aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Graham <james@hoppipolla.co.uk>2015-03-27 09:15:38 +0000
committerJames Graham <james@hoppipolla.co.uk>2015-04-03 23:28:54 +0100
commit1a81b18b9f22d7bc1a967d08fcc7fbcf2ee200f5 (patch)
tree1511d894cf8ebebf86f0390d52dfce549fe8838e
parentb2a5225831a8eee3ff596dce2be8dc08df4300a0 (diff)
downloadservo-1a81b18b9f22d7bc1a967d08fcc7fbcf2ee200f5.tar.gz
servo-1a81b18b9f22d7bc1a967d08fcc7fbcf2ee200f5.zip
Update web-platform-tests to revision 0d318188757a9c996e20b82db201fd04de5aa255
-rw-r--r--tests/wpt/metadata/2dcontext/drawing-images-to-the-canvas/2d.drawImage.canvas.html.ini5
-rw-r--r--tests/wpt/metadata/2dcontext/drawing-images-to-the-canvas/2d.drawImage.self.1.html.ini5
-rw-r--r--tests/wpt/metadata/2dcontext/drawing-images-to-the-canvas/2d.drawImage.self.2.html.ini5
-rw-r--r--tests/wpt/metadata/2dcontext/drawing-rectangles-to-the-canvas/2d.clearRect.nonfinite.html.ini5
-rw-r--r--tests/wpt/metadata/2dcontext/image-smoothing/imagesmoothing.html.ini5
-rw-r--r--tests/wpt/metadata/2dcontext/line-styles/2d.line.cap.butt.html.ini5
-rw-r--r--tests/wpt/metadata/2dcontext/line-styles/2d.line.cap.closed.html.ini5
-rw-r--r--tests/wpt/metadata/2dcontext/line-styles/2d.line.cross.html.ini5
-rw-r--r--tests/wpt/metadata/2dcontext/line-styles/2d.line.join.open.html.ini5
-rw-r--r--tests/wpt/metadata/2dcontext/line-styles/2d.line.miter.exceeded.html.ini5
-rw-r--r--tests/wpt/metadata/2dcontext/line-styles/2d.line.miter.rightangle.html.ini5
-rw-r--r--tests/wpt/metadata/2dcontext/line-styles/2d.line.width.scaledefault.html.ini5
-rw-r--r--tests/wpt/metadata/2dcontext/path-objects/2d.path.arc.empty.html.ini5
-rw-r--r--tests/wpt/metadata/2dcontext/path-objects/2d.path.arc.end.html.ini5
-rw-r--r--tests/wpt/metadata/2dcontext/path-objects/2d.path.arc.nonempty.html.ini5
-rw-r--r--tests/wpt/metadata/2dcontext/path-objects/2d.path.arc.selfintersect.1.html.ini5
-rw-r--r--tests/wpt/metadata/2dcontext/path-objects/2d.path.arc.shape.1.html.ini5
-rw-r--r--tests/wpt/metadata/2dcontext/path-objects/2d.path.arc.shape.3.html.ini5
-rw-r--r--tests/wpt/metadata/2dcontext/path-objects/2d.path.arc.shape.5.html.ini5
-rw-r--r--tests/wpt/metadata/2dcontext/path-objects/2d.path.arc.twopie.1.html.ini5
-rw-r--r--tests/wpt/metadata/2dcontext/path-objects/2d.path.arc.zero.1.html.ini5
-rw-r--r--tests/wpt/metadata/2dcontext/path-objects/2d.path.arc.zero.2.html.ini5
-rw-r--r--tests/wpt/metadata/2dcontext/path-objects/2d.path.arc.zeroradius.html.ini5
-rw-r--r--tests/wpt/metadata/2dcontext/path-objects/2d.path.bezierCurveTo.basic.html.ini5
-rw-r--r--tests/wpt/metadata/2dcontext/path-objects/2d.path.bezierCurveTo.ensuresubpath.1.html.ini5
-rw-r--r--tests/wpt/metadata/2dcontext/path-objects/2d.path.bezierCurveTo.nonfinite.html.ini5
-rw-r--r--tests/wpt/metadata/2dcontext/path-objects/2d.path.bezierCurveTo.scaled.html.ini5
-rw-r--r--tests/wpt/metadata/2dcontext/path-objects/2d.path.closePath.newline.html.ini5
-rw-r--r--tests/wpt/metadata/2dcontext/path-objects/2d.path.closePath.nextpoint.html.ini5
-rw-r--r--tests/wpt/metadata/2dcontext/path-objects/2d.path.lineTo.basic.html.ini5
-rw-r--r--tests/wpt/metadata/2dcontext/path-objects/2d.path.lineTo.ensuresubpath.1.html.ini5
-rw-r--r--tests/wpt/metadata/2dcontext/path-objects/2d.path.lineTo.ensuresubpath.2.html.ini5
-rw-r--r--tests/wpt/metadata/2dcontext/path-objects/2d.path.lineTo.nextpoint.html.ini5
-rw-r--r--tests/wpt/metadata/2dcontext/path-objects/2d.path.lineTo.nonfinite.html.ini5
-rw-r--r--tests/wpt/metadata/2dcontext/path-objects/2d.path.moveTo.multiple.html.ini5
-rw-r--r--tests/wpt/metadata/2dcontext/path-objects/2d.path.moveTo.nonfinite.html.ini5
-rw-r--r--tests/wpt/metadata/2dcontext/path-objects/2d.path.quadraticCurveTo.basic.html.ini5
-rw-r--r--tests/wpt/metadata/2dcontext/path-objects/2d.path.quadraticCurveTo.ensuresubpath.1.html.ini5
-rw-r--r--tests/wpt/metadata/2dcontext/path-objects/2d.path.quadraticCurveTo.nonfinite.html.ini5
-rw-r--r--tests/wpt/metadata/2dcontext/path-objects/2d.path.quadraticCurveTo.scaled.html.ini5
-rw-r--r--tests/wpt/metadata/2dcontext/path-objects/2d.path.stroke.empty.html.ini5
-rw-r--r--tests/wpt/metadata/2dcontext/path-objects/2d.path.stroke.prune.closed.html.ini5
-rw-r--r--tests/wpt/metadata/2dcontext/path-objects/2d.path.stroke.prune.corner.html.ini5
-rw-r--r--tests/wpt/metadata/2dcontext/path-objects/2d.path.stroke.prune.curve.html.ini5
-rw-r--r--tests/wpt/metadata/2dcontext/path-objects/2d.path.stroke.prune.line.html.ini5
-rw-r--r--tests/wpt/metadata/2dcontext/pixel-manipulation/2d.imageData.get.nonfinite.html.ini5
-rw-r--r--tests/wpt/metadata/2dcontext/pixel-manipulation/2d.imageData.put.nonfinite.html.ini5
-rw-r--r--tests/wpt/metadata/2dcontext/shadows/2d.shadow.stroke.cap.1.html.ini5
-rw-r--r--tests/wpt/metadata/2dcontext/shadows/2d.shadow.stroke.join.1.html.ini5
-rw-r--r--tests/wpt/metadata/2dcontext/shadows/2d.shadow.stroke.join.3.html.ini5
-rw-r--r--tests/wpt/metadata/2dcontext/transformations/2d.transformation.scale.nonfinite.html.ini5
-rw-r--r--tests/wpt/metadata/2dcontext/transformations/2d.transformation.setTransform.nonfinite.html.ini5
-rw-r--r--tests/wpt/metadata/2dcontext/transformations/2d.transformation.transform.nonfinite.html.ini5
-rw-r--r--tests/wpt/metadata/2dcontext/transformations/2d.transformation.translate.nonfinite.html.ini5
-rw-r--r--tests/wpt/metadata/MANIFEST.json10
-rw-r--r--tests/wpt/metadata/webstorage/event_constructor.html.ini9
-rw-r--r--tests/wpt/metadata/webstorage/event_constructor_js.html.ini9
-rw-r--r--tests/wpt/metadata/webstorage/event_local_storageeventinit.html.ini9
-rw-r--r--tests/wpt/metadata/webstorage/event_session_storageeventinit.html.ini9
-rw-r--r--tests/wpt/metadata/webstorage/missing_arguments.html.ini5
-rw-r--r--tests/wpt/metadata/webstorage/storage_local_key.html.ini5
m---------tests/wpt/web-platform-tests0
-rw-r--r--tests/wpt/web-platform-tests/.gitignore11
-rw-r--r--tests/wpt/web-platform-tests/.gitmodules7
-rw-r--r--tests/wpt/web-platform-tests/.travis.yml7
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/best-practices/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/building-paths/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/building-paths/canvas_complexshapes_arcto_001-ref.htm11
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/building-paths/canvas_complexshapes_arcto_001.htm26
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/building-paths/canvas_complexshapes_beziercurveto_001-ref.htm11
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/building-paths/canvas_complexshapes_beziercurveto_001.htm35
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/clear-100x50.pngbin0 -> 117 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.copy.html38
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.copy.pngbin0 -> 220 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.destination-atop.html38
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.destination-atop.pngbin0 -> 221 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.destination-in.html38
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.destination-in.pngbin0 -> 220 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.destination-out.html38
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.destination-out.pngbin0 -> 220 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.destination-over.html38
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.destination-over.pngbin0 -> 223 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.lighter.html38
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.lighter.pngbin0 -> 209 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.source-atop.html38
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.source-atop.pngbin0 -> 223 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.source-in.html38
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.source-in.pngbin0 -> 220 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.source-out.html38
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.source-out.pngbin0 -> 220 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.source-over.html38
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.source-over.pngbin0 -> 223 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.xor.html38
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.xor.pngbin0 -> 223 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.clip.copy.html36
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.clip.destination-atop.html36
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.clip.destination-in.html36
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.clip.destination-out.html36
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.clip.destination-over.html36
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.clip.lighter.html36
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.clip.source-atop.html36
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.clip.source-in.html36
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.clip.source-out.html36
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.clip.source-over.html36
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.clip.xor.html36
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.globalAlpha.canvas.html38
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.globalAlpha.canvaspattern.html39
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.globalAlpha.default.html27
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.globalAlpha.fill.html32
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.globalAlpha.image.html32
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.globalAlpha.imagepattern.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.globalAlpha.invalid.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.globalAlpha.range.html36
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.copy.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.copy.pngbin0 -> 220 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.destination-atop.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.destination-atop.pngbin0 -> 221 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.destination-in.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.destination-in.pngbin0 -> 220 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.destination-out.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.destination-out.pngbin0 -> 220 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.destination-over.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.destination-over.pngbin0 -> 223 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.lighter.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.lighter.pngbin0 -> 209 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.source-atop.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.source-atop.pngbin0 -> 223 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.source-in.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.source-in.pngbin0 -> 220 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.source-out.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.source-out.pngbin0 -> 220 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.source-over.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.source-over.pngbin0 -> 223 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.xor.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.xor.pngbin0 -> 223 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.operation.casesensitive.html29
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.operation.clear.html29
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.operation.darker.html29
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.operation.default.html27
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.operation.get.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.operation.highlight.html29
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.operation.nullsuffix.html29
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.operation.over.html29
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.operation.unrecognised.html29
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.copy.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.copy.pngbin0 -> 205 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.destination-atop.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.destination-atop.pngbin0 -> 206 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.destination-in.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.destination-in.pngbin0 -> 206 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.destination-out.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.destination-out.pngbin0 -> 117 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.destination-over.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.destination-over.pngbin0 -> 206 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.lighter.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.lighter.pngbin0 -> 207 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.source-atop.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.source-atop.pngbin0 -> 205 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.source-in.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.source-in.pngbin0 -> 205 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.source-out.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.source-out.pngbin0 -> 117 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.source-over.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.source-over.pngbin0 -> 205 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.xor.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.xor.pngbin0 -> 117 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.copy.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.copy.pngbin0 -> 221 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.destination-atop.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.destination-atop.pngbin0 -> 220 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.destination-in.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.destination-in.pngbin0 -> 221 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.destination-out.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.destination-out.pngbin0 -> 221 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.destination-over.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.destination-over.pngbin0 -> 222 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.lighter.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.lighter.pngbin0 -> 208 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.source-atop.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.source-atop.pngbin0 -> 222 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.source-in.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.source-in.pngbin0 -> 221 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.source-out.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.source-out.pngbin0 -> 221 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.source-over.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.source-over.pngbin0 -> 223 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.xor.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.xor.pngbin0 -> 222 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.fill.copy.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.fill.copy.pngbin0 -> 117 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.fill.destination-atop.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.fill.destination-atop.pngbin0 -> 117 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.fill.destination-in.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.fill.destination-in.pngbin0 -> 117 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.fill.source-in.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.fill.source-in.pngbin0 -> 117 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.fill.source-out.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.fill.source-out.pngbin0 -> 117 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.image.copy.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.image.copy.pngbin0 -> 117 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.image.destination-atop.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.image.destination-atop.pngbin0 -> 117 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.image.destination-in.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.image.destination-in.pngbin0 -> 117 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.image.source-in.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.image.source-in.pngbin0 -> 117 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.image.source-out.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.image.source-out.pngbin0 -> 117 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.nocontext.copy.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.nocontext.copy.pngbin0 -> 117 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.nocontext.destination-atop.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.nocontext.destination-atop.pngbin0 -> 117 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.nocontext.destination-in.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.nocontext.destination-in.pngbin0 -> 117 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.nocontext.source-in.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.nocontext.source-in.pngbin0 -> 117 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.nocontext.source-out.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.nocontext.source-out.pngbin0 -> 117 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.pattern.copy.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.pattern.copy.pngbin0 -> 117 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.pattern.destination-atop.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.pattern.destination-atop.pngbin0 -> 117 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.pattern.destination-in.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.pattern.destination-in.pngbin0 -> 117 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.pattern.source-in.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.pattern.source-in.pngbin0 -> 117 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.pattern.source-out.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.pattern.source-out.pngbin0 -> 117 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/canvas_compositing_globalcompositeoperation_001-ref.htm11
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/compositing/canvas_compositing_globalcompositeoperation_001.htm32
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/conformance-requirements/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/conformance-requirements/2d.coordinatespace-manual.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/conformance-requirements/2d.coordinatespace.pngbin0 -> 219 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/conformance-requirements/2d.missingargs.html142
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/conformance-requirements/2d.type.delete.html29
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/conformance-requirements/2d.voidreturn.html63
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.3arg.html38
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.5arg.html39
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.9arg.basic.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.9arg.destpos.html39
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.9arg.destsize.html39
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.9arg.sourcepos.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.9arg.sourcesize.html41
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.alpha.html32
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.animated.apng.html32
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.animated.gif.html32
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.animated.poster.html29
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.broken.html32
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.canvas.html40
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.clip.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.composite.html32
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.floatsource.html29
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.incomplete.emptysrc.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.incomplete.immediate.html37
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.incomplete.nosrc.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.incomplete.reload.html39
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.incomplete.removedsrc.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.negativedest.html41
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.negativedir.html41
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.negativesource.html41
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.nonfinite.html332
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.nowrap.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.null.html27
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.path.html32
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.self.1.html36
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.self.2.html38
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.svg.html29
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.transform.html32
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.wrongtype.html30
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.zerocanvas.html43
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.zerosource.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.zerosource.image.html35
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-model/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-paths-to-the-canvas/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-paths-to-the-canvas/canvas_complexshapes_ispointInpath_001.htm32
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-paths-to-the-canvas/canvas_focus_drawCustomFocusRing_001.html42
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-paths-to-the-canvas/canvas_focus_drawFocusIfNeeded_AAPI_001-manual.html50
-rwxr-xr-xtests/wpt/web-platform-tests/2dcontext/drawing-paths-to-the-canvas/drawFocusIfNeeded_001.html66
-rwxr-xr-xtests/wpt/web-platform-tests/2dcontext/drawing-paths-to-the-canvas/drawFocusIfNeeded_002.html68
-rwxr-xr-xtests/wpt/web-platform-tests/2dcontext/drawing-paths-to-the-canvas/drawFocusIfNeeded_003.html69
-rwxr-xr-xtests/wpt/web-platform-tests/2dcontext/drawing-paths-to-the-canvas/drawFocusIfNeeded_004.html88
-rwxr-xr-xtests/wpt/web-platform-tests/2dcontext/drawing-paths-to-the-canvas/drawFocusIfNeeded_005.html88
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.clearRect.basic.html30
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.clearRect.clip.html39
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.clearRect.globalalpha.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.clearRect.globalcomposite.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.clearRect.negative.html36
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.clearRect.nonfinite.html54
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.clearRect.path.html32
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.clearRect.shadow.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.clearRect.transform.html32
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.clearRect.zero.html32
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.fillRect.basic.html29
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.fillRect.clip.html40
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.fillRect.negative.html37
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.fillRect.nonfinite.html55
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.fillRect.path.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.fillRect.shadow.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.fillRect.transform.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.fillRect.zero.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.basic.html30
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.clip.html41
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.globalalpha.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.globalcomposite.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.negative.html38
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.nonfinite.html56
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.path.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.shadow.html37
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.transform.html32
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.zero.1.html30
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.zero.2.html32
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.zero.3.html30
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.zero.4.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.zero.5.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/clear-100x50.pngbin0 -> 117 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.align.center.html48
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.align.end.ltr.html48
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.align.end.rtl.html48
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.align.left.html48
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.align.right.html48
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.align.start.ltr.html48
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.align.start.rtl.html48
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.baseline.alphabetic.html48
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fill.basic-manual.html32
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fill.basic.pngbin0 -> 1062 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fill.maxWidth.bound.html45
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fill.maxWidth.fontface.html45
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fill.maxWidth.large-manual.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fill.maxWidth.large.pngbin0 -> 1062 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fill.maxWidth.negative.html32
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fill.maxWidth.small.html32
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fill.maxWidth.zero.html32
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fill.rtl-manual.html32
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fill.rtl.pngbin0 -> 1062 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fill.unaffected.html42
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fontface.html45
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fontface.notinpage.html44
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fontface.repeat.html45
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.kern.consistent-manual.html36
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.space.basic.html43
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.space.collapse.nonspace.html43
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.stroke.basic-manual.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.stroke.basic.pngbin0 -> 1637 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.stroke.unaffected.html43
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.measure.width.basic.html43
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.measure.width.empty.html38
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/drawingstyle-objects/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/examples/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.default.html27
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.get.semitransparent.html28
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.get.solid.html28
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.get.transparent.html28
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.invalidstring.html32
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.invalidtype.html32
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.current.basic.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.current.changed.html32
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.current.removed.html43
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.current.removed.pngbin0 -> 112 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hex3.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hex3.pngbin0 -> 205 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hex6.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hex6.pngbin0 -> 205 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-1.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-1.pngbin0 -> 205 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-2.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-2.pngbin0 -> 205 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-3.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-3.pngbin0 -> 205 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-4.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-4.pngbin0 -> 205 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-5.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-5.pngbin0 -> 205 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-6.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-6.pngbin0 -> 205 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-1.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-1.pngbin0 -> 205 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-2.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-2.pngbin0 -> 207 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-3.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-3.pngbin0 -> 207 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-4.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-4.pngbin0 -> 112 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-1.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-1.pngbin0 -> 220 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-2.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-2.pngbin0 -> 205 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-1.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-1.pngbin0 -> 205 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-2.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-2.pngbin0 -> 207 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-3.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-3.pngbin0 -> 207 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-4.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-4.pngbin0 -> 112 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-5.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-5.pngbin0 -> 205 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-6.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-6.pngbin0 -> 117 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.html4.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.html4.pngbin0 -> 205 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex1.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex2.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex3.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex4.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex5.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex6.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex7.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex8.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-1.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-2.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-3.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-4.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-5.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-6.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsla-1.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsla-2.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-1.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-2.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-3.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-4.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-5.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgb-1.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgb-2.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgb-3.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgb-4.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgb-5.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgb-6.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgb-7.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-1.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-2.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-3.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-4.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-5.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-6.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-7.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-1.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-1.pngbin0 -> 205 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-2.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-2.pngbin0 -> 205 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-3.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-3.pngbin0 -> 205 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-4.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-4.pngbin0 -> 205 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-5.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-5.pngbin0 -> 205 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-eof.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-eof.pngbin0 -> 205 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-num.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-num.pngbin0 -> 205 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-percent.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-percent.pngbin0 -> 205 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-clamp-1.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-clamp-1.pngbin0 -> 117 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-clamp-2.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-clamp-2.pngbin0 -> 205 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-eof.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-eof.pngbin0 -> 205 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-num-1.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-num-1.pngbin0 -> 220 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-num-2.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-num-2.pngbin0 -> 220 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-percent.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-percent.pngbin0 -> 220 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-1.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-1.pngbin0 -> 205 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-2.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-2.pngbin0 -> 205 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-3.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-3.pngbin0 -> 205 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-4.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-4.pngbin0 -> 205 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.svg-1.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.svg-1.pngbin0 -> 207 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.svg-2.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.svg-2.pngbin0 -> 207 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.system.html30
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.transparent-1.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.transparent-1.pngbin0 -> 117 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.transparent-2.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.transparent-2.pngbin0 -> 117 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.empty.html32
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.alpha.html36
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.alpha.pngbin0 -> 222 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.colour.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.colour.pngbin0 -> 222 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.colouralpha.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.colouralpha.pngbin0 -> 401 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.multiple.html36
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.multiple.pngbin0 -> 262 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.outside.html38
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.overlap.html52
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.overlap.pngbin0 -> 253 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.overlap2.html42
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.solid.html32
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.vertical.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.vertical.pngbin0 -> 231 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.zerosize.fill.html36
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.zerosize.fillRect.html35
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.zerosize.fillText.html36
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.zerosize.stroke.html44
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.zerosize.strokeRect.html43
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.zerosize.strokeText.html36
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.linear.nonfinite.html49
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.linear.transform.1.html37
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.linear.transform.2.html38
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.linear.transform.3.html38
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.object.compare.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.object.crosscanvas.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.object.current.html37
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.object.current.pngbin0 -> 112 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.object.invalidcolour.html32
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.object.invalidoffset.html32
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.object.return.html35
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.object.type.html28
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.object.update.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.cone.behind.html44
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.cone.beside.html44
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.cone.bottom.html44
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.cone.cylinder.html44
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.cone.front.html44
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.cone.shape1.html53
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.cone.shape2.html53
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.cone.top.html44
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.equal.html44
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.inside1.html44
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.inside2.html44
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.inside3.html45
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.negative.html29
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.nonfinite.html101
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.outside1.html44
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.outside2.html44
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.outside3.html45
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.touch1.html44
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.touch2.html46
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.touch3.html44
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.transform.1.html38
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.transform.2.html39
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.transform.3.html39
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.animated.gif.html38
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.basic.canvas.html49
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.basic.image.html38
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.basic.nocontext.html41
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.basic.type.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.basic.zerocanvas.html43
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.crosscanvas.html36
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.image.broken.html29
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.image.incomplete.emptysrc.html30
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.image.incomplete.immediate.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.image.incomplete.nosrc.html28
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.image.incomplete.reload.html36
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.image.incomplete.removedsrc.html30
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.image.null.html27
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.image.string.html27
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.image.undefined.html27
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.modify.canvas1.html45
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.modify.canvas2.html49
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.modify.image1.html41
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.modify.image2.html45
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.norepeat.basic.html39
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.norepeat.coord1.html42
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.norepeat.coord2.html43
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.norepeat.coord3.html43
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.norepeat.outside.html45
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.orientation.canvas.html48
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.orientation.image.html45
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.repeat.basic.html39
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.repeat.coord1.html40
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.repeat.coord2.html36
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.repeat.coord3.html39
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.repeat.outside.html40
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.repeatx.basic.html41
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.repeatx.coord1.html45
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.repeatx.outside.html42
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.repeaty.basic.html41
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.repeaty.coord1.html45
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.repeaty.outside.html42
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.repeat.case.html27
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.repeat.empty.html38
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.repeat.null.html27
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.repeat.nullsuffix.html27
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.repeat.undefined.html27
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.repeat.unrecognised.html27
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.repeat.unrecognisednull.html27
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.strokeStyle.default.html27
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/canvas_colorsandstyles_createlineargradient_001.htm35
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/green-100x50.pngbin0 -> 205 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/hit-regions/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/hit-regions/addHitRegions-NotSupportedError-01.html89
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/hit-regions/hitregions-members-exist.html29
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/image-smoothing/imagesmoothing.html46
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/line-styles/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.cap.butt.html61
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.cap.closed.html46
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.cap.invalid.html52
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.cap.open.html46
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.cap.round.html77
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.cap.square.html61
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.cap.valid.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.cross.html43
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.defaults.html30
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.join.bevel.html80
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.join.closed.html45
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.join.invalid.html52
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.join.miter.html71
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.join.open.html45
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.join.parallel.html42
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.join.round.html78
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.join.valid.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.miter.acute.html52
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.miter.exceeded.html44
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.miter.invalid.html48
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.miter.lineedge.html41
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.miter.obtuse.html52
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.miter.rightangle.html44
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.miter.valid.html37
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.miter.within.html44
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.union.html46
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.width.basic.html63
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.width.invalid.html48
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.width.scaledefault.html40
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.width.transformed.html69
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.width.valid.html37
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/line-styles/canvas_linestyles_linecap_001-ref.htm11
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/line-styles/canvas_linestyles_linecap_001.htm37
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.angle.1.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.angle.2.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.angle.3.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.angle.4.html37
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.angle.5.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.angle.6.html37
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.default.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.empty.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.end.html36
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.negative.html27
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.nonempty.html35
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.nonfinite.html77
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.scale.1.html54
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.scale.2.html44
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.selfintersect.1.html38
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.selfintersect.2.html42
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.shape.1.html39
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.shape.2.html39
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.shape.3.html38
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.shape.4.html38
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.shape.5.html38
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.twopie.1.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.twopie.2.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.twopie.3.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.twopie.4.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.zero.1.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.zero.2.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.zeroradius.html35
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.coincide.1.html46
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.coincide.2.html36
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.collinear.1.html43
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.collinear.2.html43
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.collinear.3.html48
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.ensuresubpath.1.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.ensuresubpath.2.html35
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.negative.html27
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.nonfinite.html75
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.scale.html47
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.shape.curve1.html60
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.shape.curve2.html59
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.shape.end.html40
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.shape.start.html40
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.transformation.html46
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.zero.1.html43
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.zero.2.html43
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.beginPath.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.bezierCurveTo.basic.html35
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.bezierCurveTo.ensuresubpath.1.html35
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.bezierCurveTo.ensuresubpath.2.html35
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.bezierCurveTo.nonfinite.html109
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.bezierCurveTo.scaled.html40
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.bezierCurveTo.shape.html39
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.clip.basic.1.html37
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.clip.basic.2.html37
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.clip.empty.html36
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.clip.intersect.html40
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.clip.unaffected.html42
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.clip.winding.1.html45
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.clip.winding.2.html49
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.closePath.empty.html32
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.closePath.newline.html37
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.closePath.nextpoint.html36
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.fill.closed.basic.html37
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.fill.closed.unaffected.html40
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.fill.overlap.html36
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.fill.overlap.pngbin0 -> 205 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.fill.winding.add.html42
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.fill.winding.subtract.1.html42
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.fill.winding.subtract.2.html41
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.fill.winding.subtract.3.html47
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.initial.html32
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.arc.html35
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.basic.1.html29
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.basic.2.html29
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.bezier.html48
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.bigarc.html35
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.edge.html39
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.empty.html27
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.nonfinite.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.outside.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.subpath.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.transform.1.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.transform.2.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.transform.3.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.transform.4.html32
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.unclosed.html32
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.winding.html47
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.lineTo.basic.html35
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.lineTo.ensuresubpath.1.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.lineTo.ensuresubpath.2.html35
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.lineTo.nextpoint.html36
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.lineTo.nonfinite.html41
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.moveTo.basic.html36
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.moveTo.multiple.html36
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.moveTo.newsubpath.html36
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.moveTo.nonfinite.html40
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.quadraticCurveTo.basic.html35
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.quadraticCurveTo.ensuresubpath.1.html35
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.quadraticCurveTo.ensuresubpath.2.html35
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.quadraticCurveTo.nonfinite.html57
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.quadraticCurveTo.scaled.html40
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.quadraticCurveTo.shape.html39
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.basic.html32
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.closed.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.end.1.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.end.2.html39
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.negative.html39
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.newsubpath.html36
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.nonfinite.html57
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.selfintersect.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.winding.html39
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.zero.1.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.zero.2.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.zero.3.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.zero.4.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.zero.5.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.zero.6.html36
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.stroke.empty.html40
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.stroke.overlap.html38
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.stroke.overlap.pngbin0 -> 205 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.stroke.prune.arc.html45
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.stroke.prune.closed.html41
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.stroke.prune.corner.html43
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.stroke.prune.curve.html45
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.stroke.prune.line.html40
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.stroke.prune.rect.html41
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.stroke.scale1.html54
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.stroke.scale2.html56
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.stroke.skew.html70
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.stroke.unaffected.html42
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.stroke.union.html38
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.transformation.basic.html36
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.transformation.changing.html42
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.transformation.multiple.html47
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create1.basic.html27
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create1.initial.html38
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create1.this.html30
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create1.type.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create1.zero.html27
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create2.basic.html27
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create2.initial.html35
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create2.large.html35
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create2.negative.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create2.nonfinite.html43
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create2.round.html30
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create2.this.html29
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create2.tiny.html35
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create2.type.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create2.zero.html29
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.basic.html27
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.clamp.html38
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.length.html28
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.nonfinite.html75
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.nonpremul.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.order.alpha.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.order.cols.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.order.rgb.html37
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.order.rows.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.range.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.source.negative.html46
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.source.outside.html86
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.source.size.html30
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.tiny.html30
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.type.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.unaffected.html42
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.zero.html29
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.object.clamp.html55
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.object.ctor.html28
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.object.nan.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.object.properties.html30
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.object.readonly.html40
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.object.round.html55
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.object.set.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.object.string.html36
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.object.undefined.html30
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.alpha.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.alpha.pngbin0 -> 221 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.basic.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.clip.html37
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.created.html37
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.cross.html35
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.dirty.negative.html44
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.dirty.outside.html46
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.dirty.rect1.html44
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.dirty.rect2.html44
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.dirty.zero.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.modified.html38
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.nonfinite.html109
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.null.html27
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.path.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.unaffected.html39
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.unchanged.html44
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.wrongtype.html30
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.alpha.1.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.alpha.2.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.alpha.2.pngbin0 -> 206 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.alpha.3.html35
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.alpha.3.pngbin0 -> 206 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.alpha.4.html35
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.alpha.4.pngbin0 -> 206 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.alpha.5.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.alpha.5.pngbin0 -> 206 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.attributes.shadowBlur.initial.html27
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.attributes.shadowBlur.invalid.html41
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.attributes.shadowBlur.valid.html37
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.attributes.shadowColor.initial.html27
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.attributes.shadowColor.invalid.html41
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.attributes.shadowColor.valid.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.attributes.shadowOffset.initial.html28
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.attributes.shadowOffset.invalid.html46
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.attributes.shadowOffset.valid.html50
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.blur.high-manual.html32
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.blur.high.pngbin0 -> 246 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.blur.low-manual.html39
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.blur.low.pngbin0 -> 1588 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.canvas.alpha.html41
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.canvas.alpha.pngbin0 -> 206 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.canvas.basic.html40
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.canvas.transparent.1.html38
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.canvas.transparent.2.html46
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.clip.1.html42
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.clip.2.html42
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.clip.3.html43
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.composite.1.html35
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.composite.2.html35
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.composite.3.html36
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.enable.blur.html32
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.enable.off.1.html30
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.enable.off.2.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.enable.x.html32
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.enable.y.html32
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.gradient.alpha.html37
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.gradient.alpha.pngbin0 -> 206 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.gradient.basic.html37
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.gradient.transparent.1.html37
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.gradient.transparent.2.html43
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.image.alpha.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.image.alpha.pngbin0 -> 206 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.image.basic.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.image.scale.html36
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.image.section.html36
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.image.transparent.1.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.image.transparent.2.html40
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.offset.negativeX.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.offset.negativeY.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.offset.positiveX.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.offset.positiveY.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.outside.html42
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.pattern.alpha.html36
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.pattern.alpha.pngbin0 -> 206 bytes
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.pattern.basic.html36
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.pattern.transparent.1.html36
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.pattern.transparent.2.html40
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.stroke.basic.html40
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.stroke.cap.1.html43
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.stroke.cap.2.html41
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.stroke.join.1.html43
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.stroke.join.2.html45
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.stroke.join.3.html44
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.transform.1.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.transform.2.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/canvas_shadows_001.htm36
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/canvas_shadows_002-ref.htm28
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/shadows/canvas_shadows_002.htm34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/text-styles/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.align.default.html27
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.align.invalid.html41
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.align.valid.html40
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.baseline.default.html27
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.baseline.invalid.html41
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.baseline.valid.html43
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.draw.baseline.bottom.html48
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.draw.baseline.hanging.html48
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.draw.baseline.ideographic.html48
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.draw.baseline.middle.html48
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.draw.baseline.top.html48
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.draw.space.collapse.end.html44
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.draw.space.collapse.other.html43
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.draw.space.collapse.space.html43
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.draw.space.collapse.start.html43
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.font.default.html27
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.font.parse.basic.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.font.parse.complex.html28
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.font.parse.invalid.html56
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.font.parse.size.percentage.default.html30
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.font.parse.size.percentage.html30
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.font.parse.system.html28
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.measure.width.space.html44
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/text-styles/canvas_text_font_001.htm32
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/the-canvas-state/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.bitmap.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.clip.html35
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.fillStyle.html41
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.font.html41
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.globalAlpha.html41
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.globalCompositeOperation.html41
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.lineCap.html41
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.lineJoin.html41
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.lineWidth.html41
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.miterLimit.html41
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.path.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.shadowBlur.html41
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.shadowColor.html41
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.shadowOffsetX.html41
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.shadowOffsetY.html41
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.stack.html36
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.stackdepth.html37
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.strokeStyle.html41
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.textAlign.html41
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.textBaseline.html41
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.transformation.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.underflow.html31
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/the-canvas-state/canvas_state_restore_001-ref.htm11
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/the-canvas-state/canvas_state_restore_001.htm42
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/tools/LICENSE.txt36
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/tools/current-work-canvas.xhtml3693
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/tools/gentest.py783
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/tools/name2dir.yaml45
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/tools/spec.yaml717
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/tools/specextract.py57
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/tools/templates.yaml378
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/tools/tests.yaml1031
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/tools/tests2d.yaml10030
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/tools/tests2dtext.yaml1000
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/transformations/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.order.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.rotate.direction.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.rotate.nonfinite.html38
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.rotate.radians.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.rotate.wrap.html38
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.rotate.wrapnegative.html35
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.rotate.zero.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.scale.basic.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.scale.large.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.scale.multiple.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.scale.negative.html42
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.scale.nonfinite.html42
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.scale.zero.html46
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.setTransform.multiple.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.setTransform.nonfinite.html110
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.setTransform.skewed.html55
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.transform.identity.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.transform.multiply.html34
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.transform.nonfinite.html110
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.transform.skewed.html55
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.translate.basic.html33
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.translate.nonfinite.html42
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/transformations/canvas_transformations_scale_001-ref.htm11
-rw-r--r--tests/wpt/web-platform-tests/2dcontext/transformations/canvas_transformations_scale_001.htm30
-rw-r--r--tests/wpt/web-platform-tests/CONTRIBUTING.md29
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/ClickFakeEvent.nondocument.html19
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/constructors.html147
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/event-phases-order.html28
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/init-event-while-dispatching.html83
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/Status.html26
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/approved/DOM.event.flow.html64
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/approved/EventListener.eventHandler.html60
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/approved/EventObject.after.dispatchEvent.html44
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/approved/EventObject.multiple.dispatchEvent.html55
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/approved/ProcessingInstruction.DOMCharacterDataModified.html32
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/approved/dispatchEvent.click.checkbox.html80
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/approved/domnodeinserted.html26
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/approved/stopImmediatePropagation.effect.html71
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/approved/stopPropagation.deferred.effect.html70
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/approved/stopPropagation.dispatchEvent.html65
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/approved/support/ProcessingInstruction.DOMCharacterDataModified.xml32
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/CompositionEvent.html69
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/DOMAttrModified.attrChange.html65
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/DOMAttrModified.attrName.html66
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/DOMAttrModified.html66
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/DOMAttrModified.newValue.html65
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/DOMAttrModified.prevValue.html65
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/DOMAttrModified.relatedNode.html66
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/DOMCharacterDataModified.html62
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/DOMNodeInserted.html64
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/DOMNodeRemoved.html62
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/DOMSubtreeModified.html72
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/Event.defaultPrevented.html68
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/Event.eventPhase.html77
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/Event.stopPropagation.html85
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/KeyboardEvent.key.html56
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/KeyboardEvent.location.html74
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/KeyboardEvent.modifiers.html66
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/MouseEvent.button.html65
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/MouseEvent.image.map.area.html70
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/MouseEvent.preventDefault.html94
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/MutationEvent.hasFeature.html67
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/MutationEvent.initMutationEvent.html72
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/MutationEvent.relatedNode.html76
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/ProcessingInstruction.DOMCharacterDataModified.fail.html18
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/ProcessingInstruction.DOMCharacterDataModified.xml63
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/TextEvent.hasFeature.html60
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/TextEvent.initTextEvent.html66
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/TextEvent.inputMode.IME.html69
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/TextEvent.inputMode.drop.html71
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/TextEvent.inputMode.keyboard.html67
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/TextEvent.inputMode.paste.html71
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/TextEvent.inputMode.script.html63
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/UIEvent.load.stylesheet.html59
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/WheelEvent.Capture.Bubble.html90
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/WheelEvent.ctrlKey.zoom.html93
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/WheelEvent.deltaMode.html76
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/WheelEvent.hasFeature.html60
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/WheelEvent.initWheelEvent.html76
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/WheelEvent.preventDefault.scroll.html91
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/abort.img.html74
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/abort.testresult.html30
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/blur.html57
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/compositionstart.data.html66
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/compositionstart.keydown.html76
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/compositionstart.preventDefault.html73
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/converted/DOM.event.flow.html64
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/converted/EventListener.dispatch.new.event.html77
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/converted/EventListener.eventHandler.html61
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/converted/EventObject.after.dispatchEvent.html45
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/converted/EventObject.multiple.dispatchEvent.html56
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/converted/ProcessingInstruction.DOMCharacterDataModified.html34
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/converted/dispatchEvent.click.checkbox.html80
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/converted/domnodeinserted.html26
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/converted/stopImmediatePropagation.effect.html72
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/converted/stopPropagation.deferred.effect.html71
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/converted/stopPropagation.dispatchEvent.html66
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/converted/support/ProcessingInstruction.DOMCharacterDataModified.xml32
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/customevent.html61
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/dispatchEvent.UNSPECIFIED_EVENT_TYPE_ERR.html48
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/dispatchEvent.click.checkbox.html93
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/error.image.html65
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/focusin.html61
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/focusin.relatedTarget.html64
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/focusout.relatedTarget.html64
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/hasFeature.Events.html52
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/hasFeature.feature.string.html80
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/load.image.html82
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/mouseenter.ctrlKey.html64
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/mouseenter.relatedTarget.html69
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/mouseleave.relatedTarget.html69
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/support/16kb.js140
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/support/InvalidBitMap.png1
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/support/iepreview.pngbin0 -> 76515 bytes
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/support/style01.css3
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/throwing-in-listener-and-window-error-event.html33
-rw-r--r--tests/wpt/web-platform-tests/DOMEvents/throwing-in-listener-when-all-have-not-run-yet.html31
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/BlobURL/support/file_test1.js1
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/BlobURL/support/file_test2.txt0
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/BlobURL/support/file_test3.html25
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/BlobURL/test1-manual.html122
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/BlobURL/test2-manual.html62
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/BlobURL/test3-manual.html71
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/FileReader/Progress_event_bubbles_cancelable.html33
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/FileReader/support/file_test1.txt0
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/FileReader/test_errors-manual.html71
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/FileReaderSync.worker.js28
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/blob/Blob-XHR-revoke.html28
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/blob/Blob-close.html29
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/blob/Blob-constructor.html498
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/blob/Blob-slice.html214
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/file/File-constructor.html72
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/fileReader.html67
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/filelist-section/filelist.html57
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/filelist-section/filelist_multiple_selected_files-manual.html64
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/filelist-section/filelist_selected_file-manual.html64
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/filelist-section/support/upload.txt1
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/filelist-section/support/upload.zipbin0 -> 220 bytes
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/historical.html48
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/idlharness-manual.html167
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/idlharness.html158
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/progress.html49
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/reading-data-section/Determining-Encoding.html91
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/reading-data-section/FileReader-event-handler-attributes.html23
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/reading-data-section/FileReader-multiple-reads.html73
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/reading-data-section/filereader_abort.html46
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/reading-data-section/filereader_error.html35
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/reading-data-section/filereader_file-manual.html69
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/reading-data-section/filereader_file_img-manual.html47
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/reading-data-section/filereader_readAsArrayBuffer.html38
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/reading-data-section/filereader_readAsDataURL.html39
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/reading-data-section/filereader_readAsText.html51
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/reading-data-section/filereader_readystate.html34
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/reading-data-section/filereader_result.html59
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/reading-data-section/support/blue-100x100.pngbin0 -> 227 bytes
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/support/Blob.js49
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/support/upload.txt1
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/url/url_createobjecturl_blob.html26
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/url/url_createobjecturl_file-manual.html51
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/url/url_createobjecturl_file_img-manual.html28
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/url/url_xmlhttprequest.html29
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/url/url_xmlhttprequest_img-ref.html12
-rw-r--r--tests/wpt/web-platform-tests/FileAPI/url/url_xmlhttprequest_img.html28
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/README.md8
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/abort-in-initial-upgradeneeded.html35
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/close-in-upgradeneeded.html39
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/cursor-overloads.htm88
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idb_webworkers.htm33
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor-advance-continue-async.htm186
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor-advance-invalid.htm188
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor-advance.htm243
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor-continue.htm240
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor-direction-index-keyrange.htm82
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor-direction-index.htm81
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor-direction-objectstore-keyrange.htm77
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor-direction-objectstore.htm80
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor-direction.htm73
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor-key.htm57
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor-primarykey.htm61
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor-reused.htm69
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor-source.htm68
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_advance_index.htm57
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_advance_index2.htm47
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_advance_index3.htm47
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_advance_index5.htm55
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_advance_index6.htm37
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_advance_index7.htm39
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_advance_index8.htm38
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_advance_index9.htm37
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_advance_objectstore.htm54
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_advance_objectstore2.htm40
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_advance_objectstore3.htm42
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_advance_objectstore4.htm41
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_advance_objectstore5.htm36
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_index.htm52
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_index2.htm49
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_index3.htm54
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_index4.htm65
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_index5.htm64
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_index6.htm64
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_index7.htm38
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_index8.htm38
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_invalid.htm54
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_objectstore.htm46
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_objectstore2.htm40
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_objectstore3.htm40
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_objectstore4.htm57
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_objectstore5.htm42
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_objectstore6.htm37
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_delete_index.htm69
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_delete_index2.htm42
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_delete_index3.htm40
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_delete_index4.htm38
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_delete_index5.htm39
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_delete_objectstore.htm65
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_delete_objectstore2.htm40
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_delete_objectstore3.htm39
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_delete_objectstore4.htm37
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_delete_objectstore5.htm41
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_iterating.htm110
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_iterating_index.htm53
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_iterating_index2.htm53
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_iterating_objectstore.htm51
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_iterating_objectstore2.htm51
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_index.htm64
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_index2.htm40
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_index3.htm41
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_index4.htm39
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_index5.htm45
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_index6.htm41
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_index7.htm41
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_objectstore.htm60
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_objectstore2.htm38
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_objectstore3.htm40
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_objectstore4.htm39
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_objectstore5.htm41
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_objectstore6.htm43
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_objectstore7.htm39
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_objectstore8.htm39
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbdatabase_close.htm43
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbdatabase_close2.htm39
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbdatabase_createObjectStore-createIndex-emptyname.htm45
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbdatabase_createObjectStore.htm29
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbdatabase_createObjectStore10-1000ends.htm37
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbdatabase_createObjectStore10-emptyname.htm38
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbdatabase_createObjectStore11.htm25
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbdatabase_createObjectStore2.htm33
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbdatabase_createObjectStore3.htm24
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbdatabase_createObjectStore4.htm27
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbdatabase_createObjectStore5.htm33
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbdatabase_createObjectStore6.htm30
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbdatabase_createObjectStore7.htm25
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbdatabase_createObjectStore8-parameters.htm38
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbdatabase_createObjectStore9-invalidparameters.htm29
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbdatabase_deleteObjectStore.htm25
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbdatabase_deleteObjectStore2.htm31
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbdatabase_deleteObjectStore3.htm23
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbdatabase_deleteObjectStore4-not_reused.htm42
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbdatabase_transaction.htm24
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbdatabase_transaction2.htm27
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbdatabase_transaction3.htm28
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbdatabase_transaction4.htm26
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbdatabase_transaction5.htm22
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbfactory_cmp.htm21
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbfactory_cmp2.htm41
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbfactory_deleteDatabase.htm25
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbfactory_deleteDatabase2.htm27
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbfactory_deleteDatabase3.htm33
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbfactory_deleteDatabase4.htm58
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbfactory_open.htm18
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbfactory_open10.htm91
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbfactory_open11.htm60
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbfactory_open12.htm50
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbfactory_open2.htm20
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbfactory_open3.htm27
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbfactory_open4.htm20
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbfactory_open5.htm18
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbfactory_open6.htm34
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbfactory_open7.htm38
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbfactory_open8.htm27
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbfactory_open9.htm60
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbindex-multientry-arraykeypath.htm23
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbindex-multientry-big.htm58
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbindex-multientry.htm53
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbindex_count.htm37
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbindex_count2.htm37
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbindex_count3.htm28
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbindex_count4.htm37
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbindex_get.htm36
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbindex_get2.htm39
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbindex_get3.htm27
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbindex_get4.htm39
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbindex_get5.htm26
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbindex_get6.htm29
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbindex_get7.htm29
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbindex_getKey.htm38
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbindex_getKey2.htm39
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbindex_getKey3.htm28
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbindex_getKey4.htm38
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbindex_getKey5.htm26
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbindex_getKey6.htm29
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbindex_getKey7.htm29
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbindex_indexNames.htm34
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbindex_openCursor.htm29
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbindex_openCursor2.htm29
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbindex_openKeyCursor.htm28
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbindex_openKeyCursor2.htm29
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbindex_openKeyCursor3.htm29
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbkeyrange.htm67
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbkeyrange_incorrect.htm92
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add.htm35
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add10.htm29
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add11.htm29
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add12.htm29
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add13.htm29
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add14.htm32
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add15.htm31
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add16.htm31
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add2.htm36
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add3.htm39
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add4.htm40
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add5.htm34
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add6.htm47
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add7.htm47
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add8.htm47
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add9.htm27
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_clear.htm41
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_clear2.htm43
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_clear3.htm36
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_clear4.htm31
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_count.htm35
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_count2.htm35
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_count3.htm31
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_count4.htm31
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_createIndex.htm30
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_createIndex10.htm24
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_createIndex11.htm23
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_createIndex12.htm31
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_createIndex13.htm31
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_createIndex2.htm41
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_createIndex3-usable-right-away.htm38
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_createIndex4-deleteIndex-event_order.htm66
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_createIndex5-emptykeypath.htm38
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_createIndex6-event_order.htm72
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_createIndex7-event_order.htm77
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_createIndex8-valid_keys.htm54
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_createIndex9-emptyname.htm41
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_delete.htm46
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_delete2.htm27
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_delete3.htm47
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_delete4.htm48
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_delete5.htm32
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_delete6.htm36
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_delete7.htm33
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_deleteIndex.htm43
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_deleted.htm49
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_get.htm35
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_get2.htm35
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_get3.htm34
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_get4.htm27
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_get5.htm31
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_get6.htm30
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_get7.htm29
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_index.htm34
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_openCursor.htm39
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_openCursor_invalid.htm50
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put.htm35
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put10.htm29
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put11.htm29
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put12.htm29
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put13.htm29
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put14.htm32
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put15.htm31
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put16.htm31
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put2.htm36
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put3.htm48
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put4.htm40
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put5.htm34
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put6.htm47
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put7.htm47
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put8.htm47
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put9.htm27
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbtransaction-oncomplete.htm53
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbtransaction.htm46
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbtransaction_abort.htm42
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbversionchangeevent.htm66
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/idbworker.js34
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/index_sort_order.htm51
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/interfaces.htm64
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/interfaces.html50
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/interfaces.idl145
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/interfaces.worker.js39
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/key_invalid.htm129
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/key_valid.html73
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/keygenerator-constrainterror.htm76
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/keygenerator-overflow.htm70
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/keygenerator.htm67
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/keyorder.htm180
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/keypath.htm148
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/keypath_invalid.htm65
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/keypath_maxsize.htm66
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/list_ordering.htm61
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/objectstore_keyorder.htm49
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/request_bubble-and-capture.htm69
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/string-list-ordering.htm85
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/support.js122
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/transaction-create_in_versionchange.htm82
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/transaction-lifetime-blocked.htm108
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/transaction-lifetime.htm101
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/transaction-requestqueue.htm91
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/transaction_bubble-and-capture.htm75
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/value.htm40
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/value_recursive.htm66
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/writer-starvation.htm105
-rw-r--r--tests/wpt/web-platform-tests/LICENSE29
-rw-r--r--tests/wpt/web-platform-tests/README.md218
-rw-r--r--tests/wpt/web-platform-tests/WebCryptoAPI/README.md1
-rw-r--r--tests/wpt/web-platform-tests/WebCryptoAPI/test_getRandomValues.html47
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/ecmascript-binding/es-exceptions/DOMException-constants.html59
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/ecmascript-binding/es-exceptions/DOMException-constructor.html73
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/ecmascript-binding/es-exceptions/constructor-object.html11
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/ecmascript-binding/es-exceptions/constructor-object.js111
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/ecmascript-binding/es-exceptions/constructor-object.worker.js3
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/ecmascript-binding/es-exceptions/exceptions.html136
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/invalid/idl/enum.widl1
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/invalid/idl/module.widl25
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/invalid/idl/nonnullableany.widl3
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/invalid/idl/nonnullableobjects.widl5
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/invalid/idl/raises.widl18
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/invalid/idl/scopedname.widl2
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/invalid/idl/sequenceAsAttribute.widl3
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/invalid/idl/special-omittable.widl8
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/invalid/idl/stringconstants.idl3
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/readme.txt3
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/testable_assertions.txt29
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/idl/allowany.widl6
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/idl/array.widl5
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/idl/attributes.widl14
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/idl/callback.widl5
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/idl/caller.widl5
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/idl/constants.widl18
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/idl/constructor.widl9
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/idl/dictionary-inherits.widl9
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/idl/dictionary.widl11
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/idl/documentation-dos.widl33
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/idl/documentation.widl34
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/idl/enum.widl8
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/idl/equivalent-decl.widl18
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/idl/exception-inheritance.widl7
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/idl/exception.widl8
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/idl/getter-setter.widl7
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/idl/identifier-qualified-names.widl44
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/idl/implements.widl14
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/idl/indexed-properties.widl12
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/idl/inherits-getter.widl16
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/idl/interface-inherits.widl12
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/idl/iterator.widl35
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/idl/namedconstructor.widl6
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/idl/nointerfaceobject.widl5
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/idl/nullable.widl9
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/idl/nullableobjects.widl13
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/idl/operation-optional-arg.widl4
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/idl/overloading.widl20
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/idl/overridebuiltins.widl6
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/idl/partial-interface.widl7
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/idl/primitives.widl19
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/idl/prototyperoot.widl5
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/idl/putforwards.widl5
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/idl/reg-operations.widl17
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/idl/replaceable.widl5
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/idl/sequence.widl7
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/idl/serializer.widl64
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/idl/static.widl11
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/idl/stringifier-attribute.widl6
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/idl/stringifier-custom.widl9
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/idl/stringifier.widl8
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/idl/treatasnull.widl7
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/idl/treatasundefined.widl7
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/idl/typedef.widl22
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/idl/typesuffixes.widl3
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/idl/uniontype.widl3
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/idl/variadic-operations.widl7
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/xml/allowany.widlprocxml44
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/xml/array.widlprocxml27
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/xml/attributes.widlprocxml38
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/xml/callback.widlprocxml32
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/xml/caller.widlprocxml21
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/xml/constants.widlprocxml85
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/xml/constructor.widlprocxml51
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/xml/dictionary-inherits.widlprocxml44
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/xml/dictionary.widlprocxml47
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/xml/documentation-dos.widlprocxml59
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/xml/documentation.widlprocxml61
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/xml/enum.widlprocxml52
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/xml/equivalent-decl.widlprocxml111
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/xml/exception-inheritance.widlprocxml31
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/xml/exception.widlprocxml23
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/xml/getter-setter.widlprocxml43
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/xml/identifier-qualified-names.widlprocxml107
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/xml/implements.widlprocxml51
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/xml/indexed-properties.widlprocxml92
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/xml/inherits-getter.widlprocxml44
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/xml/interface-inherits.widlprocxml48
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/xml/iterator.widlprocxml132
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/xml/module.widlprocxml99
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/xml/namedconstructor.widlprocxml30
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/xml/namespaceobject.widlprocxml60
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/xml/nointerfaceobject.widlprocxml28
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/xml/nullable.widlprocxml29
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/xml/nullableobjects.widlprocxml46
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/xml/operation-optional-arg.widlprocxml30
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/xml/overloading.widlprocxml113
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/xml/overridebuiltins.widlprocxml34
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/xml/partial-interface.widlprocxml29
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/xml/primitives.widlprocxml112
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/xml/prototyperoot.widlprocxml23
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/xml/putforwards.widlprocxml27
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/xml/reg-operations.widlprocxml70
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/xml/replaceable.widlprocxml28
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/xml/sequence.widlprocxml32
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/xml/serializer.widlprocxml296
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/xml/special-omittable.widlprocxml37
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/xml/static.widlprocxml58
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/xml/stringifier-attribute.widlprocxml29
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/xml/stringifier-custom.widlprocxml44
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/xml/stringifier.widlprocxml29
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/xml/treatasnull.widlprocxml40
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/xml/treatasundefined.widlprocxml40
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/xml/typedef.widlprocxml100
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/xml/typesuffixes.widlprocxml25
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/xml/uniontype.widlprocxml26
-rw-r--r--tests/wpt/web-platform-tests/WebIDL/valid/xml/variadic-operations.widlprocxml40
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/FormData-append.html28
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/XMLHttpRequest-withCredentials.html14
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/XMLHttpRequest-withCredentials.js43
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/XMLHttpRequest-withCredentials.worker.js3
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/abort-after-receive.htm42
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/abort-after-send.htm55
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/abort-after-stop.htm32
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/abort-after-timeout.htm58
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/abort-during-done.htm32
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/abort-during-open.htm29
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/abort-during-unsent.htm26
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/abort-during-upload.htm42
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/abort-event-abort.htm45
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/abort-event-listeners.htm25
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/abort-event-loadend.htm44
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/abort-event-order.htm65
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/abort-upload-event-abort.htm47
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/abort-upload-event-loadend.htm47
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/anonymous-mode-unsupported.htm40
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/data-uri.htm53
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/event-abort.htm29
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/event-load.htm32
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/event-loadend.htm35
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/event-loadstart.htm31
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/event-progress.htm29
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/event-readystatechange-loaded.htm38
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/event-timeout.htm34
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/event-upload-progress-crossorigin.sub.htm26
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/event-upload-progress.htm26
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/folder.txt1
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/formdata-blob.htm46
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/formdata.htm43
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/getallresponseheaders-cookies.htm38
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/getallresponseheaders-status.htm34
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/getresponseheader-case-insensitive.htm34
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/getresponseheader-chunked-trailer.htm32
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/getresponseheader-cookies-and-more.htm36
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/getresponseheader-error-state.htm36
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/getresponseheader-server-date.htm29
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/getresponseheader-special-characters.htm34
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/getresponseheader-unsent-opened-state.htm32
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/interfaces.html171
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/open-after-abort.htm35
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/open-after-setrequestheader.htm33
-rwxr-xr-xtests/wpt/web-platform-tests/XMLHttpRequest/open-during-abort.htm32
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/open-method-bogus.htm28
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/open-method-case-insensitive.htm29
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/open-method-case-sensitive.htm31
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/open-method-insecure.htm29
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/open-method-responsetype-set-sync.htm29
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/open-open-send.htm33
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/open-open-sync-send.htm31
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/open-referer.htm20
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/open-send-open.htm33
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/open-sync-open-send.htm41
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/open-url-about-blank-window.htm23
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/open-url-base-inserted-after-open.htm24
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/open-url-base-inserted.htm24
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/open-url-base.htm22
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/open-url-bogus.htm22
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/open-url-encoding.htm21
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/open-url-fragment.htm38
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/open-url-javascript-window-2.htm19
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/open-url-javascript-window.htm28
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/open-url-multi-window-2.htm24
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/open-url-multi-window-3.htm24
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/open-url-multi-window-4.htm50
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/open-url-multi-window-5.htm30
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/open-url-multi-window.htm30
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/open-url-worker-origin.htm44
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/open-url-worker-simple.htm26
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/open-user-password-non-same-origin.htm25
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/overridemimetype-done-state.htm26
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/overridemimetype-headers-received-state-force-shiftjis.htm34
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/overridemimetype-invalid-mime-type.htm25
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/overridemimetype-loading-state.htm32
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/overridemimetype-open-state-force-utf-8.htm27
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/overridemimetype-open-state-force-xml.htm34
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/overridemimetype-unsent-state-force-shiftjis.htm27
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/progress-events-response-data-gzip.htm77
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/readme.txt31
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/resources/accept-language.py4
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/resources/accept.py3
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/resources/auth1/auth.py10
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/resources/auth2/auth.py10
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/resources/auth2/corsenabled.py20
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/resources/auth3/auth.py10
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/resources/auth4/auth.py10
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/resources/auth5/auth.py13
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/resources/auth6/auth.py13
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/resources/authentication.py32
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/resources/chunked.py18
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/resources/conditional.py17
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/resources/content.py18
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/resources/corsenabled.py19
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/resources/delay.py6
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/resources/folder.txt1
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/resources/form.py2
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/resources/gzip.py23
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/resources/headers.py12
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/resources/image.gifbin0 -> 167145 bytes
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/resources/img.jpgbin0 -> 108761 bytes
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/resources/infinite-redirects.py24
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/resources/init.htm9
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/resources/inspect-headers.py22
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/resources/invalid-utf8-html.py5
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/resources/nocors/folder.txt1
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/resources/redirect.py8
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/resources/requri.py6
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/resources/shift-jis-html.py6
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/resources/status.py9
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/resources/trickle.py12
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/resources/upload.py15
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/resources/utf16.txtbin0 -> 18 bytes
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/resources/well-formed.xml4
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/resources/win-1252-xml.py5
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/resources/workerxhr-origin-referrer.js34
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/resources/workerxhr-simple.js10
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout-aborted.js15
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout-abortedonmain.js8
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout-overrides.js11
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout-overridesexpires.js13
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout-runner.js20
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout-simple.js6
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout-synconmain.js2
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout-synconworker.js11
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout-twice.js6
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout.js325
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/resources/zlib.py19
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/response-data-arraybuffer.htm54
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/response-data-blob.htm55
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/response-data-deflate.htm42
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/response-data-gzip.htm42
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/response-data-progress.htm45
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/response-invalid-responsetype.htm38
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/response-json.htm61
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/responsetext-decoding.htm52
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/responsetype.html96
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/responsexml-basic.htm33
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/responsexml-document-properties.htm63
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/responsexml-media-type.htm41
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/responsexml-non-document-types.htm45
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/responsexml-non-well-formed.htm30
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/security-consideration.sub.html30
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-accept-language.htm27
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-accept.htm24
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-after-setting-document-domain.htm38
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-authentication-basic-cors-not-enabled.htm28
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-authentication-basic-cors.htm35
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-authentication-basic-repeat-no-args.htm33
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-authentication-basic-setrequestheader-existing-session.htm53
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-authentication-basic-setrequestheader.htm36
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-authentication-basic.htm27
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-authentication-competing-names-passwords.htm54
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-authentication-cors-basic-setrequestheader.htm38
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-authentication-existing-session-manual.htm33
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-authentication-prompt-2-manual.htm25
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-authentication-prompt-manual.htm25
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-conditional.htm34
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-content-type-charset.htm58
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-content-type-string.htm26
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-data-arraybuffer.htm48
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-data-blob.htm62
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-data-es-object.htm61
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-data-formdata.htm43
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-data-unexpected-tostring.htm57
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-entity-body-basic.htm28
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-entity-body-document-bogus.htm26
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-entity-body-document.htm55
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-entity-body-empty.htm22
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-entity-body-get-head-async.htm39
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-entity-body-get-head.htm35
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-entity-body-none.htm32
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-network-error-async-events.sub.htm58
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-network-error-sync-events.sub.htm39
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-no-response-event-loadend.htm48
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-no-response-event-loadstart.htm48
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-no-response-event-order.htm61
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-non-same-origin.sub.htm28
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-receive-utf16.htm37
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-redirect-bogus-sync.htm26
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-redirect-bogus.htm36
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-redirect-infinite-sync.htm24
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-redirect-infinite.htm35
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-redirect-no-location.htm40
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-redirect-to-cors.htm36
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-redirect-to-non-cors.htm37
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-redirect.htm36
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-response-event-order.htm65
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-response-upload-event-loadend.htm40
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-response-upload-event-loadstart.htm39
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-response-upload-event-progress.htm39
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-send.htm21
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-sync-blocks-async.htm66
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-sync-no-response-event-load.htm38
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-sync-no-response-event-loadend.htm38
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-sync-no-response-event-order.htm51
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-sync-response-event-order.htm51
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-sync-timeout.htm30
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/send-timeout-events.htm76
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/setrequestheader-after-send.htm27
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/setrequestheader-allow-empty-value.htm26
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/setrequestheader-before-open.htm18
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/setrequestheader-bogus-name.htm48
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/setrequestheader-bogus-value.htm31
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/setrequestheader-case-insensitive.htm23
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/setrequestheader-header-allowed.htm32
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/setrequestheader-header-forbidden.htm43
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/setrequestheader-open-setrequestheader.htm60
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/status-async.htm62
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/status-basic.htm49
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/status-error.htm60
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/timeout-cors-async.htm43
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/timeout-sync.htm25
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-basic.htm45
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-eventtarget.htm48
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-network-error-sync.htm34
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-network-error.htm39
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-aborted.html26
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-abortedonmain.html23
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-overrides.html23
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-overridesexpires.html23
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-simple.html24
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-synconmain.html21
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-twice.html25
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-worker-aborted.html28
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-worker-overrides.html24
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-worker-overridesexpires.html25
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-worker-simple.html26
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-worker-synconworker.html25
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-worker-twice.html26
-rw-r--r--tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-unsent.htm36
-rw-r--r--tests/wpt/web-platform-tests/ambient-light/AmbientLight_tests.html11
-rw-r--r--tests/wpt/web-platform-tests/ambient-light/DeviceLightEvent_tests.js403
-rw-r--r--tests/wpt/web-platform-tests/ambient-light/idlharness.html61
-rw-r--r--tests/wpt/web-platform-tests/animation-timing/callback-invoked.html22
-rw-r--r--tests/wpt/web-platform-tests/animation-timing/cancel-invoked.html18
-rw-r--r--tests/wpt/web-platform-tests/animation-timing/idlharness.html49
-rw-r--r--tests/wpt/web-platform-tests/app-uri/README.md13
-rw-r--r--tests/wpt/web-platform-tests/app-uri/appURI_test.html394
-rw-r--r--tests/wpt/web-platform-tests/app-uri/resources/ExamPLE/mmY/index.html1
-rw-r--r--tests/wpt/web-platform-tests/app-uri/resources/ExamPLE/mmY/sth.txt1
-rw-r--r--tests/wpt/web-platform-tests/app-uri/resources/ExamPLE/{mY}/z...z/index.html1
-rw-r--r--tests/wpt/web-platform-tests/app-uri/resources/ImaGes/{{a}}/Test_1/$a/sth34!.pngbin0 -> 3059 bytes
-rw-r--r--tests/wpt/web-platform-tests/app-uri/resources/ImaGes/~t/{!a}/corrupted_file.pngbin0 -> 2964 bytes
-rw-r--r--tests/wpt/web-platform-tests/app-uri/resources/ImaGes/~t/{!a}/~sth.pngbin0 -> 3059 bytes
-rw-r--r--tests/wpt/web-platform-tests/app-uri/resources/icons/w3c-128.pngbin0 -> 2447 bytes
-rw-r--r--tests/wpt/web-platform-tests/app-uri/resources/icons/w3c-16.pngbin0 -> 984 bytes
-rw-r--r--tests/wpt/web-platform-tests/app-uri/resources/icons/w3c-48.pngbin0 -> 1453 bytes
-rw-r--r--tests/wpt/web-platform-tests/battery-status/battery-charging-manual.html53
-rw-r--r--tests/wpt/web-platform-tests/battery-status/battery-created-manual.html54
-rw-r--r--tests/wpt/web-platform-tests/battery-status/battery-discharging-manual.html53
-rw-r--r--tests/wpt/web-platform-tests/battery-status/battery-full-manual.html42
-rw-r--r--tests/wpt/web-platform-tests/battery-status/battery-interface-idlharness.html61
-rw-r--r--tests/wpt/web-platform-tests/battery-status/battery-interface.html13
-rw-r--r--tests/wpt/web-platform-tests/battery-status/battery-interface.js368
-rw-r--r--tests/wpt/web-platform-tests/battery-status/battery-plugging-in-manual.html99
-rw-r--r--tests/wpt/web-platform-tests/battery-status/battery-promise.html26
-rw-r--r--tests/wpt/web-platform-tests/battery-status/battery-unplugging-manual.html113
-rw-r--r--tests/wpt/web-platform-tests/battery-status/prime.js35
-rw-r--r--tests/wpt/web-platform-tests/common/blank.html0
-rw-r--r--tests/wpt/web-platform-tests/common/canvas-frame.css21
-rw-r--r--tests/wpt/web-platform-tests/common/canvas-index.css31
-rw-r--r--tests/wpt/web-platform-tests/common/canvas-spec.css50
-rw-r--r--tests/wpt/web-platform-tests/common/canvas-tests.css134
-rw-r--r--tests/wpt/web-platform-tests/common/canvas-tests.js86
-rw-r--r--tests/wpt/web-platform-tests/common/css-red.txt1
-rw-r--r--tests/wpt/web-platform-tests/common/large.py45
-rw-r--r--tests/wpt/web-platform-tests/common/media.js35
-rw-r--r--tests/wpt/web-platform-tests/common/redirect.py19
-rw-r--r--tests/wpt/web-platform-tests/common/reftest-wait.js9
-rw-r--r--tests/wpt/web-platform-tests/common/stringifiers.js52
-rw-r--r--tests/wpt/web-platform-tests/common/text-plain.txt4
-rw-r--r--tests/wpt/web-platform-tests/common/utils.js80
-rw-r--r--tests/wpt/web-platform-tests/common/vendor-prefix.js115
-rw-r--r--tests/wpt/web-platform-tests/config.default.json22
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/Makefile43
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/README.md11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/_/780.htm18
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/_functional/tree/ariatree.html106
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/_functional/tree/ariatree2.html124
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/_functional/tree/css/img/expander.gifbin0 -> 80 bytes
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/_functional/tree/css/treebox.css65
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/_functional/tree/css/treesimple.css50
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/_functional/tree/js/aria.js160
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/_functional/tree/js/init.js8
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/_functional/tree/js/prototype.js4184
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-input/checkbox-title.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-input/file-title.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-input/password-title.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-input/radio-title.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-input/text-title.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/673.html34
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/674.html34
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/675.html36
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/676.html38
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/677.html35
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/678.html36
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/679.html38
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/680.html37
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/681.html34
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/682.html43
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/683.html45
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/684.html44
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/685.html54
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/686.html54
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/687.html55
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/688.html55
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/689.html43
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/690.html43
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/691.html46
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/692.html44
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/693.html52
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/694.html55
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/695.html55
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/696.html42
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/697.html34
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/698.html34
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/699.html34
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/700.html34
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/701.html35
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/702.html34
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/703.html35
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/704.html34
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/705.html45
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/706.html47
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/707.html50
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/708.html53
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/709.html54
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/710.html54
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/711.html55
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/712.html55
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/713.html54
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/714.html53
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/715.html46
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/716.html47
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/717.html53
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/718.html53
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/719.html53
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/720.html53
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/aria-describedby/772.html13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/aria-describedby/773.html13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/aria-describedby/774.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/aria-describedby/838.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/567.html20
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/568.html32
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/569.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/571.html84
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/572.html73
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/573.html73
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/574.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/575.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/576.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/577.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/578.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/579.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/580.html24
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/581.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/582.html17
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/584.html17
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/button-pressed/589.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/button-pressed/590.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/combobox-autocomplete-list/div.html17
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/combobox-autocomplete-list/input.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/css-attr-sel/default.pngbin0 -> 1286 bytes
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/css-attr-sel/state-1.pngbin0 -> 1287 bytes
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/css-attr-sel/state-2.pngbin0 -> 1296 bytes
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/css-attr-sel/state-3.pngbin0 -> 1297 bytes
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/css-attr-sel/state-4.pngbin0 -> 1295 bytes
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/host-language/implicit-semantics-checkbox-disparity.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/host-language/implicit-semantics-checkbox-norole.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/host-language/implicit-semantics-checkbox-role.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/host-language/input-range-valuetext.htm10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/live-events/test-case-live-event-1.html74
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/live-events/test-case-live-event-2.html80
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/live-events/test-case-live-event-3.html76
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/live-events/test-case-live-event-4.html74
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/live-events/test-case-live-event-5.html76
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/live-events/test-case-live-event-6.html80
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/mixed-value/585.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/mixed-value/586.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-general/596.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-general/597.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-general/598.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-general/599.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-general/600.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-general/601.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-general/602.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-general/603.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-general/604.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-general/605.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-general/606.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-general/607.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-general/608.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-general/837.html18
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-img/557.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-img/565.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-img/566.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-img/foo.jpgbin0 -> 6735 bytes
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-img/test.pngbin0 -> 1913 bytes
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/538.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/542.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/543.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/544.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/545.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/546.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/551.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/552.html19
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/553.html19
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/609.html13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/610.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/611.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/612.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/613.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/614.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/615.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/659.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/660.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/661.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/662.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/663.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/721.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/723.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/724.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/725.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/748.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/749.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/750.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/751.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/753.html19
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/754.html19
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/755.html19
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/756.html19
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/758.html19
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/759.html19
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/760.html19
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/761.html19
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/foo.jpgbin0 -> 6735 bytes
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/859.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/860.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/861.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/863.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/864.html17
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/865.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/866.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/867.html18
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/868.html18
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/869.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/871.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/872.html13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/873.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/874.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/875.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/879.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/880.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/887.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/888.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/889.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/890.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/891.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/892.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/893.html20
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/noaria.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/497.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/498.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/499.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/500.html13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/501.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/502.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/503.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/504.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/505.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/506.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/507.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/509.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/510.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/511.html17
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/512.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/513.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/514.html17
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/515.html18
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/516.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/517.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/518.html18
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/519.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/520.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/521.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/522.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/523.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/524.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/525.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/527.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentational-children/testcase-839.html22
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentational-children/testcase-840.html22
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentational-children/testcase-842.html22
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentational-children/testcase-843.html22
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentational-children/testcase-844.html22
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-atomic-false.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-atomic-true.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-atomic.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-busy-false.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-busy-true.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-controls-obj1-obj2.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-controls-obj1.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-describedby-obj1-obj2.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-describedby-obj1.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-disabled-false.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-disabled-true.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-dropeffect-copy.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-dropeffect-execute.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-dropeffect-link.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-dropeffect-move.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-dropeffect-none.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-dropeffect-popup.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-flowto-obj1-obj2.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-flowto-obj1.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-grabbed-false.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-grabbed-true.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-grabbed-undefined.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-haspopup-false.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-haspopup-true.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-hidden-false.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-hidden-true.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-invalid-false.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-invalid-grammar.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-invalid-spelling.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-invalid-true.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-label-Test-string-value.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-labelledby-obj1-obj2.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-labelledby-obj1.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-live-assertive.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-live-off.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-live-polite.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-owns-obj1-obj2.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-owns-obj1.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-relevant-additions-text.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-relevant-additions.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-relevant-all.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-relevant-removals.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-relevant-text.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/relevant-state/591.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/relevant-state/592.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/relevant-state/593.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-alert.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-alertdialog.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-application.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-article.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-banner.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-button.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-complementary.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-contentinfo.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-definition.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-dialog.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-directory.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-document.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-form.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-grid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-group.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-heading.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-img.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-link.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-list.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-listbox-parent-combobox.html35
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-listbox.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-log.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-main.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-marquee.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-math.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-menu.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-menubar.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-navigation.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-note.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-option.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-presentation.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-progressbar.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-radiogroup.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-region.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-rowheader.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-search.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-separator.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-status.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-tablist.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-tabpanel.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-textbox.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-timer.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-toolbar.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-tooltip.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-tree.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-treegrid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-atomic-false.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-atomic-true.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-busy-false.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-busy-true.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-controls-obj1-obj2.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-controls-obj1.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-describedby-obj1-obj2.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-describedby-obj1.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-disabled-false.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-disabled-true.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-dropeffect-copy.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-dropeffect-execute.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-dropeffect-link.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-dropeffect-move.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-dropeffect-none.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-dropeffect-popup.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-flowto-obj1-obj2.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-flowto-obj1.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-grabbed-false.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-grabbed-true.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-grabbed-undefined.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-haspopup-false.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-haspopup-true.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-hidden-false.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-hidden-true.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-invalid-false.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-invalid-grammar.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-invalid-spelling.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-invalid-true.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-label-Test-string-value.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-labelledby-obj1-obj2.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-labelledby-obj1.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-live-assertive.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-live-off.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-live-polite.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-owns-obj1-obj2.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-owns-obj1.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-relevant-additions-text.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-relevant-additions.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-relevant-all.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-relevant-removals.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-relevant-text.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-required-inherited/menuitemcheckbox-aria-checked-mixed.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-required-inherited/menuitemcheckbox-aria-checked-undefined.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-required-inherited/radio-aria-checked-false.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-required-inherited/radio-aria-checked-mixed.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-required-inherited/radio-aria-checked-true.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-required-inherited/radio-aria-checked-undefined.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-required/roles-properties-required-checkbox-aria-checked-false.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-required/roles-properties-required-checkbox-aria-checked-mixed.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-required/roles-properties-required-checkbox-aria-checked-true.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-required/roles-properties-required-checkbox-aria-checked-undefined.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-required/roles-properties-required-combobox-aria-expanded-false.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-required/roles-properties-required-combobox-aria-expanded-true.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-required/roles-properties-required-combobox-aria-expanded-undefined.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/alert-aria-expanded-false.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/alert-aria-expanded-true.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/alert-aria-expanded-undefined.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/alertdialog-aria-expanded-false.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/alertdialog-aria-expanded-true.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/alertdialog-aria-expanded-undefined.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/application-aria-expanded-false.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/application-aria-expanded-true.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/application-aria-expanded-undefined.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/article-aria-expanded-false.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/article-aria-expanded-true.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/article-aria-expanded-undefined.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/banner-aria-expanded-false.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/banner-aria-expanded-true.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/banner-aria-expanded-undefined.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/columnheader-aria-expanded-false.html33
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/columnheader-aria-expanded-true.html33
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/columnheader-aria-expanded-undefined.html33
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/columnheader-aria-readonly-false.html33
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/columnheader-aria-readonly-true.html33
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/columnheader-aria-required-false.html33
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/columnheader-aria-required-true.html33
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/columnheader-aria-selected-false.html33
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/columnheader-aria-selected-true.html33
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/columnheader-aria-selected-undefined.html33
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/combobox-aria-activedescendant-obj1.html18
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/combobox-aria-expanded-false.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/combobox-aria-expanded-true.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/combobox-aria-expanded-undefined.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/complementary-aria-expanded-false.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/complementary-aria-expanded-true.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/complementary-aria-expanded-undefined.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/contentinfo-aria-expanded-false.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/contentinfo-aria-expanded-true.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/contentinfo-aria-expanded-undefined.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/definition-aria-expanded-false.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/definition-aria-expanded-true.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/definition-aria-expanded-undefined.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/dialog-aria-expanded-false.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/dialog-aria-expanded-true.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/dialog-aria-expanded-undefined.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/directory-aria-expanded-false.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/directory-aria-expanded-true.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/directory-aria-expanded-undefined.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/form-aria-expanded-false.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/form-aria-expanded-true.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/form-aria-expanded-undefined.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/grid-aria-activedescendant-obj1.html17
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/grid-aria-expanded-false.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/grid-aria-expanded-true.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/grid-aria-expanded-undefined.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/gridcell-aria-expanded-false.html18
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/gridcell-aria-expanded-undefined.html18
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/group-aria-expanded-false.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/group-aria-expanded-true.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/group-aria-expanded-undefined.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/heading-aria-expanded-false.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/heading-aria-expanded-true.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/heading-aria-expanded-undefined.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/img-aria-expanded-false.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/img-aria-expanded-true.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/img-aria-expanded-undefined.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/list-aria-expanded-false.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/list-aria-expanded-true.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/list-aria-expanded-undefined.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/listbox-aria-activedescendant-obj1.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/listbox-aria-expanded-false.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/listbox-aria-expanded-true.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/listbox-aria-expanded-undefined.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/log-aria-expanded-false.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/log-aria-expanded-true.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/log-aria-expanded-undefined.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/main-aria-expanded-false.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/main-aria-expanded-true.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/main-aria-expanded-undefined.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/marquee-aria-expanded-false.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/marquee-aria-expanded-true.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/marquee-aria-expanded-undefined.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/math-aria-expanded-false.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/math-aria-expanded-true.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/math-aria-expanded-undefined.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/menu-aria-activedescendant-obj1.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/menu-aria-expanded-false.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/menu-aria-expanded-true.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/menu-aria-expanded-undefined.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/menubar-aria-activedescendant-obj1.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/menubar-aria-expanded-false.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/menubar-aria-expanded-true.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/menubar-aria-expanded-undefined.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/menuitemradio-aria-checked-false.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/menuitemradio-aria-checked-mixed.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/menuitemradio-aria-checked-true.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/menuitemradio-aria-checked-undefined.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/navigation-aria-expanded-false.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/navigation-aria-expanded-true.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/navigation-aria-expanded-undefined.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/note-aria-expanded-false.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/note-aria-expanded-true.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/note-aria-expanded-undefined.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/progressbar-aria-valuemax-1.1.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/progressbar-aria-valuemin-1.1.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/progressbar-aria-valuenow-1.1.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/progressbar-aria-valuetext-Test-string-value.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/radio-aria-checked-false.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/radio-aria-checked-mixed.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/radio-aria-checked-true.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/radiogroup-aria-expanded-false.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/radiogroup-aria-expanded-true.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/radiogroup-aria-expanded-undefined.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/region-aria-expanded-false.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/region-aria-expanded-true.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/region-aria-expanded-undefined.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/row-aria-activedescendant-obj1.html17
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/rowgroup-aria-activedescendant-obj1.html19
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/rowheader-aria-expanded-false.html23
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/rowheader-aria-expanded-true.html23
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/rowheader-aria-expanded-undefined.html23
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/rowheader-aria-readonly-false.html23
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/rowheader-aria-readonly-true.html23
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/rowheader-aria-required-false.html23
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/rowheader-aria-required-true.html23
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/rowheader-aria-selected-false.html23
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/rowheader-aria-selected-true.html23
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/rowheader-aria-selected-undefined.html23
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/search-aria-expanded-false.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/search-aria-expanded-true.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/search-aria-expanded-undefined.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/status-aria-expanded-false.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/status-aria-expanded-true.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/status-aria-expanded-undefined.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tab-aria-expanded-false.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tab-aria-expanded-true.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tab-aria-expanded-undefined.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tablist-aria-activedescendant-obj1.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tablist-aria-expanded-false.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tablist-aria-expanded-true.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tablist-aria-expanded-undefined.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tabpanel-aria-expanded-false.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tabpanel-aria-expanded-true.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tabpanel-aria-expanded-undefined.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/timer-aria-expanded-false.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/timer-aria-expanded-true.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/timer-aria-expanded-undefined.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/toolbar-aria-activedescendant-obj1.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/toolbar-aria-expanded-false.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/toolbar-aria-expanded-true.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/toolbar-aria-expanded-undefined.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tooltip-aria-expanded-false.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tooltip-aria-expanded-true.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tooltip-aria-expanded-undefined.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tree-aria-activedescendant-obj1.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tree-aria-expanded-false.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tree-aria-expanded-true.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tree-aria-expanded-undefined.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treegrid-aria-activedescendant-obj1.html21
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treegrid-aria-expanded-false.html21
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treegrid-aria-expanded-true.html21
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treegrid-aria-expanded-undefined.html21
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treegrid-aria-level-1.html18
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treegrid-aria-multiselectable-false.html18
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treegrid-aria-multiselectable-true.html18
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treegrid-aria-readonly-false.html18
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treegrid-aria-readonly-true.html18
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treegrid-aria-required-false.html18
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treegrid-aria-required-true.html18
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treeitem-aria-checked-false.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treeitem-aria-checked-mixed.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treeitem-aria-checked-true.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treeitem-aria-checked-undefined.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treeitem-aria-level-1.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treeitem-aria-posinset-1.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treeitem-aria-selected-false.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treeitem-aria-selected-true.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treeitem-aria-selected-undefined.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treeitem-aria-setsize-1.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-button-aria-expanded-false.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-button-aria-expanded-true.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-button-aria-expanded-undefined.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-button-aria-pressed-false.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-button-aria-pressed-mixed.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-button-aria-pressed-true.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-button-aria-pressed-undefined.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-columnheader-aria-sort-ascending.html31
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-columnheader-aria-sort-descending.html31
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-columnheader-aria-sort-none.html31
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-columnheader-aria-sort-other.html31
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-combobox-aria-autocomplete-both.html17
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-combobox-aria-autocomplete-inline.html17
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-combobox-aria-autocomplete-list.html17
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-combobox-aria-autocomplete-none.html17
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-document-aria-expanded-false.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-document-aria-expanded-true.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-document-aria-expanded-undefined.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-grid-aria-multiselectable-false.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-grid-aria-multiselectable-true.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-grid-aria-readonly-false.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-grid-aria-readonly-true.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-gridcell-aria-readonly-false.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-gridcell-aria-readonly-true.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-gridcell-aria-required-false.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-gridcell-aria-required-true.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-gridcell-aria-selected-false.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-gridcell-aria-selected-true.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-gridcell-aria-selected-undefined.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-heading-aria-level-1.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-link-aria-expanded-false.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-link-aria-expanded-true.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-link-aria-expanded-undefined.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-listbox-aria-multiselectable-false.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-listbox-aria-multiselectable-true.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-listbox-aria-required-false.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-listbox-aria-required-true.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-listitem-aria-level-1.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-listitem-aria-posinset-1.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-listitem-aria-setsize-1.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-option-aria-checked-false.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-option-aria-checked-mixed.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-option-aria-checked-true.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-option-aria-checked-undefined.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-option-aria-posinset-1.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-option-aria-selected-false.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-option-aria-selected-true.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-option-aria-selected-undefined.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-option-aria-setsize-1.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-radiogroup-aria-required-false.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-radiogroup-aria-required-true.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-row-aria-level-1.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-row-aria-selected-false.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-row-aria-selected-true.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-row-aria-selected-undefined.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-rowheader-aria-sort-ascending.html21
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-rowheader-aria-sort-descending.html21
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-rowheader-aria-sort-none.html21
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-rowheader-aria-sort-other.html21
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-separator-aria-expanded-false.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-separator-aria-expanded-true.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-separator-aria-expanded-undefined.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-separator-aria-orientation-horizontal.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-separator-aria-orientation-vertical.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-tab-aria-selected-false.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-tab-aria-selected-true.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-tab-aria-selected-undefined.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-tablist-aria-level-1.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-textbox-aria-activedescendant-obj1.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-textbox-aria-autocomplete-both.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-textbox-aria-autocomplete-inline.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-textbox-aria-autocomplete-list.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-textbox-aria-autocomplete-none.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-textbox-aria-multiline-false.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-textbox-aria-multiline-true.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-textbox-aria-readonly-false.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-textbox-aria-readonly-true.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-textbox-aria-required-false.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-textbox-aria-required-true.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-tree-aria-multiselectable-false.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-tree-aria-multiselectable-true.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-tree-aria-required-false.html13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-tree-aria-required-true.html13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/selected-state/670.html32
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/selected-state/671.html34
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/selected-state/672.html38
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/setsize-posinset-level/setsize-posinset-level-1.html86
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/setsize-posinset-level/setsize-posinset-level-5.html71
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/setsize-posinset-level/setsize-posinset-level-6.html75
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/setsize-posinset-level/testcase-769.html89
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/stability-of-dom/669.html33
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/testcases-multiselectable/testcase-listbox-multiselectable-A.html52
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/testcases-multiselectable/testcase-listbox-multiselectable-B.html50
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/testcases-multiselectable/testcase-listbox-multiselectable-C.html64
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/testcases-multiselectable/testcase-multiselectable-D.html41
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-aria/testcases-multiselectable/testcase-tree-multiselectable-C.html46
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/html/allowedcharacters1html.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/html/allowedcharacters2html.html13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/html/allowedcharacters2htmlrules.xml3
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/html/allowedcharacters3html.html13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/html/allowedcharacters3htmlrules.xml4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/html/allowedcharacters4html.html18
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/xml/allowedcharacters1xml.xml12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/xml/allowedcharacters2xml.xml9
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/xml/allowedcharacters3xml.xml10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/xml/allowedcharacters3xmlrules.xml3
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/xml/allowedcharacters4xml.xml7
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/xml/allowedcharacters4xmlrules.xml3
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/xml/allowedcharacters5xml.xml4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/xml/allowedcharacters6xml.xml3
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/xml/allowedcharacters7xml.xml10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/xml/allowedcharacters7xmlrules.xml4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/xml/allowedcharacters8xml.xml13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/directionality/html/dir1html.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/directionality/html/dir2html.html17
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/directionality/html/dir3html.html13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/directionality/html/dir3htmlrules.xml4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/directionality/html/dir4html.html18
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/directionality/xml/dir1xml.xml12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/directionality/xml/dir2xml.xml11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/directionality/xml/dir2xmlrules.xml3
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/directionality/xml/dir3xml.xml7
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/directionality/xml/dir4xml.xml6
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/directionality/xml/dir5xml.xml13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/directionality/xml/dir6xml.xml11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/directionality/xml/dir6xmlrules.xml4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/html/domain1html.html13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/html/domain1htmlrules.xml5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/html/domain2html.html13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/html/domain2htmlrules.xml6
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/html/domain3html.html17
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/html/domain3htmlrules.xml4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/html/domain4html.html18
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/xml/domain1xml.xml13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/xml/domain2xml.xml14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/xml/domain4xml.xml10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/xml/domain4xmlrules.xml6
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/xml/domain5xml.xml17
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/xml/domain5xmlrules.xml6
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/xml/domain6xml.xml19
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/xml/domain7xml.xml16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/xml/domain7xmlrules.xml4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/elementswithintext/html/withintext1html.html33
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/elementswithintext/html/withintext1htmlrules.xml4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/elementswithintext/html/withintext2html.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/elementswithintext/html/withintext3html.html33
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/elementswithintext/html/withintext3htmlrules.xml5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/elementswithintext/html/withintext4html.html39
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/elementswithintext/xml/withintext1xml.xml12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/elementswithintext/xml/withintext2xml.xml25
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/elementswithintext/xml/withintext2xmlrules.xml6
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/elementswithintext/xml/withintext3xml.xml11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/elementswithintext/xml/withintext4xml.xml12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/elementswithintext/xml/withintext5xml.xml25
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/elementswithintext/xml/withintext6xml.xml21
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/elementswithintext/xml/withintext6xmlrules.xml5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/externalresource/html/externalresource1html.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/externalresource/html/externalresource1htmlrules.xml4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/externalresource/html/externalresource2html.html17
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/externalresource/html/externalresource2htmlrules.xml4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/externalresource/html/externalresource3html.html20
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/externalresource/xml/externalresource1xml.xml24
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/externalresource/xml/externalresource2xml.xml22
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/externalresource/xml/externalresource2xmlrules.xml3
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/externalresource/xml/externalresource3xml.xml28
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/externalresource/xml/externalresource3xmlrules.xml3
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/externalresource/xml/externalresource4xml.xml25
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/externalresource/xml/externalresource5xml.xml20
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/externalresource/xml/externalresource5xmlrules.xml5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/idvalue/html/idvalue1html.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/idvalue/html/idvalue1htmlrules.xml6
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/idvalue/html/idvalue2html.html17
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/idvalue/html/idvalue2htmlrules.xml7
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/idvalue/html/idvalue3html.html22
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/idvalue/xml/idvalue1xml.xml20
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/idvalue/xml/idvalue2xml.xml4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/idvalue/xml/idvalue3xml.xml13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/idvalue/xml/idvalue3xmlrules.xml3
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/idvalue/xml/idvalue4xml.xml17
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/idvalue/xml/idvalue4xmlrules.xml4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/idvalue/xml/idvalue5xml.xml20
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/languageinformation/html/languageinfo1html.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/languageinformation/html/languageinfo1htmlrules.xml4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/languageinformation/html/languageinfo2html.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/languageinformation/html/languageinfo2htmlrules.xml4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/languageinformation/html/languageinfo3html.html21
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/languageinformation/xml/languageinfo1xml.xml13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/languageinformation/xml/languageinfo2xml.xml19
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/languageinformation/xml/languageinfo2xmlrules.xml4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/languageinformation/xml/languageinfo3xml.xml20
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/languageinformation/xml/languageinfo4xml.xml24
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/languageinformation/xml/languageinfo4xmlrules.xml4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/html/locale1html.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/html/locale1htmlrules.xml3
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/html/locale2html.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/html/locale3html.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/html/locale3htmlrules.xml4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/html/locale4html.html18
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/html/locale5html.html21
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/xml/locale1xml.xml12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/xml/locale2xml.xml9
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/xml/locale3xml.xml10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/xml/locale3xmlrules.xml3
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/xml/locale4xml.xml16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/xml/locale4xmlrules.xml3
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/xml/locale5xml.xml8
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/xml/locale6xml.xml14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/xml/locale7xml.xml13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/xml/locale7xmlrules.xml4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/xml/locale8xml.xml18
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote1html.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote1htmlrules.xml7
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote2html.html22
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote2htmlrules.xml4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote3html.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote3htmlrules.xml3
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote4html.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote4htmlrules.xml3
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote5html.html21
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote5htmlrules.xml15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote6html.html21
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote6htmlrules.xml15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote7html.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote8html.html21
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote8htmlrules.xml16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote9html.html20
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/xml/locnote10xml.xml33
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/xml/locnote11xml.xml18
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/xml/locnote11xmlrules.xml16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/xml/locnote1xml.xml13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/xml/locnote2xml.xml19
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/xml/locnote3xml.xml12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/xml/locnote4xml.xml16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/xml/locnote5xml.xml15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/xml/locnote5xmlrules.xml9
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/xml/locnote6xml.xml21
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/xml/locnote7xml.xml20
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/xml/locnote8xml.xml17
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/xml/locnote9xml.xml8
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue10html.html26
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue1html.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue1htmlrules.xml10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue2html.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue2htmlrules.xml10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue3html.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue3htmlrules.xml12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue4html.html30
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue5html.html31
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue6html.html37
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue7html.html20
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue8html.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue8htmlrules.xml13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue9html.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue9htmlstandoff.xml13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue10xml.xml4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue11xml.xml21
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue12xml.xml11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue12xmlrules.xml11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue13xml.xml24
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue1xml.xml18
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue2xml.xml18
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue3xml.xml22
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue4xml.xml24
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue5xml.xml11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue5xmlrules.xml10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue6xml.xml4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue7xml.xml4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue8xml.xml4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue9xml.xml4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityrating/html/locqualityrating1html.html18
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityrating/html/locqualityrating2html.html18
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityrating/xml/locqualityrating1xml.xml11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityrating/xml/locqualityrating2xml.xml11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityrating/xml/locqualityrating3xml.xml11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityrating/xml/locqualityrating4xml.xml10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/html/mtconfidence1html.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/html/mtconfidence2html.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/html/mtconfidence2htmlrules.xml3
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/html/mtconfidence3html.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/html/mtconfidence3htmlrules.xml5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/html/mtconfidence4html.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/html/mtconfidence4htmlrules.xml4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/html/mtconfidence5html.html21
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/xml/mtconfidence1xml.xml22
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/xml/mtconfidence2xml.xml13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/xml/mtconfidence2xmlrules.xml10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/xml/mtconfidence3xml.xml10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/xml/mtconfidence4xml.xml10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/xml/mtconfidence5xml.xml13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/xml/mtconfidence5xmlrules.xml4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/xml/mtconfidence6xml.xml16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/xml/mtconfidence7xml.xml16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/preservespace/xml/preservespace1xml.xml13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/preservespace/xml/preservespace2xml.xml8
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/preservespace/xml/preservespace3xml.xml11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/preservespace/xml/preservespace3xmlrules.xml3
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/preservespace/xml/preservespace4xml.xml8
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/preservespace/xml/preservespace5xml.xml14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/preservespace/xml/preservespace6xml.xml9
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/preservespace/xml/preservespace6xmlrules.xml4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/html/provenance1html.html32
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/html/provenance1htmlrules.xml3
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/html/provenance2html.html36
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/html/provenance3html.html31
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/html/provenance4html.html23
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/html/provenance5html.html35
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/html/provenance5htmlrules.xml4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/html/provenance6html.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/html/provenance6htmlstandoff.xml14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/html/provenance7html.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/html/provenance7htmlstandoff.html23
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/html/provenance8html.html37
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/xml/provenance1xml.xml28
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/xml/provenance2xml.xml29
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/xml/provenance3xml.xml27
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/xml/provenance3xmlrules.xml3
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/xml/provenance4xml.xml27
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/xml/provenance4xmlrules.xml3
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/xml/provenance5xml.xml30
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/xml/provenance6xml.xml27
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/xml/provenance6xmlrules.xml4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/xml/provenance7xml.xml20
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/xml/provenance8xml.xml20
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/html/storagesize1html.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/html/storagesize2html.html13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/html/storagesize2htmlrules.xml3
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/html/storagesize3html.html13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/html/storagesize3htmlrules.xml4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/html/storagesize4html.html20
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/xml/storagesize1xml.xml10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/xml/storagesize2xml.xml8
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/xml/storagesize3xml.xml8
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/xml/storagesize3xmlrules.xml3
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/xml/storagesize4xml.xml6
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/xml/storagesize4xmlrules.xml3
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/xml/storagesize5xml.xml5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/xml/storagesize6xml.xml5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/xml/storagesize7xml.xml8
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/xml/storagesize7xmlrules.xml4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/xml/storagesize8xml.xml11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/xml/storagesize9xml.xml5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/targetpointer/html/targetpointer1html.html21
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/targetpointer/html/targetpointer1htmlrules.xml4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/targetpointer/html/targetpointer2html.html19
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/targetpointer/html/targetpointer2htmlrules.xml8
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/targetpointer/html/targetpointer3html.html24
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/targetpointer/xml/targetpointer1xml.xml14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/targetpointer/xml/targetpointer2xml.xml12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/targetpointer/xml/targetpointer2xmlrules.xml3
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/targetpointer/xml/targetpointer3xml.xml17
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/targetpointer/xml/targetpointer4xml.xml11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/targetpointer/xml/targetpointer4xmlrules.xml6
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/html/terminology1html.html18
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/html/terminology1htmlrules.xml3
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/html/terminology2html.html28
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/html/terminology2htmlrules.xml5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/html/terminology3html.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/html/terminology4html.html28
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/html/terminology4htmlrules.xml7
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/html/terminology5html.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/html/terminology6html.html23
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/xml/terminology1xml.xml11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/xml/terminology2xml.xml9
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/xml/terminology3xml.xml10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/xml/terminology4xml.xml19
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/xml/terminology4xmlrules.xml5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/xml/terminology5xml.xml7
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/xml/terminology6xml.xml7
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/xml/terminology7xml.xml17
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/xml/terminology8xml.xml14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/xml/terminology8xmlrules.xml4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/xml/terminology9xml.xml6
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/html/textanalysis1html.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/html/textanalysis1htmlrules.xml9
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/html/textanalysis2html.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/html/textanalysis2htmlrules.xml11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/html/textanalysis3html.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/html/textanalysis3htmlrules.xml5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/html/textanalysis4html.html20
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/html/textanalysis5html.html23
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/xml/textanalysis1xml.xml15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/xml/textanalysis2xml.xml7
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/xml/textanalysis2xmlrules.xml9
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/xml/textanalysis3xml.xml17
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/xml/textanalysis4xml.xml7
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/xml/textanalysis4xmlrules.xml11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/xml/textanalysis5xml.xml6
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/xml/textanalysis6xml.xml7
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/xml/textanalysis7xml.xml14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/xml/textanalysis8xml.xml7
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/xml/textanalysis8xmlrules.xml8
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/html/translate1html.html17
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/html/translate1htmlrules.xml4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/html/translate2html.html18
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/html/translate3html.html24
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/html/translate3htmlrules.xml4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/html/translate4html.html24
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/html/translate4htmlrules.xml4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/html/translate5html.html35
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/html/translate5htmlrules.xml4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/html/translate6html.html35
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/html/translate6htmlrules.xml6
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/html/translate7html.html19
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/xml/translate10xml.xml7
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/xml/translate10xmlrules.xml5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/xml/translate1xml.xml39
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/xml/translate2xml.xml10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/xml/translate2xmlrules.xml5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/xml/translate3xml.xml13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/xml/translate3xmlrules.xml6
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/xml/translate4xml.xml11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/xml/translate5xml.xml13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/xml/translate6xml.xml19
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/xml/translate7xml.xml19
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/xml/translate8xml.xml28
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/xml/translate9xml.xml11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0001-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0006-isvalid.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0007-isvalid.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0008-isvalid.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0009-isvalid.html13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0010-isvalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0014-isvalid.html13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0015-isvalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0017-isvalid.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0018-isvalid.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0019-novalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0020-isvalid.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0021-isvalid.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0023-isvalid.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0025-isvalid.html17
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0026-isvalid.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0027-isvalid.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0029-isvalid.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0030-isvalid.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0031-isvalid.html13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0032-isvalid.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0033-isvalid.html17
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0034-isvalid.html13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0035-novalid.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0036-isvalid.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0037-novalid.html17
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0038-isvalid.html13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0039-novalid.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0041-novalid.html17
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0048-isvalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0049-isvalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0050-isvalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0051-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0052-isvalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0053-isvalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0054-isvalid.html13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0055-isvalid.html13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0056-isvalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0057-isvalid.html13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0059-isvalid.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0060-isvalid.html13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0063-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0064-isvalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0065-isvalid.html21
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0066-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0067-isvalid.html9
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0068-isvalid.html13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0069-isvalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0070-isvalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0071-isvalid.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0072-isvalid.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0073-isvalid.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0074-isvalid.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0075-isvalid.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0079-novalid.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0080-isvalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0083-isvalid.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0084-isvalid.html17
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0085-novalid.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0087-isvalid.html35
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0088-isvalid.html13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0089-isvalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0091-isvalid.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0093-isvalid.html13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0099-isvalid.html19
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0104-isvalid.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0106-isvalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0107-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0109-novalid.html13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0110-isvalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0111-isvalid.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0112-isvalid.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0114-isvalid.html19
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0115-isvalid.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0117-isvalid.html13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0118-isvalid.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0119-isvalid.html17
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0120-isvalid.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0122-isvalid.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0126-isvalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0131-novalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0134-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0140-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0147-novalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0174-isvalid.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0175-isvalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0176-isvalid.html22
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0177-isvalid.html13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0178-isvalid.html13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0179-novalid.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0180-novalid.html13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0181-isvalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0182-isvalid.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0183-novalid.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0186-isvalid.html13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0187-isvalid.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0188-isvalid.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0189-isvalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0190-isvalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0196-isvalid.html13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0197-isvalid.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0206-isvalid.html13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0207-isvalid.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0213-isvalid.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0214-isvalid.html9
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0216-isvalid.html31
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0217-isvalid.html13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0218-isvalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0219-isvalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0220-isvalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0221-isvalid.html13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0222-novalid.html13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0223-novalid.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0224-isvalid.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0225-isvalid.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0226-novalid.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0227-novalid.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0228-isvalid.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0229-isvalid.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0230-novalid.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0231-isvalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0232-isvalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0233-isvalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0234-novalid.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0235-isvalid.html13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0237-novalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0238-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0239-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0240-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0241-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0242-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0243-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0244-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0245-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0246-isvalid.html13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0247-isvalid.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0248-isvalid.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0249-isvalid.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0250-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0251-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0252-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0253-isvalid.html13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0254-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0255-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0257-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0258-novalid.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0259-isvalid.html48
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0261-isvalid.html13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0262-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0263-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0264-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0265-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0266-isvalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0267-isvalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0268-isvalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0269-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0271-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0272-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0273-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0274-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0275-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0276-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0277-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0278-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0279-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0280-novalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0281-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0282-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0283-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0284-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0285-novalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0287-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0289-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0290-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0291-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0292-isvalid.html13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0293-isvalid.html13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0296-isvalid.html27
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0297-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0298-isvalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0299-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0300-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0301-isvalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0302-isvalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0303-novalid.html13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0305-isvalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0306-isvalid.html13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0307-isvalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0308-novalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0309-novalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0310-novalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0311-isvalid.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0312-isvalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0313-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0314-novalid.html36
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0315-isvalid.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0316-isvalid.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0317-isvalid.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0318-isvalid.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0319-novalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0320-novalid.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0321-isvalid.html13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0322-isvalid.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0323-isvalid.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0324-isvalid.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0325-isvalid.html17
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0326-isvalid.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0327-isvalid.html24
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0328-isvalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0329-isvalid.html13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0330-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0331-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0015-novalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0021-isvalid.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0023-isvalid.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0030-novalid.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0050-isvalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0052-isvalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0053-isvalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0066-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0067-isvalid.html9
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0071-novalid.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0074-novalid.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0075-isvalid.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0089-isvalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0115-isvalid.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0117-isvalid.html13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0134-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0140-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0147.novalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0214-isvalid.html9
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0235-isvalid.html13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0238-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0239-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0240-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0241-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0242-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0255-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0259-isvalid.html48
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0263-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0264-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0272-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0273-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0274-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0275-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0276-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0277-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0281-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0282-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0283-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0287-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0296-isvalid.html27
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0301-isvalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0302-isvalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0305-isvalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0306-isvalid.html13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0307-isvalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0311-isvalid.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0312-isvalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0313-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0319-novalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0321-isvalid.html13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0322-isvalid.html14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0323-isvalid.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0324-isvalid.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0325-isvalid.html17
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0326-isvalid.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0327-isvalid.html24
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/Makefile20
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/attributes/accesskey/duplicate-key-labels-novalid.html9
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/attributes/accesskey/multi-character-key-label-novalid.html9
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/attributes/data/no-characters-after-hyphen-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/attributes/data/not-xml-serializable-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/attributes/data/value-isvalid.html7
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/attributes/lang/deprecated-tag-haswarn.html9
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/attributes/lang/empty-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/attributes/lang/extlang-bad-novalid.html9
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/attributes/lang/xmllang-different-value-novalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/attributes/lang/xmllang-only-novalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/attributes/lang/xmllang-same-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/attributes/role/unrecognized-role-name-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/attributes/spellcheck/value-bad-novalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/attributes/spellcheck/value-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/download-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href-isvalid.html92
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/fragment-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/fragment-contains-hash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/fragment-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-double-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-double-percent-encoded-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-empty-userinfo-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-empty-with-userinfo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-hostname-in-brackets-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-invalid-unicode-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-invalid-unicode-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-square-brackets-port-contains-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-u0000-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-u0000-percent-encoded-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/path-bare-percent-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/path-contains-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/path-leading-backslash-at-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/path-leading-colon-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/path-leading-colon-chars-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/path-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/path-percent-encoded-malformed-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/path-relative-square-brackets-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/path-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/path-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/path-u0091-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/port-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/port-leading-colon-bracket-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/port-leading-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/port-leading-dash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/port-multiple-letters-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/port-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/port-single-letter-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/port-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/port-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/query-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/query-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-data-contains-fragment-haswarn.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-data-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-file-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-file-single-slash-c-bar-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-file-triple-slash-c-bar-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-ftp-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-ftp-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-http-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-http-no-slash-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-http-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-http-no-slash-square-bracket-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-http-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-https-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-https-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-javascript-no-slash-malformed-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-trailing-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-trailing-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-trailing-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/userinfo-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/userinfo-password-bad-chars-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/userinfo-password-contains-pile-of-poo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/userinfo-username-contains-at-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/userinfo-username-contains-pile-of-poo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/media-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/model-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/model-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/name-empty-novalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/abbr/model-isvalid.html24
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/abbr/model-novalid.html18
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/address/model-isvalid.html17
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/address/model-novalid.html17
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/download-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href-empty-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href-isvalid.html91
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/fragment-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/fragment-contains-hash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/fragment-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-double-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-double-percent-encoded-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-empty-userinfo-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-empty-with-userinfo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-hostname-in-brackets-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-invalid-unicode-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-invalid-unicode-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-square-brackets-port-contains-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-u0000-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-u0000-percent-encoded-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/path-bare-percent-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/path-contains-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/path-leading-backslash-at-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/path-leading-colon-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/path-leading-colon-chars-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/path-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/path-percent-encoded-malformed-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/path-relative-square-brackets-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/path-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/path-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/path-u0091-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/port-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/port-leading-colon-bracket-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/port-leading-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/port-leading-dash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/port-multiple-letters-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/port-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/port-single-letter-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/port-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/port-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/query-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/query-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-data-contains-fragment-haswarn.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-data-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-file-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-file-single-slash-c-bar-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-file-triple-slash-c-bar-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-ftp-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-ftp-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-http-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-http-no-slash-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-http-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-http-no-slash-square-bracket-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-http-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-https-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-https-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-javascript-no-slash-malformed-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-trailing-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-trailing-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-trailing-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/userinfo-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/userinfo-password-bad-chars-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/userinfo-password-contains-pile-of-poo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/userinfo-username-contains-at-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/userinfo-username-contains-pile-of-poo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/media-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/model-isvalid.html30
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/model-novalid.html53
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/model-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/model-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src-isvalid.html91
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src-whitespace-only-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/fragment-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/fragment-contains-hash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/fragment-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-double-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-double-percent-encoded-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-empty-userinfo-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-empty-with-userinfo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-hostname-in-brackets-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-invalid-unicode-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-invalid-unicode-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-square-brackets-port-contains-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-u0000-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-u0000-percent-encoded-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/path-bare-percent-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/path-contains-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/path-leading-backslash-at-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/path-leading-colon-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/path-leading-colon-chars-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/path-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/path-percent-encoded-malformed-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/path-relative-square-brackets-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/path-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/path-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/path-u0091-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/port-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/port-leading-colon-bracket-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/port-leading-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/port-leading-dash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/port-multiple-letters-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/port-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/port-single-letter-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/port-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/port-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/query-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/query-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-data-contains-fragment-haswarn.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-data-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-file-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-file-single-slash-c-bar-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-file-triple-slash-c-bar-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-ftp-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-ftp-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-http-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-http-no-slash-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-http-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-http-no-slash-square-bracket-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-http-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-https-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-https-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-javascript-no-slash-malformed-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-trailing-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-trailing-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-trailing-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/userinfo-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/userinfo-password-bad-chars-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/userinfo-password-contains-pile-of-poo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/userinfo-username-contains-at-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/userinfo-username-contains-pile-of-poo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href-and-target-missing-novalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href-empty-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/fragment-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/fragment-contains-hash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/fragment-contains-pile-of-poo-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/fragment-contains-question-mark-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/fragment-empty-hash-only-no-path-relative-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/fragment-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/fragment-non-ascii-relative-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/fragment-semicolon-question-mark-relative-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/fragment-slash-relative-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-192.0x00A80001-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-IP-address-broken-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-IP-address-fullwidth-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-IP-address-percent-encoded-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-double-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-double-percent-encoded-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-empty-userinfo-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-empty-with-userinfo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-exotic-dot-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-exotic-whitespace-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-fullwidth-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-hostname-in-brackets-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-idn-unicode-han-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-invalid-unicode-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-invalid-unicode-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-ipv6-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-ipv6-port-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-is-pile-of-poo-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-square-brackets-port-contains-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-u0000-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-u0000-percent-encoded-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-bare-percent-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-colon-colon-number-relative-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-colon-relative-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-contains-pile-of-poo-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-contains-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-leading-backslash-at-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-leading-colon-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-leading-colon-chars-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-leading-colon-chars-relative-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-leading-colon-colon-relative-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-leading-colon-hash-relative-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-leading-colon-letter-relative-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-leading-colon-number-relative-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-leading-colon-slash-relative-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-non-ascii-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-percent-encoded-dot-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-percent-encoded-malformed-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-percent-encoded-mixed-case-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-percent-encoded-multiple-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-percent-encoded-slash-plus-slashes-relative-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-percent-encoded-slash-relative-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-percent-encoded-space-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-percent-encoded-u0000-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-percent-encoded-u0091-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-relative-square-brackets-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-simple-relative-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-slash-colon-number-relative-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-slash-only-relative-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-starts-with-pile-of-poo-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-u0091-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-u202E-u202D-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-uFEFF-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-unicode-han-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/port-0-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/port-00000000000000-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/port-00000000000000000000080-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/port-999999-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/port-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/port-leading-colon-bracket-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/port-leading-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/port-leading-dash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/port-multiple-letters-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/port-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/port-none-but-colon-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/port-single-letter-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/port-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/port-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/query-contains-pile-of-poo-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/query-contains-question-mark-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/query-empty-no-path-relative-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/query-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/query-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-data-contains-fragment-haswarn.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-data-no-slash-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-data-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-file-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-file-host-empty-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-file-host-included-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-file-no-slash-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-file-scheme-only-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-file-single-slash-c-bar-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-file-single-slash-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-file-slash-only-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-file-slash-slash-abc-bar-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-file-slash-slash-c-bar-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-file-slash-slash-only-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-file-slash-slash-slash-only-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-file-triple-slash-c-bar-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-file-uppercase-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-ftp-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-ftp-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-ftps-no-slash-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-ftps-single-slash-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-gopher-no-slash-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-gopher-single-slash-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-http-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-http-no-slash-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-http-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-http-no-slash-square-bracket-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-http-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-https-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-https-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-javascript-no-slash-malformed-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-javascript-single-slash-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-mailto-no-slash-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-mailto-single-slash-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-none-relative-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-private-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-private-no-slash-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-private-path-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-private-path-leading-slashes-chars-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-private-path-leading-slashes-colon-slashes-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-private-path-leading-slashes-only-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-private-single-letter-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-private-single-slash-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-private-slash-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-private-slash-slash-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-schemeless-relative-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-trailing-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-trailing-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-trailing-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-ws-single-slash-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-wss-no-slash-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-wss-single-slash-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/userinfo-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/userinfo-empty-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/userinfo-host-port-path-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/userinfo-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/userinfo-password-bad-chars-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/userinfo-password-contains-pile-of-poo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/userinfo-password-empty-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/userinfo-user-empty-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/userinfo-username-contains-at-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/userinfo-username-contains-percent-encoded-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/userinfo-username-contains-pile-of-poo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/userinfo-username-non-alpha-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/bdo/model-isvalid.html28
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/bdo/model-novalid.html21
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite-empty-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite-isvalid.html91
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/fragment-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/fragment-contains-hash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/fragment-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-double-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-double-percent-encoded-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-empty-userinfo-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-empty-with-userinfo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-hostname-in-brackets-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-invalid-unicode-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-invalid-unicode-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-square-brackets-port-contains-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-u0000-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-u0000-percent-encoded-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/path-bare-percent-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/path-contains-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/path-leading-backslash-at-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/path-leading-colon-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/path-leading-colon-chars-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/path-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/path-percent-encoded-malformed-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/path-relative-square-brackets-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/path-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/path-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/path-u0091-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/port-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/port-leading-colon-bracket-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/port-leading-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/port-leading-dash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/port-multiple-letters-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/port-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/port-single-letter-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/port-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/port-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/query-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/query-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-data-contains-fragment-haswarn.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-data-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-file-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-file-single-slash-c-bar-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-file-triple-slash-c-bar-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-ftp-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-ftp-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-http-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-http-no-slash-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-http-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-http-no-slash-square-bracket-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-http-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-https-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-https-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-javascript-no-slash-malformed-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-trailing-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-trailing-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-trailing-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/userinfo-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/userinfo-password-bad-chars-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/userinfo-password-contains-pile-of-poo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/userinfo-username-contains-at-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/userinfo-username-contains-pile-of-poo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/model-isvalid.html18
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/model-novalid.html31
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/br/model-isvalid.html16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/br/model-novalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction-isvalid.html91
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction-whitespace-only-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/fragment-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/fragment-contains-hash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/fragment-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-double-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-double-percent-encoded-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-empty-userinfo-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-empty-with-userinfo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-hostname-in-brackets-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-invalid-unicode-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-invalid-unicode-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-square-brackets-port-contains-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-u0000-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-u0000-percent-encoded-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/path-bare-percent-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/path-contains-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/path-leading-backslash-at-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/path-leading-colon-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/path-leading-colon-chars-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/path-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/path-percent-encoded-malformed-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/path-relative-square-brackets-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/path-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/path-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/path-u0091-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/port-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/port-leading-colon-bracket-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/port-leading-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/port-leading-dash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/port-multiple-letters-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/port-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/port-single-letter-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/port-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/port-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/query-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/query-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-data-contains-fragment-haswarn.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-data-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-file-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-file-single-slash-c-bar-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-file-triple-slash-c-bar-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-ftp-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-ftp-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-http-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-http-no-slash-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-http-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-http-no-slash-square-bracket-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-http-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-https-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-https-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-javascript-no-slash-malformed-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-trailing-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-trailing-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-trailing-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/userinfo-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/userinfo-password-bad-chars-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/userinfo-password-contains-pile-of-poo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/userinfo-username-contains-at-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/userinfo-username-contains-pile-of-poo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/canvas/model-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/canvas/model-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/cite/model-isvalid.html24
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/cite/model-novalid.html18
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/code/model-isvalid.html22
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/code/model-novalid.html25
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite-empty-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite-isvalid.html91
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/fragment-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/fragment-contains-hash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/fragment-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-double-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-double-percent-encoded-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-empty-userinfo-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-empty-with-userinfo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-hostname-in-brackets-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-invalid-unicode-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-invalid-unicode-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-square-brackets-port-contains-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-u0000-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-u0000-percent-encoded-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/path-bare-percent-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/path-contains-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/path-leading-backslash-at-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/path-leading-colon-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/path-leading-colon-chars-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/path-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/path-percent-encoded-malformed-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/path-relative-square-brackets-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/path-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/path-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/path-u0091-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/port-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/port-leading-colon-bracket-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/port-leading-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/port-leading-dash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/port-multiple-letters-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/port-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/port-single-letter-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/port-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/port-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/query-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/query-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-data-contains-fragment-haswarn.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-data-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-file-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-file-single-slash-c-bar-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-file-triple-slash-c-bar-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-ftp-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-ftp-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-http-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-http-no-slash-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-http-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-http-no-slash-square-bracket-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-http-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-https-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-https-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-javascript-no-slash-malformed-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-trailing-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-trailing-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-trailing-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/userinfo-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/userinfo-password-bad-chars-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/userinfo-password-contains-pile-of-poo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/userinfo-username-contains-at-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/userinfo-username-contains-pile-of-poo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-0004-02-29-haswarn.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-0005-02-29-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-0214-09-29-haswarn.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-1900-02-29-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-1969-02-29-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-20014-09-29-haswarn.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-2014-02-29-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-2100-02-29-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-2200-02-29-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-day-01-32-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-day-03-32-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-day-04-31-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-day-05-32-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-day-06-31-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-day-07-32-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-day-08-32-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-day-09-31-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-day-10-32-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-day-11-31-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-day-12-32-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-day-missing-separator-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-day-one-digit-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-day-three-digits-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-iso8601-YYYYMMDD-no-hyphen-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-leading-bom-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-leading-whitespace-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-month-00-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-month-13-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-month-missing-separator-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-month-one-digit-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-month-three-digits-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-non-ascii-digit-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-trailing-U+0000-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-trailing-pile-of-poo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-trailing-whitespace-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-wrong-day-separator-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-wrong-month-separator-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-year-0000-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-year-five-digits-haswarn.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-year-negative-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-year-three-digits-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/datetime-isvalid.html33
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/duration-P-form-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/duration-time-component-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-2400-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-60-minutes-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-60-seconds-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-bad-fraction-separator-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-four-digit-fraction-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-hour-one-digit-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-hour-three-digits-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-iso8601-hh-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-iso8601-hhmm-no-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-iso8601-hhmmss-no-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-lowercase-z-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-minutes-one-digit-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-minutes-three-digits-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-missing-minutes-separator-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-missing-seconds-separator-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-nbsp-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-seconds-one-digit-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-seconds-three-digits-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-space-before-timezone-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-60-minutes-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-iso8601-two-digit-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-lowercase-t-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-minus-1300-haswarn.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-minus-2400-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-minutes-15-haswarn.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-multiple-spaces-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-non-T-character-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-offset-colon-start-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-offset-space-start-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-one-digit-hour-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-one-digit-minute-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-plus-1500-haswarn.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-plus-2400-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-three-digit-hour-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-three-digit-minute-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-with-seconds-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-with-both-T-and-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-wrong-minutes-separator-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-wrong-seconds-separator-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-zero-digit-fraction-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/local-date-and-time-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/model-isvalid.html32
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/model-novalid.html45
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/month-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/time-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/week-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/year-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/yearless-date-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/dfn/model-isvalid.html24
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/dfn/model-novalid.html18
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/dialog/model-novalid.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/div/model-isvalid.html20
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/div/model-novalid.html27
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/dl/model-isvalid.html55
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/dl/model-novalid.html75
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/em/model-isvalid.html22
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/em/model-novalid.html25
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/height-novalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src-isvalid.html91
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src-whitespace-only-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/fragment-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/fragment-contains-hash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/fragment-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-double-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-double-percent-encoded-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-empty-userinfo-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-empty-with-userinfo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-hostname-in-brackets-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-invalid-unicode-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-invalid-unicode-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-square-brackets-port-contains-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-u0000-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-u0000-percent-encoded-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/path-bare-percent-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/path-contains-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/path-leading-backslash-at-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/path-leading-colon-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/path-leading-colon-chars-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/path-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/path-percent-encoded-malformed-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/path-relative-square-brackets-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/path-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/path-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/path-u0091-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/port-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/port-leading-colon-bracket-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/port-leading-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/port-leading-dash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/port-multiple-letters-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/port-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/port-single-letter-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/port-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/port-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/query-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/query-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-data-contains-fragment-haswarn.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-data-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-file-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-file-single-slash-c-bar-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-file-triple-slash-c-bar-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-ftp-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-ftp-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-http-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-http-no-slash-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-http-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-http-no-slash-square-bracket-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-http-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-https-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-https-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-javascript-no-slash-malformed-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-trailing-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-trailing-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-trailing-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/userinfo-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/userinfo-password-bad-chars-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/userinfo-password-contains-pile-of-poo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/userinfo-username-contains-at-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/userinfo-username-contains-pile-of-poo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/type-novalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/width-novalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/footer/nested-footer-novalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/footer/nested-header-novalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action-isvalid.html91
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action-whitespace-only-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/fragment-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/fragment-contains-hash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/fragment-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-double-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-double-percent-encoded-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-empty-userinfo-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-empty-with-userinfo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-hostname-in-brackets-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-invalid-unicode-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-invalid-unicode-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-square-brackets-port-contains-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-u0000-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-u0000-percent-encoded-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/path-bare-percent-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/path-contains-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/path-leading-backslash-at-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/path-leading-colon-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/path-leading-colon-chars-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/path-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/path-percent-encoded-malformed-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/path-relative-square-brackets-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/path-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/path-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/path-u0091-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/port-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/port-leading-colon-bracket-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/port-leading-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/port-leading-dash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/port-multiple-letters-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/port-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/port-single-letter-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/port-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/port-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/query-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/query-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-data-contains-fragment-haswarn.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-data-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-file-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-file-single-slash-c-bar-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-file-triple-slash-c-bar-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-ftp-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-ftp-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-http-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-http-no-slash-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-http-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-http-no-slash-square-bracket-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-http-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-https-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-https-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-javascript-no-slash-malformed-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-trailing-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-trailing-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-trailing-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/userinfo-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/userinfo-password-bad-chars-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/userinfo-password-contains-pile-of-poo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/userinfo-username-contains-at-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/userinfo-username-contains-pile-of-poo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/h1/model-isvalid.html17
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/h1/model-novalid.html29
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/h2/model-isvalid.html17
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/h2/model-novalid.html29
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/h3/model-isvalid.html17
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/h3/model-novalid.html29
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/h4/model-isvalid.html17
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/h4/model-novalid.html29
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/h5/model-isvalid.html17
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/h5/model-novalid.html29
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/h6/model-isvalid.html17
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/h6/model-novalid.html29
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/header/nested-footer-novalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/header/nested-header-novalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/hr/model-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/hr/model-novalid.html28
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest-empty-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest-whitespace-only-novalid.html6
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/fragment-backslash-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/fragment-contains-hash-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/fragment-contains-pile-of-poo-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/fragment-contains-question-mark-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/fragment-empty-hash-only-no-path-relative-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/fragment-leading-space-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/fragment-non-ascii-relative-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/fragment-semicolon-question-mark-relative-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/fragment-slash-relative-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-192.0x00A80001-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-IP-address-broken-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-IP-address-fullwidth-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-IP-address-percent-encoded-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-cr-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-double-percent-encoded-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-double-percent-encoded-percent-encoded-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-empty-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-empty-userinfo-empty-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-empty-with-userinfo-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-exotic-dot-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-exotic-whitespace-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-fullwidth-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-hostname-in-brackets-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-idn-unicode-han-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-invalid-unicode-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-invalid-unicode-percent-encoded-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-ipv6-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-ipv6-port-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-is-pile-of-poo-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-newline-novalid.html6
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-space-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-square-brackets-port-contains-colon-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-tab-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-u0000-percent-encoded-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-u0000-percent-encoded-percent-encoded-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-bare-percent-sign-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-colon-colon-number-relative-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-colon-relative-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-contains-pile-of-poo-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-contains-space-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-leading-backslash-at-sign-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-leading-colon-backslash-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-leading-colon-chars-backslash-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-leading-colon-chars-relative-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-leading-colon-colon-relative-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-leading-colon-hash-relative-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-leading-colon-letter-relative-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-leading-colon-number-relative-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-leading-colon-slash-relative-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-leading-space-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-non-ascii-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-percent-encoded-dot-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-percent-encoded-malformed-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-percent-encoded-mixed-case-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-percent-encoded-multiple-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-percent-encoded-slash-plus-slashes-relative-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-percent-encoded-slash-relative-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-percent-encoded-space-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-percent-encoded-u0000-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-percent-encoded-u0091-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-relative-square-brackets-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-simple-relative-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-slash-colon-number-relative-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-slash-only-relative-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-starts-with-pile-of-poo-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-tab-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-trailing-space-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-u0091-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-u202E-u202D-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-uFEFF-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-unicode-han-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/port-0-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/port-00000000000000-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/port-00000000000000000000080-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/port-999999-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/port-cr-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/port-leading-colon-bracket-colon-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/port-leading-colon-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/port-leading-dash-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/port-multiple-letters-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/port-newline-novalid.html6
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/port-none-but-colon-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/port-single-letter-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/port-space-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/port-tab-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/query-contains-pile-of-poo-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/query-contains-question-mark-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/query-empty-no-path-relative-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/query-leading-space-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/query-trailing-space-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-data-contains-fragment-haswarn.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-data-no-slash-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-data-single-slash-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-file-backslash-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-file-host-empty-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-file-host-included-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-file-no-slash-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-file-scheme-only-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-file-single-slash-c-bar-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-file-single-slash-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-file-slash-only-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-file-slash-slash-abc-bar-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-file-slash-slash-c-bar-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-file-slash-slash-only-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-file-slash-slash-slash-only-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-file-triple-slash-c-bar-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-file-uppercase-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-ftp-no-slash-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-ftp-single-slash-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-ftps-no-slash-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-ftps-single-slash-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-gopher-no-slash-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-gopher-single-slash-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-http-backslash-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-http-no-slash-colon-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-http-no-slash-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-http-no-slash-square-bracket-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-http-single-slash-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-https-no-slash-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-https-single-slash-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-javascript-no-slash-malformed-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-javascript-single-slash-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-mailto-no-slash-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-mailto-single-slash-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-none-relative-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-private-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-private-no-slash-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-private-path-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-private-path-leading-slashes-chars-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-private-path-leading-slashes-colon-slashes-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-private-path-leading-slashes-only-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-private-single-letter-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-private-single-slash-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-private-slash-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-private-slash-slash-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-schemeless-relative-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-trailing-cr-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-trailing-newline-novalid.html6
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-trailing-space-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-trailing-tab-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-ws-single-slash-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-wss-no-slash-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-wss-single-slash-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/userinfo-backslash-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/userinfo-empty-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/userinfo-host-port-path-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/userinfo-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/userinfo-password-bad-chars-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/userinfo-password-contains-pile-of-poo-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/userinfo-password-empty-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/userinfo-user-empty-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/userinfo-username-contains-at-sign-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/userinfo-username-contains-percent-encoded-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/userinfo-username-contains-pile-of-poo-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/userinfo-username-non-alpha-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/i/model-isvalid.html24
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/i/model-novalid.html18
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/model-isvalid.html36
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/model-novalid.html74
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src-isvalid.html91
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src-whitespace-only-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/fragment-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/fragment-contains-hash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/fragment-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-double-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-double-percent-encoded-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-empty-userinfo-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-empty-with-userinfo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-hostname-in-brackets-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-invalid-unicode-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-invalid-unicode-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-square-brackets-port-contains-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-u0000-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-u0000-percent-encoded-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/path-bare-percent-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/path-contains-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/path-leading-backslash-at-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/path-leading-colon-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/path-leading-colon-chars-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/path-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/path-percent-encoded-malformed-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/path-relative-square-brackets-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/path-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/path-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/path-u0091-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/port-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/port-leading-colon-bracket-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/port-leading-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/port-leading-dash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/port-multiple-letters-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/port-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/port-single-letter-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/port-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/port-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/query-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/query-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-data-contains-fragment-haswarn.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-data-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-file-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-file-single-slash-c-bar-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-file-triple-slash-c-bar-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-ftp-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-ftp-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-http-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-http-no-slash-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-http-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-http-no-slash-square-bracket-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-http-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-https-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-https-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-javascript-no-slash-malformed-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-trailing-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-trailing-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-trailing-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/userinfo-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/userinfo-password-bad-chars-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/userinfo-password-contains-pile-of-poo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/userinfo-username-contains-at-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/userinfo-username-contains-pile-of-poo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/model-isvalid.html31
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/model-novalid.html33
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src-isvalid.html91
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src-whitespace-only-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/fragment-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/fragment-contains-hash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/fragment-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-double-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-double-percent-encoded-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-empty-userinfo-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-empty-with-userinfo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-hostname-in-brackets-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-invalid-unicode-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-invalid-unicode-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-square-brackets-port-contains-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-u0000-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-u0000-percent-encoded-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/path-bare-percent-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/path-contains-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/path-leading-backslash-at-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/path-leading-colon-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/path-leading-colon-chars-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/path-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/path-percent-encoded-malformed-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/path-relative-square-brackets-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/path-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/path-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/path-u0091-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/port-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/port-leading-colon-bracket-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/port-leading-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/port-leading-dash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/port-multiple-letters-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/port-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/port-single-letter-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/port-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/port-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/query-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/query-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-data-contains-fragment-haswarn.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-data-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-file-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-file-single-slash-c-bar-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-file-triple-slash-c-bar-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-ftp-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-ftp-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-http-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-http-no-slash-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-http-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-http-no-slash-square-bracket-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-http-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-https-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-https-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-javascript-no-slash-malformed-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-trailing-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-trailing-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-trailing-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/userinfo-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/userinfo-password-bad-chars-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/userinfo-password-contains-pile-of-poo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/userinfo-username-contains-at-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/userinfo-username-contains-pile-of-poo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/usemap-bad-value-novalid.html1
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/usemap-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/width-height-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/width-height-negative-novalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/list-novalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/pattern-asterisk-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/pattern-paren-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction-isvalid.html91
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction-whitespace-only-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/fragment-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/fragment-contains-hash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/fragment-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-double-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-double-percent-encoded-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-empty-userinfo-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-empty-with-userinfo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-hostname-in-brackets-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-invalid-unicode-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-invalid-unicode-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-square-brackets-port-contains-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-u0000-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-u0000-percent-encoded-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/path-bare-percent-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/path-contains-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/path-leading-backslash-at-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/path-leading-colon-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/path-leading-colon-chars-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/path-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/path-percent-encoded-malformed-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/path-relative-square-brackets-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/path-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/path-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/path-u0091-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/port-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/port-leading-colon-bracket-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/port-leading-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/port-leading-dash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/port-multiple-letters-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/port-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/port-single-letter-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/port-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/port-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/query-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/query-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-data-contains-fragment-haswarn.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-data-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-file-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-file-single-slash-c-bar-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-file-triple-slash-c-bar-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-ftp-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-ftp-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-http-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-http-no-slash-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-http-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-http-no-slash-square-bracket-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-http-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-https-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-https-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-javascript-no-slash-malformed-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-trailing-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-trailing-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-trailing-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/userinfo-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/userinfo-password-bad-chars-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/userinfo-password-contains-pile-of-poo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/userinfo-username-contains-at-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/userinfo-username-contains-pile-of-poo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src-isvalid.html91
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src-whitespace-only-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/fragment-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/fragment-contains-hash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/fragment-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-double-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-double-percent-encoded-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-empty-userinfo-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-empty-with-userinfo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-hostname-in-brackets-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-invalid-unicode-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-invalid-unicode-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-square-brackets-port-contains-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-u0000-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-u0000-percent-encoded-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/path-bare-percent-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/path-contains-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/path-leading-backslash-at-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/path-leading-colon-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/path-leading-colon-chars-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/path-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/path-percent-encoded-malformed-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/path-relative-square-brackets-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/path-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/path-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/path-u0091-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/port-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/port-leading-colon-bracket-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/port-leading-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/port-leading-dash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/port-multiple-letters-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/port-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/port-single-letter-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/port-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/port-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/query-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/query-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-data-contains-fragment-haswarn.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-data-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-file-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-file-single-slash-c-bar-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-file-triple-slash-c-bar-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-ftp-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-ftp-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-http-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-http-no-slash-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-http-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-http-no-slash-square-bracket-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-http-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-https-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-https-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-javascript-no-slash-malformed-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-trailing-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-trailing-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-trailing-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/userinfo-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/userinfo-password-bad-chars-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/userinfo-password-contains-pile-of-poo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/userinfo-username-contains-at-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/userinfo-username-contains-pile-of-poo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction-isvalid.html91
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction-whitespace-only-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/fragment-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/fragment-contains-hash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/fragment-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-double-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-double-percent-encoded-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-empty-userinfo-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-empty-with-userinfo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-hostname-in-brackets-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-invalid-unicode-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-invalid-unicode-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-square-brackets-port-contains-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-u0000-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-u0000-percent-encoded-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/path-bare-percent-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/path-contains-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/path-leading-backslash-at-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/path-leading-colon-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/path-leading-colon-chars-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/path-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/path-percent-encoded-malformed-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/path-relative-square-brackets-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/path-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/path-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/path-u0091-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/port-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/port-leading-colon-bracket-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/port-leading-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/port-leading-dash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/port-multiple-letters-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/port-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/port-single-letter-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/port-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/port-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/query-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/query-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-data-contains-fragment-haswarn.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-data-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-file-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-file-single-slash-c-bar-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-file-triple-slash-c-bar-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-ftp-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-ftp-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-http-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-http-no-slash-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-http-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-http-no-slash-square-bracket-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-http-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-https-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-https-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-javascript-no-slash-malformed-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-trailing-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-trailing-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-trailing-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/userinfo-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/userinfo-password-bad-chars-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/userinfo-password-contains-pile-of-poo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/userinfo-username-contains-at-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/userinfo-username-contains-pile-of-poo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value-empty-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value-isvalid.html70
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/fragment-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/fragment-contains-hash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/fragment-empty-hash-only-no-path-relative-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/fragment-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/fragment-non-ascii-relative-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/fragment-semicolon-question-mark-relative-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/fragment-slash-relative-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-double-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-double-percent-encoded-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-empty-userinfo-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-empty-with-userinfo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-hostname-in-brackets-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-invalid-unicode-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-invalid-unicode-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-square-brackets-port-contains-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-u0000-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-u0000-percent-encoded-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-bare-percent-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-contains-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-leading-backslash-at-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-leading-colon-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-leading-colon-chars-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-percent-encoded-malformed-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-percent-encoded-slash-plus-slashes-relative-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-percent-encoded-slash-relative-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-relative-square-brackets-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-simple-relative-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-slash-only-relative-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-u0091-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/port-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/port-leading-colon-bracket-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/port-leading-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/port-leading-dash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/port-multiple-letters-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/port-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/port-single-letter-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/port-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/port-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/query-empty-no-path-relative-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/query-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/query-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-data-contains-fragment-haswarn.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-data-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-file-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-file-single-slash-c-bar-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-file-triple-slash-c-bar-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-ftp-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-ftp-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-http-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-http-no-slash-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-http-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-http-no-slash-square-bracket-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-http-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-https-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-https-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-javascript-no-slash-malformed-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-schemeless-relative-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-trailing-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-trailing-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-trailing-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/userinfo-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/userinfo-password-bad-chars-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/userinfo-password-contains-pile-of-poo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/userinfo-username-contains-at-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/userinfo-username-contains-pile-of-poo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite-empty-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite-isvalid.html91
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/fragment-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/fragment-contains-hash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/fragment-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-double-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-double-percent-encoded-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-empty-userinfo-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-empty-with-userinfo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-hostname-in-brackets-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-invalid-unicode-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-invalid-unicode-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-square-brackets-port-contains-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-u0000-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-u0000-percent-encoded-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/path-bare-percent-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/path-contains-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/path-leading-backslash-at-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/path-leading-colon-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/path-leading-colon-chars-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/path-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/path-percent-encoded-malformed-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/path-relative-square-brackets-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/path-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/path-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/path-u0091-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/port-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/port-leading-colon-bracket-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/port-leading-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/port-leading-dash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/port-multiple-letters-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/port-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/port-single-letter-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/port-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/port-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/query-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/query-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-data-contains-fragment-haswarn.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-data-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-file-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-file-single-slash-c-bar-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-file-triple-slash-c-bar-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-ftp-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-ftp-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-http-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-http-no-slash-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-http-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-http-no-slash-square-bracket-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-http-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-https-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-https-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-javascript-no-slash-malformed-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-trailing-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-trailing-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-trailing-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/userinfo-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/userinfo-password-bad-chars-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/userinfo-password-contains-pile-of-poo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/userinfo-username-contains-at-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/userinfo-username-contains-pile-of-poo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-0004-02-29-haswarn.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-0005-02-29-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-0214-09-29-haswarn.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-1900-02-29-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-1969-02-29-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-20014-09-29-haswarn.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-2014-02-29-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-2100-02-29-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-2200-02-29-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-day-01-32-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-day-03-32-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-day-04-31-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-day-05-32-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-day-06-31-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-day-07-32-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-day-08-32-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-day-09-31-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-day-10-32-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-day-11-31-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-day-12-32-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-day-missing-separator-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-day-one-digit-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-day-three-digits-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-iso8601-YYYYMMDD-no-hyphen-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-leading-bom-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-leading-whitespace-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-month-00-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-month-13-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-month-missing-separator-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-month-one-digit-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-month-three-digits-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-non-ascii-digit-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-trailing-U+0000-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-trailing-pile-of-poo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-trailing-whitespace-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-wrong-day-separator-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-wrong-month-separator-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-year-0000-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-year-five-digits-haswarn.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-year-negative-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-year-three-digits-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/datetime-isvalid.html33
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/duration-P-form-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/duration-time-component-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-2400-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-60-minutes-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-60-seconds-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-bad-fraction-separator-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-four-digit-fraction-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-hour-one-digit-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-hour-three-digits-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-iso8601-hh-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-iso8601-hhmm-no-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-iso8601-hhmmss-no-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-lowercase-z-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-minutes-one-digit-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-minutes-three-digits-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-missing-minutes-separator-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-missing-seconds-separator-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-nbsp-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-seconds-one-digit-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-seconds-three-digits-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-space-before-timezone-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-60-minutes-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-iso8601-two-digit-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-lowercase-t-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-minus-1300-haswarn.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-minus-2400-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-minutes-15-haswarn.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-multiple-spaces-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-non-T-character-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-offset-colon-start-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-offset-space-start-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-one-digit-hour-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-one-digit-minute-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-plus-1500-haswarn.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-plus-2400-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-three-digit-hour-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-three-digit-minute-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-with-seconds-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-with-both-T-and-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-wrong-minutes-separator-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-wrong-seconds-separator-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-zero-digit-fraction-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/local-date-and-time-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/model-isvalid.html32
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/model-novalid.html46
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/month-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/time-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/week-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/year-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/yearless-date-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/kbd/model-isvalid.html23
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/kbd/model-novalid.html18
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/keygen/challenge-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/keygen/id-bad-novalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/keygen/id-missing-novalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/keygen/id-redundant-novalid.html13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/keygen/keytype-bad-value-novalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/keygen/keytype-empty-novalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/keygen/keytype-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/keygen/model-isvalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/keygen/model-novalid.html12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/keygen/no-attributes-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/keygen/non-void-novalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/label/for-descendant-no-id-novalid.html1
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/label/for-isvalid.html1
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/label/multiple-descendants-novalid.html1
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href-isvalid.html91
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href-missing-novalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href-whitespace-only-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/fragment-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/fragment-contains-hash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/fragment-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-double-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-double-percent-encoded-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-empty-userinfo-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-empty-with-userinfo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-hostname-in-brackets-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-invalid-unicode-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-invalid-unicode-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-square-brackets-port-contains-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-u0000-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-u0000-percent-encoded-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/path-bare-percent-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/path-contains-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/path-leading-backslash-at-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/path-leading-colon-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/path-leading-colon-chars-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/path-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/path-percent-encoded-malformed-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/path-relative-square-brackets-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/path-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/path-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/path-u0091-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/port-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/port-leading-colon-bracket-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/port-leading-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/port-leading-dash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/port-multiple-letters-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/port-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/port-single-letter-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/port-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/port-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/query-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/query-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-data-contains-fragment-haswarn.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-data-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-file-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-file-single-slash-c-bar-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-file-triple-slash-c-bar-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-ftp-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-ftp-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-http-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-http-no-slash-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-http-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-http-no-slash-square-bracket-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-http-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-https-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-https-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-javascript-no-slash-malformed-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-trailing-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-trailing-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-trailing-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/userinfo-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/userinfo-password-bad-chars-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/userinfo-password-contains-pile-of-poo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/userinfo-username-contains-at-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/userinfo-username-contains-pile-of-poo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/map/model-isvalid.html27
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/map/model-novalid.html27
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/mark/model-isvalid.html23
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/meta/names-registered-isvalid.html768
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/meta/names-standard-isvalid.html21
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/meta/refresh-isvalid.html91
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/noscript/model-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data-isvalid.html91
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data-type-missing-novalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data-whitespace-only-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/fragment-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/fragment-contains-hash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/fragment-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-double-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-double-percent-encoded-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-empty-userinfo-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-empty-with-userinfo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-hostname-in-brackets-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-invalid-unicode-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-invalid-unicode-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-square-brackets-port-contains-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-u0000-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-u0000-percent-encoded-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/path-bare-percent-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/path-contains-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/path-leading-backslash-at-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/path-leading-colon-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/path-leading-colon-chars-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/path-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/path-percent-encoded-malformed-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/path-relative-square-brackets-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/path-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/path-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/path-u0091-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/port-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/port-leading-colon-bracket-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/port-leading-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/port-leading-dash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/port-multiple-letters-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/port-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/port-single-letter-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/port-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/port-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/query-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/query-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-data-contains-fragment-haswarn.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-data-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-file-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-file-single-slash-c-bar-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-file-triple-slash-c-bar-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-ftp-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-ftp-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-http-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-http-no-slash-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-http-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-http-no-slash-square-bracket-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-http-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-https-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-https-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-javascript-no-slash-malformed-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-trailing-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-trailing-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-trailing-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/userinfo-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/userinfo-password-bad-chars-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/userinfo-password-contains-pile-of-poo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/userinfo-username-contains-at-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/userinfo-username-contains-pile-of-poo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/model-isvalid.html79
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/model-novalid.html81
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ol/model-isvalid.html38
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ol/model-novalid.html55
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/option/label-isvalid.html6
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/option/label-novalid.html6
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/option/model-isvalid.html6
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/option/model-novalid.html6
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/p/model-isvalid.html15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/p/model-novalid.html17
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/param/model-isvalid.html18
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/param/model-novalid.html40
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/always-matching-source-media-all-spaces-with-following-source-srcset-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/always-matching-source-media-all-with-following-source-srcset-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/always-matching-source-media-empty-with-following-source-srcset-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/always-matching-source-media-spaces-with-following-source-srcset-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/always-matching-source-media-uppercase-with-following-source-srcset-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/always-matching-source-sizes-with-following-source-srcset-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/always-matching-source-with-following-img-srcset-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/always-matching-source-with-following-source-media-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/always-matching-source-with-following-source-srcset-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/always-matching-source-with-following-source-type-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/audio-srcset-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/html-syntax-img-end-tag-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/html-syntax-picture-no-end-tag-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/html-syntax-picture-slash-no-end-tag-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/html-syntax-picture-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/html-syntax-source-end-tag-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/img-no-src-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/img-no-src-with-picture-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/img-no-src-with-source-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/img-no-src-with-srcset-and-picture-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/img-no-src-with-srcset-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/img-srcset-no-descriptor-with-sizes-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/img-srcset-w-and-x-width-sizes-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/img-srcset-w-no-sizes-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/img-type-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/img-type-with-picture-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/img-with-sizes-no-srcset-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/input-type-image-srcset-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-br-after-img-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-br-after-source-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-br-before-img-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-br-before-source-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-figure-wrapping-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-input-type-hidden-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-math-nog-img-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-noscript-after-source-no-img-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-noscript-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-p-after-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-p-before-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-p-wrapping-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-picture-before-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-picture-wrapping-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-span-after-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-span-before-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-span-wrapping-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-style-scroped-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-svg-no-img-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-svg-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-text-after-img-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-text-after-source-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-text-before-img-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-text-before-source-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-video-before-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-video-no-img-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/link-rel-icon-srcset-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/missing-img-empty-picture-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/missing-img-only-script-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/missing-img-only-source-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/missing-img-script-and-source-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/missing-img-source-and-script-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/multiple-img-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/multiple-img-with-script-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/multiple-img-with-source-and-script-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/multiple-img-with-source-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/object-srcset-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/parent-dl-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/parent-hgroup-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/parent-noscript-in-head-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/parent-ul-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-align-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-alt-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-aria-role-application-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-aria-role-button-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-aria-role-img-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-aria-role-presentation-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-aria-role-region-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-border-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-crossorigin-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-height-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-hspace-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-ismap-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-isvalid.html107
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-longdesc-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-lowsrc-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-media-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-name-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-sizes-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-src-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-srcset-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-usemap-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-vspace-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-width-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-auto-source-size-value-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-comma-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-css-comment-after-plus-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-css-comment-before-unit-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-default-first-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-default-source-size-value-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-deg-source-size-value-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-dpcm-source-size-value-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-dpi-source-size-value-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-dppx-source-size-value-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-foo-bar-source-size-value-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-grad-source-size-value-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-hz-source-size-value-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-inherit-source-size-value-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-initial-source-size-value-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-junk-in-default-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-junk-in-source-size-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-khz-source-size-value-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-media-all-and-min-width-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-media-all-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-media-bad-junk-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-media-general-enclosed-junk-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-media-min-width-no-parenthesis-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-ms-source-size-value-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-negative-source-size-value-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-no-unit-in-source-size-value-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-percent-in-source-size-value-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-rad-source-size-value-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-s-source-size-value-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-scientific-notation-negative-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-scientific-notation-non-integer-in-exponent-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-trailing-comma-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-trailing-junk-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-turn-source-size-value-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-two-defaults-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-after-img-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-align-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-alt-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-aria-role-img-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-aria-role-presentation-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-before-and-after-img-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-border-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-crossorigin-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-height-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-hspace-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-ismap-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-longdesc-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-name-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-no-srcset-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-no-srcset-with-media-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-no-srcset-with-sizes-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-no-srcset-with-type-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-src-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-src-srcset-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-srcset-h-with-sizes-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-srcset-w-and-x-with-sizes-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-srcset-w-no-sizes-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-srcset-x-with-sizes-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-type-srcset-w-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-usemap-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-vspace-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-width-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-broken-url-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-comma-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-css-comment-after-descriptor-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-curly-bracket-junk-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-function-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-h-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-infinity-x-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-leading-comma-multiple-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-leading-comma-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-leading-dot-x-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-nan-x-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-negative-w-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-negative-x-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-negative-zero-w-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-negative-zero-x-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-non-integer-w-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-parenthesis-junk-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-pipe-junk-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-plus-w-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-plus-x-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-scientific-notation-w-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-square-bracket-junk-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-trailing-comma-multiple-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-trailing-comma-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-unique-descriptors-1x-and-omitted-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-unique-descriptors-2x-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-unique-descriptors-integer-and-decimals-x-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-unique-descriptors-w-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-uppercase-w-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-w-and-h-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-w-and-no-descriptor-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-x-and-h-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-x-and-w-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-zero-w-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-zero-x-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/svg-image-srcset-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/track-srcset-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/video-source-media-src-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/video-source-sizes-srcset-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/video-source-srcset-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/video-source-srcset-src-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/video-srcset-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/pre/model-isvalid.html17
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/pre/model-novalid.html26
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite-empty-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite-isvalid.html91
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/fragment-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/fragment-contains-hash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/fragment-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-double-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-double-percent-encoded-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-empty-userinfo-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-empty-with-userinfo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-hostname-in-brackets-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-invalid-unicode-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-invalid-unicode-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-square-brackets-port-contains-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-u0000-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-u0000-percent-encoded-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/path-bare-percent-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/path-contains-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/path-leading-backslash-at-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/path-leading-colon-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/path-leading-colon-chars-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/path-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/path-percent-encoded-malformed-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/path-relative-square-brackets-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/path-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/path-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/path-u0091-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/port-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/port-leading-colon-bracket-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/port-leading-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/port-leading-dash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/port-multiple-letters-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/port-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/port-single-letter-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/port-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/port-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/query-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/query-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-data-contains-fragment-haswarn.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-data-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-file-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-file-single-slash-c-bar-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-file-triple-slash-c-bar-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-ftp-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-ftp-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-http-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-http-no-slash-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-http-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-http-no-slash-square-bracket-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-http-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-https-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-https-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-javascript-no-slash-malformed-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-trailing-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-trailing-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-trailing-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/userinfo-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/userinfo-password-bad-chars-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/userinfo-password-contains-pile-of-poo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/userinfo-username-contains-at-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/userinfo-username-contains-pile-of-poo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/model-isvalid.html23
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/model-novalid.html25
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ruby/empty-novalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ruby/missing-rt-novalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/s/model-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/samp/model-isvalid.html23
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/samp/model-novalid.html25
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/language-novalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src-isvalid.html91
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src-whitespace-only-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/fragment-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/fragment-contains-hash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/fragment-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-double-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-double-percent-encoded-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-empty-userinfo-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-empty-with-userinfo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-hostname-in-brackets-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-invalid-unicode-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-invalid-unicode-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-square-brackets-port-contains-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-u0000-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-u0000-percent-encoded-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/path-bare-percent-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/path-contains-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/path-leading-backslash-at-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/path-leading-colon-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/path-leading-colon-chars-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/path-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/path-percent-encoded-malformed-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/path-relative-square-brackets-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/path-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/path-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/path-u0091-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/port-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/port-leading-colon-bracket-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/port-leading-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/port-leading-dash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/port-multiple-letters-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/port-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/port-single-letter-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/port-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/port-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/query-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/query-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-data-contains-fragment-haswarn.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-data-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-file-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-file-single-slash-c-bar-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-file-triple-slash-c-bar-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-ftp-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-ftp-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-http-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-http-no-slash-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-http-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-http-no-slash-square-bracket-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-http-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-https-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-https-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-javascript-no-slash-malformed-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-trailing-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-trailing-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-trailing-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/userinfo-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/userinfo-password-bad-chars-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/userinfo-password-contains-pile-of-poo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/userinfo-username-contains-at-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/userinfo-username-contains-pile-of-poo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/small/model-isvalid.html23
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/small/model-novalid.html25
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src-isvalid.html91
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src-whitespace-only-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/fragment-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/fragment-contains-hash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/fragment-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-double-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-double-percent-encoded-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-empty-userinfo-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-empty-with-userinfo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-hostname-in-brackets-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-invalid-unicode-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-invalid-unicode-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-square-brackets-port-contains-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-u0000-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-u0000-percent-encoded-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/path-bare-percent-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/path-contains-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/path-leading-backslash-at-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/path-leading-colon-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/path-leading-colon-chars-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/path-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/path-percent-encoded-malformed-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/path-relative-square-brackets-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/path-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/path-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/path-u0091-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/port-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/port-leading-colon-bracket-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/port-leading-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/port-leading-dash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/port-multiple-letters-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/port-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/port-single-letter-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/port-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/port-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/query-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/query-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-data-contains-fragment-haswarn.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-data-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-file-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-file-single-slash-c-bar-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-file-triple-slash-c-bar-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-ftp-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-ftp-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-http-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-http-no-slash-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-http-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-http-no-slash-square-bracket-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-http-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-https-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-https-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-javascript-no-slash-malformed-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-trailing-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-trailing-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-trailing-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/userinfo-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/userinfo-password-bad-chars-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/userinfo-password-contains-pile-of-poo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/userinfo-username-contains-at-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/userinfo-username-contains-pile-of-poo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/span/model-isvalid.html23
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/span/model-novalid.html25
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/strong/model-isvalid.html22
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/strong/model-novalid.html25
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/style/model-isvalid.html20
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/style/scoped-as-div-child-isvalid.html8
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/style/scoped-as-p-child-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/style/scoped-in-head-novalid.html6
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/style/scoped-isvalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/style/scoped-model-novalid.html8
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/style/scoped-multiple-adjacent-isvalid.html9
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/sub/model-isvalid.html24
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/sub/model-novalid.html18
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/sup/model-isvalid.html24
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/sup/model-novalid.html18
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/table/model-input-child-hidden-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/table/model-input-child-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/table/model-input-type-child-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/time/datetime-isvalid.html57
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/title/empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/title/missing-novalid.html2
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src-isvalid.html91
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src-whitespace-only-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/fragment-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/fragment-contains-hash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/fragment-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-double-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-double-percent-encoded-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-empty-userinfo-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-empty-with-userinfo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-hostname-in-brackets-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-invalid-unicode-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-invalid-unicode-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-square-brackets-port-contains-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-u0000-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-u0000-percent-encoded-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/path-bare-percent-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/path-contains-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/path-leading-backslash-at-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/path-leading-colon-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/path-leading-colon-chars-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/path-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/path-percent-encoded-malformed-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/path-relative-square-brackets-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/path-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/path-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/path-u0091-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/port-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/port-leading-colon-bracket-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/port-leading-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/port-leading-dash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/port-multiple-letters-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/port-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/port-single-letter-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/port-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/port-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/query-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/query-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-data-contains-fragment-haswarn.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-data-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-file-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-file-single-slash-c-bar-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-file-triple-slash-c-bar-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-ftp-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-ftp-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-http-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-http-no-slash-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-http-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-http-no-slash-square-bracket-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-http-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-https-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-https-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-javascript-no-slash-malformed-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-trailing-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-trailing-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-trailing-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/userinfo-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/userinfo-password-bad-chars-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/userinfo-password-contains-pile-of-poo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/userinfo-username-contains-at-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/userinfo-username-contains-pile-of-poo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/u/model-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ul/model-isvalid.html39
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/ul/model-novalid.html55
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/var/model-isvalid.html24
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/var/model-novalid.html18
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/model-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/model-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster-isvalid.html91
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster-whitespace-only-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/fragment-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/fragment-contains-hash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/fragment-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-double-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-double-percent-encoded-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-empty-userinfo-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-empty-with-userinfo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-hostname-in-brackets-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-invalid-unicode-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-invalid-unicode-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-square-brackets-port-contains-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-u0000-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-u0000-percent-encoded-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/path-bare-percent-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/path-contains-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/path-leading-backslash-at-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/path-leading-colon-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/path-leading-colon-chars-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/path-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/path-percent-encoded-malformed-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/path-relative-square-brackets-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/path-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/path-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/path-u0091-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/port-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/port-leading-colon-bracket-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/port-leading-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/port-leading-dash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/port-multiple-letters-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/port-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/port-single-letter-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/port-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/port-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/query-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/query-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-data-contains-fragment-haswarn.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-data-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-file-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-file-single-slash-c-bar-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-file-triple-slash-c-bar-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-ftp-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-ftp-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-http-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-http-no-slash-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-http-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-http-no-slash-square-bracket-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-http-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-https-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-https-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-javascript-no-slash-malformed-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-trailing-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-trailing-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-trailing-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/userinfo-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/userinfo-password-bad-chars-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/userinfo-password-contains-pile-of-poo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/userinfo-username-contains-at-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/userinfo-username-contains-pile-of-poo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src-isvalid.html91
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/fragment-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/fragment-contains-hash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/fragment-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-double-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-double-percent-encoded-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-empty-userinfo-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-empty-with-userinfo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-hostname-in-brackets-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-invalid-unicode-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-invalid-unicode-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-square-brackets-port-contains-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-u0000-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-u0000-percent-encoded-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/path-bare-percent-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/path-contains-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/path-leading-backslash-at-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/path-leading-colon-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/path-leading-colon-chars-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/path-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/path-percent-encoded-malformed-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/path-relative-square-brackets-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/path-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/path-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/path-u0091-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/port-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/port-leading-colon-bracket-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/port-leading-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/port-leading-dash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/port-multiple-letters-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/port-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/port-single-letter-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/port-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/port-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/query-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/query-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-data-contains-fragment-haswarn.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-data-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-file-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-file-single-slash-c-bar-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-file-triple-slash-c-bar-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-ftp-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-ftp-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-http-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-http-no-slash-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-http-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-http-no-slash-square-bracket-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-http-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-https-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-https-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-javascript-no-slash-malformed-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-trailing-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-trailing-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-trailing-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/userinfo-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/userinfo-password-bad-chars-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/userinfo-password-contains-pile-of-poo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/userinfo-username-contains-at-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/userinfo-username-contains-pile-of-poo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/001-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/001-novalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/002-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/002-novalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/003-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/003-novalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/004-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/004-novalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/005-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/005-novalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/006-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/006-novalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/007-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/007-novalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/008-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/008-novalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/009-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/009-novalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/010-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/010-novalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/011-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/011-novalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/012-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/012-novalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/013-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/013-novalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/014-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/014-novalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/015-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/015-novalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/016-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/016-novalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/017-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/017-novalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/018-haswarn.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/018-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/019-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/019-novalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/020-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/020-novalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/021-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/021-novalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/022-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/022-novalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/023-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/023-novalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/024-novalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/025-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/026-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/027-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/028-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/029-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/030-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/031-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/032-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/033-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/118-isvalid.html13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/source-isvalid.txt33
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/source-novalid.txt24
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid-empty-isvalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid-isvalid.html91
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid-scheme-data-contains-fragment-haswarn.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/fragment-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/fragment-contains-hash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/fragment-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-double-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-double-percent-encoded-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-empty-userinfo-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-empty-with-userinfo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-hostname-in-brackets-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-invalid-unicode-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-invalid-unicode-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-square-brackets-port-contains-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-u0000-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-u0000-percent-encoded-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/path-bare-percent-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/path-contains-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/path-leading-backslash-at-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/path-leading-colon-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/path-leading-colon-chars-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/path-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/path-percent-encoded-malformed-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/path-relative-square-brackets-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/path-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/path-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/path-u0091-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/port-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/port-leading-colon-bracket-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/port-leading-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/port-leading-dash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/port-multiple-letters-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/port-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/port-single-letter-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/port-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/port-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/query-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/query-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-data-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-file-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-file-single-slash-c-bar-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-file-triple-slash-c-bar-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-ftp-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-ftp-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-http-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-http-no-slash-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-http-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-http-no-slash-square-bracket-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-http-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-https-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-https-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-javascript-no-slash-malformed-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-trailing-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-trailing-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-trailing-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/userinfo-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/userinfo-password-bad-chars-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/userinfo-password-contains-pile-of-poo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/userinfo-username-contains-at-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/userinfo-username-contains-pile-of-poo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype-isvalid.html70
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype-scheme-data-contains-fragment-haswarn.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/fragment-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/fragment-contains-hash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/fragment-empty-hash-only-no-path-relative-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/fragment-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/fragment-non-ascii-relative-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/fragment-semicolon-question-mark-relative-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/fragment-slash-relative-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-double-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-double-percent-encoded-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-empty-userinfo-empty-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-empty-with-userinfo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-hostname-in-brackets-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-invalid-unicode-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-invalid-unicode-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-square-brackets-port-contains-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-u0000-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-u0000-percent-encoded-percent-encoded-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-bare-percent-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-contains-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-leading-backslash-at-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-leading-colon-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-leading-colon-chars-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-percent-encoded-malformed-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-percent-encoded-slash-plus-slashes-relative-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-percent-encoded-slash-relative-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-relative-square-brackets-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-simple-relative-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-slash-only-relative-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-u0091-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/port-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/port-leading-colon-bracket-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/port-leading-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/port-leading-dash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/port-multiple-letters-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/port-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/port-single-letter-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/port-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/port-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/query-empty-no-path-relative-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/query-leading-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/query-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-data-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-ftp-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-ftp-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-http-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-http-no-slash-colon-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-http-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-http-no-slash-square-bracket-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-http-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-https-no-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-https-single-slash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-javascript-no-slash-malformed-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-schemeless-relative-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-trailing-cr-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-trailing-newline-novalid.html5
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-trailing-space-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-trailing-tab-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/userinfo-backslash-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/userinfo-password-bad-chars-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/userinfo-password-contains-pile-of-poo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/userinfo-username-contains-at-sign-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/userinfo-username-contains-pile-of-poo-novalid.html4
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/001-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/001-novalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/002-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/002-novalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/003-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/003-novalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/004-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/004-novalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/005-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/005-novalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/006-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/006-novalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/007-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/007-novalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/008-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/008-novalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/009-isvalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/009-novalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/010-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/010-novalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/011-isvalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/011-novalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/source-isvalid.txt11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/source-novalid.txt11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/obsolete/acronym-novalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/obsolete/applet-novalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/obsolete/basefont-novalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/obsolete/big-novalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/obsolete/center-novalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/obsolete/dir-novalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/obsolete/font-novalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/obsolete/frameset-novalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/obsolete/noframes-novalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/obsolete/profile-novalid.html11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/obsolete/strike-novalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/obsolete/tt-novalid.html10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/other/applet-novalid.html108
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/other/obj-novalid.html123
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/parser/cr-charref-novalid.html1
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/parser/range-charref-novalid.html1
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/parser/u000b-charref-novalid.html1
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/parser/u000b-novalid.html1
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/parser/u007f-charref-novalid.html1
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/parser/u10ffff-charref-novalid.html1
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/parser/ufffe-charref-novalid.html1
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/html/parser/unassigned-charref-novalid.html1
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/index.html113
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/messages.json2403
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/tools/ins-del-datetime.py176
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/tools/picture.py364
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/tools/url.py453
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/attributes/accesskey/003-novalid.xhtml8
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/attributes/accesskey/004-novalid.xhtml8
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/attributes/data/002-novalid.xhtml9
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/attributes/spellcheck/050-novalid.xhtml8
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/attributes/spellcheck/051-isvalid.xhtml8
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/attributes/spellcheck/052-isvalid.xhtml8
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/attributes/spellcheck/053-isvalid.xhtml8
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/attributes/spellcheck/350-novalid.xhtml8
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/a/100-novalid.xhtml8
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/address/029-isvalid.xhtml15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/base/001-novalid.xhtml9
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/blockquote/028-isvalid.xhtml16
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/code/010-isvalid.xhtml20
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/del/041-isvalid.xhtml32
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/dialog/001-novalid.xhtml13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/dl/032-isvalid.xhtml53
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/em/006-isvalid.xhtml21
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/embed/001-novalid.xhtml8
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/embed/002-novalid.xhtml8
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/embed/003-novalid.xhtml8
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/figure/002-novalid.xhtml12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/figure/101-novalid.xhtml12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/figure/102-novalid.xhtml12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/figure/103-novalid.xhtml12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/figure/104-novalid.xhtml12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/figure/304-novalid.xhtml12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/footer/001-novalid.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/footer/003-novalid.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/header/001-novalid.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/header/002-novalid.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/iframe/042-isvalid.xhtml19
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/iframe/042-novalid.xhtml8
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/img/003-novalid.xhtml8
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/img/004-novalid.xhtml9
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/img/043-isvalid.xhtml29
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/img/051-isvalid.xhtml8
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/img/051-novalid.xhtml8
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/img/052-isvalid.xhtml8
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/img/302-isvalid.xhtml9
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/input/003-novalid.xhtml9
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/ins/040-isvalid.xhtml25
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/054-isvalid.xhtml8
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/054-novalid.xhtml8
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/055-isvalid.xhtml8
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/056-isvalid.xhtml8
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/056-novalid.xhtml8
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/057-isvalid.xhtml8
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/057-novalid.xhtml8
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/058-isvalid.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/058-novalid.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/059-novalid.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/060-novalid.xhtml11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/061-novalid.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/154-novalid.xhtml8
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/157-novalid.xhtml8
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/359-novalid.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/360-novalid.xhtml11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/361-novalid.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/link/001-novalid.xhtml8
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/map/048-isvalid.xhtml21
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/mark/009-isvalid.xhtml21
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/menu/001-haswarn.xhtml21
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/menu/001-novalid.xhtml14
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/meter/002-isvalid.xhtml26
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/meter/003-isvalid.xhtml8
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/meter/010-novalid.xhtml8
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/meter/011-novalid.xhtml8
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/meter/012-novalid.xhtml8
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/meter/110-novalid.xhtml8
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/meter/312-novalid.xhtml8
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/object/001-novalid.xhtml9
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/object/044-isvalid.xhtml75
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/ol/031-isvalid.xhtml36
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/p/025-isvalid.xhtml12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/pre/027-isvalid.xhtml15
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/progress/002-isvalid.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/progress/008-novalid.xhtml8
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/progress/009-novalid.xhtml8
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/progress/108-novalid.xhtml8
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/progress/309-novalid.xhtml8
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/q/013-isvalid.xhtml20
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/ruby/001-novalid.xhtml8
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/ruby/002-novalid.xhtml8
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/samp/011-isvalid.xhtml20
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/script/001-novalid.xhtml8
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/span/014-isvalid.xhtml20
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/strong/007-isvalid.xhtml20
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/strong/008-isvalid.xhtml20
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/table/201-isvalid.xhtml13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/table/201-novalid.xhtml11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/table/202-isvalid.xhtml11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/table/202-novalid.xhtml11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/table/203-isvalid.xhtml12
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/table/203-novalid.xhtml11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/table/204-isvalid.xhtml8892
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/table/204-novalid.xhtml13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/table/205-novalid.xhtml13
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/time/001-isvalid.xhtml55
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/ul/030-isvalid.xhtml35
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/media-queries/119-isvalid.xhtml11
-rw-r--r--tests/wpt/web-platform-tests/conformance-checkers/xhtml/other/045-novalid.xhtml105
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/README.css27
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/README.html119
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_10.html21
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_10.html.sub.headers6
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_10_1.sub.html22
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_10_1.sub.html.sub.headers6
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_2.html15
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_2.html.sub.headers6
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_2_2.sub.html22
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_2_2.sub.html.sub.headers6
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_2_3.html22
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_2_3.html.sub.headers6
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_8.html22
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_8.html.sub.headers6
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_8_1.sub.html21
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_8_1.sub.html.sub.headers6
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_9.sub.html22
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_9.sub.html.sub.headers6
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/generic/negativeTests.js3
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/generic/positiveTest.js6
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/generic/unreached.js3
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/generic/wildcardHostTest.js8
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/generic/wildcardHostTestFailure.js8
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/generic/wildcardHostTestSuceeds.js1
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/generic/wildcardPortTest.js8
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/generic/wildcardPortTestSuceeds.js1
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/img-src/img-src-4_1.html46
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/img-src/img-src-4_1.html.sub.headers6
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/media-src/media-src-7_1.html44
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/media-src/media-src-7_1.html.sub.headers6
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/media-src/media-src-7_1_2.html54
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/media-src/media-src-7_1_2.html.sub.headers6
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/media-src/media-src-7_2.html44
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/media-src/media-src-7_2.html.sub.headers6
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/media-src/media-src-7_2_2.html54
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/media-src/media-src-7_2_2.html.sub.headers6
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/media-src/media-src-7_3.html53
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/media-src/media-src-7_3.html.sub.headers6
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/media-src/media-src-7_3_2.html53
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/media-src/media-src-7_3_2.html.sub.headers6
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/object-src/object-src-2_1.html56
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/object-src/object-src-2_1.html.sub.headers6
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/object-src/object-src-2_2.html56
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/object-src/object-src-2_2.html.sub.headers6
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/script-src/10_1_support_1.js1
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/script-src/10_1_support_2.js3
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/script-src/addInlineTestsWithDOMManipulation.js18
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/script-src/buildInlineWorker.js21
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/script-src/inlineSuccessTest.js8
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/script-src/inlineTests.js4
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/script-src/script-src-1_1.html22
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/script-src/script-src-1_1.html.sub.headers6
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/script-src/script-src-1_10.html27
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/script-src/script-src-1_10.html.sub.headers6
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/script-src/script-src-1_10_1.html20
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/script-src/script-src-1_10_1.html.sub.headers6
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/script-src/script-src-1_2_1.html23
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/script-src/script-src-1_2_1.html.sub.headers6
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/script-src/script-src-1_3.html20
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/script-src/script-src-1_3.html.sub.headers6
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/script-src/script-src-1_4.html22
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/script-src/script-src-1_4.html.sub.headers6
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/script-src/script-src-1_9.html22
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/script-src/script-src-1_9.html.sub.headers6
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/style-src/3_3.css1
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/style-src/style-src-3_1.html33
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/style-src/style-src-3_1.html.sub.headers6
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/style-src/style-src-3_2.html25
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/style-src/style-src-3_2.html.sub.headers6
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/style-src/style-src-3_3.html37
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/style-src/style-src-3_3.html.sub.headers6
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/style-src/style-src-3_4-import.css3
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/style-src/style-src-3_4.css1
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/style-src/style-src-3_4.html27
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/style-src/style-src-3_4.html.sub.headers6
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/support/checkReport.sub.js62
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/support/fail.pngbin0 -> 759 bytes
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/support/media/flash.swfbin0 -> 638 bytes
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/support/pass.pngbin0 -> 1689 bytes
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/support/report.py26
-rw-r--r--tests/wpt/web-platform-tests/cors/allow-headers.htm89
-rw-r--r--tests/wpt/web-platform-tests/cors/basic.htm63
-rw-r--r--tests/wpt/web-platform-tests/cors/credentials-flag.htm129
-rw-r--r--tests/wpt/web-platform-tests/cors/late-upload-events.htm46
-rw-r--r--tests/wpt/web-platform-tests/cors/origin.htm119
-rw-r--r--tests/wpt/web-platform-tests/cors/preflight-cache.htm140
-rw-r--r--tests/wpt/web-platform-tests/cors/redirect-origin.htm195
-rw-r--r--tests/wpt/web-platform-tests/cors/redirect-preflight-2.htm55
-rw-r--r--tests/wpt/web-platform-tests/cors/redirect-preflight.htm65
-rw-r--r--tests/wpt/web-platform-tests/cors/redirect-userinfo.htm110
-rw-r--r--tests/wpt/web-platform-tests/cors/remote-origin.htm122
-rw-r--r--tests/wpt/web-platform-tests/cors/request-headers.htm80
-rw-r--r--tests/wpt/web-platform-tests/cors/resources/.gitignore1
-rw-r--r--tests/wpt/web-platform-tests/cors/resources/checkandremove.py6
-rw-r--r--tests/wpt/web-platform-tests/cors/resources/cors-cookie.py21
-rw-r--r--tests/wpt/web-platform-tests/cors/resources/cors-headers.asis24
-rw-r--r--tests/wpt/web-platform-tests/cors/resources/cors-makeheader.py64
-rw-r--r--tests/wpt/web-platform-tests/cors/resources/preflight.py35
-rw-r--r--tests/wpt/web-platform-tests/cors/resources/remote-xhrer.html28
-rw-r--r--tests/wpt/web-platform-tests/cors/resources/status.py37
-rw-r--r--tests/wpt/web-platform-tests/cors/response-headers.htm103
-rw-r--r--tests/wpt/web-platform-tests/cors/simple-requests.htm91
-rw-r--r--tests/wpt/web-platform-tests/cors/status-async.htm114
-rw-r--r--tests/wpt/web-platform-tests/cors/status-preflight.htm64
-rw-r--r--tests/wpt/web-platform-tests/cors/status.htm80
-rw-r--r--tests/wpt/web-platform-tests/cors/support.js30
-rw-r--r--tests/wpt/web-platform-tests/csp/assert_undefined.py8
-rw-r--r--tests/wpt/web-platform-tests/csp/csp-inline-script.html11
-rw-r--r--tests/wpt/web-platform-tests/csp/csp-inline-script.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/concepts/custom-elements-type-allowed-chars-first-char.html58
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/concepts/custom-elements-type-allowed-chars.html54
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/concepts/custom-elements-type-naming.html66
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/creating-and-passing-registries/new-registry-test.html40
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/creating-and-passing-registries/no-registry-test.html49
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/creating-and-passing-registries/share-registry-create-document.html52
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/creating-and-passing-registries/share-registry-import-document.html96
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/custom-element-lifecycle/enqueuing-and-invoking-callbacks/invoke-callbacks.html61
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/custom-element-lifecycle/types-of-callbacks/attached-callback-move-element-test.html160
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/custom-element-lifecycle/types-of-callbacks/attached-callback-test.html117
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/custom-element-lifecycle/types-of-callbacks/attribute-changed-callback-change-attribute-test.html230
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/custom-element-lifecycle/types-of-callbacks/attribute-changed-callback-remove-attribute-test.html167
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/custom-element-lifecycle/types-of-callbacks/attribute-changed-callback-set-attribute-test.html339
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/custom-element-lifecycle/types-of-callbacks/created-callback-element-prototype-test.html88
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/custom-element-lifecycle/types-of-callbacks/created-callback-invocation-order-test.html243
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/custom-element-lifecycle/types-of-callbacks/created-callback-invocation-test.html168
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/custom-element-lifecycle/types-of-callbacks/detached-callback-move-element-test.html131
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/custom-element-lifecycle/types-of-callbacks/detached-callback-no-browsing-context-test.html148
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/custom-element-lifecycle/types-of-callbacks/detached-callback-with-browsing-context-test.html86
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/changing-is-attribute.html159
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/custom-element-constructor-is-attribute.html50
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/custom-element-constructor-local-name.html45
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/custom-element-constructor-namespace.html44
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/custom-element-constructor-node-document.html101
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/custom-element-constructor-prototype.html29
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/custom-element-prototype.html31
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/custom-element-type-is-attribute.html74
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/custom-element-type-local-name-and-is-attribute.html102
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/custom-element-type-local-name.html39
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/extensions-to-document-interface/create-element-interface-type-is-a-local-name.html44
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/extensions-to-document-interface/create-element-interface-type-is-a-type-extension.html70
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/extensions-to-document-interface/create-element-is-attribute.html72
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/extensions-to-document-interface/create-element-namespace.html69
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/extensions-to-document-interface/create-element-type-extension-is-a-type.html48
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/extensions-to-document-interface/create-element-type-extension-unresolved.html50
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/extensions-to-document-interface/create-element-type-is-a-local-name.html39
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/extensions-to-document-interface/created-callback-create-element-ns.html73
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/extensions-to-document-interface/created-callback-create-element.html73
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/non-configurable-constructor-property.html42
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/prototype-is-interface-prototype-object.html45
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/unchanged-attribute.html29
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/definition-construction-algorithm-default-namespace.html44
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/definition-construction-algorithm-duplicate-definition.html57
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/definition-construction-algorithm-invalid-type.html23
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/definition-construction-algorithm-local-name-lowercased.html33
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/definition-construction-algorithm-name-is-null.html41
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/definition-construction-algorithm-no-interface-for-name.html27
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/definition-construction-algorithm-svg-namespace-name-is-null.html37
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/definition-construction-algorithm-svg-namespace.html27
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/definition-construction-algorithm-type-name-lowercased.html42
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/element-registration-algorithm-no-registry.html40
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/extensions-to-document-interface/custom-element-name.html37
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/extensions-to-document-interface/custom-element-prototype.html28
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-custom-tag-ref.html16
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-custom-tag.html23
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-registered-custom-tag-ref.html16
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-registered-custom-tag.html26
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-registered-type-extension-ref.html16
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-registered-type-extension.html33
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-type-extension-ref.html17
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-type-extension.html23
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-matching-query-selector-all.html191
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-matching-query-selector.html162
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/unresolved-elements-interface-html-element.html57
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/unresolved-elements-interface-html-unknown-element.html54
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/unresolved-elements-interface-svg-element.html48
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/resources/blank.html9
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/resources/import-master-async.html10
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/resources/import-master.html10
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/resources/import.html9
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/resources/register-and-create-custom-element.html19
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/resources/x-element.html10
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/resources/x-mathml-element.html12
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/resources/x-svg-element.html12
-rw-r--r--tests/wpt/web-platform-tests/custom-elements/testcommon.js286
-rw-r--r--tests/wpt/web-platform-tests/docs/configuration.md78
-rw-r--r--tests/wpt/web-platform-tests/docs/css-metadata.md391
-rw-r--r--tests/wpt/web-platform-tests/docs/css-naming.md65
-rw-r--r--tests/wpt/web-platform-tests/docs/css-user-styles.md85
-rw-r--r--tests/wpt/web-platform-tests/docs/github-101.md361
-rw-r--r--tests/wpt/web-platform-tests/docs/manual-test.md72
-rw-r--r--tests/wpt/web-platform-tests/docs/reftests.md152
-rw-r--r--tests/wpt/web-platform-tests/docs/review-checklist.md122
-rw-r--r--tests/wpt/web-platform-tests/docs/review-process.md56
-rw-r--r--tests/wpt/web-platform-tests/docs/running_tests.md34
-rw-r--r--tests/wpt/web-platform-tests/docs/submission-process.md42
-rw-r--r--tests/wpt/web-platform-tests/docs/test-format-guidelines.md324
-rw-r--r--tests/wpt/web-platform-tests/docs/test-style-guidelines.md438
-rw-r--r--tests/wpt/web-platform-tests/docs/test-templates.md136
-rw-r--r--tests/wpt/web-platform-tests/dom/collections/HTMLCollection-empty-name.html65
-rw-r--r--tests/wpt/web-platform-tests/dom/common.js968
-rw-r--r--tests/wpt/web-platform-tests/dom/constants.js11
-rw-r--r--tests/wpt/web-platform-tests/dom/events/Event-constants.html23
-rw-r--r--tests/wpt/web-platform-tests/dom/events/Event-constructors.html124
-rw-r--r--tests/wpt/web-platform-tests/dom/events/Event-defaultPrevented.html42
-rw-r--r--tests/wpt/web-platform-tests/dom/events/Event-dispatch-bubbles-false.html68
-rw-r--r--tests/wpt/web-platform-tests/dom/events/Event-dispatch-handlers-changed.html92
-rw-r--r--tests/wpt/web-platform-tests/dom/events/Event-dispatch-omitted-capture.html70
-rw-r--r--tests/wpt/web-platform-tests/dom/events/Event-dispatch-redispatch.html28
-rw-r--r--tests/wpt/web-platform-tests/dom/events/Event-dispatch-reenter.html66
-rw-r--r--tests/wpt/web-platform-tests/dom/events/Event-dispatch-target-moved.html73
-rw-r--r--tests/wpt/web-platform-tests/dom/events/Event-dispatch-target-removed.html72
-rw-r--r--tests/wpt/web-platform-tests/dom/events/Event-initEvent.html121
-rw-r--r--tests/wpt/web-platform-tests/dom/events/Event-propagation.html38
-rw-r--r--tests/wpt/web-platform-tests/dom/events/Event-type-empty.html35
-rw-r--r--tests/wpt/web-platform-tests/dom/events/Event-type.html22
-rw-r--r--tests/wpt/web-platform-tests/dom/events/EventTarget-addEventListener.html16
-rw-r--r--tests/wpt/web-platform-tests/dom/events/EventTarget-dispatchEvent-returnvalue.html43
-rw-r--r--tests/wpt/web-platform-tests/dom/events/EventTarget-dispatchEvent.html104
-rw-r--r--tests/wpt/web-platform-tests/dom/events/EventTarget-removeEventListener.html16
-rw-r--r--tests/wpt/web-platform-tests/dom/events/ProgressEvent.html25
-rw-r--r--tests/wpt/web-platform-tests/dom/historical.html133
-rw-r--r--tests/wpt/web-platform-tests/dom/interface-objects.html46
-rw-r--r--tests/wpt/web-platform-tests/dom/interfaces.html504
-rw-r--r--tests/wpt/web-platform-tests/dom/lists/DOMTokenList-stringifier.html23
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/CharacterData-appendData.html21
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/CharacterData-deleteData.html28
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/CharacterData-insertData.html28
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/CharacterData-remove.html24
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/CharacterData-replaceData.html30
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/ChildNode-remove.js30
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Comment-Text-constructor.js77
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Comment-constructor.html11
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/DOMImplementation-createDocument.html116
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/DOMImplementation-createDocumentType.html123
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/DOMImplementation-createHTMLDocument.html84
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/DOMImplementation-createHTMLDocument.js25
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/DOMImplementation-hasFeature.html141
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-Element-getElementsByTagName.js166
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-Element-getElementsByTagNameNS.js128
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-URL.sub.html18
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-adoptNode.html50
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-characterSet-normalization.html381
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-constructor.html47
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_bmp.html15
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_css.html15
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_datauri_01.html15
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_datauri_02.html15
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_gif.html15
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_html.html15
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_javascripturi.html16
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_jpg.html15
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_mimeheader_01.html15
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_mimeheader_02.html15
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_png.html15
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_txt.html15
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_xml.html15
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/createDocument.html11
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/createHTMLDocument.html11
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/xhr_responseType_document.html18
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-contentType/resources/blob.htm1
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-contentType/resources/blob.txt1
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-contentType/resources/blob.xml2
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-contentType/resources/lib.js1
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-contentType/resources/style.css12
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-contentType/resources/t.bmpbin0 -> 30054 bytes
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-contentType/resources/t.gifbin0 -> 148 bytes
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-contentType/resources/t.jpgbin0 -> 361 bytes
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-contentType/resources/t.pngbin0 -> 228 bytes
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-contentType/support/contenttype_setter.py20
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-createAttribute.html26
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-createComment-createTextNode.js22
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-createComment.html21
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/bare_mathml.html1
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/bare_mathml.svg1
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/bare_mathml.xhtml1
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/bare_mathml.xml1
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/bare_svg.html1
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/bare_svg.svg1
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/bare_svg.xhtml1
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/bare_svg.xml1
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/bare_xhtml.html1
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/bare_xhtml.svg1
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/bare_xhtml.xhtml1
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/bare_xhtml.xml1
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/empty.html0
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/empty.svg0
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/empty.xhtml0
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/empty.xml0
-rwxr-xr-xtests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/generate.py77
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/mathml.html1
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/mathml.svg1
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/mathml.xhtml1
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/mathml.xml1
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/minimal_html.html1
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/minimal_html.svg1
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/minimal_html.xhtml1
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/minimal_html.xml1
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/svg.html1
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/svg.svg1
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/svg.xhtml1
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/svg.xml1
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/xhtml.html1
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/xhtml.svg1
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/xhtml.xhtml1
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/xhtml.xml1
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_changed.html7
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_changed.svg7
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_changed.xhtml7
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_changed.xml7
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_removed.html7
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_removed.svg7
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_removed.xhtml7
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_removed.xml7
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace.html103
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-createElement.html85
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-createElementNS.html199
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-createElementNS.js162
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-createEvent.html55
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-createEvent.js14
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-createProcessingInstruction.html11
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-createProcessingInstruction.js39
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-createProcessingInstruction.xhtml15
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-createTextNode.html21
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-createTreeWalker.html42
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-doctype.html21
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-getElementById.html312
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-getElementsByTagName.html11
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-getElementsByTagName.xhtml102
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-getElementsByTagNameNS.html11
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-implementation.html20
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Document-importNode.html57
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/DocumentType-literal.html17
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/DocumentType-literal.xhtml23
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/DocumentType-remove.html16
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Element-childElement-null.html15
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Element-childElement-null.svg20
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Element-childElement-null.xhtml20
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Element-childElementCount-dynamic-add.html17
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Element-childElementCount-dynamic-add.svg22
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Element-childElementCount-dynamic-add.xhtml22
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Element-childElementCount-dynamic-remove.html17
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Element-childElementCount-dynamic-remove.svg22
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Element-childElementCount-dynamic-remove.xhtml22
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Element-childElementCount-nochild.html14
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Element-childElementCount-nochild.svg19
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Element-childElementCount-nochild.xhtml19
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Element-childElementCount.html20
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Element-childElementCount.svg25
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Element-childElementCount.xhtml25
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Element-children.html27
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Element-classlist.html309
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Element-closest.html73
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Element-firstElementChild-entity.svg26
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Element-firstElementChild-entity.xhtml27
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Element-firstElementChild-namespace.html21
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Element-firstElementChild-namespace.svg26
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Element-firstElementChild-namespace.xhtml28
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Element-firstElementChild.html18
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Element-firstElementChild.svg23
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Element-firstElementChild.xhtml23
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Element-getElementsByClassName.html21
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Element-getElementsByTagName.html30
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Element-getElementsByTagNameNS.html37
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Element-lastElementChild.html17
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Element-lastElementChild.svg22
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Element-lastElementChild.xhtml22
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Element-matches.html87
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Element-matches.js127
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Element-nextElementSibling.html18
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Element-nextElementSibling.svg23
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Element-nextElementSibling.xhtml23
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Element-previousElementSibling.html23
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Element-previousElementSibling.svg28
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Element-previousElementSibling.xhtml28
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Element-remove.html16
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Element-removeAttributeNS.html18
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Element-siblingElement-null.html16
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Element-siblingElement-null.svg20
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Element-siblingElement-null.xhtml20
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Element-tagName.html50
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/MutationObserver-attributes.html406
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/MutationObserver-characterData.html215
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/MutationObserver-childList.html423
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/MutationObserver-disconnect.html48
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/MutationObserver-document.html167
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/MutationObserver-inner-outer.html65
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/MutationObserver-takeRecords.html53
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Node-appendChild.html59
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Node-childNodes.html48
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Node-cloneNode.html51
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Node-compareDocumentPosition.html87
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Node-constants.html39
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Node-contains.html36
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Node-contains.xml83
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Node-insertBefore.html306
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Node-isEqualNode.xhtml60
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Node-lookupPrefix.xhtml31
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Node-nodeName.html32
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Node-nodeName.xhtml42
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Node-nodeValue.html71
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Node-normalize.html54
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Node-parentElement.html83
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Node-parentNode-iframe.html1
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Node-parentNode.html33
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Node-properties.html689
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Node-removeChild.html54
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Node-replaceChild.html321
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Node-textContent.html265
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/ParentNode-querySelector-All-content.html377
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/ParentNode-querySelector-All-content.xht372
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/ParentNode-querySelector-All.html110
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/ParentNode-querySelector-All.js255
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/ParentNode-querySelector-All.xht114
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/ProcessingInstruction-literal-1.xhtml16
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/ProcessingInstruction-literal-2.xhtml21
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/Text-constructor.html11
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/attributes.html388
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/attributes.js17
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/case.html18
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/case.js179
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/creators.js5
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/encoding.py5
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-01.htm13
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-02.htm14
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-03.htm18
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-04.htm18
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-05.htm18
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-06.htm20
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-07.htm15
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-08.htm15
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-09.htm15
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-10.xml17
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-11.xml22
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-12.htm15
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-13.htm19
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-14.htm16
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-15.htm18
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-16.htm16
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-17.htm15
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-18.htm17
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-19.htm54
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-20.htm61
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-21.htm52
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-22.htm58
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-23.htm52
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-24.htm30
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-25.htm57
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-26.htm30
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-27.htm32
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-28.htm31
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-29.htm51
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-30.htm190
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-31.htm22
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/getElementsByClassNameFrame.htm6
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/mutationobservers.js76
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/productions.js3
-rw-r--r--tests/wpt/web-platform-tests/dom/nodes/selectors.js721
-rw-r--r--tests/wpt/web-platform-tests/dom/ranges/Range-attributes.html23
-rw-r--r--tests/wpt/web-platform-tests/dom/ranges/Range-cloneContents.html454
-rw-r--r--tests/wpt/web-platform-tests/dom/ranges/Range-cloneRange.html112
-rw-r--r--tests/wpt/web-platform-tests/dom/ranges/Range-collapse.html75
-rw-r--r--tests/wpt/web-platform-tests/dom/ranges/Range-commonAncestorContainer-2.html33
-rw-r--r--tests/wpt/web-platform-tests/dom/ranges/Range-commonAncestorContainer.html40
-rw-r--r--tests/wpt/web-platform-tests/dom/ranges/Range-compareBoundaryPoints.html182
-rw-r--r--tests/wpt/web-platform-tests/dom/ranges/Range-comparePoint-2.html23
-rw-r--r--tests/wpt/web-platform-tests/dom/ranges/Range-comparePoint.html92
-rw-r--r--tests/wpt/web-platform-tests/dom/ranges/Range-deleteContents.html331
-rw-r--r--tests/wpt/web-platform-tests/dom/ranges/Range-detach.html14
-rw-r--r--tests/wpt/web-platform-tests/dom/ranges/Range-extractContents.html248
-rw-r--r--tests/wpt/web-platform-tests/dom/ranges/Range-insertNode.html286
-rw-r--r--tests/wpt/web-platform-tests/dom/ranges/Range-intersectsNode-binding.html25
-rw-r--r--tests/wpt/web-platform-tests/dom/ranges/Range-intersectsNode.html78
-rw-r--r--tests/wpt/web-platform-tests/dom/ranges/Range-isPointInRange.html83
-rw-r--r--tests/wpt/web-platform-tests/dom/ranges/Range-mutations.html959
-rw-r--r--tests/wpt/web-platform-tests/dom/ranges/Range-selectNode.html99
-rw-r--r--tests/wpt/web-platform-tests/dom/ranges/Range-set.html221
-rw-r--r--tests/wpt/web-platform-tests/dom/ranges/Range-surroundContents.html354
-rw-r--r--tests/wpt/web-platform-tests/dom/ranges/Range-test-iframe.html56
-rw-r--r--tests/wpt/web-platform-tests/dom/traversal/NodeFilter-constants.html34
-rw-r--r--tests/wpt/web-platform-tests/dom/traversal/NodeIterator-removal.html100
-rw-r--r--tests/wpt/web-platform-tests/dom/traversal/NodeIterator.html177
-rw-r--r--tests/wpt/web-platform-tests/dom/traversal/TreeWalker-acceptNode-filter.html160
-rw-r--r--tests/wpt/web-platform-tests/dom/traversal/TreeWalker-basic.html146
-rw-r--r--tests/wpt/web-platform-tests/dom/traversal/TreeWalker-currentNode.html74
-rw-r--r--tests/wpt/web-platform-tests/dom/traversal/TreeWalker-previousNodeLastChildReject.html88
-rw-r--r--tests/wpt/web-platform-tests/dom/traversal/TreeWalker-previousSiblingLastChildSkip.html92
-rw-r--r--tests/wpt/web-platform-tests/dom/traversal/TreeWalker-traversal-reject.html110
-rw-r--r--tests/wpt/web-platform-tests/dom/traversal/TreeWalker-traversal-skip-most.html67
-rw-r--r--tests/wpt/web-platform-tests/dom/traversal/TreeWalker-traversal-skip.html112
-rw-r--r--tests/wpt/web-platform-tests/dom/traversal/TreeWalker-walking-outside-a-tree.html41
-rw-r--r--tests/wpt/web-platform-tests/dom/traversal/traversal-support.js28
-rw-r--r--tests/wpt/web-platform-tests/dom/traversal/unfinished/001.xml53
-rw-r--r--tests/wpt/web-platform-tests/dom/traversal/unfinished/002.xml54
-rw-r--r--tests/wpt/web-platform-tests/dom/traversal/unfinished/003.xml58
-rw-r--r--tests/wpt/web-platform-tests/dom/traversal/unfinished/004.xml49
-rw-r--r--tests/wpt/web-platform-tests/dom/traversal/unfinished/005.xml57
-rw-r--r--tests/wpt/web-platform-tests/dom/traversal/unfinished/006.xml47
-rw-r--r--tests/wpt/web-platform-tests/dom/traversal/unfinished/007.xml54
-rw-r--r--tests/wpt/web-platform-tests/dom/traversal/unfinished/008.xml48
-rw-r--r--tests/wpt/web-platform-tests/dom/traversal/unfinished/009.xml55
-rw-r--r--tests/wpt/web-platform-tests/dom/traversal/unfinished/010.xml64
-rw-r--r--tests/wpt/web-platform-tests/dom/traversal/unfinished/TODO1
-rw-r--r--tests/wpt/web-platform-tests/domparsing/DOMParser-parseFromString-html.html39
-rw-r--r--tests/wpt/web-platform-tests/domparsing/insert-adjacent.html38
-rw-r--r--tests/wpt/web-platform-tests/domxpath/001.html60
-rw-r--r--tests/wpt/web-platform-tests/domxpath/002.html60
-rw-r--r--tests/wpt/web-platform-tests/domxpath/evaluator-constructor.html17
-rw-r--r--tests/wpt/web-platform-tests/encoding/api-basics.html56
-rw-r--r--tests/wpt/web-platform-tests/encoding/api-replacement-encodings.html26
-rw-r--r--tests/wpt/web-platform-tests/encoding/api-surrogates-utf8.html54
-rw-r--r--tests/wpt/web-platform-tests/encoding/gb18030-encoder.html21
-rw-r--r--tests/wpt/web-platform-tests/encoding/gbk-encoder.html21
-rw-r--r--tests/wpt/web-platform-tests/encoding/idlharness.html66
-rw-r--r--tests/wpt/web-platform-tests/encoding/iso-2022-jp-decoder.html57
-rw-r--r--tests/wpt/web-platform-tests/encoding/iso-2022-jp-encoder.html18
-rw-r--r--tests/wpt/web-platform-tests/encoding/resources/encodings.js489
-rw-r--r--tests/wpt/web-platform-tests/encoding/resources/single-byte-raw.py3
-rw-r--r--tests/wpt/web-platform-tests/encoding/single-byte-decoder.html99
-rw-r--r--tests/wpt/web-platform-tests/encoding/textdecoder-byte-order-marks.html48
-rw-r--r--tests/wpt/web-platform-tests/encoding/textdecoder-fatal-streaming.html50
-rw-r--r--tests/wpt/web-platform-tests/encoding/textdecoder-fatal.html73
-rw-r--r--tests/wpt/web-platform-tests/encoding/textdecoder-ignorebom.html45
-rw-r--r--tests/wpt/web-platform-tests/encoding/textdecoder-labels.html25
-rw-r--r--tests/wpt/web-platform-tests/encoding/textdecoder-streaming.html29
-rw-r--r--tests/wpt/web-platform-tests/encoding/textdecoder-utf16-surrogates.html52
-rw-r--r--tests/wpt/web-platform-tests/encoding/textencoder-constructor-non-utf.html26
-rw-r--r--tests/wpt/web-platform-tests/encoding/textencoder-utf16-surrogates.html55
-rw-r--r--tests/wpt/web-platform-tests/eventsource/README.md54
-rw-r--r--tests/wpt/web-platform-tests/eventsource/dedicated-worker/eventsource-close.htm36
-rw-r--r--tests/wpt/web-platform-tests/eventsource/dedicated-worker/eventsource-constructor-non-same-origin.htm49
-rw-r--r--tests/wpt/web-platform-tests/eventsource/dedicated-worker/eventsource-constructor-url-bogus.htm34
-rw-r--r--tests/wpt/web-platform-tests/eventsource/dedicated-worker/eventsource-eventtarget.htm37
-rw-r--r--tests/wpt/web-platform-tests/eventsource/dedicated-worker/eventsource-onmesage.htm36
-rw-r--r--tests/wpt/web-platform-tests/eventsource/dedicated-worker/eventsource-onopen.htm39
-rw-r--r--tests/wpt/web-platform-tests/eventsource/dedicated-worker/eventsource-prototype.htm36
-rw-r--r--tests/wpt/web-platform-tests/eventsource/dedicated-worker/eventsource-url.htm35
-rw-r--r--tests/wpt/web-platform-tests/eventsource/event-data.html44
-rw-r--r--tests/wpt/web-platform-tests/eventsource/eventsource-close.htm82
-rw-r--r--tests/wpt/web-platform-tests/eventsource/eventsource-constructor-document-domain.htm29
-rw-r--r--tests/wpt/web-platform-tests/eventsource/eventsource-constructor-non-same-origin.htm35
-rw-r--r--tests/wpt/web-platform-tests/eventsource/eventsource-constructor-stringify.htm39
-rw-r--r--tests/wpt/web-platform-tests/eventsource/eventsource-constructor-url-bogus.htm16
-rw-r--r--tests/wpt/web-platform-tests/eventsource/eventsource-constructor-url-multi-window.htm37
-rw-r--r--tests/wpt/web-platform-tests/eventsource/eventsource-cross-origin.htm64
-rw-r--r--tests/wpt/web-platform-tests/eventsource/eventsource-eventtarget.htm26
-rw-r--r--tests/wpt/web-platform-tests/eventsource/eventsource-onmessage.htm25
-rw-r--r--tests/wpt/web-platform-tests/eventsource/eventsource-onopen.htm28
-rw-r--r--tests/wpt/web-platform-tests/eventsource/eventsource-prototype.htm21
-rw-r--r--tests/wpt/web-platform-tests/eventsource/eventsource-reconnect.htm58
-rw-r--r--tests/wpt/web-platform-tests/eventsource/eventsource-request-cancellation.htm45
-rw-r--r--tests/wpt/web-platform-tests/eventsource/eventsource-url.htm20
-rw-r--r--tests/wpt/web-platform-tests/eventsource/format-bom-2.htm35
-rw-r--r--tests/wpt/web-platform-tests/eventsource/format-bom.htm35
-rw-r--r--tests/wpt/web-platform-tests/eventsource/format-comments.htm27
-rw-r--r--tests/wpt/web-platform-tests/eventsource/format-data-before-final-empty-line.htm29
-rw-r--r--tests/wpt/web-platform-tests/eventsource/format-field-data.htm34
-rw-r--r--tests/wpt/web-platform-tests/eventsource/format-field-event-empty.htm25
-rw-r--r--tests/wpt/web-platform-tests/eventsource/format-field-event.htm27
-rw-r--r--tests/wpt/web-platform-tests/eventsource/format-field-id-2.htm38
-rw-r--r--tests/wpt/web-platform-tests/eventsource/format-field-id.htm34
-rw-r--r--tests/wpt/web-platform-tests/eventsource/format-field-parsing.htm26
-rw-r--r--tests/wpt/web-platform-tests/eventsource/format-field-retry-bogus.htm31
-rw-r--r--tests/wpt/web-platform-tests/eventsource/format-field-retry-empty.htm25
-rw-r--r--tests/wpt/web-platform-tests/eventsource/format-field-retry.htm33
-rw-r--r--tests/wpt/web-platform-tests/eventsource/format-field-unknown.htm25
-rw-r--r--tests/wpt/web-platform-tests/eventsource/format-leading-space.htm26
-rw-r--r--tests/wpt/web-platform-tests/eventsource/format-mime-bogus.htm37
-rw-r--r--tests/wpt/web-platform-tests/eventsource/format-mime-trailing-semicolon.htm32
-rw-r--r--tests/wpt/web-platform-tests/eventsource/format-mime-valid-bogus.htm36
-rw-r--r--tests/wpt/web-platform-tests/eventsource/format-newlines.htm25
-rw-r--r--tests/wpt/web-platform-tests/eventsource/format-null-character.html30
-rw-r--r--tests/wpt/web-platform-tests/eventsource/format-utf-8.htm26
-rw-r--r--tests/wpt/web-platform-tests/eventsource/interfaces.html58
-rw-r--r--tests/wpt/web-platform-tests/eventsource/request-accept.htm25
-rw-r--r--tests/wpt/web-platform-tests/eventsource/request-cache-control.htm37
-rw-r--r--tests/wpt/web-platform-tests/eventsource/request-credentials.htm49
-rw-r--r--tests/wpt/web-platform-tests/eventsource/request-redirect.htm36
-rw-r--r--tests/wpt/web-platform-tests/eventsource/request-status-error.htm39
-rw-r--r--tests/wpt/web-platform-tests/eventsource/resources/accept.event_stream2
-rw-r--r--tests/wpt/web-platform-tests/eventsource/resources/cache-control.event_stream2
-rw-r--r--tests/wpt/web-platform-tests/eventsource/resources/cors-cookie.py31
-rw-r--r--tests/wpt/web-platform-tests/eventsource/resources/cors.py34
-rw-r--r--tests/wpt/web-platform-tests/eventsource/resources/init.htm9
-rw-r--r--tests/wpt/web-platform-tests/eventsource/resources/last-event-id.py11
-rw-r--r--tests/wpt/web-platform-tests/eventsource/resources/message.py14
-rw-r--r--tests/wpt/web-platform-tests/eventsource/resources/message2.py35
-rw-r--r--tests/wpt/web-platform-tests/eventsource/resources/reconnect-fail.py24
-rw-r--r--tests/wpt/web-platform-tests/eventsource/resources/status-error.py4
-rw-r--r--tests/wpt/web-platform-tests/eventsource/resources/status-reconnect.py21
-rw-r--r--tests/wpt/web-platform-tests/eventsource/shared-worker/eventsource-close.htm39
-rw-r--r--tests/wpt/web-platform-tests/eventsource/shared-worker/eventsource-constructor-non-same-origin.htm52
-rw-r--r--tests/wpt/web-platform-tests/eventsource/shared-worker/eventsource-constructor-url-bogus.htm37
-rw-r--r--tests/wpt/web-platform-tests/eventsource/shared-worker/eventsource-eventtarget.htm40
-rw-r--r--tests/wpt/web-platform-tests/eventsource/shared-worker/eventsource-onmesage.htm39
-rw-r--r--tests/wpt/web-platform-tests/eventsource/shared-worker/eventsource-onopen.htm42
-rw-r--r--tests/wpt/web-platform-tests/eventsource/shared-worker/eventsource-prototype.htm39
-rw-r--r--tests/wpt/web-platform-tests/eventsource/shared-worker/eventsource-url.htm38
-rw-r--r--tests/wpt/web-platform-tests/ext-xhtml-pubid/the-xhtml-syntax/parsing-xhtml-documents/xhtml-local.dtd3
-rw-r--r--tests/wpt/web-platform-tests/ext-xhtml-pubid/the-xhtml-syntax/parsing-xhtml-documents/xhtml-pubid-1.html83
-rw-r--r--tests/wpt/web-platform-tests/ext-xhtml-pubid/the-xhtml-syntax/parsing-xhtml-documents/xhtml-pubid-1.xhtml16
-rw-r--r--tests/wpt/web-platform-tests/ext-xhtml-pubid/the-xhtml-syntax/parsing-xhtml-documents/xhtml-pubid-2.xhtml15
-rw-r--r--tests/wpt/web-platform-tests/ext-xhtml-pubid/the-xhtml-syntax/parsing-xhtml-documents/xhtml-pubid-3.xhtml16
-rw-r--r--tests/wpt/web-platform-tests/fonts/CanvasTest.sfd321
-rw-r--r--tests/wpt/web-platform-tests/fonts/CanvasTest.ttfbin0 -> 2528 bytes
-rw-r--r--tests/wpt/web-platform-tests/gamepad/events-manual.html34
-rw-r--r--tests/wpt/web-platform-tests/gamepad/getgamepads-polling-manual.html30
-rw-r--r--tests/wpt/web-platform-tests/gamepad/idlharness-manual.html78
-rw-r--r--tests/wpt/web-platform-tests/gamepad/idlharness.html70
-rw-r--r--tests/wpt/web-platform-tests/gamepad/timestamp-manual.html58
-rw-r--r--tests/wpt/web-platform-tests/geolocation-API/PositionOptions.html113
-rw-r--r--tests/wpt/web-platform-tests/geolocation-API/clearWatch_TypeError.html23
-rw-r--r--tests/wpt/web-platform-tests/geolocation-API/getCurrentPosition_IDL.html152
-rw-r--r--tests/wpt/web-platform-tests/geolocation-API/getCurrentPosition_TypeError.html55
-rw-r--r--tests/wpt/web-platform-tests/geolocation-API/getCurrentPosition_permission-manual.html21
-rw-r--r--tests/wpt/web-platform-tests/geolocation-API/getCurrentPosition_permission_allow-manual.html32
-rw-r--r--tests/wpt/web-platform-tests/geolocation-API/getCurrentPosition_permission_allow.html44
-rw-r--r--tests/wpt/web-platform-tests/geolocation-API/getCurrentPosition_permission_deny-manual.html34
-rw-r--r--tests/wpt/web-platform-tests/geolocation-API/getCurrentPosition_permission_deny.html34
-rw-r--r--tests/wpt/web-platform-tests/geolocation-API/interfaces.html95
-rw-r--r--tests/wpt/web-platform-tests/geolocation-API/support.js30
-rw-r--r--tests/wpt/web-platform-tests/geolocation-API/watchPosition_TypeError.html55
-rw-r--r--tests/wpt/web-platform-tests/geolocation-API/watchPosition_permission-manual.html21
-rw-r--r--tests/wpt/web-platform-tests/geolocation-API/watchPosition_permission_deny.html36
-rw-r--r--tests/wpt/web-platform-tests/hr-time/basic.html36
-rw-r--r--tests/wpt/web-platform-tests/hr-time/idlharness.html53
-rw-r--r--tests/wpt/web-platform-tests/hr-time/monotonic-clock.html36
-rw-r--r--tests/wpt/web-platform-tests/hr-time/resources/now_frame.html9
-rw-r--r--tests/wpt/web-platform-tests/hr-time/test_cross_frame_start.html56
-rw-r--r--tests/wpt/web-platform-tests/html-imports/document/document-method-changes.html23
-rw-r--r--tests/wpt/web-platform-tests/html-imports/document/resources/body-only.html4
-rw-r--r--tests/wpt/web-platform-tests/html-imports/document/resources/test-in-import.html13
-rw-r--r--tests/wpt/web-platform-tests/html-imports/fetching/already-in-import-map.html28
-rw-r--r--tests/wpt/web-platform-tests/html-imports/fetching/loading-attempt.html77
-rw-r--r--tests/wpt/web-platform-tests/html-imports/fetching/resources/async.html2
-rw-r--r--tests/wpt/web-platform-tests/html-imports/fetching/resources/dynamic.html2
-rw-r--r--tests/wpt/web-platform-tests/html-imports/fetching/resources/hello.html2
-rw-r--r--tests/wpt/web-platform-tests/html-imports/fetching/resources/parent-of-hello.html2
-rw-r--r--tests/wpt/web-platform-tests/html-imports/html-link-element/import-attribute.html44
-rw-r--r--tests/wpt/web-platform-tests/html-imports/html-link-element/resources/body-only-0.html4
-rw-r--r--tests/wpt/web-platform-tests/html-imports/html-link-element/resources/body-only-1.html4
-rw-r--r--tests/wpt/web-platform-tests/html-imports/html-link-element/resources/body-only-2.html4
-rw-r--r--tests/wpt/web-platform-tests/html-imports/html-link-element/resources/hello.css3
-rw-r--r--tests/wpt/web-platform-tests/html-longdesc/README.html109
-rw-r--r--tests/wpt/web-platform-tests/html-longdesc/data-uri-image-data-uri-description-manual.html9
-rw-r--r--tests/wpt/web-platform-tests/html-longdesc/data-uri-image-external-description-fragment-manual.html9
-rw-r--r--tests/wpt/web-platform-tests/html-longdesc/data-uri-image-external-description-manual.html9
-rw-r--r--tests/wpt/web-platform-tests/html-longdesc/data-uri-image-internal-description-manual.html14
-rw-r--r--tests/wpt/web-platform-tests/html-longdesc/empty-image-data-uri-description-manual.html9
-rw-r--r--tests/wpt/web-platform-tests/html-longdesc/empty-image-external-description-fragment-manual.html9
-rw-r--r--tests/wpt/web-platform-tests/html-longdesc/empty-image-external-description-manual.html9
-rw-r--r--tests/wpt/web-platform-tests/html-longdesc/empty-image-internal-description-manual.html14
-rw-r--r--tests/wpt/web-platform-tests/html-longdesc/empty-longdesc-manual.html11
-rw-r--r--tests/wpt/web-platform-tests/html-longdesc/external-image-data-uri-description-girt-by-spaces-manual.html9
-rw-r--r--tests/wpt/web-platform-tests/html-longdesc/external-image-data-uri-description-manual.html9
-rw-r--r--tests/wpt/web-platform-tests/html-longdesc/external-image-external-description-fragment-girt-by-spaces-manual.html9
-rw-r--r--tests/wpt/web-platform-tests/html-longdesc/external-image-external-description-fragment-manual.html9
-rw-r--r--tests/wpt/web-platform-tests/html-longdesc/external-image-external-description-girt-by-spaces-manual.html9
-rw-r--r--tests/wpt/web-platform-tests/html-longdesc/external-image-external-description-manual.html9
-rw-r--r--tests/wpt/web-platform-tests/html-longdesc/external-image-internal-description-girt-by-spaces-manual.html14
-rw-r--r--tests/wpt/web-platform-tests/html-longdesc/external-image-internal-description-manual.html14
-rw-r--r--tests/wpt/web-platform-tests/html-longdesc/external-image-with-absolute-base-external-description-manual.html12
-rw-r--r--tests/wpt/web-platform-tests/html-longdesc/external-image-with-relative-base-external-description-manual.html11
-rw-r--r--tests/wpt/web-platform-tests/html-longdesc/fail-fragment-pointer-manual.html9
-rw-r--r--tests/wpt/web-platform-tests/html-longdesc/fail-fragment.html20
-rw-r--r--tests/wpt/web-platform-tests/html-longdesc/fail.html10
-rw-r--r--tests/wpt/web-platform-tests/html-longdesc/iframe-discoverability-manual.html12
-rw-r--r--tests/wpt/web-platform-tests/html-longdesc/invalid-longdesc-manual.html9
-rw-r--r--tests/wpt/web-platform-tests/html-longdesc/pass-fragment.html20
-rw-r--r--tests/wpt/web-platform-tests/html-longdesc/pass.html12
-rw-r--r--tests/wpt/web-platform-tests/html-longdesc/picture.pngbin0 -> 4435 bytes
-rw-r--r--tests/wpt/web-platform-tests/html-longdesc/rebased/fail.html12
-rw-r--r--tests/wpt/web-platform-tests/html-longdesc/rebased/picture2.pngbin0 -> 6416 bytes
-rw-r--r--tests/wpt/web-platform-tests/html-longdesc/reflected-changing-longdesc-manual.html16
-rw-r--r--tests/wpt/web-platform-tests/html-media-capture/capture_audio-manual.html37
-rw-r--r--tests/wpt/web-platform-tests/html-media-capture/capture_audio_cancel-manual.html24
-rw-r--r--tests/wpt/web-platform-tests/html-media-capture/capture_fallback_file_upload.html44
-rw-r--r--tests/wpt/web-platform-tests/html-media-capture/capture_image-manual.html37
-rw-r--r--tests/wpt/web-platform-tests/html-media-capture/capture_image_cancel-manual.html24
-rw-r--r--tests/wpt/web-platform-tests/html-media-capture/capture_reflect.html57
-rw-r--r--tests/wpt/web-platform-tests/html-media-capture/capture_video-manual.html37
-rw-r--r--tests/wpt/web-platform-tests/html-media-capture/capture_video_cancel-manual.html24
-rw-r--r--tests/wpt/web-platform-tests/html-media-capture/idlharness.html50
-rw-r--r--tests/wpt/web-platform-tests/html-media-capture/support/upload.txt1
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/browsing-the-web/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/browsing-the-web/aborting-a-document-load/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/browsing-the-web/history-traversal/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/browsing-the-web/history-traversal/PopStateEvent.html31
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/browsing-the-web/history-traversal/contains.json6
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/browsing-the-web/navigating-across-documents/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/browsing-the-web/read-html/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/browsing-the-web/read-media/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/browsing-the-web/read-media/pageload-image.html30
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/browsing-the-web/read-media/pageload-video.html30
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/browsing-the-web/read-multipart-x-mixed-replace/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/browsing-the-web/read-plugin/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/browsing-the-web/read-text/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/browsing-the-web/read-text/load-text-plain.html41
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/browsing-the-web/read-ua-inline/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/browsing-the-web/read-xml/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/browsing-the-web/scroll-to-fragid/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/001-1.html23
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/001.html15
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/001a.html7
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/001b.html5
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/002-1.html28
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/002.html15
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/002a.html7
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/002b.html5
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/003-1.html23
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/003.html15
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/003a.html8
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/003b.html5
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/004-1.html25
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/004.html15
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/004a.html8
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/004b.html18
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/005-1.html13
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/005.html15
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/005a.html8
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/005b.html17
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/contains.json6
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/history-notes/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/001.html333
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/002.html308
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/004.html62
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/005.html47
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/006.html53
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/007.html56
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/008.html40
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/009-1.html20
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/009-3.html28
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/009-5.html23
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/009.html22
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/010-1.html16
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/010-3.html24
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/010-5.html23
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/010.html22
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/011.html32
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/012.html32
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/blank.html8
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/blank2.html13
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/blank3.html11
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/combination_history_001.html20
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/combination_history_002.html22
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/combination_history_003.html26
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/combination_history_004.html29
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/combination_history_005.html34
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/combination_history_006.html30
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/combination_history_007.html32
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/history_back.html27
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/history_forward.html32
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/history_go_minus.html27
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/history_go_plus.html33
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/history_pushstate.html19
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/history_pushstate_err.html18
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/history_pushstate_nooptionalparam.html20
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/history_replacestate.html20
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/history_replacestate_err.html18
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/history_replacestate_nooptionalparam.html20
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/history_state.html24
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/the-location-interface/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/the-location-interface/contains.json6
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/the-location-interface/location-stringifier.html11
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/the-location-interface/location_assign.html20
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/the-location-interface/location_hash.html20
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/the-location-interface/location_host.html28
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/the-location-interface/location_hostname.html33
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/the-location-interface/location_href.html19
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/the-location-interface/location_pathname.html22
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/the-location-interface/location_port.html31
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/the-location-interface/location_protocol.html25
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/the-location-interface/location_replace.html20
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/the-location-interface/location_search.html20
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/the-location-interface/security_location_0.sub.htm23
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/history/the-session-history-of-browsing-contexts/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/offline/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/offline/appcache/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/offline/application-cache-api/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/offline/application-cache-api/api_status_checking-manual.html23
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/offline/application-cache-api/api_status_downloading-manual.html24
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/offline/application-cache-api/api_status_idle.html22
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/offline/application-cache-api/api_status_obsolete-manual.html24
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/offline/application-cache-api/api_status_uncached.html19
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/offline/application-cache-api/api_status_updateready-manual.html25
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/offline/application-cache-api/api_swapcache-manual.html30
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/offline/application-cache-api/api_swapcache_error.html19
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/offline/application-cache-api/api_update.html24
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/offline/application-cache-api/api_update_error.html24
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/offline/browser-state/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/offline/browser-state/navigator_online_event-manual.html40
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/offline/browser-state/navigator_online_online.html17
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/offline/changestonetworkingmodel/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/offline/changestonetworkingmodel/original-id.json1
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/offline/disk-space/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/offline/downloading-or-updating-an-application-cache/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/offline/expiring-application-caches/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/offline/introduction-4/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/offline/introduction-4/contains.json10
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/offline/introduction-4/event_cached.html18
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/offline/introduction-4/event_checking.html18
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/offline/introduction-4/event_downloading-manual.html23
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/offline/introduction-4/event_error-manual.html23
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/offline/introduction-4/event_noupdate.html19
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/offline/introduction-4/event_obsolete-manual.html23
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/offline/introduction-4/event_progress.html18
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/offline/introduction-4/event_updateready-manual.html22
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/offline/introduction-4/event_updateready_swapcache-manual.html30
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/offline/manifest_main_empty-manual.html14
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/offline/manifest_notchanged_online-manual.html19
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/offline/manifest_section_empty-manual.html19
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/offline/manifest_section_many-manual.html19
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/offline/manifest_url_check.html18
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/offline/manifests/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/offline/manifests/contains.json14
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/offline/resources/css/clock.css1
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/offline/resources/css/offline.css5
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/offline/resources/css/online.css5
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/offline/resources/css/result.css11
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/offline/resources/html/clock.html12
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/offline/resources/js/clock.js3
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/offline/resources/manifest/clock.manifest17
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/offline/resources/manifest/section_empty.manifest10
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/offline/resources/manifest/section_many.manifest19
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/offline/resources/manifest/url_check.manifest17
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/offline/section_network_offline-manual.html17
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/offline/section_network_online-manual.html16
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/offline/the-application-cache-selection-algorithm/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/origin/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/origin/cross-origin-objects/cross-origin-objects.html336
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/origin/cross-origin-objects/frame.html35
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/origin/cross-origin-objects/win-documentdomain.html55
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/origin/relaxing-the-same-origin-restriction/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/sandboxing/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/the-window-object/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/the-window-object/accessing-other-browsing-contexts/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/the-window-object/accessing-other-browsing-contexts/indexed-browsing-contexts-01.html47
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/the-window-object/accessing-other-browsing-contexts/indexed-browsing-contexts-02.html62
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/the-window-object/accessing-other-browsing-contexts/indexed-browsing-contexts-03.html30
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/the-window-object/accessing-other-browsing-contexts/test1.html12
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/the-window-object/accessing-other-browsing-contexts/test2.html6
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/the-window-object/accessing-other-browsing-contexts/test3.html8
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/creating_browsing_context_test_01.html38
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/the-window-object/browser-interface-elements/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/the-window-object/closing-browsing-contexts/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/the-window-object/named-access-on-the-window-object/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/the-window-object/named-access-on-the-window-object/named-objects.html80
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/the-window-object/named-access-on-the-window-object/test.html7
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/the-window-object/named-access-on-the-window-object/window-null-names.html20
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/the-window-object/security-window/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/the-window-object/security-window/window-security.sub.html194
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/the-window-object/the-windowproxy-object/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/the-window-object/the-windowproxy-object/test-window-proxy-locationbar-manual.html29
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/the-window-object/the-windowproxy-object/test-window-proxy-menubar-manual.html29
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/the-window-object/the-windowproxy-object/test-window-proxy-personalbar-manual.html29
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/the-window-object/the-windowproxy-object/test-window-proxy-scrollbars-manual.html29
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/the-window-object/the-windowproxy-object/test-window-proxy-statusbar-manual.html29
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/the-window-object/the-windowproxy-object/test-window-proxy-toolbar-manual.html29
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/the-window-object/window-aliases.html28
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/the-window-object/window-indexed-properties-strict.html43
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/the-window-object/window-indexed-properties.html35
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/the-window-object/window-named-properties.html70
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/the-window-object/window-properties.html322
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/the-window-object/window-prototype-chain.html35
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/windows/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/windows/auxiliary-browsing-contexts/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/windows/auxiliary-browsing-contexts/contains.json6
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/windows/browsing-context-first-created.xhtml54
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/windows/browsing-context-names/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/windows/browsing-context-names/browsing-context-choose-existing.html25
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/windows/browsing-context-names/browsing-context-choose-parent.html20
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/windows/browsing-context-names/browsing-context-choose-self-1.html20
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/windows/browsing-context-names/browsing-context-choose-self-2.html20
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/windows/browsing-context-names/browsing-context-default-name.html26
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/windows/browsing-context-names/existing.html11
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/windows/browsing-context-names/message.html9
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/windows/browsing-context-names/parent1.html5
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/windows/browsing-context-names/parent2.html9
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/windows/browsing-context-names/self1.html11
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/windows/browsing-context-names/self2.html11
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/windows/groupings-of-browsing-contexts/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/windows/nested-browsing-contexts/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/windows/nested-browsing-contexts/contains.json6
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/windows/nested-browsing-contexts/frameElement.sub.html56
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/windows/nested-browsing-contexts/test.html7
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/windows/secondary-browsing-contexts/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/windows/security-nav/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/dom/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/dom/documents/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/Document.currentScript.html45
-rw-r--r--tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/Document.getElementsByClassName-null-undef.html31
-rw-r--r--tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/Element.getElementsByClassName-null-undef.html31
-rw-r--r--tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.body-getter.html121
-rw-r--r--tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.body-setter-01.html31
-rw-r--r--tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.embeds-document.plugins-01.html55
-rw-r--r--tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.forms.html58
-rw-r--r--tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByClassName-same.html18
-rw-r--r--tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-case.html17
-rw-r--r--tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-case.xhtml22
-rw-r--r--tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-id.html16
-rw-r--r--tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-id.xhtml21
-rw-r--r--tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-interface.html16
-rw-r--r--tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-namespace.html28
-rw-r--r--tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-namespace.xhtml33
-rw-r--r--tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-newelements.html122
-rw-r--r--tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-newelements.xhtml127
-rw-r--r--tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-null-undef.html30
-rw-r--r--tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-null-undef.xhtml35
-rw-r--r--tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-param.html24
-rw-r--r--tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-param.xhtml29
-rw-r--r--tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-same.html18
-rw-r--r--tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.head-01.html23
-rw-r--r--tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.head-02.html21
-rw-r--r--tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.images.html105
-rw-r--r--tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.title-01.html33
-rw-r--r--tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.title-02.xhtml38
-rw-r--r--tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.title-03.html44
-rw-r--r--tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.title-04.xhtml49
-rw-r--r--tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.title-05.html42
-rw-r--r--tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.title-06.html19
-rw-r--r--tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.title-07.html11
-rw-r--r--tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.title-08.html22
-rw-r--r--tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/nameditem-01.html19
-rw-r--r--tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/nameditem-02.html99
-rw-r--r--tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/nameditem-03.html110
-rw-r--r--tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/nameditem-04.html104
-rw-r--r--tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/nameditem-05.html104
-rw-r--r--tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/nameditem-06.html106
-rw-r--r--tests/wpt/web-platform-tests/html/dom/documents/loading-xml-documents/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/dom/documents/resource-metadata-management/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/dom/documents/resource-metadata-management/document-compatmode-01.html13
-rw-r--r--tests/wpt/web-platform-tests/html/dom/documents/resource-metadata-management/document-compatmode-02.html14
-rw-r--r--tests/wpt/web-platform-tests/html/dom/documents/resource-metadata-management/document-compatmode-03.html12
-rw-r--r--tests/wpt/web-platform-tests/html/dom/documents/resource-metadata-management/document-compatmode-04.xhtml18
-rw-r--r--tests/wpt/web-platform-tests/html/dom/documents/resource-metadata-management/document-compatmode-05.xhtml19
-rw-r--r--tests/wpt/web-platform-tests/html/dom/documents/resource-metadata-management/document-compatmode-06.xhtml17
-rw-r--r--tests/wpt/web-platform-tests/html/dom/documents/resource-metadata-management/document-cookie.html20
-rw-r--r--tests/wpt/web-platform-tests/html/dom/documents/resource-metadata-management/document-lastModified-01.html47
-rw-r--r--tests/wpt/web-platform-tests/html/dom/documents/resource-metadata-management/document-lastModified.html15
-rw-r--r--tests/wpt/web-platform-tests/html/dom/documents/resource-metadata-management/document-lastModified.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/html/dom/documents/resource-metadata-management/document-readyState.html33
-rw-r--r--tests/wpt/web-platform-tests/html/dom/documents/security-document/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/dom/documents/the-document-object/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/closing-the-input-stream/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/closing-the-input-stream/document.close-01.xhtml19
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/001.html12
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/002.html13
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/003.html14
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/004.html14
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/005.html14
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/005.js1
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/006.html14
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/006.js1
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/007.html15
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/007.js4
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/008-1.js3
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/008.html15
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/008.js4
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/009.html15
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/010-1.js4
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/010.html15
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/010.js4
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/011-1.js5
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/011.html15
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/011.js5
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/012.html15
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/012.js5
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/013.html15
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/013.js1
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/014.html15
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/015.html16
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/016.html16
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/017.html19
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/018.html19
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/019.html19
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/020.html18
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/021.html18
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/022.html18
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/023.html19
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/024.html19
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/025.html19
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/026.html19
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/027.html19
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/028.html21
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/029.html21
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/030.html21
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/031.html21
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/032.html22
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/033.html20
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/034.html21
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/035.html21
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/036.html21
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/037.html21
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/038.html21
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/039.html21
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/040.html10
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/041.html13
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/042.html16
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/043.html16
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/044.html17
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/045.html20
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/046.html20
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/047.html15
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/048.html15
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/049.html18
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/050.html25
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/051.html16
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/document.write-01.xhtml19
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/document.write-02.html27
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/iframe_001.html14
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/iframe_002.html22
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/iframe_003.html23
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/iframe_004.html22
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/iframe_005.html25
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/iframe_005.js3
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/iframe_006.html19
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/iframe_007.html17
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/iframe_008.html18
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/iframe_009.html21
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/iframe_010.html23
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/nested-document-write-1.html2
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/nested-document-write-2.html7
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/nested-document-write-external.js1
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/original-id.json1
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/script_001.html10
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/script_002.html20
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/script_003.html10
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/script_004.html19
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/script_005.html20
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/script_006.html20
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/script_007.html19
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/script_008.html19
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/script_009.html19
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/script_010.html22
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/script_011.html22
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/script_012.html22
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/script_013.html24
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-writeln/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-writeln/document.writeln-01.xhtml19
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-writeln/document.writeln-02.html27
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-writeln/original-id.json1
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/001.html20
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/002.html12
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/004-1.html1
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/004.html19
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/005.html16
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/006.html19
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/007.html19
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/008.html20
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/009.html34
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/010-1.html2
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/010-2.html5
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/010.html22
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/011-1.html5
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/011.html9
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/012-1.html7
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/012.html9
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/013-1.html7
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/013.html9
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/014-1.html9
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/014.html9
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/015-1.html17
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/015.html14
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/016-1.html39
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/016.html15
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/document.open-01.xhtml19
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/document.open-02.html27
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/document.open-03-frame.html10
-rw-r--r--tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/document.open-03.html19
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements-embedded.js152
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements-forms.js143
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements-grouping.js60
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements-metadata.js41
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements-microdata.js35
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements-misc.js58
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements-obsolete.js52
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements-sections.js63
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements-tabular.js120
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements-text.js64
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/content-models/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/content-models/contains.json48
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/element-definitions/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/element-definitions/contains.json6
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/elements-in-the-dom/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/elements-in-the-dom/unknown-element.html16
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/.htaccess16
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/classlist-nonstring.html44
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/contains.json38
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/custom-attrs.html29
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/data_unicode_attr.html22
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dataset-delete.html47
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dataset-enumeration.html31
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dataset-get.html57
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dataset-prototype.html26
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dataset-set.html42
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dataset.html28
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-EN-L-ref.html58
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-EN-L.html58
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-EN-R-ref.html58
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-EN-R.html58
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-L-ref.html58
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-L.html58
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-N-EN-L-ref.html58
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-N-EN-L.html58
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-N-EN-R-ref.html58
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-N-EN-R.html58
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-N-EN-ref.html51
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-N-EN.html51
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-N-L-ref.html58
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-N-L.html58
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-N-R-ref.html58
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-N-R.html58
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-R-ref.html59
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-R.html58
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-L-ref.html62
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-L.html62
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-R-ref.html58
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-R.html58
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-bdi-L-ref.html61
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-bdi-L.html61
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-bdi-R-ref.html58
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-bdi-R.html58
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-dir-L-ref.html61
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-dir-L.html61
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-dir-R-ref.html58
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-dir-R.html58
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-dir_auto-L-ref.html61
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-dir_auto-L.html61
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-dir_auto-R-ref.html58
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-dir_auto-R.html58
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-script-L-ref.html58
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-script-L.html58
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-script-R-ref.html58
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-script-R.html58
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-style-L-ref.html58
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-style-L.html58
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-style-R-ref.html58
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-style-R.html58
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-textarea-L-ref.html61
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-textarea-L.html61
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-textarea-R-ref.html58
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-textarea-R.html58
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-EN-L-ref.html59
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-EN-L.html59
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-EN-R-ref.html59
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-EN-R.html59
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-L-ref.html59
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-L.html59
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-N-EN-L-ref.html59
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-N-EN-L.html59
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-N-EN-R-ref.html59
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-N-EN-R.html59
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-N-EN-ref.html54
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-N-EN.html54
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-N-L-ref.html59
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-N-L.html59
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-N-R-ref.html59
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-N-R.html59
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-R-ref.html59
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-R.html59
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-EN-L-ref.html59
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-EN-L.html70
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-EN-R-ref.html59
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-EN-R.html70
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-L-ref.html59
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-L.html70
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-N-EN-L-ref.html59
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-N-EN-L.html70
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-N-EN-R-ref.html59
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-N-EN-R.html70
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-N-EN-ref.html54
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-N-EN.html69
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-N-L-ref.html59
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-N-L.html70
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-N-R-ref.html59
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-N-R.html70
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-R-ref.html59
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-R.html70
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-isolate-ref.html58
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-isolate.html58
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-pre-N-EN-ref.html49
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-pre-N-EN.html66
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-pre-N-between-Rs-ref.html61
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-pre-N-between-Rs.html76
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-pre-mixed-ref.html61
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-pre-mixed.html77
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-textarea-N-EN-ref.html49
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-textarea-N-EN.html66
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-textarea-N-between-Rs-ref.html64
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-textarea-N-between-Rs.html79
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-textarea-mixed-ref.html64
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-textarea-mixed.html80
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-textarea-script-N-EN-ref.html49
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-textarea-script-N-EN.html77
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-textarea-script-N-between-Rs-ref.html65
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-textarea-script-N-between-Rs.html86
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-textarea-script-mixed-ref.html64
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-textarea-script-mixed.html100
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/document-dir.html26
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/id-attribute.html130
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/id-name-specialcase.html31
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/id-name.html18
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/lang-xmllang-01-ref.html20
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/lang-xmllang-01.html58
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/lang-xyzzy-ref.html9
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/lang-xyzzy.html12
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/style-01-ref.html24
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/style-01.html26
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-001.html41
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-002.html41
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-003.html41
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-003.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-004.html42
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-005.html41
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-005.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-006.html42
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-006.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-007.html42
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-008.html41
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-009.html41
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-009.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-010.html42
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-011.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-translate-attribute-007.html29
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-translate-attribute-008.html29
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-translate-attribute-009.html29
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-translate-attribute-010.html29
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-translate-attribute-011.html29
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-translate-attribute-012.html29
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/semantics-0/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/wai-aria/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/wai-aria/README.md1
-rw-r--r--tests/wpt/web-platform-tests/html/dom/elements/wai-aria/contains.json18
-rw-r--r--tests/wpt/web-platform-tests/html/dom/interactions-with-xpath-and-xslt/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/dom/interfaces.html3382
-rw-r--r--tests/wpt/web-platform-tests/html/dom/new-harness.js22
-rw-r--r--tests/wpt/web-platform-tests/html/dom/original-harness.js332
-rw-r--r--tests/wpt/web-platform-tests/html/dom/reflection-embedded.html18
-rw-r--r--tests/wpt/web-platform-tests/html/dom/reflection-forms.html18
-rw-r--r--tests/wpt/web-platform-tests/html/dom/reflection-grouping.html18
-rw-r--r--tests/wpt/web-platform-tests/html/dom/reflection-metadata.html18
-rw-r--r--tests/wpt/web-platform-tests/html/dom/reflection-misc.html18
-rw-r--r--tests/wpt/web-platform-tests/html/dom/reflection-obsolete.html18
-rw-r--r--tests/wpt/web-platform-tests/html/dom/reflection-original.html41
-rw-r--r--tests/wpt/web-platform-tests/html/dom/reflection-sections.html18
-rw-r--r--tests/wpt/web-platform-tests/html/dom/reflection-tabular.html18
-rw-r--r--tests/wpt/web-platform-tests/html/dom/reflection-text.html18
-rw-r--r--tests/wpt/web-platform-tests/html/dom/reflection.js809
-rw-r--r--tests/wpt/web-platform-tests/html/editing/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/editing/activation/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/editing/assigning-keyboard-shortcuts/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/editing/assigning-keyboard-shortcuts/introduction-6/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/editing/assigning-keyboard-shortcuts/processing-model-4/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/editing/assigning-keyboard-shortcuts/the-accesskey-attribute/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/README23
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/canvas/001.xhtml50
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/canvas/002.xhtml35
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/canvas/003-1.xhtml20
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/canvas/003.xhtml35
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/canvas/004.xhtml35
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/canvas/005.xhtml26
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/canvas/006.xhtml25
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/canvas/007.xhtml17
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/canvas/008.xhtml17
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/canvas/009.xhtml16
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/canvas/010-1.xhtml21
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/canvas/010.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/canvas/011.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/canvas/012.xhtml42
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/canvas/013.xhtml42
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/canvas/014.xhtml42
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/canvas/cross-domain/001.xhtml59
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/canvas/helper-drag-me-green-box.xhtml19
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/canvas/helper-drop-here-canvas.xhtml27
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/crashers/dialog-001.html38
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/cross-document/001-1.html47
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/cross-document/001.html23
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/cross-document/002.html25
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/cross-document/003-1.html104
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/cross-document/003.html29
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/001.xhtml71
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/002.xhtml54
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/003.xhtml55
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/004.xhtml56
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/005.xhtml56
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/006.xhtml55
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/007.xhtml57
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/008.xhtml56
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/009-1.xhtml35
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/009.xhtml30
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/010-1.xhtml27
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/010.xhtml47
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/011.xhtml32
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/012.xhtml33
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/013-1.xhtml28
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/013.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/014-1.xhtml55
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/014.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/015-manual.html62
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/016.xhtml58
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/017.xhtml58
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/018.xhtml59
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/019.xhtml59
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/020.xhtml64
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/021.xhtml60
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/022.xhtml74
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/023.xhtml55
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/024.xhtml56
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/025.xhtml56
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/026.xhtml57
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/027.xhtml58
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/028.xhtml62
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/029.xhtml58
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/030.xhtml72
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/031.xhtml141
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/032.xhtml125
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/033.xhtml125
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/034.xhtml126
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/035.xhtml126
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/036.xhtml125
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/037.xhtml127
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/038.xhtml146
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/039.xhtml131
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/040.xhtml131
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/041.xhtml132
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/042.xhtml132
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/043.xhtml131
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/044.xhtml132
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/045.xhtml57
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/046.xhtml172
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/047.xhtml157
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/048.xhtml157
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/049.xhtml158
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/050.xhtml158
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/051.xhtml157
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/052.xhtml158
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/053.html83
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/054.html83
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/055.html46
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/056.xhtml55
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/057.xhtml56
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/058.html79
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/datastore/helper-drop-box-here.xhtml35
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/dom/draggable.html207
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/dom/events.html48
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/dom/specials.html25
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/draggable-areas/border-radius.html25
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/draggable-areas/border.html16
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/draggable-areas/box-shadow.html16
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/draggable-areas/outline.html16
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/draggable-areas/transform.html22
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/draggable-areas/z-index.html35
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/drop/001.xhtml38
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/drop/002.xhtml38
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/drop/003.xhtml35
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/drop/004.xhtml35
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/drop/005.xhtml35
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/drop/006.xhtml50
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/drop/007.xhtml38
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/drop/008.xhtml35
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/drop/009.xhtml36
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/drop/010.xhtml35
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/drop/011.xhtml38
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/drop/012.xhtml38
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/drop/013.xhtml38
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/drop/014.xhtml38
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/drop/015.xhtml35
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/drop/016.xhtml35
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/drop/017.xhtml32
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/drop/018.xhtml39
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/drop/019.xhtml39
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/drop/020.xhtml36
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/drop/021.xhtml38
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/drop/022.xhtml39
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/drop/023.xhtml40
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/drop/024.xhtml39
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/drop/025.html162
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/drop/026.xhtml35
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/drop/027.xhtml34
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/drop/028.html42
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/dropzone/001.xhtml19
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/dropzone/002.xhtml19
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/dropzone/003.xhtml19
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/dropzone/004.xhtml31
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/dropzone/005.xhtml31
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/dropzone/006.xhtml31
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/dropzone/007.html54
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/dropzone/008.html56
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/dropzone/009.html16
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/dropzone/010.html16
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/events/001-1.xhtml51
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/events/001.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/events/002-1.xhtml51
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/events/002.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/events/003-1.xhtml51
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/events/003.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/events/004.xhtml55
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/events/005.xhtml55
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/events/006.xhtml55
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/events/007.xhtml56
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/events/008.xhtml56
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/events/009.xhtml56
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/events/010.xhtml55
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/events/011.xhtml55
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/events/012.xhtml55
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/events/013.xhtml56
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/events/014.xhtml56
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/events/015.xhtml56
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/events/016.xhtml29
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/events/017.xhtml29
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/events/018.xhtml27
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/events/019.xhtml21
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/events/020.xhtml21
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/events/021.xhtml19
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/events/022.xhtml36
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/events/023.xhtml36
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/events/024.xhtml34
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/events/025.html69
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/events/026.html61
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/events/027.xhtml24
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/events/028.xhtml19
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/events/029.html79
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/events/030.html61
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/events/031-1.html25
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/events/031.html25
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/events/032.html81
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/events/033.html79
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/events/034.html56
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/events/035.html83
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/events/036.html70
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/events/037-proposed.xhtml86
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/events/037-spec.xhtml88
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/events/038-proposed.html84
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/events/events-cross-document-suite-HELPER-1.html206
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/events/events-cross-document-suite-HELPER-2.html77
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/events/events-cross-document-suite-manual.html11
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/events/events-file-suite-manual.html175
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/events/events-non-draggable-001.html60
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/events/events-non-draggable-002.html101
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/events/events-suite-manual.html370
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/events/helper-drag-me-input-with-circle.xhtml51
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/events/helper-drag-me-link-with-circle.xhtml51
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/events/helper-drag-me-p-with-circle.xhtml51
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/events/helper-drop-here-body-circle.xhtml51
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/file/001.html103
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/file/002.html146
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/file/003.html90
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/file/004.html51
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/file/005.html13
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/file/006.html13
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/file/007.html99
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/file/008.html113
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/file/009.html16
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/file/010.html29
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/file/011.html93
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/file/fail.txt1
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/file/prompt/001.html28
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/file/prompt/002.html39
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/file/prompt/003.html28
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/file/prompt/004.html27
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/file/prompt/005.html27
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/file/prompt/006.html41
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/file/prompt/007.html32
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/file/prompt/008.html41
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/file/prompt/009.html32
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/images/001.xhtml32
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/images/002.xhtml32
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/images/003.xhtml32
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/images/004.xhtml35
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/images/005.xhtml32
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/images/006.xhtml34
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/images/007.xhtml17
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/images/008.xhtml17
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/images/009.xhtml34
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/images/010.xhtml19
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/images/011.xhtml17
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/images/012-1.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/images/012.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/images/013-1.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/images/013.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/images/014-1.xhtml32
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/images/014.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/images/015.xhtml29
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/images/016.xhtml28
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/images/017.xhtml30
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/images/018.xhtml29
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/images/021.xhtml27
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/images/022.xhtml27
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/images/023.xhtml27
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/images/024.xhtml27
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/images/025.xhtml39
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/images/026.xhtml40
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/images/027.xhtml40
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/images/028.xhtml32
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/images/cross-domain/001.xhtml49
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/images/helper-circle.xhtml9
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/images/helper-drag-me-data-url-image.xhtml9
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/images/helper-drop-horizontal-scrollbar.xhtml9
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/images/helper-drop-image-here.xhtml28
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/images/helper-drop-vertical-scrollbar.xhtml13
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/interactive/frames-1.html18
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/interactive/frames.html22
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/interactive/object-retention.html144
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/interactive/plugins.html28
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/001.html29
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/002.html29
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/003.html29
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/004.html29
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/005.html25
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/006.html25
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/007.html36
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/008.html36
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/009.html25
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/010.html25
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/011.html25
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/012.html25
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/015.html25
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/016.html25
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/017.html25
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/018.html25
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/019.html25
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/020.html25
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/021.html25
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/022.html25
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/media/001.xhtml36
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/microdata/000.html93
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/microdata/001.html128
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/microdata/002.html106
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/microdata/003.html132
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/microdata/004.html116
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/microdata/005.html115
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/microdata/006.html105
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/microdata/007.html116
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/microdata/008.html94
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/microdata/009.html98
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/microdata/010.html104
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/microdata/011.html107
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/microdata/012.html104
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/microdata/013.html104
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/microdata/014.html97
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/microdata/015.html99
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/microdata/016.html160
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/microdata/017.html137
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/microdata/018.html95
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/microdata/019.html96
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/microdata/020.html99
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/microdata/021.html104
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/microdata/test2
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/navigation/001-1.xhtml19
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/navigation/001.xhtml31
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/navigation/002.xhtml14
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/navigation/003.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/navigation/004.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/navigation/005.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/navigation/006.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/navigation/007-1.xhtml13
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/navigation/007.xhtml19
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/navigation/008-1.xhtml13
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/navigation/008.xhtml19
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/navigation/009-1.xhtml13
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/navigation/009.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/navigation/010-1.xhtml27
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/navigation/010.xhtml14
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/navigation/011-1.xhtml27
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/navigation/011.xhtml39
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/navigation/012.xhtml20
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/navigation/013.xhtml20
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/navigation/014.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/navigation/015.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/navigation/016-1.xhtml30
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/navigation/016.xhtml31
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/navigation/017.xhtml14
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/navigation/018.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/navigation/019.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/navigation/020.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/navigation/021-1.xhtml25
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/navigation/021.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/navigation/022-1.xhtml21
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/navigation/022.xhtml19
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/navigation/023-1.xhtml21
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/navigation/023.xhtml19
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/navigation/helper-drag-image-dont-drop.xhtml27
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/navigation/helper-drag-selection-dont-drop.xhtml27
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/navigation/helper-drop-here-reload.xhtml30
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/navigation/helper-drop-image-now.xhtml19
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/navigation/helper-drop-link-now.xhtml17
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/navigation/helper-drop-now.xhtml13
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/navigation/helper-drop-selection-here.xhtml21
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/001.xhtml15
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/002.xhtml20
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/003.xhtml20
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/004.xhtml31
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/005.xhtml31
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/006.xhtml31
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/007.xhtml31
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/008.xhtml24
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/009.xhtml24
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/010.xhtml22
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/011.xhtml17
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/012.xhtml25
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/013.xhtml28
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/014.xhtml20
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/015.xhtml20
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/016.xhtml25
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/017.xhtml25
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/018.xhtml20
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/019.xhtml20
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/020.xhtml24
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/021.xhtml24
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/022.xhtml16
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/023.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/024.xhtml15
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/025.xhtml15
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/026.xhtml32
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/027.xhtml31
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/028.xhtml32
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/029.xhtml36
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/030.xhtml36
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/031.xhtml31
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/032.xhtml35
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/033.xhtml35
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/034.xhtml29
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/035.xhtml30
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/036.xhtml35
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/038.xhtml23
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/039.xhtml23
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/040.xhtml31
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/041.xhtml35
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/042.html59
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/043.html68
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/044.html53
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/045.html55
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/046.html54
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/047.html55
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/048.html54
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/049.xhtml17
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/050.xhtml21
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/051.xhtml21
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/052.xhtml21
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/053.xhtml17
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/054.xhtml19
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/055.xhtml21
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/056.xhtml21
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/057.xhtml20
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/058.html29
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/059.html20
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/060.html30
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/061.html30
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/062.html22
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/heavy-styling-001.html16
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/heavy-styling-002.html16
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/heavy-styling-003.html16
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/heavy-styling-004.html19
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/heavy-styling-005.html15
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/heavy-styling-006.html16
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/heavy-styling-007.html20
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/heavy-styling-008.html31
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/heavy-styling-009.html16
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/outside-viewport-001.html22
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/outside-viewport-002.html22
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/outside-viewport-003.html22
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/outside-viewport-004.html21
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/outside-viewport-005.html22
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/outside-viewport-006.html22
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/overlay/oversized-001.html18
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/alttab.html12
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/cancel-middle-click.html50
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/cancel-right-click.html50
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/close-drag-001.html24
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/close-drag-002.html25
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/close-drag-003.html28
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/close-drag-004.html22
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/close-drag-005.html16
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/close-drag-006.html25
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/cursors/001.html27
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/cursors/002.html26
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/cursors/003.html38
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/cursors/004.html42
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/cursors/005.html45
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/cursors/006.html45
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/cursors/007.html45
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/cursors/008.html51
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/cursors/009.html45
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/cursors/010.html28
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/cursors/011.html57
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/drag-keypress.html28
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/drag-link.html12
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/drag-to-title.html16
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/file-drop-position.html23
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/file-os-to-os.html13
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/file-to-system.html50
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/html-to-os-HELPER-FILE.html14
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/html-to-os.html20
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/html-unicode-to-os.html19
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/inputs-no-js.html15
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/001.html47
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/002.html49
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/003.html59
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/004.html31
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/005.html35
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/006.html32
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/007.html34
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/008.html40
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/009.html42
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/010.html39
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/011.html40
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/012.html44
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/013.html47
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/014.html39
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/015.html32
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/016.html34
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/017.html40
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/018.html42
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/019.html39
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/020.html33
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/021.html33
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/fail.txt1
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/file1.txt1
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/file2.txt1
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/pass.txt1
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/keyboardshortcuts.html18
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/modifiers/all.html175
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/modifiers/copy.html175
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/modifiers/copylink.html175
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/modifiers/copymove.html175
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/modifiers/link.html175
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/modifiers/linkmove.html175
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/modifiers/move.html175
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/modifiers/onlydropzone.html70
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/modifiers/onlydropzoneevents.html82
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/modifiers/releasemodifiersdrag.html125
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/modifiers/releasemodifiersdrop.html108
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/modifiers/scriptmodified.html99
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/moving-window.html27
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/overlappingwindows.html56
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/placeholderposition1.html14
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/placeholderposition2.html14
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/click-to-activate.js1
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/dragndrop.swfbin0 -> 4139 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/dragndropleavedeactivate.swfbin0 -> 4243 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-001.html21
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-002.html39
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-003.html22
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-004.html41
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-005.html26
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-006.html26
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-007.html42
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-008.html41
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-009.html40
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-010.html41
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-011.html40
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-101.html21
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-102.html39
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-103.html22
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-104.html41
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-105.html26
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-106.html26
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-107.html43
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-108.html41
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-109.html40
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-110.html41
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-111.html40
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-203.html22
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-204.html41
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-205.html27
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-206.html26
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-207.html43
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-303.html22
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-304.html41
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-305.html26
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-306.html26
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-307.html42
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/swfsources/dragndrop.hx133
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/swfsources/dragndrop.hxml1
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/swfsources/mouseup.hx34
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/swfsources/mouseup.hxml1
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/plugindrop.html24
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/selection-between-ui.html20
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/selection-from-os.html17
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/selection-from-ui.html20
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/selection-to-os.html14
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/selection-to-ui-via.html19
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/selection-to-ui.html16
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/selection-ui-to-self.html21
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/selection-unicode-to-os.html13
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/taskbardrop.html23
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/taskbarminimise.html12
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/text-os-to-os.html13
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/platform/text-to-os.html19
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/reload/001.xhtml39
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/reload/002.xhtml20
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/reload/003.xhtml20
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/reload/004.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/reload/005.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/reload/006.xhtml14
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/reload/007.xhtml25
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/reload/008.xhtml25
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/reload/009-1.xhtml9
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/reload/009.xhtml16
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/reload/010-1.xhtml9
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/reload/010.xhtml16
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/reload/011-1.xhtml9
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/reload/011.xhtml16
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/reload/012-1.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/reload/012-2.xhtml28
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/reload/012.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/remove/001.xhtml43
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/remove/002.xhtml24
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/remove/003.xhtml24
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/remove/004.xhtml19
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/remove/005.xhtml19
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/remove/006.xhtml19
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/remove/007.xhtml28
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/remove/008.xhtml28
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/remove/009.xhtml16
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/remove/010.xhtml16
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/remove/011.xhtml16
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/remove/012.xhtml16
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/remove/013.xhtml16
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/remove/014.xhtml16
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/remove/015.xhtml16
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/remove/016.xhtml16
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/remove/017.xhtml16
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/remove/018.xhtml16
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/remove/019.xhtml16
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/remove/020.xhtml16
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/remove/021.xhtml19
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/remove/022-1.html26
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/remove/022.html28
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/remove/helper-drag-me-input.xhtml9
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/remove/helper-drag-me-link.xhtml9
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/remove/helper-drag-me-p.xhtml9
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/resources/100x100-navy.pngbin0 -> 278 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/resources/1x1-transparent.gifbin0 -> 43 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/resources/boxnavy.swfbin0 -> 4254 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/resources/circle.pngbin0 -> 1252 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/resources/crossorigin.sub.js13
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/resources/fail.pngbin0 -> 759 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/resources/filler.html109
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/resources/pass.pngbin0 -> 1689 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/roundtrip/001.xhtml38
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/roundtrip/002.xhtml20
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/roundtrip/003.xhtml20
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/roundtrip/004.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/roundtrip/005.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/roundtrip/006.xhtml14
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/roundtrip/007.xhtml25
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/roundtrip/008.xhtml25
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/001.xhtml24
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/002.xhtml24
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/003.xhtml24
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/004.xhtml24
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/005.xhtml24
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/006.xhtml24
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/007.xhtml24
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/008.xhtml24
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/009.xhtml24
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/010.xhtml27
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/011.xhtml18
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/012.xhtml18
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/013.xhtml18
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/014.xhtml18
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/015.xhtml18
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/016.xhtml18
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/017.xhtml18
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/018.xhtml18
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/019.xhtml18
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/020.xhtml21
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/021.xhtml20
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/022.xhtml20
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/023.xhtml20
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/024.xhtml20
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/025.xhtml20
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/026.xhtml20
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/027.xhtml20
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/028.xhtml20
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/029.xhtml20
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/030.xhtml23
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/031.xhtml34
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/032.xhtml33
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/033.xhtml23
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/034.xhtml22
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/035.xhtml30
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/036.xhtml29
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/037.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/038.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/039.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/040.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/041.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/042.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/043.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/044.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/045.xhtml17
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/046.xhtml17
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/047.xhtml17
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/048.xhtml17
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/049.xhtml17
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/050.xhtml17
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/051.xhtml27
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/052.xhtml27
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/053.xhtml21
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/054.xhtml21
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/055.xhtml23
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/056.xhtml23
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/057.xhtml20
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/058.xhtml20
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/059.xhtml16
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/060.xhtml16
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/061.xhtml16
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/062.xhtml16
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/063.xhtml16
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/064-1.xhtml15
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/064.xhtml16
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/065.xhtml16
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/066.xhtml16
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/067-1.xhtml15
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/067-2.xhtml15
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/067.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/068-1.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/068-2.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/068.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/069.xhtml17
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/070.xhtml17
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/071.xhtml17
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/072.xhtml17
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/073.xhtml17
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/074.xhtml17
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/075.xhtml17
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/076.xhtml17
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/077.xhtml17
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/078.xhtml17
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/079.xhtml17
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/080.xhtml20
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/081.xhtml36
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/082.xhtml36
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/083.xhtml36
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/084.xhtml36
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/085.xhtml36
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/086.xhtml36
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/087.xhtml24
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/088.xhtml29
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/089.xhtml15
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/090.xhtml15
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/091-1.xhtml9
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/091-2.xhtml18
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/091.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/092.xhtml16
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/093.xhtml16
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/094.xhtml16
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/095.xhtml16
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/096.xhtml16
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/097.xhtml16
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/098.xhtml26
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/099.xhtml26
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/100.xhtml20
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/101.xhtml20
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/102.xhtml22
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/103.xhtml22
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/104.xhtml19
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/105.xhtml19
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/106.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/107-1.html8
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/107.html5
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/108-1.html3
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/108.html5
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/109.xhtml18
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/110.xhtml20
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/111.xhtml18
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/112.xhtml18
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/113.xhtml18
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/114.xhtml20
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/115.xhtml17
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/116.xhtml19
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/117.xhtml17
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/118.xhtml17
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/119.xhtml17
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/120.xhtml19
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/121.xhtml20
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/122.xhtml22
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/123.xhtml20
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/124.xhtml20
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/125.xhtml20
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/126.xhtml22
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/127.xhtml25
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/128.xhtml26
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/129.xhtml25
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/130.xhtml25
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/131.xhtml25
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/132.xhtml24
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/133.xhtml20
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/134.xhtml17
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/135.xhtml17
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/136.xhtml18
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/137.xhtml18
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/138.xhtml18
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/139.xhtml18
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/140.xhtml17
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/141.xhtml20
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/142.xhtml24
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/143.xhtml26
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/144.xhtml31
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/145.xhtml31
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/146.xhtml28
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/147.html15
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/148.html15
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/149.html16
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/150.html15
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/151.xhtml16
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/152.xhtml17
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/153.xhtml16
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/154.xhtml17
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/155.xhtml24
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/156.xhtml11
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/157.xhtml11
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/158.xhtml11
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/159.xhtml11
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/160.xhtml11
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/161.xhtml11
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/162.xhtml20
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/163.xhtml16
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/164.xhtml16
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/165.xhtml16
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/166.xhtml16
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/167.xhtml16
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/168.xhtml25
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/169.xhtml24
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/170.xhtml33
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/171.xhtml39
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/172.html45
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/173.html45
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/helper-drag-me-input-to-other-input.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/helper-drag-me-input-to-other-textarea.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/helper-drag-me-input.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/helper-drag-me-textarea-to-other-blue-box.xhtml15
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/helper-drag-me-textarea-to-other-input.xhtml15
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/helper-drag-me-textarea-to-other-textarea.xhtml15
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/helper-drop-here-blue-box-contenteditable.xhtml18
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/helper-drop-here-blue-box.xhtml22
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/helper-drop-here-input.xhtml15
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/helper-drop-here-textarea.xhtml16
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/selection/helper-scroll-then-drop-input.xhtml18
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/001.svg9
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/002.svg9
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/003.svg13
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/004.svg13
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/005.svg8
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/006.svg9
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/007.svg9
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/008.svg13
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/009.svg13
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/010.svg8
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/011.svg15
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/012.svg15
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/013-1.xhtml15
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/013.svg11
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/014-1.xhtml18
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/014.svg10
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/015-1.xhtml9
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/015.svg10
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/016-1.xhtml22
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/016.svg10
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/017.xhtml14
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/018.xhtml14
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/019.xhtml19
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/020.xhtml27
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/021.xhtml26
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/022.xhtml26
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/023.xhtml26
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/024.xhtml22
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/025.xhtml22
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/026.xhtml22
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/027.xhtml20
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/028.xhtml20
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/029.xhtml21
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/030-1.svg5
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/030.xhtml32
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/031.xhtml32
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/032.xhtml21
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/033.xhtml21
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/034.xhtml21
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/035.xhtml21
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/036-1.svg4
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/036.xhtml11
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/037.xhtml11
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/038.xhtml11
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/039-1.svg4
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/039.xhtml11
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/040.xhtml11
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/041.xhtml11
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/042.xhtml21
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/043.xhtml21
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/044.svg10
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/045.svg10
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/046.svg14
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/047.svg13
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/048.svg13
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/049.xhtml14
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/050.xhtml13
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/051.xhtml24
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/052.svg28
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/053.svg30
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/054.svg35
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/055.svg30
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/056.svg69
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/057.svg121
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/058.svg36
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/059-1.svg21
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/059.svg15
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/060-1.svg12
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/060.svg28
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/061.svg27
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/062.svg17
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/063.svg24
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/064.svg26
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/065.svg28
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/066.svg31
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/067.svg35
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/svg/helper-drop-selection-here-textArea.svg5
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/synthetic/001.html120
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/synthetic/005-manual.html339
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/synthetic/006-manual.html78
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/target-origin/001-manual.html110
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/target-origin/002-manual.html86
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/target-origin/003-manual.html95
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/target-origin/004-1.html25
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/target-origin/004-manual.html36
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/target-origin/005-1.html25
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/target-origin/005-manual.html36
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/target-origin/006-manual.html52
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/target-origin/007-manual.html52
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/target-origin/008-manual.html53
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/target-origin/009-manual.html25
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/target-origin/010-manual.html25
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/target-origin/011-manual.html63
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/target-origin/012-manual.html62
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/target-origin/013-manual.html24
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/target-origin/101-manual.html123
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/target-origin/102-manual.html36
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/target-origin/103-1.html32
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/target-origin/103-manual.html27
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/target-origin/104-1.html32
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/target-origin/104-manual.html27
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/target-origin/105-1.html32
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/target-origin/105-manual.html27
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/target-origin/106-1.html32
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/target-origin/106-manual.html27
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/target-origin/107-1.html32
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/target-origin/107-manual.html27
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/target-origin/108-1.html32
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/target-origin/108-manual.html27
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/target-origin/109-1.html32
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/target-origin/109-manual.html27
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/target-origin/110-1.html32
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/target-origin/110-manual.html27
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/target-origin/111-manual.html52
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/target-origin/112-manual.html56
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/target-origin/113-manual.html50
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/target-origin/114-manual.html56
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/target-origin/115-manual.html50
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/target-origin/116-manual.html31
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/target-origin/117-1.html33
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/target-origin/117-manual.html27
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/target-origin/118-1.html32
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/target-origin/118-manual.html27
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/target-origin/201-manual.html83
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/target-origin/202.html64
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/target-origin/HELPER-mustallow.html26
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/target-origin/HELPER-mustblock.html21
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/target-origin/HELPER-showorigin.html31
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/the-dragevent-interface/dragevent-manual.html99
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/the-draggable-attribute/draggable_attribute.html123
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute.html45
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_data_item_file_type-manual.html45
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_data_item_kind_file-manual.html45
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_data_item_kind_string-manual.html45
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_data_item_string_type-manual.html45
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_inputbox_element-manual.html51
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_inputbox_element_dbcs-manual.html46
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_link_element-manual.html48
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_value_case_insensitive_COpy-manual.html45
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_value_case_insensitive_STRING-manual.html45
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_value_case_insensitive_String_-manual.html45
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_value_case_insensitive_linK-manual.html45
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_value_copy-manual.html45
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_value_foo-manual.html45
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_value_link-manual.html45
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_value_move-manual.html45
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_value_multiple_values_foo_bar_move-manual.html45
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_value_multiple_values_foo_link-manual.html45
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_value_multiple_values_move_copy-manual.html45
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_value_not_specified-manual.html45
-rw-r--r--tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_value_unordered_unique_space_separated-manual.html53
-rw-r--r--tests/wpt/web-platform-tests/html/editing/editing-0/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/editing/editing-0/best-practices-for-in-page-editors/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/editing/editing-0/contenteditable/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/editing/editing-0/contenteditable/contentEditable-invalidvalue.html16
-rw-r--r--tests/wpt/web-platform-tests/html/editing/editing-0/contenteditable/user-interaction-editing-contenteditable.html54
-rw-r--r--tests/wpt/web-platform-tests/html/editing/editing-0/editing-apis/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/editing/editing-0/making-entire-documents-editable-the-designmode-idl-attribute/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/editing/editing-0/making-entire-documents-editable-the-designmode-idl-attribute/original-id.json1
-rw-r--r--tests/wpt/web-platform-tests/html/editing/editing-0/making-entire-documents-editable-the-designmode-idl-attribute/user-interaction-editing-designMode.html26
-rw-r--r--tests/wpt/web-platform-tests/html/editing/editing-0/spelling-and-grammar-checking/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/editing/editing-0/spelling-and-grammar-checking/user-interaction-editing-spellcheck.html35
-rw-r--r--tests/wpt/web-platform-tests/html/editing/focus/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/editing/focus/document-level-focus-apis/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/editing/focus/document-level-focus-apis/document-level-apis.html34
-rw-r--r--tests/wpt/web-platform-tests/html/editing/focus/document-level-focus-apis/test.html5
-rw-r--r--tests/wpt/web-platform-tests/html/editing/focus/element-level-focus-apis/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/editing/focus/focus-01-manual.html43
-rw-r--r--tests/wpt/web-platform-tests/html/editing/focus/focus-02-manual.html38
-rw-r--r--tests/wpt/web-platform-tests/html/editing/focus/focus-management/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/editing/focus/focus-management/focus-events.html32
-rw-r--r--tests/wpt/web-platform-tests/html/editing/focus/sequential-focus-navigation-and-the-tabindex-attribute/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/editing/focus/sequential-focus-navigation-and-the-tabindex-attribute/focus-tabindex-default-value.html21
-rw-r--r--tests/wpt/web-platform-tests/html/editing/focus/sequential-focus-navigation-and-the-tabindex-attribute/focus-tabindex-negative-manual.html44
-rw-r--r--tests/wpt/web-platform-tests/html/editing/focus/sequential-focus-navigation-and-the-tabindex-attribute/focus-tabindex-order-manual.html59
-rw-r--r--tests/wpt/web-platform-tests/html/editing/focus/sequential-focus-navigation-and-the-tabindex-attribute/focus-tabindex-positive-manual.html43
-rw-r--r--tests/wpt/web-platform-tests/html/editing/focus/sequential-focus-navigation-and-the-tabindex-attribute/focus-tabindex-zero-manual.html45
-rw-r--r--tests/wpt/web-platform-tests/html/editing/inert-subtrees/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/editing/inert-subtrees/the-inert-attribute/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/editing/the-hidden-attribute/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/editing/the-hidden-attribute/hidden-1-ref.html4
-rw-r--r--tests/wpt/web-platform-tests/html/editing/the-hidden-attribute/hidden-1a.html7
-rw-r--r--tests/wpt/web-platform-tests/html/editing/the-hidden-attribute/hidden-1b.html10
-rw-r--r--tests/wpt/web-platform-tests/html/editing/the-hidden-attribute/hidden-1c.html11
-rw-r--r--tests/wpt/web-platform-tests/html/editing/the-hidden-attribute/hidden-1d.html11
-rw-r--r--tests/wpt/web-platform-tests/html/editing/the-hidden-attribute/hidden-1e.html9
-rw-r--r--tests/wpt/web-platform-tests/html/editing/the-hidden-attribute/hidden-1f.html9
-rw-r--r--tests/wpt/web-platform-tests/html/editing/the-hidden-attribute/hidden-1g.html10
-rw-r--r--tests/wpt/web-platform-tests/html/editing/the-hidden-attribute/hidden-2-ref.svg7
-rw-r--r--tests/wpt/web-platform-tests/html/editing/the-hidden-attribute/hidden-2.svg12
-rw-r--r--tests/wpt/web-platform-tests/html/iana/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/iana/application-x-www-form-urlencoded/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/iana/application-x-www-form-urlencoded/original-id.json1
-rw-r--r--tests/wpt/web-platform-tests/html/iana/application-xhtml-xml/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/iana/application-xhtml-xml/original-id.json1
-rw-r--r--tests/wpt/web-platform-tests/html/iana/multipart-x-mixed-replace/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/iana/multipart-x-mixed-replace/original-id.json1
-rw-r--r--tests/wpt/web-platform-tests/html/iana/ping-to/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/iana/text-cache-manifest/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/iana/text-cache-manifest/original-id.json1
-rw-r--r--tests/wpt/web-platform-tests/html/iana/text-html/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/iana/text-html/original-id.json1
-rw-r--r--tests/wpt/web-platform-tests/html/iana/web-scheme-prefix/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/iana/web-scheme-prefix/original-id.json1
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/case-sensitivity-and-string-comparison/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/collections/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/collections/contains.json14
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/collections/htmlallcollection.html33
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/collections/htmlformcontrolscollection.html112
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/collections/htmloptionscollection.html184
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/collections/radionodelist.html78
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/domstringmap/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/garbage-collection/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/reflecting-content-attributes-in-idl-attributes/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/safe-passing-of-structured-data/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/transferable-objects/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/common-microsyntaxes/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/common-microsyntaxes/boolean-attributes/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/common-microsyntaxes/colors/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/common-microsyntaxes/comma-separated-tokens/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/common-microsyntaxes/common-parser-idioms/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/common-microsyntaxes/dates-and-times/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/common-microsyntaxes/dates-and-times/contains.json42
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/common-microsyntaxes/keywords-and-enumerated-attributes/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/common-microsyntaxes/mq/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/common-microsyntaxes/numbers/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/common-microsyntaxes/numbers/contains.json26
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/common-microsyntaxes/space-separated-tokens/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/common-microsyntaxes/syntax-references/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/conformance-requirements/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/conformance-requirements/conformance-classes/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/conformance-requirements/dependencies/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/conformance-requirements/extensibility/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/conformance-requirements/extensibility/foreign.html45
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/fetching-resources/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/fetching-resources/content-type-sniffing/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/fetching-resources/cors-enabled-fetch/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/fetching-resources/cors-settings-attributes/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/fetching-resources/encrypted-http-and-related-security-concerns/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/fetching-resources/extracting-character-encodings-from-meta-elements/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/fetching-resources/processing-model/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/fetching-resources/terminology-1/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/namespaces/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/terminology/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/terminology/character-encodings/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/terminology/dom-trees/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/terminology/plugins/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/terminology/plugins/sample.txt3
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/terminology/plugins/text-plain.html32
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/terminology/resources/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/terminology/scripting-0/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/terminology/xml/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/urls/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/urls/base-urls/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/urls/dynamic-changes-to-base-urls/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/urls/dynamic-changes-to-base-urls/dynamic-urls.sub.xhtml59
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/urls/interfaces-for-url-manipulation/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/urls/parsing-urls/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/urls/resolving-urls/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/urls/resolving-urls/query-encoding/resources/blank.py2
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/urls/resolving-urls/query-encoding/resources/css-tmpl.py5
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/urls/resolving-urls/query-encoding/resources/manifest.py12
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/urls/resolving-urls/query-encoding/resources/page-using-manifest.py12
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/urls/resolving-urls/query-encoding/resources/resolve-url.js952
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/urls/resolving-urls/query-encoding/resources/resource.py131
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/urls/resolving-urls/query-encoding/resources/stash.py16
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/urls/resolving-urls/query-encoding/utf-16be.htmlbin0 -> 1056 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/urls/resolving-urls/query-encoding/utf-16le.htmlbin0 -> 1062 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/urls/resolving-urls/query-encoding/utf-8.html9
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/urls/resolving-urls/query-encoding/windows-1251.html9
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/urls/resolving-urls/query-encoding/windows-1252.html9
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/urls/terminology-0/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/urls/terminology-0/document-base-url.html52
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/urls/terminology-0/multiple-base.sub.html17
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/urls/url-manipulation-and-creation/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/infrastructure/utf-8/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/introduction/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/introduction/a-quick-introduction-to-html/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/introduction/a-quick-introduction-to-html/common-pitfalls-to-avoid-when-using-the-scripting-apis/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/introduction/a-quick-introduction-to-html/writing-secure-applications-with-html/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/introduction/audience/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/introduction/background/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/introduction/conformance-requirements-for-authors/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/introduction/conformance-requirements-for-authors/presentational-markup/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/introduction/conformance-requirements-for-authors/restrictions-on-content-models-and-on-attribute-values/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/introduction/conformance-requirements-for-authors/syntax-errors/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/introduction/design-notes/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/introduction/design-notes/compliance-with-other-specifications/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/introduction/design-notes/serializability-of-script-execution/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/introduction/fingerprint/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/introduction/history-0/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/introduction/html-vs-xhtml/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/introduction/scope/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/introduction/structure-of-this-specification/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/introduction/structure-of-this-specification/how-to-read-this-specification/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/introduction/structure-of-this-specification/typographic-conventions/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/introduction/suggested-reading/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/obsolete/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/obsolete/non-conforming-features/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/obsolete/obsolete-but-conforming-features/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/obsolete/obsolete-but-conforming-features/warnings-for-obsolete-but-conforming-features/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/frames/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/other-elements-attributes-and-apis/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/other-elements-attributes-and-apis/document-color-01.html18
-rw-r--r--tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/other-elements-attributes-and-apis/document-color-02.html47
-rw-r--r--tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/other-elements-attributes-and-apis/document-color-03.html47
-rw-r--r--tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/other-elements-attributes-and-apis/document-color-04.html47
-rw-r--r--tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/other-elements-attributes-and-apis/heading-obsolete-attributes-01.html18
-rw-r--r--tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/other-elements-attributes-and-apis/nothing.html27
-rw-r--r--tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/other-elements-attributes-and-apis/original-id.json1
-rw-r--r--tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/other-elements-attributes-and-apis/script-IDL-event-htmlfor.html57
-rw-r--r--tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/the-applet-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/the-marquee-element-0/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/the-marquee-element-0/marquee-direction-down-manual.html8
-rw-r--r--tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/the-marquee-element-0/marquee-direction-left-manual.html8
-rw-r--r--tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/the-marquee-element-0/marquee-direction-right-manual.html8
-rw-r--r--tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/the-marquee-element-0/marquee-direction-up-manual.html8
-rw-r--r--tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/the-marquee-element-0/marquee-events.html71
-rw-r--r--tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/the-marquee-element-0/marquee-loop.html27
-rw-r--r--tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/the-marquee-element-0/marquee-scrollamount-effect.html9
-rw-r--r--tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/the-marquee-element-0/marquee-scrollamount.html27
-rw-r--r--tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/the-marquee-element-0/marquee-scrolldelay.html33
-rw-r--r--tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/the-marquee-element-0/marquee-start.html23
-rw-r--r--tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/the-marquee-element-0/marquee-stop.html22
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/bindings/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/bindings/introduction-9/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/bindings/the-button-element-0/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/bindings/the-details-element-0/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/bindings/the-input-element-as-a-button/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/bindings/the-input-element-as-a-checkbox-and-radio-button-widgets/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/bindings/the-input-element-as-a-color-well/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/bindings/the-input-element-as-a-file-upload-control/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/bindings/the-input-element-as-a-range-control/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/bindings/the-input-element-as-a-text-entry-widget/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/bindings/the-input-element-as-domain-specific-widgets/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/bindings/the-keygen-element-0/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/bindings/the-marquee-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/bindings/the-meter-element-0/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/bindings/the-progress-element-0/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/bindings/the-select-element-0/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/bindings/the-select-element-0/option-label-ref.html19
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/bindings/the-select-element-0/option-label.html66
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/bindings/the-textarea-element-0/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/frames-and-framesets/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/interactive-media/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/interactive-media/editing-hosts/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/interactive-media/links-forms-and-navigation/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/interactive-media/links-forms-and-navigation/original-id.json1
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/interactive-media/text-rendered-in-native-user-interfaces/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/interactive-media/the-title-attribute-0/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/introduction-8/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/bidirectional-text/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/flow-content-0/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/flow-content-0/figure-ref.html11
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/flow-content-0/figure.html9
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/form-controls/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/hidden-elements/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/lists/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/lists/TODO-lists.html17
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/phrasing-content-0/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/quotes/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/sections-and-headings/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/tables/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/tables/table-border-1-ref.html46
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/tables/table-border-1.html37
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/tables/table-border-2-notref.html40
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/tables/table-border-2-ref.html30
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/tables/table-border-2.html31
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/tables/table-layout-notref.html9
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/tables/table-layout-ref.html9
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/tables/table-layout.html12
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/tables/table-width-150percent-ref.html12
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/tables/table-width-150percent.html12
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/the-fieldset-element-0/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/the-hr-element-0/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/the-page/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/the-page/body_link.xhtml16
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/the-page/body_text_00ffff-ref.html14
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/the-page/body_text_00ffff.xhtml12
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/the-page/test-body.xhtml8
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/print-media/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/replaced-elements/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img_border-ref.xhtml9
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img_border_percent.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/object_border-ref.xhtml8
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/object_border_perc.xhtml9
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/object_border_pixel.xhtml9
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/replaced-elements/embedded-content-rendering-rules/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/replaced-elements/image-maps-0/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/replaced-elements/images/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/replaced-elements/images/space-ref.html13
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/replaced-elements/images/space.html14
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/replaced-elements/resources/svg-sizing.js418
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-embedded-sizing.js96
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-iframe-auto.html33
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-iframe-fixed.html33
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-iframe-percentage.html33
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-img-auto.html33
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-img-fixed.html33
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-img-percentage.html33
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-object-auto.html33
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-object-fixed.html33
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-object-percentage.html33
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/replaced-elements/svg-inline-sizing/svg-inline.html29
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/replaced-elements/svg-inline-sizing/svg-inline.js78
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/replaced-elements/toolbars-0/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/replaced-elements/tools/gen-svgsizing-tests.py55
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/the-css-user-agent-style-sheet-and-presentational-hints/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/rendering/unstyled-xml-documents/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/common-idioms/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/common-idioms/conversations/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/common-idioms/footnotes/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/common-idioms/rel-up/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/common-idioms/tag-clouds/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/common-idioms/the-main-part-of-the-content/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/disabled-elements/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/disabled-elements/disabledElement.html44
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/document-metadata/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/document-metadata/styling/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/document-metadata/styling/LinkStyle.html72
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/document-metadata/styling/support/alternate.css7
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/document-metadata/styling/support/emptytitle.css4
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/document-metadata/styling/support/normal.css5
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/document-metadata/styling/support/notitle.css4
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/document-metadata/styling/support/unmatch.css4
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/document-metadata/the-base-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/document-metadata/the-base-element/base_href_empty.html29
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/document-metadata/the-base-element/base_href_specified.sub.html28
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/document-metadata/the-base-element/base_href_unspecified.html30
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/document-metadata/the-base-element/base_multiple.html37
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/document-metadata/the-base-element/example.html7
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/document-metadata/the-base-element/example2.html5
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/document-metadata/the-head-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/document-metadata/the-link-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/document-metadata/the-link-element/link-rellist.html23
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/document-metadata/the-link-element/link-style-error-01.html32
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/document-metadata/the-meta-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/document-metadata/the-meta-element/contains.json22
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/document-metadata/the-meta-element/the-lang-attribute-012.html51
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/document-metadata/the-style-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/document-metadata/the-style-element/html_style_in_comment-ref.html18
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/document-metadata/the-style-element/html_style_in_comment.xhtml18
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/document-metadata/the-style-element/style-error-01.html32
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/document-metadata/the-style-element/style_disabled.html39
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/document-metadata/the-style-element/style_events.html36
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/document-metadata/the-style-element/style_media.html40
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/document-metadata/the-style-element/style_scoped.html42
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/document-metadata/the-title-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/document-metadata/the-title-element/title.text-01.html25
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/document-metadata/the-title-element/title.text-02.xhtml30
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/document-metadata/the-title-element/title.text-03.html32
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/document-metadata/the-title-element/title.text-04.xhtml37
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/edits/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/edits/attributes-common-to-ins-and-del-elements/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/edits/edits-and-lists/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/edits/edits-and-paragraphs/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/edits/edits-and-tables/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/edits/the-del-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/edits/the-del-element/del_effect.html19
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/edits/the-ins-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/edits/the-ins-element/ins_effect.html19
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/dimension-attributes/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/image-maps/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/image-maps/contains.json10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/mathml/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/audio_controls_present-manual.html14
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/audio_loop_base.html42
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/audio_loop_current_media_controller-manual.html23
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/audio_muted_overriding_volume-manual.html21
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/audio_muted_present-manual.html20
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/audio_volume_check.html58
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/audio_volume_loudest-manual.html21
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/audio_volume_silent-manual.html21
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/contains.json132
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/error-codes/error.html38
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_canplay.html38
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_canplay_noautoplay.html36
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_canplaythrough.html38
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_canplaythrough_noautoplay.html36
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_loadeddata.html38
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_loadeddata_noautoplay.html36
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_loadedmetadata.html38
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_loadedmetadata_noautoplay.html36
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_loadstart.html38
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_loadstart_noautoplay.html36
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_order_canplay_canplaythrough.html52
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_order_canplay_playing.html52
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_order_loadedmetadata_loadeddata.html52
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_order_loadstart_progress.html52
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_pause.html48
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_pause_noautoplay.html40
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_play.html38
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_play_noautoplay.html40
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_playing.html38
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_playing_noautoplay.html40
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_progress.html38
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_progress_noautoplay.html36
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_timeupdate.html34
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_timeupdate_noautoplay.html40
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_volumechange.html72
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/historical.html46
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLMediaElement/addTextTrack.html116
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLMediaElement/textTracks.html13
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/default.html55
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/kind.html146
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/label.html83
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/readyState.html11
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/src.html77
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/srclang.html82
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/track.html12
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/activeCues.html104
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/addCue.html68
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/constants.html23
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/cues.html100
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/kind.html31
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/label.html29
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/language.html29
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/mode.html55
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/oncuechange.html33
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/removeCue.html50
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/endTime.html39
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/id.html39
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/onenter.html36
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/onexit.html36
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/pauseOnExit.html40
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/startTime.html39
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/track.html38
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCueList/getCueById.html53
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCueList/getter.html49
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCueList/length.html22
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackList/getTrackById.html16
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackList/getter.html32
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackList/length.html18
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackList/onaddtrack.html33
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackList/onremovetrack.html33
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TrackEvent/constructor.html24
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TrackEvent/createEvent.html15
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/autoplay-overrides-preload.html28
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/load-events-networkState.html67
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/load-removes-queued-error-event.html44
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-candidate-insert-before.html29
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-candidate-moved.html21
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-candidate-remove-addEventListener.html26
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-candidate-remove-no-listener.html26
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-candidate-remove-onerror.html26
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-audio-constructor-no-src.html13
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-audio-constructor.html12
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-in-sync-event.html32
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-fragment-into-document.html22
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-into-document.html12
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-into-iframe.html23
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-parent-into-document.html19
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source-in-div.html14
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source-in-namespace.html14
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source-networkState.html38
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source-not-in-document.html13
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source.html14
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-load.html20
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-pause-networkState.html28
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-pause.html20
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-play.html20
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-remove-from-document-networkState.html29
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-remove-from-document.html21
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-remove-src.html22
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-set-src-in-namespace.html14
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-set-src-networkState.html16
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-set-src-not-in-document.html13
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-set-src.html14
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-control.html26
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-insert-br.html33
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-insert-source.html44
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-insert-text.html33
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-remove-source-after.html56
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-remove-source.html43
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-remove-text.html33
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-remove-source.html24
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-remove-src.html22
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-source-media.html14
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resources/delayed-broken-video.py5
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/stable-state-beforeunload-manual.html30
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/stable-state-dialogs-manual.html18
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/stable-state-print-manual.html22
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/location-of-the-media-resource/currentSrc.html44
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/mime-types/canPlayType.html110
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/networkState_during_loadstart.html42
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/networkState_during_progress.html42
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/networkState_initial.html33
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/offsets-into-the-media-resource/currentTime.html40
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/offsets-into-the-media-resource/duration.html11
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/paused_false_during_play.html44
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/paused_true_during_pause.html46
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/pause-move-to-other-document.html25
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/pause-move-within-document.html25
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/pause-remove-from-document-networkState.html21
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/pause-remove-from-document.html37
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/play-in-detached-document.html23
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/playbackRate.html19
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/preload_reflects_none_autoplay.html31
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/ready-states/autoplay.html73
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/readyState_during_canplay.html44
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/readyState_during_canplaythrough.html46
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/readyState_during_loadeddata.html44
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/readyState_during_loadedmetadata.html44
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/readyState_during_playing.html44
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/readyState_initial.html33
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/seeking/seek-to-currentTime.html33
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/seeking/seek-to-max-value.htm23
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/seeking/seek-to-negative-time.htm23
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/src_reflects_attribute_not_source_elements.html33
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/synchronising-multiple-media-elements/media-controllers/task-source.html27
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cloneNode.html86
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/003.html10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/004.html10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/005.html10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/006.html10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/007.html10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/008.html10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/009.html10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/010.html10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/011.html10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/012.html10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/013.html10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/014.html10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/015.html10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/016.html10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/017.html10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/018.html10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/019.html10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/020.html10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/021.html10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/022.html10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/023.html10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/024.html10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/025.html10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/026.html10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/027.html10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/028.html10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/029.html10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/030.html10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/031.html10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/032.html10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/033.html10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/034.html10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/035.html10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/036.html10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/037.html10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/038.html10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/039.html10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/040.html10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/041.html10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/042.html10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/043.html10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/044.html10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/045.html10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/046.html10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/support/common.js144
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/support/cors-tester.py51
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/support/remove-cookie.html6
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/support/set-cookie.html6
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/track.de.vtt4
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/track.en.vtt4
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/track.fr.vtt4
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/track.vtt4
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/src-clear-cues.html52
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-api-texttracks.html36
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/user-interface/muted.html152
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/video_controls_present-manual.html14
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/video_loop_base.html41
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/video_loop_current_media_controller-manual.html23
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/video_muted_overriding_volume-manual.html21
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/video_muted_present-manual.html20
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/video_volume_check.html58
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/video_volume_loudest-manual.html21
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/video_volume_silent-manual.html21
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/volume_nonfinite.html18
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/svg/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-area-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-area-element/area-stringifier.html16
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-area-element/area_nohref.xhtml18
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-area-element/test-area.xhtml9
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-audio-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-audio-element/audio_001.htm18
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-audio-element/audio_002.htm18
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-audio-element/audio_constructor.html51
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-audio-element/audio_content-ref.htm13
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/2d.canvas.readonly.html31
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/2d.canvas.reference.html27
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/2d.getcontext.exists.html27
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/2d.getcontext.extraargs.html27
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/2d.getcontext.shared.html31
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/2d.getcontext.unique.html27
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/2d.scaled-manual.html30
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/2d.scaled-manual.pngbin0 -> 219 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/2d.type.exists.html27
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/2d.type.extend.html34
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/2d.type.prototype.html36
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/2d.type.replace.html35
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/contains.json10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/context.arguments.missing.html27
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/context.casesensitive.html27
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/context.emptystring.html27
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/context.unrecognised.badname.html27
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/context.unrecognised.badsuffix.html27
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/context.unrecognised.nullsuffix.html27
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/context.unrecognised.unicode.html27
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/fallback.basic.html27
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/fallback.multiple.html27
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/fallback.nested.html27
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/initial.colour.html30
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/initial.colour.pngbin0 -> 117 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/initial.reset.2dstate.html103
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/initial.reset.clip.html33
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/initial.reset.different.html31
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/initial.reset.different.pngbin0 -> 107 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/initial.reset.gradient.html36
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/initial.reset.path.html32
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/initial.reset.path.pngbin0 -> 117 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/initial.reset.pattern.html36
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/initial.reset.same.html32
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/initial.reset.same.pngbin0 -> 117 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/initial.reset.transform.html32
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/security.dataURI.html40
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/security.drawImage.canvas.sub.html35
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/security.drawImage.image.sub.html30
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/security.pattern.canvas.fillStyle.sub.html37
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/security.pattern.canvas.strokeStyle.sub.html37
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/security.pattern.canvas.timing.sub.html40
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/security.pattern.create.sub.html31
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/security.pattern.cross.sub.html38
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/security.pattern.image.fillStyle.sub.html32
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/security.pattern.image.strokeStyle.sub.html32
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/security.reset.sub.html32
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.default.html30
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.default.pngbin0 -> 272 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.get.pngbin0 -> 125 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.idl.html50
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.idl.set.zero.html30
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.decimal.html31
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.decimal.pngbin0 -> 137 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.em.html31
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.em.pngbin0 -> 137 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.empty.html30
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.empty.pngbin0 -> 272 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.exp.html31
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.exp.pngbin0 -> 137 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.hex.html31
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.junk.html30
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.junk.pngbin0 -> 272 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.minus.html30
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.minus.pngbin0 -> 272 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.octal.html31
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.octal.pngbin0 -> 137 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.onlyspace.html30
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.onlyspace.pngbin0 -> 272 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.percent.html31
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.percent.pngbin0 -> 137 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.plus.html31
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.plus.pngbin0 -> 137 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.space.html31
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.space.pngbin0 -> 137 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.trailingjunk.html31
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.trailingjunk.pngbin0 -> 137 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.whitespace.html33
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.whitespace.pngbin0 -> 137 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.zero.html31
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.reflect.setcontent.html32
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.reflect.setcontent.pngbin0 -> 125 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.reflect.setidl.html32
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.reflect.setidl.pngbin0 -> 125 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.reflect.setidlzero.html32
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.removed.html29
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.removed.pngbin0 -> 168 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.set.pngbin0 -> 125 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.decimal.html33
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.decimal.pngbin0 -> 137 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.em.html33
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.em.pngbin0 -> 137 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.empty.html32
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.empty.pngbin0 -> 272 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.exp.html33
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.exp.pngbin0 -> 137 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.hex.html33
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.junk.html32
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.junk.pngbin0 -> 272 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.minus.html32
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.minus.pngbin0 -> 272 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.octal.html33
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.octal.pngbin0 -> 137 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.onlyspace.html32
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.onlyspace.pngbin0 -> 272 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.percent.html33
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.percent.pngbin0 -> 137 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.plus.html33
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.plus.pngbin0 -> 137 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.space.html33
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.space.pngbin0 -> 137 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.trailingjunk.html33
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.trailingjunk.pngbin0 -> 137 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.whitespace.html33
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.whitespace.pngbin0 -> 137 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.zero.html33
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.style.html28
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.style.pngbin0 -> 117 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.arguments.1.html28
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.arguments.2.html28
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.arguments.3.html29
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.bogustype.html28
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.default.html28
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.jpeg.alpha.html45
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.jpeg.alpha.pngbin0 -> 208 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.jpeg.primarycolours.html48
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.jpeg.primarycolours.pngbin0 -> 220 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.jpeg.quality.basic.html56
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.jpeg.quality.basic.pngbin0 -> 213 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.jpeg.quality.notnumber.html42
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.jpeg.quality.outsiderange.html43
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.lowercase.ascii.html35
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.lowercase.unicode.html32
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.nocontext.html29
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.png.complexcolours.html48
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.png.complexcolours.pngbin0 -> 242 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.png.html28
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.png.primarycolours.html48
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.png.primarycolours.pngbin0 -> 220 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.unrecognised.html28
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.zeroheight.html28
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.zerosize.html28
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.zerowidth.html28
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/type.delete.html28
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/type.exists.html27
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/type.extend.html28
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/type.name.html27
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/type.prototype.html36
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/type.replace.html28
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-embed-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-embed-element/embed-dimension.html20
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-embed-element/embed-represent-nothing-01.html18
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-embed-element/embed-represent-nothing-02.html22
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-embed-element/embed-represent-nothing-03.html20
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-embed-element/embed-represent-nothing-04.html20
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-embed-element/embed-represent-nothing-ref.html7
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-iframe-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-iframe-element/iframe_javascript_url_01.htm55
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_allow_script.html39
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-iframe-element/move_iframe_in_dom_01.html20
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-iframe-element/move_iframe_in_dom_02.html22
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-iframe-element/move_iframe_in_dom_03.html20
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-iframe-element/move_iframe_in_dom_04.html22
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-iframe-element/support/blank.htm1
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-iframe-element/support/sandbox_allow_script.html8
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/3.jpgbin0 -> 91072 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/brokenimg.jpg4
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/contains.json60
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/current-pixel-density/basic.html33
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/current-pixel-density/error.html30
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/environment-changes/iframed.sub.html78
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/environment-changes/viewport-change.html65
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/image-1.jpgbin0 -> 389245 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/img.complete.html82
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/relevant-mutations.html386
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/sizes/parse-a-sizes-attribute.html42
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/sizes/sizes-iframed.sub.html170
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/srcset/common.js25
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/srcset/parse-a-srcset-attribute.html244
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/srcset/select-an-image-source.html20
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/update-the-source-set.html140
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-map-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-object-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-object-element/object-attributes.html50
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-object-element/object-events.html65
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-object-element/object-fallback.html41
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-object-element/object-handler.html33
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-object-element/test0.html10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-object-element/test1.html9
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-object-element/test2.html4
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-param-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-source-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-track-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-video-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-video-element/video-tabindex.html18
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-video-element/video_content-ref.htm12
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-video-element/video_content_image.htm16
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-video-element/video_content_text.htm16
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-video-element/video_dynamic_poster-ref.htm5
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-video-element/video_dynamic_poster_absolute.htm12
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-video-element/video_dynamic_poster_relative.htm12
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-video-element/video_initially_paused-ref.html8
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-video-element/video_initially_paused.html21
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/attributes-common-to-form-controls/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/attributes-common-to-form-controls/contains.json34
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/attributes-common-to-form-controls/dirname-ltr-iframe.html4
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/attributes-common-to-form-controls/dirname-ltr.html29
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/attributes-common-to-form-controls/dirname-rtl-manual.html26
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/attributes-common-to-form-controls/disabled-elements-01.html84
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/attributes-common-to-form-controls/formAction_document_address.html74
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/attributes-common-to-form-controls/formaction.html42
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/categories/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/constraints/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/constraints/contains.json18
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-checkValidity.html145
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-reportValidity.html145
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-validate.html122
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-validity-badInput.html46
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-validity-customError.html48
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-validity-patternMismatch.html27
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-validity-rangeOverflow.html116
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-validity-rangeUnderflow.html113
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-validity-stepMismatch.html87
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-validity-tooLong.html48
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-validity-tooShort.html50
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-validity-typeMismatch.html41
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-validity-valid.html133
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-validity-valueMissing.html160
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-willValidate.html90
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/constraints/inputwillvalidate.html26
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/constraints/support/validator.js369
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/form-control-infrastructure/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/form-control-infrastructure/contains.json14
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/form-control-infrastructure/form.html46
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/form-submission-0/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/form-submission-0/contains.json30
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/introduction-1/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/introduction-1/contains.json34
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/resetting-a-form/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/resetting-a-form/reset-form.html105
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/original-id.json1
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/select-event.html45
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/selection-not-application-textarea.html20
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/selection-not-application.html48
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/selection.html144
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/textfieldselection-setRangeText.html120
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/textfieldselection-setSelectionRange.html224
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-button-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-button-element/button-events.html66
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-button-element/button-validation.html29
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-datalist-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-datalist-element/datalistoptions.html43
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-fieldset-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-fieldset-element/HTMLFieldSetElement.html54
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-fieldset-element/disabled.html71
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-form-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-form-element/form-autocomplete.html58
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-form-element/form-elements-interfaces-01.html20
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-form-element/form-elements-matches.html46
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-form-element/form-elements-nameditem-01.html43
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-form-element/form-elements-nameditem-02.html28
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-form-element/form-nameditem.html239
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/button.html66
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/checkbox.html110
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/checked.xhtml19
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/color.html45
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/contains.json154
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/date.html90
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/datetime-2.html45
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/datetime-local.html36
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/datetime.html106
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/email.html58
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/file-manual.html30
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/files.html49
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/hidden.html74
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/image01-ref.html5
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/image01.html7
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/input-textselection-01.html42
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/input-type-button.html51
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/input-type-checkbox.html60
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/month.html93
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/number.html53
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/password.html79
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/pattern_attribute.html34
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/radio-groupname-case.html75
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/radio.html137
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/range-2.html43
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/range.html276
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/required_attribute.html34
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/reset.html113
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/search_input.html35
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/telephone.html84
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/text.html104
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/time-2.html42
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/time.html207
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/type-change-state.html58
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/url.html59
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/valueMode.html72
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/week.html38
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-keygen-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-label-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-label-element/label-attributes.html124
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-label-element/labelable-elements.html96
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-legend-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-meter-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-meter-element/meter.html242
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-optgroup-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-option-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-option-element/option-label-value.js82
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-option-element/option-label.html12
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-option-element/option-text-backslash.html15
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-option-element/option-text-label.html23
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-option-element/option-text-recurse.html77
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-option-element/option-text-spaces.html75
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-option-element/option-value.html12
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-output-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-output-element/output.html39
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-progress-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-progress-element/progress-2.html34
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-progress-element/progress.html74
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-select-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-select-element/common-HTMLOptionsCollection-namedItem.html62
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-select-element/common-HTMLOptionsCollection.html70
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-select-element/select-named-getter.html46
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-select-element/select-remove.html64
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-textarea-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-textarea-element/textarea-newline-bidi-ref.html19
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-textarea-element/textarea-newline-bidi.html23
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-textarea-element/textarea-type.html16
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-textarea-element/wrap-reflect-1-ref.html5
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-textarea-element/wrap-reflect-1a.html8
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-textarea-element/wrap-reflect-1b.html8
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/grouping-content/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/grouping-content/the-blockquote-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/grouping-content/the-dd-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/grouping-content/the-dd-element/grouping-dd.html27
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/grouping-content/the-div-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/grouping-content/the-div-element/grouping-div.html28
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/grouping-content/the-dl-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/grouping-content/the-dl-element/grouping-dl.html30
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/grouping-content/the-dt-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/grouping-content/the-dt-element/grouping-dt.html28
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/grouping-content/the-figcaption-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/grouping-content/the-figcaption-element/grouping-figcaption.html28
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/grouping-content/the-figure-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/grouping-content/the-figure-element/grouping-figure.html29
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/grouping-content/the-hr-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/grouping-content/the-hr-element/grouping-hr.html30
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/grouping-content/the-li-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/grouping-content/the-li-element/grouping-li-novalue-manual.html148
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/grouping-content/the-li-element/grouping-li-reftest-001-ref.html49
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/grouping-content/the-li-element/grouping-li-reftest-001.html49
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/grouping-content/the-li-element/grouping-li-reftest-002-ref.html35
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/grouping-content/the-li-element/grouping-li-reftest-002.html36
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/grouping-content/the-li-element/grouping-li.html205
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/grouping-ol-rev-reftest-001-ref.html54
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/grouping-ol-rev-reftest-001.html59
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/grouping-ol-start-reftest-001-ref.html58
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/grouping-ol-start-reftest-001.html64
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/grouping-ol-start-reftest-002-ref.html58
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/grouping-ol-start-reftest-002.html61
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/grouping-ol-type-reftest-001-ref.html56
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/grouping-ol-type-reftest-001.html58
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/grouping-ol-type-reftest-002-ref.html63
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/grouping-ol-type-reftest-002.html65
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/grouping-ol-type-reftest-003-ref.html79
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/grouping-ol-type-reftest-003.html81
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/grouping-ol.html314
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/ol.start-reflection-1.html26
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/ol.start-reflection-2.html26
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/reversed-1-ref.html6
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/reversed-1a.html6
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/reversed-1b.html11
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/reversed-1c.html12
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/reversed-2-ref.html6
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/reversed-2.html7
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/grouping-content/the-p-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/grouping-content/the-p-element/grouping-p.html28
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/grouping-content/the-pre-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/grouping-content/the-pre-element/grouping-pre-reftest-001-ref.html23
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/grouping-content/the-pre-element/grouping-pre-reftest-001.html23
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/grouping-content/the-pre-element/grouping-pre.html28
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/grouping-content/the-pre-element/pre-newline-bidi-ref.html19
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/grouping-content/the-pre-element/pre-newline-bidi.html23
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ul-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ul-element/grouping-ul.html28
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/interactive-elements/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/interactive-elements/commands/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/interactive-elements/commands/contains.json38
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/interactive-elements/the-command-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/interactive-elements/the-details-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/interactive-elements/the-details-element/details.html47
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/interactive-elements/the-details-element/toggleEvent.html93
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/interactive-elements/the-dialog-element/contains.json6
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/interactive-elements/the-dialog-element/dialog-close.html78
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/interactive-elements/the-dialog-element/dialog-showModal.html125
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/interactive-elements/the-menu-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/interactive-elements/the-menu-element/contains.json18
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/interactive-elements/the-summary-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/interfaces.html30
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/interfaces.js138
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/links/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/links/downloading-resources/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/links/downloading-resources/contains.json6
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/links/following-hyperlinks/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/links/introduction-3/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/links/links-created-by-a-and-area-elements/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/links/linktypes/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/links/linktypes/contains.json68
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/links/linktypes/original-id.json1
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-noscript-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/async_001.htm18
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/async_002.htm31
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/async_003.htm39
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/async_004.htm37
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/async_005.htm39
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/async_006.htm45
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/async_007.htm48
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/async_008.htm47
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/async_009.htm25
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/async_010.htm54
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/async_011.htm19
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/contains.json18
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/log.py13
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/script-before-after-events.html55
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/script-for-event.html93
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/script-for-event.xhtml22
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/script-language-type.html18
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/script-languages-01.html24
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/script-languages-02.html98
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/script-noembed-noframes-iframe.xhtml36
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/script-onload-string.html17
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/script-text.html53
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/script-text.xhtml28
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/additions-to-parsing-xhtml-documents/node-document.html148
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/additions-to-parsing-xhtml-documents/template-child-nodes.html103
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/additions-to-serializing-xhtml-documents/outerhtml.html72
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/additions-to-the-css-user-agent-style-sheet/css-user-agent-style-sheet-test-001-ref.html6
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/additions-to-the-css-user-agent-style-sheet/css-user-agent-style-sheet-test-001.html12
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/additions-to-the-css-user-agent-style-sheet/css-user-agent-style-sheet-test-002.html12
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/additions-to-the-css-user-agent-style-sheet/css-user-agent-style-sheet-test-003.html19
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/additions-to-the-steps-to-clone-a-node/template-clone-children.html83
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/additions-to-the-steps-to-clone-a-node/templates-copy-document-owner.html127
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/definitions/template-contents-owner-document-type.html72
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/definitions/template-contents-owner-test-001.html45
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/definitions/template-contents-owner-test-002.html69
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/definitions/template-contents.html173
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/innerhtml-on-templates/innerhtml.html87
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/end-template-tag-in-body.html12
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/end-template-tag-in-head.html12
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/frameset-end-tag.html10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/head-template-contents-div-no-end-tag.html12
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/head-template-contents-table-no-end-tag.html14
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/html-start-tag.html10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-child-nodes-div.xhtml14
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-child-nodes-nested.xhtml16
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-contents-attribute.html10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-contents-body.html10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-contents-div-no-end-tag.html12
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-contents-empty.html11
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-contents-frameset.html10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-contents-head.html10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-contents-html.html10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-contents-nested.html10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-contents-table-no-end-tag.html14
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-contents-text.html10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-contents.html12
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-descendant-body.html12
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-descendant-frameset.html12
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-descendant-head.html13
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/two-templates.html17
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/serializing-html-templates/outerhtml.html71
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/template-element/content-attribute.html115
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/template-element/node-document-changes.html200
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/template-element/template-as-a-descendant.html115
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/template-element/template-content-node-document.html60
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/template-element/template-content.html78
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/template-element/template-descendant-body.html27
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/template-element/template-descendant-frameset.html63
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/template-element/template-descendant-head.html27
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/testcommon.js191
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/sections/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/sections/headings-and-sections/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/sections/headings-and-sections/contains.json6
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/sections/the-address-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/sections/the-article-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/sections/the-aside-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/sections/the-body-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/sections/the-footer-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/sections/the-h1-h2-h3-h4-h5-and-h6-elements/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/sections/the-h1-h2-h3-h4-h5-and-h6-elements/original-id.json1
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/sections/the-header-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/sections/the-hgroup-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/sections/the-nav-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/sections/the-section-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/sections/usage-summary-0/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/selectors/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/selectors/case-sensitivity/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/checked.html43
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/default.html61
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/dir.html36
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/dir01.html18
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/disabled.html57
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/enabled.html42
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/focus-iframe.html5
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/focus.html42
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/indeterminate.html37
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/inrange-outofrange.html27
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/link.html24
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/readwrite-readonly.html71
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/required-optional.html35
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/utils.js14
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/valid-invalid.html68
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/tabular-data/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/tabular-data/attributes-common-to-td-and-th-elements/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/tabular-data/attributes-common-to-td-and-th-elements/cellIndex.html41
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/tabular-data/examples/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/tabular-data/processing-model-1/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/tabular-data/processing-model-1/contains.json10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/tabular-data/the-caption-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/tabular-data/the-caption-element/caption_001.html69
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/tabular-data/the-col-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/tabular-data/the-colgroup-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/tabular-data/the-table-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/tabular-data/the-table-element/caption-methods.html56
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/tabular-data/the-table-element/contains.json10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/tabular-data/the-table-element/createTBody.html165
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/tabular-data/the-table-element/insertRow-method-01.html24
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/tabular-data/the-table-element/insertRow-method-02.html34
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/tabular-data/the-table-element/tBodies.html40
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/tabular-data/the-table-element/table-insertRow.html56
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/tabular-data/the-table-element/table-rows.html186
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/tabular-data/the-tbody-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/tabular-data/the-td-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/tabular-data/the-tfoot-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/tabular-data/the-th-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/tabular-data/the-thead-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/tabular-data/the-tr-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/tabular-data/the-tr-element/rowIndex.html77
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/tabular-data/the-tr-element/sectionRowIndex.html130
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-a-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-a-element/a-stringifier.html16
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-a-element/a.text-getter-01.html34
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-a-element/a.text-setter-01.html41
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-abbr-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-b-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-auto-dir-default-ref.html36
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-auto-dir-default.html46
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-missing-pdf-ref.html44
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-missing-pdf.html56
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-nested-ref.html44
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-nested.html52
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-number-ref.html44
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-number.html53
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-separate-ref.html36
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-separate.html47
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-another-bdi-1-ref.html47
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-another-bdi-1.html58
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-another-bdi-2-ref.html47
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-another-bdi-2.html59
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-letter-following-1-ref.html45
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-letter-following-1.html54
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-letter-following-2-ref.html45
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-letter-following-2.html54
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-letter-preceding-1-ref.html45
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-letter-preceding-1.html54
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-letter-preceding-2-ref.html45
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-letter-preceding-2.html54
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-number-following-1-ref.html45
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-number-following-1.html54
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-number-following-2-ref.html45
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-number-following-2.html53
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-surrounding-run-ref.html44
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-surrounding-run.html56
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-wrapped-ref.html52
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-wrapped.html73
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-paragraph-level-container-ref.html36
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-paragraph-level-container.html46
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdo-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdo-element/bdo-child.html17
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdo-element/bdo-ltr.html15
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdo-element/bdo-override.html18
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdo-element/bidi-001-ref.html11
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdo-element/bidi-001.html14
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-br-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-br-element/br-bidi-in-inline-ancestors-ref.html38
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-br-element/br-bidi-in-inline-ancestors.html59
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-br-element/br-bidi-ref.html19
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-br-element/br-bidi.html22
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-cite-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-code-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-dfn-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-em-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-i-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-kbd-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-mark-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-q-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-rp-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-rt-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-ruby-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-s-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-samp-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-small-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-span-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-strong-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-sub-and-sup-elements/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-time-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-time-element/001.html68
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-u-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-var-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-wbr-element/wbr-element-ref.html10
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-wbr-element/wbr-element.html11
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/text-level-semantics/usage-summary/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/the-root-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/the-root-element/the-html-element/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/support/encodingtests-1.css4
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/support/encodingtests-15-inverse.css4
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/support/encodingtests-15.css4
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/support/encodingtests-utf8.css4
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-001.html37
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-001.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-003.htmlbin0 -> 2624 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-004.htmlbin0 -> 2612 bytes
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-007.html37
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-007.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-009.html37
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-009.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-015.html35
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-015.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-016.html38
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-016.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-018.html38
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-018.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-030.html38
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-030.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-034.html39
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-034.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-037.html37
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-037.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-038.html38
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-038.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/Document.getElementsByTagName-foreign-01.html143
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/Document.getElementsByTagName-foreign-02.html24
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/Element.getElementsByTagName-foreign-01.html25
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/Element.getElementsByTagName-foreign-02.html29
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/README4
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/common.js24
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/contains.json490
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/foreign_content_001.html43
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/foreign_content_003.html47
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/foreign_content_004.html65
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/foreign_content_005.html45
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/foreign_content_006.html38
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/foreign_content_008.html39
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/foreign_content_009.html46
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/foreign_content_010.html44
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/foreign_content_011.html26
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/foreign_content_013.html26
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_adoption01.html28
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_adoption02.html28
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_comments01.html28
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_doctype01.html28
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_domjs-unsafe.html28
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_entities01.html28
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_entities02.html28
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_html5test-com.html28
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_inbody01.html28
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_innerHTML_tests4.html24
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_innerHTML_tests6.html24
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_innerHTML_tests7.html24
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_innerHTML_tests_innerHTML_1.html24
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_isindex.html28
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_main-element.html28
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_pending-spec-changes-plain-text-unsafe.html28
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_pending-spec-changes.html28
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_plain-text-unsafe.html28
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_scriptdata01.html28
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_scripted_adoption01.html28
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_scripted_ark.html28
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_scripted_webkit01.html28
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tables01.html28
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_template.html28
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests1.html28
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests10.html28
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests11.html28
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests12.html28
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests14.html28
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests15.html28
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests16.html28
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests17.html28
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests18.html28
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests19.html28
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests2.html28
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests20.html28
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests21.html28
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests22.html28
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests23.html28
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests24.html28
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests25.html28
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests26.html28
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests3.html28
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests5.html28
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests6.html28
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests7.html28
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests8.html28
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests9.html28
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tricky01.html28
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_webkit01.html28
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_webkit02.html28
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/math-parse01.html62
-rwxr-xr-xtests/wpt/web-platform-tests/html/syntax/parsing/math-parse03.html132
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/named-character-references-data.js2233
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/named-character-references.html36
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/template.js214
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/template/additions-to-foster-parenting/template-is-a-foster-parent-element.html64
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/template/additions-to-foster-parenting/template-is-not-a-foster-parent-element.html71
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/generating-of-implied-end-tags.html137
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/ignore-body-token.html133
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/ignore-frameset-token.html126
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/ignore-head-token.html130
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/ignore-html-token.html159
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/start-tag-body.html98
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/start-tag-html.html39
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/template-end-tag-without-start-one.html103
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/template/additions-to-the-in-frameset-insertion-mode/end-tag-frameset.html33
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/template/additions-to-the-in-head-insertion-mode/generating-of-implied-end-tags.html138
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/template/additions-to-the-in-head-insertion-mode/template-end-tag-without-start-one.html102
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/template/additions-to-the-in-table-insertion-mode/end-tag-table.html43
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/template/appending-to-a-template/template-child-nodes.html117
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/template/clearing-the-stack-back-to-a-given-context/clearing-stack-back-to-a-table-body-context.html183
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/template/clearing-the-stack-back-to-a-given-context/clearing-stack-back-to-a-table-context.html85
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/template/clearing-the-stack-back-to-a-given-context/clearing-stack-back-to-a-table-row-context.html72
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/template/creating-an-element-for-the-token/template-owner-document.html242
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/test.js326
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/parsing/the-end.html40
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/serializing-html-fragments/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/serializing-html-fragments/outerHTML.html171
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/writing/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/writing/cdata-sections/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/writing/character-references/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/writing/comments/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/writing/elements-0/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/writing/elements-0/contains.json26
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/writing/text/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/writing/text/contains.json6
-rw-r--r--tests/wpt/web-platform-tests/html/syntax/writing/the-doctype/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/the-xhtml-syntax/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/the-xhtml-syntax/parsing-xhtml-documents/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/the-xhtml-syntax/parsing-xhtml-fragments/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/the-xhtml-syntax/serializing-xhtml-fragments/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/the-xhtml-syntax/writing-xhtml-documents/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/tools/html5lib_test.xml29
-rw-r--r--tests/wpt/web-platform-tests/html/tools/html5lib_test_fragment.xml27
-rw-r--r--tests/wpt/web-platform-tests/html/tools/update_html5lib_tests.py152
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/atob/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/atob/base64.html306
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/scripting/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/scripting/enabling-and-disabling-scripting/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/scripting/event-loops/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/scripting/event-loops/contains.json14
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/scripting/events/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/scripting/events/body-onload.html20
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/scripting/events/contains.json18
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/scripting/events/event-handler-javascript.html20
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/scripting/events/event-handler-spec-example.html65
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/scripting/introduction-5/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/scripting/javascript-protocol/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/addEventListener.html32
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/body-onerror-compile-error-data-url.html37
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/body-onerror-compile-error.html39
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/body-onerror-runtime-error.html39
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-cross-origin-setInterval.html34
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-cross-origin-setTimeout.html32
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-cross-origin.html38
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-data-url.html36
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-in-attribute.html39
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-in-body-onerror.html28
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-in-setInterval.html39
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-in-setTimeout.html36
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-same-origin.html36
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error.html38
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/contains.json28
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/runtime-error-cross-origin-setInterval.html34
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/runtime-error-cross-origin-setTimeout.html32
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/runtime-error-cross-origin.html38
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/runtime-error-data-url.html36
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/runtime-error-in-attribute.html39
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/runtime-error-in-body-onerror.html25
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/runtime-error-in-setInterval.html39
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/runtime-error-in-setTimeout.html36
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/runtime-error-in-window-onerror.html29
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/runtime-error-same-origin.html36
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/runtime-error.html38
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/support/syntax-error-in-setInterval.js9
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/support/syntax-error-in-setTimeout.js8
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/support/syntax-error.js1
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/support/undefined-variable-in-setInterval.js9
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/support/undefined-variable-in-setTimeout.js8
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/support/undefined-variable.js1
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/window-onerror-parse-error.html40
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/window-onerror-runtime-error-throw.html39
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/window-onerror-runtime-error.html43
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-external-interface/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID.html10
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID.js50
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID.worker.js4
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/contains.json22
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/content.html136
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/content/001.xhtml16
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/content/002.xhtml19
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/content/003.xhtml18
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/content/004.xhtml18
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/content/005.xhtml18
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/content/006.xhtml18
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/navigator-indexed.html28
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol.html214
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol/001.xhtml17
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol/002.xhtml19
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol/003.xhtml18
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol/004.xhtml18
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol/005.xhtml18
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol/006.xhtml19
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/timers/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/timers/evil-spec-example.html23
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/user-prompts/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/user-prompts/dialogs-implemented-using-separate-documents/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/user-prompts/printing/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/html/webappapis/user-prompts/simple-dialogs/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/http/content_length.html13
-rw-r--r--tests/wpt/web-platform-tests/http/content_length.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/images/anim-gr.gifbin0 -> 241 bytes
-rw-r--r--tests/wpt/web-platform-tests/images/anim-gr.pngbin0 -> 460 bytes
-rw-r--r--tests/wpt/web-platform-tests/images/anim-poster-gr.pngbin0 -> 422 bytes
-rw-r--r--tests/wpt/web-platform-tests/images/background.pngbin0 -> 86 bytes
-rw-r--r--tests/wpt/web-platform-tests/images/black-rectangle.pngbin0 -> 307 bytes
-rw-r--r--tests/wpt/web-platform-tests/images/blue-area.pngbin0 -> 1469 bytes
-rw-r--r--tests/wpt/web-platform-tests/images/blue-border.pngbin0 -> 1823 bytes
-rw-r--r--tests/wpt/web-platform-tests/images/blue.pngbin0 -> 485 bytes
-rw-r--r--tests/wpt/web-platform-tests/images/blue96x96.pngbin0 -> 1010 bytes
-rw-r--r--tests/wpt/web-platform-tests/images/broken.pngbin0 -> 87 bytes
-rw-r--r--tests/wpt/web-platform-tests/images/canvas-line.pngbin0 -> 502 bytes
-rw-r--r--tests/wpt/web-platform-tests/images/fail.gifbin0 -> 24480 bytes
-rw-r--r--tests/wpt/web-platform-tests/images/ggrr-256x256.pngbin0 -> 120 bytes
-rw-r--r--tests/wpt/web-platform-tests/images/green-100x50.pngbin0 -> 218 bytes
-rw-r--r--tests/wpt/web-platform-tests/images/green-16x16.pngbin0 -> 92 bytes
-rw-r--r--tests/wpt/web-platform-tests/images/green-1x1.pngbin0 -> 82 bytes
-rw-r--r--tests/wpt/web-platform-tests/images/green-256x256.pngbin0 -> 103 bytes
-rw-r--r--tests/wpt/web-platform-tests/images/green-2x2.pngbin0 -> 118 bytes
-rw-r--r--tests/wpt/web-platform-tests/images/green.pngbin0 -> 87 bytes
-rw-r--r--tests/wpt/web-platform-tests/images/green.svg3
-rw-r--r--tests/wpt/web-platform-tests/images/grgr-256x256.pngbin0 -> 130 bytes
-rw-r--r--tests/wpt/web-platform-tests/images/movie_300_frame_0.pngbin0 -> 11493 bytes
-rw-r--r--tests/wpt/web-platform-tests/images/red-16x16.pngbin0 -> 130 bytes
-rw-r--r--tests/wpt/web-platform-tests/images/red-zeroheight.svg3
-rw-r--r--tests/wpt/web-platform-tests/images/red-zerosize.svg3
-rw-r--r--tests/wpt/web-platform-tests/images/red-zerowidth.svg3
-rw-r--r--tests/wpt/web-platform-tests/images/red.pngbin0 -> 87 bytes
-rw-r--r--tests/wpt/web-platform-tests/images/redtransparent.pngbin0 -> 109 bytes
-rw-r--r--tests/wpt/web-platform-tests/images/rgrg-256x256.pngbin0 -> 131 bytes
-rw-r--r--tests/wpt/web-platform-tests/images/rrgg-256x256.pngbin0 -> 120 bytes
-rw-r--r--tests/wpt/web-platform-tests/images/smiley.pngbin0 -> 1852 bytes
-rw-r--r--tests/wpt/web-platform-tests/images/threecolors.pngbin0 -> 242 bytes
-rw-r--r--tests/wpt/web-platform-tests/images/transparent.pngbin0 -> 100 bytes
-rw-r--r--tests/wpt/web-platform-tests/images/transparent50.pngbin0 -> 155 bytes
-rw-r--r--tests/wpt/web-platform-tests/images/yellow.pngbin0 -> 95 bytes
-rw-r--r--tests/wpt/web-platform-tests/images/yellow75.pngbin0 -> 150 bytes
-rw-r--r--tests/wpt/web-platform-tests/infrastructure/failing-test.html10
-rw-r--r--tests/wpt/web-platform-tests/js/builtins/Array.DefineOwnProperty.html24
-rw-r--r--tests/wpt/web-platform-tests/js/builtins/Array.prototype.join-order.html86
-rw-r--r--tests/wpt/web-platform-tests/js/builtins/Math.max.html13
-rw-r--r--tests/wpt/web-platform-tests/js/builtins/Math.maxmin.js57
-rw-r--r--tests/wpt/web-platform-tests/js/builtins/Math.min.html13
-rw-r--r--tests/wpt/web-platform-tests/js/builtins/Object.prototype.freeze.html52
-rw-r--r--tests/wpt/web-platform-tests/js/builtins/Object.prototype.hasOwnProperty-order.html21
-rw-r--r--tests/wpt/web-platform-tests/js/builtins/Object.prototype.hasOwnProperty-prototype-chain.html44
-rw-r--r--tests/wpt/web-platform-tests/js/builtins/Object.prototype.preventExtensions.html51
-rw-r--r--tests/wpt/web-platform-tests/js/builtins/Object.prototype.seal.html51
-rw-r--r--tests/wpt/web-platform-tests/js/builtins/WeakMap.prototype-properties.html122
-rwxr-xr-xtests/wpt/web-platform-tests/lint6
-rwxr-xr-xtests/wpt/web-platform-tests/manifest6
-rw-r--r--tests/wpt/web-platform-tests/media-source/SourceBuffer-abort-readyState.html71
-rw-r--r--tests/wpt/web-platform-tests/media-source/SourceBuffer-abort-removed.html52
-rw-r--r--tests/wpt/web-platform-tests/media-source/SourceBuffer-abort-updating.html92
-rw-r--r--tests/wpt/web-platform-tests/media-source/SourceBuffer-abort.html34
-rw-r--r--tests/wpt/web-platform-tests/media-source/URL-createObjectURL-null.html19
-rw-r--r--tests/wpt/web-platform-tests/media-source/URL-createObjectURL-revoke.html22
-rw-r--r--tests/wpt/web-platform-tests/media-source/URL-createObjectURL.html20
-rwxr-xr-xtests/wpt/web-platform-tests/media-source/import_tests.sh52
-rw-r--r--tests/wpt/web-platform-tests/media-source/index.html93
-rw-r--r--tests/wpt/web-platform-tests/media-source/interfaces.html145
-rw-r--r--tests/wpt/web-platform-tests/media-source/manifest.txt32
-rw-r--r--tests/wpt/web-platform-tests/media-source/mediasource-addsourcebuffer.html153
-rw-r--r--tests/wpt/web-platform-tests/media-source/mediasource-append-buffer.html538
-rw-r--r--tests/wpt/web-platform-tests/media-source/mediasource-appendwindow.html175
-rw-r--r--tests/wpt/web-platform-tests/media-source/mediasource-buffered.html219
-rw-r--r--tests/wpt/web-platform-tests/media-source/mediasource-closed.html139
-rw-r--r--tests/wpt/web-platform-tests/media-source/mediasource-config-change-mp4-a-bitrate.html16
-rw-r--r--tests/wpt/web-platform-tests/media-source/mediasource-config-change-mp4-av-audio-bitrate.html16
-rw-r--r--tests/wpt/web-platform-tests/media-source/mediasource-config-change-mp4-av-framesize.html16
-rw-r--r--tests/wpt/web-platform-tests/media-source/mediasource-config-change-mp4-av-video-bitrate.html16
-rw-r--r--tests/wpt/web-platform-tests/media-source/mediasource-config-change-mp4-v-bitrate.html16
-rw-r--r--tests/wpt/web-platform-tests/media-source/mediasource-config-change-mp4-v-framerate.html16
-rw-r--r--tests/wpt/web-platform-tests/media-source/mediasource-config-change-mp4-v-framesize.html16
-rw-r--r--tests/wpt/web-platform-tests/media-source/mediasource-config-change-webm-a-bitrate.html16
-rw-r--r--tests/wpt/web-platform-tests/media-source/mediasource-config-change-webm-av-audio-bitrate.html16
-rw-r--r--tests/wpt/web-platform-tests/media-source/mediasource-config-change-webm-av-framesize.html16
-rw-r--r--tests/wpt/web-platform-tests/media-source/mediasource-config-change-webm-av-video-bitrate.html16
-rw-r--r--tests/wpt/web-platform-tests/media-source/mediasource-config-change-webm-v-bitrate.html16
-rw-r--r--tests/wpt/web-platform-tests/media-source/mediasource-config-change-webm-v-framerate.html16
-rw-r--r--tests/wpt/web-platform-tests/media-source/mediasource-config-change-webm-v-framesize.html16
-rw-r--r--tests/wpt/web-platform-tests/media-source/mediasource-config-changes.js101
-rw-r--r--tests/wpt/web-platform-tests/media-source/mediasource-duration-boundaryconditions.html62
-rw-r--r--tests/wpt/web-platform-tests/media-source/mediasource-duration.html217
-rw-r--r--tests/wpt/web-platform-tests/media-source/mediasource-endofstream-invaliderror.html52
-rw-r--r--tests/wpt/web-platform-tests/media-source/mediasource-getvideoplaybackquality.html71
-rw-r--r--tests/wpt/web-platform-tests/media-source/mediasource-is-type-supported.html80
-rw-r--r--tests/wpt/web-platform-tests/media-source/mediasource-multiple-attach.html113
-rw-r--r--tests/wpt/web-platform-tests/media-source/mediasource-play-then-seek-back.html57
-rw-r--r--tests/wpt/web-platform-tests/media-source/mediasource-play.html44
-rw-r--r--tests/wpt/web-platform-tests/media-source/mediasource-redundant-seek.html72
-rw-r--r--tests/wpt/web-platform-tests/media-source/mediasource-remove.html293
-rw-r--r--tests/wpt/web-platform-tests/media-source/mediasource-removesourcebuffer.html92
-rw-r--r--tests/wpt/web-platform-tests/media-source/mediasource-seek-beyond-duration.html95
-rw-r--r--tests/wpt/web-platform-tests/media-source/mediasource-seek-during-pending-seek.html142
-rw-r--r--tests/wpt/web-platform-tests/media-source/mediasource-sequencemode-append-buffer.html129
-rw-r--r--tests/wpt/web-platform-tests/media-source/mediasource-sourcebuffer-mode.html140
-rw-r--r--tests/wpt/web-platform-tests/media-source/mediasource-sourcebufferlist.html83
-rw-r--r--tests/wpt/web-platform-tests/media-source/mediasource-timestamp-offset.html121
-rw-r--r--tests/wpt/web-platform-tests/media-source/mediasource-util.js431
-rw-r--r--tests/wpt/web-platform-tests/media-source/mp4/test-a-128k-44100Hz-1ch-manifest.json4
-rw-r--r--tests/wpt/web-platform-tests/media-source/mp4/test-a-128k-44100Hz-1ch.mp4bin0 -> 17408 bytes
-rw-r--r--tests/wpt/web-platform-tests/media-source/mp4/test-a-192k-44100Hz-1ch-manifest.json4
-rw-r--r--tests/wpt/web-platform-tests/media-source/mp4/test-a-192k-44100Hz-1ch.mp4bin0 -> 17685 bytes
-rw-r--r--tests/wpt/web-platform-tests/media-source/mp4/test-av-384k-44100Hz-1ch-320x240-30fps-10kfr-manifest.json4
-rw-r--r--tests/wpt/web-platform-tests/media-source/mp4/test-av-384k-44100Hz-1ch-320x240-30fps-10kfr.mp4bin0 -> 81565 bytes
-rw-r--r--tests/wpt/web-platform-tests/media-source/mp4/test-av-384k-44100Hz-1ch-640x480-30fps-10kfr-manifest.json4
-rw-r--r--tests/wpt/web-platform-tests/media-source/mp4/test-av-384k-44100Hz-1ch-640x480-30fps-10kfr.mp4bin0 -> 69474 bytes
-rw-r--r--tests/wpt/web-platform-tests/media-source/mp4/test-av-448k-44100Hz-1ch-640x480-30fps-10kfr-manifest.json4
-rw-r--r--tests/wpt/web-platform-tests/media-source/mp4/test-av-448k-44100Hz-1ch-640x480-30fps-10kfr.mp4bin0 -> 69948 bytes
-rw-r--r--tests/wpt/web-platform-tests/media-source/mp4/test-av-640k-44100Hz-1ch-640x480-30fps-10kfr-manifest.json4
-rw-r--r--tests/wpt/web-platform-tests/media-source/mp4/test-av-640k-44100Hz-1ch-640x480-30fps-10kfr.mp4bin0 -> 95171 bytes
-rw-r--r--tests/wpt/web-platform-tests/media-source/mp4/test-v-128k-320x240-24fps-8kfr-manifest.json4
-rw-r--r--tests/wpt/web-platform-tests/media-source/mp4/test-v-128k-320x240-24fps-8kfr.mp4bin0 -> 38738 bytes
-rw-r--r--tests/wpt/web-platform-tests/media-source/mp4/test-v-128k-320x240-30fps-10kfr-manifest.json4
-rw-r--r--tests/wpt/web-platform-tests/media-source/mp4/test-v-128k-320x240-30fps-10kfr.mp4bin0 -> 34009 bytes
-rw-r--r--tests/wpt/web-platform-tests/media-source/mp4/test-v-128k-640x480-30fps-10kfr-manifest.json4
-rw-r--r--tests/wpt/web-platform-tests/media-source/mp4/test-v-128k-640x480-30fps-10kfr.mp4bin0 -> 27764 bytes
-rw-r--r--tests/wpt/web-platform-tests/media-source/mp4/test-v-256k-320x240-30fps-10kfr-manifest.json4
-rw-r--r--tests/wpt/web-platform-tests/media-source/mp4/test-v-256k-320x240-30fps-10kfr.mp4bin0 -> 55293 bytes
-rw-r--r--tests/wpt/web-platform-tests/media-source/mp4/test.mp4bin0 -> 198320 bytes
-rw-r--r--tests/wpt/web-platform-tests/media-source/webm/test-a-128k-44100Hz-1ch-manifest.json4
-rw-r--r--tests/wpt/web-platform-tests/media-source/webm/test-a-128k-44100Hz-1ch.webmbin0 -> 9840 bytes
-rw-r--r--tests/wpt/web-platform-tests/media-source/webm/test-a-192k-44100Hz-1ch-manifest.json4
-rw-r--r--tests/wpt/web-platform-tests/media-source/webm/test-a-192k-44100Hz-1ch.webmbin0 -> 10735 bytes
-rw-r--r--tests/wpt/web-platform-tests/media-source/webm/test-av-384k-44100Hz-1ch-320x240-30fps-10kfr-manifest.json4
-rw-r--r--tests/wpt/web-platform-tests/media-source/webm/test-av-384k-44100Hz-1ch-320x240-30fps-10kfr.webmbin0 -> 76501 bytes
-rw-r--r--tests/wpt/web-platform-tests/media-source/webm/test-av-384k-44100Hz-1ch-640x480-30fps-10kfr-manifest.json4
-rw-r--r--tests/wpt/web-platform-tests/media-source/webm/test-av-384k-44100Hz-1ch-640x480-30fps-10kfr.webmbin0 -> 80692 bytes
-rw-r--r--tests/wpt/web-platform-tests/media-source/webm/test-av-448k-44100Hz-1ch-640x480-30fps-10kfr-manifest.json4
-rw-r--r--tests/wpt/web-platform-tests/media-source/webm/test-av-448k-44100Hz-1ch-640x480-30fps-10kfr.webmbin0 -> 81467 bytes
-rw-r--r--tests/wpt/web-platform-tests/media-source/webm/test-av-640k-44100Hz-1ch-640x480-30fps-10kfr-manifest.json4
-rw-r--r--tests/wpt/web-platform-tests/media-source/webm/test-av-640k-44100Hz-1ch-640x480-30fps-10kfr.webmbin0 -> 132509 bytes
-rw-r--r--tests/wpt/web-platform-tests/media-source/webm/test-v-128k-320x240-24fps-8kfr-manifest.json4
-rw-r--r--tests/wpt/web-platform-tests/media-source/webm/test-v-128k-320x240-24fps-8kfr.webmbin0 -> 38195 bytes
-rw-r--r--tests/wpt/web-platform-tests/media-source/webm/test-v-128k-320x240-30fps-10kfr-manifest.json4
-rw-r--r--tests/wpt/web-platform-tests/media-source/webm/test-v-128k-320x240-30fps-10kfr.webmbin0 -> 39228 bytes
-rw-r--r--tests/wpt/web-platform-tests/media-source/webm/test-v-128k-640x480-30fps-10kfr-manifest.json4
-rw-r--r--tests/wpt/web-platform-tests/media-source/webm/test-v-128k-640x480-30fps-10kfr.webmbin0 -> 48190 bytes
-rw-r--r--tests/wpt/web-platform-tests/media-source/webm/test-v-256k-320x240-30fps-10kfr-manifest.json4
-rw-r--r--tests/wpt/web-platform-tests/media-source/webm/test-v-256k-320x240-30fps-10kfr.webmbin0 -> 64318 bytes
-rw-r--r--tests/wpt/web-platform-tests/media-source/webm/test-vp8-vorbis-webvtt.webmbin0 -> 143662 bytes
-rw-r--r--tests/wpt/web-platform-tests/media-source/webm/test.webmbin0 -> 219448 bytes
-rw-r--r--tests/wpt/web-platform-tests/media/A4.mp4bin0 -> 53409 bytes
-rw-r--r--tests/wpt/web-platform-tests/media/A4.ogvbin0 -> 94372 bytes
-rw-r--r--tests/wpt/web-platform-tests/media/foo.vtt4
-rw-r--r--tests/wpt/web-platform-tests/media/foo.vtt.headers1
-rw-r--r--tests/wpt/web-platform-tests/media/green-at-15.mp4bin0 -> 299193 bytes
-rw-r--r--tests/wpt/web-platform-tests/media/green-at-15.ogvbin0 -> 287648 bytes
-rw-r--r--tests/wpt/web-platform-tests/media/movie_300.mp4bin0 -> 2757913 bytes
-rw-r--r--tests/wpt/web-platform-tests/media/movie_300.ogvbin0 -> 2344665 bytes
-rw-r--r--tests/wpt/web-platform-tests/media/movie_5.mp4bin0 -> 31603 bytes
-rw-r--r--tests/wpt/web-platform-tests/media/movie_5.ogvbin0 -> 18645 bytes
-rw-r--r--tests/wpt/web-platform-tests/media/poster.pngbin0 -> 14109 bytes
-rw-r--r--tests/wpt/web-platform-tests/media/sound_5.mp3bin0 -> 23442 bytes
-rw-r--r--tests/wpt/web-platform-tests/media/sound_5.ogabin0 -> 18541 bytes
-rw-r--r--tests/wpt/web-platform-tests/media/white.mp4bin0 -> 13713 bytes
-rw-r--r--tests/wpt/web-platform-tests/media/white.webmbin0 -> 10880 bytes
-rw-r--r--tests/wpt/web-platform-tests/mediacapture-streams/mediastreams-as-media-elements/video-assignment-manual.html56
-rw-r--r--tests/wpt/web-platform-tests/mediacapture-streams/obtaining-local-multimedia-content/navigatorusermedia/api-present.html25
-rw-r--r--tests/wpt/web-platform-tests/mediacapture-streams/obtaining-local-multimedia-content/navigatorusermedia/deny.html36
-rw-r--r--tests/wpt/web-platform-tests/mediacapture-streams/obtaining-local-multimedia-content/navigatorusermedia/empty-option-param.html36
-rw-r--r--tests/wpt/web-platform-tests/mediacapture-streams/obtaining-local-multimedia-content/navigatorusermedia/getusermedia-impossible-constraint.html34
-rw-r--r--tests/wpt/web-platform-tests/mediacapture-streams/obtaining-local-multimedia-content/navigatorusermedia/getusermedia-optional-constraint.html33
-rw-r--r--tests/wpt/web-platform-tests/mediacapture-streams/obtaining-local-multimedia-content/navigatorusermedia/getusermedia-trivial-constraint.html32
-rw-r--r--tests/wpt/web-platform-tests/mediacapture-streams/obtaining-local-multimedia-content/navigatorusermedia/unknownkey-option-param.html38
-rw-r--r--tests/wpt/web-platform-tests/mediacapture-streams/stream-api/introduction/disabled-audio-silence.html56
-rw-r--r--tests/wpt/web-platform-tests/mediacapture-streams/stream-api/introduction/disabled-video-black.html57
-rw-r--r--tests/wpt/web-platform-tests/mediacapture-streams/stream-api/mediastream/audio.html36
-rw-r--r--tests/wpt/web-platform-tests/mediacapture-streams/stream-api/mediastream/mediastream-addtrack.html55
-rw-r--r--tests/wpt/web-platform-tests/mediacapture-streams/stream-api/mediastream/mediastream-finished-add.html49
-rw-r--r--tests/wpt/web-platform-tests/mediacapture-streams/stream-api/mediastream/mediastream-gettrackid.html36
-rw-r--r--tests/wpt/web-platform-tests/mediacapture-streams/stream-api/mediastream/mediastream-id-manual.html33
-rw-r--r--tests/wpt/web-platform-tests/mediacapture-streams/stream-api/mediastream/mediastream-idl.html53
-rw-r--r--tests/wpt/web-platform-tests/mediacapture-streams/stream-api/mediastream/mediastream-removetrack.html49
-rw-r--r--tests/wpt/web-platform-tests/mediacapture-streams/stream-api/mediastream/stream-ended.html37
-rw-r--r--tests/wpt/web-platform-tests/mediacapture-streams/stream-api/mediastream/video.html34
-rw-r--r--tests/wpt/web-platform-tests/mediacapture-streams/stream-api/mediastreamtrack/mediastreamtrack-end.html40
-rw-r--r--tests/wpt/web-platform-tests/mediacapture-streams/stream-api/mediastreamtrack/mediastreamtrack-id.html29
-rw-r--r--tests/wpt/web-platform-tests/mediacapture-streams/stream-api/mediastreamtrack/mediastreamtrack-init.html77
-rw-r--r--tests/wpt/web-platform-tests/mediacapture-streams/stream-api/video-and-audio-tracks/audiostreamtrack.html27
-rw-r--r--tests/wpt/web-platform-tests/mediacapture-streams/stream-api/video-and-audio-tracks/videostreamtrack.html27
-rw-r--r--tests/wpt/web-platform-tests/microdata/conformance-requirements/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/microdata/converting-html-to-other-formats/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/microdata/converting-html-to-other-formats/json/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/microdata/dependencies/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/microdata/encoding-microdata/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/microdata/encoding-microdata/associating-names-with-items/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/microdata/encoding-microdata/items/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/microdata/encoding-microdata/microdata-and-other-namespaces/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/microdata/encoding-microdata/names-the-itemprop-attribute/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/microdata/encoding-microdata/names-the-itemprop-attribute/original-id.json1
-rw-r--r--tests/wpt/web-platform-tests/microdata/encoding-microdata/the-microdata-model/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/microdata/encoding-microdata/values/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/microdata/iana/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/microdata/introduction/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/microdata/introduction/global-identifiers-for-items/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/microdata/introduction/overview/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/microdata/introduction/selecting-names-when-defining-vocabularies/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/microdata/introduction/the-basic-syntax/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/microdata/introduction/typed-items/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/microdata/introduction/using-the-microdata-dom-api/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/microdata/microdata-dom-api/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/microdata/microdata-dom-api/001.html3665
-rw-r--r--tests/wpt/web-platform-tests/microdata/microdata-dom-api/htmlpropertiescollection/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/microdata/terminology/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/navigation-timing/idlharness.html119
-rw-r--r--tests/wpt/web-platform-tests/navigation-timing/resources/blank_page_green.html10
-rw-r--r--tests/wpt/web-platform-tests/navigation-timing/resources/blank_page_green_with_onunload.html11
-rw-r--r--tests/wpt/web-platform-tests/navigation-timing/resources/blank_page_meta_redirect.html11
-rw-r--r--tests/wpt/web-platform-tests/navigation-timing/resources/blank_page_unload.html25
-rw-r--r--tests/wpt/web-platform-tests/navigation-timing/resources/blank_page_yellow.html10
-rw-r--r--tests/wpt/web-platform-tests/navigation-timing/resources/blank_page_yellow_with_onunload.html11
-rw-r--r--tests/wpt/web-platform-tests/navigation-timing/resources/webperftestharness.js155
-rw-r--r--tests/wpt/web-platform-tests/navigation-timing/test_document_open.html83
-rw-r--r--tests/wpt/web-platform-tests/navigation-timing/test_document_readiness_exist.html50
-rw-r--r--tests/wpt/web-platform-tests/navigation-timing/test_navigate_within_document.html66
-rw-r--r--tests/wpt/web-platform-tests/navigation-timing/test_navigation_attributes_exist.html25
-rw-r--r--tests/wpt/web-platform-tests/navigation-timing/test_navigation_redirectCount_none.html29
-rw-r--r--tests/wpt/web-platform-tests/navigation-timing/test_navigation_type_backforward.html96
-rw-r--r--tests/wpt/web-platform-tests/navigation-timing/test_navigation_type_enums.html27
-rw-r--r--tests/wpt/web-platform-tests/navigation-timing/test_navigation_type_reload.html109
-rw-r--r--tests/wpt/web-platform-tests/navigation-timing/test_no_previous_document.html41
-rw-r--r--tests/wpt/web-platform-tests/navigation-timing/test_performance_attributes_exist.html23
-rw-r--r--tests/wpt/web-platform-tests/navigation-timing/test_performance_attributes_exist_in_object.html29
-rw-r--r--tests/wpt/web-platform-tests/navigation-timing/test_readwrite.html28
-rw-r--r--tests/wpt/web-platform-tests/navigation-timing/test_timing_attributes_exist.html27
-rw-r--r--tests/wpt/web-platform-tests/navigation-timing/test_timing_attributes_order.html110
-rw-r--r--tests/wpt/web-platform-tests/navigation-timing/test_timing_client_redirect.html55
-rw-r--r--tests/wpt/web-platform-tests/navigation-timing/test_timing_reload.html91
-rw-r--r--tests/wpt/web-platform-tests/navigation-timing/test_timing_server_redirect.html47
-rw-r--r--tests/wpt/web-platform-tests/navigation-timing/test_timing_xserver_redirect.html70
-rw-r--r--tests/wpt/web-platform-tests/navigation-timing/test_unique_performance_objects.html30
-rw-r--r--tests/wpt/web-platform-tests/notifications/Notification-permission.html17
-rw-r--r--tests/wpt/web-platform-tests/notifications/Notification-requestPermission-denied-manual.html22
-rw-r--r--tests/wpt/web-platform-tests/notifications/Notification-requestPermission-granted-manual.html22
-rw-r--r--tests/wpt/web-platform-tests/notifications/README.md5
-rw-r--r--tests/wpt/web-platform-tests/notifications/event-onshow.html23
-rw-r--r--tests/wpt/web-platform-tests/notifications/instance.html52
-rw-r--r--tests/wpt/web-platform-tests/notifications/interfaces.html80
-rw-r--r--tests/wpt/web-platform-tests/notifications/notification-body-basic-manual.html17
-rw-r--r--tests/wpt/web-platform-tests/notifications/notification-body-empty-manual.html17
-rw-r--r--tests/wpt/web-platform-tests/notifications/notification-close-manual.html21
-rw-r--r--tests/wpt/web-platform-tests/notifications/notification-constructor-basic.html20
-rw-r--r--tests/wpt/web-platform-tests/notifications/notification-constructor-invalid.html19
-rw-r--r--tests/wpt/web-platform-tests/notifications/notification-dir-auto-manual.html18
-rw-r--r--tests/wpt/web-platform-tests/notifications/notification-dir-ltr-manual.html18
-rw-r--r--tests/wpt/web-platform-tests/notifications/notification-dir-rtl-manual.html18
-rw-r--r--tests/wpt/web-platform-tests/notifications/notification-icon-basic-manual.html19
-rw-r--r--tests/wpt/web-platform-tests/notifications/notification-icon-empty-manual.html18
-rw-r--r--tests/wpt/web-platform-tests/notifications/notification-tag-different-manual.html23
-rw-r--r--tests/wpt/web-platform-tests/notifications/notification-tag-same-manual.html23
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/Not_Use/input_autocomplete.html47
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/Not_Use/input_list.html47
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/Not_Use/input_valueasdate.html52
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/Not_Use/input_valueasnumber.html44
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/Not_Use/select_length.html56
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/Not_Use/select_selectedindex.html50
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/button_checkvalidity.html44
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/button_labels.html48
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/button_setcustomvalidity.html43
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/button_validationmessage.html40
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/button_validity.html40
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/button_willvalidate.html40
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/fieldset_checkvalidity.html45
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/fieldset_setcustomvalidity.html44
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/fieldset_validationmessage.html41
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/fieldset_validity.html41
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/fieldset_willvalidate.html41
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/form_action.html43
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/form_checkvalidity.html47
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/form_length.html38
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/form_submit.html51
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/input_checkvalidity.html44
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/input_height.html42
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/input_labels.html49
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/input_setcustomvalidity.html43
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/input_stepdown.html44
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/input_stepup.html45
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/input_validationmessage.html40
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/input_validity.html40
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/input_value_invalidstateerr.html41
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/input_valueasdate_invalidstateerr.html41
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/input_valueasnumber_invalidstateerr.html39
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/input_width.html42
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/input_willvalidate.html40
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/keygen_checkvalidity.html44
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/keygen_labels.html48
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Infraware/Session_History/contents/Session_History/css/result.css12
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Infraware/Session_History/contents/Session_History/index.html63
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_000.htm62
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_001.htm62
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_002.htm64
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_003.htm67
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_004.htm19
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_005.htm19
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_006.htm19
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_007.htm19
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_008.htm19
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_009.htm66
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_010.htm64
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_011.htm62
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_012.htm64
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_013.htm76
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_014.htm81
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_015.htm78
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_016.htm72
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_support.js9
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/foreigncontent/foreign_content_002.html47
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/foreigncontent/foreign_content_007.html8
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/foreigncontent/foreign_content_012.html33
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/foreigncontent/foreign_content_014.html98
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/foreigncontent/foreign_content_015.html53
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/history/404.html1
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/history/history_000.htm329
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/images/blue-area.pngbin0 -> 1469 bytes
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/images/blue-border.pngbin0 -> 1823 bytes
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/images/blue.pngbin0 -> 485 bytes
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/images/fail.gifbin0 -> 24480 bytes
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/images/movie_300_frame_0.pngbin0 -> 11493 bytes
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/images/poster.pngbin0 -> 83058 bytes
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/images/poster_blue.pngbin0 -> 5316 bytes
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/images/poster_green.pngbin0 -> 5130 bytes
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/images/poster_red.pngbin0 -> 4605 bytes
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/images/rect.svg4
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_001.htm11
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_002.htm23
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_003.htm12
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_004.htm10
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_006.htm12
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_007.htm12
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_008.htm9
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_009.htm9
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_010.htm9
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_012.htm13
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_020.htm28
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_020a.htm13
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_021.htm28
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_021a.htm13
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_022.htm11
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_023.htm15
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_024.htm13
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_026.htm12
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_027.htm21
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_028.htm20
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_029.htm19
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_031.htm19
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_032.htm27
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox.pdfbin0 -> 80990 bytes
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_001.htm33
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_002.htm34
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_003.htm32
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_004.htm33
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_005.htm33
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_006.htm37
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_007.htm37
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_008.htm37
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_009.htm37
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_010.htm37
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_011.htm65
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_012.htm36
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_013.htm38
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_014.htm36
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_015.htm36
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_016.htm36
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_017.htm36
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_018.htm36
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_019.htm36
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_020.htm34
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_021.htm44
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_022.htm38
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_023.htm34
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_024.htm33
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_025.htm32
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_026.htm33
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_027.htm33
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_028.htm34
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_029.htm33
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_030.htm33
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_031.htm33
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_032.htm33
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_helper.js14
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/standalone-fail.htm9
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/standalone-iframe-content.htm9
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/standalone-pass.htm9
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/selection/RemoveElementContainingSelection.htm40
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/selection/addRange.htm72
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/selection/collapse.htm73
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/selection/collapseToEnd.htm75
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/selection/collapseToStart.htm75
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/selection/deleteFromDocument.htm80
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/selection/getRangeAt.htm59
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/selection/insertNodeIntoSelection.htm41
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/selection/removeAllRanges.htm73
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/selection/removeRange.htm72
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/selection/select.htm72
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/selection/selectAllChildren.htm32
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/selection/selectionStartEnd.htm74
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/selection/setSelectionRange.htm73
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/structuredclone/echo.js1
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/structuredclone/structuredclone_0.html400
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/xhtml5/colgroup_valign_bottom.xhtmlbin0 -> 1246 bytes
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Microsoft/xhtml5/colgroup_valign_top.xhtmlbin0 -> 1202 bytes
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/001.html27
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/002.html27
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/003.html27
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/004.html25
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/005.html27
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/006.html30
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/007.html27
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/008.html28
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/009.html29
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/010.html29
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/011.html30
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/012.html30
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/013.html28
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/014.html28
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/015.html34
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/015a.html30
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/016.html28
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/017.html33
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/018.html35
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/019.html31
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/020.html28
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/021.html29
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/022.html30
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/023.html30
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/024.html32
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/025.html30
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/026.html33
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/027.html30
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/028.html29
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/029.html37
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/030.html39
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/031.html30
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/032.html29
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/033.html35
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/034.html28
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/035.html35
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/036.html34
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/037.html33
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/038.html34
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/039.html36
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/040.html34
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/041.html29
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/042.html29
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/043.html31
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/044.html28
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/045.html28
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/046.html27
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/047.html28
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/048.html28
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/049.html28
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/050.html29
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/051.html29
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/052.html26
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/053.html31
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/054.html33
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/055.html32
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/056.html30
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/057.html31
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/058.html29
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/059.html30
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/060.html32
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/061.html29
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/062.html29
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/063.html30
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/064.html29
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/065.html30
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/066.html31
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/067.html38
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/068.html31
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/069.html32
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/070.html48
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/071.html55
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/072.html50
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/073.html52
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/074.html49
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/075.html42
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/076.html32
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/077.html41
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/078.html43
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/079.html28
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/080.html30
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/081.html31
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/082.html34
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/083.html48
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/084.html47
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/085.html24
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/086.html24
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/087.html24
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/088.html24
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/089.html34
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/090.html34
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/091.html31
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/092.html26
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/094.html21
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/095.html24
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/096.html24
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/097.html29
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/098.html25
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/099.html19
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/100.html19
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/101.html30
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/102.html24
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/103.html39
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/104.html39
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/105.html31
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/106.html27
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/107.html27
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/108.html25
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/109.html29
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/110.html30
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/111.html32
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/112.html29
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/113.html31
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/114.html26
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/115.html26
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/116.html24
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/117.html26
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/118.html26
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/119.html32
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/120.html17
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/121.html17
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/122.html28
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/123.html28
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/124.html25
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/125.html28
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/126.html29
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/127.html34
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/128.html34
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/129.html40
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/130.html34
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/131.html22
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/132.html22
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/133.html29
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/134.html28
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/135.html28
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/136.html33
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/137.html21
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/138.html30
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/139.html30
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/140.html24
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/141.html26
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/142.html27
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/143.html31
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/144.html28
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/145.html24
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/146.html22
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/147.html40
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/148.html40
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/149.html59
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/css/background.css3
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/css/import.css1
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/pages/helloworld-postMessage.html19
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/pages/helloworld.html15
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/count-script-tags.js1
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/find-body.js2
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/find-foo.js2
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/include-1.js1
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/include-10.js1
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/include-11.js4
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/include-12.js4
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/include-2.js1
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/include-3.js3
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/include-4.js3
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/include-5.js7
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/include-6.js6
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/include-7.js1
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/include-8.js4
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/include-9.js2
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/testlib/testlib.js43
-rw-r--r--tests/wpt/web-platform-tests/old-tests/submission/migration.txt26
-rw-r--r--tests/wpt/web-platform-tests/page-visibility/idlharness.html48
-rw-r--r--tests/wpt/web-platform-tests/page-visibility/resources/blank_page_green.html10
-rw-r--r--tests/wpt/web-platform-tests/page-visibility/resources/pagevistestharness.js121
-rw-r--r--tests/wpt/web-platform-tests/page-visibility/test_attributes_exist.html22
-rw-r--r--tests/wpt/web-platform-tests/page-visibility/test_child_document.html94
-rw-r--r--tests/wpt/web-platform-tests/page-visibility/test_default_view.html43
-rw-r--r--tests/wpt/web-platform-tests/page-visibility/test_minimize-manual.html188
-rw-r--r--tests/wpt/web-platform-tests/page-visibility/test_read_only.html37
-rw-r--r--tests/wpt/web-platform-tests/page-visibility/test_tab_state_change-manual.html186
-rw-r--r--tests/wpt/web-platform-tests/performance-timeline/idlharness.html54
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/README.md9
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_button_attribute_mouse-manual.html57
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_capture_mouse-manual.html132
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_capture_suppressing_mouse-manual.html175
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_change-touch-action-onpointerdown_touch-manual.html135
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_constructor.html100
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_gotpointercapture_before_first_pointerevent-manual.html97
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_lostpointercapture_for_disconnected_node-manual.html78
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_lostpointercapture_is_first-manual.html111
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_pointercancel_touch-manual.html77
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerdown-manual.html59
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerenter-manual.html52
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerenter_does_not_bubble-manual.html88
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerenter_nohover-manual.html74
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerleave_after_pointercancel_touch-manual.html66
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerleave_after_pointerup_nohover-manual.html67
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerleave_descendant_over-manual.html61
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerleave_descendants-manual.html52
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerleave_does_not_bubble-manual.html77
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerleave_mouse-manual.html53
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerleave_pen-manual.html58
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerleave_touch-manual.html53
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_pointermove-manual.html44
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_pointermove_isprimary_same_as_pointerdown-manual.html70
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_pointermove_pointertype-manual.html64
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerout-manual.html46
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerout_after_pointercancel_touch-manual.html67
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerout_after_pointerup_nohover-manual.html67
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerout_pen-manual.html57
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerout_received_once-manual.html58
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerover-manual.html52
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_pointertype_mouse-manual.html63
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_pointertype_pen-manual.html61
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_pointertype_touch-manual.html62
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerup-manual.html44
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerup_isprimary_same_as_pointerdown-manual.html63
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerup_pointertype-manual.html64
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_releasepointercapture_events_to_original_target-manual.html116
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_releasepointercapture_invalid_pointerid-manual.html76
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_releasepointercapture_onpointercancel_touch-manual.html71
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_releasepointercapture_onpointerup_mouse-manual.html79
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_setpointercapture_disconnected-manual.html55
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_setpointercapture_inactive_button_mouse-manual.html58
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_setpointercapture_invalid_pointerid-manual.html65
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_setpointercapture_relatedtarget-manual.html101
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_styles.css61
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_support.js170
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-auto-css_touch-manual.html129
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-button-test_touch-manual.html109
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-illegal.html67
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-inherit_child-auto-child-none_touch-manual.html117
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-inherit_child-none_touch-manual.html112
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-x_touch-manual.html112
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-y_touch-manual.html117
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-inherit_highest-parent-none_touch-manual.html133
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-inherit_parent-none_touch-manual.html112
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-keyboard-manual.html124
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-mouse-manual.html130
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-none-css_touch-manual.html111
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-pan-x-css_touch-manual.html106
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-pan-x-pan-y-pan-y_touch-manual.html111
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-pan-x-pan-y_touch-manual.html126
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-pan-y-css_touch-manual.html106
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-span-test_touch-manual.html113
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-svg-test_touch-manual.html122
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-table-test_touch-manual.html141
-rw-r--r--tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-verification.html101
-rw-r--r--tests/wpt/web-platform-tests/pointerlock/constructor.html53
-rw-r--r--tests/wpt/web-platform-tests/pointerlock/idlharness.html79
-rw-r--r--tests/wpt/web-platform-tests/progress-events/Status.html26
-rw-r--r--tests/wpt/web-platform-tests/progress-events/constructor.html43
-rw-r--r--tests/wpt/web-platform-tests/progress-events/interface.html53
-rw-r--r--tests/wpt/web-platform-tests/progress-events/tests/submissions/Samsung/firing-events-http-content-length.html38
-rw-r--r--tests/wpt/web-platform-tests/progress-events/tests/submissions/Samsung/firing-events-http-no-content-length.html38
-rw-r--r--tests/wpt/web-platform-tests/progress-events/tests/submissions/Samsung/resources/no-content-length.py15
-rw-r--r--tests/wpt/web-platform-tests/proximity/DeviceProximityEvent_tests.html10
-rw-r--r--tests/wpt/web-platform-tests/proximity/DeviceProximityEvent_tests.js439
-rw-r--r--tests/wpt/web-platform-tests/proximity/UserProximityEvent_tests.html10
-rw-r--r--tests/wpt/web-platform-tests/proximity/UserProximityEvent_tests.js342
-rw-r--r--tests/wpt/web-platform-tests/proximity/idlharness.html76
-rw-r--r--tests/wpt/web-platform-tests/quirks-mode/active-and-hover-manual.html182
-rw-r--r--tests/wpt/web-platform-tests/quirks-mode/blocks-ignore-line-height.html85
-rw-r--r--tests/wpt/web-platform-tests/quirks-mode/font-element-text-decoration-color/001-a.html34
-rw-r--r--tests/wpt/web-platform-tests/quirks-mode/font-element-text-decoration-color/001-q.html33
-rw-r--r--tests/wpt/web-platform-tests/quirks-mode/font-element-text-decoration-color/001-ref.html21
-rw-r--r--tests/wpt/web-platform-tests/quirks-mode/font-element-text-decoration-color/001-s.html34
-rw-r--r--tests/wpt/web-platform-tests/quirks-mode/font-element-text-decoration-color/001-x.xhtml23
-rw-r--r--tests/wpt/web-platform-tests/quirks-mode/hashless-hex-color.html500
-rw-r--r--tests/wpt/web-platform-tests/quirks-mode/line-height-calculation.html94
-rw-r--r--tests/wpt/web-platform-tests/quirks-mode/percentage-height-calculation.html142
-rw-r--r--tests/wpt/web-platform-tests/quirks-mode/table-cell-nowrap-minimum-width-calculation.html70
-rw-r--r--tests/wpt/web-platform-tests/quirks-mode/table-cell-width-calculation.html172
-rw-r--r--tests/wpt/web-platform-tests/quirks-mode/unitless-length.html226
-rw-r--r--tests/wpt/web-platform-tests/resource-timing/resources/resource_timing_test0.css4
-rw-r--r--tests/wpt/web-platform-tests/resource-timing/resources/resource_timing_test0.html15
-rw-r--r--tests/wpt/web-platform-tests/resource-timing/resources/resource_timing_test0.js3
-rw-r--r--tests/wpt/web-platform-tests/resource-timing/resources/resource_timing_test0.pngbin0 -> 249 bytes
-rw-r--r--tests/wpt/web-platform-tests/resource-timing/resources/resource_timing_test0.xml6
-rw-r--r--tests/wpt/web-platform-tests/resource-timing/resources/webperftestharness.js145
-rw-r--r--tests/wpt/web-platform-tests/resource-timing/test_resource_timing.html24
-rw-r--r--tests/wpt/web-platform-tests/resource-timing/test_resource_timing.js182
-rw-r--r--tests/wpt/web-platform-tests/resources/.gitignore3
-rw-r--r--tests/wpt/web-platform-tests/resources/.gitmodules3
-rw-r--r--tests/wpt/web-platform-tests/resources/.htaccess2
-rw-r--r--tests/wpt/web-platform-tests/resources/apisample-error-worker.js3
-rw-r--r--tests/wpt/web-platform-tests/resources/apisample-worker.js34
-rw-r--r--tests/wpt/web-platform-tests/resources/apisample.htm175
-rw-r--r--tests/wpt/web-platform-tests/resources/apisample10.html119
-rw-r--r--tests/wpt/web-platform-tests/resources/apisample11.html99
-rw-r--r--tests/wpt/web-platform-tests/resources/apisample12.html67
-rw-r--r--tests/wpt/web-platform-tests/resources/apisample13.html132
-rw-r--r--tests/wpt/web-platform-tests/resources/apisample14.html29
-rw-r--r--tests/wpt/web-platform-tests/resources/apisample15.html26
-rw-r--r--tests/wpt/web-platform-tests/resources/apisample16.html62
-rw-r--r--tests/wpt/web-platform-tests/resources/apisample2.htm19
-rw-r--r--tests/wpt/web-platform-tests/resources/apisample3.htm17
-rw-r--r--tests/wpt/web-platform-tests/resources/apisample4.htm16
-rw-r--r--tests/wpt/web-platform-tests/resources/apisample5.htm18
-rw-r--r--tests/wpt/web-platform-tests/resources/apisample6.html10
-rw-r--r--tests/wpt/web-platform-tests/resources/apisample7.html10
-rw-r--r--tests/wpt/web-platform-tests/resources/apisample8.html8
-rw-r--r--tests/wpt/web-platform-tests/resources/apisample9.html7
-rw-r--r--tests/wpt/web-platform-tests/resources/docs/api.md548
-rw-r--r--tests/wpt/web-platform-tests/resources/docs/idlharness.md118
-rw-r--r--tests/wpt/web-platform-tests/resources/idlharness.js1636
-rw-r--r--tests/wpt/web-platform-tests/resources/readme.md23
-rw-r--r--tests/wpt/web-platform-tests/resources/testharness.css102
-rw-r--r--tests/wpt/web-platform-tests/resources/testharness.js2427
-rw-r--r--tests/wpt/web-platform-tests/resources/testharnessreport.js21
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/.gitignore4
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/.gitmodules3
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/.travis.yml3
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/README.md725
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/coverage.html341
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/index.js1
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/lib/webidl2.js924
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/lib/writer.js236
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/package.json22
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/invalid.js42
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/enum.widl1
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/module.widl25
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/nonnullableany.widl3
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/nonnullableobjects.widl5
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/raises.widl18
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/scopedname.widl2
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/sequenceAsAttribute.widl3
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/special-omittable.widl8
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/stringconstants.idl3
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/enum.json4
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/module.json4
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/nonnullableany.json4
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/nonnullableobjects.json4
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/raises.json4
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/scopedname.json4
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/sequenceAsAttribute.json4
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/special-omittable.json4
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/stringconstants.json4
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/mocha.opts1
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax.js36
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/allowany.widl6
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/array.widl5
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/attributes.widl14
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/callback.widl5
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/caller.widl5
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/constants.widl18
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/constructor.widl9
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/dictionary-inherits.widl9
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/dictionary.widl11
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/documentation-dos.widl33
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/documentation.widl34
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/enum.widl8
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/equivalent-decl.widl18
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/exception-inheritance.widl7
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/exception.widl8
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/generic.widl17
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/getter-setter.widl7
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/identifier-qualified-names.widl44
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/implements.widl14
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/indexed-properties.widl12
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/inherits-getter.widl16
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/interface-inherits.widl12
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/iterator.widl35
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/map.widl5
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/namedconstructor.widl6
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/nointerfaceobject.widl5
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/nullable.widl9
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/nullableobjects.widl13
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/operation-optional-arg.widl4
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/overloading.widl20
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/overridebuiltins.widl6
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/partial-interface.widl7
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/primitives.widl19
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/prototyperoot.widl5
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/putforwards.widl5
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/reg-operations.widl17
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/replaceable.widl5
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/sequence.widl12
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/serializer.widl64
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/static.widl11
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/stringifier-attribute.widl6
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/stringifier-custom.widl9
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/stringifier.widl8
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/treatasnull.widl7
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/treatasundefined.widl7
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/typedef.widl22
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/typesuffixes.widl3
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/uniontype.widl3
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/variadic-operations.widl7
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/allowany.json109
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/array.json34
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/attributes.json56
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/callback.json76
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/caller.json47
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/constants.json141
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/constructor.json103
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/dictionary-inherits.json79
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/dictionary.json91
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/documentation-dos.json10
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/documentation.json10
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/enum.json105
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/equivalent-decl.json312
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/exception-inheritance.json37
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/exception.json35
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/generic.json156
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/getter-setter.json114
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/identifier-qualified-names.json217
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/implements.json107
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/indexed-properties.json272
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/inherits-getter.json71
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/interface-inherits.json80
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/iterator.json301
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/map.json29
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/namedconstructor.json42
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/nointerfaceobject.json52
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/nullable.json48
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/nullableobjects.json99
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/operation-optional-arg.json93
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/overloading.json312
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/overridebuiltins.json69
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/partial-interface.json53
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/primitives.json300
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/prototyperoot.json33
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/putforwards.json54
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/reg-operations.json168
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/replaceable.json54
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/sequence.json113
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/serializer.json591
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/static.json151
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/stringifier-attribute.json50
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/stringifier-custom.json88
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/stringifier.json52
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/treatasnull.json90
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/treatasundefined.json90
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/typedef.json226
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/typesuffixes.json55
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/uniontype.json87
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/variadic-operations.json100
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/web/make-web-tests.js51
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/web/run-tests.js48
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/.gitignore3
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/LICENSE202
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/Makefile158
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/README.md40
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/doc/htmltodtd.xsl28
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/doc/widlproc.html1124
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/examples/Makefile79
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/examples/README41
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/examples/bondi.widl227
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/examples/filesystem.widl1038
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/examples/spectowidl.xsl27
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/examples/widlhtml.css100
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/comment.c1827
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/comment.h25
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/entities.h271
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/lex.c560
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/lex.h141
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/main.c63
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/misc.c119
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/misc.h31
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/node.c331
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/node.h65
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/os.h31
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/parse.c1414
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/parse.h19
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/process.c319
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/process.h27
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/widlprocxmltohtml.xsl828
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/Makefile91
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/error/enum.txt1
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/error/module.txt1
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/error/nonnullableany.txt1
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/error/nonnullableobjects.txt1
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/error/scopedname.txt1
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/error/sequenceAsAttribute.txt1
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/error/stringconstants.idl1
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/idl/enum.widl1
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/idl/module.widl25
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/idl/nonnullableany.widl3
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/idl/nonnullableobjects.widl5
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/idl/raises.widl18
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/idl/scopedname.widl2
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/idl/sequenceAsAttribute.widl3
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/idl/special-omittable.widl8
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/idl/stringconstants.idl3
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/allowany.widl6
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/array.widl5
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/attributes.widl14
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/callback.widl5
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/caller.widl5
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/constants.widl18
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/constructor.widl9
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/dictionary-inherits.widl9
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/dictionary.widl11
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/documentation-dos.widl33
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/documentation.widl34
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/enum.widl8
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/equivalent-decl.widl18
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/exception-inheritance.widl7
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/exception.widl8
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/getter-setter.widl7
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/identifier-qualified-names.widl44
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/implements.widl14
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/indexed-properties.widl12
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/inherits-getter.widl16
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/interface-inherits.widl12
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/iterator.widl35
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/namedconstructor.widl6
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/nointerfaceobject.widl5
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/nullable.widl9
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/nullableobjects.widl13
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/operation-optional-arg.widl4
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/overloading.widl20
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/overridebuiltins.widl6
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/partial-interface.widl7
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/primitives.widl19
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/prototyperoot.widl5
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/putforwards.widl5
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/reg-operations.widl17
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/replaceable.widl5
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/sequence.widl7
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/serializer.widl64
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/static.widl11
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/stringifier-attribute.widl6
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/stringifier-custom.widl9
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/stringifier.widl8
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/treatasnull.widl7
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/treatasundefined.widl7
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/typedef.widl22
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/typesuffixes.widl3
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/uniontype.widl3
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/variadic-operations.widl7
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/allowany.widlprocxml44
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/array.widlprocxml27
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/attributes.widlprocxml38
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/callback.widlprocxml32
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/caller.widlprocxml21
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/constants.widlprocxml85
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/constructor.widlprocxml51
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/dictionary-inherits.widlprocxml44
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/dictionary.widlprocxml47
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/documentation-dos.widlprocxml59
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/documentation.widlprocxml61
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/enum.widlprocxml52
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/equivalent-decl.widlprocxml111
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/exception-inheritance.widlprocxml31
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/exception.widlprocxml23
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/getter-setter.widlprocxml43
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/identifier-qualified-names.widlprocxml107
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/implements.widlprocxml51
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/indexed-properties.widlprocxml92
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/inherits-getter.widlprocxml44
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/interface-inherits.widlprocxml48
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/iterator.widlprocxml132
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/module.widlprocxml99
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/namedconstructor.widlprocxml30
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/namespaceobject.widlprocxml60
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/nointerfaceobject.widlprocxml28
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/nullable.widlprocxml29
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/nullableobjects.widlprocxml46
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/operation-optional-arg.widlprocxml30
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/overloading.widlprocxml113
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/overridebuiltins.widlprocxml34
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/partial-interface.widlprocxml29
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/primitives.widlprocxml112
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/prototyperoot.widlprocxml23
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/putforwards.widlprocxml27
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/reg-operations.widlprocxml70
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/replaceable.widlprocxml28
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/sequence.widlprocxml32
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/serializer.widlprocxml296
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/special-omittable.widlprocxml37
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/static.widlprocxml58
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/stringifier-attribute.widlprocxml29
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/stringifier-custom.widlprocxml44
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/stringifier.widlprocxml29
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/treatasnull.widlprocxml40
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/treatasundefined.widlprocxml40
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/typedef.widlprocxml100
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/typesuffixes.widlprocxml25
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/uniontype.widlprocxml26
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/variadic-operations.widlprocxml40
-rw-r--r--tests/wpt/web-platform-tests/selectors-api/tests/submissions/Opera/ParentNode-query-queryAll.html89
-rw-r--r--tests/wpt/web-platform-tests/selectors-api/tests/submissions/Opera/ParentNode-query-queryAll.js278
-rw-r--r--tests/wpt/web-platform-tests/selectors/attribute-selectors/attribute-case/cssom.html65
-rw-r--r--tests/wpt/web-platform-tests/selectors/attribute-selectors/attribute-case/resources/semantics-quirks.html4
-rw-r--r--tests/wpt/web-platform-tests/selectors/attribute-selectors/attribute-case/resources/semantics-xml.xhtml10
-rw-r--r--tests/wpt/web-platform-tests/selectors/attribute-selectors/attribute-case/resources/syntax-quirks.html5
-rw-r--r--tests/wpt/web-platform-tests/selectors/attribute-selectors/attribute-case/resources/syntax-xml.xhtml11
-rw-r--r--tests/wpt/web-platform-tests/selectors/attribute-selectors/attribute-case/semantics.html146
-rw-r--r--tests/wpt/web-platform-tests/selectors/attribute-selectors/attribute-case/syntax.html117
-rwxr-xr-xtests/wpt/web-platform-tests/serve5
-rw-r--r--tests/wpt/web-platform-tests/serve.py5
-rw-r--r--tests/wpt/web-platform-tests/server-side.md234
-rw-r--r--tests/wpt/web-platform-tests/service-workers/specgen.json658
-rw-r--r--tests/wpt/web-platform-tests/service-workers/stub-3.1-service-worker-obj.html63
-rw-r--r--tests/wpt/web-platform-tests/service-workers/stub-3.1.1-service-worker-scope.html46
-rw-r--r--tests/wpt/web-platform-tests/service-workers/stub-3.1.2-service-worker-url.html43
-rw-r--r--tests/wpt/web-platform-tests/service-workers/stub-3.1.3-service-worker-state.html76
-rw-r--r--tests/wpt/web-platform-tests/service-workers/stub-3.1.4-service-worker-on-state-change.html35
-rw-r--r--tests/wpt/web-platform-tests/service-workers/stub-3.2-navigator-service-worker.html84
-rw-r--r--tests/wpt/web-platform-tests/service-workers/stub-3.2.1-navigator-service-worker-installing.html43
-rw-r--r--tests/wpt/web-platform-tests/service-workers/stub-3.2.10-navigator-service-worker-oncontrollerchange.html45
-rw-r--r--tests/wpt/web-platform-tests/service-workers/stub-3.2.11-navigator-service-worker-onreloadpage.html41
-rw-r--r--tests/wpt/web-platform-tests/service-workers/stub-3.2.12-navigator-service-worker-onerror.html37
-rw-r--r--tests/wpt/web-platform-tests/service-workers/stub-3.2.2-navigator-service-worker-waiting.html34
-rw-r--r--tests/wpt/web-platform-tests/service-workers/stub-3.2.3-navigator-service-worker-active.html40
-rw-r--r--tests/wpt/web-platform-tests/service-workers/stub-3.2.4-navigator-service-worker-controller.html37
-rw-r--r--tests/wpt/web-platform-tests/service-workers/stub-3.2.5-navigator-service-worker-ready.html67
-rw-r--r--tests/wpt/web-platform-tests/service-workers/stub-3.2.6-navigator-service-worker-getAll.html30
-rw-r--r--tests/wpt/web-platform-tests/service-workers/stub-3.2.7-navigator-service-worker-register.html32
-rw-r--r--tests/wpt/web-platform-tests/service-workers/stub-3.2.8-navigator-service-worker-unregister.html31
-rw-r--r--tests/wpt/web-platform-tests/service-workers/stub-3.2.9-navigator-service-worker-onupdatefound.html42
-rw-r--r--tests/wpt/web-platform-tests/service-workers/stub-4.1-service-worker-global-scope.html75
-rw-r--r--tests/wpt/web-platform-tests/service-workers/stub-4.1.1-service-worker-global-scope-caches.html36
-rw-r--r--tests/wpt/web-platform-tests/service-workers/stub-4.1.2-service-worker-global-scope-clients.html33
-rw-r--r--tests/wpt/web-platform-tests/service-workers/stub-4.1.3-service-worker-global-scope-scope.html36
-rw-r--r--tests/wpt/web-platform-tests/service-workers/stub-4.1.4-service-worker-global-scope-fetch.html55
-rw-r--r--tests/wpt/web-platform-tests/service-workers/stub-4.1.5-service-worker-global-scope-update.html36
-rw-r--r--tests/wpt/web-platform-tests/service-workers/stub-4.1.6-service-worker-global-scope-unregister.html31
-rw-r--r--tests/wpt/web-platform-tests/service-workers/stub-4.1.7-service-worker-global-scope-onmessage.html45
-rw-r--r--tests/wpt/web-platform-tests/service-workers/stub-4.2-client.html61
-rw-r--r--tests/wpt/web-platform-tests/service-workers/stub-4.3-service-worker-clients.html48
-rw-r--r--tests/wpt/web-platform-tests/service-workers/stub-4.3.1-get-serviced-method.html34
-rw-r--r--tests/wpt/web-platform-tests/service-workers/stub-4.3.2-reloadall-method.html37
-rw-r--r--tests/wpt/web-platform-tests/service-workers/stub-4.4-request-objects.html72
-rw-r--r--tests/wpt/web-platform-tests/service-workers/stub-4.5-response-objects.html75
-rw-r--r--tests/wpt/web-platform-tests/service-workers/stub-4.5.2-response.html36
-rw-r--r--tests/wpt/web-platform-tests/service-workers/stub-4.5.4-opaque-response.html36
-rw-r--r--tests/wpt/web-platform-tests/service-workers/stub-4.6-cache-objects.html37
-rw-r--r--tests/wpt/web-platform-tests/service-workers/stub-4.6.1-cache-lifetimes.html38
-rw-r--r--tests/wpt/web-platform-tests/service-workers/stub-4.6.2-cache.html64
-rw-r--r--tests/wpt/web-platform-tests/service-workers/stub-4.6.3-cache-storage.html62
-rw-r--r--tests/wpt/web-platform-tests/service-workers/stub-4.7.1-install-phase-event.html51
-rw-r--r--tests/wpt/web-platform-tests/service-workers/stub-4.7.1.1-wait-until-method.html39
-rw-r--r--tests/wpt/web-platform-tests/service-workers/stub-4.7.2-install-event.html35
-rw-r--r--tests/wpt/web-platform-tests/service-workers/stub-4.7.2.1-install-event-section.html47
-rw-r--r--tests/wpt/web-platform-tests/service-workers/stub-4.7.2.2-replace-method.html38
-rw-r--r--tests/wpt/web-platform-tests/service-workers/stub-4.7.3-activate-event.html41
-rw-r--r--tests/wpt/web-platform-tests/service-workers/stub-4.7.4.1-fetch-event-section.html71
-rw-r--r--tests/wpt/web-platform-tests/service-workers/stub-4.7.4.2-respond-with-method.html46
-rw-r--r--tests/wpt/web-platform-tests/service-workers/stub-4.7.4.3-default-method.html52
-rw-r--r--tests/wpt/web-platform-tests/service-workers/stub-4.7.4.4-is-reload-attribute.html32
-rw-r--r--tests/wpt/web-platform-tests/service-workers/stub-5.1-origin-relativity.html35
-rw-r--r--tests/wpt/web-platform-tests/service-workers/stub-5.2-cross-origin-resources.html48
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/LICENSE107
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/extensions-to-element-interface/attributes/test-001.html54
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/extensions-to-element-interface/attributes/test-005.html44
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/extensions-to-element-interface/attributes/test-006.html38
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/extensions-to-element-interface/methods/elements-001.html49
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/extensions-to-element-interface/methods/non-element-nodes-001.html136
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/extensions-to-element-interface/methods/test-001.html40
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/extensions-to-element-interface/methods/test-002.html45
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/extensions-to-element-interface/methods/test-003.html56
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/extensions-to-event-interface/event-path-001.html56
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/extensions-to-event-interface/event-path-002.html47
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/activeElement-confirm-return-null.html78
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-007.html50
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-009.html43
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-010.html75
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-011.html56
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-012.html39
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-013.html39
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-014.html49
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-001.html62
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-002.html83
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-003.html154
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-004.html51
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-005.html80
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-006.html42
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-007.html63
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-010.html42
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/the-content-html-element/test-001.html82
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/the-content-html-element/test-002.html98
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/the-content-html-element/test-003.html130
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/the-content-html-element/test-004.html163
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/the-content-html-element/test-005.html94
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/the-content-html-element/test-006.html94
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/the-shadow-html-element/test-001.html66
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/the-shadow-html-element/test-002.html51
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/the-shadow-html-element/test-003.html189
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/the-shadow-html-element/test-004.html107
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/events/event-dispatch/test-001.html258
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/events/event-dispatch/test-002.html61
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/events/event-dispatch/test-003.html60
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/events/event-retargeting/test-001.html107
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/events/event-retargeting/test-002.html60
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/events/event-retargeting/test-003.html61
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/events/event-retargeting/test-004.html365
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/events/events-that-are-always-stopped/test-001.html60
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/events/events-that-are-always-stopped/test-002.html60
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/events/events-that-are-always-stopped/test-003.html61
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/events/events-that-are-always-stopped/test-004.html61
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/events/events-that-are-always-stopped/test-005.html61
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/events/events-that-are-always-stopped/test-006.html61
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/events/events-that-are-always-stopped/test-007.html61
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/events/events-that-are-always-stopped/test-008.html61
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/events/events-that-are-always-stopped/test-009.html61
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/events/retargeting-focus-events/test-001.html322
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/events/retargeting-focus-events/test-002.html63
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/events/retargeting-focus-events/test-003.html62
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/events/retargeting-relatedtarget/test-001.html69
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/events/retargeting-relatedtarget/test-002.html64
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/events/retargeting-relatedtarget/test-003.html64
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/events/test-001.html71
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/html-elements-and-their-shadow-trees/test-001.html232
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/html-elements-and-their-shadow-trees/test-002.html82
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/html-elements-and-their-shadow-trees/test-003.html73
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/html-elements-and-their-shadow-trees/test-004.html75
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/html-elements-in-shadow-trees/html-forms/test-001.html74
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/html-elements-in-shadow-trees/html-forms/test-002.html103
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/html-elements-in-shadow-trees/html-forms/test-003.html90
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/html-elements-in-shadow-trees/inert-html-elements/test-001.html80
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/html-elements-in-shadow-trees/inert-html-elements/test-002.html46
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/resources/blank.html5
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/resources/bobs_page.html35
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/composition/test-001.html164
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/content-pseudo-element/test-001.html77
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/content-pseudo-element/test-002.html67
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/custom-pseudo-elements/test-001.html64
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-002-ref.html15
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-002.html23
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-003-ref.html15
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-003.html23
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-004-ref.html14
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-004.html23
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-005-ref.html14
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-005.html23
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-006-ref.html15
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-006.html23
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees/test-001.html128
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees/test-002.html86
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees/test-003.html88
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/lower-boundary-encapsulation/distribution-001-ref.html35
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/lower-boundary-encapsulation/distribution-001.html47
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/lower-boundary-encapsulation/distribution-002-ref.html40
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/lower-boundary-encapsulation/distribution-002.html53
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/lower-boundary-encapsulation/distribution-003.html75
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/lower-boundary-encapsulation/test-003.html131
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/lower-boundary-encapsulation/test-004.html103
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/lower-boundary-encapsulation/test-005.html67
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/nested-shadow-trees/nested_tree_reftest-ref.html25
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/nested-shadow-trees/nested_tree_reftest.html30
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/nested-shadow-trees/test-001.html99
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/rendering-shadow-trees/test-001.html256
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/reprojection/reprojection-001-ref.html35
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/reprojection/reprojection-001.html39
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/reprojection/reprojection-002-ref.html30
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/reprojection/reprojection-002.html40
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/reprojection/test-001.html176
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-001.html60
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-002.html66
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-003.html67
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-004.html66
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-005.html66
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-006.html58
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-007.html59
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-008.html59
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-009.html59
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-010.html59
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-011.html61
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-012.html67
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-013.html67
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-014.html67
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-015.html67
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-016.html67
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-017.html67
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-018.html67
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-019.html67
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-020.html79
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/shadow-root-001-ref.html25
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/shadow-root-001.html35
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/shadow-root-002-ref.html31
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/shadow-root-002.html49
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/text-decoration-001-ref.html13
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/text-decoration-001.html22
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/upper-boundary-encapsulation/dom-tree-accessors-001.html225
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/upper-boundary-encapsulation/dom-tree-accessors-002.html92
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/upper-boundary-encapsulation/ownerdocument-001.html109
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/upper-boundary-encapsulation/ownerdocument-002.html56
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/upper-boundary-encapsulation/selectors-api-001.html81
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/upper-boundary-encapsulation/selectors-api-002.html85
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/upper-boundary-encapsulation/shadow-root-001.html64
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/upper-boundary-encapsulation/test-005.html74
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/upper-boundary-encapsulation/test-007.html75
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/upper-boundary-encapsulation/test-009.html285
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/upper-boundary-encapsulation/test-011.html71
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/upper-boundary-encapsulation/window-named-properties-001.html91
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/upper-boundary-encapsulation/window-named-properties-002.html51
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/shadow-trees/upper-boundary-encapsulation/window-named-properties-003.html47
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/styles/css-variables/test-001.html73
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/styles/deep-combinator/deep-combinator-001.html157
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/styles/not-apply-in-shadow-root-001-ref.html27
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/styles/not-apply-in-shadow-root-001.html39
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/styles/shadow-pseudoelement/shadow-pseudoelement-001.html151
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/styles/test-001.html174
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/styles/test-002.html149
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/styles/test-003.html69
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/styles/test-005.html63
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/styles/test-007.html134
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/styles/test-008.html96
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/styles/test-009.html74
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/styles/test-010.html56
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/testcommon.js273
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/user-interaction/active-element/test-001.html48
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/user-interaction/active-element/test-002.html49
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/user-interaction/editing/inheritance-of-content-editable-001.html65
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/user-interaction/focus-navigation/test-001.html86
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/user-interaction/focus-navigation/test-002.html238
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/user-interaction/focus-navigation/test-003.html237
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/user-interaction/focus-navigation/test-004.html427
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/user-interaction/ranges-and-selections/test-001.html80
-rw-r--r--tests/wpt/web-platform-tests/shadow-dom/user-interaction/ranges-and-selections/test-002.html80
-rw-r--r--tests/wpt/web-platform-tests/subresource-integrity/loads-scripts-with-base64-encoded-sha-digests.js1
-rw-r--r--tests/wpt/web-platform-tests/subresource-integrity/loads-scripts-with-correct-content-type.js1
-rw-r--r--tests/wpt/web-platform-tests/subresource-integrity/loads-scripts-with-improper-integrity-uri-scheme.js1
-rw-r--r--tests/wpt/web-platform-tests/subresource-integrity/loads-scripts-with-incorrect-content-type.js1
-rw-r--r--tests/wpt/web-platform-tests/subresource-integrity/loads-scripts-with-matching-digest.js1
-rw-r--r--tests/wpt/web-platform-tests/subresource-integrity/loads-scripts-with-non-matching-digest.js1
-rw-r--r--tests/wpt/web-platform-tests/subresource-integrity/loads-scripts-with-unhyphenated-digest-name.js1
-rw-r--r--tests/wpt/web-platform-tests/subresource-integrity/loads-scripts-with-weak-digest-algorithms.js1
-rw-r--r--tests/wpt/web-platform-tests/subresource-integrity/subresource-integrity.html79
-rw-r--r--tests/wpt/web-platform-tests/subresource-integrity/tools/generate_javascript.py45
-rw-r--r--tests/wpt/web-platform-tests/tools/.gitmodules14
-rw-r--r--tests/wpt/web-platform-tests/tools/__init__.py0
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/.gitignore20
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/.gitmodules3
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/.travis.yml37
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/AUTHORS.rst34
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/CHANGES.rst171
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/CONTRIBUTING.rst60
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/LICENSE20
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/MANIFEST.in6
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/README.rst157
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/debug-info.py37
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/doc/Makefile177
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/doc/changes.rst3
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/doc/conf.py280
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/doc/html5lib.filters.rst59
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/doc/html5lib.rst77
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/doc/html5lib.serializer.rst19
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/doc/html5lib.treebuilders.rst43
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/doc/html5lib.treewalkers.rst59
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/doc/index.rst21
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/doc/license.rst4
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/doc/make.bat242
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/doc/modules.rst7
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/doc/movingparts.rst209
-rwxr-xr-xtests/wpt/web-platform-tests/tools/html5lib/flake8-run.sh14
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/__init__.py23
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/constants.py3104
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/filters/__init__.py0
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/filters/_base.py12
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/filters/alphabeticalattributes.py20
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/filters/inject_meta_charset.py65
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/filters/lint.py93
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/filters/optionaltags.py205
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/filters/sanitizer.py12
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/filters/whitespace.py38
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/html5parser.py2723
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/ihatexml.py285
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/inputstream.py886
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/sanitizer.py271
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/serializer/__init__.py16
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/serializer/htmlserializer.py320
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/README1
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/__init__.py1
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/mockParser.py41
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/performance/concatenation.py36
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/support.py177
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/test_encoding.py67
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/test_parser.py96
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/test_parser2.py64
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/test_sanitizer.py105
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/test_serializer.py178
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/test_stream.py183
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/test_tokenizer.py188
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/test_treeadapters.py40
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/test_treewalkers.py353
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/test_whitespace_filter.py133
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/AUTHORS.rst34
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/LICENSE21
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/encoding/chardet/test_big5.txt51
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/encoding/test-yahoo-jp.dat10
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/encoding/tests1.dat394
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/encoding/tests2.dat115
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/sanitizer/tests1.dat501
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/serializer/core.test125
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/serializer/injectmeta.test66
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/serializer/optionaltags.test965
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/serializer/options.test60
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/serializer/whitespace.test51
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/sniffer/htmlOrFeed.json43
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/README.md104
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/contentModelFlags.test81
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/domjs.test96
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/entities.test283
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/escapeFlag.test33
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/namedEntities.test42210
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/numericEntities.test1313
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/pendingSpecChanges.test7
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/test1.test196
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/test2.test179
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/test3.test6047
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/test4.test344
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/unicodeChars.test1295
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/unicodeCharsProblematic.test27
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/xmlViolation.test22
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/README.md98
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/adoption01.dat337
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/adoption02.dat39
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/comments01.dat178
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/doctype01.dat424
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/domjs-unsafe.datbin0 -> 9884 bytes
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/entities01.dat723
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/entities02.dat283
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/html5test-com.dat291
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/inbody01.dat54
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/isindex.dat47
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/main-element.dat46
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/pending-spec-changes-plain-text-unsafe.datbin0 -> 816 bytes
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/pending-spec-changes.dat46
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/plain-text-unsafe.datbin0 -> 7925 bytes
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/ruby.dat298
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/scriptdata01.dat365
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/scripted/adoption01.dat15
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/scripted/ark.dat26
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/scripted/webkit01.dat28
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tables01.dat286
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/template.dat1591
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests1.dat1959
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests10.dat847
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests11.dat482
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests12.dat62
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests14.dat75
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests15.dat216
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests16.dat2458
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests17.dat179
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests18.dat322
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests19.dat1524
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests2.dat799
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests20.dat516
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests21.dat305
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests22.dat190
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests23.dat168
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests24.dat79
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests25.dat232
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests26.dat388
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests3.dat305
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests4.dat58
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests5.dat210
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests6.dat659
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests7.dat403
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests8.dat151
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests9.dat472
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests_innerHTML_1.dat891
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tricky01.dat336
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/webkit01.dat705
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/webkit02.dat134
-rwxr-xr-xtests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/attributes.test1035
-rwxr-xr-xtests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/base-href-attribute.test787
-rwxr-xr-xtests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/base-target-attribute.test35
-rwxr-xr-xtests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/blockquote-cite-attribute.test7
-rwxr-xr-xtests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/classattribute.test152
-rwxr-xr-xtests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/contenteditableattribute.test59
-rwxr-xr-xtests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/contextmenuattribute.test115
-rwxr-xr-xtests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/dirattribute.test59
-rwxr-xr-xtests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/draggableattribute.test63
-rwxr-xr-xtests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/html-xmlns-attribute.test23
-rwxr-xr-xtests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/idattribute.test115
-rwxr-xr-xtests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/inputattributes.test2795
-rwxr-xr-xtests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/irrelevantattribute.test63
-rwxr-xr-xtests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/langattribute.test5579
-rwxr-xr-xtests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/li-value-attribute.test7
-rwxr-xr-xtests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/link-href-attribute.test7
-rwxr-xr-xtests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/link-hreflang-attribute.test7
-rwxr-xr-xtests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/link-rel-attribute.test271
-rwxr-xr-xtests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/ol-start-attribute.test7
-rwxr-xr-xtests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/starttags.test375
-rwxr-xr-xtests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/style-scoped-attribute.test7
-rwxr-xr-xtests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/tabindexattribute.test79
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/tokenizertotree.py68
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/us-ascii.html3
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/utf-8-bom.html3
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/tokenizer.py1731
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/treeadapters/__init__.py0
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/treeadapters/sax.py44
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/treebuilders/__init__.py76
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/treebuilders/_base.py377
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/treebuilders/dom.py227
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/treebuilders/etree.py337
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/treebuilders/etree_lxml.py369
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/treewalkers/__init__.py57
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/treewalkers/_base.py200
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/treewalkers/dom.py46
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/treewalkers/etree.py138
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/treewalkers/genshistream.py69
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/treewalkers/lxmletree.py204
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/treewalkers/pulldom.py63
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/trie/__init__.py12
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/trie/_base.py37
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/trie/datrie.py44
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/trie/py.py67
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/html5lib/utils.py82
-rwxr-xr-xtests/wpt/web-platform-tests/tools/html5lib/parse.py233
-rwxr-xr-xtests/wpt/web-platform-tests/tools/html5lib/requirements-install.sh16
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/requirements-optional-2.6.txt5
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/requirements-optional-cpython.txt5
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/requirements-optional.txt13
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/requirements-test.txt5
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/requirements.txt1
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/setup.py44
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/tox.ini30
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/utils/entities.py88
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/utils/iana_parse.py24
-rw-r--r--tests/wpt/web-platform-tests/tools/html5lib/utils/spider.py122
-rw-r--r--tests/wpt/web-platform-tests/tools/lint/__init__.py1
-rw-r--r--tests/wpt/web-platform-tests/tools/lint/lint.py259
-rw-r--r--tests/wpt/web-platform-tests/tools/lint/lint.whitelist104
-rw-r--r--tests/wpt/web-platform-tests/tools/localpaths.py11
-rw-r--r--tests/wpt/web-platform-tests/tools/manifest/__init__.py5
-rw-r--r--tests/wpt/web-platform-tests/tools/manifest/item.py175
-rw-r--r--tests/wpt/web-platform-tests/tools/manifest/log.py8
-rw-r--r--tests/wpt/web-platform-tests/tools/manifest/manifest.py374
-rw-r--r--tests/wpt/web-platform-tests/tools/manifest/sourcefile.py268
-rw-r--r--tests/wpt/web-platform-tests/tools/manifest/tree.py166
-rw-r--r--tests/wpt/web-platform-tests/tools/manifest/update.py98
-rw-r--r--tests/wpt/web-platform-tests/tools/manifest/utils.py43
-rw-r--r--tests/wpt/web-platform-tests/tools/manifest/vcs.py21
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/COPYING28
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/MANIFEST.in6
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/README17
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/example/abort_handshake_wsh.py43
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/example/abort_wsh.py43
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/example/arraybuffer_benchmark.html134
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/example/bench_wsh.py60
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/example/benchmark.html203
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/example/benchmark.js309
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/example/benchmark_helper_wsh.py85
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/example/close_wsh.py69
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/example/console.html317
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/example/cookie_wsh.py32
-rwxr-xr-xtests/wpt/web-platform-tests/tools/pywebsocket/src/example/echo_client.py1128
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/example/echo_noext_wsh.py61
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/example/echo_wsh.py54
-rwxr-xr-xtests/wpt/web-platform-tests/tools/pywebsocket/src/example/eventsource.cgi54
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/example/eventsource.html74
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/example/handler_map.txt11
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/example/hsts_wsh.py40
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/example/internal_error_wsh.py42
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/example/origin_check_wsh.py44
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/example/pywebsocket.conf42
-rwxr-xr-xtests/wpt/web-platform-tests/tools/pywebsocket/src/example/special_headers.cgi28
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/example/util.js177
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/example/util_main.js63
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/example/util_worker.js19
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/example/xhr_benchmark.html222
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/example/xhr_benchmark.js389
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/example/xhr_event_logger.html110
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/__init__.py224
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/_stream_base.py181
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/_stream_hixie75.py229
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/_stream_hybi.py887
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/common.py303
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/dispatch.py393
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/extensions.py885
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/fast_masking.i98
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/handshake/__init__.py110
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/handshake/_base.py182
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/handshake/hybi.py420
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/handshake/hybi00.py293
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/headerparserhandler.py254
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/http_header_util.py263
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/memorizingfile.py99
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/msgutil.py219
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/mux.py1889
-rwxr-xr-xtests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/standalone.py1193
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/stream.py57
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/util.py416
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/xhr_benchmark_handler.py109
-rwxr-xr-xtests/wpt/web-platform-tests/tools/pywebsocket/src/setup.py74
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/test/__init__.py0
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/test/cert/cacert.pem17
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/test/cert/cert.pem61
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/test/cert/client_cert.p12bin0 -> 2582 bytes
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/test/cert/key.pem15
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/test/client_for_testing.py1100
-rwxr-xr-xtests/wpt/web-platform-tests/tools/pywebsocket/src/test/endtoend_with_external_server.py67
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/test/mock.py221
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/test/mux_client_for_testing.py690
-rwxr-xr-xtests/wpt/web-platform-tests/tools/pywebsocket/src/test/run_all.py89
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/test/set_sys_path.py45
-rwxr-xr-xtests/wpt/web-platform-tests/tools/pywebsocket/src/test/test_dispatch.py288
-rwxr-xr-xtests/wpt/web-platform-tests/tools/pywebsocket/src/test/test_endtoend.py753
-rwxr-xr-xtests/wpt/web-platform-tests/tools/pywebsocket/src/test/test_extensions.py360
-rwxr-xr-xtests/wpt/web-platform-tests/tools/pywebsocket/src/test/test_handshake.py188
-rwxr-xr-xtests/wpt/web-platform-tests/tools/pywebsocket/src/test/test_handshake_hybi.py534
-rwxr-xr-xtests/wpt/web-platform-tests/tools/pywebsocket/src/test/test_handshake_hybi00.py516
-rwxr-xr-xtests/wpt/web-platform-tests/tools/pywebsocket/src/test/test_http_header_util.py90
-rwxr-xr-xtests/wpt/web-platform-tests/tools/pywebsocket/src/test/test_memorizingfile.py104
-rwxr-xr-xtests/wpt/web-platform-tests/tools/pywebsocket/src/test/test_mock.py145
-rwxr-xr-xtests/wpt/web-platform-tests/tools/pywebsocket/src/test/test_msgutil.py1356
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/test/test_mux.py2089
-rwxr-xr-xtests/wpt/web-platform-tests/tools/pywebsocket/src/test/test_stream.py77
-rwxr-xr-xtests/wpt/web-platform-tests/tools/pywebsocket/src/test/test_stream_hixie75.py59
-rwxr-xr-xtests/wpt/web-platform-tests/tools/pywebsocket/src/test/test_util.py200
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/test/testdata/README1
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/test/testdata/handlers/abort_by_user_wsh.py42
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/test/testdata/handlers/blank_wsh.py31
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/test/testdata/handlers/origin_check_wsh.py42
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/test/testdata/handlers/sub/exception_in_transfer_wsh.py44
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/test/testdata/handlers/sub/no_wsh_at_the_end.py45
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/test/testdata/handlers/sub/non_callable_wsh.py39
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/test/testdata/handlers/sub/plain_wsh.py40
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/test/testdata/handlers/sub/wrong_handshake_sig_wsh.py45
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/test/testdata/handlers/sub/wrong_transfer_sig_wsh.py45
-rw-r--r--tests/wpt/web-platform-tests/tools/pywebsocket/src/test/testdata/hello.pl32
-rw-r--r--tests/wpt/web-platform-tests/tools/runner/css/bootstrap-theme.min.css7
-rw-r--r--tests/wpt/web-platform-tests/tools/runner/css/bootstrap.min.css7
-rw-r--r--tests/wpt/web-platform-tests/tools/runner/fonts/glyphicons-halflings-regular.eotbin0 -> 20335 bytes
-rw-r--r--tests/wpt/web-platform-tests/tools/runner/fonts/glyphicons-halflings-regular.svg229
-rw-r--r--tests/wpt/web-platform-tests/tools/runner/fonts/glyphicons-halflings-regular.ttfbin0 -> 41280 bytes
-rw-r--r--tests/wpt/web-platform-tests/tools/runner/fonts/glyphicons-halflings-regular.woffbin0 -> 23320 bytes
-rw-r--r--tests/wpt/web-platform-tests/tools/runner/index.html178
-rw-r--r--tests/wpt/web-platform-tests/tools/runner/logo.svg8
-rw-r--r--tests/wpt/web-platform-tests/tools/runner/report.css43
-rw-r--r--tests/wpt/web-platform-tests/tools/runner/report.py310
-rw-r--r--tests/wpt/web-platform-tests/tools/runner/runner.css193
-rw-r--r--tests/wpt/web-platform-tests/tools/runner/runner.js729
-rw-r--r--tests/wpt/web-platform-tests/tools/runner/update_manifest.py19
-rw-r--r--tests/wpt/web-platform-tests/tools/scripts/id2path.js12
-rw-r--r--tests/wpt/web-platform-tests/tools/scripts/id2path.json822
-rw-r--r--tests/wpt/web-platform-tests/tools/scripts/manifest.js140
-rw-r--r--tests/wpt/web-platform-tests/tools/scripts/package.json11
-rw-r--r--tests/wpt/web-platform-tests/tools/scripts/toc.js107
-rw-r--r--tests/wpt/web-platform-tests/tools/scripts/update-directory-structure.js106
-rw-r--r--tests/wpt/web-platform-tests/tools/serve/__init__.py1
-rw-r--r--tests/wpt/web-platform-tests/tools/serve/serve.py456
-rw-r--r--tests/wpt/web-platform-tests/tools/six/.gitignore9
-rw-r--r--tests/wpt/web-platform-tests/tools/six/.hgignore8
-rw-r--r--tests/wpt/web-platform-tests/tools/six/CHANGES246
-rw-r--r--tests/wpt/web-platform-tests/tools/six/CONTRIBUTORS22
-rw-r--r--tests/wpt/web-platform-tests/tools/six/LICENSE18
-rw-r--r--tests/wpt/web-platform-tests/tools/six/MANIFEST.in6
-rw-r--r--tests/wpt/web-platform-tests/tools/six/README16
-rw-r--r--tests/wpt/web-platform-tests/tools/six/documentation/Makefile130
-rw-r--r--tests/wpt/web-platform-tests/tools/six/documentation/conf.py217
-rw-r--r--tests/wpt/web-platform-tests/tools/six/documentation/index.rst785
-rw-r--r--tests/wpt/web-platform-tests/tools/six/setup.cfg2
-rw-r--r--tests/wpt/web-platform-tests/tools/six/setup.py32
-rw-r--r--tests/wpt/web-platform-tests/tools/six/six.py787
-rw-r--r--tests/wpt/web-platform-tests/tools/six/test_six.py787
-rw-r--r--tests/wpt/web-platform-tests/tools/six/tox.ini12
-rw-r--r--tests/wpt/web-platform-tests/tools/sslutils/__init__.py9
-rw-r--r--tests/wpt/web-platform-tests/tools/sslutils/base.py23
-rw-r--r--tests/wpt/web-platform-tests/tools/sslutils/openssl.py386
-rw-r--r--tests/wpt/web-platform-tests/tools/sslutils/pregenerated.py26
-rw-r--r--tests/wpt/web-platform-tests/tools/webdriver/webdriver/__init__.py0
-rw-r--r--tests/wpt/web-platform-tests/tools/webdriver/webdriver/alert.py26
-rw-r--r--tests/wpt/web-platform-tests/tools/webdriver/webdriver/capabilities.py30
-rw-r--r--tests/wpt/web-platform-tests/tools/webdriver/webdriver/command.py111
-rw-r--r--tests/wpt/web-platform-tests/tools/webdriver/webdriver/driver.py199
-rw-r--r--tests/wpt/web-platform-tests/tools/webdriver/webdriver/exceptions.py166
-rw-r--r--tests/wpt/web-platform-tests/tools/webdriver/webdriver/keys.py68
-rw-r--r--tests/wpt/web-platform-tests/tools/webdriver/webdriver/searchcontext.py54
-rw-r--r--tests/wpt/web-platform-tests/tools/webdriver/webdriver/wait.py87
-rw-r--r--tests/wpt/web-platform-tests/tools/webdriver/webdriver/webelement.py56
-rw-r--r--tests/wpt/web-platform-tests/tools/wptserve/.gitignore40
-rw-r--r--tests/wpt/web-platform-tests/tools/wptserve/MANIFEST.in1
-rw-r--r--tests/wpt/web-platform-tests/tools/wptserve/README.md4
-rw-r--r--tests/wpt/web-platform-tests/tools/wptserve/docs/Makefile153
-rw-r--r--tests/wpt/web-platform-tests/tools/wptserve/docs/conf.py243
-rw-r--r--tests/wpt/web-platform-tests/tools/wptserve/docs/handlers.rst111
-rw-r--r--tests/wpt/web-platform-tests/tools/wptserve/docs/index.rst35
-rw-r--r--tests/wpt/web-platform-tests/tools/wptserve/docs/introduction.rst51
-rw-r--r--tests/wpt/web-platform-tests/tools/wptserve/docs/make.bat190
-rw-r--r--tests/wpt/web-platform-tests/tools/wptserve/docs/pipes.rst157
-rw-r--r--tests/wpt/web-platform-tests/tools/wptserve/docs/request.rst10
-rw-r--r--tests/wpt/web-platform-tests/tools/wptserve/docs/response.rst41
-rw-r--r--tests/wpt/web-platform-tests/tools/wptserve/docs/router.rst78
-rw-r--r--tests/wpt/web-platform-tests/tools/wptserve/docs/server.rst20
-rw-r--r--tests/wpt/web-platform-tests/tools/wptserve/docs/stash.rst31
-rw-r--r--tests/wpt/web-platform-tests/tools/wptserve/setup.py23
-rw-r--r--tests/wpt/web-platform-tests/tools/wptserve/tests/functional/base.py61
-rw-r--r--tests/wpt/web-platform-tests/tools/wptserve/tests/functional/docroot/document.txt1
-rw-r--r--tests/wpt/web-platform-tests/tools/wptserve/tests/functional/docroot/sub.txt1
-rw-r--r--tests/wpt/web-platform-tests/tools/wptserve/tests/functional/docroot/sub_headers.txt1
-rw-r--r--tests/wpt/web-platform-tests/tools/wptserve/tests/functional/docroot/sub_params.txt1
-rw-r--r--tests/wpt/web-platform-tests/tools/wptserve/tests/functional/docroot/test.asis5
-rw-r--r--tests/wpt/web-platform-tests/tools/wptserve/tests/functional/docroot/test_string.py3
-rw-r--r--tests/wpt/web-platform-tests/tools/wptserve/tests/functional/docroot/test_tuple_2.py2
-rw-r--r--tests/wpt/web-platform-tests/tools/wptserve/tests/functional/docroot/test_tuple_3.py2
-rw-r--r--tests/wpt/web-platform-tests/tools/wptserve/tests/functional/docroot/with_headers.txt1
-rw-r--r--tests/wpt/web-platform-tests/tools/wptserve/tests/functional/docroot/with_headers.txt.sub.headers3
-rw-r--r--tests/wpt/web-platform-tests/tools/wptserve/tests/functional/test_cookies.py65
-rw-r--r--tests/wpt/web-platform-tests/tools/wptserve/tests/functional/test_handlers.py212
-rw-r--r--tests/wpt/web-platform-tests/tools/wptserve/tests/functional/test_pipes.py80
-rw-r--r--tests/wpt/web-platform-tests/tools/wptserve/tests/functional/test_request.py86
-rw-r--r--tests/wpt/web-platform-tests/tools/wptserve/tests/functional/test_response.py51
-rw-r--r--tests/wpt/web-platform-tests/tools/wptserve/tests/functional/test_server.py43
-rw-r--r--tests/wpt/web-platform-tests/tools/wptserve/tests/functional/test_stash.py39
-rw-r--r--tests/wpt/web-platform-tests/tools/wptserve/wptserve/__init__.py3
-rw-r--r--tests/wpt/web-platform-tests/tools/wptserve/wptserve/constants.py92
-rw-r--r--tests/wpt/web-platform-tests/tools/wptserve/wptserve/handlers.py329
-rw-r--r--tests/wpt/web-platform-tests/tools/wptserve/wptserve/logger.py29
-rw-r--r--tests/wpt/web-platform-tests/tools/wptserve/wptserve/pipes.py447
-rw-r--r--tests/wpt/web-platform-tests/tools/wptserve/wptserve/ranges.py90
-rw-r--r--tests/wpt/web-platform-tests/tools/wptserve/wptserve/request.py576
-rw-r--r--tests/wpt/web-platform-tests/tools/wptserve/wptserve/response.py443
-rw-r--r--tests/wpt/web-platform-tests/tools/wptserve/wptserve/router.py168
-rw-r--r--tests/wpt/web-platform-tests/tools/wptserve/wptserve/routes.py6
-rw-r--r--tests/wpt/web-platform-tests/tools/wptserve/wptserve/server.py456
-rw-r--r--tests/wpt/web-platform-tests/tools/wptserve/wptserve/stash.py84
-rw-r--r--tests/wpt/web-platform-tests/tools/wptserve/wptserve/utils.py14
-rwxr-xr-xtests/wpt/web-platform-tests/tools/wptserve/wptserve/wptserve.py33
-rw-r--r--tests/wpt/web-platform-tests/touch-events/create-touch-touchlist.html185
-rw-r--r--tests/wpt/web-platform-tests/touch-events/multi-touch-interactions-manual.html49
-rw-r--r--tests/wpt/web-platform-tests/touch-events/multi-touch-interactions.js371
-rw-r--r--tests/wpt/web-platform-tests/touch-events/multi-touch-interfaces-manual.html273
-rw-r--r--tests/wpt/web-platform-tests/touch-events/single-touch-manual.html378
-rw-r--r--tests/wpt/web-platform-tests/typedarrays/ArrayBuffer_constructor.html30
-rw-r--r--tests/wpt/web-platform-tests/typedarrays/ArrayBuffer_properties.html67
-rw-r--r--tests/wpt/web-platform-tests/typedarrays/Uint8ClampedArray_constructor.html35
-rw-r--r--tests/wpt/web-platform-tests/typedarrays/Uint8ClampedArray_length.html25
-rw-r--r--tests/wpt/web-platform-tests/typedarrays/Uint8ClampedArray_setter_getter.html66
-rw-r--r--tests/wpt/web-platform-tests/typedarrays/Uint8ClampedArray_subarray.html50
-rw-r--r--tests/wpt/web-platform-tests/typedarrays/constructors.html48
-rw-r--r--tests/wpt/web-platform-tests/url/README.md15
-rw-r--r--tests/wpt/web-platform-tests/url/a-element.html51
-rw-r--r--tests/wpt/web-platform-tests/url/a-element.xhtml62
-rw-r--r--tests/wpt/web-platform-tests/url/interfaces.html81
-rw-r--r--tests/wpt/web-platform-tests/url/urltestdata.txt341
-rw-r--r--tests/wpt/web-platform-tests/url/urltestparser.js79
-rw-r--r--tests/wpt/web-platform-tests/user-timing/idlharness.html59
-rw-r--r--tests/wpt/web-platform-tests/user-timing/resources/webperftestharness.js155
-rw-r--r--tests/wpt/web-platform-tests/user-timing/resources/webperftestharnessextension.js199
-rw-r--r--tests/wpt/web-platform-tests/user-timing/test_user_timing_clear_marks.html134
-rw-r--r--tests/wpt/web-platform-tests/user-timing/test_user_timing_clear_measures.html136
-rw-r--r--tests/wpt/web-platform-tests/user-timing/test_user_timing_entry_type.html29
-rw-r--r--tests/wpt/web-platform-tests/user-timing/test_user_timing_exists.html28
-rw-r--r--tests/wpt/web-platform-tests/user-timing/test_user_timing_mark.html228
-rw-r--r--tests/wpt/web-platform-tests/user-timing/test_user_timing_mark_and_measure_exception_when_invoke_without_parameter.html67
-rw-r--r--tests/wpt/web-platform-tests/user-timing/test_user_timing_mark_exceptions.html105
-rw-r--r--tests/wpt/web-platform-tests/user-timing/test_user_timing_mark_with_name_of_navigation_timing_optional_attribute.html55
-rw-r--r--tests/wpt/web-platform-tests/user-timing/test_user_timing_measure.html334
-rw-r--r--tests/wpt/web-platform-tests/user-timing/test_user_timing_measure_exceptions.html282
-rw-r--r--tests/wpt/web-platform-tests/user-timing/test_user_timing_measure_navigation_timing.html233
-rw-r--r--tests/wpt/web-platform-tests/vibration/api-is-present.html28
-rw-r--r--tests/wpt/web-platform-tests/vibration/cancel-when-hidden-manual.html38
-rw-r--r--tests/wpt/web-platform-tests/vibration/cancel-with-0-manual.html31
-rw-r--r--tests/wpt/web-platform-tests/vibration/cancel-with-array-0-manual.html33
-rw-r--r--tests/wpt/web-platform-tests/vibration/cancel-with-empty-array-manual.html31
-rw-r--r--tests/wpt/web-platform-tests/vibration/cancel-with-new-manual.html32
-rw-r--r--tests/wpt/web-platform-tests/vibration/idl.html23
-rw-r--r--tests/wpt/web-platform-tests/vibration/invalid-values.html79
-rw-r--r--tests/wpt/web-platform-tests/vibration/pattern-array-extra-manual.html27
-rw-r--r--tests/wpt/web-platform-tests/vibration/pattern-array-manual.html26
-rw-r--r--tests/wpt/web-platform-tests/vibration/pattern-array-with-0-manual.html26
-rw-r--r--tests/wpt/web-platform-tests/vibration/silent-ignore.html32
-rw-r--r--tests/wpt/web-platform-tests/vibration/simple-array-manual.html23
-rw-r--r--tests/wpt/web-platform-tests/vibration/simple-scalar-manual.html25
-rw-r--r--tests/wpt/web-platform-tests/web-animations/README.md4
-rw-r--r--tests/wpt/web-platform-tests/web-animations/animation-node/animation-node-after.html420
-rw-r--r--tests/wpt/web-platform-tests/web-animations/animation-node/animation-node-before.html419
-rw-r--r--tests/wpt/web-platform-tests/web-animations/animation-node/animation-node-next-sibling.html504
-rw-r--r--tests/wpt/web-platform-tests/web-animations/animation-node/animation-node-parent.html54
-rw-r--r--tests/wpt/web-platform-tests/web-animations/animation-node/animation-node-previous-sibling.html512
-rw-r--r--tests/wpt/web-platform-tests/web-animations/animation-node/animation-node-remove.html240
-rw-r--r--tests/wpt/web-platform-tests/web-animations/animation-node/animation-node-replace.html445
-rw-r--r--tests/wpt/web-platform-tests/web-animations/animation-node/idlharness.html54
-rw-r--r--tests/wpt/web-platform-tests/web-animations/animation-timeline/animation-timeline.html89
-rw-r--r--tests/wpt/web-platform-tests/web-animations/animation-timeline/idlharness.html26
-rw-r--r--tests/wpt/web-platform-tests/web-animations/testcommon.js58
-rw-r--r--tests/wpt/web-platform-tests/webaudio/.gitignore1
-rw-r--r--tests/wpt/web-platform-tests/webaudio/README.md5
-rw-r--r--tests/wpt/web-platform-tests/webaudio/js/buffer-loader.js44
-rw-r--r--tests/wpt/web-platform-tests/webaudio/js/helpers.js33
-rw-r--r--tests/wpt/web-platform-tests/webaudio/js/lodash.js4282
-rw-r--r--tests/wpt/web-platform-tests/webaudio/js/vendor-prefixes.js2
-rwxr-xr-xtests/wpt/web-platform-tests/webaudio/refresh_idl.rb57
-rw-r--r--tests/wpt/web-platform-tests/webaudio/resources/sin_440Hz_-6dBFS_1s.wavbin0 -> 88246 bytes
-rw-r--r--tests/wpt/web-platform-tests/webaudio/specification.html5911
-rw-r--r--tests/wpt/web-platform-tests/webaudio/the-audio-api/the-analysernode-interface/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/webaudio/the-audio-api/the-audiobuffer-interface/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/webaudio/the-audio-api/the-audiobuffer-interface/idl-test.html107
-rw-r--r--tests/wpt/web-platform-tests/webaudio/the-audio-api/the-audiobuffersourcenode-interface/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/webaudio/the-audio-api/the-audiocontext-interface/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/webaudio/the-audio-api/the-audiodestinationnode-interface/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/webaudio/the-audio-api/the-audiodestinationnode-interface/idl-test.html128
-rw-r--r--tests/wpt/web-platform-tests/webaudio/the-audio-api/the-audiolistener-interface/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/webaudio/the-audio-api/the-audionode-interface/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/webaudio/the-audio-api/the-audioparam-interface/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/webaudio/the-audio-api/the-audioprocessingevent-interface/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/webaudio/the-audio-api/the-biquadfilternode-interface/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/webaudio/the-audio-api/the-channelmergernode-interface/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/webaudio/the-audio-api/the-channelsplitternode-interface/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/webaudio/the-audio-api/the-convolvernode-interface/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/webaudio/the-audio-api/the-delaynode-interface/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/webaudio/the-audio-api/the-delaynode-interface/idl-test.html152
-rw-r--r--tests/wpt/web-platform-tests/webaudio/the-audio-api/the-dynamicscompressornode-interface/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/webaudio/the-audio-api/the-gainnode-interface/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/webaudio/the-audio-api/the-gainnode-interface/gain-expected.wavbin0 -> 281400 bytes
-rw-r--r--tests/wpt/web-platform-tests/webaudio/the-audio-api/the-gainnode-interface/idl-test.html152
-rw-r--r--tests/wpt/web-platform-tests/webaudio/the-audio-api/the-gainnode-interface/test.html121
-rw-r--r--tests/wpt/web-platform-tests/webaudio/the-audio-api/the-mediaelementaudiosourcenode-interface/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/webaudio/the-audio-api/the-mediaelementaudiosourcenode-interface/mediaElementAudioSourceToScriptProcessorTest.html123
-rw-r--r--tests/wpt/web-platform-tests/webaudio/the-audio-api/the-mediastreamaudiodestinationnode-interface/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/webaudio/the-audio-api/the-mediastreamaudiosourcenode-interface/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/webaudio/the-audio-api/the-offlineaudiocontext-interface/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/webaudio/the-audio-api/the-oscillatornode-interface/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/webaudio/the-audio-api/the-pannernode-interface/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/webaudio/the-audio-api/the-periodicwave-interface/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/webaudio/the-audio-api/the-scriptprocessornode-interface/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/webaudio/the-audio-api/the-waveshapernode-interface/.gitkeep0
-rw-r--r--tests/wpt/web-platform-tests/webaudio/the-audio-api/the-waveshapernode-interface/curve-tests.html212
-rw-r--r--tests/wpt/web-platform-tests/webdriver/README.md38
-rw-r--r--tests/wpt/web-platform-tests/webdriver/base_test.py49
-rw-r--r--tests/wpt/web-platform-tests/webdriver/cookie/__init__.py0
-rw-r--r--tests/wpt/web-platform-tests/webdriver/cookie/cookie_test.py67
-rw-r--r--tests/wpt/web-platform-tests/webdriver/cookie/res/cookie_container.html5
-rw-r--r--tests/wpt/web-platform-tests/webdriver/ecmascript/ecmascript_test.py17
-rw-r--r--tests/wpt/web-platform-tests/webdriver/ecmascript/res/ecmascript_test.html2
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_location/__init__.py0
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_location/element_location_test.py37
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_location/res/elements.html10
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/__init__.py0
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/method_test.py71
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/res/0x0-pixels.html12
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/res/1x1-pixels.html12
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/res/a-with-href-attribute.html5
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/res/absolute-children-ancestor-hidden-overflow.html16
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/res/body_empty.html4
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/res/body_implicit.html3
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/res/body_overflow_hidden.html4
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/res/body_visibility_hidden.html4
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/res/display-block.html5
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/res/display-none-child-link.html11
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/res/display-none-child-paragraph.html11
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/res/display-none-child.html11
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/res/display-none-dynamic.html10
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/res/display-none-parent-presedence-visibility.html15
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/res/display-none-parent-presedence.html14
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/res/display-none.html11
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/res/element-dynamically-moved-outside-viewport.html15
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/res/element-hidden-by-other-element.html20
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/res/element-hidden-by-z-index.html29
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/res/element-moved-behind-other-element-by-transform.html31
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/res/element-moved-outside-viewport-by-transform.html15
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/res/element-outside-viewport.html13
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/res/element-partially-hidden-by-other-element.html23
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/res/element-with-color-style-attribute.html5
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/res/element-with-custom-attribute.html5
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/res/element-with-id-attribute.html5
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/res/element-with-same-color-as-background.html10
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/res/element-with-same-color-as-parent-background.html18
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/res/element-with-style-attribute.html5
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/res/element-without-attribute.html5
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/res/hidden-input-type-checkbox-untogglable.html9
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/res/hidden-input-type-text-writing.html9
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/res/hidden.html5
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/res/img-with-src-attribute.html5
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/res/input-morphs-into-hidden.html10
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/res/input-type-hidden-unclickable.html5
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/res/input-type-hidden.html5
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/res/input-with-checked-attribute.html5
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/res/input-without-checked-attribute.html5
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/res/option-with-value-attribute.html7
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/res/option-without-value-attribute.html7
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/res/text-with-matching-color-and-background.html14
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/res/text-with-same-color-as-background.html12
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/res/text-with-same-color-as-parent-background.html14
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/res/visibility-child-link.html11
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/res/visibility-child-paragraph.html11
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/res/visibility-child-presedence.html12
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/res/visibility-child.html11
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/res/visibility-hidden.html11
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/res/visibility-visible.html5
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/res/x-auto-y-hidden.html30
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/res/x-hidden-y-auto.html30
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/res/x-hidden-y-hidden.html30
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/res/x-hidden-y-scroll.html30
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/res/x-scroll-y-hidden.html30
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/res/zero-sized-element-with-sizable-decendant.html14
-rw-r--r--tests/wpt/web-platform-tests/webdriver/element_state/visibility_test.py324
-rw-r--r--tests/wpt/web-platform-tests/webdriver/javascript/__init__.py0
-rw-r--r--tests/wpt/web-platform-tests/webdriver/javascript/execute_script_test.py128
-rw-r--r--tests/wpt/web-platform-tests/webdriver/javascript/res/execute_script_test.html2
-rw-r--r--tests/wpt/web-platform-tests/webdriver/javascript/res/return_array_of_dom_elements.html3
-rw-r--r--tests/wpt/web-platform-tests/webdriver/javascript/res/return_document_body.html2
-rw-r--r--tests/wpt/web-platform-tests/webdriver/javascript/res/return_node_list.html3
-rw-r--r--tests/wpt/web-platform-tests/webdriver/modal/__init__.py0
-rw-r--r--tests/wpt/web-platform-tests/webdriver/modal/alerts_quit_test.py25
-rw-r--r--tests/wpt/web-platform-tests/webdriver/modal/alerts_test.py147
-rw-r--r--tests/wpt/web-platform-tests/webdriver/modal/res/alerts.html53
-rw-r--r--tests/wpt/web-platform-tests/webdriver/navigation/__init__.py0
-rw-r--r--tests/wpt/web-platform-tests/webdriver/navigation/auth_tests.py42
-rw-r--r--tests/wpt/web-platform-tests/webdriver/navigation/forward.py24
-rw-r--r--tests/wpt/web-platform-tests/webdriver/navigation/forwardToNothing.py20
-rw-r--r--tests/wpt/web-platform-tests/webdriver/navigation/get_from_http_test.py60
-rw-r--r--tests/wpt/web-platform-tests/webdriver/navigation/invalid_cert_test.py28
-rw-r--r--tests/wpt/web-platform-tests/webdriver/navigation/refresh-page.py27
-rw-r--r--tests/wpt/web-platform-tests/webdriver/navigation/res/1s-meta-redirect.html4
-rw-r--r--tests/wpt/web-platform-tests/webdriver/navigation/res/60s-meta-redirect.html4
-rw-r--r--tests/wpt/web-platform-tests/webdriver/navigation/res/authenticated.html5
-rw-r--r--tests/wpt/web-platform-tests/webdriver/navigation/res/empty.html4
-rw-r--r--tests/wpt/web-platform-tests/webdriver/navigation/res/forwardNext.html6
-rw-r--r--tests/wpt/web-platform-tests/webdriver/navigation/res/forwardStart.html6
-rw-r--r--tests/wpt/web-platform-tests/webdriver/navigation/res/fragment.html9
-rw-r--r--tests/wpt/web-platform-tests/webdriver/navigation/res/instant-meta-redirect.html4
-rw-r--r--tests/wpt/web-platform-tests/webdriver/navigation/res/refreshPageDynamic.html10
-rw-r--r--tests/wpt/web-platform-tests/webdriver/navigation/res/refreshPageStatic.html6
-rw-r--r--tests/wpt/web-platform-tests/webdriver/navigation/res/self-signed.key28
-rw-r--r--tests/wpt/web-platform-tests/webdriver/network.py30
-rw-r--r--tests/wpt/web-platform-tests/webdriver/runtests.py14
-rw-r--r--tests/wpt/web-platform-tests/webdriver/timeouts/__init__.py0
-rw-r--r--tests/wpt/web-platform-tests/webdriver/timeouts/implicit_waits_tests.py64
-rw-r--r--tests/wpt/web-platform-tests/webdriver/timeouts/page_load_timeouts_tests.py26
-rw-r--r--tests/wpt/web-platform-tests/webdriver/timeouts/res/implicit_waits_tests.html38
-rw-r--r--tests/wpt/web-platform-tests/webdriver/timeouts/res/page_load_timeouts_tests.html12
-rw-r--r--tests/wpt/web-platform-tests/webdriver/user_input/__init__.py0
-rw-r--r--tests/wpt/web-platform-tests/webdriver/user_input/clear_test.py53
-rw-r--r--tests/wpt/web-platform-tests/webdriver/user_input/res/element_clear_contenteditable_page.html13
-rw-r--r--tests/wpt/web-platform-tests/webdriver/user_input/res/element_clear_disabled_input_page.html11
-rw-r--r--tests/wpt/web-platform-tests/webdriver/user_input/res/element_clear_disabled_textarea_page.html13
-rw-r--r--tests/wpt/web-platform-tests/webdriver/user_input/res/element_clear_readonly_input_page.html11
-rw-r--r--tests/wpt/web-platform-tests/webdriver/user_input/res/element_clear_readonly_textarea_page.html13
-rw-r--r--tests/wpt/web-platform-tests/webdriver/user_input/res/element_clear_writable_input_page.html11
-rw-r--r--tests/wpt/web-platform-tests/webdriver/user_input/res/element_clear_writable_textarea_page.html13
-rw-r--r--tests/wpt/web-platform-tests/webdriver/webdriver.cfg31
-rw-r--r--tests/wpt/web-platform-tests/webgl/bufferSubData.html26
-rw-r--r--tests/wpt/web-platform-tests/webgl/common.js13
-rw-r--r--tests/wpt/web-platform-tests/webgl/compressedTexImage2D.html30
-rw-r--r--tests/wpt/web-platform-tests/webgl/compressedTexSubImage2D.html30
-rw-r--r--tests/wpt/web-platform-tests/webgl/texImage2D.html20
-rw-r--r--tests/wpt/web-platform-tests/webgl/texSubImage2D.html20
-rw-r--r--tests/wpt/web-platform-tests/webgl/uniformMatrixNfv.html33
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/Channel_MessagePort_initial_disabled.htm36
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/Channel_MessagePort_onmessage_start.htm38
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/Channel_postMessage_DataCloneErr.htm26
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/Channel_postMessage_clone_port.htm42
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/Channel_postMessage_clone_port_error.htm26
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/Channel_postMessage_event_properties.htm36
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/Channel_postMessage_ports_readonly_array.htm38
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/Channel_postMessage_target_source.htm35
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/MessageEvent_properties.htm47
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/README.md10
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/Transferred_objects_unusable.sub.htm60
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/event.data.sub.htm58
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/event.origin.sub.htm56
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/event.ports.sub.htm49
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/event.source.htm51
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/event.source.xorigin.sub.htm51
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/message-channels/001.html17
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/message-channels/002.html14
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/message-channels/003.html19
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/message-channels/004-1.html8
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/message-channels/004-2.html10
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/message-channels/004.html22
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/postMessage_ArrayBuffer.sub.htm44
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/postMessage_Date.sub.htm40
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/postMessage_Document.htm36
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/postMessage_Function.htm36
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/postMessage_MessagePorts_sorigin.htm76
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/postMessage_MessagePorts_xorigin.sub.htm76
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/postMessage_arrays.sub.htm39
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/postMessage_asterisk_xorigin.sub.htm55
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/postMessage_dup_transfer_objects.htm38
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/postMessage_invalid_targetOrigin.htm38
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/postMessage_objects.sub.htm40
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/postMessage_origin_mismatch.sub.htm51
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/postMessage_origin_mismatch_xorigin.sub.htm51
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/postMessage_solidus_sorigin.htm43
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/postMessage_solidus_xorigin.sub.htm48
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/support/ChildWindowPostMessage.htm58
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/support/compare.js39
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/with-ports/001.html12
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/with-ports/002.html14
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/with-ports/003.html12
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/with-ports/004.html14
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/with-ports/005.html14
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/with-ports/006.html14
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/with-ports/007.html14
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/with-ports/010.html113
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/with-ports/011.html29
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/with-ports/012.html16
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/with-ports/013.html17
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/with-ports/014.html17
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/with-ports/015.html15
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/with-ports/016.html18
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/with-ports/017.html18
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/with-ports/018.html18
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/with-ports/019.html18
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/with-ports/020.html32
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/with-ports/021.html32
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/with-ports/023.html15
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/with-ports/024.html15
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/with-ports/025.html13
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/with-ports/026.html13
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/with-ports/027.html19
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/without-ports/001.html12
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/without-ports/002.html14
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/without-ports/003.html12
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/without-ports/004.html14
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/without-ports/005.html14
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/without-ports/006.html14
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/without-ports/007.html14
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/without-ports/008.html12
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/without-ports/009.html12
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/without-ports/010.html112
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/without-ports/011.html29
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/without-ports/012.html16
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/without-ports/013.html17
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/without-ports/014.html17
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/without-ports/015.html15
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/without-ports/016.html18
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/without-ports/017.html18
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/without-ports/018.html17
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/without-ports/019-1.html1
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/without-ports/019.html18
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/without-ports/020-1.html5
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/without-ports/020.html32
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/without-ports/021.html32
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/without-ports/023.html29
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/without-ports/024.html14
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/without-ports/025-1.js10
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/without-ports/025.html18
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/without-ports/026.html16
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/without-ports/027.html19
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/without-ports/028.html20
-rw-r--r--tests/wpt/web-platform-tests/webmessaging/without-ports/029.html20
-rw-r--r--tests/wpt/web-platform-tests/webrtc/simplecall.html126
-rw-r--r--tests/wpt/web-platform-tests/websockets/Close-0.htm25
-rw-r--r--tests/wpt/web-platform-tests/websockets/Close-1000-reason.htm35
-rw-r--r--tests/wpt/web-platform-tests/websockets/Close-1000.htm35
-rw-r--r--tests/wpt/web-platform-tests/websockets/Close-NaN.htm25
-rw-r--r--tests/wpt/web-platform-tests/websockets/Close-Reason-124Bytes.htm27
-rw-r--r--tests/wpt/web-platform-tests/websockets/Close-null.htm25
-rw-r--r--tests/wpt/web-platform-tests/websockets/Close-reason-unpaired-surrogates.htm36
-rw-r--r--tests/wpt/web-platform-tests/websockets/Close-string.htm25
-rw-r--r--tests/wpt/web-platform-tests/websockets/Close-undefined.htm25
-rw-r--r--tests/wpt/web-platform-tests/websockets/Create-Secure-blocked-port.htm19
-rw-r--r--tests/wpt/web-platform-tests/websockets/Create-Secure-extensions-empty.htm33
-rw-r--r--tests/wpt/web-platform-tests/websockets/Create-Secure-url-with-space.htm19
-rw-r--r--tests/wpt/web-platform-tests/websockets/Create-Secure-valid-url-array-protocols.htm34
-rw-r--r--tests/wpt/web-platform-tests/websockets/Create-Secure-valid-url-binaryType-blob.htm34
-rw-r--r--tests/wpt/web-platform-tests/websockets/Create-Secure-valid-url-protocol-setCorrectly.htm33
-rw-r--r--tests/wpt/web-platform-tests/websockets/Create-Secure-valid-url-protocol-string.htm34
-rw-r--r--tests/wpt/web-platform-tests/websockets/Create-Secure-valid-url.htm34
-rw-r--r--tests/wpt/web-platform-tests/websockets/Create-Secure-verify-url-set-non-default-port.htm19
-rw-r--r--tests/wpt/web-platform-tests/websockets/Create-invalid-urls.htm34
-rw-r--r--tests/wpt/web-platform-tests/websockets/Create-non-absolute-url.htm18
-rw-r--r--tests/wpt/web-platform-tests/websockets/Create-nonAscii-protocol-string.htm21
-rw-r--r--tests/wpt/web-platform-tests/websockets/Create-protocol-with-space.htm18
-rw-r--r--tests/wpt/web-platform-tests/websockets/Create-protocols-repeated.htm18
-rw-r--r--tests/wpt/web-platform-tests/websockets/Create-valid-url-array-protocols.htm35
-rw-r--r--tests/wpt/web-platform-tests/websockets/Create-valid-url-protocol-empty.htm19
-rw-r--r--tests/wpt/web-platform-tests/websockets/Create-valid-url-protocol.htm34
-rw-r--r--tests/wpt/web-platform-tests/websockets/Create-valid-url.htm34
-rw-r--r--tests/wpt/web-platform-tests/websockets/Create-verify-url-set-non-default-port.htm19
-rw-r--r--tests/wpt/web-platform-tests/websockets/Create-wrong-scheme.htm18
-rw-r--r--tests/wpt/web-platform-tests/websockets/README.md10
-rw-r--r--tests/wpt/web-platform-tests/websockets/Secure-Close-0.htm25
-rw-r--r--tests/wpt/web-platform-tests/websockets/Secure-Close-1000-reason.htm35
-rw-r--r--tests/wpt/web-platform-tests/websockets/Secure-Close-1000-verify-code.htm35
-rw-r--r--tests/wpt/web-platform-tests/websockets/Secure-Close-1000.htm35
-rw-r--r--tests/wpt/web-platform-tests/websockets/Secure-Close-1005-verify-code.htm35
-rw-r--r--tests/wpt/web-platform-tests/websockets/Secure-Close-1005.htm25
-rw-r--r--tests/wpt/web-platform-tests/websockets/Secure-Close-2999-reason.htm24
-rw-r--r--tests/wpt/web-platform-tests/websockets/Secure-Close-3000-reason.htm35
-rw-r--r--tests/wpt/web-platform-tests/websockets/Secure-Close-3000-verify-code.htm34
-rw-r--r--tests/wpt/web-platform-tests/websockets/Secure-Close-4999-reason.htm35
-rw-r--r--tests/wpt/web-platform-tests/websockets/Secure-Close-NaN.htm25
-rw-r--r--tests/wpt/web-platform-tests/websockets/Secure-Close-Reason-124Bytes.htm27
-rw-r--r--tests/wpt/web-platform-tests/websockets/Secure-Close-Reason-Unpaired-surrogates.htm37
-rw-r--r--tests/wpt/web-platform-tests/websockets/Secure-Close-null.htm25
-rw-r--r--tests/wpt/web-platform-tests/websockets/Secure-Close-onlyReason.htm24
-rw-r--r--tests/wpt/web-platform-tests/websockets/Secure-Close-readyState-Closed.htm35
-rw-r--r--tests/wpt/web-platform-tests/websockets/Secure-Close-readyState-Closing.htm27
-rw-r--r--tests/wpt/web-platform-tests/websockets/Secure-Close-server-initiated-close.htm35
-rw-r--r--tests/wpt/web-platform-tests/websockets/Secure-Close-string.htm25
-rw-r--r--tests/wpt/web-platform-tests/websockets/Secure-Close-undefined.htm25
-rw-r--r--tests/wpt/web-platform-tests/websockets/Secure-Send-65K-data.htm44
-rw-r--r--tests/wpt/web-platform-tests/websockets/Secure-Send-binary-65K-arraybuffer.htm44
-rw-r--r--tests/wpt/web-platform-tests/websockets/Secure-Send-binary-arraybuffer.htm44
-rw-r--r--tests/wpt/web-platform-tests/websockets/Secure-Send-binary-arraybufferview-float32.htm51
-rw-r--r--tests/wpt/web-platform-tests/websockets/Secure-Send-binary-arraybufferview-float64.htm51
-rw-r--r--tests/wpt/web-platform-tests/websockets/Secure-Send-binary-arraybufferview-int32.htm51
-rw-r--r--tests/wpt/web-platform-tests/websockets/Secure-Send-binary-arraybufferview-uint16-offset-length.htm51
-rw-r--r--tests/wpt/web-platform-tests/websockets/Secure-Send-binary-arraybufferview-uint32-offset.htm51
-rw-r--r--tests/wpt/web-platform-tests/websockets/Secure-Send-binary-arraybufferview-uint8-offset-length.htm51
-rw-r--r--tests/wpt/web-platform-tests/websockets/Secure-Send-binary-arraybufferview-uint8-offset.htm51
-rw-r--r--tests/wpt/web-platform-tests/websockets/Secure-Send-binary-blob.htm46
-rw-r--r--tests/wpt/web-platform-tests/websockets/Secure-Send-data.htm41
-rw-r--r--tests/wpt/web-platform-tests/websockets/Secure-Send-null.htm43
-rw-r--r--tests/wpt/web-platform-tests/websockets/Secure-Send-paired-surrogates.htm41
-rw-r--r--tests/wpt/web-platform-tests/websockets/Secure-Send-unicode-data.htm41
-rw-r--r--tests/wpt/web-platform-tests/websockets/Secure-Send-unpaired-surrogates.htm41
-rw-r--r--tests/wpt/web-platform-tests/websockets/Send-0byte-data.htm41
-rw-r--r--tests/wpt/web-platform-tests/websockets/Send-65K-data.htm44
-rw-r--r--tests/wpt/web-platform-tests/websockets/Send-Unpaired-Surrogates.htm41
-rw-r--r--tests/wpt/web-platform-tests/websockets/Send-before-open.htm18
-rw-r--r--tests/wpt/web-platform-tests/websockets/Send-binary-65K-arraybuffer.htm44
-rw-r--r--tests/wpt/web-platform-tests/websockets/Send-binary-arraybuffer.htm44
-rw-r--r--tests/wpt/web-platform-tests/websockets/Send-binary-arraybufferview-int16-offset.htm51
-rw-r--r--tests/wpt/web-platform-tests/websockets/Send-binary-arraybufferview-int8.htm51
-rw-r--r--tests/wpt/web-platform-tests/websockets/Send-binary-blob.htm46
-rw-r--r--tests/wpt/web-platform-tests/websockets/Send-data.htm41
-rw-r--r--tests/wpt/web-platform-tests/websockets/Send-null.htm43
-rw-r--r--tests/wpt/web-platform-tests/websockets/Send-paired-surrogates.htm41
-rw-r--r--tests/wpt/web-platform-tests/websockets/Send-unicode-data.htm41
-rw-r--r--tests/wpt/web-platform-tests/websockets/binary/001.html24
-rw-r--r--tests/wpt/web-platform-tests/websockets/binary/002.html25
-rw-r--r--tests/wpt/web-platform-tests/websockets/binary/004.html24
-rw-r--r--tests/wpt/web-platform-tests/websockets/binary/005.html22
-rw-r--r--tests/wpt/web-platform-tests/websockets/binaryType-wrong-value.htm38
-rw-r--r--tests/wpt/web-platform-tests/websockets/closing-handshake/002.html21
-rw-r--r--tests/wpt/web-platform-tests/websockets/closing-handshake/003.html20
-rw-r--r--tests/wpt/web-platform-tests/websockets/closing-handshake/004.html22
-rw-r--r--tests/wpt/web-platform-tests/websockets/constants.js18
-rw-r--r--tests/wpt/web-platform-tests/websockets/constructor.html13
-rw-r--r--tests/wpt/web-platform-tests/websockets/constructor/001.html11
-rw-r--r--tests/wpt/web-platform-tests/websockets/constructor/002.html18
-rw-r--r--tests/wpt/web-platform-tests/websockets/constructor/004.html23
-rw-r--r--tests/wpt/web-platform-tests/websockets/constructor/005.html11
-rw-r--r--tests/wpt/web-platform-tests/websockets/constructor/006.html26
-rw-r--r--tests/wpt/web-platform-tests/websockets/constructor/007.html9
-rw-r--r--tests/wpt/web-platform-tests/websockets/constructor/008.html13
-rw-r--r--tests/wpt/web-platform-tests/websockets/constructor/009.html21
-rw-r--r--tests/wpt/web-platform-tests/websockets/constructor/010.html20
-rw-r--r--tests/wpt/web-platform-tests/websockets/constructor/011.html25
-rw-r--r--tests/wpt/web-platform-tests/websockets/constructor/012.html17
-rw-r--r--tests/wpt/web-platform-tests/websockets/constructor/013.html39
-rw-r--r--tests/wpt/web-platform-tests/websockets/constructor/014.html35
-rw-r--r--tests/wpt/web-platform-tests/websockets/constructor/016.html17
-rw-r--r--tests/wpt/web-platform-tests/websockets/constructor/017.html13
-rw-r--r--tests/wpt/web-platform-tests/websockets/constructor/018.html17
-rw-r--r--tests/wpt/web-platform-tests/websockets/constructor/019.html18
-rw-r--r--tests/wpt/web-platform-tests/websockets/constructor/020.html18
-rw-r--r--tests/wpt/web-platform-tests/websockets/constructor/021.html9
-rw-r--r--tests/wpt/web-platform-tests/websockets/constructor/022.html20
-rw-r--r--tests/wpt/web-platform-tests/websockets/cookies/001.html23
-rw-r--r--tests/wpt/web-platform-tests/websockets/cookies/002.html20
-rw-r--r--tests/wpt/web-platform-tests/websockets/cookies/003.html33
-rw-r--r--tests/wpt/web-platform-tests/websockets/cookies/004.html29
-rw-r--r--tests/wpt/web-platform-tests/websockets/cookies/005.html32
-rw-r--r--tests/wpt/web-platform-tests/websockets/cookies/006.html27
-rw-r--r--tests/wpt/web-platform-tests/websockets/cookies/007.html30
-rw-r--r--tests/wpt/web-platform-tests/websockets/cookies/support/set-cookie.py5
-rw-r--r--tests/wpt/web-platform-tests/websockets/eventhandlers.html19
-rw-r--r--tests/wpt/web-platform-tests/websockets/extended-payload-length.html65
-rwxr-xr-xtests/wpt/web-platform-tests/websockets/handlers/echo-cookie_wsh.py12
-rwxr-xr-xtests/wpt/web-platform-tests/websockets/handlers/echo-query_v13_wsh.py11
-rwxr-xr-xtests/wpt/web-platform-tests/websockets/handlers/echo-query_wsh.py9
-rwxr-xr-xtests/wpt/web-platform-tests/websockets/handlers/echo_close_data_wsh.py22
-rwxr-xr-xtests/wpt/web-platform-tests/websockets/handlers/echo_exit_wsh.py21
-rwxr-xr-xtests/wpt/web-platform-tests/websockets/handlers/echo_raw_wsh.py15
-rwxr-xr-xtests/wpt/web-platform-tests/websockets/handlers/echo_wsh.py25
-rwxr-xr-xtests/wpt/web-platform-tests/websockets/handlers/empty-message_wsh.py13
-rwxr-xr-xtests/wpt/web-platform-tests/websockets/handlers/handshake_no_protocol_wsh.py12
-rwxr-xr-xtests/wpt/web-platform-tests/websockets/handlers/handshake_protocol_wsh.py12
-rwxr-xr-xtests/wpt/web-platform-tests/websockets/handlers/handshake_sleep_1_wsh.py10
-rwxr-xr-xtests/wpt/web-platform-tests/websockets/handlers/invalid_wsh.py9
-rwxr-xr-xtests/wpt/web-platform-tests/websockets/handlers/origin_wsh.py11
-rwxr-xr-xtests/wpt/web-platform-tests/websockets/handlers/protocol_array_wsh.py14
-rwxr-xr-xtests/wpt/web-platform-tests/websockets/handlers/protocol_wsh.py12
-rwxr-xr-xtests/wpt/web-platform-tests/websockets/handlers/set-cookie_http_wsh.py14
-rwxr-xr-xtests/wpt/web-platform-tests/websockets/handlers/set-cookie_wsh.py15
-rwxr-xr-xtests/wpt/web-platform-tests/websockets/handlers/simple_handshake_wsh.py13
-rwxr-xr-xtests/wpt/web-platform-tests/websockets/handlers/sleep_10_v13_wsh.py25
-rwxr-xr-xtests/wpt/web-platform-tests/websockets/handlers/wrong_accept_key_wsh.py13
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces.html79
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/CloseEvent/clean-close.html21
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/CloseEvent/constructor.html35
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/CloseEvent/historical.html18
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/bufferedAmount/bufferedAmount-arraybuffer.html23
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/bufferedAmount/bufferedAmount-blob.html24
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/bufferedAmount/bufferedAmount-defineProperty-getter.html16
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/bufferedAmount/bufferedAmount-defineProperty-setter.html18
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/bufferedAmount/bufferedAmount-deleting.html21
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/bufferedAmount/bufferedAmount-getting.html51
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/bufferedAmount/bufferedAmount-initial.html13
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/bufferedAmount/bufferedAmount-large.html25
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/bufferedAmount/bufferedAmount-readonly.html14
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/bufferedAmount/bufferedAmount-unicode.html21
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/close/close-basic.html22
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/close/close-connecting.html23
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/close/close-multiple.html22
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/close/close-nested.html26
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/close/close-replace.html13
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/close/close-return.html12
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/constants/001.html15
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/constants/002.html22
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/constants/003.html20
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/constants/004.html19
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/constants/005.html18
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/constants/006.html18
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/001.html15
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/002.html17
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/003.html19
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/004.html14
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/006.html15
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/007.html19
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/008.html22
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/009.html19
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/010.html19
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/011.html16
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/012.html16
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/013.html16
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/014.html19
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/015.html31
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/016.html35
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/017.html51
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/018.html35
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/019.html29
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/020.html15
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/extensions/001.html12
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/protocol/protocol-initial.html12
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/readyState/001.html11
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/readyState/002.html13
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/readyState/003.html15
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/readyState/004.html15
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/readyState/005.html17
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/readyState/006.html17
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/readyState/007.html17
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/readyState/008.html19
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/send/001.html13
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/send/002.html13
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/send/003.html13
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/send/004.html23
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/send/005.html16
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/send/006.html23
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/send/007.html24
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/send/008.html23
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/send/009.html24
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/send/010.html39
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/send/011.html25
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/send/012.html25
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/url/001.html11
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/url/002.html13
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/url/003.html13
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/url/004.html15
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/url/005.html15
-rw-r--r--tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/url/006.html17
-rw-r--r--tests/wpt/web-platform-tests/websockets/keeping-connection-open/001.html26
-rw-r--r--tests/wpt/web-platform-tests/websockets/opening-handshake/001.html17
-rw-r--r--tests/wpt/web-platform-tests/websockets/opening-handshake/002.html21
-rw-r--r--tests/wpt/web-platform-tests/websockets/opening-handshake/003.html21
-rw-r--r--tests/wpt/web-platform-tests/websockets/opening-handshake/005.html20
-rw-r--r--tests/wpt/web-platform-tests/websockets/security/001.html14
-rw-r--r--tests/wpt/web-platform-tests/websockets/security/002.html18
-rw-r--r--tests/wpt/web-platform-tests/websockets/security/check.py2
-rw-r--r--tests/wpt/web-platform-tests/websockets/unload-a-document/001-1.html26
-rw-r--r--tests/wpt/web-platform-tests/websockets/unload-a-document/001.html23
-rw-r--r--tests/wpt/web-platform-tests/websockets/unload-a-document/002-1.html32
-rw-r--r--tests/wpt/web-platform-tests/websockets/unload-a-document/002.html24
-rw-r--r--tests/wpt/web-platform-tests/websockets/unload-a-document/003.html14
-rw-r--r--tests/wpt/web-platform-tests/websockets/unload-a-document/004.html16
-rw-r--r--tests/wpt/web-platform-tests/websockets/unload-a-document/005-1.html23
-rw-r--r--tests/wpt/web-platform-tests/websockets/unload-a-document/005.html18
-rw-r--r--tests/wpt/web-platform-tests/websockets/websocket.js110
-rw-r--r--tests/wpt/web-platform-tests/webstorage/README.md10
-rw-r--r--tests/wpt/web-platform-tests/webstorage/builtins.html24
-rw-r--r--tests/wpt/web-platform-tests/webstorage/clear.html24
-rw-r--r--tests/wpt/web-platform-tests/webstorage/event_constructor.html32
-rw-r--r--tests/wpt/web-platform-tests/webstorage/event_constructor_js.html37
-rw-r--r--tests/wpt/web-platform-tests/webstorage/event_local_key.html42
-rw-r--r--tests/wpt/web-platform-tests/webstorage/event_local_newvalue.html42
-rw-r--r--tests/wpt/web-platform-tests/webstorage/event_local_oldvalue.html42
-rw-r--r--tests/wpt/web-platform-tests/webstorage/event_local_storagearea.html43
-rw-r--r--tests/wpt/web-platform-tests/webstorage/event_local_storageeventinit.html39
-rw-r--r--tests/wpt/web-platform-tests/webstorage/event_local_url.html47
-rw-r--r--tests/wpt/web-platform-tests/webstorage/event_session_key.html42
-rw-r--r--tests/wpt/web-platform-tests/webstorage/event_session_newvalue.html42
-rw-r--r--tests/wpt/web-platform-tests/webstorage/event_session_oldvalue.html42
-rw-r--r--tests/wpt/web-platform-tests/webstorage/event_session_storagearea.html43
-rw-r--r--tests/wpt/web-platform-tests/webstorage/event_session_storageeventinit.html39
-rw-r--r--tests/wpt/web-platform-tests/webstorage/event_session_url.html47
-rw-r--r--tests/wpt/web-platform-tests/webstorage/getitem.html42
-rw-r--r--tests/wpt/web-platform-tests/webstorage/idlharness.html81
-rw-r--r--tests/wpt/web-platform-tests/webstorage/iframe/local_change_item_iframe.html18
-rw-r--r--tests/wpt/web-platform-tests/webstorage/iframe/local_set_item_clear_iframe.html17
-rw-r--r--tests/wpt/web-platform-tests/webstorage/iframe/local_set_item_iframe.html16
-rw-r--r--tests/wpt/web-platform-tests/webstorage/iframe/session_change_item_iframe.html18
-rw-r--r--tests/wpt/web-platform-tests/webstorage/iframe/session_set_item_clear_iframe.html17
-rw-r--r--tests/wpt/web-platform-tests/webstorage/iframe/session_set_item_iframe.html16
-rw-r--r--tests/wpt/web-platform-tests/webstorage/in.html30
-rw-r--r--tests/wpt/web-platform-tests/webstorage/indexing.html36
-rw-r--r--tests/wpt/web-platform-tests/webstorage/key.html59
-rw-r--r--tests/wpt/web-platform-tests/webstorage/length.html31
-rw-r--r--tests/wpt/web-platform-tests/webstorage/missing_arguments.html32
-rw-r--r--tests/wpt/web-platform-tests/webstorage/removeitem.html52
-rw-r--r--tests/wpt/web-platform-tests/webstorage/setitem.html160
-rw-r--r--tests/wpt/web-platform-tests/webstorage/storage_local_setitem_quotaexceedederr.html31
-rw-r--r--tests/wpt/web-platform-tests/webstorage/storage_session_setitem_quotaexceedederr.html31
-rw-r--r--tests/wpt/web-platform-tests/webvtt/interfaces.html64
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/2_cues_overlapping_completely_move_up-ref.html35
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/2_cues_overlapping_completely_move_up.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/2_cues_overlapping_partially_move_down-ref.html35
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/2_cues_overlapping_partially_move_down.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/2_cues_overlapping_partially_move_up-ref.html35
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/2_cues_overlapping_partially_move_up.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/2_tracks-ref.html26
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/2_tracks.html20
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/3_tracks-ref.html26
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/3_tracks.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_end-ref.html27
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_end.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_end_wrapped-ref.html27
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_end_wrapped.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_middle-ref.html26
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_middle.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_middle_position_50-ref.html26
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_middle_position_50.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_middle_position_gt_50-ref.html26
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_middle_position_gt_50.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_middle_position_lt_50-ref.html27
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_middle_position_lt_50.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_middle_position_lt_50_size_gt_maximum_size-ref.html27
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_middle_position_lt_50_size_gt_maximum_size.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_middle_wrapped-ref.html26
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_middle_wrapped.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_start-ref.html25
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_start.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_start_wrapped-ref.html25
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_start_wrapped.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/audio_has_no_subtitles-ref.html15
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/audio_has_no_subtitles.html25
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/basic-ref.html26
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/basic.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/bidi_ruby-ref.html26
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/bidi_ruby.html18
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/u002E_LF_u05D0-ref.html26
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/u002E_LF_u05D0.html18
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/u002E_u2028_u05D0-ref.html26
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/u002E_u2028_u05D0.html18
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/u002E_u2029_u05D0-ref.html26
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/u002E_u2029_u05D0.html18
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/u0041_first-ref.html26
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/u0041_first.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/u05D0_first-ref.html26
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/u05D0_first.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/u0628_first-ref.html26
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/u0628_first.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/u06E9_no_strong_dir-ref.html26
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/u06E9_no_strong_dir.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/cue_too_long-ref.html27
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/cue_too_long.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/decode_escaped_entities-ref.html26
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/decode_escaped_entities.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/disable_controls_reposition-ref.html25
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/disable_controls_reposition.html28
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/dom_override_cue_align_position_line_size-ref.html26
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/dom_override_cue_align_position_line_size.html43
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/dom_override_cue_align_position_line_size_while_paused-ref.html26
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/dom_override_cue_align_position_line_size_while_paused.html34
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/dom_override_cue_line-ref.html26
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/dom_override_cue_line.html39
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/dom_override_cue_text-ref.html26
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/dom_override_cue_text.html39
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/dom_override_cue_text_while_paused-ref.html26
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/dom_override_cue_text_while_paused.html30
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/dom_override_remove_cue_while_paused-ref.html13
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/dom_override_remove_cue_while_paused.html30
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/enable_controls_reposition-ref.html34
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/enable_controls_reposition.html28
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/9_cues_overlapping_completely-ref.html112
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/9_cues_overlapping_completely.html48
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/9_cues_overlapping_completely_all_cues_have_same_timestamp-ref.html112
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/9_cues_overlapping_completely_all_cues_have_same_timestamp.html48
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/media_404_omit_subtitles-ref.html13
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/media_404_omit_subtitles.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/media_height_19-ref.html25
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/media_height_19.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/single_quote-ref.html26
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/single_quote.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/size_90-ref.html26
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/size_90.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/size_99-ref.html26
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/size_99.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/support/9_cues_overlapping_completely.vtt37
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/support/9_cues_overlapping_completely_all_cues_have_same_timestamp.vtt37
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/support/single_quote.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/support/size_90.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/support/size_99.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/support/test.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_-2_wrapped_cue_grow_upwards-ref.html27
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_-2_wrapped_cue_grow_upwards.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_0_is_top-ref.html26
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_0_is_top.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_1_wrapped_cue_grow_downwards-ref.html27
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_1_wrapped_cue_grow_downwards.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_50_percent-ref.html27
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_50_percent.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_integer_and_percent_mixed_overlap-ref.html33
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_integer_and_percent_mixed_overlap.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_integer_and_percent_mixed_overlap_move_up-ref.html33
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_integer_and_percent_mixed_overlap_move_up.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_percent_and_integer_mixed_overlap-ref.html33
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_percent_and_integer_mixed_overlap.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_percent_and_integer_mixed_overlap_move_up-ref.html33
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_percent_and_integer_mixed_overlap_move_up.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/media/background.gifbin0 -> 3266 bytes
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/media_height400_with_controls-ref.html33
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/media_height400_with_controls.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/media_with_controls-ref.html33
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/media_with_controls.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/navigate_cue_position-1.html23
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/navigate_cue_position-ref-1.html34
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/navigate_cue_position-ref.html4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/navigate_cue_position.html27
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/one_line_cue_plus_wrapped_cue-ref.html27
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/one_line_cue_plus_wrapped_cue.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/repaint-ref.html25
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/repaint.html51
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/background_properties-ref.html26
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/background_properties.html26
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/background_shorthand-ref.html26
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/background_shorthand.html23
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/background_shorthand_css_relative_url-ref.html26
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/background_shorthand_css_relative_url.html23
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/color_hex-ref.html26
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/color_hex.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/color_hsla-ref.html26
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/color_hsla.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/color_rgba-ref.html26
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/color_rgba.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/cue_selector_single_colon-ref.html27
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/cue_selector_single_colon.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/font_properties-ref.html25
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/font_properties.html26
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/font_shorthand-ref.html25
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/font_shorthand.html21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/inherit_values_from_media_element-ref.html46
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/inherit_values_from_media_element.html34
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/outline_properties-ref.html27
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/outline_properties.html25
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/outline_shorthand-ref.html27
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/outline_shorthand.html23
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-decoration_line-through-ref.html27
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-decoration_line-through.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-decoration_overline-ref.html27
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-decoration_overline.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-decoration_overline_underline_line-through-ref.html27
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-decoration_overline_underline_line-through.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-decoration_underline-ref.html27
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-decoration_underline.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-shadow-ref.html27
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-shadow.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_normal_wrapped-ref.html28
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_normal_wrapped.html21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_nowrap_wrapped-ref.html28
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_nowrap_wrapped.html21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_pre-line_wrapped-ref.html28
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_pre-line_wrapped.html21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_pre-ref.html27
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_pre-wrap_wrapped-ref.html28
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_pre-wrap_wrapped.html21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_pre.html21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_pre_wrapped-ref.html28
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_pre_wrapped.html21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/background_box-ref.html27
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/background_box.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/background_properties-ref.html26
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/background_properties.html26
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/background_shorthand-ref.html26
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/background_shorthand.html23
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/background_shorthand_css_relative_url-ref.html26
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/background_shorthand_css_relative_url.html23
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_animation_with_timestamp-ref.html30
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_animation_with_timestamp.html38
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_background_properties-ref.html30
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_background_properties.html26
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_background_shorthand-ref.html30
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_background_shorthand.html23
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_color-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_color.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_font_properties-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_font_properties.html26
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_font_shorthand-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_font_shorthand.html21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_namespace-ref.html30
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_namespace.html27
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_outline_properties-ref.html33
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_outline_properties.html24
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_outline_shorthand-ref.html33
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_outline_shorthand.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_text-decoration_line-through-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_text-decoration_line-through.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_text-shadow-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_text-shadow.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_timestamp_future-ref.html30
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_timestamp_future.html21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_timestamp_past-ref.html30
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_timestamp_past.html21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_transition_with_timestamp-ref.html30
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_transition_with_timestamp.html25
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_normal_wrapped-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_normal_wrapped.html21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_nowrap-ref.html30
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_nowrap.html21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_pre-line_wrapped-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_pre-line_wrapped.html21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_pre-wrap_wrapped-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_pre-wrap_wrapped.html21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_pre_wrapped-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_pre_wrapped.html21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_with_class-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_with_class.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_with_class_object_specific_selector-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_with_class_object_specific_selector.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_animation_with_timestamp-ref.html30
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_animation_with_timestamp.html38
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_background_properties-ref.html30
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_background_properties.html26
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_background_shorthand-ref.html30
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_background_shorthand.html23
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_color-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_color.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_font_properties-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_font_properties.html26
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_font_shorthand-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_font_shorthand.html21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_namespace-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_namespace.html28
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_outline_properties-ref.html33
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_outline_properties.html24
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_outline_shorthand-ref.html33
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_outline_shorthand.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_text-decoration_line-through-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_text-decoration_line-through.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_text-shadow-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_text-shadow.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_timestamp_future-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_timestamp_future.html21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_timestamp_past-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_timestamp_past.html21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_transition_with_timestamp-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_transition_with_timestamp.html25
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_normal_wrapped-ref.html28
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_normal_wrapped.html21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_nowrap-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_nowrap.html21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_pre-line_wrapped-ref.html28
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_pre-line_wrapped.html21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_pre-wrap_wrapped-ref.html28
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_pre-wrap_wrapped.html21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_pre_wrapped-ref.html28
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_pre_wrapped.html21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_with_class-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_with_class.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_with_class_object_specific_selector-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_with_class_object_specific_selector.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/color_hex-ref.html26
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/color_hex.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/color_hsla-ref.html26
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/color_hsla.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/color_rgba-ref.html26
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/color_rgba.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/cue_func_selector_single_colon-ref.html27
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/cue_func_selector_single_colon.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/font_properties-ref.html25
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/font_properties.html26
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/font_shorthand-ref.html25
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/font_shorthand.html21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/id_color-ref.html26
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/id_color.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/inherit_values_from_media_element-ref.html46
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/inherit_values_from_media_element.html34
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_animation_with_timestamp-ref.html30
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_animation_with_timestamp.html38
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_background_properties-ref.html30
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_background_properties.html26
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_background_shorthand-ref.html30
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_background_shorthand.html23
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_color-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_color.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_font_properties-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_font_properties.html26
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_font_shorthand-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_font_shorthand.html21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_namespace-ref.html30
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_namespace.html27
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_outline_properties-ref.html33
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_outline_properties.html24
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_outline_shorthand-ref.html33
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_outline_shorthand.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_text-decoration_line-through-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_text-decoration_line-through.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_text-shadow-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_text-shadow.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_timestamp_future-ref.html30
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_timestamp_future.html21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_timestamp_past-ref.html30
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_timestamp_past.html21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_transition_with_timestamp-ref.html30
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_transition_with_timestamp.html25
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_normal_wrapped-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_normal_wrapped.html21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_nowrap-ref.html30
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_nowrap.html21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_pre-line_wrapped-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_pre-line_wrapped.html21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_pre-wrap_wrapped-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_pre-wrap_wrapped.html21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_pre_wrapped-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_pre_wrapped.html21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_with_class-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_with_class.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_with_class_object_specific_selector-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_with_class_object_specific_selector.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/not_allowed_properties-ref.html26
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/not_allowed_properties.html47
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/not_root_selector-ref.html30
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/not_root_selector.html21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/outline_properties-ref.html27
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/outline_properties.html25
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/outline_shorthand-ref.html27
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/outline_shorthand.html23
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/root_namespace-ref.html26
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/root_namespace.html27
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/root_selector-ref.html27
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/root_selector.html21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-decoration_line-through-ref.html27
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-decoration_line-through.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-decoration_overline-ref.html27
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-decoration_overline.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-decoration_overline_underline_line-through-ref.html27
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-decoration_overline_underline_line-through.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-decoration_underline-ref.html27
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-decoration_underline.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-shadow-ref.html27
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-shadow.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/type_selector_root-ref.html27
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/type_selector_root.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_animation_with_timestamp-ref.html30
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_animation_with_timestamp.html38
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_background_properties-ref.html30
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_background_properties.html26
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_background_shorthand-ref.html30
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_background_shorthand.html23
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_color-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_color.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_font_properties-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_font_properties.html26
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_font_shorthand-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_font_shorthand.html21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_namespace-ref.html30
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_namespace.html27
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_outline_properties-ref.html33
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_outline_properties.html24
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_outline_shorthand-ref.html33
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_outline_shorthand.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_text-decoration_line-through-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_text-decoration_line-through.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_text-shadow-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_text-shadow.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_timestamp_future-ref.html31
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_timestamp_future.html21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_timestamp_past-ref.html30
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_timestamp_past.html21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_transition_with_timestamp-ref.html30
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_transition_with_timestamp.html25
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_normal_wrapped-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_normal_wrapped.html21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_nowrap-ref.html30
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_nowrap.html21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_pre-line_wrapped-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_pre-line_wrapped.html21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_pre-wrap_wrapped-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_pre-wrap_wrapped.html21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_pre_wrapped-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_pre_wrapped.html21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_with_class-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_with_class.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_with_class_object_specific_selector-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_with_class_object_specific_selector.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_animation_with_timestamp-ref.html30
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_animation_with_timestamp.html38
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_background_properties-ref.html30
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_background_properties.html26
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_background_shorthand-ref.html30
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_background_shorthand.html23
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_color-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_color.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_font_properties-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_font_properties.html26
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_font_shorthand-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_font_shorthand.html21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_namespace-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_namespace.html28
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_outline_properties-ref.html33
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_outline_properties.html24
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_outline_shorthand-ref.html33
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_outline_shorthand.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_text-decoration_line-through-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_text-decoration_line-through.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_text-shadow-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_text-shadow.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_timestamp_future-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_timestamp_future.html21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_timestamp_past-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_timestamp_past.html21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_transition_with_timestamp-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_transition_with_timestamp.html25
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_voice_attribute-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_voice_attribute.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_normal_wrapped-ref.html28
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_normal_wrapped.html21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_nowrap-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_nowrap.html21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_pre-line_wrapped-ref.html28
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_pre-line_wrapped.html21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_pre-wrap_wrapped-ref.html28
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_pre-wrap_wrapped.html21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_pre_wrapped-ref.html28
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_pre_wrapped.html21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_with_class-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_with_class.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_with_class_object_specific_selector-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_with_class_object_specific_selector.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_normal_wrapped-ref.html28
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_normal_wrapped.html21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_nowrap_wrapped-ref.html28
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_nowrap_wrapped.html21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_pre-line_wrapped-ref.html28
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_pre-line_wrapped.html21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_pre-ref.html27
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_pre-wrap_wrapped-ref.html28
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_pre-wrap_wrapped.html21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_pre.html21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_pre_wrapped-ref.html28
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_pre_wrapped.html21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/default_styles/bold_object_default_font-style-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/default_styles/bold_object_default_font-style.html18
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/default_styles/inherit_as_default_value_inherits_values_from_media_element-ref.html40
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/default_styles/inherit_as_default_value_inherits_values_from_media_element.html25
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/default_styles/italic_object_default_font-style-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/default_styles/italic_object_default_font-style.html18
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/default_styles/underline_object_default_font-style-ref.html29
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/default_styles/underline_object_default_font-style.html18
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/size_50-ref.html27
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/size_50.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/2_cues_overlapping_completely_move_up.vtt7
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/2_cues_overlapping_partially_move_down.vtt7
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/2_cues_overlapping_partially_move_up.vtt7
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/align_end.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/align_end_long.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/align_middle.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/align_middle_long.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/align_middle_position_50.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/align_middle_position_gt_50.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/align_middle_position_lt_50.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/align_middle_position_lt_50_size_gt_maximum_size.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/align_start.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/align_start_long.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/bidi_ruby.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/bold_long.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/bold_with_2_timestamps.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/bold_with_timestamp.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/class_long.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/class_with_2_timestamps.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/class_with_timestamp.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/cue_with_id.vtt5
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/decode_escaped_entities.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/foo.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/foo_c_bar.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/foo_space_space_bar_LF_baz.vtt5
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/italic_long.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/italic_with_2_timestamps.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/italic_with_timestamp.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/line_-2_long.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/line_0.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/line_1_long.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/line_50_percent.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/line_integer_and_percent_overlap.vtt7
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/line_integer_and_percent_overlap_move_up.vtt7
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/line_percent_and_integer_overlap.vtt7
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/line_percent_and_integer_overlap_move_up.vtt7
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/one_line_cue_plus_wrapped_cue.vtt7
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/size_50.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/test.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/test_bold.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/test_bold_with_class.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/test_class.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/test_class_with_class.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/test_italic.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/test_italic_with_class.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/test_long.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/test_two_voices.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/test_underline.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/test_underline_with_class.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/test_voice.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/test_voice_with_class.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/too_many_cues.vtt64
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/too_many_cues_wrapped.vtt61
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/u002E_LF_u05D0.vtt5
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/u002E_u2028_u05D0.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/u002E_u2029_u05D0.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/u0041_first.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/u05D0_first.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/u0628_first.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/u06E9_no_strong_dir.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/underline_long.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/underline_with_2_timestamps.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/underline_with_timestamp.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/very_long_cue.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/voice_long.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/voice_with_2_timestamps.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/voice_with_timestamp.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/white-spaces.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/white-spaces_long.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/white-spaces_long_size_20.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/too_many_cues-ref.html27
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/too_many_cues.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/too_many_cues_wrapped-ref.html27
-rw-r--r--tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/too_many_cues_wrapped.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/webvtt-api-for-browsers/vttcue-interface/align.html54
-rw-r--r--tests/wpt/web-platform-tests/webvtt/webvtt-api-for-browsers/vttcue-interface/getCueAsHTML.html92
-rw-r--r--tests/wpt/web-platform-tests/webvtt/webvtt-api-for-browsers/vttcue-interface/line.html62
-rw-r--r--tests/wpt/web-platform-tests/webvtt/webvtt-api-for-browsers/vttcue-interface/snapToLines.html97
-rw-r--r--tests/wpt/web-platform-tests/webvtt/webvtt-api-for-browsers/vttcue-interface/text.html38
-rw-r--r--tests/wpt/web-platform-tests/webvtt/webvtt-api-for-browsers/vttcue-interface/vertical.html54
-rw-r--r--tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-cue-text-parsing-rules/buildtests.py67
-rw-r--r--tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-cue-text-parsing-rules/common.js189
-rw-r--r--tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-cue-text-parsing-rules/dat/entities.dat114
-rw-r--r--tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-cue-text-parsing-rules/dat/tags.dat56
-rw-r--r--tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-cue-text-parsing-rules/dat/timestamps.dat58
-rw-r--r--tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-cue-text-parsing-rules/dat/tree-building.dat171
-rw-r--r--tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-cue-text-parsing-rules/tests/entities.html32
-rw-r--r--tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-cue-text-parsing-rules/tests/tags.html23
-rw-r--r--tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-cue-text-parsing-rules/tests/timestamps.html22
-rw-r--r--tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-cue-text-parsing-rules/tests/tree-building.html33
-rw-r--r--tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/001.html96
-rw-r--r--tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/arrows.vtt19
-rw-r--r--tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/cue-counts.json36
-rw-r--r--tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/header-garbage.vtt5
-rw-r--r--tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/header-space.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/header-tab.vtt4
-rw-r--r--tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/header-timings.vtt3
-rw-r--r--tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/ids.vtt21
-rw-r--r--tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/newlines.vtt12
-rw-r--r--tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/no-signature.vtt2
-rw-r--r--tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/nulls.vttbin0 -> 2773 bytes
-rw-r--r--tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/omitted-hours.vtt10
-rw-r--r--tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/settings-align.vtt28
-rw-r--r--tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/settings-line.vtt88
-rw-r--r--tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/settings-multiple.vtt16
-rw-r--r--tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/settings-position.vtt40
-rw-r--r--tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/settings-size.vtt37
-rw-r--r--tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/settings-vertical.vtt19
-rw-r--r--tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/signature-bom.vtt1
-rw-r--r--tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/signature-formfeed.vtt1
-rw-r--r--tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/signature-lowercase.vtt1
-rw-r--r--tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/signature-no-newline.vtt1
-rw-r--r--tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/signature-null.vttbin0 -> 8 bytes
-rw-r--r--tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/signature-space-no-newline.vtt1
-rw-r--r--tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/signature-space.vtt1
-rw-r--r--tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/signature-tab-no-newline.vtt1
-rw-r--r--tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/signature-tab.vtt1
-rw-r--r--tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/signature-timings.vtt2
-rw-r--r--tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/signature-too-short.vtt1
-rw-r--r--tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/signature-two-boms.vtt1
-rw-r--r--tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/signature-websrt.vtt1
-rw-r--r--tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/space-chars.vtt17
-rw-r--r--tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/timings-60.vtt20
-rw-r--r--tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/timings-garbage.vtt190
-rw-r--r--tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/timings-negative.vtt13
-rw-r--r--tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/timings-too-long.vtt47
-rw-r--r--tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/timings-too-short.vtt98
-rw-r--r--tests/wpt/web-platform-tests/workers/MessagePort_initial_disabled.htm13
-rw-r--r--tests/wpt/web-platform-tests/workers/MessagePort_onmessage_start.htm13
-rw-r--r--tests/wpt/web-platform-tests/workers/README.md8
-rw-r--r--tests/wpt/web-platform-tests/workers/WorkerGlobalScope_ErrorEvent_colno.htm14
-rw-r--r--tests/wpt/web-platform-tests/workers/WorkerGlobalScope_ErrorEvent_filename.htm16
-rw-r--r--tests/wpt/web-platform-tests/workers/WorkerGlobalScope_ErrorEvent_lineno.htm14
-rw-r--r--tests/wpt/web-platform-tests/workers/WorkerGlobalScope_ErrorEvent_message.htm15
-rw-r--r--tests/wpt/web-platform-tests/workers/WorkerGlobalScope_close.htm17
-rw-r--r--tests/wpt/web-platform-tests/workers/WorkerGlobalScope_importScripts.htm14
-rw-r--r--tests/wpt/web-platform-tests/workers/WorkerGlobalScope_importScripts_NetworkErr.htm13
-rw-r--r--tests/wpt/web-platform-tests/workers/WorkerGlobalScope_setInterval.htm20
-rw-r--r--tests/wpt/web-platform-tests/workers/WorkerGlobalScope_setTimeout.htm20
-rw-r--r--tests/wpt/web-platform-tests/workers/WorkerLocation.htm15
-rw-r--r--tests/wpt/web-platform-tests/workers/WorkerLocation_hash.htm13
-rw-r--r--tests/wpt/web-platform-tests/workers/WorkerLocation_hash_encoding.htm13
-rw-r--r--tests/wpt/web-platform-tests/workers/WorkerLocation_hash_nonexist.htm13
-rw-r--r--tests/wpt/web-platform-tests/workers/WorkerLocation_host.htm13
-rw-r--r--tests/wpt/web-platform-tests/workers/WorkerLocation_hostname.htm13
-rw-r--r--tests/wpt/web-platform-tests/workers/WorkerLocation_href.htm15
-rw-r--r--tests/wpt/web-platform-tests/workers/WorkerLocation_pathname.htm15
-rw-r--r--tests/wpt/web-platform-tests/workers/WorkerLocation_port.htm13
-rw-r--r--tests/wpt/web-platform-tests/workers/WorkerLocation_protocol.htm13
-rw-r--r--tests/wpt/web-platform-tests/workers/WorkerLocation_search.htm13
-rw-r--r--tests/wpt/web-platform-tests/workers/WorkerLocation_search_empty.htm13
-rw-r--r--tests/wpt/web-platform-tests/workers/WorkerLocation_search_fragment.htm13
-rw-r--r--tests/wpt/web-platform-tests/workers/WorkerLocation_search_nonexist.htm13
-rw-r--r--tests/wpt/web-platform-tests/workers/WorkerNavigator_appName.htm13
-rw-r--r--tests/wpt/web-platform-tests/workers/WorkerNavigator_appVersion.htm13
-rw-r--r--tests/wpt/web-platform-tests/workers/WorkerNavigator_onLine.htm13
-rw-r--r--tests/wpt/web-platform-tests/workers/WorkerNavigator_platform.htm13
-rw-r--r--tests/wpt/web-platform-tests/workers/WorkerNavigator_userAgent.htm13
-rw-r--r--tests/wpt/web-platform-tests/workers/Worker_ErrorEvent_filename.htm16
-rw-r--r--tests/wpt/web-platform-tests/workers/Worker_ErrorEvent_lineno.htm14
-rw-r--r--tests/wpt/web-platform-tests/workers/Worker_ErrorEvent_message.htm15
-rw-r--r--tests/wpt/web-platform-tests/workers/Worker_ErrorEvent_type.htm15
-rw-r--r--tests/wpt/web-platform-tests/workers/Worker_basic.htm31
-rw-r--r--tests/wpt/web-platform-tests/workers/Worker_cross_origin_security_err.htm12
-rw-r--r--tests/wpt/web-platform-tests/workers/Worker_dispatchEvent_ErrorEvent.htm37
-rw-r--r--tests/wpt/web-platform-tests/workers/Worker_script_mimetype.htm14
-rw-r--r--tests/wpt/web-platform-tests/workers/Worker_terminate_event_queue.htm22
-rw-r--r--tests/wpt/web-platform-tests/workers/constructors/SharedWorker/13
-rw-r--r--tests/wpt/web-platform-tests/workers/constructors/SharedWorker/connect-event.html26
-rw-r--r--tests/wpt/web-platform-tests/workers/constructors/SharedWorker/dummy-name.html17
-rw-r--r--tests/wpt/web-platform-tests/workers/constructors/SharedWorker/dummy-shared-worker.html17
-rw-r--r--tests/wpt/web-platform-tests/workers/constructors/SharedWorker/empty-name.html17
-rw-r--r--tests/wpt/web-platform-tests/workers/constructors/SharedWorker/global-members.html34
-rw-r--r--tests/wpt/web-platform-tests/workers/constructors/SharedWorker/interface-objects.html41
-rw-r--r--tests/wpt/web-platform-tests/workers/constructors/SharedWorker/name.html24
-rw-r--r--tests/wpt/web-platform-tests/workers/constructors/SharedWorker/no-arguments-ctor.html20
-rw-r--r--tests/wpt/web-platform-tests/workers/constructors/SharedWorker/null3
-rw-r--r--tests/wpt/web-platform-tests/workers/constructors/SharedWorker/null-arguments.html25
-rw-r--r--tests/wpt/web-platform-tests/workers/constructors/SharedWorker/number-arguments.html25
-rw-r--r--tests/wpt/web-platform-tests/workers/constructors/SharedWorker/port-onmessage.html23
-rw-r--r--tests/wpt/web-platform-tests/workers/constructors/SharedWorker/port-properties.html26
-rw-r--r--tests/wpt/web-platform-tests/workers/constructors/SharedWorker/port-readonly.html21
-rw-r--r--tests/wpt/web-platform-tests/workers/constructors/SharedWorker/same-origin.html48
-rw-r--r--tests/wpt/web-platform-tests/workers/constructors/SharedWorker/setting-port-members.html59
-rw-r--r--tests/wpt/web-platform-tests/workers/constructors/SharedWorker/undefined3
-rw-r--r--tests/wpt/web-platform-tests/workers/constructors/SharedWorker/undefined-arguments.html25
-rw-r--r--tests/wpt/web-platform-tests/workers/constructors/SharedWorker/unexpected-global-properties.html30
-rw-r--r--tests/wpt/web-platform-tests/workers/constructors/SharedWorker/unresolvable-url.html19
-rw-r--r--tests/wpt/web-platform-tests/workers/constructors/Worker/11
-rw-r--r--tests/wpt/web-platform-tests/workers/constructors/Worker/AbstractWorker.onerror.html41
-rw-r--r--tests/wpt/web-platform-tests/workers/constructors/Worker/DedicatedWorkerGlobalScope-members.html34
-rw-r--r--tests/wpt/web-platform-tests/workers/constructors/Worker/ctor-1.html23
-rw-r--r--tests/wpt/web-platform-tests/workers/constructors/Worker/ctor-null.html23
-rw-r--r--tests/wpt/web-platform-tests/workers/constructors/Worker/ctor-undefined.html23
-rw-r--r--tests/wpt/web-platform-tests/workers/constructors/Worker/expected-self-properties.html30
-rw-r--r--tests/wpt/web-platform-tests/workers/constructors/Worker/no-arguments-ctor.html13
-rw-r--r--tests/wpt/web-platform-tests/workers/constructors/Worker/null1
-rw-r--r--tests/wpt/web-platform-tests/workers/constructors/Worker/resolve-empty-string.html22
-rw-r--r--tests/wpt/web-platform-tests/workers/constructors/Worker/same-origin.html51
-rw-r--r--tests/wpt/web-platform-tests/workers/constructors/Worker/terminate.html45
-rw-r--r--tests/wpt/web-platform-tests/workers/constructors/Worker/undefined1
-rw-r--r--tests/wpt/web-platform-tests/workers/constructors/Worker/unexpected-self-properties.html26
-rw-r--r--tests/wpt/web-platform-tests/workers/constructors/Worker/unresolvable-url.html12
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces.idl116
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces.worker.js20
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/DedicatedWorkerGlobalScope/EventTarget.worker.js21
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/DedicatedWorkerGlobalScope/onmessage.worker.js40
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/event-ports-dedicated.html25
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/imagedata-cloned-canvas-in-array.html39
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/message-event.html23
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/message-event.js1
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/return-value.worker.js8
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/second-argument-null-in-array.html26
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/second-argument-null.html25
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/second-argument-undefined.html25
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/setting-postMessage.html24
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/structured-clone-imagedata.html30
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/structured-clone-message.html58
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/SharedWorkerGlobalScope/name/getting.html34
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/SharedWorkerGlobalScope/name/setting.html25
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/SharedWorkerGlobalScope/onconnect.html39
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/close/incoming-message.html37
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/close/sending-messages.html27
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/close/setInterval.html42
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/close/setTimeout.html40
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/location/helper-redirect.py3
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/location/members.html31
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/location/post-location-members.js8
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/location/redirect.html28
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/location/returns-same-object.html21
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/location/setting-members.html43
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/location/worker-separate-file.html28
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/onerror/exception-in-onerror.html32
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/onerror/handled.html36
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/onerror/not-handled.html32
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/onerror/propagate-to-window-onerror.html35
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/self.html39
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/WindowTimers/001.html23
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/WindowTimers/002.html21
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/WindowTimers/003.html22
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/WindowTimers/004.html23
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/001.html26
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/002.html32
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/003.html28
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/004.html34
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/005.html30
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/006.html33
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/007.html25
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/008.html23
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/009.html29
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/010.html34
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/011.html34
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/012.html34
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/11
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/null1
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/undefined1
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/navigator/002.html21
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/navigator/003.html21
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/navigator/004.html21
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/navigator/005.html21
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/navigator/006.html21
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/navigator/007.html28
-rw-r--r--tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/navigator/language.html21
-rw-r--r--tests/wpt/web-platform-tests/workers/nested_worker.worker.js11
-rw-r--r--tests/wpt/web-platform-tests/workers/non-automated/application-cache-dedicated.html21
-rw-r--r--tests/wpt/web-platform-tests/workers/non-automated/application-cache-dedicated.js1
-rw-r--r--tests/wpt/web-platform-tests/workers/non-automated/cache.manifest3
-rw-r--r--tests/wpt/web-platform-tests/workers/non-automated/infinite-nested.html12
-rw-r--r--tests/wpt/web-platform-tests/workers/non-automated/infinite-nested.js5
-rw-r--r--tests/wpt/web-platform-tests/workers/non-automated/infinite-sibling-and-nested.html12
-rw-r--r--tests/wpt/web-platform-tests/workers/non-automated/infinite-sibling-and-nested.js8
-rw-r--r--tests/wpt/web-platform-tests/workers/non-automated/infinite-sibling.html12
-rw-r--r--tests/wpt/web-platform-tests/workers/non-automated/infinite-sibling.js8
-rw-r--r--tests/wpt/web-platform-tests/workers/non-automated/navigator-onLine.html46
-rw-r--r--tests/wpt/web-platform-tests/workers/non-automated/post-a-1.js1
-rw-r--r--tests/wpt/web-platform-tests/workers/postMessage_DataCloneErr.htm13
-rw-r--r--tests/wpt/web-platform-tests/workers/postMessage_clone_port.htm22
-rw-r--r--tests/wpt/web-platform-tests/workers/postMessage_clone_port_error.htm14
-rw-r--r--tests/wpt/web-platform-tests/workers/postMessage_event_properties.htm24
-rw-r--r--tests/wpt/web-platform-tests/workers/postMessage_ports_readonly_array.htm20
-rw-r--r--tests/wpt/web-platform-tests/workers/postMessage_target_source.htm18
-rw-r--r--tests/wpt/web-platform-tests/workers/semantics/encodings/001.html21
-rw-r--r--tests/wpt/web-platform-tests/workers/semantics/encodings/001.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/workers/semantics/encodings/002.html23
-rw-r--r--tests/wpt/web-platform-tests/workers/semantics/encodings/002.html.headers1
-rw-r--r--tests/wpt/web-platform-tests/workers/semantics/encodings/003-1.py4
-rw-r--r--tests/wpt/web-platform-tests/workers/semantics/encodings/003.html26
-rw-r--r--tests/wpt/web-platform-tests/workers/semantics/encodings/004.html27
-rw-r--r--tests/wpt/web-platform-tests/workers/semantics/interface-objects/001.worker.js48
-rw-r--r--tests/wpt/web-platform-tests/workers/semantics/interface-objects/002.worker.js18
-rw-r--r--tests/wpt/web-platform-tests/workers/semantics/interface-objects/003.html30
-rw-r--r--tests/wpt/web-platform-tests/workers/semantics/interface-objects/004.html30
-rw-r--r--tests/wpt/web-platform-tests/workers/semantics/multiple-workers/001.html41
-rw-r--r--tests/wpt/web-platform-tests/workers/semantics/multiple-workers/002.html28
-rw-r--r--tests/wpt/web-platform-tests/workers/semantics/multiple-workers/003.html34
-rw-r--r--tests/wpt/web-platform-tests/workers/semantics/multiple-workers/004-1.html7
-rw-r--r--tests/wpt/web-platform-tests/workers/semantics/multiple-workers/004-2.js6
-rw-r--r--tests/wpt/web-platform-tests/workers/semantics/multiple-workers/004.html34
-rw-r--r--tests/wpt/web-platform-tests/workers/semantics/multiple-workers/005.html37
-rw-r--r--tests/wpt/web-platform-tests/workers/semantics/multiple-workers/006-1.js3
-rw-r--r--tests/wpt/web-platform-tests/workers/semantics/multiple-workers/006.html35
-rw-r--r--tests/wpt/web-platform-tests/workers/semantics/multiple-workers/007.html39
-rw-r--r--tests/wpt/web-platform-tests/workers/semantics/multiple-workers/008-1.html8
-rw-r--r--tests/wpt/web-platform-tests/workers/semantics/multiple-workers/008.html31
-rw-r--r--tests/wpt/web-platform-tests/workers/semantics/navigation/001-1.html23
-rw-r--r--tests/wpt/web-platform-tests/workers/semantics/navigation/001.html37
-rw-r--r--tests/wpt/web-platform-tests/workers/semantics/navigation/002.html36
-rw-r--r--tests/wpt/web-platform-tests/workers/semantics/reporting-errors/001.html53
-rw-r--r--tests/wpt/web-platform-tests/workers/semantics/reporting-errors/002.html59
-rw-r--r--tests/wpt/web-platform-tests/workers/semantics/reporting-errors/003.html39
-rw-r--r--tests/wpt/web-platform-tests/workers/semantics/reporting-errors/004-1.html18
-rw-r--r--tests/wpt/web-platform-tests/workers/semantics/reporting-errors/004.html39
-rw-r--r--tests/wpt/web-platform-tests/workers/semantics/run-a-worker/001.html22
-rw-r--r--tests/wpt/web-platform-tests/workers/semantics/run-a-worker/002.html24
-rw-r--r--tests/wpt/web-platform-tests/workers/semantics/run-a-worker/003.html27
-rw-r--r--tests/wpt/web-platform-tests/workers/semantics/structured-clone/common.js596
-rw-r--r--tests/wpt/web-platform-tests/workers/semantics/structured-clone/dedicated.html9
-rw-r--r--tests/wpt/web-platform-tests/workers/semantics/structured-clone/dedicated.js4
-rw-r--r--tests/wpt/web-platform-tests/workers/semantics/structured-clone/shared.html9
-rw-r--r--tests/wpt/web-platform-tests/workers/semantics/structured-clone/shared.js6
-rw-r--r--tests/wpt/web-platform-tests/workers/semantics/structured-clone/worker-common.js1018
-rw-r--r--tests/wpt/web-platform-tests/workers/semantics/xhr/001-1.xml1
-rw-r--r--tests/wpt/web-platform-tests/workers/semantics/xhr/001.html35
-rw-r--r--tests/wpt/web-platform-tests/workers/semantics/xhr/002.html32
-rw-r--r--tests/wpt/web-platform-tests/workers/semantics/xhr/003.html41
-rw-r--r--tests/wpt/web-platform-tests/workers/semantics/xhr/004.html36
-rw-r--r--tests/wpt/web-platform-tests/workers/semantics/xhr/005.html21
-rw-r--r--tests/wpt/web-platform-tests/workers/semantics/xhr/006.html21
-rw-r--r--tests/wpt/web-platform-tests/workers/semantics/xhr/support/001-1.xml1
-rw-r--r--tests/wpt/web-platform-tests/workers/semantics/xhr/support/005-1.js5
-rw-r--r--tests/wpt/web-platform-tests/workers/semantics/xhr/support/006-1.js7
-rw-r--r--tests/wpt/web-platform-tests/workers/support/ErrorEvent.js10
-rw-r--r--tests/wpt/web-platform-tests/workers/support/ImportScripts.js9
-rw-r--r--tests/wpt/web-platform-tests/workers/support/ImportScriptsNetworkErr.js15
-rw-r--r--tests/wpt/web-platform-tests/workers/support/Timer.js50
-rw-r--r--tests/wpt/web-platform-tests/workers/support/WorkerBasic.js7
-rw-r--r--tests/wpt/web-platform-tests/workers/support/WorkerClose.js5
-rw-r--r--tests/wpt/web-platform-tests/workers/support/WorkerDataCloneErr.js15
-rw-r--r--tests/wpt/web-platform-tests/workers/support/WorkerLocation.js12
-rw-r--r--tests/wpt/web-platform-tests/workers/support/WorkerNavigator.js8
-rw-r--r--tests/wpt/web-platform-tests/workers/support/WorkerTerminate.js10
-rw-r--r--tests/wpt/web-platform-tests/workers/support/WorkerText.txt2
-rw-r--r--tests/wpt/web-platform-tests/workers/workers.js8
12321 files changed, 544385 insertions, 5 deletions
diff --git a/tests/wpt/metadata/2dcontext/drawing-images-to-the-canvas/2d.drawImage.canvas.html.ini b/tests/wpt/metadata/2dcontext/drawing-images-to-the-canvas/2d.drawImage.canvas.html.ini
new file mode 100644
index 00000000000..50084ff0b01
--- /dev/null
+++ b/tests/wpt/metadata/2dcontext/drawing-images-to-the-canvas/2d.drawImage.canvas.html.ini
@@ -0,0 +1,5 @@
+[2d.drawImage.canvas.html]
+ type: testharness
+ [Canvas test: 2d.drawImage.canvas]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/2dcontext/drawing-images-to-the-canvas/2d.drawImage.self.1.html.ini b/tests/wpt/metadata/2dcontext/drawing-images-to-the-canvas/2d.drawImage.self.1.html.ini
new file mode 100644
index 00000000000..f1466e20fe5
--- /dev/null
+++ b/tests/wpt/metadata/2dcontext/drawing-images-to-the-canvas/2d.drawImage.self.1.html.ini
@@ -0,0 +1,5 @@
+[2d.drawImage.self.1.html]
+ type: testharness
+ [Canvas test: 2d.drawImage.self.1]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/2dcontext/drawing-images-to-the-canvas/2d.drawImage.self.2.html.ini b/tests/wpt/metadata/2dcontext/drawing-images-to-the-canvas/2d.drawImage.self.2.html.ini
new file mode 100644
index 00000000000..a7e3656486d
--- /dev/null
+++ b/tests/wpt/metadata/2dcontext/drawing-images-to-the-canvas/2d.drawImage.self.2.html.ini
@@ -0,0 +1,5 @@
+[2d.drawImage.self.2.html]
+ type: testharness
+ [Canvas test: 2d.drawImage.self.2]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/2dcontext/drawing-rectangles-to-the-canvas/2d.clearRect.nonfinite.html.ini b/tests/wpt/metadata/2dcontext/drawing-rectangles-to-the-canvas/2d.clearRect.nonfinite.html.ini
new file mode 100644
index 00000000000..915e0758635
--- /dev/null
+++ b/tests/wpt/metadata/2dcontext/drawing-rectangles-to-the-canvas/2d.clearRect.nonfinite.html.ini
@@ -0,0 +1,5 @@
+[2d.clearRect.nonfinite.html]
+ type: testharness
+ [clearRect() with Infinity/NaN is ignored]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/2dcontext/image-smoothing/imagesmoothing.html.ini b/tests/wpt/metadata/2dcontext/image-smoothing/imagesmoothing.html.ini
new file mode 100644
index 00000000000..0aa58081d2f
--- /dev/null
+++ b/tests/wpt/metadata/2dcontext/image-smoothing/imagesmoothing.html.ini
@@ -0,0 +1,5 @@
+[imagesmoothing.html]
+ type: testharness
+ [When the CanvasRenderingContext2D object is created, the attribute must be set to true.]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/2dcontext/line-styles/2d.line.cap.butt.html.ini b/tests/wpt/metadata/2dcontext/line-styles/2d.line.cap.butt.html.ini
new file mode 100644
index 00000000000..386a0b1cf36
--- /dev/null
+++ b/tests/wpt/metadata/2dcontext/line-styles/2d.line.cap.butt.html.ini
@@ -0,0 +1,5 @@
+[2d.line.cap.butt.html]
+ type: testharness
+ [lineCap \'butt\' is rendered correctly]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/2dcontext/line-styles/2d.line.cap.closed.html.ini b/tests/wpt/metadata/2dcontext/line-styles/2d.line.cap.closed.html.ini
new file mode 100644
index 00000000000..20856efda4e
--- /dev/null
+++ b/tests/wpt/metadata/2dcontext/line-styles/2d.line.cap.closed.html.ini
@@ -0,0 +1,5 @@
+[2d.line.cap.closed.html]
+ type: testharness
+ [Line caps are not drawn at the corners of an unclosed rectangle]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/2dcontext/line-styles/2d.line.cross.html.ini b/tests/wpt/metadata/2dcontext/line-styles/2d.line.cross.html.ini
new file mode 100644
index 00000000000..ca2d0b733fd
--- /dev/null
+++ b/tests/wpt/metadata/2dcontext/line-styles/2d.line.cross.html.ini
@@ -0,0 +1,5 @@
+[2d.line.cross.html]
+ type: testharness
+ [Canvas test: 2d.line.cross]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/2dcontext/line-styles/2d.line.join.open.html.ini b/tests/wpt/metadata/2dcontext/line-styles/2d.line.join.open.html.ini
new file mode 100644
index 00000000000..2d03bf89eb5
--- /dev/null
+++ b/tests/wpt/metadata/2dcontext/line-styles/2d.line.join.open.html.ini
@@ -0,0 +1,5 @@
+[2d.line.join.open.html]
+ type: testharness
+ [Line joins are not drawn at the corner of an unclosed rectangle]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/2dcontext/line-styles/2d.line.miter.exceeded.html.ini b/tests/wpt/metadata/2dcontext/line-styles/2d.line.miter.exceeded.html.ini
new file mode 100644
index 00000000000..9bfac57b79b
--- /dev/null
+++ b/tests/wpt/metadata/2dcontext/line-styles/2d.line.miter.exceeded.html.ini
@@ -0,0 +1,5 @@
+[2d.line.miter.exceeded.html]
+ type: testharness
+ [Miter joins are not drawn when the miter limit is exceeded]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/2dcontext/line-styles/2d.line.miter.rightangle.html.ini b/tests/wpt/metadata/2dcontext/line-styles/2d.line.miter.rightangle.html.ini
new file mode 100644
index 00000000000..ec3453af662
--- /dev/null
+++ b/tests/wpt/metadata/2dcontext/line-styles/2d.line.miter.rightangle.html.ini
@@ -0,0 +1,5 @@
+[2d.line.miter.rightangle.html]
+ type: testharness
+ [Miter joins are not drawn when the miter limit is exceeded, on exact right angles]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/2dcontext/line-styles/2d.line.width.scaledefault.html.ini b/tests/wpt/metadata/2dcontext/line-styles/2d.line.width.scaledefault.html.ini
new file mode 100644
index 00000000000..f5ee638b6a1
--- /dev/null
+++ b/tests/wpt/metadata/2dcontext/line-styles/2d.line.width.scaledefault.html.ini
@@ -0,0 +1,5 @@
+[2d.line.width.scaledefault.html]
+ type: testharness
+ [Default lineWidth strokes are affected by scale transformations]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.arc.empty.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.arc.empty.html.ini
new file mode 100644
index 00000000000..8453ab18b35
--- /dev/null
+++ b/tests/wpt/metadata/2dcontext/path-objects/2d.path.arc.empty.html.ini
@@ -0,0 +1,5 @@
+[2d.path.arc.empty.html]
+ type: testharness
+ [arc() with an empty path does not draw a straight line to the start point]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.arc.end.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.arc.end.html.ini
new file mode 100644
index 00000000000..8aa906851c8
--- /dev/null
+++ b/tests/wpt/metadata/2dcontext/path-objects/2d.path.arc.end.html.ini
@@ -0,0 +1,5 @@
+[2d.path.arc.end.html]
+ type: testharness
+ [arc() adds the end point of the arc to the subpath]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.arc.nonempty.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.arc.nonempty.html.ini
new file mode 100644
index 00000000000..7855f8b17d1
--- /dev/null
+++ b/tests/wpt/metadata/2dcontext/path-objects/2d.path.arc.nonempty.html.ini
@@ -0,0 +1,5 @@
+[2d.path.arc.nonempty.html]
+ type: testharness
+ [arc() with a non-empty path does draw a straight line to the start point]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.arc.selfintersect.1.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.arc.selfintersect.1.html.ini
new file mode 100644
index 00000000000..64fb4beeedc
--- /dev/null
+++ b/tests/wpt/metadata/2dcontext/path-objects/2d.path.arc.selfintersect.1.html.ini
@@ -0,0 +1,5 @@
+[2d.path.arc.selfintersect.1.html]
+ type: testharness
+ [arc() with lineWidth > 2*radius is drawn sensibly]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.arc.shape.1.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.arc.shape.1.html.ini
new file mode 100644
index 00000000000..005cb67064a
--- /dev/null
+++ b/tests/wpt/metadata/2dcontext/path-objects/2d.path.arc.shape.1.html.ini
@@ -0,0 +1,5 @@
+[2d.path.arc.shape.1.html]
+ type: testharness
+ [arc() from 0 to pi does not draw anything in the wrong half]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.arc.shape.3.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.arc.shape.3.html.ini
new file mode 100644
index 00000000000..9b7071262b9
--- /dev/null
+++ b/tests/wpt/metadata/2dcontext/path-objects/2d.path.arc.shape.3.html.ini
@@ -0,0 +1,5 @@
+[2d.path.arc.shape.3.html]
+ type: testharness
+ [arc() from 0 to -pi/2 does not draw anything in the wrong quadrant]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.arc.shape.5.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.arc.shape.5.html.ini
new file mode 100644
index 00000000000..7e2e20baf52
--- /dev/null
+++ b/tests/wpt/metadata/2dcontext/path-objects/2d.path.arc.shape.5.html.ini
@@ -0,0 +1,5 @@
+[2d.path.arc.shape.5.html]
+ type: testharness
+ [arc() from 0 to 5pi does not draw crazy things]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.arc.twopie.1.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.arc.twopie.1.html.ini
new file mode 100644
index 00000000000..de2110b0beb
--- /dev/null
+++ b/tests/wpt/metadata/2dcontext/path-objects/2d.path.arc.twopie.1.html.ini
@@ -0,0 +1,5 @@
+[2d.path.arc.twopie.1.html]
+ type: testharness
+ [arc() draws nothing when end = start + 2pi-e and anticlockwise]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.arc.zero.1.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.arc.zero.1.html.ini
new file mode 100644
index 00000000000..b0c2394bb03
--- /dev/null
+++ b/tests/wpt/metadata/2dcontext/path-objects/2d.path.arc.zero.1.html.ini
@@ -0,0 +1,5 @@
+[2d.path.arc.zero.1.html]
+ type: testharness
+ [arc() draws nothing when startAngle = endAngle and anticlockwise]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.arc.zero.2.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.arc.zero.2.html.ini
new file mode 100644
index 00000000000..9b1dd1a715b
--- /dev/null
+++ b/tests/wpt/metadata/2dcontext/path-objects/2d.path.arc.zero.2.html.ini
@@ -0,0 +1,5 @@
+[2d.path.arc.zero.2.html]
+ type: testharness
+ [arc() draws nothing when startAngle = endAngle and clockwise]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.arc.zeroradius.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.arc.zeroradius.html.ini
new file mode 100644
index 00000000000..c0d7eb76e57
--- /dev/null
+++ b/tests/wpt/metadata/2dcontext/path-objects/2d.path.arc.zeroradius.html.ini
@@ -0,0 +1,5 @@
+[2d.path.arc.zeroradius.html]
+ type: testharness
+ [arc() with zero radius draws a line to the start point]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.bezierCurveTo.basic.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.bezierCurveTo.basic.html.ini
new file mode 100644
index 00000000000..51f7febafc4
--- /dev/null
+++ b/tests/wpt/metadata/2dcontext/path-objects/2d.path.bezierCurveTo.basic.html.ini
@@ -0,0 +1,5 @@
+[2d.path.bezierCurveTo.basic.html]
+ type: testharness
+ [Canvas test: 2d.path.bezierCurveTo.basic]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.bezierCurveTo.ensuresubpath.1.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.bezierCurveTo.ensuresubpath.1.html.ini
new file mode 100644
index 00000000000..040e0d40e74
--- /dev/null
+++ b/tests/wpt/metadata/2dcontext/path-objects/2d.path.bezierCurveTo.ensuresubpath.1.html.ini
@@ -0,0 +1,5 @@
+[2d.path.bezierCurveTo.ensuresubpath.1.html]
+ type: testharness
+ [If there is no subpath, the first control point is added (and nothing is drawn up to it)]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.bezierCurveTo.nonfinite.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.bezierCurveTo.nonfinite.html.ini
new file mode 100644
index 00000000000..3e6cdd5d089
--- /dev/null
+++ b/tests/wpt/metadata/2dcontext/path-objects/2d.path.bezierCurveTo.nonfinite.html.ini
@@ -0,0 +1,5 @@
+[2d.path.bezierCurveTo.nonfinite.html]
+ type: testharness
+ [bezierCurveTo() with Infinity/NaN is ignored]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.bezierCurveTo.scaled.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.bezierCurveTo.scaled.html.ini
new file mode 100644
index 00000000000..438a372be12
--- /dev/null
+++ b/tests/wpt/metadata/2dcontext/path-objects/2d.path.bezierCurveTo.scaled.html.ini
@@ -0,0 +1,5 @@
+[2d.path.bezierCurveTo.scaled.html]
+ type: testharness
+ [Canvas test: 2d.path.bezierCurveTo.scaled]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.closePath.newline.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.closePath.newline.html.ini
new file mode 100644
index 00000000000..72c6c30fb79
--- /dev/null
+++ b/tests/wpt/metadata/2dcontext/path-objects/2d.path.closePath.newline.html.ini
@@ -0,0 +1,5 @@
+[2d.path.closePath.newline.html]
+ type: testharness
+ [Canvas test: 2d.path.closePath.newline]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.closePath.nextpoint.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.closePath.nextpoint.html.ini
new file mode 100644
index 00000000000..b79e0fc4396
--- /dev/null
+++ b/tests/wpt/metadata/2dcontext/path-objects/2d.path.closePath.nextpoint.html.ini
@@ -0,0 +1,5 @@
+[2d.path.closePath.nextpoint.html]
+ type: testharness
+ [Canvas test: 2d.path.closePath.nextpoint]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.lineTo.basic.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.lineTo.basic.html.ini
new file mode 100644
index 00000000000..9ad2b96500c
--- /dev/null
+++ b/tests/wpt/metadata/2dcontext/path-objects/2d.path.lineTo.basic.html.ini
@@ -0,0 +1,5 @@
+[2d.path.lineTo.basic.html]
+ type: testharness
+ [Canvas test: 2d.path.lineTo.basic]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.lineTo.ensuresubpath.1.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.lineTo.ensuresubpath.1.html.ini
new file mode 100644
index 00000000000..7fe70780084
--- /dev/null
+++ b/tests/wpt/metadata/2dcontext/path-objects/2d.path.lineTo.ensuresubpath.1.html.ini
@@ -0,0 +1,5 @@
+[2d.path.lineTo.ensuresubpath.1.html]
+ type: testharness
+ [If there is no subpath, the point is added and nothing is drawn]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.lineTo.ensuresubpath.2.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.lineTo.ensuresubpath.2.html.ini
new file mode 100644
index 00000000000..87c2f5be4b0
--- /dev/null
+++ b/tests/wpt/metadata/2dcontext/path-objects/2d.path.lineTo.ensuresubpath.2.html.ini
@@ -0,0 +1,5 @@
+[2d.path.lineTo.ensuresubpath.2.html]
+ type: testharness
+ [If there is no subpath, the point is added and used for subsequent drawing]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.lineTo.nextpoint.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.lineTo.nextpoint.html.ini
new file mode 100644
index 00000000000..0fdb557edc2
--- /dev/null
+++ b/tests/wpt/metadata/2dcontext/path-objects/2d.path.lineTo.nextpoint.html.ini
@@ -0,0 +1,5 @@
+[2d.path.lineTo.nextpoint.html]
+ type: testharness
+ [Canvas test: 2d.path.lineTo.nextpoint]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.lineTo.nonfinite.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.lineTo.nonfinite.html.ini
new file mode 100644
index 00000000000..a40bdb285b9
--- /dev/null
+++ b/tests/wpt/metadata/2dcontext/path-objects/2d.path.lineTo.nonfinite.html.ini
@@ -0,0 +1,5 @@
+[2d.path.lineTo.nonfinite.html]
+ type: testharness
+ [lineTo() with Infinity/NaN is ignored]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.moveTo.multiple.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.moveTo.multiple.html.ini
new file mode 100644
index 00000000000..88ed837c51c
--- /dev/null
+++ b/tests/wpt/metadata/2dcontext/path-objects/2d.path.moveTo.multiple.html.ini
@@ -0,0 +1,5 @@
+[2d.path.moveTo.multiple.html]
+ type: testharness
+ [Canvas test: 2d.path.moveTo.multiple]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.moveTo.nonfinite.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.moveTo.nonfinite.html.ini
new file mode 100644
index 00000000000..8d6dd344381
--- /dev/null
+++ b/tests/wpt/metadata/2dcontext/path-objects/2d.path.moveTo.nonfinite.html.ini
@@ -0,0 +1,5 @@
+[2d.path.moveTo.nonfinite.html]
+ type: testharness
+ [moveTo() with Infinity/NaN is ignored]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.quadraticCurveTo.basic.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.quadraticCurveTo.basic.html.ini
new file mode 100644
index 00000000000..d3b625a5d54
--- /dev/null
+++ b/tests/wpt/metadata/2dcontext/path-objects/2d.path.quadraticCurveTo.basic.html.ini
@@ -0,0 +1,5 @@
+[2d.path.quadraticCurveTo.basic.html]
+ type: testharness
+ [Canvas test: 2d.path.quadraticCurveTo.basic]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.quadraticCurveTo.ensuresubpath.1.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.quadraticCurveTo.ensuresubpath.1.html.ini
new file mode 100644
index 00000000000..0a1545fe4c2
--- /dev/null
+++ b/tests/wpt/metadata/2dcontext/path-objects/2d.path.quadraticCurveTo.ensuresubpath.1.html.ini
@@ -0,0 +1,5 @@
+[2d.path.quadraticCurveTo.ensuresubpath.1.html]
+ type: testharness
+ [If there is no subpath, the first control point is added (and nothing is drawn up to it)]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.quadraticCurveTo.nonfinite.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.quadraticCurveTo.nonfinite.html.ini
new file mode 100644
index 00000000000..5f47e04b2f7
--- /dev/null
+++ b/tests/wpt/metadata/2dcontext/path-objects/2d.path.quadraticCurveTo.nonfinite.html.ini
@@ -0,0 +1,5 @@
+[2d.path.quadraticCurveTo.nonfinite.html]
+ type: testharness
+ [quadraticCurveTo() with Infinity/NaN is ignored]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.quadraticCurveTo.scaled.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.quadraticCurveTo.scaled.html.ini
new file mode 100644
index 00000000000..b5866f7763b
--- /dev/null
+++ b/tests/wpt/metadata/2dcontext/path-objects/2d.path.quadraticCurveTo.scaled.html.ini
@@ -0,0 +1,5 @@
+[2d.path.quadraticCurveTo.scaled.html]
+ type: testharness
+ [Canvas test: 2d.path.quadraticCurveTo.scaled]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.stroke.empty.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.stroke.empty.html.ini
new file mode 100644
index 00000000000..0582bcd1000
--- /dev/null
+++ b/tests/wpt/metadata/2dcontext/path-objects/2d.path.stroke.empty.html.ini
@@ -0,0 +1,5 @@
+[2d.path.stroke.empty.html]
+ type: testharness
+ [Empty subpaths are not stroked]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.stroke.prune.closed.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.stroke.prune.closed.html.ini
new file mode 100644
index 00000000000..e725f778232
--- /dev/null
+++ b/tests/wpt/metadata/2dcontext/path-objects/2d.path.stroke.prune.closed.html.ini
@@ -0,0 +1,5 @@
+[2d.path.stroke.prune.closed.html]
+ type: testharness
+ [Zero-length line segments from closed paths are removed before stroking]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.stroke.prune.corner.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.stroke.prune.corner.html.ini
new file mode 100644
index 00000000000..42da280f6e4
--- /dev/null
+++ b/tests/wpt/metadata/2dcontext/path-objects/2d.path.stroke.prune.corner.html.ini
@@ -0,0 +1,5 @@
+[2d.path.stroke.prune.corner.html]
+ type: testharness
+ [Zero-length line segments are removed before stroking with miters]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.stroke.prune.curve.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.stroke.prune.curve.html.ini
new file mode 100644
index 00000000000..8c0ce9d70c1
--- /dev/null
+++ b/tests/wpt/metadata/2dcontext/path-objects/2d.path.stroke.prune.curve.html.ini
@@ -0,0 +1,5 @@
+[2d.path.stroke.prune.curve.html]
+ type: testharness
+ [Zero-length line segments from quadraticCurveTo and bezierCurveTo are removed before stroking]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/2dcontext/path-objects/2d.path.stroke.prune.line.html.ini b/tests/wpt/metadata/2dcontext/path-objects/2d.path.stroke.prune.line.html.ini
new file mode 100644
index 00000000000..5a56734aad4
--- /dev/null
+++ b/tests/wpt/metadata/2dcontext/path-objects/2d.path.stroke.prune.line.html.ini
@@ -0,0 +1,5 @@
+[2d.path.stroke.prune.line.html]
+ type: testharness
+ [Zero-length line segments from lineTo are removed before stroking]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/2dcontext/pixel-manipulation/2d.imageData.get.nonfinite.html.ini b/tests/wpt/metadata/2dcontext/pixel-manipulation/2d.imageData.get.nonfinite.html.ini
new file mode 100644
index 00000000000..dee5527cb27
--- /dev/null
+++ b/tests/wpt/metadata/2dcontext/pixel-manipulation/2d.imageData.get.nonfinite.html.ini
@@ -0,0 +1,5 @@
+[2d.imageData.get.nonfinite.html]
+ type: testharness
+ [getImageData() throws TypeError if arguments are not finite]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/2dcontext/pixel-manipulation/2d.imageData.put.nonfinite.html.ini b/tests/wpt/metadata/2dcontext/pixel-manipulation/2d.imageData.put.nonfinite.html.ini
new file mode 100644
index 00000000000..e0f83c5951d
--- /dev/null
+++ b/tests/wpt/metadata/2dcontext/pixel-manipulation/2d.imageData.put.nonfinite.html.ini
@@ -0,0 +1,5 @@
+[2d.imageData.put.nonfinite.html]
+ type: testharness
+ [putImageData() throws TypeError if arguments are not finite]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/2dcontext/shadows/2d.shadow.stroke.cap.1.html.ini b/tests/wpt/metadata/2dcontext/shadows/2d.shadow.stroke.cap.1.html.ini
new file mode 100644
index 00000000000..eae9eb9866b
--- /dev/null
+++ b/tests/wpt/metadata/2dcontext/shadows/2d.shadow.stroke.cap.1.html.ini
@@ -0,0 +1,5 @@
+[2d.shadow.stroke.cap.1.html]
+ type: testharness
+ [Shadows are not drawn for areas outside stroke caps]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/2dcontext/shadows/2d.shadow.stroke.join.1.html.ini b/tests/wpt/metadata/2dcontext/shadows/2d.shadow.stroke.join.1.html.ini
new file mode 100644
index 00000000000..252b5d3ac0e
--- /dev/null
+++ b/tests/wpt/metadata/2dcontext/shadows/2d.shadow.stroke.join.1.html.ini
@@ -0,0 +1,5 @@
+[2d.shadow.stroke.join.1.html]
+ type: testharness
+ [Shadows are not drawn for areas outside stroke joins]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/2dcontext/shadows/2d.shadow.stroke.join.3.html.ini b/tests/wpt/metadata/2dcontext/shadows/2d.shadow.stroke.join.3.html.ini
new file mode 100644
index 00000000000..c0560c8aaba
--- /dev/null
+++ b/tests/wpt/metadata/2dcontext/shadows/2d.shadow.stroke.join.3.html.ini
@@ -0,0 +1,5 @@
+[2d.shadow.stroke.join.3.html]
+ type: testharness
+ [Shadows are drawn for stroke joins respecting miter limit]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/2dcontext/transformations/2d.transformation.scale.nonfinite.html.ini b/tests/wpt/metadata/2dcontext/transformations/2d.transformation.scale.nonfinite.html.ini
new file mode 100644
index 00000000000..c8974564113
--- /dev/null
+++ b/tests/wpt/metadata/2dcontext/transformations/2d.transformation.scale.nonfinite.html.ini
@@ -0,0 +1,5 @@
+[2d.transformation.scale.nonfinite.html]
+ type: testharness
+ [scale() with Infinity/NaN is ignored]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/2dcontext/transformations/2d.transformation.setTransform.nonfinite.html.ini b/tests/wpt/metadata/2dcontext/transformations/2d.transformation.setTransform.nonfinite.html.ini
new file mode 100644
index 00000000000..3b104d0b1e2
--- /dev/null
+++ b/tests/wpt/metadata/2dcontext/transformations/2d.transformation.setTransform.nonfinite.html.ini
@@ -0,0 +1,5 @@
+[2d.transformation.setTransform.nonfinite.html]
+ type: testharness
+ [setTransform() with Infinity/NaN is ignored]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/2dcontext/transformations/2d.transformation.transform.nonfinite.html.ini b/tests/wpt/metadata/2dcontext/transformations/2d.transformation.transform.nonfinite.html.ini
new file mode 100644
index 00000000000..f96c4fdfe63
--- /dev/null
+++ b/tests/wpt/metadata/2dcontext/transformations/2d.transformation.transform.nonfinite.html.ini
@@ -0,0 +1,5 @@
+[2d.transformation.transform.nonfinite.html]
+ type: testharness
+ [transform() with Infinity/NaN is ignored]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/2dcontext/transformations/2d.transformation.translate.nonfinite.html.ini b/tests/wpt/metadata/2dcontext/transformations/2d.transformation.translate.nonfinite.html.ini
new file mode 100644
index 00000000000..130cfa45cff
--- /dev/null
+++ b/tests/wpt/metadata/2dcontext/transformations/2d.transformation.translate.nonfinite.html.ini
@@ -0,0 +1,5 @@
+[2d.transformation.translate.nonfinite.html]
+ type: testharness
+ [translate() with Infinity/NaN is ignored]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/MANIFEST.json b/tests/wpt/metadata/MANIFEST.json
index 67335b2c749..77a963fdaee 100644
--- a/tests/wpt/metadata/MANIFEST.json
+++ b/tests/wpt/metadata/MANIFEST.json
@@ -9548,6 +9548,10 @@
"url": "/XMLHttpRequest/send-non-same-origin.sub.htm"
},
{
+ "path": "XMLHttpRequest/send-receive-utf16.htm",
+ "url": "/XMLHttpRequest/send-receive-utf16.htm"
+ },
+ {
"path": "XMLHttpRequest/send-redirect-bogus-sync.htm",
"url": "/XMLHttpRequest/send-redirect-bogus-sync.htm"
},
@@ -14188,10 +14192,6 @@
"url": "/html/semantics/forms/the-textarea-element/textarea-type.html"
},
{
- "path": "html/semantics/grouping-content/the-blockquote-element/grouping-blockquote.sub.html",
- "url": "/html/semantics/grouping-content/the-blockquote-element/grouping-blockquote.sub.html"
- },
- {
"path": "html/semantics/grouping-content/the-dd-element/grouping-dd.html",
"url": "/html/semantics/grouping-content/the-dd-element/grouping-dd.html"
},
@@ -25034,7 +25034,7 @@
}
]
},
- "rev": "29dfb8944e535d439ca94cf7d1b1d9138a8ad11f",
+ "rev": "0d318188757a9c996e20b82db201fd04de5aa255",
"url_base": "/",
"version": 2
} \ No newline at end of file
diff --git a/tests/wpt/metadata/webstorage/event_constructor.html.ini b/tests/wpt/metadata/webstorage/event_constructor.html.ini
new file mode 100644
index 00000000000..3ce5130acf1
--- /dev/null
+++ b/tests/wpt/metadata/webstorage/event_constructor.html.ini
@@ -0,0 +1,9 @@
+[event_constructor.html]
+ type: testharness
+ expected: TIMEOUT
+ [Web Storage]
+ expected: FAIL
+
+ [storageeventinit test]
+ expected: NOTRUN
+
diff --git a/tests/wpt/metadata/webstorage/event_constructor_js.html.ini b/tests/wpt/metadata/webstorage/event_constructor_js.html.ini
new file mode 100644
index 00000000000..447e6c26fb6
--- /dev/null
+++ b/tests/wpt/metadata/webstorage/event_constructor_js.html.ini
@@ -0,0 +1,9 @@
+[event_constructor_js.html]
+ type: testharness
+ expected: TIMEOUT
+ [Web Storage]
+ expected: FAIL
+
+ [StorageEvent constructor and nulls]
+ expected: NOTRUN
+
diff --git a/tests/wpt/metadata/webstorage/event_local_storageeventinit.html.ini b/tests/wpt/metadata/webstorage/event_local_storageeventinit.html.ini
new file mode 100644
index 00000000000..0658b8df06c
--- /dev/null
+++ b/tests/wpt/metadata/webstorage/event_local_storageeventinit.html.ini
@@ -0,0 +1,9 @@
+[event_local_storageeventinit.html]
+ type: testharness
+ expected: TIMEOUT
+ [Web Storage]
+ expected: FAIL
+
+ [storageeventinit test]
+ expected: NOTRUN
+
diff --git a/tests/wpt/metadata/webstorage/event_session_storageeventinit.html.ini b/tests/wpt/metadata/webstorage/event_session_storageeventinit.html.ini
new file mode 100644
index 00000000000..e4584f0cc12
--- /dev/null
+++ b/tests/wpt/metadata/webstorage/event_session_storageeventinit.html.ini
@@ -0,0 +1,9 @@
+[event_session_storageeventinit.html]
+ type: testharness
+ expected: TIMEOUT
+ [Web Storage]
+ expected: FAIL
+
+ [storageeventinit test]
+ expected: NOTRUN
+
diff --git a/tests/wpt/metadata/webstorage/missing_arguments.html.ini b/tests/wpt/metadata/webstorage/missing_arguments.html.ini
new file mode 100644
index 00000000000..8cf2b387477
--- /dev/null
+++ b/tests/wpt/metadata/webstorage/missing_arguments.html.ini
@@ -0,0 +1,5 @@
+[missing_arguments.html]
+ type: testharness
+ [Should throw TypeError for function "function () { new StorageEvent(); }".]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/webstorage/storage_local_key.html.ini b/tests/wpt/metadata/webstorage/storage_local_key.html.ini
new file mode 100644
index 00000000000..6c1b6d8aac8
--- /dev/null
+++ b/tests/wpt/metadata/webstorage/storage_local_key.html.ini
@@ -0,0 +1,5 @@
+[storage_local_key.html]
+ type: testharness
+ [Web Storage 3]
+ expected: FAIL
+
diff --git a/tests/wpt/web-platform-tests b/tests/wpt/web-platform-tests
deleted file mode 160000
-Subproject 29dfb8944e535d439ca94cf7d1b1d9138a8ad11
diff --git a/tests/wpt/web-platform-tests/.gitignore b/tests/wpt/web-platform-tests/.gitignore
new file mode 100644
index 00000000000..72908a311d8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/.gitignore
@@ -0,0 +1,11 @@
+*#
+*.py[co]
+*.sw[po]
+*~
+MANIFEST.json
+\#*
+_certs
+config.json
+node_modules
+scratch
+testharness_runner.html
diff --git a/tests/wpt/web-platform-tests/.gitmodules b/tests/wpt/web-platform-tests/.gitmodules
new file mode 100644
index 00000000000..787d28dde64
--- /dev/null
+++ b/tests/wpt/web-platform-tests/.gitmodules
@@ -0,0 +1,7 @@
+[submodule "resources"]
+ path = resources
+ url = https://github.com/w3c/testharness.js.git
+ ignore = dirty
+[submodule "tools"]
+ path = tools
+ url = https://github.com/w3c/wpt-tools.git
diff --git a/tests/wpt/web-platform-tests/.travis.yml b/tests/wpt/web-platform-tests/.travis.yml
new file mode 100644
index 00000000000..566fe18a9a6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/.travis.yml
@@ -0,0 +1,7 @@
+language: python
+python:
+ - "2.7"
+before_install:
+ - git submodule update --init --recursive
+# command to run tests, e.g. python setup.py test
+script: ./lint \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/2dcontext/best-practices/.gitkeep b/tests/wpt/web-platform-tests/2dcontext/best-practices/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/best-practices/.gitkeep
diff --git a/tests/wpt/web-platform-tests/2dcontext/building-paths/.gitkeep b/tests/wpt/web-platform-tests/2dcontext/building-paths/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/building-paths/.gitkeep
diff --git a/tests/wpt/web-platform-tests/2dcontext/building-paths/canvas_complexshapes_arcto_001-ref.htm b/tests/wpt/web-platform-tests/2dcontext/building-paths/canvas_complexshapes_arcto_001-ref.htm
new file mode 100644
index 00000000000..6fc212ea482
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/building-paths/canvas_complexshapes_arcto_001-ref.htm
@@ -0,0 +1,11 @@
+<!doctype HTML>
+<html>
+ <head>
+ <title>HTML5 Canvas Test: arcTo() adds to subpath if same point</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com" />
+ </head>
+ <body>
+ <p>Description: If x1,y1 and x2,y2 are the same point, then arcTo must add x1,y1 to the subpath, and connect that point to x0,y0 with a straight line.</p>
+ <div><img src="/images/canvas-line.png" alt="line" /></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/2dcontext/building-paths/canvas_complexshapes_arcto_001.htm b/tests/wpt/web-platform-tests/2dcontext/building-paths/canvas_complexshapes_arcto_001.htm
new file mode 100644
index 00000000000..c3f2fb6f436
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/building-paths/canvas_complexshapes_arcto_001.htm
@@ -0,0 +1,26 @@
+<!doctype HTML>
+<html>
+ <head>
+ <title>HTML5 Canvas Test: arcTo() adds to subpath if same point</title>
+ <link rel="match" href="canvas_complexshapes_arcto_001-ref.htm">
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com" />
+ <link rel="help" href="http://www.w3.org/TR/2dcontext/#dom-context-2d-arcto" />
+ <meta name="assert" content="If x1,y1 and x2,y2 are the same point, then arcTo must add x1,y1 to the subpath, and connect that point to x0,y0 with a straight line." />
+ <script type="text/javascript">
+ function runTest()
+ {
+ var canvas = document.getElementById("canvas1");
+ var ctx = canvas.getContext("2d");
+ ctx.moveTo(0, 50);
+
+ // Since (x1, y1) and (x2, y2) are the same point, (x1, y1) must be added to the subpath, thus creating a line.
+ ctx.arcTo(100, 50, 100, 50, 10);
+ ctx.stroke();
+ }
+ </script>
+ </head>
+ <body onload="runTest()">
+ <p>Description: If x1,y1 and x2,y2 are the same point, then arcTo must add x1,y1 to the subpath, and connect that point to x0,y0 with a straight line.</p>
+ <canvas id="canvas1" width="300" height="150">Browser does not support HTML5 Canvas.</canvas>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/2dcontext/building-paths/canvas_complexshapes_beziercurveto_001-ref.htm b/tests/wpt/web-platform-tests/2dcontext/building-paths/canvas_complexshapes_beziercurveto_001-ref.htm
new file mode 100644
index 00000000000..935e84c5c85
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/building-paths/canvas_complexshapes_beziercurveto_001-ref.htm
@@ -0,0 +1,11 @@
+<!doctype HTML>
+<html>
+ <head>
+ <title>HTML5 Canvas Test: bezierCurveTo() must ensure subpaths</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com" />
+ </head>
+ <body>
+ <p>Description: bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y) must ensure there is a subpath for the point (cp1x,cp1y) if the context has no subpaths, then it must connect the last point in the subpath to the point (x,y).</p>
+ <div><img src='/images/smiley.png' alt='smiley' /></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/2dcontext/building-paths/canvas_complexshapes_beziercurveto_001.htm b/tests/wpt/web-platform-tests/2dcontext/building-paths/canvas_complexshapes_beziercurveto_001.htm
new file mode 100644
index 00000000000..d04926ebaca
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/building-paths/canvas_complexshapes_beziercurveto_001.htm
@@ -0,0 +1,35 @@
+<!doctype HTML>
+<html>
+ <head>
+ <title>HTML5 Canvas Test: bezierCurveTo() must ensure subpaths</title>
+ <link rel="match" href="canvas_complexshapes_beziercurveto_001-ref.htm">
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com" />
+ <link rel="help" href="http://www.w3.org/TR/2dcontext/#dom-context-2d-beziercurveto" />
+ <meta name="assert" content="bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y) must ensure there is a subpath for the point (cp1x,cp1y) if the context has no subpaths, then it must connect the last point in the subpath to the point (x,y)." />
+ <script type="text/javascript">
+ function runTest()
+ {
+ var canvas = document.getElementById("canvas1");
+ var ctx = canvas.getContext("2d");
+
+ // Since the canvas has no subpaths, a virtual moveTo must be performed to (65,25) before creating the bezier.
+ ctx.bezierCurveTo(65, 25, 65, 25, 65, 65);
+ ctx.stroke();
+ ctx.beginPath();
+
+ // Since the canvas has no subpaths, a virtual moveTo must be performed to (35,25) before creating the bezier.
+ ctx.bezierCurveTo(35, 25, 35, 25, 35, 65);
+ ctx.stroke();
+ ctx.beginPath();
+
+ // Since the canvas has no subpaths, a virtual moveTo must be performed to (0,75) before creating the bezier.
+ ctx.bezierCurveTo(0, 75, 50, 150, 100, 75);
+ ctx.stroke();
+ }
+ </script>
+ </head>
+ <body onload="runTest()">
+ <p>Description: bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y) must ensure there is a subpath for the point (cp1x,cp1y) if the context has no subpaths, then it must connect the last point in the subpath to the point (x,y).</p>
+ <canvas id="canvas1" width="300" height="150">Browser does not support HTML5 Canvas.</canvas>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/2dcontext/clear-100x50.png b/tests/wpt/web-platform-tests/2dcontext/clear-100x50.png
new file mode 100644
index 00000000000..eeedd0ff058
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/clear-100x50.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/.gitkeep b/tests/wpt/web-platform-tests/2dcontext/compositing/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/.gitkeep
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.copy.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.copy.html
new file mode 100644
index 00000000000..5f32421fb79
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.copy.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.canvas.copy</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.canvas.copy</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.canvas.copy.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+var canvas2 = document.createElement('canvas');
+canvas2.width = canvas.width;
+canvas2.height = canvas.height;
+var ctx2 = canvas2.getContext('2d');
+ctx2.drawImage(document.getElementById('yellow75.png'), 0, 0);
+ctx.fillStyle = 'rgba(0, 255, 255, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'copy';
+ctx.drawImage(canvas2, 0, 0);
+_assertPixelApprox(canvas, 50,25, 255,255,0,191, "50,25", "255,255,0,191", 5);
+
+
+});
+</script>
+<img src="/images/yellow75.png" id="yellow75.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.copy.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.copy.png
new file mode 100644
index 00000000000..8e0668efb81
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.copy.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.destination-atop.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.destination-atop.html
new file mode 100644
index 00000000000..14261d0be0f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.destination-atop.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.canvas.destination-atop</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.canvas.destination-atop</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.canvas.destination-atop.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+var canvas2 = document.createElement('canvas');
+canvas2.width = canvas.width;
+canvas2.height = canvas.height;
+var ctx2 = canvas2.getContext('2d');
+ctx2.drawImage(document.getElementById('yellow75.png'), 0, 0);
+ctx.fillStyle = 'rgba(0, 255, 255, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'destination-atop';
+ctx.drawImage(canvas2, 0, 0);
+_assertPixelApprox(canvas, 50,25, 128,255,128,191, "50,25", "128,255,128,191", 5);
+
+
+});
+</script>
+<img src="/images/yellow75.png" id="yellow75.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.destination-atop.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.destination-atop.png
new file mode 100644
index 00000000000..59bdc91e909
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.destination-atop.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.destination-in.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.destination-in.html
new file mode 100644
index 00000000000..2320064fa26
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.destination-in.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.canvas.destination-in</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.canvas.destination-in</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.canvas.destination-in.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+var canvas2 = document.createElement('canvas');
+canvas2.width = canvas.width;
+canvas2.height = canvas.height;
+var ctx2 = canvas2.getContext('2d');
+ctx2.drawImage(document.getElementById('yellow75.png'), 0, 0);
+ctx.fillStyle = 'rgba(0, 255, 255, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'destination-in';
+ctx.drawImage(canvas2, 0, 0);
+_assertPixelApprox(canvas, 50,25, 0,255,255,96, "50,25", "0,255,255,96", 5);
+
+
+});
+</script>
+<img src="/images/yellow75.png" id="yellow75.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.destination-in.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.destination-in.png
new file mode 100644
index 00000000000..790e418a6b4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.destination-in.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.destination-out.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.destination-out.html
new file mode 100644
index 00000000000..5d392eebc81
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.destination-out.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.canvas.destination-out</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.canvas.destination-out</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.canvas.destination-out.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+var canvas2 = document.createElement('canvas');
+canvas2.width = canvas.width;
+canvas2.height = canvas.height;
+var ctx2 = canvas2.getContext('2d');
+ctx2.drawImage(document.getElementById('yellow75.png'), 0, 0);
+ctx.fillStyle = 'rgba(0, 255, 255, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'destination-out';
+ctx.drawImage(canvas2, 0, 0);
+_assertPixelApprox(canvas, 50,25, 0,255,255,32, "50,25", "0,255,255,32", 5);
+
+
+});
+</script>
+<img src="/images/yellow75.png" id="yellow75.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.destination-out.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.destination-out.png
new file mode 100644
index 00000000000..7f5ed1a8360
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.destination-out.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.destination-over.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.destination-over.html
new file mode 100644
index 00000000000..130cbba8fcb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.destination-over.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.canvas.destination-over</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.canvas.destination-over</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.canvas.destination-over.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+var canvas2 = document.createElement('canvas');
+canvas2.width = canvas.width;
+canvas2.height = canvas.height;
+var ctx2 = canvas2.getContext('2d');
+ctx2.drawImage(document.getElementById('yellow75.png'), 0, 0);
+ctx.fillStyle = 'rgba(0, 255, 255, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'destination-over';
+ctx.drawImage(canvas2, 0, 0);
+_assertPixelApprox(canvas, 50,25, 109,255,146,223, "50,25", "109,255,146,223", 5);
+
+
+});
+</script>
+<img src="/images/yellow75.png" id="yellow75.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.destination-over.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.destination-over.png
new file mode 100644
index 00000000000..ac86892233f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.destination-over.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.lighter.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.lighter.html
new file mode 100644
index 00000000000..bab8118617d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.lighter.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.canvas.lighter</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.canvas.lighter</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.canvas.lighter.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+var canvas2 = document.createElement('canvas');
+canvas2.width = canvas.width;
+canvas2.height = canvas.height;
+var ctx2 = canvas2.getContext('2d');
+ctx2.drawImage(document.getElementById('yellow75.png'), 0, 0);
+ctx.fillStyle = 'rgba(0, 255, 255, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'lighter';
+ctx.drawImage(canvas2, 0, 0);
+_assertPixelApprox(canvas, 50,25, 191,255,128,255, "50,25", "191,255,128,255", 5);
+
+
+});
+</script>
+<img src="/images/yellow75.png" id="yellow75.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.lighter.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.lighter.png
new file mode 100644
index 00000000000..9ffde4198bc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.lighter.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.source-atop.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.source-atop.html
new file mode 100644
index 00000000000..3d19701ddf8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.source-atop.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.canvas.source-atop</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.canvas.source-atop</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.canvas.source-atop.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+var canvas2 = document.createElement('canvas');
+canvas2.width = canvas.width;
+canvas2.height = canvas.height;
+var ctx2 = canvas2.getContext('2d');
+ctx2.drawImage(document.getElementById('yellow75.png'), 0, 0);
+ctx.fillStyle = 'rgba(0, 255, 255, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'source-atop';
+ctx.drawImage(canvas2, 0, 0);
+_assertPixelApprox(canvas, 50,25, 191,255,64,128, "50,25", "191,255,64,128", 5);
+
+
+});
+</script>
+<img src="/images/yellow75.png" id="yellow75.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.source-atop.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.source-atop.png
new file mode 100644
index 00000000000..1ef9630195d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.source-atop.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.source-in.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.source-in.html
new file mode 100644
index 00000000000..dfc1a5af8bb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.source-in.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.canvas.source-in</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.canvas.source-in</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.canvas.source-in.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+var canvas2 = document.createElement('canvas');
+canvas2.width = canvas.width;
+canvas2.height = canvas.height;
+var ctx2 = canvas2.getContext('2d');
+ctx2.drawImage(document.getElementById('yellow75.png'), 0, 0);
+ctx.fillStyle = 'rgba(0, 255, 255, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'source-in';
+ctx.drawImage(canvas2, 0, 0);
+_assertPixelApprox(canvas, 50,25, 255,255,0,96, "50,25", "255,255,0,96", 5);
+
+
+});
+</script>
+<img src="/images/yellow75.png" id="yellow75.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.source-in.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.source-in.png
new file mode 100644
index 00000000000..c26cdccf02f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.source-in.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.source-out.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.source-out.html
new file mode 100644
index 00000000000..a4bd322bef1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.source-out.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.canvas.source-out</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.canvas.source-out</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.canvas.source-out.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+var canvas2 = document.createElement('canvas');
+canvas2.width = canvas.width;
+canvas2.height = canvas.height;
+var ctx2 = canvas2.getContext('2d');
+ctx2.drawImage(document.getElementById('yellow75.png'), 0, 0);
+ctx.fillStyle = 'rgba(0, 255, 255, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'source-out';
+ctx.drawImage(canvas2, 0, 0);
+_assertPixelApprox(canvas, 50,25, 255,255,0,96, "50,25", "255,255,0,96", 5);
+
+
+});
+</script>
+<img src="/images/yellow75.png" id="yellow75.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.source-out.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.source-out.png
new file mode 100644
index 00000000000..c26cdccf02f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.source-out.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.source-over.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.source-over.html
new file mode 100644
index 00000000000..ff8dc528bf1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.source-over.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.canvas.source-over</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.canvas.source-over</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.canvas.source-over.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+var canvas2 = document.createElement('canvas');
+canvas2.width = canvas.width;
+canvas2.height = canvas.height;
+var ctx2 = canvas2.getContext('2d');
+ctx2.drawImage(document.getElementById('yellow75.png'), 0, 0);
+ctx.fillStyle = 'rgba(0, 255, 255, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'source-over';
+ctx.drawImage(canvas2, 0, 0);
+_assertPixelApprox(canvas, 50,25, 219,255,36,223, "50,25", "219,255,36,223", 5);
+
+
+});
+</script>
+<img src="/images/yellow75.png" id="yellow75.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.source-over.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.source-over.png
new file mode 100644
index 00000000000..5437608a83b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.source-over.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.xor.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.xor.html
new file mode 100644
index 00000000000..f39a023f6fd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.xor.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.canvas.xor</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.canvas.xor</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.canvas.xor.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+var canvas2 = document.createElement('canvas');
+canvas2.width = canvas.width;
+canvas2.height = canvas.height;
+var ctx2 = canvas2.getContext('2d');
+ctx2.drawImage(document.getElementById('yellow75.png'), 0, 0);
+ctx.fillStyle = 'rgba(0, 255, 255, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'xor';
+ctx.drawImage(canvas2, 0, 0);
+_assertPixelApprox(canvas, 50,25, 191,255,64,128, "50,25", "191,255,64,128", 5);
+
+
+});
+</script>
+<img src="/images/yellow75.png" id="yellow75.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.xor.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.xor.png
new file mode 100644
index 00000000000..1ef9630195d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.canvas.xor.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.clip.copy.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.clip.copy.html
new file mode 100644
index 00000000000..08096cf1fd3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.clip.copy.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.clip.copy</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.clip.copy</h1>
+<p class="desc">fill() does not affect pixels outside the clip region.</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("fill() does not affect pixels outside the clip region.");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'copy';
+ctx.rect(-20, -20, 10, 10);
+ctx.clip();
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 50, 50);
+_assertPixel(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255");
+_assertPixel(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.clip.destination-atop.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.clip.destination-atop.html
new file mode 100644
index 00000000000..c05cd34b5f5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.clip.destination-atop.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.clip.destination-atop</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.clip.destination-atop</h1>
+<p class="desc">fill() does not affect pixels outside the clip region.</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("fill() does not affect pixels outside the clip region.");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'destination-atop';
+ctx.rect(-20, -20, 10, 10);
+ctx.clip();
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 50, 50);
+_assertPixel(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255");
+_assertPixel(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.clip.destination-in.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.clip.destination-in.html
new file mode 100644
index 00000000000..24aff70cdfb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.clip.destination-in.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.clip.destination-in</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.clip.destination-in</h1>
+<p class="desc">fill() does not affect pixels outside the clip region.</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("fill() does not affect pixels outside the clip region.");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'destination-in';
+ctx.rect(-20, -20, 10, 10);
+ctx.clip();
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 50, 50);
+_assertPixel(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255");
+_assertPixel(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.clip.destination-out.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.clip.destination-out.html
new file mode 100644
index 00000000000..afeb00984db
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.clip.destination-out.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.clip.destination-out</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.clip.destination-out</h1>
+<p class="desc">fill() does not affect pixels outside the clip region.</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("fill() does not affect pixels outside the clip region.");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'destination-out';
+ctx.rect(-20, -20, 10, 10);
+ctx.clip();
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 50, 50);
+_assertPixel(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255");
+_assertPixel(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.clip.destination-over.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.clip.destination-over.html
new file mode 100644
index 00000000000..7a258836d49
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.clip.destination-over.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.clip.destination-over</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.clip.destination-over</h1>
+<p class="desc">fill() does not affect pixels outside the clip region.</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("fill() does not affect pixels outside the clip region.");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'destination-over';
+ctx.rect(-20, -20, 10, 10);
+ctx.clip();
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 50, 50);
+_assertPixel(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255");
+_assertPixel(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.clip.lighter.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.clip.lighter.html
new file mode 100644
index 00000000000..ffc864b7b12
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.clip.lighter.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.clip.lighter</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.clip.lighter</h1>
+<p class="desc">fill() does not affect pixels outside the clip region.</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("fill() does not affect pixels outside the clip region.");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'lighter';
+ctx.rect(-20, -20, 10, 10);
+ctx.clip();
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 50, 50);
+_assertPixel(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255");
+_assertPixel(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.clip.source-atop.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.clip.source-atop.html
new file mode 100644
index 00000000000..4580b54293c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.clip.source-atop.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.clip.source-atop</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.clip.source-atop</h1>
+<p class="desc">fill() does not affect pixels outside the clip region.</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("fill() does not affect pixels outside the clip region.");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'source-atop';
+ctx.rect(-20, -20, 10, 10);
+ctx.clip();
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 50, 50);
+_assertPixel(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255");
+_assertPixel(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.clip.source-in.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.clip.source-in.html
new file mode 100644
index 00000000000..79c4e16a619
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.clip.source-in.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.clip.source-in</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.clip.source-in</h1>
+<p class="desc">fill() does not affect pixels outside the clip region.</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("fill() does not affect pixels outside the clip region.");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'source-in';
+ctx.rect(-20, -20, 10, 10);
+ctx.clip();
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 50, 50);
+_assertPixel(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255");
+_assertPixel(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.clip.source-out.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.clip.source-out.html
new file mode 100644
index 00000000000..53456660dfa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.clip.source-out.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.clip.source-out</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.clip.source-out</h1>
+<p class="desc">fill() does not affect pixels outside the clip region.</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("fill() does not affect pixels outside the clip region.");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'source-out';
+ctx.rect(-20, -20, 10, 10);
+ctx.clip();
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 50, 50);
+_assertPixel(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255");
+_assertPixel(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.clip.source-over.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.clip.source-over.html
new file mode 100644
index 00000000000..98b446a1fe3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.clip.source-over.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.clip.source-over</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.clip.source-over</h1>
+<p class="desc">fill() does not affect pixels outside the clip region.</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("fill() does not affect pixels outside the clip region.");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'source-over';
+ctx.rect(-20, -20, 10, 10);
+ctx.clip();
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 50, 50);
+_assertPixel(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255");
+_assertPixel(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.clip.xor.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.clip.xor.html
new file mode 100644
index 00000000000..b6e36bc11ac
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.clip.xor.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.clip.xor</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.clip.xor</h1>
+<p class="desc">fill() does not affect pixels outside the clip region.</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("fill() does not affect pixels outside the clip region.");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'xor';
+ctx.rect(-20, -20, 10, 10);
+ctx.clip();
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 50, 50);
+_assertPixel(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255");
+_assertPixel(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.globalAlpha.canvas.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.globalAlpha.canvas.html
new file mode 100644
index 00000000000..0b6df493057
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.globalAlpha.canvas.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.globalAlpha.canvas</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.globalAlpha.canvas</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+var canvas2 = document.createElement('canvas');
+canvas2.width = 100;
+canvas2.height = 50;
+var ctx2 = canvas2.getContext('2d');
+ctx2.fillStyle = '#f00';
+ctx2.fillRect(0, 0, 100, 50);
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalAlpha = 0.01; // avoid any potential alpha=0 optimisations
+ctx.drawImage(canvas2, 0, 0);
+_assertPixelApprox(canvas, 50,25, 2,253,0,255, "50,25", "2,253,0,255", 2);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.globalAlpha.canvaspattern.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.globalAlpha.canvaspattern.html
new file mode 100644
index 00000000000..eeb2442bf37
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.globalAlpha.canvaspattern.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.globalAlpha.canvaspattern</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.globalAlpha.canvaspattern</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+var canvas2 = document.createElement('canvas');
+canvas2.width = 100;
+canvas2.height = 50;
+var ctx2 = canvas2.getContext('2d');
+ctx2.fillStyle = '#f00';
+ctx2.fillRect(0, 0, 100, 50);
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.fillStyle = ctx.createPattern(canvas2, 'no-repeat');
+ctx.globalAlpha = 0.01; // avoid any potential alpha=0 optimisations
+ctx.fillRect(0, 0, 100, 50);
+_assertPixelApprox(canvas, 50,25, 2,253,0,255, "50,25", "2,253,0,255", 2);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.globalAlpha.default.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.globalAlpha.default.html
new file mode 100644
index 00000000000..f84a340fe21
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.globalAlpha.default.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.globalAlpha.default</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.globalAlpha.default</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+_assertSame(ctx.globalAlpha, 1.0, "ctx.globalAlpha", "1.0");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.globalAlpha.fill.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.globalAlpha.fill.html
new file mode 100644
index 00000000000..591fb6b5a5b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.globalAlpha.fill.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.globalAlpha.fill</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.globalAlpha.fill</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalAlpha = 0.01; // avoid any potential alpha=0 optimisations
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixelApprox(canvas, 50,25, 2,253,0,255, "50,25", "2,253,0,255", 2);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.globalAlpha.image.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.globalAlpha.image.html
new file mode 100644
index 00000000000..b796992dea2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.globalAlpha.image.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.globalAlpha.image</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.globalAlpha.image</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalAlpha = 0.01; // avoid any potential alpha=0 optimisations
+ctx.drawImage(document.getElementById('red.png'), 0, 0);
+_assertPixelApprox(canvas, 50,25, 2,253,0,255, "50,25", "2,253,0,255", 2);
+
+
+});
+</script>
+<img src="/images/red.png" id="red.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.globalAlpha.imagepattern.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.globalAlpha.imagepattern.html
new file mode 100644
index 00000000000..ab8633952af
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.globalAlpha.imagepattern.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.globalAlpha.imagepattern</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.globalAlpha.imagepattern</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.fillStyle = ctx.createPattern(document.getElementById('red.png'), 'no-repeat');
+ctx.globalAlpha = 0.01; // avoid any potential alpha=0 optimisations
+ctx.fillRect(0, 0, 100, 50);
+_assertPixelApprox(canvas, 50,25, 2,253,0,255, "50,25", "2,253,0,255", 2);
+
+
+});
+</script>
+<img src="/images/red.png" id="red.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.globalAlpha.invalid.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.globalAlpha.invalid.html
new file mode 100644
index 00000000000..980ef8380f8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.globalAlpha.invalid.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.globalAlpha.invalid</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.globalAlpha.invalid</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.globalAlpha = 0.5;
+var a = ctx.globalAlpha; // might not be exactly 0.5, if it is rounded/quantised, so remember for future comparisons
+ctx.globalAlpha = Infinity;
+_assertSame(ctx.globalAlpha, a, "ctx.globalAlpha", "a");
+ctx.globalAlpha = -Infinity;
+_assertSame(ctx.globalAlpha, a, "ctx.globalAlpha", "a");
+ctx.globalAlpha = NaN;
+_assertSame(ctx.globalAlpha, a, "ctx.globalAlpha", "a");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.globalAlpha.range.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.globalAlpha.range.html
new file mode 100644
index 00000000000..14926e6ebf2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.globalAlpha.range.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.globalAlpha.range</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.globalAlpha.range</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.globalAlpha = 0.5;
+var a = ctx.globalAlpha; // might not be exactly 0.5, if it is rounded/quantised, so remember for future comparisons
+ctx.globalAlpha = 1.1;
+_assertSame(ctx.globalAlpha, a, "ctx.globalAlpha", "a");
+ctx.globalAlpha = -0.1;
+_assertSame(ctx.globalAlpha, a, "ctx.globalAlpha", "a");
+ctx.globalAlpha = 0;
+_assertSame(ctx.globalAlpha, 0, "ctx.globalAlpha", "0");
+ctx.globalAlpha = 1;
+_assertSame(ctx.globalAlpha, 1, "ctx.globalAlpha", "1");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.copy.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.copy.html
new file mode 100644
index 00000000000..96492347b43
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.copy.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.image.copy</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.image.copy</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.image.copy.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'copy';
+ctx.drawImage(document.getElementById('yellow75.png'), 0, 0);
+_assertPixelApprox(canvas, 50,25, 255,255,0,191, "50,25", "255,255,0,191", 5);
+
+
+});
+</script>
+<img src="/images/yellow75.png" id="yellow75.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.copy.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.copy.png
new file mode 100644
index 00000000000..8e0668efb81
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.copy.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.destination-atop.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.destination-atop.html
new file mode 100644
index 00000000000..221e7b205cc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.destination-atop.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.image.destination-atop</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.image.destination-atop</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.image.destination-atop.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'destination-atop';
+ctx.drawImage(document.getElementById('yellow75.png'), 0, 0);
+_assertPixelApprox(canvas, 50,25, 128,255,128,191, "50,25", "128,255,128,191", 5);
+
+
+});
+</script>
+<img src="/images/yellow75.png" id="yellow75.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.destination-atop.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.destination-atop.png
new file mode 100644
index 00000000000..59bdc91e909
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.destination-atop.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.destination-in.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.destination-in.html
new file mode 100644
index 00000000000..b52860205c5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.destination-in.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.image.destination-in</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.image.destination-in</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.image.destination-in.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'destination-in';
+ctx.drawImage(document.getElementById('yellow75.png'), 0, 0);
+_assertPixelApprox(canvas, 50,25, 0,255,255,96, "50,25", "0,255,255,96", 5);
+
+
+});
+</script>
+<img src="/images/yellow75.png" id="yellow75.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.destination-in.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.destination-in.png
new file mode 100644
index 00000000000..790e418a6b4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.destination-in.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.destination-out.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.destination-out.html
new file mode 100644
index 00000000000..572ad859ad1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.destination-out.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.image.destination-out</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.image.destination-out</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.image.destination-out.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'destination-out';
+ctx.drawImage(document.getElementById('yellow75.png'), 0, 0);
+_assertPixelApprox(canvas, 50,25, 0,255,255,32, "50,25", "0,255,255,32", 5);
+
+
+});
+</script>
+<img src="/images/yellow75.png" id="yellow75.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.destination-out.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.destination-out.png
new file mode 100644
index 00000000000..7f5ed1a8360
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.destination-out.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.destination-over.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.destination-over.html
new file mode 100644
index 00000000000..16131412bce
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.destination-over.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.image.destination-over</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.image.destination-over</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.image.destination-over.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'destination-over';
+ctx.drawImage(document.getElementById('yellow75.png'), 0, 0);
+_assertPixelApprox(canvas, 50,25, 109,255,146,223, "50,25", "109,255,146,223", 5);
+
+
+});
+</script>
+<img src="/images/yellow75.png" id="yellow75.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.destination-over.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.destination-over.png
new file mode 100644
index 00000000000..ac86892233f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.destination-over.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.lighter.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.lighter.html
new file mode 100644
index 00000000000..f44d6dc3238
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.lighter.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.image.lighter</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.image.lighter</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.image.lighter.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'lighter';
+ctx.drawImage(document.getElementById('yellow75.png'), 0, 0);
+_assertPixelApprox(canvas, 50,25, 191,255,128,255, "50,25", "191,255,128,255", 5);
+
+
+});
+</script>
+<img src="/images/yellow75.png" id="yellow75.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.lighter.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.lighter.png
new file mode 100644
index 00000000000..9ffde4198bc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.lighter.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.source-atop.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.source-atop.html
new file mode 100644
index 00000000000..2d3a88a8687
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.source-atop.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.image.source-atop</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.image.source-atop</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.image.source-atop.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'source-atop';
+ctx.drawImage(document.getElementById('yellow75.png'), 0, 0);
+_assertPixelApprox(canvas, 50,25, 191,255,64,128, "50,25", "191,255,64,128", 5);
+
+
+});
+</script>
+<img src="/images/yellow75.png" id="yellow75.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.source-atop.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.source-atop.png
new file mode 100644
index 00000000000..1ef9630195d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.source-atop.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.source-in.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.source-in.html
new file mode 100644
index 00000000000..a8c1b5848c5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.source-in.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.image.source-in</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.image.source-in</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.image.source-in.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'source-in';
+ctx.drawImage(document.getElementById('yellow75.png'), 0, 0);
+_assertPixelApprox(canvas, 50,25, 255,255,0,96, "50,25", "255,255,0,96", 5);
+
+
+});
+</script>
+<img src="/images/yellow75.png" id="yellow75.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.source-in.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.source-in.png
new file mode 100644
index 00000000000..c26cdccf02f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.source-in.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.source-out.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.source-out.html
new file mode 100644
index 00000000000..079d342c007
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.source-out.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.image.source-out</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.image.source-out</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.image.source-out.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'source-out';
+ctx.drawImage(document.getElementById('yellow75.png'), 0, 0);
+_assertPixelApprox(canvas, 50,25, 255,255,0,96, "50,25", "255,255,0,96", 5);
+
+
+});
+</script>
+<img src="/images/yellow75.png" id="yellow75.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.source-out.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.source-out.png
new file mode 100644
index 00000000000..c26cdccf02f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.source-out.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.source-over.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.source-over.html
new file mode 100644
index 00000000000..bbb00e2e8ff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.source-over.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.image.source-over</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.image.source-over</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.image.source-over.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'source-over';
+ctx.drawImage(document.getElementById('yellow75.png'), 0, 0);
+_assertPixelApprox(canvas, 50,25, 219,255,36,223, "50,25", "219,255,36,223", 5);
+
+
+});
+</script>
+<img src="/images/yellow75.png" id="yellow75.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.source-over.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.source-over.png
new file mode 100644
index 00000000000..5437608a83b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.source-over.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.xor.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.xor.html
new file mode 100644
index 00000000000..a38ece5dda7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.xor.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.image.xor</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.image.xor</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.image.xor.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'xor';
+ctx.drawImage(document.getElementById('yellow75.png'), 0, 0);
+_assertPixelApprox(canvas, 50,25, 191,255,64,128, "50,25", "191,255,64,128", 5);
+
+
+});
+</script>
+<img src="/images/yellow75.png" id="yellow75.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.xor.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.xor.png
new file mode 100644
index 00000000000..1ef9630195d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.image.xor.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.operation.casesensitive.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.operation.casesensitive.html
new file mode 100644
index 00000000000..81b72375bc6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.operation.casesensitive.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.operation.casesensitive</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.operation.casesensitive</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.globalCompositeOperation = 'xor';
+ctx.globalCompositeOperation = 'Source-over';
+_assertSame(ctx.globalCompositeOperation, 'xor', "ctx.globalCompositeOperation", "'xor'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.operation.clear.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.operation.clear.html
new file mode 100644
index 00000000000..7212cd05f1e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.operation.clear.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.operation.clear</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.operation.clear</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.globalCompositeOperation = 'xor';
+ctx.globalCompositeOperation = 'clear';
+_assertSame(ctx.globalCompositeOperation, 'xor', "ctx.globalCompositeOperation", "'xor'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.operation.darker.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.operation.darker.html
new file mode 100644
index 00000000000..ac155ab047e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.operation.darker.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.operation.darker</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.operation.darker</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.globalCompositeOperation = 'xor';
+ctx.globalCompositeOperation = 'darker';
+_assertSame(ctx.globalCompositeOperation, 'xor', "ctx.globalCompositeOperation", "'xor'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.operation.default.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.operation.default.html
new file mode 100644
index 00000000000..165e8b8334a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.operation.default.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.operation.default</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.operation.default</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+_assertSame(ctx.globalCompositeOperation, 'source-over', "ctx.globalCompositeOperation", "'source-over'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.operation.get.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.operation.get.html
new file mode 100644
index 00000000000..53762dafe38
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.operation.get.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.operation.get</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.operation.get</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+var modes = ['source-atop', 'source-in', 'source-out', 'source-over',
+ 'destination-atop', 'destination-in', 'destination-out', 'destination-over',
+ 'lighter', 'copy', 'xor'];
+for (var i = 0; i < modes.length; ++i)
+{
+ ctx.globalCompositeOperation = modes[i];
+ _assertSame(ctx.globalCompositeOperation, modes[i], "ctx.globalCompositeOperation", "modes[\""+(i)+"\"]");
+}
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.operation.highlight.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.operation.highlight.html
new file mode 100644
index 00000000000..8a3bcf753bc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.operation.highlight.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.operation.highlight</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.operation.highlight</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.globalCompositeOperation = 'xor';
+ctx.globalCompositeOperation = 'highlight';
+_assertSame(ctx.globalCompositeOperation, 'xor', "ctx.globalCompositeOperation", "'xor'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.operation.nullsuffix.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.operation.nullsuffix.html
new file mode 100644
index 00000000000..aa3f8ccd5b3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.operation.nullsuffix.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.operation.nullsuffix</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.operation.nullsuffix</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.globalCompositeOperation = 'xor';
+ctx.globalCompositeOperation = 'source-over\0';
+_assertSame(ctx.globalCompositeOperation, 'xor', "ctx.globalCompositeOperation", "'xor'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.operation.over.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.operation.over.html
new file mode 100644
index 00000000000..e9b91e83ddb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.operation.over.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.operation.over</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.operation.over</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.globalCompositeOperation = 'xor';
+ctx.globalCompositeOperation = 'over';
+_assertSame(ctx.globalCompositeOperation, 'xor', "ctx.globalCompositeOperation", "'xor'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.operation.unrecognised.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.operation.unrecognised.html
new file mode 100644
index 00000000000..ced2accc4f6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.operation.unrecognised.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.operation.unrecognised</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.operation.unrecognised</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.globalCompositeOperation = 'xor';
+ctx.globalCompositeOperation = 'nonexistent';
+_assertSame(ctx.globalCompositeOperation, 'xor', "ctx.globalCompositeOperation", "'xor'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.copy.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.copy.html
new file mode 100644
index 00000000000..8bf99f3f82f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.copy.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.solid.copy</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.solid.copy</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.solid.copy.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 1.0)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'copy';
+ctx.fillStyle = 'rgba(255, 255, 0, 1.0)';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixelApprox(canvas, 50,25, 255,255,0,255, "50,25", "255,255,0,255", 5);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.copy.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.copy.png
new file mode 100644
index 00000000000..fc0883e74fe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.copy.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.destination-atop.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.destination-atop.html
new file mode 100644
index 00000000000..045caaa0280
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.destination-atop.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.solid.destination-atop</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.solid.destination-atop</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.solid.destination-atop.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 1.0)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'destination-atop';
+ctx.fillStyle = 'rgba(255, 255, 0, 1.0)';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixelApprox(canvas, 50,25, 0,255,255,255, "50,25", "0,255,255,255", 5);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.destination-atop.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.destination-atop.png
new file mode 100644
index 00000000000..dd04072baf7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.destination-atop.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.destination-in.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.destination-in.html
new file mode 100644
index 00000000000..ec27d60b4b2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.destination-in.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.solid.destination-in</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.solid.destination-in</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.solid.destination-in.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 1.0)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'destination-in';
+ctx.fillStyle = 'rgba(255, 255, 0, 1.0)';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixelApprox(canvas, 50,25, 0,255,255,255, "50,25", "0,255,255,255", 5);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.destination-in.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.destination-in.png
new file mode 100644
index 00000000000..dd04072baf7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.destination-in.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.destination-out.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.destination-out.html
new file mode 100644
index 00000000000..d96ce76cac3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.destination-out.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.solid.destination-out</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.solid.destination-out</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.solid.destination-out.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 1.0)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'destination-out';
+ctx.fillStyle = 'rgba(255, 255, 0, 1.0)';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixelApprox(canvas, 50,25, 0,0,0,0, "50,25", "0,0,0,0", 5);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.destination-out.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.destination-out.png
new file mode 100644
index 00000000000..eeedd0ff058
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.destination-out.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.destination-over.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.destination-over.html
new file mode 100644
index 00000000000..08a02387d65
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.destination-over.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.solid.destination-over</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.solid.destination-over</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.solid.destination-over.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 1.0)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'destination-over';
+ctx.fillStyle = 'rgba(255, 255, 0, 1.0)';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixelApprox(canvas, 50,25, 0,255,255,255, "50,25", "0,255,255,255", 5);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.destination-over.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.destination-over.png
new file mode 100644
index 00000000000..dd04072baf7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.destination-over.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.lighter.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.lighter.html
new file mode 100644
index 00000000000..0ffdcbb0fc9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.lighter.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.solid.lighter</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.solid.lighter</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.solid.lighter.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 1.0)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'lighter';
+ctx.fillStyle = 'rgba(255, 255, 0, 1.0)';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixelApprox(canvas, 50,25, 255,255,255,255, "50,25", "255,255,255,255", 5);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.lighter.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.lighter.png
new file mode 100644
index 00000000000..bf48767a881
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.lighter.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.source-atop.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.source-atop.html
new file mode 100644
index 00000000000..a122e437d1c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.source-atop.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.solid.source-atop</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.solid.source-atop</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.solid.source-atop.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 1.0)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'source-atop';
+ctx.fillStyle = 'rgba(255, 255, 0, 1.0)';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixelApprox(canvas, 50,25, 255,255,0,255, "50,25", "255,255,0,255", 5);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.source-atop.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.source-atop.png
new file mode 100644
index 00000000000..fc0883e74fe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.source-atop.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.source-in.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.source-in.html
new file mode 100644
index 00000000000..ae3124ffab3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.source-in.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.solid.source-in</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.solid.source-in</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.solid.source-in.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 1.0)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'source-in';
+ctx.fillStyle = 'rgba(255, 255, 0, 1.0)';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixelApprox(canvas, 50,25, 255,255,0,255, "50,25", "255,255,0,255", 5);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.source-in.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.source-in.png
new file mode 100644
index 00000000000..fc0883e74fe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.source-in.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.source-out.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.source-out.html
new file mode 100644
index 00000000000..8ea16796c8f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.source-out.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.solid.source-out</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.solid.source-out</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.solid.source-out.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 1.0)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'source-out';
+ctx.fillStyle = 'rgba(255, 255, 0, 1.0)';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixelApprox(canvas, 50,25, 0,0,0,0, "50,25", "0,0,0,0", 5);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.source-out.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.source-out.png
new file mode 100644
index 00000000000..eeedd0ff058
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.source-out.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.source-over.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.source-over.html
new file mode 100644
index 00000000000..e038d557b18
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.source-over.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.solid.source-over</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.solid.source-over</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.solid.source-over.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 1.0)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'source-over';
+ctx.fillStyle = 'rgba(255, 255, 0, 1.0)';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixelApprox(canvas, 50,25, 255,255,0,255, "50,25", "255,255,0,255", 5);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.source-over.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.source-over.png
new file mode 100644
index 00000000000..fc0883e74fe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.source-over.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.xor.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.xor.html
new file mode 100644
index 00000000000..a7b4e821e28
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.xor.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.solid.xor</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.solid.xor</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.solid.xor.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 1.0)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'xor';
+ctx.fillStyle = 'rgba(255, 255, 0, 1.0)';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixelApprox(canvas, 50,25, 0,0,0,0, "50,25", "0,0,0,0", 5);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.xor.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.xor.png
new file mode 100644
index 00000000000..eeedd0ff058
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.solid.xor.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.copy.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.copy.html
new file mode 100644
index 00000000000..ede88859e89
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.copy.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.transparent.copy</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.transparent.copy</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.transparent.copy.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = 'rgba(0, 255, 0, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'copy';
+ctx.fillStyle = 'rgba(0, 0, 255, 0.75)';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixelApprox(canvas, 50,25, 0,0,255,191, "50,25", "0,0,255,191", 5);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.copy.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.copy.png
new file mode 100644
index 00000000000..170e88183e6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.copy.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.destination-atop.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.destination-atop.html
new file mode 100644
index 00000000000..350fe2be3f9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.destination-atop.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.transparent.destination-atop</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.transparent.destination-atop</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.transparent.destination-atop.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = 'rgba(0, 255, 0, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'destination-atop';
+ctx.fillStyle = 'rgba(0, 0, 255, 0.75)';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixelApprox(canvas, 50,25, 0,128,128,191, "50,25", "0,128,128,191", 5);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.destination-atop.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.destination-atop.png
new file mode 100644
index 00000000000..57bbf64ac46
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.destination-atop.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.destination-in.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.destination-in.html
new file mode 100644
index 00000000000..b2e907d2afc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.destination-in.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.transparent.destination-in</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.transparent.destination-in</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.transparent.destination-in.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = 'rgba(0, 255, 0, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'destination-in';
+ctx.fillStyle = 'rgba(0, 0, 255, 0.75)';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixelApprox(canvas, 50,25, 0,255,0,96, "50,25", "0,255,0,96", 5);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.destination-in.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.destination-in.png
new file mode 100644
index 00000000000..c6895de9850
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.destination-in.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.destination-out.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.destination-out.html
new file mode 100644
index 00000000000..aca47b8bd75
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.destination-out.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.transparent.destination-out</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.transparent.destination-out</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.transparent.destination-out.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = 'rgba(0, 255, 0, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'destination-out';
+ctx.fillStyle = 'rgba(0, 0, 255, 0.75)';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixelApprox(canvas, 50,25, 0,255,0,32, "50,25", "0,255,0,32", 5);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.destination-out.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.destination-out.png
new file mode 100644
index 00000000000..873a9c45d8b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.destination-out.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.destination-over.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.destination-over.html
new file mode 100644
index 00000000000..676278df770
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.destination-over.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.transparent.destination-over</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.transparent.destination-over</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.transparent.destination-over.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = 'rgba(0, 255, 0, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'destination-over';
+ctx.fillStyle = 'rgba(0, 0, 255, 0.75)';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixelApprox(canvas, 50,25, 0,146,109,223, "50,25", "0,146,109,223", 5);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.destination-over.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.destination-over.png
new file mode 100644
index 00000000000..c0f0326d266
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.destination-over.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.lighter.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.lighter.html
new file mode 100644
index 00000000000..9aba34c48a5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.lighter.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.transparent.lighter</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.transparent.lighter</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.transparent.lighter.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = 'rgba(0, 255, 0, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'lighter';
+ctx.fillStyle = 'rgba(0, 0, 255, 0.75)';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixelApprox(canvas, 50,25, 0,128,191,255, "50,25", "0,128,191,255", 5);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.lighter.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.lighter.png
new file mode 100644
index 00000000000..bcb8ab40838
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.lighter.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.source-atop.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.source-atop.html
new file mode 100644
index 00000000000..18229d6ae0b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.source-atop.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.transparent.source-atop</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.transparent.source-atop</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.transparent.source-atop.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = 'rgba(0, 255, 0, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'source-atop';
+ctx.fillStyle = 'rgba(0, 0, 255, 0.75)';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixelApprox(canvas, 50,25, 0,64,191,128, "50,25", "0,64,191,128", 5);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.source-atop.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.source-atop.png
new file mode 100644
index 00000000000..e0afff6b00b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.source-atop.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.source-in.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.source-in.html
new file mode 100644
index 00000000000..57124d886e8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.source-in.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.transparent.source-in</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.transparent.source-in</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.transparent.source-in.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = 'rgba(0, 255, 0, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'source-in';
+ctx.fillStyle = 'rgba(0, 0, 255, 0.75)';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixelApprox(canvas, 50,25, 0,0,255,96, "50,25", "0,0,255,96", 5);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.source-in.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.source-in.png
new file mode 100644
index 00000000000..1459b5e54ea
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.source-in.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.source-out.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.source-out.html
new file mode 100644
index 00000000000..9b4b9d30987
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.source-out.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.transparent.source-out</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.transparent.source-out</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.transparent.source-out.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = 'rgba(0, 255, 0, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'source-out';
+ctx.fillStyle = 'rgba(0, 0, 255, 0.75)';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixelApprox(canvas, 50,25, 0,0,255,96, "50,25", "0,0,255,96", 5);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.source-out.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.source-out.png
new file mode 100644
index 00000000000..1459b5e54ea
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.source-out.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.source-over.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.source-over.html
new file mode 100644
index 00000000000..6299e8c8edc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.source-over.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.transparent.source-over</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.transparent.source-over</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.transparent.source-over.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = 'rgba(0, 255, 0, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'source-over';
+ctx.fillStyle = 'rgba(0, 0, 255, 0.75)';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixelApprox(canvas, 50,25, 0,36,219,223, "50,25", "0,36,219,223", 5);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.source-over.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.source-over.png
new file mode 100644
index 00000000000..c92cd956359
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.source-over.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.xor.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.xor.html
new file mode 100644
index 00000000000..b53d140489e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.xor.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.transparent.xor</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.transparent.xor</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.transparent.xor.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = 'rgba(0, 255, 0, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'xor';
+ctx.fillStyle = 'rgba(0, 0, 255, 0.75)';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixelApprox(canvas, 50,25, 0,64,191,128, "50,25", "0,64,191,128", 5);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.xor.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.xor.png
new file mode 100644
index 00000000000..e0afff6b00b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.transparent.xor.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.fill.copy.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.fill.copy.html
new file mode 100644
index 00000000000..966d7265dfa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.fill.copy.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.uncovered.fill.copy</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.uncovered.fill.copy</h1>
+<p class="desc">fill() draws pixels not covered by the source object as (0,0,0,0), and does not leave the pixels unchanged.</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.uncovered.fill.copy.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("fill() draws pixels not covered by the source object as (0,0,0,0), and does not leave the pixels unchanged.");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = 'rgba(0, 255, 0, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'copy';
+ctx.fillStyle = 'rgba(0, 0, 255, 0.75)';
+ctx.translate(0, 25);
+ctx.fillRect(0, 50, 100, 50);
+_assertPixelApprox(canvas, 50,25, 0,0,0,0, "50,25", "0,0,0,0", 5);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.fill.copy.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.fill.copy.png
new file mode 100644
index 00000000000..eeedd0ff058
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.fill.copy.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.fill.destination-atop.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.fill.destination-atop.html
new file mode 100644
index 00000000000..8ffc8db3f34
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.fill.destination-atop.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.uncovered.fill.destination-atop</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.uncovered.fill.destination-atop</h1>
+<p class="desc">fill() draws pixels not covered by the source object as (0,0,0,0), and does not leave the pixels unchanged.</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.uncovered.fill.destination-atop.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("fill() draws pixels not covered by the source object as (0,0,0,0), and does not leave the pixels unchanged.");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = 'rgba(0, 255, 0, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'destination-atop';
+ctx.fillStyle = 'rgba(0, 0, 255, 0.75)';
+ctx.translate(0, 25);
+ctx.fillRect(0, 50, 100, 50);
+_assertPixelApprox(canvas, 50,25, 0,0,0,0, "50,25", "0,0,0,0", 5);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.fill.destination-atop.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.fill.destination-atop.png
new file mode 100644
index 00000000000..eeedd0ff058
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.fill.destination-atop.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.fill.destination-in.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.fill.destination-in.html
new file mode 100644
index 00000000000..040fdf3515c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.fill.destination-in.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.uncovered.fill.destination-in</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.uncovered.fill.destination-in</h1>
+<p class="desc">fill() draws pixels not covered by the source object as (0,0,0,0), and does not leave the pixels unchanged.</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.uncovered.fill.destination-in.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("fill() draws pixels not covered by the source object as (0,0,0,0), and does not leave the pixels unchanged.");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = 'rgba(0, 255, 0, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'destination-in';
+ctx.fillStyle = 'rgba(0, 0, 255, 0.75)';
+ctx.translate(0, 25);
+ctx.fillRect(0, 50, 100, 50);
+_assertPixelApprox(canvas, 50,25, 0,0,0,0, "50,25", "0,0,0,0", 5);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.fill.destination-in.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.fill.destination-in.png
new file mode 100644
index 00000000000..eeedd0ff058
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.fill.destination-in.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.fill.source-in.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.fill.source-in.html
new file mode 100644
index 00000000000..4d64f909460
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.fill.source-in.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.uncovered.fill.source-in</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.uncovered.fill.source-in</h1>
+<p class="desc">fill() draws pixels not covered by the source object as (0,0,0,0), and does not leave the pixels unchanged.</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.uncovered.fill.source-in.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("fill() draws pixels not covered by the source object as (0,0,0,0), and does not leave the pixels unchanged.");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = 'rgba(0, 255, 0, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'source-in';
+ctx.fillStyle = 'rgba(0, 0, 255, 0.75)';
+ctx.translate(0, 25);
+ctx.fillRect(0, 50, 100, 50);
+_assertPixelApprox(canvas, 50,25, 0,0,0,0, "50,25", "0,0,0,0", 5);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.fill.source-in.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.fill.source-in.png
new file mode 100644
index 00000000000..eeedd0ff058
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.fill.source-in.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.fill.source-out.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.fill.source-out.html
new file mode 100644
index 00000000000..d1f39bafff7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.fill.source-out.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.uncovered.fill.source-out</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.uncovered.fill.source-out</h1>
+<p class="desc">fill() draws pixels not covered by the source object as (0,0,0,0), and does not leave the pixels unchanged.</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.uncovered.fill.source-out.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("fill() draws pixels not covered by the source object as (0,0,0,0), and does not leave the pixels unchanged.");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = 'rgba(0, 255, 0, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'source-out';
+ctx.fillStyle = 'rgba(0, 0, 255, 0.75)';
+ctx.translate(0, 25);
+ctx.fillRect(0, 50, 100, 50);
+_assertPixelApprox(canvas, 50,25, 0,0,0,0, "50,25", "0,0,0,0", 5);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.fill.source-out.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.fill.source-out.png
new file mode 100644
index 00000000000..eeedd0ff058
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.fill.source-out.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.image.copy.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.image.copy.html
new file mode 100644
index 00000000000..43e070dc3ec
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.image.copy.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.uncovered.image.copy</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.uncovered.image.copy</h1>
+<p class="desc">drawImage() draws pixels not covered by the source object as (0,0,0,0), and does not leave the pixels unchanged.</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.uncovered.image.copy.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("drawImage() draws pixels not covered by the source object as (0,0,0,0), and does not leave the pixels unchanged.");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'copy';
+ctx.drawImage(document.getElementById('yellow.png'), 40, 40, 10, 10, 40, 50, 10, 10);
+_assertPixelApprox(canvas, 15,15, 0,0,0,0, "15,15", "0,0,0,0", 5);
+_assertPixelApprox(canvas, 50,25, 0,0,0,0, "50,25", "0,0,0,0", 5);
+
+
+});
+</script>
+<img src="/images/yellow.png" id="yellow.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.image.copy.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.image.copy.png
new file mode 100644
index 00000000000..eeedd0ff058
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.image.copy.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.image.destination-atop.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.image.destination-atop.html
new file mode 100644
index 00000000000..e59e8aa89cb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.image.destination-atop.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.uncovered.image.destination-atop</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.uncovered.image.destination-atop</h1>
+<p class="desc">drawImage() draws pixels not covered by the source object as (0,0,0,0), and does not leave the pixels unchanged.</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.uncovered.image.destination-atop.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("drawImage() draws pixels not covered by the source object as (0,0,0,0), and does not leave the pixels unchanged.");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'destination-atop';
+ctx.drawImage(document.getElementById('yellow.png'), 40, 40, 10, 10, 40, 50, 10, 10);
+_assertPixelApprox(canvas, 15,15, 0,0,0,0, "15,15", "0,0,0,0", 5);
+_assertPixelApprox(canvas, 50,25, 0,0,0,0, "50,25", "0,0,0,0", 5);
+
+
+});
+</script>
+<img src="/images/yellow.png" id="yellow.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.image.destination-atop.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.image.destination-atop.png
new file mode 100644
index 00000000000..eeedd0ff058
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.image.destination-atop.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.image.destination-in.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.image.destination-in.html
new file mode 100644
index 00000000000..2872fd23652
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.image.destination-in.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.uncovered.image.destination-in</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.uncovered.image.destination-in</h1>
+<p class="desc">drawImage() draws pixels not covered by the source object as (0,0,0,0), and does not leave the pixels unchanged.</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.uncovered.image.destination-in.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("drawImage() draws pixels not covered by the source object as (0,0,0,0), and does not leave the pixels unchanged.");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'destination-in';
+ctx.drawImage(document.getElementById('yellow.png'), 40, 40, 10, 10, 40, 50, 10, 10);
+_assertPixelApprox(canvas, 15,15, 0,0,0,0, "15,15", "0,0,0,0", 5);
+_assertPixelApprox(canvas, 50,25, 0,0,0,0, "50,25", "0,0,0,0", 5);
+
+
+});
+</script>
+<img src="/images/yellow.png" id="yellow.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.image.destination-in.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.image.destination-in.png
new file mode 100644
index 00000000000..eeedd0ff058
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.image.destination-in.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.image.source-in.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.image.source-in.html
new file mode 100644
index 00000000000..234e92472da
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.image.source-in.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.uncovered.image.source-in</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.uncovered.image.source-in</h1>
+<p class="desc">drawImage() draws pixels not covered by the source object as (0,0,0,0), and does not leave the pixels unchanged.</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.uncovered.image.source-in.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("drawImage() draws pixels not covered by the source object as (0,0,0,0), and does not leave the pixels unchanged.");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'source-in';
+ctx.drawImage(document.getElementById('yellow.png'), 40, 40, 10, 10, 40, 50, 10, 10);
+_assertPixelApprox(canvas, 15,15, 0,0,0,0, "15,15", "0,0,0,0", 5);
+_assertPixelApprox(canvas, 50,25, 0,0,0,0, "50,25", "0,0,0,0", 5);
+
+
+});
+</script>
+<img src="/images/yellow.png" id="yellow.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.image.source-in.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.image.source-in.png
new file mode 100644
index 00000000000..eeedd0ff058
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.image.source-in.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.image.source-out.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.image.source-out.html
new file mode 100644
index 00000000000..4ab233a4886
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.image.source-out.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.uncovered.image.source-out</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.uncovered.image.source-out</h1>
+<p class="desc">drawImage() draws pixels not covered by the source object as (0,0,0,0), and does not leave the pixels unchanged.</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.uncovered.image.source-out.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("drawImage() draws pixels not covered by the source object as (0,0,0,0), and does not leave the pixels unchanged.");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'source-out';
+ctx.drawImage(document.getElementById('yellow.png'), 40, 40, 10, 10, 40, 50, 10, 10);
+_assertPixelApprox(canvas, 15,15, 0,0,0,0, "15,15", "0,0,0,0", 5);
+_assertPixelApprox(canvas, 50,25, 0,0,0,0, "50,25", "0,0,0,0", 5);
+
+
+});
+</script>
+<img src="/images/yellow.png" id="yellow.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.image.source-out.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.image.source-out.png
new file mode 100644
index 00000000000..eeedd0ff058
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.image.source-out.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.nocontext.copy.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.nocontext.copy.html
new file mode 100644
index 00000000000..68a93669270
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.nocontext.copy.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.uncovered.nocontext.copy</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.uncovered.nocontext.copy</h1>
+<p class="desc">drawImage() of a canvas with no context draws pixels as (0,0,0,0), and does not leave the pixels unchanged.</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.uncovered.nocontext.copy.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("drawImage() of a canvas with no context draws pixels as (0,0,0,0), and does not leave the pixels unchanged.");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'copy';
+var canvas2 = document.createElement('canvas');
+ctx.drawImage(canvas2, 0, 0);
+_assertPixelApprox(canvas, 50,25, 0,0,0,0, "50,25", "0,0,0,0", 5);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.nocontext.copy.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.nocontext.copy.png
new file mode 100644
index 00000000000..eeedd0ff058
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.nocontext.copy.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.nocontext.destination-atop.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.nocontext.destination-atop.html
new file mode 100644
index 00000000000..ad11e21d954
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.nocontext.destination-atop.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.uncovered.nocontext.destination-atop</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.uncovered.nocontext.destination-atop</h1>
+<p class="desc">drawImage() of a canvas with no context draws pixels as (0,0,0,0), and does not leave the pixels unchanged.</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.uncovered.nocontext.destination-atop.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("drawImage() of a canvas with no context draws pixels as (0,0,0,0), and does not leave the pixels unchanged.");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'destination-atop';
+var canvas2 = document.createElement('canvas');
+ctx.drawImage(canvas2, 0, 0);
+_assertPixelApprox(canvas, 50,25, 0,0,0,0, "50,25", "0,0,0,0", 5);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.nocontext.destination-atop.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.nocontext.destination-atop.png
new file mode 100644
index 00000000000..eeedd0ff058
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.nocontext.destination-atop.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.nocontext.destination-in.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.nocontext.destination-in.html
new file mode 100644
index 00000000000..0412a7aa30a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.nocontext.destination-in.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.uncovered.nocontext.destination-in</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.uncovered.nocontext.destination-in</h1>
+<p class="desc">drawImage() of a canvas with no context draws pixels as (0,0,0,0), and does not leave the pixels unchanged.</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.uncovered.nocontext.destination-in.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("drawImage() of a canvas with no context draws pixels as (0,0,0,0), and does not leave the pixels unchanged.");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'destination-in';
+var canvas2 = document.createElement('canvas');
+ctx.drawImage(canvas2, 0, 0);
+_assertPixelApprox(canvas, 50,25, 0,0,0,0, "50,25", "0,0,0,0", 5);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.nocontext.destination-in.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.nocontext.destination-in.png
new file mode 100644
index 00000000000..eeedd0ff058
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.nocontext.destination-in.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.nocontext.source-in.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.nocontext.source-in.html
new file mode 100644
index 00000000000..d6136630ede
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.nocontext.source-in.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.uncovered.nocontext.source-in</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.uncovered.nocontext.source-in</h1>
+<p class="desc">drawImage() of a canvas with no context draws pixels as (0,0,0,0), and does not leave the pixels unchanged.</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.uncovered.nocontext.source-in.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("drawImage() of a canvas with no context draws pixels as (0,0,0,0), and does not leave the pixels unchanged.");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'source-in';
+var canvas2 = document.createElement('canvas');
+ctx.drawImage(canvas2, 0, 0);
+_assertPixelApprox(canvas, 50,25, 0,0,0,0, "50,25", "0,0,0,0", 5);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.nocontext.source-in.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.nocontext.source-in.png
new file mode 100644
index 00000000000..eeedd0ff058
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.nocontext.source-in.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.nocontext.source-out.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.nocontext.source-out.html
new file mode 100644
index 00000000000..be5d6bf1226
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.nocontext.source-out.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.uncovered.nocontext.source-out</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.uncovered.nocontext.source-out</h1>
+<p class="desc">drawImage() of a canvas with no context draws pixels as (0,0,0,0), and does not leave the pixels unchanged.</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.uncovered.nocontext.source-out.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("drawImage() of a canvas with no context draws pixels as (0,0,0,0), and does not leave the pixels unchanged.");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'source-out';
+var canvas2 = document.createElement('canvas');
+ctx.drawImage(canvas2, 0, 0);
+_assertPixelApprox(canvas, 50,25, 0,0,0,0, "50,25", "0,0,0,0", 5);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.nocontext.source-out.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.nocontext.source-out.png
new file mode 100644
index 00000000000..eeedd0ff058
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.nocontext.source-out.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.pattern.copy.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.pattern.copy.html
new file mode 100644
index 00000000000..8c38388c23b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.pattern.copy.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.uncovered.pattern.copy</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.uncovered.pattern.copy</h1>
+<p class="desc">Pattern fill() draws pixels not covered by the source object as (0,0,0,0), and does not leave the pixels unchanged.</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.uncovered.pattern.copy.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Pattern fill() draws pixels not covered by the source object as (0,0,0,0), and does not leave the pixels unchanged.");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'copy';
+ctx.fillStyle = ctx.createPattern(document.getElementById('yellow.png'), 'no-repeat');
+ctx.fillRect(0, 50, 100, 50);
+_assertPixelApprox(canvas, 50,25, 0,0,0,0, "50,25", "0,0,0,0", 5);
+
+
+});
+</script>
+<img src="/images/yellow.png" id="yellow.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.pattern.copy.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.pattern.copy.png
new file mode 100644
index 00000000000..eeedd0ff058
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.pattern.copy.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.pattern.destination-atop.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.pattern.destination-atop.html
new file mode 100644
index 00000000000..7ad35f48df0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.pattern.destination-atop.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.uncovered.pattern.destination-atop</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.uncovered.pattern.destination-atop</h1>
+<p class="desc">Pattern fill() draws pixels not covered by the source object as (0,0,0,0), and does not leave the pixels unchanged.</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.uncovered.pattern.destination-atop.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Pattern fill() draws pixels not covered by the source object as (0,0,0,0), and does not leave the pixels unchanged.");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'destination-atop';
+ctx.fillStyle = ctx.createPattern(document.getElementById('yellow.png'), 'no-repeat');
+ctx.fillRect(0, 50, 100, 50);
+_assertPixelApprox(canvas, 50,25, 0,0,0,0, "50,25", "0,0,0,0", 5);
+
+
+});
+</script>
+<img src="/images/yellow.png" id="yellow.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.pattern.destination-atop.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.pattern.destination-atop.png
new file mode 100644
index 00000000000..eeedd0ff058
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.pattern.destination-atop.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.pattern.destination-in.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.pattern.destination-in.html
new file mode 100644
index 00000000000..085851c9164
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.pattern.destination-in.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.uncovered.pattern.destination-in</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.uncovered.pattern.destination-in</h1>
+<p class="desc">Pattern fill() draws pixels not covered by the source object as (0,0,0,0), and does not leave the pixels unchanged.</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.uncovered.pattern.destination-in.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Pattern fill() draws pixels not covered by the source object as (0,0,0,0), and does not leave the pixels unchanged.");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'destination-in';
+ctx.fillStyle = ctx.createPattern(document.getElementById('yellow.png'), 'no-repeat');
+ctx.fillRect(0, 50, 100, 50);
+_assertPixelApprox(canvas, 50,25, 0,0,0,0, "50,25", "0,0,0,0", 5);
+
+
+});
+</script>
+<img src="/images/yellow.png" id="yellow.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.pattern.destination-in.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.pattern.destination-in.png
new file mode 100644
index 00000000000..eeedd0ff058
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.pattern.destination-in.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.pattern.source-in.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.pattern.source-in.html
new file mode 100644
index 00000000000..7e0b8795c5e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.pattern.source-in.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.uncovered.pattern.source-in</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.uncovered.pattern.source-in</h1>
+<p class="desc">Pattern fill() draws pixels not covered by the source object as (0,0,0,0), and does not leave the pixels unchanged.</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.uncovered.pattern.source-in.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Pattern fill() draws pixels not covered by the source object as (0,0,0,0), and does not leave the pixels unchanged.");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'source-in';
+ctx.fillStyle = ctx.createPattern(document.getElementById('yellow.png'), 'no-repeat');
+ctx.fillRect(0, 50, 100, 50);
+_assertPixelApprox(canvas, 50,25, 0,0,0,0, "50,25", "0,0,0,0", 5);
+
+
+});
+</script>
+<img src="/images/yellow.png" id="yellow.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.pattern.source-in.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.pattern.source-in.png
new file mode 100644
index 00000000000..eeedd0ff058
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.pattern.source-in.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.pattern.source-out.html b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.pattern.source-out.html
new file mode 100644
index 00000000000..0d34f693c1c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.pattern.source-out.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.composite.uncovered.pattern.source-out</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.composite.uncovered.pattern.source-out</h1>
+<p class="desc">Pattern fill() draws pixels not covered by the source object as (0,0,0,0), and does not leave the pixels unchanged.</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.composite.uncovered.pattern.source-out.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Pattern fill() draws pixels not covered by the source object as (0,0,0,0), and does not leave the pixels unchanged.");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = 'rgba(0, 255, 255, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'source-out';
+ctx.fillStyle = ctx.createPattern(document.getElementById('yellow.png'), 'no-repeat');
+ctx.fillRect(0, 50, 100, 50);
+_assertPixelApprox(canvas, 50,25, 0,0,0,0, "50,25", "0,0,0,0", 5);
+
+
+});
+</script>
+<img src="/images/yellow.png" id="yellow.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.pattern.source-out.png b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.pattern.source-out.png
new file mode 100644
index 00000000000..eeedd0ff058
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/2d.composite.uncovered.pattern.source-out.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/canvas_compositing_globalcompositeoperation_001-ref.htm b/tests/wpt/web-platform-tests/2dcontext/compositing/canvas_compositing_globalcompositeoperation_001-ref.htm
new file mode 100644
index 00000000000..70196fb36ae
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/canvas_compositing_globalcompositeoperation_001-ref.htm
@@ -0,0 +1,11 @@
+<!doctype HTML>
+<html>
+ <head>
+ <title>HTML5 Canvas Test: globalCompositeOperation "destination-over"</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com" />
+ </head>
+ <body>
+ <p>Description: If the globalCompositeOperation is set to "destination-over", display the destination image wherever the destination image is opaque.</p>
+ <div><img alt='black rectangle' src="/images/black-rectangle.png"></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/2dcontext/compositing/canvas_compositing_globalcompositeoperation_001.htm b/tests/wpt/web-platform-tests/2dcontext/compositing/canvas_compositing_globalcompositeoperation_001.htm
new file mode 100644
index 00000000000..8d6208eb32e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/compositing/canvas_compositing_globalcompositeoperation_001.htm
@@ -0,0 +1,32 @@
+<!doctype HTML>
+<html>
+ <head>
+ <title>HTML5 Canvas Test: globalCompositeOperation "destination-over"</title>
+ <link rel="match" href="canvas_compositing_globalcompositeoperation_001-ref.htm">
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com" />
+ <link rel="help" href="http://www.w3.org/TR/2dcontext/#dom-context-2d-globalcompositeoperation" />
+ <meta name="assert" content="If the globalCompositeOperation is set to 'destination-over', display the destination image wherever the destination image is opaque." />
+ <script type="text/javascript">
+ function runTest()
+ {
+ var canvas = document.getElementById("canvas1");
+ var ctx = canvas.getContext("2d");
+
+ // Source image.
+ ctx.fillStyle = "rgba(0, 0, 0, 1.0)";
+ ctx.fillRect(0, 0, 100, 50);
+
+ // Assign the globalCompositeOperation.
+ ctx.globalCompositeOperation = "destination-over";
+
+ // Destination image.
+ ctx.fillStyle = "rgba(255, 0, 0, 1.0)";
+ ctx.fillRect(0, 0, 100, 50);
+ }
+ </script>
+ </head>
+ <body onload="runTest()">
+ <p>Description: If the globalCompositeOperation is set to "destination-over", display the destination image wherever the destination image is opaque.</p>
+ <canvas id="canvas1" width="300" height="150">Browser does not support HTML5 Canvas.</canvas>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/2dcontext/conformance-requirements/.gitkeep b/tests/wpt/web-platform-tests/2dcontext/conformance-requirements/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/conformance-requirements/.gitkeep
diff --git a/tests/wpt/web-platform-tests/2dcontext/conformance-requirements/2d.coordinatespace-manual.html b/tests/wpt/web-platform-tests/2dcontext/conformance-requirements/2d.coordinatespace-manual.html
new file mode 100644
index 00000000000..ba925df1b91
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/conformance-requirements/2d.coordinatespace-manual.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.coordinatespace</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.coordinatespace</h1>
+<p class="desc">Coordinate space goes from top-left to bottom-right</p>
+
+<p class="notes">This should not be upside down.
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.coordinatespace.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Coordinate space goes from top-left to bottom-right");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#00f';
+ctx.fillRect(0, 0, 100, 50);
+ctx.fillStyle = '#0ff';
+ctx.fillRect(0, 0, 50, 25);
+_assertPixel(canvas, 25,12, 0,255,255,255, "25,12", "0,255,255,255");
+_assertPixel(canvas, 75,12, 0,0,255,255, "75,12", "0,0,255,255");
+_assertPixel(canvas, 25,37, 0,0,255,255, "25,37", "0,0,255,255");
+_assertPixel(canvas, 75,37, 0,0,255,255, "75,37", "0,0,255,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/conformance-requirements/2d.coordinatespace.png b/tests/wpt/web-platform-tests/2dcontext/conformance-requirements/2d.coordinatespace.png
new file mode 100644
index 00000000000..8f8705c1486
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/conformance-requirements/2d.coordinatespace.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/conformance-requirements/2d.missingargs.html b/tests/wpt/web-platform-tests/2dcontext/conformance-requirements/2d.missingargs.html
new file mode 100644
index 00000000000..2c89cf2ac18
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/conformance-requirements/2d.missingargs.html
@@ -0,0 +1,142 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.missingargs</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.missingargs</h1>
+<p class="desc">Missing arguments cause TypeError</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Missing arguments cause TypeError");
+_addTest(function(canvas, ctx) {
+
+assert_throws(new TypeError(), function() { ctx.scale(); });
+assert_throws(new TypeError(), function() { ctx.scale(1); });
+assert_throws(new TypeError(), function() { ctx.rotate(); });
+assert_throws(new TypeError(), function() { ctx.translate(); });
+assert_throws(new TypeError(), function() { ctx.translate(0); });
+if (ctx.transform) { // (avoid spurious failures, since the aim here is not to test that all features are supported)
+ assert_throws(new TypeError(), function() { ctx.transform(); });
+ assert_throws(new TypeError(), function() { ctx.transform(1); });
+ assert_throws(new TypeError(), function() { ctx.transform(1, 0); });
+ assert_throws(new TypeError(), function() { ctx.transform(1, 0, 0); });
+ assert_throws(new TypeError(), function() { ctx.transform(1, 0, 0, 1); });
+ assert_throws(new TypeError(), function() { ctx.transform(1, 0, 0, 1, 0); });
+}
+if (ctx.setTransform) {
+ assert_throws(new TypeError(), function() { ctx.setTransform(); });
+ assert_throws(new TypeError(), function() { ctx.setTransform(1); });
+ assert_throws(new TypeError(), function() { ctx.setTransform(1, 0); });
+ assert_throws(new TypeError(), function() { ctx.setTransform(1, 0, 0); });
+ assert_throws(new TypeError(), function() { ctx.setTransform(1, 0, 0, 1); });
+ assert_throws(new TypeError(), function() { ctx.setTransform(1, 0, 0, 1, 0); });
+}
+assert_throws(new TypeError(), function() { ctx.createLinearGradient(); });
+assert_throws(new TypeError(), function() { ctx.createLinearGradient(0); });
+assert_throws(new TypeError(), function() { ctx.createLinearGradient(0, 0); });
+assert_throws(new TypeError(), function() { ctx.createLinearGradient(0, 0, 1); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(0); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(0, 0); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(0, 0, 1); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(0, 0, 1, 0); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(0, 0, 1, 0, 0); });
+assert_throws(new TypeError(), function() { ctx.createPattern(canvas); });
+assert_throws(new TypeError(), function() { ctx.clearRect(); });
+assert_throws(new TypeError(), function() { ctx.clearRect(0); });
+assert_throws(new TypeError(), function() { ctx.clearRect(0, 0); });
+assert_throws(new TypeError(), function() { ctx.clearRect(0, 0, 0); });
+assert_throws(new TypeError(), function() { ctx.fillRect(); });
+assert_throws(new TypeError(), function() { ctx.fillRect(0); });
+assert_throws(new TypeError(), function() { ctx.fillRect(0, 0); });
+assert_throws(new TypeError(), function() { ctx.fillRect(0, 0, 0); });
+assert_throws(new TypeError(), function() { ctx.strokeRect(); });
+assert_throws(new TypeError(), function() { ctx.strokeRect(0); });
+assert_throws(new TypeError(), function() { ctx.strokeRect(0, 0); });
+assert_throws(new TypeError(), function() { ctx.strokeRect(0, 0, 0); });
+assert_throws(new TypeError(), function() { ctx.moveTo(); });
+assert_throws(new TypeError(), function() { ctx.moveTo(0); });
+assert_throws(new TypeError(), function() { ctx.lineTo(); });
+assert_throws(new TypeError(), function() { ctx.lineTo(0); });
+assert_throws(new TypeError(), function() { ctx.quadraticCurveTo(); });
+assert_throws(new TypeError(), function() { ctx.quadraticCurveTo(0); });
+assert_throws(new TypeError(), function() { ctx.quadraticCurveTo(0, 0); });
+assert_throws(new TypeError(), function() { ctx.quadraticCurveTo(0, 0, 0); });
+assert_throws(new TypeError(), function() { ctx.bezierCurveTo(); });
+assert_throws(new TypeError(), function() { ctx.bezierCurveTo(0); });
+assert_throws(new TypeError(), function() { ctx.bezierCurveTo(0, 0); });
+assert_throws(new TypeError(), function() { ctx.bezierCurveTo(0, 0, 0); });
+assert_throws(new TypeError(), function() { ctx.bezierCurveTo(0, 0, 0, 0); });
+assert_throws(new TypeError(), function() { ctx.bezierCurveTo(0, 0, 0, 0, 0); });
+assert_throws(new TypeError(), function() { ctx.arcTo(); });
+assert_throws(new TypeError(), function() { ctx.arcTo(0); });
+assert_throws(new TypeError(), function() { ctx.arcTo(0, 0); });
+assert_throws(new TypeError(), function() { ctx.arcTo(0, 0, 0); });
+assert_throws(new TypeError(), function() { ctx.arcTo(0, 0, 0, 0); });
+assert_throws(new TypeError(), function() { ctx.rect(); });
+assert_throws(new TypeError(), function() { ctx.rect(0); });
+assert_throws(new TypeError(), function() { ctx.rect(0, 0); });
+assert_throws(new TypeError(), function() { ctx.rect(0, 0, 0); });
+assert_throws(new TypeError(), function() { ctx.arc(); });
+assert_throws(new TypeError(), function() { ctx.arc(0); });
+assert_throws(new TypeError(), function() { ctx.arc(0, 0); });
+assert_throws(new TypeError(), function() { ctx.arc(0, 0, 1); });
+assert_throws(new TypeError(), function() { ctx.arc(0, 0, 1, 0); });
+// (6th argument to arc is optional)
+if (ctx.isPointInPath) {
+ assert_throws(new TypeError(), function() { ctx.isPointInPath(); });
+ assert_throws(new TypeError(), function() { ctx.isPointInPath(0); });
+}
+if (ctx.drawFocusRing) {
+ assert_throws(new TypeError(), function() { ctx.drawFocusRing(); });
+ assert_throws(new TypeError(), function() { ctx.drawFocusRing(canvas); });
+ assert_throws(new TypeError(), function() { ctx.drawFocusRing(canvas, 0); });
+}
+if (ctx.fillText) {
+ assert_throws(new TypeError(), function() { ctx.fillText(); });
+ assert_throws(new TypeError(), function() { ctx.fillText('test'); });
+ assert_throws(new TypeError(), function() { ctx.fillText('test', 0); });
+ assert_throws(new TypeError(), function() { ctx.strokeText(); });
+ assert_throws(new TypeError(), function() { ctx.strokeText('test'); });
+ assert_throws(new TypeError(), function() { ctx.strokeText('test', 0); });
+ assert_throws(new TypeError(), function() { ctx.measureText(); });
+}
+assert_throws(new TypeError(), function() { ctx.drawImage(); });
+assert_throws(new TypeError(), function() { ctx.drawImage(canvas); });
+assert_throws(new TypeError(), function() { ctx.drawImage(canvas, 0); });
+// TODO: n >= 3 args on drawImage could be either a valid overload,
+// or too few for another overload, or too many for another
+// overload - what should happen?
+if (ctx.createImageData) {
+ assert_throws(new TypeError(), function() { ctx.createImageData(); });
+ assert_throws(new TypeError(), function() { ctx.createImageData(1); });
+}
+if (ctx.getImageData) {
+ assert_throws(new TypeError(), function() { ctx.getImageData(); });
+ assert_throws(new TypeError(), function() { ctx.getImageData(0); });
+ assert_throws(new TypeError(), function() { ctx.getImageData(0, 0); });
+ assert_throws(new TypeError(), function() { ctx.getImageData(0, 0, 1); });
+}
+if (ctx.putImageData) {
+ var imgdata = ctx.getImageData(0, 0, 1, 1);
+ assert_throws(new TypeError(), function() { ctx.putImageData(); });
+ assert_throws(new TypeError(), function() { ctx.putImageData(imgdata); });
+ assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, 0); });
+}
+var g = ctx.createLinearGradient(0, 0, 0, 0);
+assert_throws(new TypeError(), function() { g.addColorStop(); });
+assert_throws(new TypeError(), function() { g.addColorStop(0); });
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/conformance-requirements/2d.type.delete.html b/tests/wpt/web-platform-tests/2dcontext/conformance-requirements/2d.type.delete.html
new file mode 100644
index 00000000000..4097c35dd5c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/conformance-requirements/2d.type.delete.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.type.delete</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.type.delete</h1>
+<p class="desc">window.CanvasRenderingContext2D is Configurable</p>
+
+<p class="notes">Defined in "Web IDL" (draft)
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("window.CanvasRenderingContext2D is Configurable");
+_addTest(function(canvas, ctx) {
+
+_assertDifferent(window.CanvasRenderingContext2D, undefined, "window.CanvasRenderingContext2D", "undefined");
+_assertSame(delete window.CanvasRenderingContext2D, true, "delete window.CanvasRenderingContext2D", "true");
+_assertSame(window.CanvasRenderingContext2D, undefined, "window.CanvasRenderingContext2D", "undefined");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/conformance-requirements/2d.voidreturn.html b/tests/wpt/web-platform-tests/2dcontext/conformance-requirements/2d.voidreturn.html
new file mode 100644
index 00000000000..b23595c174c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/conformance-requirements/2d.voidreturn.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.voidreturn</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.voidreturn</h1>
+<p class="desc">void methods return undefined</p>
+
+<p class="notes">Defined in "Web IDL" (draft)
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("void methods return undefined");
+_addTest(function(canvas, ctx) {
+
+_assertSame(ctx.save(), undefined, "ctx.save()", "undefined");
+_assertSame(ctx.restore(), undefined, "ctx.restore()", "undefined");
+_assertSame(ctx.scale(1, 1), undefined, "ctx.scale(1, 1)", "undefined");
+_assertSame(ctx.rotate(0), undefined, "ctx.rotate(0)", "undefined");
+_assertSame(ctx.translate(0, 0), undefined, "ctx.translate(0, 0)", "undefined");
+if (ctx.transform) { // (avoid spurious failures, since the aim here is not to test that all features are supported)
+ _assertSame(ctx.transform(1, 0, 0, 1, 0, 0), undefined, "ctx.transform(1, 0, 0, 1, 0, 0)", "undefined");
+}
+if (ctx.setTransform) {
+ _assertSame(ctx.setTransform(1, 0, 0, 1, 0, 0), undefined, "ctx.setTransform(1, 0, 0, 1, 0, 0)", "undefined");
+}
+_assertSame(ctx.clearRect(0, 0, 0, 0), undefined, "ctx.clearRect(0, 0, 0, 0)", "undefined");
+_assertSame(ctx.fillRect(0, 0, 0, 0), undefined, "ctx.fillRect(0, 0, 0, 0)", "undefined");
+_assertSame(ctx.strokeRect(0, 0, 0, 0), undefined, "ctx.strokeRect(0, 0, 0, 0)", "undefined");
+_assertSame(ctx.beginPath(), undefined, "ctx.beginPath()", "undefined");
+_assertSame(ctx.closePath(), undefined, "ctx.closePath()", "undefined");
+_assertSame(ctx.moveTo(0, 0), undefined, "ctx.moveTo(0, 0)", "undefined");
+_assertSame(ctx.lineTo(0, 0), undefined, "ctx.lineTo(0, 0)", "undefined");
+_assertSame(ctx.quadraticCurveTo(0, 0, 0, 0), undefined, "ctx.quadraticCurveTo(0, 0, 0, 0)", "undefined");
+_assertSame(ctx.bezierCurveTo(0, 0, 0, 0, 0, 0), undefined, "ctx.bezierCurveTo(0, 0, 0, 0, 0, 0)", "undefined");
+_assertSame(ctx.arcTo(0, 0, 0, 0, 1), undefined, "ctx.arcTo(0, 0, 0, 0, 1)", "undefined");
+_assertSame(ctx.rect(0, 0, 0, 0), undefined, "ctx.rect(0, 0, 0, 0)", "undefined");
+_assertSame(ctx.arc(0, 0, 1, 0, 0, true), undefined, "ctx.arc(0, 0, 1, 0, 0, true)", "undefined");
+_assertSame(ctx.fill(), undefined, "ctx.fill()", "undefined");
+_assertSame(ctx.stroke(), undefined, "ctx.stroke()", "undefined");
+_assertSame(ctx.clip(), undefined, "ctx.clip()", "undefined");
+if (ctx.fillText) {
+ _assertSame(ctx.fillText('test', 0, 0), undefined, "ctx.fillText('test', 0, 0)", "undefined");
+ _assertSame(ctx.strokeText('test', 0, 0), undefined, "ctx.strokeText('test', 0, 0)", "undefined");
+}
+if (ctx.putImageData) {
+ _assertSame(ctx.putImageData(ctx.getImageData(0, 0, 1, 1), 0, 0), undefined, "ctx.putImageData(ctx.getImageData(0, 0, 1, 1), 0, 0)", "undefined");
+}
+_assertSame(ctx.drawImage(document.getElementById('yellow.png'), 0, 0, 1, 1, 0, 0, 0, 0), undefined, "ctx.drawImage(document.getElementById('yellow.png'), 0, 0, 1, 1, 0, 0, 0, 0)", "undefined");
+_assertSame(ctx.drawImage(canvas, 0, 0, 1, 1, 0, 0, 0, 0), undefined, "ctx.drawImage(canvas, 0, 0, 1, 1, 0, 0, 0, 0)", "undefined");
+_assertSame(ctx.createLinearGradient(0, 0, 0, 0).addColorStop(0, 'white'), undefined, "ctx.createLinearGradient(0, 0, 0, 0).addColorStop(0, 'white')", "undefined");
+
+
+});
+</script>
+<img src="/images/yellow.png" id="yellow.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/.gitkeep b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/.gitkeep
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.3arg.html b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.3arg.html
new file mode 100644
index 00000000000..b4fd347b9bf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.3arg.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.drawImage.3arg</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.drawImage.3arg</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.drawImage(document.getElementById('green.png'), 0, 0);
+ctx.drawImage(document.getElementById('red.png'), -100, 0);
+ctx.drawImage(document.getElementById('red.png'), 100, 0);
+ctx.drawImage(document.getElementById('red.png'), 0, -50);
+ctx.drawImage(document.getElementById('red.png'), 0, 50);
+
+_assertPixelApprox(canvas, 0,0, 0,255,0,255, "0,0", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 99,0, 0,255,0,255, "99,0", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 0,49, 0,255,0,255, "0,49", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 99,49, 0,255,0,255, "99,49", "0,255,0,255", 2);
+
+
+});
+</script>
+<img src="/images/red.png" id="red.png" class="resource">
+<img src="/images/green.png" id="green.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.5arg.html b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.5arg.html
new file mode 100644
index 00000000000..b2075a607ae
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.5arg.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.drawImage.5arg</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.drawImage.5arg</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.drawImage(document.getElementById('green.png'), 50, 0, 50, 50);
+ctx.drawImage(document.getElementById('red.png'), 0, 0, 50, 50);
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 50, 50);
+
+_assertPixelApprox(canvas, 0,0, 0,255,0,255, "0,0", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 99,0, 0,255,0,255, "99,0", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 0,49, 0,255,0,255, "0,49", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 99,49, 0,255,0,255, "99,49", "0,255,0,255", 2);
+
+
+});
+</script>
+<img src="/images/red.png" id="red.png" class="resource">
+<img src="/images/green.png" id="green.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.9arg.basic.html b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.9arg.basic.html
new file mode 100644
index 00000000000..8ccecae22fa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.9arg.basic.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.drawImage.9arg.basic</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.drawImage.9arg.basic</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.drawImage(document.getElementById('green.png'), 0, 0, 100, 50, 0, 0, 100, 50);
+_assertPixelApprox(canvas, 0,0, 0,255,0,255, "0,0", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 99,0, 0,255,0,255, "99,0", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 0,49, 0,255,0,255, "0,49", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 99,49, 0,255,0,255, "99,49", "0,255,0,255", 2);
+
+
+});
+</script>
+<img src="/images/green.png" id="green.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.9arg.destpos.html b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.9arg.destpos.html
new file mode 100644
index 00000000000..e71d1ab4d5d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.9arg.destpos.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.drawImage.9arg.destpos</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.drawImage.9arg.destpos</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.drawImage(document.getElementById('green.png'), 0, 0, 100, 50, 0, 0, 100, 50);
+ctx.drawImage(document.getElementById('red.png'), 0, 0, 100, 50, -100, 0, 100, 50);
+ctx.drawImage(document.getElementById('red.png'), 0, 0, 100, 50, 100, 0, 100, 50);
+ctx.drawImage(document.getElementById('red.png'), 0, 0, 100, 50, 0, -50, 100, 50);
+ctx.drawImage(document.getElementById('red.png'), 0, 0, 100, 50, 0, 50, 100, 50);
+_assertPixelApprox(canvas, 0,0, 0,255,0,255, "0,0", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 99,0, 0,255,0,255, "99,0", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 0,49, 0,255,0,255, "0,49", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 99,49, 0,255,0,255, "99,49", "0,255,0,255", 2);
+
+
+});
+</script>
+<img src="/images/red.png" id="red.png" class="resource">
+<img src="/images/green.png" id="green.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.9arg.destsize.html b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.9arg.destsize.html
new file mode 100644
index 00000000000..a76e0baa331
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.9arg.destsize.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.drawImage.9arg.destsize</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.drawImage.9arg.destsize</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.drawImage(document.getElementById('green.png'), 1, 1, 1, 1, 0, 0, 100, 50);
+ctx.drawImage(document.getElementById('red.png'), 0, 0, 100, 50, -50, 0, 50, 50);
+ctx.drawImage(document.getElementById('red.png'), 0, 0, 100, 50, 100, 0, 50, 50);
+ctx.drawImage(document.getElementById('red.png'), 0, 0, 100, 50, 0, -25, 100, 25);
+ctx.drawImage(document.getElementById('red.png'), 0, 0, 100, 50, 0, 50, 100, 25);
+_assertPixelApprox(canvas, 0,0, 0,255,0,255, "0,0", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 99,0, 0,255,0,255, "99,0", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 0,49, 0,255,0,255, "0,49", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 99,49, 0,255,0,255, "99,49", "0,255,0,255", 2);
+
+
+});
+</script>
+<img src="/images/red.png" id="red.png" class="resource">
+<img src="/images/green.png" id="green.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.9arg.sourcepos.html b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.9arg.sourcepos.html
new file mode 100644
index 00000000000..34785c75788
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.9arg.sourcepos.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.drawImage.9arg.sourcepos</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.drawImage.9arg.sourcepos</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.drawImage(document.getElementById('rgrg-256x256.png'), 140, 20, 100, 50, 0, 0, 100, 50);
+_assertPixelApprox(canvas, 0,0, 0,255,0,255, "0,0", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 99,0, 0,255,0,255, "99,0", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 0,49, 0,255,0,255, "0,49", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 99,49, 0,255,0,255, "99,49", "0,255,0,255", 2);
+
+
+});
+</script>
+<img src="/images/rgrg-256x256.png" id="rgrg-256x256.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.9arg.sourcesize.html b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.9arg.sourcesize.html
new file mode 100644
index 00000000000..a640605b1d6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.9arg.sourcesize.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.drawImage.9arg.sourcesize</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.drawImage.9arg.sourcesize</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.drawImage(document.getElementById('rgrg-256x256.png'), 0, 0, 256, 256, 0, 0, 100, 50);
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 51, 26);
+ctx.fillRect(49, 24, 51, 26);
+_assertPixelApprox(canvas, 0,0, 0,255,0,255, "0,0", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 99,0, 0,255,0,255, "99,0", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 0,49, 0,255,0,255, "0,49", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 99,49, 0,255,0,255, "99,49", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 20,20, 0,255,0,255, "20,20", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 80,20, 0,255,0,255, "80,20", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 20,30, 0,255,0,255, "20,30", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 80,30, 0,255,0,255, "80,30", "0,255,0,255", 2);
+
+
+});
+</script>
+<img src="/images/rgrg-256x256.png" id="rgrg-256x256.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.alpha.html b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.alpha.html
new file mode 100644
index 00000000000..8056c96d360
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.alpha.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.drawImage.alpha</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.drawImage.alpha</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalAlpha = 0;
+ctx.drawImage(document.getElementById('red.png'), 0, 0);
+_assertPixelApprox(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 2);
+
+
+});
+</script>
+<img src="/images/red.png" id="red.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.animated.apng.html b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.animated.apng.html
new file mode 100644
index 00000000000..bdc64462c92
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.animated.apng.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.drawImage.animated.apng</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.drawImage.animated.apng</h1>
+<p class="desc">drawImage() of an APNG with no poster frame draws the first frame</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("drawImage() of an APNG with no poster frame draws the first frame");
+_addTest(function(canvas, ctx) {
+
+deferTest();
+setTimeout(t.step_func_done(function () {
+ ctx.drawImage(document.getElementById('anim-gr.png'), 0, 0);
+ _assertPixelApprox(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 2);
+}), 500);
+
+
+});
+</script>
+<img src="/images/anim-gr.png" id="anim-gr.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.animated.gif.html b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.animated.gif.html
new file mode 100644
index 00000000000..3cf5e0fb861
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.animated.gif.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.drawImage.animated.gif</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.drawImage.animated.gif</h1>
+<p class="desc">drawImage() of an animated GIF draws the first frame</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("drawImage() of an animated GIF draws the first frame");
+_addTest(function(canvas, ctx) {
+
+deferTest();
+setTimeout(t.step_func_done(function () {
+ ctx.drawImage(document.getElementById('anim-gr.gif'), 0, 0);
+ _assertPixelApprox(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 2);
+}), 500);
+
+
+});
+</script>
+<img src="/images/anim-gr.gif" id="anim-gr.gif" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.animated.poster.html b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.animated.poster.html
new file mode 100644
index 00000000000..b0c76c1e5a2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.animated.poster.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.drawImage.animated.poster</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.drawImage.animated.poster</h1>
+<p class="desc">drawImage() of an APNG draws the poster frame</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("drawImage() of an APNG draws the poster frame");
+_addTest(function(canvas, ctx) {
+
+ctx.drawImage(document.getElementById('anim-poster-gr.png'), 0, 0);
+_assertPixelApprox(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 2);
+
+
+});
+</script>
+<img src="/images/anim-poster-gr.png" id="anim-poster-gr.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.broken.html b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.broken.html
new file mode 100644
index 00000000000..f56ece4d0c5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.broken.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.drawImage.broken</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.drawImage.broken</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+var img = document.getElementById('broken.png');
+ctx.drawImage(img, 0, 0);
+_assertPixelApprox(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 2);
+
+
+});
+</script>
+<img src="/images/broken.png" id="broken.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.canvas.html b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.canvas.html
new file mode 100644
index 00000000000..7ae9614040e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.canvas.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.drawImage.canvas</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.drawImage.canvas</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+var canvas2 = document.createElement('canvas');
+canvas2.width = 100;
+canvas2.height = 50;
+var ctx2 = canvas2.getContext('2d');
+ctx2.fillStyle = '#0f0';
+ctx2.fillRect(0, 0, 100, 50);
+
+ctx.fillStyle = '#f00';
+ctx.drawImage(canvas2, 0, 0);
+
+_assertPixelApprox(canvas, 0,0, 0,255,0,255, "0,0", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 99,0, 0,255,0,255, "99,0", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 0,49, 0,255,0,255, "0,49", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 99,49, 0,255,0,255, "99,49", "0,255,0,255", 2);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.clip.html b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.clip.html
new file mode 100644
index 00000000000..fbf86e11cbf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.clip.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.drawImage.clip</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.drawImage.clip</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.rect(-10, -10, 1, 1);
+ctx.clip();
+ctx.drawImage(document.getElementById('red.png'), 0, 0);
+_assertPixelApprox(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 2);
+
+
+});
+</script>
+<img src="/images/red.png" id="red.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.composite.html b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.composite.html
new file mode 100644
index 00000000000..e4175312b8e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.composite.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.drawImage.composite</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.drawImage.composite</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'destination-over';
+ctx.drawImage(document.getElementById('red.png'), 0, 0);
+_assertPixelApprox(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 2);
+
+
+});
+</script>
+<img src="/images/red.png" id="red.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.floatsource.html b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.floatsource.html
new file mode 100644
index 00000000000..689b1f8ae41
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.floatsource.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.drawImage.floatsource</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.drawImage.floatsource</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.drawImage(document.getElementById('green.png'), 10.1, 10.1, 0.1, 0.1, 0, 0, 100, 50);
+_assertPixelApprox(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 2);
+
+
+});
+</script>
+<img src="/images/green.png" id="green.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.incomplete.emptysrc.html b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.incomplete.emptysrc.html
new file mode 100644
index 00000000000..132e492c9af
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.incomplete.emptysrc.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.drawImage.incomplete.emptysrc</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.drawImage.incomplete.emptysrc</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+var img = document.getElementById('red.png');
+img.src = "";
+ctx.drawImage(img, 0, 0);
+_assertPixelApprox(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 2);
+
+
+});
+</script>
+<img src="/images/red.png" id="red.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.incomplete.immediate.html b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.incomplete.immediate.html
new file mode 100644
index 00000000000..1ff5ab2c471
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.incomplete.immediate.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.drawImage.incomplete.immediate</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.drawImage.incomplete.immediate</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+var img = new Image();
+img.src = '../images/red.png';
+// This triggers the "update the image data" algorithm.
+// The image will not go to the "completely available" state
+// until a fetch task in the networking task source is processed,
+// so the image must not be fully decodable yet:
+ctx.drawImage(img, 0, 0);
+_assertPixelApprox(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 2);
+
+
+});
+</script>
+<img src="/images/red.png" id="red.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.incomplete.nosrc.html b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.incomplete.nosrc.html
new file mode 100644
index 00000000000..5067b7a5c81
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.incomplete.nosrc.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.drawImage.incomplete.nosrc</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.drawImage.incomplete.nosrc</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+var img = new Image();
+ctx.drawImage(img, 0, 0);
+_assertPixelApprox(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 2);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.incomplete.reload.html b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.incomplete.reload.html
new file mode 100644
index 00000000000..efd41c938a0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.incomplete.reload.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.drawImage.incomplete.reload</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.drawImage.incomplete.reload</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+var img = document.getElementById('yellow.png');
+img.src = '../images/red.png';
+// This triggers the "update the image data" algorithm,
+// and resets the image to the "unavailable" state.
+// The image will not go to the "completely available" state
+// until a fetch task in the networking task source is processed,
+// so the image must not be fully decodable yet:
+ctx.drawImage(img, 0, 0);
+_assertPixelApprox(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 2);
+
+
+});
+</script>
+<img src="/images/yellow.png" id="yellow.png" class="resource">
+<img src="/images/red.png" id="red.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.incomplete.removedsrc.html b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.incomplete.removedsrc.html
new file mode 100644
index 00000000000..a744d591d8f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.incomplete.removedsrc.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.drawImage.incomplete.removedsrc</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.drawImage.incomplete.removedsrc</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+var img = document.getElementById('red.png');
+img.removeAttribute('src');
+ctx.drawImage(img, 0, 0);
+_assertPixelApprox(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 2);
+
+
+});
+</script>
+<img src="/images/red.png" id="red.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.negativedest.html b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.negativedest.html
new file mode 100644
index 00000000000..2d2c15849a7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.negativedest.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.drawImage.negativedest</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.drawImage.negativedest</h1>
+<p class="desc">Negative destination width/height represents the correct rectangle</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Negative destination width/height represents the correct rectangle");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.drawImage(document.getElementById('ggrr-256x256.png'), 100, 78, 50, 50, 0, 50, 50, -50);
+ctx.drawImage(document.getElementById('ggrr-256x256.png'), 100, 128, 50, -50, 100, 50, -50, -50);
+_assertPixelApprox(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 48,1, 0,255,0,255, "48,1", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 48,48, 0,255,0,255, "48,48", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 51,1, 0,255,0,255, "51,1", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 51,48, 0,255,0,255, "51,48", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255", 2);
+
+
+});
+</script>
+<img src="/images/ggrr-256x256.png" id="ggrr-256x256.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.negativedir.html b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.negativedir.html
new file mode 100644
index 00000000000..a333f8fb9f6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.negativedir.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.drawImage.negativedir</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.drawImage.negativedir</h1>
+<p class="desc">Negative dimensions do not affect the direction of the image</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Negative dimensions do not affect the direction of the image");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.drawImage(document.getElementById('ggrr-256x256.png'), 0, 178, 50, -100, 0, 0, 50, 100);
+ctx.drawImage(document.getElementById('ggrr-256x256.png'), 0, 78, 50, 100, 50, 100, 50, -100);
+_assertPixelApprox(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 48,1, 0,255,0,255, "48,1", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 48,48, 0,255,0,255, "48,48", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 51,1, 0,255,0,255, "51,1", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 51,48, 0,255,0,255, "51,48", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255", 2);
+
+
+});
+</script>
+<img src="/images/ggrr-256x256.png" id="ggrr-256x256.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.negativesource.html b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.negativesource.html
new file mode 100644
index 00000000000..af377ffdfe7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.negativesource.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.drawImage.negativesource</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.drawImage.negativesource</h1>
+<p class="desc">Negative source width/height represents the correct rectangle</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Negative source width/height represents the correct rectangle");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.drawImage(document.getElementById('ggrr-256x256.png'), 100, 78, -100, 50, 0, 0, 50, 50);
+ctx.drawImage(document.getElementById('ggrr-256x256.png'), 100, 128, -100, -50, 50, 0, 50, 50);
+_assertPixelApprox(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 48,1, 0,255,0,255, "48,1", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 48,48, 0,255,0,255, "48,48", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 51,1, 0,255,0,255, "51,1", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 51,48, 0,255,0,255, "51,48", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255", 2);
+
+
+});
+</script>
+<img src="/images/ggrr-256x256.png" id="ggrr-256x256.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.nonfinite.html b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.nonfinite.html
new file mode 100644
index 00000000000..14e634a627a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.nonfinite.html
@@ -0,0 +1,332 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.drawImage.nonfinite</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.drawImage.nonfinite</h1>
+<p class="desc">drawImage() with Infinity/NaN is ignored</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("drawImage() with Infinity/NaN is ignored");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+var red = document.getElementById('red.png');
+ctx.drawImage(red, Infinity, 0);
+ctx.drawImage(red, -Infinity, 0);
+ctx.drawImage(red, NaN, 0);
+ctx.drawImage(red, 0, Infinity);
+ctx.drawImage(red, 0, -Infinity);
+ctx.drawImage(red, 0, NaN);
+ctx.drawImage(red, Infinity, Infinity);
+ctx.drawImage(red, Infinity, 0, 100, 50);
+ctx.drawImage(red, -Infinity, 0, 100, 50);
+ctx.drawImage(red, NaN, 0, 100, 50);
+ctx.drawImage(red, 0, Infinity, 100, 50);
+ctx.drawImage(red, 0, -Infinity, 100, 50);
+ctx.drawImage(red, 0, NaN, 100, 50);
+ctx.drawImage(red, 0, 0, Infinity, 50);
+ctx.drawImage(red, 0, 0, -Infinity, 50);
+ctx.drawImage(red, 0, 0, NaN, 50);
+ctx.drawImage(red, 0, 0, 100, Infinity);
+ctx.drawImage(red, 0, 0, 100, -Infinity);
+ctx.drawImage(red, 0, 0, 100, NaN);
+ctx.drawImage(red, Infinity, Infinity, 100, 50);
+ctx.drawImage(red, Infinity, Infinity, Infinity, 50);
+ctx.drawImage(red, Infinity, Infinity, Infinity, Infinity);
+ctx.drawImage(red, Infinity, Infinity, 100, Infinity);
+ctx.drawImage(red, Infinity, 0, Infinity, 50);
+ctx.drawImage(red, Infinity, 0, Infinity, Infinity);
+ctx.drawImage(red, Infinity, 0, 100, Infinity);
+ctx.drawImage(red, 0, Infinity, Infinity, 50);
+ctx.drawImage(red, 0, Infinity, Infinity, Infinity);
+ctx.drawImage(red, 0, Infinity, 100, Infinity);
+ctx.drawImage(red, 0, 0, Infinity, Infinity);
+ctx.drawImage(red, Infinity, 0, 100, 50, 0, 0, 100, 50);
+ctx.drawImage(red, -Infinity, 0, 100, 50, 0, 0, 100, 50);
+ctx.drawImage(red, NaN, 0, 100, 50, 0, 0, 100, 50);
+ctx.drawImage(red, 0, Infinity, 100, 50, 0, 0, 100, 50);
+ctx.drawImage(red, 0, -Infinity, 100, 50, 0, 0, 100, 50);
+ctx.drawImage(red, 0, NaN, 100, 50, 0, 0, 100, 50);
+ctx.drawImage(red, 0, 0, Infinity, 50, 0, 0, 100, 50);
+ctx.drawImage(red, 0, 0, -Infinity, 50, 0, 0, 100, 50);
+ctx.drawImage(red, 0, 0, NaN, 50, 0, 0, 100, 50);
+ctx.drawImage(red, 0, 0, 100, Infinity, 0, 0, 100, 50);
+ctx.drawImage(red, 0, 0, 100, -Infinity, 0, 0, 100, 50);
+ctx.drawImage(red, 0, 0, 100, NaN, 0, 0, 100, 50);
+ctx.drawImage(red, 0, 0, 100, 50, Infinity, 0, 100, 50);
+ctx.drawImage(red, 0, 0, 100, 50, -Infinity, 0, 100, 50);
+ctx.drawImage(red, 0, 0, 100, 50, NaN, 0, 100, 50);
+ctx.drawImage(red, 0, 0, 100, 50, 0, Infinity, 100, 50);
+ctx.drawImage(red, 0, 0, 100, 50, 0, -Infinity, 100, 50);
+ctx.drawImage(red, 0, 0, 100, 50, 0, NaN, 100, 50);
+ctx.drawImage(red, 0, 0, 100, 50, 0, 0, Infinity, 50);
+ctx.drawImage(red, 0, 0, 100, 50, 0, 0, -Infinity, 50);
+ctx.drawImage(red, 0, 0, 100, 50, 0, 0, NaN, 50);
+ctx.drawImage(red, 0, 0, 100, 50, 0, 0, 100, Infinity);
+ctx.drawImage(red, 0, 0, 100, 50, 0, 0, 100, -Infinity);
+ctx.drawImage(red, 0, 0, 100, 50, 0, 0, 100, NaN);
+ctx.drawImage(red, Infinity, Infinity, 100, 50, 0, 0, 100, 50);
+ctx.drawImage(red, Infinity, Infinity, Infinity, 50, 0, 0, 100, 50);
+ctx.drawImage(red, Infinity, Infinity, Infinity, Infinity, 0, 0, 100, 50);
+ctx.drawImage(red, Infinity, Infinity, Infinity, Infinity, Infinity, 0, 100, 50);
+ctx.drawImage(red, Infinity, Infinity, Infinity, Infinity, Infinity, Infinity, 100, 50);
+ctx.drawImage(red, Infinity, Infinity, Infinity, Infinity, Infinity, Infinity, Infinity, 50);
+ctx.drawImage(red, Infinity, Infinity, Infinity, Infinity, Infinity, Infinity, Infinity, Infinity);
+ctx.drawImage(red, Infinity, Infinity, Infinity, Infinity, Infinity, Infinity, 100, Infinity);
+ctx.drawImage(red, Infinity, Infinity, Infinity, Infinity, Infinity, 0, Infinity, 50);
+ctx.drawImage(red, Infinity, Infinity, Infinity, Infinity, Infinity, 0, Infinity, Infinity);
+ctx.drawImage(red, Infinity, Infinity, Infinity, Infinity, Infinity, 0, 100, Infinity);
+ctx.drawImage(red, Infinity, Infinity, Infinity, Infinity, 0, Infinity, 100, 50);
+ctx.drawImage(red, Infinity, Infinity, Infinity, Infinity, 0, Infinity, Infinity, 50);
+ctx.drawImage(red, Infinity, Infinity, Infinity, Infinity, 0, Infinity, Infinity, Infinity);
+ctx.drawImage(red, Infinity, Infinity, Infinity, Infinity, 0, Infinity, 100, Infinity);
+ctx.drawImage(red, Infinity, Infinity, Infinity, Infinity, 0, 0, Infinity, 50);
+ctx.drawImage(red, Infinity, Infinity, Infinity, Infinity, 0, 0, Infinity, Infinity);
+ctx.drawImage(red, Infinity, Infinity, Infinity, Infinity, 0, 0, 100, Infinity);
+ctx.drawImage(red, Infinity, Infinity, Infinity, 50, Infinity, 0, 100, 50);
+ctx.drawImage(red, Infinity, Infinity, Infinity, 50, Infinity, Infinity, 100, 50);
+ctx.drawImage(red, Infinity, Infinity, Infinity, 50, Infinity, Infinity, Infinity, 50);
+ctx.drawImage(red, Infinity, Infinity, Infinity, 50, Infinity, Infinity, Infinity, Infinity);
+ctx.drawImage(red, Infinity, Infinity, Infinity, 50, Infinity, Infinity, 100, Infinity);
+ctx.drawImage(red, Infinity, Infinity, Infinity, 50, Infinity, 0, Infinity, 50);
+ctx.drawImage(red, Infinity, Infinity, Infinity, 50, Infinity, 0, Infinity, Infinity);
+ctx.drawImage(red, Infinity, Infinity, Infinity, 50, Infinity, 0, 100, Infinity);
+ctx.drawImage(red, Infinity, Infinity, Infinity, 50, 0, Infinity, 100, 50);
+ctx.drawImage(red, Infinity, Infinity, Infinity, 50, 0, Infinity, Infinity, 50);
+ctx.drawImage(red, Infinity, Infinity, Infinity, 50, 0, Infinity, Infinity, Infinity);
+ctx.drawImage(red, Infinity, Infinity, Infinity, 50, 0, Infinity, 100, Infinity);
+ctx.drawImage(red, Infinity, Infinity, Infinity, 50, 0, 0, Infinity, 50);
+ctx.drawImage(red, Infinity, Infinity, Infinity, 50, 0, 0, Infinity, Infinity);
+ctx.drawImage(red, Infinity, Infinity, Infinity, 50, 0, 0, 100, Infinity);
+ctx.drawImage(red, Infinity, Infinity, 100, Infinity, 0, 0, 100, 50);
+ctx.drawImage(red, Infinity, Infinity, 100, Infinity, Infinity, 0, 100, 50);
+ctx.drawImage(red, Infinity, Infinity, 100, Infinity, Infinity, Infinity, 100, 50);
+ctx.drawImage(red, Infinity, Infinity, 100, Infinity, Infinity, Infinity, Infinity, 50);
+ctx.drawImage(red, Infinity, Infinity, 100, Infinity, Infinity, Infinity, Infinity, Infinity);
+ctx.drawImage(red, Infinity, Infinity, 100, Infinity, Infinity, Infinity, 100, Infinity);
+ctx.drawImage(red, Infinity, Infinity, 100, Infinity, Infinity, 0, Infinity, 50);
+ctx.drawImage(red, Infinity, Infinity, 100, Infinity, Infinity, 0, Infinity, Infinity);
+ctx.drawImage(red, Infinity, Infinity, 100, Infinity, Infinity, 0, 100, Infinity);
+ctx.drawImage(red, Infinity, Infinity, 100, Infinity, 0, Infinity, 100, 50);
+ctx.drawImage(red, Infinity, Infinity, 100, Infinity, 0, Infinity, Infinity, 50);
+ctx.drawImage(red, Infinity, Infinity, 100, Infinity, 0, Infinity, Infinity, Infinity);
+ctx.drawImage(red, Infinity, Infinity, 100, Infinity, 0, Infinity, 100, Infinity);
+ctx.drawImage(red, Infinity, Infinity, 100, Infinity, 0, 0, Infinity, 50);
+ctx.drawImage(red, Infinity, Infinity, 100, Infinity, 0, 0, Infinity, Infinity);
+ctx.drawImage(red, Infinity, Infinity, 100, Infinity, 0, 0, 100, Infinity);
+ctx.drawImage(red, Infinity, Infinity, 100, 50, Infinity, 0, 100, 50);
+ctx.drawImage(red, Infinity, Infinity, 100, 50, Infinity, Infinity, 100, 50);
+ctx.drawImage(red, Infinity, Infinity, 100, 50, Infinity, Infinity, Infinity, 50);
+ctx.drawImage(red, Infinity, Infinity, 100, 50, Infinity, Infinity, Infinity, Infinity);
+ctx.drawImage(red, Infinity, Infinity, 100, 50, Infinity, Infinity, 100, Infinity);
+ctx.drawImage(red, Infinity, Infinity, 100, 50, Infinity, 0, Infinity, 50);
+ctx.drawImage(red, Infinity, Infinity, 100, 50, Infinity, 0, Infinity, Infinity);
+ctx.drawImage(red, Infinity, Infinity, 100, 50, Infinity, 0, 100, Infinity);
+ctx.drawImage(red, Infinity, Infinity, 100, 50, 0, Infinity, 100, 50);
+ctx.drawImage(red, Infinity, Infinity, 100, 50, 0, Infinity, Infinity, 50);
+ctx.drawImage(red, Infinity, Infinity, 100, 50, 0, Infinity, Infinity, Infinity);
+ctx.drawImage(red, Infinity, Infinity, 100, 50, 0, Infinity, 100, Infinity);
+ctx.drawImage(red, Infinity, Infinity, 100, 50, 0, 0, Infinity, 50);
+ctx.drawImage(red, Infinity, Infinity, 100, 50, 0, 0, Infinity, Infinity);
+ctx.drawImage(red, Infinity, Infinity, 100, 50, 0, 0, 100, Infinity);
+ctx.drawImage(red, Infinity, 0, Infinity, 50, 0, 0, 100, 50);
+ctx.drawImage(red, Infinity, 0, Infinity, Infinity, 0, 0, 100, 50);
+ctx.drawImage(red, Infinity, 0, Infinity, Infinity, Infinity, 0, 100, 50);
+ctx.drawImage(red, Infinity, 0, Infinity, Infinity, Infinity, Infinity, 100, 50);
+ctx.drawImage(red, Infinity, 0, Infinity, Infinity, Infinity, Infinity, Infinity, 50);
+ctx.drawImage(red, Infinity, 0, Infinity, Infinity, Infinity, Infinity, Infinity, Infinity);
+ctx.drawImage(red, Infinity, 0, Infinity, Infinity, Infinity, Infinity, 100, Infinity);
+ctx.drawImage(red, Infinity, 0, Infinity, Infinity, Infinity, 0, Infinity, 50);
+ctx.drawImage(red, Infinity, 0, Infinity, Infinity, Infinity, 0, Infinity, Infinity);
+ctx.drawImage(red, Infinity, 0, Infinity, Infinity, Infinity, 0, 100, Infinity);
+ctx.drawImage(red, Infinity, 0, Infinity, Infinity, 0, Infinity, 100, 50);
+ctx.drawImage(red, Infinity, 0, Infinity, Infinity, 0, Infinity, Infinity, 50);
+ctx.drawImage(red, Infinity, 0, Infinity, Infinity, 0, Infinity, Infinity, Infinity);
+ctx.drawImage(red, Infinity, 0, Infinity, Infinity, 0, Infinity, 100, Infinity);
+ctx.drawImage(red, Infinity, 0, Infinity, Infinity, 0, 0, Infinity, 50);
+ctx.drawImage(red, Infinity, 0, Infinity, Infinity, 0, 0, Infinity, Infinity);
+ctx.drawImage(red, Infinity, 0, Infinity, Infinity, 0, 0, 100, Infinity);
+ctx.drawImage(red, Infinity, 0, Infinity, 50, Infinity, 0, 100, 50);
+ctx.drawImage(red, Infinity, 0, Infinity, 50, Infinity, Infinity, 100, 50);
+ctx.drawImage(red, Infinity, 0, Infinity, 50, Infinity, Infinity, Infinity, 50);
+ctx.drawImage(red, Infinity, 0, Infinity, 50, Infinity, Infinity, Infinity, Infinity);
+ctx.drawImage(red, Infinity, 0, Infinity, 50, Infinity, Infinity, 100, Infinity);
+ctx.drawImage(red, Infinity, 0, Infinity, 50, Infinity, 0, Infinity, 50);
+ctx.drawImage(red, Infinity, 0, Infinity, 50, Infinity, 0, Infinity, Infinity);
+ctx.drawImage(red, Infinity, 0, Infinity, 50, Infinity, 0, 100, Infinity);
+ctx.drawImage(red, Infinity, 0, Infinity, 50, 0, Infinity, 100, 50);
+ctx.drawImage(red, Infinity, 0, Infinity, 50, 0, Infinity, Infinity, 50);
+ctx.drawImage(red, Infinity, 0, Infinity, 50, 0, Infinity, Infinity, Infinity);
+ctx.drawImage(red, Infinity, 0, Infinity, 50, 0, Infinity, 100, Infinity);
+ctx.drawImage(red, Infinity, 0, Infinity, 50, 0, 0, Infinity, 50);
+ctx.drawImage(red, Infinity, 0, Infinity, 50, 0, 0, Infinity, Infinity);
+ctx.drawImage(red, Infinity, 0, Infinity, 50, 0, 0, 100, Infinity);
+ctx.drawImage(red, Infinity, 0, 100, Infinity, 0, 0, 100, 50);
+ctx.drawImage(red, Infinity, 0, 100, Infinity, Infinity, 0, 100, 50);
+ctx.drawImage(red, Infinity, 0, 100, Infinity, Infinity, Infinity, 100, 50);
+ctx.drawImage(red, Infinity, 0, 100, Infinity, Infinity, Infinity, Infinity, 50);
+ctx.drawImage(red, Infinity, 0, 100, Infinity, Infinity, Infinity, Infinity, Infinity);
+ctx.drawImage(red, Infinity, 0, 100, Infinity, Infinity, Infinity, 100, Infinity);
+ctx.drawImage(red, Infinity, 0, 100, Infinity, Infinity, 0, Infinity, 50);
+ctx.drawImage(red, Infinity, 0, 100, Infinity, Infinity, 0, Infinity, Infinity);
+ctx.drawImage(red, Infinity, 0, 100, Infinity, Infinity, 0, 100, Infinity);
+ctx.drawImage(red, Infinity, 0, 100, Infinity, 0, Infinity, 100, 50);
+ctx.drawImage(red, Infinity, 0, 100, Infinity, 0, Infinity, Infinity, 50);
+ctx.drawImage(red, Infinity, 0, 100, Infinity, 0, Infinity, Infinity, Infinity);
+ctx.drawImage(red, Infinity, 0, 100, Infinity, 0, Infinity, 100, Infinity);
+ctx.drawImage(red, Infinity, 0, 100, Infinity, 0, 0, Infinity, 50);
+ctx.drawImage(red, Infinity, 0, 100, Infinity, 0, 0, Infinity, Infinity);
+ctx.drawImage(red, Infinity, 0, 100, Infinity, 0, 0, 100, Infinity);
+ctx.drawImage(red, Infinity, 0, 100, 50, Infinity, 0, 100, 50);
+ctx.drawImage(red, Infinity, 0, 100, 50, Infinity, Infinity, 100, 50);
+ctx.drawImage(red, Infinity, 0, 100, 50, Infinity, Infinity, Infinity, 50);
+ctx.drawImage(red, Infinity, 0, 100, 50, Infinity, Infinity, Infinity, Infinity);
+ctx.drawImage(red, Infinity, 0, 100, 50, Infinity, Infinity, 100, Infinity);
+ctx.drawImage(red, Infinity, 0, 100, 50, Infinity, 0, Infinity, 50);
+ctx.drawImage(red, Infinity, 0, 100, 50, Infinity, 0, Infinity, Infinity);
+ctx.drawImage(red, Infinity, 0, 100, 50, Infinity, 0, 100, Infinity);
+ctx.drawImage(red, Infinity, 0, 100, 50, 0, Infinity, 100, 50);
+ctx.drawImage(red, Infinity, 0, 100, 50, 0, Infinity, Infinity, 50);
+ctx.drawImage(red, Infinity, 0, 100, 50, 0, Infinity, Infinity, Infinity);
+ctx.drawImage(red, Infinity, 0, 100, 50, 0, Infinity, 100, Infinity);
+ctx.drawImage(red, Infinity, 0, 100, 50, 0, 0, Infinity, 50);
+ctx.drawImage(red, Infinity, 0, 100, 50, 0, 0, Infinity, Infinity);
+ctx.drawImage(red, Infinity, 0, 100, 50, 0, 0, 100, Infinity);
+ctx.drawImage(red, 0, Infinity, Infinity, 50, 0, 0, 100, 50);
+ctx.drawImage(red, 0, Infinity, Infinity, Infinity, 0, 0, 100, 50);
+ctx.drawImage(red, 0, Infinity, Infinity, Infinity, Infinity, 0, 100, 50);
+ctx.drawImage(red, 0, Infinity, Infinity, Infinity, Infinity, Infinity, 100, 50);
+ctx.drawImage(red, 0, Infinity, Infinity, Infinity, Infinity, Infinity, Infinity, 50);
+ctx.drawImage(red, 0, Infinity, Infinity, Infinity, Infinity, Infinity, Infinity, Infinity);
+ctx.drawImage(red, 0, Infinity, Infinity, Infinity, Infinity, Infinity, 100, Infinity);
+ctx.drawImage(red, 0, Infinity, Infinity, Infinity, Infinity, 0, Infinity, 50);
+ctx.drawImage(red, 0, Infinity, Infinity, Infinity, Infinity, 0, Infinity, Infinity);
+ctx.drawImage(red, 0, Infinity, Infinity, Infinity, Infinity, 0, 100, Infinity);
+ctx.drawImage(red, 0, Infinity, Infinity, Infinity, 0, Infinity, 100, 50);
+ctx.drawImage(red, 0, Infinity, Infinity, Infinity, 0, Infinity, Infinity, 50);
+ctx.drawImage(red, 0, Infinity, Infinity, Infinity, 0, Infinity, Infinity, Infinity);
+ctx.drawImage(red, 0, Infinity, Infinity, Infinity, 0, Infinity, 100, Infinity);
+ctx.drawImage(red, 0, Infinity, Infinity, Infinity, 0, 0, Infinity, 50);
+ctx.drawImage(red, 0, Infinity, Infinity, Infinity, 0, 0, Infinity, Infinity);
+ctx.drawImage(red, 0, Infinity, Infinity, Infinity, 0, 0, 100, Infinity);
+ctx.drawImage(red, 0, Infinity, Infinity, 50, Infinity, 0, 100, 50);
+ctx.drawImage(red, 0, Infinity, Infinity, 50, Infinity, Infinity, 100, 50);
+ctx.drawImage(red, 0, Infinity, Infinity, 50, Infinity, Infinity, Infinity, 50);
+ctx.drawImage(red, 0, Infinity, Infinity, 50, Infinity, Infinity, Infinity, Infinity);
+ctx.drawImage(red, 0, Infinity, Infinity, 50, Infinity, Infinity, 100, Infinity);
+ctx.drawImage(red, 0, Infinity, Infinity, 50, Infinity, 0, Infinity, 50);
+ctx.drawImage(red, 0, Infinity, Infinity, 50, Infinity, 0, Infinity, Infinity);
+ctx.drawImage(red, 0, Infinity, Infinity, 50, Infinity, 0, 100, Infinity);
+ctx.drawImage(red, 0, Infinity, Infinity, 50, 0, Infinity, 100, 50);
+ctx.drawImage(red, 0, Infinity, Infinity, 50, 0, Infinity, Infinity, 50);
+ctx.drawImage(red, 0, Infinity, Infinity, 50, 0, Infinity, Infinity, Infinity);
+ctx.drawImage(red, 0, Infinity, Infinity, 50, 0, Infinity, 100, Infinity);
+ctx.drawImage(red, 0, Infinity, Infinity, 50, 0, 0, Infinity, 50);
+ctx.drawImage(red, 0, Infinity, Infinity, 50, 0, 0, Infinity, Infinity);
+ctx.drawImage(red, 0, Infinity, Infinity, 50, 0, 0, 100, Infinity);
+ctx.drawImage(red, 0, Infinity, 100, Infinity, 0, 0, 100, 50);
+ctx.drawImage(red, 0, Infinity, 100, Infinity, Infinity, 0, 100, 50);
+ctx.drawImage(red, 0, Infinity, 100, Infinity, Infinity, Infinity, 100, 50);
+ctx.drawImage(red, 0, Infinity, 100, Infinity, Infinity, Infinity, Infinity, 50);
+ctx.drawImage(red, 0, Infinity, 100, Infinity, Infinity, Infinity, Infinity, Infinity);
+ctx.drawImage(red, 0, Infinity, 100, Infinity, Infinity, Infinity, 100, Infinity);
+ctx.drawImage(red, 0, Infinity, 100, Infinity, Infinity, 0, Infinity, 50);
+ctx.drawImage(red, 0, Infinity, 100, Infinity, Infinity, 0, Infinity, Infinity);
+ctx.drawImage(red, 0, Infinity, 100, Infinity, Infinity, 0, 100, Infinity);
+ctx.drawImage(red, 0, Infinity, 100, Infinity, 0, Infinity, 100, 50);
+ctx.drawImage(red, 0, Infinity, 100, Infinity, 0, Infinity, Infinity, 50);
+ctx.drawImage(red, 0, Infinity, 100, Infinity, 0, Infinity, Infinity, Infinity);
+ctx.drawImage(red, 0, Infinity, 100, Infinity, 0, Infinity, 100, Infinity);
+ctx.drawImage(red, 0, Infinity, 100, Infinity, 0, 0, Infinity, 50);
+ctx.drawImage(red, 0, Infinity, 100, Infinity, 0, 0, Infinity, Infinity);
+ctx.drawImage(red, 0, Infinity, 100, Infinity, 0, 0, 100, Infinity);
+ctx.drawImage(red, 0, Infinity, 100, 50, Infinity, 0, 100, 50);
+ctx.drawImage(red, 0, Infinity, 100, 50, Infinity, Infinity, 100, 50);
+ctx.drawImage(red, 0, Infinity, 100, 50, Infinity, Infinity, Infinity, 50);
+ctx.drawImage(red, 0, Infinity, 100, 50, Infinity, Infinity, Infinity, Infinity);
+ctx.drawImage(red, 0, Infinity, 100, 50, Infinity, Infinity, 100, Infinity);
+ctx.drawImage(red, 0, Infinity, 100, 50, Infinity, 0, Infinity, 50);
+ctx.drawImage(red, 0, Infinity, 100, 50, Infinity, 0, Infinity, Infinity);
+ctx.drawImage(red, 0, Infinity, 100, 50, Infinity, 0, 100, Infinity);
+ctx.drawImage(red, 0, Infinity, 100, 50, 0, Infinity, 100, 50);
+ctx.drawImage(red, 0, Infinity, 100, 50, 0, Infinity, Infinity, 50);
+ctx.drawImage(red, 0, Infinity, 100, 50, 0, Infinity, Infinity, Infinity);
+ctx.drawImage(red, 0, Infinity, 100, 50, 0, Infinity, 100, Infinity);
+ctx.drawImage(red, 0, Infinity, 100, 50, 0, 0, Infinity, 50);
+ctx.drawImage(red, 0, Infinity, 100, 50, 0, 0, Infinity, Infinity);
+ctx.drawImage(red, 0, Infinity, 100, 50, 0, 0, 100, Infinity);
+ctx.drawImage(red, 0, 0, Infinity, Infinity, 0, 0, 100, 50);
+ctx.drawImage(red, 0, 0, Infinity, Infinity, Infinity, 0, 100, 50);
+ctx.drawImage(red, 0, 0, Infinity, Infinity, Infinity, Infinity, 100, 50);
+ctx.drawImage(red, 0, 0, Infinity, Infinity, Infinity, Infinity, Infinity, 50);
+ctx.drawImage(red, 0, 0, Infinity, Infinity, Infinity, Infinity, Infinity, Infinity);
+ctx.drawImage(red, 0, 0, Infinity, Infinity, Infinity, Infinity, 100, Infinity);
+ctx.drawImage(red, 0, 0, Infinity, Infinity, Infinity, 0, Infinity, 50);
+ctx.drawImage(red, 0, 0, Infinity, Infinity, Infinity, 0, Infinity, Infinity);
+ctx.drawImage(red, 0, 0, Infinity, Infinity, Infinity, 0, 100, Infinity);
+ctx.drawImage(red, 0, 0, Infinity, Infinity, 0, Infinity, 100, 50);
+ctx.drawImage(red, 0, 0, Infinity, Infinity, 0, Infinity, Infinity, 50);
+ctx.drawImage(red, 0, 0, Infinity, Infinity, 0, Infinity, Infinity, Infinity);
+ctx.drawImage(red, 0, 0, Infinity, Infinity, 0, Infinity, 100, Infinity);
+ctx.drawImage(red, 0, 0, Infinity, Infinity, 0, 0, Infinity, 50);
+ctx.drawImage(red, 0, 0, Infinity, Infinity, 0, 0, Infinity, Infinity);
+ctx.drawImage(red, 0, 0, Infinity, Infinity, 0, 0, 100, Infinity);
+ctx.drawImage(red, 0, 0, Infinity, 50, Infinity, 0, 100, 50);
+ctx.drawImage(red, 0, 0, Infinity, 50, Infinity, Infinity, 100, 50);
+ctx.drawImage(red, 0, 0, Infinity, 50, Infinity, Infinity, Infinity, 50);
+ctx.drawImage(red, 0, 0, Infinity, 50, Infinity, Infinity, Infinity, Infinity);
+ctx.drawImage(red, 0, 0, Infinity, 50, Infinity, Infinity, 100, Infinity);
+ctx.drawImage(red, 0, 0, Infinity, 50, Infinity, 0, Infinity, 50);
+ctx.drawImage(red, 0, 0, Infinity, 50, Infinity, 0, Infinity, Infinity);
+ctx.drawImage(red, 0, 0, Infinity, 50, Infinity, 0, 100, Infinity);
+ctx.drawImage(red, 0, 0, Infinity, 50, 0, Infinity, 100, 50);
+ctx.drawImage(red, 0, 0, Infinity, 50, 0, Infinity, Infinity, 50);
+ctx.drawImage(red, 0, 0, Infinity, 50, 0, Infinity, Infinity, Infinity);
+ctx.drawImage(red, 0, 0, Infinity, 50, 0, Infinity, 100, Infinity);
+ctx.drawImage(red, 0, 0, Infinity, 50, 0, 0, Infinity, 50);
+ctx.drawImage(red, 0, 0, Infinity, 50, 0, 0, Infinity, Infinity);
+ctx.drawImage(red, 0, 0, Infinity, 50, 0, 0, 100, Infinity);
+ctx.drawImage(red, 0, 0, 100, Infinity, Infinity, 0, 100, 50);
+ctx.drawImage(red, 0, 0, 100, Infinity, Infinity, Infinity, 100, 50);
+ctx.drawImage(red, 0, 0, 100, Infinity, Infinity, Infinity, Infinity, 50);
+ctx.drawImage(red, 0, 0, 100, Infinity, Infinity, Infinity, Infinity, Infinity);
+ctx.drawImage(red, 0, 0, 100, Infinity, Infinity, Infinity, 100, Infinity);
+ctx.drawImage(red, 0, 0, 100, Infinity, Infinity, 0, Infinity, 50);
+ctx.drawImage(red, 0, 0, 100, Infinity, Infinity, 0, Infinity, Infinity);
+ctx.drawImage(red, 0, 0, 100, Infinity, Infinity, 0, 100, Infinity);
+ctx.drawImage(red, 0, 0, 100, Infinity, 0, Infinity, 100, 50);
+ctx.drawImage(red, 0, 0, 100, Infinity, 0, Infinity, Infinity, 50);
+ctx.drawImage(red, 0, 0, 100, Infinity, 0, Infinity, Infinity, Infinity);
+ctx.drawImage(red, 0, 0, 100, Infinity, 0, Infinity, 100, Infinity);
+ctx.drawImage(red, 0, 0, 100, Infinity, 0, 0, Infinity, 50);
+ctx.drawImage(red, 0, 0, 100, Infinity, 0, 0, Infinity, Infinity);
+ctx.drawImage(red, 0, 0, 100, Infinity, 0, 0, 100, Infinity);
+ctx.drawImage(red, 0, 0, 100, 50, Infinity, Infinity, 100, 50);
+ctx.drawImage(red, 0, 0, 100, 50, Infinity, Infinity, Infinity, 50);
+ctx.drawImage(red, 0, 0, 100, 50, Infinity, Infinity, Infinity, Infinity);
+ctx.drawImage(red, 0, 0, 100, 50, Infinity, Infinity, 100, Infinity);
+ctx.drawImage(red, 0, 0, 100, 50, Infinity, 0, Infinity, 50);
+ctx.drawImage(red, 0, 0, 100, 50, Infinity, 0, Infinity, Infinity);
+ctx.drawImage(red, 0, 0, 100, 50, Infinity, 0, 100, Infinity);
+ctx.drawImage(red, 0, 0, 100, 50, 0, Infinity, Infinity, 50);
+ctx.drawImage(red, 0, 0, 100, 50, 0, Infinity, Infinity, Infinity);
+ctx.drawImage(red, 0, 0, 100, 50, 0, Infinity, 100, Infinity);
+ctx.drawImage(red, 0, 0, 100, 50, 0, 0, Infinity, Infinity);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+<img src="/images/red.png" id="red.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.nowrap.html b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.nowrap.html
new file mode 100644
index 00000000000..8b0fa4890c7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.nowrap.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.drawImage.nowrap</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.drawImage.nowrap</h1>
+<p class="desc">Stretched images do not get pixels wrapping around the edges</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Stretched images do not get pixels wrapping around the edges");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.drawImage(document.getElementById('redtransparent.png'), -1950, 0, 2000, 50);
+_assertPixelApprox(canvas, 45,25, 0,255,0,255, "45,25", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 55,25, 0,255,0,255, "55,25", "0,255,0,255", 2);
+
+
+});
+</script>
+<img src="/images/redtransparent.png" id="redtransparent.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.null.html b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.null.html
new file mode 100644
index 00000000000..f4ce00e5623
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.null.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.drawImage.null</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.drawImage.null</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+assert_throws(new TypeError(), function() { ctx.drawImage(null, 0, 0); });
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.path.html b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.path.html
new file mode 100644
index 00000000000..2e389ebd476
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.path.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.drawImage.path</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.drawImage.path</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.rect(0, 0, 100, 50);
+ctx.drawImage(document.getElementById('red.png'), 0, 0);
+ctx.fill();
+_assertPixelApprox(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 2);
+
+
+});
+</script>
+<img src="/images/red.png" id="red.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.self.1.html b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.self.1.html
new file mode 100644
index 00000000000..8f05c1445b8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.self.1.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.drawImage.self.1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.drawImage.self.1</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 50, 50);
+ctx.fillStyle = '#f00';
+ctx.fillRect(50, 0, 50, 50);
+ctx.drawImage(canvas, 50, 0);
+
+_assertPixelApprox(canvas, 0,0, 0,255,0,255, "0,0", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 99,0, 0,255,0,255, "99,0", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 0,49, 0,255,0,255, "0,49", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 99,49, 0,255,0,255, "99,49", "0,255,0,255", 2);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.self.2.html b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.self.2.html
new file mode 100644
index 00000000000..4fc1319fc89
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.self.2.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.drawImage.self.2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.drawImage.self.2</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 1, 100, 49);
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 1);
+ctx.drawImage(canvas, 0, 1);
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 2);
+
+_assertPixelApprox(canvas, 0,0, 0,255,0,255, "0,0", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 99,0, 0,255,0,255, "99,0", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 0,49, 0,255,0,255, "0,49", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 99,49, 0,255,0,255, "99,49", "0,255,0,255", 2);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.svg.html b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.svg.html
new file mode 100644
index 00000000000..5935eb8641f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.svg.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.drawImage.svg</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.drawImage.svg</h1>
+<p class="desc">drawImage() of an SVG image</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("drawImage() of an SVG image");
+_addTest(function(canvas, ctx) {
+
+ctx.drawImage(document.getElementById('green.svg'), 0, 0);
+_assertPixelApprox(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 2);
+
+
+});
+</script>
+<img src="/images/green.svg" id="green.svg" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.transform.html b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.transform.html
new file mode 100644
index 00000000000..ab3c09a22bc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.transform.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.drawImage.transform</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.drawImage.transform</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.translate(100, 0);
+ctx.drawImage(document.getElementById('red.png'), 0, 0);
+_assertPixelApprox(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 2);
+
+
+});
+</script>
+<img src="/images/red.png" id="red.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.wrongtype.html b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.wrongtype.html
new file mode 100644
index 00000000000..cd2a7fc5b8e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.wrongtype.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.drawImage.wrongtype</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.drawImage.wrongtype</h1>
+<p class="desc">Incorrect image types in drawImage do not match any defined overloads, so WebIDL throws a TypeError</p>
+
+<p class="notes">Defined in "Web IDL" (draft)
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Incorrect image types in drawImage do not match any defined overloads, so WebIDL throws a TypeError");
+_addTest(function(canvas, ctx) {
+
+assert_throws(new TypeError(), function() { ctx.drawImage(undefined, 0, 0); });
+assert_throws(new TypeError(), function() { ctx.drawImage(0, 0, 0); });
+assert_throws(new TypeError(), function() { ctx.drawImage("", 0, 0); });
+assert_throws(new TypeError(), function() { ctx.drawImage(document.createElement('p'), 0, 0); });
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.zerocanvas.html b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.zerocanvas.html
new file mode 100644
index 00000000000..e14f5d3b361
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.zerocanvas.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.drawImage.zerocanvas</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.drawImage.zerocanvas</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+var canvas2 = document.createElement('canvas');
+canvas2.width = 0;
+canvas2.height = 10;
+assert_throws("INVALID_STATE_ERR", function() { ctx.drawImage(canvas2, 0, 0); });
+
+canvas2.width = 10;
+canvas2.height = 0;
+assert_throws("INVALID_STATE_ERR", function() { ctx.drawImage(canvas2, 0, 0); });
+
+canvas2.width = 0;
+canvas2.height = 0;
+assert_throws("INVALID_STATE_ERR", function() { ctx.drawImage(canvas2, 0, 0); });
+
+_assertPixelApprox(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 2);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.zerosource.html b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.zerosource.html
new file mode 100644
index 00000000000..6906284e00a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.zerosource.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.drawImage.zerosource</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.drawImage.zerosource</h1>
+<p class="desc">drawImage with zero-sized source rectangle throws INDEX_SIZE_ERR</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("drawImage with zero-sized source rectangle throws INDEX_SIZE_ERR");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+assert_throws("INDEX_SIZE_ERR", function() { ctx.drawImage(document.getElementById('red.png'), 10, 10, 0, 1, 0, 0, 100, 50); });
+assert_throws("INDEX_SIZE_ERR", function() { ctx.drawImage(document.getElementById('red.png'), 10, 10, 1, 0, 0, 0, 100, 50); });
+assert_throws("INDEX_SIZE_ERR", function() { ctx.drawImage(document.getElementById('red.png'), 10, 10, 0, 0, 0, 0, 100, 50); });
+_assertPixelApprox(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 2);
+
+
+});
+</script>
+<img src="/images/red.png" id="red.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.zerosource.image.html b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.zerosource.image.html
new file mode 100644
index 00000000000..cda752c31c2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-images-to-the-canvas/2d.drawImage.zerosource.image.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.drawImage.zerosource.image</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.drawImage.zerosource.image</h1>
+<p class="desc">drawImage with zero-sized source rectangle from image throws INDEX_SIZE_ERR</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("drawImage with zero-sized source rectangle from image throws INDEX_SIZE_ERR");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+assert_throws("INDEX_SIZE_ERR", function() { ctx.drawImage(document.getElementById('red-zerowidth.svg'), 0, 0, 100, 50); });
+assert_throws("INDEX_SIZE_ERR", function() { ctx.drawImage(document.getElementById('red-zeroheight.svg'), 0, 0, 100, 50); });
+assert_throws("INDEX_SIZE_ERR", function() { ctx.drawImage(document.getElementById('red-zerosize.svg'), 0, 0, 100, 50); });
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+<img src="/images/red-zerowidth.svg" id="red-zerowidth.svg" class="resource">
+<img src="/images/red-zeroheight.svg" id="red-zeroheight.svg" class="resource">
+<img src="/images/red-zerosize.svg" id="red-zerosize.svg" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-model/.gitkeep b/tests/wpt/web-platform-tests/2dcontext/drawing-model/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-model/.gitkeep
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-paths-to-the-canvas/.gitkeep b/tests/wpt/web-platform-tests/2dcontext/drawing-paths-to-the-canvas/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-paths-to-the-canvas/.gitkeep
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-paths-to-the-canvas/canvas_complexshapes_ispointInpath_001.htm b/tests/wpt/web-platform-tests/2dcontext/drawing-paths-to-the-canvas/canvas_complexshapes_ispointInpath_001.htm
new file mode 100644
index 00000000000..4728f9c428c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-paths-to-the-canvas/canvas_complexshapes_ispointInpath_001.htm
@@ -0,0 +1,32 @@
+<!doctype HTML>
+<html>
+ <head>
+ <title>HTML5 Canvas Test: isPointInPath() unaffected by the current transformation matrix</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com" />
+ <link rel="help" href="http://www.w3.org/TR/2dcontext/#dom-context-2d-ispointinpath" />
+ <meta name="assert" content="isPointInPath must check the point (x, y) as coordinates unaffected by the current transformation matrix." />
+ <script type="text/javascript">
+ function runTest()
+ {
+ var canvas = document.getElementById("canvas1");
+ var ctx = canvas.getContext("2d");
+
+ // Create a path that is transformed by a translation transformation matrix.
+ ctx.translate(100, 50);
+ ctx.rect(0, 0, 100, 50);
+
+ // Ensure that the coordinates passed to isPointInPath are unaffected by the current transformation matrix.
+ if (ctx.isPointInPath(125, 75) && !ctx.isPointInPath(25, 25))
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+ }
+ </script>
+ </head>
+ <body onload="runTest();">
+ <p>Description: isPointInPath must check the point (x, y) as coordinates unaffected by the current transformation matrix.</p>
+ <p>Test passes if the word "PASS" appears below.</p>
+ <div id="testresult">FAIL</div>
+ <canvas id="canvas1" width="300" height="150">Browser does not support HTML5 Canvas.</canvas>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-paths-to-the-canvas/canvas_focus_drawCustomFocusRing_001.html b/tests/wpt/web-platform-tests/2dcontext/drawing-paths-to-the-canvas/canvas_focus_drawCustomFocusRing_001.html
new file mode 100644
index 00000000000..f8442fbb2a3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-paths-to-the-canvas/canvas_focus_drawCustomFocusRing_001.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>canvas drawCustomFocusRing() step1 test</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="stylesheet" href="/resources/testharness.css" media="all">
+ <link rel="author" title="Takeshi Kurosawa" href="mailto:kurosawa-takeshi@mitsue.co.jp">
+ <link rel="help" href="http://www.w3.org/TR/2dcontext/#dom-context-2d-drawcustomfocusring">
+ </head>
+ <body>
+ <h1>Description</h1>
+ <p>This test checks whether drawCustomFocusRing returns false if the element passed as an argument is not focused or is not a descendant of the element with whose context the method is associated.</p>
+ <div id="log"></div>
+ <div>
+ <input type="text" id="text0">
+ <canvas id="canvas"><input type="text" id="text1"></canvas>
+ </div>
+ <script>
+ (function() {
+ test(function() {
+ var canvas = document.getElementById('canvas');
+ var context = canvas.getContext('2d');
+ var text0 = document.getElementById('text0');
+ text0.focus(); // document.activeElement === text0;
+
+ var text1 = document.getElementById('text1');
+ assert_false(context.drawCustomFocusRing(text1));
+ }, 'drawCustomFocusRing must return false for an element that is not focused.');
+
+ test(function() {
+ var canvas = document.getElementById('canvas');
+ var context = canvas.getContext('2d');
+ var text0 = document.getElementById('text0');
+ text0.focus(); // document.activeElement === text0;
+
+ assert_false(context.drawCustomFocusRing(text0));
+ }, 'drawCustomFocusRing must return false for an element that is not a descendant of the canvas element.');
+ })();
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-paths-to-the-canvas/canvas_focus_drawFocusIfNeeded_AAPI_001-manual.html b/tests/wpt/web-platform-tests/2dcontext/drawing-paths-to-the-canvas/canvas_focus_drawFocusIfNeeded_AAPI_001-manual.html
new file mode 100644
index 00000000000..bf38fa68b7d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-paths-to-the-canvas/canvas_focus_drawFocusIfNeeded_AAPI_001-manual.html
@@ -0,0 +1,50 @@
+<html>
+ <head>
+ <meta charset="UTF-8">
+ <title>drawFocusIfNeeded() - AAPI test</title>
+ <link rel="author" title="Mark Sadecki" href="mark@w3.org">
+ <link rel="help" href="http://www.w3.org/TR/2dcontext/#dom-context-2d-drawFocusIfNeeded">
+
+ </head>
+ <body>
+ <h1>Description</h1>
+ <p>This manual test can be used to verify that drawFocusIfNeeded actually updates the accessible location information (i.e. UIAutomation's CurrentBoundingRectangle) in the Accessibility API. To perform this test, you will need an <a href="http://www.w3.org/WAI/PF/wiki/ARIA_Test_Plan#Test_tools">accessibility API inspector</a>. To perform this test, use the <code>tab</code> key to move from the first focusable element to through to the fourth. This test passes if the first parameter of the bounding rectangle increases by 100 when focus is moved from the gray square to the orange square.</p>
+ <p><a href="http://www.w3.org">First focusable element</a></p>
+ <canvas height=100 width=200 id=canvas>
+ <a href='http://www.w3.org' id='button1'>Second focusable element</a>
+ <a href='http://www.w3.org' id='button2'>Third focusable element</a>
+ </canvas>
+ <p><a href="http://www.w3.org">Fourth focusable element</a></p>
+
+ <script>
+ var button1 = document.getElementById('button1');
+ var button2 = document.getElementById('button2');
+ var canvas = document.getElementById('canvas');
+ var buttons = canvas.getElementsByTagName('a');
+
+ for (var i = 0; i < buttons.length; i++) {
+ buttons[i].addEventListener('focus', drawCanvas, false);
+ buttons[i].addEventListener('blur', drawCanvas, false);
+ }
+
+ function drawRect(context, color, element) {
+ context.beginPath();
+ context.rect(10, 10, 80, 80);
+ context.fillStyle = color;
+ context.fill();
+ context.drawFocusIfNeeded(element);
+ }
+
+ function drawCanvas() {
+ var canvas = document.getElementById('canvas');
+ var context = canvas.getContext('2d');
+ context.clearRect (0, 0, 200, 100);
+
+ drawRect(context, "gray", button1);
+ context.translate(100,0);
+ drawRect(context, "orange", button2);
+ }
+ drawCanvas();
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-paths-to-the-canvas/drawFocusIfNeeded_001.html b/tests/wpt/web-platform-tests/2dcontext/drawing-paths-to-the-canvas/drawFocusIfNeeded_001.html
new file mode 100755
index 00000000000..6daf32a2af9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-paths-to-the-canvas/drawFocusIfNeeded_001.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>drawFocusIfNeeded()</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="author" title="W3C">
+ <link rel="help" href="http://www.w3.org/TR/2dcontext/#dom-context-2d-drawFocusIfNeeded">
+ </head>
+ <body>
+ <h1>Description</h1>
+ <p>This test uses drawFocusIfNeeded to draw a focus ring in the canvas, then compare the ImageData before and after the invocation of the method to check that the focus ring was actually drawn.</p>
+ <div>
+ <p>Before:</p>
+ <canvas height=100 width=100 id='original'>
+ </canvas>
+ <p>After:</p>
+ <canvas height=100 width=100 id=canvas>
+ <label><a href='http://www.w3.org' id='element'>Focus</a></label>
+ </canvas>
+ </div>
+ <script>
+ test(function() {
+ var canvas = document.getElementById('canvas');
+ var context = canvas.getContext('2d');
+ var element = document.getElementById('element');
+ element.focus();
+ context.fillStyle = 'white';
+ context.fillRect(0, 0, 100, 100);
+ context.beginPath();
+ context.strokeStyle = 'black';
+ context.rect(10, 10, 80, 80);
+ context.stroke();
+ context.save();
+ var refImage = context.getImageData(0, 0, 100, 100);
+
+ assert_equals(40000, refImage.data.length, "ImageData.data.length is 40000");
+
+ var original = document.getElementById('original');
+ var o_context = original.getContext('2d');
+ o_context.fillStyle = 'white';
+ o_context.fillRect(0, 0, 100, 100);
+ o_context.putImageData(refImage, 0, 0, 0, 0, 100, 100);
+
+ context.rect(5, 5, 90, 90);
+ context.drawFocusIfNeeded(element);
+
+ var ringImage = context.getImageData(0, 0, 100, 100);
+ assert_equals(40000, ringImage.data.length, "ImageData.data.length is 40000");
+
+ // make sure refImage and ringImage are different
+ var length = 40000;
+ var index = length;
+ var identical = true;
+ while (--index > 0) {
+ if (refImage.data[index] != ringImage.data[index]) identical = false;
+ }
+
+ assert_false(identical, "The focus ring must appear in the canvas");
+
+
+ }, 'drawFocusIfNeeded draws a focus ring.');
+ </script>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-paths-to-the-canvas/drawFocusIfNeeded_002.html b/tests/wpt/web-platform-tests/2dcontext/drawing-paths-to-the-canvas/drawFocusIfNeeded_002.html
new file mode 100755
index 00000000000..ec0a4ef427c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-paths-to-the-canvas/drawFocusIfNeeded_002.html
@@ -0,0 +1,68 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>drawFocusIfNeeded()</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="author" title="W3C">
+ <link rel="help" href="http://www.w3.org/TR/2dcontext/#dom-context-2d-drawFocusIfNeeded">
+ </head>
+ <body>
+ <h1>Description</h1>
+ <p>This test uses drawFocusIfNeeded does nothing if the element is not in focus but comparing ImageData from before and after.</p>
+ <div>
+ <p>Before:</p>
+ <canvas height=100 width=100 id='original'>
+ </canvas>
+ <p>After:</p>
+ <canvas height=100 width=100 id=canvas>
+ <label><a href='http://www.w3.org' id='element'>Focus</a></label>
+ </canvas>
+ </div>
+ <script>
+ test(function() {
+ var canvas = document.getElementById('canvas');
+ var context = canvas.getContext('2d');
+ var element = document.getElementById('element');
+ context.fillStyle = 'white';
+ context.fillRect(0, 0, 100, 100);
+ context.beginPath();
+ context.strokeStyle = 'black';
+ context.rect(10, 10, 80, 80);
+ context.stroke();
+ context.save();
+ var refImage = context.getImageData(0, 0, 100, 100);
+
+ assert_equals(40000, refImage.data.length, "ImageData.data.length is 40000");
+
+ var original = document.getElementById('original');
+ var o_context = original.getContext('2d');
+ o_context.fillStyle = 'white';
+ o_context.fillRect(0, 0, 100, 100);
+ o_context.putImageData(refImage, 0, 0, 0, 0, 100, 100);
+
+
+
+ context.strokeStyle = 'blue';
+ context.rect(5, 5, 90, 90);
+ context.drawFocusIfNeeded(element);
+
+ var ringImage = context.getImageData(0, 0, 100, 100);
+ assert_equals(40000, ringImage.data.length, "ImageData.data.length is 40000");
+
+ // make sure refImage and ringImage are different
+ var length = 40000;
+ var index = length;
+ var identical = true;
+ while (--index > 0) {
+ if (refImage.data[index] != ringImage.data[index]) identical = false;
+ }
+
+ assert_true(identical, "No focus ring appears in the canvas");
+
+
+ }, 'drawFocusIfNeeded does not draw a focus ring if the element is not in focus.');
+ </script>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-paths-to-the-canvas/drawFocusIfNeeded_003.html b/tests/wpt/web-platform-tests/2dcontext/drawing-paths-to-the-canvas/drawFocusIfNeeded_003.html
new file mode 100755
index 00000000000..b62c0641f57
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-paths-to-the-canvas/drawFocusIfNeeded_003.html
@@ -0,0 +1,69 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>drawFocusIfNeeded()</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="author" title="W3C">
+ <link rel="help" href="http://www.w3.org/TR/2dcontext/#dom-context-2d-drawFocusIfNeeded">
+ </head>
+ <body>
+ <h1>Description</h1>
+ <p>This test uses drawFocusIfNeeded does nothing if the element is not a descendant but comparing ImageData from before and after.</p>
+ <div>
+ <p>Before:</p>
+ <canvas height=100 width=100 id='original'>
+ <label><a href='http://www.w3.org' id='element'>Focus</a></label>
+ </canvas>
+ <p>After:</p>
+ <canvas height=100 width=100 id=canvas>
+ </canvas>
+ </div>
+ <script>
+ test(function() {
+ var canvas = document.getElementById('canvas');
+ var context = canvas.getContext('2d');
+ var element = document.getElementById('element');
+ element.focus();
+ context.fillStyle = 'white';
+ context.fillRect(0, 0, 100, 100);
+ context.beginPath();
+ context.strokeStyle = 'black';
+ context.rect(10, 10, 80, 80);
+ context.stroke();
+ context.save();
+ var refImage = context.getImageData(0, 0, 100, 100);
+
+ assert_equals(40000, refImage.data.length, "ImageData.data.length is 40000");
+
+ var original = document.getElementById('original');
+ var o_context = original.getContext('2d');
+ o_context.fillStyle = 'white';
+ o_context.fillRect(0, 0, 100, 100);
+ o_context.putImageData(refImage, 0, 0, 0, 0, 100, 100);
+
+
+
+ context.strokeStyle = 'blue';
+ context.rect(5, 5, 90, 90);
+ context.drawFocusIfNeeded(element);
+
+ var ringImage = context.getImageData(0, 0, 100, 100);
+ assert_equals(40000, ringImage.data.length, "ImageData.data.length is 40000");
+
+ // make sure refImage and ringImage are different
+ var length = 40000;
+ var index = length;
+ var identical = true;
+ while (--index > 0) {
+ if (refImage.data[index] != ringImage.data[index]) identical = false;
+ }
+
+ assert_true(identical, "No focus ring appears in the canvas");
+
+
+ }, 'drawFocusIfNeeded does not draw a focus ring if the element is not a descendant of the context.');
+ </script>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-paths-to-the-canvas/drawFocusIfNeeded_004.html b/tests/wpt/web-platform-tests/2dcontext/drawing-paths-to-the-canvas/drawFocusIfNeeded_004.html
new file mode 100755
index 00000000000..326db0daa85
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-paths-to-the-canvas/drawFocusIfNeeded_004.html
@@ -0,0 +1,88 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>drawFocusIfNeeded()</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="author" title="W3C">
+ <link rel="help" href="http://www.w3.org/TR/2dcontext/#dom-context-2d-drawFocusIfNeeded">
+ </head>
+ <body>
+ <h1>Description</h1>
+ <p>This test uses drawFocusIfNeeded to draw a complex path focus then compare ImageData from before and after.</p>
+ <div>
+ <p>Before:</p>
+ <canvas height=100 width=100 id='original'>
+ </canvas>
+ <p>After:</p>
+ <canvas height=100 width=100 id=canvas>
+ <label><a href='http://www.w3.org' id='element'>Focus</a></label>
+ </canvas>
+ </div>
+ <script>
+ test(function() {
+ var canvas = document.getElementById('canvas');
+ var context = canvas.getContext('2d');
+ var element = document.getElementById('element');
+ element.focus();
+ context.fillStyle = 'white';
+ context.fillRect(0, 0, 100, 100);
+ context.beginPath();
+ context.strokeStyle = 'black';
+
+ context.moveTo(10, 40);
+ context.lineTo(50, 10);
+ context.lineTo(90, 40);
+ context.lineTo(70, 40);
+ context.lineTo(70, 90);
+ context.lineTo(30, 90);
+ context.lineTo(30, 40);
+ context.closePath();
+
+ context.stroke();
+ context.save();
+ var refImage = context.getImageData(0, 0, 100, 100);
+
+ assert_equals(40000, refImage.data.length, "ImageData.data.length is 40000");
+
+ var original = document.getElementById('original');
+ var o_context = original.getContext('2d');
+ o_context.fillStyle = 'white';
+ o_context.fillRect(0, 0, 100, 100);
+ o_context.putImageData(refImage, 0, 0, 0, 0, 100, 100);
+
+
+
+ context.beginPath();
+ context.moveTo(5, 40);
+ context.lineTo(50, 5);
+ context.lineTo(95, 40);
+ context.lineTo(95, 45);
+ context.lineTo(75, 45);
+ context.lineTo(75, 95);
+ context.lineTo(25, 95);
+ context.lineTo(25, 45);
+ context.lineTo(5, 45);
+ context.closePath();
+
+ context.drawFocusIfNeeded(element);
+
+ var ringImage = context.getImageData(0, 0, 100, 100);
+ assert_equals(40000, ringImage.data.length, "ImageData.data.length is 40000");
+
+ // make sure refImage and ringImage are different
+ var length = 40000;
+ var index = length;
+ var identical = true;
+ while (--index > 0) {
+ if (refImage.data[index] != ringImage.data[index]) identical = false;
+ }
+
+ assert_false(identical, "A focus ring appears in the canvas");
+
+
+ }, 'drawFocusIfNeeded does draw a focus ring if the element is in focus.');
+ </script>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-paths-to-the-canvas/drawFocusIfNeeded_005.html b/tests/wpt/web-platform-tests/2dcontext/drawing-paths-to-the-canvas/drawFocusIfNeeded_005.html
new file mode 100755
index 00000000000..96a4e3fd5d9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-paths-to-the-canvas/drawFocusIfNeeded_005.html
@@ -0,0 +1,88 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>drawFocusIfNeeded()</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="author" title="W3C">
+ <link rel="help" href="http://www.w3.org/TR/2dcontext/#dom-context-2d-drawFocusIfNeeded">
+ </head>
+ <body>
+ <h1>Description</h1>
+ <p>This test uses drawFocusIfNeeded to draw a complex path focus then compare ImageData from before and after.</p>
+ <div>
+ <p>Before:</p>
+ <canvas height=100 width=100 id='original'>
+ </canvas>
+ <p>After:</p>
+ <canvas height=100 width=100 id=canvas>
+ <p id='element' tabindex='1'>This is text.</p>
+ </canvas>
+ </div>
+ <script>
+ test(function() {
+ var canvas = document.getElementById('canvas');
+ var context = canvas.getContext('2d');
+ var element = document.getElementById('element');
+ element.focus();
+ context.fillStyle = 'white';
+ context.fillRect(0, 0, 100, 100);
+ context.beginPath();
+ context.strokeStyle = 'black';
+
+ context.moveTo(10, 40);
+ context.lineTo(50, 10);
+ context.lineTo(90, 40);
+ context.lineTo(70, 40);
+ context.lineTo(70, 90);
+ context.lineTo(30, 90);
+ context.lineTo(30, 40);
+ context.closePath();
+
+ context.stroke();
+ context.save();
+ var refImage = context.getImageData(0, 0, 100, 100);
+
+ assert_equals(40000, refImage.data.length, "ImageData.data.length is 40000");
+
+ var original = document.getElementById('original');
+ var o_context = original.getContext('2d');
+ o_context.fillStyle = 'white';
+ o_context.fillRect(0, 0, 100, 100);
+ o_context.putImageData(refImage, 0, 0, 0, 0, 100, 100);
+
+
+
+ context.beginPath();
+ context.moveTo(5, 40);
+ context.lineTo(50, 5);
+ context.lineTo(95, 40);
+ context.lineTo(95, 45);
+ context.lineTo(75, 45);
+ context.lineTo(75, 95);
+ context.lineTo(25, 95);
+ context.lineTo(25, 45);
+ context.lineTo(5, 45);
+ context.closePath();
+
+ context.drawFocusIfNeeded(element);
+
+ var ringImage = context.getImageData(0, 0, 100, 100);
+ assert_equals(40000, ringImage.data.length, "ImageData.data.length is 40000");
+
+ // make sure refImage and ringImage are different
+ var length = 40000;
+ var index = length;
+ var identical = true;
+ while (--index > 0) {
+ if (refImage.data[index] != ringImage.data[index]) identical = false;
+ }
+
+ assert_false(identical, "A focus ring appears in the canvas");
+
+
+ }, 'drawFocusIfNeeded does draw a focus ring if the element is in focus and the user activated a particular focus ring.');
+ </script>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/.gitkeep b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/.gitkeep
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.clearRect.basic.html b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.clearRect.basic.html
new file mode 100644
index 00000000000..9ec16ed5b6d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.clearRect.basic.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.clearRect.basic</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.clearRect.basic</h1>
+<p class="desc">clearRect clears to transparent black</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/clear-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("clearRect clears to transparent black");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.clearRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,0,0,0, "50,25", "0,0,0,0");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.clearRect.clip.html b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.clearRect.clip.html
new file mode 100644
index 00000000000..bd35e7f0ceb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.clearRect.clip.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.clearRect.clip</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.clearRect.clip</h1>
+<p class="desc">clearRect is affected by clipping regions</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("clearRect is affected by clipping regions");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.beginPath();
+ctx.rect(0, 0, 16, 16);
+ctx.clip();
+
+ctx.clearRect(0, 0, 100, 50);
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 16, 16);
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.clearRect.globalalpha.html b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.clearRect.globalalpha.html
new file mode 100644
index 00000000000..34c64aec9ef
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.clearRect.globalalpha.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.clearRect.globalalpha</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.clearRect.globalalpha</h1>
+<p class="desc">clearRect is not affected by globalAlpha</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/clear-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("clearRect is not affected by globalAlpha");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalAlpha = 0.1;
+ctx.clearRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,0,0,0, "50,25", "0,0,0,0");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.clearRect.globalcomposite.html b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.clearRect.globalcomposite.html
new file mode 100644
index 00000000000..96830e1ea75
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.clearRect.globalcomposite.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.clearRect.globalcomposite</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.clearRect.globalcomposite</h1>
+<p class="desc">clearRect is not affected by globalCompositeOperation</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/clear-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("clearRect is not affected by globalCompositeOperation");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'destination-atop';
+ctx.clearRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,0,0,0, "50,25", "0,0,0,0");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.clearRect.negative.html b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.clearRect.negative.html
new file mode 100644
index 00000000000..2d1a0cb05a0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.clearRect.negative.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.clearRect.negative</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.clearRect.negative</h1>
+<p class="desc">clearRect of negative sizes works</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/clear-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("clearRect of negative sizes works");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.clearRect(0, 0, 50, 25);
+ctx.clearRect(100, 0, -50, 25);
+ctx.clearRect(0, 50, 50, -25);
+ctx.clearRect(100, 50, -50, -25);
+_assertPixel(canvas, 25,12, 0,0,0,0, "25,12", "0,0,0,0");
+_assertPixel(canvas, 75,12, 0,0,0,0, "75,12", "0,0,0,0");
+_assertPixel(canvas, 25,37, 0,0,0,0, "25,37", "0,0,0,0");
+_assertPixel(canvas, 75,37, 0,0,0,0, "75,37", "0,0,0,0");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.clearRect.nonfinite.html b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.clearRect.nonfinite.html
new file mode 100644
index 00000000000..35a3d79c1c0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.clearRect.nonfinite.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.clearRect.nonfinite</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.clearRect.nonfinite</h1>
+<p class="desc">clearRect() with Infinity/NaN is ignored</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("clearRect() with Infinity/NaN is ignored");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.clearRect(Infinity, 0, 100, 50);
+ctx.clearRect(-Infinity, 0, 100, 50);
+ctx.clearRect(NaN, 0, 100, 50);
+ctx.clearRect(0, Infinity, 100, 50);
+ctx.clearRect(0, -Infinity, 100, 50);
+ctx.clearRect(0, NaN, 100, 50);
+ctx.clearRect(0, 0, Infinity, 50);
+ctx.clearRect(0, 0, -Infinity, 50);
+ctx.clearRect(0, 0, NaN, 50);
+ctx.clearRect(0, 0, 100, Infinity);
+ctx.clearRect(0, 0, 100, -Infinity);
+ctx.clearRect(0, 0, 100, NaN);
+ctx.clearRect(Infinity, Infinity, 100, 50);
+ctx.clearRect(Infinity, Infinity, Infinity, 50);
+ctx.clearRect(Infinity, Infinity, Infinity, Infinity);
+ctx.clearRect(Infinity, Infinity, 100, Infinity);
+ctx.clearRect(Infinity, 0, Infinity, 50);
+ctx.clearRect(Infinity, 0, Infinity, Infinity);
+ctx.clearRect(Infinity, 0, 100, Infinity);
+ctx.clearRect(0, Infinity, Infinity, 50);
+ctx.clearRect(0, Infinity, Infinity, Infinity);
+ctx.clearRect(0, Infinity, 100, Infinity);
+ctx.clearRect(0, 0, Infinity, Infinity);
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.clearRect.path.html b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.clearRect.path.html
new file mode 100644
index 00000000000..c5429c8c2e4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.clearRect.path.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.clearRect.path</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.clearRect.path</h1>
+<p class="desc">clearRect does not affect the current path</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("clearRect does not affect the current path");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.beginPath();
+ctx.rect(0, 0, 100, 50);
+ctx.clearRect(0, 0, 16, 16);
+ctx.fill();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.clearRect.shadow.html b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.clearRect.shadow.html
new file mode 100644
index 00000000000..384baf9c7a5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.clearRect.shadow.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.clearRect.shadow</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.clearRect.shadow</h1>
+<p class="desc">clearRect does not draw shadows</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("clearRect does not draw shadows");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.shadowColor = '#f00';
+ctx.shadowBlur = 0;
+ctx.shadowOffsetX = 0;
+ctx.shadowOffsetY = 50;
+ctx.clearRect(0, -50, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.clearRect.transform.html b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.clearRect.transform.html
new file mode 100644
index 00000000000..8ff20443c81
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.clearRect.transform.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.clearRect.transform</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.clearRect.transform</h1>
+<p class="desc">clearRect is affected by transforms</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/clear-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("clearRect is affected by transforms");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.scale(10, 10);
+ctx.translate(0, 5);
+ctx.clearRect(0, -5, 10, 5);
+_assertPixel(canvas, 50,25, 0,0,0,0, "50,25", "0,0,0,0");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.clearRect.zero.html b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.clearRect.zero.html
new file mode 100644
index 00000000000..73805edd6a0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.clearRect.zero.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.clearRect.zero</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.clearRect.zero</h1>
+<p class="desc">clearRect of zero pixels has no effect</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("clearRect of zero pixels has no effect");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.clearRect(0, 0, 100, 0);
+ctx.clearRect(0, 0, 0, 50);
+ctx.clearRect(0, 0, 0, 0);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.fillRect.basic.html b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.fillRect.basic.html
new file mode 100644
index 00000000000..455c4b5b224
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.fillRect.basic.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillRect.basic</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillRect.basic</h1>
+<p class="desc">fillRect works</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("fillRect works");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.fillRect.clip.html b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.fillRect.clip.html
new file mode 100644
index 00000000000..efd2d8cbbe4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.fillRect.clip.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillRect.clip</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillRect.clip</h1>
+<p class="desc">fillRect is affected by clipping regions</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("fillRect is affected by clipping regions");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.beginPath();
+ctx.rect(0, 0, 16, 16);
+ctx.clip();
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 16, 16);
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.fillRect.negative.html b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.fillRect.negative.html
new file mode 100644
index 00000000000..6e942753937
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.fillRect.negative.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillRect.negative</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillRect.negative</h1>
+<p class="desc">fillRect of negative sizes works</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("fillRect of negative sizes works");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 50, 25);
+ctx.fillRect(100, 0, -50, 25);
+ctx.fillRect(0, 50, 50, -25);
+ctx.fillRect(100, 50, -50, -25);
+_assertPixel(canvas, 25,12, 0,255,0,255, "25,12", "0,255,0,255");
+_assertPixel(canvas, 75,12, 0,255,0,255, "75,12", "0,255,0,255");
+_assertPixel(canvas, 25,37, 0,255,0,255, "25,37", "0,255,0,255");
+_assertPixel(canvas, 75,37, 0,255,0,255, "75,37", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.fillRect.nonfinite.html b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.fillRect.nonfinite.html
new file mode 100644
index 00000000000..92bb8fbc057
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.fillRect.nonfinite.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillRect.nonfinite</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillRect.nonfinite</h1>
+<p class="desc">fillRect() with Infinity/NaN is ignored</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("fillRect() with Infinity/NaN is ignored");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(Infinity, 0, 100, 50);
+ctx.fillRect(-Infinity, 0, 100, 50);
+ctx.fillRect(NaN, 0, 100, 50);
+ctx.fillRect(0, Infinity, 100, 50);
+ctx.fillRect(0, -Infinity, 100, 50);
+ctx.fillRect(0, NaN, 100, 50);
+ctx.fillRect(0, 0, Infinity, 50);
+ctx.fillRect(0, 0, -Infinity, 50);
+ctx.fillRect(0, 0, NaN, 50);
+ctx.fillRect(0, 0, 100, Infinity);
+ctx.fillRect(0, 0, 100, -Infinity);
+ctx.fillRect(0, 0, 100, NaN);
+ctx.fillRect(Infinity, Infinity, 100, 50);
+ctx.fillRect(Infinity, Infinity, Infinity, 50);
+ctx.fillRect(Infinity, Infinity, Infinity, Infinity);
+ctx.fillRect(Infinity, Infinity, 100, Infinity);
+ctx.fillRect(Infinity, 0, Infinity, 50);
+ctx.fillRect(Infinity, 0, Infinity, Infinity);
+ctx.fillRect(Infinity, 0, 100, Infinity);
+ctx.fillRect(0, Infinity, Infinity, 50);
+ctx.fillRect(0, Infinity, Infinity, Infinity);
+ctx.fillRect(0, Infinity, 100, Infinity);
+ctx.fillRect(0, 0, Infinity, Infinity);
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.fillRect.path.html b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.fillRect.path.html
new file mode 100644
index 00000000000..b018cba4419
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.fillRect.path.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillRect.path</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillRect.path</h1>
+<p class="desc">fillRect does not affect the current path</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("fillRect does not affect the current path");
+_addTest(function(canvas, ctx) {
+
+ctx.beginPath();
+ctx.rect(0, 0, 100, 50);
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 16, 16);
+ctx.fillStyle = '#0f0';
+ctx.fill();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.fillRect.shadow.html b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.fillRect.shadow.html
new file mode 100644
index 00000000000..be8de26c406
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.fillRect.shadow.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillRect.shadow</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillRect.shadow</h1>
+<p class="desc">fillRect draws shadows</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("fillRect draws shadows");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.shadowColor = '#0f0';
+ctx.shadowBlur = 0;
+ctx.shadowOffsetX = 0;
+ctx.shadowOffsetY = 50;
+ctx.fillRect(0, -50, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.fillRect.transform.html b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.fillRect.transform.html
new file mode 100644
index 00000000000..711b6020141
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.fillRect.transform.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillRect.transform</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillRect.transform</h1>
+<p class="desc">fillRect is affected by transforms</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("fillRect is affected by transforms");
+_addTest(function(canvas, ctx) {
+
+ctx.scale(10, 10);
+ctx.translate(0, 5);
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, -5, 10, 5);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.fillRect.zero.html b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.fillRect.zero.html
new file mode 100644
index 00000000000..c6ea3ae0299
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.fillRect.zero.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillRect.zero</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillRect.zero</h1>
+<p class="desc">fillRect of zero pixels has no effect</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("fillRect of zero pixels has no effect");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 0);
+ctx.fillRect(0, 0, 0, 50);
+ctx.fillRect(0, 0, 0, 0);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.basic.html b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.basic.html
new file mode 100644
index 00000000000..5a3af8b4c57
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.basic.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.strokeRect.basic</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.strokeRect.basic</h1>
+<p class="desc">strokeRect works</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("strokeRect works");
+_addTest(function(canvas, ctx) {
+
+ctx.strokeStyle = '#0f0';
+ctx.lineWidth = 50;
+ctx.strokeRect(25, 24, 50, 2);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.clip.html b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.clip.html
new file mode 100644
index 00000000000..6ccb7da4449
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.clip.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.strokeRect.clip</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.strokeRect.clip</h1>
+<p class="desc">strokeRect is affected by clipping regions</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("strokeRect is affected by clipping regions");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.beginPath();
+ctx.rect(0, 0, 16, 16);
+ctx.clip();
+
+ctx.strokeStyle = '#f00';
+ctx.lineWidth = 50;
+ctx.strokeRect(0, 0, 100, 50);
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 16, 16);
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.globalalpha.html b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.globalalpha.html
new file mode 100644
index 00000000000..3e4cf0769b2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.globalalpha.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.strokeRect.globalalpha</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.strokeRect.globalalpha</h1>
+<p class="desc">strokeRect is affected by globalAlpha</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/clear-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("strokeRect is affected by globalAlpha");
+_addTest(function(canvas, ctx) {
+
+ctx.globalAlpha = 0;
+ctx.strokeStyle = '#f00';
+ctx.lineWidth = 50;
+ctx.strokeRect(25, 24, 50, 2);
+_assertPixel(canvas, 50,25, 0,0,0,0, "50,25", "0,0,0,0");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.globalcomposite.html b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.globalcomposite.html
new file mode 100644
index 00000000000..5239a03d45e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.globalcomposite.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.strokeRect.globalcomposite</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.strokeRect.globalcomposite</h1>
+<p class="desc">strokeRect is not affected by globalCompositeOperation</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/clear-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("strokeRect is not affected by globalCompositeOperation");
+_addTest(function(canvas, ctx) {
+
+ctx.globalCompositeOperation = 'source-in';
+ctx.strokeStyle = '#f00';
+ctx.lineWidth = 50;
+ctx.strokeRect(25, 24, 50, 2);
+_assertPixel(canvas, 50,25, 0,0,0,0, "50,25", "0,0,0,0");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.negative.html b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.negative.html
new file mode 100644
index 00000000000..1973d66253f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.negative.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.strokeRect.negative</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.strokeRect.negative</h1>
+<p class="desc">strokeRect of negative sizes works</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("strokeRect of negative sizes works");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.strokeStyle = '#0f0';
+ctx.lineWidth = 25;
+ctx.strokeRect(12, 12, 26, 1);
+ctx.strokeRect(88, 12, -26, 1);
+ctx.strokeRect(12, 38, 26, -1);
+ctx.strokeRect(88, 38, -26, -1);
+_assertPixel(canvas, 25,12, 0,255,0,255, "25,12", "0,255,0,255");
+_assertPixel(canvas, 75,12, 0,255,0,255, "75,12", "0,255,0,255");
+_assertPixel(canvas, 25,37, 0,255,0,255, "25,37", "0,255,0,255");
+_assertPixel(canvas, 75,37, 0,255,0,255, "75,37", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.nonfinite.html b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.nonfinite.html
new file mode 100644
index 00000000000..ed4c3edce54
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.nonfinite.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.strokeRect.nonfinite</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.strokeRect.nonfinite</h1>
+<p class="desc">strokeRect() with Infinity/NaN is ignored</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("strokeRect() with Infinity/NaN is ignored");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.strokeStyle = '#f00';
+ctx.lineWidth = 150;
+ctx.strokeRect(Infinity, 0, 100, 50);
+ctx.strokeRect(-Infinity, 0, 100, 50);
+ctx.strokeRect(NaN, 0, 100, 50);
+ctx.strokeRect(0, Infinity, 100, 50);
+ctx.strokeRect(0, -Infinity, 100, 50);
+ctx.strokeRect(0, NaN, 100, 50);
+ctx.strokeRect(0, 0, Infinity, 50);
+ctx.strokeRect(0, 0, -Infinity, 50);
+ctx.strokeRect(0, 0, NaN, 50);
+ctx.strokeRect(0, 0, 100, Infinity);
+ctx.strokeRect(0, 0, 100, -Infinity);
+ctx.strokeRect(0, 0, 100, NaN);
+ctx.strokeRect(Infinity, Infinity, 100, 50);
+ctx.strokeRect(Infinity, Infinity, Infinity, 50);
+ctx.strokeRect(Infinity, Infinity, Infinity, Infinity);
+ctx.strokeRect(Infinity, Infinity, 100, Infinity);
+ctx.strokeRect(Infinity, 0, Infinity, 50);
+ctx.strokeRect(Infinity, 0, Infinity, Infinity);
+ctx.strokeRect(Infinity, 0, 100, Infinity);
+ctx.strokeRect(0, Infinity, Infinity, 50);
+ctx.strokeRect(0, Infinity, Infinity, Infinity);
+ctx.strokeRect(0, Infinity, 100, Infinity);
+ctx.strokeRect(0, 0, Infinity, Infinity);
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.path.html b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.path.html
new file mode 100644
index 00000000000..81e7d436254
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.path.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.strokeRect.path</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.strokeRect.path</h1>
+<p class="desc">strokeRect does not affect the current path</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("strokeRect does not affect the current path");
+_addTest(function(canvas, ctx) {
+
+ctx.beginPath();
+ctx.rect(0, 0, 100, 50);
+ctx.strokeStyle = '#f00';
+ctx.lineWidth = 5;
+ctx.strokeRect(0, 0, 16, 16);
+ctx.fillStyle = '#0f0';
+ctx.fill();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.shadow.html b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.shadow.html
new file mode 100644
index 00000000000..26aaa0f5d2e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.shadow.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.strokeRect.shadow</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.strokeRect.shadow</h1>
+<p class="desc">strokeRect draws shadows</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("strokeRect draws shadows");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.fillStyle = '#f00';
+ctx.shadowColor = '#0f0';
+ctx.shadowBlur = 0;
+ctx.shadowOffsetX = 0;
+ctx.shadowOffsetY = 50;
+ctx.strokeStyle = '#f00';
+ctx.lineWidth = 50;
+ctx.strokeRect(0, -75, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.transform.html b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.transform.html
new file mode 100644
index 00000000000..c9a4a76d907
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.transform.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.strokeRect.transform</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.strokeRect.transform</h1>
+<p class="desc">fillRect is affected by transforms</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("fillRect is affected by transforms");
+_addTest(function(canvas, ctx) {
+
+ctx.scale(10, 10);
+ctx.translate(0, 5);
+ctx.strokeStyle = '#0f0';
+ctx.lineWidth = 5;
+ctx.strokeRect(2.5, -2.6, 5, 0.2);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.zero.1.html b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.zero.1.html
new file mode 100644
index 00000000000..915c1252fce
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.zero.1.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.strokeRect.zero.1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.strokeRect.zero.1</h1>
+<p class="desc">strokeRect of 0x0 pixels draws nothing</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/clear-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("strokeRect of 0x0 pixels draws nothing");
+_addTest(function(canvas, ctx) {
+
+ctx.strokeStyle = '#f00';
+ctx.lineWidth = 250;
+ctx.strokeRect(50, 25, 0, 0);
+_assertPixel(canvas, 50,25, 0,0,0,0, "50,25", "0,0,0,0");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.zero.2.html b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.zero.2.html
new file mode 100644
index 00000000000..bec7bdd123a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.zero.2.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.strokeRect.zero.2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.strokeRect.zero.2</h1>
+<p class="desc">strokeRect of 0x0 pixels draws nothing, including caps and joins</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/clear-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("strokeRect of 0x0 pixels draws nothing, including caps and joins");
+_addTest(function(canvas, ctx) {
+
+ctx.strokeStyle = '#f00';
+ctx.lineWidth = 250;
+ctx.lineCap = 'round';
+ctx.lineJoin = 'round';
+ctx.strokeRect(50, 25, 0, 0);
+_assertPixel(canvas, 50,25, 0,0,0,0, "50,25", "0,0,0,0");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.zero.3.html b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.zero.3.html
new file mode 100644
index 00000000000..44232f5fde1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.zero.3.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.strokeRect.zero.3</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.strokeRect.zero.3</h1>
+<p class="desc">strokeRect of Nx0 pixels draws a straight line</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("strokeRect of Nx0 pixels draws a straight line");
+_addTest(function(canvas, ctx) {
+
+ctx.strokeStyle = '#0f0';
+ctx.lineWidth = 50;
+ctx.strokeRect(0, 25, 100, 0);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.zero.4.html b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.zero.4.html
new file mode 100644
index 00000000000..3d594147843
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.zero.4.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.strokeRect.zero.4</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.strokeRect.zero.4</h1>
+<p class="desc">strokeRect of Nx0 pixels draws a closed line with no caps</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/clear-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("strokeRect of Nx0 pixels draws a closed line with no caps");
+_addTest(function(canvas, ctx) {
+
+ctx.strokeStyle = '#f00';
+ctx.lineWidth = 250;
+ctx.lineCap = 'round';
+ctx.strokeRect(100, 25, 100, 0);
+_assertPixel(canvas, 50,25, 0,0,0,0, "50,25", "0,0,0,0");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.zero.5.html b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.zero.5.html
new file mode 100644
index 00000000000..3e8c7d4bf23
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/2d.strokeRect.zero.5.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.strokeRect.zero.5</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.strokeRect.zero.5</h1>
+<p class="desc">strokeRect of Nx0 pixels draws a closed line with joins</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("strokeRect of Nx0 pixels draws a closed line with joins");
+_addTest(function(canvas, ctx) {
+
+ctx.strokeStyle = '#0f0';
+ctx.lineWidth = 250;
+ctx.lineJoin = 'round';
+ctx.strokeRect(100, 25, 100, 0);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/clear-100x50.png b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/clear-100x50.png
new file mode 100644
index 00000000000..eeedd0ff058
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-rectangles-to-the-canvas/clear-100x50.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/.gitkeep b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/.gitkeep
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.align.center.html b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.align.center.html
new file mode 100644
index 00000000000..bcbdbd66594
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.align.center.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.text.draw.align.center</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<style>
+@font-face {
+ font-family: CanvasTest;
+ src: url("/fonts/CanvasTest.ttf");
+}
+</style>
+<body class="show_output">
+
+<h1>2d.text.draw.align.center</h1>
+<p class="desc">textAlign center is the center of the em squares (not the bounding box)</p>
+
+
+<span style="font-family: CanvasTest; position: absolute; visibility: hidden">A</span>
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("textAlign center is the center of the em squares (not the bounding box)");
+_addTest(function(canvas, ctx) {
+
+ctx.font = '50px CanvasTest';
+deferTest();
+setTimeout(t.step_func_done(function () {
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.textAlign = 'center';
+ ctx.fillText('DD', 50, 37.5);
+ _assertPixelApprox(canvas, 5,5, 0,255,0,255, "5,5", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 95,5, 0,255,0,255, "95,5", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 5,45, 0,255,0,255, "5,45", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 95,45, 0,255,0,255, "95,45", "0,255,0,255", 2);
+}), 500);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.align.end.ltr.html b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.align.end.ltr.html
new file mode 100644
index 00000000000..681085859c6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.align.end.ltr.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.text.draw.align.end.ltr</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<style>
+@font-face {
+ font-family: CanvasTest;
+ src: url("/fonts/CanvasTest.ttf");
+}
+</style>
+<body class="show_output">
+
+<h1>2d.text.draw.align.end.ltr</h1>
+<p class="desc">textAlign end with ltr is the right edge</p>
+
+
+<span style="font-family: CanvasTest; position: absolute; visibility: hidden">A</span>
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50" dir="ltr"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("textAlign end with ltr is the right edge");
+_addTest(function(canvas, ctx) {
+
+ctx.font = '50px CanvasTest';
+deferTest();
+setTimeout(t.step_func_done(function () {
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.textAlign = 'end';
+ ctx.fillText('DD', 100, 37.5);
+ _assertPixelApprox(canvas, 5,5, 0,255,0,255, "5,5", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 95,5, 0,255,0,255, "95,5", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 5,45, 0,255,0,255, "5,45", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 95,45, 0,255,0,255, "95,45", "0,255,0,255", 2);
+}), 500);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.align.end.rtl.html b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.align.end.rtl.html
new file mode 100644
index 00000000000..1ccd2bccb85
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.align.end.rtl.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.text.draw.align.end.rtl</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<style>
+@font-face {
+ font-family: CanvasTest;
+ src: url("/fonts/CanvasTest.ttf");
+}
+</style>
+<body class="show_output">
+
+<h1>2d.text.draw.align.end.rtl</h1>
+<p class="desc">textAlign end with rtl is the left edge</p>
+
+
+<span style="font-family: CanvasTest; position: absolute; visibility: hidden">A</span>
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50" dir="rtl"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("textAlign end with rtl is the left edge");
+_addTest(function(canvas, ctx) {
+
+ctx.font = '50px CanvasTest';
+deferTest();
+setTimeout(t.step_func_done(function () {
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.textAlign = 'end';
+ ctx.fillText('DD', 0, 37.5);
+ _assertPixelApprox(canvas, 5,5, 0,255,0,255, "5,5", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 95,5, 0,255,0,255, "95,5", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 5,45, 0,255,0,255, "5,45", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 95,45, 0,255,0,255, "95,45", "0,255,0,255", 2);
+}), 500);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.align.left.html b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.align.left.html
new file mode 100644
index 00000000000..5e7418e36be
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.align.left.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.text.draw.align.left</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<style>
+@font-face {
+ font-family: CanvasTest;
+ src: url("/fonts/CanvasTest.ttf");
+}
+</style>
+<body class="show_output">
+
+<h1>2d.text.draw.align.left</h1>
+<p class="desc">textAlign left is the left of the first em square (not the bounding box)</p>
+
+
+<span style="font-family: CanvasTest; position: absolute; visibility: hidden">A</span>
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("textAlign left is the left of the first em square (not the bounding box)");
+_addTest(function(canvas, ctx) {
+
+ctx.font = '50px CanvasTest';
+deferTest();
+setTimeout(t.step_func_done(function () {
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.textAlign = 'left';
+ ctx.fillText('DD', 0, 37.5);
+ _assertPixelApprox(canvas, 5,5, 0,255,0,255, "5,5", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 95,5, 0,255,0,255, "95,5", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 5,45, 0,255,0,255, "5,45", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 95,45, 0,255,0,255, "95,45", "0,255,0,255", 2);
+}), 500);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.align.right.html b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.align.right.html
new file mode 100644
index 00000000000..81e3acf36ec
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.align.right.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.text.draw.align.right</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<style>
+@font-face {
+ font-family: CanvasTest;
+ src: url("/fonts/CanvasTest.ttf");
+}
+</style>
+<body class="show_output">
+
+<h1>2d.text.draw.align.right</h1>
+<p class="desc">textAlign right is the right of the last em square (not the bounding box)</p>
+
+
+<span style="font-family: CanvasTest; position: absolute; visibility: hidden">A</span>
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("textAlign right is the right of the last em square (not the bounding box)");
+_addTest(function(canvas, ctx) {
+
+ctx.font = '50px CanvasTest';
+deferTest();
+setTimeout(t.step_func_done(function () {
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.textAlign = 'right';
+ ctx.fillText('DD', 100, 37.5);
+ _assertPixelApprox(canvas, 5,5, 0,255,0,255, "5,5", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 95,5, 0,255,0,255, "95,5", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 5,45, 0,255,0,255, "5,45", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 95,45, 0,255,0,255, "95,45", "0,255,0,255", 2);
+}), 500);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.align.start.ltr.html b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.align.start.ltr.html
new file mode 100644
index 00000000000..f47ef78a7cc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.align.start.ltr.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.text.draw.align.start.ltr</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<style>
+@font-face {
+ font-family: CanvasTest;
+ src: url("/fonts/CanvasTest.ttf");
+}
+</style>
+<body class="show_output">
+
+<h1>2d.text.draw.align.start.ltr</h1>
+<p class="desc">textAlign start with ltr is the left edge</p>
+
+
+<span style="font-family: CanvasTest; position: absolute; visibility: hidden">A</span>
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50" dir="ltr"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("textAlign start with ltr is the left edge");
+_addTest(function(canvas, ctx) {
+
+ctx.font = '50px CanvasTest';
+deferTest();
+setTimeout(t.step_func_done(function () {
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.textAlign = 'start';
+ ctx.fillText('DD', 0, 37.5);
+ _assertPixelApprox(canvas, 5,5, 0,255,0,255, "5,5", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 95,5, 0,255,0,255, "95,5", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 5,45, 0,255,0,255, "5,45", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 95,45, 0,255,0,255, "95,45", "0,255,0,255", 2);
+}), 500);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.align.start.rtl.html b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.align.start.rtl.html
new file mode 100644
index 00000000000..cc09b9e4d1a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.align.start.rtl.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.text.draw.align.start.rtl</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<style>
+@font-face {
+ font-family: CanvasTest;
+ src: url("/fonts/CanvasTest.ttf");
+}
+</style>
+<body class="show_output">
+
+<h1>2d.text.draw.align.start.rtl</h1>
+<p class="desc">textAlign start with rtl is the right edge</p>
+
+
+<span style="font-family: CanvasTest; position: absolute; visibility: hidden">A</span>
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50" dir="rtl"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("textAlign start with rtl is the right edge");
+_addTest(function(canvas, ctx) {
+
+ctx.font = '50px CanvasTest';
+deferTest();
+setTimeout(t.step_func_done(function () {
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.textAlign = 'start';
+ ctx.fillText('DD', 100, 37.5);
+ _assertPixelApprox(canvas, 5,5, 0,255,0,255, "5,5", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 95,5, 0,255,0,255, "95,5", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 5,45, 0,255,0,255, "5,45", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 95,45, 0,255,0,255, "95,45", "0,255,0,255", 2);
+}), 500);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.baseline.alphabetic.html b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.baseline.alphabetic.html
new file mode 100644
index 00000000000..bdb65ab9063
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.baseline.alphabetic.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.text.draw.baseline.alphabetic</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<style>
+@font-face {
+ font-family: CanvasTest;
+ src: url("/fonts/CanvasTest.ttf");
+}
+</style>
+<body class="show_output">
+
+<h1>2d.text.draw.baseline.alphabetic</h1>
+<p class="desc"></p>
+
+
+<span style="font-family: CanvasTest; position: absolute; visibility: hidden">A</span>
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.font = '50px CanvasTest';
+deferTest();
+setTimeout(t.step_func_done(function () {
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.textBaseline = 'alphabetic';
+ ctx.fillText('CC', 0, 37.5);
+ _assertPixelApprox(canvas, 5,5, 0,255,0,255, "5,5", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 95,5, 0,255,0,255, "95,5", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 5,45, 0,255,0,255, "5,45", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 95,45, 0,255,0,255, "95,45", "0,255,0,255", 2);
+}), 500);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fill.basic-manual.html b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fill.basic-manual.html
new file mode 100644
index 00000000000..5a4be6d3714
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fill.basic-manual.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.text.draw.fill.basic</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.text.draw.fill.basic</h1>
+<p class="desc">fillText draws filled text</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.text.draw.fill.basic.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("fillText draws filled text");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#000';
+ctx.fillRect(0, 0, 100, 50);
+ctx.fillStyle = '#0f0';
+ctx.strokeStyle = '#f00';
+ctx.font = '35px Arial, sans-serif';
+ctx.fillText('PASS', 5, 35);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fill.basic.png b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fill.basic.png
new file mode 100644
index 00000000000..deaef2c95c1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fill.basic.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fill.maxWidth.bound.html b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fill.maxWidth.bound.html
new file mode 100644
index 00000000000..3282f273e06
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fill.maxWidth.bound.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.text.draw.fill.maxWidth.bound</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<style>
+@font-face {
+ font-family: CanvasTest;
+ src: url("/fonts/CanvasTest.ttf");
+}
+</style>
+<body class="show_output">
+
+<h1>2d.text.draw.fill.maxWidth.bound</h1>
+<p class="desc">fillText handles maxWidth based on line size, not bounding box size</p>
+
+
+<span style="font-family: CanvasTest; position: absolute; visibility: hidden">A</span>
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("fillText handles maxWidth based on line size, not bounding box size");
+_addTest(function(canvas, ctx) {
+
+ctx.font = '50px CanvasTest';
+deferTest();
+setTimeout(t.step_func_done(function () {
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.fillText('DD', 0, 37.5, 100);
+ _assertPixelApprox(canvas, 5,5, 0,255,0,255, "5,5", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 95,5, 0,255,0,255, "95,5", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255", 2);
+}), 500);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fill.maxWidth.fontface.html b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fill.maxWidth.fontface.html
new file mode 100644
index 00000000000..d138047f6c4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fill.maxWidth.fontface.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.text.draw.fill.maxWidth.fontface</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<style>
+@font-face {
+ font-family: CanvasTest;
+ src: url("/fonts/CanvasTest.ttf");
+}
+</style>
+<body class="show_output">
+
+<h1>2d.text.draw.fill.maxWidth.fontface</h1>
+<p class="desc">fillText works on @font-face fonts</p>
+
+
+<span style="font-family: CanvasTest; position: absolute; visibility: hidden">A</span>
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("fillText works on @font-face fonts");
+_addTest(function(canvas, ctx) {
+
+ctx.font = '50px CanvasTest';
+deferTest();
+setTimeout(t.step_func_done(function () {
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#f00';
+ ctx.fillText('EEEE', -50, 37.5, 40);
+ _assertPixelApprox(canvas, 5,5, 0,255,0,255, "5,5", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 95,5, 0,255,0,255, "95,5", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255", 2);
+}), 500);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fill.maxWidth.large-manual.html b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fill.maxWidth.large-manual.html
new file mode 100644
index 00000000000..5f599c84d2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fill.maxWidth.large-manual.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.text.draw.fill.maxWidth.large</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.text.draw.fill.maxWidth.large</h1>
+<p class="desc">fillText handles maxWidth correctly</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.text.draw.fill.maxWidth.large.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("fillText handles maxWidth correctly");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#000';
+ctx.fillRect(0, 0, 100, 50);
+ctx.fillStyle = '#0f0';
+ctx.font = '35px Arial, sans-serif';
+ctx.fillText('PASS', 5, 35, 200);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fill.maxWidth.large.png b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fill.maxWidth.large.png
new file mode 100644
index 00000000000..deaef2c95c1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fill.maxWidth.large.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fill.maxWidth.negative.html b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fill.maxWidth.negative.html
new file mode 100644
index 00000000000..a6ec4f29063
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fill.maxWidth.negative.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.text.draw.fill.maxWidth.negative</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.text.draw.fill.maxWidth.negative</h1>
+<p class="desc">fillText handles maxWidth correctly</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("fillText handles maxWidth correctly");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.fillStyle = '#f00';
+ctx.font = '35px Arial, sans-serif';
+ctx.fillText('fail fail fail fail fail', 5, 35, -1);
+_assertGreen(ctx, 100, 50);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fill.maxWidth.small.html b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fill.maxWidth.small.html
new file mode 100644
index 00000000000..d0364d87229
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fill.maxWidth.small.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.text.draw.fill.maxWidth.small</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.text.draw.fill.maxWidth.small</h1>
+<p class="desc">fillText handles maxWidth correctly</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("fillText handles maxWidth correctly");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.fillStyle = '#f00';
+ctx.font = '35px Arial, sans-serif';
+ctx.fillText('fail fail fail fail fail', -100, 35, 90);
+_assertGreen(ctx, 100, 50);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fill.maxWidth.zero.html b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fill.maxWidth.zero.html
new file mode 100644
index 00000000000..176e43197a8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fill.maxWidth.zero.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.text.draw.fill.maxWidth.zero</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.text.draw.fill.maxWidth.zero</h1>
+<p class="desc">fillText handles maxWidth correctly</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("fillText handles maxWidth correctly");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.fillStyle = '#f00';
+ctx.font = '35px Arial, sans-serif';
+ctx.fillText('fail fail fail fail fail', 5, 35, 0);
+_assertGreen(ctx, 100, 50);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fill.rtl-manual.html b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fill.rtl-manual.html
new file mode 100644
index 00000000000..1066b837d42
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fill.rtl-manual.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.text.draw.fill.rtl</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.text.draw.fill.rtl</h1>
+<p class="desc">fillText respects Right-To-Left Override characters</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.text.draw.fill.rtl.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("fillText respects Right-To-Left Override characters");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#000';
+ctx.fillRect(0, 0, 100, 50);
+ctx.fillStyle = '#0f0';
+ctx.strokeStyle = '#f00';
+ctx.font = '35px Arial, sans-serif';
+ctx.fillText('\u202eFAIL \xa0 \xa0 SSAP', 5, 35);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fill.rtl.png b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fill.rtl.png
new file mode 100644
index 00000000000..deaef2c95c1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fill.rtl.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fill.unaffected.html b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fill.unaffected.html
new file mode 100644
index 00000000000..a7ddee41863
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fill.unaffected.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.text.draw.fill.unaffected</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.text.draw.fill.unaffected</h1>
+<p class="desc">fillText does not start a new path or subpath</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("fillText does not start a new path or subpath");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.moveTo(0, 0);
+ctx.lineTo(100, 0);
+
+ctx.font = '35px Arial, sans-serif';
+ctx.fillText('FAIL', 5, 35);
+
+ctx.lineTo(100, 50);
+ctx.lineTo(0, 50);
+ctx.fillStyle = '#0f0';
+ctx.fill();
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 5,45, 0,255,0,255, "5,45", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fontface.html b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fontface.html
new file mode 100644
index 00000000000..7bfbb7feb61
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fontface.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.text.draw.fontface</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<style>
+@font-face {
+ font-family: CanvasTest;
+ src: url("/fonts/CanvasTest.ttf");
+}
+</style>
+<body class="show_output">
+
+<h1>2d.text.draw.fontface</h1>
+<p class="desc"></p>
+
+
+<span style="font-family: CanvasTest; position: absolute; visibility: hidden">A</span>
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.font = '67px CanvasTest';
+deferTest();
+setTimeout(t.step_func_done(function () {
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.fillText('AA', 0, 50);
+ _assertPixelApprox(canvas, 5,5, 0,255,0,255, "5,5", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 95,5, 0,255,0,255, "95,5", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255", 2);
+}), 500);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fontface.notinpage.html b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fontface.notinpage.html
new file mode 100644
index 00000000000..6c4eb49190b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fontface.notinpage.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.text.draw.fontface.notinpage</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<style>
+@font-face {
+ font-family: CanvasTest;
+ src: url("/fonts/CanvasTest.ttf");
+}
+</style>
+<body class="show_output">
+
+<h1>2d.text.draw.fontface.notinpage</h1>
+<p class="desc">@font-face fonts should work even if they are not used in the page</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("@font-face fonts should work even if they are not used in the page");
+_addTest(function(canvas, ctx) {
+
+ctx.font = '67px CanvasTest';
+deferTest();
+setTimeout(t.step_func_done(function () {
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.fillText('AA', 0, 50);
+ _assertPixelApprox(canvas, 5,5, 0,255,0,255, "5,5", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 95,5, 0,255,0,255, "95,5", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255", 2);
+}), 500);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fontface.repeat.html b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fontface.repeat.html
new file mode 100644
index 00000000000..30cfb4c7f0b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.fontface.repeat.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.text.draw.fontface.repeat</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<style>
+@font-face {
+ font-family: CanvasTest;
+ src: url("/fonts/CanvasTest.ttf");
+}
+</style>
+<body class="show_output">
+
+<h1>2d.text.draw.fontface.repeat</h1>
+<p class="desc">Draw with the font immediately, then wait a bit until and draw again. (This crashes some version of WebKit.)</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Draw with the font immediately, then wait a bit until and draw again. (This crashes some version of WebKit.)");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.font = '67px CanvasTest';
+ctx.fillStyle = '#0f0';
+ctx.fillText('AA', 0, 50);
+deferTest();
+setTimeout(t.step_func_done(function () {
+ ctx.fillText('AA', 0, 50);
+ _assertPixelApprox(canvas, 5,5, 0,255,0,255, "5,5", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 95,5, 0,255,0,255, "95,5", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255", 2);
+}), 500);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.kern.consistent-manual.html b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.kern.consistent-manual.html
new file mode 100644
index 00000000000..12618f4f6af
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.kern.consistent-manual.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.text.draw.kern.consistent</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.text.draw.kern.consistent</h1>
+<p class="desc">Stroked and filled text should have exactly the same kerning so it overlaps</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Stroked and filled text should have exactly the same kerning so it overlaps");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.fillStyle = '#f00';
+ctx.strokeStyle = '#0f0';
+ctx.lineWidth = 3;
+ctx.font = '20px Arial, sans-serif';
+ctx.fillText('VAVAVAVAVAVAVA', -50, 25);
+ctx.fillText('ToToToToToToTo', -50, 45);
+ctx.strokeText('VAVAVAVAVAVAVA', -50, 25);
+ctx.strokeText('ToToToToToToTo', -50, 45);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.space.basic.html b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.space.basic.html
new file mode 100644
index 00000000000..046ce7c7aa9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.space.basic.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.text.draw.space.basic</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<style>
+@font-face {
+ font-family: CanvasTest;
+ src: url("/fonts/CanvasTest.ttf");
+}
+</style>
+<body class="show_output">
+
+<h1>2d.text.draw.space.basic</h1>
+<p class="desc">U+0020 is rendered the correct size (1em wide)</p>
+
+
+<span style="font-family: CanvasTest; position: absolute; visibility: hidden">A</span>
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("U+0020 is rendered the correct size (1em wide)");
+_addTest(function(canvas, ctx) {
+
+ctx.font = '50px CanvasTest';
+deferTest();
+setTimeout(t.step_func_done(function () {
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.fillText('E EE', -100, 37.5);
+ _assertPixelApprox(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255", 2);
+}), 500);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.space.collapse.nonspace.html b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.space.collapse.nonspace.html
new file mode 100644
index 00000000000..9dd441ade31
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.space.collapse.nonspace.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.text.draw.space.collapse.nonspace</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<style>
+@font-face {
+ font-family: CanvasTest;
+ src: url("/fonts/CanvasTest.ttf");
+}
+</style>
+<body class="show_output">
+
+<h1>2d.text.draw.space.collapse.nonspace</h1>
+<p class="desc">Non-space characters are not converted to U+0020 and collapsed</p>
+
+
+<span style="font-family: CanvasTest; position: absolute; visibility: hidden">A</span>
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Non-space characters are not converted to U+0020 and collapsed");
+_addTest(function(canvas, ctx) {
+
+ctx.font = '50px CanvasTest';
+deferTest();
+setTimeout(t.step_func_done(function () {
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.fillText('E\x0b EE', -150, 37.5);
+ _assertPixelApprox(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255", 2);
+}), 500);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.stroke.basic-manual.html b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.stroke.basic-manual.html
new file mode 100644
index 00000000000..f9eac1f62c2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.stroke.basic-manual.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.text.draw.stroke.basic</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.text.draw.stroke.basic</h1>
+<p class="desc">strokeText draws stroked text</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.text.draw.stroke.basic.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("strokeText draws stroked text");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#000';
+ctx.fillRect(0, 0, 100, 50);
+ctx.strokeStyle = '#0f0';
+ctx.fillStyle = '#f00';
+ctx.lineWidth = 1;
+ctx.font = '35px Arial, sans-serif';
+ctx.strokeText('PASS', 5, 35);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.stroke.basic.png b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.stroke.basic.png
new file mode 100644
index 00000000000..fe1b43b4672
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.stroke.basic.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.stroke.unaffected.html b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.stroke.unaffected.html
new file mode 100644
index 00000000000..1da4d927706
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.draw.stroke.unaffected.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.text.draw.stroke.unaffected</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.text.draw.stroke.unaffected</h1>
+<p class="desc">strokeText does not start a new path or subpath</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("strokeText does not start a new path or subpath");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.moveTo(0, 0);
+ctx.lineTo(100, 0);
+
+ctx.font = '35px Arial, sans-serif';
+ctx.strokeStyle = '#f00';
+ctx.strokeText('FAIL', 5, 35);
+
+ctx.lineTo(100, 50);
+ctx.lineTo(0, 50);
+ctx.fillStyle = '#0f0';
+ctx.fill();
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 5,45, 0,255,0,255, "5,45", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.measure.width.basic.html b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.measure.width.basic.html
new file mode 100644
index 00000000000..40b43deceb8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.measure.width.basic.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.text.measure.width.basic</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<style>
+@font-face {
+ font-family: CanvasTest;
+ src: url("/fonts/CanvasTest.ttf");
+}
+</style>
+<body class="show_output">
+
+<h1>2d.text.measure.width.basic</h1>
+<p class="desc"></p>
+
+
+<span style="font-family: CanvasTest; position: absolute; visibility: hidden">A</span>
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+deferTest();
+setTimeout(t.step_func_done(function () {
+ ctx.font = '50px CanvasTest';
+ _assertSame(ctx.measureText('A').width, 50, "ctx.measureText('A').width", "50");
+ _assertSame(ctx.measureText('AA').width, 100, "ctx.measureText('AA').width", "100");
+ _assertSame(ctx.measureText('ABCD').width, 200, "ctx.measureText('ABCD').width", "200");
+
+ ctx.font = '100px CanvasTest';
+ _assertSame(ctx.measureText('A').width, 100, "ctx.measureText('A').width", "100");
+}), 500);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.measure.width.empty.html b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.measure.width.empty.html
new file mode 100644
index 00000000000..67a9b405a0d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawing-text-to-the-canvas/2d.text.measure.width.empty.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.text.measure.width.empty</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<style>
+@font-face {
+ font-family: CanvasTest;
+ src: url("/fonts/CanvasTest.ttf");
+}
+</style>
+<body class="show_output">
+
+<h1>2d.text.measure.width.empty</h1>
+<p class="desc">The empty string has zero width</p>
+
+
+<span style="font-family: CanvasTest; position: absolute; visibility: hidden">A</span>
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("The empty string has zero width");
+_addTest(function(canvas, ctx) {
+
+deferTest();
+setTimeout(t.step_func_done(function () {
+ ctx.font = '50px CanvasTest';
+ _assertSame(ctx.measureText("").width, 0, "ctx.measureText(\"\").width", "0");
+}), 500);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/drawingstyle-objects/.gitkeep b/tests/wpt/web-platform-tests/2dcontext/drawingstyle-objects/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/drawingstyle-objects/.gitkeep
diff --git a/tests/wpt/web-platform-tests/2dcontext/examples/.gitkeep b/tests/wpt/web-platform-tests/2dcontext/examples/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/examples/.gitkeep
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/.gitkeep b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/.gitkeep
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.default.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.default.html
new file mode 100644
index 00000000000..a14475d7de5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.default.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.default</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.default</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+_assertSame(ctx.fillStyle, '#000000', "ctx.fillStyle", "'#000000'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.get.semitransparent.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.get.semitransparent.html
new file mode 100644
index 00000000000..d8a1d4178cf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.get.semitransparent.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.get.semitransparent</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.get.semitransparent</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = 'rgba(255,255,255,0.45)';
+assert_regexp_match(ctx.fillStyle, /^rgba\(255, 255, 255, 0\.4\d+\)$/);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.get.solid.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.get.solid.html
new file mode 100644
index 00000000000..8fc44b1c863
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.get.solid.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.get.solid</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.get.solid</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#fa0';
+_assertSame(ctx.fillStyle, '#ffaa00', "ctx.fillStyle", "'#ffaa00'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.get.transparent.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.get.transparent.html
new file mode 100644
index 00000000000..3775cf3f913
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.get.transparent.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.get.transparent</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.get.transparent</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = 'rgba(0,0,0,0)';
+_assertSame(ctx.fillStyle, 'rgba(0, 0, 0, 0)', "ctx.fillStyle", "'rgba(0, 0, 0, 0)'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.invalidstring.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.invalidstring.html
new file mode 100644
index 00000000000..eaa50dd02ff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.invalidstring.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.invalidstring</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.invalidstring</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.fillStyle = '#0f0';
+ctx.fillStyle = 'invalid';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.invalidtype.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.invalidtype.html
new file mode 100644
index 00000000000..fb778cbfba4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.invalidtype.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.invalidtype</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.invalidtype</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.fillStyle = '#0f0';
+ctx.fillStyle = null;
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.current.basic.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.current.basic.html
new file mode 100644
index 00000000000..271adfd8b36
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.current.basic.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.current.basic</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.current.basic</h1>
+<p class="desc">currentColor is computed from the canvas element</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("currentColor is computed from the canvas element");
+_addTest(function(canvas, ctx) {
+
+canvas.setAttribute('style', 'color: #0f0');
+ctx.fillStyle = '#f00';
+ctx.fillStyle = 'currentColor';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.current.changed.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.current.changed.html
new file mode 100644
index 00000000000..591b6d25602
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.current.changed.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.current.changed</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.current.changed</h1>
+<p class="desc">currentColor is computed when the attribute is set, not when it is painted</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("currentColor is computed when the attribute is set, not when it is painted");
+_addTest(function(canvas, ctx) {
+
+canvas.setAttribute('style', 'color: #0f0');
+ctx.fillStyle = '#f00';
+ctx.fillStyle = 'currentColor';
+canvas.setAttribute('style', 'color: #f00');
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.current.removed.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.current.removed.html
new file mode 100644
index 00000000000..a46e9c975b5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.current.removed.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.current.removed</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.current.removed</h1>
+<p class="desc">currentColor is solid black when the canvas element is not in a document</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.current.removed.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("currentColor is solid black when the canvas element is not in a document");
+_addTest(function(canvas, ctx) {
+
+// Try not to let it undetectably incorrectly pick up opaque-black
+// from other parts of the document:
+document.body.parentNode.setAttribute('style', 'color: #f00');
+document.body.setAttribute('style', 'color: #f00');
+canvas.setAttribute('style', 'color: #f00');
+
+var canvas2 = document.createElement('canvas');
+var ctx2 = canvas2.getContext('2d');
+ctx2.fillStyle = '#f00';
+ctx2.fillStyle = 'currentColor';
+ctx2.fillRect(0, 0, 100, 50);
+ctx.drawImage(canvas2, 0, 0);
+
+document.body.parentNode.removeAttribute('style');
+document.body.removeAttribute('style');
+
+_assertPixel(canvas, 50,25, 0,0,0,255, "50,25", "0,0,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.current.removed.png b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.current.removed.png
new file mode 100644
index 00000000000..d638d033868
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.current.removed.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hex3.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hex3.html
new file mode 100644
index 00000000000..635a59a72f9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hex3.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.hex3</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.hex3</h1>
+<p class="desc"></p>
+
+<p class="notes">
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.hex3.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#f00';
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hex3.png b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hex3.png
new file mode 100644
index 00000000000..2733836c998
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hex3.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hex6.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hex6.html
new file mode 100644
index 00000000000..37a4208009a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hex6.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.hex6</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.hex6</h1>
+<p class="desc"></p>
+
+<p class="notes">
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.hex6.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#f00';
+ctx.fillStyle = '#00fF00';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hex6.png b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hex6.png
new file mode 100644
index 00000000000..2733836c998
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hex6.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-1.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-1.html
new file mode 100644
index 00000000000..53b1f5d403b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-1.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.hsl-1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.hsl-1</h1>
+<p class="desc"></p>
+
+<p class="notes">
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.hsl-1.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#f00';
+ctx.fillStyle = 'hsl(120, 100%, 50%)';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-1.png b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-1.png
new file mode 100644
index 00000000000..2733836c998
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-1.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-2.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-2.html
new file mode 100644
index 00000000000..39790e979dd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-2.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.hsl-2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.hsl-2</h1>
+<p class="desc"></p>
+
+<p class="notes">
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.hsl-2.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#f00';
+ctx.fillStyle = 'hsl( -240 , 100% , 50% )';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-2.png b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-2.png
new file mode 100644
index 00000000000..2733836c998
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-2.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-3.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-3.html
new file mode 100644
index 00000000000..2befaab2e6d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-3.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.hsl-3</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.hsl-3</h1>
+<p class="desc"></p>
+
+<p class="notes">
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.hsl-3.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#f00';
+ctx.fillStyle = 'hsl(360120, 100%, 50%)';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-3.png b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-3.png
new file mode 100644
index 00000000000..2733836c998
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-3.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-4.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-4.html
new file mode 100644
index 00000000000..9f8e7cac10c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-4.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.hsl-4</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.hsl-4</h1>
+<p class="desc"></p>
+
+<p class="notes">
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.hsl-4.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#f00';
+ctx.fillStyle = 'hsl(-360240, 100%, 50%)';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-4.png b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-4.png
new file mode 100644
index 00000000000..2733836c998
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-4.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-5.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-5.html
new file mode 100644
index 00000000000..881bc0492b6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-5.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.hsl-5</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.hsl-5</h1>
+<p class="desc"></p>
+
+<p class="notes">
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.hsl-5.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#f00';
+ctx.fillStyle = 'hsl(120.0, 100.0%, 50.0%)';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-5.png b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-5.png
new file mode 100644
index 00000000000..2733836c998
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-5.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-6.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-6.html
new file mode 100644
index 00000000000..f2636336c87
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-6.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.hsl-6</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.hsl-6</h1>
+<p class="desc"></p>
+
+<p class="notes">
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.hsl-6.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#f00';
+ctx.fillStyle = 'hsl(+120, +100%, +50%)';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-6.png b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-6.png
new file mode 100644
index 00000000000..2733836c998
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-6.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-1.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-1.html
new file mode 100644
index 00000000000..a2fce10dc28
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-1.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.hsl-clamp-1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.hsl-clamp-1</h1>
+<p class="desc"></p>
+
+<p class="notes">
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.hsl-clamp-1.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#f00';
+ctx.fillStyle = 'hsl(120, 200%, 50%)';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-1.png b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-1.png
new file mode 100644
index 00000000000..2733836c998
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-1.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-2.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-2.html
new file mode 100644
index 00000000000..0a245a4df51
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-2.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.hsl-clamp-2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.hsl-clamp-2</h1>
+<p class="desc"></p>
+
+<p class="notes">
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.hsl-clamp-2.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#f00';
+ctx.fillStyle = 'hsl(120, -200%, 49.9%)';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 127,127,127,255, "50,25", "127,127,127,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-2.png b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-2.png
new file mode 100644
index 00000000000..88fd8279855
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-2.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-3.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-3.html
new file mode 100644
index 00000000000..ed14332f820
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-3.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.hsl-clamp-3</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.hsl-clamp-3</h1>
+<p class="desc"></p>
+
+<p class="notes">
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.hsl-clamp-3.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#f00';
+ctx.fillStyle = 'hsl(120, 100%, 200%)';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 255,255,255,255, "50,25", "255,255,255,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-3.png b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-3.png
new file mode 100644
index 00000000000..bf48767a881
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-3.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-4.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-4.html
new file mode 100644
index 00000000000..a27379c5e81
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-4.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.hsl-clamp-4</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.hsl-clamp-4</h1>
+<p class="desc"></p>
+
+<p class="notes">
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.hsl-clamp-4.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#f00';
+ctx.fillStyle = 'hsl(120, 100%, -200%)';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,0,0,255, "50,25", "0,0,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-4.png b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-4.png
new file mode 100644
index 00000000000..d638d033868
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsl-clamp-4.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-1.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-1.html
new file mode 100644
index 00000000000..2e835a8b370
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-1.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.hsla-1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.hsla-1</h1>
+<p class="desc"></p>
+
+<p class="notes">
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.hsla-1.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#f00';
+ctx.fillStyle = 'hsla(120, 100%, 50%, 0.499)';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,127, "50,25", "0,255,0,127");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-1.png b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-1.png
new file mode 100644
index 00000000000..2aa6265f066
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-1.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-2.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-2.html
new file mode 100644
index 00000000000..a7db6ac1055
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-2.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.hsla-2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.hsla-2</h1>
+<p class="desc"></p>
+
+<p class="notes">
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.hsla-2.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#f00';
+ctx.fillStyle = 'hsla( 120.0 , 100.0% , 50.0% , 1 )';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-2.png b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-2.png
new file mode 100644
index 00000000000..2733836c998
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-2.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-1.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-1.html
new file mode 100644
index 00000000000..13652aab140
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-1.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.hsla-clamp-1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.hsla-clamp-1</h1>
+<p class="desc"></p>
+
+<p class="notes">
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.hsla-clamp-1.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#f00';
+ctx.fillStyle = 'hsla(120, 200%, 50%, 1)';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-1.png b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-1.png
new file mode 100644
index 00000000000..2733836c998
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-1.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-2.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-2.html
new file mode 100644
index 00000000000..98f2505a54d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-2.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.hsla-clamp-2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.hsla-clamp-2</h1>
+<p class="desc"></p>
+
+<p class="notes">
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.hsla-clamp-2.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#f00';
+ctx.fillStyle = 'hsla(120, -200%, 49.9%, 1)';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 127,127,127,255, "50,25", "127,127,127,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-2.png b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-2.png
new file mode 100644
index 00000000000..88fd8279855
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-2.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-3.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-3.html
new file mode 100644
index 00000000000..0aa08807a0b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-3.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.hsla-clamp-3</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.hsla-clamp-3</h1>
+<p class="desc"></p>
+
+<p class="notes">
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.hsla-clamp-3.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#f00';
+ctx.fillStyle = 'hsla(120, 100%, 200%, 1)';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 255,255,255,255, "50,25", "255,255,255,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-3.png b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-3.png
new file mode 100644
index 00000000000..bf48767a881
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-3.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-4.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-4.html
new file mode 100644
index 00000000000..ab5da396ce5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-4.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.hsla-clamp-4</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.hsla-clamp-4</h1>
+<p class="desc"></p>
+
+<p class="notes">
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.hsla-clamp-4.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#f00';
+ctx.fillStyle = 'hsla(120, 100%, -200%, 1)';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,0,0,255, "50,25", "0,0,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-4.png b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-4.png
new file mode 100644
index 00000000000..d638d033868
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-4.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-5.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-5.html
new file mode 100644
index 00000000000..a64f89303e3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-5.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.hsla-clamp-5</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.hsla-clamp-5</h1>
+<p class="desc"></p>
+
+<p class="notes">
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.hsla-clamp-5.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#f00';
+ctx.fillStyle = 'hsla(120, 100%, 50%, 2)';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-5.png b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-5.png
new file mode 100644
index 00000000000..2733836c998
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-5.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-6.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-6.html
new file mode 100644
index 00000000000..60b464a6247
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-6.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.hsla-clamp-6</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.hsla-clamp-6</h1>
+<p class="desc"></p>
+
+<p class="notes">
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.hsla-clamp-6.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#f00';
+ctx.fillStyle = 'hsla(120, 100%, 0%, -2)';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,0,0,0, "50,25", "0,0,0,0");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-6.png b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-6.png
new file mode 100644
index 00000000000..eeedd0ff058
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.hsla-clamp-6.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.html4.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.html4.html
new file mode 100644
index 00000000000..3dd7d37eb9f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.html4.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.html4</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.html4</h1>
+<p class="desc"></p>
+
+<p class="notes">
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.html4.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#f00';
+ctx.fillStyle = 'limE';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.html4.png b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.html4.png
new file mode 100644
index 00000000000..2733836c998
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.html4.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex1.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex1.html
new file mode 100644
index 00000000000..36a9489e16b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex1.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.invalid.hex1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.invalid.hex1</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#0f0';
+try { ctx.fillStyle = '#f'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex2.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex2.html
new file mode 100644
index 00000000000..5a1758fc5f5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex2.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.invalid.hex2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.invalid.hex2</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#0f0';
+try { ctx.fillStyle = '#f0'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex3.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex3.html
new file mode 100644
index 00000000000..f1ada9f190f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex3.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.invalid.hex3</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.invalid.hex3</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#0f0';
+try { ctx.fillStyle = '#g00'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex4.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex4.html
new file mode 100644
index 00000000000..5307cd4184c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex4.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.invalid.hex4</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.invalid.hex4</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#0f0';
+try { ctx.fillStyle = '#ff00'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex5.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex5.html
new file mode 100644
index 00000000000..19abea32af7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex5.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.invalid.hex5</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.invalid.hex5</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#0f0';
+try { ctx.fillStyle = '#ff000'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex6.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex6.html
new file mode 100644
index 00000000000..c600b983113
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex6.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.invalid.hex6</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.invalid.hex6</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#0f0';
+try { ctx.fillStyle = '#fg0000'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex7.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex7.html
new file mode 100644
index 00000000000..cee88055e4e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex7.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.invalid.hex7</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.invalid.hex7</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#0f0';
+try { ctx.fillStyle = '#ff0000f'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex8.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex8.html
new file mode 100644
index 00000000000..11b11ce0ccf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hex8.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.invalid.hex8</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.invalid.hex8</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#0f0';
+try { ctx.fillStyle = '#ff0000ff'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-1.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-1.html
new file mode 100644
index 00000000000..3acee1f3917
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-1.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.invalid.hsl-1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.invalid.hsl-1</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#0f0';
+try { ctx.fillStyle = 'hsl(0%, 100%, 50%)'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-2.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-2.html
new file mode 100644
index 00000000000..c2c34f52461
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-2.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.invalid.hsl-2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.invalid.hsl-2</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#0f0';
+try { ctx.fillStyle = 'hsl(z, 100%, 50%)'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-3.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-3.html
new file mode 100644
index 00000000000..616639a1ec5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-3.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.invalid.hsl-3</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.invalid.hsl-3</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#0f0';
+try { ctx.fillStyle = 'hsl(0, 0, 50%)'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-4.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-4.html
new file mode 100644
index 00000000000..aaa2a8dc0d3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-4.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.invalid.hsl-4</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.invalid.hsl-4</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#0f0';
+try { ctx.fillStyle = 'hsl(0, 100%, 0)'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-5.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-5.html
new file mode 100644
index 00000000000..87b6a5731ce
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-5.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.invalid.hsl-5</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.invalid.hsl-5</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#0f0';
+try { ctx.fillStyle = 'hsl(0, 100%, 100%, 1)'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-6.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-6.html
new file mode 100644
index 00000000000..008e278b558
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsl-6.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.invalid.hsl-6</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.invalid.hsl-6</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#0f0';
+try { ctx.fillStyle = 'hsl(0, 100.%, 50%)'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsla-1.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsla-1.html
new file mode 100644
index 00000000000..dbddb0f5593
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsla-1.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.invalid.hsla-1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.invalid.hsla-1</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#0f0';
+try { ctx.fillStyle = 'hsla(0%, 100%, 50%, 1)'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsla-2.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsla-2.html
new file mode 100644
index 00000000000..8a9643f887a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.hsla-2.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.invalid.hsla-2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.invalid.hsla-2</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#0f0';
+try { ctx.fillStyle = 'hsla(0, 0, 50%, 1)'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-1.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-1.html
new file mode 100644
index 00000000000..45dcfca0c55
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-1.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.invalid.name-1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.invalid.name-1</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#0f0';
+try { ctx.fillStyle = 'darkbrown'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-2.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-2.html
new file mode 100644
index 00000000000..a3016b2a11f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-2.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.invalid.name-2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.invalid.name-2</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#0f0';
+try { ctx.fillStyle = 'firebrick1'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-3.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-3.html
new file mode 100644
index 00000000000..1d56151b6de
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-3.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.invalid.name-3</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.invalid.name-3</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#0f0';
+try { ctx.fillStyle = 'red blue'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-4.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-4.html
new file mode 100644
index 00000000000..e2619ffa8f9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-4.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.invalid.name-4</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.invalid.name-4</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#0f0';
+try { ctx.fillStyle = '"red"'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-5.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-5.html
new file mode 100644
index 00000000000..f515ff32e05
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.name-5.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.invalid.name-5</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.invalid.name-5</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#0f0';
+try { ctx.fillStyle = '"red'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgb-1.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgb-1.html
new file mode 100644
index 00000000000..fc0433eae59
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgb-1.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.invalid.rgb-1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.invalid.rgb-1</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#0f0';
+try { ctx.fillStyle = 'rgb(255.0, 0, 0)'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgb-2.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgb-2.html
new file mode 100644
index 00000000000..68c06e5ebec
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgb-2.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.invalid.rgb-2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.invalid.rgb-2</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#0f0';
+try { ctx.fillStyle = 'rgb(255, 0.0, 0)'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgb-3.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgb-3.html
new file mode 100644
index 00000000000..f864c9f2bc4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgb-3.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.invalid.rgb-3</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.invalid.rgb-3</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#0f0';
+try { ctx.fillStyle = 'rgb(255.0, 0, 0,)'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgb-4.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgb-4.html
new file mode 100644
index 00000000000..e4d78b20e14
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgb-4.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.invalid.rgb-4</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.invalid.rgb-4</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#0f0';
+try { ctx.fillStyle = 'rgb(100%, 0, 0)'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgb-5.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgb-5.html
new file mode 100644
index 00000000000..92f933db799
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgb-5.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.invalid.rgb-5</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.invalid.rgb-5</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#0f0';
+try { ctx.fillStyle = 'rgb(255 0 0)'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgb-6.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgb-6.html
new file mode 100644
index 00000000000..e3de9df5387
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgb-6.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.invalid.rgb-6</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.invalid.rgb-6</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#0f0';
+try { ctx.fillStyle = 'rgb(255, - 1, 0)'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgb-7.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgb-7.html
new file mode 100644
index 00000000000..bc0bb5ef6f6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgb-7.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.invalid.rgb-7</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.invalid.rgb-7</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#0f0';
+try { ctx.fillStyle = 'rgb(255, 0, 0, 1)'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-1.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-1.html
new file mode 100644
index 00000000000..774aed13d51
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-1.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.invalid.rgba-1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.invalid.rgba-1</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#0f0';
+try { ctx.fillStyle = 'rgba(255, 0, 0)'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-2.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-2.html
new file mode 100644
index 00000000000..14065e63426
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-2.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.invalid.rgba-2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.invalid.rgba-2</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#0f0';
+try { ctx.fillStyle = 'rgba(255.0, 0, 0, 1)'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-3.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-3.html
new file mode 100644
index 00000000000..5947169fe55
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-3.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.invalid.rgba-3</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.invalid.rgba-3</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#0f0';
+try { ctx.fillStyle = 'rgba(100%, 0, 0, 1)'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-4.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-4.html
new file mode 100644
index 00000000000..9870b14f9d1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-4.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.invalid.rgba-4</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.invalid.rgba-4</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#0f0';
+try { ctx.fillStyle = 'rgba(255, 0, 0, 100%)'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-5.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-5.html
new file mode 100644
index 00000000000..4274996cae3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-5.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.invalid.rgba-5</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.invalid.rgba-5</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#0f0';
+try { ctx.fillStyle = 'rgba(255, 0, 0, 1. 0)'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-6.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-6.html
new file mode 100644
index 00000000000..3e7f06ad436
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-6.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.invalid.rgba-6</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.invalid.rgba-6</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#0f0';
+try { ctx.fillStyle = 'rgba(255, 0, 0, 1.)'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-7.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-7.html
new file mode 100644
index 00000000000..06580f64816
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.invalid.rgba-7.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.invalid.rgba-7</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.invalid.rgba-7</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#0f0';
+try { ctx.fillStyle = 'rgba(255, 0, 0, '; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-1.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-1.html
new file mode 100644
index 00000000000..807a4961b53
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-1.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.rgb-clamp-1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.rgb-clamp-1</h1>
+<p class="desc"></p>
+
+<p class="notes">Assumes colours are clamped to [0,255].
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.rgb-clamp-1.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#f00';
+ctx.fillStyle = 'rgb(-1000, 1000, -1000)';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-1.png b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-1.png
new file mode 100644
index 00000000000..2733836c998
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-1.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-2.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-2.html
new file mode 100644
index 00000000000..46b3b6daa05
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-2.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.rgb-clamp-2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.rgb-clamp-2</h1>
+<p class="desc"></p>
+
+<p class="notes">Assumes colours are clamped to [0,255].
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.rgb-clamp-2.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#f00';
+ctx.fillStyle = 'rgb(-200%, 200%, -200%)';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-2.png b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-2.png
new file mode 100644
index 00000000000..2733836c998
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-2.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-3.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-3.html
new file mode 100644
index 00000000000..75dbe19c694
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-3.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.rgb-clamp-3</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.rgb-clamp-3</h1>
+<p class="desc"></p>
+
+<p class="notes">Assumes colours are clamped to [0,255].
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.rgb-clamp-3.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#f00';
+ctx.fillStyle = 'rgb(-2147483649, 4294967298, -18446744073709551619)';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-3.png b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-3.png
new file mode 100644
index 00000000000..2733836c998
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-3.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-4.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-4.html
new file mode 100644
index 00000000000..4888816b66d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-4.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.rgb-clamp-4</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.rgb-clamp-4</h1>
+<p class="desc"></p>
+
+<p class="notes">Assumes colours are clamped to [0,255].
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.rgb-clamp-4.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#f00';
+ctx.fillStyle = 'rgb(-1000000000000000000000000000000000000000, 1000000000000000000000000000000000000000, -1000000000000000000000000000000000000000)';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-4.png b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-4.png
new file mode 100644
index 00000000000..2733836c998
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-4.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-5.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-5.html
new file mode 100644
index 00000000000..3f7a94433cf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-5.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.rgb-clamp-5</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.rgb-clamp-5</h1>
+<p class="desc"></p>
+
+<p class="notes">Assumes colours are clamped to [0,255].
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.rgb-clamp-5.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#f00';
+ctx.fillStyle = 'rgb(-10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000, 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000, -10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000)';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-5.png b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-5.png
new file mode 100644
index 00000000000..2733836c998
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-clamp-5.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-eof.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-eof.html
new file mode 100644
index 00000000000..0d2833cebc1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-eof.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.rgb-eof</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.rgb-eof</h1>
+<p class="desc"></p>
+
+<p class="notes">
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.rgb-eof.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#f00';
+ctx.fillStyle = 'rgb(0, 255, 0';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-eof.png b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-eof.png
new file mode 100644
index 00000000000..2733836c998
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-eof.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-num.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-num.html
new file mode 100644
index 00000000000..85fc99280f8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-num.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.rgb-num</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.rgb-num</h1>
+<p class="desc"></p>
+
+<p class="notes">
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.rgb-num.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#f00';
+ctx.fillStyle = 'rgb(0,255,0)';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-num.png b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-num.png
new file mode 100644
index 00000000000..2733836c998
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-num.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-percent.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-percent.html
new file mode 100644
index 00000000000..295e72b0d2b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-percent.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.rgb-percent</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.rgb-percent</h1>
+<p class="desc"></p>
+
+<p class="notes">CSS3 Color says "The integer value 255 corresponds to 100%". (In particular, it is not 254...)
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.rgb-percent.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#f00';
+ctx.fillStyle = 'rgb(0% ,100% ,0%)';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-percent.png b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-percent.png
new file mode 100644
index 00000000000..2733836c998
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgb-percent.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-clamp-1.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-clamp-1.html
new file mode 100644
index 00000000000..0ec2ea0a18e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-clamp-1.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.rgba-clamp-1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.rgba-clamp-1</h1>
+<p class="desc"></p>
+
+<p class="notes">
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.rgba-clamp-1.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#f00';
+ctx.fillStyle = 'rgba(0, 255, 0, -2)';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,0,0,0, "50,25", "0,0,0,0");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-clamp-1.png b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-clamp-1.png
new file mode 100644
index 00000000000..eeedd0ff058
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-clamp-1.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-clamp-2.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-clamp-2.html
new file mode 100644
index 00000000000..fe352015737
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-clamp-2.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.rgba-clamp-2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.rgba-clamp-2</h1>
+<p class="desc"></p>
+
+<p class="notes">
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.rgba-clamp-2.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#f00';
+ctx.fillStyle = 'rgba(0, 255, 0, 2)';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-clamp-2.png b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-clamp-2.png
new file mode 100644
index 00000000000..2733836c998
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-clamp-2.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-eof.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-eof.html
new file mode 100644
index 00000000000..d8856813d9d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-eof.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.rgba-eof</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.rgba-eof</h1>
+<p class="desc"></p>
+
+<p class="notes">
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.rgba-eof.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#f00';
+ctx.fillStyle = 'rgba(0, 255, 0, 1';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-eof.png b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-eof.png
new file mode 100644
index 00000000000..2733836c998
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-eof.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-num-1.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-num-1.html
new file mode 100644
index 00000000000..98dd9bf877e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-num-1.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.rgba-num-1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.rgba-num-1</h1>
+<p class="desc"></p>
+
+<p class="notes">
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.rgba-num-1.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#f00';
+ctx.fillStyle = 'rgba( 0 , 255 , 0 , .499 )';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,127, "50,25", "0,255,0,127");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-num-1.png b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-num-1.png
new file mode 100644
index 00000000000..2aa6265f066
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-num-1.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-num-2.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-num-2.html
new file mode 100644
index 00000000000..5cadec16cc0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-num-2.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.rgba-num-2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.rgba-num-2</h1>
+<p class="desc"></p>
+
+<p class="notes">
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.rgba-num-2.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#f00';
+ctx.fillStyle = 'rgba( 0 , 255 , 0 , 0.499 )';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,127, "50,25", "0,255,0,127");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-num-2.png b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-num-2.png
new file mode 100644
index 00000000000..2aa6265f066
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-num-2.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-percent.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-percent.html
new file mode 100644
index 00000000000..63f8c9ea9f9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-percent.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.rgba-percent</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.rgba-percent</h1>
+<p class="desc"></p>
+
+<p class="notes">
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.rgba-percent.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#f00';
+ctx.fillStyle = 'rgba(0%,100%,0%,0.499)';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,127, "50,25", "0,255,0,127");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-percent.png b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-percent.png
new file mode 100644
index 00000000000..2aa6265f066
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-percent.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-1.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-1.html
new file mode 100644
index 00000000000..0d08a4921ff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-1.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.rgba-solid-1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.rgba-solid-1</h1>
+<p class="desc"></p>
+
+<p class="notes">
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.rgba-solid-1.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#f00';
+ctx.fillStyle = 'rgba( 0 , 255 , 0 , 1 )';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-1.png b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-1.png
new file mode 100644
index 00000000000..2733836c998
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-1.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-2.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-2.html
new file mode 100644
index 00000000000..2a9db38ed5c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-2.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.rgba-solid-2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.rgba-solid-2</h1>
+<p class="desc"></p>
+
+<p class="notes">
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.rgba-solid-2.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#f00';
+ctx.fillStyle = 'rgba( 0 , 255 , 0 , 1.0 )';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-2.png b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-2.png
new file mode 100644
index 00000000000..2733836c998
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-2.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-3.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-3.html
new file mode 100644
index 00000000000..81bf257cd8b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-3.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.rgba-solid-3</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.rgba-solid-3</h1>
+<p class="desc"></p>
+
+<p class="notes">
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.rgba-solid-3.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#f00';
+ctx.fillStyle = 'rgba( 0 , 255 , 0 , +1 )';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-3.png b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-3.png
new file mode 100644
index 00000000000..2733836c998
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-3.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-4.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-4.html
new file mode 100644
index 00000000000..82d450c01c2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-4.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.rgba-solid-4</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.rgba-solid-4</h1>
+<p class="desc"></p>
+
+<p class="notes">
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.rgba-solid-4.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#f00';
+ctx.fillStyle = 'rgba( -0 , 255 , +0 , 1 )';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-4.png b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-4.png
new file mode 100644
index 00000000000..2733836c998
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.rgba-solid-4.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.svg-1.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.svg-1.html
new file mode 100644
index 00000000000..c49620f0349
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.svg-1.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.svg-1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.svg-1</h1>
+<p class="desc"></p>
+
+<p class="notes">
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.svg-1.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#f00';
+ctx.fillStyle = 'gray';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 128,128,128,255, "50,25", "128,128,128,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.svg-1.png b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.svg-1.png
new file mode 100644
index 00000000000..5bc39cc699b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.svg-1.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.svg-2.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.svg-2.html
new file mode 100644
index 00000000000..3a7e3d97ef9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.svg-2.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.svg-2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.svg-2</h1>
+<p class="desc"></p>
+
+<p class="notes">
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.svg-2.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#f00';
+ctx.fillStyle = 'grey';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 128,128,128,255, "50,25", "128,128,128,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.svg-2.png b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.svg-2.png
new file mode 100644
index 00000000000..5bc39cc699b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.svg-2.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.system.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.system.html
new file mode 100644
index 00000000000..9bb43c6237e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.system.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.system</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.system</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#f00';
+ctx.fillStyle = 'ThreeDDarkShadow';
+assert_regexp_match(ctx.fillStyle, /^#(?!(FF0000|ff0000|f00)$)/); // test that it's not red
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.transparent-1.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.transparent-1.html
new file mode 100644
index 00000000000..36cc8043710
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.transparent-1.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.transparent-1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.transparent-1</h1>
+<p class="desc"></p>
+
+<p class="notes">
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.transparent-1.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#f00';
+ctx.fillStyle = 'transparent';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,0,0,0, "50,25", "0,0,0,0");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.transparent-1.png b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.transparent-1.png
new file mode 100644
index 00000000000..eeedd0ff058
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.transparent-1.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.transparent-2.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.transparent-2.html
new file mode 100644
index 00000000000..66e28259838
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.transparent-2.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.fillStyle.parse.transparent-2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.fillStyle.parse.transparent-2</h1>
+<p class="desc"></p>
+
+<p class="notes">
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.fillStyle.parse.transparent-2.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+
+ctx.fillStyle = '#f00';
+ctx.fillStyle = 'TrAnSpArEnT';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,0,0,0, "50,25", "0,0,0,0");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.transparent-2.png b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.transparent-2.png
new file mode 100644
index 00000000000..eeedd0ff058
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.fillStyle.parse.transparent-2.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.empty.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.empty.html
new file mode 100644
index 00000000000..e087f53c348
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.empty.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.gradient.empty</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.gradient.empty</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+var g = ctx.createLinearGradient(0, 0, 0, 50);
+ctx.fillStyle = g;
+ctx.fillRect(0, 0, 100, 50);
+_assertPixelApprox(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 2);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.alpha.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.alpha.html
new file mode 100644
index 00000000000..7bf486da4f3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.alpha.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.gradient.interpolate.alpha</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.gradient.interpolate.alpha</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.gradient.interpolate.alpha.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#ff0';
+ctx.fillRect(0, 0, 100, 50);
+var g = ctx.createLinearGradient(0, 0, 100, 0);
+g.addColorStop(0, 'rgba(0,0,255, 0)');
+g.addColorStop(1, 'rgba(0,0,255, 1)');
+ctx.fillStyle = g;
+ctx.fillRect(0, 0, 100, 50);
+_assertPixelApprox(canvas, 25,25, 191,191,63,255, "25,25", "191,191,63,255", 3);
+_assertPixelApprox(canvas, 50,25, 127,127,127,255, "50,25", "127,127,127,255", 3);
+_assertPixelApprox(canvas, 75,25, 63,63,191,255, "75,25", "63,63,191,255", 3);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.alpha.png b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.alpha.png
new file mode 100644
index 00000000000..67f34435995
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.alpha.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.colour.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.colour.html
new file mode 100644
index 00000000000..a5fd632b50f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.colour.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.gradient.interpolate.colour</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.gradient.interpolate.colour</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.gradient.interpolate.colour.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+var g = ctx.createLinearGradient(0, 0, 100, 0);
+g.addColorStop(0, '#ff0');
+g.addColorStop(1, '#00f');
+ctx.fillStyle = g;
+ctx.fillRect(0, 0, 100, 50);
+_assertPixelApprox(canvas, 25,25, 191,191,63,255, "25,25", "191,191,63,255", 3);
+_assertPixelApprox(canvas, 50,25, 127,127,127,255, "50,25", "127,127,127,255", 3);
+_assertPixelApprox(canvas, 75,25, 63,63,191,255, "75,25", "63,63,191,255", 3);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.colour.png b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.colour.png
new file mode 100644
index 00000000000..67f34435995
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.colour.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.colouralpha.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.colouralpha.html
new file mode 100644
index 00000000000..3e20e6faa3f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.colouralpha.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.gradient.interpolate.colouralpha</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.gradient.interpolate.colouralpha</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.gradient.interpolate.colouralpha.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+var g = ctx.createLinearGradient(0, 0, 100, 0);
+g.addColorStop(0, 'rgba(255,255,0, 0)');
+g.addColorStop(1, 'rgba(0,0,255, 1)');
+ctx.fillStyle = g;
+ctx.fillRect(0, 0, 100, 50);
+_assertPixelApprox(canvas, 25,25, 191,191,63,63, "25,25", "191,191,63,63", 3);
+_assertPixelApprox(canvas, 50,25, 127,127,127,127, "50,25", "127,127,127,127", 3);
+_assertPixelApprox(canvas, 75,25, 63,63,191,191, "75,25", "63,63,191,191", 3);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.colouralpha.png b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.colouralpha.png
new file mode 100644
index 00000000000..af6e50b7dc3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.colouralpha.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.multiple.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.multiple.html
new file mode 100644
index 00000000000..b6b8de13594
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.multiple.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.gradient.interpolate.multiple</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.gradient.interpolate.multiple</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.gradient.interpolate.multiple.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+canvas.width = 200;
+var g = ctx.createLinearGradient(0, 0, 200, 0);
+g.addColorStop(0, '#ff0');
+g.addColorStop(0.5, '#0ff');
+g.addColorStop(1, '#f0f');
+ctx.fillStyle = g;
+ctx.fillRect(0, 0, 200, 50);
+_assertPixelApprox(canvas, 50,25, 127,255,127,255, "50,25", "127,255,127,255", 3);
+_assertPixelApprox(canvas, 100,25, 0,255,255,255, "100,25", "0,255,255,255", 3);
+_assertPixelApprox(canvas, 150,25, 127,127,255,255, "150,25", "127,127,255,255", 3);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.multiple.png b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.multiple.png
new file mode 100644
index 00000000000..8f31ec3691e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.multiple.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.outside.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.outside.html
new file mode 100644
index 00000000000..7577c95e34d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.outside.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.gradient.interpolate.outside</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.gradient.interpolate.outside</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+var g = ctx.createLinearGradient(25, 0, 75, 0);
+g.addColorStop(0.4, '#0f0');
+g.addColorStop(0.6, '#0f0');
+
+ctx.fillStyle = g;
+ctx.fillRect(0, 0, 100, 50);
+_assertPixelApprox(canvas, 20,25, 0,255,0,255, "20,25", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 80,25, 0,255,0,255, "80,25", "0,255,0,255", 2);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.overlap.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.overlap.html
new file mode 100644
index 00000000000..ad2152f12d1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.overlap.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.gradient.interpolate.overlap</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.gradient.interpolate.overlap</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.gradient.interpolate.overlap.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+canvas.width = 200;
+var g = ctx.createLinearGradient(0, 0, 200, 0);
+g.addColorStop(0, '#f00');
+g.addColorStop(0, '#ff0');
+g.addColorStop(0.25, '#00f');
+g.addColorStop(0.25, '#0f0');
+g.addColorStop(0.25, '#0f0');
+g.addColorStop(0.25, '#0f0');
+g.addColorStop(0.25, '#ff0');
+g.addColorStop(0.5, '#00f');
+g.addColorStop(0.5, '#0f0');
+g.addColorStop(0.75, '#00f');
+g.addColorStop(0.75, '#f00');
+g.addColorStop(0.75, '#ff0');
+g.addColorStop(0.5, '#0f0');
+g.addColorStop(0.5, '#0f0');
+g.addColorStop(0.5, '#ff0');
+g.addColorStop(1, '#00f');
+ctx.fillStyle = g;
+ctx.fillRect(0, 0, 200, 50);
+_assertPixelApprox(canvas, 49,25, 0,0,255,255, "49,25", "0,0,255,255", 16);
+_assertPixelApprox(canvas, 51,25, 255,255,0,255, "51,25", "255,255,0,255", 16);
+_assertPixelApprox(canvas, 99,25, 0,0,255,255, "99,25", "0,0,255,255", 16);
+_assertPixelApprox(canvas, 101,25, 255,255,0,255, "101,25", "255,255,0,255", 16);
+_assertPixelApprox(canvas, 149,25, 0,0,255,255, "149,25", "0,0,255,255", 16);
+_assertPixelApprox(canvas, 151,25, 255,255,0,255, "151,25", "255,255,0,255", 16);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.overlap.png b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.overlap.png
new file mode 100644
index 00000000000..7d4dad8def7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.overlap.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.overlap2.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.overlap2.html
new file mode 100644
index 00000000000..7f99c1f32c4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.overlap2.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.gradient.interpolate.overlap2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.gradient.interpolate.overlap2</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+var g = ctx.createLinearGradient(0, 0, 100, 0);
+var ps = [ 0, 1/10, 1/4, 1/3, 1/2, 3/4, 1 ];
+for (var p = 0; p < ps.length; ++p)
+{
+ g.addColorStop(ps[p], '#0f0');
+ for (var i = 0; i < 15; ++i)
+ g.addColorStop(ps[p], '#f00');
+ g.addColorStop(ps[p], '#0f0');
+}
+ctx.fillStyle = g;
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 1,25, 0,255,0,255, "1,25", "0,255,0,255");
+_assertPixel(canvas, 30,25, 0,255,0,255, "30,25", "0,255,0,255");
+_assertPixel(canvas, 40,25, 0,255,0,255, "40,25", "0,255,0,255");
+_assertPixel(canvas, 60,25, 0,255,0,255, "60,25", "0,255,0,255");
+_assertPixel(canvas, 80,25, 0,255,0,255, "80,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.solid.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.solid.html
new file mode 100644
index 00000000000..46e53d3264a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.solid.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.gradient.interpolate.solid</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.gradient.interpolate.solid</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+var g = ctx.createLinearGradient(0, 0, 100, 0);
+g.addColorStop(0, '#0f0');
+g.addColorStop(1, '#0f0');
+ctx.fillStyle = g;
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.vertical.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.vertical.html
new file mode 100644
index 00000000000..a4c3453cf56
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.vertical.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.gradient.interpolate.vertical</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.gradient.interpolate.vertical</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.gradient.interpolate.vertical.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+var g = ctx.createLinearGradient(0, 0, 0, 50);
+g.addColorStop(0, '#ff0');
+g.addColorStop(1, '#00f');
+ctx.fillStyle = g;
+ctx.fillRect(0, 0, 100, 50);
+_assertPixelApprox(canvas, 50,12, 191,191,63,255, "50,12", "191,191,63,255", 10);
+_assertPixelApprox(canvas, 50,25, 127,127,127,255, "50,25", "127,127,127,255", 5);
+_assertPixelApprox(canvas, 50,37, 63,63,191,255, "50,37", "63,63,191,255", 10);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.vertical.png b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.vertical.png
new file mode 100644
index 00000000000..1d895a18f65
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.vertical.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.zerosize.fill.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.zerosize.fill.html
new file mode 100644
index 00000000000..92777bfef98
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.zerosize.fill.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.gradient.interpolate.zerosize.fill</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.gradient.interpolate.zerosize.fill</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+var g = ctx.createLinearGradient(50, 25, 50, 25); // zero-length line (undefined direction)
+g.addColorStop(0, '#f00');
+g.addColorStop(1, '#f00');
+ctx.fillStyle = g;
+ctx.rect(0, 0, 100, 50);
+ctx.fill();
+_assertPixel(canvas, 40,20, 0,255,0,255, "40,20", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.zerosize.fillRect.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.zerosize.fillRect.html
new file mode 100644
index 00000000000..98efeda7c63
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.zerosize.fillRect.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.gradient.interpolate.zerosize.fillRect</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.gradient.interpolate.zerosize.fillRect</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+var g = ctx.createLinearGradient(50, 25, 50, 25); // zero-length line (undefined direction)
+g.addColorStop(0, '#f00');
+g.addColorStop(1, '#f00');
+ctx.fillStyle = g;
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 40,20, 0,255,0,255, "40,20", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.zerosize.fillText.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.zerosize.fillText.html
new file mode 100644
index 00000000000..93397b976c5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.zerosize.fillText.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.gradient.interpolate.zerosize.fillText</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.gradient.interpolate.zerosize.fillText</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+var g = ctx.createLinearGradient(50, 25, 50, 25); // zero-length line (undefined direction)
+g.addColorStop(0, '#f00');
+g.addColorStop(1, '#f00');
+ctx.fillStyle = g;
+ctx.font = '100px sans-serif';
+ctx.fillText("AA", 0, 50);
+_assertGreen(ctx, 100, 50);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.zerosize.stroke.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.zerosize.stroke.html
new file mode 100644
index 00000000000..69e2de6f40b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.zerosize.stroke.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.gradient.interpolate.zerosize.stroke</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.gradient.interpolate.zerosize.stroke</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+var g = ctx.createLinearGradient(50, 25, 50, 25); // zero-length line (undefined direction)
+g.addColorStop(0, '#f00');
+g.addColorStop(1, '#f00');
+ctx.strokeStyle = g;
+ctx.rect(20, 20, 60, 10);
+ctx.stroke();
+_assertPixel(canvas, 19,19, 0,255,0,255, "19,19", "0,255,0,255");
+_assertPixel(canvas, 20,19, 0,255,0,255, "20,19", "0,255,0,255");
+_assertPixel(canvas, 21,19, 0,255,0,255, "21,19", "0,255,0,255");
+_assertPixel(canvas, 19,20, 0,255,0,255, "19,20", "0,255,0,255");
+_assertPixel(canvas, 20,20, 0,255,0,255, "20,20", "0,255,0,255");
+_assertPixel(canvas, 21,20, 0,255,0,255, "21,20", "0,255,0,255");
+_assertPixel(canvas, 19,21, 0,255,0,255, "19,21", "0,255,0,255");
+_assertPixel(canvas, 20,21, 0,255,0,255, "20,21", "0,255,0,255");
+_assertPixel(canvas, 21,21, 0,255,0,255, "21,21", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.zerosize.strokeRect.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.zerosize.strokeRect.html
new file mode 100644
index 00000000000..7eff74d80b3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.zerosize.strokeRect.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.gradient.interpolate.zerosize.strokeRect</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.gradient.interpolate.zerosize.strokeRect</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+var g = ctx.createLinearGradient(50, 25, 50, 25); // zero-length line (undefined direction)
+g.addColorStop(0, '#f00');
+g.addColorStop(1, '#f00');
+ctx.strokeStyle = g;
+ctx.strokeRect(20, 20, 60, 10);
+_assertPixel(canvas, 19,19, 0,255,0,255, "19,19", "0,255,0,255");
+_assertPixel(canvas, 20,19, 0,255,0,255, "20,19", "0,255,0,255");
+_assertPixel(canvas, 21,19, 0,255,0,255, "21,19", "0,255,0,255");
+_assertPixel(canvas, 19,20, 0,255,0,255, "19,20", "0,255,0,255");
+_assertPixel(canvas, 20,20, 0,255,0,255, "20,20", "0,255,0,255");
+_assertPixel(canvas, 21,20, 0,255,0,255, "21,20", "0,255,0,255");
+_assertPixel(canvas, 19,21, 0,255,0,255, "19,21", "0,255,0,255");
+_assertPixel(canvas, 20,21, 0,255,0,255, "20,21", "0,255,0,255");
+_assertPixel(canvas, 21,21, 0,255,0,255, "21,21", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.zerosize.strokeText.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.zerosize.strokeText.html
new file mode 100644
index 00000000000..d384cc01d99
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.interpolate.zerosize.strokeText.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.gradient.interpolate.zerosize.strokeText</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.gradient.interpolate.zerosize.strokeText</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+var g = ctx.createLinearGradient(50, 25, 50, 25); // zero-length line (undefined direction)
+g.addColorStop(0, '#f00');
+g.addColorStop(1, '#f00');
+ctx.strokeStyle = g;
+ctx.font = '100px sans-serif';
+ctx.strokeText("AA", 0, 50);
+_assertGreen(ctx, 100, 50);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.linear.nonfinite.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.linear.nonfinite.html
new file mode 100644
index 00000000000..b60b304385e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.linear.nonfinite.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.gradient.linear.nonfinite</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.gradient.linear.nonfinite</h1>
+<p class="desc">createLinearGradient() throws TypeError if arguments are not finite</p>
+
+<p class="notes">Defined in "Web IDL" (draft)
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("createLinearGradient() throws TypeError if arguments are not finite");
+_addTest(function(canvas, ctx) {
+
+assert_throws(new TypeError(), function() { ctx.createLinearGradient(Infinity, 0, 1, 0); });
+assert_throws(new TypeError(), function() { ctx.createLinearGradient(-Infinity, 0, 1, 0); });
+assert_throws(new TypeError(), function() { ctx.createLinearGradient(NaN, 0, 1, 0); });
+assert_throws(new TypeError(), function() { ctx.createLinearGradient(0, Infinity, 1, 0); });
+assert_throws(new TypeError(), function() { ctx.createLinearGradient(0, -Infinity, 1, 0); });
+assert_throws(new TypeError(), function() { ctx.createLinearGradient(0, NaN, 1, 0); });
+assert_throws(new TypeError(), function() { ctx.createLinearGradient(0, 0, Infinity, 0); });
+assert_throws(new TypeError(), function() { ctx.createLinearGradient(0, 0, -Infinity, 0); });
+assert_throws(new TypeError(), function() { ctx.createLinearGradient(0, 0, NaN, 0); });
+assert_throws(new TypeError(), function() { ctx.createLinearGradient(0, 0, 1, Infinity); });
+assert_throws(new TypeError(), function() { ctx.createLinearGradient(0, 0, 1, -Infinity); });
+assert_throws(new TypeError(), function() { ctx.createLinearGradient(0, 0, 1, NaN); });
+assert_throws(new TypeError(), function() { ctx.createLinearGradient(Infinity, Infinity, 1, 0); });
+assert_throws(new TypeError(), function() { ctx.createLinearGradient(Infinity, Infinity, Infinity, 0); });
+assert_throws(new TypeError(), function() { ctx.createLinearGradient(Infinity, Infinity, Infinity, Infinity); });
+assert_throws(new TypeError(), function() { ctx.createLinearGradient(Infinity, Infinity, 1, Infinity); });
+assert_throws(new TypeError(), function() { ctx.createLinearGradient(Infinity, 0, Infinity, 0); });
+assert_throws(new TypeError(), function() { ctx.createLinearGradient(Infinity, 0, Infinity, Infinity); });
+assert_throws(new TypeError(), function() { ctx.createLinearGradient(Infinity, 0, 1, Infinity); });
+assert_throws(new TypeError(), function() { ctx.createLinearGradient(0, Infinity, Infinity, 0); });
+assert_throws(new TypeError(), function() { ctx.createLinearGradient(0, Infinity, Infinity, Infinity); });
+assert_throws(new TypeError(), function() { ctx.createLinearGradient(0, Infinity, 1, Infinity); });
+assert_throws(new TypeError(), function() { ctx.createLinearGradient(0, 0, Infinity, Infinity); });
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.linear.transform.1.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.linear.transform.1.html
new file mode 100644
index 00000000000..3a4d24a3980
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.linear.transform.1.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.gradient.linear.transform.1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.gradient.linear.transform.1</h1>
+<p class="desc">Linear gradient coordinates are relative to the coordinate space at the time of filling</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Linear gradient coordinates are relative to the coordinate space at the time of filling");
+_addTest(function(canvas, ctx) {
+
+var g = ctx.createLinearGradient(0, 0, 200, 0);
+g.addColorStop(0, '#f00');
+g.addColorStop(0.25, '#0f0');
+g.addColorStop(0.75, '#0f0');
+g.addColorStop(1, '#f00');
+ctx.fillStyle = g;
+ctx.translate(-50, 0);
+ctx.fillRect(50, 0, 100, 50);
+_assertPixel(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255");
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.linear.transform.2.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.linear.transform.2.html
new file mode 100644
index 00000000000..56957a0a295
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.linear.transform.2.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.gradient.linear.transform.2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.gradient.linear.transform.2</h1>
+<p class="desc">Linear gradient coordinates are relative to the coordinate space at the time of filling</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Linear gradient coordinates are relative to the coordinate space at the time of filling");
+_addTest(function(canvas, ctx) {
+
+ctx.translate(100, 0);
+var g = ctx.createLinearGradient(0, 0, 200, 0);
+g.addColorStop(0, '#f00');
+g.addColorStop(0.25, '#0f0');
+g.addColorStop(0.75, '#0f0');
+g.addColorStop(1, '#f00');
+ctx.fillStyle = g;
+ctx.translate(-150, 0);
+ctx.fillRect(50, 0, 100, 50);
+_assertPixel(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255");
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.linear.transform.3.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.linear.transform.3.html
new file mode 100644
index 00000000000..6cc2ead2f5b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.linear.transform.3.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.gradient.linear.transform.3</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.gradient.linear.transform.3</h1>
+<p class="desc">Linear gradient transforms do not experience broken caching effects</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Linear gradient transforms do not experience broken caching effects");
+_addTest(function(canvas, ctx) {
+
+var g = ctx.createLinearGradient(0, 0, 200, 0);
+g.addColorStop(0, '#f00');
+g.addColorStop(0.25, '#0f0');
+g.addColorStop(0.75, '#0f0');
+g.addColorStop(1, '#f00');
+ctx.fillStyle = g;
+ctx.fillRect(0, 0, 100, 50);
+ctx.translate(-50, 0);
+ctx.fillRect(50, 0, 100, 50);
+_assertPixel(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255");
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.object.compare.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.object.compare.html
new file mode 100644
index 00000000000..67089a073d6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.object.compare.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.gradient.object.compare</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.gradient.object.compare</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+var g1 = ctx.createLinearGradient(0, 0, 100, 0);
+var g2 = ctx.createLinearGradient(0, 0, 100, 0);
+_assertDifferent(g1, g2, "g1", "g2");
+ctx.fillStyle = g1;
+_assertSame(ctx.fillStyle, g1, "ctx.fillStyle", "g1");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.object.crosscanvas.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.object.crosscanvas.html
new file mode 100644
index 00000000000..95144c6afdd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.object.crosscanvas.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.gradient.object.crosscanvas</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.gradient.object.crosscanvas</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+var g = document.createElement('canvas').getContext('2d').createLinearGradient(0, 0, 100, 0);
+g.addColorStop(0, '#0f0');
+g.addColorStop(1, '#0f0');
+ctx.fillStyle = g;
+ctx.fillRect(0, 0, 100, 50);
+_assertPixelApprox(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 2);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.object.current.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.object.current.html
new file mode 100644
index 00000000000..35709cbd1da
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.object.current.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.gradient.object.current</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.gradient.object.current</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.gradient.object.current.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+canvas.setAttribute('style', 'color: #f00');
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+var g = ctx.createLinearGradient(0, 0, 100, 0);
+g.addColorStop(0, 'currentColor');
+g.addColorStop(1, 'currentColor');
+ctx.fillStyle = g;
+ctx.fillRect(0, 0, 100, 50);
+_assertPixelApprox(canvas, 50,25, 0,0,0,255, "50,25", "0,0,0,255", 2);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.object.current.png b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.object.current.png
new file mode 100644
index 00000000000..d638d033868
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.object.current.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.object.invalidcolour.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.object.invalidcolour.html
new file mode 100644
index 00000000000..7687d0b94ea
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.object.invalidcolour.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.gradient.object.invalidcolour</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.gradient.object.invalidcolour</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+var g = ctx.createLinearGradient(0, 0, 100, 0);
+assert_throws("SYNTAX_ERR", function() { g.addColorStop(0, ""); });
+assert_throws("SYNTAX_ERR", function() { g.addColorStop(0, 'null'); });
+assert_throws("SYNTAX_ERR", function() { g.addColorStop(0, 'undefined'); });
+assert_throws("SYNTAX_ERR", function() { g.addColorStop(0, null); });
+assert_throws("SYNTAX_ERR", function() { g.addColorStop(0, undefined); });
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.object.invalidoffset.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.object.invalidoffset.html
new file mode 100644
index 00000000000..60071f6dc89
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.object.invalidoffset.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.gradient.object.invalidoffset</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.gradient.object.invalidoffset</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+var g = ctx.createLinearGradient(0, 0, 100, 0);
+assert_throws("INDEX_SIZE_ERR", function() { g.addColorStop(-1, '#000'); });
+assert_throws("INDEX_SIZE_ERR", function() { g.addColorStop(2, '#000'); });
+assert_throws("INDEX_SIZE_ERR", function() { g.addColorStop(Infinity, '#000'); });
+assert_throws("INDEX_SIZE_ERR", function() { g.addColorStop(-Infinity, '#000'); });
+assert_throws("INDEX_SIZE_ERR", function() { g.addColorStop(NaN, '#000'); });
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.object.return.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.object.return.html
new file mode 100644
index 00000000000..bcb4dc7af46
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.object.return.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.gradient.object.return</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.gradient.object.return</h1>
+<p class="desc">createLinearGradient() and createRadialGradient() returns objects implementing CanvasGradient</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("createLinearGradient() and createRadialGradient() returns objects implementing CanvasGradient");
+_addTest(function(canvas, ctx) {
+
+window.CanvasGradient.prototype.thisImplementsCanvasGradient = true;
+
+var g1 = ctx.createLinearGradient(0, 0, 100, 0);
+_assertDifferent(g1.addColorStop, undefined, "g1.addColorStop", "undefined");
+_assertSame(g1.thisImplementsCanvasGradient, true, "g1.thisImplementsCanvasGradient", "true");
+
+var g2 = ctx.createRadialGradient(0, 0, 10, 0, 0, 20);
+_assertDifferent(g2.addColorStop, undefined, "g2.addColorStop", "undefined");
+_assertSame(g2.thisImplementsCanvasGradient, true, "g2.thisImplementsCanvasGradient", "true");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.object.type.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.object.type.html
new file mode 100644
index 00000000000..27c91312c6a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.object.type.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.gradient.object.type</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.gradient.object.type</h1>
+<p class="desc">window.CanvasGradient exists and has the right properties</p>
+
+<p class="notes">Defined in "Web IDL" (draft)
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("window.CanvasGradient exists and has the right properties");
+_addTest(function(canvas, ctx) {
+
+_assertDifferent(window.CanvasGradient, undefined, "window.CanvasGradient", "undefined");
+_assertDifferent(window.CanvasGradient.prototype.addColorStop, undefined, "window.CanvasGradient.prototype.addColorStop", "undefined");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.object.update.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.object.update.html
new file mode 100644
index 00000000000..8151c42f954
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.object.update.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.gradient.object.update</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.gradient.object.update</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+var g = ctx.createLinearGradient(-100, 0, 200, 0);
+g.addColorStop(0, '#f00');
+g.addColorStop(1, '#f00');
+ctx.fillStyle = g;
+g.addColorStop(0.1, '#0f0');
+g.addColorStop(0.9, '#0f0');
+ctx.fillRect(0, 0, 100, 50);
+_assertPixelApprox(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 2);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.cone.behind.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.cone.behind.html
new file mode 100644
index 00000000000..5bf367ea09f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.cone.behind.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.gradient.radial.cone.behind</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.gradient.radial.cone.behind</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+var g = ctx.createRadialGradient(120, 25, 10, 211, 25, 100);
+g.addColorStop(0, '#f00');
+g.addColorStop(1, '#f00');
+ctx.fillStyle = g;
+ctx.fillRect(0, 0, 100, 50);
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 50,1, 0,255,0,255, "50,1", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 1,25, 0,255,0,255, "1,25", "0,255,0,255");
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 98,25, 0,255,0,255, "98,25", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 50,48, 0,255,0,255, "50,48", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.cone.beside.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.cone.beside.html
new file mode 100644
index 00000000000..6c7dbaa2ab5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.cone.beside.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.gradient.radial.cone.beside</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.gradient.radial.cone.beside</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+var g = ctx.createRadialGradient(0, 100, 40, 100, 100, 50);
+g.addColorStop(0, '#f00');
+g.addColorStop(1, '#f00');
+ctx.fillStyle = g;
+ctx.fillRect(0, 0, 100, 50);
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 50,1, 0,255,0,255, "50,1", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 1,25, 0,255,0,255, "1,25", "0,255,0,255");
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 98,25, 0,255,0,255, "98,25", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 50,48, 0,255,0,255, "50,48", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.cone.bottom.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.cone.bottom.html
new file mode 100644
index 00000000000..362d232935c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.cone.bottom.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.gradient.radial.cone.bottom</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.gradient.radial.cone.bottom</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+var g = ctx.createRadialGradient(210, 25, 100, 230, 25, 101);
+g.addColorStop(0, '#0f0');
+g.addColorStop(1, '#f00');
+ctx.fillStyle = g;
+ctx.fillRect(0, 0, 100, 50);
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 50,1, 0,255,0,255, "50,1", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 1,25, 0,255,0,255, "1,25", "0,255,0,255");
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 98,25, 0,255,0,255, "98,25", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 50,48, 0,255,0,255, "50,48", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.cone.cylinder.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.cone.cylinder.html
new file mode 100644
index 00000000000..a2f189d83f9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.cone.cylinder.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.gradient.radial.cone.cylinder</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.gradient.radial.cone.cylinder</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+var g = ctx.createRadialGradient(210, 25, 100, 230, 25, 100);
+g.addColorStop(0, '#0f0');
+g.addColorStop(1, '#f00');
+ctx.fillStyle = g;
+ctx.fillRect(0, 0, 100, 50);
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 50,1, 0,255,0,255, "50,1", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 1,25, 0,255,0,255, "1,25", "0,255,0,255");
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 98,25, 0,255,0,255, "98,25", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 50,48, 0,255,0,255, "50,48", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.cone.front.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.cone.front.html
new file mode 100644
index 00000000000..3ed6190b24c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.cone.front.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.gradient.radial.cone.front</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.gradient.radial.cone.front</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+var g = ctx.createRadialGradient(311, 25, 10, 210, 25, 100);
+g.addColorStop(0, '#f00');
+g.addColorStop(1, '#0f0');
+ctx.fillStyle = g;
+ctx.fillRect(0, 0, 100, 50);
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 50,1, 0,255,0,255, "50,1", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 1,25, 0,255,0,255, "1,25", "0,255,0,255");
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 98,25, 0,255,0,255, "98,25", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 50,48, 0,255,0,255, "50,48", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.cone.shape1.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.cone.shape1.html
new file mode 100644
index 00000000000..992c068055c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.cone.shape1.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.gradient.radial.cone.shape1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.gradient.radial.cone.shape1</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+var tol = 1; // tolerance to avoid antialiasing artifacts
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.fillStyle = '#f00';
+ctx.beginPath();
+ctx.moveTo(30+tol, 40);
+ctx.lineTo(110, -20+tol);
+ctx.lineTo(110, 100-tol);
+ctx.fill();
+
+var g = ctx.createRadialGradient(30+10*5/2, 40, 10*3/2, 30+10*15/4, 40, 10*9/4);
+g.addColorStop(0, '#0f0');
+g.addColorStop(1, '#0f0');
+ctx.fillStyle = g;
+ctx.fillRect(0, 0, 100, 50);
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 50,1, 0,255,0,255, "50,1", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 1,25, 0,255,0,255, "1,25", "0,255,0,255");
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 98,25, 0,255,0,255, "98,25", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 50,48, 0,255,0,255, "50,48", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.cone.shape2.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.cone.shape2.html
new file mode 100644
index 00000000000..cf9bd6d4290
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.cone.shape2.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.gradient.radial.cone.shape2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.gradient.radial.cone.shape2</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+var tol = 1; // tolerance to avoid antialiasing artifacts
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+var g = ctx.createRadialGradient(30+10*5/2, 40, 10*3/2, 30+10*15/4, 40, 10*9/4);
+g.addColorStop(0, '#f00');
+g.addColorStop(1, '#f00');
+ctx.fillStyle = g;
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.fillStyle = '#0f0';
+ctx.beginPath();
+ctx.moveTo(30-tol, 40);
+ctx.lineTo(110, -20-tol);
+ctx.lineTo(110, 100+tol);
+ctx.fill();
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 50,1, 0,255,0,255, "50,1", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 1,25, 0,255,0,255, "1,25", "0,255,0,255");
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 98,25, 0,255,0,255, "98,25", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 50,48, 0,255,0,255, "50,48", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.cone.top.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.cone.top.html
new file mode 100644
index 00000000000..fa60a0cfc14
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.cone.top.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.gradient.radial.cone.top</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.gradient.radial.cone.top</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+var g = ctx.createRadialGradient(230, 25, 100, 100, 25, 101);
+g.addColorStop(0, '#f00');
+g.addColorStop(1, '#0f0');
+ctx.fillStyle = g;
+ctx.fillRect(0, 0, 100, 50);
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 50,1, 0,255,0,255, "50,1", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 1,25, 0,255,0,255, "1,25", "0,255,0,255");
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 98,25, 0,255,0,255, "98,25", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 50,48, 0,255,0,255, "50,48", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.equal.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.equal.html
new file mode 100644
index 00000000000..f96b9761cf2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.equal.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.gradient.radial.equal</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.gradient.radial.equal</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+var g = ctx.createRadialGradient(50, 25, 20, 50, 25, 20);
+g.addColorStop(0, '#f00');
+g.addColorStop(1, '#f00');
+ctx.fillStyle = g;
+ctx.fillRect(0, 0, 100, 50);
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 50,1, 0,255,0,255, "50,1", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 1,25, 0,255,0,255, "1,25", "0,255,0,255");
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 98,25, 0,255,0,255, "98,25", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 50,48, 0,255,0,255, "50,48", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.inside1.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.inside1.html
new file mode 100644
index 00000000000..ab656ce2785
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.inside1.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.gradient.radial.inside1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.gradient.radial.inside1</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+var g = ctx.createRadialGradient(50, 25, 100, 50, 25, 200);
+g.addColorStop(0, '#0f0');
+g.addColorStop(1, '#f00');
+ctx.fillStyle = g;
+ctx.fillRect(0, 0, 100, 50);
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 50,1, 0,255,0,255, "50,1", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 1,25, 0,255,0,255, "1,25", "0,255,0,255");
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 98,25, 0,255,0,255, "98,25", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 50,48, 0,255,0,255, "50,48", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.inside2.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.inside2.html
new file mode 100644
index 00000000000..30f4c49b835
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.inside2.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.gradient.radial.inside2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.gradient.radial.inside2</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+var g = ctx.createRadialGradient(50, 25, 200, 50, 25, 100);
+g.addColorStop(0, '#f00');
+g.addColorStop(1, '#0f0');
+ctx.fillStyle = g;
+ctx.fillRect(0, 0, 100, 50);
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 50,1, 0,255,0,255, "50,1", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 1,25, 0,255,0,255, "1,25", "0,255,0,255");
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 98,25, 0,255,0,255, "98,25", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 50,48, 0,255,0,255, "50,48", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.inside3.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.inside3.html
new file mode 100644
index 00000000000..56c12a5b8e3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.inside3.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.gradient.radial.inside3</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.gradient.radial.inside3</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+var g = ctx.createRadialGradient(50, 25, 200, 50, 25, 100);
+g.addColorStop(0, '#f00');
+g.addColorStop(0.993, '#f00');
+g.addColorStop(1, '#0f0');
+ctx.fillStyle = g;
+ctx.fillRect(0, 0, 100, 50);
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 50,1, 0,255,0,255, "50,1", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 1,25, 0,255,0,255, "1,25", "0,255,0,255");
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 98,25, 0,255,0,255, "98,25", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 50,48, 0,255,0,255, "50,48", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.negative.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.negative.html
new file mode 100644
index 00000000000..29242165fd9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.negative.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.gradient.radial.negative</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.gradient.radial.negative</h1>
+<p class="desc">createRadialGradient() throws INDEX_SIZE_ERR if either radius is negative</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("createRadialGradient() throws INDEX_SIZE_ERR if either radius is negative");
+_addTest(function(canvas, ctx) {
+
+assert_throws("INDEX_SIZE_ERR", function() { ctx.createRadialGradient(0, 0, -0.1, 0, 0, 1); });
+assert_throws("INDEX_SIZE_ERR", function() { ctx.createRadialGradient(0, 0, 1, 0, 0, -0.1); });
+assert_throws("INDEX_SIZE_ERR", function() { ctx.createRadialGradient(0, 0, -0.1, 0, 0, -0.1); });
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.nonfinite.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.nonfinite.html
new file mode 100644
index 00000000000..e12d5142a25
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.nonfinite.html
@@ -0,0 +1,101 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.gradient.radial.nonfinite</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.gradient.radial.nonfinite</h1>
+<p class="desc">createRadialGradient() throws TypeError if arguments are not finite</p>
+
+<p class="notes">Defined in "Web IDL" (draft)
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("createRadialGradient() throws TypeError if arguments are not finite");
+_addTest(function(canvas, ctx) {
+
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(Infinity, 0, 1, 0, 0, 1); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(-Infinity, 0, 1, 0, 0, 1); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(NaN, 0, 1, 0, 0, 1); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(0, Infinity, 1, 0, 0, 1); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(0, -Infinity, 1, 0, 0, 1); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(0, NaN, 1, 0, 0, 1); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(0, 0, Infinity, 0, 0, 1); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(0, 0, -Infinity, 0, 0, 1); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(0, 0, NaN, 0, 0, 1); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(0, 0, 1, Infinity, 0, 1); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(0, 0, 1, -Infinity, 0, 1); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(0, 0, 1, NaN, 0, 1); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(0, 0, 1, 0, Infinity, 1); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(0, 0, 1, 0, -Infinity, 1); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(0, 0, 1, 0, NaN, 1); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(0, 0, 1, 0, 0, Infinity); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(0, 0, 1, 0, 0, -Infinity); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(0, 0, 1, 0, 0, NaN); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(Infinity, Infinity, 1, 0, 0, 1); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(Infinity, Infinity, Infinity, 0, 0, 1); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(Infinity, Infinity, Infinity, Infinity, 0, 1); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(Infinity, Infinity, Infinity, Infinity, Infinity, 1); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(Infinity, Infinity, Infinity, Infinity, Infinity, Infinity); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(Infinity, Infinity, Infinity, Infinity, 0, Infinity); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(Infinity, Infinity, Infinity, 0, Infinity, 1); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(Infinity, Infinity, Infinity, 0, Infinity, Infinity); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(Infinity, Infinity, Infinity, 0, 0, Infinity); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(Infinity, Infinity, 1, Infinity, 0, 1); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(Infinity, Infinity, 1, Infinity, Infinity, 1); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(Infinity, Infinity, 1, Infinity, Infinity, Infinity); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(Infinity, Infinity, 1, Infinity, 0, Infinity); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(Infinity, Infinity, 1, 0, Infinity, 1); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(Infinity, Infinity, 1, 0, Infinity, Infinity); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(Infinity, Infinity, 1, 0, 0, Infinity); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(Infinity, 0, Infinity, 0, 0, 1); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(Infinity, 0, Infinity, Infinity, 0, 1); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(Infinity, 0, Infinity, Infinity, Infinity, 1); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(Infinity, 0, Infinity, Infinity, Infinity, Infinity); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(Infinity, 0, Infinity, Infinity, 0, Infinity); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(Infinity, 0, Infinity, 0, Infinity, 1); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(Infinity, 0, Infinity, 0, Infinity, Infinity); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(Infinity, 0, Infinity, 0, 0, Infinity); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(Infinity, 0, 1, Infinity, 0, 1); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(Infinity, 0, 1, Infinity, Infinity, 1); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(Infinity, 0, 1, Infinity, Infinity, Infinity); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(Infinity, 0, 1, Infinity, 0, Infinity); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(Infinity, 0, 1, 0, Infinity, 1); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(Infinity, 0, 1, 0, Infinity, Infinity); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(Infinity, 0, 1, 0, 0, Infinity); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(0, Infinity, Infinity, 0, 0, 1); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(0, Infinity, Infinity, Infinity, 0, 1); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(0, Infinity, Infinity, Infinity, Infinity, 1); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(0, Infinity, Infinity, Infinity, Infinity, Infinity); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(0, Infinity, Infinity, Infinity, 0, Infinity); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(0, Infinity, Infinity, 0, Infinity, 1); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(0, Infinity, Infinity, 0, Infinity, Infinity); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(0, Infinity, Infinity, 0, 0, Infinity); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(0, Infinity, 1, Infinity, 0, 1); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(0, Infinity, 1, Infinity, Infinity, 1); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(0, Infinity, 1, Infinity, Infinity, Infinity); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(0, Infinity, 1, Infinity, 0, Infinity); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(0, Infinity, 1, 0, Infinity, 1); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(0, Infinity, 1, 0, Infinity, Infinity); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(0, Infinity, 1, 0, 0, Infinity); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(0, 0, Infinity, Infinity, 0, 1); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(0, 0, Infinity, Infinity, Infinity, 1); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(0, 0, Infinity, Infinity, Infinity, Infinity); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(0, 0, Infinity, Infinity, 0, Infinity); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(0, 0, Infinity, 0, Infinity, 1); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(0, 0, Infinity, 0, Infinity, Infinity); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(0, 0, Infinity, 0, 0, Infinity); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(0, 0, 1, Infinity, Infinity, 1); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(0, 0, 1, Infinity, Infinity, Infinity); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(0, 0, 1, Infinity, 0, Infinity); });
+assert_throws(new TypeError(), function() { ctx.createRadialGradient(0, 0, 1, 0, Infinity, Infinity); });
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.outside1.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.outside1.html
new file mode 100644
index 00000000000..e2c68d66bd0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.outside1.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.gradient.radial.outside1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.gradient.radial.outside1</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+var g = ctx.createRadialGradient(200, 25, 10, 200, 25, 20);
+g.addColorStop(0, '#f00');
+g.addColorStop(1, '#0f0');
+ctx.fillStyle = g;
+ctx.fillRect(0, 0, 100, 50);
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 50,1, 0,255,0,255, "50,1", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 1,25, 0,255,0,255, "1,25", "0,255,0,255");
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 98,25, 0,255,0,255, "98,25", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 50,48, 0,255,0,255, "50,48", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.outside2.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.outside2.html
new file mode 100644
index 00000000000..254db4574b1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.outside2.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.gradient.radial.outside2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.gradient.radial.outside2</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+var g = ctx.createRadialGradient(200, 25, 20, 200, 25, 10);
+g.addColorStop(0, '#0f0');
+g.addColorStop(1, '#f00');
+ctx.fillStyle = g;
+ctx.fillRect(0, 0, 100, 50);
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 50,1, 0,255,0,255, "50,1", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 1,25, 0,255,0,255, "1,25", "0,255,0,255");
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 98,25, 0,255,0,255, "98,25", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 50,48, 0,255,0,255, "50,48", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.outside3.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.outside3.html
new file mode 100644
index 00000000000..4324bc717ba
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.outside3.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.gradient.radial.outside3</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.gradient.radial.outside3</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+var g = ctx.createRadialGradient(200, 25, 20, 200, 25, 10);
+g.addColorStop(0, '#0f0');
+g.addColorStop(0.001, '#f00');
+g.addColorStop(1, '#f00');
+ctx.fillStyle = g;
+ctx.fillRect(0, 0, 100, 50);
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 50,1, 0,255,0,255, "50,1", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 1,25, 0,255,0,255, "1,25", "0,255,0,255");
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 98,25, 0,255,0,255, "98,25", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 50,48, 0,255,0,255, "50,48", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.touch1.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.touch1.html
new file mode 100644
index 00000000000..5e42c4094ac
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.touch1.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.gradient.radial.touch1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.gradient.radial.touch1</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+var g = ctx.createRadialGradient(150, 25, 50, 200, 25, 100);
+g.addColorStop(0, '#f00');
+g.addColorStop(1, '#f00');
+ctx.fillStyle = g;
+ctx.fillRect(0, 0, 100, 50);
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 50,1, 0,255,0,255, "50,1", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 1,25, 0,255,0,255, "1,25", "0,255,0,255");
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 98,25, 0,255,0,255, "98,25", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 50,48, 0,255,0,255, "50,48", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.touch2.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.touch2.html
new file mode 100644
index 00000000000..37dfd5ea896
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.touch2.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.gradient.radial.touch2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.gradient.radial.touch2</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+var g = ctx.createRadialGradient(-80, 25, 70, 0, 25, 150);
+g.addColorStop(0, '#f00');
+g.addColorStop(0.01, '#0f0');
+g.addColorStop(0.99, '#0f0');
+g.addColorStop(1, '#f00');
+ctx.fillStyle = g;
+ctx.fillRect(0, 0, 100, 50);
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 50,1, 0,255,0,255, "50,1", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 1,25, 0,255,0,255, "1,25", "0,255,0,255");
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 98,25, 0,255,0,255, "98,25", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 50,48, 0,255,0,255, "50,48", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.touch3.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.touch3.html
new file mode 100644
index 00000000000..e401d19b4f6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.touch3.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.gradient.radial.touch3</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.gradient.radial.touch3</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+var g = ctx.createRadialGradient(120, -15, 25, 140, -30, 50);
+g.addColorStop(0, '#f00');
+g.addColorStop(1, '#f00');
+ctx.fillStyle = g;
+ctx.fillRect(0, 0, 100, 50);
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 50,1, 0,255,0,255, "50,1", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 1,25, 0,255,0,255, "1,25", "0,255,0,255");
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 98,25, 0,255,0,255, "98,25", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 50,48, 0,255,0,255, "50,48", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.transform.1.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.transform.1.html
new file mode 100644
index 00000000000..92355825e51
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.transform.1.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.gradient.radial.transform.1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.gradient.radial.transform.1</h1>
+<p class="desc">Radial gradient coordinates are relative to the coordinate space at the time of filling</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Radial gradient coordinates are relative to the coordinate space at the time of filling");
+_addTest(function(canvas, ctx) {
+
+var g = ctx.createRadialGradient(0, 0, 0, 0, 0, 11.2);
+g.addColorStop(0, '#0f0');
+g.addColorStop(0.5, '#0f0');
+g.addColorStop(0.51, '#f00');
+g.addColorStop(1, '#f00');
+ctx.fillStyle = g;
+ctx.translate(50, 25);
+ctx.scale(10, 10);
+ctx.fillRect(-5, -2.5, 10, 5);
+_assertPixel(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255");
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.transform.2.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.transform.2.html
new file mode 100644
index 00000000000..ce7841f3b0e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.transform.2.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.gradient.radial.transform.2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.gradient.radial.transform.2</h1>
+<p class="desc">Radial gradient coordinates are relative to the coordinate space at the time of filling</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Radial gradient coordinates are relative to the coordinate space at the time of filling");
+_addTest(function(canvas, ctx) {
+
+ctx.translate(100, 0);
+var g = ctx.createRadialGradient(0, 0, 0, 0, 0, 11.2);
+g.addColorStop(0, '#0f0');
+g.addColorStop(0.5, '#0f0');
+g.addColorStop(0.51, '#f00');
+g.addColorStop(1, '#f00');
+ctx.fillStyle = g;
+ctx.translate(-50, 25);
+ctx.scale(10, 10);
+ctx.fillRect(-5, -2.5, 10, 5);
+_assertPixel(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255");
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.transform.3.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.transform.3.html
new file mode 100644
index 00000000000..ee9e6303bc1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.gradient.radial.transform.3.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.gradient.radial.transform.3</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.gradient.radial.transform.3</h1>
+<p class="desc">Radial gradient transforms do not experience broken caching effects</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Radial gradient transforms do not experience broken caching effects");
+_addTest(function(canvas, ctx) {
+
+var g = ctx.createRadialGradient(0, 0, 0, 0, 0, 11.2);
+g.addColorStop(0, '#0f0');
+g.addColorStop(0.5, '#0f0');
+g.addColorStop(0.51, '#f00');
+g.addColorStop(1, '#f00');
+ctx.fillStyle = g;
+ctx.fillRect(0, 0, 100, 50);
+ctx.translate(50, 25);
+ctx.scale(10, 10);
+ctx.fillRect(-5, -2.5, 10, 5);
+_assertPixel(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255");
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.animated.gif.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.animated.gif.html
new file mode 100644
index 00000000000..c78ef377b8d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.animated.gif.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.pattern.animated.gif</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.pattern.animated.gif</h1>
+<p class="desc">createPattern() of an animated GIF draws the first frame</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("createPattern() of an animated GIF draws the first frame");
+_addTest(function(canvas, ctx) {
+
+deferTest();
+setTimeout(function () {
+ var pattern = ctx.createPattern(document.getElementById('anim-gr.gif'), 'repeat');
+ ctx.fillStyle = pattern;
+ ctx.fillRect(0, 0, 50, 50);
+ setTimeout(t.step_func_done(function () {
+ ctx.fillRect(50, 0, 50, 50);
+ _assertPixelApprox(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255", 2);
+ }), 250);
+}, 250);
+
+
+});
+</script>
+<img src="/images/anim-gr.gif" id="anim-gr.gif" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.basic.canvas.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.basic.canvas.html
new file mode 100644
index 00000000000..3bdc679c5f0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.basic.canvas.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.pattern.basic.canvas</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.pattern.basic.canvas</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+var canvas2 = document.createElement('canvas');
+canvas2.width = 100;
+canvas2.height = 50;
+var ctx2 = canvas2.getContext('2d');
+ctx2.fillStyle = '#0f0';
+ctx2.fillRect(0, 0, 100, 50);
+
+var pattern = ctx.createPattern(canvas2, 'no-repeat');
+ctx.fillStyle = pattern;
+ctx.fillRect(0, 0, 100, 50);
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 50,1, 0,255,0,255, "50,1", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 1,25, 0,255,0,255, "1,25", "0,255,0,255");
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 98,25, 0,255,0,255, "98,25", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 50,48, 0,255,0,255, "50,48", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.basic.image.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.basic.image.html
new file mode 100644
index 00000000000..9ae64e4f5b9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.basic.image.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.pattern.basic.image</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.pattern.basic.image</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+var img = document.getElementById('green.png');
+var pattern = ctx.createPattern(img, 'no-repeat');
+ctx.fillStyle = pattern;
+ctx.fillRect(0, 0, 100, 50);
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+<img src="/images/green.png" id="green.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.basic.nocontext.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.basic.nocontext.html
new file mode 100644
index 00000000000..a24958702b1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.basic.nocontext.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.pattern.basic.nocontext</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.pattern.basic.nocontext</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+var canvas2 = document.createElement('canvas');
+canvas2.width = 100;
+canvas2.height = 50;
+var pattern = ctx.createPattern(canvas2, 'no-repeat');
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.fillStyle = '#f00';
+ctx.fillStyle = pattern;
+ctx.fillRect(0, 0, 100, 50);
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.basic.type.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.basic.type.html
new file mode 100644
index 00000000000..07ca3992370
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.basic.type.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.pattern.basic.type</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.pattern.basic.type</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+_assertDifferent(window.CanvasPattern, undefined, "window.CanvasPattern", "undefined");
+
+window.CanvasPattern.prototype.thisImplementsCanvasPattern = true;
+
+var img = document.getElementById('green.png');
+var pattern = ctx.createPattern(img, 'no-repeat');
+_assert(pattern.thisImplementsCanvasPattern, "pattern.thisImplementsCanvasPattern");
+
+
+});
+</script>
+<img src="/images/green.png" id="green.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.basic.zerocanvas.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.basic.zerocanvas.html
new file mode 100644
index 00000000000..aa393b8f7a3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.basic.zerocanvas.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.pattern.basic.zerocanvas</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.pattern.basic.zerocanvas</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+canvas.width = 0;
+canvas.height = 10;
+_assertSame(canvas.width, 0, "canvas.width", "0");
+_assertSame(canvas.height, 10, "canvas.height", "10");
+assert_throws("INVALID_STATE_ERR", function() { ctx.createPattern(canvas, 'repeat'); });
+
+canvas.width = 10;
+canvas.height = 0;
+_assertSame(canvas.width, 10, "canvas.width", "10");
+_assertSame(canvas.height, 0, "canvas.height", "0");
+assert_throws("INVALID_STATE_ERR", function() { ctx.createPattern(canvas, 'repeat'); });
+
+canvas.width = 0;
+canvas.height = 0;
+_assertSame(canvas.width, 0, "canvas.width", "0");
+_assertSame(canvas.height, 0, "canvas.height", "0");
+assert_throws("INVALID_STATE_ERR", function() { ctx.createPattern(canvas, 'repeat'); });
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.crosscanvas.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.crosscanvas.html
new file mode 100644
index 00000000000..dc80720bb7c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.crosscanvas.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.pattern.crosscanvas</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.pattern.crosscanvas</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+var img = document.getElementById('green.png');
+
+var pattern = document.createElement('canvas').getContext('2d').createPattern(img, 'no-repeat');
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.fillStyle = pattern;
+ctx.fillRect(0, 0, 100, 50);
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+<img src="/images/green.png" id="green.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.image.broken.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.image.broken.html
new file mode 100644
index 00000000000..31c8e8f2ab0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.image.broken.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.pattern.image.broken</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.pattern.image.broken</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+var img = document.getElementById('broken.png');
+assert_throws("INVALID_STATE_ERR", function() { ctx.createPattern(img, 'repeat'); });
+
+
+});
+</script>
+<img src="/images/broken.png" id="broken.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.image.incomplete.emptysrc.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.image.incomplete.emptysrc.html
new file mode 100644
index 00000000000..23f453ac1de
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.image.incomplete.emptysrc.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.pattern.image.incomplete.emptysrc</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.pattern.image.incomplete.emptysrc</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+var img = document.getElementById('red.png');
+img.src = "";
+_assertSame(ctx.createPattern(img, 'repeat'), null, "ctx.createPattern(img, 'repeat')", "null");
+
+
+});
+</script>
+<img src="/images/red.png" id="red.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.image.incomplete.immediate.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.image.incomplete.immediate.html
new file mode 100644
index 00000000000..176cf722ae9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.image.incomplete.immediate.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.pattern.image.incomplete.immediate</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.pattern.image.incomplete.immediate</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+var img = new Image();
+img.src = '../images/red.png';
+// This triggers the "update the image data" algorithm.
+// The image will not go to the "completely available" state
+// until a fetch task in the networking task source is processed,
+// so the image must not be fully decodable yet:
+_assertSame(ctx.createPattern(img, 'repeat'), null, "ctx.createPattern(img, 'repeat')", "null");
+
+
+});
+</script>
+<img src="/images/red.png" id="red.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.image.incomplete.nosrc.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.image.incomplete.nosrc.html
new file mode 100644
index 00000000000..88b8801b285
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.image.incomplete.nosrc.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.pattern.image.incomplete.nosrc</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.pattern.image.incomplete.nosrc</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+var img = new Image();
+_assertSame(ctx.createPattern(img, 'repeat'), null, "ctx.createPattern(img, 'repeat')", "null");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.image.incomplete.reload.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.image.incomplete.reload.html
new file mode 100644
index 00000000000..095055c21e0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.image.incomplete.reload.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.pattern.image.incomplete.reload</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.pattern.image.incomplete.reload</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+var img = document.getElementById('yellow.png');
+img.src = '../images/red.png';
+// This triggers the "update the image data" algorithm,
+// and resets the image to the "unavailable" state.
+// The image will not go to the "completely available" state
+// until a fetch task in the networking task source is processed,
+// so the image must not be fully decodable yet:
+_assertSame(ctx.createPattern(img, 'repeat'), null, "ctx.createPattern(img, 'repeat')", "null");
+
+
+});
+</script>
+<img src="/images/yellow.png" id="yellow.png" class="resource">
+<img src="/images/red.png" id="red.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.image.incomplete.removedsrc.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.image.incomplete.removedsrc.html
new file mode 100644
index 00000000000..514f0609c9d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.image.incomplete.removedsrc.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.pattern.image.incomplete.removedsrc</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.pattern.image.incomplete.removedsrc</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+var img = document.getElementById('red.png');
+img.removeAttribute('src');
+_assertSame(ctx.createPattern(img, 'repeat'), null, "ctx.createPattern(img, 'repeat')", "null");
+
+
+});
+</script>
+<img src="/images/red.png" id="red.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.image.null.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.image.null.html
new file mode 100644
index 00000000000..5b8c688175c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.image.null.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.pattern.image.null</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.pattern.image.null</h1>
+<p class="desc"></p>
+
+<p class="notes">Defined in "Web IDL" (draft)
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+assert_throws(new TypeError(), function() { ctx.createPattern(null, 'repeat'); });
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.image.string.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.image.string.html
new file mode 100644
index 00000000000..834d9218752
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.image.string.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.pattern.image.string</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.pattern.image.string</h1>
+<p class="desc"></p>
+
+<p class="notes">Defined in "Web IDL" (draft)
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+assert_throws(new TypeError(), function() { ctx.createPattern('../images/red.png', 'repeat'); });
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.image.undefined.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.image.undefined.html
new file mode 100644
index 00000000000..24f650d9707
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.image.undefined.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.pattern.image.undefined</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.pattern.image.undefined</h1>
+<p class="desc"></p>
+
+<p class="notes">Defined in "Web IDL" (draft)
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+assert_throws(new TypeError(), function() { ctx.createPattern(undefined, 'repeat'); });
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.modify.canvas1.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.modify.canvas1.html
new file mode 100644
index 00000000000..f60da5bac05
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.modify.canvas1.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.pattern.modify.canvas1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.pattern.modify.canvas1</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+var canvas2 = document.createElement('canvas');
+canvas2.width = 100;
+canvas2.height = 50;
+var ctx2 = canvas2.getContext('2d');
+ctx2.fillStyle = '#0f0';
+ctx2.fillRect(0, 0, 100, 50);
+
+var pattern = ctx.createPattern(canvas2, 'no-repeat');
+
+ctx2.fillStyle = '#f00';
+ctx2.fillRect(0, 0, 100, 50);
+
+ctx.fillStyle = pattern;
+ctx.fillRect(0, 0, 100, 50);
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.modify.canvas2.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.modify.canvas2.html
new file mode 100644
index 00000000000..db7a8b8423e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.modify.canvas2.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.pattern.modify.canvas2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.pattern.modify.canvas2</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+var canvas2 = document.createElement('canvas');
+canvas2.width = 100;
+canvas2.height = 50;
+var ctx2 = canvas2.getContext('2d');
+ctx2.fillStyle = '#0f0';
+ctx2.fillRect(0, 0, 100, 50);
+
+var pattern = ctx.createPattern(canvas2, 'no-repeat');
+ctx.fillStyle = pattern;
+ctx.fillRect(0, 0, 100, 50);
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx2.fillStyle = '#f00';
+ctx2.fillRect(0, 0, 100, 50);
+
+ctx.fillStyle = pattern;
+ctx.fillRect(0, 0, 100, 50);
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.modify.image1.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.modify.image1.html
new file mode 100644
index 00000000000..cfc8a965dfc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.modify.image1.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.pattern.modify.image1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.pattern.modify.image1</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+var img = document.getElementById('green.png');
+var pattern = ctx.createPattern(img, 'no-repeat');
+deferTest();
+img.onload = t.step_func_done(function ()
+{
+ ctx.fillStyle = pattern;
+ ctx.fillRect(0, 0, 100, 50);
+
+ _assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+ _assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+ _assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+ _assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+});
+img.src = '/images/red.png';
+
+
+});
+</script>
+<img src="/images/green.png" id="green.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.modify.image2.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.modify.image2.html
new file mode 100644
index 00000000000..c7f2ee3bff1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.modify.image2.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.pattern.modify.image2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.pattern.modify.image2</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+var img = document.getElementById('green.png');
+var pattern = ctx.createPattern(img, 'no-repeat');
+ctx.fillStyle = pattern;
+ctx.fillRect(0, 0, 100, 50);
+ctx.fillStyle = '#00f';
+ctx.fillRect(0, 0, 100, 50);
+deferTest();
+img.onload = t.step_func_done(function ()
+{
+ ctx.fillStyle = pattern;
+ ctx.fillRect(0, 0, 100, 50);
+
+ _assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+ _assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+ _assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+ _assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+});
+img.src = '/images/red.png';
+
+
+});
+</script>
+<img src="/images/green.png" id="green.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.norepeat.basic.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.norepeat.basic.html
new file mode 100644
index 00000000000..431437e5bf1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.norepeat.basic.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.pattern.paint.norepeat.basic</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.pattern.paint.norepeat.basic</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+var img = document.getElementById('green.png');
+var pattern = ctx.createPattern(img, 'no-repeat');
+ctx.fillStyle = pattern;
+ctx.fillRect(0, 0, 100, 50);
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+<img src="/images/green.png" id="green.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.norepeat.coord1.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.norepeat.coord1.html
new file mode 100644
index 00000000000..a560fd8dcad
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.norepeat.coord1.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.pattern.paint.norepeat.coord1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.pattern.paint.norepeat.coord1</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 50, 50);
+ctx.fillStyle = '#f00';
+ctx.fillRect(50, 0, 50, 50);
+
+var img = document.getElementById('green.png');
+var pattern = ctx.createPattern(img, 'no-repeat');
+ctx.fillStyle = pattern;
+ctx.translate(50, 0);
+ctx.fillRect(-50, 0, 100, 50);
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+<img src="/images/green.png" id="green.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.norepeat.coord2.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.norepeat.coord2.html
new file mode 100644
index 00000000000..9ae28987238
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.norepeat.coord2.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.pattern.paint.norepeat.coord2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.pattern.paint.norepeat.coord2</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+var img = document.getElementById('green.png');
+var pattern = ctx.createPattern(img, 'no-repeat');
+ctx.fillStyle = pattern;
+ctx.fillRect(0, 0, 50, 50);
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(50, 0, 50, 50);
+
+ctx.fillStyle = pattern;
+ctx.translate(50, 0);
+ctx.fillRect(-50, 0, 100, 50);
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+<img src="/images/green.png" id="green.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.norepeat.coord3.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.norepeat.coord3.html
new file mode 100644
index 00000000000..9c1b5ae6dce
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.norepeat.coord3.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.pattern.paint.norepeat.coord3</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.pattern.paint.norepeat.coord3</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+var img = document.getElementById('red.png');
+var pattern = ctx.createPattern(img, 'no-repeat');
+ctx.fillStyle = pattern;
+ctx.translate(50, 25);
+ctx.fillRect(-50, -25, 100, 50);
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 50, 25);
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+<img src="/images/red.png" id="red.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.norepeat.outside.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.norepeat.outside.html
new file mode 100644
index 00000000000..3dce7a68625
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.norepeat.outside.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.pattern.paint.norepeat.outside</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.pattern.paint.norepeat.outside</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+var img = document.getElementById('red.png');
+var pattern = ctx.createPattern(img, 'no-repeat');
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.fillStyle = pattern;
+ctx.fillRect(0, -50, 100, 50);
+ctx.fillRect(-100, 0, 100, 50);
+ctx.fillRect(0, 50, 100, 50);
+ctx.fillRect(100, 0, 100, 50);
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+<img src="/images/red.png" id="red.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.orientation.canvas.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.orientation.canvas.html
new file mode 100644
index 00000000000..70966e00aa6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.orientation.canvas.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.pattern.paint.orientation.canvas</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.pattern.paint.orientation.canvas</h1>
+<p class="desc">Canvas patterns do not get flipped when painted</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Canvas patterns do not get flipped when painted");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+var canvas2 = document.createElement('canvas');
+canvas2.width = 100;
+canvas2.height = 50;
+var ctx2 = canvas2.getContext('2d');
+ctx2.fillStyle = '#f00';
+ctx2.fillRect(0, 0, 100, 25);
+ctx2.fillStyle = '#0f0';
+ctx2.fillRect(0, 25, 100, 25);
+
+var pattern = ctx.createPattern(canvas2, 'no-repeat');
+ctx.fillStyle = pattern;
+ctx.fillRect(0, 0, 100, 50);
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 25);
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.orientation.image.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.orientation.image.html
new file mode 100644
index 00000000000..7d109c55a28
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.orientation.image.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.pattern.paint.orientation.image</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.pattern.paint.orientation.image</h1>
+<p class="desc">Image patterns do not get flipped when painted</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Image patterns do not get flipped when painted");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+var img = document.getElementById('rrgg-256x256.png');
+var pattern = ctx.createPattern(img, 'no-repeat');
+ctx.fillStyle = pattern;
+ctx.save();
+ctx.translate(0, -103);
+ctx.fillRect(0, 103, 100, 50);
+ctx.restore();
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 25);
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+<img src="/images/rrgg-256x256.png" id="rrgg-256x256.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.repeat.basic.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.repeat.basic.html
new file mode 100644
index 00000000000..501fe67e48e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.repeat.basic.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.pattern.paint.repeat.basic</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.pattern.paint.repeat.basic</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+var img = document.getElementById('green-16x16.png');
+var pattern = ctx.createPattern(img, 'repeat');
+ctx.fillStyle = pattern;
+ctx.fillRect(0, 0, 100, 50);
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+<img src="/images/green-16x16.png" id="green-16x16.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.repeat.coord1.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.repeat.coord1.html
new file mode 100644
index 00000000000..4aa75d15579
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.repeat.coord1.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.pattern.paint.repeat.coord1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.pattern.paint.repeat.coord1</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+var img = document.getElementById('rgrg-256x256.png');
+var pattern = ctx.createPattern(img, 'repeat');
+ctx.fillStyle = pattern;
+ctx.translate(-128, -78);
+ctx.fillRect(128, 78, 100, 50);
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+<img src="/images/rgrg-256x256.png" id="rgrg-256x256.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.repeat.coord2.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.repeat.coord2.html
new file mode 100644
index 00000000000..0fe8b6a5605
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.repeat.coord2.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.pattern.paint.repeat.coord2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.pattern.paint.repeat.coord2</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+var img = document.getElementById('ggrr-256x256.png');
+var pattern = ctx.createPattern(img, 'repeat');
+ctx.fillStyle = pattern;
+ctx.fillRect(0, 0, 100, 50);
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+<img src="/images/ggrr-256x256.png" id="ggrr-256x256.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.repeat.coord3.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.repeat.coord3.html
new file mode 100644
index 00000000000..b361c91f233
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.repeat.coord3.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.pattern.paint.repeat.coord3</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.pattern.paint.repeat.coord3</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+var img = document.getElementById('rgrg-256x256.png');
+var pattern = ctx.createPattern(img, 'repeat');
+ctx.fillStyle = pattern;
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.translate(-128, -78);
+ctx.fillRect(128, 78, 100, 50);
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+<img src="/images/rgrg-256x256.png" id="rgrg-256x256.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.repeat.outside.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.repeat.outside.html
new file mode 100644
index 00000000000..68d2fe84ee0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.repeat.outside.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.pattern.paint.repeat.outside</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.pattern.paint.repeat.outside</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+var img = document.getElementById('green-16x16.png');
+var pattern = ctx.createPattern(img, 'repeat');
+ctx.fillStyle = pattern;
+ctx.translate(50, 25);
+ctx.fillRect(-50, -25, 100, 50);
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+<img src="/images/green-16x16.png" id="green-16x16.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.repeatx.basic.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.repeatx.basic.html
new file mode 100644
index 00000000000..3cec292a4d6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.repeatx.basic.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.pattern.paint.repeatx.basic</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.pattern.paint.repeatx.basic</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 16);
+
+var img = document.getElementById('green-16x16.png');
+var pattern = ctx.createPattern(img, 'repeat-x');
+ctx.fillStyle = pattern;
+ctx.fillRect(0, 0, 100, 50);
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+<img src="/images/green-16x16.png" id="green-16x16.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.repeatx.coord1.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.repeatx.coord1.html
new file mode 100644
index 00000000000..1e864a729ae
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.repeatx.coord1.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.pattern.paint.repeatx.coord1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.pattern.paint.repeatx.coord1</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+var img = document.getElementById('red-16x16.png');
+var pattern = ctx.createPattern(img, 'repeat-x');
+ctx.fillStyle = pattern;
+ctx.translate(0, 16);
+ctx.fillRect(0, -16, 100, 50);
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 16);
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 1,25, 0,255,0,255, "1,25", "0,255,0,255");
+_assertPixel(canvas, 98,25, 0,255,0,255, "98,25", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+<img src="/images/red-16x16.png" id="red-16x16.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.repeatx.outside.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.repeatx.outside.html
new file mode 100644
index 00000000000..074c4afa446
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.repeatx.outside.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.pattern.paint.repeatx.outside</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.pattern.paint.repeatx.outside</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+var img = document.getElementById('red-16x16.png');
+var pattern = ctx.createPattern(img, 'repeat-x');
+ctx.fillStyle = pattern;
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 16);
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+<img src="/images/red-16x16.png" id="red-16x16.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.repeaty.basic.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.repeaty.basic.html
new file mode 100644
index 00000000000..0da99d28df1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.repeaty.basic.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.pattern.paint.repeaty.basic</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.pattern.paint.repeaty.basic</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 16, 50);
+
+var img = document.getElementById('green-16x16.png');
+var pattern = ctx.createPattern(img, 'repeat-y');
+ctx.fillStyle = pattern;
+ctx.fillRect(0, 0, 100, 50);
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+<img src="/images/green-16x16.png" id="green-16x16.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.repeaty.coord1.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.repeaty.coord1.html
new file mode 100644
index 00000000000..2f42a4e2ddc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.repeaty.coord1.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.pattern.paint.repeaty.coord1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.pattern.paint.repeaty.coord1</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+var img = document.getElementById('red-16x16.png');
+var pattern = ctx.createPattern(img, 'repeat-y');
+ctx.fillStyle = pattern;
+ctx.translate(48, 0);
+ctx.fillRect(-48, 0, 100, 50);
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 16, 50);
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 50,1, 0,255,0,255, "50,1", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 50,48, 0,255,0,255, "50,48", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+<img src="/images/red-16x16.png" id="red-16x16.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.repeaty.outside.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.repeaty.outside.html
new file mode 100644
index 00000000000..9ec618a9dc1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.paint.repeaty.outside.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.pattern.paint.repeaty.outside</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.pattern.paint.repeaty.outside</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+var img = document.getElementById('red-16x16.png');
+var pattern = ctx.createPattern(img, 'repeat-y');
+ctx.fillStyle = pattern;
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 16, 50);
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+<img src="/images/red-16x16.png" id="red-16x16.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.repeat.case.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.repeat.case.html
new file mode 100644
index 00000000000..5a4bf344b83
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.repeat.case.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.pattern.repeat.case</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.pattern.repeat.case</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+assert_throws("SYNTAX_ERR", function() { ctx.createPattern(canvas, "Repeat"); });
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.repeat.empty.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.repeat.empty.html
new file mode 100644
index 00000000000..a7190872130
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.repeat.empty.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.pattern.repeat.empty</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.pattern.repeat.empty</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+var img = document.getElementById('green-1x1.png');
+var pattern = ctx.createPattern(img, "");
+ctx.fillStyle = pattern;
+ctx.fillRect(0, 0, 200, 50);
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+<img src="/images/green-1x1.png" id="green-1x1.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.repeat.null.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.repeat.null.html
new file mode 100644
index 00000000000..25caf6c2eb7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.repeat.null.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.pattern.repeat.null</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.pattern.repeat.null</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+_assert(ctx.createPattern(canvas, null) != null, "ctx.createPattern(canvas, null) != null");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.repeat.nullsuffix.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.repeat.nullsuffix.html
new file mode 100644
index 00000000000..37130420471
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.repeat.nullsuffix.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.pattern.repeat.nullsuffix</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.pattern.repeat.nullsuffix</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+assert_throws("SYNTAX_ERR", function() { ctx.createPattern(canvas, "repeat\0"); });
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.repeat.undefined.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.repeat.undefined.html
new file mode 100644
index 00000000000..74cd84b333b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.repeat.undefined.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.pattern.repeat.undefined</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.pattern.repeat.undefined</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+assert_throws("SYNTAX_ERR", function() { ctx.createPattern(canvas, undefined); });
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.repeat.unrecognised.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.repeat.unrecognised.html
new file mode 100644
index 00000000000..ff4d50a7337
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.repeat.unrecognised.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.pattern.repeat.unrecognised</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.pattern.repeat.unrecognised</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+assert_throws("SYNTAX_ERR", function() { ctx.createPattern(canvas, "invalid"); });
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.repeat.unrecognisednull.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.repeat.unrecognisednull.html
new file mode 100644
index 00000000000..57df03be6db
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.pattern.repeat.unrecognisednull.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.pattern.repeat.unrecognisednull</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.pattern.repeat.unrecognisednull</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+assert_throws("SYNTAX_ERR", function() { ctx.createPattern(canvas, "null"); });
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.strokeStyle.default.html b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.strokeStyle.default.html
new file mode 100644
index 00000000000..6e07d608601
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/2d.strokeStyle.default.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.strokeStyle.default</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.strokeStyle.default</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+_assertSame(ctx.strokeStyle, '#000000', "ctx.strokeStyle", "'#000000'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/canvas_colorsandstyles_createlineargradient_001.htm b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/canvas_colorsandstyles_createlineargradient_001.htm
new file mode 100644
index 00000000000..a1b9ca90b17
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/fill-and-stroke-styles/canvas_colorsandstyles_createlineargradient_001.htm
@@ -0,0 +1,35 @@
+<!doctype HTML>
+<html>
+ <head>
+ <title>HTML5 Canvas Test: createlinearGradient() with two points same</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com" />
+ <link rel="help" href="http://www.w3.org/TR/2dcontext/#dom-context-2d-createlineargradient" />
+ <meta name="assert" content="If the two points in a linear gradient have identical x,y coordinates, the canvas must paint nothing." />
+ <script type="text/javascript">
+ function runTest()
+ {
+ var canvas = document.getElementById("canvas1");
+ var ctx = canvas.getContext("2d");
+
+ // Start by drawing a left to right, green-to-blue linear gradient.
+ var lingrad = ctx.createLinearGradient(0, 50, 100, 50);
+ lingrad.addColorStop(0, "rgba(0, 255, 0, 1.0)");
+ lingrad.addColorStop(1, "rgba(0, 0, 255, 1.0)");
+ ctx.fillStyle = lingrad;
+ ctx.fillRect(0, 0, 100, 50);
+
+ // Nothing must be drawn if the two points in the linear gradient are the same.
+ lingrad = ctx.createLinearGradient(100, 100, 100, 100);
+ lingrad.addColorStop(0, "rgba(255, 0, 0, 1.0)");
+ lingrad.addColorStop(1, "rgba(255, 0, 0, 1.0)");
+ ctx.fillStyle = lingrad;
+ ctx.fillRect(0, 0, 300, 150);
+ }
+ </script>
+ </head>
+ <body onload="runTest()">
+ <p>Description: If the two points in a linear gradient have identical x,y coordinates, the canvas must paint nothing.</p>
+ <p>Test passes if there is one left-to-right, green-to-blue linear gradient seen on the page and no red is seen on the page.</p>
+ <canvas id="canvas1" width="300" height="150">Browser does not support HTML5 Canvas.</canvas>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/2dcontext/green-100x50.png b/tests/wpt/web-platform-tests/2dcontext/green-100x50.png
new file mode 100644
index 00000000000..2733836c998
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/green-100x50.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/hit-regions/.gitkeep b/tests/wpt/web-platform-tests/2dcontext/hit-regions/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/hit-regions/.gitkeep
diff --git a/tests/wpt/web-platform-tests/2dcontext/hit-regions/addHitRegions-NotSupportedError-01.html b/tests/wpt/web-platform-tests/2dcontext/hit-regions/addHitRegions-NotSupportedError-01.html
new file mode 100644
index 00000000000..05818aeb8bb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/hit-regions/addHitRegions-NotSupportedError-01.html
@@ -0,0 +1,89 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="UTF-8">
+<title>Hit regions: addHitRegion throws NotSupportedError</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id="log"></div>
+<div style="display: none"><canvas id="canvas"><button id="button">button</button></canvas></div>
+
+<script>
+test(function () {
+ assert_throws({ name: "NotSupportedError" },
+ function () {
+ var canvas = document.getElementById("canvas");
+ // Reset context
+ canvas.width = canvas.width;
+ var button = document.getElementById("button");
+ var context = canvas.getContext("2d");
+
+ // Shapes are painted without affecting the current default path,
+ // http://www.w3.org/html/wg/drafts/2dcontext/html5_canvas_CR/#drawing-rectangles-to-the-canvas
+ context.fillRect(25, 25, 25, 25);
+
+ // If the specified path has no pixels, throw a NotSupportedError exception and abort these steps.
+ // http://www.w3.org/html/wg/drafts/2dcontext/html5_canvas_CR/#hit-regions
+ context.addHitRegion({ id: "notsupportederror_fillRect", control: button })
+ }, "fillRect should not affect current default path and NotSupportedError should be thrown.");
+}, "fillRect should not affect current default path and NotSupportedError should be thrown.");
+
+test(function () {
+ assert_throws({ name: "NotSupportedError" },
+ function () {
+ var canvas = document.getElementById("canvas");
+ // Reset context
+ canvas.width = canvas.width;
+ var button = document.getElementById("button");
+ var context = canvas.getContext("2d");
+
+ // "Shapes are painted without affecting the current default path,"
+ // http://www.w3.org/html/wg/drafts/2dcontext/html5_canvas_CR/#drawing-rectangles-to-the-canvas
+ context.strokeRect(75, 25, 25, 25);
+
+ // "If the specified path has no pixels, throw a NotSupportedError exception and abort these steps."
+ // http://www.w3.org/html/wg/drafts/2dcontext/html5_canvas_CR/#hit-regions
+ context.addHitRegion({ id: "notsupportederror_strokeRect", control: button })
+ }, "strokeRect should not affect current default path and NotSupportedError should be thrown.");
+}, "strokeRect should not affect current default path and NotSupportedError should be thrown.");
+
+test(function() {
+ assert_throws({ name: "NotSupportedError" },
+ function () {
+ var canvas = document.getElementById("canvas");
+ // Reset context
+ canvas.width = canvas.width;
+ var button = document.getElementById("button");
+ var context = canvas.getContext("2d");
+
+ // "These shapes are painted without affecting the current path"
+ // http://www.w3.org/html/wg/drafts/2dcontext/html5_canvas_CR/#drawing-rectangles-to-the-canvas
+ context.fillText("fillText", 25, 100);
+
+ // "If the specified path has no pixels, throw a NotSupportedError exception and abort these steps."
+ // http://www.w3.org/html/wg/drafts/2dcontext/html5_canvas_CR/#drawing-text-to-the-canvas
+ context.addHitRegion({ id: "notsupportederror_fillText", control: button });
+ }, "fillText should not affect current default path and NotSupportedError should be thrown.");
+}, "fillText should not affect current default path and NotSupportedError should be thrown.");
+
+test(function() {
+ assert_throws({ name: "NotSupportedError" },
+ function () {
+ var canvas = document.getElementById("canvas");
+ canvas.width = canvas.width;
+ var button = document.getElementById("button");
+ var context = canvas.getContext("2d");
+ // "These shapes are painted without affecting the current path"
+ // http://www.w3.org/html/wg/drafts/2dcontext/html5_canvas_CR/#drawing-rectangles-to-the-canvas
+ context.strokeText("strokeText", 75, 100);
+
+ // "If the specified path has no pixels, throw a NotSupportedError exception and abort these steps."
+ // http://www.w3.org/html/wg/drafts/2dcontext/html5_canvas_CR/#drawing-text-to-the-canvas
+ context.addHitRegion({ id: "notsupportederror_strokeText", control: button });
+ }, "strokeText should not affect current default path and NotSupportedError shuld be thrown.");
+}, "strokeText should not affect current default path and NotSupportedError shuld be thrown.");
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/2dcontext/hit-regions/hitregions-members-exist.html b/tests/wpt/web-platform-tests/2dcontext/hit-regions/hitregions-members-exist.html
new file mode 100644
index 00000000000..b9203f56067
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/hit-regions/hitregions-members-exist.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Canvas test: 2d.hitregions.members.exist</title>
+<meta name="author" content="Constantine Kim">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+
+<h1>2d.hitregions.members.exist</h1>
+<canvas></canvas>
+<div id="log"></div>
+<script>
+test(function () {
+ var ctx = document.createElement('canvas').getContext('2d');
+ assert_equals(typeof ctx.addHitRegion, 'function');
+}, 'context.addHitRegion Exists');
+
+test(function () {
+ var ctx = document.createElement('canvas').getContext('2d');
+ assert_equals(typeof ctx.removeHitRegion, 'function');
+}, 'context.removeHitRegion Exists');
+
+test(function () {
+ var ctx = document.createElement('canvas').getContext('2d');
+ assert_equals(typeof ctx.clearHitRegions, 'function');
+}, 'context.clearHitRegions Exists');
+
+</script>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/2dcontext/image-smoothing/imagesmoothing.html b/tests/wpt/web-platform-tests/2dcontext/image-smoothing/imagesmoothing.html
new file mode 100644
index 00000000000..efd503cabf6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/image-smoothing/imagesmoothing.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>CanvasRenderingContext2D imageSmoothingEnabled test</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="stylesheet" href="/resources/testharness.css" media="all">
+ <link rel="author" title="ShinHyunjin" href="mailto:jini7927@gmail.com">
+ <link rel="help" href="http://www.w3.org/html/wg/drafts/2dcontext/html5_canvas/#image-smoothing">
+ </head>
+ <body>
+ <div id="log"></div>
+ <canvas id="test_canvas_1"></canvas>
+ <canvas id="test_canvas_2"></canvas>
+ <canvas id="test_canvas_3"></canvas>
+
+ <script>
+ (function() {
+ test(function() {
+ var canvas = document.getElementById('test_canvas_1');
+ var ctx = canvas.getContext('2d');
+
+ assert_true(ctx.imageSmoothingEnabled);
+ }, "When the CanvasRenderingContext2D object is created, the attribute must be set to true.");
+
+ test(function() {
+ var canvas = document.getElementById('test_canvas_2');
+ var ctx = canvas.getContext('2d');
+
+ ctx.imageSmoothingEnabled = false;
+ assert_false(ctx.imageSmoothingEnabled);
+ }, "On getting the imageSmoothingEnabled attribute, the user agent must return the last value it was set to.");
+
+ test(function() {
+ var canvas = document.getElementById('test_canvas_3');
+ var ctx = canvas.getContext('2d');
+
+ ctx.imageSmoothingEnabled = false;
+ assert_equals(ctx.imageSmoothingEnabled, false);
+ }, "On setting the imageSmoothingEnabled attribute, it must be set to the new value.");
+ })();
+
+
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/2dcontext/line-styles/.gitkeep b/tests/wpt/web-platform-tests/2dcontext/line-styles/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/line-styles/.gitkeep
diff --git a/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.cap.butt.html b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.cap.butt.html
new file mode 100644
index 00000000000..353676233a2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.cap.butt.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.line.cap.butt</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.line.cap.butt</h1>
+<p class="desc">lineCap 'butt' is rendered correctly</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("lineCap 'butt' is rendered correctly");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.lineCap = 'butt';
+ctx.lineWidth = 20;
+
+ctx.fillStyle = '#f00';
+ctx.strokeStyle = '#0f0';
+ctx.fillRect(15, 15, 20, 20);
+ctx.beginPath();
+ctx.moveTo(25, 15);
+ctx.lineTo(25, 35);
+ctx.stroke();
+
+ctx.fillStyle = '#0f0';
+ctx.strokeStyle = '#f00';
+ctx.beginPath();
+ctx.moveTo(75, 15);
+ctx.lineTo(75, 35);
+ctx.stroke();
+ctx.fillRect(65, 15, 20, 20);
+
+_assertPixel(canvas, 25,14, 0,255,0,255, "25,14", "0,255,0,255");
+_assertPixel(canvas, 25,15, 0,255,0,255, "25,15", "0,255,0,255");
+_assertPixel(canvas, 25,16, 0,255,0,255, "25,16", "0,255,0,255");
+_assertPixel(canvas, 25,34, 0,255,0,255, "25,34", "0,255,0,255");
+_assertPixel(canvas, 25,35, 0,255,0,255, "25,35", "0,255,0,255");
+_assertPixel(canvas, 25,36, 0,255,0,255, "25,36", "0,255,0,255");
+
+_assertPixel(canvas, 75,14, 0,255,0,255, "75,14", "0,255,0,255");
+_assertPixel(canvas, 75,15, 0,255,0,255, "75,15", "0,255,0,255");
+_assertPixel(canvas, 75,16, 0,255,0,255, "75,16", "0,255,0,255");
+_assertPixel(canvas, 75,34, 0,255,0,255, "75,34", "0,255,0,255");
+_assertPixel(canvas, 75,35, 0,255,0,255, "75,35", "0,255,0,255");
+_assertPixel(canvas, 75,36, 0,255,0,255, "75,36", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.cap.closed.html b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.cap.closed.html
new file mode 100644
index 00000000000..f8e233a4101
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.cap.closed.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.line.cap.closed</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.line.cap.closed</h1>
+<p class="desc">Line caps are not drawn at the corners of an unclosed rectangle</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Line caps are not drawn at the corners of an unclosed rectangle");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.strokeStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.lineJoin = 'bevel';
+ctx.lineCap = 'square';
+ctx.lineWidth = 400;
+
+ctx.beginPath();
+ctx.moveTo(200, 200);
+ctx.lineTo(200, 1000);
+ctx.lineTo(1000, 1000);
+ctx.lineTo(1000, 200);
+ctx.closePath();
+ctx.stroke();
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 48,1, 0,255,0,255, "48,1", "0,255,0,255");
+_assertPixel(canvas, 48,48, 0,255,0,255, "48,48", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.cap.invalid.html b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.cap.invalid.html
new file mode 100644
index 00000000000..1db32a9d6d3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.cap.invalid.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.line.cap.invalid</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.line.cap.invalid</h1>
+<p class="desc">Setting lineCap to invalid values is ignored</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Setting lineCap to invalid values is ignored");
+_addTest(function(canvas, ctx) {
+
+ctx.lineCap = 'butt'
+_assertSame(ctx.lineCap, 'butt', "ctx.lineCap", "'butt'");
+
+ctx.lineCap = 'butt';
+ctx.lineCap = 'invalid';
+_assertSame(ctx.lineCap, 'butt', "ctx.lineCap", "'butt'");
+
+ctx.lineCap = 'butt';
+ctx.lineCap = 'ROUND';
+_assertSame(ctx.lineCap, 'butt', "ctx.lineCap", "'butt'");
+
+ctx.lineCap = 'butt';
+ctx.lineCap = 'round\0';
+_assertSame(ctx.lineCap, 'butt', "ctx.lineCap", "'butt'");
+
+ctx.lineCap = 'butt';
+ctx.lineCap = 'round ';
+_assertSame(ctx.lineCap, 'butt', "ctx.lineCap", "'butt'");
+
+ctx.lineCap = 'butt';
+ctx.lineCap = "";
+_assertSame(ctx.lineCap, 'butt', "ctx.lineCap", "'butt'");
+
+ctx.lineCap = 'butt';
+ctx.lineCap = 'bevel';
+_assertSame(ctx.lineCap, 'butt', "ctx.lineCap", "'butt'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.cap.open.html b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.cap.open.html
new file mode 100644
index 00000000000..499773085b7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.cap.open.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.line.cap.open</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.line.cap.open</h1>
+<p class="desc">Line caps are drawn at the corners of an unclosed rectangle</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Line caps are drawn at the corners of an unclosed rectangle");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.strokeStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.lineJoin = 'bevel';
+ctx.lineCap = 'square';
+ctx.lineWidth = 400;
+
+ctx.beginPath();
+ctx.moveTo(200, 200);
+ctx.lineTo(200, 1000);
+ctx.lineTo(1000, 1000);
+ctx.lineTo(1000, 200);
+ctx.lineTo(200, 200);
+ctx.stroke();
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 48,1, 0,255,0,255, "48,1", "0,255,0,255");
+_assertPixel(canvas, 48,48, 0,255,0,255, "48,48", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.cap.round.html b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.cap.round.html
new file mode 100644
index 00000000000..675d11ce2c9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.cap.round.html
@@ -0,0 +1,77 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.line.cap.round</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.line.cap.round</h1>
+<p class="desc">lineCap 'round' is rendered correctly</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("lineCap 'round' is rendered correctly");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+var tol = 1; // tolerance to avoid antialiasing artifacts
+
+ctx.lineCap = 'round';
+ctx.lineWidth = 20;
+
+
+ctx.fillStyle = '#f00';
+ctx.strokeStyle = '#0f0';
+
+ctx.beginPath();
+ctx.moveTo(35-tol, 15);
+ctx.arc(25, 15, 10-tol, 0, Math.PI, true);
+ctx.arc(25, 35, 10-tol, Math.PI, 0, true);
+ctx.fill();
+
+ctx.beginPath();
+ctx.moveTo(25, 15);
+ctx.lineTo(25, 35);
+ctx.stroke();
+
+
+ctx.fillStyle = '#0f0';
+ctx.strokeStyle = '#f00';
+
+ctx.beginPath();
+ctx.moveTo(75, 15);
+ctx.lineTo(75, 35);
+ctx.stroke();
+
+ctx.beginPath();
+ctx.moveTo(85+tol, 15);
+ctx.arc(75, 15, 10+tol, 0, Math.PI, true);
+ctx.arc(75, 35, 10+tol, Math.PI, 0, true);
+ctx.fill();
+
+_assertPixel(canvas, 17,6, 0,255,0,255, "17,6", "0,255,0,255");
+_assertPixel(canvas, 25,6, 0,255,0,255, "25,6", "0,255,0,255");
+_assertPixel(canvas, 32,6, 0,255,0,255, "32,6", "0,255,0,255");
+_assertPixel(canvas, 17,43, 0,255,0,255, "17,43", "0,255,0,255");
+_assertPixel(canvas, 25,43, 0,255,0,255, "25,43", "0,255,0,255");
+_assertPixel(canvas, 32,43, 0,255,0,255, "32,43", "0,255,0,255");
+
+_assertPixel(canvas, 67,6, 0,255,0,255, "67,6", "0,255,0,255");
+_assertPixel(canvas, 75,6, 0,255,0,255, "75,6", "0,255,0,255");
+_assertPixel(canvas, 82,6, 0,255,0,255, "82,6", "0,255,0,255");
+_assertPixel(canvas, 67,43, 0,255,0,255, "67,43", "0,255,0,255");
+_assertPixel(canvas, 75,43, 0,255,0,255, "75,43", "0,255,0,255");
+_assertPixel(canvas, 82,43, 0,255,0,255, "82,43", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.cap.square.html b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.cap.square.html
new file mode 100644
index 00000000000..ea1e4d94977
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.cap.square.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.line.cap.square</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.line.cap.square</h1>
+<p class="desc">lineCap 'square' is rendered correctly</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("lineCap 'square' is rendered correctly");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.lineCap = 'square';
+ctx.lineWidth = 20;
+
+ctx.fillStyle = '#f00';
+ctx.strokeStyle = '#0f0';
+ctx.fillRect(15, 5, 20, 40);
+ctx.beginPath();
+ctx.moveTo(25, 15);
+ctx.lineTo(25, 35);
+ctx.stroke();
+
+ctx.fillStyle = '#0f0';
+ctx.strokeStyle = '#f00';
+ctx.beginPath();
+ctx.moveTo(75, 15);
+ctx.lineTo(75, 35);
+ctx.stroke();
+ctx.fillRect(65, 5, 20, 40);
+
+_assertPixel(canvas, 25,4, 0,255,0,255, "25,4", "0,255,0,255");
+_assertPixel(canvas, 25,5, 0,255,0,255, "25,5", "0,255,0,255");
+_assertPixel(canvas, 25,6, 0,255,0,255, "25,6", "0,255,0,255");
+_assertPixel(canvas, 25,44, 0,255,0,255, "25,44", "0,255,0,255");
+_assertPixel(canvas, 25,45, 0,255,0,255, "25,45", "0,255,0,255");
+_assertPixel(canvas, 25,46, 0,255,0,255, "25,46", "0,255,0,255");
+
+_assertPixel(canvas, 75,4, 0,255,0,255, "75,4", "0,255,0,255");
+_assertPixel(canvas, 75,5, 0,255,0,255, "75,5", "0,255,0,255");
+_assertPixel(canvas, 75,6, 0,255,0,255, "75,6", "0,255,0,255");
+_assertPixel(canvas, 75,44, 0,255,0,255, "75,44", "0,255,0,255");
+_assertPixel(canvas, 75,45, 0,255,0,255, "75,45", "0,255,0,255");
+_assertPixel(canvas, 75,46, 0,255,0,255, "75,46", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.cap.valid.html b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.cap.valid.html
new file mode 100644
index 00000000000..6ac119d4a25
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.cap.valid.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.line.cap.valid</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.line.cap.valid</h1>
+<p class="desc">Setting lineCap to valid values works</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Setting lineCap to valid values works");
+_addTest(function(canvas, ctx) {
+
+ctx.lineCap = 'butt'
+_assertSame(ctx.lineCap, 'butt', "ctx.lineCap", "'butt'");
+
+ctx.lineCap = 'round';
+_assertSame(ctx.lineCap, 'round', "ctx.lineCap", "'round'");
+
+ctx.lineCap = 'square';
+_assertSame(ctx.lineCap, 'square', "ctx.lineCap", "'square'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.cross.html b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.cross.html
new file mode 100644
index 00000000000..61b2125c401
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.cross.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.line.cross</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.line.cross</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.lineWidth = 200;
+ctx.lineJoin = 'bevel';
+
+ctx.strokeStyle = '#f00';
+ctx.beginPath();
+ctx.moveTo(110, 50);
+ctx.lineTo(110, 60);
+ctx.lineTo(100, 60);
+ctx.stroke();
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 48,1, 0,255,0,255, "48,1", "0,255,0,255");
+_assertPixel(canvas, 48,48, 0,255,0,255, "48,48", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.defaults.html b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.defaults.html
new file mode 100644
index 00000000000..8b680785d9d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.defaults.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.line.defaults</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.line.defaults</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+_assertSame(ctx.lineWidth, 1, "ctx.lineWidth", "1");
+_assertSame(ctx.lineCap, 'butt', "ctx.lineCap", "'butt'");
+_assertSame(ctx.lineJoin, 'miter', "ctx.lineJoin", "'miter'");
+_assertSame(ctx.miterLimit, 10, "ctx.miterLimit", "10");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.join.bevel.html b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.join.bevel.html
new file mode 100644
index 00000000000..72c0186e1dd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.join.bevel.html
@@ -0,0 +1,80 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.line.join.bevel</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.line.join.bevel</h1>
+<p class="desc">lineJoin 'bevel' is rendered correctly</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("lineJoin 'bevel' is rendered correctly");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+var tol = 1; // tolerance to avoid antialiasing artifacts
+
+ctx.lineJoin = 'bevel';
+ctx.lineWidth = 20;
+
+ctx.fillStyle = '#f00';
+ctx.strokeStyle = '#0f0';
+
+ctx.fillRect(10, 10, 20, 20);
+ctx.fillRect(20, 20, 20, 20);
+ctx.beginPath();
+ctx.moveTo(30, 20);
+ctx.lineTo(40-tol, 20);
+ctx.lineTo(30, 10+tol);
+ctx.fill();
+
+ctx.beginPath();
+ctx.moveTo(10, 20);
+ctx.lineTo(30, 20);
+ctx.lineTo(30, 40);
+ctx.stroke();
+
+
+ctx.fillStyle = '#0f0';
+ctx.strokeStyle = '#f00';
+
+ctx.beginPath();
+ctx.moveTo(60, 20);
+ctx.lineTo(80, 20);
+ctx.lineTo(80, 40);
+ctx.stroke();
+
+ctx.fillRect(60, 10, 20, 20);
+ctx.fillRect(70, 20, 20, 20);
+ctx.beginPath();
+ctx.moveTo(80, 20);
+ctx.lineTo(90+tol, 20);
+ctx.lineTo(80, 10-tol);
+ctx.fill();
+
+_assertPixel(canvas, 34,16, 0,255,0,255, "34,16", "0,255,0,255");
+_assertPixel(canvas, 34,15, 0,255,0,255, "34,15", "0,255,0,255");
+_assertPixel(canvas, 35,15, 0,255,0,255, "35,15", "0,255,0,255");
+_assertPixel(canvas, 36,15, 0,255,0,255, "36,15", "0,255,0,255");
+_assertPixel(canvas, 36,14, 0,255,0,255, "36,14", "0,255,0,255");
+
+_assertPixel(canvas, 84,16, 0,255,0,255, "84,16", "0,255,0,255");
+_assertPixel(canvas, 84,15, 0,255,0,255, "84,15", "0,255,0,255");
+_assertPixel(canvas, 85,15, 0,255,0,255, "85,15", "0,255,0,255");
+_assertPixel(canvas, 86,15, 0,255,0,255, "86,15", "0,255,0,255");
+_assertPixel(canvas, 86,14, 0,255,0,255, "86,14", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.join.closed.html b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.join.closed.html
new file mode 100644
index 00000000000..1f2bf5cb75d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.join.closed.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.line.join.closed</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.line.join.closed</h1>
+<p class="desc">Line joins are drawn at the corner of a closed rectangle</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Line joins are drawn at the corner of a closed rectangle");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.strokeStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.lineJoin = 'miter';
+ctx.lineWidth = 200;
+
+ctx.beginPath();
+ctx.moveTo(100, 50);
+ctx.lineTo(100, 1000);
+ctx.lineTo(1000, 1000);
+ctx.lineTo(1000, 50);
+ctx.closePath();
+ctx.stroke();
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 48,1, 0,255,0,255, "48,1", "0,255,0,255");
+_assertPixel(canvas, 48,48, 0,255,0,255, "48,48", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.join.invalid.html b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.join.invalid.html
new file mode 100644
index 00000000000..9d54d90b19f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.join.invalid.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.line.join.invalid</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.line.join.invalid</h1>
+<p class="desc">Setting lineJoin to invalid values is ignored</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Setting lineJoin to invalid values is ignored");
+_addTest(function(canvas, ctx) {
+
+ctx.lineJoin = 'bevel'
+_assertSame(ctx.lineJoin, 'bevel', "ctx.lineJoin", "'bevel'");
+
+ctx.lineJoin = 'bevel';
+ctx.lineJoin = 'invalid';
+_assertSame(ctx.lineJoin, 'bevel', "ctx.lineJoin", "'bevel'");
+
+ctx.lineJoin = 'bevel';
+ctx.lineJoin = 'ROUND';
+_assertSame(ctx.lineJoin, 'bevel', "ctx.lineJoin", "'bevel'");
+
+ctx.lineJoin = 'bevel';
+ctx.lineJoin = 'round\0';
+_assertSame(ctx.lineJoin, 'bevel', "ctx.lineJoin", "'bevel'");
+
+ctx.lineJoin = 'bevel';
+ctx.lineJoin = 'round ';
+_assertSame(ctx.lineJoin, 'bevel', "ctx.lineJoin", "'bevel'");
+
+ctx.lineJoin = 'bevel';
+ctx.lineJoin = "";
+_assertSame(ctx.lineJoin, 'bevel', "ctx.lineJoin", "'bevel'");
+
+ctx.lineJoin = 'bevel';
+ctx.lineJoin = 'butt';
+_assertSame(ctx.lineJoin, 'bevel', "ctx.lineJoin", "'bevel'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.join.miter.html b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.join.miter.html
new file mode 100644
index 00000000000..8a6d4a60ebf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.join.miter.html
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.line.join.miter</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.line.join.miter</h1>
+<p class="desc">lineJoin 'miter' is rendered correctly</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("lineJoin 'miter' is rendered correctly");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.lineJoin = 'miter';
+ctx.lineWidth = 20;
+
+ctx.fillStyle = '#f00';
+ctx.strokeStyle = '#0f0';
+
+ctx.fillStyle = '#f00';
+ctx.strokeStyle = '#0f0';
+
+ctx.fillRect(10, 10, 30, 20);
+ctx.fillRect(20, 10, 20, 30);
+
+ctx.beginPath();
+ctx.moveTo(10, 20);
+ctx.lineTo(30, 20);
+ctx.lineTo(30, 40);
+ctx.stroke();
+
+
+ctx.fillStyle = '#0f0';
+ctx.strokeStyle = '#f00';
+
+ctx.beginPath();
+ctx.moveTo(60, 20);
+ctx.lineTo(80, 20);
+ctx.lineTo(80, 40);
+ctx.stroke();
+
+ctx.fillRect(60, 10, 30, 20);
+ctx.fillRect(70, 10, 20, 30);
+
+_assertPixel(canvas, 38,12, 0,255,0,255, "38,12", "0,255,0,255");
+_assertPixel(canvas, 39,11, 0,255,0,255, "39,11", "0,255,0,255");
+_assertPixel(canvas, 40,10, 0,255,0,255, "40,10", "0,255,0,255");
+_assertPixel(canvas, 41,9, 0,255,0,255, "41,9", "0,255,0,255");
+_assertPixel(canvas, 42,8, 0,255,0,255, "42,8", "0,255,0,255");
+
+_assertPixel(canvas, 88,12, 0,255,0,255, "88,12", "0,255,0,255");
+_assertPixel(canvas, 89,11, 0,255,0,255, "89,11", "0,255,0,255");
+_assertPixel(canvas, 90,10, 0,255,0,255, "90,10", "0,255,0,255");
+_assertPixel(canvas, 91,9, 0,255,0,255, "91,9", "0,255,0,255");
+_assertPixel(canvas, 92,8, 0,255,0,255, "92,8", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.join.open.html b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.join.open.html
new file mode 100644
index 00000000000..a72291bc397
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.join.open.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.line.join.open</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.line.join.open</h1>
+<p class="desc">Line joins are not drawn at the corner of an unclosed rectangle</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Line joins are not drawn at the corner of an unclosed rectangle");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.strokeStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.lineJoin = 'miter';
+ctx.lineWidth = 200;
+
+ctx.beginPath();
+ctx.moveTo(100, 50);
+ctx.lineTo(100, 1000);
+ctx.lineTo(1000, 1000);
+ctx.lineTo(1000, 50);
+ctx.lineTo(100, 50);
+ctx.stroke();
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 48,1, 0,255,0,255, "48,1", "0,255,0,255");
+_assertPixel(canvas, 48,48, 0,255,0,255, "48,48", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.join.parallel.html b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.join.parallel.html
new file mode 100644
index 00000000000..2a8956d7e9f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.join.parallel.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.line.join.parallel</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.line.join.parallel</h1>
+<p class="desc">Line joins are drawn at 180-degree joins</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Line joins are drawn at 180-degree joins");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.strokeStyle = '#0f0';
+ctx.lineWidth = 300;
+ctx.lineJoin = 'round';
+ctx.beginPath();
+ctx.moveTo(-100, 25);
+ctx.lineTo(0, 25);
+ctx.lineTo(-100, 25);
+ctx.stroke();
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 48,1, 0,255,0,255, "48,1", "0,255,0,255");
+_assertPixel(canvas, 48,48, 0,255,0,255, "48,48", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.join.round.html b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.join.round.html
new file mode 100644
index 00000000000..4a827adcec9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.join.round.html
@@ -0,0 +1,78 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.line.join.round</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.line.join.round</h1>
+<p class="desc">lineJoin 'round' is rendered correctly</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("lineJoin 'round' is rendered correctly");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+var tol = 1; // tolerance to avoid antialiasing artifacts
+
+ctx.lineJoin = 'round';
+ctx.lineWidth = 20;
+
+ctx.fillStyle = '#f00';
+ctx.strokeStyle = '#0f0';
+
+ctx.fillRect(10, 10, 20, 20);
+ctx.fillRect(20, 20, 20, 20);
+ctx.beginPath();
+ctx.moveTo(30, 20);
+ctx.arc(30, 20, 10-tol, 0, 2*Math.PI, true);
+ctx.fill();
+
+ctx.beginPath();
+ctx.moveTo(10, 20);
+ctx.lineTo(30, 20);
+ctx.lineTo(30, 40);
+ctx.stroke();
+
+
+ctx.fillStyle = '#0f0';
+ctx.strokeStyle = '#f00';
+
+ctx.beginPath();
+ctx.moveTo(60, 20);
+ctx.lineTo(80, 20);
+ctx.lineTo(80, 40);
+ctx.stroke();
+
+ctx.fillRect(60, 10, 20, 20);
+ctx.fillRect(70, 20, 20, 20);
+ctx.beginPath();
+ctx.moveTo(80, 20);
+ctx.arc(80, 20, 10+tol, 0, 2*Math.PI, true);
+ctx.fill();
+
+_assertPixel(canvas, 36,14, 0,255,0,255, "36,14", "0,255,0,255");
+_assertPixel(canvas, 36,13, 0,255,0,255, "36,13", "0,255,0,255");
+_assertPixel(canvas, 37,13, 0,255,0,255, "37,13", "0,255,0,255");
+_assertPixel(canvas, 38,13, 0,255,0,255, "38,13", "0,255,0,255");
+_assertPixel(canvas, 38,12, 0,255,0,255, "38,12", "0,255,0,255");
+
+_assertPixel(canvas, 86,14, 0,255,0,255, "86,14", "0,255,0,255");
+_assertPixel(canvas, 86,13, 0,255,0,255, "86,13", "0,255,0,255");
+_assertPixel(canvas, 87,13, 0,255,0,255, "87,13", "0,255,0,255");
+_assertPixel(canvas, 88,13, 0,255,0,255, "88,13", "0,255,0,255");
+_assertPixel(canvas, 88,12, 0,255,0,255, "88,12", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.join.valid.html b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.join.valid.html
new file mode 100644
index 00000000000..98fec4cb7bc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.join.valid.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.line.join.valid</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.line.join.valid</h1>
+<p class="desc">Setting lineJoin to valid values works</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Setting lineJoin to valid values works");
+_addTest(function(canvas, ctx) {
+
+ctx.lineJoin = 'bevel'
+_assertSame(ctx.lineJoin, 'bevel', "ctx.lineJoin", "'bevel'");
+
+ctx.lineJoin = 'round';
+_assertSame(ctx.lineJoin, 'round', "ctx.lineJoin", "'round'");
+
+ctx.lineJoin = 'miter';
+_assertSame(ctx.lineJoin, 'miter', "ctx.lineJoin", "'miter'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.miter.acute.html b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.miter.acute.html
new file mode 100644
index 00000000000..f11a32164bd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.miter.acute.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.line.miter.acute</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.line.miter.acute</h1>
+<p class="desc">Miter joins are drawn correctly with acute angles</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Miter joins are drawn correctly with acute angles");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.lineWidth = 200;
+ctx.lineJoin = 'miter';
+
+ctx.strokeStyle = '#0f0';
+ctx.miterLimit = 2.614;
+ctx.beginPath();
+ctx.moveTo(100, 1000);
+ctx.lineTo(100, 100);
+ctx.lineTo(1000, 1000);
+ctx.stroke();
+
+ctx.strokeStyle = '#f00';
+ctx.miterLimit = 2.613;
+ctx.beginPath();
+ctx.moveTo(100, 1000);
+ctx.lineTo(100, 100);
+ctx.lineTo(1000, 1000);
+ctx.stroke();
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 48,1, 0,255,0,255, "48,1", "0,255,0,255");
+_assertPixel(canvas, 48,48, 0,255,0,255, "48,48", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.miter.exceeded.html b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.miter.exceeded.html
new file mode 100644
index 00000000000..1cbcd3cad36
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.miter.exceeded.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.line.miter.exceeded</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.line.miter.exceeded</h1>
+<p class="desc">Miter joins are not drawn when the miter limit is exceeded</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Miter joins are not drawn when the miter limit is exceeded");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.lineWidth = 400;
+ctx.lineJoin = 'miter';
+
+ctx.strokeStyle = '#f00';
+ctx.miterLimit = 1.414;
+ctx.beginPath();
+ctx.moveTo(200, 1000);
+ctx.lineTo(200, 200);
+ctx.lineTo(1000, 201); // slightly non-right-angle to avoid being a special case
+ctx.stroke();
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 48,1, 0,255,0,255, "48,1", "0,255,0,255");
+_assertPixel(canvas, 48,48, 0,255,0,255, "48,48", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.miter.invalid.html b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.miter.invalid.html
new file mode 100644
index 00000000000..4f7fd69bcd6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.miter.invalid.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.line.miter.invalid</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.line.miter.invalid</h1>
+<p class="desc">Setting miterLimit to invalid values is ignored</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Setting miterLimit to invalid values is ignored");
+_addTest(function(canvas, ctx) {
+
+ctx.miterLimit = 1.5;
+_assertSame(ctx.miterLimit, 1.5, "ctx.miterLimit", "1.5");
+
+ctx.miterLimit = 1.5;
+ctx.miterLimit = 0;
+_assertSame(ctx.miterLimit, 1.5, "ctx.miterLimit", "1.5");
+
+ctx.miterLimit = 1.5;
+ctx.miterLimit = -1;
+_assertSame(ctx.miterLimit, 1.5, "ctx.miterLimit", "1.5");
+
+ctx.miterLimit = 1.5;
+ctx.miterLimit = Infinity;
+_assertSame(ctx.miterLimit, 1.5, "ctx.miterLimit", "1.5");
+
+ctx.miterLimit = 1.5;
+ctx.miterLimit = -Infinity;
+_assertSame(ctx.miterLimit, 1.5, "ctx.miterLimit", "1.5");
+
+ctx.miterLimit = 1.5;
+ctx.miterLimit = NaN;
+_assertSame(ctx.miterLimit, 1.5, "ctx.miterLimit", "1.5");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.miter.lineedge.html b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.miter.lineedge.html
new file mode 100644
index 00000000000..54c2ce53938
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.miter.lineedge.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.line.miter.lineedge</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.line.miter.lineedge</h1>
+<p class="desc">Miter joins are not drawn when the miter limit is exceeded at the corners of a zero-height rectangle</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Miter joins are not drawn when the miter limit is exceeded at the corners of a zero-height rectangle");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.lineWidth = 200;
+ctx.lineJoin = 'miter';
+
+ctx.strokeStyle = '#f00';
+ctx.miterLimit = 1.414;
+ctx.beginPath();
+ctx.strokeRect(100, 25, 200, 0);
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 48,1, 0,255,0,255, "48,1", "0,255,0,255");
+_assertPixel(canvas, 48,48, 0,255,0,255, "48,48", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.miter.obtuse.html b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.miter.obtuse.html
new file mode 100644
index 00000000000..40ebdd1f8d4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.miter.obtuse.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.line.miter.obtuse</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.line.miter.obtuse</h1>
+<p class="desc">Miter joins are drawn correctly with obtuse angles</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Miter joins are drawn correctly with obtuse angles");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.lineWidth = 1600;
+ctx.lineJoin = 'miter';
+
+ctx.strokeStyle = '#0f0';
+ctx.miterLimit = 1.083;
+ctx.beginPath();
+ctx.moveTo(800, 10000);
+ctx.lineTo(800, 300);
+ctx.lineTo(10000, -8900);
+ctx.stroke();
+
+ctx.strokeStyle = '#f00';
+ctx.miterLimit = 1.082;
+ctx.beginPath();
+ctx.moveTo(800, 10000);
+ctx.lineTo(800, 300);
+ctx.lineTo(10000, -8900);
+ctx.stroke();
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 48,1, 0,255,0,255, "48,1", "0,255,0,255");
+_assertPixel(canvas, 48,48, 0,255,0,255, "48,48", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.miter.rightangle.html b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.miter.rightangle.html
new file mode 100644
index 00000000000..ebcfb261a5f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.miter.rightangle.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.line.miter.rightangle</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.line.miter.rightangle</h1>
+<p class="desc">Miter joins are not drawn when the miter limit is exceeded, on exact right angles</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Miter joins are not drawn when the miter limit is exceeded, on exact right angles");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.lineWidth = 400;
+ctx.lineJoin = 'miter';
+
+ctx.strokeStyle = '#f00';
+ctx.miterLimit = 1.414;
+ctx.beginPath();
+ctx.moveTo(200, 1000);
+ctx.lineTo(200, 200);
+ctx.lineTo(1000, 200);
+ctx.stroke();
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 48,1, 0,255,0,255, "48,1", "0,255,0,255");
+_assertPixel(canvas, 48,48, 0,255,0,255, "48,48", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.miter.valid.html b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.miter.valid.html
new file mode 100644
index 00000000000..59148aa5656
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.miter.valid.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.line.miter.valid</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.line.miter.valid</h1>
+<p class="desc">Setting miterLimit to valid values works</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Setting miterLimit to valid values works");
+_addTest(function(canvas, ctx) {
+
+ctx.miterLimit = 1.5;
+_assertSame(ctx.miterLimit, 1.5, "ctx.miterLimit", "1.5");
+
+ctx.miterLimit = "1e1";
+_assertSame(ctx.miterLimit, 10, "ctx.miterLimit", "10");
+
+ctx.miterLimit = 1/1024;
+_assertSame(ctx.miterLimit, 1/1024, "ctx.miterLimit", "1/1024");
+
+ctx.miterLimit = 1000;
+_assertSame(ctx.miterLimit, 1000, "ctx.miterLimit", "1000");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.miter.within.html b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.miter.within.html
new file mode 100644
index 00000000000..5ed57e0cce3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.miter.within.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.line.miter.within</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.line.miter.within</h1>
+<p class="desc">Miter joins are drawn when the miter limit is not quite exceeded</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Miter joins are drawn when the miter limit is not quite exceeded");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.lineWidth = 400;
+ctx.lineJoin = 'miter';
+
+ctx.strokeStyle = '#0f0';
+ctx.miterLimit = 1.416;
+ctx.beginPath();
+ctx.moveTo(200, 1000);
+ctx.lineTo(200, 200);
+ctx.lineTo(1000, 201);
+ctx.stroke();
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 48,1, 0,255,0,255, "48,1", "0,255,0,255");
+_assertPixel(canvas, 48,48, 0,255,0,255, "48,48", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.union.html b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.union.html
new file mode 100644
index 00000000000..92fa2f1a2d2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.union.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.line.union</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.line.union</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.lineWidth = 100;
+ctx.lineCap = 'round';
+
+ctx.strokeStyle = '#0f0';
+ctx.beginPath();
+ctx.moveTo(0, 24);
+ctx.lineTo(100, 25);
+ctx.lineTo(0, 26);
+ctx.closePath();
+ctx.stroke();
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 25,1, 0,255,0,255, "25,1", "0,255,0,255");
+_assertPixel(canvas, 48,1, 0,255,0,255, "48,1", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 25,1, 0,255,0,255, "25,1", "0,255,0,255");
+_assertPixel(canvas, 48,48, 0,255,0,255, "48,48", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.width.basic.html b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.width.basic.html
new file mode 100644
index 00000000000..b61baaf24c1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.width.basic.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.line.width.basic</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.line.width.basic</h1>
+<p class="desc">lineWidth determines the width of line strokes</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("lineWidth determines the width of line strokes");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.lineWidth = 20;
+// Draw a green line over a red box, to check the line is not too small
+ctx.fillStyle = '#f00';
+ctx.strokeStyle = '#0f0';
+ctx.fillRect(15, 15, 20, 20);
+ctx.beginPath();
+ctx.moveTo(25, 15);
+ctx.lineTo(25, 35);
+ctx.stroke();
+
+// Draw a green box over a red line, to check the line is not too large
+ctx.fillStyle = '#0f0';
+ctx.strokeStyle = '#f00';
+ctx.beginPath();
+ctx.moveTo(75, 15);
+ctx.lineTo(75, 35);
+ctx.stroke();
+ctx.fillRect(65, 15, 20, 20);
+
+_assertPixel(canvas, 14,25, 0,255,0,255, "14,25", "0,255,0,255");
+_assertPixel(canvas, 15,25, 0,255,0,255, "15,25", "0,255,0,255");
+_assertPixel(canvas, 16,25, 0,255,0,255, "16,25", "0,255,0,255");
+_assertPixel(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255");
+_assertPixel(canvas, 34,25, 0,255,0,255, "34,25", "0,255,0,255");
+_assertPixel(canvas, 35,25, 0,255,0,255, "35,25", "0,255,0,255");
+_assertPixel(canvas, 36,25, 0,255,0,255, "36,25", "0,255,0,255");
+
+_assertPixel(canvas, 64,25, 0,255,0,255, "64,25", "0,255,0,255");
+_assertPixel(canvas, 65,25, 0,255,0,255, "65,25", "0,255,0,255");
+_assertPixel(canvas, 66,25, 0,255,0,255, "66,25", "0,255,0,255");
+_assertPixel(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255");
+_assertPixel(canvas, 84,25, 0,255,0,255, "84,25", "0,255,0,255");
+_assertPixel(canvas, 85,25, 0,255,0,255, "85,25", "0,255,0,255");
+_assertPixel(canvas, 86,25, 0,255,0,255, "86,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.width.invalid.html b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.width.invalid.html
new file mode 100644
index 00000000000..d5cd3ab0af1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.width.invalid.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.line.width.invalid</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.line.width.invalid</h1>
+<p class="desc">Setting lineWidth to invalid values is ignored</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Setting lineWidth to invalid values is ignored");
+_addTest(function(canvas, ctx) {
+
+ctx.lineWidth = 1.5;
+_assertSame(ctx.lineWidth, 1.5, "ctx.lineWidth", "1.5");
+
+ctx.lineWidth = 1.5;
+ctx.lineWidth = 0;
+_assertSame(ctx.lineWidth, 1.5, "ctx.lineWidth", "1.5");
+
+ctx.lineWidth = 1.5;
+ctx.lineWidth = -1;
+_assertSame(ctx.lineWidth, 1.5, "ctx.lineWidth", "1.5");
+
+ctx.lineWidth = 1.5;
+ctx.lineWidth = Infinity;
+_assertSame(ctx.lineWidth, 1.5, "ctx.lineWidth", "1.5");
+
+ctx.lineWidth = 1.5;
+ctx.lineWidth = -Infinity;
+_assertSame(ctx.lineWidth, 1.5, "ctx.lineWidth", "1.5");
+
+ctx.lineWidth = 1.5;
+ctx.lineWidth = NaN;
+_assertSame(ctx.lineWidth, 1.5, "ctx.lineWidth", "1.5");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.width.scaledefault.html b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.width.scaledefault.html
new file mode 100644
index 00000000000..154d7b58261
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.width.scaledefault.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.line.width.scaledefault</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.line.width.scaledefault</h1>
+<p class="desc">Default lineWidth strokes are affected by scale transformations</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Default lineWidth strokes are affected by scale transformations");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.scale(50, 50);
+ctx.strokeStyle = '#0f0';
+ctx.moveTo(0, 0.5);
+ctx.lineTo(2, 0.5);
+ctx.stroke();
+
+_assertPixel(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255");
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255");
+_assertPixel(canvas, 50,5, 0,255,0,255, "50,5", "0,255,0,255");
+_assertPixel(canvas, 50,45, 0,255,0,255, "50,45", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.width.transformed.html b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.width.transformed.html
new file mode 100644
index 00000000000..903321f44cd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.width.transformed.html
@@ -0,0 +1,69 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.line.width.transformed</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.line.width.transformed</h1>
+<p class="desc">Line stroke widths are affected by scale transformations</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Line stroke widths are affected by scale transformations");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.lineWidth = 4;
+// Draw a green line over a red box, to check the line is not too small
+ctx.fillStyle = '#f00';
+ctx.strokeStyle = '#0f0';
+ctx.fillRect(15, 15, 20, 20);
+ctx.save();
+ ctx.scale(5, 1);
+ ctx.beginPath();
+ ctx.moveTo(5, 15);
+ ctx.lineTo(5, 35);
+ ctx.stroke();
+ctx.restore();
+
+// Draw a green box over a red line, to check the line is not too large
+ctx.fillStyle = '#0f0';
+ctx.strokeStyle = '#f00';
+ctx.save();
+ ctx.scale(-5, 1);
+ ctx.beginPath();
+ ctx.moveTo(-15, 15);
+ ctx.lineTo(-15, 35);
+ ctx.stroke();
+ctx.restore();
+ctx.fillRect(65, 15, 20, 20);
+
+_assertPixel(canvas, 14,25, 0,255,0,255, "14,25", "0,255,0,255");
+_assertPixel(canvas, 15,25, 0,255,0,255, "15,25", "0,255,0,255");
+_assertPixel(canvas, 16,25, 0,255,0,255, "16,25", "0,255,0,255");
+_assertPixel(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255");
+_assertPixel(canvas, 34,25, 0,255,0,255, "34,25", "0,255,0,255");
+_assertPixel(canvas, 35,25, 0,255,0,255, "35,25", "0,255,0,255");
+_assertPixel(canvas, 36,25, 0,255,0,255, "36,25", "0,255,0,255");
+
+_assertPixel(canvas, 64,25, 0,255,0,255, "64,25", "0,255,0,255");
+_assertPixel(canvas, 65,25, 0,255,0,255, "65,25", "0,255,0,255");
+_assertPixel(canvas, 66,25, 0,255,0,255, "66,25", "0,255,0,255");
+_assertPixel(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255");
+_assertPixel(canvas, 84,25, 0,255,0,255, "84,25", "0,255,0,255");
+_assertPixel(canvas, 85,25, 0,255,0,255, "85,25", "0,255,0,255");
+_assertPixel(canvas, 86,25, 0,255,0,255, "86,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.width.valid.html b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.width.valid.html
new file mode 100644
index 00000000000..c89fa56a653
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/line-styles/2d.line.width.valid.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.line.width.valid</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.line.width.valid</h1>
+<p class="desc">Setting lineWidth to valid values works</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Setting lineWidth to valid values works");
+_addTest(function(canvas, ctx) {
+
+ctx.lineWidth = 1.5;
+_assertSame(ctx.lineWidth, 1.5, "ctx.lineWidth", "1.5");
+
+ctx.lineWidth = "1e1";
+_assertSame(ctx.lineWidth, 10, "ctx.lineWidth", "10");
+
+ctx.lineWidth = 1/1024;
+_assertSame(ctx.lineWidth, 1/1024, "ctx.lineWidth", "1/1024");
+
+ctx.lineWidth = 1000;
+_assertSame(ctx.lineWidth, 1000, "ctx.lineWidth", "1000");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/line-styles/canvas_linestyles_linecap_001-ref.htm b/tests/wpt/web-platform-tests/2dcontext/line-styles/canvas_linestyles_linecap_001-ref.htm
new file mode 100644
index 00000000000..f85af9aab2e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/line-styles/canvas_linestyles_linecap_001-ref.htm
@@ -0,0 +1,11 @@
+<!doctype HTML>
+<html>
+ <head>
+ <title>HTML5 Canvas Test: "square" lineCap</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com" />
+ </head>
+ <body>
+ <p>Description: The square value of lineCap means that a rectangle with the length of the line width and the width of half the line width, placed flat against the edge perpendicular to the direction of the line, must be added at the end of each line.</p>
+ <div><img src='/images/black-rectangle.png' alt='black rect' /></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/2dcontext/line-styles/canvas_linestyles_linecap_001.htm b/tests/wpt/web-platform-tests/2dcontext/line-styles/canvas_linestyles_linecap_001.htm
new file mode 100644
index 00000000000..583dbc9d134
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/line-styles/canvas_linestyles_linecap_001.htm
@@ -0,0 +1,37 @@
+<!doctype HTML>
+<html>
+ <head>
+ <title>HTML5 Canvas Test: "square" lineCap</title>
+ <link rel="match" href="canvas_linestyles_linecap_001-ref.htm">
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com" />
+ <link rel="help" href="http://www.w3.org/TR/2dcontext/#dom-context-2d-linecap" />
+ <meta name="assert" content="The square value of lineCap means that a rectangle with the length of the line width and the width of half the line width, placed flat against the edge perpendicular to the direction of the line, must be added at the end of each line." />
+ <script type="text/javascript">
+ function runTest()
+ {
+ var canvas = document.getElementById("canvas1");
+ var ctx = canvas.getContext("2d");
+
+ // Draw the first red rectangle.
+ ctx.fillStyle ="rgba(255, 0, 0, 1.0)";
+ ctx.fillRect(75, 0, 25, 50);
+
+ // Draw second red rectangle.
+ ctx.fillRect(0, 0, 25, 50);
+
+ // Draw a line with square lineCap.
+ ctx.strokeStyle = "rgba(0, 0, 0, 1.0)";
+ ctx.lineWidth = 50;
+ ctx.lineCap = "square";
+ ctx.beginPath();
+ ctx.moveTo(25, 25);
+ ctx.lineTo(75, 25);
+ ctx.stroke();
+ }
+ </script>
+ </head>
+ <body onload="runTest()">
+ <p>Description: The square value of lineCap means that a rectangle with the length of the line width and the width of half the line width, placed flat against the edge perpendicular to the direction of the line, must be added at the end of each line.</p>
+ <canvas id="canvas1" width="300" height="150">Browser does not support HTML5 Canvas.</canvas>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/.gitkeep b/tests/wpt/web-platform-tests/2dcontext/path-objects/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/.gitkeep
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.angle.1.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.angle.1.html
new file mode 100644
index 00000000000..06ac1665d40
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.angle.1.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.arc.angle.1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.arc.angle.1</h1>
+<p class="desc">arc() draws pi/2 .. -pi anticlockwise correctly</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("arc() draws pi/2 .. -pi anticlockwise correctly");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.fillStyle = '#f00';
+ctx.beginPath();
+ctx.moveTo(100, 0);
+ctx.arc(100, 0, 150, Math.PI/2, -Math.PI, true);
+ctx.fill();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.angle.2.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.angle.2.html
new file mode 100644
index 00000000000..328756cceab
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.angle.2.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.arc.angle.2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.arc.angle.2</h1>
+<p class="desc">arc() draws -3pi/2 .. -pi anticlockwise correctly</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("arc() draws -3pi/2 .. -pi anticlockwise correctly");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.fillStyle = '#f00';
+ctx.beginPath();
+ctx.moveTo(100, 0);
+ctx.arc(100, 0, 150, -3*Math.PI/2, -Math.PI, true);
+ctx.fill();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.angle.3.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.angle.3.html
new file mode 100644
index 00000000000..a0696d625fd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.angle.3.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.arc.angle.3</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.arc.angle.3</h1>
+<p class="desc">arc() wraps angles mod 2pi when anticlockwise and end > start+2pi</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("arc() wraps angles mod 2pi when anticlockwise and end > start+2pi");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.fillStyle = '#f00';
+ctx.beginPath();
+ctx.moveTo(100, 0);
+ctx.arc(100, 0, 150, (512+1/2)*Math.PI, (1024-1)*Math.PI, true);
+ctx.fill();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.angle.4.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.angle.4.html
new file mode 100644
index 00000000000..bad839d8004
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.angle.4.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.arc.angle.4</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.arc.angle.4</h1>
+<p class="desc">arc() draws a full circle when clockwise and end > start+2pi</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("arc() draws a full circle when clockwise and end > start+2pi");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.fillStyle = '#0f0';
+ctx.beginPath();
+ctx.moveTo(50, 25);
+ctx.arc(50, 25, 60, (512+1/2)*Math.PI, (1024-1)*Math.PI, false);
+ctx.fill();
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.angle.5.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.angle.5.html
new file mode 100644
index 00000000000..5a053445257
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.angle.5.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.arc.angle.5</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.arc.angle.5</h1>
+<p class="desc">arc() wraps angles mod 2pi when clockwise and start > end+2pi</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("arc() wraps angles mod 2pi when clockwise and start > end+2pi");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.fillStyle = '#f00';
+ctx.beginPath();
+ctx.moveTo(100, 0);
+ctx.arc(100, 0, 150, (1024-1)*Math.PI, (512+1/2)*Math.PI, false);
+ctx.fill();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.angle.6.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.angle.6.html
new file mode 100644
index 00000000000..3b645cb2773
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.angle.6.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.arc.angle.6</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.arc.angle.6</h1>
+<p class="desc">arc() draws a full circle when anticlockwise and start > end+2pi</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("arc() draws a full circle when anticlockwise and start > end+2pi");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.fillStyle = '#0f0';
+ctx.beginPath();
+ctx.moveTo(50, 25);
+ctx.arc(50, 25, 60, (1024-1)*Math.PI, (512+1/2)*Math.PI, true);
+ctx.fill();
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.default.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.default.html
new file mode 100644
index 00000000000..3ccfd99148d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.default.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.arc.default</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.arc.default</h1>
+<p class="desc">arc() with missing last argument defaults to clockwise</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("arc() with missing last argument defaults to clockwise");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.fillStyle = '#f00';
+ctx.beginPath();
+ctx.moveTo(100, 0);
+ctx.arc(100, 0, 150, -Math.PI, Math.PI/2);
+ctx.fill();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.empty.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.empty.html
new file mode 100644
index 00000000000..fa59b66f50f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.empty.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.arc.empty</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.arc.empty</h1>
+<p class="desc">arc() with an empty path does not draw a straight line to the start point</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("arc() with an empty path does not draw a straight line to the start point");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.lineWidth = 50;
+ctx.strokeStyle = '#f00';
+ctx.beginPath();
+ctx.arc(200, 25, 5, 0, 2*Math.PI, true);
+ctx.stroke();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.end.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.end.html
new file mode 100644
index 00000000000..13b1188d17a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.end.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.arc.end</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.arc.end</h1>
+<p class="desc">arc() adds the end point of the arc to the subpath</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("arc() adds the end point of the arc to the subpath");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.lineWidth = 50;
+ctx.strokeStyle = '#0f0';
+ctx.beginPath();
+ctx.moveTo(-100, 0);
+ctx.arc(-100, 0, 25, -Math.PI/2, Math.PI/2, true);
+ctx.lineTo(100, 25);
+ctx.stroke();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.negative.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.negative.html
new file mode 100644
index 00000000000..c82769046be
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.negative.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.arc.negative</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.arc.negative</h1>
+<p class="desc">arc() with negative radius throws INDEX_SIZE_ERR</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("arc() with negative radius throws INDEX_SIZE_ERR");
+_addTest(function(canvas, ctx) {
+
+assert_throws("INDEX_SIZE_ERR", function() { ctx.arc(0, 0, -1, 0, 0, true); });
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.nonempty.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.nonempty.html
new file mode 100644
index 00000000000..ffc0b8c0c2a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.nonempty.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.arc.nonempty</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.arc.nonempty</h1>
+<p class="desc">arc() with a non-empty path does draw a straight line to the start point</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("arc() with a non-empty path does draw a straight line to the start point");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.lineWidth = 50;
+ctx.strokeStyle = '#0f0';
+ctx.beginPath();
+ctx.moveTo(0, 25);
+ctx.arc(200, 25, 5, 0, 2*Math.PI, true);
+ctx.stroke();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.nonfinite.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.nonfinite.html
new file mode 100644
index 00000000000..d8cffe4467c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.nonfinite.html
@@ -0,0 +1,77 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.arc.nonfinite</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.arc.nonfinite</h1>
+<p class="desc">arc() with Infinity/NaN is ignored</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("arc() with Infinity/NaN is ignored");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.moveTo(0, 0);
+ctx.lineTo(100, 0);
+ctx.arc(Infinity, 0, 50, 0, 2*Math.PI, true);
+ctx.arc(-Infinity, 0, 50, 0, 2*Math.PI, true);
+ctx.arc(NaN, 0, 50, 0, 2*Math.PI, true);
+ctx.arc(0, Infinity, 50, 0, 2*Math.PI, true);
+ctx.arc(0, -Infinity, 50, 0, 2*Math.PI, true);
+ctx.arc(0, NaN, 50, 0, 2*Math.PI, true);
+ctx.arc(0, 0, Infinity, 0, 2*Math.PI, true);
+ctx.arc(0, 0, -Infinity, 0, 2*Math.PI, true);
+ctx.arc(0, 0, NaN, 0, 2*Math.PI, true);
+ctx.arc(0, 0, 50, Infinity, 2*Math.PI, true);
+ctx.arc(0, 0, 50, -Infinity, 2*Math.PI, true);
+ctx.arc(0, 0, 50, NaN, 2*Math.PI, true);
+ctx.arc(0, 0, 50, 0, Infinity, true);
+ctx.arc(0, 0, 50, 0, -Infinity, true);
+ctx.arc(0, 0, 50, 0, NaN, true);
+ctx.arc(Infinity, Infinity, 50, 0, 2*Math.PI, true);
+ctx.arc(Infinity, Infinity, Infinity, 0, 2*Math.PI, true);
+ctx.arc(Infinity, Infinity, Infinity, Infinity, 2*Math.PI, true);
+ctx.arc(Infinity, Infinity, Infinity, Infinity, Infinity, true);
+ctx.arc(Infinity, Infinity, Infinity, 0, Infinity, true);
+ctx.arc(Infinity, Infinity, 50, Infinity, 2*Math.PI, true);
+ctx.arc(Infinity, Infinity, 50, Infinity, Infinity, true);
+ctx.arc(Infinity, Infinity, 50, 0, Infinity, true);
+ctx.arc(Infinity, 0, Infinity, 0, 2*Math.PI, true);
+ctx.arc(Infinity, 0, Infinity, Infinity, 2*Math.PI, true);
+ctx.arc(Infinity, 0, Infinity, Infinity, Infinity, true);
+ctx.arc(Infinity, 0, Infinity, 0, Infinity, true);
+ctx.arc(Infinity, 0, 50, Infinity, 2*Math.PI, true);
+ctx.arc(Infinity, 0, 50, Infinity, Infinity, true);
+ctx.arc(Infinity, 0, 50, 0, Infinity, true);
+ctx.arc(0, Infinity, Infinity, 0, 2*Math.PI, true);
+ctx.arc(0, Infinity, Infinity, Infinity, 2*Math.PI, true);
+ctx.arc(0, Infinity, Infinity, Infinity, Infinity, true);
+ctx.arc(0, Infinity, Infinity, 0, Infinity, true);
+ctx.arc(0, Infinity, 50, Infinity, 2*Math.PI, true);
+ctx.arc(0, Infinity, 50, Infinity, Infinity, true);
+ctx.arc(0, Infinity, 50, 0, Infinity, true);
+ctx.arc(0, 0, Infinity, Infinity, 2*Math.PI, true);
+ctx.arc(0, 0, Infinity, Infinity, Infinity, true);
+ctx.arc(0, 0, Infinity, 0, Infinity, true);
+ctx.arc(0, 0, 50, Infinity, Infinity, true);
+ctx.lineTo(100, 50);
+ctx.lineTo(0, 50);
+ctx.fillStyle = '#0f0';
+ctx.fill();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 90,45, 0,255,0,255, "90,45", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.scale.1.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.scale.1.html
new file mode 100644
index 00000000000..fcb2b52ae99
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.scale.1.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.arc.scale.1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.arc.scale.1</h1>
+<p class="desc">Non-uniformly scaled arcs are the right shape</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Non-uniformly scaled arcs are the right shape");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.scale(2, 0.5);
+ctx.fillStyle = '#0f0';
+ctx.beginPath();
+ctx.arc(25, 50, 56, 0, 2*Math.PI, false);
+ctx.fill();
+ctx.fillStyle = '#f00';
+ctx.beginPath();
+ctx.moveTo(-25, 50);
+ctx.arc(-25, 50, 24, 0, 2*Math.PI, false);
+ctx.moveTo(75, 50);
+ctx.arc(75, 50, 24, 0, 2*Math.PI, false);
+ctx.moveTo(25, -25);
+ctx.arc(25, -25, 24, 0, 2*Math.PI, false);
+ctx.moveTo(25, 125);
+ctx.arc(25, 125, 24, 0, 2*Math.PI, false);
+ctx.fill();
+
+_assertPixel(canvas, 0,0, 0,255,0,255, "0,0", "0,255,0,255");
+_assertPixel(canvas, 50,0, 0,255,0,255, "50,0", "0,255,0,255");
+_assertPixel(canvas, 99,0, 0,255,0,255, "99,0", "0,255,0,255");
+_assertPixel(canvas, 0,25, 0,255,0,255, "0,25", "0,255,0,255");
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 99,25, 0,255,0,255, "99,25", "0,255,0,255");
+_assertPixel(canvas, 0,49, 0,255,0,255, "0,49", "0,255,0,255");
+_assertPixel(canvas, 50,49, 0,255,0,255, "50,49", "0,255,0,255");
+_assertPixel(canvas, 99,49, 0,255,0,255, "99,49", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.scale.2.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.scale.2.html
new file mode 100644
index 00000000000..59d182c92f2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.scale.2.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.arc.scale.2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.arc.scale.2</h1>
+<p class="desc">Highly scaled arcs are the right shape</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Highly scaled arcs are the right shape");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.scale(100, 100);
+ctx.strokeStyle = '#0f0';
+ctx.lineWidth = 1.2;
+ctx.beginPath();
+ctx.arc(0, 0, 0.6, 0, Math.PI/2, false);
+ctx.stroke();
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 50,1, 0,255,0,255, "50,1", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 1,25, 0,255,0,255, "1,25", "0,255,0,255");
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 98,25, 0,255,0,255, "98,25", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 50,48, 0,255,0,255, "50,48", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.selfintersect.1.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.selfintersect.1.html
new file mode 100644
index 00000000000..e212b49b45a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.selfintersect.1.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.arc.selfintersect.1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.arc.selfintersect.1</h1>
+<p class="desc">arc() with lineWidth > 2*radius is drawn sensibly</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("arc() with lineWidth > 2*radius is drawn sensibly");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.lineWidth = 200;
+ctx.strokeStyle = '#f00';
+ctx.beginPath();
+ctx.arc(100, 50, 25, 0, -Math.PI/2, true);
+ctx.stroke();
+ctx.beginPath();
+ctx.arc(0, 0, 25, 0, -Math.PI/2, true);
+ctx.stroke();
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.selfintersect.2.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.selfintersect.2.html
new file mode 100644
index 00000000000..8bc9fea70f4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.selfintersect.2.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.arc.selfintersect.2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.arc.selfintersect.2</h1>
+<p class="desc">arc() with lineWidth > 2*radius is drawn sensibly</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("arc() with lineWidth > 2*radius is drawn sensibly");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.lineWidth = 180;
+ctx.strokeStyle = '#0f0';
+ctx.beginPath();
+ctx.arc(-50, 50, 25, 0, -Math.PI/2, true);
+ctx.stroke();
+ctx.beginPath();
+ctx.arc(100, 0, 25, 0, -Math.PI/2, true);
+ctx.stroke();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 90,10, 0,255,0,255, "90,10", "0,255,0,255");
+_assertPixel(canvas, 97,1, 0,255,0,255, "97,1", "0,255,0,255");
+_assertPixel(canvas, 97,2, 0,255,0,255, "97,2", "0,255,0,255");
+_assertPixel(canvas, 97,3, 0,255,0,255, "97,3", "0,255,0,255");
+_assertPixel(canvas, 2,48, 0,255,0,255, "2,48", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.shape.1.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.shape.1.html
new file mode 100644
index 00000000000..dcaac9bb163
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.shape.1.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.arc.shape.1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.arc.shape.1</h1>
+<p class="desc">arc() from 0 to pi does not draw anything in the wrong half</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("arc() from 0 to pi does not draw anything in the wrong half");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.lineWidth = 50;
+ctx.strokeStyle = '#f00';
+ctx.beginPath();
+ctx.arc(50, 50, 50, 0, Math.PI, false);
+ctx.stroke();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 20,48, 0,255,0,255, "20,48", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.shape.2.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.shape.2.html
new file mode 100644
index 00000000000..dee4b3841da
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.shape.2.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.arc.shape.2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.arc.shape.2</h1>
+<p class="desc">arc() from 0 to pi draws stuff in the right half</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("arc() from 0 to pi draws stuff in the right half");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.lineWidth = 100;
+ctx.strokeStyle = '#0f0';
+ctx.beginPath();
+ctx.arc(50, 50, 50, 0, Math.PI, true);
+ctx.stroke();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 20,48, 0,255,0,255, "20,48", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.shape.3.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.shape.3.html
new file mode 100644
index 00000000000..0090411faf0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.shape.3.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.arc.shape.3</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.arc.shape.3</h1>
+<p class="desc">arc() from 0 to -pi/2 does not draw anything in the wrong quadrant</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("arc() from 0 to -pi/2 does not draw anything in the wrong quadrant");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.lineWidth = 100;
+ctx.strokeStyle = '#f00';
+ctx.beginPath();
+ctx.arc(0, 50, 50, 0, -Math.PI/2, false);
+ctx.stroke();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.shape.4.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.shape.4.html
new file mode 100644
index 00000000000..dc12ef6c116
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.shape.4.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.arc.shape.4</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.arc.shape.4</h1>
+<p class="desc">arc() from 0 to -pi/2 draws stuff in the right quadrant</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("arc() from 0 to -pi/2 draws stuff in the right quadrant");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.lineWidth = 150;
+ctx.strokeStyle = '#0f0';
+ctx.beginPath();
+ctx.arc(-50, 50, 100, 0, -Math.PI/2, true);
+ctx.stroke();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.shape.5.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.shape.5.html
new file mode 100644
index 00000000000..2a84dde748b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.shape.5.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.arc.shape.5</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.arc.shape.5</h1>
+<p class="desc">arc() from 0 to 5pi does not draw crazy things</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("arc() from 0 to 5pi does not draw crazy things");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.lineWidth = 200;
+ctx.strokeStyle = '#f00';
+ctx.beginPath();
+ctx.arc(300, 0, 100, 0, 5*Math.PI, false);
+ctx.stroke();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.twopie.1.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.twopie.1.html
new file mode 100644
index 00000000000..25fc393aa9d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.twopie.1.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.arc.twopie.1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.arc.twopie.1</h1>
+<p class="desc">arc() draws nothing when end = start + 2pi-e and anticlockwise</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("arc() draws nothing when end = start + 2pi-e and anticlockwise");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.strokeStyle = '#f00';
+ctx.lineWidth = 100;
+ctx.beginPath();
+ctx.arc(50, 25, 50, 0, 2*Math.PI - 1e-4, true);
+ctx.stroke();
+_assertPixel(canvas, 50,20, 0,255,0,255, "50,20", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.twopie.2.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.twopie.2.html
new file mode 100644
index 00000000000..775a87c223a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.twopie.2.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.arc.twopie.2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.arc.twopie.2</h1>
+<p class="desc">arc() draws a full circle when end = start + 2pi-e and clockwise</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("arc() draws a full circle when end = start + 2pi-e and clockwise");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.strokeStyle = '#0f0';
+ctx.lineWidth = 100;
+ctx.beginPath();
+ctx.arc(50, 25, 50, 0, 2*Math.PI - 1e-4, false);
+ctx.stroke();
+_assertPixel(canvas, 50,20, 0,255,0,255, "50,20", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.twopie.3.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.twopie.3.html
new file mode 100644
index 00000000000..19680022f74
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.twopie.3.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.arc.twopie.3</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.arc.twopie.3</h1>
+<p class="desc">arc() draws a full circle when end = start + 2pi+e and anticlockwise</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("arc() draws a full circle when end = start + 2pi+e and anticlockwise");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.strokeStyle = '#0f0';
+ctx.lineWidth = 100;
+ctx.beginPath();
+ctx.arc(50, 25, 50, 0, 2*Math.PI + 1e-4, true);
+ctx.stroke();
+_assertPixel(canvas, 50,20, 0,255,0,255, "50,20", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.twopie.4.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.twopie.4.html
new file mode 100644
index 00000000000..bddf7fb49b2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.twopie.4.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.arc.twopie.4</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.arc.twopie.4</h1>
+<p class="desc">arc() draws nothing when end = start + 2pi+e and clockwise</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("arc() draws nothing when end = start + 2pi+e and clockwise");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.strokeStyle = '#0f0';
+ctx.lineWidth = 100;
+ctx.beginPath();
+ctx.arc(50, 25, 50, 0, 2*Math.PI + 1e-4, false);
+ctx.stroke();
+_assertPixel(canvas, 50,20, 0,255,0,255, "50,20", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.zero.1.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.zero.1.html
new file mode 100644
index 00000000000..e18a84919f4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.zero.1.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.arc.zero.1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.arc.zero.1</h1>
+<p class="desc">arc() draws nothing when startAngle = endAngle and anticlockwise</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("arc() draws nothing when startAngle = endAngle and anticlockwise");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.strokeStyle = '#f00';
+ctx.lineWidth = 100;
+ctx.beginPath();
+ctx.arc(50, 25, 50, 0, 0, true);
+ctx.stroke();
+_assertPixel(canvas, 50,20, 0,255,0,255, "50,20", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.zero.2.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.zero.2.html
new file mode 100644
index 00000000000..398a74d2aae
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.zero.2.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.arc.zero.2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.arc.zero.2</h1>
+<p class="desc">arc() draws nothing when startAngle = endAngle and clockwise</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("arc() draws nothing when startAngle = endAngle and clockwise");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.strokeStyle = '#f00';
+ctx.lineWidth = 100;
+ctx.beginPath();
+ctx.arc(50, 25, 50, 0, 0, false);
+ctx.stroke();
+_assertPixel(canvas, 50,20, 0,255,0,255, "50,20", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.zeroradius.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.zeroradius.html
new file mode 100644
index 00000000000..af1ccf74129
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arc.zeroradius.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.arc.zeroradius</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.arc.zeroradius</h1>
+<p class="desc">arc() with zero radius draws a line to the start point</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("arc() with zero radius draws a line to the start point");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00'
+ctx.fillRect(0, 0, 100, 50);
+ctx.lineWidth = 50;
+ctx.strokeStyle = '#0f0';
+ctx.beginPath();
+ctx.moveTo(0, 25);
+ctx.arc(200, 25, 0, 0, Math.PI, true);
+ctx.stroke();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.coincide.1.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.coincide.1.html
new file mode 100644
index 00000000000..936034e38d9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.coincide.1.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.arcTo.coincide.1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.arcTo.coincide.1</h1>
+<p class="desc">arcTo() has no effect if P0 = P1</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("arcTo() has no effect if P0 = P1");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.lineWidth = 50;
+
+ctx.strokeStyle = '#0f0';
+ctx.beginPath();
+ctx.moveTo(0, 25);
+ctx.arcTo(0, 25, 50, 1000, 1);
+ctx.lineTo(100, 25);
+ctx.stroke();
+
+ctx.strokeStyle = '#f00';
+ctx.beginPath();
+ctx.moveTo(50, 25);
+ctx.arcTo(50, 25, 100, 25, 1);
+ctx.stroke();
+
+_assertPixel(canvas, 50,1, 0,255,0,255, "50,1", "0,255,0,255");
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 50,48, 0,255,0,255, "50,48", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.coincide.2.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.coincide.2.html
new file mode 100644
index 00000000000..c64fa4c81a2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.coincide.2.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.arcTo.coincide.2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.arcTo.coincide.2</h1>
+<p class="desc">arcTo() draws a straight line to P1 if P1 = P2</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("arcTo() draws a straight line to P1 if P1 = P2");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.lineWidth = 50;
+ctx.strokeStyle = '#0f0';
+ctx.beginPath();
+ctx.moveTo(0, 25);
+ctx.arcTo(100, 25, 100, 25, 1);
+ctx.stroke();
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.collinear.1.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.collinear.1.html
new file mode 100644
index 00000000000..196dbc4459d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.collinear.1.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.arcTo.collinear.1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.arcTo.collinear.1</h1>
+<p class="desc">arcTo() with all points on a line, and P1 between P0/P2, draws a straight line to P1</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("arcTo() with all points on a line, and P1 between P0/P2, draws a straight line to P1");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.lineWidth = 50;
+
+ctx.strokeStyle = '#0f0';
+ctx.beginPath();
+ctx.moveTo(0, 25);
+ctx.arcTo(100, 25, 200, 25, 1);
+ctx.stroke();
+
+ctx.strokeStyle = '#f00';
+ctx.beginPath();
+ctx.moveTo(-100, 25);
+ctx.arcTo(0, 25, 100, 25, 1);
+ctx.stroke();
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.collinear.2.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.collinear.2.html
new file mode 100644
index 00000000000..75998b308f4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.collinear.2.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.arcTo.collinear.2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.arcTo.collinear.2</h1>
+<p class="desc">arcTo() with all points on a line, and P2 between P0/P1, draws a straight line to P1</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("arcTo() with all points on a line, and P2 between P0/P1, draws a straight line to P1");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.lineWidth = 50;
+
+ctx.strokeStyle = '#0f0';
+ctx.beginPath();
+ctx.moveTo(0, 25);
+ctx.arcTo(100, 25, 10, 25, 1);
+ctx.stroke();
+
+ctx.strokeStyle = '#f00';
+ctx.beginPath();
+ctx.moveTo(100, 25);
+ctx.arcTo(200, 25, 110, 25, 1);
+ctx.stroke();
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.collinear.3.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.collinear.3.html
new file mode 100644
index 00000000000..8a0e9a8887b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.collinear.3.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.arcTo.collinear.3</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.arcTo.collinear.3</h1>
+<p class="desc">arcTo() with all points on a line, and P0 between P1/P2, draws a straight line to P1</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("arcTo() with all points on a line, and P0 between P1/P2, draws a straight line to P1");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.lineWidth = 50;
+
+ctx.strokeStyle = '#0f0';
+ctx.beginPath();
+ctx.moveTo(0, 25);
+ctx.arcTo(100, 25, -100, 25, 1);
+ctx.stroke();
+
+ctx.strokeStyle = '#f00';
+ctx.beginPath();
+ctx.moveTo(100, 25);
+ctx.arcTo(200, 25, 0, 25, 1);
+ctx.stroke();
+
+ctx.beginPath();
+ctx.moveTo(-100, 25);
+ctx.arcTo(0, 25, -200, 25, 1);
+ctx.stroke();
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.ensuresubpath.1.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.ensuresubpath.1.html
new file mode 100644
index 00000000000..cae097116ab
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.ensuresubpath.1.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.arcTo.ensuresubpath.1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.arcTo.ensuresubpath.1</h1>
+<p class="desc">If there is no subpath, the first control point is added (and nothing is drawn up to it)</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("If there is no subpath, the first control point is added (and nothing is drawn up to it)");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.lineWidth = 50;
+ctx.strokeStyle = '#f00';
+ctx.beginPath();
+ctx.arcTo(100, 50, 200, 50, 0.1);
+ctx.stroke();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.ensuresubpath.2.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.ensuresubpath.2.html
new file mode 100644
index 00000000000..4d25a84f446
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.ensuresubpath.2.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.arcTo.ensuresubpath.2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.arcTo.ensuresubpath.2</h1>
+<p class="desc">If there is no subpath, the first control point is added</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("If there is no subpath, the first control point is added");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.lineWidth = 50;
+ctx.strokeStyle = '#0f0';
+ctx.beginPath();
+ctx.arcTo(0, 25, 50, 250, 0.1); // adds (x1,y1), draws nothing
+ctx.lineTo(100, 25);
+ctx.stroke();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.negative.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.negative.html
new file mode 100644
index 00000000000..5aa7baa4c22
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.negative.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.arcTo.negative</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.arcTo.negative</h1>
+<p class="desc">arcTo() with negative radius throws an exception</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("arcTo() with negative radius throws an exception");
+_addTest(function(canvas, ctx) {
+
+assert_throws("INDEX_SIZE_ERR", function() { ctx.arcTo(0, 0, 0, 0, -1); });
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.nonfinite.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.nonfinite.html
new file mode 100644
index 00000000000..354d62186ed
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.nonfinite.html
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.arcTo.nonfinite</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.arcTo.nonfinite</h1>
+<p class="desc">arcTo() with Infinity/NaN is ignored</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("arcTo() with Infinity/NaN is ignored");
+_addTest(function(canvas, ctx) {
+
+ctx.moveTo(0, 0);
+ctx.lineTo(100, 0);
+ctx.arcTo(Infinity, 50, 0, 50, 0);
+ctx.arcTo(-Infinity, 50, 0, 50, 0);
+ctx.arcTo(NaN, 50, 0, 50, 0);
+ctx.arcTo(0, Infinity, 0, 50, 0);
+ctx.arcTo(0, -Infinity, 0, 50, 0);
+ctx.arcTo(0, NaN, 0, 50, 0);
+ctx.arcTo(0, 50, Infinity, 50, 0);
+ctx.arcTo(0, 50, -Infinity, 50, 0);
+ctx.arcTo(0, 50, NaN, 50, 0);
+ctx.arcTo(0, 50, 0, Infinity, 0);
+ctx.arcTo(0, 50, 0, -Infinity, 0);
+ctx.arcTo(0, 50, 0, NaN, 0);
+ctx.arcTo(0, 50, 0, 50, Infinity);
+ctx.arcTo(0, 50, 0, 50, -Infinity);
+ctx.arcTo(0, 50, 0, 50, NaN);
+ctx.arcTo(Infinity, Infinity, 0, 50, 0);
+ctx.arcTo(Infinity, Infinity, Infinity, 50, 0);
+ctx.arcTo(Infinity, Infinity, Infinity, Infinity, 0);
+ctx.arcTo(Infinity, Infinity, Infinity, Infinity, Infinity);
+ctx.arcTo(Infinity, Infinity, Infinity, 50, Infinity);
+ctx.arcTo(Infinity, Infinity, 0, Infinity, 0);
+ctx.arcTo(Infinity, Infinity, 0, Infinity, Infinity);
+ctx.arcTo(Infinity, Infinity, 0, 50, Infinity);
+ctx.arcTo(Infinity, 50, Infinity, 50, 0);
+ctx.arcTo(Infinity, 50, Infinity, Infinity, 0);
+ctx.arcTo(Infinity, 50, Infinity, Infinity, Infinity);
+ctx.arcTo(Infinity, 50, Infinity, 50, Infinity);
+ctx.arcTo(Infinity, 50, 0, Infinity, 0);
+ctx.arcTo(Infinity, 50, 0, Infinity, Infinity);
+ctx.arcTo(Infinity, 50, 0, 50, Infinity);
+ctx.arcTo(0, Infinity, Infinity, 50, 0);
+ctx.arcTo(0, Infinity, Infinity, Infinity, 0);
+ctx.arcTo(0, Infinity, Infinity, Infinity, Infinity);
+ctx.arcTo(0, Infinity, Infinity, 50, Infinity);
+ctx.arcTo(0, Infinity, 0, Infinity, 0);
+ctx.arcTo(0, Infinity, 0, Infinity, Infinity);
+ctx.arcTo(0, Infinity, 0, 50, Infinity);
+ctx.arcTo(0, 50, Infinity, Infinity, 0);
+ctx.arcTo(0, 50, Infinity, Infinity, Infinity);
+ctx.arcTo(0, 50, Infinity, 50, Infinity);
+ctx.arcTo(0, 50, 0, Infinity, Infinity);
+ctx.lineTo(100, 50);
+ctx.lineTo(0, 50);
+ctx.fillStyle = '#0f0';
+ctx.fill();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 90,45, 0,255,0,255, "90,45", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.scale.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.scale.html
new file mode 100644
index 00000000000..0de2336d7c5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.scale.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.arcTo.scale</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.arcTo.scale</h1>
+<p class="desc">arcTo scales the curve, not just the control points</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("arcTo scales the curve, not just the control points");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.fillStyle = '#0f0';
+ctx.beginPath();
+ctx.moveTo(0, 50);
+ctx.translate(100, 0);
+ctx.scale(0.1, 1);
+ctx.arcTo(50, 50, 50, 0, 50);
+ctx.lineTo(-1000, 0);
+ctx.fill();
+
+_assertPixel(canvas, 0,0, 0,255,0,255, "0,0", "0,255,0,255");
+_assertPixel(canvas, 50,0, 0,255,0,255, "50,0", "0,255,0,255");
+_assertPixel(canvas, 99,0, 0,255,0,255, "99,0", "0,255,0,255");
+_assertPixel(canvas, 0,25, 0,255,0,255, "0,25", "0,255,0,255");
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 99,25, 0,255,0,255, "99,25", "0,255,0,255");
+_assertPixel(canvas, 0,49, 0,255,0,255, "0,49", "0,255,0,255");
+_assertPixel(canvas, 50,49, 0,255,0,255, "50,49", "0,255,0,255");
+_assertPixel(canvas, 99,49, 0,255,0,255, "99,49", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.shape.curve1.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.shape.curve1.html
new file mode 100644
index 00000000000..fa06b5bd1aa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.shape.curve1.html
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.arcTo.shape.curve1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.arcTo.shape.curve1</h1>
+<p class="desc">arcTo() curves in the right kind of shape</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("arcTo() curves in the right kind of shape");
+_addTest(function(canvas, ctx) {
+
+var tol = 1.5; // tolerance to avoid antialiasing artifacts
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.strokeStyle = '#f00';
+ctx.lineWidth = 10;
+ctx.beginPath();
+ctx.moveTo(10, 25);
+ctx.arcTo(75, 25, 75, 60, 20);
+ctx.stroke();
+
+ctx.fillStyle = '#0f0';
+ctx.beginPath();
+ctx.rect(10, 20, 45, 10);
+ctx.moveTo(80, 45);
+ctx.arc(55, 45, 25+tol, 0, -Math.PI/2, true);
+ctx.arc(55, 45, 15-tol, -Math.PI/2, 0, false);
+ctx.fill();
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 55,19, 0,255,0,255, "55,19", "0,255,0,255");
+_assertPixel(canvas, 55,20, 0,255,0,255, "55,20", "0,255,0,255");
+_assertPixel(canvas, 55,21, 0,255,0,255, "55,21", "0,255,0,255");
+_assertPixel(canvas, 64,22, 0,255,0,255, "64,22", "0,255,0,255");
+_assertPixel(canvas, 65,21, 0,255,0,255, "65,21", "0,255,0,255");
+_assertPixel(canvas, 72,28, 0,255,0,255, "72,28", "0,255,0,255");
+_assertPixel(canvas, 73,27, 0,255,0,255, "73,27", "0,255,0,255");
+_assertPixel(canvas, 78,36, 0,255,0,255, "78,36", "0,255,0,255");
+_assertPixel(canvas, 79,35, 0,255,0,255, "79,35", "0,255,0,255");
+_assertPixel(canvas, 80,44, 0,255,0,255, "80,44", "0,255,0,255");
+_assertPixel(canvas, 80,45, 0,255,0,255, "80,45", "0,255,0,255");
+_assertPixel(canvas, 80,46, 0,255,0,255, "80,46", "0,255,0,255");
+_assertPixel(canvas, 65,45, 0,255,0,255, "65,45", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.shape.curve2.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.shape.curve2.html
new file mode 100644
index 00000000000..ae0722c54dc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.shape.curve2.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.arcTo.shape.curve2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.arcTo.shape.curve2</h1>
+<p class="desc">arcTo() curves in the right kind of shape</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("arcTo() curves in the right kind of shape");
+_addTest(function(canvas, ctx) {
+
+var tol = 1.5; // tolerance to avoid antialiasing artifacts
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.fillStyle = '#f00';
+ctx.beginPath();
+ctx.rect(10, 20, 45, 10);
+ctx.moveTo(80, 45);
+ctx.arc(55, 45, 25-tol, 0, -Math.PI/2, true);
+ctx.arc(55, 45, 15+tol, -Math.PI/2, 0, false);
+ctx.fill();
+
+ctx.strokeStyle = '#0f0';
+ctx.lineWidth = 10;
+ctx.beginPath();
+ctx.moveTo(10, 25);
+ctx.arcTo(75, 25, 75, 60, 20);
+ctx.stroke();
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 55,19, 0,255,0,255, "55,19", "0,255,0,255");
+_assertPixel(canvas, 55,20, 0,255,0,255, "55,20", "0,255,0,255");
+_assertPixel(canvas, 55,21, 0,255,0,255, "55,21", "0,255,0,255");
+_assertPixel(canvas, 64,22, 0,255,0,255, "64,22", "0,255,0,255");
+_assertPixel(canvas, 65,21, 0,255,0,255, "65,21", "0,255,0,255");
+_assertPixel(canvas, 72,28, 0,255,0,255, "72,28", "0,255,0,255");
+_assertPixel(canvas, 73,27, 0,255,0,255, "73,27", "0,255,0,255");
+_assertPixel(canvas, 78,36, 0,255,0,255, "78,36", "0,255,0,255");
+_assertPixel(canvas, 79,35, 0,255,0,255, "79,35", "0,255,0,255");
+_assertPixel(canvas, 80,44, 0,255,0,255, "80,44", "0,255,0,255");
+_assertPixel(canvas, 80,45, 0,255,0,255, "80,45", "0,255,0,255");
+_assertPixel(canvas, 80,46, 0,255,0,255, "80,46", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.shape.end.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.shape.end.html
new file mode 100644
index 00000000000..44137138b4c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.shape.end.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.arcTo.shape.end</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.arcTo.shape.end</h1>
+<p class="desc">arcTo() does not draw anything from P1 to P2</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("arcTo() does not draw anything from P1 to P2");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.strokeStyle = '#f00';
+ctx.lineWidth = 50;
+ctx.beginPath();
+ctx.moveTo(-100, -100);
+ctx.arcTo(-100, 25, 200, 25, 10);
+ctx.stroke();
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.shape.start.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.shape.start.html
new file mode 100644
index 00000000000..c7677af8dc0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.shape.start.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.arcTo.shape.start</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.arcTo.shape.start</h1>
+<p class="desc">arcTo() draws a straight line from P0 to P1</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("arcTo() draws a straight line from P0 to P1");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.strokeStyle = '#0f0';
+ctx.lineWidth = 50;
+ctx.beginPath();
+ctx.moveTo(0, 25);
+ctx.arcTo(200, 25, 200, 50, 10);
+ctx.stroke();
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.transformation.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.transformation.html
new file mode 100644
index 00000000000..351495c3882
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.transformation.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.arcTo.transformation</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.arcTo.transformation</h1>
+<p class="desc">arcTo joins up to the last subpath point correctly</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("arcTo joins up to the last subpath point correctly");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.fillStyle = '#0f0';
+ctx.beginPath();
+ctx.moveTo(0, 50);
+ctx.translate(100, 0);
+ctx.arcTo(50, 50, 50, 0, 50);
+ctx.lineTo(-100, 0);
+ctx.fill();
+
+_assertPixel(canvas, 0,0, 0,255,0,255, "0,0", "0,255,0,255");
+_assertPixel(canvas, 50,0, 0,255,0,255, "50,0", "0,255,0,255");
+_assertPixel(canvas, 99,0, 0,255,0,255, "99,0", "0,255,0,255");
+_assertPixel(canvas, 0,25, 0,255,0,255, "0,25", "0,255,0,255");
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 99,25, 0,255,0,255, "99,25", "0,255,0,255");
+_assertPixel(canvas, 0,49, 0,255,0,255, "0,49", "0,255,0,255");
+_assertPixel(canvas, 50,49, 0,255,0,255, "50,49", "0,255,0,255");
+_assertPixel(canvas, 99,49, 0,255,0,255, "99,49", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.zero.1.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.zero.1.html
new file mode 100644
index 00000000000..fa172b5a9a5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.zero.1.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.arcTo.zero.1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.arcTo.zero.1</h1>
+<p class="desc">arcTo() with zero radius draws a straight line from P0 to P1</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("arcTo() with zero radius draws a straight line from P0 to P1");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.lineWidth = 50;
+
+ctx.strokeStyle = '#0f0';
+ctx.beginPath();
+ctx.moveTo(0, 25);
+ctx.arcTo(100, 25, 100, 100, 0);
+ctx.stroke();
+
+ctx.strokeStyle = '#f00';
+ctx.beginPath();
+ctx.moveTo(0, -25);
+ctx.arcTo(50, -25, 50, 50, 0);
+ctx.stroke();
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.zero.2.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.zero.2.html
new file mode 100644
index 00000000000..ede4480fd31
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.arcTo.zero.2.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.arcTo.zero.2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.arcTo.zero.2</h1>
+<p class="desc">arcTo() with zero radius draws a straight line from P0 to P1, even when all points are collinear</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("arcTo() with zero radius draws a straight line from P0 to P1, even when all points are collinear");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.lineWidth = 50;
+
+ctx.strokeStyle = '#0f0';
+ctx.beginPath();
+ctx.moveTo(0, 25);
+ctx.arcTo(100, 25, -100, 25, 0);
+ctx.stroke();
+
+ctx.strokeStyle = '#f00';
+ctx.beginPath();
+ctx.moveTo(100, 25);
+ctx.arcTo(200, 25, 50, 25, 0);
+ctx.stroke();
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.beginPath.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.beginPath.html
new file mode 100644
index 00000000000..86c7b0721c2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.beginPath.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.beginPath</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.beginPath</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.rect(0, 0, 100, 50);
+ctx.beginPath();
+ctx.fillStyle = '#f00';
+ctx.fill();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.bezierCurveTo.basic.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.bezierCurveTo.basic.html
new file mode 100644
index 00000000000..2628fee4567
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.bezierCurveTo.basic.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.bezierCurveTo.basic</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.bezierCurveTo.basic</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.strokeStyle = '#0f0';
+ctx.lineWidth = 50;
+ctx.beginPath();
+ctx.moveTo(0, 25);
+ctx.bezierCurveTo(100, 25, 100, 25, 100, 25);
+ctx.stroke();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.bezierCurveTo.ensuresubpath.1.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.bezierCurveTo.ensuresubpath.1.html
new file mode 100644
index 00000000000..37f3c6a9a9d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.bezierCurveTo.ensuresubpath.1.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.bezierCurveTo.ensuresubpath.1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.bezierCurveTo.ensuresubpath.1</h1>
+<p class="desc">If there is no subpath, the first control point is added (and nothing is drawn up to it)</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("If there is no subpath, the first control point is added (and nothing is drawn up to it)");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.strokeStyle = '#f00';
+ctx.lineWidth = 50;
+ctx.beginPath();
+ctx.bezierCurveTo(100, 50, 200, 50, 200, 50);
+ctx.stroke();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 95,45, 0,255,0,255, "95,45", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.bezierCurveTo.ensuresubpath.2.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.bezierCurveTo.ensuresubpath.2.html
new file mode 100644
index 00000000000..4fd2a0e3c55
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.bezierCurveTo.ensuresubpath.2.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.bezierCurveTo.ensuresubpath.2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.bezierCurveTo.ensuresubpath.2</h1>
+<p class="desc">If there is no subpath, the first control point is added</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("If there is no subpath, the first control point is added");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.strokeStyle = '#0f0';
+ctx.lineWidth = 50;
+ctx.beginPath();
+ctx.bezierCurveTo(0, 25, 100, 25, 100, 25);
+ctx.stroke();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 5,45, 0,255,0,255, "5,45", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.bezierCurveTo.nonfinite.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.bezierCurveTo.nonfinite.html
new file mode 100644
index 00000000000..28639c657f1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.bezierCurveTo.nonfinite.html
@@ -0,0 +1,109 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.bezierCurveTo.nonfinite</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.bezierCurveTo.nonfinite</h1>
+<p class="desc">bezierCurveTo() with Infinity/NaN is ignored</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("bezierCurveTo() with Infinity/NaN is ignored");
+_addTest(function(canvas, ctx) {
+
+ctx.moveTo(0, 0);
+ctx.lineTo(100, 0);
+ctx.bezierCurveTo(Infinity, 50, 0, 50, 0, 50);
+ctx.bezierCurveTo(-Infinity, 50, 0, 50, 0, 50);
+ctx.bezierCurveTo(NaN, 50, 0, 50, 0, 50);
+ctx.bezierCurveTo(0, Infinity, 0, 50, 0, 50);
+ctx.bezierCurveTo(0, -Infinity, 0, 50, 0, 50);
+ctx.bezierCurveTo(0, NaN, 0, 50, 0, 50);
+ctx.bezierCurveTo(0, 50, Infinity, 50, 0, 50);
+ctx.bezierCurveTo(0, 50, -Infinity, 50, 0, 50);
+ctx.bezierCurveTo(0, 50, NaN, 50, 0, 50);
+ctx.bezierCurveTo(0, 50, 0, Infinity, 0, 50);
+ctx.bezierCurveTo(0, 50, 0, -Infinity, 0, 50);
+ctx.bezierCurveTo(0, 50, 0, NaN, 0, 50);
+ctx.bezierCurveTo(0, 50, 0, 50, Infinity, 50);
+ctx.bezierCurveTo(0, 50, 0, 50, -Infinity, 50);
+ctx.bezierCurveTo(0, 50, 0, 50, NaN, 50);
+ctx.bezierCurveTo(0, 50, 0, 50, 0, Infinity);
+ctx.bezierCurveTo(0, 50, 0, 50, 0, -Infinity);
+ctx.bezierCurveTo(0, 50, 0, 50, 0, NaN);
+ctx.bezierCurveTo(Infinity, Infinity, 0, 50, 0, 50);
+ctx.bezierCurveTo(Infinity, Infinity, Infinity, 50, 0, 50);
+ctx.bezierCurveTo(Infinity, Infinity, Infinity, Infinity, 0, 50);
+ctx.bezierCurveTo(Infinity, Infinity, Infinity, Infinity, Infinity, 50);
+ctx.bezierCurveTo(Infinity, Infinity, Infinity, Infinity, Infinity, Infinity);
+ctx.bezierCurveTo(Infinity, Infinity, Infinity, Infinity, 0, Infinity);
+ctx.bezierCurveTo(Infinity, Infinity, Infinity, 50, Infinity, 50);
+ctx.bezierCurveTo(Infinity, Infinity, Infinity, 50, Infinity, Infinity);
+ctx.bezierCurveTo(Infinity, Infinity, Infinity, 50, 0, Infinity);
+ctx.bezierCurveTo(Infinity, Infinity, 0, Infinity, 0, 50);
+ctx.bezierCurveTo(Infinity, Infinity, 0, Infinity, Infinity, 50);
+ctx.bezierCurveTo(Infinity, Infinity, 0, Infinity, Infinity, Infinity);
+ctx.bezierCurveTo(Infinity, Infinity, 0, Infinity, 0, Infinity);
+ctx.bezierCurveTo(Infinity, Infinity, 0, 50, Infinity, 50);
+ctx.bezierCurveTo(Infinity, Infinity, 0, 50, Infinity, Infinity);
+ctx.bezierCurveTo(Infinity, Infinity, 0, 50, 0, Infinity);
+ctx.bezierCurveTo(Infinity, 50, Infinity, 50, 0, 50);
+ctx.bezierCurveTo(Infinity, 50, Infinity, Infinity, 0, 50);
+ctx.bezierCurveTo(Infinity, 50, Infinity, Infinity, Infinity, 50);
+ctx.bezierCurveTo(Infinity, 50, Infinity, Infinity, Infinity, Infinity);
+ctx.bezierCurveTo(Infinity, 50, Infinity, Infinity, 0, Infinity);
+ctx.bezierCurveTo(Infinity, 50, Infinity, 50, Infinity, 50);
+ctx.bezierCurveTo(Infinity, 50, Infinity, 50, Infinity, Infinity);
+ctx.bezierCurveTo(Infinity, 50, Infinity, 50, 0, Infinity);
+ctx.bezierCurveTo(Infinity, 50, 0, Infinity, 0, 50);
+ctx.bezierCurveTo(Infinity, 50, 0, Infinity, Infinity, 50);
+ctx.bezierCurveTo(Infinity, 50, 0, Infinity, Infinity, Infinity);
+ctx.bezierCurveTo(Infinity, 50, 0, Infinity, 0, Infinity);
+ctx.bezierCurveTo(Infinity, 50, 0, 50, Infinity, 50);
+ctx.bezierCurveTo(Infinity, 50, 0, 50, Infinity, Infinity);
+ctx.bezierCurveTo(Infinity, 50, 0, 50, 0, Infinity);
+ctx.bezierCurveTo(0, Infinity, Infinity, 50, 0, 50);
+ctx.bezierCurveTo(0, Infinity, Infinity, Infinity, 0, 50);
+ctx.bezierCurveTo(0, Infinity, Infinity, Infinity, Infinity, 50);
+ctx.bezierCurveTo(0, Infinity, Infinity, Infinity, Infinity, Infinity);
+ctx.bezierCurveTo(0, Infinity, Infinity, Infinity, 0, Infinity);
+ctx.bezierCurveTo(0, Infinity, Infinity, 50, Infinity, 50);
+ctx.bezierCurveTo(0, Infinity, Infinity, 50, Infinity, Infinity);
+ctx.bezierCurveTo(0, Infinity, Infinity, 50, 0, Infinity);
+ctx.bezierCurveTo(0, Infinity, 0, Infinity, 0, 50);
+ctx.bezierCurveTo(0, Infinity, 0, Infinity, Infinity, 50);
+ctx.bezierCurveTo(0, Infinity, 0, Infinity, Infinity, Infinity);
+ctx.bezierCurveTo(0, Infinity, 0, Infinity, 0, Infinity);
+ctx.bezierCurveTo(0, Infinity, 0, 50, Infinity, 50);
+ctx.bezierCurveTo(0, Infinity, 0, 50, Infinity, Infinity);
+ctx.bezierCurveTo(0, Infinity, 0, 50, 0, Infinity);
+ctx.bezierCurveTo(0, 50, Infinity, Infinity, 0, 50);
+ctx.bezierCurveTo(0, 50, Infinity, Infinity, Infinity, 50);
+ctx.bezierCurveTo(0, 50, Infinity, Infinity, Infinity, Infinity);
+ctx.bezierCurveTo(0, 50, Infinity, Infinity, 0, Infinity);
+ctx.bezierCurveTo(0, 50, Infinity, 50, Infinity, 50);
+ctx.bezierCurveTo(0, 50, Infinity, 50, Infinity, Infinity);
+ctx.bezierCurveTo(0, 50, Infinity, 50, 0, Infinity);
+ctx.bezierCurveTo(0, 50, 0, Infinity, Infinity, 50);
+ctx.bezierCurveTo(0, 50, 0, Infinity, Infinity, Infinity);
+ctx.bezierCurveTo(0, 50, 0, Infinity, 0, Infinity);
+ctx.bezierCurveTo(0, 50, 0, 50, Infinity, Infinity);
+ctx.lineTo(100, 50);
+ctx.lineTo(0, 50);
+ctx.fillStyle = '#0f0';
+ctx.fill();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 90,45, 0,255,0,255, "90,45", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.bezierCurveTo.scaled.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.bezierCurveTo.scaled.html
new file mode 100644
index 00000000000..6546d5d6489
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.bezierCurveTo.scaled.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.bezierCurveTo.scaled</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.bezierCurveTo.scaled</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.scale(1000, 1000);
+ctx.strokeStyle = '#0f0';
+ctx.lineWidth = 0.055;
+ctx.beginPath();
+ctx.moveTo(-2, 3.1);
+ctx.bezierCurveTo(-2, -1, 2.1, -1, 2.1, 3.1);
+ctx.stroke();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.bezierCurveTo.shape.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.bezierCurveTo.shape.html
new file mode 100644
index 00000000000..26b502a982e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.bezierCurveTo.shape.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.bezierCurveTo.shape</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.bezierCurveTo.shape</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.strokeStyle = '#0f0';
+ctx.lineWidth = 55;
+ctx.beginPath();
+ctx.moveTo(-2000, 3100);
+ctx.bezierCurveTo(-2000, -1000, 2100, -1000, 2100, 3100);
+ctx.stroke();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.clip.basic.1.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.clip.basic.1.html
new file mode 100644
index 00000000000..e15a0e3bb6c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.clip.basic.1.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.clip.basic.1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.clip.basic.1</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.beginPath();
+ctx.rect(0, 0, 100, 50);
+ctx.clip();
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.clip.basic.2.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.clip.basic.2.html
new file mode 100644
index 00000000000..65f9eff737e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.clip.basic.2.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.clip.basic.2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.clip.basic.2</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.beginPath();
+ctx.rect(-100, 0, 100, 50);
+ctx.clip();
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.clip.empty.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.clip.empty.html
new file mode 100644
index 00000000000..9a437b16e4a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.clip.empty.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.clip.empty</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.clip.empty</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.beginPath();
+ctx.clip();
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.clip.intersect.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.clip.intersect.html
new file mode 100644
index 00000000000..3ef64feb365
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.clip.intersect.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.clip.intersect</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.clip.intersect</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.beginPath();
+ctx.rect(0, 0, 50, 50);
+ctx.clip();
+ctx.beginPath();
+ctx.rect(50, 0, 50, 50)
+ctx.clip();
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.clip.unaffected.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.clip.unaffected.html
new file mode 100644
index 00000000000..606c3417444
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.clip.unaffected.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.clip.unaffected</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.clip.unaffected</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.fillStyle = '#0f0';
+
+ctx.beginPath();
+ctx.moveTo(0, 0);
+ctx.lineTo(0, 50);
+ctx.lineTo(100, 50);
+ctx.lineTo(100, 0);
+ctx.clip();
+
+ctx.lineTo(0, 0);
+ctx.fill();
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.clip.winding.1.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.clip.winding.1.html
new file mode 100644
index 00000000000..9fe007b4093
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.clip.winding.1.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.clip.winding.1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.clip.winding.1</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.beginPath();
+ctx.moveTo(-10, -10);
+ctx.lineTo(110, -10);
+ctx.lineTo(110, 60);
+ctx.lineTo(-10, 60);
+ctx.lineTo(-10, -10);
+ctx.lineTo(0, 0);
+ctx.lineTo(0, 50);
+ctx.lineTo(100, 50);
+ctx.lineTo(100, 0);
+ctx.clip();
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.clip.winding.2.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.clip.winding.2.html
new file mode 100644
index 00000000000..dd9b6ad6cb0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.clip.winding.2.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.clip.winding.2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.clip.winding.2</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.beginPath();
+ctx.moveTo(-10, -10);
+ctx.lineTo(110, -10);
+ctx.lineTo(110, 60);
+ctx.lineTo(-10, 60);
+ctx.lineTo(-10, -10);
+ctx.clip();
+
+ctx.beginPath();
+ctx.moveTo(0, 0);
+ctx.lineTo(0, 50);
+ctx.lineTo(100, 50);
+ctx.lineTo(100, 0);
+ctx.lineTo(0, 0);
+ctx.clip();
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.closePath.empty.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.closePath.empty.html
new file mode 100644
index 00000000000..8ee68dc8397
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.closePath.empty.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.closePath.empty</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.closePath.empty</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.closePath();
+ctx.fillStyle = '#f00';
+ctx.fill();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.closePath.newline.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.closePath.newline.html
new file mode 100644
index 00000000000..391451e6f43
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.closePath.newline.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.closePath.newline</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.closePath.newline</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.strokeStyle = '#0f0';
+ctx.lineWidth = 50;
+ctx.moveTo(-100, 25);
+ctx.lineTo(-100, -100);
+ctx.lineTo(200, -100);
+ctx.lineTo(200, 25);
+ctx.closePath();
+ctx.stroke();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.closePath.nextpoint.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.closePath.nextpoint.html
new file mode 100644
index 00000000000..e98458b183f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.closePath.nextpoint.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.closePath.nextpoint</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.closePath.nextpoint</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.strokeStyle = '#0f0';
+ctx.lineWidth = 50;
+ctx.moveTo(-100, 25);
+ctx.lineTo(-100, -1000);
+ctx.closePath();
+ctx.lineTo(1000, 25);
+ctx.stroke();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.fill.closed.basic.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.fill.closed.basic.html
new file mode 100644
index 00000000000..b0fbee75451
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.fill.closed.basic.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.fill.closed.basic</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.fill.closed.basic</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.fillStyle = '#0f0';
+ctx.moveTo(0, 0);
+ctx.lineTo(100, 0);
+ctx.lineTo(100, 50);
+ctx.lineTo(0, 50);
+ctx.fill();
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.fill.closed.unaffected.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.fill.closed.unaffected.html
new file mode 100644
index 00000000000..a1d11287c66
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.fill.closed.unaffected.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.fill.closed.unaffected</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.fill.closed.unaffected</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#00f';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.moveTo(0, 0);
+ctx.lineTo(100, 0);
+ctx.lineTo(100, 50);
+ctx.fillStyle = '#f00';
+ctx.fill();
+ctx.lineTo(0, 50);
+ctx.fillStyle = '#0f0';
+ctx.fill();
+
+_assertPixel(canvas, 90,10, 0,255,0,255, "90,10", "0,255,0,255");
+_assertPixel(canvas, 10,40, 0,255,0,255, "10,40", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.fill.overlap.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.fill.overlap.html
new file mode 100644
index 00000000000..d69999c24c3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.fill.overlap.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.fill.overlap</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.fill.overlap</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.path.fill.overlap.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#000';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.fillStyle = 'rgba(0, 255, 0, 0.5)';
+ctx.rect(0, 0, 100, 50);
+ctx.closePath();
+ctx.rect(10, 10, 80, 30);
+ctx.fill();
+
+_assertPixelApprox(canvas, 50,25, 0,127,0,255, "50,25", "0,127,0,255", 1);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.fill.overlap.png b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.fill.overlap.png
new file mode 100644
index 00000000000..e2a35d48d4c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.fill.overlap.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.fill.winding.add.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.fill.winding.add.html
new file mode 100644
index 00000000000..3eaa0f1bf4d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.fill.winding.add.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.fill.winding.add</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.fill.winding.add</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.fillStyle = '#0f0';
+ctx.moveTo(-10, -10);
+ctx.lineTo(110, -10);
+ctx.lineTo(110, 60);
+ctx.lineTo(-10, 60);
+ctx.lineTo(-10, -10);
+ctx.lineTo(0, 0);
+ctx.lineTo(100, 0);
+ctx.lineTo(100, 50);
+ctx.lineTo(0, 50);
+ctx.fill();
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.fill.winding.subtract.1.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.fill.winding.subtract.1.html
new file mode 100644
index 00000000000..50a2a1dbb76
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.fill.winding.subtract.1.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.fill.winding.subtract.1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.fill.winding.subtract.1</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.fillStyle = '#f00';
+ctx.moveTo(-10, -10);
+ctx.lineTo(110, -10);
+ctx.lineTo(110, 60);
+ctx.lineTo(-10, 60);
+ctx.lineTo(-10, -10);
+ctx.lineTo(0, 0);
+ctx.lineTo(0, 50);
+ctx.lineTo(100, 50);
+ctx.lineTo(100, 0);
+ctx.fill();
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.fill.winding.subtract.2.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.fill.winding.subtract.2.html
new file mode 100644
index 00000000000..b9423507c7b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.fill.winding.subtract.2.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.fill.winding.subtract.2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.fill.winding.subtract.2</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.fillStyle = '#f00';
+ctx.moveTo(-10, -10);
+ctx.lineTo(110, -10);
+ctx.lineTo(110, 60);
+ctx.lineTo(-10, 60);
+ctx.moveTo(0, 0);
+ctx.lineTo(0, 50);
+ctx.lineTo(100, 50);
+ctx.lineTo(100, 0);
+ctx.fill();
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.fill.winding.subtract.3.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.fill.winding.subtract.3.html
new file mode 100644
index 00000000000..131672d1018
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.fill.winding.subtract.3.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.fill.winding.subtract.3</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.fill.winding.subtract.3</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.fillStyle = '#0f0';
+ctx.moveTo(-10, -10);
+ctx.lineTo(110, -10);
+ctx.lineTo(110, 60);
+ctx.lineTo(-10, 60);
+ctx.lineTo(-10, -10);
+ctx.lineTo(-20, -20);
+ctx.lineTo(120, -20);
+ctx.lineTo(120, 70);
+ctx.lineTo(-20, 70);
+ctx.lineTo(-20, -20);
+ctx.lineTo(0, 0);
+ctx.lineTo(0, 50);
+ctx.lineTo(100, 50);
+ctx.lineTo(100, 0);
+ctx.fill();
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.initial.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.initial.html
new file mode 100644
index 00000000000..9dadad80098
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.initial.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.initial</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.initial</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.closePath();
+ctx.fillStyle = '#f00';
+ctx.fill();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.arc.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.arc.html
new file mode 100644
index 00000000000..2d6cfcce5d1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.arc.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.isPointInPath.arc</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.isPointInPath.arc</h1>
+<p class="desc">isPointInPath() works on arcs</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("isPointInPath() works on arcs");
+_addTest(function(canvas, ctx) {
+
+ctx.arc(50, 25, 10, 0, Math.PI, false);
+_assertSame(ctx.isPointInPath(50, 10), false, "ctx.isPointInPath(50, 10)", "false");
+_assertSame(ctx.isPointInPath(50, 20), false, "ctx.isPointInPath(50, 20)", "false");
+_assertSame(ctx.isPointInPath(50, 30), true, "ctx.isPointInPath(50, 30)", "true");
+_assertSame(ctx.isPointInPath(50, 40), false, "ctx.isPointInPath(50, 40)", "false");
+_assertSame(ctx.isPointInPath(30, 20), false, "ctx.isPointInPath(30, 20)", "false");
+_assertSame(ctx.isPointInPath(70, 20), false, "ctx.isPointInPath(70, 20)", "false");
+_assertSame(ctx.isPointInPath(30, 30), false, "ctx.isPointInPath(30, 30)", "false");
+_assertSame(ctx.isPointInPath(70, 30), false, "ctx.isPointInPath(70, 30)", "false");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.basic.1.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.basic.1.html
new file mode 100644
index 00000000000..31818b0ad30
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.basic.1.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.isPointInPath.basic.1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.isPointInPath.basic.1</h1>
+<p class="desc">isPointInPath() detects whether the point is inside the path</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("isPointInPath() detects whether the point is inside the path");
+_addTest(function(canvas, ctx) {
+
+ctx.rect(0, 0, 20, 20);
+_assertSame(ctx.isPointInPath(10, 10), true, "ctx.isPointInPath(10, 10)", "true");
+_assertSame(ctx.isPointInPath(30, 10), false, "ctx.isPointInPath(30, 10)", "false");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.basic.2.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.basic.2.html
new file mode 100644
index 00000000000..138368ec173
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.basic.2.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.isPointInPath.basic.2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.isPointInPath.basic.2</h1>
+<p class="desc">isPointInPath() detects whether the point is inside the path</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("isPointInPath() detects whether the point is inside the path");
+_addTest(function(canvas, ctx) {
+
+ctx.rect(20, 0, 20, 20);
+_assertSame(ctx.isPointInPath(10, 10), false, "ctx.isPointInPath(10, 10)", "false");
+_assertSame(ctx.isPointInPath(30, 10), true, "ctx.isPointInPath(30, 10)", "true");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.bezier.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.bezier.html
new file mode 100644
index 00000000000..aa246f63c7e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.bezier.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.isPointInPath.bezier</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.isPointInPath.bezier</h1>
+<p class="desc">isPointInPath() works on Bezier curves</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("isPointInPath() works on Bezier curves");
+_addTest(function(canvas, ctx) {
+
+ctx.moveTo(25, 25);
+ctx.bezierCurveTo(50, -50, 50, 100, 75, 25);
+_assertSame(ctx.isPointInPath(25, 20), false, "ctx.isPointInPath(25, 20)", "false");
+_assertSame(ctx.isPointInPath(25, 30), false, "ctx.isPointInPath(25, 30)", "false");
+_assertSame(ctx.isPointInPath(30, 20), true, "ctx.isPointInPath(30, 20)", "true");
+_assertSame(ctx.isPointInPath(30, 30), false, "ctx.isPointInPath(30, 30)", "false");
+_assertSame(ctx.isPointInPath(40, 2), false, "ctx.isPointInPath(40, 2)", "false");
+_assertSame(ctx.isPointInPath(40, 20), true, "ctx.isPointInPath(40, 20)", "true");
+_assertSame(ctx.isPointInPath(40, 30), false, "ctx.isPointInPath(40, 30)", "false");
+_assertSame(ctx.isPointInPath(40, 47), false, "ctx.isPointInPath(40, 47)", "false");
+_assertSame(ctx.isPointInPath(45, 20), true, "ctx.isPointInPath(45, 20)", "true");
+_assertSame(ctx.isPointInPath(45, 30), false, "ctx.isPointInPath(45, 30)", "false");
+_assertSame(ctx.isPointInPath(55, 20), false, "ctx.isPointInPath(55, 20)", "false");
+_assertSame(ctx.isPointInPath(55, 30), true, "ctx.isPointInPath(55, 30)", "true");
+_assertSame(ctx.isPointInPath(60, 2), false, "ctx.isPointInPath(60, 2)", "false");
+_assertSame(ctx.isPointInPath(60, 20), false, "ctx.isPointInPath(60, 20)", "false");
+_assertSame(ctx.isPointInPath(60, 30), true, "ctx.isPointInPath(60, 30)", "true");
+_assertSame(ctx.isPointInPath(60, 47), false, "ctx.isPointInPath(60, 47)", "false");
+_assertSame(ctx.isPointInPath(70, 20), false, "ctx.isPointInPath(70, 20)", "false");
+_assertSame(ctx.isPointInPath(70, 30), true, "ctx.isPointInPath(70, 30)", "true");
+_assertSame(ctx.isPointInPath(75, 20), false, "ctx.isPointInPath(75, 20)", "false");
+_assertSame(ctx.isPointInPath(75, 30), false, "ctx.isPointInPath(75, 30)", "false");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.bigarc.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.bigarc.html
new file mode 100644
index 00000000000..1565aeeba59
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.bigarc.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.isPointInPath.bigarc</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.isPointInPath.bigarc</h1>
+<p class="desc">isPointInPath() works on unclosed arcs larger than 2pi</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("isPointInPath() works on unclosed arcs larger than 2pi");
+_addTest(function(canvas, ctx) {
+
+ctx.arc(50, 25, 10, 0, 7, false);
+_assertSame(ctx.isPointInPath(50, 10), false, "ctx.isPointInPath(50, 10)", "false");
+_assertSame(ctx.isPointInPath(50, 20), true, "ctx.isPointInPath(50, 20)", "true");
+_assertSame(ctx.isPointInPath(50, 30), true, "ctx.isPointInPath(50, 30)", "true");
+_assertSame(ctx.isPointInPath(50, 40), false, "ctx.isPointInPath(50, 40)", "false");
+_assertSame(ctx.isPointInPath(30, 20), false, "ctx.isPointInPath(30, 20)", "false");
+_assertSame(ctx.isPointInPath(70, 20), false, "ctx.isPointInPath(70, 20)", "false");
+_assertSame(ctx.isPointInPath(30, 30), false, "ctx.isPointInPath(30, 30)", "false");
+_assertSame(ctx.isPointInPath(70, 30), false, "ctx.isPointInPath(70, 30)", "false");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.edge.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.edge.html
new file mode 100644
index 00000000000..70faf8054c1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.edge.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.isPointInPath.edge</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.isPointInPath.edge</h1>
+<p class="desc">isPointInPath() counts points on the path as being inside</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("isPointInPath() counts points on the path as being inside");
+_addTest(function(canvas, ctx) {
+
+ctx.rect(0, 0, 20, 20);
+_assertSame(ctx.isPointInPath(0, 0), true, "ctx.isPointInPath(0, 0)", "true");
+_assertSame(ctx.isPointInPath(10, 0), true, "ctx.isPointInPath(10, 0)", "true");
+_assertSame(ctx.isPointInPath(20, 0), true, "ctx.isPointInPath(20, 0)", "true");
+_assertSame(ctx.isPointInPath(20, 10), true, "ctx.isPointInPath(20, 10)", "true");
+_assertSame(ctx.isPointInPath(20, 20), true, "ctx.isPointInPath(20, 20)", "true");
+_assertSame(ctx.isPointInPath(10, 20), true, "ctx.isPointInPath(10, 20)", "true");
+_assertSame(ctx.isPointInPath(0, 20), true, "ctx.isPointInPath(0, 20)", "true");
+_assertSame(ctx.isPointInPath(0, 10), true, "ctx.isPointInPath(0, 10)", "true");
+_assertSame(ctx.isPointInPath(10, -0.01), false, "ctx.isPointInPath(10, -0.01)", "false");
+_assertSame(ctx.isPointInPath(10, 20.01), false, "ctx.isPointInPath(10, 20.01)", "false");
+_assertSame(ctx.isPointInPath(-0.01, 10), false, "ctx.isPointInPath(-0.01, 10)", "false");
+_assertSame(ctx.isPointInPath(20.01, 10), false, "ctx.isPointInPath(20.01, 10)", "false");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.empty.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.empty.html
new file mode 100644
index 00000000000..b1e4b2dbdba
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.empty.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.isPointInPath.empty</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.isPointInPath.empty</h1>
+<p class="desc">isPointInPath() works when there is no path</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("isPointInPath() works when there is no path");
+_addTest(function(canvas, ctx) {
+
+_assertSame(ctx.isPointInPath(0, 0), false, "ctx.isPointInPath(0, 0)", "false");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.nonfinite.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.nonfinite.html
new file mode 100644
index 00000000000..f70e6628837
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.nonfinite.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.isPointInPath.nonfinite</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.isPointInPath.nonfinite</h1>
+<p class="desc">isPointInPath() returns false for non-finite arguments</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("isPointInPath() returns false for non-finite arguments");
+_addTest(function(canvas, ctx) {
+
+ctx.rect(-100, -50, 200, 100);
+_assertSame(ctx.isPointInPath(Infinity, 0), false, "ctx.isPointInPath(Infinity, 0)", "false");
+_assertSame(ctx.isPointInPath(-Infinity, 0), false, "ctx.isPointInPath(-Infinity, 0)", "false");
+_assertSame(ctx.isPointInPath(NaN, 0), false, "ctx.isPointInPath(NaN, 0)", "false");
+_assertSame(ctx.isPointInPath(0, Infinity), false, "ctx.isPointInPath(0, Infinity)", "false");
+_assertSame(ctx.isPointInPath(0, -Infinity), false, "ctx.isPointInPath(0, -Infinity)", "false");
+_assertSame(ctx.isPointInPath(0, NaN), false, "ctx.isPointInPath(0, NaN)", "false");
+_assertSame(ctx.isPointInPath(NaN, NaN), false, "ctx.isPointInPath(NaN, NaN)", "false");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.outside.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.outside.html
new file mode 100644
index 00000000000..1abe324838a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.outside.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.isPointInPath.outside</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.isPointInPath.outside</h1>
+<p class="desc">isPointInPath() works on paths outside the canvas</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("isPointInPath() works on paths outside the canvas");
+_addTest(function(canvas, ctx) {
+
+ctx.rect(0, -100, 20, 20);
+ctx.rect(20, -10, 20, 20);
+_assertSame(ctx.isPointInPath(10, -110), false, "ctx.isPointInPath(10, -110)", "false");
+_assertSame(ctx.isPointInPath(10, -90), true, "ctx.isPointInPath(10, -90)", "true");
+_assertSame(ctx.isPointInPath(10, -70), false, "ctx.isPointInPath(10, -70)", "false");
+_assertSame(ctx.isPointInPath(30, -20), false, "ctx.isPointInPath(30, -20)", "false");
+_assertSame(ctx.isPointInPath(30, 0), true, "ctx.isPointInPath(30, 0)", "true");
+_assertSame(ctx.isPointInPath(30, 20), false, "ctx.isPointInPath(30, 20)", "false");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.subpath.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.subpath.html
new file mode 100644
index 00000000000..34bd0c7762e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.subpath.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.isPointInPath.subpath</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.isPointInPath.subpath</h1>
+<p class="desc">isPointInPath() uses the current path, not just the subpath</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("isPointInPath() uses the current path, not just the subpath");
+_addTest(function(canvas, ctx) {
+
+ctx.rect(0, 0, 20, 20);
+ctx.beginPath();
+ctx.rect(20, 0, 20, 20);
+ctx.closePath();
+ctx.rect(40, 0, 20, 20);
+_assertSame(ctx.isPointInPath(10, 10), false, "ctx.isPointInPath(10, 10)", "false");
+_assertSame(ctx.isPointInPath(30, 10), true, "ctx.isPointInPath(30, 10)", "true");
+_assertSame(ctx.isPointInPath(50, 10), true, "ctx.isPointInPath(50, 10)", "true");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.transform.1.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.transform.1.html
new file mode 100644
index 00000000000..20777390cf8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.transform.1.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.isPointInPath.transform.1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.isPointInPath.transform.1</h1>
+<p class="desc">isPointInPath() handles transformations correctly</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("isPointInPath() handles transformations correctly");
+_addTest(function(canvas, ctx) {
+
+ctx.translate(50, 0);
+ctx.rect(0, 0, 20, 20);
+_assertSame(ctx.isPointInPath(-40, 10), false, "ctx.isPointInPath(-40, 10)", "false");
+_assertSame(ctx.isPointInPath(10, 10), false, "ctx.isPointInPath(10, 10)", "false");
+_assertSame(ctx.isPointInPath(49, 10), false, "ctx.isPointInPath(49, 10)", "false");
+_assertSame(ctx.isPointInPath(51, 10), true, "ctx.isPointInPath(51, 10)", "true");
+_assertSame(ctx.isPointInPath(69, 10), true, "ctx.isPointInPath(69, 10)", "true");
+_assertSame(ctx.isPointInPath(71, 10), false, "ctx.isPointInPath(71, 10)", "false");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.transform.2.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.transform.2.html
new file mode 100644
index 00000000000..bde026e4fcf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.transform.2.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.isPointInPath.transform.2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.isPointInPath.transform.2</h1>
+<p class="desc">isPointInPath() handles transformations correctly</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("isPointInPath() handles transformations correctly");
+_addTest(function(canvas, ctx) {
+
+ctx.rect(50, 0, 20, 20);
+ctx.translate(50, 0);
+_assertSame(ctx.isPointInPath(-40, 10), false, "ctx.isPointInPath(-40, 10)", "false");
+_assertSame(ctx.isPointInPath(10, 10), false, "ctx.isPointInPath(10, 10)", "false");
+_assertSame(ctx.isPointInPath(49, 10), false, "ctx.isPointInPath(49, 10)", "false");
+_assertSame(ctx.isPointInPath(51, 10), true, "ctx.isPointInPath(51, 10)", "true");
+_assertSame(ctx.isPointInPath(69, 10), true, "ctx.isPointInPath(69, 10)", "true");
+_assertSame(ctx.isPointInPath(71, 10), false, "ctx.isPointInPath(71, 10)", "false");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.transform.3.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.transform.3.html
new file mode 100644
index 00000000000..c612aae6090
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.transform.3.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.isPointInPath.transform.3</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.isPointInPath.transform.3</h1>
+<p class="desc">isPointInPath() handles transformations correctly</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("isPointInPath() handles transformations correctly");
+_addTest(function(canvas, ctx) {
+
+ctx.scale(-1, 1);
+ctx.rect(-70, 0, 20, 20);
+_assertSame(ctx.isPointInPath(-40, 10), false, "ctx.isPointInPath(-40, 10)", "false");
+_assertSame(ctx.isPointInPath(10, 10), false, "ctx.isPointInPath(10, 10)", "false");
+_assertSame(ctx.isPointInPath(49, 10), false, "ctx.isPointInPath(49, 10)", "false");
+_assertSame(ctx.isPointInPath(51, 10), true, "ctx.isPointInPath(51, 10)", "true");
+_assertSame(ctx.isPointInPath(69, 10), true, "ctx.isPointInPath(69, 10)", "true");
+_assertSame(ctx.isPointInPath(71, 10), false, "ctx.isPointInPath(71, 10)", "false");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.transform.4.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.transform.4.html
new file mode 100644
index 00000000000..50fc45d2f47
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.transform.4.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.isPointInPath.transform.4</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.isPointInPath.transform.4</h1>
+<p class="desc">isPointInPath() handles transformations correctly</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("isPointInPath() handles transformations correctly");
+_addTest(function(canvas, ctx) {
+
+ctx.translate(50, 0);
+ctx.rect(50, 0, 20, 20);
+ctx.translate(0, 50);
+_assertSame(ctx.isPointInPath(60, 10), false, "ctx.isPointInPath(60, 10)", "false");
+_assertSame(ctx.isPointInPath(110, 10), true, "ctx.isPointInPath(110, 10)", "true");
+_assertSame(ctx.isPointInPath(110, 60), false, "ctx.isPointInPath(110, 60)", "false");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.unclosed.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.unclosed.html
new file mode 100644
index 00000000000..a137592532b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.unclosed.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.isPointInPath.unclosed</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.isPointInPath.unclosed</h1>
+<p class="desc">isPointInPath() works on unclosed subpaths</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("isPointInPath() works on unclosed subpaths");
+_addTest(function(canvas, ctx) {
+
+ctx.moveTo(0, 0);
+ctx.lineTo(20, 0);
+ctx.lineTo(20, 20);
+ctx.lineTo(0, 20);
+_assertSame(ctx.isPointInPath(10, 10), true, "ctx.isPointInPath(10, 10)", "true");
+_assertSame(ctx.isPointInPath(30, 10), false, "ctx.isPointInPath(30, 10)", "false");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.winding.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.winding.html
new file mode 100644
index 00000000000..afa83810bfb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.isPointInPath.winding.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.isPointInPath.winding</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.isPointInPath.winding</h1>
+<p class="desc">isPointInPath() uses the non-zero winding number rule</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("isPointInPath() uses the non-zero winding number rule");
+_addTest(function(canvas, ctx) {
+
+// Create a square ring, using opposite windings to make a hole in the centre
+ctx.moveTo(0, 0);
+ctx.lineTo(50, 0);
+ctx.lineTo(50, 50);
+ctx.lineTo(0, 50);
+ctx.lineTo(0, 0);
+ctx.lineTo(10, 10);
+ctx.lineTo(10, 40);
+ctx.lineTo(40, 40);
+ctx.lineTo(40, 10);
+ctx.lineTo(10, 10);
+
+_assertSame(ctx.isPointInPath(5, 5), true, "ctx.isPointInPath(5, 5)", "true");
+_assertSame(ctx.isPointInPath(25, 5), true, "ctx.isPointInPath(25, 5)", "true");
+_assertSame(ctx.isPointInPath(45, 5), true, "ctx.isPointInPath(45, 5)", "true");
+_assertSame(ctx.isPointInPath(5, 25), true, "ctx.isPointInPath(5, 25)", "true");
+_assertSame(ctx.isPointInPath(25, 25), false, "ctx.isPointInPath(25, 25)", "false");
+_assertSame(ctx.isPointInPath(45, 25), true, "ctx.isPointInPath(45, 25)", "true");
+_assertSame(ctx.isPointInPath(5, 45), true, "ctx.isPointInPath(5, 45)", "true");
+_assertSame(ctx.isPointInPath(25, 45), true, "ctx.isPointInPath(25, 45)", "true");
+_assertSame(ctx.isPointInPath(45, 45), true, "ctx.isPointInPath(45, 45)", "true");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.lineTo.basic.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.lineTo.basic.html
new file mode 100644
index 00000000000..8606f890067
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.lineTo.basic.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.lineTo.basic</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.lineTo.basic</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.strokeStyle = '#0f0';
+ctx.lineWidth = 50;
+ctx.beginPath();
+ctx.moveTo(0, 25);
+ctx.lineTo(100, 25);
+ctx.stroke();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.lineTo.ensuresubpath.1.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.lineTo.ensuresubpath.1.html
new file mode 100644
index 00000000000..a4c0efb7e3f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.lineTo.ensuresubpath.1.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.lineTo.ensuresubpath.1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.lineTo.ensuresubpath.1</h1>
+<p class="desc">If there is no subpath, the point is added and nothing is drawn</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("If there is no subpath, the point is added and nothing is drawn");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.strokeStyle = '#f00';
+ctx.lineWidth = 50;
+ctx.beginPath();
+ctx.lineTo(100, 50);
+ctx.stroke();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.lineTo.ensuresubpath.2.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.lineTo.ensuresubpath.2.html
new file mode 100644
index 00000000000..94e6edddabf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.lineTo.ensuresubpath.2.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.lineTo.ensuresubpath.2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.lineTo.ensuresubpath.2</h1>
+<p class="desc">If there is no subpath, the point is added and used for subsequent drawing</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("If there is no subpath, the point is added and used for subsequent drawing");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.strokeStyle = '#0f0';
+ctx.lineWidth = 50;
+ctx.beginPath();
+ctx.lineTo(0, 25);
+ctx.lineTo(100, 25);
+ctx.stroke();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.lineTo.nextpoint.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.lineTo.nextpoint.html
new file mode 100644
index 00000000000..c2032f7c5a5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.lineTo.nextpoint.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.lineTo.nextpoint</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.lineTo.nextpoint</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.strokeStyle = '#0f0';
+ctx.lineWidth = 50;
+ctx.beginPath();
+ctx.moveTo(-100, -100);
+ctx.lineTo(0, 25);
+ctx.lineTo(100, 25);
+ctx.stroke();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.lineTo.nonfinite.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.lineTo.nonfinite.html
new file mode 100644
index 00000000000..52982d2f68d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.lineTo.nonfinite.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.lineTo.nonfinite</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.lineTo.nonfinite</h1>
+<p class="desc">lineTo() with Infinity/NaN is ignored</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("lineTo() with Infinity/NaN is ignored");
+_addTest(function(canvas, ctx) {
+
+ctx.moveTo(0, 0);
+ctx.lineTo(100, 0);
+ctx.lineTo(Infinity, 50);
+ctx.lineTo(-Infinity, 50);
+ctx.lineTo(NaN, 50);
+ctx.lineTo(0, Infinity);
+ctx.lineTo(0, -Infinity);
+ctx.lineTo(0, NaN);
+ctx.lineTo(Infinity, Infinity);
+ctx.lineTo(100, 50);
+ctx.lineTo(0, 50);
+ctx.fillStyle = '#0f0';
+ctx.fill();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 90,45, 0,255,0,255, "90,45", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.moveTo.basic.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.moveTo.basic.html
new file mode 100644
index 00000000000..999518fcedd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.moveTo.basic.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.moveTo.basic</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.moveTo.basic</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.rect(0, 0, 10, 50);
+ctx.moveTo(100, 0);
+ctx.lineTo(10, 0);
+ctx.lineTo(10, 50);
+ctx.lineTo(100, 50);
+ctx.fillStyle = '#0f0';
+ctx.fill();
+_assertPixel(canvas, 90,25, 0,255,0,255, "90,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.moveTo.multiple.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.moveTo.multiple.html
new file mode 100644
index 00000000000..123d39314f3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.moveTo.multiple.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.moveTo.multiple</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.moveTo.multiple</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.moveTo(0, 25);
+ctx.moveTo(100, 25);
+ctx.moveTo(0, 25);
+ctx.lineTo(100, 25);
+ctx.strokeStyle = '#0f0';
+ctx.lineWidth = 50;
+ctx.stroke();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.moveTo.newsubpath.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.moveTo.newsubpath.html
new file mode 100644
index 00000000000..caff9f81d45
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.moveTo.newsubpath.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.moveTo.newsubpath</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.moveTo.newsubpath</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.beginPath();
+ctx.moveTo(0, 0);
+ctx.moveTo(100, 0);
+ctx.moveTo(100, 50);
+ctx.moveTo(0, 50);
+ctx.fillStyle = '#f00';
+ctx.fill();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.moveTo.nonfinite.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.moveTo.nonfinite.html
new file mode 100644
index 00000000000..c531f4d05c9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.moveTo.nonfinite.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.moveTo.nonfinite</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.moveTo.nonfinite</h1>
+<p class="desc">moveTo() with Infinity/NaN is ignored</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("moveTo() with Infinity/NaN is ignored");
+_addTest(function(canvas, ctx) {
+
+ctx.moveTo(0, 0);
+ctx.lineTo(100, 0);
+ctx.moveTo(Infinity, 50);
+ctx.moveTo(-Infinity, 50);
+ctx.moveTo(NaN, 50);
+ctx.moveTo(0, Infinity);
+ctx.moveTo(0, -Infinity);
+ctx.moveTo(0, NaN);
+ctx.moveTo(Infinity, Infinity);
+ctx.lineTo(100, 50);
+ctx.lineTo(0, 50);
+ctx.fillStyle = '#0f0';
+ctx.fill();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.quadraticCurveTo.basic.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.quadraticCurveTo.basic.html
new file mode 100644
index 00000000000..247b6800590
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.quadraticCurveTo.basic.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.quadraticCurveTo.basic</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.quadraticCurveTo.basic</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.strokeStyle = '#0f0';
+ctx.lineWidth = 50;
+ctx.beginPath();
+ctx.moveTo(0, 25);
+ctx.quadraticCurveTo(100, 25, 100, 25);
+ctx.stroke();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.quadraticCurveTo.ensuresubpath.1.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.quadraticCurveTo.ensuresubpath.1.html
new file mode 100644
index 00000000000..ac7bab21220
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.quadraticCurveTo.ensuresubpath.1.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.quadraticCurveTo.ensuresubpath.1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.quadraticCurveTo.ensuresubpath.1</h1>
+<p class="desc">If there is no subpath, the first control point is added (and nothing is drawn up to it)</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("If there is no subpath, the first control point is added (and nothing is drawn up to it)");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.strokeStyle = '#f00';
+ctx.lineWidth = 50;
+ctx.beginPath();
+ctx.quadraticCurveTo(100, 50, 200, 50);
+ctx.stroke();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 95,45, 0,255,0,255, "95,45", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.quadraticCurveTo.ensuresubpath.2.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.quadraticCurveTo.ensuresubpath.2.html
new file mode 100644
index 00000000000..95951a2ad13
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.quadraticCurveTo.ensuresubpath.2.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.quadraticCurveTo.ensuresubpath.2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.quadraticCurveTo.ensuresubpath.2</h1>
+<p class="desc">If there is no subpath, the first control point is added</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("If there is no subpath, the first control point is added");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.strokeStyle = '#0f0';
+ctx.lineWidth = 50;
+ctx.beginPath();
+ctx.quadraticCurveTo(0, 25, 100, 25);
+ctx.stroke();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 5,45, 0,255,0,255, "5,45", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.quadraticCurveTo.nonfinite.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.quadraticCurveTo.nonfinite.html
new file mode 100644
index 00000000000..637d10954fd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.quadraticCurveTo.nonfinite.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.quadraticCurveTo.nonfinite</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.quadraticCurveTo.nonfinite</h1>
+<p class="desc">quadraticCurveTo() with Infinity/NaN is ignored</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("quadraticCurveTo() with Infinity/NaN is ignored");
+_addTest(function(canvas, ctx) {
+
+ctx.moveTo(0, 0);
+ctx.lineTo(100, 0);
+ctx.quadraticCurveTo(Infinity, 50, 0, 50);
+ctx.quadraticCurveTo(-Infinity, 50, 0, 50);
+ctx.quadraticCurveTo(NaN, 50, 0, 50);
+ctx.quadraticCurveTo(0, Infinity, 0, 50);
+ctx.quadraticCurveTo(0, -Infinity, 0, 50);
+ctx.quadraticCurveTo(0, NaN, 0, 50);
+ctx.quadraticCurveTo(0, 50, Infinity, 50);
+ctx.quadraticCurveTo(0, 50, -Infinity, 50);
+ctx.quadraticCurveTo(0, 50, NaN, 50);
+ctx.quadraticCurveTo(0, 50, 0, Infinity);
+ctx.quadraticCurveTo(0, 50, 0, -Infinity);
+ctx.quadraticCurveTo(0, 50, 0, NaN);
+ctx.quadraticCurveTo(Infinity, Infinity, 0, 50);
+ctx.quadraticCurveTo(Infinity, Infinity, Infinity, 50);
+ctx.quadraticCurveTo(Infinity, Infinity, Infinity, Infinity);
+ctx.quadraticCurveTo(Infinity, Infinity, 0, Infinity);
+ctx.quadraticCurveTo(Infinity, 50, Infinity, 50);
+ctx.quadraticCurveTo(Infinity, 50, Infinity, Infinity);
+ctx.quadraticCurveTo(Infinity, 50, 0, Infinity);
+ctx.quadraticCurveTo(0, Infinity, Infinity, 50);
+ctx.quadraticCurveTo(0, Infinity, Infinity, Infinity);
+ctx.quadraticCurveTo(0, Infinity, 0, Infinity);
+ctx.quadraticCurveTo(0, 50, Infinity, Infinity);
+ctx.lineTo(100, 50);
+ctx.lineTo(0, 50);
+ctx.fillStyle = '#0f0';
+ctx.fill();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 90,45, 0,255,0,255, "90,45", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.quadraticCurveTo.scaled.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.quadraticCurveTo.scaled.html
new file mode 100644
index 00000000000..36801da9408
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.quadraticCurveTo.scaled.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.quadraticCurveTo.scaled</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.quadraticCurveTo.scaled</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.scale(1000, 1000);
+ctx.strokeStyle = '#0f0';
+ctx.lineWidth = 0.055;
+ctx.beginPath();
+ctx.moveTo(-1, 1.05);
+ctx.quadraticCurveTo(0, -1, 1.2, 1.05);
+ctx.stroke();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.quadraticCurveTo.shape.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.quadraticCurveTo.shape.html
new file mode 100644
index 00000000000..9311fc2a3b0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.quadraticCurveTo.shape.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.quadraticCurveTo.shape</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.quadraticCurveTo.shape</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.strokeStyle = '#0f0';
+ctx.lineWidth = 55;
+ctx.beginPath();
+ctx.moveTo(-1000, 1050);
+ctx.quadraticCurveTo(0, -1000, 1200, 1050);
+ctx.stroke();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.basic.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.basic.html
new file mode 100644
index 00000000000..a5a6a733ea3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.basic.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.rect.basic</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.rect.basic</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.fillStyle = '#0f0';
+ctx.rect(0, 0, 100, 50);
+ctx.fill();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.closed.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.closed.html
new file mode 100644
index 00000000000..98f06480df0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.closed.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.rect.closed</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.rect.closed</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.strokeStyle = '#0f0';
+ctx.lineWidth = 200;
+ctx.lineJoin = 'miter';
+ctx.rect(100, 50, 100, 100);
+ctx.stroke();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.end.1.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.end.1.html
new file mode 100644
index 00000000000..4cfe05817b0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.end.1.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.rect.end.1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.rect.end.1</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.strokeStyle = '#0f0';
+ctx.lineWidth = 100;
+ctx.rect(200, 100, 400, 1000);
+ctx.lineTo(-2000, -1000);
+ctx.stroke();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.end.2.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.end.2.html
new file mode 100644
index 00000000000..f961b9c5215
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.end.2.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.rect.end.2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.rect.end.2</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.strokeStyle = '#0f0';
+ctx.lineWidth = 450;
+ctx.lineCap = 'round';
+ctx.lineJoin = 'bevel';
+ctx.rect(150, 150, 2000, 2000);
+ctx.lineTo(160, 160);
+ctx.stroke();
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 98,1, 0,255,0,255, "98,1", "0,255,0,255");
+_assertPixel(canvas, 1,48, 0,255,0,255, "1,48", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.negative.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.negative.html
new file mode 100644
index 00000000000..382623a5e26
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.negative.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.rect.negative</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.rect.negative</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.beginPath();
+ctx.fillStyle = '#0f0';
+ctx.rect(0, 0, 50, 25);
+ctx.rect(100, 0, -50, 25);
+ctx.rect(0, 50, 50, -25);
+ctx.rect(100, 50, -50, -25);
+ctx.fill();
+_assertPixel(canvas, 25,12, 0,255,0,255, "25,12", "0,255,0,255");
+_assertPixel(canvas, 75,12, 0,255,0,255, "75,12", "0,255,0,255");
+_assertPixel(canvas, 25,37, 0,255,0,255, "25,37", "0,255,0,255");
+_assertPixel(canvas, 75,37, 0,255,0,255, "75,37", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.newsubpath.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.newsubpath.html
new file mode 100644
index 00000000000..e0e841b8c3d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.newsubpath.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.rect.newsubpath</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.rect.newsubpath</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.beginPath();
+ctx.strokeStyle = '#f00';
+ctx.lineWidth = 50;
+ctx.moveTo(-100, 25);
+ctx.lineTo(-50, 25);
+ctx.rect(200, 25, 1, 1);
+ctx.stroke();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.nonfinite.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.nonfinite.html
new file mode 100644
index 00000000000..173fd383f56
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.nonfinite.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.rect.nonfinite</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.rect.nonfinite</h1>
+<p class="desc">rect() with Infinity/NaN is ignored</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("rect() with Infinity/NaN is ignored");
+_addTest(function(canvas, ctx) {
+
+ctx.moveTo(0, 0);
+ctx.lineTo(100, 0);
+ctx.rect(Infinity, 50, 1, 1);
+ctx.rect(-Infinity, 50, 1, 1);
+ctx.rect(NaN, 50, 1, 1);
+ctx.rect(0, Infinity, 1, 1);
+ctx.rect(0, -Infinity, 1, 1);
+ctx.rect(0, NaN, 1, 1);
+ctx.rect(0, 50, Infinity, 1);
+ctx.rect(0, 50, -Infinity, 1);
+ctx.rect(0, 50, NaN, 1);
+ctx.rect(0, 50, 1, Infinity);
+ctx.rect(0, 50, 1, -Infinity);
+ctx.rect(0, 50, 1, NaN);
+ctx.rect(Infinity, Infinity, 1, 1);
+ctx.rect(Infinity, Infinity, Infinity, 1);
+ctx.rect(Infinity, Infinity, Infinity, Infinity);
+ctx.rect(Infinity, Infinity, 1, Infinity);
+ctx.rect(Infinity, 50, Infinity, 1);
+ctx.rect(Infinity, 50, Infinity, Infinity);
+ctx.rect(Infinity, 50, 1, Infinity);
+ctx.rect(0, Infinity, Infinity, 1);
+ctx.rect(0, Infinity, Infinity, Infinity);
+ctx.rect(0, Infinity, 1, Infinity);
+ctx.rect(0, 50, Infinity, Infinity);
+ctx.lineTo(100, 50);
+ctx.lineTo(0, 50);
+ctx.fillStyle = '#0f0';
+ctx.fill();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 90,45, 0,255,0,255, "90,45", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.selfintersect.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.selfintersect.html
new file mode 100644
index 00000000000..16be6232b26
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.selfintersect.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.rect.selfintersect</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.rect.selfintersect</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.strokeStyle = '#0f0';
+ctx.lineWidth = 90;
+ctx.beginPath();
+ctx.rect(45, 20, 10, 10);
+ctx.stroke();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.winding.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.winding.html
new file mode 100644
index 00000000000..194e5733b51
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.winding.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.rect.winding</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.rect.winding</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.beginPath();
+ctx.fillStyle = '#f00';
+ctx.rect(0, 0, 50, 50);
+ctx.rect(100, 50, -50, -50);
+ctx.rect(0, 25, 100, -25);
+ctx.rect(100, 25, -100, 25);
+ctx.fill();
+_assertPixel(canvas, 25,12, 0,255,0,255, "25,12", "0,255,0,255");
+_assertPixel(canvas, 75,12, 0,255,0,255, "75,12", "0,255,0,255");
+_assertPixel(canvas, 25,37, 0,255,0,255, "25,37", "0,255,0,255");
+_assertPixel(canvas, 75,37, 0,255,0,255, "75,37", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.zero.1.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.zero.1.html
new file mode 100644
index 00000000000..dd4b1a45628
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.zero.1.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.rect.zero.1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.rect.zero.1</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.strokeStyle = '#0f0';
+ctx.lineWidth = 100;
+ctx.beginPath();
+ctx.rect(0, 50, 100, 0);
+ctx.stroke();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.zero.2.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.zero.2.html
new file mode 100644
index 00000000000..0bdfe380e4a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.zero.2.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.rect.zero.2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.rect.zero.2</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.strokeStyle = '#0f0';
+ctx.lineWidth = 100;
+ctx.beginPath();
+ctx.rect(50, -100, 0, 250);
+ctx.stroke();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.zero.3.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.zero.3.html
new file mode 100644
index 00000000000..67dd2410ba6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.zero.3.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.rect.zero.3</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.rect.zero.3</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.strokeStyle = '#f00';
+ctx.lineWidth = 100;
+ctx.beginPath();
+ctx.rect(50, 25, 0, 0);
+ctx.stroke();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.zero.4.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.zero.4.html
new file mode 100644
index 00000000000..a74399567fa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.zero.4.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.rect.zero.4</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.rect.zero.4</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.strokeStyle = '#0f0';
+ctx.lineWidth = 50;
+ctx.rect(100, 25, 0, 0);
+ctx.lineTo(0, 25);
+ctx.stroke();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.zero.5.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.zero.5.html
new file mode 100644
index 00000000000..81566fb7f23
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.zero.5.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.rect.zero.5</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.rect.zero.5</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.strokeStyle = '#f00';
+ctx.lineWidth = 50;
+ctx.moveTo(0, 0);
+ctx.rect(100, 25, 0, 0);
+ctx.stroke();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.zero.6.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.zero.6.html
new file mode 100644
index 00000000000..37b1c524c52
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.rect.zero.6.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.rect.zero.6</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.rect.zero.6</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.strokeStyle = '#f00';
+ctx.lineJoin = 'miter';
+ctx.miterLimit = 1.5;
+ctx.lineWidth = 200;
+ctx.beginPath();
+ctx.rect(100, 25, 1000, 0);
+ctx.stroke();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.stroke.empty.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.stroke.empty.html
new file mode 100644
index 00000000000..671c4552b09
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.stroke.empty.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.stroke.empty</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.stroke.empty</h1>
+<p class="desc">Empty subpaths are not stroked</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Empty subpaths are not stroked");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.strokeStyle = '#f00';
+ctx.lineWidth = 100;
+ctx.lineCap = 'round';
+ctx.lineJoin = 'round';
+
+ctx.beginPath();
+ctx.moveTo(40, 25);
+ctx.moveTo(60, 25);
+ctx.stroke();
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.stroke.overlap.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.stroke.overlap.html
new file mode 100644
index 00000000000..8a4d6989e2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.stroke.overlap.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.stroke.overlap</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.stroke.overlap</h1>
+<p class="desc">Stroked subpaths are combined before being drawn</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.path.stroke.overlap.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Stroked subpaths are combined before being drawn");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#000';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.strokeStyle = 'rgba(0, 255, 0, 0.5)';
+ctx.lineWidth = 50;
+ctx.moveTo(0, 20);
+ctx.lineTo(100, 20);
+ctx.moveTo(0, 30);
+ctx.lineTo(100, 30);
+ctx.stroke();
+
+_assertPixelApprox(canvas, 50,25, 0,127,0,255, "50,25", "0,127,0,255", 1);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.stroke.overlap.png b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.stroke.overlap.png
new file mode 100644
index 00000000000..e2a35d48d4c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.stroke.overlap.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.stroke.prune.arc.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.stroke.prune.arc.html
new file mode 100644
index 00000000000..fc4c23ffc31
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.stroke.prune.arc.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.stroke.prune.arc</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.stroke.prune.arc</h1>
+<p class="desc">Zero-length line segments from arcTo and arc are removed before stroking</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Zero-length line segments from arcTo and arc are removed before stroking");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.strokeStyle = '#f00';
+ctx.lineWidth = 100;
+ctx.lineCap = 'round';
+ctx.lineJoin = 'round';
+
+ctx.beginPath();
+ctx.moveTo(50, 25);
+ctx.arcTo(50, 25, 150, 25, 10);
+ctx.stroke();
+
+ctx.beginPath();
+ctx.moveTo(60, 25);
+ctx.arc(50, 25, 10, 0, 0, false);
+ctx.stroke();
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.stroke.prune.closed.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.stroke.prune.closed.html
new file mode 100644
index 00000000000..d356c91fa41
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.stroke.prune.closed.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.stroke.prune.closed</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.stroke.prune.closed</h1>
+<p class="desc">Zero-length line segments from closed paths are removed before stroking</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Zero-length line segments from closed paths are removed before stroking");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.strokeStyle = '#f00';
+ctx.lineWidth = 100;
+ctx.lineCap = 'round';
+ctx.lineJoin = 'round';
+
+ctx.beginPath();
+ctx.moveTo(50, 25);
+ctx.lineTo(50, 25);
+ctx.closePath();
+ctx.stroke();
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.stroke.prune.corner.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.stroke.prune.corner.html
new file mode 100644
index 00000000000..687777426de
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.stroke.prune.corner.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.stroke.prune.corner</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.stroke.prune.corner</h1>
+<p class="desc">Zero-length line segments are removed before stroking with miters</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Zero-length line segments are removed before stroking with miters");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.strokeStyle = '#f00';
+ctx.lineWidth = 400;
+ctx.lineJoin = 'miter';
+ctx.miterLimit = 1.4;
+
+ctx.beginPath();
+ctx.moveTo(-1000, 200);
+ctx.lineTo(-100, 200);
+ctx.lineTo(-100, 200);
+ctx.lineTo(-100, 200);
+ctx.lineTo(-100, 1000);
+ctx.stroke();
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.stroke.prune.curve.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.stroke.prune.curve.html
new file mode 100644
index 00000000000..721cb6eb081
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.stroke.prune.curve.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.stroke.prune.curve</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.stroke.prune.curve</h1>
+<p class="desc">Zero-length line segments from quadraticCurveTo and bezierCurveTo are removed before stroking</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Zero-length line segments from quadraticCurveTo and bezierCurveTo are removed before stroking");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.strokeStyle = '#f00';
+ctx.lineWidth = 100;
+ctx.lineCap = 'round';
+ctx.lineJoin = 'round';
+
+ctx.beginPath();
+ctx.moveTo(50, 25);
+ctx.quadraticCurveTo(50, 25, 50, 25);
+ctx.stroke();
+
+ctx.beginPath();
+ctx.moveTo(50, 25);
+ctx.bezierCurveTo(50, 25, 50, 25, 50, 25);
+ctx.stroke();
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.stroke.prune.line.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.stroke.prune.line.html
new file mode 100644
index 00000000000..aa04d457ec9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.stroke.prune.line.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.stroke.prune.line</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.stroke.prune.line</h1>
+<p class="desc">Zero-length line segments from lineTo are removed before stroking</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Zero-length line segments from lineTo are removed before stroking");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.strokeStyle = '#f00';
+ctx.lineWidth = 100;
+ctx.lineCap = 'round';
+ctx.lineJoin = 'round';
+
+ctx.beginPath();
+ctx.moveTo(50, 25);
+ctx.lineTo(50, 25);
+ctx.stroke();
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.stroke.prune.rect.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.stroke.prune.rect.html
new file mode 100644
index 00000000000..45ead6db43c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.stroke.prune.rect.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.stroke.prune.rect</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.stroke.prune.rect</h1>
+<p class="desc">Zero-length line segments from rect and strokeRect are removed before stroking</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Zero-length line segments from rect and strokeRect are removed before stroking");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.strokeStyle = '#f00';
+ctx.lineWidth = 100;
+ctx.lineCap = 'round';
+ctx.lineJoin = 'round';
+
+ctx.beginPath();
+ctx.rect(50, 25, 0, 0);
+ctx.stroke();
+
+ctx.strokeRect(50, 25, 0, 0);
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.stroke.scale1.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.stroke.scale1.html
new file mode 100644
index 00000000000..ae63be20738
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.stroke.scale1.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.stroke.scale1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.stroke.scale1</h1>
+<p class="desc">Stroke line widths are scaled by the current transformation matrix</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Stroke line widths are scaled by the current transformation matrix");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.beginPath();
+ctx.rect(25, 12.5, 50, 25);
+ctx.save();
+ctx.scale(50, 25);
+ctx.strokeStyle = '#0f0';
+ctx.stroke();
+ctx.restore();
+
+ctx.beginPath();
+ctx.rect(-25, -12.5, 150, 75);
+ctx.save();
+ctx.scale(50, 25);
+ctx.strokeStyle = '#f00';
+ctx.stroke();
+ctx.restore();
+
+_assertPixel(canvas, 0,0, 0,255,0,255, "0,0", "0,255,0,255");
+_assertPixel(canvas, 50,0, 0,255,0,255, "50,0", "0,255,0,255");
+_assertPixel(canvas, 99,0, 0,255,0,255, "99,0", "0,255,0,255");
+_assertPixel(canvas, 0,25, 0,255,0,255, "0,25", "0,255,0,255");
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 99,25, 0,255,0,255, "99,25", "0,255,0,255");
+_assertPixel(canvas, 0,49, 0,255,0,255, "0,49", "0,255,0,255");
+_assertPixel(canvas, 50,49, 0,255,0,255, "50,49", "0,255,0,255");
+_assertPixel(canvas, 99,49, 0,255,0,255, "99,49", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.stroke.scale2.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.stroke.scale2.html
new file mode 100644
index 00000000000..de8dd5e340c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.stroke.scale2.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.stroke.scale2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.stroke.scale2</h1>
+<p class="desc">Stroke line widths are scaled by the current transformation matrix</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Stroke line widths are scaled by the current transformation matrix");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.beginPath();
+ctx.rect(25, 12.5, 50, 25);
+ctx.save();
+ctx.rotate(Math.PI/2);
+ctx.scale(25, 50);
+ctx.strokeStyle = '#0f0';
+ctx.stroke();
+ctx.restore();
+
+ctx.beginPath();
+ctx.rect(-25, -12.5, 150, 75);
+ctx.save();
+ctx.rotate(Math.PI/2);
+ctx.scale(25, 50);
+ctx.strokeStyle = '#f00';
+ctx.stroke();
+ctx.restore();
+
+_assertPixel(canvas, 0,0, 0,255,0,255, "0,0", "0,255,0,255");
+_assertPixel(canvas, 50,0, 0,255,0,255, "50,0", "0,255,0,255");
+_assertPixel(canvas, 99,0, 0,255,0,255, "99,0", "0,255,0,255");
+_assertPixel(canvas, 0,25, 0,255,0,255, "0,25", "0,255,0,255");
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 99,25, 0,255,0,255, "99,25", "0,255,0,255");
+_assertPixel(canvas, 0,49, 0,255,0,255, "0,49", "0,255,0,255");
+_assertPixel(canvas, 50,49, 0,255,0,255, "50,49", "0,255,0,255");
+_assertPixel(canvas, 99,49, 0,255,0,255, "99,49", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.stroke.skew.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.stroke.skew.html
new file mode 100644
index 00000000000..6c6e0a4d7ed
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.stroke.skew.html
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.stroke.skew</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.stroke.skew</h1>
+<p class="desc">Strokes lines are skewed by the current transformation matrix</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Strokes lines are skewed by the current transformation matrix");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.save();
+ctx.beginPath();
+ctx.moveTo(49, -50);
+ctx.lineTo(201, -50);
+ctx.rotate(Math.PI/4);
+ctx.scale(1, 283);
+ctx.strokeStyle = '#0f0';
+ctx.stroke();
+ctx.restore();
+
+ctx.save();
+ctx.beginPath();
+ctx.translate(-150, 0);
+ctx.moveTo(49, -50);
+ctx.lineTo(199, -50);
+ctx.rotate(Math.PI/4);
+ctx.scale(1, 142);
+ctx.strokeStyle = '#f00';
+ctx.stroke();
+ctx.restore();
+
+ctx.save();
+ctx.beginPath();
+ctx.translate(-150, 0);
+ctx.moveTo(49, -50);
+ctx.lineTo(199, -50);
+ctx.rotate(Math.PI/4);
+ctx.scale(1, 142);
+ctx.strokeStyle = '#f00';
+ctx.stroke();
+ctx.restore();
+
+_assertPixel(canvas, 0,0, 0,255,0,255, "0,0", "0,255,0,255");
+_assertPixel(canvas, 50,0, 0,255,0,255, "50,0", "0,255,0,255");
+_assertPixel(canvas, 99,0, 0,255,0,255, "99,0", "0,255,0,255");
+_assertPixel(canvas, 0,25, 0,255,0,255, "0,25", "0,255,0,255");
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 99,25, 0,255,0,255, "99,25", "0,255,0,255");
+_assertPixel(canvas, 0,49, 0,255,0,255, "0,49", "0,255,0,255");
+_assertPixel(canvas, 50,49, 0,255,0,255, "50,49", "0,255,0,255");
+_assertPixel(canvas, 99,49, 0,255,0,255, "99,49", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.stroke.unaffected.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.stroke.unaffected.html
new file mode 100644
index 00000000000..6980a0cfd80
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.stroke.unaffected.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.stroke.unaffected</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.stroke.unaffected</h1>
+<p class="desc">Stroking does not start a new path or subpath</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Stroking does not start a new path or subpath");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.lineWidth = 50;
+ctx.moveTo(-100, 25);
+ctx.lineTo(-100, -100);
+ctx.lineTo(200, -100);
+ctx.lineTo(200, 25);
+ctx.strokeStyle = '#f00';
+ctx.stroke();
+
+ctx.closePath();
+ctx.strokeStyle = '#0f0';
+ctx.stroke();
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.stroke.union.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.stroke.union.html
new file mode 100644
index 00000000000..bf1f28a5b09
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.stroke.union.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.stroke.union</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.stroke.union</h1>
+<p class="desc">Strokes in opposite directions are unioned, not subtracted</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Strokes in opposite directions are unioned, not subtracted");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.strokeStyle = '#0f0';
+ctx.lineWidth = 40;
+ctx.moveTo(0, 10);
+ctx.lineTo(100, 10);
+ctx.moveTo(100, 40);
+ctx.lineTo(0, 40);
+ctx.stroke();
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.transformation.basic.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.transformation.basic.html
new file mode 100644
index 00000000000..52803215320
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.transformation.basic.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.transformation.basic</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.transformation.basic</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.translate(-100, 0);
+ctx.rect(100, 0, 100, 50);
+ctx.translate(0, -100);
+ctx.fillStyle = '#0f0';
+ctx.fill();
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.transformation.changing.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.transformation.changing.html
new file mode 100644
index 00000000000..24c32062d37
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.transformation.changing.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.transformation.changing</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.transformation.changing</h1>
+<p class="desc">Transformations are applied while building paths, not when drawing</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Transformations are applied while building paths, not when drawing");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.fillStyle = '#0f0';
+ctx.moveTo(0, 0);
+ctx.translate(100, 0);
+ctx.lineTo(0, 0);
+ctx.translate(0, 50);
+ctx.lineTo(0, 0);
+ctx.translate(-100, 0);
+ctx.lineTo(0, 0);
+ctx.translate(1000, 1000);
+ctx.rotate(Math.PI/2);
+ctx.scale(0.1, 0.1);
+ctx.fill();
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.transformation.multiple.html b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.transformation.multiple.html
new file mode 100644
index 00000000000..5d78d28c910
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/path-objects/2d.path.transformation.multiple.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.path.transformation.multiple</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.path.transformation.multiple</h1>
+<p class="desc">Transformations are applied while building paths, not when drawing</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Transformations are applied while building paths, not when drawing");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.fillStyle = '#f00';
+ctx.translate(-100, 0);
+ctx.rect(0, 0, 100, 50);
+ctx.fill();
+ctx.translate(100, 0);
+ctx.fill();
+
+ctx.beginPath();
+ctx.strokeStyle = '#f00';
+ctx.lineWidth = 50;
+ctx.translate(0, -50);
+ctx.moveTo(0, 25);
+ctx.lineTo(100, 25);
+ctx.stroke();
+ctx.translate(0, 50);
+ctx.stroke();
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/.gitkeep b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/.gitkeep
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create1.basic.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create1.basic.html
new file mode 100644
index 00000000000..cf236cd3381
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create1.basic.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.create1.basic</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.create1.basic</h1>
+<p class="desc">createImageData(imgdata) exists and returns something</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("createImageData(imgdata) exists and returns something");
+_addTest(function(canvas, ctx) {
+
+_assertDifferent(ctx.createImageData(ctx.createImageData(1, 1)), null, "ctx.createImageData(ctx.createImageData(1, 1))", "null");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create1.initial.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create1.initial.html
new file mode 100644
index 00000000000..15f67b72bb9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create1.initial.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.create1.initial</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.create1.initial</h1>
+<p class="desc">createImageData(imgdata) returns transparent black data of the right size</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("createImageData(imgdata) returns transparent black data of the right size");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+var imgdata1 = ctx.getImageData(0, 0, 10, 20);
+var imgdata2 = ctx.createImageData(imgdata1);
+_assertSame(imgdata2.data.length, imgdata1.data.length, "imgdata2.data.length", "imgdata1.data.length");
+_assertSame(imgdata2.width, imgdata1.width, "imgdata2.width", "imgdata1.width");
+_assertSame(imgdata2.height, imgdata1.height, "imgdata2.height", "imgdata1.height");
+var isTransparentBlack = true;
+for (var i = 0; i < imgdata2.data.length; ++i)
+ if (imgdata2.data[i] !== 0)
+ isTransparentBlack = false;
+_assert(isTransparentBlack, "isTransparentBlack");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create1.this.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create1.this.html
new file mode 100644
index 00000000000..1b9b2e0952d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create1.this.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.create1.this</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.create1.this</h1>
+<p class="desc">createImageData(imgdata) should throw when called with the wrong |this|</p>
+
+<p class="notes">Defined in "Web IDL" (draft)
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("createImageData(imgdata) should throw when called with the wrong |this|");
+_addTest(function(canvas, ctx) {
+
+var imgdata = ctx.createImageData(1, 1);
+assert_throws(new TypeError(), function() { CanvasRenderingContext2D.prototype.createImageData.call(null, imgdata); });
+assert_throws(new TypeError(), function() { CanvasRenderingContext2D.prototype.createImageData.call(undefined, imgdata); });
+assert_throws(new TypeError(), function() { CanvasRenderingContext2D.prototype.createImageData.call({}, imgdata); });
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create1.type.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create1.type.html
new file mode 100644
index 00000000000..8884035508d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create1.type.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.create1.type</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.create1.type</h1>
+<p class="desc">createImageData(imgdata) returns an ImageData object containing a Uint8ClampedArray object</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("createImageData(imgdata) returns an ImageData object containing a Uint8ClampedArray object");
+_addTest(function(canvas, ctx) {
+
+_assertDifferent(window.ImageData, undefined, "window.ImageData", "undefined");
+_assertDifferent(window.Uint8ClampedArray, undefined, "window.Uint8ClampedArray", "undefined");
+window.ImageData.prototype.thisImplementsImageData = true;
+window.Uint8ClampedArray.prototype.thisImplementsUint8ClampedArray = true;
+var imgdata = ctx.createImageData(ctx.createImageData(1, 1));
+_assert(imgdata.thisImplementsImageData, "imgdata.thisImplementsImageData");
+_assert(imgdata.data.thisImplementsUint8ClampedArray, "imgdata.data.thisImplementsUint8ClampedArray");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create1.zero.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create1.zero.html
new file mode 100644
index 00000000000..928c430f832
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create1.zero.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.create1.zero</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.create1.zero</h1>
+<p class="desc">createImageData(null) throws TypeError</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("createImageData(null) throws TypeError");
+_addTest(function(canvas, ctx) {
+
+assert_throws(new TypeError(), function() { ctx.createImageData(null); });
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create2.basic.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create2.basic.html
new file mode 100644
index 00000000000..51d3c13f9f6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create2.basic.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.create2.basic</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.create2.basic</h1>
+<p class="desc">createImageData(sw, sh) exists and returns something</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("createImageData(sw, sh) exists and returns something");
+_addTest(function(canvas, ctx) {
+
+_assertDifferent(ctx.createImageData(1, 1), null, "ctx.createImageData(1, 1)", "null");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create2.initial.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create2.initial.html
new file mode 100644
index 00000000000..a858c243781
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create2.initial.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.create2.initial</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.create2.initial</h1>
+<p class="desc">createImageData(sw, sh) returns transparent black data of the right size</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("createImageData(sw, sh) returns transparent black data of the right size");
+_addTest(function(canvas, ctx) {
+
+var imgdata = ctx.createImageData(10, 20);
+_assertSame(imgdata.data.length, imgdata.width*imgdata.height*4, "imgdata.data.length", "imgdata.width*imgdata.height*4");
+_assert(imgdata.width < imgdata.height, "imgdata.width < imgdata.height");
+_assert(imgdata.width > 0, "imgdata.width > 0");
+var isTransparentBlack = true;
+for (var i = 0; i < imgdata.data.length; ++i)
+ if (imgdata.data[i] !== 0)
+ isTransparentBlack = false;
+_assert(isTransparentBlack, "isTransparentBlack");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create2.large.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create2.large.html
new file mode 100644
index 00000000000..113a2319401
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create2.large.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.create2.large</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.create2.large</h1>
+<p class="desc">createImageData(sw, sh) works for sizes much larger than the canvas</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("createImageData(sw, sh) works for sizes much larger than the canvas");
+_addTest(function(canvas, ctx) {
+
+var imgdata = ctx.createImageData(1000, 2000);
+_assertSame(imgdata.data.length, imgdata.width*imgdata.height*4, "imgdata.data.length", "imgdata.width*imgdata.height*4");
+_assert(imgdata.width < imgdata.height, "imgdata.width < imgdata.height");
+_assert(imgdata.width > 0, "imgdata.width > 0");
+var isTransparentBlack = true;
+for (var i = 0; i < imgdata.data.length; i += 7813) // check ~1024 points (assuming normal scaling)
+ if (imgdata.data[i] !== 0)
+ isTransparentBlack = false;
+_assert(isTransparentBlack, "isTransparentBlack");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create2.negative.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create2.negative.html
new file mode 100644
index 00000000000..7a06ed45cea
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create2.negative.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.create2.negative</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.create2.negative</h1>
+<p class="desc">createImageData(sw, sh) takes the absolute magnitude of the size arguments</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("createImageData(sw, sh) takes the absolute magnitude of the size arguments");
+_addTest(function(canvas, ctx) {
+
+var imgdata1 = ctx.createImageData(10, 20);
+var imgdata2 = ctx.createImageData(-10, 20);
+var imgdata3 = ctx.createImageData(10, -20);
+var imgdata4 = ctx.createImageData(-10, -20);
+_assertSame(imgdata1.data.length, imgdata2.data.length, "imgdata1.data.length", "imgdata2.data.length");
+_assertSame(imgdata2.data.length, imgdata3.data.length, "imgdata2.data.length", "imgdata3.data.length");
+_assertSame(imgdata3.data.length, imgdata4.data.length, "imgdata3.data.length", "imgdata4.data.length");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create2.nonfinite.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create2.nonfinite.html
new file mode 100644
index 00000000000..3dabc30a63e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create2.nonfinite.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.create2.nonfinite</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.create2.nonfinite</h1>
+<p class="desc">createImageData() throws TypeError if arguments are not finite</p>
+
+<p class="notes">Defined in "Web IDL" (draft)
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("createImageData() throws TypeError if arguments are not finite");
+_addTest(function(canvas, ctx) {
+
+assert_throws(new TypeError(), function() { ctx.createImageData(Infinity, 10); });
+assert_throws(new TypeError(), function() { ctx.createImageData(-Infinity, 10); });
+assert_throws(new TypeError(), function() { ctx.createImageData(NaN, 10); });
+assert_throws(new TypeError(), function() { ctx.createImageData(10, Infinity); });
+assert_throws(new TypeError(), function() { ctx.createImageData(10, -Infinity); });
+assert_throws(new TypeError(), function() { ctx.createImageData(10, NaN); });
+assert_throws(new TypeError(), function() { ctx.createImageData(Infinity, Infinity); });
+var posinfobj = { valueOf: function() { return Infinity; } },
+ neginfobj = { valueOf: function() { return -Infinity; } },
+ nanobj = { valueOf: function() { return -Infinity; } };
+assert_throws(new TypeError(), function() { ctx.createImageData(posinfobj, 10); });
+assert_throws(new TypeError(), function() { ctx.createImageData(neginfobj, 10); });
+assert_throws(new TypeError(), function() { ctx.createImageData(nanobj, 10); });
+assert_throws(new TypeError(), function() { ctx.createImageData(10, posinfobj); });
+assert_throws(new TypeError(), function() { ctx.createImageData(10, neginfobj); });
+assert_throws(new TypeError(), function() { ctx.createImageData(10, nanobj); });
+assert_throws(new TypeError(), function() { ctx.createImageData(posinfobj, posinfobj); });
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create2.round.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create2.round.html
new file mode 100644
index 00000000000..84c2001783b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create2.round.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.create2.round</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.create2.round</h1>
+<p class="desc">createImageData(w, h) is rounded the same as getImageData(0, 0, w, h)</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("createImageData(w, h) is rounded the same as getImageData(0, 0, w, h)");
+_addTest(function(canvas, ctx) {
+
+var imgdata1 = ctx.createImageData(10.01, 10.99);
+var imgdata2 = ctx.getImageData(0, 0, 10.01, 10.99);
+_assertSame(imgdata1.width, imgdata2.width, "imgdata1.width", "imgdata2.width");
+_assertSame(imgdata1.height, imgdata2.height, "imgdata1.height", "imgdata2.height");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create2.this.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create2.this.html
new file mode 100644
index 00000000000..ff55218cff1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create2.this.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.create2.this</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.create2.this</h1>
+<p class="desc">createImageData(sw, sh) should throw when called with the wrong |this|</p>
+
+<p class="notes">Defined in "Web IDL" (draft)
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("createImageData(sw, sh) should throw when called with the wrong |this|");
+_addTest(function(canvas, ctx) {
+
+assert_throws(new TypeError(), function() { CanvasRenderingContext2D.prototype.createImageData.call(null, 1, 1); });
+assert_throws(new TypeError(), function() { CanvasRenderingContext2D.prototype.createImageData.call(undefined, 1, 1); });
+assert_throws(new TypeError(), function() { CanvasRenderingContext2D.prototype.createImageData.call({}, 1, 1); });
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create2.tiny.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create2.tiny.html
new file mode 100644
index 00000000000..dac0e5e6025
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create2.tiny.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.create2.tiny</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.create2.tiny</h1>
+<p class="desc">createImageData(sw, sh) works for sizes smaller than one pixel</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("createImageData(sw, sh) works for sizes smaller than one pixel");
+_addTest(function(canvas, ctx) {
+
+var imgdata = ctx.createImageData(0.0001, 0.0001);
+_assertSame(imgdata.data.length, imgdata.width*imgdata.height*4, "imgdata.data.length", "imgdata.width*imgdata.height*4");
+_assertSame(imgdata.width, 1, "imgdata.width", "1");
+_assertSame(imgdata.height, 1, "imgdata.height", "1");
+var isTransparentBlack = true;
+for (var i = 0; i < imgdata.data.length; ++i)
+ if (imgdata.data[i] !== 0)
+ isTransparentBlack = false;
+_assert(isTransparentBlack, "isTransparentBlack");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create2.type.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create2.type.html
new file mode 100644
index 00000000000..4e7b444cc17
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create2.type.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.create2.type</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.create2.type</h1>
+<p class="desc">createImageData(sw, sh) returns an ImageData object containing a Uint8ClampedArray object</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("createImageData(sw, sh) returns an ImageData object containing a Uint8ClampedArray object");
+_addTest(function(canvas, ctx) {
+
+_assertDifferent(window.ImageData, undefined, "window.ImageData", "undefined");
+_assertDifferent(window.Uint8ClampedArray, undefined, "window.Uint8ClampedArray", "undefined");
+window.ImageData.prototype.thisImplementsImageData = true;
+window.Uint8ClampedArray.prototype.thisImplementsUint8ClampedArray = true;
+var imgdata = ctx.createImageData(1, 1);
+_assert(imgdata.thisImplementsImageData, "imgdata.thisImplementsImageData");
+_assert(imgdata.data.thisImplementsUint8ClampedArray, "imgdata.data.thisImplementsUint8ClampedArray");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create2.zero.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create2.zero.html
new file mode 100644
index 00000000000..c8957caac76
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.create2.zero.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.create2.zero</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.create2.zero</h1>
+<p class="desc">createImageData(sw, sh) throws INDEX_SIZE_ERR if size is zero</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("createImageData(sw, sh) throws INDEX_SIZE_ERR if size is zero");
+_addTest(function(canvas, ctx) {
+
+assert_throws("INDEX_SIZE_ERR", function() { ctx.createImageData(10, 0); });
+assert_throws("INDEX_SIZE_ERR", function() { ctx.createImageData(0, 10); });
+assert_throws("INDEX_SIZE_ERR", function() { ctx.createImageData(0, 0); });
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.basic.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.basic.html
new file mode 100644
index 00000000000..d8bad1fd5d9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.basic.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.get.basic</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.get.basic</h1>
+<p class="desc">getImageData() exists and returns something</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("getImageData() exists and returns something");
+_addTest(function(canvas, ctx) {
+
+_assertDifferent(ctx.getImageData(0, 0, 100, 50), null, "ctx.getImageData(0, 0, 100, 50)", "null");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.clamp.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.clamp.html
new file mode 100644
index 00000000000..cc235bac0d1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.clamp.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.get.clamp</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.get.clamp</h1>
+<p class="desc">getImageData() clamps colours to the range [0, 255]</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("getImageData() clamps colours to the range [0, 255]");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = 'rgb(-100, -200, -300)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.fillStyle = 'rgb(256, 300, 400)';
+ctx.fillRect(20, 10, 60, 10);
+var imgdata1 = ctx.getImageData(10, 5, 1, 1);
+_assertSame(imgdata1.data[0], 0, "imgdata1.data[\""+(0)+"\"]", "0");
+_assertSame(imgdata1.data[1], 0, "imgdata1.data[\""+(1)+"\"]", "0");
+_assertSame(imgdata1.data[2], 0, "imgdata1.data[\""+(2)+"\"]", "0");
+var imgdata2 = ctx.getImageData(30, 15, 1, 1);
+_assertSame(imgdata2.data[0], 255, "imgdata2.data[\""+(0)+"\"]", "255");
+_assertSame(imgdata2.data[1], 255, "imgdata2.data[\""+(1)+"\"]", "255");
+_assertSame(imgdata2.data[2], 255, "imgdata2.data[\""+(2)+"\"]", "255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.length.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.length.html
new file mode 100644
index 00000000000..8bc30621c76
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.length.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.get.length</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.get.length</h1>
+<p class="desc">getImageData() returns a correctly-sized Uint8ClampedArray</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("getImageData() returns a correctly-sized Uint8ClampedArray");
+_addTest(function(canvas, ctx) {
+
+var imgdata = ctx.getImageData(0, 0, 10, 10);
+_assertSame(imgdata.data.length, imgdata.width*imgdata.height*4, "imgdata.data.length", "imgdata.width*imgdata.height*4");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.nonfinite.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.nonfinite.html
new file mode 100644
index 00000000000..176b7d8bb4f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.nonfinite.html
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.get.nonfinite</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.get.nonfinite</h1>
+<p class="desc">getImageData() throws TypeError if arguments are not finite</p>
+
+<p class="notes">Defined in "Web IDL" (draft)
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("getImageData() throws TypeError if arguments are not finite");
+_addTest(function(canvas, ctx) {
+
+assert_throws(new TypeError(), function() { ctx.getImageData(Infinity, 10, 10, 10); });
+assert_throws(new TypeError(), function() { ctx.getImageData(-Infinity, 10, 10, 10); });
+assert_throws(new TypeError(), function() { ctx.getImageData(NaN, 10, 10, 10); });
+assert_throws(new TypeError(), function() { ctx.getImageData(10, Infinity, 10, 10); });
+assert_throws(new TypeError(), function() { ctx.getImageData(10, -Infinity, 10, 10); });
+assert_throws(new TypeError(), function() { ctx.getImageData(10, NaN, 10, 10); });
+assert_throws(new TypeError(), function() { ctx.getImageData(10, 10, Infinity, 10); });
+assert_throws(new TypeError(), function() { ctx.getImageData(10, 10, -Infinity, 10); });
+assert_throws(new TypeError(), function() { ctx.getImageData(10, 10, NaN, 10); });
+assert_throws(new TypeError(), function() { ctx.getImageData(10, 10, 10, Infinity); });
+assert_throws(new TypeError(), function() { ctx.getImageData(10, 10, 10, -Infinity); });
+assert_throws(new TypeError(), function() { ctx.getImageData(10, 10, 10, NaN); });
+assert_throws(new TypeError(), function() { ctx.getImageData(Infinity, Infinity, 10, 10); });
+assert_throws(new TypeError(), function() { ctx.getImageData(Infinity, Infinity, Infinity, 10); });
+assert_throws(new TypeError(), function() { ctx.getImageData(Infinity, Infinity, Infinity, Infinity); });
+assert_throws(new TypeError(), function() { ctx.getImageData(Infinity, Infinity, 10, Infinity); });
+assert_throws(new TypeError(), function() { ctx.getImageData(Infinity, 10, Infinity, 10); });
+assert_throws(new TypeError(), function() { ctx.getImageData(Infinity, 10, Infinity, Infinity); });
+assert_throws(new TypeError(), function() { ctx.getImageData(Infinity, 10, 10, Infinity); });
+assert_throws(new TypeError(), function() { ctx.getImageData(10, Infinity, Infinity, 10); });
+assert_throws(new TypeError(), function() { ctx.getImageData(10, Infinity, Infinity, Infinity); });
+assert_throws(new TypeError(), function() { ctx.getImageData(10, Infinity, 10, Infinity); });
+assert_throws(new TypeError(), function() { ctx.getImageData(10, 10, Infinity, Infinity); });
+var posinfobj = { valueOf: function() { return Infinity; } },
+ neginfobj = { valueOf: function() { return -Infinity; } },
+ nanobj = { valueOf: function() { return -Infinity; } };
+assert_throws(new TypeError(), function() { ctx.getImageData(posinfobj, 10, 10, 10); });
+assert_throws(new TypeError(), function() { ctx.getImageData(neginfobj, 10, 10, 10); });
+assert_throws(new TypeError(), function() { ctx.getImageData(nanobj, 10, 10, 10); });
+assert_throws(new TypeError(), function() { ctx.getImageData(10, posinfobj, 10, 10); });
+assert_throws(new TypeError(), function() { ctx.getImageData(10, neginfobj, 10, 10); });
+assert_throws(new TypeError(), function() { ctx.getImageData(10, nanobj, 10, 10); });
+assert_throws(new TypeError(), function() { ctx.getImageData(10, 10, posinfobj, 10); });
+assert_throws(new TypeError(), function() { ctx.getImageData(10, 10, neginfobj, 10); });
+assert_throws(new TypeError(), function() { ctx.getImageData(10, 10, nanobj, 10); });
+assert_throws(new TypeError(), function() { ctx.getImageData(10, 10, 10, posinfobj); });
+assert_throws(new TypeError(), function() { ctx.getImageData(10, 10, 10, neginfobj); });
+assert_throws(new TypeError(), function() { ctx.getImageData(10, 10, 10, nanobj); });
+assert_throws(new TypeError(), function() { ctx.getImageData(posinfobj, posinfobj, 10, 10); });
+assert_throws(new TypeError(), function() { ctx.getImageData(posinfobj, posinfobj, posinfobj, 10); });
+assert_throws(new TypeError(), function() { ctx.getImageData(posinfobj, posinfobj, posinfobj, posinfobj); });
+assert_throws(new TypeError(), function() { ctx.getImageData(posinfobj, posinfobj, 10, posinfobj); });
+assert_throws(new TypeError(), function() { ctx.getImageData(posinfobj, 10, posinfobj, 10); });
+assert_throws(new TypeError(), function() { ctx.getImageData(posinfobj, 10, posinfobj, posinfobj); });
+assert_throws(new TypeError(), function() { ctx.getImageData(posinfobj, 10, 10, posinfobj); });
+assert_throws(new TypeError(), function() { ctx.getImageData(10, posinfobj, posinfobj, 10); });
+assert_throws(new TypeError(), function() { ctx.getImageData(10, posinfobj, posinfobj, posinfobj); });
+assert_throws(new TypeError(), function() { ctx.getImageData(10, posinfobj, 10, posinfobj); });
+assert_throws(new TypeError(), function() { ctx.getImageData(10, 10, posinfobj, posinfobj); });
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.nonpremul.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.nonpremul.html
new file mode 100644
index 00000000000..e8bce96f87b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.nonpremul.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.get.nonpremul</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.get.nonpremul</h1>
+<p class="desc">getImageData() returns non-premultiplied colours</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("getImageData() returns non-premultiplied colours");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = 'rgba(255, 255, 255, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+var imgdata = ctx.getImageData(10, 10, 10, 10);
+_assert(imgdata.data[0] > 200, "imgdata.data[\""+(0)+"\"] > 200");
+_assert(imgdata.data[1] > 200, "imgdata.data[\""+(1)+"\"] > 200");
+_assert(imgdata.data[2] > 200, "imgdata.data[\""+(2)+"\"] > 200");
+_assert(imgdata.data[3] > 100, "imgdata.data[\""+(3)+"\"] > 100");
+_assert(imgdata.data[3] < 200, "imgdata.data[\""+(3)+"\"] < 200");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.order.alpha.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.order.alpha.html
new file mode 100644
index 00000000000..e2453c49701
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.order.alpha.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.get.order.alpha</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.get.order.alpha</h1>
+<p class="desc">getImageData() returns A in the fourth component</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("getImageData() returns A in the fourth component");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = 'rgba(0, 0, 0, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+var imgdata = ctx.getImageData(0, 0, 10, 10);
+_assert(imgdata.data[3] < 200, "imgdata.data[\""+(3)+"\"] < 200");
+_assert(imgdata.data[3] > 100, "imgdata.data[\""+(3)+"\"] > 100");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.order.cols.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.order.cols.html
new file mode 100644
index 00000000000..123831380de
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.order.cols.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.get.order.cols</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.get.order.cols</h1>
+<p class="desc">getImageData() returns leftmost columns first</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("getImageData() returns leftmost columns first");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#fff';
+ctx.fillRect(0, 0, 100, 50);
+ctx.fillStyle = '#000';
+ctx.fillRect(0, 0, 2, 50);
+var imgdata = ctx.getImageData(0, 0, 10, 10);
+_assertSame(imgdata.data[0], 0, "imgdata.data[\""+(0)+"\"]", "0");
+_assertSame(imgdata.data[Math.round(imgdata.width/2*4)], 255, "imgdata.data[Math.round(imgdata.width/2*4)]", "255");
+_assertSame(imgdata.data[Math.round((imgdata.height/2)*imgdata.width*4)], 0, "imgdata.data[Math.round((imgdata.height/2)*imgdata.width*4)]", "0");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.order.rgb.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.order.rgb.html
new file mode 100644
index 00000000000..37531ecfa2e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.order.rgb.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.get.order.rgb</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.get.order.rgb</h1>
+<p class="desc">getImageData() returns R then G then B</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("getImageData() returns R then G then B");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#48c';
+ctx.fillRect(0, 0, 100, 50);
+var imgdata = ctx.getImageData(0, 0, 10, 10);
+_assertSame(imgdata.data[0], 0x44, "imgdata.data[\""+(0)+"\"]", "0x44");
+_assertSame(imgdata.data[1], 0x88, "imgdata.data[\""+(1)+"\"]", "0x88");
+_assertSame(imgdata.data[2], 0xCC, "imgdata.data[\""+(2)+"\"]", "0xCC");
+_assertSame(imgdata.data[3], 255, "imgdata.data[\""+(3)+"\"]", "255");
+_assertSame(imgdata.data[4], 0x44, "imgdata.data[\""+(4)+"\"]", "0x44");
+_assertSame(imgdata.data[5], 0x88, "imgdata.data[\""+(5)+"\"]", "0x88");
+_assertSame(imgdata.data[6], 0xCC, "imgdata.data[\""+(6)+"\"]", "0xCC");
+_assertSame(imgdata.data[7], 255, "imgdata.data[\""+(7)+"\"]", "255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.order.rows.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.order.rows.html
new file mode 100644
index 00000000000..de77dc6dde9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.order.rows.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.get.order.rows</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.get.order.rows</h1>
+<p class="desc">getImageData() returns topmost rows first</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("getImageData() returns topmost rows first");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#fff';
+ctx.fillRect(0, 0, 100, 50);
+ctx.fillStyle = '#000';
+ctx.fillRect(0, 0, 100, 2);
+var imgdata = ctx.getImageData(0, 0, 10, 10);
+_assertSame(imgdata.data[0], 0, "imgdata.data[\""+(0)+"\"]", "0");
+_assertSame(imgdata.data[Math.floor(imgdata.width/2*4)], 0, "imgdata.data[Math.floor(imgdata.width/2*4)]", "0");
+_assertSame(imgdata.data[(imgdata.height/2)*imgdata.width*4], 255, "imgdata.data[(imgdata.height/2)*imgdata.width*4]", "255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.range.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.range.html
new file mode 100644
index 00000000000..5f34e35df24
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.range.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.get.range</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.get.range</h1>
+<p class="desc">getImageData() returns values in the range [0, 255]</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("getImageData() returns values in the range [0, 255]");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#000';
+ctx.fillRect(0, 0, 100, 50);
+ctx.fillStyle = '#fff';
+ctx.fillRect(20, 10, 60, 10);
+var imgdata1 = ctx.getImageData(10, 5, 1, 1);
+_assertSame(imgdata1.data[0], 0, "imgdata1.data[\""+(0)+"\"]", "0");
+var imgdata2 = ctx.getImageData(30, 15, 1, 1);
+_assertSame(imgdata2.data[0], 255, "imgdata2.data[\""+(0)+"\"]", "255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.source.negative.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.source.negative.html
new file mode 100644
index 00000000000..4bab359fb81
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.source.negative.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.get.source.negative</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.get.source.negative</h1>
+<p class="desc">getImageData() works with negative width and height, and returns top-to-bottom left-to-right</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("getImageData() works with negative width and height, and returns top-to-bottom left-to-right");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#000';
+ctx.fillRect(0, 0, 100, 50);
+ctx.fillStyle = '#fff';
+ctx.fillRect(20, 10, 60, 10);
+
+var imgdata1 = ctx.getImageData(85, 25, -10, -10);
+_assertSame(imgdata1.data[0], 255, "imgdata1.data[\""+(0)+"\"]", "255");
+_assertSame(imgdata1.data[1], 255, "imgdata1.data[\""+(1)+"\"]", "255");
+_assertSame(imgdata1.data[2], 255, "imgdata1.data[\""+(2)+"\"]", "255");
+_assertSame(imgdata1.data[3], 255, "imgdata1.data[\""+(3)+"\"]", "255");
+_assertSame(imgdata1.data[imgdata1.data.length-4+0], 0, "imgdata1.data[imgdata1.data.length-4+0]", "0");
+_assertSame(imgdata1.data[imgdata1.data.length-4+1], 0, "imgdata1.data[imgdata1.data.length-4+1]", "0");
+_assertSame(imgdata1.data[imgdata1.data.length-4+2], 0, "imgdata1.data[imgdata1.data.length-4+2]", "0");
+_assertSame(imgdata1.data[imgdata1.data.length-4+3], 255, "imgdata1.data[imgdata1.data.length-4+3]", "255");
+
+var imgdata2 = ctx.getImageData(0, 0, -1, -1);
+_assertSame(imgdata2.data[0], 0, "imgdata2.data[\""+(0)+"\"]", "0");
+_assertSame(imgdata2.data[1], 0, "imgdata2.data[\""+(1)+"\"]", "0");
+_assertSame(imgdata2.data[2], 0, "imgdata2.data[\""+(2)+"\"]", "0");
+_assertSame(imgdata2.data[3], 0, "imgdata2.data[\""+(3)+"\"]", "0");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.source.outside.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.source.outside.html
new file mode 100644
index 00000000000..9950b60fffc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.source.outside.html
@@ -0,0 +1,86 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.get.source.outside</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.get.source.outside</h1>
+<p class="desc">getImageData() returns transparent black outside the canvas</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("getImageData() returns transparent black outside the canvas");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#08f';
+ctx.fillRect(0, 0, 100, 50);
+
+var imgdata1 = ctx.getImageData(-10, 5, 1, 1);
+_assertSame(imgdata1.data[0], 0, "imgdata1.data[\""+(0)+"\"]", "0");
+_assertSame(imgdata1.data[1], 0, "imgdata1.data[\""+(1)+"\"]", "0");
+_assertSame(imgdata1.data[2], 0, "imgdata1.data[\""+(2)+"\"]", "0");
+_assertSame(imgdata1.data[3], 0, "imgdata1.data[\""+(3)+"\"]", "0");
+
+var imgdata2 = ctx.getImageData(10, -5, 1, 1);
+_assertSame(imgdata2.data[0], 0, "imgdata2.data[\""+(0)+"\"]", "0");
+_assertSame(imgdata2.data[1], 0, "imgdata2.data[\""+(1)+"\"]", "0");
+_assertSame(imgdata2.data[2], 0, "imgdata2.data[\""+(2)+"\"]", "0");
+_assertSame(imgdata2.data[3], 0, "imgdata2.data[\""+(3)+"\"]", "0");
+
+var imgdata3 = ctx.getImageData(200, 5, 1, 1);
+_assertSame(imgdata3.data[0], 0, "imgdata3.data[\""+(0)+"\"]", "0");
+_assertSame(imgdata3.data[1], 0, "imgdata3.data[\""+(1)+"\"]", "0");
+_assertSame(imgdata3.data[2], 0, "imgdata3.data[\""+(2)+"\"]", "0");
+_assertSame(imgdata3.data[3], 0, "imgdata3.data[\""+(3)+"\"]", "0");
+
+var imgdata4 = ctx.getImageData(10, 60, 1, 1);
+_assertSame(imgdata4.data[0], 0, "imgdata4.data[\""+(0)+"\"]", "0");
+_assertSame(imgdata4.data[1], 0, "imgdata4.data[\""+(1)+"\"]", "0");
+_assertSame(imgdata4.data[2], 0, "imgdata4.data[\""+(2)+"\"]", "0");
+_assertSame(imgdata4.data[3], 0, "imgdata4.data[\""+(3)+"\"]", "0");
+
+var imgdata5 = ctx.getImageData(100, 10, 1, 1);
+_assertSame(imgdata5.data[0], 0, "imgdata5.data[\""+(0)+"\"]", "0");
+_assertSame(imgdata5.data[1], 0, "imgdata5.data[\""+(1)+"\"]", "0");
+_assertSame(imgdata5.data[2], 0, "imgdata5.data[\""+(2)+"\"]", "0");
+_assertSame(imgdata5.data[3], 0, "imgdata5.data[\""+(3)+"\"]", "0");
+
+var imgdata6 = ctx.getImageData(0, 10, 1, 1);
+_assertSame(imgdata6.data[0], 0, "imgdata6.data[\""+(0)+"\"]", "0");
+_assertSame(imgdata6.data[1], 136, "imgdata6.data[\""+(1)+"\"]", "136");
+_assertSame(imgdata6.data[2], 255, "imgdata6.data[\""+(2)+"\"]", "255");
+_assertSame(imgdata6.data[3], 255, "imgdata6.data[\""+(3)+"\"]", "255");
+
+var imgdata7 = ctx.getImageData(-10, 10, 20, 20);
+_assertSame(imgdata7.data[ 0*4+0], 0, "imgdata7.data[ 0*4+0]", "0");
+_assertSame(imgdata7.data[ 0*4+1], 0, "imgdata7.data[ 0*4+1]", "0");
+_assertSame(imgdata7.data[ 0*4+2], 0, "imgdata7.data[ 0*4+2]", "0");
+_assertSame(imgdata7.data[ 0*4+3], 0, "imgdata7.data[ 0*4+3]", "0");
+_assertSame(imgdata7.data[ 9*4+0], 0, "imgdata7.data[ 9*4+0]", "0");
+_assertSame(imgdata7.data[ 9*4+1], 0, "imgdata7.data[ 9*4+1]", "0");
+_assertSame(imgdata7.data[ 9*4+2], 0, "imgdata7.data[ 9*4+2]", "0");
+_assertSame(imgdata7.data[ 9*4+3], 0, "imgdata7.data[ 9*4+3]", "0");
+_assertSame(imgdata7.data[10*4+0], 0, "imgdata7.data[10*4+0]", "0");
+_assertSame(imgdata7.data[10*4+1], 136, "imgdata7.data[10*4+1]", "136");
+_assertSame(imgdata7.data[10*4+2], 255, "imgdata7.data[10*4+2]", "255");
+_assertSame(imgdata7.data[10*4+3], 255, "imgdata7.data[10*4+3]", "255");
+_assertSame(imgdata7.data[19*4+0], 0, "imgdata7.data[19*4+0]", "0");
+_assertSame(imgdata7.data[19*4+1], 136, "imgdata7.data[19*4+1]", "136");
+_assertSame(imgdata7.data[19*4+2], 255, "imgdata7.data[19*4+2]", "255");
+_assertSame(imgdata7.data[19*4+3], 255, "imgdata7.data[19*4+3]", "255");
+_assertSame(imgdata7.data[20*4+0], 0, "imgdata7.data[20*4+0]", "0");
+_assertSame(imgdata7.data[20*4+1], 0, "imgdata7.data[20*4+1]", "0");
+_assertSame(imgdata7.data[20*4+2], 0, "imgdata7.data[20*4+2]", "0");
+_assertSame(imgdata7.data[20*4+3], 0, "imgdata7.data[20*4+3]", "0");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.source.size.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.source.size.html
new file mode 100644
index 00000000000..0782b115127
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.source.size.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.get.source.size</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.get.source.size</h1>
+<p class="desc">getImageData() returns bigger ImageData for bigger source rectangle</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("getImageData() returns bigger ImageData for bigger source rectangle");
+_addTest(function(canvas, ctx) {
+
+var imgdata1 = ctx.getImageData(0, 0, 10, 10);
+var imgdata2 = ctx.getImageData(0, 0, 20, 20);
+_assert(imgdata2.width > imgdata1.width, "imgdata2.width > imgdata1.width");
+_assert(imgdata2.height > imgdata1.height, "imgdata2.height > imgdata1.height");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.tiny.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.tiny.html
new file mode 100644
index 00000000000..982f3f28b6f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.tiny.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.get.tiny</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.get.tiny</h1>
+<p class="desc">getImageData() works for sizes smaller than one pixel</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("getImageData() works for sizes smaller than one pixel");
+_addTest(function(canvas, ctx) {
+
+var imgdata = ctx.getImageData(0, 0, 0.0001, 0.0001);
+_assertSame(imgdata.data.length, imgdata.width*imgdata.height*4, "imgdata.data.length", "imgdata.width*imgdata.height*4");
+_assertSame(imgdata.width, 1, "imgdata.width", "1");
+_assertSame(imgdata.height, 1, "imgdata.height", "1");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.type.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.type.html
new file mode 100644
index 00000000000..76f711d583d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.type.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.get.type</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.get.type</h1>
+<p class="desc">getImageData() returns an ImageData object containing a Uint8ClampedArray object</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("getImageData() returns an ImageData object containing a Uint8ClampedArray object");
+_addTest(function(canvas, ctx) {
+
+_assertDifferent(window.ImageData, undefined, "window.ImageData", "undefined");
+_assertDifferent(window.Uint8ClampedArray, undefined, "window.Uint8ClampedArray", "undefined");
+window.ImageData.prototype.thisImplementsImageData = true;
+window.Uint8ClampedArray.prototype.thisImplementsUint8ClampedArray = true;
+var imgdata = ctx.getImageData(0, 0, 1, 1);
+_assert(imgdata.thisImplementsImageData, "imgdata.thisImplementsImageData");
+_assert(imgdata.data.thisImplementsUint8ClampedArray, "imgdata.data.thisImplementsUint8ClampedArray");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.unaffected.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.unaffected.html
new file mode 100644
index 00000000000..06afdb96083
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.unaffected.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.get.unaffected</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.get.unaffected</h1>
+<p class="desc">getImageData() is not affected by context state</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("getImageData() is not affected by context state");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 50, 50)
+ctx.fillStyle = '#f00';
+ctx.fillRect(50, 0, 50, 50)
+ctx.save();
+ctx.translate(50, 0);
+ctx.globalAlpha = 0.1;
+ctx.globalCompositeOperation = 'destination-atop';
+ctx.shadowColor = '#f00';
+ctx.rect(0, 0, 5, 5);
+ctx.clip();
+var imgdata = ctx.getImageData(0, 0, 50, 50);
+ctx.restore();
+ctx.putImageData(imgdata, 50, 0);
+_assertPixelApprox(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255", 2);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.zero.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.zero.html
new file mode 100644
index 00000000000..ed152172309
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.get.zero.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.get.zero</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.get.zero</h1>
+<p class="desc">getImageData() throws INDEX_SIZE_ERR if size is zero</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("getImageData() throws INDEX_SIZE_ERR if size is zero");
+_addTest(function(canvas, ctx) {
+
+assert_throws("INDEX_SIZE_ERR", function() { ctx.getImageData(1, 1, 10, 0); });
+assert_throws("INDEX_SIZE_ERR", function() { ctx.getImageData(1, 1, 0, 10); });
+assert_throws("INDEX_SIZE_ERR", function() { ctx.getImageData(1, 1, 0, 0); });
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.object.clamp.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.object.clamp.html
new file mode 100644
index 00000000000..61e10eea1df
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.object.clamp.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.object.clamp</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.object.clamp</h1>
+<p class="desc">ImageData.data clamps numbers to [0, 255]</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("ImageData.data clamps numbers to [0, 255]");
+_addTest(function(canvas, ctx) {
+
+var imgdata = ctx.getImageData(0, 0, 10, 10);
+
+imgdata.data[0] = 100;
+imgdata.data[0] = 300;
+_assertSame(imgdata.data[0], 255, "imgdata.data[\""+(0)+"\"]", "255");
+imgdata.data[0] = 100;
+imgdata.data[0] = -100;
+_assertSame(imgdata.data[0], 0, "imgdata.data[\""+(0)+"\"]", "0");
+
+imgdata.data[0] = 100;
+imgdata.data[0] = 200+Math.pow(2, 32);
+_assertSame(imgdata.data[0], 255, "imgdata.data[\""+(0)+"\"]", "255");
+imgdata.data[0] = 100;
+imgdata.data[0] = -200-Math.pow(2, 32);
+_assertSame(imgdata.data[0], 0, "imgdata.data[\""+(0)+"\"]", "0");
+
+imgdata.data[0] = 100;
+imgdata.data[0] = Math.pow(10, 39);
+_assertSame(imgdata.data[0], 255, "imgdata.data[\""+(0)+"\"]", "255");
+imgdata.data[0] = 100;
+imgdata.data[0] = -Math.pow(10, 39);
+_assertSame(imgdata.data[0], 0, "imgdata.data[\""+(0)+"\"]", "0");
+
+imgdata.data[0] = 100;
+imgdata.data[0] = -Infinity;
+_assertSame(imgdata.data[0], 0, "imgdata.data[\""+(0)+"\"]", "0");
+imgdata.data[0] = 100;
+imgdata.data[0] = Infinity;
+_assertSame(imgdata.data[0], 255, "imgdata.data[\""+(0)+"\"]", "255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.object.ctor.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.object.ctor.html
new file mode 100644
index 00000000000..c325966267c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.object.ctor.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.object.ctor</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.object.ctor</h1>
+<p class="desc">ImageData does not have a usable constructor</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("ImageData does not have a usable constructor");
+_addTest(function(canvas, ctx) {
+
+_assertDifferent(window.ImageData, undefined, "window.ImageData", "undefined");
+assert_throws(new TypeError(), function() { new window.ImageData(1,1); });
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.object.nan.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.object.nan.html
new file mode 100644
index 00000000000..4294b12f668
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.object.nan.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.object.nan</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.object.nan</h1>
+<p class="desc">ImageData.data converts NaN to 0</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("ImageData.data converts NaN to 0");
+_addTest(function(canvas, ctx) {
+
+var imgdata = ctx.getImageData(0, 0, 10, 10);
+imgdata.data[0] = 100;
+imgdata.data[0] = NaN;
+_assertSame(imgdata.data[0], 0, "imgdata.data[\""+(0)+"\"]", "0");
+imgdata.data[0] = 100;
+imgdata.data[0] = "cheese";
+_assertSame(imgdata.data[0], 0, "imgdata.data[\""+(0)+"\"]", "0");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.object.properties.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.object.properties.html
new file mode 100644
index 00000000000..a9ed94247f9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.object.properties.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.object.properties</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.object.properties</h1>
+<p class="desc">ImageData objects have the right properties</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("ImageData objects have the right properties");
+_addTest(function(canvas, ctx) {
+
+var imgdata = ctx.getImageData(0, 0, 10, 10);
+_assertSame(typeof(imgdata.width), 'number', "typeof(imgdata.width)", "'number'");
+_assertSame(typeof(imgdata.height), 'number', "typeof(imgdata.height)", "'number'");
+_assertSame(typeof(imgdata.data), 'object', "typeof(imgdata.data)", "'object'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.object.readonly.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.object.readonly.html
new file mode 100644
index 00000000000..6f183373329
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.object.readonly.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.object.readonly</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.object.readonly</h1>
+<p class="desc">ImageData objects properties are read-only</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("ImageData objects properties are read-only");
+_addTest(function(canvas, ctx) {
+
+var imgdata = ctx.getImageData(0, 0, 10, 10);
+var w = imgdata.width;
+var h = imgdata.height;
+var d = imgdata.data;
+imgdata.width = 123;
+imgdata.height = 123;
+imgdata.data = [100,100,100,100];
+_assertSame(imgdata.width, w, "imgdata.width", "w");
+_assertSame(imgdata.height, h, "imgdata.height", "h");
+_assertSame(imgdata.data, d, "imgdata.data", "d");
+_assertSame(imgdata.data[0], 0, "imgdata.data[\""+(0)+"\"]", "0");
+_assertSame(imgdata.data[1], 0, "imgdata.data[\""+(1)+"\"]", "0");
+_assertSame(imgdata.data[2], 0, "imgdata.data[\""+(2)+"\"]", "0");
+_assertSame(imgdata.data[3], 0, "imgdata.data[\""+(3)+"\"]", "0");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.object.round.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.object.round.html
new file mode 100644
index 00000000000..7f50a92c6ad
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.object.round.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.object.round</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.object.round</h1>
+<p class="desc">ImageData.data rounds numbers with round-to-zero</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("ImageData.data rounds numbers with round-to-zero");
+_addTest(function(canvas, ctx) {
+
+var imgdata = ctx.getImageData(0, 0, 10, 10);
+imgdata.data[0] = 0.499;
+_assertSame(imgdata.data[0], 0, "imgdata.data[\""+(0)+"\"]", "0");
+imgdata.data[0] = 0.5;
+_assertSame(imgdata.data[0], 0, "imgdata.data[\""+(0)+"\"]", "0");
+imgdata.data[0] = 0.501;
+_assertSame(imgdata.data[0], 1, "imgdata.data[\""+(0)+"\"]", "1");
+imgdata.data[0] = 1.499;
+_assertSame(imgdata.data[0], 1, "imgdata.data[\""+(0)+"\"]", "1");
+imgdata.data[0] = 1.5;
+_assertSame(imgdata.data[0], 2, "imgdata.data[\""+(0)+"\"]", "2");
+imgdata.data[0] = 1.501;
+_assertSame(imgdata.data[0], 2, "imgdata.data[\""+(0)+"\"]", "2");
+imgdata.data[0] = 2.5;
+_assertSame(imgdata.data[0], 2, "imgdata.data[\""+(0)+"\"]", "2");
+imgdata.data[0] = 3.5;
+_assertSame(imgdata.data[0], 4, "imgdata.data[\""+(0)+"\"]", "4");
+imgdata.data[0] = 252.5;
+_assertSame(imgdata.data[0], 252, "imgdata.data[\""+(0)+"\"]", "252");
+imgdata.data[0] = 253.5;
+_assertSame(imgdata.data[0], 254, "imgdata.data[\""+(0)+"\"]", "254");
+imgdata.data[0] = 254.5;
+_assertSame(imgdata.data[0], 254, "imgdata.data[\""+(0)+"\"]", "254");
+imgdata.data[0] = 256.5;
+_assertSame(imgdata.data[0], 255, "imgdata.data[\""+(0)+"\"]", "255");
+imgdata.data[0] = -0.5;
+_assertSame(imgdata.data[0], 0, "imgdata.data[\""+(0)+"\"]", "0");
+imgdata.data[0] = -1.5;
+_assertSame(imgdata.data[0], 0, "imgdata.data[\""+(0)+"\"]", "0");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.object.set.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.object.set.html
new file mode 100644
index 00000000000..dd63ceb90ad
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.object.set.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.object.set</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.object.set</h1>
+<p class="desc">ImageData.data can be modified</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("ImageData.data can be modified");
+_addTest(function(canvas, ctx) {
+
+var imgdata = ctx.getImageData(0, 0, 10, 10);
+imgdata.data[0] = 100;
+_assertSame(imgdata.data[0], 100, "imgdata.data[\""+(0)+"\"]", "100");
+imgdata.data[0] = 200;
+_assertSame(imgdata.data[0], 200, "imgdata.data[\""+(0)+"\"]", "200");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.object.string.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.object.string.html
new file mode 100644
index 00000000000..625b5575094
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.object.string.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.object.string</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.object.string</h1>
+<p class="desc">ImageData.data converts strings to numbers with ToNumber</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("ImageData.data converts strings to numbers with ToNumber");
+_addTest(function(canvas, ctx) {
+
+var imgdata = ctx.getImageData(0, 0, 10, 10);
+imgdata.data[0] = 100;
+imgdata.data[0] = "110";
+_assertSame(imgdata.data[0], 110, "imgdata.data[\""+(0)+"\"]", "110");
+imgdata.data[0] = 100;
+imgdata.data[0] = "0x78";
+_assertSame(imgdata.data[0], 120, "imgdata.data[\""+(0)+"\"]", "120");
+imgdata.data[0] = 100;
+imgdata.data[0] = " +130e0 ";
+_assertSame(imgdata.data[0], 130, "imgdata.data[\""+(0)+"\"]", "130");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.object.undefined.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.object.undefined.html
new file mode 100644
index 00000000000..1abf84330fa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.object.undefined.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.object.undefined</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.object.undefined</h1>
+<p class="desc">ImageData.data converts undefined to 0</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("ImageData.data converts undefined to 0");
+_addTest(function(canvas, ctx) {
+
+var imgdata = ctx.getImageData(0, 0, 10, 10);
+imgdata.data[0] = 100;
+imgdata.data[0] = undefined;
+_assertSame(imgdata.data[0], 0, "imgdata.data[\""+(0)+"\"]", "0");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.alpha.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.alpha.html
new file mode 100644
index 00000000000..9d19471492c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.alpha.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.put.alpha</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.put.alpha</h1>
+<p class="desc">putImageData() puts non-solid image data correctly</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.imageData.put.alpha.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("putImageData() puts non-solid image data correctly");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = 'rgba(0, 255, 0, 0.25)';
+ctx.fillRect(0, 0, 100, 50)
+var imgdata = ctx.getImageData(0, 0, 100, 50);
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50)
+ctx.putImageData(imgdata, 0, 0);
+_assertPixelApprox(canvas, 50,25, 0,255,0,64, "50,25", "0,255,0,64", 2);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.alpha.png b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.alpha.png
new file mode 100644
index 00000000000..5428c65524e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.alpha.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.basic.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.basic.html
new file mode 100644
index 00000000000..7d7de3cc4fd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.basic.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.put.basic</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.put.basic</h1>
+<p class="desc">putImageData() puts image data from getImageData() onto the canvas</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("putImageData() puts image data from getImageData() onto the canvas");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50)
+var imgdata = ctx.getImageData(0, 0, 100, 50);
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50)
+ctx.putImageData(imgdata, 0, 0);
+_assertPixelApprox(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 2);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.clip.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.clip.html
new file mode 100644
index 00000000000..8e8b19a6095
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.clip.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.put.clip</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.put.clip</h1>
+<p class="desc">putImageData() is not affected by clipping regions</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("putImageData() is not affected by clipping regions");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50)
+var imgdata = ctx.getImageData(0, 0, 100, 50);
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50)
+ctx.beginPath();
+ctx.rect(0, 0, 50, 50);
+ctx.clip();
+ctx.putImageData(imgdata, 0, 0);
+_assertPixelApprox(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255", 2);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.created.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.created.html
new file mode 100644
index 00000000000..4b1dd11bdb8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.created.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.put.created</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.put.created</h1>
+<p class="desc">putImageData() puts image data from createImageData() onto the canvas</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("putImageData() puts image data from createImageData() onto the canvas");
+_addTest(function(canvas, ctx) {
+
+var imgdata = ctx.createImageData(100, 50);
+for (var i = 0; i < imgdata.data.length; i += 4) {
+ imgdata.data[i] = 0;
+ imgdata.data[i+1] = 255;
+ imgdata.data[i+2] = 0;
+ imgdata.data[i+3] = 255;
+}
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50)
+ctx.putImageData(imgdata, 0, 0);
+_assertPixelApprox(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 2);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.cross.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.cross.html
new file mode 100644
index 00000000000..5fc59090a9a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.cross.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.put.cross</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.put.cross</h1>
+<p class="desc">putImageData() accepts image data got from a different canvas</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("putImageData() accepts image data got from a different canvas");
+_addTest(function(canvas, ctx) {
+
+var canvas2 = document.createElement('canvas');
+var ctx2 = canvas2.getContext('2d');
+ctx2.fillStyle = '#0f0';
+ctx2.fillRect(0, 0, 100, 50)
+var imgdata = ctx2.getImageData(0, 0, 100, 50);
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50)
+ctx.putImageData(imgdata, 0, 0);
+_assertPixelApprox(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 2);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.dirty.negative.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.dirty.negative.html
new file mode 100644
index 00000000000..67cf410cc34
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.dirty.negative.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.put.dirty.negative</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.put.dirty.negative</h1>
+<p class="desc">putImageData() handles negative-sized dirty rectangles correctly</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("putImageData() handles negative-sized dirty rectangles correctly");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50)
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 20, 20)
+
+var imgdata = ctx.getImageData(0, 0, 100, 50);
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50)
+ctx.fillStyle = '#f00';
+ctx.fillRect(40, 20, 20, 20)
+ctx.putImageData(imgdata, 40, 20, 20, 20, -20, -20);
+
+_assertPixelApprox(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 35,25, 0,255,0,255, "35,25", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 65,25, 0,255,0,255, "65,25", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 50,15, 0,255,0,255, "50,15", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 50,45, 0,255,0,255, "50,45", "0,255,0,255", 2);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.dirty.outside.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.dirty.outside.html
new file mode 100644
index 00000000000..81dc98ca971
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.dirty.outside.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.put.dirty.outside</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.put.dirty.outside</h1>
+<p class="desc">putImageData() handles dirty rectangles outside the canvas correctly</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("putImageData() handles dirty rectangles outside the canvas correctly");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50)
+
+var imgdata = ctx.getImageData(0, 0, 100, 50);
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50)
+
+ctx.putImageData(imgdata, 100, 20, 20, 20, -20, -20);
+ctx.putImageData(imgdata, 200, 200, 0, 0, 100, 50);
+ctx.putImageData(imgdata, 40, 20, -30, -20, 30, 20);
+ctx.putImageData(imgdata, -30, 20, 0, 0, 30, 20);
+
+_assertPixelApprox(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 98,15, 0,255,0,255, "98,15", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 98,25, 0,255,0,255, "98,25", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 98,45, 0,255,0,255, "98,45", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 1,5, 0,255,0,255, "1,5", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 1,25, 0,255,0,255, "1,25", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 1,45, 0,255,0,255, "1,45", "0,255,0,255", 2);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.dirty.rect1.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.dirty.rect1.html
new file mode 100644
index 00000000000..b94a9f58149
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.dirty.rect1.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.put.dirty.rect1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.put.dirty.rect1</h1>
+<p class="desc">putImageData() only modifies areas inside the dirty rectangle, using width and height</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("putImageData() only modifies areas inside the dirty rectangle, using width and height");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50)
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 20, 20)
+
+var imgdata = ctx.getImageData(0, 0, 100, 50);
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50)
+ctx.fillStyle = '#f00';
+ctx.fillRect(40, 20, 20, 20)
+ctx.putImageData(imgdata, 40, 20, 0, 0, 20, 20);
+
+_assertPixelApprox(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 35,25, 0,255,0,255, "35,25", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 65,25, 0,255,0,255, "65,25", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 50,15, 0,255,0,255, "50,15", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 50,45, 0,255,0,255, "50,45", "0,255,0,255", 2);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.dirty.rect2.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.dirty.rect2.html
new file mode 100644
index 00000000000..1fb5c141664
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.dirty.rect2.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.put.dirty.rect2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.put.dirty.rect2</h1>
+<p class="desc">putImageData() only modifies areas inside the dirty rectangle, using x and y</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("putImageData() only modifies areas inside the dirty rectangle, using x and y");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50)
+ctx.fillStyle = '#0f0';
+ctx.fillRect(60, 30, 20, 20)
+
+var imgdata = ctx.getImageData(0, 0, 100, 50);
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50)
+ctx.fillStyle = '#f00';
+ctx.fillRect(40, 20, 20, 20)
+ctx.putImageData(imgdata, -20, -10, 60, 30, 20, 20);
+
+_assertPixelApprox(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 35,25, 0,255,0,255, "35,25", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 65,25, 0,255,0,255, "65,25", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 50,15, 0,255,0,255, "50,15", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 50,45, 0,255,0,255, "50,45", "0,255,0,255", 2);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.dirty.zero.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.dirty.zero.html
new file mode 100644
index 00000000000..726fdb80956
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.dirty.zero.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.put.dirty.zero</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.put.dirty.zero</h1>
+<p class="desc">putImageData() with zero-sized dirty rectangle puts nothing</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("putImageData() with zero-sized dirty rectangle puts nothing");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50)
+var imgdata = ctx.getImageData(0, 0, 100, 50);
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50)
+ctx.putImageData(imgdata, 0, 0, 0, 0, 0, 0);
+_assertPixelApprox(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 2);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.modified.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.modified.html
new file mode 100644
index 00000000000..5815aeb26b6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.modified.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.put.modified</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.put.modified</h1>
+<p class="desc">putImageData() puts modified image data correctly</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("putImageData() puts modified image data correctly");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50)
+ctx.fillStyle = '#f00';
+ctx.fillRect(45, 20, 10, 10)
+var imgdata = ctx.getImageData(45, 20, 10, 10);
+for (var i = 0, len = imgdata.width*imgdata.height*4; i < len; i += 4)
+{
+ imgdata.data[i] = 0;
+ imgdata.data[i+1] = 255;
+}
+ctx.putImageData(imgdata, 45, 20);
+_assertPixelApprox(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 2);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.nonfinite.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.nonfinite.html
new file mode 100644
index 00000000000..861545ff3a8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.nonfinite.html
@@ -0,0 +1,109 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.put.nonfinite</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.put.nonfinite</h1>
+<p class="desc">putImageData() throws TypeError if arguments are not finite</p>
+
+<p class="notes">Defined in "Web IDL" (draft)
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("putImageData() throws TypeError if arguments are not finite");
+_addTest(function(canvas, ctx) {
+
+var imgdata = ctx.getImageData(0, 0, 10, 10);
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, Infinity, 10); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, -Infinity, 10); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, NaN, 10); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, 10, Infinity); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, 10, -Infinity); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, 10, NaN); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, Infinity, Infinity); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, Infinity, 10, 10, 10, 10, 10); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, -Infinity, 10, 10, 10, 10, 10); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, NaN, 10, 10, 10, 10, 10); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, 10, Infinity, 10, 10, 10, 10); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, 10, -Infinity, 10, 10, 10, 10); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, 10, NaN, 10, 10, 10, 10); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, 10, 10, Infinity, 10, 10, 10); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, 10, 10, -Infinity, 10, 10, 10); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, 10, 10, NaN, 10, 10, 10); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, 10, 10, 10, Infinity, 10, 10); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, 10, 10, 10, -Infinity, 10, 10); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, 10, 10, 10, NaN, 10, 10); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, 10, 10, 10, 10, Infinity, 10); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, 10, 10, 10, 10, -Infinity, 10); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, 10, 10, 10, 10, NaN, 10); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, 10, 10, 10, 10, 10, Infinity); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, 10, 10, 10, 10, 10, -Infinity); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, 10, 10, 10, 10, 10, NaN); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, Infinity, Infinity, 10, 10, 10, 10); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, Infinity, Infinity, Infinity, 10, 10, 10); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, Infinity, Infinity, Infinity, Infinity, 10, 10); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, Infinity, Infinity, Infinity, Infinity, Infinity, 10); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, Infinity, Infinity, Infinity, Infinity, Infinity, Infinity); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, Infinity, Infinity, Infinity, Infinity, 10, Infinity); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, Infinity, Infinity, Infinity, 10, Infinity, 10); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, Infinity, Infinity, Infinity, 10, Infinity, Infinity); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, Infinity, Infinity, Infinity, 10, 10, Infinity); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, Infinity, Infinity, 10, Infinity, 10, 10); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, Infinity, Infinity, 10, Infinity, Infinity, 10); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, Infinity, Infinity, 10, Infinity, Infinity, Infinity); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, Infinity, Infinity, 10, Infinity, 10, Infinity); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, Infinity, Infinity, 10, 10, Infinity, 10); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, Infinity, Infinity, 10, 10, Infinity, Infinity); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, Infinity, Infinity, 10, 10, 10, Infinity); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, Infinity, 10, Infinity, 10, 10, 10); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, Infinity, 10, Infinity, Infinity, 10, 10); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, Infinity, 10, Infinity, Infinity, Infinity, 10); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, Infinity, 10, Infinity, Infinity, Infinity, Infinity); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, Infinity, 10, Infinity, Infinity, 10, Infinity); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, Infinity, 10, Infinity, 10, Infinity, 10); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, Infinity, 10, Infinity, 10, Infinity, Infinity); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, Infinity, 10, Infinity, 10, 10, Infinity); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, Infinity, 10, 10, Infinity, 10, 10); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, Infinity, 10, 10, Infinity, Infinity, 10); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, Infinity, 10, 10, Infinity, Infinity, Infinity); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, Infinity, 10, 10, Infinity, 10, Infinity); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, Infinity, 10, 10, 10, Infinity, 10); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, Infinity, 10, 10, 10, Infinity, Infinity); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, Infinity, 10, 10, 10, 10, Infinity); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, 10, Infinity, Infinity, 10, 10, 10); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, 10, Infinity, Infinity, Infinity, 10, 10); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, 10, Infinity, Infinity, Infinity, Infinity, 10); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, 10, Infinity, Infinity, Infinity, Infinity, Infinity); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, 10, Infinity, Infinity, Infinity, 10, Infinity); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, 10, Infinity, Infinity, 10, Infinity, 10); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, 10, Infinity, Infinity, 10, Infinity, Infinity); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, 10, Infinity, Infinity, 10, 10, Infinity); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, 10, Infinity, 10, Infinity, 10, 10); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, 10, Infinity, 10, Infinity, Infinity, 10); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, 10, Infinity, 10, Infinity, Infinity, Infinity); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, 10, Infinity, 10, Infinity, 10, Infinity); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, 10, Infinity, 10, 10, Infinity, 10); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, 10, Infinity, 10, 10, Infinity, Infinity); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, 10, Infinity, 10, 10, 10, Infinity); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, 10, 10, Infinity, Infinity, 10, 10); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, 10, 10, Infinity, Infinity, Infinity, 10); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, 10, 10, Infinity, Infinity, Infinity, Infinity); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, 10, 10, Infinity, Infinity, 10, Infinity); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, 10, 10, Infinity, 10, Infinity, 10); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, 10, 10, Infinity, 10, Infinity, Infinity); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, 10, 10, Infinity, 10, 10, Infinity); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, 10, 10, 10, Infinity, Infinity, 10); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, 10, 10, 10, Infinity, Infinity, Infinity); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, 10, 10, 10, Infinity, 10, Infinity); });
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, 10, 10, 10, 10, Infinity, Infinity); });
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.null.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.null.html
new file mode 100644
index 00000000000..f827babc5a6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.null.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.put.null</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.put.null</h1>
+<p class="desc">putImageData() with null imagedata throws TypeError</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("putImageData() with null imagedata throws TypeError");
+_addTest(function(canvas, ctx) {
+
+assert_throws(new TypeError(), function() { ctx.putImageData(null, 0, 0); });
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.path.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.path.html
new file mode 100644
index 00000000000..7994e8647c9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.path.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.put.path</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.put.path</h1>
+<p class="desc">putImageData() does not affect the current path</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("putImageData() does not affect the current path");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50)
+ctx.rect(0, 0, 100, 50);
+var imgdata = ctx.getImageData(0, 0, 100, 50);
+ctx.putImageData(imgdata, 0, 0);
+ctx.fillStyle = '#0f0';
+ctx.fill();
+_assertPixelApprox(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 2);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.unaffected.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.unaffected.html
new file mode 100644
index 00000000000..8eee159958f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.unaffected.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.put.unaffected</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.put.unaffected</h1>
+<p class="desc">putImageData() is not affected by context state</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("putImageData() is not affected by context state");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50)
+var imgdata = ctx.getImageData(0, 0, 100, 50);
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50)
+ctx.globalAlpha = 0.1;
+ctx.globalCompositeOperation = 'destination-atop';
+ctx.shadowColor = '#f00';
+ctx.shadowBlur = 1;
+ctx.translate(100, 50);
+ctx.scale(0.1, 0.1);
+ctx.putImageData(imgdata, 0, 0);
+_assertPixelApprox(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 2);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.unchanged.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.unchanged.html
new file mode 100644
index 00000000000..59e05fbce22
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.unchanged.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.put.unchanged</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.put.unchanged</h1>
+<p class="desc">putImageData(getImageData(...), ...) has no effect</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("putImageData(getImageData(...), ...) has no effect");
+_addTest(function(canvas, ctx) {
+
+var i = 0;
+for (var y = 0; y < 16; ++y) {
+ for (var x = 0; x < 16; ++x, ++i) {
+ ctx.fillStyle = 'rgba(' + i + ',' + (Math.floor(i*1.5) % 256) + ',' + (Math.floor(i*23.3) % 256) + ',' + (i/256) + ')';
+ ctx.fillRect(x, y, 1, 1);
+ }
+}
+var imgdata1 = ctx.getImageData(0.1, 0.2, 15.8, 15.9);
+var olddata = [];
+for (var i = 0; i < imgdata1.data.length; ++i)
+ olddata[i] = imgdata1.data[i];
+
+ctx.putImageData(imgdata1, 0.1, 0.2);
+
+var imgdata2 = ctx.getImageData(0.1, 0.2, 15.8, 15.9);
+for (var i = 0; i < imgdata2.data.length; ++i) {
+ _assertSame(olddata[i], imgdata2.data[i], "olddata[\""+(i)+"\"]", "imgdata2.data[\""+(i)+"\"]");
+}
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.wrongtype.html b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.wrongtype.html
new file mode 100644
index 00000000000..085097fd4ec
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/pixel-manipulation/2d.imageData.put.wrongtype.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.imageData.put.wrongtype</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.imageData.put.wrongtype</h1>
+<p class="desc">putImageData() does not accept non-ImageData objects</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("putImageData() does not accept non-ImageData objects");
+_addTest(function(canvas, ctx) {
+
+var imgdata = { width: 1, height: 1, data: [255, 0, 0, 255] };
+assert_throws(new TypeError(), function() { ctx.putImageData(imgdata, 0, 0); });
+assert_throws(new TypeError(), function() { ctx.putImageData("cheese", 0, 0); });
+assert_throws(new TypeError(), function() { ctx.putImageData(42, 0, 0); });
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/.gitkeep b/tests/wpt/web-platform-tests/2dcontext/shadows/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/.gitkeep
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.alpha.1.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.alpha.1.html
new file mode 100644
index 00000000000..d541cd4b8ca
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.alpha.1.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.alpha.1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.alpha.1</h1>
+<p class="desc">Shadow colour alpha components are used</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Shadow colour alpha components are used");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.shadowColor = 'rgba(255, 0, 0, 0.01)';
+ctx.shadowOffsetY = 50;
+ctx.fillRect(0, -50, 100, 50);
+
+_assertPixelApprox(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 4);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.alpha.2.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.alpha.2.html
new file mode 100644
index 00000000000..2176182927a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.alpha.2.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.alpha.2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.alpha.2</h1>
+<p class="desc">Shadow colour alpha components are used</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.shadow.alpha.2.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Shadow colour alpha components are used");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.shadowColor = 'rgba(0, 0, 255, 0.5)';
+ctx.shadowOffsetY = 50;
+ctx.fillRect(0, -50, 100, 50);
+
+_assertPixelApprox(canvas, 50,25, 127,0,127,255, "50,25", "127,0,127,255", 2);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.alpha.2.png b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.alpha.2.png
new file mode 100644
index 00000000000..8764e89b371
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.alpha.2.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.alpha.3.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.alpha.3.html
new file mode 100644
index 00000000000..970575478b0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.alpha.3.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.alpha.3</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.alpha.3</h1>
+<p class="desc">Shadows are affected by globalAlpha</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.shadow.alpha.3.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Shadows are affected by globalAlpha");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.fillStyle = '#f00'; // (work around broken Firefox globalAlpha caching)
+ctx.shadowColor = '#00f';
+ctx.shadowOffsetY = 50;
+ctx.globalAlpha = 0.5;
+ctx.fillRect(0, -50, 100, 50);
+
+_assertPixelApprox(canvas, 50,25, 127,0,127,255, "50,25", "127,0,127,255", 2);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.alpha.3.png b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.alpha.3.png
new file mode 100644
index 00000000000..8764e89b371
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.alpha.3.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.alpha.4.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.alpha.4.html
new file mode 100644
index 00000000000..0621af631fc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.alpha.4.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.alpha.4</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.alpha.4</h1>
+<p class="desc">Shadows with alpha components are correctly affected by globalAlpha</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.shadow.alpha.4.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Shadows with alpha components are correctly affected by globalAlpha");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.fillStyle = '#f00'; // (work around broken Firefox globalAlpha caching)
+ctx.shadowColor = 'rgba(0, 0, 255, 0.707)';
+ctx.shadowOffsetY = 50;
+ctx.globalAlpha = 0.707;
+ctx.fillRect(0, -50, 100, 50);
+
+_assertPixelApprox(canvas, 50,25, 127,0,127,255, "50,25", "127,0,127,255", 2);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.alpha.4.png b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.alpha.4.png
new file mode 100644
index 00000000000..8764e89b371
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.alpha.4.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.alpha.5.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.alpha.5.html
new file mode 100644
index 00000000000..95cb2f39930
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.alpha.5.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.alpha.5</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.alpha.5</h1>
+<p class="desc">Shadows of shapes with alpha components are drawn correctly</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.shadow.alpha.5.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Shadows of shapes with alpha components are drawn correctly");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.fillStyle = 'rgba(64, 0, 0, 0.5)';
+ctx.shadowColor = '#00f';
+ctx.shadowOffsetY = 50;
+ctx.fillRect(0, -50, 100, 50);
+
+_assertPixelApprox(canvas, 50,25, 127,0,127,255, "50,25", "127,0,127,255", 2);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.alpha.5.png b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.alpha.5.png
new file mode 100644
index 00000000000..8764e89b371
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.alpha.5.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.attributes.shadowBlur.initial.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.attributes.shadowBlur.initial.html
new file mode 100644
index 00000000000..7b65cac6f4e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.attributes.shadowBlur.initial.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.attributes.shadowBlur.initial</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.attributes.shadowBlur.initial</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+_assertSame(ctx.shadowBlur, 0, "ctx.shadowBlur", "0");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.attributes.shadowBlur.invalid.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.attributes.shadowBlur.invalid.html
new file mode 100644
index 00000000000..c4bf2ba991c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.attributes.shadowBlur.invalid.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.attributes.shadowBlur.invalid</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.attributes.shadowBlur.invalid</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.shadowBlur = 1;
+ctx.shadowBlur = -2;
+_assertSame(ctx.shadowBlur, 1, "ctx.shadowBlur", "1");
+
+ctx.shadowBlur = 1;
+ctx.shadowBlur = Infinity;
+_assertSame(ctx.shadowBlur, 1, "ctx.shadowBlur", "1");
+
+ctx.shadowBlur = 1;
+ctx.shadowBlur = -Infinity;
+_assertSame(ctx.shadowBlur, 1, "ctx.shadowBlur", "1");
+
+ctx.shadowBlur = 1;
+ctx.shadowBlur = NaN;
+_assertSame(ctx.shadowBlur, 1, "ctx.shadowBlur", "1");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.attributes.shadowBlur.valid.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.attributes.shadowBlur.valid.html
new file mode 100644
index 00000000000..6aa9f9b1ae9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.attributes.shadowBlur.valid.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.attributes.shadowBlur.valid</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.attributes.shadowBlur.valid</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.shadowBlur = 1;
+_assertSame(ctx.shadowBlur, 1, "ctx.shadowBlur", "1");
+
+ctx.shadowBlur = 0.5;
+_assertSame(ctx.shadowBlur, 0.5, "ctx.shadowBlur", "0.5");
+
+ctx.shadowBlur = 1e6;
+_assertSame(ctx.shadowBlur, 1e6, "ctx.shadowBlur", "1e6");
+
+ctx.shadowBlur = 0;
+_assertSame(ctx.shadowBlur, 0, "ctx.shadowBlur", "0");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.attributes.shadowColor.initial.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.attributes.shadowColor.initial.html
new file mode 100644
index 00000000000..3f7471333d6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.attributes.shadowColor.initial.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.attributes.shadowColor.initial</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.attributes.shadowColor.initial</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+_assertSame(ctx.shadowColor, 'rgba(0, 0, 0, 0)', "ctx.shadowColor", "'rgba(0, 0, 0, 0)'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.attributes.shadowColor.invalid.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.attributes.shadowColor.invalid.html
new file mode 100644
index 00000000000..5f28ecbae06
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.attributes.shadowColor.invalid.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.attributes.shadowColor.invalid</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.attributes.shadowColor.invalid</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.shadowColor = '#00ff00';
+ctx.shadowColor = 'bogus';
+_assertSame(ctx.shadowColor, '#00ff00', "ctx.shadowColor", "'#00ff00'");
+
+ctx.shadowColor = '#00ff00';
+ctx.shadowColor = 'red bogus';
+_assertSame(ctx.shadowColor, '#00ff00', "ctx.shadowColor", "'#00ff00'");
+
+ctx.shadowColor = '#00ff00';
+ctx.shadowColor = ctx;
+_assertSame(ctx.shadowColor, '#00ff00', "ctx.shadowColor", "'#00ff00'");
+
+ctx.shadowColor = '#00ff00';
+ctx.shadowColor = undefined;
+_assertSame(ctx.shadowColor, '#00ff00', "ctx.shadowColor", "'#00ff00'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.attributes.shadowColor.valid.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.attributes.shadowColor.valid.html
new file mode 100644
index 00000000000..02ce65c905d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.attributes.shadowColor.valid.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.attributes.shadowColor.valid</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.attributes.shadowColor.valid</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.shadowColor = 'lime';
+_assertSame(ctx.shadowColor, '#00ff00', "ctx.shadowColor", "'#00ff00'");
+
+ctx.shadowColor = 'RGBA(0,255, 0,0)';
+_assertSame(ctx.shadowColor, 'rgba(0, 255, 0, 0)', "ctx.shadowColor", "'rgba(0, 255, 0, 0)'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.attributes.shadowOffset.initial.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.attributes.shadowOffset.initial.html
new file mode 100644
index 00000000000..35f1317f2f5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.attributes.shadowOffset.initial.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.attributes.shadowOffset.initial</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.attributes.shadowOffset.initial</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+_assertSame(ctx.shadowOffsetX, 0, "ctx.shadowOffsetX", "0");
+_assertSame(ctx.shadowOffsetY, 0, "ctx.shadowOffsetY", "0");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.attributes.shadowOffset.invalid.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.attributes.shadowOffset.invalid.html
new file mode 100644
index 00000000000..0b1ef728c4f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.attributes.shadowOffset.invalid.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.attributes.shadowOffset.invalid</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.attributes.shadowOffset.invalid</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.shadowOffsetX = 1;
+ctx.shadowOffsetY = 2;
+ctx.shadowOffsetX = Infinity;
+ctx.shadowOffsetY = Infinity;
+_assertSame(ctx.shadowOffsetX, 1, "ctx.shadowOffsetX", "1");
+_assertSame(ctx.shadowOffsetY, 2, "ctx.shadowOffsetY", "2");
+
+ctx.shadowOffsetX = 1;
+ctx.shadowOffsetY = 2;
+ctx.shadowOffsetX = -Infinity;
+ctx.shadowOffsetY = -Infinity;
+_assertSame(ctx.shadowOffsetX, 1, "ctx.shadowOffsetX", "1");
+_assertSame(ctx.shadowOffsetY, 2, "ctx.shadowOffsetY", "2");
+
+ctx.shadowOffsetX = 1;
+ctx.shadowOffsetY = 2;
+ctx.shadowOffsetX = NaN;
+ctx.shadowOffsetY = NaN;
+_assertSame(ctx.shadowOffsetX, 1, "ctx.shadowOffsetX", "1");
+_assertSame(ctx.shadowOffsetY, 2, "ctx.shadowOffsetY", "2");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.attributes.shadowOffset.valid.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.attributes.shadowOffset.valid.html
new file mode 100644
index 00000000000..4133ebb94eb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.attributes.shadowOffset.valid.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.attributes.shadowOffset.valid</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.attributes.shadowOffset.valid</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.shadowOffsetX = 1;
+ctx.shadowOffsetY = 2;
+_assertSame(ctx.shadowOffsetX, 1, "ctx.shadowOffsetX", "1");
+_assertSame(ctx.shadowOffsetY, 2, "ctx.shadowOffsetY", "2");
+
+ctx.shadowOffsetX = 0.5;
+ctx.shadowOffsetY = 0.25;
+_assertSame(ctx.shadowOffsetX, 0.5, "ctx.shadowOffsetX", "0.5");
+_assertSame(ctx.shadowOffsetY, 0.25, "ctx.shadowOffsetY", "0.25");
+
+ctx.shadowOffsetX = -0.5;
+ctx.shadowOffsetY = -0.25;
+_assertSame(ctx.shadowOffsetX, -0.5, "ctx.shadowOffsetX", "-0.5");
+_assertSame(ctx.shadowOffsetY, -0.25, "ctx.shadowOffsetY", "-0.25");
+
+ctx.shadowOffsetX = 0;
+ctx.shadowOffsetY = 0;
+_assertSame(ctx.shadowOffsetX, 0, "ctx.shadowOffsetX", "0");
+_assertSame(ctx.shadowOffsetY, 0, "ctx.shadowOffsetY", "0");
+
+ctx.shadowOffsetX = 1e6;
+ctx.shadowOffsetY = 1e6;
+_assertSame(ctx.shadowOffsetX, 1e6, "ctx.shadowOffsetX", "1e6");
+_assertSame(ctx.shadowOffsetY, 1e6, "ctx.shadowOffsetY", "1e6");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.blur.high-manual.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.blur.high-manual.html
new file mode 100644
index 00000000000..957f5b802d6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.blur.high-manual.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.blur.high</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.blur.high</h1>
+<p class="desc">Shadows look correct for large blurs</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.shadow.blur.high.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Shadows look correct for large blurs");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#ff0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.shadowColor = '#00f';
+ctx.shadowOffsetY = 0;
+ctx.shadowBlur = 100;
+ctx.fillRect(-200, -200, 200, 400);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.blur.high.png b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.blur.high.png
new file mode 100644
index 00000000000..743640b79f8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.blur.high.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.blur.low-manual.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.blur.low-manual.html
new file mode 100644
index 00000000000..548db5c5ea1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.blur.low-manual.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.blur.low</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.blur.low</h1>
+<p class="desc">Shadows look correct for small blurs</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.shadow.blur.low.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Shadows look correct for small blurs");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#ff0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.shadowColor = '#00f';
+ctx.shadowOffsetY = 25;
+for (var x = 0; x < 100; ++x) {
+ ctx.save();
+ ctx.beginPath();
+ ctx.rect(x, 0, 1, 50);
+ ctx.clip();
+ ctx.shadowBlur = x;
+ ctx.fillRect(-200, -200, 500, 200);
+ ctx.restore();
+}
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.blur.low.png b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.blur.low.png
new file mode 100644
index 00000000000..e1922ae79fe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.blur.low.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.canvas.alpha.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.canvas.alpha.html
new file mode 100644
index 00000000000..584703dff29
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.canvas.alpha.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.canvas.alpha</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.canvas.alpha</h1>
+<p class="desc">Shadows are drawn correctly for partially-transparent canvases</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.shadow.canvas.alpha.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Shadows are drawn correctly for partially-transparent canvases");
+_addTest(function(canvas, ctx) {
+
+var canvas2 = document.createElement('canvas');
+canvas2.width = 100;
+canvas2.height = 50;
+var ctx2 = canvas2.getContext('2d');
+ctx2.fillStyle = 'rgba(255, 0, 0, 0.5)';
+ctx2.fillRect(0, 0, 100, 50);
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.shadowOffsetY = 50;
+ctx.shadowColor = '#00f';
+ctx.drawImage(canvas2, 0, -50);
+
+_assertPixelApprox(canvas, 50,25, 127,0,127,255, "50,25", "127,0,127,255", 2);
+
+
+});
+</script>
+<img src="/images/transparent50.png" id="transparent50.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.canvas.alpha.png b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.canvas.alpha.png
new file mode 100644
index 00000000000..8764e89b371
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.canvas.alpha.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.canvas.basic.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.canvas.basic.html
new file mode 100644
index 00000000000..824c66894cc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.canvas.basic.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.canvas.basic</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.canvas.basic</h1>
+<p class="desc">Shadows are drawn for canvases</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Shadows are drawn for canvases");
+_addTest(function(canvas, ctx) {
+
+var canvas2 = document.createElement('canvas');
+canvas2.width = 100;
+canvas2.height = 50;
+var ctx2 = canvas2.getContext('2d');
+ctx2.fillStyle = '#f00';
+ctx2.fillRect(0, 0, 100, 50);
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.shadowColor = '#0f0';
+ctx.shadowOffsetY = 50;
+ctx.drawImage(canvas2, 0, -50);
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.canvas.transparent.1.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.canvas.transparent.1.html
new file mode 100644
index 00000000000..13ddd33e151
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.canvas.transparent.1.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.canvas.transparent.1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.canvas.transparent.1</h1>
+<p class="desc">Shadows are not drawn for transparent canvases</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Shadows are not drawn for transparent canvases");
+_addTest(function(canvas, ctx) {
+
+var canvas2 = document.createElement('canvas');
+canvas2.width = 100;
+canvas2.height = 50;
+var ctx2 = canvas2.getContext('2d');
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.shadowColor = '#f00';
+ctx.shadowOffsetY = 50;
+ctx.drawImage(canvas2, 0, -50);
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.canvas.transparent.2.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.canvas.transparent.2.html
new file mode 100644
index 00000000000..e795fa1e2da
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.canvas.transparent.2.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.canvas.transparent.2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.canvas.transparent.2</h1>
+<p class="desc">Shadows are not drawn for transparent parts of canvases</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Shadows are not drawn for transparent parts of canvases");
+_addTest(function(canvas, ctx) {
+
+var canvas2 = document.createElement('canvas');
+canvas2.width = 100;
+canvas2.height = 50;
+var ctx2 = canvas2.getContext('2d');
+ctx2.fillStyle = '#f00';
+ctx2.fillRect(0, 0, 50, 50);
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 50, 50);
+ctx.fillStyle = '#f00';
+ctx.fillRect(50, 0, 50, 50);
+ctx.shadowOffsetY = 50;
+ctx.shadowColor = '#0f0';
+ctx.drawImage(canvas2, 50, -50);
+ctx.shadowColor = '#f00';
+ctx.drawImage(canvas2, -50, -50);
+
+_assertPixel(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255");
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.clip.1.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.clip.1.html
new file mode 100644
index 00000000000..50fbb8711b1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.clip.1.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.clip.1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.clip.1</h1>
+<p class="desc">Shadows of clipped shapes are still drawn within the clipping region</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Shadows of clipped shapes are still drawn within the clipping region");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 50, 50);
+ctx.fillStyle = '#f00';
+ctx.fillRect(50, 0, 50, 50);
+
+ctx.save();
+ctx.beginPath();
+ctx.rect(50, 0, 50, 50);
+ctx.clip();
+ctx.shadowColor = '#0f0';
+ctx.shadowOffsetX = 50;
+ctx.fillRect(0, 0, 50, 50);
+ctx.restore();
+
+_assertPixel(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255");
+_assertPixel(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.clip.2.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.clip.2.html
new file mode 100644
index 00000000000..239b43b98ba
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.clip.2.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.clip.2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.clip.2</h1>
+<p class="desc">Shadows are not drawn outside the clipping region</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Shadows are not drawn outside the clipping region");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 50, 50);
+ctx.fillStyle = '#0f0';
+ctx.fillRect(50, 0, 50, 50);
+
+ctx.save();
+ctx.beginPath();
+ctx.rect(0, 0, 50, 50);
+ctx.clip();
+ctx.shadowColor = '#f00';
+ctx.shadowOffsetX = 50;
+ctx.fillRect(0, 0, 50, 50);
+ctx.restore();
+
+_assertPixel(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255");
+_assertPixel(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.clip.3.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.clip.3.html
new file mode 100644
index 00000000000..6b1bb02fcb5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.clip.3.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.clip.3</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.clip.3</h1>
+<p class="desc">Shadows of clipped shapes are still drawn within the clipping region</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Shadows of clipped shapes are still drawn within the clipping region");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 50, 50);
+ctx.fillStyle = '#0f0';
+ctx.fillRect(50, 0, 50, 50);
+
+ctx.save();
+ctx.beginPath();
+ctx.rect(0, 0, 50, 50);
+ctx.clip();
+ctx.fillStyle = '#f00';
+ctx.shadowColor = '#0f0';
+ctx.shadowOffsetX = 50;
+ctx.fillRect(-50, 0, 50, 50);
+ctx.restore();
+
+_assertPixel(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255");
+_assertPixel(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.composite.1.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.composite.1.html
new file mode 100644
index 00000000000..e27c1e2c07c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.composite.1.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.composite.1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.composite.1</h1>
+<p class="desc">Shadows are drawn using globalCompositeOperation</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Shadows are drawn using globalCompositeOperation");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'xor';
+ctx.shadowColor = '#f00';
+ctx.shadowOffsetX = 100;
+ctx.fillStyle = '#0f0';
+ctx.fillRect(-100, 0, 200, 50);
+
+_assertPixelApprox(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 2);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.composite.2.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.composite.2.html
new file mode 100644
index 00000000000..960b44b5419
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.composite.2.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.composite.2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.composite.2</h1>
+<p class="desc">Shadows are drawn using globalCompositeOperation</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Shadows are drawn using globalCompositeOperation");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'xor';
+ctx.shadowColor = '#f00';
+ctx.shadowBlur = 1;
+ctx.fillStyle = '#0f0';
+ctx.fillRect(-10, -10, 120, 70);
+
+_assertPixelApprox(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 2);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.composite.3.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.composite.3.html
new file mode 100644
index 00000000000..feee1ce5e8d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.composite.3.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.composite.3</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.composite.3</h1>
+<p class="desc">Areas outside shadows are drawn correctly with destination-out</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Areas outside shadows are drawn correctly with destination-out");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'destination-out';
+ctx.shadowColor = '#f00';
+ctx.shadowBlur = 10;
+ctx.fillStyle = '#f00';
+ctx.fillRect(200, 0, 100, 50);
+
+_assertPixelApprox(canvas, 5,5, 0,255,0,255, "5,5", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 2);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.enable.blur.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.enable.blur.html
new file mode 100644
index 00000000000..f94f5f69f51
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.enable.blur.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.enable.blur</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.enable.blur</h1>
+<p class="desc">Shadows are drawn if shadowBlur is set</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Shadows are drawn if shadowBlur is set");
+_addTest(function(canvas, ctx) {
+
+ctx.globalCompositeOperation = 'destination-atop';
+ctx.shadowColor = '#0f0';
+ctx.shadowBlur = 0.1;
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.enable.off.1.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.enable.off.1.html
new file mode 100644
index 00000000000..161ec52c4f8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.enable.off.1.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.enable.off.1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.enable.off.1</h1>
+<p class="desc">Shadows are not drawn when only shadowColor is set</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Shadows are not drawn when only shadowColor is set");
+_addTest(function(canvas, ctx) {
+
+ctx.shadowColor = '#f00';
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.enable.off.2.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.enable.off.2.html
new file mode 100644
index 00000000000..23bfa752afe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.enable.off.2.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.enable.off.2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.enable.off.2</h1>
+<p class="desc">Shadows are not drawn when only shadowColor is set</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Shadows are not drawn when only shadowColor is set");
+_addTest(function(canvas, ctx) {
+
+ctx.globalCompositeOperation = 'destination-atop';
+ctx.shadowColor = '#f00';
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.enable.x.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.enable.x.html
new file mode 100644
index 00000000000..b90da98dfab
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.enable.x.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.enable.x</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.enable.x</h1>
+<p class="desc">Shadows are drawn if shadowOffsetX is set</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Shadows are drawn if shadowOffsetX is set");
+_addTest(function(canvas, ctx) {
+
+ctx.globalCompositeOperation = 'destination-atop';
+ctx.shadowColor = '#0f0';
+ctx.shadowOffsetX = 0.1;
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.enable.y.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.enable.y.html
new file mode 100644
index 00000000000..32750e6f869
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.enable.y.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.enable.y</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.enable.y</h1>
+<p class="desc">Shadows are drawn if shadowOffsetY is set</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Shadows are drawn if shadowOffsetY is set");
+_addTest(function(canvas, ctx) {
+
+ctx.globalCompositeOperation = 'destination-atop';
+ctx.shadowColor = '#0f0';
+ctx.shadowOffsetY = 0.1;
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.gradient.alpha.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.gradient.alpha.html
new file mode 100644
index 00000000000..31c4adc50d2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.gradient.alpha.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.gradient.alpha</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.gradient.alpha</h1>
+<p class="desc">Shadows are drawn correctly for partially-transparent gradient fills</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.shadow.gradient.alpha.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Shadows are drawn correctly for partially-transparent gradient fills");
+_addTest(function(canvas, ctx) {
+
+var gradient = ctx.createLinearGradient(0, 0, 100, 0);
+gradient.addColorStop(0, 'rgba(255,0,0,0.5)');
+gradient.addColorStop(1, 'rgba(255,0,0,0.5)');
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.shadowOffsetY = 50;
+ctx.shadowColor = '#00f';
+ctx.fillStyle = gradient;
+ctx.fillRect(0, -50, 100, 50);
+
+_assertPixelApprox(canvas, 50,25, 127,0,127,255, "50,25", "127,0,127,255", 2);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.gradient.alpha.png b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.gradient.alpha.png
new file mode 100644
index 00000000000..8764e89b371
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.gradient.alpha.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.gradient.basic.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.gradient.basic.html
new file mode 100644
index 00000000000..cdb2232322f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.gradient.basic.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.gradient.basic</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.gradient.basic</h1>
+<p class="desc">Shadows are drawn for gradient fills</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Shadows are drawn for gradient fills");
+_addTest(function(canvas, ctx) {
+
+var gradient = ctx.createLinearGradient(0, 0, 100, 0);
+gradient.addColorStop(0, '#f00');
+gradient.addColorStop(1, '#f00');
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.shadowColor = '#0f0';
+ctx.shadowOffsetY = 50;
+ctx.fillStyle = gradient;
+ctx.fillRect(0, -50, 100, 50);
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.gradient.transparent.1.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.gradient.transparent.1.html
new file mode 100644
index 00000000000..d4a21c6b385
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.gradient.transparent.1.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.gradient.transparent.1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.gradient.transparent.1</h1>
+<p class="desc">Shadows are not drawn for transparent gradient fills</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Shadows are not drawn for transparent gradient fills");
+_addTest(function(canvas, ctx) {
+
+var gradient = ctx.createLinearGradient(0, 0, 100, 0);
+gradient.addColorStop(0, 'rgba(0,0,0,0)');
+gradient.addColorStop(1, 'rgba(0,0,0,0)');
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.shadowColor = '#f00';
+ctx.shadowOffsetY = 50;
+ctx.fillStyle = gradient;
+ctx.fillRect(0, -50, 100, 50);
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.gradient.transparent.2.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.gradient.transparent.2.html
new file mode 100644
index 00000000000..be5d93a5b23
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.gradient.transparent.2.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.gradient.transparent.2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.gradient.transparent.2</h1>
+<p class="desc">Shadows are not drawn for transparent parts of gradient fills</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Shadows are not drawn for transparent parts of gradient fills");
+_addTest(function(canvas, ctx) {
+
+var gradient = ctx.createLinearGradient(0, 0, 100, 0);
+gradient.addColorStop(0, '#f00');
+gradient.addColorStop(0.499, '#f00');
+gradient.addColorStop(0.5, 'rgba(0,0,0,0)');
+gradient.addColorStop(1, 'rgba(0,0,0,0)');
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 50, 50);
+ctx.fillStyle = '#0f0';
+ctx.fillRect(50, 0, 50, 50);
+ctx.shadowOffsetY = 50;
+ctx.shadowColor = '#0f0';
+ctx.fillStyle = gradient;
+ctx.fillRect(0, -50, 100, 50);
+
+_assertPixel(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255");
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.image.alpha.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.image.alpha.html
new file mode 100644
index 00000000000..9e7a5697306
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.image.alpha.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.image.alpha</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.image.alpha</h1>
+<p class="desc">Shadows are drawn correctly for partially-transparent images</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.shadow.image.alpha.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Shadows are drawn correctly for partially-transparent images");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.shadowOffsetY = 50;
+ctx.shadowColor = '#00f';
+ctx.drawImage(document.getElementById('transparent50.png'), 0, -50);
+
+_assertPixelApprox(canvas, 50,25, 127,0,127,255, "50,25", "127,0,127,255", 2);
+
+
+});
+</script>
+<img src="/images/transparent50.png" id="transparent50.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.image.alpha.png b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.image.alpha.png
new file mode 100644
index 00000000000..8764e89b371
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.image.alpha.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.image.basic.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.image.basic.html
new file mode 100644
index 00000000000..570451ae9df
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.image.basic.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.image.basic</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.image.basic</h1>
+<p class="desc">Shadows are drawn for images</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Shadows are drawn for images");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.shadowColor = '#0f0';
+ctx.shadowOffsetY = 50;
+ctx.drawImage(document.getElementById('red.png'), 0, -50);
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+<img src="/images/red.png" id="red.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.image.scale.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.image.scale.html
new file mode 100644
index 00000000000..ded6fc0d6b9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.image.scale.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.image.scale</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.image.scale</h1>
+<p class="desc">Shadows are drawn correctly for scaled images</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Shadows are drawn correctly for scaled images");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.shadowOffsetY = 50;
+ctx.shadowColor = '#0f0';
+ctx.drawImage(document.getElementById('redtransparent.png'), 0, 0, 100, 50, -10, -50, 240, 50);
+
+_assertPixelApprox(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255", 2);
+
+
+});
+</script>
+<img src="/images/redtransparent.png" id="redtransparent.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.image.section.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.image.section.html
new file mode 100644
index 00000000000..9dc9bca6723
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.image.section.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.image.section</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.image.section</h1>
+<p class="desc">Shadows are not drawn for areas outside image source rectangles</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Shadows are not drawn for areas outside image source rectangles");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.shadowOffsetY = 50;
+ctx.shadowColor = '#f00';
+ctx.drawImage(document.getElementById('redtransparent.png'), 50, 0, 50, 50, 0, -50, 50, 50);
+
+_assertPixelApprox(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255", 2);
+_assertPixelApprox(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255", 2);
+
+
+});
+</script>
+<img src="/images/redtransparent.png" id="redtransparent.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.image.transparent.1.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.image.transparent.1.html
new file mode 100644
index 00000000000..13dff1f2d4c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.image.transparent.1.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.image.transparent.1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.image.transparent.1</h1>
+<p class="desc">Shadows are not drawn for transparent images</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Shadows are not drawn for transparent images");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.shadowColor = '#f00';
+ctx.shadowOffsetY = 50;
+ctx.drawImage(document.getElementById('transparent.png'), 0, -50);
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+<img src="/images/transparent.png" id="transparent.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.image.transparent.2.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.image.transparent.2.html
new file mode 100644
index 00000000000..17a26407d5a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.image.transparent.2.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.image.transparent.2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.image.transparent.2</h1>
+<p class="desc">Shadows are not drawn for transparent parts of images</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Shadows are not drawn for transparent parts of images");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 50, 50);
+ctx.fillStyle = '#f00';
+ctx.fillRect(50, 0, 50, 50);
+ctx.shadowOffsetY = 50;
+ctx.shadowColor = '#0f0';
+ctx.drawImage(document.getElementById('redtransparent.png'), 50, -50);
+ctx.shadowColor = '#f00';
+ctx.drawImage(document.getElementById('redtransparent.png'), -50, -50);
+
+_assertPixel(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255");
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255");
+
+
+});
+</script>
+<img src="/images/redtransparent.png" id="redtransparent.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.offset.negativeX.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.offset.negativeX.html
new file mode 100644
index 00000000000..da1c39ba0e2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.offset.negativeX.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.offset.negativeX</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.offset.negativeX</h1>
+<p class="desc">Shadows can be offset with negative x</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Shadows can be offset with negative x");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.fillStyle = '#0f0';
+ctx.shadowColor = '#0f0';
+ctx.shadowOffsetX = -50;
+ctx.fillRect(50, 0, 50, 50);
+_assertPixel(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255");
+_assertPixel(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.offset.negativeY.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.offset.negativeY.html
new file mode 100644
index 00000000000..0f7a7f0ad3e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.offset.negativeY.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.offset.negativeY</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.offset.negativeY</h1>
+<p class="desc">Shadows can be offset with negative y</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Shadows can be offset with negative y");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.fillStyle = '#0f0';
+ctx.shadowColor = '#0f0';
+ctx.shadowOffsetY = -25;
+ctx.fillRect(0, 25, 100, 25);
+_assertPixel(canvas, 50,12, 0,255,0,255, "50,12", "0,255,0,255");
+_assertPixel(canvas, 50,37, 0,255,0,255, "50,37", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.offset.positiveX.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.offset.positiveX.html
new file mode 100644
index 00000000000..969d9b43a8d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.offset.positiveX.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.offset.positiveX</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.offset.positiveX</h1>
+<p class="desc">Shadows can be offset with positive x</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Shadows can be offset with positive x");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.fillStyle = '#0f0';
+ctx.shadowColor = '#0f0';
+ctx.shadowOffsetX = 50;
+ctx.fillRect(0, 0, 50, 50);
+_assertPixel(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255");
+_assertPixel(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.offset.positiveY.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.offset.positiveY.html
new file mode 100644
index 00000000000..c797d709f00
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.offset.positiveY.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.offset.positiveY</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.offset.positiveY</h1>
+<p class="desc">Shadows can be offset with positive y</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Shadows can be offset with positive y");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.fillStyle = '#0f0';
+ctx.shadowColor = '#0f0';
+ctx.shadowOffsetY = 25;
+ctx.fillRect(0, 0, 100, 25);
+_assertPixel(canvas, 50,12, 0,255,0,255, "50,12", "0,255,0,255");
+_assertPixel(canvas, 50,37, 0,255,0,255, "50,37", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.outside.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.outside.html
new file mode 100644
index 00000000000..ef3492226e6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.outside.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.outside</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.outside</h1>
+<p class="desc">Shadows of shapes outside the visible area can be offset onto the visible area</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Shadows of shapes outside the visible area can be offset onto the visible area");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.shadowColor = '#0f0';
+ctx.shadowOffsetX = 100;
+ctx.fillRect(-100, 0, 25, 50);
+ctx.shadowOffsetX = -100;
+ctx.fillRect(175, 0, 25, 50);
+ctx.shadowOffsetX = 0;
+ctx.shadowOffsetY = 100;
+ctx.fillRect(25, -100, 50, 25);
+ctx.shadowOffsetY = -100;
+ctx.fillRect(25, 125, 50, 25);
+_assertPixel(canvas, 12,25, 0,255,0,255, "12,25", "0,255,0,255");
+_assertPixel(canvas, 87,25, 0,255,0,255, "87,25", "0,255,0,255");
+_assertPixel(canvas, 50,12, 0,255,0,255, "50,12", "0,255,0,255");
+_assertPixel(canvas, 50,37, 0,255,0,255, "50,37", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.pattern.alpha.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.pattern.alpha.html
new file mode 100644
index 00000000000..5fcfcc4b038
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.pattern.alpha.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.pattern.alpha</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.pattern.alpha</h1>
+<p class="desc">Shadows are drawn correctly for partially-transparent fill patterns</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.shadow.pattern.alpha.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Shadows are drawn correctly for partially-transparent fill patterns");
+_addTest(function(canvas, ctx) {
+
+var pattern = ctx.createPattern(document.getElementById('transparent50.png'), 'repeat');
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.shadowOffsetY = 50;
+ctx.shadowColor = '#00f';
+ctx.fillStyle = pattern;
+ctx.fillRect(0, -50, 100, 50);
+
+_assertPixelApprox(canvas, 50,25, 127,0,127,255, "50,25", "127,0,127,255", 2);
+
+
+});
+</script>
+<img src="/images/transparent50.png" id="transparent50.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.pattern.alpha.png b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.pattern.alpha.png
new file mode 100644
index 00000000000..8764e89b371
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.pattern.alpha.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.pattern.basic.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.pattern.basic.html
new file mode 100644
index 00000000000..38b9a736712
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.pattern.basic.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.pattern.basic</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.pattern.basic</h1>
+<p class="desc">Shadows are drawn for fill patterns</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Shadows are drawn for fill patterns");
+_addTest(function(canvas, ctx) {
+
+var pattern = ctx.createPattern(document.getElementById('red.png'), 'repeat');
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.shadowColor = '#0f0';
+ctx.shadowOffsetY = 50;
+ctx.fillStyle = pattern;
+ctx.fillRect(0, -50, 100, 50);
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+<img src="/images/red.png" id="red.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.pattern.transparent.1.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.pattern.transparent.1.html
new file mode 100644
index 00000000000..fcdda5a2044
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.pattern.transparent.1.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.pattern.transparent.1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.pattern.transparent.1</h1>
+<p class="desc">Shadows are not drawn for transparent fill patterns</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Shadows are not drawn for transparent fill patterns");
+_addTest(function(canvas, ctx) {
+
+var pattern = ctx.createPattern(document.getElementById('transparent.png'), 'repeat');
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.shadowColor = '#f00';
+ctx.shadowOffsetY = 50;
+ctx.fillStyle = pattern;
+ctx.fillRect(0, -50, 100, 50);
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+<img src="/images/transparent.png" id="transparent.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.pattern.transparent.2.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.pattern.transparent.2.html
new file mode 100644
index 00000000000..3dbb856bf7f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.pattern.transparent.2.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.pattern.transparent.2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.pattern.transparent.2</h1>
+<p class="desc">Shadows are not drawn for transparent parts of fill patterns</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Shadows are not drawn for transparent parts of fill patterns");
+_addTest(function(canvas, ctx) {
+
+var pattern = ctx.createPattern(document.getElementById('redtransparent.png'), 'repeat');
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 50, 50);
+ctx.fillStyle = '#0f0';
+ctx.fillRect(50, 0, 50, 50);
+ctx.shadowOffsetY = 50;
+ctx.shadowColor = '#0f0';
+ctx.fillStyle = pattern;
+ctx.fillRect(0, -50, 100, 50);
+
+_assertPixel(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255");
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255");
+
+
+});
+</script>
+<img src="/images/redtransparent.png" id="redtransparent.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.stroke.basic.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.stroke.basic.html
new file mode 100644
index 00000000000..4e5bd06b2bd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.stroke.basic.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.stroke.basic</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.stroke.basic</h1>
+<p class="desc">Shadows are drawn for strokes</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Shadows are drawn for strokes");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.strokeStyle = '#f00';
+ctx.shadowColor = '#0f0';
+ctx.shadowOffsetY = 50;
+ctx.beginPath();
+ctx.lineWidth = 50;
+ctx.moveTo(0, -25);
+ctx.lineTo(100, -25);
+ctx.stroke();
+
+_assertPixel(canvas, 1,25, 0,255,0,255, "1,25", "0,255,0,255");
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 98,25, 0,255,0,255, "98,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.stroke.cap.1.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.stroke.cap.1.html
new file mode 100644
index 00000000000..04450b97909
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.stroke.cap.1.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.stroke.cap.1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.stroke.cap.1</h1>
+<p class="desc">Shadows are not drawn for areas outside stroke caps</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Shadows are not drawn for areas outside stroke caps");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.strokeStyle = '#f00';
+ctx.shadowColor = '#f00';
+ctx.shadowOffsetY = 50;
+ctx.beginPath();
+ctx.lineWidth = 50;
+ctx.lineCap = 'butt';
+ctx.moveTo(-50, -25);
+ctx.lineTo(0, -25);
+ctx.moveTo(100, -25);
+ctx.lineTo(150, -25);
+ctx.stroke();
+
+_assertPixel(canvas, 1,25, 0,255,0,255, "1,25", "0,255,0,255");
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 98,25, 0,255,0,255, "98,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.stroke.cap.2.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.stroke.cap.2.html
new file mode 100644
index 00000000000..11a7cf3cfe2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.stroke.cap.2.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.stroke.cap.2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.stroke.cap.2</h1>
+<p class="desc">Shadows are drawn for stroke caps</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Shadows are drawn for stroke caps");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.strokeStyle = '#f00';
+ctx.shadowColor = '#0f0';
+ctx.shadowOffsetY = 50;
+ctx.beginPath();
+ctx.lineWidth = 50;
+ctx.lineCap = 'square';
+ctx.moveTo(25, -25);
+ctx.lineTo(75, -25);
+ctx.stroke();
+
+_assertPixel(canvas, 1,25, 0,255,0,255, "1,25", "0,255,0,255");
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 98,25, 0,255,0,255, "98,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.stroke.join.1.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.stroke.join.1.html
new file mode 100644
index 00000000000..d204874d70b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.stroke.join.1.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.stroke.join.1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.stroke.join.1</h1>
+<p class="desc">Shadows are not drawn for areas outside stroke joins</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Shadows are not drawn for areas outside stroke joins");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.strokeStyle = '#f00';
+ctx.shadowColor = '#f00';
+ctx.shadowOffsetX = 100;
+ctx.lineWidth = 200;
+ctx.lineJoin = 'bevel';
+ctx.beginPath();
+ctx.moveTo(-200, -50);
+ctx.lineTo(-150, -50);
+ctx.lineTo(-151, -100);
+ctx.stroke();
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 48,48, 0,255,0,255, "48,48", "0,255,0,255");
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.stroke.join.2.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.stroke.join.2.html
new file mode 100644
index 00000000000..ccff894fd49
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.stroke.join.2.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.stroke.join.2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.stroke.join.2</h1>
+<p class="desc">Shadows are drawn for stroke joins</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Shadows are drawn for stroke joins");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 50, 50);
+ctx.fillStyle = '#0f0';
+ctx.fillRect(50, 0, 50, 50);
+ctx.strokeStyle = '#f00';
+ctx.shadowColor = '#0f0';
+ctx.shadowOffsetX = 100;
+ctx.lineWidth = 200;
+ctx.lineJoin = 'miter';
+ctx.beginPath();
+ctx.moveTo(-200, -50);
+ctx.lineTo(-150, -50);
+ctx.lineTo(-151, -100);
+ctx.stroke();
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 48,48, 0,255,0,255, "48,48", "0,255,0,255");
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.stroke.join.3.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.stroke.join.3.html
new file mode 100644
index 00000000000..25044ebfced
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.stroke.join.3.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.stroke.join.3</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.stroke.join.3</h1>
+<p class="desc">Shadows are drawn for stroke joins respecting miter limit</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Shadows are drawn for stroke joins respecting miter limit");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.strokeStyle = '#f00';
+ctx.shadowColor = '#f00';
+ctx.shadowOffsetX = 100;
+ctx.lineWidth = 200;
+ctx.lineJoin = 'miter';
+ctx.miterLimit = 0.1;
+ctx.beginPath();
+ctx.moveTo(-200, -50);
+ctx.lineTo(-150, -50);
+ctx.lineTo(-151, -100); // (not an exact right angle, to avoid some other bug in Firefox 3)
+ctx.stroke();
+
+_assertPixel(canvas, 1,1, 0,255,0,255, "1,1", "0,255,0,255");
+_assertPixel(canvas, 48,48, 0,255,0,255, "48,48", "0,255,0,255");
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 98,48, 0,255,0,255, "98,48", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.transform.1.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.transform.1.html
new file mode 100644
index 00000000000..03a4ab2e466
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.transform.1.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.transform.1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.transform.1</h1>
+<p class="desc">Shadows take account of transformations</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Shadows take account of transformations");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.shadowOffsetY = 50;
+ctx.shadowColor = '#0f0';
+ctx.translate(100, 100);
+ctx.fillRect(-100, -150, 100, 50);
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.transform.2.html b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.transform.2.html
new file mode 100644
index 00000000000..8e1ac095b97
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/2d.shadow.transform.2.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.shadow.transform.2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.shadow.transform.2</h1>
+<p class="desc">Shadow offsets are not affected by transformations</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Shadow offsets are not affected by transformations");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.shadowOffsetY = 50;
+ctx.shadowColor = '#0f0';
+ctx.rotate(Math.PI)
+ctx.fillRect(-100, 0, 100, 50);
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/canvas_shadows_001.htm b/tests/wpt/web-platform-tests/2dcontext/shadows/canvas_shadows_001.htm
new file mode 100644
index 00000000000..fd7c7d086e3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/canvas_shadows_001.htm
@@ -0,0 +1,36 @@
+<!doctype HTML>
+<html>
+ <head>
+ <title>HTML5 Canvas Test: Shadows for linear gradients</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com" />
+ <link rel="help" href="http://www.w3.org/TR/2dcontext/#shadows" />
+ <meta name="assert" content="Shadows must be drawn for linear gradients." />
+ <script type="text/javascript">
+ function runTest()
+ {
+ var canvas = document.getElementById("canvas1");
+ var ctx = canvas.getContext("2d");
+
+ // Draw a red rectangle.
+ ctx.fillStyle = "rgba(255, 0, 0, 1.0)";
+ ctx.fillRect(150, 0, 100, 50);
+
+ // Set shadow styles to draw a black shadow to overlap the red rectangle.
+ ctx.shadowOffsetX = 150;
+ ctx.shadowColor = "rgba(0, 0, 0, 1.0)";
+
+ // Draw a left to right, green-to-blue linear gradient.
+ var lingrad = ctx.createLinearGradient(0, 50, 100, 50);
+ lingrad.addColorStop(0, "rgba(0, 255, 0, 1.0)");
+ lingrad.addColorStop(1, "rgba(0, 0, 255, 1.0)");
+ ctx.fillStyle = lingrad;
+ ctx.fillRect(0, 0, 100, 50);
+ }
+ </script>
+ </head>
+ <body onload="runTest()">
+ <p>Description: Shadows must be drawn for linear gradients.</p>
+ <p>Test passes if there is one gradient filled rectangle and one black rectangle, and no red seen on the page.</p>
+ <canvas id="canvas1" width="300" height="150">Browser does not support HTML5 Canvas.</canvas>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/canvas_shadows_002-ref.htm b/tests/wpt/web-platform-tests/2dcontext/shadows/canvas_shadows_002-ref.htm
new file mode 100644
index 00000000000..7f39d1ca1b0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/canvas_shadows_002-ref.htm
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>HTML5 Canvas Test: Shadows for images</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com" />
+ <link rel="help" href="http://www.w3.org/TR/2dcontext/#shadows" />
+ <link rel="match" href="canvas_shadows_002-ref.htm" />
+ <meta name="assert" content="Shadows must be drawn for images." />
+ <script type="text/javascript">
+ function runTest() {
+ var canvas = document.getElementById("canvas1");
+ var ctx = canvas.getContext("2d");
+
+ // Draw a black rectangle image on the canvas.
+ var img = document.getElementById("imgBlackRect");
+ ctx.drawImage(img, 0, 0);
+ ctx.drawImage(img, 150, 0);
+ }
+ </script>
+
+ </head>
+ <body onload="runTest()">
+ <p>Description: Shadows must be drawn for images.</p>
+ <p>Test passes if two black rectangles are shown and there is no red visible on the page.</p>
+ <canvas id="canvas1" width="300" height="150">Browser does not support HTML5 Canvas.</canvas>
+ <img id="imgBlackRect" style="display:none;" width="100" height="50" src="/images/black-rectangle.png">
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/2dcontext/shadows/canvas_shadows_002.htm b/tests/wpt/web-platform-tests/2dcontext/shadows/canvas_shadows_002.htm
new file mode 100644
index 00000000000..908fffea13b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/shadows/canvas_shadows_002.htm
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>HTML5 Canvas Test: Shadows for images</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com" />
+ <link rel="help" href="http://www.w3.org/TR/2dcontext/#shadows" />
+ <link rel="match" href="canvas_shadows_002-ref.htm" />
+ <meta name="assert" content="Shadows must be drawn for images." />
+ <script type="text/javascript">
+ function runTest() {
+ var canvas = document.getElementById("canvas1");
+ var ctx = canvas.getContext("2d");
+
+ // Draw a red rectangle.
+ ctx.fillStyle = "rgba(255, 0, 0, 1.0)";
+ ctx.fillRect(150, 0, 100, 50);
+
+ // Set shadow styles to draw a black shadow to overlap the red rectangle.
+ ctx.shadowOffsetX = 150;
+ ctx.shadowColor = "rgba(0, 0, 0, 1.0)";
+
+ // Draw a black rectangle image on the canvas.
+ var img = document.getElementById("imgBlackRect");
+ ctx.drawImage(img, 0, 0);
+ }
+ </script>
+ </head>
+ <body onload="runTest()">
+ <p>Description: Shadows must be drawn for images.</p>
+ <p>Test passes if two black rectangles are shown and there is no red visible on the page.</p>
+ <canvas id="canvas1" width="300" height="150">Browser does not support HTML5 Canvas.</canvas>
+ <img id="imgBlackRect" style="display:none" width="100" height="50" src="/images/black-rectangle.png">
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/2dcontext/text-styles/.gitkeep b/tests/wpt/web-platform-tests/2dcontext/text-styles/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/text-styles/.gitkeep
diff --git a/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.align.default.html b/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.align.default.html
new file mode 100644
index 00000000000..6c3b5016aa3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.align.default.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.text.align.default</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.text.align.default</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+_assertSame(ctx.textAlign, 'start', "ctx.textAlign", "'start'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.align.invalid.html b/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.align.invalid.html
new file mode 100644
index 00000000000..36d3aaaf4ef
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.align.invalid.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.text.align.invalid</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.text.align.invalid</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.textAlign = 'start';
+ctx.textAlign = 'bogus';
+_assertSame(ctx.textAlign, 'start', "ctx.textAlign", "'start'");
+
+ctx.textAlign = 'start';
+ctx.textAlign = 'END';
+_assertSame(ctx.textAlign, 'start', "ctx.textAlign", "'start'");
+
+ctx.textAlign = 'start';
+ctx.textAlign = 'end ';
+_assertSame(ctx.textAlign, 'start', "ctx.textAlign", "'start'");
+
+ctx.textAlign = 'start';
+ctx.textAlign = 'end\0';
+_assertSame(ctx.textAlign, 'start', "ctx.textAlign", "'start'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.align.valid.html b/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.align.valid.html
new file mode 100644
index 00000000000..667f1bb0b69
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.align.valid.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.text.align.valid</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.text.align.valid</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.textAlign = 'start';
+_assertSame(ctx.textAlign, 'start', "ctx.textAlign", "'start'");
+
+ctx.textAlign = 'end';
+_assertSame(ctx.textAlign, 'end', "ctx.textAlign", "'end'");
+
+ctx.textAlign = 'left';
+_assertSame(ctx.textAlign, 'left', "ctx.textAlign", "'left'");
+
+ctx.textAlign = 'right';
+_assertSame(ctx.textAlign, 'right', "ctx.textAlign", "'right'");
+
+ctx.textAlign = 'center';
+_assertSame(ctx.textAlign, 'center', "ctx.textAlign", "'center'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.baseline.default.html b/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.baseline.default.html
new file mode 100644
index 00000000000..b19bcc37e71
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.baseline.default.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.text.baseline.default</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.text.baseline.default</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+_assertSame(ctx.textBaseline, 'alphabetic', "ctx.textBaseline", "'alphabetic'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.baseline.invalid.html b/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.baseline.invalid.html
new file mode 100644
index 00000000000..4cba62a14df
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.baseline.invalid.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.text.baseline.invalid</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.text.baseline.invalid</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.textBaseline = 'top';
+ctx.textBaseline = 'bogus';
+_assertSame(ctx.textBaseline, 'top', "ctx.textBaseline", "'top'");
+
+ctx.textBaseline = 'top';
+ctx.textBaseline = 'MIDDLE';
+_assertSame(ctx.textBaseline, 'top', "ctx.textBaseline", "'top'");
+
+ctx.textBaseline = 'top';
+ctx.textBaseline = 'middle ';
+_assertSame(ctx.textBaseline, 'top', "ctx.textBaseline", "'top'");
+
+ctx.textBaseline = 'top';
+ctx.textBaseline = 'middle\0';
+_assertSame(ctx.textBaseline, 'top', "ctx.textBaseline", "'top'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.baseline.valid.html b/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.baseline.valid.html
new file mode 100644
index 00000000000..e2a37b4ed09
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.baseline.valid.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.text.baseline.valid</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.text.baseline.valid</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.textBaseline = 'top';
+_assertSame(ctx.textBaseline, 'top', "ctx.textBaseline", "'top'");
+
+ctx.textBaseline = 'hanging';
+_assertSame(ctx.textBaseline, 'hanging', "ctx.textBaseline", "'hanging'");
+
+ctx.textBaseline = 'middle';
+_assertSame(ctx.textBaseline, 'middle', "ctx.textBaseline", "'middle'");
+
+ctx.textBaseline = 'alphabetic';
+_assertSame(ctx.textBaseline, 'alphabetic', "ctx.textBaseline", "'alphabetic'");
+
+ctx.textBaseline = 'ideographic';
+_assertSame(ctx.textBaseline, 'ideographic', "ctx.textBaseline", "'ideographic'");
+
+ctx.textBaseline = 'bottom';
+_assertSame(ctx.textBaseline, 'bottom', "ctx.textBaseline", "'bottom'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.draw.baseline.bottom.html b/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.draw.baseline.bottom.html
new file mode 100644
index 00000000000..cde7e891d6f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.draw.baseline.bottom.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.text.draw.baseline.bottom</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<style>
+@font-face {
+ font-family: CanvasTest;
+ src: url("/fonts/CanvasTest.ttf");
+}
+</style>
+<body class="show_output">
+
+<h1>2d.text.draw.baseline.bottom</h1>
+<p class="desc">textBaseline bottom is the bottom of the em square (not the bounding box)</p>
+
+
+<span style="font-family: CanvasTest; position: absolute; visibility: hidden">A</span>
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("textBaseline bottom is the bottom of the em square (not the bounding box)");
+_addTest(function(canvas, ctx) {
+
+ctx.font = '50px CanvasTest';
+deferTest();
+setTimeout(t.step_func_done(function () {
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.textBaseline = 'bottom';
+ ctx.fillText('CC', 0, 50);
+ _assertPixelApprox(canvas, 5,5, 0,255,0,255, "5,5", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 95,5, 0,255,0,255, "95,5", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 5,45, 0,255,0,255, "5,45", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 95,45, 0,255,0,255, "95,45", "0,255,0,255", 2);
+}), 500);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.draw.baseline.hanging.html b/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.draw.baseline.hanging.html
new file mode 100644
index 00000000000..e5bdb98cc52
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.draw.baseline.hanging.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.text.draw.baseline.hanging</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<style>
+@font-face {
+ font-family: CanvasTest;
+ src: url("/fonts/CanvasTest.ttf");
+}
+</style>
+<body class="show_output">
+
+<h1>2d.text.draw.baseline.hanging</h1>
+<p class="desc"></p>
+
+
+<span style="font-family: CanvasTest; position: absolute; visibility: hidden">A</span>
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.font = '50px CanvasTest';
+deferTest();
+setTimeout(t.step_func_done(function () {
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.textBaseline = 'hanging';
+ ctx.fillText('CC', 0, 12.5);
+ _assertPixelApprox(canvas, 5,5, 0,255,0,255, "5,5", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 95,5, 0,255,0,255, "95,5", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 5,45, 0,255,0,255, "5,45", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 95,45, 0,255,0,255, "95,45", "0,255,0,255", 2);
+}), 500);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.draw.baseline.ideographic.html b/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.draw.baseline.ideographic.html
new file mode 100644
index 00000000000..cc99e1ab437
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.draw.baseline.ideographic.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.text.draw.baseline.ideographic</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<style>
+@font-face {
+ font-family: CanvasTest;
+ src: url("/fonts/CanvasTest.ttf");
+}
+</style>
+<body class="show_output">
+
+<h1>2d.text.draw.baseline.ideographic</h1>
+<p class="desc"></p>
+
+
+<span style="font-family: CanvasTest; position: absolute; visibility: hidden">A</span>
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.font = '50px CanvasTest';
+deferTest();
+setTimeout(t.step_func_done(function () {
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.textBaseline = 'ideographic';
+ ctx.fillText('CC', 0, 31.25);
+ _assertPixelApprox(canvas, 5,5, 0,255,0,255, "5,5", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 95,5, 0,255,0,255, "95,5", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 5,45, 0,255,0,255, "5,45", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 95,45, 0,255,0,255, "95,45", "0,255,0,255", 2);
+}), 500);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.draw.baseline.middle.html b/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.draw.baseline.middle.html
new file mode 100644
index 00000000000..6cdbb17e657
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.draw.baseline.middle.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.text.draw.baseline.middle</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<style>
+@font-face {
+ font-family: CanvasTest;
+ src: url("/fonts/CanvasTest.ttf");
+}
+</style>
+<body class="show_output">
+
+<h1>2d.text.draw.baseline.middle</h1>
+<p class="desc">textBaseline middle is the middle of the em square (not the bounding box)</p>
+
+
+<span style="font-family: CanvasTest; position: absolute; visibility: hidden">A</span>
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("textBaseline middle is the middle of the em square (not the bounding box)");
+_addTest(function(canvas, ctx) {
+
+ctx.font = '50px CanvasTest';
+deferTest();
+setTimeout(t.step_func_done(function () {
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.textBaseline = 'middle';
+ ctx.fillText('CC', 0, 25);
+ _assertPixelApprox(canvas, 5,5, 0,255,0,255, "5,5", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 95,5, 0,255,0,255, "95,5", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 5,45, 0,255,0,255, "5,45", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 95,45, 0,255,0,255, "95,45", "0,255,0,255", 2);
+}), 500);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.draw.baseline.top.html b/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.draw.baseline.top.html
new file mode 100644
index 00000000000..15c0c1f3867
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.draw.baseline.top.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.text.draw.baseline.top</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<style>
+@font-face {
+ font-family: CanvasTest;
+ src: url("/fonts/CanvasTest.ttf");
+}
+</style>
+<body class="show_output">
+
+<h1>2d.text.draw.baseline.top</h1>
+<p class="desc">textBaseline top is the top of the em square (not the bounding box)</p>
+
+
+<span style="font-family: CanvasTest; position: absolute; visibility: hidden">A</span>
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("textBaseline top is the top of the em square (not the bounding box)");
+_addTest(function(canvas, ctx) {
+
+ctx.font = '50px CanvasTest';
+deferTest();
+setTimeout(t.step_func_done(function () {
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.textBaseline = 'top';
+ ctx.fillText('CC', 0, 0);
+ _assertPixelApprox(canvas, 5,5, 0,255,0,255, "5,5", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 95,5, 0,255,0,255, "95,5", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 5,45, 0,255,0,255, "5,45", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 95,45, 0,255,0,255, "95,45", "0,255,0,255", 2);
+}), 500);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.draw.space.collapse.end.html b/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.draw.space.collapse.end.html
new file mode 100644
index 00000000000..9ce607000da
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.draw.space.collapse.end.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.text.draw.space.collapse.end</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<style>
+@font-face {
+ font-family: CanvasTest;
+ src: url("/fonts/CanvasTest.ttf");
+}
+</style>
+<body class="show_output">
+
+<h1>2d.text.draw.space.collapse.end</h1>
+<p class="desc">Space characters at the end of a line are collapsed (per CSS)</p>
+
+
+<span style="font-family: CanvasTest; position: absolute; visibility: hidden">A</span>
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Space characters at the end of a line are collapsed (per CSS)");
+_addTest(function(canvas, ctx) {
+
+ctx.font = '50px CanvasTest';
+deferTest();
+setTimeout(t.step_func_done(function () {
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.textAlign = 'right';
+ ctx.fillText('EE ', 100, 37.5);
+ _assertPixelApprox(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255", 2);
+}), 500);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.draw.space.collapse.other.html b/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.draw.space.collapse.other.html
new file mode 100644
index 00000000000..25275b5b5ef
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.draw.space.collapse.other.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.text.draw.space.collapse.other</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<style>
+@font-face {
+ font-family: CanvasTest;
+ src: url("/fonts/CanvasTest.ttf");
+}
+</style>
+<body class="show_output">
+
+<h1>2d.text.draw.space.collapse.other</h1>
+<p class="desc">Space characters are converted to U+0020, and collapsed (per CSS)</p>
+
+
+<span style="font-family: CanvasTest; position: absolute; visibility: hidden">A</span>
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Space characters are converted to U+0020, and collapsed (per CSS)");
+_addTest(function(canvas, ctx) {
+
+ctx.font = '50px CanvasTest';
+deferTest();
+setTimeout(t.step_func_done(function () {
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.fillText('E \x09\x0a\x0c\x0d \x09\x0a\x0c\x0dEE', -100, 37.5);
+ _assertPixelApprox(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255", 2);
+}), 500);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.draw.space.collapse.space.html b/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.draw.space.collapse.space.html
new file mode 100644
index 00000000000..3069e794633
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.draw.space.collapse.space.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.text.draw.space.collapse.space</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<style>
+@font-face {
+ font-family: CanvasTest;
+ src: url("/fonts/CanvasTest.ttf");
+}
+</style>
+<body class="show_output">
+
+<h1>2d.text.draw.space.collapse.space</h1>
+<p class="desc">Space characters are converted to U+0020, and collapsed (per CSS)</p>
+
+
+<span style="font-family: CanvasTest; position: absolute; visibility: hidden">A</span>
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Space characters are converted to U+0020, and collapsed (per CSS)");
+_addTest(function(canvas, ctx) {
+
+ctx.font = '50px CanvasTest';
+deferTest();
+setTimeout(t.step_func_done(function () {
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.fillText('E EE', -100, 37.5);
+ _assertPixelApprox(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255", 2);
+}), 500);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.draw.space.collapse.start.html b/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.draw.space.collapse.start.html
new file mode 100644
index 00000000000..b3b05f436f8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.draw.space.collapse.start.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.text.draw.space.collapse.start</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<style>
+@font-face {
+ font-family: CanvasTest;
+ src: url("/fonts/CanvasTest.ttf");
+}
+</style>
+<body class="show_output">
+
+<h1>2d.text.draw.space.collapse.start</h1>
+<p class="desc">Space characters at the start of a line are collapsed (per CSS)</p>
+
+
+<span style="font-family: CanvasTest; position: absolute; visibility: hidden">A</span>
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Space characters at the start of a line are collapsed (per CSS)");
+_addTest(function(canvas, ctx) {
+
+ctx.font = '50px CanvasTest';
+deferTest();
+setTimeout(t.step_func_done(function () {
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.fillText(' EE', 0, 37.5);
+ _assertPixelApprox(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255", 2);
+ _assertPixelApprox(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255", 2);
+}), 500);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.font.default.html b/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.font.default.html
new file mode 100644
index 00000000000..e7405e350da
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.font.default.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.text.font.default</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.text.font.default</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+_assertSame(ctx.font, '10px sans-serif', "ctx.font", "'10px sans-serif'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.font.parse.basic.html b/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.font.parse.basic.html
new file mode 100644
index 00000000000..b4ae41cbcb7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.font.parse.basic.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.text.font.parse.basic</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.text.font.parse.basic</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.font = '20px serif';
+_assertSame(ctx.font, '20px serif', "ctx.font", "'20px serif'");
+
+ctx.font = '20PX SERIF';
+_assertSame(ctx.font, '20px serif', "ctx.font", "'20px serif'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.font.parse.complex.html b/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.font.parse.complex.html
new file mode 100644
index 00000000000..51917f36181
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.font.parse.complex.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.text.font.parse.complex</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.text.font.parse.complex</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.font = 'small-caps italic 400 12px/2 Unknown Font, sans-serif';
+_assertSame(ctx.font, 'italic small-caps 12px "Unknown Font", sans-serif', "ctx.font", "'italic small-caps 12px \"Unknown Font\", sans-serif'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.font.parse.invalid.html b/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.font.parse.invalid.html
new file mode 100644
index 00000000000..f65d680b0e9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.font.parse.invalid.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.text.font.parse.invalid</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.text.font.parse.invalid</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.font = '20px serif';
+_assertSame(ctx.font, '20px serif', "ctx.font", "'20px serif'");
+
+ctx.font = '20px serif';
+ctx.font = 'bogus';
+_assertSame(ctx.font, '20px serif', "ctx.font", "'20px serif'");
+
+ctx.font = '20px serif';
+ctx.font = 'inherit';
+_assertSame(ctx.font, '20px serif', "ctx.font", "'20px serif'");
+
+ctx.font = '20px serif';
+ctx.font = '10px {bogus}';
+_assertSame(ctx.font, '20px serif', "ctx.font", "'20px serif'");
+
+ctx.font = '20px serif';
+ctx.font = '10px initial';
+_assertSame(ctx.font, '20px serif', "ctx.font", "'20px serif'");
+
+ctx.font = '20px serif';
+ctx.font = '10px default';
+_assertSame(ctx.font, '20px serif', "ctx.font", "'20px serif'");
+
+ctx.font = '20px serif';
+ctx.font = '10px inherit';
+_assertSame(ctx.font, '20px serif', "ctx.font", "'20px serif'");
+
+ctx.font = '20px serif';
+ctx.font = '1em serif; background: green; margin: 10px';
+_assertSame(ctx.font, '20px serif', "ctx.font", "'20px serif'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.font.parse.size.percentage.default.html b/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.font.parse.size.percentage.default.html
new file mode 100644
index 00000000000..21eebde0f4b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.font.parse.size.percentage.default.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.text.font.parse.size.percentage.default</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.text.font.parse.size.percentage.default</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+var canvas2 = document.createElement('canvas');
+var ctx2 = canvas2.getContext('2d');
+ctx2.font = '1000% serif';
+_assertSame(ctx2.font, '100px serif', "ctx2.font", "'100px serif'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.font.parse.size.percentage.html b/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.font.parse.size.percentage.html
new file mode 100644
index 00000000000..6a05e48cf4d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.font.parse.size.percentage.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.text.font.parse.size.percentage</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.text.font.parse.size.percentage</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" style="font-size: 144px" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.font = '50% serif';
+_assertSame(ctx.font, '72px serif', "ctx.font", "'72px serif'");
+canvas.setAttribute('style', 'font-size: 100px');
+_assertSame(ctx.font, '72px serif', "ctx.font", "'72px serif'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.font.parse.system.html b/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.font.parse.system.html
new file mode 100644
index 00000000000..bc86f5c15b9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.font.parse.system.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.text.font.parse.system</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.text.font.parse.system</h1>
+<p class="desc">System fonts must be computed to explicit values</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("System fonts must be computed to explicit values");
+_addTest(function(canvas, ctx) {
+
+ctx.font = 'message-box';
+_assertDifferent(ctx.font, 'message-box', "ctx.font", "'message-box'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.measure.width.space.html b/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.measure.width.space.html
new file mode 100644
index 00000000000..dfa1dee1c19
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/text-styles/2d.text.measure.width.space.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.text.measure.width.space</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<style>
+@font-face {
+ font-family: CanvasTest;
+ src: url("/fonts/CanvasTest.ttf");
+}
+</style>
+<body class="show_output">
+
+<h1>2d.text.measure.width.space</h1>
+<p class="desc">Space characters are converted to U+0020 and collapsed (per CSS)</p>
+
+
+<span style="font-family: CanvasTest; position: absolute; visibility: hidden">A</span>
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Space characters are converted to U+0020 and collapsed (per CSS)");
+_addTest(function(canvas, ctx) {
+
+deferTest();
+setTimeout(t.step_func_done(function () {
+ ctx.font = '50px CanvasTest';
+ _assertSame(ctx.measureText('A B').width, 150, "ctx.measureText('A B').width", "150");
+ _assertSame(ctx.measureText('A B').width, 150, "ctx.measureText('A B').width", "150");
+ _assertSame(ctx.measureText('A \x09\x0a\x0c\x0d \x09\x0a\x0c\x0dB').width, 150, "ctx.measureText('A \\x09\\x0a\\x0c\\x0d \\x09\\x0a\\x0c\\x0dB').width", "150");
+ _assert(ctx.measureText('A \x0b B').width >= 200, "ctx.measureText('A \\x0b B').width >= 200");
+
+ _assertSame(ctx.measureText(' AB').width, 100, "ctx.measureText(' AB').width", "100");
+ _assertSame(ctx.measureText('AB ').width, 100, "ctx.measureText('AB ').width", "100");
+}), 500);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/text-styles/canvas_text_font_001.htm b/tests/wpt/web-platform-tests/2dcontext/text-styles/canvas_text_font_001.htm
new file mode 100644
index 00000000000..b7d26d672b5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/text-styles/canvas_text_font_001.htm
@@ -0,0 +1,32 @@
+<!doctype HTML>
+<html>
+ <head>
+ <title>HTML5 Canvas Test: Ignore property-independent style sheet syntax "inherit" in Text</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com" />
+ <link rel="help" href="http://www.w3.org/TR/2dcontext/#dom-context-2d-font" />
+ <meta name="assert" content=": Ignore 'inherit' property-independent style sheet syntax without assigning a new font value." />
+ <script type="text/javascript">
+ function runTest()
+ {
+ var canvas = document.getElementById("canvas1");
+ var ctx = canvas.getContext("2d");
+
+ // Assign a valid font.
+ ctx.font = "40px Times New Roman";
+
+ // Assign property-independent style sheet syntax 'inherit' as font.
+ ctx.font = "20px inherit";
+ ctx.fillText("Test String", 5, 50);
+
+ // Assign a valid font which was used earlier.
+ ctx.font = "40px Times New Roman";
+ ctx.fillText("Test String", 5, 100);
+ }
+ </script>
+ </head>
+ <body onload="runTest()">
+ <p>Description: Ignore "inherit" property-independent style sheet syntax without assigning a new font value.</p>
+ <p>Test passes if both strings are identical in both size, style, and text.</p>
+ <canvas id="canvas1" width="300" height="150">Browser does not support HTML5 Canvas.</canvas>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/.gitkeep b/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/.gitkeep
diff --git a/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.bitmap.html b/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.bitmap.html
new file mode 100644
index 00000000000..d22720c09d9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.bitmap.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.state.saverestore.bitmap</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.state.saverestore.bitmap</h1>
+<p class="desc">save()/restore() does not affect the current bitmap</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("save()/restore() does not affect the current bitmap");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.save();
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.restore();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.clip.html b/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.clip.html
new file mode 100644
index 00000000000..5f4d1ad35b9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.clip.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.state.saverestore.clip</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.state.saverestore.clip</h1>
+<p class="desc">save()/restore() affects the clipping path</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("save()/restore() affects the clipping path");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.save();
+ctx.rect(0, 0, 1, 1);
+ctx.clip();
+ctx.restore();
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.fillStyle.html b/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.fillStyle.html
new file mode 100644
index 00000000000..a44f4f96aaa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.fillStyle.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.state.saverestore.fillStyle</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.state.saverestore.fillStyle</h1>
+<p class="desc">save()/restore() works for fillStyle</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("save()/restore() works for fillStyle");
+_addTest(function(canvas, ctx) {
+
+// Test that restore() undoes any modifications
+var old = ctx.fillStyle;
+ctx.save();
+ctx.fillStyle = "#ff0000";
+ctx.restore();
+_assertSame(ctx.fillStyle, old, "ctx.fillStyle", "old");
+
+// Also test that save() doesn't modify the values
+ctx.fillStyle = "#ff0000";
+old = ctx.fillStyle;
+ // we're not interested in failures caused by get(set(x)) != x (e.g.
+ // from rounding), so compare against 'old' instead of against "#ff0000"
+ctx.save();
+_assertSame(ctx.fillStyle, old, "ctx.fillStyle", "old");
+ctx.restore();
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.font.html b/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.font.html
new file mode 100644
index 00000000000..287400646b2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.font.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.state.saverestore.font</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.state.saverestore.font</h1>
+<p class="desc">save()/restore() works for font</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("save()/restore() works for font");
+_addTest(function(canvas, ctx) {
+
+// Test that restore() undoes any modifications
+var old = ctx.font;
+ctx.save();
+ctx.font = "25px serif";
+ctx.restore();
+_assertSame(ctx.font, old, "ctx.font", "old");
+
+// Also test that save() doesn't modify the values
+ctx.font = "25px serif";
+old = ctx.font;
+ // we're not interested in failures caused by get(set(x)) != x (e.g.
+ // from rounding), so compare against 'old' instead of against "25px serif"
+ctx.save();
+_assertSame(ctx.font, old, "ctx.font", "old");
+ctx.restore();
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.globalAlpha.html b/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.globalAlpha.html
new file mode 100644
index 00000000000..27fc1aed884
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.globalAlpha.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.state.saverestore.globalAlpha</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.state.saverestore.globalAlpha</h1>
+<p class="desc">save()/restore() works for globalAlpha</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("save()/restore() works for globalAlpha");
+_addTest(function(canvas, ctx) {
+
+// Test that restore() undoes any modifications
+var old = ctx.globalAlpha;
+ctx.save();
+ctx.globalAlpha = 0.5;
+ctx.restore();
+_assertSame(ctx.globalAlpha, old, "ctx.globalAlpha", "old");
+
+// Also test that save() doesn't modify the values
+ctx.globalAlpha = 0.5;
+old = ctx.globalAlpha;
+ // we're not interested in failures caused by get(set(x)) != x (e.g.
+ // from rounding), so compare against 'old' instead of against 0.5
+ctx.save();
+_assertSame(ctx.globalAlpha, old, "ctx.globalAlpha", "old");
+ctx.restore();
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.globalCompositeOperation.html b/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.globalCompositeOperation.html
new file mode 100644
index 00000000000..419a96052df
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.globalCompositeOperation.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.state.saverestore.globalCompositeOperation</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.state.saverestore.globalCompositeOperation</h1>
+<p class="desc">save()/restore() works for globalCompositeOperation</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("save()/restore() works for globalCompositeOperation");
+_addTest(function(canvas, ctx) {
+
+// Test that restore() undoes any modifications
+var old = ctx.globalCompositeOperation;
+ctx.save();
+ctx.globalCompositeOperation = "copy";
+ctx.restore();
+_assertSame(ctx.globalCompositeOperation, old, "ctx.globalCompositeOperation", "old");
+
+// Also test that save() doesn't modify the values
+ctx.globalCompositeOperation = "copy";
+old = ctx.globalCompositeOperation;
+ // we're not interested in failures caused by get(set(x)) != x (e.g.
+ // from rounding), so compare against 'old' instead of against "copy"
+ctx.save();
+_assertSame(ctx.globalCompositeOperation, old, "ctx.globalCompositeOperation", "old");
+ctx.restore();
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.lineCap.html b/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.lineCap.html
new file mode 100644
index 00000000000..cb750219f78
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.lineCap.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.state.saverestore.lineCap</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.state.saverestore.lineCap</h1>
+<p class="desc">save()/restore() works for lineCap</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("save()/restore() works for lineCap");
+_addTest(function(canvas, ctx) {
+
+// Test that restore() undoes any modifications
+var old = ctx.lineCap;
+ctx.save();
+ctx.lineCap = "round";
+ctx.restore();
+_assertSame(ctx.lineCap, old, "ctx.lineCap", "old");
+
+// Also test that save() doesn't modify the values
+ctx.lineCap = "round";
+old = ctx.lineCap;
+ // we're not interested in failures caused by get(set(x)) != x (e.g.
+ // from rounding), so compare against 'old' instead of against "round"
+ctx.save();
+_assertSame(ctx.lineCap, old, "ctx.lineCap", "old");
+ctx.restore();
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.lineJoin.html b/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.lineJoin.html
new file mode 100644
index 00000000000..ff141126533
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.lineJoin.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.state.saverestore.lineJoin</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.state.saverestore.lineJoin</h1>
+<p class="desc">save()/restore() works for lineJoin</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("save()/restore() works for lineJoin");
+_addTest(function(canvas, ctx) {
+
+// Test that restore() undoes any modifications
+var old = ctx.lineJoin;
+ctx.save();
+ctx.lineJoin = "round";
+ctx.restore();
+_assertSame(ctx.lineJoin, old, "ctx.lineJoin", "old");
+
+// Also test that save() doesn't modify the values
+ctx.lineJoin = "round";
+old = ctx.lineJoin;
+ // we're not interested in failures caused by get(set(x)) != x (e.g.
+ // from rounding), so compare against 'old' instead of against "round"
+ctx.save();
+_assertSame(ctx.lineJoin, old, "ctx.lineJoin", "old");
+ctx.restore();
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.lineWidth.html b/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.lineWidth.html
new file mode 100644
index 00000000000..21bb266738f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.lineWidth.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.state.saverestore.lineWidth</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.state.saverestore.lineWidth</h1>
+<p class="desc">save()/restore() works for lineWidth</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("save()/restore() works for lineWidth");
+_addTest(function(canvas, ctx) {
+
+// Test that restore() undoes any modifications
+var old = ctx.lineWidth;
+ctx.save();
+ctx.lineWidth = 0.5;
+ctx.restore();
+_assertSame(ctx.lineWidth, old, "ctx.lineWidth", "old");
+
+// Also test that save() doesn't modify the values
+ctx.lineWidth = 0.5;
+old = ctx.lineWidth;
+ // we're not interested in failures caused by get(set(x)) != x (e.g.
+ // from rounding), so compare against 'old' instead of against 0.5
+ctx.save();
+_assertSame(ctx.lineWidth, old, "ctx.lineWidth", "old");
+ctx.restore();
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.miterLimit.html b/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.miterLimit.html
new file mode 100644
index 00000000000..f49edced102
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.miterLimit.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.state.saverestore.miterLimit</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.state.saverestore.miterLimit</h1>
+<p class="desc">save()/restore() works for miterLimit</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("save()/restore() works for miterLimit");
+_addTest(function(canvas, ctx) {
+
+// Test that restore() undoes any modifications
+var old = ctx.miterLimit;
+ctx.save();
+ctx.miterLimit = 0.5;
+ctx.restore();
+_assertSame(ctx.miterLimit, old, "ctx.miterLimit", "old");
+
+// Also test that save() doesn't modify the values
+ctx.miterLimit = 0.5;
+old = ctx.miterLimit;
+ // we're not interested in failures caused by get(set(x)) != x (e.g.
+ // from rounding), so compare against 'old' instead of against 0.5
+ctx.save();
+_assertSame(ctx.miterLimit, old, "ctx.miterLimit", "old");
+ctx.restore();
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.path.html b/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.path.html
new file mode 100644
index 00000000000..b6f269c32ca
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.path.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.state.saverestore.path</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.state.saverestore.path</h1>
+<p class="desc">save()/restore() does not affect the current path</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("save()/restore() does not affect the current path");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.save();
+ctx.rect(0, 0, 100, 50);
+ctx.restore();
+ctx.fillStyle = '#0f0';
+ctx.fill();
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.shadowBlur.html b/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.shadowBlur.html
new file mode 100644
index 00000000000..7f1ce6f9bb9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.shadowBlur.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.state.saverestore.shadowBlur</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.state.saverestore.shadowBlur</h1>
+<p class="desc">save()/restore() works for shadowBlur</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("save()/restore() works for shadowBlur");
+_addTest(function(canvas, ctx) {
+
+// Test that restore() undoes any modifications
+var old = ctx.shadowBlur;
+ctx.save();
+ctx.shadowBlur = 5;
+ctx.restore();
+_assertSame(ctx.shadowBlur, old, "ctx.shadowBlur", "old");
+
+// Also test that save() doesn't modify the values
+ctx.shadowBlur = 5;
+old = ctx.shadowBlur;
+ // we're not interested in failures caused by get(set(x)) != x (e.g.
+ // from rounding), so compare against 'old' instead of against 5
+ctx.save();
+_assertSame(ctx.shadowBlur, old, "ctx.shadowBlur", "old");
+ctx.restore();
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.shadowColor.html b/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.shadowColor.html
new file mode 100644
index 00000000000..95c36dfad42
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.shadowColor.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.state.saverestore.shadowColor</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.state.saverestore.shadowColor</h1>
+<p class="desc">save()/restore() works for shadowColor</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("save()/restore() works for shadowColor");
+_addTest(function(canvas, ctx) {
+
+// Test that restore() undoes any modifications
+var old = ctx.shadowColor;
+ctx.save();
+ctx.shadowColor = "#ff0000";
+ctx.restore();
+_assertSame(ctx.shadowColor, old, "ctx.shadowColor", "old");
+
+// Also test that save() doesn't modify the values
+ctx.shadowColor = "#ff0000";
+old = ctx.shadowColor;
+ // we're not interested in failures caused by get(set(x)) != x (e.g.
+ // from rounding), so compare against 'old' instead of against "#ff0000"
+ctx.save();
+_assertSame(ctx.shadowColor, old, "ctx.shadowColor", "old");
+ctx.restore();
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.shadowOffsetX.html b/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.shadowOffsetX.html
new file mode 100644
index 00000000000..363d5cc245f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.shadowOffsetX.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.state.saverestore.shadowOffsetX</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.state.saverestore.shadowOffsetX</h1>
+<p class="desc">save()/restore() works for shadowOffsetX</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("save()/restore() works for shadowOffsetX");
+_addTest(function(canvas, ctx) {
+
+// Test that restore() undoes any modifications
+var old = ctx.shadowOffsetX;
+ctx.save();
+ctx.shadowOffsetX = 5;
+ctx.restore();
+_assertSame(ctx.shadowOffsetX, old, "ctx.shadowOffsetX", "old");
+
+// Also test that save() doesn't modify the values
+ctx.shadowOffsetX = 5;
+old = ctx.shadowOffsetX;
+ // we're not interested in failures caused by get(set(x)) != x (e.g.
+ // from rounding), so compare against 'old' instead of against 5
+ctx.save();
+_assertSame(ctx.shadowOffsetX, old, "ctx.shadowOffsetX", "old");
+ctx.restore();
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.shadowOffsetY.html b/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.shadowOffsetY.html
new file mode 100644
index 00000000000..5edb62a7acd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.shadowOffsetY.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.state.saverestore.shadowOffsetY</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.state.saverestore.shadowOffsetY</h1>
+<p class="desc">save()/restore() works for shadowOffsetY</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("save()/restore() works for shadowOffsetY");
+_addTest(function(canvas, ctx) {
+
+// Test that restore() undoes any modifications
+var old = ctx.shadowOffsetY;
+ctx.save();
+ctx.shadowOffsetY = 5;
+ctx.restore();
+_assertSame(ctx.shadowOffsetY, old, "ctx.shadowOffsetY", "old");
+
+// Also test that save() doesn't modify the values
+ctx.shadowOffsetY = 5;
+old = ctx.shadowOffsetY;
+ // we're not interested in failures caused by get(set(x)) != x (e.g.
+ // from rounding), so compare against 'old' instead of against 5
+ctx.save();
+_assertSame(ctx.shadowOffsetY, old, "ctx.shadowOffsetY", "old");
+ctx.restore();
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.stack.html b/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.stack.html
new file mode 100644
index 00000000000..3a5dbea108f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.stack.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.state.saverestore.stack</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.state.saverestore.stack</h1>
+<p class="desc">save()/restore() can be nested as a stack</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("save()/restore() can be nested as a stack");
+_addTest(function(canvas, ctx) {
+
+ctx.lineWidth = 1;
+ctx.save();
+ctx.lineWidth = 2;
+ctx.save();
+ctx.lineWidth = 3;
+_assertSame(ctx.lineWidth, 3, "ctx.lineWidth", "3");
+ctx.restore();
+_assertSame(ctx.lineWidth, 2, "ctx.lineWidth", "2");
+ctx.restore();
+_assertSame(ctx.lineWidth, 1, "ctx.lineWidth", "1");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.stackdepth.html b/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.stackdepth.html
new file mode 100644
index 00000000000..5e6c459f3a7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.stackdepth.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.state.saverestore.stackdepth</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.state.saverestore.stackdepth</h1>
+<p class="desc">save()/restore() stack depth is not unreasonably limited</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("save()/restore() stack depth is not unreasonably limited");
+_addTest(function(canvas, ctx) {
+
+var limit = 512;
+for (var i = 1; i < limit; ++i)
+{
+ ctx.save();
+ ctx.lineWidth = i;
+}
+for (var i = limit-1; i > 0; --i)
+{
+ _assertSame(ctx.lineWidth, i, "ctx.lineWidth", "i");
+ ctx.restore();
+}
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.strokeStyle.html b/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.strokeStyle.html
new file mode 100644
index 00000000000..53a28f55559
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.strokeStyle.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.state.saverestore.strokeStyle</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.state.saverestore.strokeStyle</h1>
+<p class="desc">save()/restore() works for strokeStyle</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("save()/restore() works for strokeStyle");
+_addTest(function(canvas, ctx) {
+
+// Test that restore() undoes any modifications
+var old = ctx.strokeStyle;
+ctx.save();
+ctx.strokeStyle = "#ff0000";
+ctx.restore();
+_assertSame(ctx.strokeStyle, old, "ctx.strokeStyle", "old");
+
+// Also test that save() doesn't modify the values
+ctx.strokeStyle = "#ff0000";
+old = ctx.strokeStyle;
+ // we're not interested in failures caused by get(set(x)) != x (e.g.
+ // from rounding), so compare against 'old' instead of against "#ff0000"
+ctx.save();
+_assertSame(ctx.strokeStyle, old, "ctx.strokeStyle", "old");
+ctx.restore();
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.textAlign.html b/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.textAlign.html
new file mode 100644
index 00000000000..ea1b3f2e210
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.textAlign.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.state.saverestore.textAlign</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.state.saverestore.textAlign</h1>
+<p class="desc">save()/restore() works for textAlign</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("save()/restore() works for textAlign");
+_addTest(function(canvas, ctx) {
+
+// Test that restore() undoes any modifications
+var old = ctx.textAlign;
+ctx.save();
+ctx.textAlign = "center";
+ctx.restore();
+_assertSame(ctx.textAlign, old, "ctx.textAlign", "old");
+
+// Also test that save() doesn't modify the values
+ctx.textAlign = "center";
+old = ctx.textAlign;
+ // we're not interested in failures caused by get(set(x)) != x (e.g.
+ // from rounding), so compare against 'old' instead of against "center"
+ctx.save();
+_assertSame(ctx.textAlign, old, "ctx.textAlign", "old");
+ctx.restore();
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.textBaseline.html b/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.textBaseline.html
new file mode 100644
index 00000000000..22664ef1dc1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.textBaseline.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.state.saverestore.textBaseline</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.state.saverestore.textBaseline</h1>
+<p class="desc">save()/restore() works for textBaseline</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("save()/restore() works for textBaseline");
+_addTest(function(canvas, ctx) {
+
+// Test that restore() undoes any modifications
+var old = ctx.textBaseline;
+ctx.save();
+ctx.textBaseline = "bottom";
+ctx.restore();
+_assertSame(ctx.textBaseline, old, "ctx.textBaseline", "old");
+
+// Also test that save() doesn't modify the values
+ctx.textBaseline = "bottom";
+old = ctx.textBaseline;
+ // we're not interested in failures caused by get(set(x)) != x (e.g.
+ // from rounding), so compare against 'old' instead of against "bottom"
+ctx.save();
+_assertSame(ctx.textBaseline, old, "ctx.textBaseline", "old");
+ctx.restore();
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.transformation.html b/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.transformation.html
new file mode 100644
index 00000000000..744f7ab7f2b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.transformation.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.state.saverestore.transformation</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.state.saverestore.transformation</h1>
+<p class="desc">save()/restore() affects the current transformation matrix</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("save()/restore() affects the current transformation matrix");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.save();
+ctx.translate(200, 0);
+ctx.restore();
+ctx.fillStyle = '#f00';
+ctx.fillRect(-200, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.underflow.html b/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.underflow.html
new file mode 100644
index 00000000000..c965b02566c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/2d.state.saverestore.underflow.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.state.saverestore.underflow</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.state.saverestore.underflow</h1>
+<p class="desc">restore() with an empty stack has no effect</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("restore() with an empty stack has no effect");
+_addTest(function(canvas, ctx) {
+
+for (var i = 0; i < 16; ++i)
+ ctx.restore();
+ctx.lineWidth = 0.5;
+ctx.restore();
+_assertSame(ctx.lineWidth, 0.5, "ctx.lineWidth", "0.5");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/canvas_state_restore_001-ref.htm b/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/canvas_state_restore_001-ref.htm
new file mode 100644
index 00000000000..aee610d2ec8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/canvas_state_restore_001-ref.htm
@@ -0,0 +1,11 @@
+<!doctype HTML>
+<html>
+ <head>
+ <title>HTML5 Canvas Test: restore() pops top entry in drawing state stack</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com" />
+ </head>
+ <body>
+ <p>Description: restore() pops the top entry in the drawing state stack.</p>
+ <div><img src='/images/threecolors.png' alt='3 colors'></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/canvas_state_restore_001.htm b/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/canvas_state_restore_001.htm
new file mode 100644
index 00000000000..6d5a3cb20f6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/the-canvas-state/canvas_state_restore_001.htm
@@ -0,0 +1,42 @@
+<!doctype HTML>
+<html>
+ <head>
+ <title>HTML5 Canvas Test: restore() pops top entry in drawing state stack</title>
+ <link rel="match" href="canvas_state_restore_001-ref.htm">
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com" />
+ <link rel="help" href="http://www.w3.org/TR/2dcontext/#the-canvas-state" />
+ <meta name="assert" content="restore() pops the top entry in the drawing state stack." />
+ <script type="text/javascript">
+ function runTest()
+ {
+ var canvas = document.getElementById("canvas1");
+ var ctx = canvas.getContext("2d");
+ ctx.fillStyle = "rgba(255, 0, 0, 1.0)";
+ ctx.fillRect(0, 0, 99, 50);
+
+ // Save colors to the stack as separate drawing states.
+ ctx.fillStyle = "rgba(255, 255, 0, 1.0)";
+ ctx.save();
+ ctx.fillStyle = "rgba(0, 0, 255, 1.0)";
+ ctx.save();
+ ctx.fillStyle = "rgba(0, 255, 0, 1.0)";
+ ctx.save();
+
+ // Modify the current fillStyle.
+ ctx.fillStyle = "rgba(255, 0, 0, 1.0)";
+
+ // Restore the drawing states previously saved and draw with them.
+ ctx.restore();
+ ctx.fillRect(66, 0, 33, 50);
+ ctx.restore();
+ ctx.fillRect(33, 0, 33, 50);
+ ctx.restore();
+ ctx.fillRect(0, 0, 33, 50);
+ }
+ </script>
+ </head>
+ <body onload="runTest()">
+ <p>Description: restore() pops the top entry in the drawing state stack.</p>
+ <canvas id="canvas1" width="300" height="150">Browser does not support HTML5 Canvas.</canvas>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/2dcontext/tools/LICENSE.txt b/tests/wpt/web-platform-tests/2dcontext/tools/LICENSE.txt
new file mode 100644
index 00000000000..b248aa87ee4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/tools/LICENSE.txt
@@ -0,0 +1,36 @@
+2DContext and <canvas> test suite
+
+Copyright (c) 2010 Philip Taylor
+
+The code and all associated data files may be used under the terms of the
+following license:
+
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of works must retain the original copyright notice, this
+ list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the original copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+* Neither the name of the W3C nor the names of its contributors may be used to
+ endorse or promote products derived from this work without specific prior
+ written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Alternatively, the code and data may be used under the terms of
+http://www.w3.org/Consortium/Legal/2008/04-testsuite-license.html
diff --git a/tests/wpt/web-platform-tests/2dcontext/tools/current-work-canvas.xhtml b/tests/wpt/web-platform-tests/2dcontext/tools/current-work-canvas.xhtml
new file mode 100644
index 00000000000..b41ad7d4d62
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/tools/current-work-canvas.xhtml
@@ -0,0 +1,3693 @@
+<?xml version="1.0" encoding="UTF-8"?><html xml:lang="en-US-x-hixie" xmlns="http://www.w3.org/1999/xhtml"><head><title>HTML Standard</title><link href="http://www.whatwg.org/style/specification" rel="stylesheet"/><link href="http://www.whatwg.org/images/icon" rel="icon"/><style>
+ .proposal { border: blue solid; padding: 1em; }
+ .bad, .bad *:not(.XXX) { color: gray; border-color: gray; background: transparent; }
+ #updatesStatus { display: none; }
+ #updatesStatus.relevant { display: block; position: fixed; right: 1em; top: 1em; padding: 0.5em; font: bold small sans-serif; min-width: 25em; width: 30%; max-width: 40em; height: auto; border: ridge 4px gray; background: #EEEEEE; color: black; }
+ div.head .logo { width: 11em; margin-bottom: 20em; }
+ #configUI { position: absolute; z-index: 20; top: 10em; right: 0; width: 11em; padding: 0 0.5em 0 0.5em; font-size: small; background: gray; background: rgba(32,32,32,0.9); color: white; border-radius: 1em 0 0 1em; -moz-border-radius: 1em 0 0 1em; }
+ #configUI p { margin: 0.75em 0; padding: 0.3em; }
+ #configUI p label { display: block; }
+ #configUI #updateUI, #configUI .loginUI { text-align: center; }
+ #configUI input[type=button] { display: block; margin: auto; }
+ #configUI :link, #configUI :visited { color: white; }
+ #configUI :link:hover, #configUI :visited:hover { background: transparent; }
+ #reviewer { position: fixed; bottom: 0; right: 0; padding: 0.15em 0.25em 0em 0.5em; white-space: nowrap; overflow: hidden; z-index: 30; background: gray; background: rgba(32,32,32,0.9); color: white; border-radius: 1em 0 0 0; -moz-border-radius: 1em 0 0 0; max-width: 90%; }
+ #reviewer input { max-width: 50%; }
+ #reviewer * { font-size: small; }
+ #reviewer.off &gt; :not(:first-child) { display: none; }
+ #alert { position: fixed; top: 20%; left: 20%; right: 20%; font-size: 2em; padding: 0.5em; z-index: 40; background: gray; background: rgba(32,32,32,0.9); color: white; border-radius: 1em; -moz-border-radius: 1em; -webkit-transition: opacity 1s linear; }
+ #alert.closed { opacity: 0; }
+ #alert button { position: absolute; top: -1em; right: 2em; border-radius: 1em 1em 0 0; border: none; line-height: 0.9; color: white; background: rgb(64,64,64); font-size: 0.6em; font-weight: 900; cursor: pointer; }
+ #alert :link, #alert :visited { color: white; }
+ #alert :link:hover, #alert :visited:hover { background: transparent; }
+ @media print { #configUI { display: none; } }
+ .rfc2119 { font-variant: small-caps; text-shadow: 0 0 0.5em yellow; position: static; }
+ .rfc2119::after { position: absolute; left: 0; width: 25px; text-align: center; color: yellow; text-shadow: 0.075em 0.075em 0.2em black; }
+ .rfc2119.m\ust::after { content: '\2605'; }
+ .rfc2119.s\hould::after { content: '\2606'; }
+ [hidden] { display: none; }
+ </style><style type="text/css">
+
+ .applies thead th &gt; * { display: block; }
+ .applies thead code { display: block; }
+ .applies tbody th { whitespace: nowrap; }
+ .applies td { text-align: center; }
+ .applies .yes { background: yellow; }
+
+ .matrix, .matrix td { border: hidden; text-align: right; }
+ .matrix { margin-left: 2em; }
+
+ .dice-example { border-collapse: collapse; border-style: hidden solid solid hidden; border-width: thin; margin-left: 3em; }
+ .dice-example caption { width: 30em; font-size: smaller; font-style: italic; padding: 0.75em 0; text-align: left; }
+ .dice-example td, .dice-example th { border: solid thin; width: 1.35em; height: 1.05em; text-align: center; padding: 0; }
+
+ td.eg { border-width: thin; text-align: center; }
+
+ #table-example-1 { border: solid thin; border-collapse: collapse; margin-left: 3em; }
+ #table-example-1 * { font-family: &quot;Essays1743&quot;, serif; line-height: 1.01em; }
+ #table-example-1 caption { padding-bottom: 0.5em; }
+ #table-example-1 thead, #table-example-1 tbody { border: none; }
+ #table-example-1 th, #table-example-1 td { border: solid thin; }
+ #table-example-1 th { font-weight: normal; }
+ #table-example-1 td { border-style: none solid; vertical-align: top; }
+ #table-example-1 th { padding: 0.5em; vertical-align: middle; text-align: center; }
+ #table-example-1 tbody tr:first-child td { padding-top: 0.5em; }
+ #table-example-1 tbody tr:last-child td { padding-bottom: 1.5em; }
+ #table-example-1 tbody td:first-child { padding-left: 2.5em; padding-right: 0; width: 9em; }
+ #table-example-1 tbody td:first-child::after { content: leader(&quot;. &quot;); }
+ #table-example-1 tbody td { padding-left: 2em; padding-right: 2em; }
+ #table-example-1 tbody td:first-child + td { width: 10em; }
+ #table-example-1 tbody td:first-child + td ~ td { width: 2.5em; }
+ #table-example-1 tbody td:first-child + td + td + td ~ td { width: 1.25em; }
+
+ .apple-table-examples { border: none; border-collapse: separate; border-spacing: 1.5em 0em; width: 40em; margin-left: 3em; }
+ .apple-table-examples * { font-family: &quot;Times&quot;, serif; }
+ .apple-table-examples td, .apple-table-examples th { border: none; white-space: nowrap; padding-top: 0; padding-bottom: 0; }
+ .apple-table-examples tbody th:first-child { border-left: none; width: 100%; }
+ .apple-table-examples thead th:first-child ~ th { font-size: smaller; font-weight: bolder; border-bottom: solid 2px; text-align: center; }
+ .apple-table-examples tbody th::after, .apple-table-examples tfoot th::after { content: leader(&quot;. &quot;) }
+ .apple-table-examples tbody th, .apple-table-examples tfoot th { font: inherit; text-align: left; }
+ .apple-table-examples td { text-align: right; vertical-align: top; }
+ .apple-table-examples.e1 tbody tr:last-child td { border-bottom: solid 1px; }
+ .apple-table-examples.e1 tbody + tbody tr:last-child td { border-bottom: double 3px; }
+ .apple-table-examples.e2 th[scope=row] { padding-left: 1em; }
+ .apple-table-examples sup { line-height: 0; }
+
+ .details-example img { vertical-align: top; }
+
+ #base64-table {
+ white-space: nowrap;
+ font-size: 0.6em;
+ column-width: 6em;
+ column-count: 5;
+ column-gap: 1em;
+ -moz-column-width: 6em;
+ -moz-column-count: 5;
+ -moz-column-gap: 1em;
+ -webkit-column-width: 6em;
+ -webkit-column-count: 5;
+ -webkit-column-gap: 1em;
+ }
+ #base64-table thead { display: none; }
+ #base64-table * { border: none; }
+ #base64-table tbody td:first-child:after { content: ':'; }
+ #base64-table tbody td:last-child { text-align: right; }
+
+ #named-character-references-table {
+ white-space: nowrap;
+ font-size: 0.6em;
+ column-width: 30em;
+ column-gap: 1em;
+ -moz-column-width: 30em;
+ -moz-column-gap: 1em;
+ -webkit-column-width: 30em;
+ -webkit-column-gap: 1em;
+ }
+ #named-character-references-table &gt; table &gt; tbody &gt; tr &gt; td:first-child + td,
+ #named-character-references-table &gt; table &gt; tbody &gt; tr &gt; td:last-child { text-align: center; }
+ #named-character-references-table &gt; table &gt; tbody &gt; tr &gt; td:last-child:hover &gt; span { position: absolute; top: auto; left: auto; margin-left: 0.5em; line-height: 1.2; font-size: 5em; border: outset; padding: 0.25em 0.5em; background: white; width: 1.25em; height: auto; text-align: center; }
+ #named-character-references-table &gt; table &gt; tbody &gt; tr#entity-CounterClockwiseContourIntegral &gt; td:first-child { font-size: 0.5em; }
+
+ .glyph.control { color: red; }
+
+ @font-face {
+ font-family: 'Essays1743';
+ src: url('http://www.whatwg.org/specs/web-apps/current-work/fonts/Essays1743.ttf');
+ }
+ @font-face {
+ font-family: 'Essays1743';
+ font-weight: bold;
+ src: url('http://www.whatwg.org/specs/web-apps/current-work/fonts/Essays1743-Bold.ttf');
+ }
+ @font-face {
+ font-family: 'Essays1743';
+ font-style: italic;
+ src: url('http://www.whatwg.org/specs/web-apps/current-work/fonts/Essays1743-Italic.ttf');
+ }
+ @font-face {
+ font-family: 'Essays1743';
+ font-style: italic;
+ font-weight: bold;
+ src: url('http://www.whatwg.org/specs/web-apps/current-work/fonts/Essays1743-BoldItalic.ttf');
+ }
+
+ </style><style>
+ .domintro:before { display: table; margin: -1em -0.5em -0.5em auto; width: auto; content: 'This box is non-normative. Implementation requirements are given below this box.'; color: black; font-style: italic; border: solid 2px; background: white; padding: 0 0.25em; }
+ </style><link href="data:text/css," id="complete" rel="stylesheet" title="Complete specification"/><link href="data:text/css,.impl%20{%20display:%20none;%20}%0Ahtml%20{%20border:%20solid%20yellow;%20}%20.domintro:before%20{%20display:%20none;%20}" id="author" rel="alternate stylesheet" title="Author documentation only"/><link href="data:text/css,.impl%20{%20background:%20%23FFEEEE;%20}%20.domintro:before%20{%20background:%20%23FFEEEE;%20}" id="highlight" rel="alternate stylesheet" title="Highlight implementation requirements"/><link href="http://www.whatwg.org/specs/web-apps/current-work/status.css" rel="stylesheet"/></head><body class="draft" onload="init()"><header class="head" id="head"><p><a class="logo" href="http://www.whatwg.org/"><img alt="WHATWG" height="101" src="http://www.whatwg.org/images/logo" width="101"/></a></p>
+ <hgroup><h1 class="allcaps">HTML</h1>
+ <h2 class="no-num no-toc">Living Standard — Last Updated 8 August 2011</h2>
+ </hgroup><p class="copyright">© Copyright 2004-2011 Apple Computer, Inc.,
+ Mozilla Foundation, and Opera Software ASA.</p>
+ <p class="copyright">You are granted a license to use, reproduce
+ and create derivative works of this document.</p>
+
+ </header><h4 id="the-canvas-element"><span class="secno">4.8.11 </span>The <dfn id="canvas"><code>canvas</code></dfn> element</h4>
+
+ <dl class="element"><dt>Categories</dt>
+ <dd><a href="#flow-content">Flow content</a>.</dd>
+ <dd><a href="#phrasing-content">Phrasing content</a>.</dd>
+ <dd><a href="#embedded-content">Embedded content</a>.</dd>
+ <dt>Contexts in which this element can be used:</dt>
+ <dd>Where <a href="#embedded-content">embedded content</a> is expected.</dd>
+ <dt>Content model:</dt>
+ <dd><a href="#transparent">Transparent</a>.</dd>
+ <dd><a href="#transparent">Transparent</a><!--
+--><!--FORK--><!--
+-->, but with no <a href="#interactive-content">interactive content</a> descendants except for <code><a href="#the-a-element">a</a></code> elements, <code><a href="#the-button-element">button</a></code> elements, <code><a href="#the-input-element">input</a></code> elements whose <code title="attr-input-type"><a href="#attr-input-type">type</a></code> attribute are in the <a href="#checkbox-state" title="attr-input-type-checkbox">Checkbox</a> or <a href="#radio-button-state" title="attr-input-type-radio">Radio Button</a> states, and <code><a href="#the-input-element">input</a></code> elements that are <a href="#concept-button" title="concept-button">buttons</a><!--
+--><!--FORK--><!--
+-->.</dd> <!-- and maybe <select>, I guess? I've left it in for now, since I guess authors might make accessible selects if they're simple enough, and it's not obvious how to distinguish the simple ones from the complex ones... -->
+ <dt>Content attributes:</dt>
+ <dd><a href="#global-attributes">Global attributes</a></dd>
+ <dd><code title="attr-canvas-width"><a href="#attr-canvas-width">width</a></code></dd>
+ <dd><code title="attr-canvas-height"><a href="#attr-canvas-height">height</a></code></dd>
+ <dt>DOM interface:</dt>
+ <dd>
+ <pre class="idl">interface <dfn id="htmlcanvaselement">HTMLCanvasElement</dfn> : <a href="#htmlelement">HTMLElement</a> {
+ attribute unsigned long <a href="#dom-canvas-width" title="dom-canvas-width">width</a>;
+ attribute unsigned long <a href="#dom-canvas-height" title="dom-canvas-height">height</a>;
+
+ DOMString <a href="#dom-canvas-todataurl" title="dom-canvas-toDataURL">toDataURL</a>(in optional DOMString type, in any... args);
+ void <a href="#dom-canvas-toblob" title="dom-canvas-toBlob">toBlob</a>(in <span>FileCallback</span>? callback, in optional DOMString type, in any... args);
+
+ object? <a href="#dom-canvas-getcontext" title="dom-canvas-getContext">getContext</a>(in DOMString contextId, in any... args);
+};</pre>
+ </dd>
+ </dl><p>The <code><a href="#the-canvas-element">canvas</a></code> element provides scripts with a
+ resolution-dependent bitmap canvas, which can be used for rendering
+ graphs, game graphics, or other visual images on the fly.</p>
+
+ <p>Authors should not use the <code><a href="#the-canvas-element">canvas</a></code> element in a
+ document when a more suitable element is available. For example, it
+ is inappropriate to use a <code><a href="#the-canvas-element">canvas</a></code> element to render a
+ page heading: if the desired presentation of the heading is
+ graphically intense, it should be marked up using appropriate
+ elements (typically <code><a href="#the-h1,-h2,-h3,-h4,-h5,-and-h6-elements">h1</a></code>) and then styled using CSS and
+ supporting technologies such as XBL.</p>
+
+ <p>When authors use the <code><a href="#the-canvas-element">canvas</a></code> element, they must also
+ provide content that, when presented to the user, conveys
+ essentially the same function or purpose as the bitmap canvas. This
+ content may be placed as content of the <code><a href="#the-canvas-element">canvas</a></code>
+ element. The contents of the <code><a href="#the-canvas-element">canvas</a></code> element, if any,
+ are the element's <a href="#fallback-content">fallback content</a>.</p>
+
+ <p>In interactive visual media, if <a href="#concept-n-script" title="concept-n-script">scripting is enabled</a> for the
+ <code><a href="#the-canvas-element">canvas</a></code> element, and if support for <code><a href="#the-canvas-element">canvas</a></code>
+ elements has been enabled, the <code><a href="#the-canvas-element">canvas</a></code> element
+ <a href="#represents">represents</a> <a href="#embedded-content">embedded content</a> consisting of
+ a dynamically created image.</p>
+
+ <p>In non-interactive, static, visual media, if the
+ <code><a href="#the-canvas-element">canvas</a></code> element has been previously painted on (e.g. if
+ the page was viewed in an interactive visual medium and is now being
+ printed, or if some script that ran during the page layout process
+ painted on the element), then the <code><a href="#the-canvas-element">canvas</a></code> element
+ <a href="#represents">represents</a> <a href="#embedded-content">embedded content</a> with the
+ current image and size. Otherwise, the element represents its
+ <a href="#fallback-content">fallback content</a> instead.</p>
+
+ <p>In non-visual media, and in visual media if <a href="#concept-n-noscript" title="concept-n-noscript">scripting is disabled</a> for the
+ <code><a href="#the-canvas-element">canvas</a></code> element or if support for <code><a href="#the-canvas-element">canvas</a></code>
+ elements has been disabled, the <code><a href="#the-canvas-element">canvas</a></code> element
+ <a href="#represents">represents</a> its <a href="#fallback-content">fallback content</a>
+ instead.</p>
+
+ <!-- CANVAS-FOCUS-FALLBACK -->
+ <p>When a <code><a href="#the-canvas-element">canvas</a></code> element <a href="#represents">represents</a>
+ <a href="#embedded-content">embedded content</a>, the user can still focus descendants
+ of the <code><a href="#the-canvas-element">canvas</a></code> element (in the <a href="#fallback-content">fallback
+ content</a>). When an element is focused, it is the target of
+ keyboard interaction events (even though the element itself is not
+ visible). This allows authors to make an interactive canvas
+ keyboard-accessible: authors should have a one-to-one mapping of
+ interactive regions to focusable elements in the <a href="#fallback-content">fallback
+ content</a>. (Focus has no effect on mouse interaction
+ events.) <a href="#DOMEVENTS">[DOMEVENTS]</a></p>
+
+ <p>The <code><a href="#the-canvas-element">canvas</a></code> element has two attributes to control the
+ size of the coordinate space: <dfn id="attr-canvas-width" title="attr-canvas-width"><code>width</code></dfn> and <dfn id="attr-canvas-height" title="attr-canvas-height"><code>height</code></dfn>. These
+ attributes, when specified, must have values that are <a href="#valid-non-negative-integer" title="valid non-negative integer">valid non-negative
+ integers</a>. <span class="impl">The <a href="#rules-for-parsing-non-negative-integers">rules for parsing
+ non-negative integers</a> must be used to obtain their numeric
+ values. If an attribute is missing, or if parsing its value returns
+ an error, then the default value must be used instead.</span> The
+ <code title="attr-canvas-width"><a href="#attr-canvas-width">width</a></code> attribute defaults to
+ 300, and the <code title="attr-canvas-height"><a href="#attr-canvas-height">height</a></code>
+ attribute defaults to 150.</p>
+
+ <p>The intrinsic dimensions of the <code><a href="#the-canvas-element">canvas</a></code> element equal
+ the size of the coordinate space, with the numbers interpreted in
+ CSS pixels. However, the element can be sized arbitrarily by a
+ style sheet. During rendering, the image is scaled to fit this layout
+ size.</p>
+
+ <div class="impl">
+
+ <p>The size of the coordinate space does not necessarily represent
+ the size of the actual bitmap that the user agent will use
+ internally or during rendering. On high-definition displays, for
+ instance, the user agent may internally use a bitmap with two device
+ pixels per unit in the coordinate space, so that the rendering
+ remains at high quality throughout.</p>
+
+ <p>When the <code><a href="#the-canvas-element">canvas</a></code> element is created, and subsequently
+ whenever the <code title="attr-canvas-width"><a href="#attr-canvas-width">width</a></code> and <code title="attr-canvas-height"><a href="#attr-canvas-height">height</a></code> attributes are set (whether
+ to a new value or to the previous value), the bitmap and any
+ associated contexts must be cleared back to their initial state and
+ reinitialized with the newly specified coordinate space
+ dimensions.</p>
+
+ <p>When the canvas is initialized, its bitmap must be cleared to
+ transparent black.</p>
+
+ <p>The <dfn id="dom-canvas-width" title="dom-canvas-width"><code>width</code></dfn> and
+ <dfn id="dom-canvas-height" title="dom-canvas-height"><code>height</code></dfn> IDL
+ attributes must <a href="#reflect">reflect</a> the respective content
+ attributes of the same name, with the same defaults.</p>
+
+ </div>
+
+ <div class="example">
+ <p>Only one square appears to be drawn in the following example:</p>
+ <pre> // canvas is a reference to a &lt;canvas&gt; element
+ var context = canvas.getContext('2d');
+ context.fillRect(0,0,50,50);
+ canvas.setAttribute('width', '300'); // clears the canvas
+ context.fillRect(0,100,50,50);
+ canvas.width = canvas.width; // clears the canvas
+ context.fillRect(100,0,50,50); // only this square remains</pre>
+ </div>
+
+ <hr/><dl class="domintro"><dt><var title="">context</var> = <var title="">canvas</var> . <code title="dom-canvas-getContext"><a href="#dom-canvas-getcontext">getContext</a></code>(<var title="">contextId</var> [, ... ])</dt>
+
+ <dd>
+
+ <p>Returns an object that exposes an API for drawing on the
+ canvas. The first argument specifies the desired API. Subsequent
+ arguments are handled by that API.</p>
+
+<!--2DCONTEXT-->
+
+ <p>This specification defines the &quot;<code title="canvas-context-2d"><a href="#canvas-context-2d">2d</a></code>&quot; context below. There is also
+ a specification that defines a &quot;<code title="canvas-context-webgl">webgl</code>&quot; context. <a href="#refsWEBGL">[WEBGL]</a></p>
+
+<!--2DCONTEXT-->
+
+ <p>The list of defined contexts is given on the <a href="http://wiki.whatwg.org/wiki/CanvasContexts">WHATWG Wiki
+ CanvasContexts page</a>. <a href="#refsWHATWGWIKI">[WHATWGWIKI]</a>
+
+ </p><p>Returns null if the given context ID is not supported or if the
+ canvas has already been initialized with some other (incompatible)
+ context type (e.g. trying to get a &quot;<code title="canvas-context-2d"><a href="#canvas-context-2d">2d</a></code>&quot; context after getting a
+ &quot;<code title="canvas-context-webgl">webgl</code>&quot; context).</p>
+
+ </dd>
+
+ </dl><div class="impl">
+
+ <p>A <code><a href="#the-canvas-element">canvas</a></code> element can have a <dfn id="primary-context">primary
+ context</dfn>, which is the first context to have been obtained for
+ that element. When created, a <code><a href="#the-canvas-element">canvas</a></code> element must not
+ have a <a href="#primary-context">primary context</a>.</p>
+
+
+ <p>The <dfn id="dom-canvas-getcontext" title="dom-canvas-getContext"><code>getContext(<var title="">contextId</var>, <var title="">args...</var>)</code></dfn>
+ method of the <code><a href="#the-canvas-element">canvas</a></code> element, when invoked, must run
+ the following steps:</p>
+
+ <ol><li><p>Let <var title="">contextId</var> be the first argument to
+ the method.</p></li>
+
+ <li>
+
+ <p>If <var title="">contextId</var> is not the name of a context
+ supported by the user agent, return null and abort these
+ steps.</p>
+
+ <p class="note">An example of this would be a user agent that
+ theoretically supports the &quot;<code title="canvas-context-webgl">webgl</code>&quot; 3D context, in the case
+ where the platform does not have hardware support for OpenGL and
+ the user agent does not have a software OpenGL implementation.
+ Despite the user agent recognising the &quot;<code title="canvas-context-webgl">webgl</code>&quot; name, it would return
+ null at this step because that context is not, in practice,
+ supported at the time of the call.</p>
+
+ </li>
+
+ <li><p>If the element has a <a href="#primary-context">primary context</a> and that
+ context's entry in the <a href="http://wiki.whatwg.org/wiki/CanvasContexts">WHATWG Wiki
+ CanvasContexts page</a> does not list <var title="">contextId</var>
+ as a context with which it is compatible, return null and abort
+ these steps. <a href="#refsWHATWGWIKI">[WHATWGWIKI]</a></p></li>
+
+ <li><p>If the element does not have a <a href="#primary-context">primary context</a>,
+ let the element's <a href="#primary-context">primary context</a> be <var title="">contextId</var>.</p></li>
+
+ <li><p>If the <code title="dom-canvas-getContext"><a href="#dom-canvas-getcontext">getContext()</a></code> method has
+ already been invoked on this element for the same <var title="">contextId</var>, return the same object as was returned
+ that time, and abort these steps. The additional arguments are
+ ignored.</p></li>
+
+ <li><p><dfn id="getcontext-return" title="getContext-return">Return a new object for <var title="">contextId</var></dfn>, as defined by the specification
+ given for <var title="">contextId</var>'s entry in the <a href="http://wiki.whatwg.org/wiki/CanvasContexts">WHATWG Wiki
+ CanvasContexts page</a>. <a href="#refsWHATWGWIKI">[WHATWGWIKI]</a></p></li>
+
+ </ol><p>New context types may be registered in the <a href="http://wiki.whatwg.org/wiki/CanvasContexts">WHATWG Wiki
+ CanvasContexts page</a>. <a href="#refsWHATWGWIKI">[WHATWGWIKI]</a></p>
+
+ <p>Anyone is free to edit the WHATWG Wiki CanvasContexts page at any
+ time to add a new context type. These new context types must be
+ specified with the following information:</p>
+
+ <dl><dt>Keyword</dt>
+
+ <dd><p>The value of <var title="">contextID</var> that will return
+ the object for the new API.</p></dd>
+
+
+ <dt>Specification</dt>
+
+ <dd><p>A link to a formal specification of the context type's
+ API. It could be another page on the Wiki, or a link to an external
+ page. If the type does not have a formal specification, an informal
+ description can be substituted until such time as a formal
+ specification is available.</p></dd>
+
+
+ <dt>Compatible with</dt>
+
+ <dd><p>The list of context types that are compatible with this one
+ (i.e. that operate on the same underlying bitmap). This list must
+ be transitive and symmetric; if one context type is defined as
+ compatible with another, then all types it is compatible with must
+ be compatible with all types the other is compatible with.</p></dd>
+
+ </dl><p>Vendors may also define experimental contexts using the syntax
+ <code><var title="">vendorname</var>-<var title="">context</var></code>, for example,
+ <code>moz-3d</code>. Such contexts should be registered in the
+ WHATWG Wiki CanvasContexts page.</p>
+
+ </div>
+
+ <hr/><dl class="domintro"><dt><var title="">url</var> = <var title="">canvas</var> . <code title="dom-canvas-toDataURL"><a href="#dom-canvas-todataurl">toDataURL</a></code>( [ <var title="">type</var>, ... ])</dt>
+
+ <dd>
+
+ <p>Returns a <a href="#data-protocol" title="data protocol"><code title="">data:</code> URL</a> for the image in the canvas.</p>
+
+ <p>The first argument, if provided, controls the type of the image
+ to be returned (e.g. PNG or JPEG). The default is <code title="">image/png</code>; that type is also used if the given
+ type isn't supported. The other arguments are specific to the
+ type, and control the way that the image is generated, as given in
+ the table below.</p>
+
+ <p>When trying to use types other than &quot;<code>image/png</code>&quot;,
+ authors can check if the image was really returned in the
+ requested format by checking to see if the returned string starts
+ with one of the exact strings &quot;<code title="">data:image/png,</code>&quot; or &quot;<code title="">data:image/png;</code>&quot;. If it does, the image is PNG,
+ and thus the requested type was not supported. (The one exception
+ to this is if the canvas has either no height or no width, in
+ which case the result might simply be &quot;<code title="">data:,</code>&quot;.)</p>
+
+ </dd>
+
+ <dt><var title="">canvas</var> . <code title="dom-canvas-toBlob"><a href="#dom-canvas-toblob">toBlob</a></code>(<var title="">callback</var> [, <var title="">type</var>, ... ])</dt>
+
+ <dd>
+
+ <p>Creates a <code><a href="#blob">Blob</a></code> object representing a file
+ containing the image in the canvas, and invokes a callback with a
+ handle to that object.</p>
+
+ <p>The second argument, if provided, controls the type of the
+ image to be returned (e.g. PNG or JPEG). The default is <code title="">image/png</code>; that type is also used if the given
+ type isn't supported. The other arguments are specific to the
+ type, and control the way that the image is generated, as given in
+ the table below.</p>
+
+ </dd>
+
+ </dl><div class="impl">
+
+ <p>The <dfn id="dom-canvas-todataurl" title="dom-canvas-toDataURL"><code>toDataURL()</code></dfn> method
+ must run the following steps:</p>
+
+ <ol><li><p>If the canvas has no pixels (i.e. either its horizontal
+ dimension or its vertical dimension is zero) then return the string
+ &quot;<code title="">data:,</code>&quot; and abort these steps. (This is the
+ shortest <a href="#data-protocol" title="data protocol"><code title="">data:</code>
+ URL</a>; it represents the empty string in a <code title="">text/plain</code> resource.)</p></li>
+
+ <li><p>Let <var title="">file</var> be <a href="#a-serialization-of-the-image-as-a-file">a serialization of the
+ image as a file</a>, using the method's arguments (if any) as
+ the <var title="">arguments</var>.</p></li>
+
+ <li><p>Return a <a href="#data-protocol" title="data protocol"><code title="">data:</code> URL</a> representing <var title="">file</var>. <a href="#refsRFC2397">[RFC2397]</a></p>
+
+ <!-- should we explicitly require the URL to be base64-encoded and
+ not have any parameters, to ensure the same exact URL is generated
+ in each browser? -->
+
+ </li></ol><p>The <dfn id="dom-canvas-toblob" title="dom-canvas-toBlob"><code>toBlob()</code></dfn> method
+ must run the following steps:</p>
+
+ <ol><li><p>Let <var title="">callback</var> be the first
+ argument.</p></li>
+
+ <li><p>Let <var title="">arguments</var> be the second and
+ subsequent arguments to the method, if any.</p></li>
+
+ <li><p>Let <var title="">file</var> be <a href="#a-serialization-of-the-image-as-a-file">a serialization of the
+ image as a file</a>, using <var title="">arguments</var>.</p></li>
+
+ <li><p>Return, but continue running these steps
+ asynchronously.</p></li>
+
+ <li><p>If <var title="">callback</var> is null, abort these
+ steps.</p></li>
+
+ <li><p><a href="#queue-a-task">Queue a task</a> to invoke the
+ <code>FileCallback</code> <var title="">callback</var> with a
+ <code><a href="#blob">Blob</a></code> object representing <var title="">file</var> as
+ its argument. The <a href="#task-source">task source</a> for this task is the
+ <dfn id="canvas-blob-serialization-task-source">canvas blob serialization task source</dfn>. <a href="#refsFILESYSTEMAPI">[FILESYSTEMAPI]</a> <a href="#refsFILEAPI">[FILEAPI]</a> </p></li>
+
+ </ol><p>When a user agent is to create <dfn id="a-serialization-of-the-image-as-a-file">a serialization of the image
+ as a file</dfn>, optionally with some given <var title="">arguments</var>, it must create an image file in the format
+ given by the first value of <var title="">arguments</var>, or, if
+ there are no <var title="">arguments</var>, in the PNG format. <a href="#refsPNG">[PNG]</a></p>
+
+ <p>If <var title="">arguments</var> is not empty, the first value
+ must be interpreted as a <a href="#mime-type" title="MIME type">MIME type</a>
+ giving the format to use. If the type has any parameters, it must be
+ treated as not supported.</p>
+
+ <p class="example">For example, the value &quot;<code>image/png</code>&quot; would
+ mean to generate a PNG image, the value &quot;<code>image/jpeg</code>&quot;
+ would mean to generate a JPEG image, and the value
+ &quot;<code>image/svg+xml</code>&quot; would mean to generate an SVG image
+ (which would probably require that the implementation actually keep
+ enough information to reliably render an SVG image from the canvas).</p>
+
+ <p>User agents must support PNG (&quot;<code>image/png</code>&quot;). User
+ agents may support other types. If the user agent does not support
+ the requested type, it must create the file using the PNG format. <a href="#refsPNG">[PNG]</a></p>
+
+ <p>User agents must <a href="#converted-to-ascii-lowercase" title="converted to ASCII
+ lowercase">convert the provided type to ASCII lowercase</a>
+ before establishing if they support that type.</p>
+
+ <p>For image types that do not support an alpha channel, the
+ serialized image must be the canvas image composited onto a solid
+ black background using the source-over operator.</p>
+
+ <p>If the first argument in <var title="">arguments</var> gives a
+ type corresponding to one of the types given in the first column of
+ the following table, and the user agent supports that type, then the
+ subsequent arguments, if any, must be treated as described in the
+ second cell of that row.</p>
+
+ </div>
+
+ <table><thead><tr><th> Type </th><th> Other arguments </th><th> Reference
+ </th></tr></thead><tbody><tr><td> <code>image/jpeg</code>
+ </td><td> The second argument<span class="impl">, if it</span> is a
+ number in the range 0.0 to 1.0 inclusive<span class="impl">, must
+ be</span> treated as the desired quality level. <span class="impl">If it is not a number or is outside that range, the
+ user agent must use its default value, as if the argument had
+ been omitted.</span>
+ </td><td> <a href="#refsJPEG">[JPEG]</a>
+ </td></tr></tbody></table><div class="impl">
+
+ <p>For the purposes of these rules, an argument is considered to be
+ a number if it is converted to an IDL double value by the rules for
+ handling arguments of type <code title="">any</code> in the Web IDL
+ specification. <a href="#refsWEBIDL">[WEBIDL]</a></p>
+
+ <p>Other arguments must be ignored and must not cause the user agent
+ to raise an exception. A future version of this specification will
+ probably define other parameters to be passed to these methods to
+ allow authors to more carefully control compression settings, image
+ metadata, etc.</p>
+
+ </div>
+
+ <!--2DCONTEXT-->
+
+ <div data-component="HTML Canvas 2D Context (editor: Ian Hickson)">
+
+ <h5 id="2dcontext"><span class="secno">4.8.11.1 </span>The 2D context</h5>
+
+ <!-- v2: we're on v4.1. suggestions for next version are marked v5, v6. -->
+
+
+
+ <p>This specification defines the <dfn id="canvas-context-2d" title="canvas-context-2d"><code>2d</code></dfn> context type, whose
+ API is implemented using the <code><a href="#canvasrenderingcontext2d">CanvasRenderingContext2D</a></code>
+ interface.</p>
+
+ <div class="impl">
+
+ <p>When the <code title="dom-canvas-getContext"><a href="#dom-canvas-getcontext">getContext()</a></code>
+ method of a <code><a href="#the-canvas-element">canvas</a></code> element is to <a href="#getcontext-return" title="getContext-return">return a new object for the <var title="">contextId</var></a> <code title="canvas-context-2d"><a href="#canvas-context-2d">2d</a></code>, the user agent must return a
+ new <code><a href="#canvasrenderingcontext2d">CanvasRenderingContext2D</a></code> object. Any additional
+ arguments are ignored.</p>
+
+ </div>
+
+ <p>The 2D context represents a flat Cartesian surface whose origin
+ (0,0) is at the top left corner, with the coordinate space having
+ <var title="">x</var> values increasing when going right, and <var title="">y</var> values increasing when going down.</p>
+
+ <pre class="idl">interface <dfn id="canvasrenderingcontext2d">CanvasRenderingContext2D</dfn> {
+
+ // back-reference to the canvas
+ readonly attribute <a href="#htmlcanvaselement">HTMLCanvasElement</a> <a href="#dom-context-2d-canvas" title="dom-context-2d-canvas">canvas</a>;
+
+ // state
+ void <a href="#dom-context-2d-save" title="dom-context-2d-save">save</a>(); // push state on state stack
+ void <a href="#dom-context-2d-restore" title="dom-context-2d-restore">restore</a>(); // pop state stack and restore state
+<!--
+ // v6 we've also received requests for:
+ attribute boolean <span title="dom-context-2d-forceHighQuality">forceHighQuality</span> // (default false)
+ // when enabled, it would prevent the UA from falling back on lower-quality but faster rendering routines
+ // useful e.g. for when an image manipulation app uses <canvas> both for UI previews and the actual work
+-->
+ // transformations (default transform is the identity matrix)
+ void <a href="#dom-context-2d-scale" title="dom-context-2d-scale">scale</a>(in double x, in double y);
+ void <a href="#dom-context-2d-rotate" title="dom-context-2d-rotate">rotate</a>(in double angle);
+ void <a href="#dom-context-2d-translate" title="dom-context-2d-translate">translate</a>(in double x, in double y);
+ void <a href="#dom-context-2d-transform" title="dom-context-2d-transform">transform</a>(in double a, in double b, in double c, in double d, in double e, in double f);
+ void <a href="#dom-context-2d-settransform" title="dom-context-2d-setTransform">setTransform</a>(in double a, in double b, in double c, in double d, in double e, in double f);
+<!--
+ // v6 we've also received requests for:
+ void skew(...);
+ void reflect(...); // or mirror(...)
+-->
+ // compositing
+ attribute double <a href="#dom-context-2d-globalalpha" title="dom-context-2d-globalAlpha">globalAlpha</a>; // (default 1.0)
+ attribute DOMString <a href="#dom-context-2d-globalcompositeoperation" title="dom-context-2d-globalCompositeOperation">globalCompositeOperation</a>; // (default source-over)
+<!--
+ // v6 we've also received requests for:
+ - turning off antialiasing to avoid seams when patterns are painted next to each other
+ - might be better to overdraw?
+ - might be better to just draw at a higher res then downsample, like for 3d?
+ - nested layers
+ - the ability to composite an entire set of drawing operations with one shadow all at once
+ http://lists.whatwg.org/pipermail/whatwg-whatwg.org/2008-August/015567.html
+-->
+ // colors and styles
+ attribute any <a href="#dom-context-2d-strokestyle" title="dom-context-2d-strokeStyle">strokeStyle</a>; // (default black)
+ attribute any <a href="#dom-context-2d-fillstyle" title="dom-context-2d-fillStyle">fillStyle</a>; // (default black)
+ <a href="#canvasgradient">CanvasGradient</a> <a href="#dom-context-2d-createlineargradient" title="dom-context-2d-createLinearGradient">createLinearGradient</a>(in double x0, in double y0, in double x1, in double y1);
+ <a href="#canvasgradient">CanvasGradient</a> <a href="#dom-context-2d-createradialgradient" title="dom-context-2d-createRadialGradient">createRadialGradient</a>(in double x0, in double y0, in double r0, in double x1, in double y1, in double r1);
+ <a href="#canvaspattern">CanvasPattern</a> <a href="#dom-context-2d-createpattern" title="dom-context-2d-createPattern">createPattern</a>(in <a href="#htmlimageelement">HTMLImageElement</a> image, in DOMString repetition);
+ <a href="#canvaspattern">CanvasPattern</a> <a href="#dom-context-2d-createpattern" title="dom-context-2d-createPattern">createPattern</a>(in <a href="#htmlcanvaselement">HTMLCanvasElement</a> image, in DOMString repetition);
+ <a href="#canvaspattern">CanvasPattern</a> <a href="#dom-context-2d-createpattern" title="dom-context-2d-createPattern">createPattern</a>(in <a href="#htmlvideoelement">HTMLVideoElement</a> image, in DOMString repetition);
+
+ // line caps/joins
+ attribute double <a href="#dom-context-2d-linewidth" title="dom-context-2d-lineWidth">lineWidth</a>; // (default 1)
+ attribute DOMString <a href="#dom-context-2d-linecap" title="dom-context-2d-lineCap">lineCap</a>; // &quot;butt&quot;, &quot;round&quot;, &quot;square&quot; (default &quot;butt&quot;)
+ attribute DOMString <a href="#dom-context-2d-linejoin" title="dom-context-2d-lineJoin">lineJoin</a>; // &quot;round&quot;, &quot;bevel&quot;, &quot;miter&quot; (default &quot;miter&quot;)
+ attribute double <a href="#dom-context-2d-miterlimit" title="dom-context-2d-miterLimit">miterLimit</a>; // (default 10)
+
+ // shadows
+ attribute double <a href="#dom-context-2d-shadowoffsetx" title="dom-context-2d-shadowOffsetX">shadowOffsetX</a>; // (default 0)
+ attribute double <a href="#dom-context-2d-shadowoffsety" title="dom-context-2d-shadowOffsetY">shadowOffsetY</a>; // (default 0)
+ attribute double <a href="#dom-context-2d-shadowblur" title="dom-context-2d-shadowBlur">shadowBlur</a>; // (default 0)
+ attribute DOMString <a href="#dom-context-2d-shadowcolor" title="dom-context-2d-shadowColor">shadowColor</a>; // (default transparent black)
+
+ // rects
+ void <a href="#dom-context-2d-clearrect" title="dom-context-2d-clearRect">clearRect</a>(in double x, in double y, in double w, in double h);
+ void <a href="#dom-context-2d-fillrect" title="dom-context-2d-fillRect">fillRect</a>(in double x, in double y, in double w, in double h);
+ void <a href="#dom-context-2d-strokerect" title="dom-context-2d-strokeRect">strokeRect</a>(in double x, in double y, in double w, in double h);
+
+ // path API
+ void <a href="#dom-context-2d-beginpath" title="dom-context-2d-beginPath">beginPath</a>();
+ void <a href="#dom-context-2d-closepath" title="dom-context-2d-closePath">closePath</a>();
+ void <a href="#dom-context-2d-moveto" title="dom-context-2d-moveTo">moveTo</a>(in double x, in double y);
+ void <a href="#dom-context-2d-lineto" title="dom-context-2d-lineTo">lineTo</a>(in double x, in double y);
+ void <a href="#dom-context-2d-quadraticcurveto" title="dom-context-2d-quadraticCurveTo">quadraticCurveTo</a>(in double cpx, in double cpy, in double x, in double y);
+ void <a href="#dom-context-2d-beziercurveto" title="dom-context-2d-bezierCurveTo">bezierCurveTo</a>(in double cp1x, in double cp1y, in double cp2x, in double cp2y, in double x, in double y);
+ void <a href="#dom-context-2d-arcto" title="dom-context-2d-arcTo">arcTo</a>(in double x1, in double y1, in double x2, in double y2, in double radius);
+ void <a href="#dom-context-2d-rect" title="dom-context-2d-rect">rect</a>(in double x, in double y, in double w, in double h);
+ void <a href="#dom-context-2d-arc" title="dom-context-2d-arc">arc</a>(in double x, in double y, in double radius, in double startAngle, in double endAngle, in optional boolean anticlockwise);
+ void <a href="#dom-context-2d-fill" title="dom-context-2d-fill">fill</a>();
+ void <a href="#dom-context-2d-stroke" title="dom-context-2d-stroke">stroke</a>();
+ void <a href="#dom-context-2d-drawsystemfocusring" title="dom-context-2d-drawSystemFocusRing">drawSystemFocusRing</a>(in <a href="#element">Element</a> element);
+ boolean <a href="#dom-context-2d-drawcustomfocusring" title="dom-context-2d-drawCustomFocusRing">drawCustomFocusRing</a>(in <a href="#element">Element</a> element);
+ void <a href="#dom-context-2d-scrollpathintoview" title="dom-context-2d-scrollPathIntoView">scrollPathIntoView</a>();
+ void <a href="#dom-context-2d-clip" title="dom-context-2d-clip">clip</a>();
+ boolean <a href="#dom-context-2d-ispointinpath" title="dom-context-2d-isPointInPath">isPointInPath</a>(in double x, in double y);
+
+ // text
+ attribute DOMString <a href="#dom-context-2d-font" title="dom-context-2d-font">font</a>; // (default 10px sans-serif)
+ attribute DOMString <a href="#dom-context-2d-textalign" title="dom-context-2d-textAlign">textAlign</a>; // &quot;start&quot;, &quot;end&quot;, &quot;left&quot;, &quot;right&quot;, &quot;center&quot; (default: &quot;start&quot;)
+ attribute DOMString <a href="#dom-context-2d-textbaseline" title="dom-context-2d-textBaseline">textBaseline</a>; // &quot;top&quot;, &quot;hanging&quot;, &quot;middle&quot;, &quot;alphabetic&quot;, &quot;ideographic&quot;, &quot;bottom&quot; (default: &quot;alphabetic&quot;)
+ void <a href="#dom-context-2d-filltext" title="dom-context-2d-fillText">fillText</a>(in DOMString text, in double x, in double y, in optional double maxWidth);
+ void <a href="#dom-context-2d-stroketext" title="dom-context-2d-strokeText">strokeText</a>(in DOMString text, in double x, in double y, in optional double maxWidth);<!-- v6DVT
+ void <span title="dom-context-2d-fillVerticalText">fillVerticalText</span>(in DOMString text, in double x, in double y, in optional double maxHeight);
+ void <span title="dom-context-2d-strokeVerticalText">strokeVerticalText</span>(in DOMString text, in double x, in double y, in optional double maxHeight); -->
+ <a href="#textmetrics">TextMetrics</a> <a href="#dom-context-2d-measuretext" title="dom-context-2d-measureText">measureText</a>(in DOMString text);
+
+ // drawing images
+ void <a href="#dom-context-2d-drawimage" title="dom-context-2d-drawImage">drawImage</a>(in <a href="#htmlimageelement">HTMLImageElement</a> image, in double dx, in double dy);
+ void <a href="#dom-context-2d-drawimage" title="dom-context-2d-drawImage">drawImage</a>(in <a href="#htmlimageelement">HTMLImageElement</a> image, in double dx, in double dy, in double dw, in double dh);
+ void <a href="#dom-context-2d-drawimage" title="dom-context-2d-drawImage">drawImage</a>(in <a href="#htmlimageelement">HTMLImageElement</a> image, in double sx, in double sy, in double sw, in double sh, in double dx, in double dy, in double dw, in double dh);
+ void <a href="#dom-context-2d-drawimage" title="dom-context-2d-drawImage">drawImage</a>(in <a href="#htmlcanvaselement">HTMLCanvasElement</a> image, in double dx, in double dy);
+ void <a href="#dom-context-2d-drawimage" title="dom-context-2d-drawImage">drawImage</a>(in <a href="#htmlcanvaselement">HTMLCanvasElement</a> image, in double dx, in double dy, in double dw, in double dh);
+ void <a href="#dom-context-2d-drawimage" title="dom-context-2d-drawImage">drawImage</a>(in <a href="#htmlcanvaselement">HTMLCanvasElement</a> image, in double sx, in double sy, in double sw, in double sh, in double dx, in double dy, in double dw, in double dh);
+ void <a href="#dom-context-2d-drawimage" title="dom-context-2d-drawImage">drawImage</a>(in <a href="#htmlvideoelement">HTMLVideoElement</a> image, in double dx, in double dy);
+ void <a href="#dom-context-2d-drawimage" title="dom-context-2d-drawImage">drawImage</a>(in <a href="#htmlvideoelement">HTMLVideoElement</a> image, in double dx, in double dy, in double dw, in double dh);
+ void <a href="#dom-context-2d-drawimage" title="dom-context-2d-drawImage">drawImage</a>(in <a href="#htmlvideoelement">HTMLVideoElement</a> image, in double sx, in double sy, in double sw, in double sh, in double dx, in double dy, in double dw, in double dh);
+
+ // pixel manipulation
+ <a href="#imagedata">ImageData</a> <a href="#dom-context-2d-createimagedata" title="dom-context-2d-createImageData">createImageData</a>(in double sw, in double sh);
+ <a href="#imagedata">ImageData</a> <a href="#dom-context-2d-createimagedata" title="dom-context-2d-createImageData">createImageData</a>(in <a href="#imagedata">ImageData</a> imagedata);
+ <a href="#imagedata">ImageData</a> <a href="#dom-context-2d-getimagedata" title="dom-context-2d-getImageData">getImageData</a>(in double sx, in double sy, in double sw, in double sh);
+ void <a href="#dom-context-2d-putimagedata" title="dom-context-2d-putImageData">putImageData</a>(in <a href="#imagedata">ImageData</a> imagedata, in double dx, in double dy);
+ void <a href="#dom-context-2d-putimagedata" title="dom-context-2d-putImageData">putImageData</a>(in <a href="#imagedata">ImageData</a> imagedata, in double dx, in double dy, in double dirtyX, in double dirtyY, in double dirtyWidth, in double dirtyHeight);
+};
+
+interface <dfn id="canvasgradient">CanvasGradient</dfn> {
+ // opaque object
+ void <a href="#dom-canvasgradient-addcolorstop" title="dom-canvasgradient-addColorStop">addColorStop</a>(in double offset, in DOMString color);
+};
+
+interface <dfn id="canvaspattern">CanvasPattern</dfn> {
+ // opaque object
+};
+
+interface <dfn id="textmetrics">TextMetrics</dfn> {
+ readonly attribute double <a href="#dom-textmetrics-width" title="dom-textmetrics-width">width</a>;
+};
+
+interface <dfn id="imagedata">ImageData</dfn> {
+ readonly attribute unsigned long <a href="#dom-imagedata-width" title="dom-imagedata-width">width</a>;
+ readonly attribute unsigned long <a href="#dom-imagedata-height" title="dom-imagedata-height">height</a>;
+ readonly attribute <a href="#canvaspixelarray">CanvasPixelArray</a> <a href="#dom-imagedata-data" title="dom-imagedata-data">data</a>;
+};
+
+interface <dfn id="canvaspixelarray">CanvasPixelArray</dfn> {
+ readonly attribute unsigned long <a href="#dom-canvaspixelarray-length" title="dom-canvaspixelarray-length">length</a>;
+ <a href="#dom-canvaspixelarray-get" title="dom-CanvasPixelArray-get">getter</a> octet (in unsigned long index);
+ <a href="#dom-canvaspixelarray-set" title="dom-CanvasPixelArray-set">setter</a> void (in unsigned long index, [Clamp] in octet value);
+};</pre>
+
+ <dl class="domintro"><dt><var title="">context</var> . <code title="dom-context-2d-canvas"><a href="#dom-context-2d-canvas">canvas</a></code></dt>
+
+ <dd>
+
+ <p>Returns the <code><a href="#the-canvas-element">canvas</a></code> element.</p>
+
+ </dd>
+
+ </dl><div class="impl">
+
+ <p>The <dfn id="dom-context-2d-canvas" title="dom-context-2d-canvas"><code>canvas</code></dfn>
+ attribute must return the <code><a href="#the-canvas-element">canvas</a></code> element that the
+ context paints on.</p>
+
+ <p>Except where otherwise specified, for the 2D context interface,
+ any method call with a numeric argument whose value is infinite or a
+ NaN value must be ignored.</p>
+
+ <!--
+ Philip Taylor wrote:
+ > My experience with some 3d canvas code is that infinities come up in
+ > naturally harmless places, e.g. having a function that scales by x then
+ > translates by 1/x and wanting it to work when x=0 (which ought to draw
+ > nothing, since anything it draws is zero pixels wide), and it's a bit
+ > annoying to track down and fix those issues, so I'd probably like it if
+ > they were harmless in canvas methods. Opera appears to silently not draw
+ > anything if the transformation matrix is not finite, but Firefox throws
+ > exceptions when passing in non-finite arguments.
+ -->
+
+ <p>Whenever the CSS value <code title="">currentColor</code> is used
+ as a color in this API, the &quot;computed value of the 'color' property&quot;
+ for the purposes of determining the computed value of the <code title="">currentColor</code> keyword is the computed value of the
+ 'color' property on the element in question at the time that the
+ color is specified (e.g. when the appropriate attribute is set, or
+ when the method is called; not when the color is rendered or
+ otherwise used). If the computed value of the 'color' property is
+ undefined for a particular case (e.g. because the element is not
+ <a href="#in-a-document">in a <code>Document</code></a>), then the &quot;computed value
+ of the 'color' property&quot; for the purposes of determining the
+ computed value of the <code title="">currentColor</code> keyword is
+ fully opaque black. <a href="#refsCSSCOLOR">[CSSCOLOR]</a></p>
+
+ <p>In the case of <code title="dom-canvasgradient-addColorStop"><a href="#dom-canvasgradient-addcolorstop">addColorStop()</a></code> on
+ <code><a href="#canvasgradient">CanvasGradient</a></code>, the &quot;computed value of the 'color'
+ property&quot; for the purposes of determining the computed value of the
+ <code title="">currentColor</code> keyword is always fully opaque
+ black (there is no associated element). <a href="#refsCSSCOLOR">[CSSCOLOR]</a></p>
+
+ <p class="note">This is because <code><a href="#canvasgradient">CanvasGradient</a></code> objects
+ are <code><a href="#the-canvas-element">canvas</a></code>-neutral — a
+ <code><a href="#canvasgradient">CanvasGradient</a></code> object created by one
+ <code><a href="#the-canvas-element">canvas</a></code> can be used by another, and there is therefore
+ no way to know which is the &quot;element in question&quot; at the time that
+ the color is specified.</p>
+
+ </div>
+
+
+
+ <h6 id="the-canvas-state"><span class="secno">4.8.11.1.1 </span>The canvas state</h6>
+
+ <p>Each context maintains a stack of drawing states. <dfn id="drawing-state" title="drawing state">Drawing states</dfn> consist of:</p>
+
+ <ul class="brief"><li>The current <a href="#transformations" title="dom-context-2d-transformation">transformation matrix</a>.</li>
+ <li>The current <a href="#clipping-region">clipping region</a>.</li>
+ <li>The current values of the following attributes: <code title="dom-context-2d-strokeStyle"><a href="#dom-context-2d-strokestyle">strokeStyle</a></code>, <code title="dom-context-2d-fillStyle"><a href="#dom-context-2d-fillstyle">fillStyle</a></code>, <code title="dom-context-2d-globalAlpha"><a href="#dom-context-2d-globalalpha">globalAlpha</a></code>, <code title="dom-context-2d-lineWidth"><a href="#dom-context-2d-linewidth">lineWidth</a></code>, <code title="dom-context-2d-lineCap"><a href="#dom-context-2d-linecap">lineCap</a></code>, <code title="dom-context-2d-lineJoin"><a href="#dom-context-2d-linejoin">lineJoin</a></code>, <code title="dom-context-2d-miterLimit"><a href="#dom-context-2d-miterlimit">miterLimit</a></code>, <code title="dom-context-2d-shadowOffsetX"><a href="#dom-context-2d-shadowoffsetx">shadowOffsetX</a></code>, <code title="dom-context-2d-shadowOffsetY"><a href="#dom-context-2d-shadowoffsety">shadowOffsetY</a></code>, <code title="dom-context-2d-shadowBlur"><a href="#dom-context-2d-shadowblur">shadowBlur</a></code>, <code title="dom-context-2d-shadowColor"><a href="#dom-context-2d-shadowcolor">shadowColor</a></code>, <code title="dom-context-2d-globalCompositeOperation"><a href="#dom-context-2d-globalcompositeoperation">globalCompositeOperation</a></code>, <code title="dom-context-2d-font"><a href="#dom-context-2d-font">font</a></code>, <code title="dom-context-2d-textAlign"><a href="#dom-context-2d-textalign">textAlign</a></code>, <code title="dom-context-2d-textBaseline"><a href="#dom-context-2d-textbaseline">textBaseline</a></code>.</li>
+ </ul><p class="note">The current path and the current bitmap are not part
+ of the drawing state. The current path is persistent, and can only
+ be reset using the <code title="dom-context-2d-beginPath"><a href="#dom-context-2d-beginpath">beginPath()</a></code> method. The
+ current bitmap is a property of the canvas, not the context.</p>
+
+ <dl class="domintro"><dt><var title="">context</var> . <code title="dom-context-2d-save"><a href="#dom-context-2d-save">save</a></code>()</dt>
+
+ <dd>
+
+ <p>Pushes the current state onto the stack.</p>
+
+ </dd>
+
+ <dt><var title="">context</var> . <code title="dom-context-2d-restore"><a href="#dom-context-2d-restore">restore</a></code>()</dt>
+
+ <dd>
+
+ <p>Pops the top state on the stack, restoring the context to that state.</p>
+
+ </dd>
+
+ </dl><div class="impl">
+
+ <p>The <dfn id="dom-context-2d-save" title="dom-context-2d-save"><code>save()</code></dfn>
+ method must push a copy of the current drawing state onto the
+ drawing state stack.</p>
+
+ <p>The <dfn id="dom-context-2d-restore" title="dom-context-2d-restore"><code>restore()</code></dfn> method
+ must pop the top entry in the drawing state stack, and reset the
+ drawing state it describes. If there is no saved state, the method
+ must do nothing.</p>
+
+ <!-- v6
+idea from Mihai:
+> 5. Drawing states should be saveable with IDs, and for easier restoring.
+>
+> save(id)
+> restore(id)
+>
+> If id is not provided, then save() works as defined now. The same for
+> restore().
+>
+> Currently, it's not trivial to save and restore a specific state.
+...and from Philip:
+> I think a more convenient syntax would be:
+> var state = ctx.save();
+> ctx.restore(state);
+> But how would it interact with normal calls to ctx.restore()?
+ -->
+
+ </div>
+
+
+ <h6 id="transformations"><span class="secno">4.8.11.1.2 </span><dfn title="dom-context-2d-transformation">Transformations</dfn></h6>
+
+ <p>The transformation matrix is applied to coordinates when creating
+ shapes and paths.</p> <!-- conformance criteria for actual drawing
+ are described in the various sections below -->
+
+ <div class="impl">
+
+ <p>When the context is created, the transformation matrix must
+ initially be the identity transform. It may then be adjusted using
+ the transformation methods.</p>
+
+ <p>The transformations must be performed in reverse order. For
+ instance, if a scale transformation that doubles the width is
+ applied, followed by a rotation transformation that rotates drawing
+ operations by a quarter turn, and a rectangle twice as wide as it is
+ tall is then drawn on the canvas, the actual result will be a
+ square.</p>
+
+ </div>
+
+ <dl class="domintro"><dt><var title="">context</var> . <code title="dom-context-2d-scale"><a href="#dom-context-2d-scale">scale</a></code>(<var title="">x</var>, <var title="">y</var>)</dt>
+
+ <dd>
+
+ <p>Changes the transformation matrix to apply a scaling transformation with the given characteristics.</p>
+
+ </dd>
+
+ <dt><var title="">context</var> . <code title="dom-context-2d-rotate"><a href="#dom-context-2d-rotate">rotate</a></code>(<var title="">angle</var>)</dt>
+
+ <dd>
+
+ <p>Changes the transformation matrix to apply a rotation transformation with the given characteristics. The angle is in radians.</p>
+
+ </dd>
+
+ <dt><var title="">context</var> . <code title="dom-context-2d-translate"><a href="#dom-context-2d-translate">translate</a></code>(<var title="">x</var>, <var title="">y</var>)</dt>
+
+ <dd>
+
+ <p>Changes the transformation matrix to apply a translation transformation with the given characteristics.</p>
+
+ </dd>
+
+ <dt><var title="">context</var> . <code title="dom-context-2d-transform"><a href="#dom-context-2d-transform">transform</a></code>(<var title="">a</var>, <var title="">b</var>, <var title="">c</var>, <var title="">d</var>, <var title="">e</var>, <var title="">f</var>)</dt>
+
+ <dd>
+
+ <p>Changes the transformation matrix to apply the matrix given by the arguments as described below.</p>
+
+ </dd>
+
+ <dt><var title="">context</var> . <code title="dom-context-2d-setTransform"><a href="#dom-context-2d-settransform">setTransform</a></code>(<var title="">a</var>, <var title="">b</var>, <var title="">c</var>, <var title="">d</var>, <var title="">e</var>, <var title="">f</var>)</dt>
+
+ <dd>
+
+ <p>Changes the transformation matrix <em>to</em> the matrix given by the arguments as described below.</p>
+
+ </dd>
+
+ </dl><div class="impl">
+
+ <p>The <dfn id="dom-context-2d-scale" title="dom-context-2d-scale"><code>scale(<var title="">x</var>, <var title="">y</var>)</code></dfn> method must
+ add the scaling transformation described by the arguments to the
+ transformation matrix. The <var title="">x</var> argument represents
+ the scale factor in the horizontal direction and the <var title="">y</var> argument represents the scale factor in the
+ vertical direction. The factors are multiples.</p>
+
+ <p>The <dfn id="dom-context-2d-rotate" title="dom-context-2d-rotate"><code>rotate(<var title="">angle</var>)</code></dfn> method must add the rotation
+ transformation described by the argument to the transformation
+ matrix. The <var title="">angle</var> argument represents a
+ clockwise rotation angle expressed in radians.</p>
+
+ <p>The <dfn id="dom-context-2d-translate" title="dom-context-2d-translate"><code>translate(<var title="">x</var>, <var title="">y</var>)</code></dfn> method must
+ add the translation transformation described by the arguments to the
+ transformation matrix. The <var title="">x</var> argument represents
+ the translation distance in the horizontal direction and the <var title="">y</var> argument represents the translation distance in the
+ vertical direction. The arguments are in coordinate space units.</p>
+
+ <p>The <dfn id="dom-context-2d-transform" title="dom-context-2d-transform"><code>transform(<var title="">a</var>, <var title="">b</var>, <var title="">c</var>, <var title="">d</var>, <var title="">e</var>, <var title="">f</var>)</code></dfn> method must replace the current
+ transformation matrix with the result of multiplying the current
+ transformation matrix with the matrix described by:</p>
+
+ </div>
+
+ <table class="matrix"><tbody><tr><td><var title="">a</var></td>
+ <td><var title="">c</var></td>
+ <td><var title="">e</var></td>
+ </tr><tr><td><var title="">b</var></td>
+ <td><var title="">d</var></td>
+ <td><var title="">f</var></td>
+ </tr><tr><td>0</td>
+ <td>0</td>
+ <td>1</td>
+ </tr></tbody></table><p class="note">The arguments <var title="">a</var>, <var title="">b</var>, <var title="">c</var>, <var title="">d</var>, <var title="">e</var>, and <var title="">f</var> are sometimes called
+ <var title="">m11</var>, <var title="">m12</var>, <var title="">m21</var>, <var title="">m22</var>, <var title="">dx</var>,
+ and <var title="">dy</var> or <var title="">m11</var>, <var title="">m21</var>, <var title="">m12</var>, <var title="">m22</var>, <var title="">dx</var>, and <var title="">dy</var>. Care should be taken in particular with the order
+ of the second and third arguments (<var title="">b</var> and <var title="">c</var>) as their order varies from API to API and APIs
+ sometimes use the notation <var title="">m12</var>/<var title="">m21</var> and sometimes <var title="">m21</var>/<var title="">m12</var> for those positions.</p>
+
+ <div class="impl">
+
+ <p>The <dfn id="dom-context-2d-settransform" title="dom-context-2d-setTransform"><code>setTransform(<var title="">a</var>, <var title="">b</var>, <var title="">c</var>, <var title="">d</var>, <var title="">e</var>,
+ <var title="">f</var>)</code></dfn> method must reset the current
+ transform to the identity matrix, and then invoke the <code><a href="#dom-context-2d-transform" title="dom-context-2d-transform">transform</a>(<var title="">a</var>, <var title="">b</var>, <var title="">c</var>, <var title="">d</var>, <var title="">e</var>,
+ <var title="">f</var>)</code> method with the same arguments.</p>
+
+ </div>
+
+
+ <h6 id="compositing"><span class="secno">4.8.11.1.3 </span>Compositing</h6>
+
+ <dl class="domintro"><dt><var title="">context</var> . <code title="dom-context-2d-globalAlpha"><a href="#dom-context-2d-globalalpha">globalAlpha</a></code> [ = <var title="">value</var> ]</dt>
+
+ <dd>
+
+ <p>Returns the current alpha value applied to rendering operations.</p>
+
+ <p>Can be set, to change the alpha value. Values outside of the
+ range 0.0 .. 1.0 are ignored.</p>
+
+ </dd>
+
+
+ <dt><var title="">context</var> . <code title="dom-context-2d-globalCompositeOperation"><a href="#dom-context-2d-globalcompositeoperation">globalCompositeOperation</a></code> [ = <var title="">value</var> ]</dt>
+
+ <dd>
+
+ <p>Returns the current composition operation, from the list below.</p>
+
+ <p>Can be set, to change the composition operation. Unknown values
+ are ignored.</p>
+
+ </dd>
+
+ </dl><div class="impl">
+
+ <p>All drawing operations are affected by the global compositing
+ attributes, <code title="dom-context-2d-globalAlpha"><a href="#dom-context-2d-globalalpha">globalAlpha</a></code> and <code title="dom-context-2d-globalCompositeOperation"><a href="#dom-context-2d-globalcompositeoperation">globalCompositeOperation</a></code>.</p>
+
+ <!-- conformance criteria for painting are described in the "drawing
+ model" section below -->
+
+ <p>The <dfn id="dom-context-2d-globalalpha" title="dom-context-2d-globalAlpha"><code>globalAlpha</code></dfn>
+ attribute gives an alpha value that is applied to shapes and images
+ before they are composited onto the canvas. The value must be in the
+ range from 0.0 (fully transparent) to 1.0 (no additional
+ transparency). If an attempt is made to set the attribute to a value
+ outside this range, including Infinity and Not-a-Number (NaN)
+ values, the attribute must retain its previous value. When the
+ context is created, the <code title="dom-context-2d-globalAlpha"><a href="#dom-context-2d-globalalpha">globalAlpha</a></code> attribute must
+ initially have the value 1.0.</p>
+
+ <p>The <dfn id="dom-context-2d-globalcompositeoperation" title="dom-context-2d-globalCompositeOperation"><code>globalCompositeOperation</code></dfn>
+ attribute sets how shapes and images are drawn onto the existing
+ bitmap, once they have had <code title="dom-context-2d-globalAlpha"><a href="#dom-context-2d-globalalpha">globalAlpha</a></code> and the
+ current transformation matrix applied. It must be set to a value
+ from the following list. In the descriptions below, the source
+ image, <var title="">A</var>, is the shape or image being rendered,
+ and the destination image, <var title="">B</var>, is the current
+ state of the bitmap.</p>
+
+ </div>
+
+ <dl><dt><dfn id="gcop-source-atop" title="gcop-source-atop"><code>source-atop</code></dfn></dt>
+
+ <dd><var title="">A</var> atop <var title="">B</var>. <span class="note">Display the
+ source image wherever both images are opaque. Display the
+ destination image wherever the destination image is opaque but the
+ source image is transparent. Display transparency elsewhere.</span></dd>
+
+ <dt><dfn id="gcop-source-in" title="gcop-source-in"><code>source-in</code></dfn></dt>
+
+ <dd><var title="">A</var> in <var title="">B</var>. <span class="note">Display the
+ source image wherever both the source image and destination image
+ are opaque. Display transparency elsewhere.</span></dd>
+
+ <dt><dfn id="gcop-source-out" title="gcop-source-out"><code>source-out</code></dfn></dt>
+
+ <dd><var title="">A</var> out <var title="">B</var>. <span class="note">Display the
+ source image wherever the source image is opaque and the
+ destination image is transparent. Display transparency
+ elsewhere.</span></dd>
+
+ <dt><dfn id="gcop-source-over" title="gcop-source-over"><code>source-over</code></dfn> (default)</dt>
+
+ <dd><var title="">A</var> over <var title="">B</var>. <span class="note">Display the
+ source image wherever the source image is opaque. Display the
+ destination image elsewhere.</span></dd>
+
+
+ <dt><dfn id="gcop-destination-atop" title="gcop-destination-atop"><code>destination-atop</code></dfn></dt>
+
+ <dd><var title="">B</var> atop <var title="">A</var>. <span class="note">Same as <code title="gcop-source-atop"><a href="#gcop-source-atop">source-atop</a></code> but using the
+ destination image instead of the source image and vice versa.</span></dd>
+
+ <dt><dfn id="gcop-destination-in" title="gcop-destination-in"><code>destination-in</code></dfn></dt>
+
+ <dd><var title="">B</var> in <var title="">A</var>. <span class="note">Same as <code title="gcop-source-in"><a href="#gcop-source-in">source-in</a></code> but using the destination
+ image instead of the source image and vice versa.</span></dd>
+
+ <dt><dfn id="gcop-destination-out" title="gcop-destination-out"><code>destination-out</code></dfn></dt>
+
+ <dd><var title="">B</var> out <var title="">A</var>. <span class="note">Same as <code title="gcop-source-out"><a href="#gcop-source-out">source-out</a></code> but using the destination
+ image instead of the source image and vice versa.</span></dd>
+
+ <dt><dfn id="gcop-destination-over" title="gcop-destination-over"><code>destination-over</code></dfn></dt>
+
+ <dd><var title="">B</var> over <var title="">A</var>. <span class="note">Same as <code title="gcop-source-over"><a href="#gcop-source-over">source-over</a></code> but using the
+ destination image instead of the source image and vice versa.</span></dd>
+
+
+<!-- no clear definition of this operator (doesn't correspond to a PorterDuff operator)
+ <dt><dfn title="gcop-darker"><code>darker</code></dfn></dt>
+
+ <dd><span class="note">Display the sum of the source image and destination image,
+ with color values approaching 0 as a limit.</span></dd>
+-->
+
+ <dt><dfn id="gcop-lighter" title="gcop-lighter"><code>lighter</code></dfn></dt>
+
+ <dd><var title="">A</var> plus <var title="">B</var>. <span class="note">Display the
+ sum of the source image and destination image, with color values
+ approaching 255 (100%) as a limit.</span></dd>
+
+
+ <dt><dfn id="gcop-copy" title="gcop-copy"><code>copy</code></dfn></dt>
+
+ <dd><var title="">A</var> (<var title="">B</var> is
+ ignored). <span class="note">Display the source image instead of the destination
+ image.</span></dd>
+
+
+ <dt><dfn id="gcop-xor" title="gcop-xor"><code>xor</code></dfn></dt>
+
+ <dd><var title="">A</var> xor <var title="">B</var>. <span class="note">Exclusive OR
+ of the source image and destination image.</span></dd>
+
+
+ <dt class="impl"><code><var title="">vendorName</var>-<var title="">operationName</var></code></dt>
+
+ <dd class="impl">Vendor-specific extensions to the list of
+ composition operators should use this syntax.</dd>
+
+ </dl><div class="impl">
+
+ <p>The operators in the above list must be treated as described by
+ the Porter-Duff operator given at the start of their description
+ (e.g. <var title="">A</var> over <var title="">B</var>). They are to
+ be applied as part of the <a href="#drawing-model">drawing model</a>, at which point the
+ <a href="#clipping-region">clipping region</a> is also applied. (Without a clipping
+ region, these operators act on the whole bitmap with every
+ operation.) <a href="#refsPORTERDUFF">[PORTERDUFF]</a></p>
+
+ <p>These values are all case-sensitive — they must be used
+ exactly as shown. User agents must not recognize values that are not
+ a <a href="#case-sensitive">case-sensitive</a> match for one of the values given
+ above.</p>
+
+ <p>On setting, if the user agent does not recognize the specified
+ value, it must be ignored, leaving the value of <code title="dom-context-2d-globalCompositeOperation"><a href="#dom-context-2d-globalcompositeoperation">globalCompositeOperation</a></code>
+ unaffected.</p>
+
+ <p>When the context is created, the <code title="dom-context-2d-globalCompositeOperation"><a href="#dom-context-2d-globalcompositeoperation">globalCompositeOperation</a></code>
+ attribute must initially have the value
+ <code>source-over</code>.</p>
+
+ </div>
+
+
+ <h6 id="colors-and-styles"><span class="secno">4.8.11.1.4 </span>Colors and styles</h6>
+
+ <dl class="domintro"><dt><var title="">context</var> . <code title="dom-context-2d-strokeStyle"><a href="#dom-context-2d-strokestyle">strokeStyle</a></code> [ = <var title="">value</var> ]</dt>
+
+ <dd>
+
+ <p>Returns the current style used for stroking shapes.</p>
+
+ <p>Can be set, to change the stroke style.</p>
+
+ <p>The style can be either a string containing a CSS color, or a
+ <code><a href="#canvasgradient">CanvasGradient</a></code> or <code><a href="#canvaspattern">CanvasPattern</a></code>
+ object. Invalid values are ignored.</p>
+
+ </dd>
+
+ <dt><var title="">context</var> . <code title="dom-context-2d-fillStyle"><a href="#dom-context-2d-fillstyle">fillStyle</a></code> [ = <var title="">value</var> ]</dt>
+
+ <dd>
+
+ <p>Returns the current style used for filling shapes.</p>
+
+ <p>Can be set, to change the fill style.</p>
+
+ <p>The style can be either a string containing a CSS color, or a
+ <code><a href="#canvasgradient">CanvasGradient</a></code> or <code><a href="#canvaspattern">CanvasPattern</a></code>
+ object. Invalid values are ignored.</p>
+
+ </dd>
+
+ </dl><div class="impl">
+
+ <!-- v6 feature requests:
+
+ * Getting and setting colours by component to bypass the CSS value parsing.
+
+ Either:
+ context.fillStyle.red += 1;
+
+ Or:
+ var array = context.fillStyle;
+ array[1] += 1;
+ context.fillStyle = array;
+
+ * A more performant way of setting colours in general, e.g.:
+
+ context.setFillColor(r,g,b,a) // already supported by webkit
+
+ Or:
+
+ context.fillStyle = 0xRRGGBBAA; // set a 32bit int directly
+
+ * fill rule for deciding between winding and even-odd algorithms.
+ SVG has fill-rule: nonzero | evenodd
+ http://www.w3.org/TR/SVG/painting.html#FillProperties
+
+ -->
+
+ <p>The <dfn id="dom-context-2d-strokestyle" title="dom-context-2d-strokeStyle"><code>strokeStyle</code></dfn>
+ attribute represents the color or style to use for the lines around
+ shapes, and the <dfn id="dom-context-2d-fillstyle" title="dom-context-2d-fillStyle"><code>fillStyle</code></dfn>
+ attribute represents the color or style to use inside the
+ shapes.</p>
+
+ <p>Both attributes can be either strings,
+ <code><a href="#canvasgradient">CanvasGradient</a></code>s, or <code><a href="#canvaspattern">CanvasPattern</a></code>s. On
+ setting, strings must be <a href="#parsed-as-a-css-color-value" title="parsed as a CSS &lt;color&gt;
+ value">parsed as CSS &lt;color&gt; values</a> and the color
+ assigned, and <code><a href="#canvasgradient">CanvasGradient</a></code> and
+ <code><a href="#canvaspattern">CanvasPattern</a></code> objects must be assigned themselves. <a href="#refsCSSCOLOR">[CSSCOLOR]</a> If the value is a string but
+ cannot be <a href="#parsed-as-a-css-color-value">parsed as a CSS &lt;color&gt; value</a>, or is
+ neither a string, a <code><a href="#canvasgradient">CanvasGradient</a></code>, nor a
+ <code><a href="#canvaspattern">CanvasPattern</a></code>, then it must be ignored, and the
+ attribute must retain its previous value.</p>
+
+ <p>When set to a <code><a href="#canvaspattern">CanvasPattern</a></code> or
+ <code><a href="#canvasgradient">CanvasGradient</a></code> object, the assignment is
+ <a href="#live">live</a>, meaning that changes made to the object after the
+ assignment do affect subsequent stroking or filling of shapes.</p>
+
+ <p>On getting, if the value is a color, then the <a href="#serialization-of-a-color" title="serialization of a color">serialization of the color</a>
+ must be returned. Otherwise, if it is not a color but a
+ <code><a href="#canvasgradient">CanvasGradient</a></code> or <code><a href="#canvaspattern">CanvasPattern</a></code>, then the
+ respective object must be returned. (Such objects are opaque and
+ therefore only useful for assigning to other attributes or for
+ comparison to other gradients or patterns.)</p>
+
+ <p>The <dfn id="serialization-of-a-color">serialization of a color</dfn> for a color value is a
+ string, computed as follows: if it has alpha equal to 1.0, then the
+ string is a lowercase six-digit hex value, prefixed with a &quot;#&quot;
+ character (U+0023 NUMBER SIGN), with the first two digits
+ representing the red component, the next two digits representing the
+ green component, and the last two digits representing the blue
+ component, the digits being in the range 0-9 a-f (U+0030 to U+0039
+ and U+0061 to U+0066). Otherwise, the color value has alpha less
+ than 1.0, and the string is the color value in the CSS <code title="">rgba()</code> functional-notation format: the literal
+ string <code title="">rgba</code> (U+0072 U+0067 U+0062 U+0061)
+ followed by a U+0028 LEFT PARENTHESIS, a base-ten integer in the
+ range 0-255 representing the red component (using digits 0-9, U+0030
+ to U+0039, in the shortest form possible), a literal U+002C COMMA
+ and U+0020 SPACE, an integer for the green component, a comma and a
+ space, an integer for the blue component, another comma and space, a
+ U+0030 DIGIT ZERO, if the alpha value is greater than zero then a
+ U+002E FULL STOP (representing the decimal point), if the alpha
+ value is greater than zero then one or more digits in the range 0-9
+ (U+0030 to U+0039) representing the fractional part of the alpha
+ value, and finally a U+0029 RIGHT PARENTHESIS.</p> <!-- if people
+ complain this is unreadable, expand it into a <dl> with two nested
+ <ol>s -->
+
+ <p>When the context is created, the <code title="dom-context-2d-strokeStyle"><a href="#dom-context-2d-strokestyle">strokeStyle</a></code> and <code title="dom-context-2d-fillStyle"><a href="#dom-context-2d-fillstyle">fillStyle</a></code> attributes must
+ initially have the string value <code title="">#000000</code>.</p>
+
+ </div>
+
+ <hr/><p>There are two types of gradients, linear gradients and radial
+ gradients, both represented by objects implementing the opaque
+ <code><a href="#canvasgradient">CanvasGradient</a></code> interface.</p>
+
+ <p id="interpolation">Once a gradient has been created (see below),
+ stops are placed along it to define how the colors are distributed
+ along the gradient. <span class="impl">The color of the gradient at
+ each stop is the color specified for that stop. Between each such
+ stop, the colors and the alpha component must be linearly
+ interpolated over the RGBA space without premultiplying the alpha
+ value to find the color to use at that offset. Before the first
+ stop, the color must be the color of the first stop. After the last
+ stop, the color must be the color of the last stop. When there are
+ no stops, the gradient is transparent black.</span></p>
+
+ <dl class="domintro"><dt><var title="">gradient</var> . <code title="dom-canvasgradient-addColorStop"><a href="#dom-canvasgradient-addcolorstop">addColorStop</a></code>(<var title="">offset</var>, <var title="">color</var>)</dt>
+
+ <dd>
+
+ <p>Adds a color stop with the given color to the gradient at the
+ given offset. 0.0 is the offset at one end of the gradient, 1.0 is
+ the offset at the other end.</p>
+
+ <p>Throws an <code><a href="#index_size_err">INDEX_SIZE_ERR</a></code> exception if the offset
+ is out of range. Throws a <code><a href="#syntax_err">SYNTAX_ERR</a></code> exception if the
+ color cannot be parsed.</p>
+
+ </dd>
+
+ <dt><var title="">gradient</var> = <var title="">context</var> . <code title="dom-context-2d-createLinearGradient"><a href="#dom-context-2d-createlineargradient">createLinearGradient</a></code>(<var title="">x0</var>, <var title="">y0</var>, <var title="">x1</var>, <var title="">y1</var>)</dt>
+
+ <dd>
+
+ <p>Returns a <code><a href="#canvasgradient">CanvasGradient</a></code> object that represents a
+ linear gradient that paints along the line given by the
+ coordinates represented by the arguments.</p>
+
+ <p>If any of the arguments are not finite numbers, throws a
+ <code><a href="#not_supported_err">NOT_SUPPORTED_ERR</a></code> exception.</p>
+
+ </dd>
+
+ <dt><var title="">gradient</var> = <var title="">context</var> . <code title="dom-context-2d-createRadialGradient"><a href="#dom-context-2d-createradialgradient">createRadialGradient</a></code>(<var title="">x0</var>, <var title="">y0</var>, <var title="">r0</var>, <var title="">x1</var>, <var title="">y1</var>, <var title="">r1</var>)</dt>
+
+ <dd>
+
+ <p>Returns a <code><a href="#canvasgradient">CanvasGradient</a></code> object that represents a
+ radial gradient that paints along the cone given by the circles
+ represented by the arguments.</p>
+
+ <p>If any of the arguments are not finite numbers, throws a
+ <code><a href="#not_supported_err">NOT_SUPPORTED_ERR</a></code> exception. If either of the radii
+ are negative, throws an <code><a href="#index_size_err">INDEX_SIZE_ERR</a></code> exception.</p>
+
+ </dd>
+
+ </dl><div class="impl">
+
+ <p>The <dfn id="dom-canvasgradient-addcolorstop" title="dom-canvasgradient-addColorStop"><code>addColorStop(<var title="">offset</var>, <var title="">color</var>)</code></dfn>
+ method on the <code><a href="#canvasgradient">CanvasGradient</a></code> interface adds a new stop
+ to a gradient. If the <var title="">offset</var> is less than 0,
+ greater than 1, infinite, or NaN, then an
+ <code><a href="#index_size_err">INDEX_SIZE_ERR</a></code> exception must be raised. If the <var title="">color</var> cannot be <a href="#parsed-as-a-css-color-value">parsed as a CSS &lt;color&gt;
+ value</a>, then a <code><a href="#syntax_err">SYNTAX_ERR</a></code> exception must be
+ raised. Otherwise, the gradient must have a new stop placed, at
+ offset <var title="">offset</var> relative to the whole gradient,
+ and with the color obtained by parsing <var title="">color</var> as
+ a CSS &lt;color&gt; value. If multiple stops are added at the same
+ offset on a gradient, they must be placed in the order added, with
+ the first one closest to the start of the gradient, and each
+ subsequent one infinitesimally further along towards the end point
+ (in effect causing all but the first and last stop added at each
+ point to be ignored).</p>
+
+ <p>The <dfn id="dom-context-2d-createlineargradient" title="dom-context-2d-createLinearGradient"><code>createLinearGradient(<var title="">x0</var>, <var title="">y0</var>, <var title="">x1</var>,
+ <var title="">y1</var>)</code></dfn> method takes four arguments
+ that represent the start point (<var title="">x0</var>, <var title="">y0</var>) and end point (<var title="">x1</var>, <var title="">y1</var>) of the gradient. If any of the arguments to <code title="dom-context-2d-createLinearGradient"><a href="#dom-context-2d-createlineargradient">createLinearGradient()</a></code>
+ are infinite or NaN, the method must raise a
+ <code><a href="#not_supported_err">NOT_SUPPORTED_ERR</a></code> exception. Otherwise, the method must
+ return a linear <code><a href="#canvasgradient">CanvasGradient</a></code> initialized with the
+ specified line.</p>
+
+ <p>Linear gradients must be rendered such that all points on a line
+ perpendicular to the line that crosses the start and end points have
+ the color at the point where those two lines cross (with the colors
+ coming from the <a href="#interpolation">interpolation and
+ extrapolation</a> described above). The points in the linear
+ gradient must be transformed as described by the <a href="#transformations" title="dom-context-2d-transformation">current transformation
+ matrix</a> when rendering.</p>
+
+ <p>If <span title=""><var title="">x0</var> = <var title="">x1</var></span> and <span title=""><var title="">y0</var> = <var title="">y1</var></span>, then
+ the linear gradient must paint nothing.</p>
+
+ <p>The <dfn id="dom-context-2d-createradialgradient" title="dom-context-2d-createRadialGradient"><code>createRadialGradient(<var title="">x0</var>, <var title="">y0</var>, <var title="">r0</var>,
+ <var title="">x1</var>, <var title="">y1</var>, <var title="">r1</var>)</code></dfn> method takes six arguments, the
+ first three representing the start circle with origin (<var title="">x0</var>, <var title="">y0</var>) and radius <var title="">r0</var>, and the last three representing the end circle
+ with origin (<var title="">x1</var>, <var title="">y1</var>) and
+ radius <var title="">r1</var>. The values are in coordinate space
+ units. If any of the arguments are infinite or NaN, a
+ <code><a href="#not_supported_err">NOT_SUPPORTED_ERR</a></code> exception must be raised. If either
+ of <var title="">r0</var> or <var title="">r1</var> are negative, an
+ <code><a href="#index_size_err">INDEX_SIZE_ERR</a></code> exception must be raised. Otherwise,
+ the method must return a radial <code><a href="#canvasgradient">CanvasGradient</a></code>
+ initialized with the two specified circles.</p>
+
+ <p>Radial gradients must be rendered by following these steps:</p>
+
+ <ol><li><p>If <span title=""><var title="">x<sub>0</sub></var> = <var title="">x<sub>1</sub></var></span> and <span title=""><var title="">y<sub>0</sub></var> = <var title="">y<sub>1</sub></var></span> and <span title=""><var title="">r<sub>0</sub></var> = <var title="">r<sub>1</sub></var></span>, then the radial gradient must
+ paint nothing. Abort these steps.</p></li>
+
+ <li>
+
+ <p>Let <span title="">x(<var title="">ω</var>) = (<var title="">x<sub>1</sub></var>-<var title="">x<sub>0</sub></var>)<var title="">ω</var> + <var title="">x<sub>0</sub></var></span></p>
+
+ <p>Let <span title="">y(<var title="">ω</var>) = (<var title="">y<sub>1</sub></var>-<var title="">y<sub>0</sub></var>)<var title="">ω</var> + <var title="">y<sub>0</sub></var></span></p>
+
+ <p>Let <span title="">r(<var title="">ω</var>) = (<var title="">r<sub>1</sub></var>-<var title="">r<sub>0</sub></var>)<var title="">ω</var> + <var title="">r<sub>0</sub></var></span></p>
+
+ <p>Let the color at <var title="">ω</var> be the color at
+ that position on the gradient (with the colors coming from the <a href="#interpolation">interpolation and extrapolation</a>
+ described above).</p>
+
+ </li>
+
+ <li><p>For all values of <var title="">ω</var> where <span title="">r(<var title="">ω</var>) &gt; 0</span>,
+ starting with the value of <var title="">ω</var> nearest to
+ positive infinity and ending with the value of <var title="">ω</var> nearest to negative infinity, draw the
+ circumference of the circle with radius <span title="">r(<var title="">ω</var>)</span> at position (<span title="">x(<var title="">ω</var>)</span>, <span title="">y(<var title="">ω</var>)</span>), with the color at <var title="">ω</var>, but only painting on the parts of the
+ canvas that have not yet been painted on by earlier circles in this
+ step for this rendering of the gradient.</p></li>
+
+ </ol><p class="note">This effectively creates a cone, touched by the two
+ circles defined in the creation of the gradient, with the part of
+ the cone before the start circle (0.0) using the color of the first
+ offset, the part of the cone after the end circle (1.0) using the
+ color of the last offset, and areas outside the cone untouched by
+ the gradient (transparent black).</p>
+
+ <p>The points in the radial gradient must be transformed as
+ described by the <a href="#transformations" title="dom-context-2d-transformation">current
+ transformation matrix</a> when rendering.</p>
+
+ <p>Gradients must be painted only where the relevant stroking or
+ filling effects requires that they be drawn.</p>
+
+<!--
+ <p>Support for actually painting gradients is optional. Instead of
+ painting the gradients, user agents may instead just paint the first
+ stop's color. However, <code
+ title="dom-context-2d-createLinearGradient">createLinearGradient()</code>
+ and <code
+ title="dom-context-2d-createRadialGradient">createRadialGradient()</code>
+ must always return objects when passed valid arguments.</p>
+-->
+
+ </div>
+
+ <hr/><p>Patterns are represented by objects implementing the opaque
+ <code><a href="#canvaspattern">CanvasPattern</a></code> interface.</p>
+
+ <dl class="domintro"><dt><var title="">pattern</var> = <var title="">context</var> . <code title="dom-context-2d-createPattern"><a href="#dom-context-2d-createpattern">createPattern</a></code>(<var title="">image</var>, <var title="">repetition</var>)</dt>
+
+ <dd>
+
+ <p>Returns a <code><a href="#canvaspattern">CanvasPattern</a></code> object that uses the given image
+ and repeats in the direction(s) given by the <var title="">repetition</var> argument.</p>
+
+ <p>The allowed values for <var title="">repetition</var> are <code title="">repeat</code> (both directions), <code title="">repeat-x</code> (horizontal only), <code title="">repeat-y</code> (vertical only), and <code title="">no-repeat</code> (neither). If the <var title="">repetition</var> argument is empty, the value <code title="">repeat</code> is used.</p>
+
+ <p>If the image has no image data, throws an
+ <code><a href="#invalid_state_err">INVALID_STATE_ERR</a></code> exception. If the second argument
+ isn't one of the allowed values, throws a <code><a href="#syntax_err">SYNTAX_ERR</a></code>
+ exception. If the image isn't yet fully decoded, then the method
+ returns null.</p>
+
+ </dd>
+
+ </dl><div class="impl">
+
+ <p>To create objects of this type, the <dfn id="dom-context-2d-createpattern" title="dom-context-2d-createPattern"><code>createPattern(<var title="">image</var>, <var title="">repetition</var>)</code></dfn>
+ method is used. The first argument gives the image to use as the
+ pattern (either an <code><a href="#htmlimageelement">HTMLImageElement</a></code>,
+ <code><a href="#htmlcanvaselement">HTMLCanvasElement</a></code>, or <code><a href="#htmlvideoelement">HTMLVideoElement</a></code>
+ object). Modifying this image after calling the <code title="dom-context-2d-createPattern"><a href="#dom-context-2d-createpattern">createPattern()</a></code> method
+ must not affect the pattern. The second argument must be a string
+ with one of the following values: <code title="">repeat</code>,
+ <code title="">repeat-x</code>, <code title="">repeat-y</code>,
+ <code title="">no-repeat</code>. If the empty string is specified,
+ <code title="">repeat</code> must be assumed. If an unrecognized value
+ is given, then the user agent must raise a <code><a href="#syntax_err">SYNTAX_ERR</a></code>
+ exception. User agents must recognize the four values described above
+ exactly (e.g. they must not do case folding). Except as specified
+ below, the method must return a <code><a href="#canvaspattern">CanvasPattern</a></code> object
+ suitably initialized.</p>
+
+ <p>The <var title="">image</var> argument is an instance of either
+ <code><a href="#htmlimageelement">HTMLImageElement</a></code>, <code><a href="#htmlcanvaselement">HTMLCanvasElement</a></code>, or
+ <code><a href="#htmlvideoelement">HTMLVideoElement</a></code>.</p> <!-- drawImage() has an equivalent
+ paragraph -->
+
+ <p>If the <var title="">image</var> argument is an
+ <code><a href="#htmlimageelement">HTMLImageElement</a></code> object that is not <a href="#img-good" title="img-good">fully decodable</a>, or if the <var title="">image</var> argument is an <code><a href="#htmlvideoelement">HTMLVideoElement</a></code>
+ object whose <code title="dom-media-readyState"><a href="#dom-media-readystate">readyState</a></code>
+ attribute is either <code title="dom-media-HAVE_NOTHING"><a href="#dom-media-have_nothing">HAVE_NOTHING</a></code> or <code title="dom-media-HAVE_METADATA"><a href="#dom-media-have_metadata">HAVE_METADATA</a></code>, then the
+ implementation must return null.</p> <!-- drawImage() has an
+ equivalent paragraph -->
+
+ <p>If the <var title="">image</var> argument is an
+ <code><a href="#htmlcanvaselement">HTMLCanvasElement</a></code> object with either a horizontal
+ dimension or a vertical dimension equal to zero, then the
+ implementation must raise an <code><a href="#invalid_state_err">INVALID_STATE_ERR</a></code>
+ exception.</p>
+ <!-- drawImage() has an equivalent paragraph -->
+
+ <p>Patterns must be painted so that the top left of the first image
+ is anchored at the origin of the coordinate space, and images are
+ then repeated horizontally to the left and right (if the
+ <code>repeat-x</code> string was specified) or vertically up and
+ down (if the <code>repeat-y</code> string was specified) or in all
+ four directions all over the canvas (if the <code>repeat</code>
+ string was specified). The images are not scaled by this process;
+ one CSS pixel of the image must be painted on one coordinate space
+ unit. Of course, patterns must actually be painted only where the
+ stroking or filling effect requires that they be drawn, and are
+ affected by the current transformation matrix.</p>
+
+ <p>If the original image data is a bitmap image, the value painted
+ at a point in the area of the repetitions is computed by filtering
+ the original image data. The user agent may use any filtering
+ algorithm (for example bilinear interpolation or nearest-neighbor).
+ When the filtering algorithm requires a pixel value from outside the
+ original image data, it must instead use the value from wrapping the
+ pixel's coordinates to the original image's dimensions. (That is,
+ the filter uses 'repeat' behavior, regardless of the value of
+ <var title="">repetition</var>.)
+ <!-- drawImage() has a similar paragraph with different rules -->
+
+ </p><p>When the <code title="dom-context-2d-createPattern"><a href="#dom-context-2d-createpattern">createPattern()</a></code> method
+ is passed an animated image as its <var title="">image</var>
+ argument, the user agent must use the poster frame of the animation,
+ or, if there is no poster frame, the first frame of the
+ animation.</p>
+ <!-- drawImage() has an equivalent paragraph -->
+
+ <p>When the <var title="">image</var> argument is an
+ <code><a href="#htmlvideoelement">HTMLVideoElement</a></code>, then the frame at the <a href="#current-playback-position">current
+ playback position</a> must be used as the source image, and the
+ source image's dimensions must be the <a href="#concept-video-intrinsic-width" title="concept-video-intrinsic-width">intrinsic width</a> and
+ <a href="#concept-video-intrinsic-height" title="concept-video-intrinsic-height">intrinsic height</a>
+ of the <a href="#media-resource">media resource</a> (i.e. after any aspect-ratio
+ correction has been applied).</p>
+ <!-- drawImage() has an equivalent paragraph -->
+
+ <!--
+ Requests for v6 features:
+ * apply transforms to patterns, so you don't have to create
+ transformed patterns manually by rendering them to an off-screen
+ canvas then using that canvas as the pattern.
+ -->
+
+ </div>
+
+
+
+ <h6 id="line-styles"><span class="secno">4.8.11.1.5 </span>Line styles</h6>
+
+ <dl class="domintro"><dt><var title="">context</var> . <code title="dom-context-2d-lineWidth"><a href="#dom-context-2d-linewidth">lineWidth</a></code> [ = <var title="">value</var> ]</dt>
+
+ <dd>
+
+ <p>Returns the current line width.</p>
+
+ <p>Can be set, to change the line width. Values that are not
+ finite values greater than zero are ignored.</p>
+
+ </dd>
+
+ <dt><var title="">context</var> . <code title="dom-context-2d-lineCap"><a href="#dom-context-2d-linecap">lineCap</a></code> [ = <var title="">value</var> ]</dt>
+
+ <dd>
+
+ <p>Returns the current line cap style.</p>
+
+ <p>Can be set, to change the line cap style.</p>
+
+ <p>The possible line cap styles are <code>butt</code>,
+ <code>round</code>, and <code>square</code>. Other values are
+ ignored.</p>
+
+ </dd>
+
+ <dt><var title="">context</var> . <code title="dom-context-2d-lineJoin"><a href="#dom-context-2d-linejoin">lineJoin</a></code> [ = <var title="">value</var> ]</dt>
+
+ <dd>
+
+ <p>Returns the current line join style.</p>
+
+ <p>Can be set, to change the line join style.</p>
+
+ <p>The possible line join styles are <code>bevel</code>,
+ <code>round</code>, and <code>miter</code>. Other values are
+ ignored.</p>
+
+ </dd>
+
+ <dt><var title="">context</var> . <code title="dom-context-2d-miterLimit"><a href="#dom-context-2d-miterlimit">miterLimit</a></code> [ = <var title="">value</var> ]</dt>
+
+ <dd>
+
+ <p>Returns the current miter limit ratio.</p>
+
+ <p>Can be set, to change the miter limit ratio. Values that are
+ not finite values greater than zero are ignored.</p>
+
+ </dd>
+
+ </dl><div class="impl">
+
+ <p>The <dfn id="dom-context-2d-linewidth" title="dom-context-2d-lineWidth"><code>lineWidth</code></dfn>
+ attribute gives the width of lines, in coordinate space units. On
+ getting, it must return the current value. On setting, zero,
+ negative, infinite, and NaN values must be ignored, leaving the
+ value unchanged; other values must change the current value to the
+ new value.</p>
+
+ <p>When the context is created, the <code title="dom-context-2d-lineWidth"><a href="#dom-context-2d-linewidth">lineWidth</a></code> attribute must
+ initially have the value <code>1.0</code>.</p>
+
+ <hr/><p>The <dfn id="dom-context-2d-linecap" title="dom-context-2d-lineCap"><code>lineCap</code></dfn> attribute
+ defines the type of endings that UAs will place on the end of
+ lines. The three valid values are <code>butt</code>,
+ <code>round</code>, and <code>square</code>. The <code>butt</code>
+ value means that the end of each line has a flat edge perpendicular
+ to the direction of the line (and that no additional line cap is
+ added). The <code>round</code> value means that a semi-circle with
+ the diameter equal to the width of the line must then be added on to
+ the end of the line. The <code>square</code> value means that a
+ rectangle with the length of the line width and the width of half
+ the line width, placed flat against the edge perpendicular to the
+ direction of the line, must be added at the end of each line.</p>
+
+ <p>On getting, it must return the current value. On setting, if the
+ new value is one of the literal strings <code>butt</code>,
+ <code>round</code>, and <code>square</code>, then the current value
+ must be changed to the new value; other values must ignored, leaving
+ the value unchanged.</p>
+
+ <p>When the context is created, the <code title="dom-context-2d-lineCap"><a href="#dom-context-2d-linecap">lineCap</a></code> attribute must
+ initially have the value <code>butt</code>.</p>
+
+ <hr/><p>The <dfn id="dom-context-2d-linejoin" title="dom-context-2d-lineJoin"><code>lineJoin</code></dfn>
+ attribute defines the type of corners that UAs will place where two
+ lines meet. The three valid values are <code>bevel</code>,
+ <code>round</code>, and <code>miter</code>.</p>
+
+ <p>On getting, it must return the current value. On setting, if the
+ new value is one of the literal strings <code>bevel</code>,
+ <code>round</code>, and <code>miter</code>, then the current value
+ must be changed to the new value; other values must be ignored,
+ leaving the value unchanged.</p>
+
+ <p>When the context is created, the <code title="dom-context-2d-lineJoin"><a href="#dom-context-2d-linejoin">lineJoin</a></code> attribute must
+ initially have the value <code>miter</code>.</p>
+
+ <hr/><p>A join exists at any point in a subpath shared by two consecutive
+ lines. When a subpath is closed, then a join also exists at its
+ first point (equivalent to its last point) connecting the first and
+ last lines in the subpath.</p>
+
+ <p>In addition to the point where the join occurs, two additional
+ points are relevant to each join, one for each line: the two corners
+ found half the line width away from the join point, one
+ perpendicular to each line, each on the side furthest from the other
+ line.</p>
+
+ <p>A filled triangle connecting these two opposite corners with a
+ straight line, with the third point of the triangle being the join
+ point, must be rendered at all joins. The <code title="dom-context-2d-lineJoin"><a href="#dom-context-2d-linejoin">lineJoin</a></code> attribute controls
+ whether anything else is rendered. The three aforementioned values
+ have the following meanings:</p>
+
+ <p>The <code>bevel</code> value means that this is all that is
+ rendered at joins.</p>
+
+ <p>The <code>round</code> value means that a filled arc connecting
+ the two aforementioned corners of the join, abutting (and not
+ overlapping) the aforementioned triangle, with the diameter equal to
+ the line width and the origin at the point of the join, must be
+ rendered at joins.</p>
+
+ <p>The <code>miter</code> value means that a second filled triangle
+ must (if it can given the miter length) be rendered at the join,
+ with one line being the line between the two aforementioned corners,
+ abutting the first triangle, and the other two being continuations of
+ the outside edges of the two joining lines, as long as required to
+ intersect without going over the miter length.</p>
+
+ <p>The miter length is the distance from the point where the join
+ occurs to the intersection of the line edges on the outside of the
+ join. The miter limit ratio is the maximum allowed ratio of the
+ miter length to half the line width. If the miter length would cause
+ the miter limit ratio to be exceeded, this second triangle must not
+ be rendered.</p>
+
+ <p>The miter limit ratio can be explicitly set using the <dfn id="dom-context-2d-miterlimit" title="dom-context-2d-miterLimit"><code>miterLimit</code></dfn>
+ attribute. On getting, it must return the current value. On setting,
+ zero, negative, infinite, and NaN values must be ignored, leaving
+ the value unchanged; other values must change the current value to
+ the new value.</p>
+
+ <p>When the context is created, the <code title="dom-context-2d-miterLimit"><a href="#dom-context-2d-miterlimit">miterLimit</a></code> attribute must
+ initially have the value <code>10.0</code>.</p>
+
+ <!--
+v6: dashed lines have been requested. Philip Taylor provides these
+notes on what would need to be defined for dashed lines:
+> I don't think it's entirely trivial to add, to the detail that's
+> necessary in a specification. The common graphics APIs (at least
+> Cairo, Quartz and java.awt.Graphics, and any SVG implementation) all
+> have dashes specified by passing an array of dash lengths (alternating
+> on/off), so that should be alright as long as you define what units
+> it's measured in and what happens when you specify an odd number of
+> values and how errors are handled and what happens if you update the
+> array later. But after that, what does it do when stroking multiple
+> subpaths, in terms of offsetting the dashes? When you use strokeRect,
+> where is offset 0? Does moveTo reset the offset? How does it interact
+> with lineCap/lineJoin? All the potential issues need test cases too,
+> and the implementations need to make sure they handle any edge cases
+> that the underlying graphics library does differently. (SVG Tiny 1.2
+> appears to skip some of the problems by leaving things undefined and
+> allowing whatever behavior the graphics library has.)
+
+Another request has been for hairline width lines, that remain
+hairline width with transform. ack Shaun Morris.
+ -->
+
+ </div>
+
+
+ <h6 id="shadows"><span class="secno">4.8.11.1.6 </span><dfn>Shadows</dfn></h6>
+
+ <p>All drawing operations are affected by the four global shadow
+ attributes.</p>
+
+ <dl class="domintro"><dt><var title="">context</var> . <code title="dom-context-2d-shadowColor"><a href="#dom-context-2d-shadowcolor">shadowColor</a></code> [ = <var title="">value</var> ]</dt>
+
+ <dd>
+
+ <p>Returns the current shadow color.</p>
+
+ <p>Can be set, to change the shadow color. Values that cannot be parsed as CSS colors are ignored.</p>
+
+ </dd>
+
+ <dt><var title="">context</var> . <code title="dom-context-2d-shadowOffsetX"><a href="#dom-context-2d-shadowoffsetx">shadowOffsetX</a></code> [ = <var title="">value</var> ]</dt>
+ <dt><var title="">context</var> . <code title="dom-context-2d-shadowOffsetY"><a href="#dom-context-2d-shadowoffsety">shadowOffsetY</a></code> [ = <var title="">value</var> ]</dt>
+
+ <dd>
+
+ <p>Returns the current shadow offset.</p>
+
+ <p>Can be set, to change the shadow offset. Values that are not finite numbers are ignored.</p>
+
+ </dd>
+
+ <dt><var title="">context</var> . <code title="dom-context-2d-shadowBlur"><a href="#dom-context-2d-shadowblur">shadowBlur</a></code> [ = <var title="">value</var> ]</dt>
+
+ <dd>
+
+ <p>Returns the current level of blur applied to shadows.</p>
+
+ <p>Can be set, to change the blur level. Values that are not finite numbers greater than or equal to zero are ignored.</p>
+
+ </dd>
+
+ </dl><div class="impl">
+
+ <p>The <dfn id="dom-context-2d-shadowcolor" title="dom-context-2d-shadowColor"><code>shadowColor</code></dfn>
+ attribute sets the color of the shadow.</p>
+
+ <p>When the context is created, the <code title="dom-context-2d-shadowColor"><a href="#dom-context-2d-shadowcolor">shadowColor</a></code> attribute
+ initially must be fully-transparent black.</p>
+
+ <p>On getting, the <a href="#serialization-of-a-color" title="serialization of a
+ color">serialization of the color</a> must be returned.</p>
+
+ <p>On setting, the new value must be <a href="#parsed-as-a-css-color-value">parsed as a CSS
+ &lt;color&gt; value</a> and the color assigned. If the value
+ cannot be parsed as a CSS &lt;color&gt; value then it must be
+ ignored, and the attribute must retain its previous value. <a href="#refsCSSCOLOR">[CSSCOLOR]</a></p>
+
+ <p>The <dfn id="dom-context-2d-shadowoffsetx" title="dom-context-2d-shadowOffsetX"><code>shadowOffsetX</code></dfn>
+ and <dfn id="dom-context-2d-shadowoffsety" title="dom-context-2d-shadowOffsetY"><code>shadowOffsetY</code></dfn>
+ attributes specify the distance that the shadow will be offset in
+ the positive horizontal and positive vertical distance
+ respectively. Their values are in coordinate space units. They are
+ not affected by the current transformation matrix.</p>
+
+ <p>When the context is created, the shadow offset attributes must
+ initially have the value <code>0</code>.</p>
+
+ <p>On getting, they must return their current value. On setting, the
+ attribute being set must be set to the new value, except if the
+ value is infinite or NaN, in which case the new value must be
+ ignored.</p>
+
+ <p>The <dfn id="dom-context-2d-shadowblur" title="dom-context-2d-shadowBlur"><code>shadowBlur</code></dfn>
+ attribute specifies the level of the blurring effect. (The units do
+ not map to coordinate space units, and are not affected by the
+ current transformation matrix.)</p>
+
+ <p>When the context is created, the <code title="dom-context-2d-shadowBlur"><a href="#dom-context-2d-shadowblur">shadowBlur</a></code> attribute must
+ initially have the value <code>0</code>.</p>
+
+ <p>On getting, the attribute must return its current value. On
+ setting the attribute must be set to the new value, except if the
+ value is negative, infinite or NaN, in which case the new value must
+ be ignored.</p>
+
+ <p><dfn id="when-shadows-are-drawn" title="when shadows are drawn">Shadows are only drawn
+ if</dfn> the opacity component of the alpha component of the color
+ of <code title="dom-context-2d-shadowColor"><a href="#dom-context-2d-shadowcolor">shadowColor</a></code> is
+ non-zero and either the <code title="dom-context-2d-shadowBlur"><a href="#dom-context-2d-shadowblur">shadowBlur</a></code> is non-zero, or
+ the <code title="dom-context-2d-shadowOffsetX"><a href="#dom-context-2d-shadowoffsetx">shadowOffsetX</a></code>
+ is non-zero, or the <code title="dom-context-2d-shadowOffsetY"><a href="#dom-context-2d-shadowoffsety">shadowOffsetY</a></code> is
+ non-zero.</p>
+
+ <p class="critical">It is likely that this will change: browser
+ vendors have indicated an interest in changing the processing model
+ for shadows such that they only draw when the composition operator
+ is &quot;source-over&quot; (the default). <a href="http://lists.whatwg.org/htdig.cgi/whatwg-whatwg.org/2011-May/thread.html#31457">Read
+ more...</a></p>
+
+ <p><a href="#when-shadows-are-drawn">When shadows are drawn</a>, they must be rendered as follows:</p>
+
+ <ol><li> <p>Let <var title="">A</var> be an infinite transparent black
+ bitmap on which the source image for which a shadow is being
+ created has been rendered.</p> </li>
+
+ <li> <p>Let <var title="">B</var> be an infinite transparent black
+ bitmap, with a coordinate space and an origin identical to <var title="">A</var>.</p> </li>
+
+ <li> <p>Copy the alpha channel of <var title="">A</var> to <var title="">B</var>, offset by <code title="dom-context-2d-shadowOffsetX"><a href="#dom-context-2d-shadowoffsetx">shadowOffsetX</a></code> in the
+ positive <var title="">x</var> direction, and <code title="dom-context-2d-shadowOffsetY"><a href="#dom-context-2d-shadowoffsety">shadowOffsetY</a></code> in the
+ positive <var title="">y</var> direction.</p> </li>
+
+ <li> <p>If <code title="dom-context-2d-shadowBlur"><a href="#dom-context-2d-shadowblur">shadowBlur</a></code> is greater than
+ 0:</p>
+
+ <ol><li> <p>Let <var title="">σ</var> be half the value of
+ <code title="dom-context-2d-shadowBlur"><a href="#dom-context-2d-shadowblur">shadowBlur</a></code>.</p></li>
+
+ <li> <p>Perform a 2D Gaussian Blur on <var title="">B</var>,
+ using <var title="">σ</var> as the standard deviation.</p>
+ <!-- wish i could find a reference for this --> </li>
+
+ </ol><p>User agents may limit values of <var title="">σ</var> to
+ an implementation-specific maximum value to avoid exceeding
+ hardware limitations during the Gaussian blur operation.</p>
+
+ </li>
+
+ <li> <p>Set the red, green, and blue components of every pixel in
+ <var title="">B</var> to the red, green, and blue components
+ (respectively) of the color of <code title="dom-context-2d-shadowColor"><a href="#dom-context-2d-shadowcolor">shadowColor</a></code>.</p> </li>
+
+ <li> <p>Multiply the alpha component of every pixel in <var title="">B</var> by the alpha component of the color of <code title="dom-context-2d-shadowColor"><a href="#dom-context-2d-shadowcolor">shadowColor</a></code>.</p> </li>
+
+ <li> <p>The shadow is in the bitmap <var title="">B</var>, and is
+ rendered as part of the <a href="#drawing-model">drawing model</a> described below.</p> </li>
+
+ </ol></div>
+
+ <p>If the current composition operation is <code title="gcop-copy"><a href="#gcop-copy">copy</a></code>, shadows effectively won't render
+ (since the shape will overwrite the shadow).</p>
+
+
+ <h6 id="simple-shapes-(rectangles)"><span class="secno">4.8.11.1.7 </span>Simple shapes (rectangles)</h6>
+
+ <p>There are three methods that immediately draw rectangles to the
+ bitmap. They each take four arguments; the first two give the <var title="">x</var> and <var title="">y</var> coordinates of the top
+ left of the rectangle, and the second two give the width <var title="">w</var> and height <var title="">h</var> of the rectangle,
+ respectively.</p>
+
+ <div class="impl">
+
+ <p>The <a href="#transformations" title="dom-context-2d-transformation">current
+ transformation matrix</a> must be applied to the following four
+ coordinates, which form the path that must then be closed to get the
+ specified rectangle: <span title="">(<var title="">x</var>, <var title="">y</var>)</span>, <span title="">(<span title=""><var title="">x</var>+<var title="">w</var></span>, <var title="">y</var>)</span>,
+ <span title="">(<span title=""><var title="">x</var>+<var title="">w</var></span>,
+ <span title=""><var title="">y</var>+<var title="">h</var></span>)</span>,
+ <span title="">(<var title="">x</var>, <span title=""><var title="">y</var>+<var title="">h</var></span>)</span>.</p>
+
+ <p>Shapes are painted without affecting the current path, and are
+ subject to the <a href="#clipping-region" title="clipping region">clipping region</a>,
+ and, with the exception of <code title="dom-context-2d-clearRect"><a href="#dom-context-2d-clearrect">clearRect()</a></code>, also <a href="#shadows" title="shadows">shadow effects</a>, <a href="#dom-context-2d-globalalpha" title="dom-context-2d-globalAlpha">global alpha</a>, and <a href="#dom-context-2d-globalcompositeoperation" title="dom-context-2d-globalCompositeOperation">global composition
+ operators</a>.</p>
+
+ </div>
+
+ <dl class="domintro"><dt><var title="">context</var> . <code title="dom-context-2d-clearRect"><a href="#dom-context-2d-clearrect">clearRect</a></code>(<var title="">x</var>, <var title="">y</var>, <var title="">w</var>, <var title="">h</var>)</dt>
+
+ <dd>
+
+ <p>Clears all pixels on the canvas in the given rectangle to transparent black.</p>
+
+ </dd>
+
+ <dt><var title="">context</var> . <code title="dom-context-2d-fillRect"><a href="#dom-context-2d-fillrect">fillRect</a></code>(<var title="">x</var>, <var title="">y</var>, <var title="">w</var>, <var title="">h</var>)</dt>
+
+ <dd>
+
+ <p>Paints the given rectangle onto the canvas, using the current fill style.</p>
+
+ </dd>
+
+ <dt><var title="">context</var> . <code title="dom-context-2d-strokeRect"><a href="#dom-context-2d-strokerect">strokeRect</a></code>(<var title="">x</var>, <var title="">y</var>, <var title="">w</var>, <var title="">h</var>)</dt>
+
+ <dd>
+
+ <p>Paints the box that outlines the given rectangle onto the canvas, using the current stroke style.</p>
+
+ </dd>
+
+ </dl><div class="impl">
+
+ <p>The <dfn id="dom-context-2d-clearrect" title="dom-context-2d-clearRect"><code>clearRect(<var title="">x</var>, <var title="">y</var>, <var title="">w</var>, <var title="">h</var>)</code></dfn> method must clear the pixels in the
+ specified rectangle that also intersect the current clipping region
+ to a fully transparent black, erasing any previous image. If either
+ height or width are zero, this method has no effect.</p>
+
+ <p>The <dfn id="dom-context-2d-fillrect" title="dom-context-2d-fillRect"><code>fillRect(<var title="">x</var>, <var title="">y</var>, <var title="">w</var>, <var title="">h</var>)</code></dfn> method must paint the specified
+ rectangular area using the <code title="dom-context-2d-fillStyle"><a href="#dom-context-2d-fillstyle">fillStyle</a></code>. If either height
+ or width are zero, this method has no effect.</p>
+
+ <p>The <dfn id="dom-context-2d-strokerect" title="dom-context-2d-strokeRect"><code>strokeRect(<var title="">x</var>, <var title="">y</var>, <var title="">w</var>, <var title="">h</var>)</code></dfn> method must stroke the specified
+ rectangle's path using the <code title="dom-context-2d-strokeStyle"><a href="#dom-context-2d-strokestyle">strokeStyle</a></code>, <code title="dom-context-2d-lineWidth"><a href="#dom-context-2d-linewidth">lineWidth</a></code>, <code title="dom-context-2d-lineJoin"><a href="#dom-context-2d-linejoin">lineJoin</a></code>, and (if
+ appropriate) <code title="dom-context-2d-miterLimit"><a href="#dom-context-2d-miterlimit">miterLimit</a></code> attributes. If
+ both height and width are zero, this method has no effect, since
+ there is no path to stroke (it's a point). If only one of the two is
+ zero, then the method will draw a line instead (the path for the
+ outline is just a straight line along the non-zero dimension).</p>
+
+ </div>
+
+
+ <h6 id="complex-shapes-(paths)"><span class="secno">4.8.11.1.8 </span>Complex shapes (paths)</h6>
+
+ <p>The context always has a current path. There is only one current
+ path, it is not part of the <a href="#drawing-state">drawing state</a>.</p>
+
+ <p>A <dfn id="path">path</dfn> has a list of zero or more subpaths. Each
+ subpath consists of a list of one or more points, connected by
+ straight or curved lines, and a flag indicating whether the subpath
+ is closed or not. A closed subpath is one where the last point of
+ the subpath is connected to the first point of the subpath by a
+ straight line. Subpaths with fewer than two points are ignored when
+ painting the path.</p>
+
+ <dl class="domintro"><dt><var title="">context</var> . <code title="dom-context-2d-beginPath"><a href="#dom-context-2d-beginpath">beginPath</a></code>()</dt>
+
+ <dd>
+
+ <p>Resets the current path.</p>
+
+ </dd>
+
+ <dt><var title="">context</var> . <code title="dom-context-2d-moveTo"><a href="#dom-context-2d-moveto">moveTo</a></code>(<var title="">x</var>, <var title="">y</var>)</dt>
+
+ <dd>
+
+ <p>Creates a new subpath with the given point.</p>
+
+ </dd>
+
+ <dt><var title="">context</var> . <code title="dom-context-2d-closePath"><a href="#dom-context-2d-closepath">closePath</a></code>()</dt>
+
+ <dd>
+
+ <p>Marks the current subpath as closed, and starts a new subpath with a point the same as the start and end of the newly closed subpath.</p>
+
+ </dd>
+
+ <dt><var title="">context</var> . <code title="dom-context-2d-lineTo"><a href="#dom-context-2d-lineto">lineTo</a></code>(<var title="">x</var>, <var title="">y</var>)</dt>
+
+ <dd>
+
+ <p>Adds the given point to the current subpath, connected to the previous one by a straight line.</p>
+
+ </dd>
+
+ <dt><var title="">context</var> . <code title="dom-context-2d-quadraticCurveTo"><a href="#dom-context-2d-quadraticcurveto">quadraticCurveTo</a></code>(<var title="">cpx</var>, <var title="">cpy</var>, <var title="">x</var>, <var title="">y</var>)</dt>
+
+ <dd>
+
+ <p>Adds the given point to the current subpath, connected to the previous one by a quadratic Bézier curve with the given control point.</p>
+
+ </dd>
+
+ <dt><var title="">context</var> . <code title="dom-context-2d-bezierCurveTo"><a href="#dom-context-2d-beziercurveto">bezierCurveTo</a></code>(<var title="">cp1x</var>, <var title="">cp1y</var>, <var title="">cp2x</var>, <var title="">cp2y</var>, <var title="">x</var>, <var title="">y</var>)</dt>
+
+ <dd>
+
+ <p>Adds the given point to the current subpath, connected to the previous one by a cubic Bézier curve with the given control points.</p>
+
+ </dd>
+
+ <dt><var title="">context</var> . <code title="dom-context-2d-arcTo"><a href="#dom-context-2d-arcto">arcTo</a></code>(<var title="">x1</var>, <var title="">y1</var>, <var title="">x2</var>, <var title="">y2</var>, <var title="">radius</var>)</dt>
+
+ <dd>
+
+ <p>Adds an arc with the given control points and radius to the
+ current subpath, connected to the previous point by a straight
+ line.</p>
+
+ <p>Throws an <code><a href="#index_size_err">INDEX_SIZE_ERR</a></code> exception if the given
+ radius is negative.</p>
+
+ </dd>
+
+ <dt><var title="">context</var> . <code title="dom-context-2d-arc"><a href="#dom-context-2d-arc">arc</a></code>(<var title="">x</var>, <var title="">y</var>, <var title="">radius</var>, <var title="">startAngle</var>, <var title="">endAngle</var> [, <var title="">anticlockwise</var> ] )</dt>
+
+ <dd>
+
+ <p>Adds points to the subpath such that the arc described by the
+ circumference of the circle described by the arguments, starting
+ at the given start angle and ending at the given end angle, going
+ in the given direction (defaulting to clockwise), is added to the
+ path, connected to the previous point by a straight line.</p>
+
+ <p>Throws an <code><a href="#index_size_err">INDEX_SIZE_ERR</a></code> exception if the given
+ radius is negative.</p>
+
+ </dd>
+
+ <dt><var title="">context</var> . <code title="dom-context-2d-rect"><a href="#dom-context-2d-rect">rect</a></code>(<var title="">x</var>, <var title="">y</var>, <var title="">w</var>, <var title="">h</var>)</dt>
+
+ <dd>
+
+ <p>Adds a new closed subpath to the path, representing the given rectangle.</p>
+
+ </dd>
+
+ <dt><var title="">context</var> . <code title="dom-context-2d-fill"><a href="#dom-context-2d-fill">fill</a></code>()</dt>
+
+ <dd>
+
+ <p>Fills the subpaths with the current fill style.</p>
+
+ </dd>
+
+ <dt><var title="">context</var> . <code title="dom-context-2d-stroke"><a href="#dom-context-2d-stroke">stroke</a></code>()</dt>
+
+ <dd>
+
+ <p>Strokes the subpaths with the current stroke style.</p>
+
+ </dd>
+
+ <dt><var title="">context</var> . <code title="dom-context-2d-drawSystemFocusRing"><a href="#dom-context-2d-drawsystemfocusring">drawSystemFocusRing</a></code>(<var title="">element</var>)</dt>
+
+ <dd>
+
+ <p>If the given element is focused, draws a focus ring around the
+ current path, following the platform conventions for focus
+ rings.</p>
+
+ </dd>
+
+ <dt><var title="">shouldDraw</var> = <var title="">context</var> . <code title="dom-context-2d-drawCustomFocusRing"><a href="#dom-context-2d-drawcustomfocusring">drawCustomFocusRing</a></code>(<var title="">element</var>)</dt>
+
+ <dd>
+
+ <p>If the given element is focused, and the user has configured
+ his system to draw focus rings in a particular manner (for
+ example, high contrast focus rings), draws a focus ring around the
+ current path and returns false.</p>
+
+ <p>Otherwise, returns true if the given element is focused, and
+ false otherwise. This can thus be used to determine when to draw a
+ focus ring (see <a href="#drawCustomFocusRingExample">the
+ example</a> below).</p>
+
+ </dd>
+
+ <dt><var title="">context</var> . <code title="dom-context-2d-scrollPathIntoView"><a href="#dom-context-2d-scrollpathintoview">scrollPathIntoView</a></code>()</dt>
+
+ <dd>
+
+ <p>Scrolls the current path into view. This is especially useful
+ on devices with small screens, where the whole canvas might not be
+ visible at once.</p>
+
+ </dd>
+
+ <dt><var title="">context</var> . <code title="dom-context-2d-clip"><a href="#dom-context-2d-clip">clip</a></code>()</dt>
+
+ <dd>
+
+ <p>Further constrains the clipping region to the given path.</p>
+
+ </dd>
+
+ <dt><var title="">context</var> . <code title="dom-context-2d-isPointInPath"><a href="#dom-context-2d-ispointinpath">isPointInPath</a></code>(<var title="">x</var>, <var title="">y</var>)</dt>
+
+ <dd>
+
+ <p>Returns true if the given point is in the current path.</p>
+
+ </dd>
+
+ </dl><div class="impl">
+
+ <p>Initially, the context's path must have zero subpaths.</p>
+
+ <p>The points and lines added to the path by these methods must be
+ transformed according to the <a href="#transformations" title="dom-context-2d-transformation">current transformation
+ matrix</a> as they are added.</p>
+
+
+ <p>The <dfn id="dom-context-2d-beginpath" title="dom-context-2d-beginPath"><code>beginPath()</code></dfn>
+ method must empty the list of subpaths so that the context once
+ again has zero subpaths.</p>
+
+
+ <p>The <dfn id="dom-context-2d-moveto" title="dom-context-2d-moveTo"><code>moveTo(<var title="">x</var>, <var title="">y</var>)</code></dfn> method must
+ create a new subpath with the specified point as its first (and
+ only) point.</p>
+
+ <p>When the user agent is to <dfn id="ensure-there-is-a-subpath">ensure there is a subpath</dfn>
+ for a coordinate (<var title="">x</var>, <var title="">y</var>), the
+ user agent must check to see if the context has any subpaths, and if
+ it does not, then the user agent must create a new subpath with the
+ point (<var title="">x</var>, <var title="">y</var>) as its first
+ (and only) point, as if the <code title="dom-context-2d-moveTo"><a href="#dom-context-2d-moveto">moveTo()</a></code> method had been
+ called.</p>
+
+
+ <p>The <dfn id="dom-context-2d-closepath" title="dom-context-2d-closePath"><code>closePath()</code></dfn>
+ method must do nothing if the context has no subpaths. Otherwise, it
+ must mark the last subpath as closed, create a new subpath whose
+ first point is the same as the previous subpath's first point, and
+ finally add this new subpath to the path.</p>
+
+ <p class="note">If the last subpath had more than one point in its
+ list of points, then this is equivalent to adding a straight line
+ connecting the last point back to the first point, thus &quot;closing&quot;
+ the shape, and then repeating the last (possibly implied) <code title="dom-context-2d-moveTo"><a href="#dom-context-2d-moveto">moveTo()</a></code> call.</p>
+
+
+ <p>New points and the lines connecting them are added to subpaths
+ using the methods described below. In all cases, the methods only
+ modify the last subpath in the context's paths.</p>
+
+
+ <p>The <dfn id="dom-context-2d-lineto" title="dom-context-2d-lineTo"><code>lineTo(<var title="">x</var>, <var title="">y</var>)</code></dfn> method must
+ <a href="#ensure-there-is-a-subpath">ensure there is a subpath</a> for <span title="">(<var title="">x</var>, <var title="">y</var>)</span> if the context has
+ no subpaths. Otherwise, it must connect the last point in the
+ subpath to the given point (<var title="">x</var>, <var title="">y</var>) using a straight line, and must then add the given
+ point (<var title="">x</var>, <var title="">y</var>) to the
+ subpath.</p>
+
+
+ <p>The <dfn id="dom-context-2d-quadraticcurveto" title="dom-context-2d-quadraticCurveTo"><code>quadraticCurveTo(<var title="">cpx</var>, <var title="">cpy</var>, <var title="">x</var>,
+ <var title="">y</var>)</code></dfn> method must <a href="#ensure-there-is-a-subpath">ensure there
+ is a subpath</a> for <span title="">(<var title="">cpx</var>,
+ <var title="">cpy</var>)</span>, and then must connect the last
+ point in the subpath to the given point (<var title="">x</var>, <var title="">y</var>) using a quadratic Bézier curve with control
+ point (<var title="">cpx</var>, <var title="">cpy</var>), and must
+ then add the given point (<var title="">x</var>, <var title="">y</var>) to the subpath. <a href="#refsBEZIER">[BEZIER]</a></p>
+
+
+ <p>The <dfn id="dom-context-2d-beziercurveto" title="dom-context-2d-bezierCurveTo"><code>bezierCurveTo(<var title="">cp1x</var>, <var title="">cp1y</var>, <var title="">cp2x</var>, <var title="">cp2y</var>, <var title="">x</var>, <var title="">y</var>)</code></dfn> method must
+ <a href="#ensure-there-is-a-subpath">ensure there is a subpath</a> for <span title="">(<var title="">cp1x</var>, <var title="">cp1y</var>)</span>, and then must
+ connect the last point in the subpath to the given point (<var title="">x</var>, <var title="">y</var>) using a cubic Bézier
+ curve with control points (<var title="">cp1x</var>, <var title="">cp1y</var>) and (<var title="">cp2x</var>, <var title="">cp2y</var>). Then, it must add the point (<var title="">x</var>, <var title="">y</var>) to the subpath. <a href="#refsBEZIER">[BEZIER]</a></p>
+
+ <hr/><p>The <dfn id="dom-context-2d-arcto" title="dom-context-2d-arcTo"><code>arcTo(<var title="">x1</var>, <var title="">y1</var>, <var title="">x2</var>,
+ <var title="">y2</var>, <var title="">radius</var>)</code></dfn>
+ method must first <a href="#ensure-there-is-a-subpath">ensure there is a subpath</a> for <span title="">(<var title="">x1</var>, <var title="">y1</var>)</span>. Then, the behavior depends on the
+ arguments and the last point in the subpath, as described below.</p>
+
+ <p>Negative values for <var title="">radius</var> must cause the
+ implementation to raise an <code><a href="#index_size_err">INDEX_SIZE_ERR</a></code>
+ exception.</p>
+
+ <p>Let the point (<var title="">x0</var>, <var title="">y0</var>) be
+ the last point in the subpath.</p>
+
+ <p>If the point (<var title="">x0</var>, <var title="">y0</var>) is
+ equal to the point (<var title="">x1</var>, <var title="">y1</var>),
+ or if the point (<var title="">x1</var>, <var title="">y1</var>) is
+ equal to the point (<var title="">x2</var>, <var title="">y2</var>),
+ or if the radius <var title="">radius</var> is zero, then the method
+ must add the point (<var title="">x1</var>, <var title="">y1</var>)
+ to the subpath, and connect that point to the previous point (<var title="">x0</var>, <var title="">y0</var>) by a straight line.</p>
+
+ <p>Otherwise, if the points (<var title="">x0</var>, <var title="">y0</var>), (<var title="">x1</var>, <var title="">y1</var>), and (<var title="">x2</var>, <var title="">y2</var>) all lie on a single straight line, then the
+ method must add the point (<var title="">x1</var>, <var title="">y1</var>) to the subpath, and connect that point to the
+ previous point (<var title="">x0</var>, <var title="">y0</var>) by a
+ straight line.</p>
+
+ <p>Otherwise, let <var title="">The Arc</var> be the shortest arc
+ given by circumference of the circle that has radius <var title="">radius</var>, and that has one point tangent to the
+ half-infinite line that crosses the point (<var title="">x0</var>,
+ <var title="">y0</var>) and ends at the point (<var title="">x1</var>, <var title="">y1</var>), and that has a different
+ point tangent to the half-infinite line that ends at the point (<var title="">x1</var>, <var title="">y1</var>) and crosses the point
+ (<var title="">x2</var>, <var title="">y2</var>). The points at
+ which this circle touches these two lines are called the start and
+ end tangent points respectively. The method must connect the point
+ (<var title="">x0</var>, <var title="">y0</var>) to the start
+ tangent point by a straight line, adding the start tangent point to
+ the subpath, and then must connect the start tangent point to the
+ end tangent point by <var title="">The Arc</var>, adding the end
+ tangent point to the subpath.</p>
+
+ <hr/><p>The <dfn id="dom-context-2d-arc" title="dom-context-2d-arc"><code>arc(<var title="">x</var>, <var title="">y</var>, <var title="">radius</var>,
+ <var title="">startAngle</var>, <var title="">endAngle</var>, <var title="">anticlockwise</var>)</code></dfn> method draws an arc. If
+ the context has any subpaths, then the method must add a straight
+ line from the last point in the subpath to the start point of the
+ arc. In any case, it must draw the arc between the start point of
+ the arc and the end point of the arc, and add the start and end
+ points of the arc to the subpath. The arc and its start and end
+ points are defined as follows:</p>
+
+ <p>Consider a circle that has its origin at (<var title="">x</var>,
+ <var title="">y</var>) and that has radius <var title="">radius</var>. The points at <var title="">startAngle</var>
+ and <var title="">endAngle</var> along this circle's circumference,
+ measured in radians clockwise from the positive x-axis, are the
+ start and end points respectively.</p>
+
+ <p>If the <var title="">anticlockwise</var> argument is omitted or
+ false and <span title=""><var title="">endAngle</var>-<var title="">startAngle</var></span> is equal to or greater than <span title="">2π</span>, or, if the <var title="">anticlockwise</var>
+ argument is <em>true</em> and <span title=""><var title="">startAngle</var>-<var title="">endAngle</var></span> is
+ equal to or greater than <span title="">2π</span>, then the arc
+ is the whole circumference of this circle.</p>
+
+ <p>Otherwise, the arc is the path along the circumference of this
+ circle from the start point to the end point, going anti-clockwise
+ if the <var title="">anticlockwise</var> argument is true, and
+ clockwise otherwise. Since the points are on the circle, as opposed
+ to being simply angles from zero, the arc can never cover an angle
+ greater than <span title="">2π</span> radians. If the two points are the
+ same, or if the radius is zero, then the arc is defined as being of
+ zero length in both directions.</p>
+
+ <p>Negative values for <var title="">radius</var> must cause the
+ implementation to raise an <code><a href="#index_size_err">INDEX_SIZE_ERR</a></code>
+ exception.</p>
+
+ <hr/><p>The <dfn id="dom-context-2d-rect" title="dom-context-2d-rect"><code>rect(<var title="">x</var>, <var title="">y</var>, <var title="">w</var>, <var title="">h</var>)</code></dfn> method must create a new subpath
+ containing just the four points (<var title="">x</var>, <var title="">y</var>), (<var title="">x</var>+<var title="">w</var>,
+ <var title="">y</var>), (<var title="">x</var>+<var title="">w</var>, <var title="">y</var>+<var title="">h</var>),
+ (<var title="">x</var>, <var title="">y</var>+<var title="">h</var>), with those four points connected by straight
+ lines, and must then mark the subpath as closed. It must then create
+ a new subpath with the point (<var title="">x</var>, <var title="">y</var>) as the only point in the subpath.</p>
+
+
+ <!-- v6 feature request:
+ * points as a primitive shape
+ http://home.comcast.net/~urbanjost/canvas/vogle4.html
+ -->
+
+
+ <p>The <dfn id="dom-context-2d-fill" title="dom-context-2d-fill"><code>fill()</code></dfn>
+ method must fill all the subpaths of the current path, using
+ <code title="dom-context-2d-fillStyle"><a href="#dom-context-2d-fillstyle">fillStyle</a></code>, and using
+ the non-zero winding number rule. Open subpaths must be implicitly
+ closed when being filled (without affecting the actual
+ subpaths).</p>
+
+ <p class="note">Thus, if two overlapping but otherwise independent
+ subpaths have opposite windings, they cancel out and result in no
+ fill. If they have the same winding, that area just gets painted
+ once.</p>
+
+ <p>The <dfn id="dom-context-2d-stroke" title="dom-context-2d-stroke"><code>stroke()</code></dfn> method
+ must calculate the strokes of all the subpaths of the current path,
+ using the <code title="dom-context-2d-lineWidth"><a href="#dom-context-2d-linewidth">lineWidth</a></code>,
+ <code title="dom-context-2d-lineCap"><a href="#dom-context-2d-linecap">lineCap</a></code>, <code title="dom-context-2d-lineJoin"><a href="#dom-context-2d-linejoin">lineJoin</a></code>, and (if
+ appropriate) <code title="dom-context-2d-miterLimit"><a href="#dom-context-2d-miterlimit">miterLimit</a></code> attributes, and
+ then fill the combined stroke area using the <code title="dom-context-2d-strokeStyle"><a href="#dom-context-2d-strokestyle">strokeStyle</a></code>
+ attribute.</p>
+
+ <p class="note">Since the subpaths are all stroked as one,
+ overlapping parts of the paths in one stroke operation are treated
+ as if their union was what was painted.</p>
+
+ <p>Paths, when filled or stroked, must be painted without affecting
+ the current path, and must be subject to <a href="#shadows" title="shadows">shadow effects</a>, <a href="#dom-context-2d-globalalpha" title="dom-context-2d-globalAlpha">global alpha</a>, the <a href="#clipping-region" title="clipping region">clipping region</a>, and <a href="#dom-context-2d-globalcompositeoperation" title="dom-context-2d-globalCompositeOperation">global composition
+ operators</a>. (Transformations affect the path when the path is
+ created, not when it is painted, though the stroke <em>style</em> is
+ still affected by the transformation during painting.)</p>
+
+ <p>Zero-length line segments must be pruned before stroking a
+ path. Empty subpaths must be ignored.</p>
+
+ <hr/><p id="dom-context-2d-drawosfocusring">The <dfn id="dom-context-2d-drawsystemfocusring" title="dom-context-2d-drawSystemFocusRing"><code>drawSystemFocusRing(<var title="">element</var>)</code></dfn> method, when invoked, must run
+ the following steps:</p>
+
+ <ol><li><p>If <var title="">element</var> is not focused or is not a
+ descendant of the element with whose context the method is
+ associated, then abort these steps.</p></li>
+
+ <li>
+
+ <p>If the user has requested the use of particular focus rings
+ (e.g. high-contrast focus rings), or if the <var title="">element</var> would have a focus ring drawn around it,
+ then draw a focus ring of the appropriate style along the path,
+ following platform conventions, and abort these steps.</p>
+
+ <p class="note">Some platforms only draw focus rings around
+ elements that have been focused from the keyboard, and not those
+ focused from the mouse. Other platforms simply don't draw focus
+ rings around some elements at all unless relevant accessibility
+ features are enabled. This API is intended to follow these
+ conventions. User agents that implement distinctions based on the
+ manner in which the element was focused are encouraged to classify
+ focus driven by the <code title="dom-focus"><a href="#dom-focus">focus()</a></code> method
+ based on the kind of user interaction event from which the call
+ was triggered (if any).</p>
+
+ <p>The focus ring should not be subject to the <a href="#shadows" title="shadows">shadow effects</a>, the <a href="#dom-context-2d-globalalpha" title="dom-context-2d-globalAlpha">global alpha</a>, or the <a href="#dom-context-2d-globalcompositeoperation" title="dom-context-2d-globalCompositeOperation">global composition
+ operators</a>, but <em>should</em> be subject to the <a href="#clipping-region" title="clipping region">clipping region</a>.</p>
+
+ </li>
+
+ <li>
+
+ <p>Optionally, <a href="#inform">inform the user</a> that the
+ focus is at the location given by the path. User agents may wait
+ until the next time the <a href="#event-loop">event loop</a> reaches its
+ &quot;update the rendering&quot; step to optionally inform the user.</p>
+
+ </li>
+
+ </ol><p>The <dfn id="dom-context-2d-drawcustomfocusring" title="dom-context-2d-drawCustomFocusRing"><code>drawCustomFocusRing(<var title="">element</var>)</code></dfn> method, when invoked, must run
+ the following steps:</p>
+
+ <ol><li><p>If <var title="">element</var> is not focused or is not a
+ descendant of the element with whose context the method is
+ associated, then return false and abort these steps.</p></li>
+
+ <li>
+
+ <p>If the user has requested the use of particular focus rings
+ (e.g. high-contrast focus rings), then draw a focus ring of the
+ appropriate style along the path, return false, and abort these
+ steps.</p>
+
+ <p>The focus ring should not be subject to the <a href="#shadows" title="shadows">shadow effects</a>, the <a href="#dom-context-2d-globalalpha" title="dom-context-2d-globalAlpha">global alpha</a>, or the <a href="#dom-context-2d-globalcompositeoperation" title="dom-context-2d-globalCompositeOperation">global composition
+ operators</a>, but <em>should</em> be subject to the <a href="#clipping-region" title="clipping region">clipping region</a>.</p>
+
+ </li>
+
+ <li>
+
+ <p>Optionally, <a href="#inform">inform the user</a> that the
+ focus is at the location given by the path. User agents may wait
+ until the next time the <a href="#event-loop">event loop</a> reaches its
+ &quot;update the rendering&quot; step to optionally inform the user.</p>
+
+ </li>
+
+ <li><p>Return true.</p></li>
+
+ </ol><p>The <dfn id="dom-context-2d-scrollpathintoview" title="dom-context-2d-scrollPathIntoView"><code>scrollPathIntoView()</code></dfn>
+ method, when invoked, must run the following steps:</p>
+
+ <ol><li><p>Let <var title="">notional child</var> be a hypothetical
+ element that is a rendered child of the <code><a href="#the-canvas-element">canvas</a></code> element
+ whose dimensions are exactly the rectangle of the bounding box of
+ the current path.</p></li>
+
+ <li><p><span title="scroll an element into view">Scroll <var title="">notional child</var> into view</span> with the <var title="">align to top flag</var> set.</p>
+
+ </li><li><p>Optionally, <a href="#inform">inform the user</a> that the
+ caret and/or selection cover <var title="">the specified
+ rectangle</var> of the canvas. User agents may wait until the next
+ time the <a href="#event-loop">event loop</a> reaches its &quot;update the rendering&quot;
+ step to optionally inform the user.</p></li>
+
+ </ol><p class="note" id="inform">&quot;Inform the user&quot;, as used in this
+ section, could mean calling a system accessibility API, which would
+ notify assistive technologies such as magnification tools. To
+ properly drive magnification based on a focus change, a system
+ accessibility API driving a screen magnifier needs the bounds for
+ the newly focused object. The methods above are intended to enable
+ this by allowing the user agent to report the bounding box of the
+ path used to render the focus ring as the bounds of the <var title="">element</var> element passed as an argument, if that
+ element is focused, and the bounding box of the area to which the
+ user agent is scrolling as the bounding box of the current
+ selection.</p>
+
+ <hr/><p>The <dfn id="dom-context-2d-clip" title="dom-context-2d-clip"><code>clip()</code></dfn>
+ method must create a new <dfn id="clipping-region">clipping region</dfn> by calculating
+ the intersection of the current clipping region and the area
+ described by the current path, using the non-zero winding number
+ rule. Open subpaths must be implicitly closed when computing the
+ clipping region, without affecting the actual subpaths. The new
+ clipping region replaces the current clipping region.</p>
+
+ <p>When the context is initialized, the clipping region must be set
+ to the rectangle with the top left corner at (0,0) and the width and
+ height of the coordinate space.</p>
+
+ <!-- v6
+ Jordan OSETE suggests:
+ * support ways of extending the clipping region (union instead of intersection)
+ - also "add", "subtract", "replace", "intersect" and "xor"
+ * support ways of resetting the clipping region without save/restore
+ -->
+
+ <hr/><p>The <dfn id="dom-context-2d-ispointinpath" title="dom-context-2d-isPointInPath"><code>isPointInPath(<var title="">x</var>, <var title="">y</var>)</code></dfn> method must
+ return true if the point given by the <var title="">x</var> and <var title="">y</var> coordinates passed to the method, when treated as
+ coordinates in the canvas coordinate space unaffected by the current
+ transformation, is inside the current path as determined by the
+ non-zero winding number rule; and must return false
+ otherwise. Points on the path itself are considered to be inside the
+ path. If either of the arguments is infinite or NaN, then the method
+ must return false.</p>
+
+ </div>
+
+
+ <div class="example" id="drawCustomFocusRingExample">
+
+ <p>This <code><a href="#the-canvas-element">canvas</a></code> element has a couple of checkboxes. The
+ path-related commands are highlighted:</p>
+
+ <pre>&lt;canvas height=400 width=750&gt;
+ &lt;label&gt;&lt;input type=checkbox id=showA&gt; Show As&lt;/label&gt;
+ &lt;label&gt;&lt;input type=checkbox id=showB&gt; Show Bs&lt;/label&gt;
+ &lt;!-- ... --&gt;
+&lt;/canvas&gt;
+&lt;script&gt;
+ function drawCheckbox(context, element, x, y, paint) {
+ context.save();
+ context.font = '10px sans-serif';
+ context.textAlign = 'left';
+ context.textBaseline = 'middle';
+ var metrics = context.measureText(element.labels[0].textContent);
+ if (paint) {
+<strong> context.beginPath();
+ context.strokeStyle = 'black';
+ context.rect(x-5, y-5, 10, 10);
+ context.stroke();
+</strong> if (element.checked) {
+<strong> context.fillStyle = 'black';
+ context.fill();
+</strong> }
+ context.fillText(element.labels[0].textContent, x+5, y);
+ }
+<strong> context.beginPath();
+ context.rect(x-7, y-7, 12 + metrics.width+2, 14);
+ if (paint &amp;&amp; context.drawCustomFocusRing(element)) {
+ context.strokeStyle = 'silver';
+ context.stroke();
+ }
+</strong> context.restore();
+ }
+ function drawBase() { /* ... */ }
+ function drawAs() { /* ... */ }
+ function drawBs() { /* ... */ }
+ function redraw() {
+ var canvas = document.getElementsByTagName('canvas')[0];
+ var context = canvas.getContext('2d');
+ context.clearRect(0, 0, canvas.width, canvas.height);
+ drawCheckbox(context, document.getElementById('showA'), 20, 40, true);
+ drawCheckbox(context, document.getElementById('showB'), 20, 60, true);
+ drawBase();
+ if (document.getElementById('showA').checked)
+ drawAs();
+ if (document.getElementById('showB').checked)
+ drawBs();
+ }
+ function processClick(event) {
+ var canvas = document.getElementsByTagName('canvas')[0];
+ var context = canvas.getContext('2d');
+ var x = event.clientX;
+ var y = event.clientY;
+ while (node) {
+ x -= node.offsetLeft - node.scrollLeft;
+ y -= node.offsetTop - node.scrollTop;
+ node = node.offsetParent;
+ }
+ drawCheckbox(context, document.getElementById('showA'), 20, 40, false);
+ if (<strong>context.isPointInPath(x, y)</strong>)
+ document.getElementById('showA').checked = !(document.getElementById('showA').checked);
+ drawCheckbox(context, document.getElementById('showB'), 20, 60, false);
+ if (<strong>context.isPointInPath(x, y)</strong>)
+ document.getElementById('showB').checked = !(document.getElementById('showB').checked);
+ redraw();
+ }
+ document.getElementsByTagName('canvas')[0].addEventListener('focus', redraw, true);
+ document.getElementsByTagName('canvas')[0].addEventListener('blur', redraw, true);
+ document.getElementsByTagName('canvas')[0].addEventListener('change', redraw, true);
+ document.getElementsByTagName('canvas')[0].addEventListener('click', processClick, false);
+ redraw();
+&lt;/script&gt;</pre>
+<!-- http://software.hixie.ch/utilities/js/live-dom-viewer/saved/340 -->
+
+ </div>
+
+
+
+
+ <h6 id="text-0"><span class="secno">4.8.11.1.9 </span>Text</h6> <!-- a v3 feature -->
+
+ <dl class="domintro"><dt><var title="">context</var> . <code title="dom-context-2d-font"><a href="#dom-context-2d-font">font</a></code> [ = <var title="">value</var> ]</dt>
+
+ <dd>
+
+ <p>Returns the current font settings.</p>
+
+ <p>Can be set, to change the font. The syntax is the same as for
+ the CSS 'font' property; values that cannot be parsed as CSS font
+ values are ignored.</p>
+
+ <p>Relative keywords and lengths are computed relative to the font
+ of the <code><a href="#the-canvas-element">canvas</a></code> element.</p>
+
+ </dd>
+
+ <dt><var title="">context</var> . <code title="dom-context-2d-textAlign"><a href="#dom-context-2d-textalign">textAlign</a></code> [ = <var title="">value</var> ]</dt>
+
+ <dd>
+
+ <p>Returns the current text alignment settings.</p>
+
+ <p>Can be set, to change the alignment. The possible values are
+ <code title="">start</code>, <code title="">end</code>, <code title="">left</code>, <code title="">right</code>, and <code title="">center</code>. Other values are ignored. The default is
+ <code title="">start</code>.</p>
+
+ </dd>
+
+ <dt><var title="">context</var> . <code title="dom-context-2d-textBaseline"><a href="#dom-context-2d-textbaseline">textBaseline</a></code> [ = <var title="">value</var> ]</dt>
+
+ <dd>
+
+ <p>Returns the current baseline alignment settings.</p>
+
+ <p>Can be set, to change the baseline alignment. The possible
+ values and their meanings are given below. Other values are
+ ignored. The default is <code title="">alphabetic</code>.</p>
+
+ </dd>
+
+ <dt><var title="">context</var> . <code title="dom-context-2d-fillText"><a href="#dom-context-2d-filltext">fillText</a></code>(<var title="">text</var>, <var title="">x</var>, <var title="">y</var> [, <var title="">maxWidth</var> ] )</dt>
+ <dt><var title="">context</var> . <code title="dom-context-2d-strokeText"><a href="#dom-context-2d-stroketext">strokeText</a></code>(<var title="">text</var>, <var title="">x</var>, <var title="">y</var> [, <var title="">maxWidth</var> ] )</dt>
+
+ <dd>
+
+ <p>Fills or strokes (respectively) the given text at the given
+ position. If a maximum width is provided, the text will be scaled
+ to fit that width if necessary.</p>
+
+ </dd>
+
+ <dt><var title="">metrics</var> = <var title="">context</var> . <code title="dom-context-2d-measureText"><a href="#dom-context-2d-measuretext">measureText</a></code>(<var title="">text</var>)</dt>
+
+ <dd>
+
+ <p>Returns a <code><a href="#textmetrics">TextMetrics</a></code> object with the metrics of the given text in the current font.</p>
+
+ </dd>
+
+ <dt><var title="">metrics</var> . <code title="dom-textmetrics-width"><a href="#dom-textmetrics-width">width</a></code></dt>
+
+ <dd>
+
+ <p>Returns the advance width of the text that was passed to the
+ <code title="dom-context-2d-measureText"><a href="#dom-context-2d-measuretext">measureText()</a></code>
+ method.</p>
+
+ </dd>
+
+ </dl><div class="impl">
+
+ <p>The <dfn id="dom-context-2d-font" title="dom-context-2d-font"><code>font</code></dfn> IDL
+ attribute, on setting, must be parsed the same way as the 'font'
+ property of CSS (but without supporting property-independent style
+ sheet syntax like 'inherit'), and the resulting font must be
+ assigned to the context, with the 'line-height' component forced to
+ 'normal', with the 'font-size' component converted to CSS pixels,
+ and with system fonts being computed to explicit values. If the new
+ value is syntactically incorrect (including using
+ property-independent style sheet syntax like 'inherit' or
+ 'initial'), then it must be ignored, without assigning a new font
+ value. <a href="#refsCSS">[CSS]</a></p>
+
+ <p>Font names must be interpreted in the context of the
+ <code><a href="#the-canvas-element">canvas</a></code> element's stylesheets; any fonts embedded using
+ <code title="">@font-face</code> must therefore be available once
+ they are loaded. (If a font is referenced before it is fully loaded,
+ then it must be treated as if it was an unknown font, falling back
+ to another as described by the relevant CSS specifications.) <a href="#refsCSSFONTS">[CSSFONTS]</a></p>
+
+ <p>Only vector fonts should be used by the user agent; if a user
+ agent were to use bitmap fonts then transformations would likely
+ make the font look very ugly.</p>
+
+ <p>On getting, the <code title="dom-context-2d-font"><a href="#dom-context-2d-font">font</a></code>
+ attribute must return the <span title="serializing a CSS
+ value">serialized form</span> of the current font of the context
+ (with no 'line-height' component). <a href="#refsCSSOM">[CSSOM]</a></p>
+
+ <div class="example">
+
+ <p>For example, after the following statement:</p>
+
+ <pre>context.font = 'italic 400 12px/2 Unknown Font, sans-serif';</pre>
+
+ <p>...the expression <code title="">context.font</code> would
+ evaluate to the string &quot;<code title="">italic 12px &quot;Unknown Font&quot;, sans-serif</code>&quot;. The
+ &quot;400&quot; font-weight doesn't appear because that is the default
+ value. The line-height doesn't appear because it is forced to
+ &quot;normal&quot;, the default value.</p>
+
+ </div>
+
+ <p>When the context is created, the font of the context must be set
+ to 10px sans-serif. When the 'font-size' component is set to lengths
+ using percentages, 'em' or 'ex' units, or the 'larger' or 'smaller'
+ keywords, these must be interpreted relative to the computed value
+ of the 'font-size' property of the corresponding <code><a href="#the-canvas-element">canvas</a></code>
+ element at the time that the attribute is set. When the
+ 'font-weight' component is set to the relative values 'bolder' and
+ 'lighter', these must be interpreted relative to the computed value
+ of the 'font-weight' property of the corresponding
+ <code><a href="#the-canvas-element">canvas</a></code> element at the time that the attribute is
+ set. If the computed values are undefined for a particular case
+ (e.g. because the <code><a href="#the-canvas-element">canvas</a></code> element is not <a href="#in-a-document">in a
+ <code>Document</code></a>), then the relative keywords must be
+ interpreted relative to the normal-weight 10px sans-serif
+ default.</p>
+
+ <p>The <dfn id="dom-context-2d-textalign" title="dom-context-2d-textAlign"><code>textAlign</code></dfn> IDL
+ attribute, on getting, must return the current value. On setting, if
+ the value is one of <code title="">start</code>, <code title="">end</code>, <code title="">left</code>, <code title="">right</code>, or <code title="">center</code>, then the
+ value must be changed to the new value. Otherwise, the new value
+ must be ignored. When the context is created, the <code title="dom-context-2d-textAlign"><a href="#dom-context-2d-textalign">textAlign</a></code> attribute must
+ initially have the value <code title="">start</code>.</p>
+
+ <p>The <dfn id="dom-context-2d-textbaseline" title="dom-context-2d-textBaseline"><code>textBaseline</code></dfn>
+ IDL attribute, on getting, must return the current value. On
+ setting, if the value is one of <code title="dom-context-2d-textBaseline-top"><a href="#dom-context-2d-textbaseline-top">top</a></code>, <code title="dom-context-2d-textBaseline-hanging"><a href="#dom-context-2d-textbaseline-hanging">hanging</a></code>, <code title="dom-context-2d-textBaseline-middle"><a href="#dom-context-2d-textbaseline-middle">middle</a></code>, <code title="dom-context-2d-textBaseline-alphabetic"><a href="#dom-context-2d-textbaseline-alphabetic">alphabetic</a></code>,
+ <code title="dom-context-2d-textBaseline-ideographic"><a href="#dom-context-2d-textbaseline-ideographic">ideographic</a></code>,
+ or <code title="dom-context-2d-textBaseline-bottom"><a href="#dom-context-2d-textbaseline-bottom">bottom</a></code>,
+ then the value must be changed to the new value. Otherwise, the new
+ value must be ignored. When the context is created, the <code title="dom-context-2d-textBaseline"><a href="#dom-context-2d-textbaseline">textBaseline</a></code> attribute
+ must initially have the value <code title="">alphabetic</code>.</p>
+
+ </div>
+
+ <p>The <code title="dom-context-2d-textBaseline"><a href="#dom-context-2d-textbaseline">textBaseline</a></code>
+ attribute's allowed keywords correspond to alignment points in the
+ font:</p>
+
+ <p><img alt="The top of the em square is roughly at the top of the glyphs in a font, the hanging baseline is where some glyphs like आ are anchored, the middle is half-way between the top of the em square and the bottom of the em square, the alphabetic baseline is where characters like Á, ÿ, f, and Ω are anchored, the ideographic baseline is where glyphs like 私 and 達 are anchored, and the bottom of the em square is roughly at the bottom of the glyphs in a font. The top and bottom of the bounding box can be far from these baselines, due to glyphs extending far outside the em square." height="300" src="http://www.whatwg.org/specs/web-apps/current-work/http://images.whatwg.org/baselines.png" width="738"/></p>
+
+ <p>The keywords map to these alignment points as follows:</p>
+
+ <dl><dt><dfn id="dom-context-2d-textbaseline-top" title="dom-context-2d-textBaseline-top"><code>top</code></dfn>
+ </dt><dd>The top of the em square</dd>
+
+ <dt><dfn id="dom-context-2d-textbaseline-hanging" title="dom-context-2d-textBaseline-hanging"><code>hanging</code></dfn>
+ </dt><dd>The hanging baseline</dd>
+
+ <dt><dfn id="dom-context-2d-textbaseline-middle" title="dom-context-2d-textBaseline-middle"><code>middle</code></dfn>
+ </dt><dd>The middle of the em square</dd>
+
+ <dt><dfn id="dom-context-2d-textbaseline-alphabetic" title="dom-context-2d-textBaseline-alphabetic"><code>alphabetic</code></dfn>
+ </dt><dd>The alphabetic baseline</dd>
+
+ <dt><dfn id="dom-context-2d-textbaseline-ideographic" title="dom-context-2d-textBaseline-ideographic"><code>ideographic</code></dfn>
+ </dt><dd>The ideographic baseline</dd>
+
+ <dt><dfn id="dom-context-2d-textbaseline-bottom" title="dom-context-2d-textBaseline-bottom"><code>bottom</code></dfn>
+ </dt><dd>The bottom of the em square</dd>
+
+ </dl><div class="impl">
+
+ <p>The <dfn id="dom-context-2d-filltext" title="dom-context-2d-fillText"><code>fillText()</code></dfn> and
+ <dfn id="dom-context-2d-stroketext" title="dom-context-2d-strokeText"><code>strokeText()</code></dfn>
+ methods take three or four arguments, <var title="">text</var>, <var title="">x</var>, <var title="">y</var>, and optionally <var title="">maxWidth</var>, and render the given <var title="">text</var> at the given (<var title="">x</var>, <var title="">y</var>) coordinates ensuring that the text isn't wider
+ than <var title="">maxWidth</var> if specified, using the current
+ <code title="dom-context-2d-font"><a href="#dom-context-2d-font">font</a></code>, <code title="dom-context-2d-textAlign"><a href="#dom-context-2d-textalign">textAlign</a></code>, and <code title="dom-context-2d-textBaseline"><a href="#dom-context-2d-textbaseline">textBaseline</a></code>
+ values. Specifically, when the methods are called, the user agent
+ must run the following steps:</p>
+
+ <ol><li><p>If <var title="">maxWidth</var> is present but less than or
+ equal to zero, return without doing anything; abort these
+ steps.</p></li>
+
+ <li><p>Let <var title="">font</var> be the current font of the
+ context, as given by the <code title="dom-context-2d-font"><a href="#dom-context-2d-font">font</a></code> attribute.</p></li>
+
+ <li><p>Replace all the <a href="#space-character" title="space character">space
+ characters</a> in <var title="">text</var> with U+0020 SPACE
+ characters.</p></li>
+
+ <li><p>Form a hypothetical infinitely wide CSS line box containing
+ a single inline box containing the text <var title="">text</var>,
+ with all the properties at their initial values except the 'font'
+ property of the inline box set to <var title="">font</var>, the
+ 'direction' property of the inline box set to <a href="#the-directionality">the
+ directionality</a> of the <code><a href="#the-canvas-element">canvas</a></code> element, and the
+ 'white-space' property set to 'pre'. <a href="#refsCSS">[CSS]</a></p></li>
+
+ <!-- if you insert a step here, make sure to adjust the next step's
+ final words -->
+
+ <li><p>If the <var title="">maxWidth</var> argument was specified
+ and the hypothetical width of the inline box in the hypothetical
+ line box is greater than <var title="">maxWidth</var> CSS pixels,
+ then change <var title="">font</var> to have a more condensed font
+ (if one is available or if a reasonably readable one can be
+ synthesized by applying a horizontal scale factor to the font) or a
+ smaller font, and return to the previous step.</p></li>
+
+ <li>
+
+ <p>Let the <var title="">anchor point</var> be a point on the
+ inline box, determined by the <code title="dom-context-2d-textAlign"><a href="#dom-context-2d-textalign">textAlign</a></code> and <code title="dom-context-2d-textBaseline"><a href="#dom-context-2d-textbaseline">textBaseline</a></code> values, as
+ follows:</p>
+
+ <p>Horizontal position:</p>
+
+ <dl><dt> If <code title="dom-context-2d-textAlign"><a href="#dom-context-2d-textalign">textAlign</a></code> is <code title="">left</code></dt>
+ <dt> If <code title="dom-context-2d-textAlign"><a href="#dom-context-2d-textalign">textAlign</a></code> is <code title="">start</code> and <a href="#the-directionality">the directionality</a> of the
+ <code><a href="#the-canvas-element">canvas</a></code> element is 'ltr'</dt>
+ <dt> If <code title="dom-context-2d-textAlign"><a href="#dom-context-2d-textalign">textAlign</a></code> is <code title="">end</code> and <a href="#the-directionality">the directionality</a> of the
+ <code><a href="#the-canvas-element">canvas</a></code> element is 'rtl'</dt>
+
+ <dd>Let the <var title="">anchor point</var>'s horizontal
+ position be the left edge of the inline box.</dd>
+
+
+ <dt> If <code title="dom-context-2d-textAlign"><a href="#dom-context-2d-textalign">textAlign</a></code> is <code title="">right</code></dt>
+ <dt> If <code title="dom-context-2d-textAlign"><a href="#dom-context-2d-textalign">textAlign</a></code> is <code title="">end</code> and <a href="#the-directionality">the directionality</a> of the
+ <code><a href="#the-canvas-element">canvas</a></code> element is 'ltr'</dt>
+ <dt> If <code title="dom-context-2d-textAlign"><a href="#dom-context-2d-textalign">textAlign</a></code> is <code title="">start</code> and <a href="#the-directionality">the directionality</a> of the
+ <code><a href="#the-canvas-element">canvas</a></code> element is 'rtl'</dt>
+
+ <dd>Let the <var title="">anchor point</var>'s horizontal
+ position be the right edge of the inline box.</dd>
+
+
+ <dt> If <code title="dom-context-2d-textAlign"><a href="#dom-context-2d-textalign">textAlign</a></code> is <code title="">center</code></dt>
+
+ <dd>Let the <var title="">anchor point</var>'s horizontal
+ position be half way between the left and right edges of the
+ inline box.</dd>
+
+ </dl><p>Vertical position:</p>
+
+ <dl><dt> If <code title="dom-context-2d-textBaseline"><a href="#dom-context-2d-textbaseline">textBaseline</a></code> is <code title="dom-context-2d-textBaseline-top"><a href="#dom-context-2d-textbaseline-top">top</a></code></dt>
+
+ <dd>Let the <var title="">anchor point</var>'s vertical position
+ be the top of the em box of the first available font of the
+ inline box.</dd>
+
+
+ <dt> If <code title="dom-context-2d-textBaseline"><a href="#dom-context-2d-textbaseline">textBaseline</a></code> is <code title="dom-context-2d-textBaseline-hanging"><a href="#dom-context-2d-textbaseline-hanging">hanging</a></code></dt>
+
+ <dd>Let the <var title="">anchor point</var>'s vertical position
+ be the hanging baseline of the first available font of the inline
+ box.</dd>
+
+
+ <dt> If <code title="dom-context-2d-textBaseline"><a href="#dom-context-2d-textbaseline">textBaseline</a></code> is <code title="dom-context-2d-textBaseline-middle"><a href="#dom-context-2d-textbaseline-middle">middle</a></code></dt>
+
+ <dd>Let the <var title="">anchor point</var>'s vertical position
+ be half way between the bottom and the top of the em box of the
+ first available font of the inline box.</dd>
+
+
+ <dt> If <code title="dom-context-2d-textBaseline"><a href="#dom-context-2d-textbaseline">textBaseline</a></code> is <code title="dom-context-2d-textBaseline-alphabetic"><a href="#dom-context-2d-textbaseline-alphabetic">alphabetic</a></code></dt>
+
+ <dd>Let the <var title="">anchor point</var>'s vertical position
+ be the alphabetic baseline of the first available font of the inline
+ box.</dd>
+
+
+ <dt> If <code title="dom-context-2d-textBaseline"><a href="#dom-context-2d-textbaseline">textBaseline</a></code> is <code title="dom-context-2d-textBaseline-ideographic"><a href="#dom-context-2d-textbaseline-ideographic">ideographic</a></code></dt>
+
+ <dd>Let the <var title="">anchor point</var>'s vertical position
+ be the ideographic baseline of the first available font of the inline
+ box.</dd>
+
+
+ <dt> If <code title="dom-context-2d-textBaseline"><a href="#dom-context-2d-textbaseline">textBaseline</a></code> is <code title="dom-context-2d-textBaseline-bottom"><a href="#dom-context-2d-textbaseline-bottom">bottom</a></code></dt>
+
+ <dd>Let the <var title="">anchor point</var>'s vertical position
+ be the bottom of the em box of the first available font of the
+ inline box.</dd>
+
+ </dl></li>
+
+ <li>
+
+ <p>Paint the hypothetical inline box as the shape given by the
+ text's glyphs, as transformed by the <a href="#transformations" title="dom-context-2d-transformation">current transformation
+ matrix</a>, and anchored and sized so that before applying the
+ <a href="#transformations" title="dom-context-2d-transformation">current transformation
+ matrix</a>, the <var title="">anchor point</var> is at (<var title="">x</var>, <var title="">y</var>) and each CSS pixel is
+ mapped to one coordinate space unit.</p>
+
+ <p>For <code title="dom-context-2d-fillText"><a href="#dom-context-2d-filltext">fillText()</a></code>
+ <code title="dom-context-2d-fillStyle"><a href="#dom-context-2d-fillstyle">fillStyle</a></code> must be
+ applied to the glyphs and <code title="dom-context-2d-strokeStyle"><a href="#dom-context-2d-strokestyle">strokeStyle</a></code> must be
+ ignored. For <code title="dom-context-2d-strokeText"><a href="#dom-context-2d-stroketext">strokeText()</a></code> the reverse
+ holds and <code title="dom-context-2d-strokeStyle"><a href="#dom-context-2d-strokestyle">strokeStyle</a></code> must be
+ applied to the glyph outlines and <code title="dom-context-2d-fillStyle"><a href="#dom-context-2d-fillstyle">fillStyle</a></code> must be
+ ignored.</p>
+
+ <p>Text is painted without affecting the current path, and is
+ subject to <a href="#shadows" title="shadows">shadow effects</a>, <a href="#dom-context-2d-globalalpha" title="dom-context-2d-globalAlpha">global alpha</a>, the <a href="#clipping-region" title="clipping region">clipping region</a>, and <a href="#dom-context-2d-globalcompositeoperation" title="dom-context-2d-globalCompositeOperation">global composition
+ operators</a>.</p>
+
+ </li>
+
+ </ol><!--v6DVT - this is commented out until CSS can get its act together
+enough to actual specify vertical text rendering (how long have we
+been waiting now?)
+
+WHEN EDITING THIS, FIX THE PARTS MARKED "&#x0058;&#x0058;&#x0058;" BELOW
+
+ <p>The <dfn
+ title="dom-context-2d-fillVerticalText"><code>fillVerticalText()</code></dfn>
+ and <dfn
+ title="dom-context-2d-strokeVerticalText"><code>strokeVerticalText()</code></dfn>
+ methods take three or four arguments, <var title="">text</var>, <var
+ title="">x</var>, <var title="">y</var>, and optionally <var
+ title="">maxHeight</var>, and render the given <var
+ title="">text</var> as vertical text at the given (<var
+ title="">x</var>, <var title="">y</var>) coordinates ensuring that
+ the text isn't taller than <var title="">maxHeight</var> if
+ specified, using the current <code
+ title="dom-context-2d-font">font</code> and <code
+ title="dom-context-2d-textAlign">textAlign</code>
+ values. Specifically, when the methods are called, the user agent
+ must run the following steps:</p>
+
+ <ol>
+
+ <li><p>If <var title="">maxHeight</var> is present but less than or
+ equal to zero, return without doing anything; abort these
+ steps.</p></li>
+
+ <li><p>Let <var title="">font</var> be the current font of the
+ context, as given by the <code
+ title="dom-context-2d-font">font</code> attribute.</p></li>
+
+ <li><p>Replace all the <span title="space character">space
+ characters</span> in <var title="">text</var> with U+0020 SPACE
+ characters.</p></li>
+
+ <li><p>Form a <em class="&#x0058;&#x0058;&#x0058;">whatever CSS ends up calling
+ vertical line boxes and inline boxes</em> containing the text <var
+ title="">text</var>, with all the properties at their initial
+ values except the 'font' property of the inline box set to <var
+ title="">font</var> and the 'direction' property of the inline
+ box set to <span>the directionality</span> of the <code>canvas</code>
+ element.</p></li>
+
+ <!- - if you insert a step here, make sure to adjust the next step's
+ final words - ->
+
+ <li><p>If the <var title="">maxHeight</var> argument was specified
+ and the hypothetical height of the <em class="&#x0058;&#x0058;&#x0058;">box</em>
+ in the hypothetical line box is greater than <var
+ title="">maxHeight</var> CSS pixels, then change <var
+ title="">font</var> to have a more condensed font (if one is
+ available or if a reasonably readable one can be synthesized by
+ applying an appropriate scale factor to the font) or a smaller
+ font, and return to the previous step.</p></li>
+
+ <li>
+
+ <p>Let the <var title="">anchor point</var> be a point on the <em
+ class="&#x0058;&#x0058;&#x0058;">inline box</var>, determined by the <code
+ title="dom-context-2d-textAlign">textAlign</code>, as follows:</p>
+
+ <p>Vertical position:</p>
+
+ <dl>
+
+ <dt> If <code
+ title="dom-context-2d-textAlign">textAlign</code> is <code
+ title="">start</code></dt>
+ <dt> If <code
+ title="dom-context-2d-textAlign">textAlign</code> is <code
+ title="">left</code> and <span>the directionality</span> of the
+ <code>canvas</code> element is 'ltr'</dt>
+ <dt> If <code
+ title="dom-context-2d-textAlign">textAlign</code> is <code
+ title="">right</code> and <span>the directionality</span> of the
+ <code>canvas</code> element is 'rtl'</dt>
+
+ <dd>Let the <var title="">anchor point</var>'s vertical
+ position be the top edge of the <em class="&#x0058;&#x0058;&#x0058;">inline
+ box</em>.</dd>
+
+ <dt> If <code
+ title="dom-context-2d-textAlign">textAlign</code> is <code
+ title="">end</code></dt>
+ <dt> If <code
+ title="dom-context-2d-textAlign">textAlign</code> is <code
+ title="">right</code> and <span>the directionality</span> of the
+ <code>canvas</code> element is 'ltr'</dt>
+ <dt> If <code
+ title="dom-context-2d-textAlign">textAlign</code> is <code
+ title="">left</code> and <span>the directionality</span> of the
+ <code>canvas</code> element is 'rtl'</dt>
+
+ <dd>Let the <var title="">anchor point</var>'s vertical
+ position be the bottom edge of the <em class="&#x0058;&#x0058;&#x0058;">inline
+ box</em>.</dd>
+
+
+ <dt> If <code
+ title="dom-context-2d-textAlign">textAlign</code> is <code
+ title="">center</code></dt>
+
+ <dd>Let the <var title="">anchor point</var>'s vertical position
+ be half way between the top and bottom edges of the <em
+ class="&#x0058;&#x0058;&#x0058;">inline box</em>.</dd>
+
+ </dl>
+
+ <p>Let the horizontal position be half way between the left and
+ right edges of the em box of the first available font of the <em
+ class="&#x0058;&#x0058;&#x0058;">inline box</em>.</p>
+
+ </li>
+
+ <li>
+
+ <p>Paint the hypothetical inline box as the shape given by the
+ text's glyphs, as transformed by the <span
+ title="dom-context-2d-transformation">current transformation
+ matrix</span>, and anchored and sized so that before applying the
+ <span title="dom-context-2d-transformation">current transformation
+ matrix</span>, the <var title="">anchor point</var> is at (<var
+ title="">x</var>, <var title="">y</var>) and each CSS pixel is
+ mapped to one coordinate space unit.</p>
+
+ <p>For <code
+ title="dom-context-2d-fillVerticalText">fillVerticalText()</code>
+ <code title="dom-context-2d-fillStyle">fillStyle</code> must be
+ applied and <code
+ title="dom-context-2d-strokeStyle">strokeStyle</code> must be
+ ignored. For <code
+ title="dom-context-2d-strokeVerticalText">strokeVerticalText()</code>
+ the reverse holds and <code
+ title="dom-context-2d-strokeStyle">strokeStyle</code> must be
+ applied and <code
+ title="dom-context-2d-fillStyle">fillStyle</code> must be
+ ignored.</p>
+
+ <p>Text is painted without affecting the current path, and is
+ subject to <span title="shadows">shadow effects</span>, <span
+ title="dom-context-2d-globalAlpha">global alpha</span>, the <span
+ title="clipping region">clipping region</span>, and <span
+ title="dom-context-2d-globalCompositeOperation">global composition
+ operators</span>.</p>
+
+ </li>
+
+ </ol>
+
+v6DVT (also check for '- -' bits in the part above) --><p>The <dfn id="dom-context-2d-measuretext" title="dom-context-2d-measureText"><code>measureText()</code></dfn>
+ method takes one argument, <var title="">text</var>. When the method
+ is invoked, the user agent must replace all the <a href="#space-character" title="space
+ character">space characters</a> in <var title="">text</var> with
+ U+0020 SPACE characters, and then must form a hypothetical
+ infinitely wide CSS line box containing a single inline box
+ containing the text <var title="">text</var>, with all the
+ properties at their initial values except the 'white-space' property
+ of the inline element set to 'pre' and the 'font' property of the
+ inline element set to the current font of the context as given by
+ the <code title="dom-context-2d-font"><a href="#dom-context-2d-font">font</a></code> attribute, and
+ must then return a new <code><a href="#textmetrics">TextMetrics</a></code> object with its
+ <code title="dom-textmetrics-width"><a href="#dom-textmetrics-width">width</a></code> attribute set to
+ the width of that inline box, in CSS pixels. <a href="#refsCSS">[CSS]</a></p>
+
+ <p>The <code><a href="#textmetrics">TextMetrics</a></code> interface is used for the objects
+ returned from <code title="dom-context-2d-measureText"><a href="#dom-context-2d-measuretext">measureText()</a></code>. It has one
+ attribute, <dfn id="dom-textmetrics-width" title="dom-textmetrics-width"><code>width</code></dfn>, which is set
+ by the <code title="dom-context-2d-measureText"><a href="#dom-context-2d-measuretext">measureText()</a></code>
+ method.</p>
+
+ <p class="note">Glyphs rendered using <code title="dom-context-2d-fillText"><a href="#dom-context-2d-filltext">fillText()</a></code> and <code title="dom-context-2d-strokeText"><a href="#dom-context-2d-stroketext">strokeText()</a></code> can spill out
+ of the box given by the font size (the em square size) and the width
+ returned by <code title="dom-context-2d-measureText"><a href="#dom-context-2d-measuretext">measureText()</a></code> (the text
+ width). This version of the specification does not provide a way to
+ obtain the bounding box dimensions of the text. If the text is to be
+ rendered and removed, care needs to be taken to replace the entire
+ area of the canvas that the clipping region covers, not just the box
+ given by the em square height and measured text width.</p>
+
+ <!-- v6: Drawing text along a given path -->
+ <!-- v6: Adding text to a path -->
+ <!-- see also: http://www.w3.org/TR/SVG11/text.html#TextpathLayoutRules -->
+ <!-- see also: http://developer.mozilla.org/en/docs/Drawing_text_using_a_canvas -->
+
+ </div>
+
+ <p class="note">A future version of the 2D context API may provide a
+ way to render fragments of documents, rendered using CSS, straight
+ to the canvas. This would be provided in preference to a dedicated
+ way of doing multiline layout.</p>
+
+
+
+ <h6 id="images"><span class="secno">4.8.11.1.10 </span>Images</h6>
+
+ <p>To draw images onto the canvas, the <dfn id="dom-context-2d-drawimage" title="dom-context-2d-drawImage"><code>drawImage</code></dfn> method
+ can be used.</p>
+
+ <p>This method can be invoked with three different sets of arguments:</p>
+
+ <ul class="brief"><li><code title="">drawImage(<var title="">image</var>, <var title="">dx</var>, <var title="">dy</var>)</code>
+ </li><li><code title="">drawImage(<var title="">image</var>, <var title="">dx</var>, <var title="">dy</var>, <var title="">dw</var>, <var title="">dh</var>)</code>
+ </li><li><code title="">drawImage(<var title="">image</var>, <var title="">sx</var>, <var title="">sy</var>, <var title="">sw</var>, <var title="">sh</var>, <var title="">dx</var>, <var title="">dy</var>, <var title="">dw</var>, <var title="">dh</var>)</code>
+ </li></ul><!-- v3: drawImage() of an ImageData object might make sense (when resizing as well as filtering) - ack Charles Pritchard --><p>Each of those three can take either an
+ <code><a href="#htmlimageelement">HTMLImageElement</a></code>, an <code><a href="#htmlcanvaselement">HTMLCanvasElement</a></code>, or
+ an <code><a href="#htmlvideoelement">HTMLVideoElement</a></code> for the <var title="">image</var>
+ argument.</p>
+
+ <dl class="domintro"><dt><var title="">context</var> . <code title="dom-context-2d-drawImage"><a href="#dom-context-2d-drawimage">drawImage</a></code>(<var title="">image</var>, <var title="">dx</var>, <var title="">dy</var>)</dt>
+ <dt><var title="">context</var> . <code title="dom-context-2d-drawImage"><a href="#dom-context-2d-drawimage">drawImage</a></code>(<var title="">image</var>, <var title="">dx</var>, <var title="">dy</var>, <var title="">dw</var>, <var title="">dh</var>)</dt>
+ <dt><var title="">context</var> . <code title="dom-context-2d-drawImage"><a href="#dom-context-2d-drawimage">drawImage</a></code>(<var title="">image</var>, <var title="">sx</var>, <var title="">sy</var>, <var title="">sw</var>, <var title="">sh</var>, <var title="">dx</var>, <var title="">dy</var>, <var title="">dw</var>, <var title="">dh</var>)</dt>
+
+ <dd>
+
+ <p>Draws the given image onto the canvas. The arguments are
+ interpreted as follows:</p>
+
+ <p><img alt="The sx and sy parameters give the x and y coordinates of the source rectangle; the sw and sh arguments give the width and height of the source rectangle; the dx and dy give the x and y coordinates of the destination rectangle; and the dw and dh arguments give the width and height of the destination rectangle." height="356" src="http://www.whatwg.org/specs/web-apps/current-work/http://images.whatwg.org/drawImage.png" width="356"/></p>
+
+ <p>If the first argument isn't an <code><a href="#the-img-element">img</a></code>,
+ <code><a href="#the-canvas-element">canvas</a></code>, or <code><a href="#the-video-element">video</a></code> element, throws a
+ <code><a href="#type_mismatch_err">TYPE_MISMATCH_ERR</a></code> exception. If the image has no
+ image data, throws an <code><a href="#invalid_state_err">INVALID_STATE_ERR</a></code> exception. If
+ the one of the source rectangle dimensions is zero, throws an
+ <code><a href="#index_size_err">INDEX_SIZE_ERR</a></code> exception. If the image isn't yet
+ fully decoded, then nothing is drawn.</p>
+
+ </dd>
+
+ </dl><div class="impl">
+
+ <p>If not specified, the <var title="">dw</var> and <var title="">dh</var> arguments must default to the values of <var title="">sw</var> and <var title="">sh</var>, interpreted such that
+ one CSS pixel in the image is treated as one unit in the canvas
+ coordinate space. If the <var title="">sx</var>, <var title="">sy</var>, <var title="">sw</var>, and <var title="">sh</var> arguments are omitted, they must default to 0, 0,
+ the image's intrinsic width in image pixels, and the image's
+ intrinsic height in image pixels, respectively. If the image has no
+ intrinsic dimensions, the <i>concrete object size</i> must be used
+ instead, as determined using the CSS &quot;<a href="http://dev.w3.org/csswg/css3-images/#default-sizing">Concrete
+ Object Size Resolution</a>&quot; algorithm, with the <i>specified
+ size</i> having neither a definite width nor height, nor any
+ additional contraints, the object's intrinsic properties being those
+ of the <var title="">image</var> argument, and the <i>default object
+ size</i> being the size of the <code><a href="#the-canvas-element">canvas</a></code> element. <a href="#refsCSSIMAGES">[CSSIMAGES]</a></p>
+
+ <p>The <var title="">image</var> argument is an instance of either
+ <code><a href="#htmlimageelement">HTMLImageElement</a></code>, <code><a href="#htmlcanvaselement">HTMLCanvasElement</a></code>, or
+ <code><a href="#htmlvideoelement">HTMLVideoElement</a></code>.</p> <!-- createPattern() has an
+ equivalent paragraph -->
+
+ <p>If the <var title="">image</var> argument is an
+ <code><a href="#htmlimageelement">HTMLImageElement</a></code> object that is not <a href="#img-good" title="img-good">fully decodable</a>, or if the <var title="">image</var> argument is an <code><a href="#htmlvideoelement">HTMLVideoElement</a></code>
+ object whose <code title="dom-media-readyState"><a href="#dom-media-readystate">readyState</a></code>
+ attribute is either <code title="dom-media-HAVE_NOTHING"><a href="#dom-media-have_nothing">HAVE_NOTHING</a></code> or <code title="dom-media-HAVE_METADATA"><a href="#dom-media-have_metadata">HAVE_METADATA</a></code>, then the
+ implementation must return without drawing anything.</p> <!--
+ createPattern() has an equivalent paragraph -->
+
+ <p>If the <var title="">image</var> argument is an
+ <code><a href="#htmlcanvaselement">HTMLCanvasElement</a></code> object with either a horizontal
+ dimension or a vertical dimension equal to zero, then the
+ implementation must raise an <code><a href="#invalid_state_err">INVALID_STATE_ERR</a></code>
+ exception.</p>
+ <!-- createPattern() has an equivalent paragraph -->
+
+ <p>The source rectangle is the rectangle whose corners are the four
+ points (<var title="">sx</var>, <var title="">sy</var>), (<span title=""><var title="">sx</var>+<var title="">sw</var></span>, <var title="">sy</var>), (<span title=""><var title="">sx</var>+<var title="">sw</var></span>, <span title=""><var title="">sy</var>+<var title="">sh</var></span>), (<var title="">sx</var>, <span title=""><var title="">sy</var>+<var title="">sh</var></span>).</p>
+
+ <p>If one of the <var title="">sw</var> or <var title="">sh</var>
+ arguments is zero, the implementation must raise an
+ <code><a href="#index_size_err">INDEX_SIZE_ERR</a></code> exception.</p>
+
+ <p>The destination rectangle is the rectangle whose corners are the
+ four points (<var title="">dx</var>, <var title="">dy</var>),
+ (<span title=""><var title="">dx</var>+<var title="">dw</var></span>, <var title="">dy</var>), (<span title=""><var title="">dx</var>+<var title="">dw</var></span>, <span title=""><var title="">dy</var>+<var title="">dh</var></span>), (<var title="">dx</var>, <span title=""><var title="">dy</var>+<var title="">dh</var></span>).</p>
+
+ <p>When <code title="dom-context-2d-drawImage"><a href="#dom-context-2d-drawimage">drawImage()</a></code> is
+ invoked, the region of the image specified by the source rectangle
+ must be painted on the region of the canvas specified by the
+ destination rectangle, after applying the <a href="#transformations" title="dom-context-2d-transformation">current transformation
+ matrix</a> to the points of the destination rectangle.</p>
+
+ <p>The original image data of the source image must be used, not the
+ image as it is rendered (e.g. <code title="attr-dim-width"><a href="#attr-dim-width">width</a></code> and <code title="attr-dim-height"><a href="#attr-dim-height">height</a></code> attributes on the source
+ element have no effect). The image data must be processed in the
+ original direction, even if the dimensions given are negative. <!--
+ remove that last sentence if it causes confusion. Someone once
+ suggested that 5,5,-2,-2 was different than 3,3,2,2; this is trying
+ to clarify that this is no the case. --></p>
+
+ <p class="note">This specification does not define the algorithm to
+ use when scaling the image, if necessary.</p>
+
+ <p class="note">When a canvas is drawn onto itself, the <a href="#drawing-model">drawing
+ model</a> requires the source to be copied before the image is drawn
+ back onto the canvas, so it is possible to copy parts of a canvas
+ onto overlapping parts of itself.</p>
+
+ <p>If the original image data is a bitmap image, the value painted
+ at a point in the destination rectangle is computed by filtering the
+ original image data. The user agent may use any filtering algorithm
+ (for example bilinear interpolation or nearest-neighbor). When the
+ filtering algorithm requires a pixel value from outside the original
+ image data, it must instead use the value from the nearest edge
+ pixel. (That is, the filter uses 'clamp-to-edge' behavior.)</p>
+ <!-- see CORE-32111 and:
+ http://krijnhoetmer.nl/irc-logs/whatwg/20100818#l-737
+ http://www.w3.org/Bugs/Public/show_bug.cgi?id=10799#c11
+ -->
+ <!-- createPattern() has a similar paragraph with different rules -->
+
+ <p>When the <code title="dom-context-2d-drawImage"><a href="#dom-context-2d-drawimage">drawImage()</a></code> method
+ is passed an animated image as its <var title="">image</var>
+ argument, the user agent must use the poster frame of the animation,
+ or, if there is no poster frame, the first frame of the
+ animation.</p>
+ <!-- createPattern() has an equivalent paragraph -->
+
+ <p>When the <var title="">image</var> argument is an
+ <code><a href="#htmlvideoelement">HTMLVideoElement</a></code>, then the frame at the <a href="#current-playback-position">current
+ playback position</a> must be used as the source image, and the
+ source image's dimensions must be the <a href="#concept-video-intrinsic-width" title="concept-video-intrinsic-width">intrinsic width</a> and
+ <a href="#concept-video-intrinsic-height" title="concept-video-intrinsic-height">intrinsic height</a>
+ of the <a href="#media-resource">media resource</a> (i.e. after any aspect-ratio
+ correction has been applied).</p>
+ <!-- createPattern() has an equivalent paragraph -->
+
+ <p>Images are painted without affecting the current path, and are
+ subject to <a href="#shadows" title="shadows">shadow effects</a>, <a href="#dom-context-2d-globalalpha" title="dom-context-2d-globalAlpha">global alpha</a>, the <a href="#clipping-region" title="clipping region">clipping region</a>, and <a href="#dom-context-2d-globalcompositeoperation" title="dom-context-2d-globalCompositeOperation">global composition
+ operators</a>.</p>
+
+ </div>
+
+
+
+ <h6 id="pixel-manipulation"><span class="secno">4.8.11.1.11 </span><dfn>Pixel manipulation</dfn></h6>
+
+ <dl class="domintro"><dt><var title="">imagedata</var> = <var title="">context</var> . <code title="dom-context-2d-createImageData"><a href="#dom-context-2d-createimagedata">createImageData</a></code>(<var title="">sw</var>, <var title="">sh</var>)</dt>
+
+ <dd>
+
+ <p>Returns an <code><a href="#imagedata">ImageData</a></code> object with the given
+ dimensions in CSS pixels (which might map to a different number of
+ actual device pixels exposed by the object itself). All the pixels
+ in the returned object are transparent black.</p>
+
+ </dd>
+
+ <dt><var title="">imagedata</var> = <var title="">context</var> . <code title="dom-context-2d-createImageData"><a href="#dom-context-2d-createimagedata">createImageData</a></code>(<var title="">imagedata</var>)</dt>
+
+ <dd>
+
+ <p>Returns an <code><a href="#imagedata">ImageData</a></code> object with the same
+ dimensions as the argument. All the pixels in the returned object
+ are transparent black.</p>
+
+ </dd>
+
+ <dt><var title="">imagedata</var> = <var title="">context</var> . <code title="dom-context-2d-getImageData"><a href="#dom-context-2d-getimagedata">getImageData</a></code>(<var title="">sx</var>, <var title="">sy</var>, <var title="">sw</var>, <var title="">sh</var>)</dt>
+
+ <dd>
+
+ <p>Returns an <code><a href="#imagedata">ImageData</a></code> object containing the image
+ data for the given rectangle of the canvas.</p>
+
+ <p>Throws a <code><a href="#not_supported_err">NOT_SUPPORTED_ERR</a></code> exception if any of the
+ arguments are not finite. Throws an <code><a href="#index_size_err">INDEX_SIZE_ERR</a></code>
+ exception if the either of the width or height arguments are
+ zero.</p>
+
+ </dd>
+
+ <dt><var title="">imagedata</var> . <code title="dom-imagedata-width"><a href="#dom-imagedata-width">width</a></code></dt>
+ <dt><var title="">imagedata</var> . <code title="dom-imagedata-height"><a href="#dom-imagedata-height">height</a></code></dt>
+
+ <dd>
+
+ <p>Returns the actual dimensions of the data in the <code><a href="#imagedata">ImageData</a></code> object, in device pixels.</p>
+
+ </dd>
+
+ <dt><var title="">imagedata</var> . <code title="dom-imagedata-data"><a href="#dom-imagedata-data">data</a></code></dt>
+
+ <dd>
+
+ <p>Returns the one-dimensional array containing the data in RGBA order, as integers in the range 0 to 255.</p>
+
+ </dd>
+
+ <dt><var title="">context</var> . <code title="dom-context-2d-putImageData"><a href="#dom-context-2d-putimagedata">putImageData</a></code>(<var title="">imagedata</var>, <var title="">dx</var>, <var title="">dy</var> [, <var title="">dirtyX</var>, <var title="">dirtyY</var>, <var title="">dirtyWidth</var>, <var title="">dirtyHeight</var> ])</dt>
+
+ <dd>
+
+ <p>Paints the data from the given <code><a href="#imagedata">ImageData</a></code> object
+ onto the canvas. If a dirty rectangle is provided, only the pixels
+ from that rectangle are painted.</p>
+
+ <p>The <code title="dom-context-2d-globalAlpha"><a href="#dom-context-2d-globalalpha">globalAlpha</a></code>
+ and <code title="dom-context-2d-globalCompositeOperation"><a href="#dom-context-2d-globalcompositeoperation">globalCompositeOperation</a></code>
+ attributes, as well as the shadow attributes, are ignored for the
+ purposes of this method call; pixels in the canvas are replaced
+ wholesale, with no composition, alpha blending, no shadows,
+ etc.</p>
+
+ <p>If the first argument is null, throws a
+ <code><a href="#type_mismatch_err">TYPE_MISMATCH_ERR</a></code> exception. Throws a
+ <code><a href="#not_supported_err">NOT_SUPPORTED_ERR</a></code> exception if any of the other
+ arguments are not finite.</p>
+
+ </dd>
+
+ </dl><div class="impl">
+
+ <p>The <dfn id="dom-context-2d-createimagedata" title="dom-context-2d-createImageData"><code>createImageData()</code></dfn>
+ method is used to instantiate new blank <code><a href="#imagedata">ImageData</a></code>
+ objects. When the method is invoked with two arguments <var title="">sw</var> and <var title="">sh</var>, it must return an
+ <code><a href="#imagedata">ImageData</a></code> object representing a rectangle with a width
+ in CSS pixels equal to the absolute magnitude of <var title="">sw</var> and a height in CSS pixels equal to the absolute
+ magnitude of <var title="">sh</var>. When invoked with a single <var title="">imagedata</var> argument, it must return an
+ <code><a href="#imagedata">ImageData</a></code> object representing a rectangle with the same
+ dimensions as the <code><a href="#imagedata">ImageData</a></code> object passed as the
+ argument. The <code><a href="#imagedata">ImageData</a></code> object returned must be filled
+ with transparent black.</p>
+
+ <p>The <dfn id="dom-context-2d-getimagedata" title="dom-context-2d-getImageData"><code>getImageData(<var title="">sx</var>, <var title="">sy</var>, <var title="">sw</var>,
+ <var title="">sh</var>)</code></dfn> method must return an
+ <code><a href="#imagedata">ImageData</a></code> object representing the underlying pixel data
+ for the area of the canvas denoted by the rectangle whose corners are
+ the four points (<var title="">sx</var>, <var title="">sy</var>),
+ (<span title=""><var title="">sx</var>+<var title="">sw</var></span>, <var title="">sy</var>), (<span title=""><var title="">sx</var>+<var title="">sw</var></span>, <span title=""><var title="">sy</var>+<var title="">sh</var></span>), (<var title="">sx</var>, <span title=""><var title="">sy</var>+<var title="">sh</var></span>), in canvas
+ coordinate space units. Pixels outside the canvas must be returned
+ as transparent black. Pixels must be returned as non-premultiplied
+ alpha values.</p>
+
+ <p>If any of the arguments to <code title="dom-context-2d-createImageData"><a href="#dom-context-2d-createimagedata">createImageData()</a></code> or
+ <code title="dom-context-2d-getImageData"><a href="#dom-context-2d-getimagedata">getImageData()</a></code>
+ are infinite or NaN, the method must instead raise a
+ <code><a href="#not_supported_err">NOT_SUPPORTED_ERR</a></code> exception. If either the <var title="">sw</var> or <var title="">sh</var> arguments are zero,
+ the method must instead raise an <code><a href="#index_size_err">INDEX_SIZE_ERR</a></code>
+ exception.</p>
+
+ <p><code><a href="#imagedata">ImageData</a></code> objects must be initialized so that their
+ <dfn id="dom-imagedata-width" title="dom-imagedata-width"><code>width</code></dfn> attribute
+ is set to <var title="">w</var>, the number of physical device
+ pixels per row in the image data, their <dfn id="dom-imagedata-height" title="dom-imagedata-height"><code>height</code></dfn> attribute is
+ set to <var title="">h</var>, the number of rows in the image data,
+ and their <dfn id="dom-imagedata-data" title="dom-imagedata-data"><code>data</code></dfn>
+ attribute is initialized to a <code><a href="#canvaspixelarray">CanvasPixelArray</a></code> object
+ holding the image data. At least one pixel's worth of image data
+ must be returned.</p>
+
+ <p>The <code><a href="#canvaspixelarray">CanvasPixelArray</a></code> object provides ordered,
+ indexed access to the color components of each pixel of the image
+ data. The data must be represented in left-to-right order, row by
+ row top to bottom, starting with the top left, with each pixel's
+ red, green, blue, and alpha components being given in that order for
+ each pixel. Each component of each device pixel represented in this
+ array must be in the range 0..255, representing the 8 bit value for
+ that component. The components must be assigned consecutive indices
+ starting with 0 for the top left pixel's red component.</p>
+
+ <p>The <code><a href="#canvaspixelarray">CanvasPixelArray</a></code> object thus represents <var title="">h</var>×<var title="">w</var>×4 integers. The
+ <dfn id="dom-canvaspixelarray-length" title="dom-canvaspixelarray-length"><code>length</code></dfn>
+ attribute of a <code><a href="#canvaspixelarray">CanvasPixelArray</a></code> object must return this
+ number.</p>
+
+ <p>The object's <a href="#supported-property-indices">supported property indices</a> are the
+ numbers in the range 0 .. <span title=""><var title="">h</var>×<var title="">w</var>×4-1</span>.</p>
+
+ <p>To <dfn id="dom-canvaspixelarray-get" title="dom-CanvasPixelArray-get">determine the value of
+ an indexed property</dfn> <var title="">index</var>, the user agent
+ must return the value of the <var title="">index</var>th component
+ in the array.</p>
+
+ <p>To <dfn id="dom-canvaspixelarray-set" title="dom-CanvasPixelArray-set">set the value of an
+ existing indexed property</dfn> <var title="">index</var> to value
+ <var title="">value</var>, the value of the <var title="">index</var>th component in the array must be set to <var title="">value</var>.</p>
+
+ <p class="note">The width and height (<var title="">w</var> and <var title="">h</var>) might be different from the <var title="">sw</var>
+ and <var title="">sh</var> arguments to the above methods, e.g. if
+ the canvas is backed by a high-resolution bitmap, or if the <var title="">sw</var> and <var title="">sh</var> arguments are
+ negative.</p>
+
+ <p>The <dfn id="dom-context-2d-putimagedata" title="dom-context-2d-putImageData"><code>putImageData(<var title="">imagedata</var>, <var title="">dx</var>, <var title="">dy</var>, <var title="">dirtyX</var>, <var title="">dirtyY</var>, <var title="">dirtyWidth</var>, <var title="">dirtyHeight</var>)</code></dfn> method writes data from
+ <code><a href="#imagedata">ImageData</a></code> structures back to the canvas.</p>
+
+ <p>If any of the arguments to the method are infinite or NaN, the
+ method must raise a <code><a href="#not_supported_err">NOT_SUPPORTED_ERR</a></code> exception.</p>
+
+ <p>When the last four arguments are omitted, they must be assumed to
+ have the values 0, 0, the <code title="dom-imagedata-width"><a href="#dom-imagedata-width">width</a></code> member of the <var title="">imagedata</var> structure, and the <code title="dom-imagedata-height"><a href="#dom-imagedata-height">height</a></code> member of the <var title="">imagedata</var> structure, respectively.</p>
+
+ <p>When invoked with arguments that do not, per the last few
+ paragraphs, cause an exception to be raised, the <code title="dom-context-2d-putImageData"><a href="#dom-context-2d-putimagedata">putImageData()</a></code> method
+ must act as follows:</p>
+
+ <ol><li>
+
+ <p>Let <var title="">dx<sub>device</sub></var> be the x-coordinate
+ of the device pixel in the underlying pixel data of the canvas
+ corresponding to the <var title="">dx</var> coordinate in the
+ canvas coordinate space.</p>
+
+ <p>Let <var title="">dy<sub>device</sub></var> be the y-coordinate
+ of the device pixel in the underlying pixel data of the canvas
+ corresponding to the <var title="">dy</var> coordinate in the
+ canvas coordinate space.</p>
+
+ </li>
+
+ <li>
+
+ <p>If <var title="">dirtyWidth</var> is negative, let <var title="">dirtyX</var> be <span title=""><var title="">dirtyX</var>+<var title="">dirtyWidth</var></span>, and let <var title="">dirtyWidth</var> be equal to the absolute magnitude of
+ <var title="">dirtyWidth</var>.</p>
+
+ <p>If <var title="">dirtyHeight</var> is negative, let <var title="">dirtyY</var> be <span title=""><var title="">dirtyY</var>+<var title="">dirtyHeight</var></span>, and let <var title="">dirtyHeight</var> be equal to the absolute magnitude of
+ <var title="">dirtyHeight</var>.</p>
+
+ </li>
+
+ <li>
+
+ <p>If <var title="">dirtyX</var> is negative, let <var title="">dirtyWidth</var> be <span title=""><var title="">dirtyWidth</var>+<var title="">dirtyX</var></span>, and
+ let <var title="">dirtyX</var> be zero.</p>
+
+ <p>If <var title="">dirtyY</var> is negative, let <var title="">dirtyHeight</var> be <span title=""><var title="">dirtyHeight</var>+<var title="">dirtyY</var></span>, and
+ let <var title="">dirtyY</var> be zero.</p>
+
+ </li>
+
+ <li>
+
+ <p>If <span title=""><var title="">dirtyX</var>+<var title="">dirtyWidth</var></span> is greater than the <code title="dom-imagedata-width"><a href="#dom-imagedata-width">width</a></code> attribute of the <var title="">imagedata</var> argument, let <var title="">dirtyWidth</var> be the value of that <code title="dom-imagedata-width"><a href="#dom-imagedata-width">width</a></code> attribute, minus the
+ value of <var title="">dirtyX</var>.</p>
+
+ <p>If <span title=""><var title="">dirtyY</var>+<var title="">dirtyHeight</var></span> is greater than the <code title="dom-imagedata-height"><a href="#dom-imagedata-height">height</a></code> attribute of the <var title="">imagedata</var> argument, let <var title="">dirtyHeight</var> be the value of that <code title="dom-imagedata-height"><a href="#dom-imagedata-height">height</a></code> attribute, minus the
+ value of <var title="">dirtyY</var>.</p>
+
+ </li>
+
+ <li>
+
+ <p>If, after those changes, either <var title="">dirtyWidth</var>
+ or <var title="">dirtyHeight</var> is negative or zero, stop these
+ steps without affecting the canvas.</p>
+
+ </li>
+
+ <li><p>Otherwise, for all integer values of <var title="">x</var>
+ and <var title="">y</var> where <span title=""><var title="">dirtyX</var> ≤ <var title="">x</var> &lt; <span title=""><var title="">dirtyX</var>+<var title="">dirtyWidth</var></span></span>
+ and <span title=""><var title="">dirtyY</var> ≤ <var title="">y</var> &lt; <span title=""><var title="">dirtyY</var>+<var title="">dirtyHeight</var></span></span>, copy the four channels of
+ the pixel with coordinate (<var title="">x</var>, <var title="">y</var>) in the <var title="">imagedata</var> data
+ structure to the pixel with coordinate (<span title=""><var title="">dx<sub>device</sub></var>+<var title="">x</var></span>,
+ <span title=""><var title="">dy<sub>device</sub></var>+<var title="">y</var></span>) in the underlying pixel data of the
+ canvas.</p></li>
+
+ </ol><p>The handling of pixel rounding when the specified coordinates do
+ not exactly map to the device coordinate space is not defined by
+ this specification, except that the following must result in no
+ visible changes to the rendering:</p>
+
+ <pre>context.putImageData(context.getImageData(x, y, w, h), p, q);</pre>
+
+ <p>...for any value of <var title="">x</var>, <var title="">y</var>,
+ <var title="">w</var>, and <var title="">h</var> and where <var title="">p</var> is the smaller of <var title="">x</var> and the sum
+ of <var title="">x</var> and <var title="">w</var>, and <var title="">q</var> is the smaller of <var title="">y</var> and the sum
+ of <var title="">y</var> and <var title="">h</var>; and except that
+ the following two calls:</p>
+
+ <pre>context.createImageData(w, h);
+context.getImageData(0, 0, w, h);</pre>
+
+ <p>...must return <code><a href="#imagedata">ImageData</a></code> objects with the same
+ dimensions, for any value of <var title="">w</var> and <var title="">h</var>. In other words, while user agents may round the
+ arguments of these methods so that they map to device pixel
+ boundaries, any rounding performed must be performed consistently
+ for all of the <code title="dom-context-2d-getImageData"><a href="#dom-context-2d-getimagedata">createImageData()</a></code>, <code title="dom-context-2d-getImageData"><a href="#dom-context-2d-getimagedata">getImageData()</a></code> and <code title="dom-context-2d-putImageData"><a href="#dom-context-2d-putimagedata">putImageData()</a></code>
+ operations.</p>
+
+ <p class="note">Due to the lossy nature of converting to and from
+ premultiplied alpha color values, pixels that have just been set
+ using <code title="dom-context-2d-putImageData"><a href="#dom-context-2d-putimagedata">putImageData()</a></code> might be
+ returned to an equivalent <code title="dom-context-2d-getImageData"><a href="#dom-context-2d-getimagedata">getImageData()</a></code> as
+ different values.</p>
+
+ <p>The current path, <a href="#transformations" title="dom-context-2d-transformation">transformation matrix</a>,
+ <a href="#shadows" title="shadows">shadow attributes</a>, <a href="#dom-context-2d-globalalpha" title="dom-context-2d-globalAlpha">global alpha</a>, the <a href="#clipping-region" title="clipping region">clipping region</a>, and <a href="#dom-context-2d-globalcompositeoperation" title="dom-context-2d-globalCompositeOperation">global composition
+ operator</a> must not affect the <code title="dom-context-2d-getImageData"><a href="#dom-context-2d-getimagedata">getImageData()</a></code> and <code title="dom-context-2d-putImageData"><a href="#dom-context-2d-putimagedata">putImageData()</a></code>
+ methods.</p>
+
+ </div>
+
+ <div class="example">
+
+ <p>The data returned by <code title="dom-context-2d-getImageData"><a href="#dom-context-2d-getimagedata">getImageData()</a></code> is at the
+ resolution of the canvas backing store, which is likely to not be
+ one device pixel to each CSS pixel if the display used is a high
+ resolution display.</p>
+
+ <p>In the following example, the script generates an
+ <code><a href="#imagedata">ImageData</a></code> object so that it can draw onto it.</p>
+
+ <pre>// canvas is a reference to a &lt;canvas&gt; element
+var context = canvas.getContext('2d');
+
+// create a blank slate
+var data = context.createImageData(canvas.width, canvas.height);
+
+// create some plasma
+FillPlasma(data, 'green'); // green plasma
+
+// add a cloud to the plasma
+AddCloud(data, data.width/2, data.height/2); // put a cloud in the middle
+
+// paint the plasma+cloud on the canvas
+context.putImageData(data, 0, 0);
+
+// support methods
+function FillPlasma(data, color) { ... }
+function AddCloud(data, x, y) { ... }</pre>
+
+ </div>
+
+ <div class="example">
+
+ <p>Here is an example of using <code title="dom-context-2d-getImageData"><a href="#dom-context-2d-getimagedata">getImageData()</a></code> and <code title="dom-context-2d-putImageData"><a href="#dom-context-2d-putimagedata">putImageData()</a></code> to
+ implement an edge detection filter.</p>
+
+ <pre>&lt;!DOCTYPE HTML&gt;
+&lt;html&gt;
+ &lt;head&gt;
+ &lt;title&gt;Edge detection demo&lt;/title&gt;
+ &lt;script&gt;
+ var image = new Image();
+ function init() {
+ image.onload = demo;
+ image.src = &quot;image.jpeg&quot;;
+ }
+ function demo() {
+ var canvas = document.getElementsByTagName('canvas')[0];
+ var context = canvas.getContext('2d');
+
+ // draw the image onto the canvas
+ context.drawImage(image, 0, 0);
+
+ // get the image data to manipulate
+ var input = context.getImageData(0, 0, canvas.width, canvas.height);
+
+ // get an empty slate to put the data into
+ var output = context.createImageData(canvas.width, canvas.height);
+
+ // alias some variables for convenience
+ // notice that we are using input.width and input.height here
+ // as they might not be the same as canvas.width and canvas.height
+ // (in particular, they might be different on high-res displays)
+ var w = input.width, h = input.height;
+ var inputData = input.data;
+ var outputData = output.data;
+
+ // edge detection
+ for (var y = 1; y &lt; h-1; y += 1) {
+ for (var x = 1; x &lt; w-1; x += 1) {
+ for (var c = 0; c &lt; 3; c += 1) {
+ var i = (y*w + x)*4 + c;
+ outputData[i] = 127 + -inputData[i - w*4 - 4] - inputData[i - w*4] - inputData[i - w*4 + 4] +
+ -inputData[i - 4] + 8*inputData[i] - inputData[i + 4] +
+ -inputData[i + w*4 - 4] - inputData[i + w*4] - inputData[i + w*4 + 4];
+ }
+ outputData[(y*w + x)*4 + 3] = 255; // alpha
+ }
+ }
+
+ // put the image data back after manipulation
+ context.putImageData(output, 0, 0);
+ }
+ &lt;/script&gt;
+ &lt;/head&gt;
+ &lt;body onload=&quot;init()&quot;&gt;
+ &lt;canvas&gt;&lt;/canvas&gt;
+ &lt;/body&gt;
+&lt;/html&gt;</pre>
+
+ </div>
+
+
+ <div class="impl">
+
+ <h6 id="drawing-model"><span class="secno">4.8.11.1.12 </span><dfn>Drawing model</dfn></h6>
+
+ <p>When a shape or image is painted, user agents must follow these
+ steps, in the order given (or act as if they do):</p>
+
+ <ol><li><p>Render the shape or image onto an infinite transparent black
+ bitmap, creating image <var title="">A</var>, as described in the
+ previous sections. For shapes, the current fill, stroke, and line
+ styles must be honored, and the stroke must itself also be
+ subjected to the current transformation matrix.</p></li>
+
+ <li><p><a href="#when-shadows-are-drawn">When shadows are drawn</a>, render the shadow from
+ image <var title="">A</var>, using the current shadow styles,
+ creating image <var title="">B</var>.</p></li>
+
+ <li><p><a href="#when-shadows-are-drawn">When shadows are drawn</a>, multiply the alpha
+ component of every pixel in <var title="">B</var> by <code title="dom-context-2d-globalAlpha"><a href="#dom-context-2d-globalalpha">globalAlpha</a></code>.</p></li>
+
+ <li><p><a href="#when-shadows-are-drawn">When shadows are drawn</a>, composite <var title="">B</var> within the <a href="#clipping-region">clipping region</a> over the
+ current canvas bitmap using the current composition
+ operator.</p></li>
+
+ <li><p>Multiply the alpha component of every pixel in <var title="">A</var> by <code title="dom-context-2d-globalAlpha"><a href="#dom-context-2d-globalalpha">globalAlpha</a></code>.</p></li>
+
+ <li><p>Composite <var title="">A</var> within the <a href="#clipping-region">clipping
+ region</a> over the current canvas bitmap using the current
+ composition operator.</p></li>
+
+ </ol></div>
+
+
+ <h6 id="best-practices"><span class="secno">4.8.11.1.13 </span>Best practices</h6>
+
+ <p><i>This section is non-normative.</i></p>
+
+ <p>When a canvas is interactive, authors should include focusable
+ elements in the element's fallback content corresponding to each
+ focusable part of the canvas, as in the <a href="#drawCustomFocusRingExample">example above</a>.</p>
+
+ <p>To indicate which focusable part of the canvas is currently
+ focused, authors should use the <code title="dom-context-2d-drawSystemFocusRing"><a href="#dom-context-2d-drawsystemfocusring">drawSystemFocusRing()</a></code>
+ method, passing it the element for which a ring is being drawn. This
+ method only draws the focus ring if the element is focused, so that
+ it can simply be called whenever drawing the element, without
+ checking whether the element is focused or not first.</p>
+
+ <p>Authors should avoid implementing text editing controls using the
+ <code><a href="#the-canvas-element">canvas</a></code> element. Doing so has a large number of
+ disadvantages:</p>
+
+ <ul><li>Mouse placement of the caret has to be reimplemented.</li>
+
+ <li>Keyboard movement of the caret has to be reimplemented (possibly across lines, for multiline text input).</li>
+
+ <li>Scrolling of the text field has to be implemented (horizontally for long lines, vertically for multiline input).</li>
+
+ <li>Native features such as copy-and-paste have to be reimplemented.</li>
+
+ <li>Native features such as spell-checking have to be reimplemented.</li>
+
+ <li>Native features such as drag-and-drop have to be reimplemented.</li>
+
+ <li>Native features such as page-wide text search have to be reimplemented.</li>
+
+ <li>Native features specific to the user, for example custom text
+ services, have to be reimplemented. This is close to impossible
+ since each user might have different services installed, and there
+ is an unbounded set of possible such services.</li>
+
+ <li>Bidirectional text editing has to be reimplemented.</li>
+
+ <li>For multiline text editing, line wrapping has to be implemented for all relevant languages.</li>
+
+ <li>Text selection has to be reimplemented.</li>
+
+ <li>Dragging of bidirectional text selections has to be reimplemented.</li>
+
+ <li>Platform-native keyboard shortcuts have to be reimplemented.</li>
+
+ <li>Platform-native input method editors (IMEs) have to be reimplemented.</li>
+
+ <li>Undo and redo functionality has to be reimplemented.</li>
+
+ <li>Accessibility features such as magnification following the
+ caret or selection have to be reimplemented.</li>
+
+ </ul><p>This is a huge amount of work, and authors are most strongly
+ encouraged to avoid doing any of it by instead using the
+ <code><a href="#the-input-element">input</a></code> element, the <code><a href="#the-textarea-element">textarea</a></code> element, or
+ the <code title="attr-contenteditable"><a href="#attr-contenteditable">contenteditable</a></code>
+ attribute.</p>
+
+
+ <h6 id="examples"><span class="secno">4.8.11.1.14 </span>Examples</h6>
+
+ <p><i>This section is non-normative.</i></p>
+
+ <div class="example">
+
+ <p>Here is an example of a script that uses canvas to draw <a href="data:text/html;charset=utf-8;base64,PCFET0NUWVBFIEhUTUw%2BDQo8aHRtbCBsYW5nPSJlbiI%2BDQogPGhlYWQ%2BDQogIDx0aXRsZT5QcmV0dHkgR2xvd2luZyBMaW5lczwvdGl0bGU%2BDQogPC9oZWFkPg0KIDxib2R5Pg0KPGNhbnZhcyB3aWR0aD0iODAwIiBoZWlnaHQ9IjQ1MCI%2BPC9jYW52YXM%2BDQo8c2NyaXB0Pg0KDQogdmFyIGNvbnRleHQgPSBkb2N1bWVudC5nZXRFbGVtZW50c0J5VGFnTmFtZSgnY2FudmFzJylbMF0uZ2V0Q29udGV4dCgnMmQnKTsNCg0KIHZhciBsYXN0WCA9IGNvbnRleHQuY2FudmFzLndpZHRoICogTWF0aC5yYW5kb20oKTsNCiB2YXIgbGFzdFkgPSBjb250ZXh0LmNhbnZhcy5oZWlnaHQgKiBNYXRoLnJhbmRvbSgpOw0KIHZhciBodWUgPSAwOw0KIGZ1bmN0aW9uIGxpbmUoKSB7DQogICBjb250ZXh0LnNhdmUoKTsNCiAgIGNvbnRleHQudHJhbnNsYXRlKGNvbnRleHQuY2FudmFzLndpZHRoLzIsIGNvbnRleHQuY2FudmFzLmhlaWdodC8yKTsNCiAgIGNvbnRleHQuc2NhbGUoMC45LCAwLjkpOw0KICAgY29udGV4dC50cmFuc2xhdGUoLWNvbnRleHQuY2FudmFzLndpZHRoLzIsIC1jb250ZXh0LmNhbnZhcy5oZWlnaHQvMik7DQogICBjb250ZXh0LmJlZ2luUGF0aCgpOw0KICAgY29udGV4dC5saW5lV2lkdGggPSA1ICsgTWF0aC5yYW5kb20oKSAqIDEwOw0KICAgY29udGV4dC5tb3ZlVG8obGFzdFgsIGxhc3RZKTsNCiAgIGxhc3RYID0gY29udGV4dC5jYW52YXMud2lkdGggKiBNYXRoLnJhbmRvbSgpOw0KICAgbGFzdFkgPSBjb250ZXh0LmNhbnZhcy5oZWlnaHQgKiBNYXRoLnJhbmRvbSgpOw0KICAgY29udGV4dC5iZXppZXJDdXJ2ZVRvKGNvbnRleHQuY2FudmFzLndpZHRoICogTWF0aC5yYW5kb20oKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICBjb250ZXh0LmNhbnZhcy5oZWlnaHQgKiBNYXRoLnJhbmRvbSgpLA0KICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRleHQuY2FudmFzLndpZHRoICogTWF0aC5yYW5kb20oKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICBjb250ZXh0LmNhbnZhcy5oZWlnaHQgKiBNYXRoLnJhbmRvbSgpLA0KICAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RYLCBsYXN0WSk7DQoNCiAgIGh1ZSA9IGh1ZSArIDEwICogTWF0aC5yYW5kb20oKTsNCiAgIGNvbnRleHQuc3Ryb2tlU3R5bGUgPSAnaHNsKCcgKyBodWUgKyAnLCA1MCUsIDUwJSknOw0KICAgY29udGV4dC5zaGFkb3dDb2xvciA9ICd3aGl0ZSc7DQogICBjb250ZXh0LnNoYWRvd0JsdXIgPSAxMDsNCiAgIGNvbnRleHQuc3Ryb2tlKCk7DQogICBjb250ZXh0LnJlc3RvcmUoKTsNCiB9DQogc2V0SW50ZXJ2YWwobGluZSwgNTApOw0KDQogZnVuY3Rpb24gYmxhbmsoKSB7DQogICBjb250ZXh0LmZpbGxTdHlsZSA9ICdyZ2JhKDAsMCwwLDAuMSknOw0KICAgY29udGV4dC5maWxsUmVjdCgwLCAwLCBjb250ZXh0LmNhbnZhcy53aWR0aCwgY29udGV4dC5jYW52YXMuaGVpZ2h0KTsNCiB9DQogc2V0SW50ZXJ2YWwoYmxhbmssIDQwKTsNCg0KPC9zY3JpcHQ%2BDQogPC9ib2R5Pg0KPC9odG1sPg0K">pretty glowing lines</a>.</p>
+
+ <pre>&lt;canvas width=&quot;800&quot; height=&quot;450&quot;&gt;&lt;/canvas&gt;
+&lt;script&gt;
+
+ var context = document.getElementsByTagName('canvas')[0].getContext('2d');
+
+ var lastX = context.canvas.width * Math.random();
+ var lastY = context.canvas.height * Math.random();
+ var hue = 0;
+ function line() {
+ context.save();
+ context.translate(context.canvas.width/2, context.canvas.height/2);
+ context.scale(0.9, 0.9);
+ context.translate(-context.canvas.width/2, -context.canvas.height/2);
+ context.beginPath();
+ context.lineWidth = 5 + Math.random() * 10;
+ context.moveTo(lastX, lastY);
+ lastX = context.canvas.width * Math.random();
+ lastY = context.canvas.height * Math.random();
+ context.bezierCurveTo(context.canvas.width * Math.random(),
+ context.canvas.height * Math.random(),
+ context.canvas.width * Math.random(),
+ context.canvas.height * Math.random(),
+ lastX, lastY);
+
+ hue = hue + 10 * Math.random();
+ context.strokeStyle = 'hsl(' + hue + ', 50%, 50%)';
+ context.shadowColor = 'white';
+ context.shadowBlur = 10;
+ context.stroke();
+ context.restore();
+ }
+ setInterval(line, 50);
+
+ function blank() {
+ context.fillStyle = 'rgba(0,0,0,0.1)';
+ context.fillRect(0, 0, context.canvas.width, context.canvas.height);
+ }
+ setInterval(blank, 40);
+
+&lt;/script&gt;</pre>
+
+ </div>
+
+
+
+ </div><!--data-component-->
+
+ <!--2DCONTEXT-->
+
+ <div class="impl">
+
+ <h5 id="color-spaces-and-color-correction"><span class="secno">4.8.11.2 </span>Color spaces and color correction</h5>
+
+ <p>The <code><a href="#the-canvas-element">canvas</a></code> APIs must perform color correction at
+ only two points: when rendering images with their own gamma
+ correction and color space information onto the canvas, to convert
+ the image to the color space used by the canvas (e.g. using the 2D
+ Context's <code title="dom-context-2d-drawImage"><a href="#dom-context-2d-drawimage">drawImage()</a></code>
+ method with an <code><a href="#htmlimageelement">HTMLImageElement</a></code> object), and when
+ rendering the actual canvas bitmap to the output device.</p>
+
+ <p class="note">Thus, in the 2D context, colors used to draw shapes
+ onto the canvas will exactly match colors obtained through the <code title="dom-context-2d-getImageData"><a href="#dom-context-2d-getimagedata">getImageData()</a></code>
+ method.</p>
+
+ <p>The <code title="dom-canvas-toDataURL"><a href="#dom-canvas-todataurl">toDataURL()</a></code> method
+ must not include color space information in the resource
+ returned. Where the output format allows it, the color of pixels in
+ resources created by <code title="dom-canvas-toDataURL"><a href="#dom-canvas-todataurl">toDataURL()</a></code> must match those
+ returned by the <code title="dom-context-2d-getImageData"><a href="#dom-context-2d-getimagedata">getImageData()</a></code>
+ method.</p>
+
+ <p>In user agents that support CSS, the color space used by a
+ <code><a href="#the-canvas-element">canvas</a></code> element must match the color space used for
+ processing any colors for that element in CSS.</p>
+
+ <p>The gamma correction and color space information of images must
+ be handled in such a way that an image rendered directly using an
+ <code><a href="#the-img-element">img</a></code> element would use the same colors as one painted on
+ a <code><a href="#the-canvas-element">canvas</a></code> element that is then itself
+ rendered. Furthermore, the rendering of images that have no color
+ correction information (such as those returned by the <code title="dom-canvas-toDataURL"><a href="#dom-canvas-todataurl">toDataURL()</a></code> method) must be
+ rendered with no color correction.</p>
+
+ <p class="note">Thus, in the 2D context, calling the <code title="dom-context-2d-drawImage"><a href="#dom-context-2d-drawimage">drawImage()</a></code> method to render
+ the output of the <code title="dom-canvas-toDataURL"><a href="#dom-canvas-todataurl">toDataURL()</a></code> method to the
+ canvas, given the appropriate dimensions, has no visible effect.</p>
+
+ </div>
+
+
+ <div class="impl">
+
+ <h5 id="security-with-canvas-elements"><span class="secno">4.8.11.3 </span>Security with <code><a href="#the-canvas-element">canvas</a></code> elements</h5>
+
+ <p><strong>Information leakage</strong> can occur if scripts from
+ one <a href="#origin">origin</a> can access information (e.g. read pixels)
+ from images from another origin (one that isn't the <a href="#same-origin" title="same origin">same</a>).</p>
+
+ <p>To mitigate this, <code><a href="#the-canvas-element">canvas</a></code> elements are defined to
+ have a flag indicating whether they are <i>origin-clean</i>. All
+ <code><a href="#the-canvas-element">canvas</a></code> elements must start with their
+ <i>origin-clean</i> set to true. The flag must be set to false if
+ any of the following actions occur:</p>
+
+ <ul><li><p>The element's 2D context's <code title="dom-context-2d-drawImage"><a href="#dom-context-2d-drawimage">drawImage()</a></code> method is
+ called with an <code><a href="#htmlimageelement">HTMLImageElement</a></code> or an
+ <code><a href="#htmlvideoelement">HTMLVideoElement</a></code> whose <a href="#origin">origin</a> is not the
+ <a href="#same-origin" title="same origin">same</a> as that of the
+ <code><a href="#document">Document</a></code> object that owns the <code><a href="#the-canvas-element">canvas</a></code>
+ element.</p></li>
+
+ <li><p>The element's 2D context's <code title="dom-context-2d-drawImage"><a href="#dom-context-2d-drawimage">drawImage()</a></code> method is
+ called with an <code><a href="#htmlcanvaselement">HTMLCanvasElement</a></code> whose
+ <i>origin-clean</i> flag is false.</p></li>
+
+ <li><p>The element's 2D context's <code title="dom-context-2d-fillStyle"><a href="#dom-context-2d-fillstyle">fillStyle</a></code> attribute is set
+ to a <code><a href="#canvaspattern">CanvasPattern</a></code> object that was created from an
+ <code><a href="#htmlimageelement">HTMLImageElement</a></code> or an <code><a href="#htmlvideoelement">HTMLVideoElement</a></code>
+ whose <a href="#origin">origin</a> was not the <a href="#same-origin" title="same
+ origin">same</a> as that of the <code><a href="#document">Document</a></code> object
+ that owns the <code><a href="#the-canvas-element">canvas</a></code> element when the pattern was
+ created.</p></li>
+
+ <li><p>The element's 2D context's <code title="dom-context-2d-fillStyle"><a href="#dom-context-2d-fillstyle">fillStyle</a></code> attribute is set
+ to a <code><a href="#canvaspattern">CanvasPattern</a></code> object that was created from an
+ <code><a href="#htmlcanvaselement">HTMLCanvasElement</a></code> whose <i>origin-clean</i> flag was
+ false when the pattern was created.</p></li>
+
+ <li><p>The element's 2D context's <code title="dom-context-2d-strokeStyle"><a href="#dom-context-2d-strokestyle">strokeStyle</a></code> attribute is
+ set to a <code><a href="#canvaspattern">CanvasPattern</a></code> object that was created from an
+ <code><a href="#htmlimageelement">HTMLImageElement</a></code> or an <code><a href="#htmlvideoelement">HTMLVideoElement</a></code>
+ whose <a href="#origin">origin</a> was not the <a href="#same-origin" title="same
+ origin">same</a> as that of the <code><a href="#document">Document</a></code> object
+ that owns the <code><a href="#the-canvas-element">canvas</a></code> element when the pattern was
+ created.</p></li>
+
+ <li><p>The element's 2D context's <code title="dom-context-2d-strokeStyle"><a href="#dom-context-2d-strokestyle">strokeStyle</a></code> attribute is
+ set to a <code><a href="#canvaspattern">CanvasPattern</a></code> object that was created from an
+ <code><a href="#htmlcanvaselement">HTMLCanvasElement</a></code> whose <i>origin-clean</i> flag was
+ false when the pattern was created.</p></li>
+
+ <li><p>The element's 2D context's <code title="dom-context-2d-fillText"><a href="#dom-context-2d-filltext">fillText()</a></code> or <code title="dom-context-2d-fillText"><a href="#dom-context-2d-filltext">strokeText()</a></code> methods are
+ invoked and consider using a font that has an <a href="#origin">origin</a>
+ that is not the <a href="#same-origin" title="same origin">same</a> as that of
+ the <code><a href="#document">Document</a></code> object that owns the <code><a href="#the-canvas-element">canvas</a></code>
+ element. (The font doesn't even have to be used; all that matters
+ is whether the font was considered for any of the glyphs
+ drawn.)</p></li> <!-- because fonts could consider sensitive
+ material, I guess; and because that sensitivity could extend to
+ whether or not a particular glyph is in the font in the first
+ place. -->
+
+ </ul><p>Whenever the <code title="dom-canvas-toDataURL"><a href="#dom-canvas-todataurl">toDataURL()</a></code> method of a
+ <code><a href="#the-canvas-element">canvas</a></code> element whose <i>origin-clean</i> flag is set to
+ false is called, the method must raise a <code><a href="#security_err">SECURITY_ERR</a></code>
+ exception.</p>
+
+ <p>Whenever the <code title="dom-context-2d-getImageData"><a href="#dom-context-2d-getimagedata">getImageData()</a></code> method of
+ the 2D context of a <code><a href="#the-canvas-element">canvas</a></code> element whose
+ <i>origin-clean</i> flag is set to false is called with otherwise
+ correct arguments, the method must raise a <code><a href="#security_err">SECURITY_ERR</a></code>
+ exception.</p>
+
+ <p>Whenever the <code title="dom-context-2d-measureText"><a href="#dom-context-2d-measuretext">measureText()</a></code> method of
+ the 2D context of a <code><a href="#the-canvas-element">canvas</a></code> element ends up using a font
+ that has an <a href="#origin">origin</a> that is not the <a href="#same-origin" title="same
+ origin">same</a> as that of the <code><a href="#document">Document</a></code> object that
+ owns the <code><a href="#the-canvas-element">canvas</a></code> element, the method must raise a
+ <code><a href="#security_err">SECURITY_ERR</a></code> exception.</p>
+
+ <p class="note">Even resetting the canvas state by changing its
+ <code title="attr-canvas-width"><a href="#attr-canvas-width">width</a></code> or <code title="attr-canvas-height"><a href="#attr-canvas-height">height</a></code> attributes doesn't reset
+ the <i>origin-clean</i> flag.</p>
+
+ </div>
+
+
+
+ </body></html>
diff --git a/tests/wpt/web-platform-tests/2dcontext/tools/gentest.py b/tests/wpt/web-platform-tests/2dcontext/tools/gentest.py
new file mode 100644
index 00000000000..500cb4d8bce
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/tools/gentest.py
@@ -0,0 +1,783 @@
+# Copyright (c) 2010 Philip Taylor
+# Released under the BSD license and W3C Test Suite License: see LICENSE.txt
+
+# Current code status:
+#
+# This was originally written for use at
+# http://philip.html5.org/tests/canvas/suite/tests/
+#
+# It has been adapted for use with the Web Platform Test Suite suite at
+# https://github.com/w3c/web-platform-tests/
+#
+# The W3C version excludes a number of features (multiple versions of each test
+# case of varying verbosity, Mozilla mochitests, semi-automated test harness)
+# to focus on simply providing reviewable test cases. It also expects a different
+# directory structure.
+# This code attempts to support both versions, but the non-W3C version hasn't
+# been tested recently and is probably broken.
+
+# To update or add test cases:
+#
+# * Modify the tests*.yaml files.
+# 'name' is an arbitrary hierarchical name to help categorise tests.
+# 'desc' is a rough description of what behaviour the test aims to test.
+# 'testing' is a list of references to spec.yaml, to show which spec sentences
+# this test case is primarily testing.
+# 'code' is JavaScript code to execute, with some special commands starting with '@'
+# 'expected' is what the final canvas output should be: a string 'green' or 'clear'
+# (100x50 images in both cases), or a string 'size 100 50' (or any other size)
+# followed by Python code using Pycairo to generate the image.
+#
+# * Run "python gentest.py".
+# This requires a few Python modules which might not be ubiquitous.
+# It has only been tested on Linux.
+# It will usually emit some warnings, which ideally should be fixed but can
+# generally be safely ignored.
+#
+# * Test the tests, add new ones to Git, remove deleted ones from Git, etc.
+
+import re
+import codecs
+import time
+import os
+import shutil
+import sys
+import xml.dom.minidom
+from xml.dom.minidom import Node
+
+import cairo
+
+try:
+ import syck as yaml # compatible and lots faster
+except ImportError:
+ import yaml
+
+# Default mode is for the W3C test suite; the --standalone option
+# generates various extra files that aren't needed there
+W3CMODE = True
+if '--standalone' in sys.argv:
+ W3CMODE = False
+
+TESTOUTPUTDIR = '../../2dcontext'
+IMAGEOUTPUTDIR = '../../2dcontext'
+MISCOUTPUTDIR = './output'
+SPECOUTPUTDIR = '../../annotated-spec'
+
+SPECOUTPUTPATH = '../annotated-spec' # relative to TESTOUTPUTDIR
+
+def simpleEscapeJS(str):
+ return str.replace('\\', '\\\\').replace('"', '\\"')
+
+def escapeJS(str):
+ str = simpleEscapeJS(str)
+ str = re.sub(r'\[(\w+)\]', r'[\\""+(\1)+"\\"]', str) # kind of an ugly hack, for nicer failure-message output
+ return str
+
+def escapeHTML(str):
+ return str.replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;').replace('"', '&quot;')
+
+def expand_nonfinite(method, argstr, tail):
+ """
+ >>> print expand_nonfinite('f', '<0 a>, <0 b>', ';')
+ f(a, 0);
+ f(0, b);
+ f(a, b);
+ >>> print expand_nonfinite('f', '<0 a>, <0 b c>, <0 d>', ';')
+ f(a, 0, 0);
+ f(0, b, 0);
+ f(0, c, 0);
+ f(0, 0, d);
+ f(a, b, 0);
+ f(a, b, d);
+ f(a, 0, d);
+ f(0, b, d);
+ """
+ # argstr is "<valid-1 invalid1-1 invalid2-1 ...>, ..." (where usually
+ # 'invalid' is Infinity/-Infinity/NaN)
+ args = []
+ for arg in argstr.split(', '):
+ a = re.match('<(.*)>', arg).group(1)
+ args.append(a.split(' '))
+ calls = []
+ # Start with the valid argument list
+ call = [ args[j][0] for j in range(len(args)) ]
+ # For each argument alone, try setting it to all its invalid values:
+ for i in range(len(args)):
+ for a in args[i][1:]:
+ c2 = call[:]
+ c2[i] = a
+ calls.append(c2)
+ # For all combinations of >= 2 arguments, try setting them to their
+ # first invalid values. (Don't do all invalid values, because the
+ # number of combinations explodes.)
+ def f(c, start, depth):
+ for i in range(start, len(args)):
+ if len(args[i]) > 1:
+ a = args[i][1]
+ c2 = c[:]
+ c2[i] = a
+ if depth > 0: calls.append(c2)
+ f(c2, i+1, depth+1)
+ f(call, 0, 0)
+
+ return '\n'.join('%s(%s)%s' % (method, ', '.join(c), tail) for c in calls)
+
+# Run with --test argument to run unit tests
+if len(sys.argv) > 1 and sys.argv[1] == '--test':
+ import doctest
+ doctest.testmod()
+ sys.exit()
+
+templates = yaml.load(open('templates.yaml').read())
+name_mapping = yaml.load(open('name2dir.yaml').read())
+
+spec_assertions = []
+for s in yaml.load(open('spec.yaml').read())['assertions']:
+ if 'meta' in s:
+ eval(compile(s['meta'], '<meta spec assertion>', 'exec'), {}, {'assertions':spec_assertions})
+ else:
+ spec_assertions.append(s)
+
+tests = []
+for t in sum([ yaml.load(open(f).read()) for f in ['tests.yaml', 'tests2d.yaml', 'tests2dtext.yaml']], []):
+ if 'DISABLED' in t:
+ continue
+ if 'meta' in t:
+ eval(compile(t['meta'], '<meta test>', 'exec'), {}, {'tests':tests})
+ else:
+ tests.append(t)
+
+category_names = []
+category_contents_direct = {}
+category_contents_all = {}
+
+spec_ids = {}
+for t in spec_assertions: spec_ids[t['id']] = True
+spec_refs = {}
+
+def backref_html(name):
+ backrefs = []
+ c = ''
+ for p in name.split('.')[:-1]:
+ c += '.'+p
+ backrefs.append('<a href="index%s.html">%s</a>.' % (c, p))
+ backrefs.append(name.split('.')[-1])
+ return ''.join(backrefs)
+
+def make_flat_image(filename, w, h, r,g,b,a):
+ if os.path.exists('%s/%s' % (IMAGEOUTPUTDIR, filename)):
+ return filename
+ surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
+ cr = cairo.Context(surface)
+ cr.set_source_rgba(r, g, b, a)
+ cr.rectangle(0, 0, w, h)
+ cr.fill()
+ surface.write_to_png('%s/%s' % (IMAGEOUTPUTDIR, filename))
+ return filename
+
+# Ensure the test output directories exist
+testdirs = [TESTOUTPUTDIR, IMAGEOUTPUTDIR, MISCOUTPUTDIR]
+if not W3CMODE: testdirs.append('%s/mochitests' % MISCOUTPUTDIR)
+else:
+ for map_dir in set(name_mapping.values()):
+ testdirs.append("%s/%s" % (TESTOUTPUTDIR, map_dir))
+for d in testdirs:
+ try: os.mkdir(d)
+ except: pass # ignore if it already exists
+
+mochitests = []
+used_images = {}
+
+def expand_test_code(code):
+ code = re.sub(r'@nonfinite ([^(]+)\(([^)]+)\)(.*)', lambda m: expand_nonfinite(m.group(1), m.group(2), m.group(3)), code) # must come before '@assert throws'
+
+ code = re.sub(r'@assert pixel (\d+,\d+) == (\d+,\d+,\d+,\d+);',
+ r'_assertPixel(canvas, \1, \2, "\1", "\2");',
+ code)
+
+ code = re.sub(r'@assert pixel (\d+,\d+) ==~ (\d+,\d+,\d+,\d+);',
+ r'_assertPixelApprox(canvas, \1, \2, "\1", "\2", 2);',
+ code)
+
+ code = re.sub(r'@assert pixel (\d+,\d+) ==~ (\d+,\d+,\d+,\d+) \+/- (\d+);',
+ r'_assertPixelApprox(canvas, \1, \2, "\1", "\2", \3);',
+ code)
+
+ code = re.sub(r'@assert throws (\S+_ERR) (.*);',
+ r'assert_throws("\1", function() { \2; });',
+ code)
+
+ code = re.sub(r'@assert throws (\S+Error) (.*);',
+ r'assert_throws(new \1(), function() { \2; });',
+ code)
+
+ code = re.sub(r'@assert throws (.*);',
+ r'assert_throws(null, function() { \1; });',
+ code)
+
+ code = re.sub(r'@assert (.*) === (.*);',
+ lambda m: '_assertSame(%s, %s, "%s", "%s");'
+ % (m.group(1), m.group(2), escapeJS(m.group(1)), escapeJS(m.group(2)))
+ , code)
+
+ code = re.sub(r'@assert (.*) !== (.*);',
+ lambda m: '_assertDifferent(%s, %s, "%s", "%s");'
+ % (m.group(1), m.group(2), escapeJS(m.group(1)), escapeJS(m.group(2)))
+ , code)
+
+ code = re.sub(r'@assert (.*) =~ (.*);',
+ lambda m: 'assert_regexp_match(%s, %s);'
+ % (m.group(1), m.group(2))
+ , code)
+
+ code = re.sub(r'@assert (.*);',
+ lambda m: '_assert(%s, "%s");'
+ % (m.group(1), escapeJS(m.group(1)))
+ , code)
+
+ code = re.sub(r' @moz-todo', '', code)
+
+ code = re.sub(r'@moz-UniversalBrowserRead;',
+ ""
+ , code)
+
+ assert('@' not in code)
+
+ return code
+
+def expand_mochitest_code(code):
+ code = re.sub(r'@nonfinite ([^(]+)\(([^)]+)\)(.*)', lambda m: expand_nonfinite(m.group(1), m.group(2), m.group(3)), code)
+
+ code = re.sub(r'@assert pixel (\d+,\d+) == (\d+,\d+,\d+,\d+);',
+ r'isPixel(ctx, \1, \2, "\1", "\2", 0);',
+ code)
+
+ code = re.sub(r'@assert pixel (\d+,\d+) ==~ (\d+,\d+,\d+,\d+);',
+ r'isPixel(ctx, \1, \2, "\1", "\2", 2);',
+ code)
+
+ code = re.sub(r'@assert pixel (\d+,\d+) ==~ (\d+,\d+,\d+,\d+) \+/- (\d+);',
+ r'isPixel(ctx, \1, \2, "\1", "\2", \3);',
+ code)
+
+ code = re.sub(r'@assert throws (\S+_ERR) (.*);',
+ lambda m: 'var _thrown = undefined; try {\n %s;\n} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.%s, "should throw %s");'
+ % (m.group(2), m.group(1), m.group(1))
+ , code)
+
+ code = re.sub(r'@assert throws (\S+Error) (.*);',
+ lambda m: 'var _thrown = undefined; try {\n %s;\n} catch (e) { _thrown = e }; ok(_thrown && (_thrown instanceof %s), "should throw %s");'
+ % (m.group(2), m.group(1), m.group(1))
+ , code)
+
+ code = re.sub(r'@assert throws (.*);',
+ lambda m: 'try { var _thrown = false;\n %s;\n} catch (e) { _thrown = true; } finally { ok(_thrown, "should throw exception"); }'
+ % (m.group(1))
+ , code)
+
+ code = re.sub(r'@assert (.*) =~ (.*);',
+ lambda m: 'ok(%s.match(%s), "%s.match(%s)");'
+ % (m.group(1), m.group(2), escapeJS(m.group(1)), escapeJS(m.group(2)))
+ , code)
+
+ code = re.sub(r'@assert (.*);',
+ lambda m: 'ok(%s, "%s");'
+ % (m.group(1), escapeJS(m.group(1)))
+ , code)
+
+ code = re.sub(r'((?:^|\n|;)\s*)ok(.*;) @moz-todo',
+ lambda m: '%stodo%s'
+ % (m.group(1), m.group(2))
+ , code)
+
+ code = re.sub(r'((?:^|\n|;)\s*)(is.*;) @moz-todo',
+ lambda m: '%stodo_%s'
+ % (m.group(1), m.group(2))
+ , code)
+
+ code = re.sub(r'@moz-UniversalBrowserRead;',
+ "netscape.security.PrivilegeManager.enablePrivilege('UniversalBrowserRead');"
+ , code)
+
+ code = code.replace('../images/', 'image_')
+
+ assert '@' not in code, '@ not in code:\n%s' % code
+
+ return code
+
+used_tests = {}
+for i in range(len(tests)):
+ test = tests[i]
+
+ name = test['name']
+ print "\r(%s)" % name, " "*32, "\t",
+
+ if name in used_tests:
+ print "Test %s is defined twice" % name
+ used_tests[name] = 1
+
+ mapped_name = None
+ for mn in sorted(name_mapping.keys(), key=len, reverse=True):
+ if name.startswith(mn):
+ mapped_name = "%s/%s" % (name_mapping[mn], name)
+ break
+ if not mapped_name:
+ print "LIKELY ERROR: %s has no defined target directory mapping" % name
+ mapped_name = name
+ if 'manual' in test:
+ mapped_name += "-manual"
+
+ cat_total = ''
+ for cat_part in [''] + name.split('.')[:-1]:
+ cat_total += cat_part+'.'
+ if not cat_total in category_names: category_names.append(cat_total)
+ category_contents_all.setdefault(cat_total, []).append(name)
+ category_contents_direct.setdefault(cat_total, []).append(name)
+
+ for ref in test.get('testing', []):
+ if ref not in spec_ids:
+ print "Test %s uses nonexistent spec point %s" % (name, ref)
+ spec_refs.setdefault(ref, []).append(name)
+ #if not (len(test.get('testing', [])) or 'mozilla' in test):
+ if not test.get('testing', []):
+ print "Test %s doesn't refer to any spec points" % name
+
+ if test.get('expected', '') == 'green' and re.search(r'@assert pixel .* 0,0,0,0;', test['code']):
+ print "Probable incorrect pixel test in %s" % name
+
+ code = expand_test_code(test['code'])
+
+ mochitest = not (W3CMODE or 'manual' in test or 'disabled' in test.get('mozilla', {}))
+ if mochitest:
+ mochi_code = expand_mochitest_code(test['code'])
+
+ mochi_name = name
+ if 'mozilla' in test:
+ if 'throws' in test['mozilla']:
+ mochi_code = templates['mochitest.exception'] % mochi_code
+ if 'bug' in test['mozilla']:
+ mochi_name = "%s - bug %s" % (name, test['mozilla']['bug'])
+
+ if 'desc' in test:
+ mochi_desc = '<!-- Testing: %s -->\n' % test['desc']
+ else:
+ mochi_desc = ''
+
+ if 'deferTest' in mochi_code:
+ mochi_setup = ''
+ mochi_footer = ''
+ else:
+ mochi_setup = ''
+ mochi_footer = 'SimpleTest.finish();\n'
+
+ for f in ['isPixel', 'todo_isPixel', 'deferTest', 'wrapFunction']:
+ if f in mochi_code:
+ mochi_setup += templates['mochitest.%s' % f]
+ else:
+ if not W3CMODE:
+ print "Skipping mochitest for %s" % name
+ mochi_name = ''
+ mochi_desc = ''
+ mochi_code = ''
+ mochi_setup = ''
+ mochi_footer = ''
+
+ expectation_html = ''
+ if 'expected' in test and test['expected'] is not None:
+ expected = test['expected']
+ expected_img = None
+ if expected == 'green':
+ expected_img = make_flat_image('green-100x50.png', 100, 50, 0,1,0,1)
+ if W3CMODE: expected_img = "/images/" + expected_img
+ elif expected == 'clear':
+ expected_img = make_flat_image('clear-100x50.png', 100, 50, 0,0,0,0)
+ if W3CMODE: expected_img = "/images/" + expected_img
+ else:
+ if ';' in expected: print "Found semicolon in %s" % name
+ expected = re.sub(r'^size (\d+) (\d+)',
+ r'surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, \1, \2)\ncr = cairo.Context(surface)',
+ expected)
+
+ if mapped_name.endswith("-manual"):
+ png_name = mapped_name[:-len("-manual")]
+ else:
+ png_name = mapped_name
+ expected += "\nsurface.write_to_png('%s/%s.png')\n" % (IMAGEOUTPUTDIR, png_name)
+ eval(compile(expected, '<test %s>' % test['name'], 'exec'), {}, {'cairo':cairo})
+ expected_img = "%s.png" % name
+
+ if expected_img:
+ expectation_html = ('<p class="output expectedtext">Expected output:' +
+ '<p><img src="%s" class="output expected" id="expected" alt="">' % (expected_img))
+
+ canvas = test.get('canvas', 'width="100" height="50"')
+
+ prev = tests[i-1]['name'] if i != 0 else 'index'
+ next = tests[i+1]['name'] if i != len(tests)-1 else 'index'
+
+ name_wrapped = name.replace('.', '.&#8203;') # (see https://bugzilla.mozilla.org/show_bug.cgi?id=376188)
+
+ refs = ''.join('<li><a href="%s/canvas.html#testrefs.%s">%s</a>\n' % (SPECOUTPUTPATH, n,n) for n in test.get('testing', []))
+ if not W3CMODE and 'mozilla' in test and 'bug' in test['mozilla']:
+ refs += '<li><a href="https://bugzilla.mozilla.org/show_bug.cgi?id=%d">Bugzilla</a>' % test['mozilla']['bug']
+
+ notes = '<p class="notes">%s' % test['notes'] if 'notes' in test else ''
+
+ images = ''
+ for i in test.get('images', []):
+ id = i.split('/')[-1]
+ if '/' not in i:
+ used_images[i] = 1
+ i = '../images/%s' % i
+ images += '<img src="%s" id="%s" class="resource">\n' % (i,id)
+ mochi_images = images.replace('../images/', 'image_')
+ if W3CMODE: images = images.replace("../images/", "/images/")
+
+ fonts = ''
+ fonthack = ''
+ for i in test.get('fonts', []):
+ fonts += '@font-face {\n font-family: %s;\n src: url("/fonts/%s.ttf");\n}\n' % (i, i)
+ # Browsers require the font to actually be used in the page
+ if test.get('fonthack', 1):
+ fonthack += '<span style="font-family: %s; position: absolute; visibility: hidden">A</span>\n' % i
+ if fonts:
+ fonts = '<style>\n%s</style>\n' % fonts
+
+ fallback = test.get('fallback', '<p class="fallback">FAIL (fallback content)</p>')
+
+ desc = test.get('desc', '')
+ escaped_desc = simpleEscapeJS(desc)
+ template_params = {
+ 'name':name, 'name_wrapped':name_wrapped, 'backrefs':backref_html(name),
+ 'mapped_name':mapped_name,
+ 'desc':desc, 'escaped_desc':escaped_desc,
+ 'prev':prev, 'next':next, 'refs':refs, 'notes':notes, 'images':images,
+ 'fonts':fonts, 'fonthack':fonthack,
+ 'canvas':canvas, 'expected':expectation_html, 'code':code,
+ 'mochi_name':mochi_name, 'mochi_desc':mochi_desc, 'mochi_code':mochi_code,
+ 'mochi_setup':mochi_setup, 'mochi_footer':mochi_footer, 'mochi_images':mochi_images,
+ 'fallback':fallback
+ }
+
+ if W3CMODE:
+ f = codecs.open('%s/%s.html' % (TESTOUTPUTDIR, mapped_name), 'w', 'utf-8')
+ f.write(templates['w3c'] % template_params)
+ else:
+ f = codecs.open('%s/%s.html' % (TESTOUTPUTDIR, name), 'w', 'utf-8')
+ f.write(templates['standalone'] % template_params)
+
+ f = codecs.open('%s/framed.%s.html' % (TESTOUTPUTDIR, name), 'w', 'utf-8')
+ f.write(templates['framed'] % template_params)
+
+ f = codecs.open('%s/minimal.%s.html' % (TESTOUTPUTDIR, name), 'w', 'utf-8')
+ f.write(templates['minimal'] % template_params)
+
+ if mochitest:
+ mochitests.append(name)
+ f = codecs.open('%s/mochitests/test_%s.html' % (MISCOUTPUTDIR, name), 'w', 'utf-8')
+ f.write(templates['mochitest'] % template_params)
+
+def write_mochitest_makefile():
+ f = open('%s/mochitests/Makefile.in' % MISCOUTPUTDIR, 'w')
+ f.write(templates['mochitest.Makefile'])
+ files = ['test_%s.html' % n for n in mochitests] + ['image_%s' % n for n in used_images]
+ chunksize = 100
+ chunks = []
+ for i in range(0, len(files), chunksize):
+ chunk = files[i:i+chunksize]
+ name = '_TEST_FILES_%d' % (i / chunksize)
+ chunks.append(name)
+ f.write('%s = \\\n' % name)
+ for file in chunk: f.write('\t%s \\\n' % file)
+ f.write('\t$(NULL)\n\n')
+ f.write('# split up into groups to work around command-line length limits\n')
+ for name in chunks:
+ f.write('libs:: $(%s)\n\t$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)\n\n' % name)
+
+if not W3CMODE:
+ for i in used_images:
+ shutil.copyfile("../../images/%s" % i, "%s/mochitests/image_%s" % (MISCOUTPUTDIR, i))
+ write_mochitest_makefile()
+
+print
+
+def write_index():
+ f = open('%s/index.html' % TESTOUTPUTDIR, 'w')
+ f.write(templates['index.w3c' if W3CMODE else 'index'] % { 'updated':time.strftime('%Y-%m-%d', time.gmtime()) })
+ f.write('\n<ul class="testlist">\n')
+ depth = 1
+ for category in category_names:
+ name = category[1:-1] or ''
+ count = len(category_contents_all[category])
+ new_depth = category.count('.')
+ while new_depth < depth: f.write(' '*(depth-1) + '</ul>\n'); depth -= 1
+ f.write(' '*depth + templates['index.w3c.category.item' if W3CMODE else 'index.category.item'] % (name or 'all', name, count, '' if count==1 else 's'))
+ while new_depth+1 > depth: f.write(' '*depth + '<ul>\n'); depth += 1
+ for item in category_contents_direct.get(category, []):
+ f.write(' '*depth + '<li><a href="%s.html">%s</a>\n' % (item, item) )
+ while 0 < depth: f.write(' '*(depth-1) + '</ul>\n'); depth -= 1
+
+def write_category_indexes():
+ for category in category_names:
+ name = (category[1:-1] or 'all')
+
+ f = open('%s/index.%s.html' % (TESTOUTPUTDIR, name), 'w')
+ f.write(templates['index.w3c.frame' if W3CMODE else 'index.frame'] % { 'backrefs':backref_html(name), 'category':name })
+ for item in category_contents_all[category]:
+ f.write(templates['index.w3c.frame.item' if W3CMODE else 'index.frame.item'] % item)
+
+def write_reportgen():
+ f = open('%s/reportgen.html' % MISCOUTPUTDIR, 'w')
+ items_text = ',\n'.join(('"%s"' % item) for item in category_contents_all['.'])
+ f.write(templates['reportgen'] % {'items':items_text })
+
+def write_results():
+ results = {}
+ uas = []
+ uastrings = {}
+ for item in category_contents_all['.']: results[item] = {}
+
+ f = open('%s/results.html' % MISCOUTPUTDIR, 'w')
+ f.write(templates['results'])
+
+ if not os.path.exists('results.yaml'):
+ print "Can't find results.yaml"
+ else:
+ for resultset in yaml.load(open('results.yaml').read()):
+ #title = "%s (%s)" % (resultset['ua'], resultset['time'])
+ title = resultset['name']
+ #assert title not in uas # don't allow repetitions
+ if title not in uas:
+ uas.append(title)
+ uastrings[title] = resultset['ua']
+ else:
+ assert uastrings[title] == resultset['ua']
+ for r in resultset['results']:
+ if r['id'] not in results:
+ print 'Skipping results for removed test %s' % r['id']
+ continue
+ results[r['id']][title] = (
+ r['status'].lower(),
+ re.sub(r'%(..)', lambda m: chr(int(m.group(1), 16)),
+ re.sub(r'%u(....)', lambda m: unichr(int(m.group(1), 16)),
+ r['notes'])).encode('utf8')
+ )
+
+ passes = {}
+ for ua in uas:
+ f.write('<th title="%s">%s\n' % (uastrings[ua], ua))
+ passes[ua] = 0
+ for id in category_contents_all['.']:
+ f.write('<tr><td><a href="#%s" id="%s">#</a> <a href="%s.html">%s</a>\n' % (id, id, id, id))
+ for ua in uas:
+ status, details = results[id].get(ua, ('', ''))
+ f.write('<td class="r %s"><ul class="d">%s</ul>\n' % (status, details))
+ if status == 'pass': passes[ua] += 1
+ f.write('<tr><th>Passes\n')
+ for ua in uas:
+ f.write('<td>%.1f%%\n' % ((100.0 * passes[ua]) / len(category_contents_all['.'])))
+ f.write('<tr><td>\n')
+ for ua in uas:
+ f.write('<td>%s\n' % ua)
+ f.write('</table>\n')
+
+def getNodeText(node):
+ t, offsets = '', []
+
+ # Skip over any previous annotations we added
+ if node.nodeType == node.ELEMENT_NODE and 'testrefs' in node.getAttribute('class').split(' '):
+ return t, offsets
+
+ if node.nodeType == node.TEXT_NODE:
+ val = node.nodeValue
+ val = val.replace(unichr(0xa0), ' ') # replace &nbsp;s
+ t += val
+ offsets += [ (node, len(node.nodeValue)) ]
+ for n in node.childNodes:
+ child_t, child_offsets = getNodeText(n)
+ t += child_t
+ offsets += child_offsets
+ return t, offsets
+
+def htmlSerializer(element):
+ element.normalize()
+ rv = []
+ specialtext = ['style', 'script', 'xmp', 'iframe', 'noembed', 'noframes', 'noscript']
+ empty = ['area', 'base', 'basefont', 'bgsound', 'br', 'col', 'embed', 'frame',
+ 'hr', 'img', 'input', 'link', 'meta', 'param', 'spacer', 'wbr']
+
+ def serializeElement(element):
+ if element.nodeType == Node.DOCUMENT_TYPE_NODE:
+ rv.append("<!DOCTYPE %s>" % element.name)
+ elif element.nodeType == Node.DOCUMENT_NODE:
+ for child in element.childNodes:
+ serializeElement(child)
+ elif element.nodeType == Node.COMMENT_NODE:
+ rv.append("<!--%s-->" % element.nodeValue)
+ elif element.nodeType == Node.TEXT_NODE:
+ unescaped = False
+ n = element.parentNode
+ while n is not None:
+ if n.nodeName in specialtext:
+ unescaped = True
+ break
+ n = n.parentNode
+ if unescaped:
+ rv.append(element.nodeValue)
+ else:
+ rv.append(escapeHTML(element.nodeValue))
+ else:
+ rv.append("<%s" % element.nodeName)
+ if element.hasAttributes():
+ for name, value in element.attributes.items():
+ rv.append(' %s="%s"' % (name, escapeHTML(value)))
+ rv.append(">")
+ if element.nodeName not in empty:
+ for child in element.childNodes:
+ serializeElement(child)
+ rv.append("</%s>" % element.nodeName)
+ serializeElement(element)
+ return '<!DOCTYPE html>\n' + ''.join(rv)
+
+def write_annotated_spec():
+ # Load the stripped-down XHTMLised copy of the spec
+ doc = xml.dom.minidom.parse(open('current-work-canvas.xhtml', 'r'))
+
+ # Insert our new stylesheet
+ n = doc.getElementsByTagName('head')[0].appendChild(doc.createElement('link'))
+ n.setAttribute('rel', 'stylesheet')
+ n.setAttribute('href', '../common/canvas-spec.css' if W3CMODE else '../spectest.css')
+ n.setAttribute('type', 'text/css')
+
+ spec_assertion_patterns = []
+ for a in spec_assertions:
+ # Warn about problems
+ if a['id'] not in spec_refs:
+ print "Unused spec statement %s" % a['id']
+
+ pattern_text = a['text']
+
+ if 'keyword' in a:
+ # Explicit keyword override
+ keyword = a['keyword']
+ else:
+ # Extract the marked keywords, and remove the markers
+ keyword = 'none'
+ for kw in ['must', 'should', 'required']:
+ if ('*%s*' % kw) in pattern_text:
+ keyword = kw
+ pattern_text = pattern_text.replace('*%s*' % kw, kw)
+ break
+ # Make sure there wasn't >1 keyword
+ for kw in ['must', 'should', 'required']:
+ assert('*%s*' % kw not in pattern_text)
+
+ # Convert the special pattern format into regexp syntax
+ pattern_text = (pattern_text.
+ # Escape relevant characters
+ replace('*', r'\*').
+ replace('+', r'\+').
+ replace('.', r'\.').
+ replace('(', r'\(').
+ replace(')', r'\)').
+ replace('[', r'\[').
+ replace(']', r'\]').
+ # Convert special sequences back into unescaped regexp code
+ replace(' ', r'\s+').
+ replace(r'<\.\.\.>', r'.+').
+ replace('<^>', r'()').
+ replace('<eol>', r'\s*?\n')
+ )
+ pattern = re.compile(pattern_text, re.S)
+ spec_assertion_patterns.append( (a['id'], pattern, keyword, a.get('previously', None)) )
+ matched_assertions = {}
+
+ def process_element(e):
+ if e.nodeType == e.ELEMENT_NODE and (e.getAttribute('class') == 'impl' or e.hasAttribute('data-component')):
+ for c in e.childNodes:
+ process_element(c)
+ return
+
+ t, offsets = getNodeText(e)
+ for id, pattern, keyword, previously in spec_assertion_patterns:
+ m = pattern.search(t)
+ if m:
+ # When the pattern-match isn't enough to uniquely identify a sentence,
+ # allow explicit back-references to earlier paragraphs
+ if previously:
+ if len(previously) >= 3:
+ n, text, exp = previously
+ else:
+ n, text = previously
+ exp = True
+ node = e
+ while n and node.previousSibling:
+ node = node.previousSibling
+ n -= 1
+ if (text not in getNodeText(node)[0]) == exp:
+ continue # discard this match
+
+ if id in matched_assertions:
+ print "Spec statement %s matches multiple places" % id
+ matched_assertions[id] = True
+
+ if m.lastindex != 1:
+ print "Spec statement %s has incorrect number of match groups" % id
+
+ end = m.end(1)
+ end_node = None
+ for end_node, o in offsets:
+ if end < o:
+ break
+ end -= o
+ assert(end_node)
+
+ n1 = doc.createElement('span')
+ n1.setAttribute('class', 'testrefs kw-%s' % keyword)
+ n1.setAttribute('id', 'testrefs.%s' % id)
+ n1.appendChild(doc.createTextNode(' '))
+
+ n = n1.appendChild(doc.createElement('a'))
+ n.setAttribute('href', '#testrefs.%s' % id)
+ n.setAttribute('title', id)
+ n.appendChild(doc.createTextNode('#'))
+
+ n1.appendChild(doc.createTextNode(' '))
+ for test_id in spec_refs.get(id, []):
+ n = n1.appendChild(doc.createElement('a'))
+ n.setAttribute('href', '../canvas/%s.html' % test_id)
+ n.appendChild(doc.createTextNode(test_id))
+ n1.appendChild(doc.createTextNode(' '))
+ n0 = doc.createTextNode(end_node.nodeValue[:end])
+ n2 = doc.createTextNode(end_node.nodeValue[end:])
+
+ p = end_node.parentNode
+ p.replaceChild(n2, end_node)
+ p.insertBefore(n1, n2)
+ p.insertBefore(n0, n1)
+
+ t, offsets = getNodeText(e)
+
+ for e in doc.getElementsByTagName('body')[0].childNodes:
+ process_element(e)
+
+ for s in spec_assertions:
+ if s['id'] not in matched_assertions:
+ print "Annotation incomplete: Unmatched spec statement %s" % s['id']
+
+ # Convert from XHTML back to HTML
+ doc.documentElement.removeAttribute('xmlns')
+ doc.documentElement.setAttribute('lang', doc.documentElement.getAttribute('xml:lang'))
+
+ head = doc.documentElement.getElementsByTagName('head')[0]
+ head.insertBefore(doc.createElement('meta'), head.firstChild).setAttribute('charset', 'UTF-8')
+
+ f = codecs.open('%s/canvas.html' % SPECOUTPUTDIR, 'w', 'utf-8')
+ f.write(htmlSerializer(doc))
+
+if not W3CMODE:
+ write_index()
+ write_category_indexes()
+ write_reportgen()
+ write_results()
+ write_annotated_spec()
diff --git a/tests/wpt/web-platform-tests/2dcontext/tools/name2dir.yaml b/tests/wpt/web-platform-tests/2dcontext/tools/name2dir.yaml
new file mode 100644
index 00000000000..6c170ce5537
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/tools/name2dir.yaml
@@ -0,0 +1,45 @@
+2d.transformation: "transformations"
+2d.composite: "compositing"
+2d.coordinatespace: "conformance-requirements"
+2d.missingargs: "conformance-requirements"
+2d.type.delete: "conformance-requirements"
+2d.voidreturn: "conformance-requirements"
+2d.drawImage: "drawing-images-to-the-canvas"
+2d.clearRect: "drawing-rectangles-to-the-canvas"
+2d.fillRect: "drawing-rectangles-to-the-canvas"
+2d.strokeRect: "drawing-rectangles-to-the-canvas"
+2d.text.draw: "drawing-text-to-the-canvas"
+2d.text.draw.baseline.alphabetic: "drawing-text-to-the-canvas"
+2d.text.draw.space.basic: "drawing-text-to-the-canvas"
+2d.text.draw.space.collapse: "drawing-text-to-the-canvas"
+2d.text.measure: "drawing-text-to-the-canvas"
+2d.fillStyle: "fill-and-stroke-styles"
+2d.gradient: "fill-and-stroke-styles"
+2d.pattern: "fill-and-stroke-styles"
+2d.strokeStyle: "fill-and-stroke-styles"
+2d.line: "line-styles"
+2d.path: "path-objects"
+2d.imageData: "pixel-manipulation"
+2d.shadow: "shadows"
+2d.text.align: "text-styles"
+2d.text.baseline: "text-styles"
+2d.text.font: "text-styles"
+2d.text.draw.baseline: "text-styles"
+2d.text.draw.space: "text-styles"
+2d.text.measure.width.space: "text-styles"
+2d.text.draw.space.collapse.end: "text-styles"
+2d.text.draw.space.collapse.other: "text-styles"
+2d.text.draw.space.collapse.space: "text-styles"
+2d.text.draw.space.collapse.start: "text-styles"
+2d.state: "the-canvas-state"
+2d.canvas: "../html/semantics/embedded-content/the-canvas-element/"
+2d.getcontext: "../html/semantics/embedded-content/the-canvas-element/"
+2d.scaled: "../html/semantics/embedded-content/the-canvas-element/"
+2d.type: "../html/semantics/embedded-content/the-canvas-element/"
+context: "../html/semantics/embedded-content/the-canvas-element/"
+fallback: "../html/semantics/embedded-content/the-canvas-element/"
+initial: "../html/semantics/embedded-content/the-canvas-element/"
+security: "../html/semantics/embedded-content/the-canvas-element/"
+size: "../html/semantics/embedded-content/the-canvas-element/"
+toDataURL: "../html/semantics/embedded-content/the-canvas-element/"
+type: "../html/semantics/embedded-content/the-canvas-element/"
diff --git a/tests/wpt/web-platform-tests/2dcontext/tools/spec.yaml b/tests/wpt/web-platform-tests/2dcontext/tools/spec.yaml
new file mode 100644
index 00000000000..12b7d6be990
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/tools/spec.yaml
@@ -0,0 +1,717 @@
+# Extracts from http://www.whatwg.org/specs/web-apps/current-work/
+#
+# (c) Copyright 2004-2011 Apple Computer, Inc., Mozilla Foundation, and Opera Software ASA.
+# You are granted a license to use, reproduce and create derivative works of this document.
+
+assertions:
+ - id: canvas.type
+ text: "interface HTMLCanvasElement<^> : HTMLElement {"
+ - id: size.width
+ text: "interface HTMLCanvasElement<...>attribute unsigned long width;<^>"
+ - id: size.height
+ text: "interface HTMLCanvasElement<...>attribute unsigned long height;<^>"
+ - id: canvas.getContext
+ text: "interface HTMLCanvasElement<...>object\\? getContext(in DOMString contextId, in any... args);<^>"
+ - id: fallback
+ text: "The contents of the canvas element, if any, are the element's fallback content<^>."
+ - id: size.nonnegativeinteger
+ text: "The rules for parsing non-negative integers *must* be used to obtain their numeric values<^>."
+ - id: size.missing
+ text: "If an attribute is missing<^>, <...> then the default value *must* be used instead."
+ - id: size.error
+ text: "if parsing its value returns an error<^>, then the default value *must* be used instead."
+ - id: size.default
+ text: "The width attribute defaults to 300, and the height attribute defaults to 150<^>."
+ - id: size.css
+ text: "the element can be sized arbitrarily by a style sheet. During rendering, the image is scaled to fit this layout size<^>."
+ - id: initial.reset
+ text: "When the canvas element is created, and subsequently whenever the width and height attributes are set (whether to a new value or to the previous value), the bitmap and any associated contexts *must* be cleared back to their initial state <...><^>."
+ - id: initial.colour
+ text: "When the canvas is initialized, its bitmap *must* be cleared to transparent black<^>."
+ - id: size.reflect
+ text: "The width and height IDL attributes *must* reflect the respective content attributes of the same name<^>,"
+
+ - id: context.unrecognised
+ text: "If contextId is not the name of a context supported by the user agent, return null and abort these steps<^>."
+ - id: context.unique
+ text: "If the getContext() method has already been invoked on this element for the same contextId, return the same object as was returned that time, and abort these steps<^>."
+ - id: context.2d
+ text: "When the getContext() method of a canvas element is to return a new object for the contextId 2d, the user agent *must* return a new CanvasRenderingContext2D object<^>."
+ - id: context.2d.extraargs
+ text: "When the getContext() method of a canvas element is to return a new object for the contextId 2d, the user agent *must* return a new CanvasRenderingContext2D object. Any additional arguments are ignored<^>."
+
+ - id: toDataURL.noarguments
+ text: "When a user agent is to create a serialization of the image as a file, <...> if there are no arguments, in the PNG format<^>."
+ - id: toDataURL.zerosize
+ text: "If the canvas has no pixels (i.e. either its horizontal dimension or its vertical dimension is zero) then return the string \"data:,\"<^> and abort these steps."
+ - id: toDataURL.witharguments
+ text: "If arguments is not empty, the first value must be interpreted as a MIME type giving the format to use<^>."
+ - id: toDataURL.noalpha
+ text: "For image types that do not support an alpha channel, the serialized image *must* be the canvas image composited onto a solid black background using the source-over operator<^>."
+ - id: toDataURL.png
+ text: "User agents *must* support PNG (\"image/png\")<^>."
+ - id: toDataURL.unrecognised
+ text: "If the user agent does not support the requested type, it *must* create the file using the PNG format<^>."
+ - id: toDataURL.lowercase
+ text: "User agents *must* convert the provided type to ASCII lowercase before establishing if they support that type<^>."
+ - id: toDataURL.jpeg
+ previously: [ 0, "image/png", false ]
+ text: "image/jpeg<^>"
+ - id: toDataURL.jpeg.quality
+ text: "The second argument, if it is a number in the range 0.0 to 1.0 inclusive, *must* be treated as the desired quality level<^>."
+ - id: toDataURL.jpeg.nan
+ text: "If it is not a number<^> <...>, the user agent *must* use its default value, as if the argument had been omitted."
+ - id: toDataURL.jpeg.range
+ text: "If it is <...> outside that range<^>, the user agent *must* use its default value, as if the argument had been omitted."
+ - id: toDataURL.arguments
+ text: "Other arguments *must* be ignored and must not cause the user agent to raise an exception<^>."
+
+ - id: 2d.coordinatespace
+ text: "flat Cartesian surface whose origin (0,0) is at the top left corner, with the coordinate space having x values increasing when going right, and y values increasing when going down<^>."
+ - id: context.2d.type
+ text: "interface CanvasRenderingContext2D<^> {"
+ - id: 2d.canvasGradient.type
+ text: "interface CanvasGradient<^> {"
+ - id: 2d.imageData.type
+ text: "interface ImageData<^> {"
+ - id: 2d.canvas.attribute
+ text: "readonly<^> attribute HTMLCanvasElement canvas;"
+ - id: 2d.canvas
+ text: "The canvas attribute *must* return the canvas element that the context paints on<^>."
+ - id: 2d.nonfinite
+ text: "Except where otherwise specified, for the 2D context interface, any method call with a numeric argument whose value is infinite or a NaN value *must* be ignored<^>."
+
+ - id: 2d.currentColor.onset
+ text: "Whenever the CSS value currentColor is used as a color in this API, the \"computed value of the 'color' property\" for the purposes of determining the computed value of the currentColor keyword is the computed value of the 'color' property on the element in question at the time that the color is specified<^>"
+ - id: 2d.currentColor.outofdoc
+ text: "If the computed value of the 'color' property is undefined for a particular case (e.g. because the element is not in a Document), then the \"computed value of the 'color' property\" for the purposes of determining the computed value of the currentColor keyword is fully opaque black<^>."
+ - id: 2d.currentColor.gradient
+ text: "In the case of addColorStop() on CanvasGradient, the \"computed value of the 'color' property\" for the purposes of determining the computed value of the currentColor keyword is always fully opaque black<^> (there is no associated element)."
+
+ - id: 2d.state.transformation
+ text: "The current transformation matrix<^>."
+ - id: 2d.state.clip
+ text: "The current clipping region<^>."
+ - meta: |
+ for s in [
+ 'strokeStyle', 'fillStyle', 'globalAlpha',
+ 'lineWidth', 'lineCap', 'lineJoin', 'miterLimit',
+ 'shadowOffsetX', 'shadowOffsetY', 'shadowBlur', 'shadowColor',
+ 'globalCompositeOperation',
+ 'font', 'textAlign', 'textBaseline'
+ ]:
+ assertions.append( {
+ 'id': '2d.state.%s' % s,
+ 'text': 'The current values of the following attributes:<...>%s<^>' % s
+ } )
+ - id: 2d.state.path
+ text: "The current path<^> <...> are not part of the drawing state."
+ - id: 2d.state.bitmap
+ text: "The <...> current bitmap<^> are not part of the drawing state."
+
+ - id: 2d.state.save
+ text: "The save() method *must* push a copy of the current drawing state onto the drawing state stack<^>."
+ - id: 2d.state.restore
+ text: "The restore() method *must* pop the top entry in the drawing state stack, and reset the drawing state it describes<^>."
+ - id: 2d.state.restore.underflow
+ text: "If there is no saved state, the method *must* do nothing<^>."
+
+ - id: 2d.transformation.initial
+ text: "When the context is created, the transformation matrix *must* initially be the identity transform<^>."
+ - id: 2d.transformation.order
+ text: "The transformations *must* be performed in reverse order<^>."
+ - id: 2d.transformation.scale
+ text: "The scale(x, y) method *must* add the scaling transformation described by the arguments to the transformation matrix<^>."
+ - id: 2d.transformation.scale.multiple
+ text: "The factors are multiples<^>."
+ - id: 2d.transformation.rotate
+ text: "The rotate(angle) method *must* add the rotation transformation described by the argument to the transformation matrix<^>."
+ - id: 2d.transformation.rotate.direction
+ text: "The angle argument represents a clockwise rotation angle<^>"
+ - id: 2d.transformation.rotate.radians
+ text: "The angle argument <...> expressed in radians<^>."
+ - id: 2d.transformation.translate
+ text: "The translate(x, y) method *must* add the translation transformation described by the arguments to the transformation matrix<^>."
+ - id: 2d.transformation.transform
+ text: "The transform(a, b, c, d, e, f) method *must* replace the current transformation matrix with the result of multiplying the current transformation matrix with the matrix described by<^>:"
+ - id: 2d.transformation.transform.multiply
+ text: "The transform(a, b, c, d, e, f) method *must* replace the current transformation matrix with the result of multiplying<^> the current transformation matrix with the matrix described by:"
+ - id: 2d.transformation.setTransform
+ text: "The setTransform(a, b, c, d, e, f) method *must* <...> invoke the transform(a, b, c, d, e, f) method with the same arguments<^>"
+ - id: 2d.transformation.setTransform.identity
+ text: "The setTransform(a, b, c, d, e, f) method *must* reset the current transform to the identity matrix<^>, "
+
+
+ - id: 2d.composite.operation
+ text: "All drawing operations are affected by the global compositing attributes, globalAlpha and globalCompositeOperation<^>."
+
+ - id: 2d.composite.globalAlpha.shape
+ text: "The globalAlpha attribute gives an alpha value that is applied to shapes<^> and images before they are composited onto the canvas."
+ - id: 2d.composite.globalAlpha.image
+ text: "The globalAlpha attribute gives an alpha value that is applied to shapes and images<^> before they are composited onto the canvas."
+ - id: 2d.composite.globalAlpha.range
+ text: "The value must be in the range from 0.0 (fully transparent) to 1.0 (no additional transparency). If an attempt is made to set the attribute to a value outside this range, including Infinity and Not-a-Number (NaN) values, the attribute *must* retain its previous value<^>."
+ - id: 2d.composite.globalAlpha.default
+ text: "When the context is created, the globalAlpha attribute *must* initially have the value 1.0<^>."
+
+ - id: 2d.composite.operation.shape
+ text: "The globalCompositeOperation attribute sets how shapes<^> and images are drawn onto the existing bitmap,"
+ - id: 2d.composite.operation.image
+ text: "The globalCompositeOperation attribute sets how shapes and images<^> are drawn onto the existing bitmap,"
+
+ - id: 2d.composite.source-atop
+ text: "source-atop<^><eol>"
+ - id: 2d.composite.source-in
+ text: "source-in<^><eol>"
+ - id: 2d.composite.source-out
+ text: "source-out<^><eol>"
+ - id: 2d.composite.source-over
+ text: "source-over (default)<^><eol>"
+ - id: 2d.composite.destination-atop
+ text: "destination-atop<^><eol>"
+ - id: 2d.composite.destination-in
+ text: "destination-in<^><eol>"
+ - id: 2d.composite.destination-out
+ text: "destination-out<^><eol>"
+ - id: 2d.composite.destination-over
+ text: "destination-over<^><eol>"
+ - id: 2d.composite.lighter
+ text: "lighter<^><eol>"
+ - id: 2d.composite.copy
+ text: "copy<^><eol>"
+ - id: 2d.composite.xor
+ text: "xor<^><eol>"
+
+ - id: 2d.composite.operation.casesensitive
+ text: "These values are all case-sensitive<^> <...> they *must* be used exactly as shown."
+ - id: 2d.composite.operation.exact
+ text: "User agents *must* not recognize values that are not a case-sensitive match for one of the values given above<^>."
+ - id: 2d.composite.operation.porterduff
+ text: "The operators in the above list *must* be treated as described by the Porter-Duff operator given at the start of their description (e.g. A over B)<^>."
+ - id: 2d.composite.operation.unrecognised
+ text: "On setting, if the user agent does not recognize the specified value, it *must* be ignored, leaving the value of globalCompositeOperation unaffected<^>."
+ - id: 2d.composite.operation.default
+ text: "When the context is created, the globalCompositeOperation attribute *must* initially have the value source-over<^>."
+
+
+ - id: 2d.colours.parse
+ text: "On setting, strings *must* be parsed as CSS <color> values and the color assigned<^>,"
+ - id: 2d.gradient.assign
+ text: "On setting, <...> CanvasGradient<^> and CanvasPattern objects *must* be assigned themselves."
+ - id: 2d.pattern.assign
+ text: "On setting, <...> CanvasGradient and CanvasPattern<^> objects *must* be assigned themselves."
+ - id: 2d.colours.invalidstring
+ text: "If the value is a string but cannot be parsed as a CSS <color> value<^>, <...> then it *must* be ignored, and the attribute must retain its previous value."
+ - id: 2d.colours.invalidtype
+ text: "If the value is <...> neither a string, a CanvasGradient, nor a CanvasPattern<^>, then it *must* be ignored, and the attribute must retain its previous value."
+ - id: 2d.colours.getcolour
+ text: "On getting, if the value is a color, then the serialization of the color *must* be returned<^>."
+ - id: 2d.gradient.object
+ text: "if it is not a color but a CanvasGradient<^> or CanvasPattern, then the respective object *must* be returned."
+ - id: 2d.pattern.object
+ text: "if it is not a color but a CanvasGradient or CanvasPattern<^>, then the respective object *must* be returned."
+ - id: 2d.serializecolour.solid
+ text: "if it has alpha equal to 1.0, then the string is a lowercase six-digit hex value<^>"
+ - id: 2d.serializecolour.transparent
+ text: "Otherwise, the color value has alpha less than 1.0, and the string is the color value in the CSS rgba() functional-notation format<^>:"
+ - id: 2d.colours.default
+ text: "When the context is created, the strokeStyle and fillStyle attributes *must* initially have the string value #000000<^>."
+
+ - id: 2d.gradient.interpolate.linear
+ text: "Between each such stop, the colors and the alpha component *must* be linearly interpolated<^> over the RGBA space without premultiplying the alpha value to find the color to use at that offset."
+ - id: 2d.gradient.interpolate.alpha
+ text: "Between each such stop, the colors and the alpha component *must* be linearly interpolated over the RGBA space without premultiplying the alpha value<^> to find the color to use at that offset."
+ - id: 2d.gradient.outside.first
+ text: "Before the first stop, the color *must* be the color of the first stop<^>."
+ - id: 2d.gradient.outside.last
+ text: "After the last stop, the color *must* be the color of the last stop<^>."
+ - id: 2d.gradient.empty
+ text: "When there are no stops, the gradient is transparent black<^>."
+
+
+ - id: 2d.gradient.invalidoffset
+ text: "If the offset is less than 0, greater than 1, infinite, or NaN, then an INDEX_SIZE_ERR exception *must* be raised<^>."
+ - id: 2d.gradient.invalidcolour
+ text: "If the color cannot be parsed as a CSS <color> value, then a SYNTAX_ERR exception *must* be raised<^>."
+ - id: 2d.gradient.update
+ text: "Otherwise, the gradient *must* have a new stop placed, at offset offset relative to the whole gradient, and with the color obtained by parsing color as a CSS <color> value<^>."
+ - id: 2d.gradient.interpolate.overlap
+ text: "If multiple stops are added at the same offset on a gradient, they *must* be placed in the order added, with the first one closest to the start of the gradient, <...><^>."
+
+ - id: 2d.gradient.linear.nonfinite
+ text: "If any of the arguments to createLinearGradient() are infinite or NaN, the method *must* raise a NOT_SUPPORTED_ERR exception<^>."
+ - id: 2d.gradient.linear.return
+ text: "Otherwise, the method *must* return a linear CanvasGradient initialized with the specified line<^>."
+ - id: 2d.gradient.linear.rendering
+ text: "Linear gradients *must* be rendered such that all points on a line perpendicular to the line that crosses the start and end points have the color at the point where those two lines cross (with the colors coming from the interpolation and extrapolation described above)<^>."
+ - id: 2d.gradient.linear.transform
+ text: "The points in the linear gradient *must* be transformed as described by the current transformation matrix when rendering<^>."
+ - id: 2d.gradient.linear.zerosize
+ text: "If x0 = x1 and y0 = y1, then the linear gradient *must* paint nothing<^>."
+
+ - id: 2d.gradient.radial.nonfinite
+ text: "If any of the arguments are infinite or NaN, a NOT_SUPPORTED_ERR exception *must* be raised<^>."
+ - id: 2d.gradient.radial.negative
+ text: "If either of r0 or r1 are negative, an INDEX_SIZE_ERR exception *must* be raised<^>."
+ - id: 2d.gradient.radial.return
+ text: "Otherwise, the method *must* return a radial CanvasGradient initialized with the two specified circles<^>."
+ - id: 2d.gradient.radial.rendering
+ text: "Radial gradients *must* be rendered by following these steps<^>:"
+ - id: 2d.gradient.radial.equal
+ text: "If x0 = x1 and y0 = y1 and r0 = r1, then the radial gradient *must* paint nothing<^>."
+ - id: 2d.gradient.extent
+ text: "Gradients *must* be painted only where the relevant stroking or filling effects requires that they be drawn<^>."
+ - id: 2d.gradient.radial.transform
+ text: "The points in the radial gradient *must* be transformed as described by the current transformation matrix when rendering<^>."
+
+
+ - id: 2d.pattern.modify
+ text: "Modifying this image after calling the createPattern() method *must* not affect the pattern<^>."
+ - id: 2d.pattern.missing
+ text: "If the empty string is specified, repeat *must* be assumed<^>."
+ - id: 2d.pattern.unrecognised
+ text: "If an unrecognized value is given, then the user agent *must* raise a SYNTAX_ERR exception<^>."
+ - id: 2d.pattern.exact
+ text: "User agents *must* recognize the four values described above exactly (e.g. they must not do case folding)<^>."
+ - id: 2d.pattern.return
+ text: "the method *must* return a CanvasPattern object suitably initialized<^>."
+ - id: 2d.pattern.IDL
+ text: "CanvasPattern createPattern(in HTMLImageElement image, in DOMString repetition);<...>CanvasPattern createPattern(in HTMLCanvasElement image, in DOMString repetition);<...>CanvasPattern createPattern(in HTMLVideoElement image, in DOMString repetition);<^>"
+ - id: 2d.pattern.incomplete.image
+ text: "If the image argument is an HTMLImageElement object that is not fully decodable<^><...> then the implementation *must* return null."
+ - id: 2d.pattern.incomplete.video
+ previously: [ 6, "createPattern" ]
+ text: "If the image argument is <...> an HTMLVideoElement object whose readyState attribute is either HAVE_NOTHING or HAVE_METADATA<^>, then the implementation *must* return null."
+ - id: 2d.pattern.zerocanvas
+ previously: [ 10, "createPattern" ]
+ text: "If the image argument is an HTMLCanvasElement object with either a horizontal dimension or a vertical dimension equal to zero, then the implementation *must* raise an INVALID_STATE_ERR exception<^>."
+ - id: 2d.pattern.painting
+ text: "Patterns *must* be painted so that the top left of the first image is anchored at the origin of the coordinate space, and images are then repeated horizontally to the left and right (if the repeat-x string was specified) or vertically up and down (if the repeat-y string was specified) or in all four directions all over the canvas (if the repeat string was specified)<^>."
+ - id: 2d.pattern.unscaled
+ text: "The images are not scaled by this process; one CSS pixel of the image *must* be painted on one coordinate space unit<^>."
+ - id: 2d.pattern.extent
+ text: "patterns *must* actually be painted only where the stroking or filling effect requires that they be drawn<^>, and are affected by the current transformation matrix."
+ - id: 2d.pattern.animated.image
+ text: "When the createPattern() method is passed an animated image as its image argument, the user agent must use the poster frame of the animation, or, if there is no poster frame, the first frame of the animation<^>."
+ - id: 2d.pattern.animated.video
+ previously: [ 4, "createPattern" ]
+ text: "When the image argument is an HTMLVideoElement, then the frame at the current playback position *must* be used as the source image<^>,"
+ - id: 2d.pattern.video.size
+ previously: [ 4, "createPattern" ]
+ text: "When the image argument is an HTMLVideoElement, <...> the source image's dimensions *must* be the intrinsic width and intrinsic height of the media resource (i.e. after any aspect-ratio correction has been applied)<^>."
+
+
+ - id: 2d.lineWidth
+ text: "The lineWidth attribute gives the width of lines, in coordinate space units<^>."
+ - id: 2d.lineWidth.get
+ text: "The lineWidth attribute <...>. On getting, it *must* return the current value<^>."
+ - id: 2d.lineWidth.invalid
+ text: "The lineWidth attribute <...>. On setting, zero, negative, infinite, and NaN values *must* be ignored, leaving the value unchanged<^>;"
+ - id: 2d.lineWidth.set
+ text: "The lineWidth attribute <...>. On setting, <...> other values *must* change the current value to the new value<^>."
+ - id: 2d.lineWidth.default
+ text: "the lineWidth attribute *must* initially have the value 1.0<^>."
+ - id: 2d.lineCap.end
+ text: "The lineCap attribute defines the type of endings that UAs will place on the end of lines<^>."
+ - id: 2d.lineCap.butt
+ text: "The butt value means that the end of each line has a flat edge perpendicular to the direction of the line (and that no additional line cap is added)<^>."
+ - id: 2d.lineCap.round
+ text: "The round value means that a semi-circle with the diameter equal to the width of the line *must* then be added on to the end of the line<^>."
+ - id: 2d.lineCap.square
+ text: "The square value means that a rectangle with the length of the line width and the width of half the line width, placed flat against the edge perpendicular to the direction of the line, *must* be added at the end of each line<^>."
+ - id: 2d.lineCap.get
+ previously: [ 2, "The lineCap attribute" ]
+ text: "On getting, it *must* return the current value<^>."
+ - id: 2d.lineCap.set
+ text: "On setting, if the new value is one of the literal strings butt, round, and square, then the current value *must* be changed to the new value<^>;"
+ - id: 2d.lineCap.invalid
+ text: "On setting, if the new value is one of the literal strings butt, round, and square, then <...>; other values *must* ignored, leaving the value unchanged<^>."
+ - id: 2d.lineCap.default
+ text: "When the context is created, the lineCap attribute *must* initially have the value butt<^>."
+ - id: 2d.lineJoin.get
+ previously: [ 2, "lineJoin" ]
+ text: "On getting, it *must* return the current value<^>."
+ - id: 2d.lineJoin.set
+ text: "On setting, if the new value is one of the literal strings bevel, round, and miter, then the current value *must* be changed to the new value<^>;"
+ - id: 2d.lineJoin.invalid
+ text: "On setting, if the new value is one of the literal strings bevel, round, and miter, then <...>; other values *must* be ignored, leaving the value unchanged<^>."
+ - id: 2d.lineJoin.default
+ text: "When the context is created, the lineJoin attribute *must* initially have the value miter<^>."
+ - id: 2d.lineJoin.joins
+ text: "A join exists at any point in a subpath shared by two consecutive lines<^>."
+ - id: 2d.lineJoin.joinclosed
+ text: "When a subpath is closed, then a join also exists at its first point (equivalent to its last point) connecting the first and last lines in the subpath<^>."
+ - id: 2d.lineJoin.common
+ text: "A filled triangle connecting these two opposite corners with a straight line, with the third point of the triangle being the join point, *must* be rendered at all joins<^>."
+ - id: 2d.lineJoin.round
+ text: "The round value means that a filled arc connecting the two aforementioned corners of the join, abutting (and not overlapping) the aforementioned triangle, with the diameter equal to the line width and the origin at the point of the join, *must* be rendered at joins<^>."
+ - id: 2d.lineJoin.bevel
+ text: "The bevel value means that this is all that is rendered at joins<^>."
+ - id: 2d.lineJoin.miter
+ text: "The miter value means that a second filled triangle *must* (if it can given the miter length) be rendered at the join, with one line being the line between the two aforementioned corners, abutting the first triangle, and the other two being continuations of the outside edges of the two joining lines, as long as required to intersect without going over the miter length<^>."
+ - id: 2d.lineJoin.miterLimit
+ text: "If the miter length would cause the miter limit ratio to be exceeded, this second triangle *must* not be rendered<^>."
+ - id: 2d.miterLimit.get
+ text: "The miter limit <...>. On getting, it *must* return the current value<^>."
+ - id: 2d.miterLimit.invalid
+ text: "The miter limit <...>. On setting, zero, negative, infinite, and NaN values *must* be ignored, leaving the value unchanged<^>;"
+ - id: 2d.miterLimit.set
+ text: "The miter limit <...>. On setting, <...>; other values *must* change the current value to the new value<^>."
+ - id: 2d.miterLimit.default
+ text: "When the context is created, the miterLimit attribute *must* initially have the value 10.0<^>."
+
+
+ - id: 2d.shadow.color.initial
+ text: "When the context is created, the shadowColor attribute initially *must* be fully-transparent black<^>."
+ - id: 2d.shadow.color.get
+ text: "On getting, the serialization of the color *must* be returned<^>."
+ - id: 2d.shadow.color.set
+ text: "On setting, the new value *must* be parsed as a CSS <color> value and the color assigned<^>."
+ - id: 2d.shadow.color.invalid
+ text: "If the value cannot be parsed as a CSS <color> value then it *must* be ignored, and the attribute must retain its previous value<^>."
+ - id: 2d.shadow.offset.initial
+ text: "When the context is created, the shadow offset attributes *must* initially have the value 0<^>."
+ - id: 2d.shadow.offset.get
+ text: "On getting, they *must* return their current value<^>."
+ - id: 2d.shadow.offset.set
+ text: "On setting, the attribute being set *must* be set to the new value<^>,"
+ - id: 2d.shadow.offset.invalid
+ text: "On setting, <...> if the value is infinite or NaN, in which case the new value *must* be ignored<^>."
+ - id: 2d.shadow.blur.initial
+ text: "When the context is created, the shadowBlur attribute *must* initially have the value 0<^>."
+ - id: 2d.shadow.blur.get
+ text: "On getting, the attribute *must* return its current value<^>."
+ - id: 2d.shadow.blur.set
+ text: "On setting the attribute *must* be set to the new value<^>,"
+ - id: 2d.shadow.blur.invalid
+ text: "On setting <...> if the value is negative, infinite or NaN, in which case the new value *must* be ignored<^>."
+ - id: 2d.shadow.enable
+ text: "Shadows are only drawn if the opacity component of the alpha component of the color of shadowColor is non-zero and either the shadowBlur is non-zero, or the shadowOffsetX is non-zero, or the shadowOffsetY is non-zero<^>."
+ - id: 2d.shadow.render
+ text: "When shadows are drawn, they *must* be rendered as follows<^>:"
+
+ - id: 2d.rect.transform
+ text: "The current transformation matrix *must* be applied to the following four coordinates<^>,"
+ - id: 2d.rect.closed
+ text: "the following four coordinates, which form the path that *must* then be closed to get the specified rectangle<^>:"
+ - id: 2d.clearRect
+ text: "The clearRect(x, y, w, h) method *must* clear the pixels in the specified rectangle that also intersect the current clipping region to a fully transparent black, erasing any previous image<^>."
+ - id: 2d.fillRect
+ text: "The fillRect(x, y, w, h) method *must* paint the specified rectangular area using the fillStyle<^>."
+ - id: 2d.strokeRect
+ text: "The strokeRect(x, y, w, h) method *must* stroke the specified rectangle's path using the strokeStyle, lineWidth, lineJoin, and (if appropriate) miterLimit attributes<^>."
+
+
+ - id: 2d.path.initial
+ text: "Initially, the context's path *must* have zero subpaths<^>."
+ - id: 2d.path.transformation
+ text: "The points and lines added to the path by these methods *must* be transformed according to the current transformation matrix as they are added<^>."
+ - id: 2d.path.beginPath
+ text: "The beginPath() method *must* empty the list of subpaths so that the context once again has zero subpaths<^>."
+ - id: 2d.path.moveTo
+ text: "The moveTo(x, y) method *must* create a new subpath with the specified point as its first (and only) point<^>."
+ - id: 2d.path.ensure
+ text: "When the user agent is to ensure there is a subpath for a coordinate (x, y), the user agent must check to see if the context has any subpaths, and if it does not, then the user agent *must* create a new subpath with the point (x, y) as its first (and only) point, as if the moveTo() method had been called<^>."
+ - id: 2d.path.closePath.empty
+ text: "The closePath() method *must* do nothing if the context has no subpaths<^>."
+ - id: 2d.path.closePath.nonempty
+ text: "The closePath() method <...> *must* mark the last subpath as closed, create a new subpath whose first point is the same as the previous subpath's first point, and finally add this new subpath to the path<^>."
+ - id: 2d.path.lineTo.empty
+ text: "The lineTo(x, y) method *must* ensure there is a subpath for (x, y) if the context has no subpaths<^>."
+ - id: 2d.path.lineTo.nonempty
+ text: "The lineTo(x, y) method <...> *must* connect the last point in the subpath to the given point (x, y) using a straight line, and must then add the given point (x, y) to the subpath<^>."
+ - id: 2d.path.quadratic.empty
+ text: "The quadraticCurveTo(cpx, cpy, x, y) method *must* ensure there is a subpath for (cpx, cpy)<^>,"
+ - id: 2d.path.quadratic.nonempty
+ text: "The quadraticCurveTo(cpx, cpy, x, y) method <...> *must* connect the last point in the subpath to the given point (x, y) using a quadratic B<...>zier curve with control point (cpx, cpy), and must then add the given point (x, y) to the subpath<^>."
+ - id: 2d.path.bezier.empty
+ text: "The bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y) method *must* ensure there is a subpath for (cp1x, cp1y)<^>,"
+ - id: 2d.path.bezier.nonempty
+ text: "The bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y) method <...> *must* connect the last point in the subpath to the given point (x, y) using a cubic B<...>zier curve with control points (cp1x, cp1y) and (cp2x, cp2y). Then, it must add the point (x, y) to the subpath<^>."
+ - id: 2d.path.arcTo.empty
+ text: "The arcTo(x1, y1, x2, y2, radius) method *must* first ensure there is a subpath for (x1, y1)<^>."
+ - id: 2d.path.arcTo.negative
+ previously: [ 2, "arcTo(" ]
+ text: "Negative values for radius *must* cause the implementation to raise an INDEX_SIZE_ERR exception<^>."
+ - id: 2d.path.arcTo.coincide.01
+ text: "If the point (x0, y0) is equal to the point (x1, y1)<^>, or if the point (x1, y1) is equal to the point (x2, y2), or if the radius radius is zero, then the method *must* add the point (x1, y1) to the subpath, and connect that point to the previous point (x0, y0) by a straight line."
+ - id: 2d.path.arcTo.coincide.12
+ text: "If the point (x0, y0) is equal to the point (x1, y1), or if the point (x1, y1) is equal to the point (x2, y2)<^>, or if the radius radius is zero, then the method *must* add the point (x1, y1) to the subpath, and connect that point to the previous point (x0, y0) by a straight line."
+ - id: 2d.path.arcTo.zeroradius
+ text: "If the point (x0, y0) is equal to the point (x1, y1), or if the point (x1, y1) is equal to the point (x2, y2), or if the radius radius is zero<^>, then the method *must* add the point (x1, y1) to the subpath, and connect that point to the previous point (x0, y0) by a straight line."
+ - id: 2d.path.arcTo.collinear
+ text: "if the points (x0, y0), (x1, y1), and (x2, y2) all lie on a single straight line, then the method *must* add the point (x1, y1) to the subpath, and connect that point to the previous point (x0, y0) by a straight line<^>."
+ - id: 2d.path.arcTo.shape
+ text: "The method *must* connect the point (x0, y0) to the start tangent point by a straight line, adding the start tangent point to the subpath, and then must connect the start tangent point to the end tangent point by The Arc, adding the end tangent point to the subpath<^>."
+
+ - id: 2d.path.arc.nonempty
+ text: "If the context has any subpaths, then the method *must* add a straight line from the last point in the subpath to the start point of the arc<^>."
+ - id: 2d.path.arc.draw
+ text: "it *must* draw the arc between the start point of the arc and the end point of the arc, and add the start and end points of the arc to the subpath<^>."
+ - id: 2d.path.arc.zero
+ text: "If the two points are the same, or if the radius is zero<^>, then the arc is defined as being of zero length in both directions."
+ - id: 2d.path.arc.negative
+ previously: [ 2, "anticlockwise" ]
+ text: "Negative values for radius *must* cause the implementation to raise an INDEX_SIZE_ERR exception<^>."
+
+ - id: 2d.path.rect.subpath
+ text: "The rect(x, y, w, h) method *must* create a new subpath containing just the four points (x, y), (x+w, y), (x+w, y+h), (x, y+h), with those four points connected by straight lines<^>"
+ - id: 2d.path.rect.closed
+ text: "The rect(x, y, w, h) method <...> *must* then mark the subpath as closed<^>."
+ - id: 2d.path.rect.newsubpath
+ text: "The rect(x, y, w, h) method <...> *must* then create a new subpath with the point (x, y) as the only point in the subpath<^>."
+
+ - id: 2d.path.fill.basic
+ text: "The fill() method *must* fill all the subpaths of the current path, using fillStyle, and using the non-zero winding number rule<^>."
+ - id: 2d.path.fill.closed
+ text: "Open subpaths *must* be implicitly closed when being filled (without affecting the actual subpaths)<^>."
+ - id: 2d.path.stroke.basic
+ text: "The stroke() method *must* calculate the strokes of all the subpaths of the current path, using the lineWidth, lineCap, lineJoin, and (if appropriate) miterLimit attributes, and then fill the combined stroke area using the strokeStyle attribute<^>."
+ - id: 2d.path.unaffected
+ text: "Paths, when filled or stroked, *must* be painted without affecting the current path<^>"
+ - id: 2d.path.subjected
+ text: "Paths, when filled or stroked, <...> *must* be subject to shadow effects, global alpha, the clipping region, and global composition operators<^>."
+
+ - id: 2d.path.stroke.prune
+ text: "Zero-length line segments *must* be pruned before stroking a path<^>."
+ - id: 2d.path.stroke.empty
+ text: "Empty subpaths *must* be ignored<^>."
+
+ - id: 2d.path.clip.basic
+ text: "The clip() method *must* create a new clipping region by calculating the intersection of the current clipping region and the area described by the current path, using the non-zero winding number rule<^>."
+ - id: 2d.path.clip.closed
+ text: "Open subpaths *must* be implicitly closed when computing the clipping region, without affecting the actual subpaths<^>."
+ - id: 2d.path.clip.initial
+ text: "When the context is initialized, the clipping region *must* be set to the rectangle with the top left corner at (0,0) and the width and height of the coordinate space<^>."
+ - id: 2d.path.isPointInPath
+ text: "The isPointInPath(x, y) method *must* return true if the point given by the x and y coordinates passed to the method, when treated as coordinates in the canvas coordinate space unaffected by the current transformation, is inside the current path as determined by the non-zero winding number rule; and must return false otherwise<^>."
+ - id: 2d.path.isPointInPath.edge
+ text: "The isPointInPath(x, y) method *must* return true if <...>. Points on the path itself are considered to be inside the path<^>."
+ - id: 2d.path.isPointInPath.nonfinite
+ text: "If either of the arguments is infinite or NaN, then the method *must* return false<^>."
+
+ # TODO: Focus management
+
+ - id: 2d.text.font.parse
+ text: "The font IDL attribute, on setting, *must* be parsed the same way as the 'font' property of CSS (but without supporting property-independent style sheet syntax like 'inherit')<^>,"
+ - id: 2d.text.font.lineheight
+ text: "The font IDL attribute, on setting, *must* be parsed <...> with the 'line-height' component forced to 'normal'<^>,"
+ - id: 2d.text.font.fontsize
+ text: "The font IDL attribute, on setting, *must* be parsed <...> with the 'font-size' component converted to CSS pixels<^>,"
+ - id: 2d.text.font.systemfonts
+ text: "The font IDL attribute, on setting, *must* be parsed <...> with system fonts being computed to explicit values<^>."
+ - id: 2d.text.font.invalid
+ text: "If the new value is syntactically incorrect (including using property-independent style sheet syntax like 'inherit' or 'initial'), then it *must* be ignored, without assigning a new font value<^>."
+
+ - id: 2d.text.font.fontface
+ text: "Font names must be interpreted in the context of the canvas element's stylesheets; any fonts embedded using @font-face *must* therefore be available once they are loaded<^>."
+ - id: 2d.text.font.notfullyloaded
+ text: "If a font is referenced before it is fully loaded, then it *must* be treated as if it was an unknown font, falling back to another as described by the relevant CSS specifications<^>."
+ - id: 2d.text.font.get
+ text: "On getting, the font attribute *must* return the serialized form of the current font of the context (with no 'line-height' component)<^>."
+ - id: 2d.text.font.default
+ text: "When the context is created, the font of the context *must* be set to 10px sans-serif<^>."
+ - id: 2d.text.font.size
+ text: "When the 'font-size' component is set to lengths using percentages, 'em' or 'ex' units, or the 'larger' or 'smaller' keywords, these *must* be interpreted relative to the computed value of the 'font-size' property of the corresponding canvas element at the time that the attribute is set<^>."
+ - id: 2d.text.font.weight
+ text: "When the 'font-weight' component is set to the relative values 'bolder' and 'lighter', these *must* be interpreted relative to the computed value of the 'font-weight' property of the corresponding canvas element at the time that the attribute is set<^>."
+ - id: 2d.text.font.undefined
+ text: "If the computed values are undefined for a particular case (e.g. because the canvas element is not in a Document), then the relative keywords *must* be interpreted relative to the normal-weight 10px sans-serif default<^>."
+ - id: 2d.text.align.get
+ text: "The textAlign IDL attribute, on getting, *must* return the current value<^>."
+ - id: 2d.text.align.set
+ text: "On setting, if the value is one of start, end, left, right, or center, then the value *must* be changed to the new value<^>."
+ - id: 2d.text.align.invalid
+ text: "The textAlign IDL attribute, <...> Otherwise, the new value *must* be ignored<^>."
+ - id: 2d.text.align.default
+ text: "When the context is created, the textAlign attribute *must* initially have the value start<^>."
+ - id: 2d.text.baseline.get
+ text: "The textBaseline IDL attribute, on getting, *must* return the current value<^>."
+ - id: 2d.text.baseline.set
+ text: "On setting, if the value is one of top, hanging, middle, alphabetic, ideographic, or bottom, then the value *must* be changed to the new value<^>."
+ - id: 2d.text.baseline.invalid
+ text: "The textBaseline IDL attribute, <...> Otherwise, the new value *must* be ignored<^>."
+ - id: 2d.text.baseline.default
+ text: "When the context is created, the textBaseline attribute *must* initially have the value alphabetic<^>."
+
+ - id: 2d.text.draw
+ text: "The fillText() and strokeText() methods <...> when the methods are called, the user agent *must* run the following steps<^>:"
+ - id: 2d.text.draw.spaces
+ text: "Replace all the space characters in text with U+0020 SPACE characters<^>."
+ - id: 2d.text.draw.direction
+ text: "the 'direction' property of the inline box set to the directionality of the canvas element<^>,"
+ - id: 2d.text.draw.maxwidth
+ text: "If the maxWidth argument was specified and the hypothetical width of the inline box in the hypothetical line box is greater than maxWidth CSS pixels, then change font to have a more condensed font (if one is available or if a reasonably readable one can be synthesized by applying a horizontal scale factor to the font) or a smaller font, and return to the previous step<^>."
+ - id: 2d.text.align.left
+ text: "Let the anchor point's horizontal position be the left edge of the inline box<^>."
+ - id: 2d.text.align.right
+ text: "Let the anchor point's horizontal position be the right edge of the inline box<^>."
+ - id: 2d.text.align.center
+ text: "Let the anchor point's horizontal position be half way between the left and right edges of the inline box<^>."
+
+ - id: 2d.text.baseline.top
+ text: "Let the anchor point's vertical position be the top of the em box of the first available font of the inline box<^>."
+ - id: 2d.text.baseline.hanging
+ text: "Let the anchor point's vertical position be the hanging baseline of the first available font of the inline box<^>."
+ - id: 2d.text.baseline.middle
+ text: "Let the anchor point's vertical position be half way between the bottom and the top of the em box of the first available font of the inline box<^>."
+ - id: 2d.text.baseline.alphabetic
+ text: "Let the anchor point's vertical position be the alphabetic baseline of the first available font of the inline box<^>."
+ - id: 2d.text.baseline.ideographic
+ text: "Let the anchor point's vertical position be the ideographic baseline of the first available font of the inline box<^>."
+ - id: 2d.text.baseline.bottom
+ text: "Let the anchor point's vertical position be the bottom of the em box of the first available font of the inline box<^>."
+
+ - id: 2d.text.draw.fill
+ text: "For fillText() fillStyle must be applied to the glyphs and strokeStyle *must* be ignored<^>."
+ - id: 2d.text.draw.stroke
+ text: "For strokeText() the reverse holds and strokeStyle must be applied to the glyph outlines and fillStyle *must* be ignored<^>."
+ - id: 2d.text.measure.spaces
+ text: "When the method is invoked, the user agent *must* replace all the space characters in text with U+0020 SPACE characters<^>,"
+ - id: 2d.text.measure
+ text: "When the method is invoked, the user agent <...> *must* form a hypothetical infinitely wide CSS line box containing a single inline box containing the text text, with all the properties at their initial values except the 'white-space' property of the inline element set to 'pre' and the 'font' property of the inline element set to the current font of the context as given by the font attribute, and must then return a new TextMetrics object with its width attribute set to the width of that inline box, in CSS pixels<^>."
+
+ - id: 2d.drawImage.defaultdest
+ text: "If not specified, the dw and dh arguments *must* default to the values of sw and sh, interpreted such that one CSS pixel in the image is treated as one unit in the canvas coordinate space<^>."
+ - id: 2d.drawImage.defaultsource
+ text: "If the sx, sy, sw, and sh arguments are omitted, they *must* default to 0, 0, the image's intrinsic width in image pixels, and the image's intrinsic height in image pixels, respectively<^>."
+ - id: 2d.drawImage.IDL
+ text: "void drawImage(in HTMLVideoElement image, in double sx, in double sy, in double sw, in double sh, in double dx, in double dy, in double dw, in double dh);<^>"
+ - id: 2d.drawImage.incomplete.image
+ text: "If the image argument is an HTMLImageElement object that is not fully decodable<^><...> then the implementation *must* return without drawing anything."
+ - id: 2d.drawImage.incomplete.video
+ previously: [ 6, "dw and dh" ]
+ text: "If the image argument is <...> an HTMLVideoElement object whose readyState attribute is either HAVE_NOTHING or HAVE_METADATA<^>, then the implementation *must* return without drawing anything."
+ - id: 2d.drawImage.zerocanvas
+ previously: [ 10, "dw and dh" ]
+ text: "If the image argument is an HTMLCanvasElement object with either a horizontal dimension or a vertical dimension equal to zero, then the implementation *must* raise an INVALID_STATE_ERR exception<^>."
+ - id: 2d.drawImage.zerosource
+ text: "If one of the sw or sh arguments is zero<^>, the implementation *must* raise an INDEX_SIZE_ERR exception."
+ - id: 2d.drawImage.paint
+ text: "When drawImage() is invoked, the region of the image specified by the source rectangle *must* be painted on the region of the canvas specified by the destination rectangle<^>, after applying the current transformation matrix to the points of the destination rectangle."
+ - id: 2d.drawImage.original
+ text: "The original image data of the source image *must* be used, not the image as it is rendered (e.g. width and height attributes on the source element have no effect)<^>."
+ - id: 2d.drawImage.direction
+ text: "The image data *must* be processed in the original direction, even if the dimensions given are negative<^>."
+ - id: 2d.drawImage.self
+ text: "When a canvas is drawn onto itself, the drawing model requires the source to be copied before the image is drawn back onto the canvas, so it is possible to copy parts of a canvas onto overlapping parts of itself<^>."
+ - id: 2d.drawImage.animated.image
+ text: "When the drawImage() method is passed an animated image as its image argument, the user agent *must* use the poster frame of the animation, or, if there is no poster frame, the first frame of the animation<^>."
+ - id: 2d.drawImage.animated.video
+ previously: [ 4, "drawImage" ]
+ text: "When the image argument is an HTMLVideoElement, then the frame at the current playback position *must* be used as the source image<^>,"
+ - id: 2d.drawImage.video.size
+ previously: [ 4, "drawImage" ]
+ text: "When the image argument is an HTMLVideoElement, <...> the source image's dimensions *must* be the intrinsic width and intrinsic height of the media resource (i.e. after any aspect-ratio correction has been applied)<^>."
+ - id: 2d.drawImage.unaffect
+ text: "Images are painted without affecting the current path<^>"
+ - id: 2d.drawImage.subject
+ text: "Images are painted without affecting the current path, and are subject to shadow effects, global alpha, the clipping region, and global composition operators<^>."
+
+
+ - id: 2d.imageData.create2.object
+ text: "When the method is invoked with two arguments sw and sh, it *must* return an ImageData object<^>"
+ - id: 2d.imageData.create2.size
+ text: "When the method is invoked with two arguments sw and sh, it *must* return an ImageData object representing a rectangle with a width in CSS pixels equal to the absolute magnitude of sw and a height in CSS pixels equal to the absolute magnitude of sh<^>."
+ - id: 2d.imageData.create1.object
+ text: "When invoked with a single imagedata argument, it *must* return an ImageData object<^>"
+ - id: 2d.imageData.create1.size
+ text: "When invoked with a single imagedata argument, it *must* return an ImageData object representing a rectangle with the same dimensions as the ImageData object passed as the argument<^>."
+ - id: 2d.imageData.create.initial
+ text: "The ImageData object returned must be filled with transparent black<^>."
+
+ - id: 2d.imageData.get.object
+ text: "The getImageData(sx, sy, sw, sh) method *must* return an ImageData object<^>"
+ - id: 2d.imageData.get.basic
+ text: "The getImageData(sx, sy, sw, sh) method *must* return an ImageData object representing the underlying pixel data for the area of the canvas denoted by the rectangle whose corners are the four points (sx, sy), (sx+sw, sy), (sx+sw, sy+sh), (sx, sy+sh), in canvas coordinate space units<^>."
+ - id: 2d.imageData.get.outside
+ text: "Pixels outside the canvas *must* be returned as transparent black<^>."
+ - id: 2d.imageData.get.premul
+ text: "Pixels *must* be returned as non-premultiplied alpha values<^>."
+
+ - id: 2d.imageData.getcreate.nonfinite
+ text: "If any of the arguments to createImageData() or getImageData() are infinite or NaN<^>, the method *must* instead raise a NOT_SUPPORTED_ERR exception."
+ - id: 2d.imageData.create.null
+ text: "ImageData createImageData(in ImageData imagedata);<^>"
+ - id: 2d.imageData.getcreate.zero
+ text: "If either the sw or sh arguments are zero, the method *must* instead raise an INDEX_SIZE_ERR exception<^>."
+
+ - id: 2d.imageData.initial
+ text: "ImageData objects *must* be initialized so that their width attribute is set to w, the number of physical device pixels per row in the image data, their height attribute is set to h, the number of rows in the image data, and their data attribute is initialized to a CanvasPixelArray object holding the image data<^>."
+ - id: 2d.imageData.one
+ text: "At least one pixel's worth of image data *must* be returned<^>."
+ - id: 2d.pixelarray.order
+ text: "The data *must* be represented in left-to-right order, row by row top to bottom, starting with the top left, with each pixel's red, green, blue, and alpha components being given in that order for each pixel<^>."
+ - id: 2d.pixelarray.range
+ text: "Each component of each device pixel represented in this array *must* be in the range 0..255, representing the 8 bit value for that component<^>."
+ - id: 2d.pixelarray.indexes
+ text: "The components *must* be assigned consecutive indices starting with 0 for the top left pixel's red component<^>."
+ - id: 2d.pixelarray.length
+ text: "The length attribute of a CanvasPixelArray object *must* return this number<^>."
+ - id: 2d.pixelarray.retrieve
+ text: "To determine the value of an indexed property index, the user agent *must* return the value of the indexth component in the array<^>."
+ - id: 2d.pixelarray.modify
+ text: "To set the value of an existing indexed property index to value value, the value of the indexth component in the array *must* be set to value<^>."
+
+ - id: 2d.imageData.put.nonfinite
+ text: "If any of the arguments to the method are infinite or NaN, the method *must* raise a NOT_SUPPORTED_ERR exception<^>."
+ - id: 2d.imageData.put.wrongtype
+ text: "void putImageData(in ImageData imagedata, in double dx, in double dy);<...>void putImageData(in ImageData imagedata, in double dx, in double dy, in double dirtyX, in double dirtyY, in double dirtyWidth, in double dirtyHeight);<^>"
+ - id: 2d.imageData.put.3arg
+ text: "When the last four arguments are omitted, they *must* be assumed to have the values 0, 0, the width member of the imagedata structure, and the height member of the imagedata structure, respectively<^>."
+ - id: 2d.imageData.put.normal
+ text: "When invoked with arguments that do not, per the last few paragraphs, cause an exception to be raised, the putImageData() method *must* act as follows<^>:"
+
+ - id: 2d.imageData.unchanged
+ text: "the following *must* result in no visible changes to the rendering<^>:"
+ - id: 2d.imageData.createround
+ text: "...*must* return ImageData objects with the same dimensions, for any value of w and h<^>."
+ - id: 2d.imageData.unaffected
+ text: "The current path, transformation matrix, shadow attributes, global alpha, the clipping region, and global composition operator *must* not affect the getImageData() and putImageData() methods<^>."
+
+ - id: 2d.drawingmodel
+ text: "When a shape or image is painted, user agents *must* follow these steps, in the order given (or act as if they do)<^>:"
+
+ - id: 2d.colorspace.correction
+ text: "The canvas APIs *must* perform color correction at only two points: when rendering images with their own gamma correction and color space information onto the canvas, to convert the image to the color space used by the canvas (e.g. using the 2D Context's drawImage() method with an HTMLImageElement object)<^>,"
+ - id: 2d.colorspace.toDataURL.info
+ text: "The toDataURL() method *must* not include color space information in the resource returned<^>."
+ - id: 2d.colorspace.toDataURL.equal
+ text: "Where the output format allows it, the color of pixels in resources created by toDataURL() *must* match those returned by the getImageData() method<^>."
+ - id: 2d.colorspace.match
+ text: "In user agents that support CSS, the color space used by a canvas element *must* match the color space used for processing any colors for that element in CSS<^>."
+ - id: 2d.colorspace.img.equal
+ text: "The gamma correction and color space information of images *must* be handled in such a way that an image rendered directly using an img element would use the same colors as one painted on a canvas element that is then itself rendered<^>."
+ - id: 2d.colorspace.img.noinfo
+ text: "Furthermore, the rendering of images that have no color correction information (such as those returned by the toDataURL() method) *must* be rendered with no color correction<^>."
+
+ - id: security.start
+ text: "All canvas elements *must* start with their origin-clean set to true<^>."
+ - id: security.drawImage.image
+ keyword: must
+ text: "The element's 2D context's drawImage() method is called with an HTMLImageElement or an HTMLVideoElement whose origin is not the same as that of the Document object that owns the canvas element<^>."
+ - id: security.drawImage.canvas
+ keyword: must
+ text: "The element's 2D context's drawImage() method is called with an HTMLCanvasElement whose origin-clean flag is false<^>."
+ - id: security.fillStyle.image
+ keyword: must
+ text: "The element's 2D context's fillStyle attribute is set to a CanvasPattern object that was created from an HTMLImageElement<^> or an HTMLVideoElement whose origin was not the same as that of the Document object that owns the canvas element when the pattern was created."
+ - id: security.fillStyle.video
+ keyword: must
+ text: "The element's 2D context's fillStyle attribute is set to a CanvasPattern object that was created from an HTMLImageElement or an HTMLVideoElement<^> whose origin was not the same as that of the Document object that owns the canvas element when the pattern was created."
+ - id: security.fillStyle.canvas
+ keyword: must
+ text: "The element's 2D context's fillStyle attribute is set to a CanvasPattern object that was created from an HTMLCanvasElement whose origin-clean flag was false when the pattern was created<^>."
+ - id: security.strokeStyle.image
+ keyword: must
+ text: "The element's 2D context's strokeStyle attribute is set to a CanvasPattern object that was created from an HTMLImageElement<^> or an HTMLVideoElement whose origin was not the same as that of the Document object that owns the canvas element when the pattern was created."
+ - id: security.strokeStyle.video
+ keyword: must
+ text: "The element's 2D context's strokeStyle attribute is set to a CanvasPattern object that was created from an HTMLImageElement or an HTMLVideoElement<^> whose origin was not the same as that of the Document object that owns the canvas element when the pattern was created."
+ - id: security.strokeStyle.canvas
+ keyword: must
+ text: "The element's 2D context's strokeStyle attribute is set to a CanvasPattern object that was created from an HTMLCanvasElement whose origin-clean flag was false when the pattern was created<^>."
+ - id: security.toDataURL
+ text: "Whenever the toDataURL() method of a canvas element whose origin-clean flag is set to false is called, the method *must* raise a SECURITY_ERR exception<^>."
+ - id: security.getImageData
+ text: "Whenever the getImageData() method of the 2D context of a canvas element whose origin-clean flag is set to false is called with otherwise correct arguments, the method *must* raise a SECURITY_ERR exception<^>."
diff --git a/tests/wpt/web-platform-tests/2dcontext/tools/specextract.py b/tests/wpt/web-platform-tests/2dcontext/tools/specextract.py
new file mode 100644
index 00000000000..679bf10e285
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/tools/specextract.py
@@ -0,0 +1,57 @@
+import html5lib
+import html5lib.treebuilders.dom
+
+# Expected use:
+# curl --compressed http://www.whatwg.org/specs/web-apps/current-work/ >current-work
+# python specextract.py
+#
+# Generates current-work-canvas.xhtml, for use by gentest.py to create the annotated spec document
+
+def extract():
+ parser = html5lib.html5parser.HTMLParser(tree=html5lib.treebuilders.dom.TreeBuilder)
+ doc = parser.parse(open('current-work'), encoding='utf-8')
+
+ head = doc.getElementsByTagName('head')[0]
+ for n in head.childNodes:
+ if n.tagName == 'script':
+ head.removeChild(n)
+
+ header = doc.getElementsByTagName('header')[0]
+ #thecanvas = doc.getElementById('the-canvas') # doesn't work (?!)
+ thecanvas = [ n for n in doc.getElementsByTagName('h4') if n.getAttribute('id') == 'the-canvas-element' ][0]
+
+ keep = [header, thecanvas]
+ node = thecanvas.nextSibling
+ while node.nodeName != 'h4':
+ keep.append(node)
+ node = node.nextSibling
+ p = thecanvas.parentNode
+ for n in p.childNodes[:]:
+ if n not in keep:
+ p.removeChild(n)
+
+ for n in header.childNodes[3:-4]:
+ header.removeChild(n)
+
+ def make_absolute(uri):
+ if uri.startswith('data:'):
+ return uri
+ elif uri[0] == '/':
+ return 'http://www.whatwg.org' + uri
+ else:
+ return 'http://www.whatwg.org/specs/web-apps/current-work/' + uri
+
+ # Fix the stylesheet, icon and image references
+ for e in doc.getElementsByTagName('link'):
+ e.setAttribute('href', make_absolute(e.getAttribute('href')))
+ for img in doc.getElementsByTagName('img'):
+ img.setAttribute('src', make_absolute(img.getAttribute('src')))
+
+ # Convert to XHTML, because it's quicker to re-parse than HTML5
+ doc.documentElement.setAttribute('xmlns', 'http://www.w3.org/1999/xhtml')
+ doc.documentElement.setAttribute('xml:lang', doc.documentElement.getAttribute('lang'))
+ doc.removeChild(doc.firstChild) # remove the DOCTYPE
+
+ open('current-work-canvas.xhtml', 'w').write(doc.toxml(encoding = 'UTF-8'))
+
+extract()
diff --git a/tests/wpt/web-platform-tests/2dcontext/tools/templates.yaml b/tests/wpt/web-platform-tests/2dcontext/tools/templates.yaml
new file mode 100644
index 00000000000..8c8e8fda708
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/tools/templates.yaml
@@ -0,0 +1,378 @@
+# Copyright (c) 2010 Philip Taylor
+# Released under the BSD license and W3C Test Suite License: see LICENSE.txt
+
+framed: |
+ <!DOCTYPE html>
+ <title>Canvas test: %(name)s</title>
+ <script src="../tests.js"></script>
+ <link rel="stylesheet" href="../tests.css">
+ %(fonts)s<body class="framed show_output">
+ <h1>
+ <a href="%(name)s.html" target="_parent">%(name_wrapped)s</a>
+ </h1>
+ <p><a href="#" id="show_output" onclick="document.body.className += ' show_output'; return false">[show output]</a>
+ %(fonthack)s<p class="output">Actual output:</p>
+ <canvas id="c" class="output" %(canvas)s>%(fallback)s</canvas>
+ %(expected)s
+ <ul id="d"></ul>
+ <script>
+ _addTest(function(canvas, ctx) {
+
+ %(code)s
+
+ });
+ </script>
+ %(images)s
+
+standalone: |
+ <!DOCTYPE html>
+ <title>Canvas test: %(name)s</title>
+ <script src="../tests.js"></script>
+ <link rel="stylesheet" href="../tests.css">
+ <link rel="prev" href="%(prev)s.html" title="%(prev)s">
+ <link rel="next" href="%(next)s.html" title="%(next)s">
+ %(fonts)s<body class="show_output">
+ <p>
+ <a href="%(prev)s.html" accesskey="p" title="[p] %(prev)s">&lt;</a>
+ <a href="index.html">[index]</a>
+ <a href="%(next)s.html" accesskey="n" title="[n] %(next)s">&gt;</a>
+ <h1>%(backrefs)s</h1>
+ <p class="desc">%(desc)s</p>
+ <div class="refs">References:
+ <ul>
+ %(refs)s
+ </ul>
+ </div>
+ %(notes)s
+ %(fonthack)s<p class="output">Actual output:</p>
+ <canvas id="c" class="output" %(canvas)s>%(fallback)s</canvas>
+ %(expected)s
+ <ul id="d"></ul>
+ <script>
+ _addTest(function(canvas, ctx) {
+
+ %(code)s
+
+ });
+ </script>
+ %(images)s
+
+minimal: |
+ <!DOCTYPE html>
+ <html class="minimal">
+ <title>Canvas test: %(name)s</title>
+ <script src="../tests.js"></script>
+ <link rel="stylesheet" href="../tests.css">
+ <link rel="prev" href="minimal.%(prev)s.html" title="%(prev)s">
+ <link rel="next" href="minimal.%(next)s.html" title="%(next)s">
+ %(fonts)s<body>
+ <p id="passtext">Pass</p>
+ <p id="failtext">Fail</p>
+ <!-- TODO: handle "script did not run" case -->
+ %(fonthack)s<p class="output">These images should be identical:</p>
+ <canvas id="c" class="output" %(canvas)s>%(fallback)s</canvas>
+ %(expected)s
+ <ul id="d"></ul>
+ <script>
+ _addTest(function(canvas, ctx) {
+
+ %(code)s
+
+ });
+ </script>
+ %(images)s
+
+w3c: |
+ <!DOCTYPE html>
+ <!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+ <title>Canvas test: %(name)s</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/canvas-tests.js"></script>
+ <link rel="stylesheet" href="/common/canvas-tests.css">
+ %(fonts)s<body class="show_output">
+
+ <h1>%(name)s</h1>
+ <p class="desc">%(desc)s</p>
+
+ %(notes)s
+ %(fonthack)s<p class="output">Actual output:</p>
+ <canvas id="c" class="output" %(canvas)s>%(fallback)s</canvas>
+ %(expected)s
+ <ul id="d"></ul>
+ <script>
+ var t = async_test("%(escaped_desc)s");
+ _addTest(function(canvas, ctx) {
+
+ %(code)s
+
+ });
+ </script>
+ %(images)s
+
+mochitest: |
+ <!DOCTYPE HTML>
+ <title>%(mochi_name_fn)s</title>
+ %(mochi_desc)s<script src="/MochiKit/MochiKit.js"></script>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" href="/tests/SimpleTest/test.css">
+ %(fonts)s<body><!-- [[[ test_%(mochi_name)s.html ]]] -->
+
+ <p>Canvas test: %(mochi_name)s</p>
+ %(mochi_desc)s%(fonthack)s<canvas id="c" %(canvas)s>%(fallback)s</canvas>
+ <script>
+
+ function %(mochi_name_fn)s() {
+
+ var canvas = document.getElementById('c');
+ var ctx = canvas.getContext('2d');
+
+ %(mochi_code)s
+
+ }
+ </script>
+ %(mochi_images)s
+
+mochitest.isPixel: |
+ function isPixel(ctx, x,y, r,g,b,a, pos, colour, d) {
+ var pixel = ctx.getImageData(x, y, 1, 1);
+ var pr = pixel.data[0],
+ pg = pixel.data[1],
+ pb = pixel.data[2],
+ pa = pixel.data[3];
+ ok(r-d <= pr && pr <= r+d &&
+ g-d <= pg && pg <= g+d &&
+ b-d <= pb && pb <= b+d &&
+ a-d <= pa && pa <= a+d,
+ "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+ }
+
+mochitest.todo_isPixel: |
+ function todo_isPixel(ctx, x,y, r,g,b,a, pos, colour, d) {
+ var pixel = ctx.getImageData(x, y, 1, 1);
+ var pr = pixel.data[0],
+ pg = pixel.data[1],
+ pb = pixel.data[2],
+ pa = pixel.data[3];
+ todo(r-d <= pr && pr <= r+d &&
+ g-d <= pg && pg <= g+d &&
+ b-d <= pb && pb <= b+d &&
+ a-d <= pa && pa <= a+d,
+ "pixel "+pos+" is "+pr+","+pg+","+pb+","+pa+"; expected "+colour+" +/- "+d);
+ }
+
+mochitest.deferTest: |
+ function deferTest() {
+ _deferred = true;
+ }
+
+mochitest.wrapFunction: |
+ function wrapFunction(f) {
+ return function () {
+ f.apply(null, arguments);
+ SimpleTest.finish();
+ }
+ }
+
+mochitest.exception: |
+ var _thrown_outer = false;
+ try {
+
+ %s
+ } catch (e) {
+ _thrown_outer = true;
+ }
+ todo(!_thrown_outer, 'should not throw exception');
+
+mochitest.Makefile: |
+ #
+ # ***** BEGIN LICENSE BLOCK *****
+ # Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ #
+ # The contents of this file are subject to the Mozilla Public License Version
+ # 1.1 (the "License"); you may not use this file except in compliance with
+ # the License. You may obtain a copy of the License at
+ # http://www.mozilla.org/MPL/
+ #
+ # Software distributed under the License is distributed on an "AS IS" basis,
+ # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ # for the specific language governing rights and limitations under the
+ # License.
+ #
+ # The Original Code is mozilla.org code.
+ #
+ # The Initial Developer of the Original Code is
+ # Mozilla Corporation.
+ # Portions created by the Initial Developer are Copyright (C) 2007
+ # the Initial Developer. All Rights Reserved.
+ #
+ # Contributor(s):
+ # Philip Taylor <philip.taylor@cl.cam.ac.uk>
+ #
+ # Alternatively, the contents of this file may be used under the terms of
+ # either of the GNU General Public License Version 2 or later (the "GPL"),
+ # or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ # in which case the provisions of the GPL or the LGPL are applicable instead
+ # of those above. If you wish to allow use of your version of this file only
+ # under the terms of either the GPL or the LGPL, and not to allow others to
+ # use your version of this file under the terms of the MPL, indicate your
+ # decision by deleting the provisions above and replace them with the notice
+ # and other provisions required by the GPL or the LGPL. If you do not delete
+ # the provisions above, a recipient may use your version of this file under
+ # the terms of any one of the MPL, the GPL or the LGPL.
+ #
+ # ***** END LICENSE BLOCK *****
+
+ DEPTH = ../../..
+ topsrcdir = @top_srcdir@
+ srcdir = @srcdir@
+ VPATH = @srcdir@
+ relativesrcdir = content/canvas/test
+
+ include $(DEPTH)/config/autoconf.mk
+ include $(topsrcdir)/config/rules.mk
+
+
+index.frame: |
+ <!DOCTYPE html>
+ <title>Canvas tests - %(category)s.*</title>
+ <link rel="stylesheet" href="../frame.css">
+ <p><a href="index.html">[index]</a>
+ <h1>%(backrefs)s.*</h1>
+ <p>
+
+# FF trunk doesn't do onload in object, so use iframe instead
+#index.frame.item: |-
+# <object width="200" height="220" data="framed.%s.html">(object fallback)</object><!--
+# -->
+index.frame.item: |-
+ <iframe width="200" height="220" src="framed.%s.html">(iframe fallback)</iframe><!--
+ -->
+
+index.w3c.frame: |
+ <!DOCTYPE html>
+ <title>Canvas tests - %(category)s.*</title>
+ <link rel="stylesheet" href="/common/canvas-frame.css">
+ <p><a href="index.html">[index]</a>
+ <h1>%(backrefs)s.*</h1>
+ <p>
+
+index.w3c.frame.item: |-
+ <iframe width="320" height="240" src="%s.html">(iframe fallback)</iframe><!--
+ -->
+
+index: |
+ <!DOCTYPE html>
+ <title>Canvas tests - index</title>
+ <link rel="stylesheet" href="../index.css">
+ <script>
+ function expand(obj) {
+ obj.parentNode.className = obj.parentNode.className ? "" : "expand";
+ return false;
+ }
+ </script>
+
+ <h1><code>&lt;canvas&gt;</code> tests</h1>
+
+ <p>Developed by <a href="mailto:excors&#64;gmail.com">Philip Taylor</a>.
+ Last updated %(updated)s.
+
+ <p>Based on the <a
+ href="http://www.whatwg.org/specs/web-apps/current-work/#the-canvas">HTML</a>
+ Draft Standard &mdash; 22 February 2010. See also the <a
+ href="spec.html">annotated specification</a>.
+
+ <p>See <a href="results.html">test results</a> for some browsers.
+ (Generated semi-automatically via the <a
+ href="../reportgenentry.html">report generator</a>.)
+
+ <p>You may want to <a href="../source.tar.bz2">download the source
+ code/data</a> (e.g. to create an offline copy of the tests).
+
+ <h2>Test cases</h2>
+
+ <p>For each test, a green background indicates success, red indicates
+ failure, blue indicates a need to manually confirm the output is as
+ expected.
+
+ <p>The versions in the report generator are the most visually minimalist.
+ The category links below show the actual and expected renderings, and any
+ error messages. The individual test pages have links to relevant parts of
+ the specification and extra notes.
+
+ <p>There may be many inaccuracies: tests that do not notice when part of
+ the output is incorrect; tests that are too intolerant of acceptable
+ renderings differences, or make other unreasonable assumptions; tests that
+ were written for an outdated version of the specification, and tests that
+ are just wrong. Also a number of features are not tested, most notably text
+ rendering. Please contact me (<a
+ href="mailto:excors&#64;gmail.com">email</a>, <a
+ href="http://wiki.whatwg.org/wiki/IRC">IRC</a>, etc) if you find any
+ problems.
+
+index.w3c: |
+ <!DOCTYPE html>
+ <title>Canvas tests - index</title>
+ <link rel="stylesheet" href="/common/canvas-index.css">
+
+ <h1><code>&lt;canvas&gt;</code> tests</h1>
+
+index.category.item: |
+ <li><h3><a href="index.%s.html">%s.*</a></h3><p>%d test%s <a href="#" onclick="return expand(this)">expand</a></p>
+
+index.w3c.category.item: |
+ <li><h3><a href="index.%s.html">%s.*</a></h3><p>%d test%s</p>
+
+reportgen: |
+ <!DOCTYPE html>
+ <title>Canvas tests - report generator</title>
+ <link rel="stylesheet" href="../reportgen.css">
+ <script src="../reportgen.js"></script>
+ <p>This is mainly for my own use, so it is not designed to be user-friendly.
+ If anyone else wants to use it for some reason, just wait
+ until "tests not yet loaded" and "tests not yet completed" get down to zero, then click the
+ pass/fail button for any test it shows where it cannot work out the answer (or use the
+ <kbd>y</kbd>/<kbd>n</kbd> keys to choose for the magenta-highlighted case), then use the
+ buttons at the bottom to collect all the results.
+ <form id="f">
+ <p><label for="loading">Tests not yet loaded:</label> <input id="loading" value="0" readonly>
+ <p><label for="waiting">Tests not yet completed:</label> <input id="waiting" value="0" readonly>
+ <p><button type="button" onclick="showUnfinished()">Show uncompleted tests</button>
+ <button type="button" onclick="showAll()">Show all tests</button>
+ <button type="button" onclick="reloadAll()">Reload test cases serially</button>
+ <!--<button type="button" onclick="avoidFrameLimit()">HACK: work around frame limit</button>
+ <button type="button" onclick="makeObjects()">HACK: s/iframe/object/</button>-->
+ <hr>
+ <p><label for="passed">Detected passes:</label> <input id="passed" value="0" readonly>
+ <p><label for="failed">Detected fails:</label> <input id="failed" value="0" readonly>
+ <hr>
+ <table>
+ <tr>
+ <th>Test name
+ <th>Test case
+ <th>Pass?
+ <th>Fail?
+ <th>Notes
+ <script>
+ createTable( [
+ %(items)s
+ ] );
+ </script>
+ </table>
+ </form>
+ <hr>
+ <form method="post" action="../submitresults.cgi">
+ <button type="button" onclick="document.getElementById('report').value = genreport()">Generate test report</button><br>
+ <textarea name="report" id="report" cols="100" rows="10"></textarea><br>
+ <input type="submit" value="Submit results"> (Submissions will tend to be ignored unless there
+ is a good reason why they won't be, so don't use this form unless there is such a reason.)
+ </form>
+
+results: |
+ <!DOCTYPE html>
+ <title>Canvas tests - results</title>
+ <link rel="stylesheet" href="../results.css">
+ <table>
+ <col id="col1">
+ <tr>
+ <th>Test
diff --git a/tests/wpt/web-platform-tests/2dcontext/tools/tests.yaml b/tests/wpt/web-platform-tests/2dcontext/tools/tests.yaml
new file mode 100644
index 00000000000..4a89836c06f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/tools/tests.yaml
@@ -0,0 +1,1031 @@
+# Copyright (c) 2010 Philip Taylor
+# Released under the BSD license and W3C Test Suite License: see LICENSE.txt
+
+- name: fallback.basic
+ desc: Fallback content is inserted into the DOM
+ testing:
+ - fallback
+ code: |
+ @assert canvas.childNodes.length === 1;
+
+- name: fallback.multiple
+ desc: Fallback content with multiple elements
+ testing:
+ - fallback
+ fallback: '<p class="fallback">FAIL</p><p class="fallback">FAIL</p>'
+ code: |
+ @assert canvas.childNodes.length === 2;
+
+- name: fallback.nested
+ desc: Fallback content containing another canvas (mostly testing parsers)
+ testing:
+ - fallback
+ fallback: '<canvas><p class="fallback">FAIL (fallback content)</p></canvas><p class="fallback">FAIL (fallback content)</p>'
+ code: |
+ @assert canvas.childNodes.length === 2;
+
+- name: type.name
+ desc: HTMLCanvasElement type and toString
+ testing:
+ - canvas.type
+ code: |
+ @assert Object.prototype.toString.call(canvas) === '[object HTMLCanvasElement]';
+
+- name: type.exists
+ desc: HTMLCanvasElement is a property of window
+ notes: &bindings Defined in "Web IDL" (draft)
+ testing:
+ - canvas.type
+ code: |
+ @assert window.HTMLCanvasElement;
+
+- name: type.delete
+ desc: window.HTMLCanvasElement interface object is [[Configurable]]
+ notes: *bindings
+ testing:
+ - canvas.type
+ code: |
+ @assert delete window.HTMLCanvasElement === true;
+ @assert window.HTMLCanvasElement === undefined;
+
+- name: type.prototype
+ desc: window.HTMLCanvasElement has prototype, which is { ReadOnly, DontDelete }. prototype has getContext, which is not
+ notes: *bindings
+ testing:
+ - canvas.type
+ code: |
+ @assert window.HTMLCanvasElement.prototype;
+ @assert window.HTMLCanvasElement.prototype.getContext;
+ window.HTMLCanvasElement.prototype = null;
+ @assert window.HTMLCanvasElement.prototype;
+ delete window.HTMLCanvasElement.prototype;
+ @assert window.HTMLCanvasElement.prototype;
+ window.HTMLCanvasElement.prototype.getContext = 1;
+ @assert window.HTMLCanvasElement.prototype.getContext === 1;
+ delete window.HTMLCanvasElement.prototype.getContext;
+ @assert window.HTMLCanvasElement.prototype.getContext === undefined;
+
+- name: type.replace
+ desc: HTMLCanvasElement methods can be replaced, and the replacement methods used by canvases
+ notes: *bindings
+ testing:
+ - canvas.type
+ code: |
+ window.HTMLCanvasElement.prototype.getContext = function (name) { return 0; };
+ @assert canvas.getContext('2d') === 0;
+
+- name: type.extend
+ desc: HTMLCanvasElement methods can be added, and the new methods used by canvases
+ notes: *bindings
+ testing:
+ - canvas.type
+ code: |
+ window.HTMLCanvasElement.prototype.getZero = function () { return 0; };
+ @assert canvas.getZero() === 0;
+
+
+- name: size.attributes.idl.set.zero
+ desc: Setting width/height IDL attributes to 0
+ testing:
+ - size.width
+ - size.height
+ code: |
+ canvas.width = 0;
+ canvas.height = 0;
+ @assert canvas.width === 0;
+ @assert canvas.height === 0;
+# expected: size 0 0 # can't generate zero-sized PNG
+
+- name: size.attributes.idl
+ desc: Getting/setting width/height IDL attributes
+ testing:
+ - size.width
+ - size.height
+ webidl:
+ - es-unsigned-long
+ code: |
+ canvas.width = "100";
+ canvas.height = "100";
+ @assert canvas.width === 100;
+ @assert canvas.height === 100;
+
+ canvas.width = "+1.5e2";
+ canvas.height = "0x96";
+ @assert canvas.width === 150;
+ @assert canvas.height === 150;
+
+ canvas.width = 200 - Math.pow(2, 32);
+ canvas.height = 200 - Math.pow(2, 32);
+ @assert canvas.width === 200;
+ @assert canvas.height === 200;
+
+ canvas.width = 301.999;
+ canvas.height = 301.001;
+ @assert canvas.width === 301;
+ @assert canvas.height === 301;
+
+ canvas.width = "400x";
+ canvas.height = "foo";
+ @assert canvas.width === 0;
+ @assert canvas.height === 0;
+
+- name: size.attributes.default
+ desc: Default width/height when attributes are missing
+ testing:
+ - size.default
+ - size.missing
+ canvas: ""
+ code: |
+ @assert canvas.width === 300;
+ @assert canvas.height === 150;
+ @assert !canvas.hasAttribute('width');
+ @assert !canvas.hasAttribute('height');
+ expected: size 300 150
+
+- name: size.attributes.reflect.setidl
+ desc: Setting IDL attributes updates IDL and content attributes
+ testing:
+ - size.reflect
+ code: |
+ canvas.width = 120;
+ canvas.height = 60;
+ @assert canvas.getAttribute('width') === '120';
+ @assert canvas.getAttribute('height') === '60';
+ @assert canvas.width === 120;
+ @assert canvas.height === 60;
+ expected: size 120 60
+
+- name: size.attributes.reflect.setidlzero
+ desc: Setting IDL attributes to 0 updates IDL and content attributes
+ testing:
+ - size.reflect
+ code: |
+ canvas.width = 0;
+ canvas.height = 0;
+ @assert canvas.getAttribute('width') === '0';
+ @assert canvas.getAttribute('height') === '0';
+ @assert canvas.width === 0;
+ @assert canvas.height === 0;
+# expected: size 0 0 # can't generate zero-sized PNG
+
+- name: size.attributes.reflect.setcontent
+ desc: Setting content attributes updates IDL and content attributes
+ testing:
+ - size.reflect
+ code: |
+ canvas.setAttribute('width', '120');
+ canvas.setAttribute('height', '60');
+ @assert canvas.getAttribute('width') === '120';
+ @assert canvas.getAttribute('height') === '60';
+ @assert canvas.width === 120;
+ @assert canvas.height === 60;
+ expected: size 120 60
+
+- name: size.attributes.removed
+ desc: Removing content attributes reverts to default size
+ testing:
+ - size.missing
+ canvas: width="120" height="60"
+ code: |
+ @assert canvas.width === 120;
+ canvas.removeAttribute('width');
+ @assert canvas.width === 300;
+ expected: size 300 60
+
+- meta: |
+ cases = [
+ ("zero", "0", 0),
+ ("empty", "", None),
+ ("onlyspace", " ", None),
+ ("space", " 100", 100),
+ ("whitespace", "\n\t\f100", 100),
+ ("plus", "+100", 100),
+ ("minus", "-100", None),
+ ("octal", "0100", 100),
+ ("hex", "0x100", 0),
+ ("exp", "100e1", 100),
+ ("decimal", "100.999", 100),
+ ("percent", "100%", 100),
+ ("em", "100em", 100),
+ ("junk", "#!?", None),
+ ("trailingjunk", "100#!?", 100),
+ ]
+ def gen(name, string, exp, code):
+ testing = ["size.nonnegativeinteger"]
+ if exp is None:
+ testing.append("size.error")
+ code += "@assert canvas.width === 300;\n@assert canvas.height === 150;\n"
+ expected = "size 300 150"
+ else:
+ code += "@assert canvas.width === %s;\n@assert canvas.height === %s;\n" % (exp, exp)
+ expected = "size %s %s" % (exp, exp)
+
+ # With "100%", Opera gets canvas.width = 100 but renders at 100% of the frame width,
+ # so check the CSS display width
+ code += '@assert window.getComputedStyle(canvas, null).getPropertyValue("width") === "%spx";\n' % (exp, )
+
+ code += "@assert canvas.getAttribute('width') === %r;\n" % string
+ code += "@assert canvas.getAttribute('height') === %r;\n" % string
+
+ if exp == 0:
+ expected = None # can't generate zero-sized PNGs for the expected image
+
+ return code, testing, expected
+
+ for name, string, exp in cases:
+ code = ""
+ code, testing, expected = gen(name, string, exp, code)
+ tests.append( {
+ "name": "size.attributes.parse.%s" % name,
+ "desc": "Parsing of non-negative integers",
+ "testing": testing,
+ "canvas": 'width="%s" height="%s"' % (string, string),
+ "code": code,
+ "expected": expected
+ } )
+
+ for name, string, exp in cases:
+ code = "canvas.setAttribute('width', %r);\ncanvas.setAttribute('height', %r);\n" % (string, string)
+ code, testing, expected = gen(name, string, exp, code)
+ tests.append( {
+ "name": "size.attributes.setAttribute.%s" % name,
+ "desc": "Parsing of non-negative integers in setAttribute",
+ "testing": testing,
+ "canvas": 'width="50" height="50"',
+ "code": code,
+ "expected": expected
+ } )
+
+- name: size.attributes.style
+ desc: Canvas size is independent of CSS resizing
+ testing:
+ - size.css
+ canvas: 'width="50" height="30" style="width: 100px; height: 50px"'
+ code: |
+ @assert canvas.width === 50;
+ @assert canvas.height === 30;
+ expected: size 100 50
+
+- name: size.large
+ DISABLED: |
+ "User agents may impose implementation-specific limits on otherwise unconstrained
+ inputs, e.g. to prevent denial of service attacks, to guard against running out of memory,
+ or to work around platform-specific limitations."
+ testing:
+ - size.width
+ - size.height
+ notes: Not sure how reasonable this is, but the spec doesn't say there's an upper limit on the size.
+ code: |
+ var n = 2147483647; // 2^31 - 1, which should be supported by any sensible definition of "long"
+ canvas.width = n;
+ canvas.height = n;
+ @assert canvas.width === n;
+ @assert canvas.height === n;
+# expected: size 2147483647 2147483647 # not a good idea to generate the expected image in this case...
+
+- name: initial.colour
+ desc: Initial state is transparent black
+ testing:
+ - initial.colour
+ notes: |
+ Output should be transparent black (not transparent anything-else), but manual
+ verification can only confirm that it's transparent - it's not possible to make
+ the actual blackness visible.
+ code: |
+ @assert pixel 20,20 == 0,0,0,0;
+ expected: size 100 50 # transparent
+
+- name: initial.reset.different
+ desc: Changing size resets canvas to transparent black
+ testing:
+ - initial.reset
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 50, 50);
+ @assert pixel 20,20 == 255,0,0,255;
+ canvas.width = 50;
+ @assert pixel 20,20 == 0,0,0,0;
+ expected: size 50 50 # transparent
+
+- name: initial.reset.same
+ desc: Setting size (not changing the value) resets canvas to transparent black
+ testing:
+ - initial.reset
+ code: |
+ canvas.width = 100;
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 50, 50);
+ @assert pixel 20,20 == 255,0,0,255;
+ canvas.width = 100;
+ @assert pixel 20,20 == 0,0,0,0;
+ expected: size 100 50 # transparent
+
+- name: initial.reset.path
+ desc: Resetting the canvas state resets the current path
+ testing:
+ - initial.reset
+ code: |
+ canvas.width = 100;
+ ctx.rect(0, 0, 100, 50);
+ canvas.width = 100;
+ ctx.fillStyle = '#f00';
+ ctx.fill();
+ @assert pixel 20,20 == 0,0,0,0;
+ expected: size 100 50 # transparent
+
+- name: initial.reset.clip
+ desc: Resetting the canvas state resets the current clip region
+ testing:
+ - initial.reset
+ code: |
+ canvas.width = 100;
+ ctx.rect(0, 0, 1, 1);
+ ctx.clip();
+ canvas.width = 100;
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ @assert pixel 20,20 == 0,255,0,255;
+ expected: green
+
+- name: initial.reset.transform
+ desc: Resetting the canvas state resets the current transformation matrix
+ testing:
+ - initial.reset
+ code: |
+ canvas.width = 100;
+ ctx.scale(0.1, 0.1);
+ canvas.width = 100;
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ @assert pixel 20,20 == 0,255,0,255;
+ expected: green
+
+- name: initial.reset.gradient
+ desc: Resetting the canvas state does not invalidate any existing gradients
+ testing:
+ - initial.reset
+ code: |
+ canvas.width = 50;
+ var g = ctx.createLinearGradient(0, 0, 100, 0);
+ g.addColorStop(0, '#0f0');
+ g.addColorStop(1, '#0f0');
+ canvas.width = 100;
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = g;
+ ctx.fillRect(0, 0, 100, 50);
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: initial.reset.pattern
+ desc: Resetting the canvas state does not invalidate any existing patterns
+ testing:
+ - initial.reset
+ code: |
+ canvas.width = 30;
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 30, 50);
+ var p = ctx.createPattern(canvas, 'repeat-x');
+ canvas.width = 100;
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = p;
+ ctx.fillRect(0, 0, 100, 50);
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+# See tests2d.yaml for initial.reset.2dstate
+
+
+- name: context.emptystring
+ desc: getContext with empty string returns null
+ testing:
+ - context.unrecognised
+ code: |
+ @assert canvas.getContext("") === null;
+
+- name: context.unrecognised.badname
+ desc: getContext with unrecognised context name returns null
+ testing:
+ - context.unrecognised
+ code: |
+ @assert canvas.getContext('This is not an implemented context in any real browser') === null;
+
+- name: context.unrecognised.badsuffix
+ desc: Context name "2d" plus a suffix is unrecognised
+ testing:
+ - context.unrecognised
+ code: |
+ @assert canvas.getContext("2d#") === null;
+
+- name: context.unrecognised.nullsuffix
+ desc: Context name "2d" plus a "\0" suffix is unrecognised
+ testing:
+ - context.unrecognised
+ code: |
+ @assert canvas.getContext("2d\0") === null;
+
+- name: context.unrecognised.unicode
+ desc: Context name which kind of looks like "2d" is unrecognised
+ testing:
+ - context.unrecognised
+ code: |
+ @assert canvas.getContext("2\uFF44") === null; // Fullwidth Latin Small Letter D
+
+- name: context.casesensitive
+ desc: Context name "2D" is unrecognised; matching is case sensitive
+ testing:
+ - context.unrecognised
+ code: |
+ @assert canvas.getContext('2D') === null;
+
+- name: context.arguments.missing
+ notes: *bindings
+ testing:
+ - canvas.getContext
+ code: |
+ @assert throws TypeError canvas.getContext(); @moz-todo
+
+
+
+
+- name: toDataURL.default
+ desc: toDataURL with no arguments returns a PNG
+ testing:
+ - toDataURL.noarguments
+ code: |
+ var data = canvas.toDataURL();
+ @assert data =~ /^data:image\/png[;,]/;
+
+- name: toDataURL.png
+ desc: toDataURL with image/png returns a PNG
+ testing:
+ - toDataURL.png
+ - toDataURL.witharguments
+ code: |
+ var data = canvas.toDataURL('image/png');
+ @assert data =~ /^data:image\/png[;,]/;
+
+- name: toDataURL.bogustype
+ desc: toDataURL with a syntactically invalid type returns a PNG
+ testing:
+ - toDataURL.unrecognised
+ code: |
+ var data = canvas.toDataURL('bogus');
+ @assert data =~ /^data:image\/png[;,]/;
+
+- name: toDataURL.unrecognised
+ desc: toDataURL with an unhandled type returns a PNG
+ testing:
+ - toDataURL.unrecognised
+ code: |
+ var data = canvas.toDataURL('image/example');
+ @assert data =~ /^data:image\/png[;,]/;
+
+- name: toDataURL.lowercase.ascii
+ desc: toDataURL type is case-insensitive
+ testing:
+ - toDataURL.lowercase
+ code: |
+ var data = canvas.toDataURL('ImAgE/PnG');
+ @assert data =~ /^data:image\/png[;,]/;
+
+ // If JPEG is supported at all, it must be supported case-insensitively
+ data = canvas.toDataURL('image/jpeg');
+ if (data.match(/^data:image\/jpeg[;,]/)) {
+ data = canvas.toDataURL('ImAgE/JpEg');
+ @assert data =~ /^data:image\/jpeg[;,]/;
+ }
+
+- name: toDataURL.lowercase.unicode
+ desc: toDataURL type is ASCII-case-insensitive
+ testing:
+ - toDataURL.lowercase
+ code: |
+ // Use LATIN CAPITAL LETTER I WITH DOT ABOVE (Unicode lowercase is "i")
+ var data = canvas.toDataURL('\u0130mage/png');
+ @assert data =~ /^data:image\/png[;,]/;
+
+ var data = canvas.toDataURL('\u0130mage/jpeg');
+ @assert data =~ /^data:image\/png[;,]/;
+
+- name: toDataURL.arguments.1
+ desc: toDataURL ignores extra arguments
+ testing:
+ - toDataURL.arguments
+ code: |
+ var data = canvas.toDataURL('image/png', 'another argument that should not raise an exception');
+ @assert data =~ /^data:image\/png[;,]/;
+
+- name: toDataURL.arguments.2
+ desc: toDataURL ignores extra arguments
+ testing:
+ - toDataURL.arguments
+ code: |
+ var data = canvas.toDataURL('image/png', 'another argument that should not raise an exception', 'and another');
+ @assert data =~ /^data:image\/png[;,]/;
+
+- name: toDataURL.arguments.3
+ desc: toDataURL ignores extra arguments
+ testing:
+ - toDataURL.arguments
+ code: |
+ // More arguments that should not raise exceptions
+ var data = canvas.toDataURL('image/png', null, null, null);
+ @assert data =~ /^data:image\/png[;,]/;
+
+- name: toDataURL.nocontext
+ desc: toDataURL works before any context has been got
+ testing:
+ - toDataURL.noarguments
+ code: |
+ var canvas2 = document.createElement('canvas');
+ var data = canvas2.toDataURL();
+ @assert data =~ /^data:image\/png[;,]/;
+
+- name: toDataURL.zerosize
+ desc: toDataURL on zero-size canvas returns 'data:,'
+ testing:
+ - toDataURL.zerosize
+ canvas: width="0" height="0"
+ code: |
+ var data = canvas.toDataURL();
+ @assert data === 'data:,';
+
+- name: toDataURL.zerowidth
+ desc: toDataURL on zero-size canvas returns 'data:,'
+ testing:
+ - toDataURL.zerosize
+ canvas: width="0"
+ code: |
+ var data = canvas.toDataURL();
+ @assert data === 'data:,';
+
+- name: toDataURL.zeroheight
+ desc: toDataURL on zero-size canvas returns 'data:,'
+ testing:
+ - toDataURL.zerosize
+ canvas: height="0"
+ code: |
+ var data = canvas.toDataURL();
+ @assert data === 'data:,';
+
+- name: toDataURL.large1
+ DISABLED: just testing implementation limits, and tends to crash
+ canvas: width="30000" height="1"
+ code: |
+ var data = canvas.toDataURL();
+ @assert data =~ /^data:image\/png[;,]/;
+
+- name: toDataURL.large2
+ DISABLED: just testing implementation limits, and tends to crash
+ canvas: width="32767" height="1"
+ code: |
+ var data = canvas.toDataURL();
+ @assert data =~ /^data:image\/png[;,]/;
+
+- name: toDataURL.large3
+ DISABLED: just testing implementation limits, and tends to crash
+ canvas: width="32768" height="1"
+ code: |
+ var data = canvas.toDataURL();
+ @assert data =~ /^data:image\/png[;,]/;
+
+- name: toDataURL.png.primarycolours
+ desc: toDataURL with PNG handles simple colours correctly
+ testing:
+ - toDataURL.png
+ code: |
+ ctx.fillStyle = '#ff0';
+ ctx.fillRect(0, 0, 25, 40);
+ ctx.fillStyle = '#0ff';
+ ctx.fillRect(25, 0, 50, 40);
+ ctx.fillStyle = '#00f';
+ ctx.fillRect(75, 0, 25, 40);
+ ctx.fillStyle = '#fff';
+ ctx.fillRect(0, 40, 100, 10);
+ var data = canvas.toDataURL();
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ var img = new Image();
+ deferTest();
+ img.onload = t.step_func_done(function ()
+ {
+ ctx.drawImage(img, 0, 0);
+ @assert pixel 12,20 == 255,255,0,255;
+ @assert pixel 50,20 == 0,255,255,255;
+ @assert pixel 87,20 == 0,0,255,255;
+ @assert pixel 50,45 == 255,255,255,255;
+ });
+ img.src = data;
+ expected: |
+ size 100 50
+ cr.set_source_rgb(1, 1, 0)
+ cr.rectangle(0, 0, 25, 40)
+ cr.fill()
+ cr.set_source_rgb(0, 1, 1)
+ cr.rectangle(25, 0, 50, 40)
+ cr.fill()
+ cr.set_source_rgb(0, 0, 1)
+ cr.rectangle(75, 0, 25, 40)
+ cr.fill()
+ cr.set_source_rgb(1, 1, 1)
+ cr.rectangle(0, 40, 100, 10)
+ cr.fill()
+
+- name: toDataURL.png.complexcolours
+ desc: toDataURL with PNG handles non-primary and non-solid colours correctly
+ testing:
+ - toDataURL.png
+ code: |
+ // (These values are chosen to survive relatively alright through being premultiplied)
+ ctx.fillStyle = 'rgba(1, 3, 254, 1)';
+ ctx.fillRect(0, 0, 25, 25);
+ ctx.fillStyle = 'rgba(8, 252, 248, 0.75)';
+ ctx.fillRect(25, 0, 25, 25);
+ ctx.fillStyle = 'rgba(6, 10, 250, 0.502)';
+ ctx.fillRect(50, 0, 25, 25);
+ ctx.fillStyle = 'rgba(12, 16, 244, 0.25)';
+ ctx.fillRect(75, 0, 25, 25);
+ var img = new Image();
+ deferTest();
+ img.onload = t.step_func_done(function ()
+ {
+ ctx.drawImage(img, 0, 25);
+ // (The alpha values do not really survive float->int conversion, so just
+ // do approximate comparisons)
+ @assert pixel 12,40 == 1,3,254,255;
+ @assert pixel 37,40 ==~ 8,252,248,191 +/- 2;
+ @assert pixel 62,40 ==~ 6,10,250,127 +/- 4;
+ @assert pixel 87,40 ==~ 12,16,244,63 +/- 8;
+ });
+ img.src = canvas.toDataURL();
+ expected: |
+ size 100 50
+ cr.set_source_rgba(1/255., 3/255., 254/255., 1)
+ cr.rectangle(0, 0, 25, 50)
+ cr.fill()
+ cr.set_source_rgba(8/255., 252/255., 248/255., 191/255.)
+ cr.rectangle(25, 0, 25, 50)
+ cr.fill()
+ cr.set_source_rgba(6/255., 10/255., 250/255., 127/255.)
+ cr.rectangle(50, 0, 25, 50)
+ cr.fill()
+ cr.set_source_rgba(12/255., 16/255., 244/255., 63/255.)
+ cr.rectangle(75, 0, 25, 50)
+ cr.fill()
+
+- name: toDataURL.jpeg.primarycolours
+ desc: toDataURL with JPEG handles simple colours correctly
+ testing:
+ - toDataURL.jpeg
+ code: |
+ ctx.fillStyle = '#ff0';
+ ctx.fillRect(0, 0, 25, 40);
+ ctx.fillStyle = '#0ff';
+ ctx.fillRect(25, 0, 50, 40);
+ ctx.fillStyle = '#00f';
+ ctx.fillRect(75, 0, 25, 40);
+ ctx.fillStyle = '#fff';
+ ctx.fillRect(0, 40, 100, 10);
+ var data = canvas.toDataURL('image/jpeg'); // it is okay if this returns a PNG instead
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ var img = new Image();
+ deferTest();
+ img.onload = t.step_func_done(function ()
+ {
+ ctx.drawImage(img, 0, 0);
+ @assert pixel 12,20 ==~ 255,255,0,255 +/- 8;
+ @assert pixel 50,20 ==~ 0,255,255,255 +/- 8;
+ @assert pixel 87,20 ==~ 0,0,255,255 +/- 8;
+ @assert pixel 50,45 ==~ 255,255,255,255 +/- 8;
+ });
+ img.src = data;
+ expected: |
+ size 100 50
+ cr.set_source_rgb(1, 1, 0)
+ cr.rectangle(0, 0, 25, 40)
+ cr.fill()
+ cr.set_source_rgb(0, 1, 1)
+ cr.rectangle(25, 0, 50, 40)
+ cr.fill()
+ cr.set_source_rgb(0, 0, 1)
+ cr.rectangle(75, 0, 25, 40)
+ cr.fill()
+ cr.set_source_rgb(1, 1, 1)
+ cr.rectangle(0, 40, 100, 10)
+ cr.fill()
+
+- name: toDataURL.jpeg.alpha
+ desc: toDataURL with JPEG composites onto black
+ testing:
+ - toDataURL.jpeg
+ - toDataURL.noalpha
+ code: |
+ ctx.fillStyle = 'rgba(128, 255, 128, 0.5)';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.globalCompositeOperation = 'destination-over'; // should be ignored by toDataURL
+ var data = canvas.toDataURL('image/jpeg');
+ ctx.globalCompositeOperation = 'source-over';
+ if (!data.match(/^data:image\/jpeg[;,]/)) {
+ @assert true;
+ } else {
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ var img = new Image();
+ deferTest();
+ img.onload = t.step_func_done(function ()
+ {
+ ctx.drawImage(img, 0, 0);
+ @assert pixel 50,25 ==~ 63,127,63,255 +/- 8;
+ });
+ img.src = data;
+ }
+ expected: |
+ size 100 50
+ cr.set_source_rgb(0.25, 0.5, 0.25)
+ cr.rectangle(0, 0, 100, 50)
+ cr.fill()
+
+- name: toDataURL.jpeg.quality.basic
+ desc: toDataURL with JPEG uses the quality parameter
+ testing:
+ - toDataURL.jpeg.quality
+ mozilla: { throws }
+ code: |
+ ctx.fillStyle = '#00f';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0ff';
+ ctx.fillRect(0, 3, 100, 1);
+ // Check for JPEG support first
+ var data = canvas.toDataURL('image/jpeg');
+ if (!data.match(/^data:image\/jpeg[;,]/)) {
+ @assert true;
+ } else {
+ var data_hi = canvas.toDataURL('image/jpeg', 0.99);
+ var data_lo = canvas.toDataURL('image/jpeg', 0.01);
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ deferTest();
+ var img_hi = new Image();
+ img_hi.onload = function ()
+ {
+ var img_lo = new Image();
+ img_lo.onload = t.step_func_done(function ()
+ {
+ ctx.drawImage(img_hi, 0, 0, 50, 50, 0, 0, 50, 50);
+ ctx.drawImage(img_lo, 0, 0, 50, 50, 50, 0, 50, 50);
+ @assert data_hi.length > data_lo.length;
+ @assert pixel 25,25 ==~ 0,0,255,255 +/- 8;
+ @assert pixel 75,25 ==~ 0,0,255,255 +/- 32;
+ });
+ img_lo.src = data_lo;
+ };
+ img_hi.src = data_hi;
+ }
+ expected: |
+ size 100 50
+ cr.set_source_rgb(0, 0, 1)
+ cr.rectangle(0, 0, 100, 50)
+ cr.fill()
+ cr.set_source_rgb(0, 1, 1)
+ cr.rectangle(0, 3, 100, 1)
+ cr.fill()
+
+- name: toDataURL.jpeg.quality.notnumber
+ desc: toDataURL with JPEG handles non-numeric quality parameters
+ testing:
+ - toDataURL.jpeg.nan
+ code: |
+ ctx.fillStyle = '#00f';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0ff';
+ ctx.fillRect(0, 3, 100, 1);
+ // Check for JPEG support first
+ var data = canvas.toDataURL('image/jpeg');
+ if (!data.match(/^data:image\/jpeg[;,]/)) {
+ @assert true;
+ } else {
+ @assert canvas.toDataURL('image/jpeg', 'bogus') === data;
+ @assert canvas.toDataURL('image/jpeg', {}) === data;
+ @assert canvas.toDataURL('image/jpeg', null) === data;
+ @assert canvas.toDataURL('image/jpeg', undefined) === data;
+ @assert canvas.toDataURL('image/jpeg', true) === data;
+ @assert canvas.toDataURL('image/jpeg', '0.01') === data;
+ }
+
+- name: toDataURL.jpeg.quality.outsiderange
+ desc: toDataURL with JPEG handles out-of-range quality parameters
+ testing:
+ - toDataURL.jpeg.range
+ code: |
+ ctx.fillStyle = '#00f';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0ff';
+ ctx.fillRect(0, 3, 100, 1);
+ // Check for JPEG support first
+ var data = canvas.toDataURL('image/jpeg');
+ if (!data.match(/^data:image\/jpeg[;,]/)) {
+ @assert true;
+ } else {
+ @assert canvas.toDataURL('image/jpeg', 10) === data;
+ @assert canvas.toDataURL('image/jpeg', -10) === data;
+ @assert canvas.toDataURL('image/jpeg', 1.01) === data;
+ @assert canvas.toDataURL('image/jpeg', -0.01) === data;
+
+ @assert canvas.toDataURL('image/jpeg', 1).length >= canvas.toDataURL('image/jpeg', 0.9).length;
+ @assert canvas.toDataURL('image/jpeg', 0).length <= canvas.toDataURL('image/jpeg', 0.1).length;
+ }
+
+
+# TODO: work out what security exception should be thrown
+# TODO: test same-origin vs same-host
+
+- name: security.drawImage.image.sub
+ desc: drawImage of different-origin image makes the canvas origin-unclean
+ mozilla: { disabled } # relies on external resources
+ testing:
+ - security.drawImage.image
+ - security.toDataURL
+ - security.getImageData
+ images:
+ - http://{{domains[www2]}}:{{ports[http][0]}}/images/yellow.png
+ code: |
+ ctx.drawImage(document.getElementById('yellow.png'), 0, 0);
+ @assert throws SECURITY_ERR canvas.toDataURL();
+ @assert throws SECURITY_ERR ctx.getImageData(0, 0, 1, 1);
+
+- name: security.drawImage.canvas.sub
+ desc: drawImage of unclean canvas makes the canvas origin-unclean
+ mozilla: { disabled } # relies on external resources
+ testing:
+ - security.drawImage.canvas
+ images:
+ - http://{{domains[www2]}}:{{ports[http][0]}}/images/yellow.png
+ code: |
+ var canvas2 = document.createElement('canvas');
+ canvas2.width = 100;
+ canvas2.height = 50;
+ var ctx2 = canvas2.getContext('2d');
+ ctx2.drawImage(document.getElementById('yellow.png'), 0, 0);
+ ctx.drawImage(canvas2, 0, 0);
+ @assert throws SECURITY_ERR canvas.toDataURL();
+ @assert throws SECURITY_ERR ctx.getImageData(0, 0, 1, 1);
+
+- name: security.pattern.create.sub
+ desc: Creating an unclean pattern does not make the canvas origin-unclean
+ mozilla: { disabled } # relies on external resources
+ testing:
+ - security.start
+ images:
+ - http://{{domains[www]}}:{{ports[http][0]}}/images/yellow.png
+ code: |
+ var p = ctx.createPattern(document.getElementById('yellow.png'), 'repeat');
+ canvas.toDataURL();
+ ctx.getImageData(0, 0, 1, 1);
+ @assert true; // okay if there was no exception
+
+- name: security.pattern.cross.sub
+ desc: Using an unclean pattern makes the target canvas origin-unclean, not the pattern canvas
+ mozilla: { disabled } # relies on external resources
+ testing:
+ - security.start
+ images:
+ - http://{{domains[www2]}}:{{ports[http][0]}}/images/yellow.png
+ code: |
+ var canvas2 = document.createElement('canvas');
+ canvas2.width = 100;
+ canvas2.height = 50;
+ var ctx2 = canvas2.getContext('2d');
+ var p = ctx2.createPattern(document.getElementById('yellow.png'), 'repeat');
+ ctx.fillStyle = p;
+ ctx.fillRect(0, 0, 100, 50);
+ @assert throws SECURITY_ERR canvas.toDataURL();
+ @assert throws SECURITY_ERR ctx.getImageData(0, 0, 1, 1);
+ canvas2.toDataURL();
+ ctx2.getImageData(0, 0, 1, 1);
+
+- name: security.pattern.canvas.timing.sub
+ desc: Pattern safety depends on whether the source was origin-clean, not on whether it still is clean
+ notes: Disagrees with spec on "is" vs "was"
+ mozilla: { disabled } # relies on external resources
+ testing:
+ - security.start
+ - security.fillStyle.canvas
+ images:
+ - http://{{domains[www2]}}:{{ports[http][0]}}/images/yellow.png
+ code: |
+ var canvas2 = document.createElement('canvas');
+ canvas2.width = 100;
+ canvas2.height = 50;
+ var ctx2 = canvas2.getContext('2d');
+ ctx2.fillStyle = '#0f0';
+ ctx2.fillRect(0, 0, 100, 50);
+ var p = ctx.createPattern(canvas2, 'repeat');
+ ctx2.drawImage(document.getElementById('yellow.png'), 0, 0); // make canvas2 origin-unclean
+ ctx.fillStyle = p;
+ ctx.fillRect(0, 0, 100, 50);
+ canvas.toDataURL();
+ ctx.getImageData(0, 0, 1, 1);
+ @assert true; // okay if there was no exception
+
+- name: security.pattern.image.fillStyle.sub
+ desc: Setting fillStyle to a pattern of a different-origin image makes the canvas origin-unclean
+ mozilla: { disabled } # relies on external resources
+ testing:
+ - security.fillStyle.image
+ images:
+ - http://{{domains[www2]}}:{{ports[http][0]}}/images/yellow.png
+ code: |
+ var p = ctx.createPattern(document.getElementById('yellow.png'), 'repeat');
+ ctx.fillStyle = p;
+ ctx.fillStyle = 'red';
+ @assert throws SECURITY_ERR canvas.toDataURL();
+ @assert throws SECURITY_ERR ctx.getImageData(0, 0, 1, 1);
+
+- name: security.pattern.canvas.fillStyle.sub
+ desc: Setting fillStyle to a pattern of an unclean canvas makes the canvas origin-unclean
+ mozilla: { bug: 354127, disabled } # relies on external resources
+ testing:
+ - security.fillStyle.canvas
+ images:
+ - http://{{domains[www2]}}:{{ports[http][0]}}/images/yellow.png
+ code: |
+ var canvas2 = document.createElement('canvas');
+ canvas2.width = 100;
+ canvas2.height = 50;
+ var ctx2 = canvas2.getContext('2d');
+ ctx2.drawImage(document.getElementById('yellow.png'), 0, 0);
+ var p = ctx.createPattern(canvas2, 'repeat');
+ ctx.fillStyle = p;
+ ctx.fillStyle = 'red';
+ @assert throws SECURITY_ERR canvas.toDataURL();
+ @assert throws SECURITY_ERR ctx.getImageData(0, 0, 1, 1);
+
+- name: security.pattern.image.strokeStyle.sub
+ desc: Setting strokeStyle to a pattern of a different-origin image makes the canvas origin-unclean
+ mozilla: { disabled } # relies on external resources
+ testing:
+ - security.strokeStyle.image
+ images:
+ - http://{{domains[www2]}}:{{ports[http][0]}}/images/yellow.png
+ code: |
+ var p = ctx.createPattern(document.getElementById('yellow.png'), 'repeat');
+ ctx.strokeStyle = p;
+ ctx.strokeStyle = 'red';
+ @assert throws SECURITY_ERR canvas.toDataURL();
+ @assert throws SECURITY_ERR ctx.getImageData(0, 0, 1, 1);
+
+- name: security.pattern.canvas.strokeStyle.sub
+ desc: Setting strokeStyle to a pattern of an unclean canvas makes the canvas origin-unclean
+ mozilla: { bug: 354127, disabled } # relies on external resources
+ testing:
+ - security.strokeStyle.canvas
+ images:
+ - http://{{domains[www2]}}:{{ports[http][0]}}/images/yellow.png
+ code: |
+ var canvas2 = document.createElement('canvas');
+ canvas2.width = 100;
+ canvas2.height = 50;
+ var ctx2 = canvas2.getContext('2d');
+ ctx2.drawImage(document.getElementById('yellow.png'), 0, 0);
+ var p = ctx.createPattern(canvas2, 'repeat');
+ ctx.strokeStyle = p;
+ ctx.strokeStyle = 'red';
+ @assert throws SECURITY_ERR canvas.toDataURL();
+ @assert throws SECURITY_ERR ctx.getImageData(0, 0, 1, 1);
+
+- name: security.dataURI
+ desc: 'data: URIs do not count as different-origin, and do not taint the canvas'
+ mozilla: { disabled, bug: 417836 } # can't do "todo" so just disable it
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ var data = canvas.toDataURL();
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ var img = new Image();
+ deferTest();
+ img.onload = t.step_func_done(function ()
+ {
+ ctx.drawImage(img, 0, 0);
+ canvas.toDataURL(); // should be permitted
+ @assert pixel 50,25 == 0,255,0,255;
+ });
+ img.src = data;
+ expected: green
+
+- name: security.reset.sub
+ desc: Resetting the canvas state does not reset the origin-clean flag
+ mozilla: { disabled } # relies on external resources
+ testing:
+ - initial.reset
+ images:
+ - http://{{domains[www2]}}:{{ports[http][0]}}/images/yellow.png
+ code: |
+ canvas.width = 50;
+ ctx.drawImage(document.getElementById('yellow.png'), 0, 0);
+ @assert throws SECURITY_ERR canvas.toDataURL();
+ canvas.width = 100;
+ @assert throws SECURITY_ERR canvas.toDataURL();
diff --git a/tests/wpt/web-platform-tests/2dcontext/tools/tests2d.yaml b/tests/wpt/web-platform-tests/2dcontext/tools/tests2d.yaml
new file mode 100644
index 00000000000..2c8dc3078eb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/tools/tests2d.yaml
@@ -0,0 +1,10030 @@
+# Copyright (c) 2011 Philip Taylor
+# Released under the BSD license and W3C Test Suite License: see LICENSE.txt
+
+- name: 2d.getcontext.exists
+ desc: The 2D context is implemented
+ testing:
+ - context.2d
+ code: |
+ @assert canvas.getContext('2d') !== null;
+
+- name: 2d.getcontext.extraargs
+ desc: The 2D context ignores extra getContext arguments
+ testing:
+ - context.2d.extraargs
+ code: |
+ @assert canvas.getContext('2d', false, {}, [], 1, "2") !== null;
+
+- name: 2d.type.exists
+ desc: The 2D context interface is a property of 'window'
+ notes: &bindings Defined in "Web IDL" (draft)
+ testing:
+ - context.2d.type
+ code: |
+ @assert window.CanvasRenderingContext2D;
+
+- name: 2d.type.delete
+ desc: window.CanvasRenderingContext2D is Configurable
+ notes: *bindings
+ testing:
+ - context.2d.type
+ code: |
+ @assert window.CanvasRenderingContext2D !== undefined;
+ @assert delete window.CanvasRenderingContext2D === true;
+ @assert window.CanvasRenderingContext2D === undefined;
+
+- name: 2d.type.prototype
+ desc: window.CanvasRenderingContext2D.prototype are not [[Writable]] and not [[Configurable]], and its methods are [[Configurable]].
+ notes: *bindings
+ testing:
+ - context.2d.type
+ code: |
+ @assert window.CanvasRenderingContext2D.prototype;
+ @assert window.CanvasRenderingContext2D.prototype.fill;
+ window.CanvasRenderingContext2D.prototype = null;
+ @assert window.CanvasRenderingContext2D.prototype;
+ delete window.CanvasRenderingContext2D.prototype;
+ @assert window.CanvasRenderingContext2D.prototype;
+ window.CanvasRenderingContext2D.prototype.fill = 1;
+ @assert window.CanvasRenderingContext2D.prototype.fill === 1;
+ delete window.CanvasRenderingContext2D.prototype.fill;
+ @assert window.CanvasRenderingContext2D.prototype.fill === undefined;
+
+- name: 2d.type.replace
+ desc: Interface methods can be overridden
+ notes: *bindings
+ testing:
+ - context.2d.type
+ code: |
+ var fillRect = window.CanvasRenderingContext2D.prototype.fillRect;
+ window.CanvasRenderingContext2D.prototype.fillRect = function (x, y, w, h)
+ {
+ this.fillStyle = '#0f0';
+ fillRect.call(this, x, y, w, h);
+ };
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.type.extend
+ desc: Interface methods can be added
+ notes: *bindings
+ testing:
+ - context.2d.type
+ code: |
+ window.CanvasRenderingContext2D.prototype.fillRectGreen = function (x, y, w, h)
+ {
+ this.fillStyle = '#0f0';
+ this.fillRect(x, y, w, h);
+ };
+ ctx.fillStyle = '#f00';
+ ctx.fillRectGreen(0, 0, 100, 50);
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.getcontext.unique
+ desc: getContext('2d') returns the same object
+ testing:
+ - context.unique
+ code: |
+ @assert canvas.getContext('2d') === canvas.getContext('2d');
+
+- name: 2d.getcontext.shared
+ desc: getContext('2d') returns objects which share canvas state
+ testing:
+ - context.unique
+ code: |
+ var ctx2 = canvas.getContext('2d');
+ ctx.fillStyle = '#f00';
+ ctx2.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.voidreturn
+ desc: void methods return undefined
+ notes: *bindings
+ images:
+ - yellow.png
+ code: |
+ @assert ctx.save() === undefined;
+ @assert ctx.restore() === undefined;
+ @assert ctx.scale(1, 1) === undefined;
+ @assert ctx.rotate(0) === undefined;
+ @assert ctx.translate(0, 0) === undefined;
+ if (ctx.transform) { // (avoid spurious failures, since the aim here is not to test that all features are supported)
+ @assert ctx.transform(1, 0, 0, 1, 0, 0) === undefined;
+ }
+ if (ctx.setTransform) {
+ @assert ctx.setTransform(1, 0, 0, 1, 0, 0) === undefined;
+ }
+ @assert ctx.clearRect(0, 0, 0, 0) === undefined;
+ @assert ctx.fillRect(0, 0, 0, 0) === undefined;
+ @assert ctx.strokeRect(0, 0, 0, 0) === undefined;
+ @assert ctx.beginPath() === undefined;
+ @assert ctx.closePath() === undefined;
+ @assert ctx.moveTo(0, 0) === undefined;
+ @assert ctx.lineTo(0, 0) === undefined;
+ @assert ctx.quadraticCurveTo(0, 0, 0, 0) === undefined;
+ @assert ctx.bezierCurveTo(0, 0, 0, 0, 0, 0) === undefined;
+ @assert ctx.arcTo(0, 0, 0, 0, 1) === undefined;
+ @assert ctx.rect(0, 0, 0, 0) === undefined;
+ @assert ctx.arc(0, 0, 1, 0, 0, true) === undefined;
+ @assert ctx.fill() === undefined;
+ @assert ctx.stroke() === undefined;
+ @assert ctx.clip() === undefined;
+ if (ctx.fillText) {
+ @assert ctx.fillText('test', 0, 0) === undefined;
+ @assert ctx.strokeText('test', 0, 0) === undefined;
+ }
+ if (ctx.putImageData) {
+ @assert ctx.putImageData(ctx.getImageData(0, 0, 1, 1), 0, 0) === undefined;
+ }
+ @assert ctx.drawImage(document.getElementById('yellow.png'), 0, 0, 1, 1, 0, 0, 0, 0) === undefined;
+ @assert ctx.drawImage(canvas, 0, 0, 1, 1, 0, 0, 0, 0) === undefined;
+ @assert ctx.createLinearGradient(0, 0, 0, 0).addColorStop(0, 'white') === undefined;
+
+- name: 2d.missingargs
+ desc: Missing arguments cause TypeError
+ code: |
+ @assert throws TypeError ctx.scale();
+ @assert throws TypeError ctx.scale(1);
+ @assert throws TypeError ctx.rotate();
+ @assert throws TypeError ctx.translate();
+ @assert throws TypeError ctx.translate(0);
+ if (ctx.transform) { // (avoid spurious failures, since the aim here is not to test that all features are supported)
+ @assert throws TypeError ctx.transform();
+ @assert throws TypeError ctx.transform(1);
+ @assert throws TypeError ctx.transform(1, 0);
+ @assert throws TypeError ctx.transform(1, 0, 0);
+ @assert throws TypeError ctx.transform(1, 0, 0, 1);
+ @assert throws TypeError ctx.transform(1, 0, 0, 1, 0);
+ }
+ if (ctx.setTransform) {
+ @assert throws TypeError ctx.setTransform();
+ @assert throws TypeError ctx.setTransform(1);
+ @assert throws TypeError ctx.setTransform(1, 0);
+ @assert throws TypeError ctx.setTransform(1, 0, 0);
+ @assert throws TypeError ctx.setTransform(1, 0, 0, 1);
+ @assert throws TypeError ctx.setTransform(1, 0, 0, 1, 0);
+ }
+ @assert throws TypeError ctx.createLinearGradient();
+ @assert throws TypeError ctx.createLinearGradient(0);
+ @assert throws TypeError ctx.createLinearGradient(0, 0);
+ @assert throws TypeError ctx.createLinearGradient(0, 0, 1);
+ @assert throws TypeError ctx.createRadialGradient();
+ @assert throws TypeError ctx.createRadialGradient(0);
+ @assert throws TypeError ctx.createRadialGradient(0, 0);
+ @assert throws TypeError ctx.createRadialGradient(0, 0, 1);
+ @assert throws TypeError ctx.createRadialGradient(0, 0, 1, 0);
+ @assert throws TypeError ctx.createRadialGradient(0, 0, 1, 0, 0);
+ @assert throws TypeError ctx.createPattern(canvas);
+ @assert throws TypeError ctx.clearRect();
+ @assert throws TypeError ctx.clearRect(0);
+ @assert throws TypeError ctx.clearRect(0, 0);
+ @assert throws TypeError ctx.clearRect(0, 0, 0);
+ @assert throws TypeError ctx.fillRect();
+ @assert throws TypeError ctx.fillRect(0);
+ @assert throws TypeError ctx.fillRect(0, 0);
+ @assert throws TypeError ctx.fillRect(0, 0, 0);
+ @assert throws TypeError ctx.strokeRect();
+ @assert throws TypeError ctx.strokeRect(0);
+ @assert throws TypeError ctx.strokeRect(0, 0);
+ @assert throws TypeError ctx.strokeRect(0, 0, 0);
+ @assert throws TypeError ctx.moveTo();
+ @assert throws TypeError ctx.moveTo(0);
+ @assert throws TypeError ctx.lineTo();
+ @assert throws TypeError ctx.lineTo(0);
+ @assert throws TypeError ctx.quadraticCurveTo();
+ @assert throws TypeError ctx.quadraticCurveTo(0);
+ @assert throws TypeError ctx.quadraticCurveTo(0, 0);
+ @assert throws TypeError ctx.quadraticCurveTo(0, 0, 0);
+ @assert throws TypeError ctx.bezierCurveTo();
+ @assert throws TypeError ctx.bezierCurveTo(0);
+ @assert throws TypeError ctx.bezierCurveTo(0, 0);
+ @assert throws TypeError ctx.bezierCurveTo(0, 0, 0);
+ @assert throws TypeError ctx.bezierCurveTo(0, 0, 0, 0);
+ @assert throws TypeError ctx.bezierCurveTo(0, 0, 0, 0, 0);
+ @assert throws TypeError ctx.arcTo();
+ @assert throws TypeError ctx.arcTo(0);
+ @assert throws TypeError ctx.arcTo(0, 0);
+ @assert throws TypeError ctx.arcTo(0, 0, 0);
+ @assert throws TypeError ctx.arcTo(0, 0, 0, 0);
+ @assert throws TypeError ctx.rect();
+ @assert throws TypeError ctx.rect(0);
+ @assert throws TypeError ctx.rect(0, 0);
+ @assert throws TypeError ctx.rect(0, 0, 0);
+ @assert throws TypeError ctx.arc();
+ @assert throws TypeError ctx.arc(0);
+ @assert throws TypeError ctx.arc(0, 0);
+ @assert throws TypeError ctx.arc(0, 0, 1);
+ @assert throws TypeError ctx.arc(0, 0, 1, 0);
+ // (6th argument to arc is optional)
+ if (ctx.isPointInPath) {
+ @assert throws TypeError ctx.isPointInPath();
+ @assert throws TypeError ctx.isPointInPath(0);
+ }
+ if (ctx.drawFocusRing) {
+ @assert throws TypeError ctx.drawFocusRing();
+ @assert throws TypeError ctx.drawFocusRing(canvas);
+ @assert throws TypeError ctx.drawFocusRing(canvas, 0);
+ }
+ if (ctx.fillText) {
+ @assert throws TypeError ctx.fillText();
+ @assert throws TypeError ctx.fillText('test');
+ @assert throws TypeError ctx.fillText('test', 0);
+ @assert throws TypeError ctx.strokeText();
+ @assert throws TypeError ctx.strokeText('test');
+ @assert throws TypeError ctx.strokeText('test', 0);
+ @assert throws TypeError ctx.measureText();
+ }
+ @assert throws TypeError ctx.drawImage();
+ @assert throws TypeError ctx.drawImage(canvas);
+ @assert throws TypeError ctx.drawImage(canvas, 0);
+ // TODO: n >= 3 args on drawImage could be either a valid overload,
+ // or too few for another overload, or too many for another
+ // overload - what should happen?
+ if (ctx.createImageData) {
+ @assert throws TypeError ctx.createImageData();
+ @assert throws TypeError ctx.createImageData(1);
+ }
+ if (ctx.getImageData) {
+ @assert throws TypeError ctx.getImageData();
+ @assert throws TypeError ctx.getImageData(0);
+ @assert throws TypeError ctx.getImageData(0, 0);
+ @assert throws TypeError ctx.getImageData(0, 0, 1);
+ }
+ if (ctx.putImageData) {
+ var imgdata = ctx.getImageData(0, 0, 1, 1);
+ @assert throws TypeError ctx.putImageData();
+ @assert throws TypeError ctx.putImageData(imgdata);
+ @assert throws TypeError ctx.putImageData(imgdata, 0);
+ }
+ var g = ctx.createLinearGradient(0, 0, 0, 0);
+ @assert throws TypeError g.addColorStop(); @moz-todo
+ @assert throws TypeError g.addColorStop(0); @moz-todo
+
+- name: 2d.coordinatespace
+ desc: Coordinate space goes from top-left to bottom-right
+ notes: This should not be upside down.
+ manual: We can't tell that getPixelData isn't using the wrong coordinate space too.
+ testing:
+ - 2d.coordinatespace
+ code: |
+ ctx.fillStyle = '#00f';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0ff';
+ ctx.fillRect(0, 0, 50, 25);
+ @assert pixel 25,12 == 0,255,255,255;
+ @assert pixel 75,12 == 0,0,255,255;
+ @assert pixel 25,37 == 0,0,255,255;
+ @assert pixel 75,37 == 0,0,255,255;
+ expected: |
+ size 100 50
+ cr.set_source_rgb(0, 0, 1)
+ cr.rectangle(0, 0, 100, 50)
+ cr.fill()
+ cr.set_source_rgb(0, 1, 1)
+ cr.rectangle(0, 0, 50, 25)
+ cr.fill()
+
+- name: 2d.scaled
+ desc: CSS-scaled canvases get drawn correctly
+ canvas: 'width="50" height="25" style="width: 100px; height: 50px"'
+ manual:
+ code: |
+ ctx.fillStyle = '#00f';
+ ctx.fillRect(0, 0, 50, 25);
+ ctx.fillStyle = '#0ff';
+ ctx.fillRect(0, 0, 25, 10);
+ expected: |
+ size 100 50
+ cr.set_source_rgb(0, 0, 1)
+ cr.rectangle(0, 0, 100, 50)
+ cr.fill()
+ cr.set_source_rgb(0, 1, 1)
+ cr.rectangle(0, 0, 50, 20)
+ cr.fill()
+
+- name: 2d.canvas.reference
+ desc: CanvasRenderingContext2D.canvas refers back to its canvas
+ testing:
+ - 2d.canvas
+ code: |
+ @assert ctx.canvas === canvas;
+
+- name: 2d.canvas.readonly
+ desc: CanvasRenderingContext2D.canvas is readonly
+ testing:
+ - 2d.canvas.attribute
+ code: |
+ var c = document.createElement('canvas');
+ var d = ctx.canvas;
+ @assert c !== d;
+ ctx.canvas = c;
+ @assert ctx.canvas === d;
+
+- meta: |
+ state = [ # some non-default values to test with
+ ('strokeStyle', '"#ff0000"'),
+ ('fillStyle', '"#ff0000"'),
+ ('globalAlpha', 0.5),
+ ('lineWidth', 0.5),
+ ('lineCap', '"round"'),
+ ('lineJoin', '"round"'),
+ ('miterLimit', 0.5),
+ ('shadowOffsetX', 5),
+ ('shadowOffsetY', 5),
+ ('shadowBlur', 5),
+ ('shadowColor', '"#ff0000"'),
+ ('globalCompositeOperation', '"copy"'),
+ ('font', '"25px serif"'),
+ ('textAlign', '"center"'),
+ ('textBaseline', '"bottom"'),
+ ]
+ for key,value in state:
+ tests.append( {
+ 'name': '2d.state.saverestore.%s' % key,
+ 'desc': 'save()/restore() works for %s' % key,
+ 'testing': [ '2d.state.%s' % key ],
+ 'code':
+ """// Test that restore() undoes any modifications
+ var old = ctx.%(key)s;
+ ctx.save();
+ ctx.%(key)s = %(value)s;
+ ctx.restore();
+ @assert ctx.%(key)s === old;
+
+ // Also test that save() doesn't modify the values
+ ctx.%(key)s = %(value)s;
+ old = ctx.%(key)s;
+ // we're not interested in failures caused by get(set(x)) != x (e.g.
+ // from rounding), so compare against 'old' instead of against %(value)s
+ ctx.save();
+ @assert ctx.%(key)s === old;
+ ctx.restore();
+ """ % { 'key':key, 'value':value }
+ } )
+
+ tests.append( {
+ 'name': 'initial.reset.2dstate',
+ 'desc': 'Resetting the canvas state resets 2D state variables',
+ 'testing': [ 'initial.reset' ],
+ 'code':
+ """canvas.width = 100;
+ var default_val;
+ """ + "".join(
+ """
+ default_val = ctx.%(key)s;
+ ctx.%(key)s = %(value)s;
+ canvas.width = 100;
+ @assert ctx.%(key)s === default_val;
+ """ % { 'key':key, 'value':value }
+ for key,value in state),
+ } )
+
+- name: 2d.state.saverestore.transformation
+ desc: save()/restore() affects the current transformation matrix
+ testing:
+ - 2d.state.transformation
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.save();
+ ctx.translate(200, 0);
+ ctx.restore();
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(-200, 0, 100, 50);
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.state.saverestore.clip
+ desc: save()/restore() affects the clipping path
+ testing:
+ - 2d.state.clip
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.save();
+ ctx.rect(0, 0, 1, 1);
+ ctx.clip();
+ ctx.restore();
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.state.saverestore.path
+ desc: save()/restore() does not affect the current path
+ testing:
+ - 2d.state.path
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.save();
+ ctx.rect(0, 0, 100, 50);
+ ctx.restore();
+ ctx.fillStyle = '#0f0';
+ ctx.fill();
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.state.saverestore.bitmap
+ desc: save()/restore() does not affect the current bitmap
+ testing:
+ - 2d.state.bitmap
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.save();
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.restore();
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.state.saverestore.stack
+ desc: save()/restore() can be nested as a stack
+ testing:
+ - 2d.state.save
+ - 2d.state.restore
+ code: |
+ ctx.lineWidth = 1;
+ ctx.save();
+ ctx.lineWidth = 2;
+ ctx.save();
+ ctx.lineWidth = 3;
+ @assert ctx.lineWidth === 3;
+ ctx.restore();
+ @assert ctx.lineWidth === 2;
+ ctx.restore();
+ @assert ctx.lineWidth === 1;
+
+- name: 2d.state.saverestore.stackdepth
+ desc: save()/restore() stack depth is not unreasonably limited
+ testing:
+ - 2d.state.save
+ - 2d.state.restore
+ code: |
+ var limit = 512;
+ for (var i = 1; i < limit; ++i)
+ {
+ ctx.save();
+ ctx.lineWidth = i;
+ }
+ for (var i = limit-1; i > 0; --i)
+ {
+ @assert ctx.lineWidth === i;
+ ctx.restore();
+ }
+
+- name: 2d.state.saverestore.underflow
+ desc: restore() with an empty stack has no effect
+ testing:
+ - 2d.state.restore.underflow
+ code: |
+ for (var i = 0; i < 16; ++i)
+ ctx.restore();
+ ctx.lineWidth = 0.5;
+ ctx.restore();
+ @assert ctx.lineWidth === 0.5;
+
+
+- name: 2d.transformation.order
+ desc: Transformations are applied in the right order
+ testing:
+ - 2d.transformation.order
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.scale(2, 1);
+ ctx.rotate(Math.PI / 2);
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, -50, 50, 50);
+ @assert pixel 75,25 == 0,255,0,255;
+ expected: green
+
+
+- name: 2d.transformation.scale.basic
+ desc: scale() works
+ testing:
+ - 2d.transformation.scale
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.scale(2, 4);
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 50, 12.5);
+ @assert pixel 90,40 == 0,255,0,255;
+ expected: green
+
+- name: 2d.transformation.scale.zero
+ desc: scale() with a scale factor of zero works
+ testing:
+ - 2d.transformation.scale
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.save();
+ ctx.translate(50, 0);
+ ctx.scale(0, 1);
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.restore();
+
+ ctx.save();
+ ctx.translate(0, 25);
+ ctx.scale(1, 0);
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.restore();
+
+ canvas.toDataURL();
+
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.transformation.scale.negative
+ desc: scale() with negative scale factors works
+ testing:
+ - 2d.transformation.scale
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.save();
+ ctx.scale(-1, 1);
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(-50, 0, 50, 50);
+ ctx.restore();
+
+ ctx.save();
+ ctx.scale(1, -1);
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(50, -50, 50, 50);
+ ctx.restore();
+ @assert pixel 25,25 == 0,255,0,255;
+ @assert pixel 75,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.transformation.scale.large
+ desc: scale() with large scale factors works
+ notes: Not really that large at all, but it hits the limits in Firefox.
+ testing:
+ - 2d.transformation.scale
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.scale(1e5, 1e5);
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 1, 1);
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.transformation.scale.nonfinite
+ desc: scale() with Infinity/NaN is ignored
+ testing:
+ - 2d.nonfinite
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.translate(100, 10);
+ @nonfinite ctx.scale(<0.1 Infinity -Infinity NaN>, <0.1 Infinity -Infinity NaN>);
+
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(-100, -10, 100, 50);
+
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.transformation.scale.multiple
+ desc: Multiple scale()s combine
+ testing:
+ - 2d.transformation.scale.multiple
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.scale(Math.sqrt(2), Math.sqrt(2));
+ ctx.scale(Math.sqrt(2), Math.sqrt(2));
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 50, 25);
+ @assert pixel 90,40 == 0,255,0,255;
+ expected: green
+
+
+- name: 2d.transformation.rotate.zero
+ desc: rotate() by 0 does nothing
+ testing:
+ - 2d.transformation.rotate
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.rotate(0);
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.transformation.rotate.radians
+ desc: rotate() uses radians
+ testing:
+ - 2d.transformation.rotate.radians
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.rotate(Math.PI); // should fail obviously if this is 3.1 degrees
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(-100, -50, 100, 50);
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.transformation.rotate.direction
+ desc: rotate() is clockwise
+ testing:
+ - 2d.transformation.rotate.direction
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.rotate(Math.PI / 2);
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, -100, 50, 100);
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.transformation.rotate.wrap
+ desc: rotate() wraps large positive values correctly
+ testing:
+ - 2d.transformation.rotate
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.rotate(Math.PI * (1 + 4096)); // == pi (mod 2*pi)
+ // We need about pi +/- 0.001 in order to get correct-looking results
+ // 32-bit floats can store pi*4097 with precision 2^-10, so that should
+ // be safe enough on reasonable implementations
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(-100, -50, 100, 50);
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 98,2 == 0,255,0,255;
+ @assert pixel 98,47 == 0,255,0,255;
+ expected: green
+
+- name: 2d.transformation.rotate.wrapnegative
+ desc: rotate() wraps large negative values correctly
+ testing:
+ - 2d.transformation.rotate
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.rotate(-Math.PI * (1 + 4096));
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(-100, -50, 100, 50);
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 98,2 == 0,255,0,255;
+ @assert pixel 98,47 == 0,255,0,255;
+ expected: green
+
+- name: 2d.transformation.rotate.nonfinite
+ desc: rotate() with Infinity/NaN is ignored
+ testing:
+ - 2d.nonfinite
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.translate(100, 10);
+ @nonfinite ctx.rotate(<0.1 Infinity -Infinity NaN>);
+
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(-100, -10, 100, 50);
+
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.transformation.translate.basic
+ desc: translate() works
+ testing:
+ - 2d.transformation.translate
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.translate(100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(-100, -50, 100, 50);
+ @assert pixel 90,40 == 0,255,0,255;
+ expected: green
+
+- name: 2d.transformation.translate.nonfinite
+ desc: translate() with Infinity/NaN is ignored
+ testing:
+ - 2d.nonfinite
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.translate(100, 10);
+ @nonfinite ctx.translate(<0.1 Infinity -Infinity NaN>, <0.1 Infinity -Infinity NaN>);
+
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(-100, -10, 100, 50);
+
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+
+- name: 2d.transformation.transform.identity
+ desc: transform() with the identity matrix does nothing
+ testing:
+ - 2d.transformation.transform
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.transform(1,0, 0,1, 0,0);
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.transformation.transform.skewed
+ desc: transform() with skewy matrix transforms correctly
+ testing:
+ - 2d.transformation.transform
+ code: |
+ // Create green with a red square ring inside it
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(20, 10, 60, 30);
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(40, 20, 20, 10);
+
+ // Draw a skewed shape to fill that gap, to make sure it is aligned correctly
+ ctx.transform(1,4, 2,3, 5,6);
+ // Post-transform coordinates:
+ // [[20,10],[80,10],[80,40],[20,40],[20,10],[40,20],[40,30],[60,30],[60,20],[40,20],[20,10]];
+ // Hence pre-transform coordinates:
+ var pts=[[-7.4,11.2],[-43.4,59.2],[-31.4,53.2],[4.6,5.2],[-7.4,11.2],
+ [-15.4,25.2],[-11.4,23.2],[-23.4,39.2],[-27.4,41.2],[-15.4,25.2],
+ [-7.4,11.2]];
+ ctx.beginPath();
+ ctx.moveTo(pts[0][0], pts[0][1]);
+ for (var i = 0; i < pts.length; ++i)
+ ctx.lineTo(pts[i][0], pts[i][1]);
+ ctx.fill();
+ @assert pixel 21,11 == 0,255,0,255;
+ @assert pixel 79,11 == 0,255,0,255;
+ @assert pixel 21,39 == 0,255,0,255;
+ @assert pixel 79,39 == 0,255,0,255;
+ @assert pixel 39,19 == 0,255,0,255;
+ @assert pixel 61,19 == 0,255,0,255;
+ @assert pixel 39,31 == 0,255,0,255;
+ @assert pixel 61,31 == 0,255,0,255;
+ expected: green
+
+- name: 2d.transformation.transform.multiply
+ desc: transform() multiplies the CTM
+ testing:
+ - 2d.transformation.transform.multiply
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.transform(1,2, 3,4, 5,6);
+ ctx.transform(-2,1, 3/2,-1/2, 1,-2);
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.transformation.transform.nonfinite
+ desc: transform() with Infinity/NaN is ignored
+ testing:
+ - 2d.nonfinite
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.translate(100, 10);
+ @nonfinite ctx.transform(<0 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>);
+
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(-100, -10, 100, 50);
+
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+
+- name: 2d.transformation.setTransform.skewed
+ testing:
+ - 2d.transformation.setTransform
+ code: |
+ // Create green with a red square ring inside it
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(20, 10, 60, 30);
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(40, 20, 20, 10);
+
+ // Draw a skewed shape to fill that gap, to make sure it is aligned correctly
+ ctx.setTransform(1,4, 2,3, 5,6);
+ // Post-transform coordinates:
+ // [[20,10],[80,10],[80,40],[20,40],[20,10],[40,20],[40,30],[60,30],[60,20],[40,20],[20,10]];
+ // Hence pre-transform coordinates:
+ var pts=[[-7.4,11.2],[-43.4,59.2],[-31.4,53.2],[4.6,5.2],[-7.4,11.2],
+ [-15.4,25.2],[-11.4,23.2],[-23.4,39.2],[-27.4,41.2],[-15.4,25.2],
+ [-7.4,11.2]];
+ ctx.beginPath();
+ ctx.moveTo(pts[0][0], pts[0][1]);
+ for (var i = 0; i < pts.length; ++i)
+ ctx.lineTo(pts[i][0], pts[i][1]);
+ ctx.fill();
+ @assert pixel 21,11 == 0,255,0,255;
+ @assert pixel 79,11 == 0,255,0,255;
+ @assert pixel 21,39 == 0,255,0,255;
+ @assert pixel 79,39 == 0,255,0,255;
+ @assert pixel 39,19 == 0,255,0,255;
+ @assert pixel 61,19 == 0,255,0,255;
+ @assert pixel 39,31 == 0,255,0,255;
+ @assert pixel 61,31 == 0,255,0,255;
+ expected: green
+
+- name: 2d.transformation.setTransform.multiple
+ testing:
+ - 2d.transformation.setTransform.identity
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.setTransform(1/2,0, 0,1/2, 0,0);
+ ctx.setTransform(2,0, 0,2, 0,0);
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 50, 25);
+ @assert pixel 75,35 == 0,255,0,255;
+ expected: green
+
+- name: 2d.transformation.setTransform.nonfinite
+ desc: setTransform() with Infinity/NaN is ignored
+ testing:
+ - 2d.nonfinite
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.translate(100, 10);
+ @nonfinite ctx.setTransform(<0 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>);
+
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(-100, -10, 100, 50);
+
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+
+- name: 2d.composite.globalAlpha.range
+ testing:
+ - 2d.composite.globalAlpha.range
+ code: |
+ ctx.globalAlpha = 0.5;
+ var a = ctx.globalAlpha; // might not be exactly 0.5, if it is rounded/quantised, so remember for future comparisons
+ ctx.globalAlpha = 1.1;
+ @assert ctx.globalAlpha === a;
+ ctx.globalAlpha = -0.1;
+ @assert ctx.globalAlpha === a;
+ ctx.globalAlpha = 0;
+ @assert ctx.globalAlpha === 0;
+ ctx.globalAlpha = 1;
+ @assert ctx.globalAlpha === 1;
+
+- name: 2d.composite.globalAlpha.invalid
+ testing:
+ - 2d.composite.globalAlpha.range
+ code: |
+ ctx.globalAlpha = 0.5;
+ var a = ctx.globalAlpha; // might not be exactly 0.5, if it is rounded/quantised, so remember for future comparisons
+ ctx.globalAlpha = Infinity;
+ @assert ctx.globalAlpha === a;
+ ctx.globalAlpha = -Infinity;
+ @assert ctx.globalAlpha === a;
+ ctx.globalAlpha = NaN;
+ @assert ctx.globalAlpha === a;
+
+- name: 2d.composite.globalAlpha.default
+ testing:
+ - 2d.composite.globalAlpha.default
+ code: |
+ @assert ctx.globalAlpha === 1.0;
+
+- name: 2d.composite.globalAlpha.fill
+ testing:
+ - 2d.composite.globalAlpha.shape
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.globalAlpha = 0.01; // avoid any potential alpha=0 optimisations
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ @assert pixel 50,25 ==~ 2,253,0,255;
+ expected: green
+
+- name: 2d.composite.globalAlpha.image
+ testing:
+ - 2d.composite.globalAlpha.image
+ images:
+ - red.png
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.globalAlpha = 0.01; // avoid any potential alpha=0 optimisations
+ ctx.drawImage(document.getElementById('red.png'), 0, 0);
+ @assert pixel 50,25 ==~ 2,253,0,255;
+ expected: green
+
+- name: 2d.composite.globalAlpha.canvas
+ testing:
+ - 2d.composite.globalAlpha.image
+ code: |
+ var canvas2 = document.createElement('canvas');
+ canvas2.width = 100;
+ canvas2.height = 50;
+ var ctx2 = canvas2.getContext('2d');
+ ctx2.fillStyle = '#f00';
+ ctx2.fillRect(0, 0, 100, 50);
+
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.globalAlpha = 0.01; // avoid any potential alpha=0 optimisations
+ ctx.drawImage(canvas2, 0, 0);
+ @assert pixel 50,25 ==~ 2,253,0,255;
+ expected: green
+
+- name: 2d.composite.globalAlpha.imagepattern
+ testing:
+ - 2d.composite.globalAlpha.image
+ images:
+ - red.png
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = ctx.createPattern(document.getElementById('red.png'), 'no-repeat');
+ ctx.globalAlpha = 0.01; // avoid any potential alpha=0 optimisations
+ ctx.fillRect(0, 0, 100, 50);
+ @assert pixel 50,25 ==~ 2,253,0,255;
+ expected: green
+
+- name: 2d.composite.globalAlpha.canvaspattern
+ testing:
+ - 2d.composite.globalAlpha.image
+ code: |
+ var canvas2 = document.createElement('canvas');
+ canvas2.width = 100;
+ canvas2.height = 50;
+ var ctx2 = canvas2.getContext('2d');
+ ctx2.fillStyle = '#f00';
+ ctx2.fillRect(0, 0, 100, 50);
+
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = ctx.createPattern(canvas2, 'no-repeat');
+ ctx.globalAlpha = 0.01; // avoid any potential alpha=0 optimisations
+ ctx.fillRect(0, 0, 100, 50);
+ @assert pixel 50,25 ==~ 2,253,0,255;
+ expected: green
+
+
+- meta: |
+ # Composite operation tests
+ # <http://lists.whatwg.org/htdig.cgi/whatwg-whatwg.org/2007-March/010608.html>
+ ops = [
+ # name FA FB
+ ('source-over', '1', '1-aA'),
+ ('destination-over', '1-aB', '1'),
+ ('source-in', 'aB', '0'),
+ ('destination-in', '0', 'aA'),
+ ('source-out', '1-aB', '0'),
+ ('destination-out', '0', '1-aA'),
+ ('source-atop', 'aB', '1-aA'),
+ ('destination-atop', '1-aB', 'aA'),
+ ('xor', '1-aB', '1-aA'),
+ ('copy', '1', '0'),
+ ('lighter', '1', '1'),
+ ]
+
+ # The ones that change the output when src = (0,0,0,0):
+ ops_trans = [ 'source-in', 'destination-in', 'source-out', 'destination-atop', 'copy' ];
+
+ def calc_output((RA, GA, BA, aA), (RB, GB, BB, aB), FA_code, FB_code):
+ rA, gA, bA = RA*aA, GA*aA, BA*aA
+ rB, gB, bB = RB*aB, GB*aB, BB*aB
+
+ FA = eval(FA_code)
+ FB = eval(FB_code)
+
+ rO = rA*FA + rB*FB
+ gO = gA*FA + gB*FB
+ bO = bA*FA + bB*FB
+ aO = aA*FA + aB*FB
+
+ rO = min(255, rO)
+ gO = min(255, gO)
+ bO = min(255, bO)
+ aO = min(1, aO)
+
+ if aO:
+ RO = rO / aO
+ GO = gO / aO
+ BO = bO / aO
+ else: RO = GO = BO = 0
+
+ return (RO, GO, BO, aO)
+
+ def to_test((r,g,b,a)):
+ return '%d,%d,%d,%d' % (round(r), round(g), round(b), round(a*255))
+ def to_cairo((r,g,b,a)):
+ return '%f,%f,%f,%f' % (r/255., g/255., b/255., a)
+
+ for (name, src, dest) in [
+ ('solid', (255, 255, 0, 1.0), (0, 255, 255, 1.0)),
+ ('transparent', (0, 0, 255, 0.75), (0, 255, 0, 0.5)),
+ # catches the atop, xor and lighter bugs in Opera 9.10
+ ]:
+ for op, FA_code, FB_code in ops:
+ expected = calc_output(src, dest, FA_code, FB_code)
+ tests.append( {
+ 'name': '2d.composite.%s.%s' % (name, op),
+ 'testing': [ '2d.composite.%s' % op ],
+ 'code': """
+ ctx.fillStyle = 'rgba%s';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.globalCompositeOperation = '%s';
+ ctx.fillStyle = 'rgba%s';
+ ctx.fillRect(0, 0, 100, 50);
+ @assert pixel 50,25 ==~ %s +/- 5;
+ """ % (dest, op, src, to_test(expected)),
+ 'expected': """size 100 50
+ cr.set_source_rgba(%s)
+ cr.rectangle(0, 0, 100, 50)
+ cr.fill()
+ """ % to_cairo(expected),
+ } )
+
+ for (name, src, dest) in [ ('image', (255, 255, 0, 0.75), (0, 255, 255, 0.5)) ]:
+ for op, FA_code, FB_code in ops:
+ expected = calc_output(src, dest, FA_code, FB_code)
+ tests.append( {
+ 'name': '2d.composite.%s.%s' % (name, op),
+ 'testing': [ '2d.composite.%s' % op ],
+ 'images': [ 'yellow75.png' ],
+ 'code': """
+ ctx.fillStyle = 'rgba%s';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.globalCompositeOperation = '%s';
+ ctx.drawImage(document.getElementById('yellow75.png'), 0, 0);
+ @assert pixel 50,25 ==~ %s +/- 5;
+ """ % (dest, op, to_test(expected)),
+ 'expected': """size 100 50
+ cr.set_source_rgba(%s)
+ cr.rectangle(0, 0, 100, 50)
+ cr.fill()
+ """ % to_cairo(expected),
+ } )
+
+ for (name, src, dest) in [ ('canvas', (255, 255, 0, 0.75), (0, 255, 255, 0.5)) ]:
+ for op, FA_code, FB_code in ops:
+ expected = calc_output(src, dest, FA_code, FB_code)
+ tests.append( {
+ 'name': '2d.composite.%s.%s' % (name, op),
+ 'testing': [ '2d.composite.%s' % op ],
+ 'images': [ 'yellow75.png' ],
+ 'code': """
+ var canvas2 = document.createElement('canvas');
+ canvas2.width = canvas.width;
+ canvas2.height = canvas.height;
+ var ctx2 = canvas2.getContext('2d');
+ ctx2.drawImage(document.getElementById('yellow75.png'), 0, 0);
+ ctx.fillStyle = 'rgba%s';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.globalCompositeOperation = '%s';
+ ctx.drawImage(canvas2, 0, 0);
+ @assert pixel 50,25 ==~ %s +/- 5;
+ """ % (dest, op, to_test(expected)),
+ 'expected': """size 100 50
+ cr.set_source_rgba(%s)
+ cr.rectangle(0, 0, 100, 50)
+ cr.fill()
+ """ % to_cairo(expected),
+ } )
+
+
+ for (name, src, dest) in [ ('uncovered.fill', (0, 0, 255, 0.75), (0, 255, 0, 0.5)) ]:
+ for op, FA_code, FB_code in ops:
+ if op not in ops_trans: continue
+ expected0 = calc_output((0,0,0,0.0), dest, FA_code, FB_code)
+ tests.append( {
+ 'name': '2d.composite.%s.%s' % (name, op),
+ 'desc': 'fill() draws pixels not covered by the source object as (0,0,0,0), and does not leave the pixels unchanged.',
+ 'testing': [ '2d.composite.%s' % op ],
+ 'code': """
+ ctx.fillStyle = 'rgba%s';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.globalCompositeOperation = '%s';
+ ctx.fillStyle = 'rgba%s';
+ ctx.translate(0, 25);
+ ctx.fillRect(0, 50, 100, 50);
+ @assert pixel 50,25 ==~ %s +/- 5;
+ """ % (dest, op, src, to_test(expected0)),
+ 'expected': """size 100 50
+ cr.set_source_rgba(%s)
+ cr.rectangle(0, 0, 100, 50)
+ cr.fill()
+ """ % (to_cairo(expected0)),
+ } )
+
+ for (name, src, dest) in [ ('uncovered.image', (255, 255, 0, 1.0), (0, 255, 255, 0.5)) ]:
+ for op, FA_code, FB_code in ops:
+ if op not in ops_trans: continue
+ expected0 = calc_output((0,0,0,0.0), dest, FA_code, FB_code)
+ tests.append( {
+ 'name': '2d.composite.%s.%s' % (name, op),
+ 'desc': 'drawImage() draws pixels not covered by the source object as (0,0,0,0), and does not leave the pixels unchanged.',
+ 'testing': [ '2d.composite.%s' % op ],
+ 'images': [ 'yellow.png' ],
+ 'code': """
+ ctx.fillStyle = 'rgba%s';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.globalCompositeOperation = '%s';
+ ctx.drawImage(document.getElementById('yellow.png'), 40, 40, 10, 10, 40, 50, 10, 10);
+ @assert pixel 15,15 ==~ %s +/- 5;
+ @assert pixel 50,25 ==~ %s +/- 5;
+ """ % (dest, op, to_test(expected0), to_test(expected0)),
+ 'expected': """size 100 50
+ cr.set_source_rgba(%s)
+ cr.rectangle(0, 0, 100, 50)
+ cr.fill()
+ """ % (to_cairo(expected0)),
+ } )
+
+ for (name, src, dest) in [ ('uncovered.nocontext', (255, 255, 0, 1.0), (0, 255, 255, 0.5)) ]:
+ for op, FA_code, FB_code in ops:
+ if op not in ops_trans: continue
+ expected0 = calc_output((0,0,0,0.0), dest, FA_code, FB_code)
+ tests.append( {
+ 'name': '2d.composite.%s.%s' % (name, op),
+ 'desc': 'drawImage() of a canvas with no context draws pixels as (0,0,0,0), and does not leave the pixels unchanged.',
+ 'testing': [ '2d.composite.%s' % op ],
+ 'code': """
+ ctx.fillStyle = 'rgba%s';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.globalCompositeOperation = '%s';
+ var canvas2 = document.createElement('canvas');
+ ctx.drawImage(canvas2, 0, 0);
+ @assert pixel 50,25 ==~ %s +/- 5;
+ """ % (dest, op, to_test(expected0)),
+ 'expected': """size 100 50
+ cr.set_source_rgba(%s)
+ cr.rectangle(0, 0, 100, 50)
+ cr.fill()
+ """ % (to_cairo(expected0)),
+ } )
+
+ for (name, src, dest) in [ ('uncovered.pattern', (255, 255, 0, 1.0), (0, 255, 255, 0.5)) ]:
+ for op, FA_code, FB_code in ops:
+ if op not in ops_trans: continue
+ expected0 = calc_output((0,0,0,0.0), dest, FA_code, FB_code)
+ tests.append( {
+ 'name': '2d.composite.%s.%s' % (name, op),
+ 'desc': 'Pattern fill() draws pixels not covered by the source object as (0,0,0,0), and does not leave the pixels unchanged.',
+ 'testing': [ '2d.composite.%s' % op ],
+ 'images': [ 'yellow.png' ],
+ 'code': """
+ ctx.fillStyle = 'rgba%s';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.globalCompositeOperation = '%s';
+ ctx.fillStyle = ctx.createPattern(document.getElementById('yellow.png'), 'no-repeat');
+ ctx.fillRect(0, 50, 100, 50);
+ @assert pixel 50,25 ==~ %s +/- 5;
+ """ % (dest, op, to_test(expected0)),
+ 'expected': """size 100 50
+ cr.set_source_rgba(%s)
+ cr.rectangle(0, 0, 100, 50)
+ cr.fill()
+ """ % (to_cairo(expected0)),
+ } )
+
+ for op, FA_code, FB_code in ops:
+ tests.append( {
+ 'name': '2d.composite.clip.%s' % (op),
+ 'desc': 'fill() does not affect pixels outside the clip region.',
+ 'testing': [ '2d.composite.%s' % op ],
+ 'code': """
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.globalCompositeOperation = '%s';
+ ctx.rect(-20, -20, 10, 10);
+ ctx.clip();
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 50, 50);
+ @assert pixel 25,25 == 0,255,0,255;
+ @assert pixel 75,25 == 0,255,0,255;
+ """ % (op),
+ 'expected': 'green'
+ } )
+
+- name: 2d.composite.operation.get
+ testing:
+ - 2d.composite.operation
+ code: |
+ var modes = ['source-atop', 'source-in', 'source-out', 'source-over',
+ 'destination-atop', 'destination-in', 'destination-out', 'destination-over',
+ 'lighter', 'copy', 'xor'];
+ for (var i = 0; i < modes.length; ++i)
+ {
+ ctx.globalCompositeOperation = modes[i];
+ @assert ctx.globalCompositeOperation === modes[i];
+ }
+
+- name: 2d.composite.operation.unrecognised
+ testing:
+ - 2d.composite.operation.unrecognised
+ code: |
+ ctx.globalCompositeOperation = 'xor';
+ ctx.globalCompositeOperation = 'nonexistent';
+ @assert ctx.globalCompositeOperation === 'xor';
+
+- name: 2d.composite.operation.darker
+ testing:
+ - 2d.composite.operation.unrecognised
+ code: |
+ ctx.globalCompositeOperation = 'xor';
+ ctx.globalCompositeOperation = 'darker';
+ @assert ctx.globalCompositeOperation === 'xor';
+
+- name: 2d.composite.operation.over
+ testing:
+ - 2d.composite.operation.unrecognised
+ code: |
+ ctx.globalCompositeOperation = 'xor';
+ ctx.globalCompositeOperation = 'over';
+ @assert ctx.globalCompositeOperation === 'xor';
+
+- name: 2d.composite.operation.clear
+ testing:
+ - 2d.composite.operation.unrecognised
+ code: |
+ ctx.globalCompositeOperation = 'xor';
+ ctx.globalCompositeOperation = 'clear';
+ @assert ctx.globalCompositeOperation === 'xor';
+
+- name: 2d.composite.operation.highlight
+ testing:
+ - 2d.composite.operation.unrecognised
+ code: |
+ ctx.globalCompositeOperation = 'xor';
+ ctx.globalCompositeOperation = 'highlight';
+ @assert ctx.globalCompositeOperation === 'xor';
+
+- name: 2d.composite.operation.nullsuffix
+ testing:
+ - 2d.composite.operation.exact
+ code: |
+ ctx.globalCompositeOperation = 'xor';
+ ctx.globalCompositeOperation = 'source-over\0';
+ @assert ctx.globalCompositeOperation === 'xor';
+
+- name: 2d.composite.operation.casesensitive
+ testing:
+ - 2d.composite.operation.casesensitive
+ code: |
+ ctx.globalCompositeOperation = 'xor';
+ ctx.globalCompositeOperation = 'Source-over';
+ @assert ctx.globalCompositeOperation === 'xor';
+
+- name: 2d.composite.operation.default
+ testing:
+ - 2d.composite.operation.default
+ code: |
+ @assert ctx.globalCompositeOperation === 'source-over';
+
+
+- meta: |
+ # Colour parsing tests
+
+ # Try most of the CSS3 Color <color> values - http://www.w3.org/TR/css3-color/#colorunits
+ big_float = '1' + ('0' * 39)
+ big_double = '1' + ('0' * 310)
+ for name, string, r,g,b,a, notes in [
+ ('html4', 'limE', 0,255,0,255, ""),
+ ('hex3', '#0f0', 0,255,0,255, ""),
+ ('hex6', '#00fF00', 0,255,0,255, ""),
+ ('rgb-num', 'rgb(0,255,0)', 0,255,0,255, ""),
+ ('rgb-clamp-1', 'rgb(-1000, 1000, -1000)', 0,255,0,255, 'Assumes colours are clamped to [0,255].'),
+ ('rgb-clamp-2', 'rgb(-200%, 200%, -200%)', 0,255,0,255, 'Assumes colours are clamped to [0,255].'),
+ ('rgb-clamp-3', 'rgb(-2147483649, 4294967298, -18446744073709551619)', 0,255,0,255, 'Assumes colours are clamped to [0,255].'),
+ ('rgb-clamp-4', 'rgb(-'+big_float+', '+big_float+', -'+big_float+')', 0,255,0,255, 'Assumes colours are clamped to [0,255].'),
+ ('rgb-clamp-5', 'rgb(-'+big_double+', '+big_double+', -'+big_double+')', 0,255,0,255, 'Assumes colours are clamped to [0,255].'),
+ ('rgb-percent', 'rgb(0% ,100% ,0%)', 0,255,0,255, 'CSS3 Color says "The integer value 255 corresponds to 100%". (In particular, it is not 254...)'),
+ ('rgb-eof', 'rgb(0, 255, 0', 0,255,0,255, ""), # see CSS2.1 4.2 "Unexpected end of style sheet"
+ ('rgba-solid-1', 'rgba( 0 , 255 , 0 , 1 )', 0,255,0,255, ""),
+ ('rgba-solid-2', 'rgba( 0 , 255 , 0 , 1.0 )', 0,255,0,255, ""),
+ ('rgba-solid-3', 'rgba( 0 , 255 , 0 , +1 )', 0,255,0,255, ""),
+ ('rgba-solid-4', 'rgba( -0 , 255 , +0 , 1 )', 0,255,0,255, ""),
+ ('rgba-num-1', 'rgba( 0 , 255 , 0 , .499 )', 0,255,0,127, ""),
+ ('rgba-num-2', 'rgba( 0 , 255 , 0 , 0.499 )', 0,255,0,127, ""),
+ ('rgba-percent', 'rgba(0%,100%,0%,0.499)', 0,255,0,127, ""), # 0.499*255 rounds to 127, both down and nearest, so it should be safe
+ ('rgba-clamp-1', 'rgba(0, 255, 0, -2)', 0,0,0,0, ""),
+ ('rgba-clamp-2', 'rgba(0, 255, 0, 2)', 0,255,0,255, ""),
+ ('rgba-eof', 'rgba(0, 255, 0, 1', 0,255,0,255, ""),
+ ('transparent-1', 'transparent', 0,0,0,0, ""),
+ ('transparent-2', 'TrAnSpArEnT', 0,0,0,0, ""),
+ ('hsl-1', 'hsl(120, 100%, 50%)', 0,255,0,255, ""),
+ ('hsl-2', 'hsl( -240 , 100% , 50% )', 0,255,0,255, ""),
+ ('hsl-3', 'hsl(360120, 100%, 50%)', 0,255,0,255, ""),
+ ('hsl-4', 'hsl(-360240, 100%, 50%)', 0,255,0,255, ""),
+ ('hsl-5', 'hsl(120.0, 100.0%, 50.0%)', 0,255,0,255, ""),
+ ('hsl-6', 'hsl(+120, +100%, +50%)', 0,255,0,255, ""),
+ ('hsl-clamp-1', 'hsl(120, 200%, 50%)', 0,255,0,255, ""),
+ ('hsl-clamp-2', 'hsl(120, -200%, 49.9%)', 127,127,127,255, ""),
+ ('hsl-clamp-3', 'hsl(120, 100%, 200%)', 255,255,255,255, ""),
+ ('hsl-clamp-4', 'hsl(120, 100%, -200%)', 0,0,0,255, ""),
+ ('hsla-1', 'hsla(120, 100%, 50%, 0.499)', 0,255,0,127, ""),
+ ('hsla-2', 'hsla( 120.0 , 100.0% , 50.0% , 1 )', 0,255,0,255, ""),
+ ('hsla-clamp-1', 'hsla(120, 200%, 50%, 1)', 0,255,0,255, ""),
+ ('hsla-clamp-2', 'hsla(120, -200%, 49.9%, 1)', 127,127,127,255, ""),
+ ('hsla-clamp-3', 'hsla(120, 100%, 200%, 1)', 255,255,255,255, ""),
+ ('hsla-clamp-4', 'hsla(120, 100%, -200%, 1)', 0,0,0,255, ""),
+ ('hsla-clamp-5', 'hsla(120, 100%, 50%, 2)', 0,255,0,255, ""),
+ ('hsla-clamp-6', 'hsla(120, 100%, 0%, -2)', 0,0,0,0, ""),
+ ('svg-1', 'gray', 128,128,128,255, ""),
+ ('svg-2', 'grey', 128,128,128,255, ""),
+ # currentColor is handled later
+ ]:
+ # TODO: test by retrieving fillStyle, instead of actually drawing?
+ # TODO: test strokeStyle, shadowColor in the same way
+ test = {
+ 'name': '2d.fillStyle.parse.%s' % name,
+ 'testing': [ '2d.colours.parse' ],
+ 'notes': notes,
+ 'code': """
+ ctx.fillStyle = '#f00';
+ ctx.fillStyle = '%s';
+ ctx.fillRect(0, 0, 100, 50);
+ @assert pixel 50,25 == %d,%d,%d,%d;
+ """ % (string, r,g,b,a),
+ 'expected': """size 100 50
+ cr.set_source_rgba(%f, %f, %f, %f)
+ cr.rectangle(0, 0, 100, 50)
+ cr.fill()
+ """ % (r/255., g/255., b/255., a/255.),
+ }
+ tests.append(test)
+
+ # Also test that invalid colours are ignored
+ for name, string in [
+ ('hex1', '#f'),
+ ('hex2', '#f0'),
+ ('hex3', '#g00'),
+ ('hex4', '#ff00'),
+ ('hex5', '#ff000'),
+ ('hex6', '#fg0000'),
+ ('hex7', '#ff0000f'),
+ ('hex8', '#ff0000ff'),
+ ('rgb-1', 'rgb(255.0, 0, 0)'),
+ ('rgb-2', 'rgb(255, 0.0, 0)'),
+ ('rgb-3', 'rgb(255.0, 0, 0,)'),
+ ('rgb-4', 'rgb(100%, 0, 0)'),
+ ('rgb-5', 'rgb(255 0 0)'),
+ ('rgb-6', 'rgb(255, - 1, 0)'),
+ ('rgb-7', 'rgb(255, 0, 0, 1)'),
+ ('rgba-1', 'rgba(255, 0, 0)'),
+ ('rgba-2', 'rgba(255.0, 0, 0, 1)'),
+ ('rgba-3', 'rgba(100%, 0, 0, 1)'),
+ ('rgba-4', 'rgba(255, 0, 0, 100%)'),
+ ('rgba-5', 'rgba(255, 0, 0, 1. 0)'),
+ ('rgba-6', 'rgba(255, 0, 0, 1.)'),
+ ('rgba-7', 'rgba(255, 0, 0, '),
+ ('hsl-1', 'hsl(0%, 100%, 50%)'),
+ ('hsl-2', 'hsl(z, 100%, 50%)'),
+ ('hsl-3', 'hsl(0, 0, 50%)'),
+ ('hsl-4', 'hsl(0, 100%, 0)'),
+ ('hsl-5', 'hsl(0, 100%, 100%, 1)'),
+ ('hsl-6', 'hsl(0, 100.%, 50%)'),
+ ('hsla-1', 'hsla(0%, 100%, 50%, 1)'),
+ ('hsla-2', 'hsla(0, 0, 50%, 1)'),
+ ('name-1', 'darkbrown'),
+ ('name-2', 'firebrick1'),
+ ('name-3', 'red blue'),
+ ('name-4', '"red"'),
+ ('name-5', '"red'),
+ ]:
+ test = {
+ 'name': '2d.fillStyle.parse.invalid.%s' % name,
+ 'testing': [ '2d.colours.parse' ],
+ 'code': """
+ ctx.fillStyle = '#0f0';
+ try { ctx.fillStyle = '%s'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
+ ctx.fillRect(0, 0, 100, 50);
+ @assert pixel 50,25 == 0,255,0,255;
+ """ % string,
+ 'expected': 'green'
+ }
+ tests.append(test)
+
+ # Some can't have positive tests, only negative tests, because we don't know what colour they're meant to be
+ for name, string in [
+ ('system', 'ThreeDDarkShadow'),
+ #('flavor', 'flavor'), # removed from latest CSS3 Color drafts
+ ]:
+ test = {
+ 'name': '2d.fillStyle.parse.%s' % name,
+ 'testing': [ '2d.colours.parse' ],
+ 'code': """
+ ctx.fillStyle = '#f00';
+ ctx.fillStyle = '%s';
+ @assert ctx.fillStyle =~ /^#(?!(FF0000|ff0000|f00)$)/; // test that it's not red
+ """ % (string,),
+ }
+ tests.append(test)
+
+- name: 2d.fillStyle.parse.current.basic
+ desc: currentColor is computed from the canvas element
+ testing:
+ - 2d.colours.parse
+ - 2d.currentColor.onset
+ code: |
+ canvas.setAttribute('style', 'color: #0f0');
+ ctx.fillStyle = '#f00';
+ ctx.fillStyle = 'currentColor';
+ ctx.fillRect(0, 0, 100, 50);
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.fillStyle.parse.current.changed
+ desc: currentColor is computed when the attribute is set, not when it is painted
+ testing:
+ - 2d.colours.parse
+ - 2d.currentColor.onset
+ code: |
+ canvas.setAttribute('style', 'color: #0f0');
+ ctx.fillStyle = '#f00';
+ ctx.fillStyle = 'currentColor';
+ canvas.setAttribute('style', 'color: #f00');
+ ctx.fillRect(0, 0, 100, 50);
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.fillStyle.parse.current.removed
+ desc: currentColor is solid black when the canvas element is not in a document
+ testing:
+ - 2d.colours.parse
+ - 2d.currentColor.outofdoc
+ code: |
+ // Try not to let it undetectably incorrectly pick up opaque-black
+ // from other parts of the document:
+ document.body.parentNode.setAttribute('style', 'color: #f00');
+ document.body.setAttribute('style', 'color: #f00');
+ canvas.setAttribute('style', 'color: #f00');
+
+ var canvas2 = document.createElement('canvas');
+ var ctx2 = canvas2.getContext('2d');
+ ctx2.fillStyle = '#f00';
+ ctx2.fillStyle = 'currentColor';
+ ctx2.fillRect(0, 0, 100, 50);
+ ctx.drawImage(canvas2, 0, 0);
+
+ document.body.parentNode.removeAttribute('style');
+ document.body.removeAttribute('style');
+
+ @assert pixel 50,25 == 0,0,0,255;
+ expected: |
+ size 100 50
+ cr.set_source_rgb(0, 0, 0)
+ cr.rectangle(0, 0, 100, 50)
+ cr.fill()
+
+- name: 2d.fillStyle.invalidstring
+ testing:
+ - 2d.colours.invalidstring
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.fillStyle = 'invalid';
+ ctx.fillRect(0, 0, 100, 50);
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.fillStyle.invalidtype
+ testing:
+ - 2d.colours.invalidtype
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.fillStyle = null;
+ ctx.fillRect(0, 0, 100, 50);
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.fillStyle.get.solid
+ testing:
+ - 2d.colours.getcolour
+ - 2d.serializecolour.solid
+ code: |
+ ctx.fillStyle = '#fa0';
+ @assert ctx.fillStyle === '#ffaa00';
+
+- name: 2d.fillStyle.get.semitransparent
+ testing:
+ - 2d.colours.getcolour
+ - 2d.serializecolour.transparent
+ code: |
+ ctx.fillStyle = 'rgba(255,255,255,0.45)';
+ @assert ctx.fillStyle =~ /^rgba\(255, 255, 255, 0\.4\d+\)$/;
+
+- name: 2d.fillStyle.get.transparent
+ testing:
+ - 2d.colours.getcolour
+ - 2d.serializecolour.transparent
+ code: |
+ ctx.fillStyle = 'rgba(0,0,0,0)';
+ @assert ctx.fillStyle === 'rgba(0, 0, 0, 0)';
+
+- name: 2d.fillStyle.default
+ testing:
+ - 2d.colours.default
+ code: |
+ @assert ctx.fillStyle === '#000000';
+
+- name: 2d.strokeStyle.default
+ testing:
+ - 2d.colours.default
+ code: |
+ @assert ctx.strokeStyle === '#000000';
+
+
+- name: 2d.gradient.object.type
+ desc: window.CanvasGradient exists and has the right properties
+ testing:
+ - 2d.canvasGradient.type
+ notes: *bindings
+ code: |
+ @assert window.CanvasGradient !== undefined;
+ @assert window.CanvasGradient.prototype.addColorStop !== undefined;
+
+- name: 2d.gradient.object.return
+ desc: createLinearGradient() and createRadialGradient() returns objects implementing CanvasGradient
+ testing:
+ - 2d.gradient.linear.return
+ - 2d.gradient.radial.return
+ code: |
+ window.CanvasGradient.prototype.thisImplementsCanvasGradient = true;
+
+ var g1 = ctx.createLinearGradient(0, 0, 100, 0);
+ @assert g1.addColorStop !== undefined;
+ @assert g1.thisImplementsCanvasGradient === true;
+
+ var g2 = ctx.createRadialGradient(0, 0, 10, 0, 0, 20);
+ @assert g2.addColorStop !== undefined;
+ @assert g2.thisImplementsCanvasGradient === true;
+
+- name: 2d.gradient.interpolate.solid
+ testing:
+ - 2d.gradient.interpolate.linear
+ code: |
+ var g = ctx.createLinearGradient(0, 0, 100, 0);
+ g.addColorStop(0, '#0f0');
+ g.addColorStop(1, '#0f0');
+ ctx.fillStyle = g;
+ ctx.fillRect(0, 0, 100, 50);
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.gradient.interpolate.colour
+ testing:
+ - 2d.gradient.interpolate.linear
+ code: |
+ var g = ctx.createLinearGradient(0, 0, 100, 0);
+ g.addColorStop(0, '#ff0');
+ g.addColorStop(1, '#00f');
+ ctx.fillStyle = g;
+ ctx.fillRect(0, 0, 100, 50);
+ @assert pixel 25,25 ==~ 191,191,63,255 +/- 3;
+ @assert pixel 50,25 ==~ 127,127,127,255 +/- 3;
+ @assert pixel 75,25 ==~ 63,63,191,255 +/- 3;
+ expected: |
+ size 100 50
+ g = cairo.LinearGradient(0, 0, 100, 0)
+ g.add_color_stop_rgb(0, 1,1,0)
+ g.add_color_stop_rgb(1, 0,0,1)
+ cr.set_source(g)
+ cr.rectangle(0, 0, 100, 50)
+ cr.fill()
+
+- name: 2d.gradient.interpolate.alpha
+ testing:
+ - 2d.gradient.interpolate.linear
+ code: |
+ ctx.fillStyle = '#ff0';
+ ctx.fillRect(0, 0, 100, 50);
+ var g = ctx.createLinearGradient(0, 0, 100, 0);
+ g.addColorStop(0, 'rgba(0,0,255, 0)');
+ g.addColorStop(1, 'rgba(0,0,255, 1)');
+ ctx.fillStyle = g;
+ ctx.fillRect(0, 0, 100, 50);
+ @assert pixel 25,25 ==~ 191,191,63,255 +/- 3;
+ @assert pixel 50,25 ==~ 127,127,127,255 +/- 3;
+ @assert pixel 75,25 ==~ 63,63,191,255 +/- 3;
+ expected: |
+ size 100 50
+ g = cairo.LinearGradient(0, 0, 100, 0)
+ g.add_color_stop_rgb(0, 1,1,0)
+ g.add_color_stop_rgb(1, 0,0,1)
+ cr.set_source(g)
+ cr.rectangle(0, 0, 100, 50)
+ cr.fill()
+
+- name: 2d.gradient.interpolate.colouralpha
+ testing:
+ - 2d.gradient.interpolate.alpha
+ code: |
+ var g = ctx.createLinearGradient(0, 0, 100, 0);
+ g.addColorStop(0, 'rgba(255,255,0, 0)');
+ g.addColorStop(1, 'rgba(0,0,255, 1)');
+ ctx.fillStyle = g;
+ ctx.fillRect(0, 0, 100, 50);
+ @assert pixel 25,25 ==~ 191,191,63,63 +/- 3;
+ @assert pixel 50,25 ==~ 127,127,127,127 +/- 3;
+ @assert pixel 75,25 ==~ 63,63,191,191 +/- 3;
+ expected: |
+ size 100 50
+ g = cairo.LinearGradient(0, 0, 100, 0)
+ g.add_color_stop_rgba(0, 1,1,0, 0)
+ g.add_color_stop_rgba(1, 0,0,1, 1)
+ cr.set_source(g)
+ cr.rectangle(0, 0, 100, 50)
+ cr.fill()
+
+- name: 2d.gradient.interpolate.outside
+ testing:
+ - 2d.gradient.outside.first
+ - 2d.gradient.outside.last
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ var g = ctx.createLinearGradient(25, 0, 75, 0);
+ g.addColorStop(0.4, '#0f0');
+ g.addColorStop(0.6, '#0f0');
+
+ ctx.fillStyle = g;
+ ctx.fillRect(0, 0, 100, 50);
+ @assert pixel 20,25 ==~ 0,255,0,255;
+ @assert pixel 50,25 ==~ 0,255,0,255;
+ @assert pixel 80,25 ==~ 0,255,0,255;
+ expected: green
+
+- name: 2d.gradient.interpolate.zerosize.fill
+ testing:
+ - 2d.gradient.linear.zerosize
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ var g = ctx.createLinearGradient(50, 25, 50, 25); // zero-length line (undefined direction)
+ g.addColorStop(0, '#f00');
+ g.addColorStop(1, '#f00');
+ ctx.fillStyle = g;
+ ctx.rect(0, 0, 100, 50);
+ ctx.fill();
+ @assert pixel 40,20 == 0,255,0,255;
+ expected: green
+
+- name: 2d.gradient.interpolate.zerosize.stroke
+ testing:
+ - 2d.gradient.linear.zerosize
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ var g = ctx.createLinearGradient(50, 25, 50, 25); // zero-length line (undefined direction)
+ g.addColorStop(0, '#f00');
+ g.addColorStop(1, '#f00');
+ ctx.strokeStyle = g;
+ ctx.rect(20, 20, 60, 10);
+ ctx.stroke();
+ @assert pixel 19,19 == 0,255,0,255;
+ @assert pixel 20,19 == 0,255,0,255;
+ @assert pixel 21,19 == 0,255,0,255;
+ @assert pixel 19,20 == 0,255,0,255;
+ @assert pixel 20,20 == 0,255,0,255;
+ @assert pixel 21,20 == 0,255,0,255;
+ @assert pixel 19,21 == 0,255,0,255;
+ @assert pixel 20,21 == 0,255,0,255;
+ @assert pixel 21,21 == 0,255,0,255;
+ expected: green
+
+- name: 2d.gradient.interpolate.zerosize.fillRect
+ testing:
+ - 2d.gradient.linear.zerosize
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ var g = ctx.createLinearGradient(50, 25, 50, 25); // zero-length line (undefined direction)
+ g.addColorStop(0, '#f00');
+ g.addColorStop(1, '#f00');
+ ctx.fillStyle = g;
+ ctx.fillRect(0, 0, 100, 50);
+ @assert pixel 40,20 == 0,255,0,255; @moz-todo
+ expected: green
+
+- name: 2d.gradient.interpolate.zerosize.strokeRect
+ testing:
+ - 2d.gradient.linear.zerosize
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ var g = ctx.createLinearGradient(50, 25, 50, 25); // zero-length line (undefined direction)
+ g.addColorStop(0, '#f00');
+ g.addColorStop(1, '#f00');
+ ctx.strokeStyle = g;
+ ctx.strokeRect(20, 20, 60, 10);
+ @assert pixel 19,19 == 0,255,0,255;
+ @assert pixel 20,19 == 0,255,0,255;
+ @assert pixel 21,19 == 0,255,0,255;
+ @assert pixel 19,20 == 0,255,0,255;
+ @assert pixel 20,20 == 0,255,0,255;
+ @assert pixel 21,20 == 0,255,0,255;
+ @assert pixel 19,21 == 0,255,0,255;
+ @assert pixel 20,21 == 0,255,0,255;
+ @assert pixel 21,21 == 0,255,0,255;
+ expected: green
+
+- name: 2d.gradient.interpolate.zerosize.fillText
+ testing:
+ - 2d.gradient.linear.zerosize
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ var g = ctx.createLinearGradient(50, 25, 50, 25); // zero-length line (undefined direction)
+ g.addColorStop(0, '#f00');
+ g.addColorStop(1, '#f00');
+ ctx.fillStyle = g;
+ ctx.font = '100px sans-serif';
+ ctx.fillText("AA", 0, 50);
+ _assertGreen(ctx, 100, 50);
+ expected: green
+
+- name: 2d.gradient.interpolate.zerosize.strokeText
+ testing:
+ - 2d.gradient.linear.zerosize
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ var g = ctx.createLinearGradient(50, 25, 50, 25); // zero-length line (undefined direction)
+ g.addColorStop(0, '#f00');
+ g.addColorStop(1, '#f00');
+ ctx.strokeStyle = g;
+ ctx.font = '100px sans-serif';
+ ctx.strokeText("AA", 0, 50);
+ _assertGreen(ctx, 100, 50);
+ expected: green
+
+
+- name: 2d.gradient.interpolate.vertical
+ testing:
+ - 2d.gradient.interpolate.linear
+ code: |
+ var g = ctx.createLinearGradient(0, 0, 0, 50);
+ g.addColorStop(0, '#ff0');
+ g.addColorStop(1, '#00f');
+ ctx.fillStyle = g;
+ ctx.fillRect(0, 0, 100, 50);
+ @assert pixel 50,12 ==~ 191,191,63,255 +/- 10;
+ @assert pixel 50,25 ==~ 127,127,127,255 +/- 5;
+ @assert pixel 50,37 ==~ 63,63,191,255 +/- 10;
+ expected: |
+ size 100 50
+ g = cairo.LinearGradient(0, 0, 0, 50)
+ g.add_color_stop_rgb(0, 1,1,0)
+ g.add_color_stop_rgb(1, 0,0,1)
+ cr.set_source(g)
+ cr.rectangle(0, 0, 100, 50)
+ cr.fill()
+
+- name: 2d.gradient.interpolate.multiple
+ testing:
+ - 2d.gradient.interpolate.linear
+ code: |
+ canvas.width = 200;
+ var g = ctx.createLinearGradient(0, 0, 200, 0);
+ g.addColorStop(0, '#ff0');
+ g.addColorStop(0.5, '#0ff');
+ g.addColorStop(1, '#f0f');
+ ctx.fillStyle = g;
+ ctx.fillRect(0, 0, 200, 50);
+ @assert pixel 50,25 ==~ 127,255,127,255 +/- 3;
+ @assert pixel 100,25 ==~ 0,255,255,255 +/- 3;
+ @assert pixel 150,25 ==~ 127,127,255,255 +/- 3;
+ expected: |
+ size 200 50
+ g = cairo.LinearGradient(0, 0, 200, 0)
+ g.add_color_stop_rgb(0.0, 1,1,0)
+ g.add_color_stop_rgb(0.5, 0,1,1)
+ g.add_color_stop_rgb(1.0, 1,0,1)
+ cr.set_source(g)
+ cr.rectangle(0, 0, 200, 50)
+ cr.fill()
+
+- name: 2d.gradient.interpolate.overlap
+ testing:
+ - 2d.gradient.interpolate.overlap
+ code: |
+ canvas.width = 200;
+ var g = ctx.createLinearGradient(0, 0, 200, 0);
+ g.addColorStop(0, '#f00');
+ g.addColorStop(0, '#ff0');
+ g.addColorStop(0.25, '#00f');
+ g.addColorStop(0.25, '#0f0');
+ g.addColorStop(0.25, '#0f0');
+ g.addColorStop(0.25, '#0f0');
+ g.addColorStop(0.25, '#ff0');
+ g.addColorStop(0.5, '#00f');
+ g.addColorStop(0.5, '#0f0');
+ g.addColorStop(0.75, '#00f');
+ g.addColorStop(0.75, '#f00');
+ g.addColorStop(0.75, '#ff0');
+ g.addColorStop(0.5, '#0f0');
+ g.addColorStop(0.5, '#0f0');
+ g.addColorStop(0.5, '#ff0');
+ g.addColorStop(1, '#00f');
+ ctx.fillStyle = g;
+ ctx.fillRect(0, 0, 200, 50);
+ @assert pixel 49,25 ==~ 0,0,255,255 +/- 16;
+ @assert pixel 51,25 ==~ 255,255,0,255 +/- 16;
+ @assert pixel 99,25 ==~ 0,0,255,255 +/- 16;
+ @assert pixel 101,25 ==~ 255,255,0,255 +/- 16;
+ @assert pixel 149,25 ==~ 0,0,255,255 +/- 16;
+ @assert pixel 151,25 ==~ 255,255,0,255 +/- 16;
+ expected: |
+ size 200 50
+ g = cairo.LinearGradient(0, 0, 50, 0)
+ g.add_color_stop_rgb(0, 1,1,0)
+ g.add_color_stop_rgb(1, 0,0,1)
+ cr.set_source(g)
+ cr.rectangle(0, 0, 50, 50)
+ cr.fill()
+
+ g = cairo.LinearGradient(50, 0, 100, 0)
+ g.add_color_stop_rgb(0, 1,1,0)
+ g.add_color_stop_rgb(1, 0,0,1)
+ cr.set_source(g)
+ cr.rectangle(50, 0, 50, 50)
+ cr.fill()
+
+ g = cairo.LinearGradient(100, 0, 150, 0)
+ g.add_color_stop_rgb(0, 1,1,0)
+ g.add_color_stop_rgb(1, 0,0,1)
+ cr.set_source(g)
+ cr.rectangle(100, 0, 50, 50)
+ cr.fill()
+
+ g = cairo.LinearGradient(150, 0, 200, 0)
+ g.add_color_stop_rgb(0, 1,1,0)
+ g.add_color_stop_rgb(1, 0,0,1)
+ cr.set_source(g)
+ cr.rectangle(150, 0, 50, 50)
+ cr.fill()
+
+- name: 2d.gradient.interpolate.overlap2
+ testing:
+ - 2d.gradient.interpolate.overlap
+ code: |
+ var g = ctx.createLinearGradient(0, 0, 100, 0);
+ var ps = [ 0, 1/10, 1/4, 1/3, 1/2, 3/4, 1 ];
+ for (var p = 0; p < ps.length; ++p)
+ {
+ g.addColorStop(ps[p], '#0f0');
+ for (var i = 0; i < 15; ++i)
+ g.addColorStop(ps[p], '#f00');
+ g.addColorStop(ps[p], '#0f0');
+ }
+ ctx.fillStyle = g;
+ ctx.fillRect(0, 0, 100, 50);
+ @assert pixel 1,25 == 0,255,0,255;
+ @assert pixel 30,25 == 0,255,0,255;
+ @assert pixel 40,25 == 0,255,0,255;
+ @assert pixel 60,25 == 0,255,0,255;
+ @assert pixel 80,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.gradient.empty
+ testing:
+ - 2d.gradient.empty
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ var g = ctx.createLinearGradient(0, 0, 0, 50);
+ ctx.fillStyle = g;
+ ctx.fillRect(0, 0, 100, 50);
+ @assert pixel 50,25 ==~ 0,255,0,255;
+ expected: green
+
+- name: 2d.gradient.object.update
+ testing:
+ - 2d.gradient.update
+ code: |
+ var g = ctx.createLinearGradient(-100, 0, 200, 0);
+ g.addColorStop(0, '#f00');
+ g.addColorStop(1, '#f00');
+ ctx.fillStyle = g;
+ g.addColorStop(0.1, '#0f0');
+ g.addColorStop(0.9, '#0f0');
+ ctx.fillRect(0, 0, 100, 50);
+ @assert pixel 50,25 ==~ 0,255,0,255;
+ expected: green
+
+- name: 2d.gradient.object.compare
+ testing:
+ - 2d.gradient.object
+ code: |
+ var g1 = ctx.createLinearGradient(0, 0, 100, 0);
+ var g2 = ctx.createLinearGradient(0, 0, 100, 0);
+ @assert g1 !== g2;
+ ctx.fillStyle = g1;
+ @assert ctx.fillStyle === g1;
+
+- name: 2d.gradient.object.crosscanvas
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ var g = document.createElement('canvas').getContext('2d').createLinearGradient(0, 0, 100, 0);
+ g.addColorStop(0, '#0f0');
+ g.addColorStop(1, '#0f0');
+ ctx.fillStyle = g;
+ ctx.fillRect(0, 0, 100, 50);
+ @assert pixel 50,25 ==~ 0,255,0,255;
+ expected: green
+
+- name: 2d.gradient.object.current
+ testing:
+ - 2d.currentColor.gradient
+ code: |
+ canvas.setAttribute('style', 'color: #f00');
+
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ var g = ctx.createLinearGradient(0, 0, 100, 0);
+ g.addColorStop(0, 'currentColor');
+ g.addColorStop(1, 'currentColor');
+ ctx.fillStyle = g;
+ ctx.fillRect(0, 0, 100, 50);
+ @assert pixel 50,25 ==~ 0,0,0,255;
+ expected: |
+ size 100 50
+ cr.set_source_rgb(0, 0, 0)
+ cr.rectangle(0, 0, 100, 50)
+ cr.fill()
+
+- name: 2d.gradient.object.invalidoffset
+ testing:
+ - 2d.gradient.invalidoffset
+ code: |
+ var g = ctx.createLinearGradient(0, 0, 100, 0);
+ @assert throws INDEX_SIZE_ERR g.addColorStop(-1, '#000');
+ @assert throws INDEX_SIZE_ERR g.addColorStop(2, '#000');
+ @assert throws INDEX_SIZE_ERR g.addColorStop(Infinity, '#000');
+ @assert throws INDEX_SIZE_ERR g.addColorStop(-Infinity, '#000');
+ @assert throws INDEX_SIZE_ERR g.addColorStop(NaN, '#000');
+
+- name: 2d.gradient.object.invalidcolour
+ testing:
+ - 2d.gradient.invalidcolour
+ code: |
+ var g = ctx.createLinearGradient(0, 0, 100, 0);
+ @assert throws SYNTAX_ERR g.addColorStop(0, "");
+ @assert throws SYNTAX_ERR g.addColorStop(0, 'null');
+ @assert throws SYNTAX_ERR g.addColorStop(0, 'undefined');
+ @assert throws SYNTAX_ERR g.addColorStop(0, null);
+ @assert throws SYNTAX_ERR g.addColorStop(0, undefined);
+
+
+- name: 2d.gradient.linear.nonfinite
+ desc: createLinearGradient() throws TypeError if arguments are not finite
+ notes: *bindings
+ testing:
+ - 2d.gradient.linear.nonfinite
+ code: |
+ @nonfinite @assert throws TypeError ctx.createLinearGradient(<0 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>, <1 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>);
+
+- name: 2d.gradient.linear.transform.1
+ desc: Linear gradient coordinates are relative to the coordinate space at the time of filling
+ testing:
+ - 2d.gradient.linear.transform
+ code: |
+ var g = ctx.createLinearGradient(0, 0, 200, 0);
+ g.addColorStop(0, '#f00');
+ g.addColorStop(0.25, '#0f0');
+ g.addColorStop(0.75, '#0f0');
+ g.addColorStop(1, '#f00');
+ ctx.fillStyle = g;
+ ctx.translate(-50, 0);
+ ctx.fillRect(50, 0, 100, 50);
+ @assert pixel 25,25 == 0,255,0,255;
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 75,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.gradient.linear.transform.2
+ desc: Linear gradient coordinates are relative to the coordinate space at the time of filling
+ testing:
+ - 2d.gradient.linear.transform
+ code: |
+ ctx.translate(100, 0);
+ var g = ctx.createLinearGradient(0, 0, 200, 0);
+ g.addColorStop(0, '#f00');
+ g.addColorStop(0.25, '#0f0');
+ g.addColorStop(0.75, '#0f0');
+ g.addColorStop(1, '#f00');
+ ctx.fillStyle = g;
+ ctx.translate(-150, 0);
+ ctx.fillRect(50, 0, 100, 50);
+ @assert pixel 25,25 == 0,255,0,255;
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 75,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.gradient.linear.transform.3
+ desc: Linear gradient transforms do not experience broken caching effects
+ testing:
+ - 2d.gradient.linear.transform
+ code: |
+ var g = ctx.createLinearGradient(0, 0, 200, 0);
+ g.addColorStop(0, '#f00');
+ g.addColorStop(0.25, '#0f0');
+ g.addColorStop(0.75, '#0f0');
+ g.addColorStop(1, '#f00');
+ ctx.fillStyle = g;
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.translate(-50, 0);
+ ctx.fillRect(50, 0, 100, 50);
+ @assert pixel 25,25 == 0,255,0,255;
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 75,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.gradient.radial.negative
+ desc: createRadialGradient() throws INDEX_SIZE_ERR if either radius is negative
+ testing:
+ - 2d.gradient.radial.negative
+ code: |
+ @assert throws INDEX_SIZE_ERR ctx.createRadialGradient(0, 0, -0.1, 0, 0, 1);
+ @assert throws INDEX_SIZE_ERR ctx.createRadialGradient(0, 0, 1, 0, 0, -0.1);
+ @assert throws INDEX_SIZE_ERR ctx.createRadialGradient(0, 0, -0.1, 0, 0, -0.1);
+
+- name: 2d.gradient.radial.nonfinite
+ desc: createRadialGradient() throws TypeError if arguments are not finite
+ notes: *bindings
+ testing:
+ - 2d.gradient.radial.nonfinite
+ code: |
+ @nonfinite @assert throws TypeError ctx.createRadialGradient(<0 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>, <1 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>, <1 Infinity -Infinity NaN>);
+
+- name: 2d.gradient.radial.inside1
+ testing:
+ - 2d.gradient.radial.rendering
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ var g = ctx.createRadialGradient(50, 25, 100, 50, 25, 200);
+ g.addColorStop(0, '#0f0');
+ g.addColorStop(1, '#f00');
+ ctx.fillStyle = g;
+ ctx.fillRect(0, 0, 100, 50);
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 50,1 == 0,255,0,255;
+ @assert pixel 98,1 == 0,255,0,255;
+ @assert pixel 1,25 == 0,255,0,255;
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 98,25 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ @assert pixel 50,48 == 0,255,0,255;
+ @assert pixel 98,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.gradient.radial.inside2
+ testing:
+ - 2d.gradient.radial.rendering
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ var g = ctx.createRadialGradient(50, 25, 200, 50, 25, 100);
+ g.addColorStop(0, '#f00');
+ g.addColorStop(1, '#0f0');
+ ctx.fillStyle = g;
+ ctx.fillRect(0, 0, 100, 50);
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 50,1 == 0,255,0,255;
+ @assert pixel 98,1 == 0,255,0,255;
+ @assert pixel 1,25 == 0,255,0,255;
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 98,25 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ @assert pixel 50,48 == 0,255,0,255;
+ @assert pixel 98,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.gradient.radial.inside3
+ testing:
+ - 2d.gradient.radial.rendering
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ var g = ctx.createRadialGradient(50, 25, 200, 50, 25, 100);
+ g.addColorStop(0, '#f00');
+ g.addColorStop(0.993, '#f00');
+ g.addColorStop(1, '#0f0');
+ ctx.fillStyle = g;
+ ctx.fillRect(0, 0, 100, 50);
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 50,1 == 0,255,0,255;
+ @assert pixel 98,1 == 0,255,0,255;
+ @assert pixel 1,25 == 0,255,0,255;
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 98,25 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ @assert pixel 50,48 == 0,255,0,255;
+ @assert pixel 98,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.gradient.radial.outside1
+ testing:
+ - 2d.gradient.radial.rendering
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ var g = ctx.createRadialGradient(200, 25, 10, 200, 25, 20);
+ g.addColorStop(0, '#f00');
+ g.addColorStop(1, '#0f0');
+ ctx.fillStyle = g;
+ ctx.fillRect(0, 0, 100, 50);
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 50,1 == 0,255,0,255;
+ @assert pixel 98,1 == 0,255,0,255;
+ @assert pixel 1,25 == 0,255,0,255;
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 98,25 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ @assert pixel 50,48 == 0,255,0,255;
+ @assert pixel 98,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.gradient.radial.outside2
+ testing:
+ - 2d.gradient.radial.rendering
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ var g = ctx.createRadialGradient(200, 25, 20, 200, 25, 10);
+ g.addColorStop(0, '#0f0');
+ g.addColorStop(1, '#f00');
+ ctx.fillStyle = g;
+ ctx.fillRect(0, 0, 100, 50);
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 50,1 == 0,255,0,255;
+ @assert pixel 98,1 == 0,255,0,255;
+ @assert pixel 1,25 == 0,255,0,255;
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 98,25 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ @assert pixel 50,48 == 0,255,0,255;
+ @assert pixel 98,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.gradient.radial.outside3
+ testing:
+ - 2d.gradient.radial.rendering
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ var g = ctx.createRadialGradient(200, 25, 20, 200, 25, 10);
+ g.addColorStop(0, '#0f0');
+ g.addColorStop(0.001, '#f00');
+ g.addColorStop(1, '#f00');
+ ctx.fillStyle = g;
+ ctx.fillRect(0, 0, 100, 50);
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 50,1 == 0,255,0,255;
+ @assert pixel 98,1 == 0,255,0,255;
+ @assert pixel 1,25 == 0,255,0,255;
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 98,25 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ @assert pixel 50,48 == 0,255,0,255;
+ @assert pixel 98,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.gradient.radial.touch1
+ testing:
+ - 2d.gradient.radial.rendering
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ var g = ctx.createRadialGradient(150, 25, 50, 200, 25, 100);
+ g.addColorStop(0, '#f00');
+ g.addColorStop(1, '#f00');
+ ctx.fillStyle = g;
+ ctx.fillRect(0, 0, 100, 50);
+
+ @assert pixel 1,1 == 0,255,0,255; @moz-todo
+ @assert pixel 50,1 == 0,255,0,255; @moz-todo
+ @assert pixel 98,1 == 0,255,0,255; @moz-todo
+ @assert pixel 1,25 == 0,255,0,255; @moz-todo
+ @assert pixel 50,25 == 0,255,0,255; @moz-todo
+ @assert pixel 98,25 == 0,255,0,255; @moz-todo
+ @assert pixel 1,48 == 0,255,0,255; @moz-todo
+ @assert pixel 50,48 == 0,255,0,255; @moz-todo
+ @assert pixel 98,48 == 0,255,0,255; @moz-todo
+ expected: green
+
+- name: 2d.gradient.radial.touch2
+ testing:
+ - 2d.gradient.radial.rendering
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ var g = ctx.createRadialGradient(-80, 25, 70, 0, 25, 150);
+ g.addColorStop(0, '#f00');
+ g.addColorStop(0.01, '#0f0');
+ g.addColorStop(0.99, '#0f0');
+ g.addColorStop(1, '#f00');
+ ctx.fillStyle = g;
+ ctx.fillRect(0, 0, 100, 50);
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 50,1 == 0,255,0,255;
+ @assert pixel 98,1 == 0,255,0,255;
+ @assert pixel 1,25 == 0,255,0,255;
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 98,25 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ @assert pixel 50,48 == 0,255,0,255;
+ @assert pixel 98,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.gradient.radial.touch3
+ testing:
+ - 2d.gradient.radial.rendering
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ var g = ctx.createRadialGradient(120, -15, 25, 140, -30, 50);
+ g.addColorStop(0, '#f00');
+ g.addColorStop(1, '#f00');
+ ctx.fillStyle = g;
+ ctx.fillRect(0, 0, 100, 50);
+
+ @assert pixel 1,1 == 0,255,0,255; @moz-todo
+ @assert pixel 50,1 == 0,255,0,255; @moz-todo
+ @assert pixel 98,1 == 0,255,0,255; @moz-todo
+ @assert pixel 1,25 == 0,255,0,255; @moz-todo
+ @assert pixel 50,25 == 0,255,0,255; @moz-todo
+ @assert pixel 98,25 == 0,255,0,255; @moz-todo
+ @assert pixel 1,48 == 0,255,0,255; @moz-todo
+ @assert pixel 50,48 == 0,255,0,255; @moz-todo
+ @assert pixel 98,48 == 0,255,0,255; @moz-todo
+ expected: green
+
+- name: 2d.gradient.radial.equal
+ testing:
+ - 2d.gradient.radial.equal
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ var g = ctx.createRadialGradient(50, 25, 20, 50, 25, 20);
+ g.addColorStop(0, '#f00');
+ g.addColorStop(1, '#f00');
+ ctx.fillStyle = g;
+ ctx.fillRect(0, 0, 100, 50);
+
+ @assert pixel 1,1 == 0,255,0,255; @moz-todo
+ @assert pixel 50,1 == 0,255,0,255; @moz-todo
+ @assert pixel 98,1 == 0,255,0,255; @moz-todo
+ @assert pixel 1,25 == 0,255,0,255; @moz-todo
+ @assert pixel 50,25 == 0,255,0,255; @moz-todo
+ @assert pixel 98,25 == 0,255,0,255; @moz-todo
+ @assert pixel 1,48 == 0,255,0,255; @moz-todo
+ @assert pixel 50,48 == 0,255,0,255; @moz-todo
+ @assert pixel 98,48 == 0,255,0,255; @moz-todo
+ expected: green
+
+- name: 2d.gradient.radial.cone.behind
+ testing:
+ - 2d.gradient.radial.rendering
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ var g = ctx.createRadialGradient(120, 25, 10, 211, 25, 100);
+ g.addColorStop(0, '#f00');
+ g.addColorStop(1, '#f00');
+ ctx.fillStyle = g;
+ ctx.fillRect(0, 0, 100, 50);
+
+ @assert pixel 1,1 == 0,255,0,255; @moz-todo
+ @assert pixel 50,1 == 0,255,0,255; @moz-todo
+ @assert pixel 98,1 == 0,255,0,255; @moz-todo
+ @assert pixel 1,25 == 0,255,0,255; @moz-todo
+ @assert pixel 50,25 == 0,255,0,255; @moz-todo
+ @assert pixel 98,25 == 0,255,0,255; @moz-todo
+ @assert pixel 1,48 == 0,255,0,255; @moz-todo
+ @assert pixel 50,48 == 0,255,0,255; @moz-todo
+ @assert pixel 98,48 == 0,255,0,255; @moz-todo
+ expected: green
+
+- name: 2d.gradient.radial.cone.front
+ testing:
+ - 2d.gradient.radial.rendering
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ var g = ctx.createRadialGradient(311, 25, 10, 210, 25, 100);
+ g.addColorStop(0, '#f00');
+ g.addColorStop(1, '#0f0');
+ ctx.fillStyle = g;
+ ctx.fillRect(0, 0, 100, 50);
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 50,1 == 0,255,0,255;
+ @assert pixel 98,1 == 0,255,0,255;
+ @assert pixel 1,25 == 0,255,0,255;
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 98,25 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ @assert pixel 50,48 == 0,255,0,255;
+ @assert pixel 98,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.gradient.radial.cone.bottom
+ testing:
+ - 2d.gradient.radial.rendering
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ var g = ctx.createRadialGradient(210, 25, 100, 230, 25, 101);
+ g.addColorStop(0, '#0f0');
+ g.addColorStop(1, '#f00');
+ ctx.fillStyle = g;
+ ctx.fillRect(0, 0, 100, 50);
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 50,1 == 0,255,0,255;
+ @assert pixel 98,1 == 0,255,0,255;
+ @assert pixel 1,25 == 0,255,0,255;
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 98,25 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ @assert pixel 50,48 == 0,255,0,255;
+ @assert pixel 98,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.gradient.radial.cone.top
+ testing:
+ - 2d.gradient.radial.rendering
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ var g = ctx.createRadialGradient(230, 25, 100, 100, 25, 101);
+ g.addColorStop(0, '#f00');
+ g.addColorStop(1, '#0f0');
+ ctx.fillStyle = g;
+ ctx.fillRect(0, 0, 100, 50);
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 50,1 == 0,255,0,255;
+ @assert pixel 98,1 == 0,255,0,255;
+ @assert pixel 1,25 == 0,255,0,255;
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 98,25 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ @assert pixel 50,48 == 0,255,0,255;
+ @assert pixel 98,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.gradient.radial.cone.beside
+ testing:
+ - 2d.gradient.radial.rendering
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ var g = ctx.createRadialGradient(0, 100, 40, 100, 100, 50);
+ g.addColorStop(0, '#f00');
+ g.addColorStop(1, '#f00');
+ ctx.fillStyle = g;
+ ctx.fillRect(0, 0, 100, 50);
+
+ @assert pixel 1,1 == 0,255,0,255; @moz-todo
+ @assert pixel 50,1 == 0,255,0,255; @moz-todo
+ @assert pixel 98,1 == 0,255,0,255; @moz-todo
+ @assert pixel 1,25 == 0,255,0,255; @moz-todo
+ @assert pixel 50,25 == 0,255,0,255; @moz-todo
+ @assert pixel 98,25 == 0,255,0,255; @moz-todo
+ @assert pixel 1,48 == 0,255,0,255; @moz-todo
+ @assert pixel 50,48 == 0,255,0,255; @moz-todo
+ @assert pixel 98,48 == 0,255,0,255; @moz-todo
+ expected: green
+
+- name: 2d.gradient.radial.cone.cylinder
+ testing:
+ - 2d.gradient.radial.rendering
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ var g = ctx.createRadialGradient(210, 25, 100, 230, 25, 100);
+ g.addColorStop(0, '#0f0');
+ g.addColorStop(1, '#f00');
+ ctx.fillStyle = g;
+ ctx.fillRect(0, 0, 100, 50);
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 50,1 == 0,255,0,255;
+ @assert pixel 98,1 == 0,255,0,255;
+ @assert pixel 1,25 == 0,255,0,255;
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 98,25 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ @assert pixel 50,48 == 0,255,0,255;
+ @assert pixel 98,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.gradient.radial.cone.shape1
+ testing:
+ - 2d.gradient.radial.rendering
+ code: |
+ var tol = 1; // tolerance to avoid antialiasing artifacts
+
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.fillStyle = '#f00';
+ ctx.beginPath();
+ ctx.moveTo(30+tol, 40);
+ ctx.lineTo(110, -20+tol);
+ ctx.lineTo(110, 100-tol);
+ ctx.fill();
+
+ var g = ctx.createRadialGradient(30+10*5/2, 40, 10*3/2, 30+10*15/4, 40, 10*9/4);
+ g.addColorStop(0, '#0f0');
+ g.addColorStop(1, '#0f0');
+ ctx.fillStyle = g;
+ ctx.fillRect(0, 0, 100, 50);
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 50,1 == 0,255,0,255;
+ @assert pixel 98,1 == 0,255,0,255;
+ @assert pixel 1,25 == 0,255,0,255;
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 98,25 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ @assert pixel 50,48 == 0,255,0,255;
+ @assert pixel 98,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.gradient.radial.cone.shape2
+ testing:
+ - 2d.gradient.radial.rendering
+ code: |
+ var tol = 1; // tolerance to avoid antialiasing artifacts
+
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ var g = ctx.createRadialGradient(30+10*5/2, 40, 10*3/2, 30+10*15/4, 40, 10*9/4);
+ g.addColorStop(0, '#f00');
+ g.addColorStop(1, '#f00');
+ ctx.fillStyle = g;
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.fillStyle = '#0f0';
+ ctx.beginPath();
+ ctx.moveTo(30-tol, 40);
+ ctx.lineTo(110, -20-tol);
+ ctx.lineTo(110, 100+tol);
+ ctx.fill();
+
+ @assert pixel 1,1 == 0,255,0,255; @moz-todo
+ @assert pixel 50,1 == 0,255,0,255; @moz-todo
+ @assert pixel 98,1 == 0,255,0,255;
+ @assert pixel 1,25 == 0,255,0,255; @moz-todo
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 98,25 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255; @moz-todo
+ @assert pixel 50,48 == 0,255,0,255;
+ @assert pixel 98,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.gradient.radial.transform.1
+ desc: Radial gradient coordinates are relative to the coordinate space at the time of filling
+ testing:
+ - 2d.gradient.radial.transform
+ code: |
+ var g = ctx.createRadialGradient(0, 0, 0, 0, 0, 11.2);
+ g.addColorStop(0, '#0f0');
+ g.addColorStop(0.5, '#0f0');
+ g.addColorStop(0.51, '#f00');
+ g.addColorStop(1, '#f00');
+ ctx.fillStyle = g;
+ ctx.translate(50, 25);
+ ctx.scale(10, 10);
+ ctx.fillRect(-5, -2.5, 10, 5);
+ @assert pixel 25,25 == 0,255,0,255;
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 75,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.gradient.radial.transform.2
+ desc: Radial gradient coordinates are relative to the coordinate space at the time of filling
+ testing:
+ - 2d.gradient.radial.transform
+ code: |
+ ctx.translate(100, 0);
+ var g = ctx.createRadialGradient(0, 0, 0, 0, 0, 11.2);
+ g.addColorStop(0, '#0f0');
+ g.addColorStop(0.5, '#0f0');
+ g.addColorStop(0.51, '#f00');
+ g.addColorStop(1, '#f00');
+ ctx.fillStyle = g;
+ ctx.translate(-50, 25);
+ ctx.scale(10, 10);
+ ctx.fillRect(-5, -2.5, 10, 5);
+ @assert pixel 25,25 == 0,255,0,255;
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 75,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.gradient.radial.transform.3
+ desc: Radial gradient transforms do not experience broken caching effects
+ testing:
+ - 2d.gradient.radial.transform
+ code: |
+ var g = ctx.createRadialGradient(0, 0, 0, 0, 0, 11.2);
+ g.addColorStop(0, '#0f0');
+ g.addColorStop(0.5, '#0f0');
+ g.addColorStop(0.51, '#f00');
+ g.addColorStop(1, '#f00');
+ ctx.fillStyle = g;
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.translate(50, 25);
+ ctx.scale(10, 10);
+ ctx.fillRect(-5, -2.5, 10, 5);
+ @assert pixel 25,25 == 0,255,0,255;
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 75,25 == 0,255,0,255;
+ expected: green
+
+
+
+
+
+
+- name: 2d.pattern.basic.type
+ testing:
+ - 2d.pattern.return
+ images:
+ - green.png
+ code: |
+ @assert window.CanvasPattern !== undefined;
+
+ window.CanvasPattern.prototype.thisImplementsCanvasPattern = true;
+
+ var img = document.getElementById('green.png');
+ var pattern = ctx.createPattern(img, 'no-repeat');
+ @assert pattern.thisImplementsCanvasPattern;
+
+- name: 2d.pattern.basic.image
+ testing:
+ - 2d.pattern.painting
+ images:
+ - green.png
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ var img = document.getElementById('green.png');
+ var pattern = ctx.createPattern(img, 'no-repeat');
+ ctx.fillStyle = pattern;
+ ctx.fillRect(0, 0, 100, 50);
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 98,1 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ @assert pixel 98,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.pattern.basic.canvas
+ testing:
+ - 2d.pattern.painting
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ var canvas2 = document.createElement('canvas');
+ canvas2.width = 100;
+ canvas2.height = 50;
+ var ctx2 = canvas2.getContext('2d');
+ ctx2.fillStyle = '#0f0';
+ ctx2.fillRect(0, 0, 100, 50);
+
+ var pattern = ctx.createPattern(canvas2, 'no-repeat');
+ ctx.fillStyle = pattern;
+ ctx.fillRect(0, 0, 100, 50);
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 50,1 == 0,255,0,255;
+ @assert pixel 98,1 == 0,255,0,255;
+ @assert pixel 1,25 == 0,255,0,255;
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 98,25 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ @assert pixel 50,48 == 0,255,0,255;
+ @assert pixel 98,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.pattern.basic.zerocanvas
+ testing:
+ - 2d.pattern.zerocanvas
+ code: |
+ canvas.width = 0;
+ canvas.height = 10;
+ @assert canvas.width === 0;
+ @assert canvas.height === 10;
+ @assert throws INVALID_STATE_ERR ctx.createPattern(canvas, 'repeat');
+
+ canvas.width = 10;
+ canvas.height = 0;
+ @assert canvas.width === 10;
+ @assert canvas.height === 0;
+ @assert throws INVALID_STATE_ERR ctx.createPattern(canvas, 'repeat');
+
+ canvas.width = 0;
+ canvas.height = 0;
+ @assert canvas.width === 0;
+ @assert canvas.height === 0;
+ @assert throws INVALID_STATE_ERR ctx.createPattern(canvas, 'repeat');
+
+- name: 2d.pattern.basic.nocontext
+ testing:
+ - 2d.pattern.painting
+ code: |
+ var canvas2 = document.createElement('canvas');
+ canvas2.width = 100;
+ canvas2.height = 50;
+ var pattern = ctx.createPattern(canvas2, 'no-repeat');
+
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#f00';
+ ctx.fillStyle = pattern;
+ ctx.fillRect(0, 0, 100, 50);
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 98,1 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ @assert pixel 98,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.pattern.image.undefined
+ testing:
+ - 2d.pattern.IDL
+ notes: *bindings
+ code: |
+ @assert throws TypeError ctx.createPattern(undefined, 'repeat');
+
+- name: 2d.pattern.image.null
+ testing:
+ - 2d.pattern.IDL
+ notes: *bindings
+ code: |
+ @assert throws TypeError ctx.createPattern(null, 'repeat');
+
+- name: 2d.pattern.image.string
+ testing:
+ - 2d.pattern.IDL
+ notes: *bindings
+ code: |
+ @assert throws TypeError ctx.createPattern('../images/red.png', 'repeat');
+
+- name: 2d.pattern.image.incomplete.nosrc
+ testing:
+ - 2d.pattern.incomplete.image
+ mozilla: { throws }
+ code: |
+ var img = new Image();
+ @assert ctx.createPattern(img, 'repeat') === null;
+
+- name: 2d.pattern.image.incomplete.immediate
+ testing:
+ - 2d.pattern.incomplete.image
+ images:
+ - red.png
+ code: |
+ var img = new Image();
+ img.src = '../images/red.png';
+ // This triggers the "update the image data" algorithm.
+ // The image will not go to the "completely available" state
+ // until a fetch task in the networking task source is processed,
+ // so the image must not be fully decodable yet:
+ @assert ctx.createPattern(img, 'repeat') === null; @moz-todo
+
+- name: 2d.pattern.image.incomplete.reload
+ testing:
+ - 2d.pattern.incomplete.image
+ images:
+ - yellow.png
+ - red.png
+ code: |
+ var img = document.getElementById('yellow.png');
+ img.src = '../images/red.png';
+ // This triggers the "update the image data" algorithm,
+ // and resets the image to the "unavailable" state.
+ // The image will not go to the "completely available" state
+ // until a fetch task in the networking task source is processed,
+ // so the image must not be fully decodable yet:
+ @assert ctx.createPattern(img, 'repeat') === null; @moz-todo
+
+- name: 2d.pattern.image.incomplete.emptysrc
+ testing:
+ - 2d.pattern.incomplete.image
+ images:
+ - red.png
+ mozilla: { throws }
+ code: |
+ var img = document.getElementById('red.png');
+ img.src = "";
+ @assert ctx.createPattern(img, 'repeat') === null;
+
+- name: 2d.pattern.image.incomplete.removedsrc
+ testing:
+ - 2d.pattern.incomplete.image
+ images:
+ - red.png
+ mozilla: { throws }
+ code: |
+ var img = document.getElementById('red.png');
+ img.removeAttribute('src');
+ @assert ctx.createPattern(img, 'repeat') === null;
+
+- name: 2d.pattern.image.broken
+ testing:
+ - 2d.pattern.incomplete.image
+ images:
+ - broken.png
+ code: |
+ var img = document.getElementById('broken.png');
+ @assert throws INVALID_STATE_ERR ctx.createPattern(img, 'repeat');
+
+- name: 2d.pattern.repeat.empty
+ testing:
+ - 2d.pattern.missing
+ images:
+ - green-1x1.png
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ var img = document.getElementById('green-1x1.png');
+ var pattern = ctx.createPattern(img, "");
+ ctx.fillStyle = pattern;
+ ctx.fillRect(0, 0, 200, 50);
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 98,1 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ @assert pixel 98,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.pattern.repeat.null
+ testing:
+ - 2d.pattern.unrecognised
+ code: |
+ @assert ctx.createPattern(canvas, null) != null;
+
+- name: 2d.pattern.repeat.undefined
+ testing:
+ - 2d.pattern.unrecognised
+ code: |
+ @assert throws SYNTAX_ERR ctx.createPattern(canvas, undefined);
+
+- name: 2d.pattern.repeat.unrecognised
+ testing:
+ - 2d.pattern.unrecognised
+ code: |
+ @assert throws SYNTAX_ERR ctx.createPattern(canvas, "invalid");
+
+- name: 2d.pattern.repeat.unrecognisednull
+ testing:
+ - 2d.pattern.unrecognised
+ code: |
+ @assert throws SYNTAX_ERR ctx.createPattern(canvas, "null");
+
+- name: 2d.pattern.repeat.case
+ testing:
+ - 2d.pattern.exact
+ code: |
+ @assert throws SYNTAX_ERR ctx.createPattern(canvas, "Repeat");
+
+- name: 2d.pattern.repeat.nullsuffix
+ testing:
+ - 2d.pattern.exact
+ code: |
+ @assert throws SYNTAX_ERR ctx.createPattern(canvas, "repeat\0");
+
+- name: 2d.pattern.modify.image1
+ testing:
+ - 2d.pattern.modify
+ images:
+ - green.png
+ code: |
+ var img = document.getElementById('green.png');
+ var pattern = ctx.createPattern(img, 'no-repeat');
+ deferTest();
+ img.onload = t.step_func_done(function ()
+ {
+ ctx.fillStyle = pattern;
+ ctx.fillRect(0, 0, 100, 50);
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 98,1 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ @assert pixel 98,48 == 0,255,0,255;
+ });
+ img.src = '/images/red.png';
+ expected: green
+
+- name: 2d.pattern.modify.image2
+ testing:
+ - 2d.pattern.modify
+ images:
+ - green.png
+ code: |
+ var img = document.getElementById('green.png');
+ var pattern = ctx.createPattern(img, 'no-repeat');
+ ctx.fillStyle = pattern;
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#00f';
+ ctx.fillRect(0, 0, 100, 50);
+ deferTest();
+ img.onload = t.step_func_done(function ()
+ {
+ ctx.fillStyle = pattern;
+ ctx.fillRect(0, 0, 100, 50);
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 98,1 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ @assert pixel 98,48 == 0,255,0,255;
+ });
+ img.src = '/images/red.png';
+ expected: green
+
+- name: 2d.pattern.modify.canvas1
+ testing:
+ - 2d.pattern.modify
+ code: |
+ var canvas2 = document.createElement('canvas');
+ canvas2.width = 100;
+ canvas2.height = 50;
+ var ctx2 = canvas2.getContext('2d');
+ ctx2.fillStyle = '#0f0';
+ ctx2.fillRect(0, 0, 100, 50);
+
+ var pattern = ctx.createPattern(canvas2, 'no-repeat');
+
+ ctx2.fillStyle = '#f00';
+ ctx2.fillRect(0, 0, 100, 50);
+
+ ctx.fillStyle = pattern;
+ ctx.fillRect(0, 0, 100, 50);
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 98,1 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ @assert pixel 98,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.pattern.modify.canvas2
+ testing:
+ - 2d.pattern.modify
+ code: |
+ var canvas2 = document.createElement('canvas');
+ canvas2.width = 100;
+ canvas2.height = 50;
+ var ctx2 = canvas2.getContext('2d');
+ ctx2.fillStyle = '#0f0';
+ ctx2.fillRect(0, 0, 100, 50);
+
+ var pattern = ctx.createPattern(canvas2, 'no-repeat');
+ ctx.fillStyle = pattern;
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx2.fillStyle = '#f00';
+ ctx2.fillRect(0, 0, 100, 50);
+
+ ctx.fillStyle = pattern;
+ ctx.fillRect(0, 0, 100, 50);
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 98,1 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ @assert pixel 98,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.pattern.crosscanvas
+ images:
+ - green.png
+ code: |
+ var img = document.getElementById('green.png');
+
+ var pattern = document.createElement('canvas').getContext('2d').createPattern(img, 'no-repeat');
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = pattern;
+ ctx.fillRect(0, 0, 100, 50);
+
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.pattern.paint.norepeat.basic
+ testing:
+ - 2d.pattern.painting
+ images:
+ - green.png
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ var img = document.getElementById('green.png');
+ var pattern = ctx.createPattern(img, 'no-repeat');
+ ctx.fillStyle = pattern;
+ ctx.fillRect(0, 0, 100, 50);
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 98,1 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ @assert pixel 98,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.pattern.paint.norepeat.outside
+ testing:
+ - 2d.pattern.painting
+ images:
+ - red.png
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ var img = document.getElementById('red.png');
+ var pattern = ctx.createPattern(img, 'no-repeat');
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.fillStyle = pattern;
+ ctx.fillRect(0, -50, 100, 50);
+ ctx.fillRect(-100, 0, 100, 50);
+ ctx.fillRect(0, 50, 100, 50);
+ ctx.fillRect(100, 0, 100, 50);
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 98,1 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ @assert pixel 98,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.pattern.paint.norepeat.coord1
+ testing:
+ - 2d.pattern.painting
+ images:
+ - green.png
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 50, 50);
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(50, 0, 50, 50);
+
+ var img = document.getElementById('green.png');
+ var pattern = ctx.createPattern(img, 'no-repeat');
+ ctx.fillStyle = pattern;
+ ctx.translate(50, 0);
+ ctx.fillRect(-50, 0, 100, 50);
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 98,1 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ @assert pixel 98,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.pattern.paint.norepeat.coord2
+ testing:
+ - 2d.pattern.painting
+ images:
+ - green.png
+ code: |
+ var img = document.getElementById('green.png');
+ var pattern = ctx.createPattern(img, 'no-repeat');
+ ctx.fillStyle = pattern;
+ ctx.fillRect(0, 0, 50, 50);
+
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(50, 0, 50, 50);
+
+ ctx.fillStyle = pattern;
+ ctx.translate(50, 0);
+ ctx.fillRect(-50, 0, 100, 50);
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 98,1 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ @assert pixel 98,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.pattern.paint.norepeat.coord3
+ testing:
+ - 2d.pattern.painting
+ images:
+ - red.png
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ var img = document.getElementById('red.png');
+ var pattern = ctx.createPattern(img, 'no-repeat');
+ ctx.fillStyle = pattern;
+ ctx.translate(50, 25);
+ ctx.fillRect(-50, -25, 100, 50);
+
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 50, 25);
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 98,1 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ @assert pixel 98,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.pattern.paint.repeat.basic
+ testing:
+ - 2d.pattern.painting
+ images:
+ - green-16x16.png
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ var img = document.getElementById('green-16x16.png');
+ var pattern = ctx.createPattern(img, 'repeat');
+ ctx.fillStyle = pattern;
+ ctx.fillRect(0, 0, 100, 50);
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 98,1 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ @assert pixel 98,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.pattern.paint.repeat.outside
+ testing:
+ - 2d.pattern.painting
+ images:
+ - green-16x16.png
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ var img = document.getElementById('green-16x16.png');
+ var pattern = ctx.createPattern(img, 'repeat');
+ ctx.fillStyle = pattern;
+ ctx.translate(50, 25);
+ ctx.fillRect(-50, -25, 100, 50);
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 98,1 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ @assert pixel 98,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.pattern.paint.repeat.coord1
+ testing:
+ - 2d.pattern.painting
+ images:
+ - rgrg-256x256.png
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ var img = document.getElementById('rgrg-256x256.png');
+ var pattern = ctx.createPattern(img, 'repeat');
+ ctx.fillStyle = pattern;
+ ctx.translate(-128, -78);
+ ctx.fillRect(128, 78, 100, 50);
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 98,1 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ @assert pixel 98,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.pattern.paint.repeat.coord2
+ testing:
+ - 2d.pattern.painting
+ images:
+ - ggrr-256x256.png
+ code: |
+ var img = document.getElementById('ggrr-256x256.png');
+ var pattern = ctx.createPattern(img, 'repeat');
+ ctx.fillStyle = pattern;
+ ctx.fillRect(0, 0, 100, 50);
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 98,1 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ @assert pixel 98,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.pattern.paint.repeat.coord3
+ testing:
+ - 2d.pattern.painting
+ images:
+ - rgrg-256x256.png
+ code: |
+ var img = document.getElementById('rgrg-256x256.png');
+ var pattern = ctx.createPattern(img, 'repeat');
+ ctx.fillStyle = pattern;
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.translate(-128, -78);
+ ctx.fillRect(128, 78, 100, 50);
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 98,1 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ @assert pixel 98,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.pattern.paint.repeatx.basic
+ testing:
+ - 2d.pattern.painting
+ images:
+ - green-16x16.png
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 16);
+
+ var img = document.getElementById('green-16x16.png');
+ var pattern = ctx.createPattern(img, 'repeat-x');
+ ctx.fillStyle = pattern;
+ ctx.fillRect(0, 0, 100, 50);
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 98,1 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ @assert pixel 98,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.pattern.paint.repeatx.outside
+ testing:
+ - 2d.pattern.painting
+ images:
+ - red-16x16.png
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ var img = document.getElementById('red-16x16.png');
+ var pattern = ctx.createPattern(img, 'repeat-x');
+ ctx.fillStyle = pattern;
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 16);
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 98,1 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ @assert pixel 98,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.pattern.paint.repeatx.coord1
+ testing:
+ - 2d.pattern.painting
+ images:
+ - red-16x16.png
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ var img = document.getElementById('red-16x16.png');
+ var pattern = ctx.createPattern(img, 'repeat-x');
+ ctx.fillStyle = pattern;
+ ctx.translate(0, 16);
+ ctx.fillRect(0, -16, 100, 50);
+
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 16);
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 98,1 == 0,255,0,255;
+ @assert pixel 1,25 == 0,255,0,255;
+ @assert pixel 98,25 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ @assert pixel 98,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.pattern.paint.repeaty.basic
+ testing:
+ - 2d.pattern.painting
+ images:
+ - green-16x16.png
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 16, 50);
+
+ var img = document.getElementById('green-16x16.png');
+ var pattern = ctx.createPattern(img, 'repeat-y');
+ ctx.fillStyle = pattern;
+ ctx.fillRect(0, 0, 100, 50);
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 98,1 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ @assert pixel 98,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.pattern.paint.repeaty.outside
+ testing:
+ - 2d.pattern.painting
+ images:
+ - red-16x16.png
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ var img = document.getElementById('red-16x16.png');
+ var pattern = ctx.createPattern(img, 'repeat-y');
+ ctx.fillStyle = pattern;
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 16, 50);
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 98,1 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ @assert pixel 98,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.pattern.paint.repeaty.coord1
+ testing:
+ - 2d.pattern.painting
+ images:
+ - red-16x16.png
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ var img = document.getElementById('red-16x16.png');
+ var pattern = ctx.createPattern(img, 'repeat-y');
+ ctx.fillStyle = pattern;
+ ctx.translate(48, 0);
+ ctx.fillRect(-48, 0, 100, 50);
+
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 16, 50);
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 50,1 == 0,255,0,255;
+ @assert pixel 98,1 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ @assert pixel 50,48 == 0,255,0,255;
+ @assert pixel 98,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.pattern.paint.orientation.image
+ desc: Image patterns do not get flipped when painted
+ testing:
+ - 2d.pattern.painting
+ images:
+ - rrgg-256x256.png
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ var img = document.getElementById('rrgg-256x256.png');
+ var pattern = ctx.createPattern(img, 'no-repeat');
+ ctx.fillStyle = pattern;
+ ctx.save();
+ ctx.translate(0, -103);
+ ctx.fillRect(0, 103, 100, 50);
+ ctx.restore();
+
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 25);
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 98,1 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ @assert pixel 98,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.pattern.paint.orientation.canvas
+ desc: Canvas patterns do not get flipped when painted
+ testing:
+ - 2d.pattern.painting
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ var canvas2 = document.createElement('canvas');
+ canvas2.width = 100;
+ canvas2.height = 50;
+ var ctx2 = canvas2.getContext('2d');
+ ctx2.fillStyle = '#f00';
+ ctx2.fillRect(0, 0, 100, 25);
+ ctx2.fillStyle = '#0f0';
+ ctx2.fillRect(0, 25, 100, 25);
+
+ var pattern = ctx.createPattern(canvas2, 'no-repeat');
+ ctx.fillStyle = pattern;
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 25);
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 98,1 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ @assert pixel 98,48 == 0,255,0,255;
+ expected: green
+
+
+- name: 2d.pattern.animated.gif
+ desc: createPattern() of an animated GIF draws the first frame
+ testing:
+ - 2d.pattern.animated.image
+ images:
+ - anim-gr.gif
+ code: |
+ deferTest();
+ setTimeout(function () {
+ var pattern = ctx.createPattern(document.getElementById('anim-gr.gif'), 'repeat');
+ ctx.fillStyle = pattern;
+ ctx.fillRect(0, 0, 50, 50);
+ setTimeout(t.step_func_done(function () {
+ ctx.fillRect(50, 0, 50, 50);
+ @assert pixel 25,25 ==~ 0,255,0,255;
+ @assert pixel 75,25 ==~ 0,255,0,255;
+ }), 250);
+ }, 250);
+ expected: green
+
+
+
+
+- name: 2d.line.defaults
+ testing:
+ - 2d.lineWidth.default
+ - 2d.lineCap.default
+ - 2d.lineJoin.default
+ - 2d.miterLimit.default
+ code: |
+ @assert ctx.lineWidth === 1;
+ @assert ctx.lineCap === 'butt';
+ @assert ctx.lineJoin === 'miter';
+ @assert ctx.miterLimit === 10;
+
+- name: 2d.line.width.basic
+ desc: lineWidth determines the width of line strokes
+ testing:
+ - 2d.lineWidth
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.lineWidth = 20;
+ // Draw a green line over a red box, to check the line is not too small
+ ctx.fillStyle = '#f00';
+ ctx.strokeStyle = '#0f0';
+ ctx.fillRect(15, 15, 20, 20);
+ ctx.beginPath();
+ ctx.moveTo(25, 15);
+ ctx.lineTo(25, 35);
+ ctx.stroke();
+
+ // Draw a green box over a red line, to check the line is not too large
+ ctx.fillStyle = '#0f0';
+ ctx.strokeStyle = '#f00';
+ ctx.beginPath();
+ ctx.moveTo(75, 15);
+ ctx.lineTo(75, 35);
+ ctx.stroke();
+ ctx.fillRect(65, 15, 20, 20);
+
+ @assert pixel 14,25 == 0,255,0,255;
+ @assert pixel 15,25 == 0,255,0,255;
+ @assert pixel 16,25 == 0,255,0,255;
+ @assert pixel 25,25 == 0,255,0,255;
+ @assert pixel 34,25 == 0,255,0,255;
+ @assert pixel 35,25 == 0,255,0,255;
+ @assert pixel 36,25 == 0,255,0,255;
+
+ @assert pixel 64,25 == 0,255,0,255;
+ @assert pixel 65,25 == 0,255,0,255;
+ @assert pixel 66,25 == 0,255,0,255;
+ @assert pixel 75,25 == 0,255,0,255;
+ @assert pixel 84,25 == 0,255,0,255;
+ @assert pixel 85,25 == 0,255,0,255;
+ @assert pixel 86,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.line.width.transformed
+ desc: Line stroke widths are affected by scale transformations
+ testing:
+ - 2d.lineWidth
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.lineWidth = 4;
+ // Draw a green line over a red box, to check the line is not too small
+ ctx.fillStyle = '#f00';
+ ctx.strokeStyle = '#0f0';
+ ctx.fillRect(15, 15, 20, 20);
+ ctx.save();
+ ctx.scale(5, 1);
+ ctx.beginPath();
+ ctx.moveTo(5, 15);
+ ctx.lineTo(5, 35);
+ ctx.stroke();
+ ctx.restore();
+
+ // Draw a green box over a red line, to check the line is not too large
+ ctx.fillStyle = '#0f0';
+ ctx.strokeStyle = '#f00';
+ ctx.save();
+ ctx.scale(-5, 1);
+ ctx.beginPath();
+ ctx.moveTo(-15, 15);
+ ctx.lineTo(-15, 35);
+ ctx.stroke();
+ ctx.restore();
+ ctx.fillRect(65, 15, 20, 20);
+
+ @assert pixel 14,25 == 0,255,0,255;
+ @assert pixel 15,25 == 0,255,0,255;
+ @assert pixel 16,25 == 0,255,0,255;
+ @assert pixel 25,25 == 0,255,0,255;
+ @assert pixel 34,25 == 0,255,0,255;
+ @assert pixel 35,25 == 0,255,0,255;
+ @assert pixel 36,25 == 0,255,0,255;
+
+ @assert pixel 64,25 == 0,255,0,255;
+ @assert pixel 65,25 == 0,255,0,255;
+ @assert pixel 66,25 == 0,255,0,255;
+ @assert pixel 75,25 == 0,255,0,255;
+ @assert pixel 84,25 == 0,255,0,255;
+ @assert pixel 85,25 == 0,255,0,255;
+ @assert pixel 86,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.line.width.scaledefault
+ desc: Default lineWidth strokes are affected by scale transformations
+ testing:
+ - 2d.lineWidth
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.scale(50, 50);
+ ctx.strokeStyle = '#0f0';
+ ctx.moveTo(0, 0.5);
+ ctx.lineTo(2, 0.5);
+ ctx.stroke();
+
+ @assert pixel 25,25 == 0,255,0,255;
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 75,25 == 0,255,0,255;
+ @assert pixel 50,5 == 0,255,0,255;
+ @assert pixel 50,45 == 0,255,0,255;
+ expected: green
+
+- name: 2d.line.width.valid
+ desc: Setting lineWidth to valid values works
+ testing:
+ - 2d.lineWidth.set
+ - 2d.lineWidth.get
+ code: |
+ ctx.lineWidth = 1.5;
+ @assert ctx.lineWidth === 1.5;
+
+ ctx.lineWidth = "1e1";
+ @assert ctx.lineWidth === 10;
+
+ ctx.lineWidth = 1/1024;
+ @assert ctx.lineWidth === 1/1024;
+
+ ctx.lineWidth = 1000;
+ @assert ctx.lineWidth === 1000;
+
+- name: 2d.line.width.invalid
+ desc: Setting lineWidth to invalid values is ignored
+ testing:
+ - 2d.lineWidth.invalid
+ code: |
+ ctx.lineWidth = 1.5;
+ @assert ctx.lineWidth === 1.5;
+
+ ctx.lineWidth = 1.5;
+ ctx.lineWidth = 0;
+ @assert ctx.lineWidth === 1.5;
+
+ ctx.lineWidth = 1.5;
+ ctx.lineWidth = -1;
+ @assert ctx.lineWidth === 1.5;
+
+ ctx.lineWidth = 1.5;
+ ctx.lineWidth = Infinity;
+ @assert ctx.lineWidth === 1.5;
+
+ ctx.lineWidth = 1.5;
+ ctx.lineWidth = -Infinity;
+ @assert ctx.lineWidth === 1.5;
+
+ ctx.lineWidth = 1.5;
+ ctx.lineWidth = NaN;
+ @assert ctx.lineWidth === 1.5;
+
+- name: 2d.line.cap.butt
+ desc: lineCap 'butt' is rendered correctly
+ testing:
+ - 2d.lineCap.butt
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.lineCap = 'butt';
+ ctx.lineWidth = 20;
+
+ ctx.fillStyle = '#f00';
+ ctx.strokeStyle = '#0f0';
+ ctx.fillRect(15, 15, 20, 20);
+ ctx.beginPath();
+ ctx.moveTo(25, 15);
+ ctx.lineTo(25, 35);
+ ctx.stroke();
+
+ ctx.fillStyle = '#0f0';
+ ctx.strokeStyle = '#f00';
+ ctx.beginPath();
+ ctx.moveTo(75, 15);
+ ctx.lineTo(75, 35);
+ ctx.stroke();
+ ctx.fillRect(65, 15, 20, 20);
+
+ @assert pixel 25,14 == 0,255,0,255;
+ @assert pixel 25,15 == 0,255,0,255;
+ @assert pixel 25,16 == 0,255,0,255;
+ @assert pixel 25,34 == 0,255,0,255;
+ @assert pixel 25,35 == 0,255,0,255;
+ @assert pixel 25,36 == 0,255,0,255;
+
+ @assert pixel 75,14 == 0,255,0,255;
+ @assert pixel 75,15 == 0,255,0,255;
+ @assert pixel 75,16 == 0,255,0,255;
+ @assert pixel 75,34 == 0,255,0,255;
+ @assert pixel 75,35 == 0,255,0,255;
+ @assert pixel 75,36 == 0,255,0,255;
+ expected: green
+
+- name: 2d.line.cap.round
+ desc: lineCap 'round' is rendered correctly
+ testing:
+ - 2d.lineCap.round
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ var tol = 1; // tolerance to avoid antialiasing artifacts
+
+ ctx.lineCap = 'round';
+ ctx.lineWidth = 20;
+
+
+ ctx.fillStyle = '#f00';
+ ctx.strokeStyle = '#0f0';
+
+ ctx.beginPath();
+ ctx.moveTo(35-tol, 15);
+ ctx.arc(25, 15, 10-tol, 0, Math.PI, true);
+ ctx.arc(25, 35, 10-tol, Math.PI, 0, true);
+ ctx.fill();
+
+ ctx.beginPath();
+ ctx.moveTo(25, 15);
+ ctx.lineTo(25, 35);
+ ctx.stroke();
+
+
+ ctx.fillStyle = '#0f0';
+ ctx.strokeStyle = '#f00';
+
+ ctx.beginPath();
+ ctx.moveTo(75, 15);
+ ctx.lineTo(75, 35);
+ ctx.stroke();
+
+ ctx.beginPath();
+ ctx.moveTo(85+tol, 15);
+ ctx.arc(75, 15, 10+tol, 0, Math.PI, true);
+ ctx.arc(75, 35, 10+tol, Math.PI, 0, true);
+ ctx.fill();
+
+ @assert pixel 17,6 == 0,255,0,255;
+ @assert pixel 25,6 == 0,255,0,255;
+ @assert pixel 32,6 == 0,255,0,255;
+ @assert pixel 17,43 == 0,255,0,255;
+ @assert pixel 25,43 == 0,255,0,255;
+ @assert pixel 32,43 == 0,255,0,255;
+
+ @assert pixel 67,6 == 0,255,0,255;
+ @assert pixel 75,6 == 0,255,0,255;
+ @assert pixel 82,6 == 0,255,0,255;
+ @assert pixel 67,43 == 0,255,0,255;
+ @assert pixel 75,43 == 0,255,0,255;
+ @assert pixel 82,43 == 0,255,0,255;
+ expected: green
+
+- name: 2d.line.cap.square
+ desc: lineCap 'square' is rendered correctly
+ testing:
+ - 2d.lineCap.square
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.lineCap = 'square';
+ ctx.lineWidth = 20;
+
+ ctx.fillStyle = '#f00';
+ ctx.strokeStyle = '#0f0';
+ ctx.fillRect(15, 5, 20, 40);
+ ctx.beginPath();
+ ctx.moveTo(25, 15);
+ ctx.lineTo(25, 35);
+ ctx.stroke();
+
+ ctx.fillStyle = '#0f0';
+ ctx.strokeStyle = '#f00';
+ ctx.beginPath();
+ ctx.moveTo(75, 15);
+ ctx.lineTo(75, 35);
+ ctx.stroke();
+ ctx.fillRect(65, 5, 20, 40);
+
+ @assert pixel 25,4 == 0,255,0,255;
+ @assert pixel 25,5 == 0,255,0,255;
+ @assert pixel 25,6 == 0,255,0,255;
+ @assert pixel 25,44 == 0,255,0,255;
+ @assert pixel 25,45 == 0,255,0,255;
+ @assert pixel 25,46 == 0,255,0,255;
+
+ @assert pixel 75,4 == 0,255,0,255;
+ @assert pixel 75,5 == 0,255,0,255;
+ @assert pixel 75,6 == 0,255,0,255;
+ @assert pixel 75,44 == 0,255,0,255;
+ @assert pixel 75,45 == 0,255,0,255;
+ @assert pixel 75,46 == 0,255,0,255;
+ expected: green
+
+- name: 2d.line.cap.open
+ desc: Line caps are drawn at the corners of an unclosed rectangle
+ testing:
+ - 2d.lineCap.end
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.strokeStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.lineJoin = 'bevel';
+ ctx.lineCap = 'square';
+ ctx.lineWidth = 400;
+
+ ctx.beginPath();
+ ctx.moveTo(200, 200);
+ ctx.lineTo(200, 1000);
+ ctx.lineTo(1000, 1000);
+ ctx.lineTo(1000, 200);
+ ctx.lineTo(200, 200);
+ ctx.stroke();
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 48,1 == 0,255,0,255;
+ @assert pixel 48,48 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.line.cap.closed
+ desc: Line caps are not drawn at the corners of an unclosed rectangle
+ testing:
+ - 2d.lineCap.end
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.strokeStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.lineJoin = 'bevel';
+ ctx.lineCap = 'square';
+ ctx.lineWidth = 400;
+
+ ctx.beginPath();
+ ctx.moveTo(200, 200);
+ ctx.lineTo(200, 1000);
+ ctx.lineTo(1000, 1000);
+ ctx.lineTo(1000, 200);
+ ctx.closePath();
+ ctx.stroke();
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 48,1 == 0,255,0,255;
+ @assert pixel 48,48 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.line.cap.valid
+ desc: Setting lineCap to valid values works
+ testing:
+ - 2d.lineCap.set
+ - 2d.lineCap.get
+ code: |
+ ctx.lineCap = 'butt'
+ @assert ctx.lineCap === 'butt';
+
+ ctx.lineCap = 'round';
+ @assert ctx.lineCap === 'round';
+
+ ctx.lineCap = 'square';
+ @assert ctx.lineCap === 'square';
+
+- name: 2d.line.cap.invalid
+ desc: Setting lineCap to invalid values is ignored
+ testing:
+ - 2d.lineCap.invalid
+ code: |
+ ctx.lineCap = 'butt'
+ @assert ctx.lineCap === 'butt';
+
+ ctx.lineCap = 'butt';
+ ctx.lineCap = 'invalid';
+ @assert ctx.lineCap === 'butt';
+
+ ctx.lineCap = 'butt';
+ ctx.lineCap = 'ROUND';
+ @assert ctx.lineCap === 'butt';
+
+ ctx.lineCap = 'butt';
+ ctx.lineCap = 'round\0';
+ @assert ctx.lineCap === 'butt';
+
+ ctx.lineCap = 'butt';
+ ctx.lineCap = 'round ';
+ @assert ctx.lineCap === 'butt';
+
+ ctx.lineCap = 'butt';
+ ctx.lineCap = "";
+ @assert ctx.lineCap === 'butt';
+
+ ctx.lineCap = 'butt';
+ ctx.lineCap = 'bevel';
+ @assert ctx.lineCap === 'butt';
+
+- name: 2d.line.join.bevel
+ desc: lineJoin 'bevel' is rendered correctly
+ testing:
+ - 2d.lineJoin.common
+ - 2d.lineJoin.bevel
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ var tol = 1; // tolerance to avoid antialiasing artifacts
+
+ ctx.lineJoin = 'bevel';
+ ctx.lineWidth = 20;
+
+ ctx.fillStyle = '#f00';
+ ctx.strokeStyle = '#0f0';
+
+ ctx.fillRect(10, 10, 20, 20);
+ ctx.fillRect(20, 20, 20, 20);
+ ctx.beginPath();
+ ctx.moveTo(30, 20);
+ ctx.lineTo(40-tol, 20);
+ ctx.lineTo(30, 10+tol);
+ ctx.fill();
+
+ ctx.beginPath();
+ ctx.moveTo(10, 20);
+ ctx.lineTo(30, 20);
+ ctx.lineTo(30, 40);
+ ctx.stroke();
+
+
+ ctx.fillStyle = '#0f0';
+ ctx.strokeStyle = '#f00';
+
+ ctx.beginPath();
+ ctx.moveTo(60, 20);
+ ctx.lineTo(80, 20);
+ ctx.lineTo(80, 40);
+ ctx.stroke();
+
+ ctx.fillRect(60, 10, 20, 20);
+ ctx.fillRect(70, 20, 20, 20);
+ ctx.beginPath();
+ ctx.moveTo(80, 20);
+ ctx.lineTo(90+tol, 20);
+ ctx.lineTo(80, 10-tol);
+ ctx.fill();
+
+ @assert pixel 34,16 == 0,255,0,255;
+ @assert pixel 34,15 == 0,255,0,255;
+ @assert pixel 35,15 == 0,255,0,255;
+ @assert pixel 36,15 == 0,255,0,255;
+ @assert pixel 36,14 == 0,255,0,255;
+
+ @assert pixel 84,16 == 0,255,0,255;
+ @assert pixel 84,15 == 0,255,0,255;
+ @assert pixel 85,15 == 0,255,0,255;
+ @assert pixel 86,15 == 0,255,0,255;
+ @assert pixel 86,14 == 0,255,0,255;
+ expected: green
+
+- name: 2d.line.join.round
+ desc: lineJoin 'round' is rendered correctly
+ testing:
+ - 2d.lineJoin.round
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ var tol = 1; // tolerance to avoid antialiasing artifacts
+
+ ctx.lineJoin = 'round';
+ ctx.lineWidth = 20;
+
+ ctx.fillStyle = '#f00';
+ ctx.strokeStyle = '#0f0';
+
+ ctx.fillRect(10, 10, 20, 20);
+ ctx.fillRect(20, 20, 20, 20);
+ ctx.beginPath();
+ ctx.moveTo(30, 20);
+ ctx.arc(30, 20, 10-tol, 0, 2*Math.PI, true);
+ ctx.fill();
+
+ ctx.beginPath();
+ ctx.moveTo(10, 20);
+ ctx.lineTo(30, 20);
+ ctx.lineTo(30, 40);
+ ctx.stroke();
+
+
+ ctx.fillStyle = '#0f0';
+ ctx.strokeStyle = '#f00';
+
+ ctx.beginPath();
+ ctx.moveTo(60, 20);
+ ctx.lineTo(80, 20);
+ ctx.lineTo(80, 40);
+ ctx.stroke();
+
+ ctx.fillRect(60, 10, 20, 20);
+ ctx.fillRect(70, 20, 20, 20);
+ ctx.beginPath();
+ ctx.moveTo(80, 20);
+ ctx.arc(80, 20, 10+tol, 0, 2*Math.PI, true);
+ ctx.fill();
+
+ @assert pixel 36,14 == 0,255,0,255;
+ @assert pixel 36,13 == 0,255,0,255;
+ @assert pixel 37,13 == 0,255,0,255;
+ @assert pixel 38,13 == 0,255,0,255;
+ @assert pixel 38,12 == 0,255,0,255;
+
+ @assert pixel 86,14 == 0,255,0,255;
+ @assert pixel 86,13 == 0,255,0,255;
+ @assert pixel 87,13 == 0,255,0,255;
+ @assert pixel 88,13 == 0,255,0,255;
+ @assert pixel 88,12 == 0,255,0,255;
+ expected: green
+
+- name: 2d.line.join.miter
+ desc: lineJoin 'miter' is rendered correctly
+ testing:
+ - 2d.lineJoin.miter
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.lineJoin = 'miter';
+ ctx.lineWidth = 20;
+
+ ctx.fillStyle = '#f00';
+ ctx.strokeStyle = '#0f0';
+
+ ctx.fillStyle = '#f00';
+ ctx.strokeStyle = '#0f0';
+
+ ctx.fillRect(10, 10, 30, 20);
+ ctx.fillRect(20, 10, 20, 30);
+
+ ctx.beginPath();
+ ctx.moveTo(10, 20);
+ ctx.lineTo(30, 20);
+ ctx.lineTo(30, 40);
+ ctx.stroke();
+
+
+ ctx.fillStyle = '#0f0';
+ ctx.strokeStyle = '#f00';
+
+ ctx.beginPath();
+ ctx.moveTo(60, 20);
+ ctx.lineTo(80, 20);
+ ctx.lineTo(80, 40);
+ ctx.stroke();
+
+ ctx.fillRect(60, 10, 30, 20);
+ ctx.fillRect(70, 10, 20, 30);
+
+ @assert pixel 38,12 == 0,255,0,255;
+ @assert pixel 39,11 == 0,255,0,255;
+ @assert pixel 40,10 == 0,255,0,255;
+ @assert pixel 41,9 == 0,255,0,255;
+ @assert pixel 42,8 == 0,255,0,255;
+
+ @assert pixel 88,12 == 0,255,0,255;
+ @assert pixel 89,11 == 0,255,0,255;
+ @assert pixel 90,10 == 0,255,0,255;
+ @assert pixel 91,9 == 0,255,0,255;
+ @assert pixel 92,8 == 0,255,0,255;
+ expected: green
+
+- name: 2d.line.join.open
+ desc: Line joins are not drawn at the corner of an unclosed rectangle
+ testing:
+ - 2d.lineJoin.joins
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.strokeStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.lineJoin = 'miter';
+ ctx.lineWidth = 200;
+
+ ctx.beginPath();
+ ctx.moveTo(100, 50);
+ ctx.lineTo(100, 1000);
+ ctx.lineTo(1000, 1000);
+ ctx.lineTo(1000, 50);
+ ctx.lineTo(100, 50);
+ ctx.stroke();
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 48,1 == 0,255,0,255;
+ @assert pixel 48,48 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.line.join.closed
+ desc: Line joins are drawn at the corner of a closed rectangle
+ testing:
+ - 2d.lineJoin.joinclosed
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.strokeStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.lineJoin = 'miter';
+ ctx.lineWidth = 200;
+
+ ctx.beginPath();
+ ctx.moveTo(100, 50);
+ ctx.lineTo(100, 1000);
+ ctx.lineTo(1000, 1000);
+ ctx.lineTo(1000, 50);
+ ctx.closePath();
+ ctx.stroke();
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 48,1 == 0,255,0,255;
+ @assert pixel 48,48 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.line.join.parallel
+ desc: Line joins are drawn at 180-degree joins
+ testing:
+ - 2d.lineJoin.joins
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.strokeStyle = '#0f0';
+ ctx.lineWidth = 300;
+ ctx.lineJoin = 'round';
+ ctx.beginPath();
+ ctx.moveTo(-100, 25);
+ ctx.lineTo(0, 25);
+ ctx.lineTo(-100, 25);
+ ctx.stroke();
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 48,1 == 0,255,0,255;
+ @assert pixel 48,48 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.line.join.valid
+ desc: Setting lineJoin to valid values works
+ testing:
+ - 2d.lineJoin.set
+ - 2d.lineJoin.get
+ code: |
+ ctx.lineJoin = 'bevel'
+ @assert ctx.lineJoin === 'bevel';
+
+ ctx.lineJoin = 'round';
+ @assert ctx.lineJoin === 'round';
+
+ ctx.lineJoin = 'miter';
+ @assert ctx.lineJoin === 'miter';
+
+- name: 2d.line.join.invalid
+ desc: Setting lineJoin to invalid values is ignored
+ testing:
+ - 2d.lineJoin.invalid
+ code: |
+ ctx.lineJoin = 'bevel'
+ @assert ctx.lineJoin === 'bevel';
+
+ ctx.lineJoin = 'bevel';
+ ctx.lineJoin = 'invalid';
+ @assert ctx.lineJoin === 'bevel';
+
+ ctx.lineJoin = 'bevel';
+ ctx.lineJoin = 'ROUND';
+ @assert ctx.lineJoin === 'bevel';
+
+ ctx.lineJoin = 'bevel';
+ ctx.lineJoin = 'round\0';
+ @assert ctx.lineJoin === 'bevel';
+
+ ctx.lineJoin = 'bevel';
+ ctx.lineJoin = 'round ';
+ @assert ctx.lineJoin === 'bevel';
+
+ ctx.lineJoin = 'bevel';
+ ctx.lineJoin = "";
+ @assert ctx.lineJoin === 'bevel';
+
+ ctx.lineJoin = 'bevel';
+ ctx.lineJoin = 'butt';
+ @assert ctx.lineJoin === 'bevel';
+
+- name: 2d.line.miter.exceeded
+ desc: Miter joins are not drawn when the miter limit is exceeded
+ testing:
+ - 2d.lineJoin.miterLimit
+ - 2d.lineJoin.miter
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.lineWidth = 400;
+ ctx.lineJoin = 'miter';
+
+ ctx.strokeStyle = '#f00';
+ ctx.miterLimit = 1.414;
+ ctx.beginPath();
+ ctx.moveTo(200, 1000);
+ ctx.lineTo(200, 200);
+ ctx.lineTo(1000, 201); // slightly non-right-angle to avoid being a special case
+ ctx.stroke();
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 48,1 == 0,255,0,255;
+ @assert pixel 48,48 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.line.miter.acute
+ desc: Miter joins are drawn correctly with acute angles
+ testing:
+ - 2d.lineJoin.miterLimit
+ - 2d.lineJoin.miter
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.lineWidth = 200;
+ ctx.lineJoin = 'miter';
+
+ ctx.strokeStyle = '#0f0';
+ ctx.miterLimit = 2.614;
+ ctx.beginPath();
+ ctx.moveTo(100, 1000);
+ ctx.lineTo(100, 100);
+ ctx.lineTo(1000, 1000);
+ ctx.stroke();
+
+ ctx.strokeStyle = '#f00';
+ ctx.miterLimit = 2.613;
+ ctx.beginPath();
+ ctx.moveTo(100, 1000);
+ ctx.lineTo(100, 100);
+ ctx.lineTo(1000, 1000);
+ ctx.stroke();
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 48,1 == 0,255,0,255;
+ @assert pixel 48,48 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.line.miter.obtuse
+ desc: Miter joins are drawn correctly with obtuse angles
+ testing:
+ - 2d.lineJoin.miterLimit
+ - 2d.lineJoin.miter
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.lineWidth = 1600;
+ ctx.lineJoin = 'miter';
+
+ ctx.strokeStyle = '#0f0';
+ ctx.miterLimit = 1.083;
+ ctx.beginPath();
+ ctx.moveTo(800, 10000);
+ ctx.lineTo(800, 300);
+ ctx.lineTo(10000, -8900);
+ ctx.stroke();
+
+ ctx.strokeStyle = '#f00';
+ ctx.miterLimit = 1.082;
+ ctx.beginPath();
+ ctx.moveTo(800, 10000);
+ ctx.lineTo(800, 300);
+ ctx.lineTo(10000, -8900);
+ ctx.stroke();
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 48,1 == 0,255,0,255;
+ @assert pixel 48,48 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.line.miter.rightangle
+ desc: Miter joins are not drawn when the miter limit is exceeded, on exact right angles
+ testing:
+ - 2d.lineJoin.miter
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.lineWidth = 400;
+ ctx.lineJoin = 'miter';
+
+ ctx.strokeStyle = '#f00';
+ ctx.miterLimit = 1.414;
+ ctx.beginPath();
+ ctx.moveTo(200, 1000);
+ ctx.lineTo(200, 200);
+ ctx.lineTo(1000, 200);
+ ctx.stroke();
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 48,1 == 0,255,0,255;
+ @assert pixel 48,48 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.line.miter.lineedge
+ desc: Miter joins are not drawn when the miter limit is exceeded at the corners of a zero-height rectangle
+ testing:
+ - 2d.lineJoin.miter
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.lineWidth = 200;
+ ctx.lineJoin = 'miter';
+
+ ctx.strokeStyle = '#f00';
+ ctx.miterLimit = 1.414;
+ ctx.beginPath();
+ ctx.strokeRect(100, 25, 200, 0);
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 48,1 == 0,255,0,255;
+ @assert pixel 48,48 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.line.miter.within
+ desc: Miter joins are drawn when the miter limit is not quite exceeded
+ testing:
+ - 2d.lineJoin.miter
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.lineWidth = 400;
+ ctx.lineJoin = 'miter';
+
+ ctx.strokeStyle = '#0f0';
+ ctx.miterLimit = 1.416;
+ ctx.beginPath();
+ ctx.moveTo(200, 1000);
+ ctx.lineTo(200, 200);
+ ctx.lineTo(1000, 201);
+ ctx.stroke();
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 48,1 == 0,255,0,255;
+ @assert pixel 48,48 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.line.miter.valid
+ desc: Setting miterLimit to valid values works
+ testing:
+ - 2d.miterLimit.set
+ - 2d.miterLimit.get
+ code: |
+ ctx.miterLimit = 1.5;
+ @assert ctx.miterLimit === 1.5;
+
+ ctx.miterLimit = "1e1";
+ @assert ctx.miterLimit === 10;
+
+ ctx.miterLimit = 1/1024;
+ @assert ctx.miterLimit === 1/1024;
+
+ ctx.miterLimit = 1000;
+ @assert ctx.miterLimit === 1000;
+
+- name: 2d.line.miter.invalid
+ desc: Setting miterLimit to invalid values is ignored
+ testing:
+ - 2d.miterLimit.invalid
+ code: |
+ ctx.miterLimit = 1.5;
+ @assert ctx.miterLimit === 1.5;
+
+ ctx.miterLimit = 1.5;
+ ctx.miterLimit = 0;
+ @assert ctx.miterLimit === 1.5;
+
+ ctx.miterLimit = 1.5;
+ ctx.miterLimit = -1;
+ @assert ctx.miterLimit === 1.5;
+
+ ctx.miterLimit = 1.5;
+ ctx.miterLimit = Infinity;
+ @assert ctx.miterLimit === 1.5;
+
+ ctx.miterLimit = 1.5;
+ ctx.miterLimit = -Infinity;
+ @assert ctx.miterLimit === 1.5;
+
+ ctx.miterLimit = 1.5;
+ ctx.miterLimit = NaN;
+ @assert ctx.miterLimit === 1.5;
+
+- name: 2d.line.cross
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.lineWidth = 200;
+ ctx.lineJoin = 'bevel';
+
+ ctx.strokeStyle = '#f00';
+ ctx.beginPath();
+ ctx.moveTo(110, 50);
+ ctx.lineTo(110, 60);
+ ctx.lineTo(100, 60);
+ ctx.stroke();
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 48,1 == 0,255,0,255;
+ @assert pixel 48,48 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.line.union
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.lineWidth = 100;
+ ctx.lineCap = 'round';
+
+ ctx.strokeStyle = '#0f0';
+ ctx.beginPath();
+ ctx.moveTo(0, 24);
+ ctx.lineTo(100, 25);
+ ctx.lineTo(0, 26);
+ ctx.closePath();
+ ctx.stroke();
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 25,1 == 0,255,0,255;
+ @assert pixel 48,1 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ @assert pixel 25,1 == 0,255,0,255;
+ @assert pixel 48,48 == 0,255,0,255;
+ expected: green
+
+
+
+
+
+
+
+- name: 2d.shadow.attributes.shadowBlur.initial
+ testing:
+ - 2d.shadow.blur.get
+ - 2d.shadow.blur.initial
+ code: |
+ @assert ctx.shadowBlur === 0;
+
+- name: 2d.shadow.attributes.shadowBlur.valid
+ testing:
+ - 2d.shadow.blur.get
+ - 2d.shadow.blur.set
+ code: |
+ ctx.shadowBlur = 1;
+ @assert ctx.shadowBlur === 1;
+
+ ctx.shadowBlur = 0.5;
+ @assert ctx.shadowBlur === 0.5;
+
+ ctx.shadowBlur = 1e6;
+ @assert ctx.shadowBlur === 1e6;
+
+ ctx.shadowBlur = 0;
+ @assert ctx.shadowBlur === 0;
+
+- name: 2d.shadow.attributes.shadowBlur.invalid
+ testing:
+ - 2d.shadow.blur.invalid
+ code: |
+ ctx.shadowBlur = 1;
+ ctx.shadowBlur = -2;
+ @assert ctx.shadowBlur === 1;
+
+ ctx.shadowBlur = 1;
+ ctx.shadowBlur = Infinity;
+ @assert ctx.shadowBlur === 1;
+
+ ctx.shadowBlur = 1;
+ ctx.shadowBlur = -Infinity;
+ @assert ctx.shadowBlur === 1;
+
+ ctx.shadowBlur = 1;
+ ctx.shadowBlur = NaN;
+ @assert ctx.shadowBlur === 1;
+
+- name: 2d.shadow.attributes.shadowOffset.initial
+ testing:
+ - 2d.shadow.offset.initial
+ code: |
+ @assert ctx.shadowOffsetX === 0;
+ @assert ctx.shadowOffsetY === 0;
+
+- name: 2d.shadow.attributes.shadowOffset.valid
+ testing:
+ - 2d.shadow.offset.get
+ - 2d.shadow.offset.set
+ code: |
+ ctx.shadowOffsetX = 1;
+ ctx.shadowOffsetY = 2;
+ @assert ctx.shadowOffsetX === 1;
+ @assert ctx.shadowOffsetY === 2;
+
+ ctx.shadowOffsetX = 0.5;
+ ctx.shadowOffsetY = 0.25;
+ @assert ctx.shadowOffsetX === 0.5;
+ @assert ctx.shadowOffsetY === 0.25;
+
+ ctx.shadowOffsetX = -0.5;
+ ctx.shadowOffsetY = -0.25;
+ @assert ctx.shadowOffsetX === -0.5;
+ @assert ctx.shadowOffsetY === -0.25;
+
+ ctx.shadowOffsetX = 0;
+ ctx.shadowOffsetY = 0;
+ @assert ctx.shadowOffsetX === 0;
+ @assert ctx.shadowOffsetY === 0;
+
+ ctx.shadowOffsetX = 1e6;
+ ctx.shadowOffsetY = 1e6;
+ @assert ctx.shadowOffsetX === 1e6;
+ @assert ctx.shadowOffsetY === 1e6;
+
+- name: 2d.shadow.attributes.shadowOffset.invalid
+ testing:
+ - 2d.shadow.offset.invalid
+ code: |
+ ctx.shadowOffsetX = 1;
+ ctx.shadowOffsetY = 2;
+ ctx.shadowOffsetX = Infinity;
+ ctx.shadowOffsetY = Infinity;
+ @assert ctx.shadowOffsetX === 1;
+ @assert ctx.shadowOffsetY === 2;
+
+ ctx.shadowOffsetX = 1;
+ ctx.shadowOffsetY = 2;
+ ctx.shadowOffsetX = -Infinity;
+ ctx.shadowOffsetY = -Infinity;
+ @assert ctx.shadowOffsetX === 1;
+ @assert ctx.shadowOffsetY === 2;
+
+ ctx.shadowOffsetX = 1;
+ ctx.shadowOffsetY = 2;
+ ctx.shadowOffsetX = NaN;
+ ctx.shadowOffsetY = NaN;
+ @assert ctx.shadowOffsetX === 1;
+ @assert ctx.shadowOffsetY === 2;
+
+- name: 2d.shadow.attributes.shadowColor.initial
+ testing:
+ - 2d.shadow.color.initial
+ code: |
+ @assert ctx.shadowColor === 'rgba(0, 0, 0, 0)';
+
+- name: 2d.shadow.attributes.shadowColor.valid
+ testing:
+ - 2d.shadow.color.get
+ - 2d.shadow.color.set
+ code: |
+ ctx.shadowColor = 'lime';
+ @assert ctx.shadowColor === '#00ff00';
+
+ ctx.shadowColor = 'RGBA(0,255, 0,0)';
+ @assert ctx.shadowColor === 'rgba(0, 255, 0, 0)';
+
+- name: 2d.shadow.attributes.shadowColor.invalid
+ testing:
+ - 2d.shadow.color.invalid
+ code: |
+ ctx.shadowColor = '#00ff00';
+ ctx.shadowColor = 'bogus';
+ @assert ctx.shadowColor === '#00ff00';
+
+ ctx.shadowColor = '#00ff00';
+ ctx.shadowColor = 'red bogus';
+ @assert ctx.shadowColor === '#00ff00';
+
+ ctx.shadowColor = '#00ff00';
+ ctx.shadowColor = ctx;
+ @assert ctx.shadowColor === '#00ff00';
+
+ ctx.shadowColor = '#00ff00';
+ ctx.shadowColor = undefined;
+ @assert ctx.shadowColor === '#00ff00';
+
+- name: 2d.shadow.enable.off.1
+ desc: Shadows are not drawn when only shadowColor is set
+ testing:
+ - 2d.shadow.enable
+ - 2d.shadow.render
+ code: |
+ ctx.shadowColor = '#f00';
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.shadow.enable.off.2
+ desc: Shadows are not drawn when only shadowColor is set
+ testing:
+ - 2d.shadow.enable
+ - 2d.shadow.render
+ code: |
+ ctx.globalCompositeOperation = 'destination-atop';
+ ctx.shadowColor = '#f00';
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.shadow.enable.blur
+ desc: Shadows are drawn if shadowBlur is set
+ testing:
+ - 2d.shadow.enable
+ - 2d.shadow.render
+ code: |
+ ctx.globalCompositeOperation = 'destination-atop';
+ ctx.shadowColor = '#0f0';
+ ctx.shadowBlur = 0.1;
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.shadow.enable.x
+ desc: Shadows are drawn if shadowOffsetX is set
+ testing:
+ - 2d.shadow.enable
+ - 2d.shadow.render
+ code: |
+ ctx.globalCompositeOperation = 'destination-atop';
+ ctx.shadowColor = '#0f0';
+ ctx.shadowOffsetX = 0.1;
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.shadow.enable.y
+ desc: Shadows are drawn if shadowOffsetY is set
+ testing:
+ - 2d.shadow.enable
+ - 2d.shadow.render
+ code: |
+ ctx.globalCompositeOperation = 'destination-atop';
+ ctx.shadowColor = '#0f0';
+ ctx.shadowOffsetY = 0.1;
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.shadow.offset.positiveX
+ desc: Shadows can be offset with positive x
+ testing:
+ - 2d.shadow.render
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.shadowColor = '#0f0';
+ ctx.shadowOffsetX = 50;
+ ctx.fillRect(0, 0, 50, 50);
+ @assert pixel 25,25 == 0,255,0,255;
+ @assert pixel 75,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.shadow.offset.negativeX
+ desc: Shadows can be offset with negative x
+ testing:
+ - 2d.shadow.render
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.shadowColor = '#0f0';
+ ctx.shadowOffsetX = -50;
+ ctx.fillRect(50, 0, 50, 50);
+ @assert pixel 25,25 == 0,255,0,255;
+ @assert pixel 75,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.shadow.offset.positiveY
+ desc: Shadows can be offset with positive y
+ testing:
+ - 2d.shadow.render
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.shadowColor = '#0f0';
+ ctx.shadowOffsetY = 25;
+ ctx.fillRect(0, 0, 100, 25);
+ @assert pixel 50,12 == 0,255,0,255;
+ @assert pixel 50,37 == 0,255,0,255;
+ expected: green
+
+- name: 2d.shadow.offset.negativeY
+ desc: Shadows can be offset with negative y
+ testing:
+ - 2d.shadow.render
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.shadowColor = '#0f0';
+ ctx.shadowOffsetY = -25;
+ ctx.fillRect(0, 25, 100, 25);
+ @assert pixel 50,12 == 0,255,0,255;
+ @assert pixel 50,37 == 0,255,0,255;
+ expected: green
+
+- name: 2d.shadow.outside
+ desc: Shadows of shapes outside the visible area can be offset onto the visible area
+ testing:
+ - 2d.shadow.render
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.shadowColor = '#0f0';
+ ctx.shadowOffsetX = 100;
+ ctx.fillRect(-100, 0, 25, 50);
+ ctx.shadowOffsetX = -100;
+ ctx.fillRect(175, 0, 25, 50);
+ ctx.shadowOffsetX = 0;
+ ctx.shadowOffsetY = 100;
+ ctx.fillRect(25, -100, 50, 25);
+ ctx.shadowOffsetY = -100;
+ ctx.fillRect(25, 125, 50, 25);
+ @assert pixel 12,25 == 0,255,0,255;
+ @assert pixel 87,25 == 0,255,0,255;
+ @assert pixel 50,12 == 0,255,0,255;
+ @assert pixel 50,37 == 0,255,0,255;
+ expected: green
+
+- name: 2d.shadow.clip.1
+ desc: Shadows of clipped shapes are still drawn within the clipping region
+ testing:
+ - 2d.shadow.render
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 50, 50);
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(50, 0, 50, 50);
+
+ ctx.save();
+ ctx.beginPath();
+ ctx.rect(50, 0, 50, 50);
+ ctx.clip();
+ ctx.shadowColor = '#0f0';
+ ctx.shadowOffsetX = 50;
+ ctx.fillRect(0, 0, 50, 50);
+ ctx.restore();
+
+ @assert pixel 25,25 == 0,255,0,255;
+ @assert pixel 75,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.shadow.clip.2
+ desc: Shadows are not drawn outside the clipping region
+ testing:
+ - 2d.shadow.render
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 50, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(50, 0, 50, 50);
+
+ ctx.save();
+ ctx.beginPath();
+ ctx.rect(0, 0, 50, 50);
+ ctx.clip();
+ ctx.shadowColor = '#f00';
+ ctx.shadowOffsetX = 50;
+ ctx.fillRect(0, 0, 50, 50);
+ ctx.restore();
+
+ @assert pixel 25,25 == 0,255,0,255;
+ @assert pixel 75,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.shadow.clip.3
+ desc: Shadows of clipped shapes are still drawn within the clipping region
+ testing:
+ - 2d.shadow.render
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 50, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(50, 0, 50, 50);
+
+ ctx.save();
+ ctx.beginPath();
+ ctx.rect(0, 0, 50, 50);
+ ctx.clip();
+ ctx.fillStyle = '#f00';
+ ctx.shadowColor = '#0f0';
+ ctx.shadowOffsetX = 50;
+ ctx.fillRect(-50, 0, 50, 50);
+ ctx.restore();
+
+ @assert pixel 25,25 == 0,255,0,255;
+ @assert pixel 75,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.shadow.stroke.basic
+ desc: Shadows are drawn for strokes
+ testing:
+ - 2d.shadow.render
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.strokeStyle = '#f00';
+ ctx.shadowColor = '#0f0';
+ ctx.shadowOffsetY = 50;
+ ctx.beginPath();
+ ctx.lineWidth = 50;
+ ctx.moveTo(0, -25);
+ ctx.lineTo(100, -25);
+ ctx.stroke();
+
+ @assert pixel 1,25 == 0,255,0,255;
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 98,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.shadow.stroke.cap.1
+ desc: Shadows are not drawn for areas outside stroke caps
+ testing:
+ - 2d.shadow.render
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.strokeStyle = '#f00';
+ ctx.shadowColor = '#f00';
+ ctx.shadowOffsetY = 50;
+ ctx.beginPath();
+ ctx.lineWidth = 50;
+ ctx.lineCap = 'butt';
+ ctx.moveTo(-50, -25);
+ ctx.lineTo(0, -25);
+ ctx.moveTo(100, -25);
+ ctx.lineTo(150, -25);
+ ctx.stroke();
+
+ @assert pixel 1,25 == 0,255,0,255;
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 98,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.shadow.stroke.cap.2
+ desc: Shadows are drawn for stroke caps
+ testing:
+ - 2d.shadow.render
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.strokeStyle = '#f00';
+ ctx.shadowColor = '#0f0';
+ ctx.shadowOffsetY = 50;
+ ctx.beginPath();
+ ctx.lineWidth = 50;
+ ctx.lineCap = 'square';
+ ctx.moveTo(25, -25);
+ ctx.lineTo(75, -25);
+ ctx.stroke();
+
+ @assert pixel 1,25 == 0,255,0,255;
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 98,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.shadow.stroke.join.1
+ desc: Shadows are not drawn for areas outside stroke joins
+ testing:
+ - 2d.shadow.render
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.strokeStyle = '#f00';
+ ctx.shadowColor = '#f00';
+ ctx.shadowOffsetX = 100;
+ ctx.lineWidth = 200;
+ ctx.lineJoin = 'bevel';
+ ctx.beginPath();
+ ctx.moveTo(-200, -50);
+ ctx.lineTo(-150, -50);
+ ctx.lineTo(-151, -100);
+ ctx.stroke();
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 48,48 == 0,255,0,255;
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 98,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.shadow.stroke.join.2
+ desc: Shadows are drawn for stroke joins
+ testing:
+ - 2d.shadow.render
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 50, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(50, 0, 50, 50);
+ ctx.strokeStyle = '#f00';
+ ctx.shadowColor = '#0f0';
+ ctx.shadowOffsetX = 100;
+ ctx.lineWidth = 200;
+ ctx.lineJoin = 'miter';
+ ctx.beginPath();
+ ctx.moveTo(-200, -50);
+ ctx.lineTo(-150, -50);
+ ctx.lineTo(-151, -100);
+ ctx.stroke();
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 48,48 == 0,255,0,255;
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 98,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.shadow.stroke.join.3
+ desc: Shadows are drawn for stroke joins respecting miter limit
+ testing:
+ - 2d.shadow.render
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.strokeStyle = '#f00';
+ ctx.shadowColor = '#f00';
+ ctx.shadowOffsetX = 100;
+ ctx.lineWidth = 200;
+ ctx.lineJoin = 'miter';
+ ctx.miterLimit = 0.1;
+ ctx.beginPath();
+ ctx.moveTo(-200, -50);
+ ctx.lineTo(-150, -50);
+ ctx.lineTo(-151, -100); // (not an exact right angle, to avoid some other bug in Firefox 3)
+ ctx.stroke();
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 48,48 == 0,255,0,255;
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 98,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.shadow.image.basic
+ desc: Shadows are drawn for images
+ testing:
+ - 2d.shadow.render
+ images:
+ - red.png
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.shadowColor = '#0f0';
+ ctx.shadowOffsetY = 50;
+ ctx.drawImage(document.getElementById('red.png'), 0, -50);
+
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.shadow.image.transparent.1
+ desc: Shadows are not drawn for transparent images
+ testing:
+ - 2d.shadow.render
+ images:
+ - transparent.png
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.shadowColor = '#f00';
+ ctx.shadowOffsetY = 50;
+ ctx.drawImage(document.getElementById('transparent.png'), 0, -50);
+
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.shadow.image.transparent.2
+ desc: Shadows are not drawn for transparent parts of images
+ testing:
+ - 2d.shadow.render
+ images:
+ - redtransparent.png
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 50, 50);
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(50, 0, 50, 50);
+ ctx.shadowOffsetY = 50;
+ ctx.shadowColor = '#0f0';
+ ctx.drawImage(document.getElementById('redtransparent.png'), 50, -50);
+ ctx.shadowColor = '#f00';
+ ctx.drawImage(document.getElementById('redtransparent.png'), -50, -50);
+
+ @assert pixel 25,25 == 0,255,0,255;
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 75,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.shadow.image.alpha
+ desc: Shadows are drawn correctly for partially-transparent images
+ testing:
+ - 2d.shadow.render
+ images:
+ - transparent50.png
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.shadowOffsetY = 50;
+ ctx.shadowColor = '#00f';
+ ctx.drawImage(document.getElementById('transparent50.png'), 0, -50);
+
+ @assert pixel 50,25 ==~ 127,0,127,255;
+ expected: |
+ size 100 50
+ cr.set_source_rgb(0.5, 0, 0.5)
+ cr.rectangle(0, 0, 100, 50)
+ cr.fill()
+
+- name: 2d.shadow.image.section
+ desc: Shadows are not drawn for areas outside image source rectangles
+ testing:
+ - 2d.shadow.render
+ images:
+ - redtransparent.png
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.shadowOffsetY = 50;
+ ctx.shadowColor = '#f00';
+ ctx.drawImage(document.getElementById('redtransparent.png'), 50, 0, 50, 50, 0, -50, 50, 50);
+
+ @assert pixel 25,25 ==~ 0,255,0,255;
+ @assert pixel 50,25 ==~ 0,255,0,255;
+ @assert pixel 75,25 ==~ 0,255,0,255;
+ expected: green
+
+- name: 2d.shadow.image.scale
+ desc: Shadows are drawn correctly for scaled images
+ testing:
+ - 2d.shadow.render
+ images:
+ - redtransparent.png
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.shadowOffsetY = 50;
+ ctx.shadowColor = '#0f0';
+ ctx.drawImage(document.getElementById('redtransparent.png'), 0, 0, 100, 50, -10, -50, 240, 50);
+
+ @assert pixel 25,25 ==~ 0,255,0,255;
+ @assert pixel 50,25 ==~ 0,255,0,255;
+ @assert pixel 75,25 ==~ 0,255,0,255;
+ expected: green
+
+- name: 2d.shadow.canvas.basic
+ desc: Shadows are drawn for canvases
+ testing:
+ - 2d.shadow.render
+ code: |
+ var canvas2 = document.createElement('canvas');
+ canvas2.width = 100;
+ canvas2.height = 50;
+ var ctx2 = canvas2.getContext('2d');
+ ctx2.fillStyle = '#f00';
+ ctx2.fillRect(0, 0, 100, 50);
+
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.shadowColor = '#0f0';
+ ctx.shadowOffsetY = 50;
+ ctx.drawImage(canvas2, 0, -50);
+
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.shadow.canvas.transparent.1
+ desc: Shadows are not drawn for transparent canvases
+ testing:
+ - 2d.shadow.render
+ code: |
+ var canvas2 = document.createElement('canvas');
+ canvas2.width = 100;
+ canvas2.height = 50;
+ var ctx2 = canvas2.getContext('2d');
+
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.shadowColor = '#f00';
+ ctx.shadowOffsetY = 50;
+ ctx.drawImage(canvas2, 0, -50);
+
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.shadow.canvas.transparent.2
+ desc: Shadows are not drawn for transparent parts of canvases
+ testing:
+ - 2d.shadow.render
+ code: |
+ var canvas2 = document.createElement('canvas');
+ canvas2.width = 100;
+ canvas2.height = 50;
+ var ctx2 = canvas2.getContext('2d');
+ ctx2.fillStyle = '#f00';
+ ctx2.fillRect(0, 0, 50, 50);
+
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 50, 50);
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(50, 0, 50, 50);
+ ctx.shadowOffsetY = 50;
+ ctx.shadowColor = '#0f0';
+ ctx.drawImage(canvas2, 50, -50);
+ ctx.shadowColor = '#f00';
+ ctx.drawImage(canvas2, -50, -50);
+
+ @assert pixel 25,25 == 0,255,0,255;
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 75,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.shadow.canvas.alpha
+ desc: Shadows are drawn correctly for partially-transparent canvases
+ testing:
+ - 2d.shadow.render
+ images:
+ - transparent50.png
+ code: |
+ var canvas2 = document.createElement('canvas');
+ canvas2.width = 100;
+ canvas2.height = 50;
+ var ctx2 = canvas2.getContext('2d');
+ ctx2.fillStyle = 'rgba(255, 0, 0, 0.5)';
+ ctx2.fillRect(0, 0, 100, 50);
+
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.shadowOffsetY = 50;
+ ctx.shadowColor = '#00f';
+ ctx.drawImage(canvas2, 0, -50);
+
+ @assert pixel 50,25 ==~ 127,0,127,255;
+ expected: |
+ size 100 50
+ cr.set_source_rgb(0.5, 0, 0.5)
+ cr.rectangle(0, 0, 100, 50)
+ cr.fill()
+
+- name: 2d.shadow.pattern.basic
+ desc: Shadows are drawn for fill patterns
+ testing:
+ - 2d.shadow.render
+ # http://bugs.webkit.org/show_bug.cgi?id=15266
+ images:
+ - red.png
+ code: |
+ var pattern = ctx.createPattern(document.getElementById('red.png'), 'repeat');
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.shadowColor = '#0f0';
+ ctx.shadowOffsetY = 50;
+ ctx.fillStyle = pattern;
+ ctx.fillRect(0, -50, 100, 50);
+
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.shadow.pattern.transparent.1
+ desc: Shadows are not drawn for transparent fill patterns
+ testing:
+ - 2d.shadow.render
+ # http://bugs.webkit.org/show_bug.cgi?id=15266
+ images:
+ - transparent.png
+ code: |
+ var pattern = ctx.createPattern(document.getElementById('transparent.png'), 'repeat');
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.shadowColor = '#f00';
+ ctx.shadowOffsetY = 50;
+ ctx.fillStyle = pattern;
+ ctx.fillRect(0, -50, 100, 50);
+
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.shadow.pattern.transparent.2
+ desc: Shadows are not drawn for transparent parts of fill patterns
+ testing:
+ - 2d.shadow.render
+ # http://bugs.webkit.org/show_bug.cgi?id=15266
+ images:
+ - redtransparent.png
+ code: |
+ var pattern = ctx.createPattern(document.getElementById('redtransparent.png'), 'repeat');
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 50, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(50, 0, 50, 50);
+ ctx.shadowOffsetY = 50;
+ ctx.shadowColor = '#0f0';
+ ctx.fillStyle = pattern;
+ ctx.fillRect(0, -50, 100, 50);
+
+ @assert pixel 25,25 == 0,255,0,255;
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 75,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.shadow.pattern.alpha
+ desc: Shadows are drawn correctly for partially-transparent fill patterns
+ testing:
+ - 2d.shadow.render
+ # http://bugs.webkit.org/show_bug.cgi?id=15266
+ images:
+ - transparent50.png
+ code: |
+ var pattern = ctx.createPattern(document.getElementById('transparent50.png'), 'repeat');
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.shadowOffsetY = 50;
+ ctx.shadowColor = '#00f';
+ ctx.fillStyle = pattern;
+ ctx.fillRect(0, -50, 100, 50);
+
+ @assert pixel 50,25 ==~ 127,0,127,255;
+ expected: |
+ size 100 50
+ cr.set_source_rgb(0.5, 0, 0.5)
+ cr.rectangle(0, 0, 100, 50)
+ cr.fill()
+
+- name: 2d.shadow.gradient.basic
+ desc: Shadows are drawn for gradient fills
+ testing:
+ - 2d.shadow.render
+ # http://bugs.webkit.org/show_bug.cgi?id=15266
+ code: |
+ var gradient = ctx.createLinearGradient(0, 0, 100, 0);
+ gradient.addColorStop(0, '#f00');
+ gradient.addColorStop(1, '#f00');
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.shadowColor = '#0f0';
+ ctx.shadowOffsetY = 50;
+ ctx.fillStyle = gradient;
+ ctx.fillRect(0, -50, 100, 50);
+
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.shadow.gradient.transparent.1
+ desc: Shadows are not drawn for transparent gradient fills
+ testing:
+ - 2d.shadow.render
+ # http://bugs.webkit.org/show_bug.cgi?id=15266
+ code: |
+ var gradient = ctx.createLinearGradient(0, 0, 100, 0);
+ gradient.addColorStop(0, 'rgba(0,0,0,0)');
+ gradient.addColorStop(1, 'rgba(0,0,0,0)');
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.shadowColor = '#f00';
+ ctx.shadowOffsetY = 50;
+ ctx.fillStyle = gradient;
+ ctx.fillRect(0, -50, 100, 50);
+
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.shadow.gradient.transparent.2
+ desc: Shadows are not drawn for transparent parts of gradient fills
+ testing:
+ - 2d.shadow.render
+ # http://bugs.webkit.org/show_bug.cgi?id=15266
+ code: |
+ var gradient = ctx.createLinearGradient(0, 0, 100, 0);
+ gradient.addColorStop(0, '#f00');
+ gradient.addColorStop(0.499, '#f00');
+ gradient.addColorStop(0.5, 'rgba(0,0,0,0)');
+ gradient.addColorStop(1, 'rgba(0,0,0,0)');
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 50, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(50, 0, 50, 50);
+ ctx.shadowOffsetY = 50;
+ ctx.shadowColor = '#0f0';
+ ctx.fillStyle = gradient;
+ ctx.fillRect(0, -50, 100, 50);
+
+ @assert pixel 25,25 == 0,255,0,255;
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 75,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.shadow.gradient.alpha
+ desc: Shadows are drawn correctly for partially-transparent gradient fills
+ testing:
+ - 2d.shadow.render
+ # http://bugs.webkit.org/show_bug.cgi?id=15266
+ code: |
+ var gradient = ctx.createLinearGradient(0, 0, 100, 0);
+ gradient.addColorStop(0, 'rgba(255,0,0,0.5)');
+ gradient.addColorStop(1, 'rgba(255,0,0,0.5)');
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.shadowOffsetY = 50;
+ ctx.shadowColor = '#00f';
+ ctx.fillStyle = gradient;
+ ctx.fillRect(0, -50, 100, 50);
+
+ @assert pixel 50,25 ==~ 127,0,127,255;
+ expected: |
+ size 100 50
+ cr.set_source_rgb(0.5, 0, 0.5)
+ cr.rectangle(0, 0, 100, 50)
+ cr.fill()
+
+- name: 2d.shadow.transform.1
+ desc: Shadows take account of transformations
+ testing:
+ - 2d.shadow.render
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.shadowOffsetY = 50;
+ ctx.shadowColor = '#0f0';
+ ctx.translate(100, 100);
+ ctx.fillRect(-100, -150, 100, 50);
+
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.shadow.transform.2
+ desc: Shadow offsets are not affected by transformations
+ testing:
+ - 2d.shadow.render
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.shadowOffsetY = 50;
+ ctx.shadowColor = '#0f0';
+ ctx.rotate(Math.PI)
+ ctx.fillRect(-100, 0, 100, 50);
+
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.shadow.blur.low
+ desc: Shadows look correct for small blurs
+ manual:
+ testing:
+ - 2d.shadow.render
+ code: |
+ ctx.fillStyle = '#ff0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.shadowColor = '#00f';
+ ctx.shadowOffsetY = 25;
+ for (var x = 0; x < 100; ++x) {
+ ctx.save();
+ ctx.beginPath();
+ ctx.rect(x, 0, 1, 50);
+ ctx.clip();
+ ctx.shadowBlur = x;
+ ctx.fillRect(-200, -200, 500, 200);
+ ctx.restore();
+ }
+ expected: |
+ size 100 50
+ import math
+ cr.set_source_rgb(0, 0, 1)
+ cr.rectangle(0, 0, 1, 25)
+ cr.fill()
+ cr.set_source_rgb(1, 1, 0)
+ cr.rectangle(0, 25, 1, 25)
+ cr.fill()
+ for x in range(1, 100):
+ sigma = x/2.0
+ filter = [math.exp(-i*i / (2*sigma*sigma)) / (math.sqrt(2*math.pi)*sigma) for i in range(-24, 26)]
+ accum = [0]
+ for f in filter:
+ accum.append(accum[-1] + f)
+ for y in range(0, 50):
+ cr.set_source_rgb(accum[y], accum[y], 1-accum[y])
+ cr.rectangle(x, y, 1, 1)
+ cr.fill()
+
+- name: 2d.shadow.blur.high
+ desc: Shadows look correct for large blurs
+ manual:
+ testing:
+ - 2d.shadow.render
+ code: |
+ ctx.fillStyle = '#ff0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.shadowColor = '#00f';
+ ctx.shadowOffsetY = 0;
+ ctx.shadowBlur = 100;
+ ctx.fillRect(-200, -200, 200, 400);
+ expected: |
+ size 100 50
+ import math
+ sigma = 100.0/2
+ filter = [math.exp(-i*i / (2*sigma*sigma)) / (math.sqrt(2*math.pi)*sigma) for i in range(-200, 100)]
+ accum = [0]
+ for f in filter:
+ accum.append(accum[-1] + f)
+ for x in range(0, 100):
+ cr.set_source_rgb(accum[x+200], accum[x+200], 1-accum[x+200])
+ cr.rectangle(x, 0, 1, 50)
+ cr.fill()
+
+- name: 2d.shadow.alpha.1
+ desc: Shadow colour alpha components are used
+ testing:
+ - 2d.shadow.render
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.shadowColor = 'rgba(255, 0, 0, 0.01)';
+ ctx.shadowOffsetY = 50;
+ ctx.fillRect(0, -50, 100, 50);
+
+ @assert pixel 50,25 ==~ 0,255,0,255 +/- 4;
+ expected: green
+
+- name: 2d.shadow.alpha.2
+ desc: Shadow colour alpha components are used
+ testing:
+ - 2d.shadow.render
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.shadowColor = 'rgba(0, 0, 255, 0.5)';
+ ctx.shadowOffsetY = 50;
+ ctx.fillRect(0, -50, 100, 50);
+
+ @assert pixel 50,25 ==~ 127,0,127,255;
+ expected: |
+ size 100 50
+ cr.set_source_rgb(0.5, 0, 0.5)
+ cr.rectangle(0, 0, 100, 50)
+ cr.fill()
+
+- name: 2d.shadow.alpha.3
+ desc: Shadows are affected by globalAlpha
+ testing:
+ - 2d.shadow.render
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#f00'; // (work around broken Firefox globalAlpha caching)
+ ctx.shadowColor = '#00f';
+ ctx.shadowOffsetY = 50;
+ ctx.globalAlpha = 0.5;
+ ctx.fillRect(0, -50, 100, 50);
+
+ @assert pixel 50,25 ==~ 127,0,127,255;
+ expected: |
+ size 100 50
+ cr.set_source_rgb(0.5, 0, 0.5)
+ cr.rectangle(0, 0, 100, 50)
+ cr.fill()
+
+- name: 2d.shadow.alpha.4
+ desc: Shadows with alpha components are correctly affected by globalAlpha
+ testing:
+ - 2d.shadow.render
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#f00'; // (work around broken Firefox globalAlpha caching)
+ ctx.shadowColor = 'rgba(0, 0, 255, 0.707)';
+ ctx.shadowOffsetY = 50;
+ ctx.globalAlpha = 0.707;
+ ctx.fillRect(0, -50, 100, 50);
+
+ @assert pixel 50,25 ==~ 127,0,127,255;
+ expected: |
+ size 100 50
+ cr.set_source_rgb(0.5, 0, 0.5)
+ cr.rectangle(0, 0, 100, 50)
+ cr.fill()
+
+- name: 2d.shadow.alpha.5
+ desc: Shadows of shapes with alpha components are drawn correctly
+ testing:
+ - 2d.shadow.render
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = 'rgba(64, 0, 0, 0.5)';
+ ctx.shadowColor = '#00f';
+ ctx.shadowOffsetY = 50;
+ ctx.fillRect(0, -50, 100, 50);
+
+ @assert pixel 50,25 ==~ 127,0,127,255;
+ expected: |
+ size 100 50
+ cr.set_source_rgb(0.5, 0, 0.5)
+ cr.rectangle(0, 0, 100, 50)
+ cr.fill()
+
+- name: 2d.shadow.composite.1
+ desc: Shadows are drawn using globalCompositeOperation
+ testing:
+ - 2d.shadow.render
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.globalCompositeOperation = 'xor';
+ ctx.shadowColor = '#f00';
+ ctx.shadowOffsetX = 100;
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(-100, 0, 200, 50);
+
+ @assert pixel 50,25 ==~ 0,255,0,255;
+ expected: green
+
+- name: 2d.shadow.composite.2
+ desc: Shadows are drawn using globalCompositeOperation
+ testing:
+ - 2d.shadow.render
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.globalCompositeOperation = 'xor';
+ ctx.shadowColor = '#f00';
+ ctx.shadowBlur = 1;
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(-10, -10, 120, 70);
+
+ @assert pixel 50,25 ==~ 0,255,0,255;
+ expected: green
+
+- name: 2d.shadow.composite.3
+ desc: Areas outside shadows are drawn correctly with destination-out
+ testing:
+ - 2d.shadow.render
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.globalCompositeOperation = 'destination-out';
+ ctx.shadowColor = '#f00';
+ ctx.shadowBlur = 10;
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(200, 0, 100, 50);
+
+ @assert pixel 5,5 ==~ 0,255,0,255;
+ @assert pixel 50,25 ==~ 0,255,0,255;
+ expected: green
+
+
+
+
+
+
+- name: 2d.clearRect.basic
+ desc: clearRect clears to transparent black
+ testing:
+ - 2d.clearRect
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.clearRect(0, 0, 100, 50);
+ @assert pixel 50,25 == 0,0,0,0;
+ expected: clear
+
+- name: 2d.clearRect.path
+ desc: clearRect does not affect the current path
+ testing:
+ - 2d.clearRect
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.beginPath();
+ ctx.rect(0, 0, 100, 50);
+ ctx.clearRect(0, 0, 16, 16);
+ ctx.fill();
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.clearRect.zero
+ desc: clearRect of zero pixels has no effect
+ testing:
+ - 2d.clearRect
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.clearRect(0, 0, 100, 0);
+ ctx.clearRect(0, 0, 0, 50);
+ ctx.clearRect(0, 0, 0, 0);
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.clearRect.negative
+ desc: clearRect of negative sizes works
+ testing:
+ - 2d.clearRect
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.clearRect(0, 0, 50, 25);
+ ctx.clearRect(100, 0, -50, 25);
+ ctx.clearRect(0, 50, 50, -25);
+ ctx.clearRect(100, 50, -50, -25);
+ @assert pixel 25,12 == 0,0,0,0;
+ @assert pixel 75,12 == 0,0,0,0;
+ @assert pixel 25,37 == 0,0,0,0;
+ @assert pixel 75,37 == 0,0,0,0;
+ expected: clear
+
+- name: 2d.clearRect.transform
+ desc: clearRect is affected by transforms
+ testing:
+ - 2d.clearRect
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.scale(10, 10);
+ ctx.translate(0, 5);
+ ctx.clearRect(0, -5, 10, 5);
+ @assert pixel 50,25 == 0,0,0,0;
+ expected: clear
+
+- name: 2d.clearRect.globalalpha
+ desc: clearRect is not affected by globalAlpha
+ testing:
+ - 2d.clearRect
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.globalAlpha = 0.1;
+ ctx.clearRect(0, 0, 100, 50);
+ @assert pixel 50,25 == 0,0,0,0;
+ expected: clear
+
+- name: 2d.clearRect.globalcomposite
+ desc: clearRect is not affected by globalCompositeOperation
+ testing:
+ - 2d.clearRect
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.globalCompositeOperation = 'destination-atop';
+ ctx.clearRect(0, 0, 100, 50);
+ @assert pixel 50,25 == 0,0,0,0;
+ expected: clear
+
+- name: 2d.clearRect.clip
+ desc: clearRect is affected by clipping regions
+ testing:
+ - 2d.clearRect
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.beginPath();
+ ctx.rect(0, 0, 16, 16);
+ ctx.clip();
+
+ ctx.clearRect(0, 0, 100, 50);
+
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 16, 16);
+
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.clearRect.shadow
+ desc: clearRect does not draw shadows
+ testing:
+ - 2d.clearRect
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.shadowColor = '#f00';
+ ctx.shadowBlur = 0;
+ ctx.shadowOffsetX = 0;
+ ctx.shadowOffsetY = 50;
+ ctx.clearRect(0, -50, 100, 50);
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.clearRect.nonfinite
+ desc: clearRect() with Infinity/NaN is ignored
+ testing:
+ - 2d.nonfinite
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ @nonfinite ctx.clearRect(<0 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>, <100 Infinity -Infinity NaN>, <50 Infinity -Infinity NaN>);
+
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+
+- name: 2d.fillRect.basic
+ desc: fillRect works
+ testing:
+ - 2d.fillRect
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.fillRect.path
+ desc: fillRect does not affect the current path
+ testing:
+ - 2d.fillRect
+ code: |
+ ctx.beginPath();
+ ctx.rect(0, 0, 100, 50);
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 16, 16);
+ ctx.fillStyle = '#0f0';
+ ctx.fill();
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.fillRect.zero
+ desc: fillRect of zero pixels has no effect
+ testing:
+ - 2d.fillRect
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 0);
+ ctx.fillRect(0, 0, 0, 50);
+ ctx.fillRect(0, 0, 0, 0);
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.fillRect.negative
+ desc: fillRect of negative sizes works
+ testing:
+ - 2d.fillRect
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 50, 25);
+ ctx.fillRect(100, 0, -50, 25);
+ ctx.fillRect(0, 50, 50, -25);
+ ctx.fillRect(100, 50, -50, -25);
+ @assert pixel 25,12 == 0,255,0,255;
+ @assert pixel 75,12 == 0,255,0,255;
+ @assert pixel 25,37 == 0,255,0,255;
+ @assert pixel 75,37 == 0,255,0,255;
+ expected: green
+
+- name: 2d.fillRect.transform
+ desc: fillRect is affected by transforms
+ testing:
+ - 2d.fillRect
+ code: |
+ ctx.scale(10, 10);
+ ctx.translate(0, 5);
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, -5, 10, 5);
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+# don't bother testing globalalpha, globalcomposite because they're already heavily used by other test cases
+
+- name: 2d.fillRect.clip
+ desc: fillRect is affected by clipping regions
+ testing:
+ - 2d.fillRect
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.beginPath();
+ ctx.rect(0, 0, 16, 16);
+ ctx.clip();
+
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 16, 16);
+
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.fillRect.shadow
+ desc: fillRect draws shadows
+ testing:
+ - 2d.fillRect
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.shadowColor = '#0f0';
+ ctx.shadowBlur = 0;
+ ctx.shadowOffsetX = 0;
+ ctx.shadowOffsetY = 50;
+ ctx.fillRect(0, -50, 100, 50);
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.fillRect.nonfinite
+ desc: fillRect() with Infinity/NaN is ignored
+ testing:
+ - 2d.nonfinite
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.fillStyle = '#f00';
+ @nonfinite ctx.fillRect(<0 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>, <100 Infinity -Infinity NaN>, <50 Infinity -Infinity NaN>);
+
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+
+- name: 2d.strokeRect.basic
+ desc: strokeRect works
+ testing:
+ - 2d.strokeRect
+ code: |
+ ctx.strokeStyle = '#0f0';
+ ctx.lineWidth = 50;
+ ctx.strokeRect(25, 24, 50, 2);
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.strokeRect.path
+ desc: strokeRect does not affect the current path
+ testing:
+ - 2d.strokeRect
+ code: |
+ ctx.beginPath();
+ ctx.rect(0, 0, 100, 50);
+ ctx.strokeStyle = '#f00';
+ ctx.lineWidth = 5;
+ ctx.strokeRect(0, 0, 16, 16);
+ ctx.fillStyle = '#0f0';
+ ctx.fill();
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.strokeRect.zero.1
+ desc: strokeRect of 0x0 pixels draws nothing
+ testing:
+ - 2d.strokeRect
+ code: |
+ ctx.strokeStyle = '#f00';
+ ctx.lineWidth = 250;
+ ctx.strokeRect(50, 25, 0, 0);
+ @assert pixel 50,25 == 0,0,0,0;
+ expected: clear
+
+- name: 2d.strokeRect.zero.2
+ desc: strokeRect of 0x0 pixels draws nothing, including caps and joins
+ testing:
+ - 2d.strokeRect
+ code: |
+ ctx.strokeStyle = '#f00';
+ ctx.lineWidth = 250;
+ ctx.lineCap = 'round';
+ ctx.lineJoin = 'round';
+ ctx.strokeRect(50, 25, 0, 0);
+ @assert pixel 50,25 == 0,0,0,0;
+ expected: clear
+
+- name: 2d.strokeRect.zero.3
+ desc: strokeRect of Nx0 pixels draws a straight line
+ testing:
+ - 2d.strokeRect
+ code: |
+ ctx.strokeStyle = '#0f0';
+ ctx.lineWidth = 50;
+ ctx.strokeRect(0, 25, 100, 0);
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.strokeRect.zero.4
+ desc: strokeRect of Nx0 pixels draws a closed line with no caps
+ testing:
+ - 2d.strokeRect
+ code: |
+ ctx.strokeStyle = '#f00';
+ ctx.lineWidth = 250;
+ ctx.lineCap = 'round';
+ ctx.strokeRect(100, 25, 100, 0);
+ @assert pixel 50,25 == 0,0,0,0;
+ expected: clear
+
+- name: 2d.strokeRect.zero.5
+ desc: strokeRect of Nx0 pixels draws a closed line with joins
+ testing:
+ - 2d.strokeRect
+ code: |
+ ctx.strokeStyle = '#0f0';
+ ctx.lineWidth = 250;
+ ctx.lineJoin = 'round';
+ ctx.strokeRect(100, 25, 100, 0);
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.strokeRect.negative
+ desc: strokeRect of negative sizes works
+ testing:
+ - 2d.strokeRect
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.strokeStyle = '#0f0';
+ ctx.lineWidth = 25;
+ ctx.strokeRect(12, 12, 26, 1);
+ ctx.strokeRect(88, 12, -26, 1);
+ ctx.strokeRect(12, 38, 26, -1);
+ ctx.strokeRect(88, 38, -26, -1);
+ @assert pixel 25,12 == 0,255,0,255;
+ @assert pixel 75,12 == 0,255,0,255;
+ @assert pixel 25,37 == 0,255,0,255;
+ @assert pixel 75,37 == 0,255,0,255;
+ expected: green
+
+- name: 2d.strokeRect.transform
+ desc: fillRect is affected by transforms
+ testing:
+ - 2d.strokeRect
+ code: |
+ ctx.scale(10, 10);
+ ctx.translate(0, 5);
+ ctx.strokeStyle = '#0f0';
+ ctx.lineWidth = 5;
+ ctx.strokeRect(2.5, -2.6, 5, 0.2);
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.strokeRect.globalalpha
+ desc: strokeRect is affected by globalAlpha
+ testing:
+ - 2d.strokeRect
+ code: |
+ ctx.globalAlpha = 0;
+ ctx.strokeStyle = '#f00';
+ ctx.lineWidth = 50;
+ ctx.strokeRect(25, 24, 50, 2);
+ @assert pixel 50,25 == 0,0,0,0;
+ expected: clear
+
+- name: 2d.strokeRect.globalcomposite
+ desc: strokeRect is not affected by globalCompositeOperation
+ testing:
+ - 2d.strokeRect
+ code: |
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.strokeStyle = '#f00';
+ ctx.lineWidth = 50;
+ ctx.strokeRect(25, 24, 50, 2);
+ @assert pixel 50,25 == 0,0,0,0;
+ expected: clear
+
+- name: 2d.strokeRect.clip
+ desc: strokeRect is affected by clipping regions
+ testing:
+ - 2d.strokeRect
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.beginPath();
+ ctx.rect(0, 0, 16, 16);
+ ctx.clip();
+
+ ctx.strokeStyle = '#f00';
+ ctx.lineWidth = 50;
+ ctx.strokeRect(0, 0, 100, 50);
+
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 16, 16);
+
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.strokeRect.shadow
+ desc: strokeRect draws shadows
+ testing:
+ - 2d.strokeRect
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#f00';
+ ctx.shadowColor = '#0f0';
+ ctx.shadowBlur = 0;
+ ctx.shadowOffsetX = 0;
+ ctx.shadowOffsetY = 50;
+ ctx.strokeStyle = '#f00';
+ ctx.lineWidth = 50;
+ ctx.strokeRect(0, -75, 100, 50);
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.strokeRect.nonfinite
+ desc: strokeRect() with Infinity/NaN is ignored
+ testing:
+ - 2d.nonfinite
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.strokeStyle = '#f00';
+ ctx.lineWidth = 150;
+ @nonfinite ctx.strokeRect(<0 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>, <100 Infinity -Infinity NaN>, <50 Infinity -Infinity NaN>);
+
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+
+- name: 2d.path.initial
+ testing:
+ - 2d.path.initial
+ #mozilla: { bug: TODO }
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.closePath();
+ ctx.fillStyle = '#f00';
+ ctx.fill();
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.beginPath
+ testing:
+ - 2d.path.beginPath
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.rect(0, 0, 100, 50);
+ ctx.beginPath();
+ ctx.fillStyle = '#f00';
+ ctx.fill();
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.moveTo.basic
+ testing:
+ - 2d.path.moveTo
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.rect(0, 0, 10, 50);
+ ctx.moveTo(100, 0);
+ ctx.lineTo(10, 0);
+ ctx.lineTo(10, 50);
+ ctx.lineTo(100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.fill();
+ @assert pixel 90,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.moveTo.newsubpath
+ testing:
+ - 2d.path.moveTo
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.beginPath();
+ ctx.moveTo(0, 0);
+ ctx.moveTo(100, 0);
+ ctx.moveTo(100, 50);
+ ctx.moveTo(0, 50);
+ ctx.fillStyle = '#f00';
+ ctx.fill();
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.moveTo.multiple
+ testing:
+ - 2d.path.moveTo
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.moveTo(0, 25);
+ ctx.moveTo(100, 25);
+ ctx.moveTo(0, 25);
+ ctx.lineTo(100, 25);
+ ctx.strokeStyle = '#0f0';
+ ctx.lineWidth = 50;
+ ctx.stroke();
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.moveTo.nonfinite
+ desc: moveTo() with Infinity/NaN is ignored
+ testing:
+ - 2d.nonfinite
+ code: |
+ ctx.moveTo(0, 0);
+ ctx.lineTo(100, 0);
+ @nonfinite ctx.moveTo(<0 Infinity -Infinity NaN>, <50 Infinity -Infinity NaN>);
+ ctx.lineTo(100, 50);
+ ctx.lineTo(0, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.fill();
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.closePath.empty
+ testing:
+ - 2d.path.closePath.empty
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.closePath();
+ ctx.fillStyle = '#f00';
+ ctx.fill();
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.closePath.newline
+ testing:
+ - 2d.path.closePath.nonempty
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.strokeStyle = '#0f0';
+ ctx.lineWidth = 50;
+ ctx.moveTo(-100, 25);
+ ctx.lineTo(-100, -100);
+ ctx.lineTo(200, -100);
+ ctx.lineTo(200, 25);
+ ctx.closePath();
+ ctx.stroke();
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.closePath.nextpoint
+ testing:
+ - 2d.path.closePath.nonempty
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.strokeStyle = '#0f0';
+ ctx.lineWidth = 50;
+ ctx.moveTo(-100, 25);
+ ctx.lineTo(-100, -1000);
+ ctx.closePath();
+ ctx.lineTo(1000, 25);
+ ctx.stroke();
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.lineTo.ensuresubpath.1
+ desc: If there is no subpath, the point is added and nothing is drawn
+ testing:
+ - 2d.path.lineTo.empty
+ - 2d.path.ensure
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.strokeStyle = '#f00';
+ ctx.lineWidth = 50;
+ ctx.beginPath();
+ ctx.lineTo(100, 50);
+ ctx.stroke();
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.lineTo.ensuresubpath.2
+ desc: If there is no subpath, the point is added and used for subsequent drawing
+ testing:
+ - 2d.path.lineTo.empty
+ - 2d.path.ensure
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.strokeStyle = '#0f0';
+ ctx.lineWidth = 50;
+ ctx.beginPath();
+ ctx.lineTo(0, 25);
+ ctx.lineTo(100, 25);
+ ctx.stroke();
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.lineTo.basic
+ testing:
+ - 2d.path.lineTo.nonempty
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.strokeStyle = '#0f0';
+ ctx.lineWidth = 50;
+ ctx.beginPath();
+ ctx.moveTo(0, 25);
+ ctx.lineTo(100, 25);
+ ctx.stroke();
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.lineTo.nextpoint
+ testing:
+ - 2d.path.lineTo.nonempty
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.strokeStyle = '#0f0';
+ ctx.lineWidth = 50;
+ ctx.beginPath();
+ ctx.moveTo(-100, -100);
+ ctx.lineTo(0, 25);
+ ctx.lineTo(100, 25);
+ ctx.stroke();
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.lineTo.nonfinite
+ desc: lineTo() with Infinity/NaN is ignored
+ testing:
+ - 2d.nonfinite
+ code: |
+ ctx.moveTo(0, 0);
+ ctx.lineTo(100, 0);
+ @nonfinite ctx.lineTo(<0 Infinity -Infinity NaN>, <50 Infinity -Infinity NaN>);
+ ctx.lineTo(100, 50);
+ ctx.lineTo(0, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.fill();
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 90,45 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.quadraticCurveTo.ensuresubpath.1
+ desc: If there is no subpath, the first control point is added (and nothing is drawn up to it)
+ testing:
+ - 2d.path.quadratic.empty
+ - 2d.path.ensure
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.strokeStyle = '#f00';
+ ctx.lineWidth = 50;
+ ctx.beginPath();
+ ctx.quadraticCurveTo(100, 50, 200, 50);
+ ctx.stroke();
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 95,45 == 0,255,0,255; @moz-todo
+ expected: green
+
+- name: 2d.path.quadraticCurveTo.ensuresubpath.2
+ desc: If there is no subpath, the first control point is added
+ testing:
+ - 2d.path.quadratic.empty
+ - 2d.path.ensure
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.strokeStyle = '#0f0';
+ ctx.lineWidth = 50;
+ ctx.beginPath();
+ ctx.quadraticCurveTo(0, 25, 100, 25);
+ ctx.stroke();
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 5,45 == 0,255,0,255; @moz-todo
+ expected: green
+
+- name: 2d.path.quadraticCurveTo.basic
+ testing:
+ - 2d.path.quadratic.nonempty
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.strokeStyle = '#0f0';
+ ctx.lineWidth = 50;
+ ctx.beginPath();
+ ctx.moveTo(0, 25);
+ ctx.quadraticCurveTo(100, 25, 100, 25);
+ ctx.stroke();
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.quadraticCurveTo.shape
+ testing:
+ - 2d.path.quadratic.nonempty
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.strokeStyle = '#0f0';
+ ctx.lineWidth = 55;
+ ctx.beginPath();
+ ctx.moveTo(-1000, 1050);
+ ctx.quadraticCurveTo(0, -1000, 1200, 1050);
+ ctx.stroke();
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 98,1 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ @assert pixel 98,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.quadraticCurveTo.scaled
+ testing:
+ - 2d.path.quadratic.nonempty
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.scale(1000, 1000);
+ ctx.strokeStyle = '#0f0';
+ ctx.lineWidth = 0.055;
+ ctx.beginPath();
+ ctx.moveTo(-1, 1.05);
+ ctx.quadraticCurveTo(0, -1, 1.2, 1.05);
+ ctx.stroke();
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 98,1 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ @assert pixel 98,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.quadraticCurveTo.nonfinite
+ desc: quadraticCurveTo() with Infinity/NaN is ignored
+ testing:
+ - 2d.nonfinite
+ code: |
+ ctx.moveTo(0, 0);
+ ctx.lineTo(100, 0);
+ @nonfinite ctx.quadraticCurveTo(<0 Infinity -Infinity NaN>, <50 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>, <50 Infinity -Infinity NaN>);
+ ctx.lineTo(100, 50);
+ ctx.lineTo(0, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.fill();
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 90,45 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.bezierCurveTo.ensuresubpath.1
+ desc: If there is no subpath, the first control point is added (and nothing is drawn up to it)
+ testing:
+ - 2d.path.bezier.empty
+ - 2d.path.ensure
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.strokeStyle = '#f00';
+ ctx.lineWidth = 50;
+ ctx.beginPath();
+ ctx.bezierCurveTo(100, 50, 200, 50, 200, 50);
+ ctx.stroke();
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 95,45 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.bezierCurveTo.ensuresubpath.2
+ desc: If there is no subpath, the first control point is added
+ testing:
+ - 2d.path.bezier.empty
+ - 2d.path.ensure
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.strokeStyle = '#0f0';
+ ctx.lineWidth = 50;
+ ctx.beginPath();
+ ctx.bezierCurveTo(0, 25, 100, 25, 100, 25);
+ ctx.stroke();
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 5,45 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.bezierCurveTo.basic
+ testing:
+ - 2d.path.bezier.nonempty
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.strokeStyle = '#0f0';
+ ctx.lineWidth = 50;
+ ctx.beginPath();
+ ctx.moveTo(0, 25);
+ ctx.bezierCurveTo(100, 25, 100, 25, 100, 25);
+ ctx.stroke();
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.bezierCurveTo.shape
+ testing:
+ - 2d.path.bezier.nonempty
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.strokeStyle = '#0f0';
+ ctx.lineWidth = 55;
+ ctx.beginPath();
+ ctx.moveTo(-2000, 3100);
+ ctx.bezierCurveTo(-2000, -1000, 2100, -1000, 2100, 3100);
+ ctx.stroke();
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 98,1 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ @assert pixel 98,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.bezierCurveTo.scaled
+ testing:
+ - 2d.path.bezier.nonempty
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.scale(1000, 1000);
+ ctx.strokeStyle = '#0f0';
+ ctx.lineWidth = 0.055;
+ ctx.beginPath();
+ ctx.moveTo(-2, 3.1);
+ ctx.bezierCurveTo(-2, -1, 2.1, -1, 2.1, 3.1);
+ ctx.stroke();
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 98,1 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ @assert pixel 98,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.bezierCurveTo.nonfinite
+ desc: bezierCurveTo() with Infinity/NaN is ignored
+ testing:
+ - 2d.nonfinite
+ code: |
+ ctx.moveTo(0, 0);
+ ctx.lineTo(100, 0);
+ @nonfinite ctx.bezierCurveTo(<0 Infinity -Infinity NaN>, <50 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>, <50 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>, <50 Infinity -Infinity NaN>);
+ ctx.lineTo(100, 50);
+ ctx.lineTo(0, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.fill();
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 90,45 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.arcTo.ensuresubpath.1
+ desc: If there is no subpath, the first control point is added (and nothing is drawn up to it)
+ testing:
+ - 2d.path.arcTo.empty
+ - 2d.path.ensure
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.lineWidth = 50;
+ ctx.strokeStyle = '#f00';
+ ctx.beginPath();
+ ctx.arcTo(100, 50, 200, 50, 0.1);
+ ctx.stroke();
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.arcTo.ensuresubpath.2
+ desc: If there is no subpath, the first control point is added
+ testing:
+ - 2d.path.arcTo.empty
+ - 2d.path.ensure
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.lineWidth = 50;
+ ctx.strokeStyle = '#0f0';
+ ctx.beginPath();
+ ctx.arcTo(0, 25, 50, 250, 0.1); // adds (x1,y1), draws nothing
+ ctx.lineTo(100, 25);
+ ctx.stroke();
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.arcTo.coincide.1
+ desc: arcTo() has no effect if P0 = P1
+ testing:
+ - 2d.path.arcTo.coincide.01
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.lineWidth = 50;
+
+ ctx.strokeStyle = '#0f0';
+ ctx.beginPath();
+ ctx.moveTo(0, 25);
+ ctx.arcTo(0, 25, 50, 1000, 1);
+ ctx.lineTo(100, 25);
+ ctx.stroke();
+
+ ctx.strokeStyle = '#f00';
+ ctx.beginPath();
+ ctx.moveTo(50, 25);
+ ctx.arcTo(50, 25, 100, 25, 1);
+ ctx.stroke();
+
+ @assert pixel 50,1 == 0,255,0,255;
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 50,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.arcTo.coincide.2
+ desc: arcTo() draws a straight line to P1 if P1 = P2
+ testing:
+ - 2d.path.arcTo.coincide.12
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.lineWidth = 50;
+ ctx.strokeStyle = '#0f0';
+ ctx.beginPath();
+ ctx.moveTo(0, 25);
+ ctx.arcTo(100, 25, 100, 25, 1);
+ ctx.stroke();
+
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.arcTo.collinear.1
+ desc: arcTo() with all points on a line, and P1 between P0/P2, draws a straight line to P1
+ testing:
+ - 2d.path.arcTo.collinear
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.lineWidth = 50;
+
+ ctx.strokeStyle = '#0f0';
+ ctx.beginPath();
+ ctx.moveTo(0, 25);
+ ctx.arcTo(100, 25, 200, 25, 1);
+ ctx.stroke();
+
+ ctx.strokeStyle = '#f00';
+ ctx.beginPath();
+ ctx.moveTo(-100, 25);
+ ctx.arcTo(0, 25, 100, 25, 1);
+ ctx.stroke();
+
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.arcTo.collinear.2
+ desc: arcTo() with all points on a line, and P2 between P0/P1, draws a straight line to P1
+ testing:
+ - 2d.path.arcTo.collinear
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.lineWidth = 50;
+
+ ctx.strokeStyle = '#0f0';
+ ctx.beginPath();
+ ctx.moveTo(0, 25);
+ ctx.arcTo(100, 25, 10, 25, 1);
+ ctx.stroke();
+
+ ctx.strokeStyle = '#f00';
+ ctx.beginPath();
+ ctx.moveTo(100, 25);
+ ctx.arcTo(200, 25, 110, 25, 1);
+ ctx.stroke();
+
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.arcTo.collinear.3
+ desc: arcTo() with all points on a line, and P0 between P1/P2, draws a straight line to P1
+ testing:
+ - 2d.path.arcTo.collinear
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.lineWidth = 50;
+
+ ctx.strokeStyle = '#0f0';
+ ctx.beginPath();
+ ctx.moveTo(0, 25);
+ ctx.arcTo(100, 25, -100, 25, 1);
+ ctx.stroke();
+
+ ctx.strokeStyle = '#f00';
+ ctx.beginPath();
+ ctx.moveTo(100, 25);
+ ctx.arcTo(200, 25, 0, 25, 1);
+ ctx.stroke();
+
+ ctx.beginPath();
+ ctx.moveTo(-100, 25);
+ ctx.arcTo(0, 25, -200, 25, 1);
+ ctx.stroke();
+
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.arcTo.shape.curve1
+ desc: arcTo() curves in the right kind of shape
+ testing:
+ - 2d.path.arcTo.shape
+ code: |
+ var tol = 1.5; // tolerance to avoid antialiasing artifacts
+
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.strokeStyle = '#f00';
+ ctx.lineWidth = 10;
+ ctx.beginPath();
+ ctx.moveTo(10, 25);
+ ctx.arcTo(75, 25, 75, 60, 20);
+ ctx.stroke();
+
+ ctx.fillStyle = '#0f0';
+ ctx.beginPath();
+ ctx.rect(10, 20, 45, 10);
+ ctx.moveTo(80, 45);
+ ctx.arc(55, 45, 25+tol, 0, -Math.PI/2, true);
+ ctx.arc(55, 45, 15-tol, -Math.PI/2, 0, false);
+ ctx.fill();
+
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 55,19 == 0,255,0,255;
+ @assert pixel 55,20 == 0,255,0,255;
+ @assert pixel 55,21 == 0,255,0,255;
+ @assert pixel 64,22 == 0,255,0,255;
+ @assert pixel 65,21 == 0,255,0,255;
+ @assert pixel 72,28 == 0,255,0,255;
+ @assert pixel 73,27 == 0,255,0,255;
+ @assert pixel 78,36 == 0,255,0,255;
+ @assert pixel 79,35 == 0,255,0,255;
+ @assert pixel 80,44 == 0,255,0,255;
+ @assert pixel 80,45 == 0,255,0,255;
+ @assert pixel 80,46 == 0,255,0,255;
+ @assert pixel 65,45 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.arcTo.shape.curve2
+ desc: arcTo() curves in the right kind of shape
+ testing:
+ - 2d.path.arcTo.shape
+ code: |
+ var tol = 1.5; // tolerance to avoid antialiasing artifacts
+
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.fillStyle = '#f00';
+ ctx.beginPath();
+ ctx.rect(10, 20, 45, 10);
+ ctx.moveTo(80, 45);
+ ctx.arc(55, 45, 25-tol, 0, -Math.PI/2, true);
+ ctx.arc(55, 45, 15+tol, -Math.PI/2, 0, false);
+ ctx.fill();
+
+ ctx.strokeStyle = '#0f0';
+ ctx.lineWidth = 10;
+ ctx.beginPath();
+ ctx.moveTo(10, 25);
+ ctx.arcTo(75, 25, 75, 60, 20);
+ ctx.stroke();
+
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 55,19 == 0,255,0,255;
+ @assert pixel 55,20 == 0,255,0,255;
+ @assert pixel 55,21 == 0,255,0,255;
+ @assert pixel 64,22 == 0,255,0,255;
+ @assert pixel 65,21 == 0,255,0,255;
+ @assert pixel 72,28 == 0,255,0,255;
+ @assert pixel 73,27 == 0,255,0,255;
+ @assert pixel 78,36 == 0,255,0,255;
+ @assert pixel 79,35 == 0,255,0,255;
+ @assert pixel 80,44 == 0,255,0,255;
+ @assert pixel 80,45 == 0,255,0,255;
+ @assert pixel 80,46 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.arcTo.shape.start
+ desc: arcTo() draws a straight line from P0 to P1
+ testing:
+ - 2d.path.arcTo.shape
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.strokeStyle = '#0f0';
+ ctx.lineWidth = 50;
+ ctx.beginPath();
+ ctx.moveTo(0, 25);
+ ctx.arcTo(200, 25, 200, 50, 10);
+ ctx.stroke();
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 98,1 == 0,255,0,255;
+ @assert pixel 98,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.arcTo.shape.end
+ desc: arcTo() does not draw anything from P1 to P2
+ testing:
+ - 2d.path.arcTo.shape
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.strokeStyle = '#f00';
+ ctx.lineWidth = 50;
+ ctx.beginPath();
+ ctx.moveTo(-100, -100);
+ ctx.arcTo(-100, 25, 200, 25, 10);
+ ctx.stroke();
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 98,1 == 0,255,0,255;
+ @assert pixel 98,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.arcTo.negative
+ desc: arcTo() with negative radius throws an exception
+ testing:
+ - 2d.path.arcTo.negative
+ code: |
+ @assert throws INDEX_SIZE_ERR ctx.arcTo(0, 0, 0, 0, -1);
+
+- name: 2d.path.arcTo.zero.1
+ desc: arcTo() with zero radius draws a straight line from P0 to P1
+ testing:
+ - 2d.path.arcTo.zeroradius
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.lineWidth = 50;
+
+ ctx.strokeStyle = '#0f0';
+ ctx.beginPath();
+ ctx.moveTo(0, 25);
+ ctx.arcTo(100, 25, 100, 100, 0);
+ ctx.stroke();
+
+ ctx.strokeStyle = '#f00';
+ ctx.beginPath();
+ ctx.moveTo(0, -25);
+ ctx.arcTo(50, -25, 50, 50, 0);
+ ctx.stroke();
+
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.arcTo.zero.2
+ desc: arcTo() with zero radius draws a straight line from P0 to P1, even when all points are collinear
+ testing:
+ - 2d.path.arcTo.zeroradius
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.lineWidth = 50;
+
+ ctx.strokeStyle = '#0f0';
+ ctx.beginPath();
+ ctx.moveTo(0, 25);
+ ctx.arcTo(100, 25, -100, 25, 0);
+ ctx.stroke();
+
+ ctx.strokeStyle = '#f00';
+ ctx.beginPath();
+ ctx.moveTo(100, 25);
+ ctx.arcTo(200, 25, 50, 25, 0);
+ ctx.stroke();
+
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.arcTo.transformation
+ desc: arcTo joins up to the last subpath point correctly
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.fillStyle = '#0f0';
+ ctx.beginPath();
+ ctx.moveTo(0, 50);
+ ctx.translate(100, 0);
+ ctx.arcTo(50, 50, 50, 0, 50);
+ ctx.lineTo(-100, 0);
+ ctx.fill();
+
+ @assert pixel 0,0 == 0,255,0,255;
+ @assert pixel 50,0 == 0,255,0,255;
+ @assert pixel 99,0 == 0,255,0,255;
+ @assert pixel 0,25 == 0,255,0,255;
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 99,25 == 0,255,0,255;
+ @assert pixel 0,49 == 0,255,0,255;
+ @assert pixel 50,49 == 0,255,0,255;
+ @assert pixel 99,49 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.arcTo.scale
+ desc: arcTo scales the curve, not just the control points
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.fillStyle = '#0f0';
+ ctx.beginPath();
+ ctx.moveTo(0, 50);
+ ctx.translate(100, 0);
+ ctx.scale(0.1, 1);
+ ctx.arcTo(50, 50, 50, 0, 50);
+ ctx.lineTo(-1000, 0);
+ ctx.fill();
+
+ @assert pixel 0,0 == 0,255,0,255;
+ @assert pixel 50,0 == 0,255,0,255;
+ @assert pixel 99,0 == 0,255,0,255;
+ @assert pixel 0,25 == 0,255,0,255;
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 99,25 == 0,255,0,255;
+ @assert pixel 0,49 == 0,255,0,255;
+ @assert pixel 50,49 == 0,255,0,255;
+ @assert pixel 99,49 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.arcTo.nonfinite
+ desc: arcTo() with Infinity/NaN is ignored
+ testing:
+ - 2d.nonfinite
+ code: |
+ ctx.moveTo(0, 0);
+ ctx.lineTo(100, 0);
+ @nonfinite ctx.arcTo(<0 Infinity -Infinity NaN>, <50 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>, <50 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>);
+ ctx.lineTo(100, 50);
+ ctx.lineTo(0, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.fill();
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 90,45 == 0,255,0,255;
+ expected: green
+
+
+- name: 2d.path.arc.empty
+ desc: arc() with an empty path does not draw a straight line to the start point
+ testing:
+ - 2d.path.arc.nonempty
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.lineWidth = 50;
+ ctx.strokeStyle = '#f00';
+ ctx.beginPath();
+ ctx.arc(200, 25, 5, 0, 2*Math.PI, true);
+ ctx.stroke();
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.arc.nonempty
+ desc: arc() with a non-empty path does draw a straight line to the start point
+ testing:
+ - 2d.path.arc.nonempty
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.lineWidth = 50;
+ ctx.strokeStyle = '#0f0';
+ ctx.beginPath();
+ ctx.moveTo(0, 25);
+ ctx.arc(200, 25, 5, 0, 2*Math.PI, true);
+ ctx.stroke();
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.arc.end
+ desc: arc() adds the end point of the arc to the subpath
+ testing:
+ - 2d.path.arc.draw
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.lineWidth = 50;
+ ctx.strokeStyle = '#0f0';
+ ctx.beginPath();
+ ctx.moveTo(-100, 0);
+ ctx.arc(-100, 0, 25, -Math.PI/2, Math.PI/2, true);
+ ctx.lineTo(100, 25);
+ ctx.stroke();
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.arc.default
+ desc: arc() with missing last argument defaults to clockwise
+ testing:
+ - 2d.path.arc.omitted
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#f00';
+ ctx.beginPath();
+ ctx.moveTo(100, 0);
+ ctx.arc(100, 0, 150, -Math.PI, Math.PI/2);
+ ctx.fill();
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.arc.angle.1
+ desc: arc() draws pi/2 .. -pi anticlockwise correctly
+ testing:
+ - 2d.path.arc.draw
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#f00';
+ ctx.beginPath();
+ ctx.moveTo(100, 0);
+ ctx.arc(100, 0, 150, Math.PI/2, -Math.PI, true);
+ ctx.fill();
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.arc.angle.2
+ desc: arc() draws -3pi/2 .. -pi anticlockwise correctly
+ testing:
+ - 2d.path.arc.draw
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#f00';
+ ctx.beginPath();
+ ctx.moveTo(100, 0);
+ ctx.arc(100, 0, 150, -3*Math.PI/2, -Math.PI, true);
+ ctx.fill();
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.arc.angle.3
+ desc: arc() wraps angles mod 2pi when anticlockwise and end > start+2pi
+ testing:
+ - 2d.path.arc.draw
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#f00';
+ ctx.beginPath();
+ ctx.moveTo(100, 0);
+ ctx.arc(100, 0, 150, (512+1/2)*Math.PI, (1024-1)*Math.PI, true);
+ ctx.fill();
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.arc.angle.4
+ desc: arc() draws a full circle when clockwise and end > start+2pi
+ testing:
+ - 2d.path.arc.draw
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.beginPath();
+ ctx.moveTo(50, 25);
+ ctx.arc(50, 25, 60, (512+1/2)*Math.PI, (1024-1)*Math.PI, false);
+ ctx.fill();
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 98,1 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ @assert pixel 98,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.arc.angle.5
+ desc: arc() wraps angles mod 2pi when clockwise and start > end+2pi
+ testing:
+ - 2d.path.arc.draw
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#f00';
+ ctx.beginPath();
+ ctx.moveTo(100, 0);
+ ctx.arc(100, 0, 150, (1024-1)*Math.PI, (512+1/2)*Math.PI, false);
+ ctx.fill();
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.arc.angle.6
+ desc: arc() draws a full circle when anticlockwise and start > end+2pi
+ testing:
+ - 2d.path.arc.draw
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.beginPath();
+ ctx.moveTo(50, 25);
+ ctx.arc(50, 25, 60, (1024-1)*Math.PI, (512+1/2)*Math.PI, true);
+ ctx.fill();
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 98,1 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ @assert pixel 98,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.arc.zero.1
+ desc: arc() draws nothing when startAngle = endAngle and anticlockwise
+ testing:
+ - 2d.path.arc.draw
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.strokeStyle = '#f00';
+ ctx.lineWidth = 100;
+ ctx.beginPath();
+ ctx.arc(50, 25, 50, 0, 0, true);
+ ctx.stroke();
+ @assert pixel 50,20 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.arc.zero.2
+ desc: arc() draws nothing when startAngle = endAngle and clockwise
+ testing:
+ - 2d.path.arc.draw
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.strokeStyle = '#f00';
+ ctx.lineWidth = 100;
+ ctx.beginPath();
+ ctx.arc(50, 25, 50, 0, 0, false);
+ ctx.stroke();
+ @assert pixel 50,20 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.arc.twopie.1
+ desc: arc() draws nothing when end = start + 2pi-e and anticlockwise
+ testing:
+ - 2d.path.arc.draw
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.strokeStyle = '#f00';
+ ctx.lineWidth = 100;
+ ctx.beginPath();
+ ctx.arc(50, 25, 50, 0, 2*Math.PI - 1e-4, true);
+ ctx.stroke();
+ @assert pixel 50,20 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.arc.twopie.2
+ desc: arc() draws a full circle when end = start + 2pi-e and clockwise
+ testing:
+ - 2d.path.arc.draw
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.strokeStyle = '#0f0';
+ ctx.lineWidth = 100;
+ ctx.beginPath();
+ ctx.arc(50, 25, 50, 0, 2*Math.PI - 1e-4, false);
+ ctx.stroke();
+ @assert pixel 50,20 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.arc.twopie.3
+ desc: arc() draws a full circle when end = start + 2pi+e and anticlockwise
+ testing:
+ - 2d.path.arc.draw
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.strokeStyle = '#0f0';
+ ctx.lineWidth = 100;
+ ctx.beginPath();
+ ctx.arc(50, 25, 50, 0, 2*Math.PI + 1e-4, true);
+ ctx.stroke();
+ @assert pixel 50,20 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.arc.twopie.4
+ desc: arc() draws nothing when end = start + 2pi+e and clockwise
+ testing:
+ - 2d.path.arc.draw
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.strokeStyle = '#0f0';
+ ctx.lineWidth = 100;
+ ctx.beginPath();
+ ctx.arc(50, 25, 50, 0, 2*Math.PI + 1e-4, false);
+ ctx.stroke();
+ @assert pixel 50,20 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.arc.shape.1
+ desc: arc() from 0 to pi does not draw anything in the wrong half
+ testing:
+ - 2d.path.arc.draw
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.lineWidth = 50;
+ ctx.strokeStyle = '#f00';
+ ctx.beginPath();
+ ctx.arc(50, 50, 50, 0, Math.PI, false);
+ ctx.stroke();
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 98,1 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ @assert pixel 20,48 == 0,255,0,255;
+ @assert pixel 98,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.arc.shape.2
+ desc: arc() from 0 to pi draws stuff in the right half
+ testing:
+ - 2d.path.arc.draw
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.lineWidth = 100;
+ ctx.strokeStyle = '#0f0';
+ ctx.beginPath();
+ ctx.arc(50, 50, 50, 0, Math.PI, true);
+ ctx.stroke();
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 98,1 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ @assert pixel 20,48 == 0,255,0,255;
+ @assert pixel 98,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.arc.shape.3
+ desc: arc() from 0 to -pi/2 does not draw anything in the wrong quadrant
+ testing:
+ - 2d.path.arc.draw
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.lineWidth = 100;
+ ctx.strokeStyle = '#f00';
+ ctx.beginPath();
+ ctx.arc(0, 50, 50, 0, -Math.PI/2, false);
+ ctx.stroke();
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 98,1 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255; @moz-todo
+ @assert pixel 98,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.arc.shape.4
+ desc: arc() from 0 to -pi/2 draws stuff in the right quadrant
+ testing:
+ - 2d.path.arc.draw
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.lineWidth = 150;
+ ctx.strokeStyle = '#0f0';
+ ctx.beginPath();
+ ctx.arc(-50, 50, 100, 0, -Math.PI/2, true);
+ ctx.stroke();
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 98,1 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ @assert pixel 98,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.arc.shape.5
+ desc: arc() from 0 to 5pi does not draw crazy things
+ testing:
+ - 2d.path.arc.draw
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.lineWidth = 200;
+ ctx.strokeStyle = '#f00';
+ ctx.beginPath();
+ ctx.arc(300, 0, 100, 0, 5*Math.PI, false);
+ ctx.stroke();
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 98,1 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ @assert pixel 98,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.arc.selfintersect.1
+ desc: arc() with lineWidth > 2*radius is drawn sensibly
+ testing:
+ - 2d.path.arc.draw
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.lineWidth = 200;
+ ctx.strokeStyle = '#f00';
+ ctx.beginPath();
+ ctx.arc(100, 50, 25, 0, -Math.PI/2, true);
+ ctx.stroke();
+ ctx.beginPath();
+ ctx.arc(0, 0, 25, 0, -Math.PI/2, true);
+ ctx.stroke();
+ @assert pixel 1,1 == 0,255,0,255; @moz-todo
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.arc.selfintersect.2
+ desc: arc() with lineWidth > 2*radius is drawn sensibly
+ testing:
+ - 2d.path.arc.draw
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.lineWidth = 180;
+ ctx.strokeStyle = '#0f0';
+ ctx.beginPath();
+ ctx.arc(-50, 50, 25, 0, -Math.PI/2, true);
+ ctx.stroke();
+ ctx.beginPath();
+ ctx.arc(100, 0, 25, 0, -Math.PI/2, true);
+ ctx.stroke();
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 90,10 == 0,255,0,255;
+ @assert pixel 97,1 == 0,255,0,255;
+ @assert pixel 97,2 == 0,255,0,255;
+ @assert pixel 97,3 == 0,255,0,255;
+ @assert pixel 2,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.arc.negative
+ desc: arc() with negative radius throws INDEX_SIZE_ERR
+ testing:
+ - 2d.path.arc.negative
+ code: |
+ @assert throws INDEX_SIZE_ERR ctx.arc(0, 0, -1, 0, 0, true);
+
+- name: 2d.path.arc.zeroradius
+ desc: arc() with zero radius draws a line to the start point
+ testing:
+ - 2d.path.arc.zero
+ code: |
+ ctx.fillStyle = '#f00'
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.lineWidth = 50;
+ ctx.strokeStyle = '#0f0';
+ ctx.beginPath();
+ ctx.moveTo(0, 25);
+ ctx.arc(200, 25, 0, 0, Math.PI, true);
+ ctx.stroke();
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.arc.scale.1
+ desc: Non-uniformly scaled arcs are the right shape
+ testing:
+ - 2d.path.transformation
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.scale(2, 0.5);
+ ctx.fillStyle = '#0f0';
+ ctx.beginPath();
+ ctx.arc(25, 50, 56, 0, 2*Math.PI, false);
+ ctx.fill();
+ ctx.fillStyle = '#f00';
+ ctx.beginPath();
+ ctx.moveTo(-25, 50);
+ ctx.arc(-25, 50, 24, 0, 2*Math.PI, false);
+ ctx.moveTo(75, 50);
+ ctx.arc(75, 50, 24, 0, 2*Math.PI, false);
+ ctx.moveTo(25, -25);
+ ctx.arc(25, -25, 24, 0, 2*Math.PI, false);
+ ctx.moveTo(25, 125);
+ ctx.arc(25, 125, 24, 0, 2*Math.PI, false);
+ ctx.fill();
+
+ @assert pixel 0,0 == 0,255,0,255;
+ @assert pixel 50,0 == 0,255,0,255;
+ @assert pixel 99,0 == 0,255,0,255;
+ @assert pixel 0,25 == 0,255,0,255;
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 99,25 == 0,255,0,255;
+ @assert pixel 0,49 == 0,255,0,255;
+ @assert pixel 50,49 == 0,255,0,255;
+ @assert pixel 99,49 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.arc.scale.2
+ desc: Highly scaled arcs are the right shape
+ testing:
+ - 2d.path.arc.draw
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.scale(100, 100);
+ ctx.strokeStyle = '#0f0';
+ ctx.lineWidth = 1.2;
+ ctx.beginPath();
+ ctx.arc(0, 0, 0.6, 0, Math.PI/2, false);
+ ctx.stroke();
+
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 50,1 == 0,255,0,255;
+ @assert pixel 98,1 == 0,255,0,255;
+ @assert pixel 1,25 == 0,255,0,255;
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 98,25 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ @assert pixel 50,48 == 0,255,0,255;
+ @assert pixel 98,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.arc.nonfinite
+ desc: arc() with Infinity/NaN is ignored
+ testing:
+ - 2d.nonfinite
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.moveTo(0, 0);
+ ctx.lineTo(100, 0);
+ @nonfinite ctx.arc(<0 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>, <50 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>, <2*Math.PI Infinity -Infinity NaN>, <true>);
+ ctx.lineTo(100, 50);
+ ctx.lineTo(0, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.fill();
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 90,45 == 0,255,0,255;
+ expected: green
+
+
+- name: 2d.path.rect.basic
+ testing:
+ - 2d.path.rect.subpath
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.rect(0, 0, 100, 50);
+ ctx.fill();
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.rect.newsubpath
+ testing:
+ - 2d.path.rect.subpath
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.beginPath();
+ ctx.strokeStyle = '#f00';
+ ctx.lineWidth = 50;
+ ctx.moveTo(-100, 25);
+ ctx.lineTo(-50, 25);
+ ctx.rect(200, 25, 1, 1);
+ ctx.stroke();
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.rect.closed
+ testing:
+ - 2d.path.rect.closed
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.strokeStyle = '#0f0';
+ ctx.lineWidth = 200;
+ ctx.lineJoin = 'miter';
+ ctx.rect(100, 50, 100, 100);
+ ctx.stroke();
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.rect.end.1
+ testing:
+ - 2d.path.rect.newsubpath
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.strokeStyle = '#0f0';
+ ctx.lineWidth = 100;
+ ctx.rect(200, 100, 400, 1000);
+ ctx.lineTo(-2000, -1000);
+ ctx.stroke();
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.rect.end.2
+ testing:
+ - 2d.path.rect.newsubpath
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.strokeStyle = '#0f0';
+ ctx.lineWidth = 450;
+ ctx.lineCap = 'round';
+ ctx.lineJoin = 'bevel';
+ ctx.rect(150, 150, 2000, 2000);
+ ctx.lineTo(160, 160);
+ ctx.stroke();
+ @assert pixel 1,1 == 0,255,0,255;
+ @assert pixel 98,1 == 0,255,0,255;
+ @assert pixel 1,48 == 0,255,0,255;
+ @assert pixel 98,48 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.rect.zero.1
+ testing:
+ - 2d.path.rect.subpath
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.strokeStyle = '#0f0';
+ ctx.lineWidth = 100;
+ ctx.beginPath();
+ ctx.rect(0, 50, 100, 0);
+ ctx.stroke();
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.rect.zero.2
+ testing:
+ - 2d.path.rect.subpath
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.strokeStyle = '#0f0';
+ ctx.lineWidth = 100;
+ ctx.beginPath();
+ ctx.rect(50, -100, 0, 250);
+ ctx.stroke();
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.rect.zero.3
+ testing:
+ - 2d.path.rect.subpath
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.strokeStyle = '#f00';
+ ctx.lineWidth = 100;
+ ctx.beginPath();
+ ctx.rect(50, 25, 0, 0);
+ ctx.stroke();
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.rect.zero.4
+ testing:
+ - 2d.path.rect.subpath
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.strokeStyle = '#0f0';
+ ctx.lineWidth = 50;
+ ctx.rect(100, 25, 0, 0);
+ ctx.lineTo(0, 25);
+ ctx.stroke();
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.rect.zero.5
+ testing:
+ - 2d.path.rect.subpath
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.strokeStyle = '#f00';
+ ctx.lineWidth = 50;
+ ctx.moveTo(0, 0);
+ ctx.rect(100, 25, 0, 0);
+ ctx.stroke();
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.rect.zero.6
+ testing:
+ - 2d.path.rect.subpath
+ #mozilla: { bug: TODO }
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.strokeStyle = '#f00';
+ ctx.lineJoin = 'miter';
+ ctx.miterLimit = 1.5;
+ ctx.lineWidth = 200;
+ ctx.beginPath();
+ ctx.rect(100, 25, 1000, 0);
+ ctx.stroke();
+ @assert pixel 50,25 == 0,255,0,255; @moz-todo
+ expected: green
+
+- name: 2d.path.rect.negative
+ testing:
+ - 2d.path.rect.subpath
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.beginPath();
+ ctx.fillStyle = '#0f0';
+ ctx.rect(0, 0, 50, 25);
+ ctx.rect(100, 0, -50, 25);
+ ctx.rect(0, 50, 50, -25);
+ ctx.rect(100, 50, -50, -25);
+ ctx.fill();
+ @assert pixel 25,12 == 0,255,0,255;
+ @assert pixel 75,12 == 0,255,0,255;
+ @assert pixel 25,37 == 0,255,0,255;
+ @assert pixel 75,37 == 0,255,0,255;
+
+- name: 2d.path.rect.winding
+ testing:
+ - 2d.path.rect.subpath
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.beginPath();
+ ctx.fillStyle = '#f00';
+ ctx.rect(0, 0, 50, 50);
+ ctx.rect(100, 50, -50, -50);
+ ctx.rect(0, 25, 100, -25);
+ ctx.rect(100, 25, -100, 25);
+ ctx.fill();
+ @assert pixel 25,12 == 0,255,0,255;
+ @assert pixel 75,12 == 0,255,0,255;
+ @assert pixel 25,37 == 0,255,0,255;
+ @assert pixel 75,37 == 0,255,0,255;
+
+- name: 2d.path.rect.selfintersect
+ #mozilla: { bug: TODO }
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.strokeStyle = '#0f0';
+ ctx.lineWidth = 90;
+ ctx.beginPath();
+ ctx.rect(45, 20, 10, 10);
+ ctx.stroke();
+ @assert pixel 50,25 == 0,255,0,255; @moz-todo
+ expected: green
+
+- name: 2d.path.rect.nonfinite
+ desc: rect() with Infinity/NaN is ignored
+ testing:
+ - 2d.nonfinite
+ code: |
+ ctx.moveTo(0, 0);
+ ctx.lineTo(100, 0);
+ @nonfinite ctx.rect(<0 Infinity -Infinity NaN>, <50 Infinity -Infinity NaN>, <1 Infinity -Infinity NaN>, <1 Infinity -Infinity NaN>);
+ ctx.lineTo(100, 50);
+ ctx.lineTo(0, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.fill();
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 90,45 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.fill.overlap
+ testing:
+ - 2d.path.fill.basic
+ code: |
+ ctx.fillStyle = '#000';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.fillStyle = 'rgba(0, 255, 0, 0.5)';
+ ctx.rect(0, 0, 100, 50);
+ ctx.closePath();
+ ctx.rect(10, 10, 80, 30);
+ ctx.fill();
+
+ @assert pixel 50,25 ==~ 0,127,0,255 +/- 1;
+ expected: |
+ size 100 50
+ cr.set_source_rgb(0, 0.5, 0)
+ cr.rectangle(0, 0, 100, 50)
+ cr.fill()
+
+- name: 2d.path.fill.winding.add
+ testing:
+ - 2d.path.fill.basic
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.fillStyle = '#0f0';
+ ctx.moveTo(-10, -10);
+ ctx.lineTo(110, -10);
+ ctx.lineTo(110, 60);
+ ctx.lineTo(-10, 60);
+ ctx.lineTo(-10, -10);
+ ctx.lineTo(0, 0);
+ ctx.lineTo(100, 0);
+ ctx.lineTo(100, 50);
+ ctx.lineTo(0, 50);
+ ctx.fill();
+
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.fill.winding.subtract.1
+ testing:
+ - 2d.path.fill.basic
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.fillStyle = '#f00';
+ ctx.moveTo(-10, -10);
+ ctx.lineTo(110, -10);
+ ctx.lineTo(110, 60);
+ ctx.lineTo(-10, 60);
+ ctx.lineTo(-10, -10);
+ ctx.lineTo(0, 0);
+ ctx.lineTo(0, 50);
+ ctx.lineTo(100, 50);
+ ctx.lineTo(100, 0);
+ ctx.fill();
+
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.fill.winding.subtract.2
+ testing:
+ - 2d.path.fill.basic
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.fillStyle = '#f00';
+ ctx.moveTo(-10, -10);
+ ctx.lineTo(110, -10);
+ ctx.lineTo(110, 60);
+ ctx.lineTo(-10, 60);
+ ctx.moveTo(0, 0);
+ ctx.lineTo(0, 50);
+ ctx.lineTo(100, 50);
+ ctx.lineTo(100, 0);
+ ctx.fill();
+
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.fill.winding.subtract.3
+ testing:
+ - 2d.path.fill.basic
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.fillStyle = '#0f0';
+ ctx.moveTo(-10, -10);
+ ctx.lineTo(110, -10);
+ ctx.lineTo(110, 60);
+ ctx.lineTo(-10, 60);
+ ctx.lineTo(-10, -10);
+ ctx.lineTo(-20, -20);
+ ctx.lineTo(120, -20);
+ ctx.lineTo(120, 70);
+ ctx.lineTo(-20, 70);
+ ctx.lineTo(-20, -20);
+ ctx.lineTo(0, 0);
+ ctx.lineTo(0, 50);
+ ctx.lineTo(100, 50);
+ ctx.lineTo(100, 0);
+ ctx.fill();
+
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.fill.closed.basic
+ testing:
+ - 2d.path.fill.closed
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.fillStyle = '#0f0';
+ ctx.moveTo(0, 0);
+ ctx.lineTo(100, 0);
+ ctx.lineTo(100, 50);
+ ctx.lineTo(0, 50);
+ ctx.fill();
+
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.fill.closed.unaffected
+ testing:
+ - 2d.path.fill.closed
+ code: |
+ ctx.fillStyle = '#00f';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.moveTo(0, 0);
+ ctx.lineTo(100, 0);
+ ctx.lineTo(100, 50);
+ ctx.fillStyle = '#f00';
+ ctx.fill();
+ ctx.lineTo(0, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.fill();
+
+ @assert pixel 90,10 == 0,255,0,255;
+ @assert pixel 10,40 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.stroke.overlap
+ desc: Stroked subpaths are combined before being drawn
+ testing:
+ - 2d.path.stroke.basic
+ code: |
+ ctx.fillStyle = '#000';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.strokeStyle = 'rgba(0, 255, 0, 0.5)';
+ ctx.lineWidth = 50;
+ ctx.moveTo(0, 20);
+ ctx.lineTo(100, 20);
+ ctx.moveTo(0, 30);
+ ctx.lineTo(100, 30);
+ ctx.stroke();
+
+ @assert pixel 50,25 ==~ 0,127,0,255 +/- 1;
+ expected: |
+ size 100 50
+ cr.set_source_rgb(0, 0.5, 0)
+ cr.rectangle(0, 0, 100, 50)
+ cr.fill()
+
+- name: 2d.path.stroke.union
+ desc: Strokes in opposite directions are unioned, not subtracted
+ testing:
+ - 2d.path.stroke.basic
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.strokeStyle = '#0f0';
+ ctx.lineWidth = 40;
+ ctx.moveTo(0, 10);
+ ctx.lineTo(100, 10);
+ ctx.moveTo(100, 40);
+ ctx.lineTo(0, 40);
+ ctx.stroke();
+
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.stroke.unaffected
+ desc: Stroking does not start a new path or subpath
+ testing:
+ - 2d.path.stroke.basic
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.lineWidth = 50;
+ ctx.moveTo(-100, 25);
+ ctx.lineTo(-100, -100);
+ ctx.lineTo(200, -100);
+ ctx.lineTo(200, 25);
+ ctx.strokeStyle = '#f00';
+ ctx.stroke();
+
+ ctx.closePath();
+ ctx.strokeStyle = '#0f0';
+ ctx.stroke();
+
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.stroke.scale1
+ desc: Stroke line widths are scaled by the current transformation matrix
+ testing:
+ - 2d.path.transformation
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.beginPath();
+ ctx.rect(25, 12.5, 50, 25);
+ ctx.save();
+ ctx.scale(50, 25);
+ ctx.strokeStyle = '#0f0';
+ ctx.stroke();
+ ctx.restore();
+
+ ctx.beginPath();
+ ctx.rect(-25, -12.5, 150, 75);
+ ctx.save();
+ ctx.scale(50, 25);
+ ctx.strokeStyle = '#f00';
+ ctx.stroke();
+ ctx.restore();
+
+ @assert pixel 0,0 == 0,255,0,255;
+ @assert pixel 50,0 == 0,255,0,255;
+ @assert pixel 99,0 == 0,255,0,255;
+ @assert pixel 0,25 == 0,255,0,255;
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 99,25 == 0,255,0,255;
+ @assert pixel 0,49 == 0,255,0,255;
+ @assert pixel 50,49 == 0,255,0,255;
+ @assert pixel 99,49 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.stroke.scale2
+ desc: Stroke line widths are scaled by the current transformation matrix
+ testing:
+ - 2d.path.transformation
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.beginPath();
+ ctx.rect(25, 12.5, 50, 25);
+ ctx.save();
+ ctx.rotate(Math.PI/2);
+ ctx.scale(25, 50);
+ ctx.strokeStyle = '#0f0';
+ ctx.stroke();
+ ctx.restore();
+
+ ctx.beginPath();
+ ctx.rect(-25, -12.5, 150, 75);
+ ctx.save();
+ ctx.rotate(Math.PI/2);
+ ctx.scale(25, 50);
+ ctx.strokeStyle = '#f00';
+ ctx.stroke();
+ ctx.restore();
+
+ @assert pixel 0,0 == 0,255,0,255;
+ @assert pixel 50,0 == 0,255,0,255;
+ @assert pixel 99,0 == 0,255,0,255;
+ @assert pixel 0,25 == 0,255,0,255;
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 99,25 == 0,255,0,255;
+ @assert pixel 0,49 == 0,255,0,255;
+ @assert pixel 50,49 == 0,255,0,255;
+ @assert pixel 99,49 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.stroke.skew
+ desc: Strokes lines are skewed by the current transformation matrix
+ testing:
+ - 2d.path.transformation
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.save();
+ ctx.beginPath();
+ ctx.moveTo(49, -50);
+ ctx.lineTo(201, -50);
+ ctx.rotate(Math.PI/4);
+ ctx.scale(1, 283);
+ ctx.strokeStyle = '#0f0';
+ ctx.stroke();
+ ctx.restore();
+
+ ctx.save();
+ ctx.beginPath();
+ ctx.translate(-150, 0);
+ ctx.moveTo(49, -50);
+ ctx.lineTo(199, -50);
+ ctx.rotate(Math.PI/4);
+ ctx.scale(1, 142);
+ ctx.strokeStyle = '#f00';
+ ctx.stroke();
+ ctx.restore();
+
+ ctx.save();
+ ctx.beginPath();
+ ctx.translate(-150, 0);
+ ctx.moveTo(49, -50);
+ ctx.lineTo(199, -50);
+ ctx.rotate(Math.PI/4);
+ ctx.scale(1, 142);
+ ctx.strokeStyle = '#f00';
+ ctx.stroke();
+ ctx.restore();
+
+ @assert pixel 0,0 == 0,255,0,255;
+ @assert pixel 50,0 == 0,255,0,255;
+ @assert pixel 99,0 == 0,255,0,255;
+ @assert pixel 0,25 == 0,255,0,255;
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 99,25 == 0,255,0,255;
+ @assert pixel 0,49 == 0,255,0,255;
+ @assert pixel 50,49 == 0,255,0,255;
+ @assert pixel 99,49 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.stroke.empty
+ desc: Empty subpaths are not stroked
+ testing:
+ - 2d.path.stroke.empty
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.strokeStyle = '#f00';
+ ctx.lineWidth = 100;
+ ctx.lineCap = 'round';
+ ctx.lineJoin = 'round';
+
+ ctx.beginPath();
+ ctx.moveTo(40, 25);
+ ctx.moveTo(60, 25);
+ ctx.stroke();
+
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.stroke.prune.line
+ desc: Zero-length line segments from lineTo are removed before stroking
+ testing:
+ - 2d.path.stroke.prune
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.strokeStyle = '#f00';
+ ctx.lineWidth = 100;
+ ctx.lineCap = 'round';
+ ctx.lineJoin = 'round';
+
+ ctx.beginPath();
+ ctx.moveTo(50, 25);
+ ctx.lineTo(50, 25);
+ ctx.stroke();
+
+ @assert pixel 50,25 == 0,255,0,255; @moz-todo
+ expected: green
+
+- name: 2d.path.stroke.prune.closed
+ desc: Zero-length line segments from closed paths are removed before stroking
+ testing:
+ - 2d.path.stroke.prune
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.strokeStyle = '#f00';
+ ctx.lineWidth = 100;
+ ctx.lineCap = 'round';
+ ctx.lineJoin = 'round';
+
+ ctx.beginPath();
+ ctx.moveTo(50, 25);
+ ctx.lineTo(50, 25);
+ ctx.closePath();
+ ctx.stroke();
+
+ @assert pixel 50,25 == 0,255,0,255; @moz-todo
+ expected: green
+
+- name: 2d.path.stroke.prune.curve
+ desc: Zero-length line segments from quadraticCurveTo and bezierCurveTo are removed before stroking
+ testing:
+ - 2d.path.stroke.prune
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.strokeStyle = '#f00';
+ ctx.lineWidth = 100;
+ ctx.lineCap = 'round';
+ ctx.lineJoin = 'round';
+
+ ctx.beginPath();
+ ctx.moveTo(50, 25);
+ ctx.quadraticCurveTo(50, 25, 50, 25);
+ ctx.stroke();
+
+ ctx.beginPath();
+ ctx.moveTo(50, 25);
+ ctx.bezierCurveTo(50, 25, 50, 25, 50, 25);
+ ctx.stroke();
+
+ @assert pixel 50,25 == 0,255,0,255; @moz-todo
+ expected: green
+
+- name: 2d.path.stroke.prune.arc
+ desc: Zero-length line segments from arcTo and arc are removed before stroking
+ testing:
+ - 2d.path.stroke.prune
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.strokeStyle = '#f00';
+ ctx.lineWidth = 100;
+ ctx.lineCap = 'round';
+ ctx.lineJoin = 'round';
+
+ ctx.beginPath();
+ ctx.moveTo(50, 25);
+ ctx.arcTo(50, 25, 150, 25, 10);
+ ctx.stroke();
+
+ ctx.beginPath();
+ ctx.moveTo(60, 25);
+ ctx.arc(50, 25, 10, 0, 0, false);
+ ctx.stroke();
+
+ @assert pixel 50,25 == 0,255,0,255; @moz-todo
+ expected: green
+
+- name: 2d.path.stroke.prune.rect
+ desc: Zero-length line segments from rect and strokeRect are removed before stroking
+ testing:
+ - 2d.path.stroke.prune
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.strokeStyle = '#f00';
+ ctx.lineWidth = 100;
+ ctx.lineCap = 'round';
+ ctx.lineJoin = 'round';
+
+ ctx.beginPath();
+ ctx.rect(50, 25, 0, 0);
+ ctx.stroke();
+
+ ctx.strokeRect(50, 25, 0, 0);
+
+ @assert pixel 50,25 == 0,255,0,255; @moz-todo
+ expected: green
+
+- name: 2d.path.stroke.prune.corner
+ desc: Zero-length line segments are removed before stroking with miters
+ testing:
+ - 2d.path.stroke.prune
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.strokeStyle = '#f00';
+ ctx.lineWidth = 400;
+ ctx.lineJoin = 'miter';
+ ctx.miterLimit = 1.4;
+
+ ctx.beginPath();
+ ctx.moveTo(-1000, 200);
+ ctx.lineTo(-100, 200);
+ ctx.lineTo(-100, 200);
+ ctx.lineTo(-100, 200);
+ ctx.lineTo(-100, 1000);
+ ctx.stroke();
+
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+
+- name: 2d.path.transformation.basic
+ testing:
+ - 2d.path.transformation
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.translate(-100, 0);
+ ctx.rect(100, 0, 100, 50);
+ ctx.translate(0, -100);
+ ctx.fillStyle = '#0f0';
+ ctx.fill();
+
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.transformation.multiple
+ # TODO: change this name
+ desc: Transformations are applied while building paths, not when drawing
+ testing:
+ - 2d.path.transformation
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.fillStyle = '#f00';
+ ctx.translate(-100, 0);
+ ctx.rect(0, 0, 100, 50);
+ ctx.fill();
+ ctx.translate(100, 0);
+ ctx.fill();
+
+ ctx.beginPath();
+ ctx.strokeStyle = '#f00';
+ ctx.lineWidth = 50;
+ ctx.translate(0, -50);
+ ctx.moveTo(0, 25);
+ ctx.lineTo(100, 25);
+ ctx.stroke();
+ ctx.translate(0, 50);
+ ctx.stroke();
+
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.transformation.changing
+ desc: Transformations are applied while building paths, not when drawing
+ testing:
+ - 2d.path.transformation
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.moveTo(0, 0);
+ ctx.translate(100, 0);
+ ctx.lineTo(0, 0);
+ ctx.translate(0, 50);
+ ctx.lineTo(0, 0);
+ ctx.translate(-100, 0);
+ ctx.lineTo(0, 0);
+ ctx.translate(1000, 1000);
+ ctx.rotate(Math.PI/2);
+ ctx.scale(0.1, 0.1);
+ ctx.fill();
+
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+
+- name: 2d.path.clip.empty
+ testing:
+ - 2d.path.clip.basic
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.beginPath();
+ ctx.clip();
+
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.clip.basic.1
+ testing:
+ - 2d.path.clip.basic
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.beginPath();
+ ctx.rect(0, 0, 100, 50);
+ ctx.clip();
+
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.clip.basic.2
+ testing:
+ - 2d.path.clip.basic
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.beginPath();
+ ctx.rect(-100, 0, 100, 50);
+ ctx.clip();
+
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.clip.intersect
+ testing:
+ - 2d.path.clip.basic
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.beginPath();
+ ctx.rect(0, 0, 50, 50);
+ ctx.clip();
+ ctx.beginPath();
+ ctx.rect(50, 0, 50, 50)
+ ctx.clip();
+
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.clip.winding.1
+ testing:
+ - 2d.path.clip.basic
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.beginPath();
+ ctx.moveTo(-10, -10);
+ ctx.lineTo(110, -10);
+ ctx.lineTo(110, 60);
+ ctx.lineTo(-10, 60);
+ ctx.lineTo(-10, -10);
+ ctx.lineTo(0, 0);
+ ctx.lineTo(0, 50);
+ ctx.lineTo(100, 50);
+ ctx.lineTo(100, 0);
+ ctx.clip();
+
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.clip.winding.2
+ testing:
+ - 2d.path.clip.basic
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.beginPath();
+ ctx.moveTo(-10, -10);
+ ctx.lineTo(110, -10);
+ ctx.lineTo(110, 60);
+ ctx.lineTo(-10, 60);
+ ctx.lineTo(-10, -10);
+ ctx.clip();
+
+ ctx.beginPath();
+ ctx.moveTo(0, 0);
+ ctx.lineTo(0, 50);
+ ctx.lineTo(100, 50);
+ ctx.lineTo(100, 0);
+ ctx.lineTo(0, 0);
+ ctx.clip();
+
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.path.clip.unaffected
+ testing:
+ - 2d.path.clip.closed
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.fillStyle = '#0f0';
+
+ ctx.beginPath();
+ ctx.moveTo(0, 0);
+ ctx.lineTo(0, 50);
+ ctx.lineTo(100, 50);
+ ctx.lineTo(100, 0);
+ ctx.clip();
+
+ ctx.lineTo(0, 0);
+ ctx.fill();
+
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+
+
+- name: 2d.path.isPointInPath.basic.1
+ desc: isPointInPath() detects whether the point is inside the path
+ testing:
+ - 2d.path.isPointInPath
+ code: |
+ ctx.rect(0, 0, 20, 20);
+ @assert ctx.isPointInPath(10, 10) === true;
+ @assert ctx.isPointInPath(30, 10) === false;
+
+- name: 2d.path.isPointInPath.basic.2
+ desc: isPointInPath() detects whether the point is inside the path
+ testing:
+ - 2d.path.isPointInPath
+ code: |
+ ctx.rect(20, 0, 20, 20);
+ @assert ctx.isPointInPath(10, 10) === false;
+ @assert ctx.isPointInPath(30, 10) === true;
+
+- name: 2d.path.isPointInPath.edge
+ desc: isPointInPath() counts points on the path as being inside
+ testing:
+ - 2d.path.isPointInPath.edge
+ code: |
+ ctx.rect(0, 0, 20, 20);
+ @assert ctx.isPointInPath(0, 0) === true;
+ @assert ctx.isPointInPath(10, 0) === true;
+ @assert ctx.isPointInPath(20, 0) === true;
+ @assert ctx.isPointInPath(20, 10) === true;
+ @assert ctx.isPointInPath(20, 20) === true;
+ @assert ctx.isPointInPath(10, 20) === true;
+ @assert ctx.isPointInPath(0, 20) === true;
+ @assert ctx.isPointInPath(0, 10) === true;
+ @assert ctx.isPointInPath(10, -0.01) === false;
+ @assert ctx.isPointInPath(10, 20.01) === false;
+ @assert ctx.isPointInPath(-0.01, 10) === false;
+ @assert ctx.isPointInPath(20.01, 10) === false;
+
+- name: 2d.path.isPointInPath.empty
+ desc: isPointInPath() works when there is no path
+ testing:
+ - 2d.path.isPointInPath
+ code: |
+ @assert ctx.isPointInPath(0, 0) === false;
+
+- name: 2d.path.isPointInPath.subpath
+ desc: isPointInPath() uses the current path, not just the subpath
+ testing:
+ - 2d.path.isPointInPath
+ code: |
+ ctx.rect(0, 0, 20, 20);
+ ctx.beginPath();
+ ctx.rect(20, 0, 20, 20);
+ ctx.closePath();
+ ctx.rect(40, 0, 20, 20);
+ @assert ctx.isPointInPath(10, 10) === false;
+ @assert ctx.isPointInPath(30, 10) === true;
+ @assert ctx.isPointInPath(50, 10) === true;
+
+- name: 2d.path.isPointInPath.outside
+ desc: isPointInPath() works on paths outside the canvas
+ testing:
+ - 2d.path.isPointInPath
+ code: |
+ ctx.rect(0, -100, 20, 20);
+ ctx.rect(20, -10, 20, 20);
+ @assert ctx.isPointInPath(10, -110) === false;
+ @assert ctx.isPointInPath(10, -90) === true;
+ @assert ctx.isPointInPath(10, -70) === false;
+ @assert ctx.isPointInPath(30, -20) === false;
+ @assert ctx.isPointInPath(30, 0) === true;
+ @assert ctx.isPointInPath(30, 20) === false;
+
+- name: 2d.path.isPointInPath.unclosed
+ desc: isPointInPath() works on unclosed subpaths
+ testing:
+ - 2d.path.isPointInPath
+ code: |
+ ctx.moveTo(0, 0);
+ ctx.lineTo(20, 0);
+ ctx.lineTo(20, 20);
+ ctx.lineTo(0, 20);
+ @assert ctx.isPointInPath(10, 10) === true;
+ @assert ctx.isPointInPath(30, 10) === false;
+
+- name: 2d.path.isPointInPath.arc
+ desc: isPointInPath() works on arcs
+ testing:
+ - 2d.path.isPointInPath
+ code: |
+ ctx.arc(50, 25, 10, 0, Math.PI, false);
+ @assert ctx.isPointInPath(50, 10) === false;
+ @assert ctx.isPointInPath(50, 20) === false;
+ @assert ctx.isPointInPath(50, 30) === true;
+ @assert ctx.isPointInPath(50, 40) === false;
+ @assert ctx.isPointInPath(30, 20) === false;
+ @assert ctx.isPointInPath(70, 20) === false;
+ @assert ctx.isPointInPath(30, 30) === false;
+ @assert ctx.isPointInPath(70, 30) === false;
+
+- name: 2d.path.isPointInPath.bigarc
+ desc: isPointInPath() works on unclosed arcs larger than 2pi
+ opera: { bug: 320937 }
+ testing:
+ - 2d.path.isPointInPath
+ code: |
+ ctx.arc(50, 25, 10, 0, 7, false);
+ @assert ctx.isPointInPath(50, 10) === false;
+ @assert ctx.isPointInPath(50, 20) === true;
+ @assert ctx.isPointInPath(50, 30) === true;
+ @assert ctx.isPointInPath(50, 40) === false;
+ @assert ctx.isPointInPath(30, 20) === false;
+ @assert ctx.isPointInPath(70, 20) === false;
+ @assert ctx.isPointInPath(30, 30) === false;
+ @assert ctx.isPointInPath(70, 30) === false;
+
+- name: 2d.path.isPointInPath.bezier
+ desc: isPointInPath() works on Bezier curves
+ testing:
+ - 2d.path.isPointInPath
+ code: |
+ ctx.moveTo(25, 25);
+ ctx.bezierCurveTo(50, -50, 50, 100, 75, 25);
+ @assert ctx.isPointInPath(25, 20) === false;
+ @assert ctx.isPointInPath(25, 30) === false;
+ @assert ctx.isPointInPath(30, 20) === true;
+ @assert ctx.isPointInPath(30, 30) === false;
+ @assert ctx.isPointInPath(40, 2) === false;
+ @assert ctx.isPointInPath(40, 20) === true;
+ @assert ctx.isPointInPath(40, 30) === false;
+ @assert ctx.isPointInPath(40, 47) === false;
+ @assert ctx.isPointInPath(45, 20) === true;
+ @assert ctx.isPointInPath(45, 30) === false;
+ @assert ctx.isPointInPath(55, 20) === false;
+ @assert ctx.isPointInPath(55, 30) === true;
+ @assert ctx.isPointInPath(60, 2) === false;
+ @assert ctx.isPointInPath(60, 20) === false;
+ @assert ctx.isPointInPath(60, 30) === true;
+ @assert ctx.isPointInPath(60, 47) === false;
+ @assert ctx.isPointInPath(70, 20) === false;
+ @assert ctx.isPointInPath(70, 30) === true;
+ @assert ctx.isPointInPath(75, 20) === false;
+ @assert ctx.isPointInPath(75, 30) === false;
+
+- name: 2d.path.isPointInPath.winding
+ desc: isPointInPath() uses the non-zero winding number rule
+ testing:
+ - 2d.path.isPointInPath
+ code: |
+ // Create a square ring, using opposite windings to make a hole in the centre
+ ctx.moveTo(0, 0);
+ ctx.lineTo(50, 0);
+ ctx.lineTo(50, 50);
+ ctx.lineTo(0, 50);
+ ctx.lineTo(0, 0);
+ ctx.lineTo(10, 10);
+ ctx.lineTo(10, 40);
+ ctx.lineTo(40, 40);
+ ctx.lineTo(40, 10);
+ ctx.lineTo(10, 10);
+
+ @assert ctx.isPointInPath(5, 5) === true;
+ @assert ctx.isPointInPath(25, 5) === true;
+ @assert ctx.isPointInPath(45, 5) === true;
+ @assert ctx.isPointInPath(5, 25) === true;
+ @assert ctx.isPointInPath(25, 25) === false;
+ @assert ctx.isPointInPath(45, 25) === true;
+ @assert ctx.isPointInPath(5, 45) === true;
+ @assert ctx.isPointInPath(25, 45) === true;
+ @assert ctx.isPointInPath(45, 45) === true;
+
+- name: 2d.path.isPointInPath.transform.1
+ desc: isPointInPath() handles transformations correctly
+ testing:
+ - 2d.path.isPointInPath
+ code: |
+ ctx.translate(50, 0);
+ ctx.rect(0, 0, 20, 20);
+ @assert ctx.isPointInPath(-40, 10) === false;
+ @assert ctx.isPointInPath(10, 10) === false;
+ @assert ctx.isPointInPath(49, 10) === false;
+ @assert ctx.isPointInPath(51, 10) === true;
+ @assert ctx.isPointInPath(69, 10) === true;
+ @assert ctx.isPointInPath(71, 10) === false;
+
+- name: 2d.path.isPointInPath.transform.2
+ desc: isPointInPath() handles transformations correctly
+ testing:
+ - 2d.path.isPointInPath
+ code: |
+ ctx.rect(50, 0, 20, 20);
+ ctx.translate(50, 0);
+ @assert ctx.isPointInPath(-40, 10) === false;
+ @assert ctx.isPointInPath(10, 10) === false;
+ @assert ctx.isPointInPath(49, 10) === false;
+ @assert ctx.isPointInPath(51, 10) === true;
+ @assert ctx.isPointInPath(69, 10) === true;
+ @assert ctx.isPointInPath(71, 10) === false;
+
+- name: 2d.path.isPointInPath.transform.3
+ desc: isPointInPath() handles transformations correctly
+ testing:
+ - 2d.path.isPointInPath
+ code: |
+ ctx.scale(-1, 1);
+ ctx.rect(-70, 0, 20, 20);
+ @assert ctx.isPointInPath(-40, 10) === false;
+ @assert ctx.isPointInPath(10, 10) === false;
+ @assert ctx.isPointInPath(49, 10) === false;
+ @assert ctx.isPointInPath(51, 10) === true;
+ @assert ctx.isPointInPath(69, 10) === true;
+ @assert ctx.isPointInPath(71, 10) === false;
+
+- name: 2d.path.isPointInPath.transform.4
+ desc: isPointInPath() handles transformations correctly
+ testing:
+ - 2d.path.isPointInPath
+ code: |
+ ctx.translate(50, 0);
+ ctx.rect(50, 0, 20, 20);
+ ctx.translate(0, 50);
+ @assert ctx.isPointInPath(60, 10) === false;
+ @assert ctx.isPointInPath(110, 10) === true;
+ @assert ctx.isPointInPath(110, 60) === false;
+
+- name: 2d.path.isPointInPath.nonfinite
+ desc: isPointInPath() returns false for non-finite arguments
+ testing:
+ - 2d.path.isPointInPath.nonfinite
+ code: |
+ ctx.rect(-100, -50, 200, 100);
+ @assert ctx.isPointInPath(Infinity, 0) === false;
+ @assert ctx.isPointInPath(-Infinity, 0) === false;
+ @assert ctx.isPointInPath(NaN, 0) === false;
+ @assert ctx.isPointInPath(0, Infinity) === false;
+ @assert ctx.isPointInPath(0, -Infinity) === false;
+ @assert ctx.isPointInPath(0, NaN) === false;
+ @assert ctx.isPointInPath(NaN, NaN) === false;
+
+
+- name: 2d.drawImage.3arg
+ testing:
+ - 2d.drawImage.defaultsource
+ - 2d.drawImage.defaultdest
+ images:
+ - red.png
+ - green.png
+ code: |
+ ctx.drawImage(document.getElementById('green.png'), 0, 0);
+ ctx.drawImage(document.getElementById('red.png'), -100, 0);
+ ctx.drawImage(document.getElementById('red.png'), 100, 0);
+ ctx.drawImage(document.getElementById('red.png'), 0, -50);
+ ctx.drawImage(document.getElementById('red.png'), 0, 50);
+
+ @assert pixel 0,0 ==~ 0,255,0,255;
+ @assert pixel 99,0 ==~ 0,255,0,255;
+ @assert pixel 0,49 ==~ 0,255,0,255;
+ @assert pixel 99,49 ==~ 0,255,0,255;
+ expected: green
+
+- name: 2d.drawImage.5arg
+ testing:
+ - 2d.drawImage.defaultsource
+ images:
+ - red.png
+ - green.png
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.drawImage(document.getElementById('green.png'), 50, 0, 50, 50);
+ ctx.drawImage(document.getElementById('red.png'), 0, 0, 50, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 50, 50);
+
+ @assert pixel 0,0 ==~ 0,255,0,255;
+ @assert pixel 99,0 ==~ 0,255,0,255;
+ @assert pixel 0,49 ==~ 0,255,0,255;
+ @assert pixel 99,49 ==~ 0,255,0,255;
+ expected: green
+
+- name: 2d.drawImage.9arg.basic
+ testing:
+ - 2d.drawImage.paint
+ images:
+ - green.png
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.drawImage(document.getElementById('green.png'), 0, 0, 100, 50, 0, 0, 100, 50);
+ @assert pixel 0,0 ==~ 0,255,0,255;
+ @assert pixel 99,0 ==~ 0,255,0,255;
+ @assert pixel 0,49 ==~ 0,255,0,255;
+ @assert pixel 99,49 ==~ 0,255,0,255;
+ expected: green
+
+- name: 2d.drawImage.9arg.sourcepos
+ testing:
+ - 2d.drawImage.paint
+ images:
+ - rgrg-256x256.png
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.drawImage(document.getElementById('rgrg-256x256.png'), 140, 20, 100, 50, 0, 0, 100, 50);
+ @assert pixel 0,0 ==~ 0,255,0,255;
+ @assert pixel 99,0 ==~ 0,255,0,255;
+ @assert pixel 0,49 ==~ 0,255,0,255;
+ @assert pixel 99,49 ==~ 0,255,0,255;
+ expected: green
+
+- name: 2d.drawImage.9arg.sourcesize
+ testing:
+ - 2d.drawImage.paint
+ images:
+ - rgrg-256x256.png
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.drawImage(document.getElementById('rgrg-256x256.png'), 0, 0, 256, 256, 0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 51, 26);
+ ctx.fillRect(49, 24, 51, 26);
+ @assert pixel 0,0 ==~ 0,255,0,255;
+ @assert pixel 99,0 ==~ 0,255,0,255;
+ @assert pixel 0,49 ==~ 0,255,0,255;
+ @assert pixel 99,49 ==~ 0,255,0,255;
+ @assert pixel 20,20 ==~ 0,255,0,255;
+ @assert pixel 80,20 ==~ 0,255,0,255;
+ @assert pixel 20,30 ==~ 0,255,0,255;
+ @assert pixel 80,30 ==~ 0,255,0,255;
+ expected: green
+
+- name: 2d.drawImage.9arg.destpos
+ testing:
+ - 2d.drawImage.paint
+ images:
+ - red.png
+ - green.png
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.drawImage(document.getElementById('green.png'), 0, 0, 100, 50, 0, 0, 100, 50);
+ ctx.drawImage(document.getElementById('red.png'), 0, 0, 100, 50, -100, 0, 100, 50);
+ ctx.drawImage(document.getElementById('red.png'), 0, 0, 100, 50, 100, 0, 100, 50);
+ ctx.drawImage(document.getElementById('red.png'), 0, 0, 100, 50, 0, -50, 100, 50);
+ ctx.drawImage(document.getElementById('red.png'), 0, 0, 100, 50, 0, 50, 100, 50);
+ @assert pixel 0,0 ==~ 0,255,0,255;
+ @assert pixel 99,0 ==~ 0,255,0,255;
+ @assert pixel 0,49 ==~ 0,255,0,255;
+ @assert pixel 99,49 ==~ 0,255,0,255;
+ expected: green
+
+- name: 2d.drawImage.9arg.destsize
+ testing:
+ - 2d.drawImage.paint
+ images:
+ - red.png
+ - green.png
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.drawImage(document.getElementById('green.png'), 1, 1, 1, 1, 0, 0, 100, 50);
+ ctx.drawImage(document.getElementById('red.png'), 0, 0, 100, 50, -50, 0, 50, 50);
+ ctx.drawImage(document.getElementById('red.png'), 0, 0, 100, 50, 100, 0, 50, 50);
+ ctx.drawImage(document.getElementById('red.png'), 0, 0, 100, 50, 0, -25, 100, 25);
+ ctx.drawImage(document.getElementById('red.png'), 0, 0, 100, 50, 0, 50, 100, 25);
+ @assert pixel 0,0 ==~ 0,255,0,255;
+ @assert pixel 99,0 ==~ 0,255,0,255;
+ @assert pixel 0,49 ==~ 0,255,0,255;
+ @assert pixel 99,49 ==~ 0,255,0,255;
+ expected: green
+
+- name: 2d.drawImage.canvas
+ testing:
+ - 2d.drawImage.paint
+ code: |
+ var canvas2 = document.createElement('canvas');
+ canvas2.width = 100;
+ canvas2.height = 50;
+ var ctx2 = canvas2.getContext('2d');
+ ctx2.fillStyle = '#0f0';
+ ctx2.fillRect(0, 0, 100, 50);
+
+ ctx.fillStyle = '#f00';
+ ctx.drawImage(canvas2, 0, 0);
+
+ @assert pixel 0,0 ==~ 0,255,0,255;
+ @assert pixel 99,0 ==~ 0,255,0,255;
+ @assert pixel 0,49 ==~ 0,255,0,255;
+ @assert pixel 99,49 ==~ 0,255,0,255;
+ expected: green
+
+- name: 2d.drawImage.self.1
+ testing:
+ - 2d.drawImage.self
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 50, 50);
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(50, 0, 50, 50);
+ ctx.drawImage(canvas, 50, 0);
+
+ @assert pixel 0,0 ==~ 0,255,0,255;
+ @assert pixel 99,0 ==~ 0,255,0,255;
+ @assert pixel 0,49 ==~ 0,255,0,255;
+ @assert pixel 99,49 ==~ 0,255,0,255;
+ expected: green
+
+- name: 2d.drawImage.self.2
+ testing:
+ - 2d.drawImage.self
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 1, 100, 49);
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 1);
+ ctx.drawImage(canvas, 0, 1);
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 2);
+
+ @assert pixel 0,0 ==~ 0,255,0,255;
+ @assert pixel 99,0 ==~ 0,255,0,255;
+ @assert pixel 0,49 ==~ 0,255,0,255;
+ @assert pixel 99,49 ==~ 0,255,0,255;
+ expected: green
+
+- name: 2d.drawImage.null
+ testing:
+ - 2d.drawImage.IDL
+ code: |
+ @assert throws TypeError ctx.drawImage(null, 0, 0);
+
+- name: 2d.drawImage.wrongtype
+ desc: Incorrect image types in drawImage do not match any defined overloads, so WebIDL throws a TypeError
+ notes: *bindings
+ testing:
+ - 2d.drawImage.IDL
+ code: |
+ @assert throws TypeError ctx.drawImage(undefined, 0, 0);
+ @assert throws TypeError ctx.drawImage(0, 0, 0);
+ @assert throws TypeError ctx.drawImage("", 0, 0);
+ @assert throws TypeError ctx.drawImage(document.createElement('p'), 0, 0);
+
+- name: 2d.drawImage.floatsource
+ testing:
+ - 2d.drawImage.paint
+ images:
+ - green.png
+ code: |
+ ctx.drawImage(document.getElementById('green.png'), 10.1, 10.1, 0.1, 0.1, 0, 0, 100, 50);
+ @assert pixel 50,25 ==~ 0,255,0,255;
+ expected: green
+
+- name: 2d.drawImage.zerosource
+ desc: drawImage with zero-sized source rectangle throws INDEX_SIZE_ERR
+ testing:
+ - 2d.drawImage.zerosource
+ images:
+ - red.png
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ @assert throws INDEX_SIZE_ERR ctx.drawImage(document.getElementById('red.png'), 10, 10, 0, 1, 0, 0, 100, 50);
+ @assert throws INDEX_SIZE_ERR ctx.drawImage(document.getElementById('red.png'), 10, 10, 1, 0, 0, 0, 100, 50);
+ @assert throws INDEX_SIZE_ERR ctx.drawImage(document.getElementById('red.png'), 10, 10, 0, 0, 0, 0, 100, 50);
+ @assert pixel 50,25 ==~ 0,255,0,255;
+ expected: green
+
+- name: 2d.drawImage.zerosource.image
+ desc: drawImage with zero-sized source rectangle from image throws INDEX_SIZE_ERR
+ testing:
+ - 2d.drawImage.zerosource
+ images:
+ - red-zerowidth.svg
+ - red-zeroheight.svg
+ - red-zerosize.svg
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ @assert throws INDEX_SIZE_ERR ctx.drawImage(document.getElementById('red-zerowidth.svg'), 0, 0, 100, 50);
+ @assert throws INDEX_SIZE_ERR ctx.drawImage(document.getElementById('red-zeroheight.svg'), 0, 0, 100, 50);
+ @assert throws INDEX_SIZE_ERR ctx.drawImage(document.getElementById('red-zerosize.svg'), 0, 0, 100, 50);
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+- name: 2d.drawImage.negativesource
+ desc: Negative source width/height represents the correct rectangle
+ testing:
+ - 2d.drawImage.direction
+ mozilla: { throws }
+ images:
+ - ggrr-256x256.png
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.drawImage(document.getElementById('ggrr-256x256.png'), 100, 78, -100, 50, 0, 0, 50, 50);
+ ctx.drawImage(document.getElementById('ggrr-256x256.png'), 100, 128, -100, -50, 50, 0, 50, 50);
+ @assert pixel 1,1 ==~ 0,255,0,255;
+ @assert pixel 1,48 ==~ 0,255,0,255;
+ @assert pixel 98,1 ==~ 0,255,0,255;
+ @assert pixel 98,48 ==~ 0,255,0,255;
+ @assert pixel 48,1 ==~ 0,255,0,255;
+ @assert pixel 48,48 ==~ 0,255,0,255;
+ @assert pixel 51,1 ==~ 0,255,0,255;
+ @assert pixel 51,48 ==~ 0,255,0,255;
+ @assert pixel 25,25 ==~ 0,255,0,255;
+ @assert pixel 75,25 ==~ 0,255,0,255;
+ expected: green
+
+- name: 2d.drawImage.negativedest
+ desc: Negative destination width/height represents the correct rectangle
+ testing:
+ - 2d.drawImage.direction
+ mozilla: { throws }
+ images:
+ - ggrr-256x256.png
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.drawImage(document.getElementById('ggrr-256x256.png'), 100, 78, 50, 50, 0, 50, 50, -50);
+ ctx.drawImage(document.getElementById('ggrr-256x256.png'), 100, 128, 50, -50, 100, 50, -50, -50);
+ @assert pixel 1,1 ==~ 0,255,0,255;
+ @assert pixel 1,48 ==~ 0,255,0,255;
+ @assert pixel 98,1 ==~ 0,255,0,255;
+ @assert pixel 98,48 ==~ 0,255,0,255;
+ @assert pixel 48,1 ==~ 0,255,0,255;
+ @assert pixel 48,48 ==~ 0,255,0,255;
+ @assert pixel 51,1 ==~ 0,255,0,255;
+ @assert pixel 51,48 ==~ 0,255,0,255;
+ @assert pixel 25,25 ==~ 0,255,0,255;
+ @assert pixel 75,25 ==~ 0,255,0,255;
+ expected: green
+
+- name: 2d.drawImage.negativedir
+ desc: Negative dimensions do not affect the direction of the image
+ testing:
+ - 2d.drawImage.direction
+ mozilla: { throws }
+ images:
+ - ggrr-256x256.png
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.drawImage(document.getElementById('ggrr-256x256.png'), 0, 178, 50, -100, 0, 0, 50, 100);
+ ctx.drawImage(document.getElementById('ggrr-256x256.png'), 0, 78, 50, 100, 50, 100, 50, -100);
+ @assert pixel 1,1 ==~ 0,255,0,255;
+ @assert pixel 1,48 ==~ 0,255,0,255;
+ @assert pixel 98,1 ==~ 0,255,0,255;
+ @assert pixel 98,48 ==~ 0,255,0,255;
+ @assert pixel 48,1 ==~ 0,255,0,255;
+ @assert pixel 48,48 ==~ 0,255,0,255;
+ @assert pixel 51,1 ==~ 0,255,0,255;
+ @assert pixel 51,48 ==~ 0,255,0,255;
+ @assert pixel 25,25 ==~ 0,255,0,255;
+ @assert pixel 75,25 ==~ 0,255,0,255;
+ expected: green
+
+- name: 2d.drawImage.outsidesource
+ DISABLED: fix this to match the current spec (transparent black outside source)
+ testing:
+ - 2d.drawImage.outsidesource
+ mozilla: { throws }
+ images:
+ - green.png
+ - red.png
+ code: |
+ ctx.drawImage(document.getElementById('green.png'), 10.5, 10.5, 89.5, 39.5, 0, 0, 100, 50);
+ ctx.drawImage(document.getElementById('green.png'), 5.5, 5.5, -5.5, -5.5, 0, 0, 100, 50);
+ ctx.drawImage(document.getElementById('green.png'), 100, 50, -5, -5, 0, 0, 100, 50);
+ @assert throws INDEX_SIZE_ERR ctx.drawImage(document.getElementById('red.png'), -0.001, 0, 100, 50, 0, 0, 100, 50);
+ @assert throws INDEX_SIZE_ERR ctx.drawImage(document.getElementById('red.png'), 0, -0.001, 100, 50, 0, 0, 100, 50);
+ @assert throws INDEX_SIZE_ERR ctx.drawImage(document.getElementById('red.png'), 0, 0, 100.001, 50, 0, 0, 100, 50);
+ @assert throws INDEX_SIZE_ERR ctx.drawImage(document.getElementById('red.png'), 0, 0, 100, 50.001, 0, 0, 100, 50);
+ @assert throws INDEX_SIZE_ERR ctx.drawImage(document.getElementById('red.png'), 50, 0, 50.001, 50, 0, 0, 100, 50); @moz-todo
+ @assert throws INDEX_SIZE_ERR ctx.drawImage(document.getElementById('red.png'), 0, 0, -5, 5, 0, 0, 100, 50);
+ @assert throws INDEX_SIZE_ERR ctx.drawImage(document.getElementById('red.png'), 0, 0, 5, -5, 0, 0, 100, 50);
+ @assert throws INDEX_SIZE_ERR ctx.drawImage(document.getElementById('red.png'), 110, 60, -20, -20, 0, 0, 100, 50);
+ @assert pixel 50,25 ==~ 0,255,0,255; @moz-todo
+ expected: green
+
+- name: 2d.drawImage.incomplete.nosrc
+ testing:
+ - 2d.drawImage.incomplete.image
+ mozilla: { throws }
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ var img = new Image();
+ ctx.drawImage(img, 0, 0);
+ @assert pixel 50,25 ==~ 0,255,0,255;
+ expected: green
+
+- name: 2d.drawImage.incomplete.immediate
+ testing:
+ - 2d.drawImage.incomplete.image
+ images:
+ - red.png
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ var img = new Image();
+ img.src = '../images/red.png';
+ // This triggers the "update the image data" algorithm.
+ // The image will not go to the "completely available" state
+ // until a fetch task in the networking task source is processed,
+ // so the image must not be fully decodable yet:
+ ctx.drawImage(img, 0, 0);
+ @assert pixel 50,25 ==~ 0,255,0,255; @moz-todo
+ expected: green
+
+- name: 2d.drawImage.incomplete.reload
+ testing:
+ - 2d.drawImage.incomplete.image
+ images:
+ - yellow.png
+ - red.png
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ var img = document.getElementById('yellow.png');
+ img.src = '../images/red.png';
+ // This triggers the "update the image data" algorithm,
+ // and resets the image to the "unavailable" state.
+ // The image will not go to the "completely available" state
+ // until a fetch task in the networking task source is processed,
+ // so the image must not be fully decodable yet:
+ ctx.drawImage(img, 0, 0);
+ @assert pixel 50,25 ==~ 0,255,0,255; @moz-todo
+ expected: green
+
+- name: 2d.drawImage.incomplete.emptysrc
+ testing:
+ - 2d.drawImage.incomplete.image
+ images:
+ - red.png
+ mozilla: { throws }
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ var img = document.getElementById('red.png');
+ img.src = "";
+ ctx.drawImage(img, 0, 0);
+ @assert pixel 50,25 ==~ 0,255,0,255;
+ expected: green
+
+- name: 2d.drawImage.incomplete.removedsrc
+ testing:
+ - 2d.drawImage.incomplete.image
+ images:
+ - red.png
+ mozilla: { throws }
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ var img = document.getElementById('red.png');
+ img.removeAttribute('src');
+ ctx.drawImage(img, 0, 0);
+ @assert pixel 50,25 ==~ 0,255,0,255;
+ expected: green
+
+- name: 2d.drawImage.broken
+ testing:
+ - 2d.drawImage.incomplete.image
+ images:
+ - broken.png
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ var img = document.getElementById('broken.png');
+ ctx.drawImage(img, 0, 0);
+ @assert pixel 50,25 ==~ 0,255,0,255; @moz-todo
+ expected: green
+
+- name: 2d.drawImage.zerocanvas
+ testing:
+ - 2d.drawImage.zerocanvas
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+
+ var canvas2 = document.createElement('canvas');
+ canvas2.width = 0;
+ canvas2.height = 10;
+ @assert throws INVALID_STATE_ERR ctx.drawImage(canvas2, 0, 0);
+
+ canvas2.width = 10;
+ canvas2.height = 0;
+ @assert throws INVALID_STATE_ERR ctx.drawImage(canvas2, 0, 0);
+
+ canvas2.width = 0;
+ canvas2.height = 0;
+ @assert throws INVALID_STATE_ERR ctx.drawImage(canvas2, 0, 0);
+
+ @assert pixel 50,25 ==~ 0,255,0,255;
+ expected: green
+
+- name: 2d.drawImage.svg
+ desc: drawImage() of an SVG image
+ testing:
+ - 2d.drawImage.svg
+ images:
+ - green.svg
+ code: |
+ ctx.drawImage(document.getElementById('green.svg'), 0, 0);
+ @assert pixel 50,25 ==~ 0,255,0,255;
+ expected: green
+
+- name: 2d.drawImage.animated.gif
+ desc: drawImage() of an animated GIF draws the first frame
+ testing:
+ - 2d.drawImage.animated.image
+ images:
+ - anim-gr.gif
+ code: |
+ deferTest();
+ setTimeout(t.step_func_done(function () {
+ ctx.drawImage(document.getElementById('anim-gr.gif'), 0, 0);
+ @assert pixel 50,25 ==~ 0,255,0,255;
+ }), 500);
+ expected: green
+
+- name: 2d.drawImage.animated.apng
+ desc: drawImage() of an APNG with no poster frame draws the first frame
+ testing:
+ - 2d.drawImage.animated.image
+ images:
+ - anim-gr.png
+ code: |
+ deferTest();
+ setTimeout(t.step_func_done(function () {
+ ctx.drawImage(document.getElementById('anim-gr.png'), 0, 0);
+ @assert pixel 50,25 ==~ 0,255,0,255;
+ }), 500);
+ expected: green
+
+- name: 2d.drawImage.animated.poster
+ desc: drawImage() of an APNG draws the poster frame
+ testing:
+ - 2d.drawImage.animated.image
+ images:
+ - anim-poster-gr.png
+ code: |
+ ctx.drawImage(document.getElementById('anim-poster-gr.png'), 0, 0);
+ @assert pixel 50,25 ==~ 0,255,0,255; @moz-todo
+ expected: green
+
+- name: 2d.drawImage.path
+ testing:
+ - 2d.drawImage.unaffect
+ images:
+ - red.png
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.rect(0, 0, 100, 50);
+ ctx.drawImage(document.getElementById('red.png'), 0, 0);
+ ctx.fill();
+ @assert pixel 50,25 ==~ 0,255,0,255;
+ expected: green
+
+- name: 2d.drawImage.transform
+ testing:
+ - 2d.drawImage.subject
+ images:
+ - red.png
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.translate(100, 0);
+ ctx.drawImage(document.getElementById('red.png'), 0, 0);
+ @assert pixel 50,25 ==~ 0,255,0,255;
+ expected: green
+
+# TODO: drawImage shadows
+
+- name: 2d.drawImage.alpha
+ testing:
+ - 2d.drawImage.subject
+ images:
+ - red.png
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.globalAlpha = 0;
+ ctx.drawImage(document.getElementById('red.png'), 0, 0);
+ @assert pixel 50,25 ==~ 0,255,0,255;
+ expected: green
+
+- name: 2d.drawImage.clip
+ testing:
+ - 2d.drawImage.subject
+ images:
+ - red.png
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.rect(-10, -10, 1, 1);
+ ctx.clip();
+ ctx.drawImage(document.getElementById('red.png'), 0, 0);
+ @assert pixel 50,25 ==~ 0,255,0,255;
+ expected: green
+
+- name: 2d.drawImage.composite
+ testing:
+ - 2d.drawImage.subject
+ images:
+ - red.png
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.globalCompositeOperation = 'destination-over';
+ ctx.drawImage(document.getElementById('red.png'), 0, 0);
+ @assert pixel 50,25 ==~ 0,255,0,255;
+ expected: green
+
+- name: 2d.drawImage.nowrap
+ desc: Stretched images do not get pixels wrapping around the edges
+ images:
+ - redtransparent.png
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.drawImage(document.getElementById('redtransparent.png'), -1950, 0, 2000, 50);
+ @assert pixel 45,25 ==~ 0,255,0,255;
+ @assert pixel 50,25 ==~ 0,255,0,255;
+ @assert pixel 55,25 ==~ 0,255,0,255;
+ expected: green
+
+- name: 2d.drawImage.nonfinite
+ desc: drawImage() with Infinity/NaN is ignored
+ testing:
+ - 2d.nonfinite
+ images:
+ - red.png
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ var red = document.getElementById('red.png');
+ @nonfinite ctx.drawImage(<red>, <0 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>);
+ @nonfinite ctx.drawImage(<red>, <0 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>, <100 Infinity -Infinity NaN>, <50 Infinity -Infinity NaN>);
+ @nonfinite ctx.drawImage(<red>, <0 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>, <100 Infinity -Infinity NaN>, <50 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>, <0 Infinity -Infinity NaN>, <100 Infinity -Infinity NaN>, <50 Infinity -Infinity NaN>);
+ @assert pixel 50,25 == 0,255,0,255;
+ expected: green
+
+
+
+- name: 2d.imageData.create2.basic
+ desc: createImageData(sw, sh) exists and returns something
+ testing:
+ - 2d.imageData.create2.object
+ code: |
+ @assert ctx.createImageData(1, 1) !== null;
+
+- name: 2d.imageData.create1.basic
+ desc: createImageData(imgdata) exists and returns something
+ testing:
+ - 2d.imageData.create1.object
+ code: |
+ @assert ctx.createImageData(ctx.createImageData(1, 1)) !== null;
+
+- name: 2d.imageData.create2.type
+ desc: createImageData(sw, sh) returns an ImageData object containing a Uint8ClampedArray object
+ testing:
+ - 2d.imageData.create2.object
+ code: |
+ @assert window.ImageData !== undefined;
+ @assert window.Uint8ClampedArray !== undefined;
+ window.ImageData.prototype.thisImplementsImageData = true;
+ window.Uint8ClampedArray.prototype.thisImplementsUint8ClampedArray = true;
+ var imgdata = ctx.createImageData(1, 1);
+ @assert imgdata.thisImplementsImageData;
+ @assert imgdata.data.thisImplementsUint8ClampedArray;
+
+- name: 2d.imageData.create1.type
+ desc: createImageData(imgdata) returns an ImageData object containing a Uint8ClampedArray object
+ testing:
+ - 2d.imageData.create1.object
+ code: |
+ @assert window.ImageData !== undefined;
+ @assert window.Uint8ClampedArray !== undefined;
+ window.ImageData.prototype.thisImplementsImageData = true;
+ window.Uint8ClampedArray.prototype.thisImplementsUint8ClampedArray = true;
+ var imgdata = ctx.createImageData(ctx.createImageData(1, 1));
+ @assert imgdata.thisImplementsImageData;
+ @assert imgdata.data.thisImplementsUint8ClampedArray;
+
+- name: 2d.imageData.create2.this
+ desc: createImageData(sw, sh) should throw when called with the wrong |this|
+ notes: *bindings
+ testing:
+ - 2d.imageData.create2.object
+ code: |
+ @assert throws TypeError CanvasRenderingContext2D.prototype.createImageData.call(null, 1, 1); @moz-todo
+ @assert throws TypeError CanvasRenderingContext2D.prototype.createImageData.call(undefined, 1, 1); @moz-todo
+ @assert throws TypeError CanvasRenderingContext2D.prototype.createImageData.call({}, 1, 1); @moz-todo
+
+- name: 2d.imageData.create1.this
+ desc: createImageData(imgdata) should throw when called with the wrong |this|
+ notes: *bindings
+ testing:
+ - 2d.imageData.create2.object
+ code: |
+ var imgdata = ctx.createImageData(1, 1);
+ @assert throws TypeError CanvasRenderingContext2D.prototype.createImageData.call(null, imgdata); @moz-todo
+ @assert throws TypeError CanvasRenderingContext2D.prototype.createImageData.call(undefined, imgdata); @moz-todo
+ @assert throws TypeError CanvasRenderingContext2D.prototype.createImageData.call({}, imgdata); @moz-todo
+
+- name: 2d.imageData.create2.initial
+ desc: createImageData(sw, sh) returns transparent black data of the right size
+ testing:
+ - 2d.imageData.create2.size
+ - 2d.imageData.create.initial
+ - 2d.imageData.initial
+ code: |
+ var imgdata = ctx.createImageData(10, 20);
+ @assert imgdata.data.length === imgdata.width*imgdata.height*4;
+ @assert imgdata.width < imgdata.height;
+ @assert imgdata.width > 0;
+ var isTransparentBlack = true;
+ for (var i = 0; i < imgdata.data.length; ++i)
+ if (imgdata.data[i] !== 0)
+ isTransparentBlack = false;
+ @assert isTransparentBlack;
+
+- name: 2d.imageData.create1.initial
+ desc: createImageData(imgdata) returns transparent black data of the right size
+ testing:
+ - 2d.imageData.create1.size
+ - 2d.imageData.create.initial
+ - 2d.imageData.initial
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ var imgdata1 = ctx.getImageData(0, 0, 10, 20);
+ var imgdata2 = ctx.createImageData(imgdata1);
+ @assert imgdata2.data.length === imgdata1.data.length;
+ @assert imgdata2.width === imgdata1.width;
+ @assert imgdata2.height === imgdata1.height;
+ var isTransparentBlack = true;
+ for (var i = 0; i < imgdata2.data.length; ++i)
+ if (imgdata2.data[i] !== 0)
+ isTransparentBlack = false;
+ @assert isTransparentBlack;
+
+- name: 2d.imageData.create2.large
+ desc: createImageData(sw, sh) works for sizes much larger than the canvas
+ testing:
+ - 2d.imageData.create2.size
+ code: |
+ var imgdata = ctx.createImageData(1000, 2000);
+ @assert imgdata.data.length === imgdata.width*imgdata.height*4;
+ @assert imgdata.width < imgdata.height;
+ @assert imgdata.width > 0;
+ var isTransparentBlack = true;
+ for (var i = 0; i < imgdata.data.length; i += 7813) // check ~1024 points (assuming normal scaling)
+ if (imgdata.data[i] !== 0)
+ isTransparentBlack = false;
+ @assert isTransparentBlack;
+
+- name: 2d.imageData.create2.tiny
+ desc: createImageData(sw, sh) works for sizes smaller than one pixel
+ testing:
+ - 2d.imageData.create2.size
+ - 2d.imageData.one
+ code: |
+ var imgdata = ctx.createImageData(0.0001, 0.0001);
+ @assert imgdata.data.length === imgdata.width*imgdata.height*4;
+ @assert imgdata.width === 1;
+ @assert imgdata.height === 1;
+ var isTransparentBlack = true;
+ for (var i = 0; i < imgdata.data.length; ++i)
+ if (imgdata.data[i] !== 0)
+ isTransparentBlack = false;
+ @assert isTransparentBlack;
+
+- name: 2d.imageData.create2.negative
+ desc: createImageData(sw, sh) takes the absolute magnitude of the size arguments
+ testing:
+ - 2d.imageData.create2.size
+ code: |
+ var imgdata1 = ctx.createImageData(10, 20);
+ var imgdata2 = ctx.createImageData(-10, 20);
+ var imgdata3 = ctx.createImageData(10, -20);
+ var imgdata4 = ctx.createImageData(-10, -20);
+ @assert imgdata1.data.length === imgdata2.data.length;
+ @assert imgdata2.data.length === imgdata3.data.length;
+ @assert imgdata3.data.length === imgdata4.data.length;
+
+- name: 2d.imageData.create2.zero
+ desc: createImageData(sw, sh) throws INDEX_SIZE_ERR if size is zero
+ testing:
+ - 2d.imageData.getcreate.zero
+ code: |
+ @assert throws INDEX_SIZE_ERR ctx.createImageData(10, 0);
+ @assert throws INDEX_SIZE_ERR ctx.createImageData(0, 10);
+ @assert throws INDEX_SIZE_ERR ctx.createImageData(0, 0);
+
+- name: 2d.imageData.create2.nonfinite
+ desc: createImageData() throws TypeError if arguments are not finite
+ notes: *bindings
+ testing:
+ - 2d.imageData.getcreate.nonfinite
+ code: |
+ @nonfinite @assert throws TypeError ctx.createImageData(<10 Infinity -Infinity NaN>, <10 Infinity -Infinity NaN>);
+ var posinfobj = { valueOf: function() { return Infinity; } },
+ neginfobj = { valueOf: function() { return -Infinity; } },
+ nanobj = { valueOf: function() { return -Infinity; } };
+ @nonfinite @assert throws TypeError ctx.createImageData(<10 posinfobj neginfobj nanobj>, <10 posinfobj neginfobj nanobj>);
+
+- name: 2d.imageData.create1.zero
+ desc: createImageData(null) throws TypeError
+ testing:
+ - 2d.imageData.create.null
+ code: |
+ @assert throws TypeError ctx.createImageData(null);
+
+- name: 2d.imageData.create2.round
+ desc: createImageData(w, h) is rounded the same as getImageData(0, 0, w, h)
+ testing:
+ - 2d.imageData.createround
+ code: |
+ var imgdata1 = ctx.createImageData(10.01, 10.99);
+ var imgdata2 = ctx.getImageData(0, 0, 10.01, 10.99);
+ @assert imgdata1.width === imgdata2.width;
+ @assert imgdata1.height === imgdata2.height;
+
+- name: 2d.imageData.get.basic
+ desc: getImageData() exists and returns something
+ testing:
+ - 2d.imageData.get.basic
+ code: |
+ @assert ctx.getImageData(0, 0, 100, 50) !== null;
+
+- name: 2d.imageData.get.type
+ desc: getImageData() returns an ImageData object containing a Uint8ClampedArray object
+ testing:
+ - 2d.imageData.get.object
+ code: |
+ @assert window.ImageData !== undefined;
+ @assert window.Uint8ClampedArray !== undefined;
+ window.ImageData.prototype.thisImplementsImageData = true;
+ window.Uint8ClampedArray.prototype.thisImplementsUint8ClampedArray = true;
+ var imgdata = ctx.getImageData(0, 0, 1, 1);
+ @assert imgdata.thisImplementsImageData;
+ @assert imgdata.data.thisImplementsUint8ClampedArray;
+
+- name: 2d.imageData.get.zero
+ desc: getImageData() throws INDEX_SIZE_ERR if size is zero
+ testing:
+ - 2d.imageData.getcreate.zero
+ code: |
+ @assert throws INDEX_SIZE_ERR ctx.getImageData(1, 1, 10, 0);
+ @assert throws INDEX_SIZE_ERR ctx.getImageData(1, 1, 0, 10);
+ @assert throws INDEX_SIZE_ERR ctx.getImageData(1, 1, 0, 0);
+
+- name: 2d.imageData.get.nonfinite
+ desc: getImageData() throws TypeError if arguments are not finite
+ notes: *bindings
+ testing:
+ - 2d.imageData.getcreate.nonfinite
+ code: |
+ @nonfinite @assert throws TypeError ctx.getImageData(<10 Infinity -Infinity NaN>, <10 Infinity -Infinity NaN>, <10 Infinity -Infinity NaN>, <10 Infinity -Infinity NaN>);
+ var posinfobj = { valueOf: function() { return Infinity; } },
+ neginfobj = { valueOf: function() { return -Infinity; } },
+ nanobj = { valueOf: function() { return -Infinity; } };
+ @nonfinite @assert throws TypeError ctx.getImageData(<10 posinfobj neginfobj nanobj>, <10 posinfobj neginfobj nanobj>, <10 posinfobj neginfobj nanobj>, <10 posinfobj neginfobj nanobj>);
+
+- name: 2d.imageData.get.source.outside
+ desc: getImageData() returns transparent black outside the canvas
+ testing:
+ - 2d.imageData.get.basic
+ - 2d.imageData.get.outside
+ code: |
+ ctx.fillStyle = '#08f';
+ ctx.fillRect(0, 0, 100, 50);
+
+ var imgdata1 = ctx.getImageData(-10, 5, 1, 1);
+ @assert imgdata1.data[0] === 0;
+ @assert imgdata1.data[1] === 0;
+ @assert imgdata1.data[2] === 0;
+ @assert imgdata1.data[3] === 0;
+
+ var imgdata2 = ctx.getImageData(10, -5, 1, 1);
+ @assert imgdata2.data[0] === 0;
+ @assert imgdata2.data[1] === 0;
+ @assert imgdata2.data[2] === 0;
+ @assert imgdata2.data[3] === 0;
+
+ var imgdata3 = ctx.getImageData(200, 5, 1, 1);
+ @assert imgdata3.data[0] === 0;
+ @assert imgdata3.data[1] === 0;
+ @assert imgdata3.data[2] === 0;
+ @assert imgdata3.data[3] === 0;
+
+ var imgdata4 = ctx.getImageData(10, 60, 1, 1);
+ @assert imgdata4.data[0] === 0;
+ @assert imgdata4.data[1] === 0;
+ @assert imgdata4.data[2] === 0;
+ @assert imgdata4.data[3] === 0;
+
+ var imgdata5 = ctx.getImageData(100, 10, 1, 1);
+ @assert imgdata5.data[0] === 0;
+ @assert imgdata5.data[1] === 0;
+ @assert imgdata5.data[2] === 0;
+ @assert imgdata5.data[3] === 0;
+
+ var imgdata6 = ctx.getImageData(0, 10, 1, 1);
+ @assert imgdata6.data[0] === 0;
+ @assert imgdata6.data[1] === 136;
+ @assert imgdata6.data[2] === 255;
+ @assert imgdata6.data[3] === 255;
+
+ var imgdata7 = ctx.getImageData(-10, 10, 20, 20);
+ @assert imgdata7.data[ 0*4+0] === 0;
+ @assert imgdata7.data[ 0*4+1] === 0;
+ @assert imgdata7.data[ 0*4+2] === 0;
+ @assert imgdata7.data[ 0*4+3] === 0;
+ @assert imgdata7.data[ 9*4+0] === 0;
+ @assert imgdata7.data[ 9*4+1] === 0;
+ @assert imgdata7.data[ 9*4+2] === 0;
+ @assert imgdata7.data[ 9*4+3] === 0;
+ @assert imgdata7.data[10*4+0] === 0;
+ @assert imgdata7.data[10*4+1] === 136;
+ @assert imgdata7.data[10*4+2] === 255;
+ @assert imgdata7.data[10*4+3] === 255;
+ @assert imgdata7.data[19*4+0] === 0;
+ @assert imgdata7.data[19*4+1] === 136;
+ @assert imgdata7.data[19*4+2] === 255;
+ @assert imgdata7.data[19*4+3] === 255;
+ @assert imgdata7.data[20*4+0] === 0;
+ @assert imgdata7.data[20*4+1] === 0;
+ @assert imgdata7.data[20*4+2] === 0;
+ @assert imgdata7.data[20*4+3] === 0;
+
+- name: 2d.imageData.get.source.negative
+ desc: getImageData() works with negative width and height, and returns top-to-bottom left-to-right
+ testing:
+ - 2d.imageData.get.basic
+ - 2d.pixelarray.order
+ code: |
+ ctx.fillStyle = '#000';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#fff';
+ ctx.fillRect(20, 10, 60, 10);
+
+ var imgdata1 = ctx.getImageData(85, 25, -10, -10);
+ @assert imgdata1.data[0] === 255;
+ @assert imgdata1.data[1] === 255;
+ @assert imgdata1.data[2] === 255;
+ @assert imgdata1.data[3] === 255;
+ @assert imgdata1.data[imgdata1.data.length-4+0] === 0;
+ @assert imgdata1.data[imgdata1.data.length-4+1] === 0;
+ @assert imgdata1.data[imgdata1.data.length-4+2] === 0;
+ @assert imgdata1.data[imgdata1.data.length-4+3] === 255;
+
+ var imgdata2 = ctx.getImageData(0, 0, -1, -1);
+ @assert imgdata2.data[0] === 0;
+ @assert imgdata2.data[1] === 0;
+ @assert imgdata2.data[2] === 0;
+ @assert imgdata2.data[3] === 0;
+
+- name: 2d.imageData.get.source.size
+ desc: getImageData() returns bigger ImageData for bigger source rectangle
+ testing:
+ - 2d.imageData.get.basic
+ code: |
+ var imgdata1 = ctx.getImageData(0, 0, 10, 10);
+ var imgdata2 = ctx.getImageData(0, 0, 20, 20);
+ @assert imgdata2.width > imgdata1.width;
+ @assert imgdata2.height > imgdata1.height;
+
+- name: 2d.imageData.get.tiny
+ desc: getImageData() works for sizes smaller than one pixel
+ testing:
+ - 2d.imageData.one
+ code: |
+ var imgdata = ctx.getImageData(0, 0, 0.0001, 0.0001);
+ @assert imgdata.data.length === imgdata.width*imgdata.height*4;
+ @assert imgdata.width === 1;
+ @assert imgdata.height === 1;
+
+- name: 2d.imageData.get.nonpremul
+ desc: getImageData() returns non-premultiplied colours
+ testing:
+ - 2d.imageData.get.premul
+ code: |
+ ctx.fillStyle = 'rgba(255, 255, 255, 0.5)';
+ ctx.fillRect(0, 0, 100, 50);
+ var imgdata = ctx.getImageData(10, 10, 10, 10);
+ @assert imgdata.data[0] > 200;
+ @assert imgdata.data[1] > 200;
+ @assert imgdata.data[2] > 200;
+ @assert imgdata.data[3] > 100;
+ @assert imgdata.data[3] < 200;
+
+- name: 2d.imageData.get.range
+ desc: getImageData() returns values in the range [0, 255]
+ testing:
+ - 2d.pixelarray.range
+ - 2d.pixelarray.retrieve
+ code: |
+ ctx.fillStyle = '#000';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#fff';
+ ctx.fillRect(20, 10, 60, 10);
+ var imgdata1 = ctx.getImageData(10, 5, 1, 1);
+ @assert imgdata1.data[0] === 0;
+ var imgdata2 = ctx.getImageData(30, 15, 1, 1);
+ @assert imgdata2.data[0] === 255;
+
+- name: 2d.imageData.get.clamp
+ desc: getImageData() clamps colours to the range [0, 255]
+ testing:
+ - 2d.pixelarray.range
+ code: |
+ ctx.fillStyle = 'rgb(-100, -200, -300)';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = 'rgb(256, 300, 400)';
+ ctx.fillRect(20, 10, 60, 10);
+ var imgdata1 = ctx.getImageData(10, 5, 1, 1);
+ @assert imgdata1.data[0] === 0;
+ @assert imgdata1.data[1] === 0;
+ @assert imgdata1.data[2] === 0;
+ var imgdata2 = ctx.getImageData(30, 15, 1, 1);
+ @assert imgdata2.data[0] === 255;
+ @assert imgdata2.data[1] === 255;
+ @assert imgdata2.data[2] === 255;
+
+- name: 2d.imageData.get.length
+ desc: getImageData() returns a correctly-sized Uint8ClampedArray
+ testing:
+ - 2d.pixelarray.length
+ code: |
+ var imgdata = ctx.getImageData(0, 0, 10, 10);
+ @assert imgdata.data.length === imgdata.width*imgdata.height*4;
+
+- name: 2d.imageData.get.order.cols
+ desc: getImageData() returns leftmost columns first
+ testing:
+ - 2d.pixelarray.order
+ code: |
+ ctx.fillStyle = '#fff';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#000';
+ ctx.fillRect(0, 0, 2, 50);
+ var imgdata = ctx.getImageData(0, 0, 10, 10);
+ @assert imgdata.data[0] === 0;
+ @assert imgdata.data[Math.round(imgdata.width/2*4)] === 255;
+ @assert imgdata.data[Math.round((imgdata.height/2)*imgdata.width*4)] === 0;
+
+- name: 2d.imageData.get.order.rows
+ desc: getImageData() returns topmost rows first
+ testing:
+ - 2d.pixelarray.order
+ code: |
+ ctx.fillStyle = '#fff';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#000';
+ ctx.fillRect(0, 0, 100, 2);
+ var imgdata = ctx.getImageData(0, 0, 10, 10);
+ @assert imgdata.data[0] === 0;
+ @assert imgdata.data[Math.floor(imgdata.width/2*4)] === 0;
+ @assert imgdata.data[(imgdata.height/2)*imgdata.width*4] === 255;
+
+- name: 2d.imageData.get.order.rgb
+ desc: getImageData() returns R then G then B
+ testing:
+ - 2d.pixelarray.order
+ - 2d.pixelarray.indexes
+ code: |
+ ctx.fillStyle = '#48c';
+ ctx.fillRect(0, 0, 100, 50);
+ var imgdata = ctx.getImageData(0, 0, 10, 10);
+ @assert imgdata.data[0] === 0x44;
+ @assert imgdata.data[1] === 0x88;
+ @assert imgdata.data[2] === 0xCC;
+ @assert imgdata.data[3] === 255;
+ @assert imgdata.data[4] === 0x44;
+ @assert imgdata.data[5] === 0x88;
+ @assert imgdata.data[6] === 0xCC;
+ @assert imgdata.data[7] === 255;
+
+- name: 2d.imageData.get.order.alpha
+ desc: getImageData() returns A in the fourth component
+ testing:
+ - 2d.pixelarray.order
+ code: |
+ ctx.fillStyle = 'rgba(0, 0, 0, 0.5)';
+ ctx.fillRect(0, 0, 100, 50);
+ var imgdata = ctx.getImageData(0, 0, 10, 10);
+ @assert imgdata.data[3] < 200;
+ @assert imgdata.data[3] > 100;
+
+- name: 2d.imageData.get.unaffected
+ desc: getImageData() is not affected by context state
+ testing:
+ - 2d.imageData.unaffected
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 50, 50)
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(50, 0, 50, 50)
+ ctx.save();
+ ctx.translate(50, 0);
+ ctx.globalAlpha = 0.1;
+ ctx.globalCompositeOperation = 'destination-atop';
+ ctx.shadowColor = '#f00';
+ ctx.rect(0, 0, 5, 5);
+ ctx.clip();
+ var imgdata = ctx.getImageData(0, 0, 50, 50);
+ ctx.restore();
+ ctx.putImageData(imgdata, 50, 0);
+ @assert pixel 25,25 ==~ 0,255,0,255;
+ @assert pixel 75,25 ==~ 0,255,0,255;
+ expected: green
+
+
+- name: 2d.imageData.object.properties
+ desc: ImageData objects have the right properties
+ testing:
+ - 2d.imageData.type
+ code: |
+ var imgdata = ctx.getImageData(0, 0, 10, 10);
+ @assert typeof(imgdata.width) === 'number';
+ @assert typeof(imgdata.height) === 'number';
+ @assert typeof(imgdata.data) === 'object';
+
+- name: 2d.imageData.object.readonly
+ desc: ImageData objects properties are read-only
+ testing:
+ - 2d.imageData.type
+ code: |
+ var imgdata = ctx.getImageData(0, 0, 10, 10);
+ var w = imgdata.width;
+ var h = imgdata.height;
+ var d = imgdata.data;
+ imgdata.width = 123;
+ imgdata.height = 123;
+ imgdata.data = [100,100,100,100];
+ @assert imgdata.width === w;
+ @assert imgdata.height === h;
+ @assert imgdata.data === d;
+ @assert imgdata.data[0] === 0;
+ @assert imgdata.data[1] === 0;
+ @assert imgdata.data[2] === 0;
+ @assert imgdata.data[3] === 0;
+
+- name: 2d.imageData.object.ctor
+ desc: ImageData does not have a usable constructor
+ testing:
+ - 2d.imageData.type
+ code: |
+ @assert window.ImageData !== undefined;
+ @assert throws TypeError new window.ImageData(1,1);
+
+- name: 2d.imageData.object.set
+ desc: ImageData.data can be modified
+ testing:
+ - 2d.pixelarray.modify
+ code: |
+ var imgdata = ctx.getImageData(0, 0, 10, 10);
+ imgdata.data[0] = 100;
+ @assert imgdata.data[0] === 100;
+ imgdata.data[0] = 200;
+ @assert imgdata.data[0] === 200;
+
+- name: 2d.imageData.object.undefined
+ desc: ImageData.data converts undefined to 0
+ testing:
+ - 2d.pixelarray.modify
+ webidl:
+ - es-octet
+ code: |
+ var imgdata = ctx.getImageData(0, 0, 10, 10);
+ imgdata.data[0] = 100;
+ imgdata.data[0] = undefined;
+ @assert imgdata.data[0] === 0;
+
+- name: 2d.imageData.object.nan
+ desc: ImageData.data converts NaN to 0
+ testing:
+ - 2d.pixelarray.modify
+ webidl:
+ - es-octet
+ code: |
+ var imgdata = ctx.getImageData(0, 0, 10, 10);
+ imgdata.data[0] = 100;
+ imgdata.data[0] = NaN;
+ @assert imgdata.data[0] === 0;
+ imgdata.data[0] = 100;
+ imgdata.data[0] = "cheese";
+ @assert imgdata.data[0] === 0;
+
+- name: 2d.imageData.object.string
+ desc: ImageData.data converts strings to numbers with ToNumber
+ testing:
+ - 2d.pixelarray.modify
+ webidl:
+ - es-octet
+ code: |
+ var imgdata = ctx.getImageData(0, 0, 10, 10);
+ imgdata.data[0] = 100;
+ imgdata.data[0] = "110";
+ @assert imgdata.data[0] === 110;
+ imgdata.data[0] = 100;
+ imgdata.data[0] = "0x78";
+ @assert imgdata.data[0] === 120;
+ imgdata.data[0] = 100;
+ imgdata.data[0] = " +130e0 ";
+ @assert imgdata.data[0] === 130;
+
+- name: 2d.imageData.object.clamp
+ desc: ImageData.data clamps numbers to [0, 255]
+ testing:
+ - 2d.pixelarray.modify
+ webidl:
+ - es-octet
+ code: |
+ var imgdata = ctx.getImageData(0, 0, 10, 10);
+
+ imgdata.data[0] = 100;
+ imgdata.data[0] = 300;
+ @assert imgdata.data[0] === 255;
+ imgdata.data[0] = 100;
+ imgdata.data[0] = -100;
+ @assert imgdata.data[0] === 0;
+
+ imgdata.data[0] = 100;
+ imgdata.data[0] = 200+Math.pow(2, 32);
+ @assert imgdata.data[0] === 255;
+ imgdata.data[0] = 100;
+ imgdata.data[0] = -200-Math.pow(2, 32);
+ @assert imgdata.data[0] === 0;
+
+ imgdata.data[0] = 100;
+ imgdata.data[0] = Math.pow(10, 39);
+ @assert imgdata.data[0] === 255;
+ imgdata.data[0] = 100;
+ imgdata.data[0] = -Math.pow(10, 39);
+ @assert imgdata.data[0] === 0;
+
+ imgdata.data[0] = 100;
+ imgdata.data[0] = -Infinity;
+ @assert imgdata.data[0] === 0;
+ imgdata.data[0] = 100;
+ imgdata.data[0] = Infinity;
+ @assert imgdata.data[0] === 255;
+
+- name: 2d.imageData.object.round
+ desc: ImageData.data rounds numbers with round-to-zero
+ testing:
+ - 2d.pixelarray.modify
+ webidl:
+ - es-octet
+ code: |
+ var imgdata = ctx.getImageData(0, 0, 10, 10);
+ imgdata.data[0] = 0.499;
+ @assert imgdata.data[0] === 0;
+ imgdata.data[0] = 0.5;
+ @assert imgdata.data[0] === 0;
+ imgdata.data[0] = 0.501;
+ @assert imgdata.data[0] === 1;
+ imgdata.data[0] = 1.499;
+ @assert imgdata.data[0] === 1;
+ imgdata.data[0] = 1.5;
+ @assert imgdata.data[0] === 2;
+ imgdata.data[0] = 1.501;
+ @assert imgdata.data[0] === 2;
+ imgdata.data[0] = 2.5;
+ @assert imgdata.data[0] === 2;
+ imgdata.data[0] = 3.5;
+ @assert imgdata.data[0] === 4;
+ imgdata.data[0] = 252.5;
+ @assert imgdata.data[0] === 252;
+ imgdata.data[0] = 253.5;
+ @assert imgdata.data[0] === 254;
+ imgdata.data[0] = 254.5;
+ @assert imgdata.data[0] === 254;
+ imgdata.data[0] = 256.5;
+ @assert imgdata.data[0] === 255;
+ imgdata.data[0] = -0.5;
+ @assert imgdata.data[0] === 0;
+ imgdata.data[0] = -1.5;
+ @assert imgdata.data[0] === 0;
+
+
+
+- name: 2d.imageData.put.null
+ desc: putImageData() with null imagedata throws TypeError
+ testing:
+ - 2d.imageData.put.wrongtype
+ code: |
+ @assert throws TypeError ctx.putImageData(null, 0, 0);
+
+- name: 2d.imageData.put.nonfinite
+ desc: putImageData() throws TypeError if arguments are not finite
+ notes: *bindings
+ testing:
+ - 2d.imageData.put.nonfinite
+ code: |
+ var imgdata = ctx.getImageData(0, 0, 10, 10);
+ @nonfinite @assert throws TypeError ctx.putImageData(<imgdata>, <10 Infinity -Infinity NaN>, <10 Infinity -Infinity NaN>);
+ @nonfinite @assert throws TypeError ctx.putImageData(<imgdata>, <10 Infinity -Infinity NaN>, <10 Infinity -Infinity NaN>, <10 Infinity -Infinity NaN>, <10 Infinity -Infinity NaN>, <10 Infinity -Infinity NaN>, <10 Infinity -Infinity NaN>);
+
+- name: 2d.imageData.put.basic
+ desc: putImageData() puts image data from getImageData() onto the canvas
+ testing:
+ - 2d.imageData.put.normal
+ - 2d.imageData.put.3arg
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50)
+ var imgdata = ctx.getImageData(0, 0, 100, 50);
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50)
+ ctx.putImageData(imgdata, 0, 0);
+ @assert pixel 50,25 ==~ 0,255,0,255;
+ expected: green
+
+- name: 2d.imageData.put.created
+ desc: putImageData() puts image data from createImageData() onto the canvas
+ testing:
+ - 2d.imageData.put.normal
+ code: |
+ var imgdata = ctx.createImageData(100, 50);
+ for (var i = 0; i < imgdata.data.length; i += 4) {
+ imgdata.data[i] = 0;
+ imgdata.data[i+1] = 255;
+ imgdata.data[i+2] = 0;
+ imgdata.data[i+3] = 255;
+ }
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50)
+ ctx.putImageData(imgdata, 0, 0);
+ @assert pixel 50,25 ==~ 0,255,0,255;
+ expected: green
+
+- name: 2d.imageData.put.wrongtype
+ desc: putImageData() does not accept non-ImageData objects
+ testing:
+ - 2d.imageData.put.wrongtype
+ code: |
+ var imgdata = { width: 1, height: 1, data: [255, 0, 0, 255] };
+ @assert throws TypeError ctx.putImageData(imgdata, 0, 0);
+ @assert throws TypeError ctx.putImageData("cheese", 0, 0);
+ @assert throws TypeError ctx.putImageData(42, 0, 0);
+ expected: green
+
+- name: 2d.imageData.put.cross
+ desc: putImageData() accepts image data got from a different canvas
+ testing:
+ - 2d.imageData.put.normal
+ code: |
+ var canvas2 = document.createElement('canvas');
+ var ctx2 = canvas2.getContext('2d');
+ ctx2.fillStyle = '#0f0';
+ ctx2.fillRect(0, 0, 100, 50)
+ var imgdata = ctx2.getImageData(0, 0, 100, 50);
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50)
+ ctx.putImageData(imgdata, 0, 0);
+ @assert pixel 50,25 ==~ 0,255,0,255;
+ expected: green
+
+- name: 2d.imageData.put.alpha
+ desc: putImageData() puts non-solid image data correctly
+ testing:
+ - 2d.imageData.put.normal
+ code: |
+ ctx.fillStyle = 'rgba(0, 255, 0, 0.25)';
+ ctx.fillRect(0, 0, 100, 50)
+ var imgdata = ctx.getImageData(0, 0, 100, 50);
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50)
+ ctx.putImageData(imgdata, 0, 0);
+ @assert pixel 50,25 ==~ 0,255,0,64;
+ expected: |
+ size 100 50
+ cr.set_source_rgba(0, 1, 0, 0.25)
+ cr.rectangle(0, 0, 100, 50)
+ cr.fill()
+
+- name: 2d.imageData.put.modified
+ desc: putImageData() puts modified image data correctly
+ testing:
+ - 2d.imageData.put.normal
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50)
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(45, 20, 10, 10)
+ var imgdata = ctx.getImageData(45, 20, 10, 10);
+ for (var i = 0, len = imgdata.width*imgdata.height*4; i < len; i += 4)
+ {
+ imgdata.data[i] = 0;
+ imgdata.data[i+1] = 255;
+ }
+ ctx.putImageData(imgdata, 45, 20);
+ @assert pixel 50,25 ==~ 0,255,0,255;
+ expected: green
+
+- name: 2d.imageData.put.dirty.zero
+ desc: putImageData() with zero-sized dirty rectangle puts nothing
+ testing:
+ - 2d.imageData.put.normal
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50)
+ var imgdata = ctx.getImageData(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50)
+ ctx.putImageData(imgdata, 0, 0, 0, 0, 0, 0);
+ @assert pixel 50,25 ==~ 0,255,0,255;
+ expected: green
+
+- name: 2d.imageData.put.dirty.rect1
+ desc: putImageData() only modifies areas inside the dirty rectangle, using width and height
+ testing:
+ - 2d.imageData.put.normal
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50)
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 20, 20)
+
+ var imgdata = ctx.getImageData(0, 0, 100, 50);
+
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50)
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(40, 20, 20, 20)
+ ctx.putImageData(imgdata, 40, 20, 0, 0, 20, 20);
+
+ @assert pixel 50,25 ==~ 0,255,0,255;
+ @assert pixel 35,25 ==~ 0,255,0,255;
+ @assert pixel 65,25 ==~ 0,255,0,255;
+ @assert pixel 50,15 ==~ 0,255,0,255;
+ @assert pixel 50,45 ==~ 0,255,0,255;
+ expected: green
+
+- name: 2d.imageData.put.dirty.rect2
+ desc: putImageData() only modifies areas inside the dirty rectangle, using x and y
+ testing:
+ - 2d.imageData.put.normal
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50)
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(60, 30, 20, 20)
+
+ var imgdata = ctx.getImageData(0, 0, 100, 50);
+
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50)
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(40, 20, 20, 20)
+ ctx.putImageData(imgdata, -20, -10, 60, 30, 20, 20);
+
+ @assert pixel 50,25 ==~ 0,255,0,255;
+ @assert pixel 35,25 ==~ 0,255,0,255;
+ @assert pixel 65,25 ==~ 0,255,0,255;
+ @assert pixel 50,15 ==~ 0,255,0,255;
+ @assert pixel 50,45 ==~ 0,255,0,255;
+ expected: green
+
+- name: 2d.imageData.put.dirty.negative
+ desc: putImageData() handles negative-sized dirty rectangles correctly
+ testing:
+ - 2d.imageData.put.normal
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50)
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 20, 20)
+
+ var imgdata = ctx.getImageData(0, 0, 100, 50);
+
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50)
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(40, 20, 20, 20)
+ ctx.putImageData(imgdata, 40, 20, 20, 20, -20, -20);
+
+ @assert pixel 50,25 ==~ 0,255,0,255;
+ @assert pixel 35,25 ==~ 0,255,0,255;
+ @assert pixel 65,25 ==~ 0,255,0,255;
+ @assert pixel 50,15 ==~ 0,255,0,255;
+ @assert pixel 50,45 ==~ 0,255,0,255;
+ expected: green
+
+- name: 2d.imageData.put.dirty.outside
+ desc: putImageData() handles dirty rectangles outside the canvas correctly
+ testing:
+ - 2d.imageData.put.normal
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50)
+
+ var imgdata = ctx.getImageData(0, 0, 100, 50);
+
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50)
+
+ ctx.putImageData(imgdata, 100, 20, 20, 20, -20, -20);
+ ctx.putImageData(imgdata, 200, 200, 0, 0, 100, 50);
+ ctx.putImageData(imgdata, 40, 20, -30, -20, 30, 20);
+ ctx.putImageData(imgdata, -30, 20, 0, 0, 30, 20);
+
+ @assert pixel 50,25 ==~ 0,255,0,255;
+ @assert pixel 98,15 ==~ 0,255,0,255;
+ @assert pixel 98,25 ==~ 0,255,0,255;
+ @assert pixel 98,45 ==~ 0,255,0,255;
+ @assert pixel 1,5 ==~ 0,255,0,255;
+ @assert pixel 1,25 ==~ 0,255,0,255;
+ @assert pixel 1,45 ==~ 0,255,0,255;
+ expected: green
+
+- name: 2d.imageData.put.unchanged
+ desc: putImageData(getImageData(...), ...) has no effect
+ testing:
+ - 2d.imageData.unchanged
+ code: |
+ var i = 0;
+ for (var y = 0; y < 16; ++y) {
+ for (var x = 0; x < 16; ++x, ++i) {
+ ctx.fillStyle = 'rgba(' + i + ',' + (Math.floor(i*1.5) % 256) + ',' + (Math.floor(i*23.3) % 256) + ',' + (i/256) + ')';
+ ctx.fillRect(x, y, 1, 1);
+ }
+ }
+ var imgdata1 = ctx.getImageData(0.1, 0.2, 15.8, 15.9);
+ var olddata = [];
+ for (var i = 0; i < imgdata1.data.length; ++i)
+ olddata[i] = imgdata1.data[i];
+
+ ctx.putImageData(imgdata1, 0.1, 0.2);
+
+ var imgdata2 = ctx.getImageData(0.1, 0.2, 15.8, 15.9);
+ for (var i = 0; i < imgdata2.data.length; ++i) {
+ @assert olddata[i] === imgdata2.data[i];
+ }
+
+- name: 2d.imageData.put.unaffected
+ desc: putImageData() is not affected by context state
+ testing:
+ - 2d.imageData.unaffected
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50)
+ var imgdata = ctx.getImageData(0, 0, 100, 50);
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50)
+ ctx.globalAlpha = 0.1;
+ ctx.globalCompositeOperation = 'destination-atop';
+ ctx.shadowColor = '#f00';
+ ctx.shadowBlur = 1;
+ ctx.translate(100, 50);
+ ctx.scale(0.1, 0.1);
+ ctx.putImageData(imgdata, 0, 0);
+ @assert pixel 50,25 ==~ 0,255,0,255;
+ expected: green
+
+- name: 2d.imageData.put.clip
+ desc: putImageData() is not affected by clipping regions
+ testing:
+ - 2d.imageData.unaffected
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50)
+ var imgdata = ctx.getImageData(0, 0, 100, 50);
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50)
+ ctx.beginPath();
+ ctx.rect(0, 0, 50, 50);
+ ctx.clip();
+ ctx.putImageData(imgdata, 0, 0);
+ @assert pixel 25,25 ==~ 0,255,0,255;
+ @assert pixel 75,25 ==~ 0,255,0,255;
+ expected: green
+
+- name: 2d.imageData.put.path
+ desc: putImageData() does not affect the current path
+ testing:
+ - 2d.imageData.put.normal
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50)
+ ctx.rect(0, 0, 100, 50);
+ var imgdata = ctx.getImageData(0, 0, 100, 50);
+ ctx.putImageData(imgdata, 0, 0);
+ ctx.fillStyle = '#0f0';
+ ctx.fill();
+ @assert pixel 50,25 ==~ 0,255,0,255;
+ expected: green
diff --git a/tests/wpt/web-platform-tests/2dcontext/tools/tests2dtext.yaml b/tests/wpt/web-platform-tests/2dcontext/tools/tests2dtext.yaml
new file mode 100644
index 00000000000..e2358494eed
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/tools/tests2dtext.yaml
@@ -0,0 +1,1000 @@
+# Copyright (c) 2010 Philip Taylor
+# Released under the BSD license and W3C Test Suite License: see LICENSE.txt
+
+- name: 2d.text.font.parse.basic
+ testing:
+ - 2d.text.font.parse
+ - 2d.text.font.get
+ code: |
+ ctx.font = '20px serif';
+ @assert ctx.font === '20px serif';
+
+ ctx.font = '20PX SERIF';
+ @assert ctx.font === '20px serif'; @moz-todo
+
+- name: 2d.text.font.parse.complex
+ testing:
+ - 2d.text.font.parse
+ - 2d.text.font.get
+ - 2d.text.font.lineheight
+ code: |
+ ctx.font = 'small-caps italic 400 12px/2 Unknown Font, sans-serif';
+ @assert ctx.font === 'italic small-caps 12px "Unknown Font", sans-serif'; @moz-todo
+
+ # TODO:
+ # 2d.text.font.parse.size.absolute
+ # xx-small x-small small medium large x-large xx-large
+ # 2d.text.font.parse.size.relative
+ # smaller larger
+ # 2d.text.font.parse.size.length.relative
+ # em ex px
+ # 2d.text.font.parse.size.length.absolute
+ # in cm mm pt pc
+
+- name: 2d.text.font.parse.size.percentage
+ testing:
+ - 2d.text.font.parse
+ - 2d.text.font.get
+ - 2d.text.font.fontsize
+ - 2d.text.font.size
+ canvas: 'style="font-size: 144px" width="100" height="50"'
+ code: |
+ ctx.font = '50% serif';
+ @assert ctx.font === '72px serif'; @moz-todo
+ canvas.setAttribute('style', 'font-size: 100px');
+ @assert ctx.font === '72px serif'; @moz-todo
+
+- name: 2d.text.font.parse.size.percentage.default
+ testing:
+ - 2d.text.font.undefined
+ code: |
+ var canvas2 = document.createElement('canvas');
+ var ctx2 = canvas2.getContext('2d');
+ ctx2.font = '1000% serif';
+ @assert ctx2.font === '100px serif'; @moz-todo
+
+- name: 2d.text.font.parse.system
+ desc: System fonts must be computed to explicit values
+ testing:
+ - 2d.text.font.parse
+ - 2d.text.font.get
+ - 2d.text.font.systemfonts
+ code: |
+ ctx.font = 'message-box';
+ @assert ctx.font !== 'message-box';
+
+- name: 2d.text.font.parse.invalid
+ testing:
+ - 2d.text.font.invalid
+ code: |
+ ctx.font = '20px serif';
+ @assert ctx.font === '20px serif';
+
+ ctx.font = '20px serif';
+ ctx.font = 'bogus';
+ @assert ctx.font === '20px serif';
+
+ ctx.font = '20px serif';
+ ctx.font = 'inherit';
+ @assert ctx.font === '20px serif';
+
+ ctx.font = '20px serif';
+ ctx.font = '10px {bogus}';
+ @assert ctx.font === '20px serif';
+
+ ctx.font = '20px serif';
+ ctx.font = '10px initial';
+ @assert ctx.font === '20px serif'; @moz-todo
+
+ ctx.font = '20px serif';
+ ctx.font = '10px default';
+ @assert ctx.font === '20px serif'; @moz-todo
+
+ ctx.font = '20px serif';
+ ctx.font = '10px inherit';
+ @assert ctx.font === '20px serif';
+
+ ctx.font = '20px serif';
+ ctx.font = '1em serif; background: green; margin: 10px';
+ @assert ctx.font === '20px serif';
+
+- name: 2d.text.font.default
+ testing:
+ - 2d.text.font.default
+ code: |
+ @assert ctx.font === '10px sans-serif';
+
+
+
+- name: 2d.text.align.valid
+ testing:
+ - 2d.text.align.get
+ - 2d.text.align.set
+ code: |
+ ctx.textAlign = 'start';
+ @assert ctx.textAlign === 'start';
+
+ ctx.textAlign = 'end';
+ @assert ctx.textAlign === 'end';
+
+ ctx.textAlign = 'left';
+ @assert ctx.textAlign === 'left';
+
+ ctx.textAlign = 'right';
+ @assert ctx.textAlign === 'right';
+
+ ctx.textAlign = 'center';
+ @assert ctx.textAlign === 'center';
+
+- name: 2d.text.align.invalid
+ testing:
+ - 2d.text.align.invalid
+ code: |
+ ctx.textAlign = 'start';
+ ctx.textAlign = 'bogus';
+ @assert ctx.textAlign === 'start';
+
+ ctx.textAlign = 'start';
+ ctx.textAlign = 'END';
+ @assert ctx.textAlign === 'start';
+
+ ctx.textAlign = 'start';
+ ctx.textAlign = 'end ';
+ @assert ctx.textAlign === 'start';
+
+ ctx.textAlign = 'start';
+ ctx.textAlign = 'end\0';
+ @assert ctx.textAlign === 'start';
+
+- name: 2d.text.align.default
+ testing:
+ - 2d.text.align.default
+ code: |
+ @assert ctx.textAlign === 'start';
+
+
+- name: 2d.text.baseline.valid
+ testing:
+ - 2d.text.baseline.get
+ - 2d.text.baseline.set
+ code: |
+ ctx.textBaseline = 'top';
+ @assert ctx.textBaseline === 'top';
+
+ ctx.textBaseline = 'hanging';
+ @assert ctx.textBaseline === 'hanging';
+
+ ctx.textBaseline = 'middle';
+ @assert ctx.textBaseline === 'middle';
+
+ ctx.textBaseline = 'alphabetic';
+ @assert ctx.textBaseline === 'alphabetic';
+
+ ctx.textBaseline = 'ideographic';
+ @assert ctx.textBaseline === 'ideographic';
+
+ ctx.textBaseline = 'bottom';
+ @assert ctx.textBaseline === 'bottom';
+
+- name: 2d.text.baseline.invalid
+ testing:
+ - 2d.text.baseline.invalid
+ code: |
+ ctx.textBaseline = 'top';
+ ctx.textBaseline = 'bogus';
+ @assert ctx.textBaseline === 'top';
+
+ ctx.textBaseline = 'top';
+ ctx.textBaseline = 'MIDDLE';
+ @assert ctx.textBaseline === 'top';
+
+ ctx.textBaseline = 'top';
+ ctx.textBaseline = 'middle ';
+ @assert ctx.textBaseline === 'top';
+
+ ctx.textBaseline = 'top';
+ ctx.textBaseline = 'middle\0';
+ @assert ctx.textBaseline === 'top';
+
+- name: 2d.text.baseline.default
+ testing:
+ - 2d.text.baseline.default
+ code: |
+ @assert ctx.textBaseline === 'alphabetic';
+
+
+
+
+
+- name: 2d.text.draw.fill.basic
+ desc: fillText draws filled text
+ manual:
+ testing:
+ - 2d.text.draw
+ - 2d.text.draw.fill
+ code: |
+ ctx.fillStyle = '#000';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.strokeStyle = '#f00';
+ ctx.font = '35px Arial, sans-serif';
+ ctx.fillText('PASS', 5, 35);
+ expected: &passfill |
+ size 100 50
+ cr.set_source_rgb(0, 0, 0)
+ cr.rectangle(0, 0, 100, 50)
+ cr.fill()
+ cr.set_source_rgb(0, 1, 0)
+ cr.select_font_face("Arial")
+ cr.set_font_size(35)
+ cr.translate(5, 35)
+ cr.text_path("PASS")
+ cr.fill()
+
+- name: 2d.text.draw.fill.unaffected
+ desc: fillText does not start a new path or subpath
+ testing:
+ - 2d.text.draw.fill
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.moveTo(0, 0);
+ ctx.lineTo(100, 0);
+
+ ctx.font = '35px Arial, sans-serif';
+ ctx.fillText('FAIL', 5, 35);
+
+ ctx.lineTo(100, 50);
+ ctx.lineTo(0, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.fill();
+
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 5,45 == 0,255,0,255;
+ expected: green
+
+- name: 2d.text.draw.fill.rtl
+ desc: fillText respects Right-To-Left Override characters
+ manual:
+ testing:
+ - 2d.text.draw
+ code: |
+ ctx.fillStyle = '#000';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.strokeStyle = '#f00';
+ ctx.font = '35px Arial, sans-serif';
+ ctx.fillText('\u202eFAIL \xa0 \xa0 SSAP', 5, 35);
+ expected: *passfill
+
+- name: 2d.text.draw.fill.maxWidth.large
+ desc: fillText handles maxWidth correctly
+ manual:
+ testing:
+ - 2d.text.draw.maxwidth
+ code: |
+ ctx.fillStyle = '#000';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.font = '35px Arial, sans-serif';
+ ctx.fillText('PASS', 5, 35, 200);
+ expected: *passfill
+
+- name: 2d.text.draw.fill.maxWidth.small
+ desc: fillText handles maxWidth correctly
+ testing:
+ - 2d.text.draw.maxwidth
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#f00';
+ ctx.font = '35px Arial, sans-serif';
+ ctx.fillText('fail fail fail fail fail', -100, 35, 90);
+ _assertGreen(ctx, 100, 50);
+ expected: green
+
+- name: 2d.text.draw.fill.maxWidth.zero
+ desc: fillText handles maxWidth correctly
+ testing:
+ - 2d.text.draw.maxwidth
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#f00';
+ ctx.font = '35px Arial, sans-serif';
+ ctx.fillText('fail fail fail fail fail', 5, 35, 0);
+ _assertGreen(ctx, 100, 50);
+ expected: green
+
+- name: 2d.text.draw.fill.maxWidth.negative
+ desc: fillText handles maxWidth correctly
+ testing:
+ - 2d.text.draw.maxwidth
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#f00';
+ ctx.font = '35px Arial, sans-serif';
+ ctx.fillText('fail fail fail fail fail', 5, 35, -1);
+ _assertGreen(ctx, 100, 50);
+ expected: green
+
+- name: 2d.text.draw.stroke.basic
+ desc: strokeText draws stroked text
+ manual:
+ testing:
+ - 2d.text.draw
+ - 2d.text.draw.stroke
+ code: |
+ ctx.fillStyle = '#000';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.strokeStyle = '#0f0';
+ ctx.fillStyle = '#f00';
+ ctx.lineWidth = 1;
+ ctx.font = '35px Arial, sans-serif';
+ ctx.strokeText('PASS', 5, 35);
+ expected: |
+ size 100 50
+ cr.set_source_rgb(0, 0, 0)
+ cr.rectangle(0, 0, 100, 50)
+ cr.fill()
+ cr.set_source_rgb(0, 1, 0)
+ cr.select_font_face("Arial")
+ cr.set_font_size(35)
+ cr.set_line_width(1)
+ cr.translate(5, 35)
+ cr.text_path("PASS")
+ cr.stroke()
+
+- name: 2d.text.draw.stroke.unaffected
+ desc: strokeText does not start a new path or subpath
+ testing:
+ - 2d.text.draw.stroke
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+
+ ctx.moveTo(0, 0);
+ ctx.lineTo(100, 0);
+
+ ctx.font = '35px Arial, sans-serif';
+ ctx.strokeStyle = '#f00';
+ ctx.strokeText('FAIL', 5, 35);
+
+ ctx.lineTo(100, 50);
+ ctx.lineTo(0, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.fill();
+
+ @assert pixel 50,25 == 0,255,0,255;
+ @assert pixel 5,45 == 0,255,0,255;
+ expected: green
+
+- name: 2d.text.draw.kern.consistent
+ desc: Stroked and filled text should have exactly the same kerning so it overlaps
+ manual:
+ testing:
+ - 2d.text.draw
+ code: |
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#f00';
+ ctx.strokeStyle = '#0f0';
+ ctx.lineWidth = 3;
+ ctx.font = '20px Arial, sans-serif';
+ ctx.fillText('VAVAVAVAVAVAVA', -50, 25);
+ ctx.fillText('ToToToToToToTo', -50, 45);
+ ctx.strokeText('VAVAVAVAVAVAVA', -50, 25);
+ ctx.strokeText('ToToToToToToTo', -50, 45);
+ expected: green
+
+# CanvasTest is:
+# A = (0, 0) to (1em, 0.75em) (above baseline)
+# B = (0, 0) to (1em, -0.25em) (below baseline)
+# C = (0, -0.25em) to (1em, 0.75em) (the em square) plus some Xs above and below
+# D = (0, -0.25em) to (1em, 0.75em) (the em square) plus some Xs left and right
+# E = (0, -0.25em) to (1em, 0.75em) (the em square)
+# space = empty, 1em wide
+#
+# At 50px, "E" will fill the canvas vertically
+# At 67px, "A" will fill the canvas vertically
+#
+# Ideographic baseline is 0.125em above alphabetic
+# Mathematical baseline is 0.375em above alphabetic
+# Hanging baseline is 0.500em above alphabetic
+
+# WebKit doesn't block onload on font loads, so we try to make it a bit more reliable
+# by waiting with setTimeout after load before drawing
+
+- name: 2d.text.draw.fill.maxWidth.fontface
+ desc: fillText works on @font-face fonts
+ testing:
+ - 2d.text.draw.maxwidth
+ fonts:
+ - CanvasTest
+ code: |
+ ctx.font = '50px CanvasTest';
+ deferTest();
+ setTimeout(t.step_func_done(function () {
+ ctx.fillStyle = '#0f0';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#f00';
+ ctx.fillText('EEEE', -50, 37.5, 40);
+ @assert pixel 5,5 ==~ 0,255,0,255;
+ @assert pixel 95,5 ==~ 0,255,0,255;
+ @assert pixel 25,25 ==~ 0,255,0,255;
+ @assert pixel 75,25 ==~ 0,255,0,255;
+ }), 500);
+ expected: green
+
+- name: 2d.text.draw.fill.maxWidth.bound
+ desc: fillText handles maxWidth based on line size, not bounding box size
+ testing:
+ - 2d.text.draw.maxwidth
+ fonts:
+ - CanvasTest
+ code: |
+ ctx.font = '50px CanvasTest';
+ deferTest();
+ setTimeout(t.step_func_done(function () {
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.fillText('DD', 0, 37.5, 100);
+ @assert pixel 5,5 ==~ 0,255,0,255;
+ @assert pixel 95,5 ==~ 0,255,0,255;
+ @assert pixel 25,25 ==~ 0,255,0,255;
+ @assert pixel 75,25 ==~ 0,255,0,255;
+ }), 500);
+ expected: green
+
+- name: 2d.text.draw.fontface
+ testing:
+ - 2d.text.font.fontface
+ fonts:
+ - CanvasTest
+ code: |
+ ctx.font = '67px CanvasTest';
+ deferTest();
+ setTimeout(t.step_func_done(function () {
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.fillText('AA', 0, 50);
+ @assert pixel 5,5 ==~ 0,255,0,255;
+ @assert pixel 95,5 ==~ 0,255,0,255;
+ @assert pixel 25,25 ==~ 0,255,0,255;
+ @assert pixel 75,25 ==~ 0,255,0,255;
+ }), 500);
+ expected: green
+
+- name: 2d.text.draw.fontface.repeat
+ desc: Draw with the font immediately, then wait a bit until and draw again. (This crashes some version of WebKit.)
+ testing:
+ - 2d.text.font.fontface
+ fonts:
+ - CanvasTest
+ fonthack: 0
+ code: |
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.font = '67px CanvasTest';
+ ctx.fillStyle = '#0f0';
+ ctx.fillText('AA', 0, 50);
+ deferTest();
+ setTimeout(t.step_func_done(function () {
+ ctx.fillText('AA', 0, 50);
+ @assert pixel 5,5 ==~ 0,255,0,255;
+ @assert pixel 95,5 ==~ 0,255,0,255;
+ @assert pixel 25,25 ==~ 0,255,0,255;
+ @assert pixel 75,25 ==~ 0,255,0,255;
+ }), 500);
+ expected: green
+
+- name: 2d.text.draw.fontface.notinpage
+ desc: "@font-face fonts should work even if they are not used in the page"
+ testing:
+ - 2d.text.font.fontface
+ fonts:
+ - CanvasTest
+ fonthack: 0
+ code: |
+ ctx.font = '67px CanvasTest';
+ deferTest();
+ setTimeout(t.step_func_done(function () {
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.fillText('AA', 0, 50);
+ @assert pixel 5,5 ==~ 0,255,0,255; @moz-todo
+ @assert pixel 95,5 ==~ 0,255,0,255; @moz-todo
+ @assert pixel 25,25 ==~ 0,255,0,255; @moz-todo
+ @assert pixel 75,25 ==~ 0,255,0,255; @moz-todo
+ }), 500);
+ expected: green
+
+- name: 2d.text.draw.baseline.top
+ desc: textBaseline top is the top of the em square (not the bounding box)
+ testing:
+ - 2d.text.baseline.top
+ fonts:
+ - CanvasTest
+ code: |
+ ctx.font = '50px CanvasTest';
+ deferTest();
+ setTimeout(t.step_func_done(function () {
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.textBaseline = 'top';
+ ctx.fillText('CC', 0, 0);
+ @assert pixel 5,5 ==~ 0,255,0,255;
+ @assert pixel 95,5 ==~ 0,255,0,255;
+ @assert pixel 25,25 ==~ 0,255,0,255;
+ @assert pixel 75,25 ==~ 0,255,0,255;
+ @assert pixel 5,45 ==~ 0,255,0,255;
+ @assert pixel 95,45 ==~ 0,255,0,255;
+ }), 500);
+ expected: green
+
+- name: 2d.text.draw.baseline.bottom
+ desc: textBaseline bottom is the bottom of the em square (not the bounding box)
+ testing:
+ - 2d.text.baseline.bottom
+ fonts:
+ - CanvasTest
+ code: |
+ ctx.font = '50px CanvasTest';
+ deferTest();
+ setTimeout(t.step_func_done(function () {
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.textBaseline = 'bottom';
+ ctx.fillText('CC', 0, 50);
+ @assert pixel 5,5 ==~ 0,255,0,255;
+ @assert pixel 95,5 ==~ 0,255,0,255;
+ @assert pixel 25,25 ==~ 0,255,0,255;
+ @assert pixel 75,25 ==~ 0,255,0,255;
+ @assert pixel 5,45 ==~ 0,255,0,255;
+ @assert pixel 95,45 ==~ 0,255,0,255;
+ }), 500);
+ expected: green
+
+- name: 2d.text.draw.baseline.middle
+ desc: textBaseline middle is the middle of the em square (not the bounding box)
+ testing:
+ - 2d.text.baseline.middle
+ fonts:
+ - CanvasTest
+ code: |
+ ctx.font = '50px CanvasTest';
+ deferTest();
+ setTimeout(t.step_func_done(function () {
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.textBaseline = 'middle';
+ ctx.fillText('CC', 0, 25);
+ @assert pixel 5,5 ==~ 0,255,0,255;
+ @assert pixel 95,5 ==~ 0,255,0,255;
+ @assert pixel 25,25 ==~ 0,255,0,255;
+ @assert pixel 75,25 ==~ 0,255,0,255;
+ @assert pixel 5,45 ==~ 0,255,0,255;
+ @assert pixel 95,45 ==~ 0,255,0,255;
+ }), 500);
+ expected: green
+
+- name: 2d.text.draw.baseline.alphabetic
+ testing:
+ - 2d.text.baseline.alphabetic
+ fonts:
+ - CanvasTest
+ code: |
+ ctx.font = '50px CanvasTest';
+ deferTest();
+ setTimeout(t.step_func_done(function () {
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.textBaseline = 'alphabetic';
+ ctx.fillText('CC', 0, 37.5);
+ @assert pixel 5,5 ==~ 0,255,0,255;
+ @assert pixel 95,5 ==~ 0,255,0,255;
+ @assert pixel 25,25 ==~ 0,255,0,255;
+ @assert pixel 75,25 ==~ 0,255,0,255;
+ @assert pixel 5,45 ==~ 0,255,0,255;
+ @assert pixel 95,45 ==~ 0,255,0,255;
+ }), 500);
+ expected: green
+
+- name: 2d.text.draw.baseline.ideographic
+ testing:
+ - 2d.text.baseline.ideographic
+ fonts:
+ - CanvasTest
+ code: |
+ ctx.font = '50px CanvasTest';
+ deferTest();
+ setTimeout(t.step_func_done(function () {
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.textBaseline = 'ideographic';
+ ctx.fillText('CC', 0, 31.25);
+ @assert pixel 5,5 ==~ 0,255,0,255;
+ @assert pixel 95,5 ==~ 0,255,0,255;
+ @assert pixel 25,25 ==~ 0,255,0,255;
+ @assert pixel 75,25 ==~ 0,255,0,255;
+ @assert pixel 5,45 ==~ 0,255,0,255; @moz-todo
+ @assert pixel 95,45 ==~ 0,255,0,255; @moz-todo
+ }), 500);
+ expected: green
+
+- name: 2d.text.draw.baseline.hanging
+ testing:
+ - 2d.text.baseline.hanging
+ fonts:
+ - CanvasTest
+ code: |
+ ctx.font = '50px CanvasTest';
+ deferTest();
+ setTimeout(t.step_func_done(function () {
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.textBaseline = 'hanging';
+ ctx.fillText('CC', 0, 12.5);
+ @assert pixel 5,5 ==~ 0,255,0,255; @moz-todo
+ @assert pixel 95,5 ==~ 0,255,0,255; @moz-todo
+ @assert pixel 25,25 ==~ 0,255,0,255;
+ @assert pixel 75,25 ==~ 0,255,0,255;
+ @assert pixel 5,45 ==~ 0,255,0,255;
+ @assert pixel 95,45 ==~ 0,255,0,255;
+ }), 500);
+ expected: green
+
+- name: 2d.text.draw.align.left
+ desc: textAlign left is the left of the first em square (not the bounding box)
+ testing:
+ - 2d.text.align.left
+ fonts:
+ - CanvasTest
+ code: |
+ ctx.font = '50px CanvasTest';
+ deferTest();
+ setTimeout(t.step_func_done(function () {
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.textAlign = 'left';
+ ctx.fillText('DD', 0, 37.5);
+ @assert pixel 5,5 ==~ 0,255,0,255;
+ @assert pixel 95,5 ==~ 0,255,0,255;
+ @assert pixel 25,25 ==~ 0,255,0,255;
+ @assert pixel 75,25 ==~ 0,255,0,255;
+ @assert pixel 5,45 ==~ 0,255,0,255;
+ @assert pixel 95,45 ==~ 0,255,0,255;
+ }), 500);
+ expected: green
+
+- name: 2d.text.draw.align.right
+ desc: textAlign right is the right of the last em square (not the bounding box)
+ testing:
+ - 2d.text.align.right
+ fonts:
+ - CanvasTest
+ code: |
+ ctx.font = '50px CanvasTest';
+ deferTest();
+ setTimeout(t.step_func_done(function () {
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.textAlign = 'right';
+ ctx.fillText('DD', 100, 37.5);
+ @assert pixel 5,5 ==~ 0,255,0,255;
+ @assert pixel 95,5 ==~ 0,255,0,255;
+ @assert pixel 25,25 ==~ 0,255,0,255;
+ @assert pixel 75,25 ==~ 0,255,0,255;
+ @assert pixel 5,45 ==~ 0,255,0,255;
+ @assert pixel 95,45 ==~ 0,255,0,255;
+ }), 500);
+ expected: green
+
+- name: 2d.text.draw.align.start.ltr
+ desc: textAlign start with ltr is the left edge
+ testing:
+ - 2d.text.align.left
+ fonts:
+ - CanvasTest
+ canvas: width="100" height="50" dir="ltr"
+ code: |
+ ctx.font = '50px CanvasTest';
+ deferTest();
+ setTimeout(t.step_func_done(function () {
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.textAlign = 'start';
+ ctx.fillText('DD', 0, 37.5);
+ @assert pixel 5,5 ==~ 0,255,0,255;
+ @assert pixel 95,5 ==~ 0,255,0,255;
+ @assert pixel 25,25 ==~ 0,255,0,255;
+ @assert pixel 75,25 ==~ 0,255,0,255;
+ @assert pixel 5,45 ==~ 0,255,0,255;
+ @assert pixel 95,45 ==~ 0,255,0,255;
+ }), 500);
+ expected: green
+
+- name: 2d.text.draw.align.start.rtl
+ desc: textAlign start with rtl is the right edge
+ testing:
+ - 2d.text.align.right
+ - 2d.text.draw.direction
+ fonts:
+ - CanvasTest
+ canvas: width="100" height="50" dir="rtl"
+ code: |
+ ctx.font = '50px CanvasTest';
+ deferTest();
+ setTimeout(t.step_func_done(function () {
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.textAlign = 'start';
+ ctx.fillText('DD', 100, 37.5);
+ @assert pixel 5,5 ==~ 0,255,0,255;
+ @assert pixel 95,5 ==~ 0,255,0,255;
+ @assert pixel 25,25 ==~ 0,255,0,255;
+ @assert pixel 75,25 ==~ 0,255,0,255;
+ @assert pixel 5,45 ==~ 0,255,0,255;
+ @assert pixel 95,45 ==~ 0,255,0,255;
+ }), 500);
+ expected: green
+
+- name: 2d.text.draw.align.end.ltr
+ desc: textAlign end with ltr is the right edge
+ testing:
+ - 2d.text.align.right
+ fonts:
+ - CanvasTest
+ canvas: width="100" height="50" dir="ltr"
+ code: |
+ ctx.font = '50px CanvasTest';
+ deferTest();
+ setTimeout(t.step_func_done(function () {
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.textAlign = 'end';
+ ctx.fillText('DD', 100, 37.5);
+ @assert pixel 5,5 ==~ 0,255,0,255;
+ @assert pixel 95,5 ==~ 0,255,0,255;
+ @assert pixel 25,25 ==~ 0,255,0,255;
+ @assert pixel 75,25 ==~ 0,255,0,255;
+ @assert pixel 5,45 ==~ 0,255,0,255;
+ @assert pixel 95,45 ==~ 0,255,0,255;
+ }), 500);
+ expected: green
+
+- name: 2d.text.draw.align.end.rtl
+ desc: textAlign end with rtl is the left edge
+ testing:
+ - 2d.text.align.left
+ - 2d.text.draw.direction
+ fonts:
+ - CanvasTest
+ canvas: width="100" height="50" dir="rtl"
+ code: |
+ ctx.font = '50px CanvasTest';
+ deferTest();
+ setTimeout(t.step_func_done(function () {
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.textAlign = 'end';
+ ctx.fillText('DD', 0, 37.5);
+ @assert pixel 5,5 ==~ 0,255,0,255;
+ @assert pixel 95,5 ==~ 0,255,0,255;
+ @assert pixel 25,25 ==~ 0,255,0,255;
+ @assert pixel 75,25 ==~ 0,255,0,255;
+ @assert pixel 5,45 ==~ 0,255,0,255;
+ @assert pixel 95,45 ==~ 0,255,0,255;
+ }), 500);
+ expected: green
+
+- name: 2d.text.draw.align.center
+ desc: textAlign center is the center of the em squares (not the bounding box)
+ testing:
+ - 2d.text.align.center
+ fonts:
+ - CanvasTest
+ code: |
+ ctx.font = '50px CanvasTest';
+ deferTest();
+ setTimeout(t.step_func_done(function () {
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.textAlign = 'center';
+ ctx.fillText('DD', 50, 37.5);
+ @assert pixel 5,5 ==~ 0,255,0,255;
+ @assert pixel 95,5 ==~ 0,255,0,255;
+ @assert pixel 25,25 ==~ 0,255,0,255;
+ @assert pixel 75,25 ==~ 0,255,0,255;
+ @assert pixel 5,45 ==~ 0,255,0,255;
+ @assert pixel 95,45 ==~ 0,255,0,255;
+ }), 500);
+ expected: green
+
+
+- name: 2d.text.draw.space.basic
+ desc: U+0020 is rendered the correct size (1em wide)
+ testing:
+ - 2d.text.draw.spaces
+ fonts:
+ - CanvasTest
+ code: |
+ ctx.font = '50px CanvasTest';
+ deferTest();
+ setTimeout(t.step_func_done(function () {
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.fillText('E EE', -100, 37.5);
+ @assert pixel 25,25 ==~ 0,255,0,255;
+ @assert pixel 75,25 ==~ 0,255,0,255;
+ }), 500);
+ expected: green
+
+- name: 2d.text.draw.space.collapse.space
+ desc: Space characters are converted to U+0020, and collapsed (per CSS)
+ testing:
+ - 2d.text.draw.spaces
+ fonts:
+ - CanvasTest
+ code: |
+ ctx.font = '50px CanvasTest';
+ deferTest();
+ setTimeout(t.step_func_done(function () {
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.fillText('E EE', -100, 37.5);
+ @assert pixel 25,25 ==~ 0,255,0,255; @moz-todo
+ @assert pixel 75,25 ==~ 0,255,0,255;
+ }), 500);
+ expected: green
+
+- name: 2d.text.draw.space.collapse.other
+ desc: Space characters are converted to U+0020, and collapsed (per CSS)
+ testing:
+ - 2d.text.draw.spaces
+ fonts:
+ - CanvasTest
+ code: |
+ ctx.font = '50px CanvasTest';
+ deferTest();
+ setTimeout(t.step_func_done(function () {
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.fillText('E \x09\x0a\x0c\x0d \x09\x0a\x0c\x0dEE', -100, 37.5);
+ @assert pixel 25,25 ==~ 0,255,0,255; @moz-todo
+ @assert pixel 75,25 ==~ 0,255,0,255; @moz-todo
+ }), 500);
+ expected: green
+
+- name: 2d.text.draw.space.collapse.nonspace
+ desc: Non-space characters are not converted to U+0020 and collapsed
+ testing:
+ - 2d.text.draw.spaces
+ fonts:
+ - CanvasTest
+ code: |
+ ctx.font = '50px CanvasTest';
+ deferTest();
+ setTimeout(t.step_func_done(function () {
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.fillText('E\x0b EE', -150, 37.5);
+ @assert pixel 25,25 ==~ 0,255,0,255;
+ @assert pixel 75,25 ==~ 0,255,0,255;
+ }), 500);
+ expected: green
+
+- name: 2d.text.draw.space.collapse.start
+ desc: Space characters at the start of a line are collapsed (per CSS)
+ testing:
+ - 2d.text.draw.spaces
+ fonts:
+ - CanvasTest
+ code: |
+ ctx.font = '50px CanvasTest';
+ deferTest();
+ setTimeout(t.step_func_done(function () {
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.fillText(' EE', 0, 37.5);
+ @assert pixel 25,25 ==~ 0,255,0,255; @moz-todo
+ @assert pixel 75,25 ==~ 0,255,0,255;
+ }), 500);
+ expected: green
+
+- name: 2d.text.draw.space.collapse.end
+ desc: Space characters at the end of a line are collapsed (per CSS)
+ testing:
+ - 2d.text.draw.spaces
+ fonts:
+ - CanvasTest
+ code: |
+ ctx.font = '50px CanvasTest';
+ deferTest();
+ setTimeout(t.step_func_done(function () {
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ ctx.fillStyle = '#0f0';
+ ctx.textAlign = 'right';
+ ctx.fillText('EE ', 100, 37.5);
+ @assert pixel 25,25 ==~ 0,255,0,255;
+ @assert pixel 75,25 ==~ 0,255,0,255; @moz-todo
+ }), 500);
+ expected: green
+
+
+
+
+- name: 2d.text.measure.width.basic
+ testing:
+ - 2d.text.measure
+ fonts:
+ - CanvasTest
+ code: |
+ deferTest();
+ setTimeout(t.step_func_done(function () {
+ ctx.font = '50px CanvasTest';
+ @assert ctx.measureText('A').width === 50;
+ @assert ctx.measureText('AA').width === 100;
+ @assert ctx.measureText('ABCD').width === 200;
+
+ ctx.font = '100px CanvasTest';
+ @assert ctx.measureText('A').width === 100;
+ }), 500);
+
+- name: 2d.text.measure.width.empty
+ desc: The empty string has zero width
+ testing:
+ - 2d.text.measure
+ fonts:
+ - CanvasTest
+ code: |
+ deferTest();
+ setTimeout(t.step_func_done(function () {
+ ctx.font = '50px CanvasTest';
+ @assert ctx.measureText("").width === 0;
+ }), 500);
+
+- name: 2d.text.measure.width.space
+ desc: Space characters are converted to U+0020 and collapsed (per CSS)
+ testing:
+ - 2d.text.measure.spaces
+ fonts:
+ - CanvasTest
+ code: |
+ deferTest();
+ setTimeout(t.step_func_done(function () {
+ ctx.font = '50px CanvasTest';
+ @assert ctx.measureText('A B').width === 150;
+ @assert ctx.measureText('A B').width === 150; @moz-todo
+ @assert ctx.measureText('A \x09\x0a\x0c\x0d \x09\x0a\x0c\x0dB').width === 150; @moz-todo
+ @assert ctx.measureText('A \x0b B').width >= 200;
+
+ @assert ctx.measureText(' AB').width === 100; @moz-todo
+ @assert ctx.measureText('AB ').width === 100; @moz-todo
+ }), 500);
+
+# TODO: shadows, alpha, composite, clip
diff --git a/tests/wpt/web-platform-tests/2dcontext/transformations/.gitkeep b/tests/wpt/web-platform-tests/2dcontext/transformations/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/transformations/.gitkeep
diff --git a/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.order.html b/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.order.html
new file mode 100644
index 00000000000..8209ad66d42
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.order.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.transformation.order</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.transformation.order</h1>
+<p class="desc">Transformations are applied in the right order</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Transformations are applied in the right order");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.scale(2, 1);
+ctx.rotate(Math.PI / 2);
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, -50, 50, 50);
+_assertPixel(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.rotate.direction.html b/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.rotate.direction.html
new file mode 100644
index 00000000000..5113fa23827
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.rotate.direction.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.transformation.rotate.direction</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.transformation.rotate.direction</h1>
+<p class="desc">rotate() is clockwise</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("rotate() is clockwise");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.rotate(Math.PI / 2);
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, -100, 50, 100);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.rotate.nonfinite.html b/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.rotate.nonfinite.html
new file mode 100644
index 00000000000..1726dcf5b1b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.rotate.nonfinite.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.transformation.rotate.nonfinite</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.transformation.rotate.nonfinite</h1>
+<p class="desc">rotate() with Infinity/NaN is ignored</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("rotate() with Infinity/NaN is ignored");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.translate(100, 10);
+ctx.rotate(Infinity);
+ctx.rotate(-Infinity);
+ctx.rotate(NaN);
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(-100, -10, 100, 50);
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.rotate.radians.html b/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.rotate.radians.html
new file mode 100644
index 00000000000..8cfeb6fd170
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.rotate.radians.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.transformation.rotate.radians</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.transformation.rotate.radians</h1>
+<p class="desc">rotate() uses radians</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("rotate() uses radians");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.rotate(Math.PI); // should fail obviously if this is 3.1 degrees
+ctx.fillStyle = '#0f0';
+ctx.fillRect(-100, -50, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.rotate.wrap.html b/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.rotate.wrap.html
new file mode 100644
index 00000000000..fbfba2a291f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.rotate.wrap.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.transformation.rotate.wrap</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.transformation.rotate.wrap</h1>
+<p class="desc">rotate() wraps large positive values correctly</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("rotate() wraps large positive values correctly");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.rotate(Math.PI * (1 + 4096)); // == pi (mod 2*pi)
+// We need about pi +/- 0.001 in order to get correct-looking results
+// 32-bit floats can store pi*4097 with precision 2^-10, so that should
+// be safe enough on reasonable implementations
+ctx.fillStyle = '#0f0';
+ctx.fillRect(-100, -50, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 98,2, 0,255,0,255, "98,2", "0,255,0,255");
+_assertPixel(canvas, 98,47, 0,255,0,255, "98,47", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.rotate.wrapnegative.html b/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.rotate.wrapnegative.html
new file mode 100644
index 00000000000..a695e7b397b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.rotate.wrapnegative.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.transformation.rotate.wrapnegative</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.transformation.rotate.wrapnegative</h1>
+<p class="desc">rotate() wraps large negative values correctly</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("rotate() wraps large negative values correctly");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.rotate(-Math.PI * (1 + 4096));
+ctx.fillStyle = '#0f0';
+ctx.fillRect(-100, -50, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+_assertPixel(canvas, 98,2, 0,255,0,255, "98,2", "0,255,0,255");
+_assertPixel(canvas, 98,47, 0,255,0,255, "98,47", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.rotate.zero.html b/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.rotate.zero.html
new file mode 100644
index 00000000000..cd74260e756
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.rotate.zero.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.transformation.rotate.zero</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.transformation.rotate.zero</h1>
+<p class="desc">rotate() by 0 does nothing</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("rotate() by 0 does nothing");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.rotate(0);
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.scale.basic.html b/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.scale.basic.html
new file mode 100644
index 00000000000..a083a6514ae
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.scale.basic.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.transformation.scale.basic</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.transformation.scale.basic</h1>
+<p class="desc">scale() works</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("scale() works");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.scale(2, 4);
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 50, 12.5);
+_assertPixel(canvas, 90,40, 0,255,0,255, "90,40", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.scale.large.html b/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.scale.large.html
new file mode 100644
index 00000000000..926530d1f7e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.scale.large.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.transformation.scale.large</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.transformation.scale.large</h1>
+<p class="desc">scale() with large scale factors works</p>
+
+<p class="notes">Not really that large at all, but it hits the limits in Firefox.
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("scale() with large scale factors works");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.scale(1e5, 1e5);
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 1, 1);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.scale.multiple.html b/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.scale.multiple.html
new file mode 100644
index 00000000000..9856798be91
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.scale.multiple.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.transformation.scale.multiple</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.transformation.scale.multiple</h1>
+<p class="desc">Multiple scale()s combine</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Multiple scale()s combine");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.scale(Math.sqrt(2), Math.sqrt(2));
+ctx.scale(Math.sqrt(2), Math.sqrt(2));
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 50, 25);
+_assertPixel(canvas, 90,40, 0,255,0,255, "90,40", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.scale.negative.html b/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.scale.negative.html
new file mode 100644
index 00000000000..af32851651d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.scale.negative.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.transformation.scale.negative</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.transformation.scale.negative</h1>
+<p class="desc">scale() with negative scale factors works</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("scale() with negative scale factors works");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.save();
+ctx.scale(-1, 1);
+ctx.fillStyle = '#0f0';
+ctx.fillRect(-50, 0, 50, 50);
+ctx.restore();
+
+ctx.save();
+ctx.scale(1, -1);
+ctx.fillStyle = '#0f0';
+ctx.fillRect(50, -50, 50, 50);
+ctx.restore();
+_assertPixel(canvas, 25,25, 0,255,0,255, "25,25", "0,255,0,255");
+_assertPixel(canvas, 75,25, 0,255,0,255, "75,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.scale.nonfinite.html b/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.scale.nonfinite.html
new file mode 100644
index 00000000000..b9788885f0d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.scale.nonfinite.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.transformation.scale.nonfinite</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.transformation.scale.nonfinite</h1>
+<p class="desc">scale() with Infinity/NaN is ignored</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("scale() with Infinity/NaN is ignored");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.translate(100, 10);
+ctx.scale(Infinity, 0.1);
+ctx.scale(-Infinity, 0.1);
+ctx.scale(NaN, 0.1);
+ctx.scale(0.1, Infinity);
+ctx.scale(0.1, -Infinity);
+ctx.scale(0.1, NaN);
+ctx.scale(Infinity, Infinity);
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(-100, -10, 100, 50);
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.scale.zero.html b/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.scale.zero.html
new file mode 100644
index 00000000000..80e79a98825
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.scale.zero.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.transformation.scale.zero</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.transformation.scale.zero</h1>
+<p class="desc">scale() with a scale factor of zero works</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("scale() with a scale factor of zero works");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.save();
+ctx.translate(50, 0);
+ctx.scale(0, 1);
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.restore();
+
+ctx.save();
+ctx.translate(0, 25);
+ctx.scale(1, 0);
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.restore();
+
+canvas.toDataURL();
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.setTransform.multiple.html b/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.setTransform.multiple.html
new file mode 100644
index 00000000000..79caa63080e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.setTransform.multiple.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.transformation.setTransform.multiple</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.transformation.setTransform.multiple</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.setTransform(1/2,0, 0,1/2, 0,0);
+ctx.setTransform(2,0, 0,2, 0,0);
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 50, 25);
+_assertPixel(canvas, 75,35, 0,255,0,255, "75,35", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.setTransform.nonfinite.html b/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.setTransform.nonfinite.html
new file mode 100644
index 00000000000..4b5ebd6c737
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.setTransform.nonfinite.html
@@ -0,0 +1,110 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.transformation.setTransform.nonfinite</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.transformation.setTransform.nonfinite</h1>
+<p class="desc">setTransform() with Infinity/NaN is ignored</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("setTransform() with Infinity/NaN is ignored");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.translate(100, 10);
+ctx.setTransform(Infinity, 0, 0, 0, 0, 0);
+ctx.setTransform(-Infinity, 0, 0, 0, 0, 0);
+ctx.setTransform(NaN, 0, 0, 0, 0, 0);
+ctx.setTransform(0, Infinity, 0, 0, 0, 0);
+ctx.setTransform(0, -Infinity, 0, 0, 0, 0);
+ctx.setTransform(0, NaN, 0, 0, 0, 0);
+ctx.setTransform(0, 0, Infinity, 0, 0, 0);
+ctx.setTransform(0, 0, -Infinity, 0, 0, 0);
+ctx.setTransform(0, 0, NaN, 0, 0, 0);
+ctx.setTransform(0, 0, 0, Infinity, 0, 0);
+ctx.setTransform(0, 0, 0, -Infinity, 0, 0);
+ctx.setTransform(0, 0, 0, NaN, 0, 0);
+ctx.setTransform(0, 0, 0, 0, Infinity, 0);
+ctx.setTransform(0, 0, 0, 0, -Infinity, 0);
+ctx.setTransform(0, 0, 0, 0, NaN, 0);
+ctx.setTransform(0, 0, 0, 0, 0, Infinity);
+ctx.setTransform(0, 0, 0, 0, 0, -Infinity);
+ctx.setTransform(0, 0, 0, 0, 0, NaN);
+ctx.setTransform(Infinity, Infinity, 0, 0, 0, 0);
+ctx.setTransform(Infinity, Infinity, Infinity, 0, 0, 0);
+ctx.setTransform(Infinity, Infinity, Infinity, Infinity, 0, 0);
+ctx.setTransform(Infinity, Infinity, Infinity, Infinity, Infinity, 0);
+ctx.setTransform(Infinity, Infinity, Infinity, Infinity, Infinity, Infinity);
+ctx.setTransform(Infinity, Infinity, Infinity, Infinity, 0, Infinity);
+ctx.setTransform(Infinity, Infinity, Infinity, 0, Infinity, 0);
+ctx.setTransform(Infinity, Infinity, Infinity, 0, Infinity, Infinity);
+ctx.setTransform(Infinity, Infinity, Infinity, 0, 0, Infinity);
+ctx.setTransform(Infinity, Infinity, 0, Infinity, 0, 0);
+ctx.setTransform(Infinity, Infinity, 0, Infinity, Infinity, 0);
+ctx.setTransform(Infinity, Infinity, 0, Infinity, Infinity, Infinity);
+ctx.setTransform(Infinity, Infinity, 0, Infinity, 0, Infinity);
+ctx.setTransform(Infinity, Infinity, 0, 0, Infinity, 0);
+ctx.setTransform(Infinity, Infinity, 0, 0, Infinity, Infinity);
+ctx.setTransform(Infinity, Infinity, 0, 0, 0, Infinity);
+ctx.setTransform(Infinity, 0, Infinity, 0, 0, 0);
+ctx.setTransform(Infinity, 0, Infinity, Infinity, 0, 0);
+ctx.setTransform(Infinity, 0, Infinity, Infinity, Infinity, 0);
+ctx.setTransform(Infinity, 0, Infinity, Infinity, Infinity, Infinity);
+ctx.setTransform(Infinity, 0, Infinity, Infinity, 0, Infinity);
+ctx.setTransform(Infinity, 0, Infinity, 0, Infinity, 0);
+ctx.setTransform(Infinity, 0, Infinity, 0, Infinity, Infinity);
+ctx.setTransform(Infinity, 0, Infinity, 0, 0, Infinity);
+ctx.setTransform(Infinity, 0, 0, Infinity, 0, 0);
+ctx.setTransform(Infinity, 0, 0, Infinity, Infinity, 0);
+ctx.setTransform(Infinity, 0, 0, Infinity, Infinity, Infinity);
+ctx.setTransform(Infinity, 0, 0, Infinity, 0, Infinity);
+ctx.setTransform(Infinity, 0, 0, 0, Infinity, 0);
+ctx.setTransform(Infinity, 0, 0, 0, Infinity, Infinity);
+ctx.setTransform(Infinity, 0, 0, 0, 0, Infinity);
+ctx.setTransform(0, Infinity, Infinity, 0, 0, 0);
+ctx.setTransform(0, Infinity, Infinity, Infinity, 0, 0);
+ctx.setTransform(0, Infinity, Infinity, Infinity, Infinity, 0);
+ctx.setTransform(0, Infinity, Infinity, Infinity, Infinity, Infinity);
+ctx.setTransform(0, Infinity, Infinity, Infinity, 0, Infinity);
+ctx.setTransform(0, Infinity, Infinity, 0, Infinity, 0);
+ctx.setTransform(0, Infinity, Infinity, 0, Infinity, Infinity);
+ctx.setTransform(0, Infinity, Infinity, 0, 0, Infinity);
+ctx.setTransform(0, Infinity, 0, Infinity, 0, 0);
+ctx.setTransform(0, Infinity, 0, Infinity, Infinity, 0);
+ctx.setTransform(0, Infinity, 0, Infinity, Infinity, Infinity);
+ctx.setTransform(0, Infinity, 0, Infinity, 0, Infinity);
+ctx.setTransform(0, Infinity, 0, 0, Infinity, 0);
+ctx.setTransform(0, Infinity, 0, 0, Infinity, Infinity);
+ctx.setTransform(0, Infinity, 0, 0, 0, Infinity);
+ctx.setTransform(0, 0, Infinity, Infinity, 0, 0);
+ctx.setTransform(0, 0, Infinity, Infinity, Infinity, 0);
+ctx.setTransform(0, 0, Infinity, Infinity, Infinity, Infinity);
+ctx.setTransform(0, 0, Infinity, Infinity, 0, Infinity);
+ctx.setTransform(0, 0, Infinity, 0, Infinity, 0);
+ctx.setTransform(0, 0, Infinity, 0, Infinity, Infinity);
+ctx.setTransform(0, 0, Infinity, 0, 0, Infinity);
+ctx.setTransform(0, 0, 0, Infinity, Infinity, 0);
+ctx.setTransform(0, 0, 0, Infinity, Infinity, Infinity);
+ctx.setTransform(0, 0, 0, Infinity, 0, Infinity);
+ctx.setTransform(0, 0, 0, 0, Infinity, Infinity);
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(-100, -10, 100, 50);
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.setTransform.skewed.html b/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.setTransform.skewed.html
new file mode 100644
index 00000000000..d411e544bbd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.setTransform.skewed.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.transformation.setTransform.skewed</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.transformation.setTransform.skewed</h1>
+<p class="desc"></p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+// Create green with a red square ring inside it
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.fillStyle = '#f00';
+ctx.fillRect(20, 10, 60, 30);
+ctx.fillStyle = '#0f0';
+ctx.fillRect(40, 20, 20, 10);
+
+// Draw a skewed shape to fill that gap, to make sure it is aligned correctly
+ctx.setTransform(1,4, 2,3, 5,6);
+// Post-transform coordinates:
+// [[20,10],[80,10],[80,40],[20,40],[20,10],[40,20],[40,30],[60,30],[60,20],[40,20],[20,10]];
+// Hence pre-transform coordinates:
+var pts=[[-7.4,11.2],[-43.4,59.2],[-31.4,53.2],[4.6,5.2],[-7.4,11.2],
+ [-15.4,25.2],[-11.4,23.2],[-23.4,39.2],[-27.4,41.2],[-15.4,25.2],
+ [-7.4,11.2]];
+ctx.beginPath();
+ctx.moveTo(pts[0][0], pts[0][1]);
+for (var i = 0; i < pts.length; ++i)
+ ctx.lineTo(pts[i][0], pts[i][1]);
+ctx.fill();
+_assertPixel(canvas, 21,11, 0,255,0,255, "21,11", "0,255,0,255");
+_assertPixel(canvas, 79,11, 0,255,0,255, "79,11", "0,255,0,255");
+_assertPixel(canvas, 21,39, 0,255,0,255, "21,39", "0,255,0,255");
+_assertPixel(canvas, 79,39, 0,255,0,255, "79,39", "0,255,0,255");
+_assertPixel(canvas, 39,19, 0,255,0,255, "39,19", "0,255,0,255");
+_assertPixel(canvas, 61,19, 0,255,0,255, "61,19", "0,255,0,255");
+_assertPixel(canvas, 39,31, 0,255,0,255, "39,31", "0,255,0,255");
+_assertPixel(canvas, 61,31, 0,255,0,255, "61,31", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.transform.identity.html b/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.transform.identity.html
new file mode 100644
index 00000000000..bf88557b93e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.transform.identity.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.transformation.transform.identity</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.transformation.transform.identity</h1>
+<p class="desc">transform() with the identity matrix does nothing</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("transform() with the identity matrix does nothing");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.transform(1,0, 0,1, 0,0);
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.transform.multiply.html b/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.transform.multiply.html
new file mode 100644
index 00000000000..0313602abd8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.transform.multiply.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.transformation.transform.multiply</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.transformation.transform.multiply</h1>
+<p class="desc">transform() multiplies the CTM</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("transform() multiplies the CTM");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.transform(1,2, 3,4, 5,6);
+ctx.transform(-2,1, 3/2,-1/2, 1,-2);
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.transform.nonfinite.html b/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.transform.nonfinite.html
new file mode 100644
index 00000000000..1b12766cd74
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.transform.nonfinite.html
@@ -0,0 +1,110 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.transformation.transform.nonfinite</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.transformation.transform.nonfinite</h1>
+<p class="desc">transform() with Infinity/NaN is ignored</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("transform() with Infinity/NaN is ignored");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.translate(100, 10);
+ctx.transform(Infinity, 0, 0, 0, 0, 0);
+ctx.transform(-Infinity, 0, 0, 0, 0, 0);
+ctx.transform(NaN, 0, 0, 0, 0, 0);
+ctx.transform(0, Infinity, 0, 0, 0, 0);
+ctx.transform(0, -Infinity, 0, 0, 0, 0);
+ctx.transform(0, NaN, 0, 0, 0, 0);
+ctx.transform(0, 0, Infinity, 0, 0, 0);
+ctx.transform(0, 0, -Infinity, 0, 0, 0);
+ctx.transform(0, 0, NaN, 0, 0, 0);
+ctx.transform(0, 0, 0, Infinity, 0, 0);
+ctx.transform(0, 0, 0, -Infinity, 0, 0);
+ctx.transform(0, 0, 0, NaN, 0, 0);
+ctx.transform(0, 0, 0, 0, Infinity, 0);
+ctx.transform(0, 0, 0, 0, -Infinity, 0);
+ctx.transform(0, 0, 0, 0, NaN, 0);
+ctx.transform(0, 0, 0, 0, 0, Infinity);
+ctx.transform(0, 0, 0, 0, 0, -Infinity);
+ctx.transform(0, 0, 0, 0, 0, NaN);
+ctx.transform(Infinity, Infinity, 0, 0, 0, 0);
+ctx.transform(Infinity, Infinity, Infinity, 0, 0, 0);
+ctx.transform(Infinity, Infinity, Infinity, Infinity, 0, 0);
+ctx.transform(Infinity, Infinity, Infinity, Infinity, Infinity, 0);
+ctx.transform(Infinity, Infinity, Infinity, Infinity, Infinity, Infinity);
+ctx.transform(Infinity, Infinity, Infinity, Infinity, 0, Infinity);
+ctx.transform(Infinity, Infinity, Infinity, 0, Infinity, 0);
+ctx.transform(Infinity, Infinity, Infinity, 0, Infinity, Infinity);
+ctx.transform(Infinity, Infinity, Infinity, 0, 0, Infinity);
+ctx.transform(Infinity, Infinity, 0, Infinity, 0, 0);
+ctx.transform(Infinity, Infinity, 0, Infinity, Infinity, 0);
+ctx.transform(Infinity, Infinity, 0, Infinity, Infinity, Infinity);
+ctx.transform(Infinity, Infinity, 0, Infinity, 0, Infinity);
+ctx.transform(Infinity, Infinity, 0, 0, Infinity, 0);
+ctx.transform(Infinity, Infinity, 0, 0, Infinity, Infinity);
+ctx.transform(Infinity, Infinity, 0, 0, 0, Infinity);
+ctx.transform(Infinity, 0, Infinity, 0, 0, 0);
+ctx.transform(Infinity, 0, Infinity, Infinity, 0, 0);
+ctx.transform(Infinity, 0, Infinity, Infinity, Infinity, 0);
+ctx.transform(Infinity, 0, Infinity, Infinity, Infinity, Infinity);
+ctx.transform(Infinity, 0, Infinity, Infinity, 0, Infinity);
+ctx.transform(Infinity, 0, Infinity, 0, Infinity, 0);
+ctx.transform(Infinity, 0, Infinity, 0, Infinity, Infinity);
+ctx.transform(Infinity, 0, Infinity, 0, 0, Infinity);
+ctx.transform(Infinity, 0, 0, Infinity, 0, 0);
+ctx.transform(Infinity, 0, 0, Infinity, Infinity, 0);
+ctx.transform(Infinity, 0, 0, Infinity, Infinity, Infinity);
+ctx.transform(Infinity, 0, 0, Infinity, 0, Infinity);
+ctx.transform(Infinity, 0, 0, 0, Infinity, 0);
+ctx.transform(Infinity, 0, 0, 0, Infinity, Infinity);
+ctx.transform(Infinity, 0, 0, 0, 0, Infinity);
+ctx.transform(0, Infinity, Infinity, 0, 0, 0);
+ctx.transform(0, Infinity, Infinity, Infinity, 0, 0);
+ctx.transform(0, Infinity, Infinity, Infinity, Infinity, 0);
+ctx.transform(0, Infinity, Infinity, Infinity, Infinity, Infinity);
+ctx.transform(0, Infinity, Infinity, Infinity, 0, Infinity);
+ctx.transform(0, Infinity, Infinity, 0, Infinity, 0);
+ctx.transform(0, Infinity, Infinity, 0, Infinity, Infinity);
+ctx.transform(0, Infinity, Infinity, 0, 0, Infinity);
+ctx.transform(0, Infinity, 0, Infinity, 0, 0);
+ctx.transform(0, Infinity, 0, Infinity, Infinity, 0);
+ctx.transform(0, Infinity, 0, Infinity, Infinity, Infinity);
+ctx.transform(0, Infinity, 0, Infinity, 0, Infinity);
+ctx.transform(0, Infinity, 0, 0, Infinity, 0);
+ctx.transform(0, Infinity, 0, 0, Infinity, Infinity);
+ctx.transform(0, Infinity, 0, 0, 0, Infinity);
+ctx.transform(0, 0, Infinity, Infinity, 0, 0);
+ctx.transform(0, 0, Infinity, Infinity, Infinity, 0);
+ctx.transform(0, 0, Infinity, Infinity, Infinity, Infinity);
+ctx.transform(0, 0, Infinity, Infinity, 0, Infinity);
+ctx.transform(0, 0, Infinity, 0, Infinity, 0);
+ctx.transform(0, 0, Infinity, 0, Infinity, Infinity);
+ctx.transform(0, 0, Infinity, 0, 0, Infinity);
+ctx.transform(0, 0, 0, Infinity, Infinity, 0);
+ctx.transform(0, 0, 0, Infinity, Infinity, Infinity);
+ctx.transform(0, 0, 0, Infinity, 0, Infinity);
+ctx.transform(0, 0, 0, 0, Infinity, Infinity);
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(-100, -10, 100, 50);
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.transform.skewed.html b/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.transform.skewed.html
new file mode 100644
index 00000000000..cf723c7c202
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.transform.skewed.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.transformation.transform.skewed</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.transformation.transform.skewed</h1>
+<p class="desc">transform() with skewy matrix transforms correctly</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("transform() with skewy matrix transforms correctly");
+_addTest(function(canvas, ctx) {
+
+// Create green with a red square ring inside it
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+ctx.fillStyle = '#f00';
+ctx.fillRect(20, 10, 60, 30);
+ctx.fillStyle = '#0f0';
+ctx.fillRect(40, 20, 20, 10);
+
+// Draw a skewed shape to fill that gap, to make sure it is aligned correctly
+ctx.transform(1,4, 2,3, 5,6);
+// Post-transform coordinates:
+// [[20,10],[80,10],[80,40],[20,40],[20,10],[40,20],[40,30],[60,30],[60,20],[40,20],[20,10]];
+// Hence pre-transform coordinates:
+var pts=[[-7.4,11.2],[-43.4,59.2],[-31.4,53.2],[4.6,5.2],[-7.4,11.2],
+ [-15.4,25.2],[-11.4,23.2],[-23.4,39.2],[-27.4,41.2],[-15.4,25.2],
+ [-7.4,11.2]];
+ctx.beginPath();
+ctx.moveTo(pts[0][0], pts[0][1]);
+for (var i = 0; i < pts.length; ++i)
+ ctx.lineTo(pts[i][0], pts[i][1]);
+ctx.fill();
+_assertPixel(canvas, 21,11, 0,255,0,255, "21,11", "0,255,0,255");
+_assertPixel(canvas, 79,11, 0,255,0,255, "79,11", "0,255,0,255");
+_assertPixel(canvas, 21,39, 0,255,0,255, "21,39", "0,255,0,255");
+_assertPixel(canvas, 79,39, 0,255,0,255, "79,39", "0,255,0,255");
+_assertPixel(canvas, 39,19, 0,255,0,255, "39,19", "0,255,0,255");
+_assertPixel(canvas, 61,19, 0,255,0,255, "61,19", "0,255,0,255");
+_assertPixel(canvas, 39,31, 0,255,0,255, "39,31", "0,255,0,255");
+_assertPixel(canvas, 61,31, 0,255,0,255, "61,31", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.translate.basic.html b/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.translate.basic.html
new file mode 100644
index 00000000000..0238f8d0b00
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.translate.basic.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.transformation.translate.basic</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.transformation.translate.basic</h1>
+<p class="desc">translate() works</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("translate() works");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.translate(100, 50);
+ctx.fillStyle = '#0f0';
+ctx.fillRect(-100, -50, 100, 50);
+_assertPixel(canvas, 90,40, 0,255,0,255, "90,40", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.translate.nonfinite.html b/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.translate.nonfinite.html
new file mode 100644
index 00000000000..d0ff4d7487c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/transformations/2d.transformation.translate.nonfinite.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.transformation.translate.nonfinite</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.transformation.translate.nonfinite</h1>
+<p class="desc">translate() with Infinity/NaN is ignored</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("translate() with Infinity/NaN is ignored");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+
+ctx.translate(100, 10);
+ctx.translate(Infinity, 0.1);
+ctx.translate(-Infinity, 0.1);
+ctx.translate(NaN, 0.1);
+ctx.translate(0.1, Infinity);
+ctx.translate(0.1, -Infinity);
+ctx.translate(0.1, NaN);
+ctx.translate(Infinity, Infinity);
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(-100, -10, 100, 50);
+
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/2dcontext/transformations/canvas_transformations_scale_001-ref.htm b/tests/wpt/web-platform-tests/2dcontext/transformations/canvas_transformations_scale_001-ref.htm
new file mode 100644
index 00000000000..1201bcca9f8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/transformations/canvas_transformations_scale_001-ref.htm
@@ -0,0 +1,11 @@
+<!doctype HTML>
+<html>
+ <head>
+ <title>HTML5 Canvas Test: scale() transformation</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com" />
+ </head>
+ <body>
+ <p>Description: The scale(x, y) method must add the scaling transformation described by the arguments to the transformation matrix.</p>
+ <div><img alt='black rectangle' src="/images/black-rectangle.png"></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/2dcontext/transformations/canvas_transformations_scale_001.htm b/tests/wpt/web-platform-tests/2dcontext/transformations/canvas_transformations_scale_001.htm
new file mode 100644
index 00000000000..4c027202e7f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/2dcontext/transformations/canvas_transformations_scale_001.htm
@@ -0,0 +1,30 @@
+<!doctype HTML>
+<html>
+ <head>
+ <title>HTML5 Canvas Test: scale() transformation</title>
+ <link rel="match" href="canvas_transformations_scale_001-ref.htm">
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com" />
+ <link rel="help" href="http://www.w3.org/TR/2dcontext/#dom-context-2d-scale" />
+ <meta name="assert" content="The scale(x, y) method must add the scaling transformation described by the arguments to the transformation matrix." />
+ <script type="text/javascript">
+ function runTest()
+ {
+ var canvas = document.getElementById("canvas1");
+ var ctx = canvas.getContext("2d");
+
+ // Draw a red rectangle.
+ ctx.fillStyle = "rgba(255, 0, 0, 1.0)";
+ ctx.fillRect(0, 0, 100, 50);
+
+ // Draw a black rectangle with scaling.
+ ctx.fillStyle = "rgba(0, 0, 0, 1.0)";
+ ctx.scale(2, 2);
+ ctx.fillRect(0, 0, 50, 25);
+ }
+ </script>
+ </head>
+ <body onload="runTest()">
+ <p>Description: The scale(x, y) method must add the scaling transformation described by the arguments to the transformation matrix.</p>
+ <canvas id="canvas1" width="300" height="150">Browser does not support HTML5 Canvas.</canvas>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/CONTRIBUTING.md b/tests/wpt/web-platform-tests/CONTRIBUTING.md
new file mode 100644
index 00000000000..0e7968ab6bc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/CONTRIBUTING.md
@@ -0,0 +1,29 @@
+Grant of License
+----------------
+
+By contributing to this repository, you and the company you represent, if the
+company holds any copyrights in the contribution, grant to the W3C a perpetual,
+non-exclusive, royalty-free, world-wide right and license under all of your
+copyrights in this contribution to copy, publish, use, and modify the
+contribution and to distribute the contribution under a BSD License or one with
+more restrictive terms, as well as a right and license of the same scope to any
+derivative works prepared by the W3C and based on or incorporating all or part
+of the contribution. You further agree that any derivative works of this
+contribution prepared by the W3C shall be solely owned by the W3C.
+
+You state, to the best of your knowledge, that you, or the company you
+represent, have all rights necessary to contribute the materials.
+
+W3C will retain attribution of initial authorship to you. The W3C makes no
+a-priori commitment to support or distribute contributions.
+
+Disclaimer
+----------
+
+All content from this repository is provided as is, and W3C makes no
+representations or warranties, express or implied, including, but not limited
+to, warranties of merchantability, fitness for a particular purpose,
+non-infringement, or title; nor that the contents of this repository are
+suitable for any purpose. We make no representations, express or implied, that
+the content of this repository or the use thereof indicates conformance to a
+specification. All content is provided as-is to help reach interoperability.
diff --git a/tests/wpt/web-platform-tests/DOMEvents/ClickFakeEvent.nondocument.html b/tests/wpt/web-platform-tests/DOMEvents/ClickFakeEvent.nondocument.html
new file mode 100644
index 00000000000..30e15b8e44a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/ClickFakeEvent.nondocument.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<title>Click event on an element not in the document</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+test(function() {
+ var EVENT = "click";
+ var TARGET = document.createElement("somerandomelement");
+ var t = async_test("Click event can be dispatched to an element that is not in the document.")
+ TARGET.addEventListener(EVENT, t.step_func(function(evt) {
+ assert_equals(evt.target, TARGET);
+ t.done();
+ }), true);
+ var e = document.createEvent("Event");
+ e.initEvent(EVENT, true, true);
+ TARGET.dispatchEvent(e);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/DOMEvents/constructors.html b/tests/wpt/web-platform-tests/DOMEvents/constructors.html
new file mode 100644
index 00000000000..b41d1d7bd0c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/constructors.html
@@ -0,0 +1,147 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Event constructors</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+function assert_props(iface, event, defaults) {
+ assert_true(event instanceof self[iface]);
+ expected[iface].properties.forEach(function(p) {
+ var property = p[0], value = p[defaults ? 1 : 2];
+ assert_true(property in event,
+ "Event " + format_value(event) + " should have a " +
+ property + " property");
+ assert_equals(event[property], value,
+ "The value of the " + property + " property should be " +
+ format_value(value));
+ });
+ if ("parent" in expected[iface]) {
+ assert_props(expected[iface].parent, event, defaults);
+ }
+}
+
+var EventModifierInit = [
+ ["ctrlKey", false, true],
+ ["shiftKey", false, true],
+ ["altKey", false, true],
+ ["metaKey", false, true],
+];
+var expected = {
+ "Event": {
+ "properties": [
+ ["bubbles", false, true],
+ ["cancelable", false, true],
+ ],
+ },
+
+ "UIEvent": {
+ "parent": "Event",
+ "properties": [
+ ["view", null, window],
+ ["detail", 0, 7],
+ ],
+ },
+
+ "FocusEvent": {
+ "parent": "UIEvent",
+ "properties": [
+ ["relatedTarget", null, document],
+ ],
+ },
+
+ "MouseEvent": {
+ "parent": "UIEvent",
+ "properties": EventModifierInit.concat([
+ ["screenX", 0, 40],
+ ["screenY", 0, 40],
+ ["clientX", 0, 40],
+ ["clientY", 0, 40],
+ ["button", 0, 40],
+ ["buttons", 0, 40],
+ ["relatedTarget", null, document],
+ ]),
+ },
+
+ "WheelEvent": {
+ "parent": "MouseEvent",
+ "properties": [
+ ["deltaX", 0.0, 3.1],
+ ["deltaY", 0.0, 3.1],
+ ["deltaZ", 0.0, 3.1],
+ ["deltaMode", 0, 40],
+ ],
+ },
+
+ "KeyboardEvent": {
+ "parent": "UIEvent",
+ "properties": EventModifierInit.concat([
+ ["key", "", "string"],
+ ["code", "", "string"],
+ ["location", 0, 7],
+ ["repeat", false, true],
+ ["isComposing", false, true],
+ ["charCode", 0, 7],
+ ["keyCode", 0, 7],
+ ["which", 0, 7],
+ ]),
+ },
+
+ "CompositionEvent": {
+ "parent": "UIEvent",
+ "properties": [
+ ["data", "", "string"],
+ ],
+ },
+};
+
+Object.keys(expected).forEach(function(iface) {
+ test(function() {
+ var event = new self[iface]("type");
+ assert_props(iface, event, true);
+ }, iface + " constructor (no argument)");
+
+ test(function() {
+ var event = new self[iface]("type", undefined);
+ assert_props(iface, event, true);
+ }, iface + " constructor (undefined argument)");
+
+ test(function() {
+ var event = new self[iface]("type", null);
+ assert_props(iface, event, true);
+ }, iface + " constructor (null argument)");
+
+ test(function() {
+ var event = new self[iface]("type", {});
+ assert_props(iface, event, true);
+ }, iface + " constructor (empty argument)");
+
+ test(function() {
+ var dictionary = {};
+ expected[iface].properties.forEach(function(p) {
+ var property = p[0], value = p[1];
+ dictionary[property] = value;
+ });
+ var event = new self[iface]("type", dictionary);
+ assert_props(iface, event, true);
+ }, iface + " constructor (argument with default values)");
+
+ test(function() {
+ function fill_in(iface, dictionary) {
+ if ("parent" in expected[iface]) {
+ fill_in(expected[iface].parent, dictionary)
+ }
+ expected[iface].properties.forEach(function(p) {
+ var property = p[0], value = p[2];
+ dictionary[property] = value;
+ });
+ }
+
+ var dictionary = {};
+ fill_in(iface, dictionary);
+
+ var event = new self[iface]("type", dictionary);
+ assert_props(iface, event, false);
+ }, iface + " constructor (argument with non-default values)");
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/DOMEvents/event-phases-order.html b/tests/wpt/web-platform-tests/DOMEvents/event-phases-order.html
new file mode 100644
index 00000000000..d2dc4048787
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/event-phases-order.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<!-- Submitted from TestTWF Paris -->
+<title>Event phases order</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+ document.addEventListener('DOMContentLoaded', this.step_func_done(function() {
+ var parent = document.getElementById('parent');
+ var child = document.getElementById('child');
+
+ var order = [];
+
+ parent.addEventListener('click', this.step_func(function(){ order.push(1) }), true);
+ child.addEventListener('click', this.step_func(function(){ order.push(2) }), false);
+ parent.addEventListener('click', this.step_func(function(){ order.push(3) }), false);
+
+ child.click();
+
+ assert_array_equals(order, [1, 2, 3]);
+ }));
+}, "Event phases order");
+</script>
+
+ <div id="parent">
+ <div id="child"></div>
+ </div>
diff --git a/tests/wpt/web-platform-tests/DOMEvents/init-event-while-dispatching.html b/tests/wpt/web-platform-tests/DOMEvents/init-event-while-dispatching.html
new file mode 100644
index 00000000000..2aa1f6701c4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/init-event-while-dispatching.html
@@ -0,0 +1,83 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Re-initializing events while dispatching them</title>
+<link rel="author" title="Josh Matthews" href="mailto:josh@joshmatthews.net">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var events = {
+ 'KeyboardEvent': {
+ 'constructor': function() { return new KeyboardEvent("type", {key: "A"}); },
+ 'init': function(ev) { ev.initKeyboardEvent("type2", true, true, null, "a", 1, "", true, "") },
+ 'check': function(ev) {
+ assert_equals(ev.key, "A", "initKeyboardEvent key setter should short-circuit");
+ assert_false(ev.repeat, "initKeyboardEvent repeat setter should short-circuit");
+ assert_equals(ev.location, 0, "initKeyboardEvent location setter should short-circuit");
+ }
+ },
+ 'MouseEvent': {
+ 'constructor': function() { return new MouseEvent("type"); },
+ 'init': function(ev) { ev.initMouseEvent("type2", true, true, null, 0, 1, 1, 1, 1, true, true, true, true, 1, null) },
+ 'check': function(ev) {
+ assert_equals(ev.screenX, 0, "initMouseEvent screenX setter should short-circuit");
+ assert_equals(ev.screenY, 0, "initMouseEvent screenY setter should short-circuit");
+ assert_equals(ev.clientX, 0, "initMouseEvent clientX setter should short-circuit");
+ assert_equals(ev.clientY, 0, "initMouseEvent clientY setter should short-circuit");
+ assert_false(ev.ctrlKey, "initMouseEvent ctrlKey setter should short-circuit");
+ assert_false(ev.altKey, "initMouseEvent altKey setter should short-circuit");
+ assert_false(ev.shiftKey, "initMouseEvent shiftKey setter should short-circuit");
+ assert_false(ev.metaKey, "initMouseEvent metaKey setter should short-circuit");
+ assert_equals(ev.button, 0, "initMouseEvent button setter should short-circuit");
+ }
+ },
+ 'CustomEvent': {
+ 'constructor': function() { return new CustomEvent("type") },
+ 'init': function(ev) { ev.initCustomEvent("type2", true, true, 1) },
+ 'check': function(ev) {
+ assert_equals(ev.detail, null, "initCustomEvent detail setter should short-circuit");
+ }
+ },
+ 'UIEvent': {
+ 'constructor': function() { return new UIEvent("type") },
+ 'init': function(ev) { ev.initUIEvent("type2", true, true, window, 1) },
+ 'check': function(ev) {
+ assert_equals(ev.view, null, "initUIEvent view setter should short-circuit");
+ assert_equals(ev.detail, 0, "initUIEvent detail setter should short-circuit");
+ }
+ },
+ 'Event': {
+ 'constructor': function() { return new Event("type") },
+ 'init': function(ev) { ev.initEvent("type2", true, true) },
+ 'check': function(ev) {
+ assert_equals(ev.bubbles, false, "initEvent bubbles setter should short-circuit");
+ assert_equals(ev.cancelable, false, "initEvent cancelable setter should short-circuit");
+ assert_equals(ev.type, "type", "initEvent type setter should short-circuit");
+ }
+ }
+};
+
+var names = Object.keys(events);
+for (var i = 0; i < names.length; i++) {
+ var t = async_test("Calling init" + names[i] + " while dispatching.");
+ t.step(function() {
+ var e = events[names[i]].constructor();
+
+ var target = document.createElement("div")
+ target.addEventListener("type", t.step_func(function() {
+ events[names[i]].init(e);
+
+ var o = e;
+ while ((o = Object.getPrototypeOf(o))) {
+ if (!(o.constructor.name in events)) {
+ break;
+ }
+ events[o.constructor.name].check(e);
+ }
+ }), false);
+
+ assert_equals(target.dispatchEvent(e), true, "dispatchEvent must return true")
+ });
+ t.done();
+}
+</script>
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/Status.html b/tests/wpt/web-platform-tests/DOMEvents/tests/Status.html
new file mode 100644
index 00000000000..5599395549b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/Status.html
@@ -0,0 +1,26 @@
+<!doctype html>
+<html>
+<head>
+ <title>DOM Level 3 Events Test Status</title>
+</head>
+<body>
+
+<h2>DOM Level 3 Events Test Suite Status</h2>
+
+<p>This test suite is part of the
+<a href="http://www.w3.org/2008/webapps/wiki/">Web Application WG's</a>
+Test Repository as described in WebApps'
+<a href="http://www.w3.org/2008/webapps/wiki/Testing">Testing Wiki</a>.
+</p>
+
+<p>The test suite is for the
+<a href="http://dev.w3.org/2006/webapi/DOM-Level-3-Events/html/DOM3-Events.html">DOM Level 3 Events</a> specification.
+</p>
+
+<ul>
+ <li>Test suite status: all of the tests in the <code>approved</code> directory are Approved by WebApps' testing group</li>
+ <li>Test Facilitator: Alex Kuang</li>
+</ul>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/approved/DOM.event.flow.html b/tests/wpt/web-platform-tests/DOMEvents/tests/approved/DOM.event.flow.html
new file mode 100644
index 00000000000..c4d1fcfc021
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/approved/DOM.event.flow.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title> Event dispatch and DOM event flow </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id=log></div>
+
+<table id="table" border="1" style="display: none">
+ <tbody id="table-body">
+ <tr id="table-row">
+ <td id="table-cell">Shady Grove</td>
+ <td>Aeolian</td>
+ </tr>
+ <tr id="parent">
+ <td id="target">Over the river, Charlie</td>
+ <td>Dorian</td>
+ </tr>
+ </tbody>
+</table>
+
+<script>
+ var EVENT = "foo";
+ var TARGET = document.getElementById("target");
+ var PARENT = document.getElementById("parent");
+ var TBODY = document.getElementById("table-body");
+ var TABLE = document.getElementById("table");
+ var BODY = document.body;
+ var HTML = document.documentElement;
+ var CurrentTargets = [window, document, HTML, BODY, TABLE, TBODY, PARENT, TARGET];
+ var ExpectResult = CurrentTargets.concat([TARGET, PARENT, TBODY, TABLE, BODY, HTML, document, window]);
+ var ActualResult = [];
+ var ExpectPhases = [1,1,1,1,1,1,1,2,2,3,3,3,3,3,3,3,];
+ var ActualPhases = [];
+
+ var description = "Test Description: Dispatch an event in a DOM tree using the DOM event flow.";
+
+ test(function()
+ {
+ for (var i=0; i < CurrentTargets.length; i++)
+ {
+ CurrentTargets[i].addEventListener(EVENT, TestEvent, true);
+ CurrentTargets[i].addEventListener(EVENT, TestEvent, false);
+ }
+
+ var evt = document.createEvent("Event");
+ evt.initEvent(EVENT, true, true);
+ TARGET.dispatchEvent(evt);
+
+ assert_array_equals(ActualResult, ExpectResult, "ActualResult");
+ assert_array_equals(ActualPhases, ExpectPhases, "ActualPhases");
+
+ }, description);
+
+ function TestEvent(evt)
+ {
+ ActualResult.push(evt.currentTarget);
+ ActualPhases.push(evt.eventPhase);
+ }
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/approved/EventListener.eventHandler.html b/tests/wpt/web-platform-tests/DOMEvents/tests/approved/EventListener.eventHandler.html
new file mode 100644
index 00000000000..992ff1cc973
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/approved/EventListener.eventHandler.html
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title> EventLister member: handleEvent() </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id=log></div>
+
+<table id="table" border="1" style="display: none">
+ <tbody id="table-body">
+ <tr id="table-row">
+ <td id="table-cell">Shady Grove</td>
+ <td>Aeolian</td>
+ </tr>
+ <tr id="parent">
+ <td id="target">Over the river, Charlie</td>
+ <td>Dorian</td>
+ </tr>
+ </tbody>
+</table>
+
+<script>
+ var EVENT = "foo";
+ var TARGET = document.getElementById("target");
+ var TestResult = false;
+
+ var description = "Test Description: " +
+ "handleEvent - This method shall be called whenever an event occurs of the event type for " +
+ "which the EventListener interface was registered.";
+
+ var EventListener = {};
+ EventListener.handleEvent = function(evt)
+ {
+ if ((EVENT == evt.type) && (TARGET == evt.target) && (this === EventListener))
+ {
+ TestResult = true;
+ }
+ else
+ {
+ TestResult = false;
+ }
+ }
+
+ test(function()
+ {
+ var evt = document.createEvent("Event");
+ evt.initEvent(EVENT, true, true);
+
+ TARGET.addEventListener(EVENT, EventListener, true);
+ TARGET.dispatchEvent(evt);
+ TARGET.removeEventListener(EVENT, EventListener, true);
+
+ assert_true(TestResult);
+
+ }, description);
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/approved/EventObject.after.dispatchEvent.html b/tests/wpt/web-platform-tests/DOMEvents/tests/approved/EventObject.after.dispatchEvent.html
new file mode 100644
index 00000000000..d8ab8d4f26a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/approved/EventObject.after.dispatchEvent.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title> Event.defaultPrevented is reset after dipatchEvent() </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id=log></div>
+
+<input id="target" type="hidden" value=""/>
+
+<script>
+ var EVENT = "foo";
+ var TARGET = document.getElementById("target");
+ var PreState;
+ var PosState;
+
+ var description = "Test Description: " +
+ "As the final step of the event dispatch, the implementation must reset the event " +
+ "object's default-action-prevention state. ";
+
+ test(function()
+ {
+ var evt = document.createEvent("Event");
+ evt.initEvent(EVENT, true, true);
+
+ TARGET.addEventListener(EVENT, TestEvent, true);
+ TARGET.dispatchEvent(evt);
+
+ PosState = evt.defaultPrevented;
+
+ assert_array_equals([evt.target, PreState, PosState], [TARGET, true, false]);
+
+ }, description);
+
+ function TestEvent(evt)
+ {
+ evt.preventDefault();
+ PreState = evt.defaultPrevented;
+ }
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/approved/EventObject.multiple.dispatchEvent.html b/tests/wpt/web-platform-tests/DOMEvents/tests/approved/EventObject.multiple.dispatchEvent.html
new file mode 100644
index 00000000000..e8555bd78b9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/approved/EventObject.multiple.dispatchEvent.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title> Multiple dispatchEvent() and stopPropagation() </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id=log></div>
+
+<div id="parent" style="display: none">
+ <input id="target" type="hidden" value=""/>
+</div>
+
+<script>
+ var EVENT = "foo";
+ var TARGET = document.getElementById("target");
+ var PARENT = document.getElementById("parent");
+ var ExpectResult = [TARGET, PARENT, PARENT, document, window];
+ var ActualResult = [];
+
+ var description = "Test Description: " +
+ "An event object may be properly dispatched multiple times while also allowing to prevent the event objects " +
+ "propagation prior to the event dispatch.";
+
+ test(function()
+ {
+ var evt = document.createEvent("Event");
+ evt.initEvent(EVENT, true, true);
+
+ TARGET.addEventListener(EVENT, TestEvent, false);
+ PARENT.addEventListener(EVENT, TestEvent, false);
+ document.addEventListener(EVENT, TestEvent, false);
+ window.addEventListener(EVENT, TestEvent, false);
+
+ TARGET.dispatchEvent(evt);
+ PARENT.dispatchEvent(evt);
+ document.dispatchEvent(evt);
+
+ assert_array_equals(ActualResult, ExpectResult);
+
+ }, description);
+
+ function TestEvent(evt)
+ {
+ ActualResult.push(evt.currentTarget);
+
+ if (PARENT == evt.currentTarget)
+ {
+ evt.stopPropagation();
+ }
+ }
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/approved/ProcessingInstruction.DOMCharacterDataModified.html b/tests/wpt/web-platform-tests/DOMEvents/tests/approved/ProcessingInstruction.DOMCharacterDataModified.html
new file mode 100644
index 00000000000..329bc04c871
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/approved/ProcessingInstruction.DOMCharacterDataModified.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title> ProcessingInstruction.data and DOMCharacterDataModified event </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id=log></div>
+
+<iframe id="helper" style="display: none"></iframe>
+
+<script>
+ var description = "Test Description: " +
+ "DOMCharacterDataModified event fires after ProcessingInstruction.data have been modified, " +
+ "but the node itself has not been inserted or deleted. The proximal event target of this " +
+ "event shall be the ProcessingInstruction node.";
+
+ var t = async_test(description);
+
+ var HELPER = document.getElementById("helper");
+
+ HELPER.onload = t.step_func(function()
+ {
+ assert_true(HELPER.contentWindow.TestResult);
+ t.done();
+ });
+
+ HELPER.src = "./support/ProcessingInstruction.DOMCharacterDataModified.xml";
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/approved/dispatchEvent.click.checkbox.html b/tests/wpt/web-platform-tests/DOMEvents/tests/approved/dispatchEvent.click.checkbox.html
new file mode 100644
index 00000000000..4a2af9d1929
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/approved/dispatchEvent.click.checkbox.html
@@ -0,0 +1,80 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title> MouseEvent: Default action and synthetic click event </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id=log></div>
+
+<div style="display: none">
+ <input type="checkbox" id="target">
+ <button id="button"> Click Here </button>
+</div>
+
+<script>
+ setup({explicit_done:true});
+ var EVENT = "click";
+ var TARGET = document.getElementById("target");
+ var BUTTON = document.getElementById("button");
+ var state;
+
+ var description = "Test Description: " +
+ "MouseEvent: Default action is performed when a synthetic click event is dispatched on a checkbox element";
+
+ BUTTON.addEventListener(EVENT, TestEvent, true);
+ TARGET.addEventListener(EVENT, TestEvent, true);
+
+ window.onload = function()
+ {
+ state = TARGET.checked;
+ BUTTON.click();
+ }
+
+ function TestEvent(evt)
+ {
+ if (BUTTON == evt.target)
+ {
+ var e;
+ test(function()
+ {
+ BUTTON.removeEventListener(EVENT, TestEvent, true);
+
+ e = document.createEvent("MouseEvent");
+ e.initMouseEvent(EVENT, /* type */
+ false, /* bubbles */
+ true, /* cancelable */
+ window, /* view */
+ 1, /* detail */
+ 0, /* screenX */
+ 0, /* screenY */
+ 0, /* clientX */
+ 0, /* clientY */
+ false, /* ctrlKey */
+ false, /* altKey */
+ false, /* shiftKey */
+ false, /* metaKey */
+ 0, /* button */
+ null /* relatedTarget */);
+
+ assert_array_equals([TARGET.checked, e.type, e.bubbles], [state, EVENT, false]);
+
+ }, "Checkbox state is unchanged before the synthetic click event is dispatched");
+
+ TARGET.dispatchEvent(e);
+ }
+ else if (TARGET == evt.target)
+ {
+ test(function()
+ {
+ assert_array_equals([TARGET.checked, evt.type, evt.bubbles], [!state, EVENT, false]);
+
+ }, description);
+
+ done();
+ }
+ }
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/approved/domnodeinserted.html b/tests/wpt/web-platform-tests/DOMEvents/tests/approved/domnodeinserted.html
new file mode 100644
index 00000000000..934a7eaaf7c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/approved/domnodeinserted.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>MutationEvent: DOMNodeInserted Event Type</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+
+<div id="target" style="display: none"></div>
+
+<script>
+var EVENT = "DOMNodeInserted";
+var TARGET;
+var NODE;
+
+var t = async_test("Test Description: DOMNodeInserted event fires when a node has been added as a child of another node.");
+
+TARGET = document.getElementById("target");
+
+TARGET.addEventListener(EVENT, t.step_func(function(evt)
+{
+ assert_equals(evt.type, EVENT);
+ t.done();
+}), true);
+
+NODE = document.createElement("INPUT");
+TARGET.appendChild(NODE);
+</script>
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/approved/stopImmediatePropagation.effect.html b/tests/wpt/web-platform-tests/DOMEvents/tests/approved/stopImmediatePropagation.effect.html
new file mode 100644
index 00000000000..99facb969d4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/approved/stopImmediatePropagation.effect.html
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title> Event.stopImmediatePropagation() immediate effect </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id=log></div>
+
+<table id="table" border="1" style="display: none">
+ <tbody id="table-body">
+ <tr id="table-row">
+ <td id="table-cell">Shady Grove</td>
+ <td>Aeolian</td>
+ </tr>
+ <tr id="parent">
+ <td id="target">Over the river, Charlie</td>
+ <td>Dorian</td>
+ </tr>
+ </tbody>
+</table>
+
+<script>
+ var EVENT = "foo";
+ var TARGET = document.getElementById("target");
+ var PARENT = document.getElementById("parent");
+ var TBODY = document.getElementById("table-body");
+ var TABLE = document.getElementById("table");
+ var BODY = document.body;
+ var HTML = document.documentElement;
+ var CurrentTargets = [window, document, HTML, BODY, TABLE, TBODY, PARENT, TARGET];
+ var ExpectResult = [window, window, document, document, HTML, HTML, BODY, BODY, TABLE];
+ var ActualResult = [];
+ var ExpectListeners = [0,1,0,1,0,1,0,1,0];
+ var ActualListeners = [];
+
+ var description = "Test Description: " +
+ "stopImmediatePropagation() prevents other event listeners from being triggered and, unlike " +
+ "Event.stopPropagation(), its effect must be immediate. Once it has been called, further calls " +
+ "to this method have no additional effect.";
+
+ test(function()
+ {
+ for (var i=0; i < CurrentTargets.length; i++)
+ {
+ CurrentTargets[i].addEventListener(EVENT, function(e){TestEvent(e, 0)}, true);
+ CurrentTargets[i].addEventListener(EVENT, function(e){TestEvent(e, 1)}, true);
+ }
+
+ var evt = document.createEvent("Event");
+ evt.initEvent(EVENT, true, true);
+ TARGET.dispatchEvent(evt);
+
+ assert_array_equals(ActualResult, ExpectResult, "ActualResult");
+ assert_array_equals(ActualListeners, ExpectListeners, "ActualListeners");
+
+ }, description);
+
+ function TestEvent(evt, i)
+ {
+ ActualResult.push(evt.currentTarget);
+ ActualListeners.push(i);
+ if ((1 == evt.eventPhase) && (TABLE == evt.currentTarget) && (0 == i))
+ {
+ evt.stopImmediatePropagation();
+ }
+ }
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/approved/stopPropagation.deferred.effect.html b/tests/wpt/web-platform-tests/DOMEvents/tests/approved/stopPropagation.deferred.effect.html
new file mode 100644
index 00000000000..65872200648
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/approved/stopPropagation.deferred.effect.html
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title> Event.stopPropagation() deferred effect </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id=log></div>
+
+<table id="table" border="1" style="display: none">
+ <tbody id="table-body">
+ <tr id="table-row">
+ <td id="table-cell">Shady Grove</td>
+ <td>Aeolian</td>
+ </tr>
+ <tr id="parent">
+ <td id="target">Over the river, Charlie</td>
+ <td>Dorian</td>
+ </tr>
+ </tbody>
+</table>
+
+<script>
+ var EVENT = "foo";
+ var TARGET = document.getElementById("target");
+ var PARENT = document.getElementById("parent");
+ var TBODY = document.getElementById("table-body");
+ var TABLE = document.getElementById("table");
+ var BODY = document.body;
+ var HTML = document.documentElement;
+ var CurrentTargets = [window, document, HTML, BODY, TABLE, TBODY, PARENT, TARGET];
+ var ExpectResult = [window, window, document, document, HTML, HTML, BODY, BODY, TABLE, TABLE];
+ var ActualResult = [];
+ var ExpectListeners = [0,1,0,1,0,1,0,1,0,1];
+ var ActualListeners = [];
+
+ var description = "Test Description: " +
+ "stopPropagation() prevents other event listeners from being triggered but its effect must be " +
+ "deferred until all event listeners attached on the Event.currentTarget have been triggered.";
+
+ test(function()
+ {
+ for (var i=0; i < CurrentTargets.length; i++)
+ {
+ CurrentTargets[i].addEventListener(EVENT, function(e){TestEvent(e, 0)}, true);
+ CurrentTargets[i].addEventListener(EVENT, function(e){TestEvent(e, 1)}, true);
+ }
+
+ var evt = document.createEvent("Event");
+ evt.initEvent(EVENT, true, true);
+ TARGET.dispatchEvent(evt);
+
+ assert_array_equals(ActualResult, ExpectResult, "ActualResult");
+ assert_array_equals(ActualListeners, ExpectListeners, "ActualListeners");
+
+ }, description);
+
+ function TestEvent(evt, i)
+ {
+ ActualResult.push(evt.currentTarget);
+ ActualListeners.push(i);
+ if ((1 == evt.eventPhase) && (TABLE == evt.currentTarget) && (0 == i))
+ {
+ evt.stopPropagation();
+ }
+ }
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/approved/stopPropagation.dispatchEvent.html b/tests/wpt/web-platform-tests/DOMEvents/tests/approved/stopPropagation.dispatchEvent.html
new file mode 100644
index 00000000000..5c31a1d1330
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/approved/stopPropagation.dispatchEvent.html
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title> Calling stopPropagation() prior to dispatchEvent() </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id=log></div>
+
+<table id="table" border="1" style="display: none">
+ <tbody id="table-body">
+ <tr id="table-row">
+ <td id="table-cell">Shady Grove</td>
+ <td>Aeolian</td>
+ </tr>
+ <tr id="parent">
+ <td id="target">Over the river, Charlie</td>
+ <td>Dorian</td>
+ </tr>
+ </tbody>
+</table>
+
+<script>
+ var EVENT = "foo";
+ var TARGET = document.getElementById("target");
+ var PARENT = document.getElementById("parent");
+ var TBODY = document.getElementById("table-body");
+ var TABLE = document.getElementById("table");
+ var BODY = document.body;
+ var HTML = document.documentElement;
+ var CurrentTargets = [window, document, HTML, BODY, TABLE, TBODY, PARENT, TARGET];
+ var ExpectResult = [];
+ var ActualResult = [];
+ var ExpectPhases = [];
+ var ActualPhases = [];
+
+ var description = "Test Description: " +
+ "If Event.stopPropagation() has been called prior to the dispatch, all phases must be skipped.";
+ test(function()
+ {
+ for (var i=0; i < CurrentTargets.length; i++)
+ {
+ CurrentTargets[i].addEventListener(EVENT, TestEvent, true);
+ CurrentTargets[i].addEventListener(EVENT, TestEvent, false);
+ }
+
+ var evt = document.createEvent("Event");
+ evt.initEvent(EVENT, true, true);
+ evt.stopPropagation();
+ TARGET.dispatchEvent(evt);
+
+ assert_array_equals(ActualResult, ExpectResult, "ActualResult");
+ assert_array_equals(ActualPhases, ExpectPhases, "ActualPhases");
+
+ }, description);
+
+ function TestEvent(evt)
+ {
+ ActualResult.push(evt.currentTarget);
+ ActualPhases.push(evt.eventPhase);
+ }
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/approved/support/ProcessingInstruction.DOMCharacterDataModified.xml b/tests/wpt/web-platform-tests/DOMEvents/tests/approved/support/ProcessingInstruction.DOMCharacterDataModified.xml
new file mode 100644
index 00000000000..7c0091a8f91
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/approved/support/ProcessingInstruction.DOMCharacterDataModified.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0"?>
+<root>
+ <head xmlns="http://www.w3.org/1999/xhtml">
+ <title> ProcessingInstruction.data and DOMCharacterDataModified event </title>
+ </head>
+ <div id="log" xmlns="http://www.w3.org/1999/xhtml"></div>
+
+ <pi><?foo bar?></pi>
+
+ <script type="text/javascript" xmlns="http://www.w3.org/1999/xhtml">
+ <![CDATA[
+ var EVENT = "DOMCharacterDataModified";
+ var TARGET = document.getElementsByTagName('pi')[0].firstChild;
+ var TestResult = false;
+
+ TARGET.addEventListener(EVENT, TestEvent, false);
+ TARGET.data = "new" + TARGET.data;
+
+ function TestEvent(evt)
+ {
+ if ((EVENT == evt.type) && (TARGET == evt.target) && ("newbar" == evt.newValue))
+ {
+ TestResult = true;
+ }
+ else
+ {
+ TestResult = false;
+ }
+ }
+ ]]>
+ </script>
+</root> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/CompositionEvent.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/CompositionEvent.html
new file mode 100644
index 00000000000..0f8242b07d5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/CompositionEvent.html
@@ -0,0 +1,69 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title id='desc'> Composition Event Types: compositionstart, compositionupdate, compositionend </title>
+ <script type="text/javascript">
+ var PassTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+
+ var FailTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+
+ var TARGET;
+ var ExpectResult = ["compositionstart", "compositionupdate", "compositionend"];
+ var ActualResult = [];
+ var count = 0
+
+ window.onload = function(e)
+ {
+ try
+ {
+ TARGET = document.getElementById("target");
+ TARGET.addEventListener("compositionstart", TestEvent, true);
+ TARGET.addEventListener("compositionupdate", TestEvent, true);
+ TARGET.addEventListener("compositionend", TestEvent, true);
+ }
+ catch(ex)
+ {
+ FailTest();
+ }
+ }
+
+ function TestEvent(evt)
+ {
+ ActualResult.push(evt.type);
+ TARGET.removeEventListener(evt.type, TestEvent, true);
+
+ if (ExpectResult.toString() == ActualResult.toString())
+ {
+ PassTest();
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <h3>DOM Events</h3>
+ <h4>
+ Test Description: The composition events occur in a set order relative to one another:
+ 1. compositionstart, 2. compositionupdate (multiple events), 3. compositionend.
+ </h4>
+
+ <pre>
+ <input id="target" value=""/>
+
+ Steps:
+ 1) Open Japanese Microsoft IME and select Hiragana input method
+ 2) Click at the above textbox and then type 'a' using keyboard
+ 3) Press the '{Enter}' key to complete the IME composition
+ 4) <a href="CompositionEvent.html">Click here</a> to test again if not following the steps exactly
+ </pre>
+
+ <p>Test passes if the word "PASS" appears below and nothing is typed to the textbox after following the above steps.</p>
+ <div>Test result: </div>
+ <div id='testresult'>FAIL</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/DOMAttrModified.attrChange.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/DOMAttrModified.attrChange.html
new file mode 100644
index 00000000000..12c45fc848e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/DOMAttrModified.attrChange.html
@@ -0,0 +1,65 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title id='desc'> MutationEvent.attrChange for DOMAttrModified Event </title>
+ <script type="text/javascript">
+ var PassTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+
+ var FailTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+
+ var EVENT = "DOMAttrModified";
+ var ATTR = "name";
+ var TARGET;
+ var ExpectResult = [2, 1, 3];
+ var ActualResult = [];
+
+ window.onload = function(e)
+ {
+ try
+ {
+ TARGET = document.getElementById("target");
+ TARGET.addEventListener(EVENT, TestEvent, true);
+
+ TARGET.setAttribute(ATTR, "foo");
+ TARGET.setAttribute(ATTR, "bar");
+ TARGET.removeAttribute(ATTR);
+ }
+ catch(ex)
+ {
+ FailTest();
+ }
+ }
+
+ function TestEvent(evt)
+ {
+ if (evt.type == EVENT)
+ {
+ ActualResult.push(evt.attrChange);
+ }
+
+ if (ExpectResult.toString() == ActualResult.toString())
+ {
+ PassTest();
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <h3>DOM Events</h3>
+ <h4>
+ Test Description: MutationEvent.attrChange indicates the type of change which triggered the DOMAttrModified event.
+ </h4>
+
+ <div id="target"></div>
+
+ <p>Test passes if the word "PASS" appears below.</p>
+ <div>Test result: </div>
+ <div id='testresult'>FAIL</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/DOMAttrModified.attrName.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/DOMAttrModified.attrName.html
new file mode 100644
index 00000000000..ca1ad97d24d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/DOMAttrModified.attrName.html
@@ -0,0 +1,66 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title id='desc'> MutationEvent.attrName for DOMAttrModified Event </title>
+ <script type="text/javascript">
+ var PassTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+
+ var FailTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+
+ var EVENT = "DOMAttrModified";
+ var ATTR = "name";
+ var TARGET;
+ var ExpectResult = ["name", "foo", "style"];
+ var ActualResult = [];
+
+ window.onload = function(e)
+ {
+ try
+ {
+ TARGET = document.getElementById("target");
+ TARGET.addEventListener(EVENT, TestEvent, true);
+
+ TARGET.setAttribute(ATTR, "wow");
+ TARGET.setAttribute("foo", "bar");
+ TARGET.removeAttribute("style");
+ }
+ catch(ex)
+ {
+ FailTest();
+ }
+ }
+
+ function TestEvent(evt)
+ {
+ if (evt.type == EVENT)
+ {
+ ActualResult.push(evt.attrName);
+ }
+
+ if (ExpectResult.toString() == ActualResult.toString())
+ {
+ PassTest();
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <h3>DOM Events</h3>
+ <h4>
+ Test Description: MutationEvent.attrName indicates the name of the changed Attr node
+ in a DOMAttrModified event.
+ </h4>
+
+ <div id="target" name="blah" style="border:solid 1px green; width:350px; height:100px;"></div>
+
+ <p>Test passes if the word "PASS" appears below.</p>
+ <div>Test result: </div>
+ <div id='testresult'>FAIL</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/DOMAttrModified.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/DOMAttrModified.html
new file mode 100644
index 00000000000..c229abe96e3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/DOMAttrModified.html
@@ -0,0 +1,66 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title id='desc'> Mutation Event Type: DOMAttrModified </title>
+ <script type="text/javascript">
+ var PassTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+
+ var FailTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+
+ var EVENT = "DOMAttrModified";
+ var ATTR = "name";
+ var TARGET;
+ var ExpectResult = ["foo", "bar", null];
+ var ActualResult = [];
+
+ window.onload = function(e)
+ {
+ try
+ {
+ TARGET = document.getElementById("target");
+ TARGET.addEventListener(EVENT, TestEvent, true);
+
+ TARGET.setAttribute(ATTR, "foo");
+ TARGET.setAttribute(ATTR, "bar");
+ TARGET.removeAttribute(ATTR);
+ }
+ catch(ex)
+ {
+ FailTest();
+ }
+ }
+
+ function TestEvent(evt)
+ {
+ if (evt.type == EVENT)
+ {
+ ActualResult.push(TARGET.getAttribute(ATTR));
+ }
+
+ if (ExpectResult.toString() == ActualResult.toString())
+ {
+ PassTest();
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <h3>DOM Events</h3>
+ <h4>
+ Test Description: DOMAttrModified event fires after an Attr.value has been
+ modified and after an Attr node has been added to or removed from an Element.
+ </h4>
+
+ <div id="target"></div>
+
+ <p>Test passes if the word "PASS" appears below.</p>
+ <div>Test result: </div>
+ <div id='testresult'>FAIL</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/DOMAttrModified.newValue.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/DOMAttrModified.newValue.html
new file mode 100644
index 00000000000..77b8a41e1a3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/DOMAttrModified.newValue.html
@@ -0,0 +1,65 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title id='desc'> MutationEvent.newValue for DOMAttrModified Event </title>
+ <script type="text/javascript">
+ var PassTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+
+ var FailTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+
+ var EVENT = "DOMAttrModified";
+ var ATTR = "name";
+ var TARGET;
+ var ExpectResult = ["foo", "bar", null];
+ var ActualResult = [];
+
+ window.onload = function(e)
+ {
+ try
+ {
+ TARGET = document.getElementById("target");
+ TARGET.addEventListener(EVENT, TestEvent, true);
+
+ TARGET.setAttribute(ATTR, "foo");
+ TARGET.setAttribute(ATTR, "bar");
+ TARGET.removeAttribute(ATTR);
+ }
+ catch(ex)
+ {
+ FailTest();
+ }
+ }
+
+ function TestEvent(evt)
+ {
+ if (evt.type == EVENT)
+ {
+ ActualResult.push(evt.newValue);
+ }
+
+ if (ExpectResult.toString() == ActualResult.toString())
+ {
+ PassTest();
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <h3>DOM Events</h3>
+ <h4>
+ Test Description: MutationEvent.newValue indicates the new value of the Attr node in DOMAttrModified events.
+ </h4>
+
+ <div id="target"></div>
+
+ <p>Test passes if the word "PASS" appears below.</p>
+ <div>Test result: </div>
+ <div id='testresult'>FAIL</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/DOMAttrModified.prevValue.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/DOMAttrModified.prevValue.html
new file mode 100644
index 00000000000..31fbec77644
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/DOMAttrModified.prevValue.html
@@ -0,0 +1,65 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title id='desc'> MutationEvent.prevValue for DOMAttrModified Event </title>
+ <script type="text/javascript">
+ var PassTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+
+ var FailTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+
+ var EVENT = "DOMAttrModified";
+ var ATTR = "name";
+ var TARGET;
+ var ExpectResult = [null, "foo", "bar"];
+ var ActualResult = [];
+
+ window.onload = function(e)
+ {
+ try
+ {
+ TARGET = document.getElementById("target");
+ TARGET.addEventListener(EVENT, TestEvent, true);
+
+ TARGET.setAttribute(ATTR, "foo");
+ TARGET.setAttribute(ATTR, "bar");
+ TARGET.removeAttribute(ATTR);
+ }
+ catch(ex)
+ {
+ FailTest();
+ }
+ }
+
+ function TestEvent(evt)
+ {
+ if (evt.type == EVENT)
+ {
+ ActualResult.push(evt.prevValue);
+ }
+
+ if (ExpectResult.toString() == ActualResult.toString())
+ {
+ PassTest();
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <h3>DOM Events</h3>
+ <h4>
+ Test Description: MutationEvent.prevValue indicates the previous value of the Attr node in DOMAttrModified events.
+ </h4>
+
+ <div id="target"></div>
+
+ <p>Test passes if the word "PASS" appears below.</p>
+ <div>Test result: </div>
+ <div id='testresult'>FAIL</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/DOMAttrModified.relatedNode.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/DOMAttrModified.relatedNode.html
new file mode 100644
index 00000000000..5c30dabe22f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/DOMAttrModified.relatedNode.html
@@ -0,0 +1,66 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title id='desc'> MutationEvent.relatedNode for DOMAttrModified Event </title>
+ <script type="text/javascript">
+ var PassTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+
+ var FailTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+
+ var EVENT = "DOMAttrModified";
+ var ATTR = "name";
+ var TARGET;
+ var ExpectResult = ["name", "foo", "style"];
+ var ActualResult = [];
+
+ window.onload = function(e)
+ {
+ try
+ {
+ TARGET = document.getElementById("target");
+ TARGET.addEventListener(EVENT, TestEvent, true);
+
+ TARGET.setAttribute(ATTR, "wow");
+ TARGET.setAttribute("foo", "bar");
+ TARGET.removeAttribute("style");
+ }
+ catch(ex)
+ {
+ FailTest();
+ }
+ }
+
+ function TestEvent(evt)
+ {
+ if (evt.type == EVENT)
+ {
+ ActualResult.push(evt.relatedNode.nodeName);
+ }
+
+ if (ExpectResult.toString() == ActualResult.toString())
+ {
+ PassTest();
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <h3>DOM Events</h3>
+ <h4>
+ Test Description: In the case of the DOMAttrModified event, MutationEvent.relatedNode
+ indicates the Attr node which was modified, added, or removed.
+ </h4>
+
+ <div id="target" name="blah" style="border:solid 1px green; width:350px; height:100px;"></div>
+
+ <p>Test passes if the word "PASS" appears below.</p>
+ <div>Test result: </div>
+ <div id='testresult'>FAIL</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/DOMCharacterDataModified.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/DOMCharacterDataModified.html
new file mode 100644
index 00000000000..31d4fbf08f3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/DOMCharacterDataModified.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title id='desc'> MutationEvent: DOMCharacterDataModified Event Type </title>
+ <script type="text/javascript">
+ var PassTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+
+ var FailTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+
+ var EVENT = "DOMCharacterDataModified";
+ var TARGET;
+ var TEXTNODE;
+
+ window.onload = function()
+ {
+ try
+ {
+ TARGET = document.getElementById("target");
+ TARGET.addEventListener(EVENT, TestEvent, true);
+ TEXTNODE = TARGET.firstChild;
+ TEXTNODE.data += "world";
+
+ }
+ catch(ex)
+ {
+ FailTest();
+ }
+ }
+
+ function TestEvent(evt)
+ {
+ if (EVENT == evt.type)
+ {
+ PassTest();
+ }
+ else
+ {
+ FailTest();
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <h3>DOM Events</h3>
+ <h4>
+ Test Description: DOMCharacterDataModified event fires after CharacterData.data has been modified.
+ </h4>
+
+ <span id="parent">
+ <div id="target" contenteditable style="border:solid 1px green; width:100px; height:100px">Hello </div>
+ </span>
+ <p>Test passes if the word "PASS" appears below.</p>
+ <div>Test result: </div>
+ <div id='testresult'>FAIL</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/DOMNodeInserted.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/DOMNodeInserted.html
new file mode 100644
index 00000000000..0e0d26d1aae
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/DOMNodeInserted.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title id='desc'> MutationEvent: DOMNodeInserted Event Type </title>
+ <script type="text/javascript">
+ var PassTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+
+ var FailTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+
+ var EVENT = "DOMNodeInserted";
+ var TARGET;
+ var NODE;
+
+ window.onload = function()
+ {
+ try
+ {
+ TARGET = document.getElementById("target");
+ TARGET.addEventListener(EVENT, TestEvent, true);
+
+ NODE = document.createElement("INPUT");
+ TARGET.appendChild(NODE);
+ }
+ catch(ex)
+ {
+ FailTest();
+ }
+ }
+
+ function TestEvent(evt)
+ {
+ if (EVENT == evt.type)
+ {
+ PassTest();
+ }
+ else
+ {
+ FailTest();
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <h3>DOM Events</h3>
+ <h4>
+ Test Description: DOMNodeInserted event fires when a node has been added as a child of another node.
+ </h4>
+
+ <span id="parent">
+ <div id="target" style="border:solid 1px green; width:200px; height:50px">
+ </div>
+ </span>
+
+ <p>Test passes if the word "PASS" appears below.</p>
+ <div>Test result: </div>
+ <div id='testresult'>FAIL</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/DOMNodeRemoved.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/DOMNodeRemoved.html
new file mode 100644
index 00000000000..34d7112027c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/DOMNodeRemoved.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title id='desc'> MutationEvent: DOMNodeRemoved Event Type </title>
+ <script type="text/javascript">
+ var PassTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+
+ var FailTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+
+ var EVENT = "DOMNodeRemoved";
+ var TARGET;
+ var PARENT;
+
+ window.onload = function()
+ {
+ try
+ {
+ TARGET = document.getElementById("target");
+ PARENT = document.getElementById("parent");
+ TARGET.addEventListener(EVENT, TestEvent, true);
+ PARENT.removeChild(TARGET);
+ }
+ catch(ex)
+ {
+ FailTest();
+ }
+ }
+
+ function TestEvent(evt)
+ {
+ if (EVENT == evt.type)
+ {
+ PassTest();
+ }
+ else
+ {
+ FailTest();
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <h3>DOM Events</h3>
+ <h4>
+ Test Description: DOMNodeRemoved event fires when a node is being removed from its parent node.
+ </h4>
+
+ <span id="parent">
+ <div id="target" style="border:solid 1px green; width:100px; height:100px">
+ </div>
+ </span>
+ <p>Test passes if the word "PASS" appears below.</p>
+ <div>Test result: </div>
+ <div id='testresult'>FAIL</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/DOMSubtreeModified.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/DOMSubtreeModified.html
new file mode 100644
index 00000000000..1819f563dac
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/DOMSubtreeModified.html
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title id='desc'> MutationEvent: DOMSubtreeModified Event Type </title>
+ <script type="text/javascript">
+ var PassTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+
+ var FailTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+
+ var EVENT1 = "DOMSubtreeModified";
+ var EVENT2 = "DOMNodeRemoved";
+ var TARGET;
+ var HELPER;
+ var ActualResult = [];
+ var ExpectResult = [EVENT2, EVENT1];
+
+ window.onload = function()
+ {
+ try
+ {
+ TARGET = document.getElementById("target");
+ TARGET.addEventListener(EVENT1, TestEvent, true);
+ TARGET.addEventListener(EVENT2, TestEvent, true);
+
+ HELPER = document.getElementById("helper");
+ TARGET.removeChild(HELPER);
+ }
+ catch(ex)
+ {
+ FailTest();
+ }
+ }
+
+ function TestEvent(evt)
+ {
+ ActualResult.push(evt.type);
+
+ if (ExpectResult.toString() == ActualResult.toString())
+ {
+ PassTest();
+ }
+
+ if (2 < ActualResult.length)
+ {
+ FailTest();
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <h3>DOM Events</h3>
+ <h4>
+ Test Description: DOMSubtreeModified event fires after any other events
+ caused by the mutation(s) have occurred.
+ </h4>
+
+ <span id="parent">
+ <div id="target" style="border:solid 1px green; width:200px; height:50px">
+ <input id="helper">
+ </div>
+ </span>
+ <p>Test passes if the word "PASS" appears below.</p>
+ <div>Test result: </div>
+ <div id='testresult'>FAIL</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/Event.defaultPrevented.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/Event.defaultPrevented.html
new file mode 100644
index 00000000000..d1e0244c16b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/Event.defaultPrevented.html
@@ -0,0 +1,68 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title> W3C DOM Level 3 Event Object Property: defaultPrevented </title>
+ <script type="text/javascript">
+ var PassTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+
+ var FailTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+
+ var EVENT = "click";
+ var TARGET;
+
+ window.onload = function()
+ {
+ try
+ {
+ TARGET = document.getElementById("target");
+ TARGET.addEventListener(EVENT, TestCapture, true);
+ }
+ catch(ex)
+ {
+ FailTest();
+ }
+ }
+
+ function TestCapture(evt)
+ {
+ try
+ {
+ evt.preventDefault();
+
+ if ((evt.type == EVENT) && (evt.defaultPrevented == true))
+ {
+ PassTest();
+ }
+ else
+ {
+ FailTest();
+ }
+ }
+ catch(ex)
+ {
+ FailTest();
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <h4>
+ Test Description:
+ Event listeners can cancel default actions of cancelable event objects by invoking the Event.preventDefault()
+ method, and determine whether an event has been canceled through the Event.defaultPrevented attribute.
+ </h4>
+
+ Click the hyperlink:
+ <a href="http://samples.msdn.microsoft.com/ietestcenter/" id="target">http://samples.msdn.microsoft.com/ietestcenter</a>
+
+ <p>Test passes if the word "PASS" appears below after clicking the hyperlink and the page does not navigate away.</p>
+ <div>Test result: </div>
+ <div id='testresult'>FAIL</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/Event.eventPhase.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/Event.eventPhase.html
new file mode 100644
index 00000000000..ab297e7c553
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/Event.eventPhase.html
@@ -0,0 +1,77 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title> W3C DOM Level 2 Event Object Property: eventPhase </title>
+ <script type="text/javascript">
+ var PassTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+
+ var FailTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+
+ var EVENT = "dblclick";
+ var TARGET, PARENT;
+ var ActualResult = [];
+ var ExpectResult = [];
+
+ window.onload = function()
+ {
+ try
+ {
+ TARGET = document.getElementById("target");
+ PARENT = document.getElementById("parent");
+
+ ExpectResult = ["[1]" + PARENT, "[2]" + TARGET, "[3]" + document.body];
+
+ PARENT.addEventListener(EVENT, TestEvent, true);
+ PARENT.addEventListener(EVENT, TestEvent, false);
+ TARGET.addEventListener(EVENT, TestEvent, true);
+ TARGET.addEventListener(EVENT, TestEvent, false);
+ document.body.addEventListener(EVENT, TestEvent, false);
+
+ PARENT.removeEventListener(EVENT, TestEvent, false);
+ TARGET.removeEventListener(EVENT, TestEvent, true);
+ }
+ catch(ex)
+ {
+ FailTest();
+ }
+ }
+
+ function TestEvent(evt)
+ {
+ ActualResult.push("[" + evt.eventPhase + "]" + evt.currentTarget);
+
+ if ((evt.eventPhase == 3) && (evt.currentTarget == document.body))
+ {
+ if (ExpectResult.toString() == ActualResult.toString())
+ {
+ PassTest();
+ }
+ else
+ {
+ FailTest();
+ }
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <h4>
+ Test Description:
+ eventPhase is used to indicate which phase of event flow is currently being accomplished.
+ </h4>
+
+ <div id="parent">
+ Double click here: <input id="target" />
+ </div>
+
+ <p>Test passes if the word "PASS" appears below after double clicking the above textbox.</p>
+ <div>Test result: </div>
+ <div id='testresult'>FAIL</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/Event.stopPropagation.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/Event.stopPropagation.html
new file mode 100644
index 00000000000..9f796db6508
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/Event.stopPropagation.html
@@ -0,0 +1,85 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title> W3C DOM Level 3 Event Object method: stopPropagation </title>
+ <script type="text/javascript">
+ var PassTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+
+ var FailTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+
+ var EVENT = "mousedown";
+ var TARGET, PARENT;
+ var ActualResult = [];
+ var ExpectResult = [];
+
+ window.onload = function()
+ {
+ try
+ {
+ TARGET = document.getElementById("target");
+ PARENT = document.getElementById("parent");
+
+ ExpectResult = [document.body, PARENT];
+
+ TARGET.addEventListener(EVENT, TestEvent, true);
+ TARGET.addEventListener(EVENT, TestEvent, false);
+ PARENT.addEventListener(EVENT, TestEvent, true);
+ PARENT.addEventListener(EVENT, TestEvent, false);
+ document.body.addEventListener(EVENT, TestEvent, true);
+ }
+ catch(ex)
+ {
+ FailTest();
+ }
+ }
+
+ function TestEvent(evt)
+ {
+ ActualResult.push(evt.currentTarget);
+
+ if (evt.currentTarget == PARENT)
+ {
+ try
+ {
+ evt.stopPropagation();
+ }
+ catch(ex)
+ {
+ }
+ }
+ }
+
+ function VerifyTest()
+ {
+ if (ActualResult.toString() == ExpectResult.toString())
+ {
+ PassTest();
+ }
+ else
+ {
+ FailTest();
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <h4>
+ Test Description:
+ stopPropagation prevents other event listeners from being triggered.
+ </h4>
+
+ <div id="parent">
+ Click the button: <input id="target" type="button" value="Target" onmouseup="VerifyTest()" />
+ </div>
+
+ <p>Test passes if the word "PASS" appears below after clicking the above button using mouse.</p>
+ <div>Test result: </div>
+ <div id='testresult'>FAIL</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/KeyboardEvent.key.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/KeyboardEvent.key.html
new file mode 100644
index 00000000000..4c1d254474a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/KeyboardEvent.key.html
@@ -0,0 +1,56 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title id='desc'> KeyboardEvent Object Property: key </title>
+ <script type="text/javascript">
+ var PassTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+
+ var FailTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+
+ var EVENT = "keydown";
+ var TARGET;
+ var ActualResult = "";
+ var result = true;
+
+ window.onload = function(e)
+ {
+ try
+ {
+ TARGET = document.getElementById("target");
+ TARGET.addEventListener(EVENT, TestEvent, true);
+ }
+ catch(ex)
+ {
+ FailTest();
+ }
+ }
+
+ function TestEvent(evt)
+ {
+ if ((evt.type == EVENT) && (evt.key == "a"))
+ {
+ PassTest();
+ }
+ else
+ {
+ FailTest();
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <h4>Test Description: KeyboardEvent Object Property key holds the key value of the key pressed</h4>
+
+ Type 'a' here: <input id="target" value=""/>
+
+ <p>Test passes if the word "PASS" appears below after typing 'a' in the above textbox using keyboard.</p>
+ <div>Test result: </div>
+ <div id='testresult'>FAIL</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/KeyboardEvent.location.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/KeyboardEvent.location.html
new file mode 100644
index 00000000000..63fe460f3d3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/KeyboardEvent.location.html
@@ -0,0 +1,74 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title id='desc'> KeyboardEvent.location </title>
+ <script type="text/javascript">
+ var PassTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+
+ var FailTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+
+ var EVENT = "keydown";
+ var TARGET;
+ var ExpectResult = ["a", 0, "Control", 1, "Shift", 2];
+ var ActualResult = [];
+
+ window.onload = function(e)
+ {
+ try
+ {
+ TARGET = document.getElementById("target");
+ TARGET.addEventListener(EVENT, TestEvent, true);
+ }
+ catch(ex)
+ {
+ FailTest();
+ }
+ }
+
+ function TestEvent(evt)
+ {
+ ActualResult.push(evt.key, evt.location);
+
+ if ((evt.type == EVENT) && (evt.key == "Shift"))
+ {
+ if (ExpectResult.toString() == ActualResult.toString())
+ {
+ PassTest();
+ }
+ else
+ {
+ FailTest();
+ }
+ TARGET.removeEventListener(EVENT, TestEvent, true);
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <h3>DOM Events</h3>
+ <h4>
+ Test Description: KeyboardEvent.location attribute contains an indication of the
+ location of the key on the device.
+ </h4>
+
+ <pre>
+ <input id="target" value=""/>
+
+ Steps:
+ 1) Type 'a' in the above textbox using keyboard
+ 2) Press '{CTRL}' key on the left side of the keyboard
+ 3) Press '{SHIFT}' key on the right side of the keyboard
+ 4) <a href="KeyboardEvent.location.html">Click here</a> to test again if not following the steps exactly
+ </pre>
+
+ <p>Test passes if the word "PASS" appears below after following the above steps.</p>
+ <div>Test result: </div>
+ <div id='testresult'>FAIL</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/KeyboardEvent.modifiers.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/KeyboardEvent.modifiers.html
new file mode 100644
index 00000000000..ee490b47ec6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/KeyboardEvent.modifiers.html
@@ -0,0 +1,66 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title id='desc'> KeyboardEvent.getModifierState() and 'AltGraph' modifier key </title>
+ <script type="text/javascript">
+ var PassTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+
+ var FailTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+
+ var EVENT = "keydown";
+ var TARGET;
+
+ window.onload = function(e)
+ {
+ try
+ {
+ TARGET = document.getElementById("target");
+ TARGET.addEventListener(EVENT, TestEvent, true);
+ }
+ catch(ex)
+ {
+ FailTest();
+ }
+ }
+
+ function TestEvent(evt)
+ {
+ if ((evt.type == EVENT) && evt.getModifierState("AltGraph"))
+ {
+ PassTest();
+ TARGET.removeEventListener(EVENT, TestEvent, true);
+ }
+ else
+ {
+ FailTest();
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <h3>DOM Events</h3>
+ <h4>
+ Test Description: Some operating systems simulate the 'AltGraph' modifier key
+ with the combination of the 'Alt' and 'Control' modifier keys. Implementations
+ are encouraged to use the 'AltGraph' modifier key.
+ </h4>
+
+ <pre>
+ <input id="target" value=""/>
+
+ Steps:
+ 1) Click in the above textbox using mouse
+ 2) Press and hold down '{CTRL}' key and then press '{ALT}' key on the keyboard
+ </pre>
+
+ <p>Test passes if the word "PASS" appears below after following the above steps.</p>
+ <div>Test result: </div>
+ <div id='testresult'>FAIL</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/MouseEvent.button.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/MouseEvent.button.html
new file mode 100644
index 00000000000..213009f4c4d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/MouseEvent.button.html
@@ -0,0 +1,65 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title id='desc'> MouseEvent.button for mouseup Event </title>
+ <script type="text/javascript">
+ var PassTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+
+ var FailTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+
+ var EVENT = "mouseup";
+ var TARGET;
+ var ExpectResult = [0, 1, 2];
+ var ActualResult = [];
+
+ window.onload = function(e)
+ {
+ try
+ {
+ TARGET = document.getElementById("target");
+ TARGET.addEventListener(EVENT, TestEvent, true);
+ }
+ catch(ex)
+ {
+ FailTest();
+ }
+ }
+
+ function TestEvent(evt)
+ {
+
+ ActualResult.push(evt.button);
+ TARGET.value = ActualResult;
+
+ if (ExpectResult.toString() == ActualResult.toString())
+ {
+ PassTest();
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <h4>
+ Test Description: MouseEvent.button value for mouseup event is based on current button pressed.
+ </h4>
+
+ <pre>
+ <input id="target" value=""/>
+
+ Steps:
+ 1) Move the mouse pointer to the above textbox
+ 2) Click the mouse button in this order: Left Button, Middle Button, Right Button
+ 3) <a href="MouseEvent.button.html">Click here</a> to test again if not following the steps exactly
+ </pre>
+
+ <p>Test passes if the word "PASS" appears below after following the above steps.</p>
+ <div>Test result: </div>
+ <div id='testresult'>FAIL</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/MouseEvent.image.map.area.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/MouseEvent.image.map.area.html
new file mode 100644
index 00000000000..17b7dd5ccee
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/MouseEvent.image.map.area.html
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title id='desc'> MouseEvent event on IMG element with MAP and AREA elements</title>
+ <script type="text/javascript">
+ var PassTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+
+ var FailTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+
+ var TARGET;
+ var EVENT = "click";
+
+ function TestEvent(evt)
+ {
+ evt.preventDefault();
+
+ if ((EVENT == evt.type) && (TARGET === evt.target))
+ {
+ PassTest();
+ }
+ else
+ {
+ FailTest();
+ }
+ }
+
+ window.onload = function(evt)
+ {
+ try
+ {
+ TARGET = document.getElementById("target");
+ document.addEventListener(EVENT, TestEvent, false);
+ }
+ catch(ex)
+ {
+ FailTest();
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <h3>DOM Events</h3>
+ <h4>
+ Test Description: MouseEvent event fires on the AREA element when click the MAP AREA on an image
+ </h4>
+
+ <img src="./support/iepreview.png" usemap="#ieMap" />
+
+ <map name="ieMap">
+ <area id="target" href="MouseEvent.image.map.area.html" shape="rect" coords="140 180 250 250" title="Arrow" />
+ </map>
+
+ <p id="manualsteps">
+ Steps:
+ <ol>
+ <li> Click at the arrow pointer symbol on the bottom-right corner of the image.
+ </ol>
+ </p>
+
+ <p>Test passes if the word "PASS" appears below after following the above steps.</p>
+ <div>Test result: </div>
+ <div id='testresult'>FAIL</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/MouseEvent.preventDefault.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/MouseEvent.preventDefault.html
new file mode 100644
index 00000000000..e6cb57806db
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/MouseEvent.preventDefault.html
@@ -0,0 +1,94 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title id='desc'> MouseEvent: mousedown - preventDefault() for text selection </title>
+ <script type="text/javascript">
+ var PassTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+
+ var FailTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+
+ var EVENT1 = "mousedown";
+ var EVENT2 = "mouseup";
+ var TARGET;
+ var DisableSelection = false;
+ var DefaultPrevented = false;
+ var BEFORE = 0;
+ var AFTER = 0;
+
+ function DisableTextSelection()
+ {
+ DisableSelection = true;
+ }
+
+ function TestEvent(evt)
+ {
+ if ((true == DisableSelection) && (EVENT1 == evt.type))
+ {
+ evt.preventDefault();
+ DefaultPrevented = true;
+ BEFORE = evt.clientX;
+ }
+ if ((true == DisableSelection) && (EVENT2 == evt.type))
+ {
+ AFTER = evt.clientX;
+ }
+ }
+
+ function VerifyResult()
+ {
+ var distance = Math.abs(AFTER - BEFORE);
+
+ if ((true == DefaultPrevented) && (10 < distance) && ("" == window.getSelection()))
+ {
+ PassTest()
+ }
+ else
+ {
+ FailTest();
+ }
+ }
+
+ window.onload = function()
+ {
+ try
+ {
+ TARGET = document.getElementById("target");
+ TARGET.addEventListener(EVENT1, TestEvent, false);
+ TARGET.addEventListener(EVENT2, TestEvent, false);
+ }
+ catch(ex)
+ {
+ FailTest();
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <h3>DOM Events</h3>
+ <h4>
+ Test Description: MouseEvent - Text selection is disabled after cancelling mousedown event.
+ </h4>
+
+ <span id="target" style="border:1px solid green; color:blue">&nbsp; Use mouse to select the whole line here &nbsp;</span>
+
+ <p id="manualsteps">
+ Steps:
+ <ol>
+ <li> Make sure text in the above green box can be selected using mouse
+ <li> Dismiss the selection, if any, by clicking at the green box with mouse
+ <li> Now, click the button: <button onclick="DisableTextSelection()">Disable Selection</button>
+ <li> Drag mouse to select the whole line of the text inside the above green box
+ <li> Click the button: <button id="verify" onclick="VerifyResult()">VerifyResult</button>
+ </ol>
+ </p>
+ <p>Test passes if the word "PASS" appears below after following the above steps.</p>
+ <div>Test result: </div>
+ <div id='testresult'>FAIL</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/MutationEvent.hasFeature.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/MutationEvent.hasFeature.html
new file mode 100644
index 00000000000..f550a5366df
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/MutationEvent.hasFeature.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title id='desc'> MutationEvent: feature detection with hasFeature() </title>
+ <script type="text/javascript">
+ var PassTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+
+ var FailTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+
+ window.onload = function()
+ {
+ try
+ {
+ var features = ["MutationEvent",
+ "Events.MutationEvent",
+ "Events.DOMSubtreeModified",
+ "Events.DOMNodeInserted",
+ "Events.DOMNodeRemoved",
+ "Events.DOMAttrModified",
+ "Events.DOMCharacterDataModified"];
+
+ var versions = ["3.0", "", null];
+ var TestResult = true;
+ var HasFeature = false;
+
+ for (var i=0; i<features.length; i++)
+ {
+ for (var j=0; j<versions.length; j++)
+ {
+ HasFeature = document.implementation.hasFeature(features[i], versions[j]);
+ TestResult = HasFeature && TestResult;
+ }
+ }
+
+ if (HasFeature && TestResult)
+ {
+ PassTest();
+ }
+ else
+ {
+ FailTest();
+ }
+ }
+ catch(ex)
+ {
+ FailTest();
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <h3>DOM Events</h3>
+ <h4>
+ Test Description: MutationEvent - feature support detection using DOMImplementation.hasFeature() method
+ </h4>
+
+ <p>Test passes if the word "PASS" appears below.</p>
+ <div>Test result: </div>
+ <div id='testresult'>FAIL</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/MutationEvent.initMutationEvent.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/MutationEvent.initMutationEvent.html
new file mode 100644
index 00000000000..3b2bceabf45
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/MutationEvent.initMutationEvent.html
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title id='desc'> MutationEvent.initMutationEvent() and Event.trusted </title>
+ <script type="text/javascript">
+ var PassTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+
+ var FailTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+
+ var EVENT = "foo";
+ var TARGET;
+ var ExpectResult = [];
+ var ActualResult = [];
+ var TestResult = true;
+
+ window.onload = function()
+ {
+ try
+ {
+ TARGET = document.getElementById("target");
+ TARGET.addEventListener(EVENT, TestEvent, true);
+
+ var evt = document.createEvent("MutationEvent");
+ evt.initMutationEvent(EVENT, /* type */
+ true, /* bubbles */
+ true, /* cancelable */
+ null, /* relatedNode */
+ "hello", /* prevValue */
+ "world", /* newValue */
+ "bar", /* attrName */
+ 1 /* attrChange*/ );
+
+ TARGET.dispatchEvent(evt);
+ }
+ catch(ex)
+ {
+ FailTest();
+ }
+
+ }
+
+ function TestEvent(evt)
+ {
+ if ((EVENT == evt.type) && (false == evt.trusted))
+ {
+ PassTest();
+ }
+ else
+ {
+ FailTest();
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <h3>DOM Events</h3>
+ <h4>
+ Test Description: initMutationEvent initializes attributes of a MutationEvent object.
+ </h4>
+
+ <input id="target" type="hidden" />
+ <p>Test passes if the word "PASS" appears below.</p>
+ <div>Test result: </div>
+ <div id='testresult'>FAIL</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/MutationEvent.relatedNode.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/MutationEvent.relatedNode.html
new file mode 100644
index 00000000000..6b92079ef61
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/MutationEvent.relatedNode.html
@@ -0,0 +1,76 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title id='desc'> MutationEvent.relatedNode for DOMNodeInserted and DOMNodeRemoved </title>
+ <script type="text/javascript">
+ var PassTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+
+ var FailTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+
+ var EVENT1 = "DOMNodeInserted";
+ var EVENT2 = "DOMNodeRemoved";
+ var TARGET;
+ var PARENT;
+ var NODE;
+ var ActualResult = [];
+ var ExpectResult = [];
+
+ window.onload = function()
+ {
+ try
+ {
+ TARGET = document.getElementById("target");
+ PARENT = document.getElementById("parent");
+ TARGET.addEventListener(EVENT1, TestEvent, true);
+ TARGET.addEventListener(EVENT2, TestEvent, true);
+
+ ExpectResult = [TARGET, PARENT];
+
+ NODE = document.createElement("INPUT");
+ TARGET.appendChild(NODE);
+ PARENT.removeChild(TARGET);
+ }
+ catch(ex)
+ {
+ FailTest();
+ }
+ }
+
+ function TestEvent(evt)
+ {
+ ActualResult.push(evt.relatedNode);
+
+ if (ExpectResult.toString() == ActualResult.toString())
+ {
+ PassTest();
+ }
+
+ if (2 < ActualResult.length)
+ {
+ FailTest();
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <h3>DOM Events</h3>
+ <h4>
+ Test Description: MutationEvent.relatedNode is the parent node of the node being removed for DOMNodeRemoved event;
+ and, it is the parent node of the node that has been inserted for DOMNodeInserted event
+ </h4>
+
+ <span id="parent">
+ <div id="target" style="border:solid 1px green; width:200px; height:50px">
+ </div>
+ </span>
+ <p>Test passes if the word "PASS" appears below.</p>
+ <div>Test result: </div>
+ <div id='testresult'>FAIL</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/ProcessingInstruction.DOMCharacterDataModified.fail.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/ProcessingInstruction.DOMCharacterDataModified.fail.html
new file mode 100644
index 00000000000..9b0843c115e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/ProcessingInstruction.DOMCharacterDataModified.fail.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title id='desc'> ProcessingInstruction.data and DOMCharacterDataModified event </title>
+ </head>
+ <body>
+ <h3>DOM Events</h3>
+ <h4>
+ Test Description: DOMCharacterDataModified event fires after ProcessingInstruction.data have been modified,
+ but the node itself has not been inserted or deleted. The proximal event target of this event shall be the
+ ProcessingInstruction node.
+ </h4>
+
+ <p>Test passes if the word "PASS" appears below.</p>
+ <div>Test result: </div>
+ <div id='testresult'>FAIL</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/ProcessingInstruction.DOMCharacterDataModified.xml b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/ProcessingInstruction.DOMCharacterDataModified.xml
new file mode 100644
index 00000000000..0e3912ea7ef
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/ProcessingInstruction.DOMCharacterDataModified.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0"?>
+<root>
+ <head xmlns="http://www.w3.org/1999/xhtml">
+ <title> ProcessingInstruction.data and DOMCharacterDataModified event </title>
+ </head>
+
+ <p xmlns="http://www.w3.org/1999/xhtml">
+ <h3>DOM Events</h3>
+ <h4>
+ Test Description: DOMCharacterDataModified event fires after ProcessingInstruction.data have been modified,
+ but the node itself has not been inserted or deleted. The proximal event target of this event shall be the
+ ProcessingInstruction node.
+ </h4>
+
+ <pi><?foo bar?></pi>
+
+ <p>Test passes if the word "PASS" appears below.</p>
+ <div>Test result: </div>
+ <div><testresult>FAIL</testresult></div>
+
+ <script type="text/javascript" xmlns="http://www.w3.org/1999/xhtml">
+ <![CDATA[
+ var PassTest = function()
+ {
+ document.getElementsByTagName("testresult")[0].firstChild.data = "PASS";
+ TestResult = true;
+ }
+
+ var FailTest = function()
+ {
+ document.getElementsByTagName("testresult")[0].firstChild.data = "FAIL";
+ TestResult = false;
+ }
+
+ var EVENT = "DOMCharacterDataModified";
+ var TARGET = document.getElementsByTagName('pi')[0].firstChild;
+ var TestResult = false;
+
+ try
+ {
+ TARGET.addEventListener(EVENT, TestEvent, false);
+ TARGET.data = "new" + TARGET.data;
+ }
+ catch(ex)
+ {
+ FailTest();
+ }
+
+ function TestEvent(evt)
+ {
+ if ((EVENT == evt.type) && (TARGET == evt.target) && ("newbar" == evt.newValue))
+ {
+ PassTest();
+ }
+ else
+ {
+ FailTest();
+ }
+ }
+ ]]>
+ </script>
+ </p>
+</root> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/TextEvent.hasFeature.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/TextEvent.hasFeature.html
new file mode 100644
index 00000000000..853cc7c4357
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/TextEvent.hasFeature.html
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title id='desc'> TextEvent: feature detection with hasFeature() </title>
+ <script type="text/javascript">
+ var PassTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+
+ var FailTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+
+ window.onload = function()
+ {
+ try
+ {
+ var features = ["TextEvent", "Events.TextEvent", "Events.textInput"];
+ var versions = ["3.0", "", null];
+ var TestResult = true;
+ var HasFeature = false;
+
+ for (var i=0; i<features.length; i++)
+ {
+ for (var j=0; j<versions.length; j++)
+ {
+ HasFeature = document.implementation.hasFeature(features[i], versions[j]);
+ TestResult = HasFeature && TestResult;
+ }
+ }
+
+ if (HasFeature && TestResult)
+ {
+ PassTest();
+ }
+ else
+ {
+ FailTest();
+ }
+ }
+ catch(ex)
+ {
+ FailTest();
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <h3>DOM Events</h3>
+ <h4>
+ Test Description: TextEvent - feature support detection using DOMImplementation.hasFeature() method
+ </h4>
+
+ <p>Test passes if the word "PASS" appears below.</p>
+ <div>Test result: </div>
+ <div id='testresult'>FAIL</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/TextEvent.initTextEvent.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/TextEvent.initTextEvent.html
new file mode 100644
index 00000000000..52eae11aa9c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/TextEvent.initTextEvent.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title id='desc'> TextEvent.initTextEvent() and Event.trusted </title>
+ <script type="text/javascript">
+ var PassTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+
+ var FailTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+
+ var EVENT = "foo";
+ var TARGET;
+
+ window.onload = function()
+ {
+ try
+ {
+ TARGET = document.getElementById("target");
+ TARGET.addEventListener(EVENT, TestEvent, true);
+
+ var evt = document.createEvent("TextEvent");
+ evt.initTextEvent(EVENT, /* type */
+ true, /* bubbles */
+ true, /* cancelable */
+ window, /* view */
+ "domstr", /* data*/
+ 0 /* inputMode */ );
+ TARGET.dispatchEvent(evt);
+ }
+ catch(ex)
+ {
+ FailTest();
+ }
+
+ }
+
+ function TestEvent(evt)
+ {
+ if ((EVENT == evt.type) && (false == evt.trusted))
+ {
+ PassTest();
+ }
+ else
+ {
+ FailTest();
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <h3>DOM Events</h3>
+ <h4>
+ Test Description: initTextEvent initializes attributes of a TextEvent object.
+ </h4>
+
+ <input id="target" type="hidden" />
+ <p>Test passes if the word "PASS" appears below.</p>
+ <div>Test result: </div>
+ <div id='testresult'>FAIL</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/TextEvent.inputMode.IME.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/TextEvent.inputMode.IME.html
new file mode 100644
index 00000000000..af5c7362426
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/TextEvent.inputMode.IME.html
@@ -0,0 +1,69 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title id='desc'> TextEvent: inputMode with DOM_INPUT_METHOD_IME </title>
+ <script type="text/javascript">
+ var PassTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+
+ var FailTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+
+ var EVENT = "textInput";
+ var TARGET;
+
+ function TestEvent(evt)
+ {
+ TARGET.removeEventListener(EVENT, TestEvent, true);
+ if ((0x04 == evt.inputMode) && ("あ" == evt.data))
+ {
+ PassTest();
+ }
+ else
+ {
+ FailTest();
+ }
+ }
+
+ window.onload = function()
+ {
+ try
+ {
+ TARGET = document.getElementById("target");
+ TARGET.addEventListener(EVENT, TestEvent, true);
+ }
+ catch(ex)
+ {
+ FailTest();
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <h3>DOM Events</h3>
+ <h4>
+ Test Description: TextEvent.inputMode is DOM_INPUT_METHOD_IME (0x04)
+ when the text string was entered through an Input Method Editor.
+ </h4>
+
+ <span id="parent">
+ <input id="target" type="text" />
+ </span>
+
+ <p id="manualsteps">
+ Steps:
+ <ol>
+ <li> Open Japanese Microsoft IME and select Hiragana input method
+ <li> Click at the above textbox and then type 'a' using keyboard
+ <li> Press '{ENTER}' key to complete the IME composition
+ </ol>
+ </p>
+ <p>Test passes if the word "PASS" appears below after following the above steps.</p>
+ <div>Test result: </div>
+ <div id='testresult'>FAIL</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/TextEvent.inputMode.drop.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/TextEvent.inputMode.drop.html
new file mode 100644
index 00000000000..14ffc19765b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/TextEvent.inputMode.drop.html
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title id='desc'> TextEvent: inputMode with DOM_INPUT_METHOD_DROP </title>
+ <script type="text/javascript">
+ var PassTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+
+ var FailTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+
+ var EVENT = "textInput";
+ var TARGET;
+
+ function TestEvent(evt)
+ {
+ TARGET.removeEventListener(EVENT, TestEvent, true);
+
+ if ((0x03 == evt.inputMode) && ("Hello World" == evt.data))
+ {
+ PassTest();
+ }
+ else
+ {
+ FailTest();
+ }
+ }
+
+ window.onload = function()
+ {
+ try
+ {
+ TARGET = document.getElementById("target");
+ TARGET.addEventListener(EVENT, TestEvent, true);
+ }
+ catch(ex)
+ {
+ FailTest();
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <h3>DOM Events</h3>
+ <h4>
+ Test Description: TextEvent.inputMode is DOM_INPUT_METHOD_DROP (0x03)
+ when the text string was inserted as part of a drag-and-drop operation.
+ </h4>
+
+ <span id="parent">
+ <div contenteditable="true" style="border:solid 1px green; width:150px; height:20px">Hello World</div>
+ <br/>
+ <input id="target" type="text" />
+ </span>
+
+ <p id="manualsteps">
+ Steps:
+ <ol>
+ <li> Select "Hello World" inside the green editbox
+ <li> Drag-and-drop it ("Hello World") to the textbox below the green editbox
+ </ol>
+ </p>
+ <p>Test passes if the word "PASS" appears below after following the above steps.</p>
+ <div>Test result: </div>
+ <div id='testresult'>FAIL</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/TextEvent.inputMode.keyboard.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/TextEvent.inputMode.keyboard.html
new file mode 100644
index 00000000000..9d679d708e7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/TextEvent.inputMode.keyboard.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title id='desc'> TextEvent: inputMode with DOM_INPUT_METHOD_KEYBOARD </title>
+ <script type="text/javascript">
+ var PassTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+
+ var FailTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+
+ var EVENT = "textInput";
+ var TARGET;
+
+ function TestEvent(evt)
+ {
+ TARGET.removeEventListener(EVENT, TestEvent, true);
+
+ if ((0x01 == evt.inputMode) && ("a" == evt.data))
+ {
+ PassTest();
+ }
+ else
+ {
+ FailTest();
+ }
+ }
+
+ window.onload = function()
+ {
+ try
+ {
+ TARGET = document.getElementById("target");
+ TARGET.addEventListener(EVENT, TestEvent, true);
+ }
+ catch(ex)
+ {
+ FailTest();
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <h3>DOM Events</h3>
+ <h4>
+ Test Description: TextEvent.inputMode is DOM_INPUT_METHOD_KEYBOARD (0x01)
+ when the text string was input through a keyboard.
+ </h4>
+
+ <span id="parent">
+ <input id="target" type="text" />
+ </span>
+ <p id="manualsteps">
+ Steps:
+ <ol>
+ <li> Type 'a' in the above texbox using keyboard
+ </ol>
+ </p>
+ <p>Test passes if the word "PASS" appears below after following the above steps.</p>
+ <div>Test result: </div>
+ <div id='testresult'>FAIL</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/TextEvent.inputMode.paste.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/TextEvent.inputMode.paste.html
new file mode 100644
index 00000000000..a93259cd608
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/TextEvent.inputMode.paste.html
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title id='desc'> TextEvent: inputMode with DOM_INPUT_METHOD_PASTE </title>
+ <script type="text/javascript">
+ var PassTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+
+ var FailTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+
+ var EVENT = "textInput";
+ var TARGET;
+
+ function TestEvent(evt)
+ {
+ TARGET.removeEventListener(EVENT, TestEvent, true);
+
+ if ((0x02 == evt.inputMode) && ("Hello World" == evt.data))
+ {
+ PassTest();
+ }
+ else
+ {
+ FailTest();
+ }
+ }
+
+ window.onload = function()
+ {
+ try
+ {
+ TARGET = document.getElementById("target");
+ TARGET.addEventListener(EVENT, TestEvent, true);
+ }
+ catch(ex)
+ {
+ FailTest();
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <h3>DOM Events</h3>
+ <h4>
+ Test Description: TextEvent.inputMode is DOM_INPUT_METHOD_PASTE (0x02)
+ when the text string was pasted in from a clipboard.
+ </h4>
+
+ <span id="parent">
+ <div contenteditable="true" style="border:solid 1px green; width:150px; height:20px">Hello World</div>
+ <br/>
+ <input id="target" type="text" />
+ </span>
+
+ <p id="manualsteps">
+ Steps:
+ <ol>
+ <li> Select and copy "Hello World" inside the green editbox
+ <li> Paste it ("Hello World") to the textbox below the green editbox
+ </ol>
+ </p>
+ <p>Test passes if the word "PASS" appears below after following the above steps.</p>
+ <div>Test result: </div>
+ <div id='testresult'>FAIL</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/TextEvent.inputMode.script.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/TextEvent.inputMode.script.html
new file mode 100644
index 00000000000..c1327ebae57
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/TextEvent.inputMode.script.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title id='desc'> TextEvent: inputMode with DOM_INPUT_METHOD_SCRIPT </title>
+ <script type="text/javascript">
+ var PassTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+
+ var FailTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+
+ var EVENT = "textInput";
+ var TARGET;
+
+ function TestEvent(evt)
+ {
+ TARGET.removeEventListener(EVENT, TestEvent, true);
+
+ if ((0x09 == evt.inputMode) && ("Hello World" == evt.data))
+ {
+ PassTest();
+ }
+ else
+ {
+ FailTest();
+ }
+ }
+
+ window.onload = function()
+ {
+ try
+ {
+ TARGET = document.getElementById("target");
+ TARGET.addEventListener(EVENT, TestEvent, true);
+ TARGET.firstChild.data = "Hello World";
+ }
+ catch(ex)
+ {
+ FailTest();
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <h3>DOM Events</h3>
+ <h4>
+ Test Description: TextEvent.inputMode is DOM_INPUT_METHOD_SCRIPT (0x09)
+ when the text string was inserted via a script operation on the DOM.
+ </h4>
+
+ <span id="parent">
+ <div id="target" contenteditable="true" style="border:solid 1px green; width:200px; height:50px">
+ </div>
+ </span>
+ <p>Test passes if the word "PASS" appears below.</p>
+ <div>Test result: </div>
+ <div id='testresult'>FAIL</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/UIEvent.load.stylesheet.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/UIEvent.load.stylesheet.html
new file mode 100644
index 00000000000..a948a2f71a4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/UIEvent.load.stylesheet.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title id='desc'> UIEvent: load event for style sheets </title>
+ <script type="text/javascript">
+ var PassTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+
+ var FailTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+
+ function TestEvent(evt)
+ {
+ if ((evt.type == EVENT) && (evt.currentTarget == TARGET))
+ {
+ PassTest();
+ }
+ else
+ {
+ FailTest();
+ }
+ }
+
+ var EVENT = "load";
+ var TARGET;
+
+ window.onload = function()
+ {
+ try
+ {
+ TARGET = document.getElementById("target");
+ TARGET.addEventListener(EVENT, TestEvent, false);
+ TARGET.href = "./support/style01.css";
+ }
+ catch(ex)
+ {
+ FailTest();
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <h3>DOM Events</h3>
+ <h4>
+ Test Description: UIEvent - load event fires when the DOM Implementation finishes loading
+ dependent resources, such as style sheets.
+ </h4>
+
+ <LINK id="target" rel="stylesheet" />
+
+ <p>Test passes if the word "PASS" appears below.</p>
+ <div>Test result: </div>
+ <div id='testresult'>FAIL</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/WheelEvent.Capture.Bubble.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/WheelEvent.Capture.Bubble.html
new file mode 100644
index 00000000000..4dfe246136a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/WheelEvent.Capture.Bubble.html
@@ -0,0 +1,90 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title id='desc'> WheelEvent: wheel Event capturing/bubbling </title>
+ <script type="text/javascript">
+ var PassTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+
+ var FailTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+
+ function TestBubble(evt)
+ {
+ if (EVENT == evt.type)
+ {
+ ActualResult.push(evt.currentTarget);
+ }
+
+ if ((3 == evt.eventPhase) && (window === evt.currentTarget))
+ {
+ if (ExpectResult.toString() == ActualResult.toString())
+ {
+ PassTest();
+ }
+ else
+ {
+ FailTest();
+ }
+
+ for (var i=0; i < CURRENTTARGETS.length; i++)
+ {
+ CURRENTTARGETS[i].removeEventListener(EVENT, TestBubble, true);
+ CURRENTTARGETS[i].removeEventListener(EVENT, TestBubble, false);
+ }
+ }
+ }
+
+ var EVENT = "wheel";
+ var TARGET, PARENT, CURRENTTARGETS;
+ var ExpectResult = [];
+ var ActualResult = [];
+
+ window.onload = function()
+ {
+ try
+ {
+ TARGET = document.getElementById("target");
+ PARENT = document.getElementById("parent");
+ CURRENTTARGETS = [window, document, document.body, PARENT, TARGET];
+ ExpectResult = CURRENTTARGETS + "," + CURRENTTARGETS.reverse();
+
+ for (var i=0; i < CURRENTTARGETS.length; i++)
+ {
+ CURRENTTARGETS[i].addEventListener(EVENT, TestBubble, true);
+ CURRENTTARGETS[i].addEventListener(EVENT, TestBubble, false);
+ }
+ }
+ catch(ex)
+ {
+ FailTest();
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <h3>DOM Events</h3>
+ <h4>
+ Test Description: WheelEvent - wheel event bubbles.
+ </h4>
+
+ <span id="parent">
+ <textarea id="target" rows="5" cols="30">TOP TOP TOP TOP TOP TOP TOP Scroll mouse wheel over here Scroll mouse wheel over here Scroll mouse wheel over here Scroll mouse wheel over here Scroll mouse wheel over here END END END END END END END </textarea>
+ </span>
+ <p id="manualsteps">
+ Steps:
+ <ol>
+ <li> Note: an input device with scroll wheel support (e.g., mouse wheel) is required
+ <li> Move the mouse pointer over the above textarea
+ <li> Scroll down the mouse wheel 1 or more units
+ </ol>
+ </p>
+ <p>Test passes if the word "PASS" appears below after following the above steps.</p>
+ <div>Test result: </div>
+ <div id='testresult'>FAIL</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/WheelEvent.ctrlKey.zoom.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/WheelEvent.ctrlKey.zoom.html
new file mode 100644
index 00000000000..52b17ced96c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/WheelEvent.ctrlKey.zoom.html
@@ -0,0 +1,93 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title id='desc'> WheelEvent: wheel - MouseEvent.ctrlKey and Zooming </title>
+ <script type="text/javascript">
+ var PassTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+
+ var FailTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+
+ function DisableZooming()
+ {
+ BEFORE = HELPER.getBoundingClientRect().width;
+ DisableZoom = true;
+ }
+
+ function VerifyResult()
+ {
+ AFTER = HELPER.getBoundingClientRect().width;
+
+ if ((true == DisableZoom) && (true == TestResult) && (BEFORE == AFTER))
+ {
+ PassTest();
+ }
+ else
+ {
+ FailTest();
+ }
+ }
+
+ function TestEvent(evt)
+ {
+ if ((true == DisableZoom) && (true == evt.ctrlKey) && (EVENT == evt.type))
+ {
+ evt.preventDefault();
+ TestResult = evt.defaultPrevented;
+ }
+ }
+
+ var EVENT = "wheel";
+ var TARGET;
+ var HELPER;
+ var BEFORE;
+ var AFTER;
+ var DisableZoom = false;
+ var TestResult = false;
+
+ window.onload = function()
+ {
+ try
+ {
+ TARGET = document;
+ HELPER = document.getElementById("helper");
+ TARGET.addEventListener(EVENT, TestEvent, true);
+ }
+ catch(ex)
+ {
+ FailTest();
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <h3>DOM Events</h3>
+ <h4>
+ Test Description: The typical default action of the wheel event type, in some cases, is to
+ zoom the document. If this event is canceled, the implementation must not zoom the document.
+ </h4>
+
+ <div id="helper" style="width:100%"></div>
+
+ <p id="manualsteps">
+ Steps:
+ <ol>
+ <li> Note: an input device with scroll wheel support (e.g., mouse wheel) is required
+ <li> Make sure the page can be zoomed in/out by holding down '{CTRL}' key + scrolling the mouse wheel on the page
+ <li> Now, click the button: <button id="verify" onclick="DisableZooming()">Disable Zooming</button>
+ <li> Press and hold down '{CTRL}' key on the keyboard
+ <li> Move the mouse pointer to the center of the page
+ <li> Scroll down/up the mouse wheel some units
+ <li> Click the button: <button id="verify" onclick="VerifyResult()">VerifyResult</button>
+ </ol>
+ </p>
+ <p>Test passes if the word "PASS" appears below after following the above steps.</p>
+ <div>Test result: </div>
+ <div id='testresult'>FAIL</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/WheelEvent.deltaMode.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/WheelEvent.deltaMode.html
new file mode 100644
index 00000000000..11761f4083d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/WheelEvent.deltaMode.html
@@ -0,0 +1,76 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title id='desc'> WheelEvent: wheel - WheelEvent.deltaMode </title>
+ <script type="text/javascript">
+ var PassTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+
+ var FailTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+
+ var EVENT = "wheel";
+ var TARGET;
+
+ window.onload = function()
+ {
+ try
+ {
+ TARGET = document.getElementById("target");
+ TARGET.addEventListener(EVENT, TestEvent, true);
+ }
+ catch(ex)
+ {
+ FailTest();
+ }
+ }
+
+ function TestEvent(evt)
+ {
+ if ((0x00 == evt.deltaMode) || (0x01 == evt.deltaMode) || (0x02 == evt.deltaMode))
+ {
+ PassTest();
+ }
+ else
+ {
+ FailTest();
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <h3>DOM Events</h3>
+ <h4>
+ Test Description: WheelEvent.deltaMode attribute contains an indication of the units of
+ measurement for the delta values. Its value may be different based on system configuration.
+ </h4>
+
+ <span id="parent">
+ <div id="target" style="border:solid 1px green; width:220px; height:70px; overflow:scroll">
+ TOP TOP TOP TOP TOP TOP TOP
+ Scroll mouse wheel over here
+ Scroll mouse wheel over here
+ Scroll mouse wheel over here
+ Scroll mouse wheel over here
+ Scroll mouse wheel over here
+ Scroll mouse wheel over here
+ END END END END END END END
+ </div>
+ </span>
+ <p id="manualsteps">
+ Steps:
+ <ol>
+ <li> Note: an input device with scroll wheel support (e.g., mouse wheel) is required
+ <li> Move the mouse pointer over the above green box
+ <li> Scroll down the mouse wheel 1 or more units
+ </ol>
+ </p>
+ <p>Test passes if the word "PASS" appears below after following the above steps.</p>
+ <div>Test result: </div>
+ <div id='testresult'>FAIL</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/WheelEvent.hasFeature.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/WheelEvent.hasFeature.html
new file mode 100644
index 00000000000..8bd224fa98e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/WheelEvent.hasFeature.html
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title id='desc'> WheelEvent: feature detection with hasFeature() </title>
+ <script type="text/javascript">
+ var PassTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+
+ var FailTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+
+ window.onload = function()
+ {
+ try
+ {
+ var features = ["WheelEvent", "Events.WheelEvent", "Events.wheel"];
+ var versions = ["3.0", "", null];
+ var TestResult = true;
+ var HasFeature = false;
+
+ for (var i=0; i<features.length; i++)
+ {
+ for (var j=0; j<versions.length; j++)
+ {
+ HasFeature = document.implementation.hasFeature(features[i], versions[j]);
+ TestResult = HasFeature && TestResult;
+ }
+ }
+
+ if (HasFeature && TestResult)
+ {
+ PassTest();
+ }
+ else
+ {
+ FailTest();
+ }
+ }
+ catch(ex)
+ {
+ FailTest();
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <h3>DOM Events</h3>
+ <h4>
+ Test Description: WheelEvent - feature support detection using DOMImplementation.hasFeature() method
+ </h4>
+
+ <p>Test passes if the word "PASS" appears below.</p>
+ <div>Test result: </div>
+ <div id='testresult'>FAIL</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/WheelEvent.initWheelEvent.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/WheelEvent.initWheelEvent.html
new file mode 100644
index 00000000000..cd8c192e41b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/WheelEvent.initWheelEvent.html
@@ -0,0 +1,76 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title id='desc'> WheelEvent.initWheelEvent() and Event.trusted </title>
+ <script type="text/javascript">
+ var PassTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+
+ var FailTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+
+ var EVENT = "foo";
+ var TARGET;
+
+ window.onload = function()
+ {
+ try
+ {
+ TARGET = document.getElementById("target");
+ TARGET.addEventListener(EVENT, TestEvent, true);
+
+ var evt = document.createEvent("WheelEvent");
+ evt.initWheelEvent(EVENT, /* type */
+ true, /* bubbles */
+ true, /* cancelable */
+ window, /* view */
+ 0, /* detail */
+ 1, /* screenX */
+ 2, /* screenY */
+ 3, /* clientX */
+ 4, /* clientY */
+ 5, /* button */
+ null, /* relatedTarget */
+ "", /* modifiers */
+ 6, /* deltaX*/
+ 7, /* deltaY */
+ 8, /* deltaZ*/
+ 9 /* deltaMode */ );
+ TARGET.dispatchEvent(evt);
+ }
+ catch(ex)
+ {
+ FailTest();
+ }
+
+ }
+
+ function TestEvent(evt)
+ {
+ if ((EVENT == evt.type) && (false == evt.trusted))
+ {
+ PassTest();
+ }
+ else
+ {
+ FailTest();
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <h3>DOM Events</h3>
+ <h4>
+ Test Description: initWheelEvent initializes attributes of a WheelEvent object.
+ </h4>
+
+ <input id="target" type="hidden" />
+ <p>Test passes if the word "PASS" appears below.</p>
+ <div>Test result: </div>
+ <div id='testresult'>FAIL</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/WheelEvent.preventDefault.scroll.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/WheelEvent.preventDefault.scroll.html
new file mode 100644
index 00000000000..6cb55a071f3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/WheelEvent.preventDefault.scroll.html
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title id='desc'> WheelEvent: wheel - preventDefault() for Scrolling </title>
+ <script type="text/javascript">
+ var PassTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+
+ var FailTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+
+ function DisableScrolling()
+ {
+ TARGET.scrollTop = 0;
+ BEFORE = TARGET.scrollTop;
+ DisableScroll = true;
+ }
+
+ function VerifyResult()
+ {
+ AFTER = TARGET.scrollTop;
+
+ if ((true == DisableScroll) && (true == TestResult) && (BEFORE == AFTER))
+ {
+ PassTest();
+ }
+ else
+ {
+ FailTest();
+ }
+ }
+
+ function TestEvent(evt)
+ {
+ if ((true == DisableScroll) && (EVENT == evt.type))
+ {
+ evt.preventDefault();
+ TestResult = evt.defaultPrevented;
+ }
+ }
+
+ var EVENT = "wheel";
+ var BEFORE;
+ var AFTER;
+ var DisableScroll = false;
+ var TestResult = false;
+
+ window.onload = function()
+ {
+ try
+ {
+ TARGET = document.getElementById("target");
+ TARGET.addEventListener(EVENT, TestEvent, false);
+ }
+ catch(ex)
+ {
+ FailTest();
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <h3>DOM Events</h3>
+ <h4>
+ Test Description: The typical default action of the wheel event type is to scroll the document/element
+ by the indicated amount. If this event is canceled, the implementation must not scroll document/element.
+ </h4>
+
+ <span id="parent">
+ <textarea id="target" rows="5" cols="30">TOP TOP TOP TOP TOP TOP TOP Scroll mouse wheel over here Scroll mouse wheel over here Scroll mouse wheel over here Scroll mouse wheel over here Scroll mouse wheel over here END END END END END END END </textarea>
+ </span>
+ <p id="manualsteps">
+ Steps:
+ <ol>
+ <li> Note: an input device with scroll wheel support (e.g., mouse wheel) is required
+ <li> Make sure the above textarea can be scrolled by scrolling the mouse wheel over it
+ <li> Now, click the button: <button onclick="DisableScrolling()">Disable Scrolling</button>
+ <li> Move the mouse pointer over the above textarea
+ <li> Scroll down the mouse wheel 1 or more units
+ <li> Click the button: <button id="verify" onclick="VerifyResult()">VerifyResult</button>
+ </ol>
+ </p>
+ <p>Test passes if the word "PASS" appears below after following the above steps.</p>
+ <div>Test result: </div>
+ <div id='testresult'>FAIL</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/abort.img.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/abort.img.html
new file mode 100644
index 00000000000..5e403013e29
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/abort.img.html
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title> W3C DOM Level 3 Event: abort </title>
+ <script type="text/javascript">
+ var PassTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ window.localStorage.TestResult = "PASS";
+ }
+
+ var FailTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ window.localStorage.TestResult = "FAIL";
+ }
+
+ function TestCapture(evt)
+ {
+ if ((evt.currentTarget == TARGET) && (evt.type == EVENT))
+ {
+ PassTest();
+ }
+ else
+ {
+ FailTest();
+ }
+ }
+
+ function ReloadPage()
+ {
+ var LINK = document.getElementById("link");
+ LINK.href = "abort.img.html";
+ LINK.firstChild.data = "Click here to reload the page and test again.";
+ PARENT.firstChild.data = "Image loaded below. The above link should be clicked before image loads."
+ }
+ </script>
+ </head>
+ <body>
+ <h4>
+ Test Description:
+ The abort event fires when the loading of a resource has been aborted.
+ </h4>
+
+ <h3><a id="link" href="abort.testresult.html">Before image is loaded below, click here.</a></h3>
+
+ <div id="parent">Loading...<br></div>
+
+ <p>Test passes if the word "PASS" appears below.</p>
+ <div>Test result: </div>
+ <div id='testresult'>FAIL</div>
+
+ <script type="text/javascript">
+ try
+ {
+ window.localStorage.clear();
+
+ var EVENT = "abort";
+ var PARENT = document.getElementById("parent");
+ var TARGET = document.createElement("img");
+ TARGET.width = "400";
+ TARGET.height = "400";
+ TARGET.src = "./support/iepreview10mb.png?" + (new Date()).valueOf();
+ PARENT.appendChild(TARGET);
+ TARGET.onload = ReloadPage;
+ TARGET.addEventListener(EVENT, TestCapture, true);
+ }
+ catch(ex)
+ {
+ FailTest();
+ }
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/abort.testresult.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/abort.testresult.html
new file mode 100644
index 00000000000..b9c37576aa9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/abort.testresult.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+ <body>
+ <h4>
+ Test Description:
+ The abort event fires when the loading of a resource has been aborted.
+ </h4>
+
+ <h3><a id="link" href="abort.img.html">Click here to go back to the test page</a></h3>
+
+ <p>Test passes if the word "PASS" appears below.</p>
+ <div>Test result: </div>
+ <div id='testresult'>
+ <script>
+ try
+ {
+ var result = window.localStorage.getItem("TestResult");
+ }
+ catch(ex)
+ {
+ }
+ if ("PASS" != result)
+ {
+ result = "FAIL";
+ }
+ document.write(result);
+ </script>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/blur.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/blur.html
new file mode 100644
index 00000000000..0259fe6cb4b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/blur.html
@@ -0,0 +1,57 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title> W3C DOM Level 3 Event: blur </title>
+ <script type="text/javascript">
+ var PassTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+
+ var FailTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+
+ var EVENT = "blur";
+ var TARGET;
+
+ window.onload = function()
+ {
+ try
+ {
+ TARGET = document.getElementById("target");
+ TARGET.addEventListener(EVENT, TestCapture, true);
+ }
+ catch(ex)
+ {
+ FailTest();
+ }
+ }
+
+ function TestCapture(evt)
+ {
+ if ((evt.type == EVENT) && (evt.currentTarget == TARGET))
+ {
+ PassTest();
+ }
+ else
+ {
+ FailTest();
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <h4>Test Description: blur event fires when an event target loses focus.</h4>
+
+ <div id="parent">
+ Click the textbox and then the button: <br />
+ <input id="target" /> <button id="helper">Button</button>
+ </div>
+
+ <p>Test passes if the word "PASS" appears below after clicking the above textbox and then the button.</p>
+ <div>Test result: </div>
+ <div id='testresult'>FAIL</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/compositionstart.data.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/compositionstart.data.html
new file mode 100644
index 00000000000..177c37e8d76
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/compositionstart.data.html
@@ -0,0 +1,66 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title id='desc'> CompositionEvent.data for compositionstart Event </title>
+ <script type="text/javascript">
+ var PassTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+
+ var FailTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+
+ var EVENT = "compositionstart";
+ var TARGET;
+ var ExpectResult = [];
+ var ActualResult = [];
+
+ window.onload = function(e)
+ {
+ try
+ {
+ TARGET = document.getElementById("target");
+ TARGET.addEventListener(EVENT, TestEvent, true);
+ }
+ catch(ex)
+ {
+ FailTest();
+ }
+ }
+
+ function TestEvent(evt)
+ {
+ if ((evt.type == EVENT) && (evt.data == ""))
+ {
+ PassTest();
+ }
+ else
+ {
+ FailTest();
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <h3>DOM Events</h3>
+ <h4>
+ Test Description: The value of the data attribute of the compositionstart event
+ shall be null for new IME input.
+ </h4>
+
+ <pre>
+ <input id="target" value=""/>
+
+ Steps:
+ 1) Open Japanese Microsoft IME and select Hiragana input method
+ 2) Click at the above textbox and then type 'a' using keyboard
+ </pre>
+
+ <p>Test passes if the word "PASS" appears below after following the above steps.</p>
+ <div>Test result: </div>
+ <div id='testresult'>FAIL</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/compositionstart.keydown.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/compositionstart.keydown.html
new file mode 100644
index 00000000000..7316d1a8a30
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/compositionstart.keydown.html
@@ -0,0 +1,76 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title id='desc'> compositionstart Event and keydown Event </title>
+ <script type="text/javascript">
+ var PassTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+
+ var FailTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+
+ var TARGET;
+ var ExpectResult = ["keydown", "compositionstart", "keyup"];
+ var ActualResult = [];
+
+ window.onload = function(e)
+ {
+ try
+ {
+ TARGET = document.getElementById("target");
+ TARGET.addEventListener("compositionstart", TestEvent, true);
+ TARGET.addEventListener("keydown", TestEvent, true);
+ TARGET.addEventListener("keyup", TestEvent, true);
+ }
+ catch(ex)
+ {
+ FailTest();
+ }
+ }
+
+ function TestEvent(evt)
+ {
+ ActualResult.push(evt.type);
+
+ if (evt.type == "keyup")
+ {
+ if (ExpectResult.toString() == ActualResult.toString())
+ {
+ PassTest();
+ }
+ else
+ {
+ FailTest();
+ }
+ TARGET.removeEventListener("compositionstart", TestEvent, true);
+ TARGET.removeEventListener("keydown", TestEvent, true);
+ TARGET.removeEventListener("keyup", TestEvent, true);
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <h3>DOM Events</h3>
+ <h4>
+ Test Description: When a keyboard is used to feed an input method editor,
+ compositionstart event type is generated after a keydown event.
+ </h4>
+
+ <pre>
+ <input id="target" value=""/>
+
+ Steps:
+ 1) Open Japanese Microsoft IME and select Hiragana input method
+ 2) Type 'a' in the above textbox using keyboard
+ 3) <a href="compositionstart.keydown.html">Click here</a> to test again if not following the steps exactly
+ </pre>
+
+ <p>Test passes if the word "PASS" appears below after following the above steps.</p>
+ <div>Test result: </div>
+ <div id='testresult'>FAIL</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/compositionstart.preventDefault.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/compositionstart.preventDefault.html
new file mode 100644
index 00000000000..74fc52b5799
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/compositionstart.preventDefault.html
@@ -0,0 +1,73 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title id='desc'> Cancelling compositionstart Event via Event.preventDefault() </title>
+ <script type="text/javascript">
+ var PassTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+
+ var FailTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+
+ var EVENT = "compositionstart";
+ var TARGET;
+
+ window.onload = function(e)
+ {
+ try
+ {
+ TARGET = document.getElementById("target");
+ TARGET.addEventListener(EVENT, TestEvent, true);
+ TARGET.addEventListener("keyup", TestEvent, true);
+ }
+ catch(ex)
+ {
+ FailTest();
+ }
+ }
+
+ function TestEvent(evt)
+ {
+ if (evt.type == EVENT)
+ {
+ evt.preventDefault();
+ }
+
+ if (evt.type == "keyup")
+ {
+ if (TARGET.value == "")
+ {
+ PassTest();
+ }
+ else
+ {
+ FailTest();
+ }
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <h3>DOM Events</h3>
+ <h4>
+ Test Description: The default action of compositionstart event is to launch the appropriate text
+ composition system. If this event is canceled, the text composition system must not be launched.
+ </h4>
+
+ <pre>
+ <input id="target" value=""/>
+
+ Steps:
+ 1) Open Japanese Microsoft IME and select Hiragana input method
+ 2) Click at the above textbox and then type 'a' using keyboard
+ </pre>
+
+ <p>Test passes if the word "PASS" appears below and nothing is typed to the textbox after following the above steps.</p>
+ <div>Test result: </div>
+ <div id='testresult'>FAIL</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/converted/DOM.event.flow.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/converted/DOM.event.flow.html
new file mode 100644
index 00000000000..35355f766b0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/converted/DOM.event.flow.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title> Event dispatch and DOM event flow </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id=log></div>
+
+<table id="table" border="1" style="display: none">
+ <tbody id="table-body">
+ <tr id="table-row">
+ <td id="table-cell">Shady Grove</td>
+ <td>Aeolian</td>
+ </tr>
+ <tr id="parent">
+ <td id="target">Over the river, Charlie</td>
+ <td>Dorian</td>
+ </tr>
+ </tbody>
+</table>
+
+<script>
+ var EVENT = "foo";
+ var TARGET = document.getElementById("target");
+ var PARENT = document.getElementById("parent");
+ var TBODY = document.getElementById("table-body");
+ var TABLE = document.getElementById("table");
+ var BODY = document.body;
+ var HTML = document.documentElement;
+ var CurrentTargets = [window, document, HTML, BODY, TABLE, TBODY, PARENT, TARGET];
+ var ExpectResult = CurrentTargets.concat([TARGET, PARENT, TBODY, TABLE, BODY, HTML, document, window]);
+ var ActualResult = [];
+ var ExpectPhases = [1,1,1,1,1,1,1,2,2,3,3,3,3,3,3,3,];
+ var ActualPhases = [];
+
+ var description = "Test Description: Dispatch an event in a DOM tree using the DOM event flow.";
+
+ test(function()
+ {
+ for (var i=0; i < CurrentTargets.length; i++)
+ {
+ CurrentTargets[i].addEventListener(EVENT, TestEvent, true);
+ CurrentTargets[i].addEventListener(EVENT, TestEvent, false);
+ }
+
+ var evt = document.createEvent("Event");
+ evt.initEvent(EVENT, true, true);
+ TARGET.dispatchEvent(evt);
+
+ assert_array_equals(ActualResult, ExpectResult, "ActualResult");
+ assert_array_equals(ActualPhases, ExpectPhases, "ActualPhases");
+
+ }, description);
+
+ function TestEvent(evt)
+ {
+ ActualResult.push(evt.currentTarget);
+ ActualPhases.push(evt.eventPhase);
+ }
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/converted/EventListener.dispatch.new.event.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/converted/EventListener.dispatch.new.event.html
new file mode 100644
index 00000000000..e0ab7e0d3e4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/converted/EventListener.dispatch.new.event.html
@@ -0,0 +1,77 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title> Dispatch additional events inside an event listener </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id=log></div>
+
+<table id="table" border="1" style="display: none">
+ <tbody id="table-body">
+ <tr id="table-row">
+ <td id="table-cell">Shady Grove</td>
+ <td>Aeolian</td>
+ </tr>
+ <tr id="parent">
+ <td id="target">Over the river, Charlie</td>
+ <td>Dorian</td>
+ </tr>
+ </tbody>
+</table>
+
+<script>
+
+ var EVENT = "foo";
+ var TARGET = document.getElementById("target");
+ var PARENT = document.getElementById("parent");
+ var TBODY = document.getElementById("table-body");
+ var TABLE = document.getElementById("table");
+ var BODY = document.body;
+ var HTML = document.documentElement;
+ var CurrentTargets = [window, document, HTML, BODY, TABLE, TBODY, PARENT, TARGET];
+ var ExpectResult = [window, document, HTML, BODY, TABLE, TARGET, PARENT, TBODY,
+ TABLE, BODY, HTML, document, window, TBODY, PARENT, TARGET];
+ var ActualResult = [];
+ var ExpectTypes = "foo,foo,foo,foo,foo,bar,bar,bar,bar,bar,bar,bar,bar,foo,foo,foo,";
+ var ActualTypes = "";
+
+ var description = "Test Description: " +
+ "Implementations of the DOM event model must be reentrant. Event listeners may perform actions that " +
+ "cause additional events to be dispatched. Such events are handled in a synchronous manner, the event " +
+ "propagation that causes the event listener to be triggered must resume only after the event dispatch " +
+ "of the new event is completed.";
+
+ test(function()
+ {
+ for (var i=0; i < CurrentTargets.length; i++)
+ {
+ CurrentTargets[i].addEventListener(EVENT, TestEvent, true);
+ CurrentTargets[i].addEventListener("bar", TestEvent, false);
+ }
+
+ var evt = document.createEvent("Event");
+ evt.initEvent(EVENT, false, true);
+ TARGET.dispatchEvent(evt);
+
+ assert_array_equals(ActualResult, ExpectResult, "ActualResult");
+ assert_equals(ActualTypes, ExpectTypes, "ActualTypes");
+
+ }, description);
+
+ function TestEvent(evt)
+ {
+ ActualResult.push(evt.currentTarget);
+ ActualTypes += evt.type + ",";
+
+ if (TABLE == evt.currentTarget && EVENT == evt.type)
+ {
+ var e = document.createEvent("Event");
+ e.initEvent("bar", true, true);
+ TARGET.dispatchEvent(e);
+ }
+ }
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/converted/EventListener.eventHandler.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/converted/EventListener.eventHandler.html
new file mode 100644
index 00000000000..ed7e9aff280
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/converted/EventListener.eventHandler.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title> EventLister member: handleEvent() </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id=log></div>
+
+<table id="table" border="1" style="display: none">
+ <tbody id="table-body">
+ <tr id="table-row">
+ <td id="table-cell">Shady Grove</td>
+ <td>Aeolian</td>
+ </tr>
+ <tr id="parent">
+ <td id="target">Over the river, Charlie</td>
+ <td>Dorian</td>
+ </tr>
+ </tbody>
+</table>
+
+<script>
+
+ var EVENT = "foo";
+ var TARGET = document.getElementById("target");
+ var TestResult = false;
+
+ var description = "Test Description: " +
+ "handleEvent - This method shall be called whenever an event occurs of the event type for " +
+ "which the EventListener interface was registered.";
+
+ var EventListener = {};
+ EventListener.handleEvent = function(evt)
+ {
+ if ((EVENT == evt.type) && (TARGET == evt.target) && (this === EventListener))
+ {
+ TestResult = true;
+ }
+ else
+ {
+ TestResult = false;
+ }
+ }
+
+ test(function()
+ {
+ var evt = document.createEvent("Event");
+ evt.initEvent(EVENT, true, true);
+
+ TARGET.addEventListener(EVENT, EventListener, true);
+ TARGET.dispatchEvent(evt);
+ TARGET.removeEventListener(EVENT, EventListener, true);
+
+ assert_true(TestResult);
+
+ }, description);
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/converted/EventObject.after.dispatchEvent.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/converted/EventObject.after.dispatchEvent.html
new file mode 100644
index 00000000000..a2e44c9c8cf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/converted/EventObject.after.dispatchEvent.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title> Event.defaultPrevented is reset after dipatchEvent() </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id=log></div>
+
+<input id="target" type="hidden" value=""/>
+
+<script>
+
+ var EVENT = "foo";
+ var TARGET = document.getElementById("target");
+ var PreState;
+ var PosState;
+
+ var description = "Test Description: " +
+ "As the final step of the event dispatch, the implementation must reset the event " +
+ "object's default-action-prevention state. ";
+
+ test(function()
+ {
+ var evt = document.createEvent("Event");
+ evt.initEvent(EVENT, true, true);
+
+ TARGET.addEventListener(EVENT, TestEvent, true);
+ TARGET.dispatchEvent(evt);
+
+ PosState = evt.defaultPrevented;
+
+ assert_array_equals([evt.target, PreState, PosState], [TARGET, true, false]);
+
+ }, description);
+
+ function TestEvent(evt)
+ {
+ evt.preventDefault();
+ PreState = evt.defaultPrevented;
+ }
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/converted/EventObject.multiple.dispatchEvent.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/converted/EventObject.multiple.dispatchEvent.html
new file mode 100644
index 00000000000..70b2fedbcf0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/converted/EventObject.multiple.dispatchEvent.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title> Multiple dispatchEvent() and stopPropagation() </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id=log></div>
+
+<div id="parent" style="display: none">
+ <input id="target" type="hidden" value=""/>
+</div>
+
+<script>
+
+ var EVENT = "foo";
+ var TARGET = document.getElementById("target");
+ var PARENT = document.getElementById("parent");
+ var ExpectResult = [TARGET, PARENT, PARENT, document, window];
+ var ActualResult = [];
+
+ var description = "Test Description: " +
+ "An event object may be properly dispatched multiple times while also allowing to prevent the event objects " +
+ "propagation prior to the event dispatch.";
+
+ test(function()
+ {
+ var evt = document.createEvent("Event");
+ evt.initEvent(EVENT, true, true);
+
+ TARGET.addEventListener(EVENT, TestEvent, false);
+ PARENT.addEventListener(EVENT, TestEvent, false);
+ document.addEventListener(EVENT, TestEvent, false);
+ window.addEventListener(EVENT, TestEvent, false);
+
+ TARGET.dispatchEvent(evt);
+ PARENT.dispatchEvent(evt);
+ document.dispatchEvent(evt);
+
+ assert_array_equals(ActualResult, ExpectResult);
+
+ }, description);
+
+ function TestEvent(evt)
+ {
+ ActualResult.push(evt.currentTarget);
+
+ if (PARENT == evt.currentTarget)
+ {
+ evt.stopPropagation();
+ }
+ }
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/converted/ProcessingInstruction.DOMCharacterDataModified.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/converted/ProcessingInstruction.DOMCharacterDataModified.html
new file mode 100644
index 00000000000..2d91abd496e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/converted/ProcessingInstruction.DOMCharacterDataModified.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title> ProcessingInstruction.data and DOMCharacterDataModified event </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id=log></div>
+
+<iframe id="helper" style="display: none"></iframe>
+
+<script>
+
+
+ var description = "Test Description: " +
+ "DOMCharacterDataModified event fires after ProcessingInstruction.data have been modified, " +
+ "but the node itself has not been inserted or deleted. The proximal event target of this " +
+ "event shall be the ProcessingInstruction node.";
+
+ var t = async_test(description);
+
+ var HELPER = document.getElementById("helper");
+
+ HELPER.onload = t.step_func(function()
+ {
+ assert_true(HELPER.contentWindow.TestResult);
+ t.done();
+ });
+
+ HELPER.src = "./support/ProcessingInstruction.DOMCharacterDataModified.xml";
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/converted/dispatchEvent.click.checkbox.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/converted/dispatchEvent.click.checkbox.html
new file mode 100644
index 00000000000..8cb548f84c6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/converted/dispatchEvent.click.checkbox.html
@@ -0,0 +1,80 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title> MouseEvent: Default action and synthetic click event </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id=log></div>
+
+<div style="display: none">
+ <input type="checkbox" id="target">
+ <button id="button"> Click Here </button>
+</div>
+
+<script>
+ setup({explicit_done:true});
+ var EVENT = "click";
+ var TARGET = document.getElementById("target");
+ var BUTTON = document.getElementById("button");
+ var state;
+
+ var description = "Test Description: " +
+ "MouseEvent: Default action is performed when a synthetic click event is dispatched on a checkbox element";
+
+ BUTTON.addEventListener(EVENT, TestEvent, true);
+ TARGET.addEventListener(EVENT, TestEvent, true);
+
+ window.onload = function()
+ {
+ state = TARGET.checked;
+ BUTTON.click();
+ }
+
+ function TestEvent(evt)
+ {
+ if (BUTTON == evt.target)
+ {
+ var e;
+ test(function()
+ {
+ BUTTON.removeEventListener(EVENT, TestEvent, true);
+
+ e = document.createEvent("MouseEvent");
+ e.initMouseEvent(EVENT, /* type */
+ false, /* bubbles */
+ true, /* cancelable */
+ window, /* view */
+ 1, /* detail */
+ 0, /* screenX */
+ 0, /* screenY */
+ 0, /* clientX */
+ 0, /* clientY */
+ false, /* ctrlKey */
+ false, /* altKey */
+ false, /* shiftKey */
+ false, /* metaKey */
+ 0, /* button */
+ null /* relatedTarget */);
+
+ assert_array_equals([TARGET.checked, e.type, e.bubbles], [state, EVENT, false]);
+
+ }, "Checkbox state is unchanged before the synthetic click event is dispatched");
+
+ TARGET.dispatchEvent(e);
+ }
+ else if (TARGET == evt.target)
+ {
+ test(function()
+ {
+ assert_array_equals([TARGET.checked, evt.type, evt.bubbles], [!state, EVENT, false]);
+
+ }, description);
+
+ done();
+ }
+ }
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/converted/domnodeinserted.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/converted/domnodeinserted.html
new file mode 100644
index 00000000000..e5064d8d46c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/converted/domnodeinserted.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>MutationEvent: DOMNodeInserted Event Type</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+
+<div id="target" style="display: none"></div>
+
+<script>
+var EVENT = "DOMNodeInserted";
+var TARGET;
+var NODE;
+
+var t = async_test("Test Description: DOMNodeInserted event fires when a node has been added as a child of another node.");
+
+TARGET = document.getElementById("target");
+
+TARGET.addEventListener(EVENT, t.step_func(function(evt)
+{
+ assert_equals(evt.type, EVENT);
+ t.done();
+}), true);
+
+NODE = document.createElement("INPUT");
+TARGET.appendChild(NODE);
+</script>
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/converted/stopImmediatePropagation.effect.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/converted/stopImmediatePropagation.effect.html
new file mode 100644
index 00000000000..f00c749f873
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/converted/stopImmediatePropagation.effect.html
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title> Event.stopImmediatePropagation() immediate effect </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id=log></div>
+
+<table id="table" border="1" style="display: none">
+ <tbody id="table-body">
+ <tr id="table-row">
+ <td id="table-cell">Shady Grove</td>
+ <td>Aeolian</td>
+ </tr>
+ <tr id="parent">
+ <td id="target">Over the river, Charlie</td>
+ <td>Dorian</td>
+ </tr>
+ </tbody>
+</table>
+
+<script>
+
+ var EVENT = "foo";
+ var TARGET = document.getElementById("target");
+ var PARENT = document.getElementById("parent");
+ var TBODY = document.getElementById("table-body");
+ var TABLE = document.getElementById("table");
+ var BODY = document.body;
+ var HTML = document.documentElement;
+ var CurrentTargets = [window, document, HTML, BODY, TABLE, TBODY, PARENT, TARGET];
+ var ExpectResult = [window, window, document, document, HTML, HTML, BODY, BODY, TABLE];
+ var ActualResult = [];
+ var ExpectListeners = [0,1,0,1,0,1,0,1,0];
+ var ActualListeners = [];
+
+ var description = "Test Description: " +
+ "stopImmediatePropagation() prevents other event listeners from being triggered and, unlike " +
+ "Event.stopPropagation(), its effect must be immediate. Once it has been called, further calls " +
+ "to this method have no additional effect.";
+
+ test(function()
+ {
+ for (var i=0; i < CurrentTargets.length; i++)
+ {
+ CurrentTargets[i].addEventListener(EVENT, function(e){TestEvent(e, 0)}, true);
+ CurrentTargets[i].addEventListener(EVENT, function(e){TestEvent(e, 1)}, true);
+ }
+
+ var evt = document.createEvent("Event");
+ evt.initEvent(EVENT, true, true);
+ TARGET.dispatchEvent(evt);
+
+ assert_array_equals(ActualResult, ExpectResult, "ActualResult");
+ assert_array_equals(ActualListeners, ExpectListeners, "ActualListeners");
+
+ }, description);
+
+ function TestEvent(evt, i)
+ {
+ ActualResult.push(evt.currentTarget);
+ ActualListeners.push(i);
+ if ((1 == evt.eventPhase) && (TABLE == evt.currentTarget) && (0 == i))
+ {
+ evt.stopImmediatePropagation();
+ }
+ }
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/converted/stopPropagation.deferred.effect.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/converted/stopPropagation.deferred.effect.html
new file mode 100644
index 00000000000..8238fa7d962
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/converted/stopPropagation.deferred.effect.html
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title> Event.stopPropagation() deferred effect </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id=log></div>
+
+<table id="table" border="1" style="display: none">
+ <tbody id="table-body">
+ <tr id="table-row">
+ <td id="table-cell">Shady Grove</td>
+ <td>Aeolian</td>
+ </tr>
+ <tr id="parent">
+ <td id="target">Over the river, Charlie</td>
+ <td>Dorian</td>
+ </tr>
+ </tbody>
+</table>
+
+<script>
+
+ var EVENT = "foo";
+ var TARGET = document.getElementById("target");
+ var PARENT = document.getElementById("parent");
+ var TBODY = document.getElementById("table-body");
+ var TABLE = document.getElementById("table");
+ var BODY = document.body;
+ var HTML = document.documentElement;
+ var CurrentTargets = [window, document, HTML, BODY, TABLE, TBODY, PARENT, TARGET];
+ var ExpectResult = [window, window, document, document, HTML, HTML, BODY, BODY, TABLE, TABLE];
+ var ActualResult = [];
+ var ExpectListeners = [0,1,0,1,0,1,0,1,0,1];
+ var ActualListeners = [];
+
+ var description = "Test Description: " +
+ "stopPropagation() prevents other event listeners from being triggered but its effect must be " +
+ "deferred until all event listeners attached on the Event.currentTarget have been triggered.";
+
+ test(function()
+ {
+ for (var i=0; i < CurrentTargets.length; i++)
+ {
+ CurrentTargets[i].addEventListener(EVENT, function(e){TestEvent(e, 0)}, true);
+ CurrentTargets[i].addEventListener(EVENT, function(e){TestEvent(e, 1)}, true);
+ }
+
+ var evt = document.createEvent("Event");
+ evt.initEvent(EVENT, true, true);
+ TARGET.dispatchEvent(evt);
+
+ assert_array_equals(ActualResult, ExpectResult, "ActualResult");
+ assert_array_equals(ActualListeners, ExpectListeners, "ActualListeners");
+
+ }, description);
+
+ function TestEvent(evt, i)
+ {
+ ActualResult.push(evt.currentTarget);
+ ActualListeners.push(i);
+ if ((1 == evt.eventPhase) && (TABLE == evt.currentTarget) && (0 == i))
+ {
+ evt.stopPropagation();
+ }
+ }
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/converted/stopPropagation.dispatchEvent.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/converted/stopPropagation.dispatchEvent.html
new file mode 100644
index 00000000000..70ff9706290
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/converted/stopPropagation.dispatchEvent.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title> Calling stopPropagation() prior to dispatchEvent() </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id=log></div>
+
+<table id="table" border="1" style="display: none">
+ <tbody id="table-body">
+ <tr id="table-row">
+ <td id="table-cell">Shady Grove</td>
+ <td>Aeolian</td>
+ </tr>
+ <tr id="parent">
+ <td id="target">Over the river, Charlie</td>
+ <td>Dorian</td>
+ </tr>
+ </tbody>
+</table>
+
+<script>
+
+ var EVENT = "foo";
+ var TARGET = document.getElementById("target");
+ var PARENT = document.getElementById("parent");
+ var TBODY = document.getElementById("table-body");
+ var TABLE = document.getElementById("table");
+ var BODY = document.body;
+ var HTML = document.documentElement;
+ var CurrentTargets = [window, document, HTML, BODY, TABLE, TBODY, PARENT, TARGET];
+ var ExpectResult = [];
+ var ActualResult = [];
+ var ExpectPhases = [];
+ var ActualPhases = [];
+
+ var description = "Test Description: " +
+ "If Event.stopPropagation() has been called prior to the dispatch, all phases must be skipped.";
+ test(function()
+ {
+ for (var i=0; i < CurrentTargets.length; i++)
+ {
+ CurrentTargets[i].addEventListener(EVENT, TestEvent, true);
+ CurrentTargets[i].addEventListener(EVENT, TestEvent, false);
+ }
+
+ var evt = document.createEvent("Event");
+ evt.initEvent(EVENT, true, true);
+ evt.stopPropagation();
+ TARGET.dispatchEvent(evt);
+
+ assert_array_equals(ActualResult, ExpectResult, "ActualResult");
+ assert_array_equals(ActualPhases, ExpectPhases, "ActualPhases");
+
+ }, description);
+
+ function TestEvent(evt)
+ {
+ ActualResult.push(evt.currentTarget);
+ ActualPhases.push(evt.eventPhase);
+ }
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/converted/support/ProcessingInstruction.DOMCharacterDataModified.xml b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/converted/support/ProcessingInstruction.DOMCharacterDataModified.xml
new file mode 100644
index 00000000000..7c0091a8f91
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/converted/support/ProcessingInstruction.DOMCharacterDataModified.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0"?>
+<root>
+ <head xmlns="http://www.w3.org/1999/xhtml">
+ <title> ProcessingInstruction.data and DOMCharacterDataModified event </title>
+ </head>
+ <div id="log" xmlns="http://www.w3.org/1999/xhtml"></div>
+
+ <pi><?foo bar?></pi>
+
+ <script type="text/javascript" xmlns="http://www.w3.org/1999/xhtml">
+ <![CDATA[
+ var EVENT = "DOMCharacterDataModified";
+ var TARGET = document.getElementsByTagName('pi')[0].firstChild;
+ var TestResult = false;
+
+ TARGET.addEventListener(EVENT, TestEvent, false);
+ TARGET.data = "new" + TARGET.data;
+
+ function TestEvent(evt)
+ {
+ if ((EVENT == evt.type) && (TARGET == evt.target) && ("newbar" == evt.newValue))
+ {
+ TestResult = true;
+ }
+ else
+ {
+ TestResult = false;
+ }
+ }
+ ]]>
+ </script>
+</root> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/customevent.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/customevent.html
new file mode 100644
index 00000000000..a11ca15570e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/customevent.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>W3C DOM L3 Event: CustomEvent</title>
+ <script type="text/javascript">
+ var PassTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+
+ var FailTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+
+ var EVENT = "foo";
+ var TARGET;
+
+ window.onload = function()
+ {
+ try
+ {
+ TARGET = document.getElementById("target");
+ TARGET.addEventListener(EVENT, TestCapture, true);
+
+ var fooEvent = document.createEvent("CustomEvent");
+ fooEvent.initEvent(EVENT, true, true);
+ TARGET.dispatchEvent(fooEvent);
+ }
+ catch(ex)
+ {
+ FailTest();
+ }
+ }
+
+ function TestCapture(evt)
+ {
+ if ((evt.type == EVENT))
+ {
+ PassTest();
+ }
+ else
+ {
+ FailTest();
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <h4>
+ Test Description:
+ Create and fire CustomEvent using methods: createEvent, initEvent, dispatchEvent.
+ </h4>
+
+ <input type="hidden" id="target" />
+
+ <p>Test passes if the word "PASS" appears below.</p>
+ <div>Test result: </div>
+ <div id='testresult'>FAIL</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/dispatchEvent.UNSPECIFIED_EVENT_TYPE_ERR.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/dispatchEvent.UNSPECIFIED_EVENT_TYPE_ERR.html
new file mode 100644
index 00000000000..d239f06aa92
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/dispatchEvent.UNSPECIFIED_EVENT_TYPE_ERR.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title id='desc'> EventException.UNSPECIFIED_EVENT_TYPE_ERR and dispatchEvent() </title>
+ <script type="text/javascript">
+ var PassTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+
+ var FailTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+
+ window.onload = function()
+ {
+ try
+ {
+ var evt = document.createEvent("Event");
+ document.body.dispatchEvent(evt);
+ }
+ catch(ex)
+ {
+ if ((undefined != ex.code) && (ex instanceof EventException) && (EventException.UNSPECIFIED_EVENT_TYPE_ERR == ex.code))
+ {
+ PassTest();
+ }
+ else
+ {
+ FailTest();
+ }
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <h3>DOM Events</h3>
+ <h4>
+ Test Description: dispatchEvent - EventException UNSPECIFIED_EVENT_TYPE_ERR raises if the Event.type
+ was not specified by initializing the event before dispatchEvent was called.
+ </h4>
+
+ <p>Test passes if the word "PASS" appears below.</p>
+ <div>Test result: </div>
+ <div id='testresult'>FAIL</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/dispatchEvent.click.checkbox.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/dispatchEvent.click.checkbox.html
new file mode 100644
index 00000000000..757bb126460
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/dispatchEvent.click.checkbox.html
@@ -0,0 +1,93 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title id='desc'> MouseEvent: Default action and synthetic click event </title>
+ <script type="text/javascript">
+ var PassTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+
+ var FailTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+
+ var EVENT = "click";
+ var TARGET;
+ var HELPER;
+
+ function TestEvent(evt)
+ {
+ if (HELPER == evt.target)
+ {
+ HELPER.removeEventListener(EVENT, TestEvent, true);
+ var e = document.createEvent("MouseEvent");
+ e.initMouseEvent(EVENT, /* type */
+ false, /* bubbles */
+ true, /* cancelable */
+ window, /* view */
+ 1, /* detail */
+ 0, /* screenX */
+ 0, /* screenY */
+ 0, /* clientX */
+ 0, /* clientY */
+ false, /* ctrlKey */
+ false, /* altKey */
+ false, /* shiftKey */
+ false, /* metaKey */
+ 0, /* button */
+ null /* relatedTarget */ );
+
+ TARGET.dispatchEvent(e);
+ }
+ else if (TARGET == evt.target)
+ {
+ if ((true == TARGET.checked) && (false == evt.bubbles))
+ {
+ PassTest();
+ }
+ else
+ {
+ FailTest();
+ }
+ }
+ }
+
+ window.onload = function()
+ {
+ try
+ {
+ TARGET = document.getElementById("target");
+ HELPER = document.getElementById("helper");
+ TARGET.addEventListener(EVENT, TestEvent, true);
+ HELPER.addEventListener(EVENT, TestEvent, true);
+ }
+ catch(ex)
+ {
+ FailTest();
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <h3>DOM Events</h3>
+ <h4>
+ Test Description: MouseEvent: Default action is performed when a synthetic click event is dispatched on a checkbox element
+ </h4>
+
+ <input type="checkbox" id="target">
+ <button id="helper">Click Here</button>
+
+ <p id="manualsteps">
+ Steps:
+ <ol>
+ <li> Click the button "Click Here"
+ </ol>
+ </p>
+
+ <p>Test passes if the word "PASS" appears below after following the above steps.</p>
+ <div>Test result: </div>
+ <div id='testresult'>FAIL</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/error.image.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/error.image.html
new file mode 100644
index 00000000000..3f55ac9bb90
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/error.image.html
@@ -0,0 +1,65 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title> W3C DOM Level 3 Event: error </title>
+ <script type="text/javascript">
+ var PassTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+
+ var FailTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+
+ function TestCapture(evt)
+ {
+ TARGET = document.getElementById("target");
+
+ if ((evt.type == EVENT) && (evt.currentTarget == window) && (evt.target == TARGET))
+ {
+ TestResult = true;
+ }
+ else
+ {
+ TestResult = false;
+ }
+ }
+
+ var EVENT = "error";
+ var TARGET;
+ var TestResult = false;
+
+ try
+ {
+ window.addEventListener(EVENT, TestCapture, true);
+ }
+ catch(ex)
+ {
+ TestResult = false;
+ }
+
+ window.onload = function()
+ {
+ if (true == TestResult)
+ {
+ PassTest();
+ }
+ else
+ {
+ FailTest();
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <h4>Test Description: error event fires when an IMG resource failed to load.</h4>
+
+ <img id="target" src="./support/InvalidBitMap.png" alt="ERROR">
+
+ <p>Test passes if the word "PASS" appears below.</p>
+ <div>Test result: </div>
+ <div id='testresult'>FAIL</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/focusin.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/focusin.html
new file mode 100644
index 00000000000..9c89bfafea6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/focusin.html
@@ -0,0 +1,61 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title> W3C DOM Level 3 Event: focusin </title>
+ <script type="text/javascript">
+ var PassTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+
+ var FailTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+
+ var EVENT = "focusin";
+ var TARGET, PARENT;
+
+ window.onload = function()
+ {
+ try
+ {
+ TARGET = document.getElementById("target");
+ PARENT = document.getElementById("parent");
+
+ PARENT.addEventListener(EVENT, TestBubble, false);
+ }
+ catch(ex)
+ {
+ FailTest();
+ }
+ }
+
+ function TestBubble(evt)
+ {
+ if ((evt.type == EVENT) && (evt.currentTarget == PARENT) && (evt.target == TARGET))
+ {
+ PassTest();
+ }
+ else
+ {
+ FailTest();
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <h4>
+ Test Description:
+ focusin event fires when an event target is about to receive focus.
+ </h4>
+
+ <div id="parent">
+ Click here: <input id="target" />
+ </div>
+
+ <p>Test passes if the word "PASS" appears below after clicking the above textbox using mouse.</p>
+ <div>Test result: </div>
+ <div id='testresult'>FAIL</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/focusin.relatedTarget.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/focusin.relatedTarget.html
new file mode 100644
index 00000000000..a36d254666d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/focusin.relatedTarget.html
@@ -0,0 +1,64 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title id='desc'> FocusEvent.relatedTarget for focusin Event </title>
+ <script type="text/javascript">
+ var PassTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+
+ var FailTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+
+ var EVENT = "focusin";
+ var TARGET, HELPER;
+
+ window.onload = function(e)
+ {
+ try
+ {
+ TARGET = document.getElementById("target");
+ HELPER = document.getElementById("helper");
+ TARGET.addEventListener(EVENT, TestEvent, true);
+ }
+ catch(ex)
+ {
+ FailTest();
+ }
+ }
+
+ function TestEvent(evt)
+ {
+ if ((evt.target == TARGET) && (evt.relatedTarget == HELPER))
+ {
+ PassTest();
+ }
+ else
+ {
+ FailTest();
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <h3>DOM Events</h3>
+ <h4>
+ Test Description: FocusEvent.relatedTarget for focusin event is the event target losing focus.
+ </h4>
+
+ <pre>
+ <input id="helper" value="" /> <button id="target">BUTTON</button>
+
+ Steps:
+ 1) Click in the above textbox using mouse
+ 2) Then click the above button using mouse
+ </pre>
+
+ <p>Test passes if the word "PASS" appears below after following the above steps.</p>
+ <div>Test result: </div>
+ <div id='testresult'>FAIL</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/focusout.relatedTarget.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/focusout.relatedTarget.html
new file mode 100644
index 00000000000..bc02267ed7a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/focusout.relatedTarget.html
@@ -0,0 +1,64 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title id='desc'> FocusEvent.relatedTarget for focusout Event </title>
+ <script type="text/javascript">
+ var PassTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+
+ var FailTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+
+ var EVENT = "focusout";
+ var TARGET, HELPER;
+
+ window.onload = function(e)
+ {
+ try
+ {
+ TARGET = document.getElementById("target");
+ HELPER = document.getElementById("helper");
+ TARGET.addEventListener("focusout", TestEvent, true);
+ }
+ catch(ex)
+ {
+ FailTest();
+ }
+ }
+
+ function TestEvent(evt)
+ {
+ if (evt.type == EVENT && evt.relatedTarget == HELPER)
+ {
+ PassTest();
+ }
+ else
+ {
+ FailTest();
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <h3>DOM Events</h3>
+ <h4>
+ Test Description: FocusEvent.relatedTarget for focusout event is the event target receiving focus.
+ </h4>
+
+ <pre>
+ <input id="target" value="" /> <button id="helper">BUTTON</button>
+
+ Steps:
+ 1) Click in the above textbox using mouse
+ 2) Then click the above button using mouse
+ </pre>
+
+ <p>Test passes if the word "PASS" appears below after following the above steps.</p>
+ <div>Test result: </div>
+ <div id='testresult'>FAIL</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/hasFeature.Events.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/hasFeature.Events.html
new file mode 100644
index 00000000000..e0c9ba18d82
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/hasFeature.Events.html
@@ -0,0 +1,52 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title id='desc'> DOMImplementation.hasFeature() with Events, 3.0 and 2.0</title>
+ <script type="text/javascript">
+ var PassTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+
+ var FailTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+
+ window.onload = function()
+ {
+ try
+ {
+ var SupportEvents3 = document.implementation.hasFeature("Events", "3.0");
+ SupportEvents3 = SupportEvents3 && document.implementation.hasFeature("Events", "");
+ var SupportEvents2 = document.implementation.hasFeature("Events", "2.0");
+
+ if (SupportEvents3 && SupportEvents2)
+ {
+ PassTest();
+ }
+ else
+ {
+ FailTest();
+ }
+ }
+ catch(ex)
+ {
+ FailTest();
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <h3>DOM Events</h3>
+ <h4>
+ Test Description: Since DOM Level 3 Events is built on top of DOM Level 2 Events, an
+ implementation that returns true for "Events" and "3.0" shall also return true for the
+ parameters "Events" and "2.0".
+ </h4>
+
+ <p>Test passes if the word "PASS" appears below.</p>
+ <div>Test result: </div>
+ <div id='testresult'>FAIL</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/hasFeature.feature.string.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/hasFeature.feature.string.html
new file mode 100644
index 00000000000..e96c39c8556
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/hasFeature.feature.string.html
@@ -0,0 +1,80 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title id='desc'> DOMImplementation.hasFeature() and Extended Feature String </title>
+ <script type="text/javascript">
+ var PassTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+
+ var FailTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+
+ var szFeatures = ["Event", "UIEvent","FocusEvent","MouseEvent","WheelEvent","TextEvent",
+ "KeyboardEvent","CompositionEvent","MutationEvent","CustomEvent"];
+
+ var ExpectResult = [];
+ var ActualResult = [];
+ var supported = false;
+
+ window.onload = function()
+ {
+ try
+ {
+ supported = document.implementation.hasFeature("Events", "3.0");
+
+ for (var i=0; i<szFeatures.length; i++)
+ {
+ var szFeature = szFeatures[i];
+
+ supported = document.implementation.hasFeature(szFeature, "3.0") && supported;
+ supported = document.implementation.hasFeature(szFeature, "") && supported;
+ if (!supported)
+ {
+ break;
+ }
+ }
+
+ for (var i=0; i<szFeatures.length; i++)
+ {
+ var szFeature = "Events." + szFeatures[i];
+
+ supported = document.implementation.hasFeature(szFeature, "3.0") && supported;
+ supported = document.implementation.hasFeature(szFeature, "") && supported;
+ if (!supported)
+ {
+ break;
+ }
+ }
+
+ if (supported)
+ {
+ PassTest();
+ }
+ else
+ {
+ FailTest();
+ }
+ }
+ catch(ex)
+ {
+ FailTest();
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <h3>DOM Events</h3>
+ <h4>
+ Test Description: each interface defined in DOM Level 3 Events has a feature string,
+ which may act as a base feature string or as an extended feature string.
+ </h4>
+
+ <p>Test passes if the word "PASS" appears below.</p>
+ <div>Test result: </div>
+ <div id='testresult'>FAIL</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/load.image.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/load.image.html
new file mode 100644
index 00000000000..1cff3183090
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/load.image.html
@@ -0,0 +1,82 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title> W3C DOM Level 3 Event: load </title>
+ <script type="text/javascript">
+ var PassTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+
+ var FailTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+
+ function TestCapture(evt)
+ {
+ if (evt.target.tagName == "IMG")
+ {
+ TARGET = document.getElementById("target");
+
+ if ((evt.type == EVENT) && (evt.currentTarget == document) && (evt.target == TARGET))
+ {
+ TestResult = true;
+ }
+ else
+ {
+ TestResult = false;
+ }
+ }
+ }
+
+ var EVENT = "load";
+ var TARGET;
+ var TestResult = false;
+
+ try
+ {
+ document.addEventListener(EVENT, TestCapture, true);
+ }
+ catch(ex)
+ {
+ TestResult = false;
+ }
+
+ window.onload = function()
+ {
+ if (true == TestResult)
+ {
+ PassTest();
+ }
+ else
+ {
+ FailTest();
+ }
+ }
+
+ function ReloadPage()
+ {
+ var LINK = document.getElementById("link");
+ LINK.href = "load.image.html";
+ LINK.appendChild(document.createTextNode("Image loading error. Click here to test again."));
+ }
+ </script>
+ </head>
+ <body>
+ <h4>
+ Test Description:
+ load event fires when the DOM implementation finishes loading the resource (such as the document)
+ and any dependent resources (such as images, style sheets, or scripts).
+ </h4>
+
+ <p><a id="link" href=""></a></p>
+
+ <img id="target" src="./support/iepreview.png" width="300" height="300" onerror="ReloadPage()">
+
+ <p>Test passes if the word "PASS" appears below after the above image is loaded.</p>
+ <div>Test result: </div>
+ <div id='testresult'>FAIL</div>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/mouseenter.ctrlKey.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/mouseenter.ctrlKey.html
new file mode 100644
index 00000000000..dac16046cf9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/mouseenter.ctrlKey.html
@@ -0,0 +1,64 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title id='desc'> MouseEvent.ctrlKey for mouseenter Event </title>
+ <script type="text/javascript">
+ var PassTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+
+ var FailTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+
+ var EVENT = "mouseenter";
+ var TARGET;
+
+ window.onload = function(e)
+ {
+ try
+ {
+ TARGET = document.getElementById("target");
+ TARGET.addEventListener(EVENT, TestEvent, true);
+ }
+ catch(ex)
+ {
+ FailTest();
+ }
+ }
+
+ function TestEvent(evt)
+ {
+ if ((evt.type == EVENT) && (evt.ctrlKey == true))
+ {
+ TARGET.style.border = "solid 1px green";
+ PassTest();
+ }
+ else
+ {
+ FailTest();
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <h3>DOM Events</h3>
+ <h4>
+ Test Description: MouseEvent.ctrlKey returns true if 'Control' key is depressed, otherwise false.
+ </h4>
+
+ <pre>
+ <img id="target" src="./support/iepreview.png" width="256" height="256" style="border:solid 1px red" />
+
+ Steps:
+ 1) Press and hold down the '{CTRL}' key
+ 2) Move the mouse pointer into the image
+ </pre>
+
+ <p>Test passes if the word "PASS" appears below after following the above steps.</p>
+ <div>Test result: </div>
+ <div id='testresult'>FAIL</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/mouseenter.relatedTarget.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/mouseenter.relatedTarget.html
new file mode 100644
index 00000000000..f2d449dae85
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/mouseenter.relatedTarget.html
@@ -0,0 +1,69 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title id='desc'> MouseEvent.relatedTarget for mouseenter Event </title>
+ <script type="text/javascript">
+ var PassTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+
+ var FailTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+
+ var EVENT = "mouseenter";
+ var TARGET, PARENT;
+
+ window.onload = function(e)
+ {
+ try
+ {
+ TARGET = document.getElementById("target");
+ PARENT = document.getElementById("parent");
+ TARGET.addEventListener(EVENT, TestEvent, true);
+ }
+ catch(ex)
+ {
+ FailTest();
+ }
+ }
+
+ function TestEvent(evt)
+ {
+ if (evt.type == EVENT && evt.relatedTarget == PARENT)
+ {
+ PassTest();
+ }
+ else
+ {
+ FailTest();
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <h3>DOM Events</h3>
+ <h4>
+ Test Description: MouseEvent.relatedTarget for mouseenter event indicates
+ the event target a pointing device is exiting, if any.
+ </h4>
+
+ <pre>
+ <div id="parent" style="border:solid 1px green; width:350px; height:100px;">
+
+ <button id="target">BUTTON</button>
+
+ </div>
+
+ Steps:
+ 1) Move the mouse pointer into the above green rectangle
+ 2) Then move the mouse pointer onto the button
+ </pre>
+
+ <p>Test passes if the word "PASS" appears below after following the above steps.</p>
+ <div>Test result: </div>
+ <div id='testresult'>FAIL</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/mouseleave.relatedTarget.html b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/mouseleave.relatedTarget.html
new file mode 100644
index 00000000000..37ca7197507
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/mouseleave.relatedTarget.html
@@ -0,0 +1,69 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title id='desc'> MouseEvent.relatedTarget for mouseleave Event </title>
+ <script type="text/javascript">
+ var PassTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+
+ var FailTest = function()
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+
+ var EVENT = "mouseleave";
+ var TARGET, PARENT;
+
+ window.onload = function(e)
+ {
+ try
+ {
+ TARGET = document.getElementById("target");
+ PARENT = document.getElementById("parent");
+ TARGET.addEventListener(EVENT, TestEvent, true);
+ }
+ catch(ex)
+ {
+ FailTest();
+ }
+ }
+
+ function TestEvent(evt)
+ {
+ if (evt.type == EVENT && evt.relatedTarget == PARENT)
+ {
+ PassTest();
+ }
+ else
+ {
+ FailTest();
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <h3>DOM Events</h3>
+ <h4>
+ Test Description: MouseEvent.relatedTarget for mouseleave event indicates
+ the event target a pointing device is entering, if any.
+ </h4>
+
+ <pre>
+ <div id="parent" style="border:solid 1px green; width:350px; height:100px;">
+
+ <button id="target">BUTTON</button>
+
+ </div>
+
+ Steps:
+ 1) Move the mouse pointer onto the above button
+ 2) Then move the mouse pointer out of it
+ </pre>
+
+ <p>Test passes if the word "PASS" appears below after following the above steps.</p>
+ <div>Test result: </div>
+ <div id='testresult'>FAIL</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/support/16kb.js b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/support/16kb.js
new file mode 100644
index 00000000000..bf362ea39bd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/support/16kb.js
@@ -0,0 +1,140 @@
+var text =
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " +
+"This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! This is a test! " ;
+ActualResult.push("SCRIPT:loaded");
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/support/InvalidBitMap.png b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/support/InvalidBitMap.png
new file mode 100644
index 00000000000..0a15a8e10d8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/support/InvalidBitMap.png
@@ -0,0 +1 @@
+Invalid BitMap \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/support/iepreview.png b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/support/iepreview.png
new file mode 100644
index 00000000000..63959a05626
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/support/iepreview.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/support/style01.css b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/support/style01.css
new file mode 100644
index 00000000000..205e5bd7f59
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/tests/submissions/Microsoft/support/style01.css
@@ -0,0 +1,3 @@
+BODY {
+ PADDING-BOTTOM: 0px; BACKGROUND-COLOR: #eef0eb; MARGIN: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; PADDING-TOP: 0px
+}
diff --git a/tests/wpt/web-platform-tests/DOMEvents/throwing-in-listener-and-window-error-event.html b/tests/wpt/web-platform-tests/DOMEvents/throwing-in-listener-and-window-error-event.html
new file mode 100644
index 00000000000..29841d9ac17
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/throwing-in-listener-and-window-error-event.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<meta charset="UTF-8">
+<title>Throwing in event listener generates an error event on the window object</title>
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+
+<script>
+ var t = async_test("Throwing in event listener generates an error event on the window object");
+
+ var errorEvent = false;
+
+ window.onerror = function(e) {
+ errorEvent = e;
+ }
+
+ document.addEventListener('DOMContentLoaded', t.step_func(function(){
+ var element = document.getElementById('bim');
+
+ element.addEventListener('click', function(){
+ throw new Error('Error from listener');
+ });
+
+ element.click();
+
+ assert_equals(typeof errorEvent, 'string');
+ t.done();
+ }));
+</script>
+
+<div id="bim">
+</div>
diff --git a/tests/wpt/web-platform-tests/DOMEvents/throwing-in-listener-when-all-have-not-run-yet.html b/tests/wpt/web-platform-tests/DOMEvents/throwing-in-listener-when-all-have-not-run-yet.html
new file mode 100644
index 00000000000..52196329bec
--- /dev/null
+++ b/tests/wpt/web-platform-tests/DOMEvents/throwing-in-listener-when-all-have-not-run-yet.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<meta charset="UTF-8">
+<title>Throwing in event listener</title>
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+
+<script>
+ setup({allow_uncaught_exception:true})
+ var t = async_test("Throwing in event listener");
+
+ document.addEventListener('DOMContentLoaded', t.step_func(function(){
+ var element = document.getElementById('bim');
+
+ var secondCalled = false;
+
+ element.addEventListener('click', function(){
+ throw new Error('Error from listener');
+ });
+ element.addEventListener('click', t.step_func(function(){ secondCalled = true; }), false);
+
+ element.click();
+
+ assert_true(secondCalled);
+ t.done();
+ }));
+</script>
+
+<div id="bim">
+</div>
diff --git a/tests/wpt/web-platform-tests/FileAPI/BlobURL/support/file_test1.js b/tests/wpt/web-platform-tests/FileAPI/BlobURL/support/file_test1.js
new file mode 100644
index 00000000000..34983584999
--- /dev/null
+++ b/tests/wpt/web-platform-tests/FileAPI/BlobURL/support/file_test1.js
@@ -0,0 +1 @@
+var test_result = 'test1_OK'; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/FileAPI/BlobURL/support/file_test2.txt b/tests/wpt/web-platform-tests/FileAPI/BlobURL/support/file_test2.txt
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/FileAPI/BlobURL/support/file_test2.txt
diff --git a/tests/wpt/web-platform-tests/FileAPI/BlobURL/support/file_test3.html b/tests/wpt/web-platform-tests/FileAPI/BlobURL/support/file_test3.html
new file mode 100644
index 00000000000..fa234cb9f99
--- /dev/null
+++ b/tests/wpt/web-platform-tests/FileAPI/BlobURL/support/file_test3.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test file</title>
+ <style>
+ body {
+ margin: 0;
+ }
+ .block {
+ height: 5000px;
+ }
+ </style>
+ <script>
+ window.test_result = 'test3_OK';
+ </script>
+</head>
+<body>
+ <a id="block1"></a>
+ <div class="block"></div>
+
+ <a id="block2"></a>
+ <div class="block"></div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/FileAPI/BlobURL/test1-manual.html b/tests/wpt/web-platform-tests/FileAPI/BlobURL/test1-manual.html
new file mode 100644
index 00000000000..8da42cf647a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/FileAPI/BlobURL/test1-manual.html
@@ -0,0 +1,122 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Blob and File reference URL Test(1)</title>
+ <link rel=help href="http://dev.w3.org/2006/webapi/FileAPI/#convenienceAPI">
+ <link rel=author title="Breezewish" href="mailto:me@breeswish.org">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <form name="upload">
+ <input type="file" id="fileChooser">
+ </form>
+
+ <div>
+ <p>Test steps:</p>
+ <ol>
+ <li>Download the <a href="support/file_test1.js">file</a>.</li>
+ <li>Select the file in the file inputbox to run the test.</li>
+ </ol>
+ </div>
+
+ <div id="log"></div>
+
+ <script>
+
+ var fileChooser = document.querySelector('#fileChooser');
+
+ setup({explicit_done: true});
+ setup({explicit_timeout: true});
+
+ //Run the test when user selects a file
+
+ on_event(fileChooser, 'change', function() {
+
+ var testCount = 10000;
+
+ test(function() {
+
+ var list = [], file = fileChooser.files[0];
+
+ for (var i = 0; i <= testCount; i++) {
+ list.push(window.URL.createObjectURL(file));
+ }
+
+ list.sort();
+
+ for (var i = 0; i < testCount; i++) {
+ assert_not_equals(list[i], list[i+1], 'generated Blob URL should be unique');
+ }
+
+ }, 'Check whether generated Blob/File URL is unique (Notice: only generate for ' + testCount + ' times)');
+
+
+ async_test(function(t) {
+
+ var url = URL.createObjectURL(fileChooser.files[0]);
+ var expected_file_content = "var test_result = 'test1_OK';";
+
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', url, true);
+ xhr.onreadystatechange = t.step_func(function() {
+ switch (xhr.readyState) {
+ case xhr.DONE:
+ assert_equals(xhr.status, 200, 'status code should be 200');
+ assert_equals(xhr.responseText, expected_file_content);
+ t.done();
+ return;
+ }
+ });
+
+ xhr.send();
+
+ }, 'Check whether Blob/File URL could be used in XHR requests and could get expected data');
+
+ async_test(function(t) {
+
+ var url = URL.createObjectURL(fileChooser.files[0]);
+ var expected_run_result = "test1_OK";
+
+ //expected file content:
+ // var test_result = 'test1_OK';
+
+ var e = document.createElement('script');
+ e.setAttribute('type', 'text/javascript');
+ e.setAttribute('src', url);
+ e.onload = t.step_func_done(function() {
+ assert_equals(test_result, expected_run_result);
+ });
+
+ document.body.appendChild(e);
+
+ }, 'Check whether Blob/File URL could be used in tags src like <script>');
+
+ async_test(function(t) {
+
+ var url = URL.createObjectURL(fileChooser.files[0]);
+ URL.revokeObjectURL(url);
+
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', url, true);
+ xhr.onreadystatechange = t.step_func(function() {
+ switch (xhr.readyState) {
+ case xhr.DONE:
+ assert_equals(xhr.status, 500, 'status code should be 500 if Blob URI is revoked.');
+ t.done();
+ return;
+ }
+ });
+
+ xhr.send();
+
+ }, 'Check whether revokeObjectURL works well');
+
+ done();
+
+ });
+
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/FileAPI/BlobURL/test2-manual.html b/tests/wpt/web-platform-tests/FileAPI/BlobURL/test2-manual.html
new file mode 100644
index 00000000000..07fb27ef8af
--- /dev/null
+++ b/tests/wpt/web-platform-tests/FileAPI/BlobURL/test2-manual.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Blob and File reference URL Test(2)</title>
+ <link rel=help href="http://dev.w3.org/2006/webapi/FileAPI/#convenienceAPI">
+ <link rel=author title="Breezewish" href="mailto:me@breeswish.org">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <form name="upload">
+ <input type="file" id="fileChooser"><br><input type="button" id="start" value="start">
+ </form>
+
+ <div>
+ <p>Test steps:</p>
+ <ol>
+ <li>Download the <a href="support/file_test2.txt">file</a>.</li>
+ <li>Select the file in the file inputbox.</li>
+ <li>Delete the file.</li>
+ <li>Click the 'start' button.</li>
+ </ol>
+ </div>
+
+ <div id="log"></div>
+
+ <script>
+
+ var fileChooser = document.querySelector('#fileChooser');
+
+ setup({explicit_done: true});
+ setup({explicit_timeout: true});
+
+ on_event(document.querySelector('#start'), 'click', function() {
+
+ async_test(function(t) {
+
+ var url = URL.createObjectURL(fileChooser.files[0]);
+
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', url, true);
+ xhr.onreadystatechange = t.step_func(function() {
+ switch (xhr.readyState) {
+ case xhr.DONE:
+ assert_equals(xhr.status, 500, 'status code should be 500.');
+ t.done();
+ return;
+ }
+ });
+
+ xhr.send();
+
+ }, 'Check whether the browser response 500 in XHR if the selected file which File/Blob URL refered is not found');
+
+ done();
+
+ });
+
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/FileAPI/BlobURL/test3-manual.html b/tests/wpt/web-platform-tests/FileAPI/BlobURL/test3-manual.html
new file mode 100644
index 00000000000..ce020a7b74d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/FileAPI/BlobURL/test3-manual.html
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Blob and File reference URL Test(3)</title>
+ <link rel=help href="http://dev.w3.org/2006/webapi/FileAPI/#convenienceAPI">
+ <link rel=author title="Breezewish" href="mailto:me@breeswish.org">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <form name="upload">
+ <input type="file" id="fileChooser">
+ </form>
+
+ <div>
+ <p>Test steps:</p>
+ <ol>
+ <li>Download the <a href="support/file_test3.html">file</a>.</li>
+ <li>Select the file in the file inputbox and the test will start.</li>
+ </ol>
+ </div>
+
+ <div id="log"></div>
+
+ <script>
+
+ var fileChooser = document.querySelector('#fileChooser');
+
+ setup({explicit_done: true});
+ setup({explicit_timeout: true});
+
+ on_event(fileChooser, 'change', function() {
+
+ async_test(function(t) {
+
+ var url = URL.createObjectURL(fileChooser.files[0]);
+
+ var e = document.createElement('iframe');
+ e.setAttribute('src', url);
+ e.setAttribute('style', 'display:none;');
+ document.body.appendChild(e);
+
+ e.contentWindow.document.body.onload = t.step_func_done(function() {
+ assert_equals(e.contentWindow.test_result, 'test3_OK');
+ });
+
+ }, 'Check whether the iframe content could be accessed when using Blob/File URL in the same origin.');
+
+ async_test(function(t) {
+
+ var url = URL.createObjectURL(fileChooser.files[0]);
+ url += '#block2';
+
+ var e = document.createElement('iframe');
+ e.setAttribute('src', url);
+ document.body.appendChild(e);
+
+ e.contentWindow.document.body.onload = t.step_func_done(function() {
+ assert_equals(e.contentWindow.scrollY, 5000);
+ });
+
+ }, 'Check whether the Blob/File URL fragment is implemented.');
+
+ done();
+
+ });
+
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/FileAPI/FileReader/Progress_event_bubbles_cancelable.html b/tests/wpt/web-platform-tests/FileAPI/FileReader/Progress_event_bubbles_cancelable.html
new file mode 100644
index 00000000000..6a03243f934
--- /dev/null
+++ b/tests/wpt/web-platform-tests/FileAPI/FileReader/Progress_event_bubbles_cancelable.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>File API Test: Progress Event - bubbles, cancelable</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="http://www.w3.org/TR/FileAPI/#events">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+ async_test(function(){
+ var blob = new Blob(["TEST"]);
+ var reader = new FileReader();
+
+ reader.onloadstart = this.step_func(function(evt) {
+ assert_false(evt.bubbles, "The bubbles must be false when the event is dispatched");
+ assert_false(evt.cancelable, "The cancelable must be false when the event is dispatched");
+ });
+
+ reader.onload = this.step_func(function(evt) {
+ assert_false(evt.bubbles, "The bubbles must be false when the event is dispatched");
+ assert_false(evt.cancelable, "The cancelable must be false when the event is dispatched");
+ });
+
+ reader.onloadend = this.step_func(function(evt) {
+ assert_false(evt.bubbles, "The bubbles must be false when the event is dispatched");
+ assert_false(evt.cancelable, "The cancelable must be false when the event is dispatched");
+ this.done();
+ });
+
+ reader.readAsText(blob);
+ }, "Check the values of bubbles and cancelable are false when the progress event is dispatched");
+</script>
+
diff --git a/tests/wpt/web-platform-tests/FileAPI/FileReader/support/file_test1.txt b/tests/wpt/web-platform-tests/FileAPI/FileReader/support/file_test1.txt
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/FileAPI/FileReader/support/file_test1.txt
diff --git a/tests/wpt/web-platform-tests/FileAPI/FileReader/test_errors-manual.html b/tests/wpt/web-platform-tests/FileAPI/FileReader/test_errors-manual.html
new file mode 100644
index 00000000000..e0a61200145
--- /dev/null
+++ b/tests/wpt/web-platform-tests/FileAPI/FileReader/test_errors-manual.html
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>FileReader Errors Test</title>
+ <link rel=help href="http://dev.w3.org/2006/webapi/FileAPI/#convenienceAPI">
+ <link rel=author title="Breezewish" href="mailto:me@breeswish.org">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <form name="upload">
+ <input type="file" id="fileChooser"><br><input type="button" id="start" value="start">
+ </form>
+
+ <div>
+ <p>Test steps:</p>
+ <ol>
+ <li>Download the <a href="support/file_test1.txt">file</a>.</li>
+ <li>Select the file in the file inputbox.</li>
+ <li>Delete the file.</li>
+ <li>Click the 'start' button.</li>
+ </ol>
+ </div>
+
+ <div id="log"></div>
+
+ <script>
+
+ var fileChooser = document.querySelector('#fileChooser');
+
+ setup({explicit_done: true});
+ setup({explicit_timeout: true});
+
+ on_event(fileChooser, 'change', function() {
+
+ async_test(function(t) {
+
+ var reader = new FileReader();
+ reader.readAsArrayBuffer(fileChooser.files[0]);
+
+ reader.onloadend = t.step_func_done(function(event) {
+ assert_equals(event.target.readyState, FileReader.DONE);
+ assert_equals(reader.error, null);
+ });
+
+ }, 'FileReader.error should be null if there are no errors when reading');
+
+ });
+
+ on_event(document.querySelector('#start'), 'click', function() {
+
+ async_test(function(t) {
+
+ var reader = new FileReader();
+ reader.readAsArrayBuffer(fileChooser.files[0]);
+
+ reader.onloadend = t.step_func_done(function(event) {
+ assert_equals(event.target.readyState, FileReader.DONE);
+ assert_equals(reader.error.code, 8);
+ });
+
+ }, 'FileReader.error should be NOT_FOUND_ERR if the file is not found when reading');
+
+ done();
+
+ });
+
+ </script>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/FileAPI/FileReaderSync.worker.js b/tests/wpt/web-platform-tests/FileAPI/FileReaderSync.worker.js
new file mode 100644
index 00000000000..77af6a7a6a2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/FileAPI/FileReaderSync.worker.js
@@ -0,0 +1,28 @@
+importScripts("/resources/testharness.js");
+
+var blob, readerSync;
+setup(function() {
+ readerSync = new FileReaderSync();
+ blob = new Blob(["test"]);
+});
+
+test(function() {
+ assert_true(readerSync instanceof FileReaderSync);
+}, "Interface");
+
+test(function() {
+ var text = readerSync.readAsText(blob);
+ assert_equals(text, "test");
+}, "readAsText");
+
+test(function() {
+ var data = readerSync.readAsDataURL(blob);
+ assert_equals(data.indexOf("data:"), 0);
+}, "readAsDataURL");
+
+test(function() {
+ var data = readerSync.readAsArrayBuffer(blob);
+ assert_true(data instanceof ArrayBuffer);
+}, "readAsArrayBuffer");
+
+done();
diff --git a/tests/wpt/web-platform-tests/FileAPI/blob/Blob-XHR-revoke.html b/tests/wpt/web-platform-tests/FileAPI/blob/Blob-XHR-revoke.html
new file mode 100644
index 00000000000..fea313eeee5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/FileAPI/blob/Blob-XHR-revoke.html
@@ -0,0 +1,28 @@
+<!doctype html>
+<title>Revoking blob URL used with XMLHttpRequest</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<script>
+async_test(function(t) {
+ var blob = new Blob(["test"]);
+ var url = URL.createObjectURL(blob);
+ var xhr = new XMLHttpRequest();
+ xhr.open("GET", url);
+
+ // Revoke the object URL. XHR should take a reference to the blob as soon as
+ // it receives it in open(), so the request succeeds even though we revoke the
+ // URL before calling send().
+ URL.revokeObjectURL(url);
+
+ xhr.send();
+
+ xhr.onload = t.step_func(function() {
+ assert_equals(xhr.response, "test");
+ t.done();
+ })
+ xhr.onerror = t.step_func(function() {
+ assert_unreached("Got unexpected error event");
+ })
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/FileAPI/blob/Blob-close.html b/tests/wpt/web-platform-tests/FileAPI/blob/Blob-close.html
new file mode 100644
index 00000000000..8ec8bcca0b6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/FileAPI/blob/Blob-close.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Blob.close</title>
+<link rel=help href="http://dev.w3.org/2006/webapi/FileAPI/#dfn-close">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../support/Blob.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ var blob = new Blob(["TEST"]);
+ var sliced = blob.slice();
+ blob.close();
+ test_blob(function() {
+ return blob;
+ }, {
+ expected: "",
+ type: "",
+ desc: "Blob should be empty."
+ });
+ test_blob(function() {
+ return sliced;
+ }, {
+ expected: "PASS",
+ type: "",
+ desc: "Slice should still have the data."
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/FileAPI/blob/Blob-constructor.html b/tests/wpt/web-platform-tests/FileAPI/blob/Blob-constructor.html
new file mode 100644
index 00000000000..5a5104328f3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/FileAPI/blob/Blob-constructor.html
@@ -0,0 +1,498 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Blob constructor</title>
+<link rel=help href="http://dev.w3.org/2006/webapi/FileAPI/#constructorBlob">
+<link rel=help href="https://heycam.github.io/webidl/#es-union">
+<link rel=help href="https://heycam.github.io/webidl/#es-dictionary">
+<link rel=help href="https://heycam.github.io/webidl/#es-sequence">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../support/Blob.js"></script>
+<p><strong><a href="https://www.w3.org/Bugs/Public/show_bug.cgi?id=23683">Discussion</a>
+is ongoing that will affect a number of the following tests.</strong>
+<div id="log"></div>
+<!-- used by "platform object that supports indexed properties" tests -->
+<iframe style="display:none"></iframe>
+<script>
+test(function() {
+ assert_true("Blob" in window, "window should have a Blob property.");
+ assert_equals(Blob.length, 2, "Blob.length should be 2.");
+ assert_true(Blob instanceof Function, "Blob should be a function.");
+}, "Blob interface object");
+
+// Step 1.
+test(function() {
+ var blob = new Blob();
+ assert_true(blob instanceof Blob);
+ assert_equals(String(blob), '[object Blob]');
+ assert_equals(blob.size, 0);
+ assert_equals(blob.type, "");
+}, "no-argument Blob constructor");
+test(function() {
+ var blob = Blob();
+ assert_true(blob instanceof Blob);
+ assert_equals(blob.size, 0);
+ assert_equals(blob.type, "");
+}, "no-argument Blob constructor without 'new'");
+test(function() {
+ var blob = new Blob;
+ assert_true(blob instanceof Blob);
+ assert_equals(blob.size, 0);
+ assert_equals(blob.type, "");
+}, "no-argument Blob constructor without brackets");
+
+// blobParts argument (WebIDL).
+test(function() {
+ var args = [
+ null,
+ undefined,
+ true,
+ false,
+ 0,
+ 1,
+ 1.5,
+ "FAIL",
+ new Date(),
+ new RegExp(),
+ ];
+ args.forEach(function(arg) {
+ assert_throws(new TypeError(), function() {
+ new Blob(arg);
+ }, "Should throw for argument " + format_value(arg) + ".");
+ });
+}, "Passing non-objects, Dates and RegExps for blobParts should throw a TypeError.");
+
+test_blob(function() {
+ return new Blob({});
+}, {
+ expected: "",
+ type: "",
+ desc: "A plain object should be treated as a sequence for the blobParts argument."
+});
+test_blob(function() {
+ return new Blob({ 0: "PASS", length: 1 });
+}, {
+ expected: "PASS",
+ type: "",
+ desc: "A plain object with a length property should be treated as a sequence for the blobParts argument."
+});
+test_blob(function() {
+ return new Blob(new String("xyz"));
+}, {
+ expected: "xyz",
+ type: "",
+ desc: "A String object should be treated as a sequence for the blobParts argument."
+});
+test_blob(function() {
+ return new Blob(new Uint8Array([1, 2, 3]));
+}, {
+ expected: "123",
+ type: "",
+ desc: "A Uint8Array object should be treated as a sequence for the blobParts argument."
+});
+
+var test_error = { name: "test" };
+
+test(function() {
+ var obj = {
+ get length() { throw test_error; }
+ };
+ assert_throws(test_error, function() {
+ new Blob(obj);
+ });
+}, "The length getter should be invoked and any exceptions should be propagated.");
+
+test_blob(function() {
+ var element = document.createElement("div");
+ element.appendChild(document.createElement("div"));
+ element.appendChild(document.createElement("p"));
+ var list = element.children;
+ Object.defineProperty(list, "length", {
+ get: function() { throw test_error; }
+ });
+ return new Blob(list);
+}, {
+ expected: "[object HTMLDivElement][object HTMLParagraphElement]",
+ type: "",
+ desc: "A platform object that supports indexed properties should be treated as a sequence for the blobParts argument (overwritten 'length'.)"
+});
+
+test(function() {
+ assert_throws(test_error, function() {
+ var obj = {
+ length: {
+ valueOf: null,
+ toString: function() { throw test_error; }
+ }
+ };
+ new Blob(obj);
+ });
+ assert_throws(test_error, function() {
+ var obj = {
+ length: { valueOf: function() { throw test_error; } }
+ };
+ new Blob(obj);
+ });
+}, "ToUint32 should be applied to the length and any exceptions should be propagated.");
+
+test(function() {
+ var received = [];
+ var obj = {
+ get length() {
+ received.push("length getter");
+ return {
+ valueOf: function() {
+ received.push("length valueOf");
+ return 3;
+ }
+ };
+ },
+ get 0() {
+ received.push("0 getter");
+ return {
+ toString: function() {
+ received.push("0 toString");
+ return "a";
+ }
+ };
+ },
+ get 1() {
+ received.push("1 getter");
+ throw test_error;
+ },
+ get 2() {
+ received.push("2 getter");
+ assert_unreached("Should not call the getter for 2 if the getter for 1 threw.");
+ }
+ };
+ assert_throws(test_error, function() {
+ new Blob(obj);
+ });
+ assert_array_equals(received, [
+ "length getter",
+ "length valueOf",
+ "0 getter",
+ "0 toString",
+ "1 getter"
+ ]);
+}, "Getters and value conversions should happen in order until an exception is thrown.");
+
+// XXX should add tests edge cases of ToUint32(length)
+
+test(function() {
+ assert_throws(test_error, function() {
+ new Blob([{ toString: function() { throw test_error; } }]);
+ }, "Throwing toString");
+ assert_throws(test_error, function() {
+ new Blob([{ toString: undefined, valueOf: function() { throw test_error; } }]);
+ }, "Throwing valueOf");
+ assert_throws(test_error, function() {
+ new Blob([{
+ toString: function() { throw test_error; },
+ valueOf: function() { assert_unreached("Should not call valueOf if toString is present."); }
+ }]);
+ }, "Throwing toString and valueOf");
+ assert_throws(new TypeError(), function() {
+ new Blob([{toString: null, valueOf: null}]);
+ }, "Null toString and valueOf");
+}, "ToString should be called on elements of the blobParts array and any exceptions should be propagated.");
+
+test_blob(function() {
+ var arr = [
+ { toString: function() { arr.pop(); return "PASS"; } },
+ { toString: function() { assert_unreached("Should have removed the second element of the array rather than called toString() on it."); } }
+ ];
+ return new Blob(arr);
+}, {
+ expected: "PASSundefined",
+ type: "",
+ desc: "Changes to the blobParts array should be reflected in the returned Blob (pop)."
+});
+
+test_blob(function() {
+ var arr = [
+ {
+ toString: function() {
+ if (arr.length === 3) {
+ return "SS";
+ }
+ arr.unshift({
+ toString: function() {
+ assert_unreached("Should only access index 0 once.");
+ }
+ });
+ return "PA";
+ }
+ },
+ {
+ toString: function() {
+ assert_unreached("Should not access the final element.");
+ }
+ }
+ ];
+ return new Blob(arr);
+}, {
+ expected: "PASS",
+ type: "",
+ desc: "Changes to the blobParts array should be reflected in the returned Blob (unshift)."
+});
+
+test_blob(function() {
+ // https://www.w3.org/Bugs/Public/show_bug.cgi?id=17652
+ return new Blob([
+ null,
+ undefined,
+ true,
+ false,
+ 0,
+ 1,
+ new String("stringobject"),
+ [],
+ ['x', 'y'],
+ {},
+ { 0: "FAIL", length: 1 },
+ { toString: function() { return "stringA"; } },
+ { toString: undefined, valueOf: function() { return "stringB"; } },
+ { valueOf: function() { assert_unreached("Should not call valueOf if toString is present on the prototype."); } }
+ ]);
+}, {
+ expected: "nullundefinedtruefalse01stringobjectx,y[object Object][object Object]stringAstringB[object Object]",
+ type: "",
+ desc: "ToString should be called on elements of the blobParts array."
+});
+
+test_blob(function() {
+ return new Blob([
+ new ArrayBuffer(8)
+ ]);
+}, {
+ expected: "\0\0\0\0\0\0\0\0",
+ type: "",
+ desc: "ArrayBuffer elements of the blobParts array should be supported."
+});
+
+test_blob(function() {
+ return new Blob([
+ new Uint8Array([0x50, 0x41, 0x53, 0x53]),
+ new Int8Array([0x50, 0x41, 0x53, 0x53]),
+ new Uint16Array([0x4150, 0x5353]),
+ new Int16Array([0x4150, 0x5353]),
+ new Uint32Array([0x53534150]),
+ new Int32Array([0x53534150]),
+ new Float32Array([0xD341500000])
+ ]);
+}, {
+ expected: "PASSPASSPASSPASSPASSPASSPASS",
+ type: "",
+ desc: "Passing typed arrays as elements of the blobParts array should work."
+});
+test_blob(function() {
+ return new Blob([
+ // 0x535 3415053534150
+ // 0x535 = 0b010100110101 -> Sign = +, Exponent = 1333 - 1023 = 310
+ // 0x13415053534150 * 2**(-52)
+ // ==> 0x13415053534150 * 2**258 = 2510297372767036725005267563121821874921913208671273727396467555337665343087229079989707079680
+ new Float64Array([2510297372767036725005267563121821874921913208671273727396467555337665343087229079989707079680])
+ ]);
+}, {
+ expected: "PASSPASS",
+ type: "",
+ desc: "Passing a Float64Array as element of the blobParts array should work."
+});
+
+test_blob(function() {
+ return new Blob(document.createElement("div"));
+}, {
+ expected: "",
+ type: "",
+ desc: "Passing an element as the blobParts array should work."
+});
+
+test_blob(function() {
+ return new Blob(window);
+}, {
+ expected: "[object Window]",
+ type: "",
+ desc: "Passing an platform object that supports indexed properties as the blobParts array should work (window)."
+});
+test_blob(function() {
+ window[0].toString = function() { return "foo"; };
+ return new Blob(window);
+}, {
+ expected: "foo",
+ type: "",
+ desc: "Passing an platform object that supports indexed properties as the blobParts array should work (window with custom toString)."
+});
+test_blob(function() {
+ var select = document.createElement("select");
+ select.appendChild(document.createElement("option"));
+ return new Blob(select);
+}, {
+ expected: "[object HTMLOptionElement]",
+ type: "",
+ desc: "Passing an platform object that supports indexed properties as the blobParts array should work (select)."
+});
+
+var t_ports = async_test("Passing a platform array object as the blobParts array should work (MessagePort[]).");
+t_ports.step(function() {
+ var channel = new MessageChannel();
+ channel.port2.onmessage = this.step_func(function(e) {
+ var b_ports = new Blob(e.ports);
+ assert_equals(b_ports.size, "[object MessagePort]".length);
+ this.done();
+ });
+ var channel2 = new MessageChannel();
+ channel.port1.postMessage('', [channel2.port1]);
+});
+
+test_blob(function() {
+ var elm = document.createElement("div");
+ elm.setAttribute("foo", "bar");
+ return new Blob(elm.attributes);
+}, {
+ expected: "[object Attr]",
+ type: "",
+ desc: "Passing a platform array object as the blobParts array should work (Attr[])."
+});
+
+test_blob(function() {
+ var blob = new Blob(['foo']);
+ return new Blob([blob, blob]);
+}, {
+ expected: "foofoo",
+ type: "",
+ desc: "Array with two blobs"
+});
+
+test_blob_binary(function() {
+ var view = new Uint8Array([0, 255, 0]);
+ return new Blob([view.buffer, view.buffer]);
+}, {
+ expected: [0, 255, 0, 0, 255, 0],
+ type: "",
+ desc: "Array with two buffers"
+});
+
+test_blob_binary(function() {
+ var view = new Uint8Array([0, 255, 0, 4]);
+ var blob = new Blob([view, view]);
+ assert_equals(blob.size, 8);
+ var view1 = new Uint16Array(view.buffer, 2);
+ return new Blob([view1, view.buffer, view1]);
+}, {
+ expected: [0, 4, 0, 255, 0, 4, 0, 4],
+ type: "",
+ desc: "Array with two bufferviews"
+});
+
+test_blob(function() {
+ var view = new Uint8Array([0]);
+ var blob = new Blob(["fo"]);
+ return new Blob([view.buffer, blob, "foo"]);
+}, {
+ expected: "\0fofoo",
+ type: "",
+ desc: "Array with mixed types"
+});
+
+// options argument
+test(function() {
+ new Blob([], { endings: "invalidEnumValue" });
+ new Blob([], { endings: null });
+ new Blob([], { endings: undefined });
+ new Blob([], { endings: 0 });
+ new Blob([], { get endings() { assert_unreached("Should not call getter"); } });
+}, "The 'endings' property should be ignored.");
+
+test(function() {
+ assert_throws(test_error, function() {
+ new Blob([], {
+ get type() { throw test_error; }
+ });
+ });
+ assert_throws(test_error, function() {
+ new Blob([], {
+ type: { toString: function() { throw test_error; } }
+ });
+ });
+}, "options properties should be accessed in lexicographic order.");
+
+test(function() {
+ assert_throws(test_error, function() {
+ new Blob(
+ [{ toString: function() { throw test_error } }],
+ {
+ get type() { assert_unreached("type getter should not be called."); }
+ }
+ );
+ });
+}, "Arguments should be evaluated from left to right.");
+
+[
+ null,
+ undefined,
+ {},
+ { unrecognized: true },
+ /regex/,
+ function() {}
+].forEach(function(arg, idx) {
+ test_blob(function() {
+ return new Blob([], arg);
+ }, {
+ expected: "",
+ type: "",
+ desc: "Passing " + format_value(arg) + " (index " + idx + ") for options should use the defaults."
+ });
+ test_blob(function() {
+ return new Blob(["\na\r\nb\n\rc\r"], arg);
+ }, {
+ expected: "\na\r\nb\n\rc\r",
+ type: "",
+ desc: "Passing " + format_value(arg) + " (index " + idx + ") for options should use the defaults (with newlines)."
+ });
+});
+
+test_blob(function() {
+ return new Blob(["\na\r\nb\n\rc\r"], { endings: "transparent" });
+}, {
+ expected: "\na\r\nb\n\rc\r",
+ type: "",
+ desc: "Newlines should not change when endings is 'transparent'."
+});
+test_blob(function() {
+ return new Blob(["\na\r\nb\n\rc\r"], { endings: "native" });
+}, {
+ expected: "\na\r\nb\n\rc\r",
+ type: "",
+ desc: "Newlines should not change when endings is 'native'."
+});
+
+var type_tests = [
+ // blobParts, type, expected type
+ [[], '', ''],
+ [[], 'a', 'a'],
+ [[], 'A', 'a'],
+ [[], 'text/html', 'text/html'],
+ [[], 'TEXT/HTML', 'text/html'],
+ [[], '\u00E5', ''],
+ [[], '\uD801\uDC7E', ''], // U+1047E
+ [[], ' image/gif ', ' image/gif '],
+ [[], '\timage/gif\t', ''],
+ [[], 'image/gif;\u007f', ''],
+ [[], '\u0130mage/gif', ''], // uppercase i with dot
+ [[], '\u0131mage/gif', ''], // lowercase dotless i
+ [[], 'image/gif\u0000', ''],
+ // check that type isn't changed based on sniffing
+ [[0x3C, 0x48, 0x54, 0x4D, 0x4C, 0x3E], 'unknown/unknown', 'unknown/unknown'], // "<HTML>"
+ [[0x00, 0xFF], 'text/plain', 'text/plain'],
+ [[0x47, 0x49, 0x46, 0x38, 0x39, 0x61], 'image/png', 'image/png'], // "GIF89a"
+];
+
+type_tests.forEach(function(t) {
+ test(function() {
+ var arr = new Uint8Array([t[0]]).buffer;
+ var b = new Blob([arr], {type:t[1]});
+ assert_equals(b.type, t[2]);
+ }, "Blob with type " + format_value(t[1]));
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/FileAPI/blob/Blob-slice.html b/tests/wpt/web-platform-tests/FileAPI/blob/Blob-slice.html
new file mode 100644
index 00000000000..a66136b10f1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/FileAPI/blob/Blob-slice.html
@@ -0,0 +1,214 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Blob slice</title>
+<link rel=help href="http://dev.w3.org/2006/webapi/FileAPI/#slice-method-algo">
+<link rel=author title="Saurabh Anand" href="mailto:saurabhanandiit@gmail.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../support/Blob.js"></script>
+<div id="log"></div>
+<script>
+test_blob(function() {
+ var blobTemp = new Blob(["PASS"]);
+ return blobTemp.slice();
+}, {
+ expected: "PASS",
+ type: "",
+ desc: "no-argument Blob slice"
+});
+
+test(function() {
+ var blob1, blob2;
+
+ test_blob(function() {
+ return blob1 = new Blob(["squiggle"]);
+ }, {
+ expected: "squiggle",
+ type: "",
+ desc: "blob1."
+ });
+
+ test_blob(function() {
+ return blob2 = new Blob(["steak"], {type: "content/type"});
+ }, {
+ expected: "steak",
+ type: "content/type",
+ desc: "blob2."
+ });
+
+ var arrayBuffer = new ArrayBuffer(16);
+ var int8View = new Int8Array(arrayBuffer);
+ for (var i = 0; i < 16; i++) {
+ int8View[i] = i + 65;
+ }
+
+ var testData = [
+ [
+ ["PASSSTRING"],
+ [{start: -6, contents: "STRING"},
+ {start: -12, contents: "PASSSTRING"},
+ {start: 4, contents: "STRING"},
+ {start: 12, contents: ""},
+ {start: 0, end: -6, contents: "PASS"},
+ {start: 0, end: -12, contents: ""},
+ {start: 0, end: 4, contents: "PASS"},
+ {start: 0, end: 12, contents: "PASSSTRING"},
+ {start: 7, end: 4, contents: ""}]
+ ],
+
+ // Test 3 strings
+ [
+ ["foo", "bar", "baz"],
+ [{start: 0, end: 9, contents: "foobarbaz"},
+ {start: 0, end: 3, contents: "foo"},
+ {start: 3, end: 9, contents: "barbaz"},
+ {start: 6, end: 9, contents: "baz"},
+ {start: 6, end: 12, contents: "baz"},
+ {start: 0, end: 9, contents: "foobarbaz"},
+ {start: 0, end: 11, contents: "foobarbaz"},
+ {start: 10, end: 15, contents: ""}]
+ ],
+
+ // Test string, Blob, string
+ [
+ ["foo", blob1, "baz"],
+ [{start: 0, end: 3, contents: "foo"},
+ {start: 3, end: 11, contents: "squiggle"},
+ {start: 2, end: 4, contents: "os"},
+ {start: 10, end: 12, contents: "eb"}]
+ ],
+
+ // Test blob, string, blob
+ [
+ [blob1, "foo", blob1],
+ [{start: 0, end: 8, contents: "squiggle"},
+ {start: 7, end: 9, contents: "ef"},
+ {start: 10, end: 12, contents: "os"},
+ {start: 1, end: 4, contents: "qui"},
+ {start: 12, end: 15, contents: "qui"},
+ {start: 40, end: 60, contents: ""}]
+ ],
+
+ // Test blobs all the way down
+ [
+ [blob2, blob1, blob2],
+ [{start: 0, end: 5, contents: "steak"},
+ {start: 5, end: 13, contents: "squiggle"},
+ {start: 13, end: 18, contents: "steak"},
+ {start: 1, end: 3, contents: "te"},
+ {start: 6, end: 10, contents: "quig"}]
+ ],
+
+ // Test an ArrayBufferView
+ [
+ [int8View, blob1, "foo"],
+ [{start: 0, end: 8, contents: "ABCDEFGH"},
+ {start: 8, end: 18, contents: "IJKLMNOPsq"},
+ {start: 17, end: 20, contents: "qui"},
+ {start: 4, end: 12, contents: "EFGHIJKL"}]
+ ],
+
+ // Test a partial ArrayBufferView
+ [
+ [new Uint8Array(arrayBuffer, 3, 5), blob1, "foo"],
+ [{start: 0, end: 8, contents: "DEFGHsqu"},
+ {start: 8, end: 18, contents: "igglefoo"},
+ {start: 4, end: 12, contents: "Hsquiggl"}]
+ ],
+
+ // Test type coercion of a number
+ [
+ [3, int8View, "foo"],
+ [{start: 0, end: 8, contents: "3ABCDEFG"},
+ {start: 8, end: 18, contents: "HIJKLMNOPf"},
+ {start: 17, end: 21, contents: "foo"},
+ {start: 4, end: 12, contents: "DEFGHIJK"}]
+ ],
+
+ [
+ [(new Uint8Array([0, 255, 0])).buffer,
+ new Blob(['abcd']),
+ 'efgh',
+ 'ijklmnopqrstuvwxyz'],
+ [{start: 1, end: 4, contents: "\uFFFD\u0000a"},
+ {start: 4, end: 8, contents: "bcde"},
+ {start: 8, end: 12, contents: "fghi"},
+ {start: 1, end: 12, contents: "\uFFFD\u0000abcdefghi"}]
+ ]
+ ];
+
+ testData.forEach(function(data, i) {
+ var blobs = data[0];
+ var tests = data[1];
+ tests.forEach(function(expectations, j) {
+ test(function() {
+ var blob = new Blob(blobs);
+ assert_true(blob instanceof Blob);
+ assert_false(blob instanceof File);
+
+ test_blob(function() {
+ return expectations.end === undefined
+ ? blob.slice(expectations.start)
+ : blob.slice(expectations.start, expectations.end);
+ }, {
+ expected: expectations.contents,
+ type: "",
+ desc: "Slicing test: slice (" + i + "," + j + ")."
+ });
+ }, "Slicing test (" + i + "," + j + ").");
+ });
+ });
+}, "Slices");
+
+var invalidTypes = [
+ "\xFF",
+ "te(xt/plain",
+ "te)xt/plain",
+ "te<xt/plain",
+ "te>xt/plain",
+ "te@xt/plain",
+ "te,xt/plain",
+ "te;xt/plain",
+ "te:xt/plain",
+ "te\\xt/plain",
+ "te\"xt/plain",
+ "te/xt/plain",
+ "te[xt/plain",
+ "te]xt/plain",
+ "te?xt/plain",
+ "te=xt/plain",
+ "te{xt/plain",
+ "te}xt/plain",
+ "te\x20xt/plain",
+ "te\x09xt/plain",
+ "te\x00xt/plain",
+ "te\x1Fxt/plain",
+ "te\x7Fxt/plain"
+];
+invalidTypes.forEach(function(type) {
+ test_blob(function() {
+ var blob = new Blob(["PASS"]);
+ return blob.slice(0, 4, type);
+ }, {
+ expected: "PASS",
+ type: "",
+ desc: "Invalid contentType (" + format_value(type) + ")"
+ });
+});
+
+var validTypes = [
+ "TEXT/PLAIN",
+ "text/plain;charset = UTF-8",
+ "text/plain;charset=UTF-8"
+];
+validTypes.forEach(function(type) {
+ test_blob(function() {
+ var blob = new Blob(["PASS"]);
+ return blob.slice(0, 4, type);
+ }, {
+ expected: "PASS",
+ type: type.toLowerCase(),
+ desc: "Valid contentType (" + format_value(type) + ")"
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/FileAPI/file/File-constructor.html b/tests/wpt/web-platform-tests/FileAPI/file/File-constructor.html
new file mode 100644
index 00000000000..97c08b6546e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/FileAPI/file/File-constructor.html
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>File constructor</title>
+<link rel=help href="http://dev.w3.org/2006/webapi/FileAPI/#dfn-file">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ assert_true("File" in window, "window should have a File property.");
+}, "File interface object exists");
+
+function test_first_argument(arg1, expectedSize, testName) {
+ test(function() {
+ var file = new File(arg1, "dummy");
+ assert_true(file instanceof File);
+ assert_equals(file.name, "dummy");
+ assert_equals(file.size, expectedSize);
+ assert_equals(file.type, "");
+ // assert_false(file.isClosed); XXX: File.isClosed doesn't seem to be implemented
+ assert_not_equals(file.lastModified, "");
+ }, testName);
+}
+
+test_first_argument(["bits"], 4, "DOMString fileBits");
+test_first_argument(["𝓽𝓮𝔁𝓽"], 16, "Unicode DOMString fileBits");
+test_first_argument([new Blob()], 0, "Empty Blob fileBits");
+test_first_argument([new Blob(["bits"])], 4, "Blob fileBits");
+test_first_argument([new ArrayBuffer(8)], 8, "ArrayBuffer fileBits");
+test_first_argument([new Uint8Array([0x50, 0x41, 0x53, 0x53])], 4, "Typed array fileBits");
+test_first_argument(["bits", new Blob(["bits"]), new Blob(), new Uint8Array([0x50, 0x41]),
+ new Uint16Array([0x5353]), new Uint32Array([0x53534150])], 16, "Various fileBits");
+
+function test_second_argument(arg2, expectedFileName, testName) {
+ test(function() {
+ var file = new File(["bits"], arg2);
+ assert_true(file instanceof File);
+ assert_equals(file.name, expectedFileName);
+ }, testName);
+}
+
+test_second_argument("dummy", "dummy", "Using fileName");
+test_second_argument("dummy/foo", "dummy:foo", "Using special character in fileName");
+
+// testing the third argument
+test(function() {
+ var file = new File(["bits"], "dummy", { type: "text/plain"});
+ assert_true(file instanceof File);
+ assert_equals(file.type, "text/plain");
+}, "Using type on the File constructor");
+test(function() {
+ var file = new File(["bits"], "dummy", { type: "TEXT/PLAIN"});
+ assert_true(file instanceof File);
+ assert_equals(file.type, "text/plain");
+}, "Using uppercase characters in type");
+test(function() {
+ var file = new File(["bits"], "dummy", { type: "𝓽𝓮𝔁𝓽/𝔭𝔩𝔞𝔦𝔫"});
+ assert_true(file instanceof File);
+ assert_equals(file.type, "");
+}, "Using illegal character for type");
+test(function() {
+ var file = new File(["bits"], "dummy", { lastModified: 42 });
+ assert_true(file instanceof File);
+ assert_equals(file.lastModified, 42);
+}, "Using lastModified");
+test(function() {
+ var file = new File(["bits"], "dummy", { name: "foo" });
+ assert_true(file instanceof File);
+ assert_equals(file.name, "dummy");
+}, "Misusing name");
+
+</script>
diff --git a/tests/wpt/web-platform-tests/FileAPI/fileReader.html b/tests/wpt/web-platform-tests/FileAPI/fileReader.html
new file mode 100644
index 00000000000..b767e22d4a6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/FileAPI/fileReader.html
@@ -0,0 +1,67 @@
+<!doctype html>
+<html>
+ <head>
+ <title>FileReader States</title>
+ <link rel=help href="http://dev.w3.org/2006/webapi/FileAPI/#dfn-filereader">
+ <link rel=author title="Lenient" href="mailto:lenient315@gmail.com">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ test(function() {
+ assert_true("FileReader" in window, "window should have a FileReader property.");
+ }, "FileReader interface object");
+
+ test(function(){
+ var fileReader = new FileReader();
+ assert_true(fileReader instanceof FileReader);
+ }, "no-argument FileReader constructor");
+
+ var t_abort = async_test("FileReader States -- abort");
+ t_abort.step(function(){
+ var fileReader = new FileReader();
+ assert_equals(fileReader.readyState, 0);
+ assert_equals(fileReader.readyState, FileReader.EMPTY);
+
+ var blob = new Blob();
+ fileReader.readAsArrayBuffer(blob);
+ assert_equals(fileReader.readyState, 1);
+ assert_equals(fileReader.readyState, FileReader.LOADING);
+
+ fileReader.onabort = this.step_func(function(e) {
+ assert_equals(fileReader.readyState, 2);
+ assert_equals(fileReader.readyState, FileReader.DONE);
+ t_abort.done();
+ });
+ fileReader.abort();
+ fileReader.onabort = this.unreached_func("abort event should fire sync")
+ });
+
+ var t_event = async_test("FileReader States -- events");
+ t_event.step(function(){
+ var fileReader = new FileReader();
+
+ var blob = new Blob();
+ fileReader.readAsArrayBuffer(blob);
+
+ fileReader.onloadstart = this.step_func(function(e) {
+ assert_equals(fileReader.readyState, 1);
+ assert_equals(fileReader.readyState, FileReader.LOADING);
+ });
+
+ fileReader.onprogress = this.step_func(function(e) {
+ assert_equals(fileReader.readyState, 1);
+ assert_equals(fileReader.readyState, FileReader.LOADING);
+ });
+
+ fileReader.onloadend = this.step_func(function(e) {
+ assert_equals(fileReader.readyState, 2);
+ assert_equals(fileReader.readyState, FileReader.DONE);
+ t_event.done();
+ });
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/FileAPI/filelist-section/filelist.html b/tests/wpt/web-platform-tests/FileAPI/filelist-section/filelist.html
new file mode 100644
index 00000000000..b97dcde19f6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/FileAPI/filelist-section/filelist.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset='utf-8'>
+ <title>FileAPI Test: filelist</title>
+ <link rel='author' title='Intel' href='http://www.intel.com'>
+ <link rel='help' href='http://dev.w3.org/2006/webapi/FileAPI/#filelist-section'>
+ <link rel="help" href="http://dev.w3.org/2006/webapi/FileAPI/#dfn-length">
+ <link rel="help" href="http://dev.w3.org/2006/webapi/FileAPI/#dfn-item">
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+ </head>
+
+ <body>
+ <form name='uploadData' style="display:none">
+ <input type='file' id='fileChooser'>
+ </form>
+ <div id='log'></div>
+
+ <script>
+ var fileList;
+
+ setup(function () {
+ fileList = document.querySelector('#fileChooser').files;
+ });
+
+ test(function () {
+ assert_true('FileList' in window, 'window has a FileList property');
+ }, 'Check if window has a FileList property');
+
+ test(function () {
+ assert_equals(FileList.length, 0, 'FileList.length is 0');
+ }, 'Check if FileList.length is 0');
+
+ test(function () {
+ assert_true(fileList.item instanceof Function, 'item is a instanceof Function');
+ }, 'Check if item is a instanceof Function');
+
+ test(function() {
+ assert_inherits(fileList, 'item', 'item is a method of fileList');
+ }, 'Check if item is a method of fileList');
+
+ test(function() {
+ assert_equals(fileList.item(0), null, 'item method returns null');
+ }, 'Check if the item method returns null when no file selected');
+
+ test(function() {
+ assert_inherits(fileList, 'length', 'length is fileList attribute');
+ }, 'Check if length is fileList\'s attribute');
+
+ test(function() {
+ assert_equals(fileList.length, 0, 'fileList length is 0');
+ }, 'Check if the fileList length is 0 when no file selected');
+ </script>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/FileAPI/filelist-section/filelist_multiple_selected_files-manual.html b/tests/wpt/web-platform-tests/FileAPI/filelist-section/filelist_multiple_selected_files-manual.html
new file mode 100644
index 00000000000..2efaa059fa4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/FileAPI/filelist-section/filelist_multiple_selected_files-manual.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset='utf-8'>
+ <title>FileAPI Test: filelist_multiple_selected_files</title>
+ <link rel='author' title='Intel' href='http://www.intel.com'>
+ <link rel='help' href='http://dev.w3.org/2006/webapi/FileAPI/#filelist-section'>
+ <link rel="help" href="http://dev.w3.org/2006/webapi/FileAPI/#dfn-length">
+ <link rel="help" href="http://dev.w3.org/2006/webapi/FileAPI/#dfn-item">
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+ </head>
+
+ <body>
+ <form name='uploadData'>
+ <input type='file' id='fileChooser' multiple>
+ </form>
+ <div>
+ <p>Test steps:</p>
+ <ol>
+ <li>Download <a href='support/upload.txt'>upload.txt</a>, <a href="support/upload.zip">upload.zip</a> to local.</li>
+ <li>Select the local two files (upload.txt, upload.zip) to run the test.</li>
+ </ol>
+ </div>
+
+ <div id='log'></div>
+
+ <script>
+ var fileInput = document.querySelector('#fileChooser');
+ var fileList;
+
+ setup({explicit_done: true, explicit_timeout: true});
+
+ on_event(fileInput, 'change', function(evt) {
+ test(function() {
+ fileList = document.querySelector('#fileChooser').files;
+ assert_equals(fileList.length, 2, 'fileList length is 2');
+ }, 'Check if the fileList length is 2 when selected two files');
+
+ test(function() {
+ fileList = document.querySelector('#fileChooser').files;
+ assert_true(fileList.item(0) instanceof File, 'item method is instanceof File');
+ }, 'Check if the item method returns the File interface when selected two files');
+
+ test(function() {
+ fileList = document.querySelector('#fileChooser').files;
+ assert_not_equals(fileList.item(1), null, 'item(1) is not null');
+ }, 'Check if item(1) is not null when selected two files. Index must be treated by user agents as value for the position of a File object in the FileList, with 0 representing the first file.');
+
+ test(function() {
+ fileList = document.querySelector('#fileChooser').files;
+ assert_equals(fileList.item(2), null, 'item(2) is null');
+ }, 'Check if item(2) is null when selected two files');
+
+ test(function() {
+ fileList = document.querySelector('#fileChooser').files;
+ assert_array_equals([fileList.item(0).name, fileList.item(1).name], ['upload.txt', 'upload.zip'], 'file name string is the name of selected files "upload.txt", "upload.zip"');
+ }, 'Check if the file name string is the name of selected files');
+
+ done();
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/FileAPI/filelist-section/filelist_selected_file-manual.html b/tests/wpt/web-platform-tests/FileAPI/filelist-section/filelist_selected_file-manual.html
new file mode 100644
index 00000000000..966aadda615
--- /dev/null
+++ b/tests/wpt/web-platform-tests/FileAPI/filelist-section/filelist_selected_file-manual.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset='utf-8'>
+ <title>FileAPI Test: filelist_selected_file</title>
+ <link rel='author' title='Intel' href='http://www.intel.com'>
+ <link rel='help' href='http://dev.w3.org/2006/webapi/FileAPI/#filelist-section'>
+ <link rel="help" href="http://dev.w3.org/2006/webapi/FileAPI/#dfn-length">
+ <link rel="help" href="http://dev.w3.org/2006/webapi/FileAPI/#dfn-item">
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+ </head>
+
+ <body>
+ <form name='uploadData'>
+ <input type='file' id='fileChooser'>
+ </form>
+ <div>
+ <p>Test steps:</p>
+ <ol>
+ <li>Download <a href='support/upload.txt'>upload.txt</a> to local.</li>
+ <li>Select the local upload.txt file to run the test.</li>
+ </ol>
+ </div>
+
+ <div id='log'></div>
+
+ <script>
+ var fileInput = document.querySelector('#fileChooser');
+ var fileList;
+
+ setup({explicit_done: true, explicit_timeout: true});
+
+ on_event(fileInput, 'change', function(evt) {
+ test(function() {
+ fileList = document.querySelector('#fileChooser').files;
+ assert_equals(fileList.length, 1, 'fileList length is 1');
+ }, 'Check if the fileList length is 1 when selected one file');
+
+ test(function() {
+ fileList = document.querySelector('#fileChooser').files;
+ assert_true(fileList.item(0) instanceof File, 'item method is instanceof File');
+ }, 'Check if the item method returns the File interface when selected one file');
+
+ test(function() {
+ fileList = document.querySelector('#fileChooser').files;
+ assert_not_equals(fileList.item(0), null, 'item(0) is not null');
+ }, 'Check if item(0) is not null when selected one file. Index must be treated by user agents as value for the position of a File object in the FileList, with 0 representing the first file.');
+
+ test(function() {
+ fileList = document.querySelector('#fileChooser').files;
+ assert_equals(fileList.item(1), null, 'item(1) is null');
+ }, 'Check if item(1) is null when selected one file only');
+
+ test(function() {
+ fileList = document.querySelector('#fileChooser').files;
+ assert_equals(fileList.item(0).name, 'upload.txt', 'file name string is "upload.txt"');
+ }, 'Check if the file name string is the selected "upload.txt"');
+
+ done();
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/FileAPI/filelist-section/support/upload.txt b/tests/wpt/web-platform-tests/FileAPI/filelist-section/support/upload.txt
new file mode 100644
index 00000000000..f45965b711f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/FileAPI/filelist-section/support/upload.txt
@@ -0,0 +1 @@
+Hello, this is test file for file upload.
diff --git a/tests/wpt/web-platform-tests/FileAPI/filelist-section/support/upload.zip b/tests/wpt/web-platform-tests/FileAPI/filelist-section/support/upload.zip
new file mode 100644
index 00000000000..a933d6a9494
--- /dev/null
+++ b/tests/wpt/web-platform-tests/FileAPI/filelist-section/support/upload.zip
Binary files differ
diff --git a/tests/wpt/web-platform-tests/FileAPI/historical.html b/tests/wpt/web-platform-tests/FileAPI/historical.html
new file mode 100644
index 00000000000..3ff56a30164
--- /dev/null
+++ b/tests/wpt/web-platform-tests/FileAPI/historical.html
@@ -0,0 +1,48 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Historical features</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ test(function() {
+ assert_false('toNativeLineEndings' in window);
+ }, '"toNativeLineEndings" should not be supported');
+
+ test(function() {
+ assert_false('FileError' in window);
+ }, '"FileError" should not be supported');
+
+ test(function() {
+ assert_false('FileException' in window);
+ }, '"FileException" should not be supported');
+
+ test(function() {
+ var b = new Blob();
+ var prefixes = ['op', 'moz', 'webkit', 'ms'];
+ for (var i = 0; i < prefixes.length; ++i) {
+ assert_false(prefixes[i]+'Slice' in b, "'"+prefixes[i]+"Slice' in b");
+ assert_false(prefixes[i]+'Slice' in Blob.prototype, "'"+prefixes[i]+"Slice in Blob.prototype");
+ }
+ }, 'Blob should not support slice prefixed');
+
+ test(function() {
+ var prefixes = ['', 'O', 'Moz', 'WebKit', 'MS'];
+ for (var i = 0; i < prefixes.length; ++i) {
+ assert_false(prefixes[i]+'BlobBuilder' in window, prefixes[i]+'BlobBuilder');
+ }
+ }, 'BlobBuilder should not be supported.');
+
+ test(function() {
+ var reader = new FileReader();
+ assert_false('readAsBinaryString' in reader, 'should not be in reader');
+ assert_equals(reader.readAsBinaryString, undefined,
+ 'should be undefined on getting')
+ }, 'FileReader should not support readAsBinaryString');
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/FileAPI/idlharness-manual.html b/tests/wpt/web-platform-tests/FileAPI/idlharness-manual.html
new file mode 100644
index 00000000000..8fb0dfb784a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/FileAPI/idlharness-manual.html
@@ -0,0 +1,167 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>File API manual IDL tests</title>
+ <link rel="author" title="Intel" href="http://www.intel.com">
+ <link rel="help" href="http://dev.w3.org/2006/webapi/FileAPI/#conformance">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/resources/WebIDLParser.js"></script>
+ <script src="/resources/idlharness.js"></script>
+ </head>
+ <body>
+ <h1>File API manual IDL tests</h1>
+
+ <div>
+ <p>Test steps:</p>
+ <ol>
+ <li>Download <a href="support/upload.txt">upload.txt</a> to local.</li>
+ <li>Select the local upload.txt file to run the test.</li>
+ </ol>
+ </div>
+
+ <form name="uploadData">
+ <input type="file" id="fileChooser">
+ </form>
+
+ <div id="log"></div>
+
+ <pre id="untested_idl" style="display: none">
+ interface ArrayBuffer {
+ };
+
+ interface ArrayBufferView {
+ };
+
+ interface URL {
+ };
+
+ interface EventTarget {
+ };
+
+ interface Event {
+ };
+
+ [TreatNonCallableAsNull]
+ callback EventHandlerNonNull = any (Event event);
+ typedef EventHandlerNonNull? EventHandler;
+ </pre>
+
+ <pre id="idl" style="display: none">
+[Constructor,
+ Constructor(sequence<(ArrayBuffer or ArrayBufferView or Blob or DOMString)> blobParts, optional BlobPropertyBag options), Exposed=Window,Worker]
+interface Blob {
+
+ readonly attribute unsigned long long size;
+ readonly attribute DOMString type;
+ readonly attribute boolean isClosed;
+
+ //slice Blob into byte-ranged chunks
+
+ Blob slice([Clamp] optional long long start,
+ [Clamp] optional long long end,
+ optional DOMString contentType);
+ void close();
+
+};
+
+dictionary BlobPropertyBag {
+ DOMString type = "";
+};
+
+[Constructor(sequence<(Blob or DOMString or ArrayBufferView or ArrayBuffer)> fileBits,
+[EnsureUTF16] DOMString fileName, optional FilePropertyBag options), Exposed=Window,Worker]
+interface File : Blob {
+
+ readonly attribute DOMString name;
+ readonly attribute long long lastModified;
+
+};
+
+dictionary FilePropertyBag {
+
+ DOMString type = "";
+ long long lastModified;
+
+};
+
+[Exposed=Window,Worker] interface FileList {
+ getter File? item(unsigned long index);
+ readonly attribute unsigned long length;
+};
+
+[Constructor, Exposed=Window,Worker]
+interface FileReader: EventTarget {
+
+ // async read methods
+ void readAsArrayBuffer(Blob blob);
+ void readAsText(Blob blob, optional DOMString label);
+ void readAsDataURL(Blob blob);
+
+ void abort();
+
+ // states
+ const unsigned short EMPTY = 0;
+ const unsigned short LOADING = 1;
+ const unsigned short DONE = 2;
+
+ readonly attribute unsigned short readyState;
+
+ // File or Blob data
+ readonly attribute (DOMString or ArrayBuffer)? result;
+
+ readonly attribute DOMError? error;
+
+ // event handler attributes
+ attribute EventHandler onloadstart;
+ attribute EventHandler onprogress;
+ attribute EventHandler onload;
+ attribute EventHandler onabort;
+ attribute EventHandler onerror;
+ attribute EventHandler onloadend;
+
+};
+
+[Constructor, Exposed=Worker]
+interface FileReaderSync {
+
+ // Synchronously return strings
+
+ ArrayBuffer readAsArrayBuffer(Blob blob);
+ DOMString readAsText(Blob blob, optional DOMString label);
+ DOMString readAsDataURL(Blob blob);
+};
+
+partial interface URL {
+
+ static DOMString createObjectURL(Blob blob);
+ static DOMString createFor(Blob blob);
+ static void revokeObjectURL(DOMString url);
+
+};
+ </pre>
+
+ <script>
+ var fileInput;
+
+ setup(function() {
+ fileInput = document.querySelector("#fileChooser")
+ }, {explicit_done: true, explicit_timeout: true});
+
+ on_event(fileInput, "change", function(evt) {
+ var idl_array = new IdlArray();
+ idl_array.add_untested_idls(document.getElementById("untested_idl").textContent);
+ idl_array.add_idls(document.getElementById("idl").textContent);
+
+ idl_array.add_objects({
+ FileList: [fileInput.files],
+ File: [fileInput.files[0]],
+ });
+ idl_array.test();
+
+ done();
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/FileAPI/idlharness.html b/tests/wpt/web-platform-tests/FileAPI/idlharness.html
new file mode 100644
index 00000000000..64a9c8508b3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/FileAPI/idlharness.html
@@ -0,0 +1,158 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>File API automated IDL tests</title>
+ <link rel="author" title="Intel" href="http://www.intel.com">
+ <link rel="help" href="http://dev.w3.org/2006/webapi/FileAPI/#conformance">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/resources/WebIDLParser.js"></script>
+ <script src="/resources/idlharness.js"></script>
+ </head>
+ <body>
+ <h1>File API automated IDL tests</h1>
+
+ <div id="log"></div>
+
+ <pre id="untested_idl" style="display: none">
+ interface ArrayBuffer {
+ };
+
+ interface ArrayBufferView {
+ };
+
+ interface URL {
+ };
+
+ interface EventTarget {
+ };
+
+ interface Event {
+ };
+
+ [TreatNonCallableAsNull]
+ callback EventHandlerNonNull = any (Event event);
+ typedef EventHandlerNonNull? EventHandler;
+ </pre>
+
+ <pre id="idl" style="display: none">
+[Constructor,
+ Constructor(sequence<(ArrayBuffer or ArrayBufferView or Blob or DOMString)> blobParts, optional BlobPropertyBag options), Exposed=Window,Worker]
+interface Blob {
+
+ readonly attribute unsigned long long size;
+ readonly attribute DOMString type;
+ readonly attribute boolean isClosed;
+
+ //slice Blob into byte-ranged chunks
+
+ Blob slice([Clamp] optional long long start,
+ [Clamp] optional long long end,
+ optional DOMString contentType);
+ void close();
+
+};
+
+dictionary BlobPropertyBag {
+ DOMString type = "";
+};
+
+[Constructor(sequence<(Blob or DOMString or ArrayBufferView or ArrayBuffer)> fileBits,
+[EnsureUTF16] DOMString fileName, optional FilePropertyBag options), Exposed=Window,Worker]
+interface File : Blob {
+
+ readonly attribute DOMString name;
+ readonly attribute long long lastModified;
+
+};
+
+dictionary FilePropertyBag {
+
+ DOMString type = "";
+ long long lastModified;
+
+};
+
+[Exposed=Window,Worker] interface FileList {
+ getter File? item(unsigned long index);
+ readonly attribute unsigned long length;
+};
+
+[Constructor, Exposed=Window,Worker]
+interface FileReader: EventTarget {
+
+ // async read methods
+ void readAsArrayBuffer(Blob blob);
+ void readAsText(Blob blob, optional DOMString label);
+ void readAsDataURL(Blob blob);
+
+ void abort();
+
+ // states
+ const unsigned short EMPTY = 0;
+ const unsigned short LOADING = 1;
+ const unsigned short DONE = 2;
+
+ readonly attribute unsigned short readyState;
+
+ // File or Blob data
+ readonly attribute (DOMString or ArrayBuffer)? result;
+
+ readonly attribute DOMError? error;
+
+ // event handler attributes
+ attribute EventHandler onloadstart;
+ attribute EventHandler onprogress;
+ attribute EventHandler onload;
+ attribute EventHandler onabort;
+ attribute EventHandler onerror;
+ attribute EventHandler onloadend;
+
+};
+
+[Constructor, Exposed=Worker]
+interface FileReaderSync {
+
+ // Synchronously return strings
+
+ ArrayBuffer readAsArrayBuffer(Blob blob);
+ DOMString readAsText(Blob blob, optional DOMString label);
+ DOMString readAsDataURL(Blob blob);
+};
+
+partial interface URL {
+
+ static DOMString createObjectURL(Blob blob);
+ static DOMString createFor(Blob blob);
+ static void revokeObjectURL(DOMString url);
+
+};
+
+ </pre>
+
+ <form name="uploadData">
+ <input type="file" id="fileChooser">
+ </form>
+
+ <script>
+ var idl_array, file_input;
+
+ setup(function() {
+ file_input = document.querySelector("#fileChooser");
+ idl_array = new IdlArray();
+ idl_array.add_untested_idls(document.getElementById("untested_idl").textContent);
+ idl_array.add_idls(document.getElementById("idl").textContent);
+
+ idl_array.add_objects({
+ Blob: ['new Blob(["TEST"])'],
+ File: ['new File(["myFileBits"], "myFileName")'],
+ FileList: ['file_input.files'],
+ FileReader: ['new FileReader()']
+ });
+ });
+
+ idl_array.test();
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/FileAPI/progress.html b/tests/wpt/web-platform-tests/FileAPI/progress.html
new file mode 100644
index 00000000000..b2e03b3eb27
--- /dev/null
+++ b/tests/wpt/web-platform-tests/FileAPI/progress.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Process Events for FileReader</title>
+<link rel=help href="http://dev.w3.org/2006/webapi/FileAPI/#event-handler-attributes-section">
+<link rel=author title="Jinks Zhao" href="mailto:jinks@maxthon.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+Please choose one file through this input below.<br>
+<input type="file" id="filer">
+<div id="log"></div>
+<script>
+var input, reader, progressEventCounter, progressEventTimeList,
+ lastProgressEventTime;
+setup(function() {
+ input = document.getElementById('filer');
+ reader = new FileReader();
+ progressEventCounter = 0;
+ progressEventTimeList = [];
+ lastProgressEventTime;
+}, { explicit_timeout: true });
+
+var t = async_test("FileReader progress events.")
+
+reader.onprogress = t.step_func(function () {
+ var newTime = new Date;
+ var timeout = newTime - lastProgressEventTime;
+
+ progressEventTimeList.push(timeout);
+ lastProgressEventTime = newTime;
+ progressEventCounter++;
+
+ assert_less_than_equal(timeout, 50, "The progress event should be fired every 50ms.");
+});
+
+reader.onload = t.step_func_done(function () {
+ assert_greater_than_equal(progressEventCounter, 1,
+ "When read completely, the progress event must be fired at least once.")
+});
+
+input.onchange = t.step_func(function () {
+ var files = input.files;
+
+ assert_greater_than(files.length, 0);
+ var file = files[0];
+
+ lastProgressEventTime = new Date;
+ reader.readAsArrayBuffer(file);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/FileAPI/reading-data-section/Determining-Encoding.html b/tests/wpt/web-platform-tests/FileAPI/reading-data-section/Determining-Encoding.html
new file mode 100644
index 00000000000..d65ae9db18a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/FileAPI/reading-data-section/Determining-Encoding.html
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>FileAPI Test: Blob Determining Encoding</title>
+<link ref="author" title="march1993" href="mailto:march511@gmail.com">
+<link rel=help href="http://dev.w3.org/2006/webapi/FileAPI/#enctype">
+<link rel=help href="http://encoding.spec.whatwg.org/#decode">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var t = async_test("Blob Determing Encoding with encoding argument");
+t.step(function() {
+ // string 'hello'
+ var data = [0xFE,0xFF,0x00,0x68,0x00,0x65,0x00,0x6C,0x00,0x6C,0x00,0x6F];
+ var blob = new Blob([new Uint8Array(data)]);
+ var reader = new FileReader();
+
+ reader.onloadend = t.step_func_done (function(event) {
+ assert_equals(this.result, "hello", "The FileReader should read the ArrayBuffer through UTF-16BE.")
+ }, reader);
+
+ reader.readAsText(blob, "UTF-16BE");
+});
+
+var t = async_test("Blob Determing Encoding with type attribute");
+t.step(function() {
+ var data = [0xFE,0xFF,0x00,0x68,0x00,0x65,0x00,0x6C,0x00,0x6C,0x00,0x6F];
+ var blob = new Blob([new Uint8Array(data)], {type:"text/plain;charset=UTF-16BE"});
+ var reader = new FileReader();
+
+ reader.onloadend = t.step_func_done (function(event) {
+ assert_equals(this.result, "hello", "The FileReader should read the ArrayBuffer through UTF-16BE.")
+ }, reader);
+
+ reader.readAsText(blob);
+});
+
+
+var t = async_test("Blob Determing Encoding with UTF-8 BOM");
+t.step(function() {
+ var data = [0xEF,0xBB,0xBF,0x68,0x65,0x6C,0x6C,0xC3,0xB6];
+ var blob = new Blob([new Uint8Array(data)]);
+ var reader = new FileReader();
+
+ reader.onloadend = t.step_func_done (function(event) {
+ assert_equals(this.result, "hellö", "The FileReader should read the blob with UTF-8.");
+ }, reader);
+
+ reader.readAsText(blob);
+});
+
+var t = async_test("Blob Determing Encoding without anything implying charset.");
+t.step(function() {
+ var data = [0x68,0x65,0x6C,0x6C,0xC3,0xB6];
+ var blob = new Blob([new Uint8Array(data)]);
+ var reader = new FileReader();
+
+ reader.onloadend = t.step_func_done (function(event) {
+ assert_equals(this.result, "hellö", "The FileReader should read the blob by default with UTF-8.");
+ }, reader);
+
+ reader.readAsText(blob);
+});
+
+var t = async_test("Blob Determing Encoding with UTF-16BE BOM");
+t.step(function() {
+ var data = [0xFE,0xFF,0x00,0x68,0x00,0x65,0x00,0x6C,0x00,0x6C,0x00,0x6F];
+ var blob = new Blob([new Uint8Array(data)]);
+ var reader = new FileReader();
+
+ reader.onloadend = t.step_func_done (function(event) {
+ assert_equals(this.result, "hello", "The FileReader should read the ArrayBuffer through UTF-16BE.");
+ }, reader);
+
+ reader.readAsText(blob);
+});
+
+var t = async_test("Blob Determing Encoding with UTF-16LE BOM");
+t.step(function() {
+ var data = [0xFF,0xFE,0x68,0x00,0x65,0x00,0x6C,0x00,0x6C,0x00,0x6F,0x00];
+ var blob = new Blob([new Uint8Array(data)]);
+ var reader = new FileReader();
+
+ reader.onloadend = t.step_func_done (function(event) {
+ assert_equals(this.result, "hello", "The FileReader should read the ArrayBuffer through UTF-16LE.");
+ }, reader);
+
+ reader.readAsText(blob);
+});
+
+</script>
diff --git a/tests/wpt/web-platform-tests/FileAPI/reading-data-section/FileReader-event-handler-attributes.html b/tests/wpt/web-platform-tests/FileAPI/reading-data-section/FileReader-event-handler-attributes.html
new file mode 100644
index 00000000000..86657b5711a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/FileAPI/reading-data-section/FileReader-event-handler-attributes.html
@@ -0,0 +1,23 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>FileReader event handler attributes</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var attributes = [
+ "onloadstart",
+ "onprogress",
+ "onload",
+ "onabort",
+ "onerror",
+ "onloadend",
+];
+attributes.forEach(function(a) {
+ test(function() {
+ var reader = new FileReader();
+ assert_equals(reader[a], null,
+ "event handler attribute should initially be null");
+ }, "FileReader." + a + ": initial value");
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/FileAPI/reading-data-section/FileReader-multiple-reads.html b/tests/wpt/web-platform-tests/FileAPI/reading-data-section/FileReader-multiple-reads.html
new file mode 100644
index 00000000000..86a29d187b5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/FileAPI/reading-data-section/FileReader-multiple-reads.html
@@ -0,0 +1,73 @@
+<!DOCTYPE html>
+<title>FileReader: starting new reads while one is in progress</title>
+<link rel="author" title="Yinkan Li" href="mailto:liyinkan.biz@gmail.com">
+<link rel="help" href="http://dev.w3.org/2006/webapi/FileAPI/#MultipleReads">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ var blob_1 = new Blob(['TEST000000001'])
+ var blob_2 = new Blob(['TEST000000002'])
+ var reader = new FileReader();
+ reader.readAsText(blob_1)
+ assert_equals(reader.readyState, FileReader.LOADING, "readyState Must be LOADING")
+ assert_throws("InvalidStateError", function () {
+ reader.readAsText(blob_2)
+ })
+}, 'test FileReader InvalidStateError exception for readAsText');
+
+test(function() {
+ var blob_1 = new Blob(['TEST000000001'])
+ var blob_2 = new Blob(['TEST000000002'])
+ var reader = new FileReader();
+ reader.readAsDataURL(blob_1)
+ assert_equals(reader.readyState, FileReader.LOADING, "readyState Must be LOADING")
+ assert_throws("InvalidStateError", function () {
+ reader.readAsDataURL(blob_2)
+ })
+}, 'test FileReader InvalidStateError exception for readAsDataURL');
+
+test(function() {
+ var blob_1 = new Blob(['TEST000000001'])
+ var blob_2 = new Blob(['TEST000000002'])
+ var reader = new FileReader();
+ reader.readAsArrayBuffer(blob_1)
+ assert_equals(reader.readyState, FileReader.LOADING, "readyState Must be LOADING")
+ assert_throws("InvalidStateError", function () {
+ reader.readAsArrayBuffer(blob_2)
+ })
+}, 'test FileReader InvalidStateError exception for readAsArrayBuffer');
+
+async_test(function() {
+ var blob_1 = new Blob(['TEST000000001'])
+ var blob_2 = new Blob(['TEST000000002'])
+ var reader = new FileReader();
+ var triggered = false;
+ reader.onloadstart = this.step_func_done(function() {
+ assert_false(triggered, "Only one loadstart event should be dispatched");
+ triggered = true;
+ assert_equals(reader.readyState, FileReader.LOADING,
+ "readyState must be LOADING")
+ assert_throws("InvalidStateError", function () {
+ reader.readAsArrayBuffer(blob_2)
+ })
+ });
+ reader.readAsArrayBuffer(blob_1)
+ assert_equals(reader.readyState, FileReader.LOADING, "readyState Must be LOADING")
+}, 'test FileReader InvalidStateError exception in onloadstart event for readAsArrayBuffer');
+
+async_test(function() {
+ var blob_1 = new Blob(['TEST000000001'])
+ var blob_2 = new Blob(['TEST000000002'])
+ var reader = new FileReader();
+ reader.onloadend = this.step_func_done(function() {
+ assert_equals(reader.readyState, FileReader.LOADING,
+ "readyState must be LOADING")
+ reader.readAsArrayBuffer(blob_2)
+ assert_equals(reader.readyState, FileReader.LOADING, "readyState Must be LOADING")
+ });
+ reader.readAsArrayBuffer(blob_1)
+ assert_equals(reader.readyState, FileReader.LOADING, "readyState Must be LOADING")
+}, 'test FileReader no InvalidStateError exception in onloadstart event for readAsArrayBuffer');
+</script>
diff --git a/tests/wpt/web-platform-tests/FileAPI/reading-data-section/filereader_abort.html b/tests/wpt/web-platform-tests/FileAPI/reading-data-section/filereader_abort.html
new file mode 100644
index 00000000000..a96389c21d6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/FileAPI/reading-data-section/filereader_abort.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>FileAPI Test: filereader_abort</title>
+ <link rel="author" title="Intel" href="http://www.intel.com">
+ <link rel="help" href="http://dev.w3.org/2006/webapi/FileAPI/#abort">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+
+ <script>
+ test(function() {
+ var readerNoRead = new FileReader();
+ readerNoRead.abort();
+ assert_equals(readerNoRead.readyState, readerNoRead.EMPTY);
+ assert_equals(readerNoRead.result, null);
+ }, "Aborting before read");
+
+ async_test(function() {
+ var blob = new Blob(["TEST THE ABORT METHOD"]);
+ var readerAbort = new FileReader();
+
+ readerAbort.onabort = this.step_func(function(evt) {
+ assert_equals(readerAbort.readyState, readerAbort.DONE);
+ });
+
+ readerAbort.onloadstart = this.step_func(function(evt) {
+ assert_equals(readerAbort.readyState, readerAbort.LOADING);
+ readerAbort.abort();
+ });
+
+ readerAbort.onloadend = this.step_func(function(evt) {
+ // https://www.w3.org/Bugs/Public/show_bug.cgi?id=24401
+ assert_equals(readerAbort.result, null);
+ assert_equals(readerAbort.readyState, readerAbort.DONE);
+ this.done();
+ });
+
+ readerAbort.readAsText(blob);
+ }, "Aborting after read");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/FileAPI/reading-data-section/filereader_error.html b/tests/wpt/web-platform-tests/FileAPI/reading-data-section/filereader_error.html
new file mode 100644
index 00000000000..cf4524825b8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/FileAPI/reading-data-section/filereader_error.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>FileAPI Test: filereader_error</title>
+ <link rel="author" title="Intel" href="http://www.intel.com">
+ <link rel="help" href="http://dev.w3.org/2006/webapi/FileAPI/#dfn-domerror">
+ <link rel="help" href="http://dev.w3.org/2006/webapi/FileAPI/#abort">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+
+ <script>
+ async_test(function() {
+ var blob = new Blob(["TEST THE ERROR ATTRIBUTE AND ERROR EVENT"]);
+ var reader = new FileReader();
+ assert_equals(reader.error, null, "The error is null when no error occurred");
+
+ reader.onload = this.step_func(function(evt) {
+ assert_unreached("Should not dispatch the load event");
+ });
+
+ reader.onloadend = this.step_func(function(evt) {
+ assert_equals(reader.result, null, "The result is null");
+ this.done();
+ });
+
+ reader.readAsText(blob);
+ reader.abort();
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/FileAPI/reading-data-section/filereader_file-manual.html b/tests/wpt/web-platform-tests/FileAPI/reading-data-section/filereader_file-manual.html
new file mode 100644
index 00000000000..702ca9afd7b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/FileAPI/reading-data-section/filereader_file-manual.html
@@ -0,0 +1,69 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>FileAPI Test: filereader_file</title>
+ <link rel="author" title="Intel" href="http://www.intel.com">
+ <link rel="help" href="http://dev.w3.org/2006/webapi/FileAPI/#FileReader-interface">
+ <link rel="help" href="http://dev.w3.org/2006/webapi/FileAPI/#file">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div>
+ <p>Test step:</p>
+ <ol>
+ <li>Download <a href="support/blue-100x100.png">blue-100x100.png</a> to local.</li>
+ <li>Select the local file (blue-100x100.png) to run the test.</li>
+ </ol>
+ </div>
+
+ <form name="uploadData">
+ <input type="file" id="fileChooser">
+ </form>
+
+ <div id="log"></div>
+ <script>
+ var fileInput = document.querySelector('#fileChooser');
+ var reader = new FileReader();
+
+ //readType: 1-> ArrayBuffer, 2-> Text, 3-> DataURL
+ var readType = 1;
+
+ setup({
+ explicit_done: true,
+ explicit_timeout: true,
+ });
+
+ on_event(fileInput, "change", function(evt) {
+ reader.readAsArrayBuffer(fileInput.files[0]);
+ });
+
+ on_event(reader, "load", function(evt) {
+ if (readType == 1) {
+ test(function() {
+ assert_true(reader.result instanceof ArrayBuffer, "The result is instanceof ArrayBuffer");
+ }, "Check if the readAsArrayBuffer works");
+
+ readType++;
+ reader.readAsText(fileInput.files[0]);
+ } else if (readType == 2) {
+ test(function() {
+ assert_equals(typeof reader.result, "string", "The result is typeof string");
+ }, "Check if the readAsText works");
+
+ readType++;
+ reader.readAsDataURL(fileInput.files[0]);
+ } else if (readType == 3) {
+ test(function() {
+ assert_equals(typeof reader.result, "string", "The result is typeof string");
+ assert_equals(reader.result.indexOf("data"), 0, "The result starts with 'data'");
+ assert_true(reader.result.indexOf("base64") > 0, "The result contains 'base64'");
+ }, "Check if the readAsDataURL works");
+
+ done();
+ }
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/FileAPI/reading-data-section/filereader_file_img-manual.html b/tests/wpt/web-platform-tests/FileAPI/reading-data-section/filereader_file_img-manual.html
new file mode 100644
index 00000000000..fca42c7fceb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/FileAPI/reading-data-section/filereader_file_img-manual.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>FileAPI Test: filereader_file_img</title>
+ <link rel="author" title="Intel" href="http://www.intel.com">
+ <link rel="help" href="http://dev.w3.org/2006/webapi/FileAPI/#FileReader-interface">
+ <link rel="help" href="http://dev.w3.org/2006/webapi/FileAPI/#file">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div>
+ <p>Test step:</p>
+ <ol>
+ <li>Download <a href="support/blue-100x100.png">blue-100x100.png</a> to local.</li>
+ <li>Select the local file (blue-100x100.png) to run the test.</li>
+ </ol>
+ </div>
+
+ <form name="uploadData">
+ <input type="file" id="fileChooser">
+ </form>
+
+ <div id="log"></div>
+ <script>
+ var fileInput = document.querySelector('#fileChooser');
+ var reader = new FileReader();
+
+ setup({
+ explicit_done: true,
+ explicit_timeout: true,
+ });
+
+ fileInput.addEventListener("change", function(evt) {
+ reader.readAsDataURL(fileInput.files[0]);
+ }, false);
+
+ reader.addEventListener("loadend", function(evt) {
+ test(function () {
+ assert_true(reader.result.indexOf("iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAAqklEQVR42u3RsREAMAgDMe+/M4E7ZkhBoeI9gJWkWpfaeToTECACAkRAgAgIEAEB4gQgAgJEQIAICBABASIgAgJEQIAICBABASIgAgJEQIAICBABASIgAgJEQIAICBABASIgAgJEQIAICBABASIgAgJEQIAICBABASIgAgJEQIAICBABASIgAgJEQIAICBABASIgAgJEQIAICBABASIgQJwARECACAgQ/W4AQauujc8IdAoAAAAASUVORK5CYII=") != -1, "Encoded image")
+ }, "Check if readAsDataURL returns correct image");
+ done();
+ }, false);
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/FileAPI/reading-data-section/filereader_readAsArrayBuffer.html b/tests/wpt/web-platform-tests/FileAPI/reading-data-section/filereader_readAsArrayBuffer.html
new file mode 100644
index 00000000000..31001a51a07
--- /dev/null
+++ b/tests/wpt/web-platform-tests/FileAPI/reading-data-section/filereader_readAsArrayBuffer.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>FileAPI Test: filereader_readAsArrayBuffer</title>
+ <link rel="author" title="Intel" href="http://www.intel.com">
+ <link rel="help" href="http://dev.w3.org/2006/webapi/FileAPI/#readAsArrayBuffer">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+
+ <script>
+ async_test(function() {
+ var blob = new Blob(["TEST"]);
+ var reader = new FileReader();
+
+ reader.onload = this.step_func(function(evt) {
+ assert_equals(reader.result.byteLength, 4, "The byteLength is 4");
+ assert_true(reader.result instanceof ArrayBuffer, "The result is instanceof ArrayBuffer");
+ assert_equals(reader.readyState, reader.DONE);
+ this.done();
+ });
+
+ reader.onloadstart = this.step_func(function(evt) {
+ assert_equals(reader.readyState, reader.LOADING);
+ });
+
+ reader.onprogress = this.step_func(function(evt) {
+ assert_equals(reader.readyState, reader.LOADING);
+ });
+
+ reader.readAsArrayBuffer(blob);
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/FileAPI/reading-data-section/filereader_readAsDataURL.html b/tests/wpt/web-platform-tests/FileAPI/reading-data-section/filereader_readAsDataURL.html
new file mode 100644
index 00000000000..f0a3957e760
--- /dev/null
+++ b/tests/wpt/web-platform-tests/FileAPI/reading-data-section/filereader_readAsDataURL.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>FileAPI Test: filereader_readAsDataURL</title>
+ <link rel="author" title="Intel" href="http://www.intel.com">
+ <link rel="help" href="http://dev.w3.org/2006/webapi/FileAPI/#readAsDataURL">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+
+ <script>
+ async_test(function() {
+ var blob = new Blob(["TEST"]);
+ var reader = new FileReader();
+
+ reader.onload = this.step_func(function(evt) {
+ assert_equals(typeof reader.result, "string", "The result is string");
+ assert_equals(reader.result.indexOf("data:"), 0, "The result attribute starts with 'data'");
+ assert_true(reader.result.indexOf("base64") > 0, "The result attribute contains 'base64'");
+ assert_equals(reader.readyState, reader.DONE);
+ this.done();
+ });
+
+ reader.onloadstart = this.step_func(function(evt) {
+ assert_equals(reader.readyState, reader.LOADING);
+ });
+
+ reader.onprogress = this.step_func(function(evt) {
+ assert_equals(reader.readyState, reader.LOADING);
+ });
+
+ reader.readAsDataURL(blob);
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/FileAPI/reading-data-section/filereader_readAsText.html b/tests/wpt/web-platform-tests/FileAPI/reading-data-section/filereader_readAsText.html
new file mode 100644
index 00000000000..7d639d01114
--- /dev/null
+++ b/tests/wpt/web-platform-tests/FileAPI/reading-data-section/filereader_readAsText.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>FileAPI Test: filereader_readAsText</title>
+ <link rel="author" title="Intel" href="http://www.intel.com">
+ <link rel="help" href="http://dev.w3.org/2006/webapi/FileAPI/#readAsDataText">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+
+ <script>
+ async_test(function() {
+ var blob = new Blob(["TEST"]);
+ var reader = new FileReader();
+
+ reader.onload = this.step_func(function(evt) {
+ assert_equals(typeof reader.result, "string", "The result is typeof string");
+ assert_equals(reader.result, "TEST", "The result is TEST");
+ this.done();
+ });
+
+ reader.onloadstart = this.step_func(function(evt) {
+ assert_equals(reader.readyState, reader.LOADING, "The readyState");
+ });
+
+ reader.onprogress = this.step_func(function(evt) {
+ assert_equals(reader.readyState, reader.LOADING);
+ });
+
+ reader.readAsText(blob);
+ }, "readAsText should correctly read UTF-8.");
+
+ async_test(function() {
+ var blob = new Blob(["TEST"]);
+ var reader = new FileReader();
+ var reader_UTF16 = new FileReader();
+ reader_UTF16.onload = this.step_func(function(evt) {
+ // "TEST" in UTF-8 is 0x54 0x45 0x53 0x54.
+ // Decoded as utf-16 (little-endian), we get 0x4554 0x5453.
+ assert_equals(reader_UTF16.readyState, reader.DONE, "The readyState");
+ assert_equals(reader_UTF16.result, "\u4554\u5453", "The result is not TEST");
+ this.done();
+ });
+ reader_UTF16.readAsText(blob, "UTF-16");
+ }, "readAsText should correctly read UTF-16.");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/FileAPI/reading-data-section/filereader_readystate.html b/tests/wpt/web-platform-tests/FileAPI/reading-data-section/filereader_readystate.html
new file mode 100644
index 00000000000..1586b899505
--- /dev/null
+++ b/tests/wpt/web-platform-tests/FileAPI/reading-data-section/filereader_readystate.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>FileAPI Test: filereader_readystate</title>
+ <link rel="author" title="Intel" href="http://www.intel.com">
+ <link rel="help" href="http://dev.w3.org/2006/webapi/FileAPI/#blobreader-state">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+
+ <script>
+ async_test(function() {
+ var blob = new Blob(["THIS TEST THE READYSTATE WHEN READ BLOB"]);
+ var reader = new FileReader();
+
+ assert_equals(reader.readyState, reader.EMPTY);
+
+ reader.onloadstart = this.step_func(function(evt) {
+ assert_equals(reader.readyState, reader.LOADING);
+ });
+
+ reader.onloadend = this.step_func(function(evt) {
+ assert_equals(reader.readyState, reader.DONE);
+ this.done();
+ });
+
+ reader.readAsDataURL(blob);
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/FileAPI/reading-data-section/filereader_result.html b/tests/wpt/web-platform-tests/FileAPI/reading-data-section/filereader_result.html
new file mode 100644
index 00000000000..957d0337a75
--- /dev/null
+++ b/tests/wpt/web-platform-tests/FileAPI/reading-data-section/filereader_result.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>FileAPI Test: filereader_result</title>
+ <link rel="author" title="Intel" href="http://www.intel.com">
+ <link rel="help" href="http://dev.w3.org/2006/webapi/FileAPI/#filedata-attr">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+
+ <script>
+ var blob;
+ setup(function() {
+ blob = new Blob(["This test the result attribute"]);
+ });
+
+ async_test(function() {
+ var readText = new FileReader();
+ assert_equals(readText.result, null);
+
+ readText.onloadend = this.step_func(function(evt) {
+ assert_equals(typeof readText.result, "string", "The result type is string");
+ assert_equals(readText.result, "This test the result attribute", "The result is correct");
+ this.done();
+ });
+
+ readText.readAsText(blob);
+ }, "readAsText");
+
+ async_test(function() {
+ var readDataURL = new FileReader();
+ assert_equals(readDataURL.result, null);
+
+ readDataURL.onloadend = this.step_func(function(evt) {
+ assert_equals(typeof readDataURL.result, "string", "The result type is string");
+ assert_true(readDataURL.result.indexOf("VGhpcyB0ZXN0IHRoZSByZXN1bHQgYXR0cmlidXRl") != -1, "return the right base64 string");
+ this.done();
+ });
+
+ readDataURL.readAsDataURL(blob);
+ }, "readAsDataURL");
+
+ async_test(function() {
+ var readArrayBuffer = new FileReader();
+ assert_equals(readArrayBuffer.result, null);
+
+ readArrayBuffer.onloadend = this.step_func(function(evt) {
+ assert_true(readArrayBuffer.result instanceof ArrayBuffer, "The result is instanceof ArrayBuffer");
+ this.done();
+ });
+
+ readArrayBuffer.readAsArrayBuffer(blob);
+ }, "readAsArrayBuffer");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/FileAPI/reading-data-section/support/blue-100x100.png b/tests/wpt/web-platform-tests/FileAPI/reading-data-section/support/blue-100x100.png
new file mode 100644
index 00000000000..5748719ff22
--- /dev/null
+++ b/tests/wpt/web-platform-tests/FileAPI/reading-data-section/support/blue-100x100.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/FileAPI/support/Blob.js b/tests/wpt/web-platform-tests/FileAPI/support/Blob.js
new file mode 100644
index 00000000000..1d66f23a604
--- /dev/null
+++ b/tests/wpt/web-platform-tests/FileAPI/support/Blob.js
@@ -0,0 +1,49 @@
+function test_blob(fn, expectations) {
+ var expected = expectations.expected,
+ type = expectations.type,
+ desc = expectations.desc;
+
+ var t = async_test(desc);
+ t.step(function() {
+ var blob = fn();
+ assert_true(blob instanceof Blob);
+ assert_false(blob instanceof File);
+ assert_equals(blob.type, type);
+ assert_equals(blob.size, expected.length);
+
+ var fr = new FileReader();
+ fr.onload = t.step_func_done(function(event) {
+ assert_equals(this.result, expected);
+ }, fr);
+ fr.onerror = t.step_func(function(e) {
+ assert_unreached("got error event on FileReader");
+ });
+ fr.readAsText(blob, "UTF-8");
+ });
+}
+
+function test_blob_binary(fn, expectations) {
+ var expected = expectations.expected,
+ type = expectations.type,
+ desc = expectations.desc;
+
+ var t = async_test(desc);
+ t.step(function() {
+ var blob = fn();
+ assert_true(blob instanceof Blob);
+ assert_false(blob instanceof File);
+ assert_equals(blob.type, type);
+ assert_equals(blob.size, expected.length);
+
+ var fr = new FileReader();
+ fr.onload = t.step_func_done(function(event) {
+ assert_true(this.result instanceof ArrayBuffer,
+ "Result should be an ArrayBuffer");
+ assert_array_equals(new Uint8Array(this.result), expected);
+ }, fr);
+ fr.onerror = t.step_func(function(e) {
+ assert_unreached("got error event on FileReader");
+ });
+ fr.readAsArrayBuffer(blob);
+ });
+}
diff --git a/tests/wpt/web-platform-tests/FileAPI/support/upload.txt b/tests/wpt/web-platform-tests/FileAPI/support/upload.txt
new file mode 100644
index 00000000000..5ab2f8a4323
--- /dev/null
+++ b/tests/wpt/web-platform-tests/FileAPI/support/upload.txt
@@ -0,0 +1 @@
+Hello \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/FileAPI/url/url_createobjecturl_blob.html b/tests/wpt/web-platform-tests/FileAPI/url/url_createobjecturl_blob.html
new file mode 100644
index 00000000000..db6b44180ec
--- /dev/null
+++ b/tests/wpt/web-platform-tests/FileAPI/url/url_createobjecturl_blob.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>FileAPI Test: Creating Blob URL with Blob</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="JunChen Xia" href="mailto:xjconlyme@gmail.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<div id="log"></div>
+
+<script>
+ var blob = new Blob(["Test Blob"]);
+
+ test(function() {
+ var testBlob = window.URL.createObjectURL(blob);
+ assert_equals(typeof testBlob, "string", "Blob URI is typeof string");
+ assert_equals(testBlob.indexOf("blob"), 0, "Blob URI starts with 'blob'");
+ }, "Check if the Blob URI starts with 'blob' using createObjectURL()");
+
+ test(function() {
+ var testBlob = window.URL.createFor(blob);
+ assert_equals(typeof testBlob, "string", "Blob URI is typeof string");
+ assert_equals(testBlob.indexOf("blob"), 0, "Blob URI starts with 'blob'");
+ }, "Check if the Blob URI starts with 'blob' using createFor()");
+</script>
+
diff --git a/tests/wpt/web-platform-tests/FileAPI/url/url_createobjecturl_file-manual.html b/tests/wpt/web-platform-tests/FileAPI/url/url_createobjecturl_file-manual.html
new file mode 100644
index 00000000000..5dcd1d49e7c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/FileAPI/url/url_createobjecturl_file-manual.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>FileAPI Test: Creating Blob URL with File</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="JunChen Xia" href="mailto:xjconlyme@gmail.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<meta name="timeout" content="long">
+
+<div>
+ <p>Test steps:</p>
+ <ol>
+ <li>Download <a href="/images/blue96x96.png">blue96x96.png</a> to local.</li>
+ <li>Select the local file (blue96x96.png) to run the test.</li>
+ </ol>
+</div>
+
+<form name="uploadData">
+ <input type="file" id="fileChooser">
+</form>
+
+<div id="log"></div>
+
+<script>
+ async_test(function(t) {
+ var fileInput = document.querySelector('#fileChooser');
+
+ fileInput.onchange = t.step_func(function(e) {
+ var blobURL, file = fileInput.files[0];
+
+ test(function() {
+ assert_true(file instanceof File, "FileList contains File");
+ }, "Check if FileList contains File");
+
+ test(function() {
+ blobURL = window.URL.createObjectURL(file);
+ assert_equals(typeof blobURL, "string", "Blob URL is type of string");
+ assert_equals(blobURL.indexOf("blob"), 0, "Blob URL's scheme is blob");
+ }, "Check if URL.createObjectURL(File) returns a Blob URL");
+
+ test(function() {
+ blobURL = window.URL.createFor(file);
+ assert_equals(typeof blobURL, "string", "Blob URL is type of string");
+ assert_equals(blobURL.indexOf("blob"), 0, "Blob URL's scheme is blob");
+ }, "Check if URL.createFor(File) returns a Blob URL");
+
+ t.done();
+ });
+ });
+</script>
+
diff --git a/tests/wpt/web-platform-tests/FileAPI/url/url_createobjecturl_file_img-manual.html b/tests/wpt/web-platform-tests/FileAPI/url/url_createobjecturl_file_img-manual.html
new file mode 100644
index 00000000000..534c1de9968
--- /dev/null
+++ b/tests/wpt/web-platform-tests/FileAPI/url/url_createobjecturl_file_img-manual.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>FileAPI Test: Creating Blob URL with File as image source</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="JunChen Xia" href="mailto:xjconlyme@gmail.com">
+
+<div>
+ <p>Test steps:</p>
+ <ol>
+ <li>Download <a href="/images/blue96x96.png">blue96x96.png</a> to local.</li>
+ <li>Select the local file (blue96x96.png) to run the test.</li>
+ </ol>
+ <p>Pass/fail criteria:</p>
+ <p>Test passes if there is a filled blue square.</p>
+
+ <p><input type="file" accept="image/*" id="fileChooser"></p>
+ <p><img id="displayImage"></img></p>
+</div>
+
+<script>
+ var fileInput = document.querySelector("#fileChooser");
+ var img = document.querySelector("#displayImage");
+
+ fileInput.addEventListener("change", function(evt) {
+ img.src = window.URL.createObjectURL(fileInput.files[0]);
+ }, false);
+</script>
+
diff --git a/tests/wpt/web-platform-tests/FileAPI/url/url_xmlhttprequest.html b/tests/wpt/web-platform-tests/FileAPI/url/url_xmlhttprequest.html
new file mode 100644
index 00000000000..7a86cdd1e80
--- /dev/null
+++ b/tests/wpt/web-platform-tests/FileAPI/url/url_xmlhttprequest.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>FileAPI Test: Creating Blob URL via XMLHttpRequest</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="JunChen Xia" href="mailto:xjconlyme@gmail.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<div id="log"></div>
+
+<script>
+ async_test(function () {
+ var http = new XMLHttpRequest();
+ http.open("GET", "/images/blue96x96.png", true);
+ http.responseType = "blob";
+ http.onloadend = this.step_func(function(evt) {
+ var blobURI = window.URL.createObjectURL(http.response);
+ assert_true(http.response instanceof Blob, "XMLHttpRequest returns instanceof Blob");
+ assert_equals(typeof blobURI, "string", "Blob URI is typeof string");
+ assert_equals(blobURI.indexOf("blob"), 0, "Blob URI starts with 'blob'");
+ assert_equals(http.status, 200, "The status is 200");
+ assert_equals(http.statusText, "OK", "The status text is OK when XMLHttpRequest returns correct blob");
+ assert_equals(http.getResponseHeader("Content-Type"), "image/png", "The content type is image/png when set the respnose blob");
+ this.done();
+ });
+ http.send();
+ });
+</script>
+
diff --git a/tests/wpt/web-platform-tests/FileAPI/url/url_xmlhttprequest_img-ref.html b/tests/wpt/web-platform-tests/FileAPI/url/url_xmlhttprequest_img-ref.html
new file mode 100644
index 00000000000..7d7390442d3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/FileAPI/url/url_xmlhttprequest_img-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>FileAPI Reference File</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="JunChen Xia" href="mailto:xjconlyme@gmail.com">
+
+<p>Test passes if there is a filled blue square.</p>
+
+<p>
+ <img id="fileDisplay" src="/images/blue96x96.png">
+</p>
+
diff --git a/tests/wpt/web-platform-tests/FileAPI/url/url_xmlhttprequest_img.html b/tests/wpt/web-platform-tests/FileAPI/url/url_xmlhttprequest_img.html
new file mode 100644
index 00000000000..7f26633d81e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/FileAPI/url/url_xmlhttprequest_img.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<meta charset="utf-8">
+<title>FileAPI Test: Creating Blob URL via XMLHttpRequest as image source</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="author" title="JunChen Xia" href="mailto:xjconlyme@gmail.com">
+<link rel="match" href="url_xmlhttprequest_img-ref.html">
+
+<p>Test passes if there is a filled blue square.</p>
+
+<p>
+ <img id="fileDisplay">
+</p>
+
+<script src="/common/reftest-wait.js"></script>
+<script>
+ var http = new XMLHttpRequest();
+ http.open("GET", "/images/blue96x96.png", true);
+ http.responseType = "blob";
+ http.onloadend = function() {
+ var fileDisplay = document.querySelector("#fileDisplay");
+ fileDisplay.src = window.URL.createObjectURL(http.response);
+ takeScreenshot();
+ };
+ http.send();
+</script>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/IndexedDB/README.md b/tests/wpt/web-platform-tests/IndexedDB/README.md
new file mode 100644
index 00000000000..6b636d5f1a4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/README.md
@@ -0,0 +1,8 @@
+This directory contains the Indexed Database API test suite.
+
+To run the tests in this test suite within a browser, go to: <http://w3c-test.org/IndexedDB/>.
+
+The latest Editor's Draft of Indexed Database API is: <http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html>.
+
+The latest W3C Technical Report of Indexed Database API is: <http://www.w3.org/TR/IndexedDB/>.
+
diff --git a/tests/wpt/web-platform-tests/IndexedDB/abort-in-initial-upgradeneeded.html b/tests/wpt/web-platform-tests/IndexedDB/abort-in-initial-upgradeneeded.html
new file mode 100644
index 00000000000..6330ecb02e9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/abort-in-initial-upgradeneeded.html
@@ -0,0 +1,35 @@
+<!doctype html>
+<!-- Submitted from TestTWF Paris -->
+<title>Test that an abort in the initial upgradeneeded sets version back to 0</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+
+var db, open_rq = createdb(async_test(), undefined, 2);
+
+open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ assert_equals(db.version, 2);
+ transaction = e.target.transaction;
+ transaction.oncomplete = fail(this, "unexpected transaction.complete");
+ transaction.onabort = function(e) {
+ assert_equals(e.target.db.version, 0);
+ }
+ db.onabort = function() {}
+
+ transaction.abort();
+}
+
+open_rq.onerror = function(e) {
+ assert_equals(open_rq, e.target);
+ assert_equals(e.target.result, undefined);
+ assert_equals(e.target.error.name, "AbortError");
+ assert_equals(db.version, 0);
+ assert_equals(open_rq.transaction, null);
+ this.done();
+}
+</script>
+
+<div id=log></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/close-in-upgradeneeded.html b/tests/wpt/web-platform-tests/IndexedDB/close-in-upgradeneeded.html
new file mode 100644
index 00000000000..eda823a21f1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/close-in-upgradeneeded.html
@@ -0,0 +1,39 @@
+<!doctype html>
+<!-- Submitted from TestTWF Paris -->
+<title>When db.close is called in upgradeneeded, the db is cleaned up on refresh</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+
+var open_rq = createdb(async_test())
+var sawTransactionComplete = false
+
+open_rq.onupgradeneeded = function(e) {
+ db = e.target.result
+ assert_equals(db.version, 1)
+
+ db.createObjectStore('os')
+ db.close()
+
+ e.target.transaction.oncomplete = function() { sawTransactionComplete = true }
+}
+
+open_rq.onerror = function(e) {
+ assert_true(sawTransactionComplete, "saw transaction.complete")
+
+ assert_equals(e.target.error.name, 'AbortError')
+ assert_equals(e.result, undefined)
+
+ assert_true(!!db)
+ assert_equals(db.version, 1)
+ assert_equals(db.objectStoreNames.length, 1)
+ assert_throws("InvalidStateError", function() { db.transaction('os') })
+
+ this.done()
+}
+
+</script>
+
+<div id=log></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/cursor-overloads.htm b/tests/wpt/web-platform-tests/IndexedDB/cursor-overloads.htm
new file mode 100644
index 00000000000..343e5a4cc1f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/cursor-overloads.htm
@@ -0,0 +1,88 @@
+<!--
+Test converted from WebKit:
+http://trac.webkit.org/browser/trunk/LayoutTests/storage/indexeddb/cursor-overloads.html
+-->
+
+<!DOCTYPE html>
+<!-- Submitted from TestTWF Paris -->
+<meta charset=utf-8>
+<title>Validate the overloads of IDBObjectStore.openCursor(), IDBIndex.openCursor() and IDBIndex.openKeyCursor()</title>
+<link rel=author href="mailto:romain.huet@gmail.com" title="Romain Huet">
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+
+ var db, trans, store, index;
+ var t = async_test();
+
+ var request = createdb(t);
+ request.onupgradeneeded = function(e) {
+ db = request.result;
+ store = db.createObjectStore('store');
+ index = store.createIndex('index', 'value');
+ store.put({value: 0}, 0);
+ trans = request.transaction;
+ trans.oncomplete = verifyOverloads;
+ };
+
+ function verifyOverloads() {
+ trans = db.transaction('store');
+ store = trans.objectStore('store');
+ index = store.index('index');
+
+ checkCursorDirection("store.openCursor()", "next");
+ checkCursorDirection("store.openCursor(0)", "next");
+ checkCursorDirection("store.openCursor(0, 'next')", "next");
+ checkCursorDirection("store.openCursor(0, 'nextunique')", "nextunique");
+ checkCursorDirection("store.openCursor(0, 'prev')", "prev");
+ checkCursorDirection("store.openCursor(0, 'prevunique')", "prevunique");
+
+ checkCursorDirection("store.openCursor(IDBKeyRange.only(0))", "next");
+ checkCursorDirection("store.openCursor(IDBKeyRange.only(0), 'next')", "next");
+ checkCursorDirection("store.openCursor(IDBKeyRange.only(0), 'nextunique')", "nextunique");
+ checkCursorDirection("store.openCursor(IDBKeyRange.only(0), 'prev')", "prev");
+ checkCursorDirection("store.openCursor(IDBKeyRange.only(0), 'prevunique')", "prevunique");
+
+ checkCursorDirection("index.openCursor()", "next");
+ checkCursorDirection("index.openCursor(0)", "next");
+ checkCursorDirection("index.openCursor(0, 'next')", "next");
+ checkCursorDirection("index.openCursor(0, 'nextunique')", "nextunique");
+ checkCursorDirection("index.openCursor(0, 'prev')", "prev");
+ checkCursorDirection("index.openCursor(0, 'prevunique')", "prevunique");
+
+ checkCursorDirection("index.openCursor(IDBKeyRange.only(0))", "next");
+ checkCursorDirection("index.openCursor(IDBKeyRange.only(0), 'next')", "next");
+ checkCursorDirection("index.openCursor(IDBKeyRange.only(0), 'nextunique')", "nextunique");
+ checkCursorDirection("index.openCursor(IDBKeyRange.only(0), 'prev')", "prev");
+ checkCursorDirection("index.openCursor(IDBKeyRange.only(0), 'prevunique')", "prevunique");
+
+ checkCursorDirection("index.openKeyCursor()", "next");
+ checkCursorDirection("index.openKeyCursor(0)", "next");
+ checkCursorDirection("index.openKeyCursor(0, 'next')", "next");
+ checkCursorDirection("index.openKeyCursor(0, 'nextunique')", "nextunique");
+ checkCursorDirection("index.openKeyCursor(0, 'prev')", "prev");
+ checkCursorDirection("index.openKeyCursor(0, 'prevunique')", "prevunique");
+
+ checkCursorDirection("index.openKeyCursor(IDBKeyRange.only(0))", "next");
+ checkCursorDirection("index.openKeyCursor(IDBKeyRange.only(0), 'next')", "next");
+ checkCursorDirection("index.openKeyCursor(IDBKeyRange.only(0), 'nextunique')", "nextunique");
+ checkCursorDirection("index.openKeyCursor(IDBKeyRange.only(0), 'prev')", "prev");
+ checkCursorDirection("index.openKeyCursor(IDBKeyRange.only(0), 'prevunique')", "prevunique");
+
+ t.done();
+ }
+
+ function checkCursorDirection(statement, direction) {
+ request = eval(statement);
+ request.onsuccess = function(event) {
+ assert_not_equals(event.target.result, null, "Check the result is not null")
+ assert_equals(event.target.result.direction, direction, "Check the result direction");
+ };
+ }
+
+</script>
+
+<div id=log></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idb_webworkers.htm b/tests/wpt/web-platform-tests/IndexedDB/idb_webworkers.htm
new file mode 100644
index 00000000000..dba3a93f120
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idb_webworkers.htm
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<title>IndexedDB inside of a WebWorker </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db, count = 0,
+ t = async_test();
+
+ t.step(function() {
+ var worker = new Worker("idbworker.js");
+ worker.onmessage = t.step_func(function (e) {
+ switch(count) {
+ case 0:
+ assert_equals(e.data, true, 'worker has idb object')
+ break
+
+ case 1:
+ assert_equals(e.data, "test", "get(1) in worker")
+ t.done()
+ }
+
+ count++
+ });
+
+ worker.postMessage(1);
+ })
+
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor-advance-continue-async.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor-advance-continue-async.htm
new file mode 100644
index 00000000000..d1b6af3e189
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor-advance-continue-async.htm
@@ -0,0 +1,186 @@
+<!DOCTYPE html>
+<title>IDBCursor asyncness</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ var db, open;
+
+ setup(function() {
+ open = indexedDB.open('testdb-' + new Date().getTime());
+ open.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test");
+ objStore.createIndex("index", "");
+
+ objStore.add("data", 1);
+ objStore.add("data2", 2);
+ };
+ },
+ { explicit_done: true });
+
+
+ open.onsuccess = function() {
+
+
+ async_test(document.title + " - advance").step(function(e) {
+ var count = 0;
+ var rq = db.transaction("test").objectStore("test").openCursor();
+
+ rq.onsuccess = this.step_func(function(e) {
+ if (!e.target.result) {
+ assert_equals(count, 2, 'count');
+ this.done();
+ return;
+ }
+ var cursor = e.target.result;
+
+ switch(count) {
+ case 0:
+ assert_equals(cursor.value, "data")
+ assert_equals(cursor.key, 1)
+ cursor.advance(1)
+ assert_equals(cursor.value, "data")
+ assert_equals(cursor.key, 1)
+ break
+
+ case 1:
+ assert_equals(cursor.value, "data2")
+ assert_equals(cursor.key, 2)
+ cursor.advance(1)
+ assert_equals(cursor.value, "data2")
+ assert_equals(cursor.key, 2)
+ break
+
+ default:
+ assert_unreached("Unexpected count: " + count)
+ }
+
+ count++;
+ });
+ rq.onerror = fail(this, "unexpected error")
+ });
+
+
+ async_test(document.title + " - continue").step(function(e) {
+ var count = 0;
+ var rq = db.transaction("test").objectStore("test").index("index").openCursor();
+
+ rq.onsuccess = this.step_func(function(e) {
+ if (!e.target.result) {
+ assert_equals(count, 2, 'count');
+ this.done();
+ return;
+ }
+ var cursor = e.target.result;
+
+ switch(count) {
+ case 0:
+ assert_equals(cursor.value, "data")
+ assert_equals(cursor.key, "data")
+ assert_equals(cursor.primaryKey, 1)
+ cursor.continue("data2")
+ assert_equals(cursor.value, "data")
+ assert_equals(cursor.key, "data")
+ assert_equals(cursor.primaryKey, 1)
+ break
+
+ case 1:
+ assert_equals(cursor.value, "data2")
+ assert_equals(cursor.key, "data2")
+ assert_equals(cursor.primaryKey, 2)
+ cursor.continue()
+ assert_equals(cursor.value, "data2")
+ assert_equals(cursor.key, "data2")
+ assert_equals(cursor.primaryKey, 2)
+ break
+
+ default:
+ assert_unreached("Unexpected count: " + count)
+ }
+
+ count++;
+ });
+ rq.onerror = fail(this, "unexpected error")
+ });
+
+
+ async_test(document.title + " - fresh advance still async").step(function(e) {
+ var count = 0;
+ var rq = db.transaction("test").objectStore("test").index("index").openCursor();
+
+ rq.onsuccess = this.step_func(function(e) {
+ if (!e.target.result) {
+ assert_equals(count, 2, 'count');
+ this.done();
+ return;
+ }
+ var cursor = e.target.result;
+ cursor.advance(1)
+
+ switch(count) {
+ case 0:
+ assert_equals(cursor.value, "data")
+ assert_equals(cursor.key, "data")
+ assert_equals(cursor.primaryKey, 1)
+ break
+
+ case 1:
+ assert_equals(cursor.value, "data2")
+ assert_equals(cursor.key, "data2")
+ assert_equals(cursor.primaryKey, 2)
+ break
+
+ default:
+ assert_unreached("Unexpected count: " + count)
+ }
+
+ count++;
+ });
+ rq.onerror = fail(this, "unexpected error")
+ });
+
+
+ async_test(document.title + " - fresh continue still async").step(function(e) {
+ var count = 0;
+ var rq = db.transaction("test").objectStore("test").openCursor();
+
+ rq.onsuccess = this.step_func(function(e) {
+ if (!e.target.result) {
+ assert_equals(count, 2, 'count');
+ this.done();
+ return;
+ }
+ var cursor = e.target.result;
+ cursor.continue()
+
+ switch(count) {
+ case 0:
+ assert_equals(cursor.value, "data")
+ assert_equals(cursor.key, 1)
+ break
+
+ case 1:
+ assert_equals(cursor.value, "data2")
+ assert_equals(cursor.key, 2)
+ break
+
+ default:
+ assert_unreached("Unexpected count: " + count)
+ }
+
+ count++;
+ });
+ rq.onerror = fail(this, "unexpected error")
+ });
+
+ // Stop blocking the testing system from hereon
+ done();
+ }
+
+</script>
+
+<div id=log></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor-advance-invalid.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor-advance-invalid.htm
new file mode 100644
index 00000000000..dda216b7531
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor-advance-invalid.htm
@@ -0,0 +1,188 @@
+<!DOCTYPE html>
+<title>IDBCursor.advance() - invalid</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBCursor-advance-void-unsigned-long-count">
+<link rel=assert title="If the value for count is 0 (zero) or a negative number, this method must throw a JavaScript TypeError exception.">
+<link rel=assert title="TypeError The value passed into the count parameter was zero or a negative number.">
+<link rel=assert title="InvalidStateError The cursor is currently being iterated, or has iterated past its end.">
+<link rel=assert title="Calling this method more than once before new cursor data has been loaded is not allowed and results in a DOMException of type InvalidStateError being thrown. For example, calling advance() twice from the same onsuccess handler results in a DOMException of type InvalidStateError being thrown on the second call.">
+<link rel=assert title="Before this method returns, unless an exception was thrown, it sets the got value flag on the cursor to false.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ var db, open;
+
+ setup(function() {
+ open = indexedDB.open('testdb-' + new Date().getTime());
+ open.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test");
+ objStore.createIndex("index", "");
+
+ objStore.add("data", 1);
+ objStore.add("data2", 2);
+ };
+ },
+ { explicit_done: true });
+
+
+ open.onsuccess = function() {
+
+ async_test(document.title + " - attempt to call advance twice").step(function(e) {
+ var count = 0;
+ var rq = db.transaction("test").objectStore("test").index("index").openCursor();
+
+ rq.onsuccess = this.step_func(function(e) {
+ if (!e.target.result) {
+ assert_equals(count, 2, 'count');
+ this.done();
+ return;
+ }
+ var cursor = e.target.result;
+
+ cursor.advance(1);
+
+ // Second try
+ assert_throws('InvalidStateError',
+ function() { cursor.advance(1); }, 'second advance');
+
+ assert_throws('InvalidStateError',
+ function() { cursor.advance(3); }, 'third advance');
+
+ count++;
+ });
+ rq.onerror = fail(this, "unexpected error")
+ });
+
+
+ async_test(document.title + " - pass something other than number").step(function(e) {
+ var rq = db.transaction("test").objectStore("test").index("index").openCursor();
+
+ rq.onsuccess = this.step_func(function(e) {
+ var cursor = e.target.result;
+
+ assert_throws({ name: "TypeError" },
+ function() { cursor.advance(document); });
+
+ assert_throws({ name: "TypeError" },
+ function() { cursor.advance({}); });
+
+ assert_throws({ name: "TypeError" },
+ function() { cursor.advance([]); });
+
+ assert_throws({ name: "TypeError" },
+ function() { cursor.advance(""); });
+
+ assert_throws({ name: "TypeError" },
+ function() { cursor.advance("1 2"); });
+
+ this.done();
+ });
+ rq.onerror = fail(this, "unexpected error")
+ });
+
+
+ async_test(document.title + " - pass null/undefined").step(function(e) {
+ var rq = db.transaction("test").objectStore("test").index("index").openCursor();
+
+ rq.onsuccess = this.step_func(function(e) {
+ var cursor = e.target.result;
+
+ assert_throws({ name: "TypeError" },
+ function() { cursor.advance(null); });
+
+ assert_throws({ name: "TypeError" },
+ function() { cursor.advance(undefined); });
+
+ var myvar = null;
+ assert_throws({ name: "TypeError" },
+ function() { cursor.advance(myvar); });
+
+ this.done();
+ });
+ rq.onerror = fail(this, "unexpected error")
+ });
+
+
+ async_test(document.title + " - missing argument").step(function(e) {
+ var rq = db.transaction("test").objectStore("test").index("index").openCursor();
+
+ rq.onsuccess = this.step_func(function(e) {
+ var cursor = e.target.result;
+
+ assert_throws({ name: "TypeError" },
+ function() { cursor.advance(); });
+
+ this.done();
+ });
+ rq.onerror = fail(this, "unexpected error")
+ });
+
+
+ async_test(document.title + " - pass negative numbers").step(function(e) {
+ var rq = db.transaction("test").objectStore("test").index("index").openCursor();
+
+ rq.onsuccess = this.step_func(function(e) {
+ var cursor = e.target.result;
+
+ assert_throws({ name: "TypeError" },
+ function() { cursor.advance(-1); });
+
+ assert_throws({ name: "TypeError" },
+ function() { cursor.advance(NaN); });
+
+ assert_throws({ name: "TypeError" },
+ function() { cursor.advance(0); });
+
+ assert_throws({ name: "TypeError" },
+ function() { cursor.advance(-0); });
+
+ assert_throws({ name: "TypeError" },
+ function() { cursor.advance(Infinity); });
+
+ assert_throws({ name: "TypeError" },
+ function() { cursor.advance(-Infinity); });
+
+ var myvar = -999999;
+ assert_throws({ name: "TypeError" },
+ function() { cursor.advance(myvar); });
+
+ this.done();
+ });
+ rq.onerror = fail(this, "unexpected error")
+ });
+
+
+ async_test(document.title + " - got value not set on exception").step(function(e) {
+ var count = 0;
+ var rq = db.transaction("test").objectStore("test").index("index").openCursor();
+
+ rq.onsuccess = this.step_func(function(e) {
+ var cursor = e.target.result;
+ if (!cursor)
+ {
+ assert_equals(count, 2, "count runs");
+ this.done();
+ return;
+ }
+
+ assert_throws({ name: "TypeError" },
+ function() { cursor.advance(0); });
+
+ cursor.advance(1);
+ count++;
+ });
+ rq.onerror = fail(this, "unexpected error")
+ });
+
+
+ // Stop blocking the testing system from hereon
+ done();
+ }
+
+</script>
+
+<div id=log></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor-advance.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor-advance.htm
new file mode 100644
index 00000000000..f4ecbc0e5aa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor-advance.htm
@@ -0,0 +1,243 @@
+<!DOCTYPE html>
+<title>IDBCursor.advance()</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ var db, open;
+
+ setup(function() {
+ open = indexedDB.open("testdb-" + new Date().getTime());
+ open.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test");
+ objStore.createIndex("index", "");
+
+ objStore.add("cupcake", 5);
+ objStore.add("pancake", 3); // Yes, it is intended
+ objStore.add("pie", 1);
+ objStore.add("pie", 4);
+ objStore.add("taco", 2);
+ };
+ },
+ { explicit_done: true });
+
+
+ open.onsuccess = function() {
+
+ async_test(document.title + " - advances").step(function(e) {
+ var count = 0;
+ var rq = db.transaction("test").objectStore("test").index("index").openCursor();
+
+ rq.onsuccess = this.step_func(function(e) {
+ if (!e.target.result) {
+ assert_equals(count, 3, "count");
+ this.done();
+ return;
+ }
+ var cursor = e.target.result;
+
+ switch(count) {
+ case 0:
+ assert_equals(cursor.value, "cupcake");
+ assert_equals(cursor.primaryKey, 5);
+ break;
+
+ case 1:
+ assert_equals(cursor.value, "pie");
+ assert_equals(cursor.primaryKey, 1);
+ break;
+
+ case 2:
+ assert_equals(cursor.value, "taco");
+ assert_equals(cursor.primaryKey, 2);
+ break;
+
+ default:
+ assert_unreached("Unexpected count: " + count);
+ }
+
+ count++;
+ cursor.advance(2);
+ });
+ rq.onerror = fail(this, "unexpected error")
+ });
+
+ async_test(document.title + " - advances backwards").step(function(e) {
+ var count = 0;
+ var rq = db.transaction("test").objectStore("test").index("index").openCursor(null, "prev");
+
+ rq.onsuccess = this.step_func(function(e) {
+ if (!e.target.result) {
+ assert_equals(count, 3, "count");
+ this.done();
+ return;
+ }
+ var cursor = e.target.result;
+
+ switch(count) {
+ case 0:
+ assert_equals(cursor.value, "taco");
+ assert_equals(cursor.primaryKey, 2);
+ break;
+
+ case 1:
+ assert_equals(cursor.value, "pie");
+ assert_equals(cursor.primaryKey, 1);
+ break;
+
+ case 2:
+ assert_equals(cursor.value, "cupcake");
+ assert_equals(cursor.primaryKey, 5);
+ break;
+
+ default:
+ assert_unreached("Unexpected count: " + count);
+ }
+
+ count++;
+ cursor.advance(2);
+ });
+ rq.onerror = fail(this, "unexpected error")
+ });
+
+ async_test(document.title + " - skip far forward").step(function(e) {
+ var count = 0;
+ var rq = db.transaction("test").objectStore("test").index("index")
+ .openCursor();
+
+ rq.onsuccess = this.step_func(function(e) {
+ if (!e.target.result) {
+ assert_equals(count, 1, "count");
+ this.done();
+ return;
+ }
+ var cursor = e.target.result;
+
+ switch(count) {
+ case 0:
+ assert_equals(cursor.value, "cupcake");
+ assert_equals(cursor.primaryKey, 5);
+ break;
+
+ default:
+ assert_unreached("Unexpected count: " + count);
+ }
+
+ count++;
+ cursor.advance(100000);
+ });
+ rq.onerror = fail(this, "unexpected error")
+ });
+
+
+ async_test(document.title + " - within range").step(function(e) {
+ var count = 0;
+ var rq = db.transaction("test").objectStore("test").index("index")
+ .openCursor(IDBKeyRange.lowerBound("cupcake", true));
+
+ rq.onsuccess = this.step_func(function(e) {
+ if (!e.target.result) {
+ assert_equals(count, 2, "count");
+ this.done();
+ return;
+ }
+ var cursor = e.target.result;
+
+ switch(count) {
+ case 0:
+ assert_equals(cursor.value, "pancake");
+ assert_equals(cursor.primaryKey, 3);
+ break;
+
+ case 1:
+ assert_equals(cursor.value, "pie");
+ assert_equals(cursor.primaryKey, 4);
+ break;
+
+ default:
+ assert_unreached("Unexpected count: " + count);
+ }
+
+ count++;
+ cursor.advance(2);
+ });
+ rq.onerror = fail(this, "unexpected error")
+ });
+
+
+ async_test(document.title + " - within single key range").step(function(e) {
+ var count = 0;
+ var rq = db.transaction("test").objectStore("test").index("index")
+ .openCursor("pancake");
+
+ rq.onsuccess = this.step_func(function(e) {
+ if (!e.target.result) {
+ assert_equals(count, 1, "count");
+ this.done();
+ return;
+ }
+ var cursor = e.target.result;
+
+ switch(count) {
+ case 0:
+ assert_equals(cursor.value, "pancake");
+ assert_equals(cursor.primaryKey, 3);
+ break;
+
+ default:
+ assert_unreached("Unexpected count: " + count);
+ }
+
+ count++;
+ cursor.advance(1);
+ });
+ rq.onerror = fail(this, "unexpected error")
+ });
+
+
+ async_test(document.title + " - within single key range, with several results").step(function(e) {
+ var count = 0;
+ var rq = db.transaction("test").objectStore("test").index("index")
+ .openCursor("pie");
+
+ rq.onsuccess = this.step_func(function(e) {
+ if (!e.target.result) {
+ assert_equals(count, 2, "count");
+ this.done();
+ return;
+ }
+ var cursor = e.target.result;
+
+ switch(count) {
+ case 0:
+ assert_equals(cursor.value, "pie");
+ assert_equals(cursor.primaryKey, 1);
+ break;
+
+ case 1:
+ assert_equals(cursor.value, "pie");
+ assert_equals(cursor.primaryKey, 4);
+ break;
+
+ default:
+ assert_unreached("Unexpected count: " + count);
+ }
+
+ count++;
+ cursor.advance(1);
+ });
+ rq.onerror = fail(this, "unexpected error")
+ });
+
+
+ // Stop blocking the testing system from hereon
+ done();
+ }
+
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor-continue.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor-continue.htm
new file mode 100644
index 00000000000..968cd9cbd09
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor-continue.htm
@@ -0,0 +1,240 @@
+<!DOCTYPE html>
+<title>IDBCursor.continue()</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBCursor-continue-void-any-key">
+<link rel=assert title="The next key to position this cursor at">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ var db, open;
+ var store = [ { value: "cupcake", key: 5 },
+ { value: "pancake", key: 3 },
+ { value: "pie", key: 1 },
+ { value: "pie", key: 4 },
+ { value: "taco", key: 2 } ];
+
+ setup(function() {
+ open = indexedDB.open('testdb-' + new Date().getTime());
+ open.onupgradeneeded = function(e) {
+ var os, i;
+ db = e.target.result;
+ os = db.createObjectStore("test");
+ os.createIndex("index", "");
+
+ for (i = 0; i < store.length; i++)
+ os.add(store[i].value, store[i].key);
+ };
+ },
+ { explicit_done: true });
+
+
+ open.onsuccess = function() {
+
+
+ async_test(document.title + " - continues").step(function(e) {
+ var count = 0;
+ var rq = db.transaction("test").objectStore("test").index("index").openCursor();
+
+ rq.onsuccess = this.step_func(function(e) {
+ if (!e.target.result) {
+ assert_equals(count, 5, 'count');
+ this.done();
+ return;
+ }
+ var cursor = e.target.result;
+
+ assert_equals(cursor.value, store[count].value);
+ assert_equals(cursor.primaryKey, store[count].key);
+
+ cursor.continue();
+
+ count++;
+ });
+ rq.onerror = fail(this, "unexpected error")
+ });
+
+
+ async_test(document.title + " - with given key").step(function(e) {
+ var count = 0;
+ var rq = db.transaction("test").objectStore("test").index("index").openCursor();
+
+ rq.onsuccess = this.step_func(function(e) {
+ if (!e.target.result) {
+ assert_equals(count, 3, 'count');
+ this.done();
+ return;
+ }
+ var cursor = e.target.result;
+
+ switch(count) {
+ case 0:
+ assert_equals(cursor.value, "cupcake");
+ assert_equals(cursor.primaryKey, 5);
+ cursor.continue("pie");
+ break;
+
+ case 1:
+ assert_equals(cursor.value, "pie");
+ assert_equals(cursor.primaryKey, 1);
+ cursor.continue("taco");
+ break;
+
+ case 2:
+ assert_equals(cursor.value, "taco");
+ assert_equals(cursor.primaryKey, 2);
+ cursor.continue();
+ break;
+
+ default:
+ assert_unreached("Unexpected count: " + count);
+ }
+
+ count++;
+ });
+ rq.onerror = fail(this, "unexpected error")
+ });
+
+
+ async_test(document.title + " - skip far forward").step(function(e) {
+ var count = 0;
+ var rq = db.transaction("test").objectStore("test").index("index")
+ .openCursor();
+
+ rq.onsuccess = this.step_func(function(e) {
+ if (!e.target.result) {
+ assert_equals(count, 1, 'count');
+ this.done();
+ return;
+ }
+ var cursor = e.target.result;
+
+ switch(count) {
+ case 0:
+ assert_equals(cursor.value, "cupcake");
+ assert_equals(cursor.primaryKey, 5);
+ break;
+
+ default:
+ assert_unreached("Unexpected count: " + count);
+ }
+
+ count++;
+ cursor.continue([]); // Arrays are always bigger than strings
+
+ });
+ rq.onerror = fail(this, "unexpected error2")
+ });
+
+
+ async_test(document.title + " - within range").step(function(e) {
+ var count = 0;
+ var rq = db.transaction("test").objectStore("test").index("index")
+ .openCursor(IDBKeyRange.lowerBound("cupcake", true));
+
+ rq.onsuccess = this.step_func(function(e) {
+ if (!e.target.result) {
+ assert_equals(count, 2, 'count');
+ this.done();
+ return;
+ }
+ var cursor = e.target.result;
+
+ switch(count) {
+ case 0:
+ assert_equals(cursor.value, "pancake");
+ assert_equals(cursor.primaryKey, 3);
+ cursor.continue("pie");
+ break;
+
+ case 1:
+ assert_equals(cursor.value, "pie");
+ assert_equals(cursor.primaryKey, 1);
+ cursor.continue("zzz");
+ break;
+
+ default:
+ assert_unreached("Unexpected count: " + count);
+ }
+
+ count++;
+ });
+ rq.onerror = fail(this, "unexpected error1")
+ });
+
+
+ async_test(document.title + " - within single key range").step(function(e) {
+ var count = 0;
+ var rq = db.transaction("test").objectStore("test").index("index")
+ .openCursor("pancake");
+
+ rq.onsuccess = this.step_func(function(e) {
+ if (!e.target.result) {
+ assert_equals(count, 1, 'count');
+ this.done();
+ return;
+ }
+ var cursor = e.target.result;
+
+ switch(count) {
+ case 0:
+ assert_equals(cursor.value, "pancake");
+ assert_equals(cursor.primaryKey, 3);
+ cursor.continue("pie");
+ break;
+
+ default:
+ assert_unreached("Unexpected count: " + count);
+ }
+
+ count++;
+ });
+ rq.onerror = fail(this, "unexpected error1")
+ });
+
+
+ async_test(document.title + " - within single key range, with several results").step(function(e) {
+ var count = 0;
+ var rq = db.transaction("test").objectStore("test").index("index")
+ .openCursor("pie");
+
+ rq.onsuccess = this.step_func(function(e) {
+ if (!e.target.result) {
+ assert_equals(count, 2, 'count');
+ this.done();
+ return;
+ }
+ var cursor = e.target.result;
+
+ switch(count) {
+ case 0:
+ assert_equals(cursor.value, "pie");
+ assert_equals(cursor.primaryKey, 1);
+ cursor.continue();
+ break;
+
+ case 1:
+ assert_equals(cursor.value, "pie");
+ assert_equals(cursor.primaryKey, 4);
+ cursor.continue();
+ break;
+
+ default:
+ assert_unreached("Unexpected count: " + count);
+ }
+
+ count++;
+ });
+ rq.onerror = fail(this, "unexpected error1")
+ });
+
+
+ // Stop blocking the testing system from hereon
+ done();
+ }
+
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor-direction-index-keyrange.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor-direction-index-keyrange.htm
new file mode 100644
index 00000000000..c3f9340370d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor-direction-index-keyrange.htm
@@ -0,0 +1,82 @@
+<!DOCTYPE html>
+<title>IDBCursor direction - index with keyrange</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#cursor-iteration-operation">
+<link rel=assert title='If direction is "next", let found record be the first record in records which satisfy all of the following requirements'>
+<link rel=assert title="If position is defined, and source is an index, the record's key is equal to position and the record's value is greater than object store position or the record's key is greater than position.">
+<link rel=assert title='If direction is "prev", let found record be the last record in records which satisfy all of the following requirements'>
+<link rel=assert title="If position is defined, and source is an index, the record's key is equal to position and the record's value is less than object store position or the record's key is less than position.">
+<link rel=assert title="If range is defined, the record's key is in range.">
+<link rel=assert title="If temp record is defined, let found record be the first record in records whose key is equal to temp record's key.">
+<link rel=assert title="records is always sorted in ascending key order. In the case of source being an index, records is secondarily sorted in ascending value order.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var records = [ 1337, "Alice", "Bob", "Bob", "Greg", "Åke", ["Anne"] ];
+ var directions = ["next", "prev", "nextunique", "prevunique"];
+ var tests = {};
+
+ directions.forEach(function(dir) {
+ tests[dir] = async_test(document.title + ' - ' + dir);
+ });
+
+ var open_rq = indexedDB.open("testdb-" + new Date().getTime() + Math.random());
+
+ open_rq.onupgradeneeded = function(e) {
+ var objStore = e.target.result.createObjectStore("test");
+ objStore.createIndex("idx", "name");
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add({ name: records[i] }, i);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var db = e.target.result;
+ db.onerror = fail_helper("db.onerror");
+
+
+ // The tests
+ testdir('next', ['Alice:1', 'Bob:2', 'Bob:3', 'Greg:4']);
+ testdir('prev', ['Greg:4', 'Bob:3', 'Bob:2', 'Alice:1']);
+ testdir('nextunique', ['Alice:1', 'Bob:2', 'Greg:4']);
+ testdir('prevunique', ['Greg:4', 'Bob:2', 'Alice:1']);
+
+
+ // Test function
+ function testdir(dir, expect) {
+ var count = 0;
+ var t = tests[dir];
+ var rq = db.transaction("test").objectStore("test").index("idx").openCursor(IDBKeyRange.bound("AA", "ZZ"), dir);
+ rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ if (!cursor) {
+ assert_equals(count, expect.length, "cursor runs");
+ t.done();
+ }
+ assert_equals(cursor.value.name + ":" + cursor.primaryKey, expect[count], "cursor.value");
+ count++;
+ cursor.continue();
+ });
+ rq.onerror = t.step_func(function(e) {
+ e.preventDefault();
+ e.stopPropagation();
+ assert_unreached("rq.onerror - " + e.message);
+ });
+ }
+ };
+
+ // Fail handling
+ function fail_helper(name) {
+ return function() {
+ directions.forEach(function(dir) {
+ tests[dir].step(function() { assert_unreached(name); });
+ });
+ };
+ }
+ open_rq.onblocked = fail_helper('open_rq.onblocked');
+ open_rq.onerror = fail_helper('open_rq.onerror');
+</script>
+
+<div id=log> </div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor-direction-index.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor-direction-index.htm
new file mode 100644
index 00000000000..39afcb24d86
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor-direction-index.htm
@@ -0,0 +1,81 @@
+<!DOCTYPE html>
+<title>IDBCursor direction - index</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#cursor-iteration-operation">
+<link rel=assert title='If direction is "next", let found record be the first record in records which satisfy all of the following requirements'>
+<link rel=assert title="If position is defined, and source is an object store, the record's key is greater than position.">
+<link rel=assert title='If direction is "prev", let found record be the last record in records which satisfy all of the following requirements'>
+<link rel=assert title="If position is defined, and source is an object store, the record's key is less than position.">
+<link rel=assert title="Set cursor's position to found record's key. If source is an index, set cursor's object store position to found record's value.">
+<link rel=assert title="Set cursor's key to found record's key.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var records = [ "Alice", "Bob", "Bob", "Greg" ];
+ var directions = ["next", "prev", "nextunique", "prevunique"];
+ var tests = {};
+
+ directions.forEach(function(dir) {
+ tests[dir] = async_test(document.title + ' - ' + dir);
+ });
+
+ var open_rq = indexedDB.open("testdb-" + new Date().getTime() + Math.random());
+
+ open_rq.onupgradeneeded = function(e) {
+ var objStore = e.target.result.createObjectStore("test");
+ objStore.createIndex("idx", "name");
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add({ name: records[i] }, i);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var db = e.target.result;
+ db.onerror = fail_helper("db.onerror");
+
+
+ // The tests
+ testdir('next', ['Alice:0', 'Bob:1', 'Bob:2', 'Greg:3']);
+ testdir('prev', ['Greg:3', 'Bob:2', 'Bob:1', 'Alice:0']);
+ testdir('nextunique', ['Alice:0', 'Bob:1', 'Greg:3']);
+ testdir('prevunique', ['Greg:3', 'Bob:1', 'Alice:0']);
+
+
+ // Test function
+ function testdir(dir, expect) {
+ var count = 0;
+ var t = tests[dir];
+ var rq = db.transaction("test").objectStore("test").index("idx").openCursor(undefined, dir);
+ rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ if (!cursor) {
+ assert_equals(count, expect.length, "cursor runs");
+ t.done();
+ }
+ assert_equals(cursor.value.name + ":" + cursor.primaryKey, expect[count], "cursor.value");
+ count++;
+ cursor.continue();
+ });
+ rq.onerror = t.step_func(function(e) {
+ e.preventDefault();
+ e.stopPropagation();
+ assert_unreached("rq.onerror - " + e.message);
+ });
+ }
+ };
+
+ // Fail handling
+ function fail_helper(name) {
+ return function() {
+ directions.forEach(function(dir) {
+ tests[dir].step(function() { assert_unreached(name); });
+ });
+ };
+ }
+ open_rq.onblocked = fail_helper('open_rq.onblocked');
+ open_rq.onerror = fail_helper('open_rq.onerror');
+</script>
+
+<div id=log> </div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor-direction-objectstore-keyrange.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor-direction-objectstore-keyrange.htm
new file mode 100644
index 00000000000..2b2bf04bfd6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor-direction-objectstore-keyrange.htm
@@ -0,0 +1,77 @@
+<!DOCTYPE html>
+<title>IDBCursor direction - object store with keyrange</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#cursor-iteration-operation">
+<link rel=assert title='If direction is "next", let found record be the first record in records which satisfy all of the following requirements'>
+<link rel=assert title='If direction is "prev", let found record be the last record in records which satisfy all of the following requirements'>
+<link rel=assert title="If range is defined, the record's key is in range.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var records = [ 1337, "Alice", "Bob", "Greg", "Åke", ["Anne"] ];
+ var directions = ["next", "prev", "nextunique", "prevunique"];
+ var tests = {};
+
+ directions.forEach(function(dir) {
+ tests[dir] = async_test(document.title + ' - ' + dir);
+ });
+
+ var open_rq = indexedDB.open("testdb-" + new Date().getTime() + Math.random());
+
+ open_rq.onupgradeneeded = function(e) {
+ var objStore = e.target.result.createObjectStore("test");
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i], records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var db = e.target.result;
+ db.onerror = fail_helper("db.onerror");
+
+
+ // The tests
+ testdir('next', ['Alice', 'Bob', 'Greg']);
+ testdir('prev', ['Greg', 'Bob', 'Alice']);
+ testdir('nextunique', ['Alice', 'Bob', 'Greg']);
+ testdir('prevunique', ['Greg', 'Bob', 'Alice']);
+
+
+ // Test function
+ function testdir(dir, expect) {
+ var count = 0;
+ var t = tests[dir];
+ var rq = db.transaction("test").objectStore("test").openCursor(IDBKeyRange.bound("AA", "ZZ"), dir);
+ rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ if (!cursor) {
+ assert_equals(count, expect.length, "cursor runs");
+ t.done();
+ }
+ assert_equals(cursor.value, expect[count], "cursor.value");
+ count++;
+ cursor.continue();
+ });
+ rq.onerror = t.step_func(function(e) {
+ e.preventDefault();
+ e.stopPropagation();
+ assert_unreached("rq.onerror - " + e.message);
+ });
+ }
+ };
+
+ // Fail handling
+ function fail_helper(name) {
+ return function() {
+ directions.forEach(function(dir) {
+ tests[dir].step(function() { assert_unreached(name); });
+ });
+ };
+ }
+ open_rq.onblocked = fail_helper('open_rq.onblocked');
+ open_rq.onerror = fail_helper('open_rq.onerror');
+</script>
+
+<div id=log> </div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor-direction-objectstore.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor-direction-objectstore.htm
new file mode 100644
index 00000000000..c02355395a2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor-direction-objectstore.htm
@@ -0,0 +1,80 @@
+<!DOCTYPE html>
+<title>IDBCursor direction - object store</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#cursor-iteration-operation">
+<link rel=assert title='If direction is "next", let found record be the first record in records which satisfy all of the following requirements'>
+<link rel=assert title="If position is defined, and source is an object store, the record's key is greater than position.">
+<link rel=assert title='If direction is "prev", let found record be the last record in records which satisfy all of the following requirements'>
+<link rel=assert title="If position is defined, and source is an object store, the record's key is less than position.">
+<link rel=assert title="Set cursor's position to found record's key. If source is an index, set cursor's object store position to found record's value.">
+<link rel=assert title="Set cursor's key to found record's key.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var records = [ "Alice", "Bob", "Greg" ];
+ var directions = ["next", "prev", "nextunique", "prevunique"];
+ var tests = {};
+
+ directions.forEach(function(dir) {
+ tests[dir] = async_test(document.title + ' - ' + dir);
+ });
+
+ var open_rq = indexedDB.open("testdb-" + new Date().getTime() + Math.random());
+
+ open_rq.onupgradeneeded = function(e) {
+ var objStore = e.target.result.createObjectStore("test");
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i], records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var db = e.target.result;
+ db.onerror = fail_helper("db.onerror");
+
+
+ // The tests
+ testdir('next', ['Alice', 'Bob', 'Greg']);
+ testdir('prev', ['Greg', 'Bob', 'Alice']);
+ testdir('nextunique', ['Alice', 'Bob', 'Greg']);
+ testdir('prevunique', ['Greg', 'Bob', 'Alice']);
+
+
+ // Test function
+ function testdir(dir, expect) {
+ var count = 0;
+ var t = tests[dir];
+ var rq = db.transaction("test").objectStore("test").openCursor(undefined, dir);
+ rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ if (!cursor) {
+ assert_equals(count, expect.length, "cursor runs");
+ t.done();
+ }
+ assert_equals(cursor.value, expect[count], "cursor.value");
+ count++;
+ cursor.continue();
+ });
+ rq.onerror = t.step_func(function(e) {
+ e.preventDefault();
+ e.stopPropagation();
+ assert_unreached("rq.onerror - " + e.message);
+ });
+ }
+ };
+
+ // Fail handling
+ function fail_helper(name) {
+ return function() {
+ directions.forEach(function(dir) {
+ tests[dir].step(function() { assert_unreached(name); });
+ });
+ };
+ }
+ open_rq.onblocked = fail_helper('open_rq.onblocked');
+ open_rq.onerror = fail_helper('open_rq.onerror');
+</script>
+
+<div id=log> </div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor-direction.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor-direction.htm
new file mode 100644
index 00000000000..b50eded7908
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor-direction.htm
@@ -0,0 +1,73 @@
+<!DOCTYPE html>
+<title>IDBCursor.direction</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ function cursor_direction(constant, dir)
+ {
+ var db,
+ t = async_test(document.title + " - " + dir),
+ expected = dir ? dir : "next";
+
+ var open_rq = createdb(t);
+
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test");
+
+ objStore.add("data", "key");
+ };
+
+ open_rq.onsuccess = t.step_func(function(e) {
+ var cursor_rq, count = 0;
+ var os = db.transaction("test")
+ .objectStore("test");
+ if (dir)
+ cursor_rq = os.openCursor(undefined, dir);
+ else
+ cursor_rq = os.openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ assert_equals(cursor.direction, constant, 'direction constant');
+ assert_equals(cursor.direction, expected, 'direction');
+ assert_readonly(cursor, 'direction');
+
+ count++;
+ if (count >= 2)
+ t.done();
+ });
+
+ var cursor_rq2 = db.transaction("test")
+ .objectStore("test")
+ .openCursor(undefined, constant);
+
+ cursor_rq2.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ assert_equals(cursor.direction, constant, 'direction constant (second try)');
+ assert_equals(cursor.direction, expected, 'direction (second try)');
+ assert_readonly(cursor, 'direction');
+
+ count++;
+ if (count >= 2)
+ t.done();
+ });
+
+ });
+ }
+
+ cursor_direction("next");
+ cursor_direction("next", "next");
+ cursor_direction("prev", "prev");
+ cursor_direction("nextunique", "nextunique");
+ cursor_direction("prevunique", "prevunique");
+
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor-key.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor-key.htm
new file mode 100644
index 00000000000..7b10b99e225
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor-key.htm
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<title>IDBCursor.key</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ function cursor_key(key)
+ {
+ var db,
+ t = async_test(document.title + " - " + key);
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test");
+
+ objStore.add("data", key);
+ };
+
+ open_rq.onsuccess = t.step_func(function(e) {
+ var cursor_rq = db.transaction("test")
+ .objectStore("test")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ assert_equals(cursor.value, "data", "prequisite cursor.value");
+
+ assert_object_equals(cursor.key, key, 'key');
+ assert_readonly(cursor, 'key');
+
+ if (key instanceof Array) {
+ cursor.key.push("new");
+ key.push("new");
+
+ assert_object_equals(cursor.key, key, 'key after array push');
+
+ // But we can not change key (like readonly, just a bit different)
+ cursor.key = 10;
+ assert_object_equals(cursor.key, key, 'key after assignment');
+ }
+
+ t.done();
+ });
+ });
+ }
+
+ cursor_key(1);
+ cursor_key("key");
+ cursor_key(["my", "key"]);
+
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor-primarykey.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor-primarykey.htm
new file mode 100644
index 00000000000..04b4a14a07b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor-primarykey.htm
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<title>IDBCursor.primaryKey</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ function cursor_primarykey(key)
+ {
+ var db,
+ t = async_test(document.title + " - " + key);
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test");
+ objStore.createIndex("index", "");
+
+ objStore.add("data", key);
+ };
+
+ open_rq.onsuccess = t.step_func(function(e) {
+ var cursor_rq = db.transaction("test")
+ .objectStore("test")
+ .index("index")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ assert_equals(cursor.value, "data", "prequisite cursor.value");
+ assert_equals(cursor.key, "data", "prequisite cursor.key");
+
+ assert_object_equals(cursor.primaryKey, key, 'primaryKey');
+ assert_readonly(cursor, 'primaryKey');
+
+ if (key instanceof Array) {
+ cursor.primaryKey.push("new");
+ key.push("new");
+
+ assert_object_equals(cursor.primaryKey, key, 'primaryKey after array push');
+
+ // But we can not change key (like readonly, just a bit different)
+ cursor.key = 10;
+ assert_object_equals(cursor.primaryKey, key, 'key after assignment');
+ }
+
+ t.done();
+ });
+ });
+ }
+
+ cursor_primarykey(1);
+ cursor_primarykey("key");
+ cursor_primarykey(["my", "key"]);
+
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor-reused.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor-reused.htm
new file mode 100644
index 00000000000..603041e7cdf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor-reused.htm
@@ -0,0 +1,69 @@
+<!DOCTYPE html>
+<title>IDBCursor is reused</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<meta rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBCursor-continue-void-any-key">
+<meta rel=assert title="Otherwise this method runs the steps for asynchronously executing a request. However, the steps are slightly modified such that instead of creating a new IDBRequest, it reuses the request originally created when this cursor was created. The done flag on the request is set to false before the request is returned. The steps are run with the cursor's source as source and the steps for iterating a cursor as operation, using this cursor as cursor and the key parameter as key.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ var db
+ var open_rq = createdb(async_test())
+
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result
+ var os = db.createObjectStore("test")
+
+ os.add("data", "k")
+ os.add("data2", "k2")
+ }
+
+ open_rq.onsuccess = function(e) {
+ var cursor
+ var count = 0
+ var rq = db.transaction("test").objectStore("test").openCursor()
+
+ rq.onsuccess = this.step_func(function(e)
+ {
+ switch(count)
+ {
+ case 0:
+ cursor = e.target.result
+
+ assert_equals(cursor.value, "data", "prequisite cursor.value")
+ cursor.custom_cursor_value = 1
+ e.target.custom_request_value = 2
+
+ cursor.continue()
+ break
+
+ case 1:
+ assert_equals(cursor.value, "data2", "prequisite cursor.value")
+ assert_equals(cursor.custom_cursor_value, 1, "custom cursor value")
+ assert_equals(e.target.custom_request_value, 2, "custom request value")
+
+ cursor.advance(1)
+ break
+
+ case 2:
+ assert_false(!!e.target.result, "got cursor")
+ assert_equals(cursor.custom_cursor_value, 1, "custom cursor value")
+ assert_equals(e.target.custom_request_value, 2, "custom request value")
+ break
+ }
+ count++
+ })
+
+ rq.transaction.oncomplete = this.step_func(function() {
+ assert_equals(count, 3, "cursor callback runs")
+ assert_equals(rq.custom_request_value, 2, "variable placed on old IDBRequest")
+ assert_equals(cursor.custom_cursor_value, 1, "custom cursor value (transaction.complete)")
+ this.done()
+ })
+ }
+
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor-source.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor-source.htm
new file mode 100644
index 00000000000..7e3746ae7e6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor-source.htm
@@ -0,0 +1,68 @@
+<!DOCTYPE html>
+<title>IDBCursor.source</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ setup({ explicit_done: true });
+
+ var db;
+ var open_rq = indexedDB.open('testdb-' + new Date().getTime());
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("my_objectstore");
+ objStore.createIndex("my_index", "");
+
+ objStore.add("data", 1);
+ objStore.add("data2", 2);
+ };
+
+ function cursor_source(name, stringified_object, cursor_rq) {
+ var cursor;
+
+ cursor_rq.onsuccess = this.step_func(function(e) {
+ if (!e.target.result) {
+ return;
+ }
+ cursor = e.target.result;
+ assert_readonly(cursor, 'source');
+
+ // Direct try
+ assert_true(cursor.source instanceof Object, "source isobject");
+ assert_equals(cursor.source + "", stringified_object, "source");
+ assert_equals(cursor.source.name, name, "name");
+
+ cursor.continue();
+ });
+
+ cursor_rq.transaction.oncomplete = this.step_func(function(e) {
+ this.done();
+ });
+
+ cursor_rq.transaction.onerror = this.step_func(function(e) {
+ assert_unreached("Transaction got error. " + (e.target.error ? e.target.error.name : "unknown"));
+ });
+ }
+
+ open_rq.onsuccess = function() {
+ async_test(document.title + ' - IDBObjectStore').step(function() {
+ cursor_source.call(this, "my_objectstore", "[object IDBObjectStore]", db.transaction("my_objectstore")
+ .objectStore("my_objectstore")
+ .openCursor());
+ });
+
+ async_test(document.title + ' - IDBIndex').step(function() {
+ cursor_source.call(this, "my_index", "[object IDBIndex]", db.transaction("my_objectstore")
+ .objectStore("my_objectstore")
+ .index("my_index")
+ .openCursor());
+ });
+
+ done();
+ };
+
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_advance_index.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_advance_index.htm
new file mode 100644
index 00000000000..8f2d0c65182
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_advance_index.htm
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<title>IDBCursor.advance() - index - iterate cursor number of times specified by count </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var db,
+ count = 0,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" },
+ { pKey: "primaryKey_2", iKey: "indexKey_2" },
+ { pKey: "primaryKey_3", iKey: "indexKey_3" }];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = event.target.result;
+ var store = db.createObjectStore("test", {keyPath:"pKey"});
+ store.createIndex("idx", "iKey");
+
+ for(var i = 0; i < records.length; i++) {
+ store.add(records[i]);
+ }
+ };
+
+ open_rq.onsuccess = function (e) {
+ var cursor_rq = db.transaction("test")
+ .objectStore("test")
+ .index("idx")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ assert_true(cursor instanceof IDBCursor);
+
+ switch(count) {
+ case 0:
+ count += 3;
+ cursor.advance(3);
+ break;
+ case 3:
+ var record = cursor.value;
+ assert_equals(record.pKey, records[count].pKey, "record.pKey");
+ assert_equals(record.iKey, records[count].iKey, "record.iKey");
+ t.done();
+ break;
+ default:
+ assert_unreached("unexpected count");
+ break;
+ }
+ });
+ }
+</script>
+
+<div id=log></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_advance_index2.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_advance_index2.htm
new file mode 100644
index 00000000000..539c824e61e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_advance_index2.htm
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<title>IDBCursor.advance() - attempt to pass a count parameter that is not a number</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBCursor-advance-void-unsigned-long-count">
+<link rel=assert title="The value passed into the count parameter was zero or a negative number.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ var db,
+ t = async_test(document.title, {timeout: 10000}),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", {keyPath:"pKey"});
+
+ objStore.createIndex("index", "iKey");
+
+ for(var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var cursor_rq = db.transaction("test")
+ .objectStore("test")
+ .index("index")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ assert_true(cursor != null, "cursor exist");
+ assert_throws(new TypeError(),
+ function() { cursor.advance(document); });
+
+ t.done();
+ });
+ };
+
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_advance_index3.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_advance_index3.htm
new file mode 100644
index 00000000000..5adf3f077fd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_advance_index3.htm
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<title>IDBCursor.advance() - index - attempt to advance backwards</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBCursor-advance-void-unsigned-long-count">
+<link rel=assert title="The value passed into the count parameter was zero or a negative number.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script type="text/javascript">
+
+ var db,
+ t = async_test(document.title, {timeout: 10000}),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", { keyPath:"pKey" });
+
+ objStore.createIndex("index", "iKey");
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var cursor_rq = db.transaction("test")
+ .objectStore("test")
+ .index("index")
+ .openCursor(undefined, "next");
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ assert_true(cursor != null, "cursor exist");
+ assert_throws(new TypeError(),
+ function() { cursor.advance(-1); });
+
+ t.done();
+ });
+ };
+
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_advance_index5.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_advance_index5.htm
new file mode 100644
index 00000000000..452c0f142f6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_advance_index5.htm
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<title>IDBCursor.advance() - index - iterate to the next record</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBCursor-advance-void-unsigned-long-count">
+<link rel=assert title="The operation runs the steps for iterating a cursor count number of times with null as key and this cursor as cursor.">
+<link rel=assert title="The number of advances forward the cursor should make.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ count = 0,
+ t = async_test(document.title, {timeout: 10000}),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" },
+ { pKey: "primaryKey_1-2", iKey: "indexKey_1" } ],
+ expected = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1-2", iKey: "indexKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result
+ var objStore = db.createObjectStore("test", { keyPath:"pKey" })
+
+ objStore.createIndex("index", "iKey")
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i])
+ };
+
+ open_rq.onsuccess = function(e) {
+ var cursor_rq = db.transaction("test")
+ .objectStore("test")
+ .index("index")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ if (!cursor) {
+ assert_equals(count, expected.length, "cursor run count")
+ t.done()
+ }
+
+ var record = cursor.value;
+ assert_equals(record.pKey, expected[count].pKey, "primary key");
+ assert_equals(record.iKey, expected[count].iKey, "index key");
+
+ cursor.advance(2);
+ count++;
+ });
+ };
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_advance_index6.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_advance_index6.htm
new file mode 100644
index 00000000000..826cb1e1a0e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_advance_index6.htm
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBCursor.advance() - index - throw TypeError</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBCursor-advance-void-unsigned-long-count">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test(),
+ records = [{ pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" }];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function (event) {
+ db = event.target.result;
+ var objStore = db.createObjectStore("store", {keyPath : "pKey"});
+ objStore.createIndex("index", "iKey");
+ for (var i = 0; i < records.length; i++) {
+ objStore.add(records[i]);
+ }
+ var rq = objStore.index("index").openCursor();
+ rq.onsuccess = t.step_func(function(event) {
+ var cursor = event.target.result;
+ assert_true(cursor instanceof IDBCursor);
+
+ assert_throws(new TypeError(), function() {
+ cursor.advance(0);
+ }, "Calling advance() with count argument 0 should throw TypeError.");
+
+ t.done();
+ });
+ }
+</script>
+
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_advance_index7.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_advance_index7.htm
new file mode 100644
index 00000000000..8da5b618d45
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_advance_index7.htm
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBCursor.advance() - index - throw TransactionInactiveError</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBCursor-advance-void-unsigned-long-count">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test(),
+ records = [{ pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" }];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function (event) {
+ db = event.target.result;
+ var objStore = db.createObjectStore("store", {keyPath : "pKey"});
+ objStore.createIndex("index", "iKey");
+ for (var i = 0; i < records.length; i++) {
+ objStore.add(records[i]);
+ }
+ var rq = objStore.index("index").openCursor();
+ rq.onsuccess = t.step_func(function(event) {
+ var cursor = event.target.result;
+ assert_true(cursor instanceof IDBCursor);
+
+ event.target.transaction.abort();
+ assert_throws("TransactionInactiveError", function() {
+ cursor.advance(1);
+ }, "Calling advance() should throws an exception TransactionInactiveError when the transaction is not active.");
+
+ t.done();
+ });
+ }
+
+</script>
+
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_advance_index8.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_advance_index8.htm
new file mode 100644
index 00000000000..b5e64d4cdce
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_advance_index8.htm
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBCursor.advance() - index - throw InvalidStateError</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBCursor-advance-void-unsigned-long-count">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test(),
+ records = [{ pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" }];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function (event) {
+ db = event.target.result;
+ var objStore = db.createObjectStore("store", {keyPath : "pKey"});
+ objStore.createIndex("index", "iKey");
+ for (var i = 0; i < records.length; i++) {
+ objStore.add(records[i]);
+ }
+ var rq = objStore.index("index").openCursor();
+ rq.onsuccess = t.step_func(function(event) {
+ var cursor = event.target.result;
+ assert_true(cursor instanceof IDBCursor);
+
+ cursor.advance(1);
+ assert_throws("InvalidStateError", function() {
+ cursor.advance(1);
+ }, "Calling advance() should throw DOMException when the cursor is currently being iterated.");
+
+ t.done();
+ });
+ }
+</script>
+
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_advance_index9.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_advance_index9.htm
new file mode 100644
index 00000000000..517a573c49e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_advance_index9.htm
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBCursor.advance() - index - throw InvalidStateError caused by object store been deleted</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test(),
+ records = [{ pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" }];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function (event) {
+ db = event.target.result;
+ var objStore = db.createObjectStore("store", {keyPath : "pKey"});
+ objStore.createIndex("index", "iKey");
+ for (var i = 0; i < records.length; i++) {
+ objStore.add(records[i]);
+ }
+ var rq = objStore.index("index").openCursor();
+ rq.onsuccess = t.step_func(function(event) {
+ var cursor = event.target.result;
+ assert_true(cursor instanceof IDBCursor, "cursor exist");
+
+ db.deleteObjectStore("store");
+ assert_throws("InvalidStateError", function() {
+ cursor.advance(1);
+ }, "If the cursor's source or effective object store has been deleted, the implementation MUST throw a DOMException of type InvalidStateError");
+
+ t.done();
+ });
+ }
+</script>
+
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_advance_objectstore.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_advance_objectstore.htm
new file mode 100644
index 00000000000..bf7cb70fb60
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_advance_objectstore.htm
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<title> IDBCursor.advance() - object store - iterate cursor number of times specified by count </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var db,
+ count = 0,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0" },
+ { pKey: "primaryKey_1" },
+ { pKey: "primaryKey_2" },
+ { pKey: "primaryKey_3" }];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = event.target.result;
+ var store = db.createObjectStore("test", {keyPath:"pKey"});
+
+ for(var i = 0; i < records.length; i++) {
+ store.add(records[i]);
+ }
+ };
+
+ open_rq.onsuccess = function (e) {
+ var cursor_rq = db.transaction("test")
+ .objectStore("test")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ assert_true(cursor instanceof IDBCursor);
+
+ switch(count) {
+ case 0:
+ count += 3;
+ cursor.advance(3);
+ break;
+ case 3:
+ assert_equals(cursor.value.pKey, records[count].pKey, "cursor.value.pKey");
+ t.done();
+ break;
+ default:
+ assert_unreached("unexpected count");
+ break;
+ }
+ });
+ }
+
+</script>
+
+<div id=log> </div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_advance_objectstore2.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_advance_objectstore2.htm
new file mode 100644
index 00000000000..32478c141ea
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_advance_objectstore2.htm
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBCursor.advance() - object store - throw TypeError</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBCursor-advance-void-unsigned-long-count">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test(),
+ records = [{ pKey: "primaryKey_0"},
+ { pKey: "primaryKey_1"}];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function (event) {
+ db = event.target.result;
+ var objStore = db.createObjectStore("store", {keyPath:"pKey"});
+ for (var i = 0; i < records.length; i++) {
+ objStore.add(records[i]);
+ }
+ }
+
+ open_rq.onsuccess = function (event) {
+ var txn = db.transaction("store", "readwrite");
+ var rq = txn.objectStore("store").openCursor();
+ rq.onsuccess = t.step_func(function(event) {
+ var cursor = event.target.result;
+ assert_true(cursor instanceof IDBCursor);
+
+ assert_throws(new TypeError(), function() {
+ cursor.advance(0);
+ }, "Calling advance() with count argument 0 should throw TypeError.");
+
+ t.done();
+ });
+ }
+</script>
+
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_advance_objectstore3.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_advance_objectstore3.htm
new file mode 100644
index 00000000000..1accd6631a0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_advance_objectstore3.htm
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBCursor.advance() - object store - throw TransactionInactiveError</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBCursor-advance-void-unsigned-long-count">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test(),
+ records = [{ pKey: "primaryKey_0"},
+ { pKey: "primaryKey_1"}];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function (event) {
+ db = event.target.result;
+ var objStore = db.createObjectStore("store", {keyPath:"pKey"});
+ for (var i = 0; i < records.length; i++) {
+ objStore.add(records[i]);
+ }
+ }
+
+ open_rq.onsuccess = function (event) {
+ var txn = db.transaction("store", "readwrite");
+ var rq = txn.objectStore("store").openCursor();
+ rq.onsuccess = t.step_func(function(event) {
+ var cursor = event.target.result;
+ assert_true(cursor instanceof IDBCursor);
+
+ event.target.transaction.abort();
+ assert_throws("TransactionInactiveError", function() {
+ cursor.advance(1);
+ }, "Calling advance() should throws an exception TransactionInactiveError when the transaction is not active");
+
+ t.done();
+ });
+ }
+
+</script>
+
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_advance_objectstore4.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_advance_objectstore4.htm
new file mode 100644
index 00000000000..387973169d0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_advance_objectstore4.htm
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBCursor.advance() - object store - throw InvalidStateError</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBCursor-advance-void-unsigned-long-count">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test(),
+ records = [{ pKey: "primaryKey_0"},
+ { pKey: "primaryKey_1"}];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function (event) {
+ db = event.target.result;
+ var objStore = db.createObjectStore("store", {keyPath:"pKey"});
+ for (var i = 0; i < records.length; i++) {
+ objStore.add(records[i]);
+ }
+ }
+
+ open_rq.onsuccess = function (event) {
+ var txn = db.transaction("store", "readwrite");
+ var rq = txn.objectStore("store").openCursor();
+ rq.onsuccess = t.step_func(function(event) {
+ var cursor = event.target.result;
+ assert_true(cursor instanceof IDBCursor);
+
+ cursor.advance(1);
+ assert_throws("InvalidStateError", function() {
+ cursor.advance(1);
+ }, "Calling advance() should throw DOMException when the cursor is currently being iterated.");
+
+ t.done();
+ });
+ }
+</script>
+
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_advance_objectstore5.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_advance_objectstore5.htm
new file mode 100644
index 00000000000..cb0859c636e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_advance_objectstore5.htm
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBCursor.advance() - object store - throw InvalidStateError caused by object store been deleted</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test(),
+ records = [{ pKey: "primaryKey_0"},
+ { pKey: "primaryKey_1"}];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function (event) {
+ db = event.target.result;
+ var objStore = db.createObjectStore("store", {keyPath:"pKey"});
+ for (var i = 0; i < records.length; i++) {
+ objStore.add(records[i]);
+ }
+ var rq = objStore.openCursor();
+ rq.onsuccess = t.step_func(function(event) {
+ var cursor = event.target.result;
+ assert_true(cursor instanceof IDBCursor, "cursor exist");
+
+ db.deleteObjectStore("store");
+ assert_throws("InvalidStateError", function() {
+ cursor.advance(1);
+ }, "If the cursor's source or effective object store has been deleted, the implementation MUST throw a DOMException of type InvalidStateError");
+
+ t.done();
+ });
+ }
+</script>
+
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_index.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_index.htm
new file mode 100644
index 00000000000..8b0d079a939
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_index.htm
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<title>IDBCursor.continue() - index - iterate to the next record</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBCursor-continue-void-any-key">
+<link rel=assert title="Otherwise this method runs the steps for asynchronously executing a request.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ count = 0,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" },
+ { pKey: "primaryKey_1-2", iKey: "indexKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", { keyPath:"pKey" });
+
+ objStore.createIndex("index", "iKey");
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var cursor_rq = db.transaction("test")
+ .objectStore("test")
+ .index("index")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ if (!cursor) {
+ assert_equals(count, records.length, "cursor run count");
+ t.done();
+ }
+
+ var record = cursor.value;
+ assert_equals(record.pKey, records[count].pKey, "primary key");
+ assert_equals(record.iKey, records[count].iKey, "index key");
+
+ cursor.continue();
+ count++;
+ });
+ };
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_index2.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_index2.htm
new file mode 100644
index 00000000000..d0eaef3d074
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_index2.htm
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<title>IDBCursor.continue() - index - attempt to pass a key parameter that is not a valid key</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBCursor-continue-void-any-key">
+<link rel=assert title="If the key parameter is specified and fulfills any of these conditions this method must throw a DOMException of type DataError">
+<link rel=assert title="The parameter is not a valid key.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ var db,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", {keyPath:"pKey"});
+
+ objStore.createIndex("index", "iKey");
+
+ for(var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var cursor_rq = db.transaction("test")
+ .objectStore("test")
+ .index("index")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ assert_throws("DataError",
+ function() { cursor.continue(document); });
+
+ assert_true(cursor instanceof IDBCursorWithValue, "cursor");
+
+ t.done();
+ });
+ };
+
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_index3.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_index3.htm
new file mode 100644
index 00000000000..357dc157f35
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_index3.htm
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<title>IDBCursor.continue() - index - attempt to iterate to the previous record when the direction is set for the next record </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBCursor-continue-void-any-key">
+<link rel=assert title="The parameter is less than or equal to this cursor's position and this cursor's direction is 'next' or 'nextunique'.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ var db,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", {keyPath:"pKey"});
+
+ objStore.createIndex("index", "iKey");
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var count = 0;
+ var cursor_rq = db.transaction("test")
+ .objectStore("test")
+ .index("index")
+ .openCursor(undefined, "next"); // XXX: Fx has issue with "undefined"
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ if (!cursor) {
+ assert_equals(count, 2, "ran number of times");
+ t.done();
+ }
+
+ // First time checks key equal, second time checks key less than
+ assert_throws("DataError",
+ function() { cursor.continue(records[0].iKey); });
+
+ cursor.continue();
+
+ count++;
+ });
+ };
+
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_index4.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_index4.htm
new file mode 100644
index 00000000000..c5cfd85ebdb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_index4.htm
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<title>IDBCursor.continue() - index - attempt to iterate to the next record when the direction is set for the previous record</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBCursor-continue-void-any-key">
+<link rel=assert title="The parameter is greater than or equal to this cursor's position and this cursor's direction is 'prev' or 'prevunique'.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ var db,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" },
+ { pKey: "primaryKey_2", iKey: "indexKey_2" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", { keyPath: "pKey" });
+
+ objStore.createIndex("index", "iKey");
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var count = 0,
+ cursor_rq = db.transaction("test")
+ .objectStore("test")
+ .index("index")
+ .openCursor(undefined, "prev"); // XXX Fx issues w undefined
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result,
+ record = cursor.value;
+
+ switch(count) {
+ case 0:
+ assert_equals(record.pKey, records[2].pKey, "first pKey");
+ assert_equals(record.iKey, records[2].iKey, "first iKey");
+ cursor.continue();
+ break;
+
+ case 1:
+ assert_equals(record.pKey, records[1].pKey, "second pKey");
+ assert_equals(record.iKey, records[1].iKey, "second iKey");
+ assert_throws("DataError",
+ function() { cursor.continue("indexKey_2"); });
+ t.done();
+ break;
+
+ default:
+ assert_unreached("Unexpected count value: " + count);
+ }
+
+ count++;
+ });
+ };
+
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_index5.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_index5.htm
new file mode 100644
index 00000000000..abe0e658b01
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_index5.htm
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<title>IDBCursor.continue() - index - iterate using 'prevunique'</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#cursor-iteration-operation">
+<link rel=assert title='If direction is "prevunique", let temp record be the last record in records which satisfy all of the following requirements:'>
+<link rel=assert title="If position is defined, the record's key is less than position.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ var db,
+ t = async_test(document.title, {timeout: 10000}),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" },
+ { pKey: "primaryKey_1-2", iKey: "indexKey_1" },
+ { pKey: "primaryKey_2", iKey: "indexKey_2" } ],
+
+ expected = [ { pKey: "primaryKey_2", iKey: "indexKey_2" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" },
+ { pKey: "primaryKey_0", iKey: "indexKey_0" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", { keyPath: "pKey" });
+
+ objStore.createIndex("index", "iKey");
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var count = 0,
+ cursor_rq = db.transaction("test")
+ .objectStore("test")
+ .index("index")
+ .openCursor(undefined, 'prevunique');
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ if (!e.target.result) {
+ assert_equals(count, expected.length, 'count');
+ t.done();
+ return;
+ }
+ var cursor = e.target.result,
+ record = cursor.value;
+
+ assert_equals(record.pKey, expected[count].pKey, "pKey #" + count);
+ assert_equals(record.iKey, expected[count].iKey, "iKey #" + count);
+
+ assert_equals(cursor.key, expected[count].iKey, "cursor.key #" + count);
+ assert_equals(cursor.primaryKey, expected[count].pKey, "cursor.primaryKey #" + count);
+
+ count++;
+ cursor.continue(expected[count] ? expected[count].iKey : undefined);
+ });
+ };
+
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_index6.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_index6.htm
new file mode 100644
index 00000000000..cf5bd4066e8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_index6.htm
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<title>IDBCursor.continue() - index - iterate using nextunique</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#cursor-iteration-operation">
+<link rel=assert title='If direction is "nextunique", let found record be the first record in records which satisfy all of the following requirements:'>
+<link rel=assert title="If position is defined, the record's key is greater than position.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ var db,
+ t = async_test(document.title, {timeout: 10000}),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" },
+ { pKey: "primaryKey_1-2", iKey: "indexKey_1" },
+ { pKey: "primaryKey_2", iKey: "indexKey_2" } ],
+
+ expected = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" },
+ { pKey: "primaryKey_2", iKey: "indexKey_2" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", { keyPath: "pKey" });
+
+ objStore.createIndex("index", "iKey");
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var count = 0,
+ cursor_rq = db.transaction("test")
+ .objectStore("test")
+ .index("index")
+ .openCursor(undefined, "nextunique");
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ if (!e.target.result) {
+ assert_equals(count, expected.length, 'count');
+ t.done();
+ return;
+ }
+ var cursor = e.target.result,
+ record = cursor.value;
+
+ assert_equals(record.pKey, expected[count].pKey, "pKey #" + count);
+ assert_equals(record.iKey, expected[count].iKey, "iKey #" + count);
+
+ assert_equals(cursor.key, expected[count].iKey, "cursor.key #" + count);
+ assert_equals(cursor.primaryKey, expected[count].pKey, "cursor.primaryKey #" + count);
+
+ count++;
+ cursor.continue(expected[count] ? expected[count].iKey : undefined);
+ });
+ };
+
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_index7.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_index7.htm
new file mode 100644
index 00000000000..fed235685c7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_index7.htm
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBCursor.continue() - index - throw TransactionInactiveError</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+
+ var db,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function (event) {
+ db = event.target.result;
+ var objStore = db.createObjectStore("store", {keyPath : "pKey"});
+ objStore.createIndex("index", "iKey");
+ for (var i = 0; i < records.length; i++) {
+ objStore.add(records[i]);
+ }
+ var rq = objStore.index("index").openCursor();
+ rq.onsuccess = t.step_func(function(event) {
+ var cursor = event.target.result;
+ assert_true(cursor instanceof IDBCursor);
+
+ event.target.transaction.abort();
+ assert_throws("TransactionInactiveError", function() {
+ cursor.continue();
+ }, "Calling continue() should throws an exception TransactionInactiveError when the transaction is not active.");
+
+ t.done();
+ });
+ }
+
+</script>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_index8.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_index8.htm
new file mode 100644
index 00000000000..4a574ec90f4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_index8.htm
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBCursor.continue() - index - throw InvalidStateError caused by object store been deleted</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+
+ var db,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function (event) {
+ db = event.target.result;
+ var objStore = db.createObjectStore("store", {keyPath : "pKey"});
+ objStore.createIndex("index", "iKey");
+ for (var i = 0; i < records.length; i++) {
+ objStore.add(records[i]);
+ }
+ var rq = objStore.index("index").openCursor();
+ rq.onsuccess = t.step_func(function(event) {
+ var cursor = event.target.result;
+ assert_true(cursor instanceof IDBCursor);
+
+ db.deleteObjectStore("store");
+ assert_throws("InvalidStateError", function() {
+ cursor.continue();
+ }, "If the cursor's source or effective object store has been deleted, the implementation MUST throw a DOMException of type InvalidStateError");
+
+ t.done();
+ });
+ }
+
+</script>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_invalid.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_invalid.htm
new file mode 100644
index 00000000000..dea07bc9112
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_invalid.htm
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<title>IDBCursor.continue() - attempt to call continue two times</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ var db,
+ t = async_test(document.title, {timeout: 10000});
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test");
+
+ objStore.createIndex("index", "");
+
+ objStore.add("data", 1);
+ objStore.add("data2", 2);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var count = 0;
+ var cursor_rq = db.transaction("test")
+ .objectStore("test")
+ .index("index")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ if (!e.target.result) {
+ assert_equals(count, 2, 'count');
+ t.done();
+ return;
+ }
+ var cursor = e.target.result;
+
+ cursor.continue(undefined);
+
+ // Second try
+ assert_throws('InvalidStateError',
+ function() { cursor.continue(); }, 'second continue');
+
+ assert_throws('InvalidStateError',
+ function() { cursor.continue(3); }, 'third continue');
+
+ count++;
+ });
+ };
+
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_objectstore.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_objectstore.htm
new file mode 100644
index 00000000000..76750c969a4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_objectstore.htm
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<title>IDBCursor.continue() - object store - iterate to the next record</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var db,
+ count = 0,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0" },
+ { pKey: "primaryKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", {autoIncrement:true, keyPath:"pKey"});
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var store = db.transaction("test")
+ .objectStore("test");
+
+ cursor_rq = store.openCursor();
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ if (!cursor) {
+ assert_equals(count, records.length, "cursor run count");
+ t.done();
+ }
+
+ var record = cursor.value;
+ assert_equals(record.pKey, records[count].pKey, "primary key");
+ assert_equals(record.iKey, records[count].iKey, "index key");
+
+ cursor.continue();
+ count++;
+ });
+ };
+</script>
+
+<div id=log> </div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_objectstore2.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_objectstore2.htm
new file mode 100644
index 00000000000..14502330b80
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_objectstore2.htm
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<title>IDBCursor.continue() - object store - attempt to pass a key parameter is not a valid key </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0" },
+ { pKey: "primaryKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", {keyPath:"pKey"});
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var cursor_rq = db.transaction("test")
+ .objectStore("test")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ assert_true(cursor instanceof IDBCursor, "cursor exists");
+ assert_throws("DataError",
+ function() { cursor.continue(document); });
+
+ t.done();
+ });
+ };
+</script>
+
+<div id="log"> </div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_objectstore3.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_objectstore3.htm
new file mode 100644
index 00000000000..a059b62e53a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_objectstore3.htm
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<title>IDBCursor.continue() - object store - attempt to iterate to the previous record when the direction is set for the next record</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0" },
+ { pKey: "primaryKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", {keyPath:"pKey"});
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var cursor_rq = db.transaction("test")
+ .objectStore("test")
+ .openCursor(undefined, "next");
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ assert_true(cursor instanceof IDBCursor, "cursor exist");
+ assert_throws("DataError",
+ function() { cursor.continue(records[0].pKey); });
+
+ t.done();
+ });
+ };
+</script>
+
+<div id="log"> </div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_objectstore4.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_objectstore4.htm
new file mode 100644
index 00000000000..b4819c73300
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_objectstore4.htm
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<title>IDBCursor.continue() - object store - attempt to iterate to the next record when the direction is set for the previous record </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0" },
+ { pKey: "primaryKey_1" },
+ { pKey: "primaryKey_2" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", { keyPath: "pKey" });
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var count = 0,
+ cursor_rq = db.transaction("test")
+ .objectStore("test")
+ .openCursor(null, "prev");
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ assert_true(cursor != null, "cursor exist");
+
+ switch(count) {
+ case 0:
+ assert_equals(cursor.value.pKey, records[2].pKey, "first cursor pkey");
+ cursor.continue(records[1].pKey);
+ break;
+
+ case 1:
+ assert_equals(cursor.value.pKey, records[1].pKey, "second cursor pkey");
+ assert_throws("DataError",
+ function() { cursor.continue(records[2].pKey); });
+ t.done();
+ break;
+
+ default:
+ assert_unreached("Unexpected count value: " + count);
+ }
+
+ count++;
+ });
+ };
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_objectstore5.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_objectstore5.htm
new file mode 100644
index 00000000000..3c1943336c3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_objectstore5.htm
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBCursor.continue() - object store - throw TransactionInactiveError</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"> </div>
+<script>
+ var db,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0" },
+ { pKey: "primaryKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", {keyPath:"pKey"});
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var cursor_rq = db.transaction("test")
+ .objectStore("test")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ assert_true(cursor instanceof IDBCursor, "cursor exists");
+
+ e.target.transaction.abort();
+ assert_throws("TransactionInactiveError", function() {
+ cursor.continue();
+ }, "Calling continue() should throws an exception TransactionInactiveError when the transaction is not active.");
+
+
+ t.done();
+ });
+ };
+</script>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_objectstore6.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_objectstore6.htm
new file mode 100644
index 00000000000..f9d656ebf89
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_continue_objectstore6.htm
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBCursor.continue() - object store - throw InvalidStateError caused by object store been deleted</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"> </div>
+<script>
+ var db,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0" },
+ { pKey: "primaryKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", {keyPath:"pKey"});
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+
+ var cursor_rq = objStore.openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ assert_true(cursor instanceof IDBCursor, "cursor exists");
+
+ db.deleteObjectStore("test");
+ assert_throws("InvalidStateError", function() {
+ cursor.continue();
+ }, "If the cursor's source or effective object store has been deleted, the implementation MUST throw a DOMException of type InvalidStateError");
+
+ t.done();
+ });
+ }
+</script>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_delete_index.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_delete_index.htm
new file mode 100644
index 00000000000..8cddcea994f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_delete_index.htm
@@ -0,0 +1,69 @@
+<!DOCTYPE html>
+<title>IDBCursor.delete() - index - remove a record from the object store</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ var db,
+ count = 0,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var objStore = db.createObjectStore("test", { keyPath: "pKey" });
+ objStore.createIndex("index", "iKey");
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = t.step_func(CursorDeleteRecord);
+
+
+ function CursorDeleteRecord(e) {
+ var txn = db.transaction("test", "readwrite"),
+ cursor_rq = txn.objectStore("test")
+ .index("index")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ assert_true(cursor instanceof IDBCursor, "cursor exist");
+ cursor.delete();
+ });
+
+ txn.oncomplete = t.step_func(VerifyRecordWasDeleted);
+ }
+
+
+ function VerifyRecordWasDeleted(e) {
+ var cursor_rq = db.transaction("test")
+ .objectStore("test")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ if (!cursor) {
+ assert_equals(count, 1, 'count');
+ t.done();
+ }
+
+ assert_equals(cursor.value.pKey, records[1].pKey);
+ assert_equals(cursor.value.iKey, records[1].iKey);
+ cursor.continue();
+ count++;
+ });
+ }
+
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_delete_index2.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_delete_index2.htm
new file mode 100644
index 00000000000..a5147f75450
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_delete_index2.htm
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<title>IDBCursor.delete() - index - attempt to remove a record in a read-only transaction</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var objStore = db.createObjectStore("test", { keyPath: "pKey" });
+ objStore.createIndex("index", "iKey");
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var cursor_rq = db.transaction("test")
+ .objectStore("test")
+ .index("index")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ assert_true(cursor instanceof IDBCursor, "cursor exist");
+ assert_throws('ReadOnlyError', function() { cursor.delete(); });
+ t.done();
+ });
+ }
+
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_delete_index3.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_delete_index3.htm
new file mode 100644
index 00000000000..bb5722ee351
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_delete_index3.htm
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<title>IDBCursor.delete() - index - attempt to remove a record in an inactive transaction</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ var db,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", { keyPath: "pKey" });
+ var index = objStore.createIndex("index", "iKey");
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+
+ var cursor_rq = index.openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ assert_true(cursor instanceof IDBCursor, "cursor exist");
+ window.cursor = cursor;
+ });
+
+ e.target.transaction.oncomplete = t.step_func(function(e) {
+ assert_throws('TransactionInactiveError', function() { window.cursor.delete(); })
+ t.done();
+ });
+ }
+
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_delete_index4.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_delete_index4.htm
new file mode 100644
index 00000000000..9b57bd681a9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_delete_index4.htm
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBCursor.delete() - index - throw InvalidStateError caused by object store been deleted</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+
+ var db,
+ t = async_test(),
+ records = [{ pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" }];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function (event) {
+ db = event.target.result;
+ var objStore = db.createObjectStore("store", {keyPath : "pKey"});
+ objStore.createIndex("index", "iKey");
+ for (var i = 0; i < records.length; i++) {
+ objStore.add(records[i]);
+ }
+ var rq = objStore.index("index").openCursor();
+ rq.onsuccess = t.step_func(function(event) {
+ var cursor = event.target.result;
+ assert_true(cursor instanceof IDBCursor, "cursor exist");
+
+ db.deleteObjectStore("store");
+ assert_throws("InvalidStateError", function() {
+ cursor.delete();
+ }, "If the cursor's source or effective object store has been deleted, the implementation MUST throw a DOMException of type InvalidStateError");
+
+ t.done();
+ });
+ }
+
+</script>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_delete_index5.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_delete_index5.htm
new file mode 100644
index 00000000000..66eacdebe66
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_delete_index5.htm
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBCursor.delete() - index - throw InvalidStateError when the cursor is being iterated</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBCursor-delete-IDBRequest">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test(),
+ records = [{ pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" }];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function (event) {
+ db = event.target.result;
+ var objStore = db.createObjectStore("store", {keyPath : "pKey"});
+ objStore.createIndex("index", "iKey");
+ for (var i = 0; i < records.length; i++) {
+ objStore.add(records[i]);
+ }
+
+ var rq = objStore.index("index").openCursor();
+ rq.onsuccess = t.step_func(function(event) {
+ var cursor = event.target.result;
+ assert_true(cursor instanceof IDBCursor, "cursor exist");
+
+ cursor.continue();
+ assert_throws("InvalidStateError", function() {
+ cursor.delete();
+ });
+
+ t.done();
+ });
+ }
+</script>
+
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_delete_objectstore.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_delete_objectstore.htm
new file mode 100644
index 00000000000..044a4e57183
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_delete_objectstore.htm
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<title>IDBCursor.delete() - object store - remove a record from the object store </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ var db,
+ count = 0,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0" },
+ { pKey: "primaryKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var objStore = db.createObjectStore("test", { keyPath: "pKey" });
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = t.step_func(CursorDeleteRecord);
+
+
+ function CursorDeleteRecord(e) {
+ var txn = db.transaction("test", "readwrite"),
+ cursor_rq = txn.objectStore("test").openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ assert_true(cursor != null, "cursor exist");
+ cursor.delete();
+ });
+
+ txn.oncomplete = t.step_func(VerifyRecordWasDeleted);
+ }
+
+
+ function VerifyRecordWasDeleted(e) {
+ var cursor_rq = db.transaction("test")
+ .objectStore("test")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ if (!cursor) {
+ assert_equals(count, 1, 'count');
+ t.done();
+ }
+
+ assert_equals(cursor.value.pKey, records[1].pKey);
+ count++;
+ cursor.continue();
+ });
+ }
+
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_delete_objectstore2.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_delete_objectstore2.htm
new file mode 100644
index 00000000000..69521e66b79
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_delete_objectstore2.htm
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<title>IDBCursor.delete() - object store - attempt to remove a record in a read-only transaction</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var objStore = db.createObjectStore("test", { keyPath: "pKey" });
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var cursor_rq = db.transaction("test")
+ .objectStore("test")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ assert_true(cursor != null, "cursor exist");
+ assert_throws('ReadOnlyError', function() { cursor.delete(); });
+ t.done();
+ });
+ }
+
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_delete_objectstore3.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_delete_objectstore3.htm
new file mode 100644
index 00000000000..bdb8d93c34f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_delete_objectstore3.htm
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<title>IDBCursor.delete() - index - attempt to remove a record in an inactive transaction</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ var db,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", { keyPath: "pKey" });
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+
+ var cursor_rq = objStore.openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ assert_true(cursor instanceof IDBCursor, "cursor exist");
+ window.cursor = cursor;
+ });
+
+ e.target.transaction.oncomplete = t.step_func(function(e) {
+ assert_throws('TransactionInactiveError', function() { window.cursor.delete(); })
+ t.done();
+ });
+ }
+
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_delete_objectstore4.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_delete_objectstore4.htm
new file mode 100644
index 00000000000..47bcd8b0057
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_delete_objectstore4.htm
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBCursor.delete() - object store - throw InvalidStateError caused by object store been deleted</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+
+ var db,
+ t = async_test(),
+ records = [{ pKey: "primaryKey_0"},
+ { pKey: "primaryKey_1"}];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function (event) {
+ db = event.target.result;
+ var objStore = db.createObjectStore("store", {keyPath:"pKey"});
+ for (var i = 0; i < records.length; i++) {
+ objStore.add(records[i]);
+ }
+ var rq = objStore.openCursor();
+ rq.onsuccess = t.step_func(function(event) {
+ var cursor = event.target.result;
+ assert_true(cursor instanceof IDBCursor, "cursor exist");
+
+ db.deleteObjectStore("store");
+ assert_throws("InvalidStateError", function() {
+ cursor.delete();
+ }, "If the cursor's source or effective object store has been deleted, the implementation MUST throw a DOMException of type InvalidStateError");
+
+ t.done();
+ });
+ }
+
+</script>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_delete_objectstore5.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_delete_objectstore5.htm
new file mode 100644
index 00000000000..b37e26126a9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_delete_objectstore5.htm
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBCursor.delete() - object store - throw InvalidStateError when the cursor is being iterated</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBCursor-delete-IDBRequest">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test(),
+ records = [{ pKey: "primaryKey_0"},
+ { pKey: "primaryKey_1"}];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function (event) {
+ db = event.target.result;
+ var objStore = db.createObjectStore("store", {keyPath:"pKey"});
+ for (var i = 0; i < records.length; i++) {
+ objStore.add(records[i]);
+ }
+ }
+
+ open_rq.onsuccess = function (event) {
+ var txn = db.transaction("store", "readwrite");
+ var rq = txn.objectStore("store").openCursor();
+ rq.onsuccess = t.step_func(function(event) {
+ var cursor = event.target.result;
+ assert_true(cursor instanceof IDBCursor, "cursor exist");
+
+ cursor.continue();
+ assert_throws("InvalidStateError", function() {
+ cursor.delete();
+ });
+
+ t.done();
+ });
+ }
+</script>
+
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_iterating.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_iterating.htm
new file mode 100644
index 00000000000..fd3cd0a690d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_iterating.htm
@@ -0,0 +1,110 @@
+<!DOCTYPE html>
+<title>IDBCursor.continue() - objectstore - delete next element, and iterate to it</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ count = 0,
+ t = async_test(document.title, {timeout: 10000});
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", { keyPath: "key" });
+
+ for (var i = 0; i < 500; i++)
+ objStore.add({ key: i, val: "val_"+i });
+
+ var rq = objStore.add({ key: 500, val: "val_500" });
+
+ rq.onsuccess = t.step_func(function() {
+ for (var i = 999; i > 500; i--)
+ objStore.add({ key: i, val: "val_"+i });
+ });
+
+ objStore.createIndex('index', ['key', 'val']);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var cursor_rq = db.transaction("test", "readwrite")
+ .objectStore("test")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result,
+ store = e.target.source;
+ if (!cursor) {
+ assert_equals(count, 997, "cursor run count");
+
+ var rq = e.target.source.count();
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result, 995, "object count");
+ t.done();
+ });
+ return;
+ }
+
+ switch (cursor.key) {
+ case 10:
+ assert_equals(count, cursor.key, "count");
+ store.delete(11);
+ break;
+
+ case 12:
+ case 499:
+ case 500:
+ case 501:
+ assert_equals(count, cursor.key - 1, "count");
+ break;
+
+ // Delete the next key
+ case 510:
+ store.delete(511);
+ break;
+
+ // Delete randomly
+ case 512:
+ store.delete(611);
+ store.delete(499);
+ store.delete(500);
+ break;
+
+ // Delete and add a new key
+ case 520:
+ store.delete(521);
+ store.add({ key: 521, val: "new"});
+ break;
+
+ case 521:
+ assert_equals(cursor.value.val, "new");
+ break;
+
+ // We should only be here once although we're basically making the index
+ // "heavier" with its new key.
+ case 530:
+ assert_equals(cursor.value.val, "val_530");
+ cursor.update({ key: 530, val: "val_531" })
+
+ store.get(530).onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result.val, "val_531");
+ });
+ break;
+
+ // Shouldn't happen.
+ case 11:
+ case 511:
+ case 611:
+ assert_unreached(cursor.key + " should be deleted and never run");
+ break;
+ }
+
+ cursor.continue();
+ count++;
+ });
+ };
+</script>
+
+<div id="log"> </div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_iterating_index.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_iterating_index.htm
new file mode 100644
index 00000000000..559cce6db54
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_iterating_index.htm
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<title>IDBCursor.continue() - index - delete next element, and iterate to it</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ count = 0,
+ t = async_test(document.title, {timeout: 10000}),
+ records = [ { pKey: "primaryKey_0", obj: { iKey: "iKey_0" }},
+ { pKey: "primaryKey_1", obj: { iKey: "iKey_1" }},
+ { pKey: "primaryKey_2", obj: { iKey: "iKey_2" }} ],
+
+ expected = [ [ "primaryKey_2", "iKey_2" ],
+ [ "primaryKey_0", "iKey_0" ] ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", {keyPath:["pKey", "obj.iKey"]});
+ objStore.createIndex("index", [ "pKey", "obj.iKey" ]);
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var cursor_rq = db.transaction("test", "readwrite")
+ .objectStore("test")
+ .index("index")
+ .openCursor(null, "prev");
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ if (!cursor) {
+ assert_equals(count, 2, "cursor run count");
+ t.done();
+ }
+
+ if (count === 0) {
+ e.target.source.objectStore.delete(["primaryKey_1", "iKey_1"]);
+ }
+ assert_array_equals(cursor.key, expected[count], "primary key");
+
+ cursor.continue();
+ count++;
+ });
+ };
+</script>
+
+<div id="log"> </div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_iterating_index2.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_iterating_index2.htm
new file mode 100644
index 00000000000..91a8383500c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_iterating_index2.htm
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<title>IDBCursor.continue() - index - add next element, and iterate to it</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ count = 0,
+ t = async_test(document.title, {timeout: 10000}),
+ records = [ { pKey: "primaryKey_0", obj: { iKey: "iKey_0" }},
+ { pKey: "primaryKey_2", obj: { iKey: "iKey_2" }} ],
+
+ expected = [ [ "primaryKey_2", "iKey_2" ],
+ [ "primaryKey_1", "iKey_1" ],
+ [ "primaryKey_0", "iKey_0" ] ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", {keyPath:"pKey"});
+ objStore.createIndex("index", [ "pKey", "obj.iKey" ]);
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var cursor_rq = db.transaction("test", "readwrite")
+ .objectStore("test")
+ .index("index")
+ .openCursor(null, "prev");
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ if (!cursor) {
+ assert_equals(count, 3, "cursor run count");
+ t.done();
+ }
+
+ if (count === 0) {
+ e.target.source.objectStore.add({ pKey: "primaryKey_1", obj: { iKey: "iKey_1" } });
+ }
+ assert_array_equals(cursor.key, expected[count], "primary key");
+
+ cursor.continue();
+ count++;
+ });
+ };
+</script>
+
+<div id="log"> </div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_iterating_objectstore.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_iterating_objectstore.htm
new file mode 100644
index 00000000000..db66c4db33b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_iterating_objectstore.htm
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<title>IDBCursor.continue() - objectstore - delete next element, and iterate to it</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ count = 0,
+ t = async_test(document.title, {timeout: 10000}),
+ records = [ { pKey: "primaryKey_0" },
+ { pKey: "primaryKey_1" },
+ { pKey: "primaryKey_2" } ],
+ expected_records = [ { pKey: "primaryKey_0" },
+ { pKey: "primaryKey_2" }];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", {keyPath:"pKey"});
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var cursor_rq = db.transaction("test", "readwrite")
+ .objectStore("test")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ if (!cursor) {
+ assert_equals(count, 2, "cursor run count");
+ t.done();
+ }
+
+ var record = cursor.value;
+ if (record.pKey == "primaryKey_0") {
+ e.target.source.delete("primaryKey_1");
+ }
+ assert_equals(record.pKey, expected_records[count].pKey, "primary key");
+
+ cursor.continue();
+ count++;
+ });
+ };
+</script>
+
+<div id="log"> </div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_iterating_objectstore2.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_iterating_objectstore2.htm
new file mode 100644
index 00000000000..2374a854e44
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_iterating_objectstore2.htm
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<title>IDBCursor.continue() - objectstore - add next element, and iterate to it</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ count = 0,
+ t = async_test(document.title, {timeout: 10000}),
+ records = [ { pKey: "primaryKey_0" },
+ { pKey: "primaryKey_2" } ],
+ expected_records = [ { pKey: "primaryKey_0" },
+ { pKey: "primaryKey_1" },
+ { pKey: "primaryKey_2" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", {keyPath:"pKey"});
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var cursor_rq = db.transaction("test", "readwrite")
+ .objectStore("test")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ if (!cursor) {
+ assert_equals(count, 3, "cursor run count");
+ t.done();
+ }
+
+ var record = cursor.value;
+ if (record.pKey == "primaryKey_0") {
+ e.target.source.add({ pKey: "primaryKey_1" });
+ }
+ assert_equals(record.pKey, expected_records[count].pKey, "primary key");
+
+ cursor.continue();
+ count++;
+ });
+ };
+</script>
+
+<div id="log"> </div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_index.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_index.htm
new file mode 100644
index 00000000000..5fa1f940a99
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_index.htm
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<title>IDBCursor.update() - index - modify a record in the object store </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ var db,
+ count = 0,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var objStore = db.createObjectStore("test", { keyPath: "pKey" });
+ objStore.createIndex("index", "iKey");
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+
+ // XXX: Gecko doesn't like this
+ //e.target.transaction.oncomplete = t.step_func(CursorUpdateRecord);
+ };
+
+ open_rq.onsuccess = CursorUpdateRecord;
+
+
+ function CursorUpdateRecord(e) {
+ var txn = db.transaction("test", "readwrite"),
+ cursor_rq = txn.objectStore("test")
+ .index("index")
+ .openCursor();
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ cursor.value.iKey += "_updated";
+ cursor.update(cursor.value);
+ });
+
+ txn.oncomplete = t.step_func(VerifyRecordWasUpdated);
+ }
+
+
+ function VerifyRecordWasUpdated(e) {
+ var cursor_rq = db.transaction("test")
+ .objectStore("test")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ assert_equals(cursor.value.iKey, records[0].iKey + "_updated");
+ t.done();
+ });
+ }
+
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_index2.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_index2.htm
new file mode 100644
index 00000000000..03f9c2712cb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_index2.htm
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<title>IDBCursor.update() - index - attempt to modify a record in a read-only transaction</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var objStore = db.createObjectStore("test", { keyPath: "pKey" });
+ objStore.createIndex("index", "iKey");
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var cursor_rq = db.transaction("test")
+ .objectStore("test")
+ .index("index")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ assert_throws('ReadOnlyError', function() { cursor.update(cursor.value); });
+ t.done();
+ });
+ }
+
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_index3.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_index3.htm
new file mode 100644
index 00000000000..0f7b2a1dbe5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_index3.htm
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<title>IDBCursor.update() - index - attempt to modify a record in an inactive transaction</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ var db,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", { keyPath: "pKey" });
+ var index = objStore.createIndex("index", "iKey");
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+
+ var cursor_rq = index.openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ assert_true(cursor instanceof IDBCursor, "cursor exist");
+ window.cursor = cursor;
+ window.record = cursor.value;
+ });
+
+ e.target.transaction.oncomplete = t.step_func(function(e) {
+ assert_throws('TransactionInactiveError', function() { window.cursor.update(window.record); })
+ t.done();
+ });
+ }
+
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_index4.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_index4.htm
new file mode 100644
index 00000000000..ee60da0d214
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_index4.htm
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBCursor.update() - index - attempt to modify a record when object store been deleted</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+
+ var db,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function (event) {
+ db = event.target.result;
+ var objStore = db.createObjectStore("store", {keyPath : "pKey"});
+ objStore.createIndex("index", "iKey");
+ for (var i = 0; i < records.length; i++) {
+ objStore.add(records[i]);
+ }
+ var rq = objStore.index("index").openCursor();
+ rq.onsuccess = t.step_func(function(event) {
+ var cursor = event.target.result;
+ assert_true(cursor instanceof IDBCursor);
+
+ db.deleteObjectStore("store");
+ cursor.value.iKey += "_updated";
+ assert_throws("InvalidStateError", function() {
+ cursor.update(cursor.value);
+ }, "If the cursor's source or effective object store has been deleted, the implementation MUST throw a DOMException of type InvalidStateError");
+
+ t.done();
+ });
+ }
+
+</script>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_index5.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_index5.htm
new file mode 100644
index 00000000000..a31528d1658
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_index5.htm
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<title>IDBCursor.update() - index - throw DataCloneError</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBCursor-update-IDBRequest-any-value">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var objStore = db.createObjectStore("test", { keyPath: "pKey" });
+ objStore.createIndex("index", "iKey");
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var cursor_rq = db.transaction("test", "readwrite")
+ .objectStore("test")
+ .index("index")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ assert_true(cursor instanceof IDBCursor);
+
+ var record = cursor.value;
+ record.data = document;
+ assert_throws('DataCloneError', function() {
+ cursor.update(record);
+ });
+ t.done();
+ });
+ }
+</script>
+
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_index6.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_index6.htm
new file mode 100644
index 00000000000..1e51b1354cf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_index6.htm
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<title>IDBCursor.update() - index - no argument</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBCursor-update-IDBRequest-any-value">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var objStore = db.createObjectStore("test", { keyPath: "pKey" });
+ objStore.createIndex("index", "iKey");
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var cursor_rq = db.transaction("test")
+ .objectStore("test")
+ .index("index")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ assert_true(cursor instanceof IDBCursor);
+
+ assert_throws(new TypeError(), function() { cursor.update(); });
+ t.done();
+ });
+ }
+</script>
+
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_index7.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_index7.htm
new file mode 100644
index 00000000000..1d464fbcdee
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_index7.htm
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<title>IDBCursor.update() - index - throw DataError</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBCursor-update-IDBRequest-any-value">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var objStore = db.createObjectStore("test", { keyPath: "pKey" });
+ objStore.createIndex("index", "iKey");
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var cursor_rq = db.transaction("test", "readwrite")
+ .objectStore("test")
+ .index("index")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ assert_true(cursor instanceof IDBCursor);
+
+ assert_throws('DataError', function() { cursor.update(null); });
+ t.done();
+ });
+ }
+</script>
+
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_objectstore.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_objectstore.htm
new file mode 100644
index 00000000000..8aa6a13721d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_objectstore.htm
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<title>IDBCursor.update() - objectstore - modify a record in the object store </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ var db,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0" },
+ { pKey: "primaryKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", { keyPath: "pKey" });
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+
+ // XXX: Gecko doesn't like this
+ //e.target.transaction.oncomplete = t.step_func(CursorUpdateRecord);
+ };
+
+ open_rq.onsuccess = CursorUpdateRecord;
+
+
+ function CursorUpdateRecord(e) {
+ var txn = db.transaction("test", "readwrite"),
+ cursor_rq = txn.objectStore("test")
+ .openCursor();
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ cursor.value.data = "New information!";
+ cursor.update(cursor.value);
+ });
+
+ txn.oncomplete = t.step_func(VerifyRecordWasUpdated);
+ }
+
+
+ function VerifyRecordWasUpdated(e) {
+ var cursor_rq = db.transaction("test")
+ .objectStore("test")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ assert_equals(cursor.value.data, "New information!");
+ t.done();
+ });
+ }
+
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_objectstore2.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_objectstore2.htm
new file mode 100644
index 00000000000..65c87bd9536
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_objectstore2.htm
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<title>IDBCursor.update() - object store - attempt to modify a record in a read-only transaction</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var objStore = db.createObjectStore("test", { keyPath: "pKey" });
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var cursor_rq = db.transaction("test")
+ .objectStore("test")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ assert_throws('ReadOnlyError', function() { cursor.update(cursor.value); });
+ t.done();
+ });
+ }
+
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_objectstore3.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_objectstore3.htm
new file mode 100644
index 00000000000..0ce59de29c9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_objectstore3.htm
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<title>IDBCursor.update() - object store - attempt to modify a record in an inactive transaction</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ var db,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", { keyPath: "pKey" });
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+
+ var cursor_rq = objStore.openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ assert_true(cursor instanceof IDBCursor, "cursor exist");
+ window.cursor = cursor;
+ window.record = cursor.value;
+ });
+
+ e.target.transaction.oncomplete = t.step_func(function(e) {
+ assert_throws('TransactionInactiveError', function() { window.cursor.update(window.record); })
+ t.done();
+ });
+ }
+
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_objectstore4.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_objectstore4.htm
new file mode 100644
index 00000000000..cbd0b1f92a6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_objectstore4.htm
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<title>IDBCursor.update() - index - modify a record in the object store </title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ var db,
+ t = async_test(document.title, {timeout: 10000})
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test");
+
+ objStore.add("data", "key");
+ };
+
+ open_rq.onsuccess = t.step_func(function(e) {
+ var txn = db.transaction("test", "readwrite"),
+ cursor_rq = txn.objectStore("test")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ cursor.value = "new data!";
+ cursor.update(cursor.value).onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result, "key");
+ t.done();
+ });
+ });
+ });
+
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_objectstore5.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_objectstore5.htm
new file mode 100644
index 00000000000..5dfb82ca19d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_objectstore5.htm
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBCursor.update() - object store - attempt to modify a record when object store been deleted</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+
+ var db,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0" },
+ { pKey: "primaryKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", {keyPath:"pKey"});
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+
+ var cursor_rq = objStore.openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ assert_true(cursor instanceof IDBCursor, "cursor exists");
+
+ db.deleteObjectStore("test");
+ cursor.value += "_updated";
+ assert_throws("InvalidStateError", function() {
+ cursor.update(cursor.value);
+ }, "If the cursor's source or effective object store has been deleted, the implementation MUST throw a DOMException of type InvalidStateError");
+
+
+ t.done();
+ });
+ }
+
+</script>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_objectstore6.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_objectstore6.htm
new file mode 100644
index 00000000000..16aa00dfae0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_objectstore6.htm
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<title>IDBCursor.update() - object store - throw DataCloneError</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBCursor-update-IDBRequest-any-value">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var objStore = db.createObjectStore("test", { keyPath: "pKey" });
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var cursor_rq = db.transaction("test", "readwrite")
+ .objectStore("test")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ assert_true(cursor instanceof IDBCursor);
+
+ var record = cursor.value;
+ record.data = document;
+ assert_throws('DataCloneError', function() {
+ cursor.update(record);
+ });
+ t.done();
+ });
+ }
+</script>
+
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_objectstore7.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_objectstore7.htm
new file mode 100644
index 00000000000..b1b736cf0ce
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_objectstore7.htm
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<title>IDBCursor.update() - object store - no argument</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBCursor-update-IDBRequest-any-value">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var objStore = db.createObjectStore("test", { keyPath: "pKey" });
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var cursor_rq = db.transaction("test", "readwrite")
+ .objectStore("test")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ assert_true(cursor instanceof IDBCursor);
+
+ assert_throws(new TypeError(), function() { cursor.update(); });
+ t.done();
+ });
+ }
+</script>
+
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_objectstore8.htm b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_objectstore8.htm
new file mode 100644
index 00000000000..f0b8900d4b0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbcursor_update_objectstore8.htm
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<title>IDBCursor.update() - object store - throw DataError</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBCursor-update-IDBRequest-any-value">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var objStore = db.createObjectStore("test", { keyPath: "pKey" });
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var cursor_rq = db.transaction("test", "readwrite")
+ .objectStore("test")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ assert_true(cursor instanceof IDBCursor);
+
+ assert_throws('DataError', function() { cursor.update(null); });
+ t.done();
+ });
+ }
+</script>
+
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_close.htm b/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_close.htm
new file mode 100644
index 00000000000..46485a4303c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_close.htm
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<title>IDBDatabase.close() - unblock the version change transaction created by an open database request</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+var db;
+var versionchange_fired;
+var blocked_fired;
+var upgradeneeded_fired;
+var t = async_test();
+var open_rq = createdb(t);
+var counter = 0;
+
+open_rq.onupgradeneeded = function() {}
+open_rq.onsuccess = function(e) {
+ db = e.target.result;
+ db.onversionchange = t.step_func(function(e) {
+ versionchange_fired = counter++;
+ });
+ var rq = window.indexedDB.open(db.name, db.version + 1);
+ rq.onblocked = t.step_func(function (e) {
+ blocked_fired = counter++;
+ db.close();
+ });
+ rq.onupgradeneeded = t.step_func(function (e) {
+ upgradeneeded_fired = counter++;
+ });
+ rq.onsuccess = t.step_func(function (e) {
+ assert_equals(versionchange_fired, 0, 'block event fired #')
+ assert_equals(blocked_fired, 1, 'block event fired #')
+ assert_equals(upgradeneeded_fired, 2, 'second upgradeneeded event fired #')
+
+ t.done();
+ });
+ rq.onerror = fail(t, 'Unexpected database deletion error');
+};
+
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_close2.htm b/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_close2.htm
new file mode 100644
index 00000000000..68bafb94638
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_close2.htm
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<title>IDBDatabase.close() - unblock the delete database request</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+var db;
+var blocked_fired = false;
+var versionchange_fired = false;
+var t = async_test();
+var open_rq = createdb(t);
+
+open_rq.onupgradeneeded = t.step_func(function() {});
+open_rq.onsuccess = t.step_func(function(e) {
+ db = e.target.result;
+
+ db.onversionchange = t.step_func(function (e) {
+ versionchange_fired = true;
+ });
+
+ var rq = window.indexedDB.deleteDatabase(db.name);
+ rq.onblocked = t.step_func(function (e) {
+ blocked_fired = true;
+ db.close();
+ });
+ rq.onsuccess = t.step_func(function (e) {
+ assert_true(versionchange_fired, "versionchange event fired")
+ assert_true(blocked_fired, "block event fired")
+ t.done();
+ });
+ rq.onerror = fail(t, 'Unexpected database deletion error');
+});
+
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_createObjectStore-createIndex-emptyname.htm b/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_createObjectStore-createIndex-emptyname.htm
new file mode 100644
index 00000000000..97f860a7a8f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_createObjectStore-createIndex-emptyname.htm
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>IDBDatabase.createObjectStore() and IDBObjectStore.createIndex() - both with empty name</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var db
+
+ var open_rq = createdb(async_test())
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result
+ var store = db.createObjectStore("")
+
+ for (var i = 0; i < 5; i++)
+ store.add({ idx: "object_" + i }, i)
+
+ store.createIndex("", "idx")
+
+ store.get(4)
+ .onsuccess = this.step_func(function(e) {
+ assert_equals(e.target.result.idx, 'object_4', 'result')
+ })
+ assert_equals(store.indexNames[0], "", "indexNames[0]")
+ assert_equals(store.indexNames.length, 1, "indexNames.length")
+ }
+
+ open_rq.onsuccess = function() {
+ var store = db.transaction("").objectStore("")
+
+ assert_equals(store.indexNames[0], "", "indexNames[0]")
+ assert_equals(store.indexNames.length, 1, "indexNames.length")
+
+ store.index("")
+ .get('object_4')
+ .onsuccess = this.step_func(function(e) {
+ assert_equals(e.target.result.idx, 'object_4', 'result')
+ this.done()
+ })
+ }
+</script>
+
+<div id=log></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_createObjectStore.htm b/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_createObjectStore.htm
new file mode 100644
index 00000000000..36fe9325001
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_createObjectStore.htm
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>IDBDatabase.createObjectStore() - returns an instance of IDBObjectStore</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+
+var t = async_test(),
+ open_rq = createdb(t)
+
+open_rq.onupgradeneeded = function(e) {
+ var db = e.target.result
+ var objStore = db.createObjectStore('instancetest')
+
+ assert_true(objStore instanceof IDBObjectStore, 'instanceof IDBObjectStore')
+}
+
+open_rq.onsuccess = function(e) {
+ var db = e.target.result
+ var objStore = db.transaction('instancetest').objectStore('instancetest')
+
+ assert_true(objStore instanceof IDBObjectStore, 'instanceof IDBObjectStore')
+ t.done()
+}
+</script>
+
+<div id=log></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_createObjectStore10-1000ends.htm b/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_createObjectStore10-1000ends.htm
new file mode 100644
index 00000000000..d6e4a48ed1c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_createObjectStore10-1000ends.htm
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<title>IDBDatabase.createObjectStore() - create 1000 object stores, add one item and delete</title>
+<meta name=timeout content=long>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+var db,
+ t = async_test(document.title, {timeout: 600000}),
+ open_rq = createdb(t)
+
+open_rq.onupgradeneeded = function(e) {
+ db = e.target.result
+ var st, i;
+ for (i = 0; i < 1000; i++)
+ {
+ st = db.createObjectStore("object_store_" + i)
+ st.add("test", 1);
+ }
+
+ st.get(1).onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result, "test")
+ })
+}
+open_rq.onsuccess = function(e) {
+ db.close()
+ window.indexedDB.deleteDatabase(db.name).onsuccess = function(e) {
+ t.done()
+ }
+}
+</script>
+
+
+<div id="log"></div>
+
+
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_createObjectStore10-emptyname.htm b/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_createObjectStore10-emptyname.htm
new file mode 100644
index 00000000000..cee4754a8eb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_createObjectStore10-emptyname.htm
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>IDBDatabase.createObjectStore() - empty name</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var db
+
+ var open_rq = createdb(async_test())
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result
+ var store = db.createObjectStore("")
+
+ for (var i = 0; i < 5; i++)
+ store.add("object_" + i, i)
+
+ assert_equals(db.objectStoreNames[0], "", "db.objectStoreNames[0]")
+ assert_equals(db.objectStoreNames.length, 1, "objectStoreNames.length")
+ }
+
+ open_rq.onsuccess = function() {
+ var store = db.transaction("").objectStore("")
+
+ store.get(2).onsuccess = this.step_func(function(e) {
+ assert_equals(e.target.result, "object_2")
+ })
+
+ assert_equals(db.objectStoreNames[0], "", "db.objectStoreNames[0]")
+ assert_equals(db.objectStoreNames.length, 1, "objectStoreNames.length")
+
+ this.done()
+ }
+</script>
+
+<div id=log></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_createObjectStore11.htm b/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_createObjectStore11.htm
new file mode 100644
index 00000000000..8d98953e065
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_createObjectStore11.htm
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBDatabase.createObjectStore() - Attampt Create Exsists Object Store With Difference keyPath throw ConstraintError </title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBDatabase-createObjectStore-IDBObjectStore-DOMString-name-IDBObjectStoreParameters-optionalParameters">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+var t = async_test(),
+ open_rq = createdb(t);
+
+open_rq.onupgradeneeded = function (e) {
+ var db = e.target.result;
+ db.createObjectStore("store");
+ assert_throws("ConstraintError", function(){
+ db.createObjectStore("store", {
+ keyPath: "key1",
+ });
+ });
+ t.done();
+}
+</script>
+
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_createObjectStore2.htm b/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_createObjectStore2.htm
new file mode 100644
index 00000000000..78f06ff9b90
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_createObjectStore2.htm
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<title>IDBDatabase.createObjectStore() - object store 'name' and 'keyPath' properties are correctly set </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+var t = async_test(),
+ open_rq = createdb(t)
+
+open_rq.onupgradeneeded = function(e) {
+ var db = e.target.result,
+ objStore = db.createObjectStore("prop", { keyPath: "mykeypath" })
+
+ assert_equals(objStore.name, "prop", "object store name")
+ assert_equals(objStore.keyPath, "mykeypath", "key path")
+ assert_equals(objStore.autoIncrement, false, "auto increment")
+}
+
+open_rq.onsuccess = function(e) {
+ var db = e.target.result
+ var objStore = db.transaction('prop').objectStore('prop')
+
+ assert_equals(objStore.name, "prop", "object store name")
+ assert_equals(objStore.keyPath, "mykeypath", "key path")
+ assert_equals(objStore.autoIncrement, false, "auto increment")
+ t.done()
+}
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_createObjectStore3.htm b/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_createObjectStore3.htm
new file mode 100644
index 00000000000..ccf4a2b5fde
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_createObjectStore3.htm
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<title>IDBDatabase.createObjectStore() - attempt to create an object store outside of a version change transaction </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+var t = async_test(),
+ open_rq = createdb(t)
+
+open_rq.onupgradeneeded = function() {}
+open_rq.onsuccess = function (e) {
+ var db = e.target.result
+ assert_throws(
+ 'InvalidStateError',
+ function() { db.createObjectStore('fails') })
+ t.done();
+}
+
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_createObjectStore4.htm b/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_createObjectStore4.htm
new file mode 100644
index 00000000000..07d787bd9a1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_createObjectStore4.htm
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>IDBDatabase.createObjectStore() - attempt to create an object store that already exists </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+var t = async_test(),
+ open_rq = createdb(t)
+
+open_rq.onupgradeneeded = function(e) {
+ var db = e.target.result
+ db.createObjectStore("dupe")
+ assert_throws(
+ 'ConstraintError',
+ function() { db.createObjectStore("dupe") })
+
+ // Bonus test creating a new objectstore after the exception
+ db.createObjectStore("dupe ")
+ t.done()
+}
+
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_createObjectStore5.htm b/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_createObjectStore5.htm
new file mode 100644
index 00000000000..7e205096e4c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_createObjectStore5.htm
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<title>IDBDatabase.createObjectStore() - object store's name appears in database's list </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+var t = async_test(),
+ open_rq = createdb(t)
+
+open_rq.onupgradeneeded = function(e) {
+ var db = e.target.result
+
+ db.createObjectStore("My cool object store name")
+ assert_true(
+ db.objectStoreNames.contains("My cool object store name"),
+ 'objectStoreNames.contains')
+}
+
+open_rq.onsuccess = function(e) {
+ var db = e.target.result
+
+ assert_true(
+ db.objectStoreNames.contains("My cool object store name"),
+ 'objectStoreNames.contains (in success)')
+ t.done()
+}
+
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_createObjectStore6.htm b/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_createObjectStore6.htm
new file mode 100644
index 00000000000..c1200c5f93a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_createObjectStore6.htm
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<title>IDBDatabase.createObjectStore() - attempt to create an object store with an invalid key path </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+var t = async_test(),
+ open_rq = createdb(t)
+
+open_rq.onupgradeneeded = function(e) {
+ var db = e.target.result
+
+ assert_throws('SyntaxError', function() {
+ db.createObjectStore("invalidkeypath", { keyPath: "Invalid Keypath" })
+ })
+
+ assert_throws('SyntaxError', function() {
+ db.createObjectStore("invalidkeypath", { autoIncrement: true,
+ keyPath: "Invalid Keypath" })
+ })
+
+ t.done()
+}
+
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_createObjectStore7.htm b/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_createObjectStore7.htm
new file mode 100644
index 00000000000..358baeeecab
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_createObjectStore7.htm
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<title>IDBDatabase.createObjectStore() - create an object store with an unknown optional parameter </title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+var t = async_test(document.title, {timeout: 10000}),
+ open_rq = createdb(t)
+
+open_rq.onupgradeneeded = function(e) {
+ var db = e.target.result
+ db.createObjectStore("with unknown param", { parameter: 0 });
+
+ t.done()
+}
+
+</script>
+
+
+<div id="log"></div>
+
+
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_createObjectStore8-parameters.htm b/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_createObjectStore8-parameters.htm
new file mode 100644
index 00000000000..48a9993858c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_createObjectStore8-parameters.htm
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStoreParameters</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ function optionalParameters(desc, params) {
+ var t = async_test(document.title + " - " + desc);
+
+ createdb(t).onupgradeneeded = function(e) {
+ e.target.result.createObjectStore("store", params);
+
+ this.done();
+ };
+ }
+
+
+ optionalParameters("autoInc true", {autoIncrement: true});
+ optionalParameters("autoInc true, keyPath null", {autoIncrement: true, keyPath: null});
+ optionalParameters("autoInc true, keyPath undefined", {autoIncrement: true, keyPath: undefined});
+ optionalParameters("autoInc true, keyPath string", {autoIncrement: true, keyPath: "a"});
+
+ optionalParameters("autoInc false, keyPath empty", {autoIncrement: false, keyPath: ""});
+ optionalParameters("autoInc false, keyPath array", {autoIncrement: false, keyPath: ["h", "j"]});
+ optionalParameters("autoInc false, keyPath string", {autoIncrement: false, keyPath: "abc"});
+
+ optionalParameters("keyPath empty", {keyPath: ""});
+ optionalParameters("keyPath array", {keyPath: ["a","b"]});
+ optionalParameters("keyPath string", {keyPath: "abc"});
+ optionalParameters("keyPath null", {keyPath: null});
+ optionalParameters("keyPath undefined", {keyPath: undefined});
+
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_createObjectStore9-invalidparameters.htm b/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_createObjectStore9-invalidparameters.htm
new file mode 100644
index 00000000000..0a6dc03a67a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_createObjectStore9-invalidparameters.htm
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>createObjectStore: Invalid optionalParameters</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ function invalid_optionalParameters(desc, params) {
+ var t = async_test(document.title + " - " + desc);
+
+ createdb(t).onupgradeneeded = function(e) {
+ assert_throws(null, function() {
+ e.target.result.createObjectStore("store", params);
+ });
+
+ this.done();
+ };
+ }
+
+ invalid_optionalParameters("autoInc and empty keyPath", {autoIncrement: true, keyPath: ""});
+ invalid_optionalParameters("autoInc and keyPath array", {autoIncrement: true, keyPath: []});
+ invalid_optionalParameters("autoInc and keyPath array 2", {autoIncrement: true, keyPath: ["hey"]});
+ invalid_optionalParameters("autoInc and keyPath object", {autoIncrement: true, keyPath: {a:"hey", b:2}});
+
+</script>
+
+<div id=log></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_deleteObjectStore.htm b/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_deleteObjectStore.htm
new file mode 100644
index 00000000000..b69570cc063
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_deleteObjectStore.htm
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<title>IDBDatabase.deleteObjectStore() - object store's name is removed from database's list </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+var t = async_test(),
+ open_rq = createdb(t)
+
+open_rq.onupgradeneeded = function(e) {
+ var db = e.target.result
+
+ db.createObjectStore("deleted");
+ db.deleteObjectStore("deleted");
+ assert_false(db.objectStoreNames.contains("deleted"))
+
+ t.done()
+}
+
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_deleteObjectStore2.htm b/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_deleteObjectStore2.htm
new file mode 100644
index 00000000000..3c1abe63232
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_deleteObjectStore2.htm
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<title>IDBDatabase.deleteObjectStore() - attempt to remove an object store outside of a version change transaction </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+var t = async_test(),
+ open_rq = createdb(t);
+
+open_rq.onupgradeneeded = function(e)
+{
+ var db = e.target.result,
+ objStore = db.createObjectStore("delete_outside");
+
+ e.target.transaction.oncomplete = t.step_func(function (e)
+ {
+ assert_throws('InvalidStateError',
+ function() { db.deleteObjectStore("delete_outside"); });
+ t.done();
+ });
+}
+
+</script>
+
+
+<div id="log"></div>
+
+
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_deleteObjectStore3.htm b/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_deleteObjectStore3.htm
new file mode 100644
index 00000000000..cae00f9d220
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_deleteObjectStore3.htm
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<title>IDBDatabase.deleteObjectStore() - attempt to remove an object store that does not exist </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+var t = async_test(),
+ open_rq = createdb(t);
+
+open_rq.onupgradeneeded = function(e)
+{
+ var db = e.target.result;
+ assert_throws('NotFoundError',
+ function() { db.deleteObjectStore('whatever'); });
+ t.done();
+}
+
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_deleteObjectStore4-not_reused.htm b/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_deleteObjectStore4-not_reused.htm
new file mode 100644
index 00000000000..f724d092ba2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_deleteObjectStore4-not_reused.htm
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>IDBDatabase.deleteObjectStore() - the object store is not reused</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+
+var t = async_test(document.title, {timeout: 10000}),
+ keys = [],
+ open_rq = createdb(t)
+
+open_rq.onupgradeneeded = function(e) {
+ var db = e.target.result
+
+ var objStore = db.createObjectStore("resurrected", { autoIncrement: true, keyPath: "k" });
+ objStore.add({k:5}).onsuccess = function(e) { keys.push(e.target.result); }
+ objStore.add({}).onsuccess = function(e) { keys.push(e.target.result); }
+ objStore.createIndex("idx", "i");
+ assert_true(objStore.indexNames.contains("idx"));
+ assert_equals(objStore.keyPath, "k", "keyPath");
+
+ db.deleteObjectStore("resurrected");
+
+ var objStore2 = db.createObjectStore("resurrected", { autoIncrement: true });
+ objStore2.add("Unicorns'R'us").onsuccess = function(e) { keys.push(e.target.result); };
+ assert_false(objStore2.indexNames.contains("idx"), "index exist on new objstore");
+ assert_equals(objStore2.keyPath, null, "keyPath");
+
+ assert_throws("NotFoundError", function() { objStore2.index("idx"); });
+}
+
+open_rq.onsuccess = function(e) {
+ assert_object_equals(keys, [5, 6, 1], "keys");
+ t.done();
+}
+
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_transaction.htm b/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_transaction.htm
new file mode 100644
index 00000000000..94de8b43342
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_transaction.htm
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<title>IDBDatabase.transaction() - attempt to open a transaction with invalid scope</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+var db,
+ t = async_test(),
+ open_rq = createdb(t);
+
+open_rq.onupgradeneeded = function() {};
+open_rq.onsuccess = function(e) {
+ db = e.target.result;
+
+ assert_throws('NotFoundError', function() { db.transaction('non-existing'); });
+ t.done();
+};
+
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_transaction2.htm b/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_transaction2.htm
new file mode 100644
index 00000000000..310014bc510
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_transaction2.htm
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>IDBDatabase.transaction() - opening a transaction defaults to a read-only mode </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+var db,
+ t = async_test(),
+ open_rq = createdb(t);
+
+open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ db.createObjectStore('readonly');
+};
+open_rq.onsuccess = function(e) {
+ var txn = db.transaction('readonly');
+ assert_equals(txn.mode, "readonly", 'txn.mode');
+
+ t.done();
+};
+
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_transaction3.htm b/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_transaction3.htm
new file mode 100644
index 00000000000..9b353c7108f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_transaction3.htm
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<title>IDBDatabase.transaction() - attempt to open a transaction from closed database connection </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ open_rq = createdb(t);
+
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ db.createObjectStore('test');
+ };
+
+ open_rq.onsuccess = function(e) {
+ db.close();
+
+ assert_throws('InvalidStateError',
+ function() { db.transaction('test'); });
+
+ t.done();
+ };
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_transaction4.htm b/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_transaction4.htm
new file mode 100644
index 00000000000..515c499b0c8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_transaction4.htm
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>IDBDatabase.transaction() - attempt to open a transaction with invalid mode </title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(document.title, {timeout: 10000}),
+ open_rq = createdb(t);
+
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ db.createObjectStore('test');
+ };
+
+ open_rq.onsuccess = function(e) {
+ assert_throws({ name: 'TypeError' },
+ function() { db.transaction('test', 'whatever'); });
+
+ t.done();
+ };
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_transaction5.htm b/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_transaction5.htm
new file mode 100644
index 00000000000..b6b45ab9f28
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbdatabase_transaction5.htm
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBDatabase.transaction() - If storeNames is an empty list, the implementation must throw a DOMException of type InvalidAccessError</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBDatabase-transaction-IDBTransaction-DOMString-sequence-DOMString--storeNames-IDBTransactionMode-mode">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+var db,
+ t = async_test(),
+ open_rq = createdb(t);
+
+open_rq.onupgradeneeded = function() {};
+open_rq.onsuccess = function(e) {
+ db = e.target.result;
+ assert_throws('InvalidAccessError', function() { db.transaction([]); });
+ t.done();
+};
+</script>
+
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbfactory_cmp.htm b/tests/wpt/web-platform-tests/IndexedDB/idbfactory_cmp.htm
new file mode 100644
index 00000000000..7b301ece46d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbfactory_cmp.htm
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>IDBFactory.cmp() - compared keys return correct value</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ test(function() {
+ var greater = window.indexedDB.cmp(2, 1);
+ var equal = window.indexedDB.cmp(2, 2);
+ var less = window.indexedDB.cmp(1, 2);
+
+ assert_equals(greater, 1, "greater");
+ assert_equals(equal, 0, "equal");
+ assert_equals(less, -1, "less");
+ }, "IDBFactory.cmp()");
+</script>
+
+<div id=log></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbfactory_cmp2.htm b/tests/wpt/web-platform-tests/IndexedDB/idbfactory_cmp2.htm
new file mode 100644
index 00000000000..446bb465ce6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbfactory_cmp2.htm
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBFactory.cmp() - invalid key</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBFactory-cmp-short-any-first-any-second">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+<div id=log></div>
+<script>
+ test( function() {
+ assert_throws(new TypeError(), function() {
+ indexedDB.cmp();
+ });
+ }, "IDBFactory.cmp() - no argument");
+
+ test( function() {
+ assert_throws("DataError", function() {
+ indexedDB.cmp(null, null);
+ });
+ assert_throws("DataError", function() {
+ indexedDB.cmp(1, null);
+ });
+ assert_throws("DataError", function() {
+ indexedDB.cmp(null, 1);
+ });
+ }, "IDBFactory.cmp() - null");
+
+ test( function() {
+ assert_throws("DataError", function() {
+ indexedDB.cmp(NaN, NaN);
+ });
+ assert_throws("DataError", function() {
+ indexedDB.cmp(1, NaN);
+ });
+ assert_throws("DataError", function() {
+ indexedDB.cmp(NaN, 1);
+ });
+ }, "IDBFactory.cmp() - NaN");
+</script>
+
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbfactory_deleteDatabase.htm b/tests/wpt/web-platform-tests/IndexedDB/idbfactory_deleteDatabase.htm
new file mode 100644
index 00000000000..fd7a908d3d8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbfactory_deleteDatabase.htm
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<title>IDBFactory.deleteDatabase() - request has no source </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var open_rq = createdb(async_test(), undefined, 9);
+
+ open_rq.onupgradeneeded = function(e) {};
+ open_rq.onsuccess = function(e) {
+ var db = e.target.result;
+ db.close();
+
+ var delete_rq = window.indexedDB.deleteDatabase(db.name);
+ delete_rq.onerror = fail(this, "Unexpected delete_rq.error event");
+ delete_rq.onsuccess = this.step_func( function (e) {
+ assert_equals(e.target.source, null, "event.target.source")
+ this.done();
+ });
+ }
+</script>
+
+<div id=log></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbfactory_deleteDatabase2.htm b/tests/wpt/web-platform-tests/IndexedDB/idbfactory_deleteDatabase2.htm
new file mode 100644
index 00000000000..0c7c73a28fc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbfactory_deleteDatabase2.htm
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>IDBFactory.deleteDatabase() - result of the request is set to undefined</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBFactory-deleteDatabase-IDBOpenDBRequest-DOMString-name">
+<meta name=assert title="If the steps above are successful, the implementation must set the result of the request to undefined and fire a success event at the request.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var open_rq = createdb(async_test(), undefined, 9);
+
+ open_rq.onupgradeneeded = function(e) {};
+ open_rq.onsuccess = function(e) {
+ var db = e.target.result;
+ db.close();
+
+ var delete_rq = window.indexedDB.deleteDatabase(db.name);
+ delete_rq.onerror = fail(this, "Unexpected delete_rq.error event");
+ delete_rq.onsuccess = this.step_func( function (e) {
+ assert_equals(e.target.result, undefined, "result");
+ this.done();
+ });
+ }
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbfactory_deleteDatabase3.htm b/tests/wpt/web-platform-tests/IndexedDB/idbfactory_deleteDatabase3.htm
new file mode 100644
index 00000000000..e1cab41a5c1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbfactory_deleteDatabase3.htm
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<title>IDBFactory.deleteDatabase() - success event</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBFactory-deleteDatabase-IDBOpenDBRequest-DOMString-name">
+<meta name=assert title="If the steps above are successful, the implementation must set the result of the request to undefined and fire a success event at the request. The event must implement the IDBVersionChangeEvent interface and have oldVersion set to database version and have the newVersion property set to null.">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var db
+ var open_rq = createdb(async_test(document.title, {timeout: 10000}), undefined, 9)
+
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result
+ db.createObjectStore('os')
+ }
+ open_rq.onsuccess = function(e) {
+ db.close()
+
+ var delete_rq = window.indexedDB.deleteDatabase(db.name)
+ delete_rq.onerror = fail(this, "Unexpected delete_rq.error event")
+ delete_rq.onsuccess = this.step_func( function (e) {
+ assert_equals(e.oldVersion, 9, "oldVersion")
+ assert_equals(e.newVersion, null, "newVersion")
+ assert_equals(e.target.result, undefined, "result")
+ assert_true(e instanceof IDBVersionChangeEvent, "e instanceof IDBVersionChangeEvent")
+ this.done()
+ })
+ }
+</script>
+
+<div id=log></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbfactory_deleteDatabase4.htm b/tests/wpt/web-platform-tests/IndexedDB/idbfactory_deleteDatabase4.htm
new file mode 100644
index 00000000000..3a4e9944da5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbfactory_deleteDatabase4.htm
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<title>Test events opening a second database when one connection is open already</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<div id="log"></div>
+
+<script>
+
+ var t = async_test("Delete an existing database");
+
+ t.step(function() {
+ var openrq = indexedDB.open('db', 3);
+
+ openrq.onupgradeneeded = function(e) {
+ e.target.result.createObjectStore('store');
+ };
+ openrq.onsuccess = t.step_func(function(e) {
+ db = e.target.result;
+
+ // Errors
+ db.onversionchange = fail(t, "db.versionchange");
+ db.onerror = fail(t, "db.error");
+ db.abort = fail(t, "db.abort");
+
+ setTimeout(t.step_func(Second), 4);
+ db.close();
+ });
+
+ // Errors
+ openrq.onerror = fail(t, "open.error");
+ openrq.onblocked = fail(t, "open.blocked");
+ });
+
+ function Second(e) {
+ var deleterq = indexedDB.deleteDatabase('db');
+
+ deleterq.onsuccess = function(e) { t.done(); }
+
+ deleterq.onerror = fail(t, "delete.error");
+ deleterq.onblocked = fail(t, "delete.blocked");
+ deleterq.onupgradeneeded = fail(t, "delete.upgradeneeded");
+ }
+
+ async_test("Delete a nonexistant database").step(function(e) {
+ var deleterq = indexedDB.deleteDatabase('nonexistant');
+
+ deleterq.onsuccess = this.step_func(function(e) { this.done(); });
+
+ deleterq.onerror = fail(this, "delete.error");
+ deleterq.onblocked = fail(this, "delete.blocked");
+ deleterq.onupgradeneeded = fail(this, "delete.upgradeneeded");
+ });
+
+</script>
+</script>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbfactory_open.htm b/tests/wpt/web-platform-tests/IndexedDB/idbfactory_open.htm
new file mode 100644
index 00000000000..bca2cfdc801
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbfactory_open.htm
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<title>IDBFactory.open() - request has no source</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var open_rq = createdb(async_test(), undefined, 9);
+
+ open_rq.onupgradeneeded = function(e) {};
+ open_rq.onsuccess = function(e) {
+ assert_equals(e.target.source, null, "source")
+ this.done();
+ }
+</script>
+
+<div id="log"> </div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbfactory_open10.htm b/tests/wpt/web-platform-tests/IndexedDB/idbfactory_open10.htm
new file mode 100644
index 00000000000..598046ff98f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbfactory_open10.htm
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<title>IDBFactory.open() - error in upgradeneeded resets db</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var db, db2;
+ var open_rq = createdb(async_test(document.title, {timeout: 10000}), undefined, 9);
+
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var st = db.createObjectStore("store");
+ st.createIndex("index", "i");
+
+ assert_equals(db.version, 9, "first db.version");
+ assert_true(db.objectStoreNames.contains("store"), "objectStoreNames contains store");
+ assert_true(st.indexNames.contains("index"), "indexNames contains index");
+
+ st.add({i: "Joshua"}, 1);
+ st.add({i: "Jonas"}, 2);
+ };
+ open_rq.onsuccess = function(e) {
+ db.close();
+ var open_rq2 = window.indexedDB.open(db.name, 10);
+ open_rq2.onupgradeneeded = this.step_func(function(e) {
+ db2 = e.target.result;
+
+ db2.createObjectStore("store2");
+
+ var store = open_rq2.transaction.objectStore("store")
+ store.createIndex("index2", "i");
+
+ assert_equals(db2.version, 10, "db2.version");
+
+ assert_true(db2.objectStoreNames.contains("store"), "second objectStoreNames contains store");
+ assert_true(db2.objectStoreNames.contains("store2"), "second objectStoreNames contains store2");
+ assert_true(store.indexNames.contains("index"), "second indexNames contains index");
+ assert_true(store.indexNames.contains("index2"), "second indexNames contains index2");
+
+ store.add({i: "Odin"}, 3);
+ store.put({i: "Sicking"}, 2);
+
+ open_rq2.transaction.abort();
+ });
+ open_rq2.onerror = this.step_func(function(e) {
+ assert_equals(db2.version, 9, "db2.version after error");
+ assert_true(db2.objectStoreNames.contains("store"), "objectStoreNames contains store after error");
+ assert_false(db2.objectStoreNames.contains("store2"), "objectStoreNames not contains store2 after error");
+
+ var open_rq3 = window.indexedDB.open(db.name);
+ open_rq3.onsuccess = this.step_func(function(e) {
+ var db3 = e.target.result;
+
+ assert_true(db3.objectStoreNames.contains("store"), "third objectStoreNames contains store");
+ assert_false(db3.objectStoreNames.contains("store2"), "third objectStoreNames contains store2");
+
+ var st = db3.transaction("store").objectStore("store");
+
+ assert_equals(db3.version, 9, "db3.version");
+
+ assert_true(st.indexNames.contains("index"), "third indexNames contains index");
+ assert_false(st.indexNames.contains("index2"), "third indexNames contains index2");
+
+ st.openCursor(null, "prev").onsuccess = this.step_func(function(e) {
+ assert_equals(e.target.result.key, 2, "opencursor(prev) key");
+ assert_equals(e.target.result.value.i, "Jonas", "opencursor(prev) value");
+ });
+ st.get(3).onsuccess = this.step_func(function(e) {
+ assert_equals(e.target.result, undefined, "get(3)");
+ });
+
+ var idx = st.index("index");
+ idx.getKey("Jonas").onsuccess = this.step_func(function(e) {
+ assert_equals(e.target.result, 2, "getKey(Jonas)");
+ });
+ idx.getKey("Odin").onsuccess = this.step_func(function(e) {
+ assert_equals(e.target.result, undefined, "getKey(Odin)");
+ });
+ idx.getKey("Sicking").onsuccess = this.step_func(function(e) {
+ assert_equals(e.target.result, undefined, "getKey(Sicking)");
+ this.done();
+ });
+ });
+ });
+ };
+</script>
+
+<div id=log></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbfactory_open11.htm b/tests/wpt/web-platform-tests/IndexedDB/idbfactory_open11.htm
new file mode 100644
index 00000000000..66ea9d52559
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbfactory_open11.htm
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<title>IDBFactory.open() - second open's transaction is available to get objectStores</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var db;
+ var count_done = 0;
+ var open_rq = createdb(async_test(document.title, {timeout: 10000}));
+
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ db.createObjectStore("store");
+ assert_true(db.objectStoreNames.contains("store"), "objectStoreNames contains store");
+
+ var store = e.target.transaction.objectStore("store");
+ assert_equals(store.name, "store", "store.name");
+
+ store.add("data", 1);
+
+ store.count().onsuccess = this.step_func(function(e) {
+ assert_equals(e.target.result, 1, "count()");
+ count_done++;
+ });
+
+ store.add("data2", 2);
+ };
+ open_rq.onsuccess = function(e) {
+ var store = db.transaction("store").objectStore("store");
+ assert_equals(store.name, "store", "store.name");
+ store.count().onsuccess = this.step_func(function(e) {
+ assert_equals(e.target.result, 2, "count()");
+ count_done++;
+ });
+ db.close();
+
+ var open_rq2 = window.indexedDB.open(db.name, 10);
+ open_rq2.onupgradeneeded = this.step_func(function(e) {
+ var db2 = e.target.result;
+ assert_true(db2.objectStoreNames.contains("store"), "objectStoreNames contains store");
+ var store = open_rq2.transaction.objectStore("store");
+ assert_equals(store.name, "store", "store.name");
+
+ store.add("data3", 3);
+
+ store.count().onsuccess = this.step_func(function(e) {
+ assert_equals(e.target.result, 3, "count()");
+ count_done++;
+
+ assert_equals(count_done, 3, "count_done");
+ this.done();
+ });
+ });
+ };
+</script>
+
+<div id=log></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbfactory_open12.htm b/tests/wpt/web-platform-tests/IndexedDB/idbfactory_open12.htm
new file mode 100644
index 00000000000..763c4805155
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbfactory_open12.htm
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<title>IDBFactory.open() - upgradeneeded gets VersionChangeEvent</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var db;
+ var open_rq = createdb(async_test(document.title, {timeout: 10000}), undefined, 9);
+ var open2_t = async_test(document.title + " - second upgrade");
+
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ assert_true(e instanceof IDBVersionChangeEvent, "e instanceof IDBVersionChangeEvent");
+ assert_equals(e.oldVersion, 0, "oldVersion");
+ assert_equals(e.newVersion, 9, "newVersion");
+ assert_equals(e.type, "upgradeneeded", "event type");
+
+ assert_equals(db.version, 9, "db.version");
+ };
+ open_rq.onsuccess = function(e) {
+ assert_true(e instanceof Event, "e instanceof Event");
+ assert_false(e instanceof IDBVersionChangeEvent, "e not instanceof IDBVersionChangeEvent");
+ assert_equals(e.type, "success", "event type");
+ this.done();
+
+
+ /**
+ * Second test
+ */
+ db.onversionchange = function() { db.close(); };
+
+ var open_rq2 = createdb(open2_t, db.name, 10);
+ open_rq2.onupgradeneeded = function(e) {
+ var db2 = e.target.result;
+ assert_true(e instanceof IDBVersionChangeEvent, "e instanceof IDBVersionChangeEvent");
+ assert_equals(e.oldVersion, 9, "oldVersion");
+ assert_equals(e.newVersion, 10, "newVersion");
+ assert_equals(e.type, "upgradeneeded", "event type");
+
+ assert_equals(db2.version, 10, "new db.version");
+
+ this.done();
+ };
+ };
+</script>
+
+<div id=log></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbfactory_open2.htm b/tests/wpt/web-platform-tests/IndexedDB/idbfactory_open2.htm
new file mode 100644
index 00000000000..e4d54ee0a13
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbfactory_open2.htm
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<title>IDBFactory.open() - database 'name' and 'version' are correctly set</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var open_rq = createdb(async_test(), 'database_name', 13);
+
+ open_rq.onupgradeneeded = function(e) {};
+ open_rq.onsuccess = function(e) {
+ var db = e.target.result;
+ assert_equals(db.name, 'database_name', 'db.name');
+ assert_equals(db.version, 13, 'db.version');
+ this.done();
+ }
+</script>
+
+<div id=log></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbfactory_open3.htm b/tests/wpt/web-platform-tests/IndexedDB/idbfactory_open3.htm
new file mode 100644
index 00000000000..9ec6db5ab86
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbfactory_open3.htm
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>IDBFactory.open() - no version opens current database</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var open_rq = createdb(async_test(), undefined, 13);
+ var did_upgrade = false;
+
+ open_rq.onupgradeneeded = function() {};
+ open_rq.onsuccess = function(e) {
+ var db = e.target.result;
+ db.close();
+
+ var open_rq2 = window.indexedDB.open(db.name);
+ open_rq2.onsuccess = this.step_func(function(e) {
+ assert_equals(e.target.result.version, 13, "db.version")
+ this.done();
+ });
+ open_rq2.onupgradeneeded = fail(this, 'Unexpected upgradeneeded')
+ open_rq2.onerror = fail(this, 'Unexpected error')
+ }
+</script>
+
+<div id=log></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbfactory_open4.htm b/tests/wpt/web-platform-tests/IndexedDB/idbfactory_open4.htm
new file mode 100644
index 00000000000..15ca666b816
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbfactory_open4.htm
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<title>IDBFactory.open() - new database has default version</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var open_rq = createdb(async_test(), 'database_name');
+
+ open_rq.onupgradeneeded = function(e) {
+ assert_equals(e.target.result.version, 1, "db.version");
+ };
+ open_rq.onsuccess = function(e) {
+ assert_equals(e.target.result.version, 1, "db.version");
+ this.done();
+ };
+</script>
+
+<div id=log></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbfactory_open5.htm b/tests/wpt/web-platform-tests/IndexedDB/idbfactory_open5.htm
new file mode 100644
index 00000000000..d9460bb7eda
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbfactory_open5.htm
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<title>IDBFactory.open() - new database is empty</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var open_rq = createdb(async_test(), 'database_name');
+
+ open_rq.onupgradeneeded = function() {};
+ open_rq.onsuccess = function(e) {
+ assert_equals(e.target.result.objectStoreNames.length, 0, "objectStoreNames.length");
+ this.done();
+ };
+</script>
+
+<div id=log></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbfactory_open6.htm b/tests/wpt/web-platform-tests/IndexedDB/idbfactory_open6.htm
new file mode 100644
index 00000000000..bbb8ac02d37
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbfactory_open6.htm
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<title>IDBFactory.open() - open database with a lower version than current</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var open_rq = createdb(async_test(), undefined, 13);
+ var did_upgrade = false;
+
+ open_rq.onupgradeneeded = function() {};
+ open_rq.onsuccess = function(e) {
+ var db = e.target.result;
+ db.close();
+
+ var open_rq2 = window.indexedDB.open(db.name, 14);
+ open_rq2.onupgradeneeded = function() {};
+ open_rq2.onsuccess = this.step_func(open_previous_db);
+ open_rq2.onerror = fail(this, 'Unexpected error')
+ }
+
+ function open_previous_db(e) {
+ var open_rq3 = window.indexedDB.open(e.target.result.name, 13);
+ open_rq3.onerror = this.step_func(function(e) {
+ assert_equals(e.target.error.name, 'VersionError', 'e.target.error.name')
+ this.done();
+ });
+ open_rq3.onupgradeneeded = fail(this, 'Unexpected upgradeneeded')
+ open_rq3.onsuccess = fail(this, 'Unexpected success')
+ }
+</script>
+
+<div id=log></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbfactory_open7.htm b/tests/wpt/web-platform-tests/IndexedDB/idbfactory_open7.htm
new file mode 100644
index 00000000000..bd168f7557e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbfactory_open7.htm
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<title>IDBFactory.open() - open database with a higher version than current</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var open_rq = createdb(async_test(), undefined, 13);
+ var did_upgrade = false;
+
+ open_rq.onupgradeneeded = function() {};
+ open_rq.onsuccess = function(e) {
+ var db = e.target.result;
+ db.close();
+
+ var open_rq2 = window.indexedDB.open(db.name, 14);
+ open_rq2.onupgradeneeded = function() {
+ did_upgrade = true;
+ };
+ open_rq2.onsuccess = this.step_func(open_current_db);
+ open_rq2.onerror = fail(this, 'Unexpected error')
+ }
+
+ function open_current_db(e) {
+ var open_rq3 = window.indexedDB.open(e.target.result.name);
+ open_rq3.onsuccess = this.step_func(function(e) {
+ assert_equals(e.target.result.version, 14, "db.version")
+ this.done();
+ });
+ open_rq3.onupgradeneeded = fail(this, 'Unexpected upgradeneeded')
+ open_rq3.onerror = fail(this, 'Unexpected error')
+
+ assert_true(did_upgrade, 'did upgrade');
+ }
+</script>
+
+<div id=log></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbfactory_open8.htm b/tests/wpt/web-platform-tests/IndexedDB/idbfactory_open8.htm
new file mode 100644
index 00000000000..7e2ac93ec06
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbfactory_open8.htm
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>IDBFactory.open() - error in version change transaction aborts open</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var open_rq = createdb(async_test(), undefined, 13);
+ var did_upgrade = false;
+ var did_db_abort = false;
+
+ open_rq.onupgradeneeded = function(e) {
+ did_upgrade = true;
+ e.target.result.onabort = function() {
+ did_db_abort = true;
+ }
+ e.target.transaction.abort();
+ };
+ open_rq.onerror = function(e) {
+ assert_true(did_upgrade);
+ assert_equals(e.target.error.name, 'AbortError', 'target.error');
+ this.done()
+ };
+</script>
+
+<div id=log></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbfactory_open9.htm b/tests/wpt/web-platform-tests/IndexedDB/idbfactory_open9.htm
new file mode 100644
index 00000000000..d9f392cfdc3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbfactory_open9.htm
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<title>IDBFactory.open() - errors in version argument</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+function should_throw(val, name) {
+ if (!name) {
+ name = ((typeof val == "object" && val) ? "object" : format_value(val))
+ }
+ test(function() {
+ assert_throws(new TypeError(), function() {
+ window.indexedDB.open('test', val);
+ });
+ }, "Calling open() with version argument " + name + " should throw TypeError.")
+}
+
+should_throw(-1)
+should_throw(-0.5)
+should_throw(0)
+should_throw(0.5)
+should_throw(0.8)
+should_throw(0x20000000000000)
+should_throw(NaN)
+should_throw(Infinity)
+should_throw(-Infinity)
+should_throw("foo")
+should_throw(undefined)
+should_throw(null)
+should_throw(false)
+
+should_throw({
+ toString: function() { assert_unreached("toString should not be called for ToPrimitive [Number]"); },
+ valueOf: function() { return 0; }
+})
+should_throw({
+ toString: function() { return 0; },
+ valueOf: function() { return {}; }
+}, 'object (second)')
+should_throw({
+ toString: function() { return {}; },
+ valueOf: function() { return {}; },
+}, 'object (third)')
+
+/* Valid */
+
+function should_work(val) {
+ var t = async_test("Calling open() with version argument 1.5 should not throw.")
+ var rq = createdb(t)
+ rq.onupgradeneeded = function() {
+ t.done()
+ }
+}
+
+should_work(1.5)
+
+</script>
+
+<div id=log></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbindex-multientry-arraykeypath.htm b/tests/wpt/web-platform-tests/IndexedDB/idbindex-multientry-arraykeypath.htm
new file mode 100644
index 00000000000..3e584a6c4e2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbindex-multientry-arraykeypath.htm
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBIndex.multiEntry: array keyPath with multiEntry</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#key-construct">
+<link rel=assert title="XXX">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ createdb(async_test(document.title, {timeout: 10000})).onupgradeneeded = function(e) {
+ var store = e.target.result.createObjectStore("store");
+
+ assert_throws('InvalidAccessError', function() {
+ store.createIndex('actors', ['name'], { multiEntry: true })
+ });
+
+ this.done();
+ };
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbindex-multientry-big.htm b/tests/wpt/web-platform-tests/IndexedDB/idbindex-multientry-big.htm
new file mode 100644
index 00000000000..4f9df36e204
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbindex-multientry-big.htm
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBIndex.multiEntry - a 1000 entry multiEntry array</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#key-construct">
+<link rel=assert title="XXX">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t_add = async_test("Adding one item with 1000 multiEntry keys", { timeout: 10000 }),
+ t_get = async_test("Getting the one item by 1000 indeced keys ", { timeout: 10000 });
+
+ var open_rq = createdb(t_add);
+ var obj = { test: 'yo', idxkeys: [] };
+
+ for (var i = 0; i < 1000; i++)
+ obj.idxkeys.push('index_no_' + i);
+
+
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ db.createObjectStore('store')
+ .createIndex('index', 'idxkeys', { multiEntry: true });
+ };
+ open_rq.onsuccess = function(e) {
+ var tx = db.transaction('store', 'readwrite');
+ tx.objectStore('store')
+ .put(obj, 1)
+ .onsuccess = t_add.step_func(function(e)
+ {
+ assert_equals(e.target.result, 1, "put'd key");
+ this.done();
+ });
+
+ tx.oncomplete = t_get.step_func(function() {
+ var idx = db.transaction('store').objectStore('store').index('index')
+
+ for (var i = 0; i < 1000; i++)
+ {
+ idx.get('index_no_' + i).onsuccess = t_get.step_func(function(e) {
+ assert_equals(e.target.result.test, "yo");
+ });
+ }
+
+ idx.get('index_no_999').onsuccess = t_get.step_func(function(e) {
+ assert_equals(e.target.result.test, "yo");
+ assert_equals(e.target.result.idxkeys.length, 1000);
+ this.done();
+ });
+ });
+ };
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbindex-multientry.htm b/tests/wpt/web-platform-tests/IndexedDB/idbindex-multientry.htm
new file mode 100644
index 00000000000..4f44453e0a5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbindex-multientry.htm
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBIndex.multiEntry - adding keys</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#key-construct">
+<link rel=assert title="XXX">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ expected_keys = [1, 2, 2, 3, 3];
+
+ var open_rq = createdb(async_test(document.title, {timeout: 10000}))
+
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var store = db.createObjectStore("store")
+
+ store.createIndex('actors', 'name', { multiEntry: true })
+
+ store.add({name: 'Odin'}, 1);
+ store.add({name: ['Rita', 'Scheeta', {Bobby:'Bobby'}]}, 2);
+ store.add({name: [ {s: 'Robert'}, 'Neil', 'Bobby']}, 3);
+ };
+ open_rq.onsuccess = function(e) {
+ var gotten_keys = [];
+ var idx = db.transaction('store').objectStore('store').index('actors');
+
+ idx.getKey('Odin').onsuccess = this.step_func(function(e) {
+ gotten_keys.push(e.target.result)
+ });
+ idx.getKey('Rita').onsuccess = this.step_func(function(e) {
+ gotten_keys.push(e.target.result)
+ });
+ idx.getKey('Scheeta').onsuccess = this.step_func(function(e) {
+ gotten_keys.push(e.target.result)
+ });
+ idx.getKey('Neil').onsuccess = this.step_func(function(e) {
+ gotten_keys.push(e.target.result)
+ });
+ idx.getKey('Bobby').onsuccess = this.step_func(function(e) {
+ gotten_keys.push(e.target.result)
+
+ assert_object_equals(gotten_keys, expected_keys);
+ this.done();
+ });
+ }
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbindex_count.htm b/tests/wpt/web-platform-tests/IndexedDB/idbindex_count.htm
new file mode 100644
index 00000000000..1b84ef9b79e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbindex_count.htm
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>IDBIndex.count() - returns the number of records in the index </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var db, t = async_test();
+
+ var open_rq = createdb(t);
+
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var store = db.createObjectStore("store", { autoIncrement: true });
+ store.createIndex("index", "indexedProperty");
+
+ for(var i = 0; i < 10; i++) {
+ store.add({ indexedProperty: "data" + i });
+ }
+ }
+
+ open_rq.onsuccess = function(e) {
+ var rq = db.transaction("store")
+ .objectStore("store")
+ .index("index")
+ .count();
+
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result, 10);
+ t.done();
+ });
+ }
+</script>
+
+<div id=log></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbindex_count2.htm b/tests/wpt/web-platform-tests/IndexedDB/idbindex_count2.htm
new file mode 100644
index 00000000000..1494fe116fd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbindex_count2.htm
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>IDBIndex.count() - returns the number of records that have keys within the range </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var db, t = async_test();
+
+ var open_rq = createdb(t);
+
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var store = db.createObjectStore("store", { autoIncrement: true });
+ store.createIndex("index", "indexedProperty");
+
+ for(var i = 0; i < 10; i++) {
+ store.add({ indexedProperty: "data" + i });
+ }
+ }
+
+ open_rq.onsuccess = function(e) {
+ var rq = db.transaction("store")
+ .objectStore("store")
+ .index("index")
+ .count(IDBKeyRange.bound('data0', 'data4'));
+
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result, 5);
+ t.done();
+ });
+ }
+</script>
+
+<div id=log></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbindex_count3.htm b/tests/wpt/web-platform-tests/IndexedDB/idbindex_count3.htm
new file mode 100644
index 00000000000..7fb34347cdb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbindex_count3.htm
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>IDBIndex.count() - returns the number of records that have keys with the key</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var db
+
+ createdb(async_test()).onupgradeneeded = function(e) {
+ db = e.target.result
+
+ var store = db.createObjectStore("store", { autoIncrement: true })
+ store.createIndex("myindex", "idx")
+
+ for (var i = 0; i < 10; i++)
+ store.add({ idx: "data_" + (i%2) });
+
+ store.index("myindex").count("data_0").onsuccess = this.step_func(function(e) {
+ assert_equals(e.target.result, 5, "count(data_0)")
+ this.done()
+ })
+ }
+
+</script>
+<div id=log></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbindex_count4.htm b/tests/wpt/web-platform-tests/IndexedDB/idbindex_count4.htm
new file mode 100644
index 00000000000..addd99260d4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbindex_count4.htm
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBIndex.count() - throw DataError when using invalid key</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBIndex-count-IDBRequest-any-key">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db, t = async_test();
+
+ var open_rq = createdb(t);
+
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var store = db.createObjectStore("store", { autoIncrement: true });
+ store.createIndex("index", "indexedProperty");
+
+ for(var i = 0; i < 10; i++) {
+ store.add({ indexedProperty: "data" + i });
+ }
+ }
+
+ open_rq.onsuccess = function(e) {
+ var index = db.transaction("store")
+ .objectStore("store")
+ .index("index");
+
+ assert_throws("DataError", function() {
+ index.count(NaN);
+ });
+
+ t.done();
+ }
+</script>
+
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbindex_get.htm b/tests/wpt/web-platform-tests/IndexedDB/idbindex_get.htm
new file mode 100644
index 00000000000..835cbefd2c3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbindex_get.htm
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBIndex.get() - returns the record </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { key: 1, indexedProperty: "data" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("store", { keyPath: "key" });
+ index = objStore.createIndex("index", "indexedProperty");
+
+ objStore.add(record);
+ }
+
+ open_rq.onsuccess = function(e) {
+ var rq = db.transaction("store")
+ .objectStore("store")
+ .index("index")
+ .get(record.indexedProperty);
+
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result.key, record.key);
+ t.done();
+ });
+ }
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbindex_get2.htm b/tests/wpt/web-platform-tests/IndexedDB/idbindex_get2.htm
new file mode 100644
index 00000000000..52b1d371ebf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbindex_get2.htm
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBIndex.get() - returns the record where the index contains duplicate values </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ records = [ { key:1, indexedProperty:"data" },
+ { key:2, indexedProperty:"data" },
+ { key:3, indexedProperty:"data" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", { keyPath: "key" });
+ objStore.createIndex("index", "indexedProperty");
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var rq = db.transaction("test")
+ .objectStore("test")
+ .index("index")
+ .get("data");
+
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result.key, records[0].key);
+ t.done();
+ });
+ };
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbindex_get3.htm b/tests/wpt/web-platform-tests/IndexedDB/idbindex_get3.htm
new file mode 100644
index 00000000000..d0f90078905
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbindex_get3.htm
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBIndex.get() - attempt to retrieve a record that doesn't exist </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var rq = db.createObjectStore("test", { keyPath: "key" })
+ .createIndex("index", "indexedProperty")
+ .get(1);
+
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result, undefined);
+ t.done();
+ });
+ };
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbindex_get4.htm b/tests/wpt/web-platform-tests/IndexedDB/idbindex_get4.htm
new file mode 100644
index 00000000000..bd0cc5ec85e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbindex_get4.htm
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>IDBIndex.get() - returns the record with the first key in the range </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var db, t = async_test();
+
+ var open_rq = createdb(t);
+
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var store = db.createObjectStore("store", { keyPath: "key" });
+ store.createIndex("index", "indexedProperty");
+
+ for(var i = 0; i < 10; i++) {
+ store.add({ key: i, indexedProperty: "data" + i });
+ }
+ }
+
+ open_rq.onsuccess = function(e) {
+ var rq = db.transaction("store")
+ .objectStore("store")
+ .index("index")
+ .get(IDBKeyRange.bound('data4', 'data7'));
+
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result.key, 4);
+ assert_equals(e.target.result.indexedProperty, 'data4');
+
+ setTimeout(function() { t.done(); }, 4)
+ });
+ }
+</script>
+
+<div id=log></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbindex_get5.htm b/tests/wpt/web-platform-tests/IndexedDB/idbindex_get5.htm
new file mode 100644
index 00000000000..65e2623cdd9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbindex_get5.htm
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBIndex.get() - throw DataError when using invalid key </title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBIndex-get-IDBRequest-any-key">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var index = db.createObjectStore("test", { keyPath: "key" })
+ .createIndex("index", "indexedProperty");
+ assert_throws("DataError",function(){
+ index.get(NaN);
+ });
+ t.done();
+ };
+</script>
+
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbindex_get6.htm b/tests/wpt/web-platform-tests/IndexedDB/idbindex_get6.htm
new file mode 100644
index 00000000000..c7f6b92febe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbindex_get6.htm
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBIndex.get() - throw InvalidStateError when the index is deleted</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBIndex-get-IDBRequest-any-key">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var store = db.createObjectStore("store", { keyPath: "key" });
+ var index = store.createIndex("index", "indexedProperty");
+
+ store.add({ key: 1, indexedProperty: "data" });
+ store.deleteIndex("index");
+
+ assert_throws("InvalidStateError", function(){
+ index.get("data");
+ });
+ t.done();
+ }
+</script>
+
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbindex_get7.htm b/tests/wpt/web-platform-tests/IndexedDB/idbindex_get7.htm
new file mode 100644
index 00000000000..a49b0efc6ff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbindex_get7.htm
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBIndex.get() - throw TransactionInactiveError on aborted transaction</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBIndex-get-IDBRequest-any-key">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var store = db.createObjectStore("store", { keyPath: "key" });
+ var index = store.createIndex("index", "indexedProperty");
+ store.add({ key: 1, indexedProperty: "data" });
+
+ e.target.transaction.abort();
+
+ assert_throws("TransactionInactiveError", function(){
+ index.get("data");
+ });
+ t.done();
+ }
+</script>
+
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbindex_getKey.htm b/tests/wpt/web-platform-tests/IndexedDB/idbindex_getKey.htm
new file mode 100644
index 00000000000..536f2fd39f6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbindex_getKey.htm
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBIndex.getKey() - returns the record's primary key </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { key:1, indexedProperty:"data" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", { keyPath: "key" });
+ objStore.createIndex("index", "indexedProperty");
+
+ objStore.add(record);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var rq = db.transaction("test")
+ .objectStore("test");
+
+ rq = rq.index("index");
+
+ rq = rq.getKey("data");
+
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result, record.key);
+ t.done();
+ });
+ };
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbindex_getKey2.htm b/tests/wpt/web-platform-tests/IndexedDB/idbindex_getKey2.htm
new file mode 100644
index 00000000000..9e867324268
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbindex_getKey2.htm
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBIndex.getKey() - returns the record's primary key where the index contains duplicate values </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ records = [ { key:1, indexedProperty:"data" },
+ { key:2, indexedProperty:"data" },
+ { key:3, indexedProperty:"data" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", { keyPath: "key" });
+ objStore.createIndex("index", "indexedProperty");
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var rq = db.transaction("test")
+ .objectStore("test")
+ .index("index")
+ .getKey("data");
+
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result, records[0].key);
+ t.done();
+ });
+ };
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbindex_getKey3.htm b/tests/wpt/web-platform-tests/IndexedDB/idbindex_getKey3.htm
new file mode 100644
index 00000000000..238107ccc6a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbindex_getKey3.htm
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBIndex.getKey() - attempt to retrieve the primary key of a record that doesn't exist</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test();
+
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var rq = db.createObjectStore("test", { keyPath: "key" })
+ .createIndex("index", "indexedProperty")
+ .getKey(1);
+
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result, undefined);
+ t.done();
+ });
+ };
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbindex_getKey4.htm b/tests/wpt/web-platform-tests/IndexedDB/idbindex_getKey4.htm
new file mode 100644
index 00000000000..2002a5fe194
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbindex_getKey4.htm
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>IDBIndex.getKey() - returns the key of the first record within the range </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var db, t = async_test();
+
+ var open_rq = createdb(t);
+
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var store = db.createObjectStore("store", { keyPath: "key" });
+ store.createIndex("index", "indexedProperty");
+
+ for(var i = 0; i < 10; i++) {
+ store.add({ key: i, indexedProperty: "data" + i });
+ }
+ }
+
+ open_rq.onsuccess = function(e) {
+ var rq = db.transaction("store")
+ .objectStore("store")
+ .index("index")
+ .getKey(IDBKeyRange.bound('data4', 'data7'));
+
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result, 4);
+
+ setTimeout(function() { t.done(); }, 4)
+ });
+ }
+</script>
+
+<div id=log></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbindex_getKey5.htm b/tests/wpt/web-platform-tests/IndexedDB/idbindex_getKey5.htm
new file mode 100644
index 00000000000..96af868beaf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbindex_getKey5.htm
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBIndex.getKey() - throw DataError when using invalid key </title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBIndex-getKey-IDBRequest-any-key">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var index = db.createObjectStore("test", { keyPath: "key" })
+ .createIndex("index", "indexedProperty");
+ assert_throws("DataError",function(){
+ index.getKey(NaN);
+ });
+ t.done();
+ };
+</script>
+
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbindex_getKey6.htm b/tests/wpt/web-platform-tests/IndexedDB/idbindex_getKey6.htm
new file mode 100644
index 00000000000..6e9680da9ed
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbindex_getKey6.htm
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBIndex.getKey() - throw InvalidStateError when the index is deleted</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBIndex-getKey-IDBRequest-any-key">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var store = db.createObjectStore("store", { keyPath: "key" });
+ var index = store.createIndex("index", "indexedProperty");
+
+ store.add({ key: 1, indexedProperty: "data" });
+ store.deleteIndex("index");
+
+ assert_throws("InvalidStateError", function(){
+ index.getKey("data");
+ });
+ t.done();
+ }
+</script>
+
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbindex_getKey7.htm b/tests/wpt/web-platform-tests/IndexedDB/idbindex_getKey7.htm
new file mode 100644
index 00000000000..5a35ebb5c91
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbindex_getKey7.htm
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBIndex.getKey() - throw TransactionInactiveError on aborted transaction</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBIndex-getKey-IDBRequest-any-key">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var store = db.createObjectStore("store", { keyPath: "key" });
+ var index = store.createIndex("index", "indexedProperty");
+ store.add({ key: 1, indexedProperty: "data" });
+
+ e.target.transaction.abort();
+
+ assert_throws("TransactionInactiveError", function(){
+ index.getKey("data");
+ });
+ t.done();
+ }
+</script>
+
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbindex_indexNames.htm b/tests/wpt/web-platform-tests/IndexedDB/idbindex_indexNames.htm
new file mode 100644
index 00000000000..3099b45e91f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbindex_indexNames.htm
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBIndex.getKey() - returns the record's primary key</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(document.title, {timeout: 10000});
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", { keyPath: "key" });
+ objStore.createIndex("index", "data");
+
+ assert_equals(objStore.indexNames[0], "index", "indexNames");
+ assert_equals(objStore.indexNames.length, 1, "indexNames.length");
+ };
+
+ open_rq.onsuccess = function(e) {
+ var objStore = db.transaction("test")
+ .objectStore("test");
+
+ assert_equals(objStore.indexNames[0], "index", "indexNames (second)");
+ assert_equals(objStore.indexNames.length, 1, "indexNames.length (second)");
+
+ t.done();
+ };
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbindex_openCursor.htm b/tests/wpt/web-platform-tests/IndexedDB/idbindex_openCursor.htm
new file mode 100644
index 00000000000..0efff9325f7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbindex_openCursor.htm
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBIndex.openCursor() - throw InvalidStateError when the index is deleted</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBIndex-openCursor-IDBRequest-any-range-IDBCursorDirection-direction">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var store = db.createObjectStore("store", { keyPath: "key" });
+ var index = store.createIndex("index", "indexedProperty");
+
+ store.add({ key: 1, indexedProperty: "data" });
+ store.deleteIndex("index");
+
+ assert_throws("InvalidStateError", function(){
+ index.openCursor();
+ });
+ t.done();
+ }
+</script>
+
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbindex_openCursor2.htm b/tests/wpt/web-platform-tests/IndexedDB/idbindex_openCursor2.htm
new file mode 100644
index 00000000000..d39254055f1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbindex_openCursor2.htm
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBIndex.openCursor() - throw TransactionInactiveError on aborted transaction</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBIndex-openCursor-IDBRequest-any-range-IDBCursorDirection-direction">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var store = db.createObjectStore("store", { keyPath: "key" });
+ var index = store.createIndex("index", "indexedProperty");
+ store.add({ key: 1, indexedProperty: "data" });
+
+ e.target.transaction.abort();
+
+ assert_throws("TransactionInactiveError", function(){
+ index.openCursor();
+ });
+ t.done();
+ }
+</script>
+
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbindex_openKeyCursor.htm b/tests/wpt/web-platform-tests/IndexedDB/idbindex_openKeyCursor.htm
new file mode 100644
index 00000000000..e158802911e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbindex_openKeyCursor.htm
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBIndex.openKeyCursor() - throw DataError when using a invalid key</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBIndex-openKeyCursor-IDBRequest-any-range-IDBCursorDirection-direction">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var store = db.createObjectStore("store", { keyPath: "key" });
+ var index = store.createIndex("index", "indexedProperty");
+
+ store.add({ key: 1, indexedProperty: "data" });
+
+ assert_throws("DataError", function(){
+ index.openKeyCursor(NaN);
+ });
+ t.done();
+ }
+</script>
+
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbindex_openKeyCursor2.htm b/tests/wpt/web-platform-tests/IndexedDB/idbindex_openKeyCursor2.htm
new file mode 100644
index 00000000000..d8354c2fdaa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbindex_openKeyCursor2.htm
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBIndex.openKeyCursor() - throw InvalidStateError when the index is deleted</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBIndex-openKeyCursor-IDBRequest-any-range-IDBCursorDirection-direction">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var store = db.createObjectStore("store", { keyPath: "key" });
+ var index = store.createIndex("index", "indexedProperty");
+
+ store.add({ key: 1, indexedProperty: "data" });
+ store.deleteIndex("index");
+
+ assert_throws("InvalidStateError", function(){
+ index.openKeyCursor();
+ });
+ t.done();
+ }
+</script>
+
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbindex_openKeyCursor3.htm b/tests/wpt/web-platform-tests/IndexedDB/idbindex_openKeyCursor3.htm
new file mode 100644
index 00000000000..b4af3172417
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbindex_openKeyCursor3.htm
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBIndex.openKeyCursor() - throw TransactionInactiveError on aborted transaction</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBIndex-openKeyCursor-IDBRequest-any-range-IDBCursorDirection-direction">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var store = db.createObjectStore("store", { keyPath: "key" });
+ var index = store.createIndex("index", "indexedProperty");
+ store.add({ key: 1, indexedProperty: "data" });
+
+ e.target.transaction.abort();
+
+ assert_throws("TransactionInactiveError", function(){
+ index.openKeyCursor();
+ });
+ t.done();
+ }
+</script>
+
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbkeyrange.htm b/tests/wpt/web-platform-tests/IndexedDB/idbkeyrange.htm
new file mode 100644
index 00000000000..dd6e5f7e50e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbkeyrange.htm
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>IDBKeyRange Tests</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ // only
+ test( function() {
+ var keyRange = IDBKeyRange.only(1);
+ assert_true(keyRange instanceof IDBKeyRange, "keyRange instanceof IDBKeyRange");
+ assert_equals(keyRange.lower, 1, "keyRange");
+ assert_equals(keyRange.upper, 1, "keyRange");
+ assert_false(keyRange.lowerOpen, "keyRange.lowerOpen");
+ assert_false(keyRange.upperOpen, "keyRange.upperOpen");
+ }, "IDBKeyRange.only() - returns an IDBKeyRange and the properties are set correctly");
+
+ // lowerBound
+ test( function() {
+ var keyRange = IDBKeyRange.lowerBound(1, true)
+ assert_true(keyRange instanceof IDBKeyRange, "keyRange instanceof IDBKeyRange");
+ assert_equals(keyRange.lower, 1, "keyRange.lower");
+ assert_equals(keyRange.upper, undefined, "keyRange.upper");
+ assert_true(keyRange.lowerOpen, "keyRange.lowerOpen");
+ assert_true(keyRange.upperOpen, "keyRange.upperOpen");
+ }, "IDBKeyRange.lowerBound() - returns an IDBKeyRange and the properties are set correctly");
+
+ test( function() {
+ var keyRange = IDBKeyRange.lowerBound(1);
+ assert_false(keyRange.lowerOpen, "keyRange.lowerOpen");
+ }, "IDBKeyRange.lowerBound() - 'open' parameter has correct default set");
+
+ // upperBound
+ test( function() {
+ var keyRange = IDBKeyRange.upperBound(1, true);
+ assert_true(keyRange instanceof IDBKeyRange, "keyRange instanceof IDBKeyRange");
+ assert_equals(keyRange.lower, undefined, "keyRange.lower");
+ assert_equals(keyRange.upper, 1, "keyRange.upper");
+ assert_true(keyRange.lowerOpen, "keyRange.lowerOpen");
+ assert_true(keyRange.upperOpen, "keyRange.upperOpen");
+ }, "IDBKeyRange.upperBound() - returns an IDBKeyRange and the properties are set correctly");
+
+ test( function() {
+ var keyRange = IDBKeyRange.upperBound(1);
+ assert_false(keyRange.upperOpen, "keyRange.upperOpen");
+ }, "IDBKeyRange.upperBound() - 'open' parameter has correct default set");
+
+ // bound
+ test( function() {
+ var keyRange = IDBKeyRange.bound(1, 2, true, true);
+ assert_true(keyRange instanceof IDBKeyRange, "keyRange instanceof IDBKeyRange");
+ assert_equals(keyRange.lower, 1, "keyRange");
+ assert_equals(keyRange.upper, 2, "keyRange");
+ assert_true(keyRange.lowerOpen, "keyRange.lowerOpen");
+ assert_true(keyRange.upperOpen, "keyRange.upperOpen");
+ }, "IDBKeyRange.bound() - returns an IDBKeyRange and the properties are set correctly");
+
+ test( function() {
+ var keyRange = IDBKeyRange.bound(1, 2);
+ assert_false(keyRange.lowerOpen, "keyRange.lowerOpen");
+ assert_false(keyRange.upperOpen, "keyRange.upperOpen");
+ }, "IDBKeyRange.bound() - 'lowerOpen' and 'upperOpen' parameters have correct defaults set");
+</script>
+
+<div id=log></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbkeyrange_incorrect.htm b/tests/wpt/web-platform-tests/IndexedDB/idbkeyrange_incorrect.htm
new file mode 100644
index 00000000000..0449ca80732
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbkeyrange_incorrect.htm
@@ -0,0 +1,92 @@
+<!DOCTYPE html>
+<!-- Submitted from TestTWF Paris -->
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title id='desc'>IDBKeyRange Tests - Incorrect</title>
+ <link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#range-concept">
+ <link rel=assert title="If the lower key is greater than the upper key, then a DOMException of type DataError must be thrown.">
+ <link rel=author href="mailto:chrcharles67@gmail.com" title="Christophe CHARLES">
+
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="support.js"></script>
+
+ <script type="text/javascript">
+
+ // TypeError: bound requires more than 0 arguments
+ test( function() {
+ assert_throws(new TypeError(), function() {
+ IDBKeyRange.bound();
+ });
+ }, "IDBKeyRange.bound() - bound requires more than 0 arguments.");
+
+ // Null parameters
+ test( function() {
+ assert_throws("DataError", function() {
+ IDBKeyRange.bound(null, null);
+ });
+ }, "IDBKeyRange.bound(null, null) - null parameters are incorrect.");
+
+ // // Null parameter
+ test( function() {
+ assert_throws("DataError", function() {
+ IDBKeyRange.bound(1, null);
+ });
+ assert_throws("DataError", function() {
+ IDBKeyRange.bound(null, 1);
+ });
+ }, "IDBKeyRange.bound(1, null / null, 1) - null parameter is incorrect.");
+
+ // bound incorrect
+ test( function() {
+ var lowerBad = Math.floor(Math.random()*31) + 5;
+ var upper = lowerBad - 1;
+ assert_throws("DataError", function() {
+ IDBKeyRange.bound(lowerBad, upper);
+ });
+ assert_throws("DataError", function() {
+ IDBKeyRange.bound('b', 'a');
+ });
+ }, "IDBKeyRange.bound(lower, upper / lower > upper) - 'lower' is greater than 'upper'."
+ );
+
+ test( function() {
+ assert_throws("DataError", function() {
+ IDBKeyRange.bound('a', 1);
+ });
+ assert_throws("DataError", function() {
+ IDBKeyRange.bound(new Date(), 1);
+ });
+ assert_throws("DataError", function() {
+ IDBKeyRange.bound([1, 2], 1);
+ });
+ }, "IDBKeyRange.bound(DOMString/Date/Array, 1) - A DOMString, Date and Array are greater than a float.");
+
+
+ // ReferenceError: the variable is not defined
+ test( function() {
+ var goodVariable = 1;
+ assert_throws(new ReferenceError(), function() {
+ IDBKeyRange.bound(noExistingVariable, 1);
+ });
+ assert_throws(new ReferenceError(), function() {
+ IDBKeyRange.bound(goodVariable, noExistingVariable);
+ });
+ }, "IDBKeyRange.bound(noExistingVariable, 1 / goodVariable, noExistingVariable) - noExistingVariable is not defined.");
+
+ // Valid type key error
+ test( function() {
+ assert_throws("DataError", function() {
+ IDBKeyRange.bound(true, 1);
+ });
+ }, "IDBKeyRange.bound(true, 1) - boolean is not a valid key type.");
+
+
+ </script>
+ </head>
+
+ <body>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add.htm
new file mode 100644
index 00000000000..f091d1faf12
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add.htm
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.add() - add with an inline key </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { key: 1, property: "data" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("store", { keyPath: "key" });
+
+ objStore.add(record);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var rq = db.transaction("store")
+ .objectStore("store")
+ .get(record.key);
+
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result.property, record.property);
+ assert_equals(e.target.result.key, record.key);
+ t.done();
+ });
+ };
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add10.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add10.htm
new file mode 100644
index 00000000000..f2bf447500d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add10.htm
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.add() - Attempt to call 'add' without an key parameter when the object store uses out-of-line keys </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { property: "data" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var rq,
+ objStore = db.createObjectStore("store");
+
+ assert_throws("DataError",
+ function() { rq = objStore.add(record); });
+
+ assert_equals(rq, undefined);
+ t.done();
+ };
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add11.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add11.htm
new file mode 100644
index 00000000000..99ff14c31b3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add11.htm
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.add() - Attempt to add a record where the record's key does not meet the constraints of a valid key </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { key: { value: 1 }, property: "data" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var rq,
+ objStore = db.createObjectStore("store", { keyPath: "key" });
+
+ assert_throws("DataError",
+ function() { rq = objStore.add(record); });
+
+ assert_equals(rq, undefined);
+ t.done();
+ };
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add12.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add12.htm
new file mode 100644
index 00000000000..d679af08b41
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add12.htm
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.add() - Attempt to add a record where the record's in-line key is not defined </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { property: "data" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var rq,
+ objStore = db.createObjectStore("store", { keyPath: "key" });
+
+ assert_throws("DataError",
+ function() { rq = objStore.add(record); });
+
+ assert_equals(rq, undefined);
+ t.done();
+ };
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add13.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add13.htm
new file mode 100644
index 00000000000..943a6cf9baf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add13.htm
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.add() - Attempt to add a record where the out of line key provided does not meet the constraints of a valid key </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { property: "data" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var rq,
+ objStore = db.createObjectStore("store");
+
+ assert_throws("DataError",
+ function() { rq = objStore.add(record, { value: 1 }); });
+
+ assert_equals(rq, undefined);
+ t.done();
+ };
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add14.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add14.htm
new file mode 100644
index 00000000000..5bac57cb765
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add14.htm
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.add() - Add a record where a value being indexed does not meet the constraints of a valid key </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { key: 1, indexedProperty: { property: "data" } };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var rq,
+ objStore = db.createObjectStore("store", { keyPath: "key" });
+
+ objStore.createIndex("index", "indexedProperty");
+
+ rq = objStore.add(record);
+
+ assert_true(rq instanceof IDBRequest);
+ rq.onsuccess = function() {
+ t.done();
+ }
+ };
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add15.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add15.htm
new file mode 100644
index 00000000000..268ed72e935
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add15.htm
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.add() - If the transaction this IDBObjectStore belongs to has its mode set to readonly, throw ReadOnlyError </title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBObjectStore-add-IDBRequest-any-value-any-key">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function (event) {
+ db = event.target.result;
+ db.createObjectStore("store", {keyPath:"pKey"});
+ }
+
+ open_rq.onsuccess = function (event) {
+ var txn = db.transaction("store");
+ var ostore = txn.objectStore("store");
+ t.step(function(){
+ assert_throws("ReadOnlyError", function(){
+ ostore.add({ pKey: "primaryKey_0"});
+ });
+ });
+ t.done();
+ }
+</script>
+
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add16.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add16.htm
new file mode 100644
index 00000000000..a0ea3abbf07
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add16.htm
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.add() - If the object store has been deleted, the implementation must throw a DOMException of type InvalidStateError </title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBObjectStore-add-IDBRequest-any-value-any-key">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ ostore,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function (event) {
+ db = event.target.result;
+ ostore = db.createObjectStore("store", {keyPath:"pKey"});
+ db.deleteObjectStore("store");
+ }
+
+ open_rq.onsuccess = function (event) {
+ t.step(function(){
+ assert_throws("InvalidStateError", function(){
+ ostore.add({ pKey: "primaryKey_0"});
+ });
+ });
+ t.done();
+ }
+</script>
+
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add2.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add2.htm
new file mode 100644
index 00000000000..70c05544588
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add2.htm
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.add() - add with an out-of-line key </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ key = 1,
+ record = { property: "data" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("store");
+
+ objStore.add(record, key);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var rq = db.transaction("store")
+ .objectStore("store")
+ .get(key);
+
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result.property, record.property);
+
+ t.done();
+ });
+ };
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add3.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add3.htm
new file mode 100644
index 00000000000..ac397372d48
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add3.htm
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.add() - record with same key already exists </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { key: 1, property: "data" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("store", { keyPath: "key" });
+ objStore.add(record);
+
+ var rq = objStore.add(record);
+ rq.onsuccess = fail(t, "success on adding duplicate record")
+
+ rq.onerror = t.step_func(function(e) {
+ assert_equals(e.target.error.name, "ConstraintError");
+ assert_equals(rq.error.name, "ConstraintError");
+ assert_equals(e.type, "error");
+
+ e.preventDefault();
+ e.stopPropagation();
+ });
+ };
+
+ // Defer done, giving rq.onsuccess a chance to run
+ open_rq.onsuccess = function(e) {
+ t.done();
+ }
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add4.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add4.htm
new file mode 100644
index 00000000000..c4b875cd41f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add4.htm
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.add() - add where an index has unique:true specified </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { key: 1, property: "data" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("store", { autoIncrement: true });
+ objStore.createIndex("i1", "property", { unique: true });
+ objStore.add(record);
+
+ var rq = objStore.add(record);
+ rq.onsuccess = fail(t, "success on adding duplicate indexed record")
+
+ rq.onerror = t.step_func(function(e) {
+ assert_equals(rq.error.name, "ConstraintError");
+ assert_equals(e.target.error.name, "ConstraintError");
+ assert_equals(e.type, "error");
+
+ e.preventDefault();
+ e.stopPropagation();
+ });
+ };
+
+ // Defer done, giving a spurious rq.onsuccess a chance to run
+ open_rq.onsuccess = function(e) {
+ t.done();
+ }
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add5.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add5.htm
new file mode 100644
index 00000000000..1c1cd1fb284
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add5.htm
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.add() - object store's key path is an object attribute </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { test: { obj: { key: 1 } }, property: "data" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("store", { keyPath: "test.obj.key" });
+ objStore.add(record);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var rq = db.transaction("store")
+ .objectStore("store")
+ .get(record.test.obj.key);
+
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result.property, record.property);
+
+ t.done();
+ });
+ };
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add6.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add6.htm
new file mode 100644
index 00000000000..c6f1910a3ee
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add6.htm
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.add() - autoIncrement and inline keys </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { property: "data" },
+ expected_keys = [ 1, 2, 3, 4 ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("store", { keyPath: "key", autoIncrement: true });
+
+ objStore.add(record);
+ objStore.add(record);
+ objStore.add(record);
+ objStore.add(record);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var actual_keys = [],
+ rq = db.transaction("store")
+ .objectStore("store")
+ .openCursor();
+
+ rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ if (cursor) {
+ actual_keys.push(cursor.value.key);
+ cursor.continue();
+ }
+ else {
+ assert_array_equals(actual_keys, expected_keys);
+ t.done();
+ }
+ });
+ };
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add7.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add7.htm
new file mode 100644
index 00000000000..1b2a6dac3fa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add7.htm
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.add() - autoIncrement and out-of-line keys </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { property: "data" },
+ expected_keys = [ 1, 2, 3, 4 ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("store", { autoIncrement: true });
+
+ objStore.add(record);
+ objStore.add(record);
+ objStore.add(record);
+ objStore.add(record);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var actual_keys = [],
+ rq = db.transaction("store")
+ .objectStore("store")
+ .openCursor();
+
+ rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ if (cursor) {
+ actual_keys.push(cursor.key);
+ cursor.continue();
+ }
+ else {
+ assert_array_equals(actual_keys, expected_keys);
+ t.done();
+ }
+ });
+ };
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add8.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add8.htm
new file mode 100644
index 00000000000..b3266fdc0f6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add8.htm
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.add() - object store has autoIncrement:true and the key path is an object attribute </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { property: "data" },
+ expected_keys = [ 1, 2, 3, 4 ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("store", { keyPath: "test.obj.key", autoIncrement: true });
+
+ objStore.add(record);
+ objStore.add(record);
+ objStore.add(record);
+ objStore.add(record);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var actual_keys = [],
+ rq = db.transaction("store")
+ .objectStore("store")
+ .openCursor();
+
+ rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ if (cursor) {
+ actual_keys.push(cursor.value.test.obj.key);
+ cursor.continue();
+ }
+ else {
+ assert_array_equals(actual_keys, expected_keys);
+ t.done();
+ }
+ });
+ };
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add9.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add9.htm
new file mode 100644
index 00000000000..6e027a11dc4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_add9.htm
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.add() - Attempt to add a record that does not meet the constraints of an object store's inline key requirements </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var t = async_test(),
+ record = { key: 1, property: "data" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ var rq,
+ db = e.target.result,
+ objStore = db.createObjectStore("store", { keyPath: "key" });
+
+ assert_throws("DataError",
+ function() { rq = objStore.add(record, 1); });
+
+ assert_equals(rq, undefined);
+ t.done();
+ };
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_clear.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_clear.htm
new file mode 100644
index 00000000000..d9c3fb2a189
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_clear.htm
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.clear() - Verify clear removes all records </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("store", { autoIncrement: true });
+
+ objStore.add({ property: "data" });
+ objStore.add({ something_different: "Yup, totally different" });
+ objStore.add(1234);
+ objStore.add([1, 2, 1234]);
+
+ objStore.clear().onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result, undefined);
+ });
+ };
+
+
+ open_rq.onsuccess = function(e) {
+ var rq = db.transaction("store")
+ .objectStore("store")
+ .openCursor();
+
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result, null, 'cursor');
+ t.done();
+ });
+ };
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_clear2.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_clear2.htm
new file mode 100644
index 00000000000..ac1fdff4cac
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_clear2.htm
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.clear() - clear removes all records from an index </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("store", { autoIncrement: true });
+ objStore.createIndex("index", "indexedProperty");
+
+ objStore.add({ indexedProperty: "data" });
+ objStore.add({ indexedProperty: "yo, man", something_different: "Yup, totally different" });
+ objStore.add({ indexedProperty: 1234 });
+ objStore.add({ indexedProperty: [1, 2, 1234] });
+ objStore.add(1234);
+
+ objStore.clear().onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result, undefined);
+ });
+ };
+
+ open_rq.onsuccess = function(e) {
+ var rq = db.transaction("store")
+ .objectStore("store")
+ .index("index")
+ .openCursor();
+
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result, null, 'cursor');
+ t.done();
+ });
+ };
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_clear3.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_clear3.htm
new file mode 100644
index 00000000000..fc0fa4d8dff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_clear3.htm
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.clear() - If the transaction this IDBObjectStore belongs to has its mode set to readonly, throw ReadOnlyError </title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBObjectStore-clear-IDBRequest">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test(),
+ records = [{ pKey: "primaryKey_0"},
+ { pKey: "primaryKey_1"}];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function (event) {
+ db = event.target.result;
+ var objStore = db.createObjectStore("store", {keyPath:"pKey"});
+ for (var i = 0; i < records.length; i++) {
+ objStore.add(records[i]);
+ }
+ }
+
+ open_rq.onsuccess = function (event) {
+ var txn = db.transaction("store");
+ var ostore = txn.objectStore("store");
+ t.step(function(){
+ assert_throws("ReadOnlyError", function(){
+ ostore.clear();
+ });
+ });
+ t.done();
+ }
+</script>
+
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_clear4.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_clear4.htm
new file mode 100644
index 00000000000..298857a5972
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_clear4.htm
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.clear() - If the object store has been deleted, the implementation must throw a DOMException of type InvalidStateError </title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBObjectStore-clear-IDBRequest">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ ostore,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function (event) {
+ db = event.target.result;
+ ostore = db.createObjectStore("store", {keyPath:"pKey"});
+ db.deleteObjectStore("store");
+ }
+
+ open_rq.onsuccess = function (event) {
+ t.step(function(){
+ assert_throws("InvalidStateError", function(){
+ ostore.clear();
+ });
+ });
+ t.done();
+ }
+</script>
+
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_count.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_count.htm
new file mode 100644
index 00000000000..a54d16e435d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_count.htm
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>IDBObjectStore.count() - returns the number of records in the object store </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var db, t = async_test();
+
+ var open_rq = createdb(t);
+
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var store = db.createObjectStore("store");
+
+ for(var i = 0; i < 10; i++) {
+ store.add({ data: "data" + i }, i);
+ }
+ }
+
+ open_rq.onsuccess = function(e) {
+ var rq = db.transaction("store")
+ .objectStore("store")
+ .count();
+
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result, 10);
+ t.done();
+ });
+ }
+</script>
+
+<div id=log></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_count2.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_count2.htm
new file mode 100644
index 00000000000..b92715a2d99
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_count2.htm
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>IDBObjectStore.count() - returns the number of records that have keys within the range </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var db, t = async_test();
+
+ var open_rq = createdb(t);
+
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var store = db.createObjectStore("store");
+
+ for(var i = 0; i < 10; i++) {
+ store.add({ data: "data" + i }, i);
+ }
+ }
+
+ open_rq.onsuccess = function(e) {
+ var rq = db.transaction("store")
+ .objectStore("store")
+ .count(IDBKeyRange.bound(5,20));
+
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result, 5);
+ t.done();
+ });
+ }
+</script>
+
+<div id=log></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_count3.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_count3.htm
new file mode 100644
index 00000000000..970b87a3d84
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_count3.htm
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>IDBObjectStore.count() - returns the number of records that have keys with the key</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var db
+
+ createdb(async_test()).onupgradeneeded = function(e) {
+ db = e.target.result
+
+ var store = db.createObjectStore("store", { keyPath: "k" })
+
+ for (var i = 0; i < 5; i++)
+ store.add({ k: "key_" + i });
+
+ store.count("key_2").onsuccess = this.step_func(function(e) {
+ assert_equals(e.target.result, 1, "count(key_2)")
+
+ store.count("key_").onsuccess = this.step_func(function(e) {
+ assert_equals(e.target.result, 0, "count(key_)")
+ this.done()
+ })
+ })
+ }
+
+</script>
+<div id=log></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_count4.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_count4.htm
new file mode 100644
index 00000000000..6d7b34f5009
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_count4.htm
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.count() - If the object store has been deleted, the implementation must throw a DOMException of type InvalidStateError </title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBObjectStore-count-IDBRequest-any-key">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ ostore,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function (event) {
+ db = event.target.result;
+ ostore = db.createObjectStore("store", {keyPath:"pKey"});
+ db.deleteObjectStore("store");
+ }
+
+ open_rq.onsuccess = function (event) {
+ t.step(function(){
+ assert_throws("InvalidStateError", function(){
+ ostore.count();
+ });
+ });
+ t.done();
+ }
+</script>
+
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_createIndex.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_createIndex.htm
new file mode 100644
index 00000000000..8f0327c1a78
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_createIndex.htm
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.createIndex() - returns an IDBIndex and the properties are set correctly</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("store");
+ var index = objStore.createIndex("index", "indexedProperty", { unique: true });
+
+ assert_true(index instanceof IDBIndex, "IDBIndex");
+ assert_equals(index.name, "index", "name");
+ assert_equals(index.objectStore, objStore, "objectStore");
+ assert_equals(index.keyPath, "indexedProperty", "keyPath");
+ assert_true(index.unique, "unique");
+ assert_false(index.multiEntry, "multiEntry");
+
+ t.done();
+ };
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_createIndex10.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_createIndex10.htm
new file mode 100644
index 00000000000..757296253d4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_createIndex10.htm
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBDatabase.createIndex() - If an index with the name name already exists in this object store, the implementation must throw a DOMException of type ConstraintError </title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBObjectStore-createIndex-IDBIndex-DOMString-name-DOMString-sequence-DOMString--keyPath-IDBIndexParameters-optionalParameters">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+var t = async_test(),
+ open_rq = createdb(t);
+
+open_rq.onupgradeneeded = function (e) {
+ var db = e.target.result;
+ var ostore = db.createObjectStore("store");
+ ostore.createIndex("a", "a");
+ assert_throws("ConstraintError", function(){
+ ostore.createIndex("a", "a");
+ });
+ t.done();
+}
+</script>
+
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_createIndex11.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_createIndex11.htm
new file mode 100644
index 00000000000..7da1169e4c2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_createIndex11.htm
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBDatabase.createIndex() - If keyPath is not a valid key path, the implementation must throw a DOMException of type SyntaxError </title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBObjectStore-createIndex-IDBIndex-DOMString-name-DOMString-sequence-DOMString--keyPath-IDBIndexParameters-optionalParameters">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+var t = async_test(),
+ open_rq = createdb(t);
+
+open_rq.onupgradeneeded = function (e) {
+ var db = e.target.result;
+ var ostore = db.createObjectStore("store");
+ assert_throws("SyntaxError", function(){
+ ostore.createIndex("ab", ".");
+ });
+ t.done();
+}
+</script>
+
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_createIndex12.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_createIndex12.htm
new file mode 100644
index 00000000000..18296b4adbe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_createIndex12.htm
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBDatabase.createIndex() - If the object store has been deleted, the implementation must throw a DOMException of type InvalidStateError </title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBObjectStore-createIndex-IDBIndex-DOMString-name-DOMString-sequence-DOMString--keyPath-IDBIndexParameters-optionalParameters">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ ostore,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function (event) {
+ db = event.target.result;
+ ostore = db.createObjectStore("store");
+ db.deleteObjectStore("store");
+ }
+
+ open_rq.onsuccess = function (event) {
+ t.step(function(){
+ assert_throws("InvalidStateError", function(){
+ ostore.createIndex("index", "indexedProperty");
+ });
+ });
+ t.done();
+ }
+</script>
+
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_createIndex13.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_createIndex13.htm
new file mode 100644
index 00000000000..fb70cc72b8d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_createIndex13.htm
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBDatabase.createIndex() - Operate out versionchange throw InvalidStateError </title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBObjectStore-createIndex-IDBIndex-DOMString-name-DOMString-sequence-DOMString--keyPath-IDBIndexParameters-optionalParameters">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function (event) {
+ db = event.target.result;
+ db.createObjectStore("store");
+ }
+
+ open_rq.onsuccess = function (event) {
+ var txn = db.transaction("store", "readwrite");
+ ostore = txn.objectStore("store");
+ t.step(function(){
+ assert_throws("InvalidStateError", function(){
+ ostore.createIndex("index", "indexedProperty");
+ });
+ });
+ t.done();
+ }
+</script>
+
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_createIndex2.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_createIndex2.htm
new file mode 100644
index 00000000000..9dc1686b186
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_createIndex2.htm
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.createIndex() - attempt to create an index that requires unique values on an object store already contains duplicates </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db, aborted,
+ t = async_test(),
+ record = { indexedProperty: "bar" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var txn = e.target.transaction,
+ objStore = db.createObjectStore("store");
+
+ objStore.add(record, 1);
+ objStore.add(record, 2);
+ var index = objStore.createIndex("index", "indexedProperty", { unique: true });
+
+ assert_true(index instanceof IDBIndex, "IDBIndex");
+
+ e.target.transaction.onabort = t.step_func(function(e) {
+ aborted = true;
+ assert_equals(e.type, "abort", "event type");
+ });
+
+ db.onabort = function(e) {
+ assert_true(aborted, "transaction.abort event has fired");
+ t.done();
+ };
+
+ e.target.transaction.oncomplete = fail(t, "got complete, expected abort");
+ };
+
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_createIndex3-usable-right-away.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_createIndex3-usable-right-away.htm
new file mode 100644
index 00000000000..f4b9b984f05
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_createIndex3-usable-right-away.htm
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.createIndex() - the index is usable right after being made</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<meta name=timeout content=long>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db, aborted,
+ t = async_test(document.title, {timeout:19000})
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var txn = e.target.transaction,
+ objStore = db.createObjectStore("store", { keyPath: 'key' });
+
+ for (var i = 0; i < 100; i++)
+ objStore.add({ key: "key_" + i, indexedProperty: "indexed_" + i });
+
+ var idx = objStore.createIndex("index", "indexedProperty")
+
+ idx.get('indexed_99').onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result.key, 'key_99', 'key');
+ });
+ idx.get('indexed_9').onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result.key, 'key_9', 'key');
+ });
+ }
+
+ open_rq.onsuccess = function() {
+ t.done();
+ }
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_createIndex4-deleteIndex-event_order.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_createIndex4-deleteIndex-event_order.htm
new file mode 100644
index 00000000000..2dccc865e72
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_createIndex4-deleteIndex-event_order.htm
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.createIndex() - Event ordering for a later deleted index</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ events = [],
+ t = async_test(document.title, {timeout: 10000})
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ e.target.transaction.oncomplete = log("transaction.complete");
+
+ var txn = e.target.transaction,
+ objStore = db.createObjectStore("store");
+
+ var rq_add1 = objStore.add({ animal: "Unicorn" }, 1);
+ rq_add1.onsuccess = log("rq_add1.success");
+ rq_add1.onerror = log("rq_add1.error");
+
+ objStore.createIndex("index", "animal", { unique: true });
+
+ var rq_add2 = objStore.add({ animal: "Unicorn" }, 2);
+ rq_add2.onsuccess = log("rq_add2.success");
+ rq_add2.onerror = function(e) {
+ log("rq_add2.error")(e);
+ e.preventDefault();
+ e.stopPropagation();
+ }
+
+ objStore.deleteIndex("index");
+
+ var rq_add3 = objStore.add({ animal: "Unicorn" }, 3);
+ rq_add3.onsuccess = log("rq_add3.success");
+ rq_add3.onerror = log("rq_add3.error");
+ }
+
+ open_rq.onsuccess = function(e) {
+ log("open_rq.success")(e);
+ assert_object_equals(events, [ "rq_add1.success",
+ "rq_add2.error: ConstraintError",
+ "rq_add3.success",
+
+ "transaction.complete",
+
+ "open_rq.success" ],
+ "events");
+ t.done();
+ }
+
+ function log(msg) {
+ return function(e) {
+ if(e && e.target && e.target.error)
+ events.push(msg + ": " + e.target.error.name);
+ else
+ events.push(msg);
+ };
+ }
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_createIndex5-emptykeypath.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_createIndex5-emptykeypath.htm
new file mode 100644
index 00000000000..29fadc00e3f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_createIndex5-emptykeypath.htm
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.createIndex() - empty keyPath</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db, aborted,
+ t = async_test(document.title, {timeout: 10000})
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var txn = e.target.transaction,
+ objStore = db.createObjectStore("store");
+
+ for (var i = 0; i < 5; i++)
+ objStore.add("object_" + i, i);
+
+ var rq = objStore.createIndex("index", "")
+ rq.onerror = function() { assert_unreached("error: " + rq.error.name); }
+ rq.onsuccess = function() { }
+
+ objStore.index("index")
+ .get('object_4')
+ .onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result, 'object_4', 'result');
+ });
+ }
+
+ open_rq.onsuccess = function() {
+ t.done();
+ }
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_createIndex6-event_order.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_createIndex6-event_order.htm
new file mode 100644
index 00000000000..20b4890382d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_createIndex6-event_order.htm
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>IDBObjectStore.createIndex() - event order when unique constraint is triggered</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<meta rel=help href=http://odinho.html5.org/IndexedDB/spec/Overview.html#widl-IDBObjectStore-createIndex-IDBIndex-DOMString-name-any-keyPath-IDBIndexParameters-optionalParameters>
+<meta rel=assert title="The index that is requested to be created can contain constraints on the data allowed in the index's referenced object store, such as requiring uniqueness of the values referenced by the index's keyPath. If the referenced object store already contains data which violates these constraints, this must not cause the implementation of createIndex to throw an exception or affect what it returns. The implementation must still create and return an IDBIndex object. Instead the implementation must queue up an operation to abort the 'versionchange' transaction which was used for the createIndex call.">
+<meta rel=assert title="In some implementations it's possible for the implementation to asynchronously run into problems creating the index after the createIndex function has returned. For example in implementations where metadata about the newly created index is queued up to be inserted into the database asynchronously, or where the implementation might need to ask the user for permission for quota reasons. Such implementations must still create and return an IDBIndex object. Instead, once the implementation realizes that creating the index has failed, it must abort the transaction using the steps for aborting a transaction using the appropriate error as error parameter.">
+<meta rel=assert title="if the index can't be created due to unique constraints, ConstraintError must be used as error">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var db,
+ events = [],
+ t = async_test(document.title, {timeout: 10000})
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ db.onerror = log("db.error");
+ db.onabort = log("db.abort");
+ e.target.transaction.onabort = log("transaction.abort")
+ e.target.transaction.onerror = log("transaction.error")
+ e.target.transaction.oncomplete = log("transaction.complete")
+
+ var txn = e.target.transaction,
+ objStore = db.createObjectStore("store");
+
+ var rq_add1 = objStore.add({ animal: "Unicorn" }, 1);
+ rq_add1.onsuccess = log("rq_add1.success");
+ rq_add1.onerror = log("rq_add1.error");
+
+ var rq_add2 = objStore.add({ animal: "Unicorn" }, 2);
+ rq_add2.onsuccess = log("rq_add2.success");
+ rq_add2.onerror = log("rq_add2.error");
+
+ objStore.createIndex("index", "animal", { unique: true })
+
+ var rq_add3 = objStore.add({ animal: "Unicorn" }, 3);
+ rq_add3.onsuccess = log("rq_add3.success");
+ rq_add3.onerror = log("rq_add3.error");
+ }
+
+ open_rq.onerror = function(e) {
+ log("open_rq.error")(e);
+ assert_object_equals(events, [ "rq_add1.success",
+ "rq_add2.success",
+
+ "rq_add3.error: AbortError",
+ "transaction.error: AbortError",
+ "db.error: AbortError",
+
+ "transaction.abort: ConstraintError",
+ "db.abort: ConstraintError",
+
+ "open_rq.error: AbortError" ],
+ "events");
+ t.done();
+ }
+
+ function log(msg) {
+ return function(e) {
+ if(e && e.target && e.target.error)
+ events.push(msg + ": " + e.target.error.name);
+ else
+ events.push(msg);
+ };
+ }
+</script>
+
+<div id=log></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_createIndex7-event_order.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_createIndex7-event_order.htm
new file mode 100644
index 00000000000..23e3dbb8752
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_createIndex7-event_order.htm
@@ -0,0 +1,77 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.createIndex() - Event ordering for ConstraintError on request</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<meta rel=help href=http://odinho.html5.org/IndexedDB/spec/Overview.html#dfn-steps-for-aborting-a-transaction>
+<meta rel=assert title="Unless error was set to null, create a DOMError object and set its name to error. Set transaction's error property to this newly created DOMError.">
+<meta rel=assert title="If the transaction's request list contain any requests whose done flag is still false, abort the steps for asynchronously executing a request for each such request and queue a task to perform the following steps:">
+<meta rel=assert title="set the request's error attribute to a DOMError with a type of AbortError.">
+<meta rel=assert title="Dispatch an event at request. The event must use the Event interface and have its type set to 'error'. The event bubbles and is cancelable. The propagation path for the event is transaction's connection, then transaction and finally the request. There is no default action for the event.">
+<meta rel=assert title="Queue up an operation to dispatch an event at transaction. The event must use the Event interface and have its type set to 'abort'. The event does bubble but is not cancelable. The propagation path for the event is transaction's connection and then transaction.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ events = [],
+ t = async_test(document.title, {timeout: 10000})
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var txn = e.target.transaction;
+ db.onerror = log("db.error");
+ db.onabort = log("db.abort");
+ txn.onabort = log("transaction.abort")
+ txn.onerror = log("transaction.error")
+ txn.oncomplete = log("transaction.complete")
+
+ var objStore = db.createObjectStore("store");
+
+ var rq_add1 = objStore.add({ animal: "Unicorn" }, 1);
+ rq_add1.onsuccess = log("rq_add1.success");
+ rq_add1.onerror = log("rq_add1.error");
+
+ objStore.createIndex("index", "animal", { unique: true })
+
+ var rq_add2 = objStore.add({ animal: "Unicorn" }, 2);
+ rq_add2.onsuccess = log("rq_add2.success");
+ rq_add2.onerror = log("rq_add2.error");
+
+ var rq_add3 = objStore.add({ animal: "Horse" }, 3);
+ rq_add3.onsuccess = log("rq_add3.success");
+ rq_add3.onerror = log("rq_add3.error");
+ }
+
+ open_rq.onerror = function(e) {
+ log("open_rq.error")(e);
+ assert_object_equals(events, [ "rq_add1.success",
+
+ "rq_add2.error: ConstraintError",
+ "transaction.error: ConstraintError",
+ "db.error: ConstraintError",
+
+ "rq_add3.error: AbortError",
+ "transaction.error: AbortError",
+ "db.error: AbortError",
+
+ "transaction.abort: ConstraintError",
+ "db.abort: ConstraintError",
+
+ "open_rq.error: AbortError" ],
+ "events");
+ t.done();
+ }
+
+ function log(msg) {
+ return function(e) {
+ if(e && e.target && e.target.error)
+ events.push(msg + ": " + e.target.error.name);
+ else
+ events.push(msg);
+ };
+ }
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_createIndex8-valid_keys.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_createIndex8-valid_keys.htm
new file mode 100644
index 00000000000..8dbe03f59ef
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_createIndex8-valid_keys.htm
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.createIndex() - index can be valid keys</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<meta name=timeout content=long>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(document.title, {timeout:19000}),
+ now = new Date(),
+ mar18 = new Date(1111111111111),
+ ar = ["Yay", 2, -Infinity],
+ num = 1337
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var txn = e.target.transaction,
+ objStore = db.createObjectStore("store", { keyPath: 'key' });
+
+ objStore.add({ key: "now", i: now });
+ objStore.add({ key: "mar18", i: mar18 });
+ objStore.add({ key: "array", i: ar });
+ objStore.add({ key: "number", i: num });
+
+ var idx = objStore.createIndex("index", "i")
+
+ idx.get(now).onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result.key, 'now', 'key');
+ assert_equals(e.target.result.i.getTime(), now.getTime(), 'getTime');
+ });
+ idx.get(mar18).onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result.key, 'mar18', 'key');
+ assert_equals(e.target.result.i.getTime(), mar18.getTime(), 'getTime');
+ });
+ idx.get(ar).onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result.key, 'array', 'key');
+ assert_object_equals(e.target.result.i, ar, 'array is the same');
+ });
+ idx.get(num).onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result.key, 'number', 'key');
+ assert_equals(e.target.result.i, num, 'number is the same');
+ });
+ }
+
+ open_rq.onsuccess = function() {
+ t.done();
+ }
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_createIndex9-emptyname.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_createIndex9-emptyname.htm
new file mode 100644
index 00000000000..3d04357c972
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_createIndex9-emptyname.htm
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>IDBObjectStore.createIndex() - empty name</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var db
+
+ var open_rq = createdb(async_test())
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result
+ var store = db.createObjectStore("store")
+
+ for (var i = 0; i < 5; i++)
+ store.add({ idx: "object_" + i }, i)
+
+ store.createIndex("", "idx")
+
+ store.index("")
+ .get('object_4')
+ .onsuccess = this.step_func(function(e) {
+ assert_equals(e.target.result.idx, 'object_4', 'result')
+ })
+ assert_equals(store.indexNames[0], "", "indexNames[0]")
+ assert_equals(store.indexNames.length, 1, "indexNames.length")
+ }
+
+ open_rq.onsuccess = function() {
+ var store = db.transaction("store").objectStore("store")
+
+ assert_equals(store.indexNames[0], "", "indexNames[0]")
+ assert_equals(store.indexNames.length, 1, "indexNames.length")
+
+ this.done()
+ }
+</script>
+
+<div id=log></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_delete.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_delete.htm
new file mode 100644
index 00000000000..33728929623
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_delete.htm
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.delete() - delete removes record (inline keys)</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { key: 1, property: "data" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var objStore = db.createObjectStore("test", { keyPath: "key" });
+ objStore.add(record);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var delete_rq = db.transaction("test", "readwrite")
+ .objectStore("test")
+ .delete(record.key);
+
+ delete_rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result, undefined);
+
+ e.target.transaction.oncomplete = t.step_func(VerifyRecordRemoved);
+ });
+ };
+
+ function VerifyRecordRemoved() {
+ var rq = db.transaction("test")
+ .objectStore("test")
+ .get(record.key);
+
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result, undefined);
+ t.done();
+ });
+ }
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_delete2.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_delete2.htm
new file mode 100644
index 00000000000..f7e46846025
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_delete2.htm
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.delete() - key doesn't match any records </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var delete_rq = db.createObjectStore("test")
+ .delete(1);
+
+ delete_rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result, undefined);
+ t.done();
+ });
+ };
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_delete3.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_delete3.htm
new file mode 100644
index 00000000000..b72b1072d78
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_delete3.htm
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.delete() - object store's key path is an object attribute </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { test: { obj: { key: 1 } }, property: "data" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var objStore = db.createObjectStore("test", { keyPath: "test.obj.key" });
+ objStore.add(record);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var delete_rq = db.transaction("test", "readwrite")
+ .objectStore("test")
+ .delete(record.test.obj.key);
+
+ delete_rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result, undefined);
+
+ e.target.transaction.oncomplete = t.step_func(VerifyRecordRemoved);
+ });
+ };
+
+ function VerifyRecordRemoved() {
+ var rq = db.transaction("test")
+ .objectStore("test")
+ .get(record.test.obj.key);
+
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result, undefined);
+ t.done();
+ });
+ }
+
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_delete4.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_delete4.htm
new file mode 100644
index 00000000000..3d36b7962ee
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_delete4.htm
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.delete() - delete removes record (out-of-line keys) </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ key = 1,
+ record = { property: "data" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var objStore = db.createObjectStore("test");
+ objStore.add(record, key);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var delete_rq = db.transaction("test", "readwrite")
+ .objectStore("test")
+ .delete(key);
+
+ delete_rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result, undefined);
+
+ e.target.transaction.oncomplete = t.step_func(VerifyRecordRemoved);
+ });
+ };
+
+ function VerifyRecordRemoved() {
+ var rq = db.transaction("test")
+ .objectStore("test")
+ .get(key);
+
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result, undefined);
+ t.done();
+ });
+ }
+
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_delete5.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_delete5.htm
new file mode 100644
index 00000000000..9e8ac80a123
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_delete5.htm
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<title>IDBObjectStore.delete() - removes all of the records in the range</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+<script>
+ var db
+ var open_rq = createdb(async_test())
+
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result
+ var os = db.createObjectStore("store")
+
+ for(var i = 0; i < 10; i++)
+ os.add("data" + i, i)
+ }
+
+ open_rq.onsuccess = function (e) {
+ var os = db.transaction("store", "readwrite")
+ .objectStore("store")
+
+ os.delete( IDBKeyRange.bound(3, 6) )
+ os.count().onsuccess = this.step_func(function(e)
+ {
+ assert_equals(e.target.result, 6, "Count after deleting 3-6 from 10");
+ this.done();
+ })
+ }
+</script>
+
+<div id=log></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_delete6.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_delete6.htm
new file mode 100644
index 00000000000..01d54dee93b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_delete6.htm
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.delete() - If the transaction this IDBObjectStore belongs to has its mode set to readonly, throw ReadOnlyError</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBObjectStore-delete-IDBRequest-any-key">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test(),
+ records = [{ pKey: "primaryKey_0"},
+ { pKey: "primaryKey_1"}];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function (event) {
+ db = event.target.result;
+ var objStore = db.createObjectStore("store", {keyPath:"pKey"});
+ for (var i = 0; i < records.length; i++) {
+ objStore.add(records[i]);
+ }
+ }
+
+ open_rq.onsuccess = function (event) {
+ var txn = db.transaction("store");
+ var ostore = txn.objectStore("store");
+ t.step(function(){
+ assert_throws("ReadOnlyError", function(){
+ ostore.delete("primaryKey_0");
+ });
+ });
+ t.done();
+ }
+</script>
+
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_delete7.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_delete7.htm
new file mode 100644
index 00000000000..d070a6d4b16
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_delete7.htm
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.delete() - If the object store has been deleted, the implementation must throw a DOMException of type InvalidStateError</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBObjectStore-delete-IDBRequest-any-key">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ ostore,
+ t = async_test(),
+ records = [{ pKey: "primaryKey_0"},
+ { pKey: "primaryKey_1"}];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function (event) {
+ db = event.target.result;
+ ostore = db.createObjectStore("store", {keyPath:"pKey"});
+ db.deleteObjectStore("store");
+ }
+
+ open_rq.onsuccess = function (event) {
+ t.step(function(){
+ assert_throws("InvalidStateError", function(){
+ ostore.delete("primaryKey_0");
+ });
+ });
+ t.done();
+ }
+</script>
+
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_deleteIndex.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_deleteIndex.htm
new file mode 100644
index 00000000000..1e0fb2976c8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_deleteIndex.htm
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.deleteIndex() - removes the index </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ key = 1,
+ record = { property: "data" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ db.createObjectStore("test")
+ .createIndex("index", "indexedProperty")
+ };
+
+ open_rq.onsuccess = function(e) {
+ db.close();
+ var new_version = createdb(t, db.name, 2);
+ new_version.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = e.target.transaction.objectStore("test")
+ objStore.deleteIndex("index");
+ }
+ new_version.onsuccess = function(e) {
+ var index,
+ objStore = db.transaction("test")
+ .objectStore("test");
+
+ assert_throws('NotFoundError',
+ function() { index = objStore.index("index") });
+ assert_equals(index, undefined);
+ t.done();
+ }
+ }
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_deleted.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_deleted.htm
new file mode 100644
index 00000000000..1d9421ce03a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_deleted.htm
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Attempting to use deleted IDBObjectStore</title>
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#object-store">
+<link rel=assert title="InvalidStateError Occurs if a request is made on a source object that has been deleted or removed.">
+<link rel=author href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var db,
+ add_success = false,
+ t = async_test(document.title, {timeout: 10000})
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var objStore = db.createObjectStore("store", { autoIncrement: true });
+ assert_equals(db.objectStoreNames[0], "store", "objectStoreNames");
+
+ var rq_add = objStore.add(1);
+ rq_add.onsuccess = function() { add_success = true; };
+ rq_add.onerror = fail(t, 'rq_add.error');
+
+ objStore.createIndex("idx", "a");
+ db.deleteObjectStore("store");
+ assert_equals(db.objectStoreNames.length, 0, "objectStoreNames.length after delete");
+
+ assert_throws(null, function() { objStore.add(2); });
+ assert_throws(null, function() { objStore.put(3); });
+ assert_throws(null, function() { objStore.get(1); });
+ assert_throws(null, function() { objStore.clear(); });
+ assert_throws(null, function() { objStore.count(); });
+ assert_throws(null, function() { objStore.delete(1); });
+ assert_throws(null, function() { objStore.openCursor(); });
+ assert_throws(null, function() { objStore.index("idx"); });
+ assert_throws(null, function() { objStore.deleteIndex("idx"); });
+ assert_throws(null, function() { objStore.createIndex("idx2", "a"); });
+ }
+
+ open_rq.onsuccess = function() {
+ assert_true(add_success, "First add was successful");
+ t.done();
+ }
+</script>
+
+<div id=log></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_get.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_get.htm
new file mode 100644
index 00000000000..99aff78d564
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_get.htm
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.get() - key is a number </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { key: 3.14159265, property: "data" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ db.createObjectStore("store", { keyPath: "key" })
+ .add(record);
+ }
+
+ open_rq.onsuccess = function(e) {
+ var rq = db.transaction("store")
+ .objectStore("store")
+ .get(record.key);
+
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result.key, record.key);
+ assert_equals(e.target.result.property, record.property);
+ t.done();
+ });
+ }
+
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_get2.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_get2.htm
new file mode 100644
index 00000000000..dfbfea17c22
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_get2.htm
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.get() - key is a string </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { key: "this is a key that's a string", property: "data" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ db.createObjectStore("store", { keyPath: "key" })
+ .add(record);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var rq = db.transaction("store")
+ .objectStore("store")
+ .get(record.key);
+
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result.key, record.key);
+ assert_equals(e.target.result.property, record.property);
+ t.done();
+ });
+ };
+
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_get3.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_get3.htm
new file mode 100644
index 00000000000..b093e535796
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_get3.htm
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.get() - key is a Date </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { key: new Date(), property: "data" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ db.createObjectStore("store", { keyPath: "key" })
+ .add(record);
+ }
+
+ open_rq.onsuccess = function(e) {
+ var rq = db.transaction("store")
+ .objectStore("store")
+ .get(record.key);
+
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result.key.valueOf(), record.key.valueOf());
+ assert_equals(e.target.result.property, record.property);
+ t.done();
+ });
+ }
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_get4.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_get4.htm
new file mode 100644
index 00000000000..7853697a19f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_get4.htm
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.get() - attempt to retrieve a record that doesn't exist </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var rq = db.createObjectStore("store", { keyPath: "key" })
+ .get(1);
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.results, undefined);
+ setTimeout(function() { t.done(); }, 10);
+ });
+ };
+
+ open_rq.onsuccess = function() {};
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_get5.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_get5.htm
new file mode 100644
index 00000000000..59b0ede641f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_get5.htm
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<title>IDBObjectStore.get() - returns the record with the first key in the range </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+<script>
+ var db
+ var open_rq = createdb(async_test())
+
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result
+ var os = db.createObjectStore("store")
+
+ for(var i = 0; i < 10; i++)
+ os.add("data" + i, i)
+ }
+
+ open_rq.onsuccess = function (e) {
+ db.transaction("store")
+ .objectStore("store")
+ .get( IDBKeyRange.bound(3, 6) )
+ .onsuccess = this.step_func(function(e)
+ {
+ assert_equals(e.target.result, "data3", "get(3-6)");
+ this.done();
+ })
+ }
+</script>
+
+<div id=log></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_get6.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_get6.htm
new file mode 100644
index 00000000000..33381a684b6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_get6.htm
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.get() - throw TransactionInactiveError on aborted transaction </title>
+<link rel="author" title="YuichiNukiyama" href="https://github.com/YuichiNukiyama">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ db.createObjectStore("store", { keyPath: "key" })
+ }
+
+ open_rq.onsuccess = function (e) {
+ var store = db.transaction("store")
+ .objectStore("store");
+ store.transaction.abort();
+ assert_throws("TransactionInactiveError", function () {
+ store.get(1);
+ }, "throw TransactionInactiveError on aborted transaction.");
+ t.done();
+ }
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_get7.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_get7.htm
new file mode 100644
index 00000000000..570441b6634
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_get7.htm
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.get() - throw DataError when using invalid key </title>
+<link rel="author" title="YuichiNukiyama" href="https://github.com/YuichiNukiyama">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ db.createObjectStore("store", { keyPath: "key" })
+ }
+
+ open_rq.onsuccess = function(e) {
+ var store = db.transaction("store")
+ .objectStore("store")
+ assert_throws("DataError", function () {
+ store.get(null)
+ }, "throw DataError when using invalid key.");
+ t.done();
+ }
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_index.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_index.htm
new file mode 100644
index 00000000000..5da58ecc311
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_index.htm
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.index() - returns an index </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ db.createObjectStore("store")
+ .createIndex("index", "indexedProperty");
+ };
+
+ open_rq.onsuccess = function(e) {
+ var index = db.transaction("store")
+ .objectStore("store")
+ .index("index");
+
+ assert_true(index instanceof IDBIndex, 'instanceof IDBIndex');
+ t.done();
+ };
+
+</script>
+
+
+<div id="log"></div>
+
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_openCursor.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_openCursor.htm
new file mode 100644
index 00000000000..914aa57211f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_openCursor.htm
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<title>IDBObjectStore.openCursor() - iterate through 100 objects</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ var db
+ var open_rq = createdb(async_test())
+
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var store = db.createObjectStore("store");
+
+ for (var i=0; i < 100; i++)
+ store.add("record_" + i, i);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var count = 0
+ var txn = db.transaction("store")
+
+ txn.objectStore("store")
+ .openCursor().onsuccess = this.step_func(function(e)
+ {
+ if (e.target.result)
+ e.target.result.continue()
+ })
+
+ txn.oncomplete = this.step_func(function() {
+ this.done()
+ })
+ }
+
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_openCursor_invalid.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_openCursor_invalid.htm
new file mode 100644
index 00000000000..698e7998b23
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_openCursor_invalid.htm
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<title>IDBObjectStore.openCursor() - invalid</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ var db, open;
+
+ setup(function() {
+ open = indexedDB.open('testdb-' + new Date().getTime());
+ open.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test");
+ objStore.createIndex("index", "");
+
+ objStore.add("data", 1);
+ objStore.add("data2", 2);
+ };
+ },
+ { explicit_done: true });
+
+
+ open.onsuccess = function() {
+
+ async_test(document.title + " - pass something other than number").step(function(e) {
+ var idx = db.transaction("test").objectStore("test").index("index");
+
+ assert_throws("DataError",
+ function() { idx.openCursor({ lower: "a" }); });
+
+ assert_throws("DataError",
+ function() { idx.openCursor({ lower: "a", lowerOpen: false }); });
+
+ assert_throws("DataError",
+ function() { idx.openCursor({ lower: "a", lowerOpen: false, upper: null, upperOpen: false }); });
+
+ this.done();
+ });
+
+
+ // Stop blocking the testing system from hereon
+ done();
+ }
+
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put.htm
new file mode 100644
index 00000000000..6a0fed4b7fe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put.htm
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.put() - put with an inline key </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { key: 1, property: "data" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("store", { keyPath: "key" });
+
+ objStore.put(record);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var rq = db.transaction("store")
+ .objectStore("store")
+ .get(record.key);
+
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result.property, record.property);
+ assert_equals(e.target.result.key, record.key);
+ t.done();
+ });
+ };
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put10.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put10.htm
new file mode 100644
index 00000000000..d0de11c3e30
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put10.htm
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.put() - Attempt to call 'put' without an key parameter when the object store uses out-of-line keys </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { property: "data" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var rq,
+ objStore = db.createObjectStore("store", { keyPath: "key" });
+
+ assert_throws("DataError",
+ function() { rq = objStore.put(record); });
+
+ assert_equals(rq, undefined);
+ t.done();
+ };
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put11.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put11.htm
new file mode 100644
index 00000000000..9a13757ef20
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put11.htm
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.put() - Attempt to put a record where the record's key does not meet the constraints of a valid key </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { key: { value: 1 }, property: "data" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var rq,
+ objStore = db.createObjectStore("store", { keyPath: "key" });
+
+ assert_throws("DataError",
+ function() { rq = objStore.put(record); });
+
+ assert_equals(rq, undefined);
+ t.done();
+ };
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put12.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put12.htm
new file mode 100644
index 00000000000..24970dff080
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put12.htm
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.put() - Attempt to put a record where the record's in-line key is not defined </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { property: "data" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var rq,
+ objStore = db.createObjectStore("store", { keyPath: "key" });
+
+ assert_throws("DataError",
+ function() { rq = objStore.put(record); });
+
+ assert_equals(rq, undefined);
+ t.done();
+ };
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put13.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put13.htm
new file mode 100644
index 00000000000..870c8e4a718
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put13.htm
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.put() - Attempt to put a record where the out of line key provided does not meet the constraints of a valid key </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { property: "data" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var rq,
+ objStore = db.createObjectStore("store");
+
+ assert_throws("DataError",
+ function() { rq = objStore.put(record, { value: 1 }); });
+
+ assert_equals(rq, undefined);
+ t.done();
+ };
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put14.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put14.htm
new file mode 100644
index 00000000000..c6896964592
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put14.htm
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.put() - Put a record where a value being indexed does not meet the constraints of a valid key </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { key: 1, indexedProperty: { property: "data" } };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var rq,
+ objStore = db.createObjectStore("store", { keyPath: "key" });
+
+ objStore.createIndex("index", "indexedProperty");
+
+ rq = objStore.put(record);
+
+ assert_true(rq instanceof IDBRequest);
+ rq.onsuccess = function() {
+ t.done();
+ }
+ };
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put15.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put15.htm
new file mode 100644
index 00000000000..cf2c35435cf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put15.htm
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.put() - If the transaction this IDBObjectStore belongs to has its mode set to readonly, throw ReadOnlyError</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBObjectStore-put-IDBRequest-any-value-any-key">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function (event) {
+ db = event.target.result;
+ db.createObjectStore("store", {keyPath:"pKey"});
+ }
+
+ open_rq.onsuccess = function (event) {
+ var txn = db.transaction("store");
+ var ostore = txn.objectStore("store");
+ t.step(function(){
+ assert_throws("ReadOnlyError", function(){
+ ostore.put({pKey: "primaryKey_0"});
+ });
+ });
+ t.done();
+ }
+</script>
+
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put16.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put16.htm
new file mode 100644
index 00000000000..09d9e2acde2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put16.htm
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.put() - If the object store has been deleted, the implementation must throw a DOMException of type InvalidStateError</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBObjectStore-put-IDBRequest-any-value-any-key">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ ostore,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function (event) {
+ db = event.target.result;
+ ostore = db.createObjectStore("store", {keyPath:"pKey"});
+ db.deleteObjectStore("store");
+ }
+
+ open_rq.onsuccess = function (event) {
+ t.step(function(){
+ assert_throws("InvalidStateError", function(){
+ ostore.put({pKey: "primaryKey_0"});
+ });
+ });
+ t.done();
+ }
+</script>
+
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put2.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put2.htm
new file mode 100644
index 00000000000..3b9fc30a811
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put2.htm
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.put() - put with an out-of-line key </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ key = 1,
+ record = { property: "data" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("store");
+
+ objStore.put(record, key);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var rq = db.transaction("store")
+ .objectStore("store")
+ .get(key);
+
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result.property, record.property);
+
+ t.done();
+ });
+ };
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put3.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put3.htm
new file mode 100644
index 00000000000..79097a283e5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put3.htm
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.put() - record with same key already exists </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db, success_event,
+ t = async_test(),
+ record = { key: 1, property: "data" },
+ record_put = { key: 1, property: "changed", more: ["stuff", 2] };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("store", { keyPath: "key" });
+ objStore.put(record);
+
+ var rq = objStore.put(record_put);
+ rq.onerror = fail(t, "error on put");
+
+ rq.onsuccess = t.step_func(function(e) {
+ success_event = true;
+ });
+ };
+
+ open_rq.onsuccess = function(e) {
+ assert_true(success_event);
+
+ var rq = db.transaction("store")
+ .objectStore("store")
+ .get(1);
+
+ rq.onsuccess = t.step_func(function(e) {
+ var rec = e.target.result;
+
+ assert_equals(rec.key, record_put.key);
+ assert_equals(rec.property, record_put.property);
+ assert_array_equals(rec.more, record_put.more);
+
+ t.done();
+ });
+ };
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put4.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put4.htm
new file mode 100644
index 00000000000..c1335b27d00
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put4.htm
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.put() - put where an index has unique:true specified </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ record = { key: 1, property: "data" };
+
+ var open_rq = createdb(async_test());
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("store", { autoIncrement: true });
+ objStore.createIndex("i1", "property", { unique: true });
+ objStore.put(record);
+
+ var rq = objStore.put(record);
+ rq.onsuccess = fail(this, "success on putting duplicate indexed record")
+
+ rq.onerror = this.step_func(function(e) {
+ assert_equals(rq.error.name, "ConstraintError");
+ assert_equals(e.target.error.name, "ConstraintError");
+
+ assert_equals(e.type, "error");
+
+ e.preventDefault();
+ e.stopPropagation();
+ });
+ };
+
+ // Defer done, giving a spurious rq.onsuccess a chance to run
+ open_rq.onsuccess = function(e) {
+ this.done();
+ }
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put5.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put5.htm
new file mode 100644
index 00000000000..a4d9abefff6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put5.htm
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.put() - object store's key path is an object attribute </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { test: { obj: { key: 1 } }, property: "data" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("store", { keyPath: "test.obj.key" });
+ objStore.put(record);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var rq = db.transaction("store")
+ .objectStore("store")
+ .get(record.test.obj.key);
+
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result.property, record.property);
+
+ t.done();
+ });
+ };
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put6.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put6.htm
new file mode 100644
index 00000000000..bcf7e7d1934
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put6.htm
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.put() - autoIncrement and inline keys </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { property: "data" },
+ expected_keys = [ 1, 2, 3, 4 ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("store", { keyPath: "key", autoIncrement: true });
+
+ objStore.put(record);
+ objStore.put(record);
+ objStore.put(record);
+ objStore.put(record);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var actual_keys = [],
+ rq = db.transaction("store")
+ .objectStore("store")
+ .openCursor();
+
+ rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ if (cursor) {
+ actual_keys.push(cursor.value.key);
+ cursor.continue();
+ }
+ else {
+ assert_array_equals(actual_keys, expected_keys);
+ t.done();
+ }
+ });
+ };
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put7.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put7.htm
new file mode 100644
index 00000000000..6765b0a84ae
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put7.htm
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.put() - autoIncrement and out-of-line keys </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { property: "data" },
+ expected_keys = [ 1, 2, 3, 4 ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("store", { autoIncrement: true });
+
+ objStore.put(record);
+ objStore.put(record);
+ objStore.put(record);
+ objStore.put(record);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var actual_keys = [],
+ rq = db.transaction("store")
+ .objectStore("store")
+ .openCursor();
+
+ rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ if (cursor) {
+ actual_keys.push(cursor.key);
+ cursor.continue();
+ }
+ else {
+ assert_array_equals(actual_keys, expected_keys);
+ t.done();
+ }
+ });
+ };
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put8.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put8.htm
new file mode 100644
index 00000000000..3bf284eacab
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put8.htm
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.put() - object store has autoIncrement:true and the key path is an object attribute </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { property: "data" },
+ expected_keys = [ 1, 2, 3, 4 ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("store", { keyPath: "test.obj.key", autoIncrement: true });
+
+ objStore.put(record);
+ objStore.put(record);
+ objStore.put(record);
+ objStore.put(record);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var actual_keys = [],
+ rq = db.transaction("store")
+ .objectStore("store")
+ .openCursor();
+
+ rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ if (cursor) {
+ actual_keys.push(cursor.value.test.obj.key);
+ cursor.continue();
+ }
+ else {
+ assert_array_equals(actual_keys, expected_keys);
+ t.done();
+ }
+ });
+ };
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put9.htm b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put9.htm
new file mode 100644
index 00000000000..6e50a0b296d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbobjectstore_put9.htm
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.put() - Attempt to put a record that does not meet the constraints of an object store's inline key requirements </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var t = async_test(),
+ record = { key: 1, property: "data" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ var rq,
+ db = e.target.result,
+ objStore = db.createObjectStore("store", { keyPath: "key" });
+
+ assert_throws("DataError",
+ function() { rq = objStore.put(record, 1); });
+
+ assert_equals(rq, undefined);
+ t.done();
+ };
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbtransaction-oncomplete.htm b/tests/wpt/web-platform-tests/IndexedDB/idbtransaction-oncomplete.htm
new file mode 100644
index 00000000000..7c295c7c150
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbtransaction-oncomplete.htm
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<title>IDBTransaction - complete event</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db, store,
+ t = async_test(document.title, {timeout: 10000}),
+ open_rq = createdb(t),
+ stages = [];
+
+ open_rq.onupgradeneeded = function(e) {
+ stages.push("upgradeneeded");
+
+ db = e.target.result;
+ store = db.createObjectStore('store');
+
+ e.target.transaction.oncomplete = function() {
+ stages.push("complete");
+ };
+ };
+
+ open_rq.onsuccess = function(e) {
+ stages.push("success");
+
+ // Making a totally new transaction to check
+ db.transaction('store').objectStore('store').count().onsuccess = t.step_func(function(e) {
+ assert_array_equals(stages, [ "upgradeneeded",
+ "complete",
+ "success" ]);
+ t.done();
+ });
+ // XXX: Make one with real transactions, not only open() versionchange one
+
+ /*db.transaction.objectStore('store').openCursor().onsuccess = function(e) {
+ stages.push("opencursor1");
+ }
+
+ store.openCursor().onsuccess = function(e) {
+ stages.push("opencursor2");
+ }
+
+ e.target.transaction.objectStore('store').openCursor().onsuccess = function(e) {
+ stages.push("opencursor3");
+ }
+ */
+ }
+
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbtransaction.htm b/tests/wpt/web-platform-tests/IndexedDB/idbtransaction.htm
new file mode 100644
index 00000000000..8a3484511e5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbtransaction.htm
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<title>IDBTransaction</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(document.title + " - request gotten by the handler"),
+ open_t = async_test(document.title + " - request returned by open()"),
+
+ open_rq = indexedDB.open("idbtransaction-" + new Date().getTime() + Math.random());
+
+ open_t.step(function() {
+ assert_equals(open_rq.transaction, null, "IDBOpenDBRequest.transaction");
+ assert_equals(open_rq.source, null, "IDBOpenDBRequest.source");
+ assert_equals(open_rq.readyState, "pending", "IDBOpenDBRequest.readyState");
+
+ assert_true(open_rq instanceof IDBOpenDBRequest, "open_rq instanceof IDBOpenDBRequest");
+ assert_equals(open_rq + "", "[object IDBOpenDBRequest]", "IDBOpenDBRequest (open_rq)");
+
+ open_t.done();
+ });
+
+ open_rq.onupgradeneeded = t.step_func(function(e) {
+ assert_equals(e.target, open_rq, "e.target is reusing the same IDBOpenDBRequest");
+ assert_equals(e.target.transaction, open_rq.transaction, "IDBOpenDBRequest.transaction");
+
+ assert_true(e.target.transaction instanceof IDBTransaction, "transaction instanceof IDBTransaction");
+ t.done();
+ });
+
+
+ // Not plausible conditions...
+ function fail_helper(name) {
+ return function() {
+ t.step(function() { assert_unreached(name); });
+ open_t.step(function() { assert_unreached(name); });
+ };
+ }
+ open_rq.onblocked = fail_helper('open_rq.onblocked');
+ open_rq.onerror = fail_helper('open_rq.onerror');
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbtransaction_abort.htm b/tests/wpt/web-platform-tests/IndexedDB/idbtransaction_abort.htm
new file mode 100644
index 00000000000..c93a2da290f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbtransaction_abort.htm
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>IDBTransaction - abort</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ // TODO XXX DO THE IDBTransaction abort test here here
+ var db, aborted,
+ t = async_test(document.title, {timeout: 10000}),
+ record = { indexedProperty: "bar" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var txn = e.target.transaction,
+ objStore = db.createObjectStore("store");
+
+ objStore.add(record, 1);
+ objStore.add(record, 2);
+ var index = objStore.createIndex("index", "indexedProperty", { unique: true });
+
+ assert_true(index instanceof IDBIndex, "IDBIndex");
+
+ e.target.transaction.onabort = t.step_func(function(e) {
+ aborted = true;
+ assert_equals(e.type, "abort", "event type");
+ });
+
+ db.onabort = function(e) {
+ assert_true(aborted, "transaction.abort event has fired");
+ t.done();
+ };
+
+ e.target.transaction.oncomplete = fail(t, "got complete, expected abort");
+ };
+
+</script>
+
+<div id=log></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbversionchangeevent.htm b/tests/wpt/web-platform-tests/IndexedDB/idbversionchangeevent.htm
new file mode 100644
index 00000000000..5e688353364
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbversionchangeevent.htm
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<title>IDBVersionChangeEvent fired in upgradeneeded, versionchange and deleteDatabase</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#versionchange--transaction-steps">
+<link rel=assert title="Fire a versionchange event at each object in openDatabases that is open. The event must not be fired on objects which has the closePending flag set. The event must use the IDBVersionChangeEvent interface and have the oldVersion property set to db's version and have the newVersion property set to version.">
+<link rel=assert title="Fire a upgradeneeded event targeted at request. The event must use the IDBVersionChangeEvent interface and have the oldVersion property set to old version and have the newVersion property set to version.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<div id="log"></div>
+
+<script>
+
+ var db,
+ t = async_test(document.title, {timeout: 10000});
+
+ t.step(function() {
+ var openrq = indexedDB.open('db', 3);
+
+ openrq.onupgradeneeded = t.step_func(function(e) {
+ assert_equals(e.oldVersion, 0, "old version (upgradeneeded)");
+ assert_equals(e.newVersion, 3, "new version (upgradeneeded)");
+ assert_true(e instanceof IDBVersionChangeEvent, "upgradeneeded instanceof IDBVersionChangeEvent");
+ });
+
+ openrq.onsuccess = t.step_func(function(e) {
+ db = e.target.result;
+
+ db.onversionchange = t.step_func(function(e) {
+ assert_equals(e.oldVersion, 3, "old version (versionchange)");
+ assert_equals(e.newVersion, null, "new version (versionchange)");
+ assert_true(e instanceof IDBVersionChangeEvent, "versionchange instanceof IDBVersionChangeEvent");
+ db.close();
+ });
+
+ // Errors
+ db.onerror = fail(t, "db.error");
+ db.abort = fail(t, "db.abort");
+
+ setTimeout(t.step_func(deleteDB), 10);
+ });
+
+ // Errors
+ openrq.onerror = fail(t, "open.error");
+ openrq.onblocked = fail(t, "open.blocked");
+
+ });
+
+ function deleteDB (e) {
+ var deleterq = indexedDB.deleteDatabase('db');
+
+ deleterq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.oldVersion, 3, "old version (delete.success)");
+ assert_equals(e.newVersion, null, "new version (delete.success)");
+ assert_true(e instanceof IDBVersionChangeEvent, "delete.success instanceof IDBVersionChangeEvent");
+
+ setTimeout(function() { t.done(); }, 10);
+ });
+
+ // Errors
+ deleterq.onerror = fail(t, "delete.error");
+ deleterq.onblocked = fail(t, "delete.blocked");
+ }
+
+</script>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/idbworker.js b/tests/wpt/web-platform-tests/IndexedDB/idbworker.js
new file mode 100644
index 00000000000..359f6fb6911
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/idbworker.js
@@ -0,0 +1,34 @@
+var db
+
+self.addEventListener('message', MessageHandler, false)
+
+function MessageHandler(e)
+{
+ var open_rq, idb = self.indexedDB || self.msIndexedDB || self.webkitIndexedDB || self.mozIndexedDB
+
+ if (!idb)
+ {
+ self.postMessage(false)
+ return
+ }
+ else
+ self.postMessage(true)
+
+ open_rq = idb.open("webworker101", 1)
+
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result
+ db.createObjectStore("store")
+ .add("test", 1)
+ }
+ open_rq.onsuccess = function(e) {
+ db = e.target.result
+ db.onerror = function() { self.postMessage("db.error") }
+ db.transaction("store").objectStore("store").get(1).onsuccess = function(e) {
+ self.postMessage(e.target.result)
+ db.close()
+ }
+ }
+ open_rq.onerror = function() { self.postMessage("open.error") }
+ open_rq.onblocked = function() { self.postMessage("open.blocked") }
+}
diff --git a/tests/wpt/web-platform-tests/IndexedDB/index_sort_order.htm b/tests/wpt/web-platform-tests/IndexedDB/index_sort_order.htm
new file mode 100644
index 00000000000..6249c420489
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/index_sort_order.htm
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Verify key sort order in an index is 'number &lt; Date &lt; DOMString' </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ d = new Date(),
+ t = async_test(),
+ records = [ { foo: d },
+ { foo: "test" },
+ { foo: 1 },
+ { foo: 2.55 } ],
+ expectedKeyOrder = [ 1, 2.55, d.valueOf(), "test" ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("store", { autoIncrement: true });
+ objStore.createIndex("index", "foo");
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var actual_keys = [],
+ rq = db.transaction("store")
+ .objectStore("store")
+ .index("index")
+ .openCursor();
+
+ rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ if (cursor) {
+ actual_keys.push(cursor.key.valueOf());
+ cursor.continue();
+ }
+ else {
+ assert_array_equals(actual_keys, expectedKeyOrder);
+ t.done();
+ }
+ });
+ };
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/interfaces.htm b/tests/wpt/web-platform-tests/IndexedDB/interfaces.htm
new file mode 100644
index 00000000000..644f4d178f4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/interfaces.htm
@@ -0,0 +1,64 @@
+<!--
+Test converted from WebKit:
+http://trac.webkit.org/browser/trunk/LayoutTests/storage/indexeddb/resources/interfaces.js
+-->
+
+<!DOCTYPE html>
+<!-- Submitted from TestTWF Paris -->
+<meta charset=utf-8>
+<title>Test IndexedDB's interfaces</title>
+<link rel=author href="mailto:romain.huet@gmail.com" title="Romain Huet">
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+
+ test(function() {
+ assert_true('IDBCursor' in self);
+ }, "Test IDBCursor");
+
+ test(function() {
+ assert_true('IDBCursorWithValue' in self);
+ }, "Test IDBCursorWithValue");
+
+ test(function() {
+ assert_true('IDBDatabase' in self);
+ }, "Test IDBDatabase");
+
+ test(function() {
+ assert_true('IDBFactory' in self);
+ }, "Test IDBFactory");
+
+ test(function() {
+ assert_true('IDBIndex' in self);
+ }, "Test IDBIndex");
+
+ test(function() {
+ assert_true('IDBKeyRange' in self);
+ }, "Test IDBKeyRange");
+
+ test(function() {
+ assert_true('IDBObjectStore' in self);
+ }, "Test IDBObjectStore");
+
+ test(function() {
+ assert_true('IDBOpenDBRequest' in self);
+ }, "Test IDBOpenDBRequest");
+
+ test(function() {
+ assert_true('IDBRequest' in self);
+ }, "Test IDBRequest");
+
+ test(function() {
+ assert_true('IDBTransaction' in self);
+ }, "Test IDBTransaction");
+
+ test(function() {
+ assert_true('IDBVersionChangeEvent' in self);
+ }, "Test IDBVersionChangeEvent");
+
+</script>
+
+<div id=log></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/interfaces.html b/tests/wpt/web-platform-tests/IndexedDB/interfaces.html
new file mode 100644
index 00000000000..cc4e7f20392
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/interfaces.html
@@ -0,0 +1,50 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>IndexedDB IDL tests</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=/resources/WebIDLParser.js></script>
+<script src=/resources/idlharness.js></script>
+
+<h1>IndexedDB IDL tests</h1>
+<div id=log></div>
+
+<script>
+"use strict";
+setup(function() {
+ var idlArray = new IdlArray();
+
+ var request = new XMLHttpRequest();
+ request.open("GET", "interfaces.idl");
+ request.send();
+ request.onload = function() {
+ var idls = request.responseText;
+
+ idlArray.add_untested_idls("[PrimaryGlobal] interface Window { };");
+ idlArray.add_untested_idls("interface Event { };");
+ idlArray.add_untested_idls("interface EventTarget { };");
+
+ // From Indexed DB:
+ idlArray.add_idls(idls);
+ idlArray.add_idls("Window implements IDBEnvironment;");
+
+ idlArray.add_objects({
+ IDBCursor: [],
+ IDBCursorWithValue: [],
+ IDBDatabase: [],
+ IDBEnvironment: [],
+ IDBFactory: ["window.indexedDB"],
+ IDBIndex: [],
+ IDBKeyRange: ["IDBKeyRange.only(0)"],
+ IDBObjectStore: [],
+ IDBOpenDBRequest: [],
+ IDBRequest: [],
+ IDBTransaction: [],
+ IDBVersionChangeEvent: ["new IDBVersionChangeEvent('foo')"],
+ });
+
+ idlArray.test();
+ done();
+ };
+}, {explicit_done: true});
+</script>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/interfaces.idl b/tests/wpt/web-platform-tests/IndexedDB/interfaces.idl
new file mode 100644
index 00000000000..055e62f46b3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/interfaces.idl
@@ -0,0 +1,145 @@
+enum IDBTransactionMode {
+ "readonly",
+ "readwrite",
+ "versionchange"
+};
+
+enum IDBRequestReadyState {
+ "pending",
+ "done"
+};
+
+interface IDBKeyRange {
+ readonly attribute any lower;
+ readonly attribute any upper;
+ readonly attribute boolean lowerOpen;
+ readonly attribute boolean upperOpen;
+ static IDBKeyRange only (any value);
+ static IDBKeyRange lowerBound (any lower, optional boolean open = false);
+ static IDBKeyRange upperBound (any upper, optional boolean open = false);
+ static IDBKeyRange bound (any lower, any upper, optional boolean lowerOpen = false, optional boolean upperOpen = false);
+};
+
+enum IDBCursorDirection {
+ "next",
+ "nextunique",
+ "prev",
+ "prevunique"
+};
+
+dictionary IDBObjectStoreParameters {
+ (DOMString or sequence<DOMString>)? keyPath = null;
+ boolean autoIncrement = false;
+};
+
+dictionary IDBIndexParameters {
+ boolean unique = false;
+ boolean multiEntry = false;
+};
+
+dictionary IDBVersionChangeEventInit : EventInit {
+ unsigned long long oldVersion = 0;
+ unsigned long long? newVersion = null;
+};
+
+interface IDBRequest : EventTarget {
+ readonly attribute any result;
+ readonly attribute DOMError error;
+ readonly attribute (IDBObjectStore or IDBIndex or IDBCursor)? source;
+ readonly attribute IDBTransaction transaction;
+ readonly attribute IDBRequestReadyState readyState;
+ attribute EventHandler onsuccess;
+ attribute EventHandler onerror;
+};
+
+interface IDBOpenDBRequest : IDBRequest {
+ attribute EventHandler onblocked;
+ attribute EventHandler onupgradeneeded;
+};
+
+[Constructor(DOMString type, optional IDBVersionChangeEventInit eventInitDict)]
+interface IDBVersionChangeEvent : Event {
+ readonly attribute unsigned long long oldVersion;
+ readonly attribute unsigned long long? newVersion;
+};
+
+[NoInterfaceObject]
+interface IDBEnvironment {
+ readonly attribute IDBFactory indexedDB;
+};
+
+interface IDBFactory {
+ IDBOpenDBRequest open (DOMString name, [EnforceRange] optional unsigned long long version);
+ IDBOpenDBRequest deleteDatabase (DOMString name);
+ short cmp (any first, any second);
+};
+
+interface IDBDatabase : EventTarget {
+ readonly attribute DOMString name;
+ readonly attribute unsigned long long version;
+ readonly attribute DOMStringList objectStoreNames;
+ IDBObjectStore createObjectStore (DOMString name, optional IDBObjectStoreParameters optionalParameters);
+ void deleteObjectStore (DOMString name);
+ IDBTransaction transaction ((DOMString or sequence<DOMString>) storeNames, optional IDBTransactionMode mode = "readonly");
+ void close ();
+ attribute EventHandler onabort;
+ attribute EventHandler onerror;
+ attribute EventHandler onversionchange;
+};
+
+interface IDBObjectStore {
+ readonly attribute DOMString name;
+ readonly attribute any keyPath;
+ readonly attribute DOMStringList indexNames;
+ readonly attribute IDBTransaction transaction;
+ readonly attribute boolean autoIncrement;
+ IDBRequest put (any value, optional any key);
+ IDBRequest add (any value, optional any key);
+ IDBRequest delete (any key);
+ IDBRequest get (any key);
+ IDBRequest clear ();
+ IDBRequest openCursor (optional any range, optional IDBCursorDirection direction = "next");
+ IDBIndex createIndex (DOMString name, (DOMString or sequence<DOMString>) keyPath, optional IDBIndexParameters optionalParameters);
+ IDBIndex index (DOMString name);
+ void deleteIndex (DOMString indexName);
+ IDBRequest count (optional any key);
+};
+
+interface IDBIndex {
+ readonly attribute DOMString name;
+ readonly attribute IDBObjectStore objectStore;
+ readonly attribute any keyPath;
+ readonly attribute boolean multiEntry;
+ readonly attribute boolean unique;
+ IDBRequest openCursor (optional any range, optional IDBCursorDirection direction = "next");
+ IDBRequest openKeyCursor (optional any range, optional IDBCursorDirection direction = "next");
+ IDBRequest get (any key);
+ IDBRequest getKey (any key);
+ IDBRequest count (optional any key);
+};
+
+interface IDBCursor {
+ readonly attribute (IDBObjectStore or IDBIndex) source;
+ readonly attribute IDBCursorDirection direction;
+ readonly attribute any key;
+ readonly attribute any primaryKey;
+ IDBRequest update (any value);
+ void advance ([EnforceRange] unsigned long count);
+ void continue (optional any key);
+ IDBRequest delete ();
+};
+
+interface IDBCursorWithValue : IDBCursor {
+ readonly attribute any value;
+};
+
+interface IDBTransaction : EventTarget {
+ readonly attribute IDBTransactionMode mode;
+ readonly attribute IDBDatabase db;
+ readonly attribute DOMError error;
+ IDBObjectStore objectStore (DOMString name);
+ void abort ();
+ attribute EventHandler onabort;
+ attribute EventHandler oncomplete;
+ attribute EventHandler onerror;
+};
diff --git a/tests/wpt/web-platform-tests/IndexedDB/interfaces.worker.js b/tests/wpt/web-platform-tests/IndexedDB/interfaces.worker.js
new file mode 100644
index 00000000000..5da0590bb29
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/interfaces.worker.js
@@ -0,0 +1,39 @@
+"use strict";
+
+importScripts("/resources/testharness.js");
+importScripts("/resources/WebIDLParser.js", "/resources/idlharness.js");
+
+var request = new XMLHttpRequest();
+request.open("GET", "interfaces.idl");
+request.send();
+request.onload = function() {
+ var idlArray = new IdlArray();
+ var idls = request.responseText;
+
+ idlArray.add_untested_idls("interface WorkerGlobalScope {};");
+ idlArray.add_untested_idls("interface WorkerUtils {};");
+ idlArray.add_untested_idls("WorkerGlobalScope implements WorkerUtils;");
+ idlArray.add_untested_idls("interface Event { };");
+ idlArray.add_untested_idls("interface EventTarget { };");
+
+ // From Indexed DB:
+ idlArray.add_idls("WorkerUtils implements IDBEnvironment;");
+ idlArray.add_idls(idls);
+
+ idlArray.add_objects({
+ IDBCursor: [],
+ IDBCursorWithValue: [],
+ IDBDatabase: [],
+ IDBEnvironment: [],
+ IDBFactory: ["self.indexedDB"],
+ IDBIndex: [],
+ IDBKeyRange: ["IDBKeyRange.only(0)"],
+ IDBObjectStore: [],
+ IDBOpenDBRequest: [],
+ IDBRequest: [],
+ IDBTransaction: [],
+ IDBVersionChangeEvent: ["new IDBVersionChangeEvent('foo')"],
+ });
+ idlArray.test();
+ done();
+};
diff --git a/tests/wpt/web-platform-tests/IndexedDB/key_invalid.htm b/tests/wpt/web-platform-tests/IndexedDB/key_invalid.htm
new file mode 100644
index 00000000000..30759d5ef3e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/key_invalid.htm
@@ -0,0 +1,129 @@
+<!DOCTYPE html>
+<!-- Submitted from TestTWF Paris -->
+<meta charset=utf-8">
+<title>Invalid key</title>
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#key-construct">
+<link rel=assert title="A value is said to be a valid key if it is one of the following types: Array JavaScript objects [ECMA-262], DOMString [WEBIDL], Date [ECMA-262] or float [WEBIDL]. However Arrays are only valid keys if every item in the array is defined and is a valid key (i.e. sparse arrays can not be valid keys) and if the Array doesn't directly or indirectly contain itself. Any non-numeric properties are ignored, and thus does not affect whether the Array is a valid key. Additionally, if the value is of type float, it is only a valid key if it is not NaN, and if the value is of type Date it is only a valid key if its [[PrimitiveValue]] internal property, as defined by [ECMA-262], is not NaN. Conforming user agents must support all valid keys as keys.">
+<!-- original author -->
+<link rel=author href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<!-- some additions by Baptiste Fontaine (batifon@yahoo.fr) -->
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var db = createdb_for_multiple_tests(),
+ // cache for ObjectStores
+ objStore = null,
+ objStore2 = null;
+
+ function is_cloneable(o) {
+ try {
+ self.postMessage(o, '*');
+ return true;
+ } catch (ex) {
+ return false;
+ }
+ }
+
+ function invalid_key(desc, key) {
+ var t = async_test(document.title + " - " + desc);
+
+ // set the current test, and run it
+ db.setTest(t).onupgradeneeded = function(e) {
+ objStore = objStore || e.target.result.createObjectStore("store");
+ assert_throws('DataError', function() {
+ objStore.add("value", key);
+ });
+
+ if (is_cloneable(key)) {
+ objStore2 = objStore2 || e.target.result.createObjectStore("store2", { keyPath: ["x", "keypath"] });
+ assert_throws('DataError', function() {
+ objStore2.add({ x: "value", keypath: key });
+ });
+ }
+ this.done();
+ };
+ }
+
+ var fake_array = {
+ length : 0,
+ constructor : Array
+ };
+
+ var ArrayClone = function(){};
+ ArrayClone.prototype = Array;
+ var ArrayClone_instance = new ArrayClone();
+
+ // booleans
+ invalid_key( 'true' , true );
+ invalid_key( 'false' , false );
+
+ // null/NaN/undefined
+ invalid_key( 'null' , null );
+ invalid_key( 'NaN' , NaN );
+ invalid_key( 'undefined' , undefined );
+ invalid_key( 'undefined2');
+
+ // functions
+ invalid_key( 'function() {}', function(){} );
+
+ // objects
+ invalid_key( '{}' , {} );
+ invalid_key( '{ obj: 1 }' , { obj: 1 });
+ invalid_key( 'Math' , Math );
+ invalid_key( 'window' , window );
+ invalid_key( '{length:0,constructor:Array}' , fake_array );
+ invalid_key( 'Array clone’s instance' , ArrayClone_instance );
+ invalid_key( 'Array (object)' , Array );
+ invalid_key( 'String (object)' , String );
+ invalid_key( 'new String()' , new String() );
+ invalid_key( 'new Number()' , new Number() );
+ invalid_key( 'new Boolean()' , new Boolean() );
+
+ // arrays
+ invalid_key( '[{}]' , [{}] );
+ invalid_key( '[[], [], [], [[ Date ]]]' , [ [], [], [], [[ Date ]] ] );
+ invalid_key( '[undefined]' , [undefined] );
+ invalid_key( '[,1]' , [,1] );
+
+ invalid_key( 'document.getElements'
+ +'ByTagName("script")' , document.getElementsByTagName("script") );
+
+ // dates
+ invalid_key( 'new Date(NaN)' , new Date(NaN) );
+ invalid_key( 'new Date(Infinity)' , new Date(Infinity) );
+
+ // regexes
+ invalid_key( '/foo/' , /foo/ );
+ invalid_key( 'new RegExp()' , new RegExp() );
+
+ var sparse = [];
+ sparse[10] = "hei";
+ invalid_key('sparse array', sparse);
+
+ var sparse2 = [];
+ sparse2[0] = 1;
+ sparse2[""] = 2;
+ sparse2[2] = 3;
+ invalid_key('sparse array 2', sparse2);
+
+ invalid_key('[[1], [3], [7], [[ sparse array ]]]', [ [1], [3], [7], [[ sparse2 ]] ]);
+
+ // sparse3
+ invalid_key( '[1,2,3,,]', [1,2,3,,] );
+
+ var recursive = [];
+ recursive.push(recursive);
+ invalid_key('array directly contains self', recursive);
+
+ var recursive2 = [];
+ recursive2.push([recursive2]);
+ invalid_key('array indirectly contains self', recursive2);
+
+ var recursive3 = [recursive];
+ invalid_key('array member contains self', recursive3);
+
+</script>
+
+<div id=log></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/key_valid.html b/tests/wpt/web-platform-tests/IndexedDB/key_valid.html
new file mode 100644
index 00000000000..e695d14c4cd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/key_valid.html
@@ -0,0 +1,73 @@
+<!DOCTYPE html>
+<!-- Submitted from TestTWF Paris -->
+<meta charset=utf-8">
+<title>Valid key</title>
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#key-construct">
+<link rel=assert title="A value is said to be a valid key if it is one of the following types: Array JavaScript objects [ECMA-262], DOMString [WEBIDL], Date [ECMA-262] or float [WEBIDL]. However Arrays are only valid keys if every item in the array is defined and is a valid key (i.e. sparse arrays can not be valid keys) and if the Array doesn't directly or indirectly contain itself. Any non-numeric properties are ignored, and thus does not affect whether the Array is a valid key. Additionally, if the value is of type float, it is only a valid key if it is not NaN, and if the value is of type Date it is only a valid key if its [[PrimitiveValue]] internal property, as defined by [ECMA-262], is not NaN. Conforming user agents must support all valid keys as keys.">
+<link rel=author href="mailto:batifon@yahoo.fr" title="Baptiste Fontaine">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ function valid_key(desc, key) {
+ var db;
+ var t = async_test(document.title + " - " + desc);
+ var open_rq = createdb(t);
+
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ store = db.createObjectStore("store");
+ assert_true(store.add('value', key) instanceof IDBRequest);
+
+ store2 = db.createObjectStore("store2", { keyPath: ["x", "keypath"] });
+ assert_true(store2.add({ x: 'v', keypath: key }) instanceof IDBRequest);
+ };
+ open_rq.onsuccess = function(e) {
+ var rq = db.transaction("store")
+ .objectStore("store")
+ .get(key)
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result, 'value')
+ var rq = db.transaction("store2")
+ .objectStore("store2")
+ .get(['v', key])
+ rq.onsuccess = t.step_func(function(e) {
+ assert_object_equals(e.target.result, { x: 'v', keypath: key })
+ t.done()
+ })
+ })
+ }
+ }
+
+ // Date
+ valid_key( 'new Date()' , new Date() );
+ valid_key( 'new Date(0)' , new Date(0) );
+
+ // Array
+ valid_key( '[]' , [] );
+ valid_key( 'new Array()' , new Array() );
+
+ valid_key( '["undefined"]' , ['undefined'] );
+
+ // Float
+ valid_key( 'Infinity' , Infinity );
+ valid_key( '-Infinity' , -Infinity );
+ valid_key( '0' , 0 );
+ valid_key( '1.5' , 1.5 );
+ valid_key( '3e38' , 3e38 );
+ valid_key( '3e-38' , 3e38 );
+
+ // String
+ valid_key( '"foo"' , "foo" );
+ valid_key( '"\\n"' , "\n" );
+ valid_key( '""' , "" );
+ valid_key( '"\\""' , "\"" );
+ valid_key( '"\\u1234"' , "\u1234" );
+ valid_key( '"\\u0000"' , "\u0000" );
+ valid_key( '"NaN"' , "NaN" );
+
+</script>
+
+<div id=log></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/keygenerator-constrainterror.htm b/tests/wpt/web-platform-tests/IndexedDB/keygenerator-constrainterror.htm
new file mode 100644
index 00000000000..794b271ba39
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/keygenerator-constrainterror.htm
@@ -0,0 +1,76 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Keygenerator ConstraintError when using same id as already generated</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ var db,
+ t = async_test(document.title, {timeout: 10000}),
+ objects = [1, null, {id: 2}, null, 2.00001, 5, null, {id: 6} ],
+ expected = [1, 2, 2.00001, 3, 5, 6],
+ errors = 0;
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("store", { keyPath: "id", autoIncrement: true });
+
+ for (var i = 0; i < objects.length; i++)
+ {
+ if (objects[i] === null)
+ {
+ objStore.add({});
+ }
+ else if (typeof objects[i] === "object")
+ {
+ var rq = objStore.add(objects[i])
+ rq.yeh = objects[i];
+ rq.onerror = t.step_func(function(e) {
+ errors++;
+
+ assert_equals(e.target.error.name, "ConstraintError");
+ assert_equals(e.type, "error");
+
+ e.stopPropagation();
+ e.preventDefault();
+ });
+ rq.onsuccess = t.step_func(function(e) {
+ assert_unreached("Got rq.success when adding duplicate id " + objects[i]);
+ });
+ }
+ else
+ objStore.add({ id: objects[i] });
+ }
+ };
+
+ open_rq.onsuccess = function(e) {
+ var actual_keys = [],
+ rq = db.transaction("store")
+ .objectStore("store")
+ .openCursor();
+
+ rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ if (cursor) {
+ actual_keys.push(cursor.key.valueOf());
+ cursor.continue();
+ }
+ else {
+ assert_equals(errors, 2, "expected ConstraintError's");
+
+ assert_equals(actual_keys.length, expected.length, "array length");
+ assert_object_equals(actual_keys, expected, "keygenerator array");
+
+ t.done();
+ }
+ });
+ };
+
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/keygenerator-overflow.htm b/tests/wpt/web-platform-tests/IndexedDB/keygenerator-overflow.htm
new file mode 100644
index 00000000000..797a184be63
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/keygenerator-overflow.htm
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Keygenerator overflow</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#key-generator-concept">
+<link rel=assert title="When the current number of a key generator reaches above the value 2^53 (9007199254740992) any attempts to use the key generator to generate a new key will result in an error. It's still possible to insert records into the object store by specifying an explicit key, however the only way to use a key generator again for the object store is to delete the object store and create a new one.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ var db,
+ t = async_test(document.title, {timeout: 10000}),
+ overflow_error_fired = false,
+ objects = [9007199254740991, null, "error", 2, "error" ],
+ expected_keys = [2, 9007199254740991, 9007199254740992];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("store", { keyPath: "id", autoIncrement: true });
+
+ for (var i = 0; i < objects.length; i++)
+ {
+ if (objects[i] === null)
+ {
+ objStore.add({});
+ }
+ else if (objects[i] === "error")
+ {
+ var rq = objStore.add({});
+ rq.onsuccess = fail(t, 'When "current number" overflows, error event is expected');
+ rq.onerror = t.step_func(function(e) {
+ overflow_error_fired = true;
+ assert_equals(e.target.error.name, "ConstraintError", "error name");
+ e.preventDefault();
+ e.stopPropagation();
+ });
+ }
+ else
+ objStore.add({ id: objects[i] });
+ }
+ };
+
+ open_rq.onsuccess = function(e) {
+ var actual_keys = [],
+ rq = db.transaction("store")
+ .objectStore("store")
+ .openCursor();
+
+ rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ if (cursor) {
+ actual_keys.push(cursor.key.valueOf());
+ cursor.continue();
+ }
+ else {
+ assert_true(overflow_error_fired, "error fired on 'current number' overflow");
+ assert_object_equals(actual_keys, expected_keys, "keygenerator array");
+
+ t.done();
+ }
+ });
+ };
+
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/keygenerator.htm b/tests/wpt/web-platform-tests/IndexedDB/keygenerator.htm
new file mode 100644
index 00000000000..8430364fc9d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/keygenerator.htm
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Keygenerator</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#key-generator-concept">
+<link rel=assert title="The current number of a key generator is always set to 1 when the object store for that key generator is first created.">
+<link rel=assert title="When a key generator is used to generate a new key for a object store, the key generator's current number is used as the new key value and then the key generator's current number is increased by 1.">
+<link rel=assert title="When a record is stored in a object store which uses a key generator, and an explicit key is defined, if the key's value is a float greater than or equal to the key generator's current number, then the key generator's current number is set to the smallest integer number larger than the explicit key. Only explicit keys which are float values affect the current number of the key generator.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ function keygenerator(objects, expected_keys, desc, func) {
+ var db,
+ t = async_test(document.title + " - " + desc);
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("store", { keyPath: "id", autoIncrement: true });
+
+ for (var i = 0; i < objects.length; i++)
+ {
+ if (objects[i] === null)
+ objStore.add({});
+ else
+ objStore.add({ id: objects[i] });
+ }
+ };
+
+ open_rq.onsuccess = function(e) {
+ var actual_keys = [],
+ rq = db.transaction("store")
+ .objectStore("store")
+ .openCursor();
+
+ rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ if (cursor) {
+ actual_keys.push(cursor.key.valueOf());
+ cursor.continue();
+ }
+ else {
+ assert_equals(actual_keys.length, expected_keys.length, "array length");
+ assert_object_equals(actual_keys, expected_keys, "keygenerator array");
+
+ t.done();
+ }
+ });
+ };
+ }
+
+
+ keygenerator([null, null, null, null], [1, 2, 3, 4],
+ "starts at one, and increments by one");
+
+ keygenerator([2, null, 5, null, 6.66, 7], [2, 3, 5, 6, 6.66, 7],
+ "increments by one from last set key");
+
+ keygenerator([-10, null, "6", 6.3, [10], -2, 4, null], [-10, -2, 1, 4, 6.3, 7, "6", [10]],
+ "don't increment when new key is not bigger than current");
+
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/keyorder.htm b/tests/wpt/web-platform-tests/IndexedDB/keyorder.htm
new file mode 100644
index 00000000000..f65a4de4f0d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/keyorder.htm
@@ -0,0 +1,180 @@
+<!DOCTYPE html>
+<!-- Submitted from TestTWF Paris -->
+<meta charset="utf-8">
+<title>Key sort order</title>
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#key-construct">
+<link rel=assert title="For purposes of comparison, all Arrays are greater than all DOMString, Date and float values; all DOMString values are greater than all Date and float values; and all Date values are greater than all float values. Values of type float are compared to other float values numerically. Values of type Date are compared to other Date values chronologically. Values of type DOMString are compared to other values of type DOMString by using the algorithm defined by step 4 of section 11.8.5, The Abstract Relational Comparison Algorithm, of the ECMAScript Language Specification [ECMA-262]. Values of type Array are compared to other values of type Array as follows:
+
+1. Let A be the first Array value and B be the second Array value.
+2. Let length be the lesser of A's length and B's length.
+3. Let i be 0.
+4. If the ith value of A is less than the ith value of B, then A is less than B. Skip the remaining steps.
+5. If the ith value of A is greater than the ith value of B, then A is greater than B. Skip the remaining steps.
+6. Increase i by 1.
+7. If i is not equal to length, go back to step 4. Otherwise continue to next step.
+8. If A's length is less than B's length, then A is less than B. If A's length is greater than B's length, then A is greater than B. Otherwise A and B are equal.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var global_db = createdb_for_multiple_tests();
+
+ function keysort(desc, unsorted, expected) {
+ var db,
+ t = async_test("Database readback sort - " + desc, { timeout: 10000 }),
+ store_name = 'store-' + Date.now() + Math.random();
+
+ // The database test
+ var open_rq = global_db.setTest(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore(store_name);
+
+ for (var i = 0; i < unsorted.length; i++)
+ objStore.add("value", unsorted[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var actual_keys = [],
+ rq = db.transaction(store_name)
+ .objectStore(store_name)
+ .openCursor();
+
+ rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ if (cursor) {
+ actual_keys.push(cursor.key.valueOf());
+ cursor.continue();
+ }
+ else {
+ assert_object_equals(actual_keys, expected, "keyorder array");
+ assert_equals(actual_keys.length, expected.length, "array length");
+
+ t.done();
+ }
+ });
+ };
+
+ // The IDBKey.cmp test
+ test(function () {
+ var sorted = unsorted.slice(0).sort(function(a, b) { return indexedDB.cmp(a, b)});
+
+ for (var i in sorted)
+ if (typeof sorted[i] === "object" && 'valueOf' in sorted[i])
+ sorted[i] = sorted[i].valueOf();
+
+ assert_object_equals(sorted, expected, "sorted array");
+
+ }, "IDBKey.cmp sorted - " + desc);
+ }
+
+ var now = new Date(),
+ one_sec_ago = new Date(now - 1000),
+ one_min_future = new Date(now.getTime() + (1000*60));
+
+ keysort('String < Array',
+ [ [0], "yo", "", [] ],
+ [ "", "yo", [], [0] ]);
+
+ keysort('float < String',
+ [ Infinity, "yo", 0, "", 100 ],
+ [ 0, 100, Infinity, "", "yo" ]);
+
+ keysort('float < Date',
+ [ now, 0, 9999999999999, -0.22 ],
+ [ -0.22, 0, 9999999999999, now.valueOf() ]);
+
+ keysort('float < Date < String < Array',
+ [ [], "", now, [0], "-1", 0, 9999999999999, ],
+ [ 0, 9999999999999, now.valueOf(), "", "-1", [], [0] ]);
+
+
+ keysort('Date(1 sec ago) < Date(now) < Date(1 minute in future)',
+ [ now, one_sec_ago, one_min_future ],
+ [ one_sec_ago.valueOf(), now.valueOf(), one_min_future.valueOf() ]);
+
+ keysort('-1.1 < 1 < 1.01337 < 1.013373 < 2',
+ [ 1.013373, 2, 1.01337, -1.1, 1 ],
+ [ -1.1, 1, 1.01337, 1.013373, 2 ]);
+
+ keysort('-Infinity < -0.01 < 0 < Infinity',
+ [ 0, -0.01, -Infinity, Infinity ],
+ [ -Infinity, -0.01, 0, Infinity ]);
+
+ keysort('"" < "a" < "ab" < "b" < "ba"',
+ [ "a", "ba", "", "b", "ab" ],
+ [ "", "a", "ab", "b", "ba" ]);
+
+ keysort('Arrays',
+ [ [[0]], [0], [], [0, 0], [0, [0]] ],
+ [ [], [0], [0, 0], [0, [0]], [[0]] ]);
+
+ var big_array = [], bigger_array = [];
+ for (var i=0; i < 10000; i++) {
+ big_array.push(i);
+ bigger_array.push(i);
+ }
+ bigger_array.push(0);
+
+ keysort('Array.length: 10,000 < Array.length: 10,001',
+ [ bigger_array, [0, 2, 3], [0], [9], big_array ],
+ [ [0], big_array, bigger_array, [0, 2, 3], [9] ]);
+
+ keysort('Infinity inside arrays',
+ [ [Infinity, 1], [Infinity, Infinity], [1, 1],
+ [1, Infinity], [1, -Infinity], [-Infinity, Infinity] ],
+ [ [-Infinity, Infinity], [1, -Infinity], [1, 1],
+ [1, Infinity], [Infinity, 1], [Infinity, Infinity] ]);
+
+
+ keysort('Test different stuff at once',
+ [
+ now,
+ [0, []],
+ "test",
+ 1,
+ ["a", [1, [-1]]],
+ ["b", "a"],
+ [ 0, 2, "c"],
+ ["a", [1, 2]],
+ [],
+ [0, [], 3],
+ ["a", "b"],
+ [ 1, 2 ],
+ ["a", "b", "c"],
+ one_sec_ago,
+ [ 0, "b", "c"],
+ Infinity,
+ -Infinity,
+ 2.55,
+ [ 0, now ],
+ [1]
+ ],
+ [
+ -Infinity,
+ 1,
+ 2.55,
+ Infinity,
+ one_sec_ago.valueOf(),
+ now.valueOf(),
+ "test",
+ [],
+ [0 ,2, "c"],
+ [0, now.valueOf()],
+ [0, "b", "c"],
+ [0, []],
+ [0, [], 3],
+ [1],
+ [1, 2],
+ ["a", "b"],
+ ["a", "b", "c"],
+ ["a", [1, 2]],
+ ["a", [1, [-1]]],
+ ["b", "a"]
+ ]);
+
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/keypath.htm b/tests/wpt/web-platform-tests/IndexedDB/keypath.htm
new file mode 100644
index 00000000000..539af8e500b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/keypath.htm
@@ -0,0 +1,148 @@
+<!DOCTYPE html>
+<!-- Submitted from TestTWF Paris -->
+<meta charset="utf-8">
+<title>Keypath</title>
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#key-path-construct">
+<link rel=assert title="A key path is a DOMString that defines how to extract a key from a value. A valid key path is either the empty string, a JavaScript identifier, or multiple Javascript identifiers separated by periods (ASCII character code 46) [ECMA-262].">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ var global_db = createdb_for_multiple_tests();
+
+ function keypath(keypath, objects, expected_keys, desc) {
+ var db,
+ t = async_test(document.title + " - " + (desc ? desc : keypath)),
+
+ store_name = "store-"+(Date.now())+Math.random();
+
+ var open_rq = global_db.setTest(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore(store_name, { keyPath: keypath });
+
+ for (var i = 0; i < objects.length; i++)
+ objStore.add(objects[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var actual_keys = [],
+ rq = db.transaction(store_name)
+ .objectStore(store_name)
+ .openCursor();
+
+ rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ if (cursor) {
+ actual_keys.push(cursor.key.valueOf());
+ cursor.continue();
+ }
+ else {
+ assert_equals(actual_keys.length, expected_keys.length, "array length");
+ assert_object_equals(actual_keys, expected_keys, "keyorder array");
+
+ t.done();
+ }
+ });
+ };
+ }
+
+ keypath('my.key',
+ [ { my: { key: 10 } } ],
+ [ 10 ]);
+
+ keypath('my.køi',
+ [ { my: { køi: 5 } } ],
+ [ 5 ]);
+
+ keypath('my.key_ya',
+ [ { my: { key_ya: 10 } } ],
+ [ 10 ]);
+
+ keypath('public.key$ya',
+ [ { public: { key$ya: 10 } } ],
+ [ 10 ]);
+
+ keypath('true.$',
+ [ { true: { $: 10 } } ],
+ [ 10 ]);
+
+ keypath('my._',
+ [ { my: { _: 10 } } ],
+ [ 10 ]);
+
+ keypath('delete.a7',
+ [ { delete: { a7: 10 } } ],
+ [ 10 ]);
+
+ keypath('p.p.p.p.p.p.p.p.p.p.p.p.p.p',
+ [ {p:{p:{p:{p:{p:{p:{p:{p:{p:{p:{p:{p:{p:{p:10}}}}}}}}}}}}}} ],
+ [ 10 ]);
+
+ keypath('str.length',
+ [ { str: "pony" }, { str: "my" }, { str: "little" }, { str: "" } ],
+ [ 0, 2, 4, 6 ]);
+
+ keypath('arr.length',
+ [ {arr: [0, 0, 0, 0]}, {arr: [{}, 0, "hei", "length", Infinity, []]}, {arr: [10, 10]}, { arr: []} ],
+ [ 0, 2, 4, 6 ]);
+
+ keypath('length',
+ [ [10, 10], "123", { length: 20 } ],
+ [ 2, 3, 20 ]);
+
+ keypath('',
+ [ ["bags"], "bean", 10 ],
+ [ 10, "bean", ["bags"] ],
+ "'' uses value as key");
+
+ keypath([''],
+ [ ["bags"], "bean", 10 ],
+ [ [10], ["bean"] , [["bags"]] ],
+ "[''] uses value as [key]");
+
+ keypath(['x', 'y'],
+ [ {x:10, y:20}, {y:1.337, x:100} ],
+ [ [10, 20], [100, 1.337] ],
+ "['x', 'y']");
+
+ keypath([['x'], ['y']],
+ [ {x:10, y:20}, {y:1.337, x:100} ],
+ [ [10, 20], [100, 1.337] ],
+ "[['x'], 'y'] (stringifies)");
+
+ keypath(['x', {toString:function(){return 'y'}}],
+ [ {x:10, y:20}, {y:1.337, x:100} ],
+ [ [10, 20], [100, 1.337] ],
+ "['x', {toString->'y'}] (stringifies)");
+
+ if (false) {
+ var myblob = Blob(["Yoda"], {type:'suprawsum'});
+ keypath(['length', 'type'],
+ [ myblob ],
+ [ 4, 'suprawsum' ],
+ "[Blob.length, Blob.type]");
+ }
+
+ // File.name and File.lastModifiedDate is not testable automatically
+
+ keypath(['name', 'type'],
+ [ { name: "orange", type: "fruit" }, { name: "orange", type: ["telecom", "french"] } ],
+ [ ["orange", "fruit"], ["orange", ["telecom", "french"]] ]);
+
+ keypath(['name', 'type.name'],
+ [ { name: "orange", type: { name: "fruit" }}, { name: "orange", type: { name: "telecom" }} ],
+ [ ["orange", "fruit"], ["orange", "telecom" ] ]);
+
+ loop_array = [];
+ loop_array.push(loop_array);
+ keypath(loop_array,
+ [ "a", 1, ["k"] ],
+ [ [1], ["a"], [["k"]] ],
+ "array loop -> stringify becomes ['']");
+</script>
+
+<div id=log></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/keypath_invalid.htm b/tests/wpt/web-platform-tests/IndexedDB/keypath_invalid.htm
new file mode 100644
index 00000000000..9c5bd6c2f6c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/keypath_invalid.htm
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<!-- Submitted from TestTWF Paris -->
+<meta charset="utf-8">
+<title>Invalid keypath</title>
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#key-path-construct">
+<link rel=assert title="A key path is a DOMString that defines how to extract a key from a value. A valid key path is either the empty string, a JavaScript identifier, or multiple Javascript identifiers separated by periods (ASCII character code 46) [ECMA-262].">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ var global_db = createdb_for_multiple_tests();
+
+ function invalid_keypath(keypath, desc) {
+ var t = async_test("Invalid keyPath - " + (desc ? desc : format_value(keypath)), undefined, 2);
+
+ var openrq = global_db.setTest(t),
+ store_name = "store-" + Date.now() + Math.random();
+
+ openrq.onupgradeneeded = function(e) {
+ var db = e.target.result;
+ assert_throws('SyntaxError', function() {
+ db.createObjectStore(store_name, { keyPath: keypath })
+ }, "createObjectStore with keyPath");
+
+ store = db.createObjectStore(store_name);
+ assert_throws('SyntaxError', function() {
+ store.createIndex('index', keypath);
+ }, "createIndex with keyPath");
+
+ db.close();
+
+ this.done();
+ };
+ }
+
+ invalid_keypath('j a');
+ invalid_keypath('.yo');
+ invalid_keypath('yo,lo');
+ invalid_keypath([]);
+ invalid_keypath(['array with space']);
+ invalid_keypath(['multi_array', ['a', 'b']], "multidimensional array (invalid toString)"); // => ['multi_array', 'a,b']
+ invalid_keypath('3m');
+ invalid_keypath({toString:function(){return '3m'}}, '{toString->3m}');
+ invalid_keypath('my.1337');
+ invalid_keypath('..yo');
+ invalid_keypath('y..o');
+ invalid_keypath('y.o.');
+ invalid_keypath('y.o..');
+ invalid_keypath('m.*');
+ invalid_keypath('"m"');
+ invalid_keypath('m%');
+ invalid_keypath('m/');
+ invalid_keypath('m/a');
+ invalid_keypath('m&');
+ invalid_keypath('m!');
+ invalid_keypath('*');
+ invalid_keypath('*.*');
+ invalid_keypath('^m');
+ invalid_keypath('/m/');
+
+</script>
+
+<div id=log></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/keypath_maxsize.htm b/tests/wpt/web-platform-tests/IndexedDB/keypath_maxsize.htm
new file mode 100644
index 00000000000..5e0415dbc1d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/keypath_maxsize.htm
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Keypath</title>
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#key-path-construct">
+<link rel=assert title="A key path is a DOMString that defines how to extract a key from a value. A valid key path is either the empty string, a JavaScript identifier, or multiple Javascript identifiers separated by periods (ASCII character code 46) [ECMA-262].">
+<meta name=timeout content=long>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ function keypath(keypath, objects, expected_keys, desc) {
+ var db,
+ t = async_test(document.title + " - " + (desc ? desc : keypath), { timeout: 10000 }),
+ open_rq = createdb(t);
+
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("store", { keyPath: keypath });
+
+ for (var i = 0; i < objects.length; i++)
+ objStore.add(objects[i]);
+ };
+
+ open_rq.onerror = function(e) {
+ assert_unreached(e.target.error.name);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var actual_keys = [],
+ rq = db.transaction("store")
+ .objectStore("store")
+ .openCursor();
+
+ rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ if (cursor) {
+ actual_keys.push(cursor.key.valueOf());
+ cursor.continue();
+ } else {
+ assert_equals(actual_keys.length, expected_keys.length, "array length");
+ assert_object_equals(actual_keys, expected_keys, "keyorder array");
+
+ t.done();
+ }
+ });
+ };
+ }
+
+ keypath('maaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaai.keeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeey',
+ [ { maaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaai: { keeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeey: 10 } } ],
+ [ 10 ], '~260 chars');
+
+ keypath('maaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaai_maaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaai.keeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeey_keeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeey',
+ [ { maaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaai_maaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaai: { keeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeey_keeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeey: 10 } } ],
+ [ 10 ], '~530 chars');
+
+ keypath('maaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaai_maaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaai_maaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaai_maaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaai.keeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeey_keeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeey_keeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeey_keeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeey',
+ [ { maaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaai_maaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaai_maaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaai_maaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaai: { keeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeey_keeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeey_keeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeey_keeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeey: 10 } } ],
+ [ 10 ], '~1050 chars');
+
+</script>
+
+<div id=log></log>
+
diff --git a/tests/wpt/web-platform-tests/IndexedDB/list_ordering.htm b/tests/wpt/web-platform-tests/IndexedDB/list_ordering.htm
new file mode 100644
index 00000000000..8349dbae79f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/list_ordering.htm
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>objectStoreNames and indexNames order</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBDatabase-objectStoreNames">
+<link rel=assert title="The list must be sorted in ascending order using the algorithm defined by step 4 of section 11.8.5, The Abstract Relational Comparison Algorithm of the ECMAScript Language Specification [ECMA-262].">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ function list_order(desc, unsorted, expected) {
+ var objStore, db,
+ t = async_test(document.title + " - " + desc);
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ for (var i = 0; i < unsorted.length; i++)
+ objStore = db.createObjectStore(unsorted[i]);
+
+ assert_equals(db.objectStoreNames.length, expected.length, "objectStoreNames length");
+ for (var i = 0; i < expected.length; i++)
+ assert_equals(db.objectStoreNames[i], expected[i], "objectStoreNames["+i+"]");
+
+ for (var i = 0; i < unsorted.length; i++)
+ objStore.createIndex(unsorted[i], "length");
+
+ assert_equals(objStore.indexNames.length, expected.length, "indexNames length");
+ for (var i = 0; i < expected.length; i++)
+ assert_equals(objStore.indexNames[i], expected[i], "indexNames["+i+"]");
+ };
+
+ open_rq.onsuccess = function(e) {
+ assert_equals(db.objectStoreNames.length, expected.length, "objectStoreNames length");
+ for (var i = 0; i < expected.length; i++)
+ assert_equals(db.objectStoreNames[i], expected[i], "objectStoreNames["+i+"]");
+
+ assert_equals(objStore.indexNames.length, expected.length, "indexNames length");
+ for (var i = 0; i < expected.length; i++)
+ assert_equals(objStore.indexNames[i], expected[i], "indexNames["+i+"]");
+
+ t.done();
+ };
+ }
+
+ list_order("numbers",
+ [123456, -12345, -123, 123, 1234, -1234, 0, 12345, -123456],
+ ["-123", "-1234", "-12345", "-123456", "0", "123", "1234", "12345", "123456"]);
+
+ list_order("numbers 'overflow'",
+ [9, 1, 1000000000, 200000000000000000],
+ ["1", "1000000000", "200000000000000000", "9"]);
+
+ list_order("lexigraphical string sort",
+ [ "cc", "c", "aa", "a", "bb", "b", "ab", "", "ac" ],
+ [ "", "a", "aa", "ab", "ac", "b", "bb", "c", "cc" ]);
+
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/objectstore_keyorder.htm b/tests/wpt/web-platform-tests/IndexedDB/objectstore_keyorder.htm
new file mode 100644
index 00000000000..69c281fd02a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/objectstore_keyorder.htm
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Verify key sort order in an object store is 'number &lt; Date &lt; DOMString' </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ d = new Date(),
+ t = async_test(),
+ records = [ { key: d },
+ { key: "test" },
+ { key: 1 },
+ { key: 2.55 } ],
+ expectedKeyOrder = [ 1, 2.55, d.valueOf(), "test" ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("store", { keyPath: "key" });
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var actual_keys = [],
+ rq = db.transaction("store")
+ .objectStore("store")
+ .openCursor();
+
+ rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ if (cursor) {
+ actual_keys.push(cursor.key.valueOf());
+ cursor.continue();
+ }
+ else {
+ assert_array_equals(actual_keys, expectedKeyOrder);
+ t.done();
+ }
+ });
+ };
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/request_bubble-and-capture.htm b/tests/wpt/web-platform-tests/IndexedDB/request_bubble-and-capture.htm
new file mode 100644
index 00000000000..930e20ee0db
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/request_bubble-and-capture.htm
@@ -0,0 +1,69 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Bubbling and capturing of request events</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var events = [];
+
+ var open_rq = createdb(async_test(document.title, {timeout: 10000}));
+ open_rq.onupgradeneeded = function(e) {
+ var db = e.target.result;
+ var txn = e.target.transaction;
+ var store = db.createObjectStore("s");
+ var rq1 = store.add("", 1);
+ var rq2 = store.add("", 1);
+ db.onerror = function(){};
+
+ log_request(' db', db);
+ log_request('txn', txn);
+ log_request('rq1', rq1);
+ log_request('rq2', rq2);
+
+ // Don't let it get to abort
+ db.addEventListener('error', function(e) { e.preventDefault() }, false);
+ }
+
+ open_rq.onsuccess = function(e) {
+ log("open_rq.success")(e);
+ assert_object_equals(events, [
+ "capture db.success",
+ "capture txn.success",
+ "capture rq1.success",
+ "bubble rq1.success",
+
+ "capture db.error: ConstraintError",
+ "capture txn.error: ConstraintError",
+ "capture rq2.error: ConstraintError",
+ "bubble rq2.error: ConstraintError",
+ "bubble txn.error: ConstraintError",
+ "bubble db.error: ConstraintError",
+
+ "open_rq.success"
+ ],
+ "events");
+ this.done();
+ }
+
+
+ function log_request(type, obj) {
+ obj.addEventListener('success', log('capture ' + type + '.success'), true);
+ obj.addEventListener('success', log('bubble ' + type + '.success'), false);
+ obj.addEventListener('error', log('capture ' + type + '.error'), true);
+ obj.addEventListener('error', log('bubble ' + type + '.error'), false);
+ }
+
+ function log(msg) {
+ return function(e) {
+ if(e && e.target && e.target.error)
+ events.push(msg + ": " + e.target.error.name);
+ else
+ events.push(msg);
+ };
+ }
+</script>
+
+<div id=log></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/string-list-ordering.htm b/tests/wpt/web-platform-tests/IndexedDB/string-list-ordering.htm
new file mode 100644
index 00000000000..cc905e56ecf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/string-list-ordering.htm
@@ -0,0 +1,85 @@
+<!--
+Test converted from WebKit:
+http://trac.webkit.org/browser/trunk/LayoutTests/storage/indexeddb/resources/list-ordering.js
+-->
+
+<!DOCTYPE html>
+<!-- Submitted from TestTWF Paris -->
+<meta charset=utf-8>
+<title>Test string list ordering in IndexedDB</title>
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBDatabase-objectStoreNames">
+<link rel=assert title="The list must be sorted in ascending order using the algorithm defined by step 4 of section 11.8.5, The Abstract Relational Comparison Algorithm of the ECMAScript Language Specification [ECMA-262].">
+<link rel=author href="mailto:romain.huet@gmail.com" title="Romain Huet">
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+
+ var expectedOrder = [
+ "",
+ "\x00", // 'NULL' (U+0000)
+ "0",
+ "1",
+ "A",
+ "B",
+ "a",
+ "b",
+ "\x7F", // 'DELETE' (U+007F)
+ "\xC0", // 'LATIN CAPITAL LETTER A WITH GRAVE' (U+00C0)
+ "\xC1", // 'LATIN CAPITAL LETTER A WITH ACUTE' (U+00C1)
+ "\xE0", // 'LATIN SMALL LETTER A WITH GRAVE' (U+00E0)
+ "\xE1", // 'LATIN SMALL LETTER A WITH ACUTE' (U+00E1)
+ "\xFF", // 'LATIN SMALL LETTER Y WITH DIAERESIS' (U+00FF)
+ "\u0100", // 'LATIN CAPITAL LETTER A WITH MACRON' (U+0100)
+ "\u1000", // 'MYANMAR LETTER KA' (U+1000)
+ "\uD834\uDD1E", // 'MUSICAL SYMBOL G-CLEF' (U+1D11E), UTF-16 surrogate pairs
+ "\uFFFD" // 'REPLACEMENT CHARACTER' (U+FFFD)
+ ];
+
+ var i, tmp, permutedOrder = expectedOrder.slice();
+ permutedOrder.reverse();
+ for (i = 0; i < permutedOrder.length - 2; i += 2) {
+ tmp = permutedOrder[i];
+ permutedOrder[i] = permutedOrder[i + 1];
+ permutedOrder[i + 1] = tmp;
+ }
+
+ var objStore, db;
+ var t = async_test();
+
+ // Check that the expected order is the canonical JS sort order.
+ var sortedOrder = expectedOrder.slice();
+ sortedOrder.sort();
+ assert_array_equals(sortedOrder, expectedOrder);
+
+ var request = createdb(t);
+
+ request.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ // Object stores.
+ for (var i = 0; i < permutedOrder.length; i++) {
+ objStore = db.createObjectStore(permutedOrder[i]);
+ }
+ assert_array_equals(db.objectStoreNames, expectedOrder);
+
+ // Indexes.
+ for (var i = 0; i < permutedOrder.length; i++) {
+ objStore.createIndex(permutedOrder[i], "keyPath");
+ }
+ assert_array_equals(objStore.indexNames, expectedOrder);
+ };
+
+ request.onsuccess = function(e) {
+ // Object stores.
+ assert_array_equals(db.objectStoreNames, expectedOrder);
+ // Indexes.
+ assert_array_equals(objStore.indexNames, expectedOrder);
+ t.done();
+ };
+
+</script>
+
+<div id=log></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/support.js b/tests/wpt/web-platform-tests/IndexedDB/support.js
new file mode 100644
index 00000000000..858fe5d7701
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/support.js
@@ -0,0 +1,122 @@
+var databaseName = "database";
+var databaseVersion = 1;
+
+if (!window.indexedDB)
+{
+ if (window.msIndexedDB)
+ {
+ window.indexedDB = window.msIndexedDB;
+ }
+ else if (window.mozIndexedDB)
+ {
+ window.indexedDB = window.mozIndexedDB;
+ }
+ else if (window.webkitIndexedDB)
+ {
+ window.indexedDB = webkitIndexedDB;
+ IDBCursor = webkitIDBCursor;
+ IDBDatabaseException = webkitIDBDatabaseException;
+ IDBIndex = webkitIDBIndex;
+ IDBObjectStore = webkitIDBObjectStore;
+ IDBRequest = webkitIDBRequest;
+ IDBKeyRange = webkitIDBKeyRange;
+ IDBTransaction = webkitIDBTransaction;
+ }
+}
+
+/* Delete created databases
+ *
+ * Go through each finished test, see if it has an associated database. Close
+ * that and delete the database. */
+add_completion_callback(function(tests)
+{
+ for (var i in tests)
+ {
+ if(tests[i].db)
+ {
+ tests[i].db.close();
+ window.indexedDB.deleteDatabase(tests[i].db.name);
+ }
+ }
+});
+
+function fail(test, desc) {
+ return test.step_func(function(e) {
+ if (e && e.message && e.target.error)
+ assert_unreached(desc + " (" + e.target.error.name + ": " + e.message + ")");
+ else if (e && e.message)
+ assert_unreached(desc + " (" + e.message + ")");
+ else if (e && e.target.readyState === 'done' && e.target.error)
+ assert_unreached(desc + " (" + e.target.error.name + ")");
+ else
+ assert_unreached(desc);
+ });
+}
+
+function createdb(test, dbname, version)
+{
+ var rq_open = createdb_for_multiple_tests(dbname, version);
+ return rq_open.setTest(test);
+}
+
+function createdb_for_multiple_tests(dbname, version) {
+ var rq_open,
+ fake_open = {},
+ test = null,
+ dbname = (dbname ? dbname : "testdb-" + new Date().getTime() + Math.random() );
+
+ if (version)
+ rq_open = window.indexedDB.open(dbname, version);
+ else
+ rq_open = window.indexedDB.open(dbname);
+
+ function auto_fail(evt, current_test) {
+ /* Fail handlers, if we haven't set on/whatever/, don't
+ * expect to get event whatever. */
+ rq_open.manually_handled = {}
+
+ rq_open.addEventListener(evt, function(e) {
+ if (current_test !== test) {
+ return;
+ }
+
+ test.step(function() {
+ if (!rq_open.manually_handled[evt]) {
+ assert_unreached("unexpected open." + evt + " event");
+ }
+
+ if (e.target.result + "" == "[object IDBDatabase]" && !this.db) {
+ this.db = e.target.result;
+
+ this.db.onerror = fail(test, "unexpected db.error");
+ this.db.onabort = fail(test, "unexpected db.abort");
+ this.db.onversionchange = fail(test, "unexpected db.versionchange");
+ }
+ })
+ })
+ rq_open.__defineSetter__("on" + evt, function(h) {
+ rq_open.manually_handled[evt] = true;
+ if (!h)
+ rq_open.addEventListener(evt, function() {});
+ else
+ rq_open.addEventListener(evt, test.step_func(h));
+ })
+ }
+
+ // add a .setTest method to the DB object
+ Object.defineProperty(rq_open, 'setTest', {
+ enumerable: false,
+ value: function(t) {
+ test = t;
+
+ auto_fail("upgradeneeded", test);
+ auto_fail("success", test);
+ auto_fail("blocked", test);
+ auto_fail("error", test);
+
+ return this;
+ }
+ });
+
+ return rq_open;
+}
diff --git a/tests/wpt/web-platform-tests/IndexedDB/transaction-create_in_versionchange.htm b/tests/wpt/web-platform-tests/IndexedDB/transaction-create_in_versionchange.htm
new file mode 100644
index 00000000000..be2cd224500
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/transaction-create_in_versionchange.htm
@@ -0,0 +1,82 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Attempt to create new transactions inside a versionchange transaction</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var db, events = [],
+ open_rq = createdb(async_test())
+
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result
+
+ db.createObjectStore("store")
+ .add("versionchange1", 1)
+ .addEventListener("success", log("versionchange_add.success"))
+
+ assert_throws('InvalidStateError', function() { db.transaction("store") })
+
+ e.target.transaction
+ .objectStore("store")
+ .count(2)
+ .addEventListener("success", log("versionchange_count.success"))
+
+ assert_throws('InvalidStateError', function() { db.transaction("store", "readwrite") })
+
+ open_rq.transaction
+ .objectStore("store")
+ .add("versionchange2", 2)
+ .addEventListener("success", log("versionchange_add2.success"))
+
+ open_rq.transaction.oncomplete = function(e) {
+ log("versionchange_txn.complete")(e)
+
+ db.transaction("store")
+ .objectStore("store")
+ .count()
+ .addEventListener("success", log("complete_count.success"))
+ }
+ }
+
+ open_rq.onsuccess = function(e) {
+ log("open_rq.success")(e)
+
+ var txn = db.transaction("store", "readwrite")
+ txn.objectStore("store")
+ .put("woo", 1)
+ .addEventListener("success", log("complete2_get.success"))
+
+ txn.oncomplete = this.step_func(function(e) {
+ assert_object_equals(events, [
+ "versionchange_add.success: 1",
+ "versionchange_count.success: 0",
+ "versionchange_add2.success: 2",
+ "versionchange_txn.complete",
+
+ "open_rq.success: [object IDBDatabase]",
+
+ "complete_count.success: 2",
+ "complete2_get.success: 1",
+ ],
+ "events")
+ this.done()
+ })
+ }
+
+
+ function log(msg) {
+ return function(e) {
+ if(e && e.target && e.target.error)
+ events.push(msg + ": " + e.target.error.name)
+ else if(e && e.target && e.target.result !== undefined)
+ events.push(msg + ": " + e.target.result)
+ else
+ events.push(msg)
+ };
+ }
+</script>
+
+<div id=log></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/transaction-lifetime-blocked.htm b/tests/wpt/web-platform-tests/IndexedDB/transaction-lifetime-blocked.htm
new file mode 100644
index 00000000000..3288506c505
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/transaction-lifetime-blocked.htm
@@ -0,0 +1,108 @@
+<!DOCTYPE html>
+<title>Blocked event</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<div id="log"></div>
+
+<script>
+
+ var db, db_got_versionchange, db2,
+ events = [],
+ t = async_test(document.title, {timeout: 10000});
+
+ t.step(function() {
+ var openrq = indexedDB.open('db', 3);
+
+ // 1
+ openrq.onupgradeneeded = t.step_func(function(e) {
+ events.push("open." + e.type);
+ e.target.result.createObjectStore('store');
+ });
+
+ // 2
+ openrq.onsuccess = t.step_func(function(e) {
+ db = e.target.result;
+
+ events.push("open." + e.type);
+
+ // 3
+ db.onversionchange = t.step_func(function(e) {
+ events.push("db." + e.type);
+
+ assert_equals(e.oldVersion, 3, "old version");
+ assert_equals(e.newVersion, 4, "new version");
+ // Do not close db here (as we should)
+ });
+
+ // Errors
+ db.onerror = fail(t, "db.error");
+ db.abort = fail(t, "db.abort");
+
+ setTimeout(t.step_func(OpenSecond), 10);
+ });
+
+ // Errors
+ openrq.onerror = fail(t, "open.error");
+ openrq.onblocked = fail(t, "open.blocked");
+
+ });
+
+ function OpenSecond (e) {
+ assert_equals(db2, undefined);
+ assert_equals(db + "", "[object IDBDatabase]");
+ assert_array_equals(db.objectStoreNames, [ "store" ]);
+
+ var openrq2 = indexedDB.open('db', 4);
+
+ // 4
+ openrq2.onblocked = t.step_func(function(e) {
+ events.push("open2." + e.type);
+ // We're closing connection from the other open()
+ db.close();
+ });
+
+ // 5
+ openrq2.onupgradeneeded = t.step_func(function(e) {
+ db2 = e.target.result;
+
+ events.push("open2." + e.type);
+
+ assert_equals(db2 + "", "[object IDBDatabase]");
+
+ // Errors
+ db2.onversionchange = fail(t, "db2.versionchange");
+ db2.onerror = fail(t, "db2.error");
+ db2.abort = fail(t, "db2.abort");
+ });
+
+ // 6
+ openrq2.onsuccess = t.step_func(function(e) {
+ events.push("open2." + e.type);
+
+ assert_array_equals(events,
+ [ "open.upgradeneeded",
+ "open.success",
+ "db.versionchange",
+ "open2.blocked",
+ "open2.upgradeneeded",
+ "open2.success",
+ ]);
+
+ setTimeout(function() { t.done(); }, 10);
+ });
+
+ // Errors
+ openrq2.onerror = fail(t, "open2.error");
+ }
+
+
+ // Cleanup
+ add_completion_callback(function(tests) {
+ if (db2) db2.close();
+ indexedDB.deleteDatabase('db');
+ })
+
+</script>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/transaction-lifetime.htm b/tests/wpt/web-platform-tests/IndexedDB/transaction-lifetime.htm
new file mode 100644
index 00000000000..2412424fd4e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/transaction-lifetime.htm
@@ -0,0 +1,101 @@
+<!DOCTYPE html>
+<title>Test events opening a second database when one connection is open already</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<div id="log"></div>
+
+<script>
+
+ var db, db_got_versionchange, db2,
+ events = [],
+ t = async_test(document.title, {timeout: 10000});
+
+ t.step(function() {
+ var openrq = indexedDB.open('db', 3);
+
+ // 1
+ openrq.onupgradeneeded = t.step_func(function(e) {
+ events.push("open." + e.type);
+ e.target.result.createObjectStore('store');
+ });
+
+ // 2
+ openrq.onsuccess = t.step_func(function(e) {
+ db = e.target.result;
+
+ events.push("open." + e.type);
+
+ // 3
+ db.onversionchange = t.step_func(function(e) {
+ events.push("db." + e.type);
+
+ assert_equals(e.oldVersion, 3, "old version");
+ assert_equals(e.newVersion, 4, "new version");
+ db.close();
+ });
+
+ // Errors
+ db.onerror = fail(t, "db.error");
+ db.abort = fail(t, "db.abort");
+
+ setTimeout(t.step_func(OpenSecond), 10);
+ });
+
+ // Errors
+ openrq.onerror = fail(t, "open.error");
+ openrq.onblocked = fail(t, "open.blocked");
+
+ });
+
+ function OpenSecond (e) {
+ assert_equals(db2, undefined);
+ assert_equals(db + "", "[object IDBDatabase]");
+ assert_array_equals(db.objectStoreNames, [ "store" ]);
+
+ var openrq2 = indexedDB.open('db', 4);
+
+ // 4
+ openrq2.onupgradeneeded = t.step_func(function(e) {
+ db2 = e.target.result;
+
+ events.push("open2." + e.type);
+
+ assert_equals(db2 + "", "[object IDBDatabase]");
+
+ // Errors
+ db2.onversionchange = fail(t, "db2.versionchange");
+ db2.onerror = fail(t, "db2.error");
+ db2.abort = fail(t, "db2.abort");
+ });
+
+ // 5
+ openrq2.onsuccess = t.step_func(function(e) {
+ events.push("open2." + e.type);
+
+ assert_array_equals(events,
+ [ "open.upgradeneeded",
+ "open.success",
+ "db.versionchange",
+ "open2.upgradeneeded",
+ "open2.success",
+ ]);
+
+ setTimeout(function() { t.done(); }, 10);
+ });
+
+ // Errors
+ openrq2.onerror = fail(t, "open2.error");
+ openrq2.onblocked = fail(t, "open2.blocked");
+ }
+
+
+ // Cleanup
+ add_completion_callback(function(tests) {
+ if (db2) db2.close();
+ indexedDB.deleteDatabase('db');
+ })
+
+</script>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/transaction-requestqueue.htm b/tests/wpt/web-platform-tests/IndexedDB/transaction-requestqueue.htm
new file mode 100644
index 00000000000..b34c37e98c2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/transaction-requestqueue.htm
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Transactions have a request queue</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+
+var db, t = async_test(document.title, {timeout: 10000}),
+ keys = { txn: [], txn2: [] },
+ open_rq = createdb(t)
+
+open_rq.onupgradeneeded = function(e) {
+ var i, os;
+ db = e.target.result;
+
+ for (i = 1; i < 6; i++)
+ {
+ os = db.createObjectStore("os" + i, { autoIncrement: true, keyPath: "k" });
+ os.add({ os: "os" + i });
+ os.put({ os: "os" + i, k: i});
+ os.add({ os: "os" + i });
+ }
+
+// assert_object_equals(db.objectStoreNames, ["os1", "os2", "os3", "os4", "os5" ], "objectStores");
+}
+
+open_rq.onsuccess = function(e) {
+ var txn = db.transaction(["os2", "os1", "os3", "os5"])
+ txn.objectStore("os1").openCursor().onsuccess = reg("txn")
+ txn.objectStore("os3").openCursor().onsuccess = reg("txn")
+ txn.objectStore("os1").get(2).onsuccess = reg("txn")
+ txn.objectStore("os2").get(3).onsuccess = reg("txn")
+
+ var txn2 = db.transaction(["os4", "os3", "os1", "os5"])
+ var os4 = txn2.objectStore("os4")
+
+ for (var i=0; i < 3; i++) {
+ os4.openCursor().onsuccess = reg("txn2")
+ os4.get(5).onsuccess = reg("txn2")
+ os4.get(4).onsuccess = reg("txn2")
+ txn.objectStore("os2").get(1).onsuccess = reg("txn")
+ txn2.objectStore("os3").get(1).onsuccess = reg("txn2")
+ }
+
+ txn2.objectStore("os1").get(2).onsuccess = reg("txn2")
+ txn.objectStore("os1").openCursor(null, "prev").onsuccess = reg("txn")
+ os4.openCursor(null, "prev").onsuccess = reg("txn2")
+
+ txn.oncomplete = t.step_func(finish);
+ txn2.oncomplete = t.step_func(finish);
+}
+
+
+function reg(n) {
+ return t.step_func(function (e) {
+ var v = e.target.result;
+ if (v.value) v = v.value;
+ keys[n].push(v.os + ": " + v.k);
+ });
+}
+
+var finish_to_go = 2;
+function finish() {
+ if (--finish_to_go)
+ return;
+
+ assert_object_equals(keys['txn'], [
+ "os1: 1",
+ "os3: 1",
+ "os1: 2",
+ "os2: 3",
+ "os2: 1", "os2: 1", "os2: 1",
+ "os1: 2",
+ ], 'transaction keys');
+
+ assert_object_equals(keys['txn2'], [
+ "os4: 1", "os4: 5", "os4: 4", "os3: 1",
+ "os4: 1", "os4: 5", "os4: 4", "os3: 1",
+ "os4: 1", "os4: 5", "os4: 4", "os3: 1",
+ "os1: 2",
+ "os4: 5",
+ ], 'transaction 2 keys');
+
+ t.done();
+}
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/transaction_bubble-and-capture.htm b/tests/wpt/web-platform-tests/IndexedDB/transaction_bubble-and-capture.htm
new file mode 100644
index 00000000000..9da61f4fcde
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/transaction_bubble-and-capture.htm
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Capture and bubble</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var events = [];
+
+ var open_rq = createdb(async_test(document.title, {timeout: 10000}));
+ open_rq.onupgradeneeded = function(e) {
+ var db = e.target.result;
+ var txn = e.target.transaction;
+ var store = db.createObjectStore("store");
+ var rq1 = store.add("", 1);
+ var rq2 = store.add("", 1);
+
+ db.onerror = undefined; // We will run db.error, but don't let that fail the test
+
+ log_events('db', db, 'success');
+ log_events('db', db, 'error');
+
+ log_events('txn', txn, 'success');
+ log_events('txn', txn, 'error');
+
+ log_events('rq1', rq1, 'success');
+ log_events('rq1', rq1, 'error');
+
+ log_events('rq2', rq2, 'success');
+ log_events('rq2', rq2, 'error');
+
+ // Don't let it get to abort
+ db.addEventListener('error', function(e) { e.preventDefault(); }, false);
+ }
+
+ open_rq.onsuccess = function(e) {
+ log("open_rq.success")(e);
+ assert_object_equals(events, [
+ "capture db.success",
+ "capture txn.success",
+ "capture rq1.success",
+ "bubble rq1.success",
+
+ "capture db.error: ConstraintError",
+ "capture txn.error: ConstraintError",
+ "capture rq2.error: ConstraintError",
+ "bubble rq2.error: ConstraintError",
+ "bubble txn.error: ConstraintError",
+ "bubble db.error: ConstraintError",
+
+ "open_rq.success",
+ ],
+ "events");
+ this.done();
+ }
+
+
+ function log_events(type, obj, evt) {
+ obj.addEventListener(evt, log('capture ' + type + '.' + evt), true);
+ obj.addEventListener(evt, log('bubble ' + type + '.' + evt), false);
+ }
+
+ function log(msg) {
+ return function(e) {
+ if(e && e.target && e.target.error)
+ events.push(msg + ": " + e.target.error.name);
+ else
+ events.push(msg);
+ };
+ }
+</script>
+
+<div id=log></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/value.htm b/tests/wpt/web-platform-tests/IndexedDB/value.htm
new file mode 100644
index 00000000000..36e83395248
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/value.htm
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Values</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+function value(value, _instanceof) {
+ var t = async_test(document.title + " - " + _instanceof.name);
+ t.step(function() {
+ assert_true(value instanceof _instanceof, "TEST ERROR, instanceof");
+ });
+
+ createdb(t).onupgradeneeded = function(e) {
+ e.target.result
+ .createObjectStore("store")
+ .add(value, 1);
+
+ e.target.onsuccess = t.step_func(function(e) {
+ e.target.result
+ .transaction("store")
+ .objectStore("store")
+ .get(1)
+ .onsuccess = t.step_func(function(e)
+ {
+ assert_true(e.target.result instanceof _instanceof, "instanceof")
+ t.done();
+ });
+ });
+ };
+}
+
+value(new Date(), Date);
+value(new Array(), Array);
+
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/value_recursive.htm b/tests/wpt/web-platform-tests/IndexedDB/value_recursive.htm
new file mode 100644
index 00000000000..f49a1ccbc59
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/value_recursive.htm
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Recursive value</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+function recursive_value(desc, value) {
+ var db, t = async_test(document.title + " - " + desc);
+
+ createdb(t).onupgradeneeded = function(e) {
+ db = e.target.result
+ db.createObjectStore("store")
+ .add(value, 1);
+
+ e.target.onsuccess = t.step_func(function(e) {
+ db.transaction('store')
+ .objectStore('store')
+ .get(1)
+ .onsuccess = t.step_func(function(e)
+ {
+
+ try
+ {
+ var fresh_value = JSON.stringify(value);
+ assert_unreached("Testcase is written wrongly, must supply something recursive (that JSON won't stringify).");
+ }
+ catch (e)
+ {
+ if (e.name == 'TypeError')
+ {
+ try
+ {
+ JSON.stringify(e.target.result);
+ assert_unreached("Expected a non-JSON-serializable value back, didn't get that.");
+ }
+ catch (e)
+ {
+ t.done();
+ return;
+ }
+ }
+ else
+ throw e;
+ }
+ });
+ });
+ };
+}
+
+var recursive = [];
+recursive.push(recursive);
+recursive_value('array directly contains self', recursive);
+
+var recursive2 = [];
+recursive2.push([recursive2]);
+recursive_value('array indirectly contains self', recursive2);
+
+var recursive3 = [recursive];
+recursive_value('array member contains self', recursive3);
+
+</script>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/IndexedDB/writer-starvation.htm b/tests/wpt/web-platform-tests/IndexedDB/writer-starvation.htm
new file mode 100644
index 00000000000..ae6c90150e2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/writer-starvation.htm
@@ -0,0 +1,105 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Writer starvation</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<meta name=timeout content=long>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var db, read_request_count = 0, read_success_count = 0;
+ var write_request_count = 0, write_success_count = 0;
+ var RQ_COUNT = 25;
+
+ var open_rq = createdb(async_test(undefined, {timeout: 20000}));
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ db.createObjectStore("s")
+ .add("1", 1);
+ }
+
+ open_rq.onsuccess = function(e) {
+ var i = 0, continue_reading = true;
+
+ /* Pre-fill some read requests */
+ for (i = 0; i < RQ_COUNT; i++)
+ {
+ read_request_count++;
+
+ db.transaction("s")
+ .objectStore("s")
+ .get(1)
+ .onsuccess = this.step_func(function(e) {
+ read_success_count++;
+ assert_equals(e.target.transaction.mode, "readonly");
+ });
+ }
+
+ this.step(loop);
+
+ function loop() {
+ read_request_count++;
+
+ db.transaction("s")
+ .objectStore("s")
+ .get(1)
+ .onsuccess = this.step_func(function(e)
+ {
+ read_success_count++;
+ assert_equals(e.target.transaction.mode, "readonly");
+
+ if (read_success_count >= RQ_COUNT && write_request_count == 0)
+ {
+ write_request_count++;
+
+ db.transaction("s", "readwrite")
+ .objectStore("s")
+ .add("written", read_request_count)
+ .onsuccess = this.step_func(function(e)
+ {
+ write_success_count++;
+ assert_equals(e.target.transaction.mode, "readwrite");
+ assert_equals(e.target.result, read_success_count,
+ "write cb came before later read cb's")
+ });
+
+ /* Reads done after the write */
+ for (i = 0; i < 5; i++)
+ {
+ read_request_count++;
+
+ db.transaction("s")
+ .objectStore("s")
+ .get(1)
+ .onsuccess = this.step_func(function(e)
+ {
+ read_success_count++;
+ });
+ }
+ }
+ });
+
+ if (read_success_count < RQ_COUNT + 5)
+ setTimeout(this.step_func(loop), write_request_count ? 1000 : 100);
+ else
+ // This is merely a "nice" hack to run finish after the last request is done
+ db.transaction("s")
+ .objectStore("s")
+ .count()
+ .onsuccess = this.step_func(function()
+ {
+ setTimeout(this.step_func(finish), 100);
+ });
+ }
+ }
+
+
+function finish() {
+ assert_equals(read_request_count, read_success_count, "read counts");
+ assert_equals(write_request_count, write_success_count, "write counts");
+ this.done();
+}
+</script>
+
+<div id=log></div>
diff --git a/tests/wpt/web-platform-tests/LICENSE b/tests/wpt/web-platform-tests/LICENSE
new file mode 100644
index 00000000000..28fcc080cb4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/LICENSE
@@ -0,0 +1,29 @@
+W3C 3-clause BSD License
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of works must retain the original copyright notice, this
+ list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the original copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of the W3C nor the names of its contributors may be
+ used to endorse or promote products derived from this work without
+ specific prior written permission.
+
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
diff --git a/tests/wpt/web-platform-tests/README.md b/tests/wpt/web-platform-tests/README.md
new file mode 100644
index 00000000000..0c1c7165ca5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/README.md
@@ -0,0 +1,218 @@
+The Web Platform Tests Project [![IRC chat](https://goo.gl/6nCIks)](http://irc.w3.org/?channels=testing)
+==============================
+
+These are test suites for 60+ Web-platform specifications, along
+with test-infrastructure code for running the tests.
+
+Running the Tests
+=================
+
+The tests are designed to be run from your local computer. The test
+environment requires Python 2.7+ (but not Python 3.x). You will also
+need a copy of OpenSSL. For users on Windows this is available from
+[the openssl website](https://www.openssl.org/related/binaries.html).
+
+To get the tests running, you need to set up the test domains in your
+[`hosts` file](http://en.wikipedia.org/wiki/Hosts_%28file%29%23Location_in_the_file_system). The
+following entries are required:
+
+```
+127.0.0.1 web-platform.test
+127.0.0.1 www.web-platform.test
+127.0.0.1 www1.web-platform.test
+127.0.0.1 www2.web-platform.test
+127.0.0.1 xn--n8j6ds53lwwkrqhv28a.web-platform.test
+127.0.0.1 xn--lve-6lad.web-platform.test
+```
+
+Because web-platform-tests uses git submodules, you must ensure that
+these are up to date. In the root of your checkout, run:
+
+```
+git submodule update --init --recursive
+```
+
+The test environment can then be started using
+
+```
+./serve
+```
+
+This will start HTTP servers on two ports and a websockets server on
+one port. By default one web server starts on port 8000 and the other
+ports are randomly-chosen free ports. Tests must be loaded from the
+*first* HTTP server in the output. To change the ports, edit the
+`config.json` file, for example, replacing the part that reads:
+
+```
+"http": [8000, "auto"]
+```
+
+to some port of your choice e.g.
+
+```
+"http":[1234, "auto"]
+```
+
+If you installed OpenSSL in such a way that running `openssl` at a
+command line doesn't work, you also need to adjust the path to the
+OpenSSL binary. This can be done by adding a section to `config.json`
+like:
+
+```
+"ssl": {"openssl": {"binary": "/path/to/openssl"}}
+```
+
+Test Runner
+===========
+
+There is a test runner that is designed to provide a
+convenient way to run the web-platform tests in-browser. It will run
+testharness.js tests automatically but requires manual work for
+reftests and manual tests.
+
+The runner can be found at `/tools/runner/index.html` on the local
+server i.e.
+
+```
+http://web-platform.test:8000/tools/runner/index.html
+```
+
+in the default configuration. The first time you use this it has to
+generate a manifest of all tests. This may take some time, so please
+be patient.
+
+Publication
+===========
+
+The master branch is automatically synced to http://w3c-test.org/.
+
+Pull requests that have been checked are automatically mirrored to
+http://w3c-test.org/submissions/.
+
+Finding Things
+==============
+
+Each top-level directory represents a W3C specification: the name
+matches the shortname used after the canonical address of the said
+specification under http://www.w3.org/TR/ .
+
+For some of the specifications, the tree under the top-level directory
+represents the sections of the respective documents, using the section
+IDs for directory names, with a maximum of three levels deep.
+
+So if you're looking for tests in HTML for "The History interface",
+they will be under `html/browsers/history/the-history-interface/`.
+
+Various resources that tests depend on are in `common`, `images`, and
+`fonts`.
+
+
+If you're looking at a section of the specification and can't figure
+out where the directory is for it in the tree, just run:
+
+```
+node tools/scripts/id2path.js your-id
+```
+
+Branches
+========
+
+In the vast majority of cases the **only** upstream branch that you
+should need to care about is `master`. If you see other branches in
+the repository, you can generally safely ignore them.
+
+Contributing
+============
+
+Save the Web, Write Some Tests!
+
+Absolutely everyone is welcome (and even encouraged) to contribute to
+test development, so long as you fulfill the contribution requirements
+detailed in the [Contributing Guidelines][contributing]. No test is
+too small or too simple, especially if it corresponds to something for
+which you've noted an interoperability bug in a browser.
+
+The way to contribute is just as usual:
+
+* Fork this repository (and make sure you're still relatively in sync
+ with it if you forked a while ago).
+* Create a branch for your changes:
+ `git checkout -b your-name/topic`.
+* Make your changes.
+* Run the lint script described below.
+* Commit locally and push that to your repo.
+* Send in a pull request based on the above.
+
+A lint is available to test for common mistakes in testcases. It can
+be run with:
+
+```
+./lint
+```
+
+in the root of the checkout. It is also run for every submitted pull
+request, and branches with lint errors will not get merged. In the
+unusual case that the lint is reporting an error for something that is
+essential to your test, there is a whitelist at
+`tools/lint/lint.whitelist` that may be updated.
+
+Adding command-line scripts ("tools" subdirs)
+---------------------------------------------
+
+Sometimes you may want to add a script to the repository that's meant
+to be used from the command line, not from a browser (e.g., a script
+for generating test files). If you want to ensure (e.g., for security
+reasons) that such scripts won't be handled by the HTTP server, but
+will instead only be usable from the command line, then place them in
+either:
+
+* the `tools` subdir at the root of the repository, or
+
+* the `tools` subdir at the root of any top-level directory in the
+ repository which contains the tests the script is meant to be used
+ with
+
+Any files in those `tools` directories won't be handled by the HTTP
+server; instead the server will return a 404 if a user navigates to
+the URL for a file within them.
+
+If you want to add a script for use with a particular set of tests but
+there isn't yet any `tools` subdir at the root of a top-level
+directory in the repository containing those tests, you can create a
+`tools` subdir at the root of that top-level directory and place your
+scripts there.
+
+For example, if you wanted to add a script for use with tests in the
+`notifications` directory, create the `notifications/tools` subdir and
+put your script there.
+
+Test Review
+===========
+
+We can sometimes take a little while to go through pull requests
+because we have to go through all the tests and ensure that they match
+the specification correctly. But we look at all of them, and take
+everything that we can.
+
+Getting Involved
+================
+
+If you wish to contribute actively, you're very welcome to join the
+public-test-infra@w3.org mailing list (low traffic) by
+[signing up to our mailing list](mailto:public-test-infra-request@w3.org?subject=subscribe).
+The mailing list is [archived][mailarchive].
+
+Join us on irc #testing ([irc.w3.org][ircw3org], port 6665). The channel
+is [archived][ircarchive].
+
+[contributing]: https://github.com/w3c/web-platform-tests/blob/master/CONTRIBUTING.md
+[ircw3org]: https://www.w3.org/wiki/IRC
+[ircarchive]: http://krijnhoetmer.nl/irc-logs/testing/
+[mailarchive]: http://lists.w3.org/Archives/Public/public-test-infra/
+
+Documentation
+=============
+
+* [How to write and review tests](http://testthewebforward.org/docs/)
+* [Documentation for the wptserve server](http://wptserve.readthedocs.org/en/latest/)
diff --git a/tests/wpt/web-platform-tests/WebCryptoAPI/README.md b/tests/wpt/web-platform-tests/WebCryptoAPI/README.md
new file mode 100644
index 00000000000..5546cf2b6f2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebCryptoAPI/README.md
@@ -0,0 +1 @@
+Directory for Crypto API tests
diff --git a/tests/wpt/web-platform-tests/WebCryptoAPI/test_getRandomValues.html b/tests/wpt/web-platform-tests/WebCryptoAPI/test_getRandomValues.html
new file mode 100644
index 00000000000..62b00e9f12c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebCryptoAPI/test_getRandomValues.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>WebCryptoAPI: getRandomValues()</title>
+<link rel="author" title="Sunil Yoo" href="mailto:usuanday83@gmail.com">
+<link rel="help" href="https://dvcs.w3.org/hg/webcrypto-api/raw-file/tip/spec/Overview.html#dfn-Crypto-method-getRandomValues">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+// Step 1.
+test(function() {
+ assert_throws("TypeMismatchError", function() {
+ window.crypto.getRandomValues(new Float32Array(6))
+ }, "Float32Array")
+ assert_throws("TypeMismatchError", function() {
+ window.crypto.getRandomValues(new Float64Array(6))
+ }, "Float64Array")
+
+ assert_throws("TypeMismatchError", function() {
+ window.crypto.getRandomValues(new Float32Array(65537))
+ }, "Float32Array (too long)")
+ assert_throws("TypeMismatchError", function() {
+ window.crypto.getRandomValues(new Float64Array(65537))
+ }, "Float64Array (too long)")
+}, "Float arrays")
+
+test(function() {
+ assert_equals(window.crypto.getRandomValues(new Int8Array(8)).constructor,
+ Int8Array, "crypto.getRandomValues(new Int8Array(8))")
+ assert_equals(window.crypto.getRandomValues(new Uint8Array(8)).constructor,
+ Uint8Array, "crypto.getRandomValues(new Uint8Array(8))")
+
+ assert_equals(window.crypto.getRandomValues(new Int16Array(8)).constructor,
+ Int16Array, "crypto.getRandomValues(new Int16Array(8))")
+ assert_equals(window.crypto.getRandomValues(new Uint16Array(8)).constructor,
+ Uint16Array, "crypto.getRandomValues(new Uint16Array(8))")
+
+ assert_equals(window.crypto.getRandomValues(new Int32Array(8)).constructor,
+ Int32Array, "crypto.getRandomValues(new Int32Array(8))")
+ assert_equals(window.crypto.getRandomValues(new Uint32Array(8)).constructor,
+ Uint32Array, "crypto.getRandomValues(new Uint32Array(8))")
+
+ assert_throws("QuotaExceededError", function() {
+ window.crypto.getRandomValues(new Int8Array(65537))
+ }, "crypto.getRandomValues length over 65536")
+})
+</script>
diff --git a/tests/wpt/web-platform-tests/WebIDL/ecmascript-binding/es-exceptions/DOMException-constants.html b/tests/wpt/web-platform-tests/WebIDL/ecmascript-binding/es-exceptions/DOMException-constants.html
new file mode 100644
index 00000000000..450b4b334e6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/ecmascript-binding/es-exceptions/DOMException-constants.html
@@ -0,0 +1,59 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>DOMException constants</title>
+<link rel=help href="https://heycam.github.io/webidl/#es-DOMException-constructor-object">
+<link rel=help href="https://heycam.github.io/webidl/#es-DOMException-prototype-object">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ // https://www.w3.org/Bugs/Public/show_bug.cgi?id=27732
+ var constants = [
+ "INDEX_SIZE_ERR",
+ "DOMSTRING_SIZE_ERR",
+ "HIERARCHY_REQUEST_ERR",
+ "WRONG_DOCUMENT_ERR",
+ "INVALID_CHARACTER_ERR",
+ "NO_DATA_ALLOWED_ERR",
+ "NO_MODIFICATION_ALLOWED_ERR",
+ "NOT_FOUND_ERR",
+ "NOT_SUPPORTED_ERR",
+ "INUSE_ATTRIBUTE_ERR",
+ "INVALID_STATE_ERR",
+ "SYNTAX_ERR",
+ "INVALID_MODIFICATION_ERR",
+ "NAMESPACE_ERR",
+ "INVALID_ACCESS_ERR",
+ "VALIDATION_ERR",
+ "TYPE_MISMATCH_ERR",
+ "SECURITY_ERR",
+ "NETWORK_ERR",
+ "ABORT_ERR",
+ "URL_MISMATCH_ERR",
+ "QUOTA_EXCEEDED_ERR",
+ "TIMEOUT_ERR",
+ "INVALID_NODE_TYPE_ERR",
+ "DATA_CLONE_ERR"
+ ]
+ var objects = [
+ [DOMException, "DOMException constructor object"],
+ [DOMException.prototype, "DOMException prototype object"]
+ ]
+ constants.forEach(function(name, i) {
+ objects.forEach(function(o) {
+ var object = o[0], description = o[1];
+ test(function() {
+ assert_equals(object[name], i + 1, name)
+ assert_own_property(object, name)
+ var pd = Object.getOwnPropertyDescriptor(object, name)
+ assert_false("get" in pd, "property has getter")
+ assert_false("set" in pd, "property has setter")
+ assert_false(pd.writable, "not writable")
+ assert_true(pd.enumerable, "enumerable")
+ assert_false(pd.configurable, "not configurable")
+ }, "Constant " + name + " on " + description)
+ })
+ })
+})
+</script>
diff --git a/tests/wpt/web-platform-tests/WebIDL/ecmascript-binding/es-exceptions/DOMException-constructor.html b/tests/wpt/web-platform-tests/WebIDL/ecmascript-binding/es-exceptions/DOMException-constructor.html
new file mode 100644
index 00000000000..9dc6d9918a3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/ecmascript-binding/es-exceptions/DOMException-constructor.html
@@ -0,0 +1,73 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>DOMException constructor</title>
+<link rel=help href="https://heycam.github.io/webidl/#es-DOMException-constructor-object">
+<link rel=help href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-error.prototype.message">
+<link rel=help href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-error.prototype.name">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ var ex = new DOMException();
+ assert_equals(ex.name, "Error",
+ "Not passing a name should end up with 'Error' as the name");
+ assert_equals(ex.message, "",
+ "Not passing a message should end up with empty string as the message");
+}, 'new DOMException()');
+
+test(function() {
+ var ex = new DOMException();
+ assert_false(ex.hasOwnProperty("name"),
+ "The name property should be inherited");
+ assert_false(ex.hasOwnProperty("message"),
+ "The message property should be inherited");
+}, 'new DOMException(): own-ness');
+
+test(function() {
+ var ex = new DOMException(undefined);
+ assert_equals(ex.name, "Error",
+ "Not passing a name should end up with 'Error' as the name");
+ assert_equals(ex.message, "",
+ "Not passing a message should end up with empty string as the message");
+}, 'new DOMException(undefined)');
+
+test(function() {
+ var ex = new DOMException(undefined);
+ assert_false(ex.hasOwnProperty("name"),
+ "The name property should be inherited");
+ assert_false(ex.hasOwnProperty("message"),
+ "The message property should be inherited");
+}, 'new DOMException(undefined): own-ness');
+
+test(function() {
+ var ex = new DOMException("foo");
+ assert_equals(ex.name, "Error",
+ "Not passing a name should still end up with 'Error' as the name");
+ assert_equals(ex.message, "foo", "Should be using passed-in message");
+}, 'new DOMException("foo")');
+
+test(function() {
+ var ex = new DOMException("foo");
+ assert_false(ex.hasOwnProperty("name"),
+ "The name property should be inherited");
+ assert_true(ex.hasOwnProperty("message"),
+ "The message property should be own");
+}, 'new DOMException("foo"): own-ness');
+
+test(function() {
+ var ex = new DOMException("bar", "NotSupportedError");
+ assert_equals(ex.name, "NotSupportedError", "Should be using the passed-in name");
+ assert_equals(ex.message, "bar", "Should still be using passed-in message");
+ assert_equals(ex.code, DOMException.NOT_SUPPORTED_ERR,
+ "Should have the right exception code");
+}, 'new DOMException("bar", "NotSupportedError")');
+
+test(function() {
+ var ex = new DOMException("bar", "NotSupportedError");
+ assert_true(ex.hasOwnProperty("name"),
+ "The name property should be own");
+ assert_true(ex.hasOwnProperty("message"),
+ "The message property should be own");
+}, 'new DOMException("bar", "NotSupportedError"): own-ness');
+</script>
diff --git a/tests/wpt/web-platform-tests/WebIDL/ecmascript-binding/es-exceptions/constructor-object.html b/tests/wpt/web-platform-tests/WebIDL/ecmascript-binding/es-exceptions/constructor-object.html
new file mode 100644
index 00000000000..ddb40f4ddea
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/ecmascript-binding/es-exceptions/constructor-object.html
@@ -0,0 +1,11 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>DOMException constructor and prototype object</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src=constructor-object.js></script>
+<div id="log"></div>
+<script>
+setup({ explicit_done: true })
+run_test()
+</script>
diff --git a/tests/wpt/web-platform-tests/WebIDL/ecmascript-binding/es-exceptions/constructor-object.js b/tests/wpt/web-platform-tests/WebIDL/ecmascript-binding/es-exceptions/constructor-object.js
new file mode 100644
index 00000000000..e539d85dbbb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/ecmascript-binding/es-exceptions/constructor-object.js
@@ -0,0 +1,111 @@
+function run_test() {
+ test(function() {
+ // "There MUST exist a property on the ECMAScript global object whose
+ // name is “DOMException” and value is an object called the
+ // DOMException constructor object, which provides access to legacy
+ // DOMException code constants. The property has the attributes
+ // { [[Writable]]: true, [[Enumerable]]: false,
+ // [[Configurable]]: true }."
+ assert_own_property(self, "DOMException",
+ "self does not have own property \"DOMException\"");
+ var desc = Object.getOwnPropertyDescriptor(self, "DOMException");
+ assert_false("get" in desc, "self's property \"DOMException\" has getter");
+ assert_false("set" in desc, "self's property \"DOMException\" has setter");
+ assert_true(desc.writable, "self's property \"DOMException\" is not writable");
+ assert_false(desc.enumerable, "self's property \"DOMException\" is enumerable");
+ assert_true(desc.configurable, "self's property \"DOMException\" is not configurable");
+
+ // "The DOMException constructor object MUST be a function object but
+ // with a [[Prototype]] value of %Error% ([ECMA-262], section 6.1.7.4)."
+ assert_equals(Object.getPrototypeOf(self.DOMException), Error,
+ "prototype of self's property \"DOMException\" is not Error");
+
+ // "Its [[Get]] internal property is set as described in ECMA-262
+ // section 9.1.8."
+ // Not much to test for this.
+ // "Its [[Construct]] internal property is set as described in ECMA-262
+ // section 19.2.2.3."
+ // "Its @@hasInstance property is set as described in ECMA-262 section
+ // 19.2.3.8, unless otherwise specified."
+
+ // String() returns something implementation-dependent, because it
+ // calls Function#toString.
+ assert_class_string(self.DOMException, "Function",
+ "class string of DOMException");
+
+ // "For every legacy code listed in the error names table, there MUST
+ // be a property on the DOMException constructor object whose name and
+ // value are as indicated in the table. The property has attributes
+ // { [[Writable]]: false, [[Enumerable]]: true,
+ // [[Configurable]]: false }."
+ // See DOMException-constants.html.
+ }, "existence and properties of DOMException");
+
+ test(function() {
+ assert_own_property(self, "DOMException",
+ "self does not have own property \"DOMException\"");
+
+ // "The DOMException constructor object MUST also have a property named
+ // “prototype” with attributes { [[Writable]]: false,
+ // [[Enumerable]]: false, [[Configurable]]: false } whose value is an
+ // object called the DOMException prototype object. This object also
+ // provides access to the legacy code values."
+ assert_own_property(self.DOMException, "prototype",
+ 'exception "DOMException" does not have own property "prototype"');
+ var desc = Object.getOwnPropertyDescriptor(self.DOMException, "prototype");
+ assert_false("get" in desc, "DOMException.prototype has getter");
+ assert_false("set" in desc, "DOMException.prototype has setter");
+ assert_false(desc.writable, "DOMException.prototype is writable");
+ assert_false(desc.enumerable, "DOMException.prototype is enumerable");
+ assert_false(desc.configurable, "DOMException.prototype is configurable");
+
+ // "The DOMException prototype object MUST have an internal
+ // [[Prototype]] property whose value is %ErrorPrototype% ([ECMA-262],
+ // section 6.1.7.4)."
+ assert_own_property(self, "Error",
+ 'should inherit from Error, but self has no such property');
+ assert_own_property(self.Error, "prototype",
+ 'should inherit from Error, but that object has no "prototype" property');
+ assert_equals(Object.getPrototypeOf(self.DOMException.prototype),
+ self.Error.prototype,
+ 'prototype of DOMException.prototype is not Error.prototype');
+
+ // "The class string of the DOMException prototype object is
+ // “DOMExceptionPrototype”."
+ assert_class_string(self.DOMException.prototype, "DOMExceptionPrototype",
+ "class string of DOMException.prototype");
+ }, "existence and properties of DOMException.prototype");
+
+ test(function() {
+ assert_false(self.DOMException.prototype.hasOwnProperty("name"),
+ "DOMException.prototype should not have an own \"name\" " +
+ "property.");
+ assert_false(self.DOMException.prototype.hasOwnProperty("code"),
+ "DOMException.prototype should not have an own \"name\" " +
+ "property.");
+ }, "existence of name and code properties on DOMException.prototype");
+
+ test(function() {
+ assert_own_property(self, "DOMException",
+ "self does not have own property \"DOMException\"");
+ assert_own_property(self.DOMException, "prototype",
+ 'interface "DOMException" does not have own property "prototype"');
+
+ // "There MUST be a property named “constructor” on the DOMException
+ // prototype object with attributes { [[Writable]]: true,
+ // [[Enumerable]]: false, [[Configurable]]: true } and whose value is
+ // the DOMException constructor object."
+ assert_own_property(self.DOMException.prototype, "constructor",
+ "DOMException" + '.prototype does not have own property "constructor"');
+ var desc = Object.getOwnPropertyDescriptor(self.DOMException.prototype, "constructor");
+ assert_false("get" in desc, "DOMException.prototype.constructor has getter");
+ assert_false("set" in desc, "DOMException.prototype.constructor has setter");
+ assert_true(desc.writable, "DOMException.prototype.constructor is not writable");
+ assert_false(desc.enumerable, "DOMException.prototype.constructor is enumerable");
+ assert_true(desc.configurable, "DOMException.prototype.constructor in not configurable");
+ assert_equals(self.DOMException.prototype.constructor, self.DOMException,
+ "DOMException.prototype.constructor is not the same object as DOMException");
+ }, "existence and properties of exception interface prototype object's \"constructor\" property");
+
+ done();
+}
diff --git a/tests/wpt/web-platform-tests/WebIDL/ecmascript-binding/es-exceptions/constructor-object.worker.js b/tests/wpt/web-platform-tests/WebIDL/ecmascript-binding/es-exceptions/constructor-object.worker.js
new file mode 100644
index 00000000000..75149244f59
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/ecmascript-binding/es-exceptions/constructor-object.worker.js
@@ -0,0 +1,3 @@
+importScripts("/resources/testharness.js")
+importScripts("constructor-object.js")
+run_test();
diff --git a/tests/wpt/web-platform-tests/WebIDL/ecmascript-binding/es-exceptions/exceptions.html b/tests/wpt/web-platform-tests/WebIDL/ecmascript-binding/es-exceptions/exceptions.html
new file mode 100644
index 00000000000..bc1d7fe6395
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/ecmascript-binding/es-exceptions/exceptions.html
@@ -0,0 +1,136 @@
+<!doctype html>
+<title>DOMException-throwing tests</title>
+<link rel=author title="Aryeh Gregor" href=ayg@aryeh.name>
+<div id=log></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+/**
+ * This file just picks one case where browsers are supposed to throw an
+ * exception, and tests the heck out of whether it meets the spec. In the
+ * future, all these checks should be in assert_throws(), but we don't want
+ * every browser failing every assert_throws() check until they fix every
+ * single bug in their exception-throwing.
+ *
+ * We don't go out of our way to test everything that's already tested by
+ * interfaces.html, like whether all constants are present on the object, but
+ * some things are duplicated.
+ */
+setup({explicit_done: true});
+
+function testException(exception, global, desc) {
+ // https://heycam.github.io/webidl/#es-exception-objects
+ // (as of 2015-01-03): "The value of the internal [[Prototype]] property of a
+ // DOMException object MUST be the DOMException prototype object from the
+ // global environment the exception object is associated with."
+ test(function() {
+ assert_equals(global.Object.getPrototypeOf(exception),
+ global.DOMException.prototype);
+ }, desc + "Object.getPrototypeOf(exception) === DOMException.prototype");
+
+
+ // https://heycam.github.io/webidl/#es-creating-throwing-exceptions
+ // (as of 2015-01-03): "Call the [[DefineOwnProperty]] internal method of /O/
+ // passing “name”, Property Descriptor { [[Value]]: /N/, [[Writable]]: true,
+ // [[Enumerable]]: true, [[Configurable]]: true }, and false as arguments."
+ test(function() {
+ assert_true(exception.hasOwnProperty("name"));
+ }, desc + "exception.hasOwnProperty(\"name\")");
+
+ test(function() {
+ assert_equals(exception.name, "HierarchyRequestError");
+ }, desc + "exception.name === \"HierarchyRequestError\"");
+
+ test(function() {
+ var desc = global.Object.getOwnPropertyDescriptor(exception, "name");
+ assert_true(desc.writable, "must be writable");
+ assert_true(desc.enumerable, "must be enumerable");
+ assert_true(desc.configurable, "must be configurable");
+ }, desc + "Object.getOwnPropertyDescriptor(exception, \"name\")");
+
+
+ // https://heycam.github.io/webidl/#es-creating-throwing-exceptions
+ // (as of 2015-01-03): "If the optional user agent-defined message /M/ was
+ // specified, then this list has a single element whose value is the result
+ // of converting /M/ to a String value. Otherwise, the list is empty."
+ //
+ // https://heycam.github.io/webidl/#es-DOMException-constructor-object
+ // (as of 2015-01-03): "Call the [[DefineOwnProperty]] internal method of /O/
+ // passing “message”, Property Descriptor { [[Value]]: /S/,
+ // [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }, and
+ // false as arguments."
+ test(function() {
+ if (exception.hasOwnProperty("message")) {
+ var desc = global.Object.getOwnPropertyDescriptor(exception, "message");
+ assert_true(desc.writable, "must be writable");
+ assert_false(desc.enumerable, "must not be enumerable");
+ assert_true(desc.configurable, "must be configurable");
+ }
+ }, desc + "Object.getOwnPropertyDescriptor(exception, \"message\")");
+
+ test(function() {
+ if (exception.hasOwnProperty("message")) {
+ // Can't test anything more specific, since it's implementation-defined :(
+ assert_equals(typeof exception.message, "string");
+ } else {
+ // Error.prototype.message
+ assert_equals(exception.message, "");
+ }
+ }, desc + "typeof exception.message === \"string\"");
+
+
+ // https://heycam.github.io/webidl/#es-exception-objects
+ // (as of 2015-01-03): "The class string of a DOMException object MUST be
+ // “DOMException”."
+ test(function() {
+ assert_equals(global.Object.prototype.toString.call(exception),
+ "[object DOMException]");
+ }, desc + "Object.prototype.toString.call(exception) === \"[object DOMException]\"");
+
+
+ // https://heycam.github.io/webidl/#es-creating-throwing-exceptions
+ // (as of 2015-01-03): "Call the [[DefineOwnProperty]] internal method of /O/
+ // passing “code”, Property Descriptor { [[Value]]: /code/,
+ // [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true }, and
+ // false as arguments."
+ test(function() {
+ assert_equals(exception.code, global.DOMException.HIERARCHY_REQUEST_ERR);
+ }, desc + "exception.code === DOMException.HIERARCHY_REQUEST_ERR");
+
+ test(function() {
+ var desc = global.Object.getOwnPropertyDescriptor(exception, "name");
+ assert_true(desc.writable, "must be writable");
+ assert_true(desc.enumerable, "must be enumerable");
+ assert_true(desc.configurable, "must be configurable");
+ }, desc + "Object.getOwnPropertyDescriptor(exception, \"code\")");
+}
+
+
+// Test in current window
+var exception = null;
+try {
+ // This should throw a HierarchyRequestError in every browser since the
+ // Stone Age, so we're really only testing exception-throwing details.
+ document.documentElement.appendChild(document);
+} catch(e) {
+ exception = e;
+}
+testException(exception, window, "");
+
+// Test in iframe
+var iframe = document.createElement("iframe");
+iframe.src = "about:blank";
+iframe.onload = function() {
+ var exception = null;
+ try {
+ iframe.contentDocument.documentElement.appendChild(iframe.contentDocument);
+ } catch(e) {
+ exception = e;
+ }
+ testException(exception, iframe.contentWindow, "In iframe: ");
+
+ document.body.removeChild(iframe);
+ done();
+};
+document.body.appendChild(iframe);
+</script>
diff --git a/tests/wpt/web-platform-tests/WebIDL/invalid/idl/enum.widl b/tests/wpt/web-platform-tests/WebIDL/invalid/idl/enum.widl
new file mode 100644
index 00000000000..c355c3251c0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/invalid/idl/enum.widl
@@ -0,0 +1 @@
+enum foo { 1, 2, 3}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/WebIDL/invalid/idl/module.widl b/tests/wpt/web-platform-tests/WebIDL/invalid/idl/module.widl
new file mode 100644
index 00000000000..a4c79fdf155
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/invalid/idl/module.widl
@@ -0,0 +1,25 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+module gfx {
+
+ module geom {
+ interface Shape { /* ... */ };
+ interface Rectangle : Shape { /* ... */ };
+ interface Path : Shape { /* ... */ };
+ };
+
+ interface GraphicsContext {
+ void fillShape(geom::Shape s);
+ void strokeShape(geom::Shape s);
+ };
+};
+
+module gui {
+
+ interface Widget { /* ... */ };
+
+ interface Window : Widget {
+ gfx::GraphicsContext getGraphicsContext();
+ };
+
+ interface Button : Widget { /* ... */ };
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/WebIDL/invalid/idl/nonnullableany.widl b/tests/wpt/web-platform-tests/WebIDL/invalid/idl/nonnullableany.widl
new file mode 100644
index 00000000000..38957655523
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/invalid/idl/nonnullableany.widl
@@ -0,0 +1,3 @@
+interface NonNullable {
+ attribute any? foo;
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/WebIDL/invalid/idl/nonnullableobjects.widl b/tests/wpt/web-platform-tests/WebIDL/invalid/idl/nonnullableobjects.widl
new file mode 100644
index 00000000000..1deac5aeec9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/invalid/idl/nonnullableobjects.widl
@@ -0,0 +1,5 @@
+interface Foo {};
+
+interface NonNullable {
+ attribute Foo?? foo;
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/WebIDL/invalid/idl/raises.widl b/tests/wpt/web-platform-tests/WebIDL/invalid/idl/raises.widl
new file mode 100644
index 00000000000..ff65522f2b3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/invalid/idl/raises.widl
@@ -0,0 +1,18 @@
+// getraises and setraises are not longer valid Web IDL
+interface Person {
+
+ // An attribute that can raise an exception if it is set to an invalid value.
+ attribute DOMString name setraises (InvalidName);
+
+ // An attribute whose value cannot be assigned to, and which can raise an
+ // exception some circumstances.
+ readonly attribute DOMString petName getraises (NoSuchPet);
+};
+
+exception SomeException {
+};
+
+interface ExceptionThrower {
+ // This attribute always throws a SomeException and never returns a value.
+ attribute long valueOf getraises(SomeException);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/WebIDL/invalid/idl/scopedname.widl b/tests/wpt/web-platform-tests/WebIDL/invalid/idl/scopedname.widl
new file mode 100644
index 00000000000..cfcb1ccc939
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/invalid/idl/scopedname.widl
@@ -0,0 +1,2 @@
+// scoped names are no longer valid in WebIDL
+ typedef gfx::geom::geom2d::Point Point;
diff --git a/tests/wpt/web-platform-tests/WebIDL/invalid/idl/sequenceAsAttribute.widl b/tests/wpt/web-platform-tests/WebIDL/invalid/idl/sequenceAsAttribute.widl
new file mode 100644
index 00000000000..c23da82ac22
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/invalid/idl/sequenceAsAttribute.widl
@@ -0,0 +1,3 @@
+interface sequenceAsAttribute {
+ attribute sequence<short> invalid;
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/WebIDL/invalid/idl/special-omittable.widl b/tests/wpt/web-platform-tests/WebIDL/invalid/idl/special-omittable.widl
new file mode 100644
index 00000000000..bdfbfa70973
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/invalid/idl/special-omittable.widl
@@ -0,0 +1,8 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+// omittable is no longer a recognized keywoard as of 20110905
+interface Dictionary {
+ readonly attribute unsigned long propertyCount;
+
+ omittable getter float getProperty(DOMString propertyName);
+ omittable setter void setProperty(DOMString propertyName, float propertyValue);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/WebIDL/invalid/idl/stringconstants.idl b/tests/wpt/web-platform-tests/WebIDL/invalid/idl/stringconstants.idl
new file mode 100644
index 00000000000..44fd3ff136e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/invalid/idl/stringconstants.idl
@@ -0,0 +1,3 @@
+interface Util {
+ const DOMString hello = "world";
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/WebIDL/readme.txt b/tests/wpt/web-platform-tests/WebIDL/readme.txt
new file mode 100644
index 00000000000..12ded6acdf5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/readme.txt
@@ -0,0 +1,3 @@
+These are syntax tests for WebIDL parser. A correct parser should fail on the tests in the "invalid" directory, and should be able to collect the data necessary to generate the XML serialization for valid fragments collected in the "valid" directory.
+
+(the said XML serialization is the one produced by widlproc https://github.com/dontcallmedom/widlproc from which these tests have been imported)
diff --git a/tests/wpt/web-platform-tests/WebIDL/testable_assertions.txt b/tests/wpt/web-platform-tests/WebIDL/testable_assertions.txt
new file mode 100644
index 00000000000..c1706f8c39d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/testable_assertions.txt
@@ -0,0 +1,29 @@
+{
+ "travil_test_1": {
+ "title": "The Title of this spec",
+ "specRef": "html > body:nth-child(2) > div:nth-child(1) > h1:nth-child(2)",
+ "notes": "This assertion is linked to the H1 in the beginning of the spec.",
+ "author": "Microsoft",
+ "date": "2012-07-11T23:39:23.634Z",
+ "testURL": "",
+ "testApproved": false
+ },
+ "travil_test_2": {
+ "title": "The Initial publication of WebIDL (at the bottom of the spec)",
+ "specRef": "#changes > dl:nth-child(4) > dt:nth-child(19)",
+ "notes": "17 October 2007 was the FPWD.\nTime to start testing.",
+ "author": "Microsoft",
+ "date": "2012-07-11T23:40:41.624Z",
+ "testURL": "",
+ "testApproved": false
+ },
+ "travil_test_3": {
+ "title": "This assertion should not be found (by design)",
+ "specRef": "#does_not_exist > div",
+ "notes": "This is for testing purposes only (testing the framework)",
+ "author": "Microsoft",
+ "date": "2012-07-11T23:40:41.624Z",
+ "testURL": "",
+ "testApproved": false
+ }
+} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/idl/allowany.widl b/tests/wpt/web-platform-tests/WebIDL/valid/idl/allowany.widl
new file mode 100644
index 00000000000..2343bb96374
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/idl/allowany.widl
@@ -0,0 +1,6 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface B {
+ void g();
+ void g(B b);
+ void g([AllowAny] DOMString s);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/idl/array.widl b/tests/wpt/web-platform-tests/WebIDL/valid/idl/array.widl
new file mode 100644
index 00000000000..22e21fb6564
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/idl/array.widl
@@ -0,0 +1,5 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+[Constructor]
+interface LotteryResults {
+ readonly attribute unsigned short[][] numbers;
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/idl/attributes.widl b/tests/wpt/web-platform-tests/WebIDL/valid/idl/attributes.widl
new file mode 100644
index 00000000000..7e1d691cbe2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/idl/attributes.widl
@@ -0,0 +1,14 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+exception InvalidName {
+ DOMString reason;
+};
+
+exception NoSuchPet { };
+
+interface Person {
+
+ // A simple attribute that can be set to any value the range an unsigned
+ // short can take.
+ attribute unsigned short age;
+
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/idl/callback.widl b/tests/wpt/web-platform-tests/WebIDL/valid/idl/callback.widl
new file mode 100644
index 00000000000..d92f6a18c0a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/idl/callback.widl
@@ -0,0 +1,5 @@
+callback AsyncOperationCallback = void (DOMString status);
+
+callback interface EventHandler {
+ void eventOccurred(DOMString details);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/idl/caller.widl b/tests/wpt/web-platform-tests/WebIDL/valid/idl/caller.widl
new file mode 100644
index 00000000000..92acb1c0176
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/idl/caller.widl
@@ -0,0 +1,5 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface NumberQuadrupler {
+ // This operation simply returns four times the given number x.
+ legacycaller float compute(float x);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/idl/constants.widl b/tests/wpt/web-platform-tests/WebIDL/valid/idl/constants.widl
new file mode 100644
index 00000000000..5e28ae9c116
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/idl/constants.widl
@@ -0,0 +1,18 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface Util {
+ const boolean DEBUG = false;
+ const short negative = -1;
+ const octet LF = 10;
+ const unsigned long BIT_MASK = 0x0000fc00;
+ const float AVOGADRO = 6.022e23;
+ const unrestricted float sobig = Infinity;
+ const unrestricted double minusonedividedbyzero = -Infinity;
+ const short notanumber = NaN;
+};
+
+exception Error {
+ const short ERR_UNKNOWN = 0;
+ const short ERR_OUT_OF_MEMORY = 1;
+
+ short errorCode;
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/idl/constructor.widl b/tests/wpt/web-platform-tests/WebIDL/valid/idl/constructor.widl
new file mode 100644
index 00000000000..f93ec08a6e6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/idl/constructor.widl
@@ -0,0 +1,9 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+[Constructor,
+ Constructor(float radius)]
+interface Circle {
+ attribute float r;
+ attribute float cx;
+ attribute float cy;
+ readonly attribute float circumference;
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/idl/dictionary-inherits.widl b/tests/wpt/web-platform-tests/WebIDL/valid/idl/dictionary-inherits.widl
new file mode 100644
index 00000000000..48f8a0fdceb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/idl/dictionary-inherits.widl
@@ -0,0 +1,9 @@
+dictionary PaintOptions {
+ DOMString? fillPattern = "black";
+ DOMString? strokePattern = null;
+ Point position;
+};
+
+dictionary WetPaintOptions : PaintOptions {
+ float hydrometry;
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/idl/dictionary.widl b/tests/wpt/web-platform-tests/WebIDL/valid/idl/dictionary.widl
new file mode 100644
index 00000000000..f46b7ba7806
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/idl/dictionary.widl
@@ -0,0 +1,11 @@
+// Extracted from Web IDL editors draft May 31 2011
+dictionary PaintOptions {
+ DOMString? fillPattern = "black";
+ DOMString? strokePattern = null;
+ Point position;
+};
+
+partial dictionary A {
+ long h;
+ long d;
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/idl/documentation-dos.widl b/tests/wpt/web-platform-tests/WebIDL/valid/idl/documentation-dos.widl
new file mode 100644
index 00000000000..fb801101f14
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/idl/documentation-dos.widl
@@ -0,0 +1,33 @@
+/**
+* \brief Testing documentation features
+*
+* This is a
+* single paragraph
+*
+* <p>This is valid.</p>
+* <p>This is <em>valid</em>.</p>
+* <p>This is <b>valid</b>.</p>
+* <p>This is <a href=''>valid</a>.</p>
+* <ul>
+* <li>This</li>
+* <li>is</li>
+* <li>valid</li>
+* </ul>
+* <dl>
+* <dt>This</dt>
+* <dd>valid</dd>
+* </dl>
+* <table>
+* <tr>
+* <td>this</td>
+* <td>is</td>
+* </tr>
+* <tr>
+* <td>valid</td>
+* </tr>
+* </table>
+* <p>This is <br> valid.</p>
+* <p>This is <br /> valid.</p>
+* <p>This is <br/> valid.</p>
+*/
+interface Documentation {}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/idl/documentation.widl b/tests/wpt/web-platform-tests/WebIDL/valid/idl/documentation.widl
new file mode 100644
index 00000000000..003e9226f67
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/idl/documentation.widl
@@ -0,0 +1,34 @@
+/**
+* \brief Testing documentation features
+*
+* This is a
+* single paragraph
+*
+* <p>This is valid.</p>
+* <p>This is <em>valid</em>.</p>
+* <p>This is <b>valid</b>.</p>
+* <p>This is <a href=''>valid</a>.</p>
+* <ul>
+* <li>This</li>
+* <li>is</li>
+* <li>valid</li>
+* </ul>
+* <dl>
+* <dt>This</dt>
+* <dd>valid</dd>
+* </dl>
+* <table>
+* <tr>
+* <td>this</td>
+* <td>is</td>
+* </tr>
+* <tr>
+* <td>valid</td>
+* </tr>
+* </table>
+* <p>This is <br> valid.</p>
+* <p>This is <br /> valid.</p>
+* <p>This is <br/> valid.</p>
+* <p><img src="foo.png" alt="Valid"/></p>
+*/
+interface Documentation {}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/idl/enum.widl b/tests/wpt/web-platform-tests/WebIDL/valid/idl/enum.widl
new file mode 100644
index 00000000000..851fca2e6f6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/idl/enum.widl
@@ -0,0 +1,8 @@
+enum MealType { "rice", "noodles", "other" };
+
+interface Meal {
+ attribute MealType type;
+ attribute float size; // in grams
+
+ void initialize(MealType type, float size);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/idl/equivalent-decl.widl b/tests/wpt/web-platform-tests/WebIDL/valid/idl/equivalent-decl.widl
new file mode 100644
index 00000000000..6b3e0eda284
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/idl/equivalent-decl.widl
@@ -0,0 +1,18 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface Dictionary {
+ readonly attribute unsigned long propertyCount;
+
+ getter float getProperty(DOMString propertyName);
+ setter void setProperty(DOMString propertyName, float propertyValue);
+};
+
+
+interface Dictionary {
+ readonly attribute unsigned long propertyCount;
+
+ float getProperty(DOMString propertyName);
+ void setProperty(DOMString propertyName, float propertyValue);
+
+ getter float (DOMString propertyName);
+ setter void (DOMString propertyName, float propertyValue);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/idl/exception-inheritance.widl b/tests/wpt/web-platform-tests/WebIDL/valid/idl/exception-inheritance.widl
new file mode 100644
index 00000000000..258fdeba6f4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/idl/exception-inheritance.widl
@@ -0,0 +1,7 @@
+// from http://lists.w3.org/Archives/Public/public-script-coord/2010OctDec/0112.html
+ exception DOMException {
+ unsigned short code;
+ };
+
+ exception HierarchyRequestError : DOMException { };
+ exception NoModificationAllowedError : DOMException { }; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/idl/exception.widl b/tests/wpt/web-platform-tests/WebIDL/valid/idl/exception.widl
new file mode 100644
index 00000000000..f4b6ae29e10
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/idl/exception.widl
@@ -0,0 +1,8 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface Dahut {
+ attribute DOMString type;
+};
+
+exception SomeException {
+};
+
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/idl/getter-setter.widl b/tests/wpt/web-platform-tests/WebIDL/valid/idl/getter-setter.widl
new file mode 100644
index 00000000000..bdf87e1c7c7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/idl/getter-setter.widl
@@ -0,0 +1,7 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface Dictionary {
+ readonly attribute unsigned long propertyCount;
+
+ getter float (DOMString propertyName);
+ setter void (DOMString propertyName, float propertyValue);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/idl/identifier-qualified-names.widl b/tests/wpt/web-platform-tests/WebIDL/valid/idl/identifier-qualified-names.widl
new file mode 100644
index 00000000000..33893d4c644
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/idl/identifier-qualified-names.widl
@@ -0,0 +1,44 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+ // Typedef identifier: "number"
+ // Qualified name: "::framework::number"
+ typedef float number;
+
+ // Exception identifier: "FrameworkException"
+ // Qualified name: "::framework::FrameworkException"
+ exception FrameworkException {
+
+ // Constant identifier: "ERR_NOT_FOUND"
+ // Qualified name: "::framework::FrameworkException::ERR_NOT_FOUND"
+ const long ERR_NOT_FOUND = 1;
+
+ // Exception field identifier: "code"
+ long code;
+ };
+
+ // Interface identifier: "System"
+ // Qualified name: "::framework::System"
+ interface System {
+
+ // Operation identifier: "createObject"
+ // Operation argument identifier: "interface"
+ object createObject(DOMString _interface);
+
+ // Operation has no identifier; it declares a getter.
+ getter DOMString (DOMString keyName);
+ };
+
+
+ // Interface identifier: "TextField"
+ // Qualified name: "::framework::gui::TextField"
+ interface TextField {
+
+ // Attribute identifier: "const"
+ attribute boolean _const;
+
+ // Attribute identifier: "value"
+ attribute DOMString? _value;
+ };
+
+interface Foo {
+ void op(object interface);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/idl/implements.widl b/tests/wpt/web-platform-tests/WebIDL/valid/idl/implements.widl
new file mode 100644
index 00000000000..7a310926f1c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/idl/implements.widl
@@ -0,0 +1,14 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+ interface Node {
+ readonly attribute unsigned short nodeType;
+ // ...
+ };
+
+ interface EventTarget {
+ void addEventListener(DOMString type,
+ EventListener listener,
+ boolean useCapture);
+ // ...
+ };
+
+ Node implements EventTarget;
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/idl/indexed-properties.widl b/tests/wpt/web-platform-tests/WebIDL/valid/idl/indexed-properties.widl
new file mode 100644
index 00000000000..acf0ed3bf84
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/idl/indexed-properties.widl
@@ -0,0 +1,12 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface OrderedMap {
+ readonly attribute unsigned long size;
+
+ getter any getByIndex(unsigned long index);
+ setter void setByIndex(unsigned long index, any value);
+ deleter void removeByIndex(unsigned long index);
+
+ getter any get(DOMString name);
+ setter creator void set(DOMString name, any value);
+ deleter void remove(DOMString name);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/idl/inherits-getter.widl b/tests/wpt/web-platform-tests/WebIDL/valid/idl/inherits-getter.widl
new file mode 100644
index 00000000000..558e8116494
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/idl/inherits-getter.widl
@@ -0,0 +1,16 @@
+interface Animal {
+
+ // A simple attribute that can be set to any string value.
+ readonly attribute DOMString name;
+};
+
+interface Person : Animal {
+
+ // An attribute whose value cannot be assigned to.
+ readonly attribute unsigned short age;
+
+ // An attribute that can raise an exception if it is set to an invalid value.
+ // Its getter behavior is inherited from Animal, and need not be specified
+ // the description of Person.
+ inherit attribute DOMString name;
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/idl/interface-inherits.widl b/tests/wpt/web-platform-tests/WebIDL/valid/idl/interface-inherits.widl
new file mode 100644
index 00000000000..7921def7727
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/idl/interface-inherits.widl
@@ -0,0 +1,12 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface Animal {
+ attribute DOMString name;
+};
+
+interface Human : Animal {
+ attribute Dog pet;
+};
+
+interface Dog : Animal {
+ attribute Human owner;
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/idl/iterator.widl b/tests/wpt/web-platform-tests/WebIDL/valid/idl/iterator.widl
new file mode 100644
index 00000000000..3bf1b36dec6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/idl/iterator.widl
@@ -0,0 +1,35 @@
+interface SessionManager {
+ Session getSessionForUser(DOMString username);
+ readonly attribute unsigned long sessionCount;
+
+ Session iterator;
+};
+
+interface Session {
+ readonly attribute DOMString username;
+ // ...
+};
+
+interface SessionManager2 {
+ Session2 getSessionForUser(DOMString username);
+ readonly attribute unsigned long sessionCount;
+
+ Session2 iterator = SessionIterator;
+};
+
+interface Session2 {
+ readonly attribute DOMString username;
+ // ...
+};
+
+interface SessionIterator {
+ readonly attribute unsigned long remainingSessions;
+};
+
+ interface NodeList {
+ Node iterator = NodeIterator;
+ };
+
+ interface NodeIterator {
+ Node iterator object;
+ }; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/idl/namedconstructor.widl b/tests/wpt/web-platform-tests/WebIDL/valid/idl/namedconstructor.widl
new file mode 100644
index 00000000000..c468b78f8e1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/idl/namedconstructor.widl
@@ -0,0 +1,6 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+[NamedConstructor=Audio,
+ NamedConstructor=Audio(DOMString src)]
+interface HTMLAudioElement : HTMLMediaElement {
+ // ...
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/idl/nointerfaceobject.widl b/tests/wpt/web-platform-tests/WebIDL/valid/idl/nointerfaceobject.widl
new file mode 100644
index 00000000000..c17d75ff8fd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/idl/nointerfaceobject.widl
@@ -0,0 +1,5 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+[NoInterfaceObject]
+interface Query {
+ any lookupEntry(unsigned long key);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/idl/nullable.widl b/tests/wpt/web-platform-tests/WebIDL/valid/idl/nullable.widl
new file mode 100644
index 00000000000..ccbf625ff8a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/idl/nullable.widl
@@ -0,0 +1,9 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface MyConstants {
+ const boolean? ARE_WE_THERE_YET = false;
+};
+
+interface Node {
+ readonly attribute DOMString? namespaceURI;
+ // ...
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/idl/nullableobjects.widl b/tests/wpt/web-platform-tests/WebIDL/valid/idl/nullableobjects.widl
new file mode 100644
index 00000000000..83d1d40b2ac
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/idl/nullableobjects.widl
@@ -0,0 +1,13 @@
+// Extracted from WebIDL spec 2011-05-23
+
+interface A {
+ // ...
+};
+interface B {
+ // ...
+};
+interface C {
+ void f(A? x);
+ void f(B? x);
+
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/idl/operation-optional-arg.widl b/tests/wpt/web-platform-tests/WebIDL/valid/idl/operation-optional-arg.widl
new file mode 100644
index 00000000000..379053b45f1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/idl/operation-optional-arg.widl
@@ -0,0 +1,4 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface ColorCreator {
+ object createColor(float v1, float v2, float v3, optional float alpha = 3.5);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/idl/overloading.widl b/tests/wpt/web-platform-tests/WebIDL/valid/idl/overloading.widl
new file mode 100644
index 00000000000..ef1288a8877
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/idl/overloading.widl
@@ -0,0 +1,20 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface A {
+ // ...
+};
+
+interface B {
+ // ...
+};
+
+interface C {
+ void f(A x);
+ void f(B x);
+};
+
+interface A {
+ /* f1 */ void f(DOMString a);
+ /* f2 */ void f([AllowAny] DOMString a, DOMString b, float... c);
+ /* f3 */ void f();
+ /* f4 */ void f(long a, DOMString b, optional DOMString c, float... d);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/idl/overridebuiltins.widl b/tests/wpt/web-platform-tests/WebIDL/valid/idl/overridebuiltins.widl
new file mode 100644
index 00000000000..79211c29e84
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/idl/overridebuiltins.widl
@@ -0,0 +1,6 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+[OverrideBuiltins]
+interface StringMap2 {
+ readonly attribute unsigned long length;
+ getter DOMString lookup(DOMString key);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/idl/partial-interface.widl b/tests/wpt/web-platform-tests/WebIDL/valid/idl/partial-interface.widl
new file mode 100644
index 00000000000..90e7e0ea421
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/idl/partial-interface.widl
@@ -0,0 +1,7 @@
+interface Foo {
+ attribute DOMString bar;
+};
+
+partial interface Foo {
+ attribute DOMString quux;
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/idl/primitives.widl b/tests/wpt/web-platform-tests/WebIDL/valid/idl/primitives.widl
new file mode 100644
index 00000000000..92939601a1a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/idl/primitives.widl
@@ -0,0 +1,19 @@
+interface Primitives {
+ attribute boolean truth;
+ attribute byte character;
+ attribute octet value;
+ attribute short number;
+ attribute unsigned short positive;
+ attribute long big;
+ attribute unsigned long bigpositive;
+ attribute long long bigbig;
+ attribute unsigned long long bigbigpositive;
+ attribute float real;
+ attribute double bigreal;
+ attribute unrestricted float realwithinfinity;
+ attribute unrestricted double bigrealwithinfinity;
+ attribute DOMString string;
+ attribute ByteString bytes;
+ attribute Date date;
+ attribute RegExp regexp;
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/idl/prototyperoot.widl b/tests/wpt/web-platform-tests/WebIDL/valid/idl/prototyperoot.widl
new file mode 100644
index 00000000000..30dd5cbca13
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/idl/prototyperoot.widl
@@ -0,0 +1,5 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+[PrototypeRoot]
+interface Node {
+ readonly attribute unsigned short nodeType;
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/idl/putforwards.widl b/tests/wpt/web-platform-tests/WebIDL/valid/idl/putforwards.widl
new file mode 100644
index 00000000000..1e50a4ee394
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/idl/putforwards.widl
@@ -0,0 +1,5 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface Person {
+ [PutForwards=full] readonly attribute Name name;
+ attribute unsigned short age;
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/idl/reg-operations.widl b/tests/wpt/web-platform-tests/WebIDL/valid/idl/reg-operations.widl
new file mode 100644
index 00000000000..13997cb1d12
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/idl/reg-operations.widl
@@ -0,0 +1,17 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface Dimensions {
+ attribute unsigned long width;
+ attribute unsigned long height;
+};
+
+exception NoPointerDevice { };
+
+interface Button {
+
+ // An operation that takes no arguments, returns a boolean
+ boolean isMouseOver();
+
+ // Overloaded operations.
+ void setDimensions(Dimensions size);
+ void setDimensions(unsigned long width, unsigned long height);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/idl/replaceable.widl b/tests/wpt/web-platform-tests/WebIDL/valid/idl/replaceable.widl
new file mode 100644
index 00000000000..c14d0c37689
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/idl/replaceable.widl
@@ -0,0 +1,5 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface Counter {
+ [Replaceable] readonly attribute unsigned long value;
+ void increment();
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/idl/sequence.widl b/tests/wpt/web-platform-tests/WebIDL/valid/idl/sequence.widl
new file mode 100644
index 00000000000..a1aa931f5f0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/idl/sequence.widl
@@ -0,0 +1,7 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+// edited to remove sequence as attributes, now invalid
+interface Canvas {
+ void drawPolygon(sequence<float> coordinates);
+ sequence<float> getInflectionPoints();
+ // ...
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/idl/serializer.widl b/tests/wpt/web-platform-tests/WebIDL/valid/idl/serializer.widl
new file mode 100644
index 00000000000..6f6ccd0e8d5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/idl/serializer.widl
@@ -0,0 +1,64 @@
+interface Transaction {
+ readonly attribute Account from;
+ readonly attribute Account to;
+ readonly attribute float amount;
+ readonly attribute DOMString description;
+ readonly attribute unsigned long number;
+
+ serializer;
+};
+
+interface Account {
+ attribute DOMString name;
+ attribute unsigned long number;
+ serializer DOMString serialize();
+};
+
+interface Transaction2 {
+ readonly attribute Account2 from;
+ readonly attribute Account2 to;
+ readonly attribute float amount;
+ readonly attribute DOMString description;
+ readonly attribute unsigned long number;
+
+ serializer = { from, to, amount, description };
+};
+
+interface Account2 {
+ attribute DOMString name;
+ attribute unsigned long number;
+ serializer = number;
+};
+
+interface Account3 {
+ attribute DOMString name;
+ attribute unsigned long number;
+
+ serializer = { attribute };
+};
+
+interface Account4 {
+ getter object getItem(unsigned long index);
+ serializer = { getter };
+};
+
+interface Account5 : Account {
+ attribute DOMString secondname;
+ serializer = { inherit, secondname };
+};
+
+interface Account6 : Account {
+ attribute DOMString secondname;
+ serializer = { inherit, attribute };
+};
+
+interface Account7 {
+ attribute DOMString name;
+ attribute unsigned long number;
+ serializer = [ name, number ];
+};
+
+interface Account8 {
+ getter object getItem(unsigned long index);
+ serializer = [ getter ];
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/idl/static.widl b/tests/wpt/web-platform-tests/WebIDL/valid/idl/static.widl
new file mode 100644
index 00000000000..5b2cd36590f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/idl/static.widl
@@ -0,0 +1,11 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface Point { /* ... */ };
+
+interface Circle {
+ attribute float cx;
+ attribute float cy;
+ attribute float radius;
+
+ static readonly attribute long triangulationCount;
+ static Point triangulate(Circle c1, Circle c2, Circle c3);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/idl/stringifier-attribute.widl b/tests/wpt/web-platform-tests/WebIDL/valid/idl/stringifier-attribute.widl
new file mode 100644
index 00000000000..c964ecb93e6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/idl/stringifier-attribute.widl
@@ -0,0 +1,6 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+[Constructor]
+interface Student {
+ attribute unsigned long id;
+ stringifier attribute DOMString name;
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/idl/stringifier-custom.widl b/tests/wpt/web-platform-tests/WebIDL/valid/idl/stringifier-custom.widl
new file mode 100644
index 00000000000..b5d7c87e7f4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/idl/stringifier-custom.widl
@@ -0,0 +1,9 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+[Constructor]
+interface Student {
+ attribute unsigned long id;
+ attribute DOMString? familyName;
+ attribute DOMString givenName;
+
+ stringifier DOMString ();
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/idl/stringifier.widl b/tests/wpt/web-platform-tests/WebIDL/valid/idl/stringifier.widl
new file mode 100644
index 00000000000..4eb483d9b53
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/idl/stringifier.widl
@@ -0,0 +1,8 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface A {
+ stringifier DOMString ();
+};
+
+interface A {
+ stringifier;
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/idl/treatasnull.widl b/tests/wpt/web-platform-tests/WebIDL/valid/idl/treatasnull.widl
new file mode 100644
index 00000000000..d3c55b008c0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/idl/treatasnull.widl
@@ -0,0 +1,7 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface Dog {
+ attribute DOMString name;
+ attribute DOMString owner;
+
+ boolean isMemberOfBreed([TreatNullAs=EmptyString] DOMString breedName);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/idl/treatasundefined.widl b/tests/wpt/web-platform-tests/WebIDL/valid/idl/treatasundefined.widl
new file mode 100644
index 00000000000..e30050f8413
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/idl/treatasundefined.widl
@@ -0,0 +1,7 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface Cat {
+ attribute DOMString name;
+ attribute DOMString owner;
+
+ boolean isMemberOfBreed([TreatUndefinedAs=EmptyString] DOMString breedName);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/idl/typedef.widl b/tests/wpt/web-platform-tests/WebIDL/valid/idl/typedef.widl
new file mode 100644
index 00000000000..b4c17d8d36a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/idl/typedef.widl
@@ -0,0 +1,22 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+ interface Point {
+ attribute float x;
+ attribute float y;
+ };
+
+ typedef sequence<Point> PointSequence;
+
+ interface Rect {
+ attribute Point topleft;
+ attribute Point bottomright;
+ };
+
+ interface Widget {
+
+ readonly attribute Rect bounds;
+
+ boolean pointWithinBounds(Point p);
+ boolean allPointsWithinBounds(PointSequence ps);
+ };
+
+ typedef [Clamp] octet value; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/idl/typesuffixes.widl b/tests/wpt/web-platform-tests/WebIDL/valid/idl/typesuffixes.widl
new file mode 100644
index 00000000000..95e31c16902
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/idl/typesuffixes.widl
@@ -0,0 +1,3 @@
+interface Suffixes {
+ void test(sequence<DOMString[]?>? foo);
+};
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/idl/uniontype.widl b/tests/wpt/web-platform-tests/WebIDL/valid/idl/uniontype.widl
new file mode 100644
index 00000000000..4d99f019630
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/idl/uniontype.widl
@@ -0,0 +1,3 @@
+interface Union {
+ attribute (float or (Date or Event) or (Node or DOMString)?) test;
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/idl/variadic-operations.widl b/tests/wpt/web-platform-tests/WebIDL/valid/idl/variadic-operations.widl
new file mode 100644
index 00000000000..51fae4cc1ea
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/idl/variadic-operations.widl
@@ -0,0 +1,7 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface IntegerSet {
+ readonly attribute unsigned long cardinality;
+
+ void union(long... ints);
+ void intersection(long... ints);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/xml/allowany.widlprocxml b/tests/wpt/web-platform-tests/WebIDL/valid/xml/allowany.widlprocxml
new file mode 100644
index 00000000000..7da508bcb5c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/xml/allowany.widlprocxml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface B {
+ void g();
+ void g(<ref>B</ref> b);
+ void g([AllowAny] DOMString s);
+};</webidl>
+ <Interface name="B" id="::B">
+ <webidl>interface B {
+ void g();
+ void g(<ref>B</ref> b);
+ void g([AllowAny] DOMString s);
+};</webidl>
+ <Operation name="g" id="::B::g">
+ <webidl> void g();</webidl>
+ <Type type="void"/>
+ <ArgumentList/>
+ </Operation>
+ <Operation name="g" id="::B::g">
+ <webidl> void g(<ref>B</ref> b);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="b">
+ <Type name="B"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation name="g" id="::B::g">
+ <webidl> void g([AllowAny] DOMString s);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="s">
+ <ExtendedAttributeList>
+ <ExtendedAttribute name="AllowAny">
+ <webidl>AllowAny</webidl>
+ </ExtendedAttribute>
+ </ExtendedAttributeList>
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/xml/array.widlprocxml b/tests/wpt/web-platform-tests/WebIDL/valid/xml/array.widlprocxml
new file mode 100644
index 00000000000..3df72ff1608
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/xml/array.widlprocxml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>[Constructor]
+interface LotteryResults {
+ readonly attribute unsigned short[][] numbers;
+};</webidl>
+ <Interface name="LotteryResults" id="::LotteryResults">
+ <webidl>[Constructor]
+interface LotteryResults {
+ readonly attribute unsigned short[][] numbers;
+};</webidl>
+ <ExtendedAttributeList>
+ <ExtendedAttribute name="Constructor">
+ <webidl>Constructor</webidl>
+ </ExtendedAttribute>
+ </ExtendedAttributeList>
+ <Attribute readonly="readonly" name="numbers" id="::LotteryResults::numbers">
+ <webidl> readonly attribute unsigned short[][] numbers;</webidl>
+ <Type type="array">
+ <Type type="array">
+ <Type type="unsigned short"/>
+ </Type>
+ </Type>
+ </Attribute>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/xml/attributes.widlprocxml b/tests/wpt/web-platform-tests/WebIDL/valid/xml/attributes.widlprocxml
new file mode 100644
index 00000000000..89bd8ac9b01
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/xml/attributes.widlprocxml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>exception InvalidName {
+ DOMString reason;
+};
+
+exception NoSuchPet { };
+
+interface Person {
+
+ attribute unsigned short age;
+
+};</webidl>
+ <Exception name="InvalidName" id="::InvalidName">
+ <webidl>exception InvalidName {
+ DOMString reason;
+};</webidl>
+ <ExceptionField name="reason" id="::InvalidName::reason">
+ <webidl> DOMString reason;</webidl>
+ <Type type="DOMString"/>
+ </ExceptionField>
+ </Exception>
+ <Exception name="NoSuchPet" id="::NoSuchPet">
+ <webidl>exception NoSuchPet { };</webidl>
+ </Exception>
+ <Interface name="Person" id="::Person">
+ <webidl>interface Person {
+
+ attribute unsigned short age;
+
+};</webidl>
+ <Attribute name="age" id="::Person::age">
+ <webidl> attribute unsigned short age;</webidl>
+ <Type type="unsigned short"/>
+ </Attribute>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/xml/callback.widlprocxml b/tests/wpt/web-platform-tests/WebIDL/valid/xml/callback.widlprocxml
new file mode 100644
index 00000000000..9eac06ce279
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/xml/callback.widlprocxml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>callback AsyncOperationCallback = void (DOMString status);
+
+callback interface EventHandler {
+ void eventOccurred(DOMString details);
+};</webidl>
+ <Callback name="AsyncOperationCallback" id="::AsyncOperationCallback">
+ <webidl>callback AsyncOperationCallback = void (DOMString status);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="status">
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </Callback>
+ <Interface name="EventHandler" callback="callback" id="::EventHandler">
+ <webidl>callback interface EventHandler {
+ void eventOccurred(DOMString details);
+};</webidl>
+ <Operation name="eventOccurred" id="::EventHandler::eventOccurred">
+ <webidl> void eventOccurred(DOMString details);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="details">
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/xml/caller.widlprocxml b/tests/wpt/web-platform-tests/WebIDL/valid/xml/caller.widlprocxml
new file mode 100644
index 00000000000..9754d4e0268
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/xml/caller.widlprocxml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface NumberQuadrupler {
+ legacycaller float compute(float x);
+};</webidl>
+ <Interface name="NumberQuadrupler" id="::NumberQuadrupler">
+ <webidl>interface NumberQuadrupler {
+ legacycaller float compute(float x);
+};</webidl>
+ <Operation legacycaller="legacycaller" name="compute" id="::NumberQuadrupler::compute">
+ <webidl> legacycaller float compute(float x);</webidl>
+ <Type type="float"/>
+ <ArgumentList>
+ <Argument name="x">
+ <Type type="float"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/xml/constants.widlprocxml b/tests/wpt/web-platform-tests/WebIDL/valid/xml/constants.widlprocxml
new file mode 100644
index 00000000000..51cb4331f75
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/xml/constants.widlprocxml
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Util {
+ const boolean DEBUG = false;
+ const short negative = -1;
+ const octet LF = 10;
+ const unsigned long BIT_MASK = 0x0000fc00;
+ const float AVOGADRO = 6.022e23;
+ const unrestricted float sobig = Infinity;
+ const unrestricted double minusonedividedbyzero = -Infinity;
+ const short notanumber = NaN;
+};
+
+exception Error {
+ const short ERR_UNKNOWN = 0;
+ const short ERR_OUT_OF_MEMORY = 1;
+
+ short errorCode;
+};</webidl>
+ <Interface name="Util" id="::Util">
+ <webidl>interface Util {
+ const boolean DEBUG = false;
+ const short negative = -1;
+ const octet LF = 10;
+ const unsigned long BIT_MASK = 0x0000fc00;
+ const float AVOGADRO = 6.022e23;
+ const unrestricted float sobig = Infinity;
+ const unrestricted double minusonedividedbyzero = -Infinity;
+ const short notanumber = NaN;
+};</webidl>
+ <Const name="DEBUG" value="false" id="::Util::DEBUG">
+ <webidl> const boolean DEBUG = false;</webidl>
+ <Type type="boolean"/>
+ </Const>
+ <Const name="negative" value="-1" id="::Util::negative">
+ <webidl> const short negative = -1;</webidl>
+ <Type type="short"/>
+ </Const>
+ <Const name="LF" value="10" id="::Util::LF">
+ <webidl> const octet LF = 10;</webidl>
+ <Type type="octet"/>
+ </Const>
+ <Const name="BIT_MASK" value="0x0000fc00" id="::Util::BIT_MASK">
+ <webidl> const unsigned long BIT_MASK = 0x0000fc00;</webidl>
+ <Type type="unsigned long"/>
+ </Const>
+ <Const name="AVOGADRO" value="6.022e23" id="::Util::AVOGADRO">
+ <webidl> const float AVOGADRO = 6.022e23;</webidl>
+ <Type type="float"/>
+ </Const>
+ <Const name="sobig" value="Infinity" id="::Util::sobig">
+ <webidl> const unrestricted float sobig = Infinity;</webidl>
+ <Type type="unrestricted float"/>
+ </Const>
+ <Const name="minusonedividedbyzero" value="-Infinity" id="::Util::minusonedividedbyzero">
+ <webidl> const unrestricted double minusonedividedbyzero = -Infinity;</webidl>
+ <Type type="unrestricted double"/>
+ </Const>
+ <Const name="notanumber" value="NaN" id="::Util::notanumber">
+ <webidl> const short notanumber = NaN;</webidl>
+ <Type type="short"/>
+ </Const>
+ </Interface>
+ <Exception name="Error" id="::Error">
+ <webidl>exception Error {
+ const short ERR_UNKNOWN = 0;
+ const short ERR_OUT_OF_MEMORY = 1;
+
+ short errorCode;
+};</webidl>
+ <Const name="ERR_UNKNOWN" value="0" id="::Error::ERR_UNKNOWN">
+ <webidl> const short ERR_UNKNOWN = 0;</webidl>
+ <Type type="short"/>
+ </Const>
+ <Const name="ERR_OUT_OF_MEMORY" value="1" id="::Error::ERR_OUT_OF_MEMORY">
+ <webidl> const short ERR_OUT_OF_MEMORY = 1;</webidl>
+ <Type type="short"/>
+ </Const>
+ <ExceptionField name="errorCode" id="::Error::errorCode">
+ <webidl> short errorCode;</webidl>
+ <Type type="short"/>
+ </ExceptionField>
+ </Exception>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/xml/constructor.widlprocxml b/tests/wpt/web-platform-tests/WebIDL/valid/xml/constructor.widlprocxml
new file mode 100644
index 00000000000..8e78fbab365
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/xml/constructor.widlprocxml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>[Constructor,
+ Constructor(float radius)]
+interface Circle {
+ attribute float r;
+ attribute float cx;
+ attribute float cy;
+ readonly attribute float circumference;
+};</webidl>
+ <Interface name="Circle" id="::Circle">
+ <webidl>[Constructor,
+ Constructor(float radius)]
+interface Circle {
+ attribute float r;
+ attribute float cx;
+ attribute float cy;
+ readonly attribute float circumference;
+};</webidl>
+ <ExtendedAttributeList>
+ <ExtendedAttribute name="Constructor">
+ <webidl>Constructor</webidl>
+ </ExtendedAttribute>
+ <ExtendedAttribute name="Constructor">
+ <webidl> Constructor(float radius)</webidl>
+ <ArgumentList>
+ <Argument name="radius">
+ <Type type="float"/>
+ </Argument>
+ </ArgumentList>
+ </ExtendedAttribute>
+ </ExtendedAttributeList>
+ <Attribute name="r" id="::Circle::r">
+ <webidl> attribute float r;</webidl>
+ <Type type="float"/>
+ </Attribute>
+ <Attribute name="cx" id="::Circle::cx">
+ <webidl> attribute float cx;</webidl>
+ <Type type="float"/>
+ </Attribute>
+ <Attribute name="cy" id="::Circle::cy">
+ <webidl> attribute float cy;</webidl>
+ <Type type="float"/>
+ </Attribute>
+ <Attribute readonly="readonly" name="circumference" id="::Circle::circumference">
+ <webidl> readonly attribute float circumference;</webidl>
+ <Type type="float"/>
+ </Attribute>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/xml/dictionary-inherits.widlprocxml b/tests/wpt/web-platform-tests/WebIDL/valid/xml/dictionary-inherits.widlprocxml
new file mode 100644
index 00000000000..269a83cd849
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/xml/dictionary-inherits.widlprocxml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>dictionary PaintOptions {
+ DOMString? fillPattern = &quot;black&quot;;
+ DOMString? strokePattern = null;
+ <ref>Point</ref> position;
+};
+
+dictionary WetPaintOptions : <ref>PaintOptions</ref> {
+ float hydrometry;
+};</webidl>
+ <Dictionary name="PaintOptions" id="::PaintOptions">
+ <webidl>dictionary PaintOptions {
+ DOMString? fillPattern = &quot;black&quot;;
+ DOMString? strokePattern = null;
+ <ref>Point</ref> position;
+};</webidl>
+ <DictionaryMember name="fillPattern" stringvalue="black" id="::PaintOptions::fillPattern">
+ <webidl> DOMString? fillPattern = &quot;black&quot;;</webidl>
+ <Type type="DOMString" nullable="nullable"/>
+ </DictionaryMember>
+ <DictionaryMember name="strokePattern" value="null" id="::PaintOptions::strokePattern">
+ <webidl> DOMString? strokePattern = null;</webidl>
+ <Type type="DOMString" nullable="nullable"/>
+ </DictionaryMember>
+ <DictionaryMember name="position" id="::PaintOptions::position">
+ <webidl> <ref>Point</ref> position;</webidl>
+ <Type name="Point"/>
+ </DictionaryMember>
+ </Dictionary>
+ <Dictionary name="WetPaintOptions" id="::WetPaintOptions">
+ <webidl>dictionary WetPaintOptions : <ref>PaintOptions</ref> {
+ float hydrometry;
+};</webidl>
+ <DictionaryInheritance>
+ <Name name="PaintOptions"/>
+ </DictionaryInheritance>
+ <DictionaryMember name="hydrometry" id="::WetPaintOptions::hydrometry">
+ <webidl> float hydrometry;</webidl>
+ <Type type="float"/>
+ </DictionaryMember>
+ </Dictionary>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/xml/dictionary.widlprocxml b/tests/wpt/web-platform-tests/WebIDL/valid/xml/dictionary.widlprocxml
new file mode 100644
index 00000000000..978ccb4e271
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/xml/dictionary.widlprocxml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>dictionary PaintOptions {
+ DOMString? fillPattern = &quot;black&quot;;
+ DOMString? strokePattern = null;
+ <ref>Point</ref> position;
+};
+
+partial dictionary A {
+ long h;
+ long d;
+};</webidl>
+ <Dictionary name="PaintOptions" id="::PaintOptions">
+ <webidl>dictionary PaintOptions {
+ DOMString? fillPattern = &quot;black&quot;;
+ DOMString? strokePattern = null;
+ <ref>Point</ref> position;
+};</webidl>
+ <DictionaryMember name="fillPattern" stringvalue="black" id="::PaintOptions::fillPattern">
+ <webidl> DOMString? fillPattern = &quot;black&quot;;</webidl>
+ <Type type="DOMString" nullable="nullable"/>
+ </DictionaryMember>
+ <DictionaryMember name="strokePattern" value="null" id="::PaintOptions::strokePattern">
+ <webidl> DOMString? strokePattern = null;</webidl>
+ <Type type="DOMString" nullable="nullable"/>
+ </DictionaryMember>
+ <DictionaryMember name="position" id="::PaintOptions::position">
+ <webidl> <ref>Point</ref> position;</webidl>
+ <Type name="Point"/>
+ </DictionaryMember>
+ </Dictionary>
+ <Dictionary name="A" partial="partial" id="::A">
+ <webidl>partial dictionary A {
+ long h;
+ long d;
+};</webidl>
+ <DictionaryMember name="h" id="::A::h">
+ <webidl> long h;</webidl>
+ <Type type="long"/>
+ </DictionaryMember>
+ <DictionaryMember name="d" id="::A::d">
+ <webidl> long d;</webidl>
+ <Type type="long"/>
+ </DictionaryMember>
+ </Dictionary>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/xml/documentation-dos.widlprocxml b/tests/wpt/web-platform-tests/WebIDL/valid/xml/documentation-dos.widlprocxml
new file mode 100644
index 00000000000..1611f0e576a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/xml/documentation-dos.widlprocxml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Documentation {};</webidl>
+ <Interface name="Documentation" id="::Documentation">
+ <webidl>interface Documentation {};</webidl>
+ <descriptive>
+ <brief>
+ Testing documentation features
+ </brief>
+ <description>
+ <p>
+This is a
+single paragraph
+ </p>
+ <p>
+This is valid. </p>
+ <p>
+This is <em>valid</em>. </p>
+ <p>
+This is <b>valid</b>. </p>
+ <p>
+This is <a href=''>valid</a>. </p>
+ <ul>
+ <li>
+This </li>
+ <li>
+is </li>
+ <li>
+valid </li>
+ </ul>
+ <dl>
+ <dt>
+This </dt>
+ <dd>
+valid </dd>
+ </dl>
+ <table>
+ <tr>
+ <td>
+this </td>
+ <td>
+is </td>
+ </tr>
+ <tr>
+ <td>
+valid </td>
+ </tr>
+ </table>
+ <p>
+This is <br/> valid. </p>
+ <p>
+This is <br /> valid. </p>
+ <p>
+This is <br/> valid. </p>
+ </description>
+ </descriptive>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/xml/documentation.widlprocxml b/tests/wpt/web-platform-tests/WebIDL/valid/xml/documentation.widlprocxml
new file mode 100644
index 00000000000..afe4527c221
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/xml/documentation.widlprocxml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Documentation {};</webidl>
+ <Interface name="Documentation" id="::Documentation">
+ <webidl>interface Documentation {};</webidl>
+ <descriptive>
+ <brief>
+ Testing documentation features
+ </brief>
+ <description>
+ <p>
+This is a
+single paragraph
+ </p>
+ <p>
+This is valid. </p>
+ <p>
+This is <em>valid</em>. </p>
+ <p>
+This is <b>valid</b>. </p>
+ <p>
+This is <a href=''>valid</a>. </p>
+ <ul>
+ <li>
+This </li>
+ <li>
+is </li>
+ <li>
+valid </li>
+ </ul>
+ <dl>
+ <dt>
+This </dt>
+ <dd>
+valid </dd>
+ </dl>
+ <table>
+ <tr>
+ <td>
+this </td>
+ <td>
+is </td>
+ </tr>
+ <tr>
+ <td>
+valid </td>
+ </tr>
+ </table>
+ <p>
+This is <br/> valid. </p>
+ <p>
+This is <br /> valid. </p>
+ <p>
+This is <br/> valid. </p>
+ <p>
+<img src="foo.png" alt="Valid"/> </p>
+ </description>
+ </descriptive>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/xml/enum.widlprocxml b/tests/wpt/web-platform-tests/WebIDL/valid/xml/enum.widlprocxml
new file mode 100644
index 00000000000..e1e8258fbd0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/xml/enum.widlprocxml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>enum MealType { &quot;rice&quot;, &quot;noodles&quot;, &quot;other&quot; };
+
+interface Meal {
+ attribute <ref>MealType</ref> type;
+ attribute float size;
+
+ void initialize(<ref>MealType</ref> type, float size);
+};</webidl>
+ <Enum name="MealType" id="::MealType">
+ <webidl>enum MealType { &quot;rice&quot;, &quot;noodles&quot;, &quot;other&quot; };</webidl>
+ <EnumValue stringvalue="rice">
+ <webidl> &quot;rice</webidl>
+ </EnumValue>
+ <EnumValue stringvalue="noodles">
+ <webidl> &quot;noodles</webidl>
+ </EnumValue>
+ <EnumValue stringvalue="other">
+ <webidl> &quot;other</webidl>
+ </EnumValue>
+ </Enum>
+ <Interface name="Meal" id="::Meal">
+ <webidl>interface Meal {
+ attribute <ref>MealType</ref> type;
+ attribute float size;
+
+ void initialize(<ref>MealType</ref> type, float size);
+};</webidl>
+ <Attribute name="type" id="::Meal::type">
+ <webidl> attribute <ref>MealType</ref> type;</webidl>
+ <Type name="MealType"/>
+ </Attribute>
+ <Attribute name="size" id="::Meal::size">
+ <webidl> attribute float size;</webidl>
+ <Type type="float"/>
+ </Attribute>
+ <Operation name="initialize" id="::Meal::initialize">
+ <webidl> void initialize(<ref>MealType</ref> type, float size);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="type">
+ <Type name="MealType"/>
+ </Argument>
+ <Argument name="size">
+ <Type type="float"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/xml/equivalent-decl.widlprocxml b/tests/wpt/web-platform-tests/WebIDL/valid/xml/equivalent-decl.widlprocxml
new file mode 100644
index 00000000000..c322d0a5e22
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/xml/equivalent-decl.widlprocxml
@@ -0,0 +1,111 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Dictionary {
+ readonly attribute unsigned long propertyCount;
+
+ getter float getProperty(DOMString propertyName);
+ setter void setProperty(DOMString propertyName, float propertyValue);
+};
+
+
+interface Dictionary {
+ readonly attribute unsigned long propertyCount;
+
+ float getProperty(DOMString propertyName);
+ void setProperty(DOMString propertyName, float propertyValue);
+
+ getter float (DOMString propertyName);
+ setter void (DOMString propertyName, float propertyValue);
+};</webidl>
+ <Interface name="Dictionary" id="::Dictionary">
+ <webidl>interface Dictionary {
+ readonly attribute unsigned long propertyCount;
+
+ getter float getProperty(DOMString propertyName);
+ setter void setProperty(DOMString propertyName, float propertyValue);
+};</webidl>
+ <Attribute readonly="readonly" name="propertyCount" id="::Dictionary::propertyCount">
+ <webidl> readonly attribute unsigned long propertyCount;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Operation getter="getter" name="getProperty" id="::Dictionary::getProperty">
+ <webidl> getter float getProperty(DOMString propertyName);</webidl>
+ <Type type="float"/>
+ <ArgumentList>
+ <Argument name="propertyName">
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation setter="setter" name="setProperty" id="::Dictionary::setProperty">
+ <webidl> setter void setProperty(DOMString propertyName, float propertyValue);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="propertyName">
+ <Type type="DOMString"/>
+ </Argument>
+ <Argument name="propertyValue">
+ <Type type="float"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+ <Interface name="Dictionary" id="::Dictionary">
+ <webidl>interface Dictionary {
+ readonly attribute unsigned long propertyCount;
+
+ float getProperty(DOMString propertyName);
+ void setProperty(DOMString propertyName, float propertyValue);
+
+ getter float (DOMString propertyName);
+ setter void (DOMString propertyName, float propertyValue);
+};</webidl>
+ <Attribute readonly="readonly" name="propertyCount" id="::Dictionary::propertyCount">
+ <webidl> readonly attribute unsigned long propertyCount;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Operation name="getProperty" id="::Dictionary::getProperty">
+ <webidl> float getProperty(DOMString propertyName);</webidl>
+ <Type type="float"/>
+ <ArgumentList>
+ <Argument name="propertyName">
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation name="setProperty" id="::Dictionary::setProperty">
+ <webidl> void setProperty(DOMString propertyName, float propertyValue);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="propertyName">
+ <Type type="DOMString"/>
+ </Argument>
+ <Argument name="propertyValue">
+ <Type type="float"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation getter="getter">
+ <webidl> getter float (DOMString propertyName);</webidl>
+ <Type type="float"/>
+ <ArgumentList>
+ <Argument name="propertyName">
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation setter="setter">
+ <webidl> setter void (DOMString propertyName, float propertyValue);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="propertyName">
+ <Type type="DOMString"/>
+ </Argument>
+ <Argument name="propertyValue">
+ <Type type="float"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/xml/exception-inheritance.widlprocxml b/tests/wpt/web-platform-tests/WebIDL/valid/xml/exception-inheritance.widlprocxml
new file mode 100644
index 00000000000..3a1f868a4b4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/xml/exception-inheritance.widlprocxml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl> exception DOMException {
+ unsigned short code;
+ };
+
+ exception HierarchyRequestError : <ref>DOMException</ref> { };
+ exception NoModificationAllowedError : <ref>DOMException</ref> { };</webidl>
+ <Exception name="DOMException" id="::DOMException">
+ <webidl> exception DOMException {
+ unsigned short code;
+ };</webidl>
+ <ExceptionField name="code" id="::DOMException::code">
+ <webidl> unsigned short code;</webidl>
+ <Type type="unsigned short"/>
+ </ExceptionField>
+ </Exception>
+ <Exception name="HierarchyRequestError" id="::HierarchyRequestError">
+ <webidl> exception HierarchyRequestError : <ref>DOMException</ref> { };</webidl>
+ <ExceptionInheritance>
+ <Name name="DOMException"/>
+ </ExceptionInheritance>
+ </Exception>
+ <Exception name="NoModificationAllowedError" id="::NoModificationAllowedError">
+ <webidl> exception NoModificationAllowedError : <ref>DOMException</ref> { };</webidl>
+ <ExceptionInheritance>
+ <Name name="DOMException"/>
+ </ExceptionInheritance>
+ </Exception>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/xml/exception.widlprocxml b/tests/wpt/web-platform-tests/WebIDL/valid/xml/exception.widlprocxml
new file mode 100644
index 00000000000..ac93320fe16
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/xml/exception.widlprocxml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Dahut {
+ attribute DOMString type;
+};
+
+exception SomeException {
+};</webidl>
+ <Interface name="Dahut" id="::Dahut">
+ <webidl>interface Dahut {
+ attribute DOMString type;
+};</webidl>
+ <Attribute name="type" id="::Dahut::type">
+ <webidl> attribute DOMString type;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ </Interface>
+ <Exception name="SomeException" id="::SomeException">
+ <webidl>exception SomeException {
+};</webidl>
+ </Exception>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/xml/getter-setter.widlprocxml b/tests/wpt/web-platform-tests/WebIDL/valid/xml/getter-setter.widlprocxml
new file mode 100644
index 00000000000..76afc058c68
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/xml/getter-setter.widlprocxml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Dictionary {
+ readonly attribute unsigned long propertyCount;
+
+ getter float (DOMString propertyName);
+ setter void (DOMString propertyName, float propertyValue);
+};</webidl>
+ <Interface name="Dictionary" id="::Dictionary">
+ <webidl>interface Dictionary {
+ readonly attribute unsigned long propertyCount;
+
+ getter float (DOMString propertyName);
+ setter void (DOMString propertyName, float propertyValue);
+};</webidl>
+ <Attribute readonly="readonly" name="propertyCount" id="::Dictionary::propertyCount">
+ <webidl> readonly attribute unsigned long propertyCount;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Operation getter="getter">
+ <webidl> getter float (DOMString propertyName);</webidl>
+ <Type type="float"/>
+ <ArgumentList>
+ <Argument name="propertyName">
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation setter="setter">
+ <webidl> setter void (DOMString propertyName, float propertyValue);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="propertyName">
+ <Type type="DOMString"/>
+ </Argument>
+ <Argument name="propertyValue">
+ <Type type="float"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/xml/identifier-qualified-names.widlprocxml b/tests/wpt/web-platform-tests/WebIDL/valid/xml/identifier-qualified-names.widlprocxml
new file mode 100644
index 00000000000..b6024e5ff68
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/xml/identifier-qualified-names.widlprocxml
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl> typedef float number;
+
+ exception FrameworkException {
+
+ const long ERR_NOT_FOUND = 1;
+
+ long code;
+ };
+
+ interface System {
+
+ object createObject(DOMString _interface);
+
+ getter DOMString (DOMString keyName);
+ };
+
+
+ interface TextField {
+
+ attribute boolean _const;
+
+ attribute DOMString? _value;
+ };
+
+interface Foo {
+ void op(object interface);
+};</webidl>
+ <Typedef name="number" id="::number">
+ <webidl> typedef float number;</webidl>
+ <Type type="float"/>
+ </Typedef>
+ <Exception name="FrameworkException" id="::FrameworkException">
+ <webidl> exception FrameworkException {
+
+ const long ERR_NOT_FOUND = 1;
+
+ long code;
+ };</webidl>
+ <Const name="ERR_NOT_FOUND" value="1" id="::FrameworkException::ERR_NOT_FOUND">
+ <webidl> const long ERR_NOT_FOUND = 1;</webidl>
+ <Type type="long"/>
+ </Const>
+ <ExceptionField name="code" id="::FrameworkException::code">
+ <webidl> long code;</webidl>
+ <Type type="long"/>
+ </ExceptionField>
+ </Exception>
+ <Interface name="System" id="::System">
+ <webidl> interface System {
+
+ object createObject(DOMString _interface);
+
+ getter DOMString (DOMString keyName);
+ };</webidl>
+ <Operation name="createObject" id="::System::createObject">
+ <webidl> object createObject(DOMString _interface);</webidl>
+ <Type type="object"/>
+ <ArgumentList>
+ <Argument name="_interface">
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation getter="getter">
+ <webidl> getter DOMString (DOMString keyName);</webidl>
+ <Type type="DOMString"/>
+ <ArgumentList>
+ <Argument name="keyName">
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+ <Interface name="TextField" id="::TextField">
+ <webidl> interface TextField {
+
+ attribute boolean _const;
+
+ attribute DOMString? _value;
+ };</webidl>
+ <Attribute name="_const" id="::TextField::_const">
+ <webidl> attribute boolean _const;</webidl>
+ <Type type="boolean"/>
+ </Attribute>
+ <Attribute name="_value" id="::TextField::_value">
+ <webidl> attribute DOMString? _value;</webidl>
+ <Type type="DOMString" nullable="nullable"/>
+ </Attribute>
+ </Interface>
+ <Interface name="Foo" id="::Foo">
+ <webidl>interface Foo {
+ void op(object interface);
+};</webidl>
+ <Operation name="op" id="::Foo::op">
+ <webidl> void op(object interface);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="interface">
+ <Type type="object"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/xml/implements.widlprocxml b/tests/wpt/web-platform-tests/WebIDL/valid/xml/implements.widlprocxml
new file mode 100644
index 00000000000..3d1c1ab8478
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/xml/implements.widlprocxml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl> interface Node {
+ readonly attribute unsigned short nodeType;
+ };
+
+ interface EventTarget {
+ void addEventListener(DOMString type,
+ <ref>EventListener</ref> listener,
+ boolean useCapture);
+ };
+
+ <ref>Node</ref> implements <ref>EventTarget</ref>;</webidl>
+ <Interface name="Node" id="::Node">
+ <webidl> interface Node {
+ readonly attribute unsigned short nodeType;
+ };</webidl>
+ <Attribute readonly="readonly" name="nodeType" id="::Node::nodeType">
+ <webidl> readonly attribute unsigned short nodeType;</webidl>
+ <Type type="unsigned short"/>
+ </Attribute>
+ </Interface>
+ <Interface name="EventTarget" id="::EventTarget">
+ <webidl> interface EventTarget {
+ void addEventListener(DOMString type,
+ <ref>EventListener</ref> listener,
+ boolean useCapture);
+ };</webidl>
+ <Operation name="addEventListener" id="::EventTarget::addEventListener">
+ <webidl> void addEventListener(DOMString type,
+ <ref>EventListener</ref> listener,
+ boolean useCapture);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="type">
+ <Type type="DOMString"/>
+ </Argument>
+ <Argument name="listener">
+ <Type name="EventListener"/>
+ </Argument>
+ <Argument name="useCapture">
+ <Type type="boolean"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+ <Implements name1="Node" name2="EventTarget">
+ <webidl> <ref>Node</ref> implements <ref>EventTarget</ref>;</webidl>
+ </Implements>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/xml/indexed-properties.widlprocxml b/tests/wpt/web-platform-tests/WebIDL/valid/xml/indexed-properties.widlprocxml
new file mode 100644
index 00000000000..fb83621b60d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/xml/indexed-properties.widlprocxml
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface OrderedMap {
+ readonly attribute unsigned long size;
+
+ getter any getByIndex(unsigned long index);
+ setter void setByIndex(unsigned long index, any value);
+ deleter void removeByIndex(unsigned long index);
+
+ getter any get(DOMString name);
+ setter creator void set(DOMString name, any value);
+ deleter void remove(DOMString name);
+};</webidl>
+ <Interface name="OrderedMap" id="::OrderedMap">
+ <webidl>interface OrderedMap {
+ readonly attribute unsigned long size;
+
+ getter any getByIndex(unsigned long index);
+ setter void setByIndex(unsigned long index, any value);
+ deleter void removeByIndex(unsigned long index);
+
+ getter any get(DOMString name);
+ setter creator void set(DOMString name, any value);
+ deleter void remove(DOMString name);
+};</webidl>
+ <Attribute readonly="readonly" name="size" id="::OrderedMap::size">
+ <webidl> readonly attribute unsigned long size;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Operation getter="getter" name="getByIndex" id="::OrderedMap::getByIndex">
+ <webidl> getter any getByIndex(unsigned long index);</webidl>
+ <Type type="any"/>
+ <ArgumentList>
+ <Argument name="index">
+ <Type type="unsigned long"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation setter="setter" name="setByIndex" id="::OrderedMap::setByIndex">
+ <webidl> setter void setByIndex(unsigned long index, any value);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="index">
+ <Type type="unsigned long"/>
+ </Argument>
+ <Argument name="value">
+ <Type type="any"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation deleter="deleter" name="removeByIndex" id="::OrderedMap::removeByIndex">
+ <webidl> deleter void removeByIndex(unsigned long index);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="index">
+ <Type type="unsigned long"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation getter="getter" name="get" id="::OrderedMap::get">
+ <webidl> getter any get(DOMString name);</webidl>
+ <Type type="any"/>
+ <ArgumentList>
+ <Argument name="name">
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation setter="setter" creator="creator" name="set" id="::OrderedMap::set">
+ <webidl> setter creator void set(DOMString name, any value);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="name">
+ <Type type="DOMString"/>
+ </Argument>
+ <Argument name="value">
+ <Type type="any"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation deleter="deleter" name="remove" id="::OrderedMap::remove">
+ <webidl> deleter void remove(DOMString name);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="name">
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/xml/inherits-getter.widlprocxml b/tests/wpt/web-platform-tests/WebIDL/valid/xml/inherits-getter.widlprocxml
new file mode 100644
index 00000000000..55e7a317fd9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/xml/inherits-getter.widlprocxml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Animal {
+
+ readonly attribute DOMString name;
+};
+
+interface Person : <ref>Animal</ref> {
+
+ readonly attribute unsigned short age;
+
+ inherit attribute DOMString name;
+};</webidl>
+ <Interface name="Animal" id="::Animal">
+ <webidl>interface Animal {
+
+ readonly attribute DOMString name;
+};</webidl>
+ <Attribute readonly="readonly" name="name" id="::Animal::name">
+ <webidl> readonly attribute DOMString name;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ </Interface>
+ <Interface name="Person" id="::Person">
+ <webidl>interface Person : <ref>Animal</ref> {
+
+ readonly attribute unsigned short age;
+
+ inherit attribute DOMString name;
+};</webidl>
+ <InterfaceInheritance>
+ <Name name="Animal"/>
+ </InterfaceInheritance>
+ <Attribute readonly="readonly" name="age" id="::Person::age">
+ <webidl> readonly attribute unsigned short age;</webidl>
+ <Type type="unsigned short"/>
+ </Attribute>
+ <Attribute inherit="inherit" name="name" id="::Person::name">
+ <webidl> inherit attribute DOMString name;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/xml/interface-inherits.widlprocxml b/tests/wpt/web-platform-tests/WebIDL/valid/xml/interface-inherits.widlprocxml
new file mode 100644
index 00000000000..94f0e29df05
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/xml/interface-inherits.widlprocxml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Animal {
+ attribute DOMString name;
+};
+
+interface Human : <ref>Animal</ref> {
+ attribute <ref>Dog</ref> pet;
+};
+
+interface Dog : <ref>Animal</ref> {
+ attribute <ref>Human</ref> owner;
+};</webidl>
+ <Interface name="Animal" id="::Animal">
+ <webidl>interface Animal {
+ attribute DOMString name;
+};</webidl>
+ <Attribute name="name" id="::Animal::name">
+ <webidl> attribute DOMString name;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ </Interface>
+ <Interface name="Human" id="::Human">
+ <webidl>interface Human : <ref>Animal</ref> {
+ attribute <ref>Dog</ref> pet;
+};</webidl>
+ <InterfaceInheritance>
+ <Name name="Animal"/>
+ </InterfaceInheritance>
+ <Attribute name="pet" id="::Human::pet">
+ <webidl> attribute <ref>Dog</ref> pet;</webidl>
+ <Type name="Dog"/>
+ </Attribute>
+ </Interface>
+ <Interface name="Dog" id="::Dog">
+ <webidl>interface Dog : <ref>Animal</ref> {
+ attribute <ref>Human</ref> owner;
+};</webidl>
+ <InterfaceInheritance>
+ <Name name="Animal"/>
+ </InterfaceInheritance>
+ <Attribute name="owner" id="::Dog::owner">
+ <webidl> attribute <ref>Human</ref> owner;</webidl>
+ <Type name="Human"/>
+ </Attribute>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/xml/iterator.widlprocxml b/tests/wpt/web-platform-tests/WebIDL/valid/xml/iterator.widlprocxml
new file mode 100644
index 00000000000..8ca95fbbd17
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/xml/iterator.widlprocxml
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface SessionManager {
+ <ref>Session</ref> getSessionForUser(DOMString username);
+ readonly attribute unsigned long sessionCount;
+
+ <ref>Session</ref> iterator;
+};
+
+interface Session {
+ readonly attribute DOMString username;
+};
+
+interface SessionManager2 {
+ <ref>Session2</ref> getSessionForUser(DOMString username);
+ readonly attribute unsigned long sessionCount;
+
+ <ref>Session2</ref> iterator = SessionIterator;
+};
+
+interface Session2 {
+ readonly attribute DOMString username;
+};
+
+interface SessionIterator {
+ readonly attribute unsigned long remainingSessions;
+};
+
+ interface NodeList {
+ <ref>Node</ref> iterator = NodeIterator;
+ };
+
+ interface NodeIterator {
+ <ref>Node</ref> iterator object;
+ };</webidl>
+ <Interface name="SessionManager" id="::SessionManager">
+ <webidl>interface SessionManager {
+ <ref>Session</ref> getSessionForUser(DOMString username);
+ readonly attribute unsigned long sessionCount;
+
+ <ref>Session</ref> iterator;
+};</webidl>
+ <Operation name="getSessionForUser" id="::SessionManager::getSessionForUser">
+ <webidl> <ref>Session</ref> getSessionForUser(DOMString username);</webidl>
+ <Type name="Session"/>
+ <ArgumentList>
+ <Argument name="username">
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Attribute readonly="readonly" name="sessionCount" id="::SessionManager::sessionCount">
+ <webidl> readonly attribute unsigned long sessionCount;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Iterator>
+ <webidl> <ref>Session</ref> iterator;</webidl>
+ <Type name="Session"/>
+ </Iterator>
+ </Interface>
+ <Interface name="Session" id="::Session">
+ <webidl>interface Session {
+ readonly attribute DOMString username;
+};</webidl>
+ <Attribute readonly="readonly" name="username" id="::Session::username">
+ <webidl> readonly attribute DOMString username;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ </Interface>
+ <Interface name="SessionManager2" id="::SessionManager2">
+ <webidl>interface SessionManager2 {
+ <ref>Session2</ref> getSessionForUser(DOMString username);
+ readonly attribute unsigned long sessionCount;
+
+ <ref>Session2</ref> iterator = SessionIterator;
+};</webidl>
+ <Operation name="getSessionForUser" id="::SessionManager2::getSessionForUser">
+ <webidl> <ref>Session2</ref> getSessionForUser(DOMString username);</webidl>
+ <Type name="Session2"/>
+ <ArgumentList>
+ <Argument name="username">
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Attribute readonly="readonly" name="sessionCount" id="::SessionManager2::sessionCount">
+ <webidl> readonly attribute unsigned long sessionCount;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Iterator interface="SessionIterator">
+ <webidl> <ref>Session2</ref> iterator = SessionIterator;</webidl>
+ <Type name="Session2"/>
+ </Iterator>
+ </Interface>
+ <Interface name="Session2" id="::Session2">
+ <webidl>interface Session2 {
+ readonly attribute DOMString username;
+};</webidl>
+ <Attribute readonly="readonly" name="username" id="::Session2::username">
+ <webidl> readonly attribute DOMString username;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ </Interface>
+ <Interface name="SessionIterator" id="::SessionIterator">
+ <webidl>interface SessionIterator {
+ readonly attribute unsigned long remainingSessions;
+};</webidl>
+ <Attribute readonly="readonly" name="remainingSessions" id="::SessionIterator::remainingSessions">
+ <webidl> readonly attribute unsigned long remainingSessions;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ </Interface>
+ <Interface name="NodeList" id="::NodeList">
+ <webidl> interface NodeList {
+ <ref>Node</ref> iterator = NodeIterator;
+ };</webidl>
+ <Iterator interface="NodeIterator">
+ <webidl> <ref>Node</ref> iterator = NodeIterator;</webidl>
+ <Type name="Node"/>
+ </Iterator>
+ </Interface>
+ <Interface name="NodeIterator" id="::NodeIterator">
+ <webidl> interface NodeIterator {
+ <ref>Node</ref> iterator object;
+ };</webidl>
+ <IteratorObject>
+ <webidl> <ref>Node</ref> iterator object;</webidl>
+ <Type name="Node"/>
+ </IteratorObject>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/xml/module.widlprocxml b/tests/wpt/web-platform-tests/WebIDL/valid/xml/module.widlprocxml
new file mode 100644
index 00000000000..b575b8705af
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/xml/module.widlprocxml
@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <Module name="gfx" id="::gfx">
+ <webidl>module gfx {
+
+ module geom {
+ interface Shape { };
+ interface Rectangle : <ref>Shape</ref> { };
+ interface Path : <ref>Shape</ref> { };
+ };
+
+ interface GraphicsContext {
+ void fillShape(<ref>geom::Shape</ref> s);
+ void strokeShape(<ref>geom::Shape</ref> s);
+ };
+};</webidl>
+ <Module name="geom" id="::gfx::geom">
+ <webidl> module geom {
+ interface Shape { };
+ interface Rectangle : <ref>Shape</ref> { };
+ interface Path : <ref>Shape</ref> { };
+ };</webidl>
+ <Interface name="Shape" id="::gfx::geom::Shape">
+ <webidl> interface Shape { };</webidl>
+ </Interface>
+ <Interface name="Rectangle" id="::gfx::geom::Rectangle">
+ <webidl> interface Rectangle : <ref>Shape</ref> { };</webidl>
+ <InterfaceInheritance>
+ <Name name="Shape"/>
+ </InterfaceInheritance>
+ </Interface>
+ <Interface name="Path" id="::gfx::geom::Path">
+ <webidl> interface Path : <ref>Shape</ref> { };</webidl>
+ <InterfaceInheritance>
+ <Name name="Shape"/>
+ </InterfaceInheritance>
+ </Interface>
+ </Module>
+ <Interface name="GraphicsContext" id="::gfx::GraphicsContext">
+ <webidl> interface GraphicsContext {
+ void fillShape(<ref>geom::Shape</ref> s);
+ void strokeShape(<ref>geom::Shape</ref> s);
+ };</webidl>
+ <Operation name="fillShape" id="::gfx::GraphicsContext::fillShape">
+ <webidl> void fillShape(<ref>geom::Shape</ref> s);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="s">
+ <Type name="geom::Shape"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation name="strokeShape" id="::gfx::GraphicsContext::strokeShape">
+ <webidl> void strokeShape(<ref>geom::Shape</ref> s);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="s">
+ <Type name="geom::Shape"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+ </Module>
+ <Module name="gui" id="::gui">
+ <webidl>module gui {
+
+ interface Widget { };
+
+ interface Window : <ref>Widget</ref> {
+ <ref>gfx::GraphicsContext</ref> getGraphicsContext();
+ };
+
+ interface Button : <ref>Widget</ref> { };
+};</webidl>
+ <Interface name="Widget" id="::gui::Widget">
+ <webidl> interface Widget { };</webidl>
+ </Interface>
+ <Interface name="Window" id="::gui::Window">
+ <webidl> interface Window : <ref>Widget</ref> {
+ <ref>gfx::GraphicsContext</ref> getGraphicsContext();
+ };</webidl>
+ <InterfaceInheritance>
+ <Name name="Widget"/>
+ </InterfaceInheritance>
+ <Operation name="getGraphicsContext" id="::gui::Window::getGraphicsContext">
+ <webidl> <ref>gfx::GraphicsContext</ref> getGraphicsContext();</webidl>
+ <Type name="gfx::GraphicsContext"/>
+ <ArgumentList/>
+ </Operation>
+ </Interface>
+ <Interface name="Button" id="::gui::Button">
+ <webidl> interface Button : <ref>Widget</ref> { };</webidl>
+ <InterfaceInheritance>
+ <Name name="Widget"/>
+ </InterfaceInheritance>
+ </Interface>
+ </Module>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/xml/namedconstructor.widlprocxml b/tests/wpt/web-platform-tests/WebIDL/valid/xml/namedconstructor.widlprocxml
new file mode 100644
index 00000000000..9f661612879
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/xml/namedconstructor.widlprocxml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>[NamedConstructor=Audio,
+ NamedConstructor=Audio(DOMString src)]
+interface HTMLAudioElement : <ref>HTMLMediaElement</ref> {
+};</webidl>
+ <Interface name="HTMLAudioElement" id="::HTMLAudioElement">
+ <webidl>[NamedConstructor=Audio,
+ NamedConstructor=Audio(DOMString src)]
+interface HTMLAudioElement : <ref>HTMLMediaElement</ref> {
+};</webidl>
+ <ExtendedAttributeList>
+ <ExtendedAttribute name="NamedConstructor" value="Audio">
+ <webidl>NamedConstructor</webidl>
+ </ExtendedAttribute>
+ <ExtendedAttribute name="NamedConstructor" value="Audio">
+ <webidl> NamedConstructor=Audio(DOMString src)</webidl>
+ <ArgumentList>
+ <Argument name="src">
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </ExtendedAttribute>
+ </ExtendedAttributeList>
+ <InterfaceInheritance>
+ <Name name="HTMLMediaElement"/>
+ </InterfaceInheritance>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/xml/namespaceobject.widlprocxml b/tests/wpt/web-platform-tests/WebIDL/valid/xml/namespaceobject.widlprocxml
new file mode 100644
index 00000000000..af0cde93719
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/xml/namespaceobject.widlprocxml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <Module name="acme" id="::acme">
+ <webidl>[NamespaceObject]
+module acme {
+
+ exception DeviceException { };
+
+ module pim {
+
+ [Constructor]
+ interface Contact { };
+
+ [Constructor,
+ NamedConstructor=RecurringEvent(long freq)]
+ interface CalendarEvent { };
+ };
+};</webidl>
+ <ExtendedAttributeList>
+ <ExtendedAttribute name="NamespaceObject"/>
+ </ExtendedAttributeList>
+ <Exception name="DeviceException" id="::acme::DeviceException">
+ <webidl> exception DeviceException { };</webidl>
+ </Exception>
+ <Module name="pim" id="::acme::pim">
+ <webidl> module pim {
+
+ [Constructor]
+ interface Contact { };
+
+ [Constructor,
+ NamedConstructor=RecurringEvent(long freq)]
+ interface CalendarEvent { };
+ };</webidl>
+ <Interface name="Contact" id="::acme::pim::Contact">
+ <webidl> [Constructor]
+ interface Contact { };</webidl>
+ <ExtendedAttributeList>
+ <ExtendedAttribute name="Constructor"/>
+ </ExtendedAttributeList>
+ </Interface>
+ <Interface name="CalendarEvent" id="::acme::pim::CalendarEvent">
+ <webidl> [Constructor,
+ NamedConstructor=RecurringEvent(long freq)]
+ interface CalendarEvent { };</webidl>
+ <ExtendedAttributeList>
+ <ExtendedAttribute name="Constructor"/>
+ <ExtendedAttribute name="NamedConstructor" value="RecurringEvent">
+ <ArgumentList>
+ <Argument name="freq">
+ <Type type="long"/>
+ </Argument>
+ </ArgumentList>
+ </ExtendedAttribute>
+ </ExtendedAttributeList>
+ </Interface>
+ </Module>
+ </Module>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/xml/nointerfaceobject.widlprocxml b/tests/wpt/web-platform-tests/WebIDL/valid/xml/nointerfaceobject.widlprocxml
new file mode 100644
index 00000000000..f64f116b60f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/xml/nointerfaceobject.widlprocxml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>[NoInterfaceObject]
+interface Query {
+ any lookupEntry(unsigned long key);
+};</webidl>
+ <Interface name="Query" id="::Query">
+ <webidl>[NoInterfaceObject]
+interface Query {
+ any lookupEntry(unsigned long key);
+};</webidl>
+ <ExtendedAttributeList>
+ <ExtendedAttribute name="NoInterfaceObject">
+ <webidl>NoInterfaceObject</webidl>
+ </ExtendedAttribute>
+ </ExtendedAttributeList>
+ <Operation name="lookupEntry" id="::Query::lookupEntry">
+ <webidl> any lookupEntry(unsigned long key);</webidl>
+ <Type type="any"/>
+ <ArgumentList>
+ <Argument name="key">
+ <Type type="unsigned long"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/xml/nullable.widlprocxml b/tests/wpt/web-platform-tests/WebIDL/valid/xml/nullable.widlprocxml
new file mode 100644
index 00000000000..8739e443262
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/xml/nullable.widlprocxml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface MyConstants {
+ const boolean? ARE_WE_THERE_YET = false;
+};
+
+interface Node {
+ readonly attribute DOMString? namespaceURI;
+};</webidl>
+ <Interface name="MyConstants" id="::MyConstants">
+ <webidl>interface MyConstants {
+ const boolean? ARE_WE_THERE_YET = false;
+};</webidl>
+ <Const name="ARE_WE_THERE_YET" value="false" id="::MyConstants::ARE_WE_THERE_YET">
+ <webidl> const boolean? ARE_WE_THERE_YET = false;</webidl>
+ <Type type="boolean" nullable="nullable"/>
+ </Const>
+ </Interface>
+ <Interface name="Node" id="::Node">
+ <webidl>interface Node {
+ readonly attribute DOMString? namespaceURI;
+};</webidl>
+ <Attribute readonly="readonly" name="namespaceURI" id="::Node::namespaceURI">
+ <webidl> readonly attribute DOMString? namespaceURI;</webidl>
+ <Type type="DOMString" nullable="nullable"/>
+ </Attribute>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/xml/nullableobjects.widlprocxml b/tests/wpt/web-platform-tests/WebIDL/valid/xml/nullableobjects.widlprocxml
new file mode 100644
index 00000000000..22d9fdd25d6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/xml/nullableobjects.widlprocxml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface A {
+};
+interface B {
+};
+interface C {
+ void f(<ref>A</ref>? x);
+ void f(<ref>B</ref>? x);
+
+};</webidl>
+ <Interface name="A" id="::A">
+ <webidl>interface A {
+};</webidl>
+ </Interface>
+ <Interface name="B" id="::B">
+ <webidl>interface B {
+};</webidl>
+ </Interface>
+ <Interface name="C" id="::C">
+ <webidl>interface C {
+ void f(<ref>A</ref>? x);
+ void f(<ref>B</ref>? x);
+
+};</webidl>
+ <Operation name="f" id="::C::f">
+ <webidl> void f(<ref>A</ref>? x);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="x">
+ <Type name="A" nullable="nullable"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation name="f" id="::C::f">
+ <webidl> void f(<ref>B</ref>? x);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="x">
+ <Type name="B" nullable="nullable"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/xml/operation-optional-arg.widlprocxml b/tests/wpt/web-platform-tests/WebIDL/valid/xml/operation-optional-arg.widlprocxml
new file mode 100644
index 00000000000..54aef1f87e3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/xml/operation-optional-arg.widlprocxml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface ColorCreator {
+ object createColor(float v1, float v2, float v3, optional float alpha = 3.5);
+};</webidl>
+ <Interface name="ColorCreator" id="::ColorCreator">
+ <webidl>interface ColorCreator {
+ object createColor(float v1, float v2, float v3, optional float alpha = 3.5);
+};</webidl>
+ <Operation name="createColor" id="::ColorCreator::createColor">
+ <webidl> object createColor(float v1, float v2, float v3, optional float alpha = 3.5);</webidl>
+ <Type type="object"/>
+ <ArgumentList>
+ <Argument name="v1">
+ <Type type="float"/>
+ </Argument>
+ <Argument name="v2">
+ <Type type="float"/>
+ </Argument>
+ <Argument name="v3">
+ <Type type="float"/>
+ </Argument>
+ <Argument optional="optional" name="alpha" value="3.5">
+ <Type type="float"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/xml/overloading.widlprocxml b/tests/wpt/web-platform-tests/WebIDL/valid/xml/overloading.widlprocxml
new file mode 100644
index 00000000000..db6da7a68c7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/xml/overloading.widlprocxml
@@ -0,0 +1,113 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface A {
+};
+
+interface B {
+};
+
+interface C {
+ void f(<ref>A</ref> x);
+ void f(<ref>B</ref> x);
+};
+
+interface A {
+void f(DOMString a);
+void f([AllowAny] DOMString a, DOMString b, float... c);
+void f();
+void f(long a, DOMString b, optional DOMString c, float... d);
+};</webidl>
+ <Interface name="A" id="::A">
+ <webidl>interface A {
+};</webidl>
+ </Interface>
+ <Interface name="B" id="::B">
+ <webidl>interface B {
+};</webidl>
+ </Interface>
+ <Interface name="C" id="::C">
+ <webidl>interface C {
+ void f(<ref>A</ref> x);
+ void f(<ref>B</ref> x);
+};</webidl>
+ <Operation name="f" id="::C::f">
+ <webidl> void f(<ref>A</ref> x);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="x">
+ <Type name="A"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation name="f" id="::C::f">
+ <webidl> void f(<ref>B</ref> x);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="x">
+ <Type name="B"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+ <Interface name="A" id="::A">
+ <webidl>interface A {
+void f(DOMString a);
+void f([AllowAny] DOMString a, DOMString b, float... c);
+void f();
+void f(long a, DOMString b, optional DOMString c, float... d);
+};</webidl>
+ <Operation name="f" id="::A::f">
+ <webidl> void f(DOMString a);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="a">
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation name="f" id="::A::f">
+ <webidl> void f([AllowAny] DOMString a, DOMString b, float... c);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="a">
+ <ExtendedAttributeList>
+ <ExtendedAttribute name="AllowAny">
+ <webidl>AllowAny</webidl>
+ </ExtendedAttribute>
+ </ExtendedAttributeList>
+ <Type type="DOMString"/>
+ </Argument>
+ <Argument name="b">
+ <Type type="DOMString"/>
+ </Argument>
+ <Argument ellipsis="ellipsis" name="c">
+ <Type type="float"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation name="f" id="::A::f">
+ <webidl> void f();</webidl>
+ <Type type="void"/>
+ <ArgumentList/>
+ </Operation>
+ <Operation name="f" id="::A::f">
+ <webidl> void f(long a, DOMString b, optional DOMString c, float... d);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="a">
+ <Type type="long"/>
+ </Argument>
+ <Argument name="b">
+ <Type type="DOMString"/>
+ </Argument>
+ <Argument optional="optional" name="c">
+ <Type type="DOMString"/>
+ </Argument>
+ <Argument ellipsis="ellipsis" name="d">
+ <Type type="float"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/xml/overridebuiltins.widlprocxml b/tests/wpt/web-platform-tests/WebIDL/valid/xml/overridebuiltins.widlprocxml
new file mode 100644
index 00000000000..56c92517beb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/xml/overridebuiltins.widlprocxml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>[OverrideBuiltins]
+interface StringMap2 {
+ readonly attribute unsigned long length;
+ getter DOMString lookup(DOMString key);
+};</webidl>
+ <Interface name="StringMap2" id="::StringMap2">
+ <webidl>[OverrideBuiltins]
+interface StringMap2 {
+ readonly attribute unsigned long length;
+ getter DOMString lookup(DOMString key);
+};</webidl>
+ <ExtendedAttributeList>
+ <ExtendedAttribute name="OverrideBuiltins">
+ <webidl>OverrideBuiltins</webidl>
+ </ExtendedAttribute>
+ </ExtendedAttributeList>
+ <Attribute readonly="readonly" name="length" id="::StringMap2::length">
+ <webidl> readonly attribute unsigned long length;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Operation getter="getter" name="lookup" id="::StringMap2::lookup">
+ <webidl> getter DOMString lookup(DOMString key);</webidl>
+ <Type type="DOMString"/>
+ <ArgumentList>
+ <Argument name="key">
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/xml/partial-interface.widlprocxml b/tests/wpt/web-platform-tests/WebIDL/valid/xml/partial-interface.widlprocxml
new file mode 100644
index 00000000000..8d7dcb4e4f7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/xml/partial-interface.widlprocxml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Foo {
+ attribute DOMString bar;
+};
+
+partial interface Foo {
+ attribute DOMString quux;
+};</webidl>
+ <Interface name="Foo" id="::Foo">
+ <webidl>interface Foo {
+ attribute DOMString bar;
+};</webidl>
+ <Attribute name="bar" id="::Foo::bar">
+ <webidl> attribute DOMString bar;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ </Interface>
+ <Interface name="Foo" partial="partial" id="::Foo">
+ <webidl>partial interface Foo {
+ attribute DOMString quux;
+};</webidl>
+ <Attribute name="quux" id="::Foo::quux">
+ <webidl> attribute DOMString quux;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/xml/primitives.widlprocxml b/tests/wpt/web-platform-tests/WebIDL/valid/xml/primitives.widlprocxml
new file mode 100644
index 00000000000..46977a2d74e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/xml/primitives.widlprocxml
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Primitives {
+ attribute boolean truth;
+ attribute byte character;
+ attribute octet value;
+ attribute short number;
+ attribute unsigned short positive;
+ attribute long big;
+ attribute unsigned long bigpositive;
+ attribute long long bigbig;
+ attribute unsigned long long bigbigpositive;
+ attribute float real;
+ attribute double bigreal;
+ attribute unrestricted float realwithinfinity;
+ attribute unrestricted double bigrealwithinfinity;
+ attribute DOMString string;
+ attribute ByteString bytes;
+ attribute Date date;
+ attribute RegExp regexp;
+};</webidl>
+ <Interface name="Primitives" id="::Primitives">
+ <webidl>interface Primitives {
+ attribute boolean truth;
+ attribute byte character;
+ attribute octet value;
+ attribute short number;
+ attribute unsigned short positive;
+ attribute long big;
+ attribute unsigned long bigpositive;
+ attribute long long bigbig;
+ attribute unsigned long long bigbigpositive;
+ attribute float real;
+ attribute double bigreal;
+ attribute unrestricted float realwithinfinity;
+ attribute unrestricted double bigrealwithinfinity;
+ attribute DOMString string;
+ attribute ByteString bytes;
+ attribute Date date;
+ attribute RegExp regexp;
+};</webidl>
+ <Attribute name="truth" id="::Primitives::truth">
+ <webidl> attribute boolean truth;</webidl>
+ <Type type="boolean"/>
+ </Attribute>
+ <Attribute name="character" id="::Primitives::character">
+ <webidl> attribute byte character;</webidl>
+ <Type type="byte"/>
+ </Attribute>
+ <Attribute name="value" id="::Primitives::value">
+ <webidl> attribute octet value;</webidl>
+ <Type type="octet"/>
+ </Attribute>
+ <Attribute name="number" id="::Primitives::number">
+ <webidl> attribute short number;</webidl>
+ <Type type="short"/>
+ </Attribute>
+ <Attribute name="positive" id="::Primitives::positive">
+ <webidl> attribute unsigned short positive;</webidl>
+ <Type type="unsigned short"/>
+ </Attribute>
+ <Attribute name="big" id="::Primitives::big">
+ <webidl> attribute long big;</webidl>
+ <Type type="long"/>
+ </Attribute>
+ <Attribute name="bigpositive" id="::Primitives::bigpositive">
+ <webidl> attribute unsigned long bigpositive;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Attribute name="bigbig" id="::Primitives::bigbig">
+ <webidl> attribute long long bigbig;</webidl>
+ <Type type="long long"/>
+ </Attribute>
+ <Attribute name="bigbigpositive" id="::Primitives::bigbigpositive">
+ <webidl> attribute unsigned long long bigbigpositive;</webidl>
+ <Type type="unsigned long long"/>
+ </Attribute>
+ <Attribute name="real" id="::Primitives::real">
+ <webidl> attribute float real;</webidl>
+ <Type type="float"/>
+ </Attribute>
+ <Attribute name="bigreal" id="::Primitives::bigreal">
+ <webidl> attribute double bigreal;</webidl>
+ <Type type="double"/>
+ </Attribute>
+ <Attribute name="realwithinfinity" id="::Primitives::realwithinfinity">
+ <webidl> attribute unrestricted float realwithinfinity;</webidl>
+ <Type type="unrestricted float"/>
+ </Attribute>
+ <Attribute name="bigrealwithinfinity" id="::Primitives::bigrealwithinfinity">
+ <webidl> attribute unrestricted double bigrealwithinfinity;</webidl>
+ <Type type="unrestricted double"/>
+ </Attribute>
+ <Attribute name="string" id="::Primitives::string">
+ <webidl> attribute DOMString string;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ <Attribute name="bytes" id="::Primitives::bytes">
+ <webidl> attribute ByteString bytes;</webidl>
+ <Type type="ByteString"/>
+ </Attribute>
+ <Attribute name="date" id="::Primitives::date">
+ <webidl> attribute Date date;</webidl>
+ <Type type="Date"/>
+ </Attribute>
+ <Attribute name="regexp" id="::Primitives::regexp">
+ <webidl> attribute RegExp regexp;</webidl>
+ <Type type="RegExp"/>
+ </Attribute>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/xml/prototyperoot.widlprocxml b/tests/wpt/web-platform-tests/WebIDL/valid/xml/prototyperoot.widlprocxml
new file mode 100644
index 00000000000..2e56cd75ec3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/xml/prototyperoot.widlprocxml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>[PrototypeRoot]
+interface Node {
+ readonly attribute unsigned short nodeType;
+};</webidl>
+ <Interface name="Node" id="::Node">
+ <webidl>[PrototypeRoot]
+interface Node {
+ readonly attribute unsigned short nodeType;
+};</webidl>
+ <ExtendedAttributeList>
+ <ExtendedAttribute name="PrototypeRoot">
+ <webidl>PrototypeRoot</webidl>
+ </ExtendedAttribute>
+ </ExtendedAttributeList>
+ <Attribute readonly="readonly" name="nodeType" id="::Node::nodeType">
+ <webidl> readonly attribute unsigned short nodeType;</webidl>
+ <Type type="unsigned short"/>
+ </Attribute>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/xml/putforwards.widlprocxml b/tests/wpt/web-platform-tests/WebIDL/valid/xml/putforwards.widlprocxml
new file mode 100644
index 00000000000..634fad55a56
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/xml/putforwards.widlprocxml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Person {
+ [PutForwards=full] readonly attribute <ref>Name</ref> name;
+ attribute unsigned short age;
+};</webidl>
+ <Interface name="Person" id="::Person">
+ <webidl>interface Person {
+ [PutForwards=full] readonly attribute <ref>Name</ref> name;
+ attribute unsigned short age;
+};</webidl>
+ <Attribute readonly="readonly" name="name" id="::Person::name">
+ <webidl> [PutForwards=full] readonly attribute <ref>Name</ref> name;</webidl>
+ <ExtendedAttributeList>
+ <ExtendedAttribute name="PutForwards" value="full">
+ <webidl>PutForwards</webidl>
+ </ExtendedAttribute>
+ </ExtendedAttributeList>
+ <Type name="Name"/>
+ </Attribute>
+ <Attribute name="age" id="::Person::age">
+ <webidl> attribute unsigned short age;</webidl>
+ <Type type="unsigned short"/>
+ </Attribute>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/xml/reg-operations.widlprocxml b/tests/wpt/web-platform-tests/WebIDL/valid/xml/reg-operations.widlprocxml
new file mode 100644
index 00000000000..3b756ed68d8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/xml/reg-operations.widlprocxml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Dimensions {
+ attribute unsigned long width;
+ attribute unsigned long height;
+};
+
+exception NoPointerDevice { };
+
+interface Button {
+
+ boolean isMouseOver();
+
+ void setDimensions(<ref>Dimensions</ref> size);
+ void setDimensions(unsigned long width, unsigned long height);
+};</webidl>
+ <Interface name="Dimensions" id="::Dimensions">
+ <webidl>interface Dimensions {
+ attribute unsigned long width;
+ attribute unsigned long height;
+};</webidl>
+ <Attribute name="width" id="::Dimensions::width">
+ <webidl> attribute unsigned long width;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Attribute name="height" id="::Dimensions::height">
+ <webidl> attribute unsigned long height;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ </Interface>
+ <Exception name="NoPointerDevice" id="::NoPointerDevice">
+ <webidl>exception NoPointerDevice { };</webidl>
+ </Exception>
+ <Interface name="Button" id="::Button">
+ <webidl>interface Button {
+
+ boolean isMouseOver();
+
+ void setDimensions(<ref>Dimensions</ref> size);
+ void setDimensions(unsigned long width, unsigned long height);
+};</webidl>
+ <Operation name="isMouseOver" id="::Button::isMouseOver">
+ <webidl> boolean isMouseOver();</webidl>
+ <Type type="boolean"/>
+ <ArgumentList/>
+ </Operation>
+ <Operation name="setDimensions" id="::Button::setDimensions">
+ <webidl> void setDimensions(<ref>Dimensions</ref> size);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="size">
+ <Type name="Dimensions"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation name="setDimensions" id="::Button::setDimensions">
+ <webidl> void setDimensions(unsigned long width, unsigned long height);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="width">
+ <Type type="unsigned long"/>
+ </Argument>
+ <Argument name="height">
+ <Type type="unsigned long"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/xml/replaceable.widlprocxml b/tests/wpt/web-platform-tests/WebIDL/valid/xml/replaceable.widlprocxml
new file mode 100644
index 00000000000..f9762166825
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/xml/replaceable.widlprocxml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Counter {
+ [Replaceable] readonly attribute unsigned long value;
+ void increment();
+};</webidl>
+ <Interface name="Counter" id="::Counter">
+ <webidl>interface Counter {
+ [Replaceable] readonly attribute unsigned long value;
+ void increment();
+};</webidl>
+ <Attribute readonly="readonly" name="value" id="::Counter::value">
+ <webidl> [Replaceable] readonly attribute unsigned long value;</webidl>
+ <ExtendedAttributeList>
+ <ExtendedAttribute name="Replaceable">
+ <webidl>Replaceable</webidl>
+ </ExtendedAttribute>
+ </ExtendedAttributeList>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Operation name="increment" id="::Counter::increment">
+ <webidl> void increment();</webidl>
+ <Type type="void"/>
+ <ArgumentList/>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/xml/sequence.widlprocxml b/tests/wpt/web-platform-tests/WebIDL/valid/xml/sequence.widlprocxml
new file mode 100644
index 00000000000..d5f4564175b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/xml/sequence.widlprocxml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Canvas {
+ void drawPolygon(sequence&lt;float> coordinates);
+ sequence&lt;float> getInflectionPoints();
+};</webidl>
+ <Interface name="Canvas" id="::Canvas">
+ <webidl>interface Canvas {
+ void drawPolygon(sequence&lt;float> coordinates);
+ sequence&lt;float> getInflectionPoints();
+};</webidl>
+ <Operation name="drawPolygon" id="::Canvas::drawPolygon">
+ <webidl> void drawPolygon(sequence&lt;float> coordinates);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="coordinates">
+ <Type type="sequence">
+ <Type type="float"/>
+ </Type>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation name="getInflectionPoints" id="::Canvas::getInflectionPoints">
+ <webidl> sequence&lt;float> getInflectionPoints();</webidl>
+ <Type type="sequence">
+ <Type type="float"/>
+ </Type>
+ <ArgumentList/>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/xml/serializer.widlprocxml b/tests/wpt/web-platform-tests/WebIDL/valid/xml/serializer.widlprocxml
new file mode 100644
index 00000000000..eb4219f8a5e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/xml/serializer.widlprocxml
@@ -0,0 +1,296 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Transaction {
+ readonly attribute <ref>Account</ref> from;
+ readonly attribute <ref>Account</ref> to;
+ readonly attribute float amount;
+ readonly attribute DOMString description;
+ readonly attribute unsigned long number;
+
+ serializer;
+};
+
+interface Account {
+ attribute DOMString name;
+ attribute unsigned long number;
+ serializer DOMString serialize();
+};
+
+interface Transaction2 {
+ readonly attribute <ref>Account2</ref> from;
+ readonly attribute <ref>Account2</ref> to;
+ readonly attribute float amount;
+ readonly attribute DOMString description;
+ readonly attribute unsigned long number;
+
+ serializer = { from, to, amount, description };
+};
+
+interface Account2 {
+ attribute DOMString name;
+ attribute unsigned long number;
+ serializer = number;
+};
+
+interface Account3 {
+ attribute DOMString name;
+ attribute unsigned long number;
+
+ serializer = { attribute };
+};
+
+interface Account4 {
+ getter object getItem(unsigned long index);
+ serializer = { getter };
+};
+
+interface Account5 : <ref>Account</ref> {
+ attribute DOMString secondname;
+ serializer = { inherit, secondname };
+};
+
+interface Account6 : <ref>Account</ref> {
+ attribute DOMString secondname;
+ serializer = { inherit, attribute };
+};
+
+interface Account7 {
+ attribute DOMString name;
+ attribute unsigned long number;
+ serializer = [ name, number ];
+};
+
+interface Account8 {
+ getter object getItem(unsigned long index);
+ serializer = [ getter ];
+};</webidl>
+ <Interface name="Transaction" id="::Transaction">
+ <webidl>interface Transaction {
+ readonly attribute <ref>Account</ref> from;
+ readonly attribute <ref>Account</ref> to;
+ readonly attribute float amount;
+ readonly attribute DOMString description;
+ readonly attribute unsigned long number;
+
+ serializer;
+};</webidl>
+ <Attribute readonly="readonly" name="from" id="::Transaction::from">
+ <webidl> readonly attribute <ref>Account</ref> from;</webidl>
+ <Type name="Account"/>
+ </Attribute>
+ <Attribute readonly="readonly" name="to" id="::Transaction::to">
+ <webidl> readonly attribute <ref>Account</ref> to;</webidl>
+ <Type name="Account"/>
+ </Attribute>
+ <Attribute readonly="readonly" name="amount" id="::Transaction::amount">
+ <webidl> readonly attribute float amount;</webidl>
+ <Type type="float"/>
+ </Attribute>
+ <Attribute readonly="readonly" name="description" id="::Transaction::description">
+ <webidl> readonly attribute DOMString description;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ <Attribute readonly="readonly" name="number" id="::Transaction::number">
+ <webidl> readonly attribute unsigned long number;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Serializer>
+ <webidl> serializer;</webidl>
+ </Serializer>
+ </Interface>
+ <Interface name="Account" id="::Account">
+ <webidl>interface Account {
+ attribute DOMString name;
+ attribute unsigned long number;
+ serializer DOMString serialize();
+};</webidl>
+ <Attribute name="name" id="::Account::name">
+ <webidl> attribute DOMString name;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ <Attribute name="number" id="::Account::number">
+ <webidl> attribute unsigned long number;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Operation serializer="serializer" name="serialize" id="::Account::serialize">
+ <webidl> serializer DOMString serialize();</webidl>
+ <Type type="DOMString"/>
+ <ArgumentList/>
+ </Operation>
+ </Interface>
+ <Interface name="Transaction2" id="::Transaction2">
+ <webidl>interface Transaction2 {
+ readonly attribute <ref>Account2</ref> from;
+ readonly attribute <ref>Account2</ref> to;
+ readonly attribute float amount;
+ readonly attribute DOMString description;
+ readonly attribute unsigned long number;
+
+ serializer = { from, to, amount, description };
+};</webidl>
+ <Attribute readonly="readonly" name="from" id="::Transaction2::from">
+ <webidl> readonly attribute <ref>Account2</ref> from;</webidl>
+ <Type name="Account2"/>
+ </Attribute>
+ <Attribute readonly="readonly" name="to" id="::Transaction2::to">
+ <webidl> readonly attribute <ref>Account2</ref> to;</webidl>
+ <Type name="Account2"/>
+ </Attribute>
+ <Attribute readonly="readonly" name="amount" id="::Transaction2::amount">
+ <webidl> readonly attribute float amount;</webidl>
+ <Type type="float"/>
+ </Attribute>
+ <Attribute readonly="readonly" name="description" id="::Transaction2::description">
+ <webidl> readonly attribute DOMString description;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ <Attribute readonly="readonly" name="number" id="::Transaction2::number">
+ <webidl> readonly attribute unsigned long number;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Serializer>
+ <webidl> serializer = { from, to, amount, description };</webidl>
+ <Map pattern="selection">
+ <PatternAttribute name="from"/>
+ <PatternAttribute name="to"/>
+ <PatternAttribute name="amount"/>
+ <PatternAttribute name="description"/>
+ </Map>
+ </Serializer>
+ </Interface>
+ <Interface name="Account2" id="::Account2">
+ <webidl>interface Account2 {
+ attribute DOMString name;
+ attribute unsigned long number;
+ serializer = number;
+};</webidl>
+ <Attribute name="name" id="::Account2::name">
+ <webidl> attribute DOMString name;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ <Attribute name="number" id="::Account2::number">
+ <webidl> attribute unsigned long number;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Serializer attribute="number">
+ <webidl> serializer = number;</webidl>
+ </Serializer>
+ </Interface>
+ <Interface name="Account3" id="::Account3">
+ <webidl>interface Account3 {
+ attribute DOMString name;
+ attribute unsigned long number;
+
+ serializer = { attribute };
+};</webidl>
+ <Attribute name="name" id="::Account3::name">
+ <webidl> attribute DOMString name;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ <Attribute name="number" id="::Account3::number">
+ <webidl> attribute unsigned long number;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Serializer>
+ <webidl> serializer = { attribute };</webidl>
+ <Map pattern="all"/>
+ </Serializer>
+ </Interface>
+ <Interface name="Account4" id="::Account4">
+ <webidl>interface Account4 {
+ getter object getItem(unsigned long index);
+ serializer = { getter };
+};</webidl>
+ <Operation getter="getter" name="getItem" id="::Account4::getItem">
+ <webidl> getter object getItem(unsigned long index);</webidl>
+ <Type type="object"/>
+ <ArgumentList>
+ <Argument name="index">
+ <Type type="unsigned long"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Serializer>
+ <webidl> serializer = { getter };</webidl>
+ <Map pattern="getter"/>
+ </Serializer>
+ </Interface>
+ <Interface name="Account5" id="::Account5">
+ <webidl>interface Account5 : <ref>Account</ref> {
+ attribute DOMString secondname;
+ serializer = { inherit, secondname };
+};</webidl>
+ <InterfaceInheritance>
+ <Name name="Account"/>
+ </InterfaceInheritance>
+ <Attribute name="secondname" id="::Account5::secondname">
+ <webidl> attribute DOMString secondname;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ <Serializer>
+ <webidl> serializer = { inherit, secondname };</webidl>
+ <Map inherit="inherit" pattern="selection">
+ <PatternAttribute name="secondname"/>
+ </Map>
+ </Serializer>
+ </Interface>
+ <Interface name="Account6" id="::Account6">
+ <webidl>interface Account6 : <ref>Account</ref> {
+ attribute DOMString secondname;
+ serializer = { inherit, attribute };
+};</webidl>
+ <InterfaceInheritance>
+ <Name name="Account"/>
+ </InterfaceInheritance>
+ <Attribute name="secondname" id="::Account6::secondname">
+ <webidl> attribute DOMString secondname;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ <Serializer>
+ <webidl> serializer = { inherit, attribute };</webidl>
+ <Map inherit="inherit" pattern="all"/>
+ </Serializer>
+ </Interface>
+ <Interface name="Account7" id="::Account7">
+ <webidl>interface Account7 {
+ attribute DOMString name;
+ attribute unsigned long number;
+ serializer = [ name, number ];
+};</webidl>
+ <Attribute name="name" id="::Account7::name">
+ <webidl> attribute DOMString name;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ <Attribute name="number" id="::Account7::number">
+ <webidl> attribute unsigned long number;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Serializer>
+ <webidl> serializer = [ name, number ];</webidl>
+ <List pattern="selection">
+ <PatternAttribute name="name"/>
+ <PatternAttribute name="number"/>
+ </List>
+ </Serializer>
+ </Interface>
+ <Interface name="Account8" id="::Account8">
+ <webidl>interface Account8 {
+ getter object getItem(unsigned long index);
+ serializer = [ getter ];
+};</webidl>
+ <Operation getter="getter" name="getItem" id="::Account8::getItem">
+ <webidl> getter object getItem(unsigned long index);</webidl>
+ <Type type="object"/>
+ <ArgumentList>
+ <Argument name="index">
+ <Type type="unsigned long"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Serializer>
+ <webidl> serializer = [ getter ];</webidl>
+ <List pattern="getter"/>
+ </Serializer>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/xml/special-omittable.widlprocxml b/tests/wpt/web-platform-tests/WebIDL/valid/xml/special-omittable.widlprocxml
new file mode 100644
index 00000000000..1986d190a80
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/xml/special-omittable.widlprocxml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <Interface name="Dictionary" id="::Dictionary">
+ <webidl>interface Dictionary {
+ readonly attribute unsigned long propertyCount;
+
+ omittable getter float getProperty(DOMString propertyName);
+ omittable setter void setProperty(DOMString propertyName, float propertyValue);
+};</webidl>
+ <Attribute readonly="readonly" name="propertyCount" id="::Dictionary::propertyCount">
+ <webidl> readonly attribute unsigned long propertyCount;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Operation omittable="omittable" getter="getter" name="getProperty" id="::Dictionary::getProperty">
+ <webidl> omittable getter float getProperty(DOMString propertyName);</webidl>
+ <Type type="float"/>
+ <ArgumentList>
+ <Argument name="propertyName">
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation omittable="omittable" setter="setter" name="setProperty" id="::Dictionary::setProperty">
+ <webidl> omittable setter void setProperty(DOMString propertyName, float propertyValue);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="propertyName">
+ <Type type="DOMString"/>
+ </Argument>
+ <Argument name="propertyValue">
+ <Type type="float"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/xml/static.widlprocxml b/tests/wpt/web-platform-tests/WebIDL/valid/xml/static.widlprocxml
new file mode 100644
index 00000000000..03c14e16eba
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/xml/static.widlprocxml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Point { };
+
+interface Circle {
+ attribute float cx;
+ attribute float cy;
+ attribute float radius;
+
+ static readonly attribute long triangulationCount;
+ static <ref>Point</ref> triangulate(<ref>Circle</ref> c1, <ref>Circle</ref> c2, <ref>Circle</ref> c3);
+};</webidl>
+ <Interface name="Point" id="::Point">
+ <webidl>interface Point { };</webidl>
+ </Interface>
+ <Interface name="Circle" id="::Circle">
+ <webidl>interface Circle {
+ attribute float cx;
+ attribute float cy;
+ attribute float radius;
+
+ static readonly attribute long triangulationCount;
+ static <ref>Point</ref> triangulate(<ref>Circle</ref> c1, <ref>Circle</ref> c2, <ref>Circle</ref> c3);
+};</webidl>
+ <Attribute name="cx" id="::Circle::cx">
+ <webidl> attribute float cx;</webidl>
+ <Type type="float"/>
+ </Attribute>
+ <Attribute name="cy" id="::Circle::cy">
+ <webidl> attribute float cy;</webidl>
+ <Type type="float"/>
+ </Attribute>
+ <Attribute name="radius" id="::Circle::radius">
+ <webidl> attribute float radius;</webidl>
+ <Type type="float"/>
+ </Attribute>
+ <Attribute static="static" readonly="readonly" name="triangulationCount" id="::Circle::triangulationCount">
+ <webidl> static readonly attribute long triangulationCount;</webidl>
+ <Type type="long"/>
+ </Attribute>
+ <Operation static="static" name="triangulate" id="::Circle::triangulate">
+ <webidl> static <ref>Point</ref> triangulate(<ref>Circle</ref> c1, <ref>Circle</ref> c2, <ref>Circle</ref> c3);</webidl>
+ <Type name="Point"/>
+ <ArgumentList>
+ <Argument name="c1">
+ <Type name="Circle"/>
+ </Argument>
+ <Argument name="c2">
+ <Type name="Circle"/>
+ </Argument>
+ <Argument name="c3">
+ <Type name="Circle"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/xml/stringifier-attribute.widlprocxml b/tests/wpt/web-platform-tests/WebIDL/valid/xml/stringifier-attribute.widlprocxml
new file mode 100644
index 00000000000..082ce4d341b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/xml/stringifier-attribute.widlprocxml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>[Constructor]
+interface Student {
+ attribute unsigned long id;
+ stringifier attribute DOMString name;
+};</webidl>
+ <Interface name="Student" id="::Student">
+ <webidl>[Constructor]
+interface Student {
+ attribute unsigned long id;
+ stringifier attribute DOMString name;
+};</webidl>
+ <ExtendedAttributeList>
+ <ExtendedAttribute name="Constructor">
+ <webidl>Constructor</webidl>
+ </ExtendedAttribute>
+ </ExtendedAttributeList>
+ <Attribute name="id" id="::Student::id">
+ <webidl> attribute unsigned long id;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Attribute stringifier="stringifier" name="name" id="::Student::name">
+ <webidl> stringifier attribute DOMString name;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/xml/stringifier-custom.widlprocxml b/tests/wpt/web-platform-tests/WebIDL/valid/xml/stringifier-custom.widlprocxml
new file mode 100644
index 00000000000..cdab1ccfc37
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/xml/stringifier-custom.widlprocxml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>[Constructor]
+interface Student {
+ attribute unsigned long id;
+ attribute DOMString? familyName;
+ attribute DOMString givenName;
+
+ stringifier DOMString ();
+};</webidl>
+ <Interface name="Student" id="::Student">
+ <webidl>[Constructor]
+interface Student {
+ attribute unsigned long id;
+ attribute DOMString? familyName;
+ attribute DOMString givenName;
+
+ stringifier DOMString ();
+};</webidl>
+ <ExtendedAttributeList>
+ <ExtendedAttribute name="Constructor">
+ <webidl>Constructor</webidl>
+ </ExtendedAttribute>
+ </ExtendedAttributeList>
+ <Attribute name="id" id="::Student::id">
+ <webidl> attribute unsigned long id;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Attribute name="familyName" id="::Student::familyName">
+ <webidl> attribute DOMString? familyName;</webidl>
+ <Type type="DOMString" nullable="nullable"/>
+ </Attribute>
+ <Attribute name="givenName" id="::Student::givenName">
+ <webidl> attribute DOMString givenName;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ <Operation stringifier="stringifier">
+ <webidl> stringifier DOMString ();</webidl>
+ <Type type="DOMString"/>
+ <ArgumentList/>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/xml/stringifier.widlprocxml b/tests/wpt/web-platform-tests/WebIDL/valid/xml/stringifier.widlprocxml
new file mode 100644
index 00000000000..4a18b80b704
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/xml/stringifier.widlprocxml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface A {
+ stringifier DOMString ();
+};
+
+interface A {
+ stringifier;
+};</webidl>
+ <Interface name="A" id="::A">
+ <webidl>interface A {
+ stringifier DOMString ();
+};</webidl>
+ <Operation stringifier="stringifier">
+ <webidl> stringifier DOMString ();</webidl>
+ <Type type="DOMString"/>
+ <ArgumentList/>
+ </Operation>
+ </Interface>
+ <Interface name="A" id="::A">
+ <webidl>interface A {
+ stringifier;
+};</webidl>
+ <Stringifier>
+ <webidl> stringifier;</webidl>
+ </Stringifier>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/xml/treatasnull.widlprocxml b/tests/wpt/web-platform-tests/WebIDL/valid/xml/treatasnull.widlprocxml
new file mode 100644
index 00000000000..a57ae163f0b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/xml/treatasnull.widlprocxml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Dog {
+ attribute DOMString name;
+ attribute DOMString owner;
+
+ boolean isMemberOfBreed([TreatNullAs=EmptyString] DOMString breedName);
+};</webidl>
+ <Interface name="Dog" id="::Dog">
+ <webidl>interface Dog {
+ attribute DOMString name;
+ attribute DOMString owner;
+
+ boolean isMemberOfBreed([TreatNullAs=EmptyString] DOMString breedName);
+};</webidl>
+ <Attribute name="name" id="::Dog::name">
+ <webidl> attribute DOMString name;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ <Attribute name="owner" id="::Dog::owner">
+ <webidl> attribute DOMString owner;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ <Operation name="isMemberOfBreed" id="::Dog::isMemberOfBreed">
+ <webidl> boolean isMemberOfBreed([TreatNullAs=EmptyString] DOMString breedName);</webidl>
+ <Type type="boolean"/>
+ <ArgumentList>
+ <Argument name="breedName">
+ <ExtendedAttributeList>
+ <ExtendedAttribute name="TreatNullAs" value="EmptyString">
+ <webidl>TreatNullAs</webidl>
+ </ExtendedAttribute>
+ </ExtendedAttributeList>
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/xml/treatasundefined.widlprocxml b/tests/wpt/web-platform-tests/WebIDL/valid/xml/treatasundefined.widlprocxml
new file mode 100644
index 00000000000..17e71081da0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/xml/treatasundefined.widlprocxml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Cat {
+ attribute DOMString name;
+ attribute DOMString owner;
+
+ boolean isMemberOfBreed([TreatUndefinedAs=EmptyString] DOMString breedName);
+};</webidl>
+ <Interface name="Cat" id="::Cat">
+ <webidl>interface Cat {
+ attribute DOMString name;
+ attribute DOMString owner;
+
+ boolean isMemberOfBreed([TreatUndefinedAs=EmptyString] DOMString breedName);
+};</webidl>
+ <Attribute name="name" id="::Cat::name">
+ <webidl> attribute DOMString name;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ <Attribute name="owner" id="::Cat::owner">
+ <webidl> attribute DOMString owner;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ <Operation name="isMemberOfBreed" id="::Cat::isMemberOfBreed">
+ <webidl> boolean isMemberOfBreed([TreatUndefinedAs=EmptyString] DOMString breedName);</webidl>
+ <Type type="boolean"/>
+ <ArgumentList>
+ <Argument name="breedName">
+ <ExtendedAttributeList>
+ <ExtendedAttribute name="TreatUndefinedAs" value="EmptyString">
+ <webidl>TreatUndefinedAs</webidl>
+ </ExtendedAttribute>
+ </ExtendedAttributeList>
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/xml/typedef.widlprocxml b/tests/wpt/web-platform-tests/WebIDL/valid/xml/typedef.widlprocxml
new file mode 100644
index 00000000000..785f6706e6d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/xml/typedef.widlprocxml
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl> interface Point {
+ attribute float x;
+ attribute float y;
+ };
+
+ typedef sequence&lt;<ref>Point</ref>> PointSequence;
+
+ interface Rect {
+ attribute <ref>Point</ref> topleft;
+ attribute <ref>Point</ref> bottomright;
+ };
+
+ interface Widget {
+
+ readonly attribute <ref>Rect</ref> bounds;
+
+ boolean pointWithinBounds(<ref>Point</ref> p);
+ boolean allPointsWithinBounds(<ref>PointSequence</ref> ps);
+ };
+
+ typedef [Clamp] octet value;</webidl>
+ <Interface name="Point" id="::Point">
+ <webidl> interface Point {
+ attribute float x;
+ attribute float y;
+ };</webidl>
+ <Attribute name="x" id="::Point::x">
+ <webidl> attribute float x;</webidl>
+ <Type type="float"/>
+ </Attribute>
+ <Attribute name="y" id="::Point::y">
+ <webidl> attribute float y;</webidl>
+ <Type type="float"/>
+ </Attribute>
+ </Interface>
+ <Typedef name="PointSequence" id="::PointSequence">
+ <webidl> typedef sequence&lt;<ref>Point</ref>> PointSequence;</webidl>
+ <Type type="sequence">
+ <Type name="Point"/>
+ </Type>
+ </Typedef>
+ <Interface name="Rect" id="::Rect">
+ <webidl> interface Rect {
+ attribute <ref>Point</ref> topleft;
+ attribute <ref>Point</ref> bottomright;
+ };</webidl>
+ <Attribute name="topleft" id="::Rect::topleft">
+ <webidl> attribute <ref>Point</ref> topleft;</webidl>
+ <Type name="Point"/>
+ </Attribute>
+ <Attribute name="bottomright" id="::Rect::bottomright">
+ <webidl> attribute <ref>Point</ref> bottomright;</webidl>
+ <Type name="Point"/>
+ </Attribute>
+ </Interface>
+ <Interface name="Widget" id="::Widget">
+ <webidl> interface Widget {
+
+ readonly attribute <ref>Rect</ref> bounds;
+
+ boolean pointWithinBounds(<ref>Point</ref> p);
+ boolean allPointsWithinBounds(<ref>PointSequence</ref> ps);
+ };</webidl>
+ <Attribute readonly="readonly" name="bounds" id="::Widget::bounds">
+ <webidl> readonly attribute <ref>Rect</ref> bounds;</webidl>
+ <Type name="Rect"/>
+ </Attribute>
+ <Operation name="pointWithinBounds" id="::Widget::pointWithinBounds">
+ <webidl> boolean pointWithinBounds(<ref>Point</ref> p);</webidl>
+ <Type type="boolean"/>
+ <ArgumentList>
+ <Argument name="p">
+ <Type name="Point"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation name="allPointsWithinBounds" id="::Widget::allPointsWithinBounds">
+ <webidl> boolean allPointsWithinBounds(<ref>PointSequence</ref> ps);</webidl>
+ <Type type="boolean"/>
+ <ArgumentList>
+ <Argument name="ps">
+ <Type name="PointSequence"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+ <Typedef name="value" id="::value">
+ <webidl> typedef [Clamp] octet value;</webidl>
+ <Type type="octet">
+ <ExtendedAttributeList>
+ <ExtendedAttribute name="Clamp">
+ <webidl>Clamp</webidl>
+ </ExtendedAttribute>
+ </ExtendedAttributeList>
+ </Type>
+ </Typedef>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/xml/typesuffixes.widlprocxml b/tests/wpt/web-platform-tests/WebIDL/valid/xml/typesuffixes.widlprocxml
new file mode 100644
index 00000000000..830fe62bc0d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/xml/typesuffixes.widlprocxml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Suffixes {
+ void test(sequence&lt;DOMString[]?>? foo);
+};</webidl>
+ <Interface name="Suffixes" id="::Suffixes">
+ <webidl>interface Suffixes {
+ void test(sequence&lt;DOMString[]?>? foo);
+};</webidl>
+ <Operation name="test" id="::Suffixes::test">
+ <webidl> void test(sequence&lt;DOMString[]?>? foo);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="foo">
+ <Type type="sequence" nullable="nullable">
+ <Type type="array" nullable="nullable">
+ <Type type="DOMString"/>
+ </Type>
+ </Type>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/xml/uniontype.widlprocxml b/tests/wpt/web-platform-tests/WebIDL/valid/xml/uniontype.widlprocxml
new file mode 100644
index 00000000000..7d088079956
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/xml/uniontype.widlprocxml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Union {
+ attribute (float or (Date or <ref>Event</ref>) or (<ref>Node</ref> or DOMString)?) test;
+};</webidl>
+ <Interface name="Union" id="::Union">
+ <webidl>interface Union {
+ attribute (float or (Date or <ref>Event</ref>) or (<ref>Node</ref> or DOMString)?) test;
+};</webidl>
+ <Attribute name="test" id="::Union::test">
+ <webidl> attribute (float or (Date or <ref>Event</ref>) or (<ref>Node</ref> or DOMString)?) test;</webidl>
+ <Type type="union">
+ <Type type="float"/>
+ <Type type="union">
+ <Type type="Date"/>
+ <Type name="Event"/>
+ </Type>
+ <Type type="union" nullable="nullable">
+ <Type name="Node"/>
+ <Type type="DOMString"/>
+ </Type>
+ </Type>
+ </Attribute>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/WebIDL/valid/xml/variadic-operations.widlprocxml b/tests/wpt/web-platform-tests/WebIDL/valid/xml/variadic-operations.widlprocxml
new file mode 100644
index 00000000000..0bc9f784413
--- /dev/null
+++ b/tests/wpt/web-platform-tests/WebIDL/valid/xml/variadic-operations.widlprocxml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface IntegerSet {
+ readonly attribute unsigned long cardinality;
+
+ void union(long... ints);
+ void intersection(long... ints);
+};</webidl>
+ <Interface name="IntegerSet" id="::IntegerSet">
+ <webidl>interface IntegerSet {
+ readonly attribute unsigned long cardinality;
+
+ void union(long... ints);
+ void intersection(long... ints);
+};</webidl>
+ <Attribute readonly="readonly" name="cardinality" id="::IntegerSet::cardinality">
+ <webidl> readonly attribute unsigned long cardinality;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Operation name="union" id="::IntegerSet::union">
+ <webidl> void union(long... ints);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument ellipsis="ellipsis" name="ints">
+ <Type type="long"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation name="intersection" id="::IntegerSet::intersection">
+ <webidl> void intersection(long... ints);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument ellipsis="ellipsis" name="ints">
+ <Type type="long"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/FormData-append.html b/tests/wpt/web-platform-tests/XMLHttpRequest/FormData-append.html
new file mode 100644
index 00000000000..f20009e2a81
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/FormData-append.html
@@ -0,0 +1,28 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>FormData.append</title>
+<link rel=help href=https://xhr.spec.whatwg.org/#dom-formdata-append>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+function test_formdata(creator, verifier, description) {
+ async_test(description).step(function() {
+ var fd = creator();
+ var xhr = new XMLHttpRequest();
+ xhr.onload = this.step_func(function() {
+ verifier(xhr.responseText);
+ this.done();
+ });
+ xhr.open("POST", "resources/upload.py");
+ xhr.send(fd);
+ })
+}
+test_formdata(function() {
+ var fd = new FormData();
+ fd.append("name", new String("value"));
+ return fd;
+}, function(data) {
+ assert_equals(data, "name=value,\n");
+}, "Passing a String object to FormData.append should work.");
+</script>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/XMLHttpRequest-withCredentials.html b/tests/wpt/web-platform-tests/XMLHttpRequest/XMLHttpRequest-withCredentials.html
new file mode 100644
index 00000000000..c6b937bfce6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/XMLHttpRequest-withCredentials.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>XMLHttpRequest#withCredentials</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src=XMLHttpRequest-withCredentials.js></script>
+<link rel="help" href="https://xhr.spec.whatwg.org/#the-withcredentials-attribute"
+ data-tested-assertations="following::ol/li[1] following::ol/li[2]
+ following::ol/li[3] following::ol/li[4]">
+<div id="log"></div>
+<script>
+setup({ explicit_done: true })
+test_withCredentials(false)
+</script>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/XMLHttpRequest-withCredentials.js b/tests/wpt/web-platform-tests/XMLHttpRequest/XMLHttpRequest-withCredentials.js
new file mode 100644
index 00000000000..a2834ccce25
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/XMLHttpRequest-withCredentials.js
@@ -0,0 +1,43 @@
+function test_withCredentials(worker) {
+ test(function() {
+ var client = new XMLHttpRequest()
+ assert_false(client.withCredentials, "withCredentials defaults to false")
+ client.withCredentials = true
+ assert_true(client.withCredentials, "is true after setting")
+ }, "default value is false, set value is true")
+
+ test(function() {
+ var client = new XMLHttpRequest()
+ client.open("GET", "resources/delay.py?ms=1000", true)
+ client.withCredentials = true
+ assert_true(client.withCredentials, "set in OPEN state")
+ }, "can also be set in OPEN state")
+
+ test(function() {
+ var client = new XMLHttpRequest()
+ client.open("GET", "resources/delay.py?ms=1000", false)
+ if (worker) {
+ client.withCredentials = true
+ assert_true(client.withCredentials, "set in OPEN state")
+ } else {
+ assert_throws("InvalidAccessError", function() {
+ client.withCredentials = true
+ })
+ assert_false(client.withCredentials, "set in OPEN state")
+ }
+ }, "setting on synchronous XHR")
+
+ async_test("setting withCredentials when not in UNSENT, OPENED state").step(function() {
+ this.add_cleanup(done)
+ var client = new XMLHttpRequest()
+ client.open("GET", "resources/delay.py?ms=1000")
+ client.send()
+ assert_throws("InvalidStateError", function() { client.withCredentials = true })
+ client.onreadystatechange = this.step_func(function() {
+ assert_throws("InvalidStateError", function() { client.withCredentials = true })
+ if (client.readyState === 4) {
+ this.done()
+ }
+ })
+ })
+}
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/XMLHttpRequest-withCredentials.worker.js b/tests/wpt/web-platform-tests/XMLHttpRequest/XMLHttpRequest-withCredentials.worker.js
new file mode 100644
index 00000000000..dea0da24021
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/XMLHttpRequest-withCredentials.worker.js
@@ -0,0 +1,3 @@
+importScripts("/resources/testharness.js")
+importScripts("XMLHttpRequest-withCredentials.js")
+test_withCredentials(true);
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/abort-after-receive.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/abort-after-receive.htm
new file mode 100644
index 00000000000..bd97b68358d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/abort-after-receive.htm
@@ -0,0 +1,42 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: abort() after successful receive should not fire "abort" event</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-abort()-method" data-tested-assertations="following::ol[1]/li[4] following::ol[1]/li[5]"/>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test();
+
+ test.step(function() {
+ var client = new XMLHttpRequest();
+
+ client.onreadystatechange = test.step_func(function() {
+ if (client.readyState == 4) {
+ // abort should not cause the "abort" event to fire
+
+ client.abort();
+
+ assert_equals(client.readyState, 0);
+
+ setTimeout(function(){ // use a timeout to catch any implementation that might queue an abort event for later - just in case
+ test.step(function(){test.done();});
+ }, 200);
+ }
+ });
+
+ client.onabort = test.step_func(function () {
+ // this should not fire!
+
+ assert_unreached("abort() should not cause the abort event to fire");
+ });
+
+ client.open("GET", "resources/well-formed.xml", true);
+ client.send(null);
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/abort-after-send.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/abort-after-send.htm
new file mode 100644
index 00000000000..c4885c9911b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/abort-after-send.htm
@@ -0,0 +1,55 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: abort() after send()</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-abort()-method" data-tested-assertations="following-sibling::ol/li[1] following-sibling::ol/li[3] following-sibling::ol/li[4] following-sibling::ol/li[4]/ol/li[1] following-sibling::ol/li[4]/ol/li[3] following-sibling::ol/li[4]/ol/li[4] following-sibling::ol/li[4]/ol/li[5] following-sibling::ol/li[4]/ol/li[6] following-sibling::ol/li[5]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-responsetext-attribute" data-tested-assertations="following::ol/li[3]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-responsexml-attribute" data-tested-assertations="following::ol/li[3]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#dom-xmlhttprequest-getallresponseheaders" data-tested-assertations="following::ol/li[2]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#dom-xmlhttprequest-getresponseheader" data-tested-assertations="following::ol/li[2]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-status-attribute" data-tested-assertations="following::ol/li[2]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-statustext-attribute" data-tested-assertations="following::ol/li[2]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#infrastructure-for-the-send()-method" data-tested-assertations="following::dt[1] following::dd[1]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+ var client = new XMLHttpRequest(),
+ control_flag = false,
+ result = [],
+ expected = [1, 4, 'progress', 'abort', 'loadend'] // open() -> 1, abort() -> 4
+ client.onreadystatechange = function() {
+ test.step(function() {
+ result.push(client.readyState)
+ if(client.readyState == 4) {
+ control_flag = true
+ assert_equals(client.responseXML, null)
+ assert_equals(client.responseText, "")
+ assert_equals(client.status, 0)
+ assert_equals(client.statusText, "")
+ assert_equals(client.getAllResponseHeaders(), "")
+ assert_equals(client.getResponseHeader('Content-Type'), null)
+ }
+ })
+ }
+ client.open("GET", "resources/well-formed.xml", true)
+ client.send(null)
+ client.addEventListener('progress', logEvt)
+ client.addEventListener('abort', logEvt)
+ client.addEventListener('loadend', logEvt)
+ client.abort()
+ assert_true(control_flag)
+ assert_equals(client.readyState, 0)
+ assert_array_equals(result, expected)
+ test.done()
+ function logEvt (e) {
+ result.push(e.type)
+ }
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/abort-after-stop.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/abort-after-stop.htm
new file mode 100644
index 00000000000..87e9ebcd853
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/abort-after-stop.htm
@@ -0,0 +1,32 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: abort event should fire when stop() method is used</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#infrastructure-for-the-send()-method" data-tested-assertations="following::dt[3] following::dt[3]/following::dd[1]/p"/>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test();
+ test.step(function() {
+ var client = new XMLHttpRequest();
+ var abortFired = false;
+ client.onabort = test.step_func(function (e) {
+ assert_equals(e.type, 'abort');
+ abortFired = true;
+ });
+ client.open("GET", "resources/delay.py?ms=3000", true);
+ client.send(null);
+ setTimeout(function(){
+ test.step(function(){
+ assert_equals(abortFired, true);
+ test.done();
+ });
+ }, 200);
+ window.stop();
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/abort-after-timeout.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/abort-after-timeout.htm
new file mode 100644
index 00000000000..e8e84b1a35d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/abort-after-timeout.htm
@@ -0,0 +1,58 @@
+<!doctype html>
+<html>
+<head>
+ <title>XMLHttpRequest: abort() after a timeout should not fire "abort" event</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-abort()-method" data-tested-assertations="following::ol[1]/li[4] following::ol[1]/li[5]"/>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-timeout-attribute" data-tested-assertations="following::ol[1]/li[2]"/>
+</head>
+<body>
+<div id="log"></div>
+<script>
+ var test = async_test();
+
+ test.step(function() {
+ // timeout is 100ms
+ // the download would otherwise take 1000ms
+ // we check after 300ms to make sure abort does not fire an "abort" event
+
+ var timeoutFired = false;
+
+ var client = new XMLHttpRequest();
+
+ assert_true('timeout' in client, 'xhr.timeout is not supported in this user agent');
+
+ client.timeout = 100;
+
+ setTimeout(test.step_func(function() {
+ assert_true(timeoutFired);
+
+ // abort should not cause the "abort" event to fire
+ client.abort();
+
+ setTimeout(function(){ // use a timeout to catch any implementation that might queue an abort event for later - just in case
+ test.step(function(){test.done();});
+ }, 200);
+
+ assert_equals(client.readyState, 0);
+
+ test.done();
+ }), 300);
+
+ client.ontimeout = function () {
+ timeoutFired = true;
+ };
+
+ client.onabort = test.step_func(function () {
+ // this should not fire!
+
+ assert_unreached("abort() should not cause the abort event to fire");
+ });
+
+ client.open("GET", "/common/blank.html?pipe=trickle(d1)", true);
+ client.send(null);
+ });
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/abort-during-done.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/abort-during-done.htm
new file mode 100644
index 00000000000..a8b604fe3f7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/abort-during-done.htm
@@ -0,0 +1,32 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: abort() during DONE</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-abort()-method" data-tested-assertations="following-sibling::ol/li[4] following-sibling::ol/li[5]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+ var client = new XMLHttpRequest(),
+ result = [],
+ expected = [1, 4] // open() -> 1, send() -> 4
+ client.onreadystatechange = function() {
+ test.step(function() {
+ result.push(client.readyState)
+ })
+ }
+ client.open("GET", "resources/well-formed.xml", false)
+ client.send(null)
+ assert_equals(client.readyState, 4)
+ client.abort()
+ assert_equals(client.readyState, 0)
+ assert_array_equals(result, expected)
+ test.done()
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/abort-during-open.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/abort-during-open.htm
new file mode 100644
index 00000000000..60a6eeecd83
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/abort-during-open.htm
@@ -0,0 +1,29 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: abort() during OPEN</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-abort()-method" data-tested-assertations="following-sibling::ol/li[4] following-sibling::ol/li[5]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-send()-method" data-tested-assertations="following-sibling::ol/li[1]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+ var client = new XMLHttpRequest()
+ client.open("GET", "...")
+ client.onreadystatechange = function() {
+ test.step(function() {
+ assert_unreached()
+ })
+ }
+ client.abort()
+ assert_equals(client.readyState, 0)
+ assert_throws("InvalidStateError", function() { client.send("test") }, "calling send() after abort()")
+ })
+ test.done()
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/abort-during-unsent.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/abort-during-unsent.htm
new file mode 100644
index 00000000000..bc2f5cab535
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/abort-during-unsent.htm
@@ -0,0 +1,26 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: abort() during UNSENT</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-abort()-method" data-tested-assertations="following-sibling::ol/li[4] following-sibling::ol/li[5]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+ var client = new XMLHttpRequest()
+ client.onreadystatechange = function() {
+ test.step(function() {
+ assert_unreached()
+ })
+ }
+ client.abort()
+ assert_equals(client.readyState, 0)
+ })
+ test.done()
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/abort-during-upload.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/abort-during-upload.htm
new file mode 100644
index 00000000000..afb28284645
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/abort-during-upload.htm
@@ -0,0 +1,42 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: abort() while sending data</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-abort()-method" data-tested-assertations="following-sibling::ol/li[4]/ol/li[7] following-sibling::ol/li[4]/ol/li[7]/ol/li[2] following-sibling::ol/li[4]/ol/li[7]/ol/li[3] following-sibling::ol/li[4]/ol/li[7]/ol/li[4]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#make-upload-progress-notifications" data-tested-assertations="following::ul[1]/li[1] following::ul[1]/li[2]/ol[1]/li[2] following::ul[1]/li[2]/ol[1]/li[3] following::ul[1]/li[2]/ol[1]/li[4]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test(document.title, {timeout:1100})
+ var result = []
+ var expected = ['progress on XHR Upload', 'abort on XHR Upload', 'loadend on XHR Upload', 'progress on XHR', 'abort on XHR', 'loadend on XHR']
+ function logEvt (e) {
+ var str = e.type+' on '
+ str += e.target instanceof XMLHttpRequest ? 'XHR' : 'XHR Upload'
+ result.push(str)
+ }
+ test.step(function() {
+ var client = new XMLHttpRequest()
+ client.open("POST", "resources/delay.py?ms=1000")
+ client.addEventListener('progress', logEvt)
+ client.addEventListener('abort', logEvt)
+ client.addEventListener('loadend', function (e) {
+ logEvt(e)
+ test.step(function() {
+ assert_equals(client.readyState, 4)
+ assert_array_equals(result, expected)
+ test.done()
+ })
+ })
+ client.upload.addEventListener('loadend', logEvt)
+ client.upload.addEventListener('progress', logEvt)
+ client.upload.addEventListener('abort', logEvt)
+ client.send((new Array(10000)).join('a'))
+ client.abort()
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/abort-event-abort.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/abort-event-abort.htm
new file mode 100644
index 00000000000..2382241cad3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/abort-event-abort.htm
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-abort()-method" data-tested-assertations="following-sibling::ol/li[4]/ol/li[5]" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <title>XMLHttpRequest: The abort() method: do not fire abort event in OPENED state when send() flag is unset. send() throws after abort().</title>
+</head>
+
+<body>
+ <div id="log"></div>
+
+ <script type="text/javascript">
+ var test = async_test()
+
+ test.step(function()
+ {
+ var xhr = new XMLHttpRequest()
+
+ xhr.onreadystatechange = function()
+ {
+ test.step(function()
+ {
+ if (xhr.readyState == 1)
+ {
+ xhr.abort();
+ }
+ });
+ };
+
+ xhr.onabort = function(e)
+ {
+ test.step(function()
+ {
+ assert_unreached('when abort() is called, state is OPENED with the send() flag being unset, must not fire abort event per spec')
+ });
+ };
+
+ xhr.open("GET", "./resources/content.py", true); // This should cause a readystatechange event that calls abort()
+ assert_throws("InvalidStateError", function(){ xhr.send() })
+ test.done()
+ });
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/abort-event-listeners.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/abort-event-listeners.htm
new file mode 100644
index 00000000000..1c50ed394dc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/abort-event-listeners.htm
@@ -0,0 +1,25 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: abort() should not reset event listeners</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-abort()-method" data-tested-assertations="following-sibling::ol/li[6] following-sibling::ol/li[7]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+ var client = new XMLHttpRequest(),
+ test = function() {}
+ client.onreadystatechange = test
+ client.open("GET", "resources/well-formed.xml")
+ client.send(null)
+ client.abort()
+ assert_equals(client.onreadystatechange, test)
+ })
+ test.done()
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/abort-event-loadend.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/abort-event-loadend.htm
new file mode 100644
index 00000000000..8b8dfdaa422
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/abort-event-loadend.htm
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-abort()-method" data-tested-assertations="following-sibling::ol/li[4]/ol/li[6]"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <title>XMLHttpRequest: The abort() method: Fire a progress event named loadend</title>
+</head>
+
+<body>
+ <div id="log"></div>
+
+ <script type="text/javascript">
+ var test = async_test(function(test)
+ {
+ var xhr = new XMLHttpRequest();
+
+ xhr.onloadstart = function()
+ {
+ test.step(function()
+ {
+ if (xhr.readyState == 1)
+ {
+ xhr.abort();
+ }
+ });
+ };
+
+ xhr.onloadend = function(e)
+ {
+ test.step(function()
+ {
+ assert_true(e instanceof ProgressEvent);
+ assert_equals(e.type, "loadend");
+ test.done();
+ });
+ };
+
+ xhr.open("GET", "resources/content.py", true);
+ xhr.send();
+ });
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/abort-event-order.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/abort-event-order.htm
new file mode 100644
index 00000000000..b349a27d26a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/abort-event-order.htm
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-abort()-method" data-tested-assertations="following-sibling::ol/li[4]/ol/li[3] following-sibling::ol/li[4]/ol/li[5] following-sibling::ol/li[4]/ol/li[6] following-sibling::ol/li[4]/ol/li[7]/ol/li[3] following-sibling::ol/li[4]/ol/li[7]/ol/li[4] following-sibling::ol/li[5]" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <title>XMLHttpRequest: The abort() method: abort and loadend events</title>
+</head>
+
+<body>
+ <div id="log"></div>
+
+ <script type="text/javascript">
+ var test = async_test();
+
+ test.step(function()
+ {
+ var xhr = new XMLHttpRequest();
+ var expect = [1, 4, "upload.abort", "upload.loadend", "abort", "loadend"];
+ var actual = [];
+
+ xhr.onreadystatechange = function()
+ {
+ test.step(function()
+ {
+ actual.push(xhr.readyState);
+ });
+ };
+ xhr.onloadstart = function()
+ {
+ test.step(function()
+ {
+ var readyState = xhr.readyState;
+ if (readyState == 1)
+ {
+ xhr.abort();
+ VerifyResult();
+ }else{
+ assert_unreached('Loadstart event should not fire in readyState '+readyState);
+ }
+ });
+ };
+
+ xhr.onloadend = function(e){ actual.push(e.type); };
+ xhr.onabort = function(e){ actual.push(e.type); };
+
+ xhr.upload.onloadend = function(e){ actual.push("upload." + e.type); };
+ xhr.upload.onabort = function(e){ actual.push("upload." + e.type); };
+
+ function VerifyResult()
+ {
+ test.step(function()
+ {
+ assert_array_equals(actual, expect);
+ assert_equals(xhr.readyState, 0, 'state should be UNSENT');
+ test.done();
+ });
+ };
+
+ xhr.open("POST", "./resources/content.py", true);
+ xhr.send("Test Message");
+ });
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/abort-upload-event-abort.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/abort-upload-event-abort.htm
new file mode 100644
index 00000000000..1d045448b5f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/abort-upload-event-abort.htm
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-abort()-method" data-tested-assertations="following-sibling::ol/li[4]/ol/li[7]/ol/li[3]" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <title>XMLHttpRequest: The abort() method: Fire a progress event named abort on the XMLHttpRequestUpload object</title>
+</head>
+
+<body>
+ <div id="log"></div>
+
+ <script type="text/javascript">
+ var test = async_test();
+
+ test.step(function()
+ {
+ var xhr = new XMLHttpRequest();
+
+ xhr.onloadstart = function()
+ {
+ test.step(function()
+ {
+ if (xhr.readyState == 1)
+ {
+ xhr.abort();
+ }
+ });
+ };
+
+ xhr.upload.onabort = function(e)
+ {
+ test.step(function()
+ {
+ assert_true(e instanceof ProgressEvent);
+ assert_equals(e.type, "abort");
+ assert_equals(e.target, xhr.upload);
+ test.done();
+ });
+ };
+
+ xhr.open("POST", "./resources/content.py", true);
+ xhr.send("Test Message");
+ });
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/abort-upload-event-loadend.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/abort-upload-event-loadend.htm
new file mode 100644
index 00000000000..5b10b6530fd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/abort-upload-event-loadend.htm
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-abort()-method" data-tested-assertations="following-sibling::ol/li[4]/ol/li[7]/ol/li[4]" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <title>XMLHttpRequest: The abort() method: Fire a progress event named loadend on the XMLHttpRequestUpload object</title>
+</head>
+
+<body>
+ <div id="log"></div>
+
+ <script type="text/javascript">
+ var test = async_test();
+
+ test.step(function()
+ {
+ var xhr = new XMLHttpRequest();
+
+ xhr.onloadstart = function()
+ {
+ test.step(function ()
+ {
+ if (xhr.readyState == 1)
+ {
+ xhr.abort();
+ }
+ });
+ };
+
+ xhr.upload.onloadend = function(e)
+ {
+ test.step(function()
+ {
+ assert_true(e instanceof ProgressEvent);
+ assert_equals(e.type, "loadend");
+ assert_equals(e.target, xhr.upload);
+ test.done();
+ });
+ };
+
+ xhr.open("POST", "./resources/content.py", true);
+ xhr.send("Test Message");
+ });
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/anonymous-mode-unsupported.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/anonymous-mode-unsupported.htm
new file mode 100644
index 00000000000..9cacf61b7d2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/anonymous-mode-unsupported.htm
@@ -0,0 +1,40 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: anonymous mode unsupported</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ /*
+ Older versions of the XMLHttpRequest spec had an 'anonymous' mode
+ The point of this mode was to handle same-origin requests like other-origin requests,
+ i.e. require preflight, drop authentication data (cookies and HTTP auth)
+ Also the Origin: and Referer: headers would not be sent
+
+ This mode was dropped due to lack of implementations and interest,
+ and this test is here just to assert failure if any implementation
+ supports this based on an older spec version.
+ */
+ document.cookie = 'test=anonymous-mode-unsupported'
+ test = async_test();
+ test.add_cleanup(function(){
+ // make sure we clean up the cookie again to avoid confusing other tests..
+ document.cookie = 'test=;expires=Fri, 28 Feb 2014 07:25:59 GMT';
+ })
+ test.step(function() {
+ var client = new XMLHttpRequest({anonymous:true})
+ client.open("GET", "resources/inspect-headers.py?filter_name=cookie")
+ client.onreadystatechange = test.step_func(function(){
+ if(client.readyState === 4){
+ assert_equals(client.responseText, 'cookie: test=anonymous-mode-unsupported\n', 'The deprecated anonymous:true should be ignored, cookie sent anyway')
+ test.done();
+ }
+ });
+ client.send(null)
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/data-uri.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/data-uri.htm
new file mode 100644
index 00000000000..f3edd3b6d04
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/data-uri.htm
@@ -0,0 +1,53 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>XMLHttpRequest: data uri</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#data:-urls-and-http" data-tested-assertations="following::ul/li[1] following::ul/li[2] following::ul/li[4]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-send()-method" data-tested-assertations="following::ul/li[10]/dl/dt[2]" />
+<div id="log"></div>
+
+<script>
+ function do_test(method, uri, charset, testNamePostfix) {
+ if (typeof charset === 'undefined' || charset === null) charset = 'text/plain';
+ var test = async_test("XHR method " + method + " with charset " + charset+(testNamePostfix||''));
+ test.step(function() {
+ var client = new XMLHttpRequest();
+ client.onreadystatechange = test.step_func(function () {
+ if (client.readyState !== 4) {
+ return;
+ }
+
+ // Note: fetching a data URL with a non-GET method returns a network
+ // error per <http://fetch.spec.whatwg.org/#basic-fetch>.
+ if (method.toUpperCase() !== 'GET') {
+ assert_equals(client.status, 0);
+ assert_equals(client.responseText, '');
+ assert_equals(client.statusText, 'OK');
+ test.done();
+ return;
+ }
+
+ assert_equals(client.responseText, "Hello, World!");
+ assert_equals(client.status, 200);
+ assert_equals(client.getResponseHeader('Content-Type'), charset);
+ var allHeaders = client.getAllResponseHeaders();
+ assert_regexp_match(allHeaders, /content\-type\:/i, 'getAllResponseHeaders() includes Content-Type');
+ assert_false(/content\-length\:/i.test(allHeaders), 'getAllResponseHeaders() must not include Content-Length');
+ test.done();
+ });
+ client.open(method, uri);
+ client.send(null);
+ });
+ }
+ do_test('GET', "data:text/plain,Hello, World!");
+ do_test('GET', "data:text/plain;base64,SGVsbG8sIFdvcmxkIQ==", undefined, " (base64)");
+ do_test('GET', "data:text/html,Hello, World!", 'text/html');
+ do_test('GET', "data:text/html;charset=UTF-8,Hello, World!", 'text/html;charset=UTF-8');
+ do_test('GET', "data:image/png,Hello, World!", 'image/png');
+ do_test('POST', "data:text/plain,Hello, World!");
+ do_test('PUT', "data:text/plain,Hello, World!");
+ do_test('DELETE', "data:text/plain,Hello, World!");
+ do_test('HEAD', "data:text/plain,Hello, World!");
+ do_test('UNICORN', "data:text/plain,Hello, World!");
+</script>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/event-abort.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/event-abort.htm
new file mode 100644
index 00000000000..ce8d937d7fa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/event-abort.htm
@@ -0,0 +1,29 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: abort event</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#handler-xhr-onabort" data-tested-assertations="../.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#event-xhr-abort" data-tested-assertations="../.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#dom-xmlhttprequest-abort" data-tested-assertations="following::ol//ol//ol/li[3]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test();
+ test.step(function() {
+ var client = new XMLHttpRequest();
+ client.onabort = test.step_func(function() {
+ test.done();
+ });
+ client.open("GET", "resources/well-formed.xml");
+ client.send(null);
+ client.abort();
+ setTimeout(test.step_func(function () {
+ assert_unreached("onabort not called after 4 ms");
+ }), 4);
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/event-load.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/event-load.htm
new file mode 100644
index 00000000000..9098eebc743
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/event-load.htm
@@ -0,0 +1,32 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>XMLHttpRequest: The send() method: Fire an event named load (synchronous flag is unset)</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#handler-xhr-onload" data-tested-assertations="../.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#event-xhr-load" data-tested-assertations="../.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#infrastructure-for-the-send()-method" data-tested-assertations="following::a[contains(@href,'#switch-done')]/.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#switch-done" data-tested-assertations="following::ol/li[6]" />
+<div id="log"></div>
+
+<script>
+ var test = async_test();
+ test.step(function() {
+ var client = new XMLHttpRequest();
+ client.onload = test.step_func(function(e) {
+ assert_true(e instanceof ProgressEvent);
+ assert_equals(e.type, "load");
+ assert_equals(client.readyState, 4);
+ test.done();
+ });
+ client.onreadystatechange = test.step_func(function() {
+ if (client.readyState !== 4) return;
+
+ setTimeout(test.step_func(function() {
+ assert_unreached("Didn't get load event within 4ms of readystatechange==4");
+ }), 4);
+ });
+ client.open("GET", "resources/well-formed.xml");
+ client.send(null);
+ });
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/event-loadend.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/event-loadend.htm
new file mode 100644
index 00000000000..b0c62131725
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/event-loadend.htm
@@ -0,0 +1,35 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: loadend event</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#handler-xhr-onloadend" data-tested-assertations="/../.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#event-xhr-loadend" data-tested-assertations="/../.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#infrastructure-for-the-send()-method" data-tested-assertations="/following-sibling::ol/li[10]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#infrastructure-for-the-send()-method" data-tested-assertations="following::a[contains(@href,'#switch-done')]/.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#switch-done" data-tested-assertations="following::ol[1]/li[7]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test();
+ test.step(function() {
+ var client = new XMLHttpRequest();
+ client.onloadend = test.step_func(function(e) {
+ assert_true(e instanceof ProgressEvent);
+ assert_equals(e.type, "loadend");
+ test.done();
+ });
+ client.onreadystatechange = function() {
+ if (client.readyState !== 4) return;
+ setTimeout(test.step_func(function() {
+ assert_unreached("onloadend not called after 100 ms");
+ }), 100);
+ };
+ client.open("GET", "resources/well-formed.xml");
+ client.send(null);
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/event-loadstart.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/event-loadstart.htm
new file mode 100644
index 00000000000..5149003034d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/event-loadstart.htm
@@ -0,0 +1,31 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: loadstart event</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#handler-xhr-onloadstart" data-tested-assertations="../.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#event-xhr-loadstart" data-tested-assertations="../.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-send()-method" data-tested-assertations="following-sibling::ol/li[9]/ol/li[2]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test();
+ test.step(function() {
+ var client = new XMLHttpRequest();
+ client.onloadstart = test.step_func(function(e) {
+ assert_true(e instanceof ProgressEvent);
+ assert_equals(e.type, "loadstart");
+ assert_equals(client.readyState, 1);
+ test.done();
+ });
+ setTimeout(test.step_func(function () {
+ assert_unreached("onloadstart not called after 500 ms");
+ }), 500);
+ client.open("GET", "resources/well-formed.xml");
+ client.send(null);
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/event-progress.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/event-progress.htm
new file mode 100644
index 00000000000..31b35b77217
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/event-progress.htm
@@ -0,0 +1,29 @@
+<!doctype html>
+<html lang=en>
+<meta charset=utf-8>
+<title>XMLHttpRequest: The send() method: Fire a progress event named progress (synchronous flag is unset)</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="help" href="https://xhr.spec.whatwg.org/#handler-xhr-onprogress" data-tested-assertations="../.." />
+<link rel="help" href="https://xhr.spec.whatwg.org/#event-xhr-progress" data-tested-assertations="../.." />
+<link rel="help" href="https://xhr.spec.whatwg.org/#the-send()-method" data-tested-assertations="following::*//a[contains(@href,'#make-progress-notifications')]" />
+<link rel="help" href="https://xhr.spec.whatwg.org/#make-progress-notifications" data-tested-assertations=".." />
+<link rel="help" href="https://xhr.spec.whatwg.org/#switch-done" data-tested-assertations="following::li[5]" />
+<div id="log"></div>
+<script>
+ var test = async_test();
+ test.step(function() {
+ var client = new XMLHttpRequest();
+ client.onprogress = test.step_func(function(e) {
+ assert_true(e instanceof ProgressEvent);
+ assert_equals(e.type, "progress");
+ test.done();
+ });
+ client.onreadystatechange = test.step_func(function() {
+ if (client.readyState === 4)
+ assert_unreached("onprogress not called.");
+ });
+ client.open("GET", "resources/trickle.py");
+ client.send(null);
+ });
+</script>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/event-readystatechange-loaded.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/event-readystatechange-loaded.htm
new file mode 100644
index 00000000000..4368f8c9a5d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/event-readystatechange-loaded.htm
@@ -0,0 +1,38 @@
+<!doctype html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <title>XMLHttpRequest: the LOADING state change should only happen once</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-send()-method" data-tested-assertations="following::ol[1]/li[10]/dt[1]">
+ <link rel="help" href="https://xhr.spec.whatwg.org/#infrastructure-for-the-send()-method" data-tested-assertations="following::dt[7] following::a[contains(@href,'#switch-loading')]/..">
+ <link rel="help" href="https://xhr.spec.whatwg.org/#switch-loading" data-tested-assertations="following::ol[1]/li[1] following::ol[1]/li[2]">
+</head>
+
+<div id="log"></div>
+
+<script>
+
+var test = async_test();
+
+test.step(function() {
+ var client = new XMLHttpRequest();
+ var countedLoading = 0;
+
+ client.onreadystatechange = test.step_func(function() {
+ if (client.readyState === 3) {
+ countedLoading += 1;
+ }
+
+ if (client.readyState === 4) {
+ assert_equals(countedLoading, 1, "LOADING state change may only be emitted once");
+
+ test.done();
+ }
+ });
+
+ client.open("GET", "resources/trickle.py?count=10"); // default timeout in trickle.py is 1/2 sec, so this request will take 5 seconds to complete
+ client.send(null);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/event-timeout.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/event-timeout.htm
new file mode 100644
index 00000000000..3368efc4b9d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/event-timeout.htm
@@ -0,0 +1,34 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: timeout event</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#handler-xhr-ontimeout" data-tested-assertations="../.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#event-xhr-timeout" data-tested-assertations="../.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-timeout-attribute" data-tested-assertations="following-sibling::ol/li[2]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#timeout-error" data-tested-assertations=".." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#infrastructure-for-the-send()-method" data-tested-assertations="following-sibling::dl//code[contains(@title,'dom-XMLHttpRequest-timeout')]/.. following-sibling::dl//code[contains(@title,'dom-XMLHttpRequest-timeout')]/../following-sibling::dd" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test();
+ test.step(function() {
+ var client = new XMLHttpRequest();
+ client.ontimeout = function() {
+ test.step(function() {
+ assert_equals(client.readyState, 4);
+ test.done();
+ });
+ };
+ client.timeout = 5;
+ client.open("GET", "resources/delay.py?ms=20000");
+ client.send(null);
+ setTimeout(test.step_func(function () {
+ assert_unreached("ontimeout not called.");
+ }), 10);
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/event-upload-progress-crossorigin.sub.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/event-upload-progress-crossorigin.sub.htm
new file mode 100644
index 00000000000..6130bba50a2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/event-upload-progress-crossorigin.sub.htm
@@ -0,0 +1,26 @@
+<!doctype html>
+<html lang=en>
+<meta charset=utf-8>
+<title>XMLHttpRequest: upload progress event for cross-origin requests</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#handler-xhr-onprogress" data-tested-assertations="../.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-send()-method" data-tested-assertations="following::*//a[contains(@href,'#make-upload-progress-notifications')] following::ol[1]/li[8]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#make-upload-progress-notifications" data-tested-assertations=".. ../following::ul/li[1]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#dom-xmlhttprequest-upload" data-tested-assertations=".." />
+
+<div id="log"></div>
+<script>
+ var test = async_test();
+ test.step(function() {
+ var client = new XMLHttpRequest();
+ client.upload.onprogress = test.step_func(function() {
+ test.done();
+ });
+ client.onload = test.step_func(function() {
+ assert_unreached("onprogress not called.");
+ });
+ client.open("POST", "http://{{domains[www2]}}:{{ports[http][0]}}/XMLHttpRequest/resources/corsenabled.py");
+ client.send("This is a test string.");
+ });
+</script>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/event-upload-progress.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/event-upload-progress.htm
new file mode 100644
index 00000000000..98c76cc3fc3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/event-upload-progress.htm
@@ -0,0 +1,26 @@
+<!doctype html>
+<html lang=en>
+<meta charset=utf-8>
+<title>XMLHttpRequest: upload progress event</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#handler-xhr-onprogress" data-tested-assertations="../.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-send()-method" data-tested-assertations="following::*//a[contains(@href,'#make-upload-progress-notifications')] following::ol[1]/li[8]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#make-upload-progress-notifications" data-tested-assertations=".. ../following::ul/li[1]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#dom-xmlhttprequest-upload" data-tested-assertations=".." />
+
+<div id="log"></div>
+<script>
+ var test = async_test();
+ test.step(function() {
+ var client = new XMLHttpRequest();
+ client.upload.onprogress = test.step_func(function() {
+ test.done();
+ });
+ client.onreadystatechange = test.step_func(function() {
+ if (client.readyState === 4) assert_unreached("onprogress not called.");
+ });
+ client.open("POST", "resources/upload.py");
+ client.send("This is a test string.");
+ });
+</script>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/folder.txt b/tests/wpt/web-platform-tests/XMLHttpRequest/folder.txt
new file mode 100644
index 00000000000..bf1a1fdefa3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/folder.txt
@@ -0,0 +1 @@
+top
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/formdata-blob.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/formdata-blob.htm
new file mode 100644
index 00000000000..5efef7b615b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/formdata-blob.htm
@@ -0,0 +1,46 @@
+<!doctype html>
+<html lang=en>
+<meta charset=utf-8>
+<title>XMLHttpRequest: upload formdata with blob</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#interface-formdata" data-tested-assertations="following::P[1]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#dom-formdata" data-tested-assertations="following::P[2]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#dom-formdata-append" data-tested-assertations=".. following::P[1]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#dom-formdata-append" data-tested-assertations="following::P[2] following::UL[1]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#dom-XMLHttpRequest-send-FormData" data-tested-assertations="following::DD[1]" />
+<div id="log"></div>
+<script>
+ function do_test (name, fd, expected) {
+ var test = async_test(name);
+ test.step(function() {
+ var client = new XMLHttpRequest();
+ client.onreadystatechange = test.step_func(function () {
+ if (client.readyState !== 4) return;
+ assert_equals(client.responseText, expected);
+ test.done();
+ });
+ client.open("POST", "resources/upload.py");
+ client.send(fd);
+ });
+ }
+
+ function create_formdata () {
+ var fd = new FormData();
+ for (var i = 0; i < arguments.length; i++) {
+ fd.append.apply(fd, arguments[i]);
+ }
+ return fd;
+ }
+
+ do_test("formdata with blob", create_formdata(['key', new Blob(['value'], {type: 'text/x-value'})]), '\nkey=blob:text/x-value:5,');
+ do_test("formdata with named blob", create_formdata(['key', new Blob(['value'], {type: 'text/x-value'}), 'blob.txt']), '\nkey=blob.txt:text/x-value:5,');
+ // If 3rd argument is given and 2nd is not a Blob, formdata.append() should throw
+ var test = async_test('formdata.append() should throw if value is string and file name is given'); // needs to be async just because the others above are
+ test.step(function(){
+ assert_throws(new TypeError(), function(){
+ create_formdata('a', 'b', 'c');
+ });
+ });
+ test.done();
+</script>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/formdata.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/formdata.htm
new file mode 100644
index 00000000000..e0d0a4e1d4b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/formdata.htm
@@ -0,0 +1,43 @@
+<!doctype html>
+<html lang=en>
+<meta charset=utf-8>
+<title>XMLHttpRequest: upload formdata</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#interface-formdata" data-tested-assertations="following::P[1]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#dom-formdata" data-tested-assertations=".. following::P[1]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#dom-formdata-append" data-tested-assertations=".. following::UL[1]/LI[1] following::UL[1]/LI[2] following::UL[1]/LI[3]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#dom-XMLHttpRequest-send-FormData" data-tested-assertations="following::DD[1]" />
+<div id="log"></div>
+<form id="form">
+ <input type="hidden" name="key" value="value">
+</form>
+<script>
+ function do_test (name, fd, expected) {
+ var test = async_test(name);
+ test.step(function() {
+ var client = new XMLHttpRequest();
+ client.onreadystatechange = test.step_func(function () {
+ if (client.readyState !== 4) return;
+ assert_equals(client.responseText, expected);
+ test.done();
+ });
+ client.open("POST", "resources/upload.py");
+ client.send(fd);
+ });
+ }
+
+ function create_formdata () {
+ var fd = new FormData();
+ for (var i = 0; i < arguments.length; i++) {
+ fd.append.apply(fd, arguments[i]);
+ };
+ return fd;
+ }
+
+ do_test("empty formdata", new FormData(), '\n');
+ do_test("formdata with string", create_formdata(['key', 'value']), 'key=value,\n');
+ do_test("formdata with named string", create_formdata(['key', new Blob(['value'], {type: 'text/plain'}), 'kv.txt']), '\nkey=kv.txt:text/plain:5,');
+ do_test("formdata from form", new FormData(document.getElementById('form')), 'key=value,\n');
+
+</script>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/getallresponseheaders-cookies.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/getallresponseheaders-cookies.htm
new file mode 100644
index 00000000000..2cd80981859
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/getallresponseheaders-cookies.htm
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>XMLHttpRequest: getAllResponseHeaders() excludes cookies</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#dom-xmlhttprequest-getallresponseheaders" data-tested-assertations="/following::OL[1]/LI[1] /following::OL[1]/LI[3]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+ var client = new XMLHttpRequest()
+ assert_equals(client.getAllResponseHeaders(), "")
+ client.onreadystatechange = function() {
+ test.step(function() {
+ var headers = client.getAllResponseHeaders().toLowerCase()
+ if(client.readyState == 1) {
+ assert_equals(headers, "")
+ }
+ if(client.readyState > 1) {
+ assert_true(headers.indexOf("\r\n") != -1, "carriage return")
+ assert_true(headers.indexOf("content-type") != -1, "content-type")
+ assert_true(headers.indexOf("x-custom-header") != -1, "x-custom-header")
+ assert_false(headers.indexOf("set-cookie") != -1, "set-cookie")
+ assert_false(headers.indexOf("set-cookie2") != -1, "set-cookie2")
+ }
+ if(client.readyState == 4)
+ test.done()
+ })
+ }
+ client.open("GET", "resources/headers.py")
+ client.send(null)
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/getallresponseheaders-status.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/getallresponseheaders-status.htm
new file mode 100644
index 00000000000..b4afc61c469
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/getallresponseheaders-status.htm
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>XMLHttpRequest: getAllResponseHeaders() excludes status</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#dom-xmlhttprequest-getallresponseheaders" data-tested-assertations="/following::OL[1]/LI[1] /following::OL[1]/LI[3]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+ var client = new XMLHttpRequest()
+ client.onreadystatechange = function() {
+ test.step(function() {
+ var headers = client.getAllResponseHeaders().toLowerCase()
+ if(client.readyState == 1) {
+ assert_equals(headers, "")
+ }
+ if(client.readyState > 1) {
+ assert_false(headers.indexOf("200 ok") != -1)
+ assert_false(headers.indexOf("http/1.") != -1)
+ }
+ if(client.readyState == 4)
+ test.done()
+ })
+ }
+ client.open("GET", "resources/headers.py")
+ client.send(null)
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/getresponseheader-case-insensitive.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/getresponseheader-case-insensitive.htm
new file mode 100644
index 00000000000..8e0537edf17
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/getresponseheader-case-insensitive.htm
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>XMLHttpRequest: getResponseHeader() case-insensitive matching</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#dom-xmlhttprequest-getresponseheader" data-tested-assertations="following::OL[1]/LI[4] following::OL[1]/LI[5] following::OL[1]/LI[6]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+ var client = new XMLHttpRequest()
+ client.onreadystatechange = function() {
+ test.step(function() {
+ if(client.readyState == 4) {
+ assert_equals(client.getResponseHeader("x-custom-header"), "test")
+ assert_equals(client.getResponseHeader("X-Custom-Header"), "test")
+ assert_equals(client.getResponseHeader("X-CUSTOM-HEADER"), "test")
+ assert_equals(client.getResponseHeader("X-custom-HEADER"), "test")
+ assert_equals(client.getResponseHeader("X-CUSTOM-header-COMMA"), "1, 2")
+ assert_equals(client.getResponseHeader("X-CUSTOM-no-such-header-in-response"), null)
+ assert_true(client.getResponseHeader("CONTENT-TYPE").indexOf("text/plain") != -1)
+ test.done()
+ }
+ })
+ }
+ client.open("GET", "resources/headers.py")
+ client.send(null)
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/getresponseheader-chunked-trailer.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/getresponseheader-chunked-trailer.htm
new file mode 100644
index 00000000000..3cbdb9c068c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/getresponseheader-chunked-trailer.htm
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>XMLHttpRequest: getResponseHeader() and HTTP trailer</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#dom-xmlhttprequest-getresponseheader" data-tested-assertations="/following::OL[1]/LI[4] /following::OL[1]/LI[5] /following::OL[1]/LI[6]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+ var client = new XMLHttpRequest()
+ client.onreadystatechange = function() {
+ test.step(function() {
+ if(client.readyState == 4) {
+ assert_equals(client.getResponseHeader('Trailer'), 'X-Test-Me')
+ assert_equals(client.getResponseHeader('X-Test-Me'), null)
+ assert_equals(client.getAllResponseHeaders().indexOf('Trailer header value'), -1)
+ assert_regexp_match(client.getAllResponseHeaders(), /Trailer:\sX-Test-Me/)
+ assert_equals(client.responseText, "First chunk\r\nSecond chunk\r\nYet another (third) chunk\r\nYet another (fourth) chunk\r\n")
+ test.done()
+ }
+ })
+ }
+ client.open("GET", "resources/chunked.py")
+ client.send(null)
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/getresponseheader-cookies-and-more.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/getresponseheader-cookies-and-more.htm
new file mode 100644
index 00000000000..053fe441faf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/getresponseheader-cookies-and-more.htm
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>XMLHttpRequest: getResponseHeader() custom/non-existent headers and cookies</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#dom-xmlhttprequest-getresponseheader" data-tested-assertations="following::OL[1]/LI[3] following::OL[1]/LI[5] following::OL[1]/LI[6]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+ var client = new XMLHttpRequest()
+ client.onreadystatechange = function() {
+ test.step(function() {
+ if(client.readyState == 1) {
+ assert_equals(client.getResponseHeader("x-custom-header"), null)
+ }
+ if(client.readyState > 1) {
+ assert_equals(client.getResponseHeader("x-custom-header"), "test")
+ assert_equals(client.getResponseHeader("x-custom-header-empty"), "")
+ assert_equals(client.getResponseHeader("set-cookie"), null)
+ assert_equals(client.getResponseHeader("set-cookie2"), null)
+ assert_equals(client.getResponseHeader("x-non-existent-header"), null)
+ }
+ if(client.readyState == 4)
+ test.done()
+ })
+ }
+ client.open("GET", "resources/headers.py")
+ client.send(null)
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/getresponseheader-error-state.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/getresponseheader-error-state.htm
new file mode 100644
index 00000000000..c9695fdee0f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/getresponseheader-error-state.htm
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>XMLHttpRequest: getResponseHeader() in error state (failing cross-origin test)</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#dom-xmlhttprequest-getresponseheader" data-tested-assertations="following::OL[1]/LI[2]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+
+ var client = new XMLHttpRequest()
+ client.onreadystatechange = function() {
+ test.step(function() {
+ if(client.readyState == 1) {
+ assert_equals(client.getResponseHeader("x-custom-header"), null)
+ }
+ if(client.readyState > 1) {
+ assert_equals(client.getResponseHeader("x-custom-header"), null)
+ }
+ if(client.readyState == 4){
+ assert_equals(client.getResponseHeader("x-custom-header"), null)
+ test.done()
+ }
+ })
+ }
+ var url = location.protocol + "//" + 'www1.' + location.host + (location.pathname.replace(/getresponseheader-error-state\.htm/, 'resources/nocors/folder.txt'))
+ client.open("GET", url)
+ client.send(null)
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/getresponseheader-server-date.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/getresponseheader-server-date.htm
new file mode 100644
index 00000000000..409bc350390
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/getresponseheader-server-date.htm
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>XMLHttpRequest: getResponseHeader() server and date</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#dom-xmlhttprequest-getresponseheader" data-tested-assertations="/following::OL[1]/LI[4] /following::OL[1]/LI[5] /following::OL[1]/LI[6]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+ var client = new XMLHttpRequest()
+ client.onreadystatechange = function() {
+ test.step(function() {
+ if(client.readyState == 4) {
+ assert_true(client.getResponseHeader("Server") != null)
+ assert_true(client.getResponseHeader("Date") != null)
+ test.done()
+ }
+ })
+ }
+ client.open("GET", "resources/headers.py")
+ client.send(null)
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/getresponseheader-special-characters.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/getresponseheader-special-characters.htm
new file mode 100644
index 00000000000..980f8481c7e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/getresponseheader-special-characters.htm
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>XMLHttpRequest: getResponseHeader() funny characters</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#dom-xmlhttprequest-getresponseheader" data-tested-assertations="/following::OL[1]/LI[5] /following::OL[1]/LI[6]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+ var client = new XMLHttpRequest()
+ client.onreadystatechange = function() {
+ test.step(function() {
+ if(client.readyState == 4) {
+ assert_equals(client.getResponseHeader("x-custom-header "), null)
+ assert_equals(client.getResponseHeader(" x-custom-header"), null)
+ assert_equals(client.getResponseHeader("x-custom-header-bytes"), "\xE2\x80\xA6")
+ assert_equals(client.getResponseHeader("x¾"), null)
+ assert_equals(client.getResponseHeader("x-custom-header\n"), null)
+ assert_equals(client.getResponseHeader("\nx-custom-header"), null)
+ assert_equals(client.getResponseHeader("x-custom-header:"), null)
+ test.done()
+ }
+ })
+ }
+ client.open("GET", "resources/headers.py")
+ client.send(null)
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/getresponseheader-unsent-opened-state.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/getresponseheader-unsent-opened-state.htm
new file mode 100644
index 00000000000..e3bc2720f12
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/getresponseheader-unsent-opened-state.htm
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>XMLHttpRequest: getResponseHeader() in unsent, opened states</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#dom-xmlhttprequest-getresponseheader" data-tested-assertations="/following::OL[1]/LI[1]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+ var client = new XMLHttpRequest()
+ assert_equals(client.getResponseHeader("x-custom-header"), null)
+ client.onreadystatechange = function() {
+ test.step(function() {
+ if(client.readyState < 2) {
+ assert_equals(client.getResponseHeader("x-custom-header"), null)
+ assert_equals(client.getResponseHeader("CONTENT-TYPE"), null)
+ test.done()
+ }
+ })
+ }
+ client.open("GET", "resources/headers.py")
+ assert_equals(client.getResponseHeader("x-custom-header"), null)
+ assert_equals(client.getResponseHeader("Date"), null)
+ client.send(null)
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/interfaces.html b/tests/wpt/web-platform-tests/XMLHttpRequest/interfaces.html
new file mode 100644
index 00000000000..96de3c00f94
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/interfaces.html
@@ -0,0 +1,171 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>XMLHttpRequest IDL tests</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=/resources/WebIDLParser.js></script>
+<script src=/resources/idlharness.js></script>
+
+<h1>XMLHttpRequest IDL tests</h1>
+<div id=log></div>
+
+<script type=text/plain class=untested>
+[Constructor(DOMString type, optional EventInit eventInitDict)/*,
+ Exposed=(Window,Worker)*/]
+interface Event {
+ readonly attribute DOMString type;
+ readonly attribute EventTarget? target;
+ readonly attribute EventTarget? currentTarget;
+
+ const unsigned short NONE = 0;
+ const unsigned short CAPTURING_PHASE = 1;
+ const unsigned short AT_TARGET = 2;
+ const unsigned short BUBBLING_PHASE = 3;
+ readonly attribute unsigned short eventPhase;
+
+ void stopPropagation();
+ void stopImmediatePropagation();
+
+ readonly attribute boolean bubbles;
+ readonly attribute boolean cancelable;
+ void preventDefault();
+ readonly attribute boolean defaultPrevented;
+
+ [Unforgeable] readonly attribute boolean isTrusted;
+ readonly attribute DOMTimeStamp timeStamp;
+
+ void initEvent(DOMString type, boolean bubbles, boolean cancelable);
+};
+
+dictionary EventInit {
+ boolean bubbles = false;
+ boolean cancelable = false;
+};
+
+/*[Exposed=(Window,Worker)]*/
+interface EventTarget {
+ void addEventListener(DOMString type, EventListener? callback, optional boolean capture = false);
+ void removeEventListener(DOMString type, EventListener? callback, optional boolean capture = false);
+ boolean dispatchEvent(Event event);
+};
+</script>
+<script type=text/plain class=untested>
+[TreatNonCallableAsNull]
+callback EventHandlerNonNull = any (Event event);
+typedef EventHandlerNonNull? EventHandler;
+</script>
+<script type=text/plain>
+/*[Exposed=(Window,Worker)]*/
+interface XMLHttpRequestEventTarget : EventTarget {
+ // event handlers
+ attribute EventHandler onloadstart;
+ attribute EventHandler onprogress;
+ attribute EventHandler onabort;
+ attribute EventHandler onerror;
+ attribute EventHandler onload;
+ attribute EventHandler ontimeout;
+ attribute EventHandler onloadend;
+};
+
+/*[Exposed=(Window,Worker)]*/
+interface XMLHttpRequestUpload : XMLHttpRequestEventTarget {
+};
+
+enum XMLHttpRequestResponseType {
+ "",
+ "arraybuffer",
+ "blob",
+ "document",
+ "json",
+ "text"
+};
+
+[Constructor/*,
+ Exposed=(Window,Worker)*/]
+interface XMLHttpRequest : XMLHttpRequestEventTarget {
+ // event handler
+ attribute EventHandler onreadystatechange;
+
+ // states
+ const unsigned short UNSENT = 0;
+ const unsigned short OPENED = 1;
+ const unsigned short HEADERS_RECEIVED = 2;
+ const unsigned short LOADING = 3;
+ const unsigned short DONE = 4;
+ readonly attribute unsigned short readyState;
+
+ // request
+ void open(ByteString method, USVString url);
+ void open(ByteString method, USVString url, boolean async, optional USVString? username = null, optional USVString? password = null);
+ void setRequestHeader(ByteString name, ByteString value);
+ attribute unsigned long timeout;
+ attribute boolean withCredentials;
+ readonly attribute XMLHttpRequestUpload upload;
+ void send(optional (Document or BodyInit)? body = null);
+ void abort();
+
+ // response
+ readonly attribute USVString responseURL;
+ readonly attribute unsigned short status;
+ readonly attribute ByteString statusText;
+ ByteString? getResponseHeader(ByteString name);
+ ByteString getAllResponseHeaders();
+ void overrideMimeType(DOMString mime);
+ attribute XMLHttpRequestResponseType responseType;
+ readonly attribute any response;
+ readonly attribute USVString responseText;
+ [Exposed=Window] readonly attribute Document? responseXML;
+};
+
+typedef (File or USVString) FormDataEntryValue;
+
+[Constructor(optional HTMLFormElement form)/*,
+ Exposed=(Window,Worker)*/]
+interface FormData {
+ void append(USVString name, Blob value, optional USVString filename);
+ void append(USVString name, USVString value);
+ void delete(USVString name);
+ FormDataEntryValue? get(USVString name);
+ sequence<FormDataEntryValue> getAll(USVString name);
+ boolean has(USVString name);
+ void set(USVString name, Blob value, optional USVString filename);
+ void set(USVString name, USVString value);
+ /*iterable<USVString, FormDataEntryValue>;*/
+};
+
+[Constructor(DOMString type, optional ProgressEventInit eventInitDict)/*,
+ Exposed=(Window,Worker)*/]
+interface ProgressEvent : Event {
+ readonly attribute boolean lengthComputable;
+ readonly attribute unsigned long long loaded;
+ readonly attribute unsigned long long total;
+};
+
+dictionary ProgressEventInit : EventInit {
+ boolean lengthComputable = false;
+ unsigned long long loaded = 0;
+ unsigned long long total = 0;
+};
+</script>
+<script>
+"use strict";
+var form;
+var idlArray;
+setup(function() {
+ form = document.createElement("form");
+ idlArray = new IdlArray();
+ [].forEach.call(document.querySelectorAll("script[type=text\\/plain]"), function(node) {
+ if (node.className == "untested") {
+ idlArray.add_untested_idls(node.textContent);
+ } else {
+ idlArray.add_idls(node.textContent);
+ }
+ });
+ idlArray.add_objects({
+ XMLHttpRequest: ['new XMLHttpRequest()'],
+ XMLHttpRequestUpload: ['(new XMLHttpRequest()).upload'],
+ FormData: ['new FormData()', 'new FormData(form)']
+ });
+});
+idlArray.test();
+</script>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/open-after-abort.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/open-after-abort.htm
new file mode 100644
index 00000000000..ca8a4e1e62f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/open-after-abort.htm
@@ -0,0 +1,35 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: open() after abort()</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-open()-method" data-tested-assertations="following::ol/li[15] following::ol/li[15]/ol/li[1] following::ol/li[15]/ol/li[2]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+ 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)
+ })
+ }
+ client.open("GET", "resources/well-formed.xml")
+ assert_equals(client.readyState, 1)
+ client.send(null)
+ client.abort()
+ assert_equals(client.readyState, 0)
+ client.open("GET", "resources/well-formed.xml")
+ assert_equals(client.readyState, 1)
+ assert_array_equals(result, expected)
+ })
+ test.done()
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/open-after-setrequestheader.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/open-after-setrequestheader.htm
new file mode 100644
index 00000000000..525edbfc1ab
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/open-after-setrequestheader.htm
@@ -0,0 +1,33 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: open() after setRequestHeader()</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-open()-method" data-tested-assertations="following::ol/li[14]/ul/li[4]" />
+
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+ var client = new XMLHttpRequest()
+ client.onreadystatechange = function() {
+ test.step(function() {
+ if(client.readyState === 4){
+ assert_equals(client.responseText, '')
+ test.done()
+ }
+ })
+ }
+ client.open("GET", "resources/inspect-headers.py?filter_name=X-foo")
+ assert_equals(client.readyState, 1)
+ client.setRequestHeader('X-foo', 'bar')
+ client.open("GET", "resources/inspect-headers.py?filter_name=X-foo")
+ assert_equals(client.readyState, 1)
+ client.send()
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/open-during-abort.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/open-during-abort.htm
new file mode 100755
index 00000000000..1d01415d55b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/open-during-abort.htm
@@ -0,0 +1,32 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: open() during abort()</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ test(function() {
+ var client = new XMLHttpRequest(),
+ abort_flag = false,
+ result = [],
+ expected = [1, 4, 1] // open() => 1, abort() => 4, open() => 1
+
+ client.onreadystatechange = this.step_func(function() {
+ result.push(client.readyState)
+ if (abort_flag) {
+ abort_flag = false
+ client.open("GET", "...")
+ }
+ })
+ client.open("GET", "resources/well-formed.xml")
+ client.send(null)
+ abort_flag = true
+ client.abort()
+ assert_array_equals(result, expected)
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/open-method-bogus.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/open-method-bogus.htm
new file mode 100644
index 00000000000..263e7b6db7e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/open-method-bogus.htm
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>XMLHttpRequest: open() - bogus methods</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-open()-method" data-tested-assertations="following::ol[1]/li[4]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ function method(method) {
+ test(function() {
+ var client = new XMLHttpRequest()
+ assert_throws("SyntaxError", function() { client.open(method, "...") })
+ }, document.title + " (" + method + ")")
+ }
+ method("")
+ method(">")
+ method(" GET")
+ method("G T")
+ method("@GET")
+ method("G:ET")
+ method("GET?")
+ method("GET\n")
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/open-method-case-insensitive.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/open-method-case-insensitive.htm
new file mode 100644
index 00000000000..103381745a7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/open-method-case-insensitive.htm
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>XMLHttpRequest: open() - case-insensitive methods test</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-open()-method" data-tested-assertations="following::ol/li[5]" />
+
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ function method(method) {
+ test(function() {
+ var client = new XMLHttpRequest()
+ client.open(method, "resources/content.py", false)
+ client.send(null)
+ assert_equals(client.getResponseHeader("x-request-method"), method.toUpperCase())
+ }, document.title + " (" + method.toUpperCase() + ")")
+ }
+ method("deLETE")
+ method("get")
+ method("heAd")
+ method("OpTIOns")
+ method("post")
+ method("Put")
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/open-method-case-sensitive.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/open-method-case-sensitive.htm
new file mode 100644
index 00000000000..270e32d67a3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/open-method-case-sensitive.htm
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>XMLHttpRequest: open() - case-sensitive methods test</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-open()-method" data-tested-assertations="following::ol/li[5]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ function method(method) {
+ test(function() {
+ var client = new XMLHttpRequest()
+ client.open(method, "resources/content.py", false)
+ client.send(null)
+ assert_equals(client.getResponseHeader("x-request-method"), method)
+ }, document.title + " (" + method + ")")
+ }
+ method("XUNICORN")
+ method("xUNIcorn")
+ method("chiCKEN")
+ method("PATCH")
+ method("patCH")
+ method("copy")
+ method("COpy")
+ method("inDEX")
+ method("movE")
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/open-method-insecure.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/open-method-insecure.htm
new file mode 100644
index 00000000000..1a77ff3ec79
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/open-method-insecure.htm
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>XMLHttpRequest: open() - "insecure" methods</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-open()-method" data-tested-assertations="following::ol/li[5] following::ol/li[6]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ function method(method) {
+ test(function() {
+ var client = new XMLHttpRequest()
+ assert_throws("SecurityError", function() { client.open(method, "...") })
+ }, document.title + " (" + method + ")")
+ }
+ method("track")
+ method("TRACK")
+ method("trAck")
+ method("TRACE")
+ method("trace")
+ method("traCE")
+ method("connect")
+ method("CONNECT")
+ method("connECT")
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/open-method-responsetype-set-sync.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/open-method-responsetype-set-sync.htm
new file mode 100644
index 00000000000..543a1390cdd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/open-method-responsetype-set-sync.htm
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>XMLHttpRequest: open() sync request not allowed if responseType is set</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-open()-method" data-tested-assertations="following::ol[1]/li[4]" />
+
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ // Note: the case of calling synchronous open() first, and then setting
+ // responseType, is tested in responsetype.html.
+ function request(type) {
+ test(function() {
+ var client = new XMLHttpRequest()
+ client.responseType = type
+ assert_throws("InvalidAccessError", function() { client.open('GET', "...", false) })
+ }, document.title + " (" + type + ")")
+ }
+ request("arraybuffer")
+ request("blob")
+ request("json")
+ request("text")
+ request("document")
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/open-open-send.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/open-open-send.htm
new file mode 100644
index 00000000000..ebc1801ab53
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/open-open-send.htm
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>XMLHttpRequest: open() - open() - send()</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-open()-method" data-tested-assertations="following::ol/li[14]/ul/li[1] following::ol/li[14]/ul/li[2] following::ol/li[15]/ol/li[1] following::ol/li[15]/ol/li[2]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+ var client = new XMLHttpRequest(),
+ result = [],
+ expected = [1,2,3,4]
+ client.onreadystatechange = function() {
+ test.step(function() {
+ result.push(client.readyState)
+ if(4 == client.readyState) {
+ assert_array_equals(result, expected)
+ assert_equals(client.responseText, 'top\n')
+ test.done()
+ }
+ })
+ }
+ client.open("GET", "resources/folder.txt")
+ client.open("GET", "folder.txt")
+ client.send(null)
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/open-open-sync-send.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/open-open-sync-send.htm
new file mode 100644
index 00000000000..b0badfd8aa0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/open-open-sync-send.htm
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>XMLHttpRequest: open() - open() (sync) - send()</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-open()-method" data-tested-assertations="following::ol/li[14]/ul/li[1] following::ol/li[14]/ul/li[2] following::ol/li[14]/ul/li[3] following::ol/li[15]/ol/li[1] following::ol/li[15]/ol/li[2]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+ var client = new XMLHttpRequest(),
+ result = [],
+ expected = [1,4]
+ client.onreadystatechange = function() {
+ test.step(function() {
+ result.push(client.readyState)
+ })
+ }
+ client.open("GET", "folder.txt")
+ client.open("GET", "folder.txt", false)
+ client.send(null)
+ assert_equals(client.responseText, 'top\n')
+ assert_array_equals(result, expected)
+ test.done()
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/open-referer.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/open-referer.htm
new file mode 100644
index 00000000000..4ffdfe0c5d5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/open-referer.htm
@@ -0,0 +1,20 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: open() - value of Referer header</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-open()-method" data-tested-assertations="/following::ol[1]/li[2]/ol[1]/li[4]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ test(function() {
+ var client = new XMLHttpRequest()
+ client.open("POST", "resources/inspect-headers.py?filter_name=referer", false)
+ client.send(null)
+ assert_equals(client.responseText, "referer: "+location.href+'\n')
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/open-send-open.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/open-send-open.htm
new file mode 100644
index 00000000000..d57592c0ba3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/open-send-open.htm
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>XMLHttpRequest: open() - send() - open()</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-open()-method" data-tested-assertations="following::ol/li[14]/ul/li[1] following::ol/li[14]/ul/li[2] following::ol/li[15]/ol/li[1] following::ol/li[15]/ol/li[2]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+ var client = new XMLHttpRequest(),
+ result = [],
+ expected = [1, 'a', 'b', 'c']
+ client.onreadystatechange = function() {
+ test.step(function() {
+ result.push(client.readyState)
+ })
+ }
+ client.open("GET", "folder.txt")
+ result.push('a')
+ client.send()
+ result.push('b')
+ client.open("GET", "folder.txt")
+ result.push('c')
+ assert_array_equals(result, expected)
+ test.done()
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/open-sync-open-send.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/open-sync-open-send.htm
new file mode 100644
index 00000000000..cc81c522394
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/open-sync-open-send.htm
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>XMLHttpRequest: open() (sync) - send() - open()</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-open()-method" data-tested-assertations="following::ol[1]/li[14]/ul/li[1] following::ol[1]/li[14]/ul/li[2] following::ol[1]/li[14]/ul/li[3] following::ol[1]/li[15]/ol/li[1] following::ol[1]/li[15]/ol/li[2]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-responsexml-attribute" data-tested-assertations="following::ol[1]/li[2]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-responsetext-attribute" data-tested-assertations="following::ol[1]/li[2]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-status-attribute" data-tested-assertations="following::ol[1]/li[1]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-statustext-attribute" data-tested-assertations="following::ol[1]/li[1]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-getallresponseheaders()-method" data-tested-assertations="following::ol[1]/li[1]" />
+
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+ var client = new XMLHttpRequest(),
+ result = [],
+ expected = [1]
+ client.onreadystatechange = function() {
+ test.step(function() {
+ result.push(client.readyState)
+ })
+ }
+ client.open("GET", "folder.txt")
+ client.send(null)
+ client.open("GET", "folder.txt", false)
+ assert_array_equals(result, expected)
+ assert_equals(client.responseXML, null)
+ assert_equals(client.responseText, "")
+ assert_equals(client.status, 0)
+ assert_equals(client.statusText, "")
+ assert_equals(client.getAllResponseHeaders(), "")
+ test.done()
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/open-url-about-blank-window.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/open-url-about-blank-window.htm
new file mode 100644
index 00000000000..5be3b77ddfe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/open-url-about-blank-window.htm
@@ -0,0 +1,23 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: open() resolving URLs (about:blank iframe)</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-open()-method" data-tested-assertations="following::ol/li[2]/ol/li[2] following::ol/li[7] following::ol/li[14]/ul/li[2]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-responsetext-attribute" data-tested-assertations="following::ol/li[4]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#concept-xmlhttprequest-document" data-tested-assertations=".." />
+ </head>
+ <body>
+ <div id="log"></div>
+ <iframe src="about:blank"></iframe>
+ <script>
+ test(function() {
+ var client = new self[0].XMLHttpRequest()
+ client.open("GET", "folder.txt", false)
+ client.send("")
+ assert_equals(client.responseText, "top\n")
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/open-url-base-inserted-after-open.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/open-url-base-inserted-after-open.htm
new file mode 100644
index 00000000000..a4d641fafcf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/open-url-base-inserted-after-open.htm
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>XMLHttpRequest: open() resolving URLs - insert &lt;base> after open()</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-open()-method" data-tested-assertations="following::ol/li[2]/ol/li[2] following::ol/li[7] following::ol/li[14]/ul/li[2]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-responsetext-attribute" data-tested-assertations="following::ol/li[4]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ test(function() {
+ var client = new XMLHttpRequest(),
+ base = document.createElement("base")
+ base.href = location.href.replace(/\/[^/]*$/, '') + "/resources/"
+ client.open("GET", "folder.txt", false)
+ document.getElementsByTagName("head")[0].appendChild(base)
+ client.send(null)
+ assert_equals(client.responseText, "top\n")
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/open-url-base-inserted.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/open-url-base-inserted.htm
new file mode 100644
index 00000000000..69ad6193d8e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/open-url-base-inserted.htm
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>XMLHttpRequest: open() resolving URLs - insert &lt;base></title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-open()-method" data-tested-assertations="following::ol/li[2]/ol/li[2] following::ol/li[7] following::ol/li[14]/ul/li[2]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-responsetext-attribute" data-tested-assertations="following::ol/li[4]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ test(function() {
+ var client = new XMLHttpRequest(),
+ base = document.createElement("base")
+ base.href = location.href.replace(/\/[^/]*$/, '') + "/resources/"
+ document.getElementsByTagName("head")[0].appendChild(base)
+ client.open("GET", "folder.txt", false)
+ client.send(null)
+ assert_equals(client.responseText, "bottom\n")
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/open-url-base.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/open-url-base.htm
new file mode 100644
index 00000000000..3c0e8c99d51
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/open-url-base.htm
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>XMLHttpRequest: open() resolving URLs - &lt;base></title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <base href="./resources/">
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-open()-method" data-tested-assertations="following::ol/li[2]/ol/li[2] following::ol/li[7] following::ol/li[14]/ul/li[2]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-responsetext-attribute" data-tested-assertations="following::ol/li[4]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ test(function() {
+ var client = new XMLHttpRequest()
+ client.open("GET", "folder.txt", false)
+ client.send(null)
+ assert_equals(client.responseText, "bottom\n")
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/open-url-bogus.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/open-url-bogus.htm
new file mode 100644
index 00000000000..a4e296d5709
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/open-url-bogus.htm
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>XMLHttpRequest: open() - bogus URLs</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-open()-method" data-tested-assertations="following::ol/li[7] following::ol/li[8]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ function url(url) {
+ test(function() {
+ var client = new XMLHttpRequest()
+ assert_throws("SyntaxError", function() { client.open("GET", url) })
+ }, document.title + " (" + url + ")")
+ }
+ url("http:")
+ url("http://a a/")
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/open-url-encoding.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/open-url-encoding.htm
new file mode 100644
index 00000000000..a545d41b2a9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/open-url-encoding.htm
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=windows-1252>
+ <title>XMLHttpRequest: open() - URL encoding</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-open()-method" data-tested-assertations="following::ol/li[7] following::ol/li[14]/ul/li[2]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ test(function() {
+ var client = new XMLHttpRequest()
+ client.open("GET", "resources/content.py?", false)
+ client.send(null)
+ assert_equals(client.getResponseHeader("x-request-query"), "%C3%9F")
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/open-url-fragment.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/open-url-fragment.htm
new file mode 100644
index 00000000000..6b3fdeb8ae8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/open-url-fragment.htm
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>XMLHttpRequest: open() resolving URLs - fragment identifier</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-open()-method" data-tested-assertations="following::ol[1]/li[7]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ test(function() {
+ var client = new XMLHttpRequest()
+ client.open("GET", "folder.txt#foobar", false)
+ client.send(null)
+ assert_equals(client.responseText, "top\n")
+ })
+ test(function() {
+ var client = new XMLHttpRequest()
+ client.open("GET", "resources/requri.py#foobar", false)
+ client.send(null)
+ assert_regexp_match(client.responseText, /XMLHttpRequest\/resources\/requri\.py$/)
+ }, 'make sure fragment is removed from URL before request')
+ test(function() {
+ var client = new XMLHttpRequest()
+ client.open("GET", "resources/requri.py?help=#foobar", false)
+ client.send(null)
+ assert_regexp_match(client.responseText, /XMLHttpRequest\/resources\/requri\.py\?help=$/)
+ }, 'make sure fragment is removed from URL before request (with query string)')
+ test(function() {
+ var client = new XMLHttpRequest()
+ client.open("GET", "resources/requri.py?" +encodeURIComponent("#foobar"), false)
+ client.send(null)
+ assert_regexp_match(client.responseText, /XMLHttpRequest\/resources\/requri\.py\?%23foobar$/)
+ }, 'make sure escaped # is not removed')
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/open-url-javascript-window-2.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/open-url-javascript-window-2.htm
new file mode 100644
index 00000000000..f5ddd424976
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/open-url-javascript-window-2.htm
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>XMLHttpRequest: open() - resolving URLs (javascript: &lt;iframe>; 2)</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-open()-method" data-tested-assertations="following::ol[1]/li[2]/ol[1]/li[2] following::ol[1]/li[7] following::ol[1]/li[14]/ul/li[2]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+ var iframe = document.body.appendChild(document.createElement("iframe"))
+ iframe.src = "javascript:parent.test.step(function() { var x = new XMLHttpRequest(); x.open('GET', 'folder.txt', false); x.send(null); parent.assert_equals(x.responseText, 'top\\n'); parent.test.done() })"
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/open-url-javascript-window.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/open-url-javascript-window.htm
new file mode 100644
index 00000000000..cd208d51ad3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/open-url-javascript-window.htm
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>XMLHttpRequest: open() - resolving URLs (javascript: &lt;iframe>; 1)</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-open()-method" data-tested-assertations="following::ol[1]/li[2]/ol[1]/li[2] following::ol[1]/li[7] following::ol[1]/li[14]/ul/li[2]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ function request() {
+ test.step(function() {
+ var x = new XMLHttpRequest()
+ x.open("GET", "folder.txt", false)
+ x.send(null)
+ assert_equals(x.responseText, "top\n")
+ test.done()
+ })
+ }
+ test.step(function() {
+ var iframe = document.body.appendChild(document.createElement("iframe"))
+ iframe.src = "javascript:parent.request()"
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/open-url-multi-window-2.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/open-url-multi-window-2.htm
new file mode 100644
index 00000000000..398764e7050
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/open-url-multi-window-2.htm
@@ -0,0 +1,24 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: open() resolving URLs (multi-Window; 2; evil)</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-open()-method" data-tested-assertations="following::ol[1]/li[2]/ol[1]/li[1]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ function init(){ // called from page inside IFRAME
+ test(function() {
+ var client = new self[0].XMLHttpRequest()
+ document.body.removeChild(document.getElementsByTagName("iframe")[0])
+ assert_throws("InvalidStateError", function() {
+ client.open("GET", "folder.txt")
+ }, "open() when associated document's IFRAME is removed")
+ })
+ }
+ </script>
+ <iframe src="resources/init.htm"></iframe>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/open-url-multi-window-3.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/open-url-multi-window-3.htm
new file mode 100644
index 00000000000..b3652dfa508
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/open-url-multi-window-3.htm
@@ -0,0 +1,24 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: open() resolving URLs (multi-Window; 3; evil)</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ function init() {
+ test(function() {
+ var client = new self[0].XMLHttpRequest()
+ client.open("GET", "folder.txt")
+ document.body.removeChild(document.getElementsByTagName("iframe")[0])
+ assert_throws("InvalidStateError", function() {
+ client.send(null)
+ }, "send() when associated document's IFRAME is removed")
+ })
+ }
+ </script>
+ <iframe src="resources/init.htm"></iframe>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/open-url-multi-window-4.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/open-url-multi-window-4.htm
new file mode 100644
index 00000000000..9ddbb9b4772
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/open-url-multi-window-4.htm
@@ -0,0 +1,50 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: open() resolving URLs (multi-Window; 4; evil)</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ /*
+ It's unclear what the pass condition should be for this test.
+ Implementations:
+ Firefox, Opera (Presto): terminate request with no further events when IFRAME is removed.
+ Chrome: completes request to readyState=4 but responseText is "" so it's pretty much terminated with an extra event for "DONE" state
+ Pass condition is now according to my suggested spec text in https://github.com/whatwg/xhr/pull/3 , if that's not accepted we'll have to amend this test
+ */
+ var test = async_test()
+ function init() {
+ test.step(function() {
+ var hasErrorEvent = false
+ var client = new self[0].XMLHttpRequest()
+ client.onreadystatechange = function() {
+ test.step(function() {
+ if(client.readyState == 4) {
+ assert_equals(client.responseText, "", "responseText is empty on inactive document error condition")
+ }
+ })
+ }
+ client.addEventListener('error', function(){
+ test.step(function() {
+ hasErrorEvent = true
+ assert_equals(client.readyState, 4, "readyState is 4 when error listener fires")
+ })
+ })
+ client.addEventListener('loadend', function(){
+ test.step(function() {
+ assert_true(hasErrorEvent, "should get an error event")
+ test.done()
+ })
+ })
+ client.open("GET", "folder.txt")
+ client.send(null)
+ document.body.removeChild(document.getElementsByTagName("iframe")[0])
+ })
+ }
+ </script>
+ <iframe src="resources/init.htm"></iframe>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/open-url-multi-window-5.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/open-url-multi-window-5.htm
new file mode 100644
index 00000000000..a27d2b366c0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/open-url-multi-window-5.htm
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>XMLHttpRequest: open() resolving URLs (multi-Window; 5)</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-open()-method" data-tested-assertations="following::ol[1]/li[2]/ol[1]/li[1]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test(),
+ client,
+ count = 0
+ function init() {
+ test.step(function() {
+ if(0 == count) {
+ client = new self[0].XMLHttpRequest()
+ count++
+ self[0].location.reload()
+ } else if(1 == count) {
+ assert_throws("InvalidStateError", function() { client.open("GET", "...") })
+ test.done()
+ }
+ })
+ }
+ </script>
+ <iframe src="resources/init.htm"></iframe>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/open-url-multi-window.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/open-url-multi-window.htm
new file mode 100644
index 00000000000..b84aaa57fed
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/open-url-multi-window.htm
@@ -0,0 +1,30 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: open() resolving URLs (multi-Window; 1)</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-open()-method" data-tested-assertations="following::ol[1]/li[2]/ol[1]/li[2] following::ol[1]/li[7] following::ol[1]/li[14]/ul/li[2]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ function init() {
+ test.step(function() {
+ var client = new self[0].XMLHttpRequest()
+ client.onreadystatechange = function() {
+ test.step(function() {
+ if(client.readyState == 4)
+ assert_equals(client.responseText, "bottom\n")
+ test.done()
+ })
+ }
+ client.open("GET", "folder.txt")
+ client.send("")
+ })
+ }
+ </script>
+ <iframe src="resources/init.htm"></iframe>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/open-url-worker-origin.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/open-url-worker-origin.htm
new file mode 100644
index 00000000000..bad2ec4d6c4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/open-url-worker-origin.htm
@@ -0,0 +1,44 @@
+ <!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8" />
+ <title>XMLHttpRequest: worker scripts, origin and referrer</title>
+ <link rel="stylesheet" href="/resources/testharness.css" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-open()-method" data-tested-assertations="following::OL[1]/LI[3] following::OL[1]/LI[3]/ol[1]/li[1] following::OL[1]/LI[3]/ol[1]/li[2] following::OL[1]/LI[3]/ol[1]/li[3]" />
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+ var test = async_test() // This "test" does not actually do any assertations. It's just there to have multiple, separate, asyncronous sub-tests.
+ var expectations = {
+ 'Referer header': 'referer: '+(location.href.replace(/[^/]*$/, ''))+"resources/workerxhr-origin-referrer.js\n",
+ 'Origin header': 'origin: '+location.protocol+'//'+location.hostname+((location.port === "")?"":":"+location.port)+'\n',
+ 'Request URL test' : (location.href.replace(/[^/]*$/, ''))+'resources/requri.py?full'
+ }
+ // now start the worker
+ var worker = new Worker("resources/workerxhr-origin-referrer.js", true)
+ worker.onmessage = function (e) {
+ var subtest = async_test(e.data.test)
+ subtest.step(function(){
+ var thisExpectation = expectations[e.data.test]
+ delete expectations[e.data.test]
+ assert_equals(e.data.result, thisExpectation)
+ subtest.done()
+ })
+ var allDone = true
+ for(var prop in expectations){
+ allDone = false
+ }
+ if(allDone){
+ test.step(function(){
+ test.done()
+ })
+ }
+ }
+
+ </script>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/open-url-worker-simple.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/open-url-worker-simple.htm
new file mode 100644
index 00000000000..f0613c1a2d7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/open-url-worker-simple.htm
@@ -0,0 +1,26 @@
+ <!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8" />
+ <title>XMLHttpRequest: relative URLs in worker scripts resolved by script URL</title>
+ <link rel="stylesheet" href="/resources/testharness.css" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-open()-method" data-tested-assertations="following::OL[1]/LI[3] following::OL[1]/LI[3]/ol[1]/li[1]" />
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+ var test = async_test()
+ var worker = new Worker("resources/workerxhr-simple.js")
+ worker.onmessage = function (e) {
+ test.step(function(){
+ assert_equals(e.data, 'PASSED')
+ test.done()
+ })
+ }
+ worker.postMessage('start')
+ </script>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/open-user-password-non-same-origin.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/open-user-password-non-same-origin.htm
new file mode 100644
index 00000000000..e49888cd493
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/open-user-password-non-same-origin.htm
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>XMLHttpRequest: open() - user/pass argument and non same-origin URL doesn't throw</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-open()-method" data-tested-assertations="following::ol/li[9]/ol/li[1] following::ol/li[9]/ol/li[2] following::ol/li[15]/ol/li[1]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var m = "GET",
+ u = "http://test2.w3.org/",
+ a = false
+ test(function() {
+ var client = new XMLHttpRequest()
+ client.open(m, u, a, "x")
+ assert_equals(client.readyState, 1, "open() was successful - 1")
+ var client2 = new XMLHttpRequest()
+ client2.open(m, u, a, "x", "x")
+ assert_equals(client2.readyState, 1, "open() was successful - 2")
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/overridemimetype-done-state.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/overridemimetype-done-state.htm
new file mode 100644
index 00000000000..a1711e6096f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/overridemimetype-done-state.htm
@@ -0,0 +1,26 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: overrideMimeType() in DONE state</title>
+ <meta charset="utf-8">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-overridemimetype()-method" data-tested-assertations="/following::ol/li[1]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test();
+ var client = new XMLHttpRequest();
+ client.onreadystatechange = test.step_func( function() {
+ if (client.readyState !== 4) return;
+ assert_throws("InvalidStateError", function() { client.overrideMimeType('application/xml;charset=Shift-JIS'); });
+ assert_equals(client.responseXML, null);
+ test.done();
+ });
+ client.open("GET", "resources/status.py?type="+encodeURIComponent('text/plain;charset=iso-8859-1')+'&content=%3Cmsg%3E%83%65%83%58%83%67%3C%2Fmsg%3E');
+ client.send();
+ </script>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/overridemimetype-headers-received-state-force-shiftjis.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/overridemimetype-headers-received-state-force-shiftjis.htm
new file mode 100644
index 00000000000..578e28cb227
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/overridemimetype-headers-received-state-force-shiftjis.htm
@@ -0,0 +1,34 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: overrideMimeType() in HEADERS RECEIVED state, enforcing Shift-JIS encoding</title>
+ <meta charset="utf-8">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-overridemimetype()-method" data-tested-assertations="/following::ol/li[1] /following::ol/li[4]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test();
+ var client = new XMLHttpRequest();
+ var readyState2Reached = false;
+ client.onreadystatechange = test.step_func( function() {
+ if(client.readyState===2){
+ readyState2Reached = true;
+ try{
+ client.overrideMimeType('text/plain;charset=Shift-JIS');
+ }catch(e){
+ assert_unreached('overrideMimeType should not throw in state 2');
+ }
+ }
+ if (client.readyState !== 4) return;
+ assert_equals( readyState2Reached, true, "readyState = 2 event fired" );
+ assert_equals( client.responseText, 'テスト', 'overrideMimeType() in HEADERS RECEIVED state set encoding' );
+ test.done();
+ });
+ client.open("GET", "resources/status.py?type="+encodeURIComponent('text/html;charset=UTF-8')+'&content=%83%65%83%58%83%67');
+ client.send( '' );
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/overridemimetype-invalid-mime-type.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/overridemimetype-invalid-mime-type.htm
new file mode 100644
index 00000000000..9cfd801e05b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/overridemimetype-invalid-mime-type.htm
@@ -0,0 +1,25 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: overrideMimeType() in unsent state, invalid MIME types</title>
+ <meta charset="utf-8">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-overridemimetype()-method" data-tested-assertations="/following::ol/li[2]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ test(function() {
+ var client = new XMLHttpRequest();
+ assert_throws("SyntaxError", function() { client.overrideMimeType('text\\plain;charset=Shift-JIS'); });
+ assert_throws("SyntaxError", function() { client.overrideMimeType('text plain;charset=Shift-JIS'); });
+ assert_throws("SyntaxError", function() { client.overrideMimeType('text\nplain;charset=Shift-JIS'); });
+ assert_throws("SyntaxError", function() { client.overrideMimeType('cahrset=Shift-JIS'); });
+ assert_throws("SyntaxError", function() { client.overrideMimeType(null); });
+ assert_throws("SyntaxError", function() { client.overrideMimeType(50212); });
+ assert_throws("SyntaxError", function() { client.overrideMimeType( (new Array(1000)).join('a/b/c/') ); });
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/overridemimetype-loading-state.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/overridemimetype-loading-state.htm
new file mode 100644
index 00000000000..cce3fa49ef7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/overridemimetype-loading-state.htm
@@ -0,0 +1,32 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: overrideMimeType() in LOADING state</title>
+ <meta charset="utf-8">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-overridemimetype()-method" data-tested-assertations="/following::ol/li[1]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test();
+ test.step(function() {
+ var client = new XMLHttpRequest();
+ client.onreadystatechange = test.step_func(function() {
+ if (client.readyState === 3){
+ assert_throws("InvalidStateError", function(){
+ client.overrideMimeType('application/xml;charset=Shift-JIS');
+ });
+ }else if(client.readyState===4){
+ assert_equals(client.responseXML, null);
+ test.done();
+ }
+ });
+ client.open("GET", "resources/status.py?type="+encodeURIComponent('text/plain;charset=iso-8859-1')+'&content=%3Cmsg%3E%83%65%83%58%83%67%3C%2Fmsg%3E');
+ client.send();
+ });
+ </script>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/overridemimetype-open-state-force-utf-8.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/overridemimetype-open-state-force-utf-8.htm
new file mode 100644
index 00000000000..5a261005d97
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/overridemimetype-open-state-force-utf-8.htm
@@ -0,0 +1,27 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: overrideMimeType() in open state, enforcing UTF-8 encoding</title>
+ <meta charset="utf-8">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-overridemimetype()-method" data-tested-assertations="/following::ol/li[3] /following::ol/li[4]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test();
+ test.step(function() {
+ var client = new XMLHttpRequest();
+ client.onreadystatechange = function() {
+ if (client.readyState !== 4) return;
+ assert_equals( client.responseText, 'テスト' );
+ test.done();
+ };
+ client.open("GET", "resources/status.py?type="+encodeURIComponent('text/html;charset=Shift-JIS')+'&content='+encodeURIComponent('テスト'));
+ client.overrideMimeType('text/plain;charset=UTF-8');
+ client.send( '' );
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/overridemimetype-open-state-force-xml.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/overridemimetype-open-state-force-xml.htm
new file mode 100644
index 00000000000..fd0664a7cce
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/overridemimetype-open-state-force-xml.htm
@@ -0,0 +1,34 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: overrideMimeType() in open state, XML MIME type with UTF-8 charset</title>
+ <meta charset="utf-8">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-overridemimetype()-method" data-tested-assertations="/following::ol/li[3] /following::ol/li[4]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test();
+ test.step(function() {
+ var client = new XMLHttpRequest();
+ client.onreadystatechange = function() {
+ if (client.readyState !== 4) return;
+ try{
+ var str = client.responseXML.documentElement.tagName+client.responseXML.documentElement.firstChild.tagName+client.responseXML.documentElement.firstChild.textContent;
+ }catch(e){
+ assert_unreached('Exception when reading responseXML');
+ }
+ assert_equals( client.responseXML.documentElement.tagName, 'test' );
+ assert_equals( client.responseXML.documentElement.firstChild.tagName, 'message' );
+ assert_equals( client.responseXML.documentElement.firstChild.textContent, 'Hello World!' );
+ test.done();
+ };
+ client.open("GET", "resources/status.py?type="+encodeURIComponent('text/plain;charset=Shift-JIS')+'&content='+encodeURIComponent('<test><message>Hello World!</message></test>'));
+ client.overrideMimeType('application/xml;charset=UTF-8');
+ client.send();
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/overridemimetype-unsent-state-force-shiftjis.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/overridemimetype-unsent-state-force-shiftjis.htm
new file mode 100644
index 00000000000..98dfe1436d9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/overridemimetype-unsent-state-force-shiftjis.htm
@@ -0,0 +1,27 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: overrideMimeType() in unsent state, enforcing Shift-JIS encoding</title>
+ <meta charset="utf-8">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-overridemimetype()-method" data-tested-assertations="/following::ol/li[3] /following::ol/li[4]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test();
+ test.step(function() {
+ var client = new XMLHttpRequest();
+ client.overrideMimeType('text/plain;charset=Shift-JIS');
+ client.onreadystatechange = function() {
+ if (client.readyState !== 4) return;
+ assert_equals( client.responseText, 'テスト' );
+ test.done();
+ };
+ client.open("GET", "resources/status.py?type="+encodeURIComponent('text/html;charset=iso-8859-1')+'&content=%83%65%83%58%83%67');
+ client.send( '' );
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/progress-events-response-data-gzip.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/progress-events-response-data-gzip.htm
new file mode 100644
index 00000000000..dc166a2396a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/progress-events-response-data-gzip.htm
@@ -0,0 +1,77 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: progress events and GZIP encoding</title>
+ <meta name="timeout" content="long">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#firing-events-using-the-progressevent-interface-for-http" data-tested-assertations="following::p[contains(text(),'content-encodings')]" />
+ <!-- TODO: find better spec reference when https://www.w3.org/Bugs/Public/show_bug.cgi?id=25587 is fixed -->
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+ var client = new XMLHttpRequest()
+ /*
+
+ Two behaviours are considered acceptable, so there are two ways to
+ pass this test
+
+ a) Set data for the compressed resource:
+ * event.total reflects the Content-length of the gzipp'ed resource
+ * event.loaded how many gzipped bytes have arrived over the wire so far
+ * lengthComputable is true
+
+ or
+
+ b) If the implementation does not provide progress details for the compressed
+ resource, set
+ * lengthComputable to false
+ * event.total to 0
+ * event.loaded to the number of bytes available so far after gzip decoding
+
+ Implications of this are tested here as follows:
+
+ * If lengthComputable is true:
+ * Event.total must match Content-length header
+ * event.loaded should be a smaller number while resource is loading
+ and match Content-length when loading is finished
+ * Setting event.loaded to equal event.total for each progress event if the
+ resource is not fully downloaded would be cheating
+
+ * If lengthComputable is false:
+ * event.total should be 0
+ * event.loaded should be the length of the decompressed content, i.e.
+ bigger than Content-length header value when finished loading
+
+ */
+ client.addEventListener('loadend', test.step_func(function(e){
+ var len = parseInt(client.getResponseHeader('content-length'), 10)
+ if(e.lengthComputable){
+ assert_equals(e.total, len, 'event.total is content-length')
+ assert_equals(e.loaded, len, 'event.loaded should be content-length at loadend')
+ }else{
+ assert_equals(e.total, 0, 'if implementation can\'t compute event.total for gzipped content it is 0')
+ assert_true(e.loaded >= len, 'event.loaded should be set even if total is not computable')
+ }
+ test.done();
+ }), false)
+ client.addEventListener('progress', test.step_func(function(e){
+ if(e.lengthComputable && e.total && e.loaded && e.target.readyState < 4){
+ assert_not_equals(e.total, e.loaded, 'total should not equal loaded while download/decode is incomplete')
+ // We should only do this assertation once
+ // it's theoretically possible that all the data would get in
+ // and a progress event fire before the readyState switches from 3 to 4 -
+ // in this case we might report bogus and random failures. Better to remove the event listener again..
+ client.removeEventListener('progress', arguments.callee, false);
+ }
+ }), false)
+ // image.gif is 165375 bytes compressed. Sending 45000 bytes at a time with 1 second delay will load it in 4 seconds
+ client.open("GET", "resources/image.gif?pipe=gzip|trickle(45000:d1:r2)", true)
+ client.send()
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/readme.txt b/tests/wpt/web-platform-tests/XMLHttpRequest/readme.txt
new file mode 100644
index 00000000000..2e5f64cd518
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/readme.txt
@@ -0,0 +1,31 @@
+Currently this testsuite tries to provide tests for XMLHttpRequest level 1.
+This test suite is not stable and is still under development. Tests may
+contain bugs and may change over time as a result of those bugs being fixed.
+
+When more browsers implement XMLHttpRequest level 2 this testsuite will
+slowly evolve most likely.
+
+ http://dev.w3.org/2006/webapi/XMLHttpRequest/
+ http://dev.w3.org/2006/webapi/XMLHttpRequest-2/
+
+If the folders above give the status of the feature tested you can assume
+this is against level 1 unless explicitly stated otherwise.
+
+NOTE: readyState and onreadystatechange are tested throughout the various
+tests. statusText is tested together with status.
+
+NOTE: open-url-base* have absolute paths in them. They need to be adjusted
+on a per location basis.
+
+NOTE: open-url-base-inserted-after-open.htm, open-url-base-inserted.htm,
+send-authentication.htm and open-url-base.htm refer to localhost.
+
+
+TESTS THAT ARE UNSTABLE AND (PROBABLY) NEED CHANGES
+ responsexml-basic (see email WHATWG)
+ send-authentication (see "user:password" debacle)
+
+
+TESTS NOT STARTED ON YET
+
+<iframe> document.domain = w3.org create cross-origin xhr object
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/accept-language.py b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/accept-language.py
new file mode 100644
index 00000000000..e0fd30c1195
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/accept-language.py
@@ -0,0 +1,4 @@
+def main(request, response):
+ return [("Content-Type", "text/plain"),
+ request.headers.get("Accept-Language", "NO")]
+
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/accept.py b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/accept.py
new file mode 100644
index 00000000000..2fdf210b6d6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/accept.py
@@ -0,0 +1,3 @@
+def main(request, response):
+ return [("Content-Type", "text/plain")], request.headers.get("accept", "NO")
+
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/auth1/auth.py b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/auth1/auth.py
new file mode 100644
index 00000000000..8b6682686c8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/auth1/auth.py
@@ -0,0 +1,10 @@
+import imp
+import os
+
+here = os.path.split(os.path.abspath(__file__))[0]
+
+def main(request, response):
+ auth = imp.load_source("", os.path.join(here,
+ "..",
+ "authentication.py"))
+ return auth.main(request, response)
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/auth2/auth.py b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/auth2/auth.py
new file mode 100644
index 00000000000..8b6682686c8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/auth2/auth.py
@@ -0,0 +1,10 @@
+import imp
+import os
+
+here = os.path.split(os.path.abspath(__file__))[0]
+
+def main(request, response):
+ auth = imp.load_source("", os.path.join(here,
+ "..",
+ "authentication.py"))
+ return auth.main(request, response)
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/auth2/corsenabled.py b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/auth2/corsenabled.py
new file mode 100644
index 00000000000..ce22697390d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/auth2/corsenabled.py
@@ -0,0 +1,20 @@
+import imp
+import os
+
+def main(request, response):
+ response.headers.set('Access-Control-Allow-Origin', request.headers.get("origin"));
+ response.headers.set('Access-Control-Allow-Credentials', 'true');
+ response.headers.set('Access-Control-Allow-Methods', 'GET');
+ response.headers.set('Access-Control-Allow-Headers', 'authorization, x-user, x-pass');
+ response.headers.set('Access-Control-Expose-Headers', 'x-challenge, xhr-user, ses-user');
+ auth = imp.load_source("", os.path.join(os.path.abspath(os.curdir),
+ "XMLHttpRequest",
+ "resources",
+ "authentication.py"))
+ if request.method == "OPTIONS":
+ return ""
+ else:
+ return auth.main(request, response)
+
+
+
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/auth3/auth.py b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/auth3/auth.py
new file mode 100644
index 00000000000..8b6682686c8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/auth3/auth.py
@@ -0,0 +1,10 @@
+import imp
+import os
+
+here = os.path.split(os.path.abspath(__file__))[0]
+
+def main(request, response):
+ auth = imp.load_source("", os.path.join(here,
+ "..",
+ "authentication.py"))
+ return auth.main(request, response)
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/auth4/auth.py b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/auth4/auth.py
new file mode 100644
index 00000000000..8b6682686c8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/auth4/auth.py
@@ -0,0 +1,10 @@
+import imp
+import os
+
+here = os.path.split(os.path.abspath(__file__))[0]
+
+def main(request, response):
+ auth = imp.load_source("", os.path.join(here,
+ "..",
+ "authentication.py"))
+ return auth.main(request, response)
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/auth5/auth.py b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/auth5/auth.py
new file mode 100644
index 00000000000..bc739f5eb59
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/auth5/auth.py
@@ -0,0 +1,13 @@
+def main(request, response):
+ if request.auth.username == 'usr' and request.auth.password == 'secret':
+ response.headers.set('Content-type', 'text/plain')
+ content = ""
+ else:
+ response.status = 401
+ response.headers.set('Status', '401 Authorization required')
+ response.headers.set('WWW-Authenticate', 'Basic realm="test"')
+ content = 'User name/password wrong or not given: '
+
+ content += "%s\n%s" % (request.auth.username,
+ request.auth.password)
+ return content
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/auth6/auth.py b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/auth6/auth.py
new file mode 100644
index 00000000000..bc739f5eb59
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/auth6/auth.py
@@ -0,0 +1,13 @@
+def main(request, response):
+ if request.auth.username == 'usr' and request.auth.password == 'secret':
+ response.headers.set('Content-type', 'text/plain')
+ content = ""
+ else:
+ response.status = 401
+ response.headers.set('Status', '401 Authorization required')
+ response.headers.set('WWW-Authenticate', 'Basic realm="test"')
+ content = 'User name/password wrong or not given: '
+
+ content += "%s\n%s" % (request.auth.username,
+ request.auth.password)
+ return content
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/authentication.py b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/authentication.py
new file mode 100644
index 00000000000..4f65fa23d2c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/authentication.py
@@ -0,0 +1,32 @@
+def main(request, response):
+ if "logout" in request.GET:
+ return ((401, "Unauthorized"),
+ [("WWW-Authenticate", 'Basic realm="test"')],
+ "Logged out, hopefully")
+
+ session_user = request.auth.username
+ session_pass = request.auth.password
+ expected_user_name = request.headers.get("X-User", None)
+
+ token = expected_user_name
+ if session_user is None and session_pass is None:
+ if token is not None and request.server.stash.take(token) is not None:
+ return 'FAIL (did not authorize)'
+ else:
+ if token is not None:
+ request.server.stash.put(token, "1")
+ status = (401, 'Unauthorized')
+ headers = [('WWW-Authenticate', 'Basic realm="test"'),
+ ('XHR-USER', expected_user_name),
+ ('SES-USER', session_user)]
+ return status, headers, 'FAIL (should be transparent)'
+ else:
+ if request.server.stash.take(token) == "1":
+ challenge = "DID"
+ else:
+ challenge = "DID-NOT"
+ headers = [('XHR-USER', expected_user_name),
+ ('SES-USER', session_user),
+ ("X-challenge", challenge)]
+ return headers, session_user + "\n" + session_pass;
+
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/chunked.py b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/chunked.py
new file mode 100644
index 00000000000..7adabbfd7f4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/chunked.py
@@ -0,0 +1,18 @@
+def main(request, response):
+ chunks = ["First chunk\r\n",
+ "Second chunk\r\n",
+ "Yet another (third) chunk\r\n",
+ "Yet another (fourth) chunk\r\n",
+ ]
+ response.headers.set("Transfer-Encoding", "chunked");
+ response.headers.set("Trailer", "X-Test-Me");
+ response.headers.set("Content-Type", "text/plain");
+ response.write_status_headers()
+
+ for value in chunks:
+ response.writer.write("%d\r\n" % len(value))
+ response.writer.write(value)
+ response.writer.write("\r\n")
+ response.writer.write("0\r\n")
+ response.writer.write("X-Test-Me: Trailer header value\r\n\r\n")
+
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/conditional.py b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/conditional.py
new file mode 100644
index 00000000000..42dfecdfbc3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/conditional.py
@@ -0,0 +1,17 @@
+def main(request, response):
+ tag = request.GET.first("tag", None)
+ match = request.headers.get("If-None-Match", None)
+ date = request.GET.first("date", "")
+ modified = request.headers.get("If-Modified-Since", None)
+ if tag:
+ response.headers.set("ETag", '"%s"' % tag)
+ elif date:
+ response.headers.set("Last-Modified", date)
+
+ if ((match is not None and match == tag) or
+ (modified is not None and modified == date)):
+ response.status = (304, "SUPERCOOL")
+ return ""
+ else:
+ response.headers.set("Content-Type", "text/plain")
+ return "MAYBE NOT"
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/content.py b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/content.py
new file mode 100644
index 00000000000..d7c62ab6d86
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/content.py
@@ -0,0 +1,18 @@
+def main(request, response):
+ response_ctype = ''
+
+ if "response_charset_label" in request.GET:
+ response_ctype = ";charset=" + request.GET.first("response_charset_label")
+
+ headers = [("Content-type", "text/plain" + response_ctype),
+ ("X-Request-Method", request.method),
+ ("X-Request-Query", request.url_parts.query if request.url_parts.query else "NO"),
+ ("X-Request-Content-Length", request.headers.get("Content-Length", "NO")),
+ ("X-Request-Content-Type", request.headers.get("Content-Type", "NO"))]
+
+ if "content" in request.GET:
+ content = request.GET.first("content")
+ else:
+ content = request.body
+
+ return headers, content
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/corsenabled.py b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/corsenabled.py
new file mode 100644
index 00000000000..d61f85d9a1f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/corsenabled.py
@@ -0,0 +1,19 @@
+import time
+
+def main(request, response):
+ headers = [("Access-Control-Allow-Origin", "*"),
+ ("Access-Control-Allow-Credentials", "true"),
+ ("Access-Control-Allow-Methods", "GET, POST, PUT, FOO"),
+ ("Access-Control-Allow-Headers", "x-test, x-foo"),
+ ("Access-Control-Expose-Headers", "x-request-method, x-request-content-type, x-request-query, x-request-content-length")]
+
+ if "delay" in request.GET:
+ delay = int(request.GET.first("delay"))
+ time.sleep(delay)
+
+ headers.append(("X-Request-Method", request.method))
+ headers.append(("X-Request-Query", request.url_parts.query if request.url_parts.query else "NO"))
+ headers.append(("X-Request-Content-Length", request.headers.get("Content-Length", "NO")))
+ headers.append(("X-Request-Content-Type", request.headers.get("Content-Type", "NO")))
+
+ return headers, "Test"
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/delay.py b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/delay.py
new file mode 100644
index 00000000000..bdfef9b34ae
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/delay.py
@@ -0,0 +1,6 @@
+import time
+
+def main(request, response):
+ delay = float(request.GET.first("ms", 500))
+ time.sleep(delay / 1E3);
+ return [("Content-type", "text/plain")], "TEST_DELAY"
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/folder.txt b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/folder.txt
new file mode 100644
index 00000000000..fef12e21968
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/folder.txt
@@ -0,0 +1 @@
+bottom
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/form.py b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/form.py
new file mode 100644
index 00000000000..6b1c49a993b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/form.py
@@ -0,0 +1,2 @@
+def main(request, response):
+ return "id:%s;value:%s;" % (request.POST.first("id"), request.POST.first("value"))
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/gzip.py b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/gzip.py
new file mode 100644
index 00000000000..87dd5bec097
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/gzip.py
@@ -0,0 +1,23 @@
+import gzip as gzip_module
+from cStringIO import StringIO
+
+def main(request, response):
+ if "content" in request.GET:
+ output = request.GET["content"]
+ else:
+ output = request.body
+
+ out = StringIO()
+ with gzip_module.GzipFile(fileobj=out, mode="w") as f:
+ f.write(output)
+ output = out.getvalue()
+
+ headers = [("Content-type", "text/plain"),
+ ("Content-Encoding", "gzip"),
+ ("X-Request-Method", request.method),
+ ("X-Request-Query", request.url_parts.query if request.url_parts.query else "NO"),
+ ("X-Request-Content-Length", request.headers.get("Content-Length", "NO")),
+ ("X-Request-Content-Type", request.headers.get("Content-Type", "NO")),
+ ("Content-Length", len(output))]
+
+ return headers, output
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/headers.py b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/headers.py
new file mode 100644
index 00000000000..cefa8ee65f7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/headers.py
@@ -0,0 +1,12 @@
+ # -*- coding: utf-8 -*-
+
+def main(request, response):
+ response.headers.set("Content-Type", "text/plain")
+ response.headers.set("X-Custom-Header", "test")
+ response.headers.set("Set-Cookie", "test")
+ response.headers.set("Set-Cookie2", "test")
+ response.headers.set("X-Custom-Header-Empty", "")
+ response.headers.set("X-Custom-Header-Comma", "1")
+ response.headers.append("X-Custom-Header-Comma", "2")
+ response.headers.set("X-Custom-Header-Bytes", "…")
+ return "TEST"
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/image.gif b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/image.gif
new file mode 100644
index 00000000000..6d1174af119
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/image.gif
Binary files differ
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/img.jpg b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/img.jpg
new file mode 100644
index 00000000000..7aa9362529c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/img.jpg
Binary files differ
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/infinite-redirects.py b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/infinite-redirects.py
new file mode 100644
index 00000000000..b508c5b3cd7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/infinite-redirects.py
@@ -0,0 +1,24 @@
+def main(request, response):
+ location = "%s://%s:%s/%s" % (request.url_parts.scheme,
+ request.url_parts.netloc,
+ request.url_parts.port,
+ request.url_parts.path)
+ page = "alternate";
+ type = 302;
+ mix = 0;
+ if request.GET.first("page", None) == "alternate":
+ page = "default"
+
+ if request.GET.first("type", None) == "301":
+ type = 301
+
+ if request.GET.first("mix", None) == "1":
+ mix = 1
+ type = 302 if type == 301 else 301
+
+ new_location = "%s?page=%s&type=%s&mix=%s" % (location, page, type, mix)
+ headers = [("Cache-Control", "no-cache"),
+ ("Pragma", "no-cache"),
+ ("Location", new_location)]
+ return 301, headers, "Hello guest. You have been redirected to " + new_location
+
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/init.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/init.htm
new file mode 100644
index 00000000000..7c56d88800d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/init.htm
@@ -0,0 +1,9 @@
+<!doctype html>
+<html>
+ <head>
+ <title>support init file</title>
+ </head>
+ <body>
+ <script> parent.init() </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/inspect-headers.py b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/inspect-headers.py
new file mode 100644
index 00000000000..ca5960557e5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/inspect-headers.py
@@ -0,0 +1,22 @@
+def main(request, response):
+ headers = []
+ if "cors" in request.GET:
+ headers.append(("Access-Control-Allow-Origin", "*"))
+ headers.append(("Access-Control-Allow-Credentials", "true"))
+ headers.append(("Access-Control-Allow-Methods", "GET, POST, PUT, FOO"))
+ headers.append(("Access-Control-Allow-Headers", "x-test, x-foo"))
+ headers.append(("Access-Control-Expose-Headers", "x-request-method, x-request-content-type, x-request-query, x-request-content-length"))
+
+ filter_value = request.GET.first("filter_value", "")
+ filter_name = request.GET.first("filter_name", "").lower()
+
+ result = ""
+ for name, value in request.headers.iteritems():
+ if filter_value:
+ if value == filter_value:
+ result += name.lower() + ","
+ elif name.lower() == filter_name:
+ result += name.lower() + ": " + value + "\n";
+
+ headers.append(("content-type", "text/plain"))
+ return headers, result
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/invalid-utf8-html.py b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/invalid-utf8-html.py
new file mode 100644
index 00000000000..72be41a45e8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/invalid-utf8-html.py
@@ -0,0 +1,5 @@
+def main(request, response):
+ headers = [("Content-type", "text/html;charset=utf-8")]
+ content = chr(0xff)
+
+ return headers, content
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/nocors/folder.txt b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/nocors/folder.txt
new file mode 100644
index 00000000000..5257b481d17
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/nocors/folder.txt
@@ -0,0 +1 @@
+not CORS-enabled \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/redirect.py b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/redirect.py
new file mode 100644
index 00000000000..6ec9349565a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/redirect.py
@@ -0,0 +1,8 @@
+def main(request, response):
+ code = int(request.GET.first("code", 302))
+ location = request.GET.first("location", request.url_parts.path +"?followed")
+
+ if request.url.endswith("?followed"):
+ return [("Content:Type", "text/plain")], "MAGIC HAPPENED"
+ else:
+ return (code, "WEBSRT MARKETING"), [("Location", location)], "TEST"
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/requri.py b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/requri.py
new file mode 100644
index 00000000000..eaa562dff24
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/requri.py
@@ -0,0 +1,6 @@
+def main(request, response):
+ if "full" in request.GET:
+ return request.url
+ else:
+ return request.request_path
+
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/shift-jis-html.py b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/shift-jis-html.py
new file mode 100644
index 00000000000..92d06ca78c4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/shift-jis-html.py
@@ -0,0 +1,6 @@
+def main(request, response):
+ headers = [("Content-type", "text/html;charset=shift-jis")]
+ # Shift-JIS bytes for katakana TE SU TO ('test')
+ content = chr(0x83) + chr(0x65) + chr(0x83) + chr(0x58) + chr(0x83) + chr(0x67);
+
+ return headers, content
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/status.py b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/status.py
new file mode 100644
index 00000000000..5d72e10b24b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/status.py
@@ -0,0 +1,9 @@
+def main(request, response):
+ code = int(request.GET.first("code", 200))
+ text = request.GET.first("text", "OMG")
+ content = request.GET.first("content", "")
+ type = request.GET.first("type", "")
+ status = (code, text)
+ headers = [("Content-Type", type),
+ ("X-Request-Method", request.method)]
+ return status, headers, content
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/trickle.py b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/trickle.py
new file mode 100644
index 00000000000..0e709445c59
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/trickle.py
@@ -0,0 +1,12 @@
+import time
+
+def main(request, response):
+ delay = float(request.GET.first("ms", 500)) / 1E3
+ count = int(request.GET.first("count", 50))
+ time.sleep(delay)
+ response.headers.set("Content-type", "text/plain")
+ response.write_status_headers()
+ time.sleep(delay);
+ for i in xrange(count):
+ response.writer.write_content("TEST_TRICKLE\n")
+ time.sleep(delay)
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/upload.py b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/upload.py
new file mode 100644
index 00000000000..27cee598b71
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/upload.py
@@ -0,0 +1,15 @@
+def main(request, response):
+ content = []
+
+ for key, values in sorted(item for item in request.POST.items() if not hasattr(item[1][0], "filename")):
+ content.append("%s=%s," % (key, values[0]))
+ content.append("\n")
+
+ for key, values in sorted(item for item in request.POST.items() if hasattr(item[1][0], "filename")):
+ value = values[0]
+ content.append("%s=%s:%s:%s," % (key,
+ value.filename,
+ value.headers["Content-Type"],
+ len(value.file.read())))
+
+ return "".join(content)
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/utf16.txt b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/utf16.txt
new file mode 100644
index 00000000000..0085dfaee8d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/utf16.txt
Binary files differ
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/well-formed.xml b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/well-formed.xml
new file mode 100644
index 00000000000..2f4f1269880
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/well-formed.xml
@@ -0,0 +1,4 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <p id="n&#49;">1</p>
+ <p xmlns="namespacesarejuststrings" id="n2">2</p>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/win-1252-xml.py b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/win-1252-xml.py
new file mode 100644
index 00000000000..09c32e4574b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/win-1252-xml.py
@@ -0,0 +1,5 @@
+def main(request, response):
+ headers = [("Content-type", "application/xml;charset=windows-1252")]
+ content = '<' + chr(0xff) + '/>'
+
+ return headers, content
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/workerxhr-origin-referrer.js b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/workerxhr-origin-referrer.js
new file mode 100644
index 00000000000..5e2ef2a8ceb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/workerxhr-origin-referrer.js
@@ -0,0 +1,34 @@
+// This simply posts a message to the owner page with the contents of the Referer header
+var xhr=new XMLHttpRequest()
+xhr.onreadystatechange = function(){
+ if(xhr.readyState == 4){
+ var obj = {test:'Referer header', result:xhr.responseText}
+ self.postMessage(obj)
+ }
+}
+xhr.open('GET', 'inspect-headers.py?filter_name=referer', true)
+xhr.send()
+
+// This simply posts a message to the owner page with the contents of the Origin header
+var xhr2=new XMLHttpRequest()
+xhr2.onreadystatechange = function(){
+ if(xhr2.readyState == 4){
+ var obj = {test:'Origin header', result:xhr2.responseText}
+ self.postMessage(obj)
+ }
+}
+xhr2.open('GET', location.protocol + '//www2.'+location.hostname+((location.port === "")?"":":"+location.port)+(location.pathname.replace(/[^/]*$/, ''))+'inspect-headers.py?filter_name=origin&cors', true)
+xhr2.send()
+
+// If "origin" / base URL is the origin of this JS file, we can load files
+// from the server it originates from.. and requri.py will be able to tell us
+// what the requested URL was
+var xhr3=new XMLHttpRequest()
+xhr3.onreadystatechange = function(){
+ if(xhr3.readyState == 4){
+ var obj = {test:'Request URL test', result:xhr3.responseText}
+ self.postMessage(obj)
+ }
+}
+xhr3.open('GET', 'requri.py?full', true)
+xhr3.send()
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/workerxhr-simple.js b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/workerxhr-simple.js
new file mode 100644
index 00000000000..f6bcec0befa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/workerxhr-simple.js
@@ -0,0 +1,10 @@
+
+var xhr=new XMLHttpRequest()
+xhr.onreadystatechange = function(){
+ if(xhr.readyState == 4){
+ var status = xhr.responseText === 'bottom\n' ? 'PASSED' : 'FAILED'
+ self.postMessage(status)
+ }
+}
+xhr.open('GET', 'folder.txt', true)
+xhr.send()
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout-aborted.js b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout-aborted.js
new file mode 100644
index 00000000000..54142fd6355
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout-aborted.js
@@ -0,0 +1,15 @@
+if (this.document === undefined)
+ importScripts("xmlhttprequest-timeout.js");
+/*
+This sets up three requests:
+The first request will only be open()ed, not aborted, timeout will be 400 but will never triggered because send() isn't called.
+After a 1 second delay, the test asserts that no load/error/timeout/abort events fired
+
+Second request will be aborted immediately after send(), test asserts that abort fired
+
+Third request is set up to call abort() after a 1 second delay, but it also has a 400ms timeout. Asserts that timeout fired.
+(abort() is called 600ms later and should not fire an abort event per spec. This is untested!)
+*/
+runTestRequests([ new AbortedRequest(false),
+ new AbortedRequest(true, -1),
+ new AbortedRequest(true, TIME_NORMAL_LOAD) ]);
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout-abortedonmain.js b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout-abortedonmain.js
new file mode 100644
index 00000000000..a6a67f1b85f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout-abortedonmain.js
@@ -0,0 +1,8 @@
+/*
+This test sets up two requests:
+one that gets abort()ed from a 0ms timeout (0ms will obviously be clamped to whatever the implementation's minimal value is), asserts abort event fires
+one that will be aborted after 200ms (TIME_DELAY), (with a timeout at 400ms) asserts abort event fires. Does not assert that the timeout event does *not* fire.
+*/
+
+runTestRequests([ new AbortedRequest(true, 0),
+ new AbortedRequest(true, TIME_DELAY) ]);
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout-overrides.js b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout-overrides.js
new file mode 100644
index 00000000000..12f5eb5eacc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout-overrides.js
@@ -0,0 +1,11 @@
+if (this.document === undefined)
+ importScripts("xmlhttprequest-timeout.js");
+/*
+Sets up three requests to a resource that will take 0.6 seconds to load:
+1) timeout first set to 1000ms, after 400ms timeout is set to 0, asserts load fires
+2) timeout first set to 1000ms, after 200ms timeout is set to 400, asserts load fires (race condition..?!?)
+3) timeout first set to 0, after 400ms it is set to 1000, asserts load fires
+*/
+runTestRequests([ new RequestTracker(true, "timeout disabled after initially set", TIME_NORMAL_LOAD, TIME_REGULAR_TIMEOUT, 0),
+ new RequestTracker(true, "timeout overrides load after a delay", TIME_NORMAL_LOAD, TIME_DELAY, TIME_REGULAR_TIMEOUT),
+ new RequestTracker(true, "timeout enabled after initially disabled", 0, TIME_REGULAR_TIMEOUT, TIME_NORMAL_LOAD * 10) ]);
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout-overridesexpires.js b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout-overridesexpires.js
new file mode 100644
index 00000000000..7114dfe0257
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout-overridesexpires.js
@@ -0,0 +1,13 @@
+if (this.document === undefined)
+ importScripts("xmlhttprequest-timeout.js");
+/*
+ Starts three requests:
+ 1) XHR to resource which will take a least 600ms with timeout initially set to 1000ms. After 800ms timeout is supposedly reset to 200ms,
+ but the resource should have finished loading already. Asserts "load" fires.
+ 2) XHR with initial timeout set to 1000, after 400ms sets timeout to 300ms. Asserts "timeout" fires.
+ (Originally new value was 200ms. Race condition-y. Setting the new timeout to 300ms would be a better test of the "measured from start of fetching" requirement.)
+ 3) XHR with initial timeout set to 200, after 400ms sets timeout to 500ms. Asserts "timeout" fires (the change happens when timeout already fired and the request is done).
+*/
+runTestRequests([ new RequestTracker(true, "timeout set to expiring value after load fires", TIME_NORMAL_LOAD, TIME_LATE_TIMEOUT, TIME_DELAY),
+ new RequestTracker(true, "timeout set to expired value before load fires", TIME_NORMAL_LOAD, TIME_REGULAR_TIMEOUT, TIME_DELAY+100),
+ new RequestTracker(true, "timeout set to non-expiring value after timeout fires", TIME_DELAY, TIME_REGULAR_TIMEOUT, 500) ]);
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout-runner.js b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout-runner.js
new file mode 100644
index 00000000000..3d92b2ebf4c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout-runner.js
@@ -0,0 +1,20 @@
+function testResultCallbackHandler(event) {
+ if (event.data == "done") {
+ done();
+ return;
+ }
+ if (event.data.type == "is") {
+ test(function() { assert_equals(event.data.got, event.data.expected); }, "Timeout test: " + event.data.msg);
+ return;
+ }
+ if (event.data.type == "ok") {
+ test(function() { assert_true(event.data.bool); }, "Timeout test: " + event.data.msg);
+ return;
+ }
+}
+
+window.addEventListener("message", testResultCallbackHandler);
+
+// Setting up testharness.js
+setup({ explicit_done: true, timeout: 30 * 1000 });
+
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout-simple.js b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout-simple.js
new file mode 100644
index 00000000000..0207cf10764
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout-simple.js
@@ -0,0 +1,6 @@
+if (this.document === undefined)
+ importScripts("xmlhttprequest-timeout.js");
+
+runTestRequests([ new RequestTracker(true, "no time out scheduled, load fires normally", 0),
+ new RequestTracker(true, "load fires normally", TIME_NORMAL_LOAD),
+ new RequestTracker(true, "timeout hit before load", TIME_REGULAR_TIMEOUT) ]);
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout-synconmain.js b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout-synconmain.js
new file mode 100644
index 00000000000..c6c5e985d25
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout-synconmain.js
@@ -0,0 +1,2 @@
+runTestRequests([ SyncRequestSettingTimeoutAfterOpen,
+ SyncRequestSettingTimeoutBeforeOpen ]);
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout-synconworker.js b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout-synconworker.js
new file mode 100644
index 00000000000..5a6c3fc5579
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout-synconworker.js
@@ -0,0 +1,11 @@
+if (this.document === undefined){
+ importScripts("xmlhttprequest-timeout.js");
+}else{
+ throw "This test expects to be run as a Worker";
+}
+
+/* NOT TESTED: setting timeout before calling open( ... , false) in a worker context. The test code always calls open() first. */
+
+runTestRequests([ new RequestTracker(false, "no time out scheduled, load fires normally", 0),
+ new RequestTracker(false, "load fires normally", TIME_NORMAL_LOAD),
+ new RequestTracker(false, "timeout hit before load", TIME_REGULAR_TIMEOUT) ]);
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout-twice.js b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout-twice.js
new file mode 100644
index 00000000000..0061c7333cf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout-twice.js
@@ -0,0 +1,6 @@
+if (this.document === undefined)
+ importScripts("xmlhttprequest-timeout.js");
+
+runTestRequests([ new RequestTracker(true, "load fires normally with no timeout set, twice", 0, TIME_REGULAR_TIMEOUT, 0),
+ new RequestTracker(true, "load fires normally with same timeout set twice", TIME_NORMAL_LOAD, TIME_REGULAR_TIMEOUT, TIME_NORMAL_LOAD),
+ new RequestTracker(true, "timeout fires normally with same timeout set twice", TIME_REGULAR_TIMEOUT, TIME_DELAY, TIME_REGULAR_TIMEOUT) ]);
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout.js b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout.js
new file mode 100644
index 00000000000..f3ef49aef63
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/xmlhttprequest-timeout.js
@@ -0,0 +1,325 @@
+/* Test adapted from Alex Vincent's XHR2 timeout tests, written for Mozilla.
+ https://hg.mozilla.org/mozilla-central/file/tip/content/base/test/
+ Released into the public domain or under BSD, according to
+ https://bugzilla.mozilla.org/show_bug.cgi?id=525816#c86
+*/
+
+/* Notes:
+ - All times are expressed in milliseconds in this test suite.
+ - Test harness code is at the end of this file.
+ - We generate only one request at a time, to avoid overloading the HTTP
+ request handlers.
+ */
+
+var TIME_NORMAL_LOAD = 1000;
+var TIME_LATE_TIMEOUT = 800;
+var TIME_XHR_LOAD = 600;
+var TIME_REGULAR_TIMEOUT = 400;
+var TIME_SYNC_TIMEOUT = 200;
+var TIME_DELAY = 200;
+
+/*
+ * This should point to a resource that responds with a text/plain resource after a delay of TIME_XHR_LOAD milliseconds.
+ */
+var STALLED_REQUEST_URL = "delay.py?ms=" + (TIME_XHR_LOAD);
+
+var inWorker = false;
+try {
+ inWorker = !(self instanceof Window);
+} catch (e) {
+ inWorker = true;
+}
+
+if (!inWorker)
+ STALLED_REQUEST_URL = "resources/" + STALLED_REQUEST_URL;
+
+function message(obj) {
+ if (inWorker)
+ self.postMessage(obj);
+ else
+ self.postMessage(obj, "*");
+}
+
+function is(got, expected, msg) {
+ var obj = {};
+ obj.type = "is";
+ obj.got = got;
+ obj.expected = expected;
+ obj.msg = msg;
+
+ message(obj);
+}
+
+function ok(bool, msg) {
+ var obj = {};
+ obj.type = "ok";
+ obj.bool = bool;
+ obj.msg = msg;
+
+ message(obj);
+}
+
+/**
+ * Generate and track results from a XMLHttpRequest with regards to timeouts.
+ *
+ * @param {String} id The test description.
+ * @param {Number} timeLimit The initial setting for the request timeout.
+ * @param {Number} resetAfter (Optional) The time after sending the request, to
+ * reset the timeout.
+ * @param {Number} resetTo (Optional) The delay to reset the timeout to.
+ *
+ * @note The actual testing takes place in handleEvent(event).
+ * The requests are generated in startXHR().
+ *
+ * @note If resetAfter and resetTo are omitted, only the initial timeout setting
+ * applies.
+ *
+ * @constructor
+ * @implements DOMEventListener
+ */
+function RequestTracker(async, id, timeLimit /*[, resetAfter, resetTo]*/) {
+ this.async = async;
+ this.id = id;
+ this.timeLimit = timeLimit;
+
+ if (arguments.length > 3) {
+ this.mustReset = true;
+ this.resetAfter = arguments[3];
+ this.resetTo = arguments[4];
+ }
+
+ this.hasFired = false;
+}
+RequestTracker.prototype = {
+ /**
+ * Start the XMLHttpRequest!
+ */
+ startXHR: function() {
+ var req = new XMLHttpRequest();
+ this.request = req;
+ req.open("GET", STALLED_REQUEST_URL, this.async);
+ var me = this;
+ function handleEvent(e) { return me.handleEvent(e); };
+ req.onerror = handleEvent;
+ req.onload = handleEvent;
+ req.onabort = handleEvent;
+ req.ontimeout = handleEvent;
+
+ req.timeout = this.timeLimit;
+
+ if (this.mustReset) {
+ var resetTo = this.resetTo;
+ self.setTimeout(function() {
+ req.timeout = resetTo;
+ }, this.resetAfter);
+ }
+
+ try {
+ req.send(null);
+ }
+ catch (e) {
+ // Synchronous case in workers.
+ ok(!this.async && this.timeLimit < TIME_XHR_LOAD && e.name == "TimeoutError", "Unexpected error: " + e);
+ TestCounter.testComplete();
+ }
+ },
+
+ /**
+ * Get a message describing this test.
+ *
+ * @returns {String} The test description.
+ */
+ getMessage: function() {
+ var rv = this.id + ", ";
+ if (this.mustReset) {
+ rv += "original timeout at " + this.timeLimit + ", ";
+ rv += "reset at " + this.resetAfter + " to " + this.resetTo;
+ }
+ else {
+ rv += "timeout scheduled at " + this.timeLimit;
+ }
+ return rv;
+ },
+
+ /**
+ * Check the event received, and if it's the right (and only) one we get.
+ *
+ * @param {DOMProgressEvent} evt An event of type "load" or "timeout".
+ */
+ handleEvent: function(evt) {
+ if (this.hasFired) {
+ ok(false, "Only one event should fire: " + this.getMessage());
+ return;
+ }
+ this.hasFired = true;
+
+ var type = evt.type, expectedType;
+ // The XHR responds after TIME_XHR_LOAD milliseconds with a load event.
+ var timeLimit = this.mustReset && (this.resetAfter < Math.min(TIME_XHR_LOAD, this.timeLimit)) ?
+ this.resetTo :
+ this.timeLimit;
+ if ((timeLimit == 0) || (timeLimit >= TIME_XHR_LOAD)) {
+ expectedType = "load";
+ }
+ else {
+ expectedType = "timeout";
+ }
+ is(type, expectedType, this.getMessage());
+ TestCounter.testComplete();
+ }
+};
+
+/**
+ * Generate and track XMLHttpRequests which will have abort() called on.
+ *
+ * @param shouldAbort {Boolean} True if we should call abort at all.
+ * @param abortDelay {Number} The time in ms to wait before calling abort().
+ */
+function AbortedRequest(shouldAbort, abortDelay) {
+ this.shouldAbort = shouldAbort;
+ this.abortDelay = abortDelay;
+ this.hasFired = false;
+}
+AbortedRequest.prototype = {
+ /**
+ * Start the XMLHttpRequest!
+ */
+ startXHR: function() {
+ var req = new XMLHttpRequest();
+ this.request = req;
+ req.open("GET", STALLED_REQUEST_URL);
+ var _this = this;
+ function handleEvent(e) { return _this.handleEvent(e); };
+ req.onerror = handleEvent;
+ req.onload = handleEvent;
+ req.onabort = handleEvent;
+ req.ontimeout = handleEvent;
+
+ req.timeout = TIME_REGULAR_TIMEOUT;
+
+ function abortReq() {
+ req.abort();
+ }
+
+ if (!this.shouldAbort) {
+ self.setTimeout(function() {
+ try {
+ _this.noEventsFired();
+ }
+ catch (e) {
+ ok(false, "Unexpected error: " + e);
+ TestCounter.testComplete();
+ }
+ }, TIME_NORMAL_LOAD);
+ }
+ else {
+ // Abort events can only be triggered on sent requests.
+ req.send();
+ if (this.abortDelay == -1) {
+ abortReq();
+ }
+ else {
+ self.setTimeout(abortReq, this.abortDelay);
+ }
+ }
+ },
+
+ /**
+ * Ensure that no events fired at all, especially not our timeout event.
+ */
+ noEventsFired: function() {
+ ok(!this.hasFired, "No events should fire for an unsent, unaborted request");
+ // We're done; if timeout hasn't fired by now, it never will.
+ TestCounter.testComplete();
+ },
+
+ /**
+ * Get a message describing this test.
+ *
+ * @returns {String} The test description.
+ */
+ getMessage: function() {
+ return "time to abort is " + this.abortDelay + ", timeout set at " + TIME_REGULAR_TIMEOUT;
+ },
+
+ /**
+ * Check the event received, and if it's the right (and only) one we get.
+ *
+ * WebKit fires abort events even for DONE and UNSENT states, which is
+ * discussed in http://webkit.org/b/98404
+ * That's why we chose to accept secondary "abort" events in this test.
+ *
+ * @param {DOMProgressEvent} evt An event of type "load" or "timeout".
+ */
+ handleEvent: function(evt) {
+ if (this.hasFired && evt.type != "abort") {
+ ok(false, "Only abort event should fire: " + this.getMessage());
+ return;
+ }
+
+ var expectedEvent = (this.abortDelay >= TIME_REGULAR_TIMEOUT && !this.hasFired) ? "timeout" : "abort";
+ this.hasFired = true;
+ is(evt.type, expectedEvent, this.getMessage());
+ TestCounter.testComplete();
+ }
+};
+
+var SyncRequestSettingTimeoutAfterOpen = {
+ startXHR: function() {
+ var pass = false;
+ var req = new XMLHttpRequest();
+ req.open("GET", STALLED_REQUEST_URL, false);
+ try {
+ req.timeout = TIME_SYNC_TIMEOUT;
+ }
+ catch (e) {
+ pass = true;
+ }
+ ok(pass, "Synchronous XHR must not allow a timeout to be set - setting timeout must throw");
+ TestCounter.testComplete();
+ }
+};
+
+var SyncRequestSettingTimeoutBeforeOpen = {
+ startXHR: function() {
+ var pass = false;
+ var req = new XMLHttpRequest();
+ req.timeout = TIME_SYNC_TIMEOUT;
+ try {
+ req.open("GET", STALLED_REQUEST_URL, false);
+ }
+ catch (e) {
+ pass = true;
+ }
+ ok(pass, "Synchronous XHR must not allow a timeout to be set - calling open() after timeout is set must throw");
+ TestCounter.testComplete();
+ }
+};
+
+var TestRequests = [];
+
+// This code controls moving from one test to another.
+var TestCounter = {
+ testComplete: function() {
+ // Allow for the possibility there are other events coming.
+ self.setTimeout(function() {
+ TestCounter.next();
+ }, TIME_NORMAL_LOAD);
+ },
+
+ next: function() {
+ var test = TestRequests.shift();
+
+ if (test) {
+ test.startXHR();
+ }
+ else {
+ message("done");
+ }
+ }
+};
+
+function runTestRequests(testRequests) {
+ TestRequests = testRequests;
+ TestCounter.next();
+}
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/resources/zlib.py b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/zlib.py
new file mode 100644
index 00000000000..49ed69de793
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/resources/zlib.py
@@ -0,0 +1,19 @@
+import zlib
+
+def main(request, response):
+ if "content" in request.GET:
+ output = request.GET["content"]
+ else:
+ output = request.body
+
+ output = zlib.compress(output, 9)
+
+ headers = [("Content-type", "text/plain"),
+ ("Content-Encoding", "deflate"),
+ ("X-Request-Method", request.method),
+ ("X-Request-Query", request.url_parts.query if request.url_parts.query else "NO"),
+ ("X-Request-Content-Length", request.headers.get("Content-Length", "NO")),
+ ("X-Request-Content-Type", request.headers.get("Content-Type", "NO")),
+ ("Content-Length", len(output))]
+
+ return headers, output
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/response-data-arraybuffer.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/response-data-arraybuffer.htm
new file mode 100644
index 00000000000..7eaf7198ae2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/response-data-arraybuffer.htm
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-responsetype-attribute" data-tested-assertations="following::ol[1]/li[4]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-response-attribute" data-tested-assertations="following::a[contains(@href,'#arraybuffer-response-entity-body')]/.." />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <title>XMLHttpRequest: The response attribute: ArrayBuffer data</title>
+</head>
+
+<body>
+ <div id="log"></div>
+
+ <script type="text/javascript">
+ var test = async_test();
+
+ test.step(function()
+ {
+ var xhr = new XMLHttpRequest();
+
+ xhr.onreadystatechange = function()
+ {
+ if (xhr.readyState == 4)
+ {
+ test.step(function()
+ {
+ assert_equals(xhr.status, 200);
+
+ var buf = xhr.response;
+ assert_true(buf instanceof ArrayBuffer);
+
+ var arr = new Uint8Array(buf);
+ assert_equals(arr.length, 5);
+ assert_equals(arr[0], 0x48, "Expect 'H'");
+ assert_equals(arr[1], 0x65, "Expect 'e'");
+ assert_equals(arr[2], 0x6c, "Expect 'l'");
+ assert_equals(arr[3], 0x6c, "Expect 'l'");
+ assert_equals(arr[4], 0x6f, "Expect 'o'");
+
+ assert_equals(xhr.response, xhr.response,
+ "Response should be cached");
+
+ test.done();
+ });
+ }
+ };
+
+ xhr.open("GET", "./resources/content.py?content=Hello", true);
+ xhr.responseType = "arraybuffer";
+ xhr.send();
+ });
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/response-data-blob.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/response-data-blob.htm
new file mode 100644
index 00000000000..19731d3dc1e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/response-data-blob.htm
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-send()-method" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-responsetype-attribute" data-tested-assertations="following::ol[1]/li[4]"/>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-response-attribute" data-tested-assertations="following::a[contains(@href,'#blob-response-entity-body')]/.." />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <title>XMLHttpRequest: The response attribute: Blob data</title>
+</head>
+
+<body>
+ <div id="log"></div>
+
+ <script type="text/javascript">
+ var test = async_test();
+
+ test.step(function()
+ {
+ var xhr = new XMLHttpRequest();
+ var content = "Hello";
+ var blob;
+
+ xhr.onreadystatechange = function()
+ {
+ if (xhr.readyState == 4)
+ {
+ test.step(function()
+ {
+ blob = xhr.response;
+ assert_equals(xhr.response, xhr.response,
+ "Response should be cached");
+ assert_true(blob instanceof Blob, 'blob is a Blob');
+
+ var reader = new FileReader();
+ reader.onload = function()
+ {
+ test.step(function()
+ {
+ assert_equals(reader.result, content);
+ test.done();
+ });
+ };
+ reader.readAsText(blob);
+ });
+ }
+ }
+
+ xhr.open("GET", "./resources/content.py?content=" + content, true);
+ xhr.responseType = "blob";
+ xhr.send();
+ });
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/response-data-deflate.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/response-data-deflate.htm
new file mode 100644
index 00000000000..bce2745f4f7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/response-data-deflate.htm
@@ -0,0 +1,42 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: content-encoding:deflate response was correctly inflated</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://dvcs.w3.org/hg/xhr/raw-file/tip/Overview.html#the-send()-method" data-tested-assertations="following::p[contains(text(),'content-encodings')]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ function request(input) {
+ var test = async_test();
+ test.step(function() {
+ var client = new XMLHttpRequest()
+
+ client.open("POST", "resources/zlib.py", false);
+
+ client.onreadystatechange = test.step_func(function () {
+ if (client.readyState === 4) {
+ var len = parseInt(client.getResponseHeader('content-length'), 10);
+
+ assert_equals(client.getResponseHeader('content-encoding'), 'deflate');
+ assert_true(len < input.length);
+ assert_equals(client.responseText, input);
+ test.done();
+ }
+ });
+
+ client.send(input);
+ });
+ }
+
+ var wellCompressableData = '';
+ for (var i = 0; i < 500; i++) {
+ wellCompressableData += 'foofoofoofoofoofoofoo';
+ }
+
+ request(wellCompressableData);
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/response-data-gzip.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/response-data-gzip.htm
new file mode 100644
index 00000000000..a3d2713d0f4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/response-data-gzip.htm
@@ -0,0 +1,42 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: GZIP response was correctly inflated</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://dvcs.w3.org/hg/xhr/raw-file/tip/Overview.html#the-send()-method" data-tested-assertations="following::p[contains(text(),'content-encodings')]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ function request(input) {
+ var test = async_test();
+ test.step(function() {
+ var client = new XMLHttpRequest()
+
+ client.open("POST", "resources/gzip.py", false);
+
+ client.onreadystatechange = test.step_func(function () {
+ if (client.readyState === 4) {
+ var len = parseInt(client.getResponseHeader('content-length'), 10);
+
+ assert_equals(client.getResponseHeader('content-encoding'), 'gzip');
+ assert_true(len < input.length);
+ assert_equals(client.responseText, input);
+ test.done();
+ }
+ });
+
+ client.send(input);
+ }, document.title);
+ }
+
+ var wellCompressableData = '';
+ for (var i = 0; i < 500; i++) {
+ wellCompressableData += 'foofoofoofoofoofoofoo';
+ }
+
+ request(wellCompressableData);
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/response-data-progress.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/response-data-progress.htm
new file mode 100644
index 00000000000..3c5ec0e5f50
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/response-data-progress.htm
@@ -0,0 +1,45 @@
+<!doctype html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <title>XMLHttpRequest: progress events grow response body size</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-send()-method" data-tested-assertations="following::a[contains(@href,'#make-progress-notifications')]/.. following::a[contains(@href,'#make-progress-notifications')]/../following:p[1]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#make-progress-notifications" data-tested-assertations=".." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#handler-xhr-onprogress" data-tested-assertations="/../.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#event-xhr-progress" data-tested-assertations="/../.." />
+</head>
+
+<div id="log"></div>
+
+<script>
+
+var test = async_test();
+
+test.step(function() {
+ var client = new XMLHttpRequest();
+ var lastSize = 0;
+
+ client.onprogress = test.step_func(function() {
+ var currentSize = client.responseText.length;
+
+ if (lastSize > 0 && currentSize > lastSize) {
+ // growth from a positive size to bigger!
+
+ test.done();
+ }
+
+ lastSize = currentSize;
+ });
+
+ client.onreadystatechange = test.step_func(function() {
+ if (client.readyState === 4) {
+ assert_unreached("onprogress not called multiple times, or response body did not grow.");
+ }
+ });
+
+ client.open("GET", "resources/trickle.py?count=1000");
+ client.send(null);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/response-invalid-responsetype.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/response-invalid-responsetype.htm
new file mode 100644
index 00000000000..603c4cd0ed7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/response-invalid-responsetype.htm
@@ -0,0 +1,38 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: response is plain text if responseType is set to an invalid string</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-response-attribute" data-tested-assertations="following::dd[2]/ol[1]/li[2]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-responsetype-attribute" data-tested-assertations="following::ol[1]/li[4]" /><!-- Not quite - but this is handled in WebIDL, not the XHR spec -->
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ function request(type) {
+ var test = async_test(document.title+' ('+type+')')
+ test.step(function() {
+ var client = new XMLHttpRequest()
+ client.responseType = type
+ assert_equals(client.responseType, '')
+ client.open("GET", "resources/folder.txt", true)
+ client.onload = function(){
+ test.step(function(){
+ assert_equals(client.responseType, '')
+ assert_equals(client.response, 'bottom\n')
+ assert_equals(typeof client.response, 'string')
+ test.done()
+ })
+ }
+ client.send(null)
+ })
+ }
+ request("arrayBuffer") // case sensitive
+ request("JSON") // case sensitive
+ request("glob")
+ request("txt")
+ request("text/html")
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/response-json.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/response-json.htm
new file mode 100644
index 00000000000..a694d7fc615
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/response-json.htm
@@ -0,0 +1,61 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: responseType json</title>
+ <meta charset="utf-8">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-responsetype-attribute" data-tested-assertations="following::OL[1]/LI[4]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-response-attribute" data-tested-assertations="following::dt[2]/dt[4] following::dt[2]/dt[4]/following::dd[1]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#json-response-entity-body" data-tested-assertations="following::ol[1]/li[1] following::ol[1]/li[2] following::ol[1]/li[3]" />
+
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ function setupXHR () {
+ var client = new XMLHttpRequest()
+ client.open('POST', "resources/content.py", true)
+ client.responseType = 'json'
+ return client
+ }
+ function makeTest(data, expectedResponse, description){
+ var test = async_test(description)
+ var xhr = setupXHR()
+ assert_equals(xhr.responseType, 'json')
+ xhr.onreadystatechange = function(){
+ if(xhr.readyState === 4){
+ test.step(function(){
+ assert_equals(xhr.status, 200)
+ assert_equals(xhr.responseType, 'json')
+ assert_equals(typeof xhr.response, 'object')
+ if(expectedResponse){ // if the expectedResponse is not null, we iterate over properties to do a deeper comparison..
+ for(var prop in expectedResponse){
+ if (expectedResponse[prop] instanceof Array) {
+ assert_array_equals(expectedResponse[prop], xhr.response[prop])
+ }else{
+ assert_equals(expectedResponse[prop], xhr.response[prop])
+ }
+ }
+ }else{
+ assert_equals(xhr.response, expectedResponse) // null comparison, basically
+ }
+ assert_equals(xhr.response, xhr.response,
+ "Response should be cached")
+ test.done()
+ })
+ }
+ }
+ xhr.send(data)
+ }
+ // no data
+ makeTest("", null, 'json response with no data: response property is null')
+ // malformed
+ makeTest('{"test":"foo"', null, 'json response with malformed data: response property is null')
+ // real object
+ var obj = {alpha:'a-z', integer:15003, negated:-20, b1:true, b2:false, myAr:['a', 'b', 'c', 1, 2, 3]}
+ makeTest(JSON.stringify(obj), obj, 'JSON object roundtrip')
+ makeTest('{"日本語":"にほんご"}', {"日本語":"にほんご"}, 'JSON roundtrip with Japanese text')
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/responsetext-decoding.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/responsetext-decoding.htm
new file mode 100644
index 00000000000..7f179e6f306
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/responsetext-decoding.htm
@@ -0,0 +1,52 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: responseText decoding</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-responsetext-attribute" data-tested-assertations="following::ol[1]/li[4]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#text-response-entity-body" data-tested-assertations="following::ol[1]/li[2] following::ol[1]/li[3] following::ol[1]/li[4] following::ol[1]/li[5]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ function request(type, input, output, responseType) {
+ var test = async_test(document.title + " (" + type + " " + input + ")");
+ test.step(function() {
+ var client = new XMLHttpRequest()
+ if (responseType !== undefined) {
+ client.responseType = responseType
+ }
+ client.open("GET", "resources/status.py?content=" + input + "&type=" + encodeURIComponent(type), true)
+ client.onload = function(){
+ test.step(function(){
+ assert_equals(client.responseText, output)
+ test.done()
+ })
+ }
+ client.send(null)
+ })
+ }
+ request("application/xml", encodeURIComponent("<?xml version='1.0' encoding='windows-1252'?><x>")+'%FF'+encodeURIComponent("<\/x>"), "<?xml version='1.0' encoding='windows-1252'?><x>\u00FF<\/x>")
+ request("text/html", encodeURIComponent("<!doctype html><meta charset=windows-1252>")+"%FF", "<!doctype html><meta charset=windows-1252>\u00FF")
+ request("text/plain;charset=windows-1252", "%FF", "\u00FF")
+ request("text/plain", "%FF", "\uFFFD")
+ request("text/plain", "%FE%FF", "")
+ request("text/plain", "%FE%FF%FE%FF", "\uFEFF")
+ request("text/plain", "%EF%BB%BF", "")
+ request("text/plain", "%EF%BB%BF%EF%BB%BF", "\uFEFF")
+ request("text/plain", "%C2", "\uFFFD")
+
+ // XXX might need fixing
+ request("text/xml", "%FE%FF", "")
+ request("text/xml", "%FE%FF%FE%FF", "\uFEFF")
+ request("text/xml", "%EF%BB%BF", "")
+ request("text/xml", "%EF%BB%BF%EF%BB%BF", "\uFEFF")
+ request("text/plain", "%E3%81%B2", "\u3072", 'text')
+ // the point of the following test: setting responseType=text should (per spec #text-response-entity-body point 3)
+ // skip some of the charset detection even for XML resources. The test uses a wilfully mislabelled XMLish response
+ // and the pass condition is that the responseType = text makes the decoder fall back to UTF-8
+ request("text/xml", encodeURIComponent("<?xml version='1.0' encoding='windows-1252'?><x>")+"%E3%81%B2"+encodeURIComponent("<\/x>"), "<?xml version='1.0' encoding='windows-1252'?><x>\u3072<\/x>", 'text')
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/responsetype.html b/tests/wpt/web-platform-tests/XMLHttpRequest/responsetype.html
new file mode 100644
index 00000000000..ade604417a9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/responsetype.html
@@ -0,0 +1,96 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>XMLHttpRequest.responseType</title>
+<link rel="author" title="Mathias Bynens" href="http://mathiasbynens.be/">
+<link rel="author" title="Ms2ger" href="mailto:Ms2ger@gmail.com">
+<link rel="help" href="https://xhr.spec.whatwg.org/#the-responsetype-attribute">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ var xhr = new XMLHttpRequest();
+ assert_equals(xhr.responseType, '');
+}, 'Initial value of responseType');
+
+var types = ['', 'json', 'document', 'arraybuffer', 'blob', 'text'];
+types.forEach(function(type) {
+ test(function() {
+ var xhr = new XMLHttpRequest();
+ xhr.responseType = type;
+ assert_equals(xhr.responseType, type);
+ }, 'Set responseType to ' + format_value(type) + ' when readyState is UNSENT.');
+
+ test(function() {
+ var xhr = new XMLHttpRequest();
+ xhr.open('get', '/');
+ xhr.responseType = type;
+ assert_equals(xhr.responseType, type);
+ }, 'Set responseType to ' + format_value(type) + ' when readyState is OPENED.');
+
+ async_test(function() {
+ var xhr = new XMLHttpRequest();
+ xhr.open('get', '/');
+ xhr.onreadystatechange = this.step_func(function() {
+ if (xhr.readyState === XMLHttpRequest.HEADERS_RECEIVED) {
+ xhr.responseType = type;
+ assert_equals(xhr.responseType, type);
+ this.done();
+ }
+ });
+ xhr.send();
+ }, 'Set responseType to ' + format_value(type) + ' when readyState is HEADERS_RECEIVED.');
+
+ async_test(function() {
+ var xhr = new XMLHttpRequest();
+ xhr.open('get', '/');
+ xhr.onreadystatechange = this.step_func(function() {
+ if (xhr.readyState === XMLHttpRequest.LOADING) {
+ assert_throws("InvalidStateError", function() {
+ xhr.responseType = type;
+ });
+ assert_equals(xhr.responseType, "");
+ this.done();
+ }
+ });
+ xhr.send();
+ }, 'Set responseType to ' + format_value(type) + ' when readyState is LOADING.');
+
+ async_test(function() {
+ var xhr = new XMLHttpRequest();
+ xhr.open('get', '/');
+ xhr.onreadystatechange = this.step_func(function() {
+ if (xhr.readyState === XMLHttpRequest.DONE) {
+ assert_throws("InvalidStateError", function() {
+ xhr.responseType = type;
+ });
+ assert_equals(xhr.responseType, "");
+ this.done();
+ }
+ });
+ xhr.send();
+ }, 'Set responseType to ' + format_value(type) + ' when readyState is DONE.');
+
+ // Note: the case of setting responseType first, and then calling synchronous
+ // open(), is tested in open-method-responsetype-set-sync.htm.
+ test(function() {
+ var xhr = new XMLHttpRequest();
+ xhr.open('get', '/', false);
+ assert_throws("InvalidAccessError", function() {
+ xhr.responseType = type;
+ });
+ assert_equals(xhr.responseType, "");
+ }, 'Set responseType to ' + format_value(type) + ' when readyState is OPENED and the sync flag is set.');
+
+ test(function() {
+ var xhr = new XMLHttpRequest();
+ xhr.open('get', '/', false);
+ xhr.send();
+ assert_equals(xhr.readyState, XMLHttpRequest.DONE);
+ assert_throws("InvalidStateError", function() {
+ xhr.responseType = type;
+ });
+ assert_equals(xhr.responseType, "");
+ }, 'Set responseType to ' + format_value(type) + ' when readyState is DONE and the sync flag is set.');
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/responsexml-basic.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/responsexml-basic.htm
new file mode 100644
index 00000000000..8bc1ff52018
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/responsexml-basic.htm
@@ -0,0 +1,33 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: responseXML basic test</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-responsexml-attribute" data-tested-assertations="following::ol[1]/li[2] following::ol[1]/li[4]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#document-response-entity-body" data-tested-assertations="following::ol[1]/li[1] following::ol[1]/li[6] following::ol[1]/li[10]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ test(function() {
+ var client = new XMLHttpRequest()
+ assert_equals(client.responseXML, null)
+ client.open("GET", "resources/well-formed.xml", false)
+ assert_equals(client.responseXML, null)
+ client.send(null)
+ assert_equals(client.responseXML.documentElement.localName, "html", 'localName is html')
+ assert_equals(client.responseXML.documentElement.childNodes.length, 5, 'childNodes is 5')
+ assert_equals(client.responseXML.getElementById("n1").localName, client.responseXML.documentElement.childNodes[1].localName)
+ assert_equals(client.responseXML.getElementById("n2"), null, 'getElementById("n2")')
+ assert_equals(client.responseXML.getElementsByTagName("p")[1].namespaceURI, "namespacesarejuststrings", 'namespaceURI')
+ })
+ test(function() {
+ var client = new XMLHttpRequest()
+ client.open("GET", "resources/status.py?type=application/xml", false)
+ client.send(null)
+ assert_equals(client.responseXML, null)
+ }, 'responseXML on empty response documents')
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/responsexml-document-properties.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/responsexml-document-properties.htm
new file mode 100644
index 00000000000..ef4d5906cf7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/responsexml-document-properties.htm
@@ -0,0 +1,63 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: responseXML document properties</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-responsexml-attribute" data-tested-assertations="following::ol[1]/li[4]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#document-response-entity-body" data-tested-assertations="following::ol[1]/li[6] following::ol[1]/li[7] following::ol[1]/li[8] following::ol[1]/li[10]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var client = new XMLHttpRequest()
+ client.open("GET", "resources/well-formed.xml", false)
+ client.send(null)
+ var expected = {
+ domain:undefined,
+ URL:location.href.replace(/[^/]*$/, 'resources/well-formed.xml'),
+ documentURI:location.href.replace(/[^/]*$/, 'resources/well-formed.xml'),
+ referrer:'',
+ title:'',
+ contentType:'application/xml',
+ readyState:'complete',
+ location:null,
+ defaultView:null,
+ body:undefined,
+ images: undefined,
+ doctype:null,
+ forms:undefined,
+ all:undefined,
+ links: undefined,
+ cookie:''
+ }
+
+ for (var name in expected) {
+ runTest(name, expected[name])
+ }
+
+ function runTest(name, value){
+ test(function(){
+ assert_equals(client.responseXML[name], value)
+ }, name)
+ }
+
+ test(function() {
+ assert_equals((new Date(client.getResponseHeader('Last-Modified'))).getTime(), (new Date(client.responseXML.lastModified)).getTime())
+ }, 'lastModified set according to HTTP header')
+
+ test(function() {
+ client.responseXML.cookie = "thisshouldbeignored"
+ assert_equals(client.responseXML.cookie, "")
+ }, 'cookie (after setting it)')
+
+ test(function() {
+ assert_equals(typeof(client.responseXML.styleSheets), "object")
+ }, 'styleSheets')
+
+ test(function() {
+ assert_equals(typeof(client.responseXML.implementation), "object")
+ }, 'implementation')
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/responsexml-media-type.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/responsexml-media-type.htm
new file mode 100644
index 00000000000..ece413d51b8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/responsexml-media-type.htm
@@ -0,0 +1,41 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: responseXML MIME type tests</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-responsexml-attribute" data-tested-assertations="following::ol[1]/li[4]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#document-response-entity-body" data-tested-assertations="following::ol[1]/li[3] following::ol[1]/li[4] following::ol[1]/li[6] following::ol[1]/li[10]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ function request(type, succeed) {
+ test(function() {
+ var client = new XMLHttpRequest()
+ client.open("GET", "resources/status.py?content=<x><\/x>&type=" + encodeURIComponent(type), false)
+ client.send(null)
+ if(!succeed)
+ assert_equals(client.responseXML, null)
+ else
+ assert_equals(client.responseXML.documentElement.localName, "x")
+ }, document.title + " ('" + type + "', should "+(succeed?'':'not')+" parse)")
+ }
+ request("", true)
+ request("text/html", false)
+ request("bogus", true)
+ request("bogus+xml", true)
+ request("text/plain;+xml", false)
+ request("text/plainxml", false)
+ request("video/x-awesome+xml", true)
+ request("video/x-awesome", false)
+ request("text/xml", true)
+ request("application", true)
+ request("text/xsl", false)
+ request("text/plain", false)
+ request("application/rdf", false)
+ request("application/xhtml+xml", true)
+ request("image/svg+xml", true)
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/responsexml-non-document-types.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/responsexml-non-document-types.htm
new file mode 100644
index 00000000000..84d90a8d35a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/responsexml-non-document-types.htm
@@ -0,0 +1,45 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: responseXML/responseText on other responseType</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-responsexml-attribute" data-tested-assertations="following::ol[1]/li[1]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-responsetext-attribute" data-tested-assertations="following::ol[1]/li[1]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-responsetype-attribute" data-tested-assertations="following::ol[1]/li[4]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ function request(type) {
+ var test = async_test(document.title+' ('+type+')')
+ test.step(function() {
+ var client = new XMLHttpRequest()
+ client.responseType = type
+ client.open("GET", "resources/well-formed.xml", true)
+ client.onload = function(){
+ test.step(function(){
+ if(type !== 'document'){
+ assert_throws("InvalidStateError", function() {
+ var x = client.responseXML;
+ }, 'responseXML throw for '+type)
+ }
+ if(type !== 'text'){
+ assert_throws("InvalidStateError", function() {
+ var x = client.responseText;
+ }, 'responseText throws for '+type)
+ }
+ test.done()
+ })
+ }
+ client.send(null)
+ })
+ }
+ request("arraybuffer")
+ request("blob")
+ request("json")
+ request("text")
+ request("document")
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/responsexml-non-well-formed.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/responsexml-non-well-formed.htm
new file mode 100644
index 00000000000..216da81706d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/responsexml-non-well-formed.htm
@@ -0,0 +1,30 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: responseXML non well-formed tests</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-responsexml-attribute" data-tested-assertations="following::ol[1]/li[4]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#document-response-entity-body" data-tested-assertations="following::ol[1]/li[6] following::ol[1]/li[10]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ function request(content) {
+ test(function() {
+ var client = new XMLHttpRequest()
+ client.open("GET", "resources/status.py?type=text/xml&content=" + encodeURIComponent(content), false)
+ client.send(null)
+ assert_equals(client.responseXML, null)
+ })
+ }
+ request("<x")
+ request("<x></x")
+ request("<x>&amp</x>")
+ request("<x><y></x></y>") // misnested tags
+ request("<x></x><y></y>") // two root elements is not allowed
+ request("<x> <![CDATA[ foobar ]></x>") // CDATA should end with ]]>
+ request("<x> <!CDATA[ foobar ]]></x>") // CDATA should start with <![
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/security-consideration.sub.html b/tests/wpt/web-platform-tests/XMLHttpRequest/security-consideration.sub.html
new file mode 100644
index 00000000000..7d42e947f20
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/security-consideration.sub.html
@@ -0,0 +1,30 @@
+<!doctype html>
+<html>
+ <head>
+ <title>ProgressEvent: security consideration</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#security-considerations" data-tested-assertations="/following-sibling::p" />
+ <link rel="help" href="https://fetch.spec.whatwg.org/#http-fetch" data-tested-assertations="/following-sibling::ol[1]/li[3]/ol[1]/li[6]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ async_test(function() {
+ var xhr = new XMLHttpRequest();
+
+ xhr.onprogress = this.unreached_func("MUST NOT dispatch progress event.");
+ xhr.onload = this.unreached_func("MUST NOT dispatch load event.");
+ xhr.onerror = this.step_func(function(pe) {
+ assert_equals(pe.type, "error");
+ assert_equals(pe.loaded, 0, "loaded is zero.");
+ assert_false(pe.lengthComputable, "lengthComputable is false.");
+ assert_equals(pe.total, 0, "total is zero.");
+ });
+ xhr.onloadend = this.step_func_done();
+ xhr.open("GET", "http://{{host}}:{{ports[http][1]}}/XMLHttpRequest/resources/img.jpg", true);
+ xhr.send(null);
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-accept-language.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-accept-language.htm
new file mode 100644
index 00000000000..c798cd548f4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-accept-language.htm
@@ -0,0 +1,27 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: send() - Accept-Language</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-send()-method" data-tested-assertations="following::code[contains(text(),'Accept-Language')]/.. following::code[contains(text(),'Accept-Language')]/../following::ul[1]/li[1] following::code[contains(text(),'Accept-Language')]/../following::ul[1]/li[2]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ test(function() {
+ var client = new XMLHttpRequest()
+ client.open('GET', 'resources/inspect-headers.py?filter_name=accept-language', false)
+ client.send(null)
+ assert_regexp_match(client.responseText, /accept-language:\s.+/)
+ }, 'Send "sensible" default value, whatever that means')
+ test(function() {
+ var client = new XMLHttpRequest()
+ client.open("GET", "resources/inspect-headers.py?filter_name=accept-language", false)
+ client.setRequestHeader("Accept-Language", "x-GameSpeak")
+ client.send(null)
+ assert_equals(client.responseText, "accept-language: x-GameSpeak\n")
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-accept.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-accept.htm
new file mode 100644
index 00000000000..2731eb6be18
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-accept.htm
@@ -0,0 +1,24 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: send() - Accept</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-send()-method" data-tested-assertations="following::code[contains(text(),'*/*')]/.. following::code[contains(text(),'Accept')]/.. following::code[contains(text(),'Accept')]/../following::ul[1]/li[1]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ test(function() {
+ var client = new XMLHttpRequest()
+ client.open("GET", "resources/accept.py", false)
+ client.send(null)
+ assert_equals(client.responseText, "*/*")
+ client.open("GET", "resources/accept.py", false)
+ client.setRequestHeader("Accept", "x-something/vague, text/html5")
+ client.send(null)
+ assert_equals(client.responseText, "x-something/vague, text/html5")
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-after-setting-document-domain.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-after-setting-document-domain.htm
new file mode 100644
index 00000000000..943fb9495ee
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-after-setting-document-domain.htm
@@ -0,0 +1,38 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: send() with document.domain set</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!-- The spec doesn't seem to explicitly cover this case (as of June 2013) -->
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-open()-method" data-tested-assertations="following::ol[1]/li[2]/ol[1]/li[3]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ // first make sure we actually run off a domain with at least three parts, in order to be able to shorten it..
+ if (location.hostname.split(/\./).length < 3) {
+ location.href = location.protocol+'//www2.'+location.host+location.pathname
+ }
+
+ test(function() {
+ document.domain = document.domain // this is not a noop, it does actually change the security context
+ var client = new XMLHttpRequest()
+ client.open("GET", "resources/status.py?content=hello", false)
+ client.send(null)
+ assert_equals(client.responseText, "hello")
+ document.domain = document.domain.replace(/^\w+\./, '')
+ client.open("GET", "resources/status.py?content=hello2", false)
+ client.send(null)
+ assert_equals(client.responseText, "hello2")
+ }, "loading documents from original origin after setting document.domain")
+ // try to load a document from the origin document.domain was set to
+ test(function () {
+ var client = new XMLHttpRequest()
+ client.open("GET", location.protocol + '//' + document.domain + location.pathname.replace(/[^\/]*$/, '') + "resources/status.py?content=hello3", false)
+ // AFAIK this should throw
+ assert_throws('NetworkError', function(){client.send(null)})
+ }, "loading documents from the origin document.domain was set to should throw")
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-authentication-basic-cors-not-enabled.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-authentication-basic-cors-not-enabled.htm
new file mode 100644
index 00000000000..070b2ba3212
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-authentication-basic-cors-not-enabled.htm
@@ -0,0 +1,28 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: send() - "Basic" authenticated CORS requests with user name and password passed to open() (asserts failure)</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/utils.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-open()-method" data-tested-assertations="following::ol[1]/li[9]/ol[1]/li[1] following::ol[1]/li[9]/ol[1]/li[2]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-send()-method" data-tested-assertations="following::code[contains(@title,'http-authorization')]/.." />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ test(function() {
+ var client = new XMLHttpRequest(),
+ urlstart = 'www1.'+location.host + location.pathname.replace(/\/[^\/]*$/, '/')
+ client.withCredentials = true
+ user = token()
+ client.open("GET", location.protocol+'//'+urlstart + "resources/auth1/auth.py", false, user, 'pass')
+ client.setRequestHeader("x-user", user)
+ assert_throws("NetworkError", function(){ client.send(null) })
+ assert_equals(client.responseText, '')
+ assert_equals(client.status, 0)
+ assert_equals(client.getResponseHeader('x-challenge'), null)
+ }, document.title)
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-authentication-basic-cors.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-authentication-basic-cors.htm
new file mode 100644
index 00000000000..fcacdd5fec4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-authentication-basic-cors.htm
@@ -0,0 +1,35 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: send() - "Basic" authenticated CORS requests with user name and password passed to open() (asserts failure)</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-open()-method" data-tested-assertations="following::ol[1]/li[9]/ol[1]/li[1] following::ol[1]/li[9]/ol[1]/li[2]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-send()-method" data-tested-assertations="following::code[contains(@title,'http-authorization')]/.." />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+ var client = new XMLHttpRequest(),
+ urlstart = 'www1.'+location.host + location.pathname.replace(/\/[^\/]*$/, '/')
+ client.withCredentials = true
+ client.open("GET", location.protocol+'//'+urlstart + "resources/auth1/corsenabled.py", true, 'user', 'pass')
+ client.setRequestHeader("x-user", 'user')
+ client.setRequestHeader("x-pass", 'pass')
+ client.onreadystatechange = function(){
+ if (client.readyState === 4) {
+ test.step(function(){
+ assert_equals(client.responseText, '')
+ assert_equals(client.status, 0)
+ assert_equals(client.getResponseHeader('x-challenge'), null)
+ test.done()
+ })
+ }
+ }
+ client.send(null)
+ }, document.title)
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-authentication-basic-repeat-no-args.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-authentication-basic-repeat-no-args.htm
new file mode 100644
index 00000000000..464d69cf789
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-authentication-basic-repeat-no-args.htm
@@ -0,0 +1,33 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: send() - "Basic" authenticated requests with user name and password passed to open() in first request, without in second</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/utils.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-open()-method" data-tested-assertations="following::ol[1]/li[9]/ol[1]/li[1] following::ol[1]/li[9]/ol[1]/li[2]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-send()-method" data-tested-assertations="following::code[contains(@title,'http-authorization')]/.." />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ test(function() {
+ var client = new XMLHttpRequest(),
+ urlstart = location.host + location.pathname.replace(/\/[^\/]*$/, '/'),
+ user = token()
+ client.open("GET", location.protocol+'//'+urlstart + "resources/auth1/auth.py", false, user, 'pass')
+ client.setRequestHeader("x-user", user)
+ client.send(null)
+ // Repeat request but *without* credentials in the open() call.
+ // Is the UA supposed to cache credentials from above request and use them? Yes.
+ client.open("GET", location.protocol+'//'+urlstart + "resources/auth1/auth.py", false)
+ client.setRequestHeader("x-user", user)
+ client.send(null)
+
+ assert_equals(client.responseText, user + "\n" + 'pass')
+ //assert_equals(client.getResponseHeader('x-challenge'), 'DID-NOT')
+
+ }, document.title)
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-authentication-basic-setrequestheader-existing-session.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-authentication-basic-setrequestheader-existing-session.htm
new file mode 100644
index 00000000000..5b8932c2c63
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-authentication-basic-setrequestheader-existing-session.htm
@@ -0,0 +1,53 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: send() - "Basic" authenticated request using setRequestHeader() when there is an existing session</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/utils.js"></script>
+ <!-- These spec references do not make much sense simply because the spec doesn't say very much about this.. -->
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-setrequestheader()-method" data-tested-assertations="following::ol[1]/li[6]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-send()-method" data-tested-assertations="following::code[contains(@title,'http-authorization')]/.." />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+ var client = new XMLHttpRequest(),
+ urlstart = location.host + location.pathname.replace(/\/[^\/]*$/, '/')
+ // Initial request: no information is known to the UA about whether resources/auth4/auth.py requires authentication,
+ // hence it first sends a normal request, gets a 401 response that will not be passed on to the JS, and sends a new
+ // request with an Authorization header before returning
+ // (Note: this test will only work as expected if run once per browsing session)
+ var open_user = token()
+ client.open("GET", location.protocol+'//'+urlstart + "resources/auth4/auth.py", false, open_user, 'open-pass')
+ client.setRequestHeader('X-User', open_user)
+ // initial request - this will get a 401 response and re-try with HTTP auth
+ client.send(null)
+ assert_equals(client.responseText, open_user + '\nopen-pass')
+ assert_equals(client.status, 200)
+ assert_equals(client.getResponseHeader('x-challenge'), 'DID')
+ // Another request, this time user,pass is omitted and an Authorization header set explicitly
+ // Here the URL is known to require authentication (from the request above), and the UA has cached open-user:open-pass credentials
+ // However, these session credentials should now be overridden by the setRequestHeader() call so the UA should immediately
+ // send basic Authorization header with credentials user:pass. (This part is perhaps not well specified anywhere)
+ var user = token();
+ client.open("GET", location.protocol+'//'+urlstart + "resources/auth4/auth.py", true)
+ client.setRequestHeader("x-user", user)
+ client.setRequestHeader('Authorization', 'Basic ' + btoa(user + ":pass"))
+ client.onreadystatechange = function () {
+ if (client.readyState < 4) {return}
+ test.step( function () {
+ assert_equals(client.responseText, user + '\npass')
+ assert_equals(client.status, 200)
+ assert_equals(client.getResponseHeader('x-challenge'), 'DID-NOT')
+ test.done()
+ } )
+ }
+ client.send(null)
+ })
+ </script>
+ <p>Note: this test will only work as expected once per browsing session. Restart browser to re-test.</p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-authentication-basic-setrequestheader.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-authentication-basic-setrequestheader.htm
new file mode 100644
index 00000000000..84d0dd6b2cd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-authentication-basic-setrequestheader.htm
@@ -0,0 +1,36 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: send() - "Basic" authenticated request using setRequestHeader()</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/utils.js"></script>
+ <!-- These spec references do not make much sense simply because the spec doesn't say very much about this.. -->
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-setrequestheader()-method" data-tested-assertations="following::ol[1]/li[6]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-send()-method" data-tested-assertations="following::code[contains(@title,'http-authorization')]/.." />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+ var client = new XMLHttpRequest(),
+ urlstart = location.host + location.pathname.replace(/\/[^\/]*$/, '/'),
+ user = token()
+ client.open("GET", location.protocol+'//'+urlstart + "resources/auth2/auth.py", false)
+ client.setRequestHeader("x-user", user)
+ client.setRequestHeader('Authorization', 'Basic ' + btoa(user + ":pass"))
+ client.onreadystatechange = function () {
+ if (client.readyState < 4) {return}
+ test.step( function () {
+ assert_equals(client.responseText, user + '\npass')
+ assert_equals(client.status, 200)
+ assert_equals(client.getResponseHeader('x-challenge'), 'DID-NOT')
+ test.done()
+ } )
+ }
+ client.send(null)
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-authentication-basic.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-authentication-basic.htm
new file mode 100644
index 00000000000..ae3ee571141
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-authentication-basic.htm
@@ -0,0 +1,27 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: send() - "Basic" authenticated requests with user name and password passed to open()</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/utils.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-open()-method" data-tested-assertations="following::ol[1]/li[9]/ol[1]/li[1] following::ol[1]/li[9]/ol[1]/li[2]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-send()-method" data-tested-assertations="following::code[contains(@title,'http-authorization')]/.." />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ test(function() {
+ var client = new XMLHttpRequest(),
+ urlstart = location.host + location.pathname.replace(/\/[^\/]*$/, '/'),
+ user = token();
+ client.open("GET", location.protocol+'//'+urlstart + "resources/auth1/auth.py", false, user, 'pass')
+ client.setRequestHeader("x-user", user)
+ client.send(null)
+ assert_equals(client.responseText, user + "\n" + 'pass')
+ assert_equals(client.getResponseHeader('x-challenge'), 'DID')
+ }, document.title)
+ </script>
+ <p>Note: this test will only work as expected once per browsing session. Restart browser to re-test.</p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-authentication-competing-names-passwords.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-authentication-competing-names-passwords.htm
new file mode 100644
index 00000000000..994ebb5a857
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-authentication-competing-names-passwords.htm
@@ -0,0 +1,54 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: send() - "Basic" authenticated requests with competing user name/password options</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/utils.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-open()-method" data-tested-assertations="following::ol[1]/li[9]/ol[1]/li[1] following::ol[1]/li[9]/ol[1]/li[2]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-send()-method" data-tested-assertations="following::code[contains(@title,'http-authorization')]/.." /> </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ function request(user1, pass1, user2, pass2, name) {
+ // user1, pass1 will if given become userinfo part of URL
+ // user2, pass2 will if given be passed to open() call
+ test(function() {
+ var client = new XMLHttpRequest(),
+ urlstart = "", userwin, passwin
+ // if user2 is set, winning user name and password is 2
+ if(user2)
+ userwin = user2, passwin = pass2
+ // if user1 is set, and user2 is not set, user1 and pass1 win
+ if(user1 && ! user2)
+ userwin = user1, passwin = pass1
+ // if neither user name is set, pass 2 wins (there will be no userinfo in URL)
+ if (!(user1 || user2))
+ passwin = pass2
+ if(user1) { // should add userinfo to URL (there is no way to create userinfo part of URL with only password in)
+ urlstart = "http://" + user1
+ if(pass1)
+ urlstart += ":" + pass1
+ urlstart += "@" + location.host + location.pathname.replace(/\/[^\/]*$/, '/')
+ }
+ client.open("GET", urlstart + "resources/authentication.py", false, user2, pass2)
+ client.setRequestHeader("x-user", userwin)
+ client.send(null)
+ assert_equals(client.responseText, (userwin||'') + "\n" + (passwin||''))
+
+ // We want to send multiple requests to the same realm here, so we try to make the UA forget its (cached) credentials between each test..
+ // forcing a 401 response to (hopefully) "log out"
+ // NOTE: This is commented out because it causes authentication prompts while running the test
+ //client.open('GET', "resources/authentication.py?logout=1", false)
+ //client.send()
+ }, document.title+' '+name)
+ }
+ request(null, null, token(), token(), 'user/pass in open() call')
+ request(null, null, token(), token(), 'another user/pass in open() call - must override cached credentials from previous test')
+ request("userinfo-user", "userinfo-pass", token(), token(), 'user/pass both in URL userinfo AND open() call - expexted that open() wins')
+ request(token(), token(), null, null, 'user/pass *only* in URL userinfo')
+ request(token(), null, null, token(), 'user name in URL userinfo, password in open() call: user name wins and password is thrown away')
+ request("1", token(), token(), null, 'user name and password in URL userinfo, only user name in open() call: user name in open() wins')
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-authentication-cors-basic-setrequestheader.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-authentication-cors-basic-setrequestheader.htm
new file mode 100644
index 00000000000..6f2eeb734a5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-authentication-cors-basic-setrequestheader.htm
@@ -0,0 +1,38 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: send() - "Basic" authenticated CORS request using setRequestHeader() (expects to succeed)</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/utils.js"></script>
+ <!-- These spec references do not make much sense simply because the spec doesn't say very much about this.. -->
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-setrequestheader()-method" data-tested-assertations="following::ol[1]/li[6]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-send()-method" data-tested-assertations="following::code[contains(@title,'http-authorization')]/.." />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+ var client = new XMLHttpRequest(),
+ urlstart = location.host + location.pathname.replace(/\/[^\/]*$/, '/'),
+ user = token()
+ client.open("GET", location.protocol+'//www1.'+urlstart + "resources/auth2/corsenabled.py", false)
+ client.withCredentials = true
+ client.setRequestHeader("x-user", user)
+ client.setRequestHeader("x-pass", 'pass')
+ client.setRequestHeader('Authorization', 'Basic ' + btoa(user + ":pass"))
+ client.onreadystatechange = function () {
+ if (client.readyState < 4) {return}
+ test.step( function () {
+ assert_equals(client.responseText, user + '\npass')
+ assert_equals(client.status, 200)
+ assert_equals(client.getResponseHeader('x-challenge'), 'DID-NOT')
+ test.done()
+ } )
+ }
+ client.send(null)
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-authentication-existing-session-manual.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-authentication-existing-session-manual.htm
new file mode 100644
index 00000000000..a80efd6e843
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-authentication-existing-session-manual.htm
@@ -0,0 +1,33 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: send() - "Basic" authenticated requests with user name and password from interactive session</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/utils.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-send()-method" data-tested-assertations="following::code[contains(@title,'http-authorization')]/.." />
+ </head>
+ <body>
+ <p>Please follow these steps to complete the test:</p>
+ <script>var user = token();</script>
+ <ol>
+ <li>Load <a href="resources/auth3/auth.py">page</a> and authenticate with username "<script>document.write(user)</script>" and password "pass"</li>
+ <li>Go back</li>
+ <li>Click <button onclick="location.href = location.href + '?dotest&user=' + user">complete test</button></li>
+ </ol>
+ <div id="log"></div>
+ <script>
+ if (location.search.indexOf('?dotest') != -1) {
+ test(function() {
+ var user = location.search.slice(location.search.indexOf('&user=') + 6),
+ client = new XMLHttpRequest(),
+ urlstart = location.host + location.pathname.replace(/\/[^\/]*$/, '/')
+ client.open("GET", location.protocol+'//'+urlstart + "resources/auth3/auth.py", false)
+ client.send(null)
+ assert_equals(client.responseText, user + "\n" + 'pass')
+ assert_equals(client.getResponseHeader('x-challenge'), 'DID-NOT')
+ }, document.title)
+ }
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-authentication-prompt-2-manual.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-authentication-prompt-2-manual.htm
new file mode 100644
index 00000000000..023a40a63d0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-authentication-prompt-2-manual.htm
@@ -0,0 +1,25 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: WWW-Authenticate challenge when user,pass are not passed to open()</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-send()-method" data-tested-assertations="following::code[contains(@title,'http-authorization')]/.." />
+ </head>
+ <body>
+ <p>Please follow these steps to complete the test:</p>
+ <ol>
+ <li>If you are prompted for user name and password, type in 'usr' and 'secret'</li>
+ </ol>
+ <div id="log"></div>
+ <script>
+ test(function() {
+ var client = new XMLHttpRequest(),
+ urlstart = location.host + location.pathname.replace(/\/[^\/]*$/, '/')
+ client.open("GET", location.protocol+'//'+urlstart + "resources/auth6/auth.py", false)
+ client.send(null)
+ assert_equals(client.responseText, 'usr' + "\n" + 'secret')
+ }, document.title)
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-authentication-prompt-manual.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-authentication-prompt-manual.htm
new file mode 100644
index 00000000000..a836c59e2d1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-authentication-prompt-manual.htm
@@ -0,0 +1,25 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: send() - "Basic" authentication gets 401 response</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-send()-method" data-tested-assertations="following::code[contains(@title,'http-authorization')]/.." />
+ </head>
+ <body>
+ <p>Please follow these steps to complete the test:</p>
+ <ol>
+ <li>If you are prompted for user name and password, type in 'usr' and 'secret'</li>
+ </ol>
+ <div id="log"></div>
+ <script>
+ test(function() {
+ var client = new XMLHttpRequest(),
+ urlstart = location.host + location.pathname.replace(/\/[^\/]*$/, '/')
+ client.open("GET", location.protocol+'//'+urlstart + "resources/auth5/auth.py", false, 'usr', 'wrongpassword')
+ client.send(null)
+ assert_equals(client.responseText, 'usr' + "\n" + 'secret')
+ }, document.title)
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-conditional.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-conditional.htm
new file mode 100644
index 00000000000..cbe3e94a425
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-conditional.htm
@@ -0,0 +1,34 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: send() - conditional requests</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-send()-method" data-tested-assertations="following::code[contains(text(),'Modified')]/.." />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ function request(type) {
+ test(function() {
+ var client = new XMLHttpRequest,
+ identifier = type == "tag" ? Math.random() : new Date().toGMTString(),
+ url = "resources/conditional.py?" + type + "=" + identifier
+ client.open("GET", url, false)
+ client.send(null)
+ assert_equals(client.status, 200)
+ assert_equals(client.statusText, "OK")
+ assert_equals(client.responseText, "MAYBE NOT")
+ client.open("GET", url, false)
+ client.setRequestHeader(type == "tag" ? "If-None-Match" : "If-Modified-Since", identifier)
+ client.send(null)
+ assert_equals(client.status, 304)
+ assert_equals(client.statusText, "SUPERCOOL")
+ assert_equals(client.responseText, "")
+ }, document.title + " (" + type + ")")
+ }
+ request("tag")
+ request("date")
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-content-type-charset.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-content-type-charset.htm
new file mode 100644
index 00000000000..039a787d3c6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-content-type-charset.htm
@@ -0,0 +1,58 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: send() - charset parameter of Content-Type</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-send()-method" data-tested-assertations="following::ol[1]/li[4]/p/code[contains(text(),'Content-Type')]/.. following::ol[1]/li[4]/p/code[contains(text(),'Content-Type')]/../following-sibling::p" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#dom-XMLHttpRequest-send-a-string" data-tested-assertations="following::p[2]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ function request(input, output) {
+ test(function() {
+ var client = new XMLHttpRequest()
+ client.open("POST", "resources/content.py", false)
+ if(input)
+ client.setRequestHeader("Content-Type", input)
+ client.send("TEST")
+ assert_equals(client.responseText, "TEST")
+ assert_equals(client.getResponseHeader("x-request-content-type"), output)
+ })
+ }
+ request(
+ "text/x-pink-unicorn; charset=windows-1252; charset=bogus; notrelated; charset=ascii",
+ "text/x-pink-unicorn; charset=UTF-8; charset=UTF-8; notrelated; charset=UTF-8"
+ )
+ request(
+ "text; charset=ascii",
+ "text; charset=ascii"
+ )
+ request(
+ "charset=ascii",
+ "charset=ascii"
+ )
+ request(
+ "text/x-thepiano;charset= waddup",
+ "text/x-thepiano;charset=UTF-8"
+ )
+ request(
+ "text/x-pink-unicorn",
+ "text/x-pink-unicorn"
+ )
+ request(
+ "text/plain;charset=utf-8",
+ "text/plain;charset=utf-8"
+ )
+ request(
+ "text/plain;charset=utf-8;charset=waddup",
+ "text/plain;charset=UTF-8;charset=UTF-8"
+ )
+ request(
+ null,
+ "text/plain;charset=UTF-8"
+ )
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-content-type-string.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-content-type-string.htm
new file mode 100644
index 00000000000..61cb4c0ff93
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-content-type-string.htm
@@ -0,0 +1,26 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: send() - Content-Type</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#dom-XMLHttpRequest-send-document" data-tested-assertations="following::p[1] following::p[2] following::p[3]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ function request(data, expected_type) {
+ test(function() {
+ var client = new XMLHttpRequest()
+ client.open("POST", "resources/content.py", false)
+ client.send(data)
+ assert_equals(client.getResponseHeader("x-request-content-type"), expected_type)
+ })
+ }
+ request("TEST", "text/plain;charset=UTF-8")
+ function init(fr) { request(fr.contentDocument, fr.getAttribute("data-t")) }
+ </script>
+ <iframe src='data:text/xml;charset=windows-1252,<%FF/>' onload="init(this)" data-t="application/xml;charset=windows-1252"></iframe>
+ <iframe src='data:text/html;charset=windows-1252,%FF' onload="init(this)" data-t="text/html;charset=windows-1252"></iframe>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-data-arraybuffer.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-data-arraybuffer.htm
new file mode 100644
index 00000000000..25c5d240727
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-data-arraybuffer.htm
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-send()-method" data-tested-assertations="following::ol[1]/li[4] following::ol[1]/li[4]/dl[1]/dd[1]"/>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-status-attribute" data-tested-assertations="following::ol[1]/li[3]"/>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-response-attribute" data-tested-assertations="following::ol[1]/li[3]"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <title>XMLHttpRequest: The send() method: ArrayBuffer data</title>
+</head>
+
+<body>
+ <div id="log"></div>
+
+ <script type="text/javascript">
+ var test = async_test();
+
+ test.step(function()
+ {
+ var xhr = new XMLHttpRequest();
+ var buf = new ArrayBuffer(5);
+ var arr = new Uint8Array(buf);
+ arr[0] = 0x48;
+ arr[1] = 0x65;
+ arr[2] = 0x6c;
+ arr[3] = 0x6c;
+ arr[4] = 0x6f;
+
+ xhr.onreadystatechange = function()
+ {
+ if (xhr.readyState == 4)
+ {
+ test.step(function()
+ {
+ assert_equals(xhr.status, 200);
+ assert_equals(xhr.response, "Hello");
+
+ test.done();
+ });
+ }
+ };
+
+ xhr.open("POST", "./resources/content.py", true);
+ xhr.send(buf);
+ });
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-data-blob.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-data-blob.htm
new file mode 100644
index 00000000000..5285fc180cc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-data-blob.htm
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-send()-method" data-tested-assertations="following::ol[1]/li[4] following::ol[1]/li[4]/dl[1]/dd[2]/p[3]"/>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-status-attribute" data-tested-assertations="following::ol[1]/li[3]"/>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-responsetype-attribute" data-tested-assertations="following::ol[1]/li[4]"/>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-response-attribute" data-tested-assertations="following::a[contains(@href,'#blob-response-entity-body')]/.."/>
+
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <title>XMLHttpRequest: The send() method: Blob data</title>
+</head>
+
+<body>
+ <div id="log"></div>
+
+ <script type="text/javascript">
+ var test = async_test();
+
+ test.step(function()
+ {
+ var xhr = new XMLHttpRequest();
+ var xhr2 = new XMLHttpRequest();
+
+ var content = "Hello";
+ var blob;
+
+ xhr.onreadystatechange = function()
+ {
+ if (xhr.readyState == 4)
+ {
+ test.step(function()
+ {
+ blob = xhr.response;
+ assert_true(blob instanceof Blob, "Blob from XHR Response");
+
+ xhr2.open("POST", "./resources/content.py", true);
+ xhr2.send(blob);
+ });
+ }
+ }
+
+ xhr2.onreadystatechange = function()
+ {
+ if (xhr2.readyState == 4)
+ {
+ test.step(function()
+ {
+ assert_equals(xhr2.status, 200);
+ assert_equals(xhr2.response, content);
+ test.done();
+ });
+ }
+ };
+
+ xhr.open("GET", "./resources/content.py?content=" + content, true);
+ xhr.responseType = "blob";
+ xhr.send();
+ });
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-data-es-object.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-data-es-object.htm
new file mode 100644
index 00000000000..6f7743286ec
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-data-es-object.htm
@@ -0,0 +1,61 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>XMLHttpRequest: passing objects to send()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="help" href="https://xhr.spec.whatwg.org/#the-send()-method" data-tested-assertations="following::ol/li[4]" />
+<link rel="help" href="https://heycam.github.io/webidl/#es-union" data-tested-assertations="following::ol/li[16]" />
+
+<div id="log"></div>
+
+<script>
+ function do_test(obj, expected, name) {
+ var test = async_test(name)
+ test.step(function() {
+ var client = new XMLHttpRequest()
+ client.onload = test.step_func(function () {
+ assert_equals(client.responseText, expected)
+ test.done()
+ });
+ client.open('POST', 'resources/content.py')
+ if (expected.exception) {
+ assert_throws(expected.exception, function(){client.send(obj)})
+ test.done()
+ } else {
+ client.send(obj)
+ }
+ });
+ }
+
+ do_test({}, '[object Object]', 'sending a plain empty object')
+ do_test(Math, '[object Math]', 'sending the ES Math object')
+ do_test(new XMLHttpRequest, '[object XMLHttpRequest]', 'sending a new XHR instance')
+ do_test({toString:function(){}}, 'undefined', 'sending object that stringifies to undefined')
+ do_test({toString:function(){return null}}, 'null', 'sending object that stringifies to null')
+ var ancestor = {toString: function(){
+ var ar=[]
+ for (var prop in this) {
+ if (this.hasOwnProperty(prop)) {
+ ar.push(prop+'='+this[prop])
+ }
+ };
+ return ar.join('&')
+ }};
+
+ var myObj = Object.create(ancestor, {foo:{value:1, enumerable: true}, bar:{value:'foo', enumerable:true}})
+ do_test(myObj, 'foo=1&bar=foo', 'object that stringifies to query string')
+
+ var myFakeJSON = {a:'a', b:'b', toString:function(){ return JSON.stringify(this, function(key, val){ return key ==='toString'?undefined:val; }) }}
+ do_test(myFakeJSON, '{"a":"a","b":"b"}', 'object that stringifies to JSON string')
+
+ var myFakeDoc1 = {valueOf:function(){return document}}
+ do_test(myFakeDoc1, '[object Object]', 'object whose valueOf() returns a document - ignore valueOf(), stringify')
+
+ var myFakeDoc2 = {toString:function(){return document}}
+ do_test(myFakeDoc2, {exception:new TypeError()}, 'object whose toString() returns a document, expected to throw')
+
+ var myThrower = {toString:function(){throw {name:'FooError', message:'bar'}}}
+ do_test(myThrower, {exception:{name:'FooError'}}, 'object whose toString() throws, expected to throw')
+
+
+</script>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-data-formdata.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-data-formdata.htm
new file mode 100644
index 00000000000..e49762e95e2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-data-formdata.htm
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-send()-method" data-tested-assertations="following::ol[1]/li[4] following::ol[1]/li[4]/dl[1]/dd[5]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#interface-formdata" data-tested-assertations="following::*[contains(@id,'dom-formdata')]/following::ol[1]/li[1] following::*[contains(@id,'dom-formdata')]/following::ol[1]/li[3] following::*[contains(@id,'dom-formdata-append')]/following::ul[1]/li[1] following::*[contains(@id,'dom-formdata-append')]/following::ul[1]/li[2]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-response-attribute" data-tested-assertations="following::ol[1]/li[3]"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <title>XmlHttpRequest: The send() method: FormData data</title>
+</head>
+
+<body>
+ <div id="log"></div>
+
+ <script type="text/javascript">
+ var test = async_test();
+
+ test.step(function()
+ {
+ var xhr = new XMLHttpRequest();
+ var form = new FormData();
+ form.append("id", "0");
+ form.append("value", "zero");
+
+ xhr.onreadystatechange = function()
+ {
+ test.step(function ()
+ {
+ if (xhr.readyState == 4)
+ {
+ assert_equals(xhr.status, 200);
+ assert_equals(xhr.response, "id:0;value:zero;");
+ test.done();
+ }
+ });
+ };
+
+ xhr.open("POST", "./resources/form.py", true);
+ xhr.send(form);
+ });
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-data-unexpected-tostring.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-data-unexpected-tostring.htm
new file mode 100644
index 00000000000..357a9cff9d9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-data-unexpected-tostring.htm
@@ -0,0 +1,57 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>XMLHttpRequest: passing objects that interfere with the XHR instance to send()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="help" href="https://xhr.spec.whatwg.org/#the-send()-method" data-tested-assertations="following::ol/li[4]" />
+<link rel="help" href="https://heycam.github.io/webidl/#es-union" data-tested-assertations="following::ol/li[16]" />
+
+
+<div id="log"></div>
+
+<script>
+ var test1 = async_test('abort() called from data stringification')
+ test1.step(function() {
+ var client = new XMLHttpRequest()
+ var objAbortsOnStringification = {toString:function(){
+ client.abort();
+ }}
+ client.open('POST', 'resources/content.py')
+ assert_throws("InvalidStateError", function(){
+ client.send(objAbortsOnStringification)
+ })
+ test1.done()
+ });
+
+ var test2 = async_test('open() called from data stringification')
+ test2.step(function() {
+ var client = new XMLHttpRequest()
+ var objOpensOnStringification = {toString:function(){
+ client.open('POST', 'resources/status.py?text=second_open_wins');
+ }}
+ client.onloadend = test2.step_func(function(){
+ assert_equals(client.statusText, 'second_open_wins')
+ test2.done()
+ })
+ client.open('POST', 'resources/status.py?text=first_open_wins')
+ client.send(objOpensOnStringification)
+ });
+
+ var test3 = async_test('send() called from data stringification')
+ test3.step(function() {
+ var client = new XMLHttpRequest()
+ var objSendsOnStringification = {toString:function(){
+ client.send('bomb!');
+ }}
+ client.onload = test3.step_func(function(){
+ assert_equals(client.responseText, 'bomb!')
+ test3.done()
+ })
+ client.open('POST', 'resources/content.py')
+ assert_throws('InvalidStateError', function(){
+ client.send(objSendsOnStringification)
+ })
+ });
+
+
+</script>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-entity-body-basic.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-entity-body-basic.htm
new file mode 100644
index 00000000000..41c9ddec443
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-entity-body-basic.htm
@@ -0,0 +1,28 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: send() - data argument</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-send()-method" data-tested-assertations="/following::ol/li[4]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#dom-XMLHttpRequest-send-a-string" data-tested-assertations="/following::dd" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ function request(input, output) {
+ test(function() {
+ var client = new XMLHttpRequest()
+ client.open("POST", "resources/content.py", false)
+ client.send(input)
+ assert_equals(client.responseText, output)
+ }, document.title + " (" + output + ")")
+ }
+ request(1, "1")
+ request(10000000, "10000000")
+ request([2,2], "2,2")
+ request(false, "false")
+ request("A\0A", "A\0A")
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-entity-body-document-bogus.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-entity-body-document-bogus.htm
new file mode 100644
index 00000000000..e834b61055d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-entity-body-document-bogus.htm
@@ -0,0 +1,26 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: send() - unserializable Document</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#dom-XMLHttpRequest-send-document" data-tested-assertations="following::p[3]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ function request_throws(input) {
+ test(function() {
+ var client = new XMLHttpRequest()
+ client.open("POST", "resources/content.py", false)
+ assert_throws("InvalidStateError", function() { client.send(input) })
+ })
+ }
+ var doc = document.implementation.createDocument(null, null, null)
+ while(doc.childNodes.length) {
+ doc.removeChild(doc.childNodes[0])
+ }
+ request_throws(doc)
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-entity-body-document.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-entity-body-document.htm
new file mode 100644
index 00000000000..67a0ff6db49
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-entity-body-document.htm
@@ -0,0 +1,55 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: send() - Document</title>
+ <meta charset="utf-8">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-send()-method" data-tested-assertations="/following::ol/li[4]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#dom-XMLHttpRequest-send-document" data-tested-assertations="/following::dd" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var expectations = [
+ { contentType: 'application/xml;charset=UTF-8', responseText : '<\u00FF\/>' },
+ { contentType: 'text/html;charset=UTF-8', responseText : '<body>\uFFFD<\/body>' }, /*invalid character code in document turns into FFFD*/
+ { contentType: 'text/html;charset=UTF-8', responseText : '<body>\u30C6\u30b9\u30c8<\/body>' } /* correctly serialized Shift-JIS */,
+ { contentType: 'text/html;charset=UTF-8', responseText: 'top' }, /* There's some markup included, but it's not really relevant for this test suite, so we do an indexOf() test */
+ { contentType: 'text/html;charset=UTF-8' }
+ ]
+
+
+ function request(input, isHTML, title) {
+ test(function() {
+ var client = new XMLHttpRequest()
+ client.open("POST", "resources/content.py?response_charset_label=UTF-8", false)
+ client.send(input)
+ var exp = expectations[number]
+ assert_equals(client.getResponseHeader('X-Request-Content-Type'), exp.contentType, 'document should be serialized and sent as '+exp.contentType+' (TEST#'+number+')')
+ // The indexOf() assertation will overlook some stuff, i.e. XML prologues that shouldn't be there (looking at you, Presto).
+ // However, arguably these things have little to do with the XHR functionality we're testing.
+ if(exp.responseText){ // This test does not want to assert anything about what markup a standalone IMG should be wrapped in. Hence the GIF test lacks a responseText expectation.
+ assert_true(client.responseText.indexOf(exp.responseText) != -1);
+ }
+ assert_equals(client.responseXML, null)
+ }, title)
+ }
+ function init(fr, number, title) { request(fr.contentDocument, number) }
+ </script>
+ <!--
+ This test also tests how documents in various encodings are serialized.
+ The below IFRAMEs contain:
+ * one XML document parsed from a windows-1252 source - content is <ÿ/>
+ * one HTML-document parsed from an invalid UTF-8 source, will contain a basic HTML DOM
+ with a U+FFFD replacement character for the invalid char
+ * one HTML document parsed from a valid Shift-JIS source
+ -->
+ <iframe src='resources/win-1252-xml.py' onload="init(this, 0, 'XML document, windows-1252')"></iframe>
+ <iframe src='resources/invalid-utf8-html.py' onload="init(this, 1, 'HTML document, invalid UTF-8')"></iframe>
+ <iframe src='resources/shift-jis-html.py' onload="init(this, 2, 'HTML document, shift-jis')"></iframe>
+ <iframe src='folder.txt' onload="init(this, 3, 'plain text file')"></iframe>
+ <iframe src='resources/image.gif' onload="init(this, 4, 'image file')"></iframe>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-entity-body-empty.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-entity-body-empty.htm
new file mode 100644
index 00000000000..ab074c77287
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-entity-body-empty.htm
@@ -0,0 +1,22 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: send("") - empty entity body</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-send()-method" data-tested-assertations="following::ol[1]/li[7]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#dom-XMLHttpRequest-send-a-string" data-tested-assertations="following::p[1] following::p[2] following::p[3]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ test(function() {
+ var client = new XMLHttpRequest()
+ client.open("POST", "resources/content.py", false)
+ client.upload.onloadstart = function(){assert_unreached('this event should not fire for empty strings')}
+ client.send("")
+ assert_equals(client.getResponseHeader("x-request-content-length"), "0")
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-entity-body-get-head-async.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-entity-body-get-head-async.htm
new file mode 100644
index 00000000000..ff4c4b4cac0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-entity-body-get-head-async.htm
@@ -0,0 +1,39 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: send() - non-empty data argument and GET/HEAD - async, no upload events should fire</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-send()-method" data-tested-assertations="following::OL[1]/LI[3] following::OL[1]/LI[7] following::OL[1]/LI[8]" />
+
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ function request(method) {
+ var test = async_test( document.title + " (" + method + ")")
+ var events=[]
+ var logEvt = function (e) {
+ events.push(e.type)
+ }
+ var client = new XMLHttpRequest()
+ client.open(method, "resources/content.py")
+ client.upload.addEventListener('progress', logEvt)
+ client.upload.addEventListener('loadend', logEvt)
+ client.upload.addEventListener('loadstart', logEvt)
+ client.addEventListener('loadend', function(){
+ test.step(function(){
+ assert_equals(client.getResponseHeader("x-request-content-length"), "NO")
+ assert_equals(client.getResponseHeader("x-request-method"), method)
+ assert_equals(client.responseText, "")
+ assert_array_equals(events, [])
+ test.done()
+ })
+ })
+ client.send("TEST")
+ }
+ request("GET")
+ request("HEAD")
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-entity-body-get-head.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-entity-body-get-head.htm
new file mode 100644
index 00000000000..a95852273aa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-entity-body-get-head.htm
@@ -0,0 +1,35 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: send() - non-empty data argument and GET/HEAD</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-send()-method" data-tested-assertations="following::OL[1]/LI[3] following::OL[1]/LI[7]" />
+
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ function request(method) {
+ test(function() {
+ var events=[]
+ var logEvt = function (e) {
+ events.push(e.type)
+ }
+ var client = new XMLHttpRequest()
+ client.open(method, "resources/content.py", false)
+ client.send("TEST")
+ client.upload.addEventListener('progress', logEvt)
+ client.upload.addEventListener('loadend', logEvt)
+ client.upload.addEventListener('loadstart', logEvt)
+ assert_equals(client.getResponseHeader("x-request-content-length"), "NO")
+ assert_equals(client.getResponseHeader("x-request-method"), method)
+ assert_equals(client.responseText, "")
+ assert_array_equals(events, [])
+ }, document.title + " (" + method + ")")
+ }
+ request("GET")
+ request("HEAD")
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-entity-body-none.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-entity-body-none.htm
new file mode 100644
index 00000000000..11ac824f4dd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-entity-body-none.htm
@@ -0,0 +1,32 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: send(null) - no entity body</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-send()-method" data-tested-assertations="following::ol[1]/li[4] following::ol[1]/li[7]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ test(function() {
+ var client = new XMLHttpRequest()
+ client.open("POST", "resources/content.py", false)
+ client.upload.onloadstart = function(){assert_unreached('this event should not fire for null')}
+ client.send(null)
+ assert_equals(client.getResponseHeader("x-request-content-length"), "0")
+ assert_equals(client.getResponseHeader("x-request-content-type"), "NO")
+ }, "No content type")
+
+ test(function() {
+ var client = new XMLHttpRequest()
+ client.open("POST", "resources/content.py", false)
+ var content_type = 'application/x-foo'
+ client.setRequestHeader('Content-Type', content_type)
+ client.send(null)
+ assert_equals(client.getResponseHeader("x-request-content-length"), "0")
+ assert_equals(client.getResponseHeader("x-request-content-type"), content_type)
+ }, "Explicit content type")
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-network-error-async-events.sub.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-network-error-async-events.sub.htm
new file mode 100644
index 00000000000..76e5e347837
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-network-error-async-events.sub.htm
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#handler-xhr-onerror" data-tested-assertations="../.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-send()-method" data-tested-assertations="following::ol[1]/li[9]/ol/li[2] following::ol[1]/li[9]/ol/li[3]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#infrastructure-for-the-send()-method" data-tested-assertations="following::dt[4] following::dd[4]/p" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#network-error" data-tested-assertations=".." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#request-error" data-tested-assertations="following::ol[1]/li[4] following::ol[1]/li[6] following::ol[1]/li[7] following::ol[1]/li[7]/ol/li[3] following::ol[1]/li[7]/ol/li[4] following::ol[1]/li[9] following::ol[1]/li[10]" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <title>XmlHttpRequest: The send() method: Fire a progress event named error when Network error happens (synchronous flag is unset)</title>
+</head>
+
+<body>
+ <div id="log"></div>
+
+ <script type="text/javascript">
+ var test = async_test();
+
+ test.step(function(){
+ var xhr = new XMLHttpRequest();
+ var expect = ["loadstart", "upload.loadstart", 4, "upload.error", "upload.loadend", "error", "loadend"];
+ var actual = [];
+
+ xhr.onreadystatechange = function()
+ {
+ test.step(function()
+ {
+ if (xhr.readyState == 4)
+ {
+ actual.push(xhr.readyState);
+ }
+ });
+ };
+
+ xhr.onloadstart = function(e){ actual.push(e.type); };
+ xhr.onloadend = function(e){ actual.push(e.type); VerifyResult()};
+ xhr.onerror = function(e){ actual.push(e.type); };
+
+ xhr.upload.onloadstart = function(e){ actual.push("upload." + e.type);};
+ xhr.upload.onloadend = function(e){ actual.push("upload." + e.type);};
+ xhr.upload.onerror = function(e){ actual.push("upload." + e.type); };
+
+ function VerifyResult()
+ {
+ test.step(function()
+ {
+ assert_array_equals(actual, expect);
+ test.done();
+ });
+ };
+
+ xhr.open("POST", "http://nonexistent-origin.{{host}}:{{ports[http][0]}}", true);
+ xhr.send("Test Message");
+ });
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-network-error-sync-events.sub.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-network-error-sync-events.sub.htm
new file mode 100644
index 00000000000..cefa80ad54a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-network-error-sync-events.sub.htm
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#infrastructure-for-the-send()-method" data-tested-assertations="following::dt[4] following::dd[4]/p" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#network-error" data-tested-assertations=".." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#request-error" data-tested-assertations="following::ol[1]/li[4] following::ol[1]/li[5]" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <title>XmlHttpRequest: The send() method: Throw a "throw an "NetworkError" exception when Network error happens (synchronous flag is set)</title>
+</head>
+
+<body>
+ <div id="log"></div>
+
+ <script type="text/javascript">
+ test(function()
+ {
+ var xhr = new XMLHttpRequest();
+
+ xhr.open("POST", "http://nonexistent-origin.{{host}}}:{{ports[http][0]}}", false);
+
+ assert_throws("NetworkError", function()
+ {
+ xhr.send("Test Message");
+ });
+ assert_equals(xhr.readyState, 4)
+
+ xhr.open("GET", "data:text/html;charset=utf-8;base64,PT0NUWVBFIGh0bWw%2BDQo8", false);
+
+ assert_throws("NetworkError", function()
+ {
+ xhr.send("Test Message");
+ });
+ assert_equals(xhr.readyState, 4)
+
+ });
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-no-response-event-loadend.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-no-response-event-loadend.htm
new file mode 100644
index 00000000000..0a1eda53734
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-no-response-event-loadend.htm
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <title>XMLHttpRequest: The send() method: Fire a progress event named loadend (no response entity body)</title>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#handler-xhr-onloadend" data-tested-assertations="/../.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#event-xhr-loadend" data-tested-assertations="/../.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#infrastructure-for-the-send()-method" data-tested-assertations="following::dt[10] /following-sibling::ol/li[10]" />
+</head>
+
+<body>
+ <div id="log"></div>
+
+ <script type="text/javascript">
+ var test = async_test();
+
+ test.step(function ()
+ {
+ var xhr = new XMLHttpRequest();
+
+ xhr.onreadystatechange = function()
+ {
+ test.step(function()
+ {
+ if (xhr.readyState == 4)
+ {
+ assert_equals(xhr.response, "");
+ }
+ });
+ };
+
+ xhr.onloadend = function(e)
+ {
+ test.step(function()
+ {
+ assert_true(e instanceof ProgressEvent);
+ assert_equals(e.type, "loadend");
+ test.step(function() { test.done(); });
+ });
+ };
+
+ xhr.open("POST", "./resources/content.py", true);
+ xhr.send();
+ });
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-no-response-event-loadstart.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-no-response-event-loadstart.htm
new file mode 100644
index 00000000000..cd4a0683ed0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-no-response-event-loadstart.htm
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#handler-xhr-onloadstart" data-tested-assertations="/../.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#event-xhr-loadstart" data-tested-assertations="/../.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-send()-method" data-tested-assertations="/following-sibling::ol/li[9]/ol/li[2]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-response-attribute" data-tested-assertations="/following-sibling::ol/li[1]" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <title>XMLHttpRequest: The send() method: Fire a progress event named loadstart (no response entity body and the state is LOADING)</title>
+</head>
+
+<body>
+ <div id="log"></div>
+
+ <script type="text/javascript">
+ var test = async_test();
+
+ test.step(function()
+ {
+ var xhr = new XMLHttpRequest();
+
+ xhr.onreadystatechange = function()
+ {
+ test.step(function()
+ {
+ if (xhr.readyState == 3)
+ {
+ assert_equals(xhr.response, "");
+ }
+ else if (xhr.readyState == 4)
+ {
+ assert_unreached("loadstart event did not fire in LOADING state!");
+ }
+ });
+ };
+
+ xhr.onloadstart = function()
+ {
+ test.step(function() { test.done("Test done!"); });
+ };
+
+ xhr.open("POST", "./resources/content.py", true);
+ xhr.send();
+ });
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-no-response-event-order.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-no-response-event-order.htm
new file mode 100644
index 00000000000..aabef30f0a4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-no-response-event-order.htm
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#handler-xhr-onloadstart" data-tested-assertations="../.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#handler-xhr-onloadend" data-tested-assertations="../.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#event-xhr-loadstart" data-tested-assertations="../.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#event-xhr-loadend" data-tested-assertations="../.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-send()-method" data-tested-assertations="following-sibling::ol/li[9]/ol/li[2]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#infrastructure-for-the-send()-method" data-tested-assertations="following::dt[10] following::a[contains(@href,'#switch-done')]/.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#switch-done" data-tested-assertations="following::ol[1]/li[3] following::ol[1]/li[4] following::ol[1]/li[6] following::ol[1]/li[7]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-response-attribute" data-tested-assertations="following-sibling::ol/li[1]" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <title>XMLHttpRequest: The send() method: event order when there is no response entity body</title>
+</head>
+
+<body>
+ <div id="log"></div>
+
+ <script type="text/javascript">
+ var test = async_test();
+
+ test.step(function()
+ {
+ var xhr = new XMLHttpRequest();
+ var expect = ["loadstart", 4, "load", "loadend"];
+ var actual = [];
+
+ xhr.onreadystatechange = test.step_func(function()
+ {
+ test.step(function()
+ {
+ if (xhr.readyState == 3)
+ {
+ assert_equals(xhr.response, "");
+ }
+ else if (xhr.readyState == 4)
+ {
+ actual.push(xhr.readyState);
+ }
+ });
+ });
+
+ xhr.onloadstart = test.step_func(function(e){ actual.push(e.type); });
+ xhr.onload = test.step_func(function(e){ actual.push(e.type); });
+ xhr.onloadend = test.step_func(function(e){
+ actual.push(e.type);
+ assert_array_equals(actual, expect);
+ test.done();
+ });
+
+ xhr.upload.onloadstart = test.step_func(function(e){ assert_unreached('upload.'+e.type); });
+ xhr.upload.onload = test.step_func(function(e){ assert_unreached('upload.'+e.type); });
+ xhr.upload.onloadend = test.step_func(function(e){ assert_unreached('upload.'+e.type); });
+
+ xhr.open("POST", "./resources/content.py", true);
+ xhr.send();
+ });
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-non-same-origin.sub.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-non-same-origin.sub.htm
new file mode 100644
index 00000000000..bfa9023c110
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-non-same-origin.sub.htm
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>XMLHttpRequest: send() - non same-origin</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <base href="http://{{domains[www2]}}:{{ports[http][0]}}">
+ <link rel="help" href="https://xhr.spec.whatwg.org/#cross-origin-request-steps" data-tested-assertations="/following::DL[2]/DT[1] /following::DL[2]/DD[1]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#cross-origin-request-event-rules" data-tested-assertations="/following::DL[1]/DT[2] /following::DL[1]/DD[2]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ function url(url) {
+ test(function() {
+ var client = new XMLHttpRequest()
+ client.open("GET", url, false)
+ assert_throws("NetworkError", function() { client.send() })
+ }, document.title + " (" + url + ")")
+ }
+ url("mailto:test@example.org")
+ url("tel:+31600000000")
+ url("http://{{domains[www2]}}:{{ports[http][0]}}/")
+ url("javascript:alert('FAIL')")
+ url("folder.txt")
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-receive-utf16.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-receive-utf16.htm
new file mode 100644
index 00000000000..6d6fb90a173
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-receive-utf16.htm
@@ -0,0 +1,37 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>XMLHttpRequest: The send() method: receive data which is UTF-16 encoded</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#text-response" data-tested-assertations="following::ol/li[9]" />
+<div id="log"></div>
+
+<script>
+ async_test(function() {
+ var client = new XMLHttpRequest();
+ client.onload = this.step_func_done(function(e) {
+ assert_equals(client.responseText, 'æøå\nテスト\n')
+ });
+ client.open("GET", "resources/utf16.txt");
+ client.send(null);
+ }, 'UTF-16 with BOM, no encoding in content-type');
+
+ async_test(function() {
+ var client = new XMLHttpRequest();
+ client.onload = this.step_func_done(function(e) {
+ assert_equals(client.responseText, 'æøå\nテスト\n')
+ });
+ client.open("GET", "resources/status.py?code=200&type=text%2Fplain%3Bcharset%3DUTF-16&content=%E6%00%F8%00%E5%00%0A%00%C6%30%B9%30%C8%30%0A%00");
+ client.send(null);
+ }, 'UTF-16 without BOM, with charset label in content-type');
+
+ async_test(function() {
+ var client = new XMLHttpRequest();
+ client.onload = this.step_func_done(function(e) {
+ // plenty of EF BF BD Replacement Character in this invalid input..
+ assert_equals(client.responseText, "\ufffd\u0000\ufffd\u0000\ufffd\u0000\u000a\u0000\ufffd\u0030\ufffd\u0030\ufffd\u0030\u000a\u0000")
+ });
+ client.open("GET", "resources/status.py?code=200&type=text%2Fplain%3Bcharset%3DUTF-8&content=%E6%00%F8%00%E5%00%0A%00%C6%30%B9%30%C8%30%0A%00");
+ client.send(null);
+ }, 'UTF-16 without BOM, mislabelled as UTF-8 in content-type');
+</script>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-redirect-bogus-sync.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-redirect-bogus-sync.htm
new file mode 100644
index 00000000000..89e6ff0ebdf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-redirect-bogus-sync.htm
@@ -0,0 +1,26 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: send() - Redirects (bogus Location header; sync)</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#infrastructure-for-the-send()-method" data-tested-assertations="following::dl[1]/dt[2] following::dl[1]/dd[2]/ol/li[1] following::dl[1]/dd[2]/ol/li[3]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ function redirect(code, location) {
+ test(function() {
+ var client = new XMLHttpRequest()
+ client.open("GET", "resources/redirect.py?location=" + location + "&code=" + code, false)
+ assert_throws("NetworkError", function() { client.send(null) })
+ }, document.title + " (" + code + ": " + location + ")")
+ }
+ redirect("301", "foobar://abcd")
+ redirect("302", "http://z")
+ redirect("302", "mailto:someone@example.org")
+ redirect("303", "http://z")
+ redirect("303", "tel:1234567890")
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-redirect-bogus.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-redirect-bogus.htm
new file mode 100644
index 00000000000..a46fc1d339e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-redirect-bogus.htm
@@ -0,0 +1,36 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: send() - Redirects (bogus Location header)</title>
+ <meta name=timeout content=long>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#infrastructure-for-the-send()-method" data-tested-assertations="following::dl[1]/dt[2] following::dl[1]/dd[2]/ol/li[1] following::dl[1]/dd[2]/ol/li[3]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ function redirect(code, location) {
+ var test = async_test(document.title + " (" + code + ": " + location + ")", {timeout: 20000})
+ test.step(function() {
+ var client = new XMLHttpRequest()
+ client.onreadystatechange = function() {
+ test.step(function() {
+ if(client.readyState == 4) {
+ assert_equals(client.status, 0)
+ assert_equals(client.statusText, "")
+ test.done()
+ }
+ })
+ }
+ client.open("GET", "resources/redirect.py?location=" + location + "&code=" + code)
+ client.send(null)
+ })
+ }
+ redirect("302", "http://example.not")
+ redirect("302", "mailto:someone@example.org")
+ redirect("303", "http://example.not")
+ redirect("303", "foobar:someone@example.org")
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-redirect-infinite-sync.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-redirect-infinite-sync.htm
new file mode 100644
index 00000000000..6e9e47e55fc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-redirect-infinite-sync.htm
@@ -0,0 +1,24 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: send() - Redirects (infinite loop; sync)</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#infrastructure-for-the-send()-method" data-tested-assertations="following::dl[1]/dt[2] following::dl[1]/dd[2]/p[1]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#network-error" data-tested-assertations=".." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#request-error" data-tested-assertations="following::ol[1]/li[5]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ function redirect(code) {
+ test(function() {
+ var client = new XMLHttpRequest()
+ client.open("GET", "resources/infinite-redirects.py?type="+code, false)
+ assert_throws("NetworkError", function() { client.send(null) })
+ }, document.title + " (" + code + ")")
+ }
+ redirect("301")
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-redirect-infinite.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-redirect-infinite.htm
new file mode 100644
index 00000000000..414e4107efc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-redirect-infinite.htm
@@ -0,0 +1,35 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: send() - Redirects (infinite loop)</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#handler-xhr-onerror" data-tested-assertations="../.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#infrastructure-for-the-send()-method" data-tested-assertations="following::dl[1]/dt[2] following::dl[1]/dd[2]/p[1]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#network-error" data-tested-assertations=".." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#request-error" data-tested-assertations="following::ol[1]/li[4] following::ol[1]/li[9] following::ol[1]/li[10]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-responsetext-attribute" data-tested-assertations="following::ol[1]/li[3]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ var client = new XMLHttpRequest(),
+ errorEventFired = false,
+ code = 301
+ client.open("GET", "resources/infinite-redirects.py?type="+code)
+ client.onerror = function(){
+ errorEventFired = true
+ }
+ client.onloadend = function(){
+ test.step(function() {
+ assert_equals(errorEventFired, true)
+ assert_equals(client.responseText, '')
+ assert_equals(client.readyState, 4)
+ test.done()
+ })
+ }
+ client.send(null)
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-redirect-no-location.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-redirect-no-location.htm
new file mode 100644
index 00000000000..85ae963f446
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-redirect-no-location.htm
@@ -0,0 +1,40 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: send() - Redirects (no Location header)</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#infrastructure-for-the-send()-method" data-tested-assertations="following::dl[1]/dt[2]" />
+ <!--
+ NOTE: the XHR spec does not really handle this scenario. It's handled in the Fetch spec:
+ "If response's headers do not contain a header whose name is Location, return response."
+ -->
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ function redirect(code) {
+ var test = async_test(document.title + " (" + code + ")")
+ test.step(function() {
+ var client = new XMLHttpRequest()
+ client.onreadystatechange = function() {
+ test.step(function() {
+ if(client.readyState == 4) {
+ assert_equals(client.status + "", code)
+ assert_equals(client.statusText, "ABE ODDYSSEE")
+ assert_equals(client.responseXML.documentElement.localName, "x")
+ test.done()
+ }
+ })
+ }
+ client.open("GET", "resources/status.py?content=<x>x<\/x>&type=text/xml&text=ABE ODDYSSEE&code=" + code)
+ client.send(null)
+ })
+ }
+ redirect("301")
+ redirect("302")
+ redirect("303")
+ redirect("307")
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-redirect-to-cors.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-redirect-to-cors.htm
new file mode 100644
index 00000000000..f90a01b71f8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-redirect-to-cors.htm
@@ -0,0 +1,36 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: send() - Redirect to CORS-enabled resource</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#infrastructure-for-the-send()-method" data-tested-assertations="following::dl[1]/dt[2] following::dl[1]/dd[2]/ol/li[1] following::dl[1]/dd[2]/ol/li[3]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ function redirect(code) {
+ var test = async_test(document.title + " (" + code + ")")
+ test.step(function() {
+ var client = new XMLHttpRequest()
+ client.onreadystatechange = function() {
+ test.step(function() {
+ if(client.readyState == 4) {
+ assert_equals(client.getResponseHeader("x-request-method"), "GET")
+ assert_equals(client.getResponseHeader("x-request-content-type"), "application/x-pony")
+ test.done()
+ }
+ })
+ }
+ client.open("GET", "resources/redirect.py?location="+encodeURIComponent("http://www2."+location.host+(location.pathname.replace(/[^\/]+$/, ''))+'resources/corsenabled.py')+"&code=" + code)
+ client.setRequestHeader("Content-Type", "application/x-pony")
+ client.send(null)
+ })
+ }
+ redirect("301")
+ redirect("302")
+ redirect("303")
+ redirect("307")
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-redirect-to-non-cors.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-redirect-to-non-cors.htm
new file mode 100644
index 00000000000..c6886a57b59
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-redirect-to-non-cors.htm
@@ -0,0 +1,37 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: send() - Redirect to cross-origin resource, not CORS-enabled</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#infrastructure-for-the-send()-method" data-tested-assertations="following::dl[1]/dt[2] following::dl[1]/dd[2]/ol/li[1] following::dl[1]/dd[2]/ol/li[3]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ function redirect(code) {
+ var test = async_test(document.title + " (" + code + ")")
+ test.step(function() {
+ var client = new XMLHttpRequest()
+ client.onreadystatechange = function() {
+ test.step(function() {
+ if(client.readyState == 4) {
+ assert_equals(client.getResponseHeader("x-request-method"), null)
+ assert_equals(client.getResponseHeader("x-request-content-type"), null)
+ assert_equals(client.responseText, '')
+ test.done()
+ }
+ })
+ }
+ client.open("GET", "resources/redirect.py?location="+encodeURIComponent("http://www2."+location.host+(location.pathname.replace(/[^\/]+$/, ''))+'resources/content.py')+"&code=" + code)
+ client.setRequestHeader("Content-Type", "application/x-pony")
+ client.send(null)
+ })
+ }
+ redirect("301")
+ redirect("302")
+ redirect("303")
+ redirect("307")
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-redirect.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-redirect.htm
new file mode 100644
index 00000000000..16b3231e25b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-redirect.htm
@@ -0,0 +1,36 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: send() - Redirects (basics)</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#infrastructure-for-the-send()-method" data-tested-assertations="following::dl[1]/dt[2] following::dl[1]/dd[2]/ol/li[1] following::dl[1]/dd[2]/ol/li[2]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ function redirect(code) {
+ var test = async_test(document.title + " (" + code + ")")
+ test.step(function() {
+ var client = new XMLHttpRequest()
+ client.onreadystatechange = function() {
+ test.step(function() {
+ if(client.readyState == 4) {
+ assert_equals(client.getResponseHeader("x-request-method"), "GET")
+ assert_equals(client.getResponseHeader("x-request-content-type"), "application/x-pony")
+ test.done()
+ }
+ })
+ }
+ client.open("GET", "resources/redirect.py?location=content.py&code=" + code)
+ client.setRequestHeader("Content-Type", "application/x-pony")
+ client.send(null)
+ })
+ }
+ redirect("301")
+ redirect("302")
+ redirect("303")
+ redirect("307")
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-response-event-order.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-response-event-order.htm
new file mode 100644
index 00000000000..64dfaa670f8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-response-event-order.htm
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#handler-xhr-onloadstart" data-tested-assertations="../.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#handler-xhr-onloadend" data-tested-assertations="../.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#event-xhr-loadstart" data-tested-assertations="../.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#event-xhr-loadend" data-tested-assertations="../.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-send()-method" data-tested-assertations="following-sibling::ol/li[9]/ol/li[2] following-sibling::ol/li[9]/ol/li[3] following::a[contains(@href,'#make-upload-progress-notifications')]/.. following::a[contains(@href,'#make-progress-notifications')]/.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#make-upload-progress-notifications" data-tested-assertations="following::ul[1]/li[1] following::ul[1]/li[2]/ol[1]/li[2] following::ul[1]/li[2]/ol[1]/li[3] following::ul[1]/li[2]/ol[1]/li[4]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#make-progress-notifications" data-tested-assertations=".." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#infrastructure-for-the-send()-method" data-tested-assertations="following::a[contains(@href,'#switch-done')]/.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#switch-done" data-tested-assertations="following::ol[1]/li[3] following::ol[1]/li[4] following::ol[1]/li[5] following::ol[1]/li[6] following::ol[1]/li[7]" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <title>XMLHttpRequest: The send() method: event order when synchronous flag is unset</title>
+</head>
+
+<body>
+ <div id="log"></div>
+
+ <script type="text/javascript">
+ var test = async_test();
+
+ test.step(function()
+ {
+ var xhr = new XMLHttpRequest();
+ var expect = ["loadstart", "upload.loadstart", "upload.progress", "upload.load", "upload.loadend", "progress", 4, "load", "loadend"];
+ var actual = [];
+
+ xhr.onreadystatechange = function()
+ {
+ test.step(function()
+ {
+ if (xhr.readyState == 4)
+ {
+ actual.push(xhr.readyState);
+ }
+ });
+ };
+
+ xhr.onloadstart = function(e){ actual.push(e.type); };
+ xhr.onload = function(e){ actual.push(e.type); };
+ xhr.onloadend = function(e){ actual.push(e.type); VerifyResult()};
+ xhr.onprogress = function(e){ actual.push(e.type);};
+
+ xhr.upload.onloadstart = function(e){ actual.push("upload." + e.type); };
+ xhr.upload.onload = function(e){ actual.push("upload." + e.type); };
+ xhr.upload.onloadend = function(e){ actual.push("upload." + e.type);};
+ xhr.upload.onprogress = function(e){ actual.push("upload." + e.type);};
+
+ function VerifyResult()
+ {
+ test.step(function()
+ {
+ assert_array_equals(actual, expect);
+ test.done();
+ });
+ };
+
+ xhr.open("POST", "./resources/content.py", true);
+ xhr.send("Test Message");
+ });
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-response-upload-event-loadend.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-response-upload-event-loadend.htm
new file mode 100644
index 00000000000..99a239ab135
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-response-upload-event-loadend.htm
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#handler-xhr-onloadend" data-tested-assertations="../.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#event-xhr-loadend" data-tested-assertations="../.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-send()-method" data-tested-assertations="following::a[contains(@href,'#make-upload-progress-notifications')]/.. following::ol[1]/li[8]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#make-upload-progress-notifications" data-tested-assertations="following::ul[1]/li[2]/ol[1]/li[4]" />
+
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <title>XMLHttpRequest: The send() method: Fire a progress event named loadend on the XMLHttpRequestUpload (synchronous flag is unset)</title>
+</head>
+
+<body>
+ <div id="log"></div>
+
+ <script type="text/javascript">
+ var test = async_test();
+
+ test.step(function()
+ {
+ var xhr = new XMLHttpRequest();
+
+ xhr.upload.onloadend = function(e)
+ {
+ test.step(function()
+ {
+ assert_true(e instanceof ProgressEvent);
+ assert_equals(e.type, "loadend");
+ assert_equals(e.target, xhr.upload);
+ test.done();
+ });
+ };
+
+ xhr.open("POST", "./resources/content.py", true);
+ xhr.send("Test Message");
+ });
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-response-upload-event-loadstart.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-response-upload-event-loadstart.htm
new file mode 100644
index 00000000000..7a9be9f8ca4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-response-upload-event-loadstart.htm
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#handler-xhr-onloadstart" data-tested-assertations="../.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#event-xhr-loadstart" data-tested-assertations="../.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-send()-method" data-tested-assertations="following::ol[1]/li[8] following-sibling::ol/li[9]/ol/li[3]" />
+
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <title>XMLHttpRequest: The send() method: Fire a progress event named loadstart on the XMLHttpRequestUpload (synchronous flag is unset)</title>
+</head>
+
+<body>
+ <div id="log"></div>
+
+ <script type="text/javascript">
+ var test = async_test();
+
+ test.step(function()
+ {
+ var xhr = new XMLHttpRequest();
+
+ xhr.upload.onloadstart = function(e)
+ {
+ test.step(function()
+ {
+ assert_true(e instanceof ProgressEvent);
+ assert_equals(e.type, "loadstart");
+ assert_equals(e.target, xhr.upload);
+ test.done();
+ });
+ };
+
+ xhr.open("POST", "./resources/content.py", true);
+ xhr.send("Test Message");
+ });
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-response-upload-event-progress.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-response-upload-event-progress.htm
new file mode 100644
index 00000000000..914aed7255a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-response-upload-event-progress.htm
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#handler-xhr-onprogress" data-tested-assertations="../.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#event-xhr-progress" data-tested-assertations="../.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-send()-method" data-tested-assertations="following::a[contains(@href,'#make-upload-progress-notifications')]/.. following::ol[1]/li[8]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#make-upload-progress-notifications" data-tested-assertations="following::ul[1]/li[2]/ol[1]/li[2]" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <title>XMLHttpRequest: The send() method: Fire a progress event named progress on the XMLHttpRequestUpload (synchronous flag is unset)</title>
+</head>
+
+<body>
+ <div id="log"></div>
+
+ <script type="text/javascript">
+ var test = async_test();
+
+ test.step(function()
+ {
+ var xhr = new XMLHttpRequest();
+
+ xhr.upload.onprogress = function(e)
+ {
+ test.step(function()
+ {
+ assert_true(e instanceof ProgressEvent);
+ assert_equals(e.type, "progress");
+ assert_equals(e.target, xhr.upload);
+ test.done();
+ });
+ };
+
+ xhr.open("POST", "./resources/content.py", true);
+ xhr.send("Test Message");
+ });
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-send.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-send.htm
new file mode 100644
index 00000000000..5b22a3da871
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-send.htm
@@ -0,0 +1,21 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: send() - send()</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-send()-method" data-tested-assertations="following::ol/li[2]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ test(function() {
+ var client = new XMLHttpRequest()
+ client.open("GET", "resources/well-formed.xml")
+ client.send(null)
+ assert_throws("InvalidStateError", function() { client.send(null) })
+ client.abort()
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-sync-blocks-async.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-sync-blocks-async.htm
new file mode 100644
index 00000000000..87caa0f7802
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-sync-blocks-async.htm
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <!-- This behaviour is not explicitly spelled out in the spec.
+ It does say "queue tasks" under the "if the synchronous flag is unset" header in point 10 of the "send" algorithm.. -->
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-send()-method" data-tested-assertations="following-sibling::ol/li[10]/dl/dd/dl/dd[2]/p[3]" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <title>XMLHttpRequest: sync requests should block events on pending async requests</title>
+</head>
+
+<body>
+ <div id="log"></div>
+
+ <script type="text/javascript">
+ var test = async_test();
+
+ var expect = ['sync 4', 'async 2', 'async 3', 'async 4']
+ var actual = []
+
+ test.step(function()
+ {
+ var xhr_async = new XMLHttpRequest()
+ xhr_async.open('GET', 'resources/delay.py?ms=1000', true) // first launch an async request, completes in 1 second
+ xhr_async.onreadystatechange = function()
+ {
+ test.step(function()
+ {
+ actual.push('async ' + xhr_async.readyState)
+ if(xhr_async.readyState === 4 && actual.indexOf('sync 4')>-1){
+ VerifyResult()
+ }
+
+ });
+ };
+ xhr_async.send()
+
+ setTimeout(function(){
+ var xhr_sync = new XMLHttpRequest();
+ xhr_sync.open('GET', 'resources/delay.py?ms=2000', false) // here's a sync request that will take 2 seconds to finish
+ xhr_sync.onreadystatechange = function()
+ {
+ test.step(function()
+ {
+ actual.push('sync ' + xhr_sync.readyState)
+ if(xhr_sync.readyState === 4 && actual.indexOf('async 4')>-1){
+ VerifyResult()
+ }
+ });
+ };
+ xhr_sync.send()
+
+ }, 10);
+
+ function VerifyResult()
+ {
+ test.step(function()
+ {
+ assert_array_equals(actual, expect);
+ test.done();
+ });
+ };
+ });
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-sync-no-response-event-load.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-sync-no-response-event-load.htm
new file mode 100644
index 00000000000..a2a5516586d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-sync-no-response-event-load.htm
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#handler-xhr-onload" data-tested-assertations="../.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#event-xhr-load" data-tested-assertations="../.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#infrastructure-for-the-send()-method" data-tested-assertations="following::dt[11] following::a[contains(@href,'#switch-done')]/.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#switch-done" data-tested-assertations="following::ol/li[1] following::ol/li[6]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-response-attribute" data-tested-assertations="/following::ol/li[3]" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <title>XMLHttpRequest: The send() method: Fire an event named load (no response entity body and the synchronous flag is set)</title>
+</head>
+
+<body>
+ <div id="log"></div>
+
+ <script type="text/javascript">
+ test(function()
+ {
+ var xhr = new XMLHttpRequest();
+ var pass = false;
+
+ xhr.onload = function(e)
+ {
+ assert_true(e instanceof ProgressEvent);
+ assert_equals(e.type, "load");
+ pass = true;
+ };
+
+ xhr.open("POST", "./resources/content.py", false);
+ xhr.send();
+
+ assert_equals(xhr.response, "");
+ assert_true(pass);
+ });
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-sync-no-response-event-loadend.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-sync-no-response-event-loadend.htm
new file mode 100644
index 00000000000..7da2a311827
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-sync-no-response-event-loadend.htm
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#handler-xhr-onloadend" data-tested-assertations="../.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#event-xhr-loadend" data-tested-assertations="../.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#infrastructure-for-the-send()-method" data-tested-assertations="following::dt[11] following::a[contains(@href,'#switch-done')]/.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#switch-done" data-tested-assertations="following::ol/li[1] following::ol/li[7]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-response-attribute" data-tested-assertations="/following::ol/li[3]" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <title>XMLHttpRequest: The send() method: Fire an event named loadend (no response entity body and the synchronous flag is set)</title>
+</head>
+
+<body>
+ <div id="log"></div>
+
+ <script type="text/javascript">
+ test(function()
+ {
+ var xhr = new XMLHttpRequest();
+ var pass = false;
+
+ xhr.onloadend = function(e)
+ {
+ assert_true(e instanceof ProgressEvent);
+ assert_equals(e.type, "loadend");
+ pass = true;
+ };
+
+ xhr.open("POST", "./resources/content.py", false);
+ xhr.send();
+
+ assert_equals(xhr.response, "");
+ assert_true(pass);
+ });
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-sync-no-response-event-order.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-sync-no-response-event-order.htm
new file mode 100644
index 00000000000..c7e3172cb00
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-sync-no-response-event-order.htm
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>XMLHttpRequest: The send() method: event order when synchronous flag is set and there is no response entity body</title>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#handler-xhr-onloadstart" data-tested-assertations="../.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#handler-xhr-onloadend" data-tested-assertations="../.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#event-xhr-loadstart" data-tested-assertations="../.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#event-xhr-loadend" data-tested-assertations="../.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-send()-method" data-tested-assertations="following-sibling::ol[1]/li[9]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#same-origin-request-steps" data-tested-assertations="following::DL[1]/DT[1]"/>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#infrastructure-for-the-send()-method" data-tested-assertations="following::dt[11] following::a[contains(@href,'#switch-done')]/.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#switch-done" data-tested-assertations="following::ol[1]/li[1] following::ol[1]/li[3] following::ol[1]/li[4] following::ol[1]/li[6] following::ol[1]/li[7]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-response-attribute" data-tested-assertations="following::ol/li[3]" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+
+<body>
+ <div id="log"></div>
+
+ <script type="text/javascript">
+ test(function () {
+ var xhr = new XMLHttpRequest();
+ var expect = [4, "load", "loadend"];
+ var actual = [];
+
+ xhr.onreadystatechange = function()
+ {
+ if (xhr.readyState == 4)
+ {
+ actual.push(xhr.readyState);
+ }
+ };
+
+ xhr.onloadstart = function(e){ actual.push(e.type); };
+ xhr.onload = function(e){ actual.push(e.type); };
+ xhr.onloadend = function(e){ actual.push(e.type); };
+
+ xhr.upload.onload = function(e){ actual.push("upload." + e.type); };
+ xhr.upload.onloadstart = function(e){ actual.push("upload." + e.type); };
+ xhr.upload.onloadend = function(e){ actual.push("upload." + e.type);};
+
+ xhr.open("POST", "./resources/content.py", false);
+ xhr.send();
+
+ assert_equals(xhr.response, "");
+ assert_array_equals(actual, expect);
+ });
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-sync-response-event-order.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-sync-response-event-order.htm
new file mode 100644
index 00000000000..b574edb4c0e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-sync-response-event-order.htm
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <title>XMLHttpRequest: The send() method: event order when synchronous flag is set</title>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#handler-xhr-onloadstart" data-tested-assertations="../.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#handler-xhr-onloadend" data-tested-assertations="../.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#event-xhr-loadstart" data-tested-assertations="../.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#event-xhr-loadend" data-tested-assertations="../.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-send()-method" data-tested-assertations="following-sibling::ol/li[9]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#same-origin-request-steps" data-tested-assertations="following::DL[1]/DT[1]"/>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#infrastructure-for-the-send()-method" data-tested-assertations="following::dt[11] following::a[contains(@href,'#switch-done')]/.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#switch-done" data-tested-assertations="following::ol[1]/li[1] following::ol[1]/li[3] following::ol[1]/li[4] following::ol[1]/li[6] following::ol[1]/li[7]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-response-attribute" data-tested-assertations="following::ol/li[3]" />
+</head>
+
+<body>
+ <div id="log"></div>
+
+ <script type="text/javascript">
+ test(function () {
+ var xhr = new XMLHttpRequest();
+ var expect = [4, "load", "loadend"];
+ var actual = [];
+
+ xhr.onreadystatechange = function()
+ {
+ if (xhr.readyState == 4)
+ {
+ actual.push(xhr.readyState);
+ }
+ };
+
+ xhr.onloadstart = function(e){ actual.push(e.type); };
+ xhr.onload = function(e){ actual.push(e.type); };
+ xhr.onloadend = function(e){ actual.push(e.type); };
+
+ xhr.upload.onload = function(e){ actual.push("upload." + e.type); };
+ xhr.upload.onloadstart = function(e){ actual.push("upload." + e.type); };
+ xhr.upload.onloadend = function(e){ actual.push("upload." + e.type);};
+
+ xhr.open("POST", "./resources/content.py", false);
+ xhr.send("Test Message");
+
+ assert_equals(xhr.response, "Test Message");
+ assert_array_equals(actual, expect);
+ });
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-sync-timeout.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-sync-timeout.htm
new file mode 100644
index 00000000000..08ce7e9b905
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-sync-timeout.htm
@@ -0,0 +1,30 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: timeout during sync send() should not run</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-send()-method"/>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#same-origin-request-steps" data-tested-assertations="following::DL[1]/DT[1]"/>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test(),
+ hasrun = false
+ test.step(function() {
+ client = new XMLHttpRequest()
+ client.open("GET", "folder.txt", false)
+ setTimeout(function() { test.step(function() { hasrun = true }) }, 0)
+ client.onreadystatechange = function() {
+ test.step(function() {
+ assert_equals(client.readyState, 4)
+ assert_false(hasrun)
+ })
+ }
+ client.send(null)
+ test.done()
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/send-timeout-events.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/send-timeout-events.htm
new file mode 100644
index 00000000000..6aea627d661
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/send-timeout-events.htm
@@ -0,0 +1,76 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <title>XMLHttpRequest: The send() method: timeout is not 0 </title>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-timeout-attribute" data-tested-assertations="following::ol[1]/li[2]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#infrastructure-for-the-send()-method" data-tested-assertations="following::dt[5] following::a[contains(@href,'#timeout-error')]/.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#timeout-error" data-tested-assertations=".." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#request-error" data-tested-assertations="following::ol[1]/li[4] following::ol[1]/li[6] following::ol[1]/li[7]/ol/li[3] following::ol[1]/li[7]/ol/li[4] following::ol[1]/li[9] following::ol[1]/li[10]" />
+</head>
+
+<body>
+ <div id="log"></div>
+
+ <script type="text/javascript">
+ var test = async_test();
+
+ test.step(function()
+ {
+ var xhr = new XMLHttpRequest();
+ var expect = [4, "", "upload.timeout", "upload.loadend", "timeout", "loadend"];
+ var actual = [];
+
+ xhr.onreadystatechange = test.step_func(function()
+ {
+ if (xhr.readyState == 4)
+ {
+ actual.push(xhr.readyState, xhr.response);
+ }
+ });
+
+ xhr.onloadend = test.step_func_done(function(e)
+ {
+ assert_equals(e.loaded, 0);
+ assert_equals(e.total, 0);
+ actual.push(e.type);
+ assert_array_equals(actual, expect);
+ });
+
+ xhr.ontimeout = test.step_func(function(e)
+ {
+ assert_equals(e.loaded, 0);
+ assert_equals(e.total, 0);
+ actual.push(e.type);
+ });
+
+
+ xhr.upload.onloadend = test.step_func(function(e)
+ {
+ assert_equals(e.loaded, 0);
+ assert_equals(e.total, 0);
+ actual.push("upload." + e.type);
+ });
+
+ xhr.upload.ontimeout = test.step_func(function(e)
+ {
+ assert_equals(e.loaded, 0);
+ assert_equals(e.total, 0);
+ actual.push("upload." + e.type);
+ });
+
+
+ var content = "";
+ for (var i = 0; i < 121026; i++)
+ {
+ content += "[" + i + "]";
+ }
+
+ xhr.open("POST", "./resources/trickle.py", true);
+ xhr.timeout = 1;
+ xhr.send(content);
+ });
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/setrequestheader-after-send.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/setrequestheader-after-send.htm
new file mode 100644
index 00000000000..5952144713e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/setrequestheader-after-send.htm
@@ -0,0 +1,27 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: setRequestHeader() after send()</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-setrequestheader()-method" data-tested-assertations="/following::ol/li[2]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+ var client = new XMLHttpRequest()
+ client.open("GET", "resources/delay.py?ms=0")
+ client.onreadystatechange = function() {
+ test.step(function() {
+ assert_throws("InvalidStateError", function() { client.setRequestHeader("x-test", "test") })
+ if(client.readyState == 4)
+ test.done()
+ })
+ }
+ client.send(null)
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/setrequestheader-allow-empty-value.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/setrequestheader-allow-empty-value.htm
new file mode 100644
index 00000000000..bd8709417f5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/setrequestheader-allow-empty-value.htm
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>XMLHttpRequest: setRequestHeader() - empty header</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-setrequestheader()-method" data-tested-assertations="/following::ol/li[4]/p[contains(@class,'note')] /following::ol/li[6]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ function request(value) {
+ test(function() {
+ var client = new XMLHttpRequest()
+ client.open("POST", "resources/inspect-headers.py?filter_name=X-Empty", false)
+ client.setRequestHeader('X-Empty', value)
+ client.send(null)
+ assert_equals(client.responseText, 'x-empty: '+ String(value).toLowerCase()+'\n' )
+ }, document.title + " (" + value + ")")
+ }
+ request("")
+ request(null)
+ request(undefined)
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/setrequestheader-before-open.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/setrequestheader-before-open.htm
new file mode 100644
index 00000000000..d90b02eafe6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/setrequestheader-before-open.htm
@@ -0,0 +1,18 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: setRequestHeader() before open()</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-setrequestheader()-method" data-tested-assertations="following::ol/li[1]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ test(function() {
+ var client = new XMLHttpRequest()
+ assert_throws("InvalidStateError", function() { client.setRequestHeader("x-test", "test") })
+ }, 'setRequestHeader invoked before open()')
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/setrequestheader-bogus-name.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/setrequestheader-bogus-name.htm
new file mode 100644
index 00000000000..e57b8c42a9c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/setrequestheader-bogus-name.htm
@@ -0,0 +1,48 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: setRequestHeader() name argument checks</title>
+ <meta charset="utf-8">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-setrequestheader()-method" data-tested-assertations="/following::ol/li[3]" />
+ </head>
+ <body>
+ <div id="log"></div>
+<!--
+ CHAR = <any US-ASCII character (octets 0 - 127)>
+ CTL = <any US-ASCII control character
+ (octets 0 - 31) and DEL (127)>
+ SP = <US-ASCII SP, space (32)>
+ HT = <US-ASCII HT, horizontal-tab (9)>
+ token = 1*<any CHAR except CTLs or separators>
+ separators = "(" | ")" | "<" | ">" | "@"
+ | "," | ";" | ":" | "\" | <">
+ | "/" | "[" | "]" | "?" | "="
+ | "{" | "}" | SP | HT
+ field-name = token
+-->
+ <script>
+ function try_name(name) {
+ test(function() {
+ var client = new XMLHttpRequest()
+ client.open("GET", "...")
+ assert_throws("SyntaxError", function() { client.setRequestHeader(name, 'x-value') })
+ }, "setRequestHeader should throw with header name " + format_value(invalid_headers[i]) + ".")
+ }
+ var invalid_headers = ["(", ")", "<", ">", "@", ",", ";", ":", "\\",
+ "\"", "/", "[", "]", "?", "=", "{", "}", " ",
+ /* HT already tested in the loop below */
+ "\u007f", "テスト", "", "t\rt", "t\nt", "t: t", "t:t",
+ "t<t", "t t", " tt", ":tt", "\ttt", "\vtt", "t\0t",
+ "t\"t", "t,t", "t;t", "()[]{}", "a?B", "X-テスト", "a=B"]
+ for (var i = 0; i < 32; ++i) {
+ invalid_headers.push(String.fromCharCode(i))
+ }
+ for (var i = 0; i < invalid_headers.length; ++i) {
+ try_name(invalid_headers[i])
+ }
+
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/setrequestheader-bogus-value.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/setrequestheader-bogus-value.htm
new file mode 100644
index 00000000000..6ae03d64989
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/setrequestheader-bogus-value.htm
@@ -0,0 +1,31 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>XMLHttpRequest: setRequestHeader() value argument checks</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-setrequestheader()-method" data-tested-assertations="/following::ol/li[4]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ function try_value(value) {
+ test(function() {
+ var client = new XMLHttpRequest()
+ client.open("GET", "...")
+ assert_throws("SyntaxError", function() { client.setRequestHeader("x-test", value) }, ' given value ' + value+', ')
+ })
+ }
+ try_value("t\rt")
+ try_value("t\nt")
+ try_value("テスト")
+
+ test(function() {
+ var client = new XMLHttpRequest()
+ client.open("GET", "...")
+ assert_throws(new TypeError(), function() { client.setRequestHeader("x-test") })
+ }, 'Omitted value argument')
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/setrequestheader-case-insensitive.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/setrequestheader-case-insensitive.htm
new file mode 100644
index 00000000000..cf8810d0fb6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/setrequestheader-case-insensitive.htm
@@ -0,0 +1,23 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: setRequestHeader() - headers that differ in case</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-setrequestheader()-method" data-tested-assertations="/following::ol/li[6] /following::ol/li[7]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ test(function() {
+ var client = new XMLHttpRequest()
+ client.open("POST", "resources/inspect-headers.py?filter_value=t1, t2, t3", false)
+ client.setRequestHeader("x-test", "t1")
+ client.setRequestHeader("X-TEST", "t2")
+ client.setRequestHeader("X-teST", "t3")
+ client.send(null)
+ assert_equals(client.responseText, "x-test,")
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/setrequestheader-header-allowed.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/setrequestheader-header-allowed.htm
new file mode 100644
index 00000000000..a6e0eabd89a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/setrequestheader-header-allowed.htm
@@ -0,0 +1,32 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: setRequestHeader() - headers that are allowed</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-setrequestheader()-method" data-tested-assertations="/following::ol/li[6] /following::ol/li[7]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ function request(header) {
+ test(function() {
+ var client = new XMLHttpRequest()
+ client.open("POST", "resources/inspect-headers.py?filter_value=t1, t2", false)
+ client.setRequestHeader(header, "t1")
+ client.setRequestHeader(header, "t2")
+ client.send(null)
+ assert_equals(client.responseText, header.toLowerCase() + ",")
+ }, document.title + " (" + header + ")")
+ }
+ request("Authorization")
+ request("Pragma")
+ request("Content-Transfer-Encoding")
+ request("Content-Type")
+ request("Overwrite")
+ request("If")
+ request("Status-URI")
+ request("X-Pink-Unicorn")
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/setrequestheader-header-forbidden.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/setrequestheader-header-forbidden.htm
new file mode 100644
index 00000000000..00c0e7f75a8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/setrequestheader-header-forbidden.htm
@@ -0,0 +1,43 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: setRequestHeader() - headers that are forbidden</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-setrequestheader()-method" data-tested-assertations="/following::ol/li[5]" />
+
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ test(function() {
+ var client = new XMLHttpRequest()
+ client.open("POST", "resources/inspect-headers.py?filter_value=TEST", false)
+ client.setRequestHeader("Accept-Charset", "TEST")
+ client.setRequestHeader("Accept-Encoding", "TEST")
+ client.setRequestHeader("Connection", "TEST")
+ client.setRequestHeader("Content-Length", "TEST")
+ client.setRequestHeader("Cookie", "TEST")
+ client.setRequestHeader("Cookie2", "TEST")
+ client.setRequestHeader("Date", "TEST")
+ client.setRequestHeader("DNT", "TEST")
+ client.setRequestHeader("Expect", "TEST")
+ client.setRequestHeader("Host", "TEST")
+ client.setRequestHeader("Keep-Alive", "TEST")
+ client.setRequestHeader("Referer", "TEST")
+ client.setRequestHeader("TE", "TEST")
+ client.setRequestHeader("Trailer", "TEST")
+ client.setRequestHeader("Transfer-Encoding", "TEST")
+ client.setRequestHeader("Upgrade", "TEST")
+ client.setRequestHeader("User-Agent", "TEST")
+ client.setRequestHeader("Via", "TEST")
+ client.setRequestHeader("Proxy-", "TEST")
+ client.setRequestHeader("Proxy-Authorization", "TEST")
+ client.setRequestHeader("Sec-", "TEST")
+ client.setRequestHeader("Sec-X", "TEST")
+ client.send(null)
+ assert_equals(client.responseText, "")
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/setrequestheader-open-setrequestheader.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/setrequestheader-open-setrequestheader.htm
new file mode 100644
index 00000000000..56481904401
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/setrequestheader-open-setrequestheader.htm
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<!--
+Test from https://bugzilla.mozilla.org/show_bug.cgi?id=819051
+-->
+<head>
+ <title>XMLHttpRequest: setRequestHeader() and open()</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-open()-method" data-tested-assertations="following::OL[1]/LI[14]/ul[1]/li[4]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-setrequestheader()-method" data-tested-assertations="following::OL[1]/LI[6] following::ol[1]/li[7]" />
+</head>
+<body>
+ <p id="log"></p>
+<script type="text/javascript">
+var test = async_test();
+
+var url = "resources/inspect-headers.py";
+
+var xhr = new XMLHttpRequest();
+xhr.open("GET", url + "?filter_name=x-appended-to-this");
+xhr.setRequestHeader("X-appended-to-this", "False");
+xhr.open("GET", url + "?filter_name=x-appended-to-this");
+xhr.setRequestHeader("X-appended-to-this", "True");
+
+xhr.onreadystatechange = function() {
+ if (this.readyState == 4) {
+ test.step(function (){
+ assert_equals(xhr.responseText, "x-appended-to-this: True\n", "Set headers record should have been cleared by open.");
+ test_standard_header();
+ });
+ }
+}
+
+xhr.send();
+
+function test_standard_header () {
+ var header_tested = "Accept";
+ var xhr = new XMLHttpRequest();
+ xhr.open("GET", url + "?filter_name=accept");
+ xhr.setRequestHeader("Accept", "foo/bar");
+ xhr.open("GET", url + "?filter_name=accept");
+ xhr.setRequestHeader("Accept", "bar/foo");
+
+ xhr.onreadystatechange = function() {
+ if (this.readyState == 4) {
+ test.step(function (){
+ assert_equals(xhr.responseText, "accept: bar/foo\n", "Set headers record should have been cleared by open.");
+ test.done();
+ });
+ }
+ }
+
+ xhr.send();
+}
+
+
+</script>
+</pre>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/status-async.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/status-async.htm
new file mode 100644
index 00000000000..dcf7d62467a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/status-async.htm
@@ -0,0 +1,62 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: status/statusText - various responses</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-status-attribute" data-tested-assertations="following::ol/li[1] following::ol/li[3]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-statustext-attribute" data-tested-assertations="following::ol/li[1] following::ol/li[3]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-getresponseheader()-method" data-tested-assertations="following::ol/li[5]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-responsetext-attribute" data-tested-assertations="following::ol/li[4]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var counter=0
+ function statusRequest(method, code, text, content, type) {
+ counter++
+ var test = async_test(document.title +' '+ counter+" (" + method + " " + code + ")")
+ test.step(function() {
+ var client = new XMLHttpRequest()
+ client.onreadystatechange = function(e) {
+ test.step(function() {
+ if(client.readyState > 1) {
+ assert_equals(client.status, code)
+ assert_equals(client.statusText, text)
+ assert_equals(client.getResponseHeader("X-Request-Method"), method)
+ if(client.readyState == 4) {
+ if(method != "HEAD") {
+ if(type == "text/xml") {
+ assert_equals(client.responseXML.documentElement.localName, "x")
+ }
+ assert_equals(client.responseText, content)
+ }
+ test.done()
+ }
+ }else{
+ assert_equals(client.status, 0)
+ assert_equals(client.statusText, "")
+ }
+ }, this)
+ }
+ client.open(method, "resources/status.py?code=" + encodeURIComponent(code) + "&text=" + text + "&content=" + encodeURIComponent(content) + "&type=" + encodeURIComponent(type))
+ client.send(null)
+ })
+ }
+ function status(code, text, content, type) {
+ statusRequest("GET", code, text, content, type)
+ statusRequest("HEAD", code, text, content, type)
+ statusRequest("CHICKEN", code, text, content, type)
+ }
+ status(204, "UNICORNSWIN", "", "")
+ status(401, "OH HELLO", "Not today.", "")
+ status(402, "FIVE BUCKS", "<x>402<\/x>", "text/xml")
+ status(402, "FREE", "Nice!", "text/doesnotmatter")
+ status(402, "402 TEH AWESOME", "", "")
+ status(502, "YO", "", "")
+ status(502, "lowercase", "SWEET POTATO", "text/plain")
+ status(503, "HOUSTON WE HAVE A", "503", "text/plain")
+ status(699, "WAY OUTTA RANGE", "699", "text/plain")
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/status-basic.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/status-basic.htm
new file mode 100644
index 00000000000..5005ceae688
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/status-basic.htm
@@ -0,0 +1,49 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: status/statusText - various responses</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-status-attribute" data-tested-assertations="following::ol/li[3]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-statustext-attribute" data-tested-assertations="following::ol/li[3]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-getresponseheader()-method" data-tested-assertations="following::ol/li[5]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-responsetext-attribute" data-tested-assertations="following::ol/li[4]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var counter = 0
+ function statusRequest(method, code, text, content, type) {
+ counter++
+ test(function() {
+ var client = new XMLHttpRequest()
+ client.open(method, "resources/status.py?code=" + code + "&text=" + encodeURIComponent(text) + "&content=" + encodeURIComponent(content) + "&type=" + encodeURIComponent(type), false)
+ client.send(null)
+ assert_equals(client.status, code)
+ assert_equals(client.statusText, text)
+ assert_equals(client.getResponseHeader("X-Request-Method"), method)
+ if(method != "HEAD") {
+ if(type == "text/xml") {
+ assert_equals(client.responseXML.documentElement.localName, "x")
+ }
+ assert_equals(client.responseText, content)
+ }
+ }, document.title + " " + counter + " (" + method + " " + code + ")")
+ }
+ function status(code, text, content, type) {
+ statusRequest("GET", code, text, content, type)
+ statusRequest("HEAD", code, text, content, type)
+ statusRequest("CHICKEN", code, text, content, type)
+ }
+ status(204, "UNICORNSWIN", "", "")
+ status(401, "OH HELLO", "Not today.", "")
+ status(402, "FIVE BUCKS", "<x>402<\/x>", "text/xml")
+ status(402, "FREE", "Nice!", "text/doesnotmatter")
+ status(402, "402 TEH AWESOME", "", "")
+ status(502, "YO", "", "")
+ status(502, "lowercase", "SWEET POTATO", "text/plain")
+ status(503, "HOUSTON WE HAVE A", "503", "text/plain")
+ status(699, "WAY OUTTA RANGE", "699", "text/plain")
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/status-error.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/status-error.htm
new file mode 100644
index 00000000000..fbcb7fd7594
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/status-error.htm
@@ -0,0 +1,60 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: status error handling</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#handler-xhr-onerror" data-tested-assertations="../.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-status-attribute" data-tested-assertations="/following::ol/li[3]" />
+ </head>
+ <body>
+ <p>This shouldn't be tested inside a tunnel.</p>
+ <div id="log"></div>
+ <script>
+ function noError(method, code) {
+ var test = async_test(document.title + " " + method + " " + code)
+
+ test.step(function() {
+ var client = new XMLHttpRequest()
+ client.open(method, "resources/status.py?code=" + code, true)
+
+ client.onreadystatechange = test.step_func(function() {
+ assert_equals(client.response, "", "response data")
+ assert_equals(client.status, code, "response status")
+
+ if (client.readyState == client.DONE)
+ /* Give extra time for a bogus error event to pop up */
+ setTimeout(test.step_func(function() { test.done() } ), 100)
+ })
+ client.onerror = test.step_func(function() {
+ assert_unreached("HTTP error should not throw error event")
+ })
+ client.send()
+ })
+ }
+
+ noError('GET', 200)
+ noError('GET', 400)
+ noError('GET', 401)
+ noError('GET', 404)
+ noError('GET', 410)
+ noError('GET', 500)
+ noError('GET', 699)
+
+ noError('HEAD', 200)
+ noError('HEAD', 404)
+ noError('HEAD', 500)
+ noError('HEAD', 699)
+
+ noError('POST', 200)
+ noError('POST', 404)
+ noError('POST', 500)
+ noError('POST', 699)
+
+ noError('PUT', 200)
+ noError('PUT', 404)
+ noError('PUT', 500)
+ noError('PUT', 699)
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/timeout-cors-async.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/timeout-cors-async.htm
new file mode 100644
index 00000000000..35e2a30ba2f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/timeout-cors-async.htm
@@ -0,0 +1,43 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: timeout event and cross-origin request</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-timeout-attribute" data-tested-assertations="following::ol[1]/li[2]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#handler-xhr-ontimeout" data-tested-assertations="../.."/>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#timeout-error" data-tested-assertations=".."/>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#request-error" data-tested-assertations="following::ol[1]/li[4] following::ol[1]/li[9]"/>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#cross-origin-request-event-rules" data-tested-assertations="following::dl//code[contains(@title,'dom-XMLHttpRequest-timeout')]/.. following::dl//code[contains(@title,'dom-XMLHttpRequest-timeout')]/../following-sibling::dd following::dt[1] following::dd[1]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test(document.title)
+ var client = new XMLHttpRequest()
+ var gotTimeout = false
+ client.open("GET", "http://www2." + location.hostname + (location.port ? ":" + location.port : "") +(location.pathname.replace(/[^\/]+$/, '')+'resources/corsenabled.py')+"?delay=2&code=200")
+ client.timeout = 100
+ client.addEventListener('timeout', function (e) {
+ test.step(function() {
+ assert_equals(e.type, 'timeout')
+ assert_equals(client.status, 0)
+ gotTimeout = true
+ })
+ })
+ client.addEventListener('load', function (e) {
+ test.step(function() {
+ assert_unreached('load event should not fire')
+ })
+ })
+ client.addEventListener('loadend', function (e) {
+ test.step(function() {
+ assert_true(gotTimeout, "timeout event should fire")
+ test.done()
+ })
+ })
+
+ client.send(null)
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/timeout-sync.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/timeout-sync.htm
new file mode 100644
index 00000000000..9815532c70f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/timeout-sync.htm
@@ -0,0 +1,25 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: timeout not allowed for sync requests</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-timeout-attribute" data-tested-assertations="following::ol/li[1]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-open()-method" data-tested-assertations="following::ol/li[10]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ test(function() {
+ var client = new XMLHttpRequest()
+ client.open('GET', 'folder.txt', false)
+ assert_throws("InvalidAccessError", function() { client.timeout = 1000 })
+ }, 'setting timeout attribute on sync request')
+ test(function() {
+ var client = new XMLHttpRequest()
+ client.timeout = 1000
+ assert_throws("InvalidAccessError", function() { client.open('GET', 'folder.txt', false) })
+ }, 'open() with async false when timeout is set')
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-basic.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-basic.htm
new file mode 100644
index 00000000000..c48b610ff66
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-basic.htm
@@ -0,0 +1,45 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: prototype and members</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#dom-xmlhttprequest" data-tested-assertations="following::ol/li[1]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#xmlhttprequest" data-tested-assertations="." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#states" data-tested-assertations="following::dfn[2] following::dfn[3] following::dfn[4] following::dfn[5] following::dfn[6]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ test(function() {
+ XMLHttpRequest.prototype.test = function() { return "TEH" }
+ var client = new XMLHttpRequest()
+ assert_equals(client.test(), "TEH")
+ var members = ["onreadystatechange",
+ "open",
+ "setRequestHeader",
+ "send",
+ "abort",
+ "status",
+ "statusText",
+ "getResponseHeader",
+ "getAllResponseHeaders",
+ "responseText",
+ "responseXML"]
+ for(var x in members)
+ assert_true(members[x] in client, members[x])
+ var constants = ["UNSENT",
+ "OPENED",
+ "HEADERS_RECEIVED",
+ "LOADING",
+ "DONE"],
+ i = 0
+ for(var x in constants) {
+ assert_equals(client[constants[x]], i, constants[x])
+ assert_equals(XMLHttpRequest[constants[x]], i, "XHR " + constants[x])
+ i++
+ }
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-eventtarget.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-eventtarget.htm
new file mode 100644
index 00000000000..ea58fd4dc3e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-eventtarget.htm
@@ -0,0 +1,48 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: implements EventTarget</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#xmlhttprequesteventtarget" data-tested-assertations=".." />
+ <!-- Obviously, most of the stuff actually being tested here is covered in the DOM events spec, not in the XHR spec -->
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test(),
+ x = null,
+ expected = ["a1", "b1", "c1", "a2", "b2", "c2", "a3", "c3", "a4", "c4"],
+ result = []
+ function callback(e) {
+ result.push("b" + x.readyState)
+ test.step(function() {
+ if(x.readyState == 3)
+ assert_unreached()
+ })
+ }
+ test.step(function() {
+ x = new XMLHttpRequest()
+ x.onreadystatechange = function() {
+ test.step(function() {
+ result.push("a" + x.readyState)
+ })
+ }
+ x.addEventListener("readystatechange", callback, false)
+ x.addEventListener("readystatechange", function() {
+ test.step(function() {
+ result.push("c" + x.readyState)
+ if(x.readyState == 2)
+ x.removeEventListener("readystatechange", callback, false)
+ if(x.readyState == 4) {
+ assert_array_equals(result, expected)
+ test.done()
+ }
+ })
+ }, false)
+ x.open("GET", "folder.txt")
+ x.send(null)
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-network-error-sync.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-network-error-sync.htm
new file mode 100644
index 00000000000..c4a887a1ebe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-network-error-sync.htm
@@ -0,0 +1,34 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: members during network errors (sync)</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#infrastructure-for-the-send()-method" data-tested-assertations="following::dl[1]/dt[2] following::dl[1]/dd[2]/p[1]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#network-error" data-tested-assertations=".." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#request-error" data-tested-assertations="following::ol[1]/li[5]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-status-attribute" data-tested-assertations="following::ol[1]/li[1] following::ol[1]/li[2]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-statustext-attribute" data-tested-assertations="following::ol[1]/li[1] following::ol[1]/li[2]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-getresponseheader()-method" data-tested-assertations="following::ol[1]/li[1] following::ol[1]/li[2]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-getallresponseheaders()-method" data-tested-assertations="following::ol[1]/li[1] following::ol[1]/li[2]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-responsetext-attribute" data-tested-assertations="following::ol[1]/li[2] following::ol[1]/li[3]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-responsexml-attribute" data-tested-assertations="following::ol[1]/li[2] following::ol[1]/li[3]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ test(function() {
+ var client = new XMLHttpRequest()
+ client.open("GET", "resources/infinite-redirects.py", false)
+ assert_throws("NetworkError", function() { client.send(null) }, "send")
+ assert_equals(client.status, 0, "status")
+ assert_equals(client.statusText, "", "statusText")
+ assert_equals(client.getAllResponseHeaders(), "", "getAllResponseHeaders")
+ assert_equals(client.getResponseHeader("content-type"), null, "getResponseHeader")
+ assert_equals(client.responseText, "", "responseText")
+ assert_equals(client.responseXML, null, "responseXML")
+ assert_equals(client.readyState, client.DONE, "readyState")
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-network-error.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-network-error.htm
new file mode 100644
index 00000000000..c8e32008095
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-network-error.htm
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>XMLHttpRequest: members during network errors</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#infrastructure-for-the-send()-method" data-tested-assertations="following::dl[1]/dt[2] following::dl[1]/dd[2]/ol/li[1] following::dl[1]/dd[2]/ol/li[2]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-status-attribute" data-tested-assertations="following::ol[1]/li[1] following::ol[1]/li[2]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-statustext-attribute" data-tested-assertations="following::ol[1]/li[1] following::ol[1]/li[2]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-getresponseheader()-method" data-tested-assertations="following::ol[1]/li[1] following::ol[1]/li[2]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-getallresponseheaders()-method" data-tested-assertations="following::ol[1]/li[1] following::ol[1]/li[2]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-responsetext-attribute" data-tested-assertations="following::ol[1]/li[2] following::ol[1]/li[3]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-responsexml-attribute" data-tested-assertations="following::ol[1]/li[2] following::ol[1]/li[3]" />
+
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+ var client = new XMLHttpRequest()
+ client.onreadystatechange = function() {
+ test.step(function() {
+ assert_equals(client.status, 0, "status")
+ assert_equals(client.statusText, "", "statusText")
+ assert_equals(client.getAllResponseHeaders(), "", "getAllResponseHeaders")
+ assert_equals(client.getResponseHeader("content-type"), null, "getResponseHeader")
+ assert_equals(client.responseText, "", "responseText")
+ assert_equals(client.responseXML, null, "responseXML")
+ if(client.readyState == 4)
+ test.done()
+ })
+ }
+ client.open("GET", "resources/infinite-redirects.py")
+ client.send(null)
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-aborted.html b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-aborted.html
new file mode 100644
index 00000000000..2be888f8884
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-aborted.html
@@ -0,0 +1,26 @@
+ <!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8" />
+ <title>XHR2 Timeout Property Tests</title>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-abort()-method" data-tested-assertations="following-sibling::ol/li[4] following-sibling::ol/li[4]/ol/li[5]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-timeout-attribute" data-tested-assertations="following-sibling::ol/li[2]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#abort-error" data-tested-assertations=".."/>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#event-xhr-abort" data-tested-assertations="../.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#timeout-error" data-tested-assertations=".."/>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#event-xhr-timeout" data-tested-assertations="../.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#request-error" data-tested-assertations="following::ol/li[9]"/>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#infrastructure-for-the-send()-method" data-tested-assertations="following-sibling::dl//code[contains(@title,'dom-XMLHttpRequest-timeout')]/.. following-sibling::dl//code[contains(@title,'dom-XMLHttpRequest-timeout')]/../following-sibling::dd following::dt[1] following::dd[1]" />
+ <link rel="stylesheet" href="/resources/testharness.css" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="resources/xmlhttprequest-timeout.js"></script>
+ <script src="resources/xmlhttprequest-timeout-runner.js"></script>
+</head>
+<body>
+ <h1>Description</h1>
+ <p>This test validates that the XHR2 timeout property behaves as expected in async cases in document (i.e. non-worker) context.</p>
+ <div id="log"></div>
+ <script src="resources/xmlhttprequest-timeout-aborted.js" type="text/javascript"></script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-abortedonmain.html b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-abortedonmain.html
new file mode 100644
index 00000000000..9226ffadddd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-abortedonmain.html
@@ -0,0 +1,23 @@
+ <!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8" />
+ <title>XHR2 Timeout Property Tests</title>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-abort()-method" data-tested-assertations="following-sibling::ol/li[4] following-sibling::ol/li[4]/ol/li[5]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#abort-error" data-tested-assertations=".."/>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#event-xhr-abort" data-tested-assertations="../.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#request-error" data-tested-assertations="following::ol/li[9]"/>
+ <link rel="stylesheet" href="/resources/testharness.css" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="resources/xmlhttprequest-timeout.js"></script>
+ <script src="resources/xmlhttprequest-timeout-runner.js"></script>
+</head>
+<body>
+ <h1>Description</h1>
+ <p>This test validates that the XHR2 timeout property behaves as expected in async cases in document (i.e. non-worker) context.</p>
+ <div id="log"></div>
+ <script src="resources/xmlhttprequest-timeout-abortedonmain.js" type="text/javascript"></script>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-overrides.html b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-overrides.html
new file mode 100644
index 00000000000..82fee067c63
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-overrides.html
@@ -0,0 +1,23 @@
+ <!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8" />
+ <title>XHR2 Timeout Property Tests</title>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-timeout-attribute" data-tested-assertations="following::ol[1]/li[2]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#handler-xhr-ontimeout" data-tested-assertations="../.."/>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#timeout-error" data-tested-assertations=".."/>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#request-error" data-tested-assertations="following::ol[1]/li[9]"/>
+ <link rel="stylesheet" href="/resources/testharness.css" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="resources/xmlhttprequest-timeout.js"></script>
+ <script src="resources/xmlhttprequest-timeout-runner.js"></script>
+</head>
+<body>
+ <h1>Description</h1>
+ <p>This test validates that the XHR2 timeout property behaves as expected in async cases in document (i.e. non-worker) context.</p>
+ <div id="log"></div>
+ <script src="resources/xmlhttprequest-timeout-overrides.js"></script>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-overridesexpires.html b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-overridesexpires.html
new file mode 100644
index 00000000000..260844d0db6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-overridesexpires.html
@@ -0,0 +1,23 @@
+ <!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8" />
+ <title>XHR2 Timeout Property Tests</title>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-timeout-attribute" data-tested-assertations="following::ol[1]/li[2]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#handler-xhr-ontimeout" data-tested-assertations="../.."/>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#timeout-error" data-tested-assertations=".."/>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#request-error" data-tested-assertations="following::ol[1]/li[9]"/>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#infrastructure-for-the-send()-method" data-tested-assertations="following-sibling::dl//code[contains(@title,'dom-XMLHttpRequest-timeout')]/.. following-sibling::dl//code[contains(@title,'dom-XMLHttpRequest-timeout')]/../following-sibling::dd following::dt[1] following::dd[1]" />
+ <link rel="stylesheet" href="/resources/testharness.css" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="resources/xmlhttprequest-timeout.js"></script>
+ <script src="resources/xmlhttprequest-timeout-runner.js"></script>
+</head>
+<body>
+ <h1>Description</h1>
+ <p>This test validates that the XHR2 timeout property behaves as expected in async cases in document (i.e. non-worker) context.</p>
+ <div id="log"></div>
+ <script src="resources/xmlhttprequest-timeout-overridesexpires.js" type="text/javascript"></script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-simple.html b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-simple.html
new file mode 100644
index 00000000000..aa473442ee4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-simple.html
@@ -0,0 +1,24 @@
+ <!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8" />
+ <title>XHR2 Timeout Property Tests</title>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-timeout-attribute" data-tested-assertations="following::ol[1]/li[2]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#handler-xhr-ontimeout" data-tested-assertations="../.."/>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#timeout-error" data-tested-assertations=".."/>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#request-error" data-tested-assertations="following::ol[1]/li[9]"/>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#infrastructure-for-the-send()-method" data-tested-assertations="following-sibling::dl//code[contains(@title,'dom-XMLHttpRequest-timeout')]/.. following-sibling::dl//code[contains(@title,'dom-XMLHttpRequest-timeout')]/../following-sibling::dd following::dt[1] following::dd[1]" />
+ <link rel="stylesheet" href="/resources/testharness.css" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="resources/xmlhttprequest-timeout.js"></script>
+ <script src="resources/xmlhttprequest-timeout-runner.js"></script>
+</head>
+<body>
+ <h1>Description</h1>
+ <p>This test validates that the XHR2 timeout property behaves as expected in async cases in document (i.e. non-worker) context.</p>
+ <div id="log"></div>
+ <script src="resources/xmlhttprequest-timeout-simple.js"></script>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-synconmain.html b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-synconmain.html
new file mode 100644
index 00000000000..992b10efd97
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-synconmain.html
@@ -0,0 +1,21 @@
+ <!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8" />
+ <title>XHR2 Timeout Property Tests</title>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-timeout-attribute" data-tested-assertations="following::ol[1]/li[1]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-open()-method" data-tested-assertations="following::ol[1]/li[10]" />
+ <link rel="stylesheet" href="/resources/testharness.css" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="resources/xmlhttprequest-timeout.js"></script>
+ <script src="resources/xmlhttprequest-timeout-runner.js"></script>
+</head>
+<body>
+ <h1>Description</h1>
+ <p>This test validates that the XHR2 timeout property behaves as expected in async cases in document (i.e. non-worker) context.</p>
+ <div id="log"></div>
+ <script src="resources/xmlhttprequest-timeout-synconmain.js" type="text/javascript"></script>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-twice.html b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-twice.html
new file mode 100644
index 00000000000..4634220eca4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-twice.html
@@ -0,0 +1,25 @@
+ <!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8" />
+ <title>XHR2 Timeout Property Tests</title>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#timeout-error" />
+ <link rel="stylesheet" href="/resources/testharness.css" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-timeout-attribute" data-tested-assertations="following::ol[1]/li[2]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#handler-xhr-ontimeout" data-tested-assertations="../.."/>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#timeout-error" data-tested-assertations=".."/>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#request-error" data-tested-assertations="following::ol[1]/li[9]"/>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#infrastructure-for-the-send()-method" data-tested-assertations="following-sibling::dl//code[contains(@title,'dom-XMLHttpRequest-timeout')]/.. following-sibling::dl//code[contains(@title,'dom-XMLHttpRequest-timeout')]/../following-sibling::dd following::dt[1] following::dd[1]" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="resources/xmlhttprequest-timeout.js"></script>
+ <script src="resources/xmlhttprequest-timeout-runner.js"></script>
+</head>
+<body>
+ <h1>Description</h1>
+ <p>This test validates that the XHR2 timeout property behaves as expected in async cases in document (i.e. non-worker) context.</p>
+ <div id="log"></div>
+ <script src="resources/xmlhttprequest-timeout-twice.js" type="text/javascript"></script>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-worker-aborted.html b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-worker-aborted.html
new file mode 100644
index 00000000000..f0005afa2e0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-worker-aborted.html
@@ -0,0 +1,28 @@
+ <!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8" />
+ <title>XHR2 Timeout Property Tests in Worker</title>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-abort()-method" data-tested-assertations="following-sibling::ol/li[4] following-sibling::ol/li[4]/ol/li[5]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-timeout-attribute" data-tested-assertations="following-sibling::ol/li[2]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#abort-error" data-tested-assertations=".."/>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#event-xhr-abort" data-tested-assertations="../.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#timeout-error" data-tested-assertations=".."/>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#event-xhr-timeout" data-tested-assertations="../.." />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#request-error" data-tested-assertations="following::ol/li[9]"/>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#infrastructure-for-the-send()-method" data-tested-assertations="following-sibling::dl//code[contains(@title,'dom-XMLHttpRequest-timeout')]/.. following-sibling::dl//code[contains(@title,'dom-XMLHttpRequest-timeout')]/../following-sibling::dd following::dt[1] following::dd[1]" />
+ <link rel="stylesheet" href="/resources/testharness.css" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="resources/xmlhttprequest-timeout-runner.js"></script>
+</head>
+<body>
+ <h1>Description</h1>
+ <p>This test validates that the XHR2 timeout property behaves as expected in in a worker context.</p>
+ <div id="log"></div>
+ <script type="text/javascript">
+ var worker = new Worker("resources/xmlhttprequest-timeout-aborted.js");
+ worker.addEventListener("message", testResultCallbackHandler);
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-worker-overrides.html b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-worker-overrides.html
new file mode 100644
index 00000000000..e3dbd5c949b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-worker-overrides.html
@@ -0,0 +1,24 @@
+ <!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8" />
+ <title>XHR2 Timeout Property Tests in Worker</title>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-timeout-attribute" data-tested-assertations="following::ol[1]/li[2]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#handler-xhr-ontimeout" data-tested-assertations="../.."/>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#timeout-error" data-tested-assertations=".."/>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#request-error" data-tested-assertations="following::ol[1]/li[9]"/>
+ <link rel="stylesheet" href="/resources/testharness.css" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="resources/xmlhttprequest-timeout-runner.js"></script>
+</head>
+<body>
+ <h1>Description</h1>
+ <p>This test validates that the XHR2 timeout property behaves as expected in in a worker context.</p>
+ <div id="log"></div>
+ <script type="text/javascript">
+ var worker = new Worker("resources/xmlhttprequest-timeout-overrides.js");
+ worker.addEventListener("message", testResultCallbackHandler);
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-worker-overridesexpires.html b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-worker-overridesexpires.html
new file mode 100644
index 00000000000..a2c8009ea74
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-worker-overridesexpires.html
@@ -0,0 +1,25 @@
+ <!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8" />
+ <title>XHR2 Timeout Property Tests in Worker</title>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-timeout-attribute" data-tested-assertations="following::ol[1]/li[2]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#handler-xhr-ontimeout" data-tested-assertations="../.."/>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#timeout-error" data-tested-assertations=".."/>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#request-error" data-tested-assertations="following::ol[1]/li[9]"/>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#infrastructure-for-the-send()-method" data-tested-assertations="following-sibling::dl//code[contains(@title,'dom-XMLHttpRequest-timeout')]/.. following-sibling::dl//code[contains(@title,'dom-XMLHttpRequest-timeout')]/../following-sibling::dd following::dt[1] following::dd[1]" />
+ <link rel="stylesheet" href="/resources/testharness.css" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="resources/xmlhttprequest-timeout-runner.js"></script>
+</head>
+<body>
+ <h1>Description</h1>
+ <p>This test validates that the XHR2 timeout property behaves as expected in in a worker context.</p>
+ <div id="log"></div>
+ <script type="text/javascript">
+ var worker = new Worker("resources/xmlhttprequest-timeout-overridesexpires.js");
+ worker.addEventListener("message", testResultCallbackHandler);
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-worker-simple.html b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-worker-simple.html
new file mode 100644
index 00000000000..994ccb6ecce
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-worker-simple.html
@@ -0,0 +1,26 @@
+ <!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8" />
+ <title>XHR2 Timeout Property Tests in Worker</title>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-timeout-attribute" data-tested-assertations="following::ol[1]/li[2]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#handler-xhr-ontimeout" data-tested-assertations="../.."/>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#timeout-error" data-tested-assertations=".."/>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#request-error" data-tested-assertations="following::ol[1]/li[9]"/>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#infrastructure-for-the-send()-method" data-tested-assertations="following-sibling::dl//code[contains(@title,'dom-XMLHttpRequest-timeout')]/.. following-sibling::dl//code[contains(@title,'dom-XMLHttpRequest-timeout')]/../following-sibling::dd following::dt[1] following::dd[1]" />
+ <link rel="stylesheet" href="/resources/testharness.css" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="resources/xmlhttprequest-timeout-runner.js"></script>
+</head>
+<body>
+ <h1>Description</h1>
+ <p>This test validates that the XHR2 timeout property behaves as expected in in a worker context.</p>
+ <div id="log"></div>
+ <script type="text/javascript">
+ var worker = new Worker("resources/xmlhttprequest-timeout-simple.js");
+ worker.onmessage = testResultCallbackHandler;
+ </script>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-worker-synconworker.html b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-worker-synconworker.html
new file mode 100644
index 00000000000..50aa65193c9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-worker-synconworker.html
@@ -0,0 +1,25 @@
+ <!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8" />
+ <title>XHR2 Timeout Property Tests in Worker</title>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-timeout-attribute" data-tested-assertations="following::ol[1]/li[2]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#handler-xhr-ontimeout" data-tested-assertations="../.."/>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#timeout-error" data-tested-assertations=".."/>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#request-error" data-tested-assertations="following::ol[1]/li[9]"/>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#infrastructure-for-the-send()-method" data-tested-assertations="following-sibling::dl//code[contains(@title,'dom-XMLHttpRequest-timeout')]/.. following-sibling::dl//code[contains(@title,'dom-XMLHttpRequest-timeout')]/../following-sibling::dd following::dt[1] following::dd[1]" />
+ <link rel="stylesheet" href="/resources/testharness.css" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="resources/xmlhttprequest-timeout-runner.js"></script>
+</head>
+<body>
+ <h1>Description</h1>
+ <p>This test validates that the XHR2 timeout property behaves as expected in in a worker context.</p>
+ <div id="log"></div>
+ <script type="text/javascript">
+ var worker = new Worker("resources/xmlhttprequest-timeout-synconworker.js");
+ worker.addEventListener("message", testResultCallbackHandler);
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-worker-twice.html b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-worker-twice.html
new file mode 100644
index 00000000000..18f6a39248a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-timeout-worker-twice.html
@@ -0,0 +1,26 @@
+ <!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8" />
+ <title>XHR2 Timeout Property Tests in Worker</title>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-timeout-attribute" data-tested-assertations="following::ol[1]/li[2]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#handler-xhr-ontimeout" data-tested-assertations="../.."/>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#timeout-error" data-tested-assertations=".."/>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#request-error" data-tested-assertations="following::ol[1]/li[9]"/>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#infrastructure-for-the-send()-method" data-tested-assertations="following-sibling::dl//code[contains(@title,'dom-XMLHttpRequest-timeout')]/.. following-sibling::dl//code[contains(@title,'dom-XMLHttpRequest-timeout')]/../following-sibling::dd following::dt[1] following::dd[1]" />
+ <link rel="stylesheet" href="/resources/testharness.css" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="resources/xmlhttprequest-timeout-runner.js"></script>
+</head>
+<body>
+ <h1>Description</h1>
+ <p>This test validates that the XHR2 timeout property behaves as expected in in a worker context.</p>
+ <div id="log"></div>
+ <script type="text/javascript">
+ var worker = new Worker("resources/xmlhttprequest-timeout-twice.js");
+ worker.addEventListener("message", testResultCallbackHandler);
+ </script>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-unsent.htm b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-unsent.htm
new file mode 100644
index 00000000000..a343b76e649
--- /dev/null
+++ b/tests/wpt/web-platform-tests/XMLHttpRequest/xmlhttprequest-unsent.htm
@@ -0,0 +1,36 @@
+<!doctype html>
+<html>
+ <head>
+ <title>XMLHttpRequest: members during UNSENT</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://xhr.spec.whatwg.org/#dom-xmlhttprequest-unsent" data-tested-assertations=".. following::dd" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#dom-xmlhttprequest-setrequestheader" data-tested-assertations="following::ol/li[1]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-send()-method" data-tested-assertations="following::ol/li[1]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-status-attribute" data-tested-assertations="following::ol/li[1]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-statustext-attribute" data-tested-assertations="following::ol/li[1]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-getresponseheader()-method" data-tested-assertations="following::ol/li[1]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-getallresponseheaders()-method" data-tested-assertations="following::ol/li[1]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-responsetext-attribute" data-tested-assertations="following::ol/li[2]" />
+ <link rel="help" href="https://xhr.spec.whatwg.org/#the-responsexml-attribute" data-tested-assertations="following::ol/li[2]" />
+
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ test(function() {
+ var client = new XMLHttpRequest()
+ assert_throws("InvalidStateError", function() { client.setRequestHeader("x-test", "test") }, "setRequestHeader")
+ assert_throws("InvalidStateError", function() { client.send(null) }, "send")
+ assert_equals(client.status, 0, "status")
+ assert_equals(client.statusText, "", "statusText")
+ assert_equals(client.getAllResponseHeaders(), "", "getAllResponseHeaders")
+ assert_equals(client.getResponseHeader("x-test"), null, "getResponseHeader")
+ assert_equals(client.responseText, "", "responseText")
+ assert_equals(client.responseXML, null, "responseXML")
+
+ assert_equals(client.readyState, client.UNSENT, "readyState")
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/ambient-light/AmbientLight_tests.html b/tests/wpt/web-platform-tests/ambient-light/AmbientLight_tests.html
new file mode 100644
index 00000000000..3751574ae46
--- /dev/null
+++ b/tests/wpt/web-platform-tests/ambient-light/AmbientLight_tests.html
@@ -0,0 +1,11 @@
+<!doctype html>
+<meta charset=utf8>
+<meta content=long name=timeout>
+<meta content="width=device-width, initial-scale=1" name=viewport>
+<title>Ambient Light Events Test Suite</title>
+<link rel="help" href="http://www.w3.org/TR/ambient-light/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="DeviceLightEvent_tests.js"></script>
+<div id="log"></div>
+
diff --git a/tests/wpt/web-platform-tests/ambient-light/DeviceLightEvent_tests.js b/tests/wpt/web-platform-tests/ambient-light/DeviceLightEvent_tests.js
new file mode 100644
index 00000000000..af89cb45c3f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/ambient-light/DeviceLightEvent_tests.js
@@ -0,0 +1,403 @@
+(function() {
+ //inheritance tests
+ test(function() {
+ var event = new DeviceLightEvent('');
+ assert_true(event instanceof window.DeviceLightEvent);
+ }, 'the event is an instance of DeviceLightEvent');
+
+ test(function() {
+ var event = new DeviceLightEvent('');
+ assert_true(event instanceof window.Event);
+ }, 'the event inherits from Event');
+
+ //Type attribute tests
+ test(function() {
+ assert_throws(new TypeError(), function() {
+ new DeviceLightEvent();
+ }, 'First argument is required, so was expecting a TypeError.');
+ }, 'Missing type argument');
+
+ test(function() {
+ var event = new DeviceLightEvent(undefined);
+ assert_equals(event.type, 'undefined');
+ }, 'Event type set to undefined');
+
+ test(function() {
+ var event = new DeviceLightEvent(null);
+ assert_equals(event.type, 'null');
+ }, 'type argument is null');
+
+ test(function() {
+ var event = new DeviceLightEvent(123);
+ assert_equals(event.type, '123');
+ }, 'type argument is number');
+
+ test(function() {
+ var event = new DeviceLightEvent(new Number(123));
+ assert_equals(event.type, '123');
+ }, 'type argument is Number');
+
+ test(function() {
+ var event = new DeviceLightEvent([]);
+ assert_equals(event.type, '');
+ }, 'type argument is array');
+
+ test(function() {
+ var event = new DeviceLightEvent(new Array());
+ assert_equals(event.type, '');
+ }, 'type argument is instance of Array');
+
+ test(function() {
+ var event = new DeviceLightEvent(['t', ['e', ['s', ['t']]]]);
+ assert_equals(event.type, 't,e,s,t');
+ }, 'type argument is nested array');
+
+ test(function() {
+ var event = new DeviceLightEvent(Math);
+ assert_equals(event.type, '[object Math]');
+ }, 'type argument is host object');
+
+ test(function() {
+ var event = new DeviceLightEvent(true);
+ assert_equals(event.type, 'true');
+ }, 'type argument is boolean (true)');
+
+ test(function() {
+ var event = new DeviceLightEvent(new Boolean(true));
+ assert_equals(event.type, 'true');
+ }, 'type argument is instance of Boolean (true)');
+
+ test(function() {
+ var event = new DeviceLightEvent(false);
+ assert_equals(event.type, 'false');
+ }, 'type argument is boolean (false)');
+
+ test(function() {
+ var event = new DeviceLightEvent(new Boolean(false));
+ assert_equals(event.type, 'false');
+ }, 'type argument is instance of Boolean (false)');
+
+ test(function() {
+ var event = new DeviceLightEvent('test');
+ assert_equals(event.type, 'test');
+ }, 'type argument is string');
+
+ test(function() {
+ var event = new DeviceLightEvent(new String('test'));
+ assert_equals(event.type, 'test');
+ }, 'type argument is instance of String');
+
+ test(function() {
+ var event = new DeviceLightEvent(function test() {});
+ assert_regexp_match(event.type, /function test.+{\s?}/);
+ }, 'type argument is function');
+
+ test(function() {
+ var event = new DeviceLightEvent({
+ toString: function() {
+ return '123';
+ }
+ });
+ assert_equals(event.type, '123');
+ }, 'type argument is complex object, with toString method');
+
+ test(function() {
+ assert_throws(new TypeError(), function() {
+ new DeviceLightEvent({
+ toString: function() {
+ return function() {}
+ }
+ });
+ });
+ }, 'toString is of type function');
+
+ //eventInitDict attribute tests
+ test(function() {
+ var event = new DeviceLightEvent('test', undefined);
+ assert_equals(event.value, Infinity);
+ }, 'eventInitDict argument sets to undefined');
+
+ test(function() {
+ var event = new DeviceLightEvent('test', null);
+ assert_equals(event.value, Infinity);
+ }, 'eventInitDict argument is null');
+
+ test(function() {
+ var date = new Date();
+ assert_throws(new TypeError(), function() {
+ new DeviceLightEvent('test', date);
+ });
+ }, 'eventInitDict argument is Date object');
+
+ test(function() {
+ var regexp = /abc/;
+ assert_throws(new TypeError(), function() {
+ new DeviceLightEvent('test', regexp);
+ });
+ }, 'eventInitDict argument is RegExp object');
+
+ test(function() {
+ assert_throws(new TypeError(), function() {
+ new DeviceLightEvent('test', false);
+ });
+ }, 'eventInitDict argument is boolean');
+
+ test(function() {
+ assert_throws(new TypeError(), function() {
+ new DeviceLightEvent('test', 123);
+ });
+ }, 'eventInitDict argument is number');
+
+ test(function() {
+ assert_throws(new TypeError(), function() {
+ new DeviceLightEvent('test', 'hello');
+ });
+ }, 'eventInitDict argument is string');
+
+ //test readonly attribute double value;
+ test(function() {
+ var event = new DeviceLightEvent('test');
+ assert_readonly(event, 'value', 'readonly attribute value');
+ }, 'value is readonly');
+
+ test(function() {
+ var event = new DeviceLightEvent('test');
+ assert_equals(event.value, Infinity);
+ }, 'value initializes to positive Infinity');
+
+ test(function() {
+ var event = new DeviceLightEvent('test', {
+ value: Infinity
+ });
+ assert_equals(event.value, Infinity);
+ }, 'value set to positive Infinity');
+
+ test(function() {
+ var event = new DeviceLightEvent('test', {
+ value: -Infinity
+ });
+ assert_equals(event.value, -Infinity);
+ }, 'value set to negative Infinity');
+
+ test(function() {
+ var event = new DeviceLightEvent('test', {
+ value: 0
+ });
+ assert_equals(event.value, 0);
+ }, 'value set to 0');
+
+ test(function() {
+ var event = new DeviceLightEvent('test', {
+ value: 1
+ });
+ assert_equals(event.value, 1);
+ }, 'value set to 1');
+
+ test(function() {
+ var event = new DeviceLightEvent('test', {
+ value: -1
+ });
+ assert_equals(event.value, -1);
+ }, 'value set to -1');
+
+ test(function() {
+ var event = new DeviceLightEvent('test', {
+ value: 0.5
+ });
+ assert_equals(event.value, 0.5);
+ }, 'value set to 0.5');
+
+ test(function() {
+ var event = new DeviceLightEvent('test', {
+ value: false
+ });
+ assert_equals(event.value, 0, 'value set to false, converts to 0.');
+ }, 'value set to false');
+
+ test(function() {
+ var event = new DeviceLightEvent('test', {
+ value: true
+ });
+ assert_equals(event.value, 1, 'value set to true, converts to 1.');
+ }, 'value set to true');
+
+
+ test(function() {
+ var prop = {
+ value: undefined
+ };
+ try {
+ var event = new DeviceLightEvent('test', prop);
+ assert_true(isNaN(event.value));
+ } catch(e) {
+ assert_unreached('error message: ' + e.message);
+ }
+ }, 'value of undefined resolves to NaN');
+
+ test(function() {
+ var event = new DeviceLightEvent('test', {
+ value: null
+ });
+ assert_equals(event.value, 0, 'value resolves to 0');
+ }, 'value of null resolves to 0');
+
+
+ test(function() {
+ var event = new DeviceLightEvent('test', {
+ value: ''
+ });
+ assert_equals(event.value, 0, 'value must resolve to 0');
+ }, 'value of empty string must resolve to 0');
+
+ test(function() {
+ var event = new DeviceLightEvent('test', {
+ value: '\u0020'
+ });
+ assert_equals(event.value, 0, 'value must resolve to 0');
+ }, 'value of U+0020 must resolve to 0');
+
+ test(function() {
+ var event = new DeviceLightEvent('test', {
+ value: '\u0020\u0020\u0020\u0020\u0020\u0020'
+ });
+ assert_equals(event.value, 0, 'value must resolve to 0');
+ }, 'value of multiple U+0020 must resolve to 0');
+
+ test(function() {
+ var event = new DeviceLightEvent('test', {
+ value: '\u0020\u0020\u00201234\u0020\u0020\u0020'
+ });
+ assert_equals(event.value, 1234, 'converts to 1234');
+ }, 'converts to 1234');
+
+ test(function() {
+ var event = new DeviceLightEvent('test', {
+ value: []
+ });
+ assert_equals(event.value, 0, 'converts to 0');
+ }, 'converts to 0');
+
+
+ test(function() {
+ var prop = {
+ value: {}
+ };
+ try {
+ var event = new DeviceLightEvent('test', prop);
+ assert_true(isNaN(event.value));
+ } catch(e) {
+ assert_unreached('error message: ' + e.message);
+ }
+ }, 'value of {} resolves to NaN');
+
+ test(function() {
+ var prop = {
+ get value() {
+ return NaN;
+ }
+ };
+ try {
+ var event = new DeviceLightEvent('test', prop);
+ assert_true(isNaN(event.value));
+ } catch(e) {
+ assert_unreached('error message: ' + e.message);
+ }
+ }, 'value resolves to NaN');
+
+ test(function() {
+ var prop = {
+ get value() {
+ return '123';
+ }
+ };
+ var event = new DeviceLightEvent('test', prop);
+ assert_equals(event.value, 123, 'converts to 123');
+ }, 'value resolves 123');
+
+ //test attribute EventHandler ondevicelight;
+ test(function() {
+ var desc = 'window.ondevicelight did not accept callable object',
+ descidl = 'Expected to find ondevicelight attribute on window object',
+ func = function() {};
+ assert_idl_attribute(window, 'ondevicelight', descidl);
+ window.ondevicelight = func;
+ assert_equals(window.ondevicelight, func, desc);
+ }, 'expected ondevicelight on window and to be set to function');
+
+ test(function() {
+ var desc = 'window.ondevicelight must be null';
+ assert_equals(window.ondevicelight, null, desc);
+ }, 'ondevicelight is null');
+
+ test(function() {
+ var desc = 'window.ondevicelight did not treat noncallable as null';
+ window.ondevicelight = function() {};
+ window.ondevicelight = {};
+ assert_equals(window.ondevicelight, null, desc);
+ }, 'treat object as null');
+
+ test(function() {
+ var desc = 'window.ondevicelight did not treat noncallable as null';
+ window.ondevicelight = function() {};
+ window.ondevicelight = {
+ call: 'test'
+ };
+ assert_equals(window.ondevicelight, null, desc);
+ }, 'treat object with non-callable call property as null');
+
+ test(function() {
+ var desc = 'window.ondevicelight did not treat noncallable (string) as null';
+ window.ondevicelight = function() {};
+ window.ondevicelight = 'string';
+ assert_equals(window.ondevicelight, null, desc);
+ }, 'treat string as null');
+
+ test(function() {
+ var desc = 'window.ondevicelight did not treat noncallable (number) as null';
+ window.ondevicelight = function() {};
+ window.ondevicelight = 123;
+ assert_equals(window.ondevicelight, null, desc);
+ }, 'treat number as null');
+
+ test(function() {
+ var desc = 'window.ondevicelight did not treat noncallable (undefined) as null';
+ window.ondevicelight = function() {};
+ window.ondevicelight = undefined;
+ assert_equals(window.ondevicelight, null, desc);
+ }, 'treat undefined as null');
+
+ test(function() {
+ var desc = 'window.ondevicelight did not treat noncallable (array) as null';
+ window.ondevicelight = function() {};
+ window.ondevicelight = [];
+ assert_equals(window.ondevicelight, null, desc);
+ }, 'treat array as null');
+
+ test(function() {
+ var desc = 'window.ondevicelight did not treat noncallable host object as null';
+ window.ondevicelight = function() {};
+ window.ondevicelight = window.Node;
+ assert_equals(window.ondevicelight, null, desc);
+ }, 'treat non-callable host object as null');
+
+ //Async tests
+ var t = async_test('test if DeviceLightEvent received');
+ window.addEventListener('devicelight', function(e) {
+ t.step(function() {
+ var msg = 'expected instance of DeviceLightEvent: ';
+ assert_true(e instanceof window.DeviceLightEvent, msg);
+ assert_idl_attribute(e, 'value', 'event has value property');
+ });
+ t.done();
+ });
+
+ var t2 = async_test('test if DeviceLightEvent received (event handler attribute)');
+ window.ondevicelight = function(e) {
+ t2.step(function() {
+ var msg = 'expected instance of DeviceLightEvent: ';
+ assert_true(e instanceof window.DeviceLightEvent, msg);
+ assert_idl_attribute(e, 'value', 'event has value property');
+ });
+ t2.done();
+ };
+})();
diff --git a/tests/wpt/web-platform-tests/ambient-light/idlharness.html b/tests/wpt/web-platform-tests/ambient-light/idlharness.html
new file mode 100644
index 00000000000..d765e0410fd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/ambient-light/idlharness.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Ambient Light Events IDL tests</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="http://www.w3.org/TR/ambient-light/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/WebIDLParser.js"></script>
+<script src="/resources/idlharness.js"></script>
+<style>
+ pre {
+ display: none;
+ }
+</style>
+<div id="log"></div>
+
+<pre id="untested_idl">
+interface Window {
+};
+
+interface Event {
+};
+
+dictionary EventInit {
+};
+</pre>
+
+<pre id='idl'>
+partial interface Window {
+ attribute EventHandler ondevicelight;
+};
+
+dictionary DeviceLightEventInit : EventInit {
+ unrestricted double value;
+};
+
+[Constructor (DOMString type, optional DeviceLightEventInit eventInitDict)]
+interface DeviceLightEvent : Event {
+ readonly attribute unrestricted double value;
+};
+</pre>
+
+<script>
+(function() {
+ "use strict";
+ var idl_array = new IdlArray();
+ // replace 'EventHandler' and 'unrestricted double' unrecognised by idlharness.js
+ var idls = document.getElementById('idl').textContent.replace(/EventHandler/g, 'Function?').replace(/unrestricted double/g, 'double');
+
+ idl_array.add_untested_idls(document.getElementById('untested_idl').textContent);
+ idl_array.add_idls(idls);
+
+ idl_array.add_objects({
+ Window: ['window'],
+ DeviceLightEvent: ['new DeviceLightEvent("foo")']
+ });
+
+ idl_array.test();
+})();
+</script>
+
diff --git a/tests/wpt/web-platform-tests/animation-timing/callback-invoked.html b/tests/wpt/web-platform-tests/animation-timing/callback-invoked.html
new file mode 100644
index 00000000000..1bf49c0335d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/animation-timing/callback-invoked.html
@@ -0,0 +1,22 @@
+<!doctype html>
+<html>
+ <head>
+ <title>requestAnimationFrame must be triggered once</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://w3c.github.io/web-performance/specs/RequestAnimationFrame/Overview.html#dom-windowanimationtiming-requestanimationframe"/>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ async_test(function (t) {
+ t.step(function() {
+ assert_false(document.hidden, "document.hidden must be exist and be false to run this test properly");
+ });
+ window.requestAnimationFrame(function () {
+ t.step(function() { assert_true(true); t.done(); });
+ });
+ }, "requestAnimationFrame callback is invoked at least once before the timeout");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/animation-timing/cancel-invoked.html b/tests/wpt/web-platform-tests/animation-timing/cancel-invoked.html
new file mode 100644
index 00000000000..d075c0fdac1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/animation-timing/cancel-invoked.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<html>
+ <head>
+ <title>cancelAnimationFrame does nothing</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="https://w3c.github.io/web-performance/specs/RequestAnimationFrame/Overview.html#dom-windowanimationtiming-cancelanimationframe"/>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ test(function (t) {
+ window.cancelAnimationFrame(42);
+ assert_true(true);
+ }, "cancelAnimationFrame does nothing if there is no callback with the given handle");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/animation-timing/idlharness.html b/tests/wpt/web-platform-tests/animation-timing/idlharness.html
new file mode 100644
index 00000000000..09a616b5e68
--- /dev/null
+++ b/tests/wpt/web-platform-tests/animation-timing/idlharness.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8" />
+<title>idlharness test</title>
+<link rel="author" title="Kensaku Komatsu" href="mailto:kensaku.komatsu@gmail.com" />
+<link rel="help" href="http://www.w3.org/TR/animation-timing/#definitions"/>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/webidl2/lib/webidl2.js"></script>
+<script src="/resources/idlharness.js"></script>
+</head>
+<body>
+<h1>idlharness test</h1>
+<p>This test validates the WebIDL included in the Timing control for script-based animations specification.</p>
+
+<pre id='untested_idl' style='display:none'>
+interface Window {
+};
+</pre>
+
+<pre id='idl'>
+partial interface Window {
+ long requestAnimationFrame(FrameRequestCallback callback);
+ void cancelAnimationFrame(long handle);
+};
+
+callback FrameRequestCallback = void (DOMHighResTimeStamp time);
+</pre>
+
+<script>
+
+(function() {
+ var idl_array = new IdlArray();
+
+ idl_array.add_untested_idls(document.getElementById("untested_idl").textContent);
+ idl_array.add_idls(document.getElementById("idl").textContent);
+
+ idl_array.add_objects({Window: ["window"]});
+
+ idl_array.test();
+})();
+
+</script>
+
+<div id="log"></div>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/app-uri/README.md b/tests/wpt/web-platform-tests/app-uri/README.md
new file mode 100644
index 00000000000..a33f0b0b41c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/app-uri/README.md
@@ -0,0 +1,13 @@
+app-URI test suite
+==========
+
+Test suites for [app-URI scheme](http://app-uri.sysapps.org/) specification
+
+You can find here:
+
+[app-URI test suite html file](appURI_test.html)
+
+
+If you want to use System application packages there is manifest file on Sysapps github repo:
+
+[Manifest file - can be used for building application](https://github.com/sysapps/testsuites/blob/gh-pages/app-URI/manifest.webapp) \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/app-uri/appURI_test.html b/tests/wpt/web-platform-tests/app-uri/appURI_test.html
new file mode 100644
index 00000000000..1baaf06ac6a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/app-uri/appURI_test.html
@@ -0,0 +1,394 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>app:URI compliance tests</title>
+ <script src='resources/testharness.js'></script>
+ <script src='resources/testharnessreport.js'></script>
+ <link rel='stylesheet' href='resource/testharness.css'>
+ <link rel="help" href="http://app-uri.sysapps.org/" data-tested-assertations="following::OL[1]/LI[2]" />
+ <style>
+ div {padding:5px 5px 10px 5px;}
+ </style>
+ </head>
+ <body>
+ <div id="logs"></div>
+ <div id="log"></div>
+
+
+ <script>
+ /**********************************************************************************************
+ * This test suite checks your implementation for compliance with the app-URI specification *
+ **********************************************************************************************/
+
+ /* Check if protocol is "app" */
+ if (window.location.protocol === "app:") {
+
+ /* Logging current domain */
+ var domain = window.location.protocol + "//" + window.location.host + "/";
+ document.getElementById("logs").innerHTML = "Current domain: " + domain;
+
+ /* Function that will change HOST value if it is equal to currect application host */
+ function ChangeHostIfEqCurrent(URI){
+ /* Check if URI host is NOT the same as current application host */
+ if (URI.substring(6, 35) === window.location.host) {
+ if (URI.substring(6, 7) !== 4)
+ URI = URI.replace(URI.substring(6, 7), "4");
+ else
+ URI = URI.replace(URI.substring(6, 7), "5");
+ }
+ return URI;
+ }
+
+ /********************************************************
+ * 6.1 Synthesizing an app: URI
+ *
+ * link: http://app-uri.sysapps.org/#synthesizing
+ *
+ ********************************************************/
+
+ /**
+ * Syntax-Based Normalization
+ *
+ * rules for dereferencing an app: URI => 3. Let URI be the value of the [HTTP] Request URI.
+ */
+
+ var TC_name = "Test: Synthesizing an app:URI. Syntax-Based Normalization";
+
+ // variable needed to test scheme-based normalization
+ var tmp_domain = window.location.protocol + "//" + window.location.host;
+
+ var CaseNormalizationXHRtests = [ /* scheme: [ TC name, URI] */
+ [TC_name + " XHR full path: {} => %7b%7d",
+ domain + 'resources/ExamPLE/%7bmY%7d/z...z/index.html'],
+ [TC_name + " XHR full path: } => %7D",
+ domain + 'resources/ExamPLE/%7bmY%7D/z...z/index.html'],
+ [TC_name + " XHR full path: {} => %7B%7D",
+ domain + 'resources/ExamPLE/%7BmY%7D/z...z/index.html'],
+ [TC_name + " XHR full path: Capital letters in patch",
+ domain + 'resources/ExamPLE/mmY/index.html'],
+ [TC_name + " XHR relative path: {} => %7b%7d",
+ 'resources/ExamPLE/%7bmY%7d/z...z/index.html'],
+ [TC_name + " XHR relative path: } => %7D",
+ 'resources/ExamPLE/%7bmY%7D/z...z/index.html'],
+ [TC_name + " XHR relative path: P. => %50%2e",
+ 'resources/Exam%50LE/%7bmY%7d/z%2e..z/index.html'],
+ [TC_name + " XHR relative path: Capital letters in patch",
+ 'resources/ExamPLE/mmY/index.html'],
+ [TC_name + " XHR relative path: ~ => ~",
+ 'resources/ImaGes/~t/{!a}/~sth.png'],
+ [TC_name + " XHR relative path: ~{} => ~%7b%7d",
+ 'resources/ImaGes/~t/%7b!a%7d/~sth.png'],
+
+ /* Percent-Encoding Normalization*/
+ [TC_name + " Percent-Encoding Normalization - XHR full path: c. => %63%2e",
+ domain + 'resources/ExamPLE/%7bmY%7d/z%2e..z/index.html'],
+ [TC_name + " Percent-Encoding Normalization - XHR full path: P. => %50%2e",
+ domain + 'resources/Exam%50LE/%7bmY%7d/z%2e..z/index.html'],
+ [TC_name + " Percent-Encoding Normalization - XHR relative path: {} => %7B%7D",
+ 'resources/ExamPLE/%7BmY%7D/z...z/index.html'],
+ [TC_name + " Percent-Encoding Normalization - XHR relative path: c. => %63%2e",
+ 'resources/ExamPLE/%7bmY%7d/z%2e..z/index.html'],
+ [TC_name + " XHR relative path: ~{} => ~%7b%7d",
+ 'resources/ImaGes/~t/%7b!a%7d/~sth.png'],
+
+ /* Path Segment Normalization */
+ [TC_name + " Path Segment Normalization: using '../..' in path ",
+ 'resources/ExamPLE/mmY/../../ImaGes/~t/%7b!a%7d/~sth.png'],
+
+ /* Scheme-Based Normalization */
+ [TC_name + " Scheme-Based Normalization: domain:/",
+ tmp_domain + ':/resources/ImaGes/~t/%7b!a%7d/~sth.png']
+ ];
+
+ CaseNormalizationXHRtests.forEach(function (data, i) {
+ var name = data[0];
+ var URI = data[1];
+ var xhrTest = async_test(name + " [case " + i + "]");
+ var xhr;
+ xhrTest.step(function () {
+ xhr = new XMLHttpRequest();
+ xhr.open("GET", URI, true);
+ xhr.onreadystatechange = xhrTest.step_func(function (ev) {
+ if (xhr.readyState === 4 && xhr.status === 200) {
+ assert_true(true);
+ xhrTest.done();
+ }
+ if (xhr.readyState !== 4 && xhr.status !== 200 && xhr.status !== 0) {
+ assert_true(false,
+ "[ Error: readyState=" + xhr.readyState + " satus=" + xhr.status + "] ");
+ }
+ });
+ xhr.send();
+ });
+ delete name, URI, xhr, xhrTest;
+ });
+ delete CaseNormalizationXHRtests;
+
+
+ /**
+ * ContentType reponse
+ *
+ * rules for dereferencing an app: URI =>
+ 8. Let potential-file be the result of attempting locate the file at path
+ */
+
+ TC_name = "Test: [HTTP] 200 reponse status (OK),value of content-type as the [HTTP] ";
+ TC_name += "Content-Type header, and the contents of potential-file as the response body";
+
+ var ContentTypeResponsetests = [ /* scheme:[ TC name, URI, content-type] */
+ [TC_name + ' [text/html]', 'resources/ExamPLE/mmY/index.html', 'text/html'],
+ [TC_name + " [image/png]", 'resources/ImaGes/~t/%7b!a%7d/~sth.png', "image/png"],
+ [TC_name + " [text/plain]", 'resources/ExamPLE/mmY/sth.txt', "text/plain"]
+ ];
+
+ ContentTypeResponsetests.forEach(function (data, i) {
+ var name = data[0];
+ var URI = data[1];
+ var content_type = data[2];
+ var xhrTest = async_test(name + " [case " + i + "]");
+ var xhr;
+ xhrTest.step(function () {
+ xhr = new XMLHttpRequest();
+ xhr.open("GET", URI, true);
+ xhr.onreadystatechange = xhrTest.step_func(function (ev) {
+ if (xhr.readyState === 4 && xhr.status === 200) {
+ assert_true(xhr.getResponseHeader("Content-Type") === content_type,
+ "[Content-Type does not mach with expected, it is: "
+ + xhr.getResponseHeader("Content-Type") + "]");
+
+ xhrTest.done();
+ }
+ if (xhr.readyState !== 4 && xhr.status !== 200 && xhr.status !== 0) {
+ assert_true(false,
+ "[ Error: readyState=" + xhr.readyState + " satus=" + xhr.status + "] ");
+ }
+ });
+ xhr.send();
+ });
+ delete name, URI, xhr, xhrTest, content_type;
+ });
+ delete ContentTypeResponsetests;
+
+
+ /**
+ * Case Normalization in Path
+ *
+ * rules for dereferencing an app: URI =>
+ 4. Resolve URI into an absolute URL using the document's origin as the base.
+ * rules for dereferencing an app: URI => 7. Let path be the path component of URI.
+ *
+ * Character Normalization in domain name
+ */
+
+
+
+ TC_name = "Test: Synthesizing an app:URI. Syntax-Based Normalization: Case Normalization";
+ var PathCaseNormalizationtests = [ /* scheme: [ TC name, URI] */
+ [TC_name, "resources/ImaGes/{{a}}/Test_1/$a/sth34!.png",
+ domain + "resources/ImaGes/%7B%7Ba%7D%7D/Test_1/$a/sth34!.png", true],
+ [TC_name, "resources/ImaGes/{{a}}/Test_1/$a/sth34!.png",
+ domain + "resources/ImaGes/%7b%7Ba%7D%7D/Test_1/$a/sth34!.png", false],
+
+ /* Character Normalization in Domain */
+ [TC_name, window.location.protocol + "//" + window.location.host.toUpperCase()
+ + "/resources/ImaGes/{{a}}/Test_1/$a/sth34!.png",
+ domain + "resources/ImaGes/%7B%7Ba%7D%7D/Test_1/$a/sth34!.png", true]
+ ];
+
+ PathCaseNormalizationtests.forEach(function (data, i) {
+ var name = data[0];
+ var elem_path = data[1];
+ var path_expected = data[2];
+ var expected = data[3];
+ test(function () {
+ var img = document.createElement("img");
+ img.src = elem_path;
+ if (expected)
+ assert_true(img.src === path_expected,
+ "[Error, path=" + img.src + " Expected=" + domain + path_expected + "]");
+ else
+ assert_false(img.src === path_expected,
+ "[Error, path=" + img.src + " Expected=" + domain + path_expected + "]");
+ delete img;
+
+ }, name + " [case " + i + "]");
+ delete elem_path, path_expected, expected, name;
+ });
+ delete PathCaseNormalizationtests;
+
+
+
+
+ /********************************************************************************************
+ * 6.4 Dereferencing and retrieval of files from a container
+ *
+ * link: http://app-uri.sysapps.org/#dereferencing-and-retrieval-of-files-from-a-container
+ *
+ ********************************************************************************************/
+
+
+
+ /**
+ * 501 Method Not Implemented error - response body MUST be empty
+ *
+ * rules for dereferencing an app: URI =>
+ 1. If the request is not a [HTTP] GET request,
+ return a [HTTP] 501 Not Implemented response and terminate this algorithm.
+ */
+
+
+ function Get_501_reponse(name, URI, expected_response) {
+ var xhrTest = async_test(name);
+ xhrTest.step(function () {
+ var xhr = new XMLHttpRequest();
+ /* on purpose wrong method "gett" instead of "get" was used */
+ xhr.open("gett", URI, true);
+ xhr.onreadystatechange = xhrTest.step_func(function (ev) {
+ if (xhr.readyState !== 4 && xhr.status === 501) {
+ assert_true(xhr.response === expected_response,
+ "[" + xhr.status + " error, response:[" + xhr.response + "] " + "]");
+
+ xhrTest.done();
+ }
+ if (xhr.readyState === 4 && xhr.status === 200) {
+ assert_true(false,
+ "[Should get 501 but got 200 OK, "
+ +"file found while it should not find it, "
+ +" non existing 'gett' method used");
+ }
+ });
+ xhr.send();
+ });
+ delete xhrTest;
+ }
+ Get_501_reponse(TC_name + " 501 Method Not Implemented error expected",
+ 'resources/ExamPLE/mmY/index.html', "");
+
+
+ /**
+ * 400 Bad Request error - response body MUST be empty
+ *
+ * rules for dereferencing an app: URI =>
+ 5. If the URI does not conform to the appuri ABNF, return a
+ [HTTP] 400 Bad Request response and terminate this algorithm.
+ */
+
+ function Get_400_reponse(name, URI, expected_response) {
+ var xhrTest = async_test(name);
+ xhrTest.step(function () {
+ var xhr = new XMLHttpRequest();
+ //alert(URI);
+ xhr.open("GET", URI, true);
+ xhr.onreadystatechange = xhrTest.step_func(function (ev) {
+ if (xhr.readyState !== 4 && xhr.status === 400) {
+ assert_true(xhr.response === expected_response,
+ "[" + xhr.status + " error, response:[" + xhr.response + "] " + "]");
+
+ xhrTest.done();
+ }
+ if (xhr.readyState === 4 && xhr.status === 200) {
+ assert_true(false,
+ "[Should get 400 but got 200 OK, "
+ +"file found while it should not find it, "
+ +"since no specific file requested]");
+ }
+ });
+ xhr.send();
+ });
+ delete xhrTest;
+ }
+ Get_400_reponse(TC_name + " 400 Method Not Implemented error expected, no path",
+ tmp_domain, "");
+ Get_400_reponse(TC_name + " 400 Method Not Implemented error expected, different domain with no path",
+ ChangeHostIfEqCurrent("app://f15a6d20-cefa-13e5-1972-800e20d19a76"), "");
+
+
+ /**
+ * 403 Forbidden error - response body MUST be empty
+ *
+ * rules for dereferencing an app: URI =>
+ 6. If the URI uses the scheme 'app', but the authority does not match
+ the one assigned to this document, return a [HTTP] 403 Forbidden
+ response and terminate this algorithm
+ (i.e., prevent inter-application content access).
+ */
+
+ function Get_403_reponse(name, URI, expected_response) {
+ var xhrTest = async_test(name);
+ xhrTest.step(function () {
+ /* Change if URI host is the same as current application host */
+ URI = ChangeHostIfEqCurrent(URI);
+ var xhr = new XMLHttpRequest();
+ xhr.open("GET", URI, true);
+ xhr.onreadystatechange = xhrTest.step_func(function (ev) {
+ if (xhr.readyState === 4 && xhr.status === 200) {
+ assert_true(false, "[403 error expected, got: 200 OK instead]");
+ }
+ if (xhr.readyState !== 4 && xhr.status === 403) {
+ assert_true(xhr.response === expected_response, "["
+ + xhr.status + " error, response:[" + xhr.response + "] "
+ + "]");
+ xhrTest.done();
+ }
+ });
+ xhr.send();
+ });
+ }
+ Get_403_reponse(TC_name + " Access to resticted URI - 403 Forbidden error expected",
+ window.location.protocol + "//f15a6d20-cefa-13e5-1972-800e20d19a76/" + 'resources/ExamPLE/mmY/index.html', "");
+
+
+ /**
+ * 404 Not Found error - response body MUST be empty
+ *
+ * rules for dereferencing an app: URI =>
+ 9. If potential-file is not found at the given path inside the container,
+ return a [HTTP] 404 Not Found response.
+ */
+
+ TC_name = "Test: 6.4 Dereferencing and retrieval of files from a container";
+
+ var CompareResponseBodytests = [ /* scheme: [TC name, URI, expected_response]*/
+ [TC_name + " 404 Not Found error expected",
+ 'resources/ImaGes/~t/%7b!a%7d/~sth11.png', ""]
+ ];
+
+ CompareResponseBodytests.forEach(function (data, i) {
+ var name = data[0];
+ var URI = data[1];
+ var expected_response = data[2];
+ var xhrTest = async_test(name);
+ var xhr;
+ xhrTest.step(function () {
+ xhr = new XMLHttpRequest();
+ xhr.open("GET", URI, true);
+ xhr.onreadystatechange = xhrTest.step_func(function (ev) {
+ if (xhr.readyState !== 4 && xhr.status === 404) {
+ assert_true(xhr.response === expected_response,
+ "[" + xhr.status + " error, response:[" + xhr.response + "] " + "]");
+ xhrTest.done();
+ }
+ if (xhr.readyState === 4 && xhr.status === 200) {
+ assert_true(false, "[404 error expected, got: 200 OK instead]");
+ }
+ });
+ xhr.send();
+ });
+ delete xhrTest, xhr;
+ });
+ delete CompareResponseBodytests;
+
+
+
+ } else {
+ document.getElementById("logs").innerHTML =
+ "This is a test suite for app protocol only. Test aborted due to current protocol "
+ + window.location.protocol;
+ }
+
+ </script>
+ </body>
+</html>
+
+
+
diff --git a/tests/wpt/web-platform-tests/app-uri/resources/ExamPLE/mmY/index.html b/tests/wpt/web-platform-tests/app-uri/resources/ExamPLE/mmY/index.html
new file mode 100644
index 00000000000..7ef22e9a431
--- /dev/null
+++ b/tests/wpt/web-platform-tests/app-uri/resources/ExamPLE/mmY/index.html
@@ -0,0 +1 @@
+PASS
diff --git a/tests/wpt/web-platform-tests/app-uri/resources/ExamPLE/mmY/sth.txt b/tests/wpt/web-platform-tests/app-uri/resources/ExamPLE/mmY/sth.txt
new file mode 100644
index 00000000000..5e3cbc931a3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/app-uri/resources/ExamPLE/mmY/sth.txt
@@ -0,0 +1 @@
+This is simple text file
diff --git a/tests/wpt/web-platform-tests/app-uri/resources/ExamPLE/{mY}/z...z/index.html b/tests/wpt/web-platform-tests/app-uri/resources/ExamPLE/{mY}/z...z/index.html
new file mode 100644
index 00000000000..7ef22e9a431
--- /dev/null
+++ b/tests/wpt/web-platform-tests/app-uri/resources/ExamPLE/{mY}/z...z/index.html
@@ -0,0 +1 @@
+PASS
diff --git a/tests/wpt/web-platform-tests/app-uri/resources/ImaGes/{{a}}/Test_1/$a/sth34!.png b/tests/wpt/web-platform-tests/app-uri/resources/ImaGes/{{a}}/Test_1/$a/sth34!.png
new file mode 100644
index 00000000000..4a775ded297
--- /dev/null
+++ b/tests/wpt/web-platform-tests/app-uri/resources/ImaGes/{{a}}/Test_1/$a/sth34!.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/app-uri/resources/ImaGes/~t/{!a}/corrupted_file.png b/tests/wpt/web-platform-tests/app-uri/resources/ImaGes/~t/{!a}/corrupted_file.png
new file mode 100644
index 00000000000..d05eb6ea2b7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/app-uri/resources/ImaGes/~t/{!a}/corrupted_file.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/app-uri/resources/ImaGes/~t/{!a}/~sth.png b/tests/wpt/web-platform-tests/app-uri/resources/ImaGes/~t/{!a}/~sth.png
new file mode 100644
index 00000000000..4a775ded297
--- /dev/null
+++ b/tests/wpt/web-platform-tests/app-uri/resources/ImaGes/~t/{!a}/~sth.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/app-uri/resources/icons/w3c-128.png b/tests/wpt/web-platform-tests/app-uri/resources/icons/w3c-128.png
new file mode 100644
index 00000000000..c010156253d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/app-uri/resources/icons/w3c-128.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/app-uri/resources/icons/w3c-16.png b/tests/wpt/web-platform-tests/app-uri/resources/icons/w3c-16.png
new file mode 100644
index 00000000000..105194bbad5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/app-uri/resources/icons/w3c-16.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/app-uri/resources/icons/w3c-48.png b/tests/wpt/web-platform-tests/app-uri/resources/icons/w3c-48.png
new file mode 100644
index 00000000000..a19c55d6777
--- /dev/null
+++ b/tests/wpt/web-platform-tests/app-uri/resources/icons/w3c-48.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/battery-status/battery-charging-manual.html b/tests/wpt/web-platform-tests/battery-status/battery-charging-manual.html
new file mode 100644
index 00000000000..3eafcaca4d9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/battery-status/battery-charging-manual.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Battery Test: battery neither empty or full, charger plugged in</title>
+<meta name="flags" content="interact">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<h2>Description</h2>
+<p>
+ This test validates that all of the BatteryManager attributes exist and are set to their correct values when battery is charging.
+</p>
+
+<h2>Preconditions</h2>
+<ol>
+ <li>
+ The device is plugged in to the charger before this test is run.
+ </li>
+ <li>
+ The battery must neither be empty or full, nor reach empty or full capacity during the test.
+ </li>
+ <li>
+ Waiting for battery level change to fire levelchange event, maybe need a long time
+ </li>
+</ol>
+
+<script>
+
+setup({ explicit_timeout: true });
+
+async_test(function (t) {
+ navigator.getBattery().then(function (battery) {
+ t.step(function () {
+ assert_true(battery.charging, 'charging must be set to true');
+ assert_less_than(battery.chargingTime, Infinity, 'chargingTime must be less than Infinity');
+ assert_equals(battery.dischargingTime, Infinity, 'dischargingTime must be set to Infinity');
+ assert_greater_than(battery.level, 0, 'level must be greater than 0');
+ assert_less_than(battery.level, 1.0, 'level must be less than 1.0');
+
+ var battery_level = battery.level;
+ battery.onlevelchange = t.step_func(function () {
+ assert_greater_than(battery.level, battery_level, 'The value of the level attribute must increase');
+ t.done();
+ });
+ });
+ }, function (error) {
+ t.step(function () {
+ assert_unreached(error.message);
+ });
+ t.done();
+ });
+}, document.title);
+
+</script>
diff --git a/tests/wpt/web-platform-tests/battery-status/battery-created-manual.html b/tests/wpt/web-platform-tests/battery-status/battery-created-manual.html
new file mode 100644
index 00000000000..e3b8d69cf4d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/battery-status/battery-created-manual.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Battery Test: no backend implementation, charger unplugged in</title>
+<meta name="flags" content="interact">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<h2>Description</h2>
+<p>
+ <strong>
+ This test is only useful on devices that expose the BatteryManager interface,
+ but lack a backend implementation.
+ </strong>
+</p>
+<p>
+ This test validates that all of the BatteryManager attributes exist and are set to their default values.
+</p>
+
+<h2>Preconditions</h2>
+<ol>
+ <li>
+ The implementation is unable to report the battery's charging state,
+ charging time, level or remaining time respectively.
+ </li>
+ <li>
+ The device is unplugged from the charger before this test case is run.
+ </li>
+</ol>
+
+<div id="log"></div>
+
+<script>
+
+async_test(function (t) {
+ navigator.getBattery().then(function (battery) {
+ t.step(function () {
+ assert_true(battery.charging, 'charging must be set to true');
+ assert_equals(battery.chargingTime, 0, 'chargingTime must be set to 0');
+ assert_equals(battery.dischargingTime, Infinity, 'dischargingTime must be set to Infinity');
+ assert_equals(battery.level, 1.0, 'level must be set to 1.0');
+ });
+ t.done();
+ }, function (error) {
+ t.step(function () {
+ assert_unreached(error.message);
+ });
+ t.done();
+ });
+}, 'When a BatteryManager object is created, charging must be set to true, ' +
+ 'chargingTime to 0, level to 1.0 and dischargingTime to the value positive ' +
+ 'Infinity, if the implementation is unable to report the battery\'s charging ' +
+ 'state, charging time, level or remaining time respectively.');
+
+</script>
diff --git a/tests/wpt/web-platform-tests/battery-status/battery-discharging-manual.html b/tests/wpt/web-platform-tests/battery-status/battery-discharging-manual.html
new file mode 100644
index 00000000000..f335f42326d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/battery-status/battery-discharging-manual.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Battery Test: battery neither empty or full, charger unplugged in</title>
+<meta name="flags" content="interact">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<h2>Description</h2>
+<p>
+ This test validates that all of the BatteryManager attributes exist and are set to their correct values when battery is discharging.
+</p>
+
+<h2>Preconditions</h2>
+<ol>
+ <li>
+ The device is unplugged from the charger before this test is run.
+ </li>
+ <li>
+ The battery must neither be empty or full, nor reach empty or full capacity during the test.
+ </li>
+ <li>
+ Waiting for battery level change to fire levelchange event, maybe need a long time
+ </li>
+</ol>
+
+<script>
+
+setup({ explicit_timeout: true });
+
+async_test(function (t) {
+ navigator.getBattery().then(function (battery) {
+ t.step(function () {
+ assert_false(battery.charging, 'charging must be set to false');
+ assert_equals(battery.chargingTime, Infinity, 'chargingTime must be set to Infinity');
+ assert_less_than(battery.dischargingTime, Infinity, 'dischargingTime must be less than Infinity');
+ assert_greater_than(battery.level, 0, 'level must be greater than 0');
+ assert_less_than(battery.level, 1.0, 'level must be less than 1.0');
+
+ var battery_level = battery.level;
+ battery.onlevelchange = t.step_func(function () {
+ assert_less_than(battery.level, battery_level, 'The value of the level attribute must decrease');
+ t.done();
+ });
+ });
+ }, function (error) {
+ t.step(function () {
+ assert_unreached(error.message);
+ });
+ t.done();
+ });
+}, document.title);
+
+</script>
diff --git a/tests/wpt/web-platform-tests/battery-status/battery-full-manual.html b/tests/wpt/web-platform-tests/battery-status/battery-full-manual.html
new file mode 100644
index 00000000000..883d71f408d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/battery-status/battery-full-manual.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Battery Test: battery full, charger plugged in</title>
+<meta name="flags" content="interact">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<h2>Description</h2>
+<p>
+ This test validates that all of the BatteryManager attributes exist and are set to their correct values when battery is full.
+</p>
+
+<h2>Preconditions</h2>
+<ol>
+ <li>
+ The device is plugged in to the charger before this test is run.
+ </li>
+ <li>
+ The battery is full.
+ </li>
+</ol>
+
+<script>
+
+async_test(function (t) {
+ navigator.getBattery().then(function (battery) {
+ t.step(function () {
+ assert_true(battery.charging, 'charging must be set to true');
+ assert_equals(battery.chargingTime, 0, 'chargingTime must be set to 0');
+ assert_equals(battery.dischargingTime, Infinity, 'dischargingTime must be set to Infinity');
+ assert_equals(battery.level, 1.0, 'level must be set to 1.0');
+ });
+ t.done();
+ }, function (error) {
+ t.step(function () {
+ assert_unreached(error.message);
+ });
+ t.done();
+ });
+}, document.title);
+
+</script>
diff --git a/tests/wpt/web-platform-tests/battery-status/battery-interface-idlharness.html b/tests/wpt/web-platform-tests/battery-status/battery-interface-idlharness.html
new file mode 100644
index 00000000000..574d99ec7c8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/battery-status/battery-interface-idlharness.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Battery test: IDL</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/WebIDLParser.js"></script>
+<script src="/resources/idlharness.js"></script>
+<script type="text/plain" class="untested">
+interface Navigator { };
+
+interface EventTarget {
+ void addEventListener(DOMString type, EventListener? callback, optional boolean capture);
+ void removeEventListener(DOMString type, EventListener? callback, optional boolean capture);
+ boolean dispatchEvent(Event event);
+};
+
+[Callback]
+interface EventListener {
+ void handleEvent(Event event);
+};
+</script>
+<script type="text/plain">
+partial interface Navigator {
+ Promise<BatteryManager> getBattery ();
+};
+
+interface BatteryManager : EventTarget {
+ readonly attribute boolean charging;
+ readonly attribute unrestricted double chargingTime;
+ readonly attribute unrestricted double dischargingTime;
+ readonly attribute double level;
+ attribute EventHandler onchargingchange;
+ attribute EventHandler onchargingtimechange;
+ attribute EventHandler ondischargingtimechange;
+ attribute EventHandler onlevelchange;
+};
+</script>
+<script>
+"use strict";
+var idl_array = new IdlArray();
+var idls;
+[].forEach.call(document.querySelectorAll('script[type=text\\/plain]'), function(node) {
+ // replace 'EventHandler' and 'unrestricted double' unrecognized by idlharness.js
+ idls = node.textContent.replace(/EventHandler/g, 'Function?').replace(/unrestricted double/g, 'double');
+ idl_array[(node.className === 'untested') ? 'add_untested_idls' : 'add_idls'](idls);
+});
+idl_array.add_objects({Navigator: ['navigator'], BatteryManager: ['navigator.getBattery()']});
+idl_array.test();
+</script>
+
+<h2>Description</h2>
+<p>
+ This test validates the BatteryManager interface IDL.
+</p>
+<p>
+ This test uses <a href="/resources/idlharness.js">idlharness.js</a>, and
+ is complementary to the <a href="battery-interface.html">battery-interface.html</a>
+ test.
+</p>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/battery-status/battery-interface.html b/tests/wpt/web-platform-tests/battery-status/battery-interface.html
new file mode 100644
index 00000000000..aec10ae9a09
--- /dev/null
+++ b/tests/wpt/web-platform-tests/battery-status/battery-interface.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Battery Test: Interface API</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="battery-interface.js"></script>
+
+<h2>Description</h2>
+<p>
+ This test validates the BatteryManager interface IDL.
+</p>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/battery-status/battery-interface.js b/tests/wpt/web-platform-tests/battery-status/battery-interface.js
new file mode 100644
index 00000000000..7542dc965fb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/battery-status/battery-interface.js
@@ -0,0 +1,368 @@
+(function() {
+
+ setup("", {explicit_done: true});
+
+ /**
+ *
+ * partial interface Navigator {
+ * Promise<BatteryManager> getBattery ();
+ * };
+ *
+ */
+
+ test(function() {
+ assert_idl_attribute(navigator, 'getBattery', 'navigator must have getBattery attribute');
+ }, 'getBattery is present on navigator');
+
+ navigator.getBattery().then(function (battery) {
+
+ /**
+ *
+ * interface BatteryManager : EventTarget {
+ * readonly attribute boolean charging;
+ * readonly attribute unrestricted double chargingTime;
+ * readonly attribute unrestricted double dischargingTime;
+ * readonly attribute double level;
+ * attribute EventHandler onchargingchange;
+ * attribute EventHandler onchargingtimechange;
+ * attribute EventHandler ondischargingtimechange;
+ * attribute EventHandler onlevelchange;
+ * };
+ *
+ */
+
+ // interface BatteryManager : EventTarget {
+
+ test(function() {
+ assert_own_property(window, 'BatteryManager');
+ }, 'window has an own property BatteryManager');
+
+ test(function() {
+ assert_true(battery instanceof EventTarget);
+ }, 'battery inherits from EventTarget');
+
+ // readonly attribute boolean charging;
+
+ test(function() {
+ assert_idl_attribute(battery, 'charging', 'battery must have charging attribute');
+ }, 'charging attribute exists');
+
+ test(function() {
+ assert_readonly(battery, 'charging', 'charging must be readonly')
+ }, 'charging attribute is readonly');
+
+ // readonly attribute unrestricted double chargingTime;
+
+ test(function() {
+ assert_idl_attribute(battery, 'chargingTime', 'battery must have chargingTime attribute');
+ }, 'chargingTime attribute exists');
+
+ test(function() {
+ assert_readonly(battery, 'chargingTime', 'chargingTime must be readonly')
+ }, 'chargingTime attribute is readonly');
+
+ // readonly attribute unrestricted double dischargingTime;
+
+ test(function() {
+ assert_idl_attribute(battery, 'dischargingTime', 'battery must have dischargingTime attribute');
+ }, 'dischargingTime attribute exists');
+
+ test(function() {
+ assert_readonly(battery, 'dischargingTime', 'dischargingTime must be readonly')
+ }, 'dischargingTime attribute is readonly');
+
+ // readonly attribute double level;
+
+ test(function() {
+ assert_idl_attribute(battery, 'level', 'battery must have level attribute');
+ }, 'level attribute exists');
+
+ test(function() {
+ assert_readonly(battery, 'level', 'level must be readonly')
+ }, 'level attribute is readonly');
+
+ // attribute EventHandler onchargingchange;
+
+ test(function() {
+ assert_idl_attribute(battery, 'onchargingchange', 'battery must have onchargingchange attribute');
+ }, 'onchargingchange attribute exists');
+
+ test(function() {
+ assert_equals(battery.onchargingchange, null, 'onchargingchange must be null')
+ }, 'onchargingchange is null');
+
+ test(function() {
+ var desc = 'onchargingchange did not accept callable object',
+ func = function() {},
+ desc = 'Expected to find onchargingchange attribute on battery object';
+ assert_idl_attribute(battery, 'onchargingchange', desc);
+ window.onchargingchange = func;
+ assert_equals(window.onchargingchange, func, desc);
+ }, 'onchargingchange is set to function');
+
+ test(function() {
+ var desc = 'onchargingchange did not treat noncallable as null';
+ battery.onchargingchange = function() {};
+ battery.onchargingchange = {};
+ assert_equals(battery.onchargingchange, null, desc);
+ }, 'onchargingchange: treat object as null');
+
+ test(function() {
+ var desc = 'onchargingchange did not treat noncallable as null';
+ battery.onchargingchange = function() {};
+ battery.onchargingchange = {
+ call: 'test'
+ };
+ assert_equals(battery.onchargingchange, null, desc);
+ }, 'onchargingchange: treat object with non-callable call property as null');
+
+ test(function() {
+ var desc = 'onchargingchange did not treat noncallable (string) as null';
+ battery.onchargingchange = function() {};
+ battery.onchargingchange = 'string';
+ assert_equals(battery.onchargingchange, null, desc);
+ }, 'onchargingchange: treat string as null');
+
+ test(function() {
+ var desc = 'onchargingchange did not treat noncallable (number) as null';
+ battery.onchargingchange = function() {};
+ battery.onchargingchange = 123;
+ assert_equals(battery.onchargingchange, null, desc);
+ }, 'onchargingchange: treat number as null');
+
+ test(function() {
+ var desc = 'onchargingchange did not treat noncallable (undefined) as null';
+ battery.onchargingchange = function() {};
+ battery.onchargingchange = undefined;
+ assert_equals(battery.onchargingchange, null, desc);
+ }, 'onchargingchange: treat undefined as null');
+
+ test(function() {
+ var desc = 'onchargingchange did not treat noncallable (array) as null';
+ battery.onchargingchange = function() {};
+ battery.onchargingchange = [];
+ assert_equals(battery.onchargingchange, null, desc);
+ }, 'onchargingchange: treat array as null');
+
+ test(function() {
+ var desc = 'onchargingchange did not treat noncallable host object as null';
+ battery.onchargingchange = function() {};
+ battery.onchargingchange = Node;
+ assert_equals(battery.onchargingchange, null, desc);
+ }, 'onchargingchange: treat non-callable host object as null');
+
+ // attribute EventHandler onchargingtimechange;
+
+ test(function() {
+ assert_idl_attribute(battery, 'onchargingtimechange', 'battery must have onchargingtimechange attribute');
+ }, 'onchargingtimechange attribute exists');
+
+ test(function() {
+ assert_equals(battery.onchargingtimechange, null, 'onchargingtimechange must be null')
+ }, 'onchargingtimechange is null');
+
+ test(function() {
+ var desc = 'onchargingtimechange did not accept callable object',
+ func = function() {},
+ desc = 'Expected to find onchargingtimechange attribute on battery object';
+ assert_idl_attribute(battery, 'onchargingtimechange', desc);
+ window.onchargingtimechange = func;
+ assert_equals(window.onchargingtimechange, func, desc);
+ }, 'onchargingtimechange is set to function');
+
+ test(function() {
+ var desc = 'onchargingtimechange did not treat noncallable as null';
+ battery.onchargingtimechange = function() {};
+ battery.onchargingtimechange = {};
+ assert_equals(battery.onchargingtimechange, null, desc);
+ }, 'onchargingtimechange: treat object as null');
+
+ test(function() {
+ var desc = 'onchargingtimechange did not treat noncallable as null';
+ battery.onchargingtimechange = function() {};
+ battery.onchargingtimechange = {
+ call: 'test'
+ };
+ assert_equals(battery.onchargingtimechange, null, desc);
+ }, 'onchargingtimechange: treat object with non-callable call property as null');
+
+ test(function() {
+ var desc = 'onchargingtimechange did not treat noncallable (string) as null';
+ battery.onchargingtimechange = function() {};
+ battery.onchargingtimechange = 'string';
+ assert_equals(battery.onchargingtimechange, null, desc);
+ }, 'onchargingtimechange: treat string as null');
+
+ test(function() {
+ var desc = 'onchargingtimechange did not treat noncallable (number) as null';
+ battery.onchargingtimechange = function() {};
+ battery.onchargingtimechange = 123;
+ assert_equals(battery.onchargingtimechange, null, desc);
+ }, 'onchargingtimechange: treat number as null');
+
+ test(function() {
+ var desc = 'onchargingtimechange did not treat noncallable (undefined) as null';
+ battery.onchargingtimechange = function() {};
+ battery.onchargingtimechange = undefined;
+ assert_equals(battery.onchargingtimechange, null, desc);
+ }, 'onchargingtimechange: treat undefined as null');
+
+ test(function() {
+ var desc = 'onchargingtimechange did not treat noncallable (array) as null';
+ battery.onchargingtimechange = function() {};
+ battery.onchargingtimechange = [];
+ assert_equals(battery.onchargingtimechange, null, desc);
+ }, 'onchargingtimechange: treat array as null');
+
+ test(function() {
+ var desc = 'onchargingtimechange did not treat noncallable host object as null';
+ battery.onchargingtimechange = function() {};
+ battery.onchargingtimechange = Node;
+ assert_equals(battery.onchargingtimechange, null, desc);
+ }, 'onchargingtimechange: treat non-callable host object as null');
+
+ // attribute EventHandler ondischargingtimechange;
+
+ test(function() {
+ assert_idl_attribute(battery, 'ondischargingtimechange', 'battery must have ondischargingtimechange attribute');
+ }, 'ondischargingtimechange attribute exists');
+
+ test(function() {
+ assert_equals(battery.ondischargingtimechange, null, 'ondischargingtimechange must be null')
+ }, 'ondischargingtimechange is null');
+
+ test(function() {
+ var desc = 'ondischargingtimechange did not accept callable object',
+ func = function() {},
+ desc = 'Expected to find ondischargingtimechange attribute on battery object';
+ assert_idl_attribute(battery, 'ondischargingtimechange', desc);
+ window.ondischargingtimechange = func;
+ assert_equals(window.ondischargingtimechange, func, desc);
+ }, 'ondischargingtimechange is set to function');
+
+ test(function() {
+ var desc = 'ondischargingtimechange did not treat noncallable as null';
+ battery.ondischargingtimechange = function() {};
+ battery.ondischargingtimechange = {};
+ assert_equals(battery.ondischargingtimechange, null, desc);
+ }, 'ondischargingtimechange: treat object as null');
+
+ test(function() {
+ var desc = 'ondischargingtimechange did not treat noncallable as null';
+ battery.ondischargingtimechange = function() {};
+ battery.ondischargingtimechange = {
+ call: 'test'
+ };
+ assert_equals(battery.ondischargingtimechange, null, desc);
+ }, 'ondischargingtimechange: treat object with non-callable call property as null');
+
+ test(function() {
+ var desc = 'ondischargingtimechange did not treat noncallable (string) as null';
+ battery.ondischargingtimechange = function() {};
+ battery.ondischargingtimechange = 'string';
+ assert_equals(battery.ondischargingtimechange, null, desc);
+ }, 'ondischargingtimechange: treat string as null');
+
+ test(function() {
+ var desc = 'ondischargingtimechange did not treat noncallable (number) as null';
+ battery.ondischargingtimechange = function() {};
+ battery.ondischargingtimechange = 123;
+ assert_equals(battery.ondischargingtimechange, null, desc);
+ }, 'ondischargingtimechange: treat number as null');
+
+ test(function() {
+ var desc = 'ondischargingtimechange did not treat noncallable (undefined) as null';
+ battery.ondischargingtimechange = function() {};
+ battery.ondischargingtimechange = undefined;
+ assert_equals(battery.ondischargingtimechange, null, desc);
+ }, 'ondischargingtimechange: treat undefined as null');
+
+ test(function() {
+ var desc = 'ondischargingtimechange did not treat noncallable (array) as null';
+ battery.ondischargingtimechange = function() {};
+ battery.ondischargingtimechange = [];
+ assert_equals(battery.ondischargingtimechange, null, desc);
+ }, 'ondischargingtimechange: treat array as null');
+
+ test(function() {
+ var desc = 'ondischargingtimechange did not treat noncallable host object as null';
+ battery.ondischargingtimechange = function() {};
+ battery.ondischargingtimechange = Node;
+ assert_equals(battery.ondischargingtimechange, null, desc);
+ }, 'ondischargingtimechange: treat non-callable host object as null');
+
+ // attribute EventHandler onlevelchange;
+
+ test(function() {
+ assert_idl_attribute(battery, 'onlevelchange', 'battery must have onlevelchange attribute');
+ }, 'onlevelchange attribute exists');
+
+ test(function() {
+ assert_equals(battery.onlevelchange, null, 'onlevelchange must be null')
+ }, 'onlevelchange is null');
+
+ test(function() {
+ var desc = 'onlevelchange did not accept callable object',
+ func = function() {},
+ desc = 'Expected to find onlevelchange attribute on battery object';
+ assert_idl_attribute(battery, 'onlevelchange', desc);
+ window.onlevelchange = func;
+ assert_equals(window.onlevelchange, func, desc);
+ }, 'onlevelchange is set to function');
+
+ test(function() {
+ var desc = 'onlevelchange did not treat noncallable as null';
+ battery.onlevelchange = function() {};
+ battery.onlevelchange = {};
+ assert_equals(battery.onlevelchange, null, desc);
+ }, 'onlevelchange: treat object as null');
+
+ test(function() {
+ var desc = 'onlevelchange did not treat noncallable as null';
+ battery.onlevelchange = function() {};
+ battery.onlevelchange = {
+ call: 'test'
+ };
+ assert_equals(battery.onlevelchange, null, desc);
+ }, 'onlevelchange: treat object with non-callable call property as null');
+
+ test(function() {
+ var desc = 'onlevelchange did not treat noncallable (string) as null';
+ battery.onlevelchange = function() {};
+ battery.onlevelchange = 'string';
+ assert_equals(battery.onlevelchange, null, desc);
+ }, 'onlevelchange: treat string as null');
+
+ test(function() {
+ var desc = 'onlevelchange did not treat noncallable (number) as null';
+ battery.onlevelchange = function() {};
+ battery.onlevelchange = 123;
+ assert_equals(battery.onlevelchange, null, desc);
+ }, 'onlevelchange: treat number as null');
+
+ test(function() {
+ var desc = 'onlevelchange did not treat noncallable (undefined) as null';
+ battery.onlevelchange = function() {};
+ battery.onlevelchange = undefined;
+ assert_equals(battery.onlevelchange, null, desc);
+ }, 'onlevelchange: treat undefined as null');
+
+ test(function() {
+ var desc = 'onlevelchange did not treat noncallable (array) as null';
+ battery.onlevelchange = function() {};
+ battery.onlevelchange = [];
+ assert_equals(battery.onlevelchange, null, desc);
+ }, 'onlevelchange: treat array as null');
+
+ test(function() {
+ var desc = 'onlevelchange did not treat noncallable host object as null';
+ battery.onlevelchange = function() {};
+ battery.onlevelchange = Node;
+ assert_equals(battery.onlevelchange, null, desc);
+ }, 'onlevelchange: treat non-callable host object as null');
+
+ done();
+
+ }, function () {});
+
+})();
diff --git a/tests/wpt/web-platform-tests/battery-status/battery-plugging-in-manual.html b/tests/wpt/web-platform-tests/battery-status/battery-plugging-in-manual.html
new file mode 100644
index 00000000000..8b96217880c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/battery-status/battery-plugging-in-manual.html
@@ -0,0 +1,99 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Battery Test: battery not full, charger plugging in</title>
+<meta name="flags" content="interact">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+ #note {
+ background-color: #fef1b5;
+ border: solid 1px #cdab2d;
+ padding: 5px;
+ margin: 15px;
+ display: block;
+ }
+</style>
+
+<h2>Description</h2>
+<p>
+ This test validates that all of the BatteryManager attributes exist and are set to correct values, with corresponding events fired, when the charger is plugged in.
+</p>
+
+<h2>Preconditions</h2>
+<ol>
+ <li>
+ The device is unplugged from the charger before this test is run.
+ </li>
+ <li>
+ The battery must not be full or reach full capacity during the time the test is run.
+ </li>
+</ol>
+
+<div id="note">
+ Plug in the charger and wait for all the tests to complete.
+</div>
+
+<div id="log"></div>
+
+<script>
+
+(function() {
+
+ setup({ explicit_timeout: true });
+
+ var onchargingchange_test = async_test('When the device is plugged in and its charging state is updated, must set the charging attribute\'s value to true and fire a chargingchange event.');
+ var onchargingtimechange_test = async_test('When the device is plugged in and its charging time is updated, must set the chargingTime attribute\'s value and fire a chargingtimechange event.');
+ var ondischargingtimechange_test = async_test('When the device is plugged in and its discharging time is updated, must set the dischargingTime attribute\'s value to Infinity and fire a dischargingtimechange event.');
+ var onlevelchange_test = async_test('When the device is plugged in and the battery level is updated, must set the level attribute\'s value and fire a levelchange event.');
+
+ var batterySuccess = function (battery) {
+ battery.onchargingchange = onchargingchange_test.step_func(function () {
+ assert_true(battery.charging, 'The charging attribute must be set to true.');
+ onchargingchange_test.done();
+ });
+
+ var battery_chargingtime = battery.chargingTime;
+ battery.onchargingtimechange = onchargingtimechange_test.step_func(function () {
+ assert_less_than(battery.chargingTime, battery_chargingtime, 'The value of the chargingTime attribute must decrease.');
+ onchargingtimechange_test.done();
+ });
+
+ battery.ondischargingtimechange = ondischargingtimechange_test.step_func(function () {
+ assert_equals(battery.dischargingTime, Infinity, 'The value of the dischargingTime attribute must be set to Infinity.');
+ ondischargingtimechange_test.done();
+ });
+
+ battery.onlevelchange = onlevelchange_test.step_func(function () {
+ assert_greater_than(battery.level, 0);
+ assert_less_than(battery.level, 1.0);
+ onlevelchange_test.done();
+ });
+ };
+
+ var batteryFailure = function (error) {
+ onchargingchange_test.step(function () {
+ assert_unreached(error.message);
+ });
+ onchargingchange_test.done();
+
+ onchargingtimechange_test.step(function () {
+ assert_unreached(error.message);
+ });
+ onchargingtimechange_test.done();
+
+ ondischargingtimechange_test.step(function () {
+ assert_unreached(error.message);
+ });
+ ondischargingtimechange_test.done();
+
+ onlevelchange_test.step(function () {
+ assert_unreached(error.message);
+ });
+ onlevelchange_test.done();
+ };
+
+ navigator.getBattery().then(batterySuccess, batteryFailure);
+
+})();
+
+</script>
diff --git a/tests/wpt/web-platform-tests/battery-status/battery-promise.html b/tests/wpt/web-platform-tests/battery-status/battery-promise.html
new file mode 100644
index 00000000000..2e2910cda60
--- /dev/null
+++ b/tests/wpt/web-platform-tests/battery-status/battery-promise.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Battery Test: navigator.getBattery() returns BatteryManager as a promise</title>
+<link rel="author" title="YuichiNukiyama" href="https://github.com/YuichiNukiyama">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<script>
+ function returnBattery() {
+ return navigator.getBattery();
+ }
+
+ promise_test(function () {
+ return returnBattery()
+ .then(function (result) {
+ assert_class_string(result, "BatteryManager", "getBattery should return BatteryManager Object.");
+ });
+ }, "navigator.getBattery() return BatteryManager");
+
+ test(function () {
+ assert_equals(navigator.getBattery(), navigator.getBattery());
+ }, "navigator.getBattery() shall always return the same promise");
+</script>
+
+<div id="log"></div>
+
diff --git a/tests/wpt/web-platform-tests/battery-status/battery-unplugging-manual.html b/tests/wpt/web-platform-tests/battery-status/battery-unplugging-manual.html
new file mode 100644
index 00000000000..1a6b5b8982e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/battery-status/battery-unplugging-manual.html
@@ -0,0 +1,113 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Battery Test: battery not full, charger unplugging</title>
+<meta name="flags" content="interact">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+ #note {
+ background-color: #fef1b5;
+ border: solid 1px #cdab2d;
+ padding: 5px;
+ margin: 15px;
+ display: block;
+ }
+</style>
+
+<h2>Description</h2>
+<p>
+ This test validates that all of the BatteryManager attributes exist and are set to correct values, with corresponding events fired, when the charger is unplugged.
+</p>
+
+<h2>Preconditions</h2>
+<ol>
+ <li>
+ The device is plugged in to the charger before this test is run.
+ </li>
+ <li>
+ The battery must not be full or reach full capacity during the time the test is run.
+ </li>
+</ol>
+<p>
+ The highest prime number discovered so far is: <output id="prime"></output>
+</p>
+
+<div id="note">
+ Unplug the charger and wait for all the tests to complete.
+</div>
+
+<div id="log"></div>
+
+<script>
+
+(function() {
+
+ setup({ explicit_timeout: true });
+
+ var onchargingchange_test = async_test('When the device is unplugged in and its charging state is updated, must set the charging attribute\'s value to false and fire a chargingchange event.');
+ var onchargingtimechange_test = async_test('When the device is unplugged in and its charging time is updated, must set the chargingTime attribute\'s value to Infinity and fire a chargingtimechange event.');
+ var ondischargingtimechange_test = async_test('When the device is unplugged in and its discharging time is updated, must set the dischargingTime attribute\'s value and fire a dischargingtimechange event.');
+ var onlevelchange_test = async_test('When the device is plugged in and the battery level is updated, must set the level attribute\'s value and fire a levelchange event.');
+
+ var batterySuccess = function (battery) {
+ battery.onchargingchange = onchargingchange_test.step_func(function () {
+ assert_false(battery.charging, 'The charging attribute must be set to false.');
+ onchargingchange_test.done();
+ });
+
+ battery.onchargingtimechange = onchargingtimechange_test.step_func(function () {
+ assert_equals(battery.chargingTime, Infinity, 'The value of the chargingTime attribute must be set to Infinity.');
+ onchargingtimechange_test.done();
+ });
+
+ battery.ondischargingtimechange = ondischargingtimechange_test.step_func(function () {
+ assert_less_than(battery.dischargingTime, Infinity, 'The value of the dischargingTime attribute must be set to the remaining discharging time.');
+ ondischargingtimechange_test.done();
+ });
+
+ battery.onlevelchange = onlevelchange_test.step_func(function () {
+ assert_greater_than(battery.level, 0);
+ assert_less_than(battery.level, 1.0);
+ onlevelchange_test.done();
+ w.terminate();
+ });
+ };
+
+ var batteryFailure = function (error) {
+ onchargingchange_test.step(function () {
+ assert_unreached(error.message);
+ });
+ onchargingchange_test.done();
+
+ onchargingtimechange_test.step(function () {
+ assert_unreached(error.message);
+ });
+ onchargingtimechange_test.done();
+
+ ondischargingtimechange_test.step(function () {
+ assert_unreached(error.message);
+ });
+ ondischargingtimechange_test.done();
+
+ onlevelchange_test.step(function () {
+ assert_unreached(error.message);
+ });
+ onlevelchange_test.done();
+ };
+
+ // compute primes to deplete the battery faster
+ var w = new Worker('prime.js');
+ w.postMessage('compute');
+ w.onmessage = function (e) {
+ document.querySelector('#prime').textContent = e.data;
+ };
+
+ add_completion_callback(function () {
+ w.terminate();
+ });
+
+ navigator.getBattery().then(batterySuccess, batteryFailure);
+
+})();
+
+</script>
diff --git a/tests/wpt/web-platform-tests/battery-status/prime.js b/tests/wpt/web-platform-tests/battery-status/prime.js
new file mode 100644
index 00000000000..d53208093bb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/battery-status/prime.js
@@ -0,0 +1,35 @@
+// adapted from http://html5demos.com/worker
+
+var running = false;
+
+onmessage = function (event) {
+ // doesn't matter what the message is, just toggle the worker
+ if (running == false) {
+ running = true;
+ run(1);
+ } else {
+ running = false;
+ }
+};
+
+function run(n) {
+ // split the task into 20k chunks
+ var limit = n + 20000;
+ search: while (running && n < limit) {
+ n += 1;
+ for (var i = 2; i <= Math.sqrt(n); i += 1) {
+ if (n % i == 0) {
+ continue search;
+ }
+ }
+ // found a prime!
+ postMessage(n);
+ }
+ if (n === limit) {
+ // wait for the UI thread to update itself
+ setTimeout(function(start_time) {
+ // resume prime computation at n
+ run(n);
+ }, 150);
+ }
+} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/common/blank.html b/tests/wpt/web-platform-tests/common/blank.html
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/common/blank.html
diff --git a/tests/wpt/web-platform-tests/common/canvas-frame.css b/tests/wpt/web-platform-tests/common/canvas-frame.css
new file mode 100644
index 00000000000..0c97a680d18
--- /dev/null
+++ b/tests/wpt/web-platform-tests/common/canvas-frame.css
@@ -0,0 +1,21 @@
+body {
+ font-size: small;
+ font-family: sans-serif;
+}
+
+p {
+ line-height: 0;
+}
+
+p:first-child {
+ display: inline;
+}
+
+h1 {
+ display: inline;
+}
+
+iframe, object {
+ border: 1px black solid;
+ margin: 2px;
+}
diff --git a/tests/wpt/web-platform-tests/common/canvas-index.css b/tests/wpt/web-platform-tests/common/canvas-index.css
new file mode 100644
index 00000000000..ef35864bc03
--- /dev/null
+++ b/tests/wpt/web-platform-tests/common/canvas-index.css
@@ -0,0 +1,31 @@
+body {
+ font-size: small;
+ font-family: sans-serif;
+}
+
+a {
+ text-decoration: none;
+}
+
+a:hover {
+ text-decoration: underline;
+}
+
+h3 {
+ display: inline;
+ font-size: medium;
+}
+
+h3 + p {
+ display: inline;
+ margin-left: 0.5em;
+}
+
+li {
+ list-style-type: none;
+}
+
+ul {
+ padding-left: 2em;
+ margin-left: 0;
+}
diff --git a/tests/wpt/web-platform-tests/common/canvas-spec.css b/tests/wpt/web-platform-tests/common/canvas-spec.css
new file mode 100644
index 00000000000..5882acb68ef
--- /dev/null
+++ b/tests/wpt/web-platform-tests/common/canvas-spec.css
@@ -0,0 +1,50 @@
+.testrefs {
+ font-size: small;
+ margin-left: 0.2em;
+ margin-right: 0.2em;
+ border-bottom: none !important;
+
+ font-weight: normal;
+ font-style: normal;
+ white-space: normal;
+ font-family: sans-serif;
+}
+
+.kw-must, .kw-required {
+ background: #fda;
+}
+
+.kw-should {
+ background: #ffa;
+}
+
+.kw-none {
+ background: #dfa;
+}
+
+
+pre.idl .testrefs :link {
+ color: #00c;
+}
+
+pre.idl .testrefs :visited {
+ color: #609;
+}
+
+.testrefs a:hover {
+ background: transparent;
+ text-decoration: none;
+}
+
+.testrefs:before {
+ content: '[';
+}
+
+.testrefs:after {
+ content: ']';
+}
+
+.testrefs a:first-child {
+ font-weight: bold;
+ text-decoration: none;
+}
diff --git a/tests/wpt/web-platform-tests/common/canvas-tests.css b/tests/wpt/web-platform-tests/common/canvas-tests.css
new file mode 100644
index 00000000000..e006e812de4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/common/canvas-tests.css
@@ -0,0 +1,134 @@
+html.fail {
+ background: #f66;
+}
+html.pass {
+ background: #6f6;
+}
+html.needs_check {
+ background: #99f;
+}
+
+body {
+ font-size: small;
+ font-family: sans-serif;
+ color: black;
+}
+
+a:link {
+ color: #00c;
+}
+a:visited {
+ color: #808;
+}
+
+body.framed {
+ font-size: x-small;
+}
+
+h1 {
+ font-size: larger;
+ margin: 0;
+ padding-left: 0.5em;
+ text-indent: -0.5em;
+}
+
+p {
+ margin: 0;
+}
+
+p.notes {
+ margin-bottom: 0.5em;
+ font-style: italic;
+}
+
+ul {
+ margin: 0;
+ margin-bottom: 0.5em;
+ padding: 0;
+ padding-left: 1em;
+}
+
+.refs {
+ font-style: italic;
+ margin-bottom: 0.5em;
+}
+
+.refs ul {
+ display: inline;
+ margin: 0;
+ padding: 0;
+}
+
+.refs li {
+ display: inline;
+ list-style-type: none;
+ margin: 0;
+ padding: 0;
+}
+
+canvas {
+ display: none;
+ visibility: hidden;
+ border: 2px #f0f solid;
+ background: url(../images/background.png);
+}
+
+img.expected {
+ display: none;
+ border: 2px #f0f solid;
+ background: url(../images/background.png);
+}
+
+iframe {
+ border: 2px #f0f solid;
+}
+
+.output {
+ display: none;
+}
+
+.show_output .output, .needs_check .output {
+ display: block !important;
+ visibility: visible !important;
+}
+
+.show_output #show_output {
+ display: none;
+}
+
+.resource {
+ visibility: hidden;
+ height: 0;
+}
+
+.fallback {
+ font-size: 2em;
+ font-weight: bold;
+ color: #a00;
+}
+
+
+html.minimal body {
+ color: white;
+}
+html.fail.minimal {
+ background: #f00;
+}
+html.pass.minimal {
+ background: #080;
+}
+html.needs_check.minimal {
+ background: #008;
+}
+.minimal #d {
+ display: none !important;
+}
+.minimal .expectedtext {
+ visibility: hidden !important;
+}
+#passtext, #failtext {
+ display: none;
+}
+.minimal.pass #passtext, .minimal.fail #failtext {
+ display: block;
+}
diff --git a/tests/wpt/web-platform-tests/common/canvas-tests.js b/tests/wpt/web-platform-tests/common/canvas-tests.js
new file mode 100644
index 00000000000..07b31703d08
--- /dev/null
+++ b/tests/wpt/web-platform-tests/common/canvas-tests.js
@@ -0,0 +1,86 @@
+function _valToString(val)
+{
+ if (val === undefined || val === null)
+ return '[' + typeof(val) + ']';
+ return val.toString() + '[' + typeof(val) + ']';
+}
+
+function _assert(cond, text)
+{
+ assert_true(!!cond, text);
+}
+
+function _assertSame(a, b, text_a, text_b)
+{
+ var msg = text_a + ' === ' + text_b + ' (got ' + _valToString(a) +
+ ', expected ' + _valToString(b) + ')';
+ assert_equals(a, b, msg);
+}
+
+function _assertDifferent(a, b, text_a, text_b)
+{
+ var msg = text_a + ' !== ' + text_b + ' (got ' + _valToString(a) +
+ ', expected not ' + _valToString(b) + ')';
+ assert_not_equals(a, b, msg);
+}
+
+
+function _getPixel(canvas, x,y)
+{
+ var ctx = canvas.getContext('2d');
+ var imgdata = ctx.getImageData(x, y, 1, 1);
+ return [ imgdata.data[0], imgdata.data[1], imgdata.data[2], imgdata.data[3] ];
+}
+
+function _assertPixel(canvas, x,y, r,g,b,a, pos, colour)
+{
+ var c = _getPixel(canvas, x,y);
+ assert_equals(c[0], r, 'Red channel of the pixel at (' + x + ', ' + y + ')');
+ assert_equals(c[1], g, 'Green channel of the pixel at (' + x + ', ' + y + ')');
+ assert_equals(c[2], b, 'Blue channel of the pixel at (' + x + ', ' + y + ')');
+ assert_equals(c[3], a, 'Alpha channel of the pixel at (' + x + ', ' + y + ')');
+}
+
+function _assertPixelApprox(canvas, x,y, r,g,b,a, pos, colour, tolerance)
+{
+ var c = _getPixel(canvas, x,y);
+ assert_approx_equals(c[0], r, tolerance, 'Red channel of the pixel at (' + x + ', ' + y + ')');
+ assert_approx_equals(c[1], g, tolerance, 'Green channel of the pixel at (' + x + ', ' + y + ')');
+ assert_approx_equals(c[2], b, tolerance, 'Blue channel of the pixel at (' + x + ', ' + y + ')');
+ assert_approx_equals(c[3], a, tolerance, 'Alpha channel of the pixel at (' + x + ', ' + y + ')');
+}
+
+function _addTest(testFn)
+{
+ var deferred = false;
+ window.deferTest = function () { deferred = true; };
+ on_event(window, "load", function()
+ {
+ t.step(function() {
+ var canvas = document.getElementById('c');
+ var ctx = canvas.getContext('2d');
+ t.step(testFn, window, canvas, ctx);
+ });
+
+ if (!deferred) {
+ t.done();
+ }
+ });
+}
+
+function _assertGreen(ctx, canvasWidth, canvasHeight)
+{
+ var testColor = function(d, idx, expected) {
+ assert_equals(d[idx], expected, "d[" + idx + "]", String(expected));
+ };
+ var imagedata = ctx.getImageData(0, 0, canvasWidth, canvasHeight);
+ var w = imagedata.width, h = imagedata.height, d = imagedata.data;
+ for (var i = 0; i < h; ++i) {
+ for (var j = 0; j < w; ++j) {
+ testColor(d, 4 * (w * i + j) + 0, 0);
+ testColor(d, 4 * (w * i + j) + 1, 255);
+ testColor(d, 4 * (w * i + j) + 2, 0);
+ testColor(d, 4 * (w * i + j) + 3, 255);
+ }
+ }
+}
diff --git a/tests/wpt/web-platform-tests/common/css-red.txt b/tests/wpt/web-platform-tests/common/css-red.txt
new file mode 100644
index 00000000000..9ef04cbd12d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/common/css-red.txt
@@ -0,0 +1 @@
+html { color: red; }
diff --git a/tests/wpt/web-platform-tests/common/large.py b/tests/wpt/web-platform-tests/common/large.py
new file mode 100644
index 00000000000..0db4e4bbd1c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/common/large.py
@@ -0,0 +1,45 @@
+def main(request, response):
+ """Code for generating large responses where the actual response data
+ isn't very important.
+
+ Two request parameters:
+ size (required): An integer number of bytes (no suffix) or kilobytes
+ ("kb" suffix) or megabytes ("Mb" suffix).
+ string (optional): The string to repeat in the response. Defaults to "a".
+
+ Example:
+ /resources/large.py?size=32Mb&string=ab
+ """
+ if not "size" in request.GET:
+ 400, "Need an integer bytes parameter"
+
+ bytes_value = request.GET.first("size")
+
+ chunk_size = 1024
+
+ multipliers = {"kb": 1024,
+ "Mb": 1024*1024}
+
+ suffix = bytes_value[-2:]
+ if suffix in multipliers:
+ multiplier = multipliers[suffix]
+ bytes_value = bytes_value[:-2] * multiplier
+
+ try:
+ num_bytes = int(bytes_value)
+ except ValueError:
+ return 400, "Bytes must be an integer possibly with a kb or Mb suffix"
+
+ string = str(request.GET.first("string", "a"))
+
+ chunk = string * chunk_size
+
+ def content():
+ bytes_sent = 0
+ while bytes_sent < num_bytes:
+ if num_bytes - bytes_sent < len(chunk):
+ yield chunk[num_bytes - bytes_sent]
+ else:
+ yield chunk
+ bytes_sent += len(chunk)
+ return [("Content-Type", "text/plain")], content()
diff --git a/tests/wpt/web-platform-tests/common/media.js b/tests/wpt/web-platform-tests/common/media.js
new file mode 100644
index 00000000000..6bddea5fd92
--- /dev/null
+++ b/tests/wpt/web-platform-tests/common/media.js
@@ -0,0 +1,35 @@
+//
+// Returns the URI of a supported video source based on the user agent
+//
+function getVideoURI(base)
+{
+ var extension = '.mp4';
+
+ var videotag = document.createElement("video");
+
+ if ( videotag.canPlayType &&
+ videotag.canPlayType('video/ogg; codecs="theora, vorbis"') )
+ {
+ extension = '.ogv';
+ }
+
+ return base + extension;
+}
+
+//
+// Returns the URI of a supported audio source based on the user agent
+//
+function getAudioURI(base)
+{
+ var extension = '.mp3';
+
+ var audiotag = document.createElement("audio");
+
+ if ( audiotag.canPlayType &&
+ audiotag.canPlayType('audio/ogg') )
+ {
+ extension = '.oga';
+ }
+
+ return base + extension;
+}
diff --git a/tests/wpt/web-platform-tests/common/redirect.py b/tests/wpt/web-platform-tests/common/redirect.py
new file mode 100644
index 00000000000..3f15effc059
--- /dev/null
+++ b/tests/wpt/web-platform-tests/common/redirect.py
@@ -0,0 +1,19 @@
+def main(request, response):
+ """Simple handler that causes redirection.
+
+ The request should typically have two query parameters:
+ status - The status to use for the redirection. Defaults to 302.
+ location - The resource to redirect to.
+ """
+ status = 302
+ if "status" in request.GET:
+ try:
+ status = int(request.GET.first("status"))
+ except ValueError:
+ pass
+
+ response.status = status
+
+ location = request.GET.first("location")
+
+ response.headers.set("Location", location)
diff --git a/tests/wpt/web-platform-tests/common/reftest-wait.js b/tests/wpt/web-platform-tests/common/reftest-wait.js
new file mode 100644
index 00000000000..87816f83452
--- /dev/null
+++ b/tests/wpt/web-platform-tests/common/reftest-wait.js
@@ -0,0 +1,9 @@
+function takeScreenshot() {
+ document.documentElement.classList.remove("reftest-wait");
+}
+
+function takeScreenshotDelayed(timeout) {
+ setTimeout(function() {
+ takeScreenshot();
+ }, timeout);
+}
diff --git a/tests/wpt/web-platform-tests/common/stringifiers.js b/tests/wpt/web-platform-tests/common/stringifiers.js
new file mode 100644
index 00000000000..b59ca9c246f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/common/stringifiers.js
@@ -0,0 +1,52 @@
+// Tests <http://heycam.github.io/webidl/#es-stringifier>.
+function test_stringifier_attribute(aObject, aAttribute, aIsUnforgeable) {
+ // Step 1.
+ test(function() {
+ [null, undefined].forEach(function(v) {
+ assert_throws(new TypeError(), function() {
+ aObject.toString.call(v);
+ });
+ });
+ });
+
+ // TODO Step 2: security check.
+
+ // Step 3.
+ test(function() {
+ assert_false("Window" in window && aObject instanceof window.Window);
+ [{}, window].forEach(function(v) {
+ assert_throws(new TypeError(), function() {
+ aObject.toString.call(v)
+ });
+ });
+ });
+
+ // Step 4-6.
+ var expected_value;
+ test(function() {
+ expected_value = aObject[aAttribute];
+ assert_equals(aObject[aAttribute], expected_value,
+ "The attribute " + aAttribute + " should be pure.");
+ });
+
+ var test_error = { name: "test" };
+ test(function() {
+ if (!aIsUnforgeable) {
+ Object.defineProperty(aObject, aAttribute, {
+ configurable: true,
+ get: function() { throw test_error; }
+ });
+ }
+ assert_equals(aObject.toString(), expected_value);
+ });
+
+ test(function() {
+ if (!aIsUnforgeable) {
+ Object.defineProperty(aObject, aAttribute, {
+ configurable: true,
+ value: { toString: function() { throw test_error; } }
+ });
+ }
+ assert_equals(aObject.toString(), expected_value);
+ });
+}
diff --git a/tests/wpt/web-platform-tests/common/text-plain.txt b/tests/wpt/web-platform-tests/common/text-plain.txt
new file mode 100644
index 00000000000..97ca870b6d5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/common/text-plain.txt
@@ -0,0 +1,4 @@
+This is a sample text/plain document.
+
+This is not an HTML document.
+
diff --git a/tests/wpt/web-platform-tests/common/utils.js b/tests/wpt/web-platform-tests/common/utils.js
new file mode 100644
index 00000000000..bcdc256d917
--- /dev/null
+++ b/tests/wpt/web-platform-tests/common/utils.js
@@ -0,0 +1,80 @@
+function make_absolute_url(options) {
+ var loc = window.location;
+ var protocol = get(options, "protocol", loc.protocol);
+ if (protocol[protocol.length - 1] != ":") {
+ protocol += ":";
+ }
+
+ var hostname = get(options, "hostname", loc.hostname);
+
+ var subdomain = get(options, "subdomain");
+ if (subdomain) {
+ hostname = subdomain + "." + hostname;
+ }
+
+ var port = get(options, "port", loc.port)
+ var path = get(options, "path", loc.pathname);
+ var query = get(options, "query", loc.search);
+ var hash = get(options, "hash", loc.hash)
+
+ var url = protocol + "//" + hostname;
+ if (port) {
+ url += ":" + port;
+ }
+
+ if (path[0] != "/") {
+ url += "/";
+ }
+ url += path;
+ if (query) {
+ if (query[0] != "?") {
+ url += "?";
+ }
+ url += query;
+ }
+ if (hash) {
+ if (hash[0] != "#") {
+ url += "#";
+ }
+ url += hash;
+ }
+ return url;
+}
+
+function get(obj, name, default_val) {
+ if (obj.hasOwnProperty(name)) {
+ return obj[name];
+ }
+ return default_val;
+}
+
+function token() {
+ var uuid = [to_hex(rand_int(32), 8),
+ to_hex(rand_int(16), 4),
+ to_hex(0x4000 | rand_int(12), 4),
+ to_hex(0x8000 | rand_int(14), 4),
+ to_hex(rand_int(48), 12)].join("-")
+ return uuid;
+}
+
+function rand_int(bits) {
+ if (bits < 1 || bits > 53) {
+ throw new TypeError();
+ } else {
+ if (bits >= 1 && bits <= 30) {
+ return 0 | ((1 << bits) * Math.random());
+ } else {
+ var high = (0 | ((1 << (bits - 30)) * Math.random())) * (1 << 30);
+ var low = 0 | ((1 << 30) * Math.random());
+ return high + low;
+ }
+ }
+}
+
+function to_hex(x, length) {
+ var rv = x.toString(16);
+ while (rv.length < length) {
+ rv = "0" + rv;
+ }
+ return rv;
+}
diff --git a/tests/wpt/web-platform-tests/common/vendor-prefix.js b/tests/wpt/web-platform-tests/common/vendor-prefix.js
new file mode 100644
index 00000000000..1a91632cec2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/common/vendor-prefix.js
@@ -0,0 +1,115 @@
+/* Use this script when you want to test APIs that use vendor prefixes
+ and define which objects need to be checked for prefixed versions, à la
+ <script src="vendor-prefix.js"
+ data-prefixed-objects='[{"ancestors":["navigator"], "name":"getUserMedia"}]'
+ data-prefixed-prototypes='[{"ancestors":["HTMLMediaElement"],"name":"srcObject"}]'></script>
+ data-prefixed-objects lets prefix objects in the global space
+ data-prefixed-prototypes adds prefixes to interfaces, for objects that
+ get created during the tests
+
+ NB: vendor prefixes are expected to go away in favor of putting
+ new features behind flag, so hopefully there will be only limited
+ need to use this
+*/
+
+(function () {
+ var aliases = {};
+ var documentingPrefixUsage = document.createElement('div');
+ var vendorPrefixes = ["moz", "ms", "o", "webkit", "Moz", "MS", "O", "WebKit", "op"];
+
+ function getParentObject(ancestors) {
+ var parent = window;
+ var currentName = "";
+ ancestors.forEach(function (p) {
+ currentName = currentName ? currentName + "." + p : p;
+ if (parent[p] === undefined) {
+ throw currentName + " is undefined, cannot set prefix alias on child object";
+ }
+ parent = parent[p];
+ });
+ return parent;
+ }
+
+ function prependPrefix(prefix, name) {
+ var newName = name[0].toUpperCase() + name.substr(1, name.length);
+ return prefix + newName;
+ }
+
+ function setPrototypeAlias(obj) {
+ var parent = getParentObject(obj.ancestors);
+ if (!parent.prototype.hasOwnProperty(obj.name)) {
+ vendorPrefixes.forEach(function (prefix) {
+ if (parent.prototype.hasOwnProperty(prependPrefix(prefix, obj.name))) {
+ Object.defineProperty(parent.prototype, obj.name,
+ {get: function() {return this[prependPrefix(prefix, obj.name)];},
+ set: function(v) {this[prependPrefix(prefix, obj.name)] = v;}
+ });
+ aliases[obj.ancestors.join(".") + ".prototype." + obj.name] = obj.ancestors.join(".") + ".prototype." + prependPrefix(prefix, obj.name);
+ return;
+ }
+ });
+ }
+ }
+
+ function setAlias(obj) {
+ var parent = getParentObject(obj.ancestors);
+ if (parent[obj.name] === undefined) {
+ vendorPrefixes.forEach(function (prefix) {
+ if (parent[prependPrefix(prefix, obj.name)] !== undefined) {
+ parent[obj.name] = parent[prependPrefix(prefix, obj.name)];
+ aliases[obj.ancestors.join(".") + "." + obj.name] = obj.ancestors.join(".") + "." + prependPrefix(prefix, obj.name);
+ return;
+ }
+ });
+ }
+ }
+
+ if (location.search.indexOf('usePrefixes=1') !== -1) {
+ if (document.querySelector("script[data-prefixed-objects]")) {
+ var prefixObjectsData = document.querySelector("script[data-prefixed-objects]").dataset["prefixedObjects"];
+ try {
+ var prefixedObjects = JSON.parse(prefixObjectsData);
+ } catch (e) {
+ throw "couldn't parse data-prefixed-objects as JSON:" + e;
+ }
+ prefixedObjects.forEach(setAlias);
+ }
+ if (document.querySelector("script[data-prefixed-prototypes]")) {
+ var prefixProtoData = document.querySelector("script[data-prefixed-prototypes]").dataset["prefixedPrototypes"];
+ try {
+ var prefixedPrototypes = JSON.parse(prefixProtoData);
+ } catch (e) {
+ throw "couldn't parse data-prefixed-prototypes as JSON:" + e;
+ }
+ prefixedPrototypes.forEach(setPrototypeAlias);
+ }
+ var ul = document.createElement("ul");
+ Object.keys(aliases).forEach(function (alias) {
+ var li = document.createElement("li");
+ li.appendChild(document.createTextNode(alias + " has been set to be an alias of vendor-prefixed " + aliases[alias]));
+ ul.appendChild(li);
+ });
+ documentingPrefixUsage.appendChild(ul);
+ } else {
+ // Document that the test can be run with prefixes enabled
+
+ var a = document.createElement('a');
+ var link = "";
+ if (location.search) {
+ link = location.search + "&usePrefixes=1";
+ } else {
+ link = "?usePrefixes=1";
+ }
+ a.setAttribute("href", link);
+ a.appendChild(document.createTextNode("with vendor prefixes enabled"));
+ documentingPrefixUsage.appendChild(document.createTextNode("The feature(s) tested here are known to have been made available via vendor prefixes; you can run this test "));
+ documentingPrefixUsage.appendChild(a);
+ documentingPrefixUsage.appendChild(document.createTextNode("."));
+ }
+ var log = document.getElementById('log');
+ if (log) {
+ log.parentNode.insertBefore(documentingPrefixUsage, log);
+ } else {
+ document.body.appendChild(documentingPrefixUsage);
+ }
+})();
diff --git a/tests/wpt/web-platform-tests/config.default.json b/tests/wpt/web-platform-tests/config.default.json
new file mode 100644
index 00000000000..3efab6b3041
--- /dev/null
+++ b/tests/wpt/web-platform-tests/config.default.json
@@ -0,0 +1,22 @@
+{"host": "web-platform.test",
+ "external_host": null,
+ "ports":{"http":[8000, "auto"],
+ "https":[8443],
+ "ws":["auto"]},
+ "check_subdomains": true,
+ "log_level":"debug",
+ "bind_hostname": true,
+ "ssl": {"type": "openssl",
+ "encrypt_after_connect": false,
+ "openssl": {
+ "openssl_binary": "openssl",
+ "base_path": "_certs",
+ "force_regenerate": false
+ },
+ "pregenerated": {
+ "host_key_path": null,
+ "host_cert_path": null
+ },
+ "none": {}
+ }
+}
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/Makefile b/tests/wpt/web-platform-tests/conformance-checkers/Makefile
new file mode 100644
index 00000000000..161c8db7d57
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/Makefile
@@ -0,0 +1,43 @@
+HTML2MARKDOWN=html2text
+PERL=perl
+PERLFLAGS=
+FMT=fmt
+FMTFLAGS=-80
+EXPAND=expand
+EXPANDFLAGS=
+GIT=git
+GITFLAGS=
+PYTHON=python
+PYTHONFLAGS=
+VNU_TEST_REPO=git@github.com:validator/tests.git
+ITS_REPO=git@github.com:w3c/its-2.0-testsuite-inputdata.git
+.PHONY: .FORCE
+
+all: README.md messages.json
+
+README.md: index.html
+ $(HTML2MARKDOWN) $(HTML2MARKDOWNFLAGS) $< \
+ | $(PERL) $(PERLFLAGS) -pe 'undef $$/; s/(\s+\n)+/\n\n/g' \
+ | $(PERL) $(PERLFLAGS) -pe 'undef $$/; s/(\n\n\n)+/\n/g' \
+ | $(FMT) $(FMTFLAGS) \
+ | $(PERL) $(PERLFLAGS) -pe 'undef $$/; s/ +(\[[0-9]+\]:)\n +/\n $$1 /g' \
+ | $(EXPAND) $(EXPANDFLAGS) > $@
+
+messages.json: .FORCE
+ $(PYTHON) $(PYTHONFLAGS) -mjson.tool $@ > $@.tmp
+ mv $@.tmp $@
+
+push:
+ cd .. \
+ && git push $(VNU_TEST_REPO) `git subtree split -P conformance-checkers`:master --force \
+ && cd -
+
+its-push:
+ cd ..\
+ && $(GIT) subtree push -P conformance-checkers/html-its/ $(ITS_REPO) master \
+ && cd -
+
+its-pull:
+ cd .. \
+ && $(GIT) pull -s subtree $(ITS_REPO) master \
+ && cd -
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/README.md b/tests/wpt/web-platform-tests/conformance-checkers/README.md
new file mode 100644
index 00000000000..2c478afc600
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/README.md
@@ -0,0 +1,11 @@
+# WPT conformance-checker tests
+
+The files in this part of the tree are not browser tests; they're documents
+intended for testing the behavior of conformance checkers (e.g., validator.nu
+and the W3C Nu Markup Validator).
+
+TK: We should have here some details about the contents of the existing
+subdirectories in this tree...
+
+Curious committers should see the makefile.
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/_/780.htm b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/_/780.htm
new file mode 100644
index 00000000000..7e37b720efe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/_/780.htm
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>AT-SPI ONLY: option within listbox exposed as ROLE_MENU: option is exposed as ROLE_MENU_ITEM</title>
+ </head>
+ <body>
+ <h1>AT-SPI ONLY: option within listbox exposed as ROLE_MENU: option is exposed as ROLE_MENU_ITEM</h1>
+ <div role="combobox" aria-expanded="true" aria-label="Combobox for AT-SPI test of listbox/option mappings">
+ <input type="text" value="combobox entry field">
+ <div role="listbox" aria-label="Listbox child of combobox for AT-SPI test of listbox/option mappings">
+ <p role="option" id="test">Test option</p>
+ <p role="option">Another option</p>
+ <p role="option">A third option</p>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/_functional/tree/ariatree.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/_functional/tree/ariatree.html
new file mode 100644
index 00000000000..d2d57e5082e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/_functional/tree/ariatree.html
@@ -0,0 +1,106 @@
+<!DOCTYPE HTML><!-- HTML 5 -->
+<html lang="en">
+<head>
+ <title>ARIA Tree Example</title>
+ <meta http-equiv="Content-type" content="text/html; charset=utf-8">
+ <link rel="stylesheet" href="./css/treesimple.css" type="text/css">
+ <script type="text/javascript" src="./js/prototype.js"></script>
+ <script type="text/javascript" src="./js/aria.js"></script>
+ <script type="text/javascript" src="./js/init.js"></script>
+</head>
+<body>
+
+ <h1>Directions</h1>
+ <ol>
+ <li>Tab into the tree control.</li>
+ <li>Use the up/down arrow keys to change the active descendant.</li>
+ <li>Use the right/left arrow keys to expand/collapse appropriate nodes.</li>
+ </ol>
+
+ <p>Some <a href="javascript:$('tree0').focus();">focusable</a> content before the ARIA application.</p>
+
+ <div role="application">
+ <h1 id="treelabel">ARIA Tree Example</h1>
+ <ul id="tree0" role="tree" aria-labelledby="treelabel" aria-activedescendant="tree0_item0_2_0_1" tabindex="0">
+ <!-- all the ids and aria-* attributes are hardcoded here for sake of example (final version will use javascript to assign ids as needed) -->
+ <li id="tree0_item0" role="treeitem" aria-level="1" aria-expanded="true">
+ <!-- .expander becomes the javascript trigger for expand/collapse -->
+ <span class="expander"></span>
+ Animals
+ <ul role="group">
+ <li id="tree0_item0_0" role="treeitem" aria-level="2"><span>Birds</span></li>
+ <li id="tree0_item0_1" role="treeitem" aria-level="2" aria-expanded="false">
+ <span class="expander"></span>
+ Cats
+ <ul role="group">
+ <li id="tree0_item0_1_0" role="treeitem" aria-level="3">Siamese</li>
+ <li id="tree0_item0_1_1" role="treeitem" aria-level="3">Tabby</li>
+ </ul>
+ </li>
+ <li id="tree0_item0_2" role="treeitem" aria-level="2" aria-expanded="true">
+ <span class="expander"></span>
+ Dogs
+ <ul role="group">
+ <li id="tree0_item0_2_0" role="treeitem" aria-level="3" aria-expanded="true">
+ <span class="expander"></span>
+ Small Breeds
+ <ul role="group">
+ <li id="tree0_item0_2_0_0" role="treeitem" aria-level="4">Chihuahua</li>
+ <li id="tree0_item0_2_0_1" role="treeitem" aria-level="4">Italian Greyhound</li>
+ <li id="tree0_item0_2_0_2" role="treeitem" aria-level="4">Japanese Chin</li>
+ </ul>
+ </li>
+ <li id="tree0_item0_2_1" role="treeitem" aria-level="3" aria-expanded="false">
+ <span class="expander"></span>
+ Medium Breeds
+ <ul role="group">
+ <li id="tree0_item0_2_1_0" role="treeitem" aria-level="4">Beagle</li>
+ <li id="tree0_item0_2_1_1" role="treeitem" aria-level="4">Cocker Spaniel</li>
+ <li id="tree0_item0_2_1_2" role="treeitem" aria-level="4">Pit Bull</li>
+ </ul>
+ </li>
+ <li id="tree0_item0_2_2" role="treeitem" aria-level="3" aria-expanded="false">
+ <span class="expander"></span>
+ Large Breeds
+ <ul role="group">
+ <li id="tree0_item0_2_2_0" role="treeitem" aria-level="4">Afghan</li>
+ <li id="tree0_item0_2_2_1" role="treeitem" aria-level="4">Great Dane</li>
+ <li id="tree0_item0_2_2_2" role="treeitem" aria-level="4">Mastiff</li>
+ </ul>
+ </li>
+ </ul>
+ </li>
+ </ul>
+ </li>
+ <li id="tree0_item1" role="treeitem" aria-level="1" aria-expanded="true">
+ <span class="expander"></span>
+ Minerals
+ <ul role="group">
+ <li id="tree0_item1_0" role="treeitem" aria-level="2">Zinc</li>
+ <li id="tree0_item1_1" role="treeitem" aria-level="2" aria-expanded="false">
+ <span class="expander"></span>
+ Gold
+ <ul role="group">
+ <li id="tree0_item1_1_0" role="treeitem" aria-level="3">Yellow Gold</li>
+ <li id="tree0_item1_1_1" role="treeitem" aria-level="3">White Gold</li>
+ </ul>
+ </li>
+ <li id="tree0_item1_2" role="treeitem" aria-level="2">Silver</li>
+ </ul>
+ </li>
+ <li id="tree0_item2" role="treeitem" aria-level="1" aria-expanded="true">
+ <span class="expander"></span>
+ Vegetables
+ <ul role="group">
+ <li id="tree0_item2_0" role="treeitem" aria-level="2">Carrot</li>
+ <li id="tree0_item2_1" role="treeitem" aria-level="2">Tomato</li>
+ <li id="tree0_item2_2" role="treeitem" aria-level="2">Lettuce</li>
+ </ul>
+ </li>
+ </ul>
+ </div>
+
+ <p>More <a href="javascript:$('tree0').focus();">focusable</a> content after the ARIA application.</p>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/_functional/tree/ariatree2.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/_functional/tree/ariatree2.html
new file mode 100644
index 00000000000..b6d809ce61f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/_functional/tree/ariatree2.html
@@ -0,0 +1,124 @@
+<!DOCTYPE HTML><!-- HTML 5 -->
+<html lang="en">
+<head>
+ <title>ARIA Tree Example</title>
+ <meta http-equiv="Content-type" content="text/html; charset=utf-8">
+ <link rel="stylesheet" href="./css/treebox.css" type="text/css">
+ <script type="text/javascript" src="./js/prototype.js"></script>
+ <script type="text/javascript" src="./js/aria.js"></script>
+ <script type="text/javascript" src="./js/init.js"></script>
+</head>
+<body>
+
+ <h1>Directions</h1>
+ <ol>
+ <li>Tab into the tree control.</li>
+ <li>Use the up/down arrow keys to change the active descendant.</li>
+ <li>Use the right/left arrow keys to expand/collapse appropriate nodes.</li>
+ </ol>
+
+ <p>Some <a href="javascript:$('tree0').focus();">focusable</a> content before the ARIA application.</p>
+
+ <div role="application">
+ <h1 id="treelabel">ARIA Tree Example</h1>
+ <ul id="tree0" role="tree" aria-labelledby="treelabel" aria-activedescendant="tree0_item0_2_0_1" tabindex="0">
+ <!-- all the ids and aria-* attributes are hardcoded here for sake of example (final version will use javascript to assign ids as needed) -->
+ <li id="tree0_item0" role="treeitem" aria-level="1" aria-expanded="true">
+ <!-- .expander becomes the javascript trigger for expand/collapse -->
+ <span>
+ <span class="expander"></span>
+ Animals
+ </span>
+ <ul role="group">
+ <li id="tree0_item0_0" role="treeitem" aria-level="2"><span>Birds</span></li>
+ <li id="tree0_item0_1" role="treeitem" aria-level="2" aria-expanded="false">
+ <span>
+ <span class="expander"></span>
+ Cats
+ </span>
+ <ul role="group">
+ <li id="tree0_item0_1_0" role="treeitem" aria-level="3"><span>Siamese</span></li>
+ <li id="tree0_item0_1_1" role="treeitem" aria-level="3"><span>Tabby</span></li>
+ </ul>
+ </li>
+ <li id="tree0_item0_2" role="treeitem" aria-level="2" aria-expanded="true">
+ <span>
+ <span class="expander"></span>
+ Dogs
+ </span>
+ <ul role="group">
+ <li id="tree0_item0_2_0" role="treeitem" aria-level="3" aria-expanded="true">
+ <span>
+ <span class="expander"></span>
+ Small Breeds
+ </span>
+ <ul role="group">
+ <li id="tree0_item0_2_0_0" role="treeitem" aria-level="4"><span>Chihuahua</span></li>
+ <li id="tree0_item0_2_0_1" role="treeitem" aria-level="4"><span>Italian Greyhound</span></li>
+ <li id="tree0_item0_2_0_2" role="treeitem" aria-level="4"><span>Japanese Chin</span></li>
+ </ul>
+ </li>
+ <li id="tree0_item0_2_1" role="treeitem" aria-level="3" aria-expanded="false">
+ <span>
+ <span class="expander"></span>
+ Medium Breeds
+ </span>
+ <ul role="group">
+ <li id="tree0_item0_2_1_0" role="treeitem" aria-level="4"><span>Beagle</span></li>
+ <li id="tree0_item0_2_1_1" role="treeitem" aria-level="4"><span>Cocker Spaniel</span></li>
+ <li id="tree0_item0_2_1_2" role="treeitem" aria-level="4"><span>Pit Bull</span></li>
+ </ul>
+ </li>
+ <li id="tree0_item0_2_2" role="treeitem" aria-level="3" aria-expanded="false">
+ <span>
+ <span class="expander"></span>
+ Large Breeds
+ </span>
+ <ul role="group">
+ <li id="tree0_item0_2_2_0" role="treeitem" aria-level="4"><span>Afghan</span></li>
+ <li id="tree0_item0_2_2_1" role="treeitem" aria-level="4"><span>Great Dane</span></li>
+ <li id="tree0_item0_2_2_2" role="treeitem" aria-level="4"><span>Mastiff</span></li>
+ </ul>
+ </li>
+ </ul>
+ </li>
+ </ul>
+ </li>
+ <li id="tree0_item1" role="treeitem" aria-level="1" aria-expanded="true">
+ <span>
+ <span class="expander"></span>
+ Minerals
+ </span>
+ <ul role="group">
+ <li id="tree0_item1_0" role="treeitem" aria-level="2"><span>Zinc</span></li>
+ <li id="tree0_item1_1" role="treeitem" aria-level="2" aria-expanded="false">
+ <span>
+ <span class="expander"></span>
+ Gold
+ </span>
+ <ul role="group">
+ <li id="tree0_item1_1_0" role="treeitem" aria-level="3"><span>Yellow Gold</span></li>
+ <li id="tree0_item1_1_1" role="treeitem" aria-level="3"><span>White Gold</span></li>
+ </ul>
+ </li>
+ <li id="tree0_item1_2" role="treeitem" aria-level="2"><span>Silver</span></li>
+ </ul>
+ </li>
+ <li id="tree0_item2" role="treeitem" aria-level="1" aria-expanded="true">
+ <span>
+ <span class="expander"></span>
+ Vegetables
+ </span>
+ <ul role="group">
+ <li id="tree0_item2_0" role="treeitem" aria-level="2"><span>Carrot</span></li>
+ <li id="tree0_item2_1" role="treeitem" aria-level="2"><span>Tomato</span></li>
+ <li id="tree0_item2_2" role="treeitem" aria-level="2"><span>Lettuce</span></li>
+ </ul>
+ </li>
+ </ul>
+ </div>
+
+ <p>More <a href="javascript:$('tree0').focus();">focusable</a> content after the ARIA application.</p>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/_functional/tree/css/img/expander.gif b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/_functional/tree/css/img/expander.gif
new file mode 100644
index 00000000000..e305b9dd73a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/_functional/tree/css/img/expander.gif
Binary files differ
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/_functional/tree/css/treebox.css b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/_functional/tree/css/treebox.css
new file mode 100644
index 00000000000..5064fa308ab
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/_functional/tree/css/treebox.css
@@ -0,0 +1,65 @@
+
+/* variant of treesimple.css, that adds slightly more complex styling. */
+
+html, body {
+ color:#333;
+ background-color:#fff;
+ font-family:"helvetica neue", arial, helvetica, sans-serif;
+ font-size:12px;
+ line-height:1.4em;
+}
+h1{
+ font-size:14px;
+}
+[role="tree"]{
+ border:solid 1px #000;
+ width:300px; /* hardcoded for example */
+ cursor:default;
+}
+ul[role="tree"], [role="tree"] li, [role="tree"] ul {
+ display:block;
+ list-style:none;
+ margin:0;
+ padding:0;
+}
+li[role="treeitem"] {
+ position:relative;
+}
+
+[role="treeitem"] > span{ display:block; }
+
+/* looks kinda redundant, but is necessary to get the full left bleed on sub-level items */
+[role="treeitem"] > span{ padding-left:15px; }
+[role="treeitem"] [role="treeitem"] > span{ padding-left:30px; }
+[role="treeitem"] [role="treeitem"] [role="treeitem"] > span{ padding-left:45px; }
+[role="treeitem"] [role="treeitem"] [role="treeitem"] [role="treeitem"] > span{ padding-left:60px; }
+[role="treeitem"] [role="treeitem"] [role="treeitem"] [role="treeitem"] [role="treeitem"] > span{ padding-left:75px; }
+
+.expander {
+ display:block;
+ position:absolute;
+ left:2px;
+ top:0.3em;
+ width:9px;
+ height:9px;
+ background:transparent url(./img/expander.gif) -9px 0 no-repeat;
+}
+[aria-expanded="false"] > * > .expander {
+ background-position:0 0;
+}
+[role="treeitem"] [role="treeitem"] .expander { left:17px; }
+[role="treeitem"] [role="treeitem"] [role="treeitem"] .expander { left:32px; }
+[role="treeitem"] [role="treeitem"] [role="treeitem"] [role="treeitem"] .expander { left:47px; }
+[role="treeitem"] [role="treeitem"] [role="treeitem"] [role="treeitem"] [role="treeitem"] .expander { left:62px; }
+
+
+[aria-expanded="false"] [role="group"] {
+ display:none;
+}
+[role="tree"] .activedescendant > span {
+ background-color:#ccc;
+}
+[role="tree"]:focus .activedescendant > span {
+ color:#fff;
+ background-color:#03c;
+}
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/_functional/tree/css/treesimple.css b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/_functional/tree/css/treesimple.css
new file mode 100644
index 00000000000..835d4e1c3bd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/_functional/tree/css/treesimple.css
@@ -0,0 +1,50 @@
+
+html, body {
+ color:#333;
+ background-color:#fff;
+ font-family:"helvetica neue", arial, helvetica, sans-serif;
+ font-size:12px;
+ line-height:1.4em;
+}
+h1{
+ font-size:14px;
+}
+[role="tree"]{
+ cursor:default;
+}
+ul[role="tree"], [role="tree"] li, [role="tree"] ul {
+ display:block;
+ list-style:none;
+ margin:0;
+ padding:0;
+}
+li[role="treeitem"] {
+ position:relative;
+ padding-left:15px;
+}
+.expander {
+ display:block;
+ position:absolute;
+ left:2px;
+ top:0.3em;
+ width:9px;
+ height:9px;
+ background:transparent url(./img/expander.gif) -9px 0 no-repeat;
+}
+[aria-expanded="false"] > * > .expander {
+ background-position:0 0;
+}
+[aria-expanded="false"] [role="group"] {
+ display:none;
+}
+[role="tree"] .activedescendant {
+ font-weight:bold;
+ color:#000;
+}
+[role="tree"]:focus .activedescendant{
+ color:#03c;
+}
+[role="tree"] .activedescendant [role="group"] {
+ font-weight:normal;
+ color:#000;
+}
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/_functional/tree/js/aria.js b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/_functional/tree/js/aria.js
new file mode 100644
index 00000000000..e853a3a95f0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/_functional/tree/js/aria.js
@@ -0,0 +1,160 @@
+
+/* Aria Singleton */
+var Aria = {
+ Trees: new Array(), // instances of Aria.Tree Class
+ isEnabled: function(inNode){
+ // todo: this may need to check isEnabled on all parentNodes, inheritence of aria-enabled is ambiguous
+ if(inNode.getAttribute('aria-enabled') && inNode.getAttribute('aria-enabled').toLowerCase()=='false') return false;
+ else return true;
+ },
+ isExpanded: function(inNode){
+ if(inNode.getAttribute('aria-expanded') && inNode.getAttribute('aria-expanded').toLowerCase()=='false') return false;
+ else return true;
+ },
+ isTreeItem: function(inNode){
+ if(inNode.getAttribute('role') && inNode.getAttribute('role').toLowerCase()=='treeitem') return true;
+ else return false;
+ }
+};
+
+Aria.Tree = Class.create();
+Aria.Tree.prototype = {
+ initialize: function(inNode){
+ if(!$(inNode) && console.error) console.error('Error from aria.js: Aria.Tree instance initialized with invalid element, '+ inNode);
+ this.el = $(inNode);
+ this.index = Aria.Trees.length; // each tree should know its index in the Aria singleton's list, in order to concatenate id strings
+ this.strActiveDescendant = this.el.getAttribute('aria-activedescendant');
+ this.strDefaultActiveDescendant = 'tree'+this.index+'_item0'; // default first item
+ if(!$(this.strActiveDescendant)) this.strActiveDescendant = this.strDefaultActiveDescendant; // set to default if no existing activedescendant
+ this.setActiveDescendant($(this.strActiveDescendant));
+
+ // set up event delegation on the tree node
+ Event.observe(this.el, 'click', this.handleClick.bindAsEventListener(this));
+ Event.observe(this.el, 'keydown', this.handleKeyPress.bindAsEventListener(this)); //webkit doesn't send keypress events for arrow keys, so use keydown instead
+
+ },
+ getActiveDescendant: function(inNode){
+ if(inNode){ // if inNode (from event target), sets the activedescendant to nearest ancestor treeitem
+ var el = $(inNode);
+ while(el != this.el){
+ if(Aria.isTreeItem(el)) break; // exit the loop; we have the treeitem
+ el = el.parentNode;
+ }
+ if(el == this.el) {
+ this.setActiveDescendant(); // set to default activedescendant
+ } else {
+ this.setActiveDescendant(el);
+ return el;
+ }
+ } else {
+ return $(this.el.getAttribute('aria-activedescendant'));
+ }
+ },
+ getNextTreeItem: function(inNode){
+ var el = $(inNode);
+ var originalElm = $(inNode);
+ while(!Aria.isTreeItem(el) || el == originalElm){
+ if(Aria.isExpanded(el) && el.down()){ // should be el.down('[role="treeitem"]');
+ var elements = el.getElementsByTagName('*');
+ for(var i=0, c=elements.length; i<c; i++){
+ if(Aria.isTreeItem(elements[i])) return elements[i];
+ }
+ }
+ if(el.next()){
+ el = el.next();
+ } else {
+ while(!el.parentNode.next() && el.parentNode != this.el){
+ el = el.parentNode;
+ }
+ if(el.parentNode == this.el) return originalElm; // if no next items in tree, return current treeitem
+ else el = el.parentNode.next();
+ }
+ }
+ return el;
+ },
+ getPreviousTreeItem: function(inNode){
+ var el = $(inNode);
+ var originalElm = $(inNode);
+ while(!Aria.isTreeItem(el) || el == originalElm){
+ if(el.previous()){
+ el = el.previous();
+ // recursively choose last child node of previous el, as long as it's not in an collapsed node
+ if (el.down() && Aria.isExpanded(el)){
+ el = el.down();
+ while (el.next() || (el.down() && Aria.isExpanded(el))){
+ if (el.next()) el = el.next();
+ else el = el.down();
+ }
+ }
+ } else {
+ if(el.parentNode == this.el) return originalElm; // if no previous items in tree, return current treeitem
+ el = el.parentNode;
+ }
+ }
+ if(el == this.el) return originalElm; // if no previous items in tree, return current treeitem
+ return el;
+ },
+ handleClick: function(inEvent){
+ var target = inEvent.target; // get the click target
+ var el = this.getActiveDescendant(target);
+ if(target.className.indexOf('expander')>-1){ // if it's an expander widget
+ this.toggleExpanded(el); // toggle the aria-expanded attribute on activedescendant
+ Event.stop(inEvent); // and stop the event
+ }
+ },
+ handleKeyPress: function(inEvent){
+ switch(inEvent.keyCode){
+ // case Event.KEY_PAGEUP: break;
+ // case Event.KEY_PAGEDOWN: break;
+ // case Event.KEY_END: break;
+ // case Event.KEY_HOME: break;
+ case Event.KEY_LEFT: this.keyLeft(); break;
+ case Event.KEY_UP: this.keyUp(); break;
+ case Event.KEY_RIGHT: this.keyRight(); break;
+ case Event.KEY_DOWN: this.keyDown(); break;
+ default:
+ //console.log(inEvent.keyCode);
+ return;
+ }
+ Event.stop(inEvent);
+ },
+ keyLeft: function(){
+ var el = this.activeDescendant;
+ if(Aria.isExpanded(el)){
+ el.setAttribute('aria-expanded','false');
+ this.setActiveDescendant(this.activeDescendant);
+ }
+ },
+ keyUp: function(){
+ var el = this.activeDescendant;
+ this.setActiveDescendant(this.getPreviousTreeItem(el));
+ },
+ keyRight: function(){
+ var el = this.activeDescendant;
+ if(!Aria.isExpanded(el)){
+ el.setAttribute('aria-expanded','true');
+ this.setActiveDescendant(this.activeDescendant);
+ }
+ },
+ keyDown: function(){
+ var el = this.activeDescendant;
+ this.setActiveDescendant(this.getNextTreeItem(el));
+ },
+ setActiveDescendant: function(inNode){
+ Element.removeClassName(this.activeDescendant,'activedescendant')
+ if($(inNode)) this.activeDescendant = $(inNode);
+ else this.activeDescendant = $(this.strDefaultActiveDescendant);
+ Element.addClassName(this.activeDescendant,'activedescendant')
+ this.strActiveDescendant = this.activeDescendant.id;
+ this.el.setAttribute('aria-activedescendant', this.activeDescendant.id);
+ },
+ toggleExpanded: function(inNode){
+ var el = $(inNode);
+ if(Aria.isExpanded(el)){
+ el.setAttribute('aria-expanded','false');
+ } else {
+ el.setAttribute('aria-expanded','true');
+ }
+ this.setActiveDescendant(el);
+ }
+};
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/_functional/tree/js/init.js b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/_functional/tree/js/init.js
new file mode 100644
index 00000000000..c4e507f1f3e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/_functional/tree/js/init.js
@@ -0,0 +1,8 @@
+function myLoad(){
+ $$('[role="tree"]').each(function(elm){
+ // for each node where [role="tree"], create a new Aria.Tree instance and append it to array Aria.Trees
+ Aria.Trees.push(new Aria.Tree(elm));
+ });
+}
+Event.observe(window, 'load', myLoad); // will probably use onDOMContentLoaded instead of onLoad
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/_functional/tree/js/prototype.js b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/_functional/tree/js/prototype.js
new file mode 100644
index 00000000000..b0e0675867a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/_functional/tree/js/prototype.js
@@ -0,0 +1,4184 @@
+/* Prototype JavaScript framework, version 1.6.0
+ * (c) 2005-2007 Sam Stephenson
+ *
+ * Prototype is freely distributable under the terms of an MIT-style license.
+ * For details, see the Prototype web site: http://www.prototypejs.org/
+ *
+ *--------------------------------------------------------------------------*/
+
+var Prototype = {
+ Version: '1.6.0',
+
+ Browser: {
+ IE: !!(window.attachEvent && !window.opera),
+ Opera: !!window.opera,
+ WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
+ Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1,
+ MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)
+ },
+
+ BrowserFeatures: {
+ XPath: !!document.evaluate,
+ ElementExtensions: !!window.HTMLElement,
+ SpecificElementExtensions:
+ document.createElement('div').__proto__ &&
+ document.createElement('div').__proto__ !==
+ document.createElement('form').__proto__
+ },
+
+ ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
+ JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
+
+ emptyFunction: function() { },
+ K: function(x) { return x }
+};
+
+if (Prototype.Browser.MobileSafari)
+ Prototype.BrowserFeatures.SpecificElementExtensions = false;
+
+if (Prototype.Browser.WebKit)
+ Prototype.BrowserFeatures.XPath = false;
+
+/* Based on Alex Arnell's inheritance implementation. */
+var Class = {
+ create: function() {
+ var parent = null, properties = $A(arguments);
+ if (Object.isFunction(properties[0]))
+ parent = properties.shift();
+
+ function klass() {
+ this.initialize.apply(this, arguments);
+ }
+
+ Object.extend(klass, Class.Methods);
+ klass.superclass = parent;
+ klass.subclasses = [];
+
+ if (parent) {
+ var subclass = function() { };
+ subclass.prototype = parent.prototype;
+ klass.prototype = new subclass;
+ parent.subclasses.push(klass);
+ }
+
+ for (var i = 0; i < properties.length; i++)
+ klass.addMethods(properties[i]);
+
+ if (!klass.prototype.initialize)
+ klass.prototype.initialize = Prototype.emptyFunction;
+
+ klass.prototype.constructor = klass;
+
+ return klass;
+ }
+};
+
+Class.Methods = {
+ addMethods: function(source) {
+ var ancestor = this.superclass && this.superclass.prototype;
+ var properties = Object.keys(source);
+
+ if (!Object.keys({ toString: true }).length)
+ properties.push("toString", "valueOf");
+
+ for (var i = 0, length = properties.length; i < length; i++) {
+ var property = properties[i], value = source[property];
+ if (ancestor && Object.isFunction(value) &&
+ value.argumentNames().first() == "$super") {
+ var method = value, value = Object.extend((function(m) {
+ return function() { return ancestor[m].apply(this, arguments) };
+ })(property).wrap(method), {
+ valueOf: function() { return method },
+ toString: function() { return method.toString() }
+ });
+ }
+ this.prototype[property] = value;
+ }
+
+ return this;
+ }
+};
+
+var Abstract = { };
+
+Object.extend = function(destination, source) {
+ for (var property in source)
+ destination[property] = source[property];
+ return destination;
+};
+
+Object.extend(Object, {
+ inspect: function(object) {
+ try {
+ if (object === undefined) return 'undefined';
+ if (object === null) return 'null';
+ return object.inspect ? object.inspect() : object.toString();
+ } catch (e) {
+ if (e instanceof RangeError) return '...';
+ throw e;
+ }
+ },
+
+ toJSON: function(object) {
+ var type = typeof object;
+ switch (type) {
+ case 'undefined':
+ case 'function':
+ case 'unknown': return;
+ case 'boolean': return object.toString();
+ }
+
+ if (object === null) return 'null';
+ if (object.toJSON) return object.toJSON();
+ if (Object.isElement(object)) return;
+
+ var results = [];
+ for (var property in object) {
+ var value = Object.toJSON(object[property]);
+ if (value !== undefined)
+ results.push(property.toJSON() + ': ' + value);
+ }
+
+ return '{' + results.join(', ') + '}';
+ },
+
+ toQueryString: function(object) {
+ return $H(object).toQueryString();
+ },
+
+ toHTML: function(object) {
+ return object && object.toHTML ? object.toHTML() : String.interpret(object);
+ },
+
+ keys: function(object) {
+ var keys = [];
+ for (var property in object)
+ keys.push(property);
+ return keys;
+ },
+
+ values: function(object) {
+ var values = [];
+ for (var property in object)
+ values.push(object[property]);
+ return values;
+ },
+
+ clone: function(object) {
+ return Object.extend({ }, object);
+ },
+
+ isElement: function(object) {
+ return object && object.nodeType == 1;
+ },
+
+ isArray: function(object) {
+ return object && object.constructor === Array;
+ },
+
+ isHash: function(object) {
+ return object instanceof Hash;
+ },
+
+ isFunction: function(object) {
+ return typeof object == "function";
+ },
+
+ isString: function(object) {
+ return typeof object == "string";
+ },
+
+ isNumber: function(object) {
+ return typeof object == "number";
+ },
+
+ isUndefined: function(object) {
+ return typeof object == "undefined";
+ }
+});
+
+Object.extend(Function.prototype, {
+ argumentNames: function() {
+ var names = this.toString().match(/^[\s\(]*function[^(]*\((.*?)\)/)[1].split(",").invoke("strip");
+ return names.length == 1 && !names[0] ? [] : names;
+ },
+
+ bind: function() {
+ if (arguments.length < 2 && arguments[0] === undefined) return this;
+ var __method = this, args = $A(arguments), object = args.shift();
+ return function() {
+ return __method.apply(object, args.concat($A(arguments)));
+ }
+ },
+
+ bindAsEventListener: function() {
+ var __method = this, args = $A(arguments), object = args.shift();
+ return function(event) {
+ return __method.apply(object, [event || window.event].concat(args));
+ }
+ },
+
+ curry: function() {
+ if (!arguments.length) return this;
+ var __method = this, args = $A(arguments);
+ return function() {
+ return __method.apply(this, args.concat($A(arguments)));
+ }
+ },
+
+ delay: function() {
+ var __method = this, args = $A(arguments), timeout = args.shift() * 1000;
+ return window.setTimeout(function() {
+ return __method.apply(__method, args);
+ }, timeout);
+ },
+
+ wrap: function(wrapper) {
+ var __method = this;
+ return function() {
+ return wrapper.apply(this, [__method.bind(this)].concat($A(arguments)));
+ }
+ },
+
+ methodize: function() {
+ if (this._methodized) return this._methodized;
+ var __method = this;
+ return this._methodized = function() {
+ return __method.apply(null, [this].concat($A(arguments)));
+ };
+ }
+});
+
+Function.prototype.defer = Function.prototype.delay.curry(0.01);
+
+Date.prototype.toJSON = function() {
+ return '"' + this.getUTCFullYear() + '-' +
+ (this.getUTCMonth() + 1).toPaddedString(2) + '-' +
+ this.getUTCDate().toPaddedString(2) + 'T' +
+ this.getUTCHours().toPaddedString(2) + ':' +
+ this.getUTCMinutes().toPaddedString(2) + ':' +
+ this.getUTCSeconds().toPaddedString(2) + 'Z"';
+};
+
+var Try = {
+ these: function() {
+ var returnValue;
+
+ for (var i = 0, length = arguments.length; i < length; i++) {
+ var lambda = arguments[i];
+ try {
+ returnValue = lambda();
+ break;
+ } catch (e) { }
+ }
+
+ return returnValue;
+ }
+};
+
+RegExp.prototype.match = RegExp.prototype.test;
+
+RegExp.escape = function(str) {
+ return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
+};
+
+/*--------------------------------------------------------------------------*/
+
+var PeriodicalExecuter = Class.create({
+ initialize: function(callback, frequency) {
+ this.callback = callback;
+ this.frequency = frequency;
+ this.currentlyExecuting = false;
+
+ this.registerCallback();
+ },
+
+ registerCallback: function() {
+ this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
+ },
+
+ execute: function() {
+ this.callback(this);
+ },
+
+ stop: function() {
+ if (!this.timer) return;
+ clearInterval(this.timer);
+ this.timer = null;
+ },
+
+ onTimerEvent: function() {
+ if (!this.currentlyExecuting) {
+ try {
+ this.currentlyExecuting = true;
+ this.execute();
+ } finally {
+ this.currentlyExecuting = false;
+ }
+ }
+ }
+});
+Object.extend(String, {
+ interpret: function(value) {
+ return value == null ? '' : String(value);
+ },
+ specialChar: {
+ '\b': '\\b',
+ '\t': '\\t',
+ '\n': '\\n',
+ '\f': '\\f',
+ '\r': '\\r',
+ '\\': '\\\\'
+ }
+});
+
+Object.extend(String.prototype, {
+ gsub: function(pattern, replacement) {
+ var result = '', source = this, match;
+ replacement = arguments.callee.prepareReplacement(replacement);
+
+ while (source.length > 0) {
+ if (match = source.match(pattern)) {
+ result += source.slice(0, match.index);
+ result += String.interpret(replacement(match));
+ source = source.slice(match.index + match[0].length);
+ } else {
+ result += source, source = '';
+ }
+ }
+ return result;
+ },
+
+ sub: function(pattern, replacement, count) {
+ replacement = this.gsub.prepareReplacement(replacement);
+ count = count === undefined ? 1 : count;
+
+ return this.gsub(pattern, function(match) {
+ if (--count < 0) return match[0];
+ return replacement(match);
+ });
+ },
+
+ scan: function(pattern, iterator) {
+ this.gsub(pattern, iterator);
+ return String(this);
+ },
+
+ truncate: function(length, truncation) {
+ length = length || 30;
+ truncation = truncation === undefined ? '...' : truncation;
+ return this.length > length ?
+ this.slice(0, length - truncation.length) + truncation : String(this);
+ },
+
+ strip: function() {
+ return this.replace(/^\s+/, '').replace(/\s+$/, '');
+ },
+
+ stripTags: function() {
+ return this.replace(/<\/?[^>]+>/gi, '');
+ },
+
+ stripScripts: function() {
+ return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
+ },
+
+ extractScripts: function() {
+ var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
+ var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
+ return (this.match(matchAll) || []).map(function(scriptTag) {
+ return (scriptTag.match(matchOne) || ['', ''])[1];
+ });
+ },
+
+ evalScripts: function() {
+ return this.extractScripts().map(function(script) { return eval(script) });
+ },
+
+ escapeHTML: function() {
+ var self = arguments.callee;
+ self.text.data = this;
+ return self.div.innerHTML;
+ },
+
+ unescapeHTML: function() {
+ var div = new Element('div');
+ div.innerHTML = this.stripTags();
+ return div.childNodes[0] ? (div.childNodes.length > 1 ?
+ $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) :
+ div.childNodes[0].nodeValue) : '';
+ },
+
+ toQueryParams: function(separator) {
+ var match = this.strip().match(/([^?#]*)(#.*)?$/);
+ if (!match) return { };
+
+ return match[1].split(separator || '&').inject({ }, function(hash, pair) {
+ if ((pair = pair.split('='))[0]) {
+ var key = decodeURIComponent(pair.shift());
+ var value = pair.length > 1 ? pair.join('=') : pair[0];
+ if (value != undefined) value = decodeURIComponent(value);
+
+ if (key in hash) {
+ if (!Object.isArray(hash[key])) hash[key] = [hash[key]];
+ hash[key].push(value);
+ }
+ else hash[key] = value;
+ }
+ return hash;
+ });
+ },
+
+ toArray: function() {
+ return this.split('');
+ },
+
+ succ: function() {
+ return this.slice(0, this.length - 1) +
+ String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
+ },
+
+ times: function(count) {
+ return count < 1 ? '' : new Array(count + 1).join(this);
+ },
+
+ camelize: function() {
+ var parts = this.split('-'), len = parts.length;
+ if (len == 1) return parts[0];
+
+ var camelized = this.charAt(0) == '-'
+ ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)
+ : parts[0];
+
+ for (var i = 1; i < len; i++)
+ camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);
+
+ return camelized;
+ },
+
+ capitalize: function() {
+ return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
+ },
+
+ underscore: function() {
+ return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase();
+ },
+
+ dasherize: function() {
+ return this.gsub(/_/,'-');
+ },
+
+ inspect: function(useDoubleQuotes) {
+ var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) {
+ var character = String.specialChar[match[0]];
+ return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16);
+ });
+ if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
+ return "'" + escapedString.replace(/'/g, '\\\'') + "'";
+ },
+
+ toJSON: function() {
+ return this.inspect(true);
+ },
+
+ unfilterJSON: function(filter) {
+ return this.sub(filter || Prototype.JSONFilter, '#{1}');
+ },
+
+ isJSON: function() {
+ var str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
+ return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str);
+ },
+
+ evalJSON: function(sanitize) {
+ var json = this.unfilterJSON();
+ try {
+ if (!sanitize || json.isJSON()) return eval('(' + json + ')');
+ } catch (e) { }
+ throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
+ },
+
+ include: function(pattern) {
+ return this.indexOf(pattern) > -1;
+ },
+
+ startsWith: function(pattern) {
+ return this.indexOf(pattern) === 0;
+ },
+
+ endsWith: function(pattern) {
+ var d = this.length - pattern.length;
+ return d >= 0 && this.lastIndexOf(pattern) === d;
+ },
+
+ empty: function() {
+ return this == '';
+ },
+
+ blank: function() {
+ return /^\s*$/.test(this);
+ },
+
+ interpolate: function(object, pattern) {
+ return new Template(this, pattern).evaluate(object);
+ }
+});
+
+if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, {
+ escapeHTML: function() {
+ return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
+ },
+ unescapeHTML: function() {
+ return this.replace(/&amp;/g,'&').replace(/&lt;/g,'<').replace(/&gt;/g,'>');
+ }
+});
+
+String.prototype.gsub.prepareReplacement = function(replacement) {
+ if (Object.isFunction(replacement)) return replacement;
+ var template = new Template(replacement);
+ return function(match) { return template.evaluate(match) };
+};
+
+String.prototype.parseQuery = String.prototype.toQueryParams;
+
+Object.extend(String.prototype.escapeHTML, {
+ div: document.createElement('div'),
+ text: document.createTextNode('')
+});
+
+with (String.prototype.escapeHTML) div.appendChild(text);
+
+var Template = Class.create({
+ initialize: function(template, pattern) {
+ this.template = template.toString();
+ this.pattern = pattern || Template.Pattern;
+ },
+
+ evaluate: function(object) {
+ if (Object.isFunction(object.toTemplateReplacements))
+ object = object.toTemplateReplacements();
+
+ return this.template.gsub(this.pattern, function(match) {
+ if (object == null) return '';
+
+ var before = match[1] || '';
+ if (before == '\\') return match[2];
+
+ var ctx = object, expr = match[3];
+ var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/, match = pattern.exec(expr);
+ if (match == null) return before;
+
+ while (match != null) {
+ var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1];
+ ctx = ctx[comp];
+ if (null == ctx || '' == match[3]) break;
+ expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
+ match = pattern.exec(expr);
+ }
+
+ return before + String.interpret(ctx);
+ }.bind(this));
+ }
+});
+Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
+
+var $break = { };
+
+var Enumerable = {
+ each: function(iterator, context) {
+ var index = 0;
+ iterator = iterator.bind(context);
+ try {
+ this._each(function(value) {
+ iterator(value, index++);
+ });
+ } catch (e) {
+ if (e != $break) throw e;
+ }
+ return this;
+ },
+
+ eachSlice: function(number, iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var index = -number, slices = [], array = this.toArray();
+ while ((index += number) < array.length)
+ slices.push(array.slice(index, index+number));
+ return slices.collect(iterator, context);
+ },
+
+ all: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result = true;
+ this.each(function(value, index) {
+ result = result && !!iterator(value, index);
+ if (!result) throw $break;
+ });
+ return result;
+ },
+
+ any: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result = false;
+ this.each(function(value, index) {
+ if (result = !!iterator(value, index))
+ throw $break;
+ });
+ return result;
+ },
+
+ collect: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var results = [];
+ this.each(function(value, index) {
+ results.push(iterator(value, index));
+ });
+ return results;
+ },
+
+ detect: function(iterator, context) {
+ iterator = iterator.bind(context);
+ var result;
+ this.each(function(value, index) {
+ if (iterator(value, index)) {
+ result = value;
+ throw $break;
+ }
+ });
+ return result;
+ },
+
+ findAll: function(iterator, context) {
+ iterator = iterator.bind(context);
+ var results = [];
+ this.each(function(value, index) {
+ if (iterator(value, index))
+ results.push(value);
+ });
+ return results;
+ },
+
+ grep: function(filter, iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var results = [];
+
+ if (Object.isString(filter))
+ filter = new RegExp(filter);
+
+ this.each(function(value, index) {
+ if (filter.match(value))
+ results.push(iterator(value, index));
+ });
+ return results;
+ },
+
+ include: function(object) {
+ if (Object.isFunction(this.indexOf))
+ if (this.indexOf(object) != -1) return true;
+
+ var found = false;
+ this.each(function(value) {
+ if (value == object) {
+ found = true;
+ throw $break;
+ }
+ });
+ return found;
+ },
+
+ inGroupsOf: function(number, fillWith) {
+ fillWith = fillWith === undefined ? null : fillWith;
+ return this.eachSlice(number, function(slice) {
+ while(slice.length < number) slice.push(fillWith);
+ return slice;
+ });
+ },
+
+ inject: function(memo, iterator, context) {
+ iterator = iterator.bind(context);
+ this.each(function(value, index) {
+ memo = iterator(memo, value, index);
+ });
+ return memo;
+ },
+
+ invoke: function(method) {
+ var args = $A(arguments).slice(1);
+ return this.map(function(value) {
+ return value[method].apply(value, args);
+ });
+ },
+
+ max: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result;
+ this.each(function(value, index) {
+ value = iterator(value, index);
+ if (result == undefined || value >= result)
+ result = value;
+ });
+ return result;
+ },
+
+ min: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var result;
+ this.each(function(value, index) {
+ value = iterator(value, index);
+ if (result == undefined || value < result)
+ result = value;
+ });
+ return result;
+ },
+
+ partition: function(iterator, context) {
+ iterator = iterator ? iterator.bind(context) : Prototype.K;
+ var trues = [], falses = [];
+ this.each(function(value, index) {
+ (iterator(value, index) ?
+ trues : falses).push(value);
+ });
+ return [trues, falses];
+ },
+
+ pluck: function(property) {
+ var results = [];
+ this.each(function(value) {
+ results.push(value[property]);
+ });
+ return results;
+ },
+
+ reject: function(iterator, context) {
+ iterator = iterator.bind(context);
+ var results = [];
+ this.each(function(value, index) {
+ if (!iterator(value, index))
+ results.push(value);
+ });
+ return results;
+ },
+
+ sortBy: function(iterator, context) {
+ iterator = iterator.bind(context);
+ return this.map(function(value, index) {
+ return {value: value, criteria: iterator(value, index)};
+ }).sort(function(left, right) {
+ var a = left.criteria, b = right.criteria;
+ return a < b ? -1 : a > b ? 1 : 0;
+ }).pluck('value');
+ },
+
+ toArray: function() {
+ return this.map();
+ },
+
+ zip: function() {
+ var iterator = Prototype.K, args = $A(arguments);
+ if (Object.isFunction(args.last()))
+ iterator = args.pop();
+
+ var collections = [this].concat(args).map($A);
+ return this.map(function(value, index) {
+ return iterator(collections.pluck(index));
+ });
+ },
+
+ size: function() {
+ return this.toArray().length;
+ },
+
+ inspect: function() {
+ return '#<Enumerable:' + this.toArray().inspect() + '>';
+ }
+};
+
+Object.extend(Enumerable, {
+ map: Enumerable.collect,
+ find: Enumerable.detect,
+ select: Enumerable.findAll,
+ filter: Enumerable.findAll,
+ member: Enumerable.include,
+ entries: Enumerable.toArray,
+ every: Enumerable.all,
+ some: Enumerable.any
+});
+function $A(iterable) {
+ if (!iterable) return [];
+ if (iterable.toArray) return iterable.toArray();
+ var length = iterable.length, results = new Array(length);
+ while (length--) results[length] = iterable[length];
+ return results;
+}
+
+if (Prototype.Browser.WebKit) {
+ function $A(iterable) {
+ if (!iterable) return [];
+ if (!(Object.isFunction(iterable) && iterable == '[object NodeList]') &&
+ iterable.toArray) return iterable.toArray();
+ var length = iterable.length, results = new Array(length);
+ while (length--) results[length] = iterable[length];
+ return results;
+ }
+}
+
+Array.from = $A;
+
+Object.extend(Array.prototype, Enumerable);
+
+if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse;
+
+Object.extend(Array.prototype, {
+ _each: function(iterator) {
+ for (var i = 0, length = this.length; i < length; i++)
+ iterator(this[i]);
+ },
+
+ clear: function() {
+ this.length = 0;
+ return this;
+ },
+
+ first: function() {
+ return this[0];
+ },
+
+ last: function() {
+ return this[this.length - 1];
+ },
+
+ compact: function() {
+ return this.select(function(value) {
+ return value != null;
+ });
+ },
+
+ flatten: function() {
+ return this.inject([], function(array, value) {
+ return array.concat(Object.isArray(value) ?
+ value.flatten() : [value]);
+ });
+ },
+
+ without: function() {
+ var values = $A(arguments);
+ return this.select(function(value) {
+ return !values.include(value);
+ });
+ },
+
+ reverse: function(inline) {
+ return (inline !== false ? this : this.toArray())._reverse();
+ },
+
+ reduce: function() {
+ return this.length > 1 ? this : this[0];
+ },
+
+ uniq: function(sorted) {
+ return this.inject([], function(array, value, index) {
+ if (0 == index || (sorted ? array.last() != value : !array.include(value)))
+ array.push(value);
+ return array;
+ });
+ },
+
+ intersect: function(array) {
+ return this.uniq().findAll(function(item) {
+ return array.detect(function(value) { return item === value });
+ });
+ },
+
+ clone: function() {
+ return [].concat(this);
+ },
+
+ size: function() {
+ return this.length;
+ },
+
+ inspect: function() {
+ return '[' + this.map(Object.inspect).join(', ') + ']';
+ },
+
+ toJSON: function() {
+ var results = [];
+ this.each(function(object) {
+ var value = Object.toJSON(object);
+ if (value !== undefined) results.push(value);
+ });
+ return '[' + results.join(', ') + ']';
+ }
+});
+
+// use native browser JS 1.6 implementation if available
+if (Object.isFunction(Array.prototype.forEach))
+ Array.prototype._each = Array.prototype.forEach;
+
+if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) {
+ i || (i = 0);
+ var length = this.length;
+ if (i < 0) i = length + i;
+ for (; i < length; i++)
+ if (this[i] === item) return i;
+ return -1;
+};
+
+if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) {
+ i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;
+ var n = this.slice(0, i).reverse().indexOf(item);
+ return (n < 0) ? n : i - n - 1;
+};
+
+Array.prototype.toArray = Array.prototype.clone;
+
+function $w(string) {
+ if (!Object.isString(string)) return [];
+ string = string.strip();
+ return string ? string.split(/\s+/) : [];
+}
+
+if (Prototype.Browser.Opera){
+ Array.prototype.concat = function() {
+ var array = [];
+ for (var i = 0, length = this.length; i < length; i++) array.push(this[i]);
+ for (var i = 0, length = arguments.length; i < length; i++) {
+ if (Object.isArray(arguments[i])) {
+ for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
+ array.push(arguments[i][j]);
+ } else {
+ array.push(arguments[i]);
+ }
+ }
+ return array;
+ };
+}
+Object.extend(Number.prototype, {
+ toColorPart: function() {
+ return this.toPaddedString(2, 16);
+ },
+
+ succ: function() {
+ return this + 1;
+ },
+
+ times: function(iterator) {
+ $R(0, this, true).each(iterator);
+ return this;
+ },
+
+ toPaddedString: function(length, radix) {
+ var string = this.toString(radix || 10);
+ return '0'.times(length - string.length) + string;
+ },
+
+ toJSON: function() {
+ return isFinite(this) ? this.toString() : 'null';
+ }
+});
+
+$w('abs round ceil floor').each(function(method){
+ Number.prototype[method] = Math[method].methodize();
+});
+function $H(object) {
+ return new Hash(object);
+};
+
+var Hash = Class.create(Enumerable, (function() {
+ if (function() {
+ var i = 0, Test = function(value) { this.key = value };
+ Test.prototype.key = 'foo';
+ for (var property in new Test('bar')) i++;
+ return i > 1;
+ }()) {
+ function each(iterator) {
+ var cache = [];
+ for (var key in this._object) {
+ var value = this._object[key];
+ if (cache.include(key)) continue;
+ cache.push(key);
+ var pair = [key, value];
+ pair.key = key;
+ pair.value = value;
+ iterator(pair);
+ }
+ }
+ } else {
+ function each(iterator) {
+ for (var key in this._object) {
+ var value = this._object[key], pair = [key, value];
+ pair.key = key;
+ pair.value = value;
+ iterator(pair);
+ }
+ }
+ }
+
+ function toQueryPair(key, value) {
+ if (Object.isUndefined(value)) return key;
+ return key + '=' + encodeURIComponent(String.interpret(value));
+ }
+
+ return {
+ initialize: function(object) {
+ this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
+ },
+
+ _each: each,
+
+ set: function(key, value) {
+ return this._object[key] = value;
+ },
+
+ get: function(key) {
+ return this._object[key];
+ },
+
+ unset: function(key) {
+ var value = this._object[key];
+ delete this._object[key];
+ return value;
+ },
+
+ toObject: function() {
+ return Object.clone(this._object);
+ },
+
+ keys: function() {
+ return this.pluck('key');
+ },
+
+ values: function() {
+ return this.pluck('value');
+ },
+
+ index: function(value) {
+ var match = this.detect(function(pair) {
+ return pair.value === value;
+ });
+ return match && match.key;
+ },
+
+ merge: function(object) {
+ return this.clone().update(object);
+ },
+
+ update: function(object) {
+ return new Hash(object).inject(this, function(result, pair) {
+ result.set(pair.key, pair.value);
+ return result;
+ });
+ },
+
+ toQueryString: function() {
+ return this.map(function(pair) {
+ var key = encodeURIComponent(pair.key), values = pair.value;
+
+ if (values && typeof values == 'object') {
+ if (Object.isArray(values))
+ return values.map(toQueryPair.curry(key)).join('&');
+ }
+ return toQueryPair(key, values);
+ }).join('&');
+ },
+
+ inspect: function() {
+ return '#<Hash:{' + this.map(function(pair) {
+ return pair.map(Object.inspect).join(': ');
+ }).join(', ') + '}>';
+ },
+
+ toJSON: function() {
+ return Object.toJSON(this.toObject());
+ },
+
+ clone: function() {
+ return new Hash(this);
+ }
+ }
+})());
+
+Hash.prototype.toTemplateReplacements = Hash.prototype.toObject;
+Hash.from = $H;
+var ObjectRange = Class.create(Enumerable, {
+ initialize: function(start, end, exclusive) {
+ this.start = start;
+ this.end = end;
+ this.exclusive = exclusive;
+ },
+
+ _each: function(iterator) {
+ var value = this.start;
+ while (this.include(value)) {
+ iterator(value);
+ value = value.succ();
+ }
+ },
+
+ include: function(value) {
+ if (value < this.start)
+ return false;
+ if (this.exclusive)
+ return value < this.end;
+ return value <= this.end;
+ }
+});
+
+var $R = function(start, end, exclusive) {
+ return new ObjectRange(start, end, exclusive);
+};
+
+var Ajax = {
+ getTransport: function() {
+ return Try.these(
+ function() {return new XMLHttpRequest()},
+ function() {return new ActiveXObject('Msxml2.XMLHTTP')},
+ function() {return new ActiveXObject('Microsoft.XMLHTTP')}
+ ) || false;
+ },
+
+ activeRequestCount: 0
+};
+
+Ajax.Responders = {
+ responders: [],
+
+ _each: function(iterator) {
+ this.responders._each(iterator);
+ },
+
+ register: function(responder) {
+ if (!this.include(responder))
+ this.responders.push(responder);
+ },
+
+ unregister: function(responder) {
+ this.responders = this.responders.without(responder);
+ },
+
+ dispatch: function(callback, request, transport, json) {
+ this.each(function(responder) {
+ if (Object.isFunction(responder[callback])) {
+ try {
+ responder[callback].apply(responder, [request, transport, json]);
+ } catch (e) { }
+ }
+ });
+ }
+};
+
+Object.extend(Ajax.Responders, Enumerable);
+
+Ajax.Responders.register({
+ onCreate: function() { Ajax.activeRequestCount++ },
+ onComplete: function() { Ajax.activeRequestCount-- }
+});
+
+Ajax.Base = Class.create({
+ initialize: function(options) {
+ this.options = {
+ method: 'post',
+ asynchronous: true,
+ contentType: 'application/x-www-form-urlencoded',
+ encoding: 'UTF-8',
+ parameters: '',
+ evalJSON: true,
+ evalJS: true
+ };
+ Object.extend(this.options, options || { });
+
+ this.options.method = this.options.method.toLowerCase();
+ if (Object.isString(this.options.parameters))
+ this.options.parameters = this.options.parameters.toQueryParams();
+ }
+});
+
+Ajax.Request = Class.create(Ajax.Base, {
+ _complete: false,
+
+ initialize: function($super, url, options) {
+ $super(options);
+ this.transport = Ajax.getTransport();
+ this.request(url);
+ },
+
+ request: function(url) {
+ this.url = url;
+ this.method = this.options.method;
+ var params = Object.clone(this.options.parameters);
+
+ if (!['get', 'post'].include(this.method)) {
+ // simulate other verbs over post
+ params['_method'] = this.method;
+ this.method = 'post';
+ }
+
+ this.parameters = params;
+
+ if (params = Object.toQueryString(params)) {
+ // when GET, append parameters to URL
+ if (this.method == 'get')
+ this.url += (this.url.include('?') ? '&' : '?') + params;
+ else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))
+ params += '&_=';
+ }
+
+ try {
+ var response = new Ajax.Response(this);
+ if (this.options.onCreate) this.options.onCreate(response);
+ Ajax.Responders.dispatch('onCreate', this, response);
+
+ this.transport.open(this.method.toUpperCase(), this.url,
+ this.options.asynchronous);
+
+ if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);
+
+ this.transport.onreadystatechange = this.onStateChange.bind(this);
+ this.setRequestHeaders();
+
+ this.body = this.method == 'post' ? (this.options.postBody || params) : null;
+ this.transport.send(this.body);
+
+ /* Force Firefox to handle ready state 4 for synchronous requests */
+ if (!this.options.asynchronous && this.transport.overrideMimeType)
+ this.onStateChange();
+
+ }
+ catch (e) {
+ this.dispatchException(e);
+ }
+ },
+
+ onStateChange: function() {
+ var readyState = this.transport.readyState;
+ if (readyState > 1 && !((readyState == 4) && this._complete))
+ this.respondToReadyState(this.transport.readyState);
+ },
+
+ setRequestHeaders: function() {
+ var headers = {
+ 'X-Requested-With': 'XMLHttpRequest',
+ 'X-Prototype-Version': Prototype.Version,
+ 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
+ };
+
+ if (this.method == 'post') {
+ headers['Content-type'] = this.options.contentType +
+ (this.options.encoding ? '; charset=' + this.options.encoding : '');
+
+ /* Force "Connection: close" for older Mozilla browsers to work
+ * around a bug where XMLHttpRequest sends an incorrect
+ * Content-length header. See Mozilla Bugzilla #246651.
+ */
+ if (this.transport.overrideMimeType &&
+ (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
+ headers['Connection'] = 'close';
+ }
+
+ // user-defined headers
+ if (typeof this.options.requestHeaders == 'object') {
+ var extras = this.options.requestHeaders;
+
+ if (Object.isFunction(extras.push))
+ for (var i = 0, length = extras.length; i < length; i += 2)
+ headers[extras[i]] = extras[i+1];
+ else
+ $H(extras).each(function(pair) { headers[pair.key] = pair.value });
+ }
+
+ for (var name in headers)
+ this.transport.setRequestHeader(name, headers[name]);
+ },
+
+ success: function() {
+ var status = this.getStatus();
+ return !status || (status >= 200 && status < 300);
+ },
+
+ getStatus: function() {
+ try {
+ return this.transport.status || 0;
+ } catch (e) { return 0 }
+ },
+
+ respondToReadyState: function(readyState) {
+ var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this);
+
+ if (state == 'Complete') {
+ try {
+ this._complete = true;
+ (this.options['on' + response.status]
+ || this.options['on' + (this.success() ? 'Success' : 'Failure')]
+ || Prototype.emptyFunction)(response, response.headerJSON);
+ } catch (e) {
+ this.dispatchException(e);
+ }
+
+ var contentType = response.getHeader('Content-type');
+ if (this.options.evalJS == 'force'
+ || (this.options.evalJS && contentType
+ && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i)))
+ this.evalResponse();
+ }
+
+ try {
+ (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON);
+ Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON);
+ } catch (e) {
+ this.dispatchException(e);
+ }
+
+ if (state == 'Complete') {
+ // avoid memory leak in MSIE: clean up
+ this.transport.onreadystatechange = Prototype.emptyFunction;
+ }
+ },
+
+ getHeader: function(name) {
+ try {
+ return this.transport.getResponseHeader(name);
+ } catch (e) { return null }
+ },
+
+ evalResponse: function() {
+ try {
+ return eval((this.transport.responseText || '').unfilterJSON());
+ } catch (e) {
+ this.dispatchException(e);
+ }
+ },
+
+ dispatchException: function(exception) {
+ (this.options.onException || Prototype.emptyFunction)(this, exception);
+ Ajax.Responders.dispatch('onException', this, exception);
+ }
+});
+
+Ajax.Request.Events =
+ ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
+
+Ajax.Response = Class.create({
+ initialize: function(request){
+ this.request = request;
+ var transport = this.transport = request.transport,
+ readyState = this.readyState = transport.readyState;
+
+ if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) {
+ this.status = this.getStatus();
+ this.statusText = this.getStatusText();
+ this.responseText = String.interpret(transport.responseText);
+ this.headerJSON = this._getHeaderJSON();
+ }
+
+ if(readyState == 4) {
+ var xml = transport.responseXML;
+ this.responseXML = xml === undefined ? null : xml;
+ this.responseJSON = this._getResponseJSON();
+ }
+ },
+
+ status: 0,
+ statusText: '',
+
+ getStatus: Ajax.Request.prototype.getStatus,
+
+ getStatusText: function() {
+ try {
+ return this.transport.statusText || '';
+ } catch (e) { return '' }
+ },
+
+ getHeader: Ajax.Request.prototype.getHeader,
+
+ getAllHeaders: function() {
+ try {
+ return this.getAllResponseHeaders();
+ } catch (e) { return null }
+ },
+
+ getResponseHeader: function(name) {
+ return this.transport.getResponseHeader(name);
+ },
+
+ getAllResponseHeaders: function() {
+ return this.transport.getAllResponseHeaders();
+ },
+
+ _getHeaderJSON: function() {
+ var json = this.getHeader('X-JSON');
+ if (!json) return null;
+ json = decodeURIComponent(escape(json));
+ try {
+ return json.evalJSON(this.request.options.sanitizeJSON);
+ } catch (e) {
+ this.request.dispatchException(e);
+ }
+ },
+
+ _getResponseJSON: function() {
+ var options = this.request.options;
+ if (!options.evalJSON || (options.evalJSON != 'force' &&
+ !(this.getHeader('Content-type') || '').include('application/json')))
+ return null;
+ try {
+ return this.transport.responseText.evalJSON(options.sanitizeJSON);
+ } catch (e) {
+ this.request.dispatchException(e);
+ }
+ }
+});
+
+Ajax.Updater = Class.create(Ajax.Request, {
+ initialize: function($super, container, url, options) {
+ this.container = {
+ success: (container.success || container),
+ failure: (container.failure || (container.success ? null : container))
+ };
+
+ options = options || { };
+ var onComplete = options.onComplete;
+ options.onComplete = (function(response, param) {
+ this.updateContent(response.responseText);
+ if (Object.isFunction(onComplete)) onComplete(response, param);
+ }).bind(this);
+
+ $super(url, options);
+ },
+
+ updateContent: function(responseText) {
+ var receiver = this.container[this.success() ? 'success' : 'failure'],
+ options = this.options;
+
+ if (!options.evalScripts) responseText = responseText.stripScripts();
+
+ if (receiver = $(receiver)) {
+ if (options.insertion) {
+ if (Object.isString(options.insertion)) {
+ var insertion = { }; insertion[options.insertion] = responseText;
+ receiver.insert(insertion);
+ }
+ else options.insertion(receiver, responseText);
+ }
+ else receiver.update(responseText);
+ }
+
+ if (this.success()) {
+ if (this.onComplete) this.onComplete.bind(this).defer();
+ }
+ }
+});
+
+Ajax.PeriodicalUpdater = Class.create(Ajax.Base, {
+ initialize: function($super, container, url, options) {
+ $super(options);
+ this.onComplete = this.options.onComplete;
+
+ this.frequency = (this.options.frequency || 2);
+ this.decay = (this.options.decay || 1);
+
+ this.updater = { };
+ this.container = container;
+ this.url = url;
+
+ this.start();
+ },
+
+ start: function() {
+ this.options.onComplete = this.updateComplete.bind(this);
+ this.onTimerEvent();
+ },
+
+ stop: function() {
+ this.updater.options.onComplete = undefined;
+ clearTimeout(this.timer);
+ (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
+ },
+
+ updateComplete: function(response) {
+ if (this.options.decay) {
+ this.decay = (response.responseText == this.lastText ?
+ this.decay * this.options.decay : 1);
+
+ this.lastText = response.responseText;
+ }
+ this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency);
+ },
+
+ onTimerEvent: function() {
+ this.updater = new Ajax.Updater(this.container, this.url, this.options);
+ }
+});
+function $(element) {
+ if (arguments.length > 1) {
+ for (var i = 0, elements = [], length = arguments.length; i < length; i++)
+ elements.push($(arguments[i]));
+ return elements;
+ }
+ if (Object.isString(element))
+ element = document.getElementById(element);
+ return Element.extend(element);
+}
+
+if (Prototype.BrowserFeatures.XPath) {
+ document._getElementsByXPath = function(expression, parentElement) {
+ var results = [];
+ var query = document.evaluate(expression, $(parentElement) || document,
+ null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
+ for (var i = 0, length = query.snapshotLength; i < length; i++)
+ results.push(Element.extend(query.snapshotItem(i)));
+ return results;
+ };
+}
+
+/*--------------------------------------------------------------------------*/
+
+if (!window.Node) var Node = { };
+
+if (!Node.ELEMENT_NODE) {
+ // DOM level 2 ECMAScript Language Binding
+ Object.extend(Node, {
+ ELEMENT_NODE: 1,
+ ATTRIBUTE_NODE: 2,
+ TEXT_NODE: 3,
+ CDATA_SECTION_NODE: 4,
+ ENTITY_REFERENCE_NODE: 5,
+ ENTITY_NODE: 6,
+ PROCESSING_INSTRUCTION_NODE: 7,
+ COMMENT_NODE: 8,
+ DOCUMENT_NODE: 9,
+ DOCUMENT_TYPE_NODE: 10,
+ DOCUMENT_FRAGMENT_NODE: 11,
+ NOTATION_NODE: 12
+ });
+}
+
+(function() {
+ var element = this.Element;
+ this.Element = function(tagName, attributes) {
+ attributes = attributes || { };
+ tagName = tagName.toLowerCase();
+ var cache = Element.cache;
+ if (Prototype.Browser.IE && attributes.name) {
+ tagName = '<' + tagName + ' name="' + attributes.name + '">';
+ delete attributes.name;
+ return Element.writeAttribute(document.createElement(tagName), attributes);
+ }
+ if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName));
+ return Element.writeAttribute(cache[tagName].cloneNode(false), attributes);
+ };
+ Object.extend(this.Element, element || { });
+}).call(window);
+
+Element.cache = { };
+
+Element.Methods = {
+ visible: function(element) {
+ return $(element).style.display != 'none';
+ },
+
+ toggle: function(element) {
+ element = $(element);
+ Element[Element.visible(element) ? 'hide' : 'show'](element);
+ return element;
+ },
+
+ hide: function(element) {
+ $(element).style.display = 'none';
+ return element;
+ },
+
+ show: function(element) {
+ $(element).style.display = '';
+ return element;
+ },
+
+ remove: function(element) {
+ element = $(element);
+ element.parentNode.removeChild(element);
+ return element;
+ },
+
+ update: function(element, content) {
+ element = $(element);
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) return element.update().insert(content);
+ content = Object.toHTML(content);
+ element.innerHTML = content.stripScripts();
+ content.evalScripts.bind(content).defer();
+ return element;
+ },
+
+ replace: function(element, content) {
+ element = $(element);
+ if (content && content.toElement) content = content.toElement();
+ else if (!Object.isElement(content)) {
+ content = Object.toHTML(content);
+ var range = element.ownerDocument.createRange();
+ range.selectNode(element);
+ content.evalScripts.bind(content).defer();
+ content = range.createContextualFragment(content.stripScripts());
+ }
+ element.parentNode.replaceChild(content, element);
+ return element;
+ },
+
+ insert: function(element, insertions) {
+ element = $(element);
+
+ if (Object.isString(insertions) || Object.isNumber(insertions) ||
+ Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML)))
+ insertions = {bottom:insertions};
+
+ var content, t, range;
+
+ for (position in insertions) {
+ content = insertions[position];
+ position = position.toLowerCase();
+ t = Element._insertionTranslations[position];
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) {
+ t.insert(element, content);
+ continue;
+ }
+
+ content = Object.toHTML(content);
+
+ range = element.ownerDocument.createRange();
+ t.initializeRange(element, range);
+ t.insert(element, range.createContextualFragment(content.stripScripts()));
+
+ content.evalScripts.bind(content).defer();
+ }
+
+ return element;
+ },
+
+ wrap: function(element, wrapper, attributes) {
+ element = $(element);
+ if (Object.isElement(wrapper))
+ $(wrapper).writeAttribute(attributes || { });
+ else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes);
+ else wrapper = new Element('div', wrapper);
+ if (element.parentNode)
+ element.parentNode.replaceChild(wrapper, element);
+ wrapper.appendChild(element);
+ return wrapper;
+ },
+
+ inspect: function(element) {
+ element = $(element);
+ var result = '<' + element.tagName.toLowerCase();
+ $H({'id': 'id', 'className': 'class'}).each(function(pair) {
+ var property = pair.first(), attribute = pair.last();
+ var value = (element[property] || '').toString();
+ if (value) result += ' ' + attribute + '=' + value.inspect(true);
+ });
+ return result + '>';
+ },
+
+ recursivelyCollect: function(element, property) {
+ element = $(element);
+ var elements = [];
+ while (element = element[property])
+ if (element.nodeType == 1)
+ elements.push(Element.extend(element));
+ return elements;
+ },
+
+ ancestors: function(element) {
+ return $(element).recursivelyCollect('parentNode');
+ },
+
+ descendants: function(element) {
+ return $A($(element).getElementsByTagName('*')).each(Element.extend);
+ },
+
+ firstDescendant: function(element) {
+ element = $(element).firstChild;
+ while (element && element.nodeType != 1) element = element.nextSibling;
+ return $(element);
+ },
+
+ immediateDescendants: function(element) {
+ if (!(element = $(element).firstChild)) return [];
+ while (element && element.nodeType != 1) element = element.nextSibling;
+ if (element) return [element].concat($(element).nextSiblings());
+ return [];
+ },
+
+ previousSiblings: function(element) {
+ return $(element).recursivelyCollect('previousSibling');
+ },
+
+ nextSiblings: function(element) {
+ return $(element).recursivelyCollect('nextSibling');
+ },
+
+ siblings: function(element) {
+ element = $(element);
+ return element.previousSiblings().reverse().concat(element.nextSiblings());
+ },
+
+ match: function(element, selector) {
+ if (Object.isString(selector))
+ selector = new Selector(selector);
+ return selector.match($(element));
+ },
+
+ up: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(element.parentNode);
+ var ancestors = element.ancestors();
+ return expression ? Selector.findElement(ancestors, expression, index) :
+ ancestors[index || 0];
+ },
+
+ down: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return element.firstDescendant();
+ var descendants = element.descendants();
+ return expression ? Selector.findElement(descendants, expression, index) :
+ descendants[index || 0];
+ },
+
+ previous: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element));
+ var previousSiblings = element.previousSiblings();
+ return expression ? Selector.findElement(previousSiblings, expression, index) :
+ previousSiblings[index || 0];
+ },
+
+ next: function(element, expression, index) {
+ element = $(element);
+ if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element));
+ var nextSiblings = element.nextSiblings();
+ return expression ? Selector.findElement(nextSiblings, expression, index) :
+ nextSiblings[index || 0];
+ },
+
+ select: function() {
+ var args = $A(arguments), element = $(args.shift());
+ return Selector.findChildElements(element, args);
+ },
+
+ adjacent: function() {
+ var args = $A(arguments), element = $(args.shift());
+ return Selector.findChildElements(element.parentNode, args).without(element);
+ },
+
+ identify: function(element) {
+ element = $(element);
+ var id = element.readAttribute('id'), self = arguments.callee;
+ if (id) return id;
+ do { id = 'anonymous_element_' + self.counter++ } while ($(id));
+ element.writeAttribute('id', id);
+ return id;
+ },
+
+ readAttribute: function(element, name) {
+ element = $(element);
+ if (Prototype.Browser.IE) {
+ var t = Element._attributeTranslations.read;
+ if (t.values[name]) return t.values[name](element, name);
+ if (t.names[name]) name = t.names[name];
+ if (name.include(':')) {
+ return (!element.attributes || !element.attributes[name]) ? null :
+ element.attributes[name].value;
+ }
+ }
+ return element.getAttribute(name);
+ },
+
+ writeAttribute: function(element, name, value) {
+ element = $(element);
+ var attributes = { }, t = Element._attributeTranslations.write;
+
+ if (typeof name == 'object') attributes = name;
+ else attributes[name] = value === undefined ? true : value;
+
+ for (var attr in attributes) {
+ var name = t.names[attr] || attr, value = attributes[attr];
+ if (t.values[attr]) name = t.values[attr](element, value);
+ if (value === false || value === null)
+ element.removeAttribute(name);
+ else if (value === true)
+ element.setAttribute(name, name);
+ else element.setAttribute(name, value);
+ }
+ return element;
+ },
+
+ getHeight: function(element) {
+ return $(element).getDimensions().height;
+ },
+
+ getWidth: function(element) {
+ return $(element).getDimensions().width;
+ },
+
+ classNames: function(element) {
+ return new Element.ClassNames(element);
+ },
+
+ hasClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ var elementClassName = element.className;
+ return (elementClassName.length > 0 && (elementClassName == className ||
+ new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName)));
+ },
+
+ addClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ if (!element.hasClassName(className))
+ element.className += (element.className ? ' ' : '') + className;
+ return element;
+ },
+
+ removeClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ element.className = element.className.replace(
+ new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip();
+ return element;
+ },
+
+ toggleClassName: function(element, className) {
+ if (!(element = $(element))) return;
+ return element[element.hasClassName(className) ?
+ 'removeClassName' : 'addClassName'](className);
+ },
+
+ // removes whitespace-only text node children
+ cleanWhitespace: function(element) {
+ element = $(element);
+ var node = element.firstChild;
+ while (node) {
+ var nextNode = node.nextSibling;
+ if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
+ element.removeChild(node);
+ node = nextNode;
+ }
+ return element;
+ },
+
+ empty: function(element) {
+ return $(element).innerHTML.blank();
+ },
+
+ descendantOf: function(element, ancestor) {
+ element = $(element), ancestor = $(ancestor);
+
+ if (element.compareDocumentPosition)
+ return (element.compareDocumentPosition(ancestor) & 8) === 8;
+
+ if (element.sourceIndex && !Prototype.Browser.Opera) {
+ var e = element.sourceIndex, a = ancestor.sourceIndex,
+ nextAncestor = ancestor.nextSibling;
+ if (!nextAncestor) {
+ do { ancestor = ancestor.parentNode; }
+ while (!(nextAncestor = ancestor.nextSibling) && ancestor.parentNode);
+ }
+ if (nextAncestor) return (e > a && e < nextAncestor.sourceIndex);
+ }
+
+ while (element = element.parentNode)
+ if (element == ancestor) return true;
+ return false;
+ },
+
+ scrollTo: function(element) {
+ element = $(element);
+ var pos = element.cumulativeOffset();
+ window.scrollTo(pos[0], pos[1]);
+ return element;
+ },
+
+ getStyle: function(element, style) {
+ element = $(element);
+ style = style == 'float' ? 'cssFloat' : style.camelize();
+ var value = element.style[style];
+ if (!value) {
+ var css = document.defaultView.getComputedStyle(element, null);
+ value = css ? css[style] : null;
+ }
+ if (style == 'opacity') return value ? parseFloat(value) : 1.0;
+ return value == 'auto' ? null : value;
+ },
+
+ getOpacity: function(element) {
+ return $(element).getStyle('opacity');
+ },
+
+ setStyle: function(element, styles) {
+ element = $(element);
+ var elementStyle = element.style, match;
+ if (Object.isString(styles)) {
+ element.style.cssText += ';' + styles;
+ return styles.include('opacity') ?
+ element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element;
+ }
+ for (var property in styles)
+ if (property == 'opacity') element.setOpacity(styles[property]);
+ else
+ elementStyle[(property == 'float' || property == 'cssFloat') ?
+ (elementStyle.styleFloat === undefined ? 'cssFloat' : 'styleFloat') :
+ property] = styles[property];
+
+ return element;
+ },
+
+ setOpacity: function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1 || value === '') ? '' :
+ (value < 0.00001) ? 0 : value;
+ return element;
+ },
+
+ getDimensions: function(element) {
+ element = $(element);
+ var display = $(element).getStyle('display');
+ if (display != 'none' && display != null) // Safari bug
+ return {width: element.offsetWidth, height: element.offsetHeight};
+
+ // All *Width and *Height properties give 0 on elements with display none,
+ // so enable the element temporarily
+ var els = element.style;
+ var originalVisibility = els.visibility;
+ var originalPosition = els.position;
+ var originalDisplay = els.display;
+ els.visibility = 'hidden';
+ els.position = 'absolute';
+ els.display = 'block';
+ var originalWidth = element.clientWidth;
+ var originalHeight = element.clientHeight;
+ els.display = originalDisplay;
+ els.position = originalPosition;
+ els.visibility = originalVisibility;
+ return {width: originalWidth, height: originalHeight};
+ },
+
+ makePositioned: function(element) {
+ element = $(element);
+ var pos = Element.getStyle(element, 'position');
+ if (pos == 'static' || !pos) {
+ element._madePositioned = true;
+ element.style.position = 'relative';
+ // Opera returns the offset relative to the positioning context, when an
+ // element is position relative but top and left have not been defined
+ if (window.opera) {
+ element.style.top = 0;
+ element.style.left = 0;
+ }
+ }
+ return element;
+ },
+
+ undoPositioned: function(element) {
+ element = $(element);
+ if (element._madePositioned) {
+ element._madePositioned = undefined;
+ element.style.position =
+ element.style.top =
+ element.style.left =
+ element.style.bottom =
+ element.style.right = '';
+ }
+ return element;
+ },
+
+ makeClipping: function(element) {
+ element = $(element);
+ if (element._overflow) return element;
+ element._overflow = Element.getStyle(element, 'overflow') || 'auto';
+ if (element._overflow !== 'hidden')
+ element.style.overflow = 'hidden';
+ return element;
+ },
+
+ undoClipping: function(element) {
+ element = $(element);
+ if (!element._overflow) return element;
+ element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
+ element._overflow = null;
+ return element;
+ },
+
+ cumulativeOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ positionedOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ if (element) {
+ if (element.tagName == 'BODY') break;
+ var p = Element.getStyle(element, 'position');
+ if (p == 'relative' || p == 'absolute') break;
+ }
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ absolutize: function(element) {
+ element = $(element);
+ if (element.getStyle('position') == 'absolute') return;
+ // Position.prepare(); // To be done manually by Scripty when it needs it.
+
+ var offsets = element.positionedOffset();
+ var top = offsets[1];
+ var left = offsets[0];
+ var width = element.clientWidth;
+ var height = element.clientHeight;
+
+ element._originalLeft = left - parseFloat(element.style.left || 0);
+ element._originalTop = top - parseFloat(element.style.top || 0);
+ element._originalWidth = element.style.width;
+ element._originalHeight = element.style.height;
+
+ element.style.position = 'absolute';
+ element.style.top = top + 'px';
+ element.style.left = left + 'px';
+ element.style.width = width + 'px';
+ element.style.height = height + 'px';
+ return element;
+ },
+
+ relativize: function(element) {
+ element = $(element);
+ if (element.getStyle('position') == 'relative') return;
+ // Position.prepare(); // To be done manually by Scripty when it needs it.
+
+ element.style.position = 'relative';
+ var top = parseFloat(element.style.top || 0) - (element._originalTop || 0);
+ var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
+
+ element.style.top = top + 'px';
+ element.style.left = left + 'px';
+ element.style.height = element._originalHeight;
+ element.style.width = element._originalWidth;
+ return element;
+ },
+
+ cumulativeScrollOffset: function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.scrollTop || 0;
+ valueL += element.scrollLeft || 0;
+ element = element.parentNode;
+ } while (element);
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ getOffsetParent: function(element) {
+ if (element.offsetParent) return $(element.offsetParent);
+ if (element == document.body) return $(element);
+
+ while ((element = element.parentNode) && element != document.body)
+ if (Element.getStyle(element, 'position') != 'static')
+ return $(element);
+
+ return $(document.body);
+ },
+
+ viewportOffset: function(forElement) {
+ var valueT = 0, valueL = 0;
+
+ var element = forElement;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+
+ // Safari fix
+ if (element.offsetParent == document.body &&
+ Element.getStyle(element, 'position') == 'absolute') break;
+
+ } while (element = element.offsetParent);
+
+ element = forElement;
+ do {
+ if (!Prototype.Browser.Opera || element.tagName == 'BODY') {
+ valueT -= element.scrollTop || 0;
+ valueL -= element.scrollLeft || 0;
+ }
+ } while (element = element.parentNode);
+
+ return Element._returnOffset(valueL, valueT);
+ },
+
+ clonePosition: function(element, source) {
+ var options = Object.extend({
+ setLeft: true,
+ setTop: true,
+ setWidth: true,
+ setHeight: true,
+ offsetTop: 0,
+ offsetLeft: 0
+ }, arguments[2] || { });
+
+ // find page position of source
+ source = $(source);
+ var p = source.viewportOffset();
+
+ // find coordinate system to use
+ element = $(element);
+ var delta = [0, 0];
+ var parent = null;
+ // delta [0,0] will do fine with position: fixed elements,
+ // position:absolute needs offsetParent deltas
+ if (Element.getStyle(element, 'position') == 'absolute') {
+ parent = element.getOffsetParent();
+ delta = parent.viewportOffset();
+ }
+
+ // correct by body offsets (fixes Safari)
+ if (parent == document.body) {
+ delta[0] -= document.body.offsetLeft;
+ delta[1] -= document.body.offsetTop;
+ }
+
+ // set position
+ if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px';
+ if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px';
+ if (options.setWidth) element.style.width = source.offsetWidth + 'px';
+ if (options.setHeight) element.style.height = source.offsetHeight + 'px';
+ return element;
+ }
+};
+
+Element.Methods.identify.counter = 1;
+
+Object.extend(Element.Methods, {
+ getElementsBySelector: Element.Methods.select,
+ childElements: Element.Methods.immediateDescendants
+});
+
+Element._attributeTranslations = {
+ write: {
+ names: {
+ className: 'class',
+ htmlFor: 'for'
+ },
+ values: { }
+ }
+};
+
+
+if (!document.createRange || Prototype.Browser.Opera) {
+ Element.Methods.insert = function(element, insertions) {
+ element = $(element);
+
+ if (Object.isString(insertions) || Object.isNumber(insertions) ||
+ Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML)))
+ insertions = { bottom: insertions };
+
+ var t = Element._insertionTranslations, content, position, pos, tagName;
+
+ for (position in insertions) {
+ content = insertions[position];
+ position = position.toLowerCase();
+ pos = t[position];
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) {
+ pos.insert(element, content);
+ continue;
+ }
+
+ content = Object.toHTML(content);
+ tagName = ((position == 'before' || position == 'after')
+ ? element.parentNode : element).tagName.toUpperCase();
+
+ if (t.tags[tagName]) {
+ var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
+ if (position == 'top' || position == 'after') fragments.reverse();
+ fragments.each(pos.insert.curry(element));
+ }
+ else element.insertAdjacentHTML(pos.adjacency, content.stripScripts());
+
+ content.evalScripts.bind(content).defer();
+ }
+
+ return element;
+ };
+}
+
+if (Prototype.Browser.Opera) {
+ Element.Methods._getStyle = Element.Methods.getStyle;
+ Element.Methods.getStyle = function(element, style) {
+ switch(style) {
+ case 'left':
+ case 'top':
+ case 'right':
+ case 'bottom':
+ if (Element._getStyle(element, 'position') == 'static') return null;
+ default: return Element._getStyle(element, style);
+ }
+ };
+ Element.Methods._readAttribute = Element.Methods.readAttribute;
+ Element.Methods.readAttribute = function(element, attribute) {
+ if (attribute == 'title') return element.title;
+ return Element._readAttribute(element, attribute);
+ };
+}
+
+else if (Prototype.Browser.IE) {
+ $w('positionedOffset getOffsetParent viewportOffset').each(function(method) {
+ Element.Methods[method] = Element.Methods[method].wrap(
+ function(proceed, element) {
+ element = $(element);
+ var position = element.getStyle('position');
+ if (position != 'static') return proceed(element);
+ element.setStyle({ position: 'relative' });
+ var value = proceed(element);
+ element.setStyle({ position: position });
+ return value;
+ }
+ );
+ });
+
+ Element.Methods.getStyle = function(element, style) {
+ element = $(element);
+ style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize();
+ var value = element.style[style];
+ if (!value && element.currentStyle) value = element.currentStyle[style];
+
+ if (style == 'opacity') {
+ if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
+ if (value[1]) return parseFloat(value[1]) / 100;
+ return 1.0;
+ }
+
+ if (value == 'auto') {
+ if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none'))
+ return element['offset' + style.capitalize()] + 'px';
+ return null;
+ }
+ return value;
+ };
+
+ Element.Methods.setOpacity = function(element, value) {
+ function stripAlpha(filter){
+ return filter.replace(/alpha\([^\)]*\)/gi,'');
+ }
+ element = $(element);
+ var currentStyle = element.currentStyle;
+ if ((currentStyle && !currentStyle.hasLayout) ||
+ (!currentStyle && element.style.zoom == 'normal'))
+ element.style.zoom = 1;
+
+ var filter = element.getStyle('filter'), style = element.style;
+ if (value == 1 || value === '') {
+ (filter = stripAlpha(filter)) ?
+ style.filter = filter : style.removeAttribute('filter');
+ return element;
+ } else if (value < 0.00001) value = 0;
+ style.filter = stripAlpha(filter) +
+ 'alpha(opacity=' + (value * 100) + ')';
+ return element;
+ };
+
+ Element._attributeTranslations = {
+ read: {
+ names: {
+ 'class': 'className',
+ 'for': 'htmlFor'
+ },
+ values: {
+ _getAttr: function(element, attribute) {
+ return element.getAttribute(attribute, 2);
+ },
+ _getAttrNode: function(element, attribute) {
+ var node = element.getAttributeNode(attribute);
+ return node ? node.value : "";
+ },
+ _getEv: function(element, attribute) {
+ var attribute = element.getAttribute(attribute);
+ return attribute ? attribute.toString().slice(23, -2) : null;
+ },
+ _flag: function(element, attribute) {
+ return $(element).hasAttribute(attribute) ? attribute : null;
+ },
+ style: function(element) {
+ return element.style.cssText.toLowerCase();
+ },
+ title: function(element) {
+ return element.title;
+ }
+ }
+ }
+ };
+
+ Element._attributeTranslations.write = {
+ names: Object.clone(Element._attributeTranslations.read.names),
+ values: {
+ checked: function(element, value) {
+ element.checked = !!value;
+ },
+
+ style: function(element, value) {
+ element.style.cssText = value ? value : '';
+ }
+ }
+ };
+
+ Element._attributeTranslations.has = {};
+
+ $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' +
+ 'encType maxLength readOnly longDesc').each(function(attr) {
+ Element._attributeTranslations.write.names[attr.toLowerCase()] = attr;
+ Element._attributeTranslations.has[attr.toLowerCase()] = attr;
+ });
+
+ (function(v) {
+ Object.extend(v, {
+ href: v._getAttr,
+ src: v._getAttr,
+ type: v._getAttr,
+ action: v._getAttrNode,
+ disabled: v._flag,
+ checked: v._flag,
+ readonly: v._flag,
+ multiple: v._flag,
+ onload: v._getEv,
+ onunload: v._getEv,
+ onclick: v._getEv,
+ ondblclick: v._getEv,
+ onmousedown: v._getEv,
+ onmouseup: v._getEv,
+ onmouseover: v._getEv,
+ onmousemove: v._getEv,
+ onmouseout: v._getEv,
+ onfocus: v._getEv,
+ onblur: v._getEv,
+ onkeypress: v._getEv,
+ onkeydown: v._getEv,
+ onkeyup: v._getEv,
+ onsubmit: v._getEv,
+ onreset: v._getEv,
+ onselect: v._getEv,
+ onchange: v._getEv
+ });
+ })(Element._attributeTranslations.read.values);
+}
+
+else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) {
+ Element.Methods.setOpacity = function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1) ? 0.999999 :
+ (value === '') ? '' : (value < 0.00001) ? 0 : value;
+ return element;
+ };
+}
+
+else if (Prototype.Browser.WebKit) {
+ Element.Methods.setOpacity = function(element, value) {
+ element = $(element);
+ element.style.opacity = (value == 1 || value === '') ? '' :
+ (value < 0.00001) ? 0 : value;
+
+ if (value == 1)
+ if(element.tagName == 'IMG' && element.width) {
+ element.width++; element.width--;
+ } else try {
+ var n = document.createTextNode(' ');
+ element.appendChild(n);
+ element.removeChild(n);
+ } catch (e) { }
+
+ return element;
+ };
+
+ // Safari returns margins on body which is incorrect if the child is absolutely
+ // positioned. For performance reasons, redefine Position.cumulativeOffset for
+ // KHTML/WebKit only.
+ Element.Methods.cumulativeOffset = function(element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ if (element.offsetParent == document.body)
+ if (Element.getStyle(element, 'position') == 'absolute') break;
+
+ element = element.offsetParent;
+ } while (element);
+
+ return Element._returnOffset(valueL, valueT);
+ };
+}
+
+if (Prototype.Browser.IE || Prototype.Browser.Opera) {
+ // IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements
+ Element.Methods.update = function(element, content) {
+ element = $(element);
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) return element.update().insert(content);
+
+ content = Object.toHTML(content);
+ var tagName = element.tagName.toUpperCase();
+
+ if (tagName in Element._insertionTranslations.tags) {
+ $A(element.childNodes).each(function(node) { element.removeChild(node) });
+ Element._getContentFromAnonymousElement(tagName, content.stripScripts())
+ .each(function(node) { element.appendChild(node) });
+ }
+ else element.innerHTML = content.stripScripts();
+
+ content.evalScripts.bind(content).defer();
+ return element;
+ };
+}
+
+if (document.createElement('div').outerHTML) {
+ Element.Methods.replace = function(element, content) {
+ element = $(element);
+
+ if (content && content.toElement) content = content.toElement();
+ if (Object.isElement(content)) {
+ element.parentNode.replaceChild(content, element);
+ return element;
+ }
+
+ content = Object.toHTML(content);
+ var parent = element.parentNode, tagName = parent.tagName.toUpperCase();
+
+ if (Element._insertionTranslations.tags[tagName]) {
+ var nextSibling = element.next();
+ var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
+ parent.removeChild(element);
+ if (nextSibling)
+ fragments.each(function(node) { parent.insertBefore(node, nextSibling) });
+ else
+ fragments.each(function(node) { parent.appendChild(node) });
+ }
+ else element.outerHTML = content.stripScripts();
+
+ content.evalScripts.bind(content).defer();
+ return element;
+ };
+}
+
+Element._returnOffset = function(l, t) {
+ var result = [l, t];
+ result.left = l;
+ result.top = t;
+ return result;
+};
+
+Element._getContentFromAnonymousElement = function(tagName, html) {
+ var div = new Element('div'), t = Element._insertionTranslations.tags[tagName];
+ div.innerHTML = t[0] + html + t[1];
+ t[2].times(function() { div = div.firstChild });
+ return $A(div.childNodes);
+};
+
+Element._insertionTranslations = {
+ before: {
+ adjacency: 'beforeBegin',
+ insert: function(element, node) {
+ element.parentNode.insertBefore(node, element);
+ },
+ initializeRange: function(element, range) {
+ range.setStartBefore(element);
+ }
+ },
+ top: {
+ adjacency: 'afterBegin',
+ insert: function(element, node) {
+ element.insertBefore(node, element.firstChild);
+ },
+ initializeRange: function(element, range) {
+ range.selectNodeContents(element);
+ range.collapse(true);
+ }
+ },
+ bottom: {
+ adjacency: 'beforeEnd',
+ insert: function(element, node) {
+ element.appendChild(node);
+ }
+ },
+ after: {
+ adjacency: 'afterEnd',
+ insert: function(element, node) {
+ element.parentNode.insertBefore(node, element.nextSibling);
+ },
+ initializeRange: function(element, range) {
+ range.setStartAfter(element);
+ }
+ },
+ tags: {
+ TABLE: ['<table>', '</table>', 1],
+ TBODY: ['<table><tbody>', '</tbody></table>', 2],
+ TR: ['<table><tbody><tr>', '</tr></tbody></table>', 3],
+ TD: ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4],
+ SELECT: ['<select>', '</select>', 1]
+ }
+};
+
+(function() {
+ this.bottom.initializeRange = this.top.initializeRange;
+ Object.extend(this.tags, {
+ THEAD: this.tags.TBODY,
+ TFOOT: this.tags.TBODY,
+ TH: this.tags.TD
+ });
+}).call(Element._insertionTranslations);
+
+Element.Methods.Simulated = {
+ hasAttribute: function(element, attribute) {
+ attribute = Element._attributeTranslations.has[attribute] || attribute;
+ var node = $(element).getAttributeNode(attribute);
+ return node && node.specified;
+ }
+};
+
+Element.Methods.ByTag = { };
+
+Object.extend(Element, Element.Methods);
+
+if (!Prototype.BrowserFeatures.ElementExtensions &&
+ document.createElement('div').__proto__) {
+ window.HTMLElement = { };
+ window.HTMLElement.prototype = document.createElement('div').__proto__;
+ Prototype.BrowserFeatures.ElementExtensions = true;
+}
+
+Element.extend = (function() {
+ if (Prototype.BrowserFeatures.SpecificElementExtensions)
+ return Prototype.K;
+
+ var Methods = { }, ByTag = Element.Methods.ByTag;
+
+ var extend = Object.extend(function(element) {
+ if (!element || element._extendedByPrototype ||
+ element.nodeType != 1 || element == window) return element;
+
+ var methods = Object.clone(Methods),
+ tagName = element.tagName, property, value;
+
+ // extend methods for specific tags
+ if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);
+
+ for (property in methods) {
+ value = methods[property];
+ if (Object.isFunction(value) && !(property in element))
+ element[property] = value.methodize();
+ }
+
+ element._extendedByPrototype = Prototype.emptyFunction;
+ return element;
+
+ }, {
+ refresh: function() {
+ // extend methods for all tags (Safari doesn't need this)
+ if (!Prototype.BrowserFeatures.ElementExtensions) {
+ Object.extend(Methods, Element.Methods);
+ Object.extend(Methods, Element.Methods.Simulated);
+ }
+ }
+ });
+
+ extend.refresh();
+ return extend;
+})();
+
+Element.hasAttribute = function(element, attribute) {
+ if (element.hasAttribute) return element.hasAttribute(attribute);
+ return Element.Methods.Simulated.hasAttribute(element, attribute);
+};
+
+Element.addMethods = function(methods) {
+ var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag;
+
+ if (!methods) {
+ Object.extend(Form, Form.Methods);
+ Object.extend(Form.Element, Form.Element.Methods);
+ Object.extend(Element.Methods.ByTag, {
+ "FORM": Object.clone(Form.Methods),
+ "INPUT": Object.clone(Form.Element.Methods),
+ "SELECT": Object.clone(Form.Element.Methods),
+ "TEXTAREA": Object.clone(Form.Element.Methods)
+ });
+ }
+
+ if (arguments.length == 2) {
+ var tagName = methods;
+ methods = arguments[1];
+ }
+
+ if (!tagName) Object.extend(Element.Methods, methods || { });
+ else {
+ if (Object.isArray(tagName)) tagName.each(extend);
+ else extend(tagName);
+ }
+
+ function extend(tagName) {
+ tagName = tagName.toUpperCase();
+ if (!Element.Methods.ByTag[tagName])
+ Element.Methods.ByTag[tagName] = { };
+ Object.extend(Element.Methods.ByTag[tagName], methods);
+ }
+
+ function copy(methods, destination, onlyIfAbsent) {
+ onlyIfAbsent = onlyIfAbsent || false;
+ for (var property in methods) {
+ var value = methods[property];
+ if (!Object.isFunction(value)) continue;
+ if (!onlyIfAbsent || !(property in destination))
+ destination[property] = value.methodize();
+ }
+ }
+
+ function findDOMClass(tagName) {
+ var klass;
+ var trans = {
+ "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph",
+ "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList",
+ "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading",
+ "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote",
+ "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION":
+ "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD":
+ "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR":
+ "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET":
+ "FrameSet", "IFRAME": "IFrame"
+ };
+ if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';
+ if (window[klass]) return window[klass];
+ klass = 'HTML' + tagName + 'Element';
+ if (window[klass]) return window[klass];
+ klass = 'HTML' + tagName.capitalize() + 'Element';
+ if (window[klass]) return window[klass];
+
+ window[klass] = { };
+ window[klass].prototype = document.createElement(tagName).__proto__;
+ return window[klass];
+ }
+
+ if (F.ElementExtensions) {
+ copy(Element.Methods, HTMLElement.prototype);
+ copy(Element.Methods.Simulated, HTMLElement.prototype, true);
+ }
+
+ if (F.SpecificElementExtensions) {
+ for (var tag in Element.Methods.ByTag) {
+ var klass = findDOMClass(tag);
+ if (Object.isUndefined(klass)) continue;
+ copy(T[tag], klass.prototype);
+ }
+ }
+
+ Object.extend(Element, Element.Methods);
+ delete Element.ByTag;
+
+ if (Element.extend.refresh) Element.extend.refresh();
+ Element.cache = { };
+};
+
+document.viewport = {
+ getDimensions: function() {
+ var dimensions = { };
+ $w('width height').each(function(d) {
+ var D = d.capitalize();
+ dimensions[d] = self['inner' + D] ||
+ (document.documentElement['client' + D] || document.body['client' + D]);
+ });
+ return dimensions;
+ },
+
+ getWidth: function() {
+ return this.getDimensions().width;
+ },
+
+ getHeight: function() {
+ return this.getDimensions().height;
+ },
+
+ getScrollOffsets: function() {
+ return Element._returnOffset(
+ window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
+ window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
+ }
+};
+/* Portions of the Selector class are derived from Jack Slocum’s DomQuery,
+ * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style
+ * license. Please see http://www.yui-ext.com/ for more information. */
+
+var Selector = Class.create({
+ initialize: function(expression) {
+ this.expression = expression.strip();
+ this.compileMatcher();
+ },
+
+ compileMatcher: function() {
+ // Selectors with namespaced attributes can't use the XPath version
+ if (Prototype.BrowserFeatures.XPath && !(/(\[[\w-]*?:|:checked)/).test(this.expression))
+ return this.compileXPathMatcher();
+
+ var e = this.expression, ps = Selector.patterns, h = Selector.handlers,
+ c = Selector.criteria, le, p, m;
+
+ if (Selector._cache[e]) {
+ this.matcher = Selector._cache[e];
+ return;
+ }
+
+ this.matcher = ["this.matcher = function(root) {",
+ "var r = root, h = Selector.handlers, c = false, n;"];
+
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ p = ps[i];
+ if (m = e.match(p)) {
+ this.matcher.push(Object.isFunction(c[i]) ? c[i](m) :
+ new Template(c[i]).evaluate(m));
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+
+ this.matcher.push("return h.unique(n);\n}");
+ eval(this.matcher.join('\n'));
+ Selector._cache[this.expression] = this.matcher;
+ },
+
+ compileXPathMatcher: function() {
+ var e = this.expression, ps = Selector.patterns,
+ x = Selector.xpath, le, m;
+
+ if (Selector._cache[e]) {
+ this.xpath = Selector._cache[e]; return;
+ }
+
+ this.matcher = ['.//*'];
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ if (m = e.match(ps[i])) {
+ this.matcher.push(Object.isFunction(x[i]) ? x[i](m) :
+ new Template(x[i]).evaluate(m));
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+
+ this.xpath = this.matcher.join('');
+ Selector._cache[this.expression] = this.xpath;
+ },
+
+ findElements: function(root) {
+ root = root || document;
+ if (this.xpath) return document._getElementsByXPath(this.xpath, root);
+ return this.matcher(root);
+ },
+
+ match: function(element) {
+ this.tokens = [];
+
+ var e = this.expression, ps = Selector.patterns, as = Selector.assertions;
+ var le, p, m;
+
+ while (e && le !== e && (/\S/).test(e)) {
+ le = e;
+ for (var i in ps) {
+ p = ps[i];
+ if (m = e.match(p)) {
+ // use the Selector.assertions methods unless the selector
+ // is too complex.
+ if (as[i]) {
+ this.tokens.push([i, Object.clone(m)]);
+ e = e.replace(m[0], '');
+ } else {
+ // reluctantly do a document-wide search
+ // and look for a match in the array
+ return this.findElements(document).include(element);
+ }
+ }
+ }
+ }
+
+ var match = true, name, matches;
+ for (var i = 0, token; token = this.tokens[i]; i++) {
+ name = token[0], matches = token[1];
+ if (!Selector.assertions[name](element, matches)) {
+ match = false; break;
+ }
+ }
+
+ return match;
+ },
+
+ toString: function() {
+ return this.expression;
+ },
+
+ inspect: function() {
+ return "#<Selector:" + this.expression.inspect() + ">";
+ }
+});
+
+Object.extend(Selector, {
+ _cache: { },
+
+ xpath: {
+ descendant: "//*",
+ child: "/*",
+ adjacent: "/following-sibling::*[1]",
+ laterSibling: '/following-sibling::*',
+ tagName: function(m) {
+ if (m[1] == '*') return '';
+ return "[local-name()='" + m[1].toLowerCase() +
+ "' or local-name()='" + m[1].toUpperCase() + "']";
+ },
+ className: "[contains(concat(' ', @class, ' '), ' #{1} ')]",
+ id: "[@id='#{1}']",
+ attrPresence: "[@#{1}]",
+ attr: function(m) {
+ m[3] = m[5] || m[6];
+ return new Template(Selector.xpath.operators[m[2]]).evaluate(m);
+ },
+ pseudo: function(m) {
+ var h = Selector.xpath.pseudos[m[1]];
+ if (!h) return '';
+ if (Object.isFunction(h)) return h(m);
+ return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m);
+ },
+ operators: {
+ '=': "[@#{1}='#{3}']",
+ '!=': "[@#{1}!='#{3}']",
+ '^=': "[starts-with(@#{1}, '#{3}')]",
+ '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']",
+ '*=': "[contains(@#{1}, '#{3}')]",
+ '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]",
+ '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]"
+ },
+ pseudos: {
+ 'first-child': '[not(preceding-sibling::*)]',
+ 'last-child': '[not(following-sibling::*)]',
+ 'only-child': '[not(preceding-sibling::* or following-sibling::*)]',
+ 'empty': "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]",
+ 'checked': "[@checked]",
+ 'disabled': "[@disabled]",
+ 'enabled': "[not(@disabled)]",
+ 'not': function(m) {
+ var e = m[6], p = Selector.patterns,
+ x = Selector.xpath, le, m, v;
+
+ var exclusion = [];
+ while (e && le != e && (/\S/).test(e)) {
+ le = e;
+ for (var i in p) {
+ if (m = e.match(p[i])) {
+ v = Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m);
+ exclusion.push("(" + v.substring(1, v.length - 1) + ")");
+ e = e.replace(m[0], '');
+ break;
+ }
+ }
+ }
+ return "[not(" + exclusion.join(" and ") + ")]";
+ },
+ 'nth-child': function(m) {
+ return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m);
+ },
+ 'nth-last-child': function(m) {
+ return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m);
+ },
+ 'nth-of-type': function(m) {
+ return Selector.xpath.pseudos.nth("position() ", m);
+ },
+ 'nth-last-of-type': function(m) {
+ return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m);
+ },
+ 'first-of-type': function(m) {
+ m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m);
+ },
+ 'last-of-type': function(m) {
+ m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m);
+ },
+ 'only-of-type': function(m) {
+ var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m);
+ },
+ nth: function(fragment, m) {
+ var mm, formula = m[6], predicate;
+ if (formula == 'even') formula = '2n+0';
+ if (formula == 'odd') formula = '2n+1';
+ if (mm = formula.match(/^(\d+)$/)) // digit only
+ return '[' + fragment + "= " + mm[1] + ']';
+ if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
+ if (mm[1] == "-") mm[1] = -1;
+ var a = mm[1] ? Number(mm[1]) : 1;
+ var b = mm[2] ? Number(mm[2]) : 0;
+ predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " +
+ "((#{fragment} - #{b}) div #{a} >= 0)]";
+ return new Template(predicate).evaluate({
+ fragment: fragment, a: a, b: b });
+ }
+ }
+ }
+ },
+
+ criteria: {
+ tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;',
+ className: 'n = h.className(n, r, "#{1}", c); c = false;',
+ id: 'n = h.id(n, r, "#{1}", c); c = false;',
+ attrPresence: 'n = h.attrPresence(n, r, "#{1}"); c = false;',
+ attr: function(m) {
+ m[3] = (m[5] || m[6]);
+ return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}"); c = false;').evaluate(m);
+ },
+ pseudo: function(m) {
+ if (m[6]) m[6] = m[6].replace(/"/g, '\\"');
+ return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m);
+ },
+ descendant: 'c = "descendant";',
+ child: 'c = "child";',
+ adjacent: 'c = "adjacent";',
+ laterSibling: 'c = "laterSibling";'
+ },
+
+ patterns: {
+ // combinators must be listed first
+ // (and descendant needs to be last combinator)
+ laterSibling: /^\s*~\s*/,
+ child: /^\s*>\s*/,
+ adjacent: /^\s*\+\s*/,
+ descendant: /^\s/,
+
+ // selectors follow
+ tagName: /^\s*(\*|[\w\-]+)(\b|$)?/,
+ id: /^#([\w\-\*]+)(\b|$)/,
+ className: /^\.([\w\-\*]+)(\b|$)/,
+ pseudo: /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s)|(?=:))/,
+ attrPresence: /^\[([\w]+)\]/,
+ attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/
+ },
+
+ // for Selector.match and Element#match
+ assertions: {
+ tagName: function(element, matches) {
+ return matches[1].toUpperCase() == element.tagName.toUpperCase();
+ },
+
+ className: function(element, matches) {
+ return Element.hasClassName(element, matches[1]);
+ },
+
+ id: function(element, matches) {
+ return element.id === matches[1];
+ },
+
+ attrPresence: function(element, matches) {
+ return Element.hasAttribute(element, matches[1]);
+ },
+
+ attr: function(element, matches) {
+ var nodeValue = Element.readAttribute(element, matches[1]);
+ return Selector.operators[matches[2]](nodeValue, matches[3]);
+ }
+ },
+
+ handlers: {
+ // UTILITY FUNCTIONS
+ // joins two collections
+ concat: function(a, b) {
+ for (var i = 0, node; node = b[i]; i++)
+ a.push(node);
+ return a;
+ },
+
+ // marks an array of nodes for counting
+ mark: function(nodes) {
+ for (var i = 0, node; node = nodes[i]; i++)
+ node._counted = true;
+ return nodes;
+ },
+
+ unmark: function(nodes) {
+ for (var i = 0, node; node = nodes[i]; i++)
+ node._counted = undefined;
+ return nodes;
+ },
+
+ // mark each child node with its position (for nth calls)
+ // "ofType" flag indicates whether we're indexing for nth-of-type
+ // rather than nth-child
+ index: function(parentNode, reverse, ofType) {
+ parentNode._counted = true;
+ if (reverse) {
+ for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) {
+ var node = nodes[i];
+ if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++;
+ }
+ } else {
+ for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++)
+ if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++;
+ }
+ },
+
+ // filters out duplicates and extends all nodes
+ unique: function(nodes) {
+ if (nodes.length == 0) return nodes;
+ var results = [], n;
+ for (var i = 0, l = nodes.length; i < l; i++)
+ if (!(n = nodes[i])._counted) {
+ n._counted = true;
+ results.push(Element.extend(n));
+ }
+ return Selector.handlers.unmark(results);
+ },
+
+ // COMBINATOR FUNCTIONS
+ descendant: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ h.concat(results, node.getElementsByTagName('*'));
+ return results;
+ },
+
+ child: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ for (var j = 0, children = [], child; child = node.childNodes[j]; j++)
+ if (child.nodeType == 1 && child.tagName != '!') results.push(child);
+ }
+ return results;
+ },
+
+ adjacent: function(nodes) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ var next = this.nextElementSibling(node);
+ if (next) results.push(next);
+ }
+ return results;
+ },
+
+ laterSibling: function(nodes) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ h.concat(results, Element.nextSiblings(node));
+ return results;
+ },
+
+ nextElementSibling: function(node) {
+ while (node = node.nextSibling)
+ if (node.nodeType == 1) return node;
+ return null;
+ },
+
+ previousElementSibling: function(node) {
+ while (node = node.previousSibling)
+ if (node.nodeType == 1) return node;
+ return null;
+ },
+
+ // TOKEN FUNCTIONS
+ tagName: function(nodes, root, tagName, combinator) {
+ tagName = tagName.toUpperCase();
+ var results = [], h = Selector.handlers;
+ if (nodes) {
+ if (combinator) {
+ // fastlane for ordinary descendant combinators
+ if (combinator == "descendant") {
+ for (var i = 0, node; node = nodes[i]; i++)
+ h.concat(results, node.getElementsByTagName(tagName));
+ return results;
+ } else nodes = this[combinator](nodes);
+ if (tagName == "*") return nodes;
+ }
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node.tagName.toUpperCase() == tagName) results.push(node);
+ return results;
+ } else return root.getElementsByTagName(tagName);
+ },
+
+ id: function(nodes, root, id, combinator) {
+ var targetNode = $(id), h = Selector.handlers;
+ if (!targetNode) return [];
+ if (!nodes && root == document) return [targetNode];
+ if (nodes) {
+ if (combinator) {
+ if (combinator == 'child') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (targetNode.parentNode == node) return [targetNode];
+ } else if (combinator == 'descendant') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Element.descendantOf(targetNode, node)) return [targetNode];
+ } else if (combinator == 'adjacent') {
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Selector.handlers.previousElementSibling(targetNode) == node)
+ return [targetNode];
+ } else nodes = h[combinator](nodes);
+ }
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node == targetNode) return [targetNode];
+ return [];
+ }
+ return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : [];
+ },
+
+ className: function(nodes, root, className, combinator) {
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ return Selector.handlers.byClassName(nodes, root, className);
+ },
+
+ byClassName: function(nodes, root, className) {
+ if (!nodes) nodes = Selector.handlers.descendant([root]);
+ var needle = ' ' + className + ' ';
+ for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) {
+ nodeClassName = node.className;
+ if (nodeClassName.length == 0) continue;
+ if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle))
+ results.push(node);
+ }
+ return results;
+ },
+
+ attrPresence: function(nodes, root, attr) {
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ var results = [];
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (Element.hasAttribute(node, attr)) results.push(node);
+ return results;
+ },
+
+ attr: function(nodes, root, attr, value, operator) {
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ var handler = Selector.operators[operator], results = [];
+ for (var i = 0, node; node = nodes[i]; i++) {
+ var nodeValue = Element.readAttribute(node, attr);
+ if (nodeValue === null) continue;
+ if (handler(nodeValue, value)) results.push(node);
+ }
+ return results;
+ },
+
+ pseudo: function(nodes, name, value, root, combinator) {
+ if (nodes && combinator) nodes = this[combinator](nodes);
+ if (!nodes) nodes = root.getElementsByTagName("*");
+ return Selector.pseudos[name](nodes, value, root);
+ }
+ },
+
+ pseudos: {
+ 'first-child': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ if (Selector.handlers.previousElementSibling(node)) continue;
+ results.push(node);
+ }
+ return results;
+ },
+ 'last-child': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ if (Selector.handlers.nextElementSibling(node)) continue;
+ results.push(node);
+ }
+ return results;
+ },
+ 'only-child': function(nodes, value, root) {
+ var h = Selector.handlers;
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!h.previousElementSibling(node) && !h.nextElementSibling(node))
+ results.push(node);
+ return results;
+ },
+ 'nth-child': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root);
+ },
+ 'nth-last-child': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, true);
+ },
+ 'nth-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, false, true);
+ },
+ 'nth-last-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, formula, root, true, true);
+ },
+ 'first-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, "1", root, false, true);
+ },
+ 'last-of-type': function(nodes, formula, root) {
+ return Selector.pseudos.nth(nodes, "1", root, true, true);
+ },
+ 'only-of-type': function(nodes, formula, root) {
+ var p = Selector.pseudos;
+ return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root);
+ },
+
+ // handles the an+b logic
+ getIndices: function(a, b, total) {
+ if (a == 0) return b > 0 ? [b] : [];
+ return $R(1, total).inject([], function(memo, i) {
+ if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i);
+ return memo;
+ });
+ },
+
+ // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type
+ nth: function(nodes, formula, root, reverse, ofType) {
+ if (nodes.length == 0) return [];
+ if (formula == 'even') formula = '2n+0';
+ if (formula == 'odd') formula = '2n+1';
+ var h = Selector.handlers, results = [], indexed = [], m;
+ h.mark(nodes);
+ for (var i = 0, node; node = nodes[i]; i++) {
+ if (!node.parentNode._counted) {
+ h.index(node.parentNode, reverse, ofType);
+ indexed.push(node.parentNode);
+ }
+ }
+ if (formula.match(/^\d+$/)) { // just a number
+ formula = Number(formula);
+ for (var i = 0, node; node = nodes[i]; i++)
+ if (node.nodeIndex == formula) results.push(node);
+ } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
+ if (m[1] == "-") m[1] = -1;
+ var a = m[1] ? Number(m[1]) : 1;
+ var b = m[2] ? Number(m[2]) : 0;
+ var indices = Selector.pseudos.getIndices(a, b, nodes.length);
+ for (var i = 0, node, l = indices.length; node = nodes[i]; i++) {
+ for (var j = 0; j < l; j++)
+ if (node.nodeIndex == indices[j]) results.push(node);
+ }
+ }
+ h.unmark(nodes);
+ h.unmark(indexed);
+ return results;
+ },
+
+ 'empty': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
+ // IE treats comments as element nodes
+ if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\s*$/))) continue;
+ results.push(node);
+ }
+ return results;
+ },
+
+ 'not': function(nodes, selector, root) {
+ var h = Selector.handlers, selectorType, m;
+ var exclusions = new Selector(selector).findElements(root);
+ h.mark(exclusions);
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!node._counted) results.push(node);
+ h.unmark(exclusions);
+ return results;
+ },
+
+ 'enabled': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (!node.disabled) results.push(node);
+ return results;
+ },
+
+ 'disabled': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (node.disabled) results.push(node);
+ return results;
+ },
+
+ 'checked': function(nodes, value, root) {
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
+ if (node.checked) results.push(node);
+ return results;
+ }
+ },
+
+ operators: {
+ '=': function(nv, v) { return nv == v; },
+ '!=': function(nv, v) { return nv != v; },
+ '^=': function(nv, v) { return nv.startsWith(v); },
+ '$=': function(nv, v) { return nv.endsWith(v); },
+ '*=': function(nv, v) { return nv.include(v); },
+ '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); },
+ '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); }
+ },
+
+ matchElements: function(elements, expression) {
+ var matches = new Selector(expression).findElements(), h = Selector.handlers;
+ h.mark(matches);
+ for (var i = 0, results = [], element; element = elements[i]; i++)
+ if (element._counted) results.push(element);
+ h.unmark(matches);
+ return results;
+ },
+
+ findElement: function(elements, expression, index) {
+ if (Object.isNumber(expression)) {
+ index = expression; expression = false;
+ }
+ return Selector.matchElements(elements, expression || '*')[index || 0];
+ },
+
+ findChildElements: function(element, expressions) {
+ var exprs = expressions.join(','), expressions = [];
+ exprs.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) {
+ expressions.push(m[1].strip());
+ });
+ var results = [], h = Selector.handlers;
+ for (var i = 0, l = expressions.length, selector; i < l; i++) {
+ selector = new Selector(expressions[i].strip());
+ h.concat(results, selector.findElements(element));
+ }
+ return (l > 1) ? h.unique(results) : results;
+ }
+});
+
+function $$() {
+ return Selector.findChildElements(document, $A(arguments));
+}
+var Form = {
+ reset: function(form) {
+ $(form).reset();
+ return form;
+ },
+
+ serializeElements: function(elements, options) {
+ if (typeof options != 'object') options = { hash: !!options };
+ else if (options.hash === undefined) options.hash = true;
+ var key, value, submitted = false, submit = options.submit;
+
+ var data = elements.inject({ }, function(result, element) {
+ if (!element.disabled && element.name) {
+ key = element.name; value = $(element).getValue();
+ if (value != null && (element.type != 'submit' || (!submitted &&
+ submit !== false && (!submit || key == submit) && (submitted = true)))) {
+ if (key in result) {
+ // a key is already present; construct an array of values
+ if (!Object.isArray(result[key])) result[key] = [result[key]];
+ result[key].push(value);
+ }
+ else result[key] = value;
+ }
+ }
+ return result;
+ });
+
+ return options.hash ? data : Object.toQueryString(data);
+ }
+};
+
+Form.Methods = {
+ serialize: function(form, options) {
+ return Form.serializeElements(Form.getElements(form), options);
+ },
+
+ getElements: function(form) {
+ return $A($(form).getElementsByTagName('*')).inject([],
+ function(elements, child) {
+ if (Form.Element.Serializers[child.tagName.toLowerCase()])
+ elements.push(Element.extend(child));
+ return elements;
+ }
+ );
+ },
+
+ getInputs: function(form, typeName, name) {
+ form = $(form);
+ var inputs = form.getElementsByTagName('input');
+
+ if (!typeName && !name) return $A(inputs).map(Element.extend);
+
+ for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {
+ var input = inputs[i];
+ if ((typeName && input.type != typeName) || (name && input.name != name))
+ continue;
+ matchingInputs.push(Element.extend(input));
+ }
+
+ return matchingInputs;
+ },
+
+ disable: function(form) {
+ form = $(form);
+ Form.getElements(form).invoke('disable');
+ return form;
+ },
+
+ enable: function(form) {
+ form = $(form);
+ Form.getElements(form).invoke('enable');
+ return form;
+ },
+
+ findFirstElement: function(form) {
+ var elements = $(form).getElements().findAll(function(element) {
+ return 'hidden' != element.type && !element.disabled;
+ });
+ var firstByIndex = elements.findAll(function(element) {
+ return element.hasAttribute('tabIndex') && element.tabIndex >= 0;
+ }).sortBy(function(element) { return element.tabIndex }).first();
+
+ return firstByIndex ? firstByIndex : elements.find(function(element) {
+ return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
+ });
+ },
+
+ focusFirstElement: function(form) {
+ form = $(form);
+ form.findFirstElement().activate();
+ return form;
+ },
+
+ request: function(form, options) {
+ form = $(form), options = Object.clone(options || { });
+
+ var params = options.parameters, action = form.readAttribute('action') || '';
+ if (action.blank()) action = window.location.href;
+ options.parameters = form.serialize(true);
+
+ if (params) {
+ if (Object.isString(params)) params = params.toQueryParams();
+ Object.extend(options.parameters, params);
+ }
+
+ if (form.hasAttribute('method') && !options.method)
+ options.method = form.method;
+
+ return new Ajax.Request(action, options);
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+Form.Element = {
+ focus: function(element) {
+ $(element).focus();
+ return element;
+ },
+
+ select: function(element) {
+ $(element).select();
+ return element;
+ }
+};
+
+Form.Element.Methods = {
+ serialize: function(element) {
+ element = $(element);
+ if (!element.disabled && element.name) {
+ var value = element.getValue();
+ if (value != undefined) {
+ var pair = { };
+ pair[element.name] = value;
+ return Object.toQueryString(pair);
+ }
+ }
+ return '';
+ },
+
+ getValue: function(element) {
+ element = $(element);
+ var method = element.tagName.toLowerCase();
+ return Form.Element.Serializers[method](element);
+ },
+
+ setValue: function(element, value) {
+ element = $(element);
+ var method = element.tagName.toLowerCase();
+ Form.Element.Serializers[method](element, value);
+ return element;
+ },
+
+ clear: function(element) {
+ $(element).value = '';
+ return element;
+ },
+
+ present: function(element) {
+ return $(element).value != '';
+ },
+
+ activate: function(element) {
+ element = $(element);
+ try {
+ element.focus();
+ if (element.select && (element.tagName.toLowerCase() != 'input' ||
+ !['button', 'reset', 'submit'].include(element.type)))
+ element.select();
+ } catch (e) { }
+ return element;
+ },
+
+ disable: function(element) {
+ element = $(element);
+ element.blur();
+ element.disabled = true;
+ return element;
+ },
+
+ enable: function(element) {
+ element = $(element);
+ element.disabled = false;
+ return element;
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+var Field = Form.Element;
+var $F = Form.Element.Methods.getValue;
+
+/*--------------------------------------------------------------------------*/
+
+Form.Element.Serializers = {
+ input: function(element, value) {
+ switch (element.type.toLowerCase()) {
+ case 'checkbox':
+ case 'radio':
+ return Form.Element.Serializers.inputSelector(element, value);
+ default:
+ return Form.Element.Serializers.textarea(element, value);
+ }
+ },
+
+ inputSelector: function(element, value) {
+ if (value === undefined) return element.checked ? element.value : null;
+ else element.checked = !!value;
+ },
+
+ textarea: function(element, value) {
+ if (value === undefined) return element.value;
+ else element.value = value;
+ },
+
+ select: function(element, index) {
+ if (index === undefined)
+ return this[element.type == 'select-one' ?
+ 'selectOne' : 'selectMany'](element);
+ else {
+ var opt, value, single = !Object.isArray(index);
+ for (var i = 0, length = element.length; i < length; i++) {
+ opt = element.options[i];
+ value = this.optionValue(opt);
+ if (single) {
+ if (value == index) {
+ opt.selected = true;
+ return;
+ }
+ }
+ else opt.selected = index.include(value);
+ }
+ }
+ },
+
+ selectOne: function(element) {
+ var index = element.selectedIndex;
+ return index >= 0 ? this.optionValue(element.options[index]) : null;
+ },
+
+ selectMany: function(element) {
+ var values, length = element.length;
+ if (!length) return null;
+
+ for (var i = 0, values = []; i < length; i++) {
+ var opt = element.options[i];
+ if (opt.selected) values.push(this.optionValue(opt));
+ }
+ return values;
+ },
+
+ optionValue: function(opt) {
+ // extend element because hasAttribute may not be native
+ return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.TimedObserver = Class.create(PeriodicalExecuter, {
+ initialize: function($super, element, frequency, callback) {
+ $super(callback, frequency);
+ this.element = $(element);
+ this.lastValue = this.getValue();
+ },
+
+ execute: function() {
+ var value = this.getValue();
+ if (Object.isString(this.lastValue) && Object.isString(value) ?
+ this.lastValue != value : String(this.lastValue) != String(value)) {
+ this.callback(this.element, value);
+ this.lastValue = value;
+ }
+ }
+});
+
+Form.Element.Observer = Class.create(Abstract.TimedObserver, {
+ getValue: function() {
+ return Form.Element.getValue(this.element);
+ }
+});
+
+Form.Observer = Class.create(Abstract.TimedObserver, {
+ getValue: function() {
+ return Form.serialize(this.element);
+ }
+});
+
+/*--------------------------------------------------------------------------*/
+
+Abstract.EventObserver = Class.create({
+ initialize: function(element, callback) {
+ this.element = $(element);
+ this.callback = callback;
+
+ this.lastValue = this.getValue();
+ if (this.element.tagName.toLowerCase() == 'form')
+ this.registerFormCallbacks();
+ else
+ this.registerCallback(this.element);
+ },
+
+ onElementEvent: function() {
+ var value = this.getValue();
+ if (this.lastValue != value) {
+ this.callback(this.element, value);
+ this.lastValue = value;
+ }
+ },
+
+ registerFormCallbacks: function() {
+ Form.getElements(this.element).each(this.registerCallback, this);
+ },
+
+ registerCallback: function(element) {
+ if (element.type) {
+ switch (element.type.toLowerCase()) {
+ case 'checkbox':
+ case 'radio':
+ Event.observe(element, 'click', this.onElementEvent.bind(this));
+ break;
+ default:
+ Event.observe(element, 'change', this.onElementEvent.bind(this));
+ break;
+ }
+ }
+ }
+});
+
+Form.Element.EventObserver = Class.create(Abstract.EventObserver, {
+ getValue: function() {
+ return Form.Element.getValue(this.element);
+ }
+});
+
+Form.EventObserver = Class.create(Abstract.EventObserver, {
+ getValue: function() {
+ return Form.serialize(this.element);
+ }
+});
+if (!window.Event) var Event = { };
+
+Object.extend(Event, {
+ KEY_BACKSPACE: 8,
+ KEY_TAB: 9,
+ KEY_RETURN: 13,
+ KEY_ESC: 27,
+ KEY_LEFT: 37,
+ KEY_UP: 38,
+ KEY_RIGHT: 39,
+ KEY_DOWN: 40,
+ KEY_DELETE: 46,
+ KEY_HOME: 36,
+ KEY_END: 35,
+ KEY_PAGEUP: 33,
+ KEY_PAGEDOWN: 34,
+ KEY_INSERT: 45,
+
+ cache: { },
+
+ relatedTarget: function(event) {
+ var element;
+ switch(event.type) {
+ case 'mouseover': element = event.fromElement; break;
+ case 'mouseout': element = event.toElement; break;
+ default: return null;
+ }
+ return Element.extend(element);
+ }
+});
+
+Event.Methods = (function() {
+ var isButton;
+
+ if (Prototype.Browser.IE) {
+ var buttonMap = { 0: 1, 1: 4, 2: 2 };
+ isButton = function(event, code) {
+ return event.button == buttonMap[code];
+ };
+
+ } else if (Prototype.Browser.WebKit) {
+ isButton = function(event, code) {
+ switch (code) {
+ case 0: return event.which == 1 && !event.metaKey;
+ case 1: return event.which == 1 && event.metaKey;
+ default: return false;
+ }
+ };
+
+ } else {
+ isButton = function(event, code) {
+ return event.which ? (event.which === code + 1) : (event.button === code);
+ };
+ }
+
+ return {
+ isLeftClick: function(event) { return isButton(event, 0) },
+ isMiddleClick: function(event) { return isButton(event, 1) },
+ isRightClick: function(event) { return isButton(event, 2) },
+
+ element: function(event) {
+ var node = Event.extend(event).target;
+ return Element.extend(node.nodeType == Node.TEXT_NODE ? node.parentNode : node);
+ },
+
+ findElement: function(event, expression) {
+ var element = Event.element(event);
+ return element.match(expression) ? element : element.up(expression);
+ },
+
+ pointer: function(event) {
+ return {
+ x: event.pageX || (event.clientX +
+ (document.documentElement.scrollLeft || document.body.scrollLeft)),
+ y: event.pageY || (event.clientY +
+ (document.documentElement.scrollTop || document.body.scrollTop))
+ };
+ },
+
+ pointerX: function(event) { return Event.pointer(event).x },
+ pointerY: function(event) { return Event.pointer(event).y },
+
+ stop: function(event) {
+ Event.extend(event);
+ event.preventDefault();
+ event.stopPropagation();
+ event.stopped = true;
+ }
+ };
+})();
+
+Event.extend = (function() {
+ var methods = Object.keys(Event.Methods).inject({ }, function(m, name) {
+ m[name] = Event.Methods[name].methodize();
+ return m;
+ });
+
+ if (Prototype.Browser.IE) {
+ Object.extend(methods, {
+ stopPropagation: function() { this.cancelBubble = true },
+ preventDefault: function() { this.returnValue = false },
+ inspect: function() { return "[object Event]" }
+ });
+
+ return function(event) {
+ if (!event) return false;
+ if (event._extendedByPrototype) return event;
+
+ event._extendedByPrototype = Prototype.emptyFunction;
+ var pointer = Event.pointer(event);
+ Object.extend(event, {
+ target: event.srcElement,
+ relatedTarget: Event.relatedTarget(event),
+ pageX: pointer.x,
+ pageY: pointer.y
+ });
+ return Object.extend(event, methods);
+ };
+
+ } else {
+ Event.prototype = Event.prototype || document.createEvent("HTMLEvents").__proto__;
+ Object.extend(Event.prototype, methods);
+ return Prototype.K;
+ }
+})();
+
+Object.extend(Event, (function() {
+ var cache = Event.cache;
+
+ function getEventID(element) {
+ if (element._eventID) return element._eventID;
+ arguments.callee.id = arguments.callee.id || 1;
+ return element._eventID = ++arguments.callee.id;
+ }
+
+ function getDOMEventName(eventName) {
+ if (eventName && eventName.include(':')) return "dataavailable";
+ return eventName;
+ }
+
+ function getCacheForID(id) {
+ return cache[id] = cache[id] || { };
+ }
+
+ function getWrappersForEventName(id, eventName) {
+ var c = getCacheForID(id);
+ return c[eventName] = c[eventName] || [];
+ }
+
+ function createWrapper(element, eventName, handler) {
+ var id = getEventID(element);
+ var c = getWrappersForEventName(id, eventName);
+ if (c.pluck("handler").include(handler)) return false;
+
+ var wrapper = function(event) {
+ if (!Event || !Event.extend ||
+ (event.eventName && event.eventName != eventName))
+ return false;
+
+ Event.extend(event);
+ handler.call(element, event)
+ };
+
+ wrapper.handler = handler;
+ c.push(wrapper);
+ return wrapper;
+ }
+
+ function findWrapper(id, eventName, handler) {
+ var c = getWrappersForEventName(id, eventName);
+ return c.find(function(wrapper) { return wrapper.handler == handler });
+ }
+
+ function destroyWrapper(id, eventName, handler) {
+ var c = getCacheForID(id);
+ if (!c[eventName]) return false;
+ c[eventName] = c[eventName].without(findWrapper(id, eventName, handler));
+ }
+
+ function destroyCache() {
+ for (var id in cache)
+ for (var eventName in cache[id])
+ cache[id][eventName] = null;
+ }
+
+ if (window.attachEvent) {
+ window.attachEvent("onunload", destroyCache);
+ }
+
+ return {
+ observe: function(element, eventName, handler) {
+ element = $(element);
+ var name = getDOMEventName(eventName);
+
+ var wrapper = createWrapper(element, eventName, handler);
+ if (!wrapper) return element;
+
+ if (element.addEventListener) {
+ element.addEventListener(name, wrapper, false);
+ } else {
+ element.attachEvent("on" + name, wrapper);
+ }
+
+ return element;
+ },
+
+ stopObserving: function(element, eventName, handler) {
+ element = $(element);
+ var id = getEventID(element), name = getDOMEventName(eventName);
+
+ if (!handler && eventName) {
+ getWrappersForEventName(id, eventName).each(function(wrapper) {
+ element.stopObserving(eventName, wrapper.handler);
+ });
+ return element;
+
+ } else if (!eventName) {
+ Object.keys(getCacheForID(id)).each(function(eventName) {
+ element.stopObserving(eventName);
+ });
+ return element;
+ }
+
+ var wrapper = findWrapper(id, eventName, handler);
+ if (!wrapper) return element;
+
+ if (element.removeEventListener) {
+ element.removeEventListener(name, wrapper, false);
+ } else {
+ element.detachEvent("on" + name, wrapper);
+ }
+
+ destroyWrapper(id, eventName, handler);
+
+ return element;
+ },
+
+ fire: function(element, eventName, memo) {
+ element = $(element);
+ if (element == document && document.createEvent && !element.dispatchEvent)
+ element = document.documentElement;
+
+ if (document.createEvent) {
+ var event = document.createEvent("HTMLEvents");
+ event.initEvent("dataavailable", true, true);
+ } else {
+ var event = document.createEventObject();
+ event.eventType = "ondataavailable";
+ }
+
+ event.eventName = eventName;
+ event.memo = memo || { };
+
+ if (document.createEvent) {
+ element.dispatchEvent(event);
+ } else {
+ element.fireEvent(event.eventType, event);
+ }
+
+ return event;
+ }
+ };
+})());
+
+Object.extend(Event, Event.Methods);
+
+Element.addMethods({
+ fire: Event.fire,
+ observe: Event.observe,
+ stopObserving: Event.stopObserving
+});
+
+Object.extend(document, {
+ fire: Element.Methods.fire.methodize(),
+ observe: Element.Methods.observe.methodize(),
+ stopObserving: Element.Methods.stopObserving.methodize()
+});
+
+(function() {
+ /* Support for the DOMContentLoaded event is based on work by Dan Webb,
+ Matthias Miller, Dean Edwards and John Resig. */
+
+ var timer, fired = false;
+
+ function fireContentLoadedEvent() {
+ if (fired) return;
+ if (timer) window.clearInterval(timer);
+ document.fire("dom:loaded");
+ fired = true;
+ }
+
+ if (document.addEventListener) {
+ if (Prototype.Browser.WebKit) {
+ timer = window.setInterval(function() {
+ if (/loaded|complete/.test(document.readyState))
+ fireContentLoadedEvent();
+ }, 0);
+
+ Event.observe(window, "load", fireContentLoadedEvent);
+
+ } else {
+ document.addEventListener("DOMContentLoaded",
+ fireContentLoadedEvent, false);
+ }
+
+ } else {
+ document.write("<script id=__onDOMContentLoaded defer src=//:><\/script>");
+ $("__onDOMContentLoaded").onreadystatechange = function() {
+ if (this.readyState == "complete") {
+ this.onreadystatechange = null;
+ fireContentLoadedEvent();
+ }
+ };
+ }
+})();
+/*------------------------------- DEPRECATED -------------------------------*/
+
+Hash.toQueryString = Object.toQueryString;
+
+var Toggle = { display: Element.toggle };
+
+Element.Methods.childOf = Element.Methods.descendantOf;
+
+var Insertion = {
+ Before: function(element, content) {
+ return Element.insert(element, {before:content});
+ },
+
+ Top: function(element, content) {
+ return Element.insert(element, {top:content});
+ },
+
+ Bottom: function(element, content) {
+ return Element.insert(element, {bottom:content});
+ },
+
+ After: function(element, content) {
+ return Element.insert(element, {after:content});
+ }
+};
+
+var $continue = new Error('"throw $continue" is deprecated, use "return" instead');
+
+// This should be moved to script.aculo.us; notice the deprecated methods
+// further below, that map to the newer Element methods.
+var Position = {
+ // set to true if needed, warning: firefox performance problems
+ // NOT neeeded for page scrolling, only if draggable contained in
+ // scrollable elements
+ includeScrollOffsets: false,
+
+ // must be called before calling withinIncludingScrolloffset, every time the
+ // page is scrolled
+ prepare: function() {
+ this.deltaX = window.pageXOffset
+ || document.documentElement.scrollLeft
+ || document.body.scrollLeft
+ || 0;
+ this.deltaY = window.pageYOffset
+ || document.documentElement.scrollTop
+ || document.body.scrollTop
+ || 0;
+ },
+
+ // caches x/y coordinate pair to use with overlap
+ within: function(element, x, y) {
+ if (this.includeScrollOffsets)
+ return this.withinIncludingScrolloffsets(element, x, y);
+ this.xcomp = x;
+ this.ycomp = y;
+ this.offset = Element.cumulativeOffset(element);
+
+ return (y >= this.offset[1] &&
+ y < this.offset[1] + element.offsetHeight &&
+ x >= this.offset[0] &&
+ x < this.offset[0] + element.offsetWidth);
+ },
+
+ withinIncludingScrolloffsets: function(element, x, y) {
+ var offsetcache = Element.cumulativeScrollOffset(element);
+
+ this.xcomp = x + offsetcache[0] - this.deltaX;
+ this.ycomp = y + offsetcache[1] - this.deltaY;
+ this.offset = Element.cumulativeOffset(element);
+
+ return (this.ycomp >= this.offset[1] &&
+ this.ycomp < this.offset[1] + element.offsetHeight &&
+ this.xcomp >= this.offset[0] &&
+ this.xcomp < this.offset[0] + element.offsetWidth);
+ },
+
+ // within must be called directly before
+ overlap: function(mode, element) {
+ if (!mode) return 0;
+ if (mode == 'vertical')
+ return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
+ element.offsetHeight;
+ if (mode == 'horizontal')
+ return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
+ element.offsetWidth;
+ },
+
+ // Deprecation layer -- use newer Element methods now (1.5.2).
+
+ cumulativeOffset: Element.Methods.cumulativeOffset,
+
+ positionedOffset: Element.Methods.positionedOffset,
+
+ absolutize: function(element) {
+ Position.prepare();
+ return Element.absolutize(element);
+ },
+
+ relativize: function(element) {
+ Position.prepare();
+ return Element.relativize(element);
+ },
+
+ realOffset: Element.Methods.cumulativeScrollOffset,
+
+ offsetParent: Element.Methods.getOffsetParent,
+
+ page: Element.Methods.viewportOffset,
+
+ clone: function(source, target, options) {
+ options = options || { };
+ return Element.clonePosition(target, source, options);
+ }
+};
+
+/*--------------------------------------------------------------------------*/
+
+if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){
+ function iter(name) {
+ return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]";
+ }
+
+ instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ?
+ function(element, className) {
+ className = className.toString().strip();
+ var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className);
+ return cond ? document._getElementsByXPath('.//*' + cond, element) : [];
+ } : function(element, className) {
+ className = className.toString().strip();
+ var elements = [], classNames = (/\s/.test(className) ? $w(className) : null);
+ if (!classNames && !className) return elements;
+
+ var nodes = $(element).getElementsByTagName('*');
+ className = ' ' + className + ' ';
+
+ for (var i = 0, child, cn; child = nodes[i]; i++) {
+ if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) ||
+ (classNames && classNames.all(function(name) {
+ return !name.toString().blank() && cn.include(' ' + name + ' ');
+ }))))
+ elements.push(Element.extend(child));
+ }
+ return elements;
+ };
+
+ return function(className, parentElement) {
+ return $(parentElement || document.body).getElementsByClassName(className);
+ };
+}(Element.Methods);
+
+/*--------------------------------------------------------------------------*/
+
+Element.ClassNames = Class.create();
+Element.ClassNames.prototype = {
+ initialize: function(element) {
+ this.element = $(element);
+ },
+
+ _each: function(iterator) {
+ this.element.className.split(/\s+/).select(function(name) {
+ return name.length > 0;
+ })._each(iterator);
+ },
+
+ set: function(className) {
+ this.element.className = className;
+ },
+
+ add: function(classNameToAdd) {
+ if (this.include(classNameToAdd)) return;
+ this.set($A(this).concat(classNameToAdd).join(' '));
+ },
+
+ remove: function(classNameToRemove) {
+ if (!this.include(classNameToRemove)) return;
+ this.set($A(this).without(classNameToRemove).join(' '));
+ },
+
+ toString: function() {
+ return $A(this).join(' ');
+ }
+};
+
+Object.extend(Element.ClassNames.prototype, Enumerable);
+
+/*--------------------------------------------------------------------------*/
+
+Element.addMethods();
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-input/checkbox-title.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-input/checkbox-title.html
new file mode 100644
index 00000000000..6b94860264d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-input/checkbox-title.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Checkbox with title attribute and no other labeling mechanism</title>
+ </head>
+ <body>
+ <input type="checkbox" id="test" title="foo" />
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-input/file-title.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-input/file-title.html
new file mode 100644
index 00000000000..12d91348a29
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-input/file-title.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>File input with title attribute and no other labeling mechanism</title>
+ </head>
+ <body>
+ <input type="file" id="test" title="foo" />
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-input/password-title.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-input/password-title.html
new file mode 100644
index 00000000000..ab74265110c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-input/password-title.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Password input with title attribute and no other labeling mechanism</title>
+ </head>
+ <body>
+ <input type="password" id="test" title="foo" />
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-input/radio-title.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-input/radio-title.html
new file mode 100644
index 00000000000..e84c919aad3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-input/radio-title.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Radio button with title attribute and no other labeling mechanism</title>
+ </head>
+ <body>
+ <input type="radio" id="test" title="foo" />
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-input/text-title.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-input/text-title.html
new file mode 100644
index 00000000000..90ba881a31f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-input/text-title.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Text input with title attribute and no other labeling mechanism</title>
+ </head>
+ <body>
+ <input type="text" id="test" title="foo" />
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/673.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/673.html
new file mode 100644
index 00000000000..d24cd6b01e3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/673.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 673</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 673</h1>
+
+ <div id="TEST_ID" aria-live="polite" >
+ </div>
+
+ <h2>Description</h2>
+ <p>An element with an aria-live attribute is defined in markup with the value="polite".
+ After the onload event completes a child DOM text node is added to the element with
+ the aria-live attribute.</p>
+
+ <script type="text/javascript">
+
+ function addTextNode() {
+ var node = document.getElementById('TEST_ID');
+ var text_node = document.createTextNode('TEST TEXT');
+ node.appendChild(text_node);
+ }
+
+ function onload() {
+ setTimeout(addTextNode,1000);
+ }
+
+ window.addEventListener('load', onload);
+ </script>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/674.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/674.html
new file mode 100644
index 00000000000..c031ec954f4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/674.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 674</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 674</h1>
+
+ <div id="TEST_ID" aria-live="polite" >
+ </div>
+
+ <h2>Description</h2>
+ <p>An element with an aria-live attribute is defined in markup with the value="polite".
+ After the onload event completes a child DOM text node is added to the element
+ with the aria-live attribute.</p>
+
+ <script type="text/javascript">
+
+ function addTextNode() {
+ var node = document.getElementById('TEST_ID');
+ var text_node = document.createTextNode('TEST TEXT');
+ node.appendChild(text_node);
+ }
+
+ function onload() {
+ setTimeout(addTextNode,1000);
+ }
+
+ window.addEventListener('load', onload);
+ </script>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/675.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/675.html
new file mode 100644
index 00000000000..c762fcfb03b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/675.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 675</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 675</h1>
+
+ <div id="TEST_ID">
+ </div>
+
+ <h2>Description</h2>
+ <p>An element without an aria-live attribute is defined in markup.
+ After the onload event completes an aria-live attribute with the
+ value 'assertive' is added to the element and a child DOM text
+ node is added to the element.</p>
+
+ <script type="text/javascript">
+
+ function addLiveRegion() {
+ var node = document.getElementById('TEST_ID');
+ node.setAttribute('aria-live', 'assertive');
+ var text_node = document.createTextNode('TEST TEXT');
+ node.appendChild(text_node);
+ }
+
+ function onload() {
+ setTimeout(addLiveRegion,1000);
+ }
+
+ window.addEventListener('load', onload);
+ </script>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/676.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/676.html
new file mode 100644
index 00000000000..0e193cbe33d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/676.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 676</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 676</h1>
+
+ <div id="TEST_ID">
+ </div>
+
+ <h2>Description</h2>
+ <p>An element without an aria-live attribute is defined in markup.
+ After the onload event completes a new element with an aria-live attribute with the
+ value 'assertive' is added to the document and a child element and text
+ node is added to the element with the aria-live attribute.</p>
+
+ <script type="text/javascript">
+
+ function addElement() {
+ var node = document.getElementById('TEST_ID');
+ var element_node = document.createElement('span');
+ element_node.setAttribute('aria-live','assertive');
+ var text_node = document.createTextNode('Text added in a span element on load');
+ element_node.appendChild(text_node);
+ node.appendChild(element_node);
+ }
+
+ function onload() {
+ setTimeout(addElement,1000);
+ }
+
+ window.addEventListener('load', onload);
+ </script>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/677.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/677.html
new file mode 100644
index 00000000000..e93361c5838
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/677.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 677</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 677</h1>
+
+ <div aria-live="polite" >
+ <span id="TEST_ID" style="display: none">Text in markup</span>
+ </div>
+
+ <h2>Description</h2>
+ <p>An element with an aria-live attribute is defined in markup with the value="polite"
+ which has a child DOM element node with text content that is hidden using CSS display="none".
+ After the onload event completes a child DOM element node with text content has the
+ CSS dsiplay property changed to display="block".</p>
+
+ <script type="text/javascript">
+
+ function showElement() {
+ var node = document.getElementById('TEST_ID');
+ node.style.display = 'block';
+ }
+
+ function onload() {
+ setTimeout(showElement,1000);
+ }
+
+ window.addEventListener('load', onload);
+ </script>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/678.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/678.html
new file mode 100644
index 00000000000..68699e38c73
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/678.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 678</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 678</h1>
+
+ <div aria-live="assertive" >
+ <span id="TEST_ID" style="display: none">Text in markup</span>
+ </div>
+
+ <h2>Description</h2>
+ <p>An element with an aria-live attribute is defined in markup with the
+ value="assertive" which has a child DOM element node with text content
+ that is hidden using CSS display="none". After the onload event completes
+ a child DOM element node with text content has the CSS dsiplay property
+ changed to display="block".</p>
+
+ <script type="text/javascript">
+
+ function showElement() {
+ var node = document.getElementById('TEST_ID');
+ node.style.display = 'block';
+ }
+
+ function onload() {
+ setTimeout(showElement,1000);
+ }
+
+ window.addEventListener('load', onload);
+ </script>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/679.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/679.html
new file mode 100644
index 00000000000..6bb8b2da9ac
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/679.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 679</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 679</h1>
+
+ <div aria-live="polite" >
+ <span>Text before test : </span>
+ <span id="TEST_ID" style="visibility: hidden">TEST TEXT</span>
+ <span> : Text after test</span>
+ </div>
+
+ <h2>Description</h2>
+
+ <p>An element with an aria-live attribute is defined in markup with the value="polite" which has a child
+ DOM element node with text content that is hidden using CSS visibility="hidden".
+ After the onload event completes a child DOM element node with text content has the
+ CSS dsiplay property changed to visibility="visible".</p>
+
+ <script type="text/javascript">
+
+ function showElement() {
+ var node = document.getElementById('TEST_ID');
+ node.style.visibility = 'visible';
+ }
+
+ function onload() {
+ setTimeout(showElement,1000);
+ }
+
+ window.addEventListener('load', onload);
+ </script>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/680.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/680.html
new file mode 100644
index 00000000000..ef774fd3c2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/680.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 680</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 680</h1>
+
+ <div aria-live="assertive" >
+ <span>Text before test : </span>
+ <span id="TEST_ID" style="visibility: hidden">TEST TEXT</span>
+ <span> : Text after test</span>
+ </div>
+
+ <h2>Description</h2>
+ <p>An element with an aria-live attribute is defined in markup with the value="assertive"
+ which has a child DOM element node with text content that is hidden using CSS visibility="hidden".
+ After the onload event completes a child DOM element node with text content has the CSS dsiplay
+ property changed to visibility="visible".</p>
+
+ <script type="text/javascript">
+
+ function showElement() {
+ var node = document.getElementById('TEST_ID');
+ node.style.visibility = 'visible';
+ }
+
+ function onload() {
+ setTimeout(showElement,1000);
+ }
+
+ window.addEventListener('load', onload);
+ </script>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/681.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/681.html
new file mode 100644
index 00000000000..fd8befe760c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/681.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 681</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 681</h1>
+
+ <div id="TEST_ID" aria-live="polite">
+ </div>
+
+ <h2>Description</h2>
+ <p>An element with an aria-live attribute is added to the document by a script during the onload
+ event with the value="polite". After the onload event completes a child DOM text node is added
+ to the element with the aria-live attribute.</p>
+
+ <script type="text/javascript">
+
+ function addChildTextNode() {
+ var node = document.getElementById('TEST_ID');
+ var text_node = document.createTextNode("TEST TEXT");
+ node.appendChild(text_node);
+ }
+
+ function onload() {
+ setTimeout(addChildTextNode,1000);
+ }
+
+ window.addEventListener('load', onload);
+ </script>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/682.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/682.html
new file mode 100644
index 00000000000..b8d90ce19d9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/682.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 682</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 682</h1>
+
+ <div id="TEST_ID_1">
+ </div>
+
+ <h2>Description</h2>
+ <p>An element with an aria-live attribute is added to the document by a script during the onload
+ event with the value="assertive". After the onload event completes a child DOM text node is
+ added to the element with the aria-live attribute.</p>
+
+ <script type="text/javascript">
+
+ function addChildTextNode() {
+ var node = document.getElementById('TEST_ID_2');
+ var text_node = document.createTextNode("TEST TEXT");
+ node.appendChild(text_node);
+ }
+
+ function addLiveRegion() {
+ var node = document.getElementById('TEST_ID_1');
+ var element_node = document.createElement('div');
+ element_node.setAttribute('id', 'TEST_ID_2');
+ element_node.setAttribute('aria-live', 'assertive');
+ node.appendChild(element_node);
+ setTimeout(addChildTextNode,1000);
+ }
+
+ function onload() {
+ addLiveRegion();
+ }
+
+ window.addEventListener('load', onload);
+ </script>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/683.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/683.html
new file mode 100644
index 00000000000..ca45f2b55c8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/683.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 683</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 683</h1>
+
+ <div id="TEST_ID_1">
+ </div>
+
+ <h2>Description</h2>
+ <p>An element with an aria-live attribute is added to the document by a script during the onload
+ event with the value="polite". After the onload event completes a child DOM element node is
+ added to the element with the aria-live attribute.</p>
+
+ <script type="text/javascript">
+
+ function addChildElementNode() {
+ var node = document.getElementById('TEST_ID_2');
+ var element_node = document.createElement('div');
+ var text_node = document.createTextNode("TEST TEXT");
+ element_node.appendChild(text_node);
+ node.appendChild(element_node);
+ }
+
+ function addLiveRegion() {
+ var node = document.getElementById('TEST_ID_1');
+ var live_node = document.createElement('div');
+ live_node.setAttribute('id', 'TEST_ID_2');
+ live_node.setAttribute('aria-live', 'polite');
+ node.appendChild(live_node);
+ setTimeout(addChildElementNode,1000);
+ }
+
+ function onload() {
+ addLiveRegion();
+ }
+
+ window.addEventListener('load', onload);
+ </script>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/684.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/684.html
new file mode 100644
index 00000000000..2abea5c468d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/684.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 684</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 684</h1>
+
+ <div id="TEST_ID_1">
+ </div>
+
+ <h2>Description</h2>
+ <p>An element with an aria-live attribute is added to the document by a script during
+ the onload event with the value="assertive". After the onload event completes a
+ child DOM element node is added to the element with the aria-live attribute.</p>
+
+ <script type="text/javascript">
+
+ function addChildElementNode() {
+ var node = document.getElementById('TEST_ID_2');
+ var element_node = document.createElement('div');
+ element_node.setAttribute('aria-live', 'polite');
+ node.appendChild(element_node);
+ }
+
+ function addLiveRegion() {
+ var node = document.getElementById('TEST_ID_1');
+ var element_node = document.createElement('div');
+ element_node.setAttribute('id', 'TEST_ID_2');
+ element_node.setAttribute('aria-live', 'assertive');
+ node.appendChild(element_node);
+ setTimeout(addChildElementNode, 1000);
+ }
+
+ function onload() {
+ addLiveRegion();
+ }
+
+ window.addEventListener('load', onload);
+ </script>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/685.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/685.html
new file mode 100644
index 00000000000..90cb71f025d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/685.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 685</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 685</h1>
+
+ <div id="TEST_ID_1">
+ </div>
+
+ <h2>Description</h2>
+ <p>An element with an aria-live attribute is added to the document by a script during the onload
+ event with the value="polite" and the element has a child DOM element node with text content
+ that is hidden using CSS display="none". After the onload event completes a child DOM element
+ node with text content has the CSS display property changed to display="block".</p>
+
+ <script type="text/javascript">
+
+ function showElement() {
+ var node = document.getElementById('TEST_ID_3');
+ node.style.display = "block";
+ }
+
+ function addChildElementNode() {
+ var node = document.getElementById('TEST_ID_2');
+ var element_node = document.createElement('div');
+ element_node.setAttribute('id', 'TEST_ID_3');
+ element_node.setAttribute('style', 'display: none');
+ var text_node = document.createTextNode("TEST TEXT");
+ element_node.appendChild(text_node);
+ node.appendChild(element_node);
+ setTimeout(showElement,1000);
+ }
+
+ function addLiveRegion() {
+ var node = document.getElementById('TEST_ID_1');
+ var element_node = document.createElement('div');
+ element_node.setAttribute('id', 'TEST_ID_2');
+ element_node.setAttribute('aria-live', 'polite');
+ node.appendChild(element_node);
+ setTimeout(addChildElementNode,1000);
+ }
+
+ function onload() {
+ addLiveRegion();
+ }
+
+ window.addEventListener('load', onload);
+ </script>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/686.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/686.html
new file mode 100644
index 00000000000..9cf141d69cc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/686.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 686</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 686</h1>
+
+ <div id="TEST_ID_1">
+ </div>
+
+ <h2>Description</h2>
+ <p>An element with an aria-live attribute is added to the document by a script during the onload
+ event with the value="assertive" and the element has a child DOM element node with text content
+ that is hidden using CSS display="none". After the onload event completes a child DOM element
+ node with text content has the CSS display property changed to display="block".</p>
+
+ <script type="text/javascript">
+
+ function showElement() {
+ var node = document.getElementById('TEST_ID_3');
+ node.style.display = "block";
+ }
+
+ function addChildElementNode() {
+ var node = document.getElementById('TEST_ID_2');
+ var element_node = document.createElement('div');
+ element_node.setAttribute('id', 'TEST_ID_3');
+ element_node.setAttribute('style', 'display: none');
+ var text_node = document.createTextNode("TEST TEXT");
+ element_node.appendChild(text_node);
+ node.appendChild(element_node);
+ setTimeout(showElement,1000);
+ }
+
+ function addLiveRegion() {
+ var node = document.getElementById('TEST_ID_1');
+ var element_node = document.createElement('div');
+ element_node.setAttribute('id', 'TEST_ID_2');
+ element_node.setAttribute('aria-live', 'assertive');
+ node.appendChild(element_node);
+ setTimeout(addChildElementNode,1000);
+ }
+
+ function onload() {
+ addLiveRegion();
+ }
+
+ window.addEventListener('load', onload);
+ </script>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/687.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/687.html
new file mode 100644
index 00000000000..2294b4c866a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/687.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 687</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 687</h1>
+
+ <div id="TEST_ID_1">
+ </div>
+
+ <h2>Description</h2>
+ <p>An element with an aria-live attribute is added to the document by a script during
+ the onload event with the value="polite" and the element has a child DOM element node
+ with text content that is hidden using CSS visibility="hidden". After the onload
+ event completes a child DOM element node with text content has the CSS display property
+ changed to visibility="visible".</p>
+
+ <script type="text/javascript">
+
+ function showElement() {
+ var node = document.getElementById('TEST_ID_3');
+ node.setAttribute('style', 'visibility: visible');
+ }
+
+ function addChildElementNode() {
+ var node = document.getElementById('TEST_ID_2');
+ var element_node = document.createElement('div');
+ element_node.setAttribute('id', 'TEST_ID_3');
+ element_node.setAttribute('style', 'visibility: hidden');
+ var text_node = document.createTextNode("TEST TEXT");
+ element_node.appendChild(text_node);
+ node.appendChild(element_node);
+ setTimeout(showElement,1000);
+ }
+
+ function addLiveRegion() {
+ var node = document.getElementById('TEST_ID_1');
+ var element_node = document.createElement('div');
+ element_node.setAttribute('id', 'TEST_ID_2');
+ element_node.setAttribute('aria-live', 'polite');
+ node.appendChild(element_node);
+ setTimeout(addChildElementNode,1000);
+ }
+
+ function onload() {
+ addLiveRegion();
+ }
+
+ window.addEventListener('load', onload);
+ </script>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/688.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/688.html
new file mode 100644
index 00000000000..cc488b8a239
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/688.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 688</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 688</h1>
+
+ <div id="TEST_ID_1">
+ </div>
+
+ <h2>Description</h2>
+ <p>An element with an aria-live attribute is added to the document by a script
+ during the onload event with the value="assertive" and the element has a child
+ DOM element node with text content that is hidden using CSS visibility="hidden".
+ After the onload event completes a child DOM element node with text content
+ has the CSS display property changed to visibility="visible".</p>
+
+ <script type="text/javascript">
+
+ function showElement() {
+ var node = document.getElementById('TEST_ID_3');
+ node.setAttribute('style', 'visibility: visible');
+ }
+
+ function addChildElementNode() {
+ var node = document.getElementById('TEST_ID_2');
+ var element_node = document.createElement('div');
+ element_node.setAttribute('id', 'TEST_ID_3');
+ element_node.setAttribute('style', 'visibility: hidden');
+ var text_node = document.createTextNode("TEST TEXT");
+ element_node.appendChild(text_node);
+ node.appendChild(element_node);
+ setTimeout(showElement,1000);
+ }
+
+ function addLiveRegion() {
+ var node = document.getElementById('TEST_ID_1');
+ var element_node = document.createElement('div');
+ element_node.setAttribute('id', 'TEST_ID_2');
+ element_node.setAttribute('aria-live', 'assertive');
+ node.appendChild(element_node);
+ setTimeout(addChildElementNode,1000);
+ }
+
+ function onload() {
+ addLiveRegion();
+ }
+
+ window.addEventListener('load', onload);
+ </script>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/689.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/689.html
new file mode 100644
index 00000000000..714b34b0918
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/689.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 689</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 689</h1>
+
+ <div id="TEST_ID_1">
+ </div>
+
+ <h2>Description</h2>
+ <p>The aria-live attribute is added to an element in the document by a script after the
+ onload event completes with the value="polite". After the aria-live attribute is added,
+ a child DOM text node is added to the element with the aria-live attribute.</p>
+
+ <script type="text/javascript">
+
+ function addChildTextNode() {
+ var node = document.getElementById('TEST_ID_2');
+ var text_node = document.createTextNode("TEST TEXT");
+ node.appendChild(text_node);
+ }
+
+ function addLiveRegion() {
+ var node = document.getElementById('TEST_ID_1');
+ var element_node = document.createElement('div');
+ element_node.setAttribute('id', 'TEST_ID_2');
+ element_node.setAttribute('aria-live', 'polite');
+ node.appendChild(element_node);
+ setTimeout(addChildTextNode,500);
+ }
+
+ function onload() {
+ setTimeout(addLiveRegion,1000);
+ }
+
+ window.addEventListener('load', onload);
+ </script>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/690.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/690.html
new file mode 100644
index 00000000000..3f189e59add
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/690.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 690</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 690</h1>
+
+ <div id="TEST_ID_1">
+ </div>
+
+ <h2>Description</h2>
+ <p>The aria-live attribute is added to an element in the document by a script after
+ the onload event completes with the value="assertive". After the aria-live attribute
+ is added, a child DOM text node is added to the element with the aria-live attribute.</p>
+
+ <script type="text/javascript">
+
+ function addChildTextNode() {
+ var node = document.getElementById('TEST_ID_2');
+ var text_node = document.createTextNode("TEST TEXT");
+ node.appendChild(text_node);
+ }
+
+ function addLiveRegion() {
+ var node = document.getElementById('TEST_ID_1');
+ var element_node = document.createElement('div');
+ element_node.setAttribute('id', 'TEST_ID_2');
+ element_node.setAttribute('aria-live', 'assertive');
+ node.appendChild(element_node);
+ setTimeout(addChildTextNode,500);
+ }
+
+ function onload() {
+ setTimeout(addLiveRegion,1000);
+ }
+
+ window.addEventListener('load', onload);
+ </script>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/691.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/691.html
new file mode 100644
index 00000000000..85bd8c9402f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/691.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 691</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 691</h1>
+
+ <div id="TEST_ID_1">
+ </div>
+
+ <h2>Description</h2>
+ <p>The aria-live attribute is added to an element in the document by a script
+ after the onload event completes with the value="polite". After the aria-live
+ attribute is added, a child DOM element node is added to the element with
+ the aria-live attribute.</p>
+
+ <script type="text/javascript">
+
+ function addChildElementNode() {
+ var node = document.getElementById('TEST_ID_2');
+ var element_node = document.createElement('div');
+ var text_node = document.createTextNode("TEST TEXT");
+ element_node.appendChild(text_node);
+ node.appendChild(element_node);
+ }
+
+ function addLiveRegion() {
+ var node = document.getElementById('TEST_ID_1');
+ var element_node = document.createElement('div');
+ element_node.setAttribute('id', 'TEST_ID_2');
+ element_node.setAttribute('aria-live', 'polite');
+ node.appendChild(element_node);
+ setTimeout(addChildElementNode,500);
+ }
+
+ function onload() {
+ setTimeout(addLiveRegion,1000);
+ }
+
+ window.addEventListener('load', onload);
+ </script>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/692.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/692.html
new file mode 100644
index 00000000000..13c16d62fec
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/692.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 692</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 692</h1>
+
+ <div id="TEST_ID_1">
+ </div>
+
+ <h2>Description</h2>
+ <p>The aria-live attribute is added to an element in the document by a script after
+ the onload event completes with the value="assertive". After the aria-live attribute
+ is added, a child DOM element node is added to the element with the aria-live attribute.</p>
+
+ <script type="text/javascript">
+
+ function addChildElementNode() {
+ var node = document.getElementById('TEST_ID_2');
+ var element_node = document.createElement('div');
+ element_node.setAttribute('aria-live', 'polite');
+ node.appendChild(element_node);
+ }
+
+ function addLiveRegion() {
+ var node = document.getElementById('TEST_ID_1');
+ var element_node = document.createElement('div');
+ element_node.setAttribute('id', 'TEST_ID_2');
+ element_node.setAttribute('aria-live', 'assertive');
+ node.appendChild(element_node);
+ setTimeout(addChildElementNode,500);
+ }
+
+ function onload() {
+ setTimeout(addLiveRegion,1000);
+ }
+
+ window.addEventListener('load', onload);
+ </script>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/693.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/693.html
new file mode 100644
index 00000000000..8914d7e86ae
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/693.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 693</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 693</h1>
+
+ <div id="TEST_ID_1">
+ </div>
+
+ <h2>Description</h2>
+ <p>The aria-live attribute is added to an element in the document by a script after
+ the onload event completes with the value="polite" and the element has a child DOM
+ element node with text content that is hidden using CSS display="none". After the
+ aria-live attribute is added, the child DOM element node with text content has the
+ CSS display property changed to display="block".</p>
+
+ <script type="text/javascript">
+
+ function showElement() {
+ var node = document.getElementById('TEST_ID_2');
+ node.setAttribute('style', 'display: block');
+ }
+
+ function addChildElementNode() {
+ var element_node = document.getElementById('TEST_ID_2');
+ var text_node = document.createTextNode("TEST TEXT");
+ element_node.appendChild(text_node);
+ element_node.setAttribute('style', 'display: none');
+ setTimeout(showElement,500);
+ }
+
+ function addLiveRegion() {
+ var node = document.getElementById('TEST_ID_1');
+ var element_node = document.createElement('div');
+ element_node.setAttribute('id', 'TEST_ID_2');
+ element_node.setAttribute('aria-live', 'polite');
+ node.appendChild(element_node);
+ setTimeout(addChildElementNode,500);
+ }
+
+ function onload() {
+ setTimeout(addLiveRegion,1000);
+ }
+
+ window.addEventListener('load', onload);
+ </script>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/694.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/694.html
new file mode 100644
index 00000000000..49ee64c75e9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/694.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 694</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 694</h1>
+
+ <div id="TEST_ID_1">
+ </div>
+
+ <h2>Description</h2>
+ <p>The aria-live attribute is added to an element in the document by a script after
+ the onload event completes with the value="assertive" and the element has a child
+ DOM element node with text content that is hidden using CSS display="none". After
+ the aria-live attribute is added, the child DOM element node with text content has
+ the CSS display property changed to display="block".</p>
+
+ <script type="text/javascript">
+
+ function showElement() {
+ var node = document.getElementById('TEST_ID_3');
+ node.setAttribute('style', 'display: block');
+ }
+
+ function addChildElementNode() {
+ var node = document.getElementById('TEST_ID_2');
+ var element_node = document.createElement('div');
+ element_node.setAttribute('id', 'TEST_ID_3');
+ element_node.setAttribute('style', 'display: none');
+ var text_node = document.createTextNode("TEST TEXT");
+ element_node.appendChild(text_node);
+ node.appendChild(element_node);
+ setTimeout(showElement,500);
+ }
+
+ function addLiveRegion() {
+ var node = document.getElementById('TEST_ID_1');
+ var element_node = document.createElement('div');
+ element_node.setAttribute('id', 'TEST_ID_2');
+ element_node.setAttribute('aria-live', 'assertive');
+ node.appendChild(element_node);
+ setTimeout(addChildElementNode,500);
+ }
+
+ function onload() {
+ setTimeout(addLiveRegion,1000);
+ }
+
+ window.addEventListener('load', onload);
+ </script>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/695.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/695.html
new file mode 100644
index 00000000000..b2550c6982f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/695.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 695</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 695</h1>
+
+ <div id="TEST_ID_1">
+ </div>
+
+ <h2>Description</h2>
+ <p>The aria-live attribute is added to an element in the document by a script
+ after the onload event completes with the value="polite" and the element has
+ a child DOM element node with text content that is hidden using CSS
+ visibility="hidden". After the aria-live attribute is added, the child DOM
+ element node with text content has the CSS display property changed to visibility="visible".</p>
+
+ <script type="text/javascript">
+
+ function showElement() {
+ var node = document.getElementById('TEST_ID_3');
+ node.setAttribute('style', 'visibility: visible');
+ }
+
+ function addChildElementNode() {
+ var node = document.getElementById('TEST_ID_2');
+ var element_node = document.createElement('div');
+ element_node.setAttribute('id', 'TEST_ID_3');
+ element_node.setAttribute('style', 'visibility: hidden');
+ var text_node = document.createTextNode("TEST TEXT");
+ element_node.appendChild(text_node);
+ node.appendChild(element_node);
+ setTimeout(showElement,500);
+ }
+
+ function addLiveRegion() {
+ var node = document.getElementById('TEST_ID_1');
+ var element_node = document.createElement('div');
+ element_node.setAttribute('id', 'TEST_ID_2');
+ element_node.setAttribute('aria-live', 'assertive');
+ node.appendChild(element_node);
+ setTimeout(addChildElementNode,500);
+ }
+
+ function onload() {
+ setTimeout(addLiveRegion,1000);
+ }
+
+ window.addEventListener('load', onload);
+ </script>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/696.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/696.html
new file mode 100644
index 00000000000..a577b1d5aac
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/696.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 696</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 696</h1>
+
+ <div id="TEST_ID_1">
+ <div id="TEST_ID_2" style="visibility: hidden">TEST TEXT</div>
+ </div>
+
+ <h2>Description</h2>
+ <p>The aria-live attribute is added to an element in the document by a script after the
+ onload event completes with the value="assertive" and the element has a child DOM
+ element node with text content that is hidden using CSS visibility="hidden". After
+ the aria-live attribute is added, the child DOM element node with text content has
+ the CSS display property changed to visibility="visible".</p>
+
+ <script type="text/javascript">
+
+ function showElement() {
+ var node = document.getElementById('TEST_ID_2');
+ node.setAttribute('style', 'visibility: visible');
+ }
+
+ function addLiveRegion() {
+ var node = document.getElementById('TEST_ID_1');
+ node.setAttribute('aria-live', 'assertive');
+ setTimeout(showElement,500);
+ }
+
+ function onload() {
+ setTimeout(addLiveRegion,1000);
+ }
+
+ window.addEventListener('load', onload);
+ </script>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/697.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/697.html
new file mode 100644
index 00000000000..eed947c4417
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/697.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 697</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 697</h1>
+
+ <div id="TEST_ID_1" aria-live="polite">
+ TEST TEXT
+ </div>
+
+ <h2>Description</h2>
+ <p>An element with an aria-live attribute is defined in markup with the value="polite"
+ has a child DOM text node with content. After the onload event completes the child
+ DOM text node is deleted.</p>
+
+ <script type="text/javascript">
+
+ function deleteChildNodes() {
+ var node = document.getElementById('TEST_ID_1');
+ while (node.firstChild) node.removeChild(node.firstChild);
+ }
+
+ function onload() {
+ setTimeout(deleteChildNodes,1000);
+ }
+
+ window.addEventListener('load', onload);
+ </script>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/698.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/698.html
new file mode 100644
index 00000000000..3e90818997c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/698.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 698</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 698</h1>
+
+ <div id="TEST_ID_1" aria-live="assertive">
+ TEST TEXT
+ </div>
+
+ <h2>Description</h2>
+ <p>An element with an aria-live attribute is defined in markup with the value="assertive"
+ has a child DOM text node with content. After the onload event completes the child DOM
+ text node is deleted.</p>
+
+ <script type="text/javascript">
+
+ function deleteChildNodes() {
+ var node = document.getElementById('TEST_ID_1');
+ while (node.firstChild) node.removeChild(node.firstChild);
+ }
+
+ function onload() {
+ setTimeout(deleteChildNodes,1000);
+ }
+
+ window.addEventListener('load', onload);
+ </script>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/699.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/699.html
new file mode 100644
index 00000000000..f306cb1c45b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/699.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 699</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 699</h1>
+
+ <div id="TEST_ID_1" aria-live="polite">
+ <div>TEST TEXT</div>
+ </div>
+
+ <h2>Description</h2>
+ <p>An element with an aria-live attribute is defined in markup with the value="polite"
+ has a child DOM element node that contains text content. After the onload event completes
+ the child DOM element node is deleted.</p>
+
+ <script type="text/javascript">
+
+ function deleteChildNodes() {
+ var node = document.getElementById('TEST_ID_1');
+ while (node.firstChild) node.removeChild(node.firstChild);
+ }
+
+ function onload() {
+ setTimeout(deleteChildNodes,1000);
+ }
+
+ window.addEventListener('load', onload);
+ </script>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/700.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/700.html
new file mode 100644
index 00000000000..de12aff296f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/700.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 700</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 700</h1>
+
+ <div id="TEST_ID_1" aria-live="assertive">
+ <div>TEST TEXT</div>
+ </div>
+
+ <h2>Description</h2>
+ <p>An element with an aria-live attribute is defined in markup with the
+ value="assertive" has a child DOM element node that contains text content.
+ After the onload event completes the child DOM element node is deleted.</p>
+
+ <script type="text/javascript">
+
+ function deleteChildNodes() {
+ var node = document.getElementById('TEST_ID_1');
+ while (node.firstChild) node.removeChild(node.firstChild);
+ }
+
+ function onload() {
+ setTimeout(deleteChildNodes,1000);
+ }
+
+ window.addEventListener('load', onload);
+ </script>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/701.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/701.html
new file mode 100644
index 00000000000..942cab36957
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/701.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 701</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 701</h1>
+
+ <div id="TESTZ" aria-live="polite">
+ Text before: <span id="TEST_ID_1">TEST TEXT</span> :text after
+ </div>
+
+ <h2>Description</h2>
+ <p>An element with an aria-live attribute is defined in markup with
+ the value="polite" has a child DOM element node that contains text
+ content. After the onload event completes the CSS 'display' property
+ of the child DOM element node is changed to display="none".</p>
+
+ <script type="text/javascript">
+
+ function hideElement() {
+ var node = document.getElementById('TEST_ID_1');
+ node.setAttribute('style', 'display: none');
+ }
+
+ function onload() {
+ setTimeout(hideElement,1000);
+ }
+
+ window.addEventListener('load', onload);
+ </script>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/702.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/702.html
new file mode 100644
index 00000000000..f46eb1d022f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/702.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 702</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 702</h1>
+
+ <div id="TESTZ" aria-live="assertive">
+ Text before: <span id="TEST_ID_1">TEST TEXT</span> :text after
+ </div>
+
+ <h2>Description</h2>
+ <p>An element with an aria-live attribute is defined in markup with the value="assertive"
+ has a child DOM element node that contains text content. After the onload event completes
+ the CSS 'display' property of the child DOM element node is changed to display="none".</p>
+
+ <script type="text/javascript">
+
+ function hideElement() {
+ var node = document.getElementById('TEST_ID_1');
+ node.setAttribute('style', 'display: none');
+ }
+
+ function onload() {
+ setTimeout(hideElement,1000);
+ }
+
+ window.addEventListener('load', onload);
+ </script>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/703.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/703.html
new file mode 100644
index 00000000000..661eed254f7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/703.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 703</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 703</h1>
+
+ <div id="TESTZ" aria-live="polite">
+ Text before: <span id="TEST_ID_1">TEST TEXT</span> :text after
+ </div>
+
+ <h2>Description</h2>
+ <p>An element with an aria-live attribute is defined in markup with the value="polite"
+ has a child DOM element node that contains text content. After the onload event
+ completes the CSS 'visibility' property of the child DOM element node is changed
+ to visibility="hidden".</p>
+
+ <script type="text/javascript">
+
+ function hideElement() {
+ var node = document.getElementById('TEST_ID_1');
+ node.setAttribute('style', 'visibility: hidden');
+ }
+
+ function onload() {
+ setTimeout(hideElement,1000);
+ }
+
+ window.addEventListener('load', onload);
+ </script>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/704.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/704.html
new file mode 100644
index 00000000000..bb68b58ac3e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/704.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 704</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 704</h1>
+
+ <div id="TESTZ" aria-live="assertive">
+ Text before: <span id="TEST_ID_1">TEST TEXT</span> :text after
+ </div>
+
+ <h2>Description</h2>
+ <p>An element with an aria-live attribute is defined in markup with the value="assertive"
+ has a child DOM element node that contains text content. After the onload event completes
+ the CSS 'visibility' property of the child DOM element node is changed to visibility="hidden".</p>
+
+ <script type="text/javascript">
+
+ function hideElement() {
+ var node = document.getElementById('TEST_ID_1');
+ node.setAttribute('style', 'visibility: hidden');
+ }
+
+ function onload() {
+ setTimeout(hideElement,1000);
+ }
+
+ window.addEventListener('load', onload);
+ </script>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/705.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/705.html
new file mode 100644
index 00000000000..d1f8cb84af1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/705.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 705</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 705</h1>
+
+ <div id="TEST_ID_1">
+ </div>
+
+ <h2>Description</h2>
+ <p>An element with an aria-live attribute is added to the document by a script
+ during the onload event with the value="polite" and the element has a child DOM
+ text node with content. After the onload event completes the child DOM text
+ node is deleted.</p>
+
+ <script type="text/javascript">
+
+ function deleteChildNodes() {
+ var node = document.getElementById('TEST_ID_2');
+ while (node.firstChild) node.removeChild(node.firstChild);
+ }
+
+ function addLiveRegion() {
+ var node = document.getElementById('TEST_ID_1');
+ var element_node = document.createElement('div');
+ element_node.setAttribute('id', 'TEST_ID_2');
+ element_node.setAttribute('aria-live', 'polite');
+ var text_node = document.createTextNode('TEST TEXT');
+ element_node.appendChild(text_node);
+ node.appendChild(element_node);
+ setTimeout(deleteChildNodes,500);
+ }
+
+ function onload() {
+ addLiveRegion();
+ }
+
+ window.addEventListener('load', onload);
+ </script>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/706.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/706.html
new file mode 100644
index 00000000000..80f605d0ca1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/706.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 706</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 706</h1>
+
+ <div id="TEST_ID_1">
+ </div>
+
+ <h2>Description</h2>
+ <p>An element with an aria-live attribute is added to the document by a script during the onload
+ event with the value="assertive" and the element has a child DOM text node with content. After
+ the onload event completes the child DOM text node is deleted.</p>
+
+ <script type="text/javascript">
+
+ function deleteChildNodes() {
+ var node = document.getElementById('TEST_ID_2');
+ while (node.firstChild) node.removeChild(node.firstChild);
+ }
+
+ function addLiveRegion() {
+ var node = document.getElementById('TEST_ID_1');
+
+ var element_node = document.createElement('div');
+ element_node.setAttribute('aria-live', 'assertive');
+ element_node.setAttribute('id', 'TEST_ID_2');
+
+ var text_node = document.createTextNode('TEST TEXT');
+ element_node.appendChild(text_node);
+ node.appendChild(element_node);
+
+ setTimeout(deleteChildNodes,1000);
+ }
+
+ function onload() {
+ addLiveRegion();
+ }
+
+ window.addEventListener('load', onload);
+ </script>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/707.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/707.html
new file mode 100644
index 00000000000..8490112b287
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/707.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 707</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 707</h1>
+
+ <div id="TEST_ID_1">
+ </div>
+
+ <h2>Description</h2>
+ <p>An element with an aria-live attribute is added to the document by a script
+ during the onload event with the value="polite" and the element has a child
+ DOM element node that contains text content. After the onload event completes
+ the child DOM element node is deleted.</p>
+
+ <script type="text/javascript">
+
+ function deleteChildNodes() {
+ var node = document.getElementById('TEST_ID_2');
+ while (node.firstChild) node.removeChild(node.firstChild);
+ }
+
+ function addLiveRegion() {
+ var node = document.getElementById('TEST_ID_1');
+
+ var live_node = document.createElement('div');
+ live_node.setAttribute('aria-live', 'polite');
+ live_node.setAttribute('id', 'TEST_ID_2');
+
+ var element_node = document.createElement('div');
+
+ var text_node = document.createTextNode('TEST TEXT');
+ element_node.appendChild(text_node);
+ live_node.appendChild(element_node);
+ node.appendChild(live_node);
+ setTimeout(deleteChildNodes,1000);
+ }
+
+ function onload() {
+ addLiveRegion();
+ }
+
+ window.addEventListener('load', onload);
+ </script>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/708.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/708.html
new file mode 100644
index 00000000000..e1bfcd10ec6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/708.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 708</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 708</h1>
+
+ <div id="TEST_ID_1">
+ </div>
+
+ <h2>Description</h2>
+ <p>An element with an aria-live attribute is added to the document by a script during
+ the onload event with the value="assertive" and the element has a child DOM element
+ node that contains text content. After the onload event completes the child DOM
+ element node is deleted.</p>
+
+ <script type="text/javascript">
+
+
+ function deleteChildNodes() {
+ var node = document.getElementById('TEST_ID_2');
+ while (node.firstChild) node.removeChild(node.firstChild);
+ }
+
+ function addLiveRegion() {
+ var node = document.getElementById('TEST_ID_1');
+
+ var live_node = document.createElement('div');
+ live_node.setAttribute('aria-live', 'assertive');
+ live_node.setAttribute('id', 'TEST_ID_2');
+
+ var element_node = document.createElement('div');
+
+ var text_node = document.createTextNode('TEST TEXT');
+
+ element_node.appendChild(text_node);
+ live_node.appendChild(element_node);
+ node.appendChild(live_node);
+
+ setTimeout(deleteChildNodes,1000);
+ }
+
+ function onload() {
+ addLiveRegion();
+ }
+
+ window.addEventListener('load', onload);
+ </script>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/709.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/709.html
new file mode 100644
index 00000000000..321b85273fd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/709.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 709</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 709</h1>
+
+ <div id="TEST_ID_1">
+ </div>
+
+ <h2>Description</h2>
+ <p>An element with an aria-live attribute is added to the document by a script during
+ the onload event with the value="polite" and the element has a child DOM element node
+ that contains text content. After the onload event completes the CSS 'display'
+ property of the child DOM element node is changed to display="none".</p>
+
+ <script type="text/javascript">
+
+
+ function hideElement() {
+ var node = document.getElementById('TEST_ID_2');
+ node.setAttribute('style', 'display: none');
+ }
+
+ function addLiveRegion() {
+ var node = document.getElementById('TEST_ID_1');
+
+ var live_node = document.createElement('div');
+ live_node.setAttribute('aria-live', 'polite');
+ live_node.setAttribute('id','TESTZ');
+
+ var element_node = document.createElement('div');
+ element_node.setAttribute('id', 'TEST_ID_2');
+
+ var text_node = document.createTextNode('TEST TEXT');
+
+ element_node.appendChild(text_node);
+ live_node.appendChild(element_node);
+ node.appendChild(live_node);
+
+ setTimeout(hideElement,1000);
+ }
+
+ function onload() {
+ addLiveRegion();
+ }
+
+ window.addEventListener('load', onload);
+ </script>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/710.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/710.html
new file mode 100644
index 00000000000..872643f66eb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/710.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 710</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 710</h1>
+
+ <div id="TEST_ID_1">
+ </div>
+
+ <h2>Description</h2>
+ <p>An element with an aria-live attribute is added to the document by a script during
+ the onload event with the value="assertive" and the element has a child DOM element
+ node that contains text content. After the onload event completes the CSS 'display'
+ property of the child DOM element node is changed to display="none".</p>
+
+ <script type="text/javascript">
+
+
+ function hideElement() {
+ var node = document.getElementById('TEST_ID_2');
+ node.setAttribute('style', 'display: none');
+ }
+
+ function addLiveRegion() {
+ var node = document.getElementById('TEST_ID_1');
+
+ var live_node = document.createElement('div');
+ live_node.setAttribute('aria-live', 'assertive');
+ live_node.setAttribute('id','TESTZ');
+
+ var element_node = document.createElement('div');
+ element_node.setAttribute('id', 'TEST_ID_2');
+
+ var text_node = document.createTextNode('TEST TEXT');
+
+ element_node.appendChild(text_node);
+ live_node.appendChild(element_node);
+ node.appendChild(live_node);
+
+ setTimeout(hideElement,1000);
+ }
+
+ function onload() {
+ addLiveRegion();
+ }
+
+ window.addEventListener('load', onload);
+ </script>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/711.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/711.html
new file mode 100644
index 00000000000..7b4375c74d0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/711.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 711</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 711</h1>
+
+ <div id="TEST_ID_1">
+ </div>
+
+ <h2>Description</h2>
+ <p>An element with an aria-live attribute is added to the document by a script
+ during the onload event with the value="polite" and the element has a child
+ DOM element node that contains text content. After the onload event completes
+ the CSS 'visibility' property of the child DOM element node is changed
+ to visibility="hidden".</p>
+
+ <script type="text/javascript">
+
+
+ function hideElement() {
+ var node = document.getElementById('TEST_ID_2');
+ node.setAttribute('style', 'visibility: hidden');
+ }
+
+ function addLiveRegion() {
+ var node = document.getElementById('TEST_ID_1');
+
+ var live_node = document.createElement('div');
+ live_node.setAttribute('aria-live', 'polite');
+ live_node.setAttribute('id', 'TESTZ');
+
+ var element_node = document.createElement('div');
+ element_node.setAttribute('id', 'TEST_ID_2');
+
+ var text_node = document.createTextNode('TEST TEXT');
+
+ element_node.appendChild(text_node);
+ live_node.appendChild(element_node);
+ node.appendChild(live_node);
+
+ setTimeout(hideElement,1000);
+ }
+
+ function onload() {
+ addLiveRegion();
+ }
+
+ window.addEventListener('load', onload);
+ </script>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/712.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/712.html
new file mode 100644
index 00000000000..3c6d69d3377
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/712.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 712</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 712</h1>
+
+ <div id="TEST_ID_1">
+ </div>
+
+ <h2>Description</h2>
+ <p>An element with an aria-live attribute is added to the document by a
+ script during the onload event with the value="assertive" and the element
+ has a child DOM element node that contains text content. After the onload
+ event completes the CSS 'visibility' property of the child DOM element
+ node is changed to visibility="hidden".</p>
+
+ <script type="text/javascript">
+
+
+ function hideElement() {
+ var node = document.getElementById('TEST_ID_2');
+ node.setAttribute('style', 'visibility: hidden');
+ }
+
+ function addLiveRegion() {
+ var node = document.getElementById('TEST_ID_1');
+
+ var live_node = document.createElement('div');
+ live_node.setAttribute('aria-live', 'assertive');
+ live_node.setAttribute('id', 'TESTZ');
+
+ var element_node = document.createElement('div');
+ element_node.setAttribute('id', 'TEST_ID_2');
+
+ var text_node = document.createTextNode('TEST TEXT');
+
+ element_node.appendChild(text_node);
+ live_node.appendChild(element_node);
+ node.appendChild(live_node);
+
+ setTimeout(hideElement,1000);
+ }
+
+ function onload() {
+ addLiveRegion();
+ }
+
+ window.addEventListener('load', onload);
+ </script>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/713.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/713.html
new file mode 100644
index 00000000000..08f8a5b287b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/713.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 713</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 713</h1>
+
+ <div id="TEST_ID_1">
+ </div>
+
+ <h2>Description</h2>
+ <p>The aria-live attribute is added to an element in the document by a
+ script after the onload event completes with the value="polite" and
+ the element has a child DOM text node with content. After the
+ aria-live attribute is added, the child DOM text node is deleted.</p>
+
+ <script type="text/javascript">
+
+
+ function deleteChildNodes() {
+ var node = document.getElementById('TEST_ID_2');
+ while (node.firstChild) node.removeChild(node.firstChild);
+ }
+
+ function addLiveRegion() {
+ var node = document.getElementById('TEST_ID_1');
+
+ var live_node = document.createElement('div');
+ live_node.setAttribute('aria-live', 'polite');
+ live_node.setAttribute('id', 'TESTZ');
+
+ var element_node = document.createElement('div');
+ element_node.setAttribute('id', 'TEST_ID_2');
+
+ var text_node = document.createTextNode('TEST TEXT');
+
+ element_node.appendChild(text_node);
+ live_node.appendChild(element_node);
+ node.appendChild(live_node);
+
+ setTimeout(deleteChildNodes,1000);
+ }
+
+ function onload() {
+ setTimeout(addLiveRegion, 1000);
+ }
+
+ window.addEventListener('load', onload);
+ </script>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/714.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/714.html
new file mode 100644
index 00000000000..56a63f82f20
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/714.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 714</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 714</h1>
+
+ <div id="TEST_ID_1">
+ </div>
+
+ <h2>Description</h2>
+ <p>The aria-live attribute is added to an element in the document by a
+ script after the onload event completes with the value="assertive"
+ and the element has a child DOM text node with content. After the
+ aria-live attribute is added, the child DOM text node is deleted.</p>
+
+ <script type="text/javascript">
+
+ function deleteChildNodes() {
+ var node = document.getElementById('TEST_ID_2');
+ while (node.firstChild) node.removeChild(node.firstChild);
+ }
+
+ function addLiveRegion() {
+ var node = document.getElementById('TEST_ID_1');
+
+ var live_node = document.createElement('div');
+ live_node.setAttribute('aria-live', 'assertive');
+ live_node.setAttribute('id', 'TESTZ');
+
+ var element_node = document.createElement('div');
+ element_node.setAttribute('id', 'TEST_ID_2');
+
+ var text_node = document.createTextNode('TEST TEXT');
+
+ element_node.appendChild(text_node);
+ live_node.appendChild(element_node);
+ node.appendChild(live_node);
+
+ setTimeout(deleteChildNodes,500);
+ }
+
+ function onload() {
+ setTimeout(addLiveRegion,1000);
+ }
+
+ window.addEventListener('load', onload);
+ </script>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/715.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/715.html
new file mode 100644
index 00000000000..82f82b05693
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/715.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 715</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 715</h1>
+
+ <div id="TEST_ID_1">
+ </div>
+
+ <h2>Description</h2>
+ <p>The aria-live attribute is added to an element in the document by a script
+ after the onload event completes with the value="polite" and the element has
+ a child DOM element node that contains text content. After the aria-live
+ attribute is added, the child DOM element node is deleted.</p>
+
+ <script type="text/javascript">
+
+ function deleteChildNodes() {
+ var node = document.getElementById('TEST_ID_1');
+ while (node.firstChild) node.removeChild(node.firstChild);
+ }
+
+ function addLiveRegion() {
+ var node = document.getElementById('TEST_ID_1');
+
+ node.setAttribute('aria-live', 'polite');
+
+ var text_node = document.createTextNode('TEST TEXT');
+
+ node.appendChild(text_node);
+
+ setTimeout(deleteChildNodes,500);
+ }
+
+ function onload() {
+ setTimeout(addLiveRegion,1000);
+ }
+
+ window.addEventListener('load', onload);
+ </script>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/716.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/716.html
new file mode 100644
index 00000000000..3a98fad05c0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/716.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 716</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 716</h1>
+
+
+ <div id="TEST_ID_1">
+ </div>
+
+ <h2>Description</h2>
+ <p>The aria-live attribute is added to an element in the document by a script
+ after the onload event completes with the value="polite" and the element has
+ a child DOM element node that contains text content. After the aria-live
+ attribute is added, the child DOM element node is deleted.</p>
+
+ <script type="text/javascript">
+
+ function deleteChildNodes() {
+ var node = document.getElementById('TEST_ID_1');
+ while (node.firstChild) node.removeChild(node.firstChild);
+ }
+
+ function addLiveRegion() {
+ var node = document.getElementById('TEST_ID_1');
+
+ node.setAttribute('aria-live', 'assertive');
+
+ var text_node = document.createTextNode('TEST TEXT');
+
+ node.appendChild(text_node);
+
+ setTimeout(deleteChildNodes,500);
+ }
+
+ function onload() {
+ setTimeout(addLiveRegion,1000);
+ }
+
+ window.addEventListener('load', onload);
+ </script>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/717.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/717.html
new file mode 100644
index 00000000000..e4e65c3868a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/717.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 717</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 717</h1>
+
+ <div id="TEST_ID_1">
+ </div>
+
+ <h2>Description</h2>
+ <p>The aria-live attribute is added to an element in the document by a script
+ after the onload event completes with the value="polite" and the element has
+ a child DOM element node that contains text content. After the aria-live
+ attribute is added, the CSS 'display' property of the child DOM element
+ node is changed to display="none".</p>
+
+ <script type="text/javascript">
+
+ function hideElement() {
+ var node = document.getElementById('TEST_ID_2');
+ node.style.display = "none";
+ }
+
+ function addLiveRegion() {
+ var node = document.getElementById('TEST_ID_1');
+
+ var live_node = document.createElement('div');
+ live_node.setAttribute('aria-live', 'polite');
+
+ var element_node = document.createElement('div');
+ element_node.setAttribute('id', 'TEST_ID_2');
+
+ var text_node = document.createTextNode('TEST TEXT');
+
+ element_node.appendChild(text_node);
+ live_node.appendChild(element_node);
+ node.appendChild(live_node);
+
+ setTimeout(hideElement,500);
+ }
+
+ function onload() {
+ setTimeout(addLiveRegion,1000);
+ }
+
+ window.addEventListener('load', onload);
+ </script>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/718.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/718.html
new file mode 100644
index 00000000000..e662390cb05
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/718.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 718</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 718</h1>
+
+ <div id="TEST_ID_1">
+ </div>
+
+ <h2>Description</h2>
+ <p>The aria-live attribute is added to an element in the document by a script
+ after the onload event completes with the value="assertive" and the element has
+ a child DOM element node that contains text content. After the aria-live
+ attribute is added, the CSS 'display' property of the child DOM element
+ node is changed to display="none".</p>
+
+ <script type="text/javascript">
+
+ function hideElement() {
+ var node = document.getElementById('TEST_ID_2');
+ node.style.display = "none";
+ }
+
+ function addLiveRegion() {
+ var node = document.getElementById('TEST_ID_1');
+
+ var live_node = document.createElement('div');
+ live_node.setAttribute('aria-live', 'assertive');
+
+ var element_node = document.createElement('div');
+ element_node.setAttribute('id', 'TEST_ID_2');
+
+ var text_node = document.createTextNode('TEST TEXT');
+
+ element_node.appendChild(text_node);
+ live_node.appendChild(element_node);
+ node.appendChild(live_node);
+
+ setTimeout(hideElement,500);
+ }
+
+ function onload() {
+ setTimeout(addLiveRegion,1000);
+ }
+
+ window.addEventListener('load', onload);
+ </script>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/719.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/719.html
new file mode 100644
index 00000000000..4fd10b746b7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/719.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 719</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 719</h1>
+
+ <div id="TEST_ID_1">
+ </div>
+
+ <h2>Description</h2>
+ <p>The aria-live attribute is added to an element in the document by a
+ script after the onload event completes with the value="polite" and
+ the element has a child DOM element node that contains text content.
+ After the aria-live attribute is added, the CSS 'visibility' property
+ of the child DOM element node is changed to visibility="hidden".</p>
+
+ <script type="text/javascript">
+
+ function hideElement() {
+ var node = document.getElementById('TEST_ID_2');
+ node.style.visibility = "hidden";
+ }
+
+ function addLiveRegion() {
+ var node = document.getElementById('TEST_ID_1');
+
+ var live_node = document.createElement('div');
+ live_node.setAttribute('aria-live', 'polite');
+
+ var element_node = document.createElement('div');
+ element_node.setAttribute('id', 'TEST_ID_2');
+
+ var text_node = document.createTextNode('TEST TEXT');
+
+ element_node.appendChild(text_node);
+ live_node.appendChild(element_node);
+ node.appendChild(live_node);
+
+ setTimeout(hideElement,500);
+ }
+
+ function onload() {
+ setTimeout(addLiveRegion,1000);
+ }
+
+ window.addEventListener('load', onload);
+ </script>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/720.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/720.html
new file mode 100644
index 00000000000..22ab76a5349
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/accessible-name-updates/720.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 720</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 720</h1>
+
+ <div id="TEST_ID_1">
+ </div>
+
+ <h2>Description</h2>
+ <p>The aria-live attribute is added to an element in the document by a
+ script after the onload event completes with the value="assertive" and
+ the element has a child DOM element node that contains text content.
+ After the aria-live attribute is added, the CSS 'visibility' property
+ of the child DOM element node is changed to visibility="hidden".</p>
+
+ <script type="text/javascript">
+
+ function hideElement() {
+ var node = document.getElementById('TEST_ID_2');
+ node.style.visibility = "hidden";
+ }
+
+ function addLiveRegion() {
+ var node = document.getElementById('TEST_ID_1');
+
+ var live_node = document.createElement('div');
+ live_node.setAttribute('aria-live', 'assertive');
+
+ var element_node = document.createElement('div');
+ element_node.setAttribute('id', 'TEST_ID_2');
+
+ var text_node = document.createTextNode('TEST TEXT');
+
+ element_node.appendChild(text_node);
+ live_node.appendChild(element_node);
+ node.appendChild(live_node);
+
+ setTimeout(hideElement,500);
+ }
+
+ function onload() {
+ setTimeout(addLiveRegion,1000);
+ }
+
+ window.addEventListener('load', onload);
+ </script>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/aria-describedby/772.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/aria-describedby/772.html
new file mode 100644
index 00000000000..4684774cc29
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/aria-describedby/772.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>test 772
+ </title>
+ </head>
+ <body>
+ <img src="foo.jpg" id="test" alt="test" aria-describedby="t1">
+ <div id="t1">foo</div>
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/aria-describedby/773.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/aria-describedby/773.html
new file mode 100644
index 00000000000..cb1bd17ad5a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/aria-describedby/773.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>test 773
+ </title>
+ </head>
+ <body>
+ <img src="foo.jpg" id="test" alt="test" aria-describedby="t1">
+ <div id="t1" style="display:none">foo</div>
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/aria-describedby/774.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/aria-describedby/774.html
new file mode 100644
index 00000000000..0fac481545f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/aria-describedby/774.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>test 774</title>
+ </head>
+ <body>
+ <img src="foo.jpg" id="test" alt="test" aria-describedby="t1">
+ <span id="t1" role="presentation">foo</span>
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/aria-describedby/838.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/aria-describedby/838.html
new file mode 100644
index 00000000000..3a765b685dc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/aria-describedby/838.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>test 773
+ </title>
+ </head>
+ <body>
+ <img src="foo.jpg" id="test" alt="test" aria-describedby="t1">
+ <div id="t1" style="visibility:hidden">foo</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/567.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/567.html
new file mode 100644
index 00000000000..ce4c8d4c45b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/567.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>A &lt;div&gt; with role "button" followed by a modification to the value of "checkbox".</title>
+ <script type="text/javascript">
+ function changeRole (/* Element */ element, /* String */ newRole) {
+ element.setAttribute ('role', newRole);
+ element.innerHTML = "This &lt;div&gt; has role '" + newRole + "'";
+ }
+ </script>
+ </head>
+ <body>
+ <div role="button" id="test" tabindex="0" onclick="changeRole (this, 'checkbox');" onkeydown="changeRole (this, 'checkbox');">This &lt;div&gt; has role 'button'</div>
+ <p>
+ <button onclick="changeRole (document.getElementById ('test'), 'checkbox')" type="button">Change Role</button>
+ <button onclick="window.location.reload()" type="button">Reload Page</button>
+ </p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/568.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/568.html
new file mode 100644
index 00000000000..d9f06dc27d9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/568.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>A &lt;div&gt; with role "button" followed by removal of the element and its children and an insertion of a new div having role="checkbox"</title>
+ <script type="text/javascript">
+ function changeRoleByRemoval (/* Element */ element, /* String */ newRole) {
+ var parent = element.parentNode;
+ if (parent) {
+ parent.removeChild (element);
+ var div = document.createElement ('div');
+ div.setAttribute ('role', newRole);
+ div.setAttribute ('id', 'test');
+ div.setAttribute ('tabindex', '0');
+ div.setAttribute ('onclick', 'changeRoleByRemoval (this, "checkbox");');
+ div.setAttribute ('onkeydown', 'changeRoleByRemoval (this, "checkbox");');
+ div.innerHTML = "This &lt;div&gt; has role '" + newRole + "'";
+ parent.appendChild (div);
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <div>
+ <div role="button" id="test" tabindex="0" onclick="changeRoleByRemoval (this, 'checkbox');" onkeydown="changeRoleByRemoval (this, 'checkbox');">This &lt;div&gt; has role 'button'</div>
+ </div>
+ <p>
+ <button onclick="changeRoleByRemoval (document.getElementById ('test'), 'checkbox')" type="button">Change Role</button>
+ <button onclick="window.location.reload()" type="button">Reload Page</button>
+ </p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/569.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/569.html
new file mode 100644
index 00000000000..eca4e1f3e8b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/569.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>A &lt;div&gt; with role role="listbox" aria-busy="true", but no "option" descendants.</title>
+ </head>
+ <body>
+ <div id="test" role="listbox" aria-busy="true">
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/571.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/571.html
new file mode 100644
index 00000000000..41b8867616a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/571.html
@@ -0,0 +1,84 @@
+<!DOCTYPE html>
+<html><head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>In a &lt;div&gt; element with role="combobox" and aria-autocomplete="none", change values of the combobox by typing.</title>
+ <style type="text/css">
+ .hasFocus { border: 2px solid red; }
+ </style>
+ <script type="text/javascript">
+ var DEL = 8;
+ var BACK_SPACE = 72;
+ var comboInfo = {};
+
+ function initComboInfo() {
+ comboInfo.comboBox = document.getElementById ('test');
+ comboInfo.textEntry = document.getElementById ('textEntry');
+ var active = document.getElementById (comboInfo.comboBox.getAttribute ('aria-activedescendant'));
+ comboInfo.options = active.parentElement.children;
+ return active;
+ }
+
+ function matchOption(/* String */ entryVal) {
+ var theOption = null;
+
+ // Check only if entryVal is not empty.
+ //
+ if (entryVal != null && entryVal.length != 0) {
+ for (var i = 0; i < comboInfo.options.length; i++) {
+ var anOption = comboInfo.options[i];
+ var optionText = anOption.innerHTML.toLowerCase();
+ if (optionText.indexOf (entryVal) == 0) {
+ theOption = anOption;
+ break;
+ }
+ }
+ }
+ return theOption;
+ }
+
+ function updateActive (/* Element */ newActive) {
+ var oldActive = document.getElementById (comboInfo.comboBox.getAttribute ('aria-activedescendant'));
+ if (oldActive != newActive) {
+ comboInfo.comboBox.setAttribute ('aria-activedescendant', newActive.getAttribute ('id'));
+ oldActive.removeAttribute ('class');
+ newActive.setAttribute ('class', 'hasFocus');
+ }
+ }
+
+ function doOnload() {
+ var active = initComboInfo();
+ active.setAttribute ('class', 'hasFocus');
+ comboInfo.textEntry.value = active.innerHTML;
+ comboInfo.textEntry.focus();
+ }
+
+ function handleTyping (event) {
+ /* NOTE: With respect to IE, assumes IE9 as per CR criteria (http://www.w3.org/WAI/ARIA/1.0/CR/implementation-report) */
+ /* NOTE: Supports deletion only from the end of the text INPUT value */
+ var stringSoFar = event.target.value;
+
+ if (event.which == DEL || event.which == BACK_SPACE)
+ stringSoFar = stringSoFar.slice(0, stringSoFar.length-1);
+ else
+ stringSoFar = stringSoFar + String.fromCharCode (event.which);
+
+ var matchedOption = matchOption (stringSoFar.toLowerCase());
+ if (matchedOption != null)
+ updateActive (matchedOption);
+ }
+
+ </script>
+ </head>
+ <body onload="doOnload();">
+ <div id="test" role="combobox" aria-expanded="true" aria-label="Tag" aria-autocomplete="none" aria-activedescendant="o1">
+ <input id="textEntry" role="textbox" aria-owns="owned_listbox" onkeypress="handleTyping(event);" type="text">
+ <ul role="listbox" id="owned_listbox" style="list-style-type: none;">
+ <li role="option" id="o1">Zebra</li>
+ <li role="option" id="o2">Zoom</li>
+ <li role="option" id="o3">Zeta</li>
+ <li role="option" id="o4">Zaphod</li>
+ <li role="option" id="o5">Alpha</li>
+ </ul>
+ </div>
+
+</body></html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/572.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/572.html
new file mode 100644
index 00000000000..a317a1c2648
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/572.html
@@ -0,0 +1,73 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>In a &lt;div&gt; element with role="combobox" and aria-autocomplete="inline", change values of the combobox by adjusting the up and down arrow keys with focus on the textfield in the combobox.</title>
+ <style type="text/css">
+ .hasFocus { border: 2px solid red; }
+ </style>
+ <script type="text/javascript">
+ var UP = 38;
+ var DOWN = 40;
+ comboInfo = {};
+
+ function toArray (/* NodeList */ nodeList) {
+ var result = [];
+ for (var i=0; i < nodeList.length; i++) {
+ result[i] = nodeList[i];
+ }
+ return result;
+ }
+
+ function initComboInfo() {
+ comboInfo.comboBox = document.getElementById ('test');
+ comboInfo.textEntry = document.getElementById ('testEntry');
+ var active = document.getElementById (comboInfo.comboBox.getAttribute ('aria-activedescendant'));
+ comboInfo.options = toArray (active.parentElement.children);
+ return active;
+ }
+
+ function handleArrow (/* Event */ event) {
+ /* NOTE: With respect to IE, assumes IE9 as per CR criteria (http://www.w3.org/WAI/ARIA/1.0/CR/implementation-report) */
+ var active = document.getElementById (comboInfo.comboBox.getAttribute ('aria-activedescendant'));
+ var currentIndex = comboInfo.options.indexOf (active);
+ var nextIndex = currentIndex;
+ if (event.which == DOWN) {
+ nextIndex = (currentIndex + 1) % comboInfo.options.length;
+ }
+ else if (event.which == UP) {
+ nextIndex = currentIndex - 1;
+ if (nextIndex < 0)
+ nextIndex = comboInfo.options.length - 1;
+ }
+
+ if (nextIndex != currentIndex) {
+ active.removeAttribute ('class');
+ active = comboInfo.options[nextIndex];
+ comboInfo.comboBox.setAttribute ('aria-activedescendant', active.getAttribute ('id'));
+ active.setAttribute ('class', 'hasFocus');
+ event.target.value = active.innerHTML;
+ }
+ }
+
+ function doOnload() {
+ var active = initComboInfo();
+ comboInfo.textEntry.value = active.innerHTML;
+ comboInfo.textEntry.focus();
+ active.setAttribute ('class', 'hasFocus');
+ }
+
+ </script>
+ </head>
+ <body onload='doOnload()'>
+ <div id="test" role="combobox" aria-expanded="true" aria-label="Tag" aria-autocomplete="inline" aria-activedescendant="o1">
+ <input id="testEntry" type="text" role="textbox" aria-owns="owned_listbox" onkeydown='handleArrow (event)'>
+ <ul role="listbox" id="owned_listbox" style="list-style-type: none;">
+ <li role="option" id="o1">Zebra</li>
+ <li role="option" id="o2">Zoom</li>
+ <li role="option" id="o3">Zeta</li>
+ <li role="option" id="o4">Zaphod</li>
+ </ul>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/573.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/573.html
new file mode 100644
index 00000000000..388282c382d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/573.html
@@ -0,0 +1,73 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>In a &lt;div&gt; element with role="combobox" and aria-autocomplete="both", change values of the combobox by adjusting the up and down arrow keys with focus on the textfield in the combobox.</title>
+ <style type="text/css">
+ .hasFocus { border: 2px solid red; }
+ </style>
+ <script type="text/javascript">
+ var UP = 38;
+ var DOWN = 40;
+ comboInfo = {};
+
+ function toArray (/* NodeList */ nodeList) {
+ var result = [];
+ for (var i=0; i < nodeList.length; i++) {
+ result[i] = nodeList[i];
+ }
+ return result;
+ }
+
+ function initComboInfo() {
+ comboInfo.comboBox = document.getElementById ('test');
+ comboInfo.textEntry = document.getElementById ('testEntry');
+ var active = document.getElementById (comboInfo.comboBox.getAttribute ('aria-activedescendant'));
+ comboInfo.options = toArray (active.parentElement.children);
+ return active;
+ }
+
+ function handleArrow (/* Event */ event) {
+ /* NOTE: With respect to IE, assumes IE9 as per CR criteria (http://www.w3.org/WAI/ARIA/1.0/CR/implementation-report) */
+ var active = document.getElementById (comboInfo.comboBox.getAttribute ('aria-activedescendant'));
+ var currentIndex = comboInfo.options.indexOf (active);
+ var nextIndex = currentIndex;
+ if (event.which == DOWN) {
+ nextIndex = (currentIndex + 1) % comboInfo.options.length;
+ }
+ else if (event.which == UP) {
+ nextIndex = currentIndex - 1;
+ if (nextIndex < 0)
+ nextIndex = comboInfo.options.length - 1;
+ }
+
+ if (nextIndex != currentIndex) {
+ active.removeAttribute ('class');
+ active = comboInfo.options[nextIndex];
+ comboInfo.comboBox.setAttribute ('aria-activedescendant', active.getAttribute ('id'));
+ active.setAttribute ('class', 'hasFocus');
+ event.target.value = active.innerHTML;
+ }
+ }
+
+ function doOnload() {
+ var active = initComboInfo();
+ comboInfo.textEntry.value = active.innerHTML;
+ comboInfo.textEntry.focus();
+ active.setAttribute ('class', 'hasFocus');
+ }
+
+ </script>
+ </head>
+ <body onload='doOnload()'>
+ <div id="test" role="combobox" aria-expanded="true" aria-label="Tag" aria-autocomplete="both" aria-activedescendant="o2">
+ <input id="testEntry" type="text" role="textbox" aria-owns="owned_listbox" onkeydown='handleArrow (event)'>
+ <ul role="listbox" id="owned_listbox" style="list-style-type: none;">
+ <li role="option" id="o1">Zebra</li>
+ <li role="option" id="o2">Zoom</li>
+ <li role="option" id="o3">Zeta</li>
+ <li role="option" id="o4">Zaphod</li>
+ </ul>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/574.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/574.html
new file mode 100644
index 00000000000..0edd82e91de
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/574.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>A &lt;div&gt; with role="list" and a child div with role="group" who has a child of role="button".</title>
+ </head>
+ <body>
+ <div id="test" role="list">
+ <div id="listChild" role="group">
+ <span id="groupChild" role="button">List <abbr title="containing">→</abbr> group <abbr title="containing">→</abbr> button</span>
+ </div>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/575.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/575.html
new file mode 100644
index 00000000000..2672741683e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/575.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>A &lt;div&gt;with role="menu" and a child div with role="group" who has a child of role="button"..</title>
+ </head>
+ <body>
+ <div id="test" role="menu">
+ <div id="menuChild" role="group">
+ <span id="groupChild" role="button">Menu <abbr title="containing">→</abbr> group <abbr title="containing">→</abbr> button</span>
+ </div>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/576.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/576.html
new file mode 100644
index 00000000000..25ac37ce262
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/576.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>A &lt;div&gt; with role="tree" and a child div with role="group" who has a child of role="button"</title>
+ </head>
+ <body>
+ <div id="test" role="tree">
+ <div id="treeChild" role="group">
+ <span id="groupChild" role="button">Tree <abbr title="containing">→</abbr> group <abbr title="containing">→</abbr> button</span>
+ </div>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/577.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/577.html
new file mode 100644
index 00000000000..f08915bed22
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/577.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>A &lt;div&gt; with role="grid" and a child div with role="rowgroup" who has a child of role="button".</title>
+ </head>
+ <body>
+ <div id="test" role="grid">
+ <div id="gridChild" role="rowgroup">
+ <span id="rowgroupChild" role="button">Grid <abbr title="containing">→</abbr> rowgroup <abbr title="containing">→</abbr> button</span>
+ </div>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/578.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/578.html
new file mode 100644
index 00000000000..2e781e3d04a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/578.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>A page with two div elements that have role="toolbar" but not aria-label property.</title>
+ </head>
+ <body>
+ <div id="test" role="toolbar">Toolbar 1</div>
+ <div id="test2" role="toolbar">Toolbar 2</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/579.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/579.html
new file mode 100644
index 00000000000..fd2441ea6a3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/579.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>A page with one div element that has role="toolbar" but not aria-label property.</title>
+ </head>
+ <body>
+ <div id="test" role="toolbar">Toolbar 1</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/580.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/580.html
new file mode 100644
index 00000000000..5445050641a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/580.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>A div element with style="display:none" has aria-hidden="true", and then script sets style to "display: block".</title>
+ <script type="text/javascript">
+ function replaceStyle (/* Element */ element, /* String */ selector, /* String */ newValue) {
+ element.setAttribute ('style', selector + ':' + newValue);
+ if (newValue == 'block')
+ element.setAttribute ('aria-hidden', 'false');
+ else if (newValue == 'none')
+ element.setAttribute ('aria-hidden', 'true');
+ }
+ </script>
+ </head>
+ <body>
+ <div id="test" aria-hidden="true" style="display:none;">This &lt;div&gt;'s style switched from 'display:none' to 'display:block'. It's <code>aria-hidden</code> was simultaneously switched to 'false'.</div>
+ <p>
+ <button onclick="replaceStyle (document.getElementById ('test'), 'display', 'block')" type="button">Change to 'display:block'</button>
+ <button onclick="replaceStyle (document.getElementById ('test'), 'display', 'none')" type="button">Change to 'display:none'</button>
+ <button onclick="window.location.reload()" type="button">Reload Page</button>
+ </p>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/581.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/581.html
new file mode 100644
index 00000000000..bbe7143c509
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/581.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>A page with a div element with id="owned1" is referenced by two div elements that each have aria-owns="owned1".</title>
+ </head>
+ <body>
+ <div id="owner1" aria-owns="owned1">First owner of owned1</div>
+ <div id="owner2" aria-owns="owned1">Second owner of owned1</div>
+ <div id="owned1">I am owned1</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/582.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/582.html
new file mode 100644
index 00000000000..82a1f199815
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/582.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>An element with aria-setsize=5 has aria-posinset=6.</title>
+ </head>
+ <body>
+ <h2 id="label_fruit"> Available Fruit </h2>
+ <ul role="listbox" aria-labelledby="label_fruit">
+ <li role="option" aria-setsize="5" aria-posinset="6" id="test"> apples </li>
+ <li role="option" aria-setsize="5" aria-posinset="2"> bananas </li>
+ <li role="option" aria-setsize="5" aria-posinset="3"> cantaloupes </li>
+ <li role="option" aria-setsize="5" aria-posinset="4"> dates </li>
+ <li role="option" aria-setsize="5" aria-posinset="5"> kumquat </li>
+ </ul>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/584.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/584.html
new file mode 100644
index 00000000000..e784d5be04a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/author-requirements/584.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>An element with aria-setsize=1 has aria-posinset=5</title>
+ </head>
+ <body>
+ <h2 id="label_fruit"> Available Fruit </h2>
+ <ul role="listbox" aria-labelledby="label_fruit">
+ <li role="option" aria-setsize="1" aria-posinset="5" id="test"> apples </li>
+ <li role="option" aria-setsize="5" aria-posinset="2"> bananas </li>
+ <li role="option" aria-setsize="5" aria-posinset="3"> cantaloupes </li>
+ <li role="option" aria-setsize="5" aria-posinset="4"> dates </li>
+ <li role="option" aria-setsize="5" aria-posinset="5"> kumquat </li>
+ </ul>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/button-pressed/589.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/button-pressed/589.html
new file mode 100644
index 00000000000..25171dfd05d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/button-pressed/589.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>An element with role button without the aria-pressed state.</title>
+ </head>
+ <body>
+ <div id="test" role="button">This div has role button</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/button-pressed/590.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/button-pressed/590.html
new file mode 100644
index 00000000000..a5fc030cba1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/button-pressed/590.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>An element with role button with an aria-pressed state of "true".</title>
+ </head>
+ <body>
+ <div id="test" role="button" aria-pressed='true'>This div has role button, with aria-pressed='true'</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/combobox-autocomplete-list/div.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/combobox-autocomplete-list/div.html
new file mode 100644
index 00000000000..94dccb663d6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/combobox-autocomplete-list/div.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Div with role="combobox" and aria-autocomplete="list"</title>
+ </head>
+ <body>
+ <div role="combobox" aria-expanded="true" aria-label="Tag"
+ aria-autocomplete="list" aria-activedescendant="selected_option">
+ <input type="text" role="textbox" aria-owns="owned_listbox" />
+ <ul role="listbox" id="owned_listbox">
+ <li role="option">Zebra</li>
+ <li role="option" id="selected_option" aria-selected="true">Zoom</li>
+ </ul>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/combobox-autocomplete-list/input.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/combobox-autocomplete-list/input.html
new file mode 100644
index 00000000000..2dc006d995b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/combobox-autocomplete-list/input.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Input with role="combobox" and aria-autocomplete="list"</title>
+ </head>
+ <body>
+ <input tabindex="0" type="text" id="test" role="combobox" aria-label="Tag" aria-expanded="true"
+ aria-autocomplete="list" aria-owns="owned_listbox" aria-activedescendant="selected_option" />
+ <ul role="listbox" id="owned_listbox">
+ <li role="option">Zebra</li>
+ <li role="option" id="selected_option" aria-selected="true">Zoom</li>
+ </ul>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/css-attr-sel/default.png b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/css-attr-sel/default.png
new file mode 100644
index 00000000000..556809f15f9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/css-attr-sel/default.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/css-attr-sel/state-1.png b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/css-attr-sel/state-1.png
new file mode 100644
index 00000000000..7d2bbefe800
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/css-attr-sel/state-1.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/css-attr-sel/state-2.png b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/css-attr-sel/state-2.png
new file mode 100644
index 00000000000..51ce95ec28f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/css-attr-sel/state-2.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/css-attr-sel/state-3.png b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/css-attr-sel/state-3.png
new file mode 100644
index 00000000000..2e22838edc0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/css-attr-sel/state-3.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/css-attr-sel/state-4.png b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/css-attr-sel/state-4.png
new file mode 100644
index 00000000000..1bb82609970
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/css-attr-sel/state-4.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/host-language/implicit-semantics-checkbox-disparity.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/host-language/implicit-semantics-checkbox-disparity.html
new file mode 100644
index 00000000000..d5a8b099aab
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/host-language/implicit-semantics-checkbox-disparity.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Native checkbox with aria-checked that conflicts with native checked</title>
+ </head>
+ <body>
+ <form>
+ <input type="checkbox" role="checkbox" checked="checked" aria-checked="false" id="test" value="Placeholder content" />
+ </form>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/host-language/implicit-semantics-checkbox-norole.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/host-language/implicit-semantics-checkbox-norole.html
new file mode 100644
index 00000000000..717d8ac1e8a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/host-language/implicit-semantics-checkbox-norole.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Native checkbox with aria-checked but no role</title>
+ </head>
+ <body>
+ <form>
+ <input type="checkbox" checked="checked" aria-checked="mixed" id="test" value="Placeholder content" />
+ </form>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/host-language/implicit-semantics-checkbox-role.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/host-language/implicit-semantics-checkbox-role.html
new file mode 100644
index 00000000000..286e14b1b8f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/host-language/implicit-semantics-checkbox-role.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Native checkbox with aria-checked with role</title>
+ </head>
+ <body>
+ <form>
+ <input type="checkbox" checked="checked" role="checkbox" aria-checked="mixed" id="test" value="Placeholder content" />
+ </form>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/host-language/input-range-valuetext.htm b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/host-language/input-range-valuetext.htm
new file mode 100644
index 00000000000..2e6d0797335
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/host-language/input-range-valuetext.htm
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <title>valuetext</title>
+ <meta http-equiv="Content-type" content="text/html; charset=utf-8">
+</head>
+<body>
+ <input id="test" type="range" min="0" max="100" value="75" aria-valuetext="awesome">
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/live-events/test-case-live-event-1.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/live-events/test-case-live-event-1.html
new file mode 100644
index 00000000000..a04c24aa8fb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/live-events/test-case-live-event-1.html
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Live Region Event Test Case: Add text content</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <style type="text/css">
+ div#TEST_ID {
+ margin: 0.5em;
+ padding: 0.25em;
+ border: medium gray solid;
+ width: 10em;
+ }
+ </style>
+ </head>
+ <body>
+ <h1>ARIA 1.0 Live Region Event Test Case: Add text content</h1>
+
+ <div id="TEST_ID" aria-live="assertive" aria-label="charlotte">
+ </div>
+
+ <button onclick="tryAgain()">Try Again</button>
+
+ <h2>Description</h2>
+ <p>An element with an aria-live attribute with the value "assertive" has a text content added
+ 1.5 seconds after the document is loaded.</p>
+
+ <h2>Expected Results</h2>
+
+ <dl>
+ <dt>ATK/AT-SPI</dt>
+ <dd>ATK/AT-SPIevent: text_changed::insert event</dd>
+
+ <dt>AXAPI</dt>
+ <dd>AXLiveRegionChanged notification</dd>
+
+ <dt>MSAA + IAccessible2</dt>
+ <dd>IAccessible2: IA2_EVENT_TEXT_INSERTED event</dd>
+
+ <dt>MSAA + UIA Express</dt>
+ <dd>TextPattern..::.TextChangedEvent event</dd>
+
+ </dl>
+
+
+ <script type="text/javascript">
+
+ function tryAgain() {
+ var node = document.getElementById('TEST_ID');
+
+ while (node.firstChild) node.removeChild(node.firstChild);
+
+ onLoad();
+
+ }
+
+ function addText () {
+ var node = document.getElementById('TEST_ID');
+
+ var text_node = document.createTextNode('TEST TEXT ADDED');
+
+ node.appendChild(text_node);
+ }
+
+ function onLoad() {
+
+ setTimeout(addText,1500);
+
+ }
+
+ window.addEventListener('load', onLoad);
+ </script>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/live-events/test-case-live-event-2.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/live-events/test-case-live-event-2.html
new file mode 100644
index 00000000000..39cf43d79f5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/live-events/test-case-live-event-2.html
@@ -0,0 +1,80 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Live Region Event Test Case: Delete text content</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <style type="text/css">
+ div#TEST_ID {
+ margin: 0.5em;
+ padding: 0.25em;
+ border: medium gray solid;
+ width: 10em;
+ }
+ </style>
+ </head>
+ <body>
+ <h1>ARIA 1.0 Live Region Event Test Case: Delete text content</h1>
+
+ <div id="TEST_ID" aria-live="polite" >
+ TEST TEXT
+ </div>
+
+ <button onclick="tryAgain()">Try Again</button>
+
+ <h2>Description</h2>
+ <p>An element with an aria-live attribute with the value "polite" has a text content deleted
+ 1.5 seconds after the document is loaded.</p>
+
+ <h2>Expected Results</h2>
+
+ <dl>
+ <dt>ATK/AT-SPI</dt>
+ <dd>ATK/AT-SPIevent: text_changed::delete event</dd>
+
+ <dt>AXAPI</dt>
+ <dd></dd>
+ <dd>AXLiveRegionChanged notification</dd>
+
+ <dt>MSAA + IAccessible2</dt>
+ <dd>IAccessible2: IA2_EVENT_TEXT_REMOVED event</dd>
+
+ <dt>MSAA + UIA Express</dt>
+ <dd>TextPattern..::.TextChangedEvent event</dd>
+
+ </dl>
+
+
+ <script type="text/javascript">
+
+ function tryAgain() {
+ addText()
+
+ onLoad();
+
+ }
+
+ function clearText() {
+ var node = document.getElementById('TEST_ID');
+
+ while (node.firstChild) node.removeChild(node.firstChild);
+ }
+
+ function addText () {
+ var node = document.getElementById('TEST_ID');
+
+ var text_node = document.createTextNode('TEST TEXT');
+
+ node.appendChild(text_node);
+ }
+
+ function onLoad() {
+
+ setTimeout(clearText,1500);
+
+ }
+
+ window.addEventListener('load', onLoad);
+ </script>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/live-events/test-case-live-event-3.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/live-events/test-case-live-event-3.html
new file mode 100644
index 00000000000..8e49ee38e2c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/live-events/test-case-live-event-3.html
@@ -0,0 +1,76 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Live Region Event Test Case: Change text content</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <style type="text/css">
+ div#TEST_ID {
+ margin: 0.5em;
+ padding: 0.25em;
+ border: medium gray solid;
+ width: 10em;
+ }
+ </style>
+ </head>
+ <body>
+ <h1>ARIA 1.0 Live Region Event Test Case: Change text content</h1>
+
+ <div id="TEST_ID" aria-live="assertive">
+ TEST TEXT 1
+ </div>
+
+ <button onclick="tryAgain()">Try Again</button>
+
+ <h2>Description</h2>
+ <p>An element with an aria-live attribute with the value "assertive" has a text content changed
+ 1.5 seconds after the document is loaded.</p>
+
+ <h2>Expected Results</h2>
+
+ <dl>
+ <dt>ATK/AT-SPI</dt>
+ <dd>ATK/AT-SPIevent: text_changed::delete event followed by text_changed::insert event</dd>
+
+ <dt>AXAPI</dt>
+ <dd></dd>
+ <dd>AXLiveRegionChanged notification</dd>
+
+ <dt>MSAA + IAccessible2</dt>
+ <dd>IAccessible2: IA2_EVENT_TEXT_REMOVED event followed by IA2_EVENT_TEXT_INSERTED event</dd>
+
+ <dt>MSAA + UIA Express</dt>
+ <dd>TextPattern..::.TextChangedEvent event followed by another TextPattern..::.TextChangedEvent event</dd>
+
+ </dl>
+
+
+ <script type="text/javascript">
+
+ function tryAgain() {
+ changeText('TEST TEXT 1')
+ onLoad();
+ }
+
+ function changeText(str) {
+ var node = document.getElementById('TEST_ID');
+ while (node.firstChild) node.removeChild(node.firstChild);
+
+ if (typeof str !== 'string') str = 'changed test text 2';
+ addText(str)
+ }
+
+ function addText (str) {
+ var node = document.getElementById('TEST_ID');
+ var text_node = document.createTextNode(str);
+ node.appendChild(text_node);
+ }
+
+ function onLoad() {
+ setTimeout(changeText,1500);
+ }
+
+ window.addEventListener('load', onLoad);
+ </script>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/live-events/test-case-live-event-4.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/live-events/test-case-live-event-4.html
new file mode 100644
index 00000000000..a5233f3af2e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/live-events/test-case-live-event-4.html
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Live Region Event Test Case: Add text content (ALERT role)</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <style type="text/css">
+ div#TEST_ID {
+ margin: 0.5em;
+ padding: 0.25em;
+ border: medium gray solid;
+ width: 20em;
+ }
+ </style>
+ </head>
+ <body>
+ <h1>ARIA 1.0 Live Region Event Test Case: Add text content (ALERT role)</h1>
+
+ <div id="TEST_ID" role="alert" >
+ </div>
+
+ <button onclick="tryAgain()">Try Again</button>
+
+ <h2>Description</h2>
+ <p>An element with an role attribute with the value "alert" has a text content added
+ 1.5 seconds after the document is loaded.</p>
+
+ <h2>Expected Results</h2>
+
+ <dl>
+ <dt>ATK/AT-SPI</dt>
+ <dd>ATK/AT-SPIevent: text_changed::insert event</dd>
+
+ <dt>AXAPI</dt>
+ <dd>AXLiveRegionChanged notification</dd>
+
+ <dt>MSAA + IAccessible2</dt>
+ <dd>IAccessible2: IA2_EVENT_TEXT_INSERTED event</dd>
+
+ <dt>MSAA + UIA Express</dt>
+ <dd>TextPattern..::.TextChangedEvent event</dd>
+
+ </dl>
+
+
+ <script type="text/javascript">
+
+ function tryAgain() {
+ var node = document.getElementById('TEST_ID');
+
+ while (node.firstChild) node.removeChild(node.firstChild);
+
+ onLoad();
+
+ }
+
+ function addText () {
+ var node = document.getElementById('TEST_ID');
+
+ var text_node = document.createTextNode('ALERT ROLE TEST TEXT ADDED');
+
+ node.appendChild(text_node);
+ }
+
+ function onLoad() {
+
+ setTimeout(addText,1500);
+
+ }
+
+ window.addEventListener('load', onLoad);
+ </script>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/live-events/test-case-live-event-5.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/live-events/test-case-live-event-5.html
new file mode 100644
index 00000000000..914b28222c9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/live-events/test-case-live-event-5.html
@@ -0,0 +1,76 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Live Region Event Test Case: Change text content (LOG role)</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <style type="text/css">
+ div#TEST_ID {
+ margin: 0.5em;
+ padding: 0.25em;
+ border: medium gray solid;
+ width: 20em;
+ }
+ </style>
+ </head>
+ <body>
+ <h1>ARIA 1.0 Live Region Event Test Case: Change text content (LOG role)</h1>
+
+ <div id="TEST_ID" role="log">
+ LOG ROLE TEST TEXT 1
+ </div>
+
+ <button onclick="tryAgain()">Try Again</button>
+
+ <h2>Description</h2>
+ <p>An element with an role attribute with the value "log" has a text content changed
+ 1.5 seconds after the document is loaded.</p>
+
+ <h2>Expected Results</h2>
+
+ <dl>
+ <dt>ATK/AT-SPI</dt>
+ <dd>ATK/AT-SPIevent: text_changed::delete event followed by text_changed::insert event</dd>
+
+ <dt>AXAPI</dt>
+ <dd></dd>
+ <dd>AXLiveRegionChanged notification</dd>
+
+ <dt>MSAA + IAccessible2</dt>
+ <dd>IAccessible2: IA2_EVENT_TEXT_REMOVED event followed by IA2_EVENT_TEXT_INSERTED event</dd>
+
+ <dt>MSAA + UIA Express</dt>
+ <dd>TextPattern..::.TextChangedEvent event followed by another TextPattern..::.TextChangedEvent event</dd>
+
+ </dl>
+
+
+ <script type="text/javascript">
+
+ function tryAgain() {
+ changeText('LOG ROLE TEST TEXT 1')
+ onLoad();
+ }
+
+ function changeText(str) {
+ var node = document.getElementById('TEST_ID');
+ while (node.firstChild) node.removeChild(node.firstChild);
+
+ if (typeof str !== 'string') str = 'log role changed test text 2';
+ addText(str)
+ }
+
+ function addText (str) {
+ var node = document.getElementById('TEST_ID');
+ var text_node = document.createTextNode(str);
+ node.appendChild(text_node);
+ }
+
+ function onLoad() {
+ setTimeout(changeText,1500);
+ }
+
+ window.addEventListener('load', onLoad);
+ </script>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/live-events/test-case-live-event-6.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/live-events/test-case-live-event-6.html
new file mode 100644
index 00000000000..8be8f43e633
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/live-events/test-case-live-event-6.html
@@ -0,0 +1,80 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Live Region Event Test Case: Delete text content (STATUS role)</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <style type="text/css">
+ div#TEST_ID {
+ margin: 0.5em;
+ padding: 0.25em;
+ border: medium gray solid;
+ width: 20em;
+ }
+ </style>
+ </head>
+ <body>
+ <h1>ARIA 1.0 Live Region Event Test Case: Delete text content (STATUS role)</h1>
+
+ <div id="TEST_ID" role="status" >
+ STATUS ROLE TEST TEXT
+ </div>
+
+ <button onclick="tryAgain()">Try Again</button>
+
+ <h2>Description</h2>
+ <p>An element with an role attribute with the value "status" has a text content deleted
+ 1.5 seconds after the document is loaded.</p>
+
+ <h2>Expected Results</h2>
+
+ <dl>
+ <dt>ATK/AT-SPI</dt>
+ <dd>ATK/AT-SPIevent: text_changed::delete event</dd>
+
+ <dt>AXAPI</dt>
+ <dd></dd>
+ <dd>AXLiveRegionChanged notification</dd>
+
+ <dt>MSAA + IAccessible2</dt>
+ <dd>IAccessible2: IA2_EVENT_TEXT_REMOVED event </dd>
+
+ <dt>MSAA + UIA Express</dt>
+ <dd>TextPattern..::.TextChangedEvent event </dd>
+
+ </dl>
+
+
+ <script type="text/javascript">
+
+ function tryAgain() {
+ addText()
+
+ onLoad();
+
+ }
+
+ function clearText() {
+ var node = document.getElementById('TEST_ID');
+
+ while (node.firstChild) node.removeChild(node.firstChild);
+ }
+
+ function addText () {
+ var node = document.getElementById('TEST_ID');
+
+ var text_node = document.createTextNode('STATUS ROLE TEST TEXT');
+
+ node.appendChild(text_node);
+ }
+
+ function onLoad() {
+
+ setTimeout(clearText,1500);
+
+ }
+
+ window.addEventListener('load', onLoad);
+ </script>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/mixed-value/585.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/mixed-value/585.html
new file mode 100644
index 00000000000..5b7c024dd57
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/mixed-value/585.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Element with role menuitemradio having inherited state or property aria-checked with value "mixed".</title>
+ </head>
+ <body>
+ <div role="menu">
+ <div id="test" role="menuitemradio" aria-checked="mixed" tabindex="0">Radio menu item with aria-checked='mixed'</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/mixed-value/586.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/mixed-value/586.html
new file mode 100644
index 00000000000..cc5d35362c0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/mixed-value/586.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Element with role radio having inherited state or property aria-checked with value "mixed".</title>
+ </head>
+ <body>
+ <div id="test" role="radio" tabindex="0" aria-checked="mixed">Radio button with aria-checked='mixed'</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-general/596.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-general/596.html
new file mode 100644
index 00000000000..d2f4a9d8a27
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-general/596.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>DIV with aria-labelledby="ID1" and aria-label is not specified and title is not specified.</title>
+ </head>
+ <body>
+ <div id="test" aria-labelledby='ID1'>aria-labelledby='ID1'</div>
+ <span id="ID1">Label for 'test' element</span>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-general/597.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-general/597.html
new file mode 100644
index 00000000000..9a2901cefa2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-general/597.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>DIV with aria-label="Tag" and aria-labelledby is not specified and title is not specified..</title>
+ </head>
+ <body>
+ <div id="test" aria-label='Tag'>aria-label='Tag'</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-general/598.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-general/598.html
new file mode 100644
index 00000000000..7d9404d8232
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-general/598.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>DIV with aria-labelledby="ID1" aria-label="Tag" and title is not specified.</title>
+ </head>
+ <body>
+ <div id="test" aria-labelledby="ID1" aria-label='Tag'>aria-labelledby="ID1" aria-label='Tag'</div>
+ <span id="ID1">Element with id='ID1'</span>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-general/599.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-general/599.html
new file mode 100644
index 00000000000..e08b6664754
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-general/599.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+ <html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>DIV with id="ID0" and aria-labelledby="ID0 ID1" and aria-label="Tag" and title is not specified.</title>
+ </head>
+ <body>
+ <div id="test" aria-labelledby="ID0 ID1" aria-label="Tag">aria-labelledby="ID0 ID1" aria-label='Tag'</div>
+ <span id="ID0">Element with id='ID0'</span>
+ <span id="ID1">Element with id='ID1'</span>
+ </body>
+ </html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-general/600.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-general/600.html
new file mode 100644
index 00000000000..407e35009d7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-general/600.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>DIV with text and aria-label is not specified and aria-labelledby is not specified and title is not specified and role is not specified.</title>
+ </head>
+ <body>
+ <div id="test">Div with text</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-general/601.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-general/601.html
new file mode 100644
index 00000000000..696f900b993
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-general/601.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>DIV with text and role="button" and aria-label is not specified and aria-labelledby is not specified and title is not specified.</title>
+ </head>
+ <body>
+ <div id="test" role="button">Div with role of button, with text.</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-general/602.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-general/602.html
new file mode 100644
index 00000000000..cd896fc11fc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-general/602.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>DIV with text and role="button" and title="Tag" and aria-label is not specified and aria-labelledby is not specified.</title>
+ </head>
+ <body>
+ <div id="test" role="button" title="Tag" style="outline:medium solid black; width:2em; height:1em;"></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-general/603.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-general/603.html
new file mode 100644
index 00000000000..d43057cb7ca
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-general/603.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>&lt; href="test.html" aria-labelledby="ID1"&gt; ABC &lt;/A&gt; and aria-label is not specified and title is not specified.</title> </head> <body>
+ <div id="ID1">Nifty</div> <a href="test.html" aria-labelledby="ID1">ABC</a> </body> </html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-general/604.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-general/604.html
new file mode 100644
index 00000000000..d1303089354
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-general/604.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>aria-label on anchor (without aria-labelledby or title attribute)</title>
+ </head>
+ <body>
+ <a id="test" href="test.html" aria-label="Tag">ABC</a>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-general/605.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-general/605.html
new file mode 100644
index 00000000000..a9a47476bb1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-general/605.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Aria-label on anchor with aria-labelledby (no title attribute)</title>
+ </head>
+ <body>
+ <a href="test.html" id="test" aria-labelledby="ID1" aria-label="Tag">ABC</a>
+ <p id="ID1">Here is some labelledby text</p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-general/606.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-general/606.html
new file mode 100644
index 00000000000..31a65d6b8ac
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-general/606.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>aria-label on anchor with two aria-labelledby ids (no title attribute)</title>
+ </head>
+ <body>
+ <a href="test.html" id="ID0" aria-labelledby="ID0 ID1" aria-label="Tag"></a>
+ <p id="ID1">Also labelledby text ID1</p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-general/607.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-general/607.html
new file mode 100644
index 00000000000..8e71e7d6e8e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-general/607.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Anchor with no aria-label, no aria-labelledby, no title attribute</title>
+ </head>
+ <body>
+ <a href="test.html" id="test">ABC</a>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-general/608.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-general/608.html
new file mode 100644
index 00000000000..e73fc0f25a7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-general/608.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Title attribute, no aria-label, aria-labelledby</title>
+ </head>
+ <body>
+ <a href="test.html" id="test" title="Tag"></a>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-general/837.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-general/837.html
new file mode 100644
index 00000000000..eab418c842e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-general/837.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Tree item with text value "Animals" with two descendant tree items with text value "Cats" and "Dogs".</title>
+ </head>
+ <body>
+ <ul id="tree0" role="tree" aria-activedescendant="tree0_item0" tabindex="0">
+ <li id="tree0_item0" role="treeitem" aria-level="1" aria-expanded="true">
+ Animals
+ <ul role="group">
+ <li id="tree0_item0_1" role="treeitem" aria-level="2" aria-expanded="true">Cats</li>
+ <li id="tree0_item0_2" role="treeitem" aria-level="2" aria-expanded="true">Dogs</li>
+ </ul>
+ </li>
+ </ul>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-img/557.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-img/557.html
new file mode 100644
index 00000000000..127258aca64
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-img/557.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Test 557 IMG with aria-label="l" and alt="a" and title="t" and aria-labelledby not specified.</title>
+</head>
+<body>
+<img src="foo.jpg" aria-label="1" alt="a" title="t"/>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-img/565.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-img/565.html
new file mode 100644
index 00000000000..a7aeab8a135
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-img/565.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Test 565 IMG with id="ID0" and aria-label="l" and aria-labelledby="ID0 ID1 ID2 ID3" and alt="a" and title="t".</title>
+</head>
+<body>
+<input type="text" value="peanuts" id="ID1">
+<input type="text" value="popcorn" id="ID2">
+<input type="text" value="apple jacks" id="ID3">
+<img id="ID0" aria-label="1" aria-labelledby="ID0 ID1 ID2 ID3" alt= "a" title="t" src="foo.jpg"/>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-img/566.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-img/566.html
new file mode 100644
index 00000000000..656ad893bf5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-img/566.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Test 566 IMG with id="ID0" and aria-label="" and aria-labelledby="ID0 ID1 ID2 ID3" and alt="a" and title="t".</title>
+</head>
+<body>
+<input type="text" value="peanuts" id="ID1">
+<input type="text" value="popcorn" id="ID2">
+<input type="text" value="apple jacks" id="ID3">
+<img id="ID0" aria-label="" aria-labelledby="ID0 ID1 ID2 ID3" alt= "" title="t" src="foo.jpg"/>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-img/foo.jpg b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-img/foo.jpg
new file mode 100644
index 00000000000..7d11a4f7cf1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-img/foo.jpg
Binary files differ
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-img/test.png b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-img/test.png
new file mode 100644
index 00000000000..85cfa35fd13
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-img/test.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/538.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/538.html
new file mode 100644
index 00000000000..d8d9225c1fe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/538.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Test 538 UT type="hidden" with no aria-labelledby and with id="test".</title>
+</head>
+<body>
+<input type="hidden" id="test">
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/542.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/542.html
new file mode 100644
index 00000000000..1674b495c3e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/542.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Test 542 An INPUT type=submit, with id="test", with no aria-labelledby and no aria-label and does not have a role=presentation.</title>
+</head>
+<body>
+<input type="submit" id="test"/>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/543.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/543.html
new file mode 100644
index 00000000000..cd140c9164c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/543.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Test 543 An INPUT type="reset", with id="test", with no aria-labelledby and no aria-label and does not have a role=presentation.</title>
+</head>
+<body>
+<input type="reset" id="test"/>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/544.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/544.html
new file mode 100644
index 00000000000..754fe031ca2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/544.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Test 544 An INPUT type=button, with id="test", value="foo", with no aria-labelledby and no aria-label and does not have a role=presentation.</title>
+</head>
+<body>
+<input type="button" id="test" value="foo"/>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/545.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/545.html
new file mode 100644
index 00000000000..7e0bf9504de
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/545.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Test 545 An INPUT type=img, with id="test", with no aria-labelledby, and no aria-label, does not have a role=presentation, and has an alt attribute.</title>
+</head>
+<body>
+<input src="baz.html" type="image" id="test" alt="foo"/>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/546.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/546.html
new file mode 100644
index 00000000000..782682bf84d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/546.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Test 546 An INPUT type=text, password, checkbox, radio, file, or img, with id="test", with no aria-labelledby and no aria-label, does not have a role=presentation, and is referenced by a LABEL element.</title>
+</head>
+<body>
+<label for="test">States:</label>
+<input type="text" id="test"/>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/551.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/551.html
new file mode 100644
index 00000000000..12c54367416
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/551.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Test 551 An INPUT type=text, password, checkbox, radio, file, or image , with id="test", with no aria-labelledby and no aria-label, does not have a role=presentation, is not referenced by a LABEL element, and has a title.</title>
+</head>
+<body>
+<input type="text" id="test" title="crazy" value="baz"/>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/552.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/552.html
new file mode 100644
index 00000000000..005773b9464
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/552.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Test 552 An INPUT type=text, password, checkbox, radio, file, or image, with id="test", with no aria-labelledby and no aria-label, but is referenced by a LABEL element that has an associated CSS :before content rule.</title>
+<style>
+
+label:before
+{
+content:"fancy ";
+}
+</style>
+</head>
+<body>
+<label for="test">fruit</label>
+<input type="text" id="test"/>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/553.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/553.html
new file mode 100644
index 00000000000..27ca6471317
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/553.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Test 553 An INPUT type=text, password, checkbox, radio, file, or image, with id="test", with no aria-labelledby and no aria-label, but is referenced by a LABEL element that has an associated CSS :after content rule. </title>
+<style>
+
+label:after
+{
+content:" fruit";
+}
+</style>
+</head>
+<body>
+<label for="test">fancy</label>
+<input type="text" id="test"/>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/609.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/609.html
new file mode 100644
index 00000000000..b3b07abff77
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/609.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Title attribute, no aria-label, aria-labelledby</title>
+ </head>
+ <body>
+ <input id="test" type="text" aria-labelledby="ID1 ID2 ID3">
+ <p id="ID1">Here is some labelledby text for ID1</p>
+ <p id="ID2">Also labelledby text ID2</p>
+ <p id="ID3">Additional labelledby text ID3</p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/610.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/610.html
new file mode 100644
index 00000000000..bd234fbc498
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/610.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Input element, no wai-aria</title>
+ </head>
+ <body>
+ <input id="test" type="text" aria-label="bar" aria-labelledby="ID1 test">
+ <div id="ID1">foo</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/611.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/611.html
new file mode 100644
index 00000000000..c41595fe476
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/611.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Input element with type="text" referenced by a label, no wai aria</title>
+ </head>
+ <body>
+ <input id="test" type="text"/>
+ <label for="test">foo</label>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/612.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/612.html
new file mode 100644
index 00000000000..5037cbd7855
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/612.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Input with type="password" label/for without wai-aria</title>
+ </head>
+ <body>
+<input type="password" id="test">
+<label for="test">foo</label></body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/613.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/613.html
new file mode 100644
index 00000000000..0f16f922029
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/613.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Input with type="checkbox" label/for without wai-aria</title>
+ </head>
+ <body>
+<input type="checkbox" id="test">
+<label for="test">foo</label></body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/614.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/614.html
new file mode 100644
index 00000000000..29d3d59cd2f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/614.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Input with type="radio" label/for without wai-aria</title>
+ </head>
+ <body>
+<input type="radio" id="test">
+<label for="test">foo</label></body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/615.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/615.html
new file mode 100644
index 00000000000..1790e6aa8e2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/615.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Input with type="file" label/for without wai-aria</title>
+ </head>
+ <body>
+<input type="file" id="test">
+<label for="test">foo</label></body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/659.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/659.html
new file mode 100644
index 00000000000..5e9b439b089
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/659.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Text input with @title and :before and :after content rule</title>
+ <style type="text/css">
+ label:before { content: "foo"; }
+ label:after { content: "baz"; }
+ </style>
+ </head>
+ <body>
+ <form>
+ <label for="test" title="bar"><input id="test" type="text" name="test" title="bar"></label>
+ </form>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/660.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/660.html
new file mode 100644
index 00000000000..e1d5f9416ff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/660.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Text input with @title and :before and :after content rule</title>
+ <style type="text/css">
+ label:before { content: "foo "; }
+ label:after { content: " baz"; }
+ </style>
+ </head>
+ <body>
+ <form>
+ <label for="test" title="bar"><input id="test" type="password" name="test" title="bar"></label>
+ </form>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/661.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/661.html
new file mode 100644
index 00000000000..95a3d46f243
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/661.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Text input with @title and :before and :after content rule</title>
+ <style type="text/css">
+ label:before { content: "foo"; }
+ label:after { content: "baz"; }
+ </style>
+ </head>
+ <body>
+ <form>
+ <label for="test"><input id="test" type="checkbox" name="test" title=" bar "></label>
+ </form>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/662.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/662.html
new file mode 100644
index 00000000000..3bca08804f5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/662.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Text input with @title and :before and :after content rule</title>
+ <style type="text/css">
+ label:before { content: "foo"; }
+ label:after { content: "baz"; }
+ </style>
+ </head>
+ <body>
+ <form>
+ <label for="test"><input id="test" type="radio" name="test" title=" bar "></label>
+ </form>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/663.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/663.html
new file mode 100644
index 00000000000..ae70b8532ab
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/663.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Text input with @title and :before and :after content rule</title>
+ <style type="text/css">
+ label:before { content: "foo "; }
+ label:after { content: " baz"; }
+ </style>
+ </head>
+ <body>
+ <form>
+ <label for="test"><input id="test" type="file" name="test" title="bar"></label>
+ </form>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/721.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/721.html
new file mode 100644
index 00000000000..1173d1ee5fa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/721.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Test 546a An INPUT type=text, password, checkbox, radio, file, or img, with id="test", with no aria-labelledby and no aria-label, does not have a role=presentation, and is referenced by a LABEL element.</title>
+</head>
+<body>
+<label for="test">States:</label>
+<input type="password" id="test"/>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/723.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/723.html
new file mode 100644
index 00000000000..849e516b20e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/723.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Test 546b An INPUT type=text, password, checkbox, radio, file, or img, with id="test", with no aria-labelledby and no aria-label, does not have a role=presentation, and is referenced by a LABEL element.</title>
+</head>
+<body>
+<label for="test">States:</label>
+<input type="checkbox" id="test"/>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/724.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/724.html
new file mode 100644
index 00000000000..f16bb480acb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/724.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Test 546c An INPUT type=text, password, checkbox, radio, file, or img, with id="test", with no aria-labelledby and no aria-label, does not have a role=presentation, and is referenced by a LABEL element.</title>
+</head>
+<body>
+<label for="test">States:</label>
+<input type="radio" id="test"/>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/725.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/725.html
new file mode 100644
index 00000000000..3c72a299626
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/725.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Test 546d An INPUT type=text, password, checkbox, radio, file, or img, with id="test", with no aria-labelledby and no aria-label, does not have a role=presentation, and is referenced by a LABEL element.</title>
+</head>
+<body>
+<label for="test">File:</label>
+<input type="file" id="test"/>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/748.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/748.html
new file mode 100644
index 00000000000..f55510170cb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/748.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>An INPUT type=text, password, checkbox, radio, file, or image , with id="test", with no aria-labelledby and no aria-label, does not have a role=presentation, is not referenced by a LABEL element, and has a title.</title>
+</head>
+<body>
+<input type="password" id="test" title="crazy" value="baz"/>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/749.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/749.html
new file mode 100644
index 00000000000..e87964ceba7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/749.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>An INPUT type=text, password, checkbox, radio, file, or image , with id="test", with no aria-labelledby and no aria-label, does not have a role=presentation, is not referenced by a LABEL element, and has a title.</title>
+</head>
+<body>
+<input type="checkbox" id="test" title="crazy"/>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/750.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/750.html
new file mode 100644
index 00000000000..58a40ae2cea
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/750.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>An INPUT type=text, password, checkbox, radio, file, or image , with id="test", with no aria-labelledby and no aria-label, does not have a role=presentation, is not referenced by a LABEL element, and has a title.</title>
+</head>
+<body>
+<input type="radio" id="test" title="crazy"/>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/751.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/751.html
new file mode 100644
index 00000000000..b8a5e7c908a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/751.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>An INPUT type=text, password, checkbox, radio, file, or image , with id="test", with no aria-labelledby and no aria-label, does not have a role=presentation, is not referenced by a LABEL element, and has a title.</title>
+</head>
+<body>
+<input type="file" id="test" title="crazy"/>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/753.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/753.html
new file mode 100644
index 00000000000..4cb25a46adb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/753.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>An INPUT type=text, password, checkbox, radio, file, or image, with id="test", with no aria-labelledby and no aria-label, but is referenced by a LABEL element that has an associated CSS :before content rule.</title>
+<style>
+
+label:before
+{
+content:"fancy ";
+}
+</style>
+</head>
+<body>
+<label for="test">fruit</label>
+<input type="password" id="test"/>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/754.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/754.html
new file mode 100644
index 00000000000..db8916d125a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/754.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>An INPUT type=text, password, checkbox, radio, file, or image, with id="test", with no aria-labelledby and no aria-label, but is referenced by a LABEL element that has an associated CSS :before content rule.</title>
+<style>
+
+label:before
+{
+content:"fancy ";
+}
+</style>
+</head>
+<body>
+<label for="test">fruit</label>
+<input type="checkbox" id="test"/>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/755.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/755.html
new file mode 100644
index 00000000000..eb2dda3ff8f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/755.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>An INPUT type=text, password, checkbox, radio, file, or image, with id="test", with no aria-labelledby and no aria-label, but is referenced by a LABEL element that has an associated CSS :before content rule.</title>
+<style>
+
+label:before
+{
+content:"fancy ";
+}
+</style>
+</head>
+<body>
+<label for="test">fruit</label>
+<input type="radio" id="test"/>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/756.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/756.html
new file mode 100644
index 00000000000..944f3cde745
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/756.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>An INPUT type=text, password, checkbox, radio, file, or image, with id="test", with no aria-labelledby and no aria-label, but is referenced by a LABEL element that has an associated CSS :before content rule.</title>
+<style>
+
+label:before
+{
+content:"fancy ";
+}
+</style>
+</head>
+<body>
+<label for="test">fruit</label>
+<input type="file" id="test"/>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/758.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/758.html
new file mode 100644
index 00000000000..0657f8c6a7f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/758.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>An INPUT type=text, password, checkbox, radio, file, or image, with id="test", with no aria-labelledby and no aria-label, but is referenced by a LABEL element that has an associated CSS :after content rule. </title>
+<style>
+
+label:after
+{
+content:" fruit"
+}
+</style>
+</head>
+<body>
+<label for="test">fancy</label>
+<input type="password" id="test"/>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/759.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/759.html
new file mode 100644
index 00000000000..a8505f492b4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/759.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>An INPUT type=text, password, checkbox, radio, file, or image, with id="test", with no aria-labelledby and no aria-label, but is referenced by a LABEL element that has an associated CSS :after content rule. </title>
+<style>
+
+label:after
+{
+content:" fruit"
+}
+</style>
+</head>
+<body>
+<label for="test">fancy</label>
+<input type="checkbox" id="test"/>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/760.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/760.html
new file mode 100644
index 00000000000..d8809bd9439
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/760.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>An INPUT type=text, password, checkbox, radio, file, or image, with id="test", with no aria-labelledby and no aria-label, but is referenced by a LABEL element that has an associated CSS :after content rule. </title>
+<style>
+
+label:after
+{
+content:" fruit"
+}
+</style>
+</head>
+<body>
+<label for="test">fancy</label>
+<input type="radio" id="test"/>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/761.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/761.html
new file mode 100644
index 00000000000..6c8a1de52fd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/761.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>An INPUT type=text, password, checkbox, radio, file, or image, with id="test", with no aria-labelledby and no aria-label, but is referenced by a LABEL element that has an associated CSS :after content rule. </title>
+<style>
+
+label:after
+{
+content:"fancy";
+}
+</style>
+</head>
+<body>
+<label for="test">fruit</label>
+<input type="file" id="test"/>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/foo.jpg b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/foo.jpg
new file mode 100644
index 00000000000..7d11a4f7cf1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/name-computation-input/foo.jpg
Binary files differ
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/859.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/859.html
new file mode 100644
index 00000000000..ad383353b07
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/859.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>test 859</title>
+ </head>
+ <body>
+ <div id="test" aria-label="test" role="alertdialog"></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/860.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/860.html
new file mode 100644
index 00000000000..3079ef86c77
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/860.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>test 860</title>
+ </head>
+ <body>
+ <div id="test" aria-label="test" role="application"></div>
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/861.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/861.html
new file mode 100644
index 00000000000..86284e08d99
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/861.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>test 861</title>
+ </head>
+ <body>
+ <div id="test" aria-label="test" role="button"></div>
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/863.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/863.html
new file mode 100644
index 00000000000..8ae98c7f1e8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/863.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>test 863</title>
+ </head>
+ <body>
+ <div role="grid" aria-label="mygrid">
+ <div role="row">
+ <div id="test" aria-label="foo" role="columnheader"></div>
+ </div>
+ </div>
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/864.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/864.html
new file mode 100644
index 00000000000..0b706e5c874
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/864.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>test case 864
+ </title>
+ </head>
+ <body>
+ <input type="text" id="test" aria-label="foo" role="combobox"
+ aria-owns="owned_listbox" aria-activedescendant="selected_option" aria-expanded="true">
+ <ul role="listbox" id="owned_listbox">
+ <li role="option">Zebra</li>
+ <li role="option" id="selected_option">Zoom</li>
+ </ul>
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/865.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/865.html
new file mode 100644
index 00000000000..d706f80a25a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/865.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>test 865</title>
+ </head>
+ <body>
+ <div id="test" aria-label="foo" role="dialog"></div>
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/866.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/866.html
new file mode 100644
index 00000000000..8d4d5e42f1a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/866.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>test 866</title>
+ </head>
+ <body>
+ <div id="test" aria-label="foo" role="document"></div>
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/867.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/867.html
new file mode 100644
index 00000000000..a60653fd7ca
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/867.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>test 867</title>
+ </head>
+ <body>
+ <div id="test" role="grid" aria-label="foo">
+ <div role="row">
+ <div role="columnheader" id="obj1">obj1</div>
+ </div>
+ <div role="row">
+ <div role="gridcell" id="obj2">obj2</div>
+ </div>
+ </div>
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/868.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/868.html
new file mode 100644
index 00000000000..d43c86f2962
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/868.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>test 868</title>
+ </head>
+ <body>
+ <div role="grid">
+ <div role="row">
+ <div role="columnheader" id="obj1">obj1</div>
+ </div>
+ <div role="row">
+ <div id="test" aria-label="foo" role="gridcell">obj2</div>
+ </div>
+ </div>
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/869.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/869.html
new file mode 100644
index 00000000000..cba68be90ac
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/869.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>test 869</title>
+ </head>
+ <body>
+ <div id="test" aria-label="foo" role="heading" aria-level="1"></div>
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/871.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/871.html
new file mode 100644
index 00000000000..4595a7cf998
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/871.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 871</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <div id="test" role="listbox" aria-label="foo">
+ <div role="option" aria-setsize="3" aria-posinset="1" tabindex="-1">Option 1</div>
+ <div role="option" aria-setsize="3" aria-posinset="2" tabindex="-1">Option 2</div>
+ <div role="option" aria-setsize="3" aria-posinset="3" tabindex="-1">Option 3</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/872.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/872.html
new file mode 100644
index 00000000000..0469d7c1691
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/872.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>test case 872</title>
+ </head>
+ <body>
+ <div role="list"><div id="test" role="listitem" aria-label="foo"></div></div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/873.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/873.html
new file mode 100644
index 00000000000..7ae36c5e70a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/873.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>test case 873
+ </title>
+ </head>
+ <body>
+ <div id="test" role="log" aria-label="foo">Placeholder content</div>
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/874.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/874.html
new file mode 100644
index 00000000000..5d44672d31b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/874.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>test case 874
+ </title>
+ </head>
+ <body>
+ <div id="test" role=" marquee" aria-label="foo"></div>
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/875.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/875.html
new file mode 100644
index 00000000000..52422efade6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/875.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>test case 875
+ </title>
+ </head>
+ <body>
+ <div id="test" role="menu" tabindex="0" aria-label="foo" aria-activedescendant="obj1">
+ <div id="obj1" role="menuitem">obj1</div>
+ <div id="obj2" role="menuitem">obj2</div>
+ </div>
+ </body>
+</html>
+
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/879.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/879.html
new file mode 100644
index 00000000000..a9a876a03ed
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/879.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 879</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <div role="listbox">
+ <div role="option" aria-setsize="3" aria-label="foo" id="test" aria-posinset="1" tabindex="-1"></div>
+ <div role="option" aria-setsize="3" aria-posinset="2" tabindex="-1">Option 2</div>
+ <div role="option" aria-setsize="3" aria-posinset="3" tabindex="-1">Option 3</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/880.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/880.html
new file mode 100644
index 00000000000..570d85361d7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/880.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>test case 880
+ </title>
+ </head>
+ <body>
+ <div id="test" role="progressbar" aria-label="foo" aria-valuemax="1.1">Placeholder content</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/887.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/887.html
new file mode 100644
index 00000000000..90151869f71
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/887.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>test case 887</title>
+ </head>
+ <body>
+ <div role="tablist">
+ <div role="tab">tab1</div><div role="tab">tab2</div>
+ </div>
+ <div id="test" aria-label="foo" role="tabpanel">
+ Boring tab panel
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/888.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/888.html
new file mode 100644
index 00000000000..da876814e03
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/888.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>test case 888</title>
+ </head>
+ <body>
+ <div id="test" aria-label="foo" role="textbox"></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/889.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/889.html
new file mode 100644
index 00000000000..2cf67a32014
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/889.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>test case 889</title>
+ </head>
+ <body>
+ <div id="test" aria-label="foo" role="timer"></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/890.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/890.html
new file mode 100644
index 00000000000..6fd47f40e2e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/890.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>test case 890</title>
+ </head>
+ <body>
+ <input type="text" aria-describedby="test"/>
+ <div id="test" aria-label="foo" role="tooltip"></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/891.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/891.html
new file mode 100644
index 00000000000..2d2361e43d7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/891.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>test case 891
+ </title>
+ </head>
+ <body>
+ <div id="test" role="tree" aria-label="foo">
+ <div role="treeitem" id="obj1">obj1</div>
+ <div role="treeitem" id="obj2">obj2</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/892.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/892.html
new file mode 100644
index 00000000000..20934bbbfae
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/892.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>test case 892
+ </title>
+ </head>
+ <body>
+ <div role="tree">
+ <div role="treeitem" aria-label="foo" id="test">obj1</div>
+ <div role="treeitem" id="obj2">obj2</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/893.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/893.html
new file mode 100644
index 00000000000..819fa8d8d89
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/namefromauthor-requ/893.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>test case 893
+ </title>
+ </head>
+ <body>
+ <div id="test" role="treegrid" aria-label="foo" aria-activedescendant="obj1" tabindex="0">
+ <div role="row">
+ <div id="obj1" role="gridcell">obj1</div>
+ <div id="obj2" role="gridcell">obj2</div>
+ </div>
+ <div role="row">
+ <div id="obj3" role="gridcell">obj3</div>
+ <div id="obj4" role="gridcell">obj4</div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/noaria.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/noaria.html
new file mode 100644
index 00000000000..e404e6619af
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/noaria.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>No ARIA markup</title>
+ </head>
+ <body>
+ <div id="test">Placeholder content</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/497.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/497.html
new file mode 100644
index 00000000000..5efa4ab7798
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/497.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Test 497 Image element with role="presentation" but with a reference to a description </title>
+</head>
+<body>
+<img src="foo.jpg" alt="test1" width="40" height="40" role="presentation" aria-describedby="foo"/>
+<p id="foo">
+This is an image.
+</p>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/498.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/498.html
new file mode 100644
index 00000000000..834ba206d70
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/498.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Test 498 Image element with role="presentation" but aria-disabled="true" </title>
+</head>
+<body>
+<img src="foo.jpg" alt="test1" width="40" height="40" role="presentation" aria-disabled="true"/>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/499.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/499.html
new file mode 100644
index 00000000000..ad2dee407ed
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/499.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Test 499 Image element with role="presentation" but aria-dropeffect="move" </title>
+</head>
+<body>
+<img src="foo.jpg" alt="test1" width="40" height="40" role="presentation" aria-dropeffect="move"/>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/500.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/500.html
new file mode 100644
index 00000000000..578e7a2db72
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/500.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Test 500 Image element with role="presentation" but with a valid aria-flowto attribute</title>
+</head>
+<body>
+<img src="foo.jpg" alt="test1" width="40" height="40" role="presentation" aria-flowto="test2"/>
+<div role="img" id="test2">
+</div>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/501.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/501.html
new file mode 100644
index 00000000000..77cfc2ede08
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/501.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Test 501 Image element with role="presentation" but with aria-grabbed="true"</title>
+</head>
+<body>
+<img src="foo.jpg" alt="test1" width="40" height="40" role="presentation" aria-grabbed="true"/>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/502.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/502.html
new file mode 100644
index 00000000000..ae8c74d5c78
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/502.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Test 502 Image element with role="presentation" but with aria-haspopup="true"</title>
+</head>
+<body>
+<img src="foo.jpg" alt="test1" width="40" height="40" role="presentation" aria-haspopup="true"/>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/503.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/503.html
new file mode 100644
index 00000000000..3859142529a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/503.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Test 503 Image element with role="presentation" but with aria-hidden="true"</title>
+</head>
+<body>
+<img src="foo.jpg" alt="test1" width="40" height="40" role="presentation" aria-hidden="true"/>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/504.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/504.html
new file mode 100644
index 00000000000..ea19a435957
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/504.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Test 504 Image element with role="presentation" but with aria-invalid="true"</title>
+</head>
+<body>
+<img src="foo.jpg" alt="test1" width="40" height="40" role="presentation" aria-invalid="true"/>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/505.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/505.html
new file mode 100644
index 00000000000..16315641301
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/505.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Test 505 Image element with role="presentation" but with aria-label="test"</title>
+</head>
+<body>
+<img src="foo.jpg" alt="test1" width="40" height="40" role="presentation" aria-label="test"/>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/506.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/506.html
new file mode 100644
index 00000000000..495763d7799
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/506.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Test 506 Image element with role="presentation" but with a valid aria-labelledby attribute</title>
+</head>
+<body>
+<img src="foo.jpg" alt="test1" width="40" height="40" role="presentation" aria-labelledby="test2"/>
+<div id="test2">
+test_label
+</div>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/507.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/507.html
new file mode 100644
index 00000000000..09e6859655e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/507.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Test 507 Image element with role="presentation" but with aria-live="assertive"</title>
+</head>
+<body>
+<img src="foo.jpg" alt="test1" width="40" height="40" role="presentation" aria-live="assertive"/>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/509.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/509.html
new file mode 100644
index 00000000000..9780ce2ac4e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/509.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Test 509 Image element with role="presentation" but with aria-relevant="text"</title>
+</head>
+<body>
+<img src="foo.jpg" alt="test1" width="40" height="40" role="presentation" aria-live="polite" aria-relevant="text"/>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/510.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/510.html
new file mode 100644
index 00000000000..05c50a161eb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/510.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Test 510 An owned, unfocusable, element untied to an aria relationship that inherits role="presentation"</title>
+</head>
+<body>
+<table role="presentation">
+<tr>
+<td>Test me</td>
+</tr>
+</table>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/511.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/511.html
new file mode 100644
index 00000000000..d9a3043fe31
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/511.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Test 511 An owned, focusable element, tied to an aria relationship that inherits role="presentation"</title>
+</head>
+<body>
+<table role="presentation">
+<tr>
+<td tabindex="0" id="foo">Test me</td>
+</tr>
+</table>
+<div aria-controls="foo">
+</div>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/512.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/512.html
new file mode 100644
index 00000000000..35c0a5ef07a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/512.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Test 512 An owned, unfocusable element, having aria-atomic="true" that inherits role="presentation"</title>
+</head>
+<body>
+<table role="presentation">
+<tr>
+<td aria-atomic="true">Test me</td>
+</tr>
+</table>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/513.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/513.html
new file mode 100644
index 00000000000..4a908544f5e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/513.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Test 513 An owned, unfocusable element, having aria-busy="true" that inherits role="presentation"</title>
+</head>
+<body>
+<table role="presentation">
+<tr>
+<td aria-busy="true">Test me</td>
+</tr>
+</table>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/514.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/514.html
new file mode 100644
index 00000000000..0f7c3480022
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/514.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Test 514 An owned, unfocusable element, with a valid aria-controls attribue set that inherits role="presentation"</title>
+</head>
+<body>
+<table role="presentation">
+<tr>
+<td aria-controls="foo">Test me</td>
+</tr>
+</table>
+<div id="foo">
+</div>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/515.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/515.html
new file mode 100644
index 00000000000..de4d7caa2c8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/515.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Test 515 An owned, unfocusable element, with a valid aria-describedby attribue set that inherits role="presentation"</title>
+</head>
+<body>
+<table role="presentation">
+<tr>
+<td aria-describedby="foo">Test me</td>
+</tr>
+</table>
+<div id="foo">
+You can
+</div>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/516.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/516.html
new file mode 100644
index 00000000000..dacee180ca4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/516.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Test 516 An owned, unfocusable element, having aria-disabled="true" that inherits role="presentation"</title>
+</head>
+<body>
+<table role="presentation">
+<tr>
+<td aria-disabled="true">Test me</td>
+</tr>
+</table>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/517.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/517.html
new file mode 100644
index 00000000000..3154b9da2fa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/517.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Test 517 An owned, unfocusable element, having aria-dropeffect="move" that inherits role="presentation"</title>
+</head>
+<body>
+<table role="presentation">
+<tr>
+<td aria-dropeffect="move">Test me</td>
+</tr>
+</table>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/518.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/518.html
new file mode 100644
index 00000000000..a2c85521c12
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/518.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Test 518 An owned, unfocusable element, with a valid aria-flowto attribue set that inherits role="presentation"</title>
+</head>
+<body>
+<table role="presentation">
+<tr>
+<td aria-flowto="foo">Test me</td>
+</tr>
+</table>
+<div id="foo">
+You can
+</div>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/519.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/519.html
new file mode 100644
index 00000000000..8ff435f4d64
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/519.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Test 519 An owned, unfocusable element, having aria-grabbed="true" that inherits role="presentation"</title>
+</head>
+<body>
+<table role="presentation">
+<tr>
+<td aria-grabbed="true">Test me</td>
+</tr>
+</table>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/520.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/520.html
new file mode 100644
index 00000000000..9b7bee0f643
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/520.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Test 520 An owned, unfocusable element, having aria-haspopup="true" that inherits role="presentation"</title>
+</head>
+<body>
+<table role="presentation">
+<tr>
+<td aria-haspopup="true">Test me</td>
+</tr>
+</table>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/521.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/521.html
new file mode 100644
index 00000000000..c98a873d6aa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/521.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Test 521 An owned, unfocusable element, having aria-hidden="true" that inherits role="presentation"</title>
+</head>
+<body>
+<table role="presentation">
+<tr>
+<td aria-hidden="true">Test me</td>
+</tr>
+</table>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/522.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/522.html
new file mode 100644
index 00000000000..1d18a47b8a5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/522.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Test 522 An owned, unfocusable element, having aria-invalid="true" that inherits role="presentation"</title>
+</head>
+<body>
+<table role="presentation">
+<tr>
+<td aria-invalid="true">Test me</td>
+</tr>
+</table>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/523.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/523.html
new file mode 100644
index 00000000000..7a2ba4138ea
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/523.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Test 523 An owned, unfocusable element, having aria-label="test" that inherits role="presentation"</title>
+</head>
+<body>
+<table role="presentation">
+<tr>
+<td aria-label="test">foo</td>
+</tr>
+</table>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/524.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/524.html
new file mode 100644
index 00000000000..b624f041a2b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/524.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Test 524 An owned, unfocusable element, with a valid aria-labelledby attribute set that inherits role="presentation"</title>
+</head>
+<body>
+<table role="presentation">
+<tr>
+<td aria-labelledby="foo"></td>
+</tr>
+</table>
+<div id="foo">test</div>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/525.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/525.html
new file mode 100644
index 00000000000..cf97c15f61a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/525.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Test 525 An owned, unfocusable element, having aria-live="assertive" that inherits role="presentation"</title>
+</head>
+<body>
+<table role="presentation">
+<tr>
+<td aria-live="assertive">test</td>
+</tr>
+</table>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/527.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/527.html
new file mode 100644
index 00000000000..a7a6e751cf1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentation-role/527.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Test 527 An owned, unfocusable element, having aria-relevant="text" that inherits role="presentation"</title>
+</head>
+<body>
+<table role="presentation">
+<tr>
+<td aria-relevant="text">test</td>
+</tr>
+</table>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentational-children/testcase-839.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentational-children/testcase-839.html
new file mode 100644
index 00000000000..0f649a5b75c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentational-children/testcase-839.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 839: Separator</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 839: Separator</h1>
+
+ <div role="separator">
+ <div>Test text content</div>
+ <label>Textbox <input type="text" value="123456789"/></label>
+ <p><a href="#link">Test link</a></p>
+ <div role="button" onclick="alert('Button Pressed')">Button</div>
+ </div>
+
+
+ </body>
+
+</html>
+
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentational-children/testcase-840.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentational-children/testcase-840.html
new file mode 100644
index 00000000000..75acea26f97
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentational-children/testcase-840.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 840: progressbar</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 840: progressbar</h1>
+
+ <div role="progressbar">
+ <div>Test text content</div>
+ <label>Textbox <input type="text" value="123456789"/></label>
+ <p><a href="#link">Test link</a></p>
+ <div role="button" onclick="alert('Button Pressed')">Button</div>
+ </div>
+
+
+ </body>
+
+</html>
+
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentational-children/testcase-842.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentational-children/testcase-842.html
new file mode 100644
index 00000000000..5fcf8b27b22
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentational-children/testcase-842.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 842: img</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 842: img</h1>
+
+ <div role="img" aria-label="Test image">
+ <div>Test text content</div>
+ <label>Textbox <input type="text" value="123456789"/></label>
+ <p><a href="#link">Test link</a></p>
+ <div role="button" onclick="alert('Button Pressed')">Button</div>
+ </div>
+
+
+ </body>
+
+</html>
+
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentational-children/testcase-843.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentational-children/testcase-843.html
new file mode 100644
index 00000000000..02902a5f0cc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentational-children/testcase-843.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 843: slider</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 843: slider</h1>
+
+ <div role="slider" aria-valuemin="0" aria-valuenow="5" aria-valuemax="10">
+ <div>Test text content</div>
+ <label>Textbox <input type="text" value="123456789"/></label>
+ <p><a href="#link">Test link</a></p>
+ <div role="button" onclick="alert('Button Pressed')">Button</div>
+ </div>
+
+
+ </body>
+
+</html>
+
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentational-children/testcase-844.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentational-children/testcase-844.html
new file mode 100644
index 00000000000..41310676076
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/presentational-children/testcase-844.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 844: math</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 844: math</h1>
+
+ <div role="math" aria-label="a plus b equals c">
+ <div>Test text content</div>
+ <label>Textbox <input type="text" value="123456789"/></label>
+ <p><a href="#link">Test link</a></p>
+ <div role="button" onclick="alert('Button Pressed')">Button</div>
+ </div>
+
+
+ </body>
+
+</html>
+
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-atomic-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-atomic-false.html
new file mode 100644
index 00000000000..31452f627e9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-atomic-false.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with no role; global state or property "aria-atomic" value of "false"</title>
+ </head>
+ <body>
+ <div id="test" aria-live="polite" aria-atomic="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-atomic-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-atomic-true.html
new file mode 100644
index 00000000000..499b675db80
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-atomic-true.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with no role; global state or property "aria-atomic" value of "true"</title>
+ </head>
+ <body>
+ <div id="test" aria-live="polite" aria-atomic="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-atomic.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-atomic.html
new file mode 100644
index 00000000000..84faaeb86e4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-atomic.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with no role; global state or property "" value of "true"</title>
+ </head>
+ <body>
+ <div aria-atomic="true">
+ Placeholder content
+
+ </div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-busy-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-busy-false.html
new file mode 100644
index 00000000000..f10c1240406
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-busy-false.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with no role; global state or property "aria-busy" value of "false"</title>
+ </head>
+ <body>
+ <div id="test" aria-busy="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-busy-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-busy-true.html
new file mode 100644
index 00000000000..efd700760a3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-busy-true.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with no role; global state or property "aria-busy" value of "true"</title>
+ </head>
+ <body>
+ <div id="test" aria-busy="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-controls-obj1-obj2.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-controls-obj1-obj2.html
new file mode 100644
index 00000000000..63eb41b1cee
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-controls-obj1-obj2.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with no role; global state or property "aria-controls" value of "obj1 obj2"</title>
+ </head>
+ <body>
+ <div id="test" aria-controls="obj1 obj2">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-controls-obj1.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-controls-obj1.html
new file mode 100644
index 00000000000..8e012dd5644
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-controls-obj1.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with no role; global state or property "aria-controls" value of "obj1"</title>
+ </head>
+ <body>
+ <div id="test" aria-controls="obj1">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-describedby-obj1-obj2.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-describedby-obj1-obj2.html
new file mode 100644
index 00000000000..e36e08eab1d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-describedby-obj1-obj2.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with no role; global state or property "aria-describedby" value of "obj1 obj2"</title>
+ </head>
+ <body>
+ <div id="test" aria-describedby="obj1 obj2">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-describedby-obj1.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-describedby-obj1.html
new file mode 100644
index 00000000000..317165628c3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-describedby-obj1.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with no role; global state or property "aria-describedby" value of "obj1"</title>
+ </head>
+ <body>
+ <div id="test" aria-describedby="obj1">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-disabled-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-disabled-false.html
new file mode 100644
index 00000000000..dc3c8ce0ea3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-disabled-false.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with no role; global state or property "aria-disabled" value of "false"</title>
+ </head>
+ <body>
+ <div id="test" aria-disabled="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-disabled-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-disabled-true.html
new file mode 100644
index 00000000000..fd01ff2d4a8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-disabled-true.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with no role; global state or property "aria-disabled" value of "true"</title>
+ </head>
+ <body>
+ <div id="test" aria-disabled="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-dropeffect-copy.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-dropeffect-copy.html
new file mode 100644
index 00000000000..4f0782bf428
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-dropeffect-copy.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with no role; global state or property "aria-dropeffect" value of "copy"</title>
+ </head>
+ <body>
+ <div id="test" aria-dropeffect="copy">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-dropeffect-execute.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-dropeffect-execute.html
new file mode 100644
index 00000000000..e445c8b3f71
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-dropeffect-execute.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with no role; global state or property "aria-dropeffect" value of "execute"</title>
+ </head>
+ <body>
+ <div id="test" aria-dropeffect="execute">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-dropeffect-link.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-dropeffect-link.html
new file mode 100644
index 00000000000..cbbc24c0e83
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-dropeffect-link.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with no role; global state or property "aria-dropeffect" value of "link"</title>
+ </head>
+ <body>
+ <div id="test" aria-dropeffect="link">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-dropeffect-move.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-dropeffect-move.html
new file mode 100644
index 00000000000..55bfe810f50
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-dropeffect-move.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with no role; global state or property "aria-dropeffect" value of "move"</title>
+ </head>
+ <body>
+ <div id="test" aria-dropeffect="move">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-dropeffect-none.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-dropeffect-none.html
new file mode 100644
index 00000000000..05ccc7aa55e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-dropeffect-none.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with no role; global state or property "aria-dropeffect" value of "none"</title>
+ </head>
+ <body>
+ <div id="test" aria-dropeffect="none">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-dropeffect-popup.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-dropeffect-popup.html
new file mode 100644
index 00000000000..dd5045e45de
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-dropeffect-popup.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with no role; global state or property "aria-dropeffect" value of "popup"</title>
+ </head>
+ <body>
+ <div id="test" aria-dropeffect="popup">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-flowto-obj1-obj2.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-flowto-obj1-obj2.html
new file mode 100644
index 00000000000..0efca8bdca6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-flowto-obj1-obj2.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with no role; global state or property "aria-flowto" value of "obj1 obj2"</title>
+ </head>
+ <body>
+ <div id="test" aria-flowto="obj1 obj2">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-flowto-obj1.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-flowto-obj1.html
new file mode 100644
index 00000000000..d60135c3f59
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-flowto-obj1.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with no role; global state or property "aria-flowto" value of "obj1"</title>
+ </head>
+ <body>
+ <div id="test" aria-flowto="obj1">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-grabbed-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-grabbed-false.html
new file mode 100644
index 00000000000..c3e422266d6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-grabbed-false.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with no role; global state or property "aria-grabbed" value of "false"</title>
+ </head>
+ <body>
+ <div id="test" aria-grabbed="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-grabbed-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-grabbed-true.html
new file mode 100644
index 00000000000..ab42aa10010
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-grabbed-true.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with no role; global state or property "aria-grabbed" value of "true"</title>
+ </head>
+ <body>
+ <div id="test" aria-grabbed="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-grabbed-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-grabbed-undefined.html
new file mode 100644
index 00000000000..91626fe957e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-grabbed-undefined.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with no role; global state or property "aria-grabbed" value of "undefined"</title>
+ </head>
+ <body>
+ <div id="test" aria-grabbed="undefined">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-haspopup-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-haspopup-false.html
new file mode 100644
index 00000000000..125b43ba3b8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-haspopup-false.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with no role; global state or property "aria-haspopup" value of "false"</title>
+ </head>
+ <body>
+ <div id="test" aria-haspopup="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-haspopup-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-haspopup-true.html
new file mode 100644
index 00000000000..735c64e7a3a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-haspopup-true.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with no role; global state or property "aria-haspopup" value of "true"</title>
+ </head>
+ <body>
+ <div id="test" aria-haspopup="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-hidden-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-hidden-false.html
new file mode 100644
index 00000000000..185bb601149
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-hidden-false.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with no role; global state or property "aria-hidden" value of "false"</title>
+ </head>
+ <body>
+ <div id="test" aria-hidden="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-hidden-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-hidden-true.html
new file mode 100644
index 00000000000..fb3b6179f77
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-hidden-true.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with no role; global state or property "aria-hidden" value of "true"</title>
+ </head>
+ <body>
+ <div id="test" aria-hidden="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-invalid-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-invalid-false.html
new file mode 100644
index 00000000000..6293d2324e6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-invalid-false.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with no role; global state or property "aria-invalid" value of "false"</title>
+ </head>
+ <body>
+ <div id="test" aria-invalid="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-invalid-grammar.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-invalid-grammar.html
new file mode 100644
index 00000000000..f71287c17d4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-invalid-grammar.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with no role; global state or property "aria-invalid" value of "grammar"</title>
+ </head>
+ <body>
+ <div id="test" aria-invalid="grammar">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-invalid-spelling.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-invalid-spelling.html
new file mode 100644
index 00000000000..b09c6d147e8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-invalid-spelling.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with no role; global state or property "aria-invalid" value of "spelling"</title>
+ </head>
+ <body>
+ <div id="test" aria-invalid="spelling">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-invalid-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-invalid-true.html
new file mode 100644
index 00000000000..ad255df243c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-invalid-true.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with no role; global state or property "aria-invalid" value of "true"</title>
+ </head>
+ <body>
+ <div id="test" aria-invalid="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-label-Test-string-value.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-label-Test-string-value.html
new file mode 100644
index 00000000000..3b6b442d488
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-label-Test-string-value.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with no role; global state or property "aria-label" value of "Test string value"</title>
+ </head>
+ <body>
+ <div id="test" aria-label="Test string value">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-labelledby-obj1-obj2.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-labelledby-obj1-obj2.html
new file mode 100644
index 00000000000..1c45b0c2b71
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-labelledby-obj1-obj2.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with no role; global state or property "aria-labelledby" value of "obj1 obj2"</title>
+ </head>
+ <body>
+ <div id="test" aria-labelledby="obj1 obj2">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-labelledby-obj1.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-labelledby-obj1.html
new file mode 100644
index 00000000000..2a863ca9535
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-labelledby-obj1.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with no role; global state or property "aria-labelledby" value of "obj1"</title>
+ </head>
+ <body>
+ <div id="test" aria-labelledby="obj1">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-live-assertive.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-live-assertive.html
new file mode 100644
index 00000000000..b977bd4c4d3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-live-assertive.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with no role; global state or property "aria-live" value of "assertive"</title>
+ </head>
+ <body>
+ <div id="test" aria-live="assertive">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-live-off.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-live-off.html
new file mode 100644
index 00000000000..b8cbf15ad29
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-live-off.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with no role; global state or property "aria-live" value of "off"</title>
+ </head>
+ <body>
+ <div id="test" aria-live="off">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-live-polite.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-live-polite.html
new file mode 100644
index 00000000000..d250f7b5304
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-live-polite.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with no role; global state or property "aria-live" value of "polite"</title>
+ </head>
+ <body>
+ <div id="test" aria-live="polite">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-owns-obj1-obj2.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-owns-obj1-obj2.html
new file mode 100644
index 00000000000..784e02b3534
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-owns-obj1-obj2.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with no role; global state or property "aria-owns" value of "obj1 obj2"</title>
+ </head>
+ <body>
+ <div id="test" aria-owns="obj1 obj2">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-owns-obj1.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-owns-obj1.html
new file mode 100644
index 00000000000..d44ce0b38f4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-owns-obj1.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with no role; global state or property "aria-owns" value of "obj1"</title>
+ </head>
+ <body>
+ <div id="test" aria-owns="obj1">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-relevant-additions-text.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-relevant-additions-text.html
new file mode 100644
index 00000000000..12b17be1e98
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-relevant-additions-text.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with no role; global state or property "aria-relevant" value of "additions text"</title>
+ </head>
+ <body>
+ <div id="test" aria-live="polite" aria-relevant="additions text">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-relevant-additions.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-relevant-additions.html
new file mode 100644
index 00000000000..c8329d95eda
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-relevant-additions.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with no role; global state or property "aria-relevant" value of "additions"</title>
+ </head>
+ <body>
+ <div id="test" aria-live="polite" aria-relevant="additions">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-relevant-all.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-relevant-all.html
new file mode 100644
index 00000000000..574aa18281b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-relevant-all.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with no role; global state or property "aria-relevant" value of "all"</title>
+ </head>
+ <body>
+ <div id="test" aria-live="polite" aria-relevant="all">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-relevant-removals.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-relevant-removals.html
new file mode 100644
index 00000000000..3dc0b12fe95
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-relevant-removals.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with no role; global state or property "aria-relevant" value of "removals"</title>
+ </head>
+ <body>
+ <div id="test" aria-live="polite" aria-relevant="removals">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-relevant-text.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-relevant-text.html
new file mode 100644
index 00000000000..a8957f1f7cf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/properties-global-norole/properties-global-norole-aria-relevant-text.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with no role; global state or property "aria-relevant" value of "text"</title>
+ </head>
+ <body>
+ <div id="test" aria-live="polite" aria-relevant="text">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/relevant-state/591.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/relevant-state/591.html
new file mode 100644
index 00000000000..f7044aa07f5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/relevant-state/591.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Element with role main having global state or property aria-relevant with value "additions removals".</title>
+ </head>
+ <body>
+ <div id="test" role="main" aria-relevant='additions removals'>Role main with aria-relevant='additions removals'</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/relevant-state/592.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/relevant-state/592.html
new file mode 100644
index 00000000000..10bafce6090
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/relevant-state/592.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Element with role main having global state or property aria-relevant with value "removals text".</title>
+ </head>
+ <body>
+ <div id="test" role="main" aria-relevant='removals text'>Role main with aria-relevant='removals text'</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/relevant-state/593.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/relevant-state/593.html
new file mode 100644
index 00000000000..e3bb27321a1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/relevant-state/593.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Element with role main having global state or property aria-relevant with value "additions removals text".</title>
+ </head>
+ <body>
+ <div id="test" role="main" aria-relevant='additions removals text'>Role main with aria-relevant='additions removals text'</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-alert.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-alert.html
new file mode 100644
index 00000000000..733dbfd81d5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-alert.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Plain &lt;div&gt; with role "alert" and no states or properties</title>
+ </head>
+ <body>
+ <div role="alert" id="test">Placeholder content</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-alertdialog.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-alertdialog.html
new file mode 100644
index 00000000000..88941fea2f6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-alertdialog.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Plain &lt;div&gt; with role "alertdialog" and no states or properties</title>
+ </head>
+ <body>
+ <div role="alertdialog" id="test">Placeholder content</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-application.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-application.html
new file mode 100644
index 00000000000..6eea2d0c030
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-application.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Plain &lt;div&gt; with role "application" and no states or properties</title>
+ </head>
+ <body>
+ <div role="application" id="test">Placeholder content</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-article.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-article.html
new file mode 100644
index 00000000000..c8d99c590e4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-article.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Plain &lt;div&gt; with role "article" and no states or properties</title>
+ </head>
+ <body>
+ <div role="article" id="test">Placeholder content</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-banner.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-banner.html
new file mode 100644
index 00000000000..f9a8c06e88e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-banner.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Plain &lt;div&gt; with role "banner" and no states or properties</title>
+ </head>
+ <body>
+ <div role="banner" id="test">Placeholder content</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-button.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-button.html
new file mode 100644
index 00000000000..f6edccdf13e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-button.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Plain &lt;div&gt; with role "button" and no states or properties</title>
+ </head>
+ <body>
+ <div role="button" id="test">Placeholder content</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-complementary.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-complementary.html
new file mode 100644
index 00000000000..86a33255321
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-complementary.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Plain &lt;div&gt; with role "complementary" and no states or properties</title>
+ </head>
+ <body>
+ <div role="complementary" id="test">Placeholder content</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-contentinfo.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-contentinfo.html
new file mode 100644
index 00000000000..89d579eb05c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-contentinfo.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Plain &lt;div&gt; with role "contentinfo" and no states or properties</title>
+ </head>
+ <body>
+ <div role="contentinfo" id="test">Placeholder content</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-definition.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-definition.html
new file mode 100644
index 00000000000..5bdf02c9c5f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-definition.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Plain &lt;div&gt; with role "definition" and no states or properties</title>
+ </head>
+ <body>
+ <div role="definition" id="test">Placeholder content</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-dialog.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-dialog.html
new file mode 100644
index 00000000000..59ac2084c64
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-dialog.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Plain &lt;div&gt; with role "dialog" and no states or properties</title>
+ </head>
+ <body>
+ <div role="dialog" id="test">Placeholder content</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-directory.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-directory.html
new file mode 100644
index 00000000000..17ca3b66940
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-directory.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Plain &lt;div&gt; with role "directory" and no states or properties</title>
+ </head>
+ <body>
+ <div role="directory" id="test">Placeholder content</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-document.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-document.html
new file mode 100644
index 00000000000..a5bc88c614b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-document.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Plain &lt;div&gt; with role "document" and no states or properties</title>
+ </head>
+ <body>
+ <div role="document" id="test">Placeholder content</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-form.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-form.html
new file mode 100644
index 00000000000..2ca7e72deb0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-form.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Plain &lt;div&gt; with role "form" and no states or properties</title>
+ </head>
+ <body>
+ <div role="form" id="test">Placeholder content</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-grid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-grid.html
new file mode 100644
index 00000000000..3ed0c84a83e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-grid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Plain &lt;div&gt; with role "grid" and no states or properties</title>
+ </head>
+ <body>
+ <div role="grid" id="test">Placeholder content</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-group.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-group.html
new file mode 100644
index 00000000000..bcd135f68ed
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-group.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Plain &lt;div&gt; with role "group" and no states or properties</title>
+ </head>
+ <body>
+ <div role="group" id="test">Placeholder content</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-heading.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-heading.html
new file mode 100644
index 00000000000..db544900589
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-heading.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Plain &lt;div&gt; with role "heading" and no states or properties</title>
+ </head>
+ <body>
+ <div role="heading" id="test">Placeholder content</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-img.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-img.html
new file mode 100644
index 00000000000..a1f9276336b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-img.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Plain &lt;div&gt; with role "img" and no states or properties</title>
+ </head>
+ <body>
+ <div role="img" id="test">Placeholder content</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-link.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-link.html
new file mode 100644
index 00000000000..5b17724ee41
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-link.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Plain &lt;div&gt; with role "link" and no states or properties</title>
+ </head>
+ <body>
+ <div role="link" id="test">Placeholder content</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-list.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-list.html
new file mode 100644
index 00000000000..72ffee9effa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-list.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Plain &lt;div&gt; with role "list" and no states or properties</title>
+ </head>
+ <body>
+ <div role="list" id="test">Placeholder content</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-listbox-parent-combobox.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-listbox-parent-combobox.html
new file mode 100644
index 00000000000..e2e0135eeb2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-listbox-parent-combobox.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>An element with id=test and role=listbox, which is owned by a combobox</title>
+ <style type="text/css">
+ ul#test {
+ list-style-type: none;
+ width: 5em;
+ height: 3em;
+ border: 1px solid black;
+ margin-top: 0;
+ margin-left: 1em;
+ }
+
+ ul#test > li {
+ margin-left -10em;
+ }
+ </style>
+ </head>
+ <body>
+ <p>An element with <code>id=test</code> and <code>role=listbox</code>, which is owned by a <code>combobox</code>:</p>
+ <input type="text"
+ aria-label="Comobox that owns zebra-zoom listbox"
+ role="combobox"
+ aria-expanded="true"
+ aria-owns="test"
+ aria-autocomplete="none"
+ aria-activedescendant="selected_option">
+ <ul role="listbox" id="test">
+ <li role="option">Zebra</li>
+ <li role="option" id="selected_option">Zoom</li>
+ </ul>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-listbox.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-listbox.html
new file mode 100644
index 00000000000..ff7d32166a6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-listbox.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Plain &lt;div&gt; with role "listbox" and no states or properties</title>
+ </head>
+ <body>
+ <div role="listbox" id="test">
+ <div role="option">Placeholder content</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-log.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-log.html
new file mode 100644
index 00000000000..1a535928043
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-log.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Plain &lt;div&gt; with role "log" and no states or properties</title>
+ </head>
+ <body>
+ <div role="log" id="test">Placeholder content</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-main.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-main.html
new file mode 100644
index 00000000000..1f66605023e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-main.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Plain &lt;div&gt; with role "main" and no states or properties</title>
+ </head>
+ <body>
+ <div role="main" id="test">Placeholder content</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-marquee.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-marquee.html
new file mode 100644
index 00000000000..05986754b2e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-marquee.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Plain &lt;div&gt; with role "marquee" and no states or properties</title>
+ </head>
+ <body>
+ <div role="marquee" id="test">Placeholder content</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-math.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-math.html
new file mode 100644
index 00000000000..66f7571d1ad
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-math.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Plain &lt;div&gt; with role "math" and no states or properties</title>
+ </head>
+ <body>
+ <div role="math" id="test">Placeholder content</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-menu.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-menu.html
new file mode 100644
index 00000000000..63c3375aaea
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-menu.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Plain &lt;div&gt; with role "menu" and no states or properties</title>
+ </head>
+ <body>
+ <div role="menu" id="test">Placeholder content</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-menubar.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-menubar.html
new file mode 100644
index 00000000000..5e9b6a1a3d8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-menubar.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Plain &lt;div&gt; with role "menubar" and no states or properties</title>
+ </head>
+ <body>
+ <div role="menubar" id="test">Placeholder content</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-navigation.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-navigation.html
new file mode 100644
index 00000000000..1a0cc38ef6e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-navigation.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Plain &lt;div&gt; with role "navigation" and no states or properties</title>
+ </head>
+ <body>
+ <div role="navigation" id="test">Placeholder content</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-note.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-note.html
new file mode 100644
index 00000000000..6fd8bb80b79
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-note.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Plain &lt;div&gt; with role "note" and no states or properties</title>
+ </head>
+ <body>
+ <div role="note" id="test">Placeholder content</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-option.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-option.html
new file mode 100644
index 00000000000..1a44d86561e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-option.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Plain &lt;div&gt; with role "option" and no states or properties</title>
+ </head>
+ <body>
+ <div role="listbox">
+ <div role="option" id="test">Placeholder content</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-presentation.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-presentation.html
new file mode 100644
index 00000000000..0ebd3cdb812
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-presentation.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Plain &lt;div&gt; with role "presentation" and no states or properties</title>
+ </head>
+ <body>
+ <div role="presentation" id="test">Placeholder content</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-progressbar.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-progressbar.html
new file mode 100644
index 00000000000..cbfdef50975
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-progressbar.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Plain &lt;div&gt; with role "progressbar" and no states or properties</title>
+ </head>
+ <body>
+ <div role="progressbar" id="test">Placeholder content</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-radiogroup.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-radiogroup.html
new file mode 100644
index 00000000000..a4caff06f75
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-radiogroup.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Plain &lt;div&gt; with role "radiogroup" and no states or properties</title>
+ </head>
+ <body>
+ <div role="radiogroup" id="test">Placeholder content</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-region.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-region.html
new file mode 100644
index 00000000000..29929c149b4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-region.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Plain &lt;div&gt; with role "region" and no states or properties</title>
+ </head>
+ <body>
+ <div role="region" id="test">Placeholder content</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-rowheader.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-rowheader.html
new file mode 100644
index 00000000000..9a1bba18ee3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-rowheader.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Plain &lt;div&gt; with role "rowheader" and no states or properties</title>
+ </head>
+ <body>
+ <div role="grid">
+ <div role="row">
+ <div role="rowheader" id="test">Placeholder content</div>
+ </div>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-search.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-search.html
new file mode 100644
index 00000000000..160cec84b72
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-search.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Plain &lt;div&gt; with role "search" and no states or properties</title>
+ </head>
+ <body>
+ <div role="search" id="test">Placeholder content</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-separator.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-separator.html
new file mode 100644
index 00000000000..d8d8352876b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-separator.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Plain &lt;div&gt; with role "separator" and no states or properties</title>
+ </head>
+ <body>
+ <div role="separator" id="test">Placeholder content</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-status.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-status.html
new file mode 100644
index 00000000000..9e413849352
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-status.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Plain &lt;div&gt; with role "status" and no states or properties</title>
+ </head>
+ <body>
+ <div role="status" id="test">Placeholder content</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-tablist.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-tablist.html
new file mode 100644
index 00000000000..211eda8154f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-tablist.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Plain &lt;div&gt; with role "tablist" and no states or properties</title>
+ </head>
+ <body>
+ <div role="tablist" id="test">Placeholder content</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-tabpanel.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-tabpanel.html
new file mode 100644
index 00000000000..3884f39422c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-tabpanel.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Plain &lt;div&gt; with role "tabpanel" and no states or properties</title>
+ </head>
+ <body>
+ <div role="tabpanel" id="test">Placeholder content</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-textbox.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-textbox.html
new file mode 100644
index 00000000000..fcfe673fb50
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-textbox.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Plain &lt;div&gt; with role "textbox" and no states or properties</title>
+ </head>
+ <body>
+ <div role="textbox" id="test">Placeholder content</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-timer.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-timer.html
new file mode 100644
index 00000000000..af15207e0ce
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-timer.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Plain &lt;div&gt; with role "timer" and no states or properties</title>
+ </head>
+ <body>
+ <div role="timer" id="test">Placeholder content</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-toolbar.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-toolbar.html
new file mode 100644
index 00000000000..8324070282b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-toolbar.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Plain &lt;div&gt; with role "toolbar" and no states or properties</title>
+ </head>
+ <body>
+ <div role="toolbar" id="test">Placeholder content</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-tooltip.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-tooltip.html
new file mode 100644
index 00000000000..299346439b8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-tooltip.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Plain &lt;div&gt; with role "tooltip" and no states or properties</title>
+ </head>
+ <body>
+ <div role="tooltip" id="test">Placeholder content</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-tree.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-tree.html
new file mode 100644
index 00000000000..a194de5a290
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-tree.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Plain &lt;div&gt; with role "tree" and no states or properties</title>
+ </head>
+ <body>
+ <div role="tree" id="test">Placeholder content</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-treegrid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-treegrid.html
new file mode 100644
index 00000000000..25b242627cf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-plain-concrete/roles-plain-concrete-treegrid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Plain &lt;div&gt; with role "treegrid" and no states or properties</title>
+ </head>
+ <body>
+ <div role="treegrid" id="test">Placeholder content</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-atomic-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-atomic-false.html
new file mode 100644
index 00000000000..a2c0b726210
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-atomic-false.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role main; global state or property "aria-atomic" value of "false"</title>
+ </head>
+ <body>
+ <div id="test" role="main" aria-live="polite" aria-atomic="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-atomic-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-atomic-true.html
new file mode 100644
index 00000000000..53f5b6d8051
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-atomic-true.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role main; global state or property "aria-atomic" value of "true"</title>
+ </head>
+ <body>
+ <div id="test" role="main" aria-live="polite" aria-atomic="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-busy-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-busy-false.html
new file mode 100644
index 00000000000..59b1eaed136
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-busy-false.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role main; global state or property "aria-busy" value of "false"</title>
+ </head>
+ <body>
+ <div id="test" role="main" aria-busy="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-busy-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-busy-true.html
new file mode 100644
index 00000000000..f6d8f549924
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-busy-true.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role main; global state or property "aria-busy" value of "true"</title>
+ </head>
+ <body>
+ <div id="test" role="main" aria-busy="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-controls-obj1-obj2.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-controls-obj1-obj2.html
new file mode 100644
index 00000000000..5d095774a18
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-controls-obj1-obj2.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role main; global state or property "aria-controls" value of "obj1 obj2"</title>
+ </head>
+ <body>
+ <div id="test" role="main" aria-controls="obj1 obj2">Placeholder content</div>
+ <div id="obj1" role="navigation">obj1</div>
+ <div id="obj2" role="contentinfo">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-controls-obj1.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-controls-obj1.html
new file mode 100644
index 00000000000..56db460384b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-controls-obj1.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role main; global state or property "aria-controls" value of "obj1"</title>
+ </head>
+ <body>
+ <div id="test" role="main" aria-controls="obj1">Placeholder content</div>
+ <div id="obj1" role="navigation">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-describedby-obj1-obj2.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-describedby-obj1-obj2.html
new file mode 100644
index 00000000000..55369c9520d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-describedby-obj1-obj2.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role main; global state or property "aria-describedby" value of "obj1 obj2"</title>
+ </head>
+ <body>
+ <div id="test" role="main" aria-describedby="obj1 obj2">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-describedby-obj1.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-describedby-obj1.html
new file mode 100644
index 00000000000..bb3c294f7f7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-describedby-obj1.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role main; global state or property "aria-describedby" value of "obj1"</title>
+ </head>
+ <body>
+ <div id="test" role="main" aria-describedby="obj1">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-disabled-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-disabled-false.html
new file mode 100644
index 00000000000..90de02c084c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-disabled-false.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role main; global state or property "aria-disabled" value of "false"</title>
+ </head>
+ <body>
+ <div id="test" role="main" aria-disabled="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-disabled-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-disabled-true.html
new file mode 100644
index 00000000000..336975f51d1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-disabled-true.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role main; global state or property "aria-disabled" value of "true"</title>
+ </head>
+ <body>
+ <div id="test" role="main" aria-disabled="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-dropeffect-copy.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-dropeffect-copy.html
new file mode 100644
index 00000000000..4653a0a8fd6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-dropeffect-copy.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role main; global state or property "aria-dropeffect" value of "copy"</title>
+ </head>
+ <body>
+ <div id="test" role="main" aria-dropeffect="copy">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-dropeffect-execute.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-dropeffect-execute.html
new file mode 100644
index 00000000000..54752744554
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-dropeffect-execute.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role main; global state or property "aria-dropeffect" value of "execute"</title>
+ </head>
+ <body>
+ <div id="test" role="main" aria-dropeffect="execute">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-dropeffect-link.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-dropeffect-link.html
new file mode 100644
index 00000000000..b592f1e1ea5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-dropeffect-link.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role main; global state or property "aria-dropeffect" value of "link"</title>
+ </head>
+ <body>
+ <div id="test" role="main" aria-dropeffect="link">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-dropeffect-move.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-dropeffect-move.html
new file mode 100644
index 00000000000..a7caad7709c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-dropeffect-move.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role main; global state or property "aria-dropeffect" value of "move"</title>
+ </head>
+ <body>
+ <div id="test" role="main" aria-dropeffect="move">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-dropeffect-none.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-dropeffect-none.html
new file mode 100644
index 00000000000..86c73586e19
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-dropeffect-none.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role main; global state or property "aria-dropeffect" value of "none"</title>
+ </head>
+ <body>
+ <div id="test" role="main" aria-dropeffect="none">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-dropeffect-popup.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-dropeffect-popup.html
new file mode 100644
index 00000000000..23c5f5c3dfa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-dropeffect-popup.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role main; global state or property "aria-dropeffect" value of "popup"</title>
+ </head>
+ <body>
+ <div id="test" role="main" aria-dropeffect="popup">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-flowto-obj1-obj2.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-flowto-obj1-obj2.html
new file mode 100644
index 00000000000..3c72e0c5da3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-flowto-obj1-obj2.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role main; global state or property "aria-flowto" value of "obj1 obj2"</title>
+ </head>
+ <body>
+ <div id="test" role="main" aria-flowto="obj1 obj2">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-flowto-obj1.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-flowto-obj1.html
new file mode 100644
index 00000000000..92747023e93
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-flowto-obj1.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role main; global state or property "aria-flowto" value of "obj1"</title>
+ </head>
+ <body>
+ <div id="test" role="main" aria-flowto="obj1">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-grabbed-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-grabbed-false.html
new file mode 100644
index 00000000000..b44f026ff30
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-grabbed-false.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role main; global state or property "aria-grabbed" value of "false"</title>
+ </head>
+ <body>
+ <div id="test" role="main" aria-grabbed="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-grabbed-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-grabbed-true.html
new file mode 100644
index 00000000000..fef9fcad8b3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-grabbed-true.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role main; global state or property "aria-grabbed" value of "true"</title>
+ </head>
+ <body>
+ <div id="test" role="main" aria-grabbed="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-grabbed-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-grabbed-undefined.html
new file mode 100644
index 00000000000..fbe3f69cb2a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-grabbed-undefined.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role main; global state or property "aria-grabbed" value of "undefined"</title>
+ </head>
+ <body>
+ <div id="test" role="main" aria-grabbed="undefined">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-haspopup-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-haspopup-false.html
new file mode 100644
index 00000000000..b25ab992148
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-haspopup-false.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role main; global state or property "aria-haspopup" value of "false"</title>
+ </head>
+ <body>
+ <div id="test" role="main" aria-haspopup="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-haspopup-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-haspopup-true.html
new file mode 100644
index 00000000000..c3d6e6af3e3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-haspopup-true.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role main; global state or property "aria-haspopup" value of "true"</title>
+ </head>
+ <body>
+ <div id="test" role="main" aria-haspopup="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-hidden-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-hidden-false.html
new file mode 100644
index 00000000000..fe96171ccc8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-hidden-false.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role main; global state or property "aria-hidden" value of "false"</title>
+ </head>
+ <body>
+ <div id="test" role="main" aria-hidden="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-hidden-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-hidden-true.html
new file mode 100644
index 00000000000..976cfcc5206
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-hidden-true.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role main; global state or property "aria-hidden" value of "true"</title>
+ </head>
+ <body>
+ <div id="test" role="main" aria-hidden="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-invalid-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-invalid-false.html
new file mode 100644
index 00000000000..ad14b3339bf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-invalid-false.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role main; global state or property "aria-invalid" value of "false"</title>
+ </head>
+ <body>
+ <div id="test" role="main" aria-invalid="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-invalid-grammar.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-invalid-grammar.html
new file mode 100644
index 00000000000..cea7b01aed4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-invalid-grammar.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role main; global state or property "aria-invalid" value of "grammar"</title>
+ </head>
+ <body>
+ <div id="test" role="main" aria-invalid="grammar">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-invalid-spelling.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-invalid-spelling.html
new file mode 100644
index 00000000000..7ce89475814
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-invalid-spelling.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role main; global state or property "aria-invalid" value of "spelling"</title>
+ </head>
+ <body>
+ <div id="test" role="main" aria-invalid="spelling">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-invalid-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-invalid-true.html
new file mode 100644
index 00000000000..8dc3c233ff0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-invalid-true.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role main; global state or property "aria-invalid" value of "true"</title>
+ </head>
+ <body>
+ <div id="test" role="main" aria-invalid="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-label-Test-string-value.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-label-Test-string-value.html
new file mode 100644
index 00000000000..dc0c036d20c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-label-Test-string-value.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role main; global state or property "aria-label" value of "Test string
+ value"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="main" aria-label="Test string value">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-labelledby-obj1-obj2.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-labelledby-obj1-obj2.html
new file mode 100644
index 00000000000..36ee9dcd5a7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-labelledby-obj1-obj2.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role main; global state or property "aria-labelledby" value of "obj1 obj2"</title>
+ </head>
+ <body>
+ <div id="test" role="main" aria-labelledby="obj1 obj2">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-labelledby-obj1.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-labelledby-obj1.html
new file mode 100644
index 00000000000..dbcc750638f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-labelledby-obj1.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role main; global state or property "aria-labelledby" value of "obj1"</title>
+ </head>
+ <body>
+ <div id="test" role="main" aria-labelledby="obj1">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-live-assertive.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-live-assertive.html
new file mode 100644
index 00000000000..05f2f3fe875
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-live-assertive.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role main; global state or property "aria-live" value of "assertive"</title>
+ </head>
+ <body>
+ <div id="test" role="main" aria-live="assertive">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-live-off.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-live-off.html
new file mode 100644
index 00000000000..1ff8ac31c2c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-live-off.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role main; global state or property "aria-live" value of "off"</title>
+ </head>
+ <body>
+ <div id="test" role="main" aria-live="off">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-live-polite.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-live-polite.html
new file mode 100644
index 00000000000..829bf79069b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-live-polite.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role main; global state or property "aria-live" value of "polite"</title>
+ </head>
+ <body>
+ <div id="test" role="main" aria-live="polite">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-owns-obj1-obj2.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-owns-obj1-obj2.html
new file mode 100644
index 00000000000..2276906bff5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-owns-obj1-obj2.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role main; global state or property "aria-owns" value of "obj1 obj2"</title>
+ </head>
+ <body>
+ <div id="test" role="main" aria-owns="obj1 obj2">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-owns-obj1.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-owns-obj1.html
new file mode 100644
index 00000000000..ebb95c433d7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-owns-obj1.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role main; global state or property "aria-owns" value of "obj1"</title>
+ </head>
+ <body>
+ <div id="test" role="main" aria-owns="obj1">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-relevant-additions-text.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-relevant-additions-text.html
new file mode 100644
index 00000000000..be51d2872e4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-relevant-additions-text.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role main; global state or property "aria-relevant" value of "additions
+ text"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="main" aria-relevant="additions text">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-relevant-additions.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-relevant-additions.html
new file mode 100644
index 00000000000..59ae86e4ff5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-relevant-additions.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role main; global state or property "aria-relevant" value of "additions"</title>
+ </head>
+ <body>
+ <div id="test" role="main" aria-relevant="additions">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-relevant-all.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-relevant-all.html
new file mode 100644
index 00000000000..d87c522953b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-relevant-all.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role main; global state or property "aria-relevant" value of "all"</title>
+ </head>
+ <body>
+ <div id="test" role="main" aria-relevant="all">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-relevant-removals.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-relevant-removals.html
new file mode 100644
index 00000000000..791a6b2e8e1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-relevant-removals.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role main; global state or property "aria-relevant" value of "removals"</title>
+ </head>
+ <body>
+ <div id="test" role="main" aria-relevant="removals">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-relevant-text.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-relevant-text.html
new file mode 100644
index 00000000000..03cabb3fbb3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-global/roles-properties-global-main-aria-relevant-text.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role main; global state or property "aria-relevant" value of "text"</title>
+ </head>
+ <body>
+ <div id="test" role="main" aria-relevant="text">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-required-inherited/menuitemcheckbox-aria-checked-mixed.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-required-inherited/menuitemcheckbox-aria-checked-mixed.html
new file mode 100644
index 00000000000..837739e7ab6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-required-inherited/menuitemcheckbox-aria-checked-mixed.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role menuitemcheckbox; inherited required state or property "aria-checked"
+ value of "mixed"
+ </title>
+ </head>
+ <body>
+ <div role="menu">
+ <div id="test" role="menuitemcheckbox" aria-checked="mixed">Placeholder content</div>
+ </div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-required-inherited/menuitemcheckbox-aria-checked-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-required-inherited/menuitemcheckbox-aria-checked-undefined.html
new file mode 100644
index 00000000000..75f3f087f13
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-required-inherited/menuitemcheckbox-aria-checked-undefined.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role menuitemcheckbox; inherited required state or property "aria-checked"
+ value of "undefined"
+ </title>
+ </head>
+ <body>
+ <div role="menu">
+ <div id="test" role="menuitemcheckbox" aria-checked="undefined">Placeholder content</div>
+ </div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-required-inherited/radio-aria-checked-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-required-inherited/radio-aria-checked-false.html
new file mode 100644
index 00000000000..72d48e77cf0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-required-inherited/radio-aria-checked-false.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role radio; inherited required state or property "aria-checked" value of
+ "false"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="radio" aria-checked="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-required-inherited/radio-aria-checked-mixed.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-required-inherited/radio-aria-checked-mixed.html
new file mode 100644
index 00000000000..19593293223
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-required-inherited/radio-aria-checked-mixed.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role radio; inherited required state or property "aria-checked" value of
+ "mixed"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="radio" aria-checked="mixed">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-required-inherited/radio-aria-checked-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-required-inherited/radio-aria-checked-true.html
new file mode 100644
index 00000000000..81571b60c5e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-required-inherited/radio-aria-checked-true.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role radio; inherited required state or property "aria-checked" value of
+ "true"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="radio" aria-checked="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-required-inherited/radio-aria-checked-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-required-inherited/radio-aria-checked-undefined.html
new file mode 100644
index 00000000000..95a1ca7a27e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-required-inherited/radio-aria-checked-undefined.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role radio; inherited required state or property "aria-checked" value of
+ "undefined"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="radio" aria-checked="undefined">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-required/roles-properties-required-checkbox-aria-checked-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-required/roles-properties-required-checkbox-aria-checked-false.html
new file mode 100644
index 00000000000..21e7b0366af
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-required/roles-properties-required-checkbox-aria-checked-false.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role checkbox; required state or property "aria-checked" value of "false"</title>
+ </head>
+ <body>
+ <div id="test" role="checkbox" aria-checked="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-required/roles-properties-required-checkbox-aria-checked-mixed.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-required/roles-properties-required-checkbox-aria-checked-mixed.html
new file mode 100644
index 00000000000..09200351ed1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-required/roles-properties-required-checkbox-aria-checked-mixed.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role checkbox; required state or property "aria-checked" value of "mixed"</title>
+ </head>
+ <body>
+ <div id="test" role="checkbox" aria-checked="mixed">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-required/roles-properties-required-checkbox-aria-checked-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-required/roles-properties-required-checkbox-aria-checked-true.html
new file mode 100644
index 00000000000..295d992b102
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-required/roles-properties-required-checkbox-aria-checked-true.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role checkbox; required state or property "aria-checked" value of "true"</title>
+ </head>
+ <body>
+ <div id="test" role="checkbox" aria-checked="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-required/roles-properties-required-checkbox-aria-checked-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-required/roles-properties-required-checkbox-aria-checked-undefined.html
new file mode 100644
index 00000000000..250454f822f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-required/roles-properties-required-checkbox-aria-checked-undefined.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role checkbox; required state or property "aria-checked" value of "undefined"</title>
+ </head>
+ <body>
+ <div id="test" tabindex="0" role="checkbox" aria-checked="undefined">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-required/roles-properties-required-combobox-aria-expanded-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-required/roles-properties-required-combobox-aria-expanded-false.html
new file mode 100644
index 00000000000..751747aec55
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-required/roles-properties-required-combobox-aria-expanded-false.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role combobox; required state or property "aria-expanded" value of "false"</title>
+ </head>
+ <body>
+ <div id="test" role="combobox" aria-expanded="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-required/roles-properties-required-combobox-aria-expanded-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-required/roles-properties-required-combobox-aria-expanded-true.html
new file mode 100644
index 00000000000..46cd8e5061c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-required/roles-properties-required-combobox-aria-expanded-true.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role combobox; required state or property "aria-expanded" value of "true"</title>
+ </head>
+ <body>
+ <div id="test" role="combobox" aria-expanded="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-required/roles-properties-required-combobox-aria-expanded-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-required/roles-properties-required-combobox-aria-expanded-undefined.html
new file mode 100644
index 00000000000..58ea1d313c1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-required/roles-properties-required-combobox-aria-expanded-undefined.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role combobox; required state or property "aria-expanded" value of "undefined"</title>
+ </head>
+ <body>
+ <div id="test" role="combobox" aria-expanded="undefined">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/alert-aria-expanded-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/alert-aria-expanded-false.html
new file mode 100644
index 00000000000..ac960fdbf66
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/alert-aria-expanded-false.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role alert; inherited supported state or property "aria-expanded" value
+ of "false"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="alert" aria-expanded="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/alert-aria-expanded-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/alert-aria-expanded-true.html
new file mode 100644
index 00000000000..1b9c610fcc6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/alert-aria-expanded-true.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role alert; inherited supported state or property "aria-expanded" value
+ of "true"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="alert" aria-expanded="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/alert-aria-expanded-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/alert-aria-expanded-undefined.html
new file mode 100644
index 00000000000..d6f9d8d7931
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/alert-aria-expanded-undefined.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role alert; inherited supported state or property "aria-expanded" value
+ of "undefined"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="alert" aria-expanded="undefined">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/alertdialog-aria-expanded-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/alertdialog-aria-expanded-false.html
new file mode 100644
index 00000000000..d8799706457
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/alertdialog-aria-expanded-false.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role alertdialog; inherited supported state or property "aria-expanded"
+ value of "false"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="alertdialog" aria-expanded="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/alertdialog-aria-expanded-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/alertdialog-aria-expanded-true.html
new file mode 100644
index 00000000000..71f7c1b48b5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/alertdialog-aria-expanded-true.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role alertdialog; inherited supported state or property "aria-expanded"
+ value of "true"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="alertdialog" aria-expanded="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/alertdialog-aria-expanded-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/alertdialog-aria-expanded-undefined.html
new file mode 100644
index 00000000000..048ac59a789
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/alertdialog-aria-expanded-undefined.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role alertdialog; inherited supported state or property "aria-expanded"
+ value of "undefined"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="alertdialog" aria-expanded="undefined">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/application-aria-expanded-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/application-aria-expanded-false.html
new file mode 100644
index 00000000000..8b12de5aabe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/application-aria-expanded-false.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role application; inherited supported state or property "aria-expanded"
+ value of "false"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="application" aria-expanded="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/application-aria-expanded-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/application-aria-expanded-true.html
new file mode 100644
index 00000000000..0b7a2545f5c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/application-aria-expanded-true.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role application; inherited supported state or property "aria-expanded"
+ value of "true"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="application" aria-expanded="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/application-aria-expanded-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/application-aria-expanded-undefined.html
new file mode 100644
index 00000000000..04c44727dc9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/application-aria-expanded-undefined.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role application; inherited supported state or property "aria-expanded"
+ value of "undefined"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="application" aria-expanded="undefined">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/article-aria-expanded-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/article-aria-expanded-false.html
new file mode 100644
index 00000000000..6de04bcc874
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/article-aria-expanded-false.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role article; inherited supported state or property "aria-expanded" value
+ of "false"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="article" aria-expanded="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/article-aria-expanded-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/article-aria-expanded-true.html
new file mode 100644
index 00000000000..bf6bea82659
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/article-aria-expanded-true.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role article; inherited supported state or property "aria-expanded" value
+ of "true"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="article" aria-expanded="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/article-aria-expanded-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/article-aria-expanded-undefined.html
new file mode 100644
index 00000000000..804330711c3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/article-aria-expanded-undefined.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role article; inherited supported state or property "aria-expanded" value
+ of "undefined"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="article" aria-expanded="undefined">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/banner-aria-expanded-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/banner-aria-expanded-false.html
new file mode 100644
index 00000000000..ddb241c4847
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/banner-aria-expanded-false.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role banner; inherited supported state or property "aria-expanded" value
+ of "false"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="banner" aria-expanded="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/banner-aria-expanded-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/banner-aria-expanded-true.html
new file mode 100644
index 00000000000..433e68b2e62
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/banner-aria-expanded-true.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role banner; inherited supported state or property "aria-expanded" value
+ of "true"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="banner" aria-expanded="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/banner-aria-expanded-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/banner-aria-expanded-undefined.html
new file mode 100644
index 00000000000..ed7605d79c0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/banner-aria-expanded-undefined.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role banner; inherited supported state or property "aria-expanded" value
+ of "undefined"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="banner" aria-expanded="undefined">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/columnheader-aria-expanded-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/columnheader-aria-expanded-false.html
new file mode 100644
index 00000000000..4376474659d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/columnheader-aria-expanded-false.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role columnheader; inherited supported state or property "aria-expanded"
+ value of "false"
+ </title>
+ </head>
+ <body>
+ <div role="grid">
+ <div role="row">
+ <span id="test" role="columnheader" aria-expanded="false">Placeholder content</span>
+ <span role="columnheader">header 2</span>
+ <span role="columnheader">header 3</span>
+ </div>
+ <div role="row">
+ <span role="gridcell" id="obj1">obj1</span>
+ <span role="gridcell">obj2</span>
+ <span role="gridcell">obj3</span>
+ </div>
+ <div role="row">
+ <span role="gridcell">obj1</span>
+ <span role="gridcell">obj2</span>
+ <span role="gridcell">obj3</span>
+ </div>
+ <div role="row">
+ <span role="gridcell">obj1</span>
+ <span role="gridcell">obj2</span>
+ <span role="gridcell">obj3</span>
+ </div>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/columnheader-aria-expanded-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/columnheader-aria-expanded-true.html
new file mode 100644
index 00000000000..521b93520e8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/columnheader-aria-expanded-true.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role columnheader; inherited supported state or property "aria-expanded"
+ value of "true"
+ </title>
+ </head>
+ <body>
+ <div role="grid">
+ <div role="row">
+ <span id="test" role="columnheader" aria-expanded="true">Placeholder content</span>
+ <span role="columnheader">header 2</span>
+ <span role="columnheader">header 3</span>
+ </div>
+ <div role="row">
+ <span role="gridcell" id="obj1">obj1</span>
+ <span role="gridcell">obj2</span>
+ <span role="gridcell">obj3</span>
+ </div>
+ <div role="row">
+ <span role="gridcell">obj1</span>
+ <span role="gridcell">obj2</span>
+ <span role="gridcell">obj3</span>
+ </div>
+ <div role="row">
+ <span role="gridcell">obj1</span>
+ <span role="gridcell">obj2</span>
+ <span role="gridcell">obj3</span>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/columnheader-aria-expanded-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/columnheader-aria-expanded-undefined.html
new file mode 100644
index 00000000000..295c4eb5f7b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/columnheader-aria-expanded-undefined.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role columnheader; inherited supported state or property "aria-expanded"
+ value of "undefined"
+ </title>
+ </head>
+ <body>
+ <div role="grid">
+ <div role="row">
+ <span id="test" role="columnheader" aria-expanded="undefined">Placeholder content</span>
+ <span role="columnheader">header 2</span>
+ <span role="columnheader">header 3</span>
+ </div>
+ <div role="row">
+ <span role="gridcell" id="obj1">obj1</span>
+ <span role="gridcell">obj2</span>
+ <span role="gridcell">obj3</span>
+ </div>
+ <div role="row">
+ <span role="gridcell">obj1</span>
+ <span role="gridcell">obj2</span>
+ <span role="gridcell">obj3</span>
+ </div>
+ <div role="row">
+ <span role="gridcell">obj1</span>
+ <span role="gridcell">obj2</span>
+ <span role="gridcell">obj3</span>
+ </div>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/columnheader-aria-readonly-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/columnheader-aria-readonly-false.html
new file mode 100644
index 00000000000..6c32d6ae543
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/columnheader-aria-readonly-false.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role columnheader; inherited supported state or property "aria-readonly"
+ value of "false"
+ </title>
+ </head>
+ <body>
+ <div role="grid">
+ <div role="row">
+ <span id="test" role="columnheader" aria-readonly="false">Placeholder content</span>
+ <span role="columnheader">header 2</span>
+ <span role="columnheader">header 3</span>
+ </div>
+ <div role="row">
+ <span role="gridcell" id="obj1">obj1</span>
+ <span role="gridcell">obj2</span>
+ <span role="gridcell">obj3</span>
+ </div>
+ <div role="row">
+ <span role="gridcell">obj1</span>
+ <span role="gridcell">obj2</span>
+ <span role="gridcell">obj3</span>
+ </div>
+ <div role="row">
+ <span role="gridcell">obj1</span>
+ <span role="gridcell">obj2</span>
+ <span role="gridcell">obj3</span>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/columnheader-aria-readonly-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/columnheader-aria-readonly-true.html
new file mode 100644
index 00000000000..6ce21d3137f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/columnheader-aria-readonly-true.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role columnheader; inherited supported state or property "aria-readonly"
+ value of "true"
+ </title>
+ </head>
+ <body>
+ <div role="grid">
+ <div role="row">
+ <span id="test" role="columnheader" aria-readonly="true">Placeholder content</span>
+ <span role="columnheader">header 2</span>
+ <span role="columnheader">header 3</span>
+ </div>
+ <div role="row">
+ <span role="gridcell" id="obj1">obj1</span>
+ <span role="gridcell">obj2</span>
+ <span role="gridcell">obj3</span>
+ </div>
+ <div role="row">
+ <span role="gridcell">obj1</span>
+ <span role="gridcell">obj2</span>
+ <span role="gridcell">obj3</span>
+ </div>
+ <div role="row">
+ <span role="gridcell">obj1</span>
+ <span role="gridcell">obj2</span>
+ <span role="gridcell">obj3</span>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/columnheader-aria-required-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/columnheader-aria-required-false.html
new file mode 100644
index 00000000000..8c8065963be
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/columnheader-aria-required-false.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role columnheader; inherited supported state or property "aria-required"
+ value of "false"
+ </title>
+ </head>
+ <body>
+ <div role="grid">
+ <div role="row">
+ <span id="test" role="columnheader" aria-required="false">Placeholder content</span>
+ <span role="columnheader">header 2</span>
+ <span role="columnheader">header 3</span>
+ </div>
+ <div role="row">
+ <span role="gridcell" id="obj1">obj1</span>
+ <span role="gridcell">obj2</span>
+ <span role="gridcell">obj3</span>
+ </div>
+ <div role="row">
+ <span role="gridcell">obj1</span>
+ <span role="gridcell">obj2</span>
+ <span role="gridcell">obj3</span>
+ </div>
+ <div role="row">
+ <span role="gridcell">obj1</span>
+ <span role="gridcell">obj2</span>
+ <span role="gridcell">obj3</span>
+ </div>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/columnheader-aria-required-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/columnheader-aria-required-true.html
new file mode 100644
index 00000000000..644b2756d46
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/columnheader-aria-required-true.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role columnheader; inherited supported state or property "aria-required"
+ value of "true"
+ </title>
+ </head>
+ <body>
+ <div role="grid">
+ <div role="row">
+ <span id="test" role="columnheader" aria-required="true">Placeholder content</span>
+ <span role="columnheader">header 2</span>
+ <span role="columnheader">header 3</span>
+ </div>
+ <div role="row">
+ <span role="gridcell" id="obj1">obj1</span>
+ <span role="gridcell">obj2</span>
+ <span role="gridcell">obj3</span>
+ </div>
+ <div role="row">
+ <span role="gridcell">obj1</span>
+ <span role="gridcell">obj2</span>
+ <span role="gridcell">obj3</span>
+ </div>
+ <div role="row">
+ <span role="gridcell">obj1</span>
+ <span role="gridcell">obj2</span>
+ <span role="gridcell">obj3</span>
+ </div>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/columnheader-aria-selected-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/columnheader-aria-selected-false.html
new file mode 100644
index 00000000000..7a4ab45b106
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/columnheader-aria-selected-false.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role columnheader; inherited supported state or property "aria-selected"
+ value of "false"
+ </title>
+ </head>
+ <body>
+ <div role="grid">
+ <div role="row">
+ <span id="test" role="columnheader" aria-selected="false">Placeholder content</span>
+ <span role="columnheader">header 2</span>
+ <span role="columnheader">header 3</span>
+ </div>
+ <div role="row">
+ <span role="gridcell" id="obj1">obj1</span>
+ <span role="gridcell">obj2</span>
+ <span role="gridcell">obj3</span>
+ </div>
+ <div role="row">
+ <span role="gridcell">obj1</span>
+ <span role="gridcell">obj2</span>
+ <span role="gridcell">obj3</span>
+ </div>
+ <div role="row">
+ <span role="gridcell">obj1</span>
+ <span role="gridcell">obj2</span>
+ <span role="gridcell">obj3</span>
+ </div>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/columnheader-aria-selected-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/columnheader-aria-selected-true.html
new file mode 100644
index 00000000000..a16d514810c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/columnheader-aria-selected-true.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role columnheader; inherited supported state or property "aria-selected"
+ value of "true"
+ </title>
+ </head>
+ <body>
+ <div role="grid">
+ <div role="row">
+ <span id="test" role="columnheader" aria-selected="true">Placeholder content</span>
+ <span role="columnheader">header 2</span>
+ <span role="columnheader">header 3</span>
+ </div>
+ <div role="row">
+ <span role="gridcell" id="obj1">obj1</span>
+ <span role="gridcell">obj2</span>
+ <span role="gridcell">obj3</span>
+ </div>
+ <div role="row">
+ <span role="gridcell">obj1</span>
+ <span role="gridcell">obj2</span>
+ <span role="gridcell">obj3</span>
+ </div>
+ <div role="row">
+ <span role="gridcell">obj1</span>
+ <span role="gridcell">obj2</span>
+ <span role="gridcell">obj3</span>
+ </div>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/columnheader-aria-selected-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/columnheader-aria-selected-undefined.html
new file mode 100644
index 00000000000..4416bd662f3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/columnheader-aria-selected-undefined.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role columnheader; inherited supported state or property "aria-selected"
+ value of "undefined"
+ </title>
+ </head>
+ <body>
+ <div role="grid">
+ <div role="row">
+ <span id="test" role="columnheader" aria-selected="undefined">Placeholder content</span>
+ <span role="columnheader">header 2</span>
+ <span role="columnheader">header 3</span>
+ </div>
+ <div role="row">
+ <span role="gridcell" id="obj1">obj1</span>
+ <span role="gridcell">obj2</span>
+ <span role="gridcell">obj3</span>
+ </div>
+ <div role="row">
+ <span role="gridcell">obj1</span>
+ <span role="gridcell">obj2</span>
+ <span role="gridcell">obj3</span>
+ </div>
+ <div role="row">
+ <span role="gridcell">obj1</span>
+ <span role="gridcell">obj2</span>
+ <span role="gridcell">obj3</span>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/combobox-aria-activedescendant-obj1.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/combobox-aria-activedescendant-obj1.html
new file mode 100644
index 00000000000..4e8e3fd583a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/combobox-aria-activedescendant-obj1.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role combobox; inherited supported state or property "aria-activedescendant"
+ value of "obj1"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="combobox" aria-haspopup="true" aria-expanded="true" aria-activedescendant="obj1" tabindex="0">
+ <div role="textbox"></div>
+ <div role="listbox">
+ <div id="obj1" role="option">obj1</div>
+ <div id="obj2" role="option">obj2</div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/combobox-aria-expanded-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/combobox-aria-expanded-false.html
new file mode 100644
index 00000000000..76943aefa98
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/combobox-aria-expanded-false.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role combobox; inherited supported state or property "aria-expanded" value
+ of "false"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="combobox" aria-expanded="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/combobox-aria-expanded-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/combobox-aria-expanded-true.html
new file mode 100644
index 00000000000..7d29edd7a3f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/combobox-aria-expanded-true.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role combobox; inherited supported state or property "aria-expanded" value
+ of "true"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="combobox" aria-expanded="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/combobox-aria-expanded-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/combobox-aria-expanded-undefined.html
new file mode 100644
index 00000000000..46b28ef3a38
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/combobox-aria-expanded-undefined.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role combobox; inherited supported state or property "aria-expanded" value
+ of "undefined"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="combobox" aria-expanded="undefined">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/complementary-aria-expanded-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/complementary-aria-expanded-false.html
new file mode 100644
index 00000000000..ae3dcf35f32
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/complementary-aria-expanded-false.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role complementary; inherited supported state or property "aria-expanded"
+ value of "false"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="complementary" aria-expanded="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/complementary-aria-expanded-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/complementary-aria-expanded-true.html
new file mode 100644
index 00000000000..d3b0d83b3e4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/complementary-aria-expanded-true.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role complementary; inherited supported state or property "aria-expanded"
+ value of "true"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="complementary" aria-expanded="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/complementary-aria-expanded-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/complementary-aria-expanded-undefined.html
new file mode 100644
index 00000000000..a7952c25434
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/complementary-aria-expanded-undefined.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role complementary; inherited supported state or property "aria-expanded"
+ value of "undefined"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="complementary" aria-expanded="undefined">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/contentinfo-aria-expanded-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/contentinfo-aria-expanded-false.html
new file mode 100644
index 00000000000..de995a9225d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/contentinfo-aria-expanded-false.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role contentinfo; inherited supported state or property "aria-expanded"
+ value of "false"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="contentinfo" aria-expanded="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/contentinfo-aria-expanded-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/contentinfo-aria-expanded-true.html
new file mode 100644
index 00000000000..846f7295735
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/contentinfo-aria-expanded-true.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role contentinfo; inherited supported state or property "aria-expanded"
+ value of "true"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="contentinfo" aria-expanded="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/contentinfo-aria-expanded-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/contentinfo-aria-expanded-undefined.html
new file mode 100644
index 00000000000..0a924c67172
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/contentinfo-aria-expanded-undefined.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role contentinfo; inherited supported state or property "aria-expanded"
+ value of "undefined"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="contentinfo" aria-expanded="undefined">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/definition-aria-expanded-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/definition-aria-expanded-false.html
new file mode 100644
index 00000000000..7fce65cff87
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/definition-aria-expanded-false.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role definition; inherited supported state or property "aria-expanded"
+ value of "false"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="definition" aria-expanded="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/definition-aria-expanded-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/definition-aria-expanded-true.html
new file mode 100644
index 00000000000..b2ea2ce8ae4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/definition-aria-expanded-true.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role definition; inherited supported state or property "aria-expanded"
+ value of "true"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="definition" aria-expanded="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/definition-aria-expanded-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/definition-aria-expanded-undefined.html
new file mode 100644
index 00000000000..bae456aa734
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/definition-aria-expanded-undefined.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role definition; inherited supported state or property "aria-expanded"
+ value of "undefined"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="definition" aria-expanded="undefined">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/dialog-aria-expanded-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/dialog-aria-expanded-false.html
new file mode 100644
index 00000000000..e4c26f401e4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/dialog-aria-expanded-false.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role dialog; inherited supported state or property "aria-expanded" value
+ of "false"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="dialog" aria-expanded="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/dialog-aria-expanded-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/dialog-aria-expanded-true.html
new file mode 100644
index 00000000000..2095b9cd99c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/dialog-aria-expanded-true.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role dialog; inherited supported state or property "aria-expanded" value
+ of "true"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="dialog" aria-expanded="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/dialog-aria-expanded-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/dialog-aria-expanded-undefined.html
new file mode 100644
index 00000000000..1df3702ba46
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/dialog-aria-expanded-undefined.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role dialog; inherited supported state or property "aria-expanded" value
+ of "undefined"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="dialog" aria-expanded="undefined">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/directory-aria-expanded-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/directory-aria-expanded-false.html
new file mode 100644
index 00000000000..ee8ae62340d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/directory-aria-expanded-false.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role directory; inherited supported state or property "aria-expanded" value
+ of "false"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="directory" aria-expanded="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/directory-aria-expanded-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/directory-aria-expanded-true.html
new file mode 100644
index 00000000000..8ef8ae9fb7a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/directory-aria-expanded-true.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role directory; inherited supported state or property "aria-expanded" value
+ of "true"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="directory" aria-expanded="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/directory-aria-expanded-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/directory-aria-expanded-undefined.html
new file mode 100644
index 00000000000..4be1ec3f5f6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/directory-aria-expanded-undefined.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role directory; inherited supported state or property "aria-expanded" value
+ of "undefined"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="directory" aria-expanded="undefined">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/form-aria-expanded-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/form-aria-expanded-false.html
new file mode 100644
index 00000000000..ce533b2956f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/form-aria-expanded-false.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role form; inherited supported state or property "aria-expanded" value
+ of "false"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="form" aria-expanded="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/form-aria-expanded-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/form-aria-expanded-true.html
new file mode 100644
index 00000000000..01d98d4a861
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/form-aria-expanded-true.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role form; inherited supported state or property "aria-expanded" value
+ of "true"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="form" aria-expanded="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/form-aria-expanded-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/form-aria-expanded-undefined.html
new file mode 100644
index 00000000000..da9fb7bd907
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/form-aria-expanded-undefined.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role form; inherited supported state or property "aria-expanded" value
+ of "undefined"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="form" aria-expanded="undefined">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/grid-aria-activedescendant-obj1.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/grid-aria-activedescendant-obj1.html
new file mode 100644
index 00000000000..71268f39e8f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/grid-aria-activedescendant-obj1.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role grid; inherited supported state or property "aria-activedescendant"
+ value of "obj1"
+ </title>
+ </head>
+ <body>
+ <div id="test" tabindex="0" role="grid" aria-activedescendant="obj1">
+ <div role="row">
+ <span role="gridcell" id="obj1">row1-cell1</span>
+ <span role="gridcell" id="obj2">row1-cell2</span>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/grid-aria-expanded-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/grid-aria-expanded-false.html
new file mode 100644
index 00000000000..f1c958008c2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/grid-aria-expanded-false.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role grid; inherited supported state or property "aria-expanded" value
+ of "false"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="grid" aria-expanded="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/grid-aria-expanded-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/grid-aria-expanded-true.html
new file mode 100644
index 00000000000..86223ae165b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/grid-aria-expanded-true.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role grid; inherited supported state or property "aria-expanded" value
+ of "true"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="grid" aria-expanded="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/grid-aria-expanded-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/grid-aria-expanded-undefined.html
new file mode 100644
index 00000000000..aeb3693c52b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/grid-aria-expanded-undefined.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role grid; inherited supported state or property "aria-expanded" value
+ of "undefined"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="grid" aria-expanded="undefined">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/gridcell-aria-expanded-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/gridcell-aria-expanded-false.html
new file mode 100644
index 00000000000..f4955926f5a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/gridcell-aria-expanded-false.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role gridcell; inherited supported state or property "aria-expanded" value
+ of "false"
+ </title>
+ </head>
+ <body>
+ <div role="grid">
+ <div role="row">
+ <div id="test" role="gridcell" aria-expanded="false">Placeholder content</div>
+ <div id="obj1" role="gridcell">obj1</div>
+ <div id="obj2" role="gridcell">obj2</div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/gridcell-aria-expanded-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/gridcell-aria-expanded-undefined.html
new file mode 100644
index 00000000000..f68e0436996
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/gridcell-aria-expanded-undefined.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role gridcell; inherited supported state or property "aria-expanded" value
+ of "undefined"
+ </title>
+ </head>
+ <body>
+ <div role="grid">
+ <div role="row">
+ <div id="test" role="gridcell" aria-expanded="undefined">Placeholder content</div>
+ <div id="obj1" role="gridcell" >obj1</div>
+ <div id="obj2" role="gridcell" >obj2</div>
+ </div>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/group-aria-expanded-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/group-aria-expanded-false.html
new file mode 100644
index 00000000000..79a3d6a38dc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/group-aria-expanded-false.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role group; inherited supported state or property "aria-expanded" value
+ of "false"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="group" aria-expanded="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/group-aria-expanded-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/group-aria-expanded-true.html
new file mode 100644
index 00000000000..6d18a366ed3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/group-aria-expanded-true.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role group; inherited supported state or property "aria-expanded" value
+ of "true"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="group" aria-expanded="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/group-aria-expanded-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/group-aria-expanded-undefined.html
new file mode 100644
index 00000000000..4a179c532ae
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/group-aria-expanded-undefined.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role group; inherited supported state or property "aria-expanded" value
+ of "undefined"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="group" aria-expanded="undefined">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/heading-aria-expanded-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/heading-aria-expanded-false.html
new file mode 100644
index 00000000000..79976851548
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/heading-aria-expanded-false.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role heading; inherited supported state or property "aria-expanded" value
+ of "false"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="heading" aria-expanded="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/heading-aria-expanded-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/heading-aria-expanded-true.html
new file mode 100644
index 00000000000..d1c94683162
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/heading-aria-expanded-true.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role heading; inherited supported state or property "aria-expanded" value
+ of "true"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="heading" aria-expanded="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/heading-aria-expanded-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/heading-aria-expanded-undefined.html
new file mode 100644
index 00000000000..2de29fc45d1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/heading-aria-expanded-undefined.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role heading; inherited supported state or property "aria-expanded" value
+ of "undefined"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="heading" aria-expanded="undefined">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/img-aria-expanded-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/img-aria-expanded-false.html
new file mode 100644
index 00000000000..835d6bbb3b2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/img-aria-expanded-false.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role img; inherited supported state or property "aria-expanded" value of
+ "false"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="img" aria-expanded="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/img-aria-expanded-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/img-aria-expanded-true.html
new file mode 100644
index 00000000000..46ade1d9ba5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/img-aria-expanded-true.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role img; inherited supported state or property "aria-expanded" value of
+ "true"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="img" aria-expanded="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/img-aria-expanded-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/img-aria-expanded-undefined.html
new file mode 100644
index 00000000000..8d4f17be3fe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/img-aria-expanded-undefined.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role img; inherited supported state or property "aria-expanded" value of
+ "undefined"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="img" aria-expanded="undefined">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/list-aria-expanded-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/list-aria-expanded-false.html
new file mode 100644
index 00000000000..d510eb15645
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/list-aria-expanded-false.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role list; inherited supported state or property "aria-expanded" value
+ of "false"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="list" aria-expanded="false">Placeholder content
+ <div id="obj1" role="listitem">obj1</div>
+ </div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/list-aria-expanded-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/list-aria-expanded-true.html
new file mode 100644
index 00000000000..37d15ab667f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/list-aria-expanded-true.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role list; inherited supported state or property "aria-expanded" value
+ of "true"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="list" aria-expanded="true">Placeholder content
+ <div id="obj1" role="listitem">obj1</div>
+ </div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/list-aria-expanded-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/list-aria-expanded-undefined.html
new file mode 100644
index 00000000000..e1679660c2b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/list-aria-expanded-undefined.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role list; inherited supported state or property "aria-expanded" value
+ of "undefined"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="list" aria-expanded="undefined">Placeholder content
+ <div id="obj1" role="listitem">obj1</div>
+ </div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/listbox-aria-activedescendant-obj1.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/listbox-aria-activedescendant-obj1.html
new file mode 100644
index 00000000000..f28e43e6f4b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/listbox-aria-activedescendant-obj1.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role listbox; inherited supported state or property "aria-activedescendant"
+ value of "obj1"
+ </title>
+ </head>
+ <body>
+ <div id="test" tabindex="0" role="listbox" aria-activedescendant="obj1">
+ <div id="obj1" role="option">obj1</div>
+ <div id="obj2" role="option">obj2</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/listbox-aria-expanded-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/listbox-aria-expanded-false.html
new file mode 100644
index 00000000000..2bd754a3b86
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/listbox-aria-expanded-false.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role listbox; inherited supported state or property "aria-expanded" value
+ of "false"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="listbox" aria-expanded="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/listbox-aria-expanded-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/listbox-aria-expanded-true.html
new file mode 100644
index 00000000000..504c7371f9c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/listbox-aria-expanded-true.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role listbox; inherited supported state or property "aria-expanded" value
+ of "true"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="listbox" aria-expanded="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/listbox-aria-expanded-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/listbox-aria-expanded-undefined.html
new file mode 100644
index 00000000000..69055a23707
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/listbox-aria-expanded-undefined.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role listbox; inherited supported state or property "aria-expanded" value
+ of "undefined"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="listbox" aria-expanded="undefined">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/log-aria-expanded-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/log-aria-expanded-false.html
new file mode 100644
index 00000000000..fa242c39cb2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/log-aria-expanded-false.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role log; inherited supported state or property "aria-expanded" value of
+ "false"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="log" aria-expanded="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/log-aria-expanded-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/log-aria-expanded-true.html
new file mode 100644
index 00000000000..072291e90c4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/log-aria-expanded-true.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role log; inherited supported state or property "aria-expanded" value of
+ "true"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="log" aria-expanded="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/log-aria-expanded-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/log-aria-expanded-undefined.html
new file mode 100644
index 00000000000..b19c2d6d0cf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/log-aria-expanded-undefined.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role log; inherited supported state or property "aria-expanded" value of
+ "undefined"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="log" aria-expanded="undefined">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/main-aria-expanded-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/main-aria-expanded-false.html
new file mode 100644
index 00000000000..16cf8f109a7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/main-aria-expanded-false.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role main; inherited supported state or property "aria-expanded" value
+ of "false"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="main" aria-expanded="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/main-aria-expanded-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/main-aria-expanded-true.html
new file mode 100644
index 00000000000..d3687cb50fd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/main-aria-expanded-true.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role main; inherited supported state or property "aria-expanded" value
+ of "true"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="main" aria-expanded="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/main-aria-expanded-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/main-aria-expanded-undefined.html
new file mode 100644
index 00000000000..c08f1048818
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/main-aria-expanded-undefined.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role main; inherited supported state or property "aria-expanded" value
+ of "undefined"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="main" aria-expanded="undefined">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/marquee-aria-expanded-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/marquee-aria-expanded-false.html
new file mode 100644
index 00000000000..18d2f9ee850
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/marquee-aria-expanded-false.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role marquee; inherited supported state or property "aria-expanded" value
+ of "false"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="marquee" aria-expanded="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/marquee-aria-expanded-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/marquee-aria-expanded-true.html
new file mode 100644
index 00000000000..aed711775e7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/marquee-aria-expanded-true.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role marquee; inherited supported state or property "aria-expanded" value
+ of "true"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="marquee" aria-expanded="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/marquee-aria-expanded-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/marquee-aria-expanded-undefined.html
new file mode 100644
index 00000000000..9a164bea71d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/marquee-aria-expanded-undefined.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role marquee; inherited supported state or property "aria-expanded" value
+ of "undefined"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="marquee" aria-expanded="undefined">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/math-aria-expanded-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/math-aria-expanded-false.html
new file mode 100644
index 00000000000..c038fabadc2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/math-aria-expanded-false.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role math; inherited supported state or property "aria-expanded" value
+ of "false"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="math" aria-expanded="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/math-aria-expanded-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/math-aria-expanded-true.html
new file mode 100644
index 00000000000..831c095602b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/math-aria-expanded-true.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role math; inherited supported state or property "aria-expanded" value
+ of "true"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="math" aria-expanded="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/math-aria-expanded-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/math-aria-expanded-undefined.html
new file mode 100644
index 00000000000..3bd0b7b025e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/math-aria-expanded-undefined.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role math; inherited supported state or property "aria-expanded" value
+ of "undefined"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="math" aria-expanded="undefined">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/menu-aria-activedescendant-obj1.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/menu-aria-activedescendant-obj1.html
new file mode 100644
index 00000000000..06e5fc7aeb7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/menu-aria-activedescendant-obj1.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role menu; inherited supported state or property "aria-activedescendant"
+ value of "obj1"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="menu" tabindex="0" aria-activedescendant="obj1">
+ <div id="obj1" role="menuitem">obj1</div>
+ <div id="obj2" role="menuitem">obj2</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/menu-aria-expanded-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/menu-aria-expanded-false.html
new file mode 100644
index 00000000000..c96d9e2ac58
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/menu-aria-expanded-false.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role menu; inherited supported state or property "aria-expanded" value
+ of "false"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="menu" aria-expanded="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/menu-aria-expanded-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/menu-aria-expanded-true.html
new file mode 100644
index 00000000000..14361d01c1b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/menu-aria-expanded-true.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role menu; inherited supported state or property "aria-expanded" value
+ of "true"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="menu" aria-expanded="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/menu-aria-expanded-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/menu-aria-expanded-undefined.html
new file mode 100644
index 00000000000..7a82e92b13d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/menu-aria-expanded-undefined.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role menu; inherited supported state or property "aria-expanded" value
+ of "undefined"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="menu" aria-expanded="undefined">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/menubar-aria-activedescendant-obj1.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/menubar-aria-activedescendant-obj1.html
new file mode 100644
index 00000000000..e761a50a4bb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/menubar-aria-activedescendant-obj1.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role menubar; inherited supported state or property "aria-activedescendant"
+ value of "obj1"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="menubar" tabindex="0" aria-activedescendant="obj1">
+ <div id="obj1" role="menuitem">obj1</div>
+ <div id="obj2" role="menuitem">obj2</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/menubar-aria-expanded-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/menubar-aria-expanded-false.html
new file mode 100644
index 00000000000..4ab7c9590ca
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/menubar-aria-expanded-false.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role menubar; inherited supported state or property "aria-expanded" value
+ of "false"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="menubar" aria-expanded="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/menubar-aria-expanded-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/menubar-aria-expanded-true.html
new file mode 100644
index 00000000000..f7b26995fa4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/menubar-aria-expanded-true.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role menubar; inherited supported state or property "aria-expanded" value
+ of "true"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="menubar" aria-expanded="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/menubar-aria-expanded-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/menubar-aria-expanded-undefined.html
new file mode 100644
index 00000000000..431f843ba4a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/menubar-aria-expanded-undefined.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role menubar; inherited supported state or property "aria-expanded" value
+ of "undefined"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="menubar" aria-expanded="undefined">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/menuitemradio-aria-checked-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/menuitemradio-aria-checked-false.html
new file mode 100644
index 00000000000..5691a55c045
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/menuitemradio-aria-checked-false.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role menuitemradio; inherited supported state or property "aria-checked"
+ value of "false"
+ </title>
+ </head>
+ <body>
+ <div role="menu">
+ <div id="test" role="menuitemradio" aria-checked="false">Placeholder content</div>
+ <div id="obj1" role="menuitemradio" aria-checked="false">obj1</div>
+ <div id="obj2" role="menuitemradio" aria-checked="false">obj2</div>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/menuitemradio-aria-checked-mixed.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/menuitemradio-aria-checked-mixed.html
new file mode 100644
index 00000000000..d517d22a3e1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/menuitemradio-aria-checked-mixed.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role menuitemradio; inherited supported state or property "aria-checked"
+ value of "mixed"
+ </title>
+ </head>
+ <body>
+ <div role="menu">
+ <div id="test" tabindex="0" role="menuitemradio" aria-checked="mixed">Placeholder content</div>
+ <div id="obj1" role="menuitemradio" aria-checked="false">obj1</div>
+ <div id="obj2" role="menuitemradio" aria-checked="false">obj2</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/menuitemradio-aria-checked-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/menuitemradio-aria-checked-true.html
new file mode 100644
index 00000000000..0d364f8ccb0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/menuitemradio-aria-checked-true.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role menuitemradio; inherited supported state or property "aria-checked"
+ value of "true"
+ </title>
+ </head>
+ <body>
+ <div role="menu">
+ <div id="test" role="menuitemradio" aria-checked="true">Placeholder content</div>
+ <div id="obj1" role="menuitemradio" aria-checked="false">obj1</div>
+ <div id="obj2" role="menuitemradio" aria-checked="false">obj2</div>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/menuitemradio-aria-checked-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/menuitemradio-aria-checked-undefined.html
new file mode 100644
index 00000000000..bb6aa7854f4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/menuitemradio-aria-checked-undefined.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role menuitemradio; inherited supported state or property "aria-checked"
+ value of "undefined"
+ </title>
+ </head>
+ <body>
+ <div role="menu">
+ <div id="test" role="menuitemradio" aria-checked="undefined">Placeholder content</div>
+ <div id="obj1" role="menuitemradio" aria-checked="false">obj1</div>
+ <div id="obj2" role="menuitemradio" aria-checked="false">obj2</div>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/navigation-aria-expanded-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/navigation-aria-expanded-false.html
new file mode 100644
index 00000000000..5769da1789e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/navigation-aria-expanded-false.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role navigation; inherited supported state or property "aria-expanded"
+ value of "false"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="navigation" aria-expanded="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/navigation-aria-expanded-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/navigation-aria-expanded-true.html
new file mode 100644
index 00000000000..01594dc77e4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/navigation-aria-expanded-true.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role navigation; inherited supported state or property "aria-expanded"
+ value of "true"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="navigation" aria-expanded="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/navigation-aria-expanded-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/navigation-aria-expanded-undefined.html
new file mode 100644
index 00000000000..9e6f4c630f6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/navigation-aria-expanded-undefined.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role navigation; inherited supported state or property "aria-expanded"
+ value of "undefined"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="navigation" aria-expanded="undefined">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/note-aria-expanded-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/note-aria-expanded-false.html
new file mode 100644
index 00000000000..02065e732cc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/note-aria-expanded-false.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role note; inherited supported state or property "aria-expanded" value
+ of "false"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="note" aria-expanded="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/note-aria-expanded-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/note-aria-expanded-true.html
new file mode 100644
index 00000000000..d1e0f8c5956
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/note-aria-expanded-true.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role note; inherited supported state or property "aria-expanded" value
+ of "true"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="note" aria-expanded="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/note-aria-expanded-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/note-aria-expanded-undefined.html
new file mode 100644
index 00000000000..1e902fb253d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/note-aria-expanded-undefined.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role note; inherited supported state or property "aria-expanded" value
+ of "undefined"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="note" aria-expanded="undefined">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/progressbar-aria-valuemax-1.1.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/progressbar-aria-valuemax-1.1.html
new file mode 100644
index 00000000000..2179446478c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/progressbar-aria-valuemax-1.1.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role progressbar; inherited supported state or property "aria-valuemax"
+ value of "1.1"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="progressbar" aria-valuemax="1.1">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/progressbar-aria-valuemin-1.1.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/progressbar-aria-valuemin-1.1.html
new file mode 100644
index 00000000000..4fca777ec9e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/progressbar-aria-valuemin-1.1.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role progressbar; inherited supported state or property "aria-valuemin"
+ value of "1.1"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="progressbar" aria-valuemin="1.1">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/progressbar-aria-valuenow-1.1.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/progressbar-aria-valuenow-1.1.html
new file mode 100644
index 00000000000..751d47ee337
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/progressbar-aria-valuenow-1.1.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role progressbar; inherited supported state or property "aria-valuenow"
+ value of "1.1"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="progressbar" aria-valuenow="1.1">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/progressbar-aria-valuetext-Test-string-value.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/progressbar-aria-valuetext-Test-string-value.html
new file mode 100644
index 00000000000..bbd0e1fd964
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/progressbar-aria-valuetext-Test-string-value.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role progressbar; inherited supported state or property "aria-valuetext"
+ value of "Test string value"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="progressbar" aria-valuetext="Test string value">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/radio-aria-checked-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/radio-aria-checked-false.html
new file mode 100644
index 00000000000..b00d45c0980
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/radio-aria-checked-false.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role radio; inherited supported state or property "aria-checked" value
+ of "false"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="radio" aria-checked="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/radio-aria-checked-mixed.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/radio-aria-checked-mixed.html
new file mode 100644
index 00000000000..8a958373063
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/radio-aria-checked-mixed.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role radio; inherited supported state or property "aria-checked" value
+ of "mixed"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="radio" aria-checked="mixed">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/radio-aria-checked-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/radio-aria-checked-true.html
new file mode 100644
index 00000000000..61e816268a3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/radio-aria-checked-true.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role radio; inherited supported state or property "aria-checked" value
+ of "true"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="radio" aria-checked="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/radiogroup-aria-expanded-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/radiogroup-aria-expanded-false.html
new file mode 100644
index 00000000000..9d5680f32c4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/radiogroup-aria-expanded-false.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role radiogroup; inherited supported state or property "aria-expanded"
+ value of "false"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="radiogroup" aria-expanded="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/radiogroup-aria-expanded-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/radiogroup-aria-expanded-true.html
new file mode 100644
index 00000000000..f6f9e137973
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/radiogroup-aria-expanded-true.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role radiogroup; inherited supported state or property "aria-expanded"
+ value of "true"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="radiogroup" aria-expanded="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/radiogroup-aria-expanded-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/radiogroup-aria-expanded-undefined.html
new file mode 100644
index 00000000000..0532ea592eb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/radiogroup-aria-expanded-undefined.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role radiogroup; inherited supported state or property "aria-expanded"
+ value of "undefined"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="radiogroup" aria-expanded="undefined">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/region-aria-expanded-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/region-aria-expanded-false.html
new file mode 100644
index 00000000000..00b6052c2e9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/region-aria-expanded-false.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role region; inherited supported state or property "aria-expanded" value
+ of "false"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="region" aria-expanded="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/region-aria-expanded-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/region-aria-expanded-true.html
new file mode 100644
index 00000000000..2fdd56f4b76
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/region-aria-expanded-true.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role region; inherited supported state or property "aria-expanded" value
+ of "true"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="region" aria-expanded="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/region-aria-expanded-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/region-aria-expanded-undefined.html
new file mode 100644
index 00000000000..22bb8379902
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/region-aria-expanded-undefined.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role region; inherited supported state or property "aria-expanded" value
+ of "undefined"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="region" aria-expanded="undefined">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/row-aria-activedescendant-obj1.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/row-aria-activedescendant-obj1.html
new file mode 100644
index 00000000000..a24595a1049
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/row-aria-activedescendant-obj1.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role row; inherited supported state or property "aria-activedescendant"
+ value of "obj1"
+ </title>
+ </head>
+ <body>
+ <div role="grid">
+ <div id="test" role="row" tabindex="0" aria-activedescendant="obj1">
+ <div id="obj1" role="gridcell">obj1</div>
+ <div id="obj2" role="gridcell">obj2</div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/rowgroup-aria-activedescendant-obj1.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/rowgroup-aria-activedescendant-obj1.html
new file mode 100644
index 00000000000..b0ff8999302
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/rowgroup-aria-activedescendant-obj1.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role rowgroup; inherited supported state or property "aria-activedescendant"
+ value of "obj1"
+ </title>
+ </head>
+ <body>
+ <div role="grid">
+ <div id="test" tabindex="0" role="rowgroup" aria-activedescendant="obj1">
+ <div id="obj1" role="row">
+ <div role="gridcell">r1c1</div>
+ <div role="gridcell">r1c2</div>
+ </div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/rowheader-aria-expanded-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/rowheader-aria-expanded-false.html
new file mode 100644
index 00000000000..710d779f519
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/rowheader-aria-expanded-false.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role rowheader; inherited supported state or property "aria-expanded" value
+ of "false"
+ </title>
+ </head>
+ <body>
+ <div role="grid">
+ <div role="row">
+ <span id="test" role="rowheader" aria-expanded="false">Placeholder content</span>
+ <span role="gridcell" id="obj1">obj1</span>
+ <span role="gridcell" id="obj2">obj2</span>
+ </div>
+ <div role="row">
+ <span role="rowheader">header cell 2</span>
+ <span role="gridcell">obj1</span>
+ <span role="gridcell">obj2</span>
+ </div>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/rowheader-aria-expanded-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/rowheader-aria-expanded-true.html
new file mode 100644
index 00000000000..ac0e55a7464
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/rowheader-aria-expanded-true.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role rowheader; inherited supported state or property "aria-expanded" value
+ of "true"
+ </title>
+ </head>
+ <body>
+ <div role="grid">
+ <div role="row">
+ <span id="test" role="rowheader" aria-expanded="true">Placeholder content</span>
+ <span role="gridcell" id="obj1">obj1</span>
+ <span role="gridcell" id="obj2">obj2</span>
+ </div>
+ <div role="row">
+ <span role="rowheader">header cell 2</span>
+ <span role="gridcell">obj1</span>
+ <span role="gridcell">obj2</span>
+ </div>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/rowheader-aria-expanded-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/rowheader-aria-expanded-undefined.html
new file mode 100644
index 00000000000..13d7bfc6ab4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/rowheader-aria-expanded-undefined.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role rowheader; inherited supported state or property "aria-expanded" value
+ of "undefined"
+ </title>
+ </head>
+ <body>
+ <div role="grid">
+ <div role="row">
+ <span id="test" role="rowheader" aria-expanded="undefined">Placeholder content</span>
+ <span role="gridcell" id="obj1">obj1</span>
+ <span role="gridcell" id="obj2">obj2</span>
+ </div>
+ <div role="row">
+ <span role="rowheader">header cell 2</span>
+ <span role="gridcell">obj1</span>
+ <span role="gridcell">obj2</span>
+ </div>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/rowheader-aria-readonly-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/rowheader-aria-readonly-false.html
new file mode 100644
index 00000000000..009a72d766a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/rowheader-aria-readonly-false.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role rowheader; inherited supported state or property "aria-readonly" value
+ of "false"
+ </title>
+ </head>
+ <body>
+ <div role="grid">
+ <div role="row">
+ <span id="test" role="rowheader" aria-readonly="false">Placeholder content</span>
+ <span role="gridcell" id="obj1">obj1</span>
+ <span role="gridcell" id="obj2">obj2</span>
+ </div>
+ <div role="row">
+ <span role="rowheader">header cell 2</span>
+ <span role="gridcell">obj1</span>
+ <span role="gridcell">obj2</span>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/rowheader-aria-readonly-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/rowheader-aria-readonly-true.html
new file mode 100644
index 00000000000..3061cc5f9e7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/rowheader-aria-readonly-true.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role rowheader; inherited supported state or property "aria-readonly" value
+ of "true"
+ </title>
+ </head>
+ <body>
+ <div role="grid">
+ <div role="row">
+ <span id="test" role="rowheader" aria-readonly="true">Placeholder content</span>
+ <span role="gridcell" id="obj1">obj1</span>
+ <span role="gridcell" id="obj2">obj2</span>
+ </div>
+ <div role="row">
+ <span role="rowheader">header cell 2</span>
+ <span role="gridcell">obj1</span>
+ <span role="gridcell">obj2</span>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/rowheader-aria-required-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/rowheader-aria-required-false.html
new file mode 100644
index 00000000000..cdcba5973e1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/rowheader-aria-required-false.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role rowheader; inherited supported state or property "aria-required" value
+ of "false"
+ </title>
+ </head>
+ <body>
+ <div role="grid">
+ <div role="row">
+ <span id="test" role="rowheader" aria-required="false">Placeholder content</span>
+ <span role="gridcell" id="obj1">obj1</span>
+ <span role="gridcell" id="obj2">obj2</span>
+ </div>
+ <div role="row">
+ <span role="rowheader">header cell 2</span>
+ <span role="gridcell">obj1</span>
+ <span role="gridcell">obj2</span>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/rowheader-aria-required-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/rowheader-aria-required-true.html
new file mode 100644
index 00000000000..7ad7b8e99a8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/rowheader-aria-required-true.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role rowheader; inherited supported state or property "aria-required" value
+ of "true"
+ </title>
+ </head>
+ <body>
+ <div role="grid">
+ <div role="row">
+ <span id="test" role="rowheader" aria-required="true">Placeholder content</span>
+ <span role="gridcell" id="obj1">obj1</span>
+ <span role="gridcell" id="obj2">obj2</span>
+ </div>
+ <div role="row">
+ <span role="rowheader">header cell 2</span>
+ <span role="gridcell">obj1</span>
+ <span role="gridcell">obj2</span>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/rowheader-aria-selected-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/rowheader-aria-selected-false.html
new file mode 100644
index 00000000000..17c23801d5d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/rowheader-aria-selected-false.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role rowheader; inherited supported state or property "aria-selected" value
+ of "false"
+ </title>
+ </head>
+ <body>
+ <div role="grid">
+ <div role="row">
+ <span id="test" role="rowheader" aria-selected="false">Placeholder content</span>
+ <span role="gridcell" id="obj1">obj1</span>
+ <span role="gridcell" id="obj2">obj2</span>
+ </div>
+ <div role="row">
+ <span role="rowheader">header cell 2</span>
+ <span role="gridcell">obj1</span>
+ <span role="gridcell">obj2</span>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/rowheader-aria-selected-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/rowheader-aria-selected-true.html
new file mode 100644
index 00000000000..03e6d47980d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/rowheader-aria-selected-true.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role rowheader; inherited supported state or property "aria-selected" value
+ of "true"
+ </title>
+ </head>
+ <body>
+ <div role="grid">
+ <div role="row">
+ <span id="test" role="rowheader" aria-selected="true">Placeholder content</span>
+ <span role="gridcell" id="obj1">obj1</span>
+ <span role="gridcell" id="obj2">obj2</span>
+ </div>
+ <div role="row">
+ <span role="rowheader">header cell 2</span>
+ <span role="gridcell">obj1</span>
+ <span role="gridcell">obj2</span>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/rowheader-aria-selected-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/rowheader-aria-selected-undefined.html
new file mode 100644
index 00000000000..439abbb05a6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/rowheader-aria-selected-undefined.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role rowheader; inherited supported state or property "aria-selected" value
+ of "undefined"
+ </title>
+ </head>
+ <body>
+ <div role="grid">
+ <div role="row">
+ <span id="test" role="rowheader" aria-selected="undefined" tabindex="0">Placeholder content</span>
+ <span role="gridcell" id="obj1">obj1</span>
+ <span role="gridcell" id="obj2">obj2</span>
+ </div>
+ <div role="row">
+ <span role="rowheader">header cell 2</span>
+ <span role="gridcell">obj1</span>
+ <span role="gridcell">obj2</span>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/search-aria-expanded-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/search-aria-expanded-false.html
new file mode 100644
index 00000000000..2bcae837fd7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/search-aria-expanded-false.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role search; inherited supported state or property "aria-expanded" value
+ of "false"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="search" aria-expanded="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/search-aria-expanded-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/search-aria-expanded-true.html
new file mode 100644
index 00000000000..16885b8d15a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/search-aria-expanded-true.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role search; inherited supported state or property "aria-expanded" value
+ of "true"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="search" aria-expanded="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/search-aria-expanded-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/search-aria-expanded-undefined.html
new file mode 100644
index 00000000000..0e39ca5cf69
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/search-aria-expanded-undefined.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role search; inherited supported state or property "aria-expanded" value
+ of "undefined"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="search" aria-expanded="undefined">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/status-aria-expanded-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/status-aria-expanded-false.html
new file mode 100644
index 00000000000..7dcf0f9acf7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/status-aria-expanded-false.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role status; inherited supported state or property "aria-expanded" value
+ of "false"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="status" aria-expanded="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/status-aria-expanded-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/status-aria-expanded-true.html
new file mode 100644
index 00000000000..05314e41f4b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/status-aria-expanded-true.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role status; inherited supported state or property "aria-expanded" value
+ of "true"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="status" aria-expanded="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/status-aria-expanded-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/status-aria-expanded-undefined.html
new file mode 100644
index 00000000000..18ffebc08af
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/status-aria-expanded-undefined.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role status; inherited supported state or property "aria-expanded" value
+ of "undefined"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="status" aria-expanded="undefined">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tab-aria-expanded-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tab-aria-expanded-false.html
new file mode 100644
index 00000000000..c5a83f98a34
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tab-aria-expanded-false.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role tab; inherited supported state or property "aria-expanded" value of
+ "false"
+ </title>
+ </head>
+ <body>
+ <div role="tablist">
+ <div id="test" role="tab" aria-expanded="false">Placeholder content</div>
+ </div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tab-aria-expanded-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tab-aria-expanded-true.html
new file mode 100644
index 00000000000..43fa4f19c8c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tab-aria-expanded-true.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role tab; inherited supported state or property "aria-expanded" value of
+ "true"
+ </title>
+ </head>
+ <body>
+ <div role="tablist">
+ <div id="test" role="tab" aria-expanded="true">Placeholder content</div>
+ </div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tab-aria-expanded-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tab-aria-expanded-undefined.html
new file mode 100644
index 00000000000..abd5917a311
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tab-aria-expanded-undefined.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role tab; inherited supported state or property "aria-expanded" value of
+ "undefined"
+ </title>
+ </head>
+ <body>
+ <div role="tablist">
+ <div id="test" role="tab" aria-expanded="undefined">Placeholder content</div>
+ </div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tablist-aria-activedescendant-obj1.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tablist-aria-activedescendant-obj1.html
new file mode 100644
index 00000000000..ffbe638b073
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tablist-aria-activedescendant-obj1.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role tablist; inherited supported state or property "aria-activedescendant"
+ value of "obj1"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="tablist" tabindex="0" aria-activedescendant="obj1">
+ <div id="obj1" role="tab">obj1</div>
+ </div>
+
+ <div id="obj2">obj2</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tablist-aria-expanded-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tablist-aria-expanded-false.html
new file mode 100644
index 00000000000..0966d5ba6e7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tablist-aria-expanded-false.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role tablist; inherited supported state or property "aria-expanded" value
+ of "false"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="tablist" aria-expanded="false">
+ <div id="obj1" role="tab">obj1</div>
+ </div>
+ <div id="obj2">obj2</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tablist-aria-expanded-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tablist-aria-expanded-true.html
new file mode 100644
index 00000000000..7ae72f3a6c7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tablist-aria-expanded-true.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role tablist; inherited supported state or property "aria-expanded" value
+ of "true"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="tablist" aria-expanded="true">
+ <div id="obj1" role="tab">obj1</div>
+ </div>
+ <div id="obj2">obj2</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tablist-aria-expanded-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tablist-aria-expanded-undefined.html
new file mode 100644
index 00000000000..24fb428df21
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tablist-aria-expanded-undefined.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role tablist; inherited supported state or property "aria-expanded" value
+ of "undefined"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="tablist" aria-expanded="undefined">
+ <div id="obj1" role="tab">obj1</div>
+ </div>
+ <div id="obj2">obj2</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tabpanel-aria-expanded-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tabpanel-aria-expanded-false.html
new file mode 100644
index 00000000000..b431a4a6b56
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tabpanel-aria-expanded-false.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role tabpanel; inherited supported state or property "aria-expanded" value
+ of "false"
+ </title>
+ </head>
+ <body>
+ <div role="tablist">
+ <div id="obj1" role="tab">obj1</div>
+ <div id="obj2" role="tab">obj2</div>
+ </div>
+ <div id="test" role="tabpanel" aria-expanded="false">Placeholder content</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tabpanel-aria-expanded-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tabpanel-aria-expanded-true.html
new file mode 100644
index 00000000000..dd718b0e703
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tabpanel-aria-expanded-true.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role tabpanel; inherited supported state or property "aria-expanded" value
+ of "true"
+ </title>
+ </head>
+ <body>
+ <div role="tablist">
+ <div id="obj1" role="tab">obj1</div>
+ <div id="obj2" role="tab">obj2</div>
+ </div>
+ <div id="test" role="tabpanel" aria-expanded="true">Placeholder content</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tabpanel-aria-expanded-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tabpanel-aria-expanded-undefined.html
new file mode 100644
index 00000000000..b87facc44a0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tabpanel-aria-expanded-undefined.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role tabpanel; inherited supported state or property "aria-expanded" value
+ of "undefined"
+ </title>
+ </head>
+ <body>
+ <div role="tablist">
+ <div id="obj1" role="tab">obj1</div>
+ <div id="obj2" role="tab">obj2</div>
+ </div>
+ <div id="test" role="tabpanel" aria-expanded="undefined">Placeholder content</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/timer-aria-expanded-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/timer-aria-expanded-false.html
new file mode 100644
index 00000000000..c0f20820825
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/timer-aria-expanded-false.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role timer; inherited supported state or property "aria-expanded" value
+ of "false"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="timer" aria-expanded="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/timer-aria-expanded-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/timer-aria-expanded-true.html
new file mode 100644
index 00000000000..40d571748a3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/timer-aria-expanded-true.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role timer; inherited supported state or property "aria-expanded" value
+ of "true"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="timer" aria-expanded="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/timer-aria-expanded-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/timer-aria-expanded-undefined.html
new file mode 100644
index 00000000000..90260acbcd3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/timer-aria-expanded-undefined.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role timer; inherited supported state or property "aria-expanded" value
+ of "undefined"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="timer" aria-expanded="undefined">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/toolbar-aria-activedescendant-obj1.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/toolbar-aria-activedescendant-obj1.html
new file mode 100644
index 00000000000..ccc0c9f8480
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/toolbar-aria-activedescendant-obj1.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role toolbar; inherited supported state or property "aria-activedescendant"
+ value of "obj1"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="toolbar" tabindex="0" aria-activedescendant="obj1">
+ <div id="obj1" role="button">obj1</div>
+ <div id="obj2" role="button">obj2</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/toolbar-aria-expanded-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/toolbar-aria-expanded-false.html
new file mode 100644
index 00000000000..aff3beeb1b2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/toolbar-aria-expanded-false.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role toolbar; inherited supported state or property "aria-expanded" value
+ of "false"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="toolbar" aria-expanded="false">
+ <div id="obj1" role="button">obj1</div>
+ <div id="obj2" role="button">obj2</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/toolbar-aria-expanded-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/toolbar-aria-expanded-true.html
new file mode 100644
index 00000000000..fa949d2bf39
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/toolbar-aria-expanded-true.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role toolbar; inherited supported state or property "aria-expanded" value
+ of "true"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="toolbar" aria-expanded="true">
+ <div id="obj1" role="button">obj1</div>
+ <div id="obj2" role="button">obj2</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/toolbar-aria-expanded-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/toolbar-aria-expanded-undefined.html
new file mode 100644
index 00000000000..f71027fbeeb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/toolbar-aria-expanded-undefined.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role toolbar; inherited supported state or property "aria-expanded" value
+ of "undefined"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="toolbar" aria-expanded="undefined">
+ <div id="obj1" role="button">obj1</div>
+ <div id="obj2" role="button">obj2</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tooltip-aria-expanded-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tooltip-aria-expanded-false.html
new file mode 100644
index 00000000000..f867da4269c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tooltip-aria-expanded-false.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role tooltip; inherited supported state or property "aria-expanded" value
+ of "false"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="tooltip" aria-expanded="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tooltip-aria-expanded-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tooltip-aria-expanded-true.html
new file mode 100644
index 00000000000..1a52619fe21
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tooltip-aria-expanded-true.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role tooltip; inherited supported state or property "aria-expanded" value
+ of "true"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="tooltip" aria-expanded="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tooltip-aria-expanded-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tooltip-aria-expanded-undefined.html
new file mode 100644
index 00000000000..8b24ad9ed87
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tooltip-aria-expanded-undefined.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role tooltip; inherited supported state or property "aria-expanded" value
+ of "undefined"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="tooltip" aria-expanded="undefined">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tree-aria-activedescendant-obj1.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tree-aria-activedescendant-obj1.html
new file mode 100644
index 00000000000..c2d0d833915
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tree-aria-activedescendant-obj1.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role tree; inherited supported state or property "aria-activedescendant"
+ value of "obj1"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="tree" aria-activedescendant="obj1" tabindex="0">
+ <div id="obj1" role="treeitem">obj1</div>
+ <div id="obj2" role="treeitem">obj2</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tree-aria-expanded-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tree-aria-expanded-false.html
new file mode 100644
index 00000000000..c13f331fd9d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tree-aria-expanded-false.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role tree; inherited supported state or property "aria-expanded" value
+ of "false"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="tree" aria-expanded="false">
+ <div role="treeitem" id="obj1">obj1</div>
+ <div role="treeitem" id="obj2">obj2</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tree-aria-expanded-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tree-aria-expanded-true.html
new file mode 100644
index 00000000000..a2545ef32c1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tree-aria-expanded-true.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role tree; inherited supported state or property "aria-expanded" value
+ of "true"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="tree" aria-expanded="true">
+ <div role="treeitem" id="obj1">obj1</div>
+ <div role="treeitem" id="obj2">obj2</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tree-aria-expanded-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tree-aria-expanded-undefined.html
new file mode 100644
index 00000000000..5379f703957
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/tree-aria-expanded-undefined.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role tree; inherited supported state or property "aria-expanded" value
+ of "undefined"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="tree" aria-expanded="undefined">
+ <div role="treeitem" id="obj1">obj1</div>
+ <div role="treeitem" id="obj2">obj2</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treegrid-aria-activedescendant-obj1.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treegrid-aria-activedescendant-obj1.html
new file mode 100644
index 00000000000..bce72b08a0d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treegrid-aria-activedescendant-obj1.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role treegrid; inherited supported state or property "aria-activedescendant"
+ value of "obj1"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="treegrid" aria-activedescendant="obj1" tabindex="0">
+ <div role="row">
+ <div id="obj1" role="gridcell">obj1</div>
+ <div id="obj2" role="gridcell">obj2</div>
+ </div>
+ <div role="row">
+ <div id="obj3" role="gridcell">obj3</div>
+ <div id="obj4" role="gridcell">obj4</div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treegrid-aria-expanded-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treegrid-aria-expanded-false.html
new file mode 100644
index 00000000000..7b5d78c98e8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treegrid-aria-expanded-false.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role treegrid; inherited supported state or property "aria-expanded" value
+ of "false"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="treegrid" aria-expanded="false">
+ <div role="row">
+ <div id="obj1" role="gridcell">obj1</div>
+ <div id="obj2" role="gridcell">obj2</div>
+ </div>
+ <div role="row">
+ <div id="obj3" role="gridcell">obj3</div>
+ <div id="obj4" role="gridcell">obj4</div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treegrid-aria-expanded-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treegrid-aria-expanded-true.html
new file mode 100644
index 00000000000..c06b957a01c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treegrid-aria-expanded-true.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role treegrid; inherited supported state or property "aria-expanded" value
+ of "true"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="treegrid" aria-expanded="true">
+ <div role="row">
+ <div id="obj1" role="gridcell">obj1</div>
+ <div id="obj2" role="gridcell">obj2</div>
+ </div>
+ <div role="row">
+ <div id="obj3" role="gridcell">obj3</div>
+ <div id="obj4" role="gridcell">obj4</div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treegrid-aria-expanded-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treegrid-aria-expanded-undefined.html
new file mode 100644
index 00000000000..ef2232bf895
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treegrid-aria-expanded-undefined.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role treegrid; inherited supported state or property "aria-expanded" value
+ of "undefined"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="treegrid" aria-expanded="undefined">
+ <div role="row">
+ <div id="obj1" role="gridcell">obj1</div>
+ <div id="obj2" role="gridcell">obj2</div>
+ </div>
+ <div role="row">
+ <div id="obj3" role="gridcell">obj3</div>
+ <div id="obj4" role="gridcell">obj4</div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treegrid-aria-level-1.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treegrid-aria-level-1.html
new file mode 100644
index 00000000000..1a3a3ef0c67
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treegrid-aria-level-1.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role treegrid; inherited supported state or property "aria-level" value
+ of "1"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="treegrid" aria-level="1" tabindex="0">
+ <div role="row">
+ <div role="gridcell" tabindex="-1" >Placeholder content</div>
+ <div role="gridcell" id="obj1">obj1</div>
+ <div role="gridcell" id="obj2">obj2</div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treegrid-aria-multiselectable-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treegrid-aria-multiselectable-false.html
new file mode 100644
index 00000000000..ac6b7662de5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treegrid-aria-multiselectable-false.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role treegrid; inherited supported state or property "aria-multiselectable"
+ value of "false"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="treegrid" aria-multiselectable="false">
+ <div role="row">
+ <div role="gridcell">Placeholder content</div>
+ <div role="gridcell" id="obj1">obj1</div>
+ <div role="gridcell" id="obj2">obj2</div>
+ </div>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treegrid-aria-multiselectable-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treegrid-aria-multiselectable-true.html
new file mode 100644
index 00000000000..ee7696ea5f1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treegrid-aria-multiselectable-true.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role treegrid; inherited supported state or property "aria-multiselectable"
+ value of "true"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="treegrid" aria-multiselectable="true">
+ <div role="row">
+ <div role="gridcell">Placeholder content</div>
+ <div role="gridcell" id="obj1">obj1</div>
+ <div role="gridcell" id="obj2">obj2</div>
+ </div>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treegrid-aria-readonly-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treegrid-aria-readonly-false.html
new file mode 100644
index 00000000000..a8f5e6e86d0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treegrid-aria-readonly-false.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role treegrid; inherited supported state or property "aria-readonly" value
+ of "false"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="treegrid" aria-readonly="false">
+ <div role="row">
+ <div role="gridcell">Placeholder content</div>
+ <div role="gridcell" id="obj1">obj1</div>
+ <div role="gridcell" id="obj2">obj2</div>
+ </div>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treegrid-aria-readonly-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treegrid-aria-readonly-true.html
new file mode 100644
index 00000000000..1ab9c58433e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treegrid-aria-readonly-true.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role treegrid; inherited supported state or property "aria-readonly" value
+ of "true"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="treegrid" aria-readonly="true">
+ <div role="row">
+ <div role="gridcell">Placeholder content</div>
+ <div role="gridcell" id="obj1">obj1</div>
+ <div role="gridcell" id="obj2">obj2</div>
+ </div>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treegrid-aria-required-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treegrid-aria-required-false.html
new file mode 100644
index 00000000000..702655bd458
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treegrid-aria-required-false.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role treegrid; inherited supported state or property "aria-required" value
+ of "false"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="treegrid" aria-required="false">
+ <div role="row">
+ <div role="gridcell">Placeholder content</div>
+ <div role="gridcell" id="obj1">obj1</div>
+ <div role="gridcell" id="obj2">obj2</div>
+ </div>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treegrid-aria-required-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treegrid-aria-required-true.html
new file mode 100644
index 00000000000..09c0bb6d9f4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treegrid-aria-required-true.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role treegrid; inherited supported state or property "aria-required" value
+ of "true"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="treegrid" aria-required="true">
+ <div role="row">
+ <div role="gridcell">Placeholder content</div>
+ <div role="gridcell" id="obj1">obj1</div>
+ <div role="gridcell" id="obj2">obj2</div>
+ </div>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treeitem-aria-checked-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treeitem-aria-checked-false.html
new file mode 100644
index 00000000000..592cd974e90
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treeitem-aria-checked-false.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role treeitem; inherited supported state or property "aria-checked" value
+ of "false"
+ </title>
+ </head>
+ <body>
+ <div role="tree">
+ <div id="test" role="treeitem" aria-checked="false">Placeholder content</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treeitem-aria-checked-mixed.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treeitem-aria-checked-mixed.html
new file mode 100644
index 00000000000..6a29dfff751
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treeitem-aria-checked-mixed.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role treeitem; inherited supported state or property "aria-checked" value
+ of "mixed"
+ </title>
+ </head>
+ <body>
+ <div role="tree">
+ <div id="test" role="treeitem" aria-checked="mixed">Placeholder content</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treeitem-aria-checked-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treeitem-aria-checked-true.html
new file mode 100644
index 00000000000..3745c865873
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treeitem-aria-checked-true.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role treeitem; inherited supported state or property "aria-checked" value
+ of "true"
+ </title>
+ </head>
+ <body>
+ <div role="tree">
+ <div id="test" role="treeitem" aria-checked="true">Placeholder content</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treeitem-aria-checked-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treeitem-aria-checked-undefined.html
new file mode 100644
index 00000000000..ede64afbaa5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treeitem-aria-checked-undefined.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role treeitem; inherited supported state or property "aria-checked" value
+ of "undefined"
+ </title>
+ </head>
+ <body>
+ <div role="tree">
+ <div id="test" role="treeitem" aria-checked="undefined">Placeholder content</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treeitem-aria-level-1.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treeitem-aria-level-1.html
new file mode 100644
index 00000000000..adc7b23ccc0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treeitem-aria-level-1.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role treeitem; inherited supported state or property "aria-level" value
+ of "1"
+ </title>
+ </head>
+ <body>
+ <div role="tree" tabindex="0">
+ <div id="test" role="treeitem" aria-level="1">Placeholder content</div>
+ <div id="obj1" role="treeitem">obj1</div>
+ <div id="obj2" role="treeitem">obj2</div>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treeitem-aria-posinset-1.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treeitem-aria-posinset-1.html
new file mode 100644
index 00000000000..feb152c5a98
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treeitem-aria-posinset-1.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role treeitem; inherited supported state or property "aria-posinset" value
+ of "1"
+ </title>
+ </head>
+ <body>
+ <div role="tree" tabindex="0">
+ <div id="test" role="treeitem" aria-posinset="1">Placeholder content</div>
+ <div id="obj1" role="treeitem">obj1</div>
+ <div id="obj2" role="treeitem">obj2</div>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treeitem-aria-selected-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treeitem-aria-selected-false.html
new file mode 100644
index 00000000000..bce9733b762
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treeitem-aria-selected-false.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role treeitem; inherited supported state or property "aria-selected" value
+ of "false"
+ </title>
+ </head>
+ <body>
+ <div role="tree" tabindex="0">
+ <div id="test" role="treeitem" aria-selected="false">Placeholder content</div>
+ <div id="obj1" role="treeitem">obj1</div>
+ <div id="obj2" role="treeitem">obj2</div>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treeitem-aria-selected-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treeitem-aria-selected-true.html
new file mode 100644
index 00000000000..11e529a464b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treeitem-aria-selected-true.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role treeitem; inherited supported state or property "aria-selected" value
+ of "true"
+ </title>
+ </head>
+ <body>
+ <div role="tree" tabindex="0">
+ <div id="test" role="treeitem" aria-selected="true">Placeholder content</div>
+ <div id="obj1" role="treeitem">obj1</div>
+ <div id="obj2" role="treeitem">obj2</div>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treeitem-aria-selected-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treeitem-aria-selected-undefined.html
new file mode 100644
index 00000000000..d24014b0a48
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treeitem-aria-selected-undefined.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role treeitem; inherited supported state or property "aria-selected" value
+ of "undefined"
+ </title>
+ </head>
+ <body>
+ <div role="tree" tabindex="0">
+ <div id="test" role="treeitem" aria-selected="undefined">Placeholder content</div>
+ <div id="obj1" role="treeitem">obj1</div>
+ <div id="obj2" role="treeitem">obj2</div>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treeitem-aria-setsize-1.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treeitem-aria-setsize-1.html
new file mode 100644
index 00000000000..57005077d1b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported-inherited/treeitem-aria-setsize-1.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role treeitem; inherited supported state or property "aria-setsize" value
+ of "1"
+ </title>
+ </head>
+ <body>
+ <div role="tree">
+ <div id="test" role="treeitem" aria-posinset="1" aria-setsize="1">Placeholder content</div>
+ </div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-button-aria-expanded-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-button-aria-expanded-false.html
new file mode 100644
index 00000000000..81e7807e179
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-button-aria-expanded-false.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role button; supported state or property "aria-expanded" value of "false"</title>
+ </head>
+ <body>
+ <div id="test" role="button" aria-expanded="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-button-aria-expanded-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-button-aria-expanded-true.html
new file mode 100644
index 00000000000..6fd1ed8b6b6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-button-aria-expanded-true.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role button; supported state or property "aria-expanded" value of "true"</title>
+ </head>
+ <body>
+ <div id="test" role="button" aria-expanded="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-button-aria-expanded-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-button-aria-expanded-undefined.html
new file mode 100644
index 00000000000..b51b006b977
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-button-aria-expanded-undefined.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role button; supported state or property "aria-expanded" value of "undefined"</title>
+ </head>
+ <body>
+ <div id="test" role="button" aria-expanded="undefined">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-button-aria-pressed-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-button-aria-pressed-false.html
new file mode 100644
index 00000000000..c7aeae0a0a8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-button-aria-pressed-false.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role button; supported state or property "aria-pressed" value of "false"</title>
+ </head>
+ <body>
+ <div id="test" role="button" aria-pressed="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-button-aria-pressed-mixed.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-button-aria-pressed-mixed.html
new file mode 100644
index 00000000000..510846d6390
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-button-aria-pressed-mixed.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role button; supported state or property "aria-pressed" value of "mixed"</title>
+ </head>
+ <body>
+ <div id="test" role="button" aria-pressed="mixed">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-button-aria-pressed-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-button-aria-pressed-true.html
new file mode 100644
index 00000000000..f99a0e1f5e9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-button-aria-pressed-true.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role button; supported state or property "aria-pressed" value of "true"</title>
+ </head>
+ <body>
+ <div id="test" role="button" aria-pressed="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-button-aria-pressed-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-button-aria-pressed-undefined.html
new file mode 100644
index 00000000000..8591e12f073
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-button-aria-pressed-undefined.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role button; supported state or property "aria-pressed" value of "undefined"</title>
+ </head>
+ <body>
+ <div id="test" role="button" aria-pressed="undefined">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-columnheader-aria-sort-ascending.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-columnheader-aria-sort-ascending.html
new file mode 100644
index 00000000000..53fc1447962
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-columnheader-aria-sort-ascending.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role columnheader; supported state or property "aria-sort" value of "ascending"</title>
+ </head>
+ <body>
+ <div role="grid">
+ <div role="row">
+ <span id="test" role="columnheader" aria-sort="ascending">Placeholder content</span>
+ <span role="columnheader">header 2</span>
+ <span role="columnheader">header 3</span>
+ </div>
+ <div role="row">
+ <span role="gridcell" id="obj1">obj1</span>
+ <span role="gridcell">obj2</span>
+ <span role="gridcell">obj3</span>
+ </div>
+ <div role="row">
+ <span role="gridcell">obj1</span>
+ <span role="gridcell">obj2</span>
+ <span role="gridcell">obj3</span>
+ </div>
+ <div role="row">
+ <span role="gridcell">obj1</span>
+ <span role="gridcell">obj2</span>
+ <span role="gridcell">obj3</span>
+ </div>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-columnheader-aria-sort-descending.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-columnheader-aria-sort-descending.html
new file mode 100644
index 00000000000..ebffc1be7c5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-columnheader-aria-sort-descending.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role columnheader; supported state or property "aria-sort" value of "descending"</title>
+ </head>
+ <body>
+ <div role="grid">
+ <div role="row">
+ <span id="test" role="columnheader" aria-sort="descending">Placeholder content</span>
+ <span role="columnheader">header 2</span>
+ <span role="columnheader">header 3</span>
+ </div>
+ <div role="row">
+ <span role="gridcell" id="obj1">obj1</span>
+ <span role="gridcell">obj2</span>
+ <span role="gridcell">obj3</span>
+ </div>
+ <div role="row">
+ <span role="gridcell">obj1</span>
+ <span role="gridcell">obj2</span>
+ <span role="gridcell">obj3</span>
+ </div>
+ <div role="row">
+ <span role="gridcell">obj1</span>
+ <span role="gridcell">obj2</span>
+ <span role="gridcell">obj3</span>
+ </div>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-columnheader-aria-sort-none.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-columnheader-aria-sort-none.html
new file mode 100644
index 00000000000..fce4f994d54
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-columnheader-aria-sort-none.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role columnheader; supported state or property "aria-sort" value of "none"</title>
+ </head>
+ <body>
+ <div role="grid">
+ <div role="row">
+ <span id="test" role="columnheader" aria-sort="none">Placeholder content</span>
+ <span role="columnheader">header 2</span>
+ <span role="columnheader">header 3</span>
+ </div>
+ <div role="row">
+ <span role="gridcell" id="obj1">obj1</span>
+ <span role="gridcell">obj2</span>
+ <span role="gridcell">obj3</span>
+ </div>
+ <div role="row">
+ <span role="gridcell">obj1</span>
+ <span role="gridcell">obj2</span>
+ <span role="gridcell">obj3</span>
+ </div>
+ <div role="row">
+ <span role="gridcell">obj1</span>
+ <span role="gridcell">obj2</span>
+ <span role="gridcell">obj3</span>
+ </div>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-columnheader-aria-sort-other.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-columnheader-aria-sort-other.html
new file mode 100644
index 00000000000..a92ba0bfc3b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-columnheader-aria-sort-other.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role columnheader; supported state or property "aria-sort" value of "other"</title>
+</head>
+<body>
+ <div role="grid">
+ <div role="row">
+ <span id="test" role="columnheader" aria-sort="other">Placeholder content</span>
+ <span role="columnheader">header 2</span>
+ <span role="columnheader">header 3</span>
+ </div>
+ <div role="row">
+ <span role="gridcell" id="obj1">obj1</span>
+ <span role="gridcell">obj2</span>
+ <span role="gridcell">obj3</span>
+ </div>
+ <div role="row">
+ <span role="gridcell">obj1</span>
+ <span role="gridcell">obj2</span>
+ <span role="gridcell">obj3</span>
+ </div>
+ <div role="row">
+ <span role="gridcell">obj1</span>
+ <span role="gridcell">obj2</span>
+ <span role="gridcell">obj3</span>
+ </div>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-combobox-aria-autocomplete-both.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-combobox-aria-autocomplete-both.html
new file mode 100644
index 00000000000..93df0ede040
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-combobox-aria-autocomplete-both.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role combobox; supported state or property "aria-autocomplete" value of
+ "both"
+ </title>
+ </head>
+ <body>
+ <input type="text" aria-label="Tag" role="combobox"
+ aria-autocomplete="both" aria-owns="owned_listbox" aria-activedescendant="selected_option" aria-expanded="true">
+ <ul role="listbox" id="owned_listbox">
+ <li role="option">Zebra</li>
+ <li role="option" id="selected_option">Zoom</li>
+ </ul>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-combobox-aria-autocomplete-inline.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-combobox-aria-autocomplete-inline.html
new file mode 100644
index 00000000000..cc202875c17
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-combobox-aria-autocomplete-inline.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role combobox; supported state or property "aria-autocomplete" value of
+ "inline"
+ </title>
+ </head>
+ <body>
+ <input type="text" aria-label="Tag" role="combobox"
+ aria-autocomplete="inline" aria-owns="owned_listbox" aria-activedescendant="selected_option" aria-expanded="true">
+ <ul role="listbox" id="owned_listbox">
+ <li role="option">Zebra</li>
+ <li role="option" id="selected_option">Zoom</li>
+ </ul>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-combobox-aria-autocomplete-list.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-combobox-aria-autocomplete-list.html
new file mode 100644
index 00000000000..060bf24c7ad
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-combobox-aria-autocomplete-list.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role combobox; supported state or property "aria-autocomplete" value of
+ "list"
+ </title>
+ </head>
+ <body>
+ <input type="text" aria-label="Tag" role="combobox"
+ aria-autocomplete="list" aria-owns="owned_listbox" aria-activedescendant="selected_option" aria-expanded="true">
+ <ul role="listbox" id="owned_listbox">
+ <li role="option">Zebra</li>
+ <li role="option" id="selected_option">Zoom</li>
+ </ul>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-combobox-aria-autocomplete-none.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-combobox-aria-autocomplete-none.html
new file mode 100644
index 00000000000..33be42e05f5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-combobox-aria-autocomplete-none.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role combobox; supported state or property "aria-autocomplete" value of
+ "none"
+ </title>
+ </head>
+ <body>
+ <input type="text" aria-label="Tag" role="combobox"
+ aria-autocomplete="none" aria-owns="owned_listbox" aria-activedescendant="selected_option" aria-expanded="true">
+ <ul role="listbox" id="owned_listbox">
+ <li role="option">Zebra</li>
+ <li role="option" id="selected_option">Zoom</li>
+ </ul>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-document-aria-expanded-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-document-aria-expanded-false.html
new file mode 100644
index 00000000000..98703bd1e3e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-document-aria-expanded-false.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role document; supported state or property "aria-expanded" value of "false"</title>
+ </head>
+ <body>
+ <div id="test" role="document" aria-expanded="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-document-aria-expanded-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-document-aria-expanded-true.html
new file mode 100644
index 00000000000..b1ebb6b404b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-document-aria-expanded-true.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role document; supported state or property "aria-expanded" value of "true"</title>
+ </head>
+ <body>
+ <div id="test" role="document" aria-expanded="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-document-aria-expanded-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-document-aria-expanded-undefined.html
new file mode 100644
index 00000000000..320a98c8241
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-document-aria-expanded-undefined.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role document; supported state or property "aria-expanded" value of "undefined"</title>
+ </head>
+ <body>
+ <div id="test" role="document" aria-expanded="undefined">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-grid-aria-multiselectable-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-grid-aria-multiselectable-false.html
new file mode 100644
index 00000000000..e5f6b6342a0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-grid-aria-multiselectable-false.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role grid; supported state or property "aria-multiselectable" value of
+ "false"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="grid" aria-multiselectable="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-grid-aria-multiselectable-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-grid-aria-multiselectable-true.html
new file mode 100644
index 00000000000..2cba1e0d877
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-grid-aria-multiselectable-true.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role grid; supported state or property "aria-multiselectable" value of
+ "true"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="grid" aria-multiselectable="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-grid-aria-readonly-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-grid-aria-readonly-false.html
new file mode 100644
index 00000000000..9793dfa0690
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-grid-aria-readonly-false.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role grid; supported state or property "aria-readonly" value of "false"</title>
+ </head>
+ <body>
+ <div id="test" role="grid" aria-readonly="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-grid-aria-readonly-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-grid-aria-readonly-true.html
new file mode 100644
index 00000000000..ff2e3b82dd3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-grid-aria-readonly-true.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role grid; supported state or property "aria-readonly" value of "true"</title>
+ </head>
+ <body>
+ <div id="test" role="grid" aria-readonly="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-gridcell-aria-readonly-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-gridcell-aria-readonly-false.html
new file mode 100644
index 00000000000..682bd32cce8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-gridcell-aria-readonly-false.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role gridcell; supported state or property "aria-readonly" value of "false"</title>
+ </head>
+ <body>
+ <div role="grid">
+ <div role="row">
+ <div id="test" role="gridcell" aria-readonly="false">Placeholder content</div>
+ <div id="obj1" role="gridcell">obj1</div>
+ <div id="obj2" role="gridcell">obj2</div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-gridcell-aria-readonly-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-gridcell-aria-readonly-true.html
new file mode 100644
index 00000000000..4d795cd2b47
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-gridcell-aria-readonly-true.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role gridcell; supported state or property "aria-readonly" value of "true"</title>
+ </head>
+ <body>
+ <div role="grid">
+ <div role="row">
+ <div id="test" role="gridcell" aria-readonly="true">Placeholder content</div>
+ <div id="obj1" role="gridcell">obj1</div>
+ <div id="obj2" role="gridcell">obj2</div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-gridcell-aria-required-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-gridcell-aria-required-false.html
new file mode 100644
index 00000000000..7fe356c7c9f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-gridcell-aria-required-false.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role gridcell; supported state or property "aria-required" value of "false"</title>
+ </head>
+ <body>
+ <div role="grid">
+ <div role="row">
+ <div id="test" role="gridcell" aria-required="false">Placeholder content</div>
+ <div id="obj1" role="gridcell">obj1</div>
+ <div id="obj2" role="gridcell">obj2</div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-gridcell-aria-required-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-gridcell-aria-required-true.html
new file mode 100644
index 00000000000..c3de53e7135
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-gridcell-aria-required-true.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role gridcell; supported state or property "aria-required" value of "true"</title>
+ </head>
+ <body>
+ <div role="grid">
+ <div role="row">
+ <div id="test" role="gridcell" aria-required="true">Placeholder content</div>
+ <div id="obj1" role="gridcell">obj1</div>
+ <div id="obj2" role="gridcell">obj2</div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-gridcell-aria-selected-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-gridcell-aria-selected-false.html
new file mode 100644
index 00000000000..339b0564e92
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-gridcell-aria-selected-false.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role gridcell; supported state or property "aria-selected" value of "false"</title>
+ </head>
+ <body>
+ <div role="grid">
+ <div role="row">
+ <div id="test" role="gridcell" aria-selected="false">Placeholder content</div>
+ <div id="obj1" role="gridcell">obj1</div>
+ <div id="obj2" role="gridcell">obj2</div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-gridcell-aria-selected-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-gridcell-aria-selected-true.html
new file mode 100644
index 00000000000..8a52fab7aab
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-gridcell-aria-selected-true.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role gridcell; supported state or property "aria-selected" value of "true"</title>
+ </head>
+ <body>
+ <div role="grid">
+ <div role="row">
+ <div id="test" role="gridcell" aria-selected="true">Placeholder content</div>
+ <div id="obj1" role="gridcell">obj1</div>
+ <div id="obj2" role="gridcell">obj2</div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-gridcell-aria-selected-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-gridcell-aria-selected-undefined.html
new file mode 100644
index 00000000000..d276b27c2cd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-gridcell-aria-selected-undefined.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role gridcell; supported state or property "aria-selected" value of "undefined"</title>
+ </head>
+ <body>
+ <div role="grid">
+ <div role="row">
+ <div id="test" role="gridcell" aria-selected="undefined">Placeholder content</div>
+ <div id="obj1" role="gridcell">obj1</div>
+ <div id="obj2" role="gridcell">obj2</div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-heading-aria-level-1.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-heading-aria-level-1.html
new file mode 100644
index 00000000000..a57d5d59f3d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-heading-aria-level-1.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role heading; supported state or property "aria-level" value of "1"</title>
+ </head>
+ <body>
+ <div id="test" role="heading" aria-level="1">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-link-aria-expanded-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-link-aria-expanded-false.html
new file mode 100644
index 00000000000..a372b6e4420
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-link-aria-expanded-false.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role link; supported state or property "aria-expanded" value of "false"</title>
+ </head>
+ <body>
+ <div id="test" role="link" aria-expanded="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-link-aria-expanded-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-link-aria-expanded-true.html
new file mode 100644
index 00000000000..0dcaa32a5e4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-link-aria-expanded-true.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role link; supported state or property "aria-expanded" value of "true"</title>
+ </head>
+ <body>
+ <div id="test" role="link" aria-expanded="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-link-aria-expanded-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-link-aria-expanded-undefined.html
new file mode 100644
index 00000000000..cd8e03704fa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-link-aria-expanded-undefined.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role link; supported state or property "aria-expanded" value of "undefined"</title>
+ </head>
+ <body>
+ <div id="test" role="link" aria-expanded="undefined">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-listbox-aria-multiselectable-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-listbox-aria-multiselectable-false.html
new file mode 100644
index 00000000000..d7c66a6e3ec
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-listbox-aria-multiselectable-false.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role listbox; supported state or property "aria-multiselectable" value
+ of "false"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="listbox" aria-multiselectable="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-listbox-aria-multiselectable-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-listbox-aria-multiselectable-true.html
new file mode 100644
index 00000000000..e0378cecbe0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-listbox-aria-multiselectable-true.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role listbox; supported state or property "aria-multiselectable" value
+ of "true"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="listbox" aria-multiselectable="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-listbox-aria-required-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-listbox-aria-required-false.html
new file mode 100644
index 00000000000..18d6da189db
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-listbox-aria-required-false.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role listbox; supported state or property "aria-required" value of "false"</title>
+ </head>
+ <body>
+ <div id="test" role="listbox" aria-required="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-listbox-aria-required-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-listbox-aria-required-true.html
new file mode 100644
index 00000000000..707442f0ed2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-listbox-aria-required-true.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role listbox; supported state or property "aria-required" value of "true"</title>
+ </head>
+ <body>
+ <div id="test" role="listbox" aria-required="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-listitem-aria-level-1.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-listitem-aria-level-1.html
new file mode 100644
index 00000000000..fd6146a495e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-listitem-aria-level-1.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role listitem; supported state or property "aria-level" value of "1"</title>
+ </head>
+ <body>
+ <div role="list"><div id="test" role="listitem" aria-level="1">Placeholder content</div></div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-listitem-aria-posinset-1.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-listitem-aria-posinset-1.html
new file mode 100644
index 00000000000..3cab9141ae0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-listitem-aria-posinset-1.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role listitem; supported state or property "aria-posinset" value of "1"</title>
+ </head>
+ <body>
+ <div role="list"><div id="test" role="listitem" aria-posinset="1">Placeholder content</div></div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-listitem-aria-setsize-1.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-listitem-aria-setsize-1.html
new file mode 100644
index 00000000000..4ef2da2d38f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-listitem-aria-setsize-1.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role listitem; supported state or property "aria-setsize" value of "1"</title>
+ </head>
+ <body>
+ <div role="list"><div id="test" role="listitem" aria-setsize="1">Placeholder content</div></div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-option-aria-checked-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-option-aria-checked-false.html
new file mode 100644
index 00000000000..2bff3b29c20
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-option-aria-checked-false.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role option; supported state or property "aria-checked" value of "false"</title>
+ </head>
+ <body>
+ <div role="listbox"><div id="test" role="option" aria-checked="false">Placeholder content</div></div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-option-aria-checked-mixed.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-option-aria-checked-mixed.html
new file mode 100644
index 00000000000..33fee796a88
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-option-aria-checked-mixed.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role option; supported state or property "aria-checked" value of "mixed"</title>
+ </head>
+ <body>
+ <div role="listbox"><div id="test" role="option" aria-checked="mixed">Placeholder content</div></div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-option-aria-checked-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-option-aria-checked-true.html
new file mode 100644
index 00000000000..49c82099522
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-option-aria-checked-true.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role option; supported state or property "aria-checked" value of "true"</title>
+ </head>
+ <body>
+ <div role="listbox"><div id="test" role="option" aria-checked="true">Placeholder content</div></div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-option-aria-checked-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-option-aria-checked-undefined.html
new file mode 100644
index 00000000000..e372ff93aee
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-option-aria-checked-undefined.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role option; supported state or property "aria-checked" value of "undefined"</title>
+ </head>
+ <body>
+ <div role="listbox"><div id="test" role="option" aria-checked="undefined">Placeholder content</div></div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-option-aria-posinset-1.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-option-aria-posinset-1.html
new file mode 100644
index 00000000000..7fbcc50427a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-option-aria-posinset-1.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role option; supported state or property "aria-posinset" value of "1"</title>
+ </head>
+ <body>
+ <div role="listbox"><div id="test" role="option" aria-posinset="1">Placeholder content</div></div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-option-aria-selected-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-option-aria-selected-false.html
new file mode 100644
index 00000000000..56db6c2ae56
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-option-aria-selected-false.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role option; supported state or property "aria-selected" value of "false"</title>
+ </head>
+ <body>
+ <div role="listbox"><div id="test" role="option" aria-selected="false">Placeholder content</div></div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-option-aria-selected-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-option-aria-selected-true.html
new file mode 100644
index 00000000000..eaf138f2efa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-option-aria-selected-true.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role option; supported state or property "aria-selected" value of "true"</title>
+ </head>
+ <body>
+ <div role="listbox"><div id="test" role="option" aria-selected="true">Placeholder content</div></div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj1</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-option-aria-selected-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-option-aria-selected-undefined.html
new file mode 100644
index 00000000000..43489a0d2b3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-option-aria-selected-undefined.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role option; supported state or property "aria-selected" value of "undefined"</title>
+ </head>
+ <body>
+ <div role="listbox"><div id="test" role="option" aria-selected="undefined">Placeholder content</div></div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-option-aria-setsize-1.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-option-aria-setsize-1.html
new file mode 100644
index 00000000000..6a8b379896d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-option-aria-setsize-1.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role option; supported state or property "aria-setsize" value of "1"</title>
+ </head>
+ <body>
+ <div role="listbox"><div id="test" role="option" aria-setsize="1">Placeholder content</div></div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-radiogroup-aria-required-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-radiogroup-aria-required-false.html
new file mode 100644
index 00000000000..fe956b50b27
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-radiogroup-aria-required-false.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role radiogroup; supported state or property "aria-required" value of "false"</title>
+ </head>
+ <body>
+ <div id="test" role="radiogroup" aria-required="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-radiogroup-aria-required-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-radiogroup-aria-required-true.html
new file mode 100644
index 00000000000..6bf6b11beff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-radiogroup-aria-required-true.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role radiogroup; supported state or property "aria-required" value of "true"</title>
+ </head>
+ <body>
+ <div id="test" role="radiogroup" aria-required="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-row-aria-level-1.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-row-aria-level-1.html
new file mode 100644
index 00000000000..9c1ea0b174c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-row-aria-level-1.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role row; supported state or property "aria-level" value of "1"</title>
+ </head>
+ <body>
+ <div role="grid"><div id="test" role="row" aria-level="1">Placeholder content</div></div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-row-aria-selected-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-row-aria-selected-false.html
new file mode 100644
index 00000000000..832fc16a1e8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-row-aria-selected-false.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role row; supported state or property "aria-selected" value of "false"</title>
+ </head>
+ <body>
+ <div role="grid"><div id="test" role="row" aria-selected="false">Placeholder content</div></div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-row-aria-selected-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-row-aria-selected-true.html
new file mode 100644
index 00000000000..2977712b830
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-row-aria-selected-true.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role row; supported state or property "aria-selected" value of "true"</title>
+ </head>
+ <body>
+ <div role="grid"><div id="test" role="row" aria-selected="true">Placeholder content</div></div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-row-aria-selected-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-row-aria-selected-undefined.html
new file mode 100644
index 00000000000..cc4f6a828a2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-row-aria-selected-undefined.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role row; supported state or property "aria-selected" value of "undefined"</title>
+ </head>
+ <body>
+ <div role="grid"><div id="test" role="row" aria-selected="undefined"><div role="gridcell">Placeholder content</div></div></div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-rowheader-aria-sort-ascending.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-rowheader-aria-sort-ascending.html
new file mode 100644
index 00000000000..79f3316a9e4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-rowheader-aria-sort-ascending.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role rowheader; supported state or property "aria-sort" value of "ascending"</title>
+ </head>
+ <body>
+ <div role="grid">
+ <div role="row">
+ <span id="test" role="rowheader" aria-sort="ascending">Placeholder content</span>
+ <span role="gridcell" id="obj1">obj1</span>
+ <span role="gridcell" id="obj2">obj2</span>
+ </div>
+ <div role="row">
+ <span role="rowheader">header cell 2</span>
+ <span role="gridcell">obj1</span>
+ <span role="gridcell">obj2</span>
+ </div>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-rowheader-aria-sort-descending.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-rowheader-aria-sort-descending.html
new file mode 100644
index 00000000000..beca847b75b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-rowheader-aria-sort-descending.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role rowheader; supported state or property "aria-sort" value of "descending"</title>
+ </head>
+ <body>
+ <div role="grid">
+ <div role="row">
+ <span id="test" role="rowheader" aria-sort="descending">Placeholder content</span>
+ <span role="gridcell" id="obj1">obj1</span>
+ <span role="gridcell" id="obj2">obj2</span>
+ </div>
+ <div role="row">
+ <span role="rowheader">header cell 2</span>
+ <span role="gridcell">obj1</span>
+ <span role="gridcell">obj2</span>
+ </div>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-rowheader-aria-sort-none.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-rowheader-aria-sort-none.html
new file mode 100644
index 00000000000..a1d466f6529
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-rowheader-aria-sort-none.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role rowheader; supported state or property "aria-sort" value of "none"</title>
+ </head>
+ <body>
+ <div role="grid">
+ <div role="row">
+ <span id="test" role="rowheader" aria-sort="none">Placeholder content</span>
+ <span role="gridcell" id="obj1">obj1</span>
+ <span role="gridcell" id="obj2">obj2</span>
+ </div>
+ <div role="row">
+ <span role="rowheader">header cell 2</span>
+ <span role="gridcell">obj1</span>
+ <span role="gridcell">obj2</span>
+ </div>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-rowheader-aria-sort-other.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-rowheader-aria-sort-other.html
new file mode 100644
index 00000000000..6ed7626aa48
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-rowheader-aria-sort-other.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role rowheader; supported state or property "aria-sort" value of "other"</title>
+ </head>
+ <body>
+ <div role="grid">
+ <div role="row">
+ <span id="test" role="rowheader" aria-sort="other">Placeholder content</span>
+ <span role="gridcell" id="obj1">obj1</span>
+ <span role="gridcell" id="obj2">obj2</span>
+ </div>
+ <div role="row">
+ <span role="rowheader">header cell 2</span>
+ <span role="gridcell">obj1</span>
+ <span role="gridcell">obj2</span>
+ </div>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-separator-aria-expanded-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-separator-aria-expanded-false.html
new file mode 100644
index 00000000000..a14c3c43821
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-separator-aria-expanded-false.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role separator; supported state or property "aria-expanded" value of "false"</title>
+ </head>
+ <body>
+ <div id="test" role="separator" aria-expanded="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-separator-aria-expanded-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-separator-aria-expanded-true.html
new file mode 100644
index 00000000000..c2d399ea47c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-separator-aria-expanded-true.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role separator; supported state or property "aria-expanded" value of "true"</title>
+ </head>
+ <body>
+ <div id="test" role="separator" aria-expanded="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-separator-aria-expanded-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-separator-aria-expanded-undefined.html
new file mode 100644
index 00000000000..8f350b71594
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-separator-aria-expanded-undefined.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role separator; supported state or property "aria-expanded" value of "undefined"</title>
+ </head>
+ <body>
+ <div id="test" role="separator" aria-expanded="undefined">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-separator-aria-orientation-horizontal.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-separator-aria-orientation-horizontal.html
new file mode 100644
index 00000000000..e888bb90e60
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-separator-aria-orientation-horizontal.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role separator; supported state or property "aria-orientation" value of
+ "horizontal"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="separator" aria-orientation="horizontal">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-separator-aria-orientation-vertical.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-separator-aria-orientation-vertical.html
new file mode 100644
index 00000000000..5dec81b8342
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-separator-aria-orientation-vertical.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role separator; supported state or property "aria-orientation" value of
+ "vertical"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="separator" aria-orientation="vertical">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-tab-aria-selected-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-tab-aria-selected-false.html
new file mode 100644
index 00000000000..e0865918b02
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-tab-aria-selected-false.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role tab; supported state or property "aria-selected" value of "false"</title>
+ </head>
+ <body>
+ <div role="tablist"><div id="test" role="tab" aria-selected="false">Placeholder content</div></div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-tab-aria-selected-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-tab-aria-selected-true.html
new file mode 100644
index 00000000000..61c5ecedec7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-tab-aria-selected-true.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role tab; supported state or property "aria-selected" value of "true"</title>
+ </head>
+ <body>
+ <div role="tablist"><div id="test" role="tab" aria-selected="true">Placeholder content</div></div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-tab-aria-selected-undefined.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-tab-aria-selected-undefined.html
new file mode 100644
index 00000000000..9e7417a3c71
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-tab-aria-selected-undefined.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role tab; supported state or property "aria-selected" value of "undefined"</title>
+ </head>
+ <body>
+ <div role="tablist"><div id="test" role="tab" aria-selected="undefined">Placeholder content</div></div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-tablist-aria-level-1.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-tablist-aria-level-1.html
new file mode 100644
index 00000000000..0e740d8fed2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-tablist-aria-level-1.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role tablist; supported state or property "aria-level" value of "1"</title>
+ </head>
+ <body>
+ <div id="test" role="tablist" aria-level="1">
+ <div id="obj1" role="tab">obj1</div>
+ <div role="tablist" aria-level="2">
+ <div id="obj2" role="tab">obj2</div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-textbox-aria-activedescendant-obj1.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-textbox-aria-activedescendant-obj1.html
new file mode 100644
index 00000000000..732dfa0d749
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-textbox-aria-activedescendant-obj1.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Test Case 234
+ </title>
+ </head>
+ <body>
+ <div id="test" role="textbox" aria-activedescendant="obj1" tabindex="0">Placeholder content
+ <div id="obj1" role="button">obj1</div>
+ </div>
+ <div id="obj2">obj2</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-textbox-aria-autocomplete-both.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-textbox-aria-autocomplete-both.html
new file mode 100644
index 00000000000..8e6136e1eb2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-textbox-aria-autocomplete-both.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role textbox; supported state or property "aria-autocomplete" value of
+ "both"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="textbox" aria-autocomplete="both">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-textbox-aria-autocomplete-inline.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-textbox-aria-autocomplete-inline.html
new file mode 100644
index 00000000000..fa9e0098525
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-textbox-aria-autocomplete-inline.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role textbox; supported state or property "aria-autocomplete" value of
+ "inline"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="textbox" aria-autocomplete="inline">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-textbox-aria-autocomplete-list.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-textbox-aria-autocomplete-list.html
new file mode 100644
index 00000000000..85d7bfa3b23
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-textbox-aria-autocomplete-list.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role textbox; supported state or property "aria-autocomplete" value of
+ "list"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="textbox" aria-autocomplete="list">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-textbox-aria-autocomplete-none.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-textbox-aria-autocomplete-none.html
new file mode 100644
index 00000000000..6594bd72635
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-textbox-aria-autocomplete-none.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role textbox; supported state or property "aria-autocomplete" value of
+ "none"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="textbox" aria-autocomplete="none">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-textbox-aria-multiline-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-textbox-aria-multiline-false.html
new file mode 100644
index 00000000000..6c047d141cd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-textbox-aria-multiline-false.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role textbox; supported state or property "aria-multiline" value of "false"</title>
+ </head>
+ <body>
+ <div id="test" role="textbox" aria-multiline="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-textbox-aria-multiline-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-textbox-aria-multiline-true.html
new file mode 100644
index 00000000000..8231e43bc5b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-textbox-aria-multiline-true.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role textbox; supported state or property "aria-multiline" value of "true"</title>
+ </head>
+ <body>
+ <div id="test" role="textbox" aria-multiline="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-textbox-aria-readonly-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-textbox-aria-readonly-false.html
new file mode 100644
index 00000000000..c007dab15be
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-textbox-aria-readonly-false.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role textbox; supported state or property "aria-readonly" value of "false"</title>
+ </head>
+ <body>
+ <div id="test" role="textbox" aria-readonly="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-textbox-aria-readonly-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-textbox-aria-readonly-true.html
new file mode 100644
index 00000000000..6525bc02b53
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-textbox-aria-readonly-true.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role textbox; supported state or property "aria-readonly" value of "true"</title>
+ </head>
+ <body>
+ <div id="test" role="textbox" aria-readonly="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-textbox-aria-required-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-textbox-aria-required-false.html
new file mode 100644
index 00000000000..eb496bc14b2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-textbox-aria-required-false.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role textbox; supported state or property "aria-required" value of "false"</title>
+ </head>
+ <body>
+ <div id="test" role="textbox" aria-required="false">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-textbox-aria-required-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-textbox-aria-required-true.html
new file mode 100644
index 00000000000..88ebdd6a254
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-textbox-aria-required-true.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role textbox; supported state or property "aria-required" value of "true"</title>
+ </head>
+ <body>
+ <div id="test" role="textbox" aria-required="true">Placeholder content</div>
+ <div id="obj1">obj1</div>
+ <div id="obj2">obj2</div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-tree-aria-multiselectable-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-tree-aria-multiselectable-false.html
new file mode 100644
index 00000000000..17ffdcc6fb2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-tree-aria-multiselectable-false.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role tree; supported state or property "aria-multiselectable" value of
+ "false"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="tree" aria-multiselectable="false">
+ <div role="treeitem" id="obj1">obj1</div>
+ <div role="treeitem" id="obj2">obj2</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-tree-aria-multiselectable-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-tree-aria-multiselectable-true.html
new file mode 100644
index 00000000000..9af7d0cc6cb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-tree-aria-multiselectable-true.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role tree; supported state or property "aria-multiselectable" value of
+ "true"
+ </title>
+ </head>
+ <body>
+ <div id="test" role="tree" aria-multiselectable="true">
+ <div role="treeitem" id="obj1">obj1</div>
+ <div role="treeitem" id="obj2">obj2</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-tree-aria-required-false.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-tree-aria-required-false.html
new file mode 100644
index 00000000000..d049bf6523c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-tree-aria-required-false.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role tree; supported state or property "aria-required" value of "false"</title>
+ </head>
+ <body>
+ <div id="test" role="tree" aria-required="false">
+ <div role="treeitem" id="obj1">obj1</div>
+ <div role="treeitem" id="obj2">obj2</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-tree-aria-required-true.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-tree-aria-required-true.html
new file mode 100644
index 00000000000..86fbbc1a515
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/roles-properties-supported/roles-properties-supported-tree-aria-required-true.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>&lt;div&gt; with role tree; supported state or property "aria-required" value of "true"</title>
+ </head>
+ <body>
+ <div id="test" role="tree" aria-required="true">
+ <div role="treeitem" id="obj1">obj1</div>
+ <div role="treeitem" id="obj2">obj2</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/selected-state/670.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/selected-state/670.html
new file mode 100644
index 00000000000..594bf048fab
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/selected-state/670.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 670</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 670</h1>
+
+ <ul role="listbox">
+ <li role="option" aria-selected="true" id="ID_OPTION" tabindex="0">Option 1</li>
+ <li role="option">Option 2</li>
+ </ul>
+
+ <h2>Description</h2>
+ <p>For an element with role role "option" which is a child of an element with
+ role "listbox", and the value of the "aria-selected" attribute is equal
+ to "true".</p>
+
+ <script type="text/javascript">
+
+ function setFocus() {
+ var node = document.getElementById('ID_OPTION');
+ node.focus();
+ }
+
+ window.addEventListener('load', setFocus);
+ </script>
+ </body>
+
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/selected-state/671.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/selected-state/671.html
new file mode 100644
index 00000000000..2c95a4f5f23
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/selected-state/671.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 671</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 671</h1>
+
+ <ul role="listbox">
+ <li role="option" aria-selected="false" id="ID_OPTION" tabindex="0">Option 1</li>
+ <li role="option">Option 2</li>
+ </ul>
+
+ <h2>Description</h2>
+ <p>For an element with role role "option" which is a child of an element with
+ role "listbox", and the value of the "aria-selected" attribute is NOT equal
+ to "true" or the attribute is undefined.</p>
+
+
+ <script type="text/javascript">
+
+ function setFocus() {
+ var test_node = document.getElementById('ID_OPTION');
+ test_node.focus();
+ }
+
+ window.addEventListener('load', setFocus);
+ </script>
+ </body>
+
+</html>
+
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/selected-state/672.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/selected-state/672.html
new file mode 100644
index 00000000000..461d343a0e2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/selected-state/672.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 672</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 672</h1>
+ <ul role="listbox">
+ <li role="option" aria-selected="false" id="TEST_ID" tabindex="0">Option 1</li>
+ <li role="option">Option 2</li>
+ </ul>
+
+ <h2>Description</h2>
+ <p>For an element with role "option" which is a child of an element with role "listbox",
+ and the value of the "aria-selected" attribute changes (from "true", or to "true").</p>
+
+ <script type="text/javascript">
+ function changeSelectedState() {
+ var test_node = document.getElementById('TEST_ID');
+ var state = test_node.getAttribute('aria-selected');
+
+ if (state === 'false') test_node.setAttribute('aria-selected', 'true');
+ else test_node.setAttribute('aria-selected', 'true');
+
+ }
+
+ function setFocus() {
+ var test_node = document.getElementById('TEST_ID');
+ test_node.focus();
+ setTimeout(changeSelectedState,1000);
+ }
+
+ window.addEventListener('load', setFocus);
+ </script>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/setsize-posinset-level/setsize-posinset-level-1.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/setsize-posinset-level/setsize-posinset-level-1.html
new file mode 100644
index 00000000000..92bf0f4856b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/setsize-posinset-level/setsize-posinset-level-1.html
@@ -0,0 +1,86 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 763</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 763</h1>
+
+ <div role="listbox">
+ <div role="option" aria-setsize="3" aria-posinset="1" tabindex="-1">Option 1</div>
+ <div role="option" aria-setsize="3" aria-posinset="2" tabindex="-1" id="ID_TARGET">Option 2</div>
+ <div role="option" aria-setsize="3" aria-posinset="3" tabindex="-1">Option 3</div>
+ </div>
+
+ <h2>Description</h2>
+ <p>A div element with the role='listbox' has three child div elements each with
+ role='option' and aria-setsize='3'. The 1st child div element has aria-posinset='1',
+ the 2nd child div element has aria-posinset='2' and the 3rd child div element
+ has aria-posinset='3'.</p>
+
+
+ <h2>Expected Results</h2>
+
+ <h3>MSAA + UIA Express</h3>
+ <ul>
+ <li>role="tree": ROLE_SYSTEM_LIST</li>
+ <li>role="treeitem": ROLE_SYSTEM_LISTITEM</li>
+ <li>LegacyIAccessible.Description will be in the form X of Y,
+ where X is the value of aria-posinset and Y is the value of aria-setsize
+ </li>
+ </ul>
+
+ <h3>MSAA + IAccessible2</h3>
+ <ul>
+ <li>role="tree": ROLE_SYSTEM_LIST</li>
+ <li>role="treeitem": ROLE_SYSTEM_LISTITEM</li>
+ <li>The structure should be reflected in the accessibility tree as directed by aria-posinset.</li>
+ <li>function groupPosition() should be available and have the following results:
+ <ul>
+ <li>groupLevel: 1</li>
+ <li>similarItemsInGroup: 3</li>
+ <li>positionInGroup: aria-posinest value</li>
+ </ul>
+ </li>
+ </ul>
+
+ <h3>UIA</h3>
+ <ul>
+ <li>role="tree": List</li>
+ <li>role="treeitem": ListItem</li>
+ <li>LegacyIAccessible.Description will be in the form X of Y,
+ where X is the value of aria-posinset and Y is the value of aria-setsize</li>
+ </ul>
+
+
+ <h3>ATK/AT-SPI</h3>
+ <ul>
+ <li>role="tree": ROLE_LIST</li>
+ <li>role="treeitem": ROLE_LISTITEM</li>
+ <li>aria-setsize: not mapped to setsize: value</li>
+ <li>aria-posinset: is mapped to posinset: value</li>
+ </ul>
+
+ <h3>AXAPI</h3>
+ <ul>
+ <li>role="tree": AXList = 'list'</li>
+ <li>role="treeitem": AXGroup = 'group'</li>
+ <li>aria-setsize: is mapped to AXARIASetSize: value</li>
+ <li>aria-posinset: is mapped to AXARIAPosInSet: value</li>
+ </ul>
+
+
+ <script type="text/javascript">
+
+ function setFocus() {
+ var node = document.getElementById('ID_TARGET');
+ node.focus();
+ }
+
+ window.addEventListener('load', setFocus);
+ </script>
+ </body>
+</html>
+
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/setsize-posinset-level/setsize-posinset-level-5.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/setsize-posinset-level/setsize-posinset-level-5.html
new file mode 100644
index 00000000000..1ee058526be
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/setsize-posinset-level/setsize-posinset-level-5.html
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 767</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 767</h1>
+
+ <div role="list">
+ <div role="listitem">Item 1</div>
+ <div role="listitem">Item 2</div>
+ <div role="listitem">Item 3</div>
+ <div role="listitem">Item 4</div>
+ </div>
+
+ <h2>Description</h2>
+ <p>A div element with the role='list' with four child div elements with with the role='listitem'.</p>
+
+ <h2>Expected Results</h2>
+
+ <h3>MSAA + UIA Express</h3>
+ <ul>
+ <li>role="list": ROLE_SYSTEM_LIST + STATE_SYSTEM_READONLY</li>
+ <li>role="listitem": ROLE_SYSTEM_LISTITEM + STATE_SYSTEM_READONLY</li>
+ <li>LegacyIAccessible.Description will be in the form X of Y,
+ where X is the position in list and Y = 4</li>
+ </ul>
+
+ <h3>MSAA + IAccessible2</h3>
+ <ul>
+ <li>role="list": ROLE_SYSTEM_LIST + STATE_SYSTEM_READONLY</li>
+ <li>role="listitem": ROLE_SYSTEM_LISTITEM + STATE_SYSTEM_READONLY</li>
+ <li>The structure should be reflected in the accessibility tree as directed by aria-posinset.</li>
+ <li>function groupPosition() should be available and have the following results:
+ <ul>
+ <li>object attributes setsize:4, posinset:1-based position in the list></li>
+ <li>groupLevel: 0 or 1</li>
+ <li>similarItemsInGroup: 4</li>
+ <li>positionInGroup: position in list</li>
+ </ul>
+ </li>
+ </ul>
+
+ <h3>UIA</h3>
+ <ul>
+ <li>role="list": List</li>
+ <li>role="listitem": Listitem</li>
+ <li>LegacyIAccessible.Description will be in the form X of Y,
+ where X is the position in list and Y = 4</li>
+ </ul>
+
+ <h3>ATK/AT-SPI</h3>
+ <ul>
+ <li>role="list": ROLE_LIST and STATE_EDITABLE is not exposed</li>
+ <li>role="listitem": ROLE_LISTITEM and STATE_EDITABLE is not exposed</li>
+ <li>object attributes setsize:4, posinset:1-based position in the list></li>
+ </ul>
+
+ <h3>AXAPI</h3>
+ <ul>
+ <li>role="list": AXList and AXContentList = 'content list'</li>
+ <li>role="listitem": AXGroup = nil</li>
+ <li>AXARIASetSize: 4</li>
+ <li>AXARIAPosInSet: 1 based position in list</li>
+ <li>AXDisclosureLevel: 0 or 1 </li>
+ </ul>
+ </body>
+</html>
+
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/setsize-posinset-level/setsize-posinset-level-6.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/setsize-posinset-level/setsize-posinset-level-6.html
new file mode 100644
index 00000000000..af8979c27d8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/setsize-posinset-level/setsize-posinset-level-6.html
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 768</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 768</h1>
+
+ <div role="list">
+ <div role="listitem" aria-level="2">Item 1</div>
+ <div role="listitem" aria-level="2">Item 2</div>
+ <div role="listitem" aria-level="2">Item 3</div>
+ <div role="listitem" aria-level="2">Item 4</div>
+ </div>
+
+ <h2>Description</h2>
+ <p>A div element with the role='list' with four child div elements with with the role='listitem' with a aria-level='2'.</p>
+
+ <h2>Expected Results</h2>
+
+ <h3>MSAA + UIA Express</h3>
+ <ul>
+ <li>role="list": ROLE_SYSTEM_LIST + STATE_SYSTEM_READONLY</li>
+ <li>role="listitem": ROLE_SYSTEM_LISTITEM + STATE_SYSTEM_READONLY</li>
+ <li>LegacyIAccessible.Description will be in the form X of Y,
+ where X is the position in list and Y = 4</li>
+ <li>Expose level=1 in AriaProperites for list items</li>
+ </ul>
+
+ <h3>MSAA + IAccessible2</h3>
+ <ul>
+ <li>role="list": ROLE_SYSTEM_LIST + STATE_SYSTEM_READONLY</li>
+ <li>role="listitem": ROLE_SYSTEM_LISTITEM + STATE_SYSTEM_READONLY</li>
+ <li>The structure should be reflected in the accessibility tree as directed by aria-posinset.</li>
+ <li>function groupPosition() should be available and have the following results:
+ <ul>
+ <li>groupLevel: 2</li>
+ <li>similarItemsInGroup: 4</li>
+ <li>positionInGroup: position in list</li>
+ </ul>
+ </li>
+ </ul>
+
+ <h3>UIA</h3>
+ <ul>
+ <li>role="list": List</li>
+ <li>role="listitem": Listitem</li>
+ <li>LegacyIAccessible.Description will be in the form X of Y,
+ where X is the position in list and Y = 4</li>
+ <li>Expose level=1 in AriaProperites for list items</li>
+ </ul>
+
+ <h3>ATK/AT-SPI</h3>
+ <ul>
+ <li>role="list": ROLE_LIST and STATE_EDITABLE is not exposed</li>
+ <li>role="listitem": ROLE_LISTITEM and STATE_EDITABLE is not exposed</li>
+ <li>setsize: 4</li>
+ <li>posinset: position in list</li>
+ <li>level: 2 </li>
+ </ul>
+
+ <h3>AXAPI</h3>
+ <ul>
+ <li>role="list": AXList and AXContentList = 'content list'</li>
+ <li>role="listitem": AXGroup = nil</li>
+ <li>AXARIASetSize: 4</li>
+ <li>AXARIAPosInSet: position in list</li>
+ <li>AXDisclosureLevel: 2 </li>
+ </ul>
+
+ </body>
+</html>
+
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/setsize-posinset-level/testcase-769.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/setsize-posinset-level/testcase-769.html
new file mode 100644
index 00000000000..106813d2819
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/setsize-posinset-level/testcase-769.html
@@ -0,0 +1,89 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 769</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 769</h1>
+
+ <div role="list">
+ <div role="listitem">Item 1
+ <div role="group">
+ <div role="listitem">Item 1A</div>
+ <div role="listitem">Item 1B</div>
+ </div>
+ </div>
+ <div role="listitem">Item 2
+ <div role="group">
+ <div role="listitem">Item 2A</div>
+ <div role="listitem">Item 2B</div>
+ </div>
+ </div>
+ </div>
+
+ <h2>Description</h2>
+ <p>A div element with the role='list' with two child div elements with with the role='listitem'.
+ Each of the child div element also contain a div element with the role="group" with two child
+ div elements with the role='listitem'.</p>
+
+ <h2>Expected Results</h2>
+
+ <h3>MSAA + UIA Express</h3>
+ <ul>
+ <li>role="list": ROLE_SYSTEM_LIST + STATE_SYSTEM_READONLY</li>
+ <li>role="listitem": ROLE_SYSTEM_LISTITEM + STATE_SYSTEM_READONLY</li>
+ <li>LegacyIAccessible.Description will be in the form X of Y,
+ where X is the position in list and Y = 2 (since all lists have 2 items)</li>
+ <li>Expose level=1 in AriaProperites for list items for "Item 1" and "Item 2"</li>
+ <li>Expose level=2 in AriaProperites for list items for "Item 1A", "Item 1B", "Item 2A" and "Item 2B"</li>
+ </ul>
+
+ <h3>MSAA + IAccessible2</h3>
+ <ul>
+ <li>role="list": ROLE_SYSTEM_LIST + STATE_SYSTEM_READONLY</li>
+ <li>role="listitem": ROLE_SYSTEM_LISTITEM + STATE_SYSTEM_READONLY</li>
+ <li>function groupPosition() should be available and have the following results:
+ <ul>
+ <li>groupLevel: 1 for "Item 1" and "Item 2" (since all lists have 2 items)</li>
+ <li>groupLevel: 2 for "Item 1A", "Item 1B", "Item 2A" and "Item 2B"</li>
+ <li>similarItemsInGroup: 2</li>
+ <li>positionInGroup: position in list</li>
+ </ul>
+ </li>
+ </ul>
+
+ <h3>UIA</h3>
+ <ul>
+ <li>role="list": List</li>
+ <li>role="listitem": Listitem</li>
+ <li>LegacyIAccessible.Description will be in the form X of Y,
+ where X is the position in list and Y = 2 (since all lists have 2 items)</li>
+ <li>Expose level=1 in AriaProperites for "Item 1" and "Item 2"</li>
+ <li>Expose level=2 in AriaProperites for "Item 1A", "Item 1B", "Item 2A" and "Item 2B"</li>
+ </ul>
+
+ <h3>ATK/AT-SPI</h3>
+ <ul>
+ <li>role="list": ROLE_LIST and STATE_EDITABLE is not exposed</li>
+ <li>role="listitem": ROLE_LISTITEM and STATE_EDITABLE is not exposed</li>
+ <li>setsize: 2 (since all lists have 2 items)</li>
+ <li>posinset: position in list</li>
+ <li>level: 1 for "Item 1" and "Item 2"</li>
+ <li>level: 2 for "Item 1A", "Item 1B", "Item 2A" and "Item 2B"</li>
+ </ul>
+
+ <h3>AXAPI</h3>
+ <ul>
+ <li>role="list": AXList and AXContentList = 'content list'</li>
+ <li>role="listitem" for "Item 1" and "Item 2": AXGroup = 'group'</li>
+ <li>role="listitem" for "Item 1A", "Item 1B", "Item 2A" and "Item 2B": AXGroup = nil</li>
+ <li>AXARIASetSize: 2 (since all lists have 2 items)</li>
+ <li>AXARIAPosInSet: position in list</li>
+ <li>AXDisclosureLevel: 1 for "Item 1" and "Item 2"</li>
+ <li>AXDisclosureLevel: 2 for "Item 1A", "Item 1B", "Item 2A" and "Item 2B"</li>
+ </ul>
+
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/stability-of-dom/669.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/stability-of-dom/669.html
new file mode 100644
index 00000000000..6ad0f03522d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/stability-of-dom/669.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ARIA 1.0 Test Case 669</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case 669</h1>
+
+ <ul role="listbox" id="ID_LISTBOX" tabindex="0" aria-activedescendant="ID_OPTION_1">
+ <li id="ID_OPTION_1" role="option">Option 1</li>
+ <li id="ID_OPTION_2" role="option">Option 2</li>
+ </ul>
+
+ <h2>Description</h2>
+ <p>An element with role "listbox" with two descendants having role "option"
+ and aria-activedescendant set to the id of the first option for which an
+ assistive technology or API test tool requests to move focus to option 2.</p>
+
+ <script type="text/javascript">
+
+ function setFocus() {
+ var node = document.getElementById('ID_LISTBOX');
+ node.focus();
+ }
+
+ window.addEventListener('load', setFocus);
+ </script>
+ </body>
+
+</html>
+
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/testcases-multiselectable/testcase-listbox-multiselectable-A.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/testcases-multiselectable/testcase-listbox-multiselectable-A.html
new file mode 100644
index 00000000000..ab66f058f19
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/testcases-multiselectable/testcase-listbox-multiselectable-A.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<html><head>
+ <title>ARIA 1.0 Test Case: Listbox role with multiseclect</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case: Listbox role with multiseclect</h1>
+
+ <div role="listbox" aria-multiselectable="true">
+ <div role="option">Option 1</div>
+ <div role="option" aria-selected="true" tabindex="-1">Option 2 (test for selected)</div>
+ <div role="option" aria-selected="false" id="ID_TARGET" tabindex="0">Option 3 (test for selected)</div>
+ <div role="option">Option 4</div>
+ </div>
+
+ <h2>Description</h2>
+ <p>A DIV element with role role "listbox" has an aria-multiselect attribute set to "true".
+ Two of the four child "div" elements with the role "option" have the "aria-selected" attribute set
+ to "true".</p>
+
+ <h2>Accessibility API Mappings</h2>
+
+ <h3>MSAA + UIA Express</h3>
+ <p>Expose <code>STATE_SYSTEM_SELECTED</code>; Expose <code>STATE_SYSTEM_SELECTABLE</code></p>
+
+ <h3>MSAA + IAccessible2</h3>
+ <p>Expose STATE_SYSTEM_SELECTED and STATE_SYSTEM_SELECTABLE for each of the elements with role option</p>
+
+ <h3>UIA</h3>
+ <p>Expose IsSelected property in SelectionItem Control Pattern. The availability of the SelectionItem Control Pattern indicates the item is selectable.</p>
+
+ <h3>ATK/AT-SPI</h3>
+ <p>Expose STATE_SELECTED on each of the elements with role option.</p>
+
+ <h3>AXAPI</h3>
+ <p>AXSelected:Yes on option 2 and 3 and AXSelected:No on option 1 and 4</p>
+
+ <script type="text/javascript">
+
+ function setFocus() {
+ var node = document.getElementById('ID_TARGET');
+
+myVar=setTimeout(function(){var node = document.getElementById('ID_TARGET');node.setAttribute("aria-selected","true");} ,2000)
+ }
+
+ window.addEventListener('load', setFocus);
+ </script>
+
+
+
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/testcases-multiselectable/testcase-listbox-multiselectable-B.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/testcases-multiselectable/testcase-listbox-multiselectable-B.html
new file mode 100644
index 00000000000..7ae3d88dd0a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/testcases-multiselectable/testcase-listbox-multiselectable-B.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html><head>
+ <title>ARIA 1.0 Test Case: Listbox role with multiseclect</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case: Listbox role with multiseclect</h1>
+
+ <div role="listbox" aria-multiselectable="true">
+ <div role="option">Option 1</div>
+ <div role="option" aria-selected="true" tabindex="-1">Option 2 (test for selected)</div>
+ <div role="option" aria-selected="true" id="ID_TARGET" tabindex="0">Option 3 (test for selected)</div>
+ <div role="option">Option 4</div>
+ </div>
+
+ <h2>Description</h2>
+ <p>A DIV element with role role "listbox" has an aria-multiselect attribute set to "true".
+ Two of the four child "div" elements with the role "option" have the "aria-selected" attribute set
+ to "true".</p>
+
+ <h2>Accessibility API Mappings</h2>
+
+ <h3>MSAA + UIA Express</h3>
+ <p>Expose <code>STATE_SYSTEM_SELECTED</code>; Expose <code>STATE_SYSTEM_SELECTABLE</code></p>
+
+ <h3>MSAA + IAccessible2</h3>
+ <p>Expose STATE_SYSTEM_SELECTED and STATE_SYSTEM_SELECTABLE for each of the elements with role option</p>
+
+ <h3>UIA</h3>
+ <p>Expose IsSelected property in SelectionItem Control Pattern. The availability of the SelectionItem Control Pattern indicates the item is selectable.</p>
+
+ <h3>ATK/AT-SPI</h3>
+ <p>Expose STATE_SELECTED on each of the elements with role option.</p>
+
+ <h3>AXAPI</h3>
+ <p>AXSelected:Yes on option 2 and 3 and AXSelected:No on option 1 and 4</p>
+
+ <script type="text/javascript">
+
+ function clearSelection() {
+ myVar=setTimeout(function(){var node = document.getElementById('ID_TARGET');node.setAttribute("aria-selected","false");} ,3000)
+ }
+
+ window.addEventListener('load', clearSelection);
+ </script>
+
+
+
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/testcases-multiselectable/testcase-listbox-multiselectable-C.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/testcases-multiselectable/testcase-listbox-multiselectable-C.html
new file mode 100644
index 00000000000..01f8ccfaa1a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/testcases-multiselectable/testcase-listbox-multiselectable-C.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<html><head>
+ <title>ARIA 1.0 Test Case: Listbox role with multiseclect</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <style type="text/css">
+ [aria-selected="true"] { font-weight: bold; }
+ </style>
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case: Listbox role with multiseclect</h1>
+
+ <div role="listbox" aria-multiselectable="true">
+ <div role="option">Option 1</div>
+ <div role="option" aria-selected="false" tabindex="-1">Option 2 (test for selected)</div>
+ <div role="option" aria-selected="false" id="ID_TARGET" tabindex="0">Option 3 (test for selected)</div>
+ <div role="option">Option 4</div>
+ </div>
+ <p><button onclick="toggleSelectedState();">Toggle Option 3 Selected State</button>
+
+ <h2>Description</h2>
+ <p>A DIV element with role role "listbox" has an aria-multiselect attribute set to "true".
+ Two of the four child "div" elements with the role "option" have the "aria-selected" attribute set
+ to "true".</p>
+
+ <h2>Accessibility API Mappings</h2>
+
+ <h3>MSAA + UIA Express</h3>
+ <p>Expose <code>STATE_SYSTEM_SELECTED</code>; Expose <code>STATE_SYSTEM_SELECTABLE</code></p>
+
+ <h3>MSAA + IAccessible2</h3>
+ <p>Expose STATE_SYSTEM_SELECTED and STATE_SYSTEM_SELECTABLE for each of the elements with role option</p>
+
+ <h3>UIA</h3>
+ <p>Expose IsSelected property in SelectionItem Control Pattern. The availability of the SelectionItem Control Pattern indicates the item is selectable.</p>
+
+ <h3>ATK/AT-SPI</h3>
+ <p>Expose STATE_SELECTED on each of the elements with role option.</p>
+
+ <h3>AXAPI</h3>
+ <p>AXSelected:Yes on option 2 and 3 and AXSelected:No on option 1 and 4</p>
+
+ <script type="text/javascript">
+/*
+ function setSelection() {
+ var node = document.getElementById('ID_TARGET');
+ node.setAttribute("aria-selected","true");
+ }
+
+ window.addEventListener('load', setSelection);
+*/
+ function toggleSelectedState() {
+ var el = document.getElementById('ID_TARGET');
+ if (el.getAttribute('aria-selected') == 'true')
+ el.setAttribute('aria-selected', 'false');
+ else
+ el.setAttribute('aria-selected', 'true');
+ }
+
+ </script>
+
+
+
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/testcases-multiselectable/testcase-multiselectable-D.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/testcases-multiselectable/testcase-multiselectable-D.html
new file mode 100644
index 00000000000..cc13b5cfe01
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/testcases-multiselectable/testcase-multiselectable-D.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html><head>
+ <title>ARIA 1.0 Test Case: Listbox role with multiseclect</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <style type="text/css">
+ div[aria-selected="true"] {color:white;background-color:black;}
+ </style>
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case: Listbox role with multiseclect</h1>
+
+ <div role="listbox" aria-label="charlotte" aria-multiselectable="true">
+ <div role="option" aria-selected="false" id="ID1" tabindex="-1" onclick="handle1(event)">Option 1 (test for click elected)</div>
+ <div role="option" aria-selected="false" id="ID2" tabindex="-1">Option 2</div>
+ <div role="option" aria-selected="false" id="ID3" onmousedown="handle2(event)">Option 3 (test for shift click selected)</div>
+ </div>
+
+ <script type="text/javascript">
+ function handle1(e) {
+ var node=document.getElementById('ID1');
+ node.focus();
+ e.stopPropagation();
+ return false;
+ }
+ function handle2(e) {
+ shiftpressed=0;
+ shiftpressed=e.shiftKey;
+ if (shiftpressed){
+ var node=document.getElementById('ID1');
+ node.setAttribute("aria-selected", "true");
+ node=document.getElementById('ID2');
+ node.setAttribute("aria-selected", "true");
+ node=document.getElementById('ID3');
+ node.setAttribute("aria-selected", "true");
+ }
+ e.stopPropagation();
+ return false;
+ }
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-aria/testcases-multiselectable/testcase-tree-multiselectable-C.html b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/testcases-multiselectable/testcase-tree-multiselectable-C.html
new file mode 100644
index 00000000000..eeb46a0c3f8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-aria/testcases-multiselectable/testcase-tree-multiselectable-C.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html><head>
+ <title>ARIA 1.0 Test Case: Tree role with aria-multiselectable</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ </head>
+ <body>
+ <h1>ARIA 1.0 Test Case: Tree role with aria-multiselectable</h1>
+
+ <div role="tree" aria-multiselectable="true">
+ <div role="treeitem">Leaf 1
+ <div role="group">
+ <div role="treeitem" aria-selected="true">Leaf 1A (Selected)</div>
+ <div role="treeitem">Leaf 1B</div>
+ <div role="treeitem" aria-selected="false">Leaf 1C (aria-selected='false')</div>
+ </div>
+ </div>
+ <div role="treeitem" aria-selected="true">Leaf 2 (Selected)
+ <div role="group">
+ <div role="treeitem">Leaf 2A</div>
+ <div role="treeitem">Leaf 2B</div>
+ <div role="treeitem">Leaf 2C</div>
+ </div>
+ </div>
+ <div role="treeitem">Leaf 3
+ <div role="group">
+ <div role="treeitem">Leaf 3A</div>
+ <div role="treeitem" aria-selected="false">Leaf 3B (aria-selected='false')</div>
+ <div role="treeitem" aria-selected="true">Leaf 3C (Selected)</div>
+ </div>
+ </div>
+ </div>
+
+ <script type="text/javascript">
+
+ function setFocus() {
+ var node = document.getElementById('ID_TARGET');
+ node.focus();
+ }
+
+ window.addEventListener('load', setFocus);
+ </script>
+
+
+
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/html/allowedcharacters1html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/html/allowedcharacters1html.html
new file mode 100644
index 00000000000..a717f95cee0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/html/allowedcharacters1html.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset=utf-8>
+ <title>Example</title>
+ </head>
+ <body>
+ <p>Login names can only use letters from A to Z (upper or lowercase)
+ and the character underscore (_) and minus (-).
+ For example: <code its-allowed-characters="[a-zA-Z_\-]">Huck_Finn</code>.</p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/html/allowedcharacters2html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/html/allowedcharacters2html.html
new file mode 100644
index 00000000000..adc89d72d94
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/html/allowedcharacters2html.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset=utf-8>
+ <title>Example</title>
+ <link href="allowedcharacters2htmlrules.xml" rel="its-rules"/>
+ </head>
+ <body>
+ <p>Login names can only use letters from A to Z (upper or lowercase)
+ and the character underscore (_) and minus (-).
+ For example: <code>Huck_Finn</code>.</p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/html/allowedcharacters2htmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/html/allowedcharacters2htmlrules.xml
new file mode 100644
index 00000000000..a9667e0c07b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/html/allowedcharacters2htmlrules.xml
@@ -0,0 +1,3 @@
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml" version="2.0">
+ <its:allowedCharactersRule allowedCharacters="[a-zA-Z_\-]" selector="//h:p/h:code"/>
+ </its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/html/allowedcharacters3html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/html/allowedcharacters3html.html
new file mode 100644
index 00000000000..39e2c970f68
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/html/allowedcharacters3html.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8"/>
+ <title>Example</title>
+ <link href="allowedcharacters3htmlrules.xml" rel="its-rules"/>
+ </head>
+ <body>
+ <p>Login names can only use letters from A to Z (upper or lowercase)
+ and the character underscore (_) and minus (-).
+ For example: <code id="name">Huck_Finn</code>.</p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/html/allowedcharacters3htmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/html/allowedcharacters3htmlrules.xml
new file mode 100644
index 00000000000..7e490ba52fe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/html/allowedcharacters3htmlrules.xml
@@ -0,0 +1,4 @@
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml" version="2.0">
+ <its:param name="allowedcharsParam">name</its:param>
+ <its:allowedCharactersRule allowedCharacters="[a-zA-Z_\-]" selector="//h:p/h:code[@id=$allowedcharsParam]"/>
+ </its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/html/allowedcharacters4html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/html/allowedcharacters4html.html
new file mode 100644
index 00000000000..c77e3659066
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/html/allowedcharacters4html.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8"/>
+ <title>Example</title>
+ <script type="application/its+xml">
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml" version="2.0">
+ <its:param name="acParam">name</its:param>
+ <its:allowedCharactersRule allowedCharacters="[a-zA-Z_\-]" selector="//h:code[@id=$acParam]"/>
+ </its:rules>
+ </script>
+ </head>
+ <body>
+ <p>Login names can only use letters from A to Z (upper or lowercase)
+ and the character underscore (_) and minus (-).
+ For example: <code id="name">Huck_Finn</code>.</p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/xml/allowedcharacters1xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/xml/allowedcharacters1xml.xml
new file mode 100644
index 00000000000..0188ef80089
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/xml/allowedcharacters1xml.xml
@@ -0,0 +1,12 @@
+<myRes xmlns:its="http://www.w3.org/2005/11/its">
+ <head>
+ <its:rules version="2.0">
+ <its:allowedCharactersRule allowedCharacters="[^*+]" selector="//content"/>
+ </its:rules>
+ </head>
+ <body>
+ <content>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam
+ nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed
+ diam voluptua.</content>
+ </body>
+</myRes>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/xml/allowedcharacters2xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/xml/allowedcharacters2xml.xml
new file mode 100644
index 00000000000..0f44ccf22ff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/xml/allowedcharacters2xml.xml
@@ -0,0 +1,9 @@
+<res xmlns:its="http://www.w3.org/2005/11/its">
+ <head>
+ <its:rules version="2.0">
+ <its:allowedCharactersRule selector="//record" allowedCharactersPointer="@set"/>
+ </its:rules>
+ </head>
+ <record id="a1" set="[ &#xFF01;–&#xFF5E;]">FULL WIDTH ONLY</record>
+</res>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/xml/allowedcharacters3xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/xml/allowedcharacters3xml.xml
new file mode 100644
index 00000000000..21fae032678
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/xml/allowedcharacters3xml.xml
@@ -0,0 +1,10 @@
+<myRes xmlns:its="http://www.w3.org/2005/11/its">
+ <head>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:xlink="http://www.w3.org/1999/xlink" version="2.0" xlink:type="simple" xlink:href="allowedcharacters3xmlrules.xml"/>
+ </head>
+ <body>
+ <content>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam
+ nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed
+ diam voluptua.</content>
+ </body>
+</myRes>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/xml/allowedcharacters3xmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/xml/allowedcharacters3xmlrules.xml
new file mode 100644
index 00000000000..4b624c4126b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/xml/allowedcharacters3xmlrules.xml
@@ -0,0 +1,3 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:allowedCharactersRule allowedCharacters="[^*+]" selector="//content"/>
+</its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/xml/allowedcharacters4xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/xml/allowedcharacters4xml.xml
new file mode 100644
index 00000000000..49dceddc84a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/xml/allowedcharacters4xml.xml
@@ -0,0 +1,7 @@
+<res xmlns:its="http://www.w3.org/2005/11/its">
+ <head>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:xlink="http://www.w3.org/1999/xlink" version="2.0" xlink:type="simple" xlink:href="allowedcharacters4xmlrules.xml"/>
+ </head>
+ <record id="a1" set="[ &#xFF01;–&#xFF5E;]">FULL WIDTH ONLY</record>
+</res>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/xml/allowedcharacters4xmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/xml/allowedcharacters4xmlrules.xml
new file mode 100644
index 00000000000..b45129a57d8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/xml/allowedcharacters4xmlrules.xml
@@ -0,0 +1,3 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:allowedCharactersRule selector="//record" allowedCharactersPointer="@set"/>
+</its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/xml/allowedcharacters5xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/xml/allowedcharacters5xml.xml
new file mode 100644
index 00000000000..1f1ebb0ea03
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/xml/allowedcharacters5xml.xml
@@ -0,0 +1,4 @@
+<messages xmlns:its="http://www.w3.org/2005/11/its" its:version="2.0">
+ <msg num="123">Click the <panelmsg its:allowedCharacters="[&#x0020;-&#x00FE;]"
+ >CONTINUE</panelmsg> Button on the printer panel</msg>
+</messages>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/xml/allowedcharacters6xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/xml/allowedcharacters6xml.xml
new file mode 100644
index 00000000000..0dc1a9945d0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/xml/allowedcharacters6xml.xml
@@ -0,0 +1,3 @@
+<messages xmlns:its="http://www.w3.org/2005/11/its" its:version="2.0">
+ <msg num="123">Click the <its:span allowedCharacters="[&#x0020;-&#x00FE;]">CONTINUE</its:span> Button on the printer panel</msg>
+</messages>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/xml/allowedcharacters7xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/xml/allowedcharacters7xml.xml
new file mode 100644
index 00000000000..168de572ae9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/xml/allowedcharacters7xml.xml
@@ -0,0 +1,10 @@
+<myRes xmlns:its="http://www.w3.org/2005/11/its">
+ <head>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:xlink="http://www.w3.org/1999/xlink" version="2.0" xlink:type="simple" xlink:href="allowedcharacters7xmlrules.xml"/>
+ </head>
+ <body>
+ <content id="allowedchar">Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam
+ nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed
+ diam voluptua.</content>
+ </body>
+</myRes>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/xml/allowedcharacters7xmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/xml/allowedcharacters7xmlrules.xml
new file mode 100644
index 00000000000..c030ff07204
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/xml/allowedcharacters7xmlrules.xml
@@ -0,0 +1,4 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:param name="allowedcharParam">allowedchar</its:param>
+ <its:allowedCharactersRule allowedCharacters="[^*+]" selector="//content[@id=$allowedcharParam]"/>
+</its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/xml/allowedcharacters8xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/xml/allowedcharacters8xml.xml
new file mode 100644
index 00000000000..a6d2aa6d9a2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/allowedcharacters/xml/allowedcharacters8xml.xml
@@ -0,0 +1,13 @@
+<myRes xmlns:its="http://www.w3.org/2005/11/its">
+ <head>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:param name="allowedcharParam">allowedchar</its:param>
+ <its:allowedCharactersRule allowedCharacters="[^*+]" selector="//content[@id=$allowedcharParam]"/>
+</its:rules>
+ </head>
+ <body>
+ <content id="allowedchar">Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam
+ nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed
+ diam voluptua.</content>
+ </body>
+</myRes>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/directionality/html/dir1html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/directionality/html/dir1html.html
new file mode 100644
index 00000000000..d79fd7fa5b4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/directionality/html/dir1html.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset=utf-8>
+ <title>Directionality</title>
+ </head>
+ <body>
+ <p>In Hebrew, the title <q lang="he"
+ dir="rtl">פעילות הבינאום, W3C</q>
+ means "Internationalization Activity, W3C".</p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/directionality/html/dir2html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/directionality/html/dir2html.html
new file mode 100644
index 00000000000..562676dcfc0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/directionality/html/dir2html.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset=utf-8>
+ <title>Directionality</title>
+ <script type="application/its+xml">
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml" version="2.0">
+ <its:dirRule selector="//h:*[@class='rtLeft']" dir="rtl" />
+ </its:rules>
+ </script>
+ </head>
+ <body>
+ <p>In Hebrew, the title <q lang="he"
+ class="rtLeft">פעילות הבינאום, W3C</q>
+ means "Internationalization Activity, W3C".</p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/directionality/html/dir3html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/directionality/html/dir3html.html
new file mode 100644
index 00000000000..8aba163628b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/directionality/html/dir3html.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset=utf-8>
+ <title>Directionality</title>
+ <link href="dir3htmlrules.xml" rel="its-rules"/>
+ </head>
+ <body>
+ <p>In Hebrew, the title <q lang="he"
+ class="rtLeft">פעילות הבינאום, W3C</q>
+ means "Internationalization Activity, W3C".</p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/directionality/html/dir3htmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/directionality/html/dir3htmlrules.xml
new file mode 100644
index 00000000000..8e1c97b07a1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/directionality/html/dir3htmlrules.xml
@@ -0,0 +1,4 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml" version="2.0">
+ <its:param name="dirParam">rtLeft</its:param>
+ <its:dirRule selector="//h:*[@class=$dirParam]" dir="rtl" />
+</its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/directionality/html/dir4html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/directionality/html/dir4html.html
new file mode 100644
index 00000000000..1d3ed6e1541
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/directionality/html/dir4html.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset=utf-8>
+ <title>Directionality</title>
+ <script type="application/its+xml">
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml" version="2.0">
+ <its:param name="dirParam">rtLeft</its:param>
+ <its:dirRule selector="//h:*[@class=$dirParam]" dir="rtl" />
+ </its:rules>
+ </script>
+ </head>
+ <body>
+ <p>In Hebrew, the title <q lang="he"
+ class="rtLeft">פעילות הבינאום, W3C</q>
+ means "Internationalization Activity, W3C".</p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/directionality/xml/dir1xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/directionality/xml/dir1xml.xml
new file mode 100644
index 00000000000..8962c0c06e7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/directionality/xml/dir1xml.xml
@@ -0,0 +1,12 @@
+<text xml:lang="en">
+ <head>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:dirRule dir="rtl" selector="//*[@direction='rtlText']"/>
+ </its:rules>
+ </head>
+ <body>
+ <par>In Hebrew, the title <quote xml:lang="he"
+ direction="rtlText">פעילות הבינאום, W3C</quote>
+ means <quote>Internationalization Activity, W3C</quote>.</par>
+ </body>
+</text>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/directionality/xml/dir2xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/directionality/xml/dir2xml.xml
new file mode 100644
index 00000000000..da98efb7811
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/directionality/xml/dir2xml.xml
@@ -0,0 +1,11 @@
+<text xml:lang="en">
+ <head>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0"
+ xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="dir2xmlrules.xml" />
+ </head>
+ <body>
+ <par>In Hebrew, the title <quote xml:lang="he"
+ direction="rtlText">פעילות הבינאום, W3C</quote>
+ means <quote>Internationalization Activity, W3C</quote>.</par>
+ </body>
+</text>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/directionality/xml/dir2xmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/directionality/xml/dir2xmlrules.xml
new file mode 100644
index 00000000000..42b2feb006e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/directionality/xml/dir2xmlrules.xml
@@ -0,0 +1,3 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:dirRule dir="rtl" selector="//*[@direction='rtlText']"/>
+</its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/directionality/xml/dir3xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/directionality/xml/dir3xml.xml
new file mode 100644
index 00000000000..d7f1805d6c5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/directionality/xml/dir3xml.xml
@@ -0,0 +1,7 @@
+<text xml:lang="en" xmlns:its="http://www.w3.org/2005/11/its" its:version="2.0">
+ <body>
+ <par>In Arabic, the title <quote xml:lang="ar"
+ its:dir="rtl">نشاط التدويل، W3C</quote>
+ means <quote>Internationalization Activity, W3C</quote>.</par>
+ </body>
+</text>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/directionality/xml/dir4xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/directionality/xml/dir4xml.xml
new file mode 100644
index 00000000000..1a0b77ca8e8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/directionality/xml/dir4xml.xml
@@ -0,0 +1,6 @@
+<text xml:lang="en" xmlns:its="http://www.w3.org/2005/11/its" its:version="2.0">
+ <body>
+ <par>In Arabic, the title "<its:span xml:lang="ar" dir="rtl">نشاط التدويل، W3C</its:span>"
+ means "Internationalization Activity, W3C".</par>
+ </body>
+</text>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/directionality/xml/dir5xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/directionality/xml/dir5xml.xml
new file mode 100644
index 00000000000..b8c56ac211f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/directionality/xml/dir5xml.xml
@@ -0,0 +1,13 @@
+<text xml:lang="en">
+ <head>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:param name="dirParam">rtlText</its:param>
+ <its:dirRule dir="rtl" selector="//*[@direction=$dirParam]"/>
+ </its:rules>
+ </head>
+ <body>
+ <par>In Hebrew, the title <quote xml:lang="he"
+ direction="rtlText">פעילות הבינאום, W3C</quote>
+ means <quote>Internationalization Activity, W3C</quote>.</par>
+ </body>
+</text>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/directionality/xml/dir6xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/directionality/xml/dir6xml.xml
new file mode 100644
index 00000000000..0d60fb0cc2a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/directionality/xml/dir6xml.xml
@@ -0,0 +1,11 @@
+<text xml:lang="en">
+ <head>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0"
+ xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="dir6xmlrules.xml" />
+ </head>
+ <body>
+ <par>In Hebrew, the title <quote xml:lang="he"
+ direction="rtlText">פעילות הבינאום, W3C</quote>
+ means <quote>Internationalization Activity, W3C</quote>.</par>
+ </body>
+</text>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/directionality/xml/dir6xmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/directionality/xml/dir6xmlrules.xml
new file mode 100644
index 00000000000..8ade2458f8d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/directionality/xml/dir6xmlrules.xml
@@ -0,0 +1,4 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:param name="dirParam">rtlText</its:param>
+ <its:dirRule dir="rtl" selector="//*[@direction=$dirParam]"/>
+</its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/html/domain1html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/html/domain1html.html
new file mode 100644
index 00000000000..4705f414349
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/html/domain1html.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <link href="domain1htmlrules.xml" rel="its-rules"/>
+ <meta name="keywords" content="automotive"/>
+ <title>Domain HTML</title>
+ </head>
+ <body>
+ <p>The new car from XYZ - buy it now!</p>
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/html/domain1htmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/html/domain1htmlrules.xml
new file mode 100644
index 00000000000..9387be964ba
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/html/domain1htmlrules.xml
@@ -0,0 +1,5 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml" version="2.0">
+ <its:domainRule selector="/h:html/h:body"
+ domainPointer="/h:html/h:head/h:meta[@name='keywords']/@content"/>
+ </its:rules>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/html/domain2html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/html/domain2html.html
new file mode 100644
index 00000000000..4ccce0f96b4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/html/domain2html.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <link href="domain2htmlrules.xml" rel="its-rules"/>
+ <meta name="keywords" content="automotive"/>
+ <title>Domain HTML</title>
+ </head>
+ <body>
+ <p>The new car from XYZ - buy it now!</p>
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/html/domain2htmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/html/domain2htmlrules.xml
new file mode 100644
index 00000000000..4446ffb6a09
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/html/domain2htmlrules.xml
@@ -0,0 +1,6 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml" version="2.0">
+ <its:domainRule selector="/h:html/h:body"
+ domainPointer="/h:html/h:head/h:meta[@name='keywords']/@content"
+ domainMapping="automotive auto, medical medicine, 'criminal law' law, 'property law' law"/>
+ </its:rules>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/html/domain3html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/html/domain3html.html
new file mode 100644
index 00000000000..629e3578d27
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/html/domain3html.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<link href="domain3htmlrules.xml" rel="its-rules"/>
+<meta name="keywords" content="sports law"/>
+<title>Sports law</title>
+</head>
+<body>
+<p>
+Sports law is an umbrella term used to describe the legal issues at work in the world of both amateur and professional sports.
+</p>
+<p>
+Sports law overlaps substantially with labor law, contract law, competition or antitrust law, and tort law.
+</p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/html/domain3htmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/html/domain3htmlrules.xml
new file mode 100644
index 00000000000..89aed8f1a0a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/html/domain3htmlrules.xml
@@ -0,0 +1,4 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml" version="2.0">
+<its:param name="domainParam">keywords</its:param>
+<its:domainRule selector="/h:html/h:body" domainPointer="/h:html/h:head/h:meta[@name=$domainParam]/@content" domainMapping="'sports law' law, 'labor law' law, 'contract law' law, 'competition law' law,'tort law' law"/>
+</its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/html/domain4html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/html/domain4html.html
new file mode 100644
index 00000000000..80a1da8114b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/html/domain4html.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<meta name="keywords" content="SPORTS LAW, Judicial Matters"/>
+<meta property="mykeywords" content="Sport, Law"/>
+<script type="application/its+xml">
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml" version="2.0">
+<its:param name="domainParam">keywords</its:param>
+<its:domainRule selector="/h:html/h:body" domainPointer="/h:html/h:head/h:meta[@property='mykeywords' or @name=$domainParam]/@content" domainMapping="'sports law' LAW, 'labor law' LAW, 'contract law' LAW, 'competition law' LAW,'tort law' LAW"/>
+</its:rules>
+</script>
+<title>Sports law</title>
+</head>
+<body>
+<p>Some text about sport and law.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/xml/domain1xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/xml/domain1xml.xml
new file mode 100644
index 00000000000..b3fd0f716d3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/xml/domain1xml.xml
@@ -0,0 +1,13 @@
+<doc>
+ <head>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:domainRule selector="/doc/body"
+ domainPointer="/doc/head/meta[@name='DC.subject']/@content"
+ />
+ </its:rules>
+ <meta name="DC.subject" content="automotive"/>
+ </head>
+ <body>
+ <p>The new car from XYZ - buy it now!</p>
+ </body>
+</doc>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/xml/domain2xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/xml/domain2xml.xml
new file mode 100644
index 00000000000..2c7674a247d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/xml/domain2xml.xml
@@ -0,0 +1,14 @@
+<doc>
+ <head>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:domainRule selector="/doc/body"
+ domainPointer="/doc/head/meta[@name='DC.subject']/@content"
+ domainMapping="automotive auto, 'criminal law' law, 'property law' law"
+ />
+ </its:rules>
+ <meta name="DC.subject" content="automotive"/>
+ </head>
+ <body>
+ <p>The new car from XYZ - buy it now!</p>
+ </body>
+</doc>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/xml/domain4xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/xml/domain4xml.xml
new file mode 100644
index 00000000000..c08211fca93
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/xml/domain4xml.xml
@@ -0,0 +1,10 @@
+<text>
+ <head>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:xlink="http://www.w3.org/1999/xlink" version="2.0" xlink:href="domain4xmlrules.xml"/>
+ <meta name="DC.subject" content="sports law"/>
+ </head>
+ <body>
+ <p>Sports law is an umbrella term used to describe the legal issues at work in the world of both amateur and professional sports.</p>
+ <p>Sports law overlaps substantially with labor law, contract law, competition or antitrust law, and tort law.</p>
+ </body>
+</text>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/xml/domain4xmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/xml/domain4xmlrules.xml
new file mode 100644
index 00000000000..2660698c923
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/xml/domain4xmlrules.xml
@@ -0,0 +1,6 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:domainRule selector="/text/body"
+ domainPointer="/text/head/meta[@name='DC.subject']/@content"
+ domainMapping="'sports law' law, 'labor law' law, 'contract law' law, 'competition law' law,'tort law' law"
+ />
+ </its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/xml/domain5xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/xml/domain5xml.xml
new file mode 100644
index 00000000000..8831dcb2bd5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/xml/domain5xml.xml
@@ -0,0 +1,17 @@
+<text>
+<head>
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:xlink="http://www.w3.org/1999/xlink" version="2.0" xlink:type="simple" xlink:href="domain5xmlrules.xml"/>
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+<its:domainRule selector="/text/body/span" domainPointer="/text/head/meta[@name='DC.type']/@content" domainMapping="'sports law' amateur"/>
+</its:rules>
+<meta name="DC.subject" content="sports law"/>
+<meta name="DC.type" content="sports law"/>
+</head>
+<body>
+<p>
+Sports law is an umbrella term used to describe the legal issues at work in the world of both amateur and professional sports.
+Sports law overlaps substantially with labor law, contract law, competition or antitrust law, and tort law.
+</p>
+<span id="amateursports">Unlike intercollegiate sports, international amateur sports are run by a variety of organizations. </span>
+</body>
+</text>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/xml/domain5xmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/xml/domain5xmlrules.xml
new file mode 100644
index 00000000000..472b38c58b6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/xml/domain5xmlrules.xml
@@ -0,0 +1,6 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:domainRule selector="/text/body"
+ domainPointer="/text/head/meta[@name='DC.subject']/@content"
+ domainMapping="'sports law' law,'labor law' law,'contract law' law,'competition law' law,'tort law' law"
+ />
+ </its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/xml/domain6xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/xml/domain6xml.xml
new file mode 100644
index 00000000000..c62de54ac9e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/xml/domain6xml.xml
@@ -0,0 +1,19 @@
+<text>
+<head>
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+<its:param name="domainParam">DC.type</its:param>
+<its:domainRule selector="/text/body/p" domainPointer="/text/head/meta[@name=$domainParam]/@content" domainMapping="'Poetry literature' poetry"/>
+</its:rules>
+<meta name="DC.type" content="Poetry literature"/>
+</head>
+<body>
+<p>
+<span>
+A poem is a composition written in verse (although verse has also been used for epic and dramatic fiction).
+</span>
+<span>
+Poems make use of the aesthetic qualities of language to suggest differential meanings and to evoke emotive responses. Poems rely heavily on imagery and metaphor; they may have a rhythmic structure based on patterns of stresses (metric feet) or on patterns of different-length syllables (as in classical prosody); and they may or may not utilize rhyme.
+</span>
+</p>
+</body>
+</text>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/xml/domain7xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/xml/domain7xml.xml
new file mode 100644
index 00000000000..472cbb75534
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/xml/domain7xml.xml
@@ -0,0 +1,16 @@
+<text>
+<head>
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:xlink="http://www.w3.org/1999/xlink" version="2.0" xlink:href="domain7xmlrules.xml"/>
+<meta name="DC.type" content="Poetry literature"/>
+</head>
+<body>
+<p>
+<span>
+A poem is a composition written in verse (although verse has also been used for epic and dramatic fiction).
+</span>
+<span>
+Poems make use of the aesthetic qualities of language to suggest differential meanings and to evoke emotive responses. Poems rely heavily on imagery and metaphor; they may have a rhythmic structure based on patterns of stresses (metric feet) or on patterns of different-length syllables (as in classical prosody); and they may or may not utilize rhyme.
+</span>
+</p>
+</body>
+</text>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/xml/domain7xmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/xml/domain7xmlrules.xml
new file mode 100644
index 00000000000..b9e17bd7008
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/domain/xml/domain7xmlrules.xml
@@ -0,0 +1,4 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+<its:param name="domainParam">DC.type</its:param>
+<its:domainRule selector="/text/body/p" domainPointer="/text/head/meta[@name=$domainParam]/@content" domainMapping="'Poetry literature' poetry"/>
+</its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/elementswithintext/html/withintext1html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/elementswithintext/html/withintext1html.html
new file mode 100644
index 00000000000..d1a0595bd61
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/elementswithintext/html/withintext1html.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+ <html>
+ <head>
+ <meta charset=utf-8>
+ <link href="withintext1htmlrules.xml" rel="its-rules"/>
+ <title>Appaloosa</title>
+ </head>
+ <body>
+ <section itemscope>
+ <h2>keywords</h2>
+ <span itemprop="keyword">horse</span>
+ <span itemprop="keyword">appaloosa</span>
+ </section>
+ <p itemscope>
+ The Appaloosa
+ <cite>
+ The name comes from "Palouse horse" in reference to the Palouse River in Northern Idaho.
+ </cite>
+ are rugged horses originally breed by the
+ <span itemprop="keyword">Nez-Perce</span>
+ tribe in the US Northwest.
+ </p>
+ <p>
+ They are often characterized by their spotted coats, as shown here:
+ <img src="appaloosa.png" alt="Appaloosa horses"/>
+ </p>
+<!--footer-->
+ <p>
+ Copyright:
+ <em>Zebulon Inc.</em>
+ </p>
+ </body>
+ </html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/elementswithintext/html/withintext1htmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/elementswithintext/html/withintext1htmlrules.xml
new file mode 100644
index 00000000000..5d49bbcd5b0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/elementswithintext/html/withintext1htmlrules.xml
@@ -0,0 +1,4 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml" version="2.0">
+<its:withinTextRule selector="//h:cite" withinText="nested"/>
+</its:rules>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/elementswithintext/html/withintext2html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/elementswithintext/html/withintext2html.html
new file mode 100644
index 00000000000..ed7e06095f3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/elementswithintext/html/withintext2html.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset=utf-8>
+ <title>Within text test: Default</title>
+ </head>
+ <body>
+ <p>Text with <span its-within-text="YES">bold</span>.</p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/elementswithintext/html/withintext3html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/elementswithintext/html/withintext3html.html
new file mode 100644
index 00000000000..d76f7756b94
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/elementswithintext/html/withintext3html.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+ <html>
+ <head>
+ <meta charset=utf-8>
+ <link href="withintext3htmlrules.xml" rel="its-rules"/>
+ <title>Appaloosa</title>
+ </head>
+ <body>
+ <section itemscope>
+ <h2>keywords</h2>
+ <span itemprop="firstkeyword">horse</span>
+ <span itemprop="secondkeyword">appaloosa</span>
+ </section>
+ <p itemscope>
+ The Appaloosa
+ <cite>
+ The name comes from "Palouse horse" in reference to the Palouse River in Northern Idaho.
+ </cite>
+ are rugged horses originally breed by the
+ <span itemprop="keyword">Nez-Perce</span>
+ tribe in the US Northwest.
+ </p>
+ <p>
+ They are often characterized by their spotted coats, as shown here:
+ <img src="appaloosa.png" alt="Appaloosa horses"/>
+ </p>
+<!--footer-->
+ <p>
+ Copyright:
+ <em>Zebulon Inc.</em>
+ </p>
+ </body>
+ </html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/elementswithintext/html/withintext3htmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/elementswithintext/html/withintext3htmlrules.xml
new file mode 100644
index 00000000000..127dea6b731
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/elementswithintext/html/withintext3htmlrules.xml
@@ -0,0 +1,5 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml" version="2.0">
+<its:param name="withinTextParam">firstkeyword</its:param>
+<its:withinTextRule selector="//h:cite" withinText="nested"/>
+<its:withinTextRule selector="//h:section/h:span[@itemprop=$withinTextParam]" withinText="no"/>
+</its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/elementswithintext/html/withintext4html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/elementswithintext/html/withintext4html.html
new file mode 100644
index 00000000000..ac41d6b3314
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/elementswithintext/html/withintext4html.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+ <html>
+ <head>
+<script type="application/its+xml">
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml" version="2.0">
+<its:param name="withinparam">copyright</its:param>
+<its:withinTextRule selector="//h:cite" withinText="nested"/>
+<its:withinTextRule selector="//h:p[@id=$withinparam]" withinText="yes"/>
+</its:rules>
+</script>
+ <meta charset=utf-8>
+ <title>Appaloosa</title>
+ </head>
+ <body>
+ <section itemscope>
+ <h2>keywords</h2>
+ <span itemprop="keyword">horse</span>
+ <span itemprop="keyword">appaloosa</span>
+ </section>
+ <p itemscope>
+ The Appaloosa
+ <cite>
+ The name comes from "Palouse horse" in reference to the Palouse River in Northern Idaho.
+ </cite>
+ are rugged horses originally breed by the
+ <span itemprop="keyword">Nez-Perce</span>
+ tribe in the US Northwest.
+ </p>
+ <p>
+ They are often characterized by their spotted coats, as shown here:
+ <img src="appaloosa.png" alt="Appaloosa horses"/>
+ </p>
+<!--footer-->
+ <p id="copyright">
+ Copyright:
+ <em>Zebulon Inc.</em>
+ </p>
+ </body>
+ </html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/elementswithintext/xml/withintext1xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/elementswithintext/xml/withintext1xml.xml
new file mode 100644
index 00000000000..c4a44fc7b86
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/elementswithintext/xml/withintext1xml.xml
@@ -0,0 +1,12 @@
+<doc>
+ <head>
+ <its:rules version="2.0" xmlns:its="http://www.w3.org/2005/11/its">
+ <its:withinTextRule withinText="yes" selector="//b|//u|//i"/>
+ <its:withinTextRule withinText="nested" selector="//fn"/>
+ </its:rules>
+ </head>
+ <body>
+ <p>This is a paragraph with <b>bold</b>, <i>italic</i>, and <u>underlined</u>.</p>
+ <p>This is a paragraph with a footnote<fn>This is the text of the footnote</fn> at the middle.</p>
+ </body>
+ </doc>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/elementswithintext/xml/withintext2xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/elementswithintext/xml/withintext2xml.xml
new file mode 100644
index 00000000000..c0d08106791
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/elementswithintext/xml/withintext2xml.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0"?>
+<myDocument xmlns="http://my.DocumentURI/" xml:lang="en">
+ <prolog>
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0"
+ xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="withintext2xmlrules.xml"
+ xmlns:d="http://my.DocumentURI/">
+ <its:withinTextRule selector="//d:keywords/d:kw" withinText="no"/>
+</its:rules>
+ <author>Zebulon Fairfield</author>
+ <version>version 12, revision 2 - 2006-08-14</version>
+ <keywords><kw>horse</kw><kw>appaloosa</kw></keywords>
+ <storageKey>articles-6D272BA9-3B89CAD8</storageKey>
+ </prolog>
+ <content>
+ <section>
+ <title>Appaloosa</title>
+ <p>The Appaloosa<fnote>The name comes from "Palouse horse" in reference
+ to the Palouse River in Northern Idaho.</fnote> are rugged horses
+ originally breed by the <kw>Nez-Perce</kw> tribe in the US Northwest.</p>
+ <p>They are often characterized by their spotted coats, as shown
+ here: <img src="appaloosa.png" alt="Appaloosa horses"/></p>
+ </section>
+ <footer><p>Copyright: <em>Zebulon Inc.</em></p></footer>
+ </content>
+</myDocument>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/elementswithintext/xml/withintext2xmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/elementswithintext/xml/withintext2xmlrules.xml
new file mode 100644
index 00000000000..539af5b1e7a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/elementswithintext/xml/withintext2xmlrules.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0"?>
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0"
+ xmlns:d="http://my.DocumentURI/">
+ <its:withinTextRule selector="//d:kw|//d:img|//d:em" withinText="yes"/>
+ <its:withinTextRule selector="//d:fnote" withinText="nested"/>
+</its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/elementswithintext/xml/withintext3xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/elementswithintext/xml/withintext3xml.xml
new file mode 100644
index 00000000000..66debdc8f98
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/elementswithintext/xml/withintext3xml.xml
@@ -0,0 +1,11 @@
+<text xmlns:its="http://www.w3.org/2005/11/its" its:version="2.0">
+ <prolog>
+ <title its:withinText="no">Designing User Interfaces</title>
+ <author its:withinText="no">Janice Prakash</author>
+ <keywords its:withinText="no">user interface, ui, software interface</keywords>
+ </prolog>
+ <body>
+ <p>The book <title its:withinText="yes">Of Mice and Screens</title> by <author its:withinText="yes">Aldus
+ Brandywine</author> is one of the best introductions to the vast topic of designing user interfaces.</p>
+ </body>
+</text>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/elementswithintext/xml/withintext4xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/elementswithintext/xml/withintext4xml.xml
new file mode 100644
index 00000000000..1a4b3725f67
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/elementswithintext/xml/withintext4xml.xml
@@ -0,0 +1,12 @@
+<text xmlns:its="http://www.w3.org/2005/11/its" its:version="2.0">
+ <prolog>
+ <its:span withinText="no">Designing User Interfaces</its:span>
+ <its:span withinText="no">Janice Prakash</its:span>
+ <its:span withinText="no">user interface, ui, software interface</its:span>
+ </prolog>
+ <body>
+ <p>The book <its:span withinText="yes">Of Mice and Screens</its:span> by <its:span withinText="yes">Aldus
+ Brandywine</its:span> is one of the best introductions to the vast topic of designing user interfaces.</p>
+ </body>
+</text>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/elementswithintext/xml/withintext5xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/elementswithintext/xml/withintext5xml.xml
new file mode 100644
index 00000000000..37db106f6c2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/elementswithintext/xml/withintext5xml.xml
@@ -0,0 +1,25 @@
+<doc>
+<head>
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+<its:param name="withinTextParam">footnote</its:param>
+<its:withinTextRule withinText="yes" selector="//b|//u|//i"/>
+<its:withinTextRule withinText="nested" selector="//fn[@id=$withinTextParam]"/>
+</its:rules>
+</head>
+<body>
+<p>
+This is a paragraph with
+<b>bold</b>
+,
+<i>italic</i>
+, and
+<u>underlined</u>
+.
+</p>
+<p>
+This is a paragraph with a footnote
+<fn id="footnote">This is the text of the footnote</fn>
+at the middle.
+</p>
+</body>
+</doc>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/elementswithintext/xml/withintext6xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/elementswithintext/xml/withintext6xml.xml
new file mode 100644
index 00000000000..b96c3e90237
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/elementswithintext/xml/withintext6xml.xml
@@ -0,0 +1,21 @@
+<doc>
+<head>
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:xlink="http://www.w3.org/1999/xlink" version="2.0" xlink:href="withintext6xmlrules.xml"/>
+</head>
+<body>
+<p>
+This is a paragraph with
+<b>bold</b>
+,
+<i>italic</i>
+, and
+<u>underlined</u>
+.
+</p>
+<p>
+This is a paragraph with a footnote
+<fn id="footnote">This is the text of the footnote</fn>
+at the middle.
+</p>
+</body>
+</doc>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/elementswithintext/xml/withintext6xmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/elementswithintext/xml/withintext6xmlrules.xml
new file mode 100644
index 00000000000..6f41dd04295
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/elementswithintext/xml/withintext6xmlrules.xml
@@ -0,0 +1,5 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+<its:param name="withinTextParam">footnote</its:param>
+<its:withinTextRule withinText="yes" selector="//b|//u|//i"/>
+<its:withinTextRule withinText="nested" selector="//fn[@id=$withinTextParam]"/>
+</its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/externalresource/html/externalresource1html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/externalresource/html/externalresource1html.html
new file mode 100644
index 00000000000..2b03a254137
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/externalresource/html/externalresource1html.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html lang=en>
+ <head>
+ <meta charset=utf-8>
+ <link href="externalresource1htmlrules.xml" rel="its-rules"/>
+ <title>Video element example</title>
+ </head>
+ <body>
+ <video
+ width="640"
+ height="360"
+ src="http://www.example.com/video/v2.mp"
+ poster="video-image.png">If your browser doesn't support the <code>video</code> element, you can <a href="http://www.example.com/video/v2.mp">download the video</a> instead.</video>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/externalresource/html/externalresource1htmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/externalresource/html/externalresource1htmlrules.xml
new file mode 100644
index 00000000000..21608edb30b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/externalresource/html/externalresource1htmlrules.xml
@@ -0,0 +1,4 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml" version="2.0">
+ <its:externalResourceRefRule selector="//h:video/@src" externalResourceRefPointer="."/>
+ <its:externalResourceRefRule selector="//h:video/@poster" externalResourceRefPointer="."/>
+</its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/externalresource/html/externalresource2html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/externalresource/html/externalresource2html.html
new file mode 100644
index 00000000000..17e79832c3c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/externalresource/html/externalresource2html.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html lang=en>
+ <head>
+ <meta charset=utf-8>
+ <link href="externalresource2htmlrules.xml" rel="its-rules"/>
+ <title>Video element example</title>
+ </head>
+ <body>
+ <p id='1'>
+ <video
+ width="640"
+ height="360"
+ src="http://www.example.com/video/v2.mp3"
+ poster="video-image.png">If your browser doesn't support the <code>video</code> element, you can <a href="http://www.example.com/video/v2.mp3">download the video</a> instead.</video>
+ </p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/externalresource/html/externalresource2htmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/externalresource/html/externalresource2htmlrules.xml
new file mode 100644
index 00000000000..34c66b5ec4d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/externalresource/html/externalresource2htmlrules.xml
@@ -0,0 +1,4 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml" version="2.0">
+ <its:param name="externalresourceParam">1</its:param>
+ <its:externalResourceRefRule selector="//h:p[@id=$externalresourceParam]/h:video" externalResourceRefPointer="@poster"/>
+</its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/externalresource/html/externalresource3html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/externalresource/html/externalresource3html.html
new file mode 100644
index 00000000000..98c13a12e87
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/externalresource/html/externalresource3html.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html lang=en>
+ <head>
+ <script type="application/its+xml">
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml" version="2.0">
+ <its:param name="externalresourceParam">video-image.png</its:param>
+ <its:externalResourceRefRule selector="//h:video[@poster=$externalresourceParam]" externalResourceRefPointer="@src"/>
+ </its:rules>
+ </script>
+ <meta charset=utf-8>
+ <title>Video element example</title>
+ </head>
+ <body>
+ <video
+ width="640"
+ height="360"
+ src="http://www.example.com/video/v2.mp"
+ poster="video-image.png">If your browser doesn't support the <code>video</code> element, you can <a href="http://www.example.com/video/v2.mp">download the video</a> instead.</video>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/externalresource/xml/externalresource1xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/externalresource/xml/externalresource1xml.xml
new file mode 100644
index 00000000000..51b640e7eb9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/externalresource/xml/externalresource1xml.xml
@@ -0,0 +1,24 @@
+<doc
+ xmlns:its="http://www.w3.org/2005/11/its"
+ xmlns:dbk="http://docbook.org/ns/docbook" >
+ <its:rules version="2.0">
+ <its:externalResourceRefRule selector="//dbk:imagedata | //dbk:audiodata | //dbk:videodata" externalResourceRefPointer="@fileref"/>
+ </its:rules>
+ <dbk:mediaobject>
+ <dbk:videoobject>
+ <dbk:videodata fileref="movie.avi"/>
+ </dbk:videoobject>
+ <dbk:imageobject>
+ <dbk:imagedata fileref="movie-frame.gif"/>
+ </dbk:imageobject>
+ <dbk:textobject>
+ <dbk:para>This video illustrates the proper way to assemble an inverting time distortion
+ device. </dbk:para>
+ <dbk:warning>
+ <dbk:para> It is imperative that the primary and secondary temporal couplings not be
+ mounted in the wrong order. Temporal catastrophe is the likely result. The
+ future you destroy may be your own. </dbk:para>
+ </dbk:warning>
+ </dbk:textobject>
+ </dbk:mediaobject>
+</doc>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/externalresource/xml/externalresource2xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/externalresource/xml/externalresource2xml.xml
new file mode 100644
index 00000000000..818766d0ec1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/externalresource/xml/externalresource2xml.xml
@@ -0,0 +1,22 @@
+<doc
+ xmlns:its="http://www.w3.org/2005/11/its"
+ xmlns:dbk="http://docbook.org/ns/docbook" >
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:xlink="http://www.w3.org/1999/xlink" version="2.0" xlink:href="externalresource2xmlrules.xml"/>
+ <dbk:mediaobject>
+ <dbk:videoobject>
+ <dbk:videodata fileref="movie.avi"/>
+ </dbk:videoobject>
+ <dbk:imageobject>
+ <dbk:imagedata fileref="movie-frame.gif"/>
+ </dbk:imageobject>
+ <dbk:textobject>
+ <dbk:para>This video illustrates the proper way to assemble an inverting time distortion
+ device. </dbk:para>
+ <dbk:warning>
+ <dbk:para> It is imperative that the primary and secondary temporal couplings not be
+ mounted in the wrong order. Temporal catastrophe is the likely result. The
+ future you destroy may be your own. </dbk:para>
+ </dbk:warning>
+ </dbk:textobject>
+ </dbk:mediaobject>
+</doc>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/externalresource/xml/externalresource2xmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/externalresource/xml/externalresource2xmlrules.xml
new file mode 100644
index 00000000000..718135f5e3d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/externalresource/xml/externalresource2xmlrules.xml
@@ -0,0 +1,3 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:dbk="http://docbook.org/ns/docbook" version="2.0">
+ <its:externalResourceRefRule selector="//dbk:imagedata | //dbk:audiodata | //dbk:videodata" externalResourceRefPointer="@fileref"/>
+ </its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/externalresource/xml/externalresource3xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/externalresource/xml/externalresource3xml.xml
new file mode 100644
index 00000000000..0528bb9c632
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/externalresource/xml/externalresource3xml.xml
@@ -0,0 +1,28 @@
+<doc
+ xmlns:its="http://www.w3.org/2005/11/its"
+ xmlns:dbk="http://docbook.org/ns/docbook" >
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:xlink="http://www.w3.org/1999/xlink" version="2.0" xlink:href="externalresource3xmlrules.xml"/>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:dbk="http://docbook.org/ns/docbook" version="2.0">
+ <its:externalResourceRefRule selector="//dbk:audiodata" externalResourceRefPointer="@fileref"/>
+ </its:rules>
+ <dbk:mediaobject>
+ <dbk:videoobject>
+ <dbk:videodata fileref="movie.avi"/>
+ </dbk:videoobject>
+ <dbk:audioobject>
+ <dbk:audiodata fileref="movie.mp3"/>
+ </dbk:audioobject>
+ <dbk:imageobject>
+ <dbk:imagedata fileref="movie-frame.gif"/>
+ </dbk:imageobject>
+ <dbk:textobject>
+ <dbk:para>This video illustrates the proper way to assemble an inverting time distortion
+ device. </dbk:para>
+ <dbk:warning>
+ <dbk:para> It is imperative that the primary and secondary temporal couplings not be
+ mounted in the wrong order. Temporal catastrophe is the likely result. The
+ future you destroy may be your own. </dbk:para>
+ </dbk:warning>
+ </dbk:textobject>
+ </dbk:mediaobject>
+</doc>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/externalresource/xml/externalresource3xmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/externalresource/xml/externalresource3xmlrules.xml
new file mode 100644
index 00000000000..383781cecec
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/externalresource/xml/externalresource3xmlrules.xml
@@ -0,0 +1,3 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:dbk="http://docbook.org/ns/docbook" version="2.0">
+ <its:externalResourceRefRule selector="//dbk:imagedata | //dbk:videodata" externalResourceRefPointer="@fileref"/>
+ </its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/externalresource/xml/externalresource4xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/externalresource/xml/externalresource4xml.xml
new file mode 100644
index 00000000000..76df2ccd97f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/externalresource/xml/externalresource4xml.xml
@@ -0,0 +1,25 @@
+<doc
+ xmlns:its="http://www.w3.org/2005/11/its"
+ xmlns:dbk="http://docbook.org/ns/docbook" >
+ <its:rules version="2.0">
+ <its:param name="externalResourceParam">movie-frame.gif</its:param>
+ <its:externalResourceRefRule selector="//dbk:imagedata[@fileref=$externalResourceParam]" externalResourceRefPointer="@fileref"/>
+ </its:rules>
+ <dbk:mediaobject>
+ <dbk:videoobject>
+ <dbk:videodata fileref="movie.avi"/>
+ </dbk:videoobject>
+ <dbk:imageobject>
+ <dbk:imagedata fileref="movie-frame.gif"/>
+ </dbk:imageobject>
+ <dbk:textobject>
+ <dbk:para>This video illustrates the proper way to assemble an inverting time distortion
+ device. </dbk:para>
+ <dbk:warning>
+ <dbk:para> It is imperative that the primary and secondary temporal couplings not be
+ mounted in the wrong order. Temporal catastrophe is the likely result. The
+ future you destroy may be your own. </dbk:para>
+ </dbk:warning>
+ </dbk:textobject>
+ </dbk:mediaobject>
+</doc>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/externalresource/xml/externalresource5xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/externalresource/xml/externalresource5xml.xml
new file mode 100644
index 00000000000..d3e376467eb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/externalresource/xml/externalresource5xml.xml
@@ -0,0 +1,20 @@
+<doc xmlns:dbk="http://docbook.org/ns/docbook" >
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:xlink="http://www.w3.org/1999/xlink" version="2.0" xlink:href="externalresource5xmlrules.xml"/>
+ <dbk:mediaobject>
+ <dbk:videoobject>
+ <dbk:videodata fileref="movie.avi"/>
+ </dbk:videoobject>
+ <dbk:imageobject>
+ <dbk:imagedata fileref="movie-frame.gif"/>
+ </dbk:imageobject>
+ <dbk:textobject>
+ <dbk:para>This video illustrates the proper way to assemble an inverting time distortion
+ device. </dbk:para>
+ <dbk:warning>
+ <dbk:para> It is imperative that the primary and secondary temporal couplings not be
+ mounted in the wrong order. Temporal catastrophe is the likely result. The
+ future you destroy may be your own. </dbk:para>
+ </dbk:warning>
+ </dbk:textobject>
+ </dbk:mediaobject>
+</doc>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/externalresource/xml/externalresource5xmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/externalresource/xml/externalresource5xmlrules.xml
new file mode 100644
index 00000000000..01209738e15
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/externalresource/xml/externalresource5xmlrules.xml
@@ -0,0 +1,5 @@
+<its:rules version="2.0" xmlns:its="http://www.w3.org/2005/11/its"
+ xmlns:dbk="http://docbook.org/ns/docbook">
+ <its:param name="externalResourceParam">movie-frame.gif</its:param>
+ <its:externalResourceRefRule selector="//dbk:imagedata[@fileref=$externalResourceParam]" externalResourceRefPointer="@fileref"/>
+ </its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/idvalue/html/idvalue1html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/idvalue/html/idvalue1html.html
new file mode 100644
index 00000000000..b345f202f2a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/idvalue/html/idvalue1html.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Id Value</title>
+ <link href="idvalue1htmlrules.xml" rel="its-rules"/>
+</head>
+<body>
+ <p id="settingsMissing">
+ <b id="text">Can't find settings file.</b>
+ <var id="desc">The module cannot find the default settings file.
+ You need to re-initialize the system.</var>
+ </p>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/idvalue/html/idvalue1htmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/idvalue/html/idvalue1htmlrules.xml
new file mode 100644
index 00000000000..fb049999c4a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/idvalue/html/idvalue1htmlrules.xml
@@ -0,0 +1,6 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml" version="2.0">
+ <its:idValueRule selector="//h:p" idValue="@id"/>
+ <its:idValueRule selector="//h:b" idValue="@id"/>
+ <its:idValueRule selector="//h:var" idValue="@id"/>
+</its:rules>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/idvalue/html/idvalue2html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/idvalue/html/idvalue2html.html
new file mode 100644
index 00000000000..8b53d3ddf43
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/idvalue/html/idvalue2html.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Id Value</title>
+ <link href="idvalue2htmlrules.xml" rel="its-rules"/>
+</head>
+<body>
+ <p id="settingsMissing">
+ <b id="text">Can't find settings file.</b>
+ <var id="desc">The module cannot find the default settings file.
+ You need to re-initialize the system.</var>
+ <b id="crashtext">This computer is now crashing GOODBYE!!</b>
+ </p>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/idvalue/html/idvalue2htmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/idvalue/html/idvalue2htmlrules.xml
new file mode 100644
index 00000000000..942af0dbe96
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/idvalue/html/idvalue2htmlrules.xml
@@ -0,0 +1,7 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml" version="2.0">
+ <its:param name="idvalueparam">text</its:param>
+ <its:idValueRule selector="//h:p" idValue="@id"/>
+ <its:idValueRule selector="//h:b[@id=$idvalueparam]" idValue="@id"/>
+ <its:idValueRule selector="//h:b[@id='crashtext']" idValue="@id"/>
+ <its:idValueRule selector="//h:var" idValue="@id"/>
+</its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/idvalue/html/idvalue3html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/idvalue/html/idvalue3html.html
new file mode 100644
index 00000000000..4030307b1ee
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/idvalue/html/idvalue3html.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <script type="application/its+xml">
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml" version="2.0">
+ <its:param name="idvalueparam">text</its:param>
+ <its:idValueRule selector="//h:p" idValue="@id"/>
+ <its:idValueRule selector="//h:b[@id=$idvalueparam]" idValue="@id"/>
+ <its:idValueRule selector="//h:var" idValue="@id"/>
+ </its:rules>
+ </script>
+ <meta charset=utf-8>
+ <title>Id Value</title>
+</head>
+<body>
+ <p id="settingsMissing">
+ <b id="text">Can't find settings file.</b>
+ <var id="desc">The module cannot find the default settings file.
+ You need to re-initialize the system.</var>
+ </p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/idvalue/xml/idvalue1xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/idvalue/xml/idvalue1xml.xml
new file mode 100644
index 00000000000..8b2869b12ac
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/idvalue/xml/idvalue1xml.xml
@@ -0,0 +1,20 @@
+<resource
+ xmlns:its="http://www.w3.org/2005/11/its" >
+ <its:rules version="2.0">
+ <its:idValueRule selector="//text" idValue="../@name"/>
+ </its:rules>
+<webform>
+ <entry name="btn.OK">
+ <text>OK</text>
+ <pos>1, 1</pos>
+ <trig>sendOK</trig>
+ </entry>
+</webform>
+<webform>
+ <entry name="btn.CANCEL">
+ <text>Cancel</text>
+ <pos>2, 1</pos>
+ <trig>cancelAll</trig>
+ </entry>
+</webform>
+</resource>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/idvalue/xml/idvalue2xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/idvalue/xml/idvalue2xml.xml
new file mode 100644
index 00000000000..a27ad31d8da
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/idvalue/xml/idvalue2xml.xml
@@ -0,0 +1,4 @@
+<file>
+ <res name="retryBtn" xml:id="btnAgain">Try Again</res>
+ <res name="retryTip">click this to re-run the process with the current settings.</res>
+</file>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/idvalue/xml/idvalue3xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/idvalue/xml/idvalue3xml.xml
new file mode 100644
index 00000000000..6b19c6378be
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/idvalue/xml/idvalue3xml.xml
@@ -0,0 +1,13 @@
+<resource>
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:xlink="http://www.w3.org/1999/xlink" version="2.0" xlink:href="idvalue3xmlrules.xml"/>
+ <entry name="btn.OK">
+ <text>OK</text>
+ <pos>1, 1</pos>
+ <trig>sendOK</trig>
+ </entry>
+ <entry name="btn.CANCEL">
+ <text>Cancel</text>
+ <pos>2, 1</pos>
+ <trig>cancelAll</trig>
+ </entry>
+</resource>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/idvalue/xml/idvalue3xmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/idvalue/xml/idvalue3xmlrules.xml
new file mode 100644
index 00000000000..5ff498f766a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/idvalue/xml/idvalue3xmlrules.xml
@@ -0,0 +1,3 @@
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:idValueRule selector="//entry" idValue="@name"/>
+ </its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/idvalue/xml/idvalue4xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/idvalue/xml/idvalue4xml.xml
new file mode 100644
index 00000000000..909bfd270a1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/idvalue/xml/idvalue4xml.xml
@@ -0,0 +1,17 @@
+<resource>
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:xlink="http://www.w3.org/1999/xlink" version="2.0" xlink:href="idvalue4xmlrules.xml"/>
+ <webform id="1">
+ <entry name="btn.OK">
+ <text>OK</text>
+ <pos>1, 1</pos>
+ <trig>sendOK</trig>
+ </entry>
+ </webform>
+ <webform id="2">
+ <entry name="btn.CANCEL">
+ <text>Cancel</text>
+ <pos>2, 1</pos>
+ <trig>cancelAll</trig>
+ </entry>
+ </webform>
+</resource>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/idvalue/xml/idvalue4xmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/idvalue/xml/idvalue4xmlrules.xml
new file mode 100644
index 00000000000..59e7325ec1f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/idvalue/xml/idvalue4xmlrules.xml
@@ -0,0 +1,4 @@
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:param name="idvalueParam">1</its:param>
+ <its:idValueRule selector="//webform[@id=$idvalueParam]/entry" idValue="@name"/>
+ </its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/idvalue/xml/idvalue5xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/idvalue/xml/idvalue5xml.xml
new file mode 100644
index 00000000000..4b356b09e2c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/idvalue/xml/idvalue5xml.xml
@@ -0,0 +1,20 @@
+<resource>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:param name="idvalueParam">1</its:param>
+ <its:idValueRule selector="//webform[@id=$idvalueParam]/entry" idValue="@name"/>
+ </its:rules>
+ <webform id="1">
+ <entry name="btn.OK">
+ <text>OK</text>
+ <pos>1, 1</pos>
+ <trig>sendOK</trig>
+ </entry>
+ </webform>
+ <webform id="2">
+ <entry name="btn.CANCEL">
+ <text>Cancel</text>
+ <pos>2, 1</pos>
+ <trig>cancelAll</trig>
+ </entry>
+ </webform>
+</resource>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/languageinformation/html/languageinfo1html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/languageinformation/html/languageinfo1html.html
new file mode 100644
index 00000000000..b41ecb6bf66
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/languageinformation/html/languageinfo1html.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+ <html lang="en">
+ <head>
+ <meta charset=utf-8>
+ <link href="languageinfo1htmlrules.xml" rel="its-rules"/>
+ <title>EXAMPLE</title>
+ </head>
+ <body>
+ <p>The motto of Québec is:
+ <q lang="fr-CA">Je me souviens</q>
+ .</p>
+ <p>La devise du Québec est :
+ <q lang="fr-CA">Je me souviens</q>
+ .</p>
+ </body>
+ </html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/languageinformation/html/languageinfo1htmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/languageinformation/html/languageinfo1htmlrules.xml
new file mode 100644
index 00000000000..d6bfe44e06a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/languageinformation/html/languageinfo1htmlrules.xml
@@ -0,0 +1,4 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml" version="2.0">
+<its:langRule selector="/h:*" langPointer="@lang"/>
+<its:langRule selector="//h:q" langPointer="@lang"/>
+</its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/languageinformation/html/languageinfo2html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/languageinformation/html/languageinfo2html.html
new file mode 100644
index 00000000000..9d449eff57b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/languageinformation/html/languageinfo2html.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+ <html>
+ <head>
+ <meta charset=utf-8>
+ <link href="languageinfo2htmlrules.xml" rel="its-rules"/>
+ <title>EXAMPLE</title>
+ </head>
+ <body>
+ <p>The motto of Québec is:
+ <q lang="fr-CA">Je me souviens</q>
+ .</p>
+ <p>La devise du Québec est :
+ <q lang="fr-CA">Je me souviens</q>
+ .</p>
+ </body>
+ </html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/languageinformation/html/languageinfo2htmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/languageinformation/html/languageinfo2htmlrules.xml
new file mode 100644
index 00000000000..7babe27debd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/languageinformation/html/languageinfo2htmlrules.xml
@@ -0,0 +1,4 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml" version="2.0">
+<its:param name="langParam">fr-CA</its:param>
+<its:langRule selector="//h:q[@lang=$langParam]" langPointer="@lang"/>
+</its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/languageinformation/html/languageinfo3html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/languageinformation/html/languageinfo3html.html
new file mode 100644
index 00000000000..021a5375cbd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/languageinformation/html/languageinfo3html.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+ <html>
+ <head>
+ <meta charset=utf-8>
+<script type="application/its+xml">
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml" version="2.0">
+ <its:param name="langinfoparam">2</its:param>
+ <its:langRule selector="//h:p[@id=$langinfoparam]/h:q" langPointer="@lang"/>
+ </its:rules>
+</script>
+ <title>EXAMPLE</title>
+ </head>
+ <body>
+ <p id="1">The motto of Québec is:
+ <q>Je me souviens</q>
+ .</p>
+ <p id="2">La devise du Québec est :
+ <q lang="fr-CA">Je me souviens</q>
+ .</p>
+ </body>
+ </html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/languageinformation/xml/languageinfo1xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/languageinformation/xml/languageinfo1xml.xml
new file mode 100644
index 00000000000..768cca6d0e4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/languageinformation/xml/languageinfo1xml.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0"?>
+<text>
+ <head>
+ <its:rules version="2.0" xmlns:its="http://www.w3.org/2005/11/its">
+ <its:langRule selector="//content" langPointer="@language"/>
+ <its:langRule selector="//q" langPointer="@language"/>
+ </its:rules>
+ </head>
+ <content language="en">
+ <par>The motto of Québec is: <q language="fr-CA">Je me souviens</q>.</par>
+ <par>The one of Canada: <q language="la">A mari usque ad mare</q>.</par>
+ </content>
+</text>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/languageinformation/xml/languageinfo2xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/languageinformation/xml/languageinfo2xml.xml
new file mode 100644
index 00000000000..c534bcce7fc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/languageinformation/xml/languageinfo2xml.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0"?>
+<text language="en">
+ <head>
+ <its:rules version="2.0" xmlns:its="http://www.w3.org/2005/11/its"
+ xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="languageinfo2xmlrules.xml">
+ <its:langRule selector="//content/item/text" langPointer="../lang"/>
+ </its:rules>
+ </head>
+ <content>
+ <item>
+ <lang>en</lang>
+ <text>The motto of Québec is: <q language="fr-CA">Je me souviens</q>.</text>
+ </item>
+ <item>
+ <lang>fr-CA</lang>
+ <text>La devise du Québec est : <q>Je me souviens</q>.</text>
+ </item>
+ </content>
+</text>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/languageinformation/xml/languageinfo2xmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/languageinformation/xml/languageinfo2xmlrules.xml
new file mode 100644
index 00000000000..bf7a0570da0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/languageinformation/xml/languageinfo2xmlrules.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<its:rules version="2.0" xmlns:its="http://www.w3.org/2005/11/its">
+ <its:langRule selector="/text" langPointer="@language"/>
+</its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/languageinformation/xml/languageinfo3xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/languageinformation/xml/languageinfo3xml.xml
new file mode 100644
index 00000000000..80cd2bfd42e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/languageinformation/xml/languageinfo3xml.xml
@@ -0,0 +1,20 @@
+<text language="en">
+<head>
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+<its:param name="langParam">fr-CA</its:param>
+<its:langRule selector="//par/q[@language=$langParam]" langPointer="@language"/>
+</its:rules>
+</head>
+<content>
+<par>
+The motto of Québec is:
+<q language="fr-CA">Je me souviens</q>
+.
+</par>
+<par>
+The one of Canada:
+<q language="la">A mari usque ad mare</q>
+.
+</par>
+</content>
+</text>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/languageinformation/xml/languageinfo4xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/languageinformation/xml/languageinfo4xml.xml
new file mode 100644
index 00000000000..3b28792afca
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/languageinformation/xml/languageinfo4xml.xml
@@ -0,0 +1,24 @@
+<text language="en">
+<head>
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:xlink="http://www.w3.org/1999/xlink" version="2.0" xlink:href="languageinfo4xmlrules.xml">
+</its:rules>
+</head>
+<content>
+<item>
+<lang>en</lang>
+<text>
+The motto of Québec is:
+<q language="fr-CA">Je me souviens</q>
+.
+</text>
+</item>
+<item>
+<lang>fr-CA</lang>
+<text>
+La devise du Québec est :
+<q>Je me souviens</q>
+.
+</text>
+</item>
+</content>
+</text>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/languageinformation/xml/languageinfo4xmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/languageinformation/xml/languageinfo4xmlrules.xml
new file mode 100644
index 00000000000..517f4019980
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/languageinformation/xml/languageinfo4xmlrules.xml
@@ -0,0 +1,4 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+<its:param name="langParam">fr-CA</its:param>
+<its:langRule selector="//q[@language=$langParam]" langPointer="@language"/>
+</its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/html/locale1html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/html/locale1html.html
new file mode 100644
index 00000000000..72f9604045d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/html/locale1html.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Locale filter</title>
+ <link href="locale1htmlrules.xml" rel="its-rules"/>
+ </head>
+ <body>
+ <div id="Canada">
+ <p>This legal notice is only for Canadian locales.</p>
+ </div>
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/html/locale1htmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/html/locale1htmlrules.xml
new file mode 100644
index 00000000000..d87c7f94116
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/html/locale1htmlrules.xml
@@ -0,0 +1,3 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml" version="2.0">
+ <its:localeFilterRule selector="//h:div[@id='Canada']" localeFilterList="en-CA, fr-CA"/>
+</its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/html/locale2html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/html/locale2html.html
new file mode 100644
index 00000000000..6e2870f609c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/html/locale2html.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Locale filter</title>
+ </head>
+ <body>
+ <div its-locale-filter-list="en-CA, fr-CA" id="Canada">
+ <p>This legal notice is only for Canadian locales.</p>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/html/locale3html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/html/locale3html.html
new file mode 100644
index 00000000000..5f840801ef1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/html/locale3html.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8"/>
+ <title>Locale filter</title>
+ <link href="locale3htmlrules.xml" rel="its-rules"/>
+ </head>
+ <body>
+ <div id="Canada">
+ <p>This legal notice is only for Canadian locales.</p>
+ </div>
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/html/locale3htmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/html/locale3htmlrules.xml
new file mode 100644
index 00000000000..9f44ede5958
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/html/locale3htmlrules.xml
@@ -0,0 +1,4 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml" version="2.0">
+ <its:param name="localeParam">Canada</its:param>
+ <its:localeFilterRule selector="//h:div[@id=$localeParam]" localeFilterList="en-CA, fr-CA"/>
+</its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/html/locale4html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/html/locale4html.html
new file mode 100644
index 00000000000..d8effcdf78b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/html/locale4html.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <script type="application/its+xml">
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml" version="2.0">
+ <its:param name="localeParam">Canada</its:param>
+ <its:localeFilterRule selector="//h:div[@id=$localeParam]" localeFilterList="en-CA, fr-CA"/>
+ </its:rules>
+ </script>
+ <meta charset=utf-8>
+ <title>Locale filter</title>
+ </head>
+ <body>
+ <div id="Canada">
+ <p>This legal notice is only for Canadian locales.</p>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/html/locale5html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/html/locale5html.html
new file mode 100644
index 00000000000..fe5b01665d6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/html/locale5html.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Locale filter</title>
+ </head>
+ <body>
+ <div its-locale-filter-list="*-ca">
+ <p>Text for Canadian locales.</p>
+ </div>
+ <div its-locale-filter-list="*-ca" its-locale-filter-type="exclude">
+ <p>Text for non-Canadian locales.</p>
+ </div>
+ <div its-locale-filter-list="*" its-locale-filter-type="ExCluDE">
+ <p>Text for no locales.</p>
+ </div>
+ <div its-locale-filter-list="" its-locale-filter-type="EXCLude">
+ <p>Text for all locales.</p>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/xml/locale1xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/xml/locale1xml.xml
new file mode 100644
index 00000000000..fbb4c617dc1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/xml/locale1xml.xml
@@ -0,0 +1,12 @@
+<book
+ xmlns:its="http://www.w3.org/2005/11/its"
+ its:version="2.0">
+ <info>
+ <its:rules version="2.0">
+ <its:localeFilterRule selector="//legalnotice[@role='Canada']" localeFilterList="en-CA, fr-CA"/>
+ </its:rules>
+ <legalnotice role="Canada">
+ <para>This legal notice is only for Canadian locales.</para>
+ </legalnotice>
+ </info>
+</book>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/xml/locale2xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/xml/locale2xml.xml
new file mode 100644
index 00000000000..a97c8acd19a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/xml/locale2xml.xml
@@ -0,0 +1,9 @@
+<book
+ xmlns:its="http://www.w3.org/2005/11/its" its:version="2.0">
+ <info>
+ <legalnotice
+ its:localeFilterList="en-CA, fr-CA">
+ <para>This legal notice is only for Canadian locales.</para>
+ </legalnotice>
+ </info>
+</book>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/xml/locale3xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/xml/locale3xml.xml
new file mode 100644
index 00000000000..7a99e2d4e80
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/xml/locale3xml.xml
@@ -0,0 +1,10 @@
+<book
+ xmlns:its="http://www.w3.org/2005/11/its"
+ its:version="2.0">
+ <info>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:xlink="http://www.w3.org/1999/xlink" version="2.0" xlink:href="locale3xmlrules.xml"/>
+ <legalnotice role="Canada">
+ <para>This legal notice is only for Canadian locales.</para>
+ </legalnotice>
+ </info>
+</book>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/xml/locale3xmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/xml/locale3xmlrules.xml
new file mode 100644
index 00000000000..5eda8cc7fb0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/xml/locale3xmlrules.xml
@@ -0,0 +1,3 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:localeFilterRule selector="//legalnotice[@role='Canada']" localeFilterList="en-CA, fr-CA"/>
+</its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/xml/locale4xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/xml/locale4xml.xml
new file mode 100644
index 00000000000..d3eda11e379
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/xml/locale4xml.xml
@@ -0,0 +1,16 @@
+<book
+ xmlns:its="http://www.w3.org/2005/11/its"
+ its:version="2.0">
+ <info>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:xlink="http://www.w3.org/1999/xlink" version="2.0" xlink:href="locale4xmlrules.xml"/>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:localeFilterRule selector="//legalnotice[@role='Germany']" localeFilterList="de-DE"/>
+</its:rules>
+ <legalnotice role="Canada">
+ <para>This legal notice is only for Canadian locales.</para>
+ </legalnotice>
+ <legalnotice role="Germany">
+ <para>This legal notice is only for German locales.</para>
+ </legalnotice>
+ </info>
+</book>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/xml/locale4xmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/xml/locale4xmlrules.xml
new file mode 100644
index 00000000000..5eda8cc7fb0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/xml/locale4xmlrules.xml
@@ -0,0 +1,3 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:localeFilterRule selector="//legalnotice[@role='Canada']" localeFilterList="en-CA, fr-CA"/>
+</its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/xml/locale5xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/xml/locale5xml.xml
new file mode 100644
index 00000000000..8e2e84a277d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/xml/locale5xml.xml
@@ -0,0 +1,8 @@
+
+<book xmlns:its="http://www.w3.org/2005/11/its" its:version="2.0">
+<info>
+<its:span localeFilterList="en-CA, fr-CA">
+<para>This legal notice is only for Canadian locales.</para>
+</its:span>
+</info>
+</book>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/xml/locale6xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/xml/locale6xml.xml
new file mode 100644
index 00000000000..e0881f2f1a7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/xml/locale6xml.xml
@@ -0,0 +1,14 @@
+<book>
+ <info>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:param name="localeParam">Germany</its:param>
+ <its:localeFilterRule selector="//legalnotice[@role='Germany']" localeFilterList="de-DE"/>
+</its:rules>
+ <legalnotice role="Canada">
+ <para>This legal notice is only for Canadian locales.</para>
+ </legalnotice>
+ <legalnotice role="Germany">
+ <para>This legal notice is only for German locales.</para>
+ </legalnotice>
+ </info>
+</book> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/xml/locale7xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/xml/locale7xml.xml
new file mode 100644
index 00000000000..fb11bf93feb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/xml/locale7xml.xml
@@ -0,0 +1,13 @@
+<book
+ xmlns:its="http://www.w3.org/2005/11/its"
+ its:version="2.0">
+ <info>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:xlink="http://www.w3.org/1999/xlink" version="2.0" xlink:href="locale7xmlrules.xml"/>
+ <legalnotice role="Canada">
+ <para>This legal notice is only for Canadian locales.</para>
+ </legalnotice>
+ <legalnotice role="Germany">
+ <para>This legal notice is only for German locales.</para>
+ </legalnotice>
+ </info>
+</book>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/xml/locale7xmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/xml/locale7xmlrules.xml
new file mode 100644
index 00000000000..3d851a22c90
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/xml/locale7xmlrules.xml
@@ -0,0 +1,4 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:param name="localeParam">Germany</its:param>
+ <its:localeFilterRule selector="//legalnotice[@role=$localeParam]" localeFilterList="de-DE"/>
+</its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/xml/locale8xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/xml/locale8xml.xml
new file mode 100644
index 00000000000..ff7711929ca
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localefilter/xml/locale8xml.xml
@@ -0,0 +1,18 @@
+<book
+ xmlns:its="http://www.w3.org/2005/11/its"
+ its:version="2.0">
+ <info>
+ <legalnotice its:localeFilterList="*-CA" its:localeFilterType="include">
+ <para>Text only for Canadian locales.</para>
+ </legalnotice>
+ <legalnotice its:localeFilterList="*-CA" its:localeFilterType="exclude">
+ <para>Text for non-Canadian locales.</para>
+ </legalnotice>
+ <legalnotice its:localeFilterList="*" its:localeFilterType="exclude">
+ <para>Text for no locales.</para>
+ </legalnotice>
+ <legalnotice its:localeFilterList="" its:localeFilterType="exclude">
+ <para>Text for all locales.</para>
+ </legalnotice>
+ </info>
+</book>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote1html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote1html.html
new file mode 100644
index 00000000000..6c33dd2d077
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote1html.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+ <html>
+ <head>
+ <meta charset=utf-8>
+ <title>Example</title>
+ <link href="locnote1htmlrules.xml" rel="its-rules"/>
+ </head>
+ <body>
+ <span id="DisableInfo">The {0} has been disabled.</span>
+ </body>
+ </html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote1htmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote1htmlrules.xml
new file mode 100644
index 00000000000..87b8415aac0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote1htmlrules.xml
@@ -0,0 +1,7 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml" version="2.0">
+<its:locNoteRule locNoteType="alert" selector="//h:span[@id='DisableInfo']">
+<its:locNote>
+The variable {0} has three possible values: 'printer', 'stacker' and 'stapler options'.
+</its:locNote>
+</its:locNoteRule>
+</its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote2html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote2html.html
new file mode 100644
index 00000000000..21937ae3fc3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote2html.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+ <html>
+ <head>
+ <meta charset=utf-8>
+ <title>Example</title>
+ <link href="locnote2htmlrules.xml" rel="its-rules"/>
+ </head>
+ <body>
+ <section id="FileNotFound">
+ <h2>FileNotFound</h2>
+ <p>
+ Indicates that the resource file {0} could not be loaded.
+ </p>
+ <span>Cannot find the file {0}.</span>
+ </section>
+ <section id="DivByZero">
+ <h2>FileNotFound</h2>
+ <p>A division by 0 was going to be computed.</p>
+ <span>Invalid parameter.</span>
+ </section>
+ </body>
+ </html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote2htmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote2htmlrules.xml
new file mode 100644
index 00000000000..2da2d203e9f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote2htmlrules.xml
@@ -0,0 +1,4 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml" version="2.0">
+<its:translateRule selector="//h:section/h:p" translate="no"/>
+<its:locNoteRule locNoteType="description" selector="//h:section/h:span" locNotePointer="../h:p"/>
+</its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote3html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote3html.html
new file mode 100644
index 00000000000..380ab5f88da
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote3html.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+ <html>
+ <head>
+ <meta charset=utf-8>
+ <title>EXAMPLE</title>
+ <link href="locnote3htmlrules.xml" rel="its-rules"/>
+ </head>
+ <body>
+ <span id="NotFound">Cannot find {0} on {1}.</span>
+ </body>
+ </html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote3htmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote3htmlrules.xml
new file mode 100644
index 00000000000..898225e4308
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote3htmlrules.xml
@@ -0,0 +1,3 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml" version="2.0">
+<its:locNoteRule locNoteType="description" selector="//h:span[@id='NotFound']" locNoteRef="ErrorsInfo.html/#NotFound"/>
+</its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote4html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote4html.html
new file mode 100644
index 00000000000..8cc2ffe190d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote4html.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+ <html>
+ <head>
+ <meta charset=utf-8>
+ <title>EXAMPLE</title>
+ <link href="locnote4htmlrules.xml" rel="its-rules"/>
+ </head>
+ <body>
+ <p id="FileNotFound" title="Comments.html#FileNotFound">
+ <span>Cannot find the file {0}.</span>
+ </p>
+ <p id="DivByZero" title="Comments.html#DivByZero">
+ <span>Invalid parameter.</span>
+ </p>
+ </body>
+ </html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote4htmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote4htmlrules.xml
new file mode 100644
index 00000000000..2e0f1173e02
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote4htmlrules.xml
@@ -0,0 +1,3 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml" version="2.0">
+<its:locNoteRule locNoteType="description" selector="//h:body/h:p/h:span" locNoteRefPointer="../@title"/>
+</its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote5html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote5html.html
new file mode 100644
index 00000000000..1db258ab101
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote5html.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+ <html>
+ <head>
+ <meta charset=utf-8>
+ <link href="locnote5htmlrules.xml" rel="its-rules"/>
+ <title>EXAMPLE</title>
+ </head>
+ <body>
+ <p id="1">
+ This is a hippoptamus:
+ <img src="hippo.png" alt="Hippo in the Chobe River"/>
+ .
+ </p>
+ <p id="2">
+ This is an elephant:
+ <img src="elephants.png" alt="Elephants taking a mud bath"/>
+ .
+ </p>
+ <p id="DisableInfo">The {0} has been disabled.</p>
+ </body>
+ </html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote5htmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote5htmlrules.xml
new file mode 100644
index 00000000000..c9d00868a25
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote5htmlrules.xml
@@ -0,0 +1,15 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml" version="2.0">
+<its:locNoteRule selector="//h:p[@id='1']/h:img/@alt" locNoteType="alert">
+<its:locNote>Do not translate the word "Chobe"</its:locNote>
+</its:locNoteRule>
+<its:locNoteRule selector="//h:p[@id='2']/h:img/@alt" locNoteType="description">
+<its:locNote>This text will be displayed over the image.</its:locNote>
+</its:locNoteRule>
+<its:locNoteRule locNoteType="alert" selector="//h:p[@id='DisableInfo']">
+<its:locNote>
+The variable
+{0}
+has three possible values: 'printer', 'stacker' and 'stapler options'.
+</its:locNote>
+</its:locNoteRule>
+</its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote6html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote6html.html
new file mode 100644
index 00000000000..eea2ad93e44
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote6html.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+ <html>
+ <head>
+ <meta charset=utf-8>
+ <title>EXAMPLE</title>
+ <link href="locnote6htmlrules.xml" rel="its-rules"/>
+ </head>
+ <body>
+ <span id="1">
+ This is a hippoptamus:
+ <img src="hippo.png" alt="Hippo in the Chobe River"/>
+ .
+ </span>
+ <span id="2">
+ This is an elephant:
+ <img src="elephants.png" alt="Elephants taking a mud bath"/>
+ .
+ </span>
+ <span id="DisableInfo">The {0} has been disabled.</span>
+ </body>
+ </html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote6htmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote6htmlrules.xml
new file mode 100644
index 00000000000..d8a1ee4a70f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote6htmlrules.xml
@@ -0,0 +1,15 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml" version="2.0">
+<its:locNoteRule selector="//@alt" locNoteType="description">
+<its:locNote>This text will be displayed over the image.</its:locNote>
+</its:locNoteRule>
+<its:locNoteRule selector="//h:span[@id='1']/h:img/@alt" locNoteType="alert">
+<its:locNote>Do not translate the word "Chobe"</its:locNote>
+</its:locNoteRule>
+<its:locNoteRule locNoteType="alert" selector="//h:span[@id='DisableInfo']">
+<its:locNote>
+The variable
+{0}
+has three possible values: 'printer', 'stacker' and 'stapler options'.
+</its:locNote>
+</its:locNoteRule>
+</its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote7html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote7html.html
new file mode 100644
index 00000000000..4741c323d76
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote7html.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset=utf-8>
+ <title>LocNote test: Default</title>
+ </head>
+ <body>
+ <p>This is a <span its-loc-note="Check with terminology engineer" its-loc-note-type="ALERT">motherboard</span>.</p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote8html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote8html.html
new file mode 100644
index 00000000000..8913b8eada9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote8html.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+ <html>
+ <head>
+ <meta charset=utf-8>
+ <title>EXAMPLE</title>
+ <link href="locnote8htmlrules.xml" rel="its-rules"/>
+ </head>
+ <body>
+ <span id="1">
+ This is a hippoptamus:
+ <img src="hippo.png" alt="Hippo in the Chobe River"/>
+ .
+ </span>
+ <span id="2">
+ This is an elephant:
+ <img src="elephants.png" alt="Elephants taking a mud bath"/>
+ .
+ </span>
+ <span id="DisableInfo">The {0} has been disabled.</span>
+ </body>
+ </html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote8htmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote8htmlrules.xml
new file mode 100644
index 00000000000..7d6c81f1edf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote8htmlrules.xml
@@ -0,0 +1,16 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml" version="2.0">
+<its:param name="spanIdParam">DisableInfo</its:param>
+<its:locNoteRule selector="//@alt" locNoteType="description">
+<its:locNote>This text will be displayed over the image.</its:locNote>
+</its:locNoteRule>
+<its:locNoteRule selector="//h:span[@id='1']/h:img/@alt" locNoteType="alert">
+<its:locNote>Do not translate the word "Chobe"</its:locNote>
+</its:locNoteRule>
+<its:locNoteRule locNoteType="alert" selector="//h:span[@id=$spanIdParam]">
+<its:locNote>
+The variable
+{0}
+has three possible values: 'printer', 'stacker' and 'stapler options'.
+</its:locNote>
+</its:locNoteRule>
+</its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote9html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote9html.html
new file mode 100644
index 00000000000..9adbbcd23e6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/html/locnote9html.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html lang=en>
+ <head>
+<script type="application/its+xml">
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml" version="2.0">
+ <its:param name="locnoteparam">DisableInfo</its:param>
+ <its:locNoteRule locNoteType="alert" selector="//h:p[@id=$locnoteparam]">
+ <its:locNote>The variable {0} has three possible values: 'printer',
+ 'stacker' and 'stapler options'.</its:locNote>
+ </its:locNoteRule>
+ </its:rules>
+</script>
+ <meta charset=utf-8>
+ <title>Example</title>
+ </head>
+<body>
+ <p id="DisableInfo">The {0} has been disabled.</p>
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/xml/locnote10xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/xml/locnote10xml.xml
new file mode 100644
index 00000000000..aefe57b3a7c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/xml/locnote10xml.xml
@@ -0,0 +1,33 @@
+<msgList>
+<head>
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+<its:param name="DisableInfoParam">DisableInfo</its:param>
+<its:locNoteRule selector="//@alt" locNoteType="description">
+<its:locNote>This text will be displayed over the image.</its:locNote>
+</its:locNoteRule>
+<its:locNoteRule selector="//msg[@id='1']/img/@alt" locNoteType="alert">
+<its:locNote>Do not translate the word "Chobe"</its:locNote>
+</its:locNoteRule>
+<its:locNoteRule locNoteType="alert" selector="//msg[@id=$DisableInfoParam]">
+<its:locNote>
+The variable
+{0}
+has three possible values: 'printer', 'stacker' and 'stapler options'.
+</its:locNote>
+</its:locNoteRule>
+</its:rules>
+</head>
+<body>
+<msg id="1">
+This is a hippoptamus:
+<img src="hippo.png" alt="Hippo in the Chobe River"/>
+.
+</msg>
+<msg id="2">
+This is an elephant:
+<img src="elephants.png" alt="Elephants taking a mud bath"/>
+.
+</msg>
+<msg id="DisableInfo">The {0} has been disabled.</msg>
+</body>
+</msgList>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/xml/locnote11xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/xml/locnote11xml.xml
new file mode 100644
index 00000000000..20a697e98e8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/xml/locnote11xml.xml
@@ -0,0 +1,18 @@
+<msgList>
+<head>
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="locnote11xmlrules.xml"/>
+</head>
+<body>
+<msg id="1">
+This is a hippoptamus:
+<img src="hippo.png" alt="Hippo in the Chobe River"/>
+.
+</msg>
+<msg id="2">
+This is an elephant:
+<img src="elephants.png" alt="Elephants taking a mud bath"/>
+.
+</msg>
+<msg id="DisableInfo">The {0} has been disabled.</msg>
+</body>
+</msgList>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/xml/locnote11xmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/xml/locnote11xmlrules.xml
new file mode 100644
index 00000000000..43b00c70cd8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/xml/locnote11xmlrules.xml
@@ -0,0 +1,16 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+<its:param name="DisableInfoParam">DisableInfo</its:param>
+<its:locNoteRule selector="//@alt" locNoteType="description">
+<its:locNote>This text will be displayed over the image.</its:locNote>
+</its:locNoteRule>
+<its:locNoteRule selector="//msg[@id='1']/img/@alt" locNoteType="alert">
+<its:locNote>Do not translate the word "Chobe"</its:locNote>
+</its:locNoteRule>
+<its:locNoteRule locNoteType="alert" selector="//msg[@id=$DisableInfoParam]">
+<its:locNote>
+The variable
+{0}
+has three possible values: 'printer', 'stacker' and 'stapler options'.
+</its:locNote>
+</its:locNoteRule>
+</its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/xml/locnote1xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/xml/locnote1xml.xml
new file mode 100644
index 00000000000..4b509975728
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/xml/locnote1xml.xml
@@ -0,0 +1,13 @@
+<myRes>
+ <head>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:locNoteRule locNoteType="alert" selector="//msg[@id='DisableInfo']">
+ <its:locNote>The variable {0} has three possible values: 'printer',
+ 'stacker' and 'stapler options'.</its:locNote>
+ </its:locNoteRule>
+ </its:rules>
+ </head>
+ <body>
+ <msg id="DisableInfo">The {0} has been disabled.</msg>
+ </body>
+</myRes>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/xml/locnote2xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/xml/locnote2xml.xml
new file mode 100644
index 00000000000..166215d649e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/xml/locnote2xml.xml
@@ -0,0 +1,19 @@
+<Res>
+ <prolog>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:translateRule selector="//msg/notes" translate="no"/>
+ <its:locNoteRule locNoteType="description" selector="//msg/data"
+ locNotePointer="../notes"/>
+ </its:rules>
+ </prolog>
+ <body>
+ <msg id="FileNotFound">
+ <notes>Indicates that the resource file {0} could not be loaded.</notes>
+ <data>Cannot find the file {0}.</data>
+ </msg>
+ <msg id="DivByZero">
+ <notes>A division by 0 was going to be computed.</notes>
+ <data>Invalid parameter.</data>
+ </msg>
+ </body>
+</Res>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/xml/locnote3xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/xml/locnote3xml.xml
new file mode 100644
index 00000000000..3336af33d42
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/xml/locnote3xml.xml
@@ -0,0 +1,12 @@
+<myRes>
+ <head>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:locNoteRule locNoteType="description"
+ selector="//msg[@id='NotFound']"
+ locNoteRef="ErrorsInfo.html/#NotFound" />
+ </its:rules>
+ </head>
+ <body>
+ <msg id="NotFound">Cannot find {0} on {1}.</msg>
+ </body>
+</myRes>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/xml/locnote4xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/xml/locnote4xml.xml
new file mode 100644
index 00000000000..a98b30eba1b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/xml/locnote4xml.xml
@@ -0,0 +1,16 @@
+<dataFile>
+ <prolog>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:locNoteRule locNoteType="description" selector="//body/string/data"
+ locNoteRefPointer="../@noteFile" />
+ </its:rules>
+ </prolog>
+ <body>
+ <string id="FileNotFound" noteFile="Comments.html#FileNotFound">
+ <data>Cannot find the file {0}.</data>
+ </string>
+ <string id="DivByZero" noteFile="Comments.html#DivByZero">
+ <data>Invalid parameter.</data>
+ </string>
+ </body>
+</dataFile>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/xml/locnote5xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/xml/locnote5xml.xml
new file mode 100644
index 00000000000..dac3607a355
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/xml/locnote5xml.xml
@@ -0,0 +1,15 @@
+<msgList>
+ <head>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0"
+ xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="locnote5xmlrules.xml">
+ <its:locNoteRule selector="//msg[@id='1']/img/@alt" locNoteType="alert">
+ <its:locNote>Do not translate the word "Chobe"</its:locNote>
+ </its:locNoteRule>
+ </its:rules>
+ </head>
+ <body>
+ <msg id="1">This is a hippoptamus: <img src="hippo.png" alt="Hippo in the Chobe River"/>.</msg>
+ <msg id="2">This is an elephant: <img src="elephants.png" alt="Elephants taking a mud bath"/>.</msg>
+ <msg id="DisableInfo">The {0} has been disabled.</msg>
+ </body>
+</msgList>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/xml/locnote5xmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/xml/locnote5xmlrules.xml
new file mode 100644
index 00000000000..8eb7b345b48
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/xml/locnote5xmlrules.xml
@@ -0,0 +1,9 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:locNoteRule selector="//@alt" locNoteType="description">
+ <its:locNote>This text will be displayed over the image.</its:locNote>
+ </its:locNoteRule>
+ <its:locNoteRule locNoteType="alert" selector="//msg[@id='DisableInfo']">
+ <its:locNote>The variable {0} has three possible values: 'printer',
+ 'stacker' and 'stapler options'.</its:locNote>
+ </its:locNoteRule>
+</its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/xml/locnote6xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/xml/locnote6xml.xml
new file mode 100644
index 00000000000..2df88380c1c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/xml/locnote6xml.xml
@@ -0,0 +1,21 @@
+<msgList>
+ <head>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:locNoteRule selector="//@alt" locNoteType="description">
+ <its:locNote>This text will be displayed over the image.</its:locNote>
+ </its:locNoteRule>
+ <its:locNoteRule selector="//msg[@id='1']/img/@alt" locNoteType="alert">
+ <its:locNote>Do not translate the word "Chobe"</its:locNote>
+ </its:locNoteRule>
+ <its:locNoteRule locNoteType="alert" selector="//msg[@id='DisableInfo']">
+ <its:locNote>The variable {0} has three possible values: 'printer',
+ 'stacker' and 'stapler options'.</its:locNote>
+ </its:locNoteRule>
+ </its:rules>
+ </head>
+ <body>
+ <msg id="1">This is a hippoptamus: <img src="hippo.png" alt="Hippo in the Chobe River"/>.</msg>
+ <msg id="2">This is an elephant: <img src="elephants.png" alt="Elephants taking a mud bath"/>.</msg>
+ <msg id="DisableInfo">The {0} has been disabled.</msg>
+ </body>
+</msgList>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/xml/locnote7xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/xml/locnote7xml.xml
new file mode 100644
index 00000000000..65021f8b26a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/xml/locnote7xml.xml
@@ -0,0 +1,20 @@
+<Res>
+<prolog>
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+<its:translateRule selector="//msg/notes" translate="no"/>
+<its:locNoteRule locNoteType="description" selector="//msg/data" locNotePointer="../notes"/>
+</its:rules>
+</prolog>
+<body>
+<msg id="FileNotFound">
+<notes>
+Indicates that the resource file {0} could not be loaded.
+</notes>
+<data>Cannot find the file {0}.</data>
+</msg>
+<msg id="DivByZero">
+<notes>A division by 0 was going to be computed.</notes>
+<data>Invalid parameter.</data>
+</msg>
+</body>
+</Res>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/xml/locnote8xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/xml/locnote8xml.xml
new file mode 100644
index 00000000000..41049c9681e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/xml/locnote8xml.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0"?>
+<Res xmlns:its="http://www.w3.org/2005/11/its" its:version="2.0">
+ <body its:locNote="The variable {0} is the name of the host.">
+ <msg id="HostNotFound">
+ <data>Host {0} cannot be found.</data>
+ </msg>
+ <msg id="HostDisconnected">
+ <data>The connection with {0} has been lost.</data>
+ </msg>
+ <msg id="FileNotFound">
+ <data its:locNote="{0} is a filename" its:locNoteType="alert">{0} not found.</data>
+ </msg>
+ <msg id="CannotLog">
+ <data its:locNoteRef="myLocNotes.htm#CannotLog" its:locNoteType="alert">Cannot log with this username.</data>
+ </msg>
+ </body>
+</Res>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/xml/locnote9xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/xml/locnote9xml.xml
new file mode 100644
index 00000000000..c726ea1d229
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/localizationnote/xml/locnote9xml.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<Doc xmlns:its="http://www.w3.org/2005/11/its" its:version="2.0">
+ <body>
+ <p><its:span locNote="If possible keep the non-English terms in the translated version too">Everything started when
+ Zebulon discovered that he had a <its:span locNoteRef="http://en.wikipedia.org/wiki/Doppelganger">doppelgänger</its:span>
+ who was a <b>serious</b> baseball <its:span locNoteRef="http://en.wikipedia.org/wiki/Aficionado">aficionado</its:span>.</its:span></p>
+ </body>
+</Doc>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue10html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue10html.html
new file mode 100644
index 00000000000..e4957ac5161
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue10html.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html lang=en>
+ <head>
+ <script type="application/its+xml">
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml" version="2.0">
+ <its:param name="locQualityIssueParam">q1</its:param>
+ <its:locQualityIssueRule selector="//h:span[@id=$locQualityIssueParam]"
+ locQualityIssueType="typographical"
+ locQualityIssueComment="sentence without capitalization"
+ locQualityIssueEnabled="yes"/>
+ <its:locQualityIssueRule selector="//h:span[@id='q2']"
+ locQualityIssueType="misspelling"
+ locQualityIssueComment="should be 'Music can'"
+ locQualityIssueEnabled="yes"/>
+ </its:rules>
+ </script>
+ <meta charset=utf-8>
+ <title>Example</title>
+ </head>
+ <body>
+ <p>
+ <span id="q1">music </span> is an art form whose medium is sound and silence.
+ <span id="q2">Musci acn </span> take many different forms and is experienced by individuals in a range of social settings ranging from being alone to attending a large concert.
+ </p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue1html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue1html.html
new file mode 100644
index 00000000000..cc80dd325ac
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue1html.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset=utf-8>
+ <title>Example</title>
+ <link href="locqualityissue1htmlrules.xml" rel="its-rules"/>
+ </head>
+ <body>
+ <p>
+ <span id="q1">music </span> is an art form whose medium is sound and silence.
+ <span id="q2">Musci acn </span> take many different forms and is experienced by individuals in a range of social settings ranging from being alone to attending a large concert.
+ </p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue1htmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue1htmlrules.xml
new file mode 100644
index 00000000000..e4b3e203908
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue1htmlrules.xml
@@ -0,0 +1,10 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml" version="2.0">
+ <its:locQualityIssueRule selector="//h:span[@id='q1']"
+ locQualityIssueType="typographical"
+ locQualityIssueComment="sentence without capitalization"
+ locQualityIssueEnabled="yes"/>
+ <its:locQualityIssueRule selector="//h:span[@id='q2']"
+ locQualityIssueType="misspelling"
+ locQualityIssueComment="should be 'Music can'"
+ locQualityIssueEnabled="yes"/>
+</its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue2html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue2html.html
new file mode 100644
index 00000000000..7d80d4b26a8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue2html.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset=utf-8>
+ <title>Example</title>
+ <link href="locqualityissue2htmlrules.xml" rel="its-rules"/>
+ </head>
+ <body>
+ <p>
+ <span id="q1">music </span> is an art form whose medium is sound and silence.
+ <span id="q2">Musci acn </span> take many different forms and is experienced by individuals in a range of social settings ranging from being alone to attending a large concert.
+ </p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue2htmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue2htmlrules.xml
new file mode 100644
index 00000000000..1104dfd25dd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue2htmlrules.xml
@@ -0,0 +1,10 @@
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml" version="2.0">
+ <its:locQualityIssueRule selector="//h:span[@id='q1']"
+ locQualityIssueType="typographical"
+ locQualityIssueComment="sentence without capitalization"
+ locQualityIssueSeverity="50"/>
+ <its:locQualityIssueRule selector="//h:span[@id='q2']"
+ locQualityIssueType="misspelling"
+ locQualityIssueComment="should be 'Music can'"
+ locQualityIssueSeverity="75"/>
+ </its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue3html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue3html.html
new file mode 100644
index 00000000000..f9ba7d9180c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue3html.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset=utf-8>
+ <title>Example</title>
+ <link href="locqualityissue3htmlrules.xml" rel="its-rules"/>
+ </head>
+ <body>
+ <p>
+ <span id="q1">music </span> is an art form whose medium is sound and silence.
+ <span id="q2">Musci acn </span> take many different forms and is experienced by individuals in a range of social settings ranging from being alone to attending a large concert.
+ </p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue3htmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue3htmlrules.xml
new file mode 100644
index 00000000000..c4f45e00feb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue3htmlrules.xml
@@ -0,0 +1,12 @@
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml" version="2.0">
+ <its:locQualityIssueRule selector="//h:span[@id='q1']"
+ locQualityIssueType="typographical"
+ locQualityIssueComment="sentence without capitalization"
+ locQualityIssueSeverity="50"
+ locQualityIssueProfileRef="http://example.org/qaMovel/v1"/>
+ <its:locQualityIssueRule selector="//h:span[@id='q2']"
+ locQualityIssueType="misspelling"
+ locQualityIssueComment="should be 'Music can'"
+ locQualityIssueSeverity="75"
+ locQualityIssueProfileRef="http://example.org/qaMovel/v1"/>
+ </its:rules> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue4html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue4html.html
new file mode 100644
index 00000000000..82d2056436f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue4html.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8"/>
+ <title>Telharmonium 1897</title>
+ <style type="text/css">
+ [its-loc-quality-issue-type]{
+ background-color:yellow;
+ margin:2px;
+ }
+ [its-loc-quality-issue-severity = "100"]{
+ border: 2px solid red;
+ }
+ </style>
+ </head>
+ <body>
+ <h1>Telharmonium (1897)</h1>
+ <p>
+ <span
+ data-mytool-qacode="named_entity_not_found"
+ its-loc-quality-issue-type="inconsistent-entities"
+ >Christian Bale</span>(1867–1934) conceived of an instrument that could transmit its sound
+ from a power plant for hundreds of miles to listeners over telegraph wiring. Beginning in
+ 1889 the sound quality of regular telephone concerts was very poor on account of the buzzing
+ generated by carbon-granule microphones. As a result Cahill decided to set a new standard in
+ perfection of sound <span
+ its-loc-quality-issue-type="MiSSPeLLiNG">qaulity</span> with his instrument, a standard that would not only satisfy listeners but that
+ would overcome all the flaws of traditional instruments.</p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue5html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue5html.html
new file mode 100644
index 00000000000..951cfddb7eb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue5html.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8"/>
+ <title>Telharmonium 1897</title>
+ <style type="text/css">
+ [its-loc-quality-issue-type]{
+ background-color:yellow;
+ margin:2px;
+ }
+ [its-loc-quality-issue-severity = "100"]{
+ border: 2px solid red;
+ }
+ </style>
+ </head>
+ <body>
+ <h1>Telharmonium (1897)</h1>
+ <p>
+ <span
+ data-mytool-qacode="named_entity_not_found"
+ its-loc-quality-issue-type="inconsistent-entities"
+ its-loc-quality-issue-comment="should be Thomas Cahill.">Christian Bale</span>(1867–1934) conceived of an instrument that could transmit its sound
+ from a power plant for hundreds of miles to listeners over telegraph wiring. Beginning in
+ 1889 the sound quality of regular telephone concerts was very poor on account of the buzzing
+ generated by carbon-granule microphones. As a result Cahill decided to set a new standard in
+ perfection of sound <span
+ its-loc-quality-issue-type="misspelling"
+ its-loc-quality-issue-comment="should be 'quality'">qulaity</span> with his instrument, a standard that would not only satisfy listeners but that
+ would overcome all the flaws of traditional instruments.</p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue6html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue6html.html
new file mode 100644
index 00000000000..ac35ca5ef2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue6html.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8"/>
+ <title>Telharmonium 1897</title>
+ <style type="text/css">
+ [its-loc-quality-issue-type]{
+ background-color:yellow;
+ margin:2px;
+ }
+ [its-loc-quality-issue-severity = "100"]{
+ border: 2px solid red;
+ }
+ </style>
+ </head>
+ <body>
+ <h1>Telharmonium (1897)</h1>
+ <p>
+ <span
+ data-mytool-qacode="named_entity_not_found"
+ its-loc-quality-issue-type="inconsistent-entities"
+ its-loc-quality-issue-comment="should be Thomas Cahill."
+ its-loc-quality-issue-profile-ref="http://example.org/qaMovel/v1"
+ its-loc-quality-issue-severity="100"
+ its-loc-quality-issue-enabled="yes">Christian Bale</span>(1867–1934) conceived of an instrument that could transmit its sound
+ from a power plant for hundreds of miles to listeners over telegraph wiring. Beginning in
+ 1889 the sound quality of regular telephone concerts was very poor on account of the buzzing
+ generated by carbon-granule microphones. As a result Cahill decided to set a new standard in
+ perfection of sound <span
+ its-loc-quality-issue-type="misspelling"
+ its-loc-quality-issue-comment="should be 'quality'"
+ its-loc-quality-issue-profile-ref="grammar"
+ its-loc-quality-issue-severity="50"
+ its-loc-quality-issue-enabled="no">qulaity</span> with his instrument, a standard that would not only satisfy listeners but that
+ would overcome all the flaws of traditional instruments.</p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue7html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue7html.html
new file mode 100644
index 00000000000..01beb027e71
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue7html.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8"/>
+ <title>Test</title>
+ <script type="application/its+xml" id="lq1">
+ <its:locQualityIssues xml:id="lq1" xmlns:its="http://www.w3.org/2005/11/its">
+ <its:locQualityIssue
+ locQualityIssueType="misspelling"
+ locQualityIssueComment="'c'es' is unknown. Could be 'c'est'"
+ locQualityIssueSeverity="50"/>
+ </its:locQualityIssues>
+ </script>
+ <style type="text/css">.qaissue { background-color: yellow; } </style>
+ </head>
+ <body>
+ <p>
+ <span its-loc-quality-issues-ref="#lq1">c'es</span> pourquoi il n'était pas coupable</p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue8html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue8html.html
new file mode 100644
index 00000000000..1af8d79867a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue8html.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8"/>
+ <title>Example</title>
+ <link href="locqualityissue8htmlrules.xml" rel="its-rules"/>
+ </head>
+ <body>
+ <p>
+ <span id="q1">music </span> is an art form whose medium is sound and silence.
+ <span id="q2">Musci acn </span> take many different forms and is experienced by individuals in a range of social settings ranging from being alone to attending a large concert.
+ </p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue8htmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue8htmlrules.xml
new file mode 100644
index 00000000000..b6b7ae996eb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue8htmlrules.xml
@@ -0,0 +1,13 @@
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml" version="2.0">
+ <its:param name="locQualityIssueParam">q1</its:param>
+ <its:locQualityIssueRule selector="//h:span[@id=$locQualityIssueParam]"
+ locQualityIssueType="typographical"
+ locQualityIssueComment="Sentence without capitalization"
+ locQualityIssueSeverity="50"
+ locQualityIssueProfileRef="http://example.org/qaMovel/v1"/>
+ <its:locQualityIssueRule selector="//h:span[@id='q2']"
+ locQualityIssueType="misspelling"
+ locQualityIssueComment="should be 'Music can'"
+ locQualityIssueSeverity="75"
+ locQualityIssueProfileRef="http://example.org/qaMovel/v1"/>
+ </its:rules> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue9html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue9html.html
new file mode 100644
index 00000000000..da42fa05dc1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue9html.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8"/>
+ <title>Test</title>
+ </head>
+ <body>
+ <p>
+ <span its-loc-quality-issues-ref="locqualityissue9htmlstandoff.xml#lq1">c'es</span> pourquoi il n'était pas coupable</p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue9htmlstandoff.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue9htmlstandoff.xml
new file mode 100644
index 00000000000..d81222e66ee
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/html/locqualityissue9htmlstandoff.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" ?>
+<someDataFile xmlns:its="http://www.w3.org/2005/11/its" its:version="2.0">
+<its:locQualityIssues xml:id="lq1">
+ <its:locQualityIssue
+ locQualityIssueType="misspelling"
+ locQualityIssueComment="'c'es' is unknown. Could be 'c'est'"
+ locQualityIssueSeverity="50"/>
+ <its:locQualityIssue
+ locQualityIssueType="grammar"
+ locQualityIssueComment="Missing capital on the first word of a sentence."
+ locQualityIssueSeverity="30"/>
+</its:locQualityIssues>
+</someDataFile> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue10xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue10xml.xml
new file mode 100644
index 00000000000..c1d164462bc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue10xml.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<doc xmlns:its="http://www.w3.org/2005/11/its" its:version="2.0">
+<para><its:span locQualityIssueComment="Sentence without capitalization" locQualityIssueSeverity="50" locQualityIssueProfileRef="http://example.org/qaMovel/v1">transport</its:span> or transportation is the movement of people, animals and goods from one location to another.Modes of <its:span locQualityIssueComment="should be 'transport include'" locQualityIssueSeverity="75" locQualityIssueProfileRef="http://example.org/qaMovel/v1">tranport inc.</its:span> air, rail, road, water, cable, pipeline, and space.</para>
+</doc>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue11xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue11xml.xml
new file mode 100644
index 00000000000..399e6671319
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue11xml.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0"?>
+<doc>
+ <header>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:param name="locqualityissueParam">q1</its:param>
+ <its:locQualityIssueRule selector="//span[@id=$locqualityissueParam]"
+ locQualityIssueComment="Sentence without capitalization"
+ locQualityIssueSeverity="50"
+ locQualityIssueProfileRef="http://example.org/qaMovel/v1"/>
+ <its:locQualityIssueRule selector="//span[@id='q2']"
+ locQualityIssueComment="should be 'transport include'"
+ locQualityIssueSeverity="75"
+ locQualityIssueProfileRef="http://example.org/qaMovel/v1"/>
+ </its:rules>
+ </header>
+ <para>
+ <span id="q1">transport</span> or transportation is the movement of people, animals and goods from one location to another.
+ Modes of <span id="q2">tranport inc.</span> air, rail, road, water, cable, pipeline, and space.
+</para>
+</doc>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue12xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue12xml.xml
new file mode 100644
index 00000000000..1574e8c7708
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue12xml.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0"?>
+<doc>
+ <header>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:xlink="http://www.w3.org/1999/xlink" version="2.0" xlink:type="simple" xlink:href="locqualityissue12xmlrules.xml"/>
+ </header>
+ <para>
+ <span id="q1">transport</span> or transportation is the movement of people, animals and goods from one location to another.
+ Modes of <span id="q2">tranport inc.</span> air, rail, road, water, cable, pipeline, and space.
+</para>
+</doc>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue12xmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue12xmlrules.xml
new file mode 100644
index 00000000000..dc42a43b4af
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue12xmlrules.xml
@@ -0,0 +1,11 @@
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:param name="locqualityissueParam">q1</its:param>
+ <its:locQualityIssueRule selector="//span[@id=$locqualityissueParam]"
+ locQualityIssueComment="Sentence without capitalization"
+ locQualityIssueSeverity="50"
+ locQualityIssueProfileRef="http://example.org/qaMovel/v1"/>
+ <its:locQualityIssueRule selector="//span[@id='q2']"
+ locQualityIssueComment="should be 'transport include'"
+ locQualityIssueSeverity="75"
+ locQualityIssueProfileRef="http://example.org/qaMovel/v1"/>
+ </its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue13xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue13xml.xml
new file mode 100644
index 00000000000..b6722c4992f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue13xml.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0"?>
+<doc xmlns:its="http://www.w3.org/2005/11/its" its:version="2.0">
+ <file>
+ <header>
+ <its:rules version="2.0">
+ <its:locQualityIssueRule selector="//mrk[@type='x-itslq']"
+ locQualityIssuesRefPointer="@ref"/>
+ </its:rules>
+ </header>
+ <unit id="1">
+ <segment>
+ <source>This is the content</source>
+ <target><mrk type="x-itslq" ref="#lq1">c'es</mrk> le contenu</target>
+ </segment>
+ <its:locQualityIssues xml:id="lq1">
+ <its:locQualityIssue
+ locQualityIssueComment="'c'es' is unknown. Could be 'c'est'"
+ locQualityIssueSeverity="75"
+ locQualityIssueProfileRef="http://example.org/qaMovel/v1"
+ locQualityIssueEnabled="yes"/>
+ </its:locQualityIssues>
+ </unit>
+ </file>
+</doc>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue1xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue1xml.xml
new file mode 100644
index 00000000000..ee70d1d8bbc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue1xml.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0"?>
+<doc>
+ <header>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:locQualityIssueRule selector="//span[@id='q1']"
+ locQualityIssueType="typographical"/>
+ <its:locQualityIssueRule selector="//span[@id='q2']"
+ locQualityIssueType="misspelling"/>
+ </its:rules>
+ </header>
+ <para>
+ <span id="q1">transport</span> or transportation is the movement of people, animals and goods from one location to another.
+ Modes of <span id="q2">tranport inc.</span> air, rail, road, water, cable, pipeline, and space.
+</para>
+</doc>
+
+
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue2xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue2xml.xml
new file mode 100644
index 00000000000..5be4462920e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue2xml.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0"?>
+<doc>
+ <header>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:locQualityIssueRule selector="//span[@id='q1']"
+ locQualityIssueComment="Sentence without capitalization"
+ locQualityIssueSeverity="50"/>
+ <its:locQualityIssueRule selector="//span[@id='q2']"
+ locQualityIssueComment="should be 'transport include'"
+ locQualityIssueSeverity="75"/>
+ </its:rules>
+ </header>
+ <para>
+ <span id="q1">transport</span> or transportation is the movement of people, animals and goods from one location to another.
+ Modes of <span id="q2">tranport inc.</span> air, rail, road, water, cable, pipeline, and space.
+</para>
+</doc>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue3xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue3xml.xml
new file mode 100644
index 00000000000..a51fbc0a355
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue3xml.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0"?>
+<doc>
+ <header>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:locQualityIssueRule selector="//span[@id='q1']"
+ locQualityIssueType="typographical"
+ locQualityIssueSeverity="50"
+ locQualityIssueProfileRef="http://example.org/qaMovel/v1"
+ locQualityIssueEnabled="yes"/>
+ <its:locQualityIssueRule selector="//span[@id='q2']"
+ locQualityIssueType="misspelling"
+ locQualityIssueSeverity="75"
+ locQualityIssueProfileRef="http://example.org/qaMovel/v1"
+ locQualityIssueEnabled="yes"/>
+ </its:rules>
+ </header>
+ <para>
+ <span id="q1">transport</span> or transportation is the movement of people, animals and goods from one location to another.
+ Modes of <span id="q2">tranport inc.</span> air, rail, road, water, cable, pipeline, and space.
+</para>
+</doc>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue4xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue4xml.xml
new file mode 100644
index 00000000000..d50f903baee
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue4xml.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0"?>
+<doc xmlns:its="http://www.w3.org/2005/11/its" its:version="2.0">
+ <header>
+ <its:rules version="2.0">
+ <its:locQualityIssueRule selector="//span[@id='q1']"
+ locQualityIssuesRefPointer="./@issues"/>
+ <its:locQualityIssueRule selector="//span[@id='q2']"
+ locQualityIssueType="misspelling"
+ locQualityIssueSeverity="75"
+ locQualityIssueProfileRef="http://example.org/qaMovel/v1"
+ locQualityIssueEnabled="yes"/>
+ </its:rules>
+ </header>
+ <para>
+ <span id="q1" issues="#id1234">transport</span> or transportation is the movement of people, animals and goods from one location to another.
+ Modes of <span id="q2">tranport inc.</span> air, rail, road, water, cable, pipeline, and space.
+ </para>
+ <its:locQualityIssues xml:id="id1234">
+ <its:locQualityIssue locQualityIssueType="typographical"
+ locQualityIssueSeverity="50"
+ locQualityIssueProfileRef="http://example.org/qaMovel/v1"
+ locQualityIssueEnabled="no"/>
+ </its:locQualityIssues>
+</doc>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue5xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue5xml.xml
new file mode 100644
index 00000000000..b5fcceabf80
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue5xml.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0"?>
+<doc>
+ <header>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="2.0" xlink:type="simple" xlink:href="locqualityissue5xmlrules.xml"/>
+ </header>
+ <para>
+ <span id="q1">transport</span> or transportation is the movement of people, animals and goods from one location to another.
+ Modes of <span id="q2">tranport inc.</span> air, rail, road, water, cable, pipeline, and space.
+</para>
+</doc>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue5xmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue5xmlrules.xml
new file mode 100644
index 00000000000..a778ffc9bde
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue5xmlrules.xml
@@ -0,0 +1,10 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:locQualityIssueRule selector="//span[@id='q1']"
+ locQualityIssueType="typographical"
+ locQualityIssueSeverity="50"
+ locQualityIssueProfileRef="http://example.org/qaMovel/v1"/>
+ <its:locQualityIssueRule selector="//span[@id='q2']"
+ locQualityIssueComment="should be 'transport include'"
+ locQualityIssueSeverity="75"
+ locQualityIssueProfileRef="http://example.org/qaMovel/v1"/>
+ </its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue6xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue6xml.xml
new file mode 100644
index 00000000000..e8c41ebfc7d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue6xml.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<doc xmlns:its="http://www.w3.org/2005/11/its" its:version="2.0">
+ <para><span its:locQualityIssueType="typographical">transport</span> or transportation is the movement of people, animals and goods from one location to another.Modes of <span its:locQualityIssueType="misspelling">tranport inc.</span> air, rail, road, water, cable, pipeline, and space.</para>
+</doc>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue7xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue7xml.xml
new file mode 100644
index 00000000000..e81339948e1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue7xml.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<doc xmlns:its="http://www.w3.org/2005/11/its" its:version="2.0">
+ <para><span its:locQualityIssueComment="Sentence without capitalization">transport</span> or transportation is the movement of people, animals and goods from one location to another.Modes of <span its:locQualityIssueComment="should be 'transport include'">tranport inc.</span> air, rail, road, water, cable, pipeline, and space.</para>
+</doc>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue8xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue8xml.xml
new file mode 100644
index 00000000000..2fffc914869
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue8xml.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<doc xmlns:its="http://www.w3.org/2005/11/its" its:version="2.0">
+<para><span its:locQualityIssueComment="Sentence without capitalization" its:locQualityIssueSeverity="50">transport</span> or transportation is the movement of people, animals and goods from one location to another.Modes of <span its:locQualityIssueComment="should be 'transport include'" its:locQualityIssueSeverity="75">tranport inc.</span> air, rail, road, water, cable, pipeline, and space.</para>
+</doc>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue9xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue9xml.xml
new file mode 100644
index 00000000000..fa4a1088510
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityissue/xml/locqualityissue9xml.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<doc xmlns:its="http://www.w3.org/2005/11/its" its:version="2.0">
+<para><span its:locQualityIssueComment="Sentence without capitalization" its:locQualityIssueSeverity="50" its:locQualityIssueProfileRef="http://example.org/qaMovel/v1">transport</span> or transportation is the movement of people, animals and goods from one location to another.Modes of <span its:locQualityIssueComment="should be 'transport include'" its:locQualityIssueSeverity="75" its:locQualityIssueProfileRef="http://example.org/qaMovel/v1">tranport inc.</span> air, rail, road, water, cable, pipeline, and space.</para>
+</doc>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityrating/html/locqualityrating1html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityrating/html/locqualityrating1html.html
new file mode 100644
index 00000000000..668b3323e1a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityrating/html/locqualityrating1html.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html
+ its-loc-quality-rating-profile-ref="http://example.org/qamodel/v13"
+ its-loc-quality-rating-score="100"
+ its-loc-quality-rating-score-threshold="95"
+ lang="en">
+ <head>
+ <meta charset=utf-8>
+ <title>Rikki-tikki-tavi</title>
+ </head>
+ <body>
+ <p>This is the story of the great war that Rikki-tikki-tavi fought single-handed,
+ through the bath-rooms of the big bungalow in Segowlee cantonment. Darzee, the
+ Tailorbird, helped him, and Chuchundra, the musk-rat, who never comes out into
+ the middle of the floor, but always creeps round by the wall, gave him advice,
+ but Rikki-tikki did the real fighting.</p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityrating/html/locqualityrating2html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityrating/html/locqualityrating2html.html
new file mode 100644
index 00000000000..df7ff857371
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityrating/html/locqualityrating2html.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html
+ its-loc-quality-rating-profile-ref="http://example.org/qamodel/v13"
+ its-loc-quality-rating-vote="-1"
+ its-loc-quality-rating-vote-threshold="10"
+ lang="en">
+ <head>
+ <meta charset=utf-8>
+ <title>Rikki-tikki-tavi</title>
+ </head>
+ <body>
+ <p>This is the story of the great war that Rikki-tikki-tavi fought single-handed,
+ through the bath-rooms of the big bungalow in Segowlee cantonment. Darzee, the
+ Tailorbird, helped him, and Chuchundra, the musk-rat, who never comes out into
+ the middle of the floor, but always creeps round by the wall, gave him advice,
+ but Rikki-tikki did the real fighting.</p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityrating/xml/locqualityrating1xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityrating/xml/locqualityrating1xml.xml
new file mode 100644
index 00000000000..e08b1d0bf94
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityrating/xml/locqualityrating1xml.xml
@@ -0,0 +1,11 @@
+<doc xmlns:its="http://www.w3.org/2005/11/its" its:version="2.0"
+ its:locQualityRatingScore="100"
+ its:locQualityRatingScoreThreshold="95"
+ its:locQualityRatingProfileRef="http://example.org/qaModel/v13">
+ <title>The Adventures of Tom Sawyer</title>
+ <para>He got home pretty late that night, and when he climbed cautiously in at
+ the window, he uncovered an ambuscade, in the person of his aunt; and when
+ she saw the state his clothes were in her resolution to turn his Saturday
+ holiday into captivity at hard labor became adamantine in its
+ firmness.</para>
+</doc>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityrating/xml/locqualityrating2xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityrating/xml/locqualityrating2xml.xml
new file mode 100644
index 00000000000..437fdd26f2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityrating/xml/locqualityrating2xml.xml
@@ -0,0 +1,11 @@
+<doc xmlns:its="http://www.w3.org/2005/11/its" its:version="2.0"
+ its:locQualityRatingVote="-1"
+ its:locQualityRatingVoteThreshold="10"
+ its:locQualityRatingProfileRef="http://example.org/qaModel/v13">
+ <title>The Adventures of Tom Sawyer</title>
+ <para>He got home pretty late that night, and when he climbed cautiously in at
+ the window, he uncovered an ambuscade, in the person of his aunt; and when
+ she saw the state his clothes were in her resolution to turn his Saturday
+ holiday into captivity at hard labor became adamantine in its
+ firmness.</para>
+</doc>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityrating/xml/locqualityrating3xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityrating/xml/locqualityrating3xml.xml
new file mode 100644
index 00000000000..28b60154bed
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityrating/xml/locqualityrating3xml.xml
@@ -0,0 +1,11 @@
+<doc xmlns:its="http://www.w3.org/2005/11/its" its:version="2.0">
+ <title>The Adventures of Tom Sawyer</title>
+ <its:span locQualityRatingScore="100"
+ locQualityRatingScoreThreshold="95"
+ locQualityRatingProfileRef="http://example.org/qaModel/v13">
+ <para>He got home pretty late that night, and when he climbed cautiously in at
+ the window, he uncovered an ambuscade, in the person of his aunt; and when
+ she saw the state his clothes were in her resolution to turn his Saturday
+ holiday into captivity at hard labor became adamantine in its
+ firmness.</para></its:span>
+</doc>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityrating/xml/locqualityrating4xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityrating/xml/locqualityrating4xml.xml
new file mode 100644
index 00000000000..101566abb73
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/locqualityrating/xml/locqualityrating4xml.xml
@@ -0,0 +1,10 @@
+<doc xmlns:its="http://www.w3.org/2005/11/its" its:version="2.0">
+ <title>The Adventures of Tom Sawyer</title>
+ <its:span locQualityRatingVote="-1"
+ locQualityRatingVoteThreshold="10"
+ locQualityRatingProfileRef="http://example.org/qaModel/v13"><para>He got home pretty late that night, and when he climbed cautiously in at
+ the window, he uncovered an ambuscade, in the person of his aunt; and when
+ she saw the state his clothes were in her resolution to turn his Saturday
+ holiday into captivity at hard labor became adamantine in its
+ firmness.</para></its:span>
+</doc>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/html/mtconfidence1html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/html/mtconfidence1html.html
new file mode 100644
index 00000000000..91f6c3b7391
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/html/mtconfidence1html.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8"/>
+ <title>Sentences about European capitals.</title>
+ </head>
+ <body>
+ <p>
+ <span its-mt-confidence="0.8982" its-annotators-ref="mt-confidence|file:///tools.xml#T1"> Dublin is the capital of Ireland.</span>
+ <span its-mt-confidence="0.8536" its-annotators-ref="mt-confidence|file:///tools.xml#T2"> The capital of the Czech Republic is Prague.</span>
+ <span its-mt-confidence="0.7982" its-annotators-ref="mt-confidence|file:///tools.xml#T3">Madrid is the capital of Spain.</span>
+ <span its-mt-confidence="0.9982" its-annotators-ref="mt-confidence|file:///tools.xml#T4">Berlin is the capital of Germany.</span>
+ </p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/html/mtconfidence2html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/html/mtconfidence2html.html
new file mode 100644
index 00000000000..7a57318c01b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/html/mtconfidence2html.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8"/>
+ <title>Sentences about Dublin and Prague MTed from Czech with mtConfidence locally.</title>
+ <link href="mtconfidence2htmlrules.xml" rel="its-rules"/>
+ </head>
+ <body its-annotators-ref="mt-confidence|file:///tools.xml#T0">
+ <p>
+ <span its-annotators-ref="mt-confidence|file:///tools.xml#T1"> Dublin is the capital of Ireland.</span>
+ <span its-annotators-ref="mt-confidence|file:///tools.xml#T2"> The capital of the Czech Republic is Prague.</span>
+ <span its-annotators-ref="mt-confidence|file:///tools.xml#T3">Madrid is the capital of Spain.</span>
+ <span its-annotators-ref="mt-confidence|file:///tools.xml#T4">Berlin is the capital of Germany.</span>
+ </p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/html/mtconfidence2htmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/html/mtconfidence2htmlrules.xml
new file mode 100644
index 00000000000..19cb15483f0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/html/mtconfidence2htmlrules.xml
@@ -0,0 +1,3 @@
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml" version="2.0">
+ <its:mtConfidenceRule selector="/h:html/h:body/h:p" mtConfidence="0.8982"/>
+ </its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/html/mtconfidence3html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/html/mtconfidence3html.html
new file mode 100644
index 00000000000..c0f99ac8f0e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/html/mtconfidence3html.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8"/>
+ <title>Sentences about Dublin and Prague MTed from Czech with mtConfidence locally.</title>
+ <link href="mtconfidence3htmlrules.xml" rel="its-rules"/>
+ </head>
+ <body>
+ <p>
+ <span its-annotators-ref="mt-confidence|file:///tools.xml#T1" id="ireland"> Dublin is the capital of Ireland.</span>
+ <span id="czech"> The capital of the Czech Republic is Prague.</span>
+ <span id="germany">Berlin is the capital of Germany.</span>
+ <span id="london">London is the capital of England</span>
+ </p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/html/mtconfidence3htmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/html/mtconfidence3htmlrules.xml
new file mode 100644
index 00000000000..f6e20179a11
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/html/mtconfidence3htmlrules.xml
@@ -0,0 +1,5 @@
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml" version="2.0">
+ <its:param name="mtParam">ireland</its:param>
+ <its:mtConfidenceRule selector="/h:html/h:body/h:p/h:span[@id=$mtParam]"
+ mtConfidence="0.8982"/>
+ </its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/html/mtconfidence4html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/html/mtconfidence4html.html
new file mode 100644
index 00000000000..580aee97ca2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/html/mtconfidence4html.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html lang=en>
+ <head>
+ <meta charset=utf-8>
+ <title>Example of MT Confidence with annotator references.</title>
+ <link href="mtconfidence4htmlrules.xml" rel="its-rules"/>
+ </head>
+ <body its-annotators-ref="mt-confidence|file:///tools.xml#T1" >
+ <p its-annotators-ref="text-analysis|file:///tools.xml#T2" >
+ <span id="ireland">Dublin is the capital city of Ireland and has the 50th biggest population density in Europe.</span>
+ <span id="spain">Madrid is the capital of Spain.</span>
+ <span its-annotators-ref="mt-confidence|file:///tools.xml#T3" id="germany">Berlin is the capital of Germany.</span>
+ <span id="england">London is the capital of England</span>
+ </p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/html/mtconfidence4htmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/html/mtconfidence4htmlrules.xml
new file mode 100644
index 00000000000..151a0ff17d8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/html/mtconfidence4htmlrules.xml
@@ -0,0 +1,4 @@
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml" version="2.0">
+ <its:mtConfidenceRule selector="/h:html/h:body/h:p/h:span[@id='ireland']"
+ mtConfidence="0.8982"/>
+ </its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/html/mtconfidence5html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/html/mtconfidence5html.html
new file mode 100644
index 00000000000..fe343db0be0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/html/mtconfidence5html.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html lang=en>
+ <head>
+ <meta charset=utf-8>
+ <title>Sentences about European capitals.</title>
+ <script type="application/its+xml">
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml" version="2.0">
+ <its:param name="mtParam">ireland</its:param>
+ <its:mtConfidenceRule selector="/h:html/h:body/h:p/h:span[@id=$mtParam]" mtConfidence="0.8982"/>
+ </its:rules>
+ </script>
+ </head>
+ <body>
+ <p its-annotators-ref="mt-confidence|file:///tools.xml#T1">
+ <span id="ireland"> Dublin is the capital of Ireland.</span>
+ <span> The capital of the Czech Republic is Prague.</span>
+ <span>Madrid is the capital of Spain.</span>
+ <span>Berlin is the capital of Germany.</span>
+ </p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/xml/mtconfidence1xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/xml/mtconfidence1xml.xml
new file mode 100644
index 00000000000..c3cdedad0ab
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/xml/mtconfidence1xml.xml
@@ -0,0 +1,22 @@
+<text xmlns:its="http://www.w3.org/2005/11/its">
+<head>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:mtConfidenceRule selector="/text/body/p/span[@id='ireland']"
+ mtConfidence="0.6982"/>
+ <its:mtConfidenceRule selector="/text/body/p/span[@id='england']"
+ mtConfidence="0.7982"/>
+ <its:mtConfidenceRule selector="/text/body/p/span[@id='spain']"
+ mtConfidence="0.8982"/>
+ <its:mtConfidenceRule selector="/text/body/p/span[@id='germany']"
+ mtConfidence="0.8982"/>
+ </its:rules>
+</head>
+ <body>
+ <p>
+ <span its:annotatorsRef="mt-confidence|file:///tools.xml#T1" id="ireland">Dublin is the capital city of Ireland and has the 50th biggest population density in Europe.</span>
+ <span its:annotatorsRef="mt-confidence|file:///tools.xml#T2" id="spain">Madrid is the capital of Spain.</span>
+ <span its:annotatorsRef="mt-confidence|file:///tools.xml#T3" id="germany">Berlin is the capital of Germany.</span>
+ <span its:annotatorsRef="mt-confidence|file:///tools.xml#T4" id="england">London is the capital of England</span>
+ </p>
+ </body>
+</text>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/xml/mtconfidence2xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/xml/mtconfidence2xml.xml
new file mode 100644
index 00000000000..2f494163771
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/xml/mtconfidence2xml.xml
@@ -0,0 +1,13 @@
+<text xmlns:its="http://www.w3.org/2005/11/its">
+<head>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:xlink="http://www.w3.org/1999/xlink" version="2.0" xlink:type="simple" xlink:href="mtconfidence2xmlrules.xml"/>
+</head>
+ <body>
+ <p>
+ <span its:annotatorsRef="mt-confidence|file:///tools.xml#T1" id="ireland">Dublin is the capital city of Ireland and has the 50th biggest population density in Europe.</span>
+ <span its:annotatorsRef="mt-confidence|file:///tools.xml#T2" id="spain">Madrid is the capital of Spain.</span>
+ <span its:annotatorsRef="mt-confidence|file:///tools.xml#T3" id="germany">Berlin is the capital of Germany.</span>
+ <span its:annotatorsRef="mt-confidence|file:///tools.xml#T4" id="england">London is the capital of England</span>
+ </p>
+ </body>
+</text>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/xml/mtconfidence2xmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/xml/mtconfidence2xmlrules.xml
new file mode 100644
index 00000000000..36b0450b96d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/xml/mtconfidence2xmlrules.xml
@@ -0,0 +1,10 @@
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:mtConfidenceRule selector="/text/body/p/span[@id='ireland']"
+ mtConfidence="0.6982"/>
+ <its:mtConfidenceRule selector="/text/body/p/span[@id='england']"
+ mtConfidence="0.7982"/>
+ <its:mtConfidenceRule selector="/text/body/p/span[@id='spain']"
+ mtConfidence="0.8982"/>
+ <its:mtConfidenceRule selector="/text/body/p/span[@id='germany']"
+ mtConfidence="0.5982"/>
+ </its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/xml/mtconfidence3xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/xml/mtconfidence3xml.xml
new file mode 100644
index 00000000000..31be4342c91
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/xml/mtconfidence3xml.xml
@@ -0,0 +1,10 @@
+<text xmlns:its="http://www.w3.org/2005/11/its" its:version="2.0">
+ <body>
+ <p>
+ <span its:annotatorsRef="mt-confidence|file:///tools.xml#T1" its:mtConfidence="0.6982">Dublin is the capital city of Ireland and has the 50th biggest population density in Europe.</span>
+ <span its:annotatorsRef="mt-confidence|file:///tools.xml#T2" its:mtConfidence="0.7982">Madrid is the capital of Spain.</span>
+ <span its:annotatorsRef="mt-confidence|file:///tools.xml#T3" its:mtConfidence="0.9982">Berlin is the capital of Germany.</span>
+ <span its:annotatorsRef="mt-confidence|file:///tools.xml#T4" its:mtConfidence="0.6982">London is the capital of England</span>
+ </p>
+ </body>
+</text>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/xml/mtconfidence4xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/xml/mtconfidence4xml.xml
new file mode 100644
index 00000000000..04efe69da15
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/xml/mtconfidence4xml.xml
@@ -0,0 +1,10 @@
+<text xmlns:its="http://www.w3.org/2005/11/its" its:version="2.0">
+ <body>
+ <p>
+ <its:span annotatorsRef="mt-confidence|file:///tools.xml#T1" mtConfidence="0.9982">Dublin is the capital city of Ireland.</its:span>
+ <its:span annotatorsRef="mt-confidence|file:///tools.xml#T2" mtConfidence="0.8982">Madrid is the capital of Spain.</its:span>
+ <its:span annotatorsRef="mt-confidence|file:///tools.xml#T3" mtConfidence="0.7982">Berlin is the capital of Germany.</its:span>
+ <its:span annotatorsRef="mt-confidence|file:///tools.xml#T4" mtConfidence="0.6982">London is the capital of England</its:span>
+ </p>
+ </body>
+</text>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/xml/mtconfidence5xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/xml/mtconfidence5xml.xml
new file mode 100644
index 00000000000..3e8484cec6d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/xml/mtconfidence5xml.xml
@@ -0,0 +1,13 @@
+<text xmlns:its="http://www.w3.org/2005/11/its">
+<head>
+ <its:rules xmlns:xlink="http://www.w3.org/1999/xlink" version="2.0" xlink:type="simple" xlink:href="mtconfidence5xmlrules.xml"/>
+</head>
+ <body>
+ <p>
+ <span its:annotatorsRef="mt-confidence|file:///tools.xml#T1" id="ireland">Dublin is the capital city of Ireland and has the 50th biggest population density in Europe.</span>
+ <span its:annotatorsRef="mt-confidence|file:///tools.xml#T2" id="spain">Madrid is the capital of Spain.</span>
+ <span its:annotatorsRef="mt-confidence|file:///tools.xml#T3" id="germany">Berlin is the capital of Germany.</span>
+ <span its:annotatorsRef="mt-confidence|file:///tools.xml#T4" id="england">London is the capital of England</span>
+ </p>
+ </body>
+</text>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/xml/mtconfidence5xmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/xml/mtconfidence5xmlrules.xml
new file mode 100644
index 00000000000..296ff363ace
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/xml/mtconfidence5xmlrules.xml
@@ -0,0 +1,4 @@
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:param name="mtconfidenceParam">ireland</its:param>
+ <its:mtConfidenceRule selector="//span[@id=$mtconfidenceParam]" mtConfidence="0.6982"/>
+ </its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/xml/mtconfidence6xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/xml/mtconfidence6xml.xml
new file mode 100644
index 00000000000..c846e6c7c00
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/xml/mtconfidence6xml.xml
@@ -0,0 +1,16 @@
+<text xmlns:its="http://www.w3.org/2005/11/its">
+<head>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:param name="mtconfidenceParam">ireland</its:param>
+ <its:mtConfidenceRule selector="//span[@id=$mtconfidenceParam]" mtConfidence="0.6982"/>
+ </its:rules>
+</head>
+ <body>
+ <p>
+ <span its:annotatorsRef="mt-confidence|file:///tools.xml#T1" id="ireland">Dublin is the capital city of Ireland and has the 50th biggest population density in Europe.</span>
+ <span its:annotatorsRef="mt-confidence|file:///tools.xml#T2" id="spain">Madrid is the capital of Spain.</span>
+ <span its:annotatorsRef="mt-confidence|file:///tools.xml#T3" id="germany">Berlin is the capital of Germany.</span>
+ <span its:annotatorsRef="mt-confidence|file:///tools.xml#T4" id="england">London is the capital of England</span>
+ </p>
+ </body>
+</text>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/xml/mtconfidence7xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/xml/mtconfidence7xml.xml
new file mode 100644
index 00000000000..b0d545b8cfd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/mtconfidence/xml/mtconfidence7xml.xml
@@ -0,0 +1,16 @@
+<text xmlns:its="http://www.w3.org/2005/11/its">
+<head>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:mtConfidenceRule selector="/text/body/p/span[@id='germany']"
+ mtConfidence="0.8982"/>
+ </its:rules>
+</head>
+<body its:annotatorsRef="mt-confidence|file:///tools.xml#T1" >
+ <p its:annotatorsRef="text-analysis|file:///tools.xml#T2" >
+ <span id="ireland">Dublin is the capital city of Ireland and has the 50th biggest population density in Europe.</span>
+ <span id="spain">Madrid is the capital of Spain.</span>
+ <span its:annotatorsRef="mt-confidence|file:///tools.xml#T3" id="germany">Berlin is the capital of Germany.</span>
+ <span id="england">London is the capital of England</span>
+ </p>
+</body>
+</text> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/preservespace/xml/preservespace1xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/preservespace/xml/preservespace1xml.xml
new file mode 100644
index 00000000000..16330a2ee5e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/preservespace/xml/preservespace1xml.xml
@@ -0,0 +1,13 @@
+<book xmlns:its="http://www.w3.org/2005/11/its" its:version="2.0">
+ <info>
+ <its:rules version="2.0">
+ <its:preserveSpaceRule selector="//verse" space="preserve"/>
+ </its:rules>
+ </info>
+ <verse>
+ 'Twas brillig, and the slithy toves
+ Did gyre and gimble in the wabe;
+ All mimsy were the borogoves,
+ And the mome raths outgrabe.
+ </verse>
+</book>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/preservespace/xml/preservespace2xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/preservespace/xml/preservespace2xml.xml
new file mode 100644
index 00000000000..b131356abd7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/preservespace/xml/preservespace2xml.xml
@@ -0,0 +1,8 @@
+<book xmlns:its="http://www.w3.org/2005/11/its" its:version="2.0">
+ <verse xml:space="preserve">
+ 'Twas brillig, and the slithy toves
+ Did gyre and gimble in the wabe;
+ All mimsy were the borogoves,
+ And the mome raths outgrabe.
+ </verse>
+</book>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/preservespace/xml/preservespace3xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/preservespace/xml/preservespace3xml.xml
new file mode 100644
index 00000000000..e16d438d68e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/preservespace/xml/preservespace3xml.xml
@@ -0,0 +1,11 @@
+<book xmlns:its="http://www.w3.org/2005/11/its" its:version="2.0" >
+ <info>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:xlink="http://www.w3.org/1999/xlink" version="2.0" xlink:href="preservespace3xmlrules.xml"/>
+ </info>
+ <verse>
+'Twas brillig, and the slithy toves
+ Did gyre and gimble in the wabe;
+ All mimsy were the borogoves,
+ And the mome raths outgrabe.
+ </verse>
+</book>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/preservespace/xml/preservespace3xmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/preservespace/xml/preservespace3xmlrules.xml
new file mode 100644
index 00000000000..8b05d415e58
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/preservespace/xml/preservespace3xmlrules.xml
@@ -0,0 +1,3 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:preserveSpaceRule selector="//verse" space="preserve"/>
+ </its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/preservespace/xml/preservespace4xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/preservespace/xml/preservespace4xml.xml
new file mode 100644
index 00000000000..a9d919dd246
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/preservespace/xml/preservespace4xml.xml
@@ -0,0 +1,8 @@
+<book xmlns:its="http://www.w3.org/2005/11/its" its:version="2.0">
+ <its:span xml:space="preserve">
+ 'Twas brillig, and the slithy toves
+ Did gyre and gimble in the wabe;
+ All mimsy were the borogoves,
+ And the mome raths outgrabe.
+ </its:span >
+</book>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/preservespace/xml/preservespace5xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/preservespace/xml/preservespace5xml.xml
new file mode 100644
index 00000000000..57b47e17475
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/preservespace/xml/preservespace5xml.xml
@@ -0,0 +1,14 @@
+<book xmlns:its="http://www.w3.org/2005/11/its" its:version="2.0">
+ <info>
+ <its:rules version="2.0">
+ <its:param name="preserverspaceParam">firstverse</its:param>
+ <its:preserveSpaceRule selector="//verse[@id=$preserverspaceParam]" space="preserve"/>
+ </its:rules>
+ </info>
+ <verse id="firstverse">
+ 'Twas brillig, and the slithy toves
+ Did gyre and gimble in the wabe;
+ All mimsy were the borogoves,
+ And the mome raths outgrabe.
+ </verse>
+</book>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/preservespace/xml/preservespace6xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/preservespace/xml/preservespace6xml.xml
new file mode 100644
index 00000000000..ac3cc628648
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/preservespace/xml/preservespace6xml.xml
@@ -0,0 +1,9 @@
+<book xmlns:its="http://www.w3.org/2005/11/its" its:version="2.0">
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:xlink="http://www.w3.org/1999/xlink" version="2.0" xlink:type="simple" xlink:href="preservespace6xmlrules.xml"/>
+ <verse id="firstverse">
+ 'Twas brillig, and the slithy toves
+ Did gyre and gimble in the wabe;
+ All mimsy were the borogoves,
+ And the mome raths outgrabe.
+ </verse>
+</book>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/preservespace/xml/preservespace6xmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/preservespace/xml/preservespace6xmlrules.xml
new file mode 100644
index 00000000000..d626b57f267
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/preservespace/xml/preservespace6xmlrules.xml
@@ -0,0 +1,4 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:param name="preserverspaceParam">firstverse</its:param>
+ <its:preserveSpaceRule selector="//verse[@id=$preserverspaceParam]" space="preserve"/>
+ </its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/html/provenance1html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/html/provenance1html.html
new file mode 100644
index 00000000000..3254d61dd33
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/html/provenance1html.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Test</title>
+ <script id="pr1" type="application/its+xml">
+ <its:provenanceRecords xml:id="pr1" xmlns:its="http://www.w3.org/2005/11/its">
+ <its:provenanceRecord
+ tool="onlinemtex"
+ revPerson="James Joyce"
+ revTool="mycat-v1.0"
+ revOrg="acme-CAT-v2.3"
+ provRef="http://www.examplelsp.com/excontent987/production/prov/e6354"/>
+ </its:provenanceRecords>
+ </script>
+ <script id="pr2" type="application/its+xml">
+ <its:provenanceRecords xml:id="pr2" xmlns:its="http://www.w3.org/2005/11/its">
+ <its:provenanceRecord
+ person="John Doe"
+ org="legaltrans-ex"
+ revPerson="Tommy Atkins"
+ revOrg="vistatec"
+ provRef="http://www.vistatec.com/job-12-7-15-X31/reviewed/prov/re8573469"/>
+ </its:provenanceRecords>
+ </script>
+ <link href=provenance1htmlrules.xml rel=its-rules>
+ </head>
+ <body>
+ <p class="prov-records-ref"><a href="#pr1"></a>This paragraph was translated from the machine.</p>
+ <p class="prov-records-ref"><a href="#pr2"></a>This text was translated directly by a person.</p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/html/provenance1htmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/html/provenance1htmlrules.xml
new file mode 100644
index 00000000000..5fe84aeb203
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/html/provenance1htmlrules.xml
@@ -0,0 +1,3 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0" xmlns:h="http://www.w3.org/1999/xhtml">
+ <its:provRule selector="//*[@class='prov-records-ref']" provenanceRecordsRefPointer="h:a/@href"/>
+</its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/html/provenance2html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/html/provenance2html.html
new file mode 100644
index 00000000000..214693ff72a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/html/provenance2html.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Test</title>
+ <script type="application/its+xml">
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0" xmlns:h="http://www.w3.org/1999/xhtml">
+ <its:provRule selector="//*[@class='prov-records-ref']" provenanceRecordsRefPointer="h:a/@href"/>
+ </its:rules>
+ </script>
+ <script id="pr1" type="application/its+xml">
+ <its:provenanceRecords xml:id="pr1" xmlns:its="http://www.w3.org/2005/11/its">
+ <its:provenanceRecord
+ toolRef="http://www.provdata.com/tool/#onlinemtex"
+ revPerson="James Joyce"
+ revToolRef="http://www.provdata.com/RevTool/#mycat-v1"
+ revOrg="acme-CAT-v2.3"
+ provRef="http://www.examplelsp.com/excontent987/production/prov/e6354"/>
+ </its:provenanceRecords>
+ </script>
+ <script id="pr2" type="application/its+xml">
+ <its:provenanceRecords xml:id="pr2" xmlns:its="http://www.w3.org/2005/11/its">
+ <its:provenanceRecord
+ personRef="http://www.provdata.com/person/#John_Doe"
+ orgRef="http://www.provdata.com/org/#legaltrans-ex"
+ revPersonRef="http://www.provdata.com/RevPerson/#Tommy_Atkins"
+ revOrgRef="http://www.provdata.com/RevOrg/#vistatec"
+ provRef="http://www.vistatec.com/job-12-7-15-X31/reviewed/prov/re8573469"/>
+ </its:provenanceRecords>
+ </script>
+ </head>
+ <body>
+ <p class="prov-records-ref"><a href="#pr1"></a>This paragraph was translated from the machine.</p>
+ <p class="prov-records-ref"><a href="#pr2"></a>This text was translated directly by a person.</p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/html/provenance3html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/html/provenance3html.html
new file mode 100644
index 00000000000..75a99a36947
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/html/provenance3html.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Test</title>
+ <script id="pr1" type="application/its+xml">
+ <its:provenanceRecords xml:id="pr1" xmlns:its="http://www.w3.org/2005/11/its">
+ <its:provenanceRecord
+ toolRef="http://www.onlinemtex.com/2012/7/25/wsdl/"
+ org="acme-CAT-v2.3"
+ revToolRef="http://www.mycat.com/v1.0/download"
+ revOrg="acme-CAT-v2.3"
+ provRef="http://www.examplelsp.com/excontent987/production/prov/e6354"/>
+ </its:provenanceRecords>
+ </script>
+ <script id="pr2" type="application/its+xml">
+ <its:provenanceRecords xml:id="pr2" xmlns:its="http://www.w3.org/2005/11/its">
+ <its:provenanceRecord
+ person="John Doe"
+ orgRef="http://www.legaltrans-ex.com/"
+ revPerson="Tommy Atkins"
+ revOrgRef="http://www.vistatec.com/"
+ provRef="http://www.vistatec.com/job-12-7-15-X31/reviewed/prov/re8573469"/>
+ </its:provenanceRecords>
+ </script>
+ </head>
+ <body>
+ <p Its-Provenance-Records-Ref="#pr1"> This paragraph was translated from the machine.</p>
+ <p its-provenance-records-ref="#pr2">This text was translated directly by a person.</p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/html/provenance4html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/html/provenance4html.html
new file mode 100644
index 00000000000..0f387daccb0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/html/provenance4html.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html lang=en>
+ <head>
+ <meta charset=utf-8>
+ <title>Translation Revision Provenance Agent: Local Test in HTML5</title>
+ </head>
+ <body>
+ <p id="p1"
+ its-person-ref="http://www.provdata.com/person/#John_Doe"
+ its-tool-ref="http://www.onlinemtex.com/2012/7/25/wsdl/"
+ its-ORG="acme-CAT-v2.3"
+ its-rev-tool-ref="http://www.mycat.com/v1.0/download"
+ its-rev-org="acme-CAT-v2.3"
+ its-prov-ref="http://www.examplelsp.com/excontent987/production/prov/e6354"> This paragraph was translated from the machine.</p>
+ <p class="legal-notice"
+ ITS-tool="onlinemtex"
+ its-person="John Doe"
+ its-org-ref="http://www.legaltrans-ex.com/"
+ its-rev-person="Tommy Atkins"
+ its-rev-org-ref="http://www.vistatec.com/"
+ its-prov-ref="http://www.vistatec.com/job-12-7-15-X31/reviewed/prov/re8573469">This text was translated directly by a person.</p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/html/provenance5html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/html/provenance5html.html
new file mode 100644
index 00000000000..bb2f6bf0bac
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/html/provenance5html.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Test</title>
+ <script id="pr1" type="application/its+xml">
+ <its:provenanceRecords xml:id="pr1" xmlns:its="http://www.w3.org/2005/11/its">
+ <its:provenanceRecord
+ toolRef="http://www.provdata.com/tool/#onlinemtex"
+ revPerson="James Joyce"
+ revToolRef="http://www.provdata.com/RevTool/#mycat-v1"
+ revOrg="acme-CAT-v2.3"
+ provRef="http://www.examplelsp.com/excontent987/production/prov/e6354"/>
+ <its:provenanceRecord
+ revPerson="John Smith"
+ revOrg="Linguaserve I.S. S.A." />
+ </its:provenanceRecords>
+ </script>
+ <script id="pr2" type="application/its+xml">
+ <its:provenanceRecords xml:id="pr2" xmlns:its="http://www.w3.org/2005/11/its">
+ <its:provenanceRecord
+ personRef="http://www.provdata.com/person/#John_Doe"
+ orgRef="http://www.provdata.com/org/#legaltrans-ex"
+ revPersonRef="http://www.provdata.com/RevPerson/#Tommy_Atkins"
+ revOrgRef="http://www.provdata.com/RevOrg/#vistatec"
+ provRef="http://www.vistatec.com/job-12-7-15-X31/reviewed/prov/re8573469"/>
+ </its:provenanceRecords>
+ </script>
+ <link href=provenance5htmlrules.xml rel=its-rules>
+ </head>
+ <body>
+ <p class="prov-records-ref1"><a href="#pr1"></a>This paragraph was translated from the machine and subsequently revised.</p>
+ <p class="prov-records-ref2"><a href="#pr2"></a>This text was translated directly by a person.</p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/html/provenance5htmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/html/provenance5htmlrules.xml
new file mode 100644
index 00000000000..de701d979ed
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/html/provenance5htmlrules.xml
@@ -0,0 +1,4 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0" xmlns:h="http://www.w3.org/1999/xhtml">
+ <its:param name="provenanceParam">prov-records-ref1</its:param>
+ <its:provRule selector="//*[@class=$provenanceParam]" provenanceRecordsRefPointer="h:a/@href"/>
+</its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/html/provenance6html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/html/provenance6html.html
new file mode 100644
index 00000000000..a4952fc6647
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/html/provenance6html.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Test</title>
+ </head>
+ <body>
+ <p its-provenance-records-ref="provenance6htmlstandoff.xml#pr1">This paragraph was translated from the machine and subsequently revised.</p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/html/provenance6htmlstandoff.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/html/provenance6htmlstandoff.xml
new file mode 100644
index 00000000000..0be1638a674
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/html/provenance6htmlstandoff.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" ?>
+<someDataFile xmlns:its="http://www.w3.org/2005/11/its" its:version="2.0">
+<its:provenanceRecords xml:id="pr1">
+ <its:provenanceRecord
+ toolRef="http://www.provdata.com/tool/#onlinemtex"
+ revPerson="James Joyce"
+ revToolRef="http://www.provdata.com/RevTool/#mycat-v1"
+ revOrg="acme-CAT-v2.3"
+ provRef="http://www.examplelsp.com/excontent987/production/prov/e6354"/>
+ <its:provenanceRecord
+ revPerson="John Smith"
+ revOrg="Linguaserve I.S. S.A." />
+ </its:provenanceRecords>
+</someDataFile>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/html/provenance7html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/html/provenance7html.html
new file mode 100644
index 00000000000..7ddd66a606f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/html/provenance7html.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Test</title>
+ </head>
+ <body>
+ <p its-provenance-records-ref="provenance7htmlstandoff.html#pr1">This paragraph was translated from the machine and subsequently revised.</p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/html/provenance7htmlstandoff.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/html/provenance7htmlstandoff.html
new file mode 100644
index 00000000000..04e0070558b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/html/provenance7htmlstandoff.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Test</title>
+ <script id="pr1" type="application/its+xml">
+ <its:provenanceRecords xml:id="pr1" xmlns:its="http://www.w3.org/2005/11/its">
+ <its:provenanceRecord
+ toolRef="http://www.provdata.com/tool/#onlinemtex"
+ revPerson="James Joyce"
+ revToolRef="http://www.provdata.com/RevTool/#mycat-v1"
+ revOrg="acme-CAT-v2.3"
+ provRef="http://www.examplelsp.com/excontent987/production/prov/e6354"/>
+ <its:provenanceRecord
+ revPerson="John Smith"
+ revOrg="Linguaserve I.S. S.A." />
+ </its:provenanceRecords>
+ </script>
+ </head>
+ <body>
+ <p id="#pr1">Here is the information of provenance.</p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/html/provenance8html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/html/provenance8html.html
new file mode 100644
index 00000000000..a0fc83300c4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/html/provenance8html.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Test</title>
+ <script id="pr1" type="application/its+xml">
+ <its:provenanceRecords xml:id="pr1" xmlns:its="http://www.w3.org/2005/11/its">
+ <its:provenanceRecord
+ tool="onlinemtex"
+ revPerson="James Joyce"
+ revTool="mycat-v1.0"
+ revOrg="acme-CAT-v2.3"
+ provRef="http://www.examplelsp.com/excontent987/production/prov/e6354"/>
+ </its:provenanceRecords>
+ </script>
+ <script id="pr2" type="application/its+xml">
+ <its:provenanceRecords xml:id="pr2" xmlns:its="http://www.w3.org/2005/11/its">
+ <its:provenanceRecord
+ person="John Doe"
+ org="legaltrans-ex"
+ revPerson="Tommy Atkins"
+ revOrg="vistatec"
+ provRef="http://www.vistatec.com/job-12-7-15-X31/reviewed/prov/re8573469"/>
+ </its:provenanceRecords>
+ </script>
+ <script type="application/its+xml">
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml" version="2.0">
+ <its:param name="provenanceParam">prov-records-ref1</its:param>
+ <its:provRule selector="//*[@class=$provenanceParam]" provenanceRecordsRefPointer="h:a/@href"/>
+ </its:rules>
+ </script>
+ </head>
+ <body>
+ <p class="prov-records-ref1"><a href="#pr1"></a>This paragraph was translated from the machine.</p>
+ <p class="prov-records-ref2"><a href="#pr2"></a>This text was translated directly by a person.</p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/xml/provenance1xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/xml/provenance1xml.xml
new file mode 100644
index 00000000000..9c154797e17
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/xml/provenance1xml.xml
@@ -0,0 +1,28 @@
+<text xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:its="http://www.w3.org/2005/11/its" its:version="2.0">
+ <dc:creator>John Doe</dc:creator>
+ <its:provenanceRecords xml:id="pr1">
+ <its:provenanceRecord
+ tool="onlinemtex"
+ revPerson="James Joyce"
+ revTool="mycat-v1.0"
+ revOrg="acme-CAT-v2.3"
+ provRef="http://www.examplelsp.com/excontent987/production/prov/e6354"/>
+ </its:provenanceRecords>
+ <its:provenanceRecords xml:id="pr2">
+ <its:provenanceRecord
+ person="John Doe"
+ org="legaltrans-ex"
+ revPerson="Tommy Atkins"
+ revOrg="vistatec"
+ provRef="http://www.examplelsp.com/excontent987/legal/prov/e6354 http://www.vistatec.com/job-12-7-15-X31/reviewed/prov/re8573469"/>
+ </its:provenanceRecords>
+ <its:rules version="2.0">
+ <its:provRule selector="//*[@ref]" provenanceRecordsRefPointer="@ref"/>
+ </its:rules>
+ <title>Translation Revision Provenance Agent: Global Test in XML</title>
+ <body>
+ <par ref="#pr1"> This paragraph was translated from the machine.</par>
+ <legalnotice ref="#pr2">This text was translated directly by a person.</legalnotice>
+ </body>
+</text>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/xml/provenance2xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/xml/provenance2xml.xml
new file mode 100644
index 00000000000..c30afe8d39c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/xml/provenance2xml.xml
@@ -0,0 +1,29 @@
+<text xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:its="http://www.w3.org/2005/11/its" its:version="2.0">
+ <dc:creator>John Doe</dc:creator>
+ <its:provenanceRecords xml:id="pr1">
+ <its:provenanceRecord
+ toolRef="http://www.provdata.com/tool/#onlinemtex"
+ revPerson="James Joyce"
+ revToolRef="http://www.provdata.com/RevTool/#mycat-v1"
+ revOrg="acme-CAT-v2.3"
+ provRef="http://www.examplelsp.com/excontent987/production/prov/e6354"/>
+ </its:provenanceRecords>
+ <its:provenanceRecords xml:id="pr2">
+ <its:provenanceRecord
+ personRef="http://www.provdata.com/person/#John_Doe"
+ orgRef="http://www.provdata.com/org/#legaltrans-ex"
+ revPersonRef="http://www.provdata.com/RevPerson/#Tommy_Atkins"
+ revOrgRef="http://www.provdata.com/RevOrg/#vistatec"
+ provRef="http://www.examplelsp.com/excontent987/legal/prov/e6354 http://www.vistatec.com/job-12-7-15-X31/reviewed/prov/re8573469"/>
+ </its:provenanceRecords>
+ <its:rules version="2.0">
+ <its:provRule selector="//*[@ref]" provenanceRecordsRefPointer="@ref"/>
+ </its:rules>
+ <title>Translation Revision Provenance Agent: Global Test in XML</title>
+ <body>
+ <par ref="#pr1"> This paragraph was translated from the machine.</par>
+ <legalnotice ref="#pr2">This text was
+ translated directly by a person.</legalnotice>
+ </body>
+</text>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/xml/provenance3xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/xml/provenance3xml.xml
new file mode 100644
index 00000000000..a356db347ec
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/xml/provenance3xml.xml
@@ -0,0 +1,27 @@
+<text xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:its="http://www.w3.org/2005/11/its" its:version="2.0">
+ <dc:creator>John Doe</dc:creator>
+ <its:provenanceRecords xml:id="pr1">
+ <its:provenanceRecord
+ tool="onlinemtex"
+ revPerson="James Joyce"
+ revTool="mycat-v1.0"
+ revOrg="acme-CAT-v2.3"
+ provRef="http://www.examplelsp.com/excontent987/production/prov/e6354"/>
+ </its:provenanceRecords>
+ <its:provenanceRecords xml:id="pr2">
+ <its:provenanceRecord
+ person="John Doe"
+ org="legaltrans-ex"
+ revPerson="Tommy Atkins"
+ revOrg="vistatec"
+ provRef="http://www.examplelsp.com/excontent987/legal/prov/e6354 http://www.vistatec.com/job-12-7-15-X31/reviewed/prov/re8573469"/>
+ </its:provenanceRecords>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="provenance3xmlrules.xml"/>
+ <title>Translation Revision Provenance Agent: Global Test in XML</title>
+ <body>
+ <par ref="#pr1"> This paragraph was translated from the machine.</par>
+ <legalnotice ref="#pr2">This text was
+ translated directly by a person.</legalnotice>
+ </body>
+</text>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/xml/provenance3xmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/xml/provenance3xmlrules.xml
new file mode 100644
index 00000000000..30f00d3e87a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/xml/provenance3xmlrules.xml
@@ -0,0 +1,3 @@
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:provRule selector="//*[@ref]" provenanceRecordsRefPointer="@ref"/>
+ </its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/xml/provenance4xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/xml/provenance4xml.xml
new file mode 100644
index 00000000000..dde7dbb1c74
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/xml/provenance4xml.xml
@@ -0,0 +1,27 @@
+<text xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:its="http://www.w3.org/2005/11/its" its:version="2.0">
+ <dc:creator>John Doe</dc:creator>
+ <its:provenanceRecords xml:id="pr1">
+ <its:provenanceRecord
+ toolRef="http://www.provdata.com/tool/#onlinemtex"
+ revPerson="James Joyce"
+ revToolRef="http://www.provdata.com/RevTool/#mycat-v1"
+ revOrg="acme-CAT-v2.3"
+ provRef="http://www.examplelsp.com/excontent987/production/prov/e6354"/>
+ </its:provenanceRecords>
+ <its:provenanceRecords xml:id="pr2">
+ <its:provenanceRecord
+ personRef="http://www.provdata.com/person/#John_Doe"
+ orgRef="http://www.provdata.com/org/#legaltrans-ex"
+ revPersonRef="http://www.provdata.com/RevPerson/#Tommy_Atkins"
+ revOrgRef="http://www.provdata.com/RevOrg/#vistatec"
+ provRef="http://www.examplelsp.com/excontent987/legal/prov/e6354 http://www.vistatec.com/job-12-7-15-X31/reviewed/prov/re8573469"/>
+ </its:provenanceRecords>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="provenance4xmlrules.xml"/>
+ <title>Translation Revision Provenance Agent: Global Test in XML</title>
+ <body>
+ <par ref="#pr1"> This paragraph was translated from the machine.</par>
+ <legalnotice ref="#pr2">This text was
+ translated directly by a person.</legalnotice>
+ </body>
+</text>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/xml/provenance4xmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/xml/provenance4xmlrules.xml
new file mode 100644
index 00000000000..0b1e34ea8ae
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/xml/provenance4xmlrules.xml
@@ -0,0 +1,3 @@
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:provRule selector="//*[@ref]" provenanceRecordsRefPointer="@ref"/>
+ </its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/xml/provenance5xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/xml/provenance5xml.xml
new file mode 100644
index 00000000000..f82e8994b5f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/xml/provenance5xml.xml
@@ -0,0 +1,30 @@
+<text xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:its="http://www.w3.org/2005/11/its" its:version="2.0">
+ <dc:creator>John Doe</dc:creator>
+ <its:provenanceRecords xml:id="pr1">
+ <its:provenanceRecord
+ tool="onlinemtex"
+ revPerson="James Joyce"
+ revTool="mycat-v1.0"
+ revOrg="acme-CAT-v2.3"
+ provRef="http://www.examplelsp.com/excontent987/production/prov/e6354"/>
+ </its:provenanceRecords>
+ <its:provenanceRecords xml:id="pr2">
+ <its:provenanceRecord
+ person="John Doe"
+ org="legaltrans-ex"
+ revPerson="Tommy Atkins"
+ revOrg="vistatec"
+ provRef="http://www.examplelsp.com/excontent987/legal/prov/e6354 http://www.vistatec.com/job-12-7-15-X31/reviewed/prov/re8573469"/>
+ </its:provenanceRecords>
+ <its:rules version="2.0">
+ <its:param name="provenanceParam">#pr1</its:param>
+ <its:provRule selector="//*[@ref=$provenanceParam]" provenanceRecordsRefPointer="@ref"/>
+ </its:rules>
+ <title>Translation Revision Provenance Agent: Global Test in XML</title>
+ <body>
+ <par ref="#pr1"> This paragraph was translated from the machine.</par>
+ <legalnotice ref="#pr2">This text was
+ translated directly by a person.</legalnotice>
+ </body>
+</text>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/xml/provenance6xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/xml/provenance6xml.xml
new file mode 100644
index 00000000000..0b51543800b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/xml/provenance6xml.xml
@@ -0,0 +1,27 @@
+<text xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:its="http://www.w3.org/2005/11/its" its:version="2.0">
+ <dc:creator>John Doe</dc:creator>
+ <its:provenanceRecords xml:id="pr1">
+ <its:provenanceRecord
+ tool="onlinemtex"
+ revPerson="James Joyce"
+ revTool="mycat-v1.0"
+ revOrg="acme-CAT-v2.3"
+ provRef="http://www.examplelsp.com/excontent987/production/prov/e6354"/>
+ </its:provenanceRecords>
+ <its:provenanceRecords xml:id="pr2">
+ <its:provenanceRecord
+ person="John Doe"
+ org="legaltrans-ex"
+ revPerson="Tommy Atkins"
+ revOrg="vistatec"
+ provRef="http://www.examplelsp.com/excontent987/legal/prov/e6354 http://www.vistatec.com/job-12-7-15-X31/reviewed/prov/re8573469"/>
+ </its:provenanceRecords>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="provenance6xmlrules.xml"/>
+ <title>Translation Revision Provenance Agent: Global Test in XML</title>
+ <body>
+ <par ref="#pr1"> This paragraph was translated from the machine.</par>
+ <legalnotice ref="#pr2">This text was
+ translated directly by a person.</legalnotice>
+ </body>
+</text>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/xml/provenance6xmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/xml/provenance6xmlrules.xml
new file mode 100644
index 00000000000..e7e74a831b6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/xml/provenance6xmlrules.xml
@@ -0,0 +1,4 @@
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:param name="provenanceParam">#pr1</its:param>
+ <its:provRule selector="//*[@ref=$provenanceParam]" provenanceRecordsRefPointer="@ref"/>
+ </its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/xml/provenance7xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/xml/provenance7xml.xml
new file mode 100644
index 00000000000..e099e157ebf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/xml/provenance7xml.xml
@@ -0,0 +1,20 @@
+<text xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:its="http://www.w3.org/2005/11/its" its:version="2.0">
+ <title>Translation Revision Provenance Agent: Local Test in XML</title>
+ <body>
+ <par its:personRef="http://www.provdata.com/person/#John_Doe"
+ its:toolRef="http://www.onlinemtex.com/2012/7/25/wsdl/"
+ its:org="acme-CAT-v2.3"
+ its:revToolRef="http://www.mycat.com/v1.0/download"
+ its:revOrg="acme-CAT-v2.3"
+ its:provRef="http://www.examplelsp.com/excontent987/production/prov/e6354"
+ >This paragraph was translated from the machine.</par>
+ <legalnotice its:tool="onlinemtex"
+ its:person="John Doe"
+ its:orgRef="http://www.legaltrans-ex.com/"
+ its:revPerson="Tommy Atkins"
+ its:revOrgRef="http://www.vistatec.com/"
+ its:provRef="http://www.examplelsp.com/excontent987/legal/prov/e6354 http://www.vistatec.com/job-12-7-15-X31/reviewed/prov/re8573469"
+ >This text was translated directly by a person.</legalnotice>
+ </body>
+</text>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/xml/provenance8xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/xml/provenance8xml.xml
new file mode 100644
index 00000000000..c905730fcbc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/provenance/xml/provenance8xml.xml
@@ -0,0 +1,20 @@
+<text xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:its="http://www.w3.org/2005/11/its" its:version="2.0">
+ <title>Translation Revision Provenance Agent: Local Test in XML</title>
+ <body>
+ <its:span personRef="http://www.provdata.com/person/#John_Doe"
+ toolRef="http://www.onlinemtex.com/2012/7/25/wsdl/"
+ org="acme-CAT-v2.3"
+ revToolRef="http://www.mycat.com/v1.0/download"
+ revOrg="acme-CAT-v2.3"
+ provRef="http://www.examplelsp.com/excontent987/production/prov/e6354"
+ >This paragraph was translated from the machine.</its:span>
+ <its:span tool="onlinemtex"
+ person="John Doe"
+ orgRef="http://www.legaltrans-ex.com/"
+ revPerson="Tommy Atkins"
+ revOrgRef="http://www.vistatec.com/"
+ provRef="http://www.examplelsp.com/excontent987/legal/prov/e6354 http://www.vistatec.com/job-12-7-15-X31/reviewed/prov/re8573469"
+ >This text was translated directly by a person.</its:span>
+ </body>
+</text>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/html/storagesize1html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/html/storagesize1html.html
new file mode 100644
index 00000000000..fb701737625
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/html/storagesize1html.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8"/>
+ <title>Storage Size</title>
+ </head>
+ <body>
+ <p>String to translate:</p>
+ <p contenteditable="true" id="123" its-storage-size="25" its-storage-encoding="ISO-8859-1" its-line-break-type="LF">Papua New-Guinea</p>
+ <p contenteditable="true" id="139" its-storage-size="25" its-storage-encoding="ISO-8859-1" its-line-break-type="lF">Dominican Replubic</p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/html/storagesize2html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/html/storagesize2html.html
new file mode 100644
index 00000000000..0e1a720d9e9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/html/storagesize2html.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset=utf-8>
+ <title>Storage Size</title>
+ <link href="storagesize2htmlrules.xml" rel="its-rules"/>
+ </head>
+ <body>
+ <b>String to translate:</b>
+ <p contenteditable="true" id="123">Papua New-Guinea</p>
+ <p contenteditable="true" id="139">Dominican Replubic</p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/html/storagesize2htmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/html/storagesize2htmlrules.xml
new file mode 100644
index 00000000000..93d0bfa61f6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/html/storagesize2htmlrules.xml
@@ -0,0 +1,3 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml" version="2.0">
+ <its:storageSizeRule selector="//h:p" storageSize="25" storageEncoding="ISO-8859-1"/>
+ </its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/html/storagesize3html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/html/storagesize3html.html
new file mode 100644
index 00000000000..4cc8f4256cd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/html/storagesize3html.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8"/>
+ <title>Storage Size</title>
+ <link href="storagesize3htmlrules.xml" rel="its-rules"/>
+ </head>
+ <body>
+ <b>String to translate:</b>
+ <p contenteditable="true" id="123">Papua New-Guinea</p>
+ <p contenteditable="true" id="139">Dominican Replubic</p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/html/storagesize3htmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/html/storagesize3htmlrules.xml
new file mode 100644
index 00000000000..4e8b23d3d50
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/html/storagesize3htmlrules.xml
@@ -0,0 +1,4 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml" version="2.0">
+ <its:param name="storagesizeParam">123</its:param>
+ <its:storageSizeRule selector="//h:p[@id=$storagesizeParam]" storageSize="25" storageEncoding="ISO-8859-1"/>
+ </its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/html/storagesize4html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/html/storagesize4html.html
new file mode 100644
index 00000000000..4ec272a4d3c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/html/storagesize4html.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html lang=en>
+ <head>
+ <script type="application/its+xml">
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml" version="2.0">
+ <its:param name="storagesizePapParam">123</its:param>
+ <its:param name="storagesizeDomParam">139</its:param>
+ <its:storageSizeRule selector="//h:p[@id=$storagesizePapParam]" storageSize="25" storageEncoding="ISO-8859-1"/>
+ <its:storageSizeRule selector="//h:p[@id=$storagesizeDomParam]" storageSize="25" storageEncoding="ISO-8859-1"/>
+ </its:rules>
+ </script>
+ <meta charset=utf-8>
+ <title>Storage Size</title>
+ </head>
+ <body>
+ <b>String to translate:</b>
+ <p contenteditable="true" id="123">Papua New-Guinea</p>
+ <p contenteditable="true" id="139">Dominican Replubic</p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/xml/storagesize1xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/xml/storagesize1xml.xml
new file mode 100644
index 00000000000..c003af2ce73
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/xml/storagesize1xml.xml
@@ -0,0 +1,10 @@
+<db>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:storageSizeRule selector="//country" storageSize="25" storageEncoding="ISO-8859-1"/>
+ </its:rules>
+ <data>
+ <country id="123">Papouasie-Nouvelle-Guinée</country>
+ <country id="139">République Dominicaine</country>
+ </data>
+</db>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/xml/storagesize2xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/xml/storagesize2xml.xml
new file mode 100644
index 00000000000..343b4b4a9f5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/xml/storagesize2xml.xml
@@ -0,0 +1,8 @@
+<fields>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:storageSizeRule selector="//field" storageSizePointer="@max" storageEncodingPointer="@encoding"/>
+ </its:rules>
+ <field type="country" id="123" max="25" encoding="ISO-8859-1">Papouasie-Nouvelle-Guinée</field>
+ <field type="country" id="139" max="25" encoding="ISO-8859-1">République Dominicaine</field>
+</fields>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/xml/storagesize3xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/xml/storagesize3xml.xml
new file mode 100644
index 00000000000..02b07d946c8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/xml/storagesize3xml.xml
@@ -0,0 +1,8 @@
+<db>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:xlink="http://www.w3.org/1999/xlink" version="2.0" xlink:type="simple" xlink:href="storagesize3xmlrules.xml"/>
+ <data>
+ <country id="123">Papouasie-Nouvelle-Guinée</country>
+ <country id="139">République Dominicaine</country>
+ </data>
+</db>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/xml/storagesize3xmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/xml/storagesize3xmlrules.xml
new file mode 100644
index 00000000000..08135110202
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/xml/storagesize3xmlrules.xml
@@ -0,0 +1,3 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:storageSizeRule selector="//country" storageSize="25" storageEncoding="ISO-8859-1"/>
+ </its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/xml/storagesize4xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/xml/storagesize4xml.xml
new file mode 100644
index 00000000000..a48879007bc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/xml/storagesize4xml.xml
@@ -0,0 +1,6 @@
+<fields>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:xlink="http://www.w3.org/1999/xlink" version="2.0" xlink:type="simple" xlink:href="storagesize4xmlrules.xml"/>
+ <field type="country" id="123" max="25" encoding="ISO-8859-1">Papouasie-Nouvelle-Guinée</field>
+ <field type="country" id="139" max="25" encoding="ISO-8859-1">République Dominicaine</field>
+</fields>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/xml/storagesize4xmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/xml/storagesize4xmlrules.xml
new file mode 100644
index 00000000000..50be2ad8030
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/xml/storagesize4xmlrules.xml
@@ -0,0 +1,3 @@
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:storageSizeRule selector="//field" storageSizePointer="@max" storageEncodingPointer="@encoding"/>
+ </its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/xml/storagesize5xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/xml/storagesize5xml.xml
new file mode 100644
index 00000000000..cf7ff610302
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/xml/storagesize5xml.xml
@@ -0,0 +1,5 @@
+<messages xmlns:its="http://www.w3.org/2005/11/its" its:version="2.0">
+ <var num="panelA1_Continue" its:storageSize="8" its:storageEncoding="UTF-16">CONTINUE</var>
+ <var num="panelA1_Stop" its:storageSize="8" its:storageEncoding="UTF-16">STOP</var>
+ <var num="panelB5_Cancel" its:storageSize="12" its:storageEncoding="UTF-16">CANCEL</var>
+</messages>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/xml/storagesize6xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/xml/storagesize6xml.xml
new file mode 100644
index 00000000000..21cfbae15d2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/xml/storagesize6xml.xml
@@ -0,0 +1,5 @@
+<messages xmlns:its="http://www.w3.org/2005/11/its" its:version="2.0">
+ <var num="panelA1_Continue" its:storageSize="8" its:storageEncoding="UTF-16" its:lineBreakType="lf">CONTINUE</var>
+ <var num="panelA1_Stop" its:storageSize="8" its:storageEncoding="UTF-16" its:lineBreakType="lf">STOP</var>
+ <var num="panelB5_Cancel" its:storageSize="12" its:storageEncoding="UTF-16" its:lineBreakType="lf">CANCEL</var>
+</messages>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/xml/storagesize7xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/xml/storagesize7xml.xml
new file mode 100644
index 00000000000..d090b0da643
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/xml/storagesize7xml.xml
@@ -0,0 +1,8 @@
+<db>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:xlink="http://www.w3.org/1999/xlink" version="2.0" xlink:type="simple" xlink:href="storagesize7xmlrules.xml"/>
+ <data>
+ <country id="123">Papouasie-Nouvelle-Guinée</country>
+ <country id="139">République Dominicaine</country>
+ </data>
+</db>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/xml/storagesize7xmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/xml/storagesize7xmlrules.xml
new file mode 100644
index 00000000000..8df636ef7a6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/xml/storagesize7xmlrules.xml
@@ -0,0 +1,4 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:param name="storagesizeParam">123</its:param>
+ <its:storageSizeRule selector="//country[@id=$storagesizeParam]" storageSize="25" storageEncoding="ISO-8859-1"/>
+ </its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/xml/storagesize8xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/xml/storagesize8xml.xml
new file mode 100644
index 00000000000..8044869de4e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/xml/storagesize8xml.xml
@@ -0,0 +1,11 @@
+<db>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:param name="storagesizeParam">123</its:param>
+ <its:storageSizeRule selector="//country[@id=$storagesizeParam]" storageSize="25" storageEncoding="ISO-8859-1"/>
+ </its:rules>
+ <data>
+ <country id="123">Papouasie-Nouvelle-Guinée</country>
+ <country id="139">République Dominicaine</country>
+ </data>
+</db>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/xml/storagesize9xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/xml/storagesize9xml.xml
new file mode 100644
index 00000000000..e464ed6d04d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/storagesize/xml/storagesize9xml.xml
@@ -0,0 +1,5 @@
+<messages xmlns:its="http://www.w3.org/2005/11/its" its:version="2.0">
+ <its:span storageSize="8" storageEncoding="UTF-16" lineBreakType="lf">CONTINUE</its:span>
+ <its:span storageSize="8" storageEncoding="UTF-16" lineBreakType="lf">STOP</its:span>
+ <its:span storageSize="12" storageEncoding="UTF-16" lineBreakType="lf">CANCEL</its:span>
+</messages>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/targetpointer/html/targetpointer1html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/targetpointer/html/targetpointer1html.html
new file mode 100644
index 00000000000..bca5036b46a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/targetpointer/html/targetpointer1html.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8"/>
+ <title>Target Pointer</title>
+ <link href="targetpointer1htmlrules.xml" rel="its-rules"/>
+ </head>
+ <body>
+ <div id="one">
+ <p class="srcfolder">Remember last folder</p>
+ <p class="targetfolder">lastFolder</p>
+ </div>
+ <div id="two">
+ <p class="srcfile">Custom file filter:</p>
+ <p class="targetfile">testFile.txt</p>
+ </div>
+ </body>
+</html>
+
+
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/targetpointer/html/targetpointer1htmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/targetpointer/html/targetpointer1htmlrules.xml
new file mode 100644
index 00000000000..93318581b62
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/targetpointer/html/targetpointer1htmlrules.xml
@@ -0,0 +1,4 @@
+ <its:rules version="2.0" xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml">
+ <its:targetPointerRule selector="//h:div[@id='one']/h:p[@class='srcfolder']" targetPointer="../h:p[@class='targetfolder']"/>
+ <its:targetPointerRule selector="//h:div[@id='two']/h:p[@class='srcfile']" targetPointer="../h:p[@class='targetfile']"/>
+ </its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/targetpointer/html/targetpointer2html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/targetpointer/html/targetpointer2html.html
new file mode 100644
index 00000000000..bbcbc52eb3d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/targetpointer/html/targetpointer2html.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8"/>
+ <title>Target Pointer</title>
+ <link href="targetpointer2htmlrules.xml" rel="its-rules"/>
+ </head>
+ <body>
+ <div id="one">
+ <p class="srcfolder">Remember last folder</p>
+ <p class="targetfolder">lastFolder</p>
+ </div>
+ <div id="two">
+ <p class="srcfile">Custom file filter:</p>
+ <p class="targetfile">testFile.txt</p>
+ </div>
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/targetpointer/html/targetpointer2htmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/targetpointer/html/targetpointer2htmlrules.xml
new file mode 100644
index 00000000000..b26379aaf53
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/targetpointer/html/targetpointer2htmlrules.xml
@@ -0,0 +1,8 @@
+ <its:rules version="2.0" xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml">
+ <its:param name="targetFolder">targetfolder</its:param>
+ <its:param name="targetFile">targetfile</its:param>
+ <its:targetPointerRule selector="//h:div[@id='one']/h:p[@class='srcfolder']" targetPointer="../h:p[@class=$targetFolder]"/>
+ <its:targetPointerRule selector="//h:div[@id='two']/h:p[@class='srcfile']" targetPointer="../h:p[@class=$targetFile]"/>
+ </its:rules>
+
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/targetpointer/html/targetpointer3html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/targetpointer/html/targetpointer3html.html
new file mode 100644
index 00000000000..301911b2a79
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/targetpointer/html/targetpointer3html.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+ <head>
+<script type="application/its+xml">
+ <its:rules version="2.0" xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml">
+ <its:param name="targetFolder">targetfolder</its:param>
+ <its:targetPointerRule selector="//h:div[@id='one']/h:p[@class='srcfolder']" targetPointer="../h:p[@class=$targetFolder]"/>
+ <its:targetPointerRule selector="//h:div[@id='two']/h:p[@class='srcfile']" targetPointer="../h:p[@class='targetfile']"/>
+ </its:rules>
+</script>
+ <meta charset="utf-8"/>
+ <title>Target Pointer</title>
+ </head>
+ <body>
+ <div id="one">
+ <p class="srcfolder">Remember last folder</p>
+ <p class="targetfolder">lastFolder</p>
+ </div>
+ <div id="two">
+ <p class="srcfile">Custom file filter:</p>
+ <p class="targetfile">testFile.txt</p>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/targetpointer/xml/targetpointer1xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/targetpointer/xml/targetpointer1xml.xml
new file mode 100644
index 00000000000..0c32dc293d6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/targetpointer/xml/targetpointer1xml.xml
@@ -0,0 +1,14 @@
+<file
+ xmlns:its="http://www.w3.org/2005/11/its" >
+ <its:rules version="2.0">
+ <its:targetPointerRule selector="//source" targetPointer="../target"/>
+ </its:rules>
+ <entry id="one">
+ <source>Remember last folder</source>
+ <target>lastFolder</target>
+ </entry>
+ <entry id="two">
+ <source>Custom file filter:</source>
+ <target>testFile.txt</target>
+ </entry>
+</file>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/targetpointer/xml/targetpointer2xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/targetpointer/xml/targetpointer2xml.xml
new file mode 100644
index 00000000000..91350392de8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/targetpointer/xml/targetpointer2xml.xml
@@ -0,0 +1,12 @@
+<file
+ xmlns:its="http://www.w3.org/2005/11/its" >
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:xlink="http://www.w3.org/1999/xlink" version="2.0" xlink:href="targetpointer2xmlrules.xml"/>
+ <entry id="one">
+ <source>Remember last folder</source>
+ <target>lastFolder</target>
+ </entry>
+ <entry id="two">
+ <source>Custom file filter:</source>
+ <target>testFile.txt</target>
+ </entry>
+</file>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/targetpointer/xml/targetpointer2xmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/targetpointer/xml/targetpointer2xmlrules.xml
new file mode 100644
index 00000000000..b8fc4ed9a75
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/targetpointer/xml/targetpointer2xmlrules.xml
@@ -0,0 +1,3 @@
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:targetPointerRule selector="//source" targetPointer="../target"/>
+ </its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/targetpointer/xml/targetpointer3xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/targetpointer/xml/targetpointer3xml.xml
new file mode 100644
index 00000000000..2af95ca8b7a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/targetpointer/xml/targetpointer3xml.xml
@@ -0,0 +1,17 @@
+<file
+ xmlns:its="http://www.w3.org/2005/11/its" >
+ <its:rules version="2.0">
+ <its:param name="targetOneParam">firstfolder</its:param>
+ <its:param name="targetTwoParam">firstfile</its:param>
+ <its:targetPointerRule selector="//entry[@id='one']/source" targetPointer="../target[@id=$targetOneParam]"/>
+ <its:targetPointerRule selector="//entry[@id='two']/source" targetPointer="../target[@id=$targetTwoParam]"/>
+ </its:rules>
+ <entry id="one">
+ <source>Remember last folders</source>
+ <target id="firstfolder">firstFolder</target>
+ </entry>
+ <entry id="two">
+ <source>Custom file filter:</source>
+ <target id="firstfile">firstFile.txt</target>
+ </entry>
+</file>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/targetpointer/xml/targetpointer4xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/targetpointer/xml/targetpointer4xml.xml
new file mode 100644
index 00000000000..8f818262d15
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/targetpointer/xml/targetpointer4xml.xml
@@ -0,0 +1,11 @@
+<file>
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:xlink="http://www.w3.org/1999/xlink" version="2.0" xlink:href="targetpointer4xmlrules.xml"/>
+ <entry id="one">
+ <source>Remember last folders</source>
+ <target id="firstfolder">firstFolder</target>
+ </entry>
+ <entry id="two">
+ <source>Custom file filter:</source>
+ <target id="firstfile">firstFile.txt</target>
+ </entry>
+</file>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/targetpointer/xml/targetpointer4xmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/targetpointer/xml/targetpointer4xmlrules.xml
new file mode 100644
index 00000000000..0ed1d81ce7b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/targetpointer/xml/targetpointer4xmlrules.xml
@@ -0,0 +1,6 @@
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:param name="targetOneParam">firstfolder</its:param>
+ <its:param name="targetTwoParam">firstfile</its:param>
+ <its:targetPointerRule selector="//entry[@id='one']/source" targetPointer="../target[@id=$targetOneParam]"/>
+ <its:targetPointerRule selector="//entry[@id='two']/source" targetPointer="../target[@id=$targetTwoParam]"/>
+ </its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/html/terminology1html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/html/terminology1html.html
new file mode 100644
index 00000000000..0636d3f268b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/html/terminology1html.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+ <html>
+ <head>
+ <meta charset=utf-8>
+ <link href="terminology1htmlrules.xml" rel="its-rules"/>
+ <title>EXAMPLE</title>
+ </head>
+ <body>
+ <p id="term">
+ We may define
+ <a>discoursal point of view</a>
+ as
+ <cite id="TDPV">
+ the relationship, expressed through discourse structure, between the implied author or some other addresser, and the fiction.
+ </cite>
+ </p>
+ </body>
+ </html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/html/terminology1htmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/html/terminology1htmlrules.xml
new file mode 100644
index 00000000000..0326b23d444
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/html/terminology1htmlrules.xml
@@ -0,0 +1,3 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml" version="2.0">
+<its:termRule selector="//h:a[1]" term="yes" termInfoRef="#TDPV"/>
+</its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/html/terminology2html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/html/terminology2html.html
new file mode 100644
index 00000000000..a64eb18ef7a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/html/terminology2html.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+ <html>
+ <head>
+ <meta charset=utf-8>
+ <link href="terminology2htmlrules.xml" rel="its-rules"/>
+ <title>EXAMPLE</title>
+ </head>
+ <body>
+ <p>
+ We may define
+ <em id="keywords">discoursal point of view</em>
+ as
+ <dfn id="definitions">the relationship, expressed through discourse structure, between the implied author or some other addresser, and the fiction</dfn>
+ .
+ </p>
+ <p>
+ We may define
+ <em id="terms">refulgence</em>
+ as
+ <dfn id="refdef">a radiant or resplendent quality or state</dfn>
+ </p>
+ <p>
+ But I'm not sure how
+ <em id="term">quincunx</em>
+ can be defined.
+ </p>
+ </body>
+ </html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/html/terminology2htmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/html/terminology2htmlrules.xml
new file mode 100644
index 00000000000..2e4eea326bd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/html/terminology2htmlrules.xml
@@ -0,0 +1,5 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml" version="2.0">
+<its:termRule selector="//h:p[2]/h:em" term="yes" termInfoPointer="../h:dfn"/>
+<its:termRule selector="//h:p[3]/h:em" term="no"/>
+<its:termRule selector="//h:p[1]/h:em" term="yes" termInfoPointer="../h:dfn"/>
+</its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/html/terminology3html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/html/terminology3html.html
new file mode 100644
index 00000000000..4274b3f7028
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/html/terminology3html.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset=utf-8>
+ <title>Terminology test: default</title>
+ </head>
+ <body>
+ <p>We need a new <span its-term="yEs" its-term-info-ref="#TDPV">motherboard</span>
+ </p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/html/terminology4html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/html/terminology4html.html
new file mode 100644
index 00000000000..b84e5af63ef
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/html/terminology4html.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+ <html>
+ <head>
+ <meta charset=utf-8>
+ <link href="terminology4htmlrules.xml" rel="its-rules"/>
+ <title>EXAMPLE</title>
+ </head>
+ <body>
+ <p>
+ We may define
+ <em id="keywords">discoursal point of view</em>
+ as
+ <dfn id="definitions">the relationship, expressed through discourse structure, between the implied author or some other addresser, and the fiction</dfn>
+ .
+ </p>
+ <p>
+ We may define
+ <em id="terms">refulgence</em>
+ as
+ <dfn id="refdef">a radiant or resplendent quality or state</dfn>
+ </p>
+ <p>
+ But I'm not sure how
+ <em id="term">quincunx</em>
+ can be defined.
+ </p>
+ </body>
+ </html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/html/terminology4htmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/html/terminology4htmlrules.xml
new file mode 100644
index 00000000000..d405064dedb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/html/terminology4htmlrules.xml
@@ -0,0 +1,7 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml" version="2.0">
+<its:param name="termParam">keywords</its:param>
+<its:termRule selector="//h:p[2]/h:em" term="yes" termInfoPointer="../h:dfn"/>
+<its:termRule selector="//h:p[3]/h:em[@id=$termParam]" term="no"/>
+<its:termRule selector="//h:p[1]/h:em" term="yes" termInfoPointer="../h:dfn"/>
+</its:rules>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/html/terminology5html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/html/terminology5html.html
new file mode 100644
index 00000000000..c0ce5e2dc6c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/html/terminology5html.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8"/>
+ <title>Terminology test: default</title>
+ </head>
+ <body its-annotators-ref="text-analysis|file:///tools.xml#T1" >
+ <p>We need a new <span its-annotators-ref="terminology|http://example.com/term-tool#T2" its-term="YeS" its-term-info-ref="#TDPV" its-term-confidence="0.5">motherboard</span>
+ </p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/html/terminology6html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/html/terminology6html.html
new file mode 100644
index 00000000000..d35fd0b0e03
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/html/terminology6html.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+ <html>
+ <head>
+ <script type="application/its+xml">
+ <its:rules version="2.0" xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml">
+ <its:param name="termparam">term</its:param>
+ <its:termRule selector="//h:p[@id=$termparam]/h:a[1]" term="yes" termInfoRef="#TDPV"/>
+ </its:rules>
+ </script>
+ <meta charset=utf-8>
+ <title>EXAMPLE</title>
+ </head>
+ <body>
+ <p id="term">
+ We may define
+ <a>discoursal point of view</a>
+ as
+ <cite id="TDPV">
+ the relationship, expressed through discourse structure, between the implied author or some other addresser, and the fiction.
+ </cite>
+ </p>
+ </body>
+ </html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/xml/terminology1xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/xml/terminology1xml.xml
new file mode 100644
index 00000000000..55273b10bf5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/xml/terminology1xml.xml
@@ -0,0 +1,11 @@
+<text
+ xmlns:its="http://www.w3.org/2005/11/its" >
+ <its:rules version="2.0">
+ <its:termRule selector="//term" term="yes" termInfoPointer="id(@def)"/>
+ </its:rules>
+ <p>We may define <term def="TDPV">discoursal point of view</term>
+ as <gloss xml:id="TDPV">the relationship, expressed through discourse
+ structure, between the implied author or some other addresser,
+ and the fiction.</gloss>
+ </p>
+</text>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/xml/terminology2xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/xml/terminology2xml.xml
new file mode 100644
index 00000000000..33d794a6e36
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/xml/terminology2xml.xml
@@ -0,0 +1,9 @@
+<text>
+ <its:rules version="2.0" xmlns:its="http://www.w3.org/2005/11/its">
+ <its:termRule selector="//term[1]" term="yes" termInfoRef="#TDPV"/>
+ </its:rules>
+ <p>We may define <term>discoursal point of view</term>
+as <gloss xml:id="TDPV">the relationship, expressed through discourse
+structure, between the implied author or some other addresser,
+and the fiction.</gloss></p>
+</text>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/xml/terminology3xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/xml/terminology3xml.xml
new file mode 100644
index 00000000000..3d913c81e0b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/xml/terminology3xml.xml
@@ -0,0 +1,10 @@
+<text>
+ <its:rules version="2.0" xmlns:its="http://www.w3.org/2005/11/its">
+ <its:termRule selector="//term" term="yes"
+ termInfoRefPointer="@target"/>
+ </its:rules>
+ <p>We may define <term target="#TDPV">discoursal point of view</term>
+as <gloss xml:id="TDPV">the relationship, expressed through discourse
+structure, between the implied author or some other addresser,
+and the fiction.</gloss></p>
+</text>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/xml/terminology4xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/xml/terminology4xml.xml
new file mode 100644
index 00000000000..33d122b297b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/xml/terminology4xml.xml
@@ -0,0 +1,19 @@
+<text>
+ <head>
+ <its:rules version="2.0" xmlns:its="http://www.w3.org/2005/11/its"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xlink:href="terminology4xmlrules.xml">
+ <its:termRule selector="//p[2]/term" term="yes"
+ termInfoPointer="../gloss"/>
+ <its:termRule selector="//p[3]/term" term="no"/>
+ </its:rules>
+ <keywords><kw>terms</kw>, <kw>rare <kw>words</kw></kw></keywords>
+ </head>
+ <p>We may define <term>discoursal point of view</term>
+as <def>the relationship, expressed through discourse
+structure, between the implied author or some other addresser,
+and the fiction</def>.</p>
+ <p>We may define <term>refulgence</term>
+as <gloss id="refdef">a radiant or resplendent quality or state.</gloss></p>
+ <p>But I'm not sure how <term>quincunx</term> can be defined.</p>
+</text>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/xml/terminology4xmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/xml/terminology4xmlrules.xml
new file mode 100644
index 00000000000..7946cee28f4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/xml/terminology4xmlrules.xml
@@ -0,0 +1,5 @@
+<its:rules version="2.0" xmlns:its="http://www.w3.org/2005/11/its">
+ <its:termRule selector="//term" term="yes"
+ termInfoPointer="../def"/>
+ <its:termRule selector="//kw" term="yes"/>
+</its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/xml/terminology5xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/xml/terminology5xml.xml
new file mode 100644
index 00000000000..3ff4c769b99
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/xml/terminology5xml.xml
@@ -0,0 +1,7 @@
+<doc its:version="2.0" xmlns:its="http://www.w3.org/2005/11/its">
+ <section xml:id="S001">
+ <par>A <kw its:term="yes" its:termInfoRef="http://en.wikipedia.org/wiki/Motherboard">motherboard</kw>,
+ also known as a <kw its:term="yes">logic <span its:term="yes">board</span></kw> on Apple Computers,
+ is the primary circuit board making up a modern computer.</par>
+ </section>
+</doc>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/xml/terminology6xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/xml/terminology6xml.xml
new file mode 100644
index 00000000000..52bd0ecd41c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/xml/terminology6xml.xml
@@ -0,0 +1,7 @@
+<doc its:version="2.0" xmlns:its="http://www.w3.org/2005/11/its">
+ <section xml:id="S001">
+ <par>A <its:span term="yes" termInfoRef="http://en.wikipedia.org/wiki/Motherboard">motherboard</its:span>,
+ also known as a <its:span term="yes">logic <its:span term="yes">board</its:span></its:span> on Apple Computers,
+ is the primary circuit board making up a modern computer.</par>
+ </section>
+</doc>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/xml/terminology7xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/xml/terminology7xml.xml
new file mode 100644
index 00000000000..440004956d2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/xml/terminology7xml.xml
@@ -0,0 +1,17 @@
+<text>
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+<its:param name="termInfoRefPointer">2</its:param>
+<its:termRule selector="//p[@id=$termInfoRefPointer]/term" term="yes" termInfoRefPointer="@target"/>
+</its:rules>
+<p id="1">
+This is a glossary of terms.
+</p>
+<p id="2">
+We may define
+<term target="#TDPV">discoursal point of view</term>
+as
+<gloss xml:id="TDPV">
+the relationship, expressed through discourse structure, between the implied author or some other addresser, and the fiction.
+</gloss>
+</p>
+</text>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/xml/terminology8xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/xml/terminology8xml.xml
new file mode 100644
index 00000000000..b53f730930b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/xml/terminology8xml.xml
@@ -0,0 +1,14 @@
+<text>
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:xlink="http://www.w3.org/1999/xlink" version="2.0" xlink:type="simple" xlink:href="terminology8xmlrules.xml"/>
+<p id="1">
+This is a glossary of terms.
+</p>
+<p id="2">
+We may define
+<term target="#TDPV">discoursal point of view</term>
+as
+<gloss xml:id="TDPV">
+the relationship, expressed through discourse structure, between the implied author or some other addresser, and the fiction.
+</gloss>
+</p>
+</text>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/xml/terminology8xmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/xml/terminology8xmlrules.xml
new file mode 100644
index 00000000000..26501b63beb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/xml/terminology8xmlrules.xml
@@ -0,0 +1,4 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+<its:param name="termInfoRefPointer">2</its:param>
+<its:termRule selector="//p[@id=$termInfoRefPointer]/term" term="yes" termInfoRefPointer="@target"/>
+</its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/xml/terminology9xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/xml/terminology9xml.xml
new file mode 100644
index 00000000000..bf74f2669bd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/terminology/xml/terminology9xml.xml
@@ -0,0 +1,6 @@
+<book its:version="2.0" xmlns:its="http://www.w3.org/2005/11/its">
+ <head>Sample file</head>
+ <body its:annotatorsRef="text-analysis|file:///tools.xml#T1">
+ <p>And he said: you need a new <quote its:annotatorsRef="terminology|http://example.com/term-tool#T2" its:term="yes" its:termInfoRef="http://www.directron.com/motherboards1.html" its:termConfidence="0.5">motherboard</quote></p>
+ </body>
+</book>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/html/textanalysis1html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/html/textanalysis1html.html
new file mode 100644
index 00000000000..3202821838b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/html/textanalysis1html.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset=utf-8>
+ <link href="textanalysis1htmlrules.xml" rel="its-rules"/>
+ <title>Text Analysis: Local Test</title>
+ </head>
+ <body>
+ <p>
+ <span id="dublin" typeof="http://nerd.eurecom.fr/ontology#Location" property="http://dbpedia.org/resource/Dublin">Dublin</span> is the <span id="capital" typeof="http://nerd.eurecom.fr/ontology#City" about="301467919" property="Wordnet3.0">capital</span> of Ireland.</p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/html/textanalysis1htmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/html/textanalysis1htmlrules.xml
new file mode 100644
index 00000000000..c6245b71e17
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/html/textanalysis1htmlrules.xml
@@ -0,0 +1,9 @@
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0" xmlns:h="http://www.w3.org/1999/xhtml">
+ <its:textAnalysisRule selector="//h:body/h:p/h:*[@id='dublin']"
+ taClassRefPointer="@typeof"
+ taIdentRefPointer="@property"/>
+ <its:textAnalysisRule selector="//h:body/h:p/h:*[@id='capital']"
+ taClassRefPointer="@typeof"
+ taSourcePointer="@property"
+ taIdentPointer="@about"/>
+ </its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/html/textanalysis2html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/html/textanalysis2html.html
new file mode 100644
index 00000000000..39c45f9ccee
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/html/textanalysis2html.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset=utf-8>
+ <link href="textanalysis2htmlrules.xml" rel="its-rules"/>
+ <title>Text Analysis: Local Test</title>
+ </head>
+ <body>
+ <p>
+ <span id="dublin" typeof="http://nerd.eurecom.fr/ontology#Location" property="http://dbpedia.org/resource/Dublin">Dublin</span> is the <span id="capital" typeof="http://nerd.eurecom.fr/ontology#City" about="301467919" property="Wordnet3.0">capital</span> of Ireland.</p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/html/textanalysis2htmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/html/textanalysis2htmlrules.xml
new file mode 100644
index 00000000000..c5601a9ed78
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/html/textanalysis2htmlrules.xml
@@ -0,0 +1,11 @@
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0" xmlns:h="http://www.w3.org/1999/xhtml">
+ <its:param name="taCityParam">dublin</its:param>
+ <its:param name="taCapitalParam">capital</its:param>
+ <its:textAnalysisRule selector="//h:body/h:p/h:*[@id=$taCityParam]"
+ taClassRefPointer="@typeof"
+ taIdentRefPointer="@property"/>
+ <its:textAnalysisRule selector="//h:body/h:p/h:*[@id=$taCapitalParam]"
+ taClassRefPointer="@typeof"
+ taSourcePointer="@property"
+ taIdentPointer="@about"/>
+ </its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/html/textanalysis3html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/html/textanalysis3html.html
new file mode 100644
index 00000000000..bf5e466578b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/html/textanalysis3html.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html lang=en>
+ <head>
+ <meta charset=utf-8>
+ <link href="textanalysis3htmlrules.xml" rel=its-rules>
+ <title>Text Analysis: Local Test</title>
+ </head>
+ <body>
+ <p><span id="dublin" property="http://xmlns.com/foaf/0.1/name"
+ about="http://dbpedia.org/resource/Dublin"
+ typeof="http://nerd.eurecom.fr/ontology#Location">Dublin</span> is
+ the <span id="capital">capital</span> of Ireland.</p>
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/html/textanalysis3htmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/html/textanalysis3htmlrules.xml
new file mode 100644
index 00000000000..d88271f30c9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/html/textanalysis3htmlrules.xml
@@ -0,0 +1,5 @@
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0" xmlns:h="http://www.w3.org/1999/xhtml">
+ <its:textAnalysisRule selector="//h:body/h:p/h:*[@id='dublin']"
+ taClassRefPointer="@typeof"
+ taIdentRefPointer="@about"/>
+ </its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/html/textanalysis4html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/html/textanalysis4html.html
new file mode 100644
index 00000000000..42ff1d37b53
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/html/textanalysis4html.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html lang="en" its-annotators-ref="text-analysis|http://enrycher.ijs.si">
+ <head>
+ <meta charset=utf-8>
+ <title>Text Analysis: Local Test</title>
+ </head>
+ <body>
+ <p><span
+ its-ta-confidence="0.7"
+ its-ta-class-ref="http://nerd.eurecom.fr/ontology#Location"
+ its-ta-ident-ref="http://dbpedia.org/resource/Dublin"
+ >Dublin</span>
+ is the <span
+ its-ta-source="Wordnet3.0"
+ its-ta-ident="301467919"
+ its-ta-confidence="0.5"
+ >capital</span> of Ireland.</p>
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/html/textanalysis5html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/html/textanalysis5html.html
new file mode 100644
index 00000000000..8f673df4ce7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/html/textanalysis5html.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <script type="application/its+xml">
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0" xmlns:h="http://www.w3.org/1999/xhtml">
+ <its:param name="taCityParam">dublin</its:param>
+ <its:param name="taCapitalParam">capital</its:param>
+ <its:textAnalysisRule selector="//h:body/h:p/h:*[@id=$taCityParam]"
+ taClassRefPointer="@typeof"
+ taIdentRefPointer="@property"/>
+ <its:textAnalysisRule selector="//h:body/h:p/h:*[@id=$taCapitalParam]"
+ taClassRefPointer="@typeof"
+ taSourcePointer="@property"
+ taIdentPointer="@about"/>
+ </its:rules>
+ </script>
+ <meta charset=utf-8>
+ <title>Textanalysis: Local Test</title>
+ </head>
+ <body>
+ <p><span id="dublin" typeof="http://nerd.eurecom.fr/ontology#Location" property="http://dbpedia.org/resource/Dublin">Dublin</span> is the <span id="capital" typeof="http://nerd.eurecom.fr/ontology#City" about="301467919" property="Wordnet3.0">capital</span> of Ireland.</p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/xml/textanalysis1xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/xml/textanalysis1xml.xml
new file mode 100644
index 00000000000..0aa9803ac3b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/xml/textanalysis1xml.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0"?>
+<text>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:textAnalysisRule selector="/text/body/p/*[@id='dublin']"
+ taClassRefPointer="@classref"
+ taIdentRefPointer="@identref"/>
+ <its:textAnalysisRule selector="/text/body/p/*[@id='capital']"
+ taClassRefPointer="@classref"
+ taSourcePointer="@source"
+ taIdentPointer="@ident"/>
+ </its:rules>
+ <body>
+ <p><span classref="http://nerd.eurecom.fr/ontology#Location" id="dublin" identref="http://dbpedia.org/resource/Dublin">Dublin</span> is the <span id="capital" classref="http://nerd.eurecom.fr/ontology#City" source="Wordnet3.0" ident="301467919">capital</span> of Ireland.</p>
+ </body>
+</text>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/xml/textanalysis2xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/xml/textanalysis2xml.xml
new file mode 100644
index 00000000000..74ffc81194d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/xml/textanalysis2xml.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0"?>
+<text>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="textanalysis2xmlrules.xml"/>
+ <body>
+ <p><span classref="http://nerd.eurecom.fr/ontology#Location" id="dublin" identref="http://dbpedia.org/resource/Dublin">Dublin</span> is the <span id="capital" classref="http://nerd.eurecom.fr/ontology#City" source="Wordnet3.0" ident="301467919">capital</span> of Ireland.</p>
+ </body>
+</text>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/xml/textanalysis2xmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/xml/textanalysis2xmlrules.xml
new file mode 100644
index 00000000000..eb25afba0cf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/xml/textanalysis2xmlrules.xml
@@ -0,0 +1,9 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:textAnalysisRule selector="/text/body/p/*[@id='dublin']"
+ taClassRefPointer="@classref"
+ taIdentRefPointer="@identref"/>
+ <its:textAnalysisRule selector="/text/body/p/*[@id='capital']"
+ taClassRefPointer="@classref"
+ taSourcePointer="@source"
+ taIdentPointer="@ident"/>
+ </its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/xml/textanalysis3xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/xml/textanalysis3xml.xml
new file mode 100644
index 00000000000..108061ce8a3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/xml/textanalysis3xml.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0"?>
+<text>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:param name="taCityParam">dublin</its:param>
+ <its:param name="taCapitalParam">capital</its:param>
+ <its:textAnalysisRule selector="/text/body/p/*[@id='dublin']"
+ taClassRefPointer="@classref"
+ taIdentRefPointer="@identref"/>
+ <its:textAnalysisRule selector="/text/body/p/*[@id='capital']"
+ taClassRefPointer="@classref"
+ taSourcePointer="@source"
+ taIdentPointer="@ident"/>
+ </its:rules>
+ <body>
+ <p><span classref="http://nerd.eurecom.fr/ontology#Location" id="dublin" identref="http://dbpedia.org/resource/Dublin">Dublin</span> is the <span id="capital" classref="http://nerd.eurecom.fr/ontology#City" source="Wordnet3.0" ident="301467919">capital</span> of Ireland.</p>
+ </body>
+</text>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/xml/textanalysis4xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/xml/textanalysis4xml.xml
new file mode 100644
index 00000000000..e90c6c33fcd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/xml/textanalysis4xml.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0"?>
+<text>
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="textanalysis4xmlrules.xml"/>
+ <body>
+ <p><span classref="http://nerd.eurecom.fr/ontology#Location" id="dublin" identref="http://dbpedia.org/resource/Dublin">Dublin</span> is the <span id="capital" classref="http://nerd.eurecom.fr/ontology#City" source="Wordnet3.0" ident="301467919">capital</span> of Ireland.</p>
+ </body>
+</text>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/xml/textanalysis4xmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/xml/textanalysis4xmlrules.xml
new file mode 100644
index 00000000000..1a437e6cd10
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/xml/textanalysis4xmlrules.xml
@@ -0,0 +1,11 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:param name="taCityParam">dublin</its:param>
+ <its:param name="taCapitalParam">capital</its:param>
+ <its:textAnalysisRule selector="/text/body/p/*[@id='dublin']"
+ taClassRefPointer="@classref"
+ taIdentRefPointer="@identref"/>
+ <its:textAnalysisRule selector="/text/body/p/*[@id='capital']"
+ taClassRefPointer="@classref"
+ taSourcePointer="@source"
+ taIdentPointer="@ident"/>
+ </its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/xml/textanalysis5xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/xml/textanalysis5xml.xml
new file mode 100644
index 00000000000..b570404cb05
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/xml/textanalysis5xml.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0"?>
+<text xmlns:its="http://www.w3.org/2005/11/its" its:version="2.0" its:annotatorsRef="text-analysis|http://enrycher.ijs.si">
+ <body>
+ <p><span its:taClassRef="http://nerd.eurecom.fr/ontology#Location" its:taIdentRef="http://dbpedia.org/resource/Dublin" its:taConfidence="0.7">Dublin</span> is the <span its:taSource="Wordnet3.0" its:taIdent="301467919" its:taConfidence="0.5">capital</span> of Ireland.</p>
+ </body>
+</text>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/xml/textanalysis6xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/xml/textanalysis6xml.xml
new file mode 100644
index 00000000000..1ffc6516988
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/xml/textanalysis6xml.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0"?>
+<text xmlns:its="http://www.w3.org/2005/11/its" its:version="2.0" its:annotatorsRef="text-analysis|http://enrycher.ijs.si">
+ <body>
+ <p><its:span taClassRef="http://nerd.eurecom.fr/ontology#Location" taIdentRef="http://dbpedia.org/resource/Dublin" taConfidence="0.7"
+>Dublin</its:span> is the <its:span taSource="Wordnet3.0" taIdent="301467919" taConfidence="0.5">capital</its:span> of Ireland.</p>
+ </body>
+</text>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/xml/textanalysis7xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/xml/textanalysis7xml.xml
new file mode 100644
index 00000000000..f69754392f9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/xml/textanalysis7xml.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0"?>
+<text>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:textAnalysisRule selector="/text/body/p/*[@id='dublin']"
+ taClassRefPointer="@classref"
+ taIdentRefPointer="@identref"/>
+ <its:textAnalysisRule selector="/text/body/p/*[@id='capital']"
+ taSourcePointer="@source"
+ taIdentPointer="@ident"/>
+ </its:rules>
+ <body>
+ <p><span classref="http://nerd.eurecom.fr/ontology#Location" identref="http://dbpedia.org/resource/Dublin" id="dublin">Dublin</span> is the <span source="Wordnet3.0" ident="301467919" id="capital">capital</span> of Ireland.</p>
+ </body>
+</text>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/xml/textanalysis8xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/xml/textanalysis8xml.xml
new file mode 100644
index 00000000000..563d4fac055
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/xml/textanalysis8xml.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0"?>
+<text>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="textanalysis8xmlrules.xml"/>
+ <body>
+ <p><span classref="http://nerd.eurecom.fr/ontology#Location" identref="http://dbpedia.org/resource/Dublin" id="dublin">Dublin</span> is the <span source="Wordnet3.0" ident="301467919" id="capital">capital</span> of Ireland.</p>
+ </body>
+</text>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/xml/textanalysis8xmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/xml/textanalysis8xmlrules.xml
new file mode 100644
index 00000000000..05894fcaaf0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/textanalysis/xml/textanalysis8xmlrules.xml
@@ -0,0 +1,8 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:textAnalysisRule selector="/text/body/p/*[@id='dublin']"
+ taClassRefPointer="@classref"
+ taIdentRefPointer="@identref"/>
+ <its:textAnalysisRule selector="/text/body/p/*[@id='capital']"
+ taSourcePointer="@source"
+ taIdentPointer="@ident"/>
+ </its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/html/translate1html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/html/translate1html.html
new file mode 100644
index 00000000000..e31fcae0f55
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/html/translate1html.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>HTML Link Example</title>
+ <link href="translate1htmlrules.xml" rel="its-rules"/>
+ </head>
+ <body>
+ <img src="smiley.gif" alt="Smiley face" width="42" height="42"/>
+ <p id="100" title="Text">
+ This is the first paragraph. It has some
+ <code>un-translatable code</code>
+ .
+ </p>
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/html/translate1htmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/html/translate1htmlrules.xml
new file mode 100644
index 00000000000..bd51763afdc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/html/translate1htmlrules.xml
@@ -0,0 +1,4 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml" version="2.0">
+ <its:translateRule selector="//h:code" translate="no"/>
+ <its:translateRule selector="//h:link" translate="no"/>
+</its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/html/translate2html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/html/translate2html.html
new file mode 100644
index 00000000000..576eaea3a34
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/html/translate2html.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+ <html lang="en">
+ <head>
+ <meta charset=utf-8>
+ <title>The Life of a Simple Man</title>
+ </head>
+ <body>
+ <p>
+ <img src="smiley.gif" alt="Smiley face" width="42" height="42"/>
+ Everything started when Zebulon discovered that he had a
+ <span translate="NO">doppelgänger</span>
+ who was a serious baseball
+ <span translate="nO">aficionado</span>
+ .
+ </p>
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/html/translate3html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/html/translate3html.html
new file mode 100644
index 00000000000..a88bd1ac6d1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/html/translate3html.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+ <html>
+ <head>
+ <meta charset=utf-8>
+ <title>EXAMPLE</title>
+ <link href="translate3htmlrules.xml" rel="its-rules"/>
+ </head>
+ <body>
+ <span translate="yes">The Life of a Simple Man</span>
+ <!--
+ Note that the contents of <b> and <span> should end up *not* translatable with these settings
+ -->
+ <section title="section one">
+ <h2>section one</h2>
+ <p>
+ Everything started when Zebulon discovered that he had a
+ <span>doppelgänger</span>
+ who was a serious baseball
+ <span>aficionado</span>
+ .
+ </p>
+ </section>
+ </body>
+ </html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/html/translate3htmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/html/translate3htmlrules.xml
new file mode 100644
index 00000000000..6193ec01dd8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/html/translate3htmlrules.xml
@@ -0,0 +1,4 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml" version="2.0">
+<its:translateRule selector="//h:*" translate="no"/>
+<its:translateRule selector="//h:p" translate="yes"/>
+</its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/html/translate4html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/html/translate4html.html
new file mode 100644
index 00000000000..a2a4d958561
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/html/translate4html.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+ <html>
+ <head>
+ <meta charset=utf-8>
+ <title>EXAMPLE</title>
+ <link href="translate4htmlrules.xml" rel="its-rules"/>
+ </head>
+ <body>
+ <span translate="yes">The Life of a Simple Man</span>
+ <!--
+ Note that the contents of <b> and <span> should end up *not* translatable with these settings
+ -->
+ <section>
+ <h2>section</h2>
+ <p>
+ Everything started when Zebulon discovered that he had a
+ <span>doppelgänger</span>
+ who was a serious baseball
+ <span>aficionado</span>
+ .
+ </p>
+ </section>
+ </body>
+ </html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/html/translate4htmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/html/translate4htmlrules.xml
new file mode 100644
index 00000000000..c252a2de85f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/html/translate4htmlrules.xml
@@ -0,0 +1,4 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml" version="2.0">
+<its:translateRule selector="/h:html" translate="no"/>
+<its:translateRule selector="//h:p" translate="yes"/>
+</its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/html/translate5html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/html/translate5html.html
new file mode 100644
index 00000000000..c64c0cd5012
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/html/translate5html.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+ <html>
+ <head>
+ <meta charset=utf-8>
+ <title>The ITS Topic</title>
+ <link href="translate5htmlrules.xml" rel="its-rules"/>
+ </head>
+ <body>
+ <section>
+ <h2>Data category</h2>
+ <span id="tDataCat">
+ <b>Data category</b>
+ <cite>
+ ITS defines
+ <i>data category</i>
+ as an abstract concept for a particular type of information for internationalization and localization of XML schemas and documents.
+ </cite>
+ </span>
+ </section>
+ <p>
+ For the implementation of ITS, apply the rules in the order:
+ </p>
+ <ul>
+ <li>Default</li>
+ <li>Rules in the schema</li>
+ <li>Rules in the document instance</li>
+ <li>Local attributes</li>
+ </ul>
+ <p>
+ <span lang="fr">Et voila !</span>
+ The last rule wins.
+ </p>
+ </body>
+ </html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/html/translate5htmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/html/translate5htmlrules.xml
new file mode 100644
index 00000000000..6193ec01dd8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/html/translate5htmlrules.xml
@@ -0,0 +1,4 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml" version="2.0">
+<its:translateRule selector="//h:*" translate="no"/>
+<its:translateRule selector="//h:p" translate="yes"/>
+</its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/html/translate6html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/html/translate6html.html
new file mode 100644
index 00000000000..82cc62c9888
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/html/translate6html.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+ <html>
+ <head>
+ <meta charset=utf-8>
+ <title>The ITS Topic</title>
+ <link href="translate6htmlrules.xml" rel="its-rules"/>
+ </head>
+ <body>
+ <section>
+ <h2>Data category</h2>
+ <span id="tDataCat">
+ <b>Data category</b>
+ <cite>
+ ITS defines
+ <i>data category</i>
+ as an abstract concept for a particular type of information for internationalization and localization of XML schemas and documents.
+ </cite>
+ </span>
+ </section>
+ <p>
+ For the implementation of ITS, apply the rules in the order:
+ </p>
+ <ul>
+ <li>Default</li>
+ <li>Rules in the schema</li>
+ <li>Rules in the document instance</li>
+ <li>Local attributes</li>
+ </ul>
+ <p>
+ <span lang="fr">Et voila !</span>
+ The last rule wins.
+ </p>
+ </body>
+ </html>
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/html/translate6htmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/html/translate6htmlrules.xml
new file mode 100644
index 00000000000..dadbad16754
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/html/translate6htmlrules.xml
@@ -0,0 +1,6 @@
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml" version="2.0">
+<its:param name="tDataCatParam">tDataCat</its:param>
+<its:translateRule selector="//h:*" translate="no"/>
+<its:translateRule selector="//h:p" translate="yes"/>
+<its:translateRule selector="//h:span[@id=$tDataCatParam]" translate="yes"/>
+</its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/html/translate7html.html b/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/html/translate7html.html
new file mode 100644
index 00000000000..c17322df8ce
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/html/translate7html.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html lang=en>
+ <head>
+<script type="application/its+xml">
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:h="http://www.w3.org/1999/xhtml" version="2.0">
+ <its:param name="translateparam">name</its:param>
+ <its:translateRule selector="//h:*[@id=$translateparam]" translate="no"/>
+ </its:rules>
+</script>
+ <meta charset="utf-8"/>
+ <title>Example</title>
+ </head>
+ <body title="login details">
+<p style="color:green">Login names can only use letters from A to Z (upper or lowercase)
+ For example: <code id="name">Huck_Finn</code>.</p>
+ </body>
+</html>
+
+
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/xml/translate10xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/xml/translate10xml.xml
new file mode 100644
index 00000000000..0559c51c95b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/xml/translate10xml.xml
@@ -0,0 +1,7 @@
+<doc>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" xmlns:xlink="http://www.w3.org/1999/xlink" version="2.0" xlink:type="simple" xlink:href="translate10xmlrules.xml"/>
+ <msg lcid="409" num="1">Create a folder</msg>
+ <msg lcid="411" num="1">フォルダーを作成する</msg>
+ <msg lcid="407" num="1">Erstellen Sie einen Ordner</msg>
+ <msg lcid="408" num="1">Créer un dossier</msg>
+</doc>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/xml/translate10xmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/xml/translate10xmlrules.xml
new file mode 100644
index 00000000000..5b32c690592
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/xml/translate10xmlrules.xml
@@ -0,0 +1,5 @@
+ <its:rules version="2.0" xmlns:its="http://www.w3.org/2005/11/its">
+ <its:param name="LCID">409</its:param>
+ <its:translateRule selector="/doc" translate="no"/>
+ <its:translateRule selector="//msg[@lcid=$LCID]" translate="yes"/>
+ </its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/xml/translate1xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/xml/translate1xml.xml
new file mode 100644
index 00000000000..5649d70af49
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/xml/translate1xml.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0"?>
+<myMetaDoc
+ xmlns:cml="myChineseMakupLanguage">
+ <head>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:translateRule selector="//img/@alt" translate="yes"/>
+ <its:translateRule selector="//*/@title" translate="yes"/>
+ <its:translateRule selector="//verbatim" translate="no"/>
+ <its:translateRule selector="//verbatim/@*" translate="no"/>
+ <its:translateRule selector="//verbatim//*/@*" translate="no"/>
+ <its:withinTextRule selector="//img|//verbatim" withinText="yes"/>
+ </its:rules>
+ </head>
+ <body>
+ <par>Text with an image: <img alt="Image description" src="img.png"/>.</par>
+ <par id="100" title="Text">This is the first paragraph. It has some <verbatim>un-translatable
+ code with an image: <img src="test.png" alt="Image description"/></verbatim>.</par>
+ <insert xmlns:z="myChineseMakupLanguage" xmlns:i="http://www.w3.org/2005/11/its">
+ <z:书籍>
+ <z:封面>
+ <z:汇集>The Lord of the Rings</z:汇集>
+ <z:标题>The Return of the King</z:标题>
+ <z:作者>J.R.R. Tolkein</z:作者>
+ </z:封面>
+ <z:章节 数="1">
+ <z:头注>Minas Tirith</z:头注>
+ <z:段落识别 id="A34B"><z:姓名>Pippin</z:姓名> looked out from the shelter of <z:姓名>Gandalf</z:姓名>'s cloak.</z:段落识别>
+ </z:章节>
+ <z:躯>
+ <i:rules version="2.0" xmlns:cml="myChineseMakupLanguage">
+ <i:translateRule selector="//cml:作者" translate="no"/>
+ <i:translateRule selector="//cml:姓名" translate="no"/>
+ <i:withinTextRule selector="//cml:姓名" withinText="yes"/>
+ </i:rules>
+ </z:躯>
+ </z:书籍>
+ </insert>
+ </body>
+</myMetaDoc>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/xml/translate2xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/xml/translate2xml.xml
new file mode 100644
index 00000000000..68bfd3f28a8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/xml/translate2xml.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0"?>
+<myDoc>
+ <head>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0"
+ xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="translate2xmlrules.xml"/>
+ </head>
+ <body>
+ <par id="100" title="Text">This is the first paragraph. It has some <code>un-translatable code</code>.</par>
+ </body>
+</myDoc>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/xml/translate2xmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/xml/translate2xmlrules.xml
new file mode 100644
index 00000000000..69de855fc33
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/xml/translate2xmlrules.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0"?>
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:translateRule selector="//code" translate="no"/>
+ <its:translateRule selector="//*/@title" translate="yes"/>
+</its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/xml/translate3xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/xml/translate3xml.xml
new file mode 100644
index 00000000000..fcccc69841a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/xml/translate3xml.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0"?>
+<myDoc>
+ <head>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0"
+ xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:href="translate3xmlrules.xml">
+ <its:translateRule selector="//par[@id='101']/@title" translate="no"/>
+ </its:rules>
+ </head>
+ <body>
+ <par id="100" title="Text">This is the first paragraph. It has some <code>un-translatable code</code>.</par>
+ <par id="101" title="Not extractable text">Some additional text.</par>
+ </body>
+</myDoc>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/xml/translate3xmlrules.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/xml/translate3xmlrules.xml
new file mode 100644
index 00000000000..0a45c97553b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/xml/translate3xmlrules.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0"?>
+<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:translateRule selector="//head" translate="no"/>
+ <its:translateRule selector="//code" translate="no"/>
+ <its:translateRule selector="//*/@title" translate="yes"/>
+</its:rules>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/xml/translate4xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/xml/translate4xml.xml
new file mode 100644
index 00000000000..bc1ee7d64fa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/xml/translate4xml.xml
@@ -0,0 +1,11 @@
+<book xmlns:its="http://www.w3.org/2005/11/its" its:version="2.0">
+ <head>
+ <title>The Life of a Simple Man</title>
+ </head>
+ <body>
+ <img src="smiley.gif" alt="Smiley face" width="42" height="42"/>
+ <p>Everything started when Zebulon discovered that he had
+ a <fexp its:translate="no">doppelgänger</fexp> who was a
+ serious baseball <fexp its:translate="no">aficionado</fexp>.</p>
+ </body>
+</book>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/xml/translate5xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/xml/translate5xml.xml
new file mode 100644
index 00000000000..9dceba576a4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/xml/translate5xml.xml
@@ -0,0 +1,13 @@
+<book xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="EX-ways-to-use-its-5.xsd"
+ xmlns:its="http://www.w3.org/2005/11/its"
+ its:version="2.0">
+ <head>
+ <title>The Life of a Simple Man</title>
+ </head>
+ <body>
+ <p>Everything started when Zebulon discovered that he had
+ a <its:span translate="no">doppelgänger</its:span> who was a
+ serious baseball <its:span translate="no">aficionado</its:span>.</p>
+ </body>
+</book>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/xml/translate6xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/xml/translate6xml.xml
new file mode 100644
index 00000000000..28bbea14d90
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/xml/translate6xml.xml
@@ -0,0 +1,19 @@
+<doc xmlns:its="http://www.w3.org/2005/11/its" its:version="2.0">
+ <head>
+ <its:rules version="2.0">
+ <its:translateRule selector="//*" translate="no"/>
+ <its:translateRule selector="//p" translate="yes"/>
+ </its:rules>
+ </head>
+ <info>
+ <item type="title" its:translate="yes">The Life of a <b>Simple Man</b></item>
+ <!-- Note that the contents of <b> and <span> should end up
+ *not* translatable with these settings -->
+ <item type="date-main">Dec-05-2006</item>
+ </info>
+ <content>
+ <p>Everything started when Zebulon discovered that he had
+ a <span>doppelgänger</span> who was a
+ serious baseball <span>aficionado</span>.</p>
+ </content>
+</doc>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/xml/translate7xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/xml/translate7xml.xml
new file mode 100644
index 00000000000..20e9ea70b3d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/xml/translate7xml.xml
@@ -0,0 +1,19 @@
+<doc xmlns:its="http://www.w3.org/2005/11/its" its:version="2.0">
+ <head>
+ <its:rules version="2.0">
+ <its:translateRule selector="/doc" translate="no"/>
+ <its:translateRule selector="//p" translate="yes"/>
+ </its:rules>
+ </head>
+ <info>
+ <item type="title" its:translate="yes">The Life of a <b>Simple Man</b></item>
+ <!-- Note that the contents of <b> and <span> should end up
+ translatable with these settings -->
+ <item type="date-main">Dec-05-2006</item>
+ </info>
+ <content>
+ <p>Everything started when Zebulon discovered that he had
+ a <span>doppelgänger</span> who was a
+ serious baseball <span>aficionado</span>.</p>
+ </content>
+</doc>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/xml/translate8xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/xml/translate8xml.xml
new file mode 100644
index 00000000000..4692cdb0870
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/xml/translate8xml.xml
@@ -0,0 +1,28 @@
+<topic id="myTopic">
+ <title>The ITS Topic</title>
+ <prolog>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:translateRule selector="//*" translate="no"/>
+ <its:translateRule selector="//p" translate="yes"/>
+ <!-- With these rules only the text "For the implementation of ITS, apply the rules in the order:"
+ and " The last rule wins." should end up translatable -->
+ </its:rules>
+ </prolog>
+ <body>
+ <dl>
+ <dlentry id="tDataCat">
+ <dt>Data category</dt>
+ <dd>ITS defines <term>data category</term> as an abstract concept for a particular
+ type of information for internationalization and localization of XML schemas and documents.</dd>
+ </dlentry>
+ </dl>
+ <p>For the implementation of ITS, apply the rules in the order:</p>
+ <ul>
+ <li>Default</li>
+ <li>Rules in the schema</li>
+ <li>Rules in the document instance</li>
+ <li>Local attributes</li>
+ </ul>
+ <p><ph xml:lang="fr">Et voilà !</ph> The last rule wins.</p>
+ </body>
+</topic>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/xml/translate9xml.xml b/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/xml/translate9xml.xml
new file mode 100644
index 00000000000..f8606b68ff5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-its/translate/xml/translate9xml.xml
@@ -0,0 +1,11 @@
+<doc>
+ <its:rules xmlns:its="http://www.w3.org/2005/11/its" version="2.0">
+ <its:param name="LCID">409</its:param>
+ <its:translateRule selector="/doc" translate="no"/>
+ <its:translateRule selector="//msg[@lcid=$LCID]" translate="yes"/>
+ </its:rules>
+ <msg lcid="409" num="1">Create a folder</msg>
+ <msg lcid="411" num="1">フォルダーを作成する</msg>
+ <msg lcid="407" num="1">Erstellen Sie einen Ordner</msg>
+ <msg lcid="40c" num="1">Créer un dossier</msg>
+</doc>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0001-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0001-isvalid.html
new file mode 100644
index 00000000000..c7c2d8b33dc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0001-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html prefix="dc: http://purl.org/dc/elements/1.1/">
+<head>
+ <meta charset=utf-8>
+ <title>Test 0001</title>
+</head>
+<body>
+ <p>This photo was taken by <span class="author" about="photo1.jpg" property="dc:creator">Mark Birbeck</span>.</p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0006-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0006-isvalid.html
new file mode 100644
index 00000000000..6c5e168cfa1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0006-isvalid.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html prefix="dc: http://purl.org/dc/elements/1.1/ foaf: http://xmlns.com/foaf/0.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0006</title>
+ </head>
+ <body>
+ <p>
+ This photo was taken by
+ <a about="photo1.jpg" rel="dc:creator" rev="foaf:img"
+ href="http://www.blogger.com/profile/1109404">Mark Birbeck</a>.
+ </p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0007-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0007-isvalid.html
new file mode 100644
index 00000000000..1e6df222ac2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0007-isvalid.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html prefix="dc: http://purl.org/dc/elements/1.1/ foaf: http://xmlns.com/foaf/0.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0007</title>
+ </head>
+ <body>
+ <p>This photo was taken by
+ <a about="photo1.jpg" property="dc:title"
+ content="Portrait of Mark" rel="dc:creator"
+ rev="foaf:img" href="http://www.blogger.com/profile/1109404">Mark Birbeck</a>.
+ </p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0008-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0008-isvalid.html
new file mode 100644
index 00000000000..d01fcb497ca
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0008-isvalid.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html prefix="cc: http://creativecommons.org/ns#">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0008</title>
+ </head>
+ <body>
+ <p>This document is licensed under a
+ <a about="" rel="cc:license"
+ href="http://creativecommons.org/licenses/by-nc-nd/2.5/">
+ Creative Commons
+ </a>.
+ </p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0009-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0009-isvalid.html
new file mode 100644
index 00000000000..e7f426e5be4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0009-isvalid.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html prefix="foaf: http://xmlns.com/foaf/0.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0009</title>
+ <link about="http://example.org/people#Person1" rel=""
+ rev="foaf:knows" href="http://example.org/people#Person2" />
+
+ </head>
+ <body>
+ <p></p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0010-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0010-isvalid.html
new file mode 100644
index 00000000000..6fb8854f0d1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0010-isvalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html prefix="foaf: http://xmlns.com/foaf/0.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0010</title>
+ <link about="http://example.org/people#Person1"
+ rel="foaf:knows" rev="foaf:knows" href="http://example.org/people#Person2" />
+ </head>
+ <body>
+ <p></p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0014-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0014-isvalid.html
new file mode 100644
index 00000000000..6902a4aee74
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0014-isvalid.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html prefix="ex: http://example.org/ xsd: http://www.w3.org/2001/XMLSchema#">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0014</title>
+ </head>
+ <body>
+ <p>
+ <span about="http://example.org/foo"
+ property="ex:bar" content="10" datatype="xsd:integer">ten</span>
+ </p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0015-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0015-isvalid.html
new file mode 100644
index 00000000000..94742da735d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0015-isvalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html prefix="dc: http://purl.org/dc/elements/1.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0015</title>
+ <link rel="dc:source" href="urn:isbn:0140449132" />
+ <meta property="dc:creator" content="Fyodor Dostoevsky" />
+ </head>
+ <body>
+ <p></p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0017-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0017-isvalid.html
new file mode 100644
index 00000000000..a0fe4745321
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0017-isvalid.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html prefix="foaf: http://xmlns.com/foaf/0.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0017</title>
+ </head>
+ <body>
+ <p>
+ <span about="[_:a]" property="foaf:name">Manu Sporny</span>
+ <span about="[_:a]" rel="foaf:knows"
+resource="[_:b]">knows</span>
+ <span about="[_:b]" property="foaf:name">Ralph Swick</span>.
+ </p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0018-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0018-isvalid.html
new file mode 100644
index 00000000000..89130ca0449
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0018-isvalid.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html prefix="dc: http://purl.org/dc/elements/1.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0018</title>
+ </head>
+ <body>
+ <p>
+ This photo was taken by
+ <a about="photo1.jpg" rel="dc:creator"
+ href="http://www.blogger.com/profile/1109404">Mark Birbeck</a>.
+ </p>
+ </body>
+
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0019-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0019-novalid.html
new file mode 100644
index 00000000000..a2ea7a0eb5a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0019-novalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html prefix="foaf: http://xmlns.com/foaf/0.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0019</title>
+ </head>
+ <body>
+ <div about="mailto:manu.sporny@digitalbazaar.com"
+ rel="foaf:knows" href="mailto:michael.hausenblas@joanneum.at"></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0020-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0020-isvalid.html
new file mode 100644
index 00000000000..26740993bde
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0020-isvalid.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html prefix="dc: http://purl.org/dc/elements/1.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0020</title>
+ </head>
+ <body>
+ <div about="photo1.jpg">
+ <span class="attribution-line">this photo was taken by
+ <span property="dc:creator">Mark Birbeck</span>
+ </span>
+ </div>
+ </body>
+
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0021-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0021-isvalid.html
new file mode 100644
index 00000000000..21b9f42112e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0021-isvalid.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html prefix="dc: http://purl.org/dc/elements/1.1/">
+<head>
+ <meta charset=utf-8>
+ <title>Test 0021</title>
+</head>
+<body>
+ <div>
+ <span class="attribution-line">this photo was taken by
+ <span property="dc:creator">Mark Birbeck</span>
+ </span>
+ </div>
+</body>
+
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0023-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0023-isvalid.html
new file mode 100644
index 00000000000..5859d457881
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0023-isvalid.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html prefix="dc: http://purl.org/dc/elements/1.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0023</title>
+ </head>
+ <body>
+ <div id="photo1">
+ This photo was taken by
+ <span property="dc:creator">Mark Birbeck</span>
+ </div>
+ </body>
+
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0025-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0025-isvalid.html
new file mode 100644
index 00000000000..dd7f91f3385
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0025-isvalid.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html prefix="dc: http://purl.org/dc/elements/1.1/ foaf: http://xmlns.com/foaf/0.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0025</title>
+ </head>
+ <body>
+ <p>
+ This paper was written by
+ <span rel="dc:creator" resource="#me">
+ <span property="foaf:name">Ben Adida</span>.
+ </span>
+ </p>
+ </body>
+
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0026-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0026-isvalid.html
new file mode 100644
index 00000000000..42bbb1b38c0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0026-isvalid.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html prefix="dc: http://purl.org/dc/elements/1.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0026</title>
+ </head>
+ <body>
+ <p>
+ <span about="http://internet-apps.blogspot.com/"
+ property="dc:creator" content="Mark Birbeck"></span>
+ </p>
+ </body>
+
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0027-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0027-isvalid.html
new file mode 100644
index 00000000000..31c2c97fd5c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0027-isvalid.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html prefix="dc: http://purl.org/dc/elements/1.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0027</title>
+ </head>
+ <body>
+ <p>
+ <span about="http://internet-apps.blogspot.com/"
+ property="dc:creator" content="Mark Birbeck">Mark B.
+ </span>
+ </p>
+ </body>
+
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0029-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0029-isvalid.html
new file mode 100644
index 00000000000..cccb4b277f6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0029-isvalid.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html prefix="dc: http://purl.org/dc/elements/1.1/ xsd: http://www.w3.org/2001/XMLSchema#">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0029</title>
+ </head>
+ <body>
+ <p>
+ <span about="http://example.org/foo"
+ property="dc:creator" datatype="xsd:string"><b>M</b>ark <b>B</b>irbeck</span>.
+ </p>
+ </body>
+
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0030-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0030-isvalid.html
new file mode 100644
index 00000000000..7fd1a85ec7a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0030-isvalid.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html prefix="cc: http://creativecommons.org/ns#">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0030</title>
+ </head>
+ <body>
+ <p>This document is licensed under a
+ <a rel="cc:license"
+ href="http://creativecommons.org/licenses/by-nc-nd/2.5/">
+ Creative Commons License
+ </a>.
+ </p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0031-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0031-isvalid.html
new file mode 100644
index 00000000000..29f2e68fe63
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0031-isvalid.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html prefix="dc: http://purl.org/dc/elements/1.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0031</title>
+ </head>
+ <body>
+ <p about="#wtw">
+ The book <b>Weaving the Web</b> (hardcover) has the ISBN
+ <span rel="dc:identifier" resource="urn:ISBN:0752820907">0752820907</span>.
+ </p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0032-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0032-isvalid.html
new file mode 100644
index 00000000000..6a2cf7c1931
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0032-isvalid.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html prefix="dc: http://purl.org/dc/elements/1.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0032</title>
+ </head>
+ <body>
+ <p about="#wtw">
+ The book <b>Weaving the Web</b> (hardcover) has the ISBN
+ <a rel="dc:identifier" resource="urn:ISBN:0752820907"
+ href="http://www.amazon.com/Weaving-Web-Tim-Berners-Lee/dp/0752820907">0752820907</a>.
+ </p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0033-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0033-isvalid.html
new file mode 100644
index 00000000000..20201d54dbc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0033-isvalid.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html prefix="dc: http://purl.org/dc/elements/1.1/ foaf: http://xmlns.com/foaf/0.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0033</title>
+ </head>
+ <body>
+ <p>
+ This paper was written by
+ <span rel="dc:creator">
+ <span property="foaf:name">Ben Adida</span>.
+ </span>
+ </p>
+ </body>
+
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0034-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0034-isvalid.html
new file mode 100644
index 00000000000..c1ef19cc554
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0034-isvalid.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html prefix="foaf: http://xmlns.com/foaf/0.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0034</title>
+ </head>
+ <body>
+ <div about="http://sw-app.org/mic.xhtml#i" rel="foaf:img">
+ <img src="http://sw-app.org/img/mic_2007_01.jpg"
+ alt="A photo depicting Michael" />
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0035-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0035-novalid.html
new file mode 100644
index 00000000000..ad3b7e815eb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0035-novalid.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html prefix="foaf: http://xmlns.com/foaf/0.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0035</title>
+ </head>
+ <body>
+ <div>
+ <img about="http://sw-app.org/mic.xhtml#i"
+ rel="foaf:img"
+ src="http://sw-app.org/img/mic_2007_01.jpg"
+ href="http://sw-app.org/img/mic_2006_03.jpg"
+ alt="A photo depicting Michael" />
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0036-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0036-isvalid.html
new file mode 100644
index 00000000000..1538f755773
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0036-isvalid.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html prefix="foaf: http://xmlns.com/foaf/0.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0036</title>
+ </head>
+ <body>
+ <div>
+ <img about="http://sw-app.org/mic.xhtml#i"
+ rel="foaf:img"
+ src="http://sw-app.org/img/mic_2007_01.jpg"
+ resource="http://sw-app.org/img/mic_2006_03.jpg"
+ alt="A photo depicting Michael" />
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0037-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0037-novalid.html
new file mode 100644
index 00000000000..8b4798201b5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0037-novalid.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html prefix="foaf: http://xmlns.com/foaf/0.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0037</title>
+ </head>
+ <body>
+ <div>
+ <img about="http://sw-app.org/mic.xhtml#i"
+ rel="foaf:img"
+ src="http://sw-app.org/img/mic_2007_01.jpg"
+ href="http://sw-app.org/img/mic_2006_03.jpg"
+ resource="http://sw-app.org/mic.xhtml#photo"
+ alt="A photo depicting Michael" />
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0038-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0038-isvalid.html
new file mode 100644
index 00000000000..e105718c996
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0038-isvalid.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html prefix="foaf: http://xmlns.com/foaf/0.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0038</title>
+ </head>
+ <body>
+ <div about="http://sw-app.org/mic.xhtml#i" rev="foaf:depicts">
+ <img src="http://sw-app.org/img/mic_2007_01.jpg"
+ alt="A photo depicting Michael" />
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0039-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0039-novalid.html
new file mode 100644
index 00000000000..e95a49f0a55
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0039-novalid.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html prefix="foaf: http://xmlns.com/foaf/0.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0039</title>
+ </head>
+ <body>
+ <div>
+ <img about="http://sw-app.org/mic.xhtml#i"
+ rev="foaf:depicts"
+ src="http://sw-app.org/img/mic_2007_01.jpg"
+ href="http://sw-app.org/img/mic_2006_03.jpg"
+ alt="A photo depicting Michael" />
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0041-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0041-novalid.html
new file mode 100644
index 00000000000..a7839adbe73
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0041-novalid.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html prefix="foaf: http://xmlns.com/foaf/0.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0041</title>
+ </head>
+ <body>
+ <div>
+ <img about="http://sw-app.org/mic.xhtml#i"
+ rev="foaf:depicts"
+ src="http://sw-app.org/img/mic_2007_01.jpg"
+ href="http://sw-app.org/img/mic_2006_03.jpg"
+ resource="http://sw-app.org/mic.xhtml#photo"
+ alt="A photo depicting Michael" />
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0048-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0048-isvalid.html
new file mode 100644
index 00000000000..b11a63dba34
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0048-isvalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html prefix="foaf: http://xmlns.com/foaf/0.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0048</title>
+ </head>
+ <body>
+ <div about="http://www.example.org/#me" rel="foaf:knows" typeof="foaf:Person">
+ <p property="foaf:name">John Doe</p>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0049-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0049-isvalid.html
new file mode 100644
index 00000000000..f26ef8878d2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0049-isvalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html prefix="foaf: http://xmlns.com/foaf/0.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0049</title>
+ </head>
+ <body>
+ <div about="http://www.example.org/#me" typeof="foaf:Person">
+ <p property="foaf:name">John Doe</p>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0050-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0050-isvalid.html
new file mode 100644
index 00000000000..94e28c88b6c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0050-isvalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html prefix="foaf: http://xmlns.com/foaf/0.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0050</title>
+ </head>
+ <body>
+ <div typeof="foaf:Person">
+ <p property="foaf:name">John Doe</p>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0051-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0051-isvalid.html
new file mode 100644
index 00000000000..c132724b087
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0051-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html prefix="foaf: http://xmlns.com/foaf/0.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0051</title>
+ </head>
+ <body>
+ <p about="" typeof="foaf:Document" property="foaf:topic">John Doe</p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0052-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0052-isvalid.html
new file mode 100644
index 00000000000..8e4d02f7bf2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0052-isvalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html prefix="foaf: http://xmlns.com/foaf/0.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0052</title>
+ </head>
+ <body>
+ <p typeof="foaf:Person" resource="http://www.example.org/#me">
+ John Doe
+ </p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0053-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0053-isvalid.html
new file mode 100644
index 00000000000..f5d2172923c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0053-isvalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html prefix="foaf: http://xmlns.com/foaf/0.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0053</title>
+ </head>
+ <body>
+ <p typeof="foaf:Person" resource="http://www.example.org/#me">
+ <span property="foaf:name">John Doe</span>
+ </p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0054-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0054-isvalid.html
new file mode 100644
index 00000000000..e689de8aaf8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0054-isvalid.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html prefix="dc: http://purl.org/dc/elements/1.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0054</title>
+ </head>
+ <body>
+ <p>
+ This document was authored and published by
+ <span about="" property="dc:creator dc:publisher">Fabien Gandon</span>.
+ </p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0055-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0055-isvalid.html
new file mode 100644
index 00000000000..db2748fd1e6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0055-isvalid.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html prefix="dc: http://purl.org/dc/elements/1.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0055</title>
+ </head>
+ <body>
+ <p>
+ This document was authored and published by
+ <a about="" rel="dc:creator dc:publisher" href="http://www-sop.inria.fr/acacia/fabien/">Fabien Gandon</a>.
+ </p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0056-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0056-isvalid.html
new file mode 100644
index 00000000000..aa80de4568a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0056-isvalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html prefix="foaf: http://xmlns.com/foaf/0.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0056</title>
+ </head>
+ <body>
+ <div about="http://www.example.org/#ben" typeof="foaf:Person" rel="foaf:knows">
+ <p about="http://www.example.org/#mark" property="foaf:name">Mark Birbeck</p>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0057-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0057-isvalid.html
new file mode 100644
index 00000000000..41974cbedd0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0057-isvalid.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html prefix="foaf: http://xmlns.com/foaf/0.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0057</title>
+ </head>
+ <body>
+ <div about="http://www.example.org/#ben" rel="foaf:knows">
+ <p about="http://www.example.org/#mark" property="foaf:name">Mark Birbeck</p>
+ <p about="http://www.example.org/#ivan" property="foaf:name">Ivan Herman</p>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0059-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0059-isvalid.html
new file mode 100644
index 00000000000..95fbc278a78
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0059-isvalid.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html prefix="dc: http://purl.org/dc/elements/1.1/ foaf: http://xmlns.com/foaf/0.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0059</title>
+ </head>
+ <body>
+ <p>This document was authored and published by:</p>
+ <ul rel="dc:creator dc:publisher">
+ <li about="http://www.example.org/#manu" property="foaf:name">Manu Sporny</li>
+ <li about="http://www.example.org/#fabien" property="foaf:name">Fabien Gandon</li>
+ </ul>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0060-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0060-isvalid.html
new file mode 100644
index 00000000000..1563ffa73b6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0060-isvalid.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html prefix="foaf: http://xmlns.com/foaf/0.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0060</title>
+ </head>
+ <body>
+ <div about="http://www.example.org/#matsumoto-kimiko"
+ typeof="foaf:Person">
+ <p property="foaf:name">松本 后子</p>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0063-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0063-isvalid.html
new file mode 100644
index 00000000000..d5808b29b7b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0063-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0063</title>
+ <link rel=":next" href="http://rdfa.info/test-suite/test-cases/rdfa1.1/html5/0064.html" />
+ </head>
+ <body>
+ <p>This is the 63<sup>rd</sup> test. The next test is #64.</p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0064-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0064-isvalid.html
new file mode 100644
index 00000000000..0fc82f94d6c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0064-isvalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html prefix="foaf: http://xmlns.com/foaf/0.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0064</title>
+ </head>
+ <body>
+ <p about="[_:michael]">Michael knows
+ <a rel="foaf:knows" href="http://digitalbazaar.com/people/manu">Manu</a>.
+ </p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0065-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0065-isvalid.html
new file mode 100644
index 00000000000..843c6d3c39e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0065-isvalid.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html prefix="foaf: http://xmlns.com/foaf/0.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0065</title>
+ </head>
+ <body>
+ <div about="[_:manu]">
+ Manu Sporny can be reached via
+ <a rel="foaf:mbox" href="mailto:manu.sporny@digitalbazaar.com">email</a>.
+ <span rel="foaf:knows" resource="[_:michael]">He knows Michael.</span>
+ </div>
+
+ <div about="[_:michael]">
+ Michael can be reached via
+ <a rel="foaf:mbox" href="mailto:michael.hausenblas@joanneum.at">email</a>.
+ </div>
+ </body>
+
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0066-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0066-isvalid.html
new file mode 100644
index 00000000000..dc8642ac734
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0066-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html prefix="foaf: http://xmlns.com/foaf/0.1/">
+ <head typeof="foaf:Document">
+ <meta charset=utf-8>
+ <title>Test 0066</title>
+ </head>
+ <body>
+ <p>This is test #66.</p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0067-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0067-isvalid.html
new file mode 100644
index 00000000000..e60e30e04da
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0067-isvalid.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html prefix="foaf: http://xmlns.com/foaf/0.1/">
+ <head>
+ <title property="foaf:topic">Test 0067</title>
+ </head>
+ <body>
+ <p>This is test #67.</p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0068-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0068-isvalid.html
new file mode 100644
index 00000000000..cfd05482227
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0068-isvalid.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html prefix="dc: http://purl.org/dc/elements/1.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0068</title>
+ </head>
+ <body>
+ <p about="0067.html">
+ The previous test was
+ <span property="dc:title">Test 0067</span>.
+ </p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0069-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0069-isvalid.html
new file mode 100644
index 00000000000..bc166fb75ed
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0069-isvalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html prefix="xhv: http://www.w3.org/1999/xhtml/vocab#">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0069</title>
+ </head>
+ <body>
+ <p>The next test will be
+ <a about="" rel="xhv:next" href="0070.html">Test 0070</a>.
+ </p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0070-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0070-isvalid.html
new file mode 100644
index 00000000000..e2efe67daa3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0070-isvalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html prefix="xhv: http://www.w3.org/1999/xhtml/vocab#">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0070</title>
+ </head>
+ <body>
+ <p>The previous test was
+ <span about="" rel="xhv:prev" resource="0069.html">Test 0069</span>.
+ </p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0071-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0071-isvalid.html
new file mode 100644
index 00000000000..511e0b7107b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0071-isvalid.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html prefix="cc: http://creativecommons.org/ns#">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0071</title>
+ </head>
+ <body>
+ <p>This page is under a Creative Commons
+ <a rel="cc:license"
+ href="http://creativecommons.org/licenses/by-nd/3.0/">
+ Attribution-No Derivatives 3.0 license</a>.
+ </p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0072-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0072-isvalid.html
new file mode 100644
index 00000000000..e72327b9542
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0072-isvalid.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html prefix="dc: http://purl.org/dc/elements/1.1/">
+ <head>
+ <base href="http://www.example.org/"/>
+ <meta charset=utf-8>
+ <title>Test 0072</title>
+ </head>
+ <body>
+ <p about="faq">
+ Learn more by reading the example.org
+ <span property="dc:title">Example FAQ</span>.
+ </p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0073-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0073-isvalid.html
new file mode 100644
index 00000000000..f614cafbca0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0073-isvalid.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html prefix="dc: http://purl.org/dc/elements/1.1/">
+ <head>
+ <base href="http://www.example.org/"/>
+ <meta charset=utf-8>
+ <title>Test 0073</title>
+ </head>
+ <body>
+ <p>
+ This article was written by
+ <span rel="dc:creator" resource="jane">Jane</span>.
+ </p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0074-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0074-isvalid.html
new file mode 100644
index 00000000000..d25af2d5323
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0074-isvalid.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html prefix="dc: http://purl.org/dc/elements/1.1/">
+ <head>
+ <base href="http://www.example.org/"/>
+ <meta charset=utf-8>
+ <title>Test 0074</title>
+ </head>
+ <body>
+ <p>
+ This article was written by
+ <a rel="dc:creator" href="jane">Jane</a>.
+ </p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0075-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0075-isvalid.html
new file mode 100644
index 00000000000..15f0dd01927
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0075-isvalid.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html prefix="dc: http://purl.org/dc/elements/1.1/">
+ <head>
+ <base href="http://www.example.org/"/>
+ <meta charset=utf-8>
+ <title>Test 0075</title>
+ </head>
+ <body>
+ <p>
+ This page is under a Creative Commons
+ <a rel="license" href="http://creativecommons.org/licenses/by-nd/3.0/">Attribution-No Derivatives 3.0 license</a>.
+ </p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0079-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0079-novalid.html
new file mode 100644
index 00000000000..0946e189f39
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0079-novalid.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html prefix="foaf: http://xmlns.com/foaf/0.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0079</title>
+ </head>
+ <body>
+ <div about ="http://www.example.org/#somebody" rel="foaf:knows">
+ <p resource="http://www.ivan-herman.org/Ivan_Herman">Ivan Herman</p>
+ <p href="http://www.w3.org/People/Berners-Lee/card#i">Tim Berners Lee</p>
+ <p resource="http://danbri.org/foaf.rdf#danbri" href="http://www.leobard.net/rdf/foaf.xml#me">Dan Brickley</p>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0080-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0080-isvalid.html
new file mode 100644
index 00000000000..543e474d3a7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0080-isvalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html prefix="foaf: http://xmlns.com/foaf/0.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0080</title>
+ </head>
+ <body>
+ <div about ="http://www.example.org/#somebody" rel="foaf:knows">
+ <p about="http://danbri.org/foaf.rdf#danbri" resource="http://www.leobard.net/rdf/foaf.xml#me">Dan Brickley</p>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0083-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0083-isvalid.html
new file mode 100644
index 00000000000..049f0f741f0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0083-isvalid.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html prefix="foaf: http://xmlns.com/foaf/0.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0083</title>
+ </head>
+ <body>
+ <div about="http://www.example.org/#somebody" rel="foaf:knows">
+ <p property="foaf:name">Ivan Herman</p>
+ <p rel="foaf:mailbox" resource="mailto:ivan@w3.org">mailto:ivan@w3.org</p>
+ <p about="http://danbri.org/foaf.rdf#danbri" typeof="foaf:Person" property="foaf:name">Dan Brickley</p>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0084-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0084-isvalid.html
new file mode 100644
index 00000000000..c61f1051bba
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0084-isvalid.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html prefix="foaf: http://xmlns.com/foaf/0.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0084</title>
+ </head>
+ <body>
+ <div about ="http://www.example.org/#somebody" rev="foaf:knows" rel="foaf:knows">
+ <div>
+ <p property="foaf:name">Ivan Herman</p>
+ <p rel="foaf:mailbox" resource="mailto:ivan@w3.org">mailto:ivan@w3.org</p>
+ <p about="http://danbri.org/foaf.rdf#danbri" typeof="foaf:Person" property="foaf:name">Dan Brickley</p>
+
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0085-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0085-novalid.html
new file mode 100644
index 00000000000..a910e1e9077
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0085-novalid.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html prefix="foaf: http://xmlns.com/foaf/0.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0085</title>
+ </head>
+ <body>
+ <div about ="http://www.example.org/#somebody" rel="foaf:knows">
+ <div rel="foaf:knows">
+ <p resource="http://www.ivan-herman.org/Ivan_Herman">Ivan Herman</p>
+ <p href="http://www.w3.org/People/Berners-Lee/card#i">Tim Berners Lee</p>
+ <p resource="http://danbri.org/foaf.rdf#danbri" href="http://www.leobard.net/rdf/foaf.xml#me">Dan Brickley</p>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0087-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0087-isvalid.html
new file mode 100644
index 00000000000..269e193f967
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0087-isvalid.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0087</title>
+ </head>
+ <body>
+ <p>
+ <a rel=":alternate" href="http://example.org/alternate">alternate</a>
+ <a rel=":appendix" href="http://example.org/appendix">appendix</a>
+ <a rel=":bookmark" href="http://example.org/bookmark">bookmark</a>
+ <a rel=":cite" href="http://example.org/cite">cite</a>
+ <a rel=":chapter" href="http://example.org/chapter">chapter</a>
+ <a rel=":contents" href="http://example.org/contents">contents</a>
+ <a rel=":copyright" href="http://example.org/copyright">copyright</a>
+ <a rel=":glossary" href="http://example.org/glossary">glossary</a>
+ <a rel=":help" href="http://example.org/help">help</a>
+ <a rel=":icon" href="http://example.org/icon">icon</a>
+ <a rel=":index" href="http://example.org/index">index</a>
+ <a rel=":first" href="http://example.org/first">first</a>
+ <a rel=":last" href="http://example.org/last">last</a>
+ <a rel=":license" href="http://example.org/license">license</a>
+ <a rel=":meta" href="http://example.org/meta">meta</a>
+ <a rel=":next" href="http://example.org/next">next</a>
+ <a rel=":p3pv1" href="http://example.org/p3pv1">p3pv1</a>
+ <a rel=":prev" href="http://example.org/prev">prev</a>
+ <a rel=":role" href="http://example.org/role">role</a>
+ <a rel=":section" href="http://example.org/section">section</a>
+ <a rel=":subsection" href="http://example.org/subsection">subsection</a>
+ <a rel=":start" href="http://example.org/start">start</a>
+ <a rel=":stylesheet" href="http://example.org/stylesheet">stylesheet</a>
+ <a rel=":up" href="http://example.org/up">up</a>
+ </p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0088-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0088-isvalid.html
new file mode 100644
index 00000000000..b43ca20f34f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0088-isvalid.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html prefix="foaf: http://xmlns.com/foaf/0.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0088</title>
+ </head>
+ <body>
+ <div about ="http://www.example.org/#somebody" rel="foaf:knows">
+ <p about="[_:]" property="foaf:name">Dan Brickley</p>
+ <p about="[_:]" typeof="foaf:Person">Dan Brickley again:-)</p>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0089-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0089-isvalid.html
new file mode 100644
index 00000000000..e85d6d7522f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0089-isvalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html prefix="foaf: http://xmlns.com/foaf/0.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0089</title>
+ </head>
+ <body>
+ <div>
+ <img src="http://example.org/example.png" typeof="foaf:Image" alt="example image" />
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0091-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0091-isvalid.html
new file mode 100644
index 00000000000..67badc59dab
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0091-isvalid.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0091</title>
+ </head>
+ <body>
+ <p about="[_:human]">
+ A human is
+ <span property=":definition">a bi-pedal primate</span>.
+ They are quite possibly one of the most
+ <span property=":note">confused animal</span>s residing in the
+ <span property=":foo">Milky Way</span>.
+ </p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0093-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0093-isvalid.html
new file mode 100644
index 00000000000..682c65669e4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0093-isvalid.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html prefix="dc: http://purl.org/dc/elements/1.1/ ex: http://www.example.org/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0093</title>
+ </head>
+ <body>
+ <div about="">
+ Author: <span property="dc:creator">Albert Einstein</span>
+ <h2 property="dc:title" datatype="ex:XMLLiteral">E = mc<sup>2</sup>: The Most Urgent Problem of Our Time</h2>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0099-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0099-isvalid.html
new file mode 100644
index 00000000000..4c33702182c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0099-isvalid.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html prefix="example: http://www.example.org/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0099</title>
+ </head>
+ <body>
+ <p about="http://www.cwi.nl/~steven/" property="example:likes">
+ We put thirty spokes together and call it a wheel;
+ But it is on the space where there is nothing that the usefulness of the wheel depends.
+ We turn clay to make a vessel;
+ But it is on the space where there is nothing that the usefulness of the vessel depends.
+ We pierce doors and windows to make a house;
+ And it is on these spaces where there is nothing that the usefulness of the house depends.
+ Therefore just as we take advantage of what is, we should recognize the usefulness of what is not.
+
+ Lao Tzu: Tao Te Ching</p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0104-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0104-isvalid.html
new file mode 100644
index 00000000000..03e0dd192c5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0104-isvalid.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html prefix="rdf: http://www.w3.org/1999/02/22-rdf-syntax-ns# example: http://www.example.org/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0104</title>
+ </head>
+ <body>
+ <p>
+ The word "interfenestration" has
+ <span about="#interfenestration" rel="example:size">
+ <span property="rdf:value">17</span>
+ <span property="example:unit">character</span>s.
+ </span>
+ </p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0106-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0106-isvalid.html
new file mode 100644
index 00000000000..9c04bab32a8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0106-isvalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html prefix="dc: http://purl.org/dc/elements/1.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0106</title>
+ </head>
+ <body>
+ <div about="" rel="dc:creator">
+ <a rel="" href="manu.html">Manu</a> created this page.
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0107-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0107-isvalid.html
new file mode 100644
index 00000000000..75d30d72e9c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0107-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html prefix="ex: http://example.org/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0107</title>
+ </head>
+ <body>
+ <div rel="next"></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0109-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0109-novalid.html
new file mode 100644
index 00000000000..7ca6adb3e12
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0109-novalid.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html prefix="dc: http://purl.org/dc/elements/1.1/" xml:base="http://example.org/invalid/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0109</title>
+ </head>
+ <body>
+ <!-- This a NOT a valid XHTML document (due to @xml:base) -->
+ <div xml:base="http://example.org/invalid/">
+ <p about="">This is <span property="dc:title">Test 0109</span>.</p>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0110-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0110-isvalid.html
new file mode 100644
index 00000000000..39287ec2986
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0110-isvalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html prefix="xhv: http://www.w3.org/1999/xhtml/vocab#">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0110</title>
+ </head>
+ <body>
+ <div rel="xhv:next">
+ <div rel="xhv:next"></div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0111-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0111-isvalid.html
new file mode 100644
index 00000000000..195aa7a3768
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0111-isvalid.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html prefix="xhv: http://www.w3.org/1999/xhtml/vocab#">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0111</title>
+ </head>
+ <body>
+ <div rel="xhv:next">
+ <div rel="xhv:next">
+ <div rel="xhv:next"></div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0112-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0112-isvalid.html
new file mode 100644
index 00000000000..f28691f89c7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0112-isvalid.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html prefix="ex: http://example.org/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0112</title>
+ </head>
+ <body>
+ <p>
+ <span about="http://example.org/node" property="ex:property"
+ datatype="">not an XML Literal,
+whitespace preserved
+</span>
+ </p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0114-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0114-isvalid.html
new file mode 100644
index 00000000000..363cc1b0400
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0114-isvalid.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html prefix="cc: http://creativecommons.org/ns# xhv: http://www.w3.org/1999/xhtml/vocab# rdfatest: http://rdfa.info/vocabs/rdfa-test#">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0114</title>
+ </head>
+ <body>
+ <div>
+ <a rel="xhv:index" href="../../.././#">Test Suite</a>
+ <a rel="xhv:next" href="0115.html">Test Case 0115</a>
+ <a rel="xhv:up" href="./">Test Case 0114</a>
+ <a rel="cc:attributionURL" href="../../../../">RDFa Website</a>
+ <a rel="rdfatest:cornerCase1" href=".">Corner Case #1</a>
+ <a rel="rdfatest:cornerCase3" href="...">Corner Case #3</a>
+ <a rel="rdfatest:cornerCase4" href="?foo=bar../baz">Corner Case #4</a>
+ <a rel="rdfatest:cornerCase5" href="../..../../../.../.htaccess">Corner Case #5</a>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0115-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0115-isvalid.html
new file mode 100644
index 00000000000..cde9b6e40d2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0115-isvalid.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html prefix="ex: http://www.example.com/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0115</title>
+ </head>
+ <body>
+ <p>Description: XML entities in the RDFa content</p>
+ <p>
+ <span property="ex:entity1">&gt;</span>
+ <span property="ex:entity2">Ben &amp; Co.</span>
+ <span property="ex:entity3">&#x40;</span>
+ <span property="ex:entity4">&#64;</span>
+ </p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0117-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0117-isvalid.html
new file mode 100644
index 00000000000..4f3957b825a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0117-isvalid.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html prefix="dc: http://purl.org/dc/elements/1.1/">
+ <head>
+ <base href="http://www.example.org/tc117.xhtml#fragment"/>
+ <title property="dc:title">Test 0117</title>
+ </head>
+ <body>
+ <p>
+ <span property="dc:contributor">Mark Birbeck</span>
+ added this triple test.
+ </p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0118-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0118-isvalid.html
new file mode 100644
index 00000000000..2af4127f264
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0118-isvalid.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html prefix="dc: http://purl.org/dc/elements/1.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0118</title>
+ </head>
+ <body>
+ <p>
+ Check to see if parsers get confused when "" is
+ interpreted as NULL in some chaining cases.
+ <a href="http://example.org/ben.html"><span
+ about="" property="dc:creator">Ben</span></a>
+ </p>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0119-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0119-isvalid.html
new file mode 100644
index 00000000000..187a42ea189
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0119-isvalid.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html prefix="dc: http://purl.org/dc/elements/1.1/ example: http://example.org/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0119</title>
+ </head>
+ <body>
+ <div>
+ <p about="[example:]">
+ The
+ <span property="dc:title">Example Website</span>
+ is used in many W3C tutorials.
+ </p>
+ </div>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0120-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0120-isvalid.html
new file mode 100644
index 00000000000..fc44b1e2c00
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0120-isvalid.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html prefix="dc: http://purl.org/dc/elements/1.1/ example: http://example.org/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0120</title>
+ </head>
+ <body>
+ <p about="[:]">
+ The
+ <span property="dc:title">The XHTML Vocabulary Document</span>
+ is the default prefix for XHTML+RDFa 1.0.
+ </p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0122-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0122-isvalid.html
new file mode 100644
index 00000000000..e3472f54146
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0122-isvalid.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0122</title>
+ </head>
+ <body>
+ <p about="http://example.org/section1.html">
+ This section is contained below <span rel="up" resource="[]">the main site</span>.
+ </p>
+ </body>
+
+
+
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0126-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0126-isvalid.html
new file mode 100644
index 00000000000..419edd91e11
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0126-isvalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html prefix="dct: http://purl.org/dc/terms/ sioc: http://rdfs.org/sioc/ns# foaf: http://xmlns.com/foaf/0.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0126</title>
+ </head>
+ <body>
+ <div about="http://www.example.org/#article" typeof="foaf:Document sioc:Post">
+ <h1 property="dct:title">My article</h1>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0131-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0131-novalid.html
new file mode 100644
index 00000000000..2de7ecef6e6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0131-novalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html prefix="xhv: http://www.w3.org/1999/xhtml/vocab#">
+<head>
+ <meta charset=utf-8>
+ <title>Test</title>
+ <link rel="xhv:next&#x20;xhv:prev&#x09;xhv:first&#x0a;xhv:last&#x0d;xhv:subsection" href="http://example.org/test.css" />
+</head>
+<body>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0134-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0134-isvalid.html
new file mode 100644
index 00000000000..2e77ec5ad34
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0134-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test</title>
+ <link rel="LICENSE" href="http://example.org/test.css" />
+</head>
+<body>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0140-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0140-isvalid.html
new file mode 100644
index 00000000000..d2a71239296
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0140-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Blank-node as Predicate Test</title>
+</head>
+<body>
+<p>Blank Nodes are not allowed to be predicate identifiers in RDF:</p>
+<p property="_:invalid">Test</p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0147-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0147-novalid.html
new file mode 100644
index 00000000000..23adadedf12
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0147-novalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test</title>
+</head>
+<body>
+<p xmlns:xmlzzz="http://example.org/" property="xmlzzz:test">Test</p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0174-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0174-isvalid.html
new file mode 100644
index 00000000000..a7564eb7637
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0174-isvalid.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html prefix="v: http://www.w3.org/2006/vcard/ns#">
+<head>
+ <meta charset=utf-8>
+ <title>Test 0174</title>
+</head>
+<body>
+ <p>
+ This test ensures that single-character prefixes are allowed.
+ My name is:
+ <span about="http://example.org/jd" property="v:fn">John Doe</span>
+ </p>
+</body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0175-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0175-isvalid.html
new file mode 100644
index 00000000000..b02fab0b3c8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0175-isvalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0175</title>
+ </head>
+ <body>
+ <p about="_:gregg">My name is
+ <em property="http://xmlns.com/foaf/0.1/name">Gregg Kellogg</em>.
+ </p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0176-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0176-isvalid.html
new file mode 100644
index 00000000000..2983e2e038d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0176-isvalid.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html prefix="foaf: http://xmlns.com/foaf/0.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0176</title>
+ </head>
+ <body>
+ <div about="_:manu">
+ Manu can be reached via
+ <a rel="http://xmlns.com/foaf/0.1/mbox" href="mailto:manu.sporny@digitalbazaar.com">email</a>.
+ <span rel="http://xmlns.com/foaf/0.1/knows" resource="_:gregg">He knows Gregg.</span>
+ <span rev="http://xmlns.com/foaf/0.1/knows" resource="_:gregg">Who knows Manu.</span>
+ </div>
+
+ <div about="_:gregg">
+ Gregg can be reached via
+ <a rel="http://xmlns.com/foaf/0.1/mbox" href="mailto:gregg@kellogg-assoc.com">email</a>.
+ </div>
+ </body>
+
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0177-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0177-isvalid.html
new file mode 100644
index 00000000000..622a68562a4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0177-isvalid.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0177</title>
+ <base href="http://example.org/"/>
+ </head>
+ <body>
+ <div about ="#me" prefix="foaf: http://xmlns.com/foaf/0.1/" >
+ <p property="foaf:name">Ivan Herman</p>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0178-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0178-isvalid.html
new file mode 100644
index 00000000000..27c81d93da4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0178-isvalid.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0178</title>
+ <base href="http://example.org/"/>
+ </head>
+ <body>
+ <div about ="#this" prefix="foaf: http://xmlns.com/foaf/0.1/ dc: http://purl.org/dc/terms/" typeof="dc:Agent">
+ <p property="foaf:name">A particular agent</p>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0179-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0179-novalid.html
new file mode 100644
index 00000000000..80cac4fa336
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0179-novalid.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0179</title>
+ <base href="http://example.org/"/>
+ </head>
+ <body>
+ <!-- prefix has a higher priority than xmlns -->
+ <div about ="#me" xmlns:foaf="http://www.example.com/wrong/foaf/uri" prefix="foaf: http://xmlns.com/foaf/0.1/" >
+ <p property="foaf:name">Ivan Herman</p>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0180-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0180-novalid.html
new file mode 100644
index 00000000000..1d5c4fcfeee
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0180-novalid.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0180</title>
+ <base href="http://example.org/"/>
+ </head>
+ <body>
+ <div about ="#me" prefix=": http://xmlns.com/foaf/0.1/" >
+ <p property=":name">Ivan Herman</p>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0181-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0181-isvalid.html
new file mode 100644
index 00000000000..66950be4481
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0181-isvalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0181</title>
+ </head>
+ <body>
+ <div about ="http://www.example.org/software">
+ <p rel=":license" resource="http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231">Ivan Herman</p>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0182-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0182-isvalid.html
new file mode 100644
index 00000000000..0026e32eee4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0182-isvalid.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0182</title>
+ <base href="http://example.org/"/>
+ </head>
+ <body>
+ <div prefix="foaf: http://example.org/wrong/foaf/uri/ dc: http://purl.org/dc/terms/" >
+ <div about ="#this" typeof="dc:Agent" prefix="foaf: http://xmlns.com/foaf/0.1/" >
+ <p property="foaf:name">A particular agent</p>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0183-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0183-novalid.html
new file mode 100644
index 00000000000..d3a9a55d21d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0183-novalid.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0183</title>
+ <base href="http://example.org/"/>
+</head>
+<body>
+ <div prefix="foaf: http://example.org/wrong/foaf/uri/ dc: http://purl.org/dc/terms/" >
+ <div about ="#this" typeof="dc:Agent" xmlns:foaf="http://xmlns.com/foaf/0.1/" >
+ <p property="foaf:name">A particular agent</p>
+ </div>
+ </div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0186-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0186-isvalid.html
new file mode 100644
index 00000000000..798d2b5637a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0186-isvalid.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0186</title>
+ <base href="http://example.org/"/>
+</head>
+<body>
+ <div about ="#me" vocab="http://xmlns.com/foaf/0.1/" >
+ <p property="name">Ivan Herman</p>
+ </div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0187-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0187-isvalid.html
new file mode 100644
index 00000000000..5a32f133604
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0187-isvalid.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0187</title>
+ <base href="http://example.org/"/>
+ </head>
+ <body>
+ <div vocab="http://example.org/wrong/foaf/uri/">
+ <div about ="#me" vocab="http://xmlns.com/foaf/0.1/" >
+ <p property="name">Ivan Herman</p>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0188-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0188-isvalid.html
new file mode 100644
index 00000000000..a9569c9dc11
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0188-isvalid.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0188</title>
+ <base href="http://example.org/"/>
+ </head>
+ <body>
+ <div vocab="http://xmlns.com/foaf/0.1/">
+ <div about ="#me">
+ <p property="name">Ivan Herman</p>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0189-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0189-isvalid.html
new file mode 100644
index 00000000000..ff7804d24c9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0189-isvalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0189</title>
+ </head>
+ <body>
+ <div about ="http://www.example.org/software" vocab="http://www.example.org/vocab#">
+ <p rel="license" resource="http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231">Ivan Herman</p>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0190-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0190-isvalid.html
new file mode 100644
index 00000000000..d8f0f98b9ee
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0190-isvalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0190</title>
+ </head>
+ <body>
+ <div about ="http://www.example.org/software">
+ <p rel="liCeNse" resource="http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231">Ivan Herman</p>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0196-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0196-isvalid.html
new file mode 100644
index 00000000000..6b764dbd55a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0196-isvalid.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html prefix="ex: http://example.org/rdf/ rdf: http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+<head>
+ <meta charset=utf-8>
+ <title>Test 0196</title>
+</head>
+<body>
+ <div about="http://www.example.org">
+ <p property="ex:xmllit" datatype="rdf:XMLLiteral">This is an XMLLiteral</p>
+ <p property="ex:plainlit">This is a <em>plain</em> literal</p>
+</div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0197-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0197-isvalid.html
new file mode 100644
index 00000000000..57d2a2fb0c0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0197-isvalid.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html prefix="dc: http://purl.org/dc/terms/">
+<head>
+ <meta charset=utf-8>
+ <title>Test 0197</title>
+ <base href="http://www.example.org/me" />
+</head>
+<body>
+ <p about="" typeof="class/Person" property="pred/name">Gregg Kellogg</p>
+ <p property="dc:language" datatype="pred/lang">Ruby</p>
+ <p rel="pred/rel" resource="http://kellogg-assoc.com/">Kellogg Associates</p>
+ <p rev="pred/rev" resource="http://github.org/gkellogg/rdf_context">Ruby Gem</p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0206-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0206-isvalid.html
new file mode 100644
index 00000000000..cdcf64a4b1f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0206-isvalid.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Default context test 0206</title>
+</head>
+<body>
+ <p about ="xsd:maxExclusive" rel="rdf:type" resource="owl:DatatypeProperty">
+ An OWL Axiom: "xsd:maxExclusive" is a Datatype Property in OWL.
+ </p>
+</body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0207-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0207-isvalid.html
new file mode 100644
index 00000000000..db3c87de8fd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0207-isvalid.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html prefix="cal: http://www.w3.org/2002/12/cal/icaltzd# xsd: http://www.w3.org/2001/XMLSchema#">
+<head>
+ <meta charset=utf-8>
+ <title>Test 0207</title>
+</head>
+ <body>
+ <p about="#event1" typeof="cal:Vevent">
+ <b property="cal:summary">Weekend off in Iona</b>:
+ <span property="cal:dtstart" content="2006-10-21" datatype="xsd:date">Oct 21st</span>
+ to <span property="cal:dtend" content="2006-10-23" datatype="xsd:date">Oct 23rd</span>.
+ See <a rel="cal:url" href="http://freetime.example.org/">FreeTime.Example.org</a> for
+ info on <span property="cal:location">Iona, UK</span>.
+ </p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0213-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0213-isvalid.html
new file mode 100644
index 00000000000..b07bab2066f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0213-isvalid.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html prefix="dc: http://purl.org/dc/elements/1.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0213</title>
+ </head>
+ <body>
+ <!-- In RDFa 1.1, by default a plain literal is generated even if it contains XML elements -->
+ <div about="http://www.example.org/">
+ <h2 property="dc:title">E = mc<sup>2</sup>: The Most Urgent Problem of Our Time</h2>
+ </div>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0214-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0214-isvalid.html
new file mode 100644
index 00000000000..395e645fb87
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0214-isvalid.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html typeof="foaf:Document">
+<head>
+ <title property="dc:title">Test 0214</title>
+</head>
+<body>
+ <p>This document has a title.</p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0216-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0216-isvalid.html
new file mode 100644
index 00000000000..005731efe2b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0216-isvalid.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html prefix = "
+air: http://www.daml.org/2001/10/html/airport-ont#
+bio: http://vocab.org/bio/0.1/
+contact: http://www.w3.org/2000/10/swap/pim/contact#
+dc: http://purl.org/dc/terms/
+foaf: http://xmlns.com/foaf/0.1/
+ical: http://www.w3.org/2002/12/cal/icaltzd#
+owl: http://www.w3.org/2002/07/owl#
+rdf: http://www.w3.org/1999/02/22-rdf-syntax-ns#
+rdfs: http://www.w3.org/2000/01/rdf-schema#
+rel: http://vocab.org/relationship/
+openid: http://xmlns.openid.net/auth#
+rss: http://web.resource.org/rss/1.0/
+sioc: http://rdfs.org/sioc/ns#
+xsd: http://www.w3.org/2001/XMLSchema#
+google: http://rdf.data-vocabulary.org/#
+rsa: http://www.w3.org/ns/auth/rsa#
+cert: http://www.w3.org/ns/auth/cert#
+wot: http://xmlns.com/wot/0.1/
+">
+<head>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
+ <title>Test 0216</title>
+</head>
+<body>
+ <!-- Tests whether the Unicode (UTF-8 encoded) characters are properly handled even with a large set of properties
+ in the html element, ie, when the content sniffing to find out the character encoding may not work -->
+ <p about="http://www.ivan-herman.net/foaf#me" property="foaf:name">Iván</p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0217-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0217-isvalid.html
new file mode 100644
index 00000000000..b6de9ce76c2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0217-isvalid.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0217</title>
+ <base href="http://example.org/"/>
+</head>
+<body>
+ <div about="#me" vocab="http://xmlns.com/foaf/0.1/" >
+ <p property="name">Gregg Kellogg</p>
+ </div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0218-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0218-isvalid.html
new file mode 100644
index 00000000000..f8bb147def0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0218-isvalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0218</title>
+</head>
+<body>
+ <div about ="">
+ <p rel="rdf:value" inlist=""></p>
+ </div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0219-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0219-isvalid.html
new file mode 100644
index 00000000000..3865401f396
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0219-isvalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0219</title>
+</head>
+<body>
+ <div about="">
+ <p property="rdf:value" inlist="">Foo</p>
+ </div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0220-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0220-isvalid.html
new file mode 100644
index 00000000000..a171f2d472d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0220-isvalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0220</title>
+</head>
+<body>
+ <div about="">
+ <a rel="rdf:value" inlist="" href="foo">Foo</a>
+ </div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0221-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0221-isvalid.html
new file mode 100644
index 00000000000..b01b83ae9bd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0221-isvalid.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0221</title>
+</head>
+<body>
+ <div about="">
+ <p property="rdf:value" inlist="">Foo</p>
+ <a rel="rdf:value" inlist="" href="foo">Foo</a>
+ </div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0222-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0222-novalid.html
new file mode 100644
index 00000000000..09bc1b56e25
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0222-novalid.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0222</title>
+</head>
+<body>
+ <div about="">
+ <p property="rdf:value" inlist="">Foo</p>
+ <strong><p property="rdf:value" inlist="">Bar</p></strong>
+ </div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0223-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0223-novalid.html
new file mode 100644
index 00000000000..662fe5124aa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0223-novalid.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0223</title>
+</head>
+<body>
+ <div about="">
+ <p property="rdf:value" inlist="">Foo</p>
+ <strong><p property="rdf:value" inlist="">Bar</p></strong>
+ <p property="rdf:value">Baz</p>
+ </div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0224-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0224-isvalid.html
new file mode 100644
index 00000000000..08b39cf2cdc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0224-isvalid.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0224</title>
+</head>
+<body>
+ <div about="">
+ <ol rel="rdf:value" inlist="">
+ <li><a href="foo">Foo</a></li>
+ <li><a href="bar">Bar</a></li>
+ </ol>
+ </div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0225-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0225-isvalid.html
new file mode 100644
index 00000000000..f513aabb661
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0225-isvalid.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0225</title>
+</head>
+<body>
+ <div about="foo">
+ <p property="rdf:value" inlist="">Foo</p>
+ </div>
+ <div about="foo">
+ <p property="rdf:value" inlist="">Bar</p>
+ </div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0226-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0226-novalid.html
new file mode 100644
index 00000000000..bf6103ea9b9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0226-novalid.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0226</title>
+</head>
+<body prefix="ex: http://www.example.org/">
+ <div about="">
+ <p property="rdf:value" inlist="">Foo</p>
+ <span rel="ex:inlist" resource="res">
+ <p property="rdf:value" inlist="">Bar</p>
+ </span>
+ </div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0227-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0227-novalid.html
new file mode 100644
index 00000000000..a0a961fd57a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0227-novalid.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0227</title>
+</head>
+<body prefix="ex: http://www.example.org/">
+ <div about="">
+ <p property="rdf:value" inlist="">Foo</p>
+ <span rel="ex:inlist">
+ <p about="res" property="rdf:value" inlist="">Bar</p>
+ </span>
+ </div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0228-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0228-isvalid.html
new file mode 100644
index 00000000000..bc3578d57eb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0228-isvalid.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0228</title>
+ <!-- Based on 1.1 semantics for 0040 -->
+ </head>
+ <body>
+ <div>
+ <img src="http://sw-app.org/img/mic_2007_01.jpg"
+ rev="xhv:alternate"
+ resource="http://sw-app.org/img/mic_2006_03.jpg"
+ alt="A photo depicting Michael" />
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0229-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0229-isvalid.html
new file mode 100644
index 00000000000..3d37f5c4349
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0229-isvalid.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html prefix="foaf: http://xmlns.com/foaf/0.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0042</title>
+ </head>
+ <body>
+ <div>
+ <img rel="foaf:img"
+ src="http://sw-app.org/img/mic_2007_01.jpg"
+ alt="A photo depicting Michael" />
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0230-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0230-novalid.html
new file mode 100644
index 00000000000..8e19185af69
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0230-novalid.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0230</title>
+</head>
+<body>
+ <div>
+ <img
+ src="http://example.org/example.png"
+ rel="license"
+ href="http://creativecommons.org/licenses/by-nc-sa/2.0/"
+ alt="example image" />
+ </div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0231-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0231-isvalid.html
new file mode 100644
index 00000000000..19160913db6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0231-isvalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0231</title>
+</head>
+<body>
+ <div about="http://creativecommons.org/licenses/by-nc-sa/2.0/" rev="license">
+ <img src="http://example.org/example.png" alt="example image" />
+ </div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0232-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0232-isvalid.html
new file mode 100644
index 00000000000..6a3eac21945
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0232-isvalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html prefix="foaf: http://xmlns.com/foaf/0.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0232</title>
+ </head>
+ <body>
+ <div rel="foaf:maker" typeof="foaf:Person">
+ <p property="foaf:name">John Doe</p>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0233-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0233-isvalid.html
new file mode 100644
index 00000000000..586778ecf3e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0233-isvalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html prefix="foaf: http://xmlns.com/foaf/0.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0233</title>
+ </head>
+ <body>
+ <div rel="foaf:maker" typeof="foaf:Person" resource="http://www.example.org/#me">
+ <p property="foaf:name">John Doe</p>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0234-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0234-novalid.html
new file mode 100644
index 00000000000..3dfbdaa03d9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0234-novalid.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0234</title>
+ </head>
+ <body>
+ <p>
+ <a rel="describedby" href="http://example.org/describedby">describedby</a>
+ <a rel="license" href="http://example.org/license">license</a>
+ <a rel="role" href="http://example.org/role">role</a>
+ </p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0235-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0235-isvalid.html
new file mode 100644
index 00000000000..183956137e2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0235-isvalid.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0235</title>
+ </head>
+ <body>
+ <p>
+ The <span property="dc:title">rdfagraph</span> should not generate triples when
+ looking only at the processor graph.
+ </p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0237-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0237-novalid.html
new file mode 100644
index 00000000000..cf5b022224c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0237-novalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0237</title>
+</head>
+<body prefix="$malformed http://example.com"
+ property="rdf:value"
+ resource="[$malformed:curie]">
+ Malformed Prefix
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0238-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0238-isvalid.html
new file mode 100644
index 00000000000..92feca27aed
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0238-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0238</title>
+</head>
+<body property="undefined_term">
+ Undefined Term
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0239-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0239-isvalid.html
new file mode 100644
index 00000000000..a28850ee58e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0239-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0239</title>
+</head>
+<body property="rdf:value"
+ resource="[undefined:curie]">
+ Undefined Prefix
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0240-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0240-isvalid.html
new file mode 100644
index 00000000000..9938beaa8f8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0240-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0240</title>
+</head>
+<body prefix="rdfatest: http://rdfa.info/vocabs/rdfa-test#" vocab="http://rdfa.info/vocabs/rdfa-test#">
+ Using the property <code property="subProp" resource="rdfatest:subProp">subProp</code>
+ should cause a triple with <code>baseProp</code> to be added.
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0241-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0241-isvalid.html
new file mode 100644
index 00000000000..eb6b77a98db
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0241-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0241</title>
+</head>
+<body prefix="rdfatest: http://rdfa.info/vocabs/rdfa-test#" vocab="http://rdfa.info/vocabs/rdfa-test#">
+ Using the property <code property="eqProp" resource="rdfatest:eqProp">eqProp</code>
+ should cause a triple with <code>baseProp</code> to be added.
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0242-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0242-isvalid.html
new file mode 100644
index 00000000000..7b6a59078d6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0242-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0242</title>
+</head>
+<body prefix="rdfatest: http://rdfa.info/vocabs/rdfa-test#" vocab="http://rdfa.info/vocabs/rdfa-test#">
+ Using the property <code property="baseProp" resource="rdfatest:eqProp">eqProp</code>
+ should cause a triple with <code>eqProp</code> to be added.
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0243-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0243-isvalid.html
new file mode 100644
index 00000000000..7a21da41350
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0243-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0243</title>
+</head>
+<body prefix="rdfatest: http://rdfa.info/vocabs/rdfa-test#" vocab="http://rdfa.info/vocabs/rdfa-test#">
+ Using the type <code about="_:a" typeof="SubClass">SubClass</code>
+ should cause a triple with <code>BaseClass</code> to be added.
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0244-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0244-isvalid.html
new file mode 100644
index 00000000000..654009bb4b3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0244-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0244</title>
+</head>
+<body prefix="rdfatest: http://rdfa.info/vocabs/rdfa-test#" vocab="http://rdfa.info/vocabs/rdfa-test#">
+ Using the type <code about="_:a" typeof="EqClass">EqClass</code>
+ should cause a triple with <code>BaseClass</code> to be added.
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0245-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0245-isvalid.html
new file mode 100644
index 00000000000..513d80060c2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0245-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0245</title>
+</head>
+<body prefix="rdfatest: http://rdfa.info/vocabs/rdfa-test#" vocab="http://rdfa.info/vocabs/rdfa-test#">
+ Using the type <code about="_:a" typeof="BaseClass">BaseClass</code>
+ should cause a triple with <code>EqClass</code> to be added.
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0246-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0246-isvalid.html
new file mode 100644
index 00000000000..fd59c141cb2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0246-isvalid.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0246</title>
+ </head>
+ <body prefix="foaf: http://xmlns.com/foaf/0.1/">
+ <div about="http://www.example.org/#ben" rel="foaf:knows">
+ <p typeof="foaf:Person"><span property="foaf:name">Mark Birbeck</span></p>
+ <p typeof="foaf:Person"><span property="foaf:name">Ivan Herman</span></p>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0247-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0247-isvalid.html
new file mode 100644
index 00000000000..b0b8ca07114
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0247-isvalid.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0247</title>
+ </head>
+ <body prefix="foaf: http://xmlns.com/foaf/0.1/">
+ <div about ="http://www.example.org/#somebody" rel="foaf:knows">
+ <p property="foaf:name">Ivan Herman</p>
+ <p rel="foaf:mailbox" resource="mailto:ivan@w3.org">mailto:ivan@w3.org</p>
+ <p typeof="foaf:Person"><span property="foaf:name">Mark Birbeck</span></p>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0248-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0248-isvalid.html
new file mode 100644
index 00000000000..b2a3e3f6ed6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0248-isvalid.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0248</title>
+ </head>
+ <body prefix="foaf: http://xmlns.com/foaf/0.1/">
+ <div about ="http://www.example.org/#somebody" rev="foaf:knows">
+ <p property="foaf:name">Ivan Herman</p>
+ <p rel="foaf:mailbox" resource="mailto:ivan@w3.org">mailto:ivan@w3.org</p>
+ <p typeof="foaf:Person"><span property="foaf:name">Mark Birbeck</span></p>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0249-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0249-isvalid.html
new file mode 100644
index 00000000000..f84895c29ca
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0249-isvalid.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0249</title>
+ </head>
+ <body prefix="foaf: http://xmlns.com/foaf/0.1/">
+ <div about ="http://www.example.org/#somebody" rev="foaf:knows" rel="foaf:knows">
+ <p property="foaf:name">Ivan Herman</p>
+ <p rel="foaf:mailbox" resource="mailto:ivan@w3.org">mailto:ivan@w3.org</p>
+ <p typeof="foaf:Person"><span property="foaf:name">Mark Birbeck</span></p>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0250-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0250-isvalid.html
new file mode 100644
index 00000000000..61b8dbe7a96
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0250-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0250</title>
+ </head>
+ <body prefix="foaf: http://xmlns.com/foaf/0.1/">
+ <p about ="http://www.ivan-herman.net/foaf#me" typeof="foaf:Person" property="foaf:name">Ivan Herman</p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0251-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0251-isvalid.html
new file mode 100644
index 00000000000..1a39f19879b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0251-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html prefix="ex: http://example.org/">
+ <head about="">
+ <meta charset=utf-8>
+ <title>Test 251</title>
+ <meta about="http://example.org/node" property="ex:property" lang="fr" content="chat" />
+ </head>
+ <body>
+ <p></p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0252-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0252-isvalid.html
new file mode 100644
index 00000000000..ba7d228fc7e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0252-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html prefix="ex: http://example.org/">
+ <head about="" lang="fr">
+ <title lang="en">Test 0252</title>
+ <meta about="http://example.org/node" property="ex:property" content="chat" />
+ </head>
+ <body>
+ <p></p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0253-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0253-isvalid.html
new file mode 100644
index 00000000000..858aed8b247
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0253-isvalid.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html prefix="ex: http://example.org/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0108</title>
+ </head>
+ <body>
+ <p about="http://example.org/node" property="ex:property"
+ datatype="" lang="el">ελληνικό
+άσπρο διάστημα
+</p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0254-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0254-isvalid.html
new file mode 100644
index 00000000000..845a787757f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0254-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html prefix="ex: http://example.org/terms#">
+<head>
+ <meta charset=utf-8>
+ <title>Test 0254</title>
+ <base href="http://example.org/"/>
+</head>
+<body lang="en">
+ <p property="ex:prop" datatype="">A <strong>plain literal</strong> with a lang tag.</p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0255-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0255-isvalid.html
new file mode 100644
index 00000000000..1d4bbb23952
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0255-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html prefix="ex: http://example.org/terms#">
+<head>
+ <meta charset=utf-8>
+ <title>Test 0255</title>
+ <base href="http://example.org/"/>
+</head>
+<body lang="en">
+ <p property="ex:prop" lang="">Just a plain literal.</p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0257-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0257-isvalid.html
new file mode 100644
index 00000000000..01e194240cc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0257-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html prefix="dc: http://purl.org/dc/elements/1.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0257</title>
+ </head>
+ <body>
+ <span about="#a" property="dc:title"></span>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0258-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0258-novalid.html
new file mode 100644
index 00000000000..9f9a48c3d9b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0258-novalid.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Undescore Prefix is Ignored Test</title>
+</head>
+<body>
+<p>Ensure that the "_" prefix is ignored.</p>
+<p xmlns:_="http://example.org/"
+ prefix="_: http://example.org/"
+ xmlns:earl="http://www.w3.org/ns/earl#"
+ rel="earl:testcase" resource="_:test">Test</p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0259-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0259-isvalid.html
new file mode 100644
index 00000000000..e2c8e5d600f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0259-isvalid.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0259</title>
+</head>
+<body>
+ <div>
+ Vocabulary Prefixes
+ <span property="grddl:">GRDDL</span>
+ <span property="ma:">MA</span>
+ <span property="owl:">OWL</span>
+ <span property="rdf:">RDF</span>
+ <span property="rdfa:">RDFa</span>
+ <span property="rdfs:">RDFS</span>
+ <span property="rif:">RIF</span>
+ <span property="skos:">SKOS</span>
+ <span property="skosxl:">SKOS-XL</span>
+ <span property="wdr:">WDR</span>
+ <span property="void:">VOID</span>
+ <span property="wdrs:">WDRS</span>
+ <span property="xhv:">XHV</span>
+ <span property="xml:">XML</span>
+ <span property="xsd:">XSD</span>
+ </div>
+ <div>
+ Widely Used prefixes
+ <span property="cc:">CC</span>
+ <span property="ctag:">CTAG</span>
+ <span property="dc:">DC</span>
+ <span property="dcterms:">DCTERMS</span>
+ <span property="foaf:">FOAF</span>
+ <span property="gr:">GR</span>
+ <span property="ical:">ICAL</span>
+ <span property="og:">OG</span>
+ <span property="rev:">REV</span>
+ <span property="sioc:">SIOC</span>
+ <span property="v:">V</span>
+ <span property="vcard:">VCARD</span>
+ <span property="schema:">Schema</span>
+ </div>
+ <div>
+ Vocabulary Terms
+ <span property="describedby">DescribedBy</span>
+ <span property="license">License</span>
+ <span property="role">Role</span>
+ </div>
+</body></html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0261-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0261-isvalid.html
new file mode 100644
index 00000000000..6f887d1b62d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0261-isvalid.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html prefix="ex: http://example.org/rdf/ rdf: http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+<head>
+ <meta charset=utf-8>
+ <title>Test 0261</title>
+</head>
+<body>
+ <div about="http://www.example.org">
+ <p property="ex:xmllit" datatype="rdf:XMLLiteral">This is
+an XMLLiteral</p>
+</div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0262-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0262-isvalid.html
new file mode 100644
index 00000000000..5293ec2916b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0262-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html prefix="dc: http://purl.org/dc/elements/1.1/">
+<head>
+ <meta charset=utf-8>
+ <title>Test 0262</title>
+</head>
+<body>
+ <p>This photo was taken by <span class="author" about="photo1.jpg" property=" dc:creator
+">Mark Birbeck</span>.</p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0263-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0263-isvalid.html
new file mode 100644
index 00000000000..d8ef4b0b279
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0263-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html property="rdfs:seeAlso" resource="http://www.example.org">
+<head >
+ <meta charset=utf-8>
+ <title>Test 0263</title>
+</head>
+<body>
+ <p> </p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0264-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0264-isvalid.html
new file mode 100644
index 00000000000..62cefe5013d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0264-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head property="rdfs:seeAlso" resource="http://www.example.org">
+ <meta charset=utf-8>
+ <title>Test 0264</title>
+</head>
+<body>
+ <p> </p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0265-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0265-isvalid.html
new file mode 100644
index 00000000000..b4bcf8057a0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0265-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html about="http://www.example.com">
+<head property="rdfs:seeAlso" resource="http://www.example.org">
+ <meta charset=utf-8>
+ <title>Test 0265</title>
+</head>
+<body>
+ <p> </p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0266-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0266-isvalid.html
new file mode 100644
index 00000000000..5f30516f23f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0266-isvalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0266</title>
+</head>
+<body>
+ <div about="http://www.w3.org/Person/Ivan#me">
+ <a href="http://www.ivan-herman.net/foaf#me" typeof="foaf:Person" property="owl:sameAs">Ivan Herman</a>
+ </div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0267-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0267-isvalid.html
new file mode 100644
index 00000000000..291dad06caf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0267-isvalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0267</title>
+</head>
+<body>
+ <div about="http://www.w3.org/Person/Ivan#me">
+ <p resource="http://www.ivan-herman.net/foaf#me" typeof="foaf:Person" property="owl:sameAs">Ivan Herman</p>
+ </div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0268-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0268-isvalid.html
new file mode 100644
index 00000000000..77c2bc5e3d3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0268-isvalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0268</title>
+</head>
+<body>
+ <div about="http://www.ivan-herman.net/foaf#me">
+ <img src="http://www.ivan-herman.net/Images/me2003-small.png" typeof="foaf:Image" property="foaf:depiction" alt="Ivan Herman" />
+ </div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0269-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0269-isvalid.html
new file mode 100644
index 00000000000..3ff53585f11
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0269-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html property="rdfs:comment" content="This is an RDFa test">
+<head >
+ <meta charset=utf-8>
+ <title>Test 0269</title>
+</head>
+<body>
+ <p> </p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0271-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0271-isvalid.html
new file mode 100644
index 00000000000..50a8e8a84ec
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0271-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html about="http://www.example.org/">
+<head property="rdfs:comment" content="This is an RDFa test">
+ <meta charset=utf-8>
+ <title>Test 0269</title>
+</head>
+<body>
+ <p> </p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0272-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0272-isvalid.html
new file mode 100644
index 00000000000..ddd86e6b6d0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0272-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0272</title>
+</head>
+<body>
+ <time property="rdf:value" datetime="2012-03-18">18 March 2012</time>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0273-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0273-isvalid.html
new file mode 100644
index 00000000000..3bbf607f8a2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0273-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0273</title>
+</head>
+<body>
+ <time property="rdf:value" datetime="00:00:00">midnight</time>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0274-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0274-isvalid.html
new file mode 100644
index 00000000000..faf6d451ed0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0274-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0274</title>
+</head>
+<body>
+ <time property="rdf:value" datetime="2012-03-18T00:00:00Z">18 March 2012 at midnight</time>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0275-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0275-isvalid.html
new file mode 100644
index 00000000000..c53311b6457
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0275-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0275</title>
+</head>
+<body>
+ <time property="rdf:value">2012-03-18</time>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0276-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0276-isvalid.html
new file mode 100644
index 00000000000..6ca34862b6b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0276-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0275</title>
+</head>
+<body>
+ <time property="rdf:value">00:00:00</time>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0277-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0277-isvalid.html
new file mode 100644
index 00000000000..61922bf18ff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0277-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0277</title>
+</head>
+<body>
+ <time property="rdf:value">2012-03-18T00:00:00Z</time>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0278-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0278-isvalid.html
new file mode 100644
index 00000000000..7490cf0f18d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0278-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0278</title>
+</head>
+<body>
+ <p>The value of @content has a higher priority than @datetime</p>
+ <time property="rdf:value" datetime="2012-03-18" content="this should be the value">18 March 2012</time>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0279-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0279-isvalid.html
new file mode 100644
index 00000000000..da3798d085e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0279-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0279</title>
+</head>
+<body>
+ <time property="rdf:value" datetime="2012-03-18T00:00:00Z" datatype="xsd:date">18 March 2012 at midnight</time>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0280-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0280-novalid.html
new file mode 100644
index 00000000000..dbe94dfd0ac
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0280-novalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0280</title>
+</head>
+<body>
+ <time property="rdf:value" datetime="P2011Y06M28DT00H00M00S">2011 years 6 months 28 days</time>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0281-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0281-isvalid.html
new file mode 100644
index 00000000000..1158dc9361e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0281-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0281</title>
+</head>
+<body>
+ <time property="rdf:value" datetime="2012">Two Thousand Twelve</time>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0282-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0282-isvalid.html
new file mode 100644
index 00000000000..1fd9cb1a1fe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0282-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0282</title>
+</head>
+<body>
+ <time property="rdf:value" datetime="2012-03">March, Two Thousand Twelve</time>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0283-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0283-isvalid.html
new file mode 100644
index 00000000000..3be86a46f53
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0283-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0283</title>
+</head>
+<body>
+ <time property="rdf:value"> 2012-03-18</time>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0284-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0284-isvalid.html
new file mode 100644
index 00000000000..e2b0254b9a6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0284-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0284</title>
+</head>
+<body>
+ <time property="rdf:value" datatype="xsd:dateTime"> 2012-03-18</time>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0285-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0285-novalid.html
new file mode 100644
index 00000000000..58d276f28b4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0285-novalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0285</title>
+</head>
+<body>
+ <time property="rdf:value" lang="en" datetime="D-Day">
+ Non matching lexical value with language.
+ </time>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0287-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0287-isvalid.html
new file mode 100644
index 00000000000..17aa3007488
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0287-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0287</title>
+</head>
+<body>
+ <time property="rdf:value" datetime="2012-03-18T00:00:00-08:00">18 March 2012 at midnight in San Francisco</time>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0289-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0289-isvalid.html
new file mode 100644
index 00000000000..09af29ea572
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0289-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0289</title>
+</head>
+<body>
+ <h1>@href becomes subject when @property and @content are present</h1>
+ <a href="http://example.org/" property="rdf:value" content="value">ignored</a>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0290-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0290-isvalid.html
new file mode 100644
index 00000000000..12ac353b2d6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0290-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0290</title>
+</head>
+<body>
+ <h1>@href becomes subject when @property and @datatype are present</h1>
+ <a href="http://example.org/" property="rdf:value" datatype="">value</a>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0291-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0291-isvalid.html
new file mode 100644
index 00000000000..dddb87e2b68
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0291-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html prefix="rdf: http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+<head>
+ <meta charset=utf-8>
+ <title>Test 0291</title>
+</head>
+<body>
+ <h1>@href as subject overridden by @about</h1>
+ <a about="http://example.net/" href="http://example.org/" property="rdf:value" content="value">ignored</a>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0292-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0292-isvalid.html
new file mode 100644
index 00000000000..1a9e85b467c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0292-isvalid.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html prefix="rdf: http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+<head>
+ <meta charset=utf-8>
+ <title>Test 0292</title>
+</head>
+<body>
+ <h1>@about overriding @href as subject is used as parent resource</h1>
+ <a about="http://example.net/" href="http://example.org/" property="rdf:value" content="value one">
+ <span property="rdf:value">value two</span>
+ </a>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0293-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0293-isvalid.html
new file mode 100644
index 00000000000..2202603d775
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0293-isvalid.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0293</title>
+</head>
+<body>
+ <h1>Testing the ':' character usage in a CURIE</h1>
+ <div prefix="ex: http://www.example.org/">
+ <p about="http://www.example.org" property="ex:column:test">Test</p>
+ </div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0296-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0296-isvalid.html
new file mode 100644
index 00000000000..bdf56c40ed3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0296-isvalid.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0296</title>
+</head>
+<body>
+ <div vocab="http://xmlns.com/foaf/0.1/" resource="http://example.com/gregg/#me" typeof="Person">
+ <a property="homepage" href="http://example.com/gregg/"><span property="name">Gregg</span></a>
+ Knows
+ <ul>
+ <li property="knows" resource="http://example.com/niklas/#me" typeof="Person">
+ <a property="homepage" href="http://example.com/niklas/"><span property="name">Niklas</span></a>
+ </li>
+ <li property="knows" resource="http://example.com/stéphane/#me" typeof="Person">
+ <a property="homepage" href="http://example.com/stéphane/"><span property="name">Stéphane</span></a>
+ </li>
+ <li property="knows" resource="http://example.com/ivan/#me" typeof="Person">
+ <a property="homepage" href="http://example.com/ivan/"><span property="name">Ivan</span></a>
+ </li>
+ <li property="knows" resource="http://example.com/manu/#me" typeof="Person">
+ <a property="homepage" href="http://example.com/manu/"><span property="name">Manu</span></a>
+ </li>
+ </ul>
+ </div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0297-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0297-isvalid.html
new file mode 100644
index 00000000000..5832089565b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0297-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0297: Testing @typeof and @about=[]</title>
+</head>
+<body>
+ <div about="[]" typeof="foaf:Person" property="foaf:name">Alex Milowski</div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0298-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0298-isvalid.html
new file mode 100644
index 00000000000..54ab6d91d4f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0298-isvalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0298: Testing @typeof and @about=[]</title>
+</head>
+<body>
+ <div about="[]" typeof="foaf:Person">
+ <span property="foaf:name">Alex Milowski</span>
+ </div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0299-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0299-isvalid.html
new file mode 100644
index 00000000000..c529090d729
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0299-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0299: Testing @resource=[]</title>
+</head>
+<body about="http://www.example.org/">
+ <a href="http://www.example.org/license.xhtml" rel="xhv:license" resource="[]">The Foo Document</a>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0300-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0300-isvalid.html
new file mode 100644
index 00000000000..38741f14bc2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0300-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0300: Testing @resource=[]</title>
+</head>
+<body about="http://www.example.org/">
+ <a href="http://www.example.org/license.xhtml" property="xhv:license" resource="[]">The Foo Document</a>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0301-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0301-isvalid.html
new file mode 100644
index 00000000000..f6dce1da965
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0301-isvalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0301: Typed Property</title>
+</head>
+<body>
+ <p vocab="http://www.milowski.com/V/" property="bit" typeof="thing">
+ <span property="name">Fizzbit</span>
+ </p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0302-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0302-isvalid.html
new file mode 100644
index 00000000000..21020d0fc4c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0302-isvalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0302: various types of tokens in @typeof</title>
+</head>
+<body>
+ <div vocab="http://schema.org/" resource="http://openspring.net/scor#me" typeof="Person foaf:Person http://purl.org/dc/terms/Agent">
+ <a property="homepage" href="http://openspring.net/"><span property="name">Stéphane Corlosquet</span></a>
+ </div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0303-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0303-novalid.html
new file mode 100644
index 00000000000..64442095904
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0303-novalid.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0303: @rel/@rev terms removed if @property exists</title>
+</head>
+<body>
+ <div vocab="http://schema.org/" resource="http://example.org/base">
+ <a property="uri" rel="license" href="http://example.orb/val1">Not This</a>
+ <a property="name" rel="homepage foaf:homepage" href="http://greggkellogg.net/">Gregg Kellogg</a>
+ </div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0305-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0305-isvalid.html
new file mode 100644
index 00000000000..3ee7f486038
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0305-isvalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0305</title>
+ </head>
+ <body>
+ <div id="heading1" role="heading">
+ <p>Some contents that are a header</p>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0306-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0306-isvalid.html
new file mode 100644
index 00000000000..8abd9fd7409
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0306-isvalid.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0306</title>
+ <base href="http://www.example.com/tests/0306"/>
+ </head>
+ <body>
+ <div id="heading1" role="heading">
+ <p>Some contents that are a header</p>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0307-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0307-isvalid.html
new file mode 100644
index 00000000000..c9b99557abb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0307-isvalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0307</title>
+ </head>
+ <body>
+ <div role="heading">
+ <p>Some contents that are a header</p>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0308-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0308-novalid.html
new file mode 100644
index 00000000000..56f9a3930d7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0308-novalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0308</title>
+ </head>
+ <body>
+ <div id="therole" role="http://www.example.com/roles/somerole">
+ <p>Some contents that are a header</p>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0309-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0309-novalid.html
new file mode 100644
index 00000000000..e9ca319beb2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0309-novalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0309</title>
+ </head>
+ <body>
+ <div prefix="ex: http://www.example.com/roles/" id="therole" role="ex:somerole">
+ <p>Some contents that are a header</p>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0310-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0310-novalid.html
new file mode 100644
index 00000000000..89793d797a9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0310-novalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0310</title>
+ </head>
+ <body>
+ <div prefix="ex: http://www.example.com/roles/" id="therole" role="ex:somerole someOtherRole http://www.example.com/alternate/role">
+ <p>Some contents that are a header</p>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0311-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0311-isvalid.html
new file mode 100644
index 00000000000..e8991e4aed3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0311-isvalid.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0311</title>
+</head>
+<body>
+ <div>
+ <span class="attribution-line">this photo was taken by
+ <span property="">Stéphane Corlosquet</span>
+ </span>
+ </div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0312-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0312-isvalid.html
new file mode 100644
index 00000000000..af489fe88b4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0312-isvalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0312</title>
+</head>
+<body>
+ <p vocab="http://schema.org/" typeof="Person">
+ The homepage of <a href="http://example.org/" property="homepage" rel="nofollow">Some Body</a>.
+ </p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0313-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0313-isvalid.html
new file mode 100644
index 00000000000..e4b4b760da0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0313-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0313</title>
+</head>
+<body prefix="rdfa: http://www.example.org/" resource="http://www.example.com">
+ <p property="rdfa:erronouslyRedefinedProperty">Foo</p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0314-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0314-novalid.html
new file mode 100644
index 00000000000..a8e1c160845
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0314-novalid.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0314</title>
+ </head>
+ <body>
+ <div id="b" role="banner">
+ <p>Here is a banner for this page.</p>
+ </div>
+ <div id="toc" role="contentinfo">
+ <p>Here is some information about the page's contents:</p>
+ <ul id="contents" role="list">
+ <li role="listitem"><a href="#s1">Section 1</a></li>
+ <li role="listitem"><a href="#s2">Section 2</a></li>
+ <li role="listitem"><a href="#a1">Appendix 1</a></li>
+ </ul>
+ </div>
+ <div id="main" role="main">
+ <p>This is the primary content of this page. It has some sections.</p>
+ <div id="s1" role="section">
+ <h1 role="heading">Some contents that are a header</h1>
+ <p>Section 1 needs some content!</p>
+ </div>
+ <div id="s2" role="section">
+ <h1 role="heading">This is Section 2</h1>
+ <p>Section 2 is pretty boring.</p>
+ </div>
+ <div id="a1" role="appendix">
+ <h1 role="heading">This is Appendix 1</h1>
+ <p role="note">It is a note about the document - not a primary content
+ item.</p>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0315-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0315-isvalid.html
new file mode 100644
index 00000000000..79bf76a0232
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0315-isvalid.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0315</title>
+</head>
+<body prefix="po: http://example.org/">
+ <dl>
+ <dt rel="po:role" class="role">
+ <span typeof="po:Role" property="rdfs:label">Director</span>
+ </dt>
+ <dd></dd>
+ </dl>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0316-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0316-isvalid.html
new file mode 100644
index 00000000000..7063dd3aa62
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0316-isvalid.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0316</title>
+</head>
+<body prefix="po: http://example.org/">
+ <dl>
+ <dt rel="po:role" class="role">
+ <a typeof="po:Role" property="rdfs:label" href="http://example.org/profiles/director.html">Director</a>
+ </dt>
+ <dd></dd>
+ </dl>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0317-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0317-isvalid.html
new file mode 100644
index 00000000000..a8d0f895009
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0317-isvalid.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0316</title>
+</head>
+<body prefix="po: http://purl.org/ontology/po/">
+ <dl>
+ <dt rel="po:role" class="role">
+ <a typeof="po:Role" property="rdfs:label" datatype="" href="http://example.org/profiles/director.html">Director</a>
+ </dt>
+ <dd></dd>
+ </dl>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0318-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0318-isvalid.html
new file mode 100644
index 00000000000..cd81dd3291a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0318-isvalid.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0318</title>
+ </head>
+ <body>
+ <div vocab="http://xmlns.com/foaf/0.1/">
+ <div about ="#me">
+ <p property="name">Ivan Herman</p>
+ <meta vocab="" property="prop" content="value"/>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0319-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0319-novalid.html
new file mode 100644
index 00000000000..86dd40e1221
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0319-novalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <base href="http://example.com/"/>
+ <meta charset=utf-8>
+ <title>Test 0319</title>
+</head>
+<body prefix="pr: relative/iri#" xmlns:xpr="relative/uri#">
+ <p property="pr:prop xpr:prop">value</p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0320-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0320-novalid.html
new file mode 100644
index 00000000000..19816e4c849
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0320-novalid.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0320</title>
+</head>
+<body>
+ <div vocab="http://xmlns.com/foaf/0.1/" resource="http://example.com/gregg/#me" typeof="Person">
+ <a property="homepage" href="http://example.com/gregg/" src="http://example.net/gregg">
+ <span property="name">Gregg</span>
+ </a>
+ </div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0321-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0321-isvalid.html
new file mode 100644
index 00000000000..f8d6066fff1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0321-isvalid.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0321</title>
+</head>
+<body vocab="http://schema.org/">
+ <div typeof="Person">
+ <link property="rdfa:copy" resource="_:a"/>
+ </div>
+ <p resource="_:a" typeof="rdfa:Pattern">Name: <span property="name">Amanda</span></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0322-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0322-isvalid.html
new file mode 100644
index 00000000000..ec2126ea706
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0322-isvalid.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0322</title>
+</head>
+<body vocab="http://schema.org/">
+ <div typeof="Person">
+ <p>My name is <span property="name">Gregg</span></p>
+ <link property="rdfa:copy" resource="_:surname"/>
+ </div>
+ <p resource="_:surname" typeof="rdfa:Pattern">My name is <span property="name">Kellogg</span></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0323-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0323-isvalid.html
new file mode 100644
index 00000000000..3e40723b2c6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0323-isvalid.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0323</title>
+</head>
+<body>
+ <div typeof="schema:Person">
+ <link property="rdfa:copy" resource="_:a"/>
+ </div>
+ <div typeof="foaf:Person">
+ <link property="rdfa:copy" resource="_:a"/>
+ </div>
+ <p resource="_:a" typeof="rdfa:Pattern">Name: <span property="schema:name foaf:name">Amanda</span></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0324-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0324-isvalid.html
new file mode 100644
index 00000000000..4c05270fde2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0324-isvalid.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0324</title>
+</head>
+<body>
+ <div typeof="schema:Person">
+ <link property="rdfa:copy" resource="_:a"/>
+ <link property="rdfa:copy" resource="_:b"/>
+ </div>
+ <p resource="_:a" typeof="rdfa:Pattern">Name: <span property="schema:name">Amanda</span></p>
+ <p resource="_:b" typeof="rdfa:Pattern"><span property="schema:band">Jazz Band</span></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0325-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0325-isvalid.html
new file mode 100644
index 00000000000..004ba800598
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0325-isvalid.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <base href="http://example.org/"/>
+ <meta charset=utf-8>
+ <title>Test 0325</title>
+</head>
+<body vocab="http://schema.org/">
+ <div resource="#foo" typeof=""><link property="rdfa:copy" resource="_:a"/></div>
+ <div resource="#bar" typeof=""><link property="rdfa:copy" resource="_:a"/></div>
+ <div resource="_:a" typeof="rdfa:Pattern">
+ <div property="schema:refers-to" typeof="">
+ <span property="schema:name">Amanda</span>
+ </div>
+ </div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0326-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0326-isvalid.html
new file mode 100644
index 00000000000..95ae06a7fe9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0326-isvalid.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <base href="http://example.com/"/>
+ <meta charset=utf-8>
+ <title>Test 0326</title>
+</head>
+<body vocab="http://schema.org/">
+ <div resource="#referencing" typeof="Person">
+ <link property="rdfa:copy" resource="#referenced"/>
+ </div>
+ <p resource="#referenced" typeof="rdfa:Pattern">Name: <span property="name">Bella</span></p>
+ <p resource="#unreferenced" typeof="rdfa:Pattern">Name: <span property="name">Lola</span></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0327-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0327-isvalid.html
new file mode 100644
index 00000000000..25f14e7575b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0327-isvalid.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <base href="http://example.com/"/>
+ <meta charset=utf-8>
+ <title>Test 0327</title>
+</head>
+<body>
+ <div typeof="schema:Person">
+ <link property="rdfa:copy" resource="_:a"/>
+ <link property="rdfa:copy" resource="_:b"/>
+ </div>
+ <p resource="_:a" typeof="rdfa:Pattern">Name: <span property="schema:name">Amanda</span></p>
+ <div resource="_:b" typeof="rdfa:Pattern">
+ <div property="schema:band" typeof=" schema:MusicGroup">
+ <link property="rdfa:copy" resource="_:c"/>
+ </div>
+ </div>
+ <div resource="_:c" typeof="rdfa:Pattern">
+ <p>Band: <span property="schema:name">Jazz Band</span></p>
+ <p>Size: <span property="schema:size">12</span> players</p>
+ </div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0328-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0328-isvalid.html
new file mode 100644
index 00000000000..11fdf077bd5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0328-isvalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0328</title>
+</head>
+<body>
+ <p>The value of @content has a higher priority than the content of the element</p>
+ <time property="rdf:value" content="this should be the value">2012-03-18</time>
+</body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0329-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0329-isvalid.html
new file mode 100644
index 00000000000..996183c848e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0329-isvalid.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html prefix="foaf: http://xmlns.com/foaf/0.1/">
+<head>
+ <meta charset=utf-8>
+ <title>Test 0329</title>
+</head>
+<body>
+ <div about="http://example.org/foaf#me" property="foaf:name">
+ <span property="foaf:givenName">John</span>
+ <span property="foaf:familyName">Doe</span>
+ </div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0330-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0330-isvalid.html
new file mode 100644
index 00000000000..2ce3e07ede2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0330-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html prefix="dcterms: http://purl.org/dc/terms/ xsd: http://www.w3.org/2001/XMLSchema#">
+<head>
+ <meta charset=utf-8>
+ <title>Test 0330</title>
+</head>
+<body lang="en">
+ <div property="dc:date" datatype="xsd:date">2010-11-12</div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0331-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0331-isvalid.html
new file mode 100644
index 00000000000..f54979398d5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfa/0331-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html prefix="dcterms: http://purl.org/dc/terms/">
+<head>
+ <meta charset=utf-8>
+ <title>Test 0331</title>
+</head>
+<body lang="en">
+ <div property="dcterms:language" datatype="dcterms:RFC5646" content="af">Afrikaans</div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0015-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0015-novalid.html
new file mode 100644
index 00000000000..94742da735d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0015-novalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html prefix="dc: http://purl.org/dc/elements/1.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0015</title>
+ <link rel="dc:source" href="urn:isbn:0140449132" />
+ <meta property="dc:creator" content="Fyodor Dostoevsky" />
+ </head>
+ <body>
+ <p></p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0021-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0021-isvalid.html
new file mode 100644
index 00000000000..21b9f42112e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0021-isvalid.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html prefix="dc: http://purl.org/dc/elements/1.1/">
+<head>
+ <meta charset=utf-8>
+ <title>Test 0021</title>
+</head>
+<body>
+ <div>
+ <span class="attribution-line">this photo was taken by
+ <span property="dc:creator">Mark Birbeck</span>
+ </span>
+ </div>
+</body>
+
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0023-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0023-isvalid.html
new file mode 100644
index 00000000000..5859d457881
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0023-isvalid.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html prefix="dc: http://purl.org/dc/elements/1.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0023</title>
+ </head>
+ <body>
+ <div id="photo1">
+ This photo was taken by
+ <span property="dc:creator">Mark Birbeck</span>
+ </div>
+ </body>
+
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0030-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0030-novalid.html
new file mode 100644
index 00000000000..7fd1a85ec7a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0030-novalid.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html prefix="cc: http://creativecommons.org/ns#">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0030</title>
+ </head>
+ <body>
+ <p>This document is licensed under a
+ <a rel="cc:license"
+ href="http://creativecommons.org/licenses/by-nc-nd/2.5/">
+ Creative Commons License
+ </a>.
+ </p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0050-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0050-isvalid.html
new file mode 100644
index 00000000000..94e28c88b6c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0050-isvalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html prefix="foaf: http://xmlns.com/foaf/0.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0050</title>
+ </head>
+ <body>
+ <div typeof="foaf:Person">
+ <p property="foaf:name">John Doe</p>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0052-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0052-isvalid.html
new file mode 100644
index 00000000000..8e4d02f7bf2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0052-isvalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html prefix="foaf: http://xmlns.com/foaf/0.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0052</title>
+ </head>
+ <body>
+ <p typeof="foaf:Person" resource="http://www.example.org/#me">
+ John Doe
+ </p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0053-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0053-isvalid.html
new file mode 100644
index 00000000000..f5d2172923c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0053-isvalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html prefix="foaf: http://xmlns.com/foaf/0.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0053</title>
+ </head>
+ <body>
+ <p typeof="foaf:Person" resource="http://www.example.org/#me">
+ <span property="foaf:name">John Doe</span>
+ </p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0066-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0066-isvalid.html
new file mode 100644
index 00000000000..dc8642ac734
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0066-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html prefix="foaf: http://xmlns.com/foaf/0.1/">
+ <head typeof="foaf:Document">
+ <meta charset=utf-8>
+ <title>Test 0066</title>
+ </head>
+ <body>
+ <p>This is test #66.</p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0067-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0067-isvalid.html
new file mode 100644
index 00000000000..e60e30e04da
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0067-isvalid.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html prefix="foaf: http://xmlns.com/foaf/0.1/">
+ <head>
+ <title property="foaf:topic">Test 0067</title>
+ </head>
+ <body>
+ <p>This is test #67.</p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0071-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0071-novalid.html
new file mode 100644
index 00000000000..511e0b7107b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0071-novalid.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html prefix="cc: http://creativecommons.org/ns#">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0071</title>
+ </head>
+ <body>
+ <p>This page is under a Creative Commons
+ <a rel="cc:license"
+ href="http://creativecommons.org/licenses/by-nd/3.0/">
+ Attribution-No Derivatives 3.0 license</a>.
+ </p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0074-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0074-novalid.html
new file mode 100644
index 00000000000..d25af2d5323
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0074-novalid.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html prefix="dc: http://purl.org/dc/elements/1.1/">
+ <head>
+ <base href="http://www.example.org/"/>
+ <meta charset=utf-8>
+ <title>Test 0074</title>
+ </head>
+ <body>
+ <p>
+ This article was written by
+ <a rel="dc:creator" href="jane">Jane</a>.
+ </p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0075-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0075-isvalid.html
new file mode 100644
index 00000000000..15f0dd01927
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0075-isvalid.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html prefix="dc: http://purl.org/dc/elements/1.1/">
+ <head>
+ <base href="http://www.example.org/"/>
+ <meta charset=utf-8>
+ <title>Test 0075</title>
+ </head>
+ <body>
+ <p>
+ This page is under a Creative Commons
+ <a rel="license" href="http://creativecommons.org/licenses/by-nd/3.0/">Attribution-No Derivatives 3.0 license</a>.
+ </p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0089-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0089-isvalid.html
new file mode 100644
index 00000000000..e85d6d7522f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0089-isvalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html prefix="foaf: http://xmlns.com/foaf/0.1/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0089</title>
+ </head>
+ <body>
+ <div>
+ <img src="http://example.org/example.png" typeof="foaf:Image" alt="example image" />
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0115-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0115-isvalid.html
new file mode 100644
index 00000000000..cde9b6e40d2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0115-isvalid.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html prefix="ex: http://www.example.com/">
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0115</title>
+ </head>
+ <body>
+ <p>Description: XML entities in the RDFa content</p>
+ <p>
+ <span property="ex:entity1">&gt;</span>
+ <span property="ex:entity2">Ben &amp; Co.</span>
+ <span property="ex:entity3">&#x40;</span>
+ <span property="ex:entity4">&#64;</span>
+ </p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0117-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0117-isvalid.html
new file mode 100644
index 00000000000..4f3957b825a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0117-isvalid.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html prefix="dc: http://purl.org/dc/elements/1.1/">
+ <head>
+ <base href="http://www.example.org/tc117.xhtml#fragment"/>
+ <title property="dc:title">Test 0117</title>
+ </head>
+ <body>
+ <p>
+ <span property="dc:contributor">Mark Birbeck</span>
+ added this triple test.
+ </p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0134-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0134-isvalid.html
new file mode 100644
index 00000000000..2e77ec5ad34
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0134-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test</title>
+ <link rel="LICENSE" href="http://example.org/test.css" />
+</head>
+<body>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0140-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0140-isvalid.html
new file mode 100644
index 00000000000..d2a71239296
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0140-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Blank-node as Predicate Test</title>
+</head>
+<body>
+<p>Blank Nodes are not allowed to be predicate identifiers in RDF:</p>
+<p property="_:invalid">Test</p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0147.novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0147.novalid.html
new file mode 100644
index 00000000000..23adadedf12
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0147.novalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test</title>
+</head>
+<body>
+<p xmlns:xmlzzz="http://example.org/" property="xmlzzz:test">Test</p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0214-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0214-isvalid.html
new file mode 100644
index 00000000000..395e645fb87
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0214-isvalid.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html typeof="foaf:Document">
+<head>
+ <title property="dc:title">Test 0214</title>
+</head>
+<body>
+ <p>This document has a title.</p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0235-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0235-isvalid.html
new file mode 100644
index 00000000000..183956137e2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0235-isvalid.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0235</title>
+ </head>
+ <body>
+ <p>
+ The <span property="dc:title">rdfagraph</span> should not generate triples when
+ looking only at the processor graph.
+ </p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0238-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0238-isvalid.html
new file mode 100644
index 00000000000..92feca27aed
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0238-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0238</title>
+</head>
+<body property="undefined_term">
+ Undefined Term
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0239-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0239-isvalid.html
new file mode 100644
index 00000000000..a28850ee58e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0239-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0239</title>
+</head>
+<body property="rdf:value"
+ resource="[undefined:curie]">
+ Undefined Prefix
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0240-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0240-isvalid.html
new file mode 100644
index 00000000000..9938beaa8f8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0240-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0240</title>
+</head>
+<body prefix="rdfatest: http://rdfa.info/vocabs/rdfa-test#" vocab="http://rdfa.info/vocabs/rdfa-test#">
+ Using the property <code property="subProp" resource="rdfatest:subProp">subProp</code>
+ should cause a triple with <code>baseProp</code> to be added.
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0241-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0241-isvalid.html
new file mode 100644
index 00000000000..eb6b77a98db
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0241-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0241</title>
+</head>
+<body prefix="rdfatest: http://rdfa.info/vocabs/rdfa-test#" vocab="http://rdfa.info/vocabs/rdfa-test#">
+ Using the property <code property="eqProp" resource="rdfatest:eqProp">eqProp</code>
+ should cause a triple with <code>baseProp</code> to be added.
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0242-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0242-isvalid.html
new file mode 100644
index 00000000000..7b6a59078d6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0242-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0242</title>
+</head>
+<body prefix="rdfatest: http://rdfa.info/vocabs/rdfa-test#" vocab="http://rdfa.info/vocabs/rdfa-test#">
+ Using the property <code property="baseProp" resource="rdfatest:eqProp">eqProp</code>
+ should cause a triple with <code>eqProp</code> to be added.
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0255-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0255-isvalid.html
new file mode 100644
index 00000000000..1d4bbb23952
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0255-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html prefix="ex: http://example.org/terms#">
+<head>
+ <meta charset=utf-8>
+ <title>Test 0255</title>
+ <base href="http://example.org/"/>
+</head>
+<body lang="en">
+ <p property="ex:prop" lang="">Just a plain literal.</p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0259-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0259-isvalid.html
new file mode 100644
index 00000000000..e2c8e5d600f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0259-isvalid.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0259</title>
+</head>
+<body>
+ <div>
+ Vocabulary Prefixes
+ <span property="grddl:">GRDDL</span>
+ <span property="ma:">MA</span>
+ <span property="owl:">OWL</span>
+ <span property="rdf:">RDF</span>
+ <span property="rdfa:">RDFa</span>
+ <span property="rdfs:">RDFS</span>
+ <span property="rif:">RIF</span>
+ <span property="skos:">SKOS</span>
+ <span property="skosxl:">SKOS-XL</span>
+ <span property="wdr:">WDR</span>
+ <span property="void:">VOID</span>
+ <span property="wdrs:">WDRS</span>
+ <span property="xhv:">XHV</span>
+ <span property="xml:">XML</span>
+ <span property="xsd:">XSD</span>
+ </div>
+ <div>
+ Widely Used prefixes
+ <span property="cc:">CC</span>
+ <span property="ctag:">CTAG</span>
+ <span property="dc:">DC</span>
+ <span property="dcterms:">DCTERMS</span>
+ <span property="foaf:">FOAF</span>
+ <span property="gr:">GR</span>
+ <span property="ical:">ICAL</span>
+ <span property="og:">OG</span>
+ <span property="rev:">REV</span>
+ <span property="sioc:">SIOC</span>
+ <span property="v:">V</span>
+ <span property="vcard:">VCARD</span>
+ <span property="schema:">Schema</span>
+ </div>
+ <div>
+ Vocabulary Terms
+ <span property="describedby">DescribedBy</span>
+ <span property="license">License</span>
+ <span property="role">Role</span>
+ </div>
+</body></html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0263-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0263-isvalid.html
new file mode 100644
index 00000000000..d8ef4b0b279
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0263-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html property="rdfs:seeAlso" resource="http://www.example.org">
+<head >
+ <meta charset=utf-8>
+ <title>Test 0263</title>
+</head>
+<body>
+ <p> </p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0264-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0264-isvalid.html
new file mode 100644
index 00000000000..62cefe5013d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0264-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head property="rdfs:seeAlso" resource="http://www.example.org">
+ <meta charset=utf-8>
+ <title>Test 0264</title>
+</head>
+<body>
+ <p> </p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0272-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0272-isvalid.html
new file mode 100644
index 00000000000..ddd86e6b6d0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0272-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0272</title>
+</head>
+<body>
+ <time property="rdf:value" datetime="2012-03-18">18 March 2012</time>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0273-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0273-isvalid.html
new file mode 100644
index 00000000000..3bbf607f8a2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0273-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0273</title>
+</head>
+<body>
+ <time property="rdf:value" datetime="00:00:00">midnight</time>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0274-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0274-isvalid.html
new file mode 100644
index 00000000000..faf6d451ed0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0274-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0274</title>
+</head>
+<body>
+ <time property="rdf:value" datetime="2012-03-18T00:00:00Z">18 March 2012 at midnight</time>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0275-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0275-isvalid.html
new file mode 100644
index 00000000000..c53311b6457
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0275-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0275</title>
+</head>
+<body>
+ <time property="rdf:value">2012-03-18</time>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0276-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0276-isvalid.html
new file mode 100644
index 00000000000..6ca34862b6b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0276-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0275</title>
+</head>
+<body>
+ <time property="rdf:value">00:00:00</time>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0277-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0277-isvalid.html
new file mode 100644
index 00000000000..61922bf18ff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0277-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0277</title>
+</head>
+<body>
+ <time property="rdf:value">2012-03-18T00:00:00Z</time>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0281-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0281-isvalid.html
new file mode 100644
index 00000000000..1158dc9361e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0281-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0281</title>
+</head>
+<body>
+ <time property="rdf:value" datetime="2012">Two Thousand Twelve</time>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0282-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0282-isvalid.html
new file mode 100644
index 00000000000..1fd9cb1a1fe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0282-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0282</title>
+</head>
+<body>
+ <time property="rdf:value" datetime="2012-03">March, Two Thousand Twelve</time>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0283-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0283-isvalid.html
new file mode 100644
index 00000000000..3be86a46f53
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0283-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0283</title>
+</head>
+<body>
+ <time property="rdf:value"> 2012-03-18</time>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0287-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0287-isvalid.html
new file mode 100644
index 00000000000..17aa3007488
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0287-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0287</title>
+</head>
+<body>
+ <time property="rdf:value" datetime="2012-03-18T00:00:00-08:00">18 March 2012 at midnight in San Francisco</time>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0296-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0296-isvalid.html
new file mode 100644
index 00000000000..bdf56c40ed3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0296-isvalid.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0296</title>
+</head>
+<body>
+ <div vocab="http://xmlns.com/foaf/0.1/" resource="http://example.com/gregg/#me" typeof="Person">
+ <a property="homepage" href="http://example.com/gregg/"><span property="name">Gregg</span></a>
+ Knows
+ <ul>
+ <li property="knows" resource="http://example.com/niklas/#me" typeof="Person">
+ <a property="homepage" href="http://example.com/niklas/"><span property="name">Niklas</span></a>
+ </li>
+ <li property="knows" resource="http://example.com/stéphane/#me" typeof="Person">
+ <a property="homepage" href="http://example.com/stéphane/"><span property="name">Stéphane</span></a>
+ </li>
+ <li property="knows" resource="http://example.com/ivan/#me" typeof="Person">
+ <a property="homepage" href="http://example.com/ivan/"><span property="name">Ivan</span></a>
+ </li>
+ <li property="knows" resource="http://example.com/manu/#me" typeof="Person">
+ <a property="homepage" href="http://example.com/manu/"><span property="name">Manu</span></a>
+ </li>
+ </ul>
+ </div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0301-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0301-isvalid.html
new file mode 100644
index 00000000000..f6dce1da965
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0301-isvalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0301: Typed Property</title>
+</head>
+<body>
+ <p vocab="http://www.milowski.com/V/" property="bit" typeof="thing">
+ <span property="name">Fizzbit</span>
+ </p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0302-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0302-isvalid.html
new file mode 100644
index 00000000000..21020d0fc4c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0302-isvalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0302: various types of tokens in @typeof</title>
+</head>
+<body>
+ <div vocab="http://schema.org/" resource="http://openspring.net/scor#me" typeof="Person foaf:Person http://purl.org/dc/terms/Agent">
+ <a property="homepage" href="http://openspring.net/"><span property="name">Stéphane Corlosquet</span></a>
+ </div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0305-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0305-isvalid.html
new file mode 100644
index 00000000000..3ee7f486038
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0305-isvalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0305</title>
+ </head>
+ <body>
+ <div id="heading1" role="heading">
+ <p>Some contents that are a header</p>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0306-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0306-isvalid.html
new file mode 100644
index 00000000000..8abd9fd7409
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0306-isvalid.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0306</title>
+ <base href="http://www.example.com/tests/0306"/>
+ </head>
+ <body>
+ <div id="heading1" role="heading">
+ <p>Some contents that are a header</p>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0307-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0307-isvalid.html
new file mode 100644
index 00000000000..c9b99557abb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0307-isvalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>Test 0307</title>
+ </head>
+ <body>
+ <div role="heading">
+ <p>Some contents that are a header</p>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0311-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0311-isvalid.html
new file mode 100644
index 00000000000..e8991e4aed3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0311-isvalid.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0311</title>
+</head>
+<body>
+ <div>
+ <span class="attribution-line">this photo was taken by
+ <span property="">Stéphane Corlosquet</span>
+ </span>
+ </div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0312-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0312-isvalid.html
new file mode 100644
index 00000000000..af489fe88b4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0312-isvalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0312</title>
+</head>
+<body>
+ <p vocab="http://schema.org/" typeof="Person">
+ The homepage of <a href="http://example.org/" property="homepage" rel="nofollow">Some Body</a>.
+ </p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0313-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0313-isvalid.html
new file mode 100644
index 00000000000..e4b4b760da0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0313-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0313</title>
+</head>
+<body prefix="rdfa: http://www.example.org/" resource="http://www.example.com">
+ <p property="rdfa:erronouslyRedefinedProperty">Foo</p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0319-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0319-novalid.html
new file mode 100644
index 00000000000..86dd40e1221
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0319-novalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <base href="http://example.com/"/>
+ <meta charset=utf-8>
+ <title>Test 0319</title>
+</head>
+<body prefix="pr: relative/iri#" xmlns:xpr="relative/uri#">
+ <p property="pr:prop xpr:prop">value</p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0321-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0321-isvalid.html
new file mode 100644
index 00000000000..f8d6066fff1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0321-isvalid.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0321</title>
+</head>
+<body vocab="http://schema.org/">
+ <div typeof="Person">
+ <link property="rdfa:copy" resource="_:a"/>
+ </div>
+ <p resource="_:a" typeof="rdfa:Pattern">Name: <span property="name">Amanda</span></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0322-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0322-isvalid.html
new file mode 100644
index 00000000000..ec2126ea706
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0322-isvalid.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0322</title>
+</head>
+<body vocab="http://schema.org/">
+ <div typeof="Person">
+ <p>My name is <span property="name">Gregg</span></p>
+ <link property="rdfa:copy" resource="_:surname"/>
+ </div>
+ <p resource="_:surname" typeof="rdfa:Pattern">My name is <span property="name">Kellogg</span></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0323-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0323-isvalid.html
new file mode 100644
index 00000000000..3e40723b2c6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0323-isvalid.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0323</title>
+</head>
+<body>
+ <div typeof="schema:Person">
+ <link property="rdfa:copy" resource="_:a"/>
+ </div>
+ <div typeof="foaf:Person">
+ <link property="rdfa:copy" resource="_:a"/>
+ </div>
+ <p resource="_:a" typeof="rdfa:Pattern">Name: <span property="schema:name foaf:name">Amanda</span></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0324-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0324-isvalid.html
new file mode 100644
index 00000000000..4c05270fde2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0324-isvalid.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test 0324</title>
+</head>
+<body>
+ <div typeof="schema:Person">
+ <link property="rdfa:copy" resource="_:a"/>
+ <link property="rdfa:copy" resource="_:b"/>
+ </div>
+ <p resource="_:a" typeof="rdfa:Pattern">Name: <span property="schema:name">Amanda</span></p>
+ <p resource="_:b" typeof="rdfa:Pattern"><span property="schema:band">Jazz Band</span></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0325-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0325-isvalid.html
new file mode 100644
index 00000000000..004ba800598
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0325-isvalid.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <base href="http://example.org/"/>
+ <meta charset=utf-8>
+ <title>Test 0325</title>
+</head>
+<body vocab="http://schema.org/">
+ <div resource="#foo" typeof=""><link property="rdfa:copy" resource="_:a"/></div>
+ <div resource="#bar" typeof=""><link property="rdfa:copy" resource="_:a"/></div>
+ <div resource="_:a" typeof="rdfa:Pattern">
+ <div property="schema:refers-to" typeof="">
+ <span property="schema:name">Amanda</span>
+ </div>
+ </div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0326-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0326-isvalid.html
new file mode 100644
index 00000000000..95ae06a7fe9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0326-isvalid.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <base href="http://example.com/"/>
+ <meta charset=utf-8>
+ <title>Test 0326</title>
+</head>
+<body vocab="http://schema.org/">
+ <div resource="#referencing" typeof="Person">
+ <link property="rdfa:copy" resource="#referenced"/>
+ </div>
+ <p resource="#referenced" typeof="rdfa:Pattern">Name: <span property="name">Bella</span></p>
+ <p resource="#unreferenced" typeof="rdfa:Pattern">Name: <span property="name">Lola</span></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0327-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0327-isvalid.html
new file mode 100644
index 00000000000..25f14e7575b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html-rdfalite/0327-isvalid.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <base href="http://example.com/"/>
+ <meta charset=utf-8>
+ <title>Test 0327</title>
+</head>
+<body>
+ <div typeof="schema:Person">
+ <link property="rdfa:copy" resource="_:a"/>
+ <link property="rdfa:copy" resource="_:b"/>
+ </div>
+ <p resource="_:a" typeof="rdfa:Pattern">Name: <span property="schema:name">Amanda</span></p>
+ <div resource="_:b" typeof="rdfa:Pattern">
+ <div property="schema:band" typeof=" schema:MusicGroup">
+ <link property="rdfa:copy" resource="_:c"/>
+ </div>
+ </div>
+ <div resource="_:c" typeof="rdfa:Pattern">
+ <p>Band: <span property="schema:name">Jazz Band</span></p>
+ <p>Size: <span property="schema:size">12</span> players</p>
+ </div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/Makefile b/tests/wpt/web-platform-tests/conformance-checkers/html/Makefile
new file mode 100644
index 00000000000..332591348fb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/Makefile
@@ -0,0 +1,20 @@
+PYTHON=python
+PYTHONFLAGS=
+META_EXTENSIONS=http://help.whatwg.org/extensions/meta-name/
+CURL=curl
+CURLFLAGS=
+PYTHON=python
+PYTHONFLAGS=
+
+.PHONY: ins-del-datetime .FORCE
+
+all: ins-del-datetime tools/meta-extensions elements/meta/names-registered-isvalid.html
+
+ins-del-datetime: tools/ins-del-datetime.py
+ $(PYTHON) $(PYTHONFLAGS) $<
+
+tools/meta-extensions: .FORCE
+ $(CURL) $(CURLFLAGS) $(META_EXTENSIONS) > $@
+
+elements/meta/names-registered-isvalid.html: .FORCE
+ $(PYTHON) $(PYTHONFLAGS) tools/meta-name.py
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/attributes/accesskey/duplicate-key-labels-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/attributes/accesskey/duplicate-key-labels-novalid.html
new file mode 100644
index 00000000000..1c9800d6273
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/attributes/accesskey/duplicate-key-labels-novalid.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+<head><meta charset="UTF-8">
+<title>accesskey attribute with duplicate key labels</title>
+</head>
+<body>
+<a href=url accesskey="a b ぬ c ぬ">foo</a>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/attributes/accesskey/multi-character-key-label-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/attributes/accesskey/multi-character-key-label-novalid.html
new file mode 100644
index 00000000000..303e1ea92e0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/attributes/accesskey/multi-character-key-label-novalid.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+<head><meta charset="UTF-8">
+<title>accesskey attribute with multi-character key label</title>
+</head>
+<body>
+<a href=url accesskey="a b ほげ">foo</a>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/attributes/data/no-characters-after-hyphen-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/attributes/data/no-characters-after-hyphen-novalid.html
new file mode 100644
index 00000000000..b30b1f9a715
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/attributes/data/no-characters-after-hyphen-novalid.html
@@ -0,0 +1,4 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>starts with the string "data-", has at least one character after the hyphen, is XML-compatible, and contains no uppercase ASCII letters</title>
+<p data-=""> <!-- no characters after the hypen -->
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/attributes/data/not-xml-serializable-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/attributes/data/not-xml-serializable-novalid.html
new file mode 100644
index 00000000000..7bcbfcbf5e3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/attributes/data/not-xml-serializable-novalid.html
@@ -0,0 +1,4 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>starts with the string "data-", has at least one character after the hyphen, is XML-compatible, and contains no uppercase ASCII letters</title>
+<p data-z:foo=""><!-- not serializable as XML -->
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/attributes/data/value-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/attributes/data/value-isvalid.html
new file mode 100644
index 00000000000..96f0917d484
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/attributes/data/value-isvalid.html
@@ -0,0 +1,7 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>valid data-</title>
+<!-- starts with the string "data-", has at least one character after the hyphen, is XML-compatible, and contains no uppercase ASCII letters -->
+<p data-z="">
+<!-- starts with the string "data-", has at least one character after the hyphen, is XML-compatible, and contains no uppercase ASCII letters -->
+<p data-78zxyabc123-foo_bar_baz="">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/attributes/lang/deprecated-tag-haswarn.html b/tests/wpt/web-platform-tests/conformance-checkers/html/attributes/lang/deprecated-tag-haswarn.html
new file mode 100644
index 00000000000..4fc1aaaafc6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/attributes/lang/deprecated-tag-haswarn.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>must be a valid BCP 47 language tag, or the empty string</title>
+<meta charset=utf-8>
+</head>
+<body lang=mo><!-- deprecated subtag -->
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/attributes/lang/empty-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/attributes/lang/empty-isvalid.html
new file mode 100644
index 00000000000..f88354d019a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/attributes/lang/empty-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="">
+<head>
+<meta charset=utf-8>
+<title>must be a valid BCP 47 language tag, or the empty string</title>
+</head>
+<body>
+<p></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/attributes/lang/extlang-bad-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/attributes/lang/extlang-bad-novalid.html
new file mode 100644
index 00000000000..7908f08c3f4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/attributes/lang/extlang-bad-novalid.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>must be a valid BCP 47 language tag, or the empty string</title>
+<meta charset=utf-8>
+</head>
+<body lang=bat-smg><!-- bad extlang -->
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/attributes/lang/xmllang-different-value-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/attributes/lang/xmllang-different-value-novalid.html
new file mode 100644
index 00000000000..8e9f82fe515
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/attributes/lang/xmllang-different-value-novalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html xml:lang="en" lang="fr">
+<head>
+<meta charset=utf-8>
+<title>When "xml:lang" is specified, the element must also have "lang" present with the same value</title>
+</head>
+<body>
+<p></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/attributes/lang/xmllang-only-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/attributes/lang/xmllang-only-novalid.html
new file mode 100644
index 00000000000..7f4571ef12e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/attributes/lang/xmllang-only-novalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html xml:lang="en">
+<head>
+<meta charset=utf-8>
+<title>When "xml:lang" is specified, the element must also have "lang" present with the same value</title>
+</head>
+<body>
+<p></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/attributes/lang/xmllang-same-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/attributes/lang/xmllang-same-isvalid.html
new file mode 100644
index 00000000000..71418a5f623
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/attributes/lang/xmllang-same-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html xml:lang="en" lang="en">
+<head>
+<meta charset=utf-8>
+<title>When "xml:lang" is specified, the element must also have "lang" present with the same value</title>
+</head>
+<body>
+<p></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/attributes/role/unrecognized-role-name-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/attributes/role/unrecognized-role-name-novalid.html
new file mode 100644
index 00000000000..b7b7f726b8c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/attributes/role/unrecognized-role-name-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>The attribute value MUST allow a token list as the value</title>
+<input type=checkbox aria-checked=true role="switch menuitemcheckbox checkbox input">
+<!-- "switch" & "input" are unrecognized; "checkbox" is superfluous -->
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/attributes/spellcheck/value-bad-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/attributes/spellcheck/value-bad-novalid.html
new file mode 100644
index 00000000000..6cbf57e7872
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/attributes/spellcheck/value-bad-novalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>spellcheck="badvalue"</title>
+</head>
+<body>
+<p spellcheck="badvalue"></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/attributes/spellcheck/value-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/attributes/spellcheck/value-isvalid.html
new file mode 100644
index 00000000000..2ce71c581b2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/attributes/spellcheck/value-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>valid spellcheck</title>
+</head>
+<body>
+<p spellcheck="true"></p>
+<p spellcheck="false"></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/download-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/download-isvalid.html
new file mode 100644
index 00000000000..0d1fe6f1e18
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/download-isvalid.html
@@ -0,0 +1,5 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>valid download</title>
+<a download>foo</a><!-- empty download -->
+<a download=baz>foo</a><!-- arbitrary value for download -->
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href-isvalid.html
new file mode 100644
index 00000000000..504ec6e37be
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href-isvalid.html
@@ -0,0 +1,92 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href</title>
+<a href="file:///"></a><!-- scheme-file-slash-slash-slash-only -->
+<a href="http://a:@www.example.com"></a><!-- userinfo-password-empty -->
+<a href="foo://///////"></a><!-- scheme-private-path-leading-slashes-only -->
+<a href="file://abc|/foo/bar"></a><!-- scheme-file-slash-slash-abc-bar -->
+<a href="/a/b/c"></a><!-- path-simple-relative -->
+<a href="http://example.com/你好你好"></a><!-- path-unicode-han -->
+<a href="/a/%2f/c"></a><!-- path-percent-encoded-slash-plus-slashes-relative -->
+<a href="http://f:/c"></a><!-- port-none-but-colon -->
+<a href="http://example.com/foo%41%7a"></a><!-- path-percent-encoded-multiple -->
+<a href="http://192.168.0.257/"></a><!-- host-IP-address-broken -->
+<a href="madeupscheme:example.com/"></a><!-- scheme-private-no-slash -->
+<a href="?"></a><!-- query-empty-no-path-relative -->
+<a href="http://example.com/%20foo"></a><!-- path-percent-encoded-space -->
+<a href="mailto:/example.com/"></a><!-- scheme-mailto-single-slash -->
+<a href="::"></a><!-- path-leading-colon-colon-relative -->
+<a href="http://example.com/%3A%3a%3C%3c"></a><!-- path-percent-encoded-mixed-case -->
+<a href="http://user:pass@foo:21/bar;par?b#c"></a><!-- userinfo -->
+<a href="ws:/example.com/"></a><!-- scheme-ws-single-slash -->
+<a href="foo://"></a><!-- scheme-private-slash-slash -->
+<a href="#"></a><!-- fragment-empty-hash-only-no-path-relative -->
+<a href="http://f:00000000000000/c"></a><!-- port-00000000000000 -->
+<a href="foo:////://///"></a><!-- scheme-private-path-leading-slashes-colon-slashes -->
+<a href=":23"></a><!-- path-leading-colon-number-relative -->
+<a href="foo:/"></a><!-- scheme-private-slash -->
+<a href="http://💩"></a><!-- host-is-pile-of-poo -->
+<a href="file:test"></a><!-- scheme-file-no-slash -->
+<a href="file://C|/foo/bar"></a><!-- scheme-file-slash-slash-c-bar -->
+<a href="#/"></a><!-- fragment-slash-relative -->
+<a href="http://192.0x00A80001"></a><!-- host-192.0x00A80001 -->
+<a href="foo.com"></a><!-- scheme-none-relative -->
+<a href="http💩//:foo"></a><!-- path-contains-pile-of-poo -->
+<a href="File://foo/bar.html"></a><!-- scheme-file-uppercase -->
+<a href=":/"></a><!-- path-leading-colon-slash-relative -->
+<a href="http://www.foo。bar.com"></a><!-- host-exotic-dot -->
+<a href="http://GOO​⁠goo.com"></a><!-- host-exotic-whitespace -->
+<a href="file:///foo/bar.txt"></a><!-- scheme-file-host-empty -->
+<a href="javascript:/example.com/"></a><!-- scheme-javascript-single-slash -->
+<a href="gopher:/example.com/"></a><!-- scheme-gopher-single-slash -->
+<a href="ftps:example.com/"></a><!-- scheme-ftps-no-slash -->
+<a href="file://server/foo/bar"></a><!-- scheme-file-host-included -->
+<a href="http://example.com/foo%00"></a><!-- path-percent-encoded-u0000 -->
+<a href="a:foo.com"></a><!-- scheme-private -->
+<a href=":"></a><!-- path-colon-relative -->
+<a href="http://:b@www.example.com"></a><!-- userinfo-user-empty -->
+<a href="file:/"></a><!-- scheme-file-slash-only -->
+<a href="wss:example.com/"></a><!-- scheme-wss-no-slash -->
+<a href="::23"></a><!-- path-colon-colon-number-relative -->
+<a href="/a%2fc"></a><!-- path-percent-encoded-slash-relative -->
+<a href="http://a:b@c:29/d"></a><!-- userinfo-host-port-path -->
+<a href="gopher:example.com/"></a><!-- scheme-gopher-no-slash -->
+<a href="madeupscheme:/example.com/"></a><!-- scheme-private-single-slash -->
+<a href="mailto:example.com/"></a><!-- scheme-mailto-no-slash -->
+<a href="http://%25DOMAIN:foobar@foodomain.com"></a><!-- userinfo-username-contains-percent-encoded -->
+<a href="/:23"></a><!-- path-slash-colon-number-relative -->
+<a href="foo://///////bar.com/"></a><!-- scheme-private-path-leading-slashes-chars -->
+<a href="http://[2001::1]:80"></a><!-- host-ipv6-port -->
+<a href="data:text/plain,foo"></a><!-- scheme-data-no-slash -->
+<a href="http://example.com/foo/%2e"></a><!-- path-percent-encoded-dot -->
+<a href="file:/example.com/"></a><!-- scheme-file-single-slash -->
+<a href="http://example.com/©zbar"></a><!-- path-non-ascii -->
+<a href="http://example.com//foo"></a><!-- path-uFEFF -->
+<a href="wss:/example.com/"></a><!-- scheme-wss-single-slash -->
+<a href="http://foo/abcd#foo?bar"></a><!-- fragment-contains-question-mark -->
+<a href=":#"></a><!-- path-leading-colon-hash-relative -->
+<a href="http://example.com/foo%91"></a><!-- path-percent-encoded-u0091 -->
+<a href="c:/foo"></a><!-- scheme-private-single-letter -->
+<a href=":foo.com"></a><!-- path-leading-colon-chars-relative -->
+<a href="http://你好你好"></a><!-- host-idn-unicode-han -->
+<a href="http://example.com/foo#💩"></a><!-- fragment-contains-pile-of-poo -->
+<a href="file:"></a><!-- scheme-file-scheme-only -->
+<a href="#β"></a><!-- fragment-non-ascii-relative -->
+<a href="foo:/bar.com/"></a><!-- scheme-private-path -->
+<a href="http://f:0/c"></a><!-- port-0 -->
+<a href="#;?"></a><!-- fragment-semicolon-question-mark-relative -->
+<a href="http://Go.com"></a><!-- host-fullwidth -->
+<a href="http://@www.example.com"></a><!-- userinfo-empty -->
+<a href="http://example.com/‮/foo/‭/bar"></a><!-- path-u202E-u202D -->
+<a href="http://[2001::1]"></a><!-- host-ipv6 -->
+<a href="💩http://foo"></a><!-- path-starts-with-pile-of-poo -->
+<a href="http://foo/abcd?efgh?ijkl"></a><!-- query-contains-question-mark -->
+<a href="//foo/bar"></a><!-- scheme-schemeless-relative -->
+<a href="ftps:/example.com/"></a><!-- scheme-ftps-single-slash -->
+<a href="http://foo.com:b@d/"></a><!-- userinfo-username-non-alpha -->
+<a href=":a"></a><!-- path-leading-colon-letter-relative -->
+<a href="/"></a><!-- path-slash-only-relative -->
+<a href="http://example.com/foo?💩"></a><!-- query-contains-pile-of-poo -->
+<a href="http://f:00000000000000000000080/c"></a><!-- port-00000000000000000000080 -->
+<a href="file://"></a><!-- scheme-file-slash-slash-only -->
+<a href=""></a><!-- empty-href -->
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/fragment-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/fragment-backslash-novalid.html
new file mode 100644
index 00000000000..0bcbffd205e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/fragment-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: fragment-backslash</title>
+<a href="#\"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/fragment-contains-hash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/fragment-contains-hash-novalid.html
new file mode 100644
index 00000000000..5810a3d8e73
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/fragment-contains-hash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: fragment-contains-hash</title>
+<a href="http://foo/path#f#g"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/fragment-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/fragment-leading-space-novalid.html
new file mode 100644
index 00000000000..f1c73cbb7c9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/fragment-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: fragment-leading-space</title>
+<a href="http://f:21/b# e"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-cr-novalid.html
new file mode 100644
index 00000000000..8d7d4d8e492
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-cr</title>
+<a href="http://example. org"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-double-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-double-percent-encoded-novalid.html
new file mode 100644
index 00000000000..20914774bc3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-double-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-double-percent-encoded</title>
+<a href="http://%41.com"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-double-percent-encoded-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-double-percent-encoded-percent-encoded-novalid.html
new file mode 100644
index 00000000000..28ede588d83
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-double-percent-encoded-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-double-percent-encoded-percent-encoded</title>
+<a href="http://%ef%bc%85%ef%bc%94%ef%bc%91.com"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-empty-novalid.html
new file mode 100644
index 00000000000..cdd21ebff83
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-empty</title>
+<a href="http://"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-empty-userinfo-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-empty-userinfo-empty-novalid.html
new file mode 100644
index 00000000000..c4bcebfc9c0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-empty-userinfo-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-empty-userinfo-empty</title>
+<a href="http://@/www.example.com"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-empty-with-userinfo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-empty-with-userinfo-novalid.html
new file mode 100644
index 00000000000..33305eda818
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-empty-with-userinfo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-empty-with-userinfo</title>
+<a href="http://user:pass@/"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-hostname-in-brackets-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-hostname-in-brackets-novalid.html
new file mode 100644
index 00000000000..8e99033b28a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-hostname-in-brackets-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-hostname-in-brackets</title>
+<a href="http://[www.google.com]/"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-invalid-unicode-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-invalid-unicode-novalid.html
new file mode 100644
index 00000000000..2efec483058
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-invalid-unicode-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-invalid-unicode</title>
+<a href="http://﷐zyx.com"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-invalid-unicode-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-invalid-unicode-percent-encoded-novalid.html
new file mode 100644
index 00000000000..faf12df1904
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-invalid-unicode-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-invalid-unicode-percent-encoded</title>
+<a href="http://%ef%b7%90zyx.com"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-newline-novalid.html
new file mode 100644
index 00000000000..20a24039bf5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-newline</title>
+<a href="http://example.
+org"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-space-novalid.html
new file mode 100644
index 00000000000..28fbf6839c7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-space</title>
+<a href="http://example .org"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-square-brackets-port-contains-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-square-brackets-port-contains-colon-novalid.html
new file mode 100644
index 00000000000..2032854dc37
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-square-brackets-port-contains-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-square-brackets-port-contains-colon</title>
+<a href="http://[1::2]:3:4"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-tab-novalid.html
new file mode 100644
index 00000000000..0b08104983c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-tab</title>
+<a href="http://example .org"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-u0000-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-u0000-percent-encoded-novalid.html
new file mode 100644
index 00000000000..fefaeb29c84
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-u0000-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-u0000-percent-encoded</title>
+<a href="http://%00.com"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-u0000-percent-encoded-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-u0000-percent-encoded-percent-encoded-novalid.html
new file mode 100644
index 00000000000..91bca31a02f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/host-u0000-percent-encoded-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-u0000-percent-encoded-percent-encoded</title>
+<a href="http://%ef%bc%85%ef%bc%90%ef%bc%90.com"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/path-bare-percent-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/path-bare-percent-sign-novalid.html
new file mode 100644
index 00000000000..d473c10fce0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/path-bare-percent-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: path-bare-percent-sign</title>
+<a href="http://example.com/foo%"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/path-contains-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/path-contains-space-novalid.html
new file mode 100644
index 00000000000..2084b1f258f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/path-contains-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: path-contains-space</title>
+<a href="/a/ /c"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/path-leading-backslash-at-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/path-leading-backslash-at-sign-novalid.html
new file mode 100644
index 00000000000..5e3bad4e2a0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/path-leading-backslash-at-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: path-leading-backslash-at-sign</title>
+<a href="http://foo.com/\@"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/path-leading-colon-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/path-leading-colon-backslash-novalid.html
new file mode 100644
index 00000000000..c6a6de865cd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/path-leading-colon-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: path-leading-colon-backslash</title>
+<a href=":\"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/path-leading-colon-chars-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/path-leading-colon-chars-backslash-novalid.html
new file mode 100644
index 00000000000..333461a2aec
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/path-leading-colon-chars-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: path-leading-colon-chars-backslash</title>
+<a href=":foo.com\"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/path-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/path-leading-space-novalid.html
new file mode 100644
index 00000000000..a247910e493
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/path-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: path-leading-space</title>
+<a href="http://f:21/ b"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/path-percent-encoded-malformed-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/path-percent-encoded-malformed-novalid.html
new file mode 100644
index 00000000000..3547c071f32
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/path-percent-encoded-malformed-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: path-percent-encoded-malformed</title>
+<a href="http://example.com/foo/%2e%2"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/path-relative-square-brackets-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/path-relative-square-brackets-novalid.html
new file mode 100644
index 00000000000..3ca2e6da1e3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/path-relative-square-brackets-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: path-relative-square-brackets</title>
+<a href="[61:24:74]:98"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/path-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/path-tab-novalid.html
new file mode 100644
index 00000000000..6ed16e83c24
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/path-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: path-tab</title>
+<a href="http://example.com/foo bar"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/path-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/path-trailing-space-novalid.html
new file mode 100644
index 00000000000..98b950ea551
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/path-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: path-trailing-space</title>
+<a href="http://f:21/b ?"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/path-u0091-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/path-u0091-novalid.html
new file mode 100644
index 00000000000..9a5f8af70e6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/path-u0091-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: path-u0091</title>
+<a href="http://example.com/foo‘"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/port-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/port-cr-novalid.html
new file mode 100644
index 00000000000..beef30828a5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/port-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: port-cr</title>
+<a href="http://f: /c"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/port-leading-colon-bracket-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/port-leading-colon-bracket-colon-novalid.html
new file mode 100644
index 00000000000..9d5839c7a04
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/port-leading-colon-bracket-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: port-leading-colon-bracket-colon</title>
+<a href="http://2001::1]:80"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/port-leading-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/port-leading-colon-novalid.html
new file mode 100644
index 00000000000..b5c692d8a99
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/port-leading-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: port-leading-colon</title>
+<a href="http://2001::1"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/port-leading-dash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/port-leading-dash-novalid.html
new file mode 100644
index 00000000000..1a47b2e8b96
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/port-leading-dash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: port-leading-dash</title>
+<a href="http://foo:-80/"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/port-multiple-letters-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/port-multiple-letters-novalid.html
new file mode 100644
index 00000000000..47d9fd856ff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/port-multiple-letters-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: port-multiple-letters</title>
+<a href="http://f:fifty-two/c"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/port-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/port-newline-novalid.html
new file mode 100644
index 00000000000..5b1d95d5c5c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/port-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: port-newline</title>
+<a href="http://f:
+/c"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/port-single-letter-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/port-single-letter-novalid.html
new file mode 100644
index 00000000000..9c289ff93e6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/port-single-letter-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: port-single-letter</title>
+<a href="http://f:b/c"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/port-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/port-space-novalid.html
new file mode 100644
index 00000000000..219c7345ad8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/port-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: port-space</title>
+<a href="http://f: /c"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/port-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/port-tab-novalid.html
new file mode 100644
index 00000000000..266dc9f222e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/port-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: port-tab</title>
+<a href="http://f: /c"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/query-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/query-leading-space-novalid.html
new file mode 100644
index 00000000000..d786b5896a1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/query-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: query-leading-space</title>
+<a href="http://f:21/b? d"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/query-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/query-trailing-space-novalid.html
new file mode 100644
index 00000000000..7754c45a26e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/query-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: query-trailing-space</title>
+<a href="http://f:21/b?d #"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-data-contains-fragment-haswarn.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-data-contains-fragment-haswarn.html
new file mode 100644
index 00000000000..069e6ab3899
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-data-contains-fragment-haswarn.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>data:text/html,test#test warning: scheme-data-contains-fragment</title>
+<a href="data:text/html,test#test"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-data-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-data-single-slash-novalid.html
new file mode 100644
index 00000000000..8474eed4b68
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-data-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-data-single-slash</title>
+<a href="data:/example.com/"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-file-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-file-backslash-novalid.html
new file mode 100644
index 00000000000..76564e13b24
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-file-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-file-backslash</title>
+<a href="file:c:\foo\bar.html"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-file-single-slash-c-bar-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-file-single-slash-c-bar-novalid.html
new file mode 100644
index 00000000000..fecd0b75339
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-file-single-slash-c-bar-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-file-single-slash-c-bar</title>
+<a href="file:/C|/foo/bar"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-file-triple-slash-c-bar-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-file-triple-slash-c-bar-novalid.html
new file mode 100644
index 00000000000..bf05a0bfa1e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-file-triple-slash-c-bar-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-file-triple-slash-c-bar</title>
+<a href="file:///C|/foo/bar"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-ftp-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-ftp-no-slash-novalid.html
new file mode 100644
index 00000000000..52a9131f0cc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-ftp-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-ftp-no-slash</title>
+<a href="ftp:example.com/"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-ftp-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-ftp-single-slash-novalid.html
new file mode 100644
index 00000000000..a885cdf3322
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-ftp-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-ftp-single-slash</title>
+<a href="ftp:/example.com/"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-http-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-http-backslash-novalid.html
new file mode 100644
index 00000000000..90bf03e8f71
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-http-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-http-backslash</title>
+<a href="http:\\foo.com\"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-http-no-slash-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-http-no-slash-colon-novalid.html
new file mode 100644
index 00000000000..4c9df61456e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-http-no-slash-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-http-no-slash-colon</title>
+<a href="http::@c:29"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-http-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-http-no-slash-novalid.html
new file mode 100644
index 00000000000..6797c6be38c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-http-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-http-no-slash</title>
+<a href="http:foo.com"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-http-no-slash-square-bracket-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-http-no-slash-square-bracket-novalid.html
new file mode 100644
index 00000000000..3f3acb11d54
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-http-no-slash-square-bracket-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-http-no-slash-square-bracket</title>
+<a href="http:[61:27]/:foo"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-http-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-http-single-slash-novalid.html
new file mode 100644
index 00000000000..e88638d1373
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-http-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-http-single-slash</title>
+<a href="http:/example.com/"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-https-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-https-no-slash-novalid.html
new file mode 100644
index 00000000000..40325a5c305
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-https-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-https-no-slash</title>
+<a href="https:example.com/"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-https-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-https-single-slash-novalid.html
new file mode 100644
index 00000000000..391c317a11f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-https-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-https-single-slash</title>
+<a href="https:/example.com/"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-javascript-no-slash-malformed-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-javascript-no-slash-malformed-novalid.html
new file mode 100644
index 00000000000..e818ba76b54
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-javascript-no-slash-malformed-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-javascript-no-slash-malformed</title>
+<a href="javascript:example.com/"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-trailing-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-trailing-cr-novalid.html
new file mode 100644
index 00000000000..784922f5108
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-trailing-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-trailing-cr</title>
+<a href="a: foo.com"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-trailing-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-trailing-newline-novalid.html
new file mode 100644
index 00000000000..12bbe55a706
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-trailing-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-trailing-newline</title>
+<a href="a:
+foo.com"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-trailing-space-novalid.html
new file mode 100644
index 00000000000..975a72eb89c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-trailing-space</title>
+<a href="a: foo.com"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-trailing-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-trailing-tab-novalid.html
new file mode 100644
index 00000000000..38a4e338d12
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/scheme-trailing-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-trailing-tab</title>
+<a href="a: foo.com"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/userinfo-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/userinfo-backslash-novalid.html
new file mode 100644
index 00000000000..c147fea4984
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/userinfo-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: userinfo-backslash</title>
+<a href="http://a\b:c\d@foo.com"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/userinfo-password-bad-chars-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/userinfo-password-bad-chars-novalid.html
new file mode 100644
index 00000000000..6f344e19a42
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/userinfo-password-bad-chars-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: userinfo-password-bad-chars</title>
+<a href="http://&a:foo(b]c@d:2/"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/userinfo-password-contains-pile-of-poo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/userinfo-password-contains-pile-of-poo-novalid.html
new file mode 100644
index 00000000000..26add769898
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/userinfo-password-contains-pile-of-poo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: userinfo-password-contains-pile-of-poo</title>
+<a href="http://foo:💩@example.com"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/userinfo-username-contains-at-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/userinfo-username-contains-at-sign-novalid.html
new file mode 100644
index 00000000000..a7c56342bf8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/userinfo-username-contains-at-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: userinfo-username-contains-at-sign</title>
+<a href="http://::@c@d:2"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/userinfo-username-contains-pile-of-poo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/userinfo-username-contains-pile-of-poo-novalid.html
new file mode 100644
index 00000000000..6571b3846ad
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/href/userinfo-username-contains-pile-of-poo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: userinfo-username-contains-pile-of-poo</title>
+<a href="http://💩:foo@example.com"></a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/media-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/media-novalid.html
new file mode 100644
index 00000000000..756ab76420f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/media-novalid.html
@@ -0,0 +1,4 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>anchor element with "media" attribute</title>
+<a media=all>foo</a>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/model-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/model-isvalid.html
new file mode 100644
index 00000000000..4704893e2c7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/model-isvalid.html
@@ -0,0 +1,4 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>valid anchor element</title>
+<div><a><p>foo</p></a></div><!-- with flow content and flow parent -->
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/model-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/model-novalid.html
new file mode 100644
index 00000000000..86bcdf3fc08
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/model-novalid.html
@@ -0,0 +1,4 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>anchor with flow content and phrasing parent</title>
+<span><a><p>foo</p></a></span>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/name-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/name-empty-novalid.html
new file mode 100644
index 00000000000..21eec58c10e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/a/name-empty-novalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>invalid empty value for a/@name</title>
+<meta charset=utf-8>
+</head>
+<body>
+<a name=''></a>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/abbr/model-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/abbr/model-isvalid.html
new file mode 100644
index 00000000000..59518af2882
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/abbr/model-isvalid.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;abbr&gt;</title>
+</head>
+<body>
+ <!-- is structured inline -->
+ <p><abbr class="class" lang="en" title=''>text</abbr></p>
+
+ <!-- is strictly inline -->
+ <p><dfn><abbr title="text1" class="class" lang="en">text</abbr></dfn></p>
+
+ <!-- can be empty -->
+ <p>text <abbr title=''></abbr></p>
+ <p>text <dfn><abbr title=''></abbr></dfn></p>
+
+ <!-- can contain interactive -->
+ <p><abbr title=''><a>text</a></abbr></p>
+ <p><dfn><abbr title=''><a>text</a></abbr></dfn></p>
+
+ <!-- cannot contain structured inline -->
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/abbr/model-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/abbr/model-novalid.html
new file mode 100644
index 00000000000..924c98ea30d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/abbr/model-novalid.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;abbr&gt;</title>
+</head>
+<body>
+ <!-- not a block -->
+ <abbr>text</abbr>
+
+ <!-- cannot contain structured inline -->
+ <p><abbr><ul><li>text</li></ul></abbr></p>
+
+ <!-- cannot contain interactive if parent forbids interactive -->
+ <p><a><abbr><a>text</a></abbr></a></p>
+ <p><a><dfn><abbr><a>text</a></abbr></dfn></a></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/address/model-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/address/model-isvalid.html
new file mode 100644
index 00000000000..94934bba1f8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/address/model-isvalid.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;address&gt;</title>
+</head>
+<body>
+ <!-- is block -->
+ <address class="class" id="id" lang="en">text</address>
+
+ <!-- can contain interactive -->
+ <address><a>text</a></address>
+
+ <!-- cannot contain structured inline -->
+ <address>text <em>elem</em></address>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/address/model-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/address/model-novalid.html
new file mode 100644
index 00000000000..3c4575944fb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/address/model-novalid.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;address&gt;</title>
+</head>
+<body>
+ <!-- is block -->
+ <address class="class" id="id" lang="en">text</address>
+
+ <!-- can contain interactive -->
+ <address><a>text</a></address>
+
+ <!-- cannot contain address inline -->
+ <address>text <address>elem</address></address>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/download-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/download-isvalid.html
new file mode 100644
index 00000000000..12a881fc6eb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/download-isvalid.html
@@ -0,0 +1,5 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>valid download</title>
+<map name=bar><area download>foo</map><!-- empty download -->
+<map name=bar><area download=baz>foo</map><!-- arbitrary value for download -->
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href-empty-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href-empty-isvalid.html
new file mode 100644
index 00000000000..06fd9ac77c7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href-empty-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>empty href is valid</title>
+<map name=foo><area href="" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href-isvalid.html
new file mode 100644
index 00000000000..ea068dccf96
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href-isvalid.html
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href</title>
+<map name=foo><area href="file:///" alt></map><!-- scheme-file-slash-slash-slash-only -->
+<map name=foo><area href="http://a:@www.example.com" alt></map><!-- userinfo-password-empty -->
+<map name=foo><area href="foo://///////" alt></map><!-- scheme-private-path-leading-slashes-only -->
+<map name=foo><area href="file://abc|/foo/bar" alt></map><!-- scheme-file-slash-slash-abc-bar -->
+<map name=foo><area href="/a/b/c" alt></map><!-- path-simple-relative -->
+<map name=foo><area href="http://example.com/你好你好" alt></map><!-- path-unicode-han -->
+<map name=foo><area href="/a/%2f/c" alt></map><!-- path-percent-encoded-slash-plus-slashes-relative -->
+<map name=foo><area href="http://f:/c" alt></map><!-- port-none-but-colon -->
+<map name=foo><area href="http://example.com/foo%41%7a" alt></map><!-- path-percent-encoded-multiple -->
+<map name=foo><area href="http://192.168.0.257/" alt></map><!-- host-IP-address-broken -->
+<map name=foo><area href="madeupscheme:example.com/" alt></map><!-- scheme-private-no-slash -->
+<map name=foo><area href="?" alt></map><!-- query-empty-no-path-relative -->
+<map name=foo><area href="http://example.com/%20foo" alt></map><!-- path-percent-encoded-space -->
+<map name=foo><area href="mailto:/example.com/" alt></map><!-- scheme-mailto-single-slash -->
+<map name=foo><area href="::" alt></map><!-- path-leading-colon-colon-relative -->
+<map name=foo><area href="http://example.com/%3A%3a%3C%3c" alt></map><!-- path-percent-encoded-mixed-case -->
+<map name=foo><area href="http://user:pass@foo:21/bar;par?b#c" alt></map><!-- userinfo -->
+<map name=foo><area href="ws:/example.com/" alt></map><!-- scheme-ws-single-slash -->
+<map name=foo><area href="foo://" alt></map><!-- scheme-private-slash-slash -->
+<map name=foo><area href="#" alt></map><!-- fragment-empty-hash-only-no-path-relative -->
+<map name=foo><area href="http://f:00000000000000/c" alt></map><!-- port-00000000000000 -->
+<map name=foo><area href="foo:////://///" alt></map><!-- scheme-private-path-leading-slashes-colon-slashes -->
+<map name=foo><area href=":23" alt></map><!-- path-leading-colon-number-relative -->
+<map name=foo><area href="foo:/" alt></map><!-- scheme-private-slash -->
+<map name=foo><area href="http://💩" alt></map><!-- host-is-pile-of-poo -->
+<map name=foo><area href="file:test" alt></map><!-- scheme-file-no-slash -->
+<map name=foo><area href="file://C|/foo/bar" alt></map><!-- scheme-file-slash-slash-c-bar -->
+<map name=foo><area href="#/" alt></map><!-- fragment-slash-relative -->
+<map name=foo><area href="http://192.0x00A80001" alt></map><!-- host-192.0x00A80001 -->
+<map name=foo><area href="foo.com" alt></map><!-- scheme-none-relative -->
+<map name=foo><area href="http💩//:foo" alt></map><!-- path-contains-pile-of-poo -->
+<map name=foo><area href="File://foo/bar.html" alt></map><!-- scheme-file-uppercase -->
+<map name=foo><area href=":/" alt></map><!-- path-leading-colon-slash-relative -->
+<map name=foo><area href="http://www.foo。bar.com" alt></map><!-- host-exotic-dot -->
+<map name=foo><area href="http://GOO​⁠goo.com" alt></map><!-- host-exotic-whitespace -->
+<map name=foo><area href="file:///foo/bar.txt" alt></map><!-- scheme-file-host-empty -->
+<map name=foo><area href="javascript:/example.com/" alt></map><!-- scheme-javascript-single-slash -->
+<map name=foo><area href="gopher:/example.com/" alt></map><!-- scheme-gopher-single-slash -->
+<map name=foo><area href="ftps:example.com/" alt></map><!-- scheme-ftps-no-slash -->
+<map name=foo><area href="file://server/foo/bar" alt></map><!-- scheme-file-host-included -->
+<map name=foo><area href="http://example.com/foo%00" alt></map><!-- path-percent-encoded-u0000 -->
+<map name=foo><area href="a:foo.com" alt></map><!-- scheme-private -->
+<map name=foo><area href=":" alt></map><!-- path-colon-relative -->
+<map name=foo><area href="http://:b@www.example.com" alt></map><!-- userinfo-user-empty -->
+<map name=foo><area href="file:/" alt></map><!-- scheme-file-slash-only -->
+<map name=foo><area href="wss:example.com/" alt></map><!-- scheme-wss-no-slash -->
+<map name=foo><area href="::23" alt></map><!-- path-colon-colon-number-relative -->
+<map name=foo><area href="/a%2fc" alt></map><!-- path-percent-encoded-slash-relative -->
+<map name=foo><area href="http://a:b@c:29/d" alt></map><!-- userinfo-host-port-path -->
+<map name=foo><area href="gopher:example.com/" alt></map><!-- scheme-gopher-no-slash -->
+<map name=foo><area href="madeupscheme:/example.com/" alt></map><!-- scheme-private-single-slash -->
+<map name=foo><area href="mailto:example.com/" alt></map><!-- scheme-mailto-no-slash -->
+<map name=foo><area href="http://%25DOMAIN:foobar@foodomain.com" alt></map><!-- userinfo-username-contains-percent-encoded -->
+<map name=foo><area href="/:23" alt></map><!-- path-slash-colon-number-relative -->
+<map name=foo><area href="foo://///////bar.com/" alt></map><!-- scheme-private-path-leading-slashes-chars -->
+<map name=foo><area href="http://[2001::1]:80" alt></map><!-- host-ipv6-port -->
+<map name=foo><area href="data:text/plain,foo" alt></map><!-- scheme-data-no-slash -->
+<map name=foo><area href="http://example.com/foo/%2e" alt></map><!-- path-percent-encoded-dot -->
+<map name=foo><area href="file:/example.com/" alt></map><!-- scheme-file-single-slash -->
+<map name=foo><area href="http://example.com/©zbar" alt></map><!-- path-non-ascii -->
+<map name=foo><area href="http://example.com//foo" alt></map><!-- path-uFEFF -->
+<map name=foo><area href="wss:/example.com/" alt></map><!-- scheme-wss-single-slash -->
+<map name=foo><area href="http://foo/abcd#foo?bar" alt></map><!-- fragment-contains-question-mark -->
+<map name=foo><area href=":#" alt></map><!-- path-leading-colon-hash-relative -->
+<map name=foo><area href="http://example.com/foo%91" alt></map><!-- path-percent-encoded-u0091 -->
+<map name=foo><area href="c:/foo" alt></map><!-- scheme-private-single-letter -->
+<map name=foo><area href=":foo.com" alt></map><!-- path-leading-colon-chars-relative -->
+<map name=foo><area href="http://你好你好" alt></map><!-- host-idn-unicode-han -->
+<map name=foo><area href="http://example.com/foo#💩" alt></map><!-- fragment-contains-pile-of-poo -->
+<map name=foo><area href="file:" alt></map><!-- scheme-file-scheme-only -->
+<map name=foo><area href="#β" alt></map><!-- fragment-non-ascii-relative -->
+<map name=foo><area href="foo:/bar.com/" alt></map><!-- scheme-private-path -->
+<map name=foo><area href="http://f:0/c" alt></map><!-- port-0 -->
+<map name=foo><area href="#;?" alt></map><!-- fragment-semicolon-question-mark-relative -->
+<map name=foo><area href="http://Go.com" alt></map><!-- host-fullwidth -->
+<map name=foo><area href="http://@www.example.com" alt></map><!-- userinfo-empty -->
+<map name=foo><area href="http://example.com/‮/foo/‭/bar" alt></map><!-- path-u202E-u202D -->
+<map name=foo><area href="http://[2001::1]" alt></map><!-- host-ipv6 -->
+<map name=foo><area href="💩http://foo" alt></map><!-- path-starts-with-pile-of-poo -->
+<map name=foo><area href="http://foo/abcd?efgh?ijkl" alt></map><!-- query-contains-question-mark -->
+<map name=foo><area href="//foo/bar" alt></map><!-- scheme-schemeless-relative -->
+<map name=foo><area href="ftps:/example.com/" alt></map><!-- scheme-ftps-single-slash -->
+<map name=foo><area href="http://foo.com:b@d/" alt></map><!-- userinfo-username-non-alpha -->
+<map name=foo><area href=":a" alt></map><!-- path-leading-colon-letter-relative -->
+<map name=foo><area href="/" alt></map><!-- path-slash-only-relative -->
+<map name=foo><area href="http://example.com/foo?💩" alt></map><!-- query-contains-pile-of-poo -->
+<map name=foo><area href="http://f:00000000000000000000080/c" alt></map><!-- port-00000000000000000000080 -->
+<map name=foo><area href="file://" alt></map><!-- scheme-file-slash-slash-only -->
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/fragment-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/fragment-backslash-novalid.html
new file mode 100644
index 00000000000..2c6df4076c5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/fragment-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: fragment-backslash</title>
+<map name=foo><area href="#\" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/fragment-contains-hash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/fragment-contains-hash-novalid.html
new file mode 100644
index 00000000000..6e785fcf708
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/fragment-contains-hash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: fragment-contains-hash</title>
+<map name=foo><area href="http://foo/path#f#g" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/fragment-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/fragment-leading-space-novalid.html
new file mode 100644
index 00000000000..6d361df80cd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/fragment-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: fragment-leading-space</title>
+<map name=foo><area href="http://f:21/b# e" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-cr-novalid.html
new file mode 100644
index 00000000000..f5d426039df
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-cr</title>
+<map name=foo><area href="http://example. org" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-double-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-double-percent-encoded-novalid.html
new file mode 100644
index 00000000000..b4231d3fcb9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-double-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-double-percent-encoded</title>
+<map name=foo><area href="http://%41.com" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-double-percent-encoded-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-double-percent-encoded-percent-encoded-novalid.html
new file mode 100644
index 00000000000..98cb2ac4a3e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-double-percent-encoded-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-double-percent-encoded-percent-encoded</title>
+<map name=foo><area href="http://%ef%bc%85%ef%bc%94%ef%bc%91.com" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-empty-novalid.html
new file mode 100644
index 00000000000..22684d89dc0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-empty</title>
+<map name=foo><area href="http://" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-empty-userinfo-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-empty-userinfo-empty-novalid.html
new file mode 100644
index 00000000000..d29da936022
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-empty-userinfo-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-empty-userinfo-empty</title>
+<map name=foo><area href="http://@/www.example.com" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-empty-with-userinfo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-empty-with-userinfo-novalid.html
new file mode 100644
index 00000000000..5ca0ed76485
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-empty-with-userinfo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-empty-with-userinfo</title>
+<map name=foo><area href="http://user:pass@/" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-hostname-in-brackets-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-hostname-in-brackets-novalid.html
new file mode 100644
index 00000000000..c60734adfc3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-hostname-in-brackets-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-hostname-in-brackets</title>
+<map name=foo><area href="http://[www.google.com]/" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-invalid-unicode-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-invalid-unicode-novalid.html
new file mode 100644
index 00000000000..c7d11111968
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-invalid-unicode-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-invalid-unicode</title>
+<map name=foo><area href="http://﷐zyx.com" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-invalid-unicode-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-invalid-unicode-percent-encoded-novalid.html
new file mode 100644
index 00000000000..ef79d37f596
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-invalid-unicode-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-invalid-unicode-percent-encoded</title>
+<map name=foo><area href="http://%ef%b7%90zyx.com" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-newline-novalid.html
new file mode 100644
index 00000000000..ece26cf6ad3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-newline</title>
+<map name=foo><area href="http://example.
+org" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-space-novalid.html
new file mode 100644
index 00000000000..65a3611a457
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-space</title>
+<map name=foo><area href="http://example .org" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-square-brackets-port-contains-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-square-brackets-port-contains-colon-novalid.html
new file mode 100644
index 00000000000..b3a16395478
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-square-brackets-port-contains-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-square-brackets-port-contains-colon</title>
+<map name=foo><area href="http://[1::2]:3:4" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-tab-novalid.html
new file mode 100644
index 00000000000..cc58fb54c6a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-tab</title>
+<map name=foo><area href="http://example .org" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-u0000-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-u0000-percent-encoded-novalid.html
new file mode 100644
index 00000000000..1200b50e054
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-u0000-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-u0000-percent-encoded</title>
+<map name=foo><area href="http://%00.com" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-u0000-percent-encoded-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-u0000-percent-encoded-percent-encoded-novalid.html
new file mode 100644
index 00000000000..fc52797d4e9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/host-u0000-percent-encoded-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-u0000-percent-encoded-percent-encoded</title>
+<map name=foo><area href="http://%ef%bc%85%ef%bc%90%ef%bc%90.com" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/path-bare-percent-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/path-bare-percent-sign-novalid.html
new file mode 100644
index 00000000000..12a06504b23
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/path-bare-percent-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: path-bare-percent-sign</title>
+<map name=foo><area href="http://example.com/foo%" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/path-contains-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/path-contains-space-novalid.html
new file mode 100644
index 00000000000..ef2889cd752
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/path-contains-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: path-contains-space</title>
+<map name=foo><area href="/a/ /c" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/path-leading-backslash-at-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/path-leading-backslash-at-sign-novalid.html
new file mode 100644
index 00000000000..667e6313c9d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/path-leading-backslash-at-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: path-leading-backslash-at-sign</title>
+<map name=foo><area href="http://foo.com/\@" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/path-leading-colon-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/path-leading-colon-backslash-novalid.html
new file mode 100644
index 00000000000..7f9994a76e0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/path-leading-colon-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: path-leading-colon-backslash</title>
+<map name=foo><area href=":\" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/path-leading-colon-chars-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/path-leading-colon-chars-backslash-novalid.html
new file mode 100644
index 00000000000..7eede5dec58
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/path-leading-colon-chars-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: path-leading-colon-chars-backslash</title>
+<map name=foo><area href=":foo.com\" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/path-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/path-leading-space-novalid.html
new file mode 100644
index 00000000000..ff17389544e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/path-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: path-leading-space</title>
+<map name=foo><area href="http://f:21/ b" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/path-percent-encoded-malformed-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/path-percent-encoded-malformed-novalid.html
new file mode 100644
index 00000000000..9e5f0e8e1ae
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/path-percent-encoded-malformed-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: path-percent-encoded-malformed</title>
+<map name=foo><area href="http://example.com/foo/%2e%2" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/path-relative-square-brackets-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/path-relative-square-brackets-novalid.html
new file mode 100644
index 00000000000..69b04b4f21c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/path-relative-square-brackets-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: path-relative-square-brackets</title>
+<map name=foo><area href="[61:24:74]:98" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/path-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/path-tab-novalid.html
new file mode 100644
index 00000000000..a6f023c403d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/path-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: path-tab</title>
+<map name=foo><area href="http://example.com/foo bar" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/path-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/path-trailing-space-novalid.html
new file mode 100644
index 00000000000..65b1e02a4bb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/path-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: path-trailing-space</title>
+<map name=foo><area href="http://f:21/b ?" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/path-u0091-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/path-u0091-novalid.html
new file mode 100644
index 00000000000..aa0fcde344c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/path-u0091-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: path-u0091</title>
+<map name=foo><area href="http://example.com/foo‘" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/port-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/port-cr-novalid.html
new file mode 100644
index 00000000000..b38c7ba8fe8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/port-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: port-cr</title>
+<map name=foo><area href="http://f: /c" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/port-leading-colon-bracket-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/port-leading-colon-bracket-colon-novalid.html
new file mode 100644
index 00000000000..f6668e1518a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/port-leading-colon-bracket-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: port-leading-colon-bracket-colon</title>
+<map name=foo><area href="http://2001::1]:80" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/port-leading-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/port-leading-colon-novalid.html
new file mode 100644
index 00000000000..6de34e1adaa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/port-leading-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: port-leading-colon</title>
+<map name=foo><area href="http://2001::1" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/port-leading-dash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/port-leading-dash-novalid.html
new file mode 100644
index 00000000000..215197e7b55
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/port-leading-dash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: port-leading-dash</title>
+<map name=foo><area href="http://foo:-80/" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/port-multiple-letters-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/port-multiple-letters-novalid.html
new file mode 100644
index 00000000000..548f239273c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/port-multiple-letters-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: port-multiple-letters</title>
+<map name=foo><area href="http://f:fifty-two/c" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/port-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/port-newline-novalid.html
new file mode 100644
index 00000000000..0efb34e3be2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/port-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: port-newline</title>
+<map name=foo><area href="http://f:
+/c" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/port-single-letter-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/port-single-letter-novalid.html
new file mode 100644
index 00000000000..5efc977c0a7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/port-single-letter-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: port-single-letter</title>
+<map name=foo><area href="http://f:b/c" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/port-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/port-space-novalid.html
new file mode 100644
index 00000000000..85c7e60dbdf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/port-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: port-space</title>
+<map name=foo><area href="http://f: /c" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/port-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/port-tab-novalid.html
new file mode 100644
index 00000000000..591c3c736d9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/port-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: port-tab</title>
+<map name=foo><area href="http://f: /c" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/query-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/query-leading-space-novalid.html
new file mode 100644
index 00000000000..3843fe55385
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/query-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: query-leading-space</title>
+<map name=foo><area href="http://f:21/b? d" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/query-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/query-trailing-space-novalid.html
new file mode 100644
index 00000000000..7e2e981f8b4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/query-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: query-trailing-space</title>
+<map name=foo><area href="http://f:21/b?d #" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-data-contains-fragment-haswarn.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-data-contains-fragment-haswarn.html
new file mode 100644
index 00000000000..ba727f5339e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-data-contains-fragment-haswarn.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>href warning: scheme-data-contains-fragment</title>
+<map name=foo><area href="data:text/html,test#test" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-data-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-data-single-slash-novalid.html
new file mode 100644
index 00000000000..79ee412f8e7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-data-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-data-single-slash</title>
+<map name=foo><area href="data:/example.com/" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-file-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-file-backslash-novalid.html
new file mode 100644
index 00000000000..e21e8173d4c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-file-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-file-backslash</title>
+<map name=foo><area href="file:c:\foo\bar.html" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-file-single-slash-c-bar-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-file-single-slash-c-bar-novalid.html
new file mode 100644
index 00000000000..dbb9912cfdf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-file-single-slash-c-bar-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-file-single-slash-c-bar</title>
+<map name=foo><area href="file:/C|/foo/bar" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-file-triple-slash-c-bar-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-file-triple-slash-c-bar-novalid.html
new file mode 100644
index 00000000000..07276a244ba
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-file-triple-slash-c-bar-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-file-triple-slash-c-bar</title>
+<map name=foo><area href="file:///C|/foo/bar" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-ftp-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-ftp-no-slash-novalid.html
new file mode 100644
index 00000000000..e92a75d01a3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-ftp-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-ftp-no-slash</title>
+<map name=foo><area href="ftp:example.com/" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-ftp-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-ftp-single-slash-novalid.html
new file mode 100644
index 00000000000..180e0d27219
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-ftp-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-ftp-single-slash</title>
+<map name=foo><area href="ftp:/example.com/" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-http-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-http-backslash-novalid.html
new file mode 100644
index 00000000000..d1281c4de0d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-http-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-http-backslash</title>
+<map name=foo><area href="http:\\foo.com\" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-http-no-slash-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-http-no-slash-colon-novalid.html
new file mode 100644
index 00000000000..4986f1a2249
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-http-no-slash-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-http-no-slash-colon</title>
+<map name=foo><area href="http::@c:29" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-http-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-http-no-slash-novalid.html
new file mode 100644
index 00000000000..2d3ba5b5bfd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-http-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-http-no-slash</title>
+<map name=foo><area href="http:foo.com" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-http-no-slash-square-bracket-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-http-no-slash-square-bracket-novalid.html
new file mode 100644
index 00000000000..bc4ddc247bf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-http-no-slash-square-bracket-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-http-no-slash-square-bracket</title>
+<map name=foo><area href="http:[61:27]/:foo" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-http-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-http-single-slash-novalid.html
new file mode 100644
index 00000000000..eb2cb78f9d3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-http-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-http-single-slash</title>
+<map name=foo><area href="http:/example.com/" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-https-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-https-no-slash-novalid.html
new file mode 100644
index 00000000000..84e8a816c68
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-https-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-https-no-slash</title>
+<map name=foo><area href="https:example.com/" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-https-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-https-single-slash-novalid.html
new file mode 100644
index 00000000000..cc6ea3237ab
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-https-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-https-single-slash</title>
+<map name=foo><area href="https:/example.com/" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-javascript-no-slash-malformed-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-javascript-no-slash-malformed-novalid.html
new file mode 100644
index 00000000000..bb12e65f532
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-javascript-no-slash-malformed-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-javascript-no-slash-malformed</title>
+<map name=foo><area href="javascript:example.com/" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-trailing-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-trailing-cr-novalid.html
new file mode 100644
index 00000000000..5031456354f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-trailing-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-trailing-cr</title>
+<map name=foo><area href="a: foo.com" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-trailing-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-trailing-newline-novalid.html
new file mode 100644
index 00000000000..422c685e5bb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-trailing-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-trailing-newline</title>
+<map name=foo><area href="a:
+foo.com" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-trailing-space-novalid.html
new file mode 100644
index 00000000000..aa877fe965c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-trailing-space</title>
+<map name=foo><area href="a: foo.com" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-trailing-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-trailing-tab-novalid.html
new file mode 100644
index 00000000000..fb9055a41c3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/scheme-trailing-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-trailing-tab</title>
+<map name=foo><area href="a: foo.com" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/userinfo-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/userinfo-backslash-novalid.html
new file mode 100644
index 00000000000..9419fd0a766
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/userinfo-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: userinfo-backslash</title>
+<map name=foo><area href="http://a\b:c\d@foo.com" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/userinfo-password-bad-chars-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/userinfo-password-bad-chars-novalid.html
new file mode 100644
index 00000000000..f9d210a0641
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/userinfo-password-bad-chars-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: userinfo-password-bad-chars</title>
+<map name=foo><area href="http://&a:foo(b]c@d:2/" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/userinfo-password-contains-pile-of-poo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/userinfo-password-contains-pile-of-poo-novalid.html
new file mode 100644
index 00000000000..48131d7fb36
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/userinfo-password-contains-pile-of-poo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: userinfo-password-contains-pile-of-poo</title>
+<map name=foo><area href="http://foo:💩@example.com" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/userinfo-username-contains-at-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/userinfo-username-contains-at-sign-novalid.html
new file mode 100644
index 00000000000..6404378f37d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/userinfo-username-contains-at-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: userinfo-username-contains-at-sign</title>
+<map name=foo><area href="http://::@c@d:2" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/userinfo-username-contains-pile-of-poo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/userinfo-username-contains-pile-of-poo-novalid.html
new file mode 100644
index 00000000000..ecbd4bffbb9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/href/userinfo-username-contains-pile-of-poo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: userinfo-username-contains-pile-of-poo</title>
+<map name=foo><area href="http://💩:foo@example.com" alt></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/media-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/media-novalid.html
new file mode 100644
index 00000000000..c88391e4e67
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/media-novalid.html
@@ -0,0 +1,4 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>area element with "media" attribute</title>
+<map name=foo><area media=all></map>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/model-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/model-isvalid.html
new file mode 100644
index 00000000000..6f4504fc8f2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/model-isvalid.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;area&gt;</title>
+</head>
+<body>
+ <map id='foo' name='foo'>
+ <p>p
+ <!-- default -->
+ <area alt="text" shape="default" href='url'>
+
+ <!-- rect -->
+ <area alt="text" shape="rect" coords="-01,2,3,4" href="url">
+ <area alt="text" shape="rect" coords="1,2,3,4" href="url">
+ <area alt="text" coords="1,-24,388,45" href="url">
+ <area alt="text" coords="1,2,3,4" href="url">
+
+ <!-- circle -->
+ <area alt="text" shape="circle" coords="01,-223,32" href="url">
+ <area alt="text" shape="circle" coords="1,2,3" href="url">
+
+ <!-- poly -->
+ <area alt="text" shape="poly" coords="01,223,42,-35,94,-94" href="url">
+ <area alt="text" shape="poly" coords="01,223,42,35,94,94,003,2" href="url">
+ <area alt="text" shape="poly" coords="-1,2,3,4,5,6,7,8,9,10" href="url">
+ </p>
+ </map>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/model-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/model-novalid.html
new file mode 100644
index 00000000000..921ac4494e5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/area/model-novalid.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;area&gt;</title>
+</head>
+<body>
+ <map name="map1">
+ <!-- default has no coords -->
+ <area alt="text" shape="default" coords="1,2">
+
+ <!-- rect, circle, poly must have coords -->
+ <area alt="text" shape="rect">
+ <area alt="text" shape="circle">
+ <area alt="text" shape="poly">
+
+ <!-- rect must have four coords -->
+ <area alt="text" shape="rect" coords="1,2,3">
+ <area alt="text" shape="rect" coords=" 1 , 2 , 3 , 4 , 5, 6">
+ <area alt="text" coords="1,2,3,4,5,6">
+ <area alt="text" coords=" 1 , 2 , 3 , 4 ,">
+
+ <!-- circle must have three coords -->
+ <area alt="text" shape="circle" coords="1,2">
+ <area alt="text" shape="circle" coords=" 1 , 2 , 3 , 4 ">
+
+ <!-- poly must have coords in pairs, and at least 3 sets -->
+ <area alt="text" shape="poly" coords="1,2,3,4,5">
+ <area alt="text" shape="poly" coords="1,2,3,4,5,6,7,">
+ <area alt="text" shape="poly" coords=" 1 , 2 , 3 ,4 ,5,
+ 6 ,7 ,8, ,9 ">
+
+ <!-- coords must be int or percent, +/- allowed -->
+ <area alt="text" shape="rect" coords="1.5,2,3,4">
+ <area alt="text" shape="rect" coords="1,2px,3,4">
+ <area alt="text" shape="rect" coords="1 %,2,3,4">
+ <area alt="text" shape="rect" coords="1,- 2,3,4">
+ <area alt="text" shape="rect" coords="1, 2,+ 3,4">
+
+ <area alt="text" shape="circle" coords="1.5,2,3">
+ <area alt="text" shape="circle" coords="1,2px,3">
+ <area alt="text" shape="circle" coords="1 %,2,3">
+ <area alt="text" shape="circle" coords="1,- 2,3">
+ <area alt="text" shape="circle" coords="1, 2,+ 3">
+
+ <area alt="text" shape="poly" coords="5,6,1.5,2,3,4">
+ <area alt="text" shape="poly" coords="5,6,1,2px,3,4">
+ <area alt="text" shape="poly" coords="5,6,1 %,2,3,4">
+ <area alt="text" shape="poly" coords="5,6,1,- 2,3,4">
+ <area alt="text" shape="poly" coords="5,6,1, 2,+ 3,4">
+ </map>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/model-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/model-isvalid.html
new file mode 100644
index 00000000000..6588326bd16
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/model-isvalid.html
@@ -0,0 +1,4 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>audio with flow content and flow parent</title>
+<div><audio><p>foo</p></audio></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/model-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/model-novalid.html
new file mode 100644
index 00000000000..0c3d590c68a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/model-novalid.html
@@ -0,0 +1,4 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>audio with flow content and phrasing parent</title>
+<span><audio><p>foo</p></audio></span>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src-empty-novalid.html
new file mode 100644
index 00000000000..96deecbb685
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>empty audio src is not valid</title>
+<audio src=""></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src-isvalid.html
new file mode 100644
index 00000000000..c13d03b6178
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src-isvalid.html
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid src</title>
+<audio src="file:///"></audio><!-- scheme-file-slash-slash-slash-only -->
+<audio src="http://a:@www.example.com"></audio><!-- userinfo-password-empty -->
+<audio src="foo://///////"></audio><!-- scheme-private-path-leading-slashes-only -->
+<audio src="file://abc|/foo/bar"></audio><!-- scheme-file-slash-slash-abc-bar -->
+<audio src="/a/b/c"></audio><!-- path-simple-relative -->
+<audio src="http://example.com/你好你好"></audio><!-- path-unicode-han -->
+<audio src="/a/%2f/c"></audio><!-- path-percent-encoded-slash-plus-slashes-relative -->
+<audio src="http://f:/c"></audio><!-- port-none-but-colon -->
+<audio src="http://example.com/foo%41%7a"></audio><!-- path-percent-encoded-multiple -->
+<audio src="http://192.168.0.257/"></audio><!-- host-IP-address-broken -->
+<audio src="madeupscheme:example.com/"></audio><!-- scheme-private-no-slash -->
+<audio src="?"></audio><!-- query-empty-no-path-relative -->
+<audio src="http://example.com/%20foo"></audio><!-- path-percent-encoded-space -->
+<audio src="mailto:/example.com/"></audio><!-- scheme-mailto-single-slash -->
+<audio src="::"></audio><!-- path-leading-colon-colon-relative -->
+<audio src="http://example.com/%3A%3a%3C%3c"></audio><!-- path-percent-encoded-mixed-case -->
+<audio src="http://user:pass@foo:21/bar;par?b#c"></audio><!-- userinfo -->
+<audio src="ws:/example.com/"></audio><!-- scheme-ws-single-slash -->
+<audio src="foo://"></audio><!-- scheme-private-slash-slash -->
+<audio src="#"></audio><!-- fragment-empty-hash-only-no-path-relative -->
+<audio src="http://f:00000000000000/c"></audio><!-- port-00000000000000 -->
+<audio src="foo:////://///"></audio><!-- scheme-private-path-leading-slashes-colon-slashes -->
+<audio src=":23"></audio><!-- path-leading-colon-number-relative -->
+<audio src="foo:/"></audio><!-- scheme-private-slash -->
+<audio src="http://💩"></audio><!-- host-is-pile-of-poo -->
+<audio src="file:test"></audio><!-- scheme-file-no-slash -->
+<audio src="file://C|/foo/bar"></audio><!-- scheme-file-slash-slash-c-bar -->
+<audio src="#/"></audio><!-- fragment-slash-relative -->
+<audio src="http://192.0x00A80001"></audio><!-- host-192.0x00A80001 -->
+<audio src="foo.com"></audio><!-- scheme-none-relative -->
+<audio src="http💩//:foo"></audio><!-- path-contains-pile-of-poo -->
+<audio src="File://foo/bar.html"></audio><!-- scheme-file-uppercase -->
+<audio src=":/"></audio><!-- path-leading-colon-slash-relative -->
+<audio src="http://www.foo。bar.com"></audio><!-- host-exotic-dot -->
+<audio src="http://GOO​⁠goo.com"></audio><!-- host-exotic-whitespace -->
+<audio src="file:///foo/bar.txt"></audio><!-- scheme-file-host-empty -->
+<audio src="javascript:/example.com/"></audio><!-- scheme-javascript-single-slash -->
+<audio src="gopher:/example.com/"></audio><!-- scheme-gopher-single-slash -->
+<audio src="ftps:example.com/"></audio><!-- scheme-ftps-no-slash -->
+<audio src="file://server/foo/bar"></audio><!-- scheme-file-host-included -->
+<audio src="http://example.com/foo%00"></audio><!-- path-percent-encoded-u0000 -->
+<audio src="a:foo.com"></audio><!-- scheme-private -->
+<audio src=":"></audio><!-- path-colon-relative -->
+<audio src="http://:b@www.example.com"></audio><!-- userinfo-user-empty -->
+<audio src="file:/"></audio><!-- scheme-file-slash-only -->
+<audio src="wss:example.com/"></audio><!-- scheme-wss-no-slash -->
+<audio src="::23"></audio><!-- path-colon-colon-number-relative -->
+<audio src="/a%2fc"></audio><!-- path-percent-encoded-slash-relative -->
+<audio src="http://a:b@c:29/d"></audio><!-- userinfo-host-port-path -->
+<audio src="gopher:example.com/"></audio><!-- scheme-gopher-no-slash -->
+<audio src="madeupscheme:/example.com/"></audio><!-- scheme-private-single-slash -->
+<audio src="mailto:example.com/"></audio><!-- scheme-mailto-no-slash -->
+<audio src="http://%25DOMAIN:foobar@foodomain.com"></audio><!-- userinfo-username-contains-percent-encoded -->
+<audio src="/:23"></audio><!-- path-slash-colon-number-relative -->
+<audio src="foo://///////bar.com/"></audio><!-- scheme-private-path-leading-slashes-chars -->
+<audio src="http://[2001::1]:80"></audio><!-- host-ipv6-port -->
+<audio src="data:text/plain,foo"></audio><!-- scheme-data-no-slash -->
+<audio src="http://example.com/foo/%2e"></audio><!-- path-percent-encoded-dot -->
+<audio src="file:/example.com/"></audio><!-- scheme-file-single-slash -->
+<audio src="http://example.com/©zbar"></audio><!-- path-non-ascii -->
+<audio src="http://example.com//foo"></audio><!-- path-uFEFF -->
+<audio src="wss:/example.com/"></audio><!-- scheme-wss-single-slash -->
+<audio src="http://foo/abcd#foo?bar"></audio><!-- fragment-contains-question-mark -->
+<audio src=":#"></audio><!-- path-leading-colon-hash-relative -->
+<audio src="http://example.com/foo%91"></audio><!-- path-percent-encoded-u0091 -->
+<audio src="c:/foo"></audio><!-- scheme-private-single-letter -->
+<audio src=":foo.com"></audio><!-- path-leading-colon-chars-relative -->
+<audio src="http://你好你好"></audio><!-- host-idn-unicode-han -->
+<audio src="http://example.com/foo#💩"></audio><!-- fragment-contains-pile-of-poo -->
+<audio src="file:"></audio><!-- scheme-file-scheme-only -->
+<audio src="#β"></audio><!-- fragment-non-ascii-relative -->
+<audio src="foo:/bar.com/"></audio><!-- scheme-private-path -->
+<audio src="http://f:0/c"></audio><!-- port-0 -->
+<audio src="#;?"></audio><!-- fragment-semicolon-question-mark-relative -->
+<audio src="http://Go.com"></audio><!-- host-fullwidth -->
+<audio src="http://@www.example.com"></audio><!-- userinfo-empty -->
+<audio src="http://example.com/‮/foo/‭/bar"></audio><!-- path-u202E-u202D -->
+<audio src="http://[2001::1]"></audio><!-- host-ipv6 -->
+<audio src="💩http://foo"></audio><!-- path-starts-with-pile-of-poo -->
+<audio src="http://foo/abcd?efgh?ijkl"></audio><!-- query-contains-question-mark -->
+<audio src="//foo/bar"></audio><!-- scheme-schemeless-relative -->
+<audio src="ftps:/example.com/"></audio><!-- scheme-ftps-single-slash -->
+<audio src="http://foo.com:b@d/"></audio><!-- userinfo-username-non-alpha -->
+<audio src=":a"></audio><!-- path-leading-colon-letter-relative -->
+<audio src="/"></audio><!-- path-slash-only-relative -->
+<audio src="http://example.com/foo?💩"></audio><!-- query-contains-pile-of-poo -->
+<audio src="http://f:00000000000000000000080/c"></audio><!-- port-00000000000000000000080 -->
+<audio src="file://"></audio><!-- scheme-file-slash-slash-only -->
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src-whitespace-only-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src-whitespace-only-novalid.html
new file mode 100644
index 00000000000..73508d33447
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src-whitespace-only-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>empty audio src is not valid</title>
+<audio src="
+"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/fragment-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/fragment-backslash-novalid.html
new file mode 100644
index 00000000000..7c18367b52f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/fragment-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: fragment-backslash</title>
+<audio src="#\"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/fragment-contains-hash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/fragment-contains-hash-novalid.html
new file mode 100644
index 00000000000..aed50092d88
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/fragment-contains-hash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: fragment-contains-hash</title>
+<audio src="http://foo/path#f#g"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/fragment-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/fragment-leading-space-novalid.html
new file mode 100644
index 00000000000..98ed32230fb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/fragment-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: fragment-leading-space</title>
+<audio src="http://f:21/b# e"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-cr-novalid.html
new file mode 100644
index 00000000000..2e585b92720
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-cr</title>
+<audio src="http://example. org"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-double-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-double-percent-encoded-novalid.html
new file mode 100644
index 00000000000..4cb4a9acf58
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-double-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-double-percent-encoded</title>
+<audio src="http://%41.com"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-double-percent-encoded-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-double-percent-encoded-percent-encoded-novalid.html
new file mode 100644
index 00000000000..856db00f6bf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-double-percent-encoded-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-double-percent-encoded-percent-encoded</title>
+<audio src="http://%ef%bc%85%ef%bc%94%ef%bc%91.com"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-empty-novalid.html
new file mode 100644
index 00000000000..e10355480ed
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-empty</title>
+<audio src="http://"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-empty-userinfo-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-empty-userinfo-empty-novalid.html
new file mode 100644
index 00000000000..49b2e028c8d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-empty-userinfo-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-empty-userinfo-empty</title>
+<audio src="http://@/www.example.com"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-empty-with-userinfo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-empty-with-userinfo-novalid.html
new file mode 100644
index 00000000000..c1b63d760fe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-empty-with-userinfo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-empty-with-userinfo</title>
+<audio src="http://user:pass@/"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-hostname-in-brackets-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-hostname-in-brackets-novalid.html
new file mode 100644
index 00000000000..11a047f3763
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-hostname-in-brackets-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-hostname-in-brackets</title>
+<audio src="http://[www.google.com]/"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-invalid-unicode-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-invalid-unicode-novalid.html
new file mode 100644
index 00000000000..75195b59c7d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-invalid-unicode-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-invalid-unicode</title>
+<audio src="http://﷐zyx.com"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-invalid-unicode-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-invalid-unicode-percent-encoded-novalid.html
new file mode 100644
index 00000000000..afcc32114bc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-invalid-unicode-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-invalid-unicode-percent-encoded</title>
+<audio src="http://%ef%b7%90zyx.com"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-newline-novalid.html
new file mode 100644
index 00000000000..511ca147103
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-newline</title>
+<audio src="http://example.
+org"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-space-novalid.html
new file mode 100644
index 00000000000..b7cd4ed45de
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-space</title>
+<audio src="http://example .org"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-square-brackets-port-contains-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-square-brackets-port-contains-colon-novalid.html
new file mode 100644
index 00000000000..0455fffea73
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-square-brackets-port-contains-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-square-brackets-port-contains-colon</title>
+<audio src="http://[1::2]:3:4"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-tab-novalid.html
new file mode 100644
index 00000000000..518010071f1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-tab</title>
+<audio src="http://example .org"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-u0000-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-u0000-percent-encoded-novalid.html
new file mode 100644
index 00000000000..04fab6d158a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-u0000-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-u0000-percent-encoded</title>
+<audio src="http://%00.com"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-u0000-percent-encoded-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-u0000-percent-encoded-percent-encoded-novalid.html
new file mode 100644
index 00000000000..b9cc63cb5c7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/host-u0000-percent-encoded-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-u0000-percent-encoded-percent-encoded</title>
+<audio src="http://%ef%bc%85%ef%bc%90%ef%bc%90.com"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/path-bare-percent-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/path-bare-percent-sign-novalid.html
new file mode 100644
index 00000000000..2ee3f09377e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/path-bare-percent-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-bare-percent-sign</title>
+<audio src="http://example.com/foo%"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/path-contains-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/path-contains-space-novalid.html
new file mode 100644
index 00000000000..8def346ca0f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/path-contains-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-contains-space</title>
+<audio src="/a/ /c"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/path-leading-backslash-at-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/path-leading-backslash-at-sign-novalid.html
new file mode 100644
index 00000000000..56ee3535133
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/path-leading-backslash-at-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-leading-backslash-at-sign</title>
+<audio src="http://foo.com/\@"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/path-leading-colon-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/path-leading-colon-backslash-novalid.html
new file mode 100644
index 00000000000..edc0cbfa722
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/path-leading-colon-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-leading-colon-backslash</title>
+<audio src=":\"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/path-leading-colon-chars-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/path-leading-colon-chars-backslash-novalid.html
new file mode 100644
index 00000000000..3f6aa0319e2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/path-leading-colon-chars-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-leading-colon-chars-backslash</title>
+<audio src=":foo.com\"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/path-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/path-leading-space-novalid.html
new file mode 100644
index 00000000000..9a512c35e7a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/path-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-leading-space</title>
+<audio src="http://f:21/ b"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/path-percent-encoded-malformed-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/path-percent-encoded-malformed-novalid.html
new file mode 100644
index 00000000000..d84fd0c3bc7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/path-percent-encoded-malformed-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-percent-encoded-malformed</title>
+<audio src="http://example.com/foo/%2e%2"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/path-relative-square-brackets-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/path-relative-square-brackets-novalid.html
new file mode 100644
index 00000000000..3efbb56b3a2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/path-relative-square-brackets-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-relative-square-brackets</title>
+<audio src="[61:24:74]:98"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/path-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/path-tab-novalid.html
new file mode 100644
index 00000000000..1e368d11725
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/path-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-tab</title>
+<audio src="http://example.com/foo bar"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/path-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/path-trailing-space-novalid.html
new file mode 100644
index 00000000000..9751a76b864
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/path-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-trailing-space</title>
+<audio src="http://f:21/b ?"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/path-u0091-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/path-u0091-novalid.html
new file mode 100644
index 00000000000..453e2095fae
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/path-u0091-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-u0091</title>
+<audio src="http://example.com/foo‘"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/port-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/port-cr-novalid.html
new file mode 100644
index 00000000000..26ac72f8a5a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/port-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-cr</title>
+<audio src="http://f: /c"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/port-leading-colon-bracket-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/port-leading-colon-bracket-colon-novalid.html
new file mode 100644
index 00000000000..c8a549b4e0b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/port-leading-colon-bracket-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-leading-colon-bracket-colon</title>
+<audio src="http://2001::1]:80"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/port-leading-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/port-leading-colon-novalid.html
new file mode 100644
index 00000000000..836a94eb725
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/port-leading-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-leading-colon</title>
+<audio src="http://2001::1"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/port-leading-dash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/port-leading-dash-novalid.html
new file mode 100644
index 00000000000..822e666a767
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/port-leading-dash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-leading-dash</title>
+<audio src="http://foo:-80/"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/port-multiple-letters-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/port-multiple-letters-novalid.html
new file mode 100644
index 00000000000..55b0a0c507b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/port-multiple-letters-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-multiple-letters</title>
+<audio src="http://f:fifty-two/c"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/port-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/port-newline-novalid.html
new file mode 100644
index 00000000000..e9a34b0ee70
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/port-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-newline</title>
+<audio src="http://f:
+/c"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/port-single-letter-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/port-single-letter-novalid.html
new file mode 100644
index 00000000000..5f7f44ef320
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/port-single-letter-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-single-letter</title>
+<audio src="http://f:b/c"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/port-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/port-space-novalid.html
new file mode 100644
index 00000000000..a931754b86f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/port-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-space</title>
+<audio src="http://f: /c"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/port-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/port-tab-novalid.html
new file mode 100644
index 00000000000..80c169a686b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/port-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-tab</title>
+<audio src="http://f: /c"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/query-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/query-leading-space-novalid.html
new file mode 100644
index 00000000000..76bab5cc9af
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/query-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: query-leading-space</title>
+<audio src="http://f:21/b? d"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/query-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/query-trailing-space-novalid.html
new file mode 100644
index 00000000000..009d5044925
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/query-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: query-trailing-space</title>
+<audio src="http://f:21/b?d #"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-data-contains-fragment-haswarn.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-data-contains-fragment-haswarn.html
new file mode 100644
index 00000000000..d96f8742f43
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-data-contains-fragment-haswarn.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>data:text/html,test#test warning: scheme-data-contains-fragment</title>
+<audio src="data:text/html,test#test"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-data-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-data-single-slash-novalid.html
new file mode 100644
index 00000000000..693bd23c9b4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-data-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-data-single-slash</title>
+<audio src="data:/example.com/"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-file-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-file-backslash-novalid.html
new file mode 100644
index 00000000000..a84f17e15a6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-file-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-file-backslash</title>
+<audio src="file:c:\foo\bar.html"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-file-single-slash-c-bar-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-file-single-slash-c-bar-novalid.html
new file mode 100644
index 00000000000..473c5219fe9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-file-single-slash-c-bar-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-file-single-slash-c-bar</title>
+<audio src="file:/C|/foo/bar"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-file-triple-slash-c-bar-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-file-triple-slash-c-bar-novalid.html
new file mode 100644
index 00000000000..941f34e21e9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-file-triple-slash-c-bar-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-file-triple-slash-c-bar</title>
+<audio src="file:///C|/foo/bar"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-ftp-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-ftp-no-slash-novalid.html
new file mode 100644
index 00000000000..9798091d4c4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-ftp-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-ftp-no-slash</title>
+<audio src="ftp:example.com/"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-ftp-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-ftp-single-slash-novalid.html
new file mode 100644
index 00000000000..fa86c3a4840
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-ftp-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-ftp-single-slash</title>
+<audio src="ftp:/example.com/"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-http-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-http-backslash-novalid.html
new file mode 100644
index 00000000000..5a9d6a89f77
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-http-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-http-backslash</title>
+<audio src="http:\\foo.com\"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-http-no-slash-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-http-no-slash-colon-novalid.html
new file mode 100644
index 00000000000..bb71cdeed51
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-http-no-slash-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-http-no-slash-colon</title>
+<audio src="http::@c:29"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-http-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-http-no-slash-novalid.html
new file mode 100644
index 00000000000..7f795d50f36
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-http-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-http-no-slash</title>
+<audio src="http:foo.com"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-http-no-slash-square-bracket-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-http-no-slash-square-bracket-novalid.html
new file mode 100644
index 00000000000..ed81ac62cf5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-http-no-slash-square-bracket-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-http-no-slash-square-bracket</title>
+<audio src="http:[61:27]/:foo"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-http-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-http-single-slash-novalid.html
new file mode 100644
index 00000000000..51b81964450
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-http-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-http-single-slash</title>
+<audio src="http:/example.com/"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-https-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-https-no-slash-novalid.html
new file mode 100644
index 00000000000..8f67ab00f99
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-https-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-https-no-slash</title>
+<audio src="https:example.com/"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-https-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-https-single-slash-novalid.html
new file mode 100644
index 00000000000..be23c7b20a8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-https-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-https-single-slash</title>
+<audio src="https:/example.com/"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-javascript-no-slash-malformed-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-javascript-no-slash-malformed-novalid.html
new file mode 100644
index 00000000000..7d37b16afcb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-javascript-no-slash-malformed-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-javascript-no-slash-malformed</title>
+<audio src="javascript:example.com/"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-trailing-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-trailing-cr-novalid.html
new file mode 100644
index 00000000000..3e40e8a831e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-trailing-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-trailing-cr</title>
+<audio src="a: foo.com"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-trailing-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-trailing-newline-novalid.html
new file mode 100644
index 00000000000..79e9dd14fbe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-trailing-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-trailing-newline</title>
+<audio src="a:
+foo.com"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-trailing-space-novalid.html
new file mode 100644
index 00000000000..b09f7aad824
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-trailing-space</title>
+<audio src="a: foo.com"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-trailing-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-trailing-tab-novalid.html
new file mode 100644
index 00000000000..2f6137be58d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/scheme-trailing-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-trailing-tab</title>
+<audio src="a: foo.com"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/userinfo-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/userinfo-backslash-novalid.html
new file mode 100644
index 00000000000..0b95aa9799e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/userinfo-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: userinfo-backslash</title>
+<audio src="http://a\b:c\d@foo.com"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/userinfo-password-bad-chars-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/userinfo-password-bad-chars-novalid.html
new file mode 100644
index 00000000000..c2823588c71
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/userinfo-password-bad-chars-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: userinfo-password-bad-chars</title>
+<audio src="http://&a:foo(b]c@d:2/"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/userinfo-password-contains-pile-of-poo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/userinfo-password-contains-pile-of-poo-novalid.html
new file mode 100644
index 00000000000..f8039e76b2b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/userinfo-password-contains-pile-of-poo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: userinfo-password-contains-pile-of-poo</title>
+<audio src="http://foo:💩@example.com"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/userinfo-username-contains-at-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/userinfo-username-contains-at-sign-novalid.html
new file mode 100644
index 00000000000..f50b2b25f94
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/userinfo-username-contains-at-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: userinfo-username-contains-at-sign</title>
+<audio src="http://::@c@d:2"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/userinfo-username-contains-pile-of-poo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/userinfo-username-contains-pile-of-poo-novalid.html
new file mode 100644
index 00000000000..fa769f894c5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/audio/src/userinfo-username-contains-pile-of-poo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: userinfo-username-contains-pile-of-poo</title>
+<audio src="http://💩:foo@example.com"></audio>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href-and-target-missing-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href-and-target-missing-novalid.html
new file mode 100644
index 00000000000..32085fc8d2a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href-and-target-missing-novalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta charset=utf-8>
+<base>
+<title>base element missing href and target attribute</title>
+</head>
+<body>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href-empty-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href-empty-isvalid.html
new file mode 100644
index 00000000000..c3b766dfd62
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href-empty-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>empty href is valid</title>
+<base href="">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/fragment-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/fragment-backslash-novalid.html
new file mode 100644
index 00000000000..6528b43cec6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/fragment-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: fragment-backslash</title>
+<base href="#\">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/fragment-contains-hash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/fragment-contains-hash-novalid.html
new file mode 100644
index 00000000000..b5079588aed
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/fragment-contains-hash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: fragment-contains-hash</title>
+<base href="http://foo/path#f#g">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/fragment-contains-pile-of-poo-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/fragment-contains-pile-of-poo-isvalid.html
new file mode 100644
index 00000000000..2ac59a318b8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/fragment-contains-pile-of-poo-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: fragment-contains-pile-of-poo</title>
+<base href="http://example.com/foo#💩">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/fragment-contains-question-mark-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/fragment-contains-question-mark-isvalid.html
new file mode 100644
index 00000000000..7c047912572
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/fragment-contains-question-mark-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: fragment-contains-question-mark</title>
+<base href="http://foo/abcd#foo?bar">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/fragment-empty-hash-only-no-path-relative-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/fragment-empty-hash-only-no-path-relative-isvalid.html
new file mode 100644
index 00000000000..3d097006655
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/fragment-empty-hash-only-no-path-relative-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: fragment-empty-hash-only-no-path-relative</title>
+<base href="#">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/fragment-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/fragment-leading-space-novalid.html
new file mode 100644
index 00000000000..84150eadc17
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/fragment-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: fragment-leading-space</title>
+<base href="http://f:21/b# e">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/fragment-non-ascii-relative-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/fragment-non-ascii-relative-isvalid.html
new file mode 100644
index 00000000000..15858fde1ae
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/fragment-non-ascii-relative-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: fragment-non-ascii-relative</title>
+<base href="#β">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/fragment-semicolon-question-mark-relative-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/fragment-semicolon-question-mark-relative-isvalid.html
new file mode 100644
index 00000000000..68a838c8d04
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/fragment-semicolon-question-mark-relative-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: fragment-semicolon-question-mark-relative</title>
+<base href="#;?">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/fragment-slash-relative-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/fragment-slash-relative-isvalid.html
new file mode 100644
index 00000000000..7edb0b4ed44
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/fragment-slash-relative-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: fragment-slash-relative</title>
+<base href="#/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-192.0x00A80001-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-192.0x00A80001-isvalid.html
new file mode 100644
index 00000000000..75de62fdc87
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-192.0x00A80001-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: host-192.0x00A80001</title>
+<base href="http://192.0x00A80001">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-IP-address-broken-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-IP-address-broken-isvalid.html
new file mode 100644
index 00000000000..dc2e02080b8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-IP-address-broken-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: host-IP-address-broken</title>
+<base href="http://192.168.0.257/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-IP-address-fullwidth-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-IP-address-fullwidth-isvalid.html
new file mode 100644
index 00000000000..64535576d96
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-IP-address-fullwidth-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: host-IP-address-fullwidth</title>
+<base href="http://0Xc0.0250.01">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-IP-address-percent-encoded-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-IP-address-percent-encoded-isvalid.html
new file mode 100644
index 00000000000..8a092380d46
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-IP-address-percent-encoded-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: host-IP-address-percent-encoded</title>
+<base href="http://%30%78%63%30%2e%30%32%35%30.01">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-cr-novalid.html
new file mode 100644
index 00000000000..cb631459e17
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-cr</title>
+<base href="http://example. org">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-double-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-double-percent-encoded-novalid.html
new file mode 100644
index 00000000000..fc44eee8a90
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-double-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-double-percent-encoded</title>
+<base href="http://%41.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-double-percent-encoded-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-double-percent-encoded-percent-encoded-novalid.html
new file mode 100644
index 00000000000..eaee5db8a1a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-double-percent-encoded-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-double-percent-encoded-percent-encoded</title>
+<base href="http://%ef%bc%85%ef%bc%94%ef%bc%91.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-empty-novalid.html
new file mode 100644
index 00000000000..08ce416ef2f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-empty</title>
+<base href="http://">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-empty-userinfo-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-empty-userinfo-empty-novalid.html
new file mode 100644
index 00000000000..d41591fabe9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-empty-userinfo-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-empty-userinfo-empty</title>
+<base href="http://@/www.example.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-empty-with-userinfo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-empty-with-userinfo-novalid.html
new file mode 100644
index 00000000000..47941b7235e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-empty-with-userinfo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-empty-with-userinfo</title>
+<base href="http://user:pass@/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-exotic-dot-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-exotic-dot-isvalid.html
new file mode 100644
index 00000000000..d0d1f0a1d1b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-exotic-dot-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: host-exotic-dot</title>
+<base href="http://www.foo。bar.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-exotic-whitespace-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-exotic-whitespace-isvalid.html
new file mode 100644
index 00000000000..adcc57480ef
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-exotic-whitespace-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: host-exotic-whitespace</title>
+<base href="http://GOO​⁠goo.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-fullwidth-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-fullwidth-isvalid.html
new file mode 100644
index 00000000000..65108edd474
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-fullwidth-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: host-fullwidth</title>
+<base href="http://Go.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-hostname-in-brackets-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-hostname-in-brackets-novalid.html
new file mode 100644
index 00000000000..c25a1a3ffae
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-hostname-in-brackets-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-hostname-in-brackets</title>
+<base href="http://[www.google.com]/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-idn-unicode-han-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-idn-unicode-han-isvalid.html
new file mode 100644
index 00000000000..576badf53f3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-idn-unicode-han-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: host-idn-unicode-han</title>
+<base href="http://你好你好">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-invalid-unicode-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-invalid-unicode-novalid.html
new file mode 100644
index 00000000000..4b206920177
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-invalid-unicode-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-invalid-unicode</title>
+<base href="http://﷐zyx.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-invalid-unicode-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-invalid-unicode-percent-encoded-novalid.html
new file mode 100644
index 00000000000..4533dbc8872
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-invalid-unicode-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-invalid-unicode-percent-encoded</title>
+<base href="http://%ef%b7%90zyx.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-ipv6-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-ipv6-isvalid.html
new file mode 100644
index 00000000000..112eacd95af
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-ipv6-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: host-ipv6</title>
+<base href="http://[2001::1]">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-ipv6-port-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-ipv6-port-isvalid.html
new file mode 100644
index 00000000000..3495478c747
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-ipv6-port-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: host-ipv6-port</title>
+<base href="http://[2001::1]:80">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-is-pile-of-poo-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-is-pile-of-poo-isvalid.html
new file mode 100644
index 00000000000..f286407a0bd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-is-pile-of-poo-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: host-is-pile-of-poo</title>
+<base href="http://💩">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-newline-novalid.html
new file mode 100644
index 00000000000..44e53c36fc6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-newline</title>
+<base href="http://example.
+org">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-space-novalid.html
new file mode 100644
index 00000000000..4b02459e3c2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-space</title>
+<base href="http://example .org">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-square-brackets-port-contains-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-square-brackets-port-contains-colon-novalid.html
new file mode 100644
index 00000000000..1839ee26884
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-square-brackets-port-contains-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-square-brackets-port-contains-colon</title>
+<base href="http://[1::2]:3:4">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-tab-novalid.html
new file mode 100644
index 00000000000..335d7c842dd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-tab</title>
+<base href="http://example .org">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-u0000-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-u0000-percent-encoded-novalid.html
new file mode 100644
index 00000000000..94a2327129c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-u0000-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-u0000-percent-encoded</title>
+<base href="http://%00.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-u0000-percent-encoded-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-u0000-percent-encoded-percent-encoded-novalid.html
new file mode 100644
index 00000000000..bc934e67020
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/host-u0000-percent-encoded-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-u0000-percent-encoded-percent-encoded</title>
+<base href="http://%ef%bc%85%ef%bc%90%ef%bc%90.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-bare-percent-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-bare-percent-sign-novalid.html
new file mode 100644
index 00000000000..819a99d538f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-bare-percent-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: path-bare-percent-sign</title>
+<base href="http://example.com/foo%">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-colon-colon-number-relative-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-colon-colon-number-relative-isvalid.html
new file mode 100644
index 00000000000..643b01f07d0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-colon-colon-number-relative-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: path-colon-colon-number-relative</title>
+<base href="::23">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-colon-relative-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-colon-relative-isvalid.html
new file mode 100644
index 00000000000..f1254de8d2a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-colon-relative-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: path-colon-relative</title>
+<base href=":">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-contains-pile-of-poo-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-contains-pile-of-poo-isvalid.html
new file mode 100644
index 00000000000..f491b503f30
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-contains-pile-of-poo-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: path-contains-pile-of-poo</title>
+<base href="http💩//:foo">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-contains-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-contains-space-novalid.html
new file mode 100644
index 00000000000..87c76dd3057
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-contains-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: path-contains-space</title>
+<base href="/a/ /c">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-leading-backslash-at-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-leading-backslash-at-sign-novalid.html
new file mode 100644
index 00000000000..785ecad748a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-leading-backslash-at-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: path-leading-backslash-at-sign</title>
+<base href="http://foo.com/\@">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-leading-colon-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-leading-colon-backslash-novalid.html
new file mode 100644
index 00000000000..1e61b71c383
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-leading-colon-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: path-leading-colon-backslash</title>
+<base href=":\">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-leading-colon-chars-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-leading-colon-chars-backslash-novalid.html
new file mode 100644
index 00000000000..5ae57974b22
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-leading-colon-chars-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: path-leading-colon-chars-backslash</title>
+<base href=":foo.com\">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-leading-colon-chars-relative-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-leading-colon-chars-relative-isvalid.html
new file mode 100644
index 00000000000..11b94a6e1c6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-leading-colon-chars-relative-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: path-leading-colon-chars-relative</title>
+<base href=":foo.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-leading-colon-colon-relative-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-leading-colon-colon-relative-isvalid.html
new file mode 100644
index 00000000000..0589f8ae2d4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-leading-colon-colon-relative-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: path-leading-colon-colon-relative</title>
+<base href="::">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-leading-colon-hash-relative-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-leading-colon-hash-relative-isvalid.html
new file mode 100644
index 00000000000..7114dd5f5cf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-leading-colon-hash-relative-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: path-leading-colon-hash-relative</title>
+<base href=":#">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-leading-colon-letter-relative-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-leading-colon-letter-relative-isvalid.html
new file mode 100644
index 00000000000..279c2ce4c17
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-leading-colon-letter-relative-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: path-leading-colon-letter-relative</title>
+<base href=":a">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-leading-colon-number-relative-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-leading-colon-number-relative-isvalid.html
new file mode 100644
index 00000000000..c66670292f8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-leading-colon-number-relative-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: path-leading-colon-number-relative</title>
+<base href=":23">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-leading-colon-slash-relative-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-leading-colon-slash-relative-isvalid.html
new file mode 100644
index 00000000000..77ec3dd2d06
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-leading-colon-slash-relative-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: path-leading-colon-slash-relative</title>
+<base href=":/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-leading-space-novalid.html
new file mode 100644
index 00000000000..3a6cc2f33a7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: path-leading-space</title>
+<base href="http://f:21/ b">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-non-ascii-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-non-ascii-isvalid.html
new file mode 100644
index 00000000000..e9d396b02ec
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-non-ascii-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: path-non-ascii</title>
+<base href="http://example.com/©zbar">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-percent-encoded-dot-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-percent-encoded-dot-isvalid.html
new file mode 100644
index 00000000000..5921992d467
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-percent-encoded-dot-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: path-percent-encoded-dot</title>
+<base href="http://example.com/foo/%2e">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-percent-encoded-malformed-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-percent-encoded-malformed-novalid.html
new file mode 100644
index 00000000000..c9cfe232895
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-percent-encoded-malformed-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: path-percent-encoded-malformed</title>
+<base href="http://example.com/foo/%2e%2">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-percent-encoded-mixed-case-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-percent-encoded-mixed-case-isvalid.html
new file mode 100644
index 00000000000..677a564bacb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-percent-encoded-mixed-case-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: path-percent-encoded-mixed-case</title>
+<base href="http://example.com/%3A%3a%3C%3c">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-percent-encoded-multiple-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-percent-encoded-multiple-isvalid.html
new file mode 100644
index 00000000000..75a512babc4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-percent-encoded-multiple-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: path-percent-encoded-multiple</title>
+<base href="http://example.com/foo%41%7a">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-percent-encoded-slash-plus-slashes-relative-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-percent-encoded-slash-plus-slashes-relative-isvalid.html
new file mode 100644
index 00000000000..f5ed17b9025
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-percent-encoded-slash-plus-slashes-relative-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: path-percent-encoded-slash-plus-slashes-relative</title>
+<base href="/a/%2f/c">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-percent-encoded-slash-relative-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-percent-encoded-slash-relative-isvalid.html
new file mode 100644
index 00000000000..79e89e3abe2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-percent-encoded-slash-relative-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: path-percent-encoded-slash-relative</title>
+<base href="/a%2fc">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-percent-encoded-space-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-percent-encoded-space-isvalid.html
new file mode 100644
index 00000000000..cc9b8b850e0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-percent-encoded-space-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: path-percent-encoded-space</title>
+<base href="http://example.com/%20foo">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-percent-encoded-u0000-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-percent-encoded-u0000-isvalid.html
new file mode 100644
index 00000000000..515a7528edb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-percent-encoded-u0000-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: path-percent-encoded-u0000</title>
+<base href="http://example.com/foo%00">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-percent-encoded-u0091-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-percent-encoded-u0091-isvalid.html
new file mode 100644
index 00000000000..16cec3605eb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-percent-encoded-u0091-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: path-percent-encoded-u0091</title>
+<base href="http://example.com/foo%91">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-relative-square-brackets-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-relative-square-brackets-novalid.html
new file mode 100644
index 00000000000..79af6ae6f84
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-relative-square-brackets-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: path-relative-square-brackets</title>
+<base href="[61:24:74]:98">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-simple-relative-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-simple-relative-isvalid.html
new file mode 100644
index 00000000000..7e4c99fab11
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-simple-relative-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: path-simple-relative</title>
+<base href="/a/b/c">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-slash-colon-number-relative-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-slash-colon-number-relative-isvalid.html
new file mode 100644
index 00000000000..3834395ce82
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-slash-colon-number-relative-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: path-slash-colon-number-relative</title>
+<base href="/:23">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-slash-only-relative-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-slash-only-relative-isvalid.html
new file mode 100644
index 00000000000..83a89c09ae5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-slash-only-relative-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: path-slash-only-relative</title>
+<base href="/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-starts-with-pile-of-poo-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-starts-with-pile-of-poo-isvalid.html
new file mode 100644
index 00000000000..204b8b096ae
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-starts-with-pile-of-poo-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: path-starts-with-pile-of-poo</title>
+<base href="💩http://foo">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-tab-novalid.html
new file mode 100644
index 00000000000..21f8b6e5d9e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: path-tab</title>
+<base href="http://example.com/foo bar">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-trailing-space-novalid.html
new file mode 100644
index 00000000000..3a24cb6e411
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: path-trailing-space</title>
+<base href="http://f:21/b ?">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-u0091-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-u0091-novalid.html
new file mode 100644
index 00000000000..78383c870fd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-u0091-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: path-u0091</title>
+<base href="http://example.com/foo‘">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-u202E-u202D-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-u202E-u202D-isvalid.html
new file mode 100644
index 00000000000..5d865b6409b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-u202E-u202D-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: path-u202E-u202D</title>
+<base href="http://example.com/‮/foo/‭/bar">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-uFEFF-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-uFEFF-isvalid.html
new file mode 100644
index 00000000000..03c3a969ff4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-uFEFF-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: path-uFEFF</title>
+<base href="http://example.com//foo">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-unicode-han-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-unicode-han-isvalid.html
new file mode 100644
index 00000000000..e6c290bc261
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/path-unicode-han-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: path-unicode-han</title>
+<base href="http://example.com/你好你好">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/port-0-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/port-0-isvalid.html
new file mode 100644
index 00000000000..6dd7298b554
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/port-0-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: port-0</title>
+<base href="http://f:0/c">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/port-00000000000000-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/port-00000000000000-isvalid.html
new file mode 100644
index 00000000000..314c8ad777e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/port-00000000000000-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: port-00000000000000</title>
+<base href="http://f:00000000000000/c">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/port-00000000000000000000080-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/port-00000000000000000000080-isvalid.html
new file mode 100644
index 00000000000..34dd3d5624a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/port-00000000000000000000080-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: port-00000000000000000000080</title>
+<base href="http://f:00000000000000000000080/c">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/port-999999-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/port-999999-isvalid.html
new file mode 100644
index 00000000000..391b88094ba
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/port-999999-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: port-999999</title>
+<base href="http://f:999999/c">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/port-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/port-cr-novalid.html
new file mode 100644
index 00000000000..e5fe6bf6881
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/port-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: port-cr</title>
+<base href="http://f: /c">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/port-leading-colon-bracket-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/port-leading-colon-bracket-colon-novalid.html
new file mode 100644
index 00000000000..3bc673fe64c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/port-leading-colon-bracket-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: port-leading-colon-bracket-colon</title>
+<base href="http://2001::1]:80">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/port-leading-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/port-leading-colon-novalid.html
new file mode 100644
index 00000000000..c526a758ffe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/port-leading-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: port-leading-colon</title>
+<base href="http://2001::1">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/port-leading-dash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/port-leading-dash-novalid.html
new file mode 100644
index 00000000000..2270e65c9c6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/port-leading-dash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: port-leading-dash</title>
+<base href="http://foo:-80/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/port-multiple-letters-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/port-multiple-letters-novalid.html
new file mode 100644
index 00000000000..9d5ef78404a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/port-multiple-letters-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: port-multiple-letters</title>
+<base href="http://f:fifty-two/c">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/port-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/port-newline-novalid.html
new file mode 100644
index 00000000000..bef3487e4d6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/port-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: port-newline</title>
+<base href="http://f:
+/c">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/port-none-but-colon-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/port-none-but-colon-isvalid.html
new file mode 100644
index 00000000000..4307c492cb8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/port-none-but-colon-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: port-none-but-colon</title>
+<base href="http://f:/c">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/port-single-letter-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/port-single-letter-novalid.html
new file mode 100644
index 00000000000..8daa066d605
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/port-single-letter-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: port-single-letter</title>
+<base href="http://f:b/c">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/port-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/port-space-novalid.html
new file mode 100644
index 00000000000..77a3d576204
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/port-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: port-space</title>
+<base href="http://f: /c">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/port-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/port-tab-novalid.html
new file mode 100644
index 00000000000..e14664a74b4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/port-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: port-tab</title>
+<base href="http://f: /c">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/query-contains-pile-of-poo-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/query-contains-pile-of-poo-isvalid.html
new file mode 100644
index 00000000000..7ea7f410878
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/query-contains-pile-of-poo-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: query-contains-pile-of-poo</title>
+<base href="http://example.com/foo?💩">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/query-contains-question-mark-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/query-contains-question-mark-isvalid.html
new file mode 100644
index 00000000000..f78635c4e95
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/query-contains-question-mark-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: query-contains-question-mark</title>
+<base href="http://foo/abcd?efgh?ijkl">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/query-empty-no-path-relative-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/query-empty-no-path-relative-isvalid.html
new file mode 100644
index 00000000000..82b66f0644a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/query-empty-no-path-relative-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: query-empty-no-path-relative</title>
+<base href="?">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/query-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/query-leading-space-novalid.html
new file mode 100644
index 00000000000..d26d8e19652
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/query-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: query-leading-space</title>
+<base href="http://f:21/b? d">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/query-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/query-trailing-space-novalid.html
new file mode 100644
index 00000000000..d099a9f0e4e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/query-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: query-trailing-space</title>
+<base href="http://f:21/b?d #">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-data-contains-fragment-haswarn.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-data-contains-fragment-haswarn.html
new file mode 100644
index 00000000000..a1e740045a1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-data-contains-fragment-haswarn.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>href warning: scheme-data-contains-fragment</title>
+<base href="data:text/html,test#test">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-data-no-slash-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-data-no-slash-isvalid.html
new file mode 100644
index 00000000000..e13d2677b47
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-data-no-slash-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: scheme-data-no-slash</title>
+<base href="data:text/plain,foo">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-data-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-data-single-slash-novalid.html
new file mode 100644
index 00000000000..1f938779acc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-data-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-data-single-slash</title>
+<base href="data:/example.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-file-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-file-backslash-novalid.html
new file mode 100644
index 00000000000..fda3e3d0399
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-file-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-file-backslash</title>
+<base href="file:c:\foo\bar.html">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-file-host-empty-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-file-host-empty-isvalid.html
new file mode 100644
index 00000000000..a90aa6c7164
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-file-host-empty-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: scheme-file-host-empty</title>
+<base href="file:///foo/bar.txt">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-file-host-included-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-file-host-included-isvalid.html
new file mode 100644
index 00000000000..322773e2e93
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-file-host-included-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: scheme-file-host-included</title>
+<base href="file://server/foo/bar">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-file-no-slash-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-file-no-slash-isvalid.html
new file mode 100644
index 00000000000..3a31f957e12
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-file-no-slash-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: scheme-file-no-slash</title>
+<base href="file:test">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-file-scheme-only-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-file-scheme-only-isvalid.html
new file mode 100644
index 00000000000..af318cdd9dd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-file-scheme-only-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: scheme-file-scheme-only</title>
+<base href="file:">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-file-single-slash-c-bar-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-file-single-slash-c-bar-novalid.html
new file mode 100644
index 00000000000..87d17ed6c23
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-file-single-slash-c-bar-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-file-single-slash-c-bar</title>
+<base href="file:/C|/foo/bar">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-file-single-slash-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-file-single-slash-isvalid.html
new file mode 100644
index 00000000000..f67878f46cb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-file-single-slash-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: scheme-file-single-slash</title>
+<base href="file:/example.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-file-slash-only-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-file-slash-only-isvalid.html
new file mode 100644
index 00000000000..a8c329f33d1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-file-slash-only-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: scheme-file-slash-only</title>
+<base href="file:/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-file-slash-slash-abc-bar-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-file-slash-slash-abc-bar-isvalid.html
new file mode 100644
index 00000000000..4537d8c19f6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-file-slash-slash-abc-bar-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: scheme-file-slash-slash-abc-bar</title>
+<base href="file://abc|/foo/bar">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-file-slash-slash-c-bar-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-file-slash-slash-c-bar-isvalid.html
new file mode 100644
index 00000000000..4d96a67da69
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-file-slash-slash-c-bar-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: scheme-file-slash-slash-c-bar</title>
+<base href="file://C|/foo/bar">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-file-slash-slash-only-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-file-slash-slash-only-isvalid.html
new file mode 100644
index 00000000000..dcef904aa56
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-file-slash-slash-only-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: scheme-file-slash-slash-only</title>
+<base href="file://">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-file-slash-slash-slash-only-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-file-slash-slash-slash-only-isvalid.html
new file mode 100644
index 00000000000..ffe97bb7217
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-file-slash-slash-slash-only-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: scheme-file-slash-slash-slash-only</title>
+<base href="file:///">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-file-triple-slash-c-bar-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-file-triple-slash-c-bar-novalid.html
new file mode 100644
index 00000000000..06b8933be98
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-file-triple-slash-c-bar-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-file-triple-slash-c-bar</title>
+<base href="file:///C|/foo/bar">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-file-uppercase-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-file-uppercase-isvalid.html
new file mode 100644
index 00000000000..58bb4a4799f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-file-uppercase-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: scheme-file-uppercase</title>
+<base href="File://foo/bar.html">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-ftp-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-ftp-no-slash-novalid.html
new file mode 100644
index 00000000000..49285d8082b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-ftp-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-ftp-no-slash</title>
+<base href="ftp:example.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-ftp-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-ftp-single-slash-novalid.html
new file mode 100644
index 00000000000..7ff694c98be
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-ftp-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-ftp-single-slash</title>
+<base href="ftp:/example.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-ftps-no-slash-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-ftps-no-slash-isvalid.html
new file mode 100644
index 00000000000..bc0ac07fe82
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-ftps-no-slash-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: scheme-ftps-no-slash</title>
+<base href="ftps:example.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-ftps-single-slash-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-ftps-single-slash-isvalid.html
new file mode 100644
index 00000000000..758a74e172e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-ftps-single-slash-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: scheme-ftps-single-slash</title>
+<base href="ftps:/example.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-gopher-no-slash-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-gopher-no-slash-isvalid.html
new file mode 100644
index 00000000000..ec35f0abb50
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-gopher-no-slash-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: scheme-gopher-no-slash</title>
+<base href="gopher:example.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-gopher-single-slash-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-gopher-single-slash-isvalid.html
new file mode 100644
index 00000000000..aa97811b3fe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-gopher-single-slash-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: scheme-gopher-single-slash</title>
+<base href="gopher:/example.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-http-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-http-backslash-novalid.html
new file mode 100644
index 00000000000..5923cf1df1e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-http-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-http-backslash</title>
+<base href="http:\\foo.com\">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-http-no-slash-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-http-no-slash-colon-novalid.html
new file mode 100644
index 00000000000..8146e78bb6d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-http-no-slash-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-http-no-slash-colon</title>
+<base href="http::@c:29">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-http-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-http-no-slash-novalid.html
new file mode 100644
index 00000000000..6084b413f43
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-http-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-http-no-slash</title>
+<base href="http:foo.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-http-no-slash-square-bracket-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-http-no-slash-square-bracket-novalid.html
new file mode 100644
index 00000000000..21f612d8a8e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-http-no-slash-square-bracket-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-http-no-slash-square-bracket</title>
+<base href="http:[61:27]/:foo">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-http-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-http-single-slash-novalid.html
new file mode 100644
index 00000000000..4684b7b2bc9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-http-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-http-single-slash</title>
+<base href="http:/example.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-https-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-https-no-slash-novalid.html
new file mode 100644
index 00000000000..76c139dfda2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-https-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-https-no-slash</title>
+<base href="https:example.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-https-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-https-single-slash-novalid.html
new file mode 100644
index 00000000000..49d14bcec77
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-https-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-https-single-slash</title>
+<base href="https:/example.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-javascript-no-slash-malformed-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-javascript-no-slash-malformed-novalid.html
new file mode 100644
index 00000000000..16b4187b80d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-javascript-no-slash-malformed-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-javascript-no-slash-malformed</title>
+<base href="javascript:example.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-javascript-single-slash-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-javascript-single-slash-isvalid.html
new file mode 100644
index 00000000000..cb6b793bcf2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-javascript-single-slash-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: scheme-javascript-single-slash</title>
+<base href="javascript:/example.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-mailto-no-slash-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-mailto-no-slash-isvalid.html
new file mode 100644
index 00000000000..5c96deb1625
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-mailto-no-slash-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: scheme-mailto-no-slash</title>
+<base href="mailto:example.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-mailto-single-slash-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-mailto-single-slash-isvalid.html
new file mode 100644
index 00000000000..ca07ab15f2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-mailto-single-slash-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: scheme-mailto-single-slash</title>
+<base href="mailto:/example.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-none-relative-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-none-relative-isvalid.html
new file mode 100644
index 00000000000..672de82fb22
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-none-relative-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: scheme-none-relative</title>
+<base href="foo.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-private-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-private-isvalid.html
new file mode 100644
index 00000000000..d565575b57b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-private-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: scheme-private</title>
+<base href="a:foo.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-private-no-slash-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-private-no-slash-isvalid.html
new file mode 100644
index 00000000000..207a8d6cbee
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-private-no-slash-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: scheme-private-no-slash</title>
+<base href="madeupscheme:example.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-private-path-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-private-path-isvalid.html
new file mode 100644
index 00000000000..8e0552b703d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-private-path-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: scheme-private-path</title>
+<base href="foo:/bar.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-private-path-leading-slashes-chars-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-private-path-leading-slashes-chars-isvalid.html
new file mode 100644
index 00000000000..6fa812d7833
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-private-path-leading-slashes-chars-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: scheme-private-path-leading-slashes-chars</title>
+<base href="foo://///////bar.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-private-path-leading-slashes-colon-slashes-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-private-path-leading-slashes-colon-slashes-isvalid.html
new file mode 100644
index 00000000000..3e5a44a0053
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-private-path-leading-slashes-colon-slashes-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: scheme-private-path-leading-slashes-colon-slashes</title>
+<base href="foo:////://///">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-private-path-leading-slashes-only-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-private-path-leading-slashes-only-isvalid.html
new file mode 100644
index 00000000000..8d6c0c9f8db
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-private-path-leading-slashes-only-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: scheme-private-path-leading-slashes-only</title>
+<base href="foo://///////">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-private-single-letter-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-private-single-letter-isvalid.html
new file mode 100644
index 00000000000..bc82b8b7fe7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-private-single-letter-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: scheme-private-single-letter</title>
+<base href="c:/foo">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-private-single-slash-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-private-single-slash-isvalid.html
new file mode 100644
index 00000000000..c3639a432cd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-private-single-slash-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: scheme-private-single-slash</title>
+<base href="madeupscheme:/example.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-private-slash-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-private-slash-isvalid.html
new file mode 100644
index 00000000000..d56b355cf9c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-private-slash-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: scheme-private-slash</title>
+<base href="foo:/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-private-slash-slash-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-private-slash-slash-isvalid.html
new file mode 100644
index 00000000000..39a6b25cf7d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-private-slash-slash-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: scheme-private-slash-slash</title>
+<base href="foo://">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-schemeless-relative-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-schemeless-relative-isvalid.html
new file mode 100644
index 00000000000..d86d3f68caf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-schemeless-relative-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: scheme-schemeless-relative</title>
+<base href="//foo/bar">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-trailing-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-trailing-cr-novalid.html
new file mode 100644
index 00000000000..e6097e4f790
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-trailing-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-trailing-cr</title>
+<base href="a: foo.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-trailing-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-trailing-newline-novalid.html
new file mode 100644
index 00000000000..acc6c91ffaa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-trailing-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-trailing-newline</title>
+<base href="a:
+foo.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-trailing-space-novalid.html
new file mode 100644
index 00000000000..c03abd547c6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-trailing-space</title>
+<base href="a: foo.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-trailing-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-trailing-tab-novalid.html
new file mode 100644
index 00000000000..0e1f91bce62
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-trailing-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-trailing-tab</title>
+<base href="a: foo.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-ws-single-slash-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-ws-single-slash-isvalid.html
new file mode 100644
index 00000000000..63e24e9b6ba
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-ws-single-slash-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: scheme-ws-single-slash</title>
+<base href="ws:/example.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-wss-no-slash-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-wss-no-slash-isvalid.html
new file mode 100644
index 00000000000..2c4e88c3aaa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-wss-no-slash-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: scheme-wss-no-slash</title>
+<base href="wss:example.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-wss-single-slash-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-wss-single-slash-isvalid.html
new file mode 100644
index 00000000000..a2b2b6fd59b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/scheme-wss-single-slash-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: scheme-wss-single-slash</title>
+<base href="wss:/example.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/userinfo-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/userinfo-backslash-novalid.html
new file mode 100644
index 00000000000..99a6d72075d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/userinfo-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: userinfo-backslash</title>
+<base href="http://a\b:c\d@foo.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/userinfo-empty-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/userinfo-empty-isvalid.html
new file mode 100644
index 00000000000..8f641cf94b1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/userinfo-empty-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: userinfo-empty</title>
+<base href="http://@www.example.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/userinfo-host-port-path-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/userinfo-host-port-path-isvalid.html
new file mode 100644
index 00000000000..e28a20b518f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/userinfo-host-port-path-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: userinfo-host-port-path</title>
+<base href="http://a:b@c:29/d">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/userinfo-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/userinfo-isvalid.html
new file mode 100644
index 00000000000..6f1d9eaea60
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/userinfo-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: userinfo</title>
+<base href="http://user:pass@foo:21/bar;par?b#c">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/userinfo-password-bad-chars-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/userinfo-password-bad-chars-novalid.html
new file mode 100644
index 00000000000..31a68b170a4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/userinfo-password-bad-chars-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: userinfo-password-bad-chars</title>
+<base href="http://&a:foo(b]c@d:2/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/userinfo-password-contains-pile-of-poo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/userinfo-password-contains-pile-of-poo-novalid.html
new file mode 100644
index 00000000000..0fa8f05058c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/userinfo-password-contains-pile-of-poo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: userinfo-password-contains-pile-of-poo</title>
+<base href="http://foo:💩@example.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/userinfo-password-empty-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/userinfo-password-empty-isvalid.html
new file mode 100644
index 00000000000..cedf7ae3b85
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/userinfo-password-empty-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: userinfo-password-empty</title>
+<base href="http://a:@www.example.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/userinfo-user-empty-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/userinfo-user-empty-isvalid.html
new file mode 100644
index 00000000000..b6f323d2d0b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/userinfo-user-empty-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: userinfo-user-empty</title>
+<base href="http://:b@www.example.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/userinfo-username-contains-at-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/userinfo-username-contains-at-sign-novalid.html
new file mode 100644
index 00000000000..c3a16ce8634
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/userinfo-username-contains-at-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: userinfo-username-contains-at-sign</title>
+<base href="http://::@c@d:2">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/userinfo-username-contains-percent-encoded-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/userinfo-username-contains-percent-encoded-isvalid.html
new file mode 100644
index 00000000000..2c2dfebd2e2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/userinfo-username-contains-percent-encoded-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: userinfo-username-contains-percent-encoded</title>
+<base href="http://%25DOMAIN:foobar@foodomain.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/userinfo-username-contains-pile-of-poo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/userinfo-username-contains-pile-of-poo-novalid.html
new file mode 100644
index 00000000000..0ff54c4c9dc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/userinfo-username-contains-pile-of-poo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: userinfo-username-contains-pile-of-poo</title>
+<base href="http://💩:foo@example.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/userinfo-username-non-alpha-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/userinfo-username-non-alpha-isvalid.html
new file mode 100644
index 00000000000..f7507033730
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/base/href/userinfo-username-non-alpha-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href: userinfo-username-non-alpha</title>
+<base href="http://foo.com:b@d/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/bdo/model-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/bdo/model-isvalid.html
new file mode 100644
index 00000000000..17a9d2c9719
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/bdo/model-isvalid.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;bdo&gt;</title>
+</head>
+<body>
+ <!-- is structured inline; requires 'dir', test all attrs -->
+ <p><bdo dir="ltr"
+ lang="en"
+ style=""
+ class="class"
+ id="foo">text</bdo></p>
+
+ <!-- is strictly inline -->
+ <p><dfn><bdo dir="ltr" class="class" lang="en">text</bdo></dfn></p>
+
+ <!-- can be empty -->
+ <p>text <bdo dir="ltr"></bdo></p>
+ <p>text <dfn><bdo dir="ltr"></bdo></dfn></p>
+
+ <!-- can contain interactive -->
+ <p><bdo dir="ltr"><a>text</a></bdo></p>
+ <p><dfn><bdo dir="ltr"><a>text</a></bdo></dfn></p>
+
+ <!-- cannot contain structured inline -->
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/bdo/model-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/bdo/model-novalid.html
new file mode 100644
index 00000000000..5dee57cf7a9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/bdo/model-novalid.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;bdo&gt;</title>
+</head>
+<body>
+ <!-- not a block -->
+ <bdo dir="ltr">text</bdo>
+
+ <!-- 'dir' attribute required -->
+ <p><bdo>text</bdo></p>
+
+ <!-- cannot contain structured inline -->
+ <p><bdo dir="ltr"><ul><li>text</li></ul></bdo></p>
+
+ <!-- cannot contain interactive if parent forbids interactive -->
+ <p><a><bdo dir="ltr"><a>text</a></bdo></a></p>
+ <p><a><dfn><bdo dir="ltr"><a>text</a></bdo></dfn></a></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite-empty-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite-empty-isvalid.html
new file mode 100644
index 00000000000..698d8634a86
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite-empty-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>empty cite is valid</title>
+<blockquote cite=""></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite-isvalid.html
new file mode 100644
index 00000000000..03d49827217
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite-isvalid.html
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid cite</title>
+<blockquote cite="file:///"></blockquote><!-- scheme-file-slash-slash-slash-only -->
+<blockquote cite="http://a:@www.example.com"></blockquote><!-- userinfo-password-empty -->
+<blockquote cite="foo://///////"></blockquote><!-- scheme-private-path-leading-slashes-only -->
+<blockquote cite="file://abc|/foo/bar"></blockquote><!-- scheme-file-slash-slash-abc-bar -->
+<blockquote cite="/a/b/c"></blockquote><!-- path-simple-relative -->
+<blockquote cite="http://example.com/你好你好"></blockquote><!-- path-unicode-han -->
+<blockquote cite="/a/%2f/c"></blockquote><!-- path-percent-encoded-slash-plus-slashes-relative -->
+<blockquote cite="http://f:/c"></blockquote><!-- port-none-but-colon -->
+<blockquote cite="http://example.com/foo%41%7a"></blockquote><!-- path-percent-encoded-multiple -->
+<blockquote cite="http://192.168.0.257/"></blockquote><!-- host-IP-address-broken -->
+<blockquote cite="madeupscheme:example.com/"></blockquote><!-- scheme-private-no-slash -->
+<blockquote cite="?"></blockquote><!-- query-empty-no-path-relative -->
+<blockquote cite="http://example.com/%20foo"></blockquote><!-- path-percent-encoded-space -->
+<blockquote cite="mailto:/example.com/"></blockquote><!-- scheme-mailto-single-slash -->
+<blockquote cite="::"></blockquote><!-- path-leading-colon-colon-relative -->
+<blockquote cite="http://example.com/%3A%3a%3C%3c"></blockquote><!-- path-percent-encoded-mixed-case -->
+<blockquote cite="http://user:pass@foo:21/bar;par?b#c"></blockquote><!-- userinfo -->
+<blockquote cite="ws:/example.com/"></blockquote><!-- scheme-ws-single-slash -->
+<blockquote cite="foo://"></blockquote><!-- scheme-private-slash-slash -->
+<blockquote cite="#"></blockquote><!-- fragment-empty-hash-only-no-path-relative -->
+<blockquote cite="http://f:00000000000000/c"></blockquote><!-- port-00000000000000 -->
+<blockquote cite="foo:////://///"></blockquote><!-- scheme-private-path-leading-slashes-colon-slashes -->
+<blockquote cite=":23"></blockquote><!-- path-leading-colon-number-relative -->
+<blockquote cite="foo:/"></blockquote><!-- scheme-private-slash -->
+<blockquote cite="http://💩"></blockquote><!-- host-is-pile-of-poo -->
+<blockquote cite="file:test"></blockquote><!-- scheme-file-no-slash -->
+<blockquote cite="file://C|/foo/bar"></blockquote><!-- scheme-file-slash-slash-c-bar -->
+<blockquote cite="#/"></blockquote><!-- fragment-slash-relative -->
+<blockquote cite="http://192.0x00A80001"></blockquote><!-- host-192.0x00A80001 -->
+<blockquote cite="foo.com"></blockquote><!-- scheme-none-relative -->
+<blockquote cite="http💩//:foo"></blockquote><!-- path-contains-pile-of-poo -->
+<blockquote cite="File://foo/bar.html"></blockquote><!-- scheme-file-uppercase -->
+<blockquote cite=":/"></blockquote><!-- path-leading-colon-slash-relative -->
+<blockquote cite="http://www.foo。bar.com"></blockquote><!-- host-exotic-dot -->
+<blockquote cite="http://GOO​⁠goo.com"></blockquote><!-- host-exotic-whitespace -->
+<blockquote cite="file:///foo/bar.txt"></blockquote><!-- scheme-file-host-empty -->
+<blockquote cite="javascript:/example.com/"></blockquote><!-- scheme-javascript-single-slash -->
+<blockquote cite="gopher:/example.com/"></blockquote><!-- scheme-gopher-single-slash -->
+<blockquote cite="ftps:example.com/"></blockquote><!-- scheme-ftps-no-slash -->
+<blockquote cite="file://server/foo/bar"></blockquote><!-- scheme-file-host-included -->
+<blockquote cite="http://example.com/foo%00"></blockquote><!-- path-percent-encoded-u0000 -->
+<blockquote cite="a:foo.com"></blockquote><!-- scheme-private -->
+<blockquote cite=":"></blockquote><!-- path-colon-relative -->
+<blockquote cite="http://:b@www.example.com"></blockquote><!-- userinfo-user-empty -->
+<blockquote cite="file:/"></blockquote><!-- scheme-file-slash-only -->
+<blockquote cite="wss:example.com/"></blockquote><!-- scheme-wss-no-slash -->
+<blockquote cite="::23"></blockquote><!-- path-colon-colon-number-relative -->
+<blockquote cite="/a%2fc"></blockquote><!-- path-percent-encoded-slash-relative -->
+<blockquote cite="http://a:b@c:29/d"></blockquote><!-- userinfo-host-port-path -->
+<blockquote cite="gopher:example.com/"></blockquote><!-- scheme-gopher-no-slash -->
+<blockquote cite="madeupscheme:/example.com/"></blockquote><!-- scheme-private-single-slash -->
+<blockquote cite="mailto:example.com/"></blockquote><!-- scheme-mailto-no-slash -->
+<blockquote cite="http://%25DOMAIN:foobar@foodomain.com"></blockquote><!-- userinfo-username-contains-percent-encoded -->
+<blockquote cite="/:23"></blockquote><!-- path-slash-colon-number-relative -->
+<blockquote cite="foo://///////bar.com/"></blockquote><!-- scheme-private-path-leading-slashes-chars -->
+<blockquote cite="http://[2001::1]:80"></blockquote><!-- host-ipv6-port -->
+<blockquote cite="data:text/plain,foo"></blockquote><!-- scheme-data-no-slash -->
+<blockquote cite="http://example.com/foo/%2e"></blockquote><!-- path-percent-encoded-dot -->
+<blockquote cite="file:/example.com/"></blockquote><!-- scheme-file-single-slash -->
+<blockquote cite="http://example.com/©zbar"></blockquote><!-- path-non-ascii -->
+<blockquote cite="http://example.com//foo"></blockquote><!-- path-uFEFF -->
+<blockquote cite="wss:/example.com/"></blockquote><!-- scheme-wss-single-slash -->
+<blockquote cite="http://foo/abcd#foo?bar"></blockquote><!-- fragment-contains-question-mark -->
+<blockquote cite=":#"></blockquote><!-- path-leading-colon-hash-relative -->
+<blockquote cite="http://example.com/foo%91"></blockquote><!-- path-percent-encoded-u0091 -->
+<blockquote cite="c:/foo"></blockquote><!-- scheme-private-single-letter -->
+<blockquote cite=":foo.com"></blockquote><!-- path-leading-colon-chars-relative -->
+<blockquote cite="http://你好你好"></blockquote><!-- host-idn-unicode-han -->
+<blockquote cite="http://example.com/foo#💩"></blockquote><!-- fragment-contains-pile-of-poo -->
+<blockquote cite="file:"></blockquote><!-- scheme-file-scheme-only -->
+<blockquote cite="#β"></blockquote><!-- fragment-non-ascii-relative -->
+<blockquote cite="foo:/bar.com/"></blockquote><!-- scheme-private-path -->
+<blockquote cite="http://f:0/c"></blockquote><!-- port-0 -->
+<blockquote cite="#;?"></blockquote><!-- fragment-semicolon-question-mark-relative -->
+<blockquote cite="http://Go.com"></blockquote><!-- host-fullwidth -->
+<blockquote cite="http://@www.example.com"></blockquote><!-- userinfo-empty -->
+<blockquote cite="http://example.com/‮/foo/‭/bar"></blockquote><!-- path-u202E-u202D -->
+<blockquote cite="http://[2001::1]"></blockquote><!-- host-ipv6 -->
+<blockquote cite="💩http://foo"></blockquote><!-- path-starts-with-pile-of-poo -->
+<blockquote cite="http://foo/abcd?efgh?ijkl"></blockquote><!-- query-contains-question-mark -->
+<blockquote cite="//foo/bar"></blockquote><!-- scheme-schemeless-relative -->
+<blockquote cite="ftps:/example.com/"></blockquote><!-- scheme-ftps-single-slash -->
+<blockquote cite="http://foo.com:b@d/"></blockquote><!-- userinfo-username-non-alpha -->
+<blockquote cite=":a"></blockquote><!-- path-leading-colon-letter-relative -->
+<blockquote cite="/"></blockquote><!-- path-slash-only-relative -->
+<blockquote cite="http://example.com/foo?💩"></blockquote><!-- query-contains-pile-of-poo -->
+<blockquote cite="http://f:00000000000000000000080/c"></blockquote><!-- port-00000000000000000000080 -->
+<blockquote cite="file://"></blockquote><!-- scheme-file-slash-slash-only -->
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/fragment-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/fragment-backslash-novalid.html
new file mode 100644
index 00000000000..3d547007028
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/fragment-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: fragment-backslash</title>
+<blockquote cite="#\"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/fragment-contains-hash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/fragment-contains-hash-novalid.html
new file mode 100644
index 00000000000..d754a5f0eea
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/fragment-contains-hash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: fragment-contains-hash</title>
+<blockquote cite="http://foo/path#f#g"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/fragment-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/fragment-leading-space-novalid.html
new file mode 100644
index 00000000000..d5943ed30c7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/fragment-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: fragment-leading-space</title>
+<blockquote cite="http://f:21/b# e"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-cr-novalid.html
new file mode 100644
index 00000000000..ca67dfd5dec
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-cr</title>
+<blockquote cite="http://example. org"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-double-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-double-percent-encoded-novalid.html
new file mode 100644
index 00000000000..9fd5b80a673
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-double-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-double-percent-encoded</title>
+<blockquote cite="http://%41.com"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-double-percent-encoded-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-double-percent-encoded-percent-encoded-novalid.html
new file mode 100644
index 00000000000..b88dd6848dc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-double-percent-encoded-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-double-percent-encoded-percent-encoded</title>
+<blockquote cite="http://%ef%bc%85%ef%bc%94%ef%bc%91.com"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-empty-novalid.html
new file mode 100644
index 00000000000..d5745e8bb94
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-empty</title>
+<blockquote cite="http://"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-empty-userinfo-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-empty-userinfo-empty-novalid.html
new file mode 100644
index 00000000000..5cfe6d18a5f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-empty-userinfo-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-empty-userinfo-empty</title>
+<blockquote cite="http://@/www.example.com"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-empty-with-userinfo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-empty-with-userinfo-novalid.html
new file mode 100644
index 00000000000..c6b78986aa9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-empty-with-userinfo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-empty-with-userinfo</title>
+<blockquote cite="http://user:pass@/"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-hostname-in-brackets-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-hostname-in-brackets-novalid.html
new file mode 100644
index 00000000000..f3fedf4aea5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-hostname-in-brackets-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-hostname-in-brackets</title>
+<blockquote cite="http://[www.google.com]/"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-invalid-unicode-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-invalid-unicode-novalid.html
new file mode 100644
index 00000000000..c898f0a0d31
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-invalid-unicode-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-invalid-unicode</title>
+<blockquote cite="http://﷐zyx.com"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-invalid-unicode-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-invalid-unicode-percent-encoded-novalid.html
new file mode 100644
index 00000000000..5701cee95cf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-invalid-unicode-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-invalid-unicode-percent-encoded</title>
+<blockquote cite="http://%ef%b7%90zyx.com"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-newline-novalid.html
new file mode 100644
index 00000000000..8d82bfb3c17
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-newline</title>
+<blockquote cite="http://example.
+org"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-space-novalid.html
new file mode 100644
index 00000000000..16a942e4a63
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-space</title>
+<blockquote cite="http://example .org"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-square-brackets-port-contains-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-square-brackets-port-contains-colon-novalid.html
new file mode 100644
index 00000000000..30ee45d591e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-square-brackets-port-contains-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-square-brackets-port-contains-colon</title>
+<blockquote cite="http://[1::2]:3:4"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-tab-novalid.html
new file mode 100644
index 00000000000..2ce8d10bfe3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-tab</title>
+<blockquote cite="http://example .org"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-u0000-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-u0000-percent-encoded-novalid.html
new file mode 100644
index 00000000000..f9366ece0ca
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-u0000-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-u0000-percent-encoded</title>
+<blockquote cite="http://%00.com"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-u0000-percent-encoded-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-u0000-percent-encoded-percent-encoded-novalid.html
new file mode 100644
index 00000000000..be3016d9fce
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/host-u0000-percent-encoded-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-u0000-percent-encoded-percent-encoded</title>
+<blockquote cite="http://%ef%bc%85%ef%bc%90%ef%bc%90.com"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/path-bare-percent-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/path-bare-percent-sign-novalid.html
new file mode 100644
index 00000000000..2bf77ec03db
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/path-bare-percent-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: path-bare-percent-sign</title>
+<blockquote cite="http://example.com/foo%"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/path-contains-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/path-contains-space-novalid.html
new file mode 100644
index 00000000000..59bbbfecf90
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/path-contains-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: path-contains-space</title>
+<blockquote cite="/a/ /c"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/path-leading-backslash-at-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/path-leading-backslash-at-sign-novalid.html
new file mode 100644
index 00000000000..6aa8ada46ca
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/path-leading-backslash-at-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: path-leading-backslash-at-sign</title>
+<blockquote cite="http://foo.com/\@"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/path-leading-colon-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/path-leading-colon-backslash-novalid.html
new file mode 100644
index 00000000000..4b055ab47bc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/path-leading-colon-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: path-leading-colon-backslash</title>
+<blockquote cite=":\"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/path-leading-colon-chars-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/path-leading-colon-chars-backslash-novalid.html
new file mode 100644
index 00000000000..d87b41796e1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/path-leading-colon-chars-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: path-leading-colon-chars-backslash</title>
+<blockquote cite=":foo.com\"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/path-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/path-leading-space-novalid.html
new file mode 100644
index 00000000000..3d719228d2f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/path-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: path-leading-space</title>
+<blockquote cite="http://f:21/ b"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/path-percent-encoded-malformed-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/path-percent-encoded-malformed-novalid.html
new file mode 100644
index 00000000000..28f0fb78fed
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/path-percent-encoded-malformed-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: path-percent-encoded-malformed</title>
+<blockquote cite="http://example.com/foo/%2e%2"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/path-relative-square-brackets-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/path-relative-square-brackets-novalid.html
new file mode 100644
index 00000000000..75717a0aa9d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/path-relative-square-brackets-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: path-relative-square-brackets</title>
+<blockquote cite="[61:24:74]:98"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/path-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/path-tab-novalid.html
new file mode 100644
index 00000000000..a963adb9b09
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/path-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: path-tab</title>
+<blockquote cite="http://example.com/foo bar"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/path-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/path-trailing-space-novalid.html
new file mode 100644
index 00000000000..cd6b5cf08f4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/path-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: path-trailing-space</title>
+<blockquote cite="http://f:21/b ?"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/path-u0091-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/path-u0091-novalid.html
new file mode 100644
index 00000000000..d0eb4bb4476
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/path-u0091-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: path-u0091</title>
+<blockquote cite="http://example.com/foo‘"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/port-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/port-cr-novalid.html
new file mode 100644
index 00000000000..9a50760ebf6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/port-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: port-cr</title>
+<blockquote cite="http://f: /c"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/port-leading-colon-bracket-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/port-leading-colon-bracket-colon-novalid.html
new file mode 100644
index 00000000000..083eb40ceef
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/port-leading-colon-bracket-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: port-leading-colon-bracket-colon</title>
+<blockquote cite="http://2001::1]:80"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/port-leading-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/port-leading-colon-novalid.html
new file mode 100644
index 00000000000..439411bcfe7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/port-leading-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: port-leading-colon</title>
+<blockquote cite="http://2001::1"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/port-leading-dash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/port-leading-dash-novalid.html
new file mode 100644
index 00000000000..bb5fa178bfa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/port-leading-dash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: port-leading-dash</title>
+<blockquote cite="http://foo:-80/"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/port-multiple-letters-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/port-multiple-letters-novalid.html
new file mode 100644
index 00000000000..51f552ade49
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/port-multiple-letters-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: port-multiple-letters</title>
+<blockquote cite="http://f:fifty-two/c"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/port-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/port-newline-novalid.html
new file mode 100644
index 00000000000..47b709ba2de
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/port-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: port-newline</title>
+<blockquote cite="http://f:
+/c"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/port-single-letter-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/port-single-letter-novalid.html
new file mode 100644
index 00000000000..3764232b849
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/port-single-letter-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: port-single-letter</title>
+<blockquote cite="http://f:b/c"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/port-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/port-space-novalid.html
new file mode 100644
index 00000000000..19d23729135
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/port-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: port-space</title>
+<blockquote cite="http://f: /c"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/port-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/port-tab-novalid.html
new file mode 100644
index 00000000000..04330da7676
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/port-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: port-tab</title>
+<blockquote cite="http://f: /c"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/query-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/query-leading-space-novalid.html
new file mode 100644
index 00000000000..5d28efaf439
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/query-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: query-leading-space</title>
+<blockquote cite="http://f:21/b? d"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/query-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/query-trailing-space-novalid.html
new file mode 100644
index 00000000000..ce0f5ff053b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/query-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: query-trailing-space</title>
+<blockquote cite="http://f:21/b?d #"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-data-contains-fragment-haswarn.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-data-contains-fragment-haswarn.html
new file mode 100644
index 00000000000..0eef9512a3a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-data-contains-fragment-haswarn.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>data:text/html,test#test warning: scheme-data-contains-fragment</title>
+<blockquote cite="data:text/html,test#test"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-data-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-data-single-slash-novalid.html
new file mode 100644
index 00000000000..ac25010256c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-data-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-data-single-slash</title>
+<blockquote cite="data:/example.com/"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-file-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-file-backslash-novalid.html
new file mode 100644
index 00000000000..f00000b9bd6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-file-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-file-backslash</title>
+<blockquote cite="file:c:\foo\bar.html"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-file-single-slash-c-bar-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-file-single-slash-c-bar-novalid.html
new file mode 100644
index 00000000000..cbf91993e3e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-file-single-slash-c-bar-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-file-single-slash-c-bar</title>
+<blockquote cite="file:/C|/foo/bar"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-file-triple-slash-c-bar-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-file-triple-slash-c-bar-novalid.html
new file mode 100644
index 00000000000..b5a84d960cf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-file-triple-slash-c-bar-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-file-triple-slash-c-bar</title>
+<blockquote cite="file:///C|/foo/bar"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-ftp-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-ftp-no-slash-novalid.html
new file mode 100644
index 00000000000..191211f0fd4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-ftp-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-ftp-no-slash</title>
+<blockquote cite="ftp:example.com/"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-ftp-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-ftp-single-slash-novalid.html
new file mode 100644
index 00000000000..5ba4d67794a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-ftp-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-ftp-single-slash</title>
+<blockquote cite="ftp:/example.com/"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-http-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-http-backslash-novalid.html
new file mode 100644
index 00000000000..9ba1e317b4e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-http-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-http-backslash</title>
+<blockquote cite="http:\\foo.com\"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-http-no-slash-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-http-no-slash-colon-novalid.html
new file mode 100644
index 00000000000..ba549fc28c0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-http-no-slash-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-http-no-slash-colon</title>
+<blockquote cite="http::@c:29"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-http-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-http-no-slash-novalid.html
new file mode 100644
index 00000000000..e103deb13b6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-http-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-http-no-slash</title>
+<blockquote cite="http:foo.com"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-http-no-slash-square-bracket-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-http-no-slash-square-bracket-novalid.html
new file mode 100644
index 00000000000..744a4f53260
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-http-no-slash-square-bracket-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-http-no-slash-square-bracket</title>
+<blockquote cite="http:[61:27]/:foo"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-http-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-http-single-slash-novalid.html
new file mode 100644
index 00000000000..2b787b2736d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-http-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-http-single-slash</title>
+<blockquote cite="http:/example.com/"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-https-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-https-no-slash-novalid.html
new file mode 100644
index 00000000000..7a09e93d5e5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-https-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-https-no-slash</title>
+<blockquote cite="https:example.com/"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-https-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-https-single-slash-novalid.html
new file mode 100644
index 00000000000..ef32ee1e739
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-https-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-https-single-slash</title>
+<blockquote cite="https:/example.com/"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-javascript-no-slash-malformed-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-javascript-no-slash-malformed-novalid.html
new file mode 100644
index 00000000000..71df3f36e1d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-javascript-no-slash-malformed-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-javascript-no-slash-malformed</title>
+<blockquote cite="javascript:example.com/"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-trailing-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-trailing-cr-novalid.html
new file mode 100644
index 00000000000..cafe0190b56
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-trailing-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-trailing-cr</title>
+<blockquote cite="a: foo.com"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-trailing-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-trailing-newline-novalid.html
new file mode 100644
index 00000000000..075d073f0e1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-trailing-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-trailing-newline</title>
+<blockquote cite="a:
+foo.com"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-trailing-space-novalid.html
new file mode 100644
index 00000000000..1ccfb41ae7f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-trailing-space</title>
+<blockquote cite="a: foo.com"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-trailing-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-trailing-tab-novalid.html
new file mode 100644
index 00000000000..2c81a25df1c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/scheme-trailing-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-trailing-tab</title>
+<blockquote cite="a: foo.com"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/userinfo-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/userinfo-backslash-novalid.html
new file mode 100644
index 00000000000..dc16d1467bd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/userinfo-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: userinfo-backslash</title>
+<blockquote cite="http://a\b:c\d@foo.com"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/userinfo-password-bad-chars-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/userinfo-password-bad-chars-novalid.html
new file mode 100644
index 00000000000..4b5c9826d8c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/userinfo-password-bad-chars-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: userinfo-password-bad-chars</title>
+<blockquote cite="http://&a:foo(b]c@d:2/"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/userinfo-password-contains-pile-of-poo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/userinfo-password-contains-pile-of-poo-novalid.html
new file mode 100644
index 00000000000..52388a2c20a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/userinfo-password-contains-pile-of-poo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: userinfo-password-contains-pile-of-poo</title>
+<blockquote cite="http://foo:💩@example.com"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/userinfo-username-contains-at-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/userinfo-username-contains-at-sign-novalid.html
new file mode 100644
index 00000000000..76b235fbc5f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/userinfo-username-contains-at-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: userinfo-username-contains-at-sign</title>
+<blockquote cite="http://::@c@d:2"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/userinfo-username-contains-pile-of-poo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/userinfo-username-contains-pile-of-poo-novalid.html
new file mode 100644
index 00000000000..cdf71cc0b48
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/cite/userinfo-username-contains-pile-of-poo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: userinfo-username-contains-pile-of-poo</title>
+<blockquote cite="http://💩:foo@example.com"></blockquote>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/model-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/model-isvalid.html
new file mode 100644
index 00000000000..62497d33d77
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/model-isvalid.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;blockquote&gt;</title>
+</head>
+<body>
+ <!-- is block, contains blocks -->
+ <blockquote cite="url" class="class" id="id" lang="en">
+ <h2>header</h2>
+ <p>text</p>
+ <p>text2</p>
+ </blockquote>
+
+ <!-- can contain interactive -->
+ <blockquote><p><a>text</a></p></blockquote>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/model-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/model-novalid.html
new file mode 100644
index 00000000000..2985ed899bb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/blockquote/model-novalid.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;blockquote&gt;</title>
+</head>
+<body>
+ <!-- is block, contains blocks -->
+ <blockquote cite="url" class="class" id="id" lang="en">
+ <h2>header</h2>
+ <p>text</p>
+ <p>text2</p>
+ </blockquote>
+
+ <!-- is structured inline -->
+ <p>paragraph
+ <blockquote>
+ <h2>header</h2>
+ <p>text</p>
+ </blockquote>
+ </p>
+
+ <!-- can contain interactive -->
+ <blockquote><p><a>text</a></p></blockquote>
+ <p>paragraph
+ <blockquote>
+ <p><a>text</a></p>
+ </blockquote>
+ </p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/br/model-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/br/model-isvalid.html
new file mode 100644
index 00000000000..cdde875d6d1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/br/model-isvalid.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;br&gt;</title>
+</head>
+<body>
+ <!-- is structured inline -->
+ <p>text <br class="class" lang="en"></p>
+
+ <!-- is strictly inline -->
+ <p>text <dfn><br class="class" lang="en"></dfn></p>
+
+ <!-- must be empty -->
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/br/model-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/br/model-novalid.html
new file mode 100644
index 00000000000..c27c261f8f6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/br/model-novalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;br&gt;</title>
+</head>
+<body>
+ <br></br>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction-empty-novalid.html
new file mode 100644
index 00000000000..7c324e5f1f0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>empty formaction is not valid</title>
+<button formaction=""></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction-isvalid.html
new file mode 100644
index 00000000000..70e3ded983c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction-isvalid.html
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid formaction</title>
+<button formaction="file:///"></button><!-- scheme-file-slash-slash-slash-only -->
+<button formaction="http://a:@www.example.com"></button><!-- userinfo-password-empty -->
+<button formaction="foo://///////"></button><!-- scheme-private-path-leading-slashes-only -->
+<button formaction="file://abc|/foo/bar"></button><!-- scheme-file-slash-slash-abc-bar -->
+<button formaction="/a/b/c"></button><!-- path-simple-relative -->
+<button formaction="http://example.com/你好你好"></button><!-- path-unicode-han -->
+<button formaction="/a/%2f/c"></button><!-- path-percent-encoded-slash-plus-slashes-relative -->
+<button formaction="http://f:/c"></button><!-- port-none-but-colon -->
+<button formaction="http://example.com/foo%41%7a"></button><!-- path-percent-encoded-multiple -->
+<button formaction="http://192.168.0.257/"></button><!-- host-IP-address-broken -->
+<button formaction="madeupscheme:example.com/"></button><!-- scheme-private-no-slash -->
+<button formaction="?"></button><!-- query-empty-no-path-relative -->
+<button formaction="http://example.com/%20foo"></button><!-- path-percent-encoded-space -->
+<button formaction="mailto:/example.com/"></button><!-- scheme-mailto-single-slash -->
+<button formaction="::"></button><!-- path-leading-colon-colon-relative -->
+<button formaction="http://example.com/%3A%3a%3C%3c"></button><!-- path-percent-encoded-mixed-case -->
+<button formaction="http://user:pass@foo:21/bar;par?b#c"></button><!-- userinfo -->
+<button formaction="ws:/example.com/"></button><!-- scheme-ws-single-slash -->
+<button formaction="foo://"></button><!-- scheme-private-slash-slash -->
+<button formaction="#"></button><!-- fragment-empty-hash-only-no-path-relative -->
+<button formaction="http://f:00000000000000/c"></button><!-- port-00000000000000 -->
+<button formaction="foo:////://///"></button><!-- scheme-private-path-leading-slashes-colon-slashes -->
+<button formaction=":23"></button><!-- path-leading-colon-number-relative -->
+<button formaction="foo:/"></button><!-- scheme-private-slash -->
+<button formaction="http://💩"></button><!-- host-is-pile-of-poo -->
+<button formaction="file:test"></button><!-- scheme-file-no-slash -->
+<button formaction="file://C|/foo/bar"></button><!-- scheme-file-slash-slash-c-bar -->
+<button formaction="#/"></button><!-- fragment-slash-relative -->
+<button formaction="http://192.0x00A80001"></button><!-- host-192.0x00A80001 -->
+<button formaction="foo.com"></button><!-- scheme-none-relative -->
+<button formaction="http💩//:foo"></button><!-- path-contains-pile-of-poo -->
+<button formaction="File://foo/bar.html"></button><!-- scheme-file-uppercase -->
+<button formaction=":/"></button><!-- path-leading-colon-slash-relative -->
+<button formaction="http://www.foo。bar.com"></button><!-- host-exotic-dot -->
+<button formaction="http://GOO​⁠goo.com"></button><!-- host-exotic-whitespace -->
+<button formaction="file:///foo/bar.txt"></button><!-- scheme-file-host-empty -->
+<button formaction="javascript:/example.com/"></button><!-- scheme-javascript-single-slash -->
+<button formaction="gopher:/example.com/"></button><!-- scheme-gopher-single-slash -->
+<button formaction="ftps:example.com/"></button><!-- scheme-ftps-no-slash -->
+<button formaction="file://server/foo/bar"></button><!-- scheme-file-host-included -->
+<button formaction="http://example.com/foo%00"></button><!-- path-percent-encoded-u0000 -->
+<button formaction="a:foo.com"></button><!-- scheme-private -->
+<button formaction=":"></button><!-- path-colon-relative -->
+<button formaction="http://:b@www.example.com"></button><!-- userinfo-user-empty -->
+<button formaction="file:/"></button><!-- scheme-file-slash-only -->
+<button formaction="wss:example.com/"></button><!-- scheme-wss-no-slash -->
+<button formaction="::23"></button><!-- path-colon-colon-number-relative -->
+<button formaction="/a%2fc"></button><!-- path-percent-encoded-slash-relative -->
+<button formaction="http://a:b@c:29/d"></button><!-- userinfo-host-port-path -->
+<button formaction="gopher:example.com/"></button><!-- scheme-gopher-no-slash -->
+<button formaction="madeupscheme:/example.com/"></button><!-- scheme-private-single-slash -->
+<button formaction="mailto:example.com/"></button><!-- scheme-mailto-no-slash -->
+<button formaction="http://%25DOMAIN:foobar@foodomain.com"></button><!-- userinfo-username-contains-percent-encoded -->
+<button formaction="/:23"></button><!-- path-slash-colon-number-relative -->
+<button formaction="foo://///////bar.com/"></button><!-- scheme-private-path-leading-slashes-chars -->
+<button formaction="http://[2001::1]:80"></button><!-- host-ipv6-port -->
+<button formaction="data:text/plain,foo"></button><!-- scheme-data-no-slash -->
+<button formaction="http://example.com/foo/%2e"></button><!-- path-percent-encoded-dot -->
+<button formaction="file:/example.com/"></button><!-- scheme-file-single-slash -->
+<button formaction="http://example.com/©zbar"></button><!-- path-non-ascii -->
+<button formaction="http://example.com//foo"></button><!-- path-uFEFF -->
+<button formaction="wss:/example.com/"></button><!-- scheme-wss-single-slash -->
+<button formaction="http://foo/abcd#foo?bar"></button><!-- fragment-contains-question-mark -->
+<button formaction=":#"></button><!-- path-leading-colon-hash-relative -->
+<button formaction="http://example.com/foo%91"></button><!-- path-percent-encoded-u0091 -->
+<button formaction="c:/foo"></button><!-- scheme-private-single-letter -->
+<button formaction=":foo.com"></button><!-- path-leading-colon-chars-relative -->
+<button formaction="http://你好你好"></button><!-- host-idn-unicode-han -->
+<button formaction="http://example.com/foo#💩"></button><!-- fragment-contains-pile-of-poo -->
+<button formaction="file:"></button><!-- scheme-file-scheme-only -->
+<button formaction="#β"></button><!-- fragment-non-ascii-relative -->
+<button formaction="foo:/bar.com/"></button><!-- scheme-private-path -->
+<button formaction="http://f:0/c"></button><!-- port-0 -->
+<button formaction="#;?"></button><!-- fragment-semicolon-question-mark-relative -->
+<button formaction="http://Go.com"></button><!-- host-fullwidth -->
+<button formaction="http://@www.example.com"></button><!-- userinfo-empty -->
+<button formaction="http://example.com/‮/foo/‭/bar"></button><!-- path-u202E-u202D -->
+<button formaction="http://[2001::1]"></button><!-- host-ipv6 -->
+<button formaction="💩http://foo"></button><!-- path-starts-with-pile-of-poo -->
+<button formaction="http://foo/abcd?efgh?ijkl"></button><!-- query-contains-question-mark -->
+<button formaction="//foo/bar"></button><!-- scheme-schemeless-relative -->
+<button formaction="ftps:/example.com/"></button><!-- scheme-ftps-single-slash -->
+<button formaction="http://foo.com:b@d/"></button><!-- userinfo-username-non-alpha -->
+<button formaction=":a"></button><!-- path-leading-colon-letter-relative -->
+<button formaction="/"></button><!-- path-slash-only-relative -->
+<button formaction="http://example.com/foo?💩"></button><!-- query-contains-pile-of-poo -->
+<button formaction="http://f:00000000000000000000080/c"></button><!-- port-00000000000000000000080 -->
+<button formaction="file://"></button><!-- scheme-file-slash-slash-only -->
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction-whitespace-only-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction-whitespace-only-novalid.html
new file mode 100644
index 00000000000..37b4f02a48d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction-whitespace-only-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>empty formaction is not valid</title>
+<button formaction="
+"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/fragment-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/fragment-backslash-novalid.html
new file mode 100644
index 00000000000..f8dd366818e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/fragment-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: fragment-backslash</title>
+<button formaction="#\"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/fragment-contains-hash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/fragment-contains-hash-novalid.html
new file mode 100644
index 00000000000..34aa42935cc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/fragment-contains-hash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: fragment-contains-hash</title>
+<button formaction="http://foo/path#f#g"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/fragment-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/fragment-leading-space-novalid.html
new file mode 100644
index 00000000000..d5571acf0df
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/fragment-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: fragment-leading-space</title>
+<button formaction="http://f:21/b# e"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-cr-novalid.html
new file mode 100644
index 00000000000..99b23b4a79a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: host-cr</title>
+<button formaction="http://example. org"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-double-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-double-percent-encoded-novalid.html
new file mode 100644
index 00000000000..f0a118b85a0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-double-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: host-double-percent-encoded</title>
+<button formaction="http://%41.com"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-double-percent-encoded-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-double-percent-encoded-percent-encoded-novalid.html
new file mode 100644
index 00000000000..71cc7d12ba6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-double-percent-encoded-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: host-double-percent-encoded-percent-encoded</title>
+<button formaction="http://%ef%bc%85%ef%bc%94%ef%bc%91.com"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-empty-novalid.html
new file mode 100644
index 00000000000..728cf8754f0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: host-empty</title>
+<button formaction="http://"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-empty-userinfo-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-empty-userinfo-empty-novalid.html
new file mode 100644
index 00000000000..04279b9598e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-empty-userinfo-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: host-empty-userinfo-empty</title>
+<button formaction="http://@/www.example.com"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-empty-with-userinfo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-empty-with-userinfo-novalid.html
new file mode 100644
index 00000000000..5dea89f1193
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-empty-with-userinfo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: host-empty-with-userinfo</title>
+<button formaction="http://user:pass@/"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-hostname-in-brackets-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-hostname-in-brackets-novalid.html
new file mode 100644
index 00000000000..477d3871b24
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-hostname-in-brackets-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: host-hostname-in-brackets</title>
+<button formaction="http://[www.google.com]/"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-invalid-unicode-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-invalid-unicode-novalid.html
new file mode 100644
index 00000000000..52b2381dfe1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-invalid-unicode-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: host-invalid-unicode</title>
+<button formaction="http://﷐zyx.com"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-invalid-unicode-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-invalid-unicode-percent-encoded-novalid.html
new file mode 100644
index 00000000000..6728b889d99
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-invalid-unicode-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: host-invalid-unicode-percent-encoded</title>
+<button formaction="http://%ef%b7%90zyx.com"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-newline-novalid.html
new file mode 100644
index 00000000000..7906dd26781
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: host-newline</title>
+<button formaction="http://example.
+org"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-space-novalid.html
new file mode 100644
index 00000000000..4aee6d7c4b6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: host-space</title>
+<button formaction="http://example .org"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-square-brackets-port-contains-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-square-brackets-port-contains-colon-novalid.html
new file mode 100644
index 00000000000..27cb1909010
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-square-brackets-port-contains-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: host-square-brackets-port-contains-colon</title>
+<button formaction="http://[1::2]:3:4"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-tab-novalid.html
new file mode 100644
index 00000000000..e4bc59fffc5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: host-tab</title>
+<button formaction="http://example .org"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-u0000-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-u0000-percent-encoded-novalid.html
new file mode 100644
index 00000000000..3d704263998
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-u0000-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: host-u0000-percent-encoded</title>
+<button formaction="http://%00.com"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-u0000-percent-encoded-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-u0000-percent-encoded-percent-encoded-novalid.html
new file mode 100644
index 00000000000..29836a9b8cc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/host-u0000-percent-encoded-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: host-u0000-percent-encoded-percent-encoded</title>
+<button formaction="http://%ef%bc%85%ef%bc%90%ef%bc%90.com"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/path-bare-percent-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/path-bare-percent-sign-novalid.html
new file mode 100644
index 00000000000..09febe38a5f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/path-bare-percent-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: path-bare-percent-sign</title>
+<button formaction="http://example.com/foo%"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/path-contains-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/path-contains-space-novalid.html
new file mode 100644
index 00000000000..a8e6d07bfb6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/path-contains-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: path-contains-space</title>
+<button formaction="/a/ /c"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/path-leading-backslash-at-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/path-leading-backslash-at-sign-novalid.html
new file mode 100644
index 00000000000..f2c1e3bc4d2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/path-leading-backslash-at-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: path-leading-backslash-at-sign</title>
+<button formaction="http://foo.com/\@"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/path-leading-colon-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/path-leading-colon-backslash-novalid.html
new file mode 100644
index 00000000000..9fbe511ec12
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/path-leading-colon-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: path-leading-colon-backslash</title>
+<button formaction=":\"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/path-leading-colon-chars-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/path-leading-colon-chars-backslash-novalid.html
new file mode 100644
index 00000000000..87158199184
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/path-leading-colon-chars-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: path-leading-colon-chars-backslash</title>
+<button formaction=":foo.com\"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/path-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/path-leading-space-novalid.html
new file mode 100644
index 00000000000..eda9780b945
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/path-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: path-leading-space</title>
+<button formaction="http://f:21/ b"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/path-percent-encoded-malformed-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/path-percent-encoded-malformed-novalid.html
new file mode 100644
index 00000000000..d3d373ad8fe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/path-percent-encoded-malformed-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: path-percent-encoded-malformed</title>
+<button formaction="http://example.com/foo/%2e%2"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/path-relative-square-brackets-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/path-relative-square-brackets-novalid.html
new file mode 100644
index 00000000000..afb7e3032a0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/path-relative-square-brackets-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: path-relative-square-brackets</title>
+<button formaction="[61:24:74]:98"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/path-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/path-tab-novalid.html
new file mode 100644
index 00000000000..85313dc98b6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/path-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: path-tab</title>
+<button formaction="http://example.com/foo bar"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/path-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/path-trailing-space-novalid.html
new file mode 100644
index 00000000000..4b47774e3a0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/path-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: path-trailing-space</title>
+<button formaction="http://f:21/b ?"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/path-u0091-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/path-u0091-novalid.html
new file mode 100644
index 00000000000..cc3929c6adf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/path-u0091-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: path-u0091</title>
+<button formaction="http://example.com/foo‘"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/port-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/port-cr-novalid.html
new file mode 100644
index 00000000000..6596879d57f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/port-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: port-cr</title>
+<button formaction="http://f: /c"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/port-leading-colon-bracket-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/port-leading-colon-bracket-colon-novalid.html
new file mode 100644
index 00000000000..2bda92d12f1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/port-leading-colon-bracket-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: port-leading-colon-bracket-colon</title>
+<button formaction="http://2001::1]:80"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/port-leading-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/port-leading-colon-novalid.html
new file mode 100644
index 00000000000..c5f0924d870
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/port-leading-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: port-leading-colon</title>
+<button formaction="http://2001::1"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/port-leading-dash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/port-leading-dash-novalid.html
new file mode 100644
index 00000000000..e0e1a6bd375
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/port-leading-dash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: port-leading-dash</title>
+<button formaction="http://foo:-80/"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/port-multiple-letters-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/port-multiple-letters-novalid.html
new file mode 100644
index 00000000000..8a01f322ecc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/port-multiple-letters-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: port-multiple-letters</title>
+<button formaction="http://f:fifty-two/c"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/port-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/port-newline-novalid.html
new file mode 100644
index 00000000000..088183e5de9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/port-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: port-newline</title>
+<button formaction="http://f:
+/c"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/port-single-letter-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/port-single-letter-novalid.html
new file mode 100644
index 00000000000..b73404884f3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/port-single-letter-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: port-single-letter</title>
+<button formaction="http://f:b/c"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/port-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/port-space-novalid.html
new file mode 100644
index 00000000000..1f0886661c4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/port-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: port-space</title>
+<button formaction="http://f: /c"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/port-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/port-tab-novalid.html
new file mode 100644
index 00000000000..69ab282abf6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/port-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: port-tab</title>
+<button formaction="http://f: /c"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/query-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/query-leading-space-novalid.html
new file mode 100644
index 00000000000..a18576e99cb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/query-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: query-leading-space</title>
+<button formaction="http://f:21/b? d"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/query-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/query-trailing-space-novalid.html
new file mode 100644
index 00000000000..f26027f9cd2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/query-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: query-trailing-space</title>
+<button formaction="http://f:21/b?d #"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-data-contains-fragment-haswarn.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-data-contains-fragment-haswarn.html
new file mode 100644
index 00000000000..3e48f2db484
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-data-contains-fragment-haswarn.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>data:text/html,test#test warning: scheme-data-contains-fragment</title>
+<button formaction="data:text/html,test#test"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-data-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-data-single-slash-novalid.html
new file mode 100644
index 00000000000..612d2001915
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-data-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: scheme-data-single-slash</title>
+<button formaction="data:/example.com/"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-file-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-file-backslash-novalid.html
new file mode 100644
index 00000000000..63d96e3b012
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-file-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: scheme-file-backslash</title>
+<button formaction="file:c:\foo\bar.html"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-file-single-slash-c-bar-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-file-single-slash-c-bar-novalid.html
new file mode 100644
index 00000000000..85cf8539b52
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-file-single-slash-c-bar-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: scheme-file-single-slash-c-bar</title>
+<button formaction="file:/C|/foo/bar"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-file-triple-slash-c-bar-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-file-triple-slash-c-bar-novalid.html
new file mode 100644
index 00000000000..901f6b05fa7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-file-triple-slash-c-bar-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: scheme-file-triple-slash-c-bar</title>
+<button formaction="file:///C|/foo/bar"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-ftp-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-ftp-no-slash-novalid.html
new file mode 100644
index 00000000000..1f094e3fc73
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-ftp-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: scheme-ftp-no-slash</title>
+<button formaction="ftp:example.com/"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-ftp-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-ftp-single-slash-novalid.html
new file mode 100644
index 00000000000..98389130df0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-ftp-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: scheme-ftp-single-slash</title>
+<button formaction="ftp:/example.com/"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-http-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-http-backslash-novalid.html
new file mode 100644
index 00000000000..4bfbe65fdd6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-http-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: scheme-http-backslash</title>
+<button formaction="http:\\foo.com\"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-http-no-slash-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-http-no-slash-colon-novalid.html
new file mode 100644
index 00000000000..648420993e1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-http-no-slash-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: scheme-http-no-slash-colon</title>
+<button formaction="http::@c:29"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-http-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-http-no-slash-novalid.html
new file mode 100644
index 00000000000..146d1857205
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-http-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: scheme-http-no-slash</title>
+<button formaction="http:foo.com"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-http-no-slash-square-bracket-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-http-no-slash-square-bracket-novalid.html
new file mode 100644
index 00000000000..fe7de887798
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-http-no-slash-square-bracket-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: scheme-http-no-slash-square-bracket</title>
+<button formaction="http:[61:27]/:foo"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-http-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-http-single-slash-novalid.html
new file mode 100644
index 00000000000..b2d7ef0fb13
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-http-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: scheme-http-single-slash</title>
+<button formaction="http:/example.com/"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-https-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-https-no-slash-novalid.html
new file mode 100644
index 00000000000..85b13467b6e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-https-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: scheme-https-no-slash</title>
+<button formaction="https:example.com/"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-https-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-https-single-slash-novalid.html
new file mode 100644
index 00000000000..61ba3d6a308
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-https-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: scheme-https-single-slash</title>
+<button formaction="https:/example.com/"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-javascript-no-slash-malformed-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-javascript-no-slash-malformed-novalid.html
new file mode 100644
index 00000000000..74c1cbc8872
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-javascript-no-slash-malformed-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: scheme-javascript-no-slash-malformed</title>
+<button formaction="javascript:example.com/"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-trailing-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-trailing-cr-novalid.html
new file mode 100644
index 00000000000..098a02a7173
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-trailing-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: scheme-trailing-cr</title>
+<button formaction="a: foo.com"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-trailing-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-trailing-newline-novalid.html
new file mode 100644
index 00000000000..4aec7d6c5ba
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-trailing-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: scheme-trailing-newline</title>
+<button formaction="a:
+foo.com"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-trailing-space-novalid.html
new file mode 100644
index 00000000000..b08683c0cf3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: scheme-trailing-space</title>
+<button formaction="a: foo.com"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-trailing-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-trailing-tab-novalid.html
new file mode 100644
index 00000000000..515d31626d0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/scheme-trailing-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: scheme-trailing-tab</title>
+<button formaction="a: foo.com"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/userinfo-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/userinfo-backslash-novalid.html
new file mode 100644
index 00000000000..658db365c2a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/userinfo-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: userinfo-backslash</title>
+<button formaction="http://a\b:c\d@foo.com"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/userinfo-password-bad-chars-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/userinfo-password-bad-chars-novalid.html
new file mode 100644
index 00000000000..62d5c233128
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/userinfo-password-bad-chars-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: userinfo-password-bad-chars</title>
+<button formaction="http://&a:foo(b]c@d:2/"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/userinfo-password-contains-pile-of-poo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/userinfo-password-contains-pile-of-poo-novalid.html
new file mode 100644
index 00000000000..b20b35cc557
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/userinfo-password-contains-pile-of-poo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: userinfo-password-contains-pile-of-poo</title>
+<button formaction="http://foo:💩@example.com"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/userinfo-username-contains-at-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/userinfo-username-contains-at-sign-novalid.html
new file mode 100644
index 00000000000..9cd569d30b1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/userinfo-username-contains-at-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: userinfo-username-contains-at-sign</title>
+<button formaction="http://::@c@d:2"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/userinfo-username-contains-pile-of-poo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/userinfo-username-contains-pile-of-poo-novalid.html
new file mode 100644
index 00000000000..cde70e15eed
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/button/formaction/userinfo-username-contains-pile-of-poo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: userinfo-username-contains-pile-of-poo</title>
+<button formaction="http://💩:foo@example.com"></button>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/canvas/model-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/canvas/model-isvalid.html
new file mode 100644
index 00000000000..cff96ccfc25
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/canvas/model-isvalid.html
@@ -0,0 +1,4 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>canvas with flow content and flow parent</title>
+<div><canvas><p>foo</p></canvas></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/canvas/model-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/canvas/model-novalid.html
new file mode 100644
index 00000000000..34a7e5ba5c2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/canvas/model-novalid.html
@@ -0,0 +1,4 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>canvas with flow content and phrasing parent</title>
+<span><canvas><p>foo</p></canvas></span>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/cite/model-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/cite/model-isvalid.html
new file mode 100644
index 00000000000..60fc8b74438
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/cite/model-isvalid.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;cite&gt;</title>
+</head>
+<body>
+ <!-- is structured inline -->
+ <p><cite class="class" lang="en">text</cite></p>
+
+ <!-- is strictly inline -->
+ <p><dfn><cite class="class" lang="en">text</cite></dfn></p>
+
+ <!-- can be empty -->
+ <p>text <cite></cite></p>
+ <p>text <dfn><cite></cite></dfn></p>
+
+ <!-- can contain interactive -->
+ <p><cite><a>text</a></cite></p>
+ <p><dfn><cite><a>text</a></cite></dfn></p>
+
+ <!-- cannot contain structured inline -->
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/cite/model-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/cite/model-novalid.html
new file mode 100644
index 00000000000..f1070dc4544
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/cite/model-novalid.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;cite&gt;</title>
+</head>
+<body>
+ <!-- not a block -->
+ <cite>text</cite>
+
+ <!-- cannot contain structured inline -->
+ <p><cite><ul><li>text</li></ul></cite></p>
+
+ <!-- cannot contain interactive if parent forbids interactive -->
+ <p><a><cite><a>text</a></cite></a></p>
+ <p><a><dfn><cite><a>text</a></cite></dfn></a></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/code/model-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/code/model-isvalid.html
new file mode 100644
index 00000000000..0912e07d7d5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/code/model-isvalid.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;code&gt;</title>
+</head>
+<body>
+ <!-- is structured inline -->
+ <p><code class="class" lang="en">text</code></p>
+
+ <!-- is strictly inline -->
+ <p><dfn><code class="class" lang="en">text</code></dfn></p>
+
+ <!-- can be empty -->
+ <p>text <code></code></p>
+ <p>text <dfn><code></code></dfn></p>
+
+ <!-- can contain interactive -->
+ <p><code><a>text</a></code></p>
+ <p><dfn><code><a>text</a></code></dfn></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/code/model-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/code/model-novalid.html
new file mode 100644
index 00000000000..5d473d17f0f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/code/model-novalid.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;code&gt;</title>
+</head>
+<body>
+ <!-- is structured inline -->
+ <p><code class="class" lang="en">text</code></p>
+
+ <!-- is strictly inline -->
+ <p><dfn><code class="class" lang="en">text</code></dfn></p>
+
+ <!-- can be empty -->
+ <p>text <code></code></p>
+ <p>text <dfn><code></code></dfn></p>
+
+ <!-- can contain interactive -->
+ <p><code><a>text</a></code></p>
+ <p><dfn><code><a>text</a></code></dfn></p>
+
+ <!-- cannot contain structured inline -->
+ <p><code>text <ul><li>list</li></ul> <em>elem</em></code></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite-empty-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite-empty-isvalid.html
new file mode 100644
index 00000000000..cc8201c6e4b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite-empty-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>empty cite is valid</title>
+<del cite=""></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite-isvalid.html
new file mode 100644
index 00000000000..380207babb7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite-isvalid.html
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid cite</title>
+<del cite="file:///"></del><!-- scheme-file-slash-slash-slash-only -->
+<del cite="http://a:@www.example.com"></del><!-- userinfo-password-empty -->
+<del cite="foo://///////"></del><!-- scheme-private-path-leading-slashes-only -->
+<del cite="file://abc|/foo/bar"></del><!-- scheme-file-slash-slash-abc-bar -->
+<del cite="/a/b/c"></del><!-- path-simple-relative -->
+<del cite="http://example.com/你好你好"></del><!-- path-unicode-han -->
+<del cite="/a/%2f/c"></del><!-- path-percent-encoded-slash-plus-slashes-relative -->
+<del cite="http://f:/c"></del><!-- port-none-but-colon -->
+<del cite="http://example.com/foo%41%7a"></del><!-- path-percent-encoded-multiple -->
+<del cite="http://192.168.0.257/"></del><!-- host-IP-address-broken -->
+<del cite="madeupscheme:example.com/"></del><!-- scheme-private-no-slash -->
+<del cite="?"></del><!-- query-empty-no-path-relative -->
+<del cite="http://example.com/%20foo"></del><!-- path-percent-encoded-space -->
+<del cite="mailto:/example.com/"></del><!-- scheme-mailto-single-slash -->
+<del cite="::"></del><!-- path-leading-colon-colon-relative -->
+<del cite="http://example.com/%3A%3a%3C%3c"></del><!-- path-percent-encoded-mixed-case -->
+<del cite="http://user:pass@foo:21/bar;par?b#c"></del><!-- userinfo -->
+<del cite="ws:/example.com/"></del><!-- scheme-ws-single-slash -->
+<del cite="foo://"></del><!-- scheme-private-slash-slash -->
+<del cite="#"></del><!-- fragment-empty-hash-only-no-path-relative -->
+<del cite="http://f:00000000000000/c"></del><!-- port-00000000000000 -->
+<del cite="foo:////://///"></del><!-- scheme-private-path-leading-slashes-colon-slashes -->
+<del cite=":23"></del><!-- path-leading-colon-number-relative -->
+<del cite="foo:/"></del><!-- scheme-private-slash -->
+<del cite="http://💩"></del><!-- host-is-pile-of-poo -->
+<del cite="file:test"></del><!-- scheme-file-no-slash -->
+<del cite="file://C|/foo/bar"></del><!-- scheme-file-slash-slash-c-bar -->
+<del cite="#/"></del><!-- fragment-slash-relative -->
+<del cite="http://192.0x00A80001"></del><!-- host-192.0x00A80001 -->
+<del cite="foo.com"></del><!-- scheme-none-relative -->
+<del cite="http💩//:foo"></del><!-- path-contains-pile-of-poo -->
+<del cite="File://foo/bar.html"></del><!-- scheme-file-uppercase -->
+<del cite=":/"></del><!-- path-leading-colon-slash-relative -->
+<del cite="http://www.foo。bar.com"></del><!-- host-exotic-dot -->
+<del cite="http://GOO​⁠goo.com"></del><!-- host-exotic-whitespace -->
+<del cite="file:///foo/bar.txt"></del><!-- scheme-file-host-empty -->
+<del cite="javascript:/example.com/"></del><!-- scheme-javascript-single-slash -->
+<del cite="gopher:/example.com/"></del><!-- scheme-gopher-single-slash -->
+<del cite="ftps:example.com/"></del><!-- scheme-ftps-no-slash -->
+<del cite="file://server/foo/bar"></del><!-- scheme-file-host-included -->
+<del cite="http://example.com/foo%00"></del><!-- path-percent-encoded-u0000 -->
+<del cite="a:foo.com"></del><!-- scheme-private -->
+<del cite=":"></del><!-- path-colon-relative -->
+<del cite="http://:b@www.example.com"></del><!-- userinfo-user-empty -->
+<del cite="file:/"></del><!-- scheme-file-slash-only -->
+<del cite="wss:example.com/"></del><!-- scheme-wss-no-slash -->
+<del cite="::23"></del><!-- path-colon-colon-number-relative -->
+<del cite="/a%2fc"></del><!-- path-percent-encoded-slash-relative -->
+<del cite="http://a:b@c:29/d"></del><!-- userinfo-host-port-path -->
+<del cite="gopher:example.com/"></del><!-- scheme-gopher-no-slash -->
+<del cite="madeupscheme:/example.com/"></del><!-- scheme-private-single-slash -->
+<del cite="mailto:example.com/"></del><!-- scheme-mailto-no-slash -->
+<del cite="http://%25DOMAIN:foobar@foodomain.com"></del><!-- userinfo-username-contains-percent-encoded -->
+<del cite="/:23"></del><!-- path-slash-colon-number-relative -->
+<del cite="foo://///////bar.com/"></del><!-- scheme-private-path-leading-slashes-chars -->
+<del cite="http://[2001::1]:80"></del><!-- host-ipv6-port -->
+<del cite="data:text/plain,foo"></del><!-- scheme-data-no-slash -->
+<del cite="http://example.com/foo/%2e"></del><!-- path-percent-encoded-dot -->
+<del cite="file:/example.com/"></del><!-- scheme-file-single-slash -->
+<del cite="http://example.com/©zbar"></del><!-- path-non-ascii -->
+<del cite="http://example.com//foo"></del><!-- path-uFEFF -->
+<del cite="wss:/example.com/"></del><!-- scheme-wss-single-slash -->
+<del cite="http://foo/abcd#foo?bar"></del><!-- fragment-contains-question-mark -->
+<del cite=":#"></del><!-- path-leading-colon-hash-relative -->
+<del cite="http://example.com/foo%91"></del><!-- path-percent-encoded-u0091 -->
+<del cite="c:/foo"></del><!-- scheme-private-single-letter -->
+<del cite=":foo.com"></del><!-- path-leading-colon-chars-relative -->
+<del cite="http://你好你好"></del><!-- host-idn-unicode-han -->
+<del cite="http://example.com/foo#💩"></del><!-- fragment-contains-pile-of-poo -->
+<del cite="file:"></del><!-- scheme-file-scheme-only -->
+<del cite="#β"></del><!-- fragment-non-ascii-relative -->
+<del cite="foo:/bar.com/"></del><!-- scheme-private-path -->
+<del cite="http://f:0/c"></del><!-- port-0 -->
+<del cite="#;?"></del><!-- fragment-semicolon-question-mark-relative -->
+<del cite="http://Go.com"></del><!-- host-fullwidth -->
+<del cite="http://@www.example.com"></del><!-- userinfo-empty -->
+<del cite="http://example.com/‮/foo/‭/bar"></del><!-- path-u202E-u202D -->
+<del cite="http://[2001::1]"></del><!-- host-ipv6 -->
+<del cite="💩http://foo"></del><!-- path-starts-with-pile-of-poo -->
+<del cite="http://foo/abcd?efgh?ijkl"></del><!-- query-contains-question-mark -->
+<del cite="//foo/bar"></del><!-- scheme-schemeless-relative -->
+<del cite="ftps:/example.com/"></del><!-- scheme-ftps-single-slash -->
+<del cite="http://foo.com:b@d/"></del><!-- userinfo-username-non-alpha -->
+<del cite=":a"></del><!-- path-leading-colon-letter-relative -->
+<del cite="/"></del><!-- path-slash-only-relative -->
+<del cite="http://example.com/foo?💩"></del><!-- query-contains-pile-of-poo -->
+<del cite="http://f:00000000000000000000080/c"></del><!-- port-00000000000000000000080 -->
+<del cite="file://"></del><!-- scheme-file-slash-slash-only -->
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/fragment-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/fragment-backslash-novalid.html
new file mode 100644
index 00000000000..a51b0575af5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/fragment-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: fragment-backslash</title>
+<del cite="#\"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/fragment-contains-hash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/fragment-contains-hash-novalid.html
new file mode 100644
index 00000000000..d0b217dc492
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/fragment-contains-hash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: fragment-contains-hash</title>
+<del cite="http://foo/path#f#g"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/fragment-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/fragment-leading-space-novalid.html
new file mode 100644
index 00000000000..b54fd21d288
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/fragment-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: fragment-leading-space</title>
+<del cite="http://f:21/b# e"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-cr-novalid.html
new file mode 100644
index 00000000000..2da16c9a3cc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-cr</title>
+<del cite="http://example. org"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-double-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-double-percent-encoded-novalid.html
new file mode 100644
index 00000000000..18898a53324
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-double-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-double-percent-encoded</title>
+<del cite="http://%41.com"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-double-percent-encoded-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-double-percent-encoded-percent-encoded-novalid.html
new file mode 100644
index 00000000000..dd81e9a4869
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-double-percent-encoded-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-double-percent-encoded-percent-encoded</title>
+<del cite="http://%ef%bc%85%ef%bc%94%ef%bc%91.com"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-empty-novalid.html
new file mode 100644
index 00000000000..afe922a1056
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-empty</title>
+<del cite="http://"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-empty-userinfo-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-empty-userinfo-empty-novalid.html
new file mode 100644
index 00000000000..7e703bf9235
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-empty-userinfo-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-empty-userinfo-empty</title>
+<del cite="http://@/www.example.com"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-empty-with-userinfo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-empty-with-userinfo-novalid.html
new file mode 100644
index 00000000000..281333e0763
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-empty-with-userinfo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-empty-with-userinfo</title>
+<del cite="http://user:pass@/"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-hostname-in-brackets-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-hostname-in-brackets-novalid.html
new file mode 100644
index 00000000000..169318e9696
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-hostname-in-brackets-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-hostname-in-brackets</title>
+<del cite="http://[www.google.com]/"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-invalid-unicode-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-invalid-unicode-novalid.html
new file mode 100644
index 00000000000..e7c77a41596
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-invalid-unicode-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-invalid-unicode</title>
+<del cite="http://﷐zyx.com"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-invalid-unicode-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-invalid-unicode-percent-encoded-novalid.html
new file mode 100644
index 00000000000..5591088fcf7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-invalid-unicode-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-invalid-unicode-percent-encoded</title>
+<del cite="http://%ef%b7%90zyx.com"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-newline-novalid.html
new file mode 100644
index 00000000000..692baaa9226
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-newline</title>
+<del cite="http://example.
+org"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-space-novalid.html
new file mode 100644
index 00000000000..efadf49d07a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-space</title>
+<del cite="http://example .org"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-square-brackets-port-contains-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-square-brackets-port-contains-colon-novalid.html
new file mode 100644
index 00000000000..54aaf1246bf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-square-brackets-port-contains-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-square-brackets-port-contains-colon</title>
+<del cite="http://[1::2]:3:4"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-tab-novalid.html
new file mode 100644
index 00000000000..cf8d7e2ae45
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-tab</title>
+<del cite="http://example .org"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-u0000-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-u0000-percent-encoded-novalid.html
new file mode 100644
index 00000000000..20e4287a418
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-u0000-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-u0000-percent-encoded</title>
+<del cite="http://%00.com"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-u0000-percent-encoded-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-u0000-percent-encoded-percent-encoded-novalid.html
new file mode 100644
index 00000000000..9f80ee3e380
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/host-u0000-percent-encoded-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-u0000-percent-encoded-percent-encoded</title>
+<del cite="http://%ef%bc%85%ef%bc%90%ef%bc%90.com"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/path-bare-percent-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/path-bare-percent-sign-novalid.html
new file mode 100644
index 00000000000..f21b2f6f60c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/path-bare-percent-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: path-bare-percent-sign</title>
+<del cite="http://example.com/foo%"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/path-contains-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/path-contains-space-novalid.html
new file mode 100644
index 00000000000..cd189d60c61
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/path-contains-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: path-contains-space</title>
+<del cite="/a/ /c"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/path-leading-backslash-at-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/path-leading-backslash-at-sign-novalid.html
new file mode 100644
index 00000000000..dd0c500d7fa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/path-leading-backslash-at-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: path-leading-backslash-at-sign</title>
+<del cite="http://foo.com/\@"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/path-leading-colon-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/path-leading-colon-backslash-novalid.html
new file mode 100644
index 00000000000..f34c59b3bcd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/path-leading-colon-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: path-leading-colon-backslash</title>
+<del cite=":\"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/path-leading-colon-chars-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/path-leading-colon-chars-backslash-novalid.html
new file mode 100644
index 00000000000..c7e492f6523
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/path-leading-colon-chars-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: path-leading-colon-chars-backslash</title>
+<del cite=":foo.com\"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/path-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/path-leading-space-novalid.html
new file mode 100644
index 00000000000..32480867d3d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/path-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: path-leading-space</title>
+<del cite="http://f:21/ b"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/path-percent-encoded-malformed-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/path-percent-encoded-malformed-novalid.html
new file mode 100644
index 00000000000..67bcccff311
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/path-percent-encoded-malformed-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: path-percent-encoded-malformed</title>
+<del cite="http://example.com/foo/%2e%2"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/path-relative-square-brackets-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/path-relative-square-brackets-novalid.html
new file mode 100644
index 00000000000..f63045a202e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/path-relative-square-brackets-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: path-relative-square-brackets</title>
+<del cite="[61:24:74]:98"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/path-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/path-tab-novalid.html
new file mode 100644
index 00000000000..c45140beaf8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/path-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: path-tab</title>
+<del cite="http://example.com/foo bar"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/path-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/path-trailing-space-novalid.html
new file mode 100644
index 00000000000..88d758405e0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/path-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: path-trailing-space</title>
+<del cite="http://f:21/b ?"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/path-u0091-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/path-u0091-novalid.html
new file mode 100644
index 00000000000..1dc17517fb7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/path-u0091-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: path-u0091</title>
+<del cite="http://example.com/foo‘"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/port-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/port-cr-novalid.html
new file mode 100644
index 00000000000..872d3f3cf45
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/port-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: port-cr</title>
+<del cite="http://f: /c"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/port-leading-colon-bracket-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/port-leading-colon-bracket-colon-novalid.html
new file mode 100644
index 00000000000..f5f93644031
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/port-leading-colon-bracket-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: port-leading-colon-bracket-colon</title>
+<del cite="http://2001::1]:80"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/port-leading-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/port-leading-colon-novalid.html
new file mode 100644
index 00000000000..66b076f2691
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/port-leading-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: port-leading-colon</title>
+<del cite="http://2001::1"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/port-leading-dash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/port-leading-dash-novalid.html
new file mode 100644
index 00000000000..b3d1f790987
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/port-leading-dash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: port-leading-dash</title>
+<del cite="http://foo:-80/"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/port-multiple-letters-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/port-multiple-letters-novalid.html
new file mode 100644
index 00000000000..d830e1118c0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/port-multiple-letters-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: port-multiple-letters</title>
+<del cite="http://f:fifty-two/c"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/port-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/port-newline-novalid.html
new file mode 100644
index 00000000000..3da1891ddad
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/port-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: port-newline</title>
+<del cite="http://f:
+/c"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/port-single-letter-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/port-single-letter-novalid.html
new file mode 100644
index 00000000000..e7463d52b55
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/port-single-letter-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: port-single-letter</title>
+<del cite="http://f:b/c"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/port-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/port-space-novalid.html
new file mode 100644
index 00000000000..3756f82ed64
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/port-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: port-space</title>
+<del cite="http://f: /c"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/port-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/port-tab-novalid.html
new file mode 100644
index 00000000000..e85fb7bf1ee
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/port-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: port-tab</title>
+<del cite="http://f: /c"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/query-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/query-leading-space-novalid.html
new file mode 100644
index 00000000000..a05f6bdd427
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/query-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: query-leading-space</title>
+<del cite="http://f:21/b? d"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/query-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/query-trailing-space-novalid.html
new file mode 100644
index 00000000000..c7cf9e808c6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/query-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: query-trailing-space</title>
+<del cite="http://f:21/b?d #"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-data-contains-fragment-haswarn.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-data-contains-fragment-haswarn.html
new file mode 100644
index 00000000000..fa04644fd1b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-data-contains-fragment-haswarn.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>data:text/html,test#test warning: scheme-data-contains-fragment</title>
+<del cite="data:text/html,test#test"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-data-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-data-single-slash-novalid.html
new file mode 100644
index 00000000000..185133b6640
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-data-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-data-single-slash</title>
+<del cite="data:/example.com/"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-file-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-file-backslash-novalid.html
new file mode 100644
index 00000000000..d0cb7986c90
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-file-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-file-backslash</title>
+<del cite="file:c:\foo\bar.html"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-file-single-slash-c-bar-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-file-single-slash-c-bar-novalid.html
new file mode 100644
index 00000000000..72a65284a3e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-file-single-slash-c-bar-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-file-single-slash-c-bar</title>
+<del cite="file:/C|/foo/bar"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-file-triple-slash-c-bar-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-file-triple-slash-c-bar-novalid.html
new file mode 100644
index 00000000000..23c40bd7204
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-file-triple-slash-c-bar-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-file-triple-slash-c-bar</title>
+<del cite="file:///C|/foo/bar"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-ftp-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-ftp-no-slash-novalid.html
new file mode 100644
index 00000000000..fd4cbdaf072
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-ftp-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-ftp-no-slash</title>
+<del cite="ftp:example.com/"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-ftp-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-ftp-single-slash-novalid.html
new file mode 100644
index 00000000000..2e373739e3f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-ftp-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-ftp-single-slash</title>
+<del cite="ftp:/example.com/"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-http-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-http-backslash-novalid.html
new file mode 100644
index 00000000000..f3d6c90b589
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-http-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-http-backslash</title>
+<del cite="http:\\foo.com\"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-http-no-slash-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-http-no-slash-colon-novalid.html
new file mode 100644
index 00000000000..b86a891cbe5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-http-no-slash-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-http-no-slash-colon</title>
+<del cite="http::@c:29"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-http-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-http-no-slash-novalid.html
new file mode 100644
index 00000000000..12fd2cedb45
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-http-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-http-no-slash</title>
+<del cite="http:foo.com"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-http-no-slash-square-bracket-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-http-no-slash-square-bracket-novalid.html
new file mode 100644
index 00000000000..25625e7f4a5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-http-no-slash-square-bracket-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-http-no-slash-square-bracket</title>
+<del cite="http:[61:27]/:foo"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-http-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-http-single-slash-novalid.html
new file mode 100644
index 00000000000..6f95f1e0c42
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-http-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-http-single-slash</title>
+<del cite="http:/example.com/"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-https-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-https-no-slash-novalid.html
new file mode 100644
index 00000000000..6abda3c88a0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-https-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-https-no-slash</title>
+<del cite="https:example.com/"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-https-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-https-single-slash-novalid.html
new file mode 100644
index 00000000000..0e7f0addb07
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-https-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-https-single-slash</title>
+<del cite="https:/example.com/"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-javascript-no-slash-malformed-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-javascript-no-slash-malformed-novalid.html
new file mode 100644
index 00000000000..4328b02e9b3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-javascript-no-slash-malformed-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-javascript-no-slash-malformed</title>
+<del cite="javascript:example.com/"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-trailing-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-trailing-cr-novalid.html
new file mode 100644
index 00000000000..363641fc301
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-trailing-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-trailing-cr</title>
+<del cite="a: foo.com"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-trailing-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-trailing-newline-novalid.html
new file mode 100644
index 00000000000..ec8f0c04e95
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-trailing-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-trailing-newline</title>
+<del cite="a:
+foo.com"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-trailing-space-novalid.html
new file mode 100644
index 00000000000..31f418ca78a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-trailing-space</title>
+<del cite="a: foo.com"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-trailing-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-trailing-tab-novalid.html
new file mode 100644
index 00000000000..66d8ce3e067
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/scheme-trailing-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-trailing-tab</title>
+<del cite="a: foo.com"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/userinfo-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/userinfo-backslash-novalid.html
new file mode 100644
index 00000000000..99ba1d5e4f6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/userinfo-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: userinfo-backslash</title>
+<del cite="http://a\b:c\d@foo.com"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/userinfo-password-bad-chars-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/userinfo-password-bad-chars-novalid.html
new file mode 100644
index 00000000000..f0ab910ac8d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/userinfo-password-bad-chars-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: userinfo-password-bad-chars</title>
+<del cite="http://&a:foo(b]c@d:2/"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/userinfo-password-contains-pile-of-poo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/userinfo-password-contains-pile-of-poo-novalid.html
new file mode 100644
index 00000000000..16b6d271cbb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/userinfo-password-contains-pile-of-poo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: userinfo-password-contains-pile-of-poo</title>
+<del cite="http://foo:💩@example.com"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/userinfo-username-contains-at-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/userinfo-username-contains-at-sign-novalid.html
new file mode 100644
index 00000000000..06392ba644c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/userinfo-username-contains-at-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: userinfo-username-contains-at-sign</title>
+<del cite="http://::@c@d:2"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/userinfo-username-contains-pile-of-poo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/userinfo-username-contains-pile-of-poo-novalid.html
new file mode 100644
index 00000000000..e8bfa2b67ef
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/cite/userinfo-username-contains-pile-of-poo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: userinfo-username-contains-pile-of-poo</title>
+<del cite="http://💩:foo@example.com"></del>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-0004-02-29-haswarn.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-0004-02-29-haswarn.html
new file mode 100644
index 00000000000..c760319697a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-0004-02-29-haswarn.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-0004-02-29</title>
+<del datetime="0004-02-29"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-0005-02-29-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-0005-02-29-novalid.html
new file mode 100644
index 00000000000..f8b973fd407
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-0005-02-29-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-0005-02-29</title>
+<del datetime="0005-02-29"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-0214-09-29-haswarn.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-0214-09-29-haswarn.html
new file mode 100644
index 00000000000..2f7a26ea101
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-0214-09-29-haswarn.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-0214-09-29</title>
+<del datetime="0214-09-29"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-1900-02-29-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-1900-02-29-novalid.html
new file mode 100644
index 00000000000..d645c2256b4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-1900-02-29-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-1900-02-29</title>
+<del datetime="1900-02-29"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-1969-02-29-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-1969-02-29-novalid.html
new file mode 100644
index 00000000000..7821eaea15f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-1969-02-29-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-1969-02-29</title>
+<del datetime="1969-02-29"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-20014-09-29-haswarn.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-20014-09-29-haswarn.html
new file mode 100644
index 00000000000..7b4099df6c8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-20014-09-29-haswarn.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-20014-09-29</title>
+<del datetime="20014-09-29"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-2014-02-29-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-2014-02-29-novalid.html
new file mode 100644
index 00000000000..8a7909960a3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-2014-02-29-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-2014-02-29</title>
+<del datetime="2014-02-29"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-2100-02-29-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-2100-02-29-novalid.html
new file mode 100644
index 00000000000..3b732b5b368
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-2100-02-29-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-2100-02-29</title>
+<del datetime="2100-02-29"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-2200-02-29-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-2200-02-29-novalid.html
new file mode 100644
index 00000000000..8c5ef2e344c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-2200-02-29-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-2200-02-29</title>
+<del datetime="2200-02-29"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-day-01-32-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-day-01-32-novalid.html
new file mode 100644
index 00000000000..1c4e3d3971e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-day-01-32-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-day-01-32</title>
+<del datetime="2002-01-32"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-day-03-32-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-day-03-32-novalid.html
new file mode 100644
index 00000000000..651c0bb6672
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-day-03-32-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-day-03-32</title>
+<del datetime="2002-03-32"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-day-04-31-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-day-04-31-novalid.html
new file mode 100644
index 00000000000..f3ab1140156
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-day-04-31-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-day-04-31</title>
+<del datetime="2002-04-31"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-day-05-32-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-day-05-32-novalid.html
new file mode 100644
index 00000000000..c4caeade95b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-day-05-32-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-day-05-32</title>
+<del datetime="2002-05-32"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-day-06-31-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-day-06-31-novalid.html
new file mode 100644
index 00000000000..3583295f3da
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-day-06-31-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-day-06-31</title>
+<del datetime="2002-06-31"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-day-07-32-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-day-07-32-novalid.html
new file mode 100644
index 00000000000..0948cf57428
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-day-07-32-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-day-07-32</title>
+<del datetime="2002-07-32"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-day-08-32-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-day-08-32-novalid.html
new file mode 100644
index 00000000000..09830a83350
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-day-08-32-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-day-08-32</title>
+<del datetime="2002-08-32"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-day-09-31-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-day-09-31-novalid.html
new file mode 100644
index 00000000000..55c600cfa2f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-day-09-31-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-day-09-31</title>
+<del datetime="2002-09-31"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-day-10-32-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-day-10-32-novalid.html
new file mode 100644
index 00000000000..6aeefece6e8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-day-10-32-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-day-10-32</title>
+<del datetime="2002-10-32"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-day-11-31-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-day-11-31-novalid.html
new file mode 100644
index 00000000000..bfb4c572dd3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-day-11-31-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-day-11-31</title>
+<del datetime="2002-11-31"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-day-12-32-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-day-12-32-novalid.html
new file mode 100644
index 00000000000..03b511c2f14
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-day-12-32-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-day-12-32</title>
+<del datetime="2002-12-32"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-day-missing-separator-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-day-missing-separator-novalid.html
new file mode 100644
index 00000000000..8e31abfa6d4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-day-missing-separator-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-day-missing-separator</title>
+<del datetime="2014-0220"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-day-one-digit-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-day-one-digit-novalid.html
new file mode 100644
index 00000000000..b8994f93cdf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-day-one-digit-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-day-one-digit</title>
+<del datetime="2002-09-9"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-day-three-digits-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-day-three-digits-novalid.html
new file mode 100644
index 00000000000..8ee427c5c87
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-day-three-digits-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-day-three-digits</title>
+<del datetime="2002-11-009"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-iso8601-YYYYMMDD-no-hyphen-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-iso8601-YYYYMMDD-no-hyphen-novalid.html
new file mode 100644
index 00000000000..493d9de78ec
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-iso8601-YYYYMMDD-no-hyphen-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-iso8601-YYYYMMDD-no-hyphen</title>
+<del datetime="20020929"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-leading-bom-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-leading-bom-novalid.html
new file mode 100644
index 00000000000..48855e5542c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-leading-bom-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-leading-bom</title>
+<del datetime="2002-09-29"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-leading-whitespace-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-leading-whitespace-novalid.html
new file mode 100644
index 00000000000..5deaf01e4a2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-leading-whitespace-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-leading-whitespace</title>
+<del datetime=" 2002-09-29"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-month-00-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-month-00-novalid.html
new file mode 100644
index 00000000000..798e23b8ffd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-month-00-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-month-00</title>
+<del datetime="2002-00-15"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-month-13-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-month-13-novalid.html
new file mode 100644
index 00000000000..63a8b4e7108
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-month-13-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-month-13</title>
+<del datetime="2002-13-15"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-month-missing-separator-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-month-missing-separator-novalid.html
new file mode 100644
index 00000000000..b852207e5d3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-month-missing-separator-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-month-missing-separator</title>
+<del datetime="201402-20"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-month-one-digit-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-month-one-digit-novalid.html
new file mode 100644
index 00000000000..baf20b49cf9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-month-one-digit-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-month-one-digit</title>
+<del datetime="2002-9-29"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-month-three-digits-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-month-three-digits-novalid.html
new file mode 100644
index 00000000000..0ff8f8987fb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-month-three-digits-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-month-three-digits</title>
+<del datetime="2002-011-29"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-non-ascii-digit-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-non-ascii-digit-novalid.html
new file mode 100644
index 00000000000..73ef3927616
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-non-ascii-digit-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-non-ascii-digit</title>
+<del datetime="2002-09-29"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-trailing-U+0000-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-trailing-U+0000-novalid.html
new file mode 100644
index 00000000000..4870c3dd38c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-trailing-U+0000-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-trailing-U+0000</title>
+<del datetime="2002-09-29&#x0000;"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-trailing-pile-of-poo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-trailing-pile-of-poo-novalid.html
new file mode 100644
index 00000000000..4c38689078d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-trailing-pile-of-poo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-trailing-pile-of-poo</title>
+<del datetime="2002-09-29💩"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-trailing-whitespace-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-trailing-whitespace-novalid.html
new file mode 100644
index 00000000000..70269cc3485
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-trailing-whitespace-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-trailing-whitespace</title>
+<del datetime="2002-09-29 "></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-wrong-day-separator-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-wrong-day-separator-novalid.html
new file mode 100644
index 00000000000..84551710800
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-wrong-day-separator-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-wrong-day-separator</title>
+<del datetime="2014-02:20"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-wrong-month-separator-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-wrong-month-separator-novalid.html
new file mode 100644
index 00000000000..797cae4956a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-wrong-month-separator-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-wrong-month-separator</title>
+<del datetime="2014:02-20"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-year-0000-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-year-0000-novalid.html
new file mode 100644
index 00000000000..267903239d8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-year-0000-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-year-0000</title>
+<del datetime="0000-12-09"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-year-five-digits-haswarn.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-year-five-digits-haswarn.html
new file mode 100644
index 00000000000..ed42c905309
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-year-five-digits-haswarn.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-year-five-digits</title>
+<del datetime="12014-09-29"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-year-negative-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-year-negative-novalid.html
new file mode 100644
index 00000000000..459f745a8f8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-year-negative-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-year-negative</title>
+<del datetime="-2002-09-29"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-year-three-digits-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-year-three-digits-novalid.html
new file mode 100644
index 00000000000..9574f97ded6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/date-year-three-digits-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-year-three-digits</title>
+<del datetime="782-09-29"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/datetime-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/datetime-isvalid.html
new file mode 100644
index 00000000000..3dff10cc0d5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/datetime-isvalid.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid datetime</title>
+<del datetime="2011-11-12T06:54:39-08:00"></del> <!-- global-date-and-time-timezone-with-colon -->
+<del datetime="2002-12-31"></del> <!-- date-day-12-31 -->
+<del datetime="2002-08-31"></del> <!-- date-day-08-31 -->
+<del datetime="1900-02-28"></del> <!-- date-1900-02-28 -->
+<del datetime="2011-11-12T14:54:39+0000"></del> <!-- global-date-and-time-with-seconds -->
+<del datetime="2002-10-31"></del> <!-- date-day-10-31 -->
+<del datetime="2002-01-31"></del> <!-- date-day-01-31 -->
+<del datetime="2200-02-28"></del> <!-- date-2200-02-28 -->
+<del datetime="2002-09-29"></del> <!-- date -->
+<del datetime="2002-06-30"></del> <!-- date-day-06-30 -->
+<del datetime="2100-02-28"></del> <!-- date-2100-02-28 -->
+<del datetime="2011-11-12T06:54:39-0845"></del> <!-- global-date-and-time-timezone-45 -->
+<del datetime="2002-03-31"></del> <!-- date-day-03-31 -->
+<del datetime="2011-11-12T06:54:39+0900"></del> <!-- global-date-and-time-timezone -->
+<del datetime="2002-04-30"></del> <!-- date-day-04-30 -->
+<del datetime="2002-09-30"></del> <!-- date-day-09-30 -->
+<del datetime="2002-05-31"></del> <!-- date-day-05-31 -->
+<del datetime="2011-11-12T14:54Z"></del> <!-- global-date-and-time-no-seconds -->
+<del datetime="2011-11-12T06:54:39.92+07:00"></del> <!-- global-date-and-time-with-two-digit-fraction -->
+<del datetime="2400-02-29"></del> <!-- date-2400-02-29 -->
+<del datetime="2002-07-31"></del> <!-- date-day-07-31 -->
+<del datetime="2011-11-12T06:54:39.929-06:00"></del> <!-- global-date-and-time-with-three-digit-fraction -->
+<del datetime="2011-11-12T06:54:39-0830"></del> <!-- global-date-and-time-timezone-30 -->
+<del datetime="2014-02-28"></del> <!-- date-2014-02-28 -->
+<del datetime="2002-11-30"></del> <!-- date-day-11-30 -->
+<del datetime="2000-02-29"></del> <!-- date-2000-02-29 -->
+<del datetime="2011-11-12 14:54Z"></del> <!-- global-date-and-time-space -->
+<del datetime="2011-11-12T06:54:39.9-08:00"></del> <!-- global-date-and-time-with-one-digit-fraction -->
+<del datetime="1968-02-29"></del> <!-- date-1968-02-29 -->
+<del datetime="2011-11-12T06:54:39-0800"></del> <!-- global-date-and-time-timezone-without-colon -->
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/duration-P-form-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/duration-P-form-novalid.html
new file mode 100644
index 00000000000..b7487e706e8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/duration-P-form-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>duration-P-form</title>
+<del datetime="PT4H18M3S"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/duration-time-component-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/duration-time-component-novalid.html
new file mode 100644
index 00000000000..98a484d0fad
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/duration-time-component-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>duration-time-component</title>
+<del datetime="4h 18m 3s"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-2400-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-2400-novalid.html
new file mode 100644
index 00000000000..5a3328aa9bf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-2400-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-2400</title>
+<del datetime="2011-11-12T24:00:00+08:00"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-60-minutes-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-60-minutes-novalid.html
new file mode 100644
index 00000000000..5d4641c5244
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-60-minutes-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-60-minutes</title>
+<del datetime="2011-11-12T00:60:00+08:00"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-60-seconds-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-60-seconds-novalid.html
new file mode 100644
index 00000000000..ec897dca823
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-60-seconds-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-60-seconds</title>
+<del datetime="2011-11-12T00:00:60+08:00"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-bad-fraction-separator-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-bad-fraction-separator-novalid.html
new file mode 100644
index 00000000000..43fd39e7f3d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-bad-fraction-separator-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-bad-fraction-separator</title>
+<del datetime="2011-11-12T14:54:39,929+0000"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-four-digit-fraction-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-four-digit-fraction-novalid.html
new file mode 100644
index 00000000000..d17ece6f8b7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-four-digit-fraction-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-four-digit-fraction</title>
+<del datetime="2011-11-12T06:54:39.9291-08:00"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-hour-one-digit-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-hour-one-digit-novalid.html
new file mode 100644
index 00000000000..5fcad235777
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-hour-one-digit-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-hour-one-digit</title>
+<del datetime="2011-11-12T6:54:39-08:00"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-hour-three-digits-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-hour-three-digits-novalid.html
new file mode 100644
index 00000000000..3683a20df3d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-hour-three-digits-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-hour-three-digits</title>
+<del datetime="2011-11-12T016:54:39-08:00"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-iso8601-hh-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-iso8601-hh-novalid.html
new file mode 100644
index 00000000000..95f4b3df084
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-iso8601-hh-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-iso8601-hh</title>
+<del datetime="2011-11-12T14Z"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-iso8601-hhmm-no-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-iso8601-hhmm-no-colon-novalid.html
new file mode 100644
index 00000000000..9b1c4df19b0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-iso8601-hhmm-no-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-iso8601-hhmm-no-colon</title>
+<del datetime="2011-11-12T1454Z"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-iso8601-hhmmss-no-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-iso8601-hhmmss-no-colon-novalid.html
new file mode 100644
index 00000000000..4a66109f638
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-iso8601-hhmmss-no-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-iso8601-hhmmss-no-colon</title>
+<del datetime="2011-11-12T145439Z"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-lowercase-z-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-lowercase-z-novalid.html
new file mode 100644
index 00000000000..525f670a8d8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-lowercase-z-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-lowercase-z</title>
+<del datetime="2011-11-12T14:54z"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-minutes-one-digit-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-minutes-one-digit-novalid.html
new file mode 100644
index 00000000000..ae1d238df71
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-minutes-one-digit-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-minutes-one-digit</title>
+<del datetime="2011-11-12T16:4:39-08:00"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-minutes-three-digits-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-minutes-three-digits-novalid.html
new file mode 100644
index 00000000000..459d029c197
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-minutes-three-digits-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-minutes-three-digits</title>
+<del datetime="2011-11-12T16:354:39-08:00"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-missing-minutes-separator-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-missing-minutes-separator-novalid.html
new file mode 100644
index 00000000000..32b980237bc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-missing-minutes-separator-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-missing-minutes-separator</title>
+<del datetime="2011-11-12T1454Z"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-missing-seconds-separator-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-missing-seconds-separator-novalid.html
new file mode 100644
index 00000000000..16694a381a6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-missing-seconds-separator-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-missing-seconds-separator</title>
+<del datetime="2011-11-12T14:5439Z"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-nbsp-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-nbsp-novalid.html
new file mode 100644
index 00000000000..2074fcf466a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-nbsp-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-nbsp</title>
+<del datetime="2011-11-12 14:54Z"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-seconds-one-digit-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-seconds-one-digit-novalid.html
new file mode 100644
index 00000000000..f879efad840
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-seconds-one-digit-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-seconds-one-digit</title>
+<del datetime="2011-11-12T16:54:9-08:00"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-seconds-three-digits-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-seconds-three-digits-novalid.html
new file mode 100644
index 00000000000..2d616bd8c1a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-seconds-three-digits-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-seconds-three-digits</title>
+<del datetime="2011-11-12T16:54:039-08:00"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-space-before-timezone-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-space-before-timezone-novalid.html
new file mode 100644
index 00000000000..c9da89f049d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-space-before-timezone-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-space-before-timezone</title>
+<del datetime="2011-11-12T06:54:39 08:00"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-60-minutes-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-60-minutes-novalid.html
new file mode 100644
index 00000000000..26c4efd6cec
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-60-minutes-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-timezone-60-minutes</title>
+<del datetime="2011-11-12T06:54:39-08:60"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-iso8601-two-digit-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-iso8601-two-digit-novalid.html
new file mode 100644
index 00000000000..307afcac7e7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-iso8601-two-digit-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-timezone-iso8601-two-digit</title>
+<del datetime="2011-11-12T06:54:39-08"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-lowercase-t-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-lowercase-t-novalid.html
new file mode 100644
index 00000000000..a705cd02ef1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-lowercase-t-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-timezone-lowercase-t</title>
+<del datetime="2011-11-12t14:54Z"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-minus-1300-haswarn.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-minus-1300-haswarn.html
new file mode 100644
index 00000000000..ba2da94271b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-minus-1300-haswarn.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-timezone-minus-1300</title>
+<del datetime="2011-11-12T00:00:00-1300"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-minus-2400-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-minus-2400-novalid.html
new file mode 100644
index 00000000000..8db2fa3ea6c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-minus-2400-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-timezone-minus-2400</title>
+<del datetime="2011-11-12T06:54:39-24:00"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-minutes-15-haswarn.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-minutes-15-haswarn.html
new file mode 100644
index 00000000000..c371fb9024f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-minutes-15-haswarn.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-timezone-minutes-15</title>
+<del datetime="2011-11-12T00:00:00+08:15"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-multiple-spaces-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-multiple-spaces-novalid.html
new file mode 100644
index 00000000000..be4acace100
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-multiple-spaces-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-timezone-multiple-spaces</title>
+<del datetime="2011-11-12 14:54Z"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-non-T-character-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-non-T-character-novalid.html
new file mode 100644
index 00000000000..420ea8a0f36
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-non-T-character-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-timezone-non-T-character</title>
+<del datetime="2011-11-12+14:54Z"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-offset-colon-start-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-offset-colon-start-novalid.html
new file mode 100644
index 00000000000..b91337fbbcc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-offset-colon-start-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-timezone-offset-colon-start</title>
+<del datetime="2011-11-12T06:54:39.929:08:00"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-offset-space-start-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-offset-space-start-novalid.html
new file mode 100644
index 00000000000..81ace2b96d9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-offset-space-start-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-timezone-offset-space-start</title>
+<del datetime="2011-11-12T06:54:39.929 08:00"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-one-digit-hour-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-one-digit-hour-novalid.html
new file mode 100644
index 00000000000..cec77816f26
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-one-digit-hour-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-timezone-one-digit-hour</title>
+<del datetime="2011-11-12T06:54:39-5:00"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-one-digit-minute-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-one-digit-minute-novalid.html
new file mode 100644
index 00000000000..c4755de1789
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-one-digit-minute-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-timezone-one-digit-minute</title>
+<del datetime="2011-11-12T06:54:39-05:0"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-plus-1500-haswarn.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-plus-1500-haswarn.html
new file mode 100644
index 00000000000..df2835a864b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-plus-1500-haswarn.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-timezone-plus-1500</title>
+<del datetime="2011-11-12T00:00:00+1500"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-plus-2400-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-plus-2400-novalid.html
new file mode 100644
index 00000000000..304557f30b9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-plus-2400-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-timezone-plus-2400</title>
+<del datetime="2011-11-12T06:54:39-24:00"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-three-digit-hour-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-three-digit-hour-novalid.html
new file mode 100644
index 00000000000..407eac2fa61
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-three-digit-hour-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-timezone-three-digit-hour</title>
+<del datetime="2011-11-12T06:54:39-005:00"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-three-digit-minute-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-three-digit-minute-novalid.html
new file mode 100644
index 00000000000..eb0c21ac08c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-three-digit-minute-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-timezone-three-digit-minute</title>
+<del datetime="2011-11-12T06:54:39-05:000"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-with-seconds-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-with-seconds-novalid.html
new file mode 100644
index 00000000000..616f3d20724
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-timezone-with-seconds-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-timezone-with-seconds</title>
+<del datetime="2011-11-12T06:54:39-08:00:00"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-with-both-T-and-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-with-both-T-and-space-novalid.html
new file mode 100644
index 00000000000..667c9bc378d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-with-both-T-and-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-with-both-T-and-space</title>
+<del datetime="2011-11-12T 14:54Z"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-wrong-minutes-separator-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-wrong-minutes-separator-novalid.html
new file mode 100644
index 00000000000..e3598136484
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-wrong-minutes-separator-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-wrong-minutes-separator</title>
+<del datetime="2011-11-12T14-54Z"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-wrong-seconds-separator-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-wrong-seconds-separator-novalid.html
new file mode 100644
index 00000000000..474a0505d15
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-wrong-seconds-separator-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-wrong-seconds-separator</title>
+<del datetime="2011-11-12T14:54-39Z"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-zero-digit-fraction-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-zero-digit-fraction-novalid.html
new file mode 100644
index 00000000000..9e143966e9e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/global-date-and-time-zero-digit-fraction-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-zero-digit-fraction</title>
+<del datetime="2011-11-12T06:54:39.-08:00"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/local-date-and-time-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/local-date-and-time-novalid.html
new file mode 100644
index 00000000000..ec874405297
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/local-date-and-time-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>local-date-and-time</title>
+<del datetime="2011-11-12T14:54"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/model-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/model-isvalid.html
new file mode 100644
index 00000000000..194678a657f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/model-isvalid.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;del&gt;</title>
+</head>
+<body>
+
+
+ <!-- can contain strictly inline while in strictly inline context -->
+ <p><dfn>strictly inline
+ <del>
+ <em>text</em>
+ </del>
+ </dfn></p>
+
+ <!-- can contain interactive if ancestor does not forbid it -->
+ <p>paragraph
+ <del>
+ <a>link</a>
+ </del>
+ </p>
+ <p><dfn>strictly inline
+ <del>
+ <a>link</a>
+ </del>
+ </dfn></p>
+
+ <div><del><p>foo</p></del></div><!-- with flow content and flow parent -->
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/model-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/model-novalid.html
new file mode 100644
index 00000000000..0cf5c1797b8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/model-novalid.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;del&gt;</title>
+</head>
+<body>
+ <!-- can contain inline while in inline context -->
+ <p>paragraph
+ <del>
+ <em>some</em> <ul><li>inline</li></ul> content
+ </del>
+ </p>
+
+ <!-- can contain strictly inline while in strictly inline context -->
+ <p><dfn>strictly inline
+ <del>
+ <em>text</em>
+ </del>
+ </dfn></p>
+
+ <!-- can contain blocks while in block context -->
+ <del>
+ <p>text</p>
+ </del>
+
+ <!-- can contain interactive if ancestor does not forbid it -->
+ <p>paragraph
+ <del>
+ <a>link</a>
+ </del>
+ </p>
+ <p><dfn>strictly inline
+ <del>
+ <a>link</a>
+ </del>
+ </dfn></p>
+ <del>
+ <p><a>link</a></p>
+ </del>
+
+ <span><del><p>foo</p></del></span><!-- with flow content and phrasing parent -->
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/month-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/month-novalid.html
new file mode 100644
index 00000000000..0aa424db5ef
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/month-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>month</title>
+<del datetime="2011-11"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/time-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/time-novalid.html
new file mode 100644
index 00000000000..c9dabd72c9d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/time-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>time</title>
+<del datetime="14:54:39"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/week-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/week-novalid.html
new file mode 100644
index 00000000000..d4a806363a9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/week-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>week</title>
+<del datetime="2011-W46"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/year-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/year-novalid.html
new file mode 100644
index 00000000000..560309cf5df
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/year-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>year</title>
+<del datetime="2006"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/yearless-date-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/yearless-date-novalid.html
new file mode 100644
index 00000000000..4374fafc331
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/del/yearless-date-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>yearless-date</title>
+<del datetime="07-15"></del> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/dfn/model-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/dfn/model-isvalid.html
new file mode 100644
index 00000000000..15c72b4fcb6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/dfn/model-isvalid.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;dfn&gt;</title>
+</head>
+<body>
+ <!-- is structured inline -->
+ <p><dfn class="class" lang="en" title="text1">text</dfn></p>
+
+ <!-- is strictly inline -->
+ <p><i><dfn class="class" lang="en">text2</dfn></i></p>
+
+ <!-- can be empty -->
+ <p>text <dfn></dfn></p>
+ <p>text <i><dfn title="text3"></dfn></i></p>
+
+ <!-- can contain interactive -->
+ <p><dfn><a>text4</a></dfn></p>
+ <p><i><dfn><a>text5</a></dfn></i></p>
+
+ <!-- cannot contain structured inline -->
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/dfn/model-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/dfn/model-novalid.html
new file mode 100644
index 00000000000..7933d75dac7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/dfn/model-novalid.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;dfn&gt;</title>
+</head>
+<body>
+ <!-- not a block -->
+ <dfn>text</dfn>
+
+ <!-- cannot contain structured inline -->
+ <p><dfn><ul><li>text</li></ul></dfn></p>
+
+ <!-- cannot contain interactive if parent forbids interactive -->
+ <p><a><dfn><a>text</a></dfn></a></p>
+ <p><a><var><dfn><a>text</a></dfn></var></a></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/dialog/model-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/dialog/model-novalid.html
new file mode 100644
index 00000000000..f95676e374e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/dialog/model-novalid.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;dialog&gt;</title>
+</head>
+<body>
+<dialog>
+<dt>Foo</dt>
+<dt>Bar</dt>
+<dd><p>Blah</p></dd>
+<dd><p>Bleh</p></dd>
+</dialog>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/div/model-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/div/model-isvalid.html
new file mode 100644
index 00000000000..8d1ad0bf855
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/div/model-isvalid.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;div&gt;</title>
+</head>
+<body>
+ <!-- is block, contains blocks -->
+ <div class="class" id="id" lang="en">
+ <p>text</p>
+ <p>text2</p>
+ <ul></ul>
+ </div>
+
+ <!-- can contain interactive -->
+ <div>
+ <p><a>text</a></p>
+ </div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/div/model-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/div/model-novalid.html
new file mode 100644
index 00000000000..a7d8e4f60d2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/div/model-novalid.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;div&gt;</title>
+</head>
+<body>
+ <!-- is not strictly inline -->
+ <p><dfn>text
+ <div>
+ <p>text</p>
+ </div>
+ </dfn></p>
+
+ <!-- is not structured inline -->
+ <p>text
+ <div>
+ <p>text</p>
+ </div>
+ </p>
+
+ <!-- cannot contain inline -->
+ <div>
+ some <em>text</em>
+ </div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/dl/model-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/dl/model-isvalid.html
new file mode 100644
index 00000000000..c7a5de96c03
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/dl/model-isvalid.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Definition List: &lt;dl&gt; &lt;dt&gt; &lt;dd&gt;</title>
+</head>
+<body>
+ <!-- is block -->
+ <dl class="class" id="id" lang="en">
+ <dt class="class" id="id2" lang="en">text</dt>
+ <dd class="class" id="id3" lang="en">text</dd>
+ </dl>
+
+ <!-- can be empty -->
+ <dl></dl>
+ <dl>
+ <dt></dt>
+ <dd></dd>
+ </dl>
+
+ <!-- multiple groups, but always (dt+,dd+) -->
+ <dl>
+ <dt>text</dt>
+ <dd>more text</dd>
+ <dt>text</dt>
+ <dd>more text</dd>
+ <dd>more text</dd>
+ <dt>text</dt>
+ <dt>text</dt>
+ <dt>text</dt>
+ <dd>more text</dd>
+ </dl>
+
+ <!-- dd can contain structured inline, dt strictly inline -->
+ <dl>
+ <dt>some <em>text</em></dt>
+ <dd>more <pre>text</pre></dd>
+ </dl>
+
+ <!-- dd can contain blocks -->
+ <dl>
+ <dt>some <em>text</em></dt>
+ <dd>
+ <p>more</p>
+ <p>text</p>
+ </dd>
+ </dl>
+
+ <!-- can contain interactive -->
+ <dl>
+ <dt>some <a>text</a></dt>
+ <dd>more <a>text</a></dd>
+ </dl>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/dl/model-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/dl/model-novalid.html
new file mode 100644
index 00000000000..0eacdf8dbff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/dl/model-novalid.html
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Definition List: &lt;dl&gt; &lt;dt&gt; &lt;dd&gt;</title>
+</head>
+<body>
+ <!-- is block -->
+ <dl class="class" id="id" lang="en">
+ <dt class="class" id="id" lang="en">text</dt>
+ <dd class="class" id="id" lang="en">text</dd>
+ </dl>
+
+ <!-- is structured inline -->
+ <p>paragraph
+ <dl class="class" id="id" lang="en">
+ <dt class="class" id="id" lang="en">text</dt>
+ <dd class="class" id="id" lang="en">text</dd>
+ </dl>
+ </p>
+
+ <!-- can be empty -->
+ <dl></dl>
+ <dl>
+ <dt></dt>
+ <dd></dd>
+ </dl>
+
+ <!-- multiple groups, but always (dt+,dd+) -->
+ <dl>
+ <dt>text</dt>
+ <dd>more text</dd>
+ <dt>text</dt>
+ <dd>more text</dd>
+ <dd>more text</dd>
+ <dt>text</dt>
+ <dt>text</dt>
+ <dt>text</dt>
+ <dd>more text</dd>
+ </dl>
+
+ <!-- dd can contain structured inline, dt strictly inline -->
+ <dl>
+ <dt>some <em>text</em></dt>
+ <dd>more <pre>text</pre></dd>
+ </dl>
+ <p>paragraph
+ <dl>
+ <dt>some <em>text</em></dt>
+ <dd>more <pre>text</pre></dd>
+ </dl>
+ </p>
+
+ <!-- dd can contain blocks -->
+ <dl>
+ <dt>some <em>text</em></dt>
+ <dd>
+ <p>more</p>
+ <p>text</p>
+ </dd>
+ </dl>
+
+ <!-- can contain interactive -->
+ <dl>
+ <dt>some <a>text</a></dt>
+ <dd>more <a>text</a></dd>
+ </dl>
+ <p>paragraph
+ <dl>
+ <dt>some <a>text</a></dt>
+ <dd>more <a>text</a></dd>
+ </dl>
+ </p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/em/model-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/em/model-isvalid.html
new file mode 100644
index 00000000000..a473a3479ff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/em/model-isvalid.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;em&gt;</title>
+</head>
+<body>
+ <!-- is structured inline -->
+ <p><em class="class" lang="en">text</em></p>
+
+ <!-- is strictly inline -->
+ <p><dfn><em class="class" lang="en">text</em></dfn></p>
+
+ <!-- can be empty -->
+ <p>text <em></em></p>
+ <p>text <dfn><em></em></dfn></p>
+
+ <!-- can contain interactive -->
+ <p><em><a>text</a></em></p>
+ <p><dfn><em><a>text</a></em></dfn></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/em/model-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/em/model-novalid.html
new file mode 100644
index 00000000000..1b721e7b581
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/em/model-novalid.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;em&gt;</title>
+</head>
+<body>
+ <!-- is structured inline -->
+ <p><em class="class" lang="en">text</em></p>
+
+ <!-- is strictly inline -->
+ <p><dfn><em class="class" lang="en">text</em></dfn></p>
+
+ <!-- can be empty -->
+ <p>text <em></em></p>
+ <p>text <dfn><em></em></dfn></p>
+
+ <!-- can contain interactive -->
+ <p><em><a>text</a></em></p>
+ <p><dfn><em><a>text</a></em></dfn></p>
+
+ <!-- cannot contain structured inline -->
+ <p><em>text <ul><li>list</li></ul> <em>elem</em></em></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/height-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/height-novalid.html
new file mode 100644
index 00000000000..62ca5efdf94
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/height-novalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>element embed with bad height value</title>
+</head>
+<body>
+<embed height="20%">
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src-empty-novalid.html
new file mode 100644
index 00000000000..fb5b6222dd2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>empty src is not valid</title>
+<embed src="">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src-isvalid.html
new file mode 100644
index 00000000000..4b6e213ecfa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src-isvalid.html
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid src</title>
+<embed src="file:///"><!-- scheme-file-slash-slash-slash-only -->
+<embed src="http://a:@www.example.com"><!-- userinfo-password-empty -->
+<embed src="foo://///////"><!-- scheme-private-path-leading-slashes-only -->
+<embed src="file://abc|/foo/bar"><!-- scheme-file-slash-slash-abc-bar -->
+<embed src="/a/b/c"><!-- path-simple-relative -->
+<embed src="http://example.com/你好你好"><!-- path-unicode-han -->
+<embed src="/a/%2f/c"><!-- path-percent-encoded-slash-plus-slashes-relative -->
+<embed src="http://f:/c"><!-- port-none-but-colon -->
+<embed src="http://example.com/foo%41%7a"><!-- path-percent-encoded-multiple -->
+<embed src="http://192.168.0.257/"><!-- host-IP-address-broken -->
+<embed src="madeupscheme:example.com/"><!-- scheme-private-no-slash -->
+<embed src="?"><!-- query-empty-no-path-relative -->
+<embed src="http://example.com/%20foo"><!-- path-percent-encoded-space -->
+<embed src="mailto:/example.com/"><!-- scheme-mailto-single-slash -->
+<embed src="::"><!-- path-leading-colon-colon-relative -->
+<embed src="http://example.com/%3A%3a%3C%3c"><!-- path-percent-encoded-mixed-case -->
+<embed src="http://user:pass@foo:21/bar;par?b#c"><!-- userinfo -->
+<embed src="ws:/example.com/"><!-- scheme-ws-single-slash -->
+<embed src="foo://"><!-- scheme-private-slash-slash -->
+<embed src="#"><!-- fragment-empty-hash-only-no-path-relative -->
+<embed src="http://f:00000000000000/c"><!-- port-00000000000000 -->
+<embed src="foo:////://///"><!-- scheme-private-path-leading-slashes-colon-slashes -->
+<embed src=":23"><!-- path-leading-colon-number-relative -->
+<embed src="foo:/"><!-- scheme-private-slash -->
+<embed src="http://💩"><!-- host-is-pile-of-poo -->
+<embed src="file:test"><!-- scheme-file-no-slash -->
+<embed src="file://C|/foo/bar"><!-- scheme-file-slash-slash-c-bar -->
+<embed src="#/"><!-- fragment-slash-relative -->
+<embed src="http://192.0x00A80001"><!-- host-192.0x00A80001 -->
+<embed src="foo.com"><!-- scheme-none-relative -->
+<embed src="http💩//:foo"><!-- path-contains-pile-of-poo -->
+<embed src="File://foo/bar.html"><!-- scheme-file-uppercase -->
+<embed src=":/"><!-- path-leading-colon-slash-relative -->
+<embed src="http://www.foo。bar.com"><!-- host-exotic-dot -->
+<embed src="http://GOO​⁠goo.com"><!-- host-exotic-whitespace -->
+<embed src="file:///foo/bar.txt"><!-- scheme-file-host-empty -->
+<embed src="javascript:/example.com/"><!-- scheme-javascript-single-slash -->
+<embed src="gopher:/example.com/"><!-- scheme-gopher-single-slash -->
+<embed src="ftps:example.com/"><!-- scheme-ftps-no-slash -->
+<embed src="file://server/foo/bar"><!-- scheme-file-host-included -->
+<embed src="http://example.com/foo%00"><!-- path-percent-encoded-u0000 -->
+<embed src="a:foo.com"><!-- scheme-private -->
+<embed src=":"><!-- path-colon-relative -->
+<embed src="http://:b@www.example.com"><!-- userinfo-user-empty -->
+<embed src="file:/"><!-- scheme-file-slash-only -->
+<embed src="wss:example.com/"><!-- scheme-wss-no-slash -->
+<embed src="::23"><!-- path-colon-colon-number-relative -->
+<embed src="/a%2fc"><!-- path-percent-encoded-slash-relative -->
+<embed src="http://a:b@c:29/d"><!-- userinfo-host-port-path -->
+<embed src="gopher:example.com/"><!-- scheme-gopher-no-slash -->
+<embed src="madeupscheme:/example.com/"><!-- scheme-private-single-slash -->
+<embed src="mailto:example.com/"><!-- scheme-mailto-no-slash -->
+<embed src="http://%25DOMAIN:foobar@foodomain.com"><!-- userinfo-username-contains-percent-encoded -->
+<embed src="/:23"><!-- path-slash-colon-number-relative -->
+<embed src="foo://///////bar.com/"><!-- scheme-private-path-leading-slashes-chars -->
+<embed src="http://[2001::1]:80"><!-- host-ipv6-port -->
+<embed src="data:text/plain,foo"><!-- scheme-data-no-slash -->
+<embed src="http://example.com/foo/%2e"><!-- path-percent-encoded-dot -->
+<embed src="file:/example.com/"><!-- scheme-file-single-slash -->
+<embed src="http://example.com/©zbar"><!-- path-non-ascii -->
+<embed src="http://example.com//foo"><!-- path-uFEFF -->
+<embed src="wss:/example.com/"><!-- scheme-wss-single-slash -->
+<embed src="http://foo/abcd#foo?bar"><!-- fragment-contains-question-mark -->
+<embed src=":#"><!-- path-leading-colon-hash-relative -->
+<embed src="http://example.com/foo%91"><!-- path-percent-encoded-u0091 -->
+<embed src="c:/foo"><!-- scheme-private-single-letter -->
+<embed src=":foo.com"><!-- path-leading-colon-chars-relative -->
+<embed src="http://你好你好"><!-- host-idn-unicode-han -->
+<embed src="http://example.com/foo#💩"><!-- fragment-contains-pile-of-poo -->
+<embed src="file:"><!-- scheme-file-scheme-only -->
+<embed src="#β"><!-- fragment-non-ascii-relative -->
+<embed src="foo:/bar.com/"><!-- scheme-private-path -->
+<embed src="http://f:0/c"><!-- port-0 -->
+<embed src="#;?"><!-- fragment-semicolon-question-mark-relative -->
+<embed src="http://Go.com"><!-- host-fullwidth -->
+<embed src="http://@www.example.com"><!-- userinfo-empty -->
+<embed src="http://example.com/‮/foo/‭/bar"><!-- path-u202E-u202D -->
+<embed src="http://[2001::1]"><!-- host-ipv6 -->
+<embed src="💩http://foo"><!-- path-starts-with-pile-of-poo -->
+<embed src="http://foo/abcd?efgh?ijkl"><!-- query-contains-question-mark -->
+<embed src="//foo/bar"><!-- scheme-schemeless-relative -->
+<embed src="ftps:/example.com/"><!-- scheme-ftps-single-slash -->
+<embed src="http://foo.com:b@d/"><!-- userinfo-username-non-alpha -->
+<embed src=":a"><!-- path-leading-colon-letter-relative -->
+<embed src="/"><!-- path-slash-only-relative -->
+<embed src="http://example.com/foo?💩"><!-- query-contains-pile-of-poo -->
+<embed src="http://f:00000000000000000000080/c"><!-- port-00000000000000000000080 -->
+<embed src="file://"><!-- scheme-file-slash-slash-only -->
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src-whitespace-only-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src-whitespace-only-novalid.html
new file mode 100644
index 00000000000..e9259d6a311
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src-whitespace-only-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>empty src is not valid</title>
+<embed src="
+">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/fragment-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/fragment-backslash-novalid.html
new file mode 100644
index 00000000000..28ac5498aa2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/fragment-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: fragment-backslash</title>
+<embed src="#\">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/fragment-contains-hash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/fragment-contains-hash-novalid.html
new file mode 100644
index 00000000000..9e05657cb0c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/fragment-contains-hash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: fragment-contains-hash</title>
+<embed src="http://foo/path#f#g">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/fragment-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/fragment-leading-space-novalid.html
new file mode 100644
index 00000000000..3e2845abf8a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/fragment-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: fragment-leading-space</title>
+<embed src="http://f:21/b# e">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-cr-novalid.html
new file mode 100644
index 00000000000..d8e03b52542
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-cr</title>
+<embed src="http://example. org">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-double-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-double-percent-encoded-novalid.html
new file mode 100644
index 00000000000..96442617523
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-double-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-double-percent-encoded</title>
+<embed src="http://%41.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-double-percent-encoded-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-double-percent-encoded-percent-encoded-novalid.html
new file mode 100644
index 00000000000..83513733fe0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-double-percent-encoded-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-double-percent-encoded-percent-encoded</title>
+<embed src="http://%ef%bc%85%ef%bc%94%ef%bc%91.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-empty-novalid.html
new file mode 100644
index 00000000000..b0b4eab599b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-empty</title>
+<embed src="http://">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-empty-userinfo-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-empty-userinfo-empty-novalid.html
new file mode 100644
index 00000000000..2d9d0d019be
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-empty-userinfo-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-empty-userinfo-empty</title>
+<embed src="http://@/www.example.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-empty-with-userinfo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-empty-with-userinfo-novalid.html
new file mode 100644
index 00000000000..be983e2ee32
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-empty-with-userinfo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-empty-with-userinfo</title>
+<embed src="http://user:pass@/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-hostname-in-brackets-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-hostname-in-brackets-novalid.html
new file mode 100644
index 00000000000..a636d49204a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-hostname-in-brackets-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-hostname-in-brackets</title>
+<embed src="http://[www.google.com]/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-invalid-unicode-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-invalid-unicode-novalid.html
new file mode 100644
index 00000000000..a50f5435c2a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-invalid-unicode-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-invalid-unicode</title>
+<embed src="http://﷐zyx.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-invalid-unicode-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-invalid-unicode-percent-encoded-novalid.html
new file mode 100644
index 00000000000..2cd5dced045
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-invalid-unicode-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-invalid-unicode-percent-encoded</title>
+<embed src="http://%ef%b7%90zyx.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-newline-novalid.html
new file mode 100644
index 00000000000..ce5e9c395bb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-newline</title>
+<embed src="http://example.
+org">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-space-novalid.html
new file mode 100644
index 00000000000..8e48edb2902
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-space</title>
+<embed src="http://example .org">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-square-brackets-port-contains-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-square-brackets-port-contains-colon-novalid.html
new file mode 100644
index 00000000000..34ff35c85ae
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-square-brackets-port-contains-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-square-brackets-port-contains-colon</title>
+<embed src="http://[1::2]:3:4">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-tab-novalid.html
new file mode 100644
index 00000000000..54eb72adafb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-tab</title>
+<embed src="http://example .org">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-u0000-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-u0000-percent-encoded-novalid.html
new file mode 100644
index 00000000000..f9da71c715f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-u0000-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-u0000-percent-encoded</title>
+<embed src="http://%00.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-u0000-percent-encoded-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-u0000-percent-encoded-percent-encoded-novalid.html
new file mode 100644
index 00000000000..cbb60db2206
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/host-u0000-percent-encoded-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-u0000-percent-encoded-percent-encoded</title>
+<embed src="http://%ef%bc%85%ef%bc%90%ef%bc%90.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/path-bare-percent-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/path-bare-percent-sign-novalid.html
new file mode 100644
index 00000000000..8fece4c1f14
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/path-bare-percent-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-bare-percent-sign</title>
+<embed src="http://example.com/foo%">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/path-contains-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/path-contains-space-novalid.html
new file mode 100644
index 00000000000..729219ae033
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/path-contains-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-contains-space</title>
+<embed src="/a/ /c">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/path-leading-backslash-at-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/path-leading-backslash-at-sign-novalid.html
new file mode 100644
index 00000000000..daa9caf21dd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/path-leading-backslash-at-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-leading-backslash-at-sign</title>
+<embed src="http://foo.com/\@">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/path-leading-colon-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/path-leading-colon-backslash-novalid.html
new file mode 100644
index 00000000000..dbd21679cbd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/path-leading-colon-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-leading-colon-backslash</title>
+<embed src=":\">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/path-leading-colon-chars-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/path-leading-colon-chars-backslash-novalid.html
new file mode 100644
index 00000000000..fbb85e06f8a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/path-leading-colon-chars-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-leading-colon-chars-backslash</title>
+<embed src=":foo.com\">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/path-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/path-leading-space-novalid.html
new file mode 100644
index 00000000000..826a9b66382
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/path-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-leading-space</title>
+<embed src="http://f:21/ b">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/path-percent-encoded-malformed-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/path-percent-encoded-malformed-novalid.html
new file mode 100644
index 00000000000..bd1cec37d86
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/path-percent-encoded-malformed-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-percent-encoded-malformed</title>
+<embed src="http://example.com/foo/%2e%2">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/path-relative-square-brackets-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/path-relative-square-brackets-novalid.html
new file mode 100644
index 00000000000..0d664b33d0f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/path-relative-square-brackets-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-relative-square-brackets</title>
+<embed src="[61:24:74]:98">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/path-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/path-tab-novalid.html
new file mode 100644
index 00000000000..e567b2e1c4f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/path-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-tab</title>
+<embed src="http://example.com/foo bar">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/path-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/path-trailing-space-novalid.html
new file mode 100644
index 00000000000..813f1c09adc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/path-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-trailing-space</title>
+<embed src="http://f:21/b ?">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/path-u0091-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/path-u0091-novalid.html
new file mode 100644
index 00000000000..3725b447e1f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/path-u0091-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-u0091</title>
+<embed src="http://example.com/foo‘">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/port-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/port-cr-novalid.html
new file mode 100644
index 00000000000..f91f00a5952
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/port-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-cr</title>
+<embed src="http://f: /c">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/port-leading-colon-bracket-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/port-leading-colon-bracket-colon-novalid.html
new file mode 100644
index 00000000000..216c25b414a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/port-leading-colon-bracket-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-leading-colon-bracket-colon</title>
+<embed src="http://2001::1]:80">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/port-leading-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/port-leading-colon-novalid.html
new file mode 100644
index 00000000000..02f55037462
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/port-leading-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-leading-colon</title>
+<embed src="http://2001::1">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/port-leading-dash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/port-leading-dash-novalid.html
new file mode 100644
index 00000000000..fab5f995e4e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/port-leading-dash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-leading-dash</title>
+<embed src="http://foo:-80/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/port-multiple-letters-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/port-multiple-letters-novalid.html
new file mode 100644
index 00000000000..4c6f73d50ea
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/port-multiple-letters-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-multiple-letters</title>
+<embed src="http://f:fifty-two/c">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/port-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/port-newline-novalid.html
new file mode 100644
index 00000000000..f434a0f82b8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/port-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-newline</title>
+<embed src="http://f:
+/c">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/port-single-letter-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/port-single-letter-novalid.html
new file mode 100644
index 00000000000..a685bd3890e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/port-single-letter-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-single-letter</title>
+<embed src="http://f:b/c">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/port-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/port-space-novalid.html
new file mode 100644
index 00000000000..b21dc093292
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/port-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-space</title>
+<embed src="http://f: /c">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/port-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/port-tab-novalid.html
new file mode 100644
index 00000000000..ee1329d15f7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/port-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-tab</title>
+<embed src="http://f: /c">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/query-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/query-leading-space-novalid.html
new file mode 100644
index 00000000000..16c00ae10ec
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/query-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: query-leading-space</title>
+<embed src="http://f:21/b? d">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/query-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/query-trailing-space-novalid.html
new file mode 100644
index 00000000000..6e75ffc41c2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/query-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: query-trailing-space</title>
+<embed src="http://f:21/b?d #">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-data-contains-fragment-haswarn.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-data-contains-fragment-haswarn.html
new file mode 100644
index 00000000000..f13b3b66640
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-data-contains-fragment-haswarn.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>src warning: scheme-data-contains-fragment</title>
+<embed src="data:text/html,test#test">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-data-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-data-single-slash-novalid.html
new file mode 100644
index 00000000000..e29dbb42186
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-data-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-data-single-slash</title>
+<embed src="data:/example.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-file-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-file-backslash-novalid.html
new file mode 100644
index 00000000000..72babd1bb0e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-file-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-file-backslash</title>
+<embed src="file:c:\foo\bar.html">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-file-single-slash-c-bar-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-file-single-slash-c-bar-novalid.html
new file mode 100644
index 00000000000..0d49b31e87e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-file-single-slash-c-bar-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-file-single-slash-c-bar</title>
+<embed src="file:/C|/foo/bar">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-file-triple-slash-c-bar-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-file-triple-slash-c-bar-novalid.html
new file mode 100644
index 00000000000..3f84b6e8b5a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-file-triple-slash-c-bar-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-file-triple-slash-c-bar</title>
+<embed src="file:///C|/foo/bar">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-ftp-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-ftp-no-slash-novalid.html
new file mode 100644
index 00000000000..af6d96024d8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-ftp-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-ftp-no-slash</title>
+<embed src="ftp:example.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-ftp-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-ftp-single-slash-novalid.html
new file mode 100644
index 00000000000..02cfc51d3fc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-ftp-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-ftp-single-slash</title>
+<embed src="ftp:/example.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-http-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-http-backslash-novalid.html
new file mode 100644
index 00000000000..6847bac4e7a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-http-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-http-backslash</title>
+<embed src="http:\\foo.com\">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-http-no-slash-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-http-no-slash-colon-novalid.html
new file mode 100644
index 00000000000..1e5a0f2c8fa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-http-no-slash-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-http-no-slash-colon</title>
+<embed src="http::@c:29">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-http-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-http-no-slash-novalid.html
new file mode 100644
index 00000000000..f97dfe838c6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-http-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-http-no-slash</title>
+<embed src="http:foo.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-http-no-slash-square-bracket-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-http-no-slash-square-bracket-novalid.html
new file mode 100644
index 00000000000..524d4bb6d52
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-http-no-slash-square-bracket-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-http-no-slash-square-bracket</title>
+<embed src="http:[61:27]/:foo">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-http-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-http-single-slash-novalid.html
new file mode 100644
index 00000000000..31e7be41bff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-http-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-http-single-slash</title>
+<embed src="http:/example.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-https-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-https-no-slash-novalid.html
new file mode 100644
index 00000000000..1aeaae42242
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-https-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-https-no-slash</title>
+<embed src="https:example.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-https-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-https-single-slash-novalid.html
new file mode 100644
index 00000000000..7b3fec7e8e1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-https-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-https-single-slash</title>
+<embed src="https:/example.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-javascript-no-slash-malformed-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-javascript-no-slash-malformed-novalid.html
new file mode 100644
index 00000000000..52aff9fb792
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-javascript-no-slash-malformed-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-javascript-no-slash-malformed</title>
+<embed src="javascript:example.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-trailing-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-trailing-cr-novalid.html
new file mode 100644
index 00000000000..f0c5d930765
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-trailing-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-trailing-cr</title>
+<embed src="a: foo.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-trailing-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-trailing-newline-novalid.html
new file mode 100644
index 00000000000..3829a82fe70
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-trailing-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-trailing-newline</title>
+<embed src="a:
+foo.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-trailing-space-novalid.html
new file mode 100644
index 00000000000..e3a98caec64
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-trailing-space</title>
+<embed src="a: foo.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-trailing-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-trailing-tab-novalid.html
new file mode 100644
index 00000000000..6a1610d619e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/scheme-trailing-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-trailing-tab</title>
+<embed src="a: foo.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/userinfo-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/userinfo-backslash-novalid.html
new file mode 100644
index 00000000000..d662052c126
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/userinfo-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: userinfo-backslash</title>
+<embed src="http://a\b:c\d@foo.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/userinfo-password-bad-chars-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/userinfo-password-bad-chars-novalid.html
new file mode 100644
index 00000000000..ebd7452064c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/userinfo-password-bad-chars-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: userinfo-password-bad-chars</title>
+<embed src="http://&a:foo(b]c@d:2/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/userinfo-password-contains-pile-of-poo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/userinfo-password-contains-pile-of-poo-novalid.html
new file mode 100644
index 00000000000..658d48c4657
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/userinfo-password-contains-pile-of-poo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: userinfo-password-contains-pile-of-poo</title>
+<embed src="http://foo:💩@example.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/userinfo-username-contains-at-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/userinfo-username-contains-at-sign-novalid.html
new file mode 100644
index 00000000000..d0963b79538
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/userinfo-username-contains-at-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: userinfo-username-contains-at-sign</title>
+<embed src="http://::@c@d:2">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/userinfo-username-contains-pile-of-poo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/userinfo-username-contains-pile-of-poo-novalid.html
new file mode 100644
index 00000000000..6f102c35315
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/src/userinfo-username-contains-pile-of-poo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: userinfo-username-contains-pile-of-poo</title>
+<embed src="http://💩:foo@example.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/type-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/type-novalid.html
new file mode 100644
index 00000000000..c6d456e4666
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/type-novalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>element embed with bad type value</title>
+</head>
+<body>
+<embed type="foo">
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/width-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/width-novalid.html
new file mode 100644
index 00000000000..7e6e4449c9a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/embed/width-novalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>element embed with bad width value</title>
+</head>
+<body>
+<embed width="20%">
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/footer/nested-footer-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/footer/nested-footer-novalid.html
new file mode 100644
index 00000000000..1dd79e86476
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/footer/nested-footer-novalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>"footer" with "footer" descendant</title>
+</head>
+<body>
+<footer>
+<footer></footer>
+</footer>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/footer/nested-header-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/footer/nested-header-novalid.html
new file mode 100644
index 00000000000..26c60a31f54
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/footer/nested-header-novalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>"footer" with "header" descendant</title>
+</head>
+<body>
+<footer>
+<header></header>
+</footer>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action-empty-novalid.html
new file mode 100644
index 00000000000..4090e01ce61
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>empty action is not valid</title>
+<form action=""></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action-isvalid.html
new file mode 100644
index 00000000000..a7fb1360d92
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action-isvalid.html
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid action</title>
+<form action="file:///"></form><!-- scheme-file-slash-slash-slash-only -->
+<form action="http://a:@www.example.com"></form><!-- userinfo-password-empty -->
+<form action="foo://///////"></form><!-- scheme-private-path-leading-slashes-only -->
+<form action="file://abc|/foo/bar"></form><!-- scheme-file-slash-slash-abc-bar -->
+<form action="/a/b/c"></form><!-- path-simple-relative -->
+<form action="http://example.com/你好你好"></form><!-- path-unicode-han -->
+<form action="/a/%2f/c"></form><!-- path-percent-encoded-slash-plus-slashes-relative -->
+<form action="http://f:/c"></form><!-- port-none-but-colon -->
+<form action="http://example.com/foo%41%7a"></form><!-- path-percent-encoded-multiple -->
+<form action="http://192.168.0.257/"></form><!-- host-IP-address-broken -->
+<form action="madeupscheme:example.com/"></form><!-- scheme-private-no-slash -->
+<form action="?"></form><!-- query-empty-no-path-relative -->
+<form action="http://example.com/%20foo"></form><!-- path-percent-encoded-space -->
+<form action="mailto:/example.com/"></form><!-- scheme-mailto-single-slash -->
+<form action="::"></form><!-- path-leading-colon-colon-relative -->
+<form action="http://example.com/%3A%3a%3C%3c"></form><!-- path-percent-encoded-mixed-case -->
+<form action="http://user:pass@foo:21/bar;par?b#c"></form><!-- userinfo -->
+<form action="ws:/example.com/"></form><!-- scheme-ws-single-slash -->
+<form action="foo://"></form><!-- scheme-private-slash-slash -->
+<form action="#"></form><!-- fragment-empty-hash-only-no-path-relative -->
+<form action="http://f:00000000000000/c"></form><!-- port-00000000000000 -->
+<form action="foo:////://///"></form><!-- scheme-private-path-leading-slashes-colon-slashes -->
+<form action=":23"></form><!-- path-leading-colon-number-relative -->
+<form action="foo:/"></form><!-- scheme-private-slash -->
+<form action="http://💩"></form><!-- host-is-pile-of-poo -->
+<form action="file:test"></form><!-- scheme-file-no-slash -->
+<form action="file://C|/foo/bar"></form><!-- scheme-file-slash-slash-c-bar -->
+<form action="#/"></form><!-- fragment-slash-relative -->
+<form action="http://192.0x00A80001"></form><!-- host-192.0x00A80001 -->
+<form action="foo.com"></form><!-- scheme-none-relative -->
+<form action="http💩//:foo"></form><!-- path-contains-pile-of-poo -->
+<form action="File://foo/bar.html"></form><!-- scheme-file-uppercase -->
+<form action=":/"></form><!-- path-leading-colon-slash-relative -->
+<form action="http://www.foo。bar.com"></form><!-- host-exotic-dot -->
+<form action="http://GOO​⁠goo.com"></form><!-- host-exotic-whitespace -->
+<form action="file:///foo/bar.txt"></form><!-- scheme-file-host-empty -->
+<form action="javascript:/example.com/"></form><!-- scheme-javascript-single-slash -->
+<form action="gopher:/example.com/"></form><!-- scheme-gopher-single-slash -->
+<form action="ftps:example.com/"></form><!-- scheme-ftps-no-slash -->
+<form action="file://server/foo/bar"></form><!-- scheme-file-host-included -->
+<form action="http://example.com/foo%00"></form><!-- path-percent-encoded-u0000 -->
+<form action="a:foo.com"></form><!-- scheme-private -->
+<form action=":"></form><!-- path-colon-relative -->
+<form action="http://:b@www.example.com"></form><!-- userinfo-user-empty -->
+<form action="file:/"></form><!-- scheme-file-slash-only -->
+<form action="wss:example.com/"></form><!-- scheme-wss-no-slash -->
+<form action="::23"></form><!-- path-colon-colon-number-relative -->
+<form action="/a%2fc"></form><!-- path-percent-encoded-slash-relative -->
+<form action="http://a:b@c:29/d"></form><!-- userinfo-host-port-path -->
+<form action="gopher:example.com/"></form><!-- scheme-gopher-no-slash -->
+<form action="madeupscheme:/example.com/"></form><!-- scheme-private-single-slash -->
+<form action="mailto:example.com/"></form><!-- scheme-mailto-no-slash -->
+<form action="http://%25DOMAIN:foobar@foodomain.com"></form><!-- userinfo-username-contains-percent-encoded -->
+<form action="/:23"></form><!-- path-slash-colon-number-relative -->
+<form action="foo://///////bar.com/"></form><!-- scheme-private-path-leading-slashes-chars -->
+<form action="http://[2001::1]:80"></form><!-- host-ipv6-port -->
+<form action="data:text/plain,foo"></form><!-- scheme-data-no-slash -->
+<form action="http://example.com/foo/%2e"></form><!-- path-percent-encoded-dot -->
+<form action="file:/example.com/"></form><!-- scheme-file-single-slash -->
+<form action="http://example.com/©zbar"></form><!-- path-non-ascii -->
+<form action="http://example.com//foo"></form><!-- path-uFEFF -->
+<form action="wss:/example.com/"></form><!-- scheme-wss-single-slash -->
+<form action="http://foo/abcd#foo?bar"></form><!-- fragment-contains-question-mark -->
+<form action=":#"></form><!-- path-leading-colon-hash-relative -->
+<form action="http://example.com/foo%91"></form><!-- path-percent-encoded-u0091 -->
+<form action="c:/foo"></form><!-- scheme-private-single-letter -->
+<form action=":foo.com"></form><!-- path-leading-colon-chars-relative -->
+<form action="http://你好你好"></form><!-- host-idn-unicode-han -->
+<form action="http://example.com/foo#💩"></form><!-- fragment-contains-pile-of-poo -->
+<form action="file:"></form><!-- scheme-file-scheme-only -->
+<form action="#β"></form><!-- fragment-non-ascii-relative -->
+<form action="foo:/bar.com/"></form><!-- scheme-private-path -->
+<form action="http://f:0/c"></form><!-- port-0 -->
+<form action="#;?"></form><!-- fragment-semicolon-question-mark-relative -->
+<form action="http://Go.com"></form><!-- host-fullwidth -->
+<form action="http://@www.example.com"></form><!-- userinfo-empty -->
+<form action="http://example.com/‮/foo/‭/bar"></form><!-- path-u202E-u202D -->
+<form action="http://[2001::1]"></form><!-- host-ipv6 -->
+<form action="💩http://foo"></form><!-- path-starts-with-pile-of-poo -->
+<form action="http://foo/abcd?efgh?ijkl"></form><!-- query-contains-question-mark -->
+<form action="//foo/bar"></form><!-- scheme-schemeless-relative -->
+<form action="ftps:/example.com/"></form><!-- scheme-ftps-single-slash -->
+<form action="http://foo.com:b@d/"></form><!-- userinfo-username-non-alpha -->
+<form action=":a"></form><!-- path-leading-colon-letter-relative -->
+<form action="/"></form><!-- path-slash-only-relative -->
+<form action="http://example.com/foo?💩"></form><!-- query-contains-pile-of-poo -->
+<form action="http://f:00000000000000000000080/c"></form><!-- port-00000000000000000000080 -->
+<form action="file://"></form><!-- scheme-file-slash-slash-only -->
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action-whitespace-only-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action-whitespace-only-novalid.html
new file mode 100644
index 00000000000..23222c775db
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action-whitespace-only-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>empty action is not valid</title>
+<form action="
+"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/fragment-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/fragment-backslash-novalid.html
new file mode 100644
index 00000000000..d5a014727bd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/fragment-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: fragment-backslash</title>
+<form action="#\"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/fragment-contains-hash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/fragment-contains-hash-novalid.html
new file mode 100644
index 00000000000..8dfcce917a0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/fragment-contains-hash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: fragment-contains-hash</title>
+<form action="http://foo/path#f#g"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/fragment-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/fragment-leading-space-novalid.html
new file mode 100644
index 00000000000..b95be6bed35
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/fragment-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: fragment-leading-space</title>
+<form action="http://f:21/b# e"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-cr-novalid.html
new file mode 100644
index 00000000000..57be7114fb5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: host-cr</title>
+<form action="http://example. org"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-double-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-double-percent-encoded-novalid.html
new file mode 100644
index 00000000000..df5e0d4a08e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-double-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: host-double-percent-encoded</title>
+<form action="http://%41.com"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-double-percent-encoded-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-double-percent-encoded-percent-encoded-novalid.html
new file mode 100644
index 00000000000..eab6133a82e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-double-percent-encoded-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: host-double-percent-encoded-percent-encoded</title>
+<form action="http://%ef%bc%85%ef%bc%94%ef%bc%91.com"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-empty-novalid.html
new file mode 100644
index 00000000000..1879fc86dfe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: host-empty</title>
+<form action="http://"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-empty-userinfo-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-empty-userinfo-empty-novalid.html
new file mode 100644
index 00000000000..e7689786458
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-empty-userinfo-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: host-empty-userinfo-empty</title>
+<form action="http://@/www.example.com"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-empty-with-userinfo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-empty-with-userinfo-novalid.html
new file mode 100644
index 00000000000..dceaae334d9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-empty-with-userinfo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: host-empty-with-userinfo</title>
+<form action="http://user:pass@/"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-hostname-in-brackets-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-hostname-in-brackets-novalid.html
new file mode 100644
index 00000000000..9d707cd4da7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-hostname-in-brackets-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: host-hostname-in-brackets</title>
+<form action="http://[www.google.com]/"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-invalid-unicode-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-invalid-unicode-novalid.html
new file mode 100644
index 00000000000..6613d7ae5c4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-invalid-unicode-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: host-invalid-unicode</title>
+<form action="http://﷐zyx.com"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-invalid-unicode-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-invalid-unicode-percent-encoded-novalid.html
new file mode 100644
index 00000000000..cbabc9d37c8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-invalid-unicode-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: host-invalid-unicode-percent-encoded</title>
+<form action="http://%ef%b7%90zyx.com"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-newline-novalid.html
new file mode 100644
index 00000000000..f3c90d5ef61
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: host-newline</title>
+<form action="http://example.
+org"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-space-novalid.html
new file mode 100644
index 00000000000..a1155951197
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: host-space</title>
+<form action="http://example .org"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-square-brackets-port-contains-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-square-brackets-port-contains-colon-novalid.html
new file mode 100644
index 00000000000..88042b5ab8a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-square-brackets-port-contains-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: host-square-brackets-port-contains-colon</title>
+<form action="http://[1::2]:3:4"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-tab-novalid.html
new file mode 100644
index 00000000000..a36e6597f7a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: host-tab</title>
+<form action="http://example .org"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-u0000-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-u0000-percent-encoded-novalid.html
new file mode 100644
index 00000000000..fc500a0b08a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-u0000-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: host-u0000-percent-encoded</title>
+<form action="http://%00.com"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-u0000-percent-encoded-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-u0000-percent-encoded-percent-encoded-novalid.html
new file mode 100644
index 00000000000..0f9f20a4a50
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/host-u0000-percent-encoded-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: host-u0000-percent-encoded-percent-encoded</title>
+<form action="http://%ef%bc%85%ef%bc%90%ef%bc%90.com"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/path-bare-percent-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/path-bare-percent-sign-novalid.html
new file mode 100644
index 00000000000..be8318b82c1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/path-bare-percent-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: path-bare-percent-sign</title>
+<form action="http://example.com/foo%"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/path-contains-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/path-contains-space-novalid.html
new file mode 100644
index 00000000000..4194fbad8da
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/path-contains-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: path-contains-space</title>
+<form action="/a/ /c"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/path-leading-backslash-at-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/path-leading-backslash-at-sign-novalid.html
new file mode 100644
index 00000000000..e41abc4a461
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/path-leading-backslash-at-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: path-leading-backslash-at-sign</title>
+<form action="http://foo.com/\@"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/path-leading-colon-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/path-leading-colon-backslash-novalid.html
new file mode 100644
index 00000000000..a967ca78a85
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/path-leading-colon-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: path-leading-colon-backslash</title>
+<form action=":\"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/path-leading-colon-chars-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/path-leading-colon-chars-backslash-novalid.html
new file mode 100644
index 00000000000..2f50a571e8f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/path-leading-colon-chars-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: path-leading-colon-chars-backslash</title>
+<form action=":foo.com\"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/path-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/path-leading-space-novalid.html
new file mode 100644
index 00000000000..fae910c82bc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/path-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: path-leading-space</title>
+<form action="http://f:21/ b"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/path-percent-encoded-malformed-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/path-percent-encoded-malformed-novalid.html
new file mode 100644
index 00000000000..cc43c394217
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/path-percent-encoded-malformed-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: path-percent-encoded-malformed</title>
+<form action="http://example.com/foo/%2e%2"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/path-relative-square-brackets-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/path-relative-square-brackets-novalid.html
new file mode 100644
index 00000000000..b90ce68330c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/path-relative-square-brackets-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: path-relative-square-brackets</title>
+<form action="[61:24:74]:98"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/path-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/path-tab-novalid.html
new file mode 100644
index 00000000000..c08a28800c6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/path-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: path-tab</title>
+<form action="http://example.com/foo bar"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/path-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/path-trailing-space-novalid.html
new file mode 100644
index 00000000000..866ba41c58c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/path-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: path-trailing-space</title>
+<form action="http://f:21/b ?"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/path-u0091-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/path-u0091-novalid.html
new file mode 100644
index 00000000000..7f2bd6d669e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/path-u0091-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: path-u0091</title>
+<form action="http://example.com/foo‘"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/port-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/port-cr-novalid.html
new file mode 100644
index 00000000000..07413a33683
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/port-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: port-cr</title>
+<form action="http://f: /c"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/port-leading-colon-bracket-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/port-leading-colon-bracket-colon-novalid.html
new file mode 100644
index 00000000000..ca12578b0cd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/port-leading-colon-bracket-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: port-leading-colon-bracket-colon</title>
+<form action="http://2001::1]:80"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/port-leading-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/port-leading-colon-novalid.html
new file mode 100644
index 00000000000..ab06dfb6fda
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/port-leading-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: port-leading-colon</title>
+<form action="http://2001::1"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/port-leading-dash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/port-leading-dash-novalid.html
new file mode 100644
index 00000000000..2192f87f6da
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/port-leading-dash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: port-leading-dash</title>
+<form action="http://foo:-80/"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/port-multiple-letters-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/port-multiple-letters-novalid.html
new file mode 100644
index 00000000000..def350e6c1c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/port-multiple-letters-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: port-multiple-letters</title>
+<form action="http://f:fifty-two/c"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/port-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/port-newline-novalid.html
new file mode 100644
index 00000000000..deeaa68a307
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/port-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: port-newline</title>
+<form action="http://f:
+/c"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/port-single-letter-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/port-single-letter-novalid.html
new file mode 100644
index 00000000000..7aa8b83b632
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/port-single-letter-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: port-single-letter</title>
+<form action="http://f:b/c"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/port-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/port-space-novalid.html
new file mode 100644
index 00000000000..27b549e4613
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/port-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: port-space</title>
+<form action="http://f: /c"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/port-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/port-tab-novalid.html
new file mode 100644
index 00000000000..99f6b9b0d6b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/port-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: port-tab</title>
+<form action="http://f: /c"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/query-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/query-leading-space-novalid.html
new file mode 100644
index 00000000000..5c18e9aaea4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/query-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: query-leading-space</title>
+<form action="http://f:21/b? d"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/query-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/query-trailing-space-novalid.html
new file mode 100644
index 00000000000..103f75b79f3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/query-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: query-trailing-space</title>
+<form action="http://f:21/b?d #"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-data-contains-fragment-haswarn.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-data-contains-fragment-haswarn.html
new file mode 100644
index 00000000000..ba826225e76
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-data-contains-fragment-haswarn.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>data:text/html,test#test warning: scheme-data-contains-fragment</title>
+<form action="data:text/html,test#test"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-data-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-data-single-slash-novalid.html
new file mode 100644
index 00000000000..738714d1a7d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-data-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: scheme-data-single-slash</title>
+<form action="data:/example.com/"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-file-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-file-backslash-novalid.html
new file mode 100644
index 00000000000..7e944c6572e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-file-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: scheme-file-backslash</title>
+<form action="file:c:\foo\bar.html"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-file-single-slash-c-bar-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-file-single-slash-c-bar-novalid.html
new file mode 100644
index 00000000000..c72ada05313
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-file-single-slash-c-bar-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: scheme-file-single-slash-c-bar</title>
+<form action="file:/C|/foo/bar"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-file-triple-slash-c-bar-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-file-triple-slash-c-bar-novalid.html
new file mode 100644
index 00000000000..e4b1bbaadc5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-file-triple-slash-c-bar-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: scheme-file-triple-slash-c-bar</title>
+<form action="file:///C|/foo/bar"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-ftp-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-ftp-no-slash-novalid.html
new file mode 100644
index 00000000000..ea5f35911c8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-ftp-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: scheme-ftp-no-slash</title>
+<form action="ftp:example.com/"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-ftp-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-ftp-single-slash-novalid.html
new file mode 100644
index 00000000000..9629bb8a63a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-ftp-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: scheme-ftp-single-slash</title>
+<form action="ftp:/example.com/"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-http-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-http-backslash-novalid.html
new file mode 100644
index 00000000000..672a812f837
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-http-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: scheme-http-backslash</title>
+<form action="http:\\foo.com\"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-http-no-slash-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-http-no-slash-colon-novalid.html
new file mode 100644
index 00000000000..e6f8f724e77
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-http-no-slash-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: scheme-http-no-slash-colon</title>
+<form action="http::@c:29"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-http-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-http-no-slash-novalid.html
new file mode 100644
index 00000000000..d53e1a2fd60
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-http-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: scheme-http-no-slash</title>
+<form action="http:foo.com"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-http-no-slash-square-bracket-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-http-no-slash-square-bracket-novalid.html
new file mode 100644
index 00000000000..506ac46f3a7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-http-no-slash-square-bracket-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: scheme-http-no-slash-square-bracket</title>
+<form action="http:[61:27]/:foo"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-http-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-http-single-slash-novalid.html
new file mode 100644
index 00000000000..047e218b074
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-http-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: scheme-http-single-slash</title>
+<form action="http:/example.com/"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-https-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-https-no-slash-novalid.html
new file mode 100644
index 00000000000..8cb2a7f583c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-https-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: scheme-https-no-slash</title>
+<form action="https:example.com/"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-https-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-https-single-slash-novalid.html
new file mode 100644
index 00000000000..be422fdbff3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-https-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: scheme-https-single-slash</title>
+<form action="https:/example.com/"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-javascript-no-slash-malformed-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-javascript-no-slash-malformed-novalid.html
new file mode 100644
index 00000000000..bc66953ab7d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-javascript-no-slash-malformed-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: scheme-javascript-no-slash-malformed</title>
+<form action="javascript:example.com/"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-trailing-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-trailing-cr-novalid.html
new file mode 100644
index 00000000000..6090097a686
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-trailing-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: scheme-trailing-cr</title>
+<form action="a: foo.com"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-trailing-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-trailing-newline-novalid.html
new file mode 100644
index 00000000000..50c64a94f7b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-trailing-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: scheme-trailing-newline</title>
+<form action="a:
+foo.com"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-trailing-space-novalid.html
new file mode 100644
index 00000000000..8632616c2c3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: scheme-trailing-space</title>
+<form action="a: foo.com"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-trailing-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-trailing-tab-novalid.html
new file mode 100644
index 00000000000..cd39c5ad629
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/scheme-trailing-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: scheme-trailing-tab</title>
+<form action="a: foo.com"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/userinfo-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/userinfo-backslash-novalid.html
new file mode 100644
index 00000000000..37ef4f20180
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/userinfo-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: userinfo-backslash</title>
+<form action="http://a\b:c\d@foo.com"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/userinfo-password-bad-chars-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/userinfo-password-bad-chars-novalid.html
new file mode 100644
index 00000000000..1ed632962c5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/userinfo-password-bad-chars-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: userinfo-password-bad-chars</title>
+<form action="http://&a:foo(b]c@d:2/"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/userinfo-password-contains-pile-of-poo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/userinfo-password-contains-pile-of-poo-novalid.html
new file mode 100644
index 00000000000..33460c9ffbb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/userinfo-password-contains-pile-of-poo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: userinfo-password-contains-pile-of-poo</title>
+<form action="http://foo:💩@example.com"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/userinfo-username-contains-at-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/userinfo-username-contains-at-sign-novalid.html
new file mode 100644
index 00000000000..03cf279264f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/userinfo-username-contains-at-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: userinfo-username-contains-at-sign</title>
+<form action="http://::@c@d:2"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/userinfo-username-contains-pile-of-poo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/userinfo-username-contains-pile-of-poo-novalid.html
new file mode 100644
index 00000000000..ccc38c24f42
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/form/action/userinfo-username-contains-pile-of-poo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid action: userinfo-username-contains-pile-of-poo</title>
+<form action="http://💩:foo@example.com"></form>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/h1/model-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/h1/model-isvalid.html
new file mode 100644
index 00000000000..3e92f42e541
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/h1/model-isvalid.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;h1&gt;</title>
+</head>
+<body>
+ <!-- is block -->
+ <h1 class="class" id="id" lang="en">text</h1>
+
+ <!-- can contain strictly inline -->
+ <h1>text <em>elem</em></h1>
+
+ <!-- can contain interactive -->
+ <h1><a>text</a></h1>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/h1/model-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/h1/model-novalid.html
new file mode 100644
index 00000000000..86eafc073d2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/h1/model-novalid.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;h1&gt;</title>
+</head>
+<body>
+ <!-- is not strictly inline -->
+ <p><dfn>text
+ <h1>more text</h1>
+ </dfn></p>
+
+ <!-- is not structured inline -->
+ <p>text
+ <h1>more text</h1>
+ </p>
+
+ <!-- cannot contain blocks -->
+ <h1>
+ <p>p1</p>
+ <p>p2</p>
+ </h1>
+
+ <!-- cannot contain structured inline -->
+ <h1>text
+ <ul><li>text</li></ul>
+ </h1>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/h2/model-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/h2/model-isvalid.html
new file mode 100644
index 00000000000..d1767ecaf6f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/h2/model-isvalid.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;h2&gt;</title>
+</head>
+<body>
+ <!-- is block -->
+ <h2 class="class" id="id" lang="en">text</h2>
+
+ <!-- can contain strictly inline -->
+ <h2>text <em>elem</em></h2>
+
+ <!-- can contain interactive -->
+ <h2><a>text</a></h2>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/h2/model-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/h2/model-novalid.html
new file mode 100644
index 00000000000..f4374f4fbfd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/h2/model-novalid.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;h2&gt;</title>
+</head>
+<body>
+ <!-- is not strictly inline -->
+ <p><dfn>text
+ <h2>more text</h2>
+ </dfn></p>
+
+ <!-- is not structured inline -->
+ <p>text
+ <h2>more text</h2>
+ </p>
+
+ <!-- cannot contain blocks -->
+ <h2>
+ <p>p1</p>
+ <p>p2</p>
+ </h2>
+
+ <!-- cannot contain structured inline -->
+ <h2>text
+ <ul><li>text</li></ul>
+ </h2>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/h3/model-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/h3/model-isvalid.html
new file mode 100644
index 00000000000..29a870ea4e0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/h3/model-isvalid.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;h3&gt;</title>
+</head>
+<body>
+ <!-- is block -->
+ <h3 class="class" id="id" lang="en">text</h3>
+
+ <!-- can contain strictly inline -->
+ <h3>text <em>elem</em></h3>
+
+ <!-- can contain interactive -->
+ <h3><a>text</a></h3>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/h3/model-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/h3/model-novalid.html
new file mode 100644
index 00000000000..8df7903332b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/h3/model-novalid.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;h3&gt;</title>
+</head>
+<body>
+ <!-- is not strictly inline -->
+ <p><dfn>text
+ <h3>more text</h3>
+ </dfn></p>
+
+ <!-- is not structured inline -->
+ <p>text
+ <h3>more text</h3>
+ </p>
+
+ <!-- cannot contain blocks -->
+ <h3>
+ <p>p1</p>
+ <p>p2</p>
+ </h3>
+
+ <!-- cannot contain structured inline -->
+ <h3>text
+ <ul><li>text</li></ul>
+ </h3>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/h4/model-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/h4/model-isvalid.html
new file mode 100644
index 00000000000..657ed6a3330
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/h4/model-isvalid.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;h4&gt;</title>
+</head>
+<body>
+ <!-- is block -->
+ <h4 class="class" id="id" lang="en">text</h4>
+
+ <!-- can contain strictly inline -->
+ <h4>text <em>elem</em></h4>
+
+ <!-- can contain interactive -->
+ <h4><a>text</a></h4>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/h4/model-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/h4/model-novalid.html
new file mode 100644
index 00000000000..1a0b1f28e39
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/h4/model-novalid.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;h4&gt;</title>
+</head>
+<body>
+ <!-- is not strictly inline -->
+ <p><dfn>text
+ <h4>more text</h4>
+ </dfn></p>
+
+ <!-- is not structured inline -->
+ <p>text
+ <h4>more text</h4>
+ </p>
+
+ <!-- cannot contain blocks -->
+ <h4>
+ <p>p1</p>
+ <p>p2</p>
+ </h4>
+
+ <!-- cannot contain structured inline -->
+ <h4>text
+ <ul><li>text</li></ul>
+ </h4>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/h5/model-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/h5/model-isvalid.html
new file mode 100644
index 00000000000..6060e03849f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/h5/model-isvalid.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;h5&gt;</title>
+</head>
+<body>
+ <!-- is block -->
+ <h5 class="class" id="id" lang="en">text</h5>
+
+ <!-- can contain strictly inline -->
+ <h5>text <em>elem</em></h5>
+
+ <!-- can contain interactive -->
+ <h5><a>text</a></h5>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/h5/model-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/h5/model-novalid.html
new file mode 100644
index 00000000000..c88504826f4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/h5/model-novalid.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;h5&gt;</title>
+</head>
+<body>
+ <!-- is not strictly inline -->
+ <p><dfn>text
+ <h5>more text</h5>
+ </dfn></p>
+
+ <!-- is not structured inline -->
+ <p>text
+ <h5>more text</h5>
+ </p>
+
+ <!-- cannot contain blocks -->
+ <h5>
+ <p>p1</p>
+ <p>p2</p>
+ </h5>
+
+ <!-- cannot contain structured inline -->
+ <h5>text
+ <ul><li>text</li></ul>
+ </h5>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/h6/model-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/h6/model-isvalid.html
new file mode 100644
index 00000000000..9f971bd6ff8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/h6/model-isvalid.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;h6&gt;</title>
+</head>
+<body>
+ <!-- is block -->
+ <h6 class="class" id="id" lang="en">text</h6>
+
+ <!-- can contain strictly inline -->
+ <h6>text <em>elem</em></h6>
+
+ <!-- can contain interactive -->
+ <h6><a>text</a></h6>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/h6/model-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/h6/model-novalid.html
new file mode 100644
index 00000000000..a9a393e4c43
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/h6/model-novalid.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;h6&gt;</title>
+</head>
+<body>
+ <!-- is not strictly inline -->
+ <p><dfn>text
+ <h6>more text</h6>
+ </dfn></p>
+
+ <!-- is not structured inline -->
+ <p>text
+ <h6>more text</h6>
+ </p>
+
+ <!-- cannot contain blocks -->
+ <h6>
+ <p>p1</p>
+ <p>p2</p>
+ </h6>
+
+ <!-- cannot contain structured inline -->
+ <h6>text
+ <ul><li>text</li></ul>
+ </h6>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/header/nested-footer-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/header/nested-footer-novalid.html
new file mode 100644
index 00000000000..958f974ee0b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/header/nested-footer-novalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>"header" with "footer" descendant</title>
+</head>
+<body>
+<header>
+<footer></footer>
+</header>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/header/nested-header-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/header/nested-header-novalid.html
new file mode 100644
index 00000000000..0a4d8b51ce5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/header/nested-header-novalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>"header" with "header" descendant</title>
+</head>
+<body>
+<header>
+<header></header>
+</header>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/hr/model-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/hr/model-isvalid.html
new file mode 100644
index 00000000000..4202896bd57
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/hr/model-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;hr&gt;</title>
+</head>
+<body>
+ <!-- is block -->
+ <hr class="class" id="id" lang="en">
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/hr/model-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/hr/model-novalid.html
new file mode 100644
index 00000000000..1c76bfb6b1a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/hr/model-novalid.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;hr&gt;</title>
+</head>
+<body>
+ <!-- is not structured inline -->
+ <p>
+ <ul>
+ <li>
+ <hr>
+ </li>
+ </ul>
+ </p>
+
+ <!-- is not strictly inline -->
+ <p><dfn>text
+ <hr>
+ </dfn></p>
+
+ <!-- must be empty -->
+ <hr>
+ <p>p1</p>
+
+ <hr><em>text</em>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest-empty-novalid.html
new file mode 100644
index 00000000000..23b82f543ca
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest-empty-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="">
+<meta charset=utf-8>
+<title>empty manifest is not valid</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest-whitespace-only-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest-whitespace-only-novalid.html
new file mode 100644
index 00000000000..d9ee8070a02
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest-whitespace-only-novalid.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<html manifest="
+">
+<meta charset=utf-8>
+<title>empty manifest is not valid</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/fragment-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/fragment-backslash-novalid.html
new file mode 100644
index 00000000000..00259455e15
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/fragment-backslash-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="#\">
+<meta charset=utf-8>
+<title>invalid manifest: fragment-backslash</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/fragment-contains-hash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/fragment-contains-hash-novalid.html
new file mode 100644
index 00000000000..09d918e3eaa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/fragment-contains-hash-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://foo/path#f#g">
+<meta charset=utf-8>
+<title>invalid manifest: fragment-contains-hash</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/fragment-contains-pile-of-poo-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/fragment-contains-pile-of-poo-isvalid.html
new file mode 100644
index 00000000000..fffad819a85
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/fragment-contains-pile-of-poo-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://example.com/foo#💩">
+<meta charset=utf-8>
+<title>valid manifest: fragment-contains-pile-of-poo</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/fragment-contains-question-mark-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/fragment-contains-question-mark-isvalid.html
new file mode 100644
index 00000000000..19187c700c5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/fragment-contains-question-mark-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://foo/abcd#foo?bar">
+<meta charset=utf-8>
+<title>valid manifest: fragment-contains-question-mark</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/fragment-empty-hash-only-no-path-relative-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/fragment-empty-hash-only-no-path-relative-isvalid.html
new file mode 100644
index 00000000000..27b57ce2372
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/fragment-empty-hash-only-no-path-relative-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="#">
+<meta charset=utf-8>
+<title>valid manifest: fragment-empty-hash-only-no-path-relative</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/fragment-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/fragment-leading-space-novalid.html
new file mode 100644
index 00000000000..c150d0835bb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/fragment-leading-space-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://f:21/b# e">
+<meta charset=utf-8>
+<title>invalid manifest: fragment-leading-space</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/fragment-non-ascii-relative-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/fragment-non-ascii-relative-isvalid.html
new file mode 100644
index 00000000000..fb991b68e62
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/fragment-non-ascii-relative-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="#β">
+<meta charset=utf-8>
+<title>valid manifest: fragment-non-ascii-relative</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/fragment-semicolon-question-mark-relative-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/fragment-semicolon-question-mark-relative-isvalid.html
new file mode 100644
index 00000000000..ea5b805626e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/fragment-semicolon-question-mark-relative-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="#;?">
+<meta charset=utf-8>
+<title>valid manifest: fragment-semicolon-question-mark-relative</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/fragment-slash-relative-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/fragment-slash-relative-isvalid.html
new file mode 100644
index 00000000000..6ce956067fd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/fragment-slash-relative-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="#/">
+<meta charset=utf-8>
+<title>valid manifest: fragment-slash-relative</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-192.0x00A80001-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-192.0x00A80001-isvalid.html
new file mode 100644
index 00000000000..345fd9d6408
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-192.0x00A80001-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://192.0x00A80001">
+<meta charset=utf-8>
+<title>valid manifest: host-192.0x00A80001</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-IP-address-broken-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-IP-address-broken-isvalid.html
new file mode 100644
index 00000000000..38865022c0f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-IP-address-broken-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://192.168.0.257/">
+<meta charset=utf-8>
+<title>valid manifest: host-IP-address-broken</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-IP-address-fullwidth-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-IP-address-fullwidth-isvalid.html
new file mode 100644
index 00000000000..10666ae29d1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-IP-address-fullwidth-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://0Xc0.0250.01">
+<meta charset=utf-8>
+<title>valid manifest: host-IP-address-fullwidth</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-IP-address-percent-encoded-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-IP-address-percent-encoded-isvalid.html
new file mode 100644
index 00000000000..200da79baf8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-IP-address-percent-encoded-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://%30%78%63%30%2e%30%32%35%30.01">
+<meta charset=utf-8>
+<title>valid manifest: host-IP-address-percent-encoded</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-cr-novalid.html
new file mode 100644
index 00000000000..67825718acd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-cr-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://example. org">
+<meta charset=utf-8>
+<title>invalid manifest: host-cr</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-double-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-double-percent-encoded-novalid.html
new file mode 100644
index 00000000000..e18e4216b9a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-double-percent-encoded-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://%41.com">
+<meta charset=utf-8>
+<title>invalid manifest: host-double-percent-encoded</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-double-percent-encoded-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-double-percent-encoded-percent-encoded-novalid.html
new file mode 100644
index 00000000000..b2f7fb39912
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-double-percent-encoded-percent-encoded-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://%ef%bc%85%ef%bc%94%ef%bc%91.com">
+<meta charset=utf-8>
+<title>invalid manifest: host-double-percent-encoded-percent-encoded</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-empty-novalid.html
new file mode 100644
index 00000000000..c24cde01edd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-empty-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://">
+<meta charset=utf-8>
+<title>invalid manifest: host-empty</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-empty-userinfo-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-empty-userinfo-empty-novalid.html
new file mode 100644
index 00000000000..36e22f73651
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-empty-userinfo-empty-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://@/www.example.com">
+<meta charset=utf-8>
+<title>invalid manifest: host-empty-userinfo-empty</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-empty-with-userinfo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-empty-with-userinfo-novalid.html
new file mode 100644
index 00000000000..80b3f8f076c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-empty-with-userinfo-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://user:pass@/">
+<meta charset=utf-8>
+<title>invalid manifest: host-empty-with-userinfo</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-exotic-dot-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-exotic-dot-isvalid.html
new file mode 100644
index 00000000000..fa81d73b01f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-exotic-dot-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://www.foo。bar.com">
+<meta charset=utf-8>
+<title>valid manifest: host-exotic-dot</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-exotic-whitespace-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-exotic-whitespace-isvalid.html
new file mode 100644
index 00000000000..04d2499cace
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-exotic-whitespace-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://GOO​⁠goo.com">
+<meta charset=utf-8>
+<title>valid manifest: host-exotic-whitespace</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-fullwidth-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-fullwidth-isvalid.html
new file mode 100644
index 00000000000..9d355c9eac8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-fullwidth-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://Go.com">
+<meta charset=utf-8>
+<title>valid manifest: host-fullwidth</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-hostname-in-brackets-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-hostname-in-brackets-novalid.html
new file mode 100644
index 00000000000..a651c000396
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-hostname-in-brackets-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://[www.google.com]/">
+<meta charset=utf-8>
+<title>invalid manifest: host-hostname-in-brackets</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-idn-unicode-han-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-idn-unicode-han-isvalid.html
new file mode 100644
index 00000000000..71e9530f5eb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-idn-unicode-han-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://你好你好">
+<meta charset=utf-8>
+<title>valid manifest: host-idn-unicode-han</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-invalid-unicode-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-invalid-unicode-novalid.html
new file mode 100644
index 00000000000..d86538bd46a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-invalid-unicode-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://﷐zyx.com">
+<meta charset=utf-8>
+<title>invalid manifest: host-invalid-unicode</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-invalid-unicode-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-invalid-unicode-percent-encoded-novalid.html
new file mode 100644
index 00000000000..c5a3810d492
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-invalid-unicode-percent-encoded-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://%ef%b7%90zyx.com">
+<meta charset=utf-8>
+<title>invalid manifest: host-invalid-unicode-percent-encoded</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-ipv6-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-ipv6-isvalid.html
new file mode 100644
index 00000000000..c6cf132922c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-ipv6-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://[2001::1]">
+<meta charset=utf-8>
+<title>valid manifest: host-ipv6</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-ipv6-port-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-ipv6-port-isvalid.html
new file mode 100644
index 00000000000..18292187adf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-ipv6-port-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://[2001::1]:80">
+<meta charset=utf-8>
+<title>valid manifest: host-ipv6-port</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-is-pile-of-poo-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-is-pile-of-poo-isvalid.html
new file mode 100644
index 00000000000..a56696d181f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-is-pile-of-poo-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://💩">
+<meta charset=utf-8>
+<title>valid manifest: host-is-pile-of-poo</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-newline-novalid.html
new file mode 100644
index 00000000000..8b4f8e048da
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-newline-novalid.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<html manifest="http://example.
+org">
+<meta charset=utf-8>
+<title>invalid manifest: host-newline</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-space-novalid.html
new file mode 100644
index 00000000000..53d49012ee4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-space-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://example .org">
+<meta charset=utf-8>
+<title>invalid manifest: host-space</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-square-brackets-port-contains-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-square-brackets-port-contains-colon-novalid.html
new file mode 100644
index 00000000000..cb654811fea
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-square-brackets-port-contains-colon-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://[1::2]:3:4">
+<meta charset=utf-8>
+<title>invalid manifest: host-square-brackets-port-contains-colon</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-tab-novalid.html
new file mode 100644
index 00000000000..abc896073db
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-tab-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://example .org">
+<meta charset=utf-8>
+<title>invalid manifest: host-tab</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-u0000-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-u0000-percent-encoded-novalid.html
new file mode 100644
index 00000000000..f1f22dfb2fc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-u0000-percent-encoded-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://%00.com">
+<meta charset=utf-8>
+<title>invalid manifest: host-u0000-percent-encoded</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-u0000-percent-encoded-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-u0000-percent-encoded-percent-encoded-novalid.html
new file mode 100644
index 00000000000..bc5254117dd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/host-u0000-percent-encoded-percent-encoded-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://%ef%bc%85%ef%bc%90%ef%bc%90.com">
+<meta charset=utf-8>
+<title>invalid manifest: host-u0000-percent-encoded-percent-encoded</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-bare-percent-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-bare-percent-sign-novalid.html
new file mode 100644
index 00000000000..39cb890aa76
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-bare-percent-sign-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://example.com/foo%">
+<meta charset=utf-8>
+<title>invalid manifest: path-bare-percent-sign</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-colon-colon-number-relative-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-colon-colon-number-relative-isvalid.html
new file mode 100644
index 00000000000..9110e619424
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-colon-colon-number-relative-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="::23">
+<meta charset=utf-8>
+<title>valid manifest: path-colon-colon-number-relative</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-colon-relative-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-colon-relative-isvalid.html
new file mode 100644
index 00000000000..9387fbf07e9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-colon-relative-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest=":">
+<meta charset=utf-8>
+<title>valid manifest: path-colon-relative</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-contains-pile-of-poo-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-contains-pile-of-poo-isvalid.html
new file mode 100644
index 00000000000..7fcc6f644dc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-contains-pile-of-poo-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http💩//:foo">
+<meta charset=utf-8>
+<title>valid manifest: path-contains-pile-of-poo</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-contains-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-contains-space-novalid.html
new file mode 100644
index 00000000000..e44c2fbcb85
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-contains-space-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="/a/ /c">
+<meta charset=utf-8>
+<title>invalid manifest: path-contains-space</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-leading-backslash-at-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-leading-backslash-at-sign-novalid.html
new file mode 100644
index 00000000000..efc42dfb6b5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-leading-backslash-at-sign-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://foo.com/\@">
+<meta charset=utf-8>
+<title>invalid manifest: path-leading-backslash-at-sign</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-leading-colon-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-leading-colon-backslash-novalid.html
new file mode 100644
index 00000000000..7621629aa46
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-leading-colon-backslash-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest=":\">
+<meta charset=utf-8>
+<title>invalid manifest: path-leading-colon-backslash</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-leading-colon-chars-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-leading-colon-chars-backslash-novalid.html
new file mode 100644
index 00000000000..61407fb5373
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-leading-colon-chars-backslash-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest=":foo.com\">
+<meta charset=utf-8>
+<title>invalid manifest: path-leading-colon-chars-backslash</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-leading-colon-chars-relative-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-leading-colon-chars-relative-isvalid.html
new file mode 100644
index 00000000000..d211906ba90
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-leading-colon-chars-relative-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest=":foo.com">
+<meta charset=utf-8>
+<title>valid manifest: path-leading-colon-chars-relative</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-leading-colon-colon-relative-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-leading-colon-colon-relative-isvalid.html
new file mode 100644
index 00000000000..82d824f61e5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-leading-colon-colon-relative-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="::">
+<meta charset=utf-8>
+<title>valid manifest: path-leading-colon-colon-relative</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-leading-colon-hash-relative-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-leading-colon-hash-relative-isvalid.html
new file mode 100644
index 00000000000..8e4165d0346
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-leading-colon-hash-relative-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest=":#">
+<meta charset=utf-8>
+<title>valid manifest: path-leading-colon-hash-relative</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-leading-colon-letter-relative-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-leading-colon-letter-relative-isvalid.html
new file mode 100644
index 00000000000..d60081dc7fe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-leading-colon-letter-relative-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest=":a">
+<meta charset=utf-8>
+<title>valid manifest: path-leading-colon-letter-relative</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-leading-colon-number-relative-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-leading-colon-number-relative-isvalid.html
new file mode 100644
index 00000000000..d89a20bdadc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-leading-colon-number-relative-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest=":23">
+<meta charset=utf-8>
+<title>valid manifest: path-leading-colon-number-relative</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-leading-colon-slash-relative-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-leading-colon-slash-relative-isvalid.html
new file mode 100644
index 00000000000..246fd8028fa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-leading-colon-slash-relative-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest=":/">
+<meta charset=utf-8>
+<title>valid manifest: path-leading-colon-slash-relative</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-leading-space-novalid.html
new file mode 100644
index 00000000000..e723ed665f0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-leading-space-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://f:21/ b">
+<meta charset=utf-8>
+<title>invalid manifest: path-leading-space</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-non-ascii-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-non-ascii-isvalid.html
new file mode 100644
index 00000000000..37ef395ea05
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-non-ascii-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://example.com/©zbar">
+<meta charset=utf-8>
+<title>valid manifest: path-non-ascii</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-percent-encoded-dot-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-percent-encoded-dot-isvalid.html
new file mode 100644
index 00000000000..855f316cb95
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-percent-encoded-dot-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://example.com/foo/%2e">
+<meta charset=utf-8>
+<title>valid manifest: path-percent-encoded-dot</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-percent-encoded-malformed-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-percent-encoded-malformed-novalid.html
new file mode 100644
index 00000000000..f9bbb42f693
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-percent-encoded-malformed-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://example.com/foo/%2e%2">
+<meta charset=utf-8>
+<title>invalid manifest: path-percent-encoded-malformed</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-percent-encoded-mixed-case-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-percent-encoded-mixed-case-isvalid.html
new file mode 100644
index 00000000000..a8d9c9224b0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-percent-encoded-mixed-case-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://example.com/%3A%3a%3C%3c">
+<meta charset=utf-8>
+<title>valid manifest: path-percent-encoded-mixed-case</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-percent-encoded-multiple-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-percent-encoded-multiple-isvalid.html
new file mode 100644
index 00000000000..4e9cfb94ef9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-percent-encoded-multiple-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://example.com/foo%41%7a">
+<meta charset=utf-8>
+<title>valid manifest: path-percent-encoded-multiple</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-percent-encoded-slash-plus-slashes-relative-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-percent-encoded-slash-plus-slashes-relative-isvalid.html
new file mode 100644
index 00000000000..6e703da5c1f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-percent-encoded-slash-plus-slashes-relative-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="/a/%2f/c">
+<meta charset=utf-8>
+<title>valid manifest: path-percent-encoded-slash-plus-slashes-relative</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-percent-encoded-slash-relative-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-percent-encoded-slash-relative-isvalid.html
new file mode 100644
index 00000000000..113fa978adf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-percent-encoded-slash-relative-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="/a%2fc">
+<meta charset=utf-8>
+<title>valid manifest: path-percent-encoded-slash-relative</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-percent-encoded-space-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-percent-encoded-space-isvalid.html
new file mode 100644
index 00000000000..4bf72938b58
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-percent-encoded-space-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://example.com/%20foo">
+<meta charset=utf-8>
+<title>valid manifest: path-percent-encoded-space</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-percent-encoded-u0000-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-percent-encoded-u0000-isvalid.html
new file mode 100644
index 00000000000..48173a3340a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-percent-encoded-u0000-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://example.com/foo%00">
+<meta charset=utf-8>
+<title>valid manifest: path-percent-encoded-u0000</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-percent-encoded-u0091-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-percent-encoded-u0091-isvalid.html
new file mode 100644
index 00000000000..5956032c258
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-percent-encoded-u0091-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://example.com/foo%91">
+<meta charset=utf-8>
+<title>valid manifest: path-percent-encoded-u0091</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-relative-square-brackets-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-relative-square-brackets-novalid.html
new file mode 100644
index 00000000000..77b5bbc7822
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-relative-square-brackets-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="[61:24:74]:98">
+<meta charset=utf-8>
+<title>invalid manifest: path-relative-square-brackets</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-simple-relative-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-simple-relative-isvalid.html
new file mode 100644
index 00000000000..88927765855
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-simple-relative-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="/a/b/c">
+<meta charset=utf-8>
+<title>valid manifest: path-simple-relative</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-slash-colon-number-relative-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-slash-colon-number-relative-isvalid.html
new file mode 100644
index 00000000000..e26fd678e46
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-slash-colon-number-relative-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="/:23">
+<meta charset=utf-8>
+<title>valid manifest: path-slash-colon-number-relative</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-slash-only-relative-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-slash-only-relative-isvalid.html
new file mode 100644
index 00000000000..f4094bfde59
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-slash-only-relative-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="/">
+<meta charset=utf-8>
+<title>valid manifest: path-slash-only-relative</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-starts-with-pile-of-poo-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-starts-with-pile-of-poo-isvalid.html
new file mode 100644
index 00000000000..8c54ac33d68
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-starts-with-pile-of-poo-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="💩http://foo">
+<meta charset=utf-8>
+<title>valid manifest: path-starts-with-pile-of-poo</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-tab-novalid.html
new file mode 100644
index 00000000000..b895139445f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-tab-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://example.com/foo bar">
+<meta charset=utf-8>
+<title>invalid manifest: path-tab</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-trailing-space-novalid.html
new file mode 100644
index 00000000000..419ef427d3b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-trailing-space-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://f:21/b ?">
+<meta charset=utf-8>
+<title>invalid manifest: path-trailing-space</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-u0091-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-u0091-novalid.html
new file mode 100644
index 00000000000..66e754ea0d5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-u0091-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://example.com/foo‘">
+<meta charset=utf-8>
+<title>invalid manifest: path-u0091</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-u202E-u202D-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-u202E-u202D-isvalid.html
new file mode 100644
index 00000000000..a2073bb1009
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-u202E-u202D-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://example.com/‮/foo/‭/bar">
+<meta charset=utf-8>
+<title>valid manifest: path-u202E-u202D</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-uFEFF-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-uFEFF-isvalid.html
new file mode 100644
index 00000000000..02d902a2845
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-uFEFF-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://example.com//foo">
+<meta charset=utf-8>
+<title>valid manifest: path-uFEFF</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-unicode-han-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-unicode-han-isvalid.html
new file mode 100644
index 00000000000..d7f33f0698b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/path-unicode-han-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://example.com/你好你好">
+<meta charset=utf-8>
+<title>valid manifest: path-unicode-han</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/port-0-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/port-0-isvalid.html
new file mode 100644
index 00000000000..bd79085dd7b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/port-0-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://f:0/c">
+<meta charset=utf-8>
+<title>valid manifest: port-0</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/port-00000000000000-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/port-00000000000000-isvalid.html
new file mode 100644
index 00000000000..ed6136e5d23
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/port-00000000000000-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://f:00000000000000/c">
+<meta charset=utf-8>
+<title>valid manifest: port-00000000000000</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/port-00000000000000000000080-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/port-00000000000000000000080-isvalid.html
new file mode 100644
index 00000000000..4bebdf91e3f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/port-00000000000000000000080-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://f:00000000000000000000080/c">
+<meta charset=utf-8>
+<title>valid manifest: port-00000000000000000000080</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/port-999999-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/port-999999-isvalid.html
new file mode 100644
index 00000000000..bd27dd49f1b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/port-999999-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://f:999999/c">
+<meta charset=utf-8>
+<title>valid manifest: port-999999</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/port-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/port-cr-novalid.html
new file mode 100644
index 00000000000..9e21524abde
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/port-cr-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://f: /c">
+<meta charset=utf-8>
+<title>invalid manifest: port-cr</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/port-leading-colon-bracket-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/port-leading-colon-bracket-colon-novalid.html
new file mode 100644
index 00000000000..50987282911
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/port-leading-colon-bracket-colon-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://2001::1]:80">
+<meta charset=utf-8>
+<title>invalid manifest: port-leading-colon-bracket-colon</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/port-leading-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/port-leading-colon-novalid.html
new file mode 100644
index 00000000000..605becab821
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/port-leading-colon-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://2001::1">
+<meta charset=utf-8>
+<title>invalid manifest: port-leading-colon</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/port-leading-dash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/port-leading-dash-novalid.html
new file mode 100644
index 00000000000..01e665bfd67
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/port-leading-dash-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://foo:-80/">
+<meta charset=utf-8>
+<title>invalid manifest: port-leading-dash</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/port-multiple-letters-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/port-multiple-letters-novalid.html
new file mode 100644
index 00000000000..b01820a613b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/port-multiple-letters-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://f:fifty-two/c">
+<meta charset=utf-8>
+<title>invalid manifest: port-multiple-letters</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/port-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/port-newline-novalid.html
new file mode 100644
index 00000000000..4afb34049a8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/port-newline-novalid.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<html manifest="http://f:
+/c">
+<meta charset=utf-8>
+<title>invalid manifest: port-newline</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/port-none-but-colon-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/port-none-but-colon-isvalid.html
new file mode 100644
index 00000000000..1138973c4dd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/port-none-but-colon-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://f:/c">
+<meta charset=utf-8>
+<title>valid manifest: port-none-but-colon</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/port-single-letter-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/port-single-letter-novalid.html
new file mode 100644
index 00000000000..69c5a649fe1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/port-single-letter-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://f:b/c">
+<meta charset=utf-8>
+<title>invalid manifest: port-single-letter</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/port-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/port-space-novalid.html
new file mode 100644
index 00000000000..6c64dd7d81a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/port-space-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://f: /c">
+<meta charset=utf-8>
+<title>invalid manifest: port-space</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/port-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/port-tab-novalid.html
new file mode 100644
index 00000000000..0c3c9691c8d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/port-tab-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://f: /c">
+<meta charset=utf-8>
+<title>invalid manifest: port-tab</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/query-contains-pile-of-poo-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/query-contains-pile-of-poo-isvalid.html
new file mode 100644
index 00000000000..d87dab24702
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/query-contains-pile-of-poo-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://example.com/foo?💩">
+<meta charset=utf-8>
+<title>valid manifest: query-contains-pile-of-poo</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/query-contains-question-mark-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/query-contains-question-mark-isvalid.html
new file mode 100644
index 00000000000..6bcfa74c11f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/query-contains-question-mark-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://foo/abcd?efgh?ijkl">
+<meta charset=utf-8>
+<title>valid manifest: query-contains-question-mark</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/query-empty-no-path-relative-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/query-empty-no-path-relative-isvalid.html
new file mode 100644
index 00000000000..ccf1cd817b8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/query-empty-no-path-relative-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="?">
+<meta charset=utf-8>
+<title>valid manifest: query-empty-no-path-relative</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/query-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/query-leading-space-novalid.html
new file mode 100644
index 00000000000..121125a2794
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/query-leading-space-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://f:21/b? d">
+<meta charset=utf-8>
+<title>invalid manifest: query-leading-space</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/query-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/query-trailing-space-novalid.html
new file mode 100644
index 00000000000..5580a23fbd5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/query-trailing-space-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://f:21/b?d #">
+<meta charset=utf-8>
+<title>invalid manifest: query-trailing-space</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-data-contains-fragment-haswarn.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-data-contains-fragment-haswarn.html
new file mode 100644
index 00000000000..270fe8bc35a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-data-contains-fragment-haswarn.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="data:text/html,test#test">
+<meta charset=utf-8>
+<title>manifest warning: scheme-data-contains-fragment</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-data-no-slash-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-data-no-slash-isvalid.html
new file mode 100644
index 00000000000..56853b148ae
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-data-no-slash-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="data:text/plain,foo">
+<meta charset=utf-8>
+<title>valid manifest: scheme-data-no-slash</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-data-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-data-single-slash-novalid.html
new file mode 100644
index 00000000000..ddd8293b10b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-data-single-slash-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="data:/example.com/">
+<meta charset=utf-8>
+<title>invalid manifest: scheme-data-single-slash</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-file-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-file-backslash-novalid.html
new file mode 100644
index 00000000000..3117d0284b8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-file-backslash-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="file:c:\foo\bar.html">
+<meta charset=utf-8>
+<title>invalid manifest: scheme-file-backslash</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-file-host-empty-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-file-host-empty-isvalid.html
new file mode 100644
index 00000000000..f51329c0674
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-file-host-empty-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="file:///foo/bar.txt">
+<meta charset=utf-8>
+<title>valid manifest: scheme-file-host-empty</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-file-host-included-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-file-host-included-isvalid.html
new file mode 100644
index 00000000000..f62e9596539
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-file-host-included-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="file://server/foo/bar">
+<meta charset=utf-8>
+<title>valid manifest: scheme-file-host-included</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-file-no-slash-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-file-no-slash-isvalid.html
new file mode 100644
index 00000000000..3706aaed2b1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-file-no-slash-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="file:test">
+<meta charset=utf-8>
+<title>valid manifest: scheme-file-no-slash</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-file-scheme-only-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-file-scheme-only-isvalid.html
new file mode 100644
index 00000000000..37ddc808038
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-file-scheme-only-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="file:">
+<meta charset=utf-8>
+<title>valid manifest: scheme-file-scheme-only</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-file-single-slash-c-bar-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-file-single-slash-c-bar-novalid.html
new file mode 100644
index 00000000000..90700a420e2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-file-single-slash-c-bar-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="file:/C|/foo/bar">
+<meta charset=utf-8>
+<title>invalid manifest: scheme-file-single-slash-c-bar</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-file-single-slash-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-file-single-slash-isvalid.html
new file mode 100644
index 00000000000..ccac15caf1d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-file-single-slash-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="file:/example.com/">
+<meta charset=utf-8>
+<title>valid manifest: scheme-file-single-slash</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-file-slash-only-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-file-slash-only-isvalid.html
new file mode 100644
index 00000000000..bd2b8514bbe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-file-slash-only-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="file:/">
+<meta charset=utf-8>
+<title>valid manifest: scheme-file-slash-only</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-file-slash-slash-abc-bar-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-file-slash-slash-abc-bar-isvalid.html
new file mode 100644
index 00000000000..2321c0c45db
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-file-slash-slash-abc-bar-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="file://abc|/foo/bar">
+<meta charset=utf-8>
+<title>valid manifest: scheme-file-slash-slash-abc-bar</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-file-slash-slash-c-bar-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-file-slash-slash-c-bar-isvalid.html
new file mode 100644
index 00000000000..0743f63b6ed
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-file-slash-slash-c-bar-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="file://C|/foo/bar">
+<meta charset=utf-8>
+<title>valid manifest: scheme-file-slash-slash-c-bar</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-file-slash-slash-only-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-file-slash-slash-only-isvalid.html
new file mode 100644
index 00000000000..32ac621a3b8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-file-slash-slash-only-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="file://">
+<meta charset=utf-8>
+<title>valid manifest: scheme-file-slash-slash-only</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-file-slash-slash-slash-only-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-file-slash-slash-slash-only-isvalid.html
new file mode 100644
index 00000000000..b4707389417
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-file-slash-slash-slash-only-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="file:///">
+<meta charset=utf-8>
+<title>valid manifest: scheme-file-slash-slash-slash-only</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-file-triple-slash-c-bar-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-file-triple-slash-c-bar-novalid.html
new file mode 100644
index 00000000000..a511e345edb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-file-triple-slash-c-bar-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="file:///C|/foo/bar">
+<meta charset=utf-8>
+<title>invalid manifest: scheme-file-triple-slash-c-bar</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-file-uppercase-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-file-uppercase-isvalid.html
new file mode 100644
index 00000000000..061784e82c7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-file-uppercase-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="File://foo/bar.html">
+<meta charset=utf-8>
+<title>valid manifest: scheme-file-uppercase</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-ftp-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-ftp-no-slash-novalid.html
new file mode 100644
index 00000000000..64d78da68c3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-ftp-no-slash-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="ftp:example.com/">
+<meta charset=utf-8>
+<title>invalid manifest: scheme-ftp-no-slash</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-ftp-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-ftp-single-slash-novalid.html
new file mode 100644
index 00000000000..40564d9ca99
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-ftp-single-slash-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="ftp:/example.com/">
+<meta charset=utf-8>
+<title>invalid manifest: scheme-ftp-single-slash</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-ftps-no-slash-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-ftps-no-slash-isvalid.html
new file mode 100644
index 00000000000..02ef1d62654
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-ftps-no-slash-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="ftps:example.com/">
+<meta charset=utf-8>
+<title>valid manifest: scheme-ftps-no-slash</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-ftps-single-slash-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-ftps-single-slash-isvalid.html
new file mode 100644
index 00000000000..45366356e5e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-ftps-single-slash-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="ftps:/example.com/">
+<meta charset=utf-8>
+<title>valid manifest: scheme-ftps-single-slash</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-gopher-no-slash-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-gopher-no-slash-isvalid.html
new file mode 100644
index 00000000000..38270e19e88
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-gopher-no-slash-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="gopher:example.com/">
+<meta charset=utf-8>
+<title>valid manifest: scheme-gopher-no-slash</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-gopher-single-slash-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-gopher-single-slash-isvalid.html
new file mode 100644
index 00000000000..dfcb01513f9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-gopher-single-slash-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="gopher:/example.com/">
+<meta charset=utf-8>
+<title>valid manifest: scheme-gopher-single-slash</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-http-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-http-backslash-novalid.html
new file mode 100644
index 00000000000..1096e1b4c8c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-http-backslash-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http:\\foo.com\">
+<meta charset=utf-8>
+<title>invalid manifest: scheme-http-backslash</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-http-no-slash-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-http-no-slash-colon-novalid.html
new file mode 100644
index 00000000000..de4733f4338
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-http-no-slash-colon-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http::@c:29">
+<meta charset=utf-8>
+<title>invalid manifest: scheme-http-no-slash-colon</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-http-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-http-no-slash-novalid.html
new file mode 100644
index 00000000000..b080bfc8073
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-http-no-slash-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http:foo.com">
+<meta charset=utf-8>
+<title>invalid manifest: scheme-http-no-slash</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-http-no-slash-square-bracket-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-http-no-slash-square-bracket-novalid.html
new file mode 100644
index 00000000000..bbf05a5e18e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-http-no-slash-square-bracket-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http:[61:27]/:foo">
+<meta charset=utf-8>
+<title>invalid manifest: scheme-http-no-slash-square-bracket</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-http-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-http-single-slash-novalid.html
new file mode 100644
index 00000000000..5268c6061a0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-http-single-slash-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http:/example.com/">
+<meta charset=utf-8>
+<title>invalid manifest: scheme-http-single-slash</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-https-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-https-no-slash-novalid.html
new file mode 100644
index 00000000000..591686d950f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-https-no-slash-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="https:example.com/">
+<meta charset=utf-8>
+<title>invalid manifest: scheme-https-no-slash</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-https-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-https-single-slash-novalid.html
new file mode 100644
index 00000000000..edb658d6e12
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-https-single-slash-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="https:/example.com/">
+<meta charset=utf-8>
+<title>invalid manifest: scheme-https-single-slash</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-javascript-no-slash-malformed-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-javascript-no-slash-malformed-novalid.html
new file mode 100644
index 00000000000..f1a91bbe3c1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-javascript-no-slash-malformed-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="javascript:example.com/">
+<meta charset=utf-8>
+<title>invalid manifest: scheme-javascript-no-slash-malformed</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-javascript-single-slash-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-javascript-single-slash-isvalid.html
new file mode 100644
index 00000000000..306b7ac94d7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-javascript-single-slash-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="javascript:/example.com/">
+<meta charset=utf-8>
+<title>valid manifest: scheme-javascript-single-slash</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-mailto-no-slash-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-mailto-no-slash-isvalid.html
new file mode 100644
index 00000000000..b55c8a8a36b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-mailto-no-slash-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="mailto:example.com/">
+<meta charset=utf-8>
+<title>valid manifest: scheme-mailto-no-slash</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-mailto-single-slash-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-mailto-single-slash-isvalid.html
new file mode 100644
index 00000000000..d29dc5e9a92
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-mailto-single-slash-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="mailto:/example.com/">
+<meta charset=utf-8>
+<title>valid manifest: scheme-mailto-single-slash</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-none-relative-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-none-relative-isvalid.html
new file mode 100644
index 00000000000..d1a0642c8d4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-none-relative-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="foo.com">
+<meta charset=utf-8>
+<title>valid manifest: scheme-none-relative</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-private-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-private-isvalid.html
new file mode 100644
index 00000000000..e0ba7493279
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-private-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="a:foo.com">
+<meta charset=utf-8>
+<title>valid manifest: scheme-private</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-private-no-slash-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-private-no-slash-isvalid.html
new file mode 100644
index 00000000000..676da6f3ba0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-private-no-slash-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="madeupscheme:example.com/">
+<meta charset=utf-8>
+<title>valid manifest: scheme-private-no-slash</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-private-path-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-private-path-isvalid.html
new file mode 100644
index 00000000000..c839f760ab4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-private-path-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="foo:/bar.com/">
+<meta charset=utf-8>
+<title>valid manifest: scheme-private-path</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-private-path-leading-slashes-chars-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-private-path-leading-slashes-chars-isvalid.html
new file mode 100644
index 00000000000..9881ee4168a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-private-path-leading-slashes-chars-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="foo://///////bar.com/">
+<meta charset=utf-8>
+<title>valid manifest: scheme-private-path-leading-slashes-chars</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-private-path-leading-slashes-colon-slashes-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-private-path-leading-slashes-colon-slashes-isvalid.html
new file mode 100644
index 00000000000..08aeb85c8f7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-private-path-leading-slashes-colon-slashes-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="foo:////://///">
+<meta charset=utf-8>
+<title>valid manifest: scheme-private-path-leading-slashes-colon-slashes</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-private-path-leading-slashes-only-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-private-path-leading-slashes-only-isvalid.html
new file mode 100644
index 00000000000..90aee1d494d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-private-path-leading-slashes-only-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="foo://///////">
+<meta charset=utf-8>
+<title>valid manifest: scheme-private-path-leading-slashes-only</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-private-single-letter-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-private-single-letter-isvalid.html
new file mode 100644
index 00000000000..88e344a114c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-private-single-letter-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="c:/foo">
+<meta charset=utf-8>
+<title>valid manifest: scheme-private-single-letter</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-private-single-slash-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-private-single-slash-isvalid.html
new file mode 100644
index 00000000000..385ccceac94
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-private-single-slash-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="madeupscheme:/example.com/">
+<meta charset=utf-8>
+<title>valid manifest: scheme-private-single-slash</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-private-slash-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-private-slash-isvalid.html
new file mode 100644
index 00000000000..4f1b38b394c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-private-slash-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="foo:/">
+<meta charset=utf-8>
+<title>valid manifest: scheme-private-slash</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-private-slash-slash-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-private-slash-slash-isvalid.html
new file mode 100644
index 00000000000..d7444534694
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-private-slash-slash-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="foo://">
+<meta charset=utf-8>
+<title>valid manifest: scheme-private-slash-slash</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-schemeless-relative-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-schemeless-relative-isvalid.html
new file mode 100644
index 00000000000..e2eb5fcc691
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-schemeless-relative-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="//foo/bar">
+<meta charset=utf-8>
+<title>valid manifest: scheme-schemeless-relative</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-trailing-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-trailing-cr-novalid.html
new file mode 100644
index 00000000000..dd9f4173a79
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-trailing-cr-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="a: foo.com">
+<meta charset=utf-8>
+<title>invalid manifest: scheme-trailing-cr</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-trailing-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-trailing-newline-novalid.html
new file mode 100644
index 00000000000..a7ec3ec3a55
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-trailing-newline-novalid.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<html manifest="a:
+foo.com">
+<meta charset=utf-8>
+<title>invalid manifest: scheme-trailing-newline</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-trailing-space-novalid.html
new file mode 100644
index 00000000000..5118f88b51e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-trailing-space-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="a: foo.com">
+<meta charset=utf-8>
+<title>invalid manifest: scheme-trailing-space</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-trailing-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-trailing-tab-novalid.html
new file mode 100644
index 00000000000..200a48c6deb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-trailing-tab-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="a: foo.com">
+<meta charset=utf-8>
+<title>invalid manifest: scheme-trailing-tab</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-ws-single-slash-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-ws-single-slash-isvalid.html
new file mode 100644
index 00000000000..e8c33f70941
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-ws-single-slash-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="ws:/example.com/">
+<meta charset=utf-8>
+<title>valid manifest: scheme-ws-single-slash</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-wss-no-slash-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-wss-no-slash-isvalid.html
new file mode 100644
index 00000000000..4b60718498c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-wss-no-slash-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="wss:example.com/">
+<meta charset=utf-8>
+<title>valid manifest: scheme-wss-no-slash</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-wss-single-slash-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-wss-single-slash-isvalid.html
new file mode 100644
index 00000000000..a86f5617f8c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/scheme-wss-single-slash-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="wss:/example.com/">
+<meta charset=utf-8>
+<title>valid manifest: scheme-wss-single-slash</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/userinfo-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/userinfo-backslash-novalid.html
new file mode 100644
index 00000000000..d20219825bb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/userinfo-backslash-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://a\b:c\d@foo.com">
+<meta charset=utf-8>
+<title>invalid manifest: userinfo-backslash</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/userinfo-empty-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/userinfo-empty-isvalid.html
new file mode 100644
index 00000000000..82a49feca48
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/userinfo-empty-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://@www.example.com">
+<meta charset=utf-8>
+<title>valid manifest: userinfo-empty</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/userinfo-host-port-path-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/userinfo-host-port-path-isvalid.html
new file mode 100644
index 00000000000..7ec46ffeaff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/userinfo-host-port-path-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://a:b@c:29/d">
+<meta charset=utf-8>
+<title>valid manifest: userinfo-host-port-path</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/userinfo-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/userinfo-isvalid.html
new file mode 100644
index 00000000000..c7008c60e21
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/userinfo-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://user:pass@foo:21/bar;par?b#c">
+<meta charset=utf-8>
+<title>valid manifest: userinfo</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/userinfo-password-bad-chars-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/userinfo-password-bad-chars-novalid.html
new file mode 100644
index 00000000000..3b846b44fc6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/userinfo-password-bad-chars-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://&a:foo(b]c@d:2/">
+<meta charset=utf-8>
+<title>invalid manifest: userinfo-password-bad-chars</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/userinfo-password-contains-pile-of-poo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/userinfo-password-contains-pile-of-poo-novalid.html
new file mode 100644
index 00000000000..6f9774c053b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/userinfo-password-contains-pile-of-poo-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://foo:💩@example.com">
+<meta charset=utf-8>
+<title>invalid manifest: userinfo-password-contains-pile-of-poo</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/userinfo-password-empty-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/userinfo-password-empty-isvalid.html
new file mode 100644
index 00000000000..51add89dc6e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/userinfo-password-empty-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://a:@www.example.com">
+<meta charset=utf-8>
+<title>valid manifest: userinfo-password-empty</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/userinfo-user-empty-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/userinfo-user-empty-isvalid.html
new file mode 100644
index 00000000000..1da26e7edc7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/userinfo-user-empty-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://:b@www.example.com">
+<meta charset=utf-8>
+<title>valid manifest: userinfo-user-empty</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/userinfo-username-contains-at-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/userinfo-username-contains-at-sign-novalid.html
new file mode 100644
index 00000000000..2856f570442
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/userinfo-username-contains-at-sign-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://::@c@d:2">
+<meta charset=utf-8>
+<title>invalid manifest: userinfo-username-contains-at-sign</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/userinfo-username-contains-percent-encoded-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/userinfo-username-contains-percent-encoded-isvalid.html
new file mode 100644
index 00000000000..fa4a2223a52
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/userinfo-username-contains-percent-encoded-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://%25DOMAIN:foobar@foodomain.com">
+<meta charset=utf-8>
+<title>valid manifest: userinfo-username-contains-percent-encoded</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/userinfo-username-contains-pile-of-poo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/userinfo-username-contains-pile-of-poo-novalid.html
new file mode 100644
index 00000000000..ce1e91b321d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/userinfo-username-contains-pile-of-poo-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://💩:foo@example.com">
+<meta charset=utf-8>
+<title>invalid manifest: userinfo-username-contains-pile-of-poo</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/userinfo-username-non-alpha-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/userinfo-username-non-alpha-isvalid.html
new file mode 100644
index 00000000000..e5339b98d21
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/html/manifest/userinfo-username-non-alpha-isvalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html manifest="http://foo.com:b@d/">
+<meta charset=utf-8>
+<title>valid manifest: userinfo-username-non-alpha</title>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/i/model-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/i/model-isvalid.html
new file mode 100644
index 00000000000..4d0fe7a37c0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/i/model-isvalid.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;i&gt;</title>
+</head>
+<body>
+ <!-- is structured inline -->
+ <p><i class="class" lang="en">text</i></p>
+
+ <!-- is strictly inline -->
+ <p><dfn><i class="class" lang="en">text</i></dfn></p>
+
+ <!-- can be empty -->
+ <p>text <i></i></p>
+ <p>text <dfn><i></i></dfn></p>
+
+ <!-- can contain interactive -->
+ <p><i><a>text</a></i></p>
+ <p><dfn><i><a>text</a></i></dfn></p>
+
+ <!-- cannot contain structured inline -->
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/i/model-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/i/model-novalid.html
new file mode 100644
index 00000000000..892bb395e23
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/i/model-novalid.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;i&gt;</title>
+</head>
+<body>
+ <!-- not a block -->
+ <i>text</i>
+
+ <!-- cannot contain structured inline -->
+ <p><i><ul><li>text</li></ul></i></p>
+
+ <!-- cannot contain interactive if parent forbids interactive -->
+ <p><a><i><a>text</a></i></a></p>
+ <p><a><dfn><i><a>text</a></i></dfn></a></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/model-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/model-isvalid.html
new file mode 100644
index 00000000000..45e29ed72ef
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/model-isvalid.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;iframe&gt;</title>
+</head>
+<body>
+ <!-- is structured inline -->
+ <p><iframe
+ src="uri"
+ class="class"
+ lang="en"></iframe></p>
+
+ <!-- is strictly inline -->
+ <p><dfn><iframe
+ src="uri"
+ class="class"
+ lang="en"></iframe></dfn></p>
+
+ <p><dfn>strictly inline
+ <iframe>
+ text
+ </iframe>
+ </dfn></p>
+ <p>paragraph
+ <iframe>
+ text
+ </iframe>
+ </p>
+ <p><dfn>strictly inline
+ <iframe>
+ text
+ </iframe>
+ </dfn></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/model-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/model-novalid.html
new file mode 100644
index 00000000000..c2db35294bb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/model-novalid.html
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;iframe&gt;</title>
+</head>
+<body>
+ <!-- is structured inline -->
+ <p><iframe
+ name="frame1"
+ src="uri"
+ width="2"
+ height="90"
+ frameborder="0"
+ scrolling="yes"
+ class="class"
+ lang="en"></iframe></p>
+
+ <!-- is strictly inline -->
+ <p><dfn><iframe
+ name="frame1"
+ src="uri"
+ width="2"
+ height="90"
+ frameborder="1"
+ scrolling="no"
+ class="class"
+ lang="en"></iframe></dfn></p>
+
+ <!-- is block -->
+ <iframe
+ name="frame1"
+ src="uri"
+ width="2"
+ height="90"
+ frameborder="0"
+ scrolling="auto"
+ class="class"
+ lang="en"></iframe>
+
+ <!-- can contain inline while in inline context -->
+ <p>paragraph
+ <iframe>
+ <em>some</em> <ul><li>inline</li></ul> content
+ </iframe>
+ </p>
+ <!-- can contain strictly inline while in strictly inline context -->
+ <p><dfn>strictly inline
+ <iframe>
+ <em>text</em>
+ </iframe>
+ </dfn></p>
+
+ <!-- can contain blocks while in block context -->
+ <iframe>
+ <p>text</p>
+ </iframe>
+
+ <!-- can contain interactive if ancestor does not forbid it -->
+ <p>paragraph
+ <iframe>
+ <a>link</a>
+ </iframe>
+ </p>
+ <p><dfn>strictly inline
+ <iframe>
+ <a>link</a>
+ </iframe>
+ </dfn></p>
+ <iframe>
+ <p><a>link</a></p>
+ </iframe>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src-empty-novalid.html
new file mode 100644
index 00000000000..db0bd30947e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>empty src is not valid</title>
+<iframe src=""></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src-isvalid.html
new file mode 100644
index 00000000000..a0bbcbe4eb0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src-isvalid.html
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid src</title>
+<iframe src="file:///"></iframe><!-- scheme-file-slash-slash-slash-only -->
+<iframe src="http://a:@www.example.com"></iframe><!-- userinfo-password-empty -->
+<iframe src="foo://///////"></iframe><!-- scheme-private-path-leading-slashes-only -->
+<iframe src="file://abc|/foo/bar"></iframe><!-- scheme-file-slash-slash-abc-bar -->
+<iframe src="/a/b/c"></iframe><!-- path-simple-relative -->
+<iframe src="http://example.com/你好你好"></iframe><!-- path-unicode-han -->
+<iframe src="/a/%2f/c"></iframe><!-- path-percent-encoded-slash-plus-slashes-relative -->
+<iframe src="http://f:/c"></iframe><!-- port-none-but-colon -->
+<iframe src="http://example.com/foo%41%7a"></iframe><!-- path-percent-encoded-multiple -->
+<iframe src="http://192.168.0.257/"></iframe><!-- host-IP-address-broken -->
+<iframe src="madeupscheme:example.com/"></iframe><!-- scheme-private-no-slash -->
+<iframe src="?"></iframe><!-- query-empty-no-path-relative -->
+<iframe src="http://example.com/%20foo"></iframe><!-- path-percent-encoded-space -->
+<iframe src="mailto:/example.com/"></iframe><!-- scheme-mailto-single-slash -->
+<iframe src="::"></iframe><!-- path-leading-colon-colon-relative -->
+<iframe src="http://example.com/%3A%3a%3C%3c"></iframe><!-- path-percent-encoded-mixed-case -->
+<iframe src="http://user:pass@foo:21/bar;par?b#c"></iframe><!-- userinfo -->
+<iframe src="ws:/example.com/"></iframe><!-- scheme-ws-single-slash -->
+<iframe src="foo://"></iframe><!-- scheme-private-slash-slash -->
+<iframe src="#"></iframe><!-- fragment-empty-hash-only-no-path-relative -->
+<iframe src="http://f:00000000000000/c"></iframe><!-- port-00000000000000 -->
+<iframe src="foo:////://///"></iframe><!-- scheme-private-path-leading-slashes-colon-slashes -->
+<iframe src=":23"></iframe><!-- path-leading-colon-number-relative -->
+<iframe src="foo:/"></iframe><!-- scheme-private-slash -->
+<iframe src="http://💩"></iframe><!-- host-is-pile-of-poo -->
+<iframe src="file:test"></iframe><!-- scheme-file-no-slash -->
+<iframe src="file://C|/foo/bar"></iframe><!-- scheme-file-slash-slash-c-bar -->
+<iframe src="#/"></iframe><!-- fragment-slash-relative -->
+<iframe src="http://192.0x00A80001"></iframe><!-- host-192.0x00A80001 -->
+<iframe src="foo.com"></iframe><!-- scheme-none-relative -->
+<iframe src="http💩//:foo"></iframe><!-- path-contains-pile-of-poo -->
+<iframe src="File://foo/bar.html"></iframe><!-- scheme-file-uppercase -->
+<iframe src=":/"></iframe><!-- path-leading-colon-slash-relative -->
+<iframe src="http://www.foo。bar.com"></iframe><!-- host-exotic-dot -->
+<iframe src="http://GOO​⁠goo.com"></iframe><!-- host-exotic-whitespace -->
+<iframe src="file:///foo/bar.txt"></iframe><!-- scheme-file-host-empty -->
+<iframe src="javascript:/example.com/"></iframe><!-- scheme-javascript-single-slash -->
+<iframe src="gopher:/example.com/"></iframe><!-- scheme-gopher-single-slash -->
+<iframe src="ftps:example.com/"></iframe><!-- scheme-ftps-no-slash -->
+<iframe src="file://server/foo/bar"></iframe><!-- scheme-file-host-included -->
+<iframe src="http://example.com/foo%00"></iframe><!-- path-percent-encoded-u0000 -->
+<iframe src="a:foo.com"></iframe><!-- scheme-private -->
+<iframe src=":"></iframe><!-- path-colon-relative -->
+<iframe src="http://:b@www.example.com"></iframe><!-- userinfo-user-empty -->
+<iframe src="file:/"></iframe><!-- scheme-file-slash-only -->
+<iframe src="wss:example.com/"></iframe><!-- scheme-wss-no-slash -->
+<iframe src="::23"></iframe><!-- path-colon-colon-number-relative -->
+<iframe src="/a%2fc"></iframe><!-- path-percent-encoded-slash-relative -->
+<iframe src="http://a:b@c:29/d"></iframe><!-- userinfo-host-port-path -->
+<iframe src="gopher:example.com/"></iframe><!-- scheme-gopher-no-slash -->
+<iframe src="madeupscheme:/example.com/"></iframe><!-- scheme-private-single-slash -->
+<iframe src="mailto:example.com/"></iframe><!-- scheme-mailto-no-slash -->
+<iframe src="http://%25DOMAIN:foobar@foodomain.com"></iframe><!-- userinfo-username-contains-percent-encoded -->
+<iframe src="/:23"></iframe><!-- path-slash-colon-number-relative -->
+<iframe src="foo://///////bar.com/"></iframe><!-- scheme-private-path-leading-slashes-chars -->
+<iframe src="http://[2001::1]:80"></iframe><!-- host-ipv6-port -->
+<iframe src="data:text/plain,foo"></iframe><!-- scheme-data-no-slash -->
+<iframe src="http://example.com/foo/%2e"></iframe><!-- path-percent-encoded-dot -->
+<iframe src="file:/example.com/"></iframe><!-- scheme-file-single-slash -->
+<iframe src="http://example.com/©zbar"></iframe><!-- path-non-ascii -->
+<iframe src="http://example.com//foo"></iframe><!-- path-uFEFF -->
+<iframe src="wss:/example.com/"></iframe><!-- scheme-wss-single-slash -->
+<iframe src="http://foo/abcd#foo?bar"></iframe><!-- fragment-contains-question-mark -->
+<iframe src=":#"></iframe><!-- path-leading-colon-hash-relative -->
+<iframe src="http://example.com/foo%91"></iframe><!-- path-percent-encoded-u0091 -->
+<iframe src="c:/foo"></iframe><!-- scheme-private-single-letter -->
+<iframe src=":foo.com"></iframe><!-- path-leading-colon-chars-relative -->
+<iframe src="http://你好你好"></iframe><!-- host-idn-unicode-han -->
+<iframe src="http://example.com/foo#💩"></iframe><!-- fragment-contains-pile-of-poo -->
+<iframe src="file:"></iframe><!-- scheme-file-scheme-only -->
+<iframe src="#β"></iframe><!-- fragment-non-ascii-relative -->
+<iframe src="foo:/bar.com/"></iframe><!-- scheme-private-path -->
+<iframe src="http://f:0/c"></iframe><!-- port-0 -->
+<iframe src="#;?"></iframe><!-- fragment-semicolon-question-mark-relative -->
+<iframe src="http://Go.com"></iframe><!-- host-fullwidth -->
+<iframe src="http://@www.example.com"></iframe><!-- userinfo-empty -->
+<iframe src="http://example.com/‮/foo/‭/bar"></iframe><!-- path-u202E-u202D -->
+<iframe src="http://[2001::1]"></iframe><!-- host-ipv6 -->
+<iframe src="💩http://foo"></iframe><!-- path-starts-with-pile-of-poo -->
+<iframe src="http://foo/abcd?efgh?ijkl"></iframe><!-- query-contains-question-mark -->
+<iframe src="//foo/bar"></iframe><!-- scheme-schemeless-relative -->
+<iframe src="ftps:/example.com/"></iframe><!-- scheme-ftps-single-slash -->
+<iframe src="http://foo.com:b@d/"></iframe><!-- userinfo-username-non-alpha -->
+<iframe src=":a"></iframe><!-- path-leading-colon-letter-relative -->
+<iframe src="/"></iframe><!-- path-slash-only-relative -->
+<iframe src="http://example.com/foo?💩"></iframe><!-- query-contains-pile-of-poo -->
+<iframe src="http://f:00000000000000000000080/c"></iframe><!-- port-00000000000000000000080 -->
+<iframe src="file://"></iframe><!-- scheme-file-slash-slash-only -->
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src-whitespace-only-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src-whitespace-only-novalid.html
new file mode 100644
index 00000000000..12b307da287
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src-whitespace-only-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>empty src is not valid</title>
+<iframe src="
+"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/fragment-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/fragment-backslash-novalid.html
new file mode 100644
index 00000000000..f1e149373e6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/fragment-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: fragment-backslash</title>
+<iframe src="#\"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/fragment-contains-hash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/fragment-contains-hash-novalid.html
new file mode 100644
index 00000000000..d781f871aca
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/fragment-contains-hash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: fragment-contains-hash</title>
+<iframe src="http://foo/path#f#g"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/fragment-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/fragment-leading-space-novalid.html
new file mode 100644
index 00000000000..f567ab48cca
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/fragment-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: fragment-leading-space</title>
+<iframe src="http://f:21/b# e"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-cr-novalid.html
new file mode 100644
index 00000000000..dfa8d99b14e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-cr</title>
+<iframe src="http://example. org"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-double-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-double-percent-encoded-novalid.html
new file mode 100644
index 00000000000..322e4ec4188
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-double-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-double-percent-encoded</title>
+<iframe src="http://%41.com"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-double-percent-encoded-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-double-percent-encoded-percent-encoded-novalid.html
new file mode 100644
index 00000000000..1a505f0704f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-double-percent-encoded-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-double-percent-encoded-percent-encoded</title>
+<iframe src="http://%ef%bc%85%ef%bc%94%ef%bc%91.com"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-empty-novalid.html
new file mode 100644
index 00000000000..c7c67515118
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-empty</title>
+<iframe src="http://"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-empty-userinfo-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-empty-userinfo-empty-novalid.html
new file mode 100644
index 00000000000..f44f6ceb600
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-empty-userinfo-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-empty-userinfo-empty</title>
+<iframe src="http://@/www.example.com"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-empty-with-userinfo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-empty-with-userinfo-novalid.html
new file mode 100644
index 00000000000..dfb4c8af7c7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-empty-with-userinfo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-empty-with-userinfo</title>
+<iframe src="http://user:pass@/"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-hostname-in-brackets-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-hostname-in-brackets-novalid.html
new file mode 100644
index 00000000000..27c546addbd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-hostname-in-brackets-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-hostname-in-brackets</title>
+<iframe src="http://[www.google.com]/"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-invalid-unicode-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-invalid-unicode-novalid.html
new file mode 100644
index 00000000000..9cf93c27f95
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-invalid-unicode-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-invalid-unicode</title>
+<iframe src="http://﷐zyx.com"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-invalid-unicode-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-invalid-unicode-percent-encoded-novalid.html
new file mode 100644
index 00000000000..c5d371e4326
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-invalid-unicode-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-invalid-unicode-percent-encoded</title>
+<iframe src="http://%ef%b7%90zyx.com"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-newline-novalid.html
new file mode 100644
index 00000000000..f914a5c84d8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-newline</title>
+<iframe src="http://example.
+org"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-space-novalid.html
new file mode 100644
index 00000000000..00567d593d9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-space</title>
+<iframe src="http://example .org"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-square-brackets-port-contains-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-square-brackets-port-contains-colon-novalid.html
new file mode 100644
index 00000000000..ae72842756b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-square-brackets-port-contains-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-square-brackets-port-contains-colon</title>
+<iframe src="http://[1::2]:3:4"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-tab-novalid.html
new file mode 100644
index 00000000000..d36f1257898
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-tab</title>
+<iframe src="http://example .org"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-u0000-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-u0000-percent-encoded-novalid.html
new file mode 100644
index 00000000000..509184a6a9a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-u0000-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-u0000-percent-encoded</title>
+<iframe src="http://%00.com"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-u0000-percent-encoded-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-u0000-percent-encoded-percent-encoded-novalid.html
new file mode 100644
index 00000000000..7599cc11945
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/host-u0000-percent-encoded-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-u0000-percent-encoded-percent-encoded</title>
+<iframe src="http://%ef%bc%85%ef%bc%90%ef%bc%90.com"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/path-bare-percent-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/path-bare-percent-sign-novalid.html
new file mode 100644
index 00000000000..61fbdf004b6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/path-bare-percent-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-bare-percent-sign</title>
+<iframe src="http://example.com/foo%"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/path-contains-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/path-contains-space-novalid.html
new file mode 100644
index 00000000000..d11dfb92ae7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/path-contains-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-contains-space</title>
+<iframe src="/a/ /c"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/path-leading-backslash-at-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/path-leading-backslash-at-sign-novalid.html
new file mode 100644
index 00000000000..f3d0d22b6cb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/path-leading-backslash-at-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-leading-backslash-at-sign</title>
+<iframe src="http://foo.com/\@"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/path-leading-colon-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/path-leading-colon-backslash-novalid.html
new file mode 100644
index 00000000000..bf8a1ca17c7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/path-leading-colon-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-leading-colon-backslash</title>
+<iframe src=":\"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/path-leading-colon-chars-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/path-leading-colon-chars-backslash-novalid.html
new file mode 100644
index 00000000000..3db3992c06a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/path-leading-colon-chars-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-leading-colon-chars-backslash</title>
+<iframe src=":foo.com\"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/path-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/path-leading-space-novalid.html
new file mode 100644
index 00000000000..56f349685ba
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/path-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-leading-space</title>
+<iframe src="http://f:21/ b"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/path-percent-encoded-malformed-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/path-percent-encoded-malformed-novalid.html
new file mode 100644
index 00000000000..db315eddeca
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/path-percent-encoded-malformed-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-percent-encoded-malformed</title>
+<iframe src="http://example.com/foo/%2e%2"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/path-relative-square-brackets-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/path-relative-square-brackets-novalid.html
new file mode 100644
index 00000000000..9417972d6a6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/path-relative-square-brackets-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-relative-square-brackets</title>
+<iframe src="[61:24:74]:98"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/path-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/path-tab-novalid.html
new file mode 100644
index 00000000000..0b0a6d75544
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/path-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-tab</title>
+<iframe src="http://example.com/foo bar"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/path-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/path-trailing-space-novalid.html
new file mode 100644
index 00000000000..e79f6456f2c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/path-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-trailing-space</title>
+<iframe src="http://f:21/b ?"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/path-u0091-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/path-u0091-novalid.html
new file mode 100644
index 00000000000..e03e054f087
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/path-u0091-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-u0091</title>
+<iframe src="http://example.com/foo‘"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/port-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/port-cr-novalid.html
new file mode 100644
index 00000000000..b2df05bb6fa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/port-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-cr</title>
+<iframe src="http://f: /c"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/port-leading-colon-bracket-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/port-leading-colon-bracket-colon-novalid.html
new file mode 100644
index 00000000000..41280d20e8c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/port-leading-colon-bracket-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-leading-colon-bracket-colon</title>
+<iframe src="http://2001::1]:80"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/port-leading-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/port-leading-colon-novalid.html
new file mode 100644
index 00000000000..4a4a6a04563
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/port-leading-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-leading-colon</title>
+<iframe src="http://2001::1"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/port-leading-dash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/port-leading-dash-novalid.html
new file mode 100644
index 00000000000..052e77e051e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/port-leading-dash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-leading-dash</title>
+<iframe src="http://foo:-80/"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/port-multiple-letters-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/port-multiple-letters-novalid.html
new file mode 100644
index 00000000000..d2b6be6ae6e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/port-multiple-letters-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-multiple-letters</title>
+<iframe src="http://f:fifty-two/c"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/port-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/port-newline-novalid.html
new file mode 100644
index 00000000000..adff8ec67c5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/port-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-newline</title>
+<iframe src="http://f:
+/c"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/port-single-letter-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/port-single-letter-novalid.html
new file mode 100644
index 00000000000..fb149be62ea
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/port-single-letter-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-single-letter</title>
+<iframe src="http://f:b/c"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/port-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/port-space-novalid.html
new file mode 100644
index 00000000000..aafdfe523e9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/port-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-space</title>
+<iframe src="http://f: /c"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/port-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/port-tab-novalid.html
new file mode 100644
index 00000000000..de0ce71ae88
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/port-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-tab</title>
+<iframe src="http://f: /c"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/query-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/query-leading-space-novalid.html
new file mode 100644
index 00000000000..28014d70447
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/query-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: query-leading-space</title>
+<iframe src="http://f:21/b? d"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/query-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/query-trailing-space-novalid.html
new file mode 100644
index 00000000000..15f2db6f774
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/query-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: query-trailing-space</title>
+<iframe src="http://f:21/b?d #"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-data-contains-fragment-haswarn.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-data-contains-fragment-haswarn.html
new file mode 100644
index 00000000000..504824ca11b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-data-contains-fragment-haswarn.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>data:text/html,test#test warning: scheme-data-contains-fragment</title>
+<iframe src="data:text/html,test#test"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-data-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-data-single-slash-novalid.html
new file mode 100644
index 00000000000..ef6b1f9db8e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-data-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-data-single-slash</title>
+<iframe src="data:/example.com/"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-file-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-file-backslash-novalid.html
new file mode 100644
index 00000000000..debfa48520d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-file-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-file-backslash</title>
+<iframe src="file:c:\foo\bar.html"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-file-single-slash-c-bar-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-file-single-slash-c-bar-novalid.html
new file mode 100644
index 00000000000..194ff491c10
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-file-single-slash-c-bar-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-file-single-slash-c-bar</title>
+<iframe src="file:/C|/foo/bar"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-file-triple-slash-c-bar-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-file-triple-slash-c-bar-novalid.html
new file mode 100644
index 00000000000..1584da92a61
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-file-triple-slash-c-bar-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-file-triple-slash-c-bar</title>
+<iframe src="file:///C|/foo/bar"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-ftp-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-ftp-no-slash-novalid.html
new file mode 100644
index 00000000000..d8a2d18fb91
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-ftp-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-ftp-no-slash</title>
+<iframe src="ftp:example.com/"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-ftp-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-ftp-single-slash-novalid.html
new file mode 100644
index 00000000000..eccb4dd75f0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-ftp-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-ftp-single-slash</title>
+<iframe src="ftp:/example.com/"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-http-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-http-backslash-novalid.html
new file mode 100644
index 00000000000..8e9fe240521
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-http-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-http-backslash</title>
+<iframe src="http:\\foo.com\"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-http-no-slash-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-http-no-slash-colon-novalid.html
new file mode 100644
index 00000000000..0546f29cbcc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-http-no-slash-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-http-no-slash-colon</title>
+<iframe src="http::@c:29"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-http-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-http-no-slash-novalid.html
new file mode 100644
index 00000000000..d77d7e5d575
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-http-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-http-no-slash</title>
+<iframe src="http:foo.com"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-http-no-slash-square-bracket-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-http-no-slash-square-bracket-novalid.html
new file mode 100644
index 00000000000..f66c4397fa8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-http-no-slash-square-bracket-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-http-no-slash-square-bracket</title>
+<iframe src="http:[61:27]/:foo"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-http-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-http-single-slash-novalid.html
new file mode 100644
index 00000000000..12a75c3ca44
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-http-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-http-single-slash</title>
+<iframe src="http:/example.com/"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-https-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-https-no-slash-novalid.html
new file mode 100644
index 00000000000..18dc42fa34a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-https-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-https-no-slash</title>
+<iframe src="https:example.com/"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-https-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-https-single-slash-novalid.html
new file mode 100644
index 00000000000..142e7b0e1af
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-https-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-https-single-slash</title>
+<iframe src="https:/example.com/"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-javascript-no-slash-malformed-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-javascript-no-slash-malformed-novalid.html
new file mode 100644
index 00000000000..6424e83c0f0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-javascript-no-slash-malformed-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-javascript-no-slash-malformed</title>
+<iframe src="javascript:example.com/"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-trailing-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-trailing-cr-novalid.html
new file mode 100644
index 00000000000..dfc74a21265
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-trailing-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-trailing-cr</title>
+<iframe src="a: foo.com"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-trailing-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-trailing-newline-novalid.html
new file mode 100644
index 00000000000..7c7dca7708b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-trailing-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-trailing-newline</title>
+<iframe src="a:
+foo.com"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-trailing-space-novalid.html
new file mode 100644
index 00000000000..4d439a76deb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-trailing-space</title>
+<iframe src="a: foo.com"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-trailing-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-trailing-tab-novalid.html
new file mode 100644
index 00000000000..5542fe93d79
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/scheme-trailing-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-trailing-tab</title>
+<iframe src="a: foo.com"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/userinfo-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/userinfo-backslash-novalid.html
new file mode 100644
index 00000000000..099e4861e97
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/userinfo-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: userinfo-backslash</title>
+<iframe src="http://a\b:c\d@foo.com"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/userinfo-password-bad-chars-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/userinfo-password-bad-chars-novalid.html
new file mode 100644
index 00000000000..084b8f0b9fe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/userinfo-password-bad-chars-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: userinfo-password-bad-chars</title>
+<iframe src="http://&a:foo(b]c@d:2/"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/userinfo-password-contains-pile-of-poo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/userinfo-password-contains-pile-of-poo-novalid.html
new file mode 100644
index 00000000000..85aadb63391
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/userinfo-password-contains-pile-of-poo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: userinfo-password-contains-pile-of-poo</title>
+<iframe src="http://foo:💩@example.com"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/userinfo-username-contains-at-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/userinfo-username-contains-at-sign-novalid.html
new file mode 100644
index 00000000000..4ff2b75c53d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/userinfo-username-contains-at-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: userinfo-username-contains-at-sign</title>
+<iframe src="http://::@c@d:2"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/userinfo-username-contains-pile-of-poo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/userinfo-username-contains-pile-of-poo-novalid.html
new file mode 100644
index 00000000000..41fc10e2923
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/iframe/src/userinfo-username-contains-pile-of-poo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: userinfo-username-contains-pile-of-poo</title>
+<iframe src="http://💩:foo@example.com"></iframe>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/model-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/model-isvalid.html
new file mode 100644
index 00000000000..b0c7b33f02b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/model-isvalid.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;img&gt;</title>
+</head>
+<body>
+ <!-- is structured inline -->
+ <p><a href='foo'><img
+ src="url"
+ alt="text"
+ width="42"
+ height="095"
+ ismap="ismap"
+ class="class"
+ lang="en"></a></p>
+
+ <!-- is strictly inline -->
+ <p><a href='foo'><dfn><img
+ src="url"
+ alt="text"
+ width="42"
+ height="095"
+ ismap="ismap"
+ class="class"
+ lang="en"></dfn></a></p>
+
+ <!-- src and alt are required, others optional -->
+ <p><img src="ur" alt="text"></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/model-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/model-novalid.html
new file mode 100644
index 00000000000..d16a8064169
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/model-novalid.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;img&gt;</title>
+</head>
+<body>
+ <!-- is structured inline -->
+ <p><img
+ src="url"
+ alt="text"
+ width="42"
+ height="095"
+ usemap="url"
+ ismap="ismap"
+ class="class"
+ lang="en"></img></p>
+
+ <!-- is strictly inline -->
+ <p><dfn><img
+ src="url"
+ alt="text"
+ width="42"
+ height="095"
+ usemap="url"
+ ismap="ismap"
+ class="class"
+ lang="en"></img></dfn></p>
+
+ <!-- src and alt are required, others optional -->
+ <p><img src="ur" alt="text"></img></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src-empty-novalid.html
new file mode 100644
index 00000000000..d585907509d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>empty src is not valid</title>
+<img src="" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src-isvalid.html
new file mode 100644
index 00000000000..0837cfe1e36
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src-isvalid.html
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid src</title>
+<img src="file:///" alt><!-- scheme-file-slash-slash-slash-only -->
+<img src="http://a:@www.example.com" alt><!-- userinfo-password-empty -->
+<img src="foo://///////" alt><!-- scheme-private-path-leading-slashes-only -->
+<img src="file://abc|/foo/bar" alt><!-- scheme-file-slash-slash-abc-bar -->
+<img src="/a/b/c" alt><!-- path-simple-relative -->
+<img src="http://example.com/你好你好" alt><!-- path-unicode-han -->
+<img src="/a/%2f/c" alt><!-- path-percent-encoded-slash-plus-slashes-relative -->
+<img src="http://f:/c" alt><!-- port-none-but-colon -->
+<img src="http://example.com/foo%41%7a" alt><!-- path-percent-encoded-multiple -->
+<img src="http://192.168.0.257/" alt><!-- host-IP-address-broken -->
+<img src="madeupscheme:example.com/" alt><!-- scheme-private-no-slash -->
+<img src="?" alt><!-- query-empty-no-path-relative -->
+<img src="http://example.com/%20foo" alt><!-- path-percent-encoded-space -->
+<img src="mailto:/example.com/" alt><!-- scheme-mailto-single-slash -->
+<img src="::" alt><!-- path-leading-colon-colon-relative -->
+<img src="http://example.com/%3A%3a%3C%3c" alt><!-- path-percent-encoded-mixed-case -->
+<img src="http://user:pass@foo:21/bar;par?b#c" alt><!-- userinfo -->
+<img src="ws:/example.com/" alt><!-- scheme-ws-single-slash -->
+<img src="foo://" alt><!-- scheme-private-slash-slash -->
+<img src="#" alt><!-- fragment-empty-hash-only-no-path-relative -->
+<img src="http://f:00000000000000/c" alt><!-- port-00000000000000 -->
+<img src="foo:////://///" alt><!-- scheme-private-path-leading-slashes-colon-slashes -->
+<img src=":23" alt><!-- path-leading-colon-number-relative -->
+<img src="foo:/" alt><!-- scheme-private-slash -->
+<img src="http://💩" alt><!-- host-is-pile-of-poo -->
+<img src="file:test" alt><!-- scheme-file-no-slash -->
+<img src="file://C|/foo/bar" alt><!-- scheme-file-slash-slash-c-bar -->
+<img src="#/" alt><!-- fragment-slash-relative -->
+<img src="http://192.0x00A80001" alt><!-- host-192.0x00A80001 -->
+<img src="foo.com" alt><!-- scheme-none-relative -->
+<img src="http💩//:foo" alt><!-- path-contains-pile-of-poo -->
+<img src="File://foo/bar.html" alt><!-- scheme-file-uppercase -->
+<img src=":/" alt><!-- path-leading-colon-slash-relative -->
+<img src="http://www.foo。bar.com" alt><!-- host-exotic-dot -->
+<img src="http://GOO​⁠goo.com" alt><!-- host-exotic-whitespace -->
+<img src="file:///foo/bar.txt" alt><!-- scheme-file-host-empty -->
+<img src="javascript:/example.com/" alt><!-- scheme-javascript-single-slash -->
+<img src="gopher:/example.com/" alt><!-- scheme-gopher-single-slash -->
+<img src="ftps:example.com/" alt><!-- scheme-ftps-no-slash -->
+<img src="file://server/foo/bar" alt><!-- scheme-file-host-included -->
+<img src="http://example.com/foo%00" alt><!-- path-percent-encoded-u0000 -->
+<img src="a:foo.com" alt><!-- scheme-private -->
+<img src=":" alt><!-- path-colon-relative -->
+<img src="http://:b@www.example.com" alt><!-- userinfo-user-empty -->
+<img src="file:/" alt><!-- scheme-file-slash-only -->
+<img src="wss:example.com/" alt><!-- scheme-wss-no-slash -->
+<img src="::23" alt><!-- path-colon-colon-number-relative -->
+<img src="/a%2fc" alt><!-- path-percent-encoded-slash-relative -->
+<img src="http://a:b@c:29/d" alt><!-- userinfo-host-port-path -->
+<img src="gopher:example.com/" alt><!-- scheme-gopher-no-slash -->
+<img src="madeupscheme:/example.com/" alt><!-- scheme-private-single-slash -->
+<img src="mailto:example.com/" alt><!-- scheme-mailto-no-slash -->
+<img src="http://%25DOMAIN:foobar@foodomain.com" alt><!-- userinfo-username-contains-percent-encoded -->
+<img src="/:23" alt><!-- path-slash-colon-number-relative -->
+<img src="foo://///////bar.com/" alt><!-- scheme-private-path-leading-slashes-chars -->
+<img src="http://[2001::1]:80" alt><!-- host-ipv6-port -->
+<img src="data:text/plain,foo" alt><!-- scheme-data-no-slash -->
+<img src="http://example.com/foo/%2e" alt><!-- path-percent-encoded-dot -->
+<img src="file:/example.com/" alt><!-- scheme-file-single-slash -->
+<img src="http://example.com/©zbar" alt><!-- path-non-ascii -->
+<img src="http://example.com//foo" alt><!-- path-uFEFF -->
+<img src="wss:/example.com/" alt><!-- scheme-wss-single-slash -->
+<img src="http://foo/abcd#foo?bar" alt><!-- fragment-contains-question-mark -->
+<img src=":#" alt><!-- path-leading-colon-hash-relative -->
+<img src="http://example.com/foo%91" alt><!-- path-percent-encoded-u0091 -->
+<img src="c:/foo" alt><!-- scheme-private-single-letter -->
+<img src=":foo.com" alt><!-- path-leading-colon-chars-relative -->
+<img src="http://你好你好" alt><!-- host-idn-unicode-han -->
+<img src="http://example.com/foo#💩" alt><!-- fragment-contains-pile-of-poo -->
+<img src="file:" alt><!-- scheme-file-scheme-only -->
+<img src="#β" alt><!-- fragment-non-ascii-relative -->
+<img src="foo:/bar.com/" alt><!-- scheme-private-path -->
+<img src="http://f:0/c" alt><!-- port-0 -->
+<img src="#;?" alt><!-- fragment-semicolon-question-mark-relative -->
+<img src="http://Go.com" alt><!-- host-fullwidth -->
+<img src="http://@www.example.com" alt><!-- userinfo-empty -->
+<img src="http://example.com/‮/foo/‭/bar" alt><!-- path-u202E-u202D -->
+<img src="http://[2001::1]" alt><!-- host-ipv6 -->
+<img src="💩http://foo" alt><!-- path-starts-with-pile-of-poo -->
+<img src="http://foo/abcd?efgh?ijkl" alt><!-- query-contains-question-mark -->
+<img src="//foo/bar" alt><!-- scheme-schemeless-relative -->
+<img src="ftps:/example.com/" alt><!-- scheme-ftps-single-slash -->
+<img src="http://foo.com:b@d/" alt><!-- userinfo-username-non-alpha -->
+<img src=":a" alt><!-- path-leading-colon-letter-relative -->
+<img src="/" alt><!-- path-slash-only-relative -->
+<img src="http://example.com/foo?💩" alt><!-- query-contains-pile-of-poo -->
+<img src="http://f:00000000000000000000080/c" alt><!-- port-00000000000000000000080 -->
+<img src="file://" alt><!-- scheme-file-slash-slash-only -->
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src-whitespace-only-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src-whitespace-only-novalid.html
new file mode 100644
index 00000000000..cc0140808fd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src-whitespace-only-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>empty src is not valid</title>
+<img src="
+" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/fragment-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/fragment-backslash-novalid.html
new file mode 100644
index 00000000000..f54d6cbadd1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/fragment-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: fragment-backslash</title>
+<img src="#\" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/fragment-contains-hash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/fragment-contains-hash-novalid.html
new file mode 100644
index 00000000000..59829cfee46
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/fragment-contains-hash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: fragment-contains-hash</title>
+<img src="http://foo/path#f#g" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/fragment-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/fragment-leading-space-novalid.html
new file mode 100644
index 00000000000..c7420ec545a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/fragment-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: fragment-leading-space</title>
+<img src="http://f:21/b# e" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-cr-novalid.html
new file mode 100644
index 00000000000..2b14d6bda33
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-cr</title>
+<img src="http://example. org" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-double-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-double-percent-encoded-novalid.html
new file mode 100644
index 00000000000..d0fcc7336ca
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-double-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-double-percent-encoded</title>
+<img src="http://%41.com" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-double-percent-encoded-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-double-percent-encoded-percent-encoded-novalid.html
new file mode 100644
index 00000000000..6be9a8a4f7c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-double-percent-encoded-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-double-percent-encoded-percent-encoded</title>
+<img src="http://%ef%bc%85%ef%bc%94%ef%bc%91.com" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-empty-novalid.html
new file mode 100644
index 00000000000..41191edb5a4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-empty</title>
+<img src="http://" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-empty-userinfo-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-empty-userinfo-empty-novalid.html
new file mode 100644
index 00000000000..8f02f8e9c26
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-empty-userinfo-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-empty-userinfo-empty</title>
+<img src="http://@/www.example.com" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-empty-with-userinfo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-empty-with-userinfo-novalid.html
new file mode 100644
index 00000000000..b0b86cc3038
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-empty-with-userinfo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-empty-with-userinfo</title>
+<img src="http://user:pass@/" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-hostname-in-brackets-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-hostname-in-brackets-novalid.html
new file mode 100644
index 00000000000..f17042f721e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-hostname-in-brackets-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-hostname-in-brackets</title>
+<img src="http://[www.google.com]/" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-invalid-unicode-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-invalid-unicode-novalid.html
new file mode 100644
index 00000000000..37d687ab5f3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-invalid-unicode-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-invalid-unicode</title>
+<img src="http://﷐zyx.com" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-invalid-unicode-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-invalid-unicode-percent-encoded-novalid.html
new file mode 100644
index 00000000000..7d905ea3b9c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-invalid-unicode-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-invalid-unicode-percent-encoded</title>
+<img src="http://%ef%b7%90zyx.com" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-newline-novalid.html
new file mode 100644
index 00000000000..10bb356b352
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-newline</title>
+<img src="http://example.
+org" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-space-novalid.html
new file mode 100644
index 00000000000..633ea951b35
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-space</title>
+<img src="http://example .org" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-square-brackets-port-contains-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-square-brackets-port-contains-colon-novalid.html
new file mode 100644
index 00000000000..e37c9070fd6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-square-brackets-port-contains-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-square-brackets-port-contains-colon</title>
+<img src="http://[1::2]:3:4" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-tab-novalid.html
new file mode 100644
index 00000000000..c2b47937a8f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-tab</title>
+<img src="http://example .org" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-u0000-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-u0000-percent-encoded-novalid.html
new file mode 100644
index 00000000000..524834a9475
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-u0000-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-u0000-percent-encoded</title>
+<img src="http://%00.com" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-u0000-percent-encoded-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-u0000-percent-encoded-percent-encoded-novalid.html
new file mode 100644
index 00000000000..2b19cb86264
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/host-u0000-percent-encoded-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-u0000-percent-encoded-percent-encoded</title>
+<img src="http://%ef%bc%85%ef%bc%90%ef%bc%90.com" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/path-bare-percent-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/path-bare-percent-sign-novalid.html
new file mode 100644
index 00000000000..368e940411e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/path-bare-percent-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-bare-percent-sign</title>
+<img src="http://example.com/foo%" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/path-contains-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/path-contains-space-novalid.html
new file mode 100644
index 00000000000..7b1da54cb50
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/path-contains-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-contains-space</title>
+<img src="/a/ /c" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/path-leading-backslash-at-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/path-leading-backslash-at-sign-novalid.html
new file mode 100644
index 00000000000..ded9f27fc60
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/path-leading-backslash-at-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-leading-backslash-at-sign</title>
+<img src="http://foo.com/\@" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/path-leading-colon-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/path-leading-colon-backslash-novalid.html
new file mode 100644
index 00000000000..7bebfa8b677
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/path-leading-colon-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-leading-colon-backslash</title>
+<img src=":\" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/path-leading-colon-chars-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/path-leading-colon-chars-backslash-novalid.html
new file mode 100644
index 00000000000..f1fe58ebdbe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/path-leading-colon-chars-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-leading-colon-chars-backslash</title>
+<img src=":foo.com\" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/path-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/path-leading-space-novalid.html
new file mode 100644
index 00000000000..c1fc4d0b7cc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/path-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-leading-space</title>
+<img src="http://f:21/ b" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/path-percent-encoded-malformed-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/path-percent-encoded-malformed-novalid.html
new file mode 100644
index 00000000000..62bb73054de
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/path-percent-encoded-malformed-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-percent-encoded-malformed</title>
+<img src="http://example.com/foo/%2e%2" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/path-relative-square-brackets-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/path-relative-square-brackets-novalid.html
new file mode 100644
index 00000000000..da8bcd72571
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/path-relative-square-brackets-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-relative-square-brackets</title>
+<img src="[61:24:74]:98" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/path-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/path-tab-novalid.html
new file mode 100644
index 00000000000..42e555e6832
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/path-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-tab</title>
+<img src="http://example.com/foo bar" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/path-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/path-trailing-space-novalid.html
new file mode 100644
index 00000000000..98812cb9a65
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/path-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-trailing-space</title>
+<img src="http://f:21/b ?" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/path-u0091-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/path-u0091-novalid.html
new file mode 100644
index 00000000000..a15047c3ec8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/path-u0091-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-u0091</title>
+<img src="http://example.com/foo‘" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/port-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/port-cr-novalid.html
new file mode 100644
index 00000000000..49e6a1a0a76
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/port-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-cr</title>
+<img src="http://f: /c" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/port-leading-colon-bracket-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/port-leading-colon-bracket-colon-novalid.html
new file mode 100644
index 00000000000..6d7233039f1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/port-leading-colon-bracket-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-leading-colon-bracket-colon</title>
+<img src="http://2001::1]:80" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/port-leading-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/port-leading-colon-novalid.html
new file mode 100644
index 00000000000..75eba0ea32a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/port-leading-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-leading-colon</title>
+<img src="http://2001::1" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/port-leading-dash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/port-leading-dash-novalid.html
new file mode 100644
index 00000000000..9a66f5a411a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/port-leading-dash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-leading-dash</title>
+<img src="http://foo:-80/" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/port-multiple-letters-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/port-multiple-letters-novalid.html
new file mode 100644
index 00000000000..fcb6e959f69
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/port-multiple-letters-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-multiple-letters</title>
+<img src="http://f:fifty-two/c" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/port-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/port-newline-novalid.html
new file mode 100644
index 00000000000..3d59a2e4bcc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/port-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-newline</title>
+<img src="http://f:
+/c" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/port-single-letter-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/port-single-letter-novalid.html
new file mode 100644
index 00000000000..1ba9df25c27
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/port-single-letter-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-single-letter</title>
+<img src="http://f:b/c" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/port-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/port-space-novalid.html
new file mode 100644
index 00000000000..e59cda369a5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/port-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-space</title>
+<img src="http://f: /c" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/port-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/port-tab-novalid.html
new file mode 100644
index 00000000000..9ae34b348e4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/port-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-tab</title>
+<img src="http://f: /c" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/query-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/query-leading-space-novalid.html
new file mode 100644
index 00000000000..896fd99b3ca
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/query-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: query-leading-space</title>
+<img src="http://f:21/b? d" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/query-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/query-trailing-space-novalid.html
new file mode 100644
index 00000000000..ac079b454ff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/query-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: query-trailing-space</title>
+<img src="http://f:21/b?d #" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-data-contains-fragment-haswarn.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-data-contains-fragment-haswarn.html
new file mode 100644
index 00000000000..964cdce93f4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-data-contains-fragment-haswarn.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>src warning: scheme-data-contains-fragment</title>
+<img src="data:text/html,test#test" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-data-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-data-single-slash-novalid.html
new file mode 100644
index 00000000000..d5e0ae53eb8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-data-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-data-single-slash</title>
+<img src="data:/example.com/" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-file-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-file-backslash-novalid.html
new file mode 100644
index 00000000000..efb0fa5d77e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-file-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-file-backslash</title>
+<img src="file:c:\foo\bar.html" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-file-single-slash-c-bar-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-file-single-slash-c-bar-novalid.html
new file mode 100644
index 00000000000..61a7697e3d2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-file-single-slash-c-bar-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-file-single-slash-c-bar</title>
+<img src="file:/C|/foo/bar" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-file-triple-slash-c-bar-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-file-triple-slash-c-bar-novalid.html
new file mode 100644
index 00000000000..15120451d42
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-file-triple-slash-c-bar-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-file-triple-slash-c-bar</title>
+<img src="file:///C|/foo/bar" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-ftp-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-ftp-no-slash-novalid.html
new file mode 100644
index 00000000000..3c2e7439ac1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-ftp-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-ftp-no-slash</title>
+<img src="ftp:example.com/" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-ftp-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-ftp-single-slash-novalid.html
new file mode 100644
index 00000000000..f3218f03d17
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-ftp-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-ftp-single-slash</title>
+<img src="ftp:/example.com/" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-http-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-http-backslash-novalid.html
new file mode 100644
index 00000000000..fa2a92173a1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-http-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-http-backslash</title>
+<img src="http:\\foo.com\" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-http-no-slash-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-http-no-slash-colon-novalid.html
new file mode 100644
index 00000000000..16c9fa05a2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-http-no-slash-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-http-no-slash-colon</title>
+<img src="http::@c:29" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-http-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-http-no-slash-novalid.html
new file mode 100644
index 00000000000..0554f086c92
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-http-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-http-no-slash</title>
+<img src="http:foo.com" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-http-no-slash-square-bracket-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-http-no-slash-square-bracket-novalid.html
new file mode 100644
index 00000000000..518ba415f21
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-http-no-slash-square-bracket-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-http-no-slash-square-bracket</title>
+<img src="http:[61:27]/:foo" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-http-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-http-single-slash-novalid.html
new file mode 100644
index 00000000000..1c1ba05e0ef
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-http-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-http-single-slash</title>
+<img src="http:/example.com/" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-https-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-https-no-slash-novalid.html
new file mode 100644
index 00000000000..4057a3fa908
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-https-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-https-no-slash</title>
+<img src="https:example.com/" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-https-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-https-single-slash-novalid.html
new file mode 100644
index 00000000000..00d028cab04
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-https-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-https-single-slash</title>
+<img src="https:/example.com/" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-javascript-no-slash-malformed-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-javascript-no-slash-malformed-novalid.html
new file mode 100644
index 00000000000..00a8c885719
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-javascript-no-slash-malformed-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-javascript-no-slash-malformed</title>
+<img src="javascript:example.com/" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-trailing-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-trailing-cr-novalid.html
new file mode 100644
index 00000000000..c50d3ac1632
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-trailing-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-trailing-cr</title>
+<img src="a: foo.com" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-trailing-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-trailing-newline-novalid.html
new file mode 100644
index 00000000000..ee97e7af197
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-trailing-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-trailing-newline</title>
+<img src="a:
+foo.com" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-trailing-space-novalid.html
new file mode 100644
index 00000000000..f1f6b75723e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-trailing-space</title>
+<img src="a: foo.com" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-trailing-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-trailing-tab-novalid.html
new file mode 100644
index 00000000000..5649c226cb4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/scheme-trailing-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-trailing-tab</title>
+<img src="a: foo.com" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/userinfo-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/userinfo-backslash-novalid.html
new file mode 100644
index 00000000000..5d5a271ea65
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/userinfo-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: userinfo-backslash</title>
+<img src="http://a\b:c\d@foo.com" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/userinfo-password-bad-chars-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/userinfo-password-bad-chars-novalid.html
new file mode 100644
index 00000000000..6bd0affb488
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/userinfo-password-bad-chars-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: userinfo-password-bad-chars</title>
+<img src="http://&a:foo(b]c@d:2/" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/userinfo-password-contains-pile-of-poo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/userinfo-password-contains-pile-of-poo-novalid.html
new file mode 100644
index 00000000000..78873928f95
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/userinfo-password-contains-pile-of-poo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: userinfo-password-contains-pile-of-poo</title>
+<img src="http://foo:💩@example.com" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/userinfo-username-contains-at-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/userinfo-username-contains-at-sign-novalid.html
new file mode 100644
index 00000000000..2e2002a49a2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/userinfo-username-contains-at-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: userinfo-username-contains-at-sign</title>
+<img src="http://::@c@d:2" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/userinfo-username-contains-pile-of-poo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/userinfo-username-contains-pile-of-poo-novalid.html
new file mode 100644
index 00000000000..306ea7782ef
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/src/userinfo-username-contains-pile-of-poo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: userinfo-username-contains-pile-of-poo</title>
+<img src="http://💩:foo@example.com" alt>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/usemap-bad-value-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/usemap-bad-value-novalid.html
new file mode 100644
index 00000000000..708878a3075
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/usemap-bad-value-novalid.html
@@ -0,0 +1 @@
+<!doctype html><meta charset=utf-8><title>usemap="#"</title>There should be an error.<img src="foo" alt="" usemap="#">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/usemap-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/usemap-isvalid.html
new file mode 100644
index 00000000000..0e165c8c544
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/usemap-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;img&gt; with usemap attribute</title>
+</head>
+<body>
+ <map name="foo"></map>
+ <p><img src="url" usemap="#foo" alt="bar"></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/width-height-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/width-height-isvalid.html
new file mode 100644
index 00000000000..32b46d7cffa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/width-height-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>valid width and height</title>
+</head>
+<body>
+<img src="url" width="0" height="0" alt="bar"><!-- img with 0 value for width and height -->
+<img src="url" width="10" height="10" alt="bar"><!-- img with positive values for width and height -->
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/width-height-negative-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/width-height-negative-novalid.html
new file mode 100644
index 00000000000..d324106f11d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/img/width-height-negative-novalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>img with negative values for width and height</title>
+</head>
+<body>
+<img src="url" width="-1" height="-1">
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/list-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/list-novalid.html
new file mode 100644
index 00000000000..63f43af1f5a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/list-novalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>invalid input/@list reference to datalist/@id</title>
+<meta charset=utf-8>
+</head>
+<body>
+<datalist id=foo></datalist>
+<input type=text list=bar>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/pattern-asterisk-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/pattern-asterisk-novalid.html
new file mode 100644
index 00000000000..397344c0d41
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/pattern-asterisk-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid pattern</title>
+<p><input pattern='*'></p> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/pattern-paren-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/pattern-paren-novalid.html
new file mode 100644
index 00000000000..892cc02f1f9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/pattern-paren-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid pattern</title>
+<p><input pattern='('></p> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction-empty-novalid.html
new file mode 100644
index 00000000000..5deda965c57
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>empty formaction is not valid</title>
+<input type=image alt="foo" formaction="">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction-isvalid.html
new file mode 100644
index 00000000000..ea797c3b94d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction-isvalid.html
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid formaction</title>
+<input type=image alt="foo" formaction="file:///"><!-- scheme-file-slash-slash-slash-only -->
+<input type=image alt="foo" formaction="http://a:@www.example.com"><!-- userinfo-password-empty -->
+<input type=image alt="foo" formaction="foo://///////"><!-- scheme-private-path-leading-slashes-only -->
+<input type=image alt="foo" formaction="file://abc|/foo/bar"><!-- scheme-file-slash-slash-abc-bar -->
+<input type=image alt="foo" formaction="/a/b/c"><!-- path-simple-relative -->
+<input type=image alt="foo" formaction="http://example.com/你好你好"><!-- path-unicode-han -->
+<input type=image alt="foo" formaction="/a/%2f/c"><!-- path-percent-encoded-slash-plus-slashes-relative -->
+<input type=image alt="foo" formaction="http://f:/c"><!-- port-none-but-colon -->
+<input type=image alt="foo" formaction="http://example.com/foo%41%7a"><!-- path-percent-encoded-multiple -->
+<input type=image alt="foo" formaction="http://192.168.0.257/"><!-- host-IP-address-broken -->
+<input type=image alt="foo" formaction="madeupscheme:example.com/"><!-- scheme-private-no-slash -->
+<input type=image alt="foo" formaction="?"><!-- query-empty-no-path-relative -->
+<input type=image alt="foo" formaction="http://example.com/%20foo"><!-- path-percent-encoded-space -->
+<input type=image alt="foo" formaction="mailto:/example.com/"><!-- scheme-mailto-single-slash -->
+<input type=image alt="foo" formaction="::"><!-- path-leading-colon-colon-relative -->
+<input type=image alt="foo" formaction="http://example.com/%3A%3a%3C%3c"><!-- path-percent-encoded-mixed-case -->
+<input type=image alt="foo" formaction="http://user:pass@foo:21/bar;par?b#c"><!-- userinfo -->
+<input type=image alt="foo" formaction="ws:/example.com/"><!-- scheme-ws-single-slash -->
+<input type=image alt="foo" formaction="foo://"><!-- scheme-private-slash-slash -->
+<input type=image alt="foo" formaction="#"><!-- fragment-empty-hash-only-no-path-relative -->
+<input type=image alt="foo" formaction="http://f:00000000000000/c"><!-- port-00000000000000 -->
+<input type=image alt="foo" formaction="foo:////://///"><!-- scheme-private-path-leading-slashes-colon-slashes -->
+<input type=image alt="foo" formaction=":23"><!-- path-leading-colon-number-relative -->
+<input type=image alt="foo" formaction="foo:/"><!-- scheme-private-slash -->
+<input type=image alt="foo" formaction="http://💩"><!-- host-is-pile-of-poo -->
+<input type=image alt="foo" formaction="file:test"><!-- scheme-file-no-slash -->
+<input type=image alt="foo" formaction="file://C|/foo/bar"><!-- scheme-file-slash-slash-c-bar -->
+<input type=image alt="foo" formaction="#/"><!-- fragment-slash-relative -->
+<input type=image alt="foo" formaction="http://192.0x00A80001"><!-- host-192.0x00A80001 -->
+<input type=image alt="foo" formaction="foo.com"><!-- scheme-none-relative -->
+<input type=image alt="foo" formaction="http💩//:foo"><!-- path-contains-pile-of-poo -->
+<input type=image alt="foo" formaction="File://foo/bar.html"><!-- scheme-file-uppercase -->
+<input type=image alt="foo" formaction=":/"><!-- path-leading-colon-slash-relative -->
+<input type=image alt="foo" formaction="http://www.foo。bar.com"><!-- host-exotic-dot -->
+<input type=image alt="foo" formaction="http://GOO​⁠goo.com"><!-- host-exotic-whitespace -->
+<input type=image alt="foo" formaction="file:///foo/bar.txt"><!-- scheme-file-host-empty -->
+<input type=image alt="foo" formaction="javascript:/example.com/"><!-- scheme-javascript-single-slash -->
+<input type=image alt="foo" formaction="gopher:/example.com/"><!-- scheme-gopher-single-slash -->
+<input type=image alt="foo" formaction="ftps:example.com/"><!-- scheme-ftps-no-slash -->
+<input type=image alt="foo" formaction="file://server/foo/bar"><!-- scheme-file-host-included -->
+<input type=image alt="foo" formaction="http://example.com/foo%00"><!-- path-percent-encoded-u0000 -->
+<input type=image alt="foo" formaction="a:foo.com"><!-- scheme-private -->
+<input type=image alt="foo" formaction=":"><!-- path-colon-relative -->
+<input type=image alt="foo" formaction="http://:b@www.example.com"><!-- userinfo-user-empty -->
+<input type=image alt="foo" formaction="file:/"><!-- scheme-file-slash-only -->
+<input type=image alt="foo" formaction="wss:example.com/"><!-- scheme-wss-no-slash -->
+<input type=image alt="foo" formaction="::23"><!-- path-colon-colon-number-relative -->
+<input type=image alt="foo" formaction="/a%2fc"><!-- path-percent-encoded-slash-relative -->
+<input type=image alt="foo" formaction="http://a:b@c:29/d"><!-- userinfo-host-port-path -->
+<input type=image alt="foo" formaction="gopher:example.com/"><!-- scheme-gopher-no-slash -->
+<input type=image alt="foo" formaction="madeupscheme:/example.com/"><!-- scheme-private-single-slash -->
+<input type=image alt="foo" formaction="mailto:example.com/"><!-- scheme-mailto-no-slash -->
+<input type=image alt="foo" formaction="http://%25DOMAIN:foobar@foodomain.com"><!-- userinfo-username-contains-percent-encoded -->
+<input type=image alt="foo" formaction="/:23"><!-- path-slash-colon-number-relative -->
+<input type=image alt="foo" formaction="foo://///////bar.com/"><!-- scheme-private-path-leading-slashes-chars -->
+<input type=image alt="foo" formaction="http://[2001::1]:80"><!-- host-ipv6-port -->
+<input type=image alt="foo" formaction="data:text/plain,foo"><!-- scheme-data-no-slash -->
+<input type=image alt="foo" formaction="http://example.com/foo/%2e"><!-- path-percent-encoded-dot -->
+<input type=image alt="foo" formaction="file:/example.com/"><!-- scheme-file-single-slash -->
+<input type=image alt="foo" formaction="http://example.com/©zbar"><!-- path-non-ascii -->
+<input type=image alt="foo" formaction="http://example.com//foo"><!-- path-uFEFF -->
+<input type=image alt="foo" formaction="wss:/example.com/"><!-- scheme-wss-single-slash -->
+<input type=image alt="foo" formaction="http://foo/abcd#foo?bar"><!-- fragment-contains-question-mark -->
+<input type=image alt="foo" formaction=":#"><!-- path-leading-colon-hash-relative -->
+<input type=image alt="foo" formaction="http://example.com/foo%91"><!-- path-percent-encoded-u0091 -->
+<input type=image alt="foo" formaction="c:/foo"><!-- scheme-private-single-letter -->
+<input type=image alt="foo" formaction=":foo.com"><!-- path-leading-colon-chars-relative -->
+<input type=image alt="foo" formaction="http://你好你好"><!-- host-idn-unicode-han -->
+<input type=image alt="foo" formaction="http://example.com/foo#💩"><!-- fragment-contains-pile-of-poo -->
+<input type=image alt="foo" formaction="file:"><!-- scheme-file-scheme-only -->
+<input type=image alt="foo" formaction="#β"><!-- fragment-non-ascii-relative -->
+<input type=image alt="foo" formaction="foo:/bar.com/"><!-- scheme-private-path -->
+<input type=image alt="foo" formaction="http://f:0/c"><!-- port-0 -->
+<input type=image alt="foo" formaction="#;?"><!-- fragment-semicolon-question-mark-relative -->
+<input type=image alt="foo" formaction="http://Go.com"><!-- host-fullwidth -->
+<input type=image alt="foo" formaction="http://@www.example.com"><!-- userinfo-empty -->
+<input type=image alt="foo" formaction="http://example.com/‮/foo/‭/bar"><!-- path-u202E-u202D -->
+<input type=image alt="foo" formaction="http://[2001::1]"><!-- host-ipv6 -->
+<input type=image alt="foo" formaction="💩http://foo"><!-- path-starts-with-pile-of-poo -->
+<input type=image alt="foo" formaction="http://foo/abcd?efgh?ijkl"><!-- query-contains-question-mark -->
+<input type=image alt="foo" formaction="//foo/bar"><!-- scheme-schemeless-relative -->
+<input type=image alt="foo" formaction="ftps:/example.com/"><!-- scheme-ftps-single-slash -->
+<input type=image alt="foo" formaction="http://foo.com:b@d/"><!-- userinfo-username-non-alpha -->
+<input type=image alt="foo" formaction=":a"><!-- path-leading-colon-letter-relative -->
+<input type=image alt="foo" formaction="/"><!-- path-slash-only-relative -->
+<input type=image alt="foo" formaction="http://example.com/foo?💩"><!-- query-contains-pile-of-poo -->
+<input type=image alt="foo" formaction="http://f:00000000000000000000080/c"><!-- port-00000000000000000000080 -->
+<input type=image alt="foo" formaction="file://"><!-- scheme-file-slash-slash-only -->
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction-whitespace-only-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction-whitespace-only-novalid.html
new file mode 100644
index 00000000000..1c7fae12ba0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction-whitespace-only-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>empty formaction is not valid</title>
+<input type=image alt="foo" formaction="
+">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/fragment-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/fragment-backslash-novalid.html
new file mode 100644
index 00000000000..dee7e3b058d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/fragment-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: fragment-backslash</title>
+<input type=image alt="foo" formaction="#\">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/fragment-contains-hash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/fragment-contains-hash-novalid.html
new file mode 100644
index 00000000000..3bc4e4cddb7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/fragment-contains-hash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: fragment-contains-hash</title>
+<input type=image alt="foo" formaction="http://foo/path#f#g">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/fragment-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/fragment-leading-space-novalid.html
new file mode 100644
index 00000000000..07a0678eef0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/fragment-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: fragment-leading-space</title>
+<input type=image alt="foo" formaction="http://f:21/b# e">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-cr-novalid.html
new file mode 100644
index 00000000000..48919b1d8a9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: host-cr</title>
+<input type=image alt="foo" formaction="http://example. org">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-double-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-double-percent-encoded-novalid.html
new file mode 100644
index 00000000000..0919432afad
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-double-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: host-double-percent-encoded</title>
+<input type=image alt="foo" formaction="http://%41.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-double-percent-encoded-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-double-percent-encoded-percent-encoded-novalid.html
new file mode 100644
index 00000000000..007e045f66e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-double-percent-encoded-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: host-double-percent-encoded-percent-encoded</title>
+<input type=image alt="foo" formaction="http://%ef%bc%85%ef%bc%94%ef%bc%91.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-empty-novalid.html
new file mode 100644
index 00000000000..479146ab94d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: host-empty</title>
+<input type=image alt="foo" formaction="http://">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-empty-userinfo-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-empty-userinfo-empty-novalid.html
new file mode 100644
index 00000000000..62339541a0a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-empty-userinfo-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: host-empty-userinfo-empty</title>
+<input type=image alt="foo" formaction="http://@/www.example.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-empty-with-userinfo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-empty-with-userinfo-novalid.html
new file mode 100644
index 00000000000..30c5f8e8681
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-empty-with-userinfo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: host-empty-with-userinfo</title>
+<input type=image alt="foo" formaction="http://user:pass@/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-hostname-in-brackets-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-hostname-in-brackets-novalid.html
new file mode 100644
index 00000000000..dab28abffd4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-hostname-in-brackets-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: host-hostname-in-brackets</title>
+<input type=image alt="foo" formaction="http://[www.google.com]/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-invalid-unicode-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-invalid-unicode-novalid.html
new file mode 100644
index 00000000000..b389ecb58f7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-invalid-unicode-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: host-invalid-unicode</title>
+<input type=image alt="foo" formaction="http://﷐zyx.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-invalid-unicode-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-invalid-unicode-percent-encoded-novalid.html
new file mode 100644
index 00000000000..eab0190640a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-invalid-unicode-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: host-invalid-unicode-percent-encoded</title>
+<input type=image alt="foo" formaction="http://%ef%b7%90zyx.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-newline-novalid.html
new file mode 100644
index 00000000000..6af1be04994
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: host-newline</title>
+<input type=image alt="foo" formaction="http://example.
+org">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-space-novalid.html
new file mode 100644
index 00000000000..6b9e40850a6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: host-space</title>
+<input type=image alt="foo" formaction="http://example .org">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-square-brackets-port-contains-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-square-brackets-port-contains-colon-novalid.html
new file mode 100644
index 00000000000..fa76475e30c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-square-brackets-port-contains-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: host-square-brackets-port-contains-colon</title>
+<input type=image alt="foo" formaction="http://[1::2]:3:4">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-tab-novalid.html
new file mode 100644
index 00000000000..2a50d5275d3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: host-tab</title>
+<input type=image alt="foo" formaction="http://example .org">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-u0000-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-u0000-percent-encoded-novalid.html
new file mode 100644
index 00000000000..d6fb9579691
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-u0000-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: host-u0000-percent-encoded</title>
+<input type=image alt="foo" formaction="http://%00.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-u0000-percent-encoded-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-u0000-percent-encoded-percent-encoded-novalid.html
new file mode 100644
index 00000000000..a55751d8da9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/host-u0000-percent-encoded-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: host-u0000-percent-encoded-percent-encoded</title>
+<input type=image alt="foo" formaction="http://%ef%bc%85%ef%bc%90%ef%bc%90.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/path-bare-percent-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/path-bare-percent-sign-novalid.html
new file mode 100644
index 00000000000..1a8e6444c14
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/path-bare-percent-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: path-bare-percent-sign</title>
+<input type=image alt="foo" formaction="http://example.com/foo%">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/path-contains-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/path-contains-space-novalid.html
new file mode 100644
index 00000000000..a74a6604f81
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/path-contains-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: path-contains-space</title>
+<input type=image alt="foo" formaction="/a/ /c">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/path-leading-backslash-at-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/path-leading-backslash-at-sign-novalid.html
new file mode 100644
index 00000000000..db8534ac305
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/path-leading-backslash-at-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: path-leading-backslash-at-sign</title>
+<input type=image alt="foo" formaction="http://foo.com/\@">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/path-leading-colon-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/path-leading-colon-backslash-novalid.html
new file mode 100644
index 00000000000..ee2cb3157d2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/path-leading-colon-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: path-leading-colon-backslash</title>
+<input type=image alt="foo" formaction=":\">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/path-leading-colon-chars-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/path-leading-colon-chars-backslash-novalid.html
new file mode 100644
index 00000000000..843915930e1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/path-leading-colon-chars-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: path-leading-colon-chars-backslash</title>
+<input type=image alt="foo" formaction=":foo.com\">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/path-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/path-leading-space-novalid.html
new file mode 100644
index 00000000000..dc991b8db54
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/path-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: path-leading-space</title>
+<input type=image alt="foo" formaction="http://f:21/ b">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/path-percent-encoded-malformed-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/path-percent-encoded-malformed-novalid.html
new file mode 100644
index 00000000000..830ecfa13e3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/path-percent-encoded-malformed-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: path-percent-encoded-malformed</title>
+<input type=image alt="foo" formaction="http://example.com/foo/%2e%2">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/path-relative-square-brackets-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/path-relative-square-brackets-novalid.html
new file mode 100644
index 00000000000..222a0bd940d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/path-relative-square-brackets-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: path-relative-square-brackets</title>
+<input type=image alt="foo" formaction="[61:24:74]:98">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/path-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/path-tab-novalid.html
new file mode 100644
index 00000000000..b0440aabda1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/path-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: path-tab</title>
+<input type=image alt="foo" formaction="http://example.com/foo bar">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/path-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/path-trailing-space-novalid.html
new file mode 100644
index 00000000000..61a6a1a1b64
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/path-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: path-trailing-space</title>
+<input type=image alt="foo" formaction="http://f:21/b ?">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/path-u0091-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/path-u0091-novalid.html
new file mode 100644
index 00000000000..3edbb7aab5b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/path-u0091-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: path-u0091</title>
+<input type=image alt="foo" formaction="http://example.com/foo‘">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/port-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/port-cr-novalid.html
new file mode 100644
index 00000000000..ceca5a8355b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/port-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: port-cr</title>
+<input type=image alt="foo" formaction="http://f: /c">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/port-leading-colon-bracket-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/port-leading-colon-bracket-colon-novalid.html
new file mode 100644
index 00000000000..f8144521894
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/port-leading-colon-bracket-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: port-leading-colon-bracket-colon</title>
+<input type=image alt="foo" formaction="http://2001::1]:80">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/port-leading-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/port-leading-colon-novalid.html
new file mode 100644
index 00000000000..fd3d244c845
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/port-leading-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: port-leading-colon</title>
+<input type=image alt="foo" formaction="http://2001::1">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/port-leading-dash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/port-leading-dash-novalid.html
new file mode 100644
index 00000000000..a4136525675
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/port-leading-dash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: port-leading-dash</title>
+<input type=image alt="foo" formaction="http://foo:-80/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/port-multiple-letters-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/port-multiple-letters-novalid.html
new file mode 100644
index 00000000000..f899b643d51
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/port-multiple-letters-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: port-multiple-letters</title>
+<input type=image alt="foo" formaction="http://f:fifty-two/c">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/port-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/port-newline-novalid.html
new file mode 100644
index 00000000000..efa6fef4309
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/port-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: port-newline</title>
+<input type=image alt="foo" formaction="http://f:
+/c">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/port-single-letter-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/port-single-letter-novalid.html
new file mode 100644
index 00000000000..6b04af7a8f2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/port-single-letter-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: port-single-letter</title>
+<input type=image alt="foo" formaction="http://f:b/c">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/port-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/port-space-novalid.html
new file mode 100644
index 00000000000..666db3a7f57
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/port-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: port-space</title>
+<input type=image alt="foo" formaction="http://f: /c">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/port-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/port-tab-novalid.html
new file mode 100644
index 00000000000..dd671716021
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/port-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: port-tab</title>
+<input type=image alt="foo" formaction="http://f: /c">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/query-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/query-leading-space-novalid.html
new file mode 100644
index 00000000000..01d360dd50f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/query-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: query-leading-space</title>
+<input type=image alt="foo" formaction="http://f:21/b? d">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/query-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/query-trailing-space-novalid.html
new file mode 100644
index 00000000000..98322081e83
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/query-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: query-trailing-space</title>
+<input type=image alt="foo" formaction="http://f:21/b?d #">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-data-contains-fragment-haswarn.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-data-contains-fragment-haswarn.html
new file mode 100644
index 00000000000..aa3ea3aad1f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-data-contains-fragment-haswarn.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>formaction warning: scheme-data-contains-fragment</title>
+<input type=image alt="foo" formaction="data:text/html,test#test">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-data-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-data-single-slash-novalid.html
new file mode 100644
index 00000000000..48e5ec30bba
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-data-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: scheme-data-single-slash</title>
+<input type=image alt="foo" formaction="data:/example.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-file-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-file-backslash-novalid.html
new file mode 100644
index 00000000000..e77493c24d6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-file-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: scheme-file-backslash</title>
+<input type=image alt="foo" formaction="file:c:\foo\bar.html">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-file-single-slash-c-bar-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-file-single-slash-c-bar-novalid.html
new file mode 100644
index 00000000000..3a12a2f2c29
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-file-single-slash-c-bar-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: scheme-file-single-slash-c-bar</title>
+<input type=image alt="foo" formaction="file:/C|/foo/bar">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-file-triple-slash-c-bar-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-file-triple-slash-c-bar-novalid.html
new file mode 100644
index 00000000000..da3f423ea70
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-file-triple-slash-c-bar-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: scheme-file-triple-slash-c-bar</title>
+<input type=image alt="foo" formaction="file:///C|/foo/bar">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-ftp-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-ftp-no-slash-novalid.html
new file mode 100644
index 00000000000..620a37c83dd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-ftp-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: scheme-ftp-no-slash</title>
+<input type=image alt="foo" formaction="ftp:example.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-ftp-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-ftp-single-slash-novalid.html
new file mode 100644
index 00000000000..e5f064e2509
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-ftp-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: scheme-ftp-single-slash</title>
+<input type=image alt="foo" formaction="ftp:/example.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-http-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-http-backslash-novalid.html
new file mode 100644
index 00000000000..cad3f1e993c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-http-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: scheme-http-backslash</title>
+<input type=image alt="foo" formaction="http:\\foo.com\">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-http-no-slash-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-http-no-slash-colon-novalid.html
new file mode 100644
index 00000000000..fb1ecc696a8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-http-no-slash-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: scheme-http-no-slash-colon</title>
+<input type=image alt="foo" formaction="http::@c:29">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-http-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-http-no-slash-novalid.html
new file mode 100644
index 00000000000..62bdcd8c2c2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-http-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: scheme-http-no-slash</title>
+<input type=image alt="foo" formaction="http:foo.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-http-no-slash-square-bracket-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-http-no-slash-square-bracket-novalid.html
new file mode 100644
index 00000000000..90f76c9d1e5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-http-no-slash-square-bracket-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: scheme-http-no-slash-square-bracket</title>
+<input type=image alt="foo" formaction="http:[61:27]/:foo">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-http-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-http-single-slash-novalid.html
new file mode 100644
index 00000000000..9f1a492113d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-http-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: scheme-http-single-slash</title>
+<input type=image alt="foo" formaction="http:/example.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-https-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-https-no-slash-novalid.html
new file mode 100644
index 00000000000..2357c0a1e74
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-https-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: scheme-https-no-slash</title>
+<input type=image alt="foo" formaction="https:example.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-https-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-https-single-slash-novalid.html
new file mode 100644
index 00000000000..4e3075b4948
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-https-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: scheme-https-single-slash</title>
+<input type=image alt="foo" formaction="https:/example.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-javascript-no-slash-malformed-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-javascript-no-slash-malformed-novalid.html
new file mode 100644
index 00000000000..727da488fc7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-javascript-no-slash-malformed-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: scheme-javascript-no-slash-malformed</title>
+<input type=image alt="foo" formaction="javascript:example.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-trailing-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-trailing-cr-novalid.html
new file mode 100644
index 00000000000..45affd7ec44
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-trailing-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: scheme-trailing-cr</title>
+<input type=image alt="foo" formaction="a: foo.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-trailing-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-trailing-newline-novalid.html
new file mode 100644
index 00000000000..161cffbf6bb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-trailing-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: scheme-trailing-newline</title>
+<input type=image alt="foo" formaction="a:
+foo.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-trailing-space-novalid.html
new file mode 100644
index 00000000000..ebd08615a60
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: scheme-trailing-space</title>
+<input type=image alt="foo" formaction="a: foo.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-trailing-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-trailing-tab-novalid.html
new file mode 100644
index 00000000000..1429b7a273d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/scheme-trailing-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: scheme-trailing-tab</title>
+<input type=image alt="foo" formaction="a: foo.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/userinfo-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/userinfo-backslash-novalid.html
new file mode 100644
index 00000000000..a0df503e102
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/userinfo-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: userinfo-backslash</title>
+<input type=image alt="foo" formaction="http://a\b:c\d@foo.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/userinfo-password-bad-chars-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/userinfo-password-bad-chars-novalid.html
new file mode 100644
index 00000000000..1673f65ecf4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/userinfo-password-bad-chars-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: userinfo-password-bad-chars</title>
+<input type=image alt="foo" formaction="http://&a:foo(b]c@d:2/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/userinfo-password-contains-pile-of-poo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/userinfo-password-contains-pile-of-poo-novalid.html
new file mode 100644
index 00000000000..aae3d288a58
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/userinfo-password-contains-pile-of-poo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: userinfo-password-contains-pile-of-poo</title>
+<input type=image alt="foo" formaction="http://foo:💩@example.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/userinfo-username-contains-at-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/userinfo-username-contains-at-sign-novalid.html
new file mode 100644
index 00000000000..cc0652c8b35
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/userinfo-username-contains-at-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: userinfo-username-contains-at-sign</title>
+<input type=image alt="foo" formaction="http://::@c@d:2">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/userinfo-username-contains-pile-of-poo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/userinfo-username-contains-pile-of-poo-novalid.html
new file mode 100644
index 00000000000..abc75f3ed98
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-formaction/userinfo-username-contains-pile-of-poo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: userinfo-username-contains-pile-of-poo</title>
+<input type=image alt="foo" formaction="http://💩:foo@example.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src-empty-novalid.html
new file mode 100644
index 00000000000..f773a2aa450
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>empty src is not valid</title>
+<input type=image alt="foo" src="">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src-isvalid.html
new file mode 100644
index 00000000000..0d744c002ad
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src-isvalid.html
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid src</title>
+<input type=image alt="foo" src="file:///"><!-- scheme-file-slash-slash-slash-only -->
+<input type=image alt="foo" src="http://a:@www.example.com"><!-- userinfo-password-empty -->
+<input type=image alt="foo" src="foo://///////"><!-- scheme-private-path-leading-slashes-only -->
+<input type=image alt="foo" src="file://abc|/foo/bar"><!-- scheme-file-slash-slash-abc-bar -->
+<input type=image alt="foo" src="/a/b/c"><!-- path-simple-relative -->
+<input type=image alt="foo" src="http://example.com/你好你好"><!-- path-unicode-han -->
+<input type=image alt="foo" src="/a/%2f/c"><!-- path-percent-encoded-slash-plus-slashes-relative -->
+<input type=image alt="foo" src="http://f:/c"><!-- port-none-but-colon -->
+<input type=image alt="foo" src="http://example.com/foo%41%7a"><!-- path-percent-encoded-multiple -->
+<input type=image alt="foo" src="http://192.168.0.257/"><!-- host-IP-address-broken -->
+<input type=image alt="foo" src="madeupscheme:example.com/"><!-- scheme-private-no-slash -->
+<input type=image alt="foo" src="?"><!-- query-empty-no-path-relative -->
+<input type=image alt="foo" src="http://example.com/%20foo"><!-- path-percent-encoded-space -->
+<input type=image alt="foo" src="mailto:/example.com/"><!-- scheme-mailto-single-slash -->
+<input type=image alt="foo" src="::"><!-- path-leading-colon-colon-relative -->
+<input type=image alt="foo" src="http://example.com/%3A%3a%3C%3c"><!-- path-percent-encoded-mixed-case -->
+<input type=image alt="foo" src="http://user:pass@foo:21/bar;par?b#c"><!-- userinfo -->
+<input type=image alt="foo" src="ws:/example.com/"><!-- scheme-ws-single-slash -->
+<input type=image alt="foo" src="foo://"><!-- scheme-private-slash-slash -->
+<input type=image alt="foo" src="#"><!-- fragment-empty-hash-only-no-path-relative -->
+<input type=image alt="foo" src="http://f:00000000000000/c"><!-- port-00000000000000 -->
+<input type=image alt="foo" src="foo:////://///"><!-- scheme-private-path-leading-slashes-colon-slashes -->
+<input type=image alt="foo" src=":23"><!-- path-leading-colon-number-relative -->
+<input type=image alt="foo" src="foo:/"><!-- scheme-private-slash -->
+<input type=image alt="foo" src="http://💩"><!-- host-is-pile-of-poo -->
+<input type=image alt="foo" src="file:test"><!-- scheme-file-no-slash -->
+<input type=image alt="foo" src="file://C|/foo/bar"><!-- scheme-file-slash-slash-c-bar -->
+<input type=image alt="foo" src="#/"><!-- fragment-slash-relative -->
+<input type=image alt="foo" src="http://192.0x00A80001"><!-- host-192.0x00A80001 -->
+<input type=image alt="foo" src="foo.com"><!-- scheme-none-relative -->
+<input type=image alt="foo" src="http💩//:foo"><!-- path-contains-pile-of-poo -->
+<input type=image alt="foo" src="File://foo/bar.html"><!-- scheme-file-uppercase -->
+<input type=image alt="foo" src=":/"><!-- path-leading-colon-slash-relative -->
+<input type=image alt="foo" src="http://www.foo。bar.com"><!-- host-exotic-dot -->
+<input type=image alt="foo" src="http://GOO​⁠goo.com"><!-- host-exotic-whitespace -->
+<input type=image alt="foo" src="file:///foo/bar.txt"><!-- scheme-file-host-empty -->
+<input type=image alt="foo" src="javascript:/example.com/"><!-- scheme-javascript-single-slash -->
+<input type=image alt="foo" src="gopher:/example.com/"><!-- scheme-gopher-single-slash -->
+<input type=image alt="foo" src="ftps:example.com/"><!-- scheme-ftps-no-slash -->
+<input type=image alt="foo" src="file://server/foo/bar"><!-- scheme-file-host-included -->
+<input type=image alt="foo" src="http://example.com/foo%00"><!-- path-percent-encoded-u0000 -->
+<input type=image alt="foo" src="a:foo.com"><!-- scheme-private -->
+<input type=image alt="foo" src=":"><!-- path-colon-relative -->
+<input type=image alt="foo" src="http://:b@www.example.com"><!-- userinfo-user-empty -->
+<input type=image alt="foo" src="file:/"><!-- scheme-file-slash-only -->
+<input type=image alt="foo" src="wss:example.com/"><!-- scheme-wss-no-slash -->
+<input type=image alt="foo" src="::23"><!-- path-colon-colon-number-relative -->
+<input type=image alt="foo" src="/a%2fc"><!-- path-percent-encoded-slash-relative -->
+<input type=image alt="foo" src="http://a:b@c:29/d"><!-- userinfo-host-port-path -->
+<input type=image alt="foo" src="gopher:example.com/"><!-- scheme-gopher-no-slash -->
+<input type=image alt="foo" src="madeupscheme:/example.com/"><!-- scheme-private-single-slash -->
+<input type=image alt="foo" src="mailto:example.com/"><!-- scheme-mailto-no-slash -->
+<input type=image alt="foo" src="http://%25DOMAIN:foobar@foodomain.com"><!-- userinfo-username-contains-percent-encoded -->
+<input type=image alt="foo" src="/:23"><!-- path-slash-colon-number-relative -->
+<input type=image alt="foo" src="foo://///////bar.com/"><!-- scheme-private-path-leading-slashes-chars -->
+<input type=image alt="foo" src="http://[2001::1]:80"><!-- host-ipv6-port -->
+<input type=image alt="foo" src="data:text/plain,foo"><!-- scheme-data-no-slash -->
+<input type=image alt="foo" src="http://example.com/foo/%2e"><!-- path-percent-encoded-dot -->
+<input type=image alt="foo" src="file:/example.com/"><!-- scheme-file-single-slash -->
+<input type=image alt="foo" src="http://example.com/©zbar"><!-- path-non-ascii -->
+<input type=image alt="foo" src="http://example.com//foo"><!-- path-uFEFF -->
+<input type=image alt="foo" src="wss:/example.com/"><!-- scheme-wss-single-slash -->
+<input type=image alt="foo" src="http://foo/abcd#foo?bar"><!-- fragment-contains-question-mark -->
+<input type=image alt="foo" src=":#"><!-- path-leading-colon-hash-relative -->
+<input type=image alt="foo" src="http://example.com/foo%91"><!-- path-percent-encoded-u0091 -->
+<input type=image alt="foo" src="c:/foo"><!-- scheme-private-single-letter -->
+<input type=image alt="foo" src=":foo.com"><!-- path-leading-colon-chars-relative -->
+<input type=image alt="foo" src="http://你好你好"><!-- host-idn-unicode-han -->
+<input type=image alt="foo" src="http://example.com/foo#💩"><!-- fragment-contains-pile-of-poo -->
+<input type=image alt="foo" src="file:"><!-- scheme-file-scheme-only -->
+<input type=image alt="foo" src="#β"><!-- fragment-non-ascii-relative -->
+<input type=image alt="foo" src="foo:/bar.com/"><!-- scheme-private-path -->
+<input type=image alt="foo" src="http://f:0/c"><!-- port-0 -->
+<input type=image alt="foo" src="#;?"><!-- fragment-semicolon-question-mark-relative -->
+<input type=image alt="foo" src="http://Go.com"><!-- host-fullwidth -->
+<input type=image alt="foo" src="http://@www.example.com"><!-- userinfo-empty -->
+<input type=image alt="foo" src="http://example.com/‮/foo/‭/bar"><!-- path-u202E-u202D -->
+<input type=image alt="foo" src="http://[2001::1]"><!-- host-ipv6 -->
+<input type=image alt="foo" src="💩http://foo"><!-- path-starts-with-pile-of-poo -->
+<input type=image alt="foo" src="http://foo/abcd?efgh?ijkl"><!-- query-contains-question-mark -->
+<input type=image alt="foo" src="//foo/bar"><!-- scheme-schemeless-relative -->
+<input type=image alt="foo" src="ftps:/example.com/"><!-- scheme-ftps-single-slash -->
+<input type=image alt="foo" src="http://foo.com:b@d/"><!-- userinfo-username-non-alpha -->
+<input type=image alt="foo" src=":a"><!-- path-leading-colon-letter-relative -->
+<input type=image alt="foo" src="/"><!-- path-slash-only-relative -->
+<input type=image alt="foo" src="http://example.com/foo?💩"><!-- query-contains-pile-of-poo -->
+<input type=image alt="foo" src="http://f:00000000000000000000080/c"><!-- port-00000000000000000000080 -->
+<input type=image alt="foo" src="file://"><!-- scheme-file-slash-slash-only -->
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src-whitespace-only-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src-whitespace-only-novalid.html
new file mode 100644
index 00000000000..e3d0486e622
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src-whitespace-only-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>empty src is not valid</title>
+<input type=image alt="foo" src="
+">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/fragment-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/fragment-backslash-novalid.html
new file mode 100644
index 00000000000..eda0b37a8ab
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/fragment-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: fragment-backslash</title>
+<input type=image alt="foo" src="#\">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/fragment-contains-hash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/fragment-contains-hash-novalid.html
new file mode 100644
index 00000000000..3b4ada53301
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/fragment-contains-hash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: fragment-contains-hash</title>
+<input type=image alt="foo" src="http://foo/path#f#g">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/fragment-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/fragment-leading-space-novalid.html
new file mode 100644
index 00000000000..4e91c794ab9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/fragment-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: fragment-leading-space</title>
+<input type=image alt="foo" src="http://f:21/b# e">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-cr-novalid.html
new file mode 100644
index 00000000000..c6c7dcd6956
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-cr</title>
+<input type=image alt="foo" src="http://example. org">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-double-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-double-percent-encoded-novalid.html
new file mode 100644
index 00000000000..3946af19fe7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-double-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-double-percent-encoded</title>
+<input type=image alt="foo" src="http://%41.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-double-percent-encoded-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-double-percent-encoded-percent-encoded-novalid.html
new file mode 100644
index 00000000000..0e657ba1a71
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-double-percent-encoded-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-double-percent-encoded-percent-encoded</title>
+<input type=image alt="foo" src="http://%ef%bc%85%ef%bc%94%ef%bc%91.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-empty-novalid.html
new file mode 100644
index 00000000000..faac339c6bd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-empty</title>
+<input type=image alt="foo" src="http://">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-empty-userinfo-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-empty-userinfo-empty-novalid.html
new file mode 100644
index 00000000000..623e61268b7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-empty-userinfo-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-empty-userinfo-empty</title>
+<input type=image alt="foo" src="http://@/www.example.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-empty-with-userinfo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-empty-with-userinfo-novalid.html
new file mode 100644
index 00000000000..9cc6d8624d3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-empty-with-userinfo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-empty-with-userinfo</title>
+<input type=image alt="foo" src="http://user:pass@/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-hostname-in-brackets-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-hostname-in-brackets-novalid.html
new file mode 100644
index 00000000000..c48b95b0087
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-hostname-in-brackets-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-hostname-in-brackets</title>
+<input type=image alt="foo" src="http://[www.google.com]/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-invalid-unicode-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-invalid-unicode-novalid.html
new file mode 100644
index 00000000000..8595d37ecca
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-invalid-unicode-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-invalid-unicode</title>
+<input type=image alt="foo" src="http://﷐zyx.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-invalid-unicode-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-invalid-unicode-percent-encoded-novalid.html
new file mode 100644
index 00000000000..3c7f42df1cd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-invalid-unicode-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-invalid-unicode-percent-encoded</title>
+<input type=image alt="foo" src="http://%ef%b7%90zyx.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-newline-novalid.html
new file mode 100644
index 00000000000..68fdc0aea44
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-newline</title>
+<input type=image alt="foo" src="http://example.
+org">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-space-novalid.html
new file mode 100644
index 00000000000..45c7e8bb15a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-space</title>
+<input type=image alt="foo" src="http://example .org">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-square-brackets-port-contains-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-square-brackets-port-contains-colon-novalid.html
new file mode 100644
index 00000000000..b4b5552a8b6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-square-brackets-port-contains-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-square-brackets-port-contains-colon</title>
+<input type=image alt="foo" src="http://[1::2]:3:4">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-tab-novalid.html
new file mode 100644
index 00000000000..ae443539c94
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-tab</title>
+<input type=image alt="foo" src="http://example .org">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-u0000-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-u0000-percent-encoded-novalid.html
new file mode 100644
index 00000000000..8e554bb9ca2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-u0000-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-u0000-percent-encoded</title>
+<input type=image alt="foo" src="http://%00.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-u0000-percent-encoded-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-u0000-percent-encoded-percent-encoded-novalid.html
new file mode 100644
index 00000000000..ea9f960fee4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/host-u0000-percent-encoded-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-u0000-percent-encoded-percent-encoded</title>
+<input type=image alt="foo" src="http://%ef%bc%85%ef%bc%90%ef%bc%90.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/path-bare-percent-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/path-bare-percent-sign-novalid.html
new file mode 100644
index 00000000000..864ea496045
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/path-bare-percent-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-bare-percent-sign</title>
+<input type=image alt="foo" src="http://example.com/foo%">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/path-contains-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/path-contains-space-novalid.html
new file mode 100644
index 00000000000..069e2a1c382
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/path-contains-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-contains-space</title>
+<input type=image alt="foo" src="/a/ /c">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/path-leading-backslash-at-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/path-leading-backslash-at-sign-novalid.html
new file mode 100644
index 00000000000..71b05d901a8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/path-leading-backslash-at-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-leading-backslash-at-sign</title>
+<input type=image alt="foo" src="http://foo.com/\@">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/path-leading-colon-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/path-leading-colon-backslash-novalid.html
new file mode 100644
index 00000000000..2d4baf9108f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/path-leading-colon-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-leading-colon-backslash</title>
+<input type=image alt="foo" src=":\">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/path-leading-colon-chars-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/path-leading-colon-chars-backslash-novalid.html
new file mode 100644
index 00000000000..ef690bbf07c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/path-leading-colon-chars-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-leading-colon-chars-backslash</title>
+<input type=image alt="foo" src=":foo.com\">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/path-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/path-leading-space-novalid.html
new file mode 100644
index 00000000000..c0204f5c1af
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/path-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-leading-space</title>
+<input type=image alt="foo" src="http://f:21/ b">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/path-percent-encoded-malformed-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/path-percent-encoded-malformed-novalid.html
new file mode 100644
index 00000000000..c5222fab64c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/path-percent-encoded-malformed-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-percent-encoded-malformed</title>
+<input type=image alt="foo" src="http://example.com/foo/%2e%2">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/path-relative-square-brackets-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/path-relative-square-brackets-novalid.html
new file mode 100644
index 00000000000..8c05cbef6b6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/path-relative-square-brackets-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-relative-square-brackets</title>
+<input type=image alt="foo" src="[61:24:74]:98">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/path-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/path-tab-novalid.html
new file mode 100644
index 00000000000..a2b683d9dcd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/path-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-tab</title>
+<input type=image alt="foo" src="http://example.com/foo bar">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/path-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/path-trailing-space-novalid.html
new file mode 100644
index 00000000000..a047676f478
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/path-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-trailing-space</title>
+<input type=image alt="foo" src="http://f:21/b ?">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/path-u0091-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/path-u0091-novalid.html
new file mode 100644
index 00000000000..0da7c170cc2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/path-u0091-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-u0091</title>
+<input type=image alt="foo" src="http://example.com/foo‘">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/port-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/port-cr-novalid.html
new file mode 100644
index 00000000000..b2467d2be6b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/port-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-cr</title>
+<input type=image alt="foo" src="http://f: /c">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/port-leading-colon-bracket-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/port-leading-colon-bracket-colon-novalid.html
new file mode 100644
index 00000000000..1bb21c61b80
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/port-leading-colon-bracket-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-leading-colon-bracket-colon</title>
+<input type=image alt="foo" src="http://2001::1]:80">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/port-leading-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/port-leading-colon-novalid.html
new file mode 100644
index 00000000000..5b7c1837713
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/port-leading-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-leading-colon</title>
+<input type=image alt="foo" src="http://2001::1">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/port-leading-dash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/port-leading-dash-novalid.html
new file mode 100644
index 00000000000..0f125e1f851
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/port-leading-dash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-leading-dash</title>
+<input type=image alt="foo" src="http://foo:-80/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/port-multiple-letters-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/port-multiple-letters-novalid.html
new file mode 100644
index 00000000000..ffc0b87472b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/port-multiple-letters-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-multiple-letters</title>
+<input type=image alt="foo" src="http://f:fifty-two/c">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/port-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/port-newline-novalid.html
new file mode 100644
index 00000000000..51e6c7358fc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/port-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-newline</title>
+<input type=image alt="foo" src="http://f:
+/c">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/port-single-letter-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/port-single-letter-novalid.html
new file mode 100644
index 00000000000..007ec33d1e1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/port-single-letter-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-single-letter</title>
+<input type=image alt="foo" src="http://f:b/c">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/port-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/port-space-novalid.html
new file mode 100644
index 00000000000..4086ace7a92
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/port-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-space</title>
+<input type=image alt="foo" src="http://f: /c">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/port-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/port-tab-novalid.html
new file mode 100644
index 00000000000..90faa300775
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/port-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-tab</title>
+<input type=image alt="foo" src="http://f: /c">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/query-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/query-leading-space-novalid.html
new file mode 100644
index 00000000000..183e1fad858
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/query-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: query-leading-space</title>
+<input type=image alt="foo" src="http://f:21/b? d">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/query-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/query-trailing-space-novalid.html
new file mode 100644
index 00000000000..a64a7c6b7cc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/query-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: query-trailing-space</title>
+<input type=image alt="foo" src="http://f:21/b?d #">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-data-contains-fragment-haswarn.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-data-contains-fragment-haswarn.html
new file mode 100644
index 00000000000..71b9a8873b9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-data-contains-fragment-haswarn.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>src warning: scheme-data-contains-fragment</title>
+<input type=image alt="foo" src="data:text/html,test#test">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-data-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-data-single-slash-novalid.html
new file mode 100644
index 00000000000..a2b5d1f8622
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-data-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-data-single-slash</title>
+<input type=image alt="foo" src="data:/example.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-file-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-file-backslash-novalid.html
new file mode 100644
index 00000000000..0a1b8fb52e6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-file-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-file-backslash</title>
+<input type=image alt="foo" src="file:c:\foo\bar.html">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-file-single-slash-c-bar-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-file-single-slash-c-bar-novalid.html
new file mode 100644
index 00000000000..ee896fe55fc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-file-single-slash-c-bar-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-file-single-slash-c-bar</title>
+<input type=image alt="foo" src="file:/C|/foo/bar">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-file-triple-slash-c-bar-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-file-triple-slash-c-bar-novalid.html
new file mode 100644
index 00000000000..8cb7521e8b3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-file-triple-slash-c-bar-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-file-triple-slash-c-bar</title>
+<input type=image alt="foo" src="file:///C|/foo/bar">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-ftp-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-ftp-no-slash-novalid.html
new file mode 100644
index 00000000000..bd109af8072
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-ftp-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-ftp-no-slash</title>
+<input type=image alt="foo" src="ftp:example.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-ftp-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-ftp-single-slash-novalid.html
new file mode 100644
index 00000000000..d892ac52d97
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-ftp-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-ftp-single-slash</title>
+<input type=image alt="foo" src="ftp:/example.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-http-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-http-backslash-novalid.html
new file mode 100644
index 00000000000..6fafed4ab53
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-http-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-http-backslash</title>
+<input type=image alt="foo" src="http:\\foo.com\">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-http-no-slash-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-http-no-slash-colon-novalid.html
new file mode 100644
index 00000000000..90a1212ac29
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-http-no-slash-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-http-no-slash-colon</title>
+<input type=image alt="foo" src="http::@c:29">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-http-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-http-no-slash-novalid.html
new file mode 100644
index 00000000000..e2c684aac53
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-http-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-http-no-slash</title>
+<input type=image alt="foo" src="http:foo.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-http-no-slash-square-bracket-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-http-no-slash-square-bracket-novalid.html
new file mode 100644
index 00000000000..7a64662c8e2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-http-no-slash-square-bracket-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-http-no-slash-square-bracket</title>
+<input type=image alt="foo" src="http:[61:27]/:foo">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-http-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-http-single-slash-novalid.html
new file mode 100644
index 00000000000..cdfd4d74cee
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-http-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-http-single-slash</title>
+<input type=image alt="foo" src="http:/example.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-https-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-https-no-slash-novalid.html
new file mode 100644
index 00000000000..d6b2bce5648
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-https-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-https-no-slash</title>
+<input type=image alt="foo" src="https:example.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-https-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-https-single-slash-novalid.html
new file mode 100644
index 00000000000..301281c141b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-https-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-https-single-slash</title>
+<input type=image alt="foo" src="https:/example.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-javascript-no-slash-malformed-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-javascript-no-slash-malformed-novalid.html
new file mode 100644
index 00000000000..f22ebf50226
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-javascript-no-slash-malformed-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-javascript-no-slash-malformed</title>
+<input type=image alt="foo" src="javascript:example.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-trailing-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-trailing-cr-novalid.html
new file mode 100644
index 00000000000..2cef8164e56
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-trailing-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-trailing-cr</title>
+<input type=image alt="foo" src="a: foo.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-trailing-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-trailing-newline-novalid.html
new file mode 100644
index 00000000000..1cac5852c25
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-trailing-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-trailing-newline</title>
+<input type=image alt="foo" src="a:
+foo.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-trailing-space-novalid.html
new file mode 100644
index 00000000000..8b8f11fa217
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-trailing-space</title>
+<input type=image alt="foo" src="a: foo.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-trailing-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-trailing-tab-novalid.html
new file mode 100644
index 00000000000..6f5772f6b4b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/scheme-trailing-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-trailing-tab</title>
+<input type=image alt="foo" src="a: foo.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/userinfo-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/userinfo-backslash-novalid.html
new file mode 100644
index 00000000000..85b04e06b1a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/userinfo-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: userinfo-backslash</title>
+<input type=image alt="foo" src="http://a\b:c\d@foo.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/userinfo-password-bad-chars-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/userinfo-password-bad-chars-novalid.html
new file mode 100644
index 00000000000..4b3ef342699
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/userinfo-password-bad-chars-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: userinfo-password-bad-chars</title>
+<input type=image alt="foo" src="http://&a:foo(b]c@d:2/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/userinfo-password-contains-pile-of-poo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/userinfo-password-contains-pile-of-poo-novalid.html
new file mode 100644
index 00000000000..2b86aa33273
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/userinfo-password-contains-pile-of-poo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: userinfo-password-contains-pile-of-poo</title>
+<input type=image alt="foo" src="http://foo:💩@example.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/userinfo-username-contains-at-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/userinfo-username-contains-at-sign-novalid.html
new file mode 100644
index 00000000000..bdaf3479f4a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/userinfo-username-contains-at-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: userinfo-username-contains-at-sign</title>
+<input type=image alt="foo" src="http://::@c@d:2">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/userinfo-username-contains-pile-of-poo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/userinfo-username-contains-pile-of-poo-novalid.html
new file mode 100644
index 00000000000..32627a1f331
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-image-src/userinfo-username-contains-pile-of-poo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: userinfo-username-contains-pile-of-poo</title>
+<input type=image alt="foo" src="http://💩:foo@example.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction-empty-novalid.html
new file mode 100644
index 00000000000..ae291ca35bd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>empty formaction is not valid</title>
+<input type=submit formaction="">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction-isvalid.html
new file mode 100644
index 00000000000..332b92065e1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction-isvalid.html
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid formaction</title>
+<input type=submit formaction="file:///"><!-- scheme-file-slash-slash-slash-only -->
+<input type=submit formaction="http://a:@www.example.com"><!-- userinfo-password-empty -->
+<input type=submit formaction="foo://///////"><!-- scheme-private-path-leading-slashes-only -->
+<input type=submit formaction="file://abc|/foo/bar"><!-- scheme-file-slash-slash-abc-bar -->
+<input type=submit formaction="/a/b/c"><!-- path-simple-relative -->
+<input type=submit formaction="http://example.com/你好你好"><!-- path-unicode-han -->
+<input type=submit formaction="/a/%2f/c"><!-- path-percent-encoded-slash-plus-slashes-relative -->
+<input type=submit formaction="http://f:/c"><!-- port-none-but-colon -->
+<input type=submit formaction="http://example.com/foo%41%7a"><!-- path-percent-encoded-multiple -->
+<input type=submit formaction="http://192.168.0.257/"><!-- host-IP-address-broken -->
+<input type=submit formaction="madeupscheme:example.com/"><!-- scheme-private-no-slash -->
+<input type=submit formaction="?"><!-- query-empty-no-path-relative -->
+<input type=submit formaction="http://example.com/%20foo"><!-- path-percent-encoded-space -->
+<input type=submit formaction="mailto:/example.com/"><!-- scheme-mailto-single-slash -->
+<input type=submit formaction="::"><!-- path-leading-colon-colon-relative -->
+<input type=submit formaction="http://example.com/%3A%3a%3C%3c"><!-- path-percent-encoded-mixed-case -->
+<input type=submit formaction="http://user:pass@foo:21/bar;par?b#c"><!-- userinfo -->
+<input type=submit formaction="ws:/example.com/"><!-- scheme-ws-single-slash -->
+<input type=submit formaction="foo://"><!-- scheme-private-slash-slash -->
+<input type=submit formaction="#"><!-- fragment-empty-hash-only-no-path-relative -->
+<input type=submit formaction="http://f:00000000000000/c"><!-- port-00000000000000 -->
+<input type=submit formaction="foo:////://///"><!-- scheme-private-path-leading-slashes-colon-slashes -->
+<input type=submit formaction=":23"><!-- path-leading-colon-number-relative -->
+<input type=submit formaction="foo:/"><!-- scheme-private-slash -->
+<input type=submit formaction="http://💩"><!-- host-is-pile-of-poo -->
+<input type=submit formaction="file:test"><!-- scheme-file-no-slash -->
+<input type=submit formaction="file://C|/foo/bar"><!-- scheme-file-slash-slash-c-bar -->
+<input type=submit formaction="#/"><!-- fragment-slash-relative -->
+<input type=submit formaction="http://192.0x00A80001"><!-- host-192.0x00A80001 -->
+<input type=submit formaction="foo.com"><!-- scheme-none-relative -->
+<input type=submit formaction="http💩//:foo"><!-- path-contains-pile-of-poo -->
+<input type=submit formaction="File://foo/bar.html"><!-- scheme-file-uppercase -->
+<input type=submit formaction=":/"><!-- path-leading-colon-slash-relative -->
+<input type=submit formaction="http://www.foo。bar.com"><!-- host-exotic-dot -->
+<input type=submit formaction="http://GOO​⁠goo.com"><!-- host-exotic-whitespace -->
+<input type=submit formaction="file:///foo/bar.txt"><!-- scheme-file-host-empty -->
+<input type=submit formaction="javascript:/example.com/"><!-- scheme-javascript-single-slash -->
+<input type=submit formaction="gopher:/example.com/"><!-- scheme-gopher-single-slash -->
+<input type=submit formaction="ftps:example.com/"><!-- scheme-ftps-no-slash -->
+<input type=submit formaction="file://server/foo/bar"><!-- scheme-file-host-included -->
+<input type=submit formaction="http://example.com/foo%00"><!-- path-percent-encoded-u0000 -->
+<input type=submit formaction="a:foo.com"><!-- scheme-private -->
+<input type=submit formaction=":"><!-- path-colon-relative -->
+<input type=submit formaction="http://:b@www.example.com"><!-- userinfo-user-empty -->
+<input type=submit formaction="file:/"><!-- scheme-file-slash-only -->
+<input type=submit formaction="wss:example.com/"><!-- scheme-wss-no-slash -->
+<input type=submit formaction="::23"><!-- path-colon-colon-number-relative -->
+<input type=submit formaction="/a%2fc"><!-- path-percent-encoded-slash-relative -->
+<input type=submit formaction="http://a:b@c:29/d"><!-- userinfo-host-port-path -->
+<input type=submit formaction="gopher:example.com/"><!-- scheme-gopher-no-slash -->
+<input type=submit formaction="madeupscheme:/example.com/"><!-- scheme-private-single-slash -->
+<input type=submit formaction="mailto:example.com/"><!-- scheme-mailto-no-slash -->
+<input type=submit formaction="http://%25DOMAIN:foobar@foodomain.com"><!-- userinfo-username-contains-percent-encoded -->
+<input type=submit formaction="/:23"><!-- path-slash-colon-number-relative -->
+<input type=submit formaction="foo://///////bar.com/"><!-- scheme-private-path-leading-slashes-chars -->
+<input type=submit formaction="http://[2001::1]:80"><!-- host-ipv6-port -->
+<input type=submit formaction="data:text/plain,foo"><!-- scheme-data-no-slash -->
+<input type=submit formaction="http://example.com/foo/%2e"><!-- path-percent-encoded-dot -->
+<input type=submit formaction="file:/example.com/"><!-- scheme-file-single-slash -->
+<input type=submit formaction="http://example.com/©zbar"><!-- path-non-ascii -->
+<input type=submit formaction="http://example.com//foo"><!-- path-uFEFF -->
+<input type=submit formaction="wss:/example.com/"><!-- scheme-wss-single-slash -->
+<input type=submit formaction="http://foo/abcd#foo?bar"><!-- fragment-contains-question-mark -->
+<input type=submit formaction=":#"><!-- path-leading-colon-hash-relative -->
+<input type=submit formaction="http://example.com/foo%91"><!-- path-percent-encoded-u0091 -->
+<input type=submit formaction="c:/foo"><!-- scheme-private-single-letter -->
+<input type=submit formaction=":foo.com"><!-- path-leading-colon-chars-relative -->
+<input type=submit formaction="http://你好你好"><!-- host-idn-unicode-han -->
+<input type=submit formaction="http://example.com/foo#💩"><!-- fragment-contains-pile-of-poo -->
+<input type=submit formaction="file:"><!-- scheme-file-scheme-only -->
+<input type=submit formaction="#β"><!-- fragment-non-ascii-relative -->
+<input type=submit formaction="foo:/bar.com/"><!-- scheme-private-path -->
+<input type=submit formaction="http://f:0/c"><!-- port-0 -->
+<input type=submit formaction="#;?"><!-- fragment-semicolon-question-mark-relative -->
+<input type=submit formaction="http://Go.com"><!-- host-fullwidth -->
+<input type=submit formaction="http://@www.example.com"><!-- userinfo-empty -->
+<input type=submit formaction="http://example.com/‮/foo/‭/bar"><!-- path-u202E-u202D -->
+<input type=submit formaction="http://[2001::1]"><!-- host-ipv6 -->
+<input type=submit formaction="💩http://foo"><!-- path-starts-with-pile-of-poo -->
+<input type=submit formaction="http://foo/abcd?efgh?ijkl"><!-- query-contains-question-mark -->
+<input type=submit formaction="//foo/bar"><!-- scheme-schemeless-relative -->
+<input type=submit formaction="ftps:/example.com/"><!-- scheme-ftps-single-slash -->
+<input type=submit formaction="http://foo.com:b@d/"><!-- userinfo-username-non-alpha -->
+<input type=submit formaction=":a"><!-- path-leading-colon-letter-relative -->
+<input type=submit formaction="/"><!-- path-slash-only-relative -->
+<input type=submit formaction="http://example.com/foo?💩"><!-- query-contains-pile-of-poo -->
+<input type=submit formaction="http://f:00000000000000000000080/c"><!-- port-00000000000000000000080 -->
+<input type=submit formaction="file://"><!-- scheme-file-slash-slash-only -->
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction-whitespace-only-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction-whitespace-only-novalid.html
new file mode 100644
index 00000000000..6f2d34e8d13
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction-whitespace-only-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>empty formaction is not valid</title>
+<input type=submit formaction="
+">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/fragment-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/fragment-backslash-novalid.html
new file mode 100644
index 00000000000..f425c30763f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/fragment-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: fragment-backslash</title>
+<input type=submit formaction="#\">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/fragment-contains-hash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/fragment-contains-hash-novalid.html
new file mode 100644
index 00000000000..074b066b9e3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/fragment-contains-hash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: fragment-contains-hash</title>
+<input type=submit formaction="http://foo/path#f#g">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/fragment-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/fragment-leading-space-novalid.html
new file mode 100644
index 00000000000..370bc0d8bf9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/fragment-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: fragment-leading-space</title>
+<input type=submit formaction="http://f:21/b# e">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-cr-novalid.html
new file mode 100644
index 00000000000..30c67fdf9e5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: host-cr</title>
+<input type=submit formaction="http://example. org">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-double-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-double-percent-encoded-novalid.html
new file mode 100644
index 00000000000..b6bcab6dcac
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-double-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: host-double-percent-encoded</title>
+<input type=submit formaction="http://%41.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-double-percent-encoded-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-double-percent-encoded-percent-encoded-novalid.html
new file mode 100644
index 00000000000..b25b389482a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-double-percent-encoded-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: host-double-percent-encoded-percent-encoded</title>
+<input type=submit formaction="http://%ef%bc%85%ef%bc%94%ef%bc%91.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-empty-novalid.html
new file mode 100644
index 00000000000..7f0bff475ae
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: host-empty</title>
+<input type=submit formaction="http://">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-empty-userinfo-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-empty-userinfo-empty-novalid.html
new file mode 100644
index 00000000000..548576d6f8d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-empty-userinfo-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: host-empty-userinfo-empty</title>
+<input type=submit formaction="http://@/www.example.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-empty-with-userinfo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-empty-with-userinfo-novalid.html
new file mode 100644
index 00000000000..fc22cd19463
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-empty-with-userinfo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: host-empty-with-userinfo</title>
+<input type=submit formaction="http://user:pass@/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-hostname-in-brackets-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-hostname-in-brackets-novalid.html
new file mode 100644
index 00000000000..6b714a213bf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-hostname-in-brackets-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: host-hostname-in-brackets</title>
+<input type=submit formaction="http://[www.google.com]/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-invalid-unicode-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-invalid-unicode-novalid.html
new file mode 100644
index 00000000000..f9e490b155f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-invalid-unicode-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: host-invalid-unicode</title>
+<input type=submit formaction="http://﷐zyx.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-invalid-unicode-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-invalid-unicode-percent-encoded-novalid.html
new file mode 100644
index 00000000000..8bd4fa53b78
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-invalid-unicode-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: host-invalid-unicode-percent-encoded</title>
+<input type=submit formaction="http://%ef%b7%90zyx.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-newline-novalid.html
new file mode 100644
index 00000000000..4bf31608365
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: host-newline</title>
+<input type=submit formaction="http://example.
+org">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-space-novalid.html
new file mode 100644
index 00000000000..40d1b5e1b31
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: host-space</title>
+<input type=submit formaction="http://example .org">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-square-brackets-port-contains-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-square-brackets-port-contains-colon-novalid.html
new file mode 100644
index 00000000000..b58d8edfb83
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-square-brackets-port-contains-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: host-square-brackets-port-contains-colon</title>
+<input type=submit formaction="http://[1::2]:3:4">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-tab-novalid.html
new file mode 100644
index 00000000000..1f0818c8359
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: host-tab</title>
+<input type=submit formaction="http://example .org">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-u0000-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-u0000-percent-encoded-novalid.html
new file mode 100644
index 00000000000..38d6adf0579
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-u0000-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: host-u0000-percent-encoded</title>
+<input type=submit formaction="http://%00.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-u0000-percent-encoded-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-u0000-percent-encoded-percent-encoded-novalid.html
new file mode 100644
index 00000000000..d4628743d45
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/host-u0000-percent-encoded-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: host-u0000-percent-encoded-percent-encoded</title>
+<input type=submit formaction="http://%ef%bc%85%ef%bc%90%ef%bc%90.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/path-bare-percent-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/path-bare-percent-sign-novalid.html
new file mode 100644
index 00000000000..507dd282c1b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/path-bare-percent-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: path-bare-percent-sign</title>
+<input type=submit formaction="http://example.com/foo%">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/path-contains-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/path-contains-space-novalid.html
new file mode 100644
index 00000000000..41b10273045
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/path-contains-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: path-contains-space</title>
+<input type=submit formaction="/a/ /c">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/path-leading-backslash-at-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/path-leading-backslash-at-sign-novalid.html
new file mode 100644
index 00000000000..5bc0f540f26
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/path-leading-backslash-at-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: path-leading-backslash-at-sign</title>
+<input type=submit formaction="http://foo.com/\@">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/path-leading-colon-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/path-leading-colon-backslash-novalid.html
new file mode 100644
index 00000000000..9f96f075289
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/path-leading-colon-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: path-leading-colon-backslash</title>
+<input type=submit formaction=":\">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/path-leading-colon-chars-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/path-leading-colon-chars-backslash-novalid.html
new file mode 100644
index 00000000000..a6d07f61243
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/path-leading-colon-chars-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: path-leading-colon-chars-backslash</title>
+<input type=submit formaction=":foo.com\">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/path-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/path-leading-space-novalid.html
new file mode 100644
index 00000000000..2906aa3acc3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/path-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: path-leading-space</title>
+<input type=submit formaction="http://f:21/ b">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/path-percent-encoded-malformed-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/path-percent-encoded-malformed-novalid.html
new file mode 100644
index 00000000000..955bd05ab5f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/path-percent-encoded-malformed-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: path-percent-encoded-malformed</title>
+<input type=submit formaction="http://example.com/foo/%2e%2">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/path-relative-square-brackets-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/path-relative-square-brackets-novalid.html
new file mode 100644
index 00000000000..3bc8dbf2dc3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/path-relative-square-brackets-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: path-relative-square-brackets</title>
+<input type=submit formaction="[61:24:74]:98">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/path-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/path-tab-novalid.html
new file mode 100644
index 00000000000..e424a2a23f1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/path-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: path-tab</title>
+<input type=submit formaction="http://example.com/foo bar">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/path-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/path-trailing-space-novalid.html
new file mode 100644
index 00000000000..d61566d2905
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/path-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: path-trailing-space</title>
+<input type=submit formaction="http://f:21/b ?">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/path-u0091-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/path-u0091-novalid.html
new file mode 100644
index 00000000000..d9c5c0bddc5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/path-u0091-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: path-u0091</title>
+<input type=submit formaction="http://example.com/foo‘">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/port-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/port-cr-novalid.html
new file mode 100644
index 00000000000..bcacfa8b82b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/port-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: port-cr</title>
+<input type=submit formaction="http://f: /c">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/port-leading-colon-bracket-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/port-leading-colon-bracket-colon-novalid.html
new file mode 100644
index 00000000000..02caabe38bf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/port-leading-colon-bracket-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: port-leading-colon-bracket-colon</title>
+<input type=submit formaction="http://2001::1]:80">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/port-leading-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/port-leading-colon-novalid.html
new file mode 100644
index 00000000000..1222d48fe34
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/port-leading-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: port-leading-colon</title>
+<input type=submit formaction="http://2001::1">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/port-leading-dash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/port-leading-dash-novalid.html
new file mode 100644
index 00000000000..eea1fb9fe89
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/port-leading-dash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: port-leading-dash</title>
+<input type=submit formaction="http://foo:-80/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/port-multiple-letters-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/port-multiple-letters-novalid.html
new file mode 100644
index 00000000000..575f7b15654
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/port-multiple-letters-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: port-multiple-letters</title>
+<input type=submit formaction="http://f:fifty-two/c">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/port-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/port-newline-novalid.html
new file mode 100644
index 00000000000..77281c7f26a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/port-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: port-newline</title>
+<input type=submit formaction="http://f:
+/c">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/port-single-letter-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/port-single-letter-novalid.html
new file mode 100644
index 00000000000..231f8865996
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/port-single-letter-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: port-single-letter</title>
+<input type=submit formaction="http://f:b/c">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/port-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/port-space-novalid.html
new file mode 100644
index 00000000000..df250d3cb3b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/port-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: port-space</title>
+<input type=submit formaction="http://f: /c">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/port-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/port-tab-novalid.html
new file mode 100644
index 00000000000..7e817369db2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/port-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: port-tab</title>
+<input type=submit formaction="http://f: /c">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/query-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/query-leading-space-novalid.html
new file mode 100644
index 00000000000..9bdcfa9ce75
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/query-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: query-leading-space</title>
+<input type=submit formaction="http://f:21/b? d">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/query-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/query-trailing-space-novalid.html
new file mode 100644
index 00000000000..094f5008d82
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/query-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: query-trailing-space</title>
+<input type=submit formaction="http://f:21/b?d #">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-data-contains-fragment-haswarn.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-data-contains-fragment-haswarn.html
new file mode 100644
index 00000000000..4677df8937f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-data-contains-fragment-haswarn.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>formaction warning: scheme-data-contains-fragment</title>
+<input type=submit formaction="data:text/html,test#test">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-data-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-data-single-slash-novalid.html
new file mode 100644
index 00000000000..ae851bea539
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-data-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: scheme-data-single-slash</title>
+<input type=submit formaction="data:/example.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-file-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-file-backslash-novalid.html
new file mode 100644
index 00000000000..22600d617d7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-file-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: scheme-file-backslash</title>
+<input type=submit formaction="file:c:\foo\bar.html">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-file-single-slash-c-bar-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-file-single-slash-c-bar-novalid.html
new file mode 100644
index 00000000000..05c18e64692
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-file-single-slash-c-bar-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: scheme-file-single-slash-c-bar</title>
+<input type=submit formaction="file:/C|/foo/bar">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-file-triple-slash-c-bar-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-file-triple-slash-c-bar-novalid.html
new file mode 100644
index 00000000000..f15f3083d51
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-file-triple-slash-c-bar-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: scheme-file-triple-slash-c-bar</title>
+<input type=submit formaction="file:///C|/foo/bar">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-ftp-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-ftp-no-slash-novalid.html
new file mode 100644
index 00000000000..f4d95347da7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-ftp-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: scheme-ftp-no-slash</title>
+<input type=submit formaction="ftp:example.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-ftp-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-ftp-single-slash-novalid.html
new file mode 100644
index 00000000000..40314614e4f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-ftp-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: scheme-ftp-single-slash</title>
+<input type=submit formaction="ftp:/example.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-http-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-http-backslash-novalid.html
new file mode 100644
index 00000000000..a29e4fa9751
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-http-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: scheme-http-backslash</title>
+<input type=submit formaction="http:\\foo.com\">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-http-no-slash-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-http-no-slash-colon-novalid.html
new file mode 100644
index 00000000000..5350ea0a915
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-http-no-slash-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: scheme-http-no-slash-colon</title>
+<input type=submit formaction="http::@c:29">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-http-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-http-no-slash-novalid.html
new file mode 100644
index 00000000000..c7f227eab7c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-http-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: scheme-http-no-slash</title>
+<input type=submit formaction="http:foo.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-http-no-slash-square-bracket-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-http-no-slash-square-bracket-novalid.html
new file mode 100644
index 00000000000..3d66391cd24
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-http-no-slash-square-bracket-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: scheme-http-no-slash-square-bracket</title>
+<input type=submit formaction="http:[61:27]/:foo">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-http-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-http-single-slash-novalid.html
new file mode 100644
index 00000000000..6c69f278936
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-http-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: scheme-http-single-slash</title>
+<input type=submit formaction="http:/example.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-https-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-https-no-slash-novalid.html
new file mode 100644
index 00000000000..6c15ad999d8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-https-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: scheme-https-no-slash</title>
+<input type=submit formaction="https:example.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-https-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-https-single-slash-novalid.html
new file mode 100644
index 00000000000..27e668c97c2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-https-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: scheme-https-single-slash</title>
+<input type=submit formaction="https:/example.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-javascript-no-slash-malformed-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-javascript-no-slash-malformed-novalid.html
new file mode 100644
index 00000000000..fe2c0ce719c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-javascript-no-slash-malformed-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: scheme-javascript-no-slash-malformed</title>
+<input type=submit formaction="javascript:example.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-trailing-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-trailing-cr-novalid.html
new file mode 100644
index 00000000000..3ab19fffd8a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-trailing-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: scheme-trailing-cr</title>
+<input type=submit formaction="a: foo.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-trailing-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-trailing-newline-novalid.html
new file mode 100644
index 00000000000..eba43de91da
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-trailing-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: scheme-trailing-newline</title>
+<input type=submit formaction="a:
+foo.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-trailing-space-novalid.html
new file mode 100644
index 00000000000..e0d62b36fed
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: scheme-trailing-space</title>
+<input type=submit formaction="a: foo.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-trailing-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-trailing-tab-novalid.html
new file mode 100644
index 00000000000..4b75ff2e740
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/scheme-trailing-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: scheme-trailing-tab</title>
+<input type=submit formaction="a: foo.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/userinfo-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/userinfo-backslash-novalid.html
new file mode 100644
index 00000000000..56f8a0b7d99
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/userinfo-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: userinfo-backslash</title>
+<input type=submit formaction="http://a\b:c\d@foo.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/userinfo-password-bad-chars-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/userinfo-password-bad-chars-novalid.html
new file mode 100644
index 00000000000..d005f35cbd4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/userinfo-password-bad-chars-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: userinfo-password-bad-chars</title>
+<input type=submit formaction="http://&a:foo(b]c@d:2/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/userinfo-password-contains-pile-of-poo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/userinfo-password-contains-pile-of-poo-novalid.html
new file mode 100644
index 00000000000..eba2430b586
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/userinfo-password-contains-pile-of-poo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: userinfo-password-contains-pile-of-poo</title>
+<input type=submit formaction="http://foo:💩@example.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/userinfo-username-contains-at-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/userinfo-username-contains-at-sign-novalid.html
new file mode 100644
index 00000000000..060f63c16ba
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/userinfo-username-contains-at-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: userinfo-username-contains-at-sign</title>
+<input type=submit formaction="http://::@c@d:2">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/userinfo-username-contains-pile-of-poo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/userinfo-username-contains-pile-of-poo-novalid.html
new file mode 100644
index 00000000000..5e528bff8b5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-submit-formaction/userinfo-username-contains-pile-of-poo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid formaction: userinfo-username-contains-pile-of-poo</title>
+<input type=submit formaction="http://💩:foo@example.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value-empty-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value-empty-isvalid.html
new file mode 100644
index 00000000000..229b7a2b99d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value-empty-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>empty value attribute is valid</title>
+<input type=url value="">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value-isvalid.html
new file mode 100644
index 00000000000..93f5eb5cc70
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value-isvalid.html
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid value attribute</title>
+<input type=url value="file:///"><!-- scheme-file-slash-slash-slash-only -->
+<input type=url value="http://a:@www.example.com"><!-- userinfo-password-empty -->
+<input type=url value="foo://///////"><!-- scheme-private-path-leading-slashes-only -->
+<input type=url value="file://abc|/foo/bar"><!-- scheme-file-slash-slash-abc-bar -->
+<input type=url value="http://example.com/foo#💩"><!-- fragment-contains-pile-of-poo -->
+<input type=url value="http://example.com/你好你好"><!-- path-unicode-han -->
+<input type=url value="http://f:/c"><!-- port-none-but-colon -->
+<input type=url value="http://example.com/foo%41%7a"><!-- path-percent-encoded-multiple -->
+<input type=url value="http://192.168.0.257/"><!-- host-IP-address-broken -->
+<input type=url value="madeupscheme:example.com/"><!-- scheme-private-no-slash -->
+<input type=url value="http://example.com/%20foo"><!-- path-percent-encoded-space -->
+<input type=url value="http://%25DOMAIN:foobar@foodomain.com"><!-- userinfo-username-contains-percent-encoded -->
+<input type=url value="http://你好你好"><!-- host-idn-unicode-han -->
+<input type=url value="http://example.com/%3A%3a%3C%3c"><!-- path-percent-encoded-mixed-case -->
+<input type=url value="http://user:pass@foo:21/bar;par?b#c"><!-- userinfo -->
+<input type=url value="ws:/example.com/"><!-- scheme-ws-single-slash -->
+<input type=url value="foo://"><!-- scheme-private-slash-slash -->
+<input type=url value="http://f:00000000000000/c"><!-- port-00000000000000 -->
+<input type=url value="foo:////://///"><!-- scheme-private-path-leading-slashes-colon-slashes -->
+<input type=url value="foo:/"><!-- scheme-private-slash -->
+<input type=url value="http://💩"><!-- host-is-pile-of-poo -->
+<input type=url value="file:test"><!-- scheme-file-no-slash -->
+<input type=url value="file://C|/foo/bar"><!-- scheme-file-slash-slash-c-bar -->
+<input type=url value="http://192.0x00A80001"><!-- host-192.0x00A80001 -->
+<input type=url value="http://example.com/foo/💩"><!-- path-contains-pile-of-poo -->
+<input type=url value="File://foo/bar.html"><!-- scheme-file-uppercase -->
+<input type=url value="http://www.foo。bar.com"><!-- host-exotic-dot -->
+<input type=url value="http://GOO​⁠goo.com"><!-- host-exotic-whitespace -->
+<input type=url value="file:///foo/bar.txt"><!-- scheme-file-host-empty -->
+<input type=url value="javascript:/example.com/"><!-- scheme-javascript-single-slash -->
+<input type=url value="gopher:/example.com/"><!-- scheme-gopher-single-slash -->
+<input type=url value="ftps:example.com/"><!-- scheme-ftps-no-slash -->
+<input type=url value="file://server/foo/bar"><!-- scheme-file-host-included -->
+<input type=url value="http://foo/abcd#foo?bar"><!-- fragment-contains-question-mark -->
+<input type=url value="a:foo.com"><!-- scheme-private -->
+<input type=url value="http://:b@www.example.com"><!-- userinfo-user-empty -->
+<input type=url value="file:/"><!-- scheme-file-slash-only -->
+<input type=url value="madeupscheme:/example.com/"><!-- scheme-private-single-slash -->
+<input type=url value="http://a:b@c:29/d"><!-- userinfo-host-port-path -->
+<input type=url value="gopher:example.com/"><!-- scheme-gopher-no-slash -->
+<input type=url value="mailto:example.com/"><!-- scheme-mailto-no-slash -->
+<input type=url value="mailto:/example.com/"><!-- scheme-mailto-single-slash -->
+<input type=url value="foo://///////bar.com/"><!-- scheme-private-path-leading-slashes-chars -->
+<input type=url value="http://[2001::1]:80"><!-- host-ipv6-port -->
+<input type=url value="http://example.com/foo/%2e"><!-- path-percent-encoded-dot -->
+<input type=url value="file:/example.com/"><!-- scheme-file-single-slash -->
+<input type=url value="http://example.com/©zbar"><!-- path-non-ascii -->
+<input type=url value="http://example.com//foo"><!-- path-uFEFF -->
+<input type=url value="wss:/example.com/"><!-- scheme-wss-single-slash -->
+<input type=url value="http://example.com/foo%00"><!-- path-percent-encoded-u0000 -->
+<input type=url value="http://example.com/foo%91"><!-- path-percent-encoded-u0091 -->
+<input type=url value="c:/foo"><!-- scheme-private-single-letter -->
+<input type=url value="wss:example.com/"><!-- scheme-wss-no-slash -->
+<input type=url value="http://foo/abcd?efgh?ijkl"><!-- query-contains-question-mark -->
+<input type=url value="file:"><!-- scheme-file-scheme-only -->
+<input type=url value="foo:/bar.com/"><!-- scheme-private-path -->
+<input type=url value="http://f:0/c"><!-- port-0 -->
+<input type=url value="http://Go.com"><!-- host-fullwidth -->
+<input type=url value="http://@www.example.com"><!-- userinfo-empty -->
+<input type=url value="http://example.com/‮/foo/‭/bar"><!-- path-u202E-u202D -->
+<input type=url value="http://[2001::1]"><!-- host-ipv6 -->
+<input type=url value="ftps:/example.com/"><!-- scheme-ftps-single-slash -->
+<input type=url value="http://foo.com:b@d/"><!-- userinfo-username-non-alpha -->
+<input type=url value="data:text/plain,foo"><!-- scheme-data-no-slash -->
+<input type=url value="http://example.com/foo?💩"><!-- query-contains-pile-of-poo -->
+<input type=url value="http://f:00000000000000000000080/c"><!-- port-00000000000000000000080 -->
+<input type=url value="file://"><!-- scheme-file-slash-slash-only -->
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/fragment-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/fragment-backslash-novalid.html
new file mode 100644
index 00000000000..0f194d5862e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/fragment-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: fragment-backslash</title>
+<input type=url value="#\">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/fragment-contains-hash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/fragment-contains-hash-novalid.html
new file mode 100644
index 00000000000..aae446c357d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/fragment-contains-hash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: fragment-contains-hash</title>
+<input type=url value="http://foo/path#f#g">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/fragment-empty-hash-only-no-path-relative-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/fragment-empty-hash-only-no-path-relative-novalid.html
new file mode 100644
index 00000000000..afb742bdd64
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/fragment-empty-hash-only-no-path-relative-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: fragment-empty-hash-only-no-path-relative</title>
+<input type=url value="#">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/fragment-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/fragment-leading-space-novalid.html
new file mode 100644
index 00000000000..58535e9c970
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/fragment-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: fragment-leading-space</title>
+<input type=url value="http://f:21/b# e">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/fragment-non-ascii-relative-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/fragment-non-ascii-relative-novalid.html
new file mode 100644
index 00000000000..ad41f427b31
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/fragment-non-ascii-relative-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: fragment-non-ascii-relative</title>
+<input type=url value="#β">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/fragment-semicolon-question-mark-relative-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/fragment-semicolon-question-mark-relative-novalid.html
new file mode 100644
index 00000000000..1bfc99cc92f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/fragment-semicolon-question-mark-relative-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: fragment-semicolon-question-mark-relative</title>
+<input type=url value="#;?">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/fragment-slash-relative-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/fragment-slash-relative-novalid.html
new file mode 100644
index 00000000000..ccbfa4c2f3c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/fragment-slash-relative-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: fragment-slash-relative</title>
+<input type=url value="#/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-cr-novalid.html
new file mode 100644
index 00000000000..b47e6fc5fe0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: host-cr</title>
+<input type=url value="http://example. org">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-double-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-double-percent-encoded-novalid.html
new file mode 100644
index 00000000000..f8e96bc4493
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-double-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: host-double-percent-encoded</title>
+<input type=url value="http://%41.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-double-percent-encoded-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-double-percent-encoded-percent-encoded-novalid.html
new file mode 100644
index 00000000000..392c783d0bc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-double-percent-encoded-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: host-double-percent-encoded-percent-encoded</title>
+<input type=url value="http://%ef%bc%85%ef%bc%94%ef%bc%91.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-empty-novalid.html
new file mode 100644
index 00000000000..d56b619caa2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: host-empty</title>
+<input type=url value="http://">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-empty-userinfo-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-empty-userinfo-empty-novalid.html
new file mode 100644
index 00000000000..2ac3f54f433
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-empty-userinfo-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: host-empty-userinfo-empty</title>
+<input type=url value="http://@/www.example.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-empty-with-userinfo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-empty-with-userinfo-novalid.html
new file mode 100644
index 00000000000..7976c171717
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-empty-with-userinfo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: host-empty-with-userinfo</title>
+<input type=url value="http://user:pass@/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-hostname-in-brackets-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-hostname-in-brackets-novalid.html
new file mode 100644
index 00000000000..d4e59450b8d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-hostname-in-brackets-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: host-hostname-in-brackets</title>
+<input type=url value="http://[www.google.com]/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-invalid-unicode-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-invalid-unicode-novalid.html
new file mode 100644
index 00000000000..f18867cc9c0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-invalid-unicode-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: host-invalid-unicode</title>
+<input type=url value="http://﷐zyx.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-invalid-unicode-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-invalid-unicode-percent-encoded-novalid.html
new file mode 100644
index 00000000000..073e1d9eddd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-invalid-unicode-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: host-invalid-unicode-percent-encoded</title>
+<input type=url value="http://%ef%b7%90zyx.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-newline-novalid.html
new file mode 100644
index 00000000000..01a2a771984
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: host-newline</title>
+<input type=url value="http://example.
+org">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-space-novalid.html
new file mode 100644
index 00000000000..95883e2892b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: host-space</title>
+<input type=url value="http://example .org">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-square-brackets-port-contains-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-square-brackets-port-contains-colon-novalid.html
new file mode 100644
index 00000000000..eb0b0a23c7d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-square-brackets-port-contains-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: host-square-brackets-port-contains-colon</title>
+<input type=url value="http://[1::2]:3:4">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-tab-novalid.html
new file mode 100644
index 00000000000..e6be4953ed1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: host-tab</title>
+<input type=url value="http://example .org">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-u0000-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-u0000-percent-encoded-novalid.html
new file mode 100644
index 00000000000..c2460b040b4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-u0000-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: host-u0000-percent-encoded</title>
+<input type=url value="http://%00.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-u0000-percent-encoded-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-u0000-percent-encoded-percent-encoded-novalid.html
new file mode 100644
index 00000000000..905b48383d0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/host-u0000-percent-encoded-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: host-u0000-percent-encoded-percent-encoded</title>
+<input type=url value="http://%ef%bc%85%ef%bc%90%ef%bc%90.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-bare-percent-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-bare-percent-sign-novalid.html
new file mode 100644
index 00000000000..f409db5a020
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-bare-percent-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: path-bare-percent-sign</title>
+<input type=url value="http://example.com/foo%">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-contains-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-contains-space-novalid.html
new file mode 100644
index 00000000000..29e3eddf0b3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-contains-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: path-contains-space</title>
+<input type=url value="/a/ /c">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-leading-backslash-at-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-leading-backslash-at-sign-novalid.html
new file mode 100644
index 00000000000..8ce609a6683
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-leading-backslash-at-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: path-leading-backslash-at-sign</title>
+<input type=url value="http://foo.com/\@">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-leading-colon-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-leading-colon-backslash-novalid.html
new file mode 100644
index 00000000000..10c69106a44
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-leading-colon-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: path-leading-colon-backslash</title>
+<input type=url value=":\">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-leading-colon-chars-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-leading-colon-chars-backslash-novalid.html
new file mode 100644
index 00000000000..b3f22fe4a11
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-leading-colon-chars-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: path-leading-colon-chars-backslash</title>
+<input type=url value=":foo.com\">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-leading-space-novalid.html
new file mode 100644
index 00000000000..657fd16e307
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: path-leading-space</title>
+<input type=url value="http://f:21/ b">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-percent-encoded-malformed-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-percent-encoded-malformed-novalid.html
new file mode 100644
index 00000000000..cc232af6813
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-percent-encoded-malformed-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: path-percent-encoded-malformed</title>
+<input type=url value="http://example.com/foo/%2e%2">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-percent-encoded-slash-plus-slashes-relative-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-percent-encoded-slash-plus-slashes-relative-novalid.html
new file mode 100644
index 00000000000..c717ac0ea5f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-percent-encoded-slash-plus-slashes-relative-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: path-percent-encoded-slash-plus-slashes-relative</title>
+<input type=url value="/a/%2f/c">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-percent-encoded-slash-relative-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-percent-encoded-slash-relative-novalid.html
new file mode 100644
index 00000000000..a61bdcb5b48
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-percent-encoded-slash-relative-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: path-percent-encoded-slash-relative</title>
+<input type=url value="/a%2fc">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-relative-square-brackets-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-relative-square-brackets-novalid.html
new file mode 100644
index 00000000000..f9265b7bbbf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-relative-square-brackets-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: path-relative-square-brackets</title>
+<input type=url value="[61:24:74]:98">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-simple-relative-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-simple-relative-novalid.html
new file mode 100644
index 00000000000..6eb803b7981
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-simple-relative-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: path-simple-relative</title>
+<input type=url value="/a/b/c">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-slash-only-relative-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-slash-only-relative-novalid.html
new file mode 100644
index 00000000000..8fb0efcb466
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-slash-only-relative-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: path-slash-only-relative</title>
+<input type=url value="/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-tab-novalid.html
new file mode 100644
index 00000000000..2d70b76f7cd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: path-tab</title>
+<input type=url value="http://example.com/foo bar">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-trailing-space-novalid.html
new file mode 100644
index 00000000000..8a5b79123a0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: path-trailing-space</title>
+<input type=url value="http://f:21/b ?">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-u0091-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-u0091-novalid.html
new file mode 100644
index 00000000000..ed3ec7f0ab7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/path-u0091-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: path-u0091</title>
+<input type=url value="http://example.com/foo‘">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/port-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/port-cr-novalid.html
new file mode 100644
index 00000000000..650968dfce2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/port-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: port-cr</title>
+<input type=url value="http://f: /c">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/port-leading-colon-bracket-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/port-leading-colon-bracket-colon-novalid.html
new file mode 100644
index 00000000000..d64939376aa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/port-leading-colon-bracket-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: port-leading-colon-bracket-colon</title>
+<input type=url value="http://2001::1]:80">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/port-leading-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/port-leading-colon-novalid.html
new file mode 100644
index 00000000000..030e9d32990
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/port-leading-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: port-leading-colon</title>
+<input type=url value="http://2001::1">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/port-leading-dash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/port-leading-dash-novalid.html
new file mode 100644
index 00000000000..9ceabb9bd61
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/port-leading-dash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: port-leading-dash</title>
+<input type=url value="http://foo:-80/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/port-multiple-letters-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/port-multiple-letters-novalid.html
new file mode 100644
index 00000000000..02df80f07b9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/port-multiple-letters-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: port-multiple-letters</title>
+<input type=url value="http://f:fifty-two/c">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/port-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/port-newline-novalid.html
new file mode 100644
index 00000000000..09c399998dc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/port-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: port-newline</title>
+<input type=url value="http://f:
+/c">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/port-single-letter-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/port-single-letter-novalid.html
new file mode 100644
index 00000000000..7b673eb220f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/port-single-letter-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: port-single-letter</title>
+<input type=url value="http://f:b/c">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/port-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/port-space-novalid.html
new file mode 100644
index 00000000000..cf8439b4d1c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/port-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: port-space</title>
+<input type=url value="http://f: /c">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/port-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/port-tab-novalid.html
new file mode 100644
index 00000000000..f05db667692
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/port-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: port-tab</title>
+<input type=url value="http://f: /c">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/query-empty-no-path-relative-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/query-empty-no-path-relative-novalid.html
new file mode 100644
index 00000000000..9ade778dba2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/query-empty-no-path-relative-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: query-empty-no-path-relative</title>
+<input type=url value="?">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/query-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/query-leading-space-novalid.html
new file mode 100644
index 00000000000..49196c94a11
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/query-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: query-leading-space</title>
+<input type=url value="http://f:21/b? d">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/query-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/query-trailing-space-novalid.html
new file mode 100644
index 00000000000..a877bdf1db5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/query-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: query-trailing-space</title>
+<input type=url value="http://f:21/b?d #">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-data-contains-fragment-haswarn.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-data-contains-fragment-haswarn.html
new file mode 100644
index 00000000000..aa4204c1141
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-data-contains-fragment-haswarn.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>value warning: scheme-data-contains-fragment</title>
+<input type=url value="data:text/html,test#test">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-data-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-data-single-slash-novalid.html
new file mode 100644
index 00000000000..e1926f48817
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-data-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: scheme-data-single-slash</title>
+<input type=url value="data:/example.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-file-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-file-backslash-novalid.html
new file mode 100644
index 00000000000..cb2823b84ff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-file-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: scheme-file-backslash</title>
+<input type=url value="file:c:\foo\bar.html">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-file-single-slash-c-bar-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-file-single-slash-c-bar-novalid.html
new file mode 100644
index 00000000000..4d3d662baab
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-file-single-slash-c-bar-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: scheme-file-single-slash-c-bar</title>
+<input type=url value="file:/C|/foo/bar">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-file-triple-slash-c-bar-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-file-triple-slash-c-bar-novalid.html
new file mode 100644
index 00000000000..d0bf5325cb6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-file-triple-slash-c-bar-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: scheme-file-triple-slash-c-bar</title>
+<input type=url value="file:///C|/foo/bar">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-ftp-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-ftp-no-slash-novalid.html
new file mode 100644
index 00000000000..5fab853b6e8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-ftp-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: scheme-ftp-no-slash</title>
+<input type=url value="ftp:example.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-ftp-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-ftp-single-slash-novalid.html
new file mode 100644
index 00000000000..fc6fd7d1343
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-ftp-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: scheme-ftp-single-slash</title>
+<input type=url value="ftp:/example.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-http-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-http-backslash-novalid.html
new file mode 100644
index 00000000000..1de549d9392
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-http-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: scheme-http-backslash</title>
+<input type=url value="http:\\foo.com\">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-http-no-slash-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-http-no-slash-colon-novalid.html
new file mode 100644
index 00000000000..9bf960341ea
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-http-no-slash-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: scheme-http-no-slash-colon</title>
+<input type=url value="http::@c:29">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-http-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-http-no-slash-novalid.html
new file mode 100644
index 00000000000..41b939e0212
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-http-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: scheme-http-no-slash</title>
+<input type=url value="http:foo.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-http-no-slash-square-bracket-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-http-no-slash-square-bracket-novalid.html
new file mode 100644
index 00000000000..11004d954ae
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-http-no-slash-square-bracket-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: scheme-http-no-slash-square-bracket</title>
+<input type=url value="http:[61:27]/:foo">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-http-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-http-single-slash-novalid.html
new file mode 100644
index 00000000000..f4fd889239e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-http-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: scheme-http-single-slash</title>
+<input type=url value="http:/example.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-https-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-https-no-slash-novalid.html
new file mode 100644
index 00000000000..b0b6ae6f45b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-https-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: scheme-https-no-slash</title>
+<input type=url value="https:example.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-https-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-https-single-slash-novalid.html
new file mode 100644
index 00000000000..5de56191d77
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-https-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: scheme-https-single-slash</title>
+<input type=url value="https:/example.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-javascript-no-slash-malformed-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-javascript-no-slash-malformed-novalid.html
new file mode 100644
index 00000000000..73c7e6adf4d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-javascript-no-slash-malformed-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: scheme-javascript-no-slash-malformed</title>
+<input type=url value="javascript:example.com/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-schemeless-relative-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-schemeless-relative-novalid.html
new file mode 100644
index 00000000000..f626dfe1054
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-schemeless-relative-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: scheme-schemeless-relative</title>
+<input type=url value="//foo/bar">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-trailing-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-trailing-cr-novalid.html
new file mode 100644
index 00000000000..5731f372f3c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-trailing-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: scheme-trailing-cr</title>
+<input type=url value="a: foo.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-trailing-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-trailing-newline-novalid.html
new file mode 100644
index 00000000000..428471ce6da
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-trailing-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: scheme-trailing-newline</title>
+<input type=url value="a:
+foo.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-trailing-space-novalid.html
new file mode 100644
index 00000000000..ea2ffe302cb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: scheme-trailing-space</title>
+<input type=url value="a: foo.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-trailing-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-trailing-tab-novalid.html
new file mode 100644
index 00000000000..40f77c7e827
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/scheme-trailing-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: scheme-trailing-tab</title>
+<input type=url value="a: foo.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/userinfo-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/userinfo-backslash-novalid.html
new file mode 100644
index 00000000000..2c62de24740
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/userinfo-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: userinfo-backslash</title>
+<input type=url value="http://a\b:c\d@foo.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/userinfo-password-bad-chars-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/userinfo-password-bad-chars-novalid.html
new file mode 100644
index 00000000000..00cbff7e826
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/userinfo-password-bad-chars-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: userinfo-password-bad-chars</title>
+<input type=url value="http://&a:foo(b]c@d:2/">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/userinfo-password-contains-pile-of-poo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/userinfo-password-contains-pile-of-poo-novalid.html
new file mode 100644
index 00000000000..2d43c888835
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/userinfo-password-contains-pile-of-poo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: userinfo-password-contains-pile-of-poo</title>
+<input type=url value="http://foo:💩@example.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/userinfo-username-contains-at-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/userinfo-username-contains-at-sign-novalid.html
new file mode 100644
index 00000000000..4d88541aa73
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/userinfo-username-contains-at-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: userinfo-username-contains-at-sign</title>
+<input type=url value="http://::@c@d:2">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/userinfo-username-contains-pile-of-poo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/userinfo-username-contains-pile-of-poo-novalid.html
new file mode 100644
index 00000000000..a457fe6b486
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/input/type-url-value/userinfo-username-contains-pile-of-poo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid value attribute: userinfo-username-contains-pile-of-poo</title>
+<input type=url value="http://💩:foo@example.com">
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite-empty-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite-empty-isvalid.html
new file mode 100644
index 00000000000..a0b625fb704
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite-empty-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>empty cite is valid</title>
+<ins cite=""></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite-isvalid.html
new file mode 100644
index 00000000000..64c2d189e67
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite-isvalid.html
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid cite</title>
+<ins cite="file:///"></ins><!-- scheme-file-slash-slash-slash-only -->
+<ins cite="http://a:@www.example.com"></ins><!-- userinfo-password-empty -->
+<ins cite="foo://///////"></ins><!-- scheme-private-path-leading-slashes-only -->
+<ins cite="file://abc|/foo/bar"></ins><!-- scheme-file-slash-slash-abc-bar -->
+<ins cite="/a/b/c"></ins><!-- path-simple-relative -->
+<ins cite="http://example.com/你好你好"></ins><!-- path-unicode-han -->
+<ins cite="/a/%2f/c"></ins><!-- path-percent-encoded-slash-plus-slashes-relative -->
+<ins cite="http://f:/c"></ins><!-- port-none-but-colon -->
+<ins cite="http://example.com/foo%41%7a"></ins><!-- path-percent-encoded-multiple -->
+<ins cite="http://192.168.0.257/"></ins><!-- host-IP-address-broken -->
+<ins cite="madeupscheme:example.com/"></ins><!-- scheme-private-no-slash -->
+<ins cite="?"></ins><!-- query-empty-no-path-relative -->
+<ins cite="http://example.com/%20foo"></ins><!-- path-percent-encoded-space -->
+<ins cite="mailto:/example.com/"></ins><!-- scheme-mailto-single-slash -->
+<ins cite="::"></ins><!-- path-leading-colon-colon-relative -->
+<ins cite="http://example.com/%3A%3a%3C%3c"></ins><!-- path-percent-encoded-mixed-case -->
+<ins cite="http://user:pass@foo:21/bar;par?b#c"></ins><!-- userinfo -->
+<ins cite="ws:/example.com/"></ins><!-- scheme-ws-single-slash -->
+<ins cite="foo://"></ins><!-- scheme-private-slash-slash -->
+<ins cite="#"></ins><!-- fragment-empty-hash-only-no-path-relative -->
+<ins cite="http://f:00000000000000/c"></ins><!-- port-00000000000000 -->
+<ins cite="foo:////://///"></ins><!-- scheme-private-path-leading-slashes-colon-slashes -->
+<ins cite=":23"></ins><!-- path-leading-colon-number-relative -->
+<ins cite="foo:/"></ins><!-- scheme-private-slash -->
+<ins cite="http://💩"></ins><!-- host-is-pile-of-poo -->
+<ins cite="file:test"></ins><!-- scheme-file-no-slash -->
+<ins cite="file://C|/foo/bar"></ins><!-- scheme-file-slash-slash-c-bar -->
+<ins cite="#/"></ins><!-- fragment-slash-relative -->
+<ins cite="http://192.0x00A80001"></ins><!-- host-192.0x00A80001 -->
+<ins cite="foo.com"></ins><!-- scheme-none-relative -->
+<ins cite="http💩//:foo"></ins><!-- path-contains-pile-of-poo -->
+<ins cite="File://foo/bar.html"></ins><!-- scheme-file-uppercase -->
+<ins cite=":/"></ins><!-- path-leading-colon-slash-relative -->
+<ins cite="http://www.foo。bar.com"></ins><!-- host-exotic-dot -->
+<ins cite="http://GOO​⁠goo.com"></ins><!-- host-exotic-whitespace -->
+<ins cite="file:///foo/bar.txt"></ins><!-- scheme-file-host-empty -->
+<ins cite="javascript:/example.com/"></ins><!-- scheme-javascript-single-slash -->
+<ins cite="gopher:/example.com/"></ins><!-- scheme-gopher-single-slash -->
+<ins cite="ftps:example.com/"></ins><!-- scheme-ftps-no-slash -->
+<ins cite="file://server/foo/bar"></ins><!-- scheme-file-host-included -->
+<ins cite="http://example.com/foo%00"></ins><!-- path-percent-encoded-u0000 -->
+<ins cite="a:foo.com"></ins><!-- scheme-private -->
+<ins cite=":"></ins><!-- path-colon-relative -->
+<ins cite="http://:b@www.example.com"></ins><!-- userinfo-user-empty -->
+<ins cite="file:/"></ins><!-- scheme-file-slash-only -->
+<ins cite="wss:example.com/"></ins><!-- scheme-wss-no-slash -->
+<ins cite="::23"></ins><!-- path-colon-colon-number-relative -->
+<ins cite="/a%2fc"></ins><!-- path-percent-encoded-slash-relative -->
+<ins cite="http://a:b@c:29/d"></ins><!-- userinfo-host-port-path -->
+<ins cite="gopher:example.com/"></ins><!-- scheme-gopher-no-slash -->
+<ins cite="madeupscheme:/example.com/"></ins><!-- scheme-private-single-slash -->
+<ins cite="mailto:example.com/"></ins><!-- scheme-mailto-no-slash -->
+<ins cite="http://%25DOMAIN:foobar@foodomain.com"></ins><!-- userinfo-username-contains-percent-encoded -->
+<ins cite="/:23"></ins><!-- path-slash-colon-number-relative -->
+<ins cite="foo://///////bar.com/"></ins><!-- scheme-private-path-leading-slashes-chars -->
+<ins cite="http://[2001::1]:80"></ins><!-- host-ipv6-port -->
+<ins cite="data:text/plain,foo"></ins><!-- scheme-data-no-slash -->
+<ins cite="http://example.com/foo/%2e"></ins><!-- path-percent-encoded-dot -->
+<ins cite="file:/example.com/"></ins><!-- scheme-file-single-slash -->
+<ins cite="http://example.com/©zbar"></ins><!-- path-non-ascii -->
+<ins cite="http://example.com//foo"></ins><!-- path-uFEFF -->
+<ins cite="wss:/example.com/"></ins><!-- scheme-wss-single-slash -->
+<ins cite="http://foo/abcd#foo?bar"></ins><!-- fragment-contains-question-mark -->
+<ins cite=":#"></ins><!-- path-leading-colon-hash-relative -->
+<ins cite="http://example.com/foo%91"></ins><!-- path-percent-encoded-u0091 -->
+<ins cite="c:/foo"></ins><!-- scheme-private-single-letter -->
+<ins cite=":foo.com"></ins><!-- path-leading-colon-chars-relative -->
+<ins cite="http://你好你好"></ins><!-- host-idn-unicode-han -->
+<ins cite="http://example.com/foo#💩"></ins><!-- fragment-contains-pile-of-poo -->
+<ins cite="file:"></ins><!-- scheme-file-scheme-only -->
+<ins cite="#β"></ins><!-- fragment-non-ascii-relative -->
+<ins cite="foo:/bar.com/"></ins><!-- scheme-private-path -->
+<ins cite="http://f:0/c"></ins><!-- port-0 -->
+<ins cite="#;?"></ins><!-- fragment-semicolon-question-mark-relative -->
+<ins cite="http://Go.com"></ins><!-- host-fullwidth -->
+<ins cite="http://@www.example.com"></ins><!-- userinfo-empty -->
+<ins cite="http://example.com/‮/foo/‭/bar"></ins><!-- path-u202E-u202D -->
+<ins cite="http://[2001::1]"></ins><!-- host-ipv6 -->
+<ins cite="💩http://foo"></ins><!-- path-starts-with-pile-of-poo -->
+<ins cite="http://foo/abcd?efgh?ijkl"></ins><!-- query-contains-question-mark -->
+<ins cite="//foo/bar"></ins><!-- scheme-schemeless-relative -->
+<ins cite="ftps:/example.com/"></ins><!-- scheme-ftps-single-slash -->
+<ins cite="http://foo.com:b@d/"></ins><!-- userinfo-username-non-alpha -->
+<ins cite=":a"></ins><!-- path-leading-colon-letter-relative -->
+<ins cite="/"></ins><!-- path-slash-only-relative -->
+<ins cite="http://example.com/foo?💩"></ins><!-- query-contains-pile-of-poo -->
+<ins cite="http://f:00000000000000000000080/c"></ins><!-- port-00000000000000000000080 -->
+<ins cite="file://"></ins><!-- scheme-file-slash-slash-only -->
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/fragment-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/fragment-backslash-novalid.html
new file mode 100644
index 00000000000..a2519ec53e2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/fragment-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: fragment-backslash</title>
+<ins cite="#\"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/fragment-contains-hash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/fragment-contains-hash-novalid.html
new file mode 100644
index 00000000000..0f8149f38ce
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/fragment-contains-hash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: fragment-contains-hash</title>
+<ins cite="http://foo/path#f#g"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/fragment-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/fragment-leading-space-novalid.html
new file mode 100644
index 00000000000..9ff6f2e967c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/fragment-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: fragment-leading-space</title>
+<ins cite="http://f:21/b# e"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-cr-novalid.html
new file mode 100644
index 00000000000..c436dad3784
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-cr</title>
+<ins cite="http://example. org"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-double-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-double-percent-encoded-novalid.html
new file mode 100644
index 00000000000..abf421a13e0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-double-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-double-percent-encoded</title>
+<ins cite="http://%41.com"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-double-percent-encoded-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-double-percent-encoded-percent-encoded-novalid.html
new file mode 100644
index 00000000000..5a39b32a91b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-double-percent-encoded-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-double-percent-encoded-percent-encoded</title>
+<ins cite="http://%ef%bc%85%ef%bc%94%ef%bc%91.com"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-empty-novalid.html
new file mode 100644
index 00000000000..b2d37f30d33
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-empty</title>
+<ins cite="http://"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-empty-userinfo-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-empty-userinfo-empty-novalid.html
new file mode 100644
index 00000000000..b8d2608a713
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-empty-userinfo-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-empty-userinfo-empty</title>
+<ins cite="http://@/www.example.com"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-empty-with-userinfo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-empty-with-userinfo-novalid.html
new file mode 100644
index 00000000000..89f04ce7992
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-empty-with-userinfo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-empty-with-userinfo</title>
+<ins cite="http://user:pass@/"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-hostname-in-brackets-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-hostname-in-brackets-novalid.html
new file mode 100644
index 00000000000..c56f1960846
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-hostname-in-brackets-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-hostname-in-brackets</title>
+<ins cite="http://[www.google.com]/"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-invalid-unicode-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-invalid-unicode-novalid.html
new file mode 100644
index 00000000000..47ca570a942
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-invalid-unicode-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-invalid-unicode</title>
+<ins cite="http://﷐zyx.com"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-invalid-unicode-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-invalid-unicode-percent-encoded-novalid.html
new file mode 100644
index 00000000000..0f81221428d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-invalid-unicode-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-invalid-unicode-percent-encoded</title>
+<ins cite="http://%ef%b7%90zyx.com"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-newline-novalid.html
new file mode 100644
index 00000000000..67506630824
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-newline</title>
+<ins cite="http://example.
+org"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-space-novalid.html
new file mode 100644
index 00000000000..69425323fe4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-space</title>
+<ins cite="http://example .org"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-square-brackets-port-contains-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-square-brackets-port-contains-colon-novalid.html
new file mode 100644
index 00000000000..44ab3ecb19f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-square-brackets-port-contains-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-square-brackets-port-contains-colon</title>
+<ins cite="http://[1::2]:3:4"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-tab-novalid.html
new file mode 100644
index 00000000000..ddbe575b882
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-tab</title>
+<ins cite="http://example .org"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-u0000-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-u0000-percent-encoded-novalid.html
new file mode 100644
index 00000000000..065ca6062d6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-u0000-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-u0000-percent-encoded</title>
+<ins cite="http://%00.com"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-u0000-percent-encoded-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-u0000-percent-encoded-percent-encoded-novalid.html
new file mode 100644
index 00000000000..fc999b5fee9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/host-u0000-percent-encoded-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-u0000-percent-encoded-percent-encoded</title>
+<ins cite="http://%ef%bc%85%ef%bc%90%ef%bc%90.com"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/path-bare-percent-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/path-bare-percent-sign-novalid.html
new file mode 100644
index 00000000000..637bc283e03
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/path-bare-percent-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: path-bare-percent-sign</title>
+<ins cite="http://example.com/foo%"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/path-contains-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/path-contains-space-novalid.html
new file mode 100644
index 00000000000..c9b63ed9194
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/path-contains-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: path-contains-space</title>
+<ins cite="/a/ /c"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/path-leading-backslash-at-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/path-leading-backslash-at-sign-novalid.html
new file mode 100644
index 00000000000..0773005c3c4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/path-leading-backslash-at-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: path-leading-backslash-at-sign</title>
+<ins cite="http://foo.com/\@"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/path-leading-colon-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/path-leading-colon-backslash-novalid.html
new file mode 100644
index 00000000000..da1af59e415
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/path-leading-colon-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: path-leading-colon-backslash</title>
+<ins cite=":\"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/path-leading-colon-chars-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/path-leading-colon-chars-backslash-novalid.html
new file mode 100644
index 00000000000..95366e5cc15
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/path-leading-colon-chars-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: path-leading-colon-chars-backslash</title>
+<ins cite=":foo.com\"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/path-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/path-leading-space-novalid.html
new file mode 100644
index 00000000000..44769d75775
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/path-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: path-leading-space</title>
+<ins cite="http://f:21/ b"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/path-percent-encoded-malformed-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/path-percent-encoded-malformed-novalid.html
new file mode 100644
index 00000000000..85177801eb4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/path-percent-encoded-malformed-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: path-percent-encoded-malformed</title>
+<ins cite="http://example.com/foo/%2e%2"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/path-relative-square-brackets-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/path-relative-square-brackets-novalid.html
new file mode 100644
index 00000000000..8ccb9cd775f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/path-relative-square-brackets-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: path-relative-square-brackets</title>
+<ins cite="[61:24:74]:98"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/path-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/path-tab-novalid.html
new file mode 100644
index 00000000000..2cdc5c8f97f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/path-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: path-tab</title>
+<ins cite="http://example.com/foo bar"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/path-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/path-trailing-space-novalid.html
new file mode 100644
index 00000000000..302dac4f61b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/path-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: path-trailing-space</title>
+<ins cite="http://f:21/b ?"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/path-u0091-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/path-u0091-novalid.html
new file mode 100644
index 00000000000..1d954112196
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/path-u0091-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: path-u0091</title>
+<ins cite="http://example.com/foo‘"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/port-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/port-cr-novalid.html
new file mode 100644
index 00000000000..194ab6c0230
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/port-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: port-cr</title>
+<ins cite="http://f: /c"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/port-leading-colon-bracket-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/port-leading-colon-bracket-colon-novalid.html
new file mode 100644
index 00000000000..137e699dfa3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/port-leading-colon-bracket-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: port-leading-colon-bracket-colon</title>
+<ins cite="http://2001::1]:80"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/port-leading-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/port-leading-colon-novalid.html
new file mode 100644
index 00000000000..3ef71420fdc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/port-leading-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: port-leading-colon</title>
+<ins cite="http://2001::1"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/port-leading-dash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/port-leading-dash-novalid.html
new file mode 100644
index 00000000000..b759b88c8e7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/port-leading-dash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: port-leading-dash</title>
+<ins cite="http://foo:-80/"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/port-multiple-letters-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/port-multiple-letters-novalid.html
new file mode 100644
index 00000000000..d5cc8a21f0d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/port-multiple-letters-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: port-multiple-letters</title>
+<ins cite="http://f:fifty-two/c"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/port-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/port-newline-novalid.html
new file mode 100644
index 00000000000..d2b7614f415
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/port-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: port-newline</title>
+<ins cite="http://f:
+/c"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/port-single-letter-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/port-single-letter-novalid.html
new file mode 100644
index 00000000000..9ddd1c56e4a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/port-single-letter-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: port-single-letter</title>
+<ins cite="http://f:b/c"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/port-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/port-space-novalid.html
new file mode 100644
index 00000000000..f6ac1c3553d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/port-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: port-space</title>
+<ins cite="http://f: /c"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/port-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/port-tab-novalid.html
new file mode 100644
index 00000000000..59524a40c9a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/port-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: port-tab</title>
+<ins cite="http://f: /c"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/query-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/query-leading-space-novalid.html
new file mode 100644
index 00000000000..5cc177a4fd1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/query-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: query-leading-space</title>
+<ins cite="http://f:21/b? d"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/query-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/query-trailing-space-novalid.html
new file mode 100644
index 00000000000..e05a4ce0302
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/query-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: query-trailing-space</title>
+<ins cite="http://f:21/b?d #"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-data-contains-fragment-haswarn.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-data-contains-fragment-haswarn.html
new file mode 100644
index 00000000000..433c5ee63ed
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-data-contains-fragment-haswarn.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>data:text/html,test#test warning: scheme-data-contains-fragment</title>
+<ins cite="data:text/html,test#test"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-data-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-data-single-slash-novalid.html
new file mode 100644
index 00000000000..95a8f8c49e1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-data-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-data-single-slash</title>
+<ins cite="data:/example.com/"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-file-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-file-backslash-novalid.html
new file mode 100644
index 00000000000..ff869b614ee
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-file-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-file-backslash</title>
+<ins cite="file:c:\foo\bar.html"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-file-single-slash-c-bar-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-file-single-slash-c-bar-novalid.html
new file mode 100644
index 00000000000..83e02034377
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-file-single-slash-c-bar-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-file-single-slash-c-bar</title>
+<ins cite="file:/C|/foo/bar"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-file-triple-slash-c-bar-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-file-triple-slash-c-bar-novalid.html
new file mode 100644
index 00000000000..a003799e4e1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-file-triple-slash-c-bar-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-file-triple-slash-c-bar</title>
+<ins cite="file:///C|/foo/bar"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-ftp-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-ftp-no-slash-novalid.html
new file mode 100644
index 00000000000..5d9a2919828
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-ftp-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-ftp-no-slash</title>
+<ins cite="ftp:example.com/"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-ftp-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-ftp-single-slash-novalid.html
new file mode 100644
index 00000000000..56ca71cc392
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-ftp-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-ftp-single-slash</title>
+<ins cite="ftp:/example.com/"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-http-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-http-backslash-novalid.html
new file mode 100644
index 00000000000..f40b32fae4e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-http-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-http-backslash</title>
+<ins cite="http:\\foo.com\"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-http-no-slash-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-http-no-slash-colon-novalid.html
new file mode 100644
index 00000000000..ece7ecb2a05
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-http-no-slash-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-http-no-slash-colon</title>
+<ins cite="http::@c:29"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-http-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-http-no-slash-novalid.html
new file mode 100644
index 00000000000..a604c209e22
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-http-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-http-no-slash</title>
+<ins cite="http:foo.com"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-http-no-slash-square-bracket-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-http-no-slash-square-bracket-novalid.html
new file mode 100644
index 00000000000..bf9d732f426
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-http-no-slash-square-bracket-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-http-no-slash-square-bracket</title>
+<ins cite="http:[61:27]/:foo"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-http-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-http-single-slash-novalid.html
new file mode 100644
index 00000000000..efd92124918
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-http-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-http-single-slash</title>
+<ins cite="http:/example.com/"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-https-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-https-no-slash-novalid.html
new file mode 100644
index 00000000000..36331cf9798
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-https-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-https-no-slash</title>
+<ins cite="https:example.com/"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-https-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-https-single-slash-novalid.html
new file mode 100644
index 00000000000..75d3fb24463
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-https-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-https-single-slash</title>
+<ins cite="https:/example.com/"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-javascript-no-slash-malformed-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-javascript-no-slash-malformed-novalid.html
new file mode 100644
index 00000000000..267f1131ace
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-javascript-no-slash-malformed-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-javascript-no-slash-malformed</title>
+<ins cite="javascript:example.com/"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-trailing-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-trailing-cr-novalid.html
new file mode 100644
index 00000000000..c603ca23e31
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-trailing-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-trailing-cr</title>
+<ins cite="a: foo.com"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-trailing-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-trailing-newline-novalid.html
new file mode 100644
index 00000000000..8762f24b316
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-trailing-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-trailing-newline</title>
+<ins cite="a:
+foo.com"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-trailing-space-novalid.html
new file mode 100644
index 00000000000..8b4b310a1dd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-trailing-space</title>
+<ins cite="a: foo.com"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-trailing-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-trailing-tab-novalid.html
new file mode 100644
index 00000000000..9cc2491ae30
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/scheme-trailing-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-trailing-tab</title>
+<ins cite="a: foo.com"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/userinfo-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/userinfo-backslash-novalid.html
new file mode 100644
index 00000000000..48e87bdebd3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/userinfo-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: userinfo-backslash</title>
+<ins cite="http://a\b:c\d@foo.com"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/userinfo-password-bad-chars-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/userinfo-password-bad-chars-novalid.html
new file mode 100644
index 00000000000..0cc97767684
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/userinfo-password-bad-chars-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: userinfo-password-bad-chars</title>
+<ins cite="http://&a:foo(b]c@d:2/"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/userinfo-password-contains-pile-of-poo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/userinfo-password-contains-pile-of-poo-novalid.html
new file mode 100644
index 00000000000..c225c2c7c70
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/userinfo-password-contains-pile-of-poo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: userinfo-password-contains-pile-of-poo</title>
+<ins cite="http://foo:💩@example.com"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/userinfo-username-contains-at-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/userinfo-username-contains-at-sign-novalid.html
new file mode 100644
index 00000000000..6c7c667b0c9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/userinfo-username-contains-at-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: userinfo-username-contains-at-sign</title>
+<ins cite="http://::@c@d:2"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/userinfo-username-contains-pile-of-poo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/userinfo-username-contains-pile-of-poo-novalid.html
new file mode 100644
index 00000000000..de82cee96f8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/cite/userinfo-username-contains-pile-of-poo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: userinfo-username-contains-pile-of-poo</title>
+<ins cite="http://💩:foo@example.com"></ins>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-0004-02-29-haswarn.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-0004-02-29-haswarn.html
new file mode 100644
index 00000000000..5fad16aa3c6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-0004-02-29-haswarn.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-0004-02-29</title>
+<ins datetime="0004-02-29"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-0005-02-29-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-0005-02-29-novalid.html
new file mode 100644
index 00000000000..1d8de9bd88f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-0005-02-29-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-0005-02-29</title>
+<ins datetime="0005-02-29"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-0214-09-29-haswarn.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-0214-09-29-haswarn.html
new file mode 100644
index 00000000000..8938898505c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-0214-09-29-haswarn.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-0214-09-29</title>
+<ins datetime="0214-09-29"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-1900-02-29-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-1900-02-29-novalid.html
new file mode 100644
index 00000000000..04a87af388e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-1900-02-29-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-1900-02-29</title>
+<ins datetime="1900-02-29"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-1969-02-29-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-1969-02-29-novalid.html
new file mode 100644
index 00000000000..2ef44002046
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-1969-02-29-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-1969-02-29</title>
+<ins datetime="1969-02-29"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-20014-09-29-haswarn.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-20014-09-29-haswarn.html
new file mode 100644
index 00000000000..006804686b4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-20014-09-29-haswarn.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-20014-09-29</title>
+<ins datetime="20014-09-29"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-2014-02-29-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-2014-02-29-novalid.html
new file mode 100644
index 00000000000..244edadd6ee
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-2014-02-29-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-2014-02-29</title>
+<ins datetime="2014-02-29"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-2100-02-29-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-2100-02-29-novalid.html
new file mode 100644
index 00000000000..405a710cc19
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-2100-02-29-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-2100-02-29</title>
+<ins datetime="2100-02-29"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-2200-02-29-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-2200-02-29-novalid.html
new file mode 100644
index 00000000000..6144a86b17f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-2200-02-29-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-2200-02-29</title>
+<ins datetime="2200-02-29"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-day-01-32-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-day-01-32-novalid.html
new file mode 100644
index 00000000000..84a368ae1f8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-day-01-32-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-day-01-32</title>
+<ins datetime="2002-01-32"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-day-03-32-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-day-03-32-novalid.html
new file mode 100644
index 00000000000..4bfa96f2f50
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-day-03-32-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-day-03-32</title>
+<ins datetime="2002-03-32"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-day-04-31-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-day-04-31-novalid.html
new file mode 100644
index 00000000000..3e720617ab1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-day-04-31-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-day-04-31</title>
+<ins datetime="2002-04-31"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-day-05-32-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-day-05-32-novalid.html
new file mode 100644
index 00000000000..8e3129a1c0f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-day-05-32-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-day-05-32</title>
+<ins datetime="2002-05-32"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-day-06-31-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-day-06-31-novalid.html
new file mode 100644
index 00000000000..4ab9d3ab9ac
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-day-06-31-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-day-06-31</title>
+<ins datetime="2002-06-31"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-day-07-32-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-day-07-32-novalid.html
new file mode 100644
index 00000000000..e719a2d3cdb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-day-07-32-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-day-07-32</title>
+<ins datetime="2002-07-32"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-day-08-32-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-day-08-32-novalid.html
new file mode 100644
index 00000000000..b64612d67db
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-day-08-32-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-day-08-32</title>
+<ins datetime="2002-08-32"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-day-09-31-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-day-09-31-novalid.html
new file mode 100644
index 00000000000..1274aabe80a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-day-09-31-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-day-09-31</title>
+<ins datetime="2002-09-31"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-day-10-32-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-day-10-32-novalid.html
new file mode 100644
index 00000000000..2b064605b4b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-day-10-32-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-day-10-32</title>
+<ins datetime="2002-10-32"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-day-11-31-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-day-11-31-novalid.html
new file mode 100644
index 00000000000..ed8dad3e0b6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-day-11-31-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-day-11-31</title>
+<ins datetime="2002-11-31"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-day-12-32-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-day-12-32-novalid.html
new file mode 100644
index 00000000000..c31e099f783
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-day-12-32-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-day-12-32</title>
+<ins datetime="2002-12-32"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-day-missing-separator-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-day-missing-separator-novalid.html
new file mode 100644
index 00000000000..11e95e25a06
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-day-missing-separator-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-day-missing-separator</title>
+<ins datetime="2014-0220"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-day-one-digit-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-day-one-digit-novalid.html
new file mode 100644
index 00000000000..8d51c0df6f0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-day-one-digit-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-day-one-digit</title>
+<ins datetime="2002-09-9"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-day-three-digits-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-day-three-digits-novalid.html
new file mode 100644
index 00000000000..7f97a5b5f75
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-day-three-digits-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-day-three-digits</title>
+<ins datetime="2002-11-009"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-iso8601-YYYYMMDD-no-hyphen-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-iso8601-YYYYMMDD-no-hyphen-novalid.html
new file mode 100644
index 00000000000..a412c46351b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-iso8601-YYYYMMDD-no-hyphen-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-iso8601-YYYYMMDD-no-hyphen</title>
+<ins datetime="20020929"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-leading-bom-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-leading-bom-novalid.html
new file mode 100644
index 00000000000..1b541fbb2f2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-leading-bom-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-leading-bom</title>
+<ins datetime="2002-09-29"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-leading-whitespace-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-leading-whitespace-novalid.html
new file mode 100644
index 00000000000..faa7e7f52ed
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-leading-whitespace-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-leading-whitespace</title>
+<ins datetime=" 2002-09-29"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-month-00-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-month-00-novalid.html
new file mode 100644
index 00000000000..3aa1dcebf40
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-month-00-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-month-00</title>
+<ins datetime="2002-00-15"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-month-13-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-month-13-novalid.html
new file mode 100644
index 00000000000..501528d85db
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-month-13-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-month-13</title>
+<ins datetime="2002-13-15"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-month-missing-separator-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-month-missing-separator-novalid.html
new file mode 100644
index 00000000000..a0f7473b690
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-month-missing-separator-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-month-missing-separator</title>
+<ins datetime="201402-20"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-month-one-digit-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-month-one-digit-novalid.html
new file mode 100644
index 00000000000..b26933c02dc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-month-one-digit-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-month-one-digit</title>
+<ins datetime="2002-9-29"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-month-three-digits-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-month-three-digits-novalid.html
new file mode 100644
index 00000000000..b61171df92c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-month-three-digits-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-month-three-digits</title>
+<ins datetime="2002-011-29"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-non-ascii-digit-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-non-ascii-digit-novalid.html
new file mode 100644
index 00000000000..14c37880ed9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-non-ascii-digit-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-non-ascii-digit</title>
+<ins datetime="2002-09-29"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-trailing-U+0000-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-trailing-U+0000-novalid.html
new file mode 100644
index 00000000000..fb849779e27
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-trailing-U+0000-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-trailing-U+0000</title>
+<ins datetime="2002-09-29&#x0000;"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-trailing-pile-of-poo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-trailing-pile-of-poo-novalid.html
new file mode 100644
index 00000000000..3349cc80a7b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-trailing-pile-of-poo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-trailing-pile-of-poo</title>
+<ins datetime="2002-09-29💩"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-trailing-whitespace-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-trailing-whitespace-novalid.html
new file mode 100644
index 00000000000..39bbeef70c1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-trailing-whitespace-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-trailing-whitespace</title>
+<ins datetime="2002-09-29 "></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-wrong-day-separator-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-wrong-day-separator-novalid.html
new file mode 100644
index 00000000000..530a05e41f2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-wrong-day-separator-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-wrong-day-separator</title>
+<ins datetime="2014-02:20"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-wrong-month-separator-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-wrong-month-separator-novalid.html
new file mode 100644
index 00000000000..9ed0be6f8e3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-wrong-month-separator-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-wrong-month-separator</title>
+<ins datetime="2014:02-20"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-year-0000-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-year-0000-novalid.html
new file mode 100644
index 00000000000..4f5e524a9cd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-year-0000-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-year-0000</title>
+<ins datetime="0000-12-09"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-year-five-digits-haswarn.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-year-five-digits-haswarn.html
new file mode 100644
index 00000000000..6de3a432613
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-year-five-digits-haswarn.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-year-five-digits</title>
+<ins datetime="12014-09-29"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-year-negative-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-year-negative-novalid.html
new file mode 100644
index 00000000000..767b9f47610
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-year-negative-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-year-negative</title>
+<ins datetime="-2002-09-29"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-year-three-digits-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-year-three-digits-novalid.html
new file mode 100644
index 00000000000..805b6a214be
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/date-year-three-digits-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>date-year-three-digits</title>
+<ins datetime="782-09-29"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/datetime-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/datetime-isvalid.html
new file mode 100644
index 00000000000..e9f6daf621f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/datetime-isvalid.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid datetime</title>
+<ins datetime="2011-11-12T06:54:39-08:00"></ins> <!-- global-date-and-time-timezone-with-colon -->
+<ins datetime="2002-12-31"></ins> <!-- date-day-12-31 -->
+<ins datetime="2002-08-31"></ins> <!-- date-day-08-31 -->
+<ins datetime="1900-02-28"></ins> <!-- date-1900-02-28 -->
+<ins datetime="2011-11-12T14:54:39+0000"></ins> <!-- global-date-and-time-with-seconds -->
+<ins datetime="2002-10-31"></ins> <!-- date-day-10-31 -->
+<ins datetime="2002-01-31"></ins> <!-- date-day-01-31 -->
+<ins datetime="2200-02-28"></ins> <!-- date-2200-02-28 -->
+<ins datetime="2002-09-29"></ins> <!-- date -->
+<ins datetime="2002-06-30"></ins> <!-- date-day-06-30 -->
+<ins datetime="2100-02-28"></ins> <!-- date-2100-02-28 -->
+<ins datetime="2011-11-12T06:54:39-0845"></ins> <!-- global-date-and-time-timezone-45 -->
+<ins datetime="2002-03-31"></ins> <!-- date-day-03-31 -->
+<ins datetime="2011-11-12T06:54:39+0900"></ins> <!-- global-date-and-time-timezone -->
+<ins datetime="2002-04-30"></ins> <!-- date-day-04-30 -->
+<ins datetime="2002-09-30"></ins> <!-- date-day-09-30 -->
+<ins datetime="2002-05-31"></ins> <!-- date-day-05-31 -->
+<ins datetime="2011-11-12T14:54Z"></ins> <!-- global-date-and-time-no-seconds -->
+<ins datetime="2011-11-12T06:54:39.92+07:00"></ins> <!-- global-date-and-time-with-two-digit-fraction -->
+<ins datetime="2400-02-29"></ins> <!-- date-2400-02-29 -->
+<ins datetime="2002-07-31"></ins> <!-- date-day-07-31 -->
+<ins datetime="2011-11-12T06:54:39.929-06:00"></ins> <!-- global-date-and-time-with-three-digit-fraction -->
+<ins datetime="2011-11-12T06:54:39-0830"></ins> <!-- global-date-and-time-timezone-30 -->
+<ins datetime="2014-02-28"></ins> <!-- date-2014-02-28 -->
+<ins datetime="2002-11-30"></ins> <!-- date-day-11-30 -->
+<ins datetime="2000-02-29"></ins> <!-- date-2000-02-29 -->
+<ins datetime="2011-11-12 14:54Z"></ins> <!-- global-date-and-time-space -->
+<ins datetime="2011-11-12T06:54:39.9-08:00"></ins> <!-- global-date-and-time-with-one-digit-fraction -->
+<ins datetime="1968-02-29"></ins> <!-- date-1968-02-29 -->
+<ins datetime="2011-11-12T06:54:39-0800"></ins> <!-- global-date-and-time-timezone-without-colon -->
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/duration-P-form-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/duration-P-form-novalid.html
new file mode 100644
index 00000000000..addb39e6c60
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/duration-P-form-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>duration-P-form</title>
+<ins datetime="PT4H18M3S"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/duration-time-component-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/duration-time-component-novalid.html
new file mode 100644
index 00000000000..6151e9ee740
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/duration-time-component-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>duration-time-component</title>
+<ins datetime="4h 18m 3s"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-2400-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-2400-novalid.html
new file mode 100644
index 00000000000..2d77c4c5d6e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-2400-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-2400</title>
+<ins datetime="2011-11-12T24:00:00+08:00"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-60-minutes-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-60-minutes-novalid.html
new file mode 100644
index 00000000000..59895e85fb6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-60-minutes-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-60-minutes</title>
+<ins datetime="2011-11-12T00:60:00+08:00"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-60-seconds-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-60-seconds-novalid.html
new file mode 100644
index 00000000000..f20905342f8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-60-seconds-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-60-seconds</title>
+<ins datetime="2011-11-12T00:00:60+08:00"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-bad-fraction-separator-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-bad-fraction-separator-novalid.html
new file mode 100644
index 00000000000..68d44b2ded8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-bad-fraction-separator-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-bad-fraction-separator</title>
+<ins datetime="2011-11-12T14:54:39,929+0000"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-four-digit-fraction-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-four-digit-fraction-novalid.html
new file mode 100644
index 00000000000..7d130bffb13
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-four-digit-fraction-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-four-digit-fraction</title>
+<ins datetime="2011-11-12T06:54:39.9291-08:00"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-hour-one-digit-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-hour-one-digit-novalid.html
new file mode 100644
index 00000000000..10f4c7d40af
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-hour-one-digit-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-hour-one-digit</title>
+<ins datetime="2011-11-12T6:54:39-08:00"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-hour-three-digits-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-hour-three-digits-novalid.html
new file mode 100644
index 00000000000..edea421e5da
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-hour-three-digits-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-hour-three-digits</title>
+<ins datetime="2011-11-12T016:54:39-08:00"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-iso8601-hh-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-iso8601-hh-novalid.html
new file mode 100644
index 00000000000..9f9b0536b8a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-iso8601-hh-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-iso8601-hh</title>
+<ins datetime="2011-11-12T14Z"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-iso8601-hhmm-no-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-iso8601-hhmm-no-colon-novalid.html
new file mode 100644
index 00000000000..67a041220e4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-iso8601-hhmm-no-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-iso8601-hhmm-no-colon</title>
+<ins datetime="2011-11-12T1454Z"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-iso8601-hhmmss-no-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-iso8601-hhmmss-no-colon-novalid.html
new file mode 100644
index 00000000000..5b868661bb4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-iso8601-hhmmss-no-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-iso8601-hhmmss-no-colon</title>
+<ins datetime="2011-11-12T145439Z"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-lowercase-z-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-lowercase-z-novalid.html
new file mode 100644
index 00000000000..b4fd1d917d4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-lowercase-z-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-lowercase-z</title>
+<ins datetime="2011-11-12T14:54z"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-minutes-one-digit-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-minutes-one-digit-novalid.html
new file mode 100644
index 00000000000..7d878234511
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-minutes-one-digit-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-minutes-one-digit</title>
+<ins datetime="2011-11-12T16:4:39-08:00"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-minutes-three-digits-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-minutes-three-digits-novalid.html
new file mode 100644
index 00000000000..bdeeba4971c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-minutes-three-digits-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-minutes-three-digits</title>
+<ins datetime="2011-11-12T16:354:39-08:00"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-missing-minutes-separator-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-missing-minutes-separator-novalid.html
new file mode 100644
index 00000000000..174db0e6f10
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-missing-minutes-separator-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-missing-minutes-separator</title>
+<ins datetime="2011-11-12T1454Z"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-missing-seconds-separator-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-missing-seconds-separator-novalid.html
new file mode 100644
index 00000000000..745f243dba9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-missing-seconds-separator-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-missing-seconds-separator</title>
+<ins datetime="2011-11-12T14:5439Z"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-nbsp-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-nbsp-novalid.html
new file mode 100644
index 00000000000..292dc36e231
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-nbsp-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-nbsp</title>
+<ins datetime="2011-11-12 14:54Z"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-seconds-one-digit-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-seconds-one-digit-novalid.html
new file mode 100644
index 00000000000..bd9bddd02ce
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-seconds-one-digit-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-seconds-one-digit</title>
+<ins datetime="2011-11-12T16:54:9-08:00"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-seconds-three-digits-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-seconds-three-digits-novalid.html
new file mode 100644
index 00000000000..12968b15dd3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-seconds-three-digits-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-seconds-three-digits</title>
+<ins datetime="2011-11-12T16:54:039-08:00"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-space-before-timezone-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-space-before-timezone-novalid.html
new file mode 100644
index 00000000000..d97bfc4e325
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-space-before-timezone-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-space-before-timezone</title>
+<ins datetime="2011-11-12T06:54:39 08:00"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-60-minutes-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-60-minutes-novalid.html
new file mode 100644
index 00000000000..4dbd785bf82
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-60-minutes-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-timezone-60-minutes</title>
+<ins datetime="2011-11-12T06:54:39-08:60"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-iso8601-two-digit-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-iso8601-two-digit-novalid.html
new file mode 100644
index 00000000000..c60facf9d7f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-iso8601-two-digit-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-timezone-iso8601-two-digit</title>
+<ins datetime="2011-11-12T06:54:39-08"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-lowercase-t-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-lowercase-t-novalid.html
new file mode 100644
index 00000000000..056c876ae86
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-lowercase-t-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-timezone-lowercase-t</title>
+<ins datetime="2011-11-12t14:54Z"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-minus-1300-haswarn.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-minus-1300-haswarn.html
new file mode 100644
index 00000000000..314e0ce2cbd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-minus-1300-haswarn.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-timezone-minus-1300</title>
+<ins datetime="2011-11-12T00:00:00-1300"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-minus-2400-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-minus-2400-novalid.html
new file mode 100644
index 00000000000..63b239712a4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-minus-2400-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-timezone-minus-2400</title>
+<ins datetime="2011-11-12T06:54:39-24:00"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-minutes-15-haswarn.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-minutes-15-haswarn.html
new file mode 100644
index 00000000000..c65cc9038cd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-minutes-15-haswarn.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-timezone-minutes-15</title>
+<ins datetime="2011-11-12T00:00:00+08:15"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-multiple-spaces-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-multiple-spaces-novalid.html
new file mode 100644
index 00000000000..20659abc922
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-multiple-spaces-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-timezone-multiple-spaces</title>
+<ins datetime="2011-11-12 14:54Z"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-non-T-character-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-non-T-character-novalid.html
new file mode 100644
index 00000000000..17b7024764c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-non-T-character-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-timezone-non-T-character</title>
+<ins datetime="2011-11-12+14:54Z"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-offset-colon-start-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-offset-colon-start-novalid.html
new file mode 100644
index 00000000000..6b81d78831f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-offset-colon-start-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-timezone-offset-colon-start</title>
+<ins datetime="2011-11-12T06:54:39.929:08:00"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-offset-space-start-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-offset-space-start-novalid.html
new file mode 100644
index 00000000000..6d5ae820195
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-offset-space-start-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-timezone-offset-space-start</title>
+<ins datetime="2011-11-12T06:54:39.929 08:00"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-one-digit-hour-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-one-digit-hour-novalid.html
new file mode 100644
index 00000000000..292fd1340fd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-one-digit-hour-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-timezone-one-digit-hour</title>
+<ins datetime="2011-11-12T06:54:39-5:00"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-one-digit-minute-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-one-digit-minute-novalid.html
new file mode 100644
index 00000000000..a1afb91704f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-one-digit-minute-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-timezone-one-digit-minute</title>
+<ins datetime="2011-11-12T06:54:39-05:0"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-plus-1500-haswarn.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-plus-1500-haswarn.html
new file mode 100644
index 00000000000..91b6e23b8ac
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-plus-1500-haswarn.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-timezone-plus-1500</title>
+<ins datetime="2011-11-12T00:00:00+1500"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-plus-2400-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-plus-2400-novalid.html
new file mode 100644
index 00000000000..6044623bc22
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-plus-2400-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-timezone-plus-2400</title>
+<ins datetime="2011-11-12T06:54:39-24:00"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-three-digit-hour-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-three-digit-hour-novalid.html
new file mode 100644
index 00000000000..ba7b84b32eb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-three-digit-hour-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-timezone-three-digit-hour</title>
+<ins datetime="2011-11-12T06:54:39-005:00"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-three-digit-minute-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-three-digit-minute-novalid.html
new file mode 100644
index 00000000000..8b1fb6d368a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-three-digit-minute-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-timezone-three-digit-minute</title>
+<ins datetime="2011-11-12T06:54:39-05:000"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-with-seconds-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-with-seconds-novalid.html
new file mode 100644
index 00000000000..6d51004edce
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-timezone-with-seconds-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-timezone-with-seconds</title>
+<ins datetime="2011-11-12T06:54:39-08:00:00"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-with-both-T-and-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-with-both-T-and-space-novalid.html
new file mode 100644
index 00000000000..6c67d7cf2dd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-with-both-T-and-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-with-both-T-and-space</title>
+<ins datetime="2011-11-12T 14:54Z"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-wrong-minutes-separator-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-wrong-minutes-separator-novalid.html
new file mode 100644
index 00000000000..a19752c6f5d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-wrong-minutes-separator-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-wrong-minutes-separator</title>
+<ins datetime="2011-11-12T14-54Z"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-wrong-seconds-separator-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-wrong-seconds-separator-novalid.html
new file mode 100644
index 00000000000..03f7b3579a5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-wrong-seconds-separator-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-wrong-seconds-separator</title>
+<ins datetime="2011-11-12T14:54-39Z"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-zero-digit-fraction-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-zero-digit-fraction-novalid.html
new file mode 100644
index 00000000000..1e388dd994e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/global-date-and-time-zero-digit-fraction-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>global-date-and-time-zero-digit-fraction</title>
+<ins datetime="2011-11-12T06:54:39.-08:00"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/local-date-and-time-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/local-date-and-time-novalid.html
new file mode 100644
index 00000000000..32136f3e541
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/local-date-and-time-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>local-date-and-time</title>
+<ins datetime="2011-11-12T14:54"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/model-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/model-isvalid.html
new file mode 100644
index 00000000000..cd10ac511e5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/model-isvalid.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;ins&gt;</title>
+</head>
+<body>
+
+ <!-- can contain strictly inline while in strictly inline context -->
+ <p><dfn>strictly inline
+ <ins>
+ <em>text</em>
+ </ins>
+ </dfn></p>
+
+ <!-- can contain interactive if ancestor does not forbid it -->
+ <p>paragraph
+ <ins>
+ <a>link</a>
+ </ins>
+ </p>
+ <p><dfn>strictly inline
+ <ins>
+ <a>link</a>
+ </ins>
+ </dfn></p>
+
+ <!-- ins with flow content and flow parent -->
+ <div><ins><p>foo</p></ins></div>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/model-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/model-novalid.html
new file mode 100644
index 00000000000..65ee321f2fc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/model-novalid.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;ins&gt;</title>
+</head>
+<body>
+ <!-- can contain inline while in inline context -->
+ <p>paragraph
+ <ins>
+ <em>some</em> <ul><li>inline</li></ul> content
+ </ins>
+ </p>
+
+ <!-- can contain strictly inline while in strictly inline context -->
+ <p><dfn>strictly inline
+ <ins>
+ <em>text</em>
+ </ins>
+ </dfn></p>
+
+ <!-- can contain blocks while in block context -->
+ <ins>
+ <p>text</p>
+ </ins>
+
+ <!-- can contain interactive if ancestor does not forbid it -->
+ <p>paragraph
+ <ins>
+ <a>link</a>
+ </ins>
+ </p>
+ <p><dfn>strictly inline
+ <ins>
+ <a>link</a>
+ </ins>
+ </dfn></p>
+ <ins>
+ <p><a>link</a></p>
+ </ins>
+
+ <!-- ins with flow content and phrasing parent -->
+ <span><ins><p>foo</p></ins></span>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/month-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/month-novalid.html
new file mode 100644
index 00000000000..57f8bf0da25
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/month-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>month</title>
+<ins datetime="2011-11"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/time-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/time-novalid.html
new file mode 100644
index 00000000000..aaf798ff779
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/time-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>time</title>
+<ins datetime="14:54:39"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/week-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/week-novalid.html
new file mode 100644
index 00000000000..77c2dcfc96b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/week-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>week</title>
+<ins datetime="2011-W46"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/year-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/year-novalid.html
new file mode 100644
index 00000000000..b971e7fbf48
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/year-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>year</title>
+<ins datetime="2006"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/yearless-date-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/yearless-date-novalid.html
new file mode 100644
index 00000000000..e477cb45213
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ins/yearless-date-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>yearless-date</title>
+<ins datetime="07-15"></ins> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/kbd/model-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/kbd/model-isvalid.html
new file mode 100644
index 00000000000..45646d0eb54
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/kbd/model-isvalid.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;kbd&gt;</title>
+</head>
+<body>
+ <!-- is structured inline -->
+ <p><kbd class="class" lang="en">text</kbd></p>
+
+ <!-- is strictly inline -->
+ <p><dfn><kbd class="class" lang="en">text</kbd></dfn></p>
+
+ <!-- can be empty -->
+ <p>text <kbd></kbd></p>
+ <p>text <dfn><kbd></kbd></dfn></p>
+
+ <!-- can contain interactive -->
+ <p><kbd><a>text</a></kbd></p>
+ <p><dfn><kbd><a>text</a></kbd></dfn></p>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/kbd/model-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/kbd/model-novalid.html
new file mode 100644
index 00000000000..8bfbb883956
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/kbd/model-novalid.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;kbd&gt;</title>
+</head>
+<body>
+ <!-- not a block -->
+ <kbd>text</kbd>
+
+ <!-- cannot contain structured inline -->
+ <p><kbd><ul><li>text</li></ul></kbd></p>
+
+ <!-- cannot contain interactive if parent forbids interactive -->
+ <p><a><kbd><a>text</a></kbd></a></p>
+ <p><a><dfn><kbd><a>text</a></kbd></dfn></a></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/keygen/challenge-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/keygen/challenge-isvalid.html
new file mode 100644
index 00000000000..09bb2a096c7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/keygen/challenge-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>keygen with "challenge" attribute</title>
+</head>
+<body>
+<keygen challenge="123456">
+<keygen challenge=""> <!-- empty challenge -->
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/keygen/id-bad-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/keygen/id-bad-novalid.html
new file mode 100644
index 00000000000..1c8d72c781a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/keygen/id-bad-novalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>keygen as &lt;label> descendant, with wrong ID</title>
+</head>
+<body>
+<label for="foo">
+<keygen id="bar">
+</label>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/keygen/id-missing-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/keygen/id-missing-novalid.html
new file mode 100644
index 00000000000..1793192c850
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/keygen/id-missing-novalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>keygen as &lt;label> descendant, with no ID</title>
+</head>
+<body>
+<label for="foo">
+<keygen>
+</label>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/keygen/id-redundant-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/keygen/id-redundant-novalid.html
new file mode 100644
index 00000000000..9bc49b5ed13
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/keygen/id-redundant-novalid.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>keygen as redundant &lt;label> descendant</title>
+</head>
+<body>
+<label for="foo">
+<input id="foo">
+<keygen>
+</label>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/keygen/keytype-bad-value-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/keygen/keytype-bad-value-novalid.html
new file mode 100644
index 00000000000..791f7c20630
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/keygen/keytype-bad-value-novalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>keygen with invalid value for "keytype" attribute</title>
+</head>
+<body>
+<keygen keytype="dsa">
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/keygen/keytype-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/keygen/keytype-empty-novalid.html
new file mode 100644
index 00000000000..88c32a96900
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/keygen/keytype-empty-novalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>keygen with invalid empty "keytype" attribute</title>
+</head>
+<body>
+<keygen keytype="">
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/keygen/keytype-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/keygen/keytype-isvalid.html
new file mode 100644
index 00000000000..a92a32a8644
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/keygen/keytype-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>keygen with "keytype" attribute</title>
+</head>
+<body>
+<keygen keytype="rsa">
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/keygen/model-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/keygen/model-isvalid.html
new file mode 100644
index 00000000000..953ec6ad09c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/keygen/model-isvalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>keygen as &lt;label> descendant</title>
+</head>
+<body>
+<label for="foo">
+<keygen id="foo">
+</label>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/keygen/model-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/keygen/model-novalid.html
new file mode 100644
index 00000000000..8d267093ab3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/keygen/model-novalid.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>keygen as an invalid &lt;a> descendant</title>
+</head>
+<body>
+<a href="url">
+<keygen>
+</a>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/keygen/no-attributes-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/keygen/no-attributes-isvalid.html
new file mode 100644
index 00000000000..ca17832aa67
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/keygen/no-attributes-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>keygen with no attributes</title>
+</head>
+<body>
+<keygen>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/keygen/non-void-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/keygen/non-void-novalid.html
new file mode 100644
index 00000000000..fb5fcef0cba
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/keygen/non-void-novalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>no-void keygen</title>
+</head>
+<body>
+<keygen>foo</keygen>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/label/for-descendant-no-id-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/label/for-descendant-no-id-novalid.html
new file mode 100644
index 00000000000..2f1ed73f2b8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/label/for-descendant-no-id-novalid.html
@@ -0,0 +1 @@
+<!doctype html><meta charset=utf-8><title>&lt;input id=a>&lt;label for=a>&lt;input></title><p>There should be an error. <input id=a><label for=a><input></label>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/label/for-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/label/for-isvalid.html
new file mode 100644
index 00000000000..c4a4e60da4a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/label/for-isvalid.html
@@ -0,0 +1 @@
+<!doctype html><meta charset=utf-8><title>&lt;label for=a>&lt;input id=a></title><p>There should be no error. <label for=a><input id=a></label>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/label/multiple-descendants-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/label/multiple-descendants-novalid.html
new file mode 100644
index 00000000000..014085bb6b4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/label/multiple-descendants-novalid.html
@@ -0,0 +1 @@
+<!doctype html><meta charset=utf-8><title>&lt;label>&lt;input>&lt;input></title><p>There should be an error. <label><input><input></label>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href-empty-novalid.html
new file mode 100644
index 00000000000..fb1f349f75b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>empty href is not valid</title>
+<link href="" rel>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href-isvalid.html
new file mode 100644
index 00000000000..fd4bd484a8a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href-isvalid.html
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid href</title>
+<link href="file:///" rel=help><!-- scheme-file-slash-slash-slash-only -->
+<link href="http://a:@www.example.com" rel=help><!-- userinfo-password-empty -->
+<link href="foo://///////" rel=help><!-- scheme-private-path-leading-slashes-only -->
+<link href="file://abc|/foo/bar" rel=help><!-- scheme-file-slash-slash-abc-bar -->
+<link href="/a/b/c" rel=help><!-- path-simple-relative -->
+<link href="http://example.com/你好你好" rel=help><!-- path-unicode-han -->
+<link href="/a/%2f/c" rel=help><!-- path-percent-encoded-slash-plus-slashes-relative -->
+<link href="http://f:/c" rel=help><!-- port-none-but-colon -->
+<link href="http://example.com/foo%41%7a" rel=help><!-- path-percent-encoded-multiple -->
+<link href="http://192.168.0.257/" rel=help><!-- host-IP-address-broken -->
+<link href="madeupscheme:example.com/" rel=help><!-- scheme-private-no-slash -->
+<link href="?" rel=help><!-- query-empty-no-path-relative -->
+<link href="http://example.com/%20foo" rel=help><!-- path-percent-encoded-space -->
+<link href="mailto:/example.com/" rel=help><!-- scheme-mailto-single-slash -->
+<link href="::" rel=help><!-- path-leading-colon-colon-relative -->
+<link href="http://example.com/%3A%3a%3C%3c" rel=help><!-- path-percent-encoded-mixed-case -->
+<link href="http://user:pass@foo:21/bar;par?b#c" rel=help><!-- userinfo -->
+<link href="ws:/example.com/" rel=help><!-- scheme-ws-single-slash -->
+<link href="foo://" rel=help><!-- scheme-private-slash-slash -->
+<link href="#" rel=help><!-- fragment-empty-hash-only-no-path-relative -->
+<link href="http://f:00000000000000/c" rel=help><!-- port-00000000000000 -->
+<link href="foo:////://///" rel=help><!-- scheme-private-path-leading-slashes-colon-slashes -->
+<link href=":23" rel=help><!-- path-leading-colon-number-relative -->
+<link href="foo:/" rel=help><!-- scheme-private-slash -->
+<link href="http://💩" rel=help><!-- host-is-pile-of-poo -->
+<link href="file:test" rel=help><!-- scheme-file-no-slash -->
+<link href="file://C|/foo/bar" rel=help><!-- scheme-file-slash-slash-c-bar -->
+<link href="#/" rel=help><!-- fragment-slash-relative -->
+<link href="http://192.0x00A80001" rel=help><!-- host-192.0x00A80001 -->
+<link href="foo.com" rel=help><!-- scheme-none-relative -->
+<link href="http💩//:foo" rel=help><!-- path-contains-pile-of-poo -->
+<link href="File://foo/bar.html" rel=help><!-- scheme-file-uppercase -->
+<link href=":/" rel=help><!-- path-leading-colon-slash-relative -->
+<link href="http://www.foo。bar.com" rel=help><!-- host-exotic-dot -->
+<link href="http://GOO​⁠goo.com" rel=help><!-- host-exotic-whitespace -->
+<link href="file:///foo/bar.txt" rel=help><!-- scheme-file-host-empty -->
+<link href="javascript:/example.com/" rel=help><!-- scheme-javascript-single-slash -->
+<link href="gopher:/example.com/" rel=help><!-- scheme-gopher-single-slash -->
+<link href="ftps:example.com/" rel=help><!-- scheme-ftps-no-slash -->
+<link href="file://server/foo/bar" rel=help><!-- scheme-file-host-included -->
+<link href="http://example.com/foo%00" rel=help><!-- path-percent-encoded-u0000 -->
+<link href="a:foo.com" rel=help><!-- scheme-private -->
+<link href=":" rel=help><!-- path-colon-relative -->
+<link href="http://:b@www.example.com" rel=help><!-- userinfo-user-empty -->
+<link href="file:/" rel=help><!-- scheme-file-slash-only -->
+<link href="wss:example.com/" rel=help><!-- scheme-wss-no-slash -->
+<link href="::23" rel=help><!-- path-colon-colon-number-relative -->
+<link href="/a%2fc" rel=help><!-- path-percent-encoded-slash-relative -->
+<link href="http://a:b@c:29/d" rel=help><!-- userinfo-host-port-path -->
+<link href="gopher:example.com/" rel=help><!-- scheme-gopher-no-slash -->
+<link href="madeupscheme:/example.com/" rel=help><!-- scheme-private-single-slash -->
+<link href="mailto:example.com/" rel=help><!-- scheme-mailto-no-slash -->
+<link href="http://%25DOMAIN:foobar@foodomain.com" rel=help><!-- userinfo-username-contains-percent-encoded -->
+<link href="/:23" rel=help><!-- path-slash-colon-number-relative -->
+<link href="foo://///////bar.com/" rel=help><!-- scheme-private-path-leading-slashes-chars -->
+<link href="http://[2001::1]:80" rel=help><!-- host-ipv6-port -->
+<link href="data:text/plain,foo" rel=help><!-- scheme-data-no-slash -->
+<link href="http://example.com/foo/%2e" rel=help><!-- path-percent-encoded-dot -->
+<link href="file:/example.com/" rel=help><!-- scheme-file-single-slash -->
+<link href="http://example.com/©zbar" rel=help><!-- path-non-ascii -->
+<link href="http://example.com//foo" rel=help><!-- path-uFEFF -->
+<link href="wss:/example.com/" rel=help><!-- scheme-wss-single-slash -->
+<link href="http://foo/abcd#foo?bar" rel=help><!-- fragment-contains-question-mark -->
+<link href=":#" rel=help><!-- path-leading-colon-hash-relative -->
+<link href="http://example.com/foo%91" rel=help><!-- path-percent-encoded-u0091 -->
+<link href="c:/foo" rel=help><!-- scheme-private-single-letter -->
+<link href=":foo.com" rel=help><!-- path-leading-colon-chars-relative -->
+<link href="http://你好你好" rel=help><!-- host-idn-unicode-han -->
+<link href="http://example.com/foo#💩" rel=help><!-- fragment-contains-pile-of-poo -->
+<link href="file:" rel=help><!-- scheme-file-scheme-only -->
+<link href="#β" rel=help><!-- fragment-non-ascii-relative -->
+<link href="foo:/bar.com/" rel=help><!-- scheme-private-path -->
+<link href="http://f:0/c" rel=help><!-- port-0 -->
+<link href="#;?" rel=help><!-- fragment-semicolon-question-mark-relative -->
+<link href="http://Go.com" rel=help><!-- host-fullwidth -->
+<link href="http://@www.example.com" rel=help><!-- userinfo-empty -->
+<link href="http://example.com/‮/foo/‭/bar" rel=help><!-- path-u202E-u202D -->
+<link href="http://[2001::1]" rel=help><!-- host-ipv6 -->
+<link href="💩http://foo" rel=help><!-- path-starts-with-pile-of-poo -->
+<link href="http://foo/abcd?efgh?ijkl" rel=help><!-- query-contains-question-mark -->
+<link href="//foo/bar" rel=help><!-- scheme-schemeless-relative -->
+<link href="ftps:/example.com/" rel=help><!-- scheme-ftps-single-slash -->
+<link href="http://foo.com:b@d/" rel=help><!-- userinfo-username-non-alpha -->
+<link href=":a" rel=help><!-- path-leading-colon-letter-relative -->
+<link href="/" rel=help><!-- path-slash-only-relative -->
+<link href="http://example.com/foo?💩" rel=help><!-- query-contains-pile-of-poo -->
+<link href="http://f:00000000000000000000080/c" rel=help><!-- port-00000000000000000000080 -->
+<link href="file://" rel=help><!-- scheme-file-slash-slash-only -->
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href-missing-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href-missing-novalid.html
new file mode 100644
index 00000000000..eded973f6b7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href-missing-novalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta charset=utf-8>
+<title>link element missing href attribute</title>
+<link rel=stylesheet>
+</head>
+<body>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href-whitespace-only-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href-whitespace-only-novalid.html
new file mode 100644
index 00000000000..6874b119736
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href-whitespace-only-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>empty href is not valid</title>
+<link href="
+" rel>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/fragment-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/fragment-backslash-novalid.html
new file mode 100644
index 00000000000..8f59c37ca87
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/fragment-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: fragment-backslash</title>
+<link href="#\" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/fragment-contains-hash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/fragment-contains-hash-novalid.html
new file mode 100644
index 00000000000..77997986afd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/fragment-contains-hash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: fragment-contains-hash</title>
+<link href="http://foo/path#f#g" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/fragment-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/fragment-leading-space-novalid.html
new file mode 100644
index 00000000000..3cd63e09c7f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/fragment-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: fragment-leading-space</title>
+<link href="http://f:21/b# e" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-cr-novalid.html
new file mode 100644
index 00000000000..f66c1640acc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-cr</title>
+<link href="http://example. org" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-double-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-double-percent-encoded-novalid.html
new file mode 100644
index 00000000000..591dca85232
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-double-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-double-percent-encoded</title>
+<link href="http://%41.com" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-double-percent-encoded-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-double-percent-encoded-percent-encoded-novalid.html
new file mode 100644
index 00000000000..484097db862
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-double-percent-encoded-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-double-percent-encoded-percent-encoded</title>
+<link href="http://%ef%bc%85%ef%bc%94%ef%bc%91.com" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-empty-novalid.html
new file mode 100644
index 00000000000..30bfc0f084f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-empty</title>
+<link href="http://" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-empty-userinfo-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-empty-userinfo-empty-novalid.html
new file mode 100644
index 00000000000..027efe0d44a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-empty-userinfo-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-empty-userinfo-empty</title>
+<link href="http://@/www.example.com" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-empty-with-userinfo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-empty-with-userinfo-novalid.html
new file mode 100644
index 00000000000..b07878ee919
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-empty-with-userinfo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-empty-with-userinfo</title>
+<link href="http://user:pass@/" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-hostname-in-brackets-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-hostname-in-brackets-novalid.html
new file mode 100644
index 00000000000..03b35eb582b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-hostname-in-brackets-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-hostname-in-brackets</title>
+<link href="http://[www.google.com]/" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-invalid-unicode-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-invalid-unicode-novalid.html
new file mode 100644
index 00000000000..22b5e8d3cd8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-invalid-unicode-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-invalid-unicode</title>
+<link href="http://﷐zyx.com" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-invalid-unicode-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-invalid-unicode-percent-encoded-novalid.html
new file mode 100644
index 00000000000..fcba2a20bdf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-invalid-unicode-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-invalid-unicode-percent-encoded</title>
+<link href="http://%ef%b7%90zyx.com" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-newline-novalid.html
new file mode 100644
index 00000000000..446a0d4803c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-newline</title>
+<link href="http://example.
+org" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-space-novalid.html
new file mode 100644
index 00000000000..7cf4ab8d3b2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-space</title>
+<link href="http://example .org" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-square-brackets-port-contains-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-square-brackets-port-contains-colon-novalid.html
new file mode 100644
index 00000000000..34500ab8c06
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-square-brackets-port-contains-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-square-brackets-port-contains-colon</title>
+<link href="http://[1::2]:3:4" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-tab-novalid.html
new file mode 100644
index 00000000000..4f4a97bd3c9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-tab</title>
+<link href="http://example .org" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-u0000-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-u0000-percent-encoded-novalid.html
new file mode 100644
index 00000000000..905c8661ff1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-u0000-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-u0000-percent-encoded</title>
+<link href="http://%00.com" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-u0000-percent-encoded-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-u0000-percent-encoded-percent-encoded-novalid.html
new file mode 100644
index 00000000000..084773e6f49
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/host-u0000-percent-encoded-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: host-u0000-percent-encoded-percent-encoded</title>
+<link href="http://%ef%bc%85%ef%bc%90%ef%bc%90.com" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/path-bare-percent-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/path-bare-percent-sign-novalid.html
new file mode 100644
index 00000000000..1e02cf8e813
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/path-bare-percent-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: path-bare-percent-sign</title>
+<link href="http://example.com/foo%" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/path-contains-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/path-contains-space-novalid.html
new file mode 100644
index 00000000000..8386f5d8014
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/path-contains-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: path-contains-space</title>
+<link href="/a/ /c" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/path-leading-backslash-at-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/path-leading-backslash-at-sign-novalid.html
new file mode 100644
index 00000000000..5c333681ba0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/path-leading-backslash-at-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: path-leading-backslash-at-sign</title>
+<link href="http://foo.com/\@" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/path-leading-colon-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/path-leading-colon-backslash-novalid.html
new file mode 100644
index 00000000000..19d37d8f100
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/path-leading-colon-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: path-leading-colon-backslash</title>
+<link href=":\" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/path-leading-colon-chars-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/path-leading-colon-chars-backslash-novalid.html
new file mode 100644
index 00000000000..5580214cb0b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/path-leading-colon-chars-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: path-leading-colon-chars-backslash</title>
+<link href=":foo.com\" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/path-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/path-leading-space-novalid.html
new file mode 100644
index 00000000000..28890058547
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/path-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: path-leading-space</title>
+<link href="http://f:21/ b" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/path-percent-encoded-malformed-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/path-percent-encoded-malformed-novalid.html
new file mode 100644
index 00000000000..599fecbbc25
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/path-percent-encoded-malformed-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: path-percent-encoded-malformed</title>
+<link href="http://example.com/foo/%2e%2" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/path-relative-square-brackets-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/path-relative-square-brackets-novalid.html
new file mode 100644
index 00000000000..630062db8e9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/path-relative-square-brackets-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: path-relative-square-brackets</title>
+<link href="[61:24:74]:98" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/path-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/path-tab-novalid.html
new file mode 100644
index 00000000000..4c5e234c4f3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/path-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: path-tab</title>
+<link href="http://example.com/foo bar" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/path-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/path-trailing-space-novalid.html
new file mode 100644
index 00000000000..f8bcef833bf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/path-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: path-trailing-space</title>
+<link href="http://f:21/b ?" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/path-u0091-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/path-u0091-novalid.html
new file mode 100644
index 00000000000..5bed826c04f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/path-u0091-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: path-u0091</title>
+<link href="http://example.com/foo‘" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/port-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/port-cr-novalid.html
new file mode 100644
index 00000000000..030307b479a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/port-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: port-cr</title>
+<link href="http://f: /c" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/port-leading-colon-bracket-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/port-leading-colon-bracket-colon-novalid.html
new file mode 100644
index 00000000000..0bf977156bc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/port-leading-colon-bracket-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: port-leading-colon-bracket-colon</title>
+<link href="http://2001::1]:80" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/port-leading-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/port-leading-colon-novalid.html
new file mode 100644
index 00000000000..04eb695a046
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/port-leading-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: port-leading-colon</title>
+<link href="http://2001::1" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/port-leading-dash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/port-leading-dash-novalid.html
new file mode 100644
index 00000000000..f77f17e1380
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/port-leading-dash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: port-leading-dash</title>
+<link href="http://foo:-80/" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/port-multiple-letters-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/port-multiple-letters-novalid.html
new file mode 100644
index 00000000000..2a8ab2aac0a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/port-multiple-letters-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: port-multiple-letters</title>
+<link href="http://f:fifty-two/c" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/port-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/port-newline-novalid.html
new file mode 100644
index 00000000000..5346b4fa2ee
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/port-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: port-newline</title>
+<link href="http://f:
+/c" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/port-single-letter-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/port-single-letter-novalid.html
new file mode 100644
index 00000000000..f0b2d511799
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/port-single-letter-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: port-single-letter</title>
+<link href="http://f:b/c" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/port-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/port-space-novalid.html
new file mode 100644
index 00000000000..1acf0b3d381
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/port-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: port-space</title>
+<link href="http://f: /c" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/port-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/port-tab-novalid.html
new file mode 100644
index 00000000000..4371db32de1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/port-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: port-tab</title>
+<link href="http://f: /c" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/query-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/query-leading-space-novalid.html
new file mode 100644
index 00000000000..1a45d5a8077
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/query-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: query-leading-space</title>
+<link href="http://f:21/b? d" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/query-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/query-trailing-space-novalid.html
new file mode 100644
index 00000000000..ccd4596d3d7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/query-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: query-trailing-space</title>
+<link href="http://f:21/b?d #" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-data-contains-fragment-haswarn.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-data-contains-fragment-haswarn.html
new file mode 100644
index 00000000000..70fd6492c5f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-data-contains-fragment-haswarn.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>href warning: scheme-data-contains-fragment</title>
+<link href="data:text/html,test#test" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-data-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-data-single-slash-novalid.html
new file mode 100644
index 00000000000..95f89580699
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-data-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-data-single-slash</title>
+<link href="data:/example.com/" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-file-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-file-backslash-novalid.html
new file mode 100644
index 00000000000..8b37e6b76f9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-file-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-file-backslash</title>
+<link href="file:c:\foo\bar.html" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-file-single-slash-c-bar-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-file-single-slash-c-bar-novalid.html
new file mode 100644
index 00000000000..cb02748125c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-file-single-slash-c-bar-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-file-single-slash-c-bar</title>
+<link href="file:/C|/foo/bar" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-file-triple-slash-c-bar-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-file-triple-slash-c-bar-novalid.html
new file mode 100644
index 00000000000..0364ce64970
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-file-triple-slash-c-bar-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-file-triple-slash-c-bar</title>
+<link href="file:///C|/foo/bar" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-ftp-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-ftp-no-slash-novalid.html
new file mode 100644
index 00000000000..17a72ac5425
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-ftp-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-ftp-no-slash</title>
+<link href="ftp:example.com/" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-ftp-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-ftp-single-slash-novalid.html
new file mode 100644
index 00000000000..c930a16b47b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-ftp-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-ftp-single-slash</title>
+<link href="ftp:/example.com/" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-http-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-http-backslash-novalid.html
new file mode 100644
index 00000000000..af1814b44bb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-http-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-http-backslash</title>
+<link href="http:\\foo.com\" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-http-no-slash-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-http-no-slash-colon-novalid.html
new file mode 100644
index 00000000000..816bd3b2548
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-http-no-slash-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-http-no-slash-colon</title>
+<link href="http::@c:29" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-http-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-http-no-slash-novalid.html
new file mode 100644
index 00000000000..1678caac762
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-http-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-http-no-slash</title>
+<link href="http:foo.com" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-http-no-slash-square-bracket-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-http-no-slash-square-bracket-novalid.html
new file mode 100644
index 00000000000..f768ffa9dc9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-http-no-slash-square-bracket-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-http-no-slash-square-bracket</title>
+<link href="http:[61:27]/:foo" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-http-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-http-single-slash-novalid.html
new file mode 100644
index 00000000000..b2210d4900c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-http-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-http-single-slash</title>
+<link href="http:/example.com/" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-https-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-https-no-slash-novalid.html
new file mode 100644
index 00000000000..13c5e34620d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-https-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-https-no-slash</title>
+<link href="https:example.com/" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-https-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-https-single-slash-novalid.html
new file mode 100644
index 00000000000..b9192eb216c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-https-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-https-single-slash</title>
+<link href="https:/example.com/" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-javascript-no-slash-malformed-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-javascript-no-slash-malformed-novalid.html
new file mode 100644
index 00000000000..6cf49ca2367
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-javascript-no-slash-malformed-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-javascript-no-slash-malformed</title>
+<link href="javascript:example.com/" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-trailing-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-trailing-cr-novalid.html
new file mode 100644
index 00000000000..3877fab7cb4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-trailing-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-trailing-cr</title>
+<link href="a: foo.com" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-trailing-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-trailing-newline-novalid.html
new file mode 100644
index 00000000000..5b747be012c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-trailing-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-trailing-newline</title>
+<link href="a:
+foo.com" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-trailing-space-novalid.html
new file mode 100644
index 00000000000..65dd25d8431
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-trailing-space</title>
+<link href="a: foo.com" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-trailing-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-trailing-tab-novalid.html
new file mode 100644
index 00000000000..934a8c4d371
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/scheme-trailing-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: scheme-trailing-tab</title>
+<link href="a: foo.com" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/userinfo-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/userinfo-backslash-novalid.html
new file mode 100644
index 00000000000..78e636f58cb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/userinfo-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: userinfo-backslash</title>
+<link href="http://a\b:c\d@foo.com" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/userinfo-password-bad-chars-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/userinfo-password-bad-chars-novalid.html
new file mode 100644
index 00000000000..259f84eb613
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/userinfo-password-bad-chars-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: userinfo-password-bad-chars</title>
+<link href="http://&a:foo(b]c@d:2/" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/userinfo-password-contains-pile-of-poo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/userinfo-password-contains-pile-of-poo-novalid.html
new file mode 100644
index 00000000000..5acd244ccf0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/userinfo-password-contains-pile-of-poo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: userinfo-password-contains-pile-of-poo</title>
+<link href="http://foo:💩@example.com" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/userinfo-username-contains-at-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/userinfo-username-contains-at-sign-novalid.html
new file mode 100644
index 00000000000..1cff4f27532
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/userinfo-username-contains-at-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: userinfo-username-contains-at-sign</title>
+<link href="http://::@c@d:2" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/userinfo-username-contains-pile-of-poo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/userinfo-username-contains-pile-of-poo-novalid.html
new file mode 100644
index 00000000000..0db2f57b988
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/link/href/userinfo-username-contains-pile-of-poo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid href: userinfo-username-contains-pile-of-poo</title>
+<link href="http://💩:foo@example.com" rel=help>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/map/model-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/map/model-isvalid.html
new file mode 100644
index 00000000000..ae6dbac6f75
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/map/model-isvalid.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;map&gt;</title>
+</head>
+<body>
+ <!-- is block, contains blocks and <area> -->
+ <map class="class" id="id" name="id" lang="en">
+ <h2>header</h2>
+ <p><area alt="text" href='foo' coords="1,2,3,4">p</p>
+ <p>text</p>
+ <p><area alt="text" href='foo' coords="3,2,5,4">p</p>
+ <p>text2</p>
+ </map>
+
+ <!-- can contain interactive -->
+ <map id='foo' name="foo">
+ <p><a>text</a></p>
+ <p><area alt="text" href='foo' coords="3,2,5,4">p</p>
+ </map>
+
+ <!-- map with flow content and flow parent -->
+ <div><map name=foo><p>foo</p></map></div>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/map/model-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/map/model-novalid.html
new file mode 100644
index 00000000000..3ee9b822eb2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/map/model-novalid.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;map&gt;</title>
+</head>
+<body>
+ <!-- is block, contains blocks and <area> -->
+ <map name="foo" class="class" id="id" lang="en">
+ <h2>header</h2>
+ <area alt="text" coords="1,2,3,4">
+ <p>text</p>
+ <area alt="text" coords="5,2,3,4">
+ <p>text2</p>
+ </map>
+
+ <!-- can contain interactive -->
+ <map>
+ <p><a>text</a></p>
+ <area alt="text" coords="5,2,3,4">
+ </map>
+
+ <!-- map with flow content and phrasing parent -->
+ <span><map name=foo><p>foo</p></map></span>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/mark/model-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/mark/model-isvalid.html
new file mode 100644
index 00000000000..20ba6d25d02
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/mark/model-isvalid.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;m&gt;</title>
+</head>
+<body>
+ <!-- is structured inline -->
+ <p><mark class="class" lang="en">text</mark></p>
+
+ <!-- is strictly inline -->
+ <p><dfn><mark class="class" lang="en">text</mark></dfn></p>
+
+ <!-- can be empty -->
+ <p>text <mark></mark></p>
+ <p>text <dfn><mark></mark></dfn></p>
+
+ <!-- can contain interactive -->
+ <p><mark><a>text</a></mark></p>
+ <p><dfn><mark><a>text</a></mark></dfn></p>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/meta/names-registered-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/meta/names-registered-isvalid.html
new file mode 100644
index 00000000000..f2cb75bb135
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/meta/names-registered-isvalid.html
@@ -0,0 +1,768 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Registered extensions to the predefined set of metadata names</title>
+<meta name="aglsterms.accessibility" content>
+<meta name="AGLSTERMS.ACCESSIBILITY" content>
+<meta name="AgLsTeRmS.AcCeSsIbIlItY" content>
+<meta name="aglsterms.accessmode" content>
+<meta name="AGLSTERMS.ACCESSMODE" content>
+<meta name="AgLsTeRmS.AcCeSsMoDe" content>
+<meta name="aglsterms.act" content>
+<meta name="AGLSTERMS.ACT" content>
+<meta name="AgLsTeRmS.AcT" content>
+<meta name="aglsterms.aggregationlevel" content>
+<meta name="AGLSTERMS.AGGREGATIONLEVEL" content>
+<meta name="AgLsTeRmS.AgGrEgAtIoNlEvEl" content>
+<meta name="aglsterms.availability" content>
+<meta name="AGLSTERMS.AVAILABILITY" content>
+<meta name="AgLsTeRmS.AvAiLaBiLiTy" content>
+<meta name="aglsterms.case" content>
+<meta name="AGLSTERMS.CASE" content>
+<meta name="AgLsTeRmS.CaSe" content>
+<meta name="aglsterms.category" content>
+<meta name="AGLSTERMS.CATEGORY" content>
+<meta name="AgLsTeRmS.CaTeGoRy" content>
+<meta name="aglsterms.datelicensed" content>
+<meta name="AGLSTERMS.DATELICENSED" content>
+<meta name="AgLsTeRmS.DaTeLiCeNsEd" content>
+<meta name="aglsterms.documenttype" content>
+<meta name="AGLSTERMS.DOCUMENTTYPE" content>
+<meta name="AgLsTeRmS.DoCuMeNtTyPe" content>
+<meta name="aglsterms.function" content>
+<meta name="AGLSTERMS.FUNCTION" content>
+<meta name="AgLsTeRmS.FuNcTiOn" content>
+<meta name="aglsterms.isbasedon" content>
+<meta name="AGLSTERMS.ISBASEDON" content>
+<meta name="AgLsTeRmS.IsBaSeDoN" content>
+<meta name="aglsterms.isbasisfor" content>
+<meta name="AGLSTERMS.ISBASISFOR" content>
+<meta name="AgLsTeRmS.IsBaSiSfOr" content>
+<meta name="aglsterms.jurisdiction" content>
+<meta name="AGLSTERMS.JURISDICTION" content>
+<meta name="AgLsTeRmS.JuRiSdIcTiOn" content>
+<meta name="aglsterms.mandate" content>
+<meta name="AGLSTERMS.MANDATE" content>
+<meta name="AgLsTeRmS.MaNdAtE" content>
+<meta name="aglsterms.protectivemarking" content>
+<meta name="AGLSTERMS.PROTECTIVEMARKING" content>
+<meta name="AgLsTeRmS.PrOtEcTiVeMaRkInG" content>
+<meta name="aglsterms.regulation" content>
+<meta name="AGLSTERMS.REGULATION" content>
+<meta name="AgLsTeRmS.ReGuLaTiOn" content>
+<meta name="aglsterms.servicetype" content>
+<meta name="AGLSTERMS.SERVICETYPE" content>
+<meta name="AgLsTeRmS.SeRvIcEtYpE" content>
+<meta name="alexaverifyid" content>
+<meta name="ALEXAVERIFYID" content>
+<meta name="AlExAvErIfYiD" content>
+<meta name="apple-itunes-app" content>
+<meta name="APPLE-ITUNES-APP" content>
+<meta name="ApPlE-ItUnEs-aPp" content>
+<meta name="apple-mobile-web-app-capable" content>
+<meta name="APPLE-MOBILE-WEB-APP-CAPABLE" content>
+<meta name="ApPlE-MoBiLe-wEb-aPp-cApAbLe" content>
+<meta name="apple-mobile-web-app-status-bar-style" content>
+<meta name="APPLE-MOBILE-WEB-APP-STATUS-BAR-STYLE" content>
+<meta name="ApPlE-MoBiLe-wEb-aPp-sTaTuS-BaR-StYlE" content>
+<meta name="apple-mobile-web-app-title" content>
+<meta name="APPLE-MOBILE-WEB-APP-TITLE" content>
+<meta name="ApPlE-MoBiLe-wEb-aPp-tItLe" content>
+<meta name="apple-touch-fullscreen" content>
+<meta name="APPLE-TOUCH-FULLSCREEN" content>
+<meta name="ApPlE-ToUcH-FuLlScReEn" content>
+<meta name="application-url" content>
+<meta name="APPLICATION-URL" content>
+<meta name="ApPlIcAtIoN-UrL" content>
+<meta name="baiduspider" content>
+<meta name="BAIDUSPIDER" content>
+<meta name="BaIdUsPiDeR" content>
+<meta name="bitcoin" content>
+<meta name="BITCOIN" content>
+<meta name="BiTcOiN" content>
+<meta name="blazerr-secure" content>
+<meta name="BLAZERR-SECURE" content>
+<meta name="BlAzErR-SeCuRe" content>
+<meta name="blazerr-seo" content>
+<meta name="BLAZERR-SEO" content>
+<meta name="BlAzErR-SeO" content>
+<meta name="blazerr-ssl" content>
+<meta name="BLAZERR-SSL" content>
+<meta name="BlAzErR-SsL" content>
+<meta name="blazerr-support-id-noncookies" content>
+<meta name="BLAZERR-SUPPORT-ID-NONCOOKIES" content>
+<meta name="BlAzErR-SuPpOrT-Id-nOnCoOkIeS" content>
+<meta name="blazerr-support-identifier" content>
+<meta name="BLAZERR-SUPPORT-IDENTIFIER" content>
+<meta name="BlAzErR-SuPpOrT-IdEnTiFiEr" content>
+<meta name="cfia.gdr.activity" content>
+<meta name="CFIA.GDR.ACTIVITY" content>
+<meta name="CfIa.gDr.aCtIvItY" content>
+<meta name="cfia.gdr.commodity" content>
+<meta name="CFIA.GDR.COMMODITY" content>
+<meta name="CfIa.gDr.cOmMoDiTy" content>
+<meta name="cfia.gdr.include" content>
+<meta name="CFIA.GDR.INCLUDE" content>
+<meta name="CfIa.gDr.iNcLuDe" content>
+<meta name="cfia.gdr.program" content>
+<meta name="CFIA.GDR.PROGRAM" content>
+<meta name="CfIa.gDr.pRoGrAm" content>
+<meta name="citeseerxbot" content>
+<meta name="CITESEERXBOT" content>
+<meta name="CiTeSeErXbOt" content>
+<meta name="collection" content>
+<meta name="COLLECTION" content>
+<meta name="CoLlEcTiOn" content>
+<meta name="csrf-param" content>
+<meta name="CSRF-PARAM" content>
+<meta name="CsRf-pArAm" content>
+<meta name="csrf-token" content>
+<meta name="CSRF-TOKEN" content>
+<meta name="CsRf-tOkEn" content>
+<meta name="da_anonymiseip" content>
+<meta name="DA_ANONYMISEIP" content>
+<meta name="Da_aNoNyMiSeIp" content>
+<meta name="da_contactcompany" content>
+<meta name="DA_CONTACTCOMPANY" content>
+<meta name="Da_cOnTaCtCoMpAnY" content>
+<meta name="da_contactemail" content>
+<meta name="DA_CONTACTEMAIL" content>
+<meta name="Da_cOnTaCtEmAiL" content>
+<meta name="da_contactfirstname" content>
+<meta name="DA_CONTACTFIRSTNAME" content>
+<meta name="Da_cOnTaCtFiRsTnAmE" content>
+<meta name="da_contactlastname" content>
+<meta name="DA_CONTACTLASTNAME" content>
+<meta name="Da_cOnTaCtLaStNaMe" content>
+<meta name="da_contactname" content>
+<meta name="DA_CONTACTNAME" content>
+<meta name="Da_cOnTaCtNaMe" content>
+<meta name="da_contacttelephone" content>
+<meta name="DA_CONTACTTELEPHONE" content>
+<meta name="Da_cOnTaCtTeLePhOnE" content>
+<meta name="da_conversioncurrency" content>
+<meta name="DA_CONVERSIONCURRENCY" content>
+<meta name="Da_cOnVeRsIoNcUrReNcY" content>
+<meta name="da_conversionid" content>
+<meta name="DA_CONVERSIONID" content>
+<meta name="Da_cOnVeRsIoNiD" content>
+<meta name="da_conversionvalue" content>
+<meta name="DA_CONVERSIONVALUE" content>
+<meta name="Da_cOnVeRsIoNvAlUe" content>
+<meta name="da_goalcurrency" content>
+<meta name="DA_GOALCURRENCY" content>
+<meta name="Da_gOaLcUrReNcY" content>
+<meta name="da_goalid" content>
+<meta name="DA_GOALID" content>
+<meta name="Da_gOaLiD" content>
+<meta name="da_goalvalue" content>
+<meta name="DA_GOALVALUE" content>
+<meta name="Da_gOaLvAlUe" content>
+<meta name="da_interactionselector" content>
+<meta name="DA_INTERACTIONSELECTOR" content>
+<meta name="Da_iNtErAcTiOnSeLeCtOr" content>
+<meta name="da_pagerole" content>
+<meta name="DA_PAGEROLE" content>
+<meta name="Da_pAgErOlE" content>
+<meta name="da_pagetaxonomy" content>
+<meta name="DA_PAGETAXONOMY" content>
+<meta name="Da_pAgEtAxOnOmY" content>
+<meta name="da_pagetitle" content>
+<meta name="DA_PAGETITLE" content>
+<meta name="Da_pAgEtItLe" content>
+<meta name="da_pageversion" content>
+<meta name="DA_PAGEVERSION" content>
+<meta name="Da_pAgEvErSiOn" content>
+<meta name="da_sessionid" content>
+<meta name="DA_SESSIONID" content>
+<meta name="Da_sEsSiOnId" content>
+<meta name="da_userid" content>
+<meta name="DA_USERID" content>
+<meta name="Da_uSeRiD" content>
+<meta name="dc.date.issued" content>
+<meta name="DC.DATE.ISSUED" content>
+<meta name="Dc.dAtE.IsSuEd" content>
+<meta name="dc.language" content>
+<meta name="DC.LANGUAGE" content>
+<meta name="Dc.lAnGuAgE" content>
+<meta name="dcterms.abstract" content>
+<meta name="DCTERMS.ABSTRACT" content>
+<meta name="DcTeRmS.AbStRaCt" content>
+<meta name="dcterms.accessrights" content>
+<meta name="DCTERMS.ACCESSRIGHTS" content>
+<meta name="DcTeRmS.AcCeSsRiGhTs" content>
+<meta name="dcterms.accrualmethod" content>
+<meta name="DCTERMS.ACCRUALMETHOD" content>
+<meta name="DcTeRmS.AcCrUaLmEtHoD" content>
+<meta name="dcterms.accrualperiodicity" content>
+<meta name="DCTERMS.ACCRUALPERIODICITY" content>
+<meta name="DcTeRmS.AcCrUaLpErIoDiCiTy" content>
+<meta name="dcterms.accrualpolicy" content>
+<meta name="DCTERMS.ACCRUALPOLICY" content>
+<meta name="DcTeRmS.AcCrUaLpOlIcY" content>
+<meta name="dcterms.alternative" content>
+<meta name="DCTERMS.ALTERNATIVE" content>
+<meta name="DcTeRmS.AlTeRnAtIvE" content>
+<meta name="dcterms.audience" content>
+<meta name="DCTERMS.AUDIENCE" content>
+<meta name="DcTeRmS.AuDiEnCe" content>
+<meta name="dcterms.available" content>
+<meta name="DCTERMS.AVAILABLE" content>
+<meta name="DcTeRmS.AvAiLaBlE" content>
+<meta name="dcterms.bibliographiccitation" content>
+<meta name="DCTERMS.BIBLIOGRAPHICCITATION" content>
+<meta name="DcTeRmS.BiBlIoGrApHiCcItAtIoN" content>
+<meta name="dcterms.collection" content>
+<meta name="DCTERMS.COLLECTION" content>
+<meta name="DcTeRmS.CoLlEcTiOn" content>
+<meta name="dcterms.conformsto" content>
+<meta name="DCTERMS.CONFORMSTO" content>
+<meta name="DcTeRmS.CoNfOrMsTo" content>
+<meta name="dcterms.contributor" content>
+<meta name="DCTERMS.CONTRIBUTOR" content>
+<meta name="DcTeRmS.CoNtRiBuToR" content>
+<meta name="dcterms.coverage" content>
+<meta name="DCTERMS.COVERAGE" content>
+<meta name="DcTeRmS.CoVeRaGe" content>
+<meta name="dcterms.created" content>
+<meta name="DCTERMS.CREATED" content>
+<meta name="DcTeRmS.CrEaTeD" content>
+<meta name="dcterms.creator" content>
+<meta name="DCTERMS.CREATOR" content>
+<meta name="DcTeRmS.CrEaToR" content>
+<meta name="dcterms.date" content>
+<meta name="DCTERMS.DATE" content>
+<meta name="DcTeRmS.DaTe" content>
+<meta name="dcterms.dateaccepted" content>
+<meta name="DCTERMS.DATEACCEPTED" content>
+<meta name="DcTeRmS.DaTeAcCePtEd" content>
+<meta name="dcterms.datecopyrighted" content>
+<meta name="DCTERMS.DATECOPYRIGHTED" content>
+<meta name="DcTeRmS.DaTeCoPyRiGhTeD" content>
+<meta name="dcterms.datesubmitted" content>
+<meta name="DCTERMS.DATESUBMITTED" content>
+<meta name="DcTeRmS.DaTeSuBmItTeD" content>
+<meta name="dcterms.description" content>
+<meta name="DCTERMS.DESCRIPTION" content>
+<meta name="DcTeRmS.DeScRiPtIoN" content>
+<meta name="dcterms.educationlevel" content>
+<meta name="DCTERMS.EDUCATIONLEVEL" content>
+<meta name="DcTeRmS.EdUcAtIoNlEvEl" content>
+<meta name="dcterms.extent" content>
+<meta name="DCTERMS.EXTENT" content>
+<meta name="DcTeRmS.ExTeNt" content>
+<meta name="dcterms.format" content>
+<meta name="DCTERMS.FORMAT" content>
+<meta name="DcTeRmS.FoRmAt" content>
+<meta name="dcterms.hasformat" content>
+<meta name="DCTERMS.HASFORMAT" content>
+<meta name="DcTeRmS.HaSfOrMaT" content>
+<meta name="dcterms.haspart" content>
+<meta name="DCTERMS.HASPART" content>
+<meta name="DcTeRmS.HaSpArT" content>
+<meta name="dcterms.hasversion" content>
+<meta name="DCTERMS.HASVERSION" content>
+<meta name="DcTeRmS.HaSvErSiOn" content>
+<meta name="dcterms.identifier" content>
+<meta name="DCTERMS.IDENTIFIER" content>
+<meta name="DcTeRmS.IdEnTiFiEr" content>
+<meta name="dcterms.instructionalmethod" content>
+<meta name="DCTERMS.INSTRUCTIONALMETHOD" content>
+<meta name="DcTeRmS.InStRuCtIoNaLmEtHoD" content>
+<meta name="dcterms.isformatof" content>
+<meta name="DCTERMS.ISFORMATOF" content>
+<meta name="DcTeRmS.IsFoRmAtOf" content>
+<meta name="dcterms.ispartof" content>
+<meta name="DCTERMS.ISPARTOF" content>
+<meta name="DcTeRmS.IsPaRtOf" content>
+<meta name="dcterms.isreferencedby" content>
+<meta name="DCTERMS.ISREFERENCEDBY" content>
+<meta name="DcTeRmS.IsReFeReNcEdBy" content>
+<meta name="dcterms.isreplacedby" content>
+<meta name="DCTERMS.ISREPLACEDBY" content>
+<meta name="DcTeRmS.IsRePlAcEdBy" content>
+<meta name="dcterms.isrequiredby" content>
+<meta name="DCTERMS.ISREQUIREDBY" content>
+<meta name="DcTeRmS.IsReQuIrEdBy" content>
+<meta name="dcterms.issued" content>
+<meta name="DCTERMS.ISSUED" content>
+<meta name="DcTeRmS.IsSuEd" content>
+<meta name="dcterms.isversionof" content>
+<meta name="DCTERMS.ISVERSIONOF" content>
+<meta name="DcTeRmS.IsVeRsIoNoF" content>
+<meta name="dcterms.language" content>
+<meta name="DCTERMS.LANGUAGE" content>
+<meta name="DcTeRmS.LaNgUaGe" content>
+<meta name="dcterms.license" content>
+<meta name="DCTERMS.LICENSE" content>
+<meta name="DcTeRmS.LiCeNsE" content>
+<meta name="dcterms.mediator" content>
+<meta name="DCTERMS.MEDIATOR" content>
+<meta name="DcTeRmS.MeDiAtOr" content>
+<meta name="dcterms.medium" content>
+<meta name="DCTERMS.MEDIUM" content>
+<meta name="DcTeRmS.MeDiUm" content>
+<meta name="dcterms.modified" content>
+<meta name="DCTERMS.MODIFIED" content>
+<meta name="DcTeRmS.MoDiFiEd" content>
+<meta name="dcterms.provenance" content>
+<meta name="DCTERMS.PROVENANCE" content>
+<meta name="DcTeRmS.PrOvEnAnCe" content>
+<meta name="dcterms.publisher" content>
+<meta name="DCTERMS.PUBLISHER" content>
+<meta name="DcTeRmS.PuBlIsHeR" content>
+<meta name="dcterms.references" content>
+<meta name="DCTERMS.REFERENCES" content>
+<meta name="DcTeRmS.ReFeReNcEs" content>
+<meta name="dcterms.relation" content>
+<meta name="DCTERMS.RELATION" content>
+<meta name="DcTeRmS.ReLaTiOn" content>
+<meta name="dcterms.replaces" content>
+<meta name="DCTERMS.REPLACES" content>
+<meta name="DcTeRmS.RePlAcEs" content>
+<meta name="dcterms.requires" content>
+<meta name="DCTERMS.REQUIRES" content>
+<meta name="DcTeRmS.ReQuIrEs" content>
+<meta name="dcterms.rights" content>
+<meta name="DCTERMS.RIGHTS" content>
+<meta name="DcTeRmS.RiGhTs" content>
+<meta name="dcterms.rightsholder" content>
+<meta name="DCTERMS.RIGHTSHOLDER" content>
+<meta name="DcTeRmS.RiGhTsHoLdEr" content>
+<meta name="dcterms.source" content>
+<meta name="DCTERMS.SOURCE" content>
+<meta name="DcTeRmS.SoUrCe" content>
+<meta name="dcterms.spatial" content>
+<meta name="DCTERMS.SPATIAL" content>
+<meta name="DcTeRmS.SpAtIaL" content>
+<meta name="dcterms.subject" content>
+<meta name="DCTERMS.SUBJECT" content>
+<meta name="DcTeRmS.SuBjEcT" content>
+<meta name="dcterms.tableofcontents" content>
+<meta name="DCTERMS.TABLEOFCONTENTS" content>
+<meta name="DcTeRmS.TaBlEoFcOnTeNtS" content>
+<meta name="dcterms.temporal" content>
+<meta name="DCTERMS.TEMPORAL" content>
+<meta name="DcTeRmS.TeMpOrAl" content>
+<meta name="dcterms.title" content>
+<meta name="DCTERMS.TITLE" content>
+<meta name="DcTeRmS.TiTlE" content>
+<meta name="dcterms.type" content>
+<meta name="DCTERMS.TYPE" content>
+<meta name="DcTeRmS.TyPe" content>
+<meta name="dcterms.valid" content>
+<meta name="DCTERMS.VALID" content>
+<meta name="DcTeRmS.VaLiD" content>
+<meta name="designer" content>
+<meta name="DESIGNER" content>
+<meta name="DeSiGnEr" content>
+<meta name="entity" content>
+<meta name="ENTITY" content>
+<meta name="EnTiTy" content>
+<meta name="essaydirectory" content>
+<meta name="ESSAYDIRECTORY" content>
+<meta name="EsSaYdIrEcToRy" content>
+<meta name="fdse-description" content>
+<meta name="FDSE-DESCRIPTION" content>
+<meta name="FdSe-dEsCrIpTiOn" content>
+<meta name="fdse-index-as" content>
+<meta name="FDSE-INDEX-AS" content>
+<meta name="FdSe-iNdEx-aS" content>
+<meta name="fdse-keywords" content>
+<meta name="FDSE-KEYWORDS" content>
+<meta name="FdSe-kEyWoRdS" content>
+<meta name="fdse-refresh" content>
+<meta name="FDSE-REFRESH" content>
+<meta name="FdSe-rEfReSh" content>
+<meta name="fdse-robots" content>
+<meta name="FDSE-ROBOTS" content>
+<meta name="FdSe-rObOtS" content>
+<meta name="format-detection" content>
+<meta name="FORMAT-DETECTION" content>
+<meta name="FoRmAt-dEtEcTiOn" content>
+<meta name="fragment" content>
+<meta name="FRAGMENT" content>
+<meta name="FrAgMeNt" content>
+<meta name="gcterms.topictaxonomy" content>
+<meta name="GCTERMS.TOPICTAXONOMY" content>
+<meta name="GcTeRmS.ToPiCtAxOnOmY" content>
+<meta name="geo.a1" content>
+<meta name="GEO.A1" content>
+<meta name="GeO.A1" content>
+<meta name="geo.a2" content>
+<meta name="GEO.A2" content>
+<meta name="GeO.A2" content>
+<meta name="geo.a3" content>
+<meta name="GEO.A3" content>
+<meta name="GeO.A3" content>
+<meta name="geo.country" content>
+<meta name="GEO.COUNTRY" content>
+<meta name="GeO.CoUnTrY" content>
+<meta name="geo.lmk" content>
+<meta name="GEO.LMK" content>
+<meta name="GeO.LmK" content>
+<meta name="geo.placename" content>
+<meta name="GEO.PLACENAME" content>
+<meta name="GeO.PlAcEnAmE" content>
+<meta name="geo.position" content>
+<meta name="GEO.POSITION" content>
+<meta name="GeO.PoSiTiOn" content>
+<meta name="geo.region" content>
+<meta name="GEO.REGION" content>
+<meta name="GeO.ReGiOn" content>
+<meta name="globrix.bathrooms" content>
+<meta name="GLOBRIX.BATHROOMS" content>
+<meta name="GlObRiX.BaThRoOmS" content>
+<meta name="globrix.bedrooms" content>
+<meta name="GLOBRIX.BEDROOMS" content>
+<meta name="GlObRiX.BeDrOoMs" content>
+<meta name="globrix.condition" content>
+<meta name="GLOBRIX.CONDITION" content>
+<meta name="GlObRiX.CoNdItIoN" content>
+<meta name="globrix.features" content>
+<meta name="GLOBRIX.FEATURES" content>
+<meta name="GlObRiX.FeAtUrEs" content>
+<meta name="globrix.instruction" content>
+<meta name="GLOBRIX.INSTRUCTION" content>
+<meta name="GlObRiX.InStRuCtIoN" content>
+<meta name="globrix.latitude" content>
+<meta name="GLOBRIX.LATITUDE" content>
+<meta name="GlObRiX.LaTiTuDe" content>
+<meta name="globrix.longitude" content>
+<meta name="GLOBRIX.LONGITUDE" content>
+<meta name="GlObRiX.LoNgItUdE" content>
+<meta name="globrix.outsidespace" content>
+<meta name="GLOBRIX.OUTSIDESPACE" content>
+<meta name="GlObRiX.OuTsIdEsPaCe" content>
+<meta name="globrix.parking" content>
+<meta name="GLOBRIX.PARKING" content>
+<meta name="GlObRiX.PaRkInG" content>
+<meta name="globrix.period" content>
+<meta name="GLOBRIX.PERIOD" content>
+<meta name="GlObRiX.PeRiOd" content>
+<meta name="globrix.poa" content>
+<meta name="GLOBRIX.POA" content>
+<meta name="GlObRiX.PoA" content>
+<meta name="globrix.postcode" content>
+<meta name="GLOBRIX.POSTCODE" content>
+<meta name="GlObRiX.PoStCoDe" content>
+<meta name="globrix.price" content>
+<meta name="GLOBRIX.PRICE" content>
+<meta name="GlObRiX.PrIcE" content>
+<meta name="globrix.priceproximity" content>
+<meta name="GLOBRIX.PRICEPROXIMITY" content>
+<meta name="GlObRiX.PrIcEpRoXiMiTy" content>
+<meta name="globrix.tenure" content>
+<meta name="GLOBRIX.TENURE" content>
+<meta name="GlObRiX.TeNuRe" content>
+<meta name="globrix.type" content>
+<meta name="GLOBRIX.TYPE" content>
+<meta name="GlObRiX.TyPe" content>
+<meta name="globrix.underoffer" content>
+<meta name="GLOBRIX.UNDEROFFER" content>
+<meta name="GlObRiX.UnDeRoFfEr" content>
+<meta name="go-import" content>
+<meta name="GO-IMPORT" content>
+<meta name="Go-iMpOrT" content>
+<meta name="google" content>
+<meta name="GOOGLE" content>
+<meta name="GoOgLe" content>
+<meta name="google-site-verification" content>
+<meta name="GOOGLE-SITE-VERIFICATION" content>
+<meta name="GoOgLe-sItE-VeRiFiCaTiOn" content>
+<meta name="googlebot" content>
+<meta name="GOOGLEBOT" content>
+<meta name="GoOgLeBoT" content>
+<meta name="googlebot-mobile" content>
+<meta name="GOOGLEBOT-MOBILE" content>
+<meta name="GoOgLeBoT-MoBiLe" content>
+<meta name="gwt:property" content>
+<meta name="GWT:PROPERTY" content>
+<meta name="GwT:PrOpErTy" content>
+<meta name="handheldfriendly" content>
+<meta name="HANDHELDFRIENDLY" content>
+<meta name="HaNdHeLdFrIeNdLy" content>
+<meta name="icas.datetime" content>
+<meta name="ICAS.DATETIME" content>
+<meta name="IcAs.dAtEtImE" content>
+<meta name="icas.datetime.abbr" content>
+<meta name="ICAS.DATETIME.ABBR" content>
+<meta name="IcAs.dAtEtImE.AbBr" content>
+<meta name="icas.datetime.day" content>
+<meta name="ICAS.DATETIME.DAY" content>
+<meta name="IcAs.dAtEtImE.DaY" content>
+<meta name="icas.datetime.long" content>
+<meta name="ICAS.DATETIME.LONG" content>
+<meta name="IcAs.dAtEtImE.LoNg" content>
+<meta name="icbm" content>
+<meta name="ICBM" content>
+<meta name="IcBm" content>
+<meta name="itemsperpage" content>
+<meta name="ITEMSPERPAGE" content>
+<meta name="ItEmSpErPaGe" content>
+<meta name="meta_date" content>
+<meta name="META_DATE" content>
+<meta name="MeTa_dAtE" content>
+<meta name="mobile-agent" content>
+<meta name="MOBILE-AGENT" content>
+<meta name="MoBiLe-aGeNt" content>
+<meta name="mobile-web-app-capable" content>
+<meta name="MOBILE-WEB-APP-CAPABLE" content>
+<meta name="MoBiLe-wEb-aPp-cApAbLe" content>
+<meta name="mobileoptimized" content>
+<meta name="MOBILEOPTIMIZED" content>
+<meta name="MoBiLeOpTiMiZeD" content>
+<meta name="msapplication-config" content>
+<meta name="MSAPPLICATION-CONFIG" content>
+<meta name="MsApPlIcAtIoN-CoNfIg" content>
+<meta name="msapplication-navbutton-color" content>
+<meta name="MSAPPLICATION-NAVBUTTON-COLOR" content>
+<meta name="MsApPlIcAtIoN-NaVbUtToN-CoLoR" content>
+<meta name="msapplication-square150x150logo" content>
+<meta name="MSAPPLICATION-SQUARE150X150LOGO" content>
+<meta name="MsApPlIcAtIoN-SqUaRe150x150lOgO" content>
+<meta name="msapplication-square310x310logo" content>
+<meta name="MSAPPLICATION-SQUARE310X310LOGO" content>
+<meta name="MsApPlIcAtIoN-SqUaRe310x310lOgO" content>
+<meta name="msapplication-square70x70logo" content>
+<meta name="MSAPPLICATION-SQUARE70X70LOGO" content>
+<meta name="MsApPlIcAtIoN-SqUaRe70X70lOgO" content>
+<meta name="msapplication-starturl" content>
+<meta name="MSAPPLICATION-STARTURL" content>
+<meta name="MsApPlIcAtIoN-StArTuRl" content>
+<meta name="msapplication-tap-highlight" content>
+<meta name="MSAPPLICATION-TAP-HIGHLIGHT" content>
+<meta name="MsApPlIcAtIoN-TaP-HiGhLiGhT" content>
+<meta name="msapplication-task" content>
+<meta name="MSAPPLICATION-TASK" content>
+<meta name="MsApPlIcAtIoN-TaSk" content>
+<meta name="msapplication-tilecolor" content>
+<meta name="MSAPPLICATION-TILECOLOR" content>
+<meta name="MsApPlIcAtIoN-TiLeCoLoR" content>
+<meta name="msapplication-tileimage" content>
+<meta name="MSAPPLICATION-TILEIMAGE" content>
+<meta name="MsApPlIcAtIoN-TiLeImAgE" content>
+<meta name="msapplication-tooltip" content>
+<meta name="MSAPPLICATION-TOOLTIP" content>
+<meta name="MsApPlIcAtIoN-ToOlTiP" content>
+<meta name="msapplication-wide310x150logo" content>
+<meta name="MSAPPLICATION-WIDE310X150LOGO" content>
+<meta name="MsApPlIcAtIoN-WiDe310x150lOgO" content>
+<meta name="msapplication-window" content>
+<meta name="MSAPPLICATION-WINDOW" content>
+<meta name="MsApPlIcAtIoN-WiNdOw" content>
+<meta name="msvalidate.01" content>
+<meta name="MSVALIDATE.01" content>
+<meta name="MsVaLiDaTe.01" content>
+<meta name="norton-safeweb-site-verification" content>
+<meta name="NORTON-SAFEWEB-SITE-VERIFICATION" content>
+<meta name="NoRtOn-sAfEwEb-sItE-VeRiFiCaTiOn" content>
+<meta name="p:domain_verify" content>
+<meta name="P:DOMAIN_VERIFY" content>
+<meta name="P:DoMaIn_vErIfY" content>
+<meta name="pingdom" content>
+<meta name="PINGDOM" content>
+<meta name="PiNgDoM" content>
+<meta name="pinterest" content>
+<meta name="PINTEREST" content>
+<meta name="PiNtErEsT" content>
+<meta name="rating" content>
+<meta name="RATING" content>
+<meta name="RaTiNg" content>
+<meta name="referrer" content>
+<meta name="REFERRER" content>
+<meta name="ReFeRrEr" content>
+<meta name="repostusapikey" content>
+<meta name="REPOSTUSAPIKEY" content>
+<meta name="RePoStUsApIkEy" content>
+<meta name="resourceloaderdynamicstyles" content>
+<meta name="RESOURCELOADERDYNAMICSTYLES" content>
+<meta name="ReSoUrCeLoAdErDyNaMiCsTyLeS" content>
+<meta name="review_date" content>
+<meta name="REVIEW_DATE" content>
+<meta name="ReViEw_dAtE" content>
+<meta name="revision" content>
+<meta name="REVISION" content>
+<meta name="ReViSiOn" content>
+<meta name="revisit-after" content>
+<meta name="REVISIT-AFTER" content>
+<meta name="ReViSiT-AfTeR" content>
+<meta name="rights-standard" content>
+<meta name="RIGHTS-STANDARD" content>
+<meta name="RiGhTs-sTaNdArD" content>
+<meta name="robots" content>
+<meta name="ROBOTS" content>
+<meta name="RoBoTs" content>
+<meta name="rpuplugin" content>
+<meta name="RPUPLUGIN" content>
+<meta name="RpUpLuGiN" content>
+<meta name="rqid" content>
+<meta name="RQID" content>
+<meta name="RqId" content>
+<meta name="signet:authors" content>
+<meta name="SIGNET:AUTHORS" content>
+<meta name="SiGnEt:aUtHoRs" content>
+<meta name="signet:links" content>
+<meta name="SIGNET:LINKS" content>
+<meta name="SiGnEt:lInKs" content>
+<meta name="skype_toolbar" content>
+<meta name="SKYPE_TOOLBAR" content>
+<meta name="SkYpE_ToOlBaR" content>
+<meta name="slurp" content>
+<meta name="SLURP" content>
+<meta name="SlUrP" content>
+<meta name="startindex" content>
+<meta name="STARTINDEX" content>
+<meta name="StArTiNdEx" content>
+<meta name="startver" content>
+<meta name="STARTVER" content>
+<meta name="StArTvEr" content>
+<meta name="teoma" content>
+<meta name="TEOMA" content>
+<meta name="TeOmA" content>
+<meta name="totalresults" content>
+<meta name="TOTALRESULTS" content>
+<meta name="ToTaLrEsUlTs" content>
+<meta name="twitter:app:country" content>
+<meta name="TWITTER:APP:COUNTRY" content>
+<meta name="TwItTeR:ApP:CoUnTrY" content>
+<meta name="twitter:app:id:googleplay" content>
+<meta name="TWITTER:APP:ID:GOOGLEPLAY" content>
+<meta name="TwItTeR:ApP:Id:gOoGlEpLaY" content>
+<meta name="twitter:app:id:ipad" content>
+<meta name="TWITTER:APP:ID:IPAD" content>
+<meta name="TwItTeR:ApP:Id:iPaD" content>
+<meta name="twitter:app:id:iphone" content>
+<meta name="TWITTER:APP:ID:IPHONE" content>
+<meta name="TwItTeR:ApP:Id:iPhOnE" content>
+<meta name="twitter:app:url:googleplay" content>
+<meta name="TWITTER:APP:URL:GOOGLEPLAY" content>
+<meta name="TwItTeR:ApP:UrL:GoOgLePlAy" content>
+<meta name="twitter:app:url:ipad" content>
+<meta name="TWITTER:APP:URL:IPAD" content>
+<meta name="TwItTeR:ApP:UrL:IpAd" content>
+<meta name="twitter:app:url:iphone" content>
+<meta name="TWITTER:APP:URL:IPHONE" content>
+<meta name="TwItTeR:ApP:UrL:IpHoNe" content>
+<meta name="twitter:card" content>
+<meta name="TWITTER:CARD" content>
+<meta name="TwItTeR:CaRd" content>
+<meta name="twitter:creator" content>
+<meta name="TWITTER:CREATOR" content>
+<meta name="TwItTeR:CrEaToR" content>
+<meta name="twitter:creator:id" content>
+<meta name="TWITTER:CREATOR:ID" content>
+<meta name="TwItTeR:CrEaToR:Id" content>
+<meta name="twitter:description" content>
+<meta name="TWITTER:DESCRIPTION" content>
+<meta name="TwItTeR:DeScRiPtIoN" content>
+<meta name="twitter:domain" content>
+<meta name="TWITTER:DOMAIN" content>
+<meta name="TwItTeR:DoMaIn" content>
+<meta name="twitter:image" content>
+<meta name="TWITTER:IMAGE" content>
+<meta name="TwItTeR:ImAgE" content>
+<meta name="twitter:image0" content>
+<meta name="TWITTER:IMAGE0" content>
+<meta name="TwItTeR:ImAgE0" content>
+<meta name="twitter:image1" content>
+<meta name="TWITTER:IMAGE1" content>
+<meta name="TwItTeR:ImAgE1" content>
+<meta name="twitter:image2" content>
+<meta name="TWITTER:IMAGE2" content>
+<meta name="TwItTeR:ImAgE2" content>
+<meta name="twitter:image3" content>
+<meta name="TWITTER:IMAGE3" content>
+<meta name="TwItTeR:ImAgE3" content>
+<meta name="twitter:image:height" content>
+<meta name="TWITTER:IMAGE:HEIGHT" content>
+<meta name="TwItTeR:ImAgE:HeIgHt" content>
+<meta name="twitter:image:src" content>
+<meta name="TWITTER:IMAGE:SRC" content>
+<meta name="TwItTeR:ImAgE:SrC" content>
+<meta name="twitter:image:width" content>
+<meta name="TWITTER:IMAGE:WIDTH" content>
+<meta name="TwItTeR:ImAgE:WiDtH" content>
+<meta name="twitter:site" content>
+<meta name="TWITTER:SITE" content>
+<meta name="TwItTeR:SiTe" content>
+<meta name="twitter:site:id" content>
+<meta name="TWITTER:SITE:ID" content>
+<meta name="TwItTeR:SiTe:iD" content>
+<meta name="twitter:title" content>
+<meta name="TWITTER:TITLE" content>
+<meta name="TwItTeR:TiTlE" content>
+<meta name="twitter:url" content>
+<meta name="TWITTER:URL" content>
+<meta name="TwItTeR:UrL" content>
+<meta name="typemetal.formatprefs" content>
+<meta name="TYPEMETAL.FORMATPREFS" content>
+<meta name="TyPeMeTaL.FoRmAtPrEfS" content>
+<meta name="verify-v1" content>
+<meta name="VERIFY-V1" content>
+<meta name="VeRiFy-v1" content>
+<meta name="vfb-version" content>
+<meta name="VFB-VERSION" content>
+<meta name="VfB-VeRsIoN" content>
+<meta name="viewport" content>
+<meta name="VIEWPORT" content>
+<meta name="ViEwPoRt" content>
+<meta name="web_author" content>
+<meta name="WEB_AUTHOR" content>
+<meta name="WeB_AuThOr" content>
+<meta name="wot-verification" content>
+<meta name="WOT-VERIFICATION" content>
+<meta name="WoT-VeRiFiCaTiOn" content>
+<meta name="wt.ac" content>
+<meta name="WT.AC" content>
+<meta name="Wt.aC" content>
+<meta name="wt.ad" content>
+<meta name="WT.AD" content>
+<meta name="Wt.aD" content>
+<meta name="wt.cg_n" content>
+<meta name="WT.CG_N" content>
+<meta name="Wt.cG_N" content>
+<meta name="wt.cg_s" content>
+<meta name="WT.CG_S" content>
+<meta name="Wt.cG_S" content>
+<meta name="wt.mc_id" content>
+<meta name="WT.MC_ID" content>
+<meta name="Wt.mC_Id" content>
+<meta name="wt.si_n" content>
+<meta name="WT.SI_N" content>
+<meta name="Wt.sI_N" content>
+<meta name="wt.si_p" content>
+<meta name="WT.SI_P" content>
+<meta name="Wt.sI_P" content>
+<meta name="wt.si_x" content>
+<meta name="WT.SI_X" content>
+<meta name="Wt.sI_X" content>
+<meta name="wt.sv" content>
+<meta name="WT.SV" content>
+<meta name="Wt.sV" content>
+<meta name="wt.ti" content>
+<meta name="WT.TI" content>
+<meta name="Wt.tI" content>
+<meta name="y_key" content>
+<meta name="Y_KEY" content>
+<meta name="Y_KeY" content>
+<meta name="yandex-verification" content>
+<meta name="YANDEX-VERIFICATION" content>
+<meta name="YaNdEx-vErIfIcAtIoN" content>
+<meta name="zoomcategory" content>
+<meta name="ZOOMCATEGORY" content>
+<meta name="ZoOmCaTeGoRy" content>
+<meta name="zoomdescription" content>
+<meta name="ZOOMDESCRIPTION" content>
+<meta name="ZoOmDeScRiPtIoN" content>
+<meta name="zoomimage" content>
+<meta name="ZOOMIMAGE" content>
+<meta name="ZoOmImAgE" content>
+<meta name="zoompageboost" content>
+<meta name="ZOOMPAGEBOOST" content>
+<meta name="ZoOmPaGeBoOsT" content>
+<meta name="zoomtitle" content>
+<meta name="ZOOMTITLE" content>
+<meta name="ZoOmTiTlE" content>
+<meta name="zoomwords" content>
+<meta name="ZOOMWORDS" content>
+<meta name="ZoOmWoRdS" content>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/meta/names-standard-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/meta/names-standard-isvalid.html
new file mode 100644
index 00000000000..738af2a9dd8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/meta/names-standard-isvalid.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Standard metadata names</title>
+<!-- all lowercase-->
+<meta name="application-name" content>
+<meta name="author" content>
+<meta name="description" content>
+<meta name="generator" content>
+<meta name="keywords" content>
+<!-- all uppercase -->
+<meta name="APPLICATION-NAME" content>
+<meta name="AUTHOR" content>
+<meta name="DESCRIPTION" content>
+<meta name="GENERATOR" content>
+<meta name="KEYWORDS" content>
+<!-- mixed case -->
+<meta name="aPplIcAtioN-nAmE" content>
+<meta name="AUtHOr" content>
+<meta name="dEScrIpTiON" content>
+<meta name="GEneRatoR" content>
+<meta name="kEyWoRDs" content>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/meta/refresh-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/meta/refresh-isvalid.html
new file mode 100644
index 00000000000..8b3f499690f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/meta/refresh-isvalid.html
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid meta refresh</title>
+<meta http-equiv=refresh content="0; URL=file:///"><!-- scheme-file-slash-slash-slash-only -->
+<meta http-equiv=refresh content="0; URL=http://a:@www.example.com"><!-- userinfo-password-empty -->
+<meta http-equiv=refresh content="0; URL=foo://///////"><!-- scheme-private-path-leading-slashes-only -->
+<meta http-equiv=refresh content="0; URL=file://abc|/foo/bar"><!-- scheme-file-slash-slash-abc-bar -->
+<meta http-equiv=refresh content="0; URL=/a/b/c"><!-- path-simple-relative -->
+<meta http-equiv=refresh content="0; URL=http://example.com/你好你好"><!-- path-unicode-han -->
+<meta http-equiv=refresh content="0; URL=/a/%2f/c"><!-- path-percent-encoded-slash-plus-slashes-relative -->
+<meta http-equiv=refresh content="0; URL=http://f:/c"><!-- port-none-but-colon -->
+<meta http-equiv=refresh content="0; URL=http://example.com/foo%41%7a"><!-- path-percent-encoded-multiple -->
+<meta http-equiv=refresh content="0; URL=http://192.168.0.257/"><!-- host-IP-address-broken -->
+<meta http-equiv=refresh content="0; URL=madeupscheme:example.com/"><!-- scheme-private-no-slash -->
+<meta http-equiv=refresh content="0; URL=?"><!-- query-empty-no-path-relative -->
+<meta http-equiv=refresh content="0; URL=http://example.com/%20foo"><!-- path-percent-encoded-space -->
+<meta http-equiv=refresh content="0; URL=mailto:/example.com/"><!-- scheme-mailto-single-slash -->
+<meta http-equiv=refresh content="0; URL=::"><!-- path-leading-colon-colon-relative -->
+<meta http-equiv=refresh content="0; URL=http://example.com/%3A%3a%3C%3c"><!-- path-percent-encoded-mixed-case -->
+<meta http-equiv=refresh content="0; URL=http://user:pass@foo:21/bar;par?b#c"><!-- userinfo -->
+<meta http-equiv=refresh content="0; URL=ws:/example.com/"><!-- scheme-ws-single-slash -->
+<meta http-equiv=refresh content="0; URL=foo://"><!-- scheme-private-slash-slash -->
+<meta http-equiv=refresh content="0; URL=#"><!-- fragment-empty-hash-only-no-path-relative -->
+<meta http-equiv=refresh content="0; URL=http://f:00000000000000/c"><!-- port-00000000000000 -->
+<meta http-equiv=refresh content="0; URL=foo:////://///"><!-- scheme-private-path-leading-slashes-colon-slashes -->
+<meta http-equiv=refresh content="0; URL=:23"><!-- path-leading-colon-number-relative -->
+<meta http-equiv=refresh content="0; URL=foo:/"><!-- scheme-private-slash -->
+<meta http-equiv=refresh content="0; URL=http://💩"><!-- host-is-pile-of-poo -->
+<meta http-equiv=refresh content="0; URL=file:test"><!-- scheme-file-no-slash -->
+<meta http-equiv=refresh content="0; URL=file://C|/foo/bar"><!-- scheme-file-slash-slash-c-bar -->
+<meta http-equiv=refresh content="0; URL=#/"><!-- fragment-slash-relative -->
+<meta http-equiv=refresh content="0; URL=http://192.0x00A80001"><!-- host-192.0x00A80001 -->
+<meta http-equiv=refresh content="0; URL=foo.com"><!-- scheme-none-relative -->
+<meta http-equiv=refresh content="0; URL=http💩//:foo"><!-- path-contains-pile-of-poo -->
+<meta http-equiv=refresh content="0; URL=File://foo/bar.html"><!-- scheme-file-uppercase -->
+<meta http-equiv=refresh content="0; URL=:/"><!-- path-leading-colon-slash-relative -->
+<meta http-equiv=refresh content="0; URL=http://www.foo。bar.com"><!-- host-exotic-dot -->
+<meta http-equiv=refresh content="0; URL=http://GOO​⁠goo.com"><!-- host-exotic-whitespace -->
+<meta http-equiv=refresh content="0; URL=file:///foo/bar.txt"><!-- scheme-file-host-empty -->
+<meta http-equiv=refresh content="0; URL=javascript:/example.com/"><!-- scheme-javascript-single-slash -->
+<meta http-equiv=refresh content="0; URL=gopher:/example.com/"><!-- scheme-gopher-single-slash -->
+<meta http-equiv=refresh content="0; URL=ftps:example.com/"><!-- scheme-ftps-no-slash -->
+<meta http-equiv=refresh content="0; URL=file://server/foo/bar"><!-- scheme-file-host-included -->
+<meta http-equiv=refresh content="0; URL=http://example.com/foo%00"><!-- path-percent-encoded-u0000 -->
+<meta http-equiv=refresh content="0; URL=a:foo.com"><!-- scheme-private -->
+<meta http-equiv=refresh content="0; URL=:"><!-- path-colon-relative -->
+<meta http-equiv=refresh content="0; URL=http://:b@www.example.com"><!-- userinfo-user-empty -->
+<meta http-equiv=refresh content="0; URL=file:/"><!-- scheme-file-slash-only -->
+<meta http-equiv=refresh content="0; URL=wss:example.com/"><!-- scheme-wss-no-slash -->
+<meta http-equiv=refresh content="0; URL=::23"><!-- path-colon-colon-number-relative -->
+<meta http-equiv=refresh content="0; URL=/a%2fc"><!-- path-percent-encoded-slash-relative -->
+<meta http-equiv=refresh content="0; URL=http://a:b@c:29/d"><!-- userinfo-host-port-path -->
+<meta http-equiv=refresh content="0; URL=gopher:example.com/"><!-- scheme-gopher-no-slash -->
+<meta http-equiv=refresh content="0; URL=madeupscheme:/example.com/"><!-- scheme-private-single-slash -->
+<meta http-equiv=refresh content="0; URL=mailto:example.com/"><!-- scheme-mailto-no-slash -->
+<meta http-equiv=refresh content="0; URL=http://%25DOMAIN:foobar@foodomain.com"><!-- userinfo-username-contains-percent-encoded -->
+<meta http-equiv=refresh content="0; URL=/:23"><!-- path-slash-colon-number-relative -->
+<meta http-equiv=refresh content="0; URL=foo://///////bar.com/"><!-- scheme-private-path-leading-slashes-chars -->
+<meta http-equiv=refresh content="0; URL=http://[2001::1]:80"><!-- host-ipv6-port -->
+<meta http-equiv=refresh content="0; URL=data:text/plain,foo"><!-- scheme-data-no-slash -->
+<meta http-equiv=refresh content="0; URL=http://example.com/foo/%2e"><!-- path-percent-encoded-dot -->
+<meta http-equiv=refresh content="0; URL=file:/example.com/"><!-- scheme-file-single-slash -->
+<meta http-equiv=refresh content="0; URL=http://example.com/©zbar"><!-- path-non-ascii -->
+<meta http-equiv=refresh content="0; URL=http://example.com//foo"><!-- path-uFEFF -->
+<meta http-equiv=refresh content="0; URL=wss:/example.com/"><!-- scheme-wss-single-slash -->
+<meta http-equiv=refresh content="0; URL=http://foo/abcd#foo?bar"><!-- fragment-contains-question-mark -->
+<meta http-equiv=refresh content="0; URL=:#"><!-- path-leading-colon-hash-relative -->
+<meta http-equiv=refresh content="0; URL=http://example.com/foo%91"><!-- path-percent-encoded-u0091 -->
+<meta http-equiv=refresh content="0; URL=c:/foo"><!-- scheme-private-single-letter -->
+<meta http-equiv=refresh content="0; URL=:foo.com"><!-- path-leading-colon-chars-relative -->
+<meta http-equiv=refresh content="0; URL=http://你好你好"><!-- host-idn-unicode-han -->
+<meta http-equiv=refresh content="0; URL=http://example.com/foo#💩"><!-- fragment-contains-pile-of-poo -->
+<meta http-equiv=refresh content="0; URL=file:"><!-- scheme-file-scheme-only -->
+<meta http-equiv=refresh content="0; URL=#β"><!-- fragment-non-ascii-relative -->
+<meta http-equiv=refresh content="0; URL=foo:/bar.com/"><!-- scheme-private-path -->
+<meta http-equiv=refresh content="0; URL=http://f:0/c"><!-- port-0 -->
+<meta http-equiv=refresh content="0; URL=#;?"><!-- fragment-semicolon-question-mark-relative -->
+<meta http-equiv=refresh content="0; URL=http://Go.com"><!-- host-fullwidth -->
+<meta http-equiv=refresh content="0; URL=http://@www.example.com"><!-- userinfo-empty -->
+<meta http-equiv=refresh content="0; URL=http://example.com/‮/foo/‭/bar"><!-- path-u202E-u202D -->
+<meta http-equiv=refresh content="0; URL=http://[2001::1]"><!-- host-ipv6 -->
+<meta http-equiv=refresh content="0; URL=💩http://foo"><!-- path-starts-with-pile-of-poo -->
+<meta http-equiv=refresh content="0; URL=http://foo/abcd?efgh?ijkl"><!-- query-contains-question-mark -->
+<meta http-equiv=refresh content="0; URL=//foo/bar"><!-- scheme-schemeless-relative -->
+<meta http-equiv=refresh content="0; URL=ftps:/example.com/"><!-- scheme-ftps-single-slash -->
+<meta http-equiv=refresh content="0; URL=http://foo.com:b@d/"><!-- userinfo-username-non-alpha -->
+<meta http-equiv=refresh content="0; URL=:a"><!-- path-leading-colon-letter-relative -->
+<meta http-equiv=refresh content="0; URL=/"><!-- path-slash-only-relative -->
+<meta http-equiv=refresh content="0; URL=http://example.com/foo?💩"><!-- query-contains-pile-of-poo -->
+<meta http-equiv=refresh content="0; URL=http://f:00000000000000000000080/c"><!-- port-00000000000000000000080 -->
+<meta http-equiv=refresh content="0; URL=file://"><!-- scheme-file-slash-slash-only -->
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/noscript/model-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/noscript/model-isvalid.html
new file mode 100644
index 00000000000..6d74e762b44
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/noscript/model-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <noscript><style></style></noscript>
+ <meta charset=utf-8>
+ <title>&lt;noscript&gt; in &lt;head&gt;</title>
+</head>
+<body>
+<p>foo</p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data-empty-novalid.html
new file mode 100644
index 00000000000..ffa455f9fe7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>empty data is not valid</title>
+<object data=""></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data-isvalid.html
new file mode 100644
index 00000000000..a4b3d4fbacd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data-isvalid.html
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid data</title>
+<object data="file:///"></object><!-- scheme-file-slash-slash-slash-only -->
+<object data="http://a:@www.example.com"></object><!-- userinfo-password-empty -->
+<object data="foo://///////"></object><!-- scheme-private-path-leading-slashes-only -->
+<object data="file://abc|/foo/bar"></object><!-- scheme-file-slash-slash-abc-bar -->
+<object data="/a/b/c"></object><!-- path-simple-relative -->
+<object data="http://example.com/你好你好"></object><!-- path-unicode-han -->
+<object data="/a/%2f/c"></object><!-- path-percent-encoded-slash-plus-slashes-relative -->
+<object data="http://f:/c"></object><!-- port-none-but-colon -->
+<object data="http://example.com/foo%41%7a"></object><!-- path-percent-encoded-multiple -->
+<object data="http://192.168.0.257/"></object><!-- host-IP-address-broken -->
+<object data="madeupscheme:example.com/"></object><!-- scheme-private-no-slash -->
+<object data="?"></object><!-- query-empty-no-path-relative -->
+<object data="http://example.com/%20foo"></object><!-- path-percent-encoded-space -->
+<object data="mailto:/example.com/"></object><!-- scheme-mailto-single-slash -->
+<object data="::"></object><!-- path-leading-colon-colon-relative -->
+<object data="http://example.com/%3A%3a%3C%3c"></object><!-- path-percent-encoded-mixed-case -->
+<object data="http://user:pass@foo:21/bar;par?b#c"></object><!-- userinfo -->
+<object data="ws:/example.com/"></object><!-- scheme-ws-single-slash -->
+<object data="foo://"></object><!-- scheme-private-slash-slash -->
+<object data="#"></object><!-- fragment-empty-hash-only-no-path-relative -->
+<object data="http://f:00000000000000/c"></object><!-- port-00000000000000 -->
+<object data="foo:////://///"></object><!-- scheme-private-path-leading-slashes-colon-slashes -->
+<object data=":23"></object><!-- path-leading-colon-number-relative -->
+<object data="foo:/"></object><!-- scheme-private-slash -->
+<object data="http://💩"></object><!-- host-is-pile-of-poo -->
+<object data="file:test"></object><!-- scheme-file-no-slash -->
+<object data="file://C|/foo/bar"></object><!-- scheme-file-slash-slash-c-bar -->
+<object data="#/"></object><!-- fragment-slash-relative -->
+<object data="http://192.0x00A80001"></object><!-- host-192.0x00A80001 -->
+<object data="foo.com"></object><!-- scheme-none-relative -->
+<object data="http💩//:foo"></object><!-- path-contains-pile-of-poo -->
+<object data="File://foo/bar.html"></object><!-- scheme-file-uppercase -->
+<object data=":/"></object><!-- path-leading-colon-slash-relative -->
+<object data="http://www.foo。bar.com"></object><!-- host-exotic-dot -->
+<object data="http://GOO​⁠goo.com"></object><!-- host-exotic-whitespace -->
+<object data="file:///foo/bar.txt"></object><!-- scheme-file-host-empty -->
+<object data="javascript:/example.com/"></object><!-- scheme-javascript-single-slash -->
+<object data="gopher:/example.com/"></object><!-- scheme-gopher-single-slash -->
+<object data="ftps:example.com/"></object><!-- scheme-ftps-no-slash -->
+<object data="file://server/foo/bar"></object><!-- scheme-file-host-included -->
+<object data="http://example.com/foo%00"></object><!-- path-percent-encoded-u0000 -->
+<object data="a:foo.com"></object><!-- scheme-private -->
+<object data=":"></object><!-- path-colon-relative -->
+<object data="http://:b@www.example.com"></object><!-- userinfo-user-empty -->
+<object data="file:/"></object><!-- scheme-file-slash-only -->
+<object data="wss:example.com/"></object><!-- scheme-wss-no-slash -->
+<object data="::23"></object><!-- path-colon-colon-number-relative -->
+<object data="/a%2fc"></object><!-- path-percent-encoded-slash-relative -->
+<object data="http://a:b@c:29/d"></object><!-- userinfo-host-port-path -->
+<object data="gopher:example.com/"></object><!-- scheme-gopher-no-slash -->
+<object data="madeupscheme:/example.com/"></object><!-- scheme-private-single-slash -->
+<object data="mailto:example.com/"></object><!-- scheme-mailto-no-slash -->
+<object data="http://%25DOMAIN:foobar@foodomain.com"></object><!-- userinfo-username-contains-percent-encoded -->
+<object data="/:23"></object><!-- path-slash-colon-number-relative -->
+<object data="foo://///////bar.com/"></object><!-- scheme-private-path-leading-slashes-chars -->
+<object data="http://[2001::1]:80"></object><!-- host-ipv6-port -->
+<object data="data:text/plain,foo"></object><!-- scheme-data-no-slash -->
+<object data="http://example.com/foo/%2e"></object><!-- path-percent-encoded-dot -->
+<object data="file:/example.com/"></object><!-- scheme-file-single-slash -->
+<object data="http://example.com/©zbar"></object><!-- path-non-ascii -->
+<object data="http://example.com//foo"></object><!-- path-uFEFF -->
+<object data="wss:/example.com/"></object><!-- scheme-wss-single-slash -->
+<object data="http://foo/abcd#foo?bar"></object><!-- fragment-contains-question-mark -->
+<object data=":#"></object><!-- path-leading-colon-hash-relative -->
+<object data="http://example.com/foo%91"></object><!-- path-percent-encoded-u0091 -->
+<object data="c:/foo"></object><!-- scheme-private-single-letter -->
+<object data=":foo.com"></object><!-- path-leading-colon-chars-relative -->
+<object data="http://你好你好"></object><!-- host-idn-unicode-han -->
+<object data="http://example.com/foo#💩"></object><!-- fragment-contains-pile-of-poo -->
+<object data="file:"></object><!-- scheme-file-scheme-only -->
+<object data="#β"></object><!-- fragment-non-ascii-relative -->
+<object data="foo:/bar.com/"></object><!-- scheme-private-path -->
+<object data="http://f:0/c"></object><!-- port-0 -->
+<object data="#;?"></object><!-- fragment-semicolon-question-mark-relative -->
+<object data="http://Go.com"></object><!-- host-fullwidth -->
+<object data="http://@www.example.com"></object><!-- userinfo-empty -->
+<object data="http://example.com/‮/foo/‭/bar"></object><!-- path-u202E-u202D -->
+<object data="http://[2001::1]"></object><!-- host-ipv6 -->
+<object data="💩http://foo"></object><!-- path-starts-with-pile-of-poo -->
+<object data="http://foo/abcd?efgh?ijkl"></object><!-- query-contains-question-mark -->
+<object data="//foo/bar"></object><!-- scheme-schemeless-relative -->
+<object data="ftps:/example.com/"></object><!-- scheme-ftps-single-slash -->
+<object data="http://foo.com:b@d/"></object><!-- userinfo-username-non-alpha -->
+<object data=":a"></object><!-- path-leading-colon-letter-relative -->
+<object data="/"></object><!-- path-slash-only-relative -->
+<object data="http://example.com/foo?💩"></object><!-- query-contains-pile-of-poo -->
+<object data="http://f:00000000000000000000080/c"></object><!-- port-00000000000000000000080 -->
+<object data="file://"></object><!-- scheme-file-slash-slash-only -->
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data-type-missing-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data-type-missing-novalid.html
new file mode 100644
index 00000000000..03f84f90448
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data-type-missing-novalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta charset=utf-8>
+<title>object element missing data and type attribute</title>
+</head>
+<body>
+<object></object>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data-whitespace-only-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data-whitespace-only-novalid.html
new file mode 100644
index 00000000000..26b77fd4679
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data-whitespace-only-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>empty data is not valid</title>
+<object data="
+"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/fragment-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/fragment-backslash-novalid.html
new file mode 100644
index 00000000000..db712e2482c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/fragment-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: fragment-backslash</title>
+<object data="#\"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/fragment-contains-hash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/fragment-contains-hash-novalid.html
new file mode 100644
index 00000000000..91c15319776
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/fragment-contains-hash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: fragment-contains-hash</title>
+<object data="http://foo/path#f#g"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/fragment-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/fragment-leading-space-novalid.html
new file mode 100644
index 00000000000..bf09cca1ae5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/fragment-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: fragment-leading-space</title>
+<object data="http://f:21/b# e"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-cr-novalid.html
new file mode 100644
index 00000000000..0d834e8da02
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: host-cr</title>
+<object data="http://example. org"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-double-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-double-percent-encoded-novalid.html
new file mode 100644
index 00000000000..d9f6ead7a0a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-double-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: host-double-percent-encoded</title>
+<object data="http://%41.com"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-double-percent-encoded-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-double-percent-encoded-percent-encoded-novalid.html
new file mode 100644
index 00000000000..7bcff83e1e5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-double-percent-encoded-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: host-double-percent-encoded-percent-encoded</title>
+<object data="http://%ef%bc%85%ef%bc%94%ef%bc%91.com"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-empty-novalid.html
new file mode 100644
index 00000000000..2e2d6d84a79
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: host-empty</title>
+<object data="http://"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-empty-userinfo-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-empty-userinfo-empty-novalid.html
new file mode 100644
index 00000000000..db6dc05564b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-empty-userinfo-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: host-empty-userinfo-empty</title>
+<object data="http://@/www.example.com"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-empty-with-userinfo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-empty-with-userinfo-novalid.html
new file mode 100644
index 00000000000..a468c3743c0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-empty-with-userinfo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: host-empty-with-userinfo</title>
+<object data="http://user:pass@/"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-hostname-in-brackets-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-hostname-in-brackets-novalid.html
new file mode 100644
index 00000000000..64388a6a5cb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-hostname-in-brackets-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: host-hostname-in-brackets</title>
+<object data="http://[www.google.com]/"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-invalid-unicode-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-invalid-unicode-novalid.html
new file mode 100644
index 00000000000..ee26451bfbb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-invalid-unicode-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: host-invalid-unicode</title>
+<object data="http://﷐zyx.com"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-invalid-unicode-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-invalid-unicode-percent-encoded-novalid.html
new file mode 100644
index 00000000000..600c40146c3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-invalid-unicode-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: host-invalid-unicode-percent-encoded</title>
+<object data="http://%ef%b7%90zyx.com"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-newline-novalid.html
new file mode 100644
index 00000000000..9cda7a1ccab
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: host-newline</title>
+<object data="http://example.
+org"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-space-novalid.html
new file mode 100644
index 00000000000..24ee0daf46f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: host-space</title>
+<object data="http://example .org"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-square-brackets-port-contains-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-square-brackets-port-contains-colon-novalid.html
new file mode 100644
index 00000000000..e65b6a35dad
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-square-brackets-port-contains-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: host-square-brackets-port-contains-colon</title>
+<object data="http://[1::2]:3:4"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-tab-novalid.html
new file mode 100644
index 00000000000..06424d027a5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: host-tab</title>
+<object data="http://example .org"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-u0000-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-u0000-percent-encoded-novalid.html
new file mode 100644
index 00000000000..0782bd2baf3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-u0000-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: host-u0000-percent-encoded</title>
+<object data="http://%00.com"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-u0000-percent-encoded-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-u0000-percent-encoded-percent-encoded-novalid.html
new file mode 100644
index 00000000000..72bee10c220
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/host-u0000-percent-encoded-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: host-u0000-percent-encoded-percent-encoded</title>
+<object data="http://%ef%bc%85%ef%bc%90%ef%bc%90.com"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/path-bare-percent-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/path-bare-percent-sign-novalid.html
new file mode 100644
index 00000000000..7672e0075c4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/path-bare-percent-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: path-bare-percent-sign</title>
+<object data="http://example.com/foo%"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/path-contains-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/path-contains-space-novalid.html
new file mode 100644
index 00000000000..306bd90cbd3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/path-contains-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: path-contains-space</title>
+<object data="/a/ /c"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/path-leading-backslash-at-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/path-leading-backslash-at-sign-novalid.html
new file mode 100644
index 00000000000..4d421d7e779
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/path-leading-backslash-at-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: path-leading-backslash-at-sign</title>
+<object data="http://foo.com/\@"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/path-leading-colon-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/path-leading-colon-backslash-novalid.html
new file mode 100644
index 00000000000..bab2c3661ac
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/path-leading-colon-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: path-leading-colon-backslash</title>
+<object data=":\"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/path-leading-colon-chars-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/path-leading-colon-chars-backslash-novalid.html
new file mode 100644
index 00000000000..d24fc52e6f7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/path-leading-colon-chars-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: path-leading-colon-chars-backslash</title>
+<object data=":foo.com\"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/path-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/path-leading-space-novalid.html
new file mode 100644
index 00000000000..9093f5e26e5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/path-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: path-leading-space</title>
+<object data="http://f:21/ b"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/path-percent-encoded-malformed-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/path-percent-encoded-malformed-novalid.html
new file mode 100644
index 00000000000..d0a32ca506d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/path-percent-encoded-malformed-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: path-percent-encoded-malformed</title>
+<object data="http://example.com/foo/%2e%2"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/path-relative-square-brackets-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/path-relative-square-brackets-novalid.html
new file mode 100644
index 00000000000..d3c020df8a9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/path-relative-square-brackets-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: path-relative-square-brackets</title>
+<object data="[61:24:74]:98"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/path-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/path-tab-novalid.html
new file mode 100644
index 00000000000..393ad621bab
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/path-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: path-tab</title>
+<object data="http://example.com/foo bar"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/path-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/path-trailing-space-novalid.html
new file mode 100644
index 00000000000..7637e81e430
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/path-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: path-trailing-space</title>
+<object data="http://f:21/b ?"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/path-u0091-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/path-u0091-novalid.html
new file mode 100644
index 00000000000..16b7b75044c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/path-u0091-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: path-u0091</title>
+<object data="http://example.com/foo‘"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/port-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/port-cr-novalid.html
new file mode 100644
index 00000000000..c66522f3da8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/port-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: port-cr</title>
+<object data="http://f: /c"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/port-leading-colon-bracket-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/port-leading-colon-bracket-colon-novalid.html
new file mode 100644
index 00000000000..23a94ce3675
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/port-leading-colon-bracket-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: port-leading-colon-bracket-colon</title>
+<object data="http://2001::1]:80"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/port-leading-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/port-leading-colon-novalid.html
new file mode 100644
index 00000000000..67d1d40f1b2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/port-leading-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: port-leading-colon</title>
+<object data="http://2001::1"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/port-leading-dash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/port-leading-dash-novalid.html
new file mode 100644
index 00000000000..ace5c2109e8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/port-leading-dash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: port-leading-dash</title>
+<object data="http://foo:-80/"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/port-multiple-letters-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/port-multiple-letters-novalid.html
new file mode 100644
index 00000000000..72aabe72dc7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/port-multiple-letters-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: port-multiple-letters</title>
+<object data="http://f:fifty-two/c"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/port-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/port-newline-novalid.html
new file mode 100644
index 00000000000..f9cec6d9b36
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/port-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: port-newline</title>
+<object data="http://f:
+/c"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/port-single-letter-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/port-single-letter-novalid.html
new file mode 100644
index 00000000000..1c349f119b2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/port-single-letter-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: port-single-letter</title>
+<object data="http://f:b/c"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/port-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/port-space-novalid.html
new file mode 100644
index 00000000000..0efa3a64664
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/port-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: port-space</title>
+<object data="http://f: /c"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/port-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/port-tab-novalid.html
new file mode 100644
index 00000000000..d472787a90d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/port-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: port-tab</title>
+<object data="http://f: /c"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/query-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/query-leading-space-novalid.html
new file mode 100644
index 00000000000..a0791358911
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/query-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: query-leading-space</title>
+<object data="http://f:21/b? d"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/query-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/query-trailing-space-novalid.html
new file mode 100644
index 00000000000..6a8cc4bc63c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/query-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: query-trailing-space</title>
+<object data="http://f:21/b?d #"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-data-contains-fragment-haswarn.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-data-contains-fragment-haswarn.html
new file mode 100644
index 00000000000..7075d88a076
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-data-contains-fragment-haswarn.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>data:text/html,test#test warning: scheme-data-contains-fragment</title>
+<object data="data:text/html,test#test"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-data-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-data-single-slash-novalid.html
new file mode 100644
index 00000000000..97d1d041839
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-data-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: scheme-data-single-slash</title>
+<object data="data:/example.com/"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-file-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-file-backslash-novalid.html
new file mode 100644
index 00000000000..829632449fb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-file-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: scheme-file-backslash</title>
+<object data="file:c:\foo\bar.html"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-file-single-slash-c-bar-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-file-single-slash-c-bar-novalid.html
new file mode 100644
index 00000000000..a5d0c782b29
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-file-single-slash-c-bar-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: scheme-file-single-slash-c-bar</title>
+<object data="file:/C|/foo/bar"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-file-triple-slash-c-bar-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-file-triple-slash-c-bar-novalid.html
new file mode 100644
index 00000000000..4109b8c848f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-file-triple-slash-c-bar-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: scheme-file-triple-slash-c-bar</title>
+<object data="file:///C|/foo/bar"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-ftp-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-ftp-no-slash-novalid.html
new file mode 100644
index 00000000000..a828a9fb665
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-ftp-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: scheme-ftp-no-slash</title>
+<object data="ftp:example.com/"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-ftp-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-ftp-single-slash-novalid.html
new file mode 100644
index 00000000000..0f4a5d31157
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-ftp-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: scheme-ftp-single-slash</title>
+<object data="ftp:/example.com/"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-http-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-http-backslash-novalid.html
new file mode 100644
index 00000000000..4286ae797f2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-http-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: scheme-http-backslash</title>
+<object data="http:\\foo.com\"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-http-no-slash-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-http-no-slash-colon-novalid.html
new file mode 100644
index 00000000000..522f34cb9d7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-http-no-slash-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: scheme-http-no-slash-colon</title>
+<object data="http::@c:29"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-http-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-http-no-slash-novalid.html
new file mode 100644
index 00000000000..8ae3cc5e456
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-http-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: scheme-http-no-slash</title>
+<object data="http:foo.com"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-http-no-slash-square-bracket-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-http-no-slash-square-bracket-novalid.html
new file mode 100644
index 00000000000..af87406c3c9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-http-no-slash-square-bracket-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: scheme-http-no-slash-square-bracket</title>
+<object data="http:[61:27]/:foo"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-http-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-http-single-slash-novalid.html
new file mode 100644
index 00000000000..3923512854c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-http-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: scheme-http-single-slash</title>
+<object data="http:/example.com/"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-https-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-https-no-slash-novalid.html
new file mode 100644
index 00000000000..79ca00c60b3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-https-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: scheme-https-no-slash</title>
+<object data="https:example.com/"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-https-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-https-single-slash-novalid.html
new file mode 100644
index 00000000000..17f03174208
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-https-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: scheme-https-single-slash</title>
+<object data="https:/example.com/"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-javascript-no-slash-malformed-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-javascript-no-slash-malformed-novalid.html
new file mode 100644
index 00000000000..aa277965975
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-javascript-no-slash-malformed-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: scheme-javascript-no-slash-malformed</title>
+<object data="javascript:example.com/"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-trailing-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-trailing-cr-novalid.html
new file mode 100644
index 00000000000..4c9c1226c8a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-trailing-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: scheme-trailing-cr</title>
+<object data="a: foo.com"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-trailing-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-trailing-newline-novalid.html
new file mode 100644
index 00000000000..7a46f0ccc96
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-trailing-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: scheme-trailing-newline</title>
+<object data="a:
+foo.com"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-trailing-space-novalid.html
new file mode 100644
index 00000000000..756cbb9c76a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: scheme-trailing-space</title>
+<object data="a: foo.com"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-trailing-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-trailing-tab-novalid.html
new file mode 100644
index 00000000000..f85ac5dcdad
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/scheme-trailing-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: scheme-trailing-tab</title>
+<object data="a: foo.com"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/userinfo-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/userinfo-backslash-novalid.html
new file mode 100644
index 00000000000..c196363507b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/userinfo-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: userinfo-backslash</title>
+<object data="http://a\b:c\d@foo.com"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/userinfo-password-bad-chars-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/userinfo-password-bad-chars-novalid.html
new file mode 100644
index 00000000000..c1b3669e38f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/userinfo-password-bad-chars-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: userinfo-password-bad-chars</title>
+<object data="http://&a:foo(b]c@d:2/"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/userinfo-password-contains-pile-of-poo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/userinfo-password-contains-pile-of-poo-novalid.html
new file mode 100644
index 00000000000..b6f542d72da
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/userinfo-password-contains-pile-of-poo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: userinfo-password-contains-pile-of-poo</title>
+<object data="http://foo:💩@example.com"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/userinfo-username-contains-at-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/userinfo-username-contains-at-sign-novalid.html
new file mode 100644
index 00000000000..15763d0e07c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/userinfo-username-contains-at-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: userinfo-username-contains-at-sign</title>
+<object data="http://::@c@d:2"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/userinfo-username-contains-pile-of-poo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/userinfo-username-contains-pile-of-poo-novalid.html
new file mode 100644
index 00000000000..9cb6d9cc28c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/data/userinfo-username-contains-pile-of-poo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid data: userinfo-username-contains-pile-of-poo</title>
+<object data="http://💩:foo@example.com"></object>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/model-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/model-isvalid.html
new file mode 100644
index 00000000000..820915ed3a7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/model-isvalid.html
@@ -0,0 +1,79 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;object&gt;</title>
+</head>
+<body>
+ <map name="idref"></map>
+ <!-- is structured inline -->
+ <p><object
+ data="uri"
+ height="40"
+ usemap="#idref"
+ width="40"
+ class="class"
+ lang="en"></object></p>
+
+ <!-- is strictly inline -->
+ <p><dfn><object
+ data="uri"
+ height="40"
+ usemap="#idref"
+ width="40"
+ class="class"
+ lang="en"></object></dfn></p>
+
+
+ <!-- can contain strictly inline while in strictly inline context, but param must come first -->
+ <p><dfn>strictly inline
+ <object data='f'>
+ <em>text</em>
+ </object>
+ </dfn></p>
+ <p><dfn>strictly inline
+ <object data='f'>
+ <param name="foo" value='bar'><param name="bar" value='foo'>
+ <em>text</em>
+ </object>
+ </dfn></p>
+
+ <!-- can contain blocks while in block context, but param must come first -->
+<!-- REVISIT
+ <object>
+ <p>text</p>
+ </object>
+ <object>
+ <param name="foo" value='bar'><param name="bar" value='foo'>
+ <p>text</p>
+ </object>
+-->
+ <!-- can contain interactive if ancestor does not forbid it, but param must come first -->
+ <p>paragraph
+ <object data='f'>
+ <a>link</a>
+ </object>
+ </p>
+ <p>paragraph
+ <object data='f'>
+ <param name="foo" value='bar'><param name="bar" value='foo'>
+ <a>link</a>
+ </object>
+ </p>
+ <p><dfn>strictly inline
+ <object data='f'>
+ <a>link</a>
+ </object>
+ </dfn></p>
+ <p><dfn>strictly inline
+ <object data='f'>
+ <param name="foo" value='bar'><param name="bar" value='foo'>
+ <a>link</a>
+ </object>
+ </dfn></p>
+
+ <!-- object with flow content and flow parent -->
+ <div><object data=foo><p>foo</p></object></div>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/model-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/model-novalid.html
new file mode 100644
index 00000000000..f5037efa817
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/object/model-novalid.html
@@ -0,0 +1,81 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;obj&gt;</title>
+</head>
+<body>
+ <!-- classid, codebase, data, usemap are uris; archive is uri list
+ width and height are positive integers
+ type and codetype are MIME types -->
+ <p><object archive="&lt;"></object></p>
+ <p><object classid="&lt;"></object></p>
+ <p><object codebase="&lt;"></object></p>
+ <p><object codetype="//"></object></p>
+ <p><object data="&lt;"></object></p>
+ <p><object height="4.2"></object></p>
+ <p><object type="//"></object></p>
+ <p><object usemap="&lt;"></object></p>
+ <p><object width="0"></object></p>
+
+ <!-- cannot contain blocks while in inline context -->
+ <p>paragraph
+ <object>
+ <p>para</p>
+ </object>
+ </p>
+
+ <!-- cannot contain blocks while in strictly inline context -->
+ <p><dfn>strictly inline
+ <object>
+ <p>para</p>
+ </object>
+ </dfn></p>
+
+ <!-- cannot contain structured inline while in strictly inline context -->
+ <p><dfn>strictly inline
+ <object>
+ <ul><li>para</li></ul>
+ </object>
+ </dfn></p>
+
+ <!-- cannot contain inline while in block context -->
+ <object>
+ <em>inline</em> text
+ </object>
+
+ <!-- param must be first -->
+ <p>paragraph
+ <object>
+ <em>text</em>
+ <param name="foo">
+ </object>
+ </p>
+ <p><dfn>strictly inline
+ <object>
+ text
+ <param name="foo">
+ </object>
+ </dfn></p>
+ <object>
+ <p>para</p>
+ <param name="foo">
+ </object>
+
+ <!-- cannot contain interactive if ancestor forbids it -->
+ <p><a>paragraph
+ <object>
+ <a>para</a>
+ </object>
+ </a></p>
+ <p><dfn><a>strictly inline
+ <object>
+ <a>para</a>
+ </object>
+ </a></dfn></p>
+
+ <!-- object with flow content and phrasing parent -->
+ <span><object data=foo><p>foo</p></object></span>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ol/model-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ol/model-isvalid.html
new file mode 100644
index 00000000000..28e545a1291
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ol/model-isvalid.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Ordered List: &lt;ol&gt; &lt;li&gt;</title>
+</head>
+<body>
+ <!-- is block -->
+ <ol class="class" id="id" lang="en" start="05">
+ <li class="class" id="id2" lang="en" value="9">text</li>
+ </ol>
+
+ <!-- can be empty -->
+ <ol></ol>
+ <ol>
+ <li></li>
+ <li></li>
+ </ol>
+
+ <!-- can contain structured inline -->
+ <ol>
+ <li>some <em>text</em>
+ <pre>more text</pre>
+ </li>
+ </ol>
+
+ <!-- can contain blocks -->
+ <ol>
+ <li>
+ <p>some</p>
+ <p>text</p>
+ </li>
+ </ol>
+
+ <!-- can contain interactive -->
+ <ol><li><a>text</a></li></ol>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ol/model-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ol/model-novalid.html
new file mode 100644
index 00000000000..2b00a34e6c5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ol/model-novalid.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Ordered List: &lt;ol&gt; &lt;li&gt;</title>
+</head>
+<body>
+ <!-- is block -->
+ <ol class="class" id="id" lang="en" start="05">
+ <li class="class" id="id" lang="en" value="9">text</li>
+ </ol>
+
+ <!-- is structured inline -->
+ <p>paragraph
+ <ol class="class" id="id" lang="en" start="-8">
+ <li class="class" id="id" lang="en" value="-19">text</li>
+ </ol>
+ </p>
+
+ <!-- can be empty -->
+ <ol></ol>
+ <ol>
+ <li></li>
+ <li></li>
+ </ol>
+
+ <!-- cannot contain structured inline -->
+ <ol>
+ <li>some <em>text</em>
+ <pre>more text</pre>
+ </li>
+ </ol>
+ <p>paragraph
+ <ol>
+ <li>some <em>text</em>
+ <pre>more text</pre>
+ </li>
+ </ol>
+ </p>
+
+ <!-- can contain blocks -->
+ <ol>
+ <li>
+ <p>some</p>
+ <p>text</p>
+ </li>
+ </ol>
+
+ <!-- can contain interactive -->
+ <ol><li><a>text</a></li></ol>
+ <p>paragraph
+ <ol><li><a>text</a></li></ol>
+ </p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/option/label-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/option/label-isvalid.html
new file mode 100644
index 00000000000..66c3a4f080d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/option/label-isvalid.html
@@ -0,0 +1,6 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>option element with label attribute</title>
+<select>
+<option label=foo></option>
+</select>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/option/label-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/option/label-novalid.html
new file mode 100644
index 00000000000..c68367a4fca
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/option/label-novalid.html
@@ -0,0 +1,6 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>option element with empty label attribute</title>
+<select>
+<option label=""></option>
+</select>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/option/model-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/option/model-isvalid.html
new file mode 100644
index 00000000000..7cc75ab8069
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/option/model-isvalid.html
@@ -0,0 +1,6 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>non-empty option element</title>
+<select>
+<option>foo</option>
+</select>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/option/model-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/option/model-novalid.html
new file mode 100644
index 00000000000..dbe431d5f59
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/option/model-novalid.html
@@ -0,0 +1,6 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>empty option element</title>
+<select>
+<option></option>
+</select>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/p/model-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/p/model-isvalid.html
new file mode 100644
index 00000000000..9d9e2a11d8f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/p/model-isvalid.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;p&gt;</title>
+</head>
+<body>
+ <!-- is block -->
+ <p class="class" id="id" lang="en">text</p>
+
+ <!-- can contain interactive -->
+ <p><a>text</a></p>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/p/model-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/p/model-novalid.html
new file mode 100644
index 00000000000..18cdd54996d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/p/model-novalid.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;p&gt;</title>
+</head>
+<body>
+ <!-- is block -->
+ <p class="class" id="id" lang="en">text</p>
+
+ <!-- can contain interactive -->
+ <p><a>text</a></p>
+
+ <!-- cannot contain structured inline -->
+ <p>text <ul><li>list</li></ul> <em>elem</em></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/param/model-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/param/model-isvalid.html
new file mode 100644
index 00000000000..eedf9d0066c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/param/model-isvalid.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;param&gt;</title>
+</head>
+<body>
+<p>
+ <object data='foo'><param name="foo" value='bar'></object>
+
+ <object data='foo'><param name="foo" value="!@#$%$ ^&amp;)"></object>
+ <object data='foo'><param name="foo" value="!@#$%$ ^&amp;)"></object>
+
+ <object data='foo'><param name="foo" value="uri"></object>
+ <object data='foo'><param name="foo" value="uri"></object>
+</p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/param/model-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/param/model-novalid.html
new file mode 100644
index 00000000000..ad780fc833f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/param/model-novalid.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;param&gt;</title>
+</head>
+<body>
+ <!-- param is not block or inline -->
+ <param name="foo">
+ <p>para<param name="foo"></p>
+ <p><dfn>strictly<param name="foo"></dfn></p>
+
+ <!-- param must be empty -->
+ <object><param name="foo"><p>yo</p></object>
+ <p><object><param name="foo"><em>some</em> text</object></p>
+
+ <!-- name is required -->
+ <object><param></object>
+
+ <!-- param data value cannot have type attr -->
+ <object><param name="foo" value="!@#$%$ ^&amp;)"
+ type="application/octet-stream"></object>
+ <object><param name="foo" valuetype="data" value="!@#$%$ ^&amp;)"
+ type="application/octet-stream"></object>
+
+ <!-- param ref value must be URI -->
+ <object><param name="foo" valuetype="ref" value="&lt;"></object>
+ <object><param name="foo" valuetype="ref" value="&lt;"
+ type="application/octet-stream"></object>
+
+ <!-- param object value must be IDREF, cannot have type attr -->
+ <object><param name="foo" valuetype="object" value="sth"></object>
+ <object><param name="foo" valuetype="object" value="#"></object>
+ <object><param name="foo" valuetype="object" value="#"
+ type="application/octet-stream"></object>
+
+ <!-- valuetype can't take any other values -->
+ <object><param name="foo" valuetype="sth"></object>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/always-matching-source-media-all-spaces-with-following-source-srcset-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/always-matching-source-media-all-spaces-with-following-source-srcset-novalid.html
new file mode 100644
index 00000000000..7bcac2b42f2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/always-matching-source-media-all-spaces-with-following-source-srcset-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid always-matching-source-media-all-spaces-with-following-source-srcset</title>
+<picture><source srcset=x media=' all '><source srcset=x><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/always-matching-source-media-all-with-following-source-srcset-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/always-matching-source-media-all-with-following-source-srcset-novalid.html
new file mode 100644
index 00000000000..320ca691248
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/always-matching-source-media-all-with-following-source-srcset-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid always-matching-source-media-all-with-following-source-srcset</title>
+<picture><source srcset=x media=all><source srcset=x><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/always-matching-source-media-empty-with-following-source-srcset-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/always-matching-source-media-empty-with-following-source-srcset-novalid.html
new file mode 100644
index 00000000000..a9dd0ab87ca
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/always-matching-source-media-empty-with-following-source-srcset-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid always-matching-source-media-empty-with-following-source-srcset</title>
+<picture><source srcset=x media><source srcset=x><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/always-matching-source-media-spaces-with-following-source-srcset-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/always-matching-source-media-spaces-with-following-source-srcset-novalid.html
new file mode 100644
index 00000000000..95c36b0cd21
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/always-matching-source-media-spaces-with-following-source-srcset-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid always-matching-source-media-spaces-with-following-source-srcset</title>
+<picture><source srcset=x media='
+ '><source srcset=x><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/always-matching-source-media-uppercase-with-following-source-srcset-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/always-matching-source-media-uppercase-with-following-source-srcset-novalid.html
new file mode 100644
index 00000000000..d495d18b46b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/always-matching-source-media-uppercase-with-following-source-srcset-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid always-matching-source-media-uppercase-with-following-source-srcset</title>
+<picture><source srcset=x media=ALL><source srcset=x><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/always-matching-source-sizes-with-following-source-srcset-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/always-matching-source-sizes-with-following-source-srcset-novalid.html
new file mode 100644
index 00000000000..2cb7ea80297
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/always-matching-source-sizes-with-following-source-srcset-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid always-matching-source-sizes-with-following-source-srcset</title>
+<picture><source srcset='x 100w' sizes=50vw><source srcset=x><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/always-matching-source-with-following-img-srcset-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/always-matching-source-with-following-img-srcset-novalid.html
new file mode 100644
index 00000000000..c2962a9a7f8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/always-matching-source-with-following-img-srcset-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid always-matching-source-with-following-img-srcset</title>
+<picture><source srcset=x><img src=x srcset=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/always-matching-source-with-following-source-media-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/always-matching-source-with-following-source-media-novalid.html
new file mode 100644
index 00000000000..a097307cd1e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/always-matching-source-with-following-source-media-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid always-matching-source-with-following-source-media</title>
+<picture><source srcset=x><source srcset=x media=screen><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/always-matching-source-with-following-source-srcset-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/always-matching-source-with-following-source-srcset-novalid.html
new file mode 100644
index 00000000000..d0f3ea9379e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/always-matching-source-with-following-source-srcset-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid always-matching-source-with-following-source-srcset</title>
+<picture><source srcset=x><source srcset=x><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/always-matching-source-with-following-source-type-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/always-matching-source-with-following-source-type-novalid.html
new file mode 100644
index 00000000000..99eadd808d6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/always-matching-source-with-following-source-type-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid always-matching-source-with-following-source-type</title>
+<picture><source srcset=x><source srcset=x type=image/gif><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/audio-srcset-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/audio-srcset-novalid.html
new file mode 100644
index 00000000000..883f05be432
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/audio-srcset-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid audio-srcset</title>
+<audio src=x srcset=x></audio> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/html-syntax-img-end-tag-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/html-syntax-img-end-tag-novalid.html
new file mode 100644
index 00000000000..0c56b597abe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/html-syntax-img-end-tag-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid html-syntax-img-end-tag</title>
+<picture><img src=x alt></img></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/html-syntax-picture-no-end-tag-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/html-syntax-picture-no-end-tag-novalid.html
new file mode 100644
index 00000000000..a7e378d38ed
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/html-syntax-picture-no-end-tag-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid html-syntax-picture-no-end-tag</title>
+<picture><img src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/html-syntax-picture-slash-no-end-tag-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/html-syntax-picture-slash-no-end-tag-novalid.html
new file mode 100644
index 00000000000..50816e522d4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/html-syntax-picture-slash-no-end-tag-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid html-syntax-picture-slash-no-end-tag</title>
+<picture/><img src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/html-syntax-picture-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/html-syntax-picture-slash-novalid.html
new file mode 100644
index 00000000000..0c824ef56c8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/html-syntax-picture-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid html-syntax-picture-slash</title>
+<picture/><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/html-syntax-source-end-tag-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/html-syntax-source-end-tag-novalid.html
new file mode 100644
index 00000000000..8a8b2c447ef
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/html-syntax-source-end-tag-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid html-syntax-source-end-tag</title>
+<picture><source srcset=x></source><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/img-no-src-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/img-no-src-novalid.html
new file mode 100644
index 00000000000..a97c2a52d80
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/img-no-src-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid img-no-src</title>
+<img alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/img-no-src-with-picture-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/img-no-src-with-picture-novalid.html
new file mode 100644
index 00000000000..aae2586129e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/img-no-src-with-picture-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid img-no-src-with-picture</title>
+<picture><img alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/img-no-src-with-source-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/img-no-src-with-source-novalid.html
new file mode 100644
index 00000000000..185231fd632
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/img-no-src-with-source-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid img-no-src-with-source</title>
+<picture><source srcset=x><img alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/img-no-src-with-srcset-and-picture-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/img-no-src-with-srcset-and-picture-novalid.html
new file mode 100644
index 00000000000..d7e820a1eec
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/img-no-src-with-srcset-and-picture-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid img-no-src-with-srcset-and-picture</title>
+<picture><img srcset=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/img-no-src-with-srcset-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/img-no-src-with-srcset-novalid.html
new file mode 100644
index 00000000000..aade7df01ca
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/img-no-src-with-srcset-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid img-no-src-with-srcset</title>
+<img srcset=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/img-srcset-no-descriptor-with-sizes-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/img-srcset-no-descriptor-with-sizes-novalid.html
new file mode 100644
index 00000000000..c23295931bb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/img-srcset-no-descriptor-with-sizes-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid img-srcset-no-descriptor-with-sizes</title>
+<img src=x srcset='x' sizes=50vw alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/img-srcset-w-and-x-width-sizes-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/img-srcset-w-and-x-width-sizes-novalid.html
new file mode 100644
index 00000000000..ae5cba4e189
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/img-srcset-w-and-x-width-sizes-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid img-srcset-w-and-x-width-sizes</title>
+<img src=x srcset='x 100w, y 2x' sizes=50vw alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/img-srcset-w-no-sizes-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/img-srcset-w-no-sizes-novalid.html
new file mode 100644
index 00000000000..c6970b7587f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/img-srcset-w-no-sizes-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid img-srcset-w-no-sizes</title>
+<img srcset='x 100w, y 200w' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/img-type-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/img-type-novalid.html
new file mode 100644
index 00000000000..41a813c1c44
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/img-type-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid img-type</title>
+<img src=x type=image/gif alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/img-type-with-picture-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/img-type-with-picture-novalid.html
new file mode 100644
index 00000000000..d05284ee589
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/img-type-with-picture-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid img-type-with-picture</title>
+<picture><img src=x type=image/gif alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/img-with-sizes-no-srcset-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/img-with-sizes-no-srcset-novalid.html
new file mode 100644
index 00000000000..a77c4a53906
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/img-with-sizes-no-srcset-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid img-with-sizes-no-srcset</title>
+<img sizes=50vw src=foo alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/input-type-image-srcset-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/input-type-image-srcset-novalid.html
new file mode 100644
index 00000000000..80c7995e5b0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/input-type-image-srcset-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid input-type-image-srcset</title>
+<input type=image src=x srcset=x alt=x> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-br-after-img-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-br-after-img-novalid.html
new file mode 100644
index 00000000000..66ea1f9605f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-br-after-img-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid junk-br-after-img</title>
+<picture><img src=x alt><br></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-br-after-source-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-br-after-source-novalid.html
new file mode 100644
index 00000000000..55bb78c19e6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-br-after-source-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid junk-br-after-source</title>
+<picture><source srcset=x><br><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-br-before-img-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-br-before-img-novalid.html
new file mode 100644
index 00000000000..06462c42bfe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-br-before-img-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid junk-br-before-img</title>
+<picture><br><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-br-before-source-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-br-before-source-novalid.html
new file mode 100644
index 00000000000..7f9bbc0a26f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-br-before-source-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid junk-br-before-source</title>
+<picture><br><source srcset=x><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-figure-wrapping-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-figure-wrapping-novalid.html
new file mode 100644
index 00000000000..ffe22b73b13
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-figure-wrapping-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid junk-figure-wrapping</title>
+<picture><figure><img src=x alt></figure></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-input-type-hidden-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-input-type-hidden-novalid.html
new file mode 100644
index 00000000000..b4763de6e4c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-input-type-hidden-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid junk-input-type-hidden</title>
+<picture><input type=hidden name=x value=x><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-math-nog-img-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-math-nog-img-novalid.html
new file mode 100644
index 00000000000..5f1b85dbb28
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-math-nog-img-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid junk-math-nog-img</title>
+<picture><math></math></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-noscript-after-source-no-img-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-noscript-after-source-no-img-novalid.html
new file mode 100644
index 00000000000..957c8bc1a39
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-noscript-after-source-no-img-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid junk-noscript-after-source-no-img</title>
+<picture><source srcset=x><noscript><img src=x alt></noscript></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-noscript-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-noscript-novalid.html
new file mode 100644
index 00000000000..45efb6712c5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-noscript-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid junk-noscript</title>
+<picture><img src=x alt><noscript></noscript></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-p-after-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-p-after-novalid.html
new file mode 100644
index 00000000000..0848d51e045
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-p-after-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid junk-p-after</title>
+<picture><source srcset=x><img src=x alt><p></p></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-p-before-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-p-before-novalid.html
new file mode 100644
index 00000000000..abb046b7640
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-p-before-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid junk-p-before</title>
+<picture><p></p><source srcset=x><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-p-wrapping-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-p-wrapping-novalid.html
new file mode 100644
index 00000000000..c1561cf33b4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-p-wrapping-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid junk-p-wrapping</title>
+<picture><p><source srcset=x><img src=x alt></p></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-picture-before-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-picture-before-novalid.html
new file mode 100644
index 00000000000..d2d3ce9ff23
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-picture-before-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid junk-picture-before</title>
+<picture><picture><img src=x alt></picture><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-picture-wrapping-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-picture-wrapping-novalid.html
new file mode 100644
index 00000000000..beb9577c5eb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-picture-wrapping-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid junk-picture-wrapping</title>
+<picture><picture><img src=x alt></picture></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-span-after-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-span-after-novalid.html
new file mode 100644
index 00000000000..03f6923e776
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-span-after-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid junk-span-after</title>
+<picture><source srcset=x><img src=x alt><span></span></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-span-before-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-span-before-novalid.html
new file mode 100644
index 00000000000..85307cfb5ec
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-span-before-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid junk-span-before</title>
+<picture><span></span><source srcset=x><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-span-wrapping-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-span-wrapping-novalid.html
new file mode 100644
index 00000000000..701a263d569
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-span-wrapping-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid junk-span-wrapping</title>
+<picture><span><source srcset=x><img src=x alt></span></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-style-scroped-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-style-scroped-novalid.html
new file mode 100644
index 00000000000..7aae2a0fe7a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-style-scroped-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid junk-style-scroped</title>
+<picture><style scroped></style><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-svg-no-img-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-svg-no-img-novalid.html
new file mode 100644
index 00000000000..0a444584989
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-svg-no-img-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid junk-svg-no-img</title>
+<picture><svg></svg></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-svg-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-svg-novalid.html
new file mode 100644
index 00000000000..03d47c7189f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-svg-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid junk-svg</title>
+<picture><img src=x alt><svg></svg></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-text-after-img-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-text-after-img-novalid.html
new file mode 100644
index 00000000000..700f317c2b0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-text-after-img-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid junk-text-after-img</title>
+<picture><img src=x alt>x</picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-text-after-source-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-text-after-source-novalid.html
new file mode 100644
index 00000000000..99c173e8f60
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-text-after-source-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid junk-text-after-source</title>
+<picture><source srcset=x>x<img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-text-before-img-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-text-before-img-novalid.html
new file mode 100644
index 00000000000..256804c9623
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-text-before-img-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid junk-text-before-img</title>
+<picture>x<img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-text-before-source-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-text-before-source-novalid.html
new file mode 100644
index 00000000000..cf1cf0f4ea5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-text-before-source-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid junk-text-before-source</title>
+<picture>x<source srcset=x><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-video-before-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-video-before-novalid.html
new file mode 100644
index 00000000000..2e91d9c2984
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-video-before-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid junk-video-before</title>
+<picture><video></video><source srcset=x><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-video-no-img-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-video-no-img-novalid.html
new file mode 100644
index 00000000000..05d89383b99
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/junk-video-no-img-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid junk-video-no-img</title>
+<picture><video></video></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/link-rel-icon-srcset-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/link-rel-icon-srcset-novalid.html
new file mode 100644
index 00000000000..df2d56c8efe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/link-rel-icon-srcset-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid link-rel-icon-srcset</title>
+<link rel=icon srcset=x href=x> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/missing-img-empty-picture-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/missing-img-empty-picture-novalid.html
new file mode 100644
index 00000000000..6f604e165be
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/missing-img-empty-picture-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid missing-img-empty-picture</title>
+<picture></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/missing-img-only-script-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/missing-img-only-script-novalid.html
new file mode 100644
index 00000000000..96015048cff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/missing-img-only-script-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid missing-img-only-script</title>
+<picture><script></script></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/missing-img-only-source-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/missing-img-only-source-novalid.html
new file mode 100644
index 00000000000..b8b25bd7377
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/missing-img-only-source-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid missing-img-only-source</title>
+<picture><source srcset=x></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/missing-img-script-and-source-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/missing-img-script-and-source-novalid.html
new file mode 100644
index 00000000000..ea61fadbdb1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/missing-img-script-and-source-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid missing-img-script-and-source</title>
+<picture><script></script><source srcset=x></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/missing-img-source-and-script-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/missing-img-source-and-script-novalid.html
new file mode 100644
index 00000000000..a31715d3369
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/missing-img-source-and-script-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid missing-img-source-and-script</title>
+<picture><source srcset=x><script></script></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/multiple-img-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/multiple-img-novalid.html
new file mode 100644
index 00000000000..bed5b38ac90
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/multiple-img-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid multiple-img</title>
+<picture><img src=x alt><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/multiple-img-with-script-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/multiple-img-with-script-novalid.html
new file mode 100644
index 00000000000..973d01f807b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/multiple-img-with-script-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid multiple-img-with-script</title>
+<picture><img src=x alt><script></script><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/multiple-img-with-source-and-script-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/multiple-img-with-source-and-script-novalid.html
new file mode 100644
index 00000000000..8c722ac0704
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/multiple-img-with-source-and-script-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid multiple-img-with-source-and-script</title>
+<picture><source srcset=x><img src=x alt><script></script><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/multiple-img-with-source-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/multiple-img-with-source-novalid.html
new file mode 100644
index 00000000000..d6c2402e85f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/multiple-img-with-source-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid multiple-img-with-source</title>
+<picture><source srcset=x><img src=x alt><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/object-srcset-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/object-srcset-novalid.html
new file mode 100644
index 00000000000..df784de7ef2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/object-srcset-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid object-srcset</title>
+<object data=x srcset=x></object> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/parent-dl-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/parent-dl-novalid.html
new file mode 100644
index 00000000000..12b32af3430
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/parent-dl-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid parent-dl</title>
+<dl><picture><img src=x alt></picture></dl> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/parent-hgroup-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/parent-hgroup-novalid.html
new file mode 100644
index 00000000000..3b260d27f28
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/parent-hgroup-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid parent-hgroup</title>
+<hgroup><h1>x</h1><picture><img src=x alt></picture></hgroup> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/parent-noscript-in-head-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/parent-noscript-in-head-novalid.html
new file mode 100644
index 00000000000..648a16c1dc8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/parent-noscript-in-head-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid parent-noscript-in-head</title>
+<noscript><picture><img src=x alt></picture></noscript> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/parent-ul-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/parent-ul-novalid.html
new file mode 100644
index 00000000000..ed39ef722bb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/parent-ul-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid parent-ul</title>
+<ul><picture><img src=x alt></picture></ul> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-align-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-align-novalid.html
new file mode 100644
index 00000000000..494a44d0b5d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-align-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid picture-align</title>
+<picture align=left><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-alt-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-alt-novalid.html
new file mode 100644
index 00000000000..678dfe46a99
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-alt-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid picture-alt</title>
+<picture alt><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-aria-role-application-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-aria-role-application-novalid.html
new file mode 100644
index 00000000000..6d1771f2a9e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-aria-role-application-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid picture-aria-role-application</title>
+<picture role=application><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-aria-role-button-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-aria-role-button-novalid.html
new file mode 100644
index 00000000000..ad144b79d7f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-aria-role-button-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid picture-aria-role-button</title>
+<picture role=button><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-aria-role-img-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-aria-role-img-novalid.html
new file mode 100644
index 00000000000..f91f2671058
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-aria-role-img-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid picture-aria-role-img</title>
+<picture role=img><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-aria-role-presentation-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-aria-role-presentation-novalid.html
new file mode 100644
index 00000000000..7c8998c2ab9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-aria-role-presentation-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid picture-aria-role-presentation</title>
+<picture role=presentation><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-aria-role-region-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-aria-role-region-novalid.html
new file mode 100644
index 00000000000..336b58d6fa9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-aria-role-region-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid picture-aria-role-region</title>
+<picture role=region><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-border-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-border-novalid.html
new file mode 100644
index 00000000000..013d6d668b5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-border-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid picture-border</title>
+<picture border=1><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-crossorigin-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-crossorigin-novalid.html
new file mode 100644
index 00000000000..733be02c5bd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-crossorigin-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid picture-crossorigin</title>
+<picture crossorigin><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-height-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-height-novalid.html
new file mode 100644
index 00000000000..d5c0f0c1a0f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-height-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid picture-height</title>
+<picture height=100><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-hspace-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-hspace-novalid.html
new file mode 100644
index 00000000000..53912928bfd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-hspace-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid picture-hspace</title>
+<picture hspace=1><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-ismap-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-ismap-novalid.html
new file mode 100644
index 00000000000..d6dbfe4254a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-ismap-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid picture-ismap</title>
+<picture ismap><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-isvalid.html
new file mode 100644
index 00000000000..e8a76edf25c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-isvalid.html
@@ -0,0 +1,107 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid picture</title>
+<template><picture><img src=x alt></picture></template> <!-- parent-template-in-head -->
+<body>
+<img sizes='1q' srcset='x 100w, y 200w' src=x alt> <!-- sizes-microsyntax-q-in-source-size-value -->
+<img sizes='not (width:500px) and (width:500px) 500px' srcset='x 100w, y 200w' src=x alt> <!-- sizes-microsyntax-media-not-and -->
+<img sizes='1mm' srcset='x 100w, y 200w' src=x alt> <!-- sizes-microsyntax-mm-in-source-size-value -->
+<noscript><picture><img src=x alt></picture></noscript> <!-- parent-noscript-in-body -->
+<img sizes='1rem' srcset='x 100w, y 200w' src=x alt> <!-- sizes-microsyntax-rem-in-source-size-value -->
+<embed sizes> <!-- embed-sizes-empty -->
+<embed srcset> <!-- embed-srcset-empty -->
+<picture title=x class=x dir=ltr hidden id=asdf tabindex=0><img src=x alt></picture> <!-- picture-global-attributes -->
+<img sizes='/**/50vw' srcset='x 100w, y 200w' src=x alt> <!-- sizes-microsyntax-leading-css-comment -->
+<img sizes='1em' srcset='x 100w, y 200w' src=x alt> <!-- sizes-microsyntax-em-in-source-size-value -->
+<picture><source srcset=x media=SCREEN><img src=x srcset=x alt></picture> <!-- source-with-media-uppercase-img-with-srcset -->
+<img srcset='%2Cx' src=x alt> <!-- srcset-microsyntax-percent-escaped-leading-comma-in-url -->
+<img srcset='x 1x,y 2x' src=x alt> <!-- srcset-microsyntax-no-space-between-candidates -->
+<video src=x><picture><img src=x alt></picture></video> <!-- parent-video -->
+<img sizes='50vw/**/' srcset='x 100w, y 200w' src=x alt> <!-- sizes-microsyntax-trailing-css-comment -->
+<picture><img usemap=#x src=x alt></picture><map name=x></map> <!-- img-usemap-with-picture -->
+<ruby>x<rt><picture><img src=x alt></picture></rt></ruby> <!-- parent-rt -->
+<ruby>x<rp><picture><img src=x alt></picture></rp><rt>x</rt><rp>x</rp></ruby> <!-- parent-rp -->
+<img sizes='1vmax' srcset='x 100w, y 200w' src=x alt> <!-- sizes-microsyntax-vmax-in-source-size-value -->
+<main><picture><img src=x alt></picture></main> <!-- parent-main -->
+<img sizes='1in' srcset='x 100w, y 200w' src=x alt> <!-- sizes-microsyntax-in-in-source-size-value -->
+<picture><source srcset=x media=screen><source srcset=x><img src=x alt></picture> <!-- source-with-media-source-with-srcset -->
+<img sizes='-0' srcset='x 100w, y 200w' src=x alt> <!-- sizes-microsyntax-minus-zero -->
+<img src=x srcset='x 100w, y 200w' sizes=100vw alt> <!-- img-src-also-in-srcset-w -->
+<img src=x srcset='y 1x, x 2x' alt> <!-- img-src-also-in-srcset-2x -->
+<img srcset='%20' src=x alt> <!-- srcset-microsyntax-percent-escaped-space-in-url -->
+<picture><source srcset=x type=image/gif><img src=x srcset=x alt></picture> <!-- source-with-type-img-with-srcset -->
+<img srcset='x 100w, y 200w' sizes=50vw src=x alt> <!-- img-with-sizes -->
+<picture><template></template><source srcset=x><script></script><img src=x alt><template></template></picture> <!-- script-and-template -->
+<img sizes='+50vw' srcset='x 100w, y 200w' src=x alt> <!-- sizes-microsyntax-plus -->
+<img src=x srcset='y 100w, z 200w' sizes=100vw alt> <!-- img-src-not-in-srcset-w -->
+<h1><picture><img src=x alt=x></picture></h1> <!-- parent-h1 -->
+<img src=x srcset='y 1x, z 2x' alt> <!-- img-src-not-in-srcset-x -->
+<embed srcset='foo bar'> <!-- embed-srcset-junk -->
+<picture><source srcset=x><script></script><img src=x alt></picture> <!-- script-between -->
+<img src=x alt> <!-- basic-img-src -->
+<picture><img src=x alt width=1 height=1></picture> <!-- img-width-height-with-picture -->
+<canvas><picture><img src=x alt></picture></canvas> <!-- parent-canvas -->
+<img src=x srcset='x 1x, y 2x' alt> <!-- img-src-also-in-srcset-1x -->
+<img sizes='(min-width:calc(500px)) 500px' srcset='x 100w, y 200w' src=x alt> <!-- sizes-microsyntax-calc-in-media -->
+<ruby><picture><img src=x alt></picture><rt>x</rt></ruby> <!-- parent-ruby -->
+<img sizes='33E33px' srcset='x 100w, y 200w' src=x alt> <!-- sizes-microsyntax-scientifi-notation-3 -->
+<img sizes='2.2e2px' srcset='x 100w, y 200w' src=x alt> <!-- sizes-microsyntax-scientifi-notation-2 -->
+<img sizes='+11.11e+11px' srcset='x 100w, y 200w' src=x alt> <!-- sizes-microsyntax-scientifi-notation-1 -->
+<img sizes='-0e-0px' srcset='x 100w, y 200w' src=x alt> <!-- sizes-microsyntax-scientifi-notation-0 -->
+<a href=x><picture><img src=x alt></picture></a> <!-- parent-a -->
+<img sizes='.4E4px' srcset='x 100w, y 200w' src=x alt> <!-- sizes-microsyntax-scientifi-notation-4 -->
+<img sizes='calc(500px)' srcset='x 100w, y 200w' src=x alt> <!-- sizes-microsyntax-calc-in-default -->
+<img srcset='x 1e-0x' src=x alt> <!-- srcset-microsyntax-scientific-notation-e-minus-x -->
+<img sizes='(min-width:500px) 500px' srcset='x 100w, y 200w' src=x alt> <!-- sizes-microsyntax-no-default -->
+<embed sizes='foo bar'> <!-- embed-sizes-junk -->
+<p><picture><img src=x alt></picture></p> <!-- parent-p -->
+<img sizes='.2px' srcset='x 100w, y 200w' src=x alt> <!-- sizes-microsyntax-non-integer-omitted-zero -->
+<img sizes='(min-width:500px) 500px, 100vw' srcset='x 100w, y 200w' src=x alt> <!-- sizes-microsyntax-media-min-width -->
+<img srcset='x 1w' sizes=100vw src=x alt> <!-- srcset-microsyntax-w -->
+<object data=x><picture><img src=x alt></picture></object> <!-- parent-object -->
+<picture><source srcset=x type=image/gif><source srcset=x><img src=x alt></picture> <!-- source-with-type-source-with-srcset -->
+<picture> <!--x--> <source srcset=x> <!--x--> <img src=x alt> <!--x--> </picture> <!-- inter-element-whitespace -->
+<a href=x><picture><img ismap src=x alt></picture></a> <!-- img-ismap-with-picture -->
+<img sizes='1ex' srcset='x 100w, y 200w' src=x alt> <!-- sizes-microsyntax-ex-in-source-size-value -->
+<img sizes='1vmin' srcset='x 100w, y 200w' src=x alt> <!-- sizes-microsyntax-vmin-in-source-size-value -->
+<img srcset='x 1x' src=x alt> <!-- srcset-microsyntax-x -->
+<picture><img src=x alt width=0 height=0></picture> <!-- img-width-height-zero-with-picture -->
+<img sizes='1vw' srcset='x 100w, y 200w' src=x alt> <!-- sizes-microsyntax-vw-in-source-size-value -->
+<picture><source srcset='x 1x, y 2x' type=image/gif><img src=x alt></picture> <!-- source-type-srcset-x -->
+<img srcset='x 1e+0x' src=x alt> <!-- srcset-microsyntax-scientific-notation-e-plus-x -->
+<picture><template></template><source srcset=x><img src=x alt></picture> <!-- template-first -->
+<img sizes='0' srcset='x 100w, y 200w' src=x alt> <!-- sizes-microsyntax-zero -->
+<img sizes='1ch' srcset='x 100w, y 200w' src=x alt> <!-- sizes-microsyntax-ch-in-source-size-value -->
+<img sizes='1px' srcset='x 100w, y 200w' src=x alt> <!-- sizes-microsyntax-px-in-source-size-value -->
+<picture><source srcset=x media='
+ screen
+ '><img src=x srcset=x alt></picture> <!-- source-with-media-spaces-img-with-srcset -->
+<picture><source srcset='x 100w, y 200w' type=image/gif sizes=50vw><img src=x alt></picture> <!-- source-type-srcset-w-sizes -->
+<picture><script></script><source srcset=x><script></script><img src=x alt><script></script></picture> <!-- script-before-between-after -->
+<img sizes='500px' srcset='x 100w, y 200w' src=x alt> <!-- sizes-microsyntax-only-default -->
+<picture><img crossorigin src=x alt></picture> <!-- img-crossorigin-with-picture -->
+<picture><img src=x alt></picture> <!-- basic-picture-img-src -->
+<img sizes='1pt' srcset='x 100w, y 200w' src=x alt> <!-- sizes-microsyntax-pt-in-source-size-value -->
+<picture><source srcset=x type=image/gif><img src=x alt></picture> <!-- source-type -->
+<picture><script></script><source srcset=x><img src=x alt><script></script></picture> <!-- script-before-after -->
+<button><picture><img src=x alt></picture></button> <!-- parent-button -->
+<img srcset='x 1.5x' src=x alt> <!-- srcset-microsyntax-non-integer-x -->
+<img sizes='1cm' srcset='x 100w, y 200w' src=x alt> <!-- sizes-microsyntax-cm-in-source-size-value -->
+<img sizes='(min-width:500px) calc(500px)' srcset='x 100w, y 200w' src=x alt> <!-- sizes-microsyntax-calc-in-source-size-value -->
+<img srcset='x 1e0x' src=x alt> <!-- srcset-microsyntax-scientific-notation-x -->
+<img srcset='x%2C' src=x alt> <!-- srcset-microsyntax-percent-escaped-trailing-comma-in-url -->
+<section><h2>x</h2><picture><img src=x alt></picture></section> <!-- parent-section -->
+<picture><source srcset='x 100w, y 200w' sizes=50vw><img src=x alt></picture> <!-- source-with-sizes -->
+<picture><source srcset=x media=screen><img src=x srcset=x alt></picture> <!-- source-with-media-img-with-srcset -->
+<img sizes='1vh' srcset='x 100w, y 200w' src=x alt> <!-- sizes-microsyntax-vh-in-source-size-value -->
+<template><picture><img src=x alt></picture></template> <!-- parent-template-in-body -->
+<img srcset='x,x' src=x alt> <!-- srcset-microsyntax-comma-in-url -->
+<img sizes='1pc' srcset='x 100w, y 200w' src=x alt> <!-- sizes-microsyntax-pc-in-source-size-value -->
+<img sizes='0.2px' srcset='x 100w, y 200w' src=x alt> <!-- sizes-microsyntax-non-integer-px-in-source-size-value -->
+<img srcset='x 1E0x' src=x alt> <!-- srcset-microsyntax-scientific-notation-e-uppercase-x -->
+<img sizes='(min-width:1500px) 500px, (min-width:1000px) 33vw, (min-width:500px) 50vw, 100vw' srcset='x 100w, y 200w' src=x alt> <!-- sizes-microsyntax-multiple-source-sizes -->
+<picture><script></script><source srcset=x><img src=x alt></picture> <!-- script-first -->
+<img srcset='x 1.5e0x' src=x alt> <!-- srcset-microsyntax-scientific-notation-decimals-x -->
+<picture><source srcset=x><img src=x alt><script></script></picture> <!-- script-after -->
+<table><tr><td><picture><img src=x alt></picture></table> <!-- parent-td -->
+<picture><source srcset=x><img src=x alt></picture> <!-- basic-picture-source -->
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-longdesc-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-longdesc-novalid.html
new file mode 100644
index 00000000000..86d77931388
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-longdesc-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid picture-longdesc</title>
+<picture longdesc=x><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-lowsrc-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-lowsrc-novalid.html
new file mode 100644
index 00000000000..00361b00feb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-lowsrc-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid picture-lowsrc</title>
+<picture lowsrc=x><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-media-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-media-novalid.html
new file mode 100644
index 00000000000..e81f5e9ef0c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-media-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid picture-media</title>
+<picture media=screen><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-name-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-name-novalid.html
new file mode 100644
index 00000000000..d8867a1b2ef
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-name-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid picture-name</title>
+<picture name=x><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-sizes-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-sizes-novalid.html
new file mode 100644
index 00000000000..8064a3d2685
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-sizes-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid picture-sizes</title>
+<picture sizes=50vw><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-src-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-src-novalid.html
new file mode 100644
index 00000000000..b5e6e30e829
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-src-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid picture-src</title>
+<picture src=x><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-srcset-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-srcset-novalid.html
new file mode 100644
index 00000000000..1f3703e50be
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-srcset-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid picture-srcset</title>
+<picture srcset=x><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-usemap-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-usemap-novalid.html
new file mode 100644
index 00000000000..1def698f176
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-usemap-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid picture-usemap</title>
+<picture usemap><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-vspace-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-vspace-novalid.html
new file mode 100644
index 00000000000..fc62cd514d9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-vspace-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid picture-vspace</title>
+<picture vspace=1><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-width-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-width-novalid.html
new file mode 100644
index 00000000000..1fa63afa0c4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/picture-width-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid picture-width</title>
+<picture width=100><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-auto-source-size-value-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-auto-source-size-value-novalid.html
new file mode 100644
index 00000000000..734ed4a8c52
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-auto-source-size-value-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid sizes-microsyntax-auto-source-size-value</title>
+<img sizes='auto' srcset='x 100w, y 200w' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-comma-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-comma-novalid.html
new file mode 100644
index 00000000000..06b83dc4ae5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-comma-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid sizes-microsyntax-comma</title>
+<img sizes=',' srcset='x 100w, y 200w' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-css-comment-after-plus-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-css-comment-after-plus-novalid.html
new file mode 100644
index 00000000000..c3e04ca6b6e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-css-comment-after-plus-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid sizes-microsyntax-css-comment-after-plus</title>
+<img sizes='+/**/50vw' srcset='x 100w, y 200w' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-css-comment-before-unit-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-css-comment-before-unit-novalid.html
new file mode 100644
index 00000000000..3d0ad297dc2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-css-comment-before-unit-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid sizes-microsyntax-css-comment-before-unit</title>
+<img sizes='50/**/vw' srcset='x 100w, y 200w' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-default-first-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-default-first-novalid.html
new file mode 100644
index 00000000000..c5331b0d4ef
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-default-first-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid sizes-microsyntax-default-first</title>
+<img sizes='100vw, (min-width:500px) 500px' srcset='x 100w, y 200w' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-default-source-size-value-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-default-source-size-value-novalid.html
new file mode 100644
index 00000000000..2f70de718ab
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-default-source-size-value-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid sizes-microsyntax-default-source-size-value</title>
+<img sizes='default' srcset='x 100w, y 200w' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-deg-source-size-value-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-deg-source-size-value-novalid.html
new file mode 100644
index 00000000000..d0e608b95d6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-deg-source-size-value-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid sizes-microsyntax-deg-source-size-value</title>
+<img sizes='1deg' srcset='x 100w, y 200w' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-dpcm-source-size-value-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-dpcm-source-size-value-novalid.html
new file mode 100644
index 00000000000..c8b8b7a2dd8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-dpcm-source-size-value-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid sizes-microsyntax-dpcm-source-size-value</title>
+<img sizes='1dpcm' srcset='x 100w, y 200w' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-dpi-source-size-value-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-dpi-source-size-value-novalid.html
new file mode 100644
index 00000000000..95160c13939
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-dpi-source-size-value-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid sizes-microsyntax-dpi-source-size-value</title>
+<img sizes='1dpi' srcset='x 100w, y 200w' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-dppx-source-size-value-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-dppx-source-size-value-novalid.html
new file mode 100644
index 00000000000..778f6b49b99
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-dppx-source-size-value-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid sizes-microsyntax-dppx-source-size-value</title>
+<img sizes='1dppx' srcset='x 100w, y 200w' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-empty-novalid.html
new file mode 100644
index 00000000000..be232a5cd1f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid sizes-microsyntax-empty</title>
+<img sizes='' srcset='x 100w, y 200w' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-foo-bar-source-size-value-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-foo-bar-source-size-value-novalid.html
new file mode 100644
index 00000000000..7e969dafcb6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-foo-bar-source-size-value-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid sizes-microsyntax-foo-bar-source-size-value</title>
+<img sizes='foo-bar' srcset='x 100w, y 200w' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-grad-source-size-value-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-grad-source-size-value-novalid.html
new file mode 100644
index 00000000000..506ebf561cb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-grad-source-size-value-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid sizes-microsyntax-grad-source-size-value</title>
+<img sizes='1grad' srcset='x 100w, y 200w' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-hz-source-size-value-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-hz-source-size-value-novalid.html
new file mode 100644
index 00000000000..bc4e21c3fd2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-hz-source-size-value-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid sizes-microsyntax-hz-source-size-value</title>
+<img sizes='1Hz' srcset='x 100w, y 200w' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-inherit-source-size-value-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-inherit-source-size-value-novalid.html
new file mode 100644
index 00000000000..c232648dc6f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-inherit-source-size-value-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid sizes-microsyntax-inherit-source-size-value</title>
+<img sizes='inherit' srcset='x 100w, y 200w' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-initial-source-size-value-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-initial-source-size-value-novalid.html
new file mode 100644
index 00000000000..b70a543dee3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-initial-source-size-value-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid sizes-microsyntax-initial-source-size-value</title>
+<img sizes='initial' srcset='x 100w, y 200w' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-junk-in-default-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-junk-in-default-novalid.html
new file mode 100644
index 00000000000..1121b56691f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-junk-in-default-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid sizes-microsyntax-junk-in-default</title>
+<img sizes='(min-width:500px) 500px, 100vw foo bar' srcset='x 100w, y 200w' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-junk-in-source-size-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-junk-in-source-size-novalid.html
new file mode 100644
index 00000000000..1fc7cffec92
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-junk-in-source-size-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid sizes-microsyntax-junk-in-source-size</title>
+<img sizes='(min-width:500px) 500px foo bar, 100vw' srcset='x 100w, y 200w' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-khz-source-size-value-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-khz-source-size-value-novalid.html
new file mode 100644
index 00000000000..039da34cf69
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-khz-source-size-value-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid sizes-microsyntax-khz-source-size-value</title>
+<img sizes='1kHz' srcset='x 100w, y 200w' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-media-all-and-min-width-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-media-all-and-min-width-novalid.html
new file mode 100644
index 00000000000..1ac0cf6e31a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-media-all-and-min-width-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid sizes-microsyntax-media-all-and-min-width</title>
+<img sizes='all and (min-width:500px) 500px, 100vw' srcset='x 100w, y 200w' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-media-all-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-media-all-novalid.html
new file mode 100644
index 00000000000..453ba8ac9e2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-media-all-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid sizes-microsyntax-media-all</title>
+<img sizes='all 500px, 100vw' srcset='x 100w, y 200w' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-media-bad-junk-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-media-bad-junk-novalid.html
new file mode 100644
index 00000000000..27fc624ac53
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-media-bad-junk-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid sizes-microsyntax-media-bad-junk</title>
+<img sizes='(}) 500px, 100vw' srcset='x 100w, y 200w' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-media-general-enclosed-junk-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-media-general-enclosed-junk-novalid.html
new file mode 100644
index 00000000000..b8b8f8e9909
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-media-general-enclosed-junk-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid sizes-microsyntax-media-general-enclosed-junk</title>
+<img sizes='(123) 500px, 100vw' srcset='x 100w, y 200w' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-media-min-width-no-parenthesis-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-media-min-width-no-parenthesis-novalid.html
new file mode 100644
index 00000000000..b442eeddcc1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-media-min-width-no-parenthesis-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid sizes-microsyntax-media-min-width-no-parenthesis</title>
+<img sizes='min-width:500px 500px, 100vw' srcset='x 100w, y 200w' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-ms-source-size-value-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-ms-source-size-value-novalid.html
new file mode 100644
index 00000000000..4fa0acf7c17
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-ms-source-size-value-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid sizes-microsyntax-ms-source-size-value</title>
+<img sizes='1ms' srcset='x 100w, y 200w' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-negative-source-size-value-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-negative-source-size-value-novalid.html
new file mode 100644
index 00000000000..0ac929a8194
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-negative-source-size-value-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid sizes-microsyntax-negative-source-size-value</title>
+<img sizes='-1px' srcset='x 100w, y 200w' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-no-unit-in-source-size-value-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-no-unit-in-source-size-value-novalid.html
new file mode 100644
index 00000000000..6c018626950
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-no-unit-in-source-size-value-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid sizes-microsyntax-no-unit-in-source-size-value</title>
+<img sizes='(min-width:500px) 50, 100vw' srcset='x 100w, y 200w' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-percent-in-source-size-value-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-percent-in-source-size-value-novalid.html
new file mode 100644
index 00000000000..2864631e091
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-percent-in-source-size-value-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid sizes-microsyntax-percent-in-source-size-value</title>
+<img sizes='(min-width:500px) 50%, 100vw' srcset='x 100w, y 200w' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-rad-source-size-value-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-rad-source-size-value-novalid.html
new file mode 100644
index 00000000000..ec98f9d349f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-rad-source-size-value-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid sizes-microsyntax-rad-source-size-value</title>
+<img sizes='1rad' srcset='x 100w, y 200w' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-s-source-size-value-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-s-source-size-value-novalid.html
new file mode 100644
index 00000000000..a85f14d9190
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-s-source-size-value-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid sizes-microsyntax-s-source-size-value</title>
+<img sizes='1s' srcset='x 100w, y 200w' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-scientific-notation-negative-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-scientific-notation-negative-novalid.html
new file mode 100644
index 00000000000..8a4d9c66830
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-scientific-notation-negative-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid sizes-microsyntax-scientific-notation-negative</title>
+<img sizes='-1e+0px' srcset='x 100w, y 200w' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-scientific-notation-non-integer-in-exponent-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-scientific-notation-non-integer-in-exponent-novalid.html
new file mode 100644
index 00000000000..08db943cd92
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-scientific-notation-non-integer-in-exponent-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid sizes-microsyntax-scientific-notation-non-integer-in-exponent</title>
+<img sizes='1e+1.5px' srcset='x 100w, y 200w' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-trailing-comma-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-trailing-comma-novalid.html
new file mode 100644
index 00000000000..8a6a809375f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-trailing-comma-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid sizes-microsyntax-trailing-comma</title>
+<img sizes='(min-width:500px) 500px, 100vw,' srcset='x 100w, y 200w' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-trailing-junk-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-trailing-junk-novalid.html
new file mode 100644
index 00000000000..d987fecfc24
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-trailing-junk-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid sizes-microsyntax-trailing-junk</title>
+<img sizes='(min-width:500px) 500px, 100vw, foo bar' srcset='x 100w, y 200w' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-turn-source-size-value-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-turn-source-size-value-novalid.html
new file mode 100644
index 00000000000..6edfd39c8af
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-turn-source-size-value-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid sizes-microsyntax-turn-source-size-value</title>
+<img sizes='1turn' srcset='x 100w, y 200w' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-two-defaults-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-two-defaults-novalid.html
new file mode 100644
index 00000000000..ee6ce9f63e3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/sizes-microsyntax-two-defaults-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid sizes-microsyntax-two-defaults</title>
+<img sizes='500px, 100vw' srcset='x 100w, y 200w' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-after-img-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-after-img-novalid.html
new file mode 100644
index 00000000000..3a209dc590d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-after-img-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid source-after-img</title>
+<picture><img src=x alt><source srcset=x></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-align-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-align-novalid.html
new file mode 100644
index 00000000000..e1584674f0c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-align-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid source-align</title>
+<picture><source srcset=x align=left><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-alt-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-alt-novalid.html
new file mode 100644
index 00000000000..0bd6646f096
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-alt-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid source-alt</title>
+<picture><source srcset=x alt><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-aria-role-img-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-aria-role-img-novalid.html
new file mode 100644
index 00000000000..6f8d130aa1f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-aria-role-img-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid source-aria-role-img</title>
+<picture><source role=img srcset=x><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-aria-role-presentation-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-aria-role-presentation-novalid.html
new file mode 100644
index 00000000000..b0fcbc05e10
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-aria-role-presentation-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid source-aria-role-presentation</title>
+<picture><source role=presentation srcset=x><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-before-and-after-img-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-before-and-after-img-novalid.html
new file mode 100644
index 00000000000..3e083105bbc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-before-and-after-img-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid source-before-and-after-img</title>
+<picture><source srcset=x><img src=x alt><source srcset=x></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-border-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-border-novalid.html
new file mode 100644
index 00000000000..fa746a81d98
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-border-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid source-border</title>
+<picture><source srcset=x border=1><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-crossorigin-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-crossorigin-novalid.html
new file mode 100644
index 00000000000..a4ebb7ecb0d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-crossorigin-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid source-crossorigin</title>
+<picture><source srcset=x crossorigin><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-height-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-height-novalid.html
new file mode 100644
index 00000000000..2eeb159345c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-height-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid source-height</title>
+<picture><source srcset=x height=100><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-hspace-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-hspace-novalid.html
new file mode 100644
index 00000000000..a6e717357f7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-hspace-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid source-hspace</title>
+<picture><source srcset=x hspace=1><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-ismap-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-ismap-novalid.html
new file mode 100644
index 00000000000..2c02869e357
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-ismap-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid source-ismap</title>
+<picture><source srcset=x ismap><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-longdesc-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-longdesc-novalid.html
new file mode 100644
index 00000000000..c523ef21076
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-longdesc-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid source-longdesc</title>
+<picture><source srcset=x longdesc=x><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-name-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-name-novalid.html
new file mode 100644
index 00000000000..dab3247e773
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-name-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid source-name</title>
+<picture><source srcset=x crossorigin><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-no-srcset-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-no-srcset-novalid.html
new file mode 100644
index 00000000000..acb6eab05bf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-no-srcset-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid source-no-srcset</title>
+<picture><source><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-no-srcset-with-media-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-no-srcset-with-media-novalid.html
new file mode 100644
index 00000000000..a7625f755a2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-no-srcset-with-media-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid source-no-srcset-with-media</title>
+<picture><source media=screen><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-no-srcset-with-sizes-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-no-srcset-with-sizes-novalid.html
new file mode 100644
index 00000000000..517c67054b7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-no-srcset-with-sizes-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid source-no-srcset-with-sizes</title>
+<picture><source sizes=50vw><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-no-srcset-with-type-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-no-srcset-with-type-novalid.html
new file mode 100644
index 00000000000..510c7eed6b9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-no-srcset-with-type-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid source-no-srcset-with-type</title>
+<picture><source type='image/webp'><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-src-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-src-novalid.html
new file mode 100644
index 00000000000..a5eff2b7019
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-src-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid source-src</title>
+<picture><source src=x><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-src-srcset-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-src-srcset-novalid.html
new file mode 100644
index 00000000000..80714cb86fb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-src-srcset-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid source-src-srcset</title>
+<picture><source src=x srcset=x><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-srcset-h-with-sizes-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-srcset-h-with-sizes-novalid.html
new file mode 100644
index 00000000000..5da6331e539
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-srcset-h-with-sizes-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid source-srcset-h-with-sizes</title>
+<picture><source srcset='x 100h, y 200h' sizes=50vw><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-srcset-w-and-x-with-sizes-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-srcset-w-and-x-with-sizes-novalid.html
new file mode 100644
index 00000000000..cf6603ea8ff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-srcset-w-and-x-with-sizes-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid source-srcset-w-and-x-with-sizes</title>
+<picture><source srcset='x 100w, y 2x' sizes=50vw><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-srcset-w-no-sizes-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-srcset-w-no-sizes-novalid.html
new file mode 100644
index 00000000000..0375c5415f2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-srcset-w-no-sizes-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid source-srcset-w-no-sizes</title>
+<picture><source srcset='x 100w, y 200w'><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-srcset-x-with-sizes-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-srcset-x-with-sizes-novalid.html
new file mode 100644
index 00000000000..a8efda291ee
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-srcset-x-with-sizes-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid source-srcset-x-with-sizes</title>
+<picture><source srcset='x 1x, y 2x' sizes=50vw><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-type-srcset-w-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-type-srcset-w-novalid.html
new file mode 100644
index 00000000000..a9ccaa312b8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-type-srcset-w-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid source-type-srcset-w</title>
+<picture><source srcset='x 100w, y 200w' type=image/gif><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-usemap-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-usemap-novalid.html
new file mode 100644
index 00000000000..603bb472d8a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-usemap-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid source-usemap</title>
+<picture><source srcset=x usemap><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-vspace-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-vspace-novalid.html
new file mode 100644
index 00000000000..2e26c73ce44
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-vspace-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid source-vspace</title>
+<picture><source srcset=x vspace=1><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-width-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-width-novalid.html
new file mode 100644
index 00000000000..1649b791b29
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/source-width-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid source-width</title>
+<picture><source srcset=x width=100><img src=x alt></picture> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-broken-url-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-broken-url-novalid.html
new file mode 100644
index 00000000000..82388ab5136
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-broken-url-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid srcset-microsyntax-broken-url</title>
+<img srcset='http: 1x' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-comma-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-comma-novalid.html
new file mode 100644
index 00000000000..ff36674849e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-comma-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid srcset-microsyntax-comma</title>
+<img srcset=',' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-css-comment-after-descriptor-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-css-comment-after-descriptor-novalid.html
new file mode 100644
index 00000000000..758c3551ca7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-css-comment-after-descriptor-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid srcset-microsyntax-css-comment-after-descriptor</title>
+<img srcset='x 2x/**/' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-curly-bracket-junk-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-curly-bracket-junk-novalid.html
new file mode 100644
index 00000000000..346f160886d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-curly-bracket-junk-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid srcset-microsyntax-curly-bracket-junk</title>
+<img srcset='x {, y 1x' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-empty-novalid.html
new file mode 100644
index 00000000000..ad8a12a3a03
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid srcset-microsyntax-empty</title>
+<img srcset='' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-function-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-function-novalid.html
new file mode 100644
index 00000000000..499a14752b4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-function-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid srcset-microsyntax-function</title>
+<img srcset='x foobar(baz quux, lol), y 1x' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-h-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-h-novalid.html
new file mode 100644
index 00000000000..3c381e04eba
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-h-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid srcset-microsyntax-h</title>
+<img srcset='x 1h' sizes=100vw src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-infinity-x-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-infinity-x-novalid.html
new file mode 100644
index 00000000000..51aba7b2970
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-infinity-x-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid srcset-microsyntax-infinity-x</title>
+<img srcset='x Infinityx' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-leading-comma-multiple-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-leading-comma-multiple-novalid.html
new file mode 100644
index 00000000000..c715e0e35d0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-leading-comma-multiple-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid srcset-microsyntax-leading-comma-multiple</title>
+<img srcset=',,,x' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-leading-comma-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-leading-comma-novalid.html
new file mode 100644
index 00000000000..ad138943734
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-leading-comma-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid srcset-microsyntax-leading-comma</title>
+<img srcset=',x' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-leading-dot-x-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-leading-dot-x-novalid.html
new file mode 100644
index 00000000000..3a9da140b6b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-leading-dot-x-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid srcset-microsyntax-leading-dot-x</title>
+<img srcset='x .5x' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-nan-x-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-nan-x-novalid.html
new file mode 100644
index 00000000000..da7d829dff6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-nan-x-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid srcset-microsyntax-nan-x</title>
+<img srcset='x NaNx' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-negative-w-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-negative-w-novalid.html
new file mode 100644
index 00000000000..0e61668fd88
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-negative-w-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid srcset-microsyntax-negative-w</title>
+<img srcset='x -1w' sizes=100vw src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-negative-x-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-negative-x-novalid.html
new file mode 100644
index 00000000000..08e5fb70a4a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-negative-x-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid srcset-microsyntax-negative-x</title>
+<img srcset='x -1x' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-negative-zero-w-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-negative-zero-w-novalid.html
new file mode 100644
index 00000000000..ebc5d346a76
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-negative-zero-w-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid srcset-microsyntax-negative-zero-w</title>
+<img srcset='x -0w' sizes=100vw src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-negative-zero-x-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-negative-zero-x-novalid.html
new file mode 100644
index 00000000000..d1260c027fb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-negative-zero-x-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid srcset-microsyntax-negative-zero-x</title>
+<img srcset='x -0x' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-non-integer-w-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-non-integer-w-novalid.html
new file mode 100644
index 00000000000..05554d8ee37
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-non-integer-w-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid srcset-microsyntax-non-integer-w</title>
+<img srcset='x 1.5w' sizes=100vw src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-parenthesis-junk-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-parenthesis-junk-novalid.html
new file mode 100644
index 00000000000..1459e1610b2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-parenthesis-junk-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid srcset-microsyntax-parenthesis-junk</title>
+<img srcset='x ><(((((o)>, y 1x' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-pipe-junk-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-pipe-junk-novalid.html
new file mode 100644
index 00000000000..7c1ee3a0414
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-pipe-junk-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid srcset-microsyntax-pipe-junk</title>
+<img srcset='x ||, y 1x' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-plus-w-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-plus-w-novalid.html
new file mode 100644
index 00000000000..c452c91738e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-plus-w-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid srcset-microsyntax-plus-w</title>
+<img srcset='x +1w' sizes=100vw src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-plus-x-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-plus-x-novalid.html
new file mode 100644
index 00000000000..7c285635d96
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-plus-x-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid srcset-microsyntax-plus-x</title>
+<img srcset='x +1x' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-scientific-notation-w-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-scientific-notation-w-novalid.html
new file mode 100644
index 00000000000..b1be3575390
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-scientific-notation-w-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid srcset-microsyntax-scientific-notation-w</title>
+<img srcset='x 1e0w' sizes=100vw src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-square-bracket-junk-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-square-bracket-junk-novalid.html
new file mode 100644
index 00000000000..effc9379673
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-square-bracket-junk-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid srcset-microsyntax-square-bracket-junk</title>
+<img srcset='x [, y 1x' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-trailing-comma-multiple-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-trailing-comma-multiple-novalid.html
new file mode 100644
index 00000000000..869af64fa5b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-trailing-comma-multiple-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid srcset-microsyntax-trailing-comma-multiple</title>
+<img srcset='x,,,' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-trailing-comma-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-trailing-comma-novalid.html
new file mode 100644
index 00000000000..9250e468dff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-trailing-comma-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid srcset-microsyntax-trailing-comma</title>
+<img srcset='x,' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-unique-descriptors-1x-and-omitted-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-unique-descriptors-1x-and-omitted-novalid.html
new file mode 100644
index 00000000000..72bc68e075b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-unique-descriptors-1x-and-omitted-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid srcset-microsyntax-unique-descriptors-1x-and-omitted</title>
+<img srcset='x 1x, y' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-unique-descriptors-2x-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-unique-descriptors-2x-novalid.html
new file mode 100644
index 00000000000..9ab38cd2412
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-unique-descriptors-2x-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid srcset-microsyntax-unique-descriptors-2x</title>
+<img srcset='x 2x, y 2x' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-unique-descriptors-integer-and-decimals-x-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-unique-descriptors-integer-and-decimals-x-novalid.html
new file mode 100644
index 00000000000..76d6eeccf49
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-unique-descriptors-integer-and-decimals-x-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid srcset-microsyntax-unique-descriptors-integer-and-decimals-x</title>
+<img srcset='x 1x, y 1.0x' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-unique-descriptors-w-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-unique-descriptors-w-novalid.html
new file mode 100644
index 00000000000..d5c8fdab130
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-unique-descriptors-w-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid srcset-microsyntax-unique-descriptors-w</title>
+<img srcset='x 1w, y 1w' sizes=100vw src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-uppercase-w-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-uppercase-w-novalid.html
new file mode 100644
index 00000000000..51601192f3f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-uppercase-w-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid srcset-microsyntax-uppercase-w</title>
+<img srcset='x 1W' sizes=100vw src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-w-and-h-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-w-and-h-novalid.html
new file mode 100644
index 00000000000..84ef6ae2bb8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-w-and-h-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid srcset-microsyntax-w-and-h</title>
+<img srcset='x 1w 1h' sizes=100vw src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-w-and-no-descriptor-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-w-and-no-descriptor-novalid.html
new file mode 100644
index 00000000000..78c44834ef3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-w-and-no-descriptor-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid srcset-microsyntax-w-and-no-descriptor</title>
+<img srcset='x 1w, y' sizes=100vw src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-x-and-h-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-x-and-h-novalid.html
new file mode 100644
index 00000000000..4c26cfaf3b9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-x-and-h-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid srcset-microsyntax-x-and-h</title>
+<img srcset='x 1x 1h' sizes=100vw src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-x-and-w-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-x-and-w-novalid.html
new file mode 100644
index 00000000000..3c0cd89b9fe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-x-and-w-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid srcset-microsyntax-x-and-w</title>
+<img srcset='x 1x 1w' sizes=100vw src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-zero-w-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-zero-w-novalid.html
new file mode 100644
index 00000000000..908343f81b2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-zero-w-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid srcset-microsyntax-zero-w</title>
+<img srcset='x 0w' sizes=100vw src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-zero-x-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-zero-x-novalid.html
new file mode 100644
index 00000000000..fbf7e98e698
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/srcset-microsyntax-zero-x-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid srcset-microsyntax-zero-x</title>
+<img srcset='x 0x' src=x alt> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/svg-image-srcset-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/svg-image-srcset-novalid.html
new file mode 100644
index 00000000000..22950c23e83
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/svg-image-srcset-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid svg-image-srcset</title>
+<svg><image xlink:href=x srcset=x width=1 height=1 /></svg> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/track-srcset-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/track-srcset-novalid.html
new file mode 100644
index 00000000000..99dd22be0fd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/track-srcset-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid track-srcset</title>
+<video src=x><track src=x srcset=x></video> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/video-source-media-src-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/video-source-media-src-novalid.html
new file mode 100644
index 00000000000..f065a12f493
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/video-source-media-src-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid video-source-media-src</title>
+<video><source media=screen src=x></video> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/video-source-sizes-srcset-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/video-source-sizes-srcset-novalid.html
new file mode 100644
index 00000000000..a20fd2db626
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/video-source-sizes-srcset-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid video-source-sizes-srcset</title>
+<video><source sizes=50vw srcset='x 100w'></video> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/video-source-srcset-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/video-source-srcset-novalid.html
new file mode 100644
index 00000000000..bde4a64b8f6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/video-source-srcset-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid video-source-srcset</title>
+<video><source srcset=x></video> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/video-source-srcset-src-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/video-source-srcset-src-novalid.html
new file mode 100644
index 00000000000..f7bf4844654
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/video-source-srcset-src-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid video-source-srcset-src</title>
+<video><source srcset=x src=x></video> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/video-srcset-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/video-srcset-novalid.html
new file mode 100644
index 00000000000..2115044869d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/picture/video-srcset-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid video-srcset</title>
+<video src=x srcset=x></video> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/pre/model-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/pre/model-isvalid.html
new file mode 100644
index 00000000000..99d1a75be23
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/pre/model-isvalid.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;pre&gt;</title>
+</head>
+<body>
+ <!-- is block -->
+ <pre class="class" id="id" lang="en">text</pre>
+
+ <!-- can contain interactive -->
+ <pre><a>text</a></pre>
+
+ <!-- can contain strictly inline -->
+ <pre>text <em>elem</em></pre>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/pre/model-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/pre/model-novalid.html
new file mode 100644
index 00000000000..384386c2b0a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/pre/model-novalid.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;pre&gt;</title>
+</head>
+<body>
+ <!-- is block -->
+ <pre class="class" id="id" lang="en">text</pre>
+
+ <!-- is structured inline -->
+ <p>paragraph
+ <pre>text</pre>
+ </p>
+
+ <!-- can contain interactive -->
+ <pre><a>text</a></pre>
+ <!-- but not struct-inline -->
+ <p>paragraph
+ <pre><a>text</a></pre>
+ </p>
+
+ <!-- can contain strictly inline -->
+ <pre>text <em>elem</em></pre>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite-empty-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite-empty-isvalid.html
new file mode 100644
index 00000000000..1621184c729
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite-empty-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>empty cite is valid</title>
+<q cite=""></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite-isvalid.html
new file mode 100644
index 00000000000..0f4f7391fd5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite-isvalid.html
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid cite</title>
+<q cite="file:///"></q><!-- scheme-file-slash-slash-slash-only -->
+<q cite="http://a:@www.example.com"></q><!-- userinfo-password-empty -->
+<q cite="foo://///////"></q><!-- scheme-private-path-leading-slashes-only -->
+<q cite="file://abc|/foo/bar"></q><!-- scheme-file-slash-slash-abc-bar -->
+<q cite="/a/b/c"></q><!-- path-simple-relative -->
+<q cite="http://example.com/你好你好"></q><!-- path-unicode-han -->
+<q cite="/a/%2f/c"></q><!-- path-percent-encoded-slash-plus-slashes-relative -->
+<q cite="http://f:/c"></q><!-- port-none-but-colon -->
+<q cite="http://example.com/foo%41%7a"></q><!-- path-percent-encoded-multiple -->
+<q cite="http://192.168.0.257/"></q><!-- host-IP-address-broken -->
+<q cite="madeupscheme:example.com/"></q><!-- scheme-private-no-slash -->
+<q cite="?"></q><!-- query-empty-no-path-relative -->
+<q cite="http://example.com/%20foo"></q><!-- path-percent-encoded-space -->
+<q cite="mailto:/example.com/"></q><!-- scheme-mailto-single-slash -->
+<q cite="::"></q><!-- path-leading-colon-colon-relative -->
+<q cite="http://example.com/%3A%3a%3C%3c"></q><!-- path-percent-encoded-mixed-case -->
+<q cite="http://user:pass@foo:21/bar;par?b#c"></q><!-- userinfo -->
+<q cite="ws:/example.com/"></q><!-- scheme-ws-single-slash -->
+<q cite="foo://"></q><!-- scheme-private-slash-slash -->
+<q cite="#"></q><!-- fragment-empty-hash-only-no-path-relative -->
+<q cite="http://f:00000000000000/c"></q><!-- port-00000000000000 -->
+<q cite="foo:////://///"></q><!-- scheme-private-path-leading-slashes-colon-slashes -->
+<q cite=":23"></q><!-- path-leading-colon-number-relative -->
+<q cite="foo:/"></q><!-- scheme-private-slash -->
+<q cite="http://💩"></q><!-- host-is-pile-of-poo -->
+<q cite="file:test"></q><!-- scheme-file-no-slash -->
+<q cite="file://C|/foo/bar"></q><!-- scheme-file-slash-slash-c-bar -->
+<q cite="#/"></q><!-- fragment-slash-relative -->
+<q cite="http://192.0x00A80001"></q><!-- host-192.0x00A80001 -->
+<q cite="foo.com"></q><!-- scheme-none-relative -->
+<q cite="http💩//:foo"></q><!-- path-contains-pile-of-poo -->
+<q cite="File://foo/bar.html"></q><!-- scheme-file-uppercase -->
+<q cite=":/"></q><!-- path-leading-colon-slash-relative -->
+<q cite="http://www.foo。bar.com"></q><!-- host-exotic-dot -->
+<q cite="http://GOO​⁠goo.com"></q><!-- host-exotic-whitespace -->
+<q cite="file:///foo/bar.txt"></q><!-- scheme-file-host-empty -->
+<q cite="javascript:/example.com/"></q><!-- scheme-javascript-single-slash -->
+<q cite="gopher:/example.com/"></q><!-- scheme-gopher-single-slash -->
+<q cite="ftps:example.com/"></q><!-- scheme-ftps-no-slash -->
+<q cite="file://server/foo/bar"></q><!-- scheme-file-host-included -->
+<q cite="http://example.com/foo%00"></q><!-- path-percent-encoded-u0000 -->
+<q cite="a:foo.com"></q><!-- scheme-private -->
+<q cite=":"></q><!-- path-colon-relative -->
+<q cite="http://:b@www.example.com"></q><!-- userinfo-user-empty -->
+<q cite="file:/"></q><!-- scheme-file-slash-only -->
+<q cite="wss:example.com/"></q><!-- scheme-wss-no-slash -->
+<q cite="::23"></q><!-- path-colon-colon-number-relative -->
+<q cite="/a%2fc"></q><!-- path-percent-encoded-slash-relative -->
+<q cite="http://a:b@c:29/d"></q><!-- userinfo-host-port-path -->
+<q cite="gopher:example.com/"></q><!-- scheme-gopher-no-slash -->
+<q cite="madeupscheme:/example.com/"></q><!-- scheme-private-single-slash -->
+<q cite="mailto:example.com/"></q><!-- scheme-mailto-no-slash -->
+<q cite="http://%25DOMAIN:foobar@foodomain.com"></q><!-- userinfo-username-contains-percent-encoded -->
+<q cite="/:23"></q><!-- path-slash-colon-number-relative -->
+<q cite="foo://///////bar.com/"></q><!-- scheme-private-path-leading-slashes-chars -->
+<q cite="http://[2001::1]:80"></q><!-- host-ipv6-port -->
+<q cite="data:text/plain,foo"></q><!-- scheme-data-no-slash -->
+<q cite="http://example.com/foo/%2e"></q><!-- path-percent-encoded-dot -->
+<q cite="file:/example.com/"></q><!-- scheme-file-single-slash -->
+<q cite="http://example.com/©zbar"></q><!-- path-non-ascii -->
+<q cite="http://example.com//foo"></q><!-- path-uFEFF -->
+<q cite="wss:/example.com/"></q><!-- scheme-wss-single-slash -->
+<q cite="http://foo/abcd#foo?bar"></q><!-- fragment-contains-question-mark -->
+<q cite=":#"></q><!-- path-leading-colon-hash-relative -->
+<q cite="http://example.com/foo%91"></q><!-- path-percent-encoded-u0091 -->
+<q cite="c:/foo"></q><!-- scheme-private-single-letter -->
+<q cite=":foo.com"></q><!-- path-leading-colon-chars-relative -->
+<q cite="http://你好你好"></q><!-- host-idn-unicode-han -->
+<q cite="http://example.com/foo#💩"></q><!-- fragment-contains-pile-of-poo -->
+<q cite="file:"></q><!-- scheme-file-scheme-only -->
+<q cite="#β"></q><!-- fragment-non-ascii-relative -->
+<q cite="foo:/bar.com/"></q><!-- scheme-private-path -->
+<q cite="http://f:0/c"></q><!-- port-0 -->
+<q cite="#;?"></q><!-- fragment-semicolon-question-mark-relative -->
+<q cite="http://Go.com"></q><!-- host-fullwidth -->
+<q cite="http://@www.example.com"></q><!-- userinfo-empty -->
+<q cite="http://example.com/‮/foo/‭/bar"></q><!-- path-u202E-u202D -->
+<q cite="http://[2001::1]"></q><!-- host-ipv6 -->
+<q cite="💩http://foo"></q><!-- path-starts-with-pile-of-poo -->
+<q cite="http://foo/abcd?efgh?ijkl"></q><!-- query-contains-question-mark -->
+<q cite="//foo/bar"></q><!-- scheme-schemeless-relative -->
+<q cite="ftps:/example.com/"></q><!-- scheme-ftps-single-slash -->
+<q cite="http://foo.com:b@d/"></q><!-- userinfo-username-non-alpha -->
+<q cite=":a"></q><!-- path-leading-colon-letter-relative -->
+<q cite="/"></q><!-- path-slash-only-relative -->
+<q cite="http://example.com/foo?💩"></q><!-- query-contains-pile-of-poo -->
+<q cite="http://f:00000000000000000000080/c"></q><!-- port-00000000000000000000080 -->
+<q cite="file://"></q><!-- scheme-file-slash-slash-only -->
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/fragment-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/fragment-backslash-novalid.html
new file mode 100644
index 00000000000..6c7cc13940a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/fragment-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: fragment-backslash</title>
+<q cite="#\"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/fragment-contains-hash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/fragment-contains-hash-novalid.html
new file mode 100644
index 00000000000..7a7af4f659b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/fragment-contains-hash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: fragment-contains-hash</title>
+<q cite="http://foo/path#f#g"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/fragment-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/fragment-leading-space-novalid.html
new file mode 100644
index 00000000000..25b1122c3a9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/fragment-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: fragment-leading-space</title>
+<q cite="http://f:21/b# e"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-cr-novalid.html
new file mode 100644
index 00000000000..cf065e28c73
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-cr</title>
+<q cite="http://example. org"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-double-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-double-percent-encoded-novalid.html
new file mode 100644
index 00000000000..1c89424f3cf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-double-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-double-percent-encoded</title>
+<q cite="http://%41.com"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-double-percent-encoded-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-double-percent-encoded-percent-encoded-novalid.html
new file mode 100644
index 00000000000..30cdf591dc0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-double-percent-encoded-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-double-percent-encoded-percent-encoded</title>
+<q cite="http://%ef%bc%85%ef%bc%94%ef%bc%91.com"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-empty-novalid.html
new file mode 100644
index 00000000000..59318111b36
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-empty</title>
+<q cite="http://"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-empty-userinfo-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-empty-userinfo-empty-novalid.html
new file mode 100644
index 00000000000..2bc854d87b7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-empty-userinfo-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-empty-userinfo-empty</title>
+<q cite="http://@/www.example.com"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-empty-with-userinfo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-empty-with-userinfo-novalid.html
new file mode 100644
index 00000000000..e495b8067c4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-empty-with-userinfo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-empty-with-userinfo</title>
+<q cite="http://user:pass@/"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-hostname-in-brackets-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-hostname-in-brackets-novalid.html
new file mode 100644
index 00000000000..49dfc87da91
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-hostname-in-brackets-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-hostname-in-brackets</title>
+<q cite="http://[www.google.com]/"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-invalid-unicode-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-invalid-unicode-novalid.html
new file mode 100644
index 00000000000..02e4b63d04e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-invalid-unicode-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-invalid-unicode</title>
+<q cite="http://﷐zyx.com"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-invalid-unicode-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-invalid-unicode-percent-encoded-novalid.html
new file mode 100644
index 00000000000..d9ac64ee490
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-invalid-unicode-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-invalid-unicode-percent-encoded</title>
+<q cite="http://%ef%b7%90zyx.com"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-newline-novalid.html
new file mode 100644
index 00000000000..081c966eb8b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-newline</title>
+<q cite="http://example.
+org"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-space-novalid.html
new file mode 100644
index 00000000000..f12f661672f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-space</title>
+<q cite="http://example .org"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-square-brackets-port-contains-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-square-brackets-port-contains-colon-novalid.html
new file mode 100644
index 00000000000..cdf2f79cbcf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-square-brackets-port-contains-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-square-brackets-port-contains-colon</title>
+<q cite="http://[1::2]:3:4"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-tab-novalid.html
new file mode 100644
index 00000000000..479577b08d2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-tab</title>
+<q cite="http://example .org"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-u0000-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-u0000-percent-encoded-novalid.html
new file mode 100644
index 00000000000..1ef717a06ba
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-u0000-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-u0000-percent-encoded</title>
+<q cite="http://%00.com"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-u0000-percent-encoded-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-u0000-percent-encoded-percent-encoded-novalid.html
new file mode 100644
index 00000000000..ab08fdf8de3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/host-u0000-percent-encoded-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: host-u0000-percent-encoded-percent-encoded</title>
+<q cite="http://%ef%bc%85%ef%bc%90%ef%bc%90.com"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/path-bare-percent-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/path-bare-percent-sign-novalid.html
new file mode 100644
index 00000000000..0751ebd03de
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/path-bare-percent-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: path-bare-percent-sign</title>
+<q cite="http://example.com/foo%"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/path-contains-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/path-contains-space-novalid.html
new file mode 100644
index 00000000000..c262da55ddf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/path-contains-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: path-contains-space</title>
+<q cite="/a/ /c"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/path-leading-backslash-at-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/path-leading-backslash-at-sign-novalid.html
new file mode 100644
index 00000000000..67bb53f459e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/path-leading-backslash-at-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: path-leading-backslash-at-sign</title>
+<q cite="http://foo.com/\@"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/path-leading-colon-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/path-leading-colon-backslash-novalid.html
new file mode 100644
index 00000000000..2210cde73dc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/path-leading-colon-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: path-leading-colon-backslash</title>
+<q cite=":\"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/path-leading-colon-chars-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/path-leading-colon-chars-backslash-novalid.html
new file mode 100644
index 00000000000..96cedcfc069
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/path-leading-colon-chars-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: path-leading-colon-chars-backslash</title>
+<q cite=":foo.com\"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/path-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/path-leading-space-novalid.html
new file mode 100644
index 00000000000..3339c6f749f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/path-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: path-leading-space</title>
+<q cite="http://f:21/ b"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/path-percent-encoded-malformed-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/path-percent-encoded-malformed-novalid.html
new file mode 100644
index 00000000000..d186e987c54
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/path-percent-encoded-malformed-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: path-percent-encoded-malformed</title>
+<q cite="http://example.com/foo/%2e%2"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/path-relative-square-brackets-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/path-relative-square-brackets-novalid.html
new file mode 100644
index 00000000000..1e7b9025fad
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/path-relative-square-brackets-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: path-relative-square-brackets</title>
+<q cite="[61:24:74]:98"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/path-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/path-tab-novalid.html
new file mode 100644
index 00000000000..636733d65ea
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/path-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: path-tab</title>
+<q cite="http://example.com/foo bar"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/path-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/path-trailing-space-novalid.html
new file mode 100644
index 00000000000..9526b3d3db7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/path-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: path-trailing-space</title>
+<q cite="http://f:21/b ?"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/path-u0091-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/path-u0091-novalid.html
new file mode 100644
index 00000000000..93340436abd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/path-u0091-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: path-u0091</title>
+<q cite="http://example.com/foo‘"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/port-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/port-cr-novalid.html
new file mode 100644
index 00000000000..976e030aaa3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/port-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: port-cr</title>
+<q cite="http://f: /c"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/port-leading-colon-bracket-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/port-leading-colon-bracket-colon-novalid.html
new file mode 100644
index 00000000000..0d2cdef269e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/port-leading-colon-bracket-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: port-leading-colon-bracket-colon</title>
+<q cite="http://2001::1]:80"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/port-leading-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/port-leading-colon-novalid.html
new file mode 100644
index 00000000000..0edae205d11
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/port-leading-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: port-leading-colon</title>
+<q cite="http://2001::1"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/port-leading-dash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/port-leading-dash-novalid.html
new file mode 100644
index 00000000000..7e0ae9e730c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/port-leading-dash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: port-leading-dash</title>
+<q cite="http://foo:-80/"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/port-multiple-letters-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/port-multiple-letters-novalid.html
new file mode 100644
index 00000000000..32c1e93b125
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/port-multiple-letters-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: port-multiple-letters</title>
+<q cite="http://f:fifty-two/c"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/port-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/port-newline-novalid.html
new file mode 100644
index 00000000000..3b79fcda40d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/port-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: port-newline</title>
+<q cite="http://f:
+/c"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/port-single-letter-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/port-single-letter-novalid.html
new file mode 100644
index 00000000000..47a7fb952b2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/port-single-letter-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: port-single-letter</title>
+<q cite="http://f:b/c"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/port-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/port-space-novalid.html
new file mode 100644
index 00000000000..4e88d648334
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/port-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: port-space</title>
+<q cite="http://f: /c"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/port-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/port-tab-novalid.html
new file mode 100644
index 00000000000..f2cf428fccc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/port-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: port-tab</title>
+<q cite="http://f: /c"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/query-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/query-leading-space-novalid.html
new file mode 100644
index 00000000000..2b1713d2553
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/query-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: query-leading-space</title>
+<q cite="http://f:21/b? d"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/query-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/query-trailing-space-novalid.html
new file mode 100644
index 00000000000..7dd56090b83
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/query-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: query-trailing-space</title>
+<q cite="http://f:21/b?d #"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-data-contains-fragment-haswarn.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-data-contains-fragment-haswarn.html
new file mode 100644
index 00000000000..6c0e8e9d4ad
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-data-contains-fragment-haswarn.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>data:text/html,test#test warning: scheme-data-contains-fragment</title>
+<q cite="data:text/html,test#test"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-data-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-data-single-slash-novalid.html
new file mode 100644
index 00000000000..35713a0cd89
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-data-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-data-single-slash</title>
+<q cite="data:/example.com/"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-file-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-file-backslash-novalid.html
new file mode 100644
index 00000000000..9fd2264d374
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-file-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-file-backslash</title>
+<q cite="file:c:\foo\bar.html"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-file-single-slash-c-bar-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-file-single-slash-c-bar-novalid.html
new file mode 100644
index 00000000000..fa4d6b9af73
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-file-single-slash-c-bar-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-file-single-slash-c-bar</title>
+<q cite="file:/C|/foo/bar"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-file-triple-slash-c-bar-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-file-triple-slash-c-bar-novalid.html
new file mode 100644
index 00000000000..17355d96957
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-file-triple-slash-c-bar-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-file-triple-slash-c-bar</title>
+<q cite="file:///C|/foo/bar"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-ftp-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-ftp-no-slash-novalid.html
new file mode 100644
index 00000000000..b842e1a181c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-ftp-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-ftp-no-slash</title>
+<q cite="ftp:example.com/"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-ftp-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-ftp-single-slash-novalid.html
new file mode 100644
index 00000000000..8bdafa6b82e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-ftp-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-ftp-single-slash</title>
+<q cite="ftp:/example.com/"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-http-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-http-backslash-novalid.html
new file mode 100644
index 00000000000..78bc526458f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-http-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-http-backslash</title>
+<q cite="http:\\foo.com\"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-http-no-slash-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-http-no-slash-colon-novalid.html
new file mode 100644
index 00000000000..60a6b9b9752
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-http-no-slash-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-http-no-slash-colon</title>
+<q cite="http::@c:29"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-http-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-http-no-slash-novalid.html
new file mode 100644
index 00000000000..edf9a5d7f1b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-http-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-http-no-slash</title>
+<q cite="http:foo.com"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-http-no-slash-square-bracket-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-http-no-slash-square-bracket-novalid.html
new file mode 100644
index 00000000000..6858419ba04
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-http-no-slash-square-bracket-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-http-no-slash-square-bracket</title>
+<q cite="http:[61:27]/:foo"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-http-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-http-single-slash-novalid.html
new file mode 100644
index 00000000000..fb470d393c3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-http-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-http-single-slash</title>
+<q cite="http:/example.com/"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-https-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-https-no-slash-novalid.html
new file mode 100644
index 00000000000..78ebcaf5754
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-https-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-https-no-slash</title>
+<q cite="https:example.com/"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-https-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-https-single-slash-novalid.html
new file mode 100644
index 00000000000..77e41fdaf5f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-https-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-https-single-slash</title>
+<q cite="https:/example.com/"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-javascript-no-slash-malformed-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-javascript-no-slash-malformed-novalid.html
new file mode 100644
index 00000000000..a142b0040b2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-javascript-no-slash-malformed-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-javascript-no-slash-malformed</title>
+<q cite="javascript:example.com/"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-trailing-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-trailing-cr-novalid.html
new file mode 100644
index 00000000000..885454d6490
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-trailing-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-trailing-cr</title>
+<q cite="a: foo.com"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-trailing-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-trailing-newline-novalid.html
new file mode 100644
index 00000000000..7d637e10ee6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-trailing-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-trailing-newline</title>
+<q cite="a:
+foo.com"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-trailing-space-novalid.html
new file mode 100644
index 00000000000..37ca55f73e6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-trailing-space</title>
+<q cite="a: foo.com"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-trailing-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-trailing-tab-novalid.html
new file mode 100644
index 00000000000..a38c794de83
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/scheme-trailing-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: scheme-trailing-tab</title>
+<q cite="a: foo.com"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/userinfo-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/userinfo-backslash-novalid.html
new file mode 100644
index 00000000000..f83002c231f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/userinfo-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: userinfo-backslash</title>
+<q cite="http://a\b:c\d@foo.com"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/userinfo-password-bad-chars-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/userinfo-password-bad-chars-novalid.html
new file mode 100644
index 00000000000..8992b51154b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/userinfo-password-bad-chars-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: userinfo-password-bad-chars</title>
+<q cite="http://&a:foo(b]c@d:2/"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/userinfo-password-contains-pile-of-poo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/userinfo-password-contains-pile-of-poo-novalid.html
new file mode 100644
index 00000000000..aed0a860456
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/userinfo-password-contains-pile-of-poo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: userinfo-password-contains-pile-of-poo</title>
+<q cite="http://foo:💩@example.com"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/userinfo-username-contains-at-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/userinfo-username-contains-at-sign-novalid.html
new file mode 100644
index 00000000000..d78aaab3464
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/userinfo-username-contains-at-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: userinfo-username-contains-at-sign</title>
+<q cite="http://::@c@d:2"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/userinfo-username-contains-pile-of-poo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/userinfo-username-contains-pile-of-poo-novalid.html
new file mode 100644
index 00000000000..2aa14ab9933
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/cite/userinfo-username-contains-pile-of-poo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid cite: userinfo-username-contains-pile-of-poo</title>
+<q cite="http://💩:foo@example.com"></q>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/model-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/model-isvalid.html
new file mode 100644
index 00000000000..c8d8073749d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/model-isvalid.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;q&gt;</title>
+</head>
+<body>
+ <!-- is structured inline -->
+ <p><q cite="url" class="class" lang="en">text</q></p>
+
+ <!-- is strictly inline -->
+ <p><dfn><q cite="url" class="class" lang="en">text</q></dfn></p>
+
+ <!-- can be empty -->
+ <p>text <q></q></p>
+ <p>text <dfn><q></q></dfn></p>
+
+ <!-- can contain interactive -->
+ <p><q><a>text</a></q></p>
+ <p><dfn><q><a>text</a></q></dfn></p>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/model-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/model-novalid.html
new file mode 100644
index 00000000000..c742f757fb3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/q/model-novalid.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;q&gt;</title>
+</head>
+<body>
+ <!-- is structured inline -->
+ <p><q cite="url" class="class" lang="en">text</q></p>
+
+ <!-- is strictly inline -->
+ <p><dfn><q cite="url" class="class" lang="en">text</q></dfn></p>
+
+ <!-- can be empty -->
+ <p>text <q></q></p>
+ <p>text <dfn><q></q></dfn></p>
+
+ <!-- can contain interactive -->
+ <p><q><a>text</a></q></p>
+ <p><dfn><q><a>text</a></q></dfn></p>
+
+ <!-- cannot contain structured inline -->
+ <p><q>text <ul><li>list</li></ul> <em>elem</em></q></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ruby/empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ruby/empty-novalid.html
new file mode 100644
index 00000000000..8ce4ec42141
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ruby/empty-novalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta charset=utf-8>
+<title>ruby element missing rt child</title>
+</head>
+<body>
+<ruby></ruby>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ruby/missing-rt-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ruby/missing-rt-novalid.html
new file mode 100644
index 00000000000..0f8d363df98
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ruby/missing-rt-novalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta charset=utf-8>
+<title>ruby element missing rt child</title>
+</head>
+<body>
+<ruby><rt></rt><rp></rp><rp></rp></ruby>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/s/model-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/s/model-isvalid.html
new file mode 100644
index 00000000000..16474321a64
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/s/model-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>the "s" element is not obsolete</title>
+<meta charset=utf-8>
+</head>
+<body>
+<s>baz</s>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/samp/model-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/samp/model-isvalid.html
new file mode 100644
index 00000000000..4049a956936
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/samp/model-isvalid.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;samp&gt;</title>
+</head>
+<body>
+ <!-- is structured inline -->
+ <p><samp class="class" lang="en">text</samp></p>
+
+ <!-- is strictly inline -->
+ <p><dfn><samp class="class" lang="en">text</samp></dfn></p>
+
+ <!-- can be empty -->
+ <p>text <samp></samp></p>
+ <p>text <dfn><samp></samp></dfn></p>
+
+ <!-- can contain interactive -->
+ <p><samp><a>text</a></samp></p>
+ <p><dfn><samp><a>text</a></samp></dfn></p>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/samp/model-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/samp/model-novalid.html
new file mode 100644
index 00000000000..27d469d7a5c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/samp/model-novalid.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;samp&gt;</title>
+</head>
+<body>
+ <!-- is structured inline -->
+ <p><samp class="class" lang="en">text</samp></p>
+
+ <!-- is strictly inline -->
+ <p><dfn><samp class="class" lang="en">text</samp></dfn></p>
+
+ <!-- can be empty -->
+ <p>text <samp></samp></p>
+ <p>text <dfn><samp></samp></dfn></p>
+
+ <!-- can contain interactive -->
+ <p><samp><a>text</a></samp></p>
+ <p><dfn><samp><a>text</a></samp></dfn></p>
+
+ <!-- cannot contain structured inline -->
+ <p><samp>text <ul><li>list</li></ul> <em>elem</em></samp></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/language-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/language-novalid.html
new file mode 100644
index 00000000000..3ac19056a03
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/language-novalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>the "language" attribute is obsolete</title>
+<meta charset=utf-8>
+</head>
+<body>
+<script language=vbscript src=url></script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src-empty-novalid.html
new file mode 100644
index 00000000000..ebf2dca0a28
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>empty src is not valid</title>
+<script src=""></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src-isvalid.html
new file mode 100644
index 00000000000..752e2d266f5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src-isvalid.html
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid src</title>
+<script src="file:///"></script><!-- scheme-file-slash-slash-slash-only -->
+<script src="http://a:@www.example.com"></script><!-- userinfo-password-empty -->
+<script src="foo://///////"></script><!-- scheme-private-path-leading-slashes-only -->
+<script src="file://abc|/foo/bar"></script><!-- scheme-file-slash-slash-abc-bar -->
+<script src="/a/b/c"></script><!-- path-simple-relative -->
+<script src="http://example.com/你好你好"></script><!-- path-unicode-han -->
+<script src="/a/%2f/c"></script><!-- path-percent-encoded-slash-plus-slashes-relative -->
+<script src="http://f:/c"></script><!-- port-none-but-colon -->
+<script src="http://example.com/foo%41%7a"></script><!-- path-percent-encoded-multiple -->
+<script src="http://192.168.0.257/"></script><!-- host-IP-address-broken -->
+<script src="madeupscheme:example.com/"></script><!-- scheme-private-no-slash -->
+<script src="?"></script><!-- query-empty-no-path-relative -->
+<script src="http://example.com/%20foo"></script><!-- path-percent-encoded-space -->
+<script src="mailto:/example.com/"></script><!-- scheme-mailto-single-slash -->
+<script src="::"></script><!-- path-leading-colon-colon-relative -->
+<script src="http://example.com/%3A%3a%3C%3c"></script><!-- path-percent-encoded-mixed-case -->
+<script src="http://user:pass@foo:21/bar;par?b#c"></script><!-- userinfo -->
+<script src="ws:/example.com/"></script><!-- scheme-ws-single-slash -->
+<script src="foo://"></script><!-- scheme-private-slash-slash -->
+<script src="#"></script><!-- fragment-empty-hash-only-no-path-relative -->
+<script src="http://f:00000000000000/c"></script><!-- port-00000000000000 -->
+<script src="foo:////://///"></script><!-- scheme-private-path-leading-slashes-colon-slashes -->
+<script src=":23"></script><!-- path-leading-colon-number-relative -->
+<script src="foo:/"></script><!-- scheme-private-slash -->
+<script src="http://💩"></script><!-- host-is-pile-of-poo -->
+<script src="file:test"></script><!-- scheme-file-no-slash -->
+<script src="file://C|/foo/bar"></script><!-- scheme-file-slash-slash-c-bar -->
+<script src="#/"></script><!-- fragment-slash-relative -->
+<script src="http://192.0x00A80001"></script><!-- host-192.0x00A80001 -->
+<script src="foo.com"></script><!-- scheme-none-relative -->
+<script src="http💩//:foo"></script><!-- path-contains-pile-of-poo -->
+<script src="File://foo/bar.html"></script><!-- scheme-file-uppercase -->
+<script src=":/"></script><!-- path-leading-colon-slash-relative -->
+<script src="http://www.foo。bar.com"></script><!-- host-exotic-dot -->
+<script src="http://GOO​⁠goo.com"></script><!-- host-exotic-whitespace -->
+<script src="file:///foo/bar.txt"></script><!-- scheme-file-host-empty -->
+<script src="javascript:/example.com/"></script><!-- scheme-javascript-single-slash -->
+<script src="gopher:/example.com/"></script><!-- scheme-gopher-single-slash -->
+<script src="ftps:example.com/"></script><!-- scheme-ftps-no-slash -->
+<script src="file://server/foo/bar"></script><!-- scheme-file-host-included -->
+<script src="http://example.com/foo%00"></script><!-- path-percent-encoded-u0000 -->
+<script src="a:foo.com"></script><!-- scheme-private -->
+<script src=":"></script><!-- path-colon-relative -->
+<script src="http://:b@www.example.com"></script><!-- userinfo-user-empty -->
+<script src="file:/"></script><!-- scheme-file-slash-only -->
+<script src="wss:example.com/"></script><!-- scheme-wss-no-slash -->
+<script src="::23"></script><!-- path-colon-colon-number-relative -->
+<script src="/a%2fc"></script><!-- path-percent-encoded-slash-relative -->
+<script src="http://a:b@c:29/d"></script><!-- userinfo-host-port-path -->
+<script src="gopher:example.com/"></script><!-- scheme-gopher-no-slash -->
+<script src="madeupscheme:/example.com/"></script><!-- scheme-private-single-slash -->
+<script src="mailto:example.com/"></script><!-- scheme-mailto-no-slash -->
+<script src="http://%25DOMAIN:foobar@foodomain.com"></script><!-- userinfo-username-contains-percent-encoded -->
+<script src="/:23"></script><!-- path-slash-colon-number-relative -->
+<script src="foo://///////bar.com/"></script><!-- scheme-private-path-leading-slashes-chars -->
+<script src="http://[2001::1]:80"></script><!-- host-ipv6-port -->
+<script src="data:text/plain,foo"></script><!-- scheme-data-no-slash -->
+<script src="http://example.com/foo/%2e"></script><!-- path-percent-encoded-dot -->
+<script src="file:/example.com/"></script><!-- scheme-file-single-slash -->
+<script src="http://example.com/©zbar"></script><!-- path-non-ascii -->
+<script src="http://example.com//foo"></script><!-- path-uFEFF -->
+<script src="wss:/example.com/"></script><!-- scheme-wss-single-slash -->
+<script src="http://foo/abcd#foo?bar"></script><!-- fragment-contains-question-mark -->
+<script src=":#"></script><!-- path-leading-colon-hash-relative -->
+<script src="http://example.com/foo%91"></script><!-- path-percent-encoded-u0091 -->
+<script src="c:/foo"></script><!-- scheme-private-single-letter -->
+<script src=":foo.com"></script><!-- path-leading-colon-chars-relative -->
+<script src="http://你好你好"></script><!-- host-idn-unicode-han -->
+<script src="http://example.com/foo#💩"></script><!-- fragment-contains-pile-of-poo -->
+<script src="file:"></script><!-- scheme-file-scheme-only -->
+<script src="#β"></script><!-- fragment-non-ascii-relative -->
+<script src="foo:/bar.com/"></script><!-- scheme-private-path -->
+<script src="http://f:0/c"></script><!-- port-0 -->
+<script src="#;?"></script><!-- fragment-semicolon-question-mark-relative -->
+<script src="http://Go.com"></script><!-- host-fullwidth -->
+<script src="http://@www.example.com"></script><!-- userinfo-empty -->
+<script src="http://example.com/‮/foo/‭/bar"></script><!-- path-u202E-u202D -->
+<script src="http://[2001::1]"></script><!-- host-ipv6 -->
+<script src="💩http://foo"></script><!-- path-starts-with-pile-of-poo -->
+<script src="http://foo/abcd?efgh?ijkl"></script><!-- query-contains-question-mark -->
+<script src="//foo/bar"></script><!-- scheme-schemeless-relative -->
+<script src="ftps:/example.com/"></script><!-- scheme-ftps-single-slash -->
+<script src="http://foo.com:b@d/"></script><!-- userinfo-username-non-alpha -->
+<script src=":a"></script><!-- path-leading-colon-letter-relative -->
+<script src="/"></script><!-- path-slash-only-relative -->
+<script src="http://example.com/foo?💩"></script><!-- query-contains-pile-of-poo -->
+<script src="http://f:00000000000000000000080/c"></script><!-- port-00000000000000000000080 -->
+<script src="file://"></script><!-- scheme-file-slash-slash-only -->
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src-whitespace-only-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src-whitespace-only-novalid.html
new file mode 100644
index 00000000000..3d850fc735c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src-whitespace-only-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>empty src is not valid</title>
+<script src="
+"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/fragment-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/fragment-backslash-novalid.html
new file mode 100644
index 00000000000..55bcbb9f9a4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/fragment-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: fragment-backslash</title>
+<script src="#\"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/fragment-contains-hash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/fragment-contains-hash-novalid.html
new file mode 100644
index 00000000000..03cab750582
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/fragment-contains-hash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: fragment-contains-hash</title>
+<script src="http://foo/path#f#g"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/fragment-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/fragment-leading-space-novalid.html
new file mode 100644
index 00000000000..0c97b6b1a68
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/fragment-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: fragment-leading-space</title>
+<script src="http://f:21/b# e"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-cr-novalid.html
new file mode 100644
index 00000000000..4e90cab023a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-cr</title>
+<script src="http://example. org"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-double-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-double-percent-encoded-novalid.html
new file mode 100644
index 00000000000..229c0115f00
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-double-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-double-percent-encoded</title>
+<script src="http://%41.com"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-double-percent-encoded-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-double-percent-encoded-percent-encoded-novalid.html
new file mode 100644
index 00000000000..958c18e4b97
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-double-percent-encoded-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-double-percent-encoded-percent-encoded</title>
+<script src="http://%ef%bc%85%ef%bc%94%ef%bc%91.com"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-empty-novalid.html
new file mode 100644
index 00000000000..37338edcce9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-empty</title>
+<script src="http://"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-empty-userinfo-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-empty-userinfo-empty-novalid.html
new file mode 100644
index 00000000000..b8c12b06ed1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-empty-userinfo-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-empty-userinfo-empty</title>
+<script src="http://@/www.example.com"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-empty-with-userinfo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-empty-with-userinfo-novalid.html
new file mode 100644
index 00000000000..82e95ba5ecf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-empty-with-userinfo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-empty-with-userinfo</title>
+<script src="http://user:pass@/"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-hostname-in-brackets-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-hostname-in-brackets-novalid.html
new file mode 100644
index 00000000000..63c908e807c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-hostname-in-brackets-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-hostname-in-brackets</title>
+<script src="http://[www.google.com]/"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-invalid-unicode-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-invalid-unicode-novalid.html
new file mode 100644
index 00000000000..38936b3b86f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-invalid-unicode-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-invalid-unicode</title>
+<script src="http://﷐zyx.com"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-invalid-unicode-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-invalid-unicode-percent-encoded-novalid.html
new file mode 100644
index 00000000000..1e3cac534e3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-invalid-unicode-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-invalid-unicode-percent-encoded</title>
+<script src="http://%ef%b7%90zyx.com"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-newline-novalid.html
new file mode 100644
index 00000000000..4995fe428c2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-newline</title>
+<script src="http://example.
+org"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-space-novalid.html
new file mode 100644
index 00000000000..676705ed88a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-space</title>
+<script src="http://example .org"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-square-brackets-port-contains-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-square-brackets-port-contains-colon-novalid.html
new file mode 100644
index 00000000000..4f8581e69ad
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-square-brackets-port-contains-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-square-brackets-port-contains-colon</title>
+<script src="http://[1::2]:3:4"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-tab-novalid.html
new file mode 100644
index 00000000000..58a8aecd69a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-tab</title>
+<script src="http://example .org"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-u0000-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-u0000-percent-encoded-novalid.html
new file mode 100644
index 00000000000..c58b09b9df1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-u0000-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-u0000-percent-encoded</title>
+<script src="http://%00.com"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-u0000-percent-encoded-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-u0000-percent-encoded-percent-encoded-novalid.html
new file mode 100644
index 00000000000..f659cf0d5b5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/host-u0000-percent-encoded-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-u0000-percent-encoded-percent-encoded</title>
+<script src="http://%ef%bc%85%ef%bc%90%ef%bc%90.com"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/path-bare-percent-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/path-bare-percent-sign-novalid.html
new file mode 100644
index 00000000000..c23ef7bc936
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/path-bare-percent-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-bare-percent-sign</title>
+<script src="http://example.com/foo%"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/path-contains-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/path-contains-space-novalid.html
new file mode 100644
index 00000000000..f54c9aeaa86
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/path-contains-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-contains-space</title>
+<script src="/a/ /c"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/path-leading-backslash-at-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/path-leading-backslash-at-sign-novalid.html
new file mode 100644
index 00000000000..f8a8317d057
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/path-leading-backslash-at-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-leading-backslash-at-sign</title>
+<script src="http://foo.com/\@"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/path-leading-colon-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/path-leading-colon-backslash-novalid.html
new file mode 100644
index 00000000000..df39dc2fdf7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/path-leading-colon-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-leading-colon-backslash</title>
+<script src=":\"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/path-leading-colon-chars-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/path-leading-colon-chars-backslash-novalid.html
new file mode 100644
index 00000000000..af8803b6028
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/path-leading-colon-chars-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-leading-colon-chars-backslash</title>
+<script src=":foo.com\"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/path-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/path-leading-space-novalid.html
new file mode 100644
index 00000000000..49d0a41cbf0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/path-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-leading-space</title>
+<script src="http://f:21/ b"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/path-percent-encoded-malformed-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/path-percent-encoded-malformed-novalid.html
new file mode 100644
index 00000000000..99d207f4028
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/path-percent-encoded-malformed-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-percent-encoded-malformed</title>
+<script src="http://example.com/foo/%2e%2"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/path-relative-square-brackets-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/path-relative-square-brackets-novalid.html
new file mode 100644
index 00000000000..3f2447018c3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/path-relative-square-brackets-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-relative-square-brackets</title>
+<script src="[61:24:74]:98"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/path-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/path-tab-novalid.html
new file mode 100644
index 00000000000..28f15327a07
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/path-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-tab</title>
+<script src="http://example.com/foo bar"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/path-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/path-trailing-space-novalid.html
new file mode 100644
index 00000000000..157fd07dc40
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/path-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-trailing-space</title>
+<script src="http://f:21/b ?"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/path-u0091-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/path-u0091-novalid.html
new file mode 100644
index 00000000000..5ff1dfb7a48
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/path-u0091-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-u0091</title>
+<script src="http://example.com/foo‘"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/port-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/port-cr-novalid.html
new file mode 100644
index 00000000000..14cc85f13f2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/port-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-cr</title>
+<script src="http://f: /c"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/port-leading-colon-bracket-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/port-leading-colon-bracket-colon-novalid.html
new file mode 100644
index 00000000000..b20a459624a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/port-leading-colon-bracket-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-leading-colon-bracket-colon</title>
+<script src="http://2001::1]:80"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/port-leading-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/port-leading-colon-novalid.html
new file mode 100644
index 00000000000..5e2e7db787c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/port-leading-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-leading-colon</title>
+<script src="http://2001::1"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/port-leading-dash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/port-leading-dash-novalid.html
new file mode 100644
index 00000000000..ce486bcca13
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/port-leading-dash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-leading-dash</title>
+<script src="http://foo:-80/"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/port-multiple-letters-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/port-multiple-letters-novalid.html
new file mode 100644
index 00000000000..2f7174ec1aa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/port-multiple-letters-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-multiple-letters</title>
+<script src="http://f:fifty-two/c"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/port-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/port-newline-novalid.html
new file mode 100644
index 00000000000..003f9d489c6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/port-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-newline</title>
+<script src="http://f:
+/c"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/port-single-letter-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/port-single-letter-novalid.html
new file mode 100644
index 00000000000..c57c1694847
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/port-single-letter-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-single-letter</title>
+<script src="http://f:b/c"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/port-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/port-space-novalid.html
new file mode 100644
index 00000000000..ed84a101e66
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/port-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-space</title>
+<script src="http://f: /c"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/port-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/port-tab-novalid.html
new file mode 100644
index 00000000000..fca9c6b9ce3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/port-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-tab</title>
+<script src="http://f: /c"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/query-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/query-leading-space-novalid.html
new file mode 100644
index 00000000000..f864a2a0652
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/query-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: query-leading-space</title>
+<script src="http://f:21/b? d"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/query-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/query-trailing-space-novalid.html
new file mode 100644
index 00000000000..92a5453cb94
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/query-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: query-trailing-space</title>
+<script src="http://f:21/b?d #"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-data-contains-fragment-haswarn.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-data-contains-fragment-haswarn.html
new file mode 100644
index 00000000000..f26fb056d9f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-data-contains-fragment-haswarn.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>data:text/html,test#test warning: scheme-data-contains-fragment</title>
+<script src="data:text/html,test#test"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-data-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-data-single-slash-novalid.html
new file mode 100644
index 00000000000..1bae7962e26
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-data-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-data-single-slash</title>
+<script src="data:/example.com/"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-file-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-file-backslash-novalid.html
new file mode 100644
index 00000000000..d23ad76fda7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-file-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-file-backslash</title>
+<script src="file:c:\foo\bar.html"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-file-single-slash-c-bar-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-file-single-slash-c-bar-novalid.html
new file mode 100644
index 00000000000..5efd30aaae8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-file-single-slash-c-bar-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-file-single-slash-c-bar</title>
+<script src="file:/C|/foo/bar"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-file-triple-slash-c-bar-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-file-triple-slash-c-bar-novalid.html
new file mode 100644
index 00000000000..b9b9db1ee9e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-file-triple-slash-c-bar-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-file-triple-slash-c-bar</title>
+<script src="file:///C|/foo/bar"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-ftp-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-ftp-no-slash-novalid.html
new file mode 100644
index 00000000000..9dfcff84706
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-ftp-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-ftp-no-slash</title>
+<script src="ftp:example.com/"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-ftp-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-ftp-single-slash-novalid.html
new file mode 100644
index 00000000000..7d641fa5b3f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-ftp-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-ftp-single-slash</title>
+<script src="ftp:/example.com/"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-http-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-http-backslash-novalid.html
new file mode 100644
index 00000000000..5b1877e8851
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-http-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-http-backslash</title>
+<script src="http:\\foo.com\"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-http-no-slash-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-http-no-slash-colon-novalid.html
new file mode 100644
index 00000000000..fa9437aba50
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-http-no-slash-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-http-no-slash-colon</title>
+<script src="http::@c:29"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-http-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-http-no-slash-novalid.html
new file mode 100644
index 00000000000..5e0848eaac8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-http-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-http-no-slash</title>
+<script src="http:foo.com"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-http-no-slash-square-bracket-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-http-no-slash-square-bracket-novalid.html
new file mode 100644
index 00000000000..bb4642fc704
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-http-no-slash-square-bracket-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-http-no-slash-square-bracket</title>
+<script src="http:[61:27]/:foo"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-http-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-http-single-slash-novalid.html
new file mode 100644
index 00000000000..90a94ef29be
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-http-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-http-single-slash</title>
+<script src="http:/example.com/"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-https-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-https-no-slash-novalid.html
new file mode 100644
index 00000000000..63c8ba3cda3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-https-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-https-no-slash</title>
+<script src="https:example.com/"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-https-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-https-single-slash-novalid.html
new file mode 100644
index 00000000000..656fdc01b84
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-https-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-https-single-slash</title>
+<script src="https:/example.com/"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-javascript-no-slash-malformed-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-javascript-no-slash-malformed-novalid.html
new file mode 100644
index 00000000000..6e85d80fee4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-javascript-no-slash-malformed-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-javascript-no-slash-malformed</title>
+<script src="javascript:example.com/"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-trailing-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-trailing-cr-novalid.html
new file mode 100644
index 00000000000..3c97e997588
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-trailing-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-trailing-cr</title>
+<script src="a: foo.com"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-trailing-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-trailing-newline-novalid.html
new file mode 100644
index 00000000000..a0415fb9cd7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-trailing-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-trailing-newline</title>
+<script src="a:
+foo.com"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-trailing-space-novalid.html
new file mode 100644
index 00000000000..e500ae56e0b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-trailing-space</title>
+<script src="a: foo.com"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-trailing-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-trailing-tab-novalid.html
new file mode 100644
index 00000000000..37449448ebc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/scheme-trailing-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-trailing-tab</title>
+<script src="a: foo.com"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/userinfo-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/userinfo-backslash-novalid.html
new file mode 100644
index 00000000000..44419f43a7c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/userinfo-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: userinfo-backslash</title>
+<script src="http://a\b:c\d@foo.com"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/userinfo-password-bad-chars-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/userinfo-password-bad-chars-novalid.html
new file mode 100644
index 00000000000..b9a29923601
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/userinfo-password-bad-chars-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: userinfo-password-bad-chars</title>
+<script src="http://&a:foo(b]c@d:2/"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/userinfo-password-contains-pile-of-poo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/userinfo-password-contains-pile-of-poo-novalid.html
new file mode 100644
index 00000000000..26baccf6025
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/userinfo-password-contains-pile-of-poo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: userinfo-password-contains-pile-of-poo</title>
+<script src="http://foo:💩@example.com"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/userinfo-username-contains-at-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/userinfo-username-contains-at-sign-novalid.html
new file mode 100644
index 00000000000..38e21c6ea63
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/userinfo-username-contains-at-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: userinfo-username-contains-at-sign</title>
+<script src="http://::@c@d:2"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/userinfo-username-contains-pile-of-poo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/userinfo-username-contains-pile-of-poo-novalid.html
new file mode 100644
index 00000000000..dd331c5ff92
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/script/src/userinfo-username-contains-pile-of-poo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: userinfo-username-contains-pile-of-poo</title>
+<script src="http://💩:foo@example.com"></script>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/small/model-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/small/model-isvalid.html
new file mode 100644
index 00000000000..b86e5850d08
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/small/model-isvalid.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;small&gt;</title>
+</head>
+<body>
+ <!-- is structured inline -->
+ <p><small class="class" lang="en">text</small></p>
+
+ <!-- is strictly inline -->
+ <p><dfn><small class="class" lang="en">text</small></dfn></p>
+
+ <!-- can be empty -->
+ <p>text <small></small></p>
+ <p>text <dfn><small></small></dfn></p>
+
+ <!-- can contain interactive -->
+ <p><small><a>text</a></small></p>
+ <p><dfn><small><a>text</a></small></dfn></p>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/small/model-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/small/model-novalid.html
new file mode 100644
index 00000000000..f874f3b87c7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/small/model-novalid.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;small&gt;</title>
+</head>
+<body>
+ <!-- is structured inline -->
+ <p><small class="class" lang="en">text</small></p>
+
+ <!-- is strictly inline -->
+ <p><dfn><small class="class" lang="en">text</small></dfn></p>
+
+ <!-- can be empty -->
+ <p>text <small></small></p>
+ <p>text <dfn><small></small></dfn></p>
+
+ <!-- can contain interactive -->
+ <p><small><a>text</a></small></p>
+ <p><dfn><small><a>text</a></small></dfn></p>
+
+ <!-- cannot contain structured inline -->
+ <p><small>text <ul><li>list</li></ul> <em>elem</em></small></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src-empty-novalid.html
new file mode 100644
index 00000000000..40af9974f8f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>empty src is not valid</title>
+<video><source src=""></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src-isvalid.html
new file mode 100644
index 00000000000..138463d951d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src-isvalid.html
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid src</title>
+<video><source src="file:///"></video><!-- scheme-file-slash-slash-slash-only -->
+<video><source src="http://a:@www.example.com"></video><!-- userinfo-password-empty -->
+<video><source src="foo://///////"></video><!-- scheme-private-path-leading-slashes-only -->
+<video><source src="file://abc|/foo/bar"></video><!-- scheme-file-slash-slash-abc-bar -->
+<video><source src="/a/b/c"></video><!-- path-simple-relative -->
+<video><source src="http://example.com/你好你好"></video><!-- path-unicode-han -->
+<video><source src="/a/%2f/c"></video><!-- path-percent-encoded-slash-plus-slashes-relative -->
+<video><source src="http://f:/c"></video><!-- port-none-but-colon -->
+<video><source src="http://example.com/foo%41%7a"></video><!-- path-percent-encoded-multiple -->
+<video><source src="http://192.168.0.257/"></video><!-- host-IP-address-broken -->
+<video><source src="madeupscheme:example.com/"></video><!-- scheme-private-no-slash -->
+<video><source src="?"></video><!-- query-empty-no-path-relative -->
+<video><source src="http://example.com/%20foo"></video><!-- path-percent-encoded-space -->
+<video><source src="mailto:/example.com/"></video><!-- scheme-mailto-single-slash -->
+<video><source src="::"></video><!-- path-leading-colon-colon-relative -->
+<video><source src="http://example.com/%3A%3a%3C%3c"></video><!-- path-percent-encoded-mixed-case -->
+<video><source src="http://user:pass@foo:21/bar;par?b#c"></video><!-- userinfo -->
+<video><source src="ws:/example.com/"></video><!-- scheme-ws-single-slash -->
+<video><source src="foo://"></video><!-- scheme-private-slash-slash -->
+<video><source src="#"></video><!-- fragment-empty-hash-only-no-path-relative -->
+<video><source src="http://f:00000000000000/c"></video><!-- port-00000000000000 -->
+<video><source src="foo:////://///"></video><!-- scheme-private-path-leading-slashes-colon-slashes -->
+<video><source src=":23"></video><!-- path-leading-colon-number-relative -->
+<video><source src="foo:/"></video><!-- scheme-private-slash -->
+<video><source src="http://💩"></video><!-- host-is-pile-of-poo -->
+<video><source src="file:test"></video><!-- scheme-file-no-slash -->
+<video><source src="file://C|/foo/bar"></video><!-- scheme-file-slash-slash-c-bar -->
+<video><source src="#/"></video><!-- fragment-slash-relative -->
+<video><source src="http://192.0x00A80001"></video><!-- host-192.0x00A80001 -->
+<video><source src="foo.com"></video><!-- scheme-none-relative -->
+<video><source src="http💩//:foo"></video><!-- path-contains-pile-of-poo -->
+<video><source src="File://foo/bar.html"></video><!-- scheme-file-uppercase -->
+<video><source src=":/"></video><!-- path-leading-colon-slash-relative -->
+<video><source src="http://www.foo。bar.com"></video><!-- host-exotic-dot -->
+<video><source src="http://GOO​⁠goo.com"></video><!-- host-exotic-whitespace -->
+<video><source src="file:///foo/bar.txt"></video><!-- scheme-file-host-empty -->
+<video><source src="javascript:/example.com/"></video><!-- scheme-javascript-single-slash -->
+<video><source src="gopher:/example.com/"></video><!-- scheme-gopher-single-slash -->
+<video><source src="ftps:example.com/"></video><!-- scheme-ftps-no-slash -->
+<video><source src="file://server/foo/bar"></video><!-- scheme-file-host-included -->
+<video><source src="http://example.com/foo%00"></video><!-- path-percent-encoded-u0000 -->
+<video><source src="a:foo.com"></video><!-- scheme-private -->
+<video><source src=":"></video><!-- path-colon-relative -->
+<video><source src="http://:b@www.example.com"></video><!-- userinfo-user-empty -->
+<video><source src="file:/"></video><!-- scheme-file-slash-only -->
+<video><source src="wss:example.com/"></video><!-- scheme-wss-no-slash -->
+<video><source src="::23"></video><!-- path-colon-colon-number-relative -->
+<video><source src="/a%2fc"></video><!-- path-percent-encoded-slash-relative -->
+<video><source src="http://a:b@c:29/d"></video><!-- userinfo-host-port-path -->
+<video><source src="gopher:example.com/"></video><!-- scheme-gopher-no-slash -->
+<video><source src="madeupscheme:/example.com/"></video><!-- scheme-private-single-slash -->
+<video><source src="mailto:example.com/"></video><!-- scheme-mailto-no-slash -->
+<video><source src="http://%25DOMAIN:foobar@foodomain.com"></video><!-- userinfo-username-contains-percent-encoded -->
+<video><source src="/:23"></video><!-- path-slash-colon-number-relative -->
+<video><source src="foo://///////bar.com/"></video><!-- scheme-private-path-leading-slashes-chars -->
+<video><source src="http://[2001::1]:80"></video><!-- host-ipv6-port -->
+<video><source src="data:text/plain,foo"></video><!-- scheme-data-no-slash -->
+<video><source src="http://example.com/foo/%2e"></video><!-- path-percent-encoded-dot -->
+<video><source src="file:/example.com/"></video><!-- scheme-file-single-slash -->
+<video><source src="http://example.com/©zbar"></video><!-- path-non-ascii -->
+<video><source src="http://example.com//foo"></video><!-- path-uFEFF -->
+<video><source src="wss:/example.com/"></video><!-- scheme-wss-single-slash -->
+<video><source src="http://foo/abcd#foo?bar"></video><!-- fragment-contains-question-mark -->
+<video><source src=":#"></video><!-- path-leading-colon-hash-relative -->
+<video><source src="http://example.com/foo%91"></video><!-- path-percent-encoded-u0091 -->
+<video><source src="c:/foo"></video><!-- scheme-private-single-letter -->
+<video><source src=":foo.com"></video><!-- path-leading-colon-chars-relative -->
+<video><source src="http://你好你好"></video><!-- host-idn-unicode-han -->
+<video><source src="http://example.com/foo#💩"></video><!-- fragment-contains-pile-of-poo -->
+<video><source src="file:"></video><!-- scheme-file-scheme-only -->
+<video><source src="#β"></video><!-- fragment-non-ascii-relative -->
+<video><source src="foo:/bar.com/"></video><!-- scheme-private-path -->
+<video><source src="http://f:0/c"></video><!-- port-0 -->
+<video><source src="#;?"></video><!-- fragment-semicolon-question-mark-relative -->
+<video><source src="http://Go.com"></video><!-- host-fullwidth -->
+<video><source src="http://@www.example.com"></video><!-- userinfo-empty -->
+<video><source src="http://example.com/‮/foo/‭/bar"></video><!-- path-u202E-u202D -->
+<video><source src="http://[2001::1]"></video><!-- host-ipv6 -->
+<video><source src="💩http://foo"></video><!-- path-starts-with-pile-of-poo -->
+<video><source src="http://foo/abcd?efgh?ijkl"></video><!-- query-contains-question-mark -->
+<video><source src="//foo/bar"></video><!-- scheme-schemeless-relative -->
+<video><source src="ftps:/example.com/"></video><!-- scheme-ftps-single-slash -->
+<video><source src="http://foo.com:b@d/"></video><!-- userinfo-username-non-alpha -->
+<video><source src=":a"></video><!-- path-leading-colon-letter-relative -->
+<video><source src="/"></video><!-- path-slash-only-relative -->
+<video><source src="http://example.com/foo?💩"></video><!-- query-contains-pile-of-poo -->
+<video><source src="http://f:00000000000000000000080/c"></video><!-- port-00000000000000000000080 -->
+<video><source src="file://"></video><!-- scheme-file-slash-slash-only -->
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src-whitespace-only-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src-whitespace-only-novalid.html
new file mode 100644
index 00000000000..d814f5bee19
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src-whitespace-only-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>empty src is not valid</title>
+<video><source src="
+"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/fragment-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/fragment-backslash-novalid.html
new file mode 100644
index 00000000000..d01d315a804
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/fragment-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: fragment-backslash</title>
+<video><source src="#\"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/fragment-contains-hash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/fragment-contains-hash-novalid.html
new file mode 100644
index 00000000000..1780fe69811
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/fragment-contains-hash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: fragment-contains-hash</title>
+<video><source src="http://foo/path#f#g"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/fragment-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/fragment-leading-space-novalid.html
new file mode 100644
index 00000000000..cf2d6028b02
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/fragment-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: fragment-leading-space</title>
+<video><source src="http://f:21/b# e"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-cr-novalid.html
new file mode 100644
index 00000000000..fce5132b171
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-cr</title>
+<video><source src="http://example. org"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-double-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-double-percent-encoded-novalid.html
new file mode 100644
index 00000000000..e670a118fb9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-double-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-double-percent-encoded</title>
+<video><source src="http://%41.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-double-percent-encoded-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-double-percent-encoded-percent-encoded-novalid.html
new file mode 100644
index 00000000000..e459233329f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-double-percent-encoded-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-double-percent-encoded-percent-encoded</title>
+<video><source src="http://%ef%bc%85%ef%bc%94%ef%bc%91.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-empty-novalid.html
new file mode 100644
index 00000000000..0c8af3c1402
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-empty</title>
+<video><source src="http://"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-empty-userinfo-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-empty-userinfo-empty-novalid.html
new file mode 100644
index 00000000000..401b95d784a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-empty-userinfo-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-empty-userinfo-empty</title>
+<video><source src="http://@/www.example.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-empty-with-userinfo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-empty-with-userinfo-novalid.html
new file mode 100644
index 00000000000..20aee85b0a4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-empty-with-userinfo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-empty-with-userinfo</title>
+<video><source src="http://user:pass@/"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-hostname-in-brackets-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-hostname-in-brackets-novalid.html
new file mode 100644
index 00000000000..459a77a7c1c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-hostname-in-brackets-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-hostname-in-brackets</title>
+<video><source src="http://[www.google.com]/"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-invalid-unicode-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-invalid-unicode-novalid.html
new file mode 100644
index 00000000000..87343ea53dc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-invalid-unicode-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-invalid-unicode</title>
+<video><source src="http://﷐zyx.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-invalid-unicode-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-invalid-unicode-percent-encoded-novalid.html
new file mode 100644
index 00000000000..89198c0c018
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-invalid-unicode-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-invalid-unicode-percent-encoded</title>
+<video><source src="http://%ef%b7%90zyx.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-newline-novalid.html
new file mode 100644
index 00000000000..d6fbbff9f58
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-newline</title>
+<video><source src="http://example.
+org"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-space-novalid.html
new file mode 100644
index 00000000000..4b948bb4242
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-space</title>
+<video><source src="http://example .org"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-square-brackets-port-contains-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-square-brackets-port-contains-colon-novalid.html
new file mode 100644
index 00000000000..1c0948bdeca
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-square-brackets-port-contains-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-square-brackets-port-contains-colon</title>
+<video><source src="http://[1::2]:3:4"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-tab-novalid.html
new file mode 100644
index 00000000000..bfa213cf9ca
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-tab</title>
+<video><source src="http://example .org"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-u0000-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-u0000-percent-encoded-novalid.html
new file mode 100644
index 00000000000..af4112397fb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-u0000-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-u0000-percent-encoded</title>
+<video><source src="http://%00.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-u0000-percent-encoded-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-u0000-percent-encoded-percent-encoded-novalid.html
new file mode 100644
index 00000000000..2b8764b7733
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/host-u0000-percent-encoded-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-u0000-percent-encoded-percent-encoded</title>
+<video><source src="http://%ef%bc%85%ef%bc%90%ef%bc%90.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/path-bare-percent-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/path-bare-percent-sign-novalid.html
new file mode 100644
index 00000000000..a3f169c0b0b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/path-bare-percent-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-bare-percent-sign</title>
+<video><source src="http://example.com/foo%"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/path-contains-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/path-contains-space-novalid.html
new file mode 100644
index 00000000000..8290e235520
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/path-contains-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-contains-space</title>
+<video><source src="/a/ /c"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/path-leading-backslash-at-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/path-leading-backslash-at-sign-novalid.html
new file mode 100644
index 00000000000..6a7028d120c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/path-leading-backslash-at-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-leading-backslash-at-sign</title>
+<video><source src="http://foo.com/\@"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/path-leading-colon-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/path-leading-colon-backslash-novalid.html
new file mode 100644
index 00000000000..8c42b1c88fe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/path-leading-colon-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-leading-colon-backslash</title>
+<video><source src=":\"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/path-leading-colon-chars-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/path-leading-colon-chars-backslash-novalid.html
new file mode 100644
index 00000000000..3764f1e87f6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/path-leading-colon-chars-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-leading-colon-chars-backslash</title>
+<video><source src=":foo.com\"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/path-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/path-leading-space-novalid.html
new file mode 100644
index 00000000000..fd99580750e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/path-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-leading-space</title>
+<video><source src="http://f:21/ b"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/path-percent-encoded-malformed-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/path-percent-encoded-malformed-novalid.html
new file mode 100644
index 00000000000..4d133de219d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/path-percent-encoded-malformed-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-percent-encoded-malformed</title>
+<video><source src="http://example.com/foo/%2e%2"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/path-relative-square-brackets-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/path-relative-square-brackets-novalid.html
new file mode 100644
index 00000000000..b7fba024735
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/path-relative-square-brackets-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-relative-square-brackets</title>
+<video><source src="[61:24:74]:98"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/path-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/path-tab-novalid.html
new file mode 100644
index 00000000000..a755948615e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/path-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-tab</title>
+<video><source src="http://example.com/foo bar"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/path-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/path-trailing-space-novalid.html
new file mode 100644
index 00000000000..e410928b0c5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/path-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-trailing-space</title>
+<video><source src="http://f:21/b ?"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/path-u0091-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/path-u0091-novalid.html
new file mode 100644
index 00000000000..315c9c04079
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/path-u0091-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-u0091</title>
+<video><source src="http://example.com/foo‘"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/port-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/port-cr-novalid.html
new file mode 100644
index 00000000000..f4a35d68a0d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/port-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-cr</title>
+<video><source src="http://f: /c"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/port-leading-colon-bracket-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/port-leading-colon-bracket-colon-novalid.html
new file mode 100644
index 00000000000..6162bb6ec49
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/port-leading-colon-bracket-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-leading-colon-bracket-colon</title>
+<video><source src="http://2001::1]:80"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/port-leading-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/port-leading-colon-novalid.html
new file mode 100644
index 00000000000..590459c48ec
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/port-leading-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-leading-colon</title>
+<video><source src="http://2001::1"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/port-leading-dash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/port-leading-dash-novalid.html
new file mode 100644
index 00000000000..32aa2a60992
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/port-leading-dash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-leading-dash</title>
+<video><source src="http://foo:-80/"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/port-multiple-letters-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/port-multiple-letters-novalid.html
new file mode 100644
index 00000000000..0c5edbf21be
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/port-multiple-letters-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-multiple-letters</title>
+<video><source src="http://f:fifty-two/c"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/port-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/port-newline-novalid.html
new file mode 100644
index 00000000000..b5103483b0c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/port-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-newline</title>
+<video><source src="http://f:
+/c"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/port-single-letter-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/port-single-letter-novalid.html
new file mode 100644
index 00000000000..6359c2dec93
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/port-single-letter-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-single-letter</title>
+<video><source src="http://f:b/c"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/port-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/port-space-novalid.html
new file mode 100644
index 00000000000..8b255e538df
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/port-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-space</title>
+<video><source src="http://f: /c"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/port-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/port-tab-novalid.html
new file mode 100644
index 00000000000..7e3eede3c84
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/port-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-tab</title>
+<video><source src="http://f: /c"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/query-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/query-leading-space-novalid.html
new file mode 100644
index 00000000000..c2b2ccf61b2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/query-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: query-leading-space</title>
+<video><source src="http://f:21/b? d"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/query-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/query-trailing-space-novalid.html
new file mode 100644
index 00000000000..3d18f7316a6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/query-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: query-trailing-space</title>
+<video><source src="http://f:21/b?d #"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-data-contains-fragment-haswarn.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-data-contains-fragment-haswarn.html
new file mode 100644
index 00000000000..c92f72c9d56
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-data-contains-fragment-haswarn.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>src warning: scheme-data-contains-fragment</title>
+<video><source src="data:text/html,test#test"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-data-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-data-single-slash-novalid.html
new file mode 100644
index 00000000000..5be1b6aa5d5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-data-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-data-single-slash</title>
+<video><source src="data:/example.com/"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-file-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-file-backslash-novalid.html
new file mode 100644
index 00000000000..3d2ba290e3a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-file-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-file-backslash</title>
+<video><source src="file:c:\foo\bar.html"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-file-single-slash-c-bar-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-file-single-slash-c-bar-novalid.html
new file mode 100644
index 00000000000..3f73121760d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-file-single-slash-c-bar-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-file-single-slash-c-bar</title>
+<video><source src="file:/C|/foo/bar"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-file-triple-slash-c-bar-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-file-triple-slash-c-bar-novalid.html
new file mode 100644
index 00000000000..b1d44ebc7ce
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-file-triple-slash-c-bar-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-file-triple-slash-c-bar</title>
+<video><source src="file:///C|/foo/bar"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-ftp-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-ftp-no-slash-novalid.html
new file mode 100644
index 00000000000..5388a0e6a05
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-ftp-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-ftp-no-slash</title>
+<video><source src="ftp:example.com/"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-ftp-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-ftp-single-slash-novalid.html
new file mode 100644
index 00000000000..f24622fe250
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-ftp-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-ftp-single-slash</title>
+<video><source src="ftp:/example.com/"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-http-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-http-backslash-novalid.html
new file mode 100644
index 00000000000..de2b3888c2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-http-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-http-backslash</title>
+<video><source src="http:\\foo.com\"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-http-no-slash-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-http-no-slash-colon-novalid.html
new file mode 100644
index 00000000000..c331a355d82
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-http-no-slash-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-http-no-slash-colon</title>
+<video><source src="http::@c:29"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-http-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-http-no-slash-novalid.html
new file mode 100644
index 00000000000..fa49920494c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-http-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-http-no-slash</title>
+<video><source src="http:foo.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-http-no-slash-square-bracket-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-http-no-slash-square-bracket-novalid.html
new file mode 100644
index 00000000000..576fef6f47d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-http-no-slash-square-bracket-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-http-no-slash-square-bracket</title>
+<video><source src="http:[61:27]/:foo"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-http-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-http-single-slash-novalid.html
new file mode 100644
index 00000000000..09837749cb1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-http-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-http-single-slash</title>
+<video><source src="http:/example.com/"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-https-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-https-no-slash-novalid.html
new file mode 100644
index 00000000000..931e59c008a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-https-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-https-no-slash</title>
+<video><source src="https:example.com/"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-https-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-https-single-slash-novalid.html
new file mode 100644
index 00000000000..87f75d8fb37
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-https-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-https-single-slash</title>
+<video><source src="https:/example.com/"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-javascript-no-slash-malformed-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-javascript-no-slash-malformed-novalid.html
new file mode 100644
index 00000000000..6516b42310d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-javascript-no-slash-malformed-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-javascript-no-slash-malformed</title>
+<video><source src="javascript:example.com/"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-trailing-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-trailing-cr-novalid.html
new file mode 100644
index 00000000000..99170ba10a5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-trailing-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-trailing-cr</title>
+<video><source src="a: foo.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-trailing-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-trailing-newline-novalid.html
new file mode 100644
index 00000000000..4e68da6e7ee
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-trailing-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-trailing-newline</title>
+<video><source src="a:
+foo.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-trailing-space-novalid.html
new file mode 100644
index 00000000000..8a7e5471c4f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-trailing-space</title>
+<video><source src="a: foo.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-trailing-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-trailing-tab-novalid.html
new file mode 100644
index 00000000000..87ebab22dbe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/scheme-trailing-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-trailing-tab</title>
+<video><source src="a: foo.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/userinfo-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/userinfo-backslash-novalid.html
new file mode 100644
index 00000000000..110363739e5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/userinfo-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: userinfo-backslash</title>
+<video><source src="http://a\b:c\d@foo.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/userinfo-password-bad-chars-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/userinfo-password-bad-chars-novalid.html
new file mode 100644
index 00000000000..2e88fd4d43a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/userinfo-password-bad-chars-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: userinfo-password-bad-chars</title>
+<video><source src="http://&a:foo(b]c@d:2/"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/userinfo-password-contains-pile-of-poo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/userinfo-password-contains-pile-of-poo-novalid.html
new file mode 100644
index 00000000000..147678b38d7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/userinfo-password-contains-pile-of-poo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: userinfo-password-contains-pile-of-poo</title>
+<video><source src="http://foo:💩@example.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/userinfo-username-contains-at-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/userinfo-username-contains-at-sign-novalid.html
new file mode 100644
index 00000000000..c6f9bef7147
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/userinfo-username-contains-at-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: userinfo-username-contains-at-sign</title>
+<video><source src="http://::@c@d:2"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/userinfo-username-contains-pile-of-poo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/userinfo-username-contains-pile-of-poo-novalid.html
new file mode 100644
index 00000000000..fb2f9413f49
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/source/src/userinfo-username-contains-pile-of-poo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: userinfo-username-contains-pile-of-poo</title>
+<video><source src="http://💩:foo@example.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/span/model-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/span/model-isvalid.html
new file mode 100644
index 00000000000..ee1abffabf0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/span/model-isvalid.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;span&gt;</title>
+</head>
+<body>
+ <!-- is structured inline -->
+ <p><span class="class" lang="en">text</span></p>
+
+ <!-- is strictly inline -->
+ <p><dfn><span class="class" lang="en">text</span></dfn></p>
+
+ <!-- can be empty -->
+ <p>text <span></span></p>
+ <p>text <dfn><span></span></dfn></p>
+
+ <!-- can contain interactive -->
+ <p><span><a>text</a></span></p>
+ <p><dfn><span><a>text</a></span></dfn></p>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/span/model-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/span/model-novalid.html
new file mode 100644
index 00000000000..30814fc2c1a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/span/model-novalid.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;span&gt;</title>
+</head>
+<body>
+ <!-- is structured inline -->
+ <p><span class="class" lang="en">text</span></p>
+
+ <!-- is strictly inline -->
+ <p><dfn><span class="class" lang="en">text</span></dfn></p>
+
+ <!-- can be empty -->
+ <p>text <span></span></p>
+ <p>text <dfn><span></span></dfn></p>
+
+ <!-- can contain interactive -->
+ <p><span><a>text</a></span></p>
+ <p><dfn><span><a>text</a></span></dfn></p>
+
+ <!-- cannot contain structured inline -->
+ <p><span>text <ul><li>list</li></ul> <em>elem</em></span></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/strong/model-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/strong/model-isvalid.html
new file mode 100644
index 00000000000..1510a641c05
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/strong/model-isvalid.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;strong&gt;</title>
+</head>
+<body>
+ <!-- is structured inline -->
+ <p><strong class="class" lang="en">text</strong></p>
+
+ <!-- is strictly inline -->
+ <p><dfn><strong class="class" lang="en">text</strong></dfn></p>
+
+ <!-- can be empty -->
+ <p>text <strong></strong></p>
+ <p>text <dfn><strong></strong></dfn></p>
+
+ <!-- can contain interactive -->
+ <p><strong><a>text</a></strong></p>
+ <p><dfn><strong><a>text</a></strong></dfn></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/strong/model-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/strong/model-novalid.html
new file mode 100644
index 00000000000..a202dfc8ddd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/strong/model-novalid.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;strong&gt;</title>
+</head>
+<body>
+ <!-- is structured inline -->
+ <p><strong class="class" lang="en">text</strong></p>
+
+ <!-- is strictly inline -->
+ <p><dfn><strong class="class" lang="en">text</strong></dfn></p>
+
+ <!-- can be empty -->
+ <p>text <strong></strong></p>
+ <p>text <dfn><strong></strong></dfn></p>
+
+ <!-- can contain interactive -->
+ <p><strong><a>text</a></strong></p>
+ <p><dfn><strong><a>text</a></strong></dfn></p>
+
+ <!-- cannot contain structured inline -->
+ <p><strong>text <ul><li>list</li></ul> <em>elem</em></strong></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/style/model-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/style/model-isvalid.html
new file mode 100644
index 00000000000..f0dd1c23fd1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/style/model-isvalid.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <style>
+<!--
+
+Something or other
+
+-->
+ </style>
+ <meta charset=utf-8>
+ <title>&lt;STYLE&gt;s</title>
+ <style type="application/vnd.nonsense" title="My Style">
+ Something or other
+ </style>
+</head>
+<body>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/style/scoped-as-div-child-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/style/scoped-as-div-child-isvalid.html
new file mode 100644
index 00000000000..d927a60f101
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/style/scoped-as-div-child-isvalid.html
@@ -0,0 +1,8 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>style@scoped as child of div with flow content after</title>
+<body>
+<div>
+<style scoped></style>
+<p>foo
+</div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/style/scoped-as-p-child-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/style/scoped-as-p-child-novalid.html
new file mode 100644
index 00000000000..8619e0815e9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/style/scoped-as-p-child-novalid.html
@@ -0,0 +1,5 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>style@scoped as child of p (where flow content is not allowed)</title>
+<body>
+<p><style scoped></style></p>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/style/scoped-in-head-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/style/scoped-in-head-novalid.html
new file mode 100644
index 00000000000..358bd694bb6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/style/scoped-in-head-novalid.html
@@ -0,0 +1,6 @@
+<!doctype html>
+<head>
+<meta charset=utf-8>
+<title>style@scoped in head</title>
+<style scoped></style>
+</head>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/style/scoped-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/style/scoped-isvalid.html
new file mode 100644
index 00000000000..cdcc00eb709
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/style/scoped-isvalid.html
@@ -0,0 +1,5 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>style@scoped as child of div</title>
+<body>
+<div><style scoped></style></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/style/scoped-model-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/style/scoped-model-novalid.html
new file mode 100644
index 00000000000..19d56bbc98d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/style/scoped-model-novalid.html
@@ -0,0 +1,8 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>style@scoped as child of div with flow content before</title>
+<body>
+<div>
+<p>foo</p>
+<style scoped></style>
+</div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/style/scoped-multiple-adjacent-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/style/scoped-multiple-adjacent-isvalid.html
new file mode 100644
index 00000000000..1799dd128c8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/style/scoped-multiple-adjacent-isvalid.html
@@ -0,0 +1,9 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>mutliple adjacent style@scoped as child of div with flow content after</title>
+<body>
+<div>
+<style scoped></style>
+<style scoped></style>
+<p>foo</p>
+</div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/sub/model-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/sub/model-isvalid.html
new file mode 100644
index 00000000000..2dbd047f464
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/sub/model-isvalid.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;sub&gt;</title>
+</head>
+<body>
+ <!-- is structured inline -->
+ <p><sub class="class" lang="en">text</sub></p>
+
+ <!-- is strictly inline -->
+ <p><dfn><sub class="class" lang="en">text</sub></dfn></p>
+
+ <!-- can be empty -->
+ <p>text <sub></sub></p>
+ <p>text <dfn><sub></sub></dfn></p>
+
+ <!-- can contain interactive -->
+ <p><sub><a>text</a></sub></p>
+ <p><dfn><sub><a>text</a></sub></dfn></p>
+
+ <!-- cannot contain structured inline -->
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/sub/model-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/sub/model-novalid.html
new file mode 100644
index 00000000000..41e40a63d7d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/sub/model-novalid.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;sub&gt;</title>
+</head>
+<body>
+ <!-- not a block -->
+ <sub>text</sub>
+
+ <!-- cannot contain structured inline -->
+ <p><sub><ul><li>text</li></ul></sub></p>
+
+ <!-- cannot contain interactive if parent forbids interactive -->
+ <p><a><sub><a>text</a></sub></a></p>
+ <p><a><dfn><sub><a>text</a></sub></dfn></a></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/sup/model-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/sup/model-isvalid.html
new file mode 100644
index 00000000000..af3642f5ed9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/sup/model-isvalid.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;sup&gt;</title>
+</head>
+<body>
+ <!-- is structured inline -->
+ <p><sup class="class" lang="en">text</sup></p>
+
+ <!-- is strictly inline -->
+ <p><dfn><sup class="class" lang="en">text</sup></dfn></p>
+
+ <!-- can be empty -->
+ <p>text <sup></sup></p>
+ <p>text <dfn><sup></sup></dfn></p>
+
+ <!-- can contain interactive -->
+ <p><sup><a>text</a></sup></p>
+ <p><dfn><sup><a>text</a></sup></dfn></p>
+
+ <!-- cannot contain structured inline -->
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/sup/model-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/sup/model-novalid.html
new file mode 100644
index 00000000000..321a9439e69
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/sup/model-novalid.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;sup&gt;</title>
+</head>
+<body>
+ <!-- not a block -->
+ <sup>text</sup>
+
+ <!-- cannot contain structured inline -->
+ <p><sup><ul><li>text</li></ul></sup></p>
+
+ <!-- cannot contain interactive if parent forbids interactive -->
+ <p><a><sup><a>text</a></sup></a></p>
+ <p><a><dfn><sup><a>text</a></sup></dfn></a></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/table/model-input-child-hidden-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/table/model-input-child-hidden-novalid.html
new file mode 100644
index 00000000000..e7aa64dbc2a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/table/model-input-child-hidden-novalid.html
@@ -0,0 +1,4 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>The "in table" insertion mode - A start tag whose tag name is "input" (type=hidden)</title>
+<table><input type="hidden"></table> <!-- not a streaming violation; doesn't get foster-parented -->
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/table/model-input-child-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/table/model-input-child-novalid.html
new file mode 100644
index 00000000000..08b168707d8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/table/model-input-child-novalid.html
@@ -0,0 +1,4 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>The "in table" insertion mode - A start tag whose tag name is "input"</title>
+<table><input></table>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/table/model-input-type-child-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/table/model-input-type-child-novalid.html
new file mode 100644
index 00000000000..39553d02f17
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/table/model-input-type-child-novalid.html
@@ -0,0 +1,4 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>The "in table" insertion mode - A start tag whose tag name is "input"</title>
+<table><input type=submit></table>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/time/datetime-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/time/datetime-isvalid.html
new file mode 100644
index 00000000000..644608b15bb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/time/datetime-isvalid.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;t&gt;</title>
+</head>
+<body>
+ <!-- is structured inline -->
+ <p><time datetime='2006-11-20'>text</time></p>
+
+ <!-- is strictly inline -->
+ <p><dfn><time datetime='2006-11-20'>text</time></dfn></p>
+
+ <!-- can be empty -->
+ <p>text <time datetime='2006-11-20'></time></p>
+ <p>text <dfn><time datetime='2006-11-20'></time></dfn></p>
+
+ <!-- can contain interactive -->
+ <p><time datetime='2006-11-20'><a>text</a></time></p>
+ <p><dfn><time datetime='2006-11-20'><a>text</a></time></dfn></p>
+
+ <!-- vague moment of time in attribute -->
+ <p><time datetime='2006-11-20T16:24'>text</time></p>
+ <p><time datetime='2006-11-20T16:24:33'>text</time></p>
+ <p><time datetime='2006-11-20T16:24:33.89'>text</time></p>
+
+ <p><time datetime='2006-11-20T16:24Z'>text</time></p>
+ <p><time datetime='2006-11-20T16:24:33Z'>text</time></p>
+ <p><time datetime='2006-11-20T16:24:33.89Z'>text</time></p>
+
+ <p><time datetime='2006-11-20T16:24+02:00'>text</time></p>
+ <p><time datetime='2006-11-20T16:24:33+02:00'>text</time></p>
+ <p><time datetime='2006-11-20T16:24:33.89+02:00'>text</time></p>
+
+ <p><time datetime='16:24'>text</time></p>
+ <p><time datetime='16:24:33'>text</time></p>
+ <p><time datetime='16:24:33.89'>text</time></p>
+
+ <!-- vague moment of time in content -->
+ <p><time>2006-11-20T16:24</time></p>
+ <p><time>2006-11-20T16:24:33</time></p>
+ <p><time>2006-11-20T16:24:33.89</time></p>
+
+ <p><time>2006-11-20T16:24Z</time></p>
+ <p><time>2006-11-20T16:24:33Z</time></p>
+ <p><time>2006-11-20T16:24:33.89Z</time></p>
+
+ <p><time>2006-11-20T16:24+02:00</time></p>
+ <p><time>2006-11-20T16:24:33+02:00</time></p>
+ <p><time>2006-11-20T16:24:33.89+02:00</time></p>
+
+ <p><time>16:24</time></p>
+ <p><time>16:24:33</time></p>
+ <p><time>16:24:33.89</time></p>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/title/empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/title/empty-novalid.html
new file mode 100644
index 00000000000..f3089b5961f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/title/empty-novalid.html
@@ -0,0 +1,4 @@
+<!doctype html>
+<!-- document with empty title element -->
+<meta charset=utf-8>
+<title></title>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/title/missing-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/title/missing-novalid.html
new file mode 100644
index 00000000000..c0a83a4da90
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/title/missing-novalid.html
@@ -0,0 +1,2 @@
+<!doctype html>
+<!-- document with no title element -->
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src-empty-novalid.html
new file mode 100644
index 00000000000..c915ef521a8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>empty src is not valid</title>
+<video><track src=""></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src-isvalid.html
new file mode 100644
index 00000000000..190eec7e8af
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src-isvalid.html
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid src</title>
+<video><track src="file:///"></video><!-- scheme-file-slash-slash-slash-only -->
+<video><track src="http://a:@www.example.com"></video><!-- userinfo-password-empty -->
+<video><track src="foo://///////"></video><!-- scheme-private-path-leading-slashes-only -->
+<video><track src="file://abc|/foo/bar"></video><!-- scheme-file-slash-slash-abc-bar -->
+<video><track src="/a/b/c"></video><!-- path-simple-relative -->
+<video><track src="http://example.com/你好你好"></video><!-- path-unicode-han -->
+<video><track src="/a/%2f/c"></video><!-- path-percent-encoded-slash-plus-slashes-relative -->
+<video><track src="http://f:/c"></video><!-- port-none-but-colon -->
+<video><track src="http://example.com/foo%41%7a"></video><!-- path-percent-encoded-multiple -->
+<video><track src="http://192.168.0.257/"></video><!-- host-IP-address-broken -->
+<video><track src="madeupscheme:example.com/"></video><!-- scheme-private-no-slash -->
+<video><track src="?"></video><!-- query-empty-no-path-relative -->
+<video><track src="http://example.com/%20foo"></video><!-- path-percent-encoded-space -->
+<video><track src="mailto:/example.com/"></video><!-- scheme-mailto-single-slash -->
+<video><track src="::"></video><!-- path-leading-colon-colon-relative -->
+<video><track src="http://example.com/%3A%3a%3C%3c"></video><!-- path-percent-encoded-mixed-case -->
+<video><track src="http://user:pass@foo:21/bar;par?b#c"></video><!-- userinfo -->
+<video><track src="ws:/example.com/"></video><!-- scheme-ws-single-slash -->
+<video><track src="foo://"></video><!-- scheme-private-slash-slash -->
+<video><track src="#"></video><!-- fragment-empty-hash-only-no-path-relative -->
+<video><track src="http://f:00000000000000/c"></video><!-- port-00000000000000 -->
+<video><track src="foo:////://///"></video><!-- scheme-private-path-leading-slashes-colon-slashes -->
+<video><track src=":23"></video><!-- path-leading-colon-number-relative -->
+<video><track src="foo:/"></video><!-- scheme-private-slash -->
+<video><track src="http://💩"></video><!-- host-is-pile-of-poo -->
+<video><track src="file:test"></video><!-- scheme-file-no-slash -->
+<video><track src="file://C|/foo/bar"></video><!-- scheme-file-slash-slash-c-bar -->
+<video><track src="#/"></video><!-- fragment-slash-relative -->
+<video><track src="http://192.0x00A80001"></video><!-- host-192.0x00A80001 -->
+<video><track src="foo.com"></video><!-- scheme-none-relative -->
+<video><track src="http💩//:foo"></video><!-- path-contains-pile-of-poo -->
+<video><track src="File://foo/bar.html"></video><!-- scheme-file-uppercase -->
+<video><track src=":/"></video><!-- path-leading-colon-slash-relative -->
+<video><track src="http://www.foo。bar.com"></video><!-- host-exotic-dot -->
+<video><track src="http://GOO​⁠goo.com"></video><!-- host-exotic-whitespace -->
+<video><track src="file:///foo/bar.txt"></video><!-- scheme-file-host-empty -->
+<video><track src="javascript:/example.com/"></video><!-- scheme-javascript-single-slash -->
+<video><track src="gopher:/example.com/"></video><!-- scheme-gopher-single-slash -->
+<video><track src="ftps:example.com/"></video><!-- scheme-ftps-no-slash -->
+<video><track src="file://server/foo/bar"></video><!-- scheme-file-host-included -->
+<video><track src="http://example.com/foo%00"></video><!-- path-percent-encoded-u0000 -->
+<video><track src="a:foo.com"></video><!-- scheme-private -->
+<video><track src=":"></video><!-- path-colon-relative -->
+<video><track src="http://:b@www.example.com"></video><!-- userinfo-user-empty -->
+<video><track src="file:/"></video><!-- scheme-file-slash-only -->
+<video><track src="wss:example.com/"></video><!-- scheme-wss-no-slash -->
+<video><track src="::23"></video><!-- path-colon-colon-number-relative -->
+<video><track src="/a%2fc"></video><!-- path-percent-encoded-slash-relative -->
+<video><track src="http://a:b@c:29/d"></video><!-- userinfo-host-port-path -->
+<video><track src="gopher:example.com/"></video><!-- scheme-gopher-no-slash -->
+<video><track src="madeupscheme:/example.com/"></video><!-- scheme-private-single-slash -->
+<video><track src="mailto:example.com/"></video><!-- scheme-mailto-no-slash -->
+<video><track src="http://%25DOMAIN:foobar@foodomain.com"></video><!-- userinfo-username-contains-percent-encoded -->
+<video><track src="/:23"></video><!-- path-slash-colon-number-relative -->
+<video><track src="foo://///////bar.com/"></video><!-- scheme-private-path-leading-slashes-chars -->
+<video><track src="http://[2001::1]:80"></video><!-- host-ipv6-port -->
+<video><track src="data:text/plain,foo"></video><!-- scheme-data-no-slash -->
+<video><track src="http://example.com/foo/%2e"></video><!-- path-percent-encoded-dot -->
+<video><track src="file:/example.com/"></video><!-- scheme-file-single-slash -->
+<video><track src="http://example.com/©zbar"></video><!-- path-non-ascii -->
+<video><track src="http://example.com//foo"></video><!-- path-uFEFF -->
+<video><track src="wss:/example.com/"></video><!-- scheme-wss-single-slash -->
+<video><track src="http://foo/abcd#foo?bar"></video><!-- fragment-contains-question-mark -->
+<video><track src=":#"></video><!-- path-leading-colon-hash-relative -->
+<video><track src="http://example.com/foo%91"></video><!-- path-percent-encoded-u0091 -->
+<video><track src="c:/foo"></video><!-- scheme-private-single-letter -->
+<video><track src=":foo.com"></video><!-- path-leading-colon-chars-relative -->
+<video><track src="http://你好你好"></video><!-- host-idn-unicode-han -->
+<video><track src="http://example.com/foo#💩"></video><!-- fragment-contains-pile-of-poo -->
+<video><track src="file:"></video><!-- scheme-file-scheme-only -->
+<video><track src="#β"></video><!-- fragment-non-ascii-relative -->
+<video><track src="foo:/bar.com/"></video><!-- scheme-private-path -->
+<video><track src="http://f:0/c"></video><!-- port-0 -->
+<video><track src="#;?"></video><!-- fragment-semicolon-question-mark-relative -->
+<video><track src="http://Go.com"></video><!-- host-fullwidth -->
+<video><track src="http://@www.example.com"></video><!-- userinfo-empty -->
+<video><track src="http://example.com/‮/foo/‭/bar"></video><!-- path-u202E-u202D -->
+<video><track src="http://[2001::1]"></video><!-- host-ipv6 -->
+<video><track src="💩http://foo"></video><!-- path-starts-with-pile-of-poo -->
+<video><track src="http://foo/abcd?efgh?ijkl"></video><!-- query-contains-question-mark -->
+<video><track src="//foo/bar"></video><!-- scheme-schemeless-relative -->
+<video><track src="ftps:/example.com/"></video><!-- scheme-ftps-single-slash -->
+<video><track src="http://foo.com:b@d/"></video><!-- userinfo-username-non-alpha -->
+<video><track src=":a"></video><!-- path-leading-colon-letter-relative -->
+<video><track src="/"></video><!-- path-slash-only-relative -->
+<video><track src="http://example.com/foo?💩"></video><!-- query-contains-pile-of-poo -->
+<video><track src="http://f:00000000000000000000080/c"></video><!-- port-00000000000000000000080 -->
+<video><track src="file://"></video><!-- scheme-file-slash-slash-only -->
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src-whitespace-only-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src-whitespace-only-novalid.html
new file mode 100644
index 00000000000..49a19ded1a5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src-whitespace-only-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>empty src is not valid</title>
+<video><track src="
+"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/fragment-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/fragment-backslash-novalid.html
new file mode 100644
index 00000000000..06dc4825bd1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/fragment-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: fragment-backslash</title>
+<video><track src="#\"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/fragment-contains-hash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/fragment-contains-hash-novalid.html
new file mode 100644
index 00000000000..c629c503d5f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/fragment-contains-hash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: fragment-contains-hash</title>
+<video><track src="http://foo/path#f#g"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/fragment-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/fragment-leading-space-novalid.html
new file mode 100644
index 00000000000..f2632d5e26a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/fragment-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: fragment-leading-space</title>
+<video><track src="http://f:21/b# e"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-cr-novalid.html
new file mode 100644
index 00000000000..1b2d74fc2f8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-cr</title>
+<video><track src="http://example. org"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-double-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-double-percent-encoded-novalid.html
new file mode 100644
index 00000000000..098225713cf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-double-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-double-percent-encoded</title>
+<video><track src="http://%41.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-double-percent-encoded-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-double-percent-encoded-percent-encoded-novalid.html
new file mode 100644
index 00000000000..7a66a895730
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-double-percent-encoded-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-double-percent-encoded-percent-encoded</title>
+<video><track src="http://%ef%bc%85%ef%bc%94%ef%bc%91.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-empty-novalid.html
new file mode 100644
index 00000000000..0978bfe8407
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-empty</title>
+<video><track src="http://"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-empty-userinfo-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-empty-userinfo-empty-novalid.html
new file mode 100644
index 00000000000..a193260fc26
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-empty-userinfo-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-empty-userinfo-empty</title>
+<video><track src="http://@/www.example.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-empty-with-userinfo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-empty-with-userinfo-novalid.html
new file mode 100644
index 00000000000..fc9c41e8efb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-empty-with-userinfo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-empty-with-userinfo</title>
+<video><track src="http://user:pass@/"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-hostname-in-brackets-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-hostname-in-brackets-novalid.html
new file mode 100644
index 00000000000..70aa4d064ca
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-hostname-in-brackets-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-hostname-in-brackets</title>
+<video><track src="http://[www.google.com]/"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-invalid-unicode-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-invalid-unicode-novalid.html
new file mode 100644
index 00000000000..54433b15b97
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-invalid-unicode-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-invalid-unicode</title>
+<video><track src="http://﷐zyx.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-invalid-unicode-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-invalid-unicode-percent-encoded-novalid.html
new file mode 100644
index 00000000000..8e93c61bdf4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-invalid-unicode-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-invalid-unicode-percent-encoded</title>
+<video><track src="http://%ef%b7%90zyx.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-newline-novalid.html
new file mode 100644
index 00000000000..7b206246d62
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-newline</title>
+<video><track src="http://example.
+org"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-space-novalid.html
new file mode 100644
index 00000000000..31c35862b6e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-space</title>
+<video><track src="http://example .org"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-square-brackets-port-contains-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-square-brackets-port-contains-colon-novalid.html
new file mode 100644
index 00000000000..791359b5017
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-square-brackets-port-contains-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-square-brackets-port-contains-colon</title>
+<video><track src="http://[1::2]:3:4"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-tab-novalid.html
new file mode 100644
index 00000000000..cebfa553ba6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-tab</title>
+<video><track src="http://example .org"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-u0000-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-u0000-percent-encoded-novalid.html
new file mode 100644
index 00000000000..7aaf5336f0f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-u0000-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-u0000-percent-encoded</title>
+<video><track src="http://%00.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-u0000-percent-encoded-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-u0000-percent-encoded-percent-encoded-novalid.html
new file mode 100644
index 00000000000..2901170f15f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/host-u0000-percent-encoded-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-u0000-percent-encoded-percent-encoded</title>
+<video><track src="http://%ef%bc%85%ef%bc%90%ef%bc%90.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/path-bare-percent-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/path-bare-percent-sign-novalid.html
new file mode 100644
index 00000000000..a6cea54599d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/path-bare-percent-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-bare-percent-sign</title>
+<video><track src="http://example.com/foo%"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/path-contains-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/path-contains-space-novalid.html
new file mode 100644
index 00000000000..4cc4ea47c80
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/path-contains-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-contains-space</title>
+<video><track src="/a/ /c"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/path-leading-backslash-at-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/path-leading-backslash-at-sign-novalid.html
new file mode 100644
index 00000000000..8f785227730
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/path-leading-backslash-at-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-leading-backslash-at-sign</title>
+<video><track src="http://foo.com/\@"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/path-leading-colon-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/path-leading-colon-backslash-novalid.html
new file mode 100644
index 00000000000..4e959284469
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/path-leading-colon-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-leading-colon-backslash</title>
+<video><track src=":\"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/path-leading-colon-chars-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/path-leading-colon-chars-backslash-novalid.html
new file mode 100644
index 00000000000..8e14139e665
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/path-leading-colon-chars-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-leading-colon-chars-backslash</title>
+<video><track src=":foo.com\"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/path-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/path-leading-space-novalid.html
new file mode 100644
index 00000000000..0b9847f009c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/path-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-leading-space</title>
+<video><track src="http://f:21/ b"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/path-percent-encoded-malformed-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/path-percent-encoded-malformed-novalid.html
new file mode 100644
index 00000000000..a4f6e796e9e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/path-percent-encoded-malformed-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-percent-encoded-malformed</title>
+<video><track src="http://example.com/foo/%2e%2"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/path-relative-square-brackets-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/path-relative-square-brackets-novalid.html
new file mode 100644
index 00000000000..f83da9a1d60
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/path-relative-square-brackets-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-relative-square-brackets</title>
+<video><track src="[61:24:74]:98"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/path-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/path-tab-novalid.html
new file mode 100644
index 00000000000..b8c5b36ba06
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/path-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-tab</title>
+<video><track src="http://example.com/foo bar"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/path-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/path-trailing-space-novalid.html
new file mode 100644
index 00000000000..5da84a87294
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/path-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-trailing-space</title>
+<video><track src="http://f:21/b ?"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/path-u0091-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/path-u0091-novalid.html
new file mode 100644
index 00000000000..16c810dff24
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/path-u0091-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-u0091</title>
+<video><track src="http://example.com/foo‘"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/port-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/port-cr-novalid.html
new file mode 100644
index 00000000000..666a5d89d3c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/port-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-cr</title>
+<video><track src="http://f: /c"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/port-leading-colon-bracket-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/port-leading-colon-bracket-colon-novalid.html
new file mode 100644
index 00000000000..c568c332cb3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/port-leading-colon-bracket-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-leading-colon-bracket-colon</title>
+<video><track src="http://2001::1]:80"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/port-leading-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/port-leading-colon-novalid.html
new file mode 100644
index 00000000000..a6e554183c1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/port-leading-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-leading-colon</title>
+<video><track src="http://2001::1"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/port-leading-dash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/port-leading-dash-novalid.html
new file mode 100644
index 00000000000..fe6a8bf0aa6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/port-leading-dash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-leading-dash</title>
+<video><track src="http://foo:-80/"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/port-multiple-letters-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/port-multiple-letters-novalid.html
new file mode 100644
index 00000000000..2798d9a4d47
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/port-multiple-letters-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-multiple-letters</title>
+<video><track src="http://f:fifty-two/c"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/port-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/port-newline-novalid.html
new file mode 100644
index 00000000000..5d1d924a16c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/port-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-newline</title>
+<video><track src="http://f:
+/c"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/port-single-letter-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/port-single-letter-novalid.html
new file mode 100644
index 00000000000..40ee9156a4b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/port-single-letter-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-single-letter</title>
+<video><track src="http://f:b/c"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/port-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/port-space-novalid.html
new file mode 100644
index 00000000000..d6e85ae51f0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/port-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-space</title>
+<video><track src="http://f: /c"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/port-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/port-tab-novalid.html
new file mode 100644
index 00000000000..a4963cf999f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/port-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-tab</title>
+<video><track src="http://f: /c"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/query-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/query-leading-space-novalid.html
new file mode 100644
index 00000000000..d5d1f278264
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/query-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: query-leading-space</title>
+<video><track src="http://f:21/b? d"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/query-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/query-trailing-space-novalid.html
new file mode 100644
index 00000000000..489f0fa378d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/query-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: query-trailing-space</title>
+<video><track src="http://f:21/b?d #"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-data-contains-fragment-haswarn.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-data-contains-fragment-haswarn.html
new file mode 100644
index 00000000000..e0489ac6046
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-data-contains-fragment-haswarn.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>src warning: scheme-data-contains-fragment</title>
+<video><track src="data:text/html,test#test"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-data-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-data-single-slash-novalid.html
new file mode 100644
index 00000000000..5799c3fb981
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-data-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-data-single-slash</title>
+<video><track src="data:/example.com/"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-file-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-file-backslash-novalid.html
new file mode 100644
index 00000000000..6921ade0ac8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-file-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-file-backslash</title>
+<video><track src="file:c:\foo\bar.html"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-file-single-slash-c-bar-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-file-single-slash-c-bar-novalid.html
new file mode 100644
index 00000000000..19ec1b90d4c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-file-single-slash-c-bar-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-file-single-slash-c-bar</title>
+<video><track src="file:/C|/foo/bar"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-file-triple-slash-c-bar-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-file-triple-slash-c-bar-novalid.html
new file mode 100644
index 00000000000..3fcc985f90b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-file-triple-slash-c-bar-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-file-triple-slash-c-bar</title>
+<video><track src="file:///C|/foo/bar"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-ftp-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-ftp-no-slash-novalid.html
new file mode 100644
index 00000000000..35e17447841
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-ftp-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-ftp-no-slash</title>
+<video><track src="ftp:example.com/"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-ftp-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-ftp-single-slash-novalid.html
new file mode 100644
index 00000000000..e9a53858791
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-ftp-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-ftp-single-slash</title>
+<video><track src="ftp:/example.com/"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-http-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-http-backslash-novalid.html
new file mode 100644
index 00000000000..ed6968d4ff7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-http-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-http-backslash</title>
+<video><track src="http:\\foo.com\"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-http-no-slash-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-http-no-slash-colon-novalid.html
new file mode 100644
index 00000000000..79ddaf10a38
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-http-no-slash-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-http-no-slash-colon</title>
+<video><track src="http::@c:29"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-http-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-http-no-slash-novalid.html
new file mode 100644
index 00000000000..813e4aeff17
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-http-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-http-no-slash</title>
+<video><track src="http:foo.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-http-no-slash-square-bracket-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-http-no-slash-square-bracket-novalid.html
new file mode 100644
index 00000000000..1db1adad1b6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-http-no-slash-square-bracket-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-http-no-slash-square-bracket</title>
+<video><track src="http:[61:27]/:foo"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-http-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-http-single-slash-novalid.html
new file mode 100644
index 00000000000..9c262feea62
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-http-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-http-single-slash</title>
+<video><track src="http:/example.com/"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-https-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-https-no-slash-novalid.html
new file mode 100644
index 00000000000..f2999019e27
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-https-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-https-no-slash</title>
+<video><track src="https:example.com/"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-https-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-https-single-slash-novalid.html
new file mode 100644
index 00000000000..73048441267
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-https-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-https-single-slash</title>
+<video><track src="https:/example.com/"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-javascript-no-slash-malformed-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-javascript-no-slash-malformed-novalid.html
new file mode 100644
index 00000000000..13a633d3708
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-javascript-no-slash-malformed-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-javascript-no-slash-malformed</title>
+<video><track src="javascript:example.com/"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-trailing-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-trailing-cr-novalid.html
new file mode 100644
index 00000000000..32e379e9947
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-trailing-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-trailing-cr</title>
+<video><track src="a: foo.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-trailing-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-trailing-newline-novalid.html
new file mode 100644
index 00000000000..81bf43c97f8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-trailing-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-trailing-newline</title>
+<video><track src="a:
+foo.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-trailing-space-novalid.html
new file mode 100644
index 00000000000..65f414637cd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-trailing-space</title>
+<video><track src="a: foo.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-trailing-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-trailing-tab-novalid.html
new file mode 100644
index 00000000000..924eb4e868f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/scheme-trailing-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-trailing-tab</title>
+<video><track src="a: foo.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/userinfo-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/userinfo-backslash-novalid.html
new file mode 100644
index 00000000000..603c7d21042
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/userinfo-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: userinfo-backslash</title>
+<video><track src="http://a\b:c\d@foo.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/userinfo-password-bad-chars-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/userinfo-password-bad-chars-novalid.html
new file mode 100644
index 00000000000..58b50489ff3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/userinfo-password-bad-chars-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: userinfo-password-bad-chars</title>
+<video><track src="http://&a:foo(b]c@d:2/"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/userinfo-password-contains-pile-of-poo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/userinfo-password-contains-pile-of-poo-novalid.html
new file mode 100644
index 00000000000..8bd21d98736
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/userinfo-password-contains-pile-of-poo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: userinfo-password-contains-pile-of-poo</title>
+<video><track src="http://foo:💩@example.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/userinfo-username-contains-at-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/userinfo-username-contains-at-sign-novalid.html
new file mode 100644
index 00000000000..e20902adaac
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/userinfo-username-contains-at-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: userinfo-username-contains-at-sign</title>
+<video><track src="http://::@c@d:2"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/userinfo-username-contains-pile-of-poo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/userinfo-username-contains-pile-of-poo-novalid.html
new file mode 100644
index 00000000000..98866840743
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/track/src/userinfo-username-contains-pile-of-poo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: userinfo-username-contains-pile-of-poo</title>
+<video><track src="http://💩:foo@example.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/u/model-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/u/model-isvalid.html
new file mode 100644
index 00000000000..0ce3f95b461
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/u/model-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>the "u" element is not obsolete</title>
+<meta charset=utf-8>
+</head>
+<body>
+<u>baz</u>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ul/model-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ul/model-isvalid.html
new file mode 100644
index 00000000000..3f3adbf9b40
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ul/model-isvalid.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Unordered List: &lt;ul&gt; &lt;li&gt;</title>
+</head>
+<body>
+ <!-- is block -->
+ <ul class="class" id="id" lang="en">
+ <li class="class" id="id2" lang="en">text</li>
+ </ul>
+
+ <!-- can be empty -->
+ <ul></ul>
+ <ul>
+ <li></li>
+ <li></li>
+ </ul>
+
+ <!-- can contain structured inline -->
+ <ul>
+ <li>some <em>text</em>
+ <pre>more text</pre>
+ </li>
+ </ul>
+
+ <!-- can contain blocks -->
+ <ul>
+ <li>
+ <p>some</p>
+ <p>text</p>
+ </li>
+ </ul>
+
+ <!-- can contain interactive -->
+ <ul><li><a>text</a></li></ul>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ul/model-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ul/model-novalid.html
new file mode 100644
index 00000000000..9bb4bf09030
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/ul/model-novalid.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Unordered List: &lt;ul&gt; &lt;li&gt;</title>
+</head>
+<body>
+ <!-- is block -->
+ <ul class="class" id="id" lang="en">
+ <li class="class" id="id" lang="en">text</li>
+ </ul>
+
+ <!-- is structured inline -->
+ <p>paragraph
+ <ul class="class" id="id" lang="en">
+ <li class="class" id="id" lang="en">text</li>
+ </ul>
+ </p>
+
+ <!-- can be empty -->
+ <ul></ul>
+ <ul>
+ <li></li>
+ <li></li>
+ </ul>
+
+ <!-- cannot contain structured inline -->
+ <ul>
+ <li>some <em>text</em>
+ <pre>more text</pre>
+ </li>
+ </ul>
+ <p>paragraph
+ <ul>
+ <li>some <em>text</em>
+ <pre>more text</pre>
+ </li>
+ </ul>
+ </p>
+
+ <!-- can contain blocks -->
+ <ul>
+ <li>
+ <p>some</p>
+ <p>text</p>
+ </li>
+ </ul>
+
+ <!-- can contain interactive -->
+ <ul><li><a>text</a></li></ul>
+ <p>paragraph
+ <ul><li><a>text</a></li></ul>
+ </p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/var/model-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/var/model-isvalid.html
new file mode 100644
index 00000000000..06a71d4b31c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/var/model-isvalid.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;var&gt;</title>
+</head>
+<body>
+ <!-- is structured inline -->
+ <p><var class="class" lang="en">text</var></p>
+
+ <!-- is strictly inline -->
+ <p><dfn><var class="class" lang="en">text</var></dfn></p>
+
+ <!-- can be empty -->
+ <p>text <var></var></p>
+ <p>text <dfn><var></var></dfn></p>
+
+ <!-- can contain interactive -->
+ <p><var><a>text</a></var></p>
+ <p><dfn><var><a>text</a></var></dfn></p>
+
+ <!-- cannot contain structured inline -->
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/var/model-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/var/model-novalid.html
new file mode 100644
index 00000000000..853481ad105
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/var/model-novalid.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;var&gt;</title>
+</head>
+<body>
+ <!-- not a block -->
+ <var>text</var>
+
+ <!-- cannot contain structured inline -->
+ <p><var><ul><li>text</li></ul></var></p>
+
+ <!-- cannot contain interactive if parent forbids interactive -->
+ <p><a><var><a>text</a></var></a></p>
+ <p><a><dfn><var><a>text</a></var></dfn></a></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/model-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/model-isvalid.html
new file mode 100644
index 00000000000..4d49826832e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/model-isvalid.html
@@ -0,0 +1,4 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>video with flow content and flow parent</title>
+<div><video><p>foo</p></video></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/model-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/model-novalid.html
new file mode 100644
index 00000000000..fa9af261972
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/model-novalid.html
@@ -0,0 +1,4 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>video with flow content and phrasing parent</title>
+<span><video><p>foo</p></video></span>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster-empty-novalid.html
new file mode 100644
index 00000000000..efd5238b697
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>empty poster is not valid</title>
+<video poster=""></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster-isvalid.html
new file mode 100644
index 00000000000..01e32e775d0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster-isvalid.html
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid poster</title>
+<video poster="file:///"></video><!-- scheme-file-slash-slash-slash-only -->
+<video poster="http://a:@www.example.com"></video><!-- userinfo-password-empty -->
+<video poster="foo://///////"></video><!-- scheme-private-path-leading-slashes-only -->
+<video poster="file://abc|/foo/bar"></video><!-- scheme-file-slash-slash-abc-bar -->
+<video poster="/a/b/c"></video><!-- path-simple-relative -->
+<video poster="http://example.com/你好你好"></video><!-- path-unicode-han -->
+<video poster="/a/%2f/c"></video><!-- path-percent-encoded-slash-plus-slashes-relative -->
+<video poster="http://f:/c"></video><!-- port-none-but-colon -->
+<video poster="http://example.com/foo%41%7a"></video><!-- path-percent-encoded-multiple -->
+<video poster="http://192.168.0.257/"></video><!-- host-IP-address-broken -->
+<video poster="madeupscheme:example.com/"></video><!-- scheme-private-no-slash -->
+<video poster="?"></video><!-- query-empty-no-path-relative -->
+<video poster="http://example.com/%20foo"></video><!-- path-percent-encoded-space -->
+<video poster="mailto:/example.com/"></video><!-- scheme-mailto-single-slash -->
+<video poster="::"></video><!-- path-leading-colon-colon-relative -->
+<video poster="http://example.com/%3A%3a%3C%3c"></video><!-- path-percent-encoded-mixed-case -->
+<video poster="http://user:pass@foo:21/bar;par?b#c"></video><!-- userinfo -->
+<video poster="ws:/example.com/"></video><!-- scheme-ws-single-slash -->
+<video poster="foo://"></video><!-- scheme-private-slash-slash -->
+<video poster="#"></video><!-- fragment-empty-hash-only-no-path-relative -->
+<video poster="http://f:00000000000000/c"></video><!-- port-00000000000000 -->
+<video poster="foo:////://///"></video><!-- scheme-private-path-leading-slashes-colon-slashes -->
+<video poster=":23"></video><!-- path-leading-colon-number-relative -->
+<video poster="foo:/"></video><!-- scheme-private-slash -->
+<video poster="http://💩"></video><!-- host-is-pile-of-poo -->
+<video poster="file:test"></video><!-- scheme-file-no-slash -->
+<video poster="file://C|/foo/bar"></video><!-- scheme-file-slash-slash-c-bar -->
+<video poster="#/"></video><!-- fragment-slash-relative -->
+<video poster="http://192.0x00A80001"></video><!-- host-192.0x00A80001 -->
+<video poster="foo.com"></video><!-- scheme-none-relative -->
+<video poster="http💩//:foo"></video><!-- path-contains-pile-of-poo -->
+<video poster="File://foo/bar.html"></video><!-- scheme-file-uppercase -->
+<video poster=":/"></video><!-- path-leading-colon-slash-relative -->
+<video poster="http://www.foo。bar.com"></video><!-- host-exotic-dot -->
+<video poster="http://GOO​⁠goo.com"></video><!-- host-exotic-whitespace -->
+<video poster="file:///foo/bar.txt"></video><!-- scheme-file-host-empty -->
+<video poster="javascript:/example.com/"></video><!-- scheme-javascript-single-slash -->
+<video poster="gopher:/example.com/"></video><!-- scheme-gopher-single-slash -->
+<video poster="ftps:example.com/"></video><!-- scheme-ftps-no-slash -->
+<video poster="file://server/foo/bar"></video><!-- scheme-file-host-included -->
+<video poster="http://example.com/foo%00"></video><!-- path-percent-encoded-u0000 -->
+<video poster="a:foo.com"></video><!-- scheme-private -->
+<video poster=":"></video><!-- path-colon-relative -->
+<video poster="http://:b@www.example.com"></video><!-- userinfo-user-empty -->
+<video poster="file:/"></video><!-- scheme-file-slash-only -->
+<video poster="wss:example.com/"></video><!-- scheme-wss-no-slash -->
+<video poster="::23"></video><!-- path-colon-colon-number-relative -->
+<video poster="/a%2fc"></video><!-- path-percent-encoded-slash-relative -->
+<video poster="http://a:b@c:29/d"></video><!-- userinfo-host-port-path -->
+<video poster="gopher:example.com/"></video><!-- scheme-gopher-no-slash -->
+<video poster="madeupscheme:/example.com/"></video><!-- scheme-private-single-slash -->
+<video poster="mailto:example.com/"></video><!-- scheme-mailto-no-slash -->
+<video poster="http://%25DOMAIN:foobar@foodomain.com"></video><!-- userinfo-username-contains-percent-encoded -->
+<video poster="/:23"></video><!-- path-slash-colon-number-relative -->
+<video poster="foo://///////bar.com/"></video><!-- scheme-private-path-leading-slashes-chars -->
+<video poster="http://[2001::1]:80"></video><!-- host-ipv6-port -->
+<video poster="data:text/plain,foo"></video><!-- scheme-data-no-slash -->
+<video poster="http://example.com/foo/%2e"></video><!-- path-percent-encoded-dot -->
+<video poster="file:/example.com/"></video><!-- scheme-file-single-slash -->
+<video poster="http://example.com/©zbar"></video><!-- path-non-ascii -->
+<video poster="http://example.com//foo"></video><!-- path-uFEFF -->
+<video poster="wss:/example.com/"></video><!-- scheme-wss-single-slash -->
+<video poster="http://foo/abcd#foo?bar"></video><!-- fragment-contains-question-mark -->
+<video poster=":#"></video><!-- path-leading-colon-hash-relative -->
+<video poster="http://example.com/foo%91"></video><!-- path-percent-encoded-u0091 -->
+<video poster="c:/foo"></video><!-- scheme-private-single-letter -->
+<video poster=":foo.com"></video><!-- path-leading-colon-chars-relative -->
+<video poster="http://你好你好"></video><!-- host-idn-unicode-han -->
+<video poster="http://example.com/foo#💩"></video><!-- fragment-contains-pile-of-poo -->
+<video poster="file:"></video><!-- scheme-file-scheme-only -->
+<video poster="#β"></video><!-- fragment-non-ascii-relative -->
+<video poster="foo:/bar.com/"></video><!-- scheme-private-path -->
+<video poster="http://f:0/c"></video><!-- port-0 -->
+<video poster="#;?"></video><!-- fragment-semicolon-question-mark-relative -->
+<video poster="http://Go.com"></video><!-- host-fullwidth -->
+<video poster="http://@www.example.com"></video><!-- userinfo-empty -->
+<video poster="http://example.com/‮/foo/‭/bar"></video><!-- path-u202E-u202D -->
+<video poster="http://[2001::1]"></video><!-- host-ipv6 -->
+<video poster="💩http://foo"></video><!-- path-starts-with-pile-of-poo -->
+<video poster="http://foo/abcd?efgh?ijkl"></video><!-- query-contains-question-mark -->
+<video poster="//foo/bar"></video><!-- scheme-schemeless-relative -->
+<video poster="ftps:/example.com/"></video><!-- scheme-ftps-single-slash -->
+<video poster="http://foo.com:b@d/"></video><!-- userinfo-username-non-alpha -->
+<video poster=":a"></video><!-- path-leading-colon-letter-relative -->
+<video poster="/"></video><!-- path-slash-only-relative -->
+<video poster="http://example.com/foo?💩"></video><!-- query-contains-pile-of-poo -->
+<video poster="http://f:00000000000000000000080/c"></video><!-- port-00000000000000000000080 -->
+<video poster="file://"></video><!-- scheme-file-slash-slash-only -->
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster-whitespace-only-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster-whitespace-only-novalid.html
new file mode 100644
index 00000000000..b53bf190263
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster-whitespace-only-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>empty poster is not valid</title>
+<video poster="
+"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/fragment-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/fragment-backslash-novalid.html
new file mode 100644
index 00000000000..e2d9764e37b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/fragment-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: fragment-backslash</title>
+<video poster="#\"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/fragment-contains-hash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/fragment-contains-hash-novalid.html
new file mode 100644
index 00000000000..cb01ae009f0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/fragment-contains-hash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: fragment-contains-hash</title>
+<video poster="http://foo/path#f#g"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/fragment-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/fragment-leading-space-novalid.html
new file mode 100644
index 00000000000..8bf3631bfb8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/fragment-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: fragment-leading-space</title>
+<video poster="http://f:21/b# e"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-cr-novalid.html
new file mode 100644
index 00000000000..8e7cd1af040
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: host-cr</title>
+<video poster="http://example. org"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-double-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-double-percent-encoded-novalid.html
new file mode 100644
index 00000000000..e3c4eafc653
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-double-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: host-double-percent-encoded</title>
+<video poster="http://%41.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-double-percent-encoded-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-double-percent-encoded-percent-encoded-novalid.html
new file mode 100644
index 00000000000..34f58f6fa5c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-double-percent-encoded-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: host-double-percent-encoded-percent-encoded</title>
+<video poster="http://%ef%bc%85%ef%bc%94%ef%bc%91.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-empty-novalid.html
new file mode 100644
index 00000000000..704af4b76a7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: host-empty</title>
+<video poster="http://"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-empty-userinfo-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-empty-userinfo-empty-novalid.html
new file mode 100644
index 00000000000..896ed885003
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-empty-userinfo-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: host-empty-userinfo-empty</title>
+<video poster="http://@/www.example.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-empty-with-userinfo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-empty-with-userinfo-novalid.html
new file mode 100644
index 00000000000..2ac4d5f7f34
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-empty-with-userinfo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: host-empty-with-userinfo</title>
+<video poster="http://user:pass@/"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-hostname-in-brackets-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-hostname-in-brackets-novalid.html
new file mode 100644
index 00000000000..5458f16e654
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-hostname-in-brackets-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: host-hostname-in-brackets</title>
+<video poster="http://[www.google.com]/"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-invalid-unicode-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-invalid-unicode-novalid.html
new file mode 100644
index 00000000000..c8f206dde36
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-invalid-unicode-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: host-invalid-unicode</title>
+<video poster="http://﷐zyx.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-invalid-unicode-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-invalid-unicode-percent-encoded-novalid.html
new file mode 100644
index 00000000000..b891644888c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-invalid-unicode-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: host-invalid-unicode-percent-encoded</title>
+<video poster="http://%ef%b7%90zyx.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-newline-novalid.html
new file mode 100644
index 00000000000..de25e97766a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: host-newline</title>
+<video poster="http://example.
+org"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-space-novalid.html
new file mode 100644
index 00000000000..1e35a2f9620
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: host-space</title>
+<video poster="http://example .org"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-square-brackets-port-contains-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-square-brackets-port-contains-colon-novalid.html
new file mode 100644
index 00000000000..094eec8770d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-square-brackets-port-contains-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: host-square-brackets-port-contains-colon</title>
+<video poster="http://[1::2]:3:4"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-tab-novalid.html
new file mode 100644
index 00000000000..c5455bee119
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: host-tab</title>
+<video poster="http://example .org"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-u0000-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-u0000-percent-encoded-novalid.html
new file mode 100644
index 00000000000..81c27763820
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-u0000-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: host-u0000-percent-encoded</title>
+<video poster="http://%00.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-u0000-percent-encoded-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-u0000-percent-encoded-percent-encoded-novalid.html
new file mode 100644
index 00000000000..34ccb2844a0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/host-u0000-percent-encoded-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: host-u0000-percent-encoded-percent-encoded</title>
+<video poster="http://%ef%bc%85%ef%bc%90%ef%bc%90.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/path-bare-percent-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/path-bare-percent-sign-novalid.html
new file mode 100644
index 00000000000..170314bbe5f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/path-bare-percent-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: path-bare-percent-sign</title>
+<video poster="http://example.com/foo%"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/path-contains-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/path-contains-space-novalid.html
new file mode 100644
index 00000000000..e17733c2eb1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/path-contains-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: path-contains-space</title>
+<video poster="/a/ /c"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/path-leading-backslash-at-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/path-leading-backslash-at-sign-novalid.html
new file mode 100644
index 00000000000..83d43d2b4e6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/path-leading-backslash-at-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: path-leading-backslash-at-sign</title>
+<video poster="http://foo.com/\@"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/path-leading-colon-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/path-leading-colon-backslash-novalid.html
new file mode 100644
index 00000000000..a0a8c6c52a1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/path-leading-colon-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: path-leading-colon-backslash</title>
+<video poster=":\"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/path-leading-colon-chars-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/path-leading-colon-chars-backslash-novalid.html
new file mode 100644
index 00000000000..5e63c1b4d6b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/path-leading-colon-chars-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: path-leading-colon-chars-backslash</title>
+<video poster=":foo.com\"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/path-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/path-leading-space-novalid.html
new file mode 100644
index 00000000000..e738c1feb17
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/path-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: path-leading-space</title>
+<video poster="http://f:21/ b"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/path-percent-encoded-malformed-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/path-percent-encoded-malformed-novalid.html
new file mode 100644
index 00000000000..1c211fd4ca8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/path-percent-encoded-malformed-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: path-percent-encoded-malformed</title>
+<video poster="http://example.com/foo/%2e%2"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/path-relative-square-brackets-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/path-relative-square-brackets-novalid.html
new file mode 100644
index 00000000000..786f91dac13
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/path-relative-square-brackets-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: path-relative-square-brackets</title>
+<video poster="[61:24:74]:98"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/path-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/path-tab-novalid.html
new file mode 100644
index 00000000000..bb9fc12b177
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/path-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: path-tab</title>
+<video poster="http://example.com/foo bar"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/path-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/path-trailing-space-novalid.html
new file mode 100644
index 00000000000..f66866c8fcb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/path-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: path-trailing-space</title>
+<video poster="http://f:21/b ?"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/path-u0091-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/path-u0091-novalid.html
new file mode 100644
index 00000000000..360426c3a93
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/path-u0091-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: path-u0091</title>
+<video poster="http://example.com/foo‘"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/port-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/port-cr-novalid.html
new file mode 100644
index 00000000000..28796729d7f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/port-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: port-cr</title>
+<video poster="http://f: /c"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/port-leading-colon-bracket-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/port-leading-colon-bracket-colon-novalid.html
new file mode 100644
index 00000000000..b5b6bef5c78
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/port-leading-colon-bracket-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: port-leading-colon-bracket-colon</title>
+<video poster="http://2001::1]:80"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/port-leading-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/port-leading-colon-novalid.html
new file mode 100644
index 00000000000..bd5c281016d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/port-leading-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: port-leading-colon</title>
+<video poster="http://2001::1"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/port-leading-dash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/port-leading-dash-novalid.html
new file mode 100644
index 00000000000..354fe3103d5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/port-leading-dash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: port-leading-dash</title>
+<video poster="http://foo:-80/"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/port-multiple-letters-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/port-multiple-letters-novalid.html
new file mode 100644
index 00000000000..04a2cf18e8b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/port-multiple-letters-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: port-multiple-letters</title>
+<video poster="http://f:fifty-two/c"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/port-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/port-newline-novalid.html
new file mode 100644
index 00000000000..1634a10e0b0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/port-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: port-newline</title>
+<video poster="http://f:
+/c"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/port-single-letter-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/port-single-letter-novalid.html
new file mode 100644
index 00000000000..8b95dcc647c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/port-single-letter-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: port-single-letter</title>
+<video poster="http://f:b/c"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/port-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/port-space-novalid.html
new file mode 100644
index 00000000000..6164a9206fd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/port-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: port-space</title>
+<video poster="http://f: /c"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/port-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/port-tab-novalid.html
new file mode 100644
index 00000000000..5dbbdd5b4f2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/port-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: port-tab</title>
+<video poster="http://f: /c"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/query-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/query-leading-space-novalid.html
new file mode 100644
index 00000000000..e465e950b85
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/query-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: query-leading-space</title>
+<video poster="http://f:21/b? d"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/query-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/query-trailing-space-novalid.html
new file mode 100644
index 00000000000..640e3997206
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/query-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: query-trailing-space</title>
+<video poster="http://f:21/b?d #"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-data-contains-fragment-haswarn.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-data-contains-fragment-haswarn.html
new file mode 100644
index 00000000000..4207e1babec
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-data-contains-fragment-haswarn.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>data:text/html,test#test warning: scheme-data-contains-fragment</title>
+<video poster="data:text/html,test#test"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-data-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-data-single-slash-novalid.html
new file mode 100644
index 00000000000..61a3376e105
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-data-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: scheme-data-single-slash</title>
+<video poster="data:/example.com/"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-file-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-file-backslash-novalid.html
new file mode 100644
index 00000000000..2d2a13b1a51
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-file-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: scheme-file-backslash</title>
+<video poster="file:c:\foo\bar.html"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-file-single-slash-c-bar-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-file-single-slash-c-bar-novalid.html
new file mode 100644
index 00000000000..f6b4897d971
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-file-single-slash-c-bar-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: scheme-file-single-slash-c-bar</title>
+<video poster="file:/C|/foo/bar"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-file-triple-slash-c-bar-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-file-triple-slash-c-bar-novalid.html
new file mode 100644
index 00000000000..40b21e03ac0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-file-triple-slash-c-bar-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: scheme-file-triple-slash-c-bar</title>
+<video poster="file:///C|/foo/bar"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-ftp-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-ftp-no-slash-novalid.html
new file mode 100644
index 00000000000..b06cd92de39
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-ftp-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: scheme-ftp-no-slash</title>
+<video poster="ftp:example.com/"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-ftp-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-ftp-single-slash-novalid.html
new file mode 100644
index 00000000000..2db8cbb1d39
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-ftp-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: scheme-ftp-single-slash</title>
+<video poster="ftp:/example.com/"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-http-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-http-backslash-novalid.html
new file mode 100644
index 00000000000..82223ebe182
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-http-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: scheme-http-backslash</title>
+<video poster="http:\\foo.com\"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-http-no-slash-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-http-no-slash-colon-novalid.html
new file mode 100644
index 00000000000..cb9cb519169
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-http-no-slash-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: scheme-http-no-slash-colon</title>
+<video poster="http::@c:29"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-http-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-http-no-slash-novalid.html
new file mode 100644
index 00000000000..a55b66b5a99
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-http-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: scheme-http-no-slash</title>
+<video poster="http:foo.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-http-no-slash-square-bracket-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-http-no-slash-square-bracket-novalid.html
new file mode 100644
index 00000000000..53028e1ea3a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-http-no-slash-square-bracket-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: scheme-http-no-slash-square-bracket</title>
+<video poster="http:[61:27]/:foo"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-http-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-http-single-slash-novalid.html
new file mode 100644
index 00000000000..e21f10cb92c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-http-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: scheme-http-single-slash</title>
+<video poster="http:/example.com/"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-https-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-https-no-slash-novalid.html
new file mode 100644
index 00000000000..103a89e3e2f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-https-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: scheme-https-no-slash</title>
+<video poster="https:example.com/"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-https-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-https-single-slash-novalid.html
new file mode 100644
index 00000000000..0c2002984dc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-https-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: scheme-https-single-slash</title>
+<video poster="https:/example.com/"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-javascript-no-slash-malformed-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-javascript-no-slash-malformed-novalid.html
new file mode 100644
index 00000000000..af5c83dd2d6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-javascript-no-slash-malformed-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: scheme-javascript-no-slash-malformed</title>
+<video poster="javascript:example.com/"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-trailing-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-trailing-cr-novalid.html
new file mode 100644
index 00000000000..7ab4fd95334
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-trailing-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: scheme-trailing-cr</title>
+<video poster="a: foo.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-trailing-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-trailing-newline-novalid.html
new file mode 100644
index 00000000000..e411aa29561
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-trailing-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: scheme-trailing-newline</title>
+<video poster="a:
+foo.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-trailing-space-novalid.html
new file mode 100644
index 00000000000..8018630da5e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: scheme-trailing-space</title>
+<video poster="a: foo.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-trailing-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-trailing-tab-novalid.html
new file mode 100644
index 00000000000..176164f8f91
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/scheme-trailing-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: scheme-trailing-tab</title>
+<video poster="a: foo.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/userinfo-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/userinfo-backslash-novalid.html
new file mode 100644
index 00000000000..5842693077f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/userinfo-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: userinfo-backslash</title>
+<video poster="http://a\b:c\d@foo.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/userinfo-password-bad-chars-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/userinfo-password-bad-chars-novalid.html
new file mode 100644
index 00000000000..a4afc95e894
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/userinfo-password-bad-chars-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: userinfo-password-bad-chars</title>
+<video poster="http://&a:foo(b]c@d:2/"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/userinfo-password-contains-pile-of-poo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/userinfo-password-contains-pile-of-poo-novalid.html
new file mode 100644
index 00000000000..4948ef6dad0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/userinfo-password-contains-pile-of-poo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: userinfo-password-contains-pile-of-poo</title>
+<video poster="http://foo:💩@example.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/userinfo-username-contains-at-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/userinfo-username-contains-at-sign-novalid.html
new file mode 100644
index 00000000000..c0527bc19a5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/userinfo-username-contains-at-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: userinfo-username-contains-at-sign</title>
+<video poster="http://::@c@d:2"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/userinfo-username-contains-pile-of-poo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/userinfo-username-contains-pile-of-poo-novalid.html
new file mode 100644
index 00000000000..0275ab7e670
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/poster/userinfo-username-contains-pile-of-poo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid poster: userinfo-username-contains-pile-of-poo</title>
+<video poster="http://💩:foo@example.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src-isvalid.html
new file mode 100644
index 00000000000..d7a85fe4587
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src-isvalid.html
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid src</title>
+<video src="file:///"></video><!-- scheme-file-slash-slash-slash-only -->
+<video src="http://a:@www.example.com"></video><!-- userinfo-password-empty -->
+<video src="foo://///////"></video><!-- scheme-private-path-leading-slashes-only -->
+<video src="file://abc|/foo/bar"></video><!-- scheme-file-slash-slash-abc-bar -->
+<video src="/a/b/c"></video><!-- path-simple-relative -->
+<video src="http://example.com/你好你好"></video><!-- path-unicode-han -->
+<video src="/a/%2f/c"></video><!-- path-percent-encoded-slash-plus-slashes-relative -->
+<video src="http://f:/c"></video><!-- port-none-but-colon -->
+<video src="http://example.com/foo%41%7a"></video><!-- path-percent-encoded-multiple -->
+<video src="http://192.168.0.257/"></video><!-- host-IP-address-broken -->
+<video src="madeupscheme:example.com/"></video><!-- scheme-private-no-slash -->
+<video src="?"></video><!-- query-empty-no-path-relative -->
+<video src="http://example.com/%20foo"></video><!-- path-percent-encoded-space -->
+<video src="mailto:/example.com/"></video><!-- scheme-mailto-single-slash -->
+<video src="::"></video><!-- path-leading-colon-colon-relative -->
+<video src="http://example.com/%3A%3a%3C%3c"></video><!-- path-percent-encoded-mixed-case -->
+<video src="http://user:pass@foo:21/bar;par?b#c"></video><!-- userinfo -->
+<video src="ws:/example.com/"></video><!-- scheme-ws-single-slash -->
+<video src="foo://"></video><!-- scheme-private-slash-slash -->
+<video src="#"></video><!-- fragment-empty-hash-only-no-path-relative -->
+<video src="http://f:00000000000000/c"></video><!-- port-00000000000000 -->
+<video src="foo:////://///"></video><!-- scheme-private-path-leading-slashes-colon-slashes -->
+<video src=":23"></video><!-- path-leading-colon-number-relative -->
+<video src="foo:/"></video><!-- scheme-private-slash -->
+<video src="http://💩"></video><!-- host-is-pile-of-poo -->
+<video src="file:test"></video><!-- scheme-file-no-slash -->
+<video src="file://C|/foo/bar"></video><!-- scheme-file-slash-slash-c-bar -->
+<video src="#/"></video><!-- fragment-slash-relative -->
+<video src="http://192.0x00A80001"></video><!-- host-192.0x00A80001 -->
+<video src="foo.com"></video><!-- scheme-none-relative -->
+<video src="http💩//:foo"></video><!-- path-contains-pile-of-poo -->
+<video src="File://foo/bar.html"></video><!-- scheme-file-uppercase -->
+<video src=":/"></video><!-- path-leading-colon-slash-relative -->
+<video src="http://www.foo。bar.com"></video><!-- host-exotic-dot -->
+<video src="http://GOO​⁠goo.com"></video><!-- host-exotic-whitespace -->
+<video src="file:///foo/bar.txt"></video><!-- scheme-file-host-empty -->
+<video src="javascript:/example.com/"></video><!-- scheme-javascript-single-slash -->
+<video src="gopher:/example.com/"></video><!-- scheme-gopher-single-slash -->
+<video src="ftps:example.com/"></video><!-- scheme-ftps-no-slash -->
+<video src="file://server/foo/bar"></video><!-- scheme-file-host-included -->
+<video src="http://example.com/foo%00"></video><!-- path-percent-encoded-u0000 -->
+<video src="a:foo.com"></video><!-- scheme-private -->
+<video src=":"></video><!-- path-colon-relative -->
+<video src="http://:b@www.example.com"></video><!-- userinfo-user-empty -->
+<video src="file:/"></video><!-- scheme-file-slash-only -->
+<video src="wss:example.com/"></video><!-- scheme-wss-no-slash -->
+<video src="::23"></video><!-- path-colon-colon-number-relative -->
+<video src="/a%2fc"></video><!-- path-percent-encoded-slash-relative -->
+<video src="http://a:b@c:29/d"></video><!-- userinfo-host-port-path -->
+<video src="gopher:example.com/"></video><!-- scheme-gopher-no-slash -->
+<video src="madeupscheme:/example.com/"></video><!-- scheme-private-single-slash -->
+<video src="mailto:example.com/"></video><!-- scheme-mailto-no-slash -->
+<video src="http://%25DOMAIN:foobar@foodomain.com"></video><!-- userinfo-username-contains-percent-encoded -->
+<video src="/:23"></video><!-- path-slash-colon-number-relative -->
+<video src="foo://///////bar.com/"></video><!-- scheme-private-path-leading-slashes-chars -->
+<video src="http://[2001::1]:80"></video><!-- host-ipv6-port -->
+<video src="data:text/plain,foo"></video><!-- scheme-data-no-slash -->
+<video src="http://example.com/foo/%2e"></video><!-- path-percent-encoded-dot -->
+<video src="file:/example.com/"></video><!-- scheme-file-single-slash -->
+<video src="http://example.com/©zbar"></video><!-- path-non-ascii -->
+<video src="http://example.com//foo"></video><!-- path-uFEFF -->
+<video src="wss:/example.com/"></video><!-- scheme-wss-single-slash -->
+<video src="http://foo/abcd#foo?bar"></video><!-- fragment-contains-question-mark -->
+<video src=":#"></video><!-- path-leading-colon-hash-relative -->
+<video src="http://example.com/foo%91"></video><!-- path-percent-encoded-u0091 -->
+<video src="c:/foo"></video><!-- scheme-private-single-letter -->
+<video src=":foo.com"></video><!-- path-leading-colon-chars-relative -->
+<video src="http://你好你好"></video><!-- host-idn-unicode-han -->
+<video src="http://example.com/foo#💩"></video><!-- fragment-contains-pile-of-poo -->
+<video src="file:"></video><!-- scheme-file-scheme-only -->
+<video src="#β"></video><!-- fragment-non-ascii-relative -->
+<video src="foo:/bar.com/"></video><!-- scheme-private-path -->
+<video src="http://f:0/c"></video><!-- port-0 -->
+<video src="#;?"></video><!-- fragment-semicolon-question-mark-relative -->
+<video src="http://Go.com"></video><!-- host-fullwidth -->
+<video src="http://@www.example.com"></video><!-- userinfo-empty -->
+<video src="http://example.com/‮/foo/‭/bar"></video><!-- path-u202E-u202D -->
+<video src="http://[2001::1]"></video><!-- host-ipv6 -->
+<video src="💩http://foo"></video><!-- path-starts-with-pile-of-poo -->
+<video src="http://foo/abcd?efgh?ijkl"></video><!-- query-contains-question-mark -->
+<video src="//foo/bar"></video><!-- scheme-schemeless-relative -->
+<video src="ftps:/example.com/"></video><!-- scheme-ftps-single-slash -->
+<video src="http://foo.com:b@d/"></video><!-- userinfo-username-non-alpha -->
+<video src=":a"></video><!-- path-leading-colon-letter-relative -->
+<video src="/"></video><!-- path-slash-only-relative -->
+<video src="http://example.com/foo?💩"></video><!-- query-contains-pile-of-poo -->
+<video src="http://f:00000000000000000000080/c"></video><!-- port-00000000000000000000080 -->
+<video src="file://"></video><!-- scheme-file-slash-slash-only -->
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/fragment-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/fragment-backslash-novalid.html
new file mode 100644
index 00000000000..ee68bff3d91
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/fragment-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: fragment-backslash</title>
+<video src="#\"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/fragment-contains-hash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/fragment-contains-hash-novalid.html
new file mode 100644
index 00000000000..b9d870a9ead
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/fragment-contains-hash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: fragment-contains-hash</title>
+<video src="http://foo/path#f#g"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/fragment-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/fragment-leading-space-novalid.html
new file mode 100644
index 00000000000..4b155216032
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/fragment-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: fragment-leading-space</title>
+<video src="http://f:21/b# e"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-cr-novalid.html
new file mode 100644
index 00000000000..961ef7768d2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-cr</title>
+<video src="http://example. org"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-double-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-double-percent-encoded-novalid.html
new file mode 100644
index 00000000000..920ee8a5464
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-double-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-double-percent-encoded</title>
+<video src="http://%41.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-double-percent-encoded-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-double-percent-encoded-percent-encoded-novalid.html
new file mode 100644
index 00000000000..4134e80de8b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-double-percent-encoded-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-double-percent-encoded-percent-encoded</title>
+<video src="http://%ef%bc%85%ef%bc%94%ef%bc%91.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-empty-novalid.html
new file mode 100644
index 00000000000..816c3742d2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-empty</title>
+<video src="http://"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-empty-userinfo-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-empty-userinfo-empty-novalid.html
new file mode 100644
index 00000000000..34f65d1a845
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-empty-userinfo-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-empty-userinfo-empty</title>
+<video src="http://@/www.example.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-empty-with-userinfo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-empty-with-userinfo-novalid.html
new file mode 100644
index 00000000000..95dfb6f5b2e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-empty-with-userinfo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-empty-with-userinfo</title>
+<video src="http://user:pass@/"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-hostname-in-brackets-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-hostname-in-brackets-novalid.html
new file mode 100644
index 00000000000..0768743f4e9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-hostname-in-brackets-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-hostname-in-brackets</title>
+<video src="http://[www.google.com]/"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-invalid-unicode-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-invalid-unicode-novalid.html
new file mode 100644
index 00000000000..9508562d7ba
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-invalid-unicode-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-invalid-unicode</title>
+<video src="http://﷐zyx.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-invalid-unicode-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-invalid-unicode-percent-encoded-novalid.html
new file mode 100644
index 00000000000..b29836ab97c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-invalid-unicode-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-invalid-unicode-percent-encoded</title>
+<video src="http://%ef%b7%90zyx.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-newline-novalid.html
new file mode 100644
index 00000000000..41537aeaca6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-newline</title>
+<video src="http://example.
+org"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-space-novalid.html
new file mode 100644
index 00000000000..f480f32c5c4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-space</title>
+<video src="http://example .org"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-square-brackets-port-contains-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-square-brackets-port-contains-colon-novalid.html
new file mode 100644
index 00000000000..447a2aa614d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-square-brackets-port-contains-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-square-brackets-port-contains-colon</title>
+<video src="http://[1::2]:3:4"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-tab-novalid.html
new file mode 100644
index 00000000000..4076b232c77
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-tab</title>
+<video src="http://example .org"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-u0000-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-u0000-percent-encoded-novalid.html
new file mode 100644
index 00000000000..549297e1895
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-u0000-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-u0000-percent-encoded</title>
+<video src="http://%00.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-u0000-percent-encoded-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-u0000-percent-encoded-percent-encoded-novalid.html
new file mode 100644
index 00000000000..8041f2d7812
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/host-u0000-percent-encoded-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: host-u0000-percent-encoded-percent-encoded</title>
+<video src="http://%ef%bc%85%ef%bc%90%ef%bc%90.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/path-bare-percent-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/path-bare-percent-sign-novalid.html
new file mode 100644
index 00000000000..d9c3ee5718c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/path-bare-percent-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-bare-percent-sign</title>
+<video src="http://example.com/foo%"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/path-contains-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/path-contains-space-novalid.html
new file mode 100644
index 00000000000..9d5e0c7994b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/path-contains-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-contains-space</title>
+<video src="/a/ /c"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/path-leading-backslash-at-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/path-leading-backslash-at-sign-novalid.html
new file mode 100644
index 00000000000..99bea08254a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/path-leading-backslash-at-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-leading-backslash-at-sign</title>
+<video src="http://foo.com/\@"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/path-leading-colon-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/path-leading-colon-backslash-novalid.html
new file mode 100644
index 00000000000..a6c02e7d68a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/path-leading-colon-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-leading-colon-backslash</title>
+<video src=":\"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/path-leading-colon-chars-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/path-leading-colon-chars-backslash-novalid.html
new file mode 100644
index 00000000000..d16c250a86e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/path-leading-colon-chars-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-leading-colon-chars-backslash</title>
+<video src=":foo.com\"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/path-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/path-leading-space-novalid.html
new file mode 100644
index 00000000000..72d3eb00fb4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/path-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-leading-space</title>
+<video src="http://f:21/ b"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/path-percent-encoded-malformed-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/path-percent-encoded-malformed-novalid.html
new file mode 100644
index 00000000000..d4a76d67ff2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/path-percent-encoded-malformed-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-percent-encoded-malformed</title>
+<video src="http://example.com/foo/%2e%2"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/path-relative-square-brackets-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/path-relative-square-brackets-novalid.html
new file mode 100644
index 00000000000..70e5f34d69b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/path-relative-square-brackets-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-relative-square-brackets</title>
+<video src="[61:24:74]:98"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/path-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/path-tab-novalid.html
new file mode 100644
index 00000000000..9600b35c9bb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/path-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-tab</title>
+<video src="http://example.com/foo bar"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/path-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/path-trailing-space-novalid.html
new file mode 100644
index 00000000000..8d778ed2127
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/path-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-trailing-space</title>
+<video src="http://f:21/b ?"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/path-u0091-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/path-u0091-novalid.html
new file mode 100644
index 00000000000..3a8729e2e68
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/path-u0091-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: path-u0091</title>
+<video src="http://example.com/foo‘"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/port-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/port-cr-novalid.html
new file mode 100644
index 00000000000..c2ccfb09605
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/port-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-cr</title>
+<video src="http://f: /c"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/port-leading-colon-bracket-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/port-leading-colon-bracket-colon-novalid.html
new file mode 100644
index 00000000000..e5fb232d4a3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/port-leading-colon-bracket-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-leading-colon-bracket-colon</title>
+<video src="http://2001::1]:80"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/port-leading-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/port-leading-colon-novalid.html
new file mode 100644
index 00000000000..96e191517dc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/port-leading-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-leading-colon</title>
+<video src="http://2001::1"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/port-leading-dash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/port-leading-dash-novalid.html
new file mode 100644
index 00000000000..fe6f633d4a5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/port-leading-dash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-leading-dash</title>
+<video src="http://foo:-80/"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/port-multiple-letters-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/port-multiple-letters-novalid.html
new file mode 100644
index 00000000000..3adbe71514d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/port-multiple-letters-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-multiple-letters</title>
+<video src="http://f:fifty-two/c"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/port-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/port-newline-novalid.html
new file mode 100644
index 00000000000..8537b673798
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/port-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-newline</title>
+<video src="http://f:
+/c"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/port-single-letter-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/port-single-letter-novalid.html
new file mode 100644
index 00000000000..e26c266056c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/port-single-letter-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-single-letter</title>
+<video src="http://f:b/c"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/port-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/port-space-novalid.html
new file mode 100644
index 00000000000..a64478c873b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/port-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-space</title>
+<video src="http://f: /c"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/port-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/port-tab-novalid.html
new file mode 100644
index 00000000000..06a2197333b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/port-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: port-tab</title>
+<video src="http://f: /c"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/query-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/query-leading-space-novalid.html
new file mode 100644
index 00000000000..7fadece7cbf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/query-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: query-leading-space</title>
+<video src="http://f:21/b? d"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/query-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/query-trailing-space-novalid.html
new file mode 100644
index 00000000000..c63758bf849
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/query-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: query-trailing-space</title>
+<video src="http://f:21/b?d #"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-data-contains-fragment-haswarn.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-data-contains-fragment-haswarn.html
new file mode 100644
index 00000000000..b0e34b8fcc5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-data-contains-fragment-haswarn.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>data:text/html,test#test warning: scheme-data-contains-fragment</title>
+<video src="data:text/html,test#test"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-data-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-data-single-slash-novalid.html
new file mode 100644
index 00000000000..8d8dae71252
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-data-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-data-single-slash</title>
+<video src="data:/example.com/"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-file-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-file-backslash-novalid.html
new file mode 100644
index 00000000000..e8901f2c76b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-file-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-file-backslash</title>
+<video src="file:c:\foo\bar.html"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-file-single-slash-c-bar-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-file-single-slash-c-bar-novalid.html
new file mode 100644
index 00000000000..4b0da950953
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-file-single-slash-c-bar-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-file-single-slash-c-bar</title>
+<video src="file:/C|/foo/bar"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-file-triple-slash-c-bar-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-file-triple-slash-c-bar-novalid.html
new file mode 100644
index 00000000000..24955ef06fd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-file-triple-slash-c-bar-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-file-triple-slash-c-bar</title>
+<video src="file:///C|/foo/bar"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-ftp-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-ftp-no-slash-novalid.html
new file mode 100644
index 00000000000..5667bea15a5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-ftp-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-ftp-no-slash</title>
+<video src="ftp:example.com/"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-ftp-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-ftp-single-slash-novalid.html
new file mode 100644
index 00000000000..e9dcf201b66
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-ftp-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-ftp-single-slash</title>
+<video src="ftp:/example.com/"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-http-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-http-backslash-novalid.html
new file mode 100644
index 00000000000..6809d90d1b4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-http-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-http-backslash</title>
+<video src="http:\\foo.com\"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-http-no-slash-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-http-no-slash-colon-novalid.html
new file mode 100644
index 00000000000..e519b030b8a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-http-no-slash-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-http-no-slash-colon</title>
+<video src="http::@c:29"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-http-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-http-no-slash-novalid.html
new file mode 100644
index 00000000000..4b8d3177751
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-http-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-http-no-slash</title>
+<video src="http:foo.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-http-no-slash-square-bracket-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-http-no-slash-square-bracket-novalid.html
new file mode 100644
index 00000000000..7251562c463
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-http-no-slash-square-bracket-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-http-no-slash-square-bracket</title>
+<video src="http:[61:27]/:foo"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-http-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-http-single-slash-novalid.html
new file mode 100644
index 00000000000..33f3518fcde
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-http-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-http-single-slash</title>
+<video src="http:/example.com/"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-https-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-https-no-slash-novalid.html
new file mode 100644
index 00000000000..c80331a6e71
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-https-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-https-no-slash</title>
+<video src="https:example.com/"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-https-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-https-single-slash-novalid.html
new file mode 100644
index 00000000000..876011ec09b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-https-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-https-single-slash</title>
+<video src="https:/example.com/"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-javascript-no-slash-malformed-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-javascript-no-slash-malformed-novalid.html
new file mode 100644
index 00000000000..adc7a878982
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-javascript-no-slash-malformed-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-javascript-no-slash-malformed</title>
+<video src="javascript:example.com/"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-trailing-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-trailing-cr-novalid.html
new file mode 100644
index 00000000000..bb0a0de9001
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-trailing-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-trailing-cr</title>
+<video src="a: foo.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-trailing-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-trailing-newline-novalid.html
new file mode 100644
index 00000000000..01bb310f918
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-trailing-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-trailing-newline</title>
+<video src="a:
+foo.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-trailing-space-novalid.html
new file mode 100644
index 00000000000..6149a4df2ba
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-trailing-space</title>
+<video src="a: foo.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-trailing-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-trailing-tab-novalid.html
new file mode 100644
index 00000000000..4285fea135d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/scheme-trailing-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: scheme-trailing-tab</title>
+<video src="a: foo.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/userinfo-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/userinfo-backslash-novalid.html
new file mode 100644
index 00000000000..c18402881c6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/userinfo-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: userinfo-backslash</title>
+<video src="http://a\b:c\d@foo.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/userinfo-password-bad-chars-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/userinfo-password-bad-chars-novalid.html
new file mode 100644
index 00000000000..0f34b9ec295
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/userinfo-password-bad-chars-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: userinfo-password-bad-chars</title>
+<video src="http://&a:foo(b]c@d:2/"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/userinfo-password-contains-pile-of-poo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/userinfo-password-contains-pile-of-poo-novalid.html
new file mode 100644
index 00000000000..971c1f0eba6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/userinfo-password-contains-pile-of-poo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: userinfo-password-contains-pile-of-poo</title>
+<video src="http://foo:💩@example.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/userinfo-username-contains-at-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/userinfo-username-contains-at-sign-novalid.html
new file mode 100644
index 00000000000..a3d5736d1e2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/userinfo-username-contains-at-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: userinfo-username-contains-at-sign</title>
+<video src="http://::@c@d:2"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/userinfo-username-contains-pile-of-poo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/userinfo-username-contains-pile-of-poo-novalid.html
new file mode 100644
index 00000000000..d3cc8e1abb0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/elements/video/src/userinfo-username-contains-pile-of-poo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid src: userinfo-username-contains-pile-of-poo</title>
+<video src="http://💩:foo@example.com"></video>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/001-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/001-isvalid.html
new file mode 100644
index 00000000000..445394dde97
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/001-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>screen</title>
+<link href='foo' media='screen' rel='stylesheet'>
+</head>
+<body>
+<p>screen</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/001-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/001-novalid.html
new file mode 100644
index 00000000000..d1117760404
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/001-novalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>screen and</title>
+<link href='foo' media='screen and' rel='stylesheet'>
+</head>
+<body>
+<p>screen and</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/002-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/002-isvalid.html
new file mode 100644
index 00000000000..8820d56547d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/002-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title> screen</title>
+<link href='foo' media=' screen' rel='stylesheet'>
+</head>
+<body>
+<p> screen</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/002-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/002-novalid.html
new file mode 100644
index 00000000000..819d4622fbd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/002-novalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>alla</title>
+<link href='foo' media='alla' rel='stylesheet'>
+</head>
+<body>
+<p>alla</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/003-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/003-isvalid.html
new file mode 100644
index 00000000000..220eb820bf3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/003-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>all</title>
+<link href='foo' media='all' rel='stylesheet'>
+</head>
+<body>
+<p>all</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/003-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/003-novalid.html
new file mode 100644
index 00000000000..81a7db013d9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/003-novalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>PROJECTİON</title>
+<link href='foo' media='PROJECTİON' rel='stylesheet'>
+</head>
+<body>
+<p>PROJECTİON</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/004-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/004-isvalid.html
new file mode 100644
index 00000000000..6e362710d9b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/004-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>projection</title>
+<link href='foo' media='projection' rel='stylesheet'>
+</head>
+<body>
+<p>projection</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/004-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/004-novalid.html
new file mode 100644
index 00000000000..d30fc2055f4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/004-novalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>notscreen</title>
+<link href='foo' media='notscreen' rel='stylesheet'>
+</head>
+<body>
+<p>notscreen</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/005-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/005-isvalid.html
new file mode 100644
index 00000000000..cfcf027d0d1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/005-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>not screen</title>
+<link href='foo' media='not screen' rel='stylesheet'>
+</head>
+<body>
+<p>not screen</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/005-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/005-novalid.html
new file mode 100644
index 00000000000..f7bb8529386
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/005-novalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>onlyscreen</title>
+<link href='foo' media='onlyscreen' rel='stylesheet'>
+</head>
+<body>
+<p>onlyscreen</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/006-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/006-isvalid.html
new file mode 100644
index 00000000000..7a24e16a1b6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/006-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>only screen</title>
+<link href='foo' media='only screen' rel='stylesheet'>
+</head>
+<body>
+<p>only screen</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/006-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/006-novalid.html
new file mode 100644
index 00000000000..5315c8afe71
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/006-novalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>screenand (min-width: 400px)</title>
+<link href='foo' media='screenand (min-width: 400px)' rel='stylesheet'>
+</head>
+<body>
+<p>screenand (min-width: 400px)</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/007-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/007-isvalid.html
new file mode 100644
index 00000000000..59c4a8409ce
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/007-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>screen and (min-width: 400px)</title>
+<link href='foo' media='screen and (min-width: 400px)' rel='stylesheet'>
+</head>
+<body>
+<p>screen and (min-width: 400px)</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/007-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/007-novalid.html
new file mode 100644
index 00000000000..122d5ce778a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/007-novalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>screen and(min-width: 400px)</title>
+<link href='foo' media='screen and(min-width: 400px)' rel='stylesheet'>
+</head>
+<body>
+<p>screen and(min-width: 400px)</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/008-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/008-isvalid.html
new file mode 100644
index 00000000000..544bcbeef0f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/008-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>screen and (min-width:400px)</title>
+<link href='foo' media='screen and (min-width:400px)' rel='stylesheet'>
+</head>
+<body>
+<p>screen and (min-width:400px)</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/008-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/008-novalid.html
new file mode 100644
index 00000000000..4531534948e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/008-novalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>screen and (min-width: 400px;)</title>
+<link href='foo' media='screen and (min-width: 400px;)' rel='stylesheet'>
+</head>
+<body>
+<p>screen and (min-width: 400px;)</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/009-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/009-isvalid.html
new file mode 100644
index 00000000000..cee1a4aba1b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/009-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>screen and ( min-width: 400px )</title>
+<link href='foo' media='screen and ( min-width: 400px )' rel='stylesheet'>
+</head>
+<body>
+<p>screen and ( min-width: 400px )</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/009-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/009-novalid.html
new file mode 100644
index 00000000000..d44dbfa4023
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/009-novalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>screen and (min-width: 400uu)</title>
+<link href='foo' media='screen and (min-width: 400uu)' rel='stylesheet'>
+</head>
+<body>
+<p>screen and (min-width: 400uu)</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/010-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/010-isvalid.html
new file mode 100644
index 00000000000..43584464f7e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/010-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>screen and ( min-width : 400px )</title>
+<link href='foo' media='screen and ( min-width : 400px )' rel='stylesheet'>
+</head>
+<body>
+<p>screen and ( min-width : 400px )</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/010-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/010-novalid.html
new file mode 100644
index 00000000000..a016cd99c85
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/010-novalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>screen and (min-width: 400)</title>
+<link href='foo' media='screen and (min-width: 400)' rel='stylesheet'>
+</head>
+<body>
+<p>screen and (min-width: 400)</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/011-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/011-isvalid.html
new file mode 100644
index 00000000000..335e0e6fdd1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/011-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>screen and (min-width: 400px)</title>
+<link href='foo' media='screen and (min-width: 400px)' rel='stylesheet'>
+</head>
+<body>
+<p>screen and (min-width: 400px)</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/011-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/011-novalid.html
new file mode 100644
index 00000000000..cb9d5ab706a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/011-novalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>screen and (min-width: 400dpi)</title>
+<link href='foo' media='screen and (min-width: 400dpi)' rel='stylesheet'>
+</head>
+<body>
+<p>screen and (min-width: 400dpi)</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/012-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/012-isvalid.html
new file mode 100644
index 00000000000..4de7b828bdb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/012-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>screen and ( min-width: 400px)</title>
+<link href='foo' media='screen and ( min-width: 400px)' rel='stylesheet'>
+</head>
+<body>
+<p>screen and ( min-width: 400px)</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/012-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/012-novalid.html
new file mode 100644
index 00000000000..6395788af4f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/012-novalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>screen and (min-width: 400px)and (max-width: 600px)</title>
+<link href='foo' media='screen and (min-width: 400px)and (max-width: 600px)' rel='stylesheet'>
+</head>
+<body>
+<p>screen and (min-width: 400px)and (max-width: 600px)</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/013-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/013-isvalid.html
new file mode 100644
index 00000000000..3f138bfb2b0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/013-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>screen and (min-width: 400px )</title>
+<link href='foo' media='screen and (min-width: 400px )' rel='stylesheet'>
+</head>
+<body>
+<p>screen and (min-width: 400px )</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/013-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/013-novalid.html
new file mode 100644
index 00000000000..f8b1a9873ff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/013-novalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>screen and (min-width:</title>
+<link href='foo' media='screen and (min-width:' rel='stylesheet'>
+</head>
+<body>
+<p>screen and (min-width:</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/014-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/014-isvalid.html
new file mode 100644
index 00000000000..6f013397175
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/014-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>screen and (min-width: 400px)</title>
+<link href='foo' media='screen and (min-width: 400px)' rel='stylesheet'>
+</head>
+<body>
+<p>screen and (min-width: 400px)</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/014-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/014-novalid.html
new file mode 100644
index 00000000000..6d1cfdbf60e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/014-novalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>screen and (min-width: 400px) and</title>
+<link href='foo' media='screen and (min-width: 400px) and' rel='stylesheet'>
+</head>
+<body>
+<p>screen and (min-width: 400px) and</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/015-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/015-isvalid.html
new file mode 100644
index 00000000000..598bb944350
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/015-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>screen and (min-width: 400px)</title>
+<link href='foo' media='screen and (min-width: 400px)' rel='stylesheet'>
+</head>
+<body>
+<p>screen and (min-width: 400px)</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/015-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/015-novalid.html
new file mode 100644
index 00000000000..3f896f06171
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/015-novalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>tv and (scan: 1)</title>
+<link href='foo' media='tv and (scan: 1)' rel='stylesheet'>
+</head>
+<body>
+<p>tv and (scan: 1)</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/016-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/016-isvalid.html
new file mode 100644
index 00000000000..6f013397175
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/016-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>screen and (min-width: 400px)</title>
+<link href='foo' media='screen and (min-width: 400px)' rel='stylesheet'>
+</head>
+<body>
+<p>screen and (min-width: 400px)</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/016-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/016-novalid.html
new file mode 100644
index 00000000000..8f7a3f003f2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/016-novalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>tv and (scan: İNTERLACE)</title>
+<link href='foo' media='tv and (scan: İNTERLACE)' rel='stylesheet'>
+</head>
+<body>
+<p>tv and (scan: İNTERLACE)</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/017-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/017-isvalid.html
new file mode 100644
index 00000000000..2b9ebfdce13
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/017-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>screen and (min-width: 400px)</title>
+<link href='foo' media='screen and (min-width: 400px)' rel='stylesheet'>
+</head>
+<body>
+<p>screen and (min-width: 400px)</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/017-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/017-novalid.html
new file mode 100644
index 00000000000..b8340dd9829
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/017-novalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>screen and (device-aspect-ratio: 16px/9pt)</title>
+<link href='foo' media='screen and (device-aspect-ratio: 16px/9pt)' rel='stylesheet'>
+</head>
+<body>
+<p>screen and (device-aspect-ratio: 16px/9pt)</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/018-haswarn.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/018-haswarn.html
new file mode 100644
index 00000000000..2b9b1cde9ec
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/018-haswarn.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Check that device-aspect-ratio warns about U+000C before/after slash in value</title>
+<link href='foo' media='screen and (device-aspect-ratio: 16 / 9)' rel='stylesheet'><!-- U+000C before & after slash -->
+</head>
+<body>
+<p>screen and (device-aspect-ratio: 16 / 9)</p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/018-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/018-isvalid.html
new file mode 100644
index 00000000000..08d398a89b7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/018-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>screen and (min-width: 400px) and (max-width: 600px)</title>
+<link href='foo' media='screen and (min-width: 400px) and (max-width: 600px)' rel='stylesheet'>
+</head>
+<body>
+<p>screen and (min-width: 400px) and (max-width: 600px)</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/019-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/019-isvalid.html
new file mode 100644
index 00000000000..8fa020aa5fb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/019-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>screen and (min-width: 400px) and (max-width: 600px)</title>
+<link href='foo' media='screen and (min-width: 400px) and (max-width: 600px)' rel='stylesheet'>
+</head>
+<body>
+<p>screen and (min-width: 400px) and (max-width: 600px)</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/019-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/019-novalid.html
new file mode 100644
index 00000000000..16a06b68a77
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/019-novalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>screen and (color: 1em)</title>
+<link href='foo' media='screen and (color: 1em)' rel='stylesheet'>
+</head>
+<body>
+<p>screen and (color: 1em)</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/020-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/020-isvalid.html
new file mode 100644
index 00000000000..0a140e9bfdf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/020-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>screen and (min-width: 400px) and (max-width: 600px)</title>
+<link href='foo' media='screen and (min-width: 400px) and (max-width: 600px)' rel='stylesheet'>
+</head>
+<body>
+<p>screen and (min-width: 400px) and (max-width: 600px)</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/020-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/020-novalid.html
new file mode 100644
index 00000000000..d7aada42f9f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/020-novalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>,</title>
+<link href='foo' media=',' rel='stylesheet'>
+</head>
+<body>
+<p>,</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/021-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/021-isvalid.html
new file mode 100644
index 00000000000..6fc7cfcf02a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/021-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>tv and (scan: progressive)</title>
+<link href='foo' media='tv and (scan: progressive)' rel='stylesheet'>
+</head>
+<body>
+<p>tv and (scan: progressive)</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/021-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/021-novalid.html
new file mode 100644
index 00000000000..7b62b984372
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/021-novalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>screen,,print</title>
+<link href='foo' media='screen,,print' rel='stylesheet'>
+</head>
+<body>
+<p>screen,,print</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/022-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/022-isvalid.html
new file mode 100644
index 00000000000..0481671ada4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/022-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>tv and (scan: interlace)</title>
+<link href='foo' media='tv and (scan: interlace)' rel='stylesheet'>
+</head>
+<body>
+<p>tv and (scan: interlace)</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/022-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/022-novalid.html
new file mode 100644
index 00000000000..92f7c609a85
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/022-novalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>screen,</title>
+<link href='foo' media='screen,' rel='stylesheet'>
+</head>
+<body>
+<p>screen,</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/023-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/023-isvalid.html
new file mode 100644
index 00000000000..2b851935908
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/023-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>screen and (device-aspect-ratio: 16/9)</title>
+<link href='foo' media='screen and (device-aspect-ratio: 16/9)' rel='stylesheet'>
+</head>
+<body>
+<p>screen and (device-aspect-ratio: 16/9)</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/023-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/023-novalid.html
new file mode 100644
index 00000000000..55ac1c007dc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/023-novalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>,screen</title>
+<link href='foo' media=',screen' rel='stylesheet'>
+</head>
+<body>
+<p>,screen</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/024-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/024-novalid.html
new file mode 100644
index 00000000000..a016cd99c85
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/024-novalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>screen and (min-width: 400)</title>
+<link href='foo' media='screen and (min-width: 400)' rel='stylesheet'>
+</head>
+<body>
+<p>screen and (min-width: 400)</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/025-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/025-isvalid.html
new file mode 100644
index 00000000000..cf0079302c3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/025-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>screen and (color: 1)</title>
+<link href='foo' media='screen and (color: 1)' rel='stylesheet'>
+</head>
+<body>
+<p>screen and (color: 1)</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/026-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/026-isvalid.html
new file mode 100644
index 00000000000..ef8523b8c4a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/026-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>screen and (color: 2)</title>
+<link href='foo' media='screen and (color: 2)' rel='stylesheet'>
+</head>
+<body>
+<p>screen and (color: 2)</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/027-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/027-isvalid.html
new file mode 100644
index 00000000000..99799c77dae
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/027-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>screen and (color: 0)</title>
+<link href='foo' media='screen and (color: 0)' rel='stylesheet'>
+</head>
+<body>
+<p>screen and (color: 0)</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/028-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/028-isvalid.html
new file mode 100644
index 00000000000..61d5b2f68ef
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/028-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>print and (min-resolution: 100dpi)</title>
+<link href='foo' media='print and (min-resolution: 100dpi)' rel='stylesheet'>
+</head>
+<body>
+<p>print and (min-resolution: 100dpi)</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/029-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/029-isvalid.html
new file mode 100644
index 00000000000..a3f8cecfc9a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/029-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>screen and (min-width: 400px), print</title>
+<link href='foo' media='screen and (min-width: 400px), print' rel='stylesheet'>
+</head>
+<body>
+<p>screen and (min-width: 400px), print</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/030-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/030-isvalid.html
new file mode 100644
index 00000000000..c6d20c62cdb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/030-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>screen and (min-width: 0)</title>
+<link href='foo' media='screen and (min-width: 0)' rel='stylesheet'>
+</head>
+<body>
+<p>screen and (min-width: 0)</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/031-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/031-isvalid.html
new file mode 100644
index 00000000000..944fadb4e70
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/031-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>screen and (min-width: 0.0)</title>
+<link href='foo' media='screen and (min-width: 0.0)' rel='stylesheet'>
+</head>
+<body>
+<p>screen and (min-width: 0.0)</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/032-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/032-isvalid.html
new file mode 100644
index 00000000000..7c60e5a886d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/032-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>screen and (min-width: 00)</title>
+<link href='foo' media='screen and (min-width: 00)' rel='stylesheet'>
+</head>
+<body>
+<p>screen and (min-width: 00)</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/033-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/033-isvalid.html
new file mode 100644
index 00000000000..7a9d3acdf8c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/033-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>screen and (min-width: .0)</title>
+<link href='foo' media='screen and (min-width: .0)' rel='stylesheet'>
+</head>
+<body>
+<p>screen and (min-width: .0)</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/118-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/118-isvalid.html
new file mode 100644
index 00000000000..00999cfa8ca
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/118-isvalid.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Check that device-aspect-ratio allows space, tab, or LF before & after slash</title>
+<link href='foo' media='screen and (device-aspect-ratio: 16
+/
+9)' rel='stylesheet'> <!-- space, tab, or LF before & after slash -->
+</head>
+<body>
+<p>Check that device-aspect-ratio allows space, tab, or LF before & after slash</p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/source-isvalid.txt b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/source-isvalid.txt
new file mode 100644
index 00000000000..8096ac36d52
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/source-isvalid.txt
@@ -0,0 +1,33 @@
+screen
+ screen
+all
+projection
+not screen
+only screen
+screen and (min-width: 400px)
+screen and (min-width:400px)
+screen and ( min-width: 400px )
+screen and ( min-width : 400px )
+screen and (min-width: 400px)
+screen and ( min-width: 400px)
+screen and (min-width: 400px )
+screen and (min-width: 400px)
+screen and (min-width: 400px)
+screen and (min-width: 400px)
+screen and (min-width: 400px)
+screen and (min-width: 400px) and (max-width: 600px)
+screen and (min-width: 400px) and (max-width: 600px)
+screen and (min-width: 400px) and (max-width: 600px)
+tv and (scan: progressive)
+tv and (scan: interlace)
+screen and (device-aspect-ratio: 16/9)
+screen and (device-aspect-ratio: -16/-9)
+screen and (color: 1)
+screen and (color: 2)
+screen and (color: 0)
+print and (min-resolution: 100dpi)
+screen and (min-width: 400px), print
+screen and (min-width: 0)
+screen and (min-width: 0.0)
+screen and (min-width: 00)
+screen and (min-width: .0) \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/source-novalid.txt b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/source-novalid.txt
new file mode 100644
index 00000000000..91a5e3fcc83
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/media-queries/source-novalid.txt
@@ -0,0 +1,24 @@
+screen and
+alla
+PROJECTİON
+notscreen
+onlyscreen
+screenand (min-width: 400px)
+screen and(min-width: 400px)
+screen and (min-width: 400px;)
+screen and (min-width: 400uu)
+screen and (min-width: 400)
+screen and (min-width: 400dpi)
+screen and (min-width: 400px)and (max-width: 600px)
+screen and (min-width:
+screen and (min-width: 400px) and
+tv and (scan: 1)
+tv and (scan: İNTERLACE)
+screen and (device-aspect-ratio: 16px/9pt)
+screen and (device-aspect-ratio: 16 / 9)
+screen and (color: 1em)
+,
+screen,,print
+screen,
+,screen
+screen and (min-width: 400) \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid-empty-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid-empty-isvalid.html
new file mode 100644
index 00000000000..956e951c4d2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid-empty-isvalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>empty itemid is valid</title>
+<div itemid="" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid-isvalid.html
new file mode 100644
index 00000000000..26ac06797eb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid-isvalid.html
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid itemid</title>
+<div itemid="file:///" itemtype="http://foo" itemscope></div><!-- scheme-file-slash-slash-slash-only -->
+<div itemid="http://a:@www.example.com" itemtype="http://foo" itemscope></div><!-- userinfo-password-empty -->
+<div itemid="foo://///////" itemtype="http://foo" itemscope></div><!-- scheme-private-path-leading-slashes-only -->
+<div itemid="file://abc|/foo/bar" itemtype="http://foo" itemscope></div><!-- scheme-file-slash-slash-abc-bar -->
+<div itemid="/a/b/c" itemtype="http://foo" itemscope></div><!-- path-simple-relative -->
+<div itemid="http://example.com/你好你好" itemtype="http://foo" itemscope></div><!-- path-unicode-han -->
+<div itemid="/a/%2f/c" itemtype="http://foo" itemscope></div><!-- path-percent-encoded-slash-plus-slashes-relative -->
+<div itemid="http://f:/c" itemtype="http://foo" itemscope></div><!-- port-none-but-colon -->
+<div itemid="http://example.com/foo%41%7a" itemtype="http://foo" itemscope></div><!-- path-percent-encoded-multiple -->
+<div itemid="http://192.168.0.257/" itemtype="http://foo" itemscope></div><!-- host-IP-address-broken -->
+<div itemid="madeupscheme:example.com/" itemtype="http://foo" itemscope></div><!-- scheme-private-no-slash -->
+<div itemid="?" itemtype="http://foo" itemscope></div><!-- query-empty-no-path-relative -->
+<div itemid="http://example.com/%20foo" itemtype="http://foo" itemscope></div><!-- path-percent-encoded-space -->
+<div itemid="mailto:/example.com/" itemtype="http://foo" itemscope></div><!-- scheme-mailto-single-slash -->
+<div itemid="::" itemtype="http://foo" itemscope></div><!-- path-leading-colon-colon-relative -->
+<div itemid="http://example.com/%3A%3a%3C%3c" itemtype="http://foo" itemscope></div><!-- path-percent-encoded-mixed-case -->
+<div itemid="http://user:pass@foo:21/bar;par?b#c" itemtype="http://foo" itemscope></div><!-- userinfo -->
+<div itemid="ws:/example.com/" itemtype="http://foo" itemscope></div><!-- scheme-ws-single-slash -->
+<div itemid="foo://" itemtype="http://foo" itemscope></div><!-- scheme-private-slash-slash -->
+<div itemid="#" itemtype="http://foo" itemscope></div><!-- fragment-empty-hash-only-no-path-relative -->
+<div itemid="http://f:00000000000000/c" itemtype="http://foo" itemscope></div><!-- port-00000000000000 -->
+<div itemid="foo:////://///" itemtype="http://foo" itemscope></div><!-- scheme-private-path-leading-slashes-colon-slashes -->
+<div itemid=":23" itemtype="http://foo" itemscope></div><!-- path-leading-colon-number-relative -->
+<div itemid="foo:/" itemtype="http://foo" itemscope></div><!-- scheme-private-slash -->
+<div itemid="http://💩" itemtype="http://foo" itemscope></div><!-- host-is-pile-of-poo -->
+<div itemid="file:test" itemtype="http://foo" itemscope></div><!-- scheme-file-no-slash -->
+<div itemid="file://C|/foo/bar" itemtype="http://foo" itemscope></div><!-- scheme-file-slash-slash-c-bar -->
+<div itemid="#/" itemtype="http://foo" itemscope></div><!-- fragment-slash-relative -->
+<div itemid="http://192.0x00A80001" itemtype="http://foo" itemscope></div><!-- host-192.0x00A80001 -->
+<div itemid="foo.com" itemtype="http://foo" itemscope></div><!-- scheme-none-relative -->
+<div itemid="http💩//:foo" itemtype="http://foo" itemscope></div><!-- path-contains-pile-of-poo -->
+<div itemid="File://foo/bar.html" itemtype="http://foo" itemscope></div><!-- scheme-file-uppercase -->
+<div itemid=":/" itemtype="http://foo" itemscope></div><!-- path-leading-colon-slash-relative -->
+<div itemid="http://www.foo。bar.com" itemtype="http://foo" itemscope></div><!-- host-exotic-dot -->
+<div itemid="http://GOO​⁠goo.com" itemtype="http://foo" itemscope></div><!-- host-exotic-whitespace -->
+<div itemid="file:///foo/bar.txt" itemtype="http://foo" itemscope></div><!-- scheme-file-host-empty -->
+<div itemid="javascript:/example.com/" itemtype="http://foo" itemscope></div><!-- scheme-javascript-single-slash -->
+<div itemid="gopher:/example.com/" itemtype="http://foo" itemscope></div><!-- scheme-gopher-single-slash -->
+<div itemid="ftps:example.com/" itemtype="http://foo" itemscope></div><!-- scheme-ftps-no-slash -->
+<div itemid="file://server/foo/bar" itemtype="http://foo" itemscope></div><!-- scheme-file-host-included -->
+<div itemid="http://example.com/foo%00" itemtype="http://foo" itemscope></div><!-- path-percent-encoded-u0000 -->
+<div itemid="a:foo.com" itemtype="http://foo" itemscope></div><!-- scheme-private -->
+<div itemid=":" itemtype="http://foo" itemscope></div><!-- path-colon-relative -->
+<div itemid="http://:b@www.example.com" itemtype="http://foo" itemscope></div><!-- userinfo-user-empty -->
+<div itemid="file:/" itemtype="http://foo" itemscope></div><!-- scheme-file-slash-only -->
+<div itemid="wss:example.com/" itemtype="http://foo" itemscope></div><!-- scheme-wss-no-slash -->
+<div itemid="::23" itemtype="http://foo" itemscope></div><!-- path-colon-colon-number-relative -->
+<div itemid="/a%2fc" itemtype="http://foo" itemscope></div><!-- path-percent-encoded-slash-relative -->
+<div itemid="http://a:b@c:29/d" itemtype="http://foo" itemscope></div><!-- userinfo-host-port-path -->
+<div itemid="gopher:example.com/" itemtype="http://foo" itemscope></div><!-- scheme-gopher-no-slash -->
+<div itemid="madeupscheme:/example.com/" itemtype="http://foo" itemscope></div><!-- scheme-private-single-slash -->
+<div itemid="mailto:example.com/" itemtype="http://foo" itemscope></div><!-- scheme-mailto-no-slash -->
+<div itemid="http://%25DOMAIN:foobar@foodomain.com" itemtype="http://foo" itemscope></div><!-- userinfo-username-contains-percent-encoded -->
+<div itemid="/:23" itemtype="http://foo" itemscope></div><!-- path-slash-colon-number-relative -->
+<div itemid="foo://///////bar.com/" itemtype="http://foo" itemscope></div><!-- scheme-private-path-leading-slashes-chars -->
+<div itemid="http://[2001::1]:80" itemtype="http://foo" itemscope></div><!-- host-ipv6-port -->
+<div itemid="data:text/plain,foo" itemtype="http://foo" itemscope></div><!-- scheme-data-no-slash -->
+<div itemid="http://example.com/foo/%2e" itemtype="http://foo" itemscope></div><!-- path-percent-encoded-dot -->
+<div itemid="file:/example.com/" itemtype="http://foo" itemscope></div><!-- scheme-file-single-slash -->
+<div itemid="http://example.com/©zbar" itemtype="http://foo" itemscope></div><!-- path-non-ascii -->
+<div itemid="http://example.com//foo" itemtype="http://foo" itemscope></div><!-- path-uFEFF -->
+<div itemid="wss:/example.com/" itemtype="http://foo" itemscope></div><!-- scheme-wss-single-slash -->
+<div itemid="http://foo/abcd#foo?bar" itemtype="http://foo" itemscope></div><!-- fragment-contains-question-mark -->
+<div itemid=":#" itemtype="http://foo" itemscope></div><!-- path-leading-colon-hash-relative -->
+<div itemid="http://example.com/foo%91" itemtype="http://foo" itemscope></div><!-- path-percent-encoded-u0091 -->
+<div itemid="c:/foo" itemtype="http://foo" itemscope></div><!-- scheme-private-single-letter -->
+<div itemid=":foo.com" itemtype="http://foo" itemscope></div><!-- path-leading-colon-chars-relative -->
+<div itemid="http://你好你好" itemtype="http://foo" itemscope></div><!-- host-idn-unicode-han -->
+<div itemid="http://example.com/foo#💩" itemtype="http://foo" itemscope></div><!-- fragment-contains-pile-of-poo -->
+<div itemid="file:" itemtype="http://foo" itemscope></div><!-- scheme-file-scheme-only -->
+<div itemid="#β" itemtype="http://foo" itemscope></div><!-- fragment-non-ascii-relative -->
+<div itemid="foo:/bar.com/" itemtype="http://foo" itemscope></div><!-- scheme-private-path -->
+<div itemid="http://f:0/c" itemtype="http://foo" itemscope></div><!-- port-0 -->
+<div itemid="#;?" itemtype="http://foo" itemscope></div><!-- fragment-semicolon-question-mark-relative -->
+<div itemid="http://Go.com" itemtype="http://foo" itemscope></div><!-- host-fullwidth -->
+<div itemid="http://@www.example.com" itemtype="http://foo" itemscope></div><!-- userinfo-empty -->
+<div itemid="http://example.com/‮/foo/‭/bar" itemtype="http://foo" itemscope></div><!-- path-u202E-u202D -->
+<div itemid="http://[2001::1]" itemtype="http://foo" itemscope></div><!-- host-ipv6 -->
+<div itemid="💩http://foo" itemtype="http://foo" itemscope></div><!-- path-starts-with-pile-of-poo -->
+<div itemid="http://foo/abcd?efgh?ijkl" itemtype="http://foo" itemscope></div><!-- query-contains-question-mark -->
+<div itemid="//foo/bar" itemtype="http://foo" itemscope></div><!-- scheme-schemeless-relative -->
+<div itemid="ftps:/example.com/" itemtype="http://foo" itemscope></div><!-- scheme-ftps-single-slash -->
+<div itemid="http://foo.com:b@d/" itemtype="http://foo" itemscope></div><!-- userinfo-username-non-alpha -->
+<div itemid=":a" itemtype="http://foo" itemscope></div><!-- path-leading-colon-letter-relative -->
+<div itemid="/" itemtype="http://foo" itemscope></div><!-- path-slash-only-relative -->
+<div itemid="http://example.com/foo?💩" itemtype="http://foo" itemscope></div><!-- query-contains-pile-of-poo -->
+<div itemid="http://f:00000000000000000000080/c" itemtype="http://foo" itemscope></div><!-- port-00000000000000000000080 -->
+<div itemid="file://" itemtype="http://foo" itemscope></div><!-- scheme-file-slash-slash-only -->
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid-scheme-data-contains-fragment-haswarn.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid-scheme-data-contains-fragment-haswarn.html
new file mode 100644
index 00000000000..2fe232933ad
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid-scheme-data-contains-fragment-haswarn.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>warning: scheme-data-contains-fragment</title>
+<div itemid="data:text/html,test#test" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/fragment-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/fragment-backslash-novalid.html
new file mode 100644
index 00000000000..a765e5e79ed
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/fragment-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: fragment-backslash</title>
+<div itemid="#\" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/fragment-contains-hash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/fragment-contains-hash-novalid.html
new file mode 100644
index 00000000000..f365b9e720a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/fragment-contains-hash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: fragment-contains-hash</title>
+<div itemid="http://foo/path#f#g" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/fragment-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/fragment-leading-space-novalid.html
new file mode 100644
index 00000000000..2f7182fe22a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/fragment-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: fragment-leading-space</title>
+<div itemid="http://f:21/b# e" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-cr-novalid.html
new file mode 100644
index 00000000000..36d3dc82f56
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: host-cr</title>
+<div itemid="http://example. org" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-double-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-double-percent-encoded-novalid.html
new file mode 100644
index 00000000000..8f7618e37e7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-double-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: host-double-percent-encoded</title>
+<div itemid="http://%41.com" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-double-percent-encoded-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-double-percent-encoded-percent-encoded-novalid.html
new file mode 100644
index 00000000000..c271ada0211
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-double-percent-encoded-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: host-double-percent-encoded-percent-encoded</title>
+<div itemid="http://%ef%bc%85%ef%bc%94%ef%bc%91.com" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-empty-novalid.html
new file mode 100644
index 00000000000..07368db651a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: host-empty</title>
+<div itemid="http://" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-empty-userinfo-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-empty-userinfo-empty-novalid.html
new file mode 100644
index 00000000000..6c5d07beb66
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-empty-userinfo-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: host-empty-userinfo-empty</title>
+<div itemid="http://@/www.example.com" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-empty-with-userinfo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-empty-with-userinfo-novalid.html
new file mode 100644
index 00000000000..41a664bf223
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-empty-with-userinfo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: host-empty-with-userinfo</title>
+<div itemid="http://user:pass@/" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-hostname-in-brackets-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-hostname-in-brackets-novalid.html
new file mode 100644
index 00000000000..a99370b65fe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-hostname-in-brackets-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: host-hostname-in-brackets</title>
+<div itemid="http://[www.google.com]/" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-invalid-unicode-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-invalid-unicode-novalid.html
new file mode 100644
index 00000000000..0104bd3ec74
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-invalid-unicode-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: host-invalid-unicode</title>
+<div itemid="http://﷐zyx.com" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-invalid-unicode-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-invalid-unicode-percent-encoded-novalid.html
new file mode 100644
index 00000000000..940fe8a0181
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-invalid-unicode-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: host-invalid-unicode-percent-encoded</title>
+<div itemid="http://%ef%b7%90zyx.com" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-newline-novalid.html
new file mode 100644
index 00000000000..6474d8ffa9d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: host-newline</title>
+<div itemid="http://example.
+org" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-space-novalid.html
new file mode 100644
index 00000000000..5ccff6990b6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: host-space</title>
+<div itemid="http://example .org" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-square-brackets-port-contains-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-square-brackets-port-contains-colon-novalid.html
new file mode 100644
index 00000000000..0c73b6c51d5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-square-brackets-port-contains-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: host-square-brackets-port-contains-colon</title>
+<div itemid="http://[1::2]:3:4" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-tab-novalid.html
new file mode 100644
index 00000000000..f29256c3d6c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: host-tab</title>
+<div itemid="http://example .org" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-u0000-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-u0000-percent-encoded-novalid.html
new file mode 100644
index 00000000000..154a92579e1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-u0000-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: host-u0000-percent-encoded</title>
+<div itemid="http://%00.com" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-u0000-percent-encoded-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-u0000-percent-encoded-percent-encoded-novalid.html
new file mode 100644
index 00000000000..6747c076e3d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/host-u0000-percent-encoded-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: host-u0000-percent-encoded-percent-encoded</title>
+<div itemid="http://%ef%bc%85%ef%bc%90%ef%bc%90.com" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/path-bare-percent-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/path-bare-percent-sign-novalid.html
new file mode 100644
index 00000000000..e5d5f5fa11b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/path-bare-percent-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: path-bare-percent-sign</title>
+<div itemid="http://example.com/foo%" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/path-contains-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/path-contains-space-novalid.html
new file mode 100644
index 00000000000..a1d17b5f8b5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/path-contains-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: path-contains-space</title>
+<div itemid="/a/ /c" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/path-leading-backslash-at-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/path-leading-backslash-at-sign-novalid.html
new file mode 100644
index 00000000000..0c59308d90c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/path-leading-backslash-at-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: path-leading-backslash-at-sign</title>
+<div itemid="http://foo.com/\@" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/path-leading-colon-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/path-leading-colon-backslash-novalid.html
new file mode 100644
index 00000000000..08a190900ba
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/path-leading-colon-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: path-leading-colon-backslash</title>
+<div itemid=":\" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/path-leading-colon-chars-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/path-leading-colon-chars-backslash-novalid.html
new file mode 100644
index 00000000000..01115ee8853
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/path-leading-colon-chars-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: path-leading-colon-chars-backslash</title>
+<div itemid=":foo.com\" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/path-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/path-leading-space-novalid.html
new file mode 100644
index 00000000000..042758b438a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/path-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: path-leading-space</title>
+<div itemid="http://f:21/ b" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/path-percent-encoded-malformed-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/path-percent-encoded-malformed-novalid.html
new file mode 100644
index 00000000000..49cab58db6a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/path-percent-encoded-malformed-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: path-percent-encoded-malformed</title>
+<div itemid="http://example.com/foo/%2e%2" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/path-relative-square-brackets-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/path-relative-square-brackets-novalid.html
new file mode 100644
index 00000000000..b750b59e49c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/path-relative-square-brackets-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: path-relative-square-brackets</title>
+<div itemid="[61:24:74]:98" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/path-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/path-tab-novalid.html
new file mode 100644
index 00000000000..238d57e9925
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/path-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: path-tab</title>
+<div itemid="http://example.com/foo bar" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/path-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/path-trailing-space-novalid.html
new file mode 100644
index 00000000000..65b750b6f1f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/path-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: path-trailing-space</title>
+<div itemid="http://f:21/b ?" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/path-u0091-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/path-u0091-novalid.html
new file mode 100644
index 00000000000..ae36d74ead4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/path-u0091-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: path-u0091</title>
+<div itemid="http://example.com/foo‘" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/port-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/port-cr-novalid.html
new file mode 100644
index 00000000000..28cededa54e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/port-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: port-cr</title>
+<div itemid="http://f: /c" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/port-leading-colon-bracket-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/port-leading-colon-bracket-colon-novalid.html
new file mode 100644
index 00000000000..24c9fd15422
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/port-leading-colon-bracket-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: port-leading-colon-bracket-colon</title>
+<div itemid="http://2001::1]:80" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/port-leading-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/port-leading-colon-novalid.html
new file mode 100644
index 00000000000..18656d36aef
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/port-leading-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: port-leading-colon</title>
+<div itemid="http://2001::1" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/port-leading-dash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/port-leading-dash-novalid.html
new file mode 100644
index 00000000000..1d275f79d64
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/port-leading-dash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: port-leading-dash</title>
+<div itemid="http://foo:-80/" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/port-multiple-letters-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/port-multiple-letters-novalid.html
new file mode 100644
index 00000000000..e404011d24a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/port-multiple-letters-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: port-multiple-letters</title>
+<div itemid="http://f:fifty-two/c" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/port-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/port-newline-novalid.html
new file mode 100644
index 00000000000..3b556be6b72
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/port-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: port-newline</title>
+<div itemid="http://f:
+/c" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/port-single-letter-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/port-single-letter-novalid.html
new file mode 100644
index 00000000000..b1274e33bf1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/port-single-letter-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: port-single-letter</title>
+<div itemid="http://f:b/c" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/port-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/port-space-novalid.html
new file mode 100644
index 00000000000..ad2e271ceeb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/port-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: port-space</title>
+<div itemid="http://f: /c" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/port-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/port-tab-novalid.html
new file mode 100644
index 00000000000..e015e7c87e8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/port-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: port-tab</title>
+<div itemid="http://f: /c" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/query-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/query-leading-space-novalid.html
new file mode 100644
index 00000000000..c4465245ec5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/query-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: query-leading-space</title>
+<div itemid="http://f:21/b? d" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/query-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/query-trailing-space-novalid.html
new file mode 100644
index 00000000000..9ca912bfe13
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/query-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: query-trailing-space</title>
+<div itemid="http://f:21/b?d #" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-data-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-data-single-slash-novalid.html
new file mode 100644
index 00000000000..1ec8d49758c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-data-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: scheme-data-single-slash</title>
+<div itemid="data:/example.com/" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-file-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-file-backslash-novalid.html
new file mode 100644
index 00000000000..602e154d8c1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-file-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: scheme-file-backslash</title>
+<div itemid="file:c:\foo\bar.html" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-file-single-slash-c-bar-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-file-single-slash-c-bar-novalid.html
new file mode 100644
index 00000000000..f94b9e63834
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-file-single-slash-c-bar-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: scheme-file-single-slash-c-bar</title>
+<div itemid="file:/C|/foo/bar" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-file-triple-slash-c-bar-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-file-triple-slash-c-bar-novalid.html
new file mode 100644
index 00000000000..c77fe276843
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-file-triple-slash-c-bar-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: scheme-file-triple-slash-c-bar</title>
+<div itemid="file:///C|/foo/bar" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-ftp-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-ftp-no-slash-novalid.html
new file mode 100644
index 00000000000..906f089aca0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-ftp-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: scheme-ftp-no-slash</title>
+<div itemid="ftp:example.com/" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-ftp-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-ftp-single-slash-novalid.html
new file mode 100644
index 00000000000..48ae5d1d26c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-ftp-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: scheme-ftp-single-slash</title>
+<div itemid="ftp:/example.com/" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-http-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-http-backslash-novalid.html
new file mode 100644
index 00000000000..8e28363a8aa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-http-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: scheme-http-backslash</title>
+<div itemid="http:\\foo.com\" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-http-no-slash-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-http-no-slash-colon-novalid.html
new file mode 100644
index 00000000000..e52bf145cad
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-http-no-slash-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: scheme-http-no-slash-colon</title>
+<div itemid="http::@c:29" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-http-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-http-no-slash-novalid.html
new file mode 100644
index 00000000000..d6015babadc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-http-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: scheme-http-no-slash</title>
+<div itemid="http:foo.com" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-http-no-slash-square-bracket-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-http-no-slash-square-bracket-novalid.html
new file mode 100644
index 00000000000..3dc8745f3f0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-http-no-slash-square-bracket-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: scheme-http-no-slash-square-bracket</title>
+<div itemid="http:[61:27]/:foo" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-http-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-http-single-slash-novalid.html
new file mode 100644
index 00000000000..a653c2c7d25
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-http-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: scheme-http-single-slash</title>
+<div itemid="http:/example.com/" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-https-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-https-no-slash-novalid.html
new file mode 100644
index 00000000000..07b7261b273
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-https-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: scheme-https-no-slash</title>
+<div itemid="https:example.com/" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-https-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-https-single-slash-novalid.html
new file mode 100644
index 00000000000..6fbd3c1a813
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-https-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: scheme-https-single-slash</title>
+<div itemid="https:/example.com/" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-javascript-no-slash-malformed-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-javascript-no-slash-malformed-novalid.html
new file mode 100644
index 00000000000..3bf1c6516a5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-javascript-no-slash-malformed-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: scheme-javascript-no-slash-malformed</title>
+<div itemid="javascript:example.com/" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-trailing-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-trailing-cr-novalid.html
new file mode 100644
index 00000000000..fabd1ebe30e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-trailing-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: scheme-trailing-cr</title>
+<div itemid="a: foo.com" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-trailing-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-trailing-newline-novalid.html
new file mode 100644
index 00000000000..4d82605af27
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-trailing-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: scheme-trailing-newline</title>
+<div itemid="a:
+foo.com" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-trailing-space-novalid.html
new file mode 100644
index 00000000000..f7a61cd7724
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: scheme-trailing-space</title>
+<div itemid="a: foo.com" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-trailing-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-trailing-tab-novalid.html
new file mode 100644
index 00000000000..a3c50b1875f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/scheme-trailing-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: scheme-trailing-tab</title>
+<div itemid="a: foo.com" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/userinfo-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/userinfo-backslash-novalid.html
new file mode 100644
index 00000000000..838664b2517
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/userinfo-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: userinfo-backslash</title>
+<div itemid="http://a\b:c\d@foo.com" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/userinfo-password-bad-chars-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/userinfo-password-bad-chars-novalid.html
new file mode 100644
index 00000000000..282669321db
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/userinfo-password-bad-chars-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: userinfo-password-bad-chars</title>
+<div itemid="http://&a:foo(b]c@d:2/" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/userinfo-password-contains-pile-of-poo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/userinfo-password-contains-pile-of-poo-novalid.html
new file mode 100644
index 00000000000..8a5ba7a71f5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/userinfo-password-contains-pile-of-poo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: userinfo-password-contains-pile-of-poo</title>
+<div itemid="http://foo:💩@example.com" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/userinfo-username-contains-at-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/userinfo-username-contains-at-sign-novalid.html
new file mode 100644
index 00000000000..99f41339cbd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/userinfo-username-contains-at-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: userinfo-username-contains-at-sign</title>
+<div itemid="http://::@c@d:2" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/userinfo-username-contains-pile-of-poo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/userinfo-username-contains-pile-of-poo-novalid.html
new file mode 100644
index 00000000000..66d597ffc1f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemid/userinfo-username-contains-pile-of-poo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemid: userinfo-username-contains-pile-of-poo</title>
+<div itemid="http://💩:foo@example.com" itemtype="http://foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype-empty-novalid.html
new file mode 100644
index 00000000000..1ed8c466109
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>empty itemtype is not valid</title>
+<div itemtype="" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype-isvalid.html
new file mode 100644
index 00000000000..81538abebdd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype-isvalid.html
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>valid itemtype</title>
+<div itemtype="file:///" itemscope></div><!-- scheme-file-slash-slash-slash-only -->
+<div itemtype="http://a:@www.example.com" itemscope></div><!-- userinfo-password-empty -->
+<div itemtype="foo://///////" itemscope></div><!-- scheme-private-path-leading-slashes-only -->
+<div itemtype="file://abc|/foo/bar" itemscope></div><!-- scheme-file-slash-slash-abc-bar -->
+<div itemtype="http://example.com/foo#💩" itemscope></div><!-- fragment-contains-pile-of-poo -->
+<div itemtype="http://example.com/你好你好" itemscope></div><!-- path-unicode-han -->
+<div itemtype="http://f:/c" itemscope></div><!-- port-none-but-colon -->
+<div itemtype="http://example.com/foo%41%7a" itemscope></div><!-- path-percent-encoded-multiple -->
+<div itemtype="http://192.168.0.257/" itemscope></div><!-- host-IP-address-broken -->
+<div itemtype="madeupscheme:example.com/" itemscope></div><!-- scheme-private-no-slash -->
+<div itemtype="http://example.com/%20foo" itemscope></div><!-- path-percent-encoded-space -->
+<div itemtype="http://%25DOMAIN:foobar@foodomain.com" itemscope></div><!-- userinfo-username-contains-percent-encoded -->
+<div itemtype="http://你好你好" itemscope></div><!-- host-idn-unicode-han -->
+<div itemtype="http://example.com/%3A%3a%3C%3c" itemscope></div><!-- path-percent-encoded-mixed-case -->
+<div itemtype="http://user:pass@foo:21/bar;par?b#c" itemscope></div><!-- userinfo -->
+<div itemtype="ws:/example.com/" itemscope></div><!-- scheme-ws-single-slash -->
+<div itemtype="foo://" itemscope></div><!-- scheme-private-slash-slash -->
+<div itemtype="http://f:00000000000000/c" itemscope></div><!-- port-00000000000000 -->
+<div itemtype="foo:////://///" itemscope></div><!-- scheme-private-path-leading-slashes-colon-slashes -->
+<div itemtype="foo:/" itemscope></div><!-- scheme-private-slash -->
+<div itemtype="http://💩" itemscope></div><!-- host-is-pile-of-poo -->
+<div itemtype="file:test" itemscope></div><!-- scheme-file-no-slash -->
+<div itemtype="file://C|/foo/bar" itemscope></div><!-- scheme-file-slash-slash-c-bar -->
+<div itemtype="http://192.0x00A80001" itemscope></div><!-- host-192.0x00A80001 -->
+<div itemtype="http://example.com/foo/💩" itemscope></div><!-- path-contains-pile-of-poo -->
+<div itemtype="File://foo/bar.html" itemscope></div><!-- scheme-file-uppercase -->
+<div itemtype="http://www.foo。bar.com" itemscope></div><!-- host-exotic-dot -->
+<div itemtype="http://GOO​⁠goo.com" itemscope></div><!-- host-exotic-whitespace -->
+<div itemtype="file:///foo/bar.txt" itemscope></div><!-- scheme-file-host-empty -->
+<div itemtype="javascript:/example.com/" itemscope></div><!-- scheme-javascript-single-slash -->
+<div itemtype="gopher:/example.com/" itemscope></div><!-- scheme-gopher-single-slash -->
+<div itemtype="ftps:example.com/" itemscope></div><!-- scheme-ftps-no-slash -->
+<div itemtype="file://server/foo/bar" itemscope></div><!-- scheme-file-host-included -->
+<div itemtype="http://foo/abcd#foo?bar" itemscope></div><!-- fragment-contains-question-mark -->
+<div itemtype="a:foo.com" itemscope></div><!-- scheme-private -->
+<div itemtype="http://:b@www.example.com" itemscope></div><!-- userinfo-user-empty -->
+<div itemtype="file:/" itemscope></div><!-- scheme-file-slash-only -->
+<div itemtype="madeupscheme:/example.com/" itemscope></div><!-- scheme-private-single-slash -->
+<div itemtype="http://a:b@c:29/d" itemscope></div><!-- userinfo-host-port-path -->
+<div itemtype="gopher:example.com/" itemscope></div><!-- scheme-gopher-no-slash -->
+<div itemtype="mailto:example.com/" itemscope></div><!-- scheme-mailto-no-slash -->
+<div itemtype="mailto:/example.com/" itemscope></div><!-- scheme-mailto-single-slash -->
+<div itemtype="foo://///////bar.com/" itemscope></div><!-- scheme-private-path-leading-slashes-chars -->
+<div itemtype="http://[2001::1]:80" itemscope></div><!-- host-ipv6-port -->
+<div itemtype="http://example.com/foo/%2e" itemscope></div><!-- path-percent-encoded-dot -->
+<div itemtype="file:/example.com/" itemscope></div><!-- scheme-file-single-slash -->
+<div itemtype="http://example.com/©zbar" itemscope></div><!-- path-non-ascii -->
+<div itemtype="http://example.com//foo" itemscope></div><!-- path-uFEFF -->
+<div itemtype="wss:/example.com/" itemscope></div><!-- scheme-wss-single-slash -->
+<div itemtype="http://example.com/foo%00" itemscope></div><!-- path-percent-encoded-u0000 -->
+<div itemtype="http://example.com/foo%91" itemscope></div><!-- path-percent-encoded-u0091 -->
+<div itemtype="c:/foo" itemscope></div><!-- scheme-private-single-letter -->
+<div itemtype="wss:example.com/" itemscope></div><!-- scheme-wss-no-slash -->
+<div itemtype="http://foo/abcd?efgh?ijkl" itemscope></div><!-- query-contains-question-mark -->
+<div itemtype="file:" itemscope></div><!-- scheme-file-scheme-only -->
+<div itemtype="foo:/bar.com/" itemscope></div><!-- scheme-private-path -->
+<div itemtype="http://f:0/c" itemscope></div><!-- port-0 -->
+<div itemtype="http://Go.com" itemscope></div><!-- host-fullwidth -->
+<div itemtype="http://@www.example.com" itemscope></div><!-- userinfo-empty -->
+<div itemtype="http://example.com/‮/foo/‭/bar" itemscope></div><!-- path-u202E-u202D -->
+<div itemtype="http://[2001::1]" itemscope></div><!-- host-ipv6 -->
+<div itemtype="ftps:/example.com/" itemscope></div><!-- scheme-ftps-single-slash -->
+<div itemtype="http://foo.com:b@d/" itemscope></div><!-- userinfo-username-non-alpha -->
+<div itemtype="data:text/plain,foo" itemscope></div><!-- scheme-data-no-slash -->
+<div itemtype="http://example.com/foo?💩" itemscope></div><!-- query-contains-pile-of-poo -->
+<div itemtype="http://f:00000000000000000000080/c" itemscope></div><!-- port-00000000000000000000080 -->
+<div itemtype="file://" itemscope></div><!-- scheme-file-slash-slash-only -->
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype-scheme-data-contains-fragment-haswarn.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype-scheme-data-contains-fragment-haswarn.html
new file mode 100644
index 00000000000..3374691574f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype-scheme-data-contains-fragment-haswarn.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>warning: scheme-data-contains-fragment</title>
+<div itemtype="data:text/html,test#test" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/fragment-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/fragment-backslash-novalid.html
new file mode 100644
index 00000000000..7165f965052
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/fragment-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: fragment-backslash</title>
+<div itemtype="#\" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/fragment-contains-hash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/fragment-contains-hash-novalid.html
new file mode 100644
index 00000000000..0f36d930d76
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/fragment-contains-hash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: fragment-contains-hash</title>
+<div itemtype="http://foo/path#f#g" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/fragment-empty-hash-only-no-path-relative-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/fragment-empty-hash-only-no-path-relative-novalid.html
new file mode 100644
index 00000000000..b6d6f63031b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/fragment-empty-hash-only-no-path-relative-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: fragment-empty-hash-only-no-path-relative</title>
+<div itemtype="#" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/fragment-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/fragment-leading-space-novalid.html
new file mode 100644
index 00000000000..140200b5199
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/fragment-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: fragment-leading-space</title>
+<div itemtype="http://f:21/b# e" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/fragment-non-ascii-relative-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/fragment-non-ascii-relative-novalid.html
new file mode 100644
index 00000000000..bf8bd41bab4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/fragment-non-ascii-relative-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: fragment-non-ascii-relative</title>
+<div itemtype="#β" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/fragment-semicolon-question-mark-relative-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/fragment-semicolon-question-mark-relative-novalid.html
new file mode 100644
index 00000000000..654b38ee53b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/fragment-semicolon-question-mark-relative-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: fragment-semicolon-question-mark-relative</title>
+<div itemtype="#;?" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/fragment-slash-relative-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/fragment-slash-relative-novalid.html
new file mode 100644
index 00000000000..d257b10f4af
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/fragment-slash-relative-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: fragment-slash-relative</title>
+<div itemtype="#/" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-cr-novalid.html
new file mode 100644
index 00000000000..e3528dfdf0a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: host-cr</title>
+<div itemtype="http://example. org" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-double-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-double-percent-encoded-novalid.html
new file mode 100644
index 00000000000..435a7422605
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-double-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: host-double-percent-encoded</title>
+<div itemtype="http://%41.com" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-double-percent-encoded-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-double-percent-encoded-percent-encoded-novalid.html
new file mode 100644
index 00000000000..d84dd8ef2ba
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-double-percent-encoded-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: host-double-percent-encoded-percent-encoded</title>
+<div itemtype="http://%ef%bc%85%ef%bc%94%ef%bc%91.com" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-empty-novalid.html
new file mode 100644
index 00000000000..3de07bdf004
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: host-empty</title>
+<div itemtype="http://" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-empty-userinfo-empty-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-empty-userinfo-empty-novalid.html
new file mode 100644
index 00000000000..e4a11f71729
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-empty-userinfo-empty-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: host-empty-userinfo-empty</title>
+<div itemtype="http://@/www.example.com" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-empty-with-userinfo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-empty-with-userinfo-novalid.html
new file mode 100644
index 00000000000..9457bbd6ebb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-empty-with-userinfo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: host-empty-with-userinfo</title>
+<div itemtype="http://user:pass@/" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-hostname-in-brackets-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-hostname-in-brackets-novalid.html
new file mode 100644
index 00000000000..9046800cc58
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-hostname-in-brackets-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: host-hostname-in-brackets</title>
+<div itemtype="http://[www.google.com]/" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-invalid-unicode-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-invalid-unicode-novalid.html
new file mode 100644
index 00000000000..c059b89b060
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-invalid-unicode-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: host-invalid-unicode</title>
+<div itemtype="http://﷐zyx.com" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-invalid-unicode-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-invalid-unicode-percent-encoded-novalid.html
new file mode 100644
index 00000000000..0f1522d8017
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-invalid-unicode-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: host-invalid-unicode-percent-encoded</title>
+<div itemtype="http://%ef%b7%90zyx.com" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-newline-novalid.html
new file mode 100644
index 00000000000..9fcb3cdedc7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: host-newline</title>
+<div itemtype="http://example.
+org" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-space-novalid.html
new file mode 100644
index 00000000000..195ec60b5c9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: host-space</title>
+<div itemtype="http://example .org" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-square-brackets-port-contains-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-square-brackets-port-contains-colon-novalid.html
new file mode 100644
index 00000000000..dc53b33caeb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-square-brackets-port-contains-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: host-square-brackets-port-contains-colon</title>
+<div itemtype="http://[1::2]:3:4" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-tab-novalid.html
new file mode 100644
index 00000000000..54d754c2c39
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: host-tab</title>
+<div itemtype="http://example .org" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-u0000-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-u0000-percent-encoded-novalid.html
new file mode 100644
index 00000000000..e087825a9ad
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-u0000-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: host-u0000-percent-encoded</title>
+<div itemtype="http://%00.com" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-u0000-percent-encoded-percent-encoded-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-u0000-percent-encoded-percent-encoded-novalid.html
new file mode 100644
index 00000000000..342056e1b19
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/host-u0000-percent-encoded-percent-encoded-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: host-u0000-percent-encoded-percent-encoded</title>
+<div itemtype="http://%ef%bc%85%ef%bc%90%ef%bc%90.com" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-bare-percent-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-bare-percent-sign-novalid.html
new file mode 100644
index 00000000000..ee4f3b19742
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-bare-percent-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: path-bare-percent-sign</title>
+<div itemtype="http://example.com/foo%" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-contains-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-contains-space-novalid.html
new file mode 100644
index 00000000000..a23414ada63
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-contains-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: path-contains-space</title>
+<div itemtype="/a/ /c" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-leading-backslash-at-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-leading-backslash-at-sign-novalid.html
new file mode 100644
index 00000000000..bc3bd936310
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-leading-backslash-at-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: path-leading-backslash-at-sign</title>
+<div itemtype="http://foo.com/\@" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-leading-colon-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-leading-colon-backslash-novalid.html
new file mode 100644
index 00000000000..42173c5a7c2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-leading-colon-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: path-leading-colon-backslash</title>
+<div itemtype=":\" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-leading-colon-chars-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-leading-colon-chars-backslash-novalid.html
new file mode 100644
index 00000000000..a12ee18389e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-leading-colon-chars-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: path-leading-colon-chars-backslash</title>
+<div itemtype=":foo.com\" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-leading-space-novalid.html
new file mode 100644
index 00000000000..23107f27e24
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: path-leading-space</title>
+<div itemtype="http://f:21/ b" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-percent-encoded-malformed-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-percent-encoded-malformed-novalid.html
new file mode 100644
index 00000000000..76c92a24729
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-percent-encoded-malformed-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: path-percent-encoded-malformed</title>
+<div itemtype="http://example.com/foo/%2e%2" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-percent-encoded-slash-plus-slashes-relative-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-percent-encoded-slash-plus-slashes-relative-novalid.html
new file mode 100644
index 00000000000..74e8c6cb078
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-percent-encoded-slash-plus-slashes-relative-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: path-percent-encoded-slash-plus-slashes-relative</title>
+<div itemtype="/a/%2f/c" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-percent-encoded-slash-relative-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-percent-encoded-slash-relative-novalid.html
new file mode 100644
index 00000000000..524a7599875
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-percent-encoded-slash-relative-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: path-percent-encoded-slash-relative</title>
+<div itemtype="/a%2fc" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-relative-square-brackets-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-relative-square-brackets-novalid.html
new file mode 100644
index 00000000000..5b9835bde7b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-relative-square-brackets-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: path-relative-square-brackets</title>
+<div itemtype="[61:24:74]:98" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-simple-relative-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-simple-relative-novalid.html
new file mode 100644
index 00000000000..fb94f42fe44
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-simple-relative-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: path-simple-relative</title>
+<div itemtype="/a/b/c" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-slash-only-relative-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-slash-only-relative-novalid.html
new file mode 100644
index 00000000000..078fff90235
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-slash-only-relative-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: path-slash-only-relative</title>
+<div itemtype="/" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-tab-novalid.html
new file mode 100644
index 00000000000..e54d0937868
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: path-tab</title>
+<div itemtype="http://example.com/foo bar" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-trailing-space-novalid.html
new file mode 100644
index 00000000000..d5dd76481b0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: path-trailing-space</title>
+<div itemtype="http://f:21/b ?" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-u0091-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-u0091-novalid.html
new file mode 100644
index 00000000000..83445495757
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/path-u0091-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: path-u0091</title>
+<div itemtype="http://example.com/foo‘" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/port-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/port-cr-novalid.html
new file mode 100644
index 00000000000..302a96c79f5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/port-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: port-cr</title>
+<div itemtype="http://f: /c" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/port-leading-colon-bracket-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/port-leading-colon-bracket-colon-novalid.html
new file mode 100644
index 00000000000..482e11d8f53
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/port-leading-colon-bracket-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: port-leading-colon-bracket-colon</title>
+<div itemtype="http://2001::1]:80" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/port-leading-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/port-leading-colon-novalid.html
new file mode 100644
index 00000000000..15c969782e3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/port-leading-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: port-leading-colon</title>
+<div itemtype="http://2001::1" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/port-leading-dash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/port-leading-dash-novalid.html
new file mode 100644
index 00000000000..b6b2847c2bf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/port-leading-dash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: port-leading-dash</title>
+<div itemtype="http://foo:-80/" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/port-multiple-letters-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/port-multiple-letters-novalid.html
new file mode 100644
index 00000000000..1d63eb6b98f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/port-multiple-letters-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: port-multiple-letters</title>
+<div itemtype="http://f:fifty-two/c" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/port-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/port-newline-novalid.html
new file mode 100644
index 00000000000..56f5b418015
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/port-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: port-newline</title>
+<div itemtype="http://f:
+/c" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/port-single-letter-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/port-single-letter-novalid.html
new file mode 100644
index 00000000000..5817b69d5bb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/port-single-letter-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: port-single-letter</title>
+<div itemtype="http://f:b/c" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/port-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/port-space-novalid.html
new file mode 100644
index 00000000000..c66dde4cd74
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/port-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: port-space</title>
+<div itemtype="http://f: /c" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/port-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/port-tab-novalid.html
new file mode 100644
index 00000000000..0056f4ef9dd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/port-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: port-tab</title>
+<div itemtype="http://f: /c" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/query-empty-no-path-relative-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/query-empty-no-path-relative-novalid.html
new file mode 100644
index 00000000000..389c2acc8d7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/query-empty-no-path-relative-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: query-empty-no-path-relative</title>
+<div itemtype="?" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/query-leading-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/query-leading-space-novalid.html
new file mode 100644
index 00000000000..ab89c0e2a38
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/query-leading-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: query-leading-space</title>
+<div itemtype="http://f:21/b? d" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/query-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/query-trailing-space-novalid.html
new file mode 100644
index 00000000000..8db94d80cfc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/query-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: query-trailing-space</title>
+<div itemtype="http://f:21/b?d #" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-data-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-data-single-slash-novalid.html
new file mode 100644
index 00000000000..a4b88ed71dd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-data-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: scheme-data-single-slash</title>
+<div itemtype="data:/example.com/" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-ftp-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-ftp-no-slash-novalid.html
new file mode 100644
index 00000000000..e4c5289f175
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-ftp-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: scheme-ftp-no-slash</title>
+<div itemtype="ftp:example.com/" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-ftp-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-ftp-single-slash-novalid.html
new file mode 100644
index 00000000000..0a95473a469
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-ftp-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: scheme-ftp-single-slash</title>
+<div itemtype="ftp:/example.com/" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-http-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-http-backslash-novalid.html
new file mode 100644
index 00000000000..133b47c832f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-http-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: scheme-http-backslash</title>
+<div itemtype="http:\\foo.com\" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-http-no-slash-colon-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-http-no-slash-colon-novalid.html
new file mode 100644
index 00000000000..613afa1376f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-http-no-slash-colon-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: scheme-http-no-slash-colon</title>
+<div itemtype="http::@c:29" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-http-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-http-no-slash-novalid.html
new file mode 100644
index 00000000000..4da5f8f3117
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-http-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: scheme-http-no-slash</title>
+<div itemtype="http:foo.com" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-http-no-slash-square-bracket-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-http-no-slash-square-bracket-novalid.html
new file mode 100644
index 00000000000..03aa71aadb9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-http-no-slash-square-bracket-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: scheme-http-no-slash-square-bracket</title>
+<div itemtype="http:[61:27]/:foo" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-http-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-http-single-slash-novalid.html
new file mode 100644
index 00000000000..32f31a64c7e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-http-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: scheme-http-single-slash</title>
+<div itemtype="http:/example.com/" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-https-no-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-https-no-slash-novalid.html
new file mode 100644
index 00000000000..e5d4bd70dbd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-https-no-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: scheme-https-no-slash</title>
+<div itemtype="https:example.com/" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-https-single-slash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-https-single-slash-novalid.html
new file mode 100644
index 00000000000..d4608d0381d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-https-single-slash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: scheme-https-single-slash</title>
+<div itemtype="https:/example.com/" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-javascript-no-slash-malformed-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-javascript-no-slash-malformed-novalid.html
new file mode 100644
index 00000000000..5110c6d35b2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-javascript-no-slash-malformed-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: scheme-javascript-no-slash-malformed</title>
+<div itemtype="javascript:example.com/" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-schemeless-relative-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-schemeless-relative-novalid.html
new file mode 100644
index 00000000000..c2301027d4c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-schemeless-relative-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: scheme-schemeless-relative</title>
+<div itemtype="//foo/bar" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-trailing-cr-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-trailing-cr-novalid.html
new file mode 100644
index 00000000000..0ec64f5a4cc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-trailing-cr-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: scheme-trailing-cr</title>
+<div itemtype="a: foo.com" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-trailing-newline-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-trailing-newline-novalid.html
new file mode 100644
index 00000000000..1ea50fcc9cb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-trailing-newline-novalid.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: scheme-trailing-newline</title>
+<div itemtype="a:
+foo.com" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-trailing-space-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-trailing-space-novalid.html
new file mode 100644
index 00000000000..5421a3e81ba
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-trailing-space-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: scheme-trailing-space</title>
+<div itemtype="a: foo.com" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-trailing-tab-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-trailing-tab-novalid.html
new file mode 100644
index 00000000000..fa0e3ca8381
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/scheme-trailing-tab-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: scheme-trailing-tab</title>
+<div itemtype="a: foo.com" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/userinfo-backslash-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/userinfo-backslash-novalid.html
new file mode 100644
index 00000000000..10e6853cf10
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/userinfo-backslash-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: userinfo-backslash</title>
+<div itemtype="http://a\b:c\d@foo.com" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/userinfo-password-bad-chars-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/userinfo-password-bad-chars-novalid.html
new file mode 100644
index 00000000000..e617ca7b7f0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/userinfo-password-bad-chars-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: userinfo-password-bad-chars</title>
+<div itemtype="http://&a:foo(b]c@d:2/" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/userinfo-password-contains-pile-of-poo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/userinfo-password-contains-pile-of-poo-novalid.html
new file mode 100644
index 00000000000..ecde2e96d8d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/userinfo-password-contains-pile-of-poo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: userinfo-password-contains-pile-of-poo</title>
+<div itemtype="http://foo:💩@example.com" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/userinfo-username-contains-at-sign-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/userinfo-username-contains-at-sign-novalid.html
new file mode 100644
index 00000000000..b89683c3859
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/userinfo-username-contains-at-sign-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: userinfo-username-contains-at-sign</title>
+<div itemtype="http://::@c@d:2" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/userinfo-username-contains-pile-of-poo-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/userinfo-username-contains-pile-of-poo-novalid.html
new file mode 100644
index 00000000000..7b09f94cd60
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/microdata/itemtype/userinfo-username-contains-pile-of-poo-novalid.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>invalid itemtype: userinfo-username-contains-pile-of-poo</title>
+<div itemtype="http://💩:foo@example.com" itemscope></div>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/001-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/001-isvalid.html
new file mode 100644
index 00000000000..beee463156e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/001-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>text/html</title>
+<link href='foo' type='text/html' rel='stylesheet'>
+</head>
+<body>
+<p>text/html</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/001-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/001-novalid.html
new file mode 100644
index 00000000000..98d7d44a3c3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/001-novalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>text/html </title>
+<link href='foo' type='text/html ' rel='stylesheet'>
+</head>
+<body>
+<p>text/html </p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/002-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/002-isvalid.html
new file mode 100644
index 00000000000..88bd22910ea
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/002-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>TEXT/HTML</title>
+<link href='foo' type='TEXT/HTML' rel='stylesheet'>
+</head>
+<body>
+<p>TEXT/HTML</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/002-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/002-novalid.html
new file mode 100644
index 00000000000..3f434dd3de3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/002-novalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title> TEXT/HTML</title>
+<link href='foo' type=' TEXT/HTML' rel='stylesheet'>
+</head>
+<body>
+<p> TEXT/HTML</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/003-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/003-isvalid.html
new file mode 100644
index 00000000000..99f4bed5967
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/003-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>text/html;charset=utf-8</title>
+<link href='foo' type='text/html;charset=utf-8' rel='stylesheet'>
+</head>
+<body>
+<p>text/html;charset=utf-8</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/003-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/003-novalid.html
new file mode 100644
index 00000000000..39d2be0c1de
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/003-novalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>text/html;charset=</title>
+<link href='foo' type='text/html;charset=' rel='stylesheet'>
+</head>
+<body>
+<p>text/html;charset=</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/004-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/004-isvalid.html
new file mode 100644
index 00000000000..5c9a2065b1b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/004-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>text/html ;charset=utf-8</title>
+<link href='foo' type='text/html ;charset=utf-8' rel='stylesheet'>
+</head>
+<body>
+<p>text/html ;charset=utf-8</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/004-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/004-novalid.html
new file mode 100644
index 00000000000..4fa0bf9992f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/004-novalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>text/html ;charset</title>
+<link href='foo' type='text/html ;charset' rel='stylesheet'>
+</head>
+<body>
+<p>text/html ;charset</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/005-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/005-isvalid.html
new file mode 100644
index 00000000000..4803124f394
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/005-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>text/html; charset=utf-8</title>
+<link href='foo' type='text/html; charset=utf-8' rel='stylesheet'>
+</head>
+<body>
+<p>text/html; charset=utf-8</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/005-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/005-novalid.html
new file mode 100644
index 00000000000..4ada4f9f9d3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/005-novalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>text/html;</title>
+<link href='foo' type='text/html;' rel='stylesheet'>
+</head>
+<body>
+<p>text/html;</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/006-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/006-isvalid.html
new file mode 100644
index 00000000000..5e25924acff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/006-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>text/html ; charset=utf-8</title>
+<link href='foo' type='text/html ; charset=utf-8' rel='stylesheet'>
+</head>
+<body>
+<p>text/html ; charset=utf-8</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/006-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/006-novalid.html
new file mode 100644
index 00000000000..29bf1653c9e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/006-novalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>text/html; </title>
+<link href='foo' type='text/html; ' rel='stylesheet'>
+</head>
+<body>
+<p>text/html; </p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/007-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/007-isvalid.html
new file mode 100644
index 00000000000..c71d991ffab
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/007-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>text/html;charset="utf-8"</title>
+<link href='foo' type='text/html;charset="utf-8"' rel='stylesheet'>
+</head>
+<body>
+<p>text/html;charset="utf-8"</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/007-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/007-novalid.html
new file mode 100644
index 00000000000..83c36896303
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/007-novalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>text/html ;</title>
+<link href='foo' type='text/html ;' rel='stylesheet'>
+</head>
+<body>
+<p>text/html ;</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/008-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/008-isvalid.html
new file mode 100644
index 00000000000..2a9c7dfac5d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/008-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>text/html;charset="\utf-8"</title>
+<link href='foo' type='text/html;charset="\utf-8"' rel='stylesheet'>
+</head>
+<body>
+<p>text/html;charset="\utf-8"</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/008-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/008-novalid.html
new file mode 100644
index 00000000000..0c40587634d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/008-novalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>text/html;charset="utf-8</title>
+<link href='foo' type='text/html;charset="utf-8' rel='stylesheet'>
+</head>
+<body>
+<p>text/html;charset="utf-8</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/009-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/009-isvalid.html
new file mode 100644
index 00000000000..3f145d9fd0d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/009-isvalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>text/html;charset="u\t\f\-\8"</title>
+<link href='foo' type='text/html;charset="u\t\f\-\8"' rel='stylesheet'>
+</head>
+<body>
+<p>text/html;charset="u\t\f\-\8"</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/009-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/009-novalid.html
new file mode 100644
index 00000000000..897ab104274
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/009-novalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>text/html;charset="u\</title>
+<link href='foo' type='text/html;charset="u\' rel='stylesheet'>
+</head>
+<body>
+<p>text/html;charset="u\</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/010-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/010-isvalid.html
new file mode 100644
index 00000000000..f581b74d589
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/010-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>application/auth-policy+xml</title>
+<link href='foo' type='application/auth-policy+xml' rel='stylesheet'>
+</head>
+<body>
+<p>application/auth-policy+xml</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/010-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/010-novalid.html
new file mode 100644
index 00000000000..66b2431526f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/010-novalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>application</title>
+<link href='foo' type='application' rel='stylesheet'>
+</head>
+<body>
+<p>application</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/011-isvalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/011-isvalid.html
new file mode 100644
index 00000000000..a1fe2c5461c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/011-isvalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>application/vnd.apple.installer+xml</title>
+<link href='foo' type='application/vnd.apple.installer+xml' rel='stylesheet'>
+</head>
+<body>
+<p>application/vnd.apple.installer+xml</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/011-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/011-novalid.html
new file mode 100644
index 00000000000..ffd850c77aa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/011-novalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>application/</title>
+<link href='foo' type='application/' rel='stylesheet'>
+</head>
+<body>
+<p>application/</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/source-isvalid.txt b/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/source-isvalid.txt
new file mode 100644
index 00000000000..ef2436e4984
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/source-isvalid.txt
@@ -0,0 +1,11 @@
+text/html
+TEXT/HTML
+text/html;charset=utf-8
+text/html ;charset=utf-8
+text/html; charset=utf-8
+text/html ; charset=utf-8
+text/html;charset="utf-8"
+text/html;charset="\utf-8"
+text/html;charset="u\t\f\-\8"
+application/auth-policy+xml
+application/vnd.apple.installer+xml \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/source-novalid.txt b/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/source-novalid.txt
new file mode 100644
index 00000000000..52a320e85bf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/mime-types/source-novalid.txt
@@ -0,0 +1,11 @@
+text/html
+ TEXT/HTML
+text/html;charset=
+text/html ;charset
+text/html;
+text/html;
+text/html ;
+text/html;charset="utf-8
+text/html;charset="u\
+application
+application/ \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/obsolete/acronym-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/obsolete/acronym-novalid.html
new file mode 100644
index 00000000000..c00eff544c3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/obsolete/acronym-novalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>the "acronym" element is obsolete</title>
+<meta charset=utf-8>
+</head>
+<body>
+<acronym>baz</acronym>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/obsolete/applet-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/obsolete/applet-novalid.html
new file mode 100644
index 00000000000..94bb0165dfc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/obsolete/applet-novalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>the "applet" element is obsolete</title>
+<meta charset=utf-8>
+</head>
+<body>
+<applet>baz</applet>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/obsolete/basefont-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/obsolete/basefont-novalid.html
new file mode 100644
index 00000000000..7f329d5cac7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/obsolete/basefont-novalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>the "basefont" element is obsolete</title>
+<meta charset=utf-8>
+</head>
+<body>
+<basefont>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/obsolete/big-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/obsolete/big-novalid.html
new file mode 100644
index 00000000000..90868cc89eb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/obsolete/big-novalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>the "big" element is obsolete</title>
+<meta charset=utf-8>
+</head>
+<body>
+<big>baz</big>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/obsolete/center-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/obsolete/center-novalid.html
new file mode 100644
index 00000000000..83d3cc28d19
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/obsolete/center-novalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>the "center" element is obsolete</title>
+<meta charset=utf-8>
+</head>
+<body>
+<center>baz</center>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/obsolete/dir-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/obsolete/dir-novalid.html
new file mode 100644
index 00000000000..072f1c61965
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/obsolete/dir-novalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>the "dir" element is obsolete</title>
+<meta charset=utf-8>
+</head>
+<body>
+<dir></dir>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/obsolete/font-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/obsolete/font-novalid.html
new file mode 100644
index 00000000000..450f27ad49c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/obsolete/font-novalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>the "font" element is obsolete</title>
+<meta charset=utf-8>
+</head>
+<body>
+<font>baz</font>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/obsolete/frameset-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/obsolete/frameset-novalid.html
new file mode 100644
index 00000000000..d7de332feed
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/obsolete/frameset-novalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>the "frameset" element is obsolete</title>
+<meta charset=utf-8>
+</head>
+<frameset>
+<frame src="url">
+<frame src="url2">
+</frameset>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/obsolete/noframes-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/obsolete/noframes-novalid.html
new file mode 100644
index 00000000000..84699e67b31
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/obsolete/noframes-novalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>the "noframes" element is obsolete</title>
+<meta charset=utf-8>
+</head>
+<body>
+<noframes>baz</noframes>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/obsolete/profile-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/obsolete/profile-novalid.html
new file mode 100644
index 00000000000..6b4a4f39e86
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/obsolete/profile-novalid.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head profile="http://www.w3.org/2006/03/hcard http://dublincore.org/documents/2008/08/04/dc-html/">
+<title>the profile attribute on the head element is obsolete</title>
+<meta charset=utf-8>
+</head>
+<body>
+<p>This page contains a <code>head</code> element with an obsolete
+<code>profile</code> attribute. It should trigger a validation error.</p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/obsolete/strike-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/obsolete/strike-novalid.html
new file mode 100644
index 00000000000..0a4c770468b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/obsolete/strike-novalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>the "strike" element is obsolete</title>
+<meta charset=utf-8>
+</head>
+<body>
+<strike>baz</strike>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/obsolete/tt-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/obsolete/tt-novalid.html
new file mode 100644
index 00000000000..ee4942dccb0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/obsolete/tt-novalid.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>the "tt" element is obsolete</title>
+<meta charset=utf-8>
+</head>
+<body>
+<tt>baz</tt>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/other/applet-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/other/applet-novalid.html
new file mode 100644
index 00000000000..5b0c8de3433
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/other/applet-novalid.html
@@ -0,0 +1,108 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;applet&gt;</title>
+</head>
+<body>
+
+ <!-- is structured inline -->
+ <p><applet
+ archive="uri1,uri2"
+ code="foo"
+ codebase="uri"
+ height="40"
+ width="40"
+ name="sth"
+ class="class"
+ lang="en"></applet></p>
+
+ <!-- is strictly inline -->
+ <p><dfn><applet
+ archive="uri1,uri2"
+ code="foo"
+ codebase="uri"
+ height="40"
+ width="40"
+ name="sth"
+ class="class"
+ lang="en"></applet></dfn></p>
+
+ <!-- is block -->
+ <applet
+ archive="uri1,uri2"
+ code="foo"
+ codebase="uri"
+ height="40"
+ width="40"
+ name="sth"
+ class="class"
+ lang="en"></applet>
+
+ <!-- can contain inline while in inline context, but param must come first -->
+ <p>paragraph
+ <applet code="foo" width="10" height="10">
+ <em>some</em> <ul><li>inline</li></ul> content
+ </applet>
+ </p>
+ <p>paragraph
+ <applet code="foo" width="10" height="10">
+ <param name="foo"><param name="bar">
+ <em>some</em> <ul><li>inline</li></ul> content
+ </applet>
+ </p>
+
+ <!-- can contain strictly inline while in strictly inline context, but param must come first -->
+ <p><dfn>strictly inline
+ <applet code="foo" width="10" height="10">
+ <em>text</em>
+ </applet>
+ </dfn></p>
+ <p><dfn>strictly inline
+ <applet code="foo" width="10" height="10">
+ <param name="foo"><param name="bar">
+ <em>text</em>
+ </applet>
+ </dfn></p>
+
+ <!-- can contain blocks while in block context, but param must come first -->
+ <applet code="foo" width="10" height="10">
+ <p>text</p>
+ </applet>
+ <applet code="foo" width="10" height="10">
+ <param name="foo"><param name="bar">
+ <p>text</p>
+ </applet>
+
+ <!-- can contain interactive if ancestor does not forbid it, but param must come first -->
+ <p>paragraph
+ <applet code="foo" width="10" height="10">
+ <a>link</a>
+ </applet>
+ </p>
+ <p>paragraph
+ <applet code="foo" width="10" height="10">
+ <param name="foo"><param name="bar">
+ <a>link</a>
+ </applet>
+ </p>
+ <p><dfn>strictly inline
+ <applet code="foo" width="10" height="10">
+ <a>link</a>
+ </applet>
+ </dfn></p>
+ <p><dfn>strictly inline
+ <applet code="foo" width="10" height="10">
+ <param name="foo"><param name="bar">
+ <a>link</a>
+ </applet>
+ </dfn></p>
+ <applet code="foo" width="10" height="10">
+ <p><a>link</a></p>
+ </applet>
+ <applet code="foo" width="10" height="10">
+ <param name="foo"><param name="bar">
+ <p><a>link</a></p>
+ </applet>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/other/obj-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/other/obj-novalid.html
new file mode 100644
index 00000000000..178b7d259e3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/other/obj-novalid.html
@@ -0,0 +1,123 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>&lt;obj&gt;</title>
+</head>
+<body>
+
+ <!-- is structured inline -->
+ <p><obj
+ archive="uri1 uri2"
+ classid="uri"
+ codebase="uri"
+ codetype="application/octet-stream"
+ data="uri"
+ height="40"
+ name="sth"
+ standby="text"
+ type="application/octet-stream"
+ usemap="uri"
+ width="40"
+ class="class"
+ lang="en"></obj></p>
+
+ <!-- is strictly inline -->
+ <p><dfn><obj
+ archive="uri1 uri2"
+ classid="uri"
+ codebase="uri"
+ codetype="application/octet-stream"
+ data="uri"
+ height="40"
+ name="sth"
+ standby="text"
+ type="application/octet-stream"
+ usemap="uri"
+ width="40"
+ class="class"
+ lang="en"></obj></dfn></p>
+
+ <!-- is block -->
+ <obj
+ archive="uri1 uri2"
+ classid="uri"
+ codebase="uri"
+ codetype="application/octet-stream"
+ data="uri"
+ height="40"
+ name="sth"
+ standby="text"
+ type="application/octet-stream"
+ usemap="uri"
+ width="40"
+ class="class"
+ lang="en"></obj>
+
+ <!-- can contain inline while in inline context, but param must come first -->
+ <p>paragraph
+ <obj>
+ <em>some</em> <ul><li>inline</li></ul> content
+ </obj>
+ </p>
+ <p>paragraph
+ <obj>
+ <param name="foo"><param name="bar">
+ <em>some</em> <ul><li>inline</li></ul> content
+ </obj>
+ </p>
+
+ <!-- can contain strictly inline while in strictly inline context, but param must come first -->
+ <p><dfn>strictly inline
+ <obj>
+ <em>text</em>
+ </obj>
+ </dfn></p>
+ <p><dfn>strictly inline
+ <obj>
+ <param name="foo"><param name="bar">
+ <em>text</em>
+ </obj>
+ </dfn></p>
+
+ <!-- can contain blocks while in block context, but param must come first -->
+ <obj>
+ <p>text</p>
+ </obj>
+ <obj>
+ <param name="foo"><param name="bar">
+ <p>text</p>
+ </obj>
+
+ <!-- can contain interactive if ancestor does not forbid it, but param must come first -->
+ <p>paragraph
+ <obj>
+ <a>link</a>
+ </obj>
+ </p>
+ <p>paragraph
+ <obj>
+ <param name="foo"><param name="bar">
+ <a>link</a>
+ </obj>
+ </p>
+ <p><dfn>strictly inline
+ <obj>
+ <a>link</a>
+ </obj>
+ </dfn></p>
+ <p><dfn>strictly inline
+ <obj>
+ <param name="foo"><param name="bar">
+ <a>link</a>
+ </obj>
+ </dfn></p>
+ <obj>
+ <p><a>link</a></p>
+ </obj>
+ <obj>
+ <param name="foo"><param name="bar">
+ <p><a>link</a></p>
+ </obj>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/parser/cr-charref-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/parser/cr-charref-novalid.html
new file mode 100644
index 00000000000..d517ec011cc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/parser/cr-charref-novalid.html
@@ -0,0 +1 @@
+<!doctype html><meta charset=utf-8><title>&amp;#x0d;</title><p>There should be an error.&#x0d;
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/parser/range-charref-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/parser/range-charref-novalid.html
new file mode 100644
index 00000000000..304b25fb95a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/parser/range-charref-novalid.html
@@ -0,0 +1 @@
+<!doctype html><meta charset=utf-8><title>&amp;#x110000;</title><p>There should be an error.&#x110000;
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/parser/u000b-charref-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/parser/u000b-charref-novalid.html
new file mode 100644
index 00000000000..c31ade018d6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/parser/u000b-charref-novalid.html
@@ -0,0 +1 @@
+<!doctype html><meta charset=utf-8><title>&amp;#x000B;</title><p>There should be an error.&#x000B;
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/parser/u000b-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/parser/u000b-novalid.html
new file mode 100644
index 00000000000..d35d7ca34c1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/parser/u000b-novalid.html
@@ -0,0 +1 @@
+<!doctype html><meta charset=utf-8><title>U+000B</title><p>There should be an error.
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/parser/u007f-charref-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/parser/u007f-charref-novalid.html
new file mode 100644
index 00000000000..1dba4b5d27c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/parser/u007f-charref-novalid.html
@@ -0,0 +1 @@
+<!doctype html><meta charset=utf-8><title>&amp;#x007F;</title><p>There should be an error.&#x007F;
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/parser/u10ffff-charref-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/parser/u10ffff-charref-novalid.html
new file mode 100644
index 00000000000..f823390a000
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/parser/u10ffff-charref-novalid.html
@@ -0,0 +1 @@
+<!doctype html><meta charset=utf-8><title>&amp;#x10FFFF;</title><p>There should be an error.&#x10FFFF;
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/parser/ufffe-charref-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/parser/ufffe-charref-novalid.html
new file mode 100644
index 00000000000..0ddab4a4222
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/parser/ufffe-charref-novalid.html
@@ -0,0 +1 @@
+<!doctype html><meta charset=utf-8><title>&amp;#xFFFE;</title><p>There should be an error.&#xFFFE;
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/html/parser/unassigned-charref-novalid.html b/tests/wpt/web-platform-tests/conformance-checkers/html/parser/unassigned-charref-novalid.html
new file mode 100644
index 00000000000..4e4c7489817
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/html/parser/unassigned-charref-novalid.html
@@ -0,0 +1 @@
+<!doctype html><meta charset=utf-8><title>&amp;#xfdd0;</title><p>There should be an error.&#xfdd0;
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/index.html b/tests/wpt/web-platform-tests/conformance-checkers/index.html
new file mode 100644
index 00000000000..2dadc40cf1f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/index.html
@@ -0,0 +1,113 @@
+<!doctype html><html><head><meta charset=utf-8>
+<title>WPT conformance-checker tests</title></head>
+<body>
+ <h1>WPT conformance-checker tests</h1>
+
+<p>The files in this part of the tree are not browser tests; they're
+ documents intended for testing the behavior of conformance checkers
+ (e.g., validator.nu and the W3C Nu Markup Validator).
+
+ <div class=set>
+ <p>TK: We should have here some details about the contents of the
+ existing subdirectories in this tree...
+ </div>
+
+<p>Curious committers should see the makefile.
+
+<style type="text/css">
+html {
+ background: #DDE5D9 url(data:image/gif;base64,R0lGODlhBAAEAIAAANra2v///yH5BAAAAAAALAAAAAAEAAQAAAIFTGB4xlcAOw==) repeat 0 0;
+ font-family: "Lucida Sans Unicode", "Lucida Sans", verdana, arial, helvetica;
+}
+body {
+ border: solid 1px #CED4CA;
+ background-color: #FFF;
+ padding: 4px 25px 4px 25px;
+ margin: 20px 20% 20px 20px;
+ line-height: 1.75;
+}
+h1 {
+ font-size: 36px;
+ font-weight: normal;
+ color: #0B5B9D;
+ vertical-align: top;
+ margin-bottom: 0px;
+}
+h2 {
+ font-size: 28px;
+ font-weight: normal;
+ color: #0B5B9D;
+ vertical-align: top;
+ margin-bottom: 0px;
+ margin-top: 24px;
+}
+h3 {
+ font-size: 22px;
+ font-weight: normal;
+ color: #0B5B9D;
+ vertical-align: top;
+ margin-bottom: 0px;
+ margin-top: 32px;
+}
+h4 {
+ font-size: 20px;
+ font-weight: normal;
+ color: #0B5B9D;
+ vertical-align: top;
+ margin-bottom: 0px;
+ margin-top: 22px;
+}
+a {
+ text-decoration: none;
+ color: #0B5B9D;
+ padding: 2px;
+}
+
+a:hover {
+ text-decoration: none;
+ background-color: #0B5B9D;
+ color: white;
+}
+a:active {
+ text-decoration: none;
+ background-color: white;
+ color: black;
+}
+.set, .note {
+ background-color: ivory;
+ padding: 16px;
+ padding-top: 4px;
+ padding-bottom: 4px;
+ padding-right: 32px;
+ padding-left: 32px;
+ border: 1px solid #ccc;
+ margin-left: 2px;
+ margin-right: 2px;
+ border-radius: 6px;
+}
+code {
+ background-color: #F8F8F8;
+ border: 1px solid #ccc;
+ border-radius: 3px;
+ padding: 2px 6px;
+}
+pre {
+ background-color: #F8F8F8;
+ border: 1px solid #ccc;
+ border-radius: 3px;
+ padding: 10px;
+ margin-right: 15%;
+ margin-top: 6px;
+ line-height: 1.2
+}
+.java-class, .java-property, .option-value {
+ background-color: yellow;
+ padding: 2px 6px;
+}
+.arg {
+ color: green;
+}
+.links {
+ text-align: center;
+}
+</style>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/messages.json b/tests/wpt/web-platform-tests/conformance-checkers/messages.json
new file mode 100644
index 00000000000..71c5f3ca5c5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/messages.json
@@ -0,0 +1,2403 @@
+{
+ "html-rdfa/0019-novalid.html": "Attribute \u201chref\u201d not allowed on element \u201cdiv\u201d in this context.",
+ "html-rdfa/0035-novalid.html": "Attribute \u201chref\u201d not allowed on element \u201cimg\u201d in this context.",
+ "html-rdfa/0037-novalid.html": "Attribute \u201chref\u201d not allowed on element \u201cimg\u201d in this context.",
+ "html-rdfa/0039-novalid.html": "Attribute \u201chref\u201d not allowed on element \u201cimg\u201d in this context.",
+ "html-rdfa/0041-novalid.html": "Attribute \u201chref\u201d not allowed on element \u201cimg\u201d in this context.",
+ "html-rdfa/0079-novalid.html": "Attribute \u201chref\u201d not allowed on element \u201cp\u201d in this context.",
+ "html-rdfa/0085-novalid.html": "Attribute \u201chref\u201d not allowed on element \u201cp\u201d in this context.",
+ "html-rdfa/0109-novalid.html": "Attribute \u201cxml:base\u201d not allowed on element \u201chtml\u201d in this context.",
+ "html-rdfa/0131-novalid.html": "A numeric character reference expanded to carriage return.",
+ "html-rdfa/0147-novalid.html": "Attribute \u201cxmlns:xmlzzz\u201d not allowed here.",
+ "html-rdfa/0179-novalid.html": "Attribute \u201cxmlns:foaf\u201d not allowed here.",
+ "html-rdfa/0180-novalid.html": "Bad value \u201c: http://xmlns.com/foaf/0.1/\u201d for attribute \u201cprefix\u201d on element \u201cdiv\u201d.",
+ "html-rdfa/0183-novalid.html": "Attribute \u201cxmlns:foaf\u201d not allowed here.",
+ "html-rdfa/0222-novalid.html": "Element \u201cp\u201d not allowed in this context. (The parent was element \u201cstrong\u201d.) Suppressing further errors from this subtree.",
+ "html-rdfa/0223-novalid.html": "Element \u201cp\u201d not allowed in this context. (The parent was element \u201cstrong\u201d.) Suppressing further errors from this subtree.",
+ "html-rdfa/0226-novalid.html": "Element \u201cp\u201d not allowed in this context. (The parent was element \u201cspan\u201d.) Suppressing further errors from this subtree.",
+ "html-rdfa/0227-novalid.html": "Element \u201cp\u201d not allowed in this context. (The parent was element \u201cspan\u201d.) Suppressing further errors from this subtree.",
+ "html-rdfa/0230-novalid.html": "Attribute \u201chref\u201d not allowed on element \u201cimg\u201d in this context.",
+ "html-rdfa/0234-novalid.html": "Bad value \u201cdescribedby\u201d for attribute \u201crel\u201d on element \u201ca\u201d: Bad list of link-type keywords: The string \u201cdescribedby\u201d is not a registered keyword.",
+ "html-rdfa/0237-novalid.html": "Bad value \u201c$malformed http://example.com\u201d for attribute \u201cprefix\u201d on element \u201cbody\u201d.",
+ "html-rdfa/0258-novalid.html": "Attribute \u201cxmlns:_\u201d not allowed here.",
+ "html-rdfa/0280-novalid.html": "Bad value \u201cP2011Y06M28DT00H00M00S\u201d for attribute \u201cdatetime\u201d on element \u201ctime\u201d: Bad time-datetime: The literal did not satisfy the time-datetime format.",
+ "html-rdfa/0285-novalid.html": "Bad value \u201cD-Day\u201d for attribute \u201cdatetime\u201d on element \u201ctime\u201d: Bad time-datetime: The literal did not satisfy the time-datetime format.",
+ "html-rdfa/0303-novalid.html": "Bad value \u201chomepage foaf:homepage\u201d for attribute \u201crel\u201d on element \u201ca\u201d: Bad list of link-type keywords: The string \u201chomepage\u201d is not a registered keyword.",
+ "html-rdfa/0308-novalid.html": "Bad value \u201chttp://www.example.com/roles/somerole\u201d for attribute \u201crole\u201d on element \u201cdiv\u201d.",
+ "html-rdfa/0309-novalid.html": "Bad value \u201cex:somerole\u201d for attribute \u201crole\u201d on element \u201cdiv\u201d.",
+ "html-rdfa/0310-novalid.html": "Bad value \u201cex:somerole someOtherRole http://www.example.com/alternate/role\u201d for attribute \u201crole\u201d on element \u201cdiv\u201d.",
+ "html-rdfa/0314-novalid.html": "Bad value \u201csection\u201d for attribute \u201crole\u201d on element \u201cdiv\u201d.",
+ "html-rdfa/0319-novalid.html": "Attribute \u201cxmlns:xpr\u201d not allowed here.",
+ "html-rdfa/0320-novalid.html": "Attribute \u201csrc\u201d not allowed on element \u201ca\u201d in this context.",
+ "html-rdfalite/0015-novalid.html": "Bad value \u201cdc:source\u201d for attribute \u201crel\u201d on element \u201clink\u201d: Bad list of link-type keywords: The string \u201cdc:source\u201d is not a registered keyword.",
+ "html-rdfalite/0030-novalid.html": "Bad value \u201ccc:license\u201d for attribute \u201crel\u201d on element \u201ca\u201d: Bad list of link-type keywords: The string \u201ccc:license\u201d is not a registered keyword.",
+ "html-rdfalite/0071-novalid.html": "Bad value \u201ccc:license\u201d for attribute \u201crel\u201d on element \u201ca\u201d: Bad list of link-type keywords: The string \u201ccc:license\u201d is not a registered keyword.",
+ "html-rdfalite/0074-novalid.html": "Bad value \u201cdc:creator\u201d for attribute \u201crel\u201d on element \u201ca\u201d: Bad list of link-type keywords: The string \u201cdc:creator\u201d is not a registered keyword.",
+ "html-rdfalite/0147.novalid.html": "Attribute \u201cxmlns:xmlzzz\u201d not allowed here.",
+ "html-rdfalite/0319-novalid.html": "Attribute \u201cxmlns:xpr\u201d not allowed here.",
+ "html/attributes/accesskey/duplicate-key-labels-novalid.html": "Bad value \u201ca b \u306c c \u306c\u201d for attribute \u201caccesskey\u201d on element \u201ca\u201d: Bad key label list: Duplicate key label. Each key label must be unique.",
+ "html/attributes/accesskey/multi-character-key-label-novalid.html": "Bad value \u201ca b \u307b\u3052\u201d for attribute \u201caccesskey\u201d on element \u201ca\u201d: Bad key label list: Key label has multiple characters. Each key label must be a single character.",
+ "html/attributes/data/no-characters-after-hyphen-novalid.html": "Attribute \u201cdata-\u201d not allowed on element \u201cp\u201d in this context.",
+ "html/attributes/data/not-xml-serializable-novalid.html": "\u201cdata-*\u201d attribute names must be XML 1.0 4th ed. plus Namespaces NCNames.",
+ "html/attributes/lang/deprecated-tag-haswarn.html": "Bad value \u201cmo\u201d for attribute \u201clang\u201d on element \u201cbody\u201d: Bad language tag: The language subtag \u201cmo\u201d is deprecated. Use \u201cro\u201d instead.",
+ "html/attributes/lang/extlang-bad-novalid.html": "Bad value \u201cbat-smg\u201d for attribute \u201clang\u201d on element \u201cbody\u201d: Bad language tag: Bad extlang subtag \u201csmg\u201d.",
+ "html/attributes/lang/xmllang-different-value-novalid.html": "When the attribute \u201cxml:lang\u201d in no namespace is specified, the element must also have the attribute \u201clang\u201d present with the same value.",
+ "html/attributes/lang/xmllang-only-novalid.html": "When the attribute \u201cxml:lang\u201d in no namespace is specified, the element must also have the attribute \u201clang\u201d present with the same value.",
+ "html/attributes/role/unrecognized-role-name-novalid.html": "Discarding unrecognized tokens \u201cswitch\u201d, \u201cinput\u201d from value of attribute \u201crole\u201d. Browsers ignore any token that is not a defined ARIA non-abstract role.",
+ "html/attributes/spellcheck/value-bad-novalid.html": "Bad value \u201cbadvalue\u201d for attribute \u201cspellcheck\u201d on element \u201cp\u201d.",
+ "html/elements/a/href/fragment-backslash-novalid.html": "Bad value \u201c#\\\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/a/href/fragment-contains-hash-novalid.html": "Bad value \u201chttp://foo/path#f#g\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/a/href/fragment-leading-space-novalid.html": "Bad value \u201chttp://f:21/b# e\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/a/href/host-cr-novalid.html": "Bad value \u201chttp://example.\norg\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/a/href/host-double-percent-encoded-novalid.html": "Bad value \u201chttp://\uff05\uff14\uff11.com\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/a/href/host-double-percent-encoded-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%bc%85%ef%bc%94%ef%bc%91.com\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/a/href/host-empty-novalid.html": "Bad value \u201chttp://\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/a/href/host-empty-userinfo-empty-novalid.html": "Bad value \u201chttp://@/www.example.com\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/a/href/host-empty-with-userinfo-novalid.html": "Bad value \u201chttp://user:pass@/\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/a/href/host-hostname-in-brackets-novalid.html": "Bad value \u201chttp://[www.google.com]/\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Invalid host: Illegal character.",
+ "html/elements/a/href/host-invalid-unicode-novalid.html": "Forbidden code point U+fdd0.",
+ "html/elements/a/href/host-invalid-unicode-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%b7%90zyx.com\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Invalid host: A label or domain name contains disallowed characters..",
+ "html/elements/a/href/host-newline-novalid.html": "Bad value \u201chttp://example.\norg\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/a/href/host-space-novalid.html": "Bad value \u201chttp://example .org\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Invalid host: Domain contains invalid character: .",
+ "html/elements/a/href/host-square-brackets-port-contains-colon-novalid.html": "Bad value \u201chttp://[1::2]:3:4\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Illegal character in port.",
+ "html/elements/a/href/host-tab-novalid.html": "Bad value \u201chttp://example\t.org\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/a/href/host-u0000-percent-encoded-novalid.html": "Bad value \u201chttp://\uff05\uff10\uff10.com\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/a/href/host-u0000-percent-encoded-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%bc%85%ef%bc%90%ef%bc%90.com\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/a/href/path-bare-percent-sign-novalid.html": "Bad value \u201chttp://example.com/foo%\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Percentage (\"%\") is not followed by two hexadecimal digits.",
+ "html/elements/a/href/path-contains-space-novalid.html": "Bad value \u201c/a/ /c\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/a/href/path-leading-backslash-at-sign-novalid.html": "Bad value \u201chttp://foo.com/\\@\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/a/href/path-leading-colon-backslash-novalid.html": "Bad value \u201c:\\\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/a/href/path-leading-colon-chars-backslash-novalid.html": "Bad value \u201c:foo.com\\\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/a/href/path-leading-space-novalid.html": "Bad value \u201chttp://f:21/ b\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/a/href/path-percent-encoded-malformed-novalid.html": "Bad value \u201chttp://example.com/foo/%2e%2\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Percentage (\"%\") is not followed by two hexadecimal digits.",
+ "html/elements/a/href/path-relative-square-brackets-novalid.html": "Bad value \u201c[61:24:74]:98\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/a/href/path-tab-novalid.html": "Bad value \u201chttp://example.com/foo\tbar\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/a/href/path-trailing-space-novalid.html": "Bad value \u201chttp://f:21/b ?\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/a/href/path-u0091-novalid.html": "Forbidden code point U+0091.",
+ "html/elements/a/href/port-cr-novalid.html": "Bad value \u201chttp://f:\n/c\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/a/href/port-leading-colon-bracket-colon-novalid.html": "Bad value \u201chttp://2001::1]:80\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Illegal character in port.",
+ "html/elements/a/href/port-leading-colon-novalid.html": "Bad value \u201chttp://2001::1\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Illegal character in port.",
+ "html/elements/a/href/port-leading-dash-novalid.html": "Bad value \u201chttp://foo:-80/\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Illegal character in port.",
+ "html/elements/a/href/port-multiple-letters-novalid.html": "Bad value \u201chttp://f:fifty-two/c\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Illegal character in port.",
+ "html/elements/a/href/port-newline-novalid.html": "Bad value \u201chttp://f:\n/c\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/a/href/port-single-letter-novalid.html": "Bad value \u201chttp://f:b/c\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Illegal character in port.",
+ "html/elements/a/href/port-space-novalid.html": "Bad value \u201chttp://f: /c\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Illegal character in port.",
+ "html/elements/a/href/port-tab-novalid.html": "Bad value \u201chttp://f:\t/c\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/a/href/query-leading-space-novalid.html": "Bad value \u201chttp://f:21/b? d\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Illegal character in query: not a URL code point.",
+ "html/elements/a/href/query-trailing-space-novalid.html": "Bad value \u201chttp://f:21/b?d #\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Illegal character in query: not a URL code point.",
+ "html/elements/a/href/scheme-data-contains-fragment-haswarn.html": "Bad value \u201cdata:text/html,test#test\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Fragment is not allowed for data: URIs according to RFC 2397.",
+ "html/elements/a/href/scheme-data-single-slash-novalid.html": "Bad value \u201cdata:/example.com/\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Expected a token character or a semicolon but saw \u201c/\u201d instead.",
+ "html/elements/a/href/scheme-file-backslash-novalid.html": "Bad value \u201cfile:c:\\foo\\bar.html\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/a/href/scheme-file-single-slash-c-bar-novalid.html": "Bad value \u201cfile:/C|/foo/bar\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/a/href/scheme-file-triple-slash-c-bar-novalid.html": "Bad value \u201cfile:///C|/foo/bar\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/a/href/scheme-ftp-no-slash-novalid.html": "Bad value \u201cftp:example.com/\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/a/href/scheme-ftp-single-slash-novalid.html": "Bad value \u201cftp:/example.com/\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/a/href/scheme-http-backslash-novalid.html": "Bad value \u201chttp:\\\\foo.com\\\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/a/href/scheme-http-no-slash-colon-novalid.html": "Bad value \u201chttp::@c:29\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/a/href/scheme-http-no-slash-novalid.html": "Bad value \u201chttp:foo.com\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/a/href/scheme-http-no-slash-square-bracket-novalid.html": "Bad value \u201chttp:[61:27]/:foo\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/a/href/scheme-http-single-slash-novalid.html": "Bad value \u201chttp:/example.com/\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/a/href/scheme-https-no-slash-novalid.html": "Bad value \u201chttps:example.com/\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/a/href/scheme-https-single-slash-novalid.html": "Bad value \u201chttps:/example.com/\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/a/href/scheme-javascript-no-slash-malformed-novalid.html": "Bad value \u201cjavascript:example.com/\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: syntax error",
+ "html/elements/a/href/scheme-trailing-cr-novalid.html": "Bad value \u201ca:\nfoo.com\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/a/href/scheme-trailing-newline-novalid.html": "Bad value \u201ca:\nfoo.com\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/a/href/scheme-trailing-space-novalid.html": "Bad value \u201ca: foo.com\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/a/href/scheme-trailing-tab-novalid.html": "Bad value \u201ca:\tfoo.com\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/a/href/userinfo-backslash-novalid.html": "Bad value \u201chttp://a\\b:c\\d@foo.com\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/a/href/userinfo-password-bad-chars-novalid.html": "\u201c&\u201d did not start a character reference. (\u201c&\u201d probably should have been escaped as \u201c&amp;\u201d.)",
+ "html/elements/a/href/userinfo-password-contains-pile-of-poo-novalid.html": "Bad value \u201chttp://foo:\ud83d\udca9@example.com\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Illegal character in user or password: not a URL code point.",
+ "html/elements/a/href/userinfo-username-contains-at-sign-novalid.html": "Bad value \u201chttp://::@c@d:2\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: User or password contains an at symbol (\"@\") not percent-encoded.",
+ "html/elements/a/href/userinfo-username-contains-pile-of-poo-novalid.html": "Bad value \u201chttp://\ud83d\udca9:foo@example.com\u201d for attribute \u201chref\u201d on element \u201ca\u201d: Bad URL: Illegal character in user or password: not a URL code point.",
+ "html/elements/a/media-novalid.html": "Attribute \u201cmedia\u201d not allowed on element \u201ca\u201d in this context.",
+ "html/elements/a/model-novalid.html": "Element \u201cp\u201d not allowed in this context. (The parent was element \u201ca\u201d.) Suppressing further errors from this subtree.",
+ "html/elements/a/name-empty-novalid.html": "Bad value \u201c\u201d for attribute \u201cname\u201d on element \u201ca\u201d: Bad id: An ID must not be the empty string.",
+ "html/elements/abbr/model-novalid.html": "End tag \u201cp\u201d implied, but there were open elements.",
+ "html/elements/address/model-novalid.html": "The element \u201caddress\u201d must not appear as a descendant of the \u201caddress\u201d element.",
+ "html/elements/area/href/fragment-backslash-novalid.html": "Bad value \u201c#\\\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/area/href/fragment-contains-hash-novalid.html": "Bad value \u201chttp://foo/path#f#g\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/area/href/fragment-leading-space-novalid.html": "Bad value \u201chttp://f:21/b# e\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/area/href/host-cr-novalid.html": "Bad value \u201chttp://example.\norg\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/area/href/host-double-percent-encoded-novalid.html": "Bad value \u201chttp://\uff05\uff14\uff11.com\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/area/href/host-double-percent-encoded-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%bc%85%ef%bc%94%ef%bc%91.com\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/area/href/host-empty-novalid.html": "Bad value \u201chttp://\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/area/href/host-empty-userinfo-empty-novalid.html": "Bad value \u201chttp://@/www.example.com\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/area/href/host-empty-with-userinfo-novalid.html": "Bad value \u201chttp://user:pass@/\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/area/href/host-hostname-in-brackets-novalid.html": "Bad value \u201chttp://[www.google.com]/\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Invalid host: Illegal character.",
+ "html/elements/area/href/host-invalid-unicode-novalid.html": "Forbidden code point U+fdd0.",
+ "html/elements/area/href/host-invalid-unicode-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%b7%90zyx.com\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Invalid host: A label or domain name contains disallowed characters..",
+ "html/elements/area/href/host-newline-novalid.html": "Bad value \u201chttp://example.\norg\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/area/href/host-space-novalid.html": "Bad value \u201chttp://example .org\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Invalid host: Domain contains invalid character: .",
+ "html/elements/area/href/host-square-brackets-port-contains-colon-novalid.html": "Bad value \u201chttp://[1::2]:3:4\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Illegal character in port.",
+ "html/elements/area/href/host-tab-novalid.html": "Bad value \u201chttp://example\t.org\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/area/href/host-u0000-percent-encoded-novalid.html": "Bad value \u201chttp://\uff05\uff10\uff10.com\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/area/href/host-u0000-percent-encoded-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%bc%85%ef%bc%90%ef%bc%90.com\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/area/href/path-bare-percent-sign-novalid.html": "Bad value \u201chttp://example.com/foo%\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Percentage (\"%\") is not followed by two hexadecimal digits.",
+ "html/elements/area/href/path-contains-space-novalid.html": "Bad value \u201c/a/ /c\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/area/href/path-leading-backslash-at-sign-novalid.html": "Bad value \u201chttp://foo.com/\\@\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/area/href/path-leading-colon-backslash-novalid.html": "Bad value \u201c:\\\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/area/href/path-leading-colon-chars-backslash-novalid.html": "Bad value \u201c:foo.com\\\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/area/href/path-leading-space-novalid.html": "Bad value \u201chttp://f:21/ b\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/area/href/path-percent-encoded-malformed-novalid.html": "Bad value \u201chttp://example.com/foo/%2e%2\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Percentage (\"%\") is not followed by two hexadecimal digits.",
+ "html/elements/area/href/path-relative-square-brackets-novalid.html": "Bad value \u201c[61:24:74]:98\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/area/href/path-tab-novalid.html": "Bad value \u201chttp://example.com/foo\tbar\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/area/href/path-trailing-space-novalid.html": "Bad value \u201chttp://f:21/b ?\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/area/href/path-u0091-novalid.html": "Forbidden code point U+0091.",
+ "html/elements/area/href/port-cr-novalid.html": "Bad value \u201chttp://f:\n/c\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/area/href/port-leading-colon-bracket-colon-novalid.html": "Bad value \u201chttp://2001::1]:80\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Illegal character in port.",
+ "html/elements/area/href/port-leading-colon-novalid.html": "Bad value \u201chttp://2001::1\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Illegal character in port.",
+ "html/elements/area/href/port-leading-dash-novalid.html": "Bad value \u201chttp://foo:-80/\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Illegal character in port.",
+ "html/elements/area/href/port-multiple-letters-novalid.html": "Bad value \u201chttp://f:fifty-two/c\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Illegal character in port.",
+ "html/elements/area/href/port-newline-novalid.html": "Bad value \u201chttp://f:\n/c\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/area/href/port-single-letter-novalid.html": "Bad value \u201chttp://f:b/c\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Illegal character in port.",
+ "html/elements/area/href/port-space-novalid.html": "Bad value \u201chttp://f: /c\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Illegal character in port.",
+ "html/elements/area/href/port-tab-novalid.html": "Bad value \u201chttp://f:\t/c\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/area/href/query-leading-space-novalid.html": "Bad value \u201chttp://f:21/b? d\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Illegal character in query: not a URL code point.",
+ "html/elements/area/href/query-trailing-space-novalid.html": "Bad value \u201chttp://f:21/b?d #\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Illegal character in query: not a URL code point.",
+ "html/elements/area/href/scheme-data-contains-fragment-haswarn.html": "Bad value \u201cdata:text/html,test#test\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Fragment is not allowed for data: URIs according to RFC 2397.",
+ "html/elements/area/href/scheme-data-single-slash-novalid.html": "Bad value \u201cdata:/example.com/\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Expected a token character or a semicolon but saw \u201c/\u201d instead.",
+ "html/elements/area/href/scheme-file-backslash-novalid.html": "Bad value \u201cfile:c:\\foo\\bar.html\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/area/href/scheme-file-single-slash-c-bar-novalid.html": "Bad value \u201cfile:/C|/foo/bar\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/area/href/scheme-file-triple-slash-c-bar-novalid.html": "Bad value \u201cfile:///C|/foo/bar\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/area/href/scheme-ftp-no-slash-novalid.html": "Bad value \u201cftp:example.com/\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/area/href/scheme-ftp-single-slash-novalid.html": "Bad value \u201cftp:/example.com/\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/area/href/scheme-http-backslash-novalid.html": "Bad value \u201chttp:\\\\foo.com\\\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/area/href/scheme-http-no-slash-colon-novalid.html": "Bad value \u201chttp::@c:29\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/area/href/scheme-http-no-slash-novalid.html": "Bad value \u201chttp:foo.com\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/area/href/scheme-http-no-slash-square-bracket-novalid.html": "Bad value \u201chttp:[61:27]/:foo\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/area/href/scheme-http-single-slash-novalid.html": "Bad value \u201chttp:/example.com/\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/area/href/scheme-https-no-slash-novalid.html": "Bad value \u201chttps:example.com/\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/area/href/scheme-https-single-slash-novalid.html": "Bad value \u201chttps:/example.com/\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/area/href/scheme-javascript-no-slash-malformed-novalid.html": "Bad value \u201cjavascript:example.com/\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: syntax error",
+ "html/elements/area/href/scheme-trailing-cr-novalid.html": "Bad value \u201ca:\nfoo.com\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/area/href/scheme-trailing-newline-novalid.html": "Bad value \u201ca:\nfoo.com\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/area/href/scheme-trailing-space-novalid.html": "Bad value \u201ca: foo.com\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/area/href/scheme-trailing-tab-novalid.html": "Bad value \u201ca:\tfoo.com\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/area/href/userinfo-backslash-novalid.html": "Bad value \u201chttp://a\\b:c\\d@foo.com\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/area/href/userinfo-password-bad-chars-novalid.html": "\u201c&\u201d did not start a character reference. (\u201c&\u201d probably should have been escaped as \u201c&amp;\u201d.)",
+ "html/elements/area/href/userinfo-password-contains-pile-of-poo-novalid.html": "Bad value \u201chttp://foo:\ud83d\udca9@example.com\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Illegal character in user or password: not a URL code point.",
+ "html/elements/area/href/userinfo-username-contains-at-sign-novalid.html": "Bad value \u201chttp://::@c@d:2\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: User or password contains an at symbol (\"@\") not percent-encoded.",
+ "html/elements/area/href/userinfo-username-contains-pile-of-poo-novalid.html": "Bad value \u201chttp://\ud83d\udca9:foo@example.com\u201d for attribute \u201chref\u201d on element \u201carea\u201d: Bad URL: Illegal character in user or password: not a URL code point.",
+ "html/elements/area/media-novalid.html": "Attribute \u201cmedia\u201d not allowed on element \u201carea\u201d in this context.",
+ "html/elements/area/model-novalid.html": "Attribute \u201ccoords\u201d not allowed on element \u201carea\u201d in this context.",
+ "html/elements/audio/model-novalid.html": "Element \u201cp\u201d not allowed in this context. (The parent was element \u201caudio\u201d.) Suppressing further errors from this subtree.",
+ "html/elements/audio/src-empty-novalid.html": "Bad value \u201c\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Must be non-empty.",
+ "html/elements/audio/src-whitespace-only-novalid.html": "Bad value \u201c\t \n\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Must be non-empty.",
+ "html/elements/audio/src/fragment-backslash-novalid.html": "Bad value \u201c#\\\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/audio/src/fragment-contains-hash-novalid.html": "Bad value \u201chttp://foo/path#f#g\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/audio/src/fragment-leading-space-novalid.html": "Bad value \u201chttp://f:21/b# e\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/audio/src/host-cr-novalid.html": "Bad value \u201chttp://example.\norg\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/audio/src/host-double-percent-encoded-novalid.html": "Bad value \u201chttp://\uff05\uff14\uff11.com\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/audio/src/host-double-percent-encoded-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%bc%85%ef%bc%94%ef%bc%91.com\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/audio/src/host-empty-novalid.html": "Bad value \u201chttp://\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/audio/src/host-empty-userinfo-empty-novalid.html": "Bad value \u201chttp://@/www.example.com\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/audio/src/host-empty-with-userinfo-novalid.html": "Bad value \u201chttp://user:pass@/\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/audio/src/host-hostname-in-brackets-novalid.html": "Bad value \u201chttp://[www.google.com]/\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Invalid host: Illegal character.",
+ "html/elements/audio/src/host-invalid-unicode-novalid.html": "Forbidden code point U+fdd0.",
+ "html/elements/audio/src/host-invalid-unicode-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%b7%90zyx.com\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Invalid host: A label or domain name contains disallowed characters..",
+ "html/elements/audio/src/host-newline-novalid.html": "Bad value \u201chttp://example.\norg\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/audio/src/host-space-novalid.html": "Bad value \u201chttp://example .org\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Invalid host: Domain contains invalid character: .",
+ "html/elements/audio/src/host-square-brackets-port-contains-colon-novalid.html": "Bad value \u201chttp://[1::2]:3:4\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Illegal character in port.",
+ "html/elements/audio/src/host-tab-novalid.html": "Bad value \u201chttp://example\t.org\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/audio/src/host-u0000-percent-encoded-novalid.html": "Bad value \u201chttp://\uff05\uff10\uff10.com\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/audio/src/host-u0000-percent-encoded-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%bc%85%ef%bc%90%ef%bc%90.com\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/audio/src/path-bare-percent-sign-novalid.html": "Bad value \u201chttp://example.com/foo%\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Percentage (\"%\") is not followed by two hexadecimal digits.",
+ "html/elements/audio/src/path-contains-space-novalid.html": "Bad value \u201c/a/ /c\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/audio/src/path-leading-backslash-at-sign-novalid.html": "Bad value \u201chttp://foo.com/\\@\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/audio/src/path-leading-colon-backslash-novalid.html": "Bad value \u201c:\\\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/audio/src/path-leading-colon-chars-backslash-novalid.html": "Bad value \u201c:foo.com\\\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/audio/src/path-leading-space-novalid.html": "Bad value \u201chttp://f:21/ b\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/audio/src/path-percent-encoded-malformed-novalid.html": "Bad value \u201chttp://example.com/foo/%2e%2\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Percentage (\"%\") is not followed by two hexadecimal digits.",
+ "html/elements/audio/src/path-relative-square-brackets-novalid.html": "Bad value \u201c[61:24:74]:98\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/audio/src/path-tab-novalid.html": "Bad value \u201chttp://example.com/foo\tbar\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/audio/src/path-trailing-space-novalid.html": "Bad value \u201chttp://f:21/b ?\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/audio/src/path-u0091-novalid.html": "Forbidden code point U+0091.",
+ "html/elements/audio/src/port-cr-novalid.html": "Bad value \u201chttp://f:\n/c\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/audio/src/port-leading-colon-bracket-colon-novalid.html": "Bad value \u201chttp://2001::1]:80\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Illegal character in port.",
+ "html/elements/audio/src/port-leading-colon-novalid.html": "Bad value \u201chttp://2001::1\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Illegal character in port.",
+ "html/elements/audio/src/port-leading-dash-novalid.html": "Bad value \u201chttp://foo:-80/\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Illegal character in port.",
+ "html/elements/audio/src/port-multiple-letters-novalid.html": "Bad value \u201chttp://f:fifty-two/c\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Illegal character in port.",
+ "html/elements/audio/src/port-newline-novalid.html": "Bad value \u201chttp://f:\n/c\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/audio/src/port-single-letter-novalid.html": "Bad value \u201chttp://f:b/c\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Illegal character in port.",
+ "html/elements/audio/src/port-space-novalid.html": "Bad value \u201chttp://f: /c\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Illegal character in port.",
+ "html/elements/audio/src/port-tab-novalid.html": "Bad value \u201chttp://f:\t/c\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/audio/src/query-leading-space-novalid.html": "Bad value \u201chttp://f:21/b? d\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Illegal character in query: not a URL code point.",
+ "html/elements/audio/src/query-trailing-space-novalid.html": "Bad value \u201chttp://f:21/b?d #\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Illegal character in query: not a URL code point.",
+ "html/elements/audio/src/scheme-data-contains-fragment-haswarn.html": "Bad value \u201cdata:text/html,test#test\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Fragment is not allowed for data: URIs according to RFC 2397.",
+ "html/elements/audio/src/scheme-data-single-slash-novalid.html": "Bad value \u201cdata:/example.com/\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Expected a token character or a semicolon but saw \u201c/\u201d instead.",
+ "html/elements/audio/src/scheme-file-backslash-novalid.html": "Bad value \u201cfile:c:\\foo\\bar.html\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/audio/src/scheme-file-single-slash-c-bar-novalid.html": "Bad value \u201cfile:/C|/foo/bar\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/audio/src/scheme-file-triple-slash-c-bar-novalid.html": "Bad value \u201cfile:///C|/foo/bar\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/audio/src/scheme-ftp-no-slash-novalid.html": "Bad value \u201cftp:example.com/\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/audio/src/scheme-ftp-single-slash-novalid.html": "Bad value \u201cftp:/example.com/\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/audio/src/scheme-http-backslash-novalid.html": "Bad value \u201chttp:\\\\foo.com\\\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/audio/src/scheme-http-no-slash-colon-novalid.html": "Bad value \u201chttp::@c:29\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/audio/src/scheme-http-no-slash-novalid.html": "Bad value \u201chttp:foo.com\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/audio/src/scheme-http-no-slash-square-bracket-novalid.html": "Bad value \u201chttp:[61:27]/:foo\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/audio/src/scheme-http-single-slash-novalid.html": "Bad value \u201chttp:/example.com/\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/audio/src/scheme-https-no-slash-novalid.html": "Bad value \u201chttps:example.com/\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/audio/src/scheme-https-single-slash-novalid.html": "Bad value \u201chttps:/example.com/\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/audio/src/scheme-javascript-no-slash-malformed-novalid.html": "Bad value \u201cjavascript:example.com/\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: syntax error",
+ "html/elements/audio/src/scheme-trailing-cr-novalid.html": "Bad value \u201ca:\nfoo.com\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/audio/src/scheme-trailing-newline-novalid.html": "Bad value \u201ca:\nfoo.com\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/audio/src/scheme-trailing-space-novalid.html": "Bad value \u201ca: foo.com\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/audio/src/scheme-trailing-tab-novalid.html": "Bad value \u201ca:\tfoo.com\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/audio/src/userinfo-backslash-novalid.html": "Bad value \u201chttp://a\\b:c\\d@foo.com\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/audio/src/userinfo-password-bad-chars-novalid.html": "\u201c&\u201d did not start a character reference. (\u201c&\u201d probably should have been escaped as \u201c&amp;\u201d.)",
+ "html/elements/audio/src/userinfo-password-contains-pile-of-poo-novalid.html": "Bad value \u201chttp://foo:\ud83d\udca9@example.com\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Illegal character in user or password: not a URL code point.",
+ "html/elements/audio/src/userinfo-username-contains-at-sign-novalid.html": "Bad value \u201chttp://::@c@d:2\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: User or password contains an at symbol (\"@\") not percent-encoded.",
+ "html/elements/audio/src/userinfo-username-contains-pile-of-poo-novalid.html": "Bad value \u201chttp://\ud83d\udca9:foo@example.com\u201d for attribute \u201csrc\u201d on element \u201caudio\u201d: Bad URL: Illegal character in user or password: not a URL code point.",
+ "html/elements/base/href-and-target-missing-novalid.html": "Element \u201cbase\u201d is missing one or more of the following attributes: [href, target].",
+ "html/elements/base/href/fragment-backslash-novalid.html": "Bad value \u201c#\\\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/base/href/fragment-contains-hash-novalid.html": "Bad value \u201chttp://foo/path#f#g\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/base/href/fragment-leading-space-novalid.html": "Bad value \u201chttp://f:21/b# e\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/base/href/host-cr-novalid.html": "Bad value \u201chttp://example.\norg\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/base/href/host-double-percent-encoded-novalid.html": "Bad value \u201chttp://\uff05\uff14\uff11.com\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/base/href/host-double-percent-encoded-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%bc%85%ef%bc%94%ef%bc%91.com\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/base/href/host-empty-novalid.html": "Bad value \u201chttp://\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/base/href/host-empty-userinfo-empty-novalid.html": "Bad value \u201chttp://@/www.example.com\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/base/href/host-empty-with-userinfo-novalid.html": "Bad value \u201chttp://user:pass@/\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/base/href/host-hostname-in-brackets-novalid.html": "Bad value \u201chttp://[www.google.com]/\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Invalid host: Illegal character.",
+ "html/elements/base/href/host-invalid-unicode-novalid.html": "Forbidden code point U+fdd0.",
+ "html/elements/base/href/host-invalid-unicode-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%b7%90zyx.com\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Invalid host: A label or domain name contains disallowed characters..",
+ "html/elements/base/href/host-newline-novalid.html": "Bad value \u201chttp://example.\norg\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/base/href/host-space-novalid.html": "Bad value \u201chttp://example .org\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Invalid host: Domain contains invalid character: .",
+ "html/elements/base/href/host-square-brackets-port-contains-colon-novalid.html": "Bad value \u201chttp://[1::2]:3:4\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Illegal character in port.",
+ "html/elements/base/href/host-tab-novalid.html": "Bad value \u201chttp://example\t.org\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/base/href/host-u0000-percent-encoded-novalid.html": "Bad value \u201chttp://\uff05\uff10\uff10.com\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/base/href/host-u0000-percent-encoded-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%bc%85%ef%bc%90%ef%bc%90.com\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/base/href/path-bare-percent-sign-novalid.html": "Bad value \u201chttp://example.com/foo%\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Percentage (\"%\") is not followed by two hexadecimal digits.",
+ "html/elements/base/href/path-contains-space-novalid.html": "Bad value \u201c/a/ /c\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/base/href/path-leading-backslash-at-sign-novalid.html": "Bad value \u201chttp://foo.com/\\@\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/base/href/path-leading-colon-backslash-novalid.html": "Bad value \u201c:\\\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/base/href/path-leading-colon-chars-backslash-novalid.html": "Bad value \u201c:foo.com\\\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/base/href/path-leading-space-novalid.html": "Bad value \u201chttp://f:21/ b\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/base/href/path-percent-encoded-malformed-novalid.html": "Bad value \u201chttp://example.com/foo/%2e%2\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Percentage (\"%\") is not followed by two hexadecimal digits.",
+ "html/elements/base/href/path-relative-square-brackets-novalid.html": "Bad value \u201c[61:24:74]:98\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/base/href/path-tab-novalid.html": "Bad value \u201chttp://example.com/foo\tbar\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/base/href/path-trailing-space-novalid.html": "Bad value \u201chttp://f:21/b ?\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/base/href/path-u0091-novalid.html": "Forbidden code point U+0091.",
+ "html/elements/base/href/port-cr-novalid.html": "Bad value \u201chttp://f:\n/c\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/base/href/port-leading-colon-bracket-colon-novalid.html": "Bad value \u201chttp://2001::1]:80\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Illegal character in port.",
+ "html/elements/base/href/port-leading-colon-novalid.html": "Bad value \u201chttp://2001::1\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Illegal character in port.",
+ "html/elements/base/href/port-leading-dash-novalid.html": "Bad value \u201chttp://foo:-80/\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Illegal character in port.",
+ "html/elements/base/href/port-multiple-letters-novalid.html": "Bad value \u201chttp://f:fifty-two/c\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Illegal character in port.",
+ "html/elements/base/href/port-newline-novalid.html": "Bad value \u201chttp://f:\n/c\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/base/href/port-single-letter-novalid.html": "Bad value \u201chttp://f:b/c\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Illegal character in port.",
+ "html/elements/base/href/port-space-novalid.html": "Bad value \u201chttp://f: /c\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Illegal character in port.",
+ "html/elements/base/href/port-tab-novalid.html": "Bad value \u201chttp://f:\t/c\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/base/href/query-leading-space-novalid.html": "Bad value \u201chttp://f:21/b? d\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Illegal character in query: not a URL code point.",
+ "html/elements/base/href/query-trailing-space-novalid.html": "Bad value \u201chttp://f:21/b?d #\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Illegal character in query: not a URL code point.",
+ "html/elements/base/href/scheme-data-contains-fragment-haswarn.html": "Bad value \u201cdata:text/html,test#test\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Fragment is not allowed for data: URIs according to RFC 2397.",
+ "html/elements/base/href/scheme-data-single-slash-novalid.html": "Bad value \u201cdata:/example.com/\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Expected a token character or a semicolon but saw \u201c/\u201d instead.",
+ "html/elements/base/href/scheme-file-backslash-novalid.html": "Bad value \u201cfile:c:\\foo\\bar.html\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/base/href/scheme-file-single-slash-c-bar-novalid.html": "Bad value \u201cfile:/C|/foo/bar\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/base/href/scheme-file-triple-slash-c-bar-novalid.html": "Bad value \u201cfile:///C|/foo/bar\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/base/href/scheme-ftp-no-slash-novalid.html": "Bad value \u201cftp:example.com/\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/base/href/scheme-ftp-single-slash-novalid.html": "Bad value \u201cftp:/example.com/\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/base/href/scheme-http-backslash-novalid.html": "Bad value \u201chttp:\\\\foo.com\\\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/base/href/scheme-http-no-slash-colon-novalid.html": "Bad value \u201chttp::@c:29\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/base/href/scheme-http-no-slash-novalid.html": "Bad value \u201chttp:foo.com\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/base/href/scheme-http-no-slash-square-bracket-novalid.html": "Bad value \u201chttp:[61:27]/:foo\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/base/href/scheme-http-single-slash-novalid.html": "Bad value \u201chttp:/example.com/\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/base/href/scheme-https-no-slash-novalid.html": "Bad value \u201chttps:example.com/\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/base/href/scheme-https-single-slash-novalid.html": "Bad value \u201chttps:/example.com/\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/base/href/scheme-javascript-no-slash-malformed-novalid.html": "Bad value \u201cjavascript:example.com/\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: syntax error",
+ "html/elements/base/href/scheme-trailing-cr-novalid.html": "Bad value \u201ca:\nfoo.com\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/base/href/scheme-trailing-newline-novalid.html": "Bad value \u201ca:\nfoo.com\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/base/href/scheme-trailing-space-novalid.html": "Bad value \u201ca: foo.com\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/base/href/scheme-trailing-tab-novalid.html": "Bad value \u201ca:\tfoo.com\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/base/href/userinfo-backslash-novalid.html": "Bad value \u201chttp://a\\b:c\\d@foo.com\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/base/href/userinfo-password-bad-chars-novalid.html": "\u201c&\u201d did not start a character reference. (\u201c&\u201d probably should have been escaped as \u201c&amp;\u201d.)",
+ "html/elements/base/href/userinfo-password-contains-pile-of-poo-novalid.html": "Bad value \u201chttp://foo:\ud83d\udca9@example.com\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Illegal character in user or password: not a URL code point.",
+ "html/elements/base/href/userinfo-username-contains-at-sign-novalid.html": "Bad value \u201chttp://::@c@d:2\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: User or password contains an at symbol (\"@\") not percent-encoded.",
+ "html/elements/base/href/userinfo-username-contains-pile-of-poo-novalid.html": "Bad value \u201chttp://\ud83d\udca9:foo@example.com\u201d for attribute \u201chref\u201d on element \u201cbase\u201d: Bad URL: Illegal character in user or password: not a URL code point.",
+ "html/elements/bdo/model-novalid.html": "Element \u201cbdo\u201d must have attribute \u201cdir\u201d.",
+ "html/elements/blockquote/cite/fragment-backslash-novalid.html": "Bad value \u201c#\\\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/blockquote/cite/fragment-contains-hash-novalid.html": "Bad value \u201chttp://foo/path#f#g\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/blockquote/cite/fragment-leading-space-novalid.html": "Bad value \u201chttp://f:21/b# e\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/blockquote/cite/host-cr-novalid.html": "Bad value \u201chttp://example.\norg\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/blockquote/cite/host-double-percent-encoded-novalid.html": "Bad value \u201chttp://\uff05\uff14\uff11.com\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/blockquote/cite/host-double-percent-encoded-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%bc%85%ef%bc%94%ef%bc%91.com\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/blockquote/cite/host-empty-novalid.html": "Bad value \u201chttp://\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/blockquote/cite/host-empty-userinfo-empty-novalid.html": "Bad value \u201chttp://@/www.example.com\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/blockquote/cite/host-empty-with-userinfo-novalid.html": "Bad value \u201chttp://user:pass@/\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/blockquote/cite/host-hostname-in-brackets-novalid.html": "Bad value \u201chttp://[www.google.com]/\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Invalid host: Illegal character.",
+ "html/elements/blockquote/cite/host-invalid-unicode-novalid.html": "Forbidden code point U+fdd0.",
+ "html/elements/blockquote/cite/host-invalid-unicode-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%b7%90zyx.com\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Invalid host: A label or domain name contains disallowed characters..",
+ "html/elements/blockquote/cite/host-newline-novalid.html": "Bad value \u201chttp://example.\norg\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/blockquote/cite/host-space-novalid.html": "Bad value \u201chttp://example .org\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Invalid host: Domain contains invalid character: .",
+ "html/elements/blockquote/cite/host-square-brackets-port-contains-colon-novalid.html": "Bad value \u201chttp://[1::2]:3:4\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Illegal character in port.",
+ "html/elements/blockquote/cite/host-tab-novalid.html": "Bad value \u201chttp://example\t.org\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/blockquote/cite/host-u0000-percent-encoded-novalid.html": "Bad value \u201chttp://\uff05\uff10\uff10.com\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/blockquote/cite/host-u0000-percent-encoded-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%bc%85%ef%bc%90%ef%bc%90.com\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/blockquote/cite/path-bare-percent-sign-novalid.html": "Bad value \u201chttp://example.com/foo%\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Percentage (\"%\") is not followed by two hexadecimal digits.",
+ "html/elements/blockquote/cite/path-contains-space-novalid.html": "Bad value \u201c/a/ /c\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/blockquote/cite/path-leading-backslash-at-sign-novalid.html": "Bad value \u201chttp://foo.com/\\@\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/blockquote/cite/path-leading-colon-backslash-novalid.html": "Bad value \u201c:\\\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/blockquote/cite/path-leading-colon-chars-backslash-novalid.html": "Bad value \u201c:foo.com\\\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/blockquote/cite/path-leading-space-novalid.html": "Bad value \u201chttp://f:21/ b\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/blockquote/cite/path-percent-encoded-malformed-novalid.html": "Bad value \u201chttp://example.com/foo/%2e%2\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Percentage (\"%\") is not followed by two hexadecimal digits.",
+ "html/elements/blockquote/cite/path-relative-square-brackets-novalid.html": "Bad value \u201c[61:24:74]:98\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/blockquote/cite/path-tab-novalid.html": "Bad value \u201chttp://example.com/foo\tbar\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/blockquote/cite/path-trailing-space-novalid.html": "Bad value \u201chttp://f:21/b ?\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/blockquote/cite/path-u0091-novalid.html": "Forbidden code point U+0091.",
+ "html/elements/blockquote/cite/port-cr-novalid.html": "Bad value \u201chttp://f:\n/c\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/blockquote/cite/port-leading-colon-bracket-colon-novalid.html": "Bad value \u201chttp://2001::1]:80\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Illegal character in port.",
+ "html/elements/blockquote/cite/port-leading-colon-novalid.html": "Bad value \u201chttp://2001::1\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Illegal character in port.",
+ "html/elements/blockquote/cite/port-leading-dash-novalid.html": "Bad value \u201chttp://foo:-80/\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Illegal character in port.",
+ "html/elements/blockquote/cite/port-multiple-letters-novalid.html": "Bad value \u201chttp://f:fifty-two/c\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Illegal character in port.",
+ "html/elements/blockquote/cite/port-newline-novalid.html": "Bad value \u201chttp://f:\n/c\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/blockquote/cite/port-single-letter-novalid.html": "Bad value \u201chttp://f:b/c\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Illegal character in port.",
+ "html/elements/blockquote/cite/port-space-novalid.html": "Bad value \u201chttp://f: /c\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Illegal character in port.",
+ "html/elements/blockquote/cite/port-tab-novalid.html": "Bad value \u201chttp://f:\t/c\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/blockquote/cite/query-leading-space-novalid.html": "Bad value \u201chttp://f:21/b? d\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Illegal character in query: not a URL code point.",
+ "html/elements/blockquote/cite/query-trailing-space-novalid.html": "Bad value \u201chttp://f:21/b?d #\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Illegal character in query: not a URL code point.",
+ "html/elements/blockquote/cite/scheme-data-contains-fragment-haswarn.html": "Bad value \u201cdata:text/html,test#test\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Fragment is not allowed for data: URIs according to RFC 2397.",
+ "html/elements/blockquote/cite/scheme-data-single-slash-novalid.html": "Bad value \u201cdata:/example.com/\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Expected a token character or a semicolon but saw \u201c/\u201d instead.",
+ "html/elements/blockquote/cite/scheme-file-backslash-novalid.html": "Bad value \u201cfile:c:\\foo\\bar.html\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/blockquote/cite/scheme-file-single-slash-c-bar-novalid.html": "Bad value \u201cfile:/C|/foo/bar\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/blockquote/cite/scheme-file-triple-slash-c-bar-novalid.html": "Bad value \u201cfile:///C|/foo/bar\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/blockquote/cite/scheme-ftp-no-slash-novalid.html": "Bad value \u201cftp:example.com/\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/blockquote/cite/scheme-ftp-single-slash-novalid.html": "Bad value \u201cftp:/example.com/\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/blockquote/cite/scheme-http-backslash-novalid.html": "Bad value \u201chttp:\\\\foo.com\\\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/blockquote/cite/scheme-http-no-slash-colon-novalid.html": "Bad value \u201chttp::@c:29\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/blockquote/cite/scheme-http-no-slash-novalid.html": "Bad value \u201chttp:foo.com\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/blockquote/cite/scheme-http-no-slash-square-bracket-novalid.html": "Bad value \u201chttp:[61:27]/:foo\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/blockquote/cite/scheme-http-single-slash-novalid.html": "Bad value \u201chttp:/example.com/\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/blockquote/cite/scheme-https-no-slash-novalid.html": "Bad value \u201chttps:example.com/\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/blockquote/cite/scheme-https-single-slash-novalid.html": "Bad value \u201chttps:/example.com/\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/blockquote/cite/scheme-javascript-no-slash-malformed-novalid.html": "Bad value \u201cjavascript:example.com/\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: syntax error",
+ "html/elements/blockquote/cite/scheme-trailing-cr-novalid.html": "Bad value \u201ca:\nfoo.com\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/blockquote/cite/scheme-trailing-newline-novalid.html": "Bad value \u201ca:\nfoo.com\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/blockquote/cite/scheme-trailing-space-novalid.html": "Bad value \u201ca: foo.com\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/blockquote/cite/scheme-trailing-tab-novalid.html": "Bad value \u201ca:\tfoo.com\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/blockquote/cite/userinfo-backslash-novalid.html": "Bad value \u201chttp://a\\b:c\\d@foo.com\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/blockquote/cite/userinfo-password-bad-chars-novalid.html": "\u201c&\u201d did not start a character reference. (\u201c&\u201d probably should have been escaped as \u201c&amp;\u201d.)",
+ "html/elements/blockquote/cite/userinfo-password-contains-pile-of-poo-novalid.html": "Bad value \u201chttp://foo:\ud83d\udca9@example.com\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Illegal character in user or password: not a URL code point.",
+ "html/elements/blockquote/cite/userinfo-username-contains-at-sign-novalid.html": "Bad value \u201chttp://::@c@d:2\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: User or password contains an at symbol (\"@\") not percent-encoded.",
+ "html/elements/blockquote/cite/userinfo-username-contains-pile-of-poo-novalid.html": "Bad value \u201chttp://\ud83d\udca9:foo@example.com\u201d for attribute \u201ccite\u201d on element \u201cblockquote\u201d: Bad URL: Illegal character in user or password: not a URL code point.",
+ "html/elements/blockquote/model-novalid.html": "No \u201cp\u201d element in scope but a \u201cp\u201d end tag seen.",
+ "html/elements/br/model-novalid.html": "End tag \u201cbr\u201d.",
+ "html/elements/button/formaction-empty-novalid.html": "Bad value \u201c\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Must be non-empty.",
+ "html/elements/button/formaction-whitespace-only-novalid.html": "Bad value \u201c\t \n\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Must be non-empty.",
+ "html/elements/button/formaction/fragment-backslash-novalid.html": "Bad value \u201c#\\\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/button/formaction/fragment-contains-hash-novalid.html": "Bad value \u201chttp://foo/path#f#g\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/button/formaction/fragment-leading-space-novalid.html": "Bad value \u201chttp://f:21/b# e\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/button/formaction/host-cr-novalid.html": "Bad value \u201chttp://example.\norg\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/button/formaction/host-double-percent-encoded-novalid.html": "Bad value \u201chttp://\uff05\uff14\uff11.com\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/button/formaction/host-double-percent-encoded-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%bc%85%ef%bc%94%ef%bc%91.com\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/button/formaction/host-empty-novalid.html": "Bad value \u201chttp://\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/button/formaction/host-empty-userinfo-empty-novalid.html": "Bad value \u201chttp://@/www.example.com\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/button/formaction/host-empty-with-userinfo-novalid.html": "Bad value \u201chttp://user:pass@/\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/button/formaction/host-hostname-in-brackets-novalid.html": "Bad value \u201chttp://[www.google.com]/\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Invalid host: Illegal character.",
+ "html/elements/button/formaction/host-invalid-unicode-novalid.html": "Forbidden code point U+fdd0.",
+ "html/elements/button/formaction/host-invalid-unicode-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%b7%90zyx.com\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Invalid host: A label or domain name contains disallowed characters..",
+ "html/elements/button/formaction/host-newline-novalid.html": "Bad value \u201chttp://example.\norg\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/button/formaction/host-space-novalid.html": "Bad value \u201chttp://example .org\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Invalid host: Domain contains invalid character: .",
+ "html/elements/button/formaction/host-square-brackets-port-contains-colon-novalid.html": "Bad value \u201chttp://[1::2]:3:4\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Illegal character in port.",
+ "html/elements/button/formaction/host-tab-novalid.html": "Bad value \u201chttp://example\t.org\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/button/formaction/host-u0000-percent-encoded-novalid.html": "Bad value \u201chttp://\uff05\uff10\uff10.com\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/button/formaction/host-u0000-percent-encoded-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%bc%85%ef%bc%90%ef%bc%90.com\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/button/formaction/path-bare-percent-sign-novalid.html": "Bad value \u201chttp://example.com/foo%\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Percentage (\"%\") is not followed by two hexadecimal digits.",
+ "html/elements/button/formaction/path-contains-space-novalid.html": "Bad value \u201c/a/ /c\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/button/formaction/path-leading-backslash-at-sign-novalid.html": "Bad value \u201chttp://foo.com/\\@\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/button/formaction/path-leading-colon-backslash-novalid.html": "Bad value \u201c:\\\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/button/formaction/path-leading-colon-chars-backslash-novalid.html": "Bad value \u201c:foo.com\\\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/button/formaction/path-leading-space-novalid.html": "Bad value \u201chttp://f:21/ b\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/button/formaction/path-percent-encoded-malformed-novalid.html": "Bad value \u201chttp://example.com/foo/%2e%2\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Percentage (\"%\") is not followed by two hexadecimal digits.",
+ "html/elements/button/formaction/path-relative-square-brackets-novalid.html": "Bad value \u201c[61:24:74]:98\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/button/formaction/path-tab-novalid.html": "Bad value \u201chttp://example.com/foo\tbar\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/button/formaction/path-trailing-space-novalid.html": "Bad value \u201chttp://f:21/b ?\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/button/formaction/path-u0091-novalid.html": "Forbidden code point U+0091.",
+ "html/elements/button/formaction/port-cr-novalid.html": "Bad value \u201chttp://f:\n/c\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/button/formaction/port-leading-colon-bracket-colon-novalid.html": "Bad value \u201chttp://2001::1]:80\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Illegal character in port.",
+ "html/elements/button/formaction/port-leading-colon-novalid.html": "Bad value \u201chttp://2001::1\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Illegal character in port.",
+ "html/elements/button/formaction/port-leading-dash-novalid.html": "Bad value \u201chttp://foo:-80/\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Illegal character in port.",
+ "html/elements/button/formaction/port-multiple-letters-novalid.html": "Bad value \u201chttp://f:fifty-two/c\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Illegal character in port.",
+ "html/elements/button/formaction/port-newline-novalid.html": "Bad value \u201chttp://f:\n/c\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/button/formaction/port-single-letter-novalid.html": "Bad value \u201chttp://f:b/c\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Illegal character in port.",
+ "html/elements/button/formaction/port-space-novalid.html": "Bad value \u201chttp://f: /c\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Illegal character in port.",
+ "html/elements/button/formaction/port-tab-novalid.html": "Bad value \u201chttp://f:\t/c\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/button/formaction/query-leading-space-novalid.html": "Bad value \u201chttp://f:21/b? d\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Illegal character in query: not a URL code point.",
+ "html/elements/button/formaction/query-trailing-space-novalid.html": "Bad value \u201chttp://f:21/b?d #\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Illegal character in query: not a URL code point.",
+ "html/elements/button/formaction/scheme-data-contains-fragment-haswarn.html": "Bad value \u201cdata:text/html,test#test\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Fragment is not allowed for data: URIs according to RFC 2397.",
+ "html/elements/button/formaction/scheme-data-single-slash-novalid.html": "Bad value \u201cdata:/example.com/\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Expected a token character or a semicolon but saw \u201c/\u201d instead.",
+ "html/elements/button/formaction/scheme-file-backslash-novalid.html": "Bad value \u201cfile:c:\\foo\\bar.html\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/button/formaction/scheme-file-single-slash-c-bar-novalid.html": "Bad value \u201cfile:/C|/foo/bar\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/button/formaction/scheme-file-triple-slash-c-bar-novalid.html": "Bad value \u201cfile:///C|/foo/bar\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/button/formaction/scheme-ftp-no-slash-novalid.html": "Bad value \u201cftp:example.com/\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/button/formaction/scheme-ftp-single-slash-novalid.html": "Bad value \u201cftp:/example.com/\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/button/formaction/scheme-http-backslash-novalid.html": "Bad value \u201chttp:\\\\foo.com\\\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/button/formaction/scheme-http-no-slash-colon-novalid.html": "Bad value \u201chttp::@c:29\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/button/formaction/scheme-http-no-slash-novalid.html": "Bad value \u201chttp:foo.com\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/button/formaction/scheme-http-no-slash-square-bracket-novalid.html": "Bad value \u201chttp:[61:27]/:foo\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/button/formaction/scheme-http-single-slash-novalid.html": "Bad value \u201chttp:/example.com/\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/button/formaction/scheme-https-no-slash-novalid.html": "Bad value \u201chttps:example.com/\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/button/formaction/scheme-https-single-slash-novalid.html": "Bad value \u201chttps:/example.com/\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/button/formaction/scheme-javascript-no-slash-malformed-novalid.html": "Bad value \u201cjavascript:example.com/\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: syntax error",
+ "html/elements/button/formaction/scheme-trailing-cr-novalid.html": "Bad value \u201ca:\nfoo.com\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/button/formaction/scheme-trailing-newline-novalid.html": "Bad value \u201ca:\nfoo.com\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/button/formaction/scheme-trailing-space-novalid.html": "Bad value \u201ca: foo.com\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/button/formaction/scheme-trailing-tab-novalid.html": "Bad value \u201ca:\tfoo.com\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/button/formaction/userinfo-backslash-novalid.html": "Bad value \u201chttp://a\\b:c\\d@foo.com\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/button/formaction/userinfo-password-bad-chars-novalid.html": "\u201c&\u201d did not start a character reference. (\u201c&\u201d probably should have been escaped as \u201c&amp;\u201d.)",
+ "html/elements/button/formaction/userinfo-password-contains-pile-of-poo-novalid.html": "Bad value \u201chttp://foo:\ud83d\udca9@example.com\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Illegal character in user or password: not a URL code point.",
+ "html/elements/button/formaction/userinfo-username-contains-at-sign-novalid.html": "Bad value \u201chttp://::@c@d:2\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: User or password contains an at symbol (\"@\") not percent-encoded.",
+ "html/elements/button/formaction/userinfo-username-contains-pile-of-poo-novalid.html": "Bad value \u201chttp://\ud83d\udca9:foo@example.com\u201d for attribute \u201cformaction\u201d on element \u201cbutton\u201d: Bad URL: Illegal character in user or password: not a URL code point.",
+ "html/elements/canvas/model-novalid.html": "Element \u201cp\u201d not allowed in this context. (The parent was element \u201ccanvas\u201d.) Suppressing further errors from this subtree.",
+ "html/elements/cite/model-novalid.html": "End tag \u201cp\u201d implied, but there were open elements.",
+ "html/elements/code/model-novalid.html": "End tag \u201cp\u201d implied, but there were open elements.",
+ "html/elements/del/cite/fragment-backslash-novalid.html": "Bad value \u201c#\\\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/del/cite/fragment-contains-hash-novalid.html": "Bad value \u201chttp://foo/path#f#g\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/del/cite/fragment-leading-space-novalid.html": "Bad value \u201chttp://f:21/b# e\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/del/cite/host-cr-novalid.html": "Bad value \u201chttp://example.\norg\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/del/cite/host-double-percent-encoded-novalid.html": "Bad value \u201chttp://\uff05\uff14\uff11.com\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/del/cite/host-double-percent-encoded-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%bc%85%ef%bc%94%ef%bc%91.com\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/del/cite/host-empty-novalid.html": "Bad value \u201chttp://\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/del/cite/host-empty-userinfo-empty-novalid.html": "Bad value \u201chttp://@/www.example.com\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/del/cite/host-empty-with-userinfo-novalid.html": "Bad value \u201chttp://user:pass@/\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/del/cite/host-hostname-in-brackets-novalid.html": "Bad value \u201chttp://[www.google.com]/\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Invalid host: Illegal character.",
+ "html/elements/del/cite/host-invalid-unicode-novalid.html": "Forbidden code point U+fdd0.",
+ "html/elements/del/cite/host-invalid-unicode-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%b7%90zyx.com\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Invalid host: A label or domain name contains disallowed characters..",
+ "html/elements/del/cite/host-newline-novalid.html": "Bad value \u201chttp://example.\norg\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/del/cite/host-space-novalid.html": "Bad value \u201chttp://example .org\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Invalid host: Domain contains invalid character: .",
+ "html/elements/del/cite/host-square-brackets-port-contains-colon-novalid.html": "Bad value \u201chttp://[1::2]:3:4\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Illegal character in port.",
+ "html/elements/del/cite/host-tab-novalid.html": "Bad value \u201chttp://example\t.org\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/del/cite/host-u0000-percent-encoded-novalid.html": "Bad value \u201chttp://\uff05\uff10\uff10.com\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/del/cite/host-u0000-percent-encoded-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%bc%85%ef%bc%90%ef%bc%90.com\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/del/cite/path-bare-percent-sign-novalid.html": "Bad value \u201chttp://example.com/foo%\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Percentage (\"%\") is not followed by two hexadecimal digits.",
+ "html/elements/del/cite/path-contains-space-novalid.html": "Bad value \u201c/a/ /c\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/del/cite/path-leading-backslash-at-sign-novalid.html": "Bad value \u201chttp://foo.com/\\@\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/del/cite/path-leading-colon-backslash-novalid.html": "Bad value \u201c:\\\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/del/cite/path-leading-colon-chars-backslash-novalid.html": "Bad value \u201c:foo.com\\\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/del/cite/path-leading-space-novalid.html": "Bad value \u201chttp://f:21/ b\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/del/cite/path-percent-encoded-malformed-novalid.html": "Bad value \u201chttp://example.com/foo/%2e%2\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Percentage (\"%\") is not followed by two hexadecimal digits.",
+ "html/elements/del/cite/path-relative-square-brackets-novalid.html": "Bad value \u201c[61:24:74]:98\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/del/cite/path-tab-novalid.html": "Bad value \u201chttp://example.com/foo\tbar\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/del/cite/path-trailing-space-novalid.html": "Bad value \u201chttp://f:21/b ?\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/del/cite/path-u0091-novalid.html": "Forbidden code point U+0091.",
+ "html/elements/del/cite/port-cr-novalid.html": "Bad value \u201chttp://f:\n/c\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/del/cite/port-leading-colon-bracket-colon-novalid.html": "Bad value \u201chttp://2001::1]:80\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Illegal character in port.",
+ "html/elements/del/cite/port-leading-colon-novalid.html": "Bad value \u201chttp://2001::1\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Illegal character in port.",
+ "html/elements/del/cite/port-leading-dash-novalid.html": "Bad value \u201chttp://foo:-80/\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Illegal character in port.",
+ "html/elements/del/cite/port-multiple-letters-novalid.html": "Bad value \u201chttp://f:fifty-two/c\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Illegal character in port.",
+ "html/elements/del/cite/port-newline-novalid.html": "Bad value \u201chttp://f:\n/c\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/del/cite/port-single-letter-novalid.html": "Bad value \u201chttp://f:b/c\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Illegal character in port.",
+ "html/elements/del/cite/port-space-novalid.html": "Bad value \u201chttp://f: /c\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Illegal character in port.",
+ "html/elements/del/cite/port-tab-novalid.html": "Bad value \u201chttp://f:\t/c\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/del/cite/query-leading-space-novalid.html": "Bad value \u201chttp://f:21/b? d\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Illegal character in query: not a URL code point.",
+ "html/elements/del/cite/query-trailing-space-novalid.html": "Bad value \u201chttp://f:21/b?d #\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Illegal character in query: not a URL code point.",
+ "html/elements/del/cite/scheme-data-contains-fragment-haswarn.html": "Bad value \u201cdata:text/html,test#test\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Fragment is not allowed for data: URIs according to RFC 2397.",
+ "html/elements/del/cite/scheme-data-single-slash-novalid.html": "Bad value \u201cdata:/example.com/\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Expected a token character or a semicolon but saw \u201c/\u201d instead.",
+ "html/elements/del/cite/scheme-file-backslash-novalid.html": "Bad value \u201cfile:c:\\foo\\bar.html\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/del/cite/scheme-file-single-slash-c-bar-novalid.html": "Bad value \u201cfile:/C|/foo/bar\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/del/cite/scheme-file-triple-slash-c-bar-novalid.html": "Bad value \u201cfile:///C|/foo/bar\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/del/cite/scheme-ftp-no-slash-novalid.html": "Bad value \u201cftp:example.com/\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/del/cite/scheme-ftp-single-slash-novalid.html": "Bad value \u201cftp:/example.com/\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/del/cite/scheme-http-backslash-novalid.html": "Bad value \u201chttp:\\\\foo.com\\\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/del/cite/scheme-http-no-slash-colon-novalid.html": "Bad value \u201chttp::@c:29\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/del/cite/scheme-http-no-slash-novalid.html": "Bad value \u201chttp:foo.com\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/del/cite/scheme-http-no-slash-square-bracket-novalid.html": "Bad value \u201chttp:[61:27]/:foo\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/del/cite/scheme-http-single-slash-novalid.html": "Bad value \u201chttp:/example.com/\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/del/cite/scheme-https-no-slash-novalid.html": "Bad value \u201chttps:example.com/\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/del/cite/scheme-https-single-slash-novalid.html": "Bad value \u201chttps:/example.com/\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/del/cite/scheme-javascript-no-slash-malformed-novalid.html": "Bad value \u201cjavascript:example.com/\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: syntax error",
+ "html/elements/del/cite/scheme-trailing-cr-novalid.html": "Bad value \u201ca:\nfoo.com\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/del/cite/scheme-trailing-newline-novalid.html": "Bad value \u201ca:\nfoo.com\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/del/cite/scheme-trailing-space-novalid.html": "Bad value \u201ca: foo.com\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/del/cite/scheme-trailing-tab-novalid.html": "Bad value \u201ca:\tfoo.com\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/del/cite/userinfo-backslash-novalid.html": "Bad value \u201chttp://a\\b:c\\d@foo.com\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/del/cite/userinfo-password-bad-chars-novalid.html": "\u201c&\u201d did not start a character reference. (\u201c&\u201d probably should have been escaped as \u201c&amp;\u201d.)",
+ "html/elements/del/cite/userinfo-password-contains-pile-of-poo-novalid.html": "Bad value \u201chttp://foo:\ud83d\udca9@example.com\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Illegal character in user or password: not a URL code point.",
+ "html/elements/del/cite/userinfo-username-contains-at-sign-novalid.html": "Bad value \u201chttp://::@c@d:2\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: User or password contains an at symbol (\"@\") not percent-encoded.",
+ "html/elements/del/cite/userinfo-username-contains-pile-of-poo-novalid.html": "Bad value \u201chttp://\ud83d\udca9:foo@example.com\u201d for attribute \u201ccite\u201d on element \u201cdel\u201d: Bad URL: Illegal character in user or password: not a URL code point.",
+ "html/elements/del/date-0004-02-29-haswarn.html": "Bad value \u201c0004-02-29\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad date: Year may be mistyped. Bad datetime with timezone: The literal did not satisfy the datetime with timezone format.",
+ "html/elements/del/date-0005-02-29-novalid.html": "Bad value \u201c0005-02-29\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: Day out of range.",
+ "html/elements/del/date-0214-09-29-haswarn.html": "Bad value \u201c0214-09-29\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad date: Year may be mistyped. Bad datetime with timezone: The literal did not satisfy the datetime with timezone format.",
+ "html/elements/del/date-1900-02-29-novalid.html": "Bad value \u201c1900-02-29\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: Day out of range.",
+ "html/elements/del/date-1969-02-29-novalid.html": "Bad value \u201c1969-02-29\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: Day out of range.",
+ "html/elements/del/date-20014-09-29-haswarn.html": "Bad value \u201c20014-09-29\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad date: Year may be mistyped. Bad datetime with timezone: The literal did not satisfy the datetime with timezone format.",
+ "html/elements/del/date-2014-02-29-novalid.html": "Bad value \u201c2014-02-29\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: Day out of range.",
+ "html/elements/del/date-2100-02-29-novalid.html": "Bad value \u201c2100-02-29\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: Day out of range.",
+ "html/elements/del/date-2200-02-29-novalid.html": "Bad value \u201c2200-02-29\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: Day out of range.",
+ "html/elements/del/date-day-01-32-novalid.html": "Bad value \u201c2002-01-32\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: Day out of range.",
+ "html/elements/del/date-day-03-32-novalid.html": "Bad value \u201c2002-03-32\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: Day out of range.",
+ "html/elements/del/date-day-04-31-novalid.html": "Bad value \u201c2002-04-31\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: Day out of range.",
+ "html/elements/del/date-day-05-32-novalid.html": "Bad value \u201c2002-05-32\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: Day out of range.",
+ "html/elements/del/date-day-06-31-novalid.html": "Bad value \u201c2002-06-31\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: Day out of range.",
+ "html/elements/del/date-day-07-32-novalid.html": "Bad value \u201c2002-07-32\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: Day out of range.",
+ "html/elements/del/date-day-08-32-novalid.html": "Bad value \u201c2002-08-32\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: Day out of range.",
+ "html/elements/del/date-day-09-31-novalid.html": "Bad value \u201c2002-09-31\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: Day out of range.",
+ "html/elements/del/date-day-10-32-novalid.html": "Bad value \u201c2002-10-32\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: Day out of range.",
+ "html/elements/del/date-day-11-31-novalid.html": "Bad value \u201c2002-11-31\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: Day out of range.",
+ "html/elements/del/date-day-12-32-novalid.html": "Bad value \u201c2002-12-32\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: Day out of range.",
+ "html/elements/del/date-day-missing-separator-novalid.html": "Bad value \u201c2014-0220\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/date-day-one-digit-novalid.html": "Bad value \u201c2002-09-9\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/date-day-three-digits-novalid.html": "Bad value \u201c2002-11-009\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/date-iso8601-YYYYMMDD-no-hyphen-novalid.html": "Bad value \u201c20020929\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/date-leading-bom-novalid.html": "Bad value \u201c\ufeff2002-09-29\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/date-leading-whitespace-novalid.html": "Bad value \u201c 2002-09-29\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/date-month-00-novalid.html": "Bad value \u201c2002-00-15\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad date: Month cannot be less than 1. Bad datetime with timezone: The literal did not satisfy the datetime with timezone format.",
+ "html/elements/del/date-month-13-novalid.html": "Bad value \u201c2002-13-15\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: Month cannot be greater than 12.",
+ "html/elements/del/date-month-missing-separator-novalid.html": "Bad value \u201c201402-20\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/date-month-one-digit-novalid.html": "Bad value \u201c2002-9-29\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/date-month-three-digits-novalid.html": "Bad value \u201c2002-011-29\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/date-non-ascii-digit-novalid.html": "Bad value \u201c2002-09-2\uff19\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/date-trailing-U+0000-novalid.html": "Character reference expands to zero.",
+ "html/elements/del/date-trailing-pile-of-poo-novalid.html": "Bad value \u201c2002-09-29\ud83d\udca9\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/date-trailing-whitespace-novalid.html": "Bad value \u201c2002-09-29 \u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/date-wrong-day-separator-novalid.html": "Bad value \u201c2014-02:20\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/date-wrong-month-separator-novalid.html": "Bad value \u201c2014:02-20\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/date-year-0000-novalid.html": "Bad value \u201c0000-12-09\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: Year cannot be less than 1.",
+ "html/elements/del/date-year-five-digits-haswarn.html": "Bad value \u201c12014-09-29\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad date: Year may be mistyped. Bad datetime with timezone: The literal did not satisfy the datetime with timezone format.",
+ "html/elements/del/date-year-negative-novalid.html": "Bad value \u201c-2002-09-29\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/date-year-three-digits-novalid.html": "Bad value \u201c782-09-29\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/duration-P-form-novalid.html": "Bad value \u201cPT4H18M3S\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/duration-time-component-novalid.html": "Bad value \u201c4h 18m 3s\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/global-date-and-time-2400-novalid.html": "Bad value \u201c2011-11-12T24:00:00+08:00\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: Hour cannot be greater than 23. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/global-date-and-time-60-minutes-novalid.html": "Bad value \u201c2011-11-12T00:60:00+08:00\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: Minute cannot be greater than 59. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/global-date-and-time-60-seconds-novalid.html": "Bad value \u201c2011-11-12T00:00:60+08:00\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: Second cannot be greater than 59. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/global-date-and-time-bad-fraction-separator-novalid.html": "Bad value \u201c2011-11-12T14:54:39,929+0000\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/global-date-and-time-four-digit-fraction-novalid.html": "Bad value \u201c2011-11-12T06:54:39.9291-08:00\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad date: The literal did not satisfy the date format. Bad datetime with timezone: A fraction of a second must be one, two, or three digits.",
+ "html/elements/del/global-date-and-time-hour-one-digit-novalid.html": "Bad value \u201c2011-11-12T6:54:39-08:00\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/global-date-and-time-hour-three-digits-novalid.html": "Bad value \u201c2011-11-12T016:54:39-08:00\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/global-date-and-time-iso8601-hh-novalid.html": "Bad value \u201c2011-11-12T14Z\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/global-date-and-time-iso8601-hhmm-no-colon-novalid.html": "Bad value \u201c2011-11-12T1454Z\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/global-date-and-time-iso8601-hhmmss-no-colon-novalid.html": "Bad value \u201c2011-11-12T145439Z\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/global-date-and-time-lowercase-z-novalid.html": "Bad value \u201c2011-11-12T14:54z\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/global-date-and-time-minutes-one-digit-novalid.html": "Bad value \u201c2011-11-12T16:4:39-08:00\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/global-date-and-time-minutes-three-digits-novalid.html": "Bad value \u201c2011-11-12T16:354:39-08:00\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/global-date-and-time-missing-minutes-separator-novalid.html": "Bad value \u201c2011-11-12T1454Z\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/global-date-and-time-missing-seconds-separator-novalid.html": "Bad value \u201c2011-11-12T14:5439Z\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/global-date-and-time-nbsp-novalid.html": "Bad value \u201c2011-11-12\u00a014:54Z\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/global-date-and-time-seconds-one-digit-novalid.html": "Bad value \u201c2011-11-12T16:54:9-08:00\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/global-date-and-time-seconds-three-digits-novalid.html": "Bad value \u201c2011-11-12T16:54:039-08:00\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/global-date-and-time-space-before-timezone-novalid.html": "Bad value \u201c2011-11-12T06:54:39 08:00\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/global-date-and-time-timezone-60-minutes-novalid.html": "Bad value \u201c2011-11-12T06:54:39-08:60\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad date: The literal did not satisfy the date format. Bad datetime with timezone: Minutes out of range in time zone designator.",
+ "html/elements/del/global-date-and-time-timezone-iso8601-two-digit-novalid.html": "Bad value \u201c2011-11-12T06:54:39-08\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/global-date-and-time-timezone-lowercase-t-novalid.html": "Bad value \u201c2011-11-12t14:54Z\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/global-date-and-time-timezone-minus-1300-haswarn.html": "Bad value \u201c2011-11-12T00:00:00-1300\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: Hours in time zone designator should be from \u201c-12:00\u201d to \u201d+14:00\u201d Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/global-date-and-time-timezone-minus-2400-novalid.html": "Bad value \u201c2011-11-12T06:54:39-24:00\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: Hours out of range in time zone designator. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/global-date-and-time-timezone-minutes-15-haswarn.html": "Bad value \u201c2011-11-12T00:00:00+08:15\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: Minutes in time zone designator should be either \u201c00\u201d, \u201c30\u201d, or \u201c45\u201d. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/global-date-and-time-timezone-multiple-spaces-novalid.html": "Bad value \u201c2011-11-12 14:54Z\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/global-date-and-time-timezone-non-T-character-novalid.html": "Bad value \u201c2011-11-12+14:54Z\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/global-date-and-time-timezone-offset-colon-start-novalid.html": "Bad value \u201c2011-11-12T06:54:39.929:08:00\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/global-date-and-time-timezone-offset-space-start-novalid.html": "Bad value \u201c2011-11-12T06:54:39.929 08:00\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/global-date-and-time-timezone-one-digit-hour-novalid.html": "Bad value \u201c2011-11-12T06:54:39-5:00\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/global-date-and-time-timezone-one-digit-minute-novalid.html": "Bad value \u201c2011-11-12T06:54:39-05:0\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/global-date-and-time-timezone-plus-1500-haswarn.html": "Bad value \u201c2011-11-12T00:00:00+1500\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: Hours in time zone designator should be from \u201c-12:00\u201d to \u201d+14:00\u201d Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/global-date-and-time-timezone-plus-2400-novalid.html": "Bad value \u201c2011-11-12T06:54:39-24:00\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: Hours out of range in time zone designator. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/global-date-and-time-timezone-three-digit-hour-novalid.html": "Bad value \u201c2011-11-12T06:54:39-005:00\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/global-date-and-time-timezone-three-digit-minute-novalid.html": "Bad value \u201c2011-11-12T06:54:39-05:000\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/global-date-and-time-timezone-with-seconds-novalid.html": "Bad value \u201c2011-11-12T06:54:39-08:00:00\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/global-date-and-time-with-both-T-and-space-novalid.html": "Bad value \u201c2011-11-12T 14:54Z\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/global-date-and-time-wrong-minutes-separator-novalid.html": "Bad value \u201c2011-11-12T14-54Z\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/global-date-and-time-wrong-seconds-separator-novalid.html": "Bad value \u201c2011-11-12T14:54-39Z\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/global-date-and-time-zero-digit-fraction-novalid.html": "Bad value \u201c2011-11-12T06:54:39.-08:00\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/local-date-and-time-novalid.html": "Bad value \u201c2011-11-12T14:54\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/model-novalid.html": "End tag \u201cp\u201d implied, but there were open elements.",
+ "html/elements/del/month-novalid.html": "Bad value \u201c2011-11\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/time-novalid.html": "Bad value \u201c14:54:39\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/week-novalid.html": "Bad value \u201c2011-W46\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/year-novalid.html": "Bad value \u201c2006\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/del/yearless-date-novalid.html": "Bad value \u201c07-15\u201d for attribute \u201cdatetime\u201d on element \u201cdel\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/dfn/model-novalid.html": "End tag \u201cp\u201d implied, but there were open elements.",
+ "html/elements/dialog/model-novalid.html": "Element \u201cdt\u201d not allowed in this context. (The parent was element \u201cdialog\u201d.) Suppressing further errors from this subtree.",
+ "html/elements/div/model-novalid.html": "End tag \u201cp\u201d implied, but there were open elements.",
+ "html/elements/dl/model-novalid.html": "Duplicate ID \u201cid\u201d.",
+ "html/elements/em/model-novalid.html": "End tag \u201cp\u201d implied, but there were open elements.",
+ "html/elements/embed/height-novalid.html": "Bad value \u201c20%\u201d for attribute \u201cheight\u201d on element \u201cembed\u201d: Bad non-negative integer: Expected a digit but saw \u201c%\u201d instead.",
+ "html/elements/embed/src-empty-novalid.html": "Bad value \u201c\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Must be non-empty.",
+ "html/elements/embed/src-whitespace-only-novalid.html": "Bad value \u201c\t \n\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Must be non-empty.",
+ "html/elements/embed/src/fragment-backslash-novalid.html": "Bad value \u201c#\\\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/embed/src/fragment-contains-hash-novalid.html": "Bad value \u201chttp://foo/path#f#g\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/embed/src/fragment-leading-space-novalid.html": "Bad value \u201chttp://f:21/b# e\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/embed/src/host-cr-novalid.html": "Bad value \u201chttp://example.\norg\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/embed/src/host-double-percent-encoded-novalid.html": "Bad value \u201chttp://\uff05\uff14\uff11.com\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/embed/src/host-double-percent-encoded-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%bc%85%ef%bc%94%ef%bc%91.com\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/embed/src/host-empty-novalid.html": "Bad value \u201chttp://\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/embed/src/host-empty-userinfo-empty-novalid.html": "Bad value \u201chttp://@/www.example.com\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/embed/src/host-empty-with-userinfo-novalid.html": "Bad value \u201chttp://user:pass@/\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/embed/src/host-hostname-in-brackets-novalid.html": "Bad value \u201chttp://[www.google.com]/\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Invalid host: Illegal character.",
+ "html/elements/embed/src/host-invalid-unicode-novalid.html": "Forbidden code point U+fdd0.",
+ "html/elements/embed/src/host-invalid-unicode-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%b7%90zyx.com\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Invalid host: A label or domain name contains disallowed characters..",
+ "html/elements/embed/src/host-newline-novalid.html": "Bad value \u201chttp://example.\norg\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/embed/src/host-space-novalid.html": "Bad value \u201chttp://example .org\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Invalid host: Domain contains invalid character: .",
+ "html/elements/embed/src/host-square-brackets-port-contains-colon-novalid.html": "Bad value \u201chttp://[1::2]:3:4\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Illegal character in port.",
+ "html/elements/embed/src/host-tab-novalid.html": "Bad value \u201chttp://example\t.org\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/embed/src/host-u0000-percent-encoded-novalid.html": "Bad value \u201chttp://\uff05\uff10\uff10.com\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/embed/src/host-u0000-percent-encoded-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%bc%85%ef%bc%90%ef%bc%90.com\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/embed/src/path-bare-percent-sign-novalid.html": "Bad value \u201chttp://example.com/foo%\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Percentage (\"%\") is not followed by two hexadecimal digits.",
+ "html/elements/embed/src/path-contains-space-novalid.html": "Bad value \u201c/a/ /c\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/embed/src/path-leading-backslash-at-sign-novalid.html": "Bad value \u201chttp://foo.com/\\@\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/embed/src/path-leading-colon-backslash-novalid.html": "Bad value \u201c:\\\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/embed/src/path-leading-colon-chars-backslash-novalid.html": "Bad value \u201c:foo.com\\\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/embed/src/path-leading-space-novalid.html": "Bad value \u201chttp://f:21/ b\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/embed/src/path-percent-encoded-malformed-novalid.html": "Bad value \u201chttp://example.com/foo/%2e%2\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Percentage (\"%\") is not followed by two hexadecimal digits.",
+ "html/elements/embed/src/path-relative-square-brackets-novalid.html": "Bad value \u201c[61:24:74]:98\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/embed/src/path-tab-novalid.html": "Bad value \u201chttp://example.com/foo\tbar\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/embed/src/path-trailing-space-novalid.html": "Bad value \u201chttp://f:21/b ?\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/embed/src/path-u0091-novalid.html": "Forbidden code point U+0091.",
+ "html/elements/embed/src/port-cr-novalid.html": "Bad value \u201chttp://f:\n/c\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/embed/src/port-leading-colon-bracket-colon-novalid.html": "Bad value \u201chttp://2001::1]:80\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Illegal character in port.",
+ "html/elements/embed/src/port-leading-colon-novalid.html": "Bad value \u201chttp://2001::1\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Illegal character in port.",
+ "html/elements/embed/src/port-leading-dash-novalid.html": "Bad value \u201chttp://foo:-80/\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Illegal character in port.",
+ "html/elements/embed/src/port-multiple-letters-novalid.html": "Bad value \u201chttp://f:fifty-two/c\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Illegal character in port.",
+ "html/elements/embed/src/port-newline-novalid.html": "Bad value \u201chttp://f:\n/c\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/embed/src/port-single-letter-novalid.html": "Bad value \u201chttp://f:b/c\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Illegal character in port.",
+ "html/elements/embed/src/port-space-novalid.html": "Bad value \u201chttp://f: /c\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Illegal character in port.",
+ "html/elements/embed/src/port-tab-novalid.html": "Bad value \u201chttp://f:\t/c\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/embed/src/query-leading-space-novalid.html": "Bad value \u201chttp://f:21/b? d\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Illegal character in query: not a URL code point.",
+ "html/elements/embed/src/query-trailing-space-novalid.html": "Bad value \u201chttp://f:21/b?d #\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Illegal character in query: not a URL code point.",
+ "html/elements/embed/src/scheme-data-contains-fragment-haswarn.html": "Bad value \u201cdata:text/html,test#test\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Fragment is not allowed for data: URIs according to RFC 2397.",
+ "html/elements/embed/src/scheme-data-single-slash-novalid.html": "Bad value \u201cdata:/example.com/\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Expected a token character or a semicolon but saw \u201c/\u201d instead.",
+ "html/elements/embed/src/scheme-file-backslash-novalid.html": "Bad value \u201cfile:c:\\foo\\bar.html\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/embed/src/scheme-file-single-slash-c-bar-novalid.html": "Bad value \u201cfile:/C|/foo/bar\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/embed/src/scheme-file-triple-slash-c-bar-novalid.html": "Bad value \u201cfile:///C|/foo/bar\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/embed/src/scheme-ftp-no-slash-novalid.html": "Bad value \u201cftp:example.com/\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/embed/src/scheme-ftp-single-slash-novalid.html": "Bad value \u201cftp:/example.com/\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/embed/src/scheme-http-backslash-novalid.html": "Bad value \u201chttp:\\\\foo.com\\\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/embed/src/scheme-http-no-slash-colon-novalid.html": "Bad value \u201chttp::@c:29\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/embed/src/scheme-http-no-slash-novalid.html": "Bad value \u201chttp:foo.com\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/embed/src/scheme-http-no-slash-square-bracket-novalid.html": "Bad value \u201chttp:[61:27]/:foo\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/embed/src/scheme-http-single-slash-novalid.html": "Bad value \u201chttp:/example.com/\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/embed/src/scheme-https-no-slash-novalid.html": "Bad value \u201chttps:example.com/\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/embed/src/scheme-https-single-slash-novalid.html": "Bad value \u201chttps:/example.com/\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/embed/src/scheme-javascript-no-slash-malformed-novalid.html": "Bad value \u201cjavascript:example.com/\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: syntax error",
+ "html/elements/embed/src/scheme-trailing-cr-novalid.html": "Bad value \u201ca:\nfoo.com\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/embed/src/scheme-trailing-newline-novalid.html": "Bad value \u201ca:\nfoo.com\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/embed/src/scheme-trailing-space-novalid.html": "Bad value \u201ca: foo.com\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/embed/src/scheme-trailing-tab-novalid.html": "Bad value \u201ca:\tfoo.com\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/embed/src/userinfo-backslash-novalid.html": "Bad value \u201chttp://a\\b:c\\d@foo.com\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/embed/src/userinfo-password-bad-chars-novalid.html": "\u201c&\u201d did not start a character reference. (\u201c&\u201d probably should have been escaped as \u201c&amp;\u201d.)",
+ "html/elements/embed/src/userinfo-password-contains-pile-of-poo-novalid.html": "Bad value \u201chttp://foo:\ud83d\udca9@example.com\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Illegal character in user or password: not a URL code point.",
+ "html/elements/embed/src/userinfo-username-contains-at-sign-novalid.html": "Bad value \u201chttp://::@c@d:2\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: User or password contains an at symbol (\"@\") not percent-encoded.",
+ "html/elements/embed/src/userinfo-username-contains-pile-of-poo-novalid.html": "Bad value \u201chttp://\ud83d\udca9:foo@example.com\u201d for attribute \u201csrc\u201d on element \u201cembed\u201d: Bad URL: Illegal character in user or password: not a URL code point.",
+ "html/elements/embed/type-novalid.html": "Bad value \u201cfoo\u201d for attribute \u201ctype\u201d on element \u201cembed\u201d: Bad MIME type: Subtype missing.",
+ "html/elements/embed/width-novalid.html": "Bad value \u201c20%\u201d for attribute \u201cwidth\u201d on element \u201cembed\u201d: Bad non-negative integer: Expected a digit but saw \u201c%\u201d instead.",
+ "html/elements/footer/nested-footer-novalid.html": "The element \u201cfooter\u201d must not appear as a descendant of the \u201cfooter\u201d element.",
+ "html/elements/footer/nested-header-novalid.html": "The element \u201cheader\u201d must not appear as a descendant of the \u201cfooter\u201d element.",
+ "html/elements/form/action-empty-novalid.html": "Bad value \u201c\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Must be non-empty.",
+ "html/elements/form/action-whitespace-only-novalid.html": "Bad value \u201c\t \n\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Must be non-empty.",
+ "html/elements/form/action/fragment-backslash-novalid.html": "Bad value \u201c#\\\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/form/action/fragment-contains-hash-novalid.html": "Bad value \u201chttp://foo/path#f#g\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/form/action/fragment-leading-space-novalid.html": "Bad value \u201chttp://f:21/b# e\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/form/action/host-cr-novalid.html": "Bad value \u201chttp://example.\norg\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/form/action/host-double-percent-encoded-novalid.html": "Bad value \u201chttp://\uff05\uff14\uff11.com\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/form/action/host-double-percent-encoded-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%bc%85%ef%bc%94%ef%bc%91.com\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/form/action/host-empty-novalid.html": "Bad value \u201chttp://\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/form/action/host-empty-userinfo-empty-novalid.html": "Bad value \u201chttp://@/www.example.com\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/form/action/host-empty-with-userinfo-novalid.html": "Bad value \u201chttp://user:pass@/\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/form/action/host-hostname-in-brackets-novalid.html": "Bad value \u201chttp://[www.google.com]/\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Invalid host: Illegal character.",
+ "html/elements/form/action/host-invalid-unicode-novalid.html": "Forbidden code point U+fdd0.",
+ "html/elements/form/action/host-invalid-unicode-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%b7%90zyx.com\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Invalid host: A label or domain name contains disallowed characters..",
+ "html/elements/form/action/host-newline-novalid.html": "Bad value \u201chttp://example.\norg\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/form/action/host-space-novalid.html": "Bad value \u201chttp://example .org\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Invalid host: Domain contains invalid character: .",
+ "html/elements/form/action/host-square-brackets-port-contains-colon-novalid.html": "Bad value \u201chttp://[1::2]:3:4\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Illegal character in port.",
+ "html/elements/form/action/host-tab-novalid.html": "Bad value \u201chttp://example\t.org\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/form/action/host-u0000-percent-encoded-novalid.html": "Bad value \u201chttp://\uff05\uff10\uff10.com\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/form/action/host-u0000-percent-encoded-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%bc%85%ef%bc%90%ef%bc%90.com\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/form/action/path-bare-percent-sign-novalid.html": "Bad value \u201chttp://example.com/foo%\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Percentage (\"%\") is not followed by two hexadecimal digits.",
+ "html/elements/form/action/path-contains-space-novalid.html": "Bad value \u201c/a/ /c\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/form/action/path-leading-backslash-at-sign-novalid.html": "Bad value \u201chttp://foo.com/\\@\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/form/action/path-leading-colon-backslash-novalid.html": "Bad value \u201c:\\\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/form/action/path-leading-colon-chars-backslash-novalid.html": "Bad value \u201c:foo.com\\\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/form/action/path-leading-space-novalid.html": "Bad value \u201chttp://f:21/ b\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/form/action/path-percent-encoded-malformed-novalid.html": "Bad value \u201chttp://example.com/foo/%2e%2\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Percentage (\"%\") is not followed by two hexadecimal digits.",
+ "html/elements/form/action/path-relative-square-brackets-novalid.html": "Bad value \u201c[61:24:74]:98\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/form/action/path-tab-novalid.html": "Bad value \u201chttp://example.com/foo\tbar\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/form/action/path-trailing-space-novalid.html": "Bad value \u201chttp://f:21/b ?\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/form/action/path-u0091-novalid.html": "Forbidden code point U+0091.",
+ "html/elements/form/action/port-cr-novalid.html": "Bad value \u201chttp://f:\n/c\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/form/action/port-leading-colon-bracket-colon-novalid.html": "Bad value \u201chttp://2001::1]:80\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Illegal character in port.",
+ "html/elements/form/action/port-leading-colon-novalid.html": "Bad value \u201chttp://2001::1\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Illegal character in port.",
+ "html/elements/form/action/port-leading-dash-novalid.html": "Bad value \u201chttp://foo:-80/\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Illegal character in port.",
+ "html/elements/form/action/port-multiple-letters-novalid.html": "Bad value \u201chttp://f:fifty-two/c\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Illegal character in port.",
+ "html/elements/form/action/port-newline-novalid.html": "Bad value \u201chttp://f:\n/c\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/form/action/port-single-letter-novalid.html": "Bad value \u201chttp://f:b/c\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Illegal character in port.",
+ "html/elements/form/action/port-space-novalid.html": "Bad value \u201chttp://f: /c\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Illegal character in port.",
+ "html/elements/form/action/port-tab-novalid.html": "Bad value \u201chttp://f:\t/c\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/form/action/query-leading-space-novalid.html": "Bad value \u201chttp://f:21/b? d\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Illegal character in query: not a URL code point.",
+ "html/elements/form/action/query-trailing-space-novalid.html": "Bad value \u201chttp://f:21/b?d #\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Illegal character in query: not a URL code point.",
+ "html/elements/form/action/scheme-data-contains-fragment-haswarn.html": "Bad value \u201cdata:text/html,test#test\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Fragment is not allowed for data: URIs according to RFC 2397.",
+ "html/elements/form/action/scheme-data-single-slash-novalid.html": "Bad value \u201cdata:/example.com/\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Expected a token character or a semicolon but saw \u201c/\u201d instead.",
+ "html/elements/form/action/scheme-file-backslash-novalid.html": "Bad value \u201cfile:c:\\foo\\bar.html\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/form/action/scheme-file-single-slash-c-bar-novalid.html": "Bad value \u201cfile:/C|/foo/bar\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/form/action/scheme-file-triple-slash-c-bar-novalid.html": "Bad value \u201cfile:///C|/foo/bar\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/form/action/scheme-ftp-no-slash-novalid.html": "Bad value \u201cftp:example.com/\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/form/action/scheme-ftp-single-slash-novalid.html": "Bad value \u201cftp:/example.com/\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/form/action/scheme-http-backslash-novalid.html": "Bad value \u201chttp:\\\\foo.com\\\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/form/action/scheme-http-no-slash-colon-novalid.html": "Bad value \u201chttp::@c:29\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/form/action/scheme-http-no-slash-novalid.html": "Bad value \u201chttp:foo.com\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/form/action/scheme-http-no-slash-square-bracket-novalid.html": "Bad value \u201chttp:[61:27]/:foo\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/form/action/scheme-http-single-slash-novalid.html": "Bad value \u201chttp:/example.com/\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/form/action/scheme-https-no-slash-novalid.html": "Bad value \u201chttps:example.com/\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/form/action/scheme-https-single-slash-novalid.html": "Bad value \u201chttps:/example.com/\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/form/action/scheme-javascript-no-slash-malformed-novalid.html": "Bad value \u201cjavascript:example.com/\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: syntax error",
+ "html/elements/form/action/scheme-trailing-cr-novalid.html": "Bad value \u201ca:\nfoo.com\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/form/action/scheme-trailing-newline-novalid.html": "Bad value \u201ca:\nfoo.com\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/form/action/scheme-trailing-space-novalid.html": "Bad value \u201ca: foo.com\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/form/action/scheme-trailing-tab-novalid.html": "Bad value \u201ca:\tfoo.com\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/form/action/userinfo-backslash-novalid.html": "Bad value \u201chttp://a\\b:c\\d@foo.com\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/form/action/userinfo-password-bad-chars-novalid.html": "\u201c&\u201d did not start a character reference. (\u201c&\u201d probably should have been escaped as \u201c&amp;\u201d.)",
+ "html/elements/form/action/userinfo-password-contains-pile-of-poo-novalid.html": "Bad value \u201chttp://foo:\ud83d\udca9@example.com\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Illegal character in user or password: not a URL code point.",
+ "html/elements/form/action/userinfo-username-contains-at-sign-novalid.html": "Bad value \u201chttp://::@c@d:2\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: User or password contains an at symbol (\"@\") not percent-encoded.",
+ "html/elements/form/action/userinfo-username-contains-pile-of-poo-novalid.html": "Bad value \u201chttp://\ud83d\udca9:foo@example.com\u201d for attribute \u201caction\u201d on element \u201cform\u201d: Bad URL: Illegal character in user or password: not a URL code point.",
+ "html/elements/h1/model-novalid.html": "End tag \u201cp\u201d implied, but there were open elements.",
+ "html/elements/h2/model-novalid.html": "End tag \u201cp\u201d implied, but there were open elements.",
+ "html/elements/h3/model-novalid.html": "End tag \u201cp\u201d implied, but there were open elements.",
+ "html/elements/h4/model-novalid.html": "End tag \u201cp\u201d implied, but there were open elements.",
+ "html/elements/h5/model-novalid.html": "End tag \u201cp\u201d implied, but there were open elements.",
+ "html/elements/h6/model-novalid.html": "End tag \u201cp\u201d implied, but there were open elements.",
+ "html/elements/header/nested-footer-novalid.html": "The element \u201cfooter\u201d must not appear as a descendant of the \u201cheader\u201d element.",
+ "html/elements/header/nested-header-novalid.html": "The element \u201cheader\u201d must not appear as a descendant of the \u201cheader\u201d element.",
+ "html/elements/hr/model-novalid.html": "No \u201cp\u201d element in scope but a \u201cp\u201d end tag seen.",
+ "html/elements/html/manifest-empty-novalid.html": "Bad value \u201c\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Must be non-empty.",
+ "html/elements/html/manifest-whitespace-only-novalid.html": "Bad value \u201c\t \n\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Must be non-empty.",
+ "html/elements/html/manifest/fragment-backslash-novalid.html": "Bad value \u201c#\\\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/html/manifest/fragment-contains-hash-novalid.html": "Bad value \u201chttp://foo/path#f#g\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/html/manifest/fragment-leading-space-novalid.html": "Bad value \u201chttp://f:21/b# e\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/html/manifest/host-cr-novalid.html": "Bad value \u201chttp://example.\norg\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/html/manifest/host-double-percent-encoded-novalid.html": "Bad value \u201chttp://\uff05\uff14\uff11.com\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/html/manifest/host-double-percent-encoded-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%bc%85%ef%bc%94%ef%bc%91.com\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/html/manifest/host-empty-novalid.html": "Bad value \u201chttp://\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/html/manifest/host-empty-userinfo-empty-novalid.html": "Bad value \u201chttp://@/www.example.com\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/html/manifest/host-empty-with-userinfo-novalid.html": "Bad value \u201chttp://user:pass@/\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/html/manifest/host-hostname-in-brackets-novalid.html": "Bad value \u201chttp://[www.google.com]/\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Invalid host: Illegal character.",
+ "html/elements/html/manifest/host-invalid-unicode-novalid.html": "Forbidden code point U+fdd0.",
+ "html/elements/html/manifest/host-invalid-unicode-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%b7%90zyx.com\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Invalid host: A label or domain name contains disallowed characters..",
+ "html/elements/html/manifest/host-newline-novalid.html": "Bad value \u201chttp://example.\norg\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/html/manifest/host-space-novalid.html": "Bad value \u201chttp://example .org\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Invalid host: Domain contains invalid character: .",
+ "html/elements/html/manifest/host-square-brackets-port-contains-colon-novalid.html": "Bad value \u201chttp://[1::2]:3:4\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Illegal character in port.",
+ "html/elements/html/manifest/host-tab-novalid.html": "Bad value \u201chttp://example\t.org\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/html/manifest/host-u0000-percent-encoded-novalid.html": "Bad value \u201chttp://\uff05\uff10\uff10.com\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/html/manifest/host-u0000-percent-encoded-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%bc%85%ef%bc%90%ef%bc%90.com\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/html/manifest/path-bare-percent-sign-novalid.html": "Bad value \u201chttp://example.com/foo%\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Percentage (\"%\") is not followed by two hexadecimal digits.",
+ "html/elements/html/manifest/path-contains-space-novalid.html": "Bad value \u201c/a/ /c\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/html/manifest/path-leading-backslash-at-sign-novalid.html": "Bad value \u201chttp://foo.com/\\@\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/html/manifest/path-leading-colon-backslash-novalid.html": "Bad value \u201c:\\\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/html/manifest/path-leading-colon-chars-backslash-novalid.html": "Bad value \u201c:foo.com\\\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/html/manifest/path-leading-space-novalid.html": "Bad value \u201chttp://f:21/ b\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/html/manifest/path-percent-encoded-malformed-novalid.html": "Bad value \u201chttp://example.com/foo/%2e%2\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Percentage (\"%\") is not followed by two hexadecimal digits.",
+ "html/elements/html/manifest/path-relative-square-brackets-novalid.html": "Bad value \u201c[61:24:74]:98\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/html/manifest/path-tab-novalid.html": "Bad value \u201chttp://example.com/foo\tbar\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/html/manifest/path-trailing-space-novalid.html": "Bad value \u201chttp://f:21/b ?\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/html/manifest/path-u0091-novalid.html": "Forbidden code point U+0091.",
+ "html/elements/html/manifest/port-cr-novalid.html": "Bad value \u201chttp://f:\n/c\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/html/manifest/port-leading-colon-bracket-colon-novalid.html": "Bad value \u201chttp://2001::1]:80\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Illegal character in port.",
+ "html/elements/html/manifest/port-leading-colon-novalid.html": "Bad value \u201chttp://2001::1\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Illegal character in port.",
+ "html/elements/html/manifest/port-leading-dash-novalid.html": "Bad value \u201chttp://foo:-80/\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Illegal character in port.",
+ "html/elements/html/manifest/port-multiple-letters-novalid.html": "Bad value \u201chttp://f:fifty-two/c\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Illegal character in port.",
+ "html/elements/html/manifest/port-newline-novalid.html": "Bad value \u201chttp://f:\n/c\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/html/manifest/port-single-letter-novalid.html": "Bad value \u201chttp://f:b/c\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Illegal character in port.",
+ "html/elements/html/manifest/port-space-novalid.html": "Bad value \u201chttp://f: /c\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Illegal character in port.",
+ "html/elements/html/manifest/port-tab-novalid.html": "Bad value \u201chttp://f:\t/c\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/html/manifest/query-leading-space-novalid.html": "Bad value \u201chttp://f:21/b? d\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Illegal character in query: not a URL code point.",
+ "html/elements/html/manifest/query-trailing-space-novalid.html": "Bad value \u201chttp://f:21/b?d #\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Illegal character in query: not a URL code point.",
+ "html/elements/html/manifest/scheme-data-contains-fragment-haswarn.html": "Bad value \u201cdata:text/html,test#test\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Fragment is not allowed for data: URIs according to RFC 2397.",
+ "html/elements/html/manifest/scheme-data-single-slash-novalid.html": "Bad value \u201cdata:/example.com/\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Expected a token character or a semicolon but saw \u201c/\u201d instead.",
+ "html/elements/html/manifest/scheme-file-backslash-novalid.html": "Bad value \u201cfile:c:\\foo\\bar.html\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/html/manifest/scheme-file-single-slash-c-bar-novalid.html": "Bad value \u201cfile:/C|/foo/bar\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/html/manifest/scheme-file-triple-slash-c-bar-novalid.html": "Bad value \u201cfile:///C|/foo/bar\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/html/manifest/scheme-ftp-no-slash-novalid.html": "Bad value \u201cftp:example.com/\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/html/manifest/scheme-ftp-single-slash-novalid.html": "Bad value \u201cftp:/example.com/\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/html/manifest/scheme-http-backslash-novalid.html": "Bad value \u201chttp:\\\\foo.com\\\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/html/manifest/scheme-http-no-slash-colon-novalid.html": "Bad value \u201chttp::@c:29\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/html/manifest/scheme-http-no-slash-novalid.html": "Bad value \u201chttp:foo.com\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/html/manifest/scheme-http-no-slash-square-bracket-novalid.html": "Bad value \u201chttp:[61:27]/:foo\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/html/manifest/scheme-http-single-slash-novalid.html": "Bad value \u201chttp:/example.com/\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/html/manifest/scheme-https-no-slash-novalid.html": "Bad value \u201chttps:example.com/\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/html/manifest/scheme-https-single-slash-novalid.html": "Bad value \u201chttps:/example.com/\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/html/manifest/scheme-javascript-no-slash-malformed-novalid.html": "Bad value \u201cjavascript:example.com/\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: syntax error",
+ "html/elements/html/manifest/scheme-trailing-cr-novalid.html": "Bad value \u201ca:\nfoo.com\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/html/manifest/scheme-trailing-newline-novalid.html": "Bad value \u201ca:\nfoo.com\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/html/manifest/scheme-trailing-space-novalid.html": "Bad value \u201ca: foo.com\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/html/manifest/scheme-trailing-tab-novalid.html": "Bad value \u201ca:\tfoo.com\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/html/manifest/userinfo-backslash-novalid.html": "Bad value \u201chttp://a\\b:c\\d@foo.com\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/html/manifest/userinfo-password-bad-chars-novalid.html": "\u201c&\u201d did not start a character reference. (\u201c&\u201d probably should have been escaped as \u201c&amp;\u201d.)",
+ "html/elements/html/manifest/userinfo-password-contains-pile-of-poo-novalid.html": "Bad value \u201chttp://foo:\ud83d\udca9@example.com\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Illegal character in user or password: not a URL code point.",
+ "html/elements/html/manifest/userinfo-username-contains-at-sign-novalid.html": "Bad value \u201chttp://::@c@d:2\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: User or password contains an at symbol (\"@\") not percent-encoded.",
+ "html/elements/html/manifest/userinfo-username-contains-pile-of-poo-novalid.html": "Bad value \u201chttp://\ud83d\udca9:foo@example.com\u201d for attribute \u201cmanifest\u201d on element \u201chtml\u201d: Bad URL: Illegal character in user or password: not a URL code point.",
+ "html/elements/i/model-novalid.html": "End tag \u201cp\u201d implied, but there were open elements.",
+ "html/elements/iframe/model-novalid.html": "The \u201cframeborder\u201d attribute on the \u201ciframe\u201d element is obsolete. Use CSS instead.",
+ "html/elements/iframe/src-empty-novalid.html": "Bad value \u201c\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Must be non-empty.",
+ "html/elements/iframe/src-whitespace-only-novalid.html": "Bad value \u201c\t \n\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Must be non-empty.",
+ "html/elements/iframe/src/fragment-backslash-novalid.html": "Bad value \u201c#\\\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/iframe/src/fragment-contains-hash-novalid.html": "Bad value \u201chttp://foo/path#f#g\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/iframe/src/fragment-leading-space-novalid.html": "Bad value \u201chttp://f:21/b# e\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/iframe/src/host-cr-novalid.html": "Bad value \u201chttp://example.\norg\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/iframe/src/host-double-percent-encoded-novalid.html": "Bad value \u201chttp://\uff05\uff14\uff11.com\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/iframe/src/host-double-percent-encoded-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%bc%85%ef%bc%94%ef%bc%91.com\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/iframe/src/host-empty-novalid.html": "Bad value \u201chttp://\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/iframe/src/host-empty-userinfo-empty-novalid.html": "Bad value \u201chttp://@/www.example.com\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/iframe/src/host-empty-with-userinfo-novalid.html": "Bad value \u201chttp://user:pass@/\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/iframe/src/host-hostname-in-brackets-novalid.html": "Bad value \u201chttp://[www.google.com]/\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Invalid host: Illegal character.",
+ "html/elements/iframe/src/host-invalid-unicode-novalid.html": "Forbidden code point U+fdd0.",
+ "html/elements/iframe/src/host-invalid-unicode-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%b7%90zyx.com\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Invalid host: A label or domain name contains disallowed characters..",
+ "html/elements/iframe/src/host-newline-novalid.html": "Bad value \u201chttp://example.\norg\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/iframe/src/host-space-novalid.html": "Bad value \u201chttp://example .org\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Invalid host: Domain contains invalid character: .",
+ "html/elements/iframe/src/host-square-brackets-port-contains-colon-novalid.html": "Bad value \u201chttp://[1::2]:3:4\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Illegal character in port.",
+ "html/elements/iframe/src/host-tab-novalid.html": "Bad value \u201chttp://example\t.org\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/iframe/src/host-u0000-percent-encoded-novalid.html": "Bad value \u201chttp://\uff05\uff10\uff10.com\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/iframe/src/host-u0000-percent-encoded-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%bc%85%ef%bc%90%ef%bc%90.com\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/iframe/src/path-bare-percent-sign-novalid.html": "Bad value \u201chttp://example.com/foo%\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Percentage (\"%\") is not followed by two hexadecimal digits.",
+ "html/elements/iframe/src/path-contains-space-novalid.html": "Bad value \u201c/a/ /c\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/iframe/src/path-leading-backslash-at-sign-novalid.html": "Bad value \u201chttp://foo.com/\\@\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/iframe/src/path-leading-colon-backslash-novalid.html": "Bad value \u201c:\\\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/iframe/src/path-leading-colon-chars-backslash-novalid.html": "Bad value \u201c:foo.com\\\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/iframe/src/path-leading-space-novalid.html": "Bad value \u201chttp://f:21/ b\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/iframe/src/path-percent-encoded-malformed-novalid.html": "Bad value \u201chttp://example.com/foo/%2e%2\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Percentage (\"%\") is not followed by two hexadecimal digits.",
+ "html/elements/iframe/src/path-relative-square-brackets-novalid.html": "Bad value \u201c[61:24:74]:98\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/iframe/src/path-tab-novalid.html": "Bad value \u201chttp://example.com/foo\tbar\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/iframe/src/path-trailing-space-novalid.html": "Bad value \u201chttp://f:21/b ?\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/iframe/src/path-u0091-novalid.html": "Forbidden code point U+0091.",
+ "html/elements/iframe/src/port-cr-novalid.html": "Bad value \u201chttp://f:\n/c\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/iframe/src/port-leading-colon-bracket-colon-novalid.html": "Bad value \u201chttp://2001::1]:80\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Illegal character in port.",
+ "html/elements/iframe/src/port-leading-colon-novalid.html": "Bad value \u201chttp://2001::1\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Illegal character in port.",
+ "html/elements/iframe/src/port-leading-dash-novalid.html": "Bad value \u201chttp://foo:-80/\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Illegal character in port.",
+ "html/elements/iframe/src/port-multiple-letters-novalid.html": "Bad value \u201chttp://f:fifty-two/c\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Illegal character in port.",
+ "html/elements/iframe/src/port-newline-novalid.html": "Bad value \u201chttp://f:\n/c\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/iframe/src/port-single-letter-novalid.html": "Bad value \u201chttp://f:b/c\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Illegal character in port.",
+ "html/elements/iframe/src/port-space-novalid.html": "Bad value \u201chttp://f: /c\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Illegal character in port.",
+ "html/elements/iframe/src/port-tab-novalid.html": "Bad value \u201chttp://f:\t/c\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/iframe/src/query-leading-space-novalid.html": "Bad value \u201chttp://f:21/b? d\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Illegal character in query: not a URL code point.",
+ "html/elements/iframe/src/query-trailing-space-novalid.html": "Bad value \u201chttp://f:21/b?d #\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Illegal character in query: not a URL code point.",
+ "html/elements/iframe/src/scheme-data-contains-fragment-haswarn.html": "Bad value \u201cdata:text/html,test#test\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Fragment is not allowed for data: URIs according to RFC 2397.",
+ "html/elements/iframe/src/scheme-data-single-slash-novalid.html": "Bad value \u201cdata:/example.com/\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Expected a token character or a semicolon but saw \u201c/\u201d instead.",
+ "html/elements/iframe/src/scheme-file-backslash-novalid.html": "Bad value \u201cfile:c:\\foo\\bar.html\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/iframe/src/scheme-file-single-slash-c-bar-novalid.html": "Bad value \u201cfile:/C|/foo/bar\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/iframe/src/scheme-file-triple-slash-c-bar-novalid.html": "Bad value \u201cfile:///C|/foo/bar\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/iframe/src/scheme-ftp-no-slash-novalid.html": "Bad value \u201cftp:example.com/\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/iframe/src/scheme-ftp-single-slash-novalid.html": "Bad value \u201cftp:/example.com/\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/iframe/src/scheme-http-backslash-novalid.html": "Bad value \u201chttp:\\\\foo.com\\\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/iframe/src/scheme-http-no-slash-colon-novalid.html": "Bad value \u201chttp::@c:29\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/iframe/src/scheme-http-no-slash-novalid.html": "Bad value \u201chttp:foo.com\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/iframe/src/scheme-http-no-slash-square-bracket-novalid.html": "Bad value \u201chttp:[61:27]/:foo\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/iframe/src/scheme-http-single-slash-novalid.html": "Bad value \u201chttp:/example.com/\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/iframe/src/scheme-https-no-slash-novalid.html": "Bad value \u201chttps:example.com/\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/iframe/src/scheme-https-single-slash-novalid.html": "Bad value \u201chttps:/example.com/\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/iframe/src/scheme-javascript-no-slash-malformed-novalid.html": "Bad value \u201cjavascript:example.com/\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: syntax error",
+ "html/elements/iframe/src/scheme-trailing-cr-novalid.html": "Bad value \u201ca:\nfoo.com\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/iframe/src/scheme-trailing-newline-novalid.html": "Bad value \u201ca:\nfoo.com\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/iframe/src/scheme-trailing-space-novalid.html": "Bad value \u201ca: foo.com\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/iframe/src/scheme-trailing-tab-novalid.html": "Bad value \u201ca:\tfoo.com\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/iframe/src/userinfo-backslash-novalid.html": "Bad value \u201chttp://a\\b:c\\d@foo.com\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/iframe/src/userinfo-password-bad-chars-novalid.html": "\u201c&\u201d did not start a character reference. (\u201c&\u201d probably should have been escaped as \u201c&amp;\u201d.)",
+ "html/elements/iframe/src/userinfo-password-contains-pile-of-poo-novalid.html": "Bad value \u201chttp://foo:\ud83d\udca9@example.com\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Illegal character in user or password: not a URL code point.",
+ "html/elements/iframe/src/userinfo-username-contains-at-sign-novalid.html": "Bad value \u201chttp://::@c@d:2\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: User or password contains an at symbol (\"@\") not percent-encoded.",
+ "html/elements/iframe/src/userinfo-username-contains-pile-of-poo-novalid.html": "Bad value \u201chttp://\ud83d\udca9:foo@example.com\u201d for attribute \u201csrc\u201d on element \u201ciframe\u201d: Bad URL: Illegal character in user or password: not a URL code point.",
+ "html/elements/img/model-novalid.html": "Bad value \u201curl\u201d for attribute \u201cusemap\u201d on element \u201cimg\u201d: Bad hash-name reference: A hash-name reference must start with \u201c#\u201d.",
+ "html/elements/img/src-empty-novalid.html": "Bad value \u201c\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Must be non-empty.",
+ "html/elements/img/src-whitespace-only-novalid.html": "Bad value \u201c\t \n\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Must be non-empty.",
+ "html/elements/img/src/fragment-backslash-novalid.html": "Bad value \u201c#\\\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/img/src/fragment-contains-hash-novalid.html": "Bad value \u201chttp://foo/path#f#g\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/img/src/fragment-leading-space-novalid.html": "Bad value \u201chttp://f:21/b# e\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/img/src/host-cr-novalid.html": "Bad value \u201chttp://example.\norg\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/img/src/host-double-percent-encoded-novalid.html": "Bad value \u201chttp://\uff05\uff14\uff11.com\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/img/src/host-double-percent-encoded-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%bc%85%ef%bc%94%ef%bc%91.com\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/img/src/host-empty-novalid.html": "Bad value \u201chttp://\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/img/src/host-empty-userinfo-empty-novalid.html": "Bad value \u201chttp://@/www.example.com\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/img/src/host-empty-with-userinfo-novalid.html": "Bad value \u201chttp://user:pass@/\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/img/src/host-hostname-in-brackets-novalid.html": "Bad value \u201chttp://[www.google.com]/\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Invalid host: Illegal character.",
+ "html/elements/img/src/host-invalid-unicode-novalid.html": "Forbidden code point U+fdd0.",
+ "html/elements/img/src/host-invalid-unicode-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%b7%90zyx.com\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Invalid host: A label or domain name contains disallowed characters..",
+ "html/elements/img/src/host-newline-novalid.html": "Bad value \u201chttp://example.\norg\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/img/src/host-space-novalid.html": "Bad value \u201chttp://example .org\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Invalid host: Domain contains invalid character: .",
+ "html/elements/img/src/host-square-brackets-port-contains-colon-novalid.html": "Bad value \u201chttp://[1::2]:3:4\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Illegal character in port.",
+ "html/elements/img/src/host-tab-novalid.html": "Bad value \u201chttp://example\t.org\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/img/src/host-u0000-percent-encoded-novalid.html": "Bad value \u201chttp://\uff05\uff10\uff10.com\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/img/src/host-u0000-percent-encoded-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%bc%85%ef%bc%90%ef%bc%90.com\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/img/src/path-bare-percent-sign-novalid.html": "Bad value \u201chttp://example.com/foo%\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Percentage (\"%\") is not followed by two hexadecimal digits.",
+ "html/elements/img/src/path-contains-space-novalid.html": "Bad value \u201c/a/ /c\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/img/src/path-leading-backslash-at-sign-novalid.html": "Bad value \u201chttp://foo.com/\\@\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/img/src/path-leading-colon-backslash-novalid.html": "Bad value \u201c:\\\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/img/src/path-leading-colon-chars-backslash-novalid.html": "Bad value \u201c:foo.com\\\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/img/src/path-leading-space-novalid.html": "Bad value \u201chttp://f:21/ b\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/img/src/path-percent-encoded-malformed-novalid.html": "Bad value \u201chttp://example.com/foo/%2e%2\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Percentage (\"%\") is not followed by two hexadecimal digits.",
+ "html/elements/img/src/path-relative-square-brackets-novalid.html": "Bad value \u201c[61:24:74]:98\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/img/src/path-tab-novalid.html": "Bad value \u201chttp://example.com/foo\tbar\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/img/src/path-trailing-space-novalid.html": "Bad value \u201chttp://f:21/b ?\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/img/src/path-u0091-novalid.html": "Forbidden code point U+0091.",
+ "html/elements/img/src/port-cr-novalid.html": "Bad value \u201chttp://f:\n/c\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/img/src/port-leading-colon-bracket-colon-novalid.html": "Bad value \u201chttp://2001::1]:80\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Illegal character in port.",
+ "html/elements/img/src/port-leading-colon-novalid.html": "Bad value \u201chttp://2001::1\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Illegal character in port.",
+ "html/elements/img/src/port-leading-dash-novalid.html": "Bad value \u201chttp://foo:-80/\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Illegal character in port.",
+ "html/elements/img/src/port-multiple-letters-novalid.html": "Bad value \u201chttp://f:fifty-two/c\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Illegal character in port.",
+ "html/elements/img/src/port-newline-novalid.html": "Bad value \u201chttp://f:\n/c\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/img/src/port-single-letter-novalid.html": "Bad value \u201chttp://f:b/c\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Illegal character in port.",
+ "html/elements/img/src/port-space-novalid.html": "Bad value \u201chttp://f: /c\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Illegal character in port.",
+ "html/elements/img/src/port-tab-novalid.html": "Bad value \u201chttp://f:\t/c\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/img/src/query-leading-space-novalid.html": "Bad value \u201chttp://f:21/b? d\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Illegal character in query: not a URL code point.",
+ "html/elements/img/src/query-trailing-space-novalid.html": "Bad value \u201chttp://f:21/b?d #\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Illegal character in query: not a URL code point.",
+ "html/elements/img/src/scheme-data-contains-fragment-haswarn.html": "Bad value \u201cdata:text/html,test#test\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Fragment is not allowed for data: URIs according to RFC 2397.",
+ "html/elements/img/src/scheme-data-single-slash-novalid.html": "Bad value \u201cdata:/example.com/\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Expected a token character or a semicolon but saw \u201c/\u201d instead.",
+ "html/elements/img/src/scheme-file-backslash-novalid.html": "Bad value \u201cfile:c:\\foo\\bar.html\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/img/src/scheme-file-single-slash-c-bar-novalid.html": "Bad value \u201cfile:/C|/foo/bar\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/img/src/scheme-file-triple-slash-c-bar-novalid.html": "Bad value \u201cfile:///C|/foo/bar\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/img/src/scheme-ftp-no-slash-novalid.html": "Bad value \u201cftp:example.com/\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/img/src/scheme-ftp-single-slash-novalid.html": "Bad value \u201cftp:/example.com/\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/img/src/scheme-http-backslash-novalid.html": "Bad value \u201chttp:\\\\foo.com\\\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/img/src/scheme-http-no-slash-colon-novalid.html": "Bad value \u201chttp::@c:29\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/img/src/scheme-http-no-slash-novalid.html": "Bad value \u201chttp:foo.com\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/img/src/scheme-http-no-slash-square-bracket-novalid.html": "Bad value \u201chttp:[61:27]/:foo\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/img/src/scheme-http-single-slash-novalid.html": "Bad value \u201chttp:/example.com/\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/img/src/scheme-https-no-slash-novalid.html": "Bad value \u201chttps:example.com/\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/img/src/scheme-https-single-slash-novalid.html": "Bad value \u201chttps:/example.com/\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/img/src/scheme-javascript-no-slash-malformed-novalid.html": "Bad value \u201cjavascript:example.com/\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: syntax error",
+ "html/elements/img/src/scheme-trailing-cr-novalid.html": "Bad value \u201ca:\nfoo.com\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/img/src/scheme-trailing-newline-novalid.html": "Bad value \u201ca:\nfoo.com\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/img/src/scheme-trailing-space-novalid.html": "Bad value \u201ca: foo.com\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/img/src/scheme-trailing-tab-novalid.html": "Bad value \u201ca:\tfoo.com\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/img/src/userinfo-backslash-novalid.html": "Bad value \u201chttp://a\\b:c\\d@foo.com\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/img/src/userinfo-password-bad-chars-novalid.html": "\u201c&\u201d did not start a character reference. (\u201c&\u201d probably should have been escaped as \u201c&amp;\u201d.)",
+ "html/elements/img/src/userinfo-password-contains-pile-of-poo-novalid.html": "Bad value \u201chttp://foo:\ud83d\udca9@example.com\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Illegal character in user or password: not a URL code point.",
+ "html/elements/img/src/userinfo-username-contains-at-sign-novalid.html": "Bad value \u201chttp://::@c@d:2\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: User or password contains an at symbol (\"@\") not percent-encoded.",
+ "html/elements/img/src/userinfo-username-contains-pile-of-poo-novalid.html": "Bad value \u201chttp://\ud83d\udca9:foo@example.com\u201d for attribute \u201csrc\u201d on element \u201cimg\u201d: Bad URL: Illegal character in user or password: not a URL code point.",
+ "html/elements/img/usemap-bad-value-novalid.html": "Bad value \u201c#\u201d for attribute \u201cusemap\u201d on element \u201cimg\u201d: Bad hash-name reference: A hash-name reference must have at least one character after \u201c#\u201d.",
+ "html/elements/img/width-height-negative-novalid.html": "Bad value \u201c-1\u201d for attribute \u201cwidth\u201d on element \u201cimg\u201d: Bad non-negative integer: Expected a digit but saw \u201c-\u201d instead.",
+ "html/elements/input/list-novalid.html": "The \u201clist\u201d attribute of the \u201cinput\u201d element must refer to a \u201cdatalist\u201d element.",
+ "html/elements/input/pattern-asterisk-novalid.html": "Bad value \u201c*\u201d for attribute \u201cpattern\u201d on element \u201cinput\u201d: Bad pattern: Invalid quantifier *",
+ "html/elements/input/pattern-paren-novalid.html": "Bad value \u201c(\u201d for attribute \u201cpattern\u201d on element \u201cinput\u201d: Bad pattern: Unterminated parenthetical ",
+ "html/elements/input/type-image-formaction-empty-novalid.html": "Bad value \u201c\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Must be non-empty.",
+ "html/elements/input/type-image-formaction-whitespace-only-novalid.html": "Bad value \u201c\t \n\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Must be non-empty.",
+ "html/elements/input/type-image-formaction/fragment-backslash-novalid.html": "Bad value \u201c#\\\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/input/type-image-formaction/fragment-contains-hash-novalid.html": "Bad value \u201chttp://foo/path#f#g\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/input/type-image-formaction/fragment-leading-space-novalid.html": "Bad value \u201chttp://f:21/b# e\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/input/type-image-formaction/host-cr-novalid.html": "Bad value \u201chttp://example.\norg\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/input/type-image-formaction/host-double-percent-encoded-novalid.html": "Bad value \u201chttp://\uff05\uff14\uff11.com\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/input/type-image-formaction/host-double-percent-encoded-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%bc%85%ef%bc%94%ef%bc%91.com\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/input/type-image-formaction/host-empty-novalid.html": "Bad value \u201chttp://\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/input/type-image-formaction/host-empty-userinfo-empty-novalid.html": "Bad value \u201chttp://@/www.example.com\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/input/type-image-formaction/host-empty-with-userinfo-novalid.html": "Bad value \u201chttp://user:pass@/\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/input/type-image-formaction/host-hostname-in-brackets-novalid.html": "Bad value \u201chttp://[www.google.com]/\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Invalid host: Illegal character.",
+ "html/elements/input/type-image-formaction/host-invalid-unicode-novalid.html": "Forbidden code point U+fdd0.",
+ "html/elements/input/type-image-formaction/host-invalid-unicode-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%b7%90zyx.com\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Invalid host: A label or domain name contains disallowed characters..",
+ "html/elements/input/type-image-formaction/host-newline-novalid.html": "Bad value \u201chttp://example.\norg\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/input/type-image-formaction/host-space-novalid.html": "Bad value \u201chttp://example .org\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Invalid host: Domain contains invalid character: .",
+ "html/elements/input/type-image-formaction/host-square-brackets-port-contains-colon-novalid.html": "Bad value \u201chttp://[1::2]:3:4\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Illegal character in port.",
+ "html/elements/input/type-image-formaction/host-tab-novalid.html": "Bad value \u201chttp://example\t.org\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/input/type-image-formaction/host-u0000-percent-encoded-novalid.html": "Bad value \u201chttp://\uff05\uff10\uff10.com\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/input/type-image-formaction/host-u0000-percent-encoded-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%bc%85%ef%bc%90%ef%bc%90.com\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/input/type-image-formaction/path-bare-percent-sign-novalid.html": "Bad value \u201chttp://example.com/foo%\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Percentage (\"%\") is not followed by two hexadecimal digits.",
+ "html/elements/input/type-image-formaction/path-contains-space-novalid.html": "Bad value \u201c/a/ /c\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/input/type-image-formaction/path-leading-backslash-at-sign-novalid.html": "Bad value \u201chttp://foo.com/\\@\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/input/type-image-formaction/path-leading-colon-backslash-novalid.html": "Bad value \u201c:\\\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/input/type-image-formaction/path-leading-colon-chars-backslash-novalid.html": "Bad value \u201c:foo.com\\\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/input/type-image-formaction/path-leading-space-novalid.html": "Bad value \u201chttp://f:21/ b\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/input/type-image-formaction/path-percent-encoded-malformed-novalid.html": "Bad value \u201chttp://example.com/foo/%2e%2\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Percentage (\"%\") is not followed by two hexadecimal digits.",
+ "html/elements/input/type-image-formaction/path-relative-square-brackets-novalid.html": "Bad value \u201c[61:24:74]:98\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/input/type-image-formaction/path-tab-novalid.html": "Bad value \u201chttp://example.com/foo\tbar\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/input/type-image-formaction/path-trailing-space-novalid.html": "Bad value \u201chttp://f:21/b ?\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/input/type-image-formaction/path-u0091-novalid.html": "Forbidden code point U+0091.",
+ "html/elements/input/type-image-formaction/port-cr-novalid.html": "Bad value \u201chttp://f:\n/c\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/input/type-image-formaction/port-leading-colon-bracket-colon-novalid.html": "Bad value \u201chttp://2001::1]:80\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Illegal character in port.",
+ "html/elements/input/type-image-formaction/port-leading-colon-novalid.html": "Bad value \u201chttp://2001::1\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Illegal character in port.",
+ "html/elements/input/type-image-formaction/port-leading-dash-novalid.html": "Bad value \u201chttp://foo:-80/\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Illegal character in port.",
+ "html/elements/input/type-image-formaction/port-multiple-letters-novalid.html": "Bad value \u201chttp://f:fifty-two/c\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Illegal character in port.",
+ "html/elements/input/type-image-formaction/port-newline-novalid.html": "Bad value \u201chttp://f:\n/c\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/input/type-image-formaction/port-single-letter-novalid.html": "Bad value \u201chttp://f:b/c\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Illegal character in port.",
+ "html/elements/input/type-image-formaction/port-space-novalid.html": "Bad value \u201chttp://f: /c\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Illegal character in port.",
+ "html/elements/input/type-image-formaction/port-tab-novalid.html": "Bad value \u201chttp://f:\t/c\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/input/type-image-formaction/query-leading-space-novalid.html": "Bad value \u201chttp://f:21/b? d\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Illegal character in query: not a URL code point.",
+ "html/elements/input/type-image-formaction/query-trailing-space-novalid.html": "Bad value \u201chttp://f:21/b?d #\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Illegal character in query: not a URL code point.",
+ "html/elements/input/type-image-formaction/scheme-data-contains-fragment-haswarn.html": "Bad value \u201cdata:text/html,test#test\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Fragment is not allowed for data: URIs according to RFC 2397.",
+ "html/elements/input/type-image-formaction/scheme-data-single-slash-novalid.html": "Bad value \u201cdata:/example.com/\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Expected a token character or a semicolon but saw \u201c/\u201d instead.",
+ "html/elements/input/type-image-formaction/scheme-file-backslash-novalid.html": "Bad value \u201cfile:c:\\foo\\bar.html\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/input/type-image-formaction/scheme-file-single-slash-c-bar-novalid.html": "Bad value \u201cfile:/C|/foo/bar\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/input/type-image-formaction/scheme-file-triple-slash-c-bar-novalid.html": "Bad value \u201cfile:///C|/foo/bar\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/input/type-image-formaction/scheme-ftp-no-slash-novalid.html": "Bad value \u201cftp:example.com/\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/input/type-image-formaction/scheme-ftp-single-slash-novalid.html": "Bad value \u201cftp:/example.com/\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/input/type-image-formaction/scheme-http-backslash-novalid.html": "Bad value \u201chttp:\\\\foo.com\\\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/input/type-image-formaction/scheme-http-no-slash-colon-novalid.html": "Bad value \u201chttp::@c:29\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/input/type-image-formaction/scheme-http-no-slash-novalid.html": "Bad value \u201chttp:foo.com\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/input/type-image-formaction/scheme-http-no-slash-square-bracket-novalid.html": "Bad value \u201chttp:[61:27]/:foo\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/input/type-image-formaction/scheme-http-single-slash-novalid.html": "Bad value \u201chttp:/example.com/\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/input/type-image-formaction/scheme-https-no-slash-novalid.html": "Bad value \u201chttps:example.com/\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/input/type-image-formaction/scheme-https-single-slash-novalid.html": "Bad value \u201chttps:/example.com/\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/input/type-image-formaction/scheme-javascript-no-slash-malformed-novalid.html": "Bad value \u201cjavascript:example.com/\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: syntax error",
+ "html/elements/input/type-image-formaction/scheme-trailing-cr-novalid.html": "Bad value \u201ca:\nfoo.com\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/input/type-image-formaction/scheme-trailing-newline-novalid.html": "Bad value \u201ca:\nfoo.com\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/input/type-image-formaction/scheme-trailing-space-novalid.html": "Bad value \u201ca: foo.com\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/input/type-image-formaction/scheme-trailing-tab-novalid.html": "Bad value \u201ca:\tfoo.com\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/input/type-image-formaction/userinfo-backslash-novalid.html": "Bad value \u201chttp://a\\b:c\\d@foo.com\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/input/type-image-formaction/userinfo-password-bad-chars-novalid.html": "\u201c&\u201d did not start a character reference. (\u201c&\u201d probably should have been escaped as \u201c&amp;\u201d.)",
+ "html/elements/input/type-image-formaction/userinfo-password-contains-pile-of-poo-novalid.html": "Bad value \u201chttp://foo:\ud83d\udca9@example.com\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Illegal character in user or password: not a URL code point.",
+ "html/elements/input/type-image-formaction/userinfo-username-contains-at-sign-novalid.html": "Bad value \u201chttp://::@c@d:2\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: User or password contains an at symbol (\"@\") not percent-encoded.",
+ "html/elements/input/type-image-formaction/userinfo-username-contains-pile-of-poo-novalid.html": "Bad value \u201chttp://\ud83d\udca9:foo@example.com\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Illegal character in user or password: not a URL code point.",
+ "html/elements/input/type-image-src-empty-novalid.html": "Bad value \u201c\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Must be non-empty.",
+ "html/elements/input/type-image-src-whitespace-only-novalid.html": "Bad value \u201c\t \n\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Must be non-empty.",
+ "html/elements/input/type-image-src/fragment-backslash-novalid.html": "Bad value \u201c#\\\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/input/type-image-src/fragment-contains-hash-novalid.html": "Bad value \u201chttp://foo/path#f#g\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/input/type-image-src/fragment-leading-space-novalid.html": "Bad value \u201chttp://f:21/b# e\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/input/type-image-src/host-cr-novalid.html": "Bad value \u201chttp://example.\norg\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/input/type-image-src/host-double-percent-encoded-novalid.html": "Bad value \u201chttp://\uff05\uff14\uff11.com\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/input/type-image-src/host-double-percent-encoded-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%bc%85%ef%bc%94%ef%bc%91.com\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/input/type-image-src/host-empty-novalid.html": "Bad value \u201chttp://\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/input/type-image-src/host-empty-userinfo-empty-novalid.html": "Bad value \u201chttp://@/www.example.com\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/input/type-image-src/host-empty-with-userinfo-novalid.html": "Bad value \u201chttp://user:pass@/\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/input/type-image-src/host-hostname-in-brackets-novalid.html": "Bad value \u201chttp://[www.google.com]/\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Invalid host: Illegal character.",
+ "html/elements/input/type-image-src/host-invalid-unicode-novalid.html": "Forbidden code point U+fdd0.",
+ "html/elements/input/type-image-src/host-invalid-unicode-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%b7%90zyx.com\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Invalid host: A label or domain name contains disallowed characters..",
+ "html/elements/input/type-image-src/host-newline-novalid.html": "Bad value \u201chttp://example.\norg\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/input/type-image-src/host-space-novalid.html": "Bad value \u201chttp://example .org\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Invalid host: Domain contains invalid character: .",
+ "html/elements/input/type-image-src/host-square-brackets-port-contains-colon-novalid.html": "Bad value \u201chttp://[1::2]:3:4\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Illegal character in port.",
+ "html/elements/input/type-image-src/host-tab-novalid.html": "Bad value \u201chttp://example\t.org\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/input/type-image-src/host-u0000-percent-encoded-novalid.html": "Bad value \u201chttp://\uff05\uff10\uff10.com\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/input/type-image-src/host-u0000-percent-encoded-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%bc%85%ef%bc%90%ef%bc%90.com\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/input/type-image-src/path-bare-percent-sign-novalid.html": "Bad value \u201chttp://example.com/foo%\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Percentage (\"%\") is not followed by two hexadecimal digits.",
+ "html/elements/input/type-image-src/path-contains-space-novalid.html": "Bad value \u201c/a/ /c\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/input/type-image-src/path-leading-backslash-at-sign-novalid.html": "Bad value \u201chttp://foo.com/\\@\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/input/type-image-src/path-leading-colon-backslash-novalid.html": "Bad value \u201c:\\\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/input/type-image-src/path-leading-colon-chars-backslash-novalid.html": "Bad value \u201c:foo.com\\\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/input/type-image-src/path-leading-space-novalid.html": "Bad value \u201chttp://f:21/ b\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/input/type-image-src/path-percent-encoded-malformed-novalid.html": "Bad value \u201chttp://example.com/foo/%2e%2\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Percentage (\"%\") is not followed by two hexadecimal digits.",
+ "html/elements/input/type-image-src/path-relative-square-brackets-novalid.html": "Bad value \u201c[61:24:74]:98\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/input/type-image-src/path-tab-novalid.html": "Bad value \u201chttp://example.com/foo\tbar\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/input/type-image-src/path-trailing-space-novalid.html": "Bad value \u201chttp://f:21/b ?\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/input/type-image-src/path-u0091-novalid.html": "Forbidden code point U+0091.",
+ "html/elements/input/type-image-src/port-cr-novalid.html": "Bad value \u201chttp://f:\n/c\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/input/type-image-src/port-leading-colon-bracket-colon-novalid.html": "Bad value \u201chttp://2001::1]:80\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Illegal character in port.",
+ "html/elements/input/type-image-src/port-leading-colon-novalid.html": "Bad value \u201chttp://2001::1\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Illegal character in port.",
+ "html/elements/input/type-image-src/port-leading-dash-novalid.html": "Bad value \u201chttp://foo:-80/\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Illegal character in port.",
+ "html/elements/input/type-image-src/port-multiple-letters-novalid.html": "Bad value \u201chttp://f:fifty-two/c\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Illegal character in port.",
+ "html/elements/input/type-image-src/port-newline-novalid.html": "Bad value \u201chttp://f:\n/c\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/input/type-image-src/port-single-letter-novalid.html": "Bad value \u201chttp://f:b/c\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Illegal character in port.",
+ "html/elements/input/type-image-src/port-space-novalid.html": "Bad value \u201chttp://f: /c\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Illegal character in port.",
+ "html/elements/input/type-image-src/port-tab-novalid.html": "Bad value \u201chttp://f:\t/c\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/input/type-image-src/query-leading-space-novalid.html": "Bad value \u201chttp://f:21/b? d\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Illegal character in query: not a URL code point.",
+ "html/elements/input/type-image-src/query-trailing-space-novalid.html": "Bad value \u201chttp://f:21/b?d #\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Illegal character in query: not a URL code point.",
+ "html/elements/input/type-image-src/scheme-data-contains-fragment-haswarn.html": "Bad value \u201cdata:text/html,test#test\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Fragment is not allowed for data: URIs according to RFC 2397.",
+ "html/elements/input/type-image-src/scheme-data-single-slash-novalid.html": "Bad value \u201cdata:/example.com/\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Expected a token character or a semicolon but saw \u201c/\u201d instead.",
+ "html/elements/input/type-image-src/scheme-file-backslash-novalid.html": "Bad value \u201cfile:c:\\foo\\bar.html\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/input/type-image-src/scheme-file-single-slash-c-bar-novalid.html": "Bad value \u201cfile:/C|/foo/bar\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/input/type-image-src/scheme-file-triple-slash-c-bar-novalid.html": "Bad value \u201cfile:///C|/foo/bar\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/input/type-image-src/scheme-ftp-no-slash-novalid.html": "Bad value \u201cftp:example.com/\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/input/type-image-src/scheme-ftp-single-slash-novalid.html": "Bad value \u201cftp:/example.com/\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/input/type-image-src/scheme-http-backslash-novalid.html": "Bad value \u201chttp:\\\\foo.com\\\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/input/type-image-src/scheme-http-no-slash-colon-novalid.html": "Bad value \u201chttp::@c:29\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/input/type-image-src/scheme-http-no-slash-novalid.html": "Bad value \u201chttp:foo.com\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/input/type-image-src/scheme-http-no-slash-square-bracket-novalid.html": "Bad value \u201chttp:[61:27]/:foo\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/input/type-image-src/scheme-http-single-slash-novalid.html": "Bad value \u201chttp:/example.com/\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/input/type-image-src/scheme-https-no-slash-novalid.html": "Bad value \u201chttps:example.com/\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/input/type-image-src/scheme-https-single-slash-novalid.html": "Bad value \u201chttps:/example.com/\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/input/type-image-src/scheme-javascript-no-slash-malformed-novalid.html": "Bad value \u201cjavascript:example.com/\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: syntax error",
+ "html/elements/input/type-image-src/scheme-trailing-cr-novalid.html": "Bad value \u201ca:\nfoo.com\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/input/type-image-src/scheme-trailing-newline-novalid.html": "Bad value \u201ca:\nfoo.com\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/input/type-image-src/scheme-trailing-space-novalid.html": "Bad value \u201ca: foo.com\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/input/type-image-src/scheme-trailing-tab-novalid.html": "Bad value \u201ca:\tfoo.com\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/input/type-image-src/userinfo-backslash-novalid.html": "Bad value \u201chttp://a\\b:c\\d@foo.com\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/input/type-image-src/userinfo-password-bad-chars-novalid.html": "\u201c&\u201d did not start a character reference. (\u201c&\u201d probably should have been escaped as \u201c&amp;\u201d.)",
+ "html/elements/input/type-image-src/userinfo-password-contains-pile-of-poo-novalid.html": "Bad value \u201chttp://foo:\ud83d\udca9@example.com\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Illegal character in user or password: not a URL code point.",
+ "html/elements/input/type-image-src/userinfo-username-contains-at-sign-novalid.html": "Bad value \u201chttp://::@c@d:2\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: User or password contains an at symbol (\"@\") not percent-encoded.",
+ "html/elements/input/type-image-src/userinfo-username-contains-pile-of-poo-novalid.html": "Bad value \u201chttp://\ud83d\udca9:foo@example.com\u201d for attribute \u201csrc\u201d on element \u201cinput\u201d: Bad URL: Illegal character in user or password: not a URL code point.",
+ "html/elements/input/type-submit-formaction-empty-novalid.html": "Bad value \u201c\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Must be non-empty.",
+ "html/elements/input/type-submit-formaction-whitespace-only-novalid.html": "Bad value \u201c\t \n\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Must be non-empty.",
+ "html/elements/input/type-submit-formaction/fragment-backslash-novalid.html": "Bad value \u201c#\\\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/input/type-submit-formaction/fragment-contains-hash-novalid.html": "Bad value \u201chttp://foo/path#f#g\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/input/type-submit-formaction/fragment-leading-space-novalid.html": "Bad value \u201chttp://f:21/b# e\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/input/type-submit-formaction/host-cr-novalid.html": "Bad value \u201chttp://example.\norg\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/input/type-submit-formaction/host-double-percent-encoded-novalid.html": "Bad value \u201chttp://\uff05\uff14\uff11.com\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/input/type-submit-formaction/host-double-percent-encoded-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%bc%85%ef%bc%94%ef%bc%91.com\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/input/type-submit-formaction/host-empty-novalid.html": "Bad value \u201chttp://\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/input/type-submit-formaction/host-empty-userinfo-empty-novalid.html": "Bad value \u201chttp://@/www.example.com\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/input/type-submit-formaction/host-empty-with-userinfo-novalid.html": "Bad value \u201chttp://user:pass@/\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/input/type-submit-formaction/host-hostname-in-brackets-novalid.html": "Bad value \u201chttp://[www.google.com]/\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Invalid host: Illegal character.",
+ "html/elements/input/type-submit-formaction/host-invalid-unicode-novalid.html": "Forbidden code point U+fdd0.",
+ "html/elements/input/type-submit-formaction/host-invalid-unicode-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%b7%90zyx.com\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Invalid host: A label or domain name contains disallowed characters..",
+ "html/elements/input/type-submit-formaction/host-newline-novalid.html": "Bad value \u201chttp://example.\norg\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/input/type-submit-formaction/host-space-novalid.html": "Bad value \u201chttp://example .org\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Invalid host: Domain contains invalid character: .",
+ "html/elements/input/type-submit-formaction/host-square-brackets-port-contains-colon-novalid.html": "Bad value \u201chttp://[1::2]:3:4\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Illegal character in port.",
+ "html/elements/input/type-submit-formaction/host-tab-novalid.html": "Bad value \u201chttp://example\t.org\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/input/type-submit-formaction/host-u0000-percent-encoded-novalid.html": "Bad value \u201chttp://\uff05\uff10\uff10.com\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/input/type-submit-formaction/host-u0000-percent-encoded-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%bc%85%ef%bc%90%ef%bc%90.com\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/input/type-submit-formaction/path-bare-percent-sign-novalid.html": "Bad value \u201chttp://example.com/foo%\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Percentage (\"%\") is not followed by two hexadecimal digits.",
+ "html/elements/input/type-submit-formaction/path-contains-space-novalid.html": "Bad value \u201c/a/ /c\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/input/type-submit-formaction/path-leading-backslash-at-sign-novalid.html": "Bad value \u201chttp://foo.com/\\@\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/input/type-submit-formaction/path-leading-colon-backslash-novalid.html": "Bad value \u201c:\\\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/input/type-submit-formaction/path-leading-colon-chars-backslash-novalid.html": "Bad value \u201c:foo.com\\\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/input/type-submit-formaction/path-leading-space-novalid.html": "Bad value \u201chttp://f:21/ b\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/input/type-submit-formaction/path-percent-encoded-malformed-novalid.html": "Bad value \u201chttp://example.com/foo/%2e%2\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Percentage (\"%\") is not followed by two hexadecimal digits.",
+ "html/elements/input/type-submit-formaction/path-relative-square-brackets-novalid.html": "Bad value \u201c[61:24:74]:98\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/input/type-submit-formaction/path-tab-novalid.html": "Bad value \u201chttp://example.com/foo\tbar\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/input/type-submit-formaction/path-trailing-space-novalid.html": "Bad value \u201chttp://f:21/b ?\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/input/type-submit-formaction/path-u0091-novalid.html": "Forbidden code point U+0091.",
+ "html/elements/input/type-submit-formaction/port-cr-novalid.html": "Bad value \u201chttp://f:\n/c\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/input/type-submit-formaction/port-leading-colon-bracket-colon-novalid.html": "Bad value \u201chttp://2001::1]:80\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Illegal character in port.",
+ "html/elements/input/type-submit-formaction/port-leading-colon-novalid.html": "Bad value \u201chttp://2001::1\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Illegal character in port.",
+ "html/elements/input/type-submit-formaction/port-leading-dash-novalid.html": "Bad value \u201chttp://foo:-80/\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Illegal character in port.",
+ "html/elements/input/type-submit-formaction/port-multiple-letters-novalid.html": "Bad value \u201chttp://f:fifty-two/c\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Illegal character in port.",
+ "html/elements/input/type-submit-formaction/port-newline-novalid.html": "Bad value \u201chttp://f:\n/c\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/input/type-submit-formaction/port-single-letter-novalid.html": "Bad value \u201chttp://f:b/c\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Illegal character in port.",
+ "html/elements/input/type-submit-formaction/port-space-novalid.html": "Bad value \u201chttp://f: /c\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Illegal character in port.",
+ "html/elements/input/type-submit-formaction/port-tab-novalid.html": "Bad value \u201chttp://f:\t/c\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/input/type-submit-formaction/query-leading-space-novalid.html": "Bad value \u201chttp://f:21/b? d\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Illegal character in query: not a URL code point.",
+ "html/elements/input/type-submit-formaction/query-trailing-space-novalid.html": "Bad value \u201chttp://f:21/b?d #\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Illegal character in query: not a URL code point.",
+ "html/elements/input/type-submit-formaction/scheme-data-contains-fragment-haswarn.html": "Bad value \u201cdata:text/html,test#test\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Fragment is not allowed for data: URIs according to RFC 2397.",
+ "html/elements/input/type-submit-formaction/scheme-data-single-slash-novalid.html": "Bad value \u201cdata:/example.com/\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Expected a token character or a semicolon but saw \u201c/\u201d instead.",
+ "html/elements/input/type-submit-formaction/scheme-file-backslash-novalid.html": "Bad value \u201cfile:c:\\foo\\bar.html\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/input/type-submit-formaction/scheme-file-single-slash-c-bar-novalid.html": "Bad value \u201cfile:/C|/foo/bar\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/input/type-submit-formaction/scheme-file-triple-slash-c-bar-novalid.html": "Bad value \u201cfile:///C|/foo/bar\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/input/type-submit-formaction/scheme-ftp-no-slash-novalid.html": "Bad value \u201cftp:example.com/\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/input/type-submit-formaction/scheme-ftp-single-slash-novalid.html": "Bad value \u201cftp:/example.com/\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/input/type-submit-formaction/scheme-http-backslash-novalid.html": "Bad value \u201chttp:\\\\foo.com\\\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/input/type-submit-formaction/scheme-http-no-slash-colon-novalid.html": "Bad value \u201chttp::@c:29\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/input/type-submit-formaction/scheme-http-no-slash-novalid.html": "Bad value \u201chttp:foo.com\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/input/type-submit-formaction/scheme-http-no-slash-square-bracket-novalid.html": "Bad value \u201chttp:[61:27]/:foo\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/input/type-submit-formaction/scheme-http-single-slash-novalid.html": "Bad value \u201chttp:/example.com/\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/input/type-submit-formaction/scheme-https-no-slash-novalid.html": "Bad value \u201chttps:example.com/\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/input/type-submit-formaction/scheme-https-single-slash-novalid.html": "Bad value \u201chttps:/example.com/\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/input/type-submit-formaction/scheme-javascript-no-slash-malformed-novalid.html": "Bad value \u201cjavascript:example.com/\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: syntax error",
+ "html/elements/input/type-submit-formaction/scheme-trailing-cr-novalid.html": "Bad value \u201ca:\nfoo.com\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/input/type-submit-formaction/scheme-trailing-newline-novalid.html": "Bad value \u201ca:\nfoo.com\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/input/type-submit-formaction/scheme-trailing-space-novalid.html": "Bad value \u201ca: foo.com\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/input/type-submit-formaction/scheme-trailing-tab-novalid.html": "Bad value \u201ca:\tfoo.com\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/input/type-submit-formaction/userinfo-backslash-novalid.html": "Bad value \u201chttp://a\\b:c\\d@foo.com\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/input/type-submit-formaction/userinfo-password-bad-chars-novalid.html": "\u201c&\u201d did not start a character reference. (\u201c&\u201d probably should have been escaped as \u201c&amp;\u201d.)",
+ "html/elements/input/type-submit-formaction/userinfo-password-contains-pile-of-poo-novalid.html": "Bad value \u201chttp://foo:\ud83d\udca9@example.com\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Illegal character in user or password: not a URL code point.",
+ "html/elements/input/type-submit-formaction/userinfo-username-contains-at-sign-novalid.html": "Bad value \u201chttp://::@c@d:2\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: User or password contains an at symbol (\"@\") not percent-encoded.",
+ "html/elements/input/type-submit-formaction/userinfo-username-contains-pile-of-poo-novalid.html": "Bad value \u201chttp://\ud83d\udca9:foo@example.com\u201d for attribute \u201cformaction\u201d on element \u201cinput\u201d: Bad URL: Illegal character in user or password: not a URL code point.",
+ "html/elements/input/type-url-value/fragment-backslash-novalid.html": "Bad value \u201c#\\\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: The string \u201c#\\\u201d is not an absolute URL.",
+ "html/elements/input/type-url-value/fragment-contains-hash-novalid.html": "Bad value \u201chttp://foo/path#f#g\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/input/type-url-value/fragment-empty-hash-only-no-path-relative-novalid.html": "Bad value \u201c#\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: The string \u201c#\u201d is not an absolute URL.",
+ "html/elements/input/type-url-value/fragment-leading-space-novalid.html": "Bad value \u201chttp://f:21/b# e\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/input/type-url-value/fragment-non-ascii-relative-novalid.html": "Bad value \u201c#\u03b2\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: The string \u201c#\u03b2\u201d is not an absolute URL.",
+ "html/elements/input/type-url-value/fragment-semicolon-question-mark-relative-novalid.html": "Bad value \u201c#;?\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: The string \u201c#;?\u201d is not an absolute URL.",
+ "html/elements/input/type-url-value/fragment-slash-relative-novalid.html": "Bad value \u201c#/\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: The string \u201c#/\u201d is not an absolute URL.",
+ "html/elements/input/type-url-value/host-cr-novalid.html": "Bad value \u201chttp://example.\norg\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: Tab, new line or carriage return found.",
+ "html/elements/input/type-url-value/host-double-percent-encoded-novalid.html": "Bad value \u201chttp://\uff05\uff14\uff11.com\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/input/type-url-value/host-double-percent-encoded-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%bc%85%ef%bc%94%ef%bc%91.com\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/input/type-url-value/host-empty-novalid.html": "Bad value \u201chttp://\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: Invalid host: empty host.",
+ "html/elements/input/type-url-value/host-empty-userinfo-empty-novalid.html": "Bad value \u201chttp://@/www.example.com\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: Invalid host: empty host.",
+ "html/elements/input/type-url-value/host-empty-with-userinfo-novalid.html": "Bad value \u201chttp://user:pass@/\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: Invalid host: empty host.",
+ "html/elements/input/type-url-value/host-hostname-in-brackets-novalid.html": "Bad value \u201chttp://[www.google.com]/\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: Invalid host: Illegal character.",
+ "html/elements/input/type-url-value/host-invalid-unicode-novalid.html": "Forbidden code point U+fdd0.",
+ "html/elements/input/type-url-value/host-invalid-unicode-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%b7%90zyx.com\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: Invalid host: A label or domain name contains disallowed characters..",
+ "html/elements/input/type-url-value/host-newline-novalid.html": "Bad value \u201chttp://example.\norg\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: Tab, new line or carriage return found.",
+ "html/elements/input/type-url-value/host-space-novalid.html": "Bad value \u201chttp://example .org\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: Invalid host: Domain contains invalid character: .",
+ "html/elements/input/type-url-value/host-square-brackets-port-contains-colon-novalid.html": "Bad value \u201chttp://[1::2]:3:4\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: Illegal character in port.",
+ "html/elements/input/type-url-value/host-tab-novalid.html": "Bad value \u201chttp://example\t.org\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: Tab, new line or carriage return found.",
+ "html/elements/input/type-url-value/host-u0000-percent-encoded-novalid.html": "Bad value \u201chttp://\uff05\uff10\uff10.com\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/input/type-url-value/host-u0000-percent-encoded-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%bc%85%ef%bc%90%ef%bc%90.com\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/input/type-url-value/path-bare-percent-sign-novalid.html": "Bad value \u201chttp://example.com/foo%\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: Percentage (\"%\") is not followed by two hexadecimal digits.",
+ "html/elements/input/type-url-value/path-contains-space-novalid.html": "Bad value \u201c/a/ /c\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: The string \u201c/a/ /c\u201d is not an absolute URL.",
+ "html/elements/input/type-url-value/path-leading-backslash-at-sign-novalid.html": "Bad value \u201chttp://foo.com/\\@\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/input/type-url-value/path-leading-colon-backslash-novalid.html": "Bad value \u201c:\\\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: The string \u201c:\\\u201d is not an absolute URL.",
+ "html/elements/input/type-url-value/path-leading-colon-chars-backslash-novalid.html": "Bad value \u201c:foo.com\\\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: The string \u201c:foo.com\\\u201d is not an absolute URL.",
+ "html/elements/input/type-url-value/path-leading-space-novalid.html": "Bad value \u201chttp://f:21/ b\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/input/type-url-value/path-percent-encoded-malformed-novalid.html": "Bad value \u201chttp://example.com/foo/%2e%2\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: Percentage (\"%\") is not followed by two hexadecimal digits.",
+ "html/elements/input/type-url-value/path-percent-encoded-slash-plus-slashes-relative-novalid.html": "Bad value \u201c/a/%2f/c\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: The string \u201c/a/%2f/c\u201d is not an absolute URL.",
+ "html/elements/input/type-url-value/path-percent-encoded-slash-relative-novalid.html": "Bad value \u201c/a%2fc\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: The string \u201c/a%2fc\u201d is not an absolute URL.",
+ "html/elements/input/type-url-value/path-relative-square-brackets-novalid.html": "Bad value \u201c[61:24:74]:98\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: The string \u201c[61:24:74]:98\u201d is not an absolute URL.",
+ "html/elements/input/type-url-value/path-simple-relative-novalid.html": "Bad value \u201c/a/b/c\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: The string \u201c/a/b/c\u201d is not an absolute URL.",
+ "html/elements/input/type-url-value/path-slash-only-relative-novalid.html": "Bad value \u201c/\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: The string \u201c/\u201d is not an absolute URL.",
+ "html/elements/input/type-url-value/path-tab-novalid.html": "Bad value \u201chttp://example.com/foo\tbar\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: Tab, new line or carriage return found.",
+ "html/elements/input/type-url-value/path-trailing-space-novalid.html": "Bad value \u201chttp://f:21/b ?\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/input/type-url-value/path-u0091-novalid.html": "Forbidden code point U+0091.",
+ "html/elements/input/type-url-value/port-cr-novalid.html": "Bad value \u201chttp://f:\n/c\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: Tab, new line or carriage return found.",
+ "html/elements/input/type-url-value/port-leading-colon-bracket-colon-novalid.html": "Bad value \u201chttp://2001::1]:80\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: Illegal character in port.",
+ "html/elements/input/type-url-value/port-leading-colon-novalid.html": "Bad value \u201chttp://2001::1\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: Illegal character in port.",
+ "html/elements/input/type-url-value/port-leading-dash-novalid.html": "Bad value \u201chttp://foo:-80/\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: Illegal character in port.",
+ "html/elements/input/type-url-value/port-multiple-letters-novalid.html": "Bad value \u201chttp://f:fifty-two/c\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: Illegal character in port.",
+ "html/elements/input/type-url-value/port-newline-novalid.html": "Bad value \u201chttp://f:\n/c\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: Tab, new line or carriage return found.",
+ "html/elements/input/type-url-value/port-single-letter-novalid.html": "Bad value \u201chttp://f:b/c\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: Illegal character in port.",
+ "html/elements/input/type-url-value/port-space-novalid.html": "Bad value \u201chttp://f: /c\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: Illegal character in port.",
+ "html/elements/input/type-url-value/port-tab-novalid.html": "Bad value \u201chttp://f:\t/c\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: Tab, new line or carriage return found.",
+ "html/elements/input/type-url-value/query-empty-no-path-relative-novalid.html": "Bad value \u201c?\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: The string \u201c?\u201d is not an absolute URL.",
+ "html/elements/input/type-url-value/query-leading-space-novalid.html": "Bad value \u201chttp://f:21/b? d\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: Illegal character in query: not a URL code point.",
+ "html/elements/input/type-url-value/query-trailing-space-novalid.html": "Bad value \u201chttp://f:21/b?d #\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: Illegal character in query: not a URL code point.",
+ "html/elements/input/type-url-value/scheme-data-contains-fragment-haswarn.html": "Bad value \u201cdata:text/html,test#test\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: Fragment is not allowed for data: URIs according to RFC 2397.",
+ "html/elements/input/type-url-value/scheme-data-single-slash-novalid.html": "Bad value \u201cdata:/example.com/\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: Expected a token character or a semicolon but saw \u201c/\u201d instead.",
+ "html/elements/input/type-url-value/scheme-file-backslash-novalid.html": "Bad value \u201cfile:c:\\foo\\bar.html\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/input/type-url-value/scheme-file-single-slash-c-bar-novalid.html": "Bad value \u201cfile:/C|/foo/bar\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/input/type-url-value/scheme-file-triple-slash-c-bar-novalid.html": "Bad value \u201cfile:///C|/foo/bar\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/input/type-url-value/scheme-ftp-no-slash-novalid.html": "Bad value \u201cftp:example.com/\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: Expected a slash (\"/\").",
+ "html/elements/input/type-url-value/scheme-ftp-single-slash-novalid.html": "Bad value \u201cftp:/example.com/\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: Expected a slash (\"/\").",
+ "html/elements/input/type-url-value/scheme-http-backslash-novalid.html": "Bad value \u201chttp:\\\\foo.com\\\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: Expected a slash (\"/\").",
+ "html/elements/input/type-url-value/scheme-http-no-slash-colon-novalid.html": "Bad value \u201chttp::@c:29\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: Expected a slash (\"/\").",
+ "html/elements/input/type-url-value/scheme-http-no-slash-novalid.html": "Bad value \u201chttp:foo.com\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: Expected a slash (\"/\").",
+ "html/elements/input/type-url-value/scheme-http-no-slash-square-bracket-novalid.html": "Bad value \u201chttp:[61:27]/:foo\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: Expected a slash (\"/\").",
+ "html/elements/input/type-url-value/scheme-http-single-slash-novalid.html": "Bad value \u201chttp:/example.com/\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: Expected a slash (\"/\").",
+ "html/elements/input/type-url-value/scheme-https-no-slash-novalid.html": "Bad value \u201chttps:example.com/\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: Expected a slash (\"/\").",
+ "html/elements/input/type-url-value/scheme-https-single-slash-novalid.html": "Bad value \u201chttps:/example.com/\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: Expected a slash (\"/\").",
+ "html/elements/input/type-url-value/scheme-javascript-no-slash-malformed-novalid.html": "Bad value \u201cjavascript:example.com/\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: syntax error",
+ "html/elements/input/type-url-value/scheme-schemeless-relative-novalid.html": "Bad value \u201c//foo/bar\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: The string \u201c//foo/bar\u201d is not an absolute URL.",
+ "html/elements/input/type-url-value/scheme-trailing-cr-novalid.html": "Bad value \u201ca:\nfoo.com\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/input/type-url-value/scheme-trailing-newline-novalid.html": "Bad value \u201ca:\nfoo.com\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/input/type-url-value/scheme-trailing-space-novalid.html": "Bad value \u201ca: foo.com\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/input/type-url-value/scheme-trailing-tab-novalid.html": "Bad value \u201ca:\tfoo.com\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/input/type-url-value/userinfo-backslash-novalid.html": "Bad value \u201chttp://a\\b:c\\d@foo.com\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/input/type-url-value/userinfo-password-bad-chars-novalid.html": "\u201c&\u201d did not start a character reference. (\u201c&\u201d probably should have been escaped as \u201c&amp;\u201d.)",
+ "html/elements/input/type-url-value/userinfo-password-contains-pile-of-poo-novalid.html": "Bad value \u201chttp://foo:\ud83d\udca9@example.com\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: Illegal character in user or password: not a URL code point.",
+ "html/elements/input/type-url-value/userinfo-username-contains-at-sign-novalid.html": "Bad value \u201chttp://::@c@d:2\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: User or password contains an at symbol (\"@\") not percent-encoded.",
+ "html/elements/input/type-url-value/userinfo-username-contains-pile-of-poo-novalid.html": "Bad value \u201chttp://\ud83d\udca9:foo@example.com\u201d for attribute \u201cvalue\u201d on element \u201cinput\u201d: Bad absolute URL: Illegal character in user or password: not a URL code point.",
+ "html/elements/ins/cite/fragment-backslash-novalid.html": "Bad value \u201c#\\\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/ins/cite/fragment-contains-hash-novalid.html": "Bad value \u201chttp://foo/path#f#g\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/ins/cite/fragment-leading-space-novalid.html": "Bad value \u201chttp://f:21/b# e\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/ins/cite/host-cr-novalid.html": "Bad value \u201chttp://example.\norg\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/ins/cite/host-double-percent-encoded-novalid.html": "Bad value \u201chttp://\uff05\uff14\uff11.com\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/ins/cite/host-double-percent-encoded-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%bc%85%ef%bc%94%ef%bc%91.com\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/ins/cite/host-empty-novalid.html": "Bad value \u201chttp://\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/ins/cite/host-empty-userinfo-empty-novalid.html": "Bad value \u201chttp://@/www.example.com\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/ins/cite/host-empty-with-userinfo-novalid.html": "Bad value \u201chttp://user:pass@/\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/ins/cite/host-hostname-in-brackets-novalid.html": "Bad value \u201chttp://[www.google.com]/\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Invalid host: Illegal character.",
+ "html/elements/ins/cite/host-invalid-unicode-novalid.html": "Forbidden code point U+fdd0.",
+ "html/elements/ins/cite/host-invalid-unicode-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%b7%90zyx.com\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Invalid host: A label or domain name contains disallowed characters..",
+ "html/elements/ins/cite/host-newline-novalid.html": "Bad value \u201chttp://example.\norg\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/ins/cite/host-space-novalid.html": "Bad value \u201chttp://example .org\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Invalid host: Domain contains invalid character: .",
+ "html/elements/ins/cite/host-square-brackets-port-contains-colon-novalid.html": "Bad value \u201chttp://[1::2]:3:4\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Illegal character in port.",
+ "html/elements/ins/cite/host-tab-novalid.html": "Bad value \u201chttp://example\t.org\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/ins/cite/host-u0000-percent-encoded-novalid.html": "Bad value \u201chttp://\uff05\uff10\uff10.com\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/ins/cite/host-u0000-percent-encoded-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%bc%85%ef%bc%90%ef%bc%90.com\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/ins/cite/path-bare-percent-sign-novalid.html": "Bad value \u201chttp://example.com/foo%\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Percentage (\"%\") is not followed by two hexadecimal digits.",
+ "html/elements/ins/cite/path-contains-space-novalid.html": "Bad value \u201c/a/ /c\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/ins/cite/path-leading-backslash-at-sign-novalid.html": "Bad value \u201chttp://foo.com/\\@\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/ins/cite/path-leading-colon-backslash-novalid.html": "Bad value \u201c:\\\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/ins/cite/path-leading-colon-chars-backslash-novalid.html": "Bad value \u201c:foo.com\\\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/ins/cite/path-leading-space-novalid.html": "Bad value \u201chttp://f:21/ b\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/ins/cite/path-percent-encoded-malformed-novalid.html": "Bad value \u201chttp://example.com/foo/%2e%2\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Percentage (\"%\") is not followed by two hexadecimal digits.",
+ "html/elements/ins/cite/path-relative-square-brackets-novalid.html": "Bad value \u201c[61:24:74]:98\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/ins/cite/path-tab-novalid.html": "Bad value \u201chttp://example.com/foo\tbar\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/ins/cite/path-trailing-space-novalid.html": "Bad value \u201chttp://f:21/b ?\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/ins/cite/path-u0091-novalid.html": "Forbidden code point U+0091.",
+ "html/elements/ins/cite/port-cr-novalid.html": "Bad value \u201chttp://f:\n/c\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/ins/cite/port-leading-colon-bracket-colon-novalid.html": "Bad value \u201chttp://2001::1]:80\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Illegal character in port.",
+ "html/elements/ins/cite/port-leading-colon-novalid.html": "Bad value \u201chttp://2001::1\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Illegal character in port.",
+ "html/elements/ins/cite/port-leading-dash-novalid.html": "Bad value \u201chttp://foo:-80/\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Illegal character in port.",
+ "html/elements/ins/cite/port-multiple-letters-novalid.html": "Bad value \u201chttp://f:fifty-two/c\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Illegal character in port.",
+ "html/elements/ins/cite/port-newline-novalid.html": "Bad value \u201chttp://f:\n/c\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/ins/cite/port-single-letter-novalid.html": "Bad value \u201chttp://f:b/c\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Illegal character in port.",
+ "html/elements/ins/cite/port-space-novalid.html": "Bad value \u201chttp://f: /c\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Illegal character in port.",
+ "html/elements/ins/cite/port-tab-novalid.html": "Bad value \u201chttp://f:\t/c\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/ins/cite/query-leading-space-novalid.html": "Bad value \u201chttp://f:21/b? d\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Illegal character in query: not a URL code point.",
+ "html/elements/ins/cite/query-trailing-space-novalid.html": "Bad value \u201chttp://f:21/b?d #\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Illegal character in query: not a URL code point.",
+ "html/elements/ins/cite/scheme-data-contains-fragment-haswarn.html": "Bad value \u201cdata:text/html,test#test\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Fragment is not allowed for data: URIs according to RFC 2397.",
+ "html/elements/ins/cite/scheme-data-single-slash-novalid.html": "Bad value \u201cdata:/example.com/\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Expected a token character or a semicolon but saw \u201c/\u201d instead.",
+ "html/elements/ins/cite/scheme-file-backslash-novalid.html": "Bad value \u201cfile:c:\\foo\\bar.html\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/ins/cite/scheme-file-single-slash-c-bar-novalid.html": "Bad value \u201cfile:/C|/foo/bar\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/ins/cite/scheme-file-triple-slash-c-bar-novalid.html": "Bad value \u201cfile:///C|/foo/bar\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/ins/cite/scheme-ftp-no-slash-novalid.html": "Bad value \u201cftp:example.com/\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/ins/cite/scheme-ftp-single-slash-novalid.html": "Bad value \u201cftp:/example.com/\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/ins/cite/scheme-http-backslash-novalid.html": "Bad value \u201chttp:\\\\foo.com\\\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/ins/cite/scheme-http-no-slash-colon-novalid.html": "Bad value \u201chttp::@c:29\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/ins/cite/scheme-http-no-slash-novalid.html": "Bad value \u201chttp:foo.com\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/ins/cite/scheme-http-no-slash-square-bracket-novalid.html": "Bad value \u201chttp:[61:27]/:foo\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/ins/cite/scheme-http-single-slash-novalid.html": "Bad value \u201chttp:/example.com/\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/ins/cite/scheme-https-no-slash-novalid.html": "Bad value \u201chttps:example.com/\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/ins/cite/scheme-https-single-slash-novalid.html": "Bad value \u201chttps:/example.com/\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/ins/cite/scheme-javascript-no-slash-malformed-novalid.html": "Bad value \u201cjavascript:example.com/\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: syntax error",
+ "html/elements/ins/cite/scheme-trailing-cr-novalid.html": "Bad value \u201ca:\nfoo.com\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/ins/cite/scheme-trailing-newline-novalid.html": "Bad value \u201ca:\nfoo.com\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/ins/cite/scheme-trailing-space-novalid.html": "Bad value \u201ca: foo.com\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/ins/cite/scheme-trailing-tab-novalid.html": "Bad value \u201ca:\tfoo.com\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/ins/cite/userinfo-backslash-novalid.html": "Bad value \u201chttp://a\\b:c\\d@foo.com\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/ins/cite/userinfo-password-bad-chars-novalid.html": "\u201c&\u201d did not start a character reference. (\u201c&\u201d probably should have been escaped as \u201c&amp;\u201d.)",
+ "html/elements/ins/cite/userinfo-password-contains-pile-of-poo-novalid.html": "Bad value \u201chttp://foo:\ud83d\udca9@example.com\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Illegal character in user or password: not a URL code point.",
+ "html/elements/ins/cite/userinfo-username-contains-at-sign-novalid.html": "Bad value \u201chttp://::@c@d:2\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: User or password contains an at symbol (\"@\") not percent-encoded.",
+ "html/elements/ins/cite/userinfo-username-contains-pile-of-poo-novalid.html": "Bad value \u201chttp://\ud83d\udca9:foo@example.com\u201d for attribute \u201ccite\u201d on element \u201cins\u201d: Bad URL: Illegal character in user or password: not a URL code point.",
+ "html/elements/ins/date-0004-02-29-haswarn.html": "Bad value \u201c0004-02-29\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad date: Year may be mistyped. Bad datetime with timezone: The literal did not satisfy the datetime with timezone format.",
+ "html/elements/ins/date-0005-02-29-novalid.html": "Bad value \u201c0005-02-29\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: Day out of range.",
+ "html/elements/ins/date-0214-09-29-haswarn.html": "Bad value \u201c0214-09-29\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad date: Year may be mistyped. Bad datetime with timezone: The literal did not satisfy the datetime with timezone format.",
+ "html/elements/ins/date-1900-02-29-novalid.html": "Bad value \u201c1900-02-29\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: Day out of range.",
+ "html/elements/ins/date-1969-02-29-novalid.html": "Bad value \u201c1969-02-29\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: Day out of range.",
+ "html/elements/ins/date-20014-09-29-haswarn.html": "Bad value \u201c20014-09-29\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad date: Year may be mistyped. Bad datetime with timezone: The literal did not satisfy the datetime with timezone format.",
+ "html/elements/ins/date-2014-02-29-novalid.html": "Bad value \u201c2014-02-29\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: Day out of range.",
+ "html/elements/ins/date-2100-02-29-novalid.html": "Bad value \u201c2100-02-29\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: Day out of range.",
+ "html/elements/ins/date-2200-02-29-novalid.html": "Bad value \u201c2200-02-29\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: Day out of range.",
+ "html/elements/ins/date-day-01-32-novalid.html": "Bad value \u201c2002-01-32\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: Day out of range.",
+ "html/elements/ins/date-day-03-32-novalid.html": "Bad value \u201c2002-03-32\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: Day out of range.",
+ "html/elements/ins/date-day-04-31-novalid.html": "Bad value \u201c2002-04-31\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: Day out of range.",
+ "html/elements/ins/date-day-05-32-novalid.html": "Bad value \u201c2002-05-32\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: Day out of range.",
+ "html/elements/ins/date-day-06-31-novalid.html": "Bad value \u201c2002-06-31\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: Day out of range.",
+ "html/elements/ins/date-day-07-32-novalid.html": "Bad value \u201c2002-07-32\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: Day out of range.",
+ "html/elements/ins/date-day-08-32-novalid.html": "Bad value \u201c2002-08-32\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: Day out of range.",
+ "html/elements/ins/date-day-09-31-novalid.html": "Bad value \u201c2002-09-31\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: Day out of range.",
+ "html/elements/ins/date-day-10-32-novalid.html": "Bad value \u201c2002-10-32\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: Day out of range.",
+ "html/elements/ins/date-day-11-31-novalid.html": "Bad value \u201c2002-11-31\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: Day out of range.",
+ "html/elements/ins/date-day-12-32-novalid.html": "Bad value \u201c2002-12-32\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: Day out of range.",
+ "html/elements/ins/date-day-missing-separator-novalid.html": "Bad value \u201c2014-0220\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/date-day-one-digit-novalid.html": "Bad value \u201c2002-09-9\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/date-day-three-digits-novalid.html": "Bad value \u201c2002-11-009\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/date-iso8601-YYYYMMDD-no-hyphen-novalid.html": "Bad value \u201c20020929\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/date-leading-bom-novalid.html": "Bad value \u201c\ufeff2002-09-29\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/date-leading-whitespace-novalid.html": "Bad value \u201c 2002-09-29\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/date-month-00-novalid.html": "Bad value \u201c2002-00-15\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad date: Month cannot be less than 1. Bad datetime with timezone: The literal did not satisfy the datetime with timezone format.",
+ "html/elements/ins/date-month-13-novalid.html": "Bad value \u201c2002-13-15\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: Month cannot be greater than 12.",
+ "html/elements/ins/date-month-missing-separator-novalid.html": "Bad value \u201c201402-20\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/date-month-one-digit-novalid.html": "Bad value \u201c2002-9-29\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/date-month-three-digits-novalid.html": "Bad value \u201c2002-011-29\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/date-non-ascii-digit-novalid.html": "Bad value \u201c2002-09-2\uff19\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/date-trailing-U+0000-novalid.html": "Character reference expands to zero.",
+ "html/elements/ins/date-trailing-pile-of-poo-novalid.html": "Bad value \u201c2002-09-29\ud83d\udca9\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/date-trailing-whitespace-novalid.html": "Bad value \u201c2002-09-29 \u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/date-wrong-day-separator-novalid.html": "Bad value \u201c2014-02:20\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/date-wrong-month-separator-novalid.html": "Bad value \u201c2014:02-20\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/date-year-0000-novalid.html": "Bad value \u201c0000-12-09\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: Year cannot be less than 1.",
+ "html/elements/ins/date-year-five-digits-haswarn.html": "Bad value \u201c12014-09-29\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad date: Year may be mistyped. Bad datetime with timezone: The literal did not satisfy the datetime with timezone format.",
+ "html/elements/ins/date-year-negative-novalid.html": "Bad value \u201c-2002-09-29\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/date-year-three-digits-novalid.html": "Bad value \u201c782-09-29\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/duration-P-form-novalid.html": "Bad value \u201cPT4H18M3S\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/duration-time-component-novalid.html": "Bad value \u201c4h 18m 3s\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/global-date-and-time-2400-novalid.html": "Bad value \u201c2011-11-12T24:00:00+08:00\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: Hour cannot be greater than 23. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/global-date-and-time-60-minutes-novalid.html": "Bad value \u201c2011-11-12T00:60:00+08:00\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: Minute cannot be greater than 59. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/global-date-and-time-60-seconds-novalid.html": "Bad value \u201c2011-11-12T00:00:60+08:00\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: Second cannot be greater than 59. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/global-date-and-time-bad-fraction-separator-novalid.html": "Bad value \u201c2011-11-12T14:54:39,929+0000\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/global-date-and-time-four-digit-fraction-novalid.html": "Bad value \u201c2011-11-12T06:54:39.9291-08:00\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad date: The literal did not satisfy the date format. Bad datetime with timezone: A fraction of a second must be one, two, or three digits.",
+ "html/elements/ins/global-date-and-time-hour-one-digit-novalid.html": "Bad value \u201c2011-11-12T6:54:39-08:00\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/global-date-and-time-hour-three-digits-novalid.html": "Bad value \u201c2011-11-12T016:54:39-08:00\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/global-date-and-time-iso8601-hh-novalid.html": "Bad value \u201c2011-11-12T14Z\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/global-date-and-time-iso8601-hhmm-no-colon-novalid.html": "Bad value \u201c2011-11-12T1454Z\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/global-date-and-time-iso8601-hhmmss-no-colon-novalid.html": "Bad value \u201c2011-11-12T145439Z\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/global-date-and-time-lowercase-z-novalid.html": "Bad value \u201c2011-11-12T14:54z\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/global-date-and-time-minutes-one-digit-novalid.html": "Bad value \u201c2011-11-12T16:4:39-08:00\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/global-date-and-time-minutes-three-digits-novalid.html": "Bad value \u201c2011-11-12T16:354:39-08:00\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/global-date-and-time-missing-minutes-separator-novalid.html": "Bad value \u201c2011-11-12T1454Z\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/global-date-and-time-missing-seconds-separator-novalid.html": "Bad value \u201c2011-11-12T14:5439Z\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/global-date-and-time-nbsp-novalid.html": "Bad value \u201c2011-11-12\u00a014:54Z\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/global-date-and-time-seconds-one-digit-novalid.html": "Bad value \u201c2011-11-12T16:54:9-08:00\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/global-date-and-time-seconds-three-digits-novalid.html": "Bad value \u201c2011-11-12T16:54:039-08:00\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/global-date-and-time-space-before-timezone-novalid.html": "Bad value \u201c2011-11-12T06:54:39 08:00\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/global-date-and-time-timezone-60-minutes-novalid.html": "Bad value \u201c2011-11-12T06:54:39-08:60\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad date: The literal did not satisfy the date format. Bad datetime with timezone: Minutes out of range in time zone designator.",
+ "html/elements/ins/global-date-and-time-timezone-iso8601-two-digit-novalid.html": "Bad value \u201c2011-11-12T06:54:39-08\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/global-date-and-time-timezone-lowercase-t-novalid.html": "Bad value \u201c2011-11-12t14:54Z\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/global-date-and-time-timezone-minus-1300-haswarn.html": "Bad value \u201c2011-11-12T00:00:00-1300\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: Hours in time zone designator should be from \u201c-12:00\u201d to \u201d+14:00\u201d Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/global-date-and-time-timezone-minus-2400-novalid.html": "Bad value \u201c2011-11-12T06:54:39-24:00\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: Hours out of range in time zone designator. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/global-date-and-time-timezone-minutes-15-haswarn.html": "Bad value \u201c2011-11-12T00:00:00+08:15\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: Minutes in time zone designator should be either \u201c00\u201d, \u201c30\u201d, or \u201c45\u201d. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/global-date-and-time-timezone-multiple-spaces-novalid.html": "Bad value \u201c2011-11-12 14:54Z\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/global-date-and-time-timezone-non-T-character-novalid.html": "Bad value \u201c2011-11-12+14:54Z\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/global-date-and-time-timezone-offset-colon-start-novalid.html": "Bad value \u201c2011-11-12T06:54:39.929:08:00\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/global-date-and-time-timezone-offset-space-start-novalid.html": "Bad value \u201c2011-11-12T06:54:39.929 08:00\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/global-date-and-time-timezone-one-digit-hour-novalid.html": "Bad value \u201c2011-11-12T06:54:39-5:00\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/global-date-and-time-timezone-one-digit-minute-novalid.html": "Bad value \u201c2011-11-12T06:54:39-05:0\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/global-date-and-time-timezone-plus-1500-haswarn.html": "Bad value \u201c2011-11-12T00:00:00+1500\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: Hours in time zone designator should be from \u201c-12:00\u201d to \u201d+14:00\u201d Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/global-date-and-time-timezone-plus-2400-novalid.html": "Bad value \u201c2011-11-12T06:54:39-24:00\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: Hours out of range in time zone designator. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/global-date-and-time-timezone-three-digit-hour-novalid.html": "Bad value \u201c2011-11-12T06:54:39-005:00\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/global-date-and-time-timezone-three-digit-minute-novalid.html": "Bad value \u201c2011-11-12T06:54:39-05:000\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/global-date-and-time-timezone-with-seconds-novalid.html": "Bad value \u201c2011-11-12T06:54:39-08:00:00\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/global-date-and-time-with-both-T-and-space-novalid.html": "Bad value \u201c2011-11-12T 14:54Z\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/global-date-and-time-wrong-minutes-separator-novalid.html": "Bad value \u201c2011-11-12T14-54Z\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/global-date-and-time-wrong-seconds-separator-novalid.html": "Bad value \u201c2011-11-12T14:54-39Z\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/global-date-and-time-zero-digit-fraction-novalid.html": "Bad value \u201c2011-11-12T06:54:39.-08:00\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/local-date-and-time-novalid.html": "Bad value \u201c2011-11-12T14:54\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/model-novalid.html": "End tag \u201cp\u201d implied, but there were open elements.",
+ "html/elements/ins/month-novalid.html": "Bad value \u201c2011-11\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/time-novalid.html": "Bad value \u201c14:54:39\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/week-novalid.html": "Bad value \u201c2011-W46\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/year-novalid.html": "Bad value \u201c2006\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/ins/yearless-date-novalid.html": "Bad value \u201c07-15\u201d for attribute \u201cdatetime\u201d on element \u201cins\u201d: Bad datetime with timezone: The literal did not satisfy the datetime with timezone format. Bad date: The literal did not satisfy the date format.",
+ "html/elements/kbd/model-novalid.html": "End tag \u201cp\u201d implied, but there were open elements.",
+ "html/elements/keygen/id-bad-novalid.html": "Any \u201ckeygen\u201d descendant of a \u201clabel\u201d element with a \u201cfor\u201d attribute must have an ID value that matches that \u201cfor\u201d attribute.",
+ "html/elements/keygen/id-missing-novalid.html": "Any \u201ckeygen\u201d descendant of a \u201clabel\u201d element with a \u201cfor\u201d attribute must have an ID value that matches that \u201cfor\u201d attribute.",
+ "html/elements/keygen/id-redundant-novalid.html": "The \u201clabel\u201d element may contain at most one \u201cinput\u201d, \u201cbutton\u201d, \u201cselect\u201d, \u201ctextarea\u201d, or \u201ckeygen\u201d descendant.",
+ "html/elements/keygen/keytype-bad-value-novalid.html": "Bad value \u201cdsa\u201d for attribute \u201ckeytype\u201d on element \u201ckeygen\u201d.",
+ "html/elements/keygen/keytype-empty-novalid.html": "Bad value \u201c\u201d for attribute \u201ckeytype\u201d on element \u201ckeygen\u201d.",
+ "html/elements/keygen/model-novalid.html": "The element \u201ckeygen\u201d must not appear as a descendant of the \u201ca\u201d element.",
+ "html/elements/keygen/non-void-novalid.html": "Stray end tag \u201ckeygen\u201d.",
+ "html/elements/label/for-descendant-no-id-novalid.html": "Any \u201cinput\u201d descendant of a \u201clabel\u201d element with a \u201cfor\u201d attribute must have an ID value that matches that \u201cfor\u201d attribute.",
+ "html/elements/label/multiple-descendants-novalid.html": "The \u201clabel\u201d element may contain at most one \u201cinput\u201d, \u201cbutton\u201d, \u201cselect\u201d, \u201ctextarea\u201d, or \u201ckeygen\u201d descendant.",
+ "html/elements/link/href-empty-novalid.html": "Bad value \u201c\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Must be non-empty.",
+ "html/elements/link/href-missing-novalid.html": "Element \u201clink\u201d is missing required attribute \u201chref\u201d.",
+ "html/elements/link/href-whitespace-only-novalid.html": "Bad value \u201c\t \n\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Must be non-empty.",
+ "html/elements/link/href/fragment-backslash-novalid.html": "Bad value \u201c#\\\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/link/href/fragment-contains-hash-novalid.html": "Bad value \u201chttp://foo/path#f#g\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/link/href/fragment-leading-space-novalid.html": "Bad value \u201chttp://f:21/b# e\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/link/href/host-cr-novalid.html": "Bad value \u201chttp://example.\norg\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/link/href/host-double-percent-encoded-novalid.html": "Bad value \u201chttp://\uff05\uff14\uff11.com\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/link/href/host-double-percent-encoded-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%bc%85%ef%bc%94%ef%bc%91.com\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/link/href/host-empty-novalid.html": "Bad value \u201chttp://\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/link/href/host-empty-userinfo-empty-novalid.html": "Bad value \u201chttp://@/www.example.com\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/link/href/host-empty-with-userinfo-novalid.html": "Bad value \u201chttp://user:pass@/\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/link/href/host-hostname-in-brackets-novalid.html": "Bad value \u201chttp://[www.google.com]/\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Invalid host: Illegal character.",
+ "html/elements/link/href/host-invalid-unicode-novalid.html": "Forbidden code point U+fdd0.",
+ "html/elements/link/href/host-invalid-unicode-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%b7%90zyx.com\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Invalid host: A label or domain name contains disallowed characters..",
+ "html/elements/link/href/host-newline-novalid.html": "Bad value \u201chttp://example.\norg\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/link/href/host-space-novalid.html": "Bad value \u201chttp://example .org\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Invalid host: Domain contains invalid character: .",
+ "html/elements/link/href/host-square-brackets-port-contains-colon-novalid.html": "Bad value \u201chttp://[1::2]:3:4\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Illegal character in port.",
+ "html/elements/link/href/host-tab-novalid.html": "Bad value \u201chttp://example\t.org\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/link/href/host-u0000-percent-encoded-novalid.html": "Bad value \u201chttp://\uff05\uff10\uff10.com\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/link/href/host-u0000-percent-encoded-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%bc%85%ef%bc%90%ef%bc%90.com\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/link/href/path-bare-percent-sign-novalid.html": "Bad value \u201chttp://example.com/foo%\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Percentage (\"%\") is not followed by two hexadecimal digits.",
+ "html/elements/link/href/path-contains-space-novalid.html": "Bad value \u201c/a/ /c\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/link/href/path-leading-backslash-at-sign-novalid.html": "Bad value \u201chttp://foo.com/\\@\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/link/href/path-leading-colon-backslash-novalid.html": "Bad value \u201c:\\\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/link/href/path-leading-colon-chars-backslash-novalid.html": "Bad value \u201c:foo.com\\\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/link/href/path-leading-space-novalid.html": "Bad value \u201chttp://f:21/ b\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/link/href/path-percent-encoded-malformed-novalid.html": "Bad value \u201chttp://example.com/foo/%2e%2\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Percentage (\"%\") is not followed by two hexadecimal digits.",
+ "html/elements/link/href/path-relative-square-brackets-novalid.html": "Bad value \u201c[61:24:74]:98\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/link/href/path-tab-novalid.html": "Bad value \u201chttp://example.com/foo\tbar\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/link/href/path-trailing-space-novalid.html": "Bad value \u201chttp://f:21/b ?\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/link/href/path-u0091-novalid.html": "Forbidden code point U+0091.",
+ "html/elements/link/href/port-cr-novalid.html": "Bad value \u201chttp://f:\n/c\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/link/href/port-leading-colon-bracket-colon-novalid.html": "Bad value \u201chttp://2001::1]:80\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Illegal character in port.",
+ "html/elements/link/href/port-leading-colon-novalid.html": "Bad value \u201chttp://2001::1\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Illegal character in port.",
+ "html/elements/link/href/port-leading-dash-novalid.html": "Bad value \u201chttp://foo:-80/\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Illegal character in port.",
+ "html/elements/link/href/port-multiple-letters-novalid.html": "Bad value \u201chttp://f:fifty-two/c\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Illegal character in port.",
+ "html/elements/link/href/port-newline-novalid.html": "Bad value \u201chttp://f:\n/c\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/link/href/port-single-letter-novalid.html": "Bad value \u201chttp://f:b/c\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Illegal character in port.",
+ "html/elements/link/href/port-space-novalid.html": "Bad value \u201chttp://f: /c\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Illegal character in port.",
+ "html/elements/link/href/port-tab-novalid.html": "Bad value \u201chttp://f:\t/c\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/link/href/query-leading-space-novalid.html": "Bad value \u201chttp://f:21/b? d\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Illegal character in query: not a URL code point.",
+ "html/elements/link/href/query-trailing-space-novalid.html": "Bad value \u201chttp://f:21/b?d #\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Illegal character in query: not a URL code point.",
+ "html/elements/link/href/scheme-data-contains-fragment-haswarn.html": "Bad value \u201cdata:text/html,test#test\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Fragment is not allowed for data: URIs according to RFC 2397.",
+ "html/elements/link/href/scheme-data-single-slash-novalid.html": "Bad value \u201cdata:/example.com/\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Expected a token character or a semicolon but saw \u201c/\u201d instead.",
+ "html/elements/link/href/scheme-file-backslash-novalid.html": "Bad value \u201cfile:c:\\foo\\bar.html\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/link/href/scheme-file-single-slash-c-bar-novalid.html": "Bad value \u201cfile:/C|/foo/bar\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/link/href/scheme-file-triple-slash-c-bar-novalid.html": "Bad value \u201cfile:///C|/foo/bar\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/link/href/scheme-ftp-no-slash-novalid.html": "Bad value \u201cftp:example.com/\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/link/href/scheme-ftp-single-slash-novalid.html": "Bad value \u201cftp:/example.com/\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/link/href/scheme-http-backslash-novalid.html": "Bad value \u201chttp:\\\\foo.com\\\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/link/href/scheme-http-no-slash-colon-novalid.html": "Bad value \u201chttp::@c:29\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/link/href/scheme-http-no-slash-novalid.html": "Bad value \u201chttp:foo.com\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/link/href/scheme-http-no-slash-square-bracket-novalid.html": "Bad value \u201chttp:[61:27]/:foo\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/link/href/scheme-http-single-slash-novalid.html": "Bad value \u201chttp:/example.com/\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/link/href/scheme-https-no-slash-novalid.html": "Bad value \u201chttps:example.com/\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/link/href/scheme-https-single-slash-novalid.html": "Bad value \u201chttps:/example.com/\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/link/href/scheme-javascript-no-slash-malformed-novalid.html": "Bad value \u201cjavascript:example.com/\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: syntax error",
+ "html/elements/link/href/scheme-trailing-cr-novalid.html": "Bad value \u201ca:\nfoo.com\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/link/href/scheme-trailing-newline-novalid.html": "Bad value \u201ca:\nfoo.com\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/link/href/scheme-trailing-space-novalid.html": "Bad value \u201ca: foo.com\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/link/href/scheme-trailing-tab-novalid.html": "Bad value \u201ca:\tfoo.com\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/link/href/userinfo-backslash-novalid.html": "Bad value \u201chttp://a\\b:c\\d@foo.com\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/link/href/userinfo-password-bad-chars-novalid.html": "\u201c&\u201d did not start a character reference. (\u201c&\u201d probably should have been escaped as \u201c&amp;\u201d.)",
+ "html/elements/link/href/userinfo-password-contains-pile-of-poo-novalid.html": "Bad value \u201chttp://foo:\ud83d\udca9@example.com\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Illegal character in user or password: not a URL code point.",
+ "html/elements/link/href/userinfo-username-contains-at-sign-novalid.html": "Bad value \u201chttp://::@c@d:2\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: User or password contains an at symbol (\"@\") not percent-encoded.",
+ "html/elements/link/href/userinfo-username-contains-pile-of-poo-novalid.html": "Bad value \u201chttp://\ud83d\udca9:foo@example.com\u201d for attribute \u201chref\u201d on element \u201clink\u201d: Bad URL: Illegal character in user or password: not a URL code point.",
+ "html/elements/map/model-novalid.html": "The \u201cid\u201d attribute on a \u201cmap\u201d element must have an the same value as the \u201cname\u201d attribute.",
+ "html/elements/object/data-empty-novalid.html": "Bad value \u201c\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Must be non-empty.",
+ "html/elements/object/data-type-missing-novalid.html": "Element \u201cobject\u201d is missing one or more of the following attributes: [data, type].",
+ "html/elements/object/data-whitespace-only-novalid.html": "Bad value \u201c\t \n\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Must be non-empty.",
+ "html/elements/object/data/fragment-backslash-novalid.html": "Bad value \u201c#\\\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/object/data/fragment-contains-hash-novalid.html": "Bad value \u201chttp://foo/path#f#g\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/object/data/fragment-leading-space-novalid.html": "Bad value \u201chttp://f:21/b# e\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/object/data/host-cr-novalid.html": "Bad value \u201chttp://example.\norg\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/object/data/host-double-percent-encoded-novalid.html": "Bad value \u201chttp://\uff05\uff14\uff11.com\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/object/data/host-double-percent-encoded-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%bc%85%ef%bc%94%ef%bc%91.com\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/object/data/host-empty-novalid.html": "Bad value \u201chttp://\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/object/data/host-empty-userinfo-empty-novalid.html": "Bad value \u201chttp://@/www.example.com\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/object/data/host-empty-with-userinfo-novalid.html": "Bad value \u201chttp://user:pass@/\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/object/data/host-hostname-in-brackets-novalid.html": "Bad value \u201chttp://[www.google.com]/\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Invalid host: Illegal character.",
+ "html/elements/object/data/host-invalid-unicode-novalid.html": "Forbidden code point U+fdd0.",
+ "html/elements/object/data/host-invalid-unicode-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%b7%90zyx.com\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Invalid host: A label or domain name contains disallowed characters..",
+ "html/elements/object/data/host-newline-novalid.html": "Bad value \u201chttp://example.\norg\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/object/data/host-space-novalid.html": "Bad value \u201chttp://example .org\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Invalid host: Domain contains invalid character: .",
+ "html/elements/object/data/host-square-brackets-port-contains-colon-novalid.html": "Bad value \u201chttp://[1::2]:3:4\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Illegal character in port.",
+ "html/elements/object/data/host-tab-novalid.html": "Bad value \u201chttp://example\t.org\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/object/data/host-u0000-percent-encoded-novalid.html": "Bad value \u201chttp://\uff05\uff10\uff10.com\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/object/data/host-u0000-percent-encoded-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%bc%85%ef%bc%90%ef%bc%90.com\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/object/data/path-bare-percent-sign-novalid.html": "Bad value \u201chttp://example.com/foo%\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Percentage (\"%\") is not followed by two hexadecimal digits.",
+ "html/elements/object/data/path-contains-space-novalid.html": "Bad value \u201c/a/ /c\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/object/data/path-leading-backslash-at-sign-novalid.html": "Bad value \u201chttp://foo.com/\\@\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/object/data/path-leading-colon-backslash-novalid.html": "Bad value \u201c:\\\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/object/data/path-leading-colon-chars-backslash-novalid.html": "Bad value \u201c:foo.com\\\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/object/data/path-leading-space-novalid.html": "Bad value \u201chttp://f:21/ b\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/object/data/path-percent-encoded-malformed-novalid.html": "Bad value \u201chttp://example.com/foo/%2e%2\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Percentage (\"%\") is not followed by two hexadecimal digits.",
+ "html/elements/object/data/path-relative-square-brackets-novalid.html": "Bad value \u201c[61:24:74]:98\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/object/data/path-tab-novalid.html": "Bad value \u201chttp://example.com/foo\tbar\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/object/data/path-trailing-space-novalid.html": "Bad value \u201chttp://f:21/b ?\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/object/data/path-u0091-novalid.html": "Forbidden code point U+0091.",
+ "html/elements/object/data/port-cr-novalid.html": "Bad value \u201chttp://f:\n/c\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/object/data/port-leading-colon-bracket-colon-novalid.html": "Bad value \u201chttp://2001::1]:80\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Illegal character in port.",
+ "html/elements/object/data/port-leading-colon-novalid.html": "Bad value \u201chttp://2001::1\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Illegal character in port.",
+ "html/elements/object/data/port-leading-dash-novalid.html": "Bad value \u201chttp://foo:-80/\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Illegal character in port.",
+ "html/elements/object/data/port-multiple-letters-novalid.html": "Bad value \u201chttp://f:fifty-two/c\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Illegal character in port.",
+ "html/elements/object/data/port-newline-novalid.html": "Bad value \u201chttp://f:\n/c\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/object/data/port-single-letter-novalid.html": "Bad value \u201chttp://f:b/c\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Illegal character in port.",
+ "html/elements/object/data/port-space-novalid.html": "Bad value \u201chttp://f: /c\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Illegal character in port.",
+ "html/elements/object/data/port-tab-novalid.html": "Bad value \u201chttp://f:\t/c\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/object/data/query-leading-space-novalid.html": "Bad value \u201chttp://f:21/b? d\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Illegal character in query: not a URL code point.",
+ "html/elements/object/data/query-trailing-space-novalid.html": "Bad value \u201chttp://f:21/b?d #\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Illegal character in query: not a URL code point.",
+ "html/elements/object/data/scheme-data-contains-fragment-haswarn.html": "Bad value \u201cdata:text/html,test#test\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Fragment is not allowed for data: URIs according to RFC 2397.",
+ "html/elements/object/data/scheme-data-single-slash-novalid.html": "Bad value \u201cdata:/example.com/\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Expected a token character or a semicolon but saw \u201c/\u201d instead.",
+ "html/elements/object/data/scheme-file-backslash-novalid.html": "Bad value \u201cfile:c:\\foo\\bar.html\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/object/data/scheme-file-single-slash-c-bar-novalid.html": "Bad value \u201cfile:/C|/foo/bar\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/object/data/scheme-file-triple-slash-c-bar-novalid.html": "Bad value \u201cfile:///C|/foo/bar\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/object/data/scheme-ftp-no-slash-novalid.html": "Bad value \u201cftp:example.com/\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/object/data/scheme-ftp-single-slash-novalid.html": "Bad value \u201cftp:/example.com/\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/object/data/scheme-http-backslash-novalid.html": "Bad value \u201chttp:\\\\foo.com\\\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/object/data/scheme-http-no-slash-colon-novalid.html": "Bad value \u201chttp::@c:29\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/object/data/scheme-http-no-slash-novalid.html": "Bad value \u201chttp:foo.com\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/object/data/scheme-http-no-slash-square-bracket-novalid.html": "Bad value \u201chttp:[61:27]/:foo\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/object/data/scheme-http-single-slash-novalid.html": "Bad value \u201chttp:/example.com/\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/object/data/scheme-https-no-slash-novalid.html": "Bad value \u201chttps:example.com/\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/object/data/scheme-https-single-slash-novalid.html": "Bad value \u201chttps:/example.com/\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/object/data/scheme-javascript-no-slash-malformed-novalid.html": "Bad value \u201cjavascript:example.com/\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: syntax error",
+ "html/elements/object/data/scheme-trailing-cr-novalid.html": "Bad value \u201ca:\nfoo.com\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/object/data/scheme-trailing-newline-novalid.html": "Bad value \u201ca:\nfoo.com\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/object/data/scheme-trailing-space-novalid.html": "Bad value \u201ca: foo.com\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/object/data/scheme-trailing-tab-novalid.html": "Bad value \u201ca:\tfoo.com\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/object/data/userinfo-backslash-novalid.html": "Bad value \u201chttp://a\\b:c\\d@foo.com\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/object/data/userinfo-password-bad-chars-novalid.html": "\u201c&\u201d did not start a character reference. (\u201c&\u201d probably should have been escaped as \u201c&amp;\u201d.)",
+ "html/elements/object/data/userinfo-password-contains-pile-of-poo-novalid.html": "Bad value \u201chttp://foo:\ud83d\udca9@example.com\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Illegal character in user or password: not a URL code point.",
+ "html/elements/object/data/userinfo-username-contains-at-sign-novalid.html": "Bad value \u201chttp://::@c@d:2\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: User or password contains an at symbol (\"@\") not percent-encoded.",
+ "html/elements/object/data/userinfo-username-contains-pile-of-poo-novalid.html": "Bad value \u201chttp://\ud83d\udca9:foo@example.com\u201d for attribute \u201cdata\u201d on element \u201cobject\u201d: Bad URL: Illegal character in user or password: not a URL code point.",
+ "html/elements/object/model-novalid.html": "Element \u201cobject\u201d is missing one or more of the following attributes: [data, type].",
+ "html/elements/ol/model-novalid.html": "Duplicate ID \u201cid\u201d.",
+ "html/elements/option/label-novalid.html": "Bad value \u201c\u201d for attribute \u201clabel\u201d on element \u201coption\u201d: Bad non-empty string: Must not be empty.",
+ "html/elements/option/model-novalid.html": "Element \u201coption\u201d without attribute \u201clabel\u201d must not be empty.",
+ "html/elements/p/model-novalid.html": "No \u201cp\u201d element in scope but a \u201cp\u201d end tag seen.",
+ "html/elements/param/model-novalid.html": "Element \u201cparam\u201d not allowed in this context. (The parent was element \u201cbody\u201d.) Suppressing further errors from this subtree.",
+ "html/elements/picture/always-matching-source-media-all-spaces-with-following-source-srcset-novalid.html": "Value of \u201cmedia\u201d attribute here must not be \u201call\u201d.",
+ "html/elements/picture/always-matching-source-media-all-with-following-source-srcset-novalid.html": "Value of \u201cmedia\u201d attribute here must not be \u201call\u201d.",
+ "html/elements/picture/always-matching-source-media-empty-with-following-source-srcset-novalid.html": "Bad value \u201c\u201d for attribute \u201cmedia\u201d on element \u201csource\u201d: Bad media query: Media query ended prematurely.",
+ "html/elements/picture/always-matching-source-media-spaces-with-following-source-srcset-novalid.html": "Bad value \u201c \n\t\u201d for attribute \u201cmedia\u201d on element \u201csource\u201d: Bad media query: Media query ended prematurely.",
+ "html/elements/picture/always-matching-source-media-uppercase-with-following-source-srcset-novalid.html": "Value of \u201cmedia\u201d attribute here must not be \u201call\u201d.",
+ "html/elements/picture/always-matching-source-sizes-with-following-source-srcset-novalid.html": "A \u201csource\u201d element that has a following sibling \u201csource\u201d element or \u201cimg\u201d element with a \u201csrcset\u201d attribute must have a \u201cmedia\u201d attribute and/or \u201ctype\u201d attribute.",
+ "html/elements/picture/always-matching-source-with-following-img-srcset-novalid.html": "A \u201csource\u201d element that has a following sibling \u201csource\u201d element or \u201cimg\u201d element with a \u201csrcset\u201d attribute must have a \u201cmedia\u201d attribute and/or \u201ctype\u201d attribute.",
+ "html/elements/picture/always-matching-source-with-following-source-media-novalid.html": "A \u201csource\u201d element that has a following sibling \u201csource\u201d element or \u201cimg\u201d element with a \u201csrcset\u201d attribute must have a \u201cmedia\u201d attribute and/or \u201ctype\u201d attribute.",
+ "html/elements/picture/always-matching-source-with-following-source-srcset-novalid.html": "A \u201csource\u201d element that has a following sibling \u201csource\u201d element or \u201cimg\u201d element with a \u201csrcset\u201d attribute must have a \u201cmedia\u201d attribute and/or \u201ctype\u201d attribute.",
+ "html/elements/picture/always-matching-source-with-following-source-type-novalid.html": "A \u201csource\u201d element that has a following sibling \u201csource\u201d element or \u201cimg\u201d element with a \u201csrcset\u201d attribute must have a \u201cmedia\u201d attribute and/or \u201ctype\u201d attribute.",
+ "html/elements/picture/audio-srcset-novalid.html": "Attribute \u201csrcset\u201d not allowed on element \u201caudio\u201d in this context.",
+ "html/elements/picture/html-syntax-img-end-tag-novalid.html": "Stray end tag \u201cimg\u201d.",
+ "html/elements/picture/html-syntax-picture-no-end-tag-novalid.html": "End of file seen and there were open elements.",
+ "html/elements/picture/html-syntax-picture-slash-no-end-tag-novalid.html": "Self-closing syntax (\u201c/>\u201d) used on a non-void HTML element. Ignoring the slash and treating as a start tag.",
+ "html/elements/picture/html-syntax-picture-slash-novalid.html": "Self-closing syntax (\u201c/>\u201d) used on a non-void HTML element. Ignoring the slash and treating as a start tag.",
+ "html/elements/picture/html-syntax-source-end-tag-novalid.html": "Stray end tag \u201csource\u201d.",
+ "html/elements/picture/img-no-src-novalid.html": "Element \u201cimg\u201d is missing required attribute \u201csrc\u201d.",
+ "html/elements/picture/img-no-src-with-picture-novalid.html": "Element \u201cimg\u201d is missing required attribute \u201csrc\u201d.",
+ "html/elements/picture/img-no-src-with-source-novalid.html": "Element \u201cimg\u201d is missing required attribute \u201csrc\u201d.",
+ "html/elements/picture/img-no-src-with-srcset-and-picture-novalid.html": "Element \u201cimg\u201d is missing required attribute \u201csrc\u201d.",
+ "html/elements/picture/img-no-src-with-srcset-novalid.html": "Element \u201cimg\u201d is missing required attribute \u201csrc\u201d.",
+ "html/elements/picture/img-srcset-no-descriptor-with-sizes-novalid.html": "Bad value \u201cx\u201d for attribute \u201csrcset\u201d on element \u201cimg\u201d: No width specified for image \u201cx\u201d. (When the \u201csizes\u201d attribute is present, all image candidate strings must specify a width.)",
+ "html/elements/picture/img-srcset-w-and-x-width-sizes-novalid.html": "Bad value \u201cx 100w, y 2x\u201d for attribute \u201csrcset\u201d on element \u201cimg\u201d: Expected width descriptor but found \u201c2x\u201d at \u201cx 100w, y 2x\u201d. (When the \u201csizes\u201d attribute is present, all image candidate strings must specify a width.)",
+ "html/elements/picture/img-srcset-w-no-sizes-novalid.html": "When the \u201csrcset\u201d attribute has any image candidate string with a width descriptor, the \u201csizes\u201d attribute must also be present.",
+ "html/elements/picture/img-type-novalid.html": "Attribute \u201ctype\u201d not allowed on element \u201cimg\u201d in this context.",
+ "html/elements/picture/img-type-with-picture-novalid.html": "Attribute \u201ctype\u201d not allowed on element \u201cimg\u201d in this context.",
+ "html/elements/picture/img-with-sizes-no-srcset-novalid.html": "The \u201csizes\u201d attribute may be specified only if the \u201csrcset\u201d attribute is also present.",
+ "html/elements/picture/input-type-image-srcset-novalid.html": "Attribute \u201csrcset\u201d not allowed on element \u201cinput\u201d in this context.",
+ "html/elements/picture/junk-br-after-img-novalid.html": "Element \u201cbr\u201d not allowed in this context. (The parent was element \u201cpicture\u201d.) Suppressing further errors from this subtree.",
+ "html/elements/picture/junk-br-after-source-novalid.html": "Element \u201cbr\u201d not allowed in this context. (The parent was element \u201cpicture\u201d.) Suppressing further errors from this subtree.",
+ "html/elements/picture/junk-br-before-img-novalid.html": "Element \u201cbr\u201d not allowed in this context. (The parent was element \u201cpicture\u201d.) Suppressing further errors from this subtree.",
+ "html/elements/picture/junk-br-before-source-novalid.html": "Element \u201cbr\u201d not allowed in this context. (The parent was element \u201cpicture\u201d.) Suppressing further errors from this subtree.",
+ "html/elements/picture/junk-figure-wrapping-novalid.html": "Element \u201cfigure\u201d not allowed in this context. (The parent was element \u201cpicture\u201d.) Suppressing further errors from this subtree.",
+ "html/elements/picture/junk-input-type-hidden-novalid.html": "Element \u201cinput\u201d not allowed in this context. (The parent was element \u201cpicture\u201d.) Suppressing further errors from this subtree.",
+ "html/elements/picture/junk-math-nog-img-novalid.html": "Element \u201cmath\u201d not allowed in this context. (The parent was element \u201cpicture\u201d.) Suppressing further errors from this subtree.",
+ "html/elements/picture/junk-noscript-after-source-no-img-novalid.html": "Element \u201cnoscript\u201d not allowed in this context. (The parent was element \u201cpicture\u201d.) Suppressing further errors from this subtree.",
+ "html/elements/picture/junk-noscript-novalid.html": "Element \u201cnoscript\u201d not allowed in this context. (The parent was element \u201cpicture\u201d.) Suppressing further errors from this subtree.",
+ "html/elements/picture/junk-p-after-novalid.html": "Element \u201cp\u201d not allowed in this context. (The parent was element \u201cpicture\u201d.) Suppressing further errors from this subtree.",
+ "html/elements/picture/junk-p-before-novalid.html": "Element \u201cp\u201d not allowed in this context. (The parent was element \u201cpicture\u201d.) Suppressing further errors from this subtree.",
+ "html/elements/picture/junk-p-wrapping-novalid.html": "Element \u201cp\u201d not allowed in this context. (The parent was element \u201cpicture\u201d.) Suppressing further errors from this subtree.",
+ "html/elements/picture/junk-picture-before-novalid.html": "Element \u201cpicture\u201d not allowed in this context. (The parent was element \u201cpicture\u201d.) Suppressing further errors from this subtree.",
+ "html/elements/picture/junk-picture-wrapping-novalid.html": "Element \u201cpicture\u201d not allowed in this context. (The parent was element \u201cpicture\u201d.) Suppressing further errors from this subtree.",
+ "html/elements/picture/junk-span-after-novalid.html": "Element \u201cspan\u201d not allowed in this context. (The parent was element \u201cpicture\u201d.) Suppressing further errors from this subtree.",
+ "html/elements/picture/junk-span-before-novalid.html": "Element \u201cspan\u201d not allowed in this context. (The parent was element \u201cpicture\u201d.) Suppressing further errors from this subtree.",
+ "html/elements/picture/junk-span-wrapping-novalid.html": "Element \u201cspan\u201d not allowed in this context. (The parent was element \u201cpicture\u201d.) Suppressing further errors from this subtree.",
+ "html/elements/picture/junk-style-scroped-novalid.html": "Element \u201cstyle\u201d not allowed in this context. (The parent was element \u201cpicture\u201d.) Suppressing further errors from this subtree.",
+ "html/elements/picture/junk-svg-no-img-novalid.html": "Element \u201csvg\u201d not allowed in this context. (The parent was element \u201cpicture\u201d.) Suppressing further errors from this subtree.",
+ "html/elements/picture/junk-svg-novalid.html": "Element \u201csvg\u201d not allowed in this context. (The parent was element \u201cpicture\u201d.) Suppressing further errors from this subtree.",
+ "html/elements/picture/junk-text-after-img-novalid.html": "Text not allowed in element \u201cpicture\u201d in this context.",
+ "html/elements/picture/junk-text-after-source-novalid.html": "Text not allowed in element \u201cpicture\u201d in this context.",
+ "html/elements/picture/junk-text-before-img-novalid.html": "Text not allowed in element \u201cpicture\u201d in this context.",
+ "html/elements/picture/junk-text-before-source-novalid.html": "Text not allowed in element \u201cpicture\u201d in this context.",
+ "html/elements/picture/junk-video-before-novalid.html": "Element \u201cvideo\u201d not allowed in this context. (The parent was element \u201cpicture\u201d.) Suppressing further errors from this subtree.",
+ "html/elements/picture/junk-video-no-img-novalid.html": "Element \u201cvideo\u201d not allowed in this context. (The parent was element \u201cpicture\u201d.) Suppressing further errors from this subtree.",
+ "html/elements/picture/link-rel-icon-srcset-novalid.html": "Attribute \u201csrcset\u201d not allowed on element \u201clink\u201d in this context.",
+ "html/elements/picture/missing-img-empty-picture-novalid.html": "Element \u201cpicture\u201d is missing required child element \u201cimg\u201d.",
+ "html/elements/picture/missing-img-only-script-novalid.html": "Element \u201cpicture\u201d is missing required child element \u201cimg\u201d.",
+ "html/elements/picture/missing-img-only-source-novalid.html": "Element \u201cpicture\u201d is missing required child element \u201cimg\u201d.",
+ "html/elements/picture/missing-img-script-and-source-novalid.html": "Element \u201cpicture\u201d is missing required child element \u201cimg\u201d.",
+ "html/elements/picture/missing-img-source-and-script-novalid.html": "Element \u201cpicture\u201d is missing required child element \u201cimg\u201d.",
+ "html/elements/picture/multiple-img-novalid.html": "Element \u201cimg\u201d not allowed in this context. (The parent was element \u201cpicture\u201d.) Suppressing further errors from this subtree.",
+ "html/elements/picture/multiple-img-with-script-novalid.html": "Element \u201cimg\u201d not allowed in this context. (The parent was element \u201cpicture\u201d.) Suppressing further errors from this subtree.",
+ "html/elements/picture/multiple-img-with-source-and-script-novalid.html": "Element \u201cimg\u201d not allowed in this context. (The parent was element \u201cpicture\u201d.) Suppressing further errors from this subtree.",
+ "html/elements/picture/multiple-img-with-source-novalid.html": "Element \u201cimg\u201d not allowed in this context. (The parent was element \u201cpicture\u201d.) Suppressing further errors from this subtree.",
+ "html/elements/picture/object-srcset-novalid.html": "Attribute \u201csrcset\u201d not allowed on element \u201cobject\u201d in this context.",
+ "html/elements/picture/parent-dl-novalid.html": "Element \u201cpicture\u201d not allowed in this context. (The parent was element \u201cdl\u201d.) Suppressing further errors from this subtree.",
+ "html/elements/picture/parent-hgroup-novalid.html": "Element \u201cpicture\u201d not allowed in this context. (The parent was element \u201chgroup\u201d.) Suppressing further errors from this subtree.",
+ "html/elements/picture/parent-noscript-in-head-novalid.html": "Bad start tag in \u201cpicture\u201d in \u201chead\u201d.",
+ "html/elements/picture/parent-ul-novalid.html": "Element \u201cpicture\u201d not allowed in this context. (The parent was element \u201cul\u201d.) Suppressing further errors from this subtree.",
+ "html/elements/picture/picture-align-novalid.html": "Attribute \u201calign\u201d not allowed on element \u201cpicture\u201d in this context.",
+ "html/elements/picture/picture-alt-novalid.html": "Attribute \u201calt\u201d not allowed on element \u201cpicture\u201d in this context.",
+ "html/elements/picture/picture-aria-role-application-novalid.html": "Attribute \u201crole\u201d not allowed on element \u201cpicture\u201d in this context.",
+ "html/elements/picture/picture-aria-role-button-novalid.html": "Attribute \u201crole\u201d not allowed on element \u201cpicture\u201d in this context.",
+ "html/elements/picture/picture-aria-role-img-novalid.html": "Attribute \u201crole\u201d not allowed on element \u201cpicture\u201d in this context.",
+ "html/elements/picture/picture-aria-role-presentation-novalid.html": "Attribute \u201crole\u201d not allowed on element \u201cpicture\u201d in this context.",
+ "html/elements/picture/picture-aria-role-region-novalid.html": "Attribute \u201crole\u201d not allowed on element \u201cpicture\u201d in this context.",
+ "html/elements/picture/picture-border-novalid.html": "Attribute \u201cborder\u201d not allowed on element \u201cpicture\u201d in this context.",
+ "html/elements/picture/picture-crossorigin-novalid.html": "Attribute \u201ccrossorigin\u201d not allowed on element \u201cpicture\u201d in this context.",
+ "html/elements/picture/picture-height-novalid.html": "Attribute \u201cheight\u201d not allowed on element \u201cpicture\u201d in this context.",
+ "html/elements/picture/picture-hspace-novalid.html": "Attribute \u201chspace\u201d not allowed on element \u201cpicture\u201d in this context.",
+ "html/elements/picture/picture-ismap-novalid.html": "Attribute \u201cismap\u201d not allowed on element \u201cpicture\u201d in this context.",
+ "html/elements/picture/picture-longdesc-novalid.html": "Attribute \u201clongdesc\u201d not allowed on element \u201cpicture\u201d in this context.",
+ "html/elements/picture/picture-lowsrc-novalid.html": "Attribute \u201clowsrc\u201d not allowed on element \u201cpicture\u201d in this context.",
+ "html/elements/picture/picture-media-novalid.html": "Attribute \u201cmedia\u201d not allowed on element \u201cpicture\u201d in this context.",
+ "html/elements/picture/picture-name-novalid.html": "Attribute \u201cname\u201d not allowed on element \u201cpicture\u201d in this context.",
+ "html/elements/picture/picture-sizes-novalid.html": "Attribute \u201csizes\u201d not allowed on element \u201cpicture\u201d in this context.",
+ "html/elements/picture/picture-src-novalid.html": "Attribute \u201csrc\u201d not allowed on element \u201cpicture\u201d in this context.",
+ "html/elements/picture/picture-srcset-novalid.html": "Attribute \u201csrcset\u201d not allowed on element \u201cpicture\u201d in this context.",
+ "html/elements/picture/picture-usemap-novalid.html": "Attribute \u201cusemap\u201d not allowed on element \u201cpicture\u201d in this context.",
+ "html/elements/picture/picture-vspace-novalid.html": "Attribute \u201cvspace\u201d not allowed on element \u201cpicture\u201d in this context.",
+ "html/elements/picture/picture-width-novalid.html": "Attribute \u201cwidth\u201d not allowed on element \u201cpicture\u201d in this context.",
+ "html/elements/picture/sizes-microsyntax-auto-source-size-value-novalid.html": "Bad value \u201cauto\u201d for attribute \u201csizes\u201d on element \u201cimg\u201d: Bad source size list: Bad CSS number token: Expected a minus sign or a digit but saw \u201ca\u201d instead at \u201cauto\u201d.",
+ "html/elements/picture/sizes-microsyntax-comma-novalid.html": "Bad value \u201c,\u201d for attribute \u201csizes\u201d on element \u201cimg\u201d: Bad source size list: Starts with empty source size.",
+ "html/elements/picture/sizes-microsyntax-css-comment-after-plus-novalid.html": "Bad value \u201c+/**/50vw\u201d for attribute \u201csizes\u201d on element \u201cimg\u201d: Bad source size list: Expected number but found \u201c+/\u201d at \u201c+/**/50vw\u201d.",
+ "html/elements/picture/sizes-microsyntax-css-comment-before-unit-novalid.html": "Bad value \u201c50/**/vw\u201d for attribute \u201csizes\u201d on element \u201cimg\u201d: Bad source size list: Expected units (one of \u201cem\u201d, \u201cex\u201d, \u201cch\u201d, \u201crem\u201d, \u201cvw\u201d, \u201cvh\u201d, \u201cvmin\u201d, \u201cvmax\u201d, \u201ccm\u201d, \u201cmm\u201d, \u201cq\u201d, \u201cin\u201d, \u201cpc\u201d, \u201cpt\u201d, \u201cpx\u201d) but found \u201c/vw\u201d at \u201c50/**/vw\u201d.",
+ "html/elements/picture/sizes-microsyntax-default-first-novalid.html": "Bad value \u201c100vw, (min-width:500px) 500px\u201d for attribute \u201csizes\u201d on element \u201cimg\u201d: Bad source size list: Expected media condition before \u201c\u201d at \u201c100vw,\u201d.",
+ "html/elements/picture/sizes-microsyntax-default-source-size-value-novalid.html": "Bad value \u201cdefault\u201d for attribute \u201csizes\u201d on element \u201cimg\u201d: Bad source size list: Bad CSS number token: Expected a minus sign or a digit but saw \u201cd\u201d instead at \u201cdefault\u201d.",
+ "html/elements/picture/sizes-microsyntax-deg-source-size-value-novalid.html": "Bad value \u201c1deg\u201d for attribute \u201csizes\u201d on element \u201cimg\u201d: Bad source size list: Expected units (one of \u201cem\u201d, \u201cex\u201d, \u201cch\u201d, \u201crem\u201d, \u201cvw\u201d, \u201cvh\u201d, \u201cvmin\u201d, \u201cvmax\u201d, \u201ccm\u201d, \u201cmm\u201d, \u201cq\u201d, \u201cin\u201d, \u201cpc\u201d, \u201cpt\u201d, \u201cpx\u201d) but found \u201cdeg\u201d at \u201c1deg\u201d.",
+ "html/elements/picture/sizes-microsyntax-dpcm-source-size-value-novalid.html": "Bad value \u201c1dpcm\u201d for attribute \u201csizes\u201d on element \u201cimg\u201d: Bad source size list: Expected units (one of \u201cem\u201d, \u201cex\u201d, \u201cch\u201d, \u201crem\u201d, \u201cvw\u201d, \u201cvh\u201d, \u201cvmin\u201d, \u201cvmax\u201d, \u201ccm\u201d, \u201cmm\u201d, \u201cq\u201d, \u201cin\u201d, \u201cpc\u201d, \u201cpt\u201d, \u201cpx\u201d) but found \u201cdpcm\u201d at \u201c1dpcm\u201d.",
+ "html/elements/picture/sizes-microsyntax-dpi-source-size-value-novalid.html": "Bad value \u201c1dpi\u201d for attribute \u201csizes\u201d on element \u201cimg\u201d: Bad source size list: Expected units (one of \u201cem\u201d, \u201cex\u201d, \u201cch\u201d, \u201crem\u201d, \u201cvw\u201d, \u201cvh\u201d, \u201cvmin\u201d, \u201cvmax\u201d, \u201ccm\u201d, \u201cmm\u201d, \u201cq\u201d, \u201cin\u201d, \u201cpc\u201d, \u201cpt\u201d, \u201cpx\u201d) but found \u201cdpi\u201d at \u201c1dpi\u201d.",
+ "html/elements/picture/sizes-microsyntax-dppx-source-size-value-novalid.html": "Bad value \u201c1dppx\u201d for attribute \u201csizes\u201d on element \u201cimg\u201d: Bad source size list: Expected units (one of \u201cem\u201d, \u201cex\u201d, \u201cch\u201d, \u201crem\u201d, \u201cvw\u201d, \u201cvh\u201d, \u201cvmin\u201d, \u201cvmax\u201d, \u201ccm\u201d, \u201cmm\u201d, \u201cq\u201d, \u201cin\u201d, \u201cpc\u201d, \u201cpt\u201d, \u201cpx\u201d) but found \u201cdppx\u201d at \u201c1dppx\u201d.",
+ "html/elements/picture/sizes-microsyntax-empty-novalid.html": "Bad value \u201c\u201d for attribute \u201csizes\u201d on element \u201cimg\u201d: Bad source size list: Must not be empty.",
+ "html/elements/picture/sizes-microsyntax-foo-bar-source-size-value-novalid.html": "Bad value \u201cfoo-bar\u201d for attribute \u201csizes\u201d on element \u201cimg\u201d: Bad source size list: Bad CSS number token: Expected a minus sign or a digit but saw \u201cf\u201d instead at \u201cfoo-bar\u201d.",
+ "html/elements/picture/sizes-microsyntax-grad-source-size-value-novalid.html": "Bad value \u201c1grad\u201d for attribute \u201csizes\u201d on element \u201cimg\u201d: Bad source size list: Expected units (one of \u201cem\u201d, \u201cex\u201d, \u201cch\u201d, \u201crem\u201d, \u201cvw\u201d, \u201cvh\u201d, \u201cvmin\u201d, \u201cvmax\u201d, \u201ccm\u201d, \u201cmm\u201d, \u201cq\u201d, \u201cin\u201d, \u201cpc\u201d, \u201cpt\u201d, \u201cpx\u201d) but found \u201cgrad\u201d at \u201c1grad\u201d.",
+ "html/elements/picture/sizes-microsyntax-hz-source-size-value-novalid.html": "Bad value \u201c1Hz\u201d for attribute \u201csizes\u201d on element \u201cimg\u201d: Bad source size list: Expected units (one of \u201cem\u201d, \u201cex\u201d, \u201cch\u201d, \u201crem\u201d, \u201cvw\u201d, \u201cvh\u201d, \u201cvmin\u201d, \u201cvmax\u201d, \u201ccm\u201d, \u201cmm\u201d, \u201cq\u201d, \u201cin\u201d, \u201cpc\u201d, \u201cpt\u201d, \u201cpx\u201d) but found \u201cHz\u201d at \u201c1Hz\u201d.",
+ "html/elements/picture/sizes-microsyntax-inherit-source-size-value-novalid.html": "Bad value \u201cinherit\u201d for attribute \u201csizes\u201d on element \u201cimg\u201d: Bad source size list: Bad CSS number token: Expected a minus sign or a digit but saw \u201ci\u201d instead at \u201cinherit\u201d.",
+ "html/elements/picture/sizes-microsyntax-initial-source-size-value-novalid.html": "Bad value \u201cinitial\u201d for attribute \u201csizes\u201d on element \u201cimg\u201d: Bad source size list: Bad CSS number token: Expected a minus sign or a digit but saw \u201ci\u201d instead at \u201cinitial\u201d.",
+ "html/elements/picture/sizes-microsyntax-junk-in-default-novalid.html": "Bad value \u201c(min-width:500px) 500px, 100vw foo bar\u201d for attribute \u201csizes\u201d on element \u201cimg\u201d: Bad source size list: Bad CSS number token: Expected a minus sign or a digit but saw \u201cb\u201d instead at \u201c\u20260px) 500px, 100vw foo bar\u201d.",
+ "html/elements/picture/sizes-microsyntax-junk-in-source-size-novalid.html": "Bad value \u201c(min-width:500px) 500px foo bar, 100vw\u201d for attribute \u201csizes\u201d on element \u201cimg\u201d: Bad source size list: Bad CSS number token: Expected a minus sign or a digit but saw \u201cb\u201d instead at \u201c\u2026dth:500px) 500px foo bar,\u201d.",
+ "html/elements/picture/sizes-microsyntax-khz-source-size-value-novalid.html": "Bad value \u201c1kHz\u201d for attribute \u201csizes\u201d on element \u201cimg\u201d: Bad source size list: Expected units (one of \u201cem\u201d, \u201cex\u201d, \u201cch\u201d, \u201crem\u201d, \u201cvw\u201d, \u201cvh\u201d, \u201cvmin\u201d, \u201cvmax\u201d, \u201ccm\u201d, \u201cmm\u201d, \u201cq\u201d, \u201cin\u201d, \u201cpc\u201d, \u201cpt\u201d, \u201cpx\u201d) but found \u201ckHz\u201d at \u201c1kHz\u201d.",
+ "html/elements/picture/sizes-microsyntax-media-all-and-min-width-novalid.html": "Bad value \u201call and (min-width:500px) 500px, 100vw\u201d for attribute \u201csizes\u201d on element \u201cimg\u201d: Bad source size list: Bad media condition: Expected a CSS media condition but saw CSS media type \u201call\u201d instead at \u201c\u2026 (min-width:500px) 500px,\u201d.",
+ "html/elements/picture/sizes-microsyntax-media-all-novalid.html": "Bad value \u201call 500px, 100vw\u201d for attribute \u201csizes\u201d on element \u201cimg\u201d: Bad source size list: Bad media condition: Expected a CSS media condition but saw CSS media type \u201call\u201d instead at \u201call 500px,\u201d.",
+ "html/elements/picture/sizes-microsyntax-media-bad-junk-novalid.html": "Bad value \u201c(}) 500px, 100vw\u201d for attribute \u201csizes\u201d on element \u201cimg\u201d: Bad source size list: Bad media condition: Expected a letter at start of a media feature part but saw \u201c}\u201d instead at \u201c(}) 500px,\u201d.",
+ "html/elements/picture/sizes-microsyntax-media-general-enclosed-junk-novalid.html": "Bad value \u201c(123) 500px, 100vw\u201d for attribute \u201csizes\u201d on element \u201cimg\u201d: Bad source size list: Bad media condition: Expected a letter at start of a media feature part but saw \u201c1\u201d instead at \u201c(123) 500px,\u201d.",
+ "html/elements/picture/sizes-microsyntax-media-min-width-no-parenthesis-novalid.html": "Bad value \u201cmin-width:500px 500px, 100vw\u201d for attribute \u201csizes\u201d on element \u201cimg\u201d: Bad source size list: Bad media condition: Expected a letter, hyphen or whitespace but saw \u201c:\u201d instead at \u201cmin-width:500px 500px,\u201d.",
+ "html/elements/picture/sizes-microsyntax-ms-source-size-value-novalid.html": "Bad value \u201c1ms\u201d for attribute \u201csizes\u201d on element \u201cimg\u201d: Bad source size list: Expected units (one of \u201cem\u201d, \u201cex\u201d, \u201cch\u201d, \u201crem\u201d, \u201cvw\u201d, \u201cvh\u201d, \u201cvmin\u201d, \u201cvmax\u201d, \u201ccm\u201d, \u201cmm\u201d, \u201cq\u201d, \u201cin\u201d, \u201cpc\u201d, \u201cpt\u201d, \u201cpx\u201d) but found \u201cms\u201d at \u201c1ms\u201d.",
+ "html/elements/picture/sizes-microsyntax-negative-source-size-value-novalid.html": "Bad value \u201c-1px\u201d for attribute \u201csizes\u201d on element \u201cimg\u201d: Bad source size list: Expected positive size value but found \u201c-1px\u201d at \u201c-1px\u201d.",
+ "html/elements/picture/sizes-microsyntax-no-unit-in-source-size-value-novalid.html": "Bad value \u201c(min-width:500px) 50, 100vw\u201d for attribute \u201csizes\u201d on element \u201cimg\u201d: Bad source size list: Expected units (one of \u201cem\u201d, \u201cex\u201d, \u201cch\u201d, \u201crem\u201d, \u201cvw\u201d, \u201cvh\u201d, \u201cvmin\u201d, \u201cvmax\u201d, \u201ccm\u201d, \u201cmm\u201d, \u201cq\u201d, \u201cin\u201d, \u201cpc\u201d, \u201cpt\u201d, \u201cpx\u201d) but found no units at \u201c(min-width:500px) 50,\u201d.",
+ "html/elements/picture/sizes-microsyntax-percent-in-source-size-value-novalid.html": "Bad value \u201c(min-width:500px) 50%, 100vw\u201d for attribute \u201csizes\u201d on element \u201cimg\u201d: Bad source size list: Expected units (one of \u201cem\u201d, \u201cex\u201d, \u201cch\u201d, \u201crem\u201d, \u201cvw\u201d, \u201cvh\u201d, \u201cvmin\u201d, \u201cvmax\u201d, \u201ccm\u201d, \u201cmm\u201d, \u201cq\u201d, \u201cin\u201d, \u201cpc\u201d, \u201cpt\u201d, \u201cpx\u201d) but found \u201c%\u201d at \u201c(min-width:500px) 50%,\u201d.",
+ "html/elements/picture/sizes-microsyntax-rad-source-size-value-novalid.html": "Bad value \u201c1rad\u201d for attribute \u201csizes\u201d on element \u201cimg\u201d: Bad source size list: Expected units (one of \u201cem\u201d, \u201cex\u201d, \u201cch\u201d, \u201crem\u201d, \u201cvw\u201d, \u201cvh\u201d, \u201cvmin\u201d, \u201cvmax\u201d, \u201ccm\u201d, \u201cmm\u201d, \u201cq\u201d, \u201cin\u201d, \u201cpc\u201d, \u201cpt\u201d, \u201cpx\u201d) but found \u201crad\u201d at \u201c1rad\u201d.",
+ "html/elements/picture/sizes-microsyntax-s-source-size-value-novalid.html": "Bad value \u201c1s\u201d for attribute \u201csizes\u201d on element \u201cimg\u201d: Bad source size list: Expected units (one of \u201cem\u201d, \u201cex\u201d, \u201cch\u201d, \u201crem\u201d, \u201cvw\u201d, \u201cvh\u201d, \u201cvmin\u201d, \u201cvmax\u201d, \u201ccm\u201d, \u201cmm\u201d, \u201cq\u201d, \u201cin\u201d, \u201cpc\u201d, \u201cpt\u201d, \u201cpx\u201d) but found \u201cs\u201d at \u201c1s\u201d.",
+ "html/elements/picture/sizes-microsyntax-scientific-notation-negative-novalid.html": "Bad value \u201c-1e+0px\u201d for attribute \u201csizes\u201d on element \u201cimg\u201d: Bad source size list: Expected positive size value but found \u201c-1e+0px\u201d at \u201c-1e+0px\u201d.",
+ "html/elements/picture/sizes-microsyntax-scientific-notation-non-integer-in-exponent-novalid.html": "Bad value \u201c1e+1.5px\u201d for attribute \u201csizes\u201d on element \u201cimg\u201d: Bad source size list: Bad CSS number token: Expected a digit but saw \u201c.\u201d instead at \u201c1e+1.5px\u201d.",
+ "html/elements/picture/sizes-microsyntax-trailing-comma-novalid.html": "Bad value \u201c(min-width:500px) 500px, 100vw,\u201d for attribute \u201csizes\u201d on element \u201cimg\u201d: Bad source size list: Expected media condition before \u201c\u201d at \u201c\u2026idth:500px) 500px, 100vw,\u201d.",
+ "html/elements/picture/sizes-microsyntax-trailing-junk-novalid.html": "Bad value \u201c(min-width:500px) 500px, 100vw, foo bar\u201d for attribute \u201csizes\u201d on element \u201cimg\u201d: Bad source size list: Expected media condition before \u201c\u201d at \u201c\u2026idth:500px) 500px, 100vw,\u201d.",
+ "html/elements/picture/sizes-microsyntax-turn-source-size-value-novalid.html": "Bad value \u201c1turn\u201d for attribute \u201csizes\u201d on element \u201cimg\u201d: Bad source size list: Expected units (one of \u201cem\u201d, \u201cex\u201d, \u201cch\u201d, \u201crem\u201d, \u201cvw\u201d, \u201cvh\u201d, \u201cvmin\u201d, \u201cvmax\u201d, \u201ccm\u201d, \u201cmm\u201d, \u201cq\u201d, \u201cin\u201d, \u201cpc\u201d, \u201cpt\u201d, \u201cpx\u201d) but found \u201cturn\u201d at \u201c1turn\u201d.",
+ "html/elements/picture/sizes-microsyntax-two-defaults-novalid.html": "Bad value \u201c500px, 100vw\u201d for attribute \u201csizes\u201d on element \u201cimg\u201d: Bad source size list: Expected media condition before \u201c\u201d at \u201c500px,\u201d.",
+ "html/elements/picture/source-after-img-novalid.html": "Element \u201csource\u201d not allowed in this context. (The parent was element \u201cpicture\u201d.) Suppressing further errors from this subtree.",
+ "html/elements/picture/source-align-novalid.html": "Attribute \u201calign\u201d not allowed on element \u201csource\u201d in this context.",
+ "html/elements/picture/source-alt-novalid.html": "Attribute \u201calt\u201d not allowed on element \u201csource\u201d in this context.",
+ "html/elements/picture/source-aria-role-img-novalid.html": "Attribute \u201crole\u201d not allowed on element \u201csource\u201d in this context.",
+ "html/elements/picture/source-aria-role-presentation-novalid.html": "Attribute \u201crole\u201d not allowed on element \u201csource\u201d in this context.",
+ "html/elements/picture/source-before-and-after-img-novalid.html": "Element \u201csource\u201d not allowed in this context. (The parent was element \u201cpicture\u201d.) Suppressing further errors from this subtree.",
+ "html/elements/picture/source-border-novalid.html": "Attribute \u201cborder\u201d not allowed on element \u201csource\u201d in this context.",
+ "html/elements/picture/source-crossorigin-novalid.html": "Attribute \u201ccrossorigin\u201d not allowed on element \u201csource\u201d in this context.",
+ "html/elements/picture/source-height-novalid.html": "Attribute \u201cheight\u201d not allowed on element \u201csource\u201d in this context.",
+ "html/elements/picture/source-hspace-novalid.html": "Attribute \u201chspace\u201d not allowed on element \u201csource\u201d in this context.",
+ "html/elements/picture/source-ismap-novalid.html": "Attribute \u201cismap\u201d not allowed on element \u201csource\u201d in this context.",
+ "html/elements/picture/source-longdesc-novalid.html": "Attribute \u201clongdesc\u201d not allowed on element \u201csource\u201d in this context.",
+ "html/elements/picture/source-name-novalid.html": "Attribute \u201ccrossorigin\u201d not allowed on element \u201csource\u201d in this context.",
+ "html/elements/picture/source-no-srcset-novalid.html": "Element \u201csource\u201d is missing required attribute \u201csrcset\u201d.",
+ "html/elements/picture/source-no-srcset-with-media-novalid.html": "Element \u201csource\u201d is missing required attribute \u201csrcset\u201d.",
+ "html/elements/picture/source-no-srcset-with-sizes-novalid.html": "Element \u201csource\u201d is missing required attribute \u201csrcset\u201d.",
+ "html/elements/picture/source-no-srcset-with-type-novalid.html": "Element \u201csource\u201d is missing required attribute \u201csrcset\u201d.",
+ "html/elements/picture/source-src-novalid.html": "Attribute \u201csrc\u201d not allowed on element \u201csource\u201d in this context.",
+ "html/elements/picture/source-src-srcset-novalid.html": "Attribute \u201csrc\u201d not allowed on element \u201csource\u201d in this context.",
+ "html/elements/picture/source-srcset-h-with-sizes-novalid.html": "Bad value \u201cx 100h, y 200h\u201d for attribute \u201csrcset\u201d on element \u201csource\u201d: Expected width descriptor but found \u201c100h\u201d at \u201cx 100h,\u201d. (When the \u201csizes\u201d attribute is present, all image candidate strings must specify a width.)",
+ "html/elements/picture/source-srcset-w-and-x-with-sizes-novalid.html": "Bad value \u201cx 100w, y 2x\u201d for attribute \u201csrcset\u201d on element \u201csource\u201d: Expected width descriptor but found \u201c2x\u201d at \u201cx 100w, y 2x\u201d. (When the \u201csizes\u201d attribute is present, all image candidate strings must specify a width.)",
+ "html/elements/picture/source-srcset-w-no-sizes-novalid.html": "When the \u201csrcset\u201d attribute has any image candidate string with a width descriptor, the \u201csizes\u201d attribute must also be present.",
+ "html/elements/picture/source-srcset-x-with-sizes-novalid.html": "Bad value \u201cx 1x, y 2x\u201d for attribute \u201csrcset\u201d on element \u201csource\u201d: Expected width descriptor but found \u201c1x\u201d at \u201cx 1x,\u201d. (When the \u201csizes\u201d attribute is present, all image candidate strings must specify a width.)",
+ "html/elements/picture/source-type-srcset-w-novalid.html": "When the \u201csrcset\u201d attribute has any image candidate string with a width descriptor, the \u201csizes\u201d attribute must also be present.",
+ "html/elements/picture/source-usemap-novalid.html": "Attribute \u201cusemap\u201d not allowed on element \u201csource\u201d in this context.",
+ "html/elements/picture/source-vspace-novalid.html": "Attribute \u201cvspace\u201d not allowed on element \u201csource\u201d in this context.",
+ "html/elements/picture/source-width-novalid.html": "Attribute \u201cwidth\u201d not allowed on element \u201csource\u201d in this context.",
+ "html/elements/picture/srcset-microsyntax-broken-url-novalid.html": "Bad value \u201chttp: 1x\u201d for attribute \u201csrcset\u201d on element \u201cimg\u201d: Bad image-candidate URL: \u201chttp:\u201d: Expected a slash (\"/\").",
+ "html/elements/picture/srcset-microsyntax-comma-novalid.html": "Bad value \u201c,\u201d for attribute \u201csrcset\u201d on element \u201cimg\u201d: Starts with empty image-candidate string.",
+ "html/elements/picture/srcset-microsyntax-css-comment-after-descriptor-novalid.html": "Bad value \u201cx 2x/**/\u201d for attribute \u201csrcset\u201d on element \u201cimg\u201d: Expected number followed by \u201cw\u201d or \u201cx\u201d but found \u201c2x/**/\u201d at \u201cx 2x/**/\u201d.",
+ "html/elements/picture/srcset-microsyntax-curly-bracket-junk-novalid.html": "Bad value \u201cx {, y 1x\u201d for attribute \u201csrcset\u201d on element \u201cimg\u201d: Expected number followed by \u201cw\u201d or \u201cx\u201d but found \u201c{\u201d at \u201cx {,\u201d.",
+ "html/elements/picture/srcset-microsyntax-empty-novalid.html": "Bad value \u201c\u201d for attribute \u201csrcset\u201d on element \u201cimg\u201d: Must contain one or more image candidate strings.",
+ "html/elements/picture/srcset-microsyntax-function-novalid.html": "Bad value \u201cx foobar(baz quux, lol), y 1x\u201d for attribute \u201csrcset\u201d on element \u201cimg\u201d: Expected number followed by \u201cw\u201d or \u201cx\u201d but found \u201cfoobar(baz quux, lol))\u201d at \u201c\u2026baz quux, lol),\u201d.",
+ "html/elements/picture/srcset-microsyntax-h-novalid.html": "Bad value \u201cx 1h\u201d for attribute \u201csrcset\u201d on element \u201cimg\u201d: Expected width descriptor but found \u201c1h\u201d at \u201cx 1h\u201d. (When the \u201csizes\u201d attribute is present, all image candidate strings must specify a width.)",
+ "html/elements/picture/srcset-microsyntax-infinity-x-novalid.html": "Bad value \u201cx Infinityx\u201d for attribute \u201csrcset\u201d on element \u201cimg\u201d: Bad positive floating point number: Expected a digit but saw \u201cI\u201d instead at \u201cx Infinityx\u201d.",
+ "html/elements/picture/srcset-microsyntax-leading-comma-multiple-novalid.html": "Bad value \u201c,,,x\u201d for attribute \u201csrcset\u201d on element \u201cimg\u201d: Starts with empty image-candidate string.",
+ "html/elements/picture/srcset-microsyntax-leading-comma-novalid.html": "Bad value \u201c,x\u201d for attribute \u201csrcset\u201d on element \u201cimg\u201d: Starts with empty image-candidate string.",
+ "html/elements/picture/srcset-microsyntax-leading-dot-x-novalid.html": "Bad value \u201cx .5x\u201d for attribute \u201csrcset\u201d on element \u201cimg\u201d: Bad positive floating point number: Expected a digit but saw \u201c.\u201d instead at \u201cx .5x\u201d.",
+ "html/elements/picture/srcset-microsyntax-nan-x-novalid.html": "Bad value \u201cx NaNx\u201d for attribute \u201csrcset\u201d on element \u201cimg\u201d: Bad positive floating point number: Expected a digit but saw \u201cN\u201d instead at \u201cx NaNx\u201d.",
+ "html/elements/picture/srcset-microsyntax-negative-w-novalid.html": "Bad value \u201cx -1w\u201d for attribute \u201csrcset\u201d on element \u201cimg\u201d: Expected number greater than zero but found \u201c-1\u201d at \u201cx -1w\u201d.",
+ "html/elements/picture/srcset-microsyntax-negative-x-novalid.html": "Bad value \u201cx -1x\u201d for attribute \u201csrcset\u201d on element \u201cimg\u201d: Expected number greater than zero but found \u201c-1\u201d at \u201cx -1x\u201d.",
+ "html/elements/picture/srcset-microsyntax-negative-zero-w-novalid.html": "Bad value \u201cx -0w\u201d for attribute \u201csrcset\u201d on element \u201cimg\u201d: Expected number greater than zero but found \u201c-0\u201d at \u201cx -0w\u201d.",
+ "html/elements/picture/srcset-microsyntax-negative-zero-x-novalid.html": "Bad value \u201cx -0x\u201d for attribute \u201csrcset\u201d on element \u201cimg\u201d: Expected number greater than zero but found \u201c-0\u201d at \u201cx -0x\u201d.",
+ "html/elements/picture/srcset-microsyntax-non-integer-w-novalid.html": "Bad value \u201cx 1.5w\u201d for attribute \u201csrcset\u201d on element \u201cimg\u201d: Expected integer but found \u201c1.5\u201d at \u201cx 1.5w\u201d.",
+ "html/elements/picture/srcset-microsyntax-parenthesis-junk-novalid.html": "Bad value \u201cx ><(((((o)>, y 1x\u201d for attribute \u201csrcset\u201d on element \u201cimg\u201d: Expected number followed by \u201cw\u201d or \u201cx\u201d but found \u201c><(((((o))>\u201d at \u201cx ><(((((o)>,\u201d.",
+ "html/elements/picture/srcset-microsyntax-pipe-junk-novalid.html": "Bad value \u201cx ||, y 1x\u201d for attribute \u201csrcset\u201d on element \u201cimg\u201d: Expected number followed by \u201cw\u201d or \u201cx\u201d but found \u201c||\u201d at \u201cx ||,\u201d.",
+ "html/elements/picture/srcset-microsyntax-plus-w-novalid.html": "Bad value \u201cx +1w\u201d for attribute \u201csrcset\u201d on element \u201cimg\u201d: Expected number without leading plus sign but found \u201c+1\u201d at \u201cx +1w\u201d.",
+ "html/elements/picture/srcset-microsyntax-plus-x-novalid.html": "Bad value \u201cx +1x\u201d for attribute \u201csrcset\u201d on element \u201cimg\u201d: Expected number without leading plus sign but found \u201c+1\u201d at \u201cx +1x\u201d.",
+ "html/elements/picture/srcset-microsyntax-scientific-notation-w-novalid.html": "Bad value \u201cx 1e0w\u201d for attribute \u201csrcset\u201d on element \u201cimg\u201d: Expected integer but found \u201c1e0\u201d at \u201cx 1e0w\u201d.",
+ "html/elements/picture/srcset-microsyntax-square-bracket-junk-novalid.html": "Bad value \u201cx [, y 1x\u201d for attribute \u201csrcset\u201d on element \u201cimg\u201d: Expected number followed by \u201cw\u201d or \u201cx\u201d but found \u201c[\u201d at \u201cx [,\u201d.",
+ "html/elements/picture/srcset-microsyntax-trailing-comma-multiple-novalid.html": "Bad value \u201cx,,,\u201d for attribute \u201csrcset\u201d on element \u201cimg\u201d: Empty image-candidate string at \u201cx,,,\u201d.",
+ "html/elements/picture/srcset-microsyntax-trailing-comma-novalid.html": "Bad value \u201cx,\u201d for attribute \u201csrcset\u201d on element \u201cimg\u201d: Ends with empty image-candidate string.",
+ "html/elements/picture/srcset-microsyntax-unique-descriptors-1x-and-omitted-novalid.html": "Bad value \u201cx 1x, y\u201d for attribute \u201csrcset\u201d on element \u201cimg\u201d: Density for image \u201cy\u201d is identical to density for image \u201cx\u201d.",
+ "html/elements/picture/srcset-microsyntax-unique-descriptors-2x-novalid.html": "Bad value \u201cx 2x, y 2x\u201d for attribute \u201csrcset\u201d on element \u201cimg\u201d: Density for image \u201cy\u201d is identical to density for image \u201cx\u201d.",
+ "html/elements/picture/srcset-microsyntax-unique-descriptors-integer-and-decimals-x-novalid.html": "Bad value \u201cx 1x, y 1.0x\u201d for attribute \u201csrcset\u201d on element \u201cimg\u201d: Density for image \u201cy\u201d is identical to density for image \u201cx\u201d.",
+ "html/elements/picture/srcset-microsyntax-unique-descriptors-w-novalid.html": "Bad value \u201cx 1w, y 1w\u201d for attribute \u201csrcset\u201d on element \u201cimg\u201d: Width for image \u201cy\u201d is identical to width for image \u201cx\u201d.",
+ "html/elements/picture/srcset-microsyntax-uppercase-w-novalid.html": "Bad value \u201cx 1W\u201d for attribute \u201csrcset\u201d on element \u201cimg\u201d: Expected width descriptor but found \u201c1W\u201d at \u201cx 1W\u201d. (When the \u201csizes\u201d attribute is present, all image candidate strings must specify a width.)",
+ "html/elements/picture/srcset-microsyntax-w-and-h-novalid.html": "Bad value \u201cx 1w 1h\u201d for attribute \u201csrcset\u201d on element \u201cimg\u201d: Expected single descriptor but found extraneous descriptor \u201c1h\u201d at \u201cx 1w 1h\u201d.",
+ "html/elements/picture/srcset-microsyntax-w-and-no-descriptor-novalid.html": "Bad value \u201cx 1w, y\u201d for attribute \u201csrcset\u201d on element \u201cimg\u201d: No width specified for image \u201cy\u201d. (When the \u201csizes\u201d attribute is present, all image candidate strings must specify a width.)",
+ "html/elements/picture/srcset-microsyntax-x-and-h-novalid.html": "Bad value \u201cx 1x 1h\u201d for attribute \u201csrcset\u201d on element \u201cimg\u201d: Expected width descriptor but found \u201c1x\u201d at \u201cx 1x \u201d. (When the \u201csizes\u201d attribute is present, all image candidate strings must specify a width.)",
+ "html/elements/picture/srcset-microsyntax-x-and-w-novalid.html": "Bad value \u201cx 1x 1w\u201d for attribute \u201csrcset\u201d on element \u201cimg\u201d: Expected width descriptor but found \u201c1x\u201d at \u201cx 1x \u201d. (When the \u201csizes\u201d attribute is present, all image candidate strings must specify a width.)",
+ "html/elements/picture/srcset-microsyntax-zero-w-novalid.html": "Bad value \u201cx 0w\u201d for attribute \u201csrcset\u201d on element \u201cimg\u201d: Expected number greater than zero but found \u201c0\u201d at \u201cx 0w\u201d.",
+ "html/elements/picture/srcset-microsyntax-zero-x-novalid.html": "Bad value \u201cx 0x\u201d for attribute \u201csrcset\u201d on element \u201cimg\u201d: Bad positive floating point number: Zero is not a valid positive floating point number at \u201cx 0x\u201d.",
+ "html/elements/picture/svg-image-srcset-novalid.html": "Attribute \u201csrcset\u201d not allowed on element \u201cimage\u201d in this context.",
+ "html/elements/picture/track-srcset-novalid.html": "Attribute \u201csrcset\u201d not allowed on element \u201ctrack\u201d in this context.",
+ "html/elements/picture/video-source-media-src-novalid.html": "Attribute \u201cmedia\u201d not allowed on element \u201csource\u201d in this context.",
+ "html/elements/picture/video-source-sizes-srcset-novalid.html": "Attribute \u201csizes\u201d not allowed on element \u201csource\u201d in this context.",
+ "html/elements/picture/video-source-srcset-novalid.html": "Attribute \u201csrcset\u201d not allowed on element \u201csource\u201d in this context.",
+ "html/elements/picture/video-source-srcset-src-novalid.html": "Attribute \u201csrcset\u201d not allowed on element \u201csource\u201d in this context.",
+ "html/elements/picture/video-srcset-novalid.html": "Attribute \u201csrcset\u201d not allowed on element \u201cvideo\u201d in this context.",
+ "html/elements/pre/model-novalid.html": "No \u201cp\u201d element in scope but a \u201cp\u201d end tag seen.",
+ "html/elements/q/cite/fragment-backslash-novalid.html": "Bad value \u201c#\\\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/q/cite/fragment-contains-hash-novalid.html": "Bad value \u201chttp://foo/path#f#g\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/q/cite/fragment-leading-space-novalid.html": "Bad value \u201chttp://f:21/b# e\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/q/cite/host-cr-novalid.html": "Bad value \u201chttp://example.\norg\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/q/cite/host-double-percent-encoded-novalid.html": "Bad value \u201chttp://\uff05\uff14\uff11.com\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/q/cite/host-double-percent-encoded-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%bc%85%ef%bc%94%ef%bc%91.com\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/q/cite/host-empty-novalid.html": "Bad value \u201chttp://\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/q/cite/host-empty-userinfo-empty-novalid.html": "Bad value \u201chttp://@/www.example.com\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/q/cite/host-empty-with-userinfo-novalid.html": "Bad value \u201chttp://user:pass@/\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/q/cite/host-hostname-in-brackets-novalid.html": "Bad value \u201chttp://[www.google.com]/\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Invalid host: Illegal character.",
+ "html/elements/q/cite/host-invalid-unicode-novalid.html": "Forbidden code point U+fdd0.",
+ "html/elements/q/cite/host-invalid-unicode-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%b7%90zyx.com\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Invalid host: A label or domain name contains disallowed characters..",
+ "html/elements/q/cite/host-newline-novalid.html": "Bad value \u201chttp://example.\norg\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/q/cite/host-space-novalid.html": "Bad value \u201chttp://example .org\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Invalid host: Domain contains invalid character: .",
+ "html/elements/q/cite/host-square-brackets-port-contains-colon-novalid.html": "Bad value \u201chttp://[1::2]:3:4\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Illegal character in port.",
+ "html/elements/q/cite/host-tab-novalid.html": "Bad value \u201chttp://example\t.org\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/q/cite/host-u0000-percent-encoded-novalid.html": "Bad value \u201chttp://\uff05\uff10\uff10.com\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/q/cite/host-u0000-percent-encoded-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%bc%85%ef%bc%90%ef%bc%90.com\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/q/cite/path-bare-percent-sign-novalid.html": "Bad value \u201chttp://example.com/foo%\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Percentage (\"%\") is not followed by two hexadecimal digits.",
+ "html/elements/q/cite/path-contains-space-novalid.html": "Bad value \u201c/a/ /c\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/q/cite/path-leading-backslash-at-sign-novalid.html": "Bad value \u201chttp://foo.com/\\@\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/q/cite/path-leading-colon-backslash-novalid.html": "Bad value \u201c:\\\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/q/cite/path-leading-colon-chars-backslash-novalid.html": "Bad value \u201c:foo.com\\\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/q/cite/path-leading-space-novalid.html": "Bad value \u201chttp://f:21/ b\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/q/cite/path-percent-encoded-malformed-novalid.html": "Bad value \u201chttp://example.com/foo/%2e%2\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Percentage (\"%\") is not followed by two hexadecimal digits.",
+ "html/elements/q/cite/path-relative-square-brackets-novalid.html": "Bad value \u201c[61:24:74]:98\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/q/cite/path-tab-novalid.html": "Bad value \u201chttp://example.com/foo\tbar\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/q/cite/path-trailing-space-novalid.html": "Bad value \u201chttp://f:21/b ?\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/q/cite/path-u0091-novalid.html": "Forbidden code point U+0091.",
+ "html/elements/q/cite/port-cr-novalid.html": "Bad value \u201chttp://f:\n/c\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/q/cite/port-leading-colon-bracket-colon-novalid.html": "Bad value \u201chttp://2001::1]:80\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Illegal character in port.",
+ "html/elements/q/cite/port-leading-colon-novalid.html": "Bad value \u201chttp://2001::1\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Illegal character in port.",
+ "html/elements/q/cite/port-leading-dash-novalid.html": "Bad value \u201chttp://foo:-80/\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Illegal character in port.",
+ "html/elements/q/cite/port-multiple-letters-novalid.html": "Bad value \u201chttp://f:fifty-two/c\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Illegal character in port.",
+ "html/elements/q/cite/port-newline-novalid.html": "Bad value \u201chttp://f:\n/c\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/q/cite/port-single-letter-novalid.html": "Bad value \u201chttp://f:b/c\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Illegal character in port.",
+ "html/elements/q/cite/port-space-novalid.html": "Bad value \u201chttp://f: /c\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Illegal character in port.",
+ "html/elements/q/cite/port-tab-novalid.html": "Bad value \u201chttp://f:\t/c\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/q/cite/query-leading-space-novalid.html": "Bad value \u201chttp://f:21/b? d\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Illegal character in query: not a URL code point.",
+ "html/elements/q/cite/query-trailing-space-novalid.html": "Bad value \u201chttp://f:21/b?d #\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Illegal character in query: not a URL code point.",
+ "html/elements/q/cite/scheme-data-contains-fragment-haswarn.html": "Bad value \u201cdata:text/html,test#test\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Fragment is not allowed for data: URIs according to RFC 2397.",
+ "html/elements/q/cite/scheme-data-single-slash-novalid.html": "Bad value \u201cdata:/example.com/\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Expected a token character or a semicolon but saw \u201c/\u201d instead.",
+ "html/elements/q/cite/scheme-file-backslash-novalid.html": "Bad value \u201cfile:c:\\foo\\bar.html\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/q/cite/scheme-file-single-slash-c-bar-novalid.html": "Bad value \u201cfile:/C|/foo/bar\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/q/cite/scheme-file-triple-slash-c-bar-novalid.html": "Bad value \u201cfile:///C|/foo/bar\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/q/cite/scheme-ftp-no-slash-novalid.html": "Bad value \u201cftp:example.com/\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/q/cite/scheme-ftp-single-slash-novalid.html": "Bad value \u201cftp:/example.com/\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/q/cite/scheme-http-backslash-novalid.html": "Bad value \u201chttp:\\\\foo.com\\\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/q/cite/scheme-http-no-slash-colon-novalid.html": "Bad value \u201chttp::@c:29\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/q/cite/scheme-http-no-slash-novalid.html": "Bad value \u201chttp:foo.com\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/q/cite/scheme-http-no-slash-square-bracket-novalid.html": "Bad value \u201chttp:[61:27]/:foo\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/q/cite/scheme-http-single-slash-novalid.html": "Bad value \u201chttp:/example.com/\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/q/cite/scheme-https-no-slash-novalid.html": "Bad value \u201chttps:example.com/\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/q/cite/scheme-https-single-slash-novalid.html": "Bad value \u201chttps:/example.com/\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/q/cite/scheme-javascript-no-slash-malformed-novalid.html": "Bad value \u201cjavascript:example.com/\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: syntax error",
+ "html/elements/q/cite/scheme-trailing-cr-novalid.html": "Bad value \u201ca:\nfoo.com\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/q/cite/scheme-trailing-newline-novalid.html": "Bad value \u201ca:\nfoo.com\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/q/cite/scheme-trailing-space-novalid.html": "Bad value \u201ca: foo.com\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/q/cite/scheme-trailing-tab-novalid.html": "Bad value \u201ca:\tfoo.com\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/q/cite/userinfo-backslash-novalid.html": "Bad value \u201chttp://a\\b:c\\d@foo.com\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/q/cite/userinfo-password-bad-chars-novalid.html": "\u201c&\u201d did not start a character reference. (\u201c&\u201d probably should have been escaped as \u201c&amp;\u201d.)",
+ "html/elements/q/cite/userinfo-password-contains-pile-of-poo-novalid.html": "Bad value \u201chttp://foo:\ud83d\udca9@example.com\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Illegal character in user or password: not a URL code point.",
+ "html/elements/q/cite/userinfo-username-contains-at-sign-novalid.html": "Bad value \u201chttp://::@c@d:2\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: User or password contains an at symbol (\"@\") not percent-encoded.",
+ "html/elements/q/cite/userinfo-username-contains-pile-of-poo-novalid.html": "Bad value \u201chttp://\ud83d\udca9:foo@example.com\u201d for attribute \u201ccite\u201d on element \u201cq\u201d: Bad URL: Illegal character in user or password: not a URL code point.",
+ "html/elements/q/model-novalid.html": "End tag \u201cp\u201d implied, but there were open elements.",
+ "html/elements/ruby/empty-novalid.html": "Element \u201cruby\u201d is missing one or more of the following child elements: [rp, rt].",
+ "html/elements/ruby/missing-rt-novalid.html": "Element \u201cruby\u201d is missing required child element \u201crt\u201d.",
+ "html/elements/samp/model-novalid.html": "End tag \u201cp\u201d implied, but there were open elements.",
+ "html/elements/script/language-novalid.html": "The \u201clanguage\u201d attribute on the \u201cscript\u201d element is obsolete. Use the \u201ctype\u201d attribute instead.",
+ "html/elements/script/src-empty-novalid.html": "Bad value \u201c\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Must be non-empty.",
+ "html/elements/script/src-whitespace-only-novalid.html": "Bad value \u201c\t \n\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Must be non-empty.",
+ "html/elements/script/src/fragment-backslash-novalid.html": "Bad value \u201c#\\\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/script/src/fragment-contains-hash-novalid.html": "Bad value \u201chttp://foo/path#f#g\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/script/src/fragment-leading-space-novalid.html": "Bad value \u201chttp://f:21/b# e\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/script/src/host-cr-novalid.html": "Bad value \u201chttp://example.\norg\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/script/src/host-double-percent-encoded-novalid.html": "Bad value \u201chttp://\uff05\uff14\uff11.com\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/script/src/host-double-percent-encoded-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%bc%85%ef%bc%94%ef%bc%91.com\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/script/src/host-empty-novalid.html": "Bad value \u201chttp://\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/script/src/host-empty-userinfo-empty-novalid.html": "Bad value \u201chttp://@/www.example.com\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/script/src/host-empty-with-userinfo-novalid.html": "Bad value \u201chttp://user:pass@/\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/script/src/host-hostname-in-brackets-novalid.html": "Bad value \u201chttp://[www.google.com]/\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Invalid host: Illegal character.",
+ "html/elements/script/src/host-invalid-unicode-novalid.html": "Forbidden code point U+fdd0.",
+ "html/elements/script/src/host-invalid-unicode-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%b7%90zyx.com\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Invalid host: A label or domain name contains disallowed characters..",
+ "html/elements/script/src/host-newline-novalid.html": "Bad value \u201chttp://example.\norg\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/script/src/host-space-novalid.html": "Bad value \u201chttp://example .org\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Invalid host: Domain contains invalid character: .",
+ "html/elements/script/src/host-square-brackets-port-contains-colon-novalid.html": "Bad value \u201chttp://[1::2]:3:4\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Illegal character in port.",
+ "html/elements/script/src/host-tab-novalid.html": "Bad value \u201chttp://example\t.org\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/script/src/host-u0000-percent-encoded-novalid.html": "Bad value \u201chttp://\uff05\uff10\uff10.com\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/script/src/host-u0000-percent-encoded-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%bc%85%ef%bc%90%ef%bc%90.com\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/script/src/path-bare-percent-sign-novalid.html": "Bad value \u201chttp://example.com/foo%\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Percentage (\"%\") is not followed by two hexadecimal digits.",
+ "html/elements/script/src/path-contains-space-novalid.html": "Bad value \u201c/a/ /c\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/script/src/path-leading-backslash-at-sign-novalid.html": "Bad value \u201chttp://foo.com/\\@\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/script/src/path-leading-colon-backslash-novalid.html": "Bad value \u201c:\\\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/script/src/path-leading-colon-chars-backslash-novalid.html": "Bad value \u201c:foo.com\\\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/script/src/path-leading-space-novalid.html": "Bad value \u201chttp://f:21/ b\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/script/src/path-percent-encoded-malformed-novalid.html": "Bad value \u201chttp://example.com/foo/%2e%2\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Percentage (\"%\") is not followed by two hexadecimal digits.",
+ "html/elements/script/src/path-relative-square-brackets-novalid.html": "Bad value \u201c[61:24:74]:98\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/script/src/path-tab-novalid.html": "Bad value \u201chttp://example.com/foo\tbar\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/script/src/path-trailing-space-novalid.html": "Bad value \u201chttp://f:21/b ?\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/script/src/path-u0091-novalid.html": "Forbidden code point U+0091.",
+ "html/elements/script/src/port-cr-novalid.html": "Bad value \u201chttp://f:\n/c\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/script/src/port-leading-colon-bracket-colon-novalid.html": "Bad value \u201chttp://2001::1]:80\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Illegal character in port.",
+ "html/elements/script/src/port-leading-colon-novalid.html": "Bad value \u201chttp://2001::1\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Illegal character in port.",
+ "html/elements/script/src/port-leading-dash-novalid.html": "Bad value \u201chttp://foo:-80/\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Illegal character in port.",
+ "html/elements/script/src/port-multiple-letters-novalid.html": "Bad value \u201chttp://f:fifty-two/c\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Illegal character in port.",
+ "html/elements/script/src/port-newline-novalid.html": "Bad value \u201chttp://f:\n/c\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/script/src/port-single-letter-novalid.html": "Bad value \u201chttp://f:b/c\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Illegal character in port.",
+ "html/elements/script/src/port-space-novalid.html": "Bad value \u201chttp://f: /c\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Illegal character in port.",
+ "html/elements/script/src/port-tab-novalid.html": "Bad value \u201chttp://f:\t/c\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/script/src/query-leading-space-novalid.html": "Bad value \u201chttp://f:21/b? d\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Illegal character in query: not a URL code point.",
+ "html/elements/script/src/query-trailing-space-novalid.html": "Bad value \u201chttp://f:21/b?d #\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Illegal character in query: not a URL code point.",
+ "html/elements/script/src/scheme-data-contains-fragment-haswarn.html": "Bad value \u201cdata:text/html,test#test\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Fragment is not allowed for data: URIs according to RFC 2397.",
+ "html/elements/script/src/scheme-data-single-slash-novalid.html": "Bad value \u201cdata:/example.com/\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Expected a token character or a semicolon but saw \u201c/\u201d instead.",
+ "html/elements/script/src/scheme-file-backslash-novalid.html": "Bad value \u201cfile:c:\\foo\\bar.html\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/script/src/scheme-file-single-slash-c-bar-novalid.html": "Bad value \u201cfile:/C|/foo/bar\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/script/src/scheme-file-triple-slash-c-bar-novalid.html": "Bad value \u201cfile:///C|/foo/bar\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/script/src/scheme-ftp-no-slash-novalid.html": "Bad value \u201cftp:example.com/\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/script/src/scheme-ftp-single-slash-novalid.html": "Bad value \u201cftp:/example.com/\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/script/src/scheme-http-backslash-novalid.html": "Bad value \u201chttp:\\\\foo.com\\\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/script/src/scheme-http-no-slash-colon-novalid.html": "Bad value \u201chttp::@c:29\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/script/src/scheme-http-no-slash-novalid.html": "Bad value \u201chttp:foo.com\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/script/src/scheme-http-no-slash-square-bracket-novalid.html": "Bad value \u201chttp:[61:27]/:foo\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/script/src/scheme-http-single-slash-novalid.html": "Bad value \u201chttp:/example.com/\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/script/src/scheme-https-no-slash-novalid.html": "Bad value \u201chttps:example.com/\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/script/src/scheme-https-single-slash-novalid.html": "Bad value \u201chttps:/example.com/\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/script/src/scheme-javascript-no-slash-malformed-novalid.html": "Bad value \u201cjavascript:example.com/\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: syntax error",
+ "html/elements/script/src/scheme-trailing-cr-novalid.html": "Bad value \u201ca:\nfoo.com\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/script/src/scheme-trailing-newline-novalid.html": "Bad value \u201ca:\nfoo.com\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/script/src/scheme-trailing-space-novalid.html": "Bad value \u201ca: foo.com\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/script/src/scheme-trailing-tab-novalid.html": "Bad value \u201ca:\tfoo.com\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/script/src/userinfo-backslash-novalid.html": "Bad value \u201chttp://a\\b:c\\d@foo.com\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/script/src/userinfo-password-bad-chars-novalid.html": "\u201c&\u201d did not start a character reference. (\u201c&\u201d probably should have been escaped as \u201c&amp;\u201d.)",
+ "html/elements/script/src/userinfo-password-contains-pile-of-poo-novalid.html": "Bad value \u201chttp://foo:\ud83d\udca9@example.com\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Illegal character in user or password: not a URL code point.",
+ "html/elements/script/src/userinfo-username-contains-at-sign-novalid.html": "Bad value \u201chttp://::@c@d:2\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: User or password contains an at symbol (\"@\") not percent-encoded.",
+ "html/elements/script/src/userinfo-username-contains-pile-of-poo-novalid.html": "Bad value \u201chttp://\ud83d\udca9:foo@example.com\u201d for attribute \u201csrc\u201d on element \u201cscript\u201d: Bad URL: Illegal character in user or password: not a URL code point.",
+ "html/elements/small/model-novalid.html": "End tag \u201cp\u201d implied, but there were open elements.",
+ "html/elements/source/src-empty-novalid.html": "Bad value \u201c\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Must be non-empty.",
+ "html/elements/source/src-whitespace-only-novalid.html": "Bad value \u201c\t \n\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Must be non-empty.",
+ "html/elements/source/src/fragment-backslash-novalid.html": "Bad value \u201c#\\\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/source/src/fragment-contains-hash-novalid.html": "Bad value \u201chttp://foo/path#f#g\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/source/src/fragment-leading-space-novalid.html": "Bad value \u201chttp://f:21/b# e\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/source/src/host-cr-novalid.html": "Bad value \u201chttp://example.\norg\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/source/src/host-double-percent-encoded-novalid.html": "Bad value \u201chttp://\uff05\uff14\uff11.com\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/source/src/host-double-percent-encoded-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%bc%85%ef%bc%94%ef%bc%91.com\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/source/src/host-empty-novalid.html": "Bad value \u201chttp://\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/source/src/host-empty-userinfo-empty-novalid.html": "Bad value \u201chttp://@/www.example.com\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/source/src/host-empty-with-userinfo-novalid.html": "Bad value \u201chttp://user:pass@/\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/source/src/host-hostname-in-brackets-novalid.html": "Bad value \u201chttp://[www.google.com]/\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Invalid host: Illegal character.",
+ "html/elements/source/src/host-invalid-unicode-novalid.html": "Forbidden code point U+fdd0.",
+ "html/elements/source/src/host-invalid-unicode-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%b7%90zyx.com\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Invalid host: A label or domain name contains disallowed characters..",
+ "html/elements/source/src/host-newline-novalid.html": "Bad value \u201chttp://example.\norg\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/source/src/host-space-novalid.html": "Bad value \u201chttp://example .org\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Invalid host: Domain contains invalid character: .",
+ "html/elements/source/src/host-square-brackets-port-contains-colon-novalid.html": "Bad value \u201chttp://[1::2]:3:4\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Illegal character in port.",
+ "html/elements/source/src/host-tab-novalid.html": "Bad value \u201chttp://example\t.org\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/source/src/host-u0000-percent-encoded-novalid.html": "Bad value \u201chttp://\uff05\uff10\uff10.com\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/source/src/host-u0000-percent-encoded-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%bc%85%ef%bc%90%ef%bc%90.com\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/source/src/path-bare-percent-sign-novalid.html": "Bad value \u201chttp://example.com/foo%\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Percentage (\"%\") is not followed by two hexadecimal digits.",
+ "html/elements/source/src/path-contains-space-novalid.html": "Bad value \u201c/a/ /c\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/source/src/path-leading-backslash-at-sign-novalid.html": "Bad value \u201chttp://foo.com/\\@\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/source/src/path-leading-colon-backslash-novalid.html": "Bad value \u201c:\\\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/source/src/path-leading-colon-chars-backslash-novalid.html": "Bad value \u201c:foo.com\\\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/source/src/path-leading-space-novalid.html": "Bad value \u201chttp://f:21/ b\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/source/src/path-percent-encoded-malformed-novalid.html": "Bad value \u201chttp://example.com/foo/%2e%2\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Percentage (\"%\") is not followed by two hexadecimal digits.",
+ "html/elements/source/src/path-relative-square-brackets-novalid.html": "Bad value \u201c[61:24:74]:98\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/source/src/path-tab-novalid.html": "Bad value \u201chttp://example.com/foo\tbar\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/source/src/path-trailing-space-novalid.html": "Bad value \u201chttp://f:21/b ?\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/source/src/path-u0091-novalid.html": "Forbidden code point U+0091.",
+ "html/elements/source/src/port-cr-novalid.html": "Bad value \u201chttp://f:\n/c\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/source/src/port-leading-colon-bracket-colon-novalid.html": "Bad value \u201chttp://2001::1]:80\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Illegal character in port.",
+ "html/elements/source/src/port-leading-colon-novalid.html": "Bad value \u201chttp://2001::1\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Illegal character in port.",
+ "html/elements/source/src/port-leading-dash-novalid.html": "Bad value \u201chttp://foo:-80/\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Illegal character in port.",
+ "html/elements/source/src/port-multiple-letters-novalid.html": "Bad value \u201chttp://f:fifty-two/c\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Illegal character in port.",
+ "html/elements/source/src/port-newline-novalid.html": "Bad value \u201chttp://f:\n/c\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/source/src/port-single-letter-novalid.html": "Bad value \u201chttp://f:b/c\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Illegal character in port.",
+ "html/elements/source/src/port-space-novalid.html": "Bad value \u201chttp://f: /c\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Illegal character in port.",
+ "html/elements/source/src/port-tab-novalid.html": "Bad value \u201chttp://f:\t/c\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/source/src/query-leading-space-novalid.html": "Bad value \u201chttp://f:21/b? d\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Illegal character in query: not a URL code point.",
+ "html/elements/source/src/query-trailing-space-novalid.html": "Bad value \u201chttp://f:21/b?d #\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Illegal character in query: not a URL code point.",
+ "html/elements/source/src/scheme-data-contains-fragment-haswarn.html": "Bad value \u201cdata:text/html,test#test\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Fragment is not allowed for data: URIs according to RFC 2397.",
+ "html/elements/source/src/scheme-data-single-slash-novalid.html": "Bad value \u201cdata:/example.com/\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Expected a token character or a semicolon but saw \u201c/\u201d instead.",
+ "html/elements/source/src/scheme-file-backslash-novalid.html": "Bad value \u201cfile:c:\\foo\\bar.html\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/source/src/scheme-file-single-slash-c-bar-novalid.html": "Bad value \u201cfile:/C|/foo/bar\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/source/src/scheme-file-triple-slash-c-bar-novalid.html": "Bad value \u201cfile:///C|/foo/bar\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/source/src/scheme-ftp-no-slash-novalid.html": "Bad value \u201cftp:example.com/\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/source/src/scheme-ftp-single-slash-novalid.html": "Bad value \u201cftp:/example.com/\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/source/src/scheme-http-backslash-novalid.html": "Bad value \u201chttp:\\\\foo.com\\\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/source/src/scheme-http-no-slash-colon-novalid.html": "Bad value \u201chttp::@c:29\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/source/src/scheme-http-no-slash-novalid.html": "Bad value \u201chttp:foo.com\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/source/src/scheme-http-no-slash-square-bracket-novalid.html": "Bad value \u201chttp:[61:27]/:foo\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/source/src/scheme-http-single-slash-novalid.html": "Bad value \u201chttp:/example.com/\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/source/src/scheme-https-no-slash-novalid.html": "Bad value \u201chttps:example.com/\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/source/src/scheme-https-single-slash-novalid.html": "Bad value \u201chttps:/example.com/\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/source/src/scheme-javascript-no-slash-malformed-novalid.html": "Bad value \u201cjavascript:example.com/\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: syntax error",
+ "html/elements/source/src/scheme-trailing-cr-novalid.html": "Bad value \u201ca:\nfoo.com\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/source/src/scheme-trailing-newline-novalid.html": "Bad value \u201ca:\nfoo.com\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/source/src/scheme-trailing-space-novalid.html": "Bad value \u201ca: foo.com\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/source/src/scheme-trailing-tab-novalid.html": "Bad value \u201ca:\tfoo.com\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/source/src/userinfo-backslash-novalid.html": "Bad value \u201chttp://a\\b:c\\d@foo.com\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/source/src/userinfo-password-bad-chars-novalid.html": "\u201c&\u201d did not start a character reference. (\u201c&\u201d probably should have been escaped as \u201c&amp;\u201d.)",
+ "html/elements/source/src/userinfo-password-contains-pile-of-poo-novalid.html": "Bad value \u201chttp://foo:\ud83d\udca9@example.com\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Illegal character in user or password: not a URL code point.",
+ "html/elements/source/src/userinfo-username-contains-at-sign-novalid.html": "Bad value \u201chttp://::@c@d:2\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: User or password contains an at symbol (\"@\") not percent-encoded.",
+ "html/elements/source/src/userinfo-username-contains-pile-of-poo-novalid.html": "Bad value \u201chttp://\ud83d\udca9:foo@example.com\u201d for attribute \u201csrc\u201d on element \u201csource\u201d: Bad URL: Illegal character in user or password: not a URL code point.",
+ "html/elements/span/model-novalid.html": "End tag \u201cp\u201d implied, but there were open elements.",
+ "html/elements/strong/model-novalid.html": "End tag \u201cp\u201d implied, but there were open elements.",
+ "html/elements/style/scoped-as-p-child-novalid.html": "Element \u201cstyle\u201d not allowed in this context. (The parent was element \u201cp\u201d.) Suppressing further errors from this subtree.",
+ "html/elements/style/scoped-in-head-novalid.html": "Attribute \u201cscoped\u201d not allowed on element \u201cstyle\u201d in this context.",
+ "html/elements/style/scoped-model-novalid.html": "Element \u201cstyle\u201d not allowed in this context. (The parent was element \u201cdiv\u201d.) Suppressing further errors from this subtree.",
+ "html/elements/sub/model-novalid.html": "End tag \u201cp\u201d implied, but there were open elements.",
+ "html/elements/sup/model-novalid.html": "End tag \u201cp\u201d implied, but there were open elements.",
+ "html/elements/table/model-input-child-hidden-novalid.html": "Start tag \u201cinput\u201d seen in \u201ctable\u201d.",
+ "html/elements/table/model-input-child-novalid.html": "Start tag \u201cinput\u201d seen in \u201ctable\u201d.",
+ "html/elements/table/model-input-type-child-novalid.html": "Start tag \u201cinput\u201d seen in \u201ctable\u201d.",
+ "html/elements/title/empty-novalid.html": "Element \u201ctitle\u201d must not be empty.",
+ "html/elements/title/missing-novalid.html": "Element \u201chead\u201d is missing required child element \u201ctitle\u201d.",
+ "html/elements/track/src-empty-novalid.html": "Bad value \u201c\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Must be non-empty.",
+ "html/elements/track/src-whitespace-only-novalid.html": "Bad value \u201c\t \n\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Must be non-empty.",
+ "html/elements/track/src/fragment-backslash-novalid.html": "Bad value \u201c#\\\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/track/src/fragment-contains-hash-novalid.html": "Bad value \u201chttp://foo/path#f#g\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/track/src/fragment-leading-space-novalid.html": "Bad value \u201chttp://f:21/b# e\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/track/src/host-cr-novalid.html": "Bad value \u201chttp://example.\norg\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/track/src/host-double-percent-encoded-novalid.html": "Bad value \u201chttp://\uff05\uff14\uff11.com\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/track/src/host-double-percent-encoded-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%bc%85%ef%bc%94%ef%bc%91.com\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/track/src/host-empty-novalid.html": "Bad value \u201chttp://\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/track/src/host-empty-userinfo-empty-novalid.html": "Bad value \u201chttp://@/www.example.com\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/track/src/host-empty-with-userinfo-novalid.html": "Bad value \u201chttp://user:pass@/\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/track/src/host-hostname-in-brackets-novalid.html": "Bad value \u201chttp://[www.google.com]/\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Invalid host: Illegal character.",
+ "html/elements/track/src/host-invalid-unicode-novalid.html": "Forbidden code point U+fdd0.",
+ "html/elements/track/src/host-invalid-unicode-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%b7%90zyx.com\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Invalid host: A label or domain name contains disallowed characters..",
+ "html/elements/track/src/host-newline-novalid.html": "Bad value \u201chttp://example.\norg\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/track/src/host-space-novalid.html": "Bad value \u201chttp://example .org\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Invalid host: Domain contains invalid character: .",
+ "html/elements/track/src/host-square-brackets-port-contains-colon-novalid.html": "Bad value \u201chttp://[1::2]:3:4\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Illegal character in port.",
+ "html/elements/track/src/host-tab-novalid.html": "Bad value \u201chttp://example\t.org\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/track/src/host-u0000-percent-encoded-novalid.html": "Bad value \u201chttp://\uff05\uff10\uff10.com\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/track/src/host-u0000-percent-encoded-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%bc%85%ef%bc%90%ef%bc%90.com\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/track/src/path-bare-percent-sign-novalid.html": "Bad value \u201chttp://example.com/foo%\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Percentage (\"%\") is not followed by two hexadecimal digits.",
+ "html/elements/track/src/path-contains-space-novalid.html": "Bad value \u201c/a/ /c\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/track/src/path-leading-backslash-at-sign-novalid.html": "Bad value \u201chttp://foo.com/\\@\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/track/src/path-leading-colon-backslash-novalid.html": "Bad value \u201c:\\\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/track/src/path-leading-colon-chars-backslash-novalid.html": "Bad value \u201c:foo.com\\\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/track/src/path-leading-space-novalid.html": "Bad value \u201chttp://f:21/ b\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/track/src/path-percent-encoded-malformed-novalid.html": "Bad value \u201chttp://example.com/foo/%2e%2\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Percentage (\"%\") is not followed by two hexadecimal digits.",
+ "html/elements/track/src/path-relative-square-brackets-novalid.html": "Bad value \u201c[61:24:74]:98\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/track/src/path-tab-novalid.html": "Bad value \u201chttp://example.com/foo\tbar\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/track/src/path-trailing-space-novalid.html": "Bad value \u201chttp://f:21/b ?\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/track/src/path-u0091-novalid.html": "Forbidden code point U+0091.",
+ "html/elements/track/src/port-cr-novalid.html": "Bad value \u201chttp://f:\n/c\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/track/src/port-leading-colon-bracket-colon-novalid.html": "Bad value \u201chttp://2001::1]:80\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Illegal character in port.",
+ "html/elements/track/src/port-leading-colon-novalid.html": "Bad value \u201chttp://2001::1\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Illegal character in port.",
+ "html/elements/track/src/port-leading-dash-novalid.html": "Bad value \u201chttp://foo:-80/\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Illegal character in port.",
+ "html/elements/track/src/port-multiple-letters-novalid.html": "Bad value \u201chttp://f:fifty-two/c\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Illegal character in port.",
+ "html/elements/track/src/port-newline-novalid.html": "Bad value \u201chttp://f:\n/c\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/track/src/port-single-letter-novalid.html": "Bad value \u201chttp://f:b/c\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Illegal character in port.",
+ "html/elements/track/src/port-space-novalid.html": "Bad value \u201chttp://f: /c\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Illegal character in port.",
+ "html/elements/track/src/port-tab-novalid.html": "Bad value \u201chttp://f:\t/c\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/track/src/query-leading-space-novalid.html": "Bad value \u201chttp://f:21/b? d\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Illegal character in query: not a URL code point.",
+ "html/elements/track/src/query-trailing-space-novalid.html": "Bad value \u201chttp://f:21/b?d #\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Illegal character in query: not a URL code point.",
+ "html/elements/track/src/scheme-data-contains-fragment-haswarn.html": "Bad value \u201cdata:text/html,test#test\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Fragment is not allowed for data: URIs according to RFC 2397.",
+ "html/elements/track/src/scheme-data-single-slash-novalid.html": "Bad value \u201cdata:/example.com/\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Expected a token character or a semicolon but saw \u201c/\u201d instead.",
+ "html/elements/track/src/scheme-file-backslash-novalid.html": "Bad value \u201cfile:c:\\foo\\bar.html\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/track/src/scheme-file-single-slash-c-bar-novalid.html": "Bad value \u201cfile:/C|/foo/bar\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/track/src/scheme-file-triple-slash-c-bar-novalid.html": "Bad value \u201cfile:///C|/foo/bar\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/track/src/scheme-ftp-no-slash-novalid.html": "Bad value \u201cftp:example.com/\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/track/src/scheme-ftp-single-slash-novalid.html": "Bad value \u201cftp:/example.com/\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/track/src/scheme-http-backslash-novalid.html": "Bad value \u201chttp:\\\\foo.com\\\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/track/src/scheme-http-no-slash-colon-novalid.html": "Bad value \u201chttp::@c:29\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/track/src/scheme-http-no-slash-novalid.html": "Bad value \u201chttp:foo.com\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/track/src/scheme-http-no-slash-square-bracket-novalid.html": "Bad value \u201chttp:[61:27]/:foo\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/track/src/scheme-http-single-slash-novalid.html": "Bad value \u201chttp:/example.com/\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/track/src/scheme-https-no-slash-novalid.html": "Bad value \u201chttps:example.com/\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/track/src/scheme-https-single-slash-novalid.html": "Bad value \u201chttps:/example.com/\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/track/src/scheme-javascript-no-slash-malformed-novalid.html": "Bad value \u201cjavascript:example.com/\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: syntax error",
+ "html/elements/track/src/scheme-trailing-cr-novalid.html": "Bad value \u201ca:\nfoo.com\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/track/src/scheme-trailing-newline-novalid.html": "Bad value \u201ca:\nfoo.com\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/track/src/scheme-trailing-space-novalid.html": "Bad value \u201ca: foo.com\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/track/src/scheme-trailing-tab-novalid.html": "Bad value \u201ca:\tfoo.com\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/track/src/userinfo-backslash-novalid.html": "Bad value \u201chttp://a\\b:c\\d@foo.com\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/track/src/userinfo-password-bad-chars-novalid.html": "\u201c&\u201d did not start a character reference. (\u201c&\u201d probably should have been escaped as \u201c&amp;\u201d.)",
+ "html/elements/track/src/userinfo-password-contains-pile-of-poo-novalid.html": "Bad value \u201chttp://foo:\ud83d\udca9@example.com\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Illegal character in user or password: not a URL code point.",
+ "html/elements/track/src/userinfo-username-contains-at-sign-novalid.html": "Bad value \u201chttp://::@c@d:2\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: User or password contains an at symbol (\"@\") not percent-encoded.",
+ "html/elements/track/src/userinfo-username-contains-pile-of-poo-novalid.html": "Bad value \u201chttp://\ud83d\udca9:foo@example.com\u201d for attribute \u201csrc\u201d on element \u201ctrack\u201d: Bad URL: Illegal character in user or password: not a URL code point.",
+ "html/elements/ul/model-novalid.html": "Duplicate ID \u201cid\u201d.",
+ "html/elements/var/model-novalid.html": "End tag \u201cp\u201d implied, but there were open elements.",
+ "html/elements/video/model-novalid.html": "Element \u201cp\u201d not allowed in this context. (The parent was element \u201cvideo\u201d.) Suppressing further errors from this subtree.",
+ "html/elements/video/poster-empty-novalid.html": "Bad value \u201c\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Must be non-empty.",
+ "html/elements/video/poster-whitespace-only-novalid.html": "Bad value \u201c\t \n\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Must be non-empty.",
+ "html/elements/video/poster/fragment-backslash-novalid.html": "Bad value \u201c#\\\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/video/poster/fragment-contains-hash-novalid.html": "Bad value \u201chttp://foo/path#f#g\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/video/poster/fragment-leading-space-novalid.html": "Bad value \u201chttp://f:21/b# e\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/video/poster/host-cr-novalid.html": "Bad value \u201chttp://example.\norg\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/video/poster/host-double-percent-encoded-novalid.html": "Bad value \u201chttp://\uff05\uff14\uff11.com\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/video/poster/host-double-percent-encoded-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%bc%85%ef%bc%94%ef%bc%91.com\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/video/poster/host-empty-novalid.html": "Bad value \u201chttp://\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/video/poster/host-empty-userinfo-empty-novalid.html": "Bad value \u201chttp://@/www.example.com\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/video/poster/host-empty-with-userinfo-novalid.html": "Bad value \u201chttp://user:pass@/\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/video/poster/host-hostname-in-brackets-novalid.html": "Bad value \u201chttp://[www.google.com]/\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Invalid host: Illegal character.",
+ "html/elements/video/poster/host-invalid-unicode-novalid.html": "Forbidden code point U+fdd0.",
+ "html/elements/video/poster/host-invalid-unicode-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%b7%90zyx.com\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Invalid host: A label or domain name contains disallowed characters..",
+ "html/elements/video/poster/host-newline-novalid.html": "Bad value \u201chttp://example.\norg\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/video/poster/host-space-novalid.html": "Bad value \u201chttp://example .org\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Invalid host: Domain contains invalid character: .",
+ "html/elements/video/poster/host-square-brackets-port-contains-colon-novalid.html": "Bad value \u201chttp://[1::2]:3:4\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Illegal character in port.",
+ "html/elements/video/poster/host-tab-novalid.html": "Bad value \u201chttp://example\t.org\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/video/poster/host-u0000-percent-encoded-novalid.html": "Bad value \u201chttp://\uff05\uff10\uff10.com\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/video/poster/host-u0000-percent-encoded-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%bc%85%ef%bc%90%ef%bc%90.com\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/video/poster/path-bare-percent-sign-novalid.html": "Bad value \u201chttp://example.com/foo%\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Percentage (\"%\") is not followed by two hexadecimal digits.",
+ "html/elements/video/poster/path-contains-space-novalid.html": "Bad value \u201c/a/ /c\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/video/poster/path-leading-backslash-at-sign-novalid.html": "Bad value \u201chttp://foo.com/\\@\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/video/poster/path-leading-colon-backslash-novalid.html": "Bad value \u201c:\\\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/video/poster/path-leading-colon-chars-backslash-novalid.html": "Bad value \u201c:foo.com\\\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/video/poster/path-leading-space-novalid.html": "Bad value \u201chttp://f:21/ b\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/video/poster/path-percent-encoded-malformed-novalid.html": "Bad value \u201chttp://example.com/foo/%2e%2\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Percentage (\"%\") is not followed by two hexadecimal digits.",
+ "html/elements/video/poster/path-relative-square-brackets-novalid.html": "Bad value \u201c[61:24:74]:98\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/video/poster/path-tab-novalid.html": "Bad value \u201chttp://example.com/foo\tbar\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/video/poster/path-trailing-space-novalid.html": "Bad value \u201chttp://f:21/b ?\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/video/poster/path-u0091-novalid.html": "Forbidden code point U+0091.",
+ "html/elements/video/poster/port-cr-novalid.html": "Bad value \u201chttp://f:\n/c\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/video/poster/port-leading-colon-bracket-colon-novalid.html": "Bad value \u201chttp://2001::1]:80\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Illegal character in port.",
+ "html/elements/video/poster/port-leading-colon-novalid.html": "Bad value \u201chttp://2001::1\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Illegal character in port.",
+ "html/elements/video/poster/port-leading-dash-novalid.html": "Bad value \u201chttp://foo:-80/\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Illegal character in port.",
+ "html/elements/video/poster/port-multiple-letters-novalid.html": "Bad value \u201chttp://f:fifty-two/c\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Illegal character in port.",
+ "html/elements/video/poster/port-newline-novalid.html": "Bad value \u201chttp://f:\n/c\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/video/poster/port-single-letter-novalid.html": "Bad value \u201chttp://f:b/c\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Illegal character in port.",
+ "html/elements/video/poster/port-space-novalid.html": "Bad value \u201chttp://f: /c\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Illegal character in port.",
+ "html/elements/video/poster/port-tab-novalid.html": "Bad value \u201chttp://f:\t/c\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/video/poster/query-leading-space-novalid.html": "Bad value \u201chttp://f:21/b? d\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Illegal character in query: not a URL code point.",
+ "html/elements/video/poster/query-trailing-space-novalid.html": "Bad value \u201chttp://f:21/b?d #\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Illegal character in query: not a URL code point.",
+ "html/elements/video/poster/scheme-data-contains-fragment-haswarn.html": "Bad value \u201cdata:text/html,test#test\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Fragment is not allowed for data: URIs according to RFC 2397.",
+ "html/elements/video/poster/scheme-data-single-slash-novalid.html": "Bad value \u201cdata:/example.com/\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Expected a token character or a semicolon but saw \u201c/\u201d instead.",
+ "html/elements/video/poster/scheme-file-backslash-novalid.html": "Bad value \u201cfile:c:\\foo\\bar.html\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/video/poster/scheme-file-single-slash-c-bar-novalid.html": "Bad value \u201cfile:/C|/foo/bar\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/video/poster/scheme-file-triple-slash-c-bar-novalid.html": "Bad value \u201cfile:///C|/foo/bar\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/video/poster/scheme-ftp-no-slash-novalid.html": "Bad value \u201cftp:example.com/\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/video/poster/scheme-ftp-single-slash-novalid.html": "Bad value \u201cftp:/example.com/\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/video/poster/scheme-http-backslash-novalid.html": "Bad value \u201chttp:\\\\foo.com\\\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/video/poster/scheme-http-no-slash-colon-novalid.html": "Bad value \u201chttp::@c:29\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/video/poster/scheme-http-no-slash-novalid.html": "Bad value \u201chttp:foo.com\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/video/poster/scheme-http-no-slash-square-bracket-novalid.html": "Bad value \u201chttp:[61:27]/:foo\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/video/poster/scheme-http-single-slash-novalid.html": "Bad value \u201chttp:/example.com/\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/video/poster/scheme-https-no-slash-novalid.html": "Bad value \u201chttps:example.com/\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/video/poster/scheme-https-single-slash-novalid.html": "Bad value \u201chttps:/example.com/\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/video/poster/scheme-javascript-no-slash-malformed-novalid.html": "Bad value \u201cjavascript:example.com/\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: syntax error",
+ "html/elements/video/poster/scheme-trailing-cr-novalid.html": "Bad value \u201ca:\nfoo.com\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/video/poster/scheme-trailing-newline-novalid.html": "Bad value \u201ca:\nfoo.com\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/video/poster/scheme-trailing-space-novalid.html": "Bad value \u201ca: foo.com\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/video/poster/scheme-trailing-tab-novalid.html": "Bad value \u201ca:\tfoo.com\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/video/poster/userinfo-backslash-novalid.html": "Bad value \u201chttp://a\\b:c\\d@foo.com\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/video/poster/userinfo-password-bad-chars-novalid.html": "\u201c&\u201d did not start a character reference. (\u201c&\u201d probably should have been escaped as \u201c&amp;\u201d.)",
+ "html/elements/video/poster/userinfo-password-contains-pile-of-poo-novalid.html": "Bad value \u201chttp://foo:\ud83d\udca9@example.com\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Illegal character in user or password: not a URL code point.",
+ "html/elements/video/poster/userinfo-username-contains-at-sign-novalid.html": "Bad value \u201chttp://::@c@d:2\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: User or password contains an at symbol (\"@\") not percent-encoded.",
+ "html/elements/video/poster/userinfo-username-contains-pile-of-poo-novalid.html": "Bad value \u201chttp://\ud83d\udca9:foo@example.com\u201d for attribute \u201cposter\u201d on element \u201cvideo\u201d: Bad URL: Illegal character in user or password: not a URL code point.",
+ "html/elements/video/src/fragment-backslash-novalid.html": "Bad value \u201c#\\\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/video/src/fragment-contains-hash-novalid.html": "Bad value \u201chttp://foo/path#f#g\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/video/src/fragment-leading-space-novalid.html": "Bad value \u201chttp://f:21/b# e\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/elements/video/src/host-cr-novalid.html": "Bad value \u201chttp://example.\norg\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/video/src/host-double-percent-encoded-novalid.html": "Bad value \u201chttp://\uff05\uff14\uff11.com\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/video/src/host-double-percent-encoded-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%bc%85%ef%bc%94%ef%bc%91.com\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/video/src/host-empty-novalid.html": "Bad value \u201chttp://\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/video/src/host-empty-userinfo-empty-novalid.html": "Bad value \u201chttp://@/www.example.com\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/video/src/host-empty-with-userinfo-novalid.html": "Bad value \u201chttp://user:pass@/\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Invalid host: empty host.",
+ "html/elements/video/src/host-hostname-in-brackets-novalid.html": "Bad value \u201chttp://[www.google.com]/\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Invalid host: Illegal character.",
+ "html/elements/video/src/host-invalid-unicode-novalid.html": "Forbidden code point U+fdd0.",
+ "html/elements/video/src/host-invalid-unicode-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%b7%90zyx.com\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Invalid host: A label or domain name contains disallowed characters..",
+ "html/elements/video/src/host-newline-novalid.html": "Bad value \u201chttp://example.\norg\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/video/src/host-space-novalid.html": "Bad value \u201chttp://example .org\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Invalid host: Domain contains invalid character: .",
+ "html/elements/video/src/host-square-brackets-port-contains-colon-novalid.html": "Bad value \u201chttp://[1::2]:3:4\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Illegal character in port.",
+ "html/elements/video/src/host-tab-novalid.html": "Bad value \u201chttp://example\t.org\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/video/src/host-u0000-percent-encoded-novalid.html": "Bad value \u201chttp://\uff05\uff10\uff10.com\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/video/src/host-u0000-percent-encoded-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%bc%85%ef%bc%90%ef%bc%90.com\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/elements/video/src/path-bare-percent-sign-novalid.html": "Bad value \u201chttp://example.com/foo%\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Percentage (\"%\") is not followed by two hexadecimal digits.",
+ "html/elements/video/src/path-contains-space-novalid.html": "Bad value \u201c/a/ /c\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/video/src/path-leading-backslash-at-sign-novalid.html": "Bad value \u201chttp://foo.com/\\@\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/video/src/path-leading-colon-backslash-novalid.html": "Bad value \u201c:\\\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/video/src/path-leading-colon-chars-backslash-novalid.html": "Bad value \u201c:foo.com\\\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/video/src/path-leading-space-novalid.html": "Bad value \u201chttp://f:21/ b\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/video/src/path-percent-encoded-malformed-novalid.html": "Bad value \u201chttp://example.com/foo/%2e%2\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Percentage (\"%\") is not followed by two hexadecimal digits.",
+ "html/elements/video/src/path-relative-square-brackets-novalid.html": "Bad value \u201c[61:24:74]:98\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/video/src/path-tab-novalid.html": "Bad value \u201chttp://example.com/foo\tbar\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/video/src/path-trailing-space-novalid.html": "Bad value \u201chttp://f:21/b ?\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/video/src/path-u0091-novalid.html": "Forbidden code point U+0091.",
+ "html/elements/video/src/port-cr-novalid.html": "Bad value \u201chttp://f:\n/c\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/video/src/port-leading-colon-bracket-colon-novalid.html": "Bad value \u201chttp://2001::1]:80\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Illegal character in port.",
+ "html/elements/video/src/port-leading-colon-novalid.html": "Bad value \u201chttp://2001::1\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Illegal character in port.",
+ "html/elements/video/src/port-leading-dash-novalid.html": "Bad value \u201chttp://foo:-80/\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Illegal character in port.",
+ "html/elements/video/src/port-multiple-letters-novalid.html": "Bad value \u201chttp://f:fifty-two/c\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Illegal character in port.",
+ "html/elements/video/src/port-newline-novalid.html": "Bad value \u201chttp://f:\n/c\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/video/src/port-single-letter-novalid.html": "Bad value \u201chttp://f:b/c\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Illegal character in port.",
+ "html/elements/video/src/port-space-novalid.html": "Bad value \u201chttp://f: /c\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Illegal character in port.",
+ "html/elements/video/src/port-tab-novalid.html": "Bad value \u201chttp://f:\t/c\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/elements/video/src/query-leading-space-novalid.html": "Bad value \u201chttp://f:21/b? d\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Illegal character in query: not a URL code point.",
+ "html/elements/video/src/query-trailing-space-novalid.html": "Bad value \u201chttp://f:21/b?d #\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Illegal character in query: not a URL code point.",
+ "html/elements/video/src/scheme-data-contains-fragment-haswarn.html": "Bad value \u201cdata:text/html,test#test\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Fragment is not allowed for data: URIs according to RFC 2397.",
+ "html/elements/video/src/scheme-data-single-slash-novalid.html": "Bad value \u201cdata:/example.com/\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Expected a token character or a semicolon but saw \u201c/\u201d instead.",
+ "html/elements/video/src/scheme-file-backslash-novalid.html": "Bad value \u201cfile:c:\\foo\\bar.html\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/video/src/scheme-file-single-slash-c-bar-novalid.html": "Bad value \u201cfile:/C|/foo/bar\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/video/src/scheme-file-triple-slash-c-bar-novalid.html": "Bad value \u201cfile:///C|/foo/bar\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/elements/video/src/scheme-ftp-no-slash-novalid.html": "Bad value \u201cftp:example.com/\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/video/src/scheme-ftp-single-slash-novalid.html": "Bad value \u201cftp:/example.com/\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/video/src/scheme-http-backslash-novalid.html": "Bad value \u201chttp:\\\\foo.com\\\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/video/src/scheme-http-no-slash-colon-novalid.html": "Bad value \u201chttp::@c:29\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/video/src/scheme-http-no-slash-novalid.html": "Bad value \u201chttp:foo.com\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/video/src/scheme-http-no-slash-square-bracket-novalid.html": "Bad value \u201chttp:[61:27]/:foo\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/video/src/scheme-http-single-slash-novalid.html": "Bad value \u201chttp:/example.com/\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/video/src/scheme-https-no-slash-novalid.html": "Bad value \u201chttps:example.com/\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/video/src/scheme-https-single-slash-novalid.html": "Bad value \u201chttps:/example.com/\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/elements/video/src/scheme-javascript-no-slash-malformed-novalid.html": "Bad value \u201cjavascript:example.com/\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: syntax error",
+ "html/elements/video/src/scheme-trailing-cr-novalid.html": "Bad value \u201ca:\nfoo.com\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/video/src/scheme-trailing-newline-novalid.html": "Bad value \u201ca:\nfoo.com\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/video/src/scheme-trailing-space-novalid.html": "Bad value \u201ca: foo.com\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/video/src/scheme-trailing-tab-novalid.html": "Bad value \u201ca:\tfoo.com\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/elements/video/src/userinfo-backslash-novalid.html": "Bad value \u201chttp://a\\b:c\\d@foo.com\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/elements/video/src/userinfo-password-bad-chars-novalid.html": "\u201c&\u201d did not start a character reference. (\u201c&\u201d probably should have been escaped as \u201c&amp;\u201d.)",
+ "html/elements/video/src/userinfo-password-contains-pile-of-poo-novalid.html": "Bad value \u201chttp://foo:\ud83d\udca9@example.com\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Illegal character in user or password: not a URL code point.",
+ "html/elements/video/src/userinfo-username-contains-at-sign-novalid.html": "Bad value \u201chttp://::@c@d:2\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: User or password contains an at symbol (\"@\") not percent-encoded.",
+ "html/elements/video/src/userinfo-username-contains-pile-of-poo-novalid.html": "Bad value \u201chttp://\ud83d\udca9:foo@example.com\u201d for attribute \u201csrc\u201d on element \u201cvideo\u201d: Bad URL: Illegal character in user or password: not a URL code point.",
+ "html/media-queries/001-novalid.html": "Bad value \u201cscreen and\u201d for attribute \u201cmedia\u201d on element \u201clink\u201d: Bad media query: Media query ended prematurely.",
+ "html/media-queries/002-novalid.html": "Bad value \u201calla\u201d for attribute \u201cmedia\u201d on element \u201clink\u201d: Bad media query: Expected a CSS media type but the query ended.",
+ "html/media-queries/003-novalid.html": "Bad value \u201cPROJECT\u0130ON\u201d for attribute \u201cmedia\u201d on element \u201clink\u201d: Bad media query: Expected a letter, hyphen or whitespace but saw \u201c\u0130\u201d instead.",
+ "html/media-queries/004-novalid.html": "Bad value \u201cnotscreen\u201d for attribute \u201cmedia\u201d on element \u201clink\u201d: Bad media query: Media query ended prematurely.",
+ "html/media-queries/005-novalid.html": "Bad value \u201conlyscreen\u201d for attribute \u201cmedia\u201d on element \u201clink\u201d: Bad media query: Media query ended prematurely.",
+ "html/media-queries/006-novalid.html": "Bad value \u201cscreenand (min-width: 400px)\u201d for attribute \u201cmedia\u201d on element \u201clink\u201d: Bad media query: Expected a CSS media type but saw \u201cscreenand\u201d instead.",
+ "html/media-queries/007-novalid.html": "Bad value \u201cscreen and(min-width: 400px)\u201d for attribute \u201cmedia\u201d on element \u201clink\u201d: Bad media query: Expected a letter or whitespace but saw \u201c(\u201d instead.",
+ "html/media-queries/008-novalid.html": "Bad value \u201cscreen and (min-width: 400px;)\u201d for attribute \u201cmedia\u201d on element \u201clink\u201d: Bad media query: Expected a letter, a dot or a digit but saw \u201c;\u201d instead.",
+ "html/media-queries/009-novalid.html": "Bad value \u201cscreen and (min-width: 400uu)\u201d for attribute \u201cmedia\u201d on element \u201clink\u201d: Bad media query: Expected a length unit but saw \u201c)\u201d instead.",
+ "html/media-queries/010-novalid.html": "Bad value \u201cscreen and (min-width: 400)\u201d for attribute \u201cmedia\u201d on element \u201clink\u201d: Bad media query: Non-zero lengths require a unit.",
+ "html/media-queries/011-novalid.html": "Bad value \u201cscreen and (min-width: 400dpi)\u201d for attribute \u201cmedia\u201d on element \u201clink\u201d: Bad media query: Expected a length unit but saw \u201c)\u201d instead.",
+ "html/media-queries/012-novalid.html": "Bad value \u201cscreen and (min-width: 400px)and (max-width: 600px)\u201d for attribute \u201cmedia\u201d on element \u201clink\u201d: Bad media query: Expected whitespace but saw \u201ca\u201d instead.",
+ "html/media-queries/013-novalid.html": "Bad value \u201cscreen and (min-width:\u201d for attribute \u201cmedia\u201d on element \u201clink\u201d: Bad media query: Media query ended prematurely.",
+ "html/media-queries/014-novalid.html": "Bad value \u201cscreen and (min-width: 400px) and\u201d for attribute \u201cmedia\u201d on element \u201clink\u201d: Bad media query: Media query ended prematurely.",
+ "html/media-queries/015-novalid.html": "Bad value \u201ctv and (scan: 1)\u201d for attribute \u201cmedia\u201d on element \u201clink\u201d: Bad media query: Expected a letter but saw \u201c1\u201d instead.",
+ "html/media-queries/016-novalid.html": "Bad value \u201ctv and (scan: \u0130NTERLACE)\u201d for attribute \u201cmedia\u201d on element \u201clink\u201d: Bad media query: Expected a letter but saw \u201c\u0130\u201d instead.",
+ "html/media-queries/017-novalid.html": "Bad value \u201cscreen and (device-aspect-ratio: 16px/9pt)\u201d for attribute \u201cmedia\u201d on element \u201clink\u201d: Bad media query: Expected a digit, whitespace or \u201c/\u201d for device-aspect-ratio value but saw \u201cp\u201d instead.",
+ "html/media-queries/018-haswarn.html": "This document is not mappable to XML 1.0 without data loss due to U+000c which is not a legal XML 1.0 character.",
+ "html/media-queries/019-novalid.html": "Bad value \u201cscreen and (color: 1em)\u201d for attribute \u201cmedia\u201d on element \u201clink\u201d: Bad media query: Expected a digit, whitespace or \u201c)\u201d but saw \u201ce\u201d instead.",
+ "html/media-queries/020-novalid.html": "Bad value \u201c,\u201d for attribute \u201cmedia\u201d on element \u201clink\u201d: Bad media query: Media query ended prematurely.",
+ "html/media-queries/021-novalid.html": "Bad value \u201cscreen,,print\u201d for attribute \u201cmedia\u201d on element \u201clink\u201d: Bad media query: Media query ended prematurely.",
+ "html/media-queries/022-novalid.html": "Bad value \u201cscreen,\u201d for attribute \u201cmedia\u201d on element \u201clink\u201d: Bad media query: Media query ended prematurely.",
+ "html/media-queries/023-novalid.html": "Bad value \u201c,screen\u201d for attribute \u201cmedia\u201d on element \u201clink\u201d: Bad media query: Media query ended prematurely.",
+ "html/media-queries/024-novalid.html": "Bad value \u201cscreen and (min-width: 400)\u201d for attribute \u201cmedia\u201d on element \u201clink\u201d: Bad media query: Non-zero lengths require a unit.",
+ "html/microdata/itemid-scheme-data-contains-fragment-haswarn.html": "Bad value \u201cdata:text/html,test#test\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Fragment is not allowed for data: URIs according to RFC 2397.",
+ "html/microdata/itemid/fragment-backslash-novalid.html": "Bad value \u201c#\\\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/microdata/itemid/fragment-contains-hash-novalid.html": "Bad value \u201chttp://foo/path#f#g\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/microdata/itemid/fragment-leading-space-novalid.html": "Bad value \u201chttp://f:21/b# e\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Illegal character in fragment: not a URL code point.",
+ "html/microdata/itemid/host-cr-novalid.html": "Bad value \u201chttp://example.\norg\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/microdata/itemid/host-double-percent-encoded-novalid.html": "Bad value \u201chttp://\uff05\uff14\uff11.com\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/microdata/itemid/host-double-percent-encoded-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%bc%85%ef%bc%94%ef%bc%91.com\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/microdata/itemid/host-empty-novalid.html": "Bad value \u201chttp://\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Invalid host: empty host.",
+ "html/microdata/itemid/host-empty-userinfo-empty-novalid.html": "Bad value \u201chttp://@/www.example.com\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Invalid host: empty host.",
+ "html/microdata/itemid/host-empty-with-userinfo-novalid.html": "Bad value \u201chttp://user:pass@/\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Invalid host: empty host.",
+ "html/microdata/itemid/host-hostname-in-brackets-novalid.html": "Bad value \u201chttp://[www.google.com]/\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Invalid host: Illegal character.",
+ "html/microdata/itemid/host-invalid-unicode-novalid.html": "Forbidden code point U+fdd0.",
+ "html/microdata/itemid/host-invalid-unicode-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%b7%90zyx.com\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Invalid host: A label or domain name contains disallowed characters..",
+ "html/microdata/itemid/host-newline-novalid.html": "Bad value \u201chttp://example.\norg\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/microdata/itemid/host-space-novalid.html": "Bad value \u201chttp://example .org\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Invalid host: Domain contains invalid character: .",
+ "html/microdata/itemid/host-square-brackets-port-contains-colon-novalid.html": "Bad value \u201chttp://[1::2]:3:4\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Illegal character in port.",
+ "html/microdata/itemid/host-tab-novalid.html": "Bad value \u201chttp://example\t.org\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/microdata/itemid/host-u0000-percent-encoded-novalid.html": "Bad value \u201chttp://\uff05\uff10\uff10.com\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/microdata/itemid/host-u0000-percent-encoded-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%bc%85%ef%bc%90%ef%bc%90.com\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Invalid host: Domain contains invalid character: %.",
+ "html/microdata/itemid/path-bare-percent-sign-novalid.html": "Bad value \u201chttp://example.com/foo%\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Percentage (\"%\") is not followed by two hexadecimal digits.",
+ "html/microdata/itemid/path-contains-space-novalid.html": "Bad value \u201c/a/ /c\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/microdata/itemid/path-leading-backslash-at-sign-novalid.html": "Bad value \u201chttp://foo.com/\\@\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/microdata/itemid/path-leading-colon-backslash-novalid.html": "Bad value \u201c:\\\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/microdata/itemid/path-leading-colon-chars-backslash-novalid.html": "Bad value \u201c:foo.com\\\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/microdata/itemid/path-leading-space-novalid.html": "Bad value \u201chttp://f:21/ b\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/microdata/itemid/path-percent-encoded-malformed-novalid.html": "Bad value \u201chttp://example.com/foo/%2e%2\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Percentage (\"%\") is not followed by two hexadecimal digits.",
+ "html/microdata/itemid/path-relative-square-brackets-novalid.html": "Bad value \u201c[61:24:74]:98\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/microdata/itemid/path-tab-novalid.html": "Bad value \u201chttp://example.com/foo\tbar\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/microdata/itemid/path-trailing-space-novalid.html": "Bad value \u201chttp://f:21/b ?\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/microdata/itemid/path-u0091-novalid.html": "Forbidden code point U+0091.",
+ "html/microdata/itemid/port-cr-novalid.html": "Bad value \u201chttp://f:\n/c\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/microdata/itemid/port-leading-colon-bracket-colon-novalid.html": "Bad value \u201chttp://2001::1]:80\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Illegal character in port.",
+ "html/microdata/itemid/port-leading-colon-novalid.html": "Bad value \u201chttp://2001::1\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Illegal character in port.",
+ "html/microdata/itemid/port-leading-dash-novalid.html": "Bad value \u201chttp://foo:-80/\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Illegal character in port.",
+ "html/microdata/itemid/port-multiple-letters-novalid.html": "Bad value \u201chttp://f:fifty-two/c\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Illegal character in port.",
+ "html/microdata/itemid/port-newline-novalid.html": "Bad value \u201chttp://f:\n/c\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/microdata/itemid/port-single-letter-novalid.html": "Bad value \u201chttp://f:b/c\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Illegal character in port.",
+ "html/microdata/itemid/port-space-novalid.html": "Bad value \u201chttp://f: /c\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Illegal character in port.",
+ "html/microdata/itemid/port-tab-novalid.html": "Bad value \u201chttp://f:\t/c\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Tab, new line or carriage return found.",
+ "html/microdata/itemid/query-leading-space-novalid.html": "Bad value \u201chttp://f:21/b? d\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Illegal character in query: not a URL code point.",
+ "html/microdata/itemid/query-trailing-space-novalid.html": "Bad value \u201chttp://f:21/b?d #\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Illegal character in query: not a URL code point.",
+ "html/microdata/itemid/scheme-data-single-slash-novalid.html": "Bad value \u201cdata:/example.com/\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Expected a token character or a semicolon but saw \u201c/\u201d instead.",
+ "html/microdata/itemid/scheme-file-backslash-novalid.html": "Bad value \u201cfile:c:\\foo\\bar.html\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/microdata/itemid/scheme-file-single-slash-c-bar-novalid.html": "Bad value \u201cfile:/C|/foo/bar\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/microdata/itemid/scheme-file-triple-slash-c-bar-novalid.html": "Bad value \u201cfile:///C|/foo/bar\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Illegal character in path segment: not a URL code point.",
+ "html/microdata/itemid/scheme-ftp-no-slash-novalid.html": "Bad value \u201cftp:example.com/\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/microdata/itemid/scheme-ftp-single-slash-novalid.html": "Bad value \u201cftp:/example.com/\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/microdata/itemid/scheme-http-backslash-novalid.html": "Bad value \u201chttp:\\\\foo.com\\\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/microdata/itemid/scheme-http-no-slash-colon-novalid.html": "Bad value \u201chttp::@c:29\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/microdata/itemid/scheme-http-no-slash-novalid.html": "Bad value \u201chttp:foo.com\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/microdata/itemid/scheme-http-no-slash-square-bracket-novalid.html": "Bad value \u201chttp:[61:27]/:foo\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/microdata/itemid/scheme-http-single-slash-novalid.html": "Bad value \u201chttp:/example.com/\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/microdata/itemid/scheme-https-no-slash-novalid.html": "Bad value \u201chttps:example.com/\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/microdata/itemid/scheme-https-single-slash-novalid.html": "Bad value \u201chttps:/example.com/\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Expected a slash (\"/\").",
+ "html/microdata/itemid/scheme-javascript-no-slash-malformed-novalid.html": "Bad value \u201cjavascript:example.com/\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: syntax error",
+ "html/microdata/itemid/scheme-trailing-cr-novalid.html": "Bad value \u201ca:\nfoo.com\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/microdata/itemid/scheme-trailing-newline-novalid.html": "Bad value \u201ca:\nfoo.com\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/microdata/itemid/scheme-trailing-space-novalid.html": "Bad value \u201ca: foo.com\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/microdata/itemid/scheme-trailing-tab-novalid.html": "Bad value \u201ca:\tfoo.com\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Illegal character in scheme data: not a URL code point.",
+ "html/microdata/itemid/userinfo-backslash-novalid.html": "Bad value \u201chttp://a\\b:c\\d@foo.com\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/microdata/itemid/userinfo-password-bad-chars-novalid.html": "\u201c&\u201d did not start a character reference. (\u201c&\u201d probably should have been escaped as \u201c&amp;\u201d.)",
+ "html/microdata/itemid/userinfo-password-contains-pile-of-poo-novalid.html": "Bad value \u201chttp://foo:\ud83d\udca9@example.com\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Illegal character in user or password: not a URL code point.",
+ "html/microdata/itemid/userinfo-username-contains-at-sign-novalid.html": "Bad value \u201chttp://::@c@d:2\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: User or password contains an at symbol (\"@\") not percent-encoded.",
+ "html/microdata/itemid/userinfo-username-contains-pile-of-poo-novalid.html": "Bad value \u201chttp://\ud83d\udca9:foo@example.com\u201d for attribute \u201citemid\u201d on element \u201cdiv\u201d: Bad URL: Illegal character in user or password: not a URL code point.",
+ "html/microdata/itemtype-empty-novalid.html": "Bad value \u201c\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d.",
+ "html/microdata/itemtype-scheme-data-contains-fragment-haswarn.html": "Bad value \u201cdata:text/html,test#test\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: Fragment is not allowed for data: URIs according to RFC 2397.",
+ "html/microdata/itemtype/fragment-backslash-novalid.html": "Bad value \u201c#\\\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: The string \u201c#\\\u201d is not an absolute URL.",
+ "html/microdata/itemtype/fragment-contains-hash-novalid.html": "Bad value \u201chttp://foo/path#f#g\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: Illegal character in fragment: not a URL code point.",
+ "html/microdata/itemtype/fragment-empty-hash-only-no-path-relative-novalid.html": "Bad value \u201c#\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: The string \u201c#\u201d is not an absolute URL.",
+ "html/microdata/itemtype/fragment-leading-space-novalid.html": "Bad value \u201chttp://f:21/b# e\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: The string \u201ce\u201d is not an absolute URL.",
+ "html/microdata/itemtype/fragment-non-ascii-relative-novalid.html": "Bad value \u201c#\u03b2\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: The string \u201c#\u03b2\u201d is not an absolute URL.",
+ "html/microdata/itemtype/fragment-semicolon-question-mark-relative-novalid.html": "Bad value \u201c#;?\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: The string \u201c#;?\u201d is not an absolute URL.",
+ "html/microdata/itemtype/fragment-slash-relative-novalid.html": "Bad value \u201c#/\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: The string \u201c#/\u201d is not an absolute URL.",
+ "html/microdata/itemtype/host-cr-novalid.html": "Bad value \u201chttp://example.\norg\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: The string \u201corg\u201d is not an absolute URL.",
+ "html/microdata/itemtype/host-double-percent-encoded-novalid.html": "Bad value \u201chttp://\uff05\uff14\uff11.com\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: Invalid host: Domain contains invalid character: %.",
+ "html/microdata/itemtype/host-double-percent-encoded-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%bc%85%ef%bc%94%ef%bc%91.com\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: Invalid host: Domain contains invalid character: %.",
+ "html/microdata/itemtype/host-empty-novalid.html": "Bad value \u201chttp://\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: Invalid host: empty host.",
+ "html/microdata/itemtype/host-empty-userinfo-empty-novalid.html": "Bad value \u201chttp://@/www.example.com\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: Invalid host: empty host.",
+ "html/microdata/itemtype/host-empty-with-userinfo-novalid.html": "Bad value \u201chttp://user:pass@/\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: Invalid host: empty host.",
+ "html/microdata/itemtype/host-hostname-in-brackets-novalid.html": "Bad value \u201chttp://[www.google.com]/\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: Invalid host: Illegal character.",
+ "html/microdata/itemtype/host-invalid-unicode-novalid.html": "Forbidden code point U+fdd0.",
+ "html/microdata/itemtype/host-invalid-unicode-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%b7%90zyx.com\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: Invalid host: A label or domain name contains disallowed characters..",
+ "html/microdata/itemtype/host-newline-novalid.html": "Bad value \u201chttp://example.\norg\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: The string \u201corg\u201d is not an absolute URL.",
+ "html/microdata/itemtype/host-space-novalid.html": "Bad value \u201chttp://example .org\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: The string \u201c.org\u201d is not an absolute URL.",
+ "html/microdata/itemtype/host-square-brackets-port-contains-colon-novalid.html": "Bad value \u201chttp://[1::2]:3:4\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: Illegal character in port.",
+ "html/microdata/itemtype/host-tab-novalid.html": "Bad value \u201chttp://example\t.org\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: The string \u201c.org\u201d is not an absolute URL.",
+ "html/microdata/itemtype/host-u0000-percent-encoded-novalid.html": "Bad value \u201chttp://\uff05\uff10\uff10.com\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: Invalid host: Domain contains invalid character: %.",
+ "html/microdata/itemtype/host-u0000-percent-encoded-percent-encoded-novalid.html": "Bad value \u201chttp://%ef%bc%85%ef%bc%90%ef%bc%90.com\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: Invalid host: Domain contains invalid character: %.",
+ "html/microdata/itemtype/path-bare-percent-sign-novalid.html": "Bad value \u201chttp://example.com/foo%\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: Percentage (\"%\") is not followed by two hexadecimal digits.",
+ "html/microdata/itemtype/path-contains-space-novalid.html": "Bad value \u201c/a/ /c\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: The string \u201c/a/\u201d is not an absolute URL.",
+ "html/microdata/itemtype/path-leading-backslash-at-sign-novalid.html": "Bad value \u201chttp://foo.com/\\@\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/microdata/itemtype/path-leading-colon-backslash-novalid.html": "Bad value \u201c:\\\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: The string \u201c:\\\u201d is not an absolute URL.",
+ "html/microdata/itemtype/path-leading-colon-chars-backslash-novalid.html": "Bad value \u201c:foo.com\\\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: The string \u201c:foo.com\\\u201d is not an absolute URL.",
+ "html/microdata/itemtype/path-leading-space-novalid.html": "Bad value \u201chttp://f:21/ b\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: The string \u201cb\u201d is not an absolute URL.",
+ "html/microdata/itemtype/path-percent-encoded-malformed-novalid.html": "Bad value \u201chttp://example.com/foo/%2e%2\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: Percentage (\"%\") is not followed by two hexadecimal digits.",
+ "html/microdata/itemtype/path-percent-encoded-slash-plus-slashes-relative-novalid.html": "Bad value \u201c/a/%2f/c\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: The string \u201c/a/%2f/c\u201d is not an absolute URL.",
+ "html/microdata/itemtype/path-percent-encoded-slash-relative-novalid.html": "Bad value \u201c/a%2fc\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: The string \u201c/a%2fc\u201d is not an absolute URL.",
+ "html/microdata/itemtype/path-relative-square-brackets-novalid.html": "Bad value \u201c[61:24:74]:98\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: The string \u201c[61:24:74]:98\u201d is not an absolute URL.",
+ "html/microdata/itemtype/path-simple-relative-novalid.html": "Bad value \u201c/a/b/c\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: The string \u201c/a/b/c\u201d is not an absolute URL.",
+ "html/microdata/itemtype/path-slash-only-relative-novalid.html": "Bad value \u201c/\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: The string \u201c/\u201d is not an absolute URL.",
+ "html/microdata/itemtype/path-tab-novalid.html": "Bad value \u201chttp://example.com/foo\tbar\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: The string \u201cbar\u201d is not an absolute URL.",
+ "html/microdata/itemtype/path-trailing-space-novalid.html": "Bad value \u201chttp://f:21/b ?\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: The string \u201c?\u201d is not an absolute URL.",
+ "html/microdata/itemtype/path-u0091-novalid.html": "Forbidden code point U+0091.",
+ "html/microdata/itemtype/port-cr-novalid.html": "Bad value \u201chttp://f:\n/c\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: The string \u201c/c\u201d is not an absolute URL.",
+ "html/microdata/itemtype/port-leading-colon-bracket-colon-novalid.html": "Bad value \u201chttp://2001::1]:80\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: Illegal character in port.",
+ "html/microdata/itemtype/port-leading-colon-novalid.html": "Bad value \u201chttp://2001::1\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: Illegal character in port.",
+ "html/microdata/itemtype/port-leading-dash-novalid.html": "Bad value \u201chttp://foo:-80/\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: Illegal character in port.",
+ "html/microdata/itemtype/port-multiple-letters-novalid.html": "Bad value \u201chttp://f:fifty-two/c\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: Illegal character in port.",
+ "html/microdata/itemtype/port-newline-novalid.html": "Bad value \u201chttp://f:\n/c\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: The string \u201c/c\u201d is not an absolute URL.",
+ "html/microdata/itemtype/port-single-letter-novalid.html": "Bad value \u201chttp://f:b/c\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: Illegal character in port.",
+ "html/microdata/itemtype/port-space-novalid.html": "Bad value \u201chttp://f: /c\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: The string \u201c/c\u201d is not an absolute URL.",
+ "html/microdata/itemtype/port-tab-novalid.html": "Bad value \u201chttp://f:\t/c\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: The string \u201c/c\u201d is not an absolute URL.",
+ "html/microdata/itemtype/query-empty-no-path-relative-novalid.html": "Bad value \u201c?\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: The string \u201c?\u201d is not an absolute URL.",
+ "html/microdata/itemtype/query-leading-space-novalid.html": "Bad value \u201chttp://f:21/b? d\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: The string \u201cd\u201d is not an absolute URL.",
+ "html/microdata/itemtype/query-trailing-space-novalid.html": "Bad value \u201chttp://f:21/b?d #\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: The string \u201c#\u201d is not an absolute URL.",
+ "html/microdata/itemtype/scheme-data-single-slash-novalid.html": "Bad value \u201cdata:/example.com/\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: Expected a token character or a semicolon but saw \u201c/\u201d instead.",
+ "html/microdata/itemtype/scheme-ftp-no-slash-novalid.html": "Bad value \u201cftp:example.com/\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: Expected a slash (\"/\").",
+ "html/microdata/itemtype/scheme-ftp-single-slash-novalid.html": "Bad value \u201cftp:/example.com/\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: Expected a slash (\"/\").",
+ "html/microdata/itemtype/scheme-http-backslash-novalid.html": "Bad value \u201chttp:\\\\foo.com\\\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: Expected a slash (\"/\").",
+ "html/microdata/itemtype/scheme-http-no-slash-colon-novalid.html": "Bad value \u201chttp::@c:29\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: Expected a slash (\"/\").",
+ "html/microdata/itemtype/scheme-http-no-slash-novalid.html": "Bad value \u201chttp:foo.com\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: Expected a slash (\"/\").",
+ "html/microdata/itemtype/scheme-http-no-slash-square-bracket-novalid.html": "Bad value \u201chttp:[61:27]/:foo\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: Expected a slash (\"/\").",
+ "html/microdata/itemtype/scheme-http-single-slash-novalid.html": "Bad value \u201chttp:/example.com/\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: Expected a slash (\"/\").",
+ "html/microdata/itemtype/scheme-https-no-slash-novalid.html": "Bad value \u201chttps:example.com/\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: Expected a slash (\"/\").",
+ "html/microdata/itemtype/scheme-https-single-slash-novalid.html": "Bad value \u201chttps:/example.com/\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: Expected a slash (\"/\").",
+ "html/microdata/itemtype/scheme-javascript-no-slash-malformed-novalid.html": "Bad value \u201cjavascript:example.com/\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: syntax error",
+ "html/microdata/itemtype/scheme-schemeless-relative-novalid.html": "Bad value \u201c//foo/bar\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: The string \u201c//foo/bar\u201d is not an absolute URL.",
+ "html/microdata/itemtype/scheme-trailing-cr-novalid.html": "Bad value \u201ca:\nfoo.com\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: The string \u201cfoo.com\u201d is not an absolute URL.",
+ "html/microdata/itemtype/scheme-trailing-newline-novalid.html": "Bad value \u201ca:\nfoo.com\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: The string \u201cfoo.com\u201d is not an absolute URL.",
+ "html/microdata/itemtype/scheme-trailing-space-novalid.html": "Bad value \u201ca: foo.com\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: The string \u201cfoo.com\u201d is not an absolute URL.",
+ "html/microdata/itemtype/scheme-trailing-tab-novalid.html": "Bad value \u201ca:\tfoo.com\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: The string \u201cfoo.com\u201d is not an absolute URL.",
+ "html/microdata/itemtype/userinfo-backslash-novalid.html": "Bad value \u201chttp://a\\b:c\\d@foo.com\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: Backslash (\"\\\") used as path segment delimiter.",
+ "html/microdata/itemtype/userinfo-password-bad-chars-novalid.html": "\u201c&\u201d did not start a character reference. (\u201c&\u201d probably should have been escaped as \u201c&amp;\u201d.)",
+ "html/microdata/itemtype/userinfo-password-contains-pile-of-poo-novalid.html": "Bad value \u201chttp://foo:\ud83d\udca9@example.com\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: Illegal character in user or password: not a URL code point.",
+ "html/microdata/itemtype/userinfo-username-contains-at-sign-novalid.html": "Bad value \u201chttp://::@c@d:2\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: User or password contains an at symbol (\"@\") not percent-encoded.",
+ "html/microdata/itemtype/userinfo-username-contains-pile-of-poo-novalid.html": "Bad value \u201chttp://\ud83d\udca9:foo@example.com\u201d for attribute \u201citemtype\u201d on element \u201cdiv\u201d: Bad absolute URL: Illegal character in user or password: not a URL code point.",
+ "html/mime-types/001-novalid.html": "Bad value \u201ctext/html \u201d for attribute \u201ctype\u201d on element \u201clink\u201d: Bad MIME type: Extraneous trailing whitespace.",
+ "html/mime-types/002-novalid.html": "Bad value \u201c TEXT/HTML\u201d for attribute \u201ctype\u201d on element \u201clink\u201d: Bad MIME type: Expected a token character but saw \u201c \u201d instead.",
+ "html/mime-types/003-novalid.html": "Bad value \u201ctext/html;charset=\u201d for attribute \u201ctype\u201d on element \u201clink\u201d: Bad MIME type: Parameter value missing.",
+ "html/mime-types/004-novalid.html": "Bad value \u201ctext/html ;charset\u201d for attribute \u201ctype\u201d on element \u201clink\u201d: Bad MIME type: Parameter value missing.",
+ "html/mime-types/005-novalid.html": "Bad value \u201ctext/html;\u201d for attribute \u201ctype\u201d on element \u201clink\u201d: Bad MIME type: Semicolon seen but there was no parameter following it.",
+ "html/mime-types/006-novalid.html": "Bad value \u201ctext/html; \u201d for attribute \u201ctype\u201d on element \u201clink\u201d: Bad MIME type: Semicolon seen but there was no parameter following it.",
+ "html/mime-types/007-novalid.html": "Bad value \u201ctext/html ;\u201d for attribute \u201ctype\u201d on element \u201clink\u201d: Bad MIME type: Semicolon seen but there was no parameter following it.",
+ "html/mime-types/008-novalid.html": "Bad value \u201ctext/html;charset=\"utf-8\u201d for attribute \u201ctype\u201d on element \u201clink\u201d: Bad MIME type: Unfinished quoted string.",
+ "html/mime-types/009-novalid.html": "Bad value \u201ctext/html;charset=\"u\\\u201d for attribute \u201ctype\u201d on element \u201clink\u201d: Bad MIME type: Unfinished quoted string.",
+ "html/mime-types/010-novalid.html": "Bad value \u201capplication\u201d for attribute \u201ctype\u201d on element \u201clink\u201d: Bad MIME type: Subtype missing.",
+ "html/mime-types/011-novalid.html": "Bad value \u201capplication/\u201d for attribute \u201ctype\u201d on element \u201clink\u201d: Bad MIME type: Subtype missing.",
+ "html/obsolete/acronym-novalid.html": "The \u201cacronym\u201d element is obsolete. Use the \u201cabbr\u201d element instead.",
+ "html/obsolete/applet-novalid.html": "Element \u201capplet\u201d is missing required attribute \u201ccode\u201d.",
+ "html/obsolete/basefont-novalid.html": "The \u201cbasefont\u201d element is obsolete. Use CSS instead.",
+ "html/obsolete/big-novalid.html": "The \u201cbig\u201d element is obsolete. Use CSS instead.",
+ "html/obsolete/center-novalid.html": "The \u201ccenter\u201d element is obsolete. Use CSS instead.",
+ "html/obsolete/dir-novalid.html": "The \u201cdir\u201d element is obsolete. Use the \u201cul\u201d element instead.",
+ "html/obsolete/font-novalid.html": "The \u201cfont\u201d element is obsolete. Use CSS instead.",
+ "html/obsolete/frameset-novalid.html": "The \u201cframeset\u201d element is obsolete. Use the \u201ciframe\u201d element and CSS instead, or use server-side includes.",
+ "html/obsolete/noframes-novalid.html": "The \u201cnoframes\u201d element is obsolete. Use the \u201ciframe\u201d element and CSS instead, or use server-side includes.",
+ "html/obsolete/profile-novalid.html": "The \u201cprofile\u201d attribute on the \u201chead\u201d element is obsolete. To declare which \u201cmeta\u201d terms are used in the document, instead register the names as meta extensions. To trigger specific UA behaviors, use a \u201clink\u201d element instead.",
+ "html/obsolete/strike-novalid.html": "The \u201cstrike\u201d element is obsolete. Use CSS instead.",
+ "html/obsolete/tt-novalid.html": "The \u201ctt\u201d element is obsolete. Use CSS instead.",
+ "html/other/applet-novalid.html": "The \u201capplet\u201d element is obsolete. Use the \u201cobject\u201d element instead.",
+ "html/other/obj-novalid.html": "Element \u201cobj\u201d not allowed in this context. (The parent was element \u201cp\u201d.) Suppressing further errors from this subtree.",
+ "html/parser/cr-charref-novalid.html": "A numeric character reference expanded to carriage return.",
+ "html/parser/range-charref-novalid.html": "Character reference outside the permissible Unicode range.",
+ "html/parser/u000b-charref-novalid.html": "Character reference expands to a control character (U+000b).",
+ "html/parser/u000b-novalid.html": "Forbidden code point U+000b.",
+ "html/parser/u007f-charref-novalid.html": "Character reference expands to a control character (U+007f).",
+ "html/parser/u10ffff-charref-novalid.html": "Character reference expands to an astral non-character (U+10ffff).",
+ "html/parser/ufffe-charref-novalid.html": "Character reference expands to a non-character (U+fffe).",
+ "html/parser/unassigned-charref-novalid.html": "Character reference expands to a permanently unassigned code point.",
+ "xhtml/attributes/accesskey/003-novalid.xhtml": "Bad value \u201ca b \u306c c \u306c\u201d for attribute \u201caccesskey\u201d on element \u201ca\u201d: Bad key label list: Duplicate key label. Each key label must be unique.",
+ "xhtml/attributes/accesskey/004-novalid.xhtml": "Bad value \u201ca b \u307b\u3052\u201d for attribute \u201caccesskey\u201d on element \u201ca\u201d: Bad key label list: Key label has multiple characters. Each key label must be a single character.",
+ "xhtml/attributes/data/002-novalid.xhtml": "\u201cdata-*\u201d attributes must not have characters from the range \u201cA\u201d\u2026\u201cZ\u201d in the name.",
+ "xhtml/attributes/spellcheck/050-novalid.xhtml": "Bad value \u201cbadvalue\u201d for attribute \u201cspellcheck\u201d on element \u201cp\u201d.",
+ "xhtml/attributes/spellcheck/350-novalid.xhtml": "Bad value \u201cbadvalue\u201d for attribute \u201cspellcheck\u201d on element \u201cp\u201d.",
+ "xhtml/elements/a/100-novalid.xhtml": "Bad value \u201c\u201d for attribute \u201cname\u201d on element \u201ca\u201d: Bad id: An ID must not be the empty string.",
+ "xhtml/elements/base/001-novalid.xhtml": "Element \u201cbase\u201d is missing one or more of the following attributes: [href, target].",
+ "xhtml/elements/dialog/001-novalid.xhtml": "Element \u201cdt\u201d not allowed in this context. (The parent was element \u201cdialog\u201d.) Suppressing further errors from this subtree.",
+ "xhtml/elements/embed/001-novalid.xhtml": "Bad value \u201c20%\u201d for attribute \u201cheight\u201d on element \u201cembed\u201d: Bad non-negative integer: Expected a digit but saw \u201c%\u201d instead.",
+ "xhtml/elements/embed/002-novalid.xhtml": "Bad value \u201cfoo\u201d for attribute \u201ctype\u201d on element \u201cembed\u201d: Bad MIME type: Subtype missing.",
+ "xhtml/elements/embed/003-novalid.xhtml": "Bad value \u201c20%\u201d for attribute \u201cwidth\u201d on element \u201cembed\u201d: Bad non-negative integer: Expected a digit but saw \u201c%\u201d instead.",
+ "xhtml/elements/figure/002-novalid.xhtml": "Text not allowed in element \u201cfigure\u201d in this context.",
+ "xhtml/elements/figure/101-novalid.xhtml": "Element \u201cimg\u201d not allowed in this context. (The parent was element \u201cfigure\u201d.) Suppressing further errors from this subtree.",
+ "xhtml/elements/figure/102-novalid.xhtml": "Text not allowed in element \u201cfigure\u201d in this context.",
+ "xhtml/elements/figure/103-novalid.xhtml": "Text not allowed in element \u201cfigure\u201d in this context.",
+ "xhtml/elements/figure/104-novalid.xhtml": "Element \u201cimg\u201d not allowed in this context. (The parent was element \u201cfigure\u201d.) Suppressing further errors from this subtree.",
+ "xhtml/elements/figure/304-novalid.xhtml": "Element \u201cimg\u201d not allowed in this context. (The parent was element \u201cfigure\u201d.) Suppressing further errors from this subtree.",
+ "xhtml/elements/footer/001-novalid.xhtml": "The element \u201cfooter\u201d must not appear as a descendant of the \u201cfooter\u201d element.",
+ "xhtml/elements/footer/003-novalid.xhtml": "The element \u201cheader\u201d must not appear as a descendant of the \u201cfooter\u201d element.",
+ "xhtml/elements/header/001-novalid.xhtml": "The element \u201cfooter\u201d must not appear as a descendant of the \u201cheader\u201d element.",
+ "xhtml/elements/header/002-novalid.xhtml": "The element \u201cheader\u201d must not appear as a descendant of the \u201cheader\u201d element.",
+ "xhtml/elements/iframe/042-novalid.xhtml": "Text not allowed in element \u201ciframe\u201d in this context.",
+ "xhtml/elements/img/003-novalid.xhtml": "The \u201cimg\u201d element with the \u201cismap\u201d attribute set must have an \u201ca\u201d ancestor with the \u201chref\u201d attribute.",
+ "xhtml/elements/img/004-novalid.xhtml": "The element \u201cimg\u201d with the attribute \u201cusemap\u201d must not appear as a descendant of the \u201ca\u201d element.",
+ "xhtml/elements/img/051-novalid.xhtml": "Bad value \u201c-1\u201d for attribute \u201cwidth\u201d on element \u201cimg\u201d: Bad non-negative integer: Expected a digit but saw \u201c-\u201d instead.",
+ "xhtml/elements/input/003-novalid.xhtml": "The \u201clist\u201d attribute of the \u201cinput\u201d element must refer to a \u201cdatalist\u201d element.",
+ "xhtml/elements/keygen/054-novalid.xhtml": "Text not allowed in element \u201ckeygen\u201d in this context.",
+ "xhtml/elements/keygen/056-novalid.xhtml": "Bad value \u201cdsa\u201d for attribute \u201ckeytype\u201d on element \u201ckeygen\u201d.",
+ "xhtml/elements/keygen/057-novalid.xhtml": "Bad value \u201c\u201d for attribute \u201ckeytype\u201d on element \u201ckeygen\u201d.",
+ "xhtml/elements/keygen/058-novalid.xhtml": "Any \u201ckeygen\u201d descendant of a \u201clabel\u201d element with a \u201cfor\u201d attribute must have an ID value that matches that \u201cfor\u201d attribute.",
+ "xhtml/elements/keygen/059-novalid.xhtml": "Any \u201ckeygen\u201d descendant of a \u201clabel\u201d element with a \u201cfor\u201d attribute must have an ID value that matches that \u201cfor\u201d attribute.",
+ "xhtml/elements/keygen/060-novalid.xhtml": "The \u201clabel\u201d element may contain at most one \u201cinput\u201d, \u201cbutton\u201d, \u201cselect\u201d, \u201ctextarea\u201d, or \u201ckeygen\u201d descendant.",
+ "xhtml/elements/keygen/061-novalid.xhtml": "The element \u201ckeygen\u201d must not appear as a descendant of the \u201ca\u201d element.",
+ "xhtml/elements/keygen/154-novalid.xhtml": "Text not allowed in element \u201ckeygen\u201d in this context.",
+ "xhtml/elements/keygen/157-novalid.xhtml": "Bad value \u201c\u201d for attribute \u201ckeytype\u201d on element \u201ckeygen\u201d.",
+ "xhtml/elements/keygen/359-novalid.xhtml": "Any \u201ckeygen\u201d descendant of a \u201clabel\u201d element with a \u201cfor\u201d attribute must have an ID value that matches that \u201cfor\u201d attribute.",
+ "xhtml/elements/keygen/360-novalid.xhtml": "The \u201clabel\u201d element may contain at most one \u201cinput\u201d, \u201cbutton\u201d, \u201cselect\u201d, \u201ctextarea\u201d, or \u201ckeygen\u201d descendant.",
+ "xhtml/elements/keygen/361-novalid.xhtml": "The element \u201ckeygen\u201d must not appear as a descendant of the \u201ca\u201d element.",
+ "xhtml/elements/link/001-novalid.xhtml": "Element \u201clink\u201d is missing required attribute \u201chref\u201d.",
+ "xhtml/elements/menu/001-haswarn.xhtml": "The \u201cmenu\u201d element is not supported by browsers yet. It would probably be better to wait for implementations.",
+ "xhtml/elements/menu/001-novalid.xhtml": "The \u201ccontextmenu\u201d attribute must refer to a \u201cmenu\u201d element.",
+ "xhtml/elements/meter/010-novalid.xhtml": "The value of the \u201cmin\u201d attribute must be less than or equal to the value of the \u201cvalue\u201d attribute.",
+ "xhtml/elements/meter/011-novalid.xhtml": "Element \u201cmeter\u201d is missing required attribute \u201cvalue\u201d.",
+ "xhtml/elements/meter/012-novalid.xhtml": "Element \u201cmeter\u201d is missing required attribute \u201cvalue\u201d.",
+ "xhtml/elements/meter/110-novalid.xhtml": "The value of the \u201cmin\u201d attribute must be less than or equal to the value of the \u201cvalue\u201d attribute.",
+ "xhtml/elements/meter/312-novalid.xhtml": "Element \u201cmeter\u201d is missing required attribute \u201cvalue\u201d.",
+ "xhtml/elements/object/001-novalid.xhtml": "Element \u201cobject\u201d is missing one or more of the following attributes: [data, type].",
+ "xhtml/elements/progress/008-novalid.xhtml": "The value of the \u201cvalue\u201d attribute must be less than or equal to one when the \u201cmax\u201d attribute is absent.",
+ "xhtml/elements/progress/009-novalid.xhtml": "The value of the \u201cvalue\u201d attribute must be less than or equal to the value of the \u201cmax\u201d attribute.",
+ "xhtml/elements/progress/108-novalid.xhtml": "The value of the \u201cvalue\u201d attribute must be less than or equal to one when the \u201cmax\u201d attribute is absent.",
+ "xhtml/elements/progress/309-novalid.xhtml": "The value of the \u201cvalue\u201d attribute must be less than or equal to the value of the \u201cmax\u201d attribute.",
+ "xhtml/elements/ruby/001-novalid.xhtml": "Element \u201cruby\u201d is missing one or more of the following child elements: [rp, rt].",
+ "xhtml/elements/ruby/002-novalid.xhtml": "Element \u201cruby\u201d is missing required child element \u201crt\u201d.",
+ "xhtml/elements/script/001-novalid.xhtml": "The \u201clanguage\u201d attribute on the \u201cscript\u201d element is obsolete. Use the \u201ctype\u201d attribute instead.",
+ "xhtml/elements/table/201-novalid.xhtml": "Table cell spans past the end of its row group established by a \u201ctbody\u201d element; clipped to the end of the row group.",
+ "xhtml/elements/table/202-novalid.xhtml": "Table cell is overlapped by later table cell.",
+ "xhtml/elements/table/203-novalid.xhtml": "Table column 3 established by element \u201ctd\u201d has no cells beginning in it.",
+ "xhtml/elements/table/204-novalid.xhtml": "Row 3 of an implicit row group has no cells beginning on it.",
+ "xhtml/elements/table/205-novalid.xhtml": "Element \u201ccol\u201d not allowed in this context. (The parent was element \u201ctable\u201d.) Suppressing further errors from this subtree.",
+ "xhtml/other/045-novalid.xhtml": "The \u201capplet\u201d element is obsolete. Use the \u201cobject\u201d element instead."
+}
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/tools/ins-del-datetime.py b/tests/wpt/web-platform-tests/conformance-checkers/tools/ins-del-datetime.py
new file mode 100644
index 00000000000..3767a7d709f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/tools/ins-del-datetime.py
@@ -0,0 +1,176 @@
+# -*- coding: utf-8 -*-
+import os
+ccdir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+template = """<!DOCTYPE html>
+<meta charset=utf-8>
+"""
+errors = {
+ "date-year-0000": "0000-12-09",
+ "date-month-00": "2002-00-15",
+ "date-month-13": "2002-13-15",
+ "date-0005-02-29": "0005-02-29",
+ "date-1969-02-29": "1969-02-29",
+ "date-1900-02-29": "1900-02-29",
+ "date-2100-02-29": "2100-02-29",
+ "date-2200-02-29": "2200-02-29",
+ "date-2014-02-29": "2014-02-29",
+ "date-day-04-31": "2002-04-31",
+ "date-day-06-31": "2002-06-31",
+ "date-day-09-31": "2002-09-31",
+ "date-day-11-31": "2002-11-31",
+ "date-day-01-32": "2002-01-32",
+ "date-day-03-32": "2002-03-32",
+ "date-day-05-32": "2002-05-32",
+ "date-day-07-32": "2002-07-32",
+ "date-day-08-32": "2002-08-32",
+ "date-day-10-32": "2002-10-32",
+ "date-day-12-32": "2002-12-32",
+ "date-iso8601-YYYYMMDD-no-hyphen": "20020929",
+ "date-leading-whitespace": " 2002-09-29",
+ "date-trailing-whitespace": "2002-09-29 ",
+ "date-month-one-digit": "2002-9-29",
+ "date-month-three-digits": "2002-011-29",
+ "date-year-three-digits": "782-09-29",
+ "date-day-one-digit": "2002-09-9",
+ "date-day-three-digits": "2002-11-009",
+ "date-day-missing-separator": "2014-0220",
+ "date-month-missing-separator": "201402-20",
+ "date-non-ascii-digit": "2002-09-29",
+ "date-trailing-U+0000": "2002-09-29&#x0000;",
+ "date-trailing-pile-of-poo": "2002-09-29💩",
+ "date-wrong-day-separator": "2014-02:20",
+ "date-wrong-month-separator": "2014:02-20",
+ "date-year-negative": "-2002-09-29",
+ "date-leading-bom": "2002-09-29",
+ "global-date-and-time-60-minutes": "2011-11-12T00:60:00+08:00",
+ "global-date-and-time-60-seconds": "2011-11-12T00:00:60+08:00",
+ "global-date-and-time-2400": "2011-11-12T24:00:00+08:00",
+ "global-date-and-time-space-before-timezone": "2011-11-12T06:54:39 08:00",
+ "global-date-and-time-hour-one-digit": "2011-11-12T6:54:39-08:00",
+ "global-date-and-time-hour-three-digits": "2011-11-12T016:54:39-08:00",
+ "global-date-and-time-minutes-one-digit": "2011-11-12T16:4:39-08:00",
+ "global-date-and-time-minutes-three-digits": "2011-11-12T16:354:39-08:00",
+ "global-date-and-time-seconds-one-digit": "2011-11-12T16:54:9-08:00",
+ "global-date-and-time-seconds-three-digits": "2011-11-12T16:54:039-08:00",
+ "global-date-and-time-timezone-with-seconds": "2011-11-12T06:54:39-08:00:00",
+ "global-date-and-time-timezone-60-minutes": "2011-11-12T06:54:39-08:60",
+ "global-date-and-time-timezone-one-digit-hour": "2011-11-12T06:54:39-5:00",
+ "global-date-and-time-timezone-one-digit-minute": "2011-11-12T06:54:39-05:0",
+ "global-date-and-time-timezone-three-digit-hour": "2011-11-12T06:54:39-005:00",
+ "global-date-and-time-timezone-three-digit-minute": "2011-11-12T06:54:39-05:000",
+ "global-date-and-time-nbsp": "2011-11-12 14:54Z",
+ "global-date-and-time-missing-minutes-separator": "2011-11-12T1454Z",
+ "global-date-and-time-missing-seconds-separator": "2011-11-12T14:5439Z",
+ "global-date-and-time-wrong-minutes-separator": "2011-11-12T14-54Z",
+ "global-date-and-time-wrong-seconds-separator": "2011-11-12T14:54-39Z",
+ "global-date-and-time-lowercase-z": "2011-11-12T14:54z",
+ "global-date-and-time-with-both-T-and-space": "2011-11-12T 14:54Z",
+ "global-date-and-time-zero-digit-fraction": "2011-11-12T06:54:39.-08:00",
+ "global-date-and-time-four-digit-fraction": "2011-11-12T06:54:39.9291-08:00",
+ "global-date-and-time-bad-fraction-separator": "2011-11-12T14:54:39,929+0000",
+ "global-date-and-time-timezone-non-T-character": "2011-11-12+14:54Z",
+ "global-date-and-time-timezone-lowercase-t": "2011-11-12t14:54Z",
+ "global-date-and-time-timezone-multiple-spaces": "2011-11-12 14:54Z",
+ "global-date-and-time-timezone-offset-space-start": "2011-11-12T06:54:39.929 08:00",
+ "global-date-and-time-timezone-offset-colon-start": "2011-11-12T06:54:39.929:08:00",
+ "global-date-and-time-timezone-plus-2400": "2011-11-12T06:54:39-24:00",
+ "global-date-and-time-timezone-minus-2400": "2011-11-12T06:54:39-24:00",
+ "global-date-and-time-timezone-iso8601-two-digit": "2011-11-12T06:54:39-08",
+ "global-date-and-time-iso8601-hhmmss-no-colon": "2011-11-12T145439Z",
+ "global-date-and-time-iso8601-hhmm-no-colon": "2011-11-12T1454Z",
+ "global-date-and-time-iso8601-hh": "2011-11-12T14Z",
+ "year": "2006",
+ "yearless-date": "07-15",
+ "month": "2011-11",
+ "week": "2011-W46",
+ "time": "14:54:39",
+ "local-date-and-time": "2011-11-12T14:54",
+ "duration-P-form": "PT4H18M3S",
+ "duration-time-component": "4h 18m 3s",
+}
+
+warnings = {
+ "global-date-and-time-timezone-plus-1500": "2011-11-12T00:00:00+1500",
+ "global-date-and-time-timezone-minus-1300": "2011-11-12T00:00:00-1300",
+ "global-date-and-time-timezone-minutes-15": "2011-11-12T00:00:00+08:15",
+ "date-0214-09-29": "0214-09-29",
+ "date-20014-09-29": "20014-09-29",
+ "date-0004-02-29": "0004-02-29",
+ "date-year-five-digits": "12014-09-29",
+}
+
+non_errors = {
+ "date": "2002-09-29",
+ "date-2000-02-29": "2000-02-29",
+ "date-2400-02-29": "2400-02-29",
+ "date-1968-02-29": "1968-02-29",
+ "date-1900-02-28": "1900-02-28",
+ "date-2100-02-28": "2100-02-28",
+ "date-2100-02-28": "2100-02-28",
+ "date-2200-02-28": "2200-02-28",
+ "date-2014-02-28": "2014-02-28",
+ "date-day-01-31": "2002-01-31",
+ "date-day-03-31": "2002-03-31",
+ "date-day-05-31": "2002-05-31",
+ "date-day-07-31": "2002-07-31",
+ "date-day-08-31": "2002-08-31",
+ "date-day-10-31": "2002-10-31",
+ "date-day-12-31": "2002-12-31",
+ "date-day-04-30": "2002-04-30",
+ "date-day-06-30": "2002-06-30",
+ "date-day-09-30": "2002-09-30",
+ "date-day-11-30": "2002-11-30",
+ "global-date-and-time-no-seconds": "2011-11-12T14:54Z",
+ "global-date-and-time-with-seconds": "2011-11-12T14:54:39+0000",
+ "global-date-and-time-with-one-digit-fraction": "2011-11-12T06:54:39.9-08:00",
+ "global-date-and-time-with-two-digit-fraction": "2011-11-12T06:54:39.92+07:00",
+ "global-date-and-time-with-three-digit-fraction": "2011-11-12T06:54:39.929-06:00",
+ "global-date-and-time-space": "2011-11-12 14:54Z",
+ "global-date-and-time-timezone": "2011-11-12T06:54:39+0900",
+ "global-date-and-time-timezone-30": "2011-11-12T06:54:39-0830",
+ "global-date-and-time-timezone-45": "2011-11-12T06:54:39-0845",
+ "global-date-and-time-timezone-with-colon": "2011-11-12T06:54:39-08:00",
+ "global-date-and-time-timezone-without-colon": "2011-11-12T06:54:39-0800",
+}
+
+for key in errors.keys():
+ error = errors[key]
+ template_ins = template
+ template_del = template
+ template_ins += '<title>%s</title>\n' % key
+ template_del += '<title>%s</title>\n' % key
+ template_ins += '<ins datetime="%s"></ins>' % errors[key]
+ template_del += '<del datetime="%s"></del>' % errors[key]
+ ins_file = open(os.path.join(ccdir, "html/elements/ins/%s-novalid.html" % key), 'wb')
+ ins_file.write(template_ins)
+ ins_file.close()
+ del_file = open(os.path.join(ccdir, "html/elements/del/%s-novalid.html" % key), 'wb')
+ del_file.write(template_del)
+ del_file.close()
+
+for key in warnings.keys():
+ non_error = warnings[key]
+ template_ins = template
+ template_del = template
+ template_ins += '<title>%s</title>\n' % key
+ template_del += '<title>%s</title>\n' % key
+ template_ins += '<ins datetime="%s"></ins>' % warnings[key]
+ template_del += '<del datetime="%s"></del>' % warnings[key]
+ ins_file = open(os.path.join(ccdir, "html/elements/ins/%s-haswarn.html" % key), 'wb')
+ ins_file.write(template_ins)
+ ins_file.close()
+ del_file = open(os.path.join(ccdir, "html/elements/del/%s-haswarn.html" % key), 'wb')
+ del_file.write(template_del)
+ del_file.close()
+
+ins_file = open(os.path.join(ccdir, "html/elements/ins/datetime-isvalid.html"), 'wb')
+del_file = open(os.path.join(ccdir, "html/elements/del/datetime-isvalid.html"), 'wb')
+ins_file.write(template + '<title>valid datetime</title>\n')
+del_file.write(template + '<title>valid datetime</title>\n')
+for key in non_errors.keys():
+ non_error = non_errors[key]
+ ins_file.write('<ins datetime="%s"></ins> <!-- %s -->\n' % (non_errors[key], key))
+ del_file.write('<del datetime="%s"></del> <!-- %s -->\n' % (non_errors[key], key))
+ins_file.close()
+del_file.close()
+# vim: ts=4:sw=4
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/tools/picture.py b/tests/wpt/web-platform-tests/conformance-checkers/tools/picture.py
new file mode 100644
index 00000000000..5b03f67ac98
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/tools/picture.py
@@ -0,0 +1,364 @@
+# -*- coding: utf-8 -*-
+import os
+ccdir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+template = """<!DOCTYPE html>
+<meta charset=utf-8>
+"""
+
+errors = {
+ # missing src on img
+ "img-no-src": "<img alt>",
+ "img-no-src-with-srcset": "<img srcset=x alt>",
+ "img-no-src-with-picture": "<picture><img alt></picture>",
+ "img-no-src-with-srcset-and-picture": "<picture><img srcset=x alt></picture>",
+ "img-no-src-with-source": "<picture><source srcset=x><img alt></picture>",
+ # junk content in picture
+ "junk-text-before-img": "<picture>x<img src=x alt></picture>",
+ "junk-text-after-img": "<picture><img src=x alt>x</picture>",
+ "junk-text-before-source": "<picture>x<source srcset=x><img src=x alt></picture>",
+ "junk-text-after-source": "<picture><source srcset=x>x<img src=x alt></picture>",
+ "junk-br-before-img": "<picture><br><img src=x alt></picture>",
+ "junk-br-after-img": "<picture><img src=x alt><br></picture>",
+ "junk-br-before-source": "<picture><br><source srcset=x><img src=x alt></picture>",
+ "junk-br-after-source": "<picture><source srcset=x><br><img src=x alt></picture>",
+ "junk-video-before": "<picture><video></video><source srcset=x><img src=x alt></picture>",
+ "junk-video-no-img": "<picture><video></video></picture>",
+ "junk-p-before": "<picture><p></p><source srcset=x><img src=x alt></picture>",
+ "junk-p-after": "<picture><source srcset=x><img src=x alt><p></p></picture>",
+ "junk-p-wrapping": "<picture><p><source srcset=x><img src=x alt></p></picture>",
+ "junk-span-before": "<picture><span></span><source srcset=x><img src=x alt></picture>",
+ "junk-span-after": "<picture><source srcset=x><img src=x alt><span></span></picture>",
+ "junk-span-wrapping": "<picture><span><source srcset=x><img src=x alt></span></picture>",
+ "junk-picture-before": "<picture><picture><img src=x alt></picture><img src=x alt></picture>",
+ "junk-picture-wrapping": "<picture><picture><img src=x alt></picture></picture>",
+ "junk-figure-wrapping": "<picture><figure><img src=x alt></figure></picture>",
+ "junk-input-type-hidden": "<picture><input type=hidden name=x value=x><img src=x alt></picture>",
+ "junk-style-scroped": "<picture><style scroped></style><img src=x alt></picture>",
+ "junk-noscript": "<picture><img src=x alt><noscript></noscript></picture>",
+ "junk-noscript-after-source-no-img": "<picture><source srcset=x><noscript><img src=x alt></noscript></picture>",
+ "junk-svg": "<picture><img src=x alt><svg></svg></picture>",
+ "junk-svg-no-img": "<picture><svg></svg></picture>",
+ "junk-math-nog-img": "<picture><math></math></picture>",
+ # parents
+ "parent-ul": "<ul><picture><img src=x alt></picture></ul>",
+ "parent-dl": "<dl><picture><img src=x alt></picture></dl>",
+ "parent-hgroup": "<hgroup><h1>x</h1><picture><img src=x alt></picture></hgroup>",
+ "parent-noscript-in-head": "<noscript><picture><img src=x alt></picture></noscript>",
+ # invalid html syntax
+ "html-syntax-source-end-tag": "<picture><source srcset=x></source><img src=x alt></picture>",
+ "html-syntax-img-end-tag": "<picture><img src=x alt></img></picture>",
+ "html-syntax-picture-no-end-tag": "<picture><img src=x alt>",
+ "html-syntax-picture-slash": "<picture/><img src=x alt></picture>",
+ "html-syntax-picture-slash-no-end-tag": "<picture/><img src=x alt>",
+ # missing img in picture
+ "missing-img-empty-picture": "<picture></picture>",
+ "missing-img-only-source": "<picture><source srcset=x></picture>",
+ "missing-img-only-script": "<picture><script></script></picture>",
+ "missing-img-script-and-source": "<picture><script></script><source srcset=x></picture>",
+ "missing-img-source-and-script": "<picture><source srcset=x><script></script></picture>",
+ # multiple img in picture
+ "multiple-img": "<picture><img src=x alt><img src=x alt></picture>",
+ "multiple-img-with-script": "<picture><img src=x alt><script></script><img src=x alt></picture>",
+ "multiple-img-with-source": "<picture><source srcset=x><img src=x alt><img src=x alt></picture>",
+ "multiple-img-with-source-and-script": "<picture><source srcset=x><img src=x alt><script></script><img src=x alt></picture>",
+ # source after img
+ "source-after-img": "<picture><img src=x alt><source srcset=x></picture>",
+ "source-before-and-after-img": "<picture><source srcset=x><img src=x alt><source srcset=x></picture>",
+ # source with following sibling source element or img element with a srcset attribute
+ "always-matching-source-with-following-img-srcset": "<picture><source srcset=x><img src=x srcset=x alt></picture>",
+ "always-matching-source-with-following-source-srcset": "<picture><source srcset=x><source srcset=x><img src=x alt></picture>",
+ "always-matching-source-with-following-source-media": "<picture><source srcset=x><source srcset=x media=screen><img src=x alt></picture>",
+ "always-matching-source-with-following-source-type": "<picture><source srcset=x><source srcset=x type=image/gif><img src=x alt></picture>",
+ "always-matching-source-media-empty-with-following-source-srcset": "<picture><source srcset=x media><source srcset=x><img src=x alt></picture>",
+ "always-matching-source-media-spaces-with-following-source-srcset": "<picture><source srcset=x media=' \n\t'><source srcset=x><img src=x alt></picture>",
+ "always-matching-source-media-all-with-following-source-srcset": "<picture><source srcset=x media=all><source srcset=x><img src=x alt></picture>",
+ "always-matching-source-media-uppercase-with-following-source-srcset": "<picture><source srcset=x media=ALL><source srcset=x><img src=x alt></picture>",
+ "always-matching-source-media-all-spaces-with-following-source-srcset": "<picture><source srcset=x media=' all '><source srcset=x><img src=x alt></picture>",
+ "always-matching-source-sizes-with-following-source-srcset": "<picture><source srcset='x 100w' sizes=50vw><source srcset=x><img src=x alt></picture>",
+ # sizes present
+ "img-srcset-no-descriptor-with-sizes": "<img src=x srcset='x' sizes=50vw alt>",
+ "img-srcset-w-and-x-width-sizes": "<img src=x srcset='x 100w, y 2x' sizes=50vw alt>",
+ "source-srcset-x-with-sizes": "<picture><source srcset='x 1x, y 2x' sizes=50vw><img src=x alt></picture>",
+ "source-srcset-h-with-sizes": "<picture><source srcset='x 100h, y 200h' sizes=50vw><img src=x alt></picture>",
+ "source-srcset-w-and-x-with-sizes": "<picture><source srcset='x 100w, y 2x' sizes=50vw><img src=x alt></picture>",
+ "img-with-sizes-no-srcset": "<img sizes=50vw src=foo alt>",
+ # width descriptor without sizes
+ "img-srcset-w-no-sizes": "<img srcset='x 100w, y 200w' src=x alt>",
+ "source-srcset-w-no-sizes": "<picture><source srcset='x 100w, y 200w'><img src=x alt></picture>",
+ "source-type-srcset-w": "<picture><source srcset='x 100w, y 200w' type=image/gif><img src=x alt></picture>",
+ # invalid attributes on source
+ "source-src": "<picture><source src=x><img src=x alt></picture>",
+ "source-src-srcset": "<picture><source src=x srcset=x><img src=x alt></picture>",
+ "source-alt": "<picture><source srcset=x alt><img src=x alt></picture>",
+ "source-width": "<picture><source srcset=x width=100><img src=x alt></picture>",
+ "source-height": "<picture><source srcset=x height=100><img src=x alt></picture>",
+ "source-usemap": "<picture><source srcset=x usemap><img src=x alt></picture>",
+ "source-ismap": "<picture><source srcset=x ismap><img src=x alt></picture>",
+ "source-crossorigin": "<picture><source srcset=x crossorigin><img src=x alt></picture>",
+ "source-name": "<picture><source srcset=x crossorigin><img src=x alt></picture>",
+ "source-align": "<picture><source srcset=x align=left><img src=x alt></picture>",
+ "source-hspace": "<picture><source srcset=x hspace=1><img src=x alt></picture>",
+ "source-vspace": "<picture><source srcset=x vspace=1><img src=x alt></picture>",
+ "source-longdesc": "<picture><source srcset=x longdesc=x><img src=x alt></picture>",
+ "source-border": "<picture><source srcset=x border=1><img src=x alt></picture>",
+ # missing srcset on source
+ "source-no-srcset": "<picture><source><img src=x alt></picture>",
+ "source-no-srcset-with-sizes": "<picture><source sizes=50vw><img src=x alt></picture>",
+ "source-no-srcset-with-media": "<picture><source media=screen><img src=x alt></picture>",
+ "source-no-srcset-with-type": "<picture><source type='image/webp'><img src=x alt></picture>",
+ # invalid attributes on picture
+ "picture-src": "<picture src=x><img src=x alt></picture>",
+ "picture-srcset": "<picture srcset=x><img src=x alt></picture>",
+ "picture-media": "<picture media=screen><img src=x alt></picture>",
+ "picture-sizes": "<picture sizes=50vw><img src=x alt></picture>",
+ "picture-alt": "<picture alt><img src=x alt></picture>",
+ "picture-width": "<picture width=100><img src=x alt></picture>",
+ "picture-height": "<picture height=100><img src=x alt></picture>",
+ "picture-usemap": "<picture usemap><img src=x alt></picture>",
+ "picture-ismap": "<picture ismap><img src=x alt></picture>",
+ "picture-crossorigin": "<picture crossorigin><img src=x alt></picture>",
+ "picture-name": "<picture name=x><img src=x alt></picture>",
+ "picture-lowsrc": "<picture lowsrc=x><img src=x alt></picture>",
+ "picture-align": "<picture align=left><img src=x alt></picture>",
+ "picture-hspace": "<picture hspace=1><img src=x alt></picture>",
+ "picture-vspace": "<picture vspace=1><img src=x alt></picture>",
+ "picture-longdesc": "<picture longdesc=x><img src=x alt></picture>",
+ "picture-border": "<picture border=1><img src=x alt></picture>",
+ # invalid attributes on source in video
+ "video-source-srcset": "<video><source srcset=x></video>",
+ "video-source-srcset-src": "<video><source srcset=x src=x></video>",
+ "video-source-sizes-srcset": "<video><source sizes=50vw srcset='x 100w'></video>",
+ "video-source-media-src": "<video><source media=screen src=x></video>",
+ # srcset on other elements
+ "link-rel-icon-srcset": "<link rel=icon srcset=x href=x>",
+ "input-type-image-srcset": "<input type=image src=x srcset=x alt=x>",
+ "object-srcset": "<object data=x srcset=x></object>",
+ "video-srcset": "<video src=x srcset=x></video>",
+ "audio-srcset": "<audio src=x srcset=x></audio>",
+ "track-srcset": "<video src=x><track src=x srcset=x></video>",
+ "svg-image-srcset": "<svg><image xlink:href=x srcset=x width=1 height=1 /></svg>",
+ # invalid attributes on img
+ "img-type": "<img src=x type=image/gif alt>",
+ "img-type-with-picture": "<picture><img src=x type=image/gif alt></picture>",
+ # sizes microsyntax
+ "sizes-microsyntax-media-all": "<img sizes='all 500px, 100vw' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-media-all-and-min-width": "<img sizes='all and (min-width:500px) 500px, 100vw' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-media-min-width-no-parenthesis": "<img sizes='min-width:500px 500px, 100vw' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-media-general-enclosed-junk": "<img sizes='(123) 500px, 100vw' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-media-bad-junk": "<img sizes='(}) 500px, 100vw' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-two-defaults": "<img sizes='500px, 100vw' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-default-first": "<img sizes='100vw, (min-width:500px) 500px' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-trailing-comma": "<img sizes='(min-width:500px) 500px, 100vw,' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-trailing-junk": "<img sizes='(min-width:500px) 500px, 100vw, foo bar' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-junk-in-default": "<img sizes='(min-width:500px) 500px, 100vw foo bar' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-junk-in-source-size": "<img sizes='(min-width:500px) 500px foo bar, 100vw' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-percent-in-source-size-value": "<img sizes='(min-width:500px) 50%, 100vw' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-no-unit-in-source-size-value": "<img sizes='(min-width:500px) 50, 100vw' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-deg-source-size-value": "<img sizes='1deg' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-grad-source-size-value": "<img sizes='1grad' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-rad-source-size-value": "<img sizes='1rad' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-turn-source-size-value": "<img sizes='1turn' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-s-source-size-value": "<img sizes='1s' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-ms-source-size-value": "<img sizes='1ms' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-hz-source-size-value": "<img sizes='1Hz' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-khz-source-size-value": "<img sizes='1kHz' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-dpi-source-size-value": "<img sizes='1dpi' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-dpcm-source-size-value": "<img sizes='1dpcm' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-dppx-source-size-value": "<img sizes='1dppx' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-auto-source-size-value": "<img sizes='auto' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-inherit-source-size-value": "<img sizes='inherit' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-initial-source-size-value": "<img sizes='initial' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-default-source-size-value": "<img sizes='default' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-foo-bar-source-size-value": "<img sizes='foo-bar' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-negative-source-size-value": "<img sizes='-1px' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-empty": "<img sizes='' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-comma": "<img sizes=',' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-css-comment-after-plus": "<img sizes='+/**/50vw' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-css-comment-before-unit": "<img sizes='50/**/vw' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-scientific-notation-negative": "<img sizes='-1e+0px' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-scientific-notation-non-integer-in-exponent": "<img sizes='1e+1.5px' srcset='x 100w, y 200w' src=x alt>",
+ # srcset microsyntax
+ "srcset-microsyntax-leading-comma": "<img srcset=',x' src=x alt>",
+ "srcset-microsyntax-leading-comma-multiple": "<img srcset=',,,x' src=x alt>",
+ "srcset-microsyntax-trailing-comma": "<img srcset='x,' src=x alt>",
+ "srcset-microsyntax-trailing-comma-multiple": "<img srcset='x,,,' src=x alt>",
+ "srcset-microsyntax-broken-url": "<img srcset='http: 1x' src=x alt>",
+ "srcset-microsyntax-non-integer-w": "<img srcset='x 1.5w' sizes=100vw src=x alt>",
+ "srcset-microsyntax-uppercase-w": "<img srcset='x 1W' sizes=100vw src=x alt>",
+ "srcset-microsyntax-plus-w": "<img srcset='x +1w' sizes=100vw src=x alt>",
+ "srcset-microsyntax-scientific-notation-w": "<img srcset='x 1e0w' sizes=100vw src=x alt>",
+ "srcset-microsyntax-zero-w": "<img srcset='x 0w' sizes=100vw src=x alt>",
+ "srcset-microsyntax-negative-zero-w": "<img srcset='x -0w' sizes=100vw src=x alt>",
+ "srcset-microsyntax-negative-w": "<img srcset='x -1w' sizes=100vw src=x alt>",
+ "srcset-microsyntax-plus-x": "<img srcset='x +1x' src=x alt>",
+ "srcset-microsyntax-negative-x": "<img srcset='x -1x' src=x alt>",
+ "srcset-microsyntax-zero-x": "<img srcset='x 0x' src=x alt>",
+ "srcset-microsyntax-negative-zero-x": "<img srcset='x -0x' src=x alt>",
+ "srcset-microsyntax-leading-dot-x": "<img srcset='x .5x' src=x alt>",
+ "srcset-microsyntax-nan-x": "<img srcset='x NaNx' src=x alt>",
+ "srcset-microsyntax-infinity-x": "<img srcset='x Infinityx' src=x alt>",
+ "srcset-microsyntax-x-and-w": "<img srcset='x 1x 1w' sizes=100vw src=x alt>",
+ "srcset-microsyntax-x-and-h": "<img srcset='x 1x 1h' sizes=100vw src=x alt>",
+ "srcset-microsyntax-w-and-h": "<img srcset='x 1w 1h' sizes=100vw src=x alt>",
+ "srcset-microsyntax-h": "<img srcset='x 1h' sizes=100vw src=x alt>",
+ "srcset-microsyntax-function": "<img srcset='x foobar(baz quux, lol), y 1x' src=x alt>",
+ "srcset-microsyntax-parenthesis-junk": "<img srcset='x ><(((((o)>, y 1x' src=x alt>",
+ "srcset-microsyntax-square-bracket-junk": "<img srcset='x [, y 1x' src=x alt>",
+ "srcset-microsyntax-curly-bracket-junk": "<img srcset='x {, y 1x' src=x alt>",
+ "srcset-microsyntax-pipe-junk": "<img srcset='x ||, y 1x' src=x alt>",
+ "srcset-microsyntax-w-and-no-descriptor": "<img srcset='x 1w, y' sizes=100vw src=x alt>",
+ "srcset-microsyntax-unique-descriptors-1x-and-omitted": "<img srcset='x 1x, y' src=x alt>",
+ "srcset-microsyntax-unique-descriptors-2x": "<img srcset='x 2x, y 2x' src=x alt>",
+ "srcset-microsyntax-unique-descriptors-integer-and-decimals-x": "<img srcset='x 1x, y 1.0x' src=x alt>",
+ "srcset-microsyntax-unique-descriptors-w": "<img srcset='x 1w, y 1w' sizes=100vw src=x alt>",
+ "srcset-microsyntax-empty": "<img srcset='' src=x alt>",
+ "srcset-microsyntax-comma": "<img srcset=',' src=x alt>",
+ "srcset-microsyntax-css-comment-after-descriptor": "<img srcset='x 2x/**/' src=x alt>",
+ # aria
+ "picture-aria-role-img": "<picture role=img><img src=x alt></picture>",
+ "picture-aria-role-button": "<picture role=button><img src=x alt></picture>",
+ "picture-aria-role-region": "<picture role=region><img src=x alt></picture>",
+ "picture-aria-role-application": "<picture role=application><img src=x alt></picture>",
+ "source-aria-role-img": "<picture><source role=img srcset=x><img src=x alt></picture>",
+ "picture-aria-role-presentation": "<picture role=presentation><img src=x alt></picture>",
+ "source-aria-role-presentation": "<picture><source role=presentation srcset=x><img src=x alt></picture>",
+}
+
+non_errors_in_head = {
+ "parent-template-in-head": "<template><picture><img src=x alt></picture></template>",
+}
+
+non_errors = {
+ # basic
+ "basic-img-src": "<img src=x alt>",
+ "basic-picture-img-src": "<picture><img src=x alt></picture>",
+ "basic-picture-source": "<picture><source srcset=x><img src=x alt></picture>",
+ # inter-element whitespace
+ "inter-element-whitespace": "<picture> <!--x--> <source srcset=x> <!--x--> <img src=x alt> <!--x--> </picture>",
+ # parents
+ "parent-p": "<p><picture><img src=x alt></picture></p>",
+ "parent-h1": "<h1><picture><img src=x alt=x></picture></h1>",
+ "parent-noscript-in-body": "<noscript><picture><img src=x alt></picture></noscript>",
+ "parent-object": "<object data=x><picture><img src=x alt></picture></object>",
+ "parent-video": "<video src=x><picture><img src=x alt></picture></video>",
+ "parent-section": "<section><h2>x</h2><picture><img src=x alt></picture></section>",
+ "parent-main": "<main><picture><img src=x alt></picture></main>",
+ "parent-canvas": "<canvas><picture><img src=x alt></picture></canvas>",
+ "parent-template-in-body": "<template><picture><img src=x alt></picture></template>",
+ "parent-ruby": "<ruby><picture><img src=x alt></picture><rt>x</rt></ruby>",
+ "parent-rt": "<ruby>x<rt><picture><img src=x alt></picture></rt></ruby>",
+ "parent-rp": "<ruby>x<rp><picture><img src=x alt></picture></rp><rt>x</rt><rp>x</rp></ruby>",
+ "parent-a": "<a href=x><picture><img src=x alt></picture></a>",
+ "parent-button": "<button><picture><img src=x alt></picture></button>",
+ "parent-td": "<table><tr><td><picture><img src=x alt></picture></table>",
+ # script-supporting elements
+ "script-first": "<picture><script></script><source srcset=x><img src=x alt></picture>",
+ "template-first": "<picture><template></template><source srcset=x><img src=x alt></picture>",
+ "script-between": "<picture><source srcset=x><script></script><img src=x alt></picture>",
+ "script-after": "<picture><source srcset=x><img src=x alt><script></script></picture>",
+ "script-before-after": "<picture><script></script><source srcset=x><img src=x alt><script></script></picture>",
+ "script-before-between-after": "<picture><script></script><source srcset=x><script></script><img src=x alt><script></script></picture>",
+ "script-and-template": "<picture><template></template><source srcset=x><script></script><img src=x alt><template></template></picture>",
+ # source with following sibling source element or img element with a srcset attribute
+ "source-with-media-img-with-srcset": "<picture><source srcset=x media=screen><img src=x srcset=x alt></picture>",
+ "source-with-media-uppercase-img-with-srcset": "<picture><source srcset=x media=SCREEN><img src=x srcset=x alt></picture>",
+ "source-with-media-spaces-img-with-srcset": "<picture><source srcset=x media=' \n\tscreen \n\t'><img src=x srcset=x alt></picture>",
+ "source-with-media-source-with-srcset": "<picture><source srcset=x media=screen><source srcset=x><img src=x alt></picture>",
+ "source-with-type-img-with-srcset": "<picture><source srcset=x type=image/gif><img src=x srcset=x alt></picture>",
+ "source-with-type-source-with-srcset": "<picture><source srcset=x type=image/gif><source srcset=x><img src=x alt></picture>",
+ # sizes present
+ "img-with-sizes": "<img srcset='x 100w, y 200w' sizes=50vw src=x alt>",
+ "source-with-sizes": "<picture><source srcset='x 100w, y 200w' sizes=50vw><img src=x alt></picture>",
+ # embed allows any attributes
+ "embed-srcset-empty": "<embed srcset>",
+ "embed-srcset-junk": "<embed srcset='foo bar'>",
+ "embed-sizes-empty": "<embed sizes>",
+ "embed-sizes-junk": "<embed sizes='foo bar'>",
+ # img src also in srcset
+ "img-src-also-in-srcset-1x": "<img src=x srcset='x 1x, y 2x' alt>",
+ "img-src-also-in-srcset-2x": "<img src=x srcset='y 1x, x 2x' alt>",
+ "img-src-also-in-srcset-w": "<img src=x srcset='x 100w, y 200w' sizes=100vw alt>",
+ # img src not in srcset
+ "img-src-not-in-srcset-x": "<img src=x srcset='y 1x, z 2x' alt>",
+ "img-src-not-in-srcset-w": "<img src=x srcset='y 100w, z 200w' sizes=100vw alt>",
+ # source type
+ "source-type": "<picture><source srcset=x type=image/gif><img src=x alt></picture>",
+ "source-type-srcset-x": "<picture><source srcset='x 1x, y 2x' type=image/gif><img src=x alt></picture>",
+ "source-type-srcset-w-sizes": "<picture><source srcset='x 100w, y 200w' type=image/gif sizes=50vw><img src=x alt></picture>",
+ # sizes microsyntax
+ "sizes-microsyntax-media-min-width": "<img sizes='(min-width:500px) 500px, 100vw' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-multiple-source-sizes": "<img sizes='(min-width:1500px) 500px, (min-width:1000px) 33vw, (min-width:500px) 50vw, 100vw' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-no-default": "<img sizes='(min-width:500px) 500px' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-media-not-and": "<img sizes='not (width:500px) and (width:500px) 500px' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-only-default": "<img sizes='500px' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-calc-in-default": "<img sizes='calc(500px)' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-calc-in-source-size-value": "<img sizes='(min-width:500px) calc(500px)' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-calc-in-media": "<img sizes='(min-width:calc(500px)) 500px' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-zero": "<img sizes='0' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-minus-zero": "<img sizes='-0' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-em-in-source-size-value": "<img sizes='1em' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-ex-in-source-size-value": "<img sizes='1ex' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-ch-in-source-size-value": "<img sizes='1ch' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-rem-in-source-size-value": "<img sizes='1rem' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-vw-in-source-size-value": "<img sizes='1vw' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-vh-in-source-size-value": "<img sizes='1vh' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-vmin-in-source-size-value": "<img sizes='1vmin' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-vmax-in-source-size-value": "<img sizes='1vmax' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-cm-in-source-size-value": "<img sizes='1cm' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-mm-in-source-size-value": "<img sizes='1mm' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-q-in-source-size-value": "<img sizes='1q' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-in-in-source-size-value": "<img sizes='1in' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-pc-in-source-size-value": "<img sizes='1pc' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-pt-in-source-size-value": "<img sizes='1pt' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-px-in-source-size-value": "<img sizes='1px' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-non-integer-px-in-source-size-value": "<img sizes='0.2px' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-leading-css-comment": "<img sizes='/**/50vw' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-trailing-css-comment": "<img sizes='50vw/**/' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-plus": "<img sizes='+50vw' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-non-integer-omitted-zero": "<img sizes='.2px' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-scientifi-notation-0": "<img sizes='-0e-0px' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-scientifi-notation-1": "<img sizes='+11.11e+11px' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-scientifi-notation-2": "<img sizes='2.2e2px' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-scientifi-notation-3": "<img sizes='33E33px' srcset='x 100w, y 200w' src=x alt>",
+ "sizes-microsyntax-scientifi-notation-4": "<img sizes='.4E4px' srcset='x 100w, y 200w' src=x alt>",
+ # srcset microsyntax
+ "srcset-microsyntax-comma-in-url": "<img srcset='x,x' src=x alt>",
+ "srcset-microsyntax-percent-escaped-leading-comma-in-url": "<img srcset='%2Cx' src=x alt>",
+ "srcset-microsyntax-percent-escaped-trailing-comma-in-url": "<img srcset='x%2C' src=x alt>",
+ "srcset-microsyntax-percent-escaped-space-in-url": "<img srcset='%20' src=x alt>",
+ "srcset-microsyntax-w": "<img srcset='x 1w' sizes=100vw src=x alt>",
+ "srcset-microsyntax-x": "<img srcset='x 1x' src=x alt>",
+ "srcset-microsyntax-non-integer-x": "<img srcset='x 1.5x' src=x alt>",
+ "srcset-microsyntax-scientific-notation-x": "<img srcset='x 1e0x' src=x alt>",
+ "srcset-microsyntax-scientific-notation-decimals-x": "<img srcset='x 1.5e0x' src=x alt>",
+ "srcset-microsyntax-scientific-notation-e-plus-x": "<img srcset='x 1e+0x' src=x alt>",
+ "srcset-microsyntax-scientific-notation-e-minus-x": "<img srcset='x 1e-0x' src=x alt>",
+ "srcset-microsyntax-scientific-notation-e-uppercase-x": "<img srcset='x 1E0x' src=x alt>",
+ "srcset-microsyntax-no-space-between-candidates": "<img srcset='x 1x,y 2x' src=x alt>",
+ # valid attributes on img in picture
+ "img-crossorigin-with-picture": "<picture><img crossorigin src=x alt></picture>",
+ "img-usemap-with-picture": "<picture><img usemap=#x src=x alt></picture><map name=x></map>",
+ "img-ismap-with-picture": "<a href=x><picture><img ismap src=x alt></picture></a>",
+ "img-width-height-with-picture": "<picture><img src=x alt width=1 height=1></picture>",
+ "img-width-height-zero-with-picture": "<picture><img src=x alt width=0 height=0></picture>",
+ # global attributes on picture
+ "picture-global-attributes": "<picture title=x class=x dir=ltr hidden id=asdf tabindex=0><img src=x alt></picture>",
+}
+
+for key in errors.keys():
+ template_error = template
+ template_error += '<title>invalid %s</title>\n' % key
+ template_error += errors[key]
+ file = open(os.path.join(ccdir, "html/elements/picture/%s-novalid.html" % key), 'wb')
+ file.write(template_error)
+ file.close()
+
+file = open(os.path.join(ccdir, "html/elements/picture/picture-isvalid.html"), 'wb')
+file.write(template + '<title>valid picture</title>\n')
+for key in non_errors_in_head.keys():
+ file.write('%s <!-- %s -->\n' % (non_errors_in_head[key], key))
+file.write('<body>\n')
+for key in non_errors.keys():
+ file.write('%s <!-- %s -->\n' % (non_errors[key], key))
+file.close()
+# vim: ts=4:sw=4
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/tools/url.py b/tests/wpt/web-platform-tests/conformance-checkers/tools/url.py
new file mode 100644
index 00000000000..ce3eef7d868
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/tools/url.py
@@ -0,0 +1,453 @@
+# -*- coding: utf-8 -*-
+import os
+ccdir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+# based on https://github.com/w3c/web-platform-tests/blob/275544eab54a0d0c7f74ccc2baae9711293d8908/url/urltestdata.txt
+invalid = {
+ "scheme-trailing-tab": "a:\tfoo.com",
+ "scheme-trailing-newline": "a:\nfoo.com",
+ "scheme-trailing-cr": "a:\rfoo.com",
+ "scheme-trailing-space": "a: foo.com",
+ "scheme-trailing-tab": "a:\tfoo.com",
+ "scheme-trailing-newline": "a:\nfoo.com",
+ "scheme-trailing-cr": "a:\rfoo.com",
+ "scheme-http-no-slash": "http:foo.com",
+ "scheme-http-no-slash-colon": "http::@c:29",
+ "scheme-http-no-slash-square-bracket": "http:[61:27]/:foo",
+ "scheme-http-backslash": "http:\\\\foo.com\\",
+ "scheme-http-single-slash": "http:/example.com/",
+ "scheme-ftp-single-slash": "ftp:/example.com/",
+ "scheme-https-single-slash": "https:/example.com/",
+ "scheme-data-single-slash": "data:/example.com/",
+ "scheme-ftp-no-slash": "ftp:example.com/",
+ "scheme-https-no-slash": "https:example.com/",
+ "scheme-javascript-no-slash-malformed": "javascript:example.com/",
+ "userinfo-password-bad-chars": "http://&a:foo(b]c@d:2/",
+ "userinfo-username-contains-at-sign": "http://::@c@d:2",
+ "userinfo-backslash": "http://a\\b:c\\d@foo.com",
+ "host-space": "http://example .org",
+ "host-tab": "http://example\t.org",
+ "host-newline": "http://example.\norg",
+ "host-cr": "http://example.\rorg",
+ "host-square-brackets-port-contains-colon": "http://[1::2]:3:4",
+ "port-single-letter": "http://f:b/c",
+ "port-multiple-letters": "http://f:fifty-two/c",
+ "port-leading-colon": "http://2001::1",
+ "port-leading-colon-bracket-colon": "http://2001::1]:80",
+ "path-leading-backslash-at-sign": "http://foo.com/\\@",
+ "path-leading-colon-backslash": ":\\",
+ "path-leading-colon-chars-backslash": ":foo.com\\",
+ "path-relative-square-brackets": "[61:24:74]:98",
+ "fragment-contains-hash": "http://foo/path#f#g",
+ "path-percent-encoded-malformed": "http://example.com/foo/%2e%2",
+ "path-bare-percent-sign": "http://example.com/foo%",
+ "path-u0091": u"http://example.com/foo\u0091".encode('utf-8'),
+ "userinfo-username-contains-pile-of-poo": "http://💩:foo@example.com",
+ "userinfo-password-contains-pile-of-poo": "http://foo:💩@example.com",
+ "host-hostname-in-brackets": "http://[www.google.com]/",
+ "host-empty": "http://",
+ "host-empty-with-userinfo": "http://user:pass@/",
+ "port-leading-dash": "http://foo:-80/",
+ "host-empty-userinfo-empty": "http://@/www.example.com",
+ "host-invalid-unicode": u"http://\ufdd0zyx.com".encode('utf-8'),
+ "host-invalid-unicode-percent-encoded": "http://%ef%b7%90zyx.com",
+ "host-double-percent-encoded": u"http://\uff05\uff14\uff11.com".encode('utf-8'),
+ "host-double-percent-encoded-percent-encoded": "http://%ef%bc%85%ef%bc%94%ef%bc%91.com",
+ "host-u0000-percent-encoded": u"http://\uff05\uff10\uff10.com".encode('utf-8'),
+ "host-u0000-percent-encoded-percent-encoded": "http://%ef%bc%85%ef%bc%90%ef%bc%90.com",
+}
+invalid_absolute = invalid.copy()
+
+invalid_url_code_points = {
+ "fragment-backslash": "#\\",
+ "fragment-leading-space": "http://f:21/b# e",
+ "path-contains-space": "/a/ /c",
+ "path-leading-space": "http://f:21/ b",
+ "path-tab": "http://example.com/foo\tbar",
+ "path-trailing-space": "http://f:21/b ?",
+ "port-cr": "http://f:\r/c",
+ "port-newline": "http://f:\n/c",
+ "port-space": "http://f: /c",
+ "port-tab": "http://f:\t/c",
+ "query-leading-space": "http://f:21/b? d",
+ "query-trailing-space": "http://f:21/b?d #",
+}
+invalid.update(invalid_url_code_points)
+invalid_absolute.update(invalid_url_code_points)
+
+valid_absolute = {
+ "scheme-private": "a:foo.com",
+ "scheme-private-slash": "foo:/",
+ "scheme-private-slash-slash": "foo://",
+ "scheme-private-path": "foo:/bar.com/",
+ "scheme-private-path-leading-slashes-only": "foo://///////",
+ "scheme-private-path-leading-slashes-chars": "foo://///////bar.com/",
+ "scheme-private-path-leading-slashes-colon-slashes": "foo:////://///",
+ "scheme-private-single-letter": "c:/foo",
+ "scheme-private-single-slash": "madeupscheme:/example.com/",
+ "scheme-file-single-slash": "file:/example.com/",
+ "scheme-ftps-single-slash": "ftps:/example.com/",
+ "scheme-gopher-single-slash": "gopher:/example.com/",
+ "scheme-ws-single-slash": "ws:/example.com/",
+ "scheme-wss-single-slash": "wss:/example.com/",
+ "scheme-javascript-single-slash": "javascript:/example.com/",
+ "scheme-mailto-single-slash": "mailto:/example.com/",
+ "scheme-private-no-slash": "madeupscheme:example.com/",
+ "scheme-ftps-no-slash": "ftps:example.com/",
+ "scheme-gopher-no-slash": "gopher:example.com/",
+ "scheme-wss-no-slash": "wss:example.com/",
+ "scheme-mailto-no-slash": "mailto:example.com/",
+ "scheme-data-no-slash": "data:text/plain,foo",
+ "userinfo": "http://user:pass@foo:21/bar;par?b#c",
+ "host-ipv6": "http://[2001::1]",
+ "host-ipv6-port": "http://[2001::1]:80",
+ "port-none-but-colon": "http://f:/c",
+ "port-0": "http://f:0/c",
+ "port-00000000000000": "http://f:00000000000000/c",
+ "port-00000000000000000000080": "http://f:00000000000000000000080/c",
+ "port-00000000000000000000080": "http://f:00000000000000000000080/c",
+ "userinfo-host-port-path": "http://a:b@c:29/d",
+ "userinfo-username-non-alpha": "http://foo.com:b@d/",
+ "query-contains-question-mark": "http://foo/abcd?efgh?ijkl",
+ "fragment-contains-question-mark": "http://foo/abcd#foo?bar",
+ "path-percent-encoded-dot": "http://example.com/foo/%2e",
+ "path-percent-encoded-space": "http://example.com/%20foo",
+ "path-non-ascii": u"http://example.com/\u00C2\u00A9zbar".encode('utf-8'),
+ "path-percent-encoded-multiple": "http://example.com/foo%41%7a",
+ "path-percent-encoded-u0091": "http://example.com/foo%91",
+ "path-percent-encoded-u0000": "http://example.com/foo%00",
+ "path-percent-encoded-mixed-case": "http://example.com/%3A%3a%3C%3c",
+ "path-unicode-han": u"http://example.com/\u4F60\u597D\u4F60\u597D".encode('utf-8'),
+ "path-uFEFF": u"http://example.com/\uFEFF/foo".encode('utf-8'),
+ "path-u202E-u202D": u"http://example.com/\u202E/foo/\u202D/bar".encode('utf-8'),
+ "host-is-pile-of-poo": "http://💩",
+ "path-contains-pile-of-poo": "http://example.com/foo/💩",
+ "query-contains-pile-of-poo": "http://example.com/foo?💩",
+ "fragment-contains-pile-of-poo": "http://example.com/foo#💩",
+ "host-192.0x00A80001": "http://192.0x00A80001",
+ "userinfo-username-contains-percent-encoded": "http://%25DOMAIN:foobar@foodomain.com",
+ "userinfo-empty": "http://@www.example.com",
+ "userinfo-user-empty": "http://:b@www.example.com",
+ "userinfo-password-empty": "http://a:@www.example.com",
+ "host-exotic-whitespace": u"http://GOO\u200b\u2060\ufeffgoo.com".encode('utf-8'),
+ "host-exotic-dot": u"http://www.foo\u3002bar.com".encode('utf-8'),
+ "host-fullwidth": u"http://\uff27\uff4f.com".encode('utf-8'),
+ "host-idn-unicode-han": u"http://\u4f60\u597d\u4f60\u597d".encode('utf-8'),
+ "host-IP-address-broken": "http://192.168.0.257/",
+}
+valid = valid_absolute.copy()
+
+valid_relative = {
+ "scheme-schemeless-relative": "//foo/bar",
+ "path-slash-only-relative": "/",
+ "path-simple-relative": "/a/b/c",
+ "path-percent-encoded-slash-relative": "/a%2fc",
+ "path-percent-encoded-slash-plus-slashes-relative": "/a/%2f/c",
+ "query-empty-no-path-relative": "?",
+ "fragment-empty-hash-only-no-path-relative": "#",
+ "fragment-slash-relative": "#/",
+ "fragment-semicolon-question-mark-relative": "#;?",
+ "fragment-non-ascii-relative": u"#\u03B2".encode('utf-8'),
+}
+valid.update(valid_relative)
+invalid_absolute.update(valid_relative)
+
+valid_relative_colon_dot = {
+ "scheme-none-relative": "foo.com",
+ "path-colon-relative": ":",
+ "path-leading-colon-letter-relative": ":a",
+ "path-leading-colon-chars-relative": ":foo.com",
+ "path-leading-colon-slash-relative": ":/",
+ "path-leading-colon-hash-relative": ":#",
+ "path-leading-colon-number-relative": ":23",
+ "path-slash-colon-number-relative": "/:23",
+ "path-leading-colon-colon-relative": "::",
+ "path-colon-colon-number-relative": "::23",
+ "path-starts-with-pile-of-poo": "💩http://foo",
+ "path-contains-pile-of-poo": "http💩//:foo",
+}
+valid.update(valid_relative_colon_dot)
+
+invalid_file = {
+ "scheme-file-backslash": "file:c:\\foo\\bar.html",
+ "scheme-file-single-slash-c-bar": "file:/C|/foo/bar",
+ "scheme-file-triple-slash-c-bar": "file:///C|/foo/bar",
+}
+invalid.update(invalid_file)
+
+valid_file = {
+ "scheme-file-uppercase": "File://foo/bar.html",
+ "scheme-file-slash-slash-c-bar": "file://C|/foo/bar",
+ "scheme-file-slash-slash-abc-bar": "file://abc|/foo/bar",
+ "scheme-file-host-included": "file://server/foo/bar",
+ "scheme-file-host-empty": "file:///foo/bar.txt",
+ "scheme-file-scheme-only": "file:",
+ "scheme-file-slash-only": "file:/",
+ "scheme-file-slash-slash-only": "file://",
+ "scheme-file-slash-slash-slash-only": "file:///",
+ "scheme-file-no-slash": "file:test",
+}
+valid.update(valid_file)
+valid_absolute.update(valid_file)
+
+warnings = {
+ "scheme-data-contains-fragment": "data:text/html,test#test",
+}
+
+element_attribute_pairs = [
+ "a href",
+ # "a ping", space-separated list of URLs; tested elsewhere
+ "area href",
+ # "area ping", space-separated list of URLs; tested elsewhere
+ "audio src",
+ "base href",
+ "blockquote cite",
+ "button formaction",
+ "del cite",
+ "embed src",
+ "form action",
+ "html manifest",
+ "iframe src",
+ "img src", # srcset is tested elsewhere
+ "input formaction", # type=submit, type=image
+ "input src", # type=image
+ "input value", # type=url
+ "ins cite",
+ "link href",
+ #"menuitem icon", # skip until parser is updated
+ "object data",
+ "q cite",
+ "script src",
+ "source src",
+ "track src",
+ "video poster",
+ "video src",
+]
+
+template = "<!DOCTYPE html>\n<meta charset=utf-8>\n"
+
+def write_novalid_files():
+ for el, attr in (pair.split() for pair in element_attribute_pairs):
+ for desc, url in invalid.items():
+ if ("area" == el):
+ f = open(os.path.join(ccdir, "html/elements/area/href/%s-novalid.html" % desc), 'wb')
+ f.write(template + '<title>invalid href: %s</title>\n' % desc)
+ f.write('<map name=foo><%s %s="%s" alt></map>\n' % (el, attr, url))
+ f.close()
+ elif ("base" == el or "embed" == el):
+ f = open(os.path.join(ccdir, "html/elements/%s/%s/%s-novalid.html" % (el, attr, desc)), 'wb')
+ f.write(template + '<title>invalid %s: %s</title>\n' % (attr, desc))
+ f.write('<%s %s="%s">\n' % (el, attr, url))
+ f.close()
+ elif ("html" == el):
+ f = open(os.path.join(ccdir, "html/elements/html/manifest/%s-novalid.html" % desc), 'wb')
+ f.write('<!DOCTYPE html>\n')
+ f.write('<html manifest="%s">\n' % url)
+ f.write('<meta charset=utf-8>\n')
+ f.write('<title>invalid manifest: %s</title>\n' % desc)
+ f.write('</html>\n')
+ f.close()
+ elif ("img" == el):
+ f = open(os.path.join(ccdir, "html/elements/img/src/%s-novalid.html" % desc), 'wb')
+ f.write(template + '<title>invalid src: %s</title>\n' % desc)
+ f.write('<img src="%s" alt>\n' % url)
+ f.close()
+ elif ("input" == el and "src" == attr):
+ f = open(os.path.join(ccdir, "html/elements/input/type-image-src/%s-novalid.html" % desc), 'wb')
+ f.write(template + '<title>invalid src: %s</title>\n' % desc)
+ f.write('<%s type=image alt="foo" %s="%s">\n' % (el, attr, url))
+ f.close()
+ elif ("input" == el and "formaction" == attr):
+ f = open(os.path.join(ccdir, "html/elements/input/type-submit-formaction/%s-novalid.html" % desc), 'wb')
+ f.write(template + '<title>invalid formaction: %s</title>\n' % desc)
+ f.write('<%s type=submit %s="%s">\n' % (el, attr, url))
+ f.close()
+ f = open(os.path.join(ccdir, "html/elements/input/type-image-formaction/%s-novalid.html" % desc), 'wb')
+ f.write(template + '<title>invalid formaction: %s</title>\n' % desc)
+ f.write('<%s type=image alt="foo" %s="%s">\n' % (el, attr, url))
+ f.close()
+ elif ("input" == el and "value" == attr):
+ f = open(os.path.join(ccdir, "html/elements/input/type-url-value/%s-novalid.html" % desc), 'wb')
+ f.write(template + '<title>invalid value attribute: %s</title>\n' % desc)
+ f.write('<%s type=url %s="%s">\n' % (el, attr, url))
+ f.close()
+ elif ("link" == el):
+ f = open(os.path.join(ccdir, "html/elements/link/href/%s-novalid.html" % desc), 'wb')
+ f.write(template + '<title>invalid href: %s</title>\n' % desc)
+ f.write('<link href="%s" rel=help>\n' % url)
+ f.close()
+ elif ("source" == el or "track" == el):
+ f = open(os.path.join(ccdir, "html/elements/%s/%s/%s-novalid.html" % (el, attr, desc)), 'wb')
+ f.write(template + '<title>invalid %s: %s</title>\n' % (attr, desc))
+ f.write('<video><%s %s="%s"></video>\n' % (el, attr, url))
+ f.close()
+ else:
+ f = open(os.path.join(ccdir, "html/elements/%s/%s/%s-novalid.html" % (el, attr, desc)), 'wb')
+ f.write(template + '<title>invalid %s: %s</title>\n' % (attr, desc))
+ f.write('<%s %s="%s"></%s>\n' % (el, attr, url, el))
+ f.close()
+ for desc, url in invalid.items():
+ f = open(os.path.join(ccdir, "html/microdata/itemid/%s-novalid.html" % desc), 'wb')
+ f.write(template + '<title>invalid itemid: %s</title>\n' % desc)
+ f.write('<div itemid="%s" itemtype="http://foo" itemscope></div>\n' % url)
+ f.close()
+ for desc, url in invalid_absolute.items():
+ f = open(os.path.join(ccdir, "html/microdata/itemtype/%s-novalid.html" % desc), 'wb')
+ f.write(template + '<title>invalid itemtype: %s</title>\n' % desc)
+ f.write('<div itemtype="%s" itemscope></div>\n' % url)
+ f.close()
+ f = open(os.path.join(ccdir, "html/elements/input/type-url-value/%s-novalid.html" % desc), 'wb')
+ f.write(template + '<title>invalid value attribute: %s</title>\n' %desc)
+ f.write('<input type=url value="%s">\n' % url)
+ f.close()
+
+def write_haswarn_files():
+ for el, attr in (pair.split() for pair in element_attribute_pairs):
+ for desc, url in warnings.items():
+ if ("area" == el):
+ f = open(os.path.join(ccdir, "html/elements/area/href/%s-haswarn.html" % desc), 'wb')
+ f.write(template + '<title>%s warning: %s</title>\n' % (attr, desc))
+ f.write('<map name=foo><%s %s="%s" alt></map>\n' % (el, attr, url))
+ f.close()
+ elif ("base" == el or "embed" == el):
+ f = open(os.path.join(ccdir, "html/elements/%s/%s/%s-haswarn.html" % (el, attr, desc)), 'wb')
+ f.write(template + '<title>%s warning: %s</title>\n' % (attr, desc))
+ f.write('<%s %s="%s">\n' % (el, attr, url))
+ f.close()
+ elif ("html" == el):
+ f = open(os.path.join(ccdir, "html/elements/html/manifest/%s-haswarn.html" % desc), 'wb')
+ f.write('<!DOCTYPE html>\n')
+ f.write('<html manifest="%s">\n' % url)
+ f.write('<meta charset=utf-8>\n')
+ f.write('<title>%s warning: %s</title>\n' % (attr, desc))
+ f.write('</html>\n')
+ f.close()
+ elif ("img" == el):
+ f = open(os.path.join(ccdir, "html/elements/img/src/%s-haswarn.html" % desc), 'wb')
+ f.write(template + '<title>%s warning: %s</title>\n' % (attr, desc))
+ f.write('<%s %s="%s" alt>\n' % (el, attr, url))
+ f.close()
+ elif ("input" == el and "src" == attr):
+ f = open(os.path.join(ccdir, "html/elements/input/type-image-src/%s-haswarn.html" % desc), 'wb')
+ f.write(template + '<title>%s warning: %s</title>\n' % (attr, desc))
+ f.write('<%s type=image alt="foo" %s="%s">\n' % (el, attr, url))
+ f.close()
+ elif ("input" == el and "formaction" == attr):
+ f = open(os.path.join(ccdir, "html/elements/input/type-submit-formaction/%s-haswarn.html" % desc), 'wb')
+ f.write(template + '<title>%s warning: %s</title>\n' % (attr, desc))
+ f.write('<%s type=submit %s="%s">\n' % (el, attr, url))
+ f.close()
+ f = open(os.path.join(ccdir, "html/elements/input/type-image-formaction/%s-haswarn.html" % desc), 'wb')
+ f.write(template + '<title>%s warning: %s</title>\n' % (attr, desc))
+ f.write('<%s type=image alt="foo" %s="%s">\n' % (el, attr, url))
+ f.close()
+ elif ("input" == el and "value" == attr):
+ f = open(os.path.join(ccdir, "html/elements/input/type-url-value/%s-haswarn.html" % desc), 'wb')
+ f.write(template + '<title>%s warning: %s</title>\n' % (attr, desc))
+ f.write('<%s type=url %s="%s">\n' % (el, attr, url))
+ f.close()
+ elif ("link" == el):
+ f = open(os.path.join(ccdir, "html/elements/link/href/%s-haswarn.html" % desc), 'wb')
+ f.write(template + '<title>%s warning: %s</title>\n' % (attr, desc))
+ f.write('<%s %s="%s" rel=help>\n' % (el, attr, url))
+ f.close()
+ elif ("source" == el or "track" == el):
+ f = open(os.path.join(ccdir, "html/elements/%s/%s/%s-haswarn.html" % (el, attr, desc)), 'wb')
+ f.write(template + '<title>%s warning: %s</title>\n' % (attr, desc))
+ f.write('<video><%s %s="%s"></video>\n' % (el, attr, url))
+ f.close()
+ else:
+ f = open(os.path.join(ccdir, "html/elements/%s/%s/%s-haswarn.html" % (el, attr, desc)), 'wb')
+ f.write(template + '<title>%s warning: %s</title>\n' % (url, desc))
+ f.write('<%s %s="%s"></%s>\n' % (el, attr, url, el))
+ f.close()
+ for desc, url in warnings.items():
+ f = open(os.path.join(ccdir, "html/microdata/itemtype-%s-haswarn.html" % desc ), 'wb')
+ f.write(template + '<title>warning: %s</title>\n' % desc)
+ f.write('<div itemtype="%s" itemscope></div>\n' % url)
+ f.close()
+ f = open(os.path.join(ccdir, "html/microdata/itemid-%s-haswarn.html" % desc), 'wb')
+ f.write(template + '<title>warning: %s</title>\n' % desc)
+ f.write('<div itemid="%s" itemtype="http://foo" itemscope></div>\n' % url)
+ f.close()
+
+def write_isvalid_files():
+ for el, attr in (pair.split() for pair in element_attribute_pairs):
+ if ("base" == el):
+ continue
+ if ("html" == el):
+ continue
+ elif ("input" == el and "value" == attr):
+ continue
+ elif ("input" == el and "formaction" == attr):
+ fs = open(os.path.join(ccdir, "html/elements/input/type-submit-formaction-isvalid.html"), 'wb')
+ fs.write(template + '<title>valid formaction</title>\n')
+ fi = open(os.path.join(ccdir, "html/elements/input/type-image-formaction-isvalid.html"), 'wb')
+ fi.write(template + '<title>valid formaction</title>\n')
+ elif ("input" == el and "src" == attr):
+ f = open(os.path.join(ccdir, "html/elements/input/type-image-src-isvalid.html"), 'wb')
+ f.write(template + '<title>valid src</title>\n')
+ else:
+ f = open(os.path.join(ccdir, "html/elements/%s/%s-isvalid.html" % (el, attr)), 'wb')
+ f.write(template + '<title>valid %s</title>\n' % attr)
+ for desc, url in valid.items():
+ if ("area" == el):
+ f.write('<map name=foo><%s %s="%s" alt></map><!-- %s -->\n' % (el, attr, url, desc))
+ elif ("embed" == el):
+ f.write('<%s %s="%s"><!-- %s -->\n' % (el, attr, url, desc))
+ elif ("img" == el):
+ f.write('<%s %s="%s" alt><!-- %s -->\n' % (el, attr, url, desc))
+ elif ("input" == el and "src" == attr):
+ f.write('<%s type=image alt="foo" %s="%s"><!-- %s -->\n' % (el, attr, url, desc))
+ elif ("input" == el and "formaction" == attr):
+ fs.write('<%s type=submit %s="%s"><!-- %s -->\n' % (el, attr, url, desc))
+ fi.write('<%s type=image alt="foo" %s="%s"><!-- %s -->\n' % (el, attr, url, desc))
+ elif ("link" == el):
+ f.write('<%s %s="%s" rel=help><!-- %s -->\n' % (el, attr, url, desc))
+ elif ("source" == el or "track" == el):
+ f.write('<video><%s %s="%s"></video><!-- %s -->\n' % (el, attr, url, desc))
+ else:
+ f.write('<%s %s="%s"></%s><!-- %s -->\n' % (el, attr, url, el, desc))
+ if ("input" == el and "formaction" == attr):
+ fs.close()
+ fi.close()
+ else:
+ if ("a" == el and "href" == attr):
+ f.write('<a href=""></a><!-- empty-href -->\n')
+ f.close()
+ for desc, url in valid.items():
+ f = open(os.path.join(ccdir, "html/elements/base/href/%s-isvalid.html" % desc), 'wb')
+ f.write(template + '<title>valid href: %s</title>\n' % desc)
+ f.write('<base href="%s">\n' % url)
+ f.close()
+ f = open(os.path.join(ccdir, "html/elements/html/manifest/%s-isvalid.html" % desc), 'wb')
+ f.write('<!DOCTYPE html>\n')
+ f.write('<html manifest="%s">\n' % url)
+ f.write('<meta charset=utf-8>\n')
+ f.write('<title>valid manifest: %s</title>\n' % desc)
+ f.write('</html>\n')
+ f.close()
+ f = open(os.path.join(ccdir, "html/elements/meta/refresh-isvalid.html"), 'wb')
+ f.write(template + '<title>valid meta refresh</title>\n')
+ for desc, url in valid.items():
+ f.write('<meta http-equiv=refresh content="0; URL=%s"><!-- %s -->\n' % (url, desc))
+ f.close()
+ f = open(os.path.join(ccdir, "html/microdata/itemid-isvalid.html"), 'wb')
+ f.write(template + '<title>valid itemid</title>\n')
+ for desc, url in valid.items():
+ f.write('<div itemid="%s" itemtype="http://foo" itemscope></div><!-- %s -->\n' % (url, desc))
+ f.close()
+ f = open(os.path.join(ccdir, "html/microdata/itemtype-isvalid.html"), 'wb')
+ f.write(template + '<title>valid itemtype</title>\n')
+ for desc, url in valid_absolute.items():
+ f.write('<div itemtype="%s" itemscope></div><!-- %s -->\n' % (url, desc))
+ f.close()
+ f = open(os.path.join(ccdir, "html/elements/input/type-url-value-isvalid.html"), 'wb')
+ f.write(template + '<title>valid value attribute</title>\n')
+ for desc, url in valid_absolute.items():
+ f.write('<input type=url value="%s"><!-- %s -->\n' % (url, desc))
+ f.close()
+
+write_novalid_files()
+write_haswarn_files()
+write_isvalid_files()
+# vim: ts=4:sw=4
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/attributes/accesskey/003-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/attributes/accesskey/003-novalid.xhtml
new file mode 100644
index 00000000000..0cf79bd9f5a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/attributes/accesskey/003-novalid.xhtml
@@ -0,0 +1,8 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>accesskey attribute with duplicate key labels</title>
+</head>
+<body>
+<a href="url" accesskey="a b ぬ c ぬ">foo</a>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/attributes/accesskey/004-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/attributes/accesskey/004-novalid.xhtml
new file mode 100644
index 00000000000..a6088221c56
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/attributes/accesskey/004-novalid.xhtml
@@ -0,0 +1,8 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>accesskey attribute with multi-character key label</title>
+</head>
+<body>
+<a href="url" accesskey="a b ほげ">foo</a>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/attributes/data/002-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/attributes/data/002-novalid.xhtml
new file mode 100644
index 00000000000..59ba0740ad9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/attributes/data/002-novalid.xhtml
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML>
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>starts with the string "data-", has at least one character after the hyphen, is XML-compatible, and contains no uppercase ASCII letters</title>
+ </head>
+ <body>
+ <p data-zZ=""></p><!-- has uppercase ASCII letter in name -->
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/attributes/spellcheck/050-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/attributes/spellcheck/050-novalid.xhtml
new file mode 100644
index 00000000000..fe82de048ba
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/attributes/spellcheck/050-novalid.xhtml
@@ -0,0 +1,8 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>spellcheck="badvalue"</title>
+</head>
+<body>
+<p spellcheck="badvalue"></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/attributes/spellcheck/051-isvalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/attributes/spellcheck/051-isvalid.xhtml
new file mode 100644
index 00000000000..ffc5c2c5fd8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/attributes/spellcheck/051-isvalid.xhtml
@@ -0,0 +1,8 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>spellcheck=""</title>
+</head>
+<body>
+<p spellcheck=""></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/attributes/spellcheck/052-isvalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/attributes/spellcheck/052-isvalid.xhtml
new file mode 100644
index 00000000000..be64c4d20bf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/attributes/spellcheck/052-isvalid.xhtml
@@ -0,0 +1,8 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>spellcheck="true"</title>
+</head>
+<body>
+<p spellcheck="true"></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/attributes/spellcheck/053-isvalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/attributes/spellcheck/053-isvalid.xhtml
new file mode 100644
index 00000000000..a1d391dbc82
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/attributes/spellcheck/053-isvalid.xhtml
@@ -0,0 +1,8 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>spellcheck="false"</title>
+</head>
+<body>
+<p spellcheck="false"></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/attributes/spellcheck/350-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/attributes/spellcheck/350-novalid.xhtml
new file mode 100644
index 00000000000..fe82de048ba
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/attributes/spellcheck/350-novalid.xhtml
@@ -0,0 +1,8 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>spellcheck="badvalue"</title>
+</head>
+<body>
+<p spellcheck="badvalue"></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/a/100-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/a/100-novalid.xhtml
new file mode 100644
index 00000000000..a093b6ee1fc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/a/100-novalid.xhtml
@@ -0,0 +1,8 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>invalid empty value for a/@name</title>
+</head>
+<body>
+<a name=''></a>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/address/029-isvalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/address/029-isvalid.xhtml
new file mode 100644
index 00000000000..04c981450a7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/address/029-isvalid.xhtml
@@ -0,0 +1,15 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>&lt;address&gt;</title>
+</head>
+<body>
+ <!-- is block -->
+ <address class="class" id="id" xml:lang="en">text</address>
+
+ <!-- can contain interactive -->
+ <address><a>text</a></address>
+
+ <!-- can contain strict inline -->
+ <address>text <em>elem</em></address>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/base/001-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/base/001-novalid.xhtml
new file mode 100644
index 00000000000..917a9821171
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/base/001-novalid.xhtml
@@ -0,0 +1,9 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<base/>
+<title>base element missing href and target attribute</title>
+</head>
+<body>
+<iframe sandbox="aLLOw-TOp-nAVIGAtion"></iframe>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/blockquote/028-isvalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/blockquote/028-isvalid.xhtml
new file mode 100644
index 00000000000..8b61d25a2e1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/blockquote/028-isvalid.xhtml
@@ -0,0 +1,16 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>&lt;blockquote&gt;</title>
+</head>
+<body>
+ <!-- is block, contains blocks -->
+ <blockquote cite="url" class="class" id="id" xml:lang="en">
+ <h2>header</h2>
+ <p>text</p>
+ <p>text2</p>
+ </blockquote>
+
+ <!-- can contain interactive -->
+ <blockquote><p><a>text</a></p></blockquote>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/code/010-isvalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/code/010-isvalid.xhtml
new file mode 100644
index 00000000000..ed6aa2c4b48
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/code/010-isvalid.xhtml
@@ -0,0 +1,20 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>&lt;code&gt;</title>
+</head>
+<body>
+ <!-- is structured inline -->
+ <p><code class="class" xml:lang="en">text</code></p>
+
+ <!-- is strictly inline -->
+ <p><dfn><code class="class" xml:lang="en">text</code></dfn></p>
+
+ <!-- can be empty -->
+ <p>text <code></code></p>
+ <p>text <dfn><code></code></dfn></p>
+
+ <!-- can contain interactive -->
+ <p><code><a>text</a></code></p>
+ <p><dfn><code><a>text</a></code></dfn></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/del/041-isvalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/del/041-isvalid.xhtml
new file mode 100644
index 00000000000..3d9fc243c63
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/del/041-isvalid.xhtml
@@ -0,0 +1,32 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>&lt;del&gt;</title>
+</head>
+<body>
+ <!-- can contain inline while in inline context -->
+ <p>paragraph
+ <del>
+ <em>some</em>
+ </del>
+ </p>
+
+ <!-- can contain strictly inline while in strictly inline context -->
+ <p><dfn>strictly inline
+ <del>
+ <em>text</em>
+ </del>
+ </dfn></p>
+
+ <!-- can contain interactive if ancestor does not forbid it -->
+ <p>paragraph
+ <del>
+ <a>link</a>
+ </del>
+ </p>
+ <p><dfn>strictly inline
+ <del>
+ <a>link</a>
+ </del>
+ </dfn></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/dialog/001-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/dialog/001-novalid.xhtml
new file mode 100644
index 00000000000..dc4d58924d9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/dialog/001-novalid.xhtml
@@ -0,0 +1,13 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>&lt;dialog&gt;</title>
+</head>
+<body>
+<dialog>
+<dt>Foo</dt>
+<dt>Bar</dt>
+<dd><p>Blah</p></dd>
+<dd><p>Bleh</p></dd>
+</dialog>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/dl/032-isvalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/dl/032-isvalid.xhtml
new file mode 100644
index 00000000000..e943d5e21f9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/dl/032-isvalid.xhtml
@@ -0,0 +1,53 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>Definition List: &lt;dl&gt; &lt;dt&gt; &lt;dd&gt;</title>
+</head>
+<body>
+ <!-- is block -->
+ <dl class="class" id="id" xml:lang="en">
+ <dt class="class" id="id2" xml:lang="en">text</dt>
+ <dd class="class" id="id3" xml:lang="en">text</dd>
+ </dl>
+
+ <!-- can be empty -->
+ <dl></dl>
+ <dl>
+ <dt></dt>
+ <dd></dd>
+ </dl>
+
+ <!-- multiple groups, but always (dt+,dd+) -->
+ <dl>
+ <dt>text</dt>
+ <dd>more text</dd>
+ <dt>text</dt>
+ <dd>more text</dd>
+ <dd>more text</dd>
+ <dt>text</dt>
+ <dt>text</dt>
+ <dt>text</dt>
+ <dd>more text</dd>
+ </dl>
+
+ <!-- dd can contain structured inline, dt strictly inline -->
+ <dl>
+ <dt>some <em>text</em></dt>
+ <dd>more <pre>text</pre></dd>
+ </dl>
+
+ <!-- dd can contain blocks -->
+ <dl>
+ <dt>some <em>text</em></dt>
+ <dd>
+ <p>more</p>
+ <p>text</p>
+ </dd>
+ </dl>
+
+ <!-- can contain interactive -->
+ <dl>
+ <dt>some <a>text</a></dt>
+ <dd>more <a>text</a></dd>
+ </dl>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/em/006-isvalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/em/006-isvalid.xhtml
new file mode 100644
index 00000000000..f3c1e8da574
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/em/006-isvalid.xhtml
@@ -0,0 +1,21 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>&lt;em&gt;</title>
+</head>
+<body>
+ <!-- is structured inline -->
+ <p><em class="class" xml:lang="en">text</em></p>
+
+ <!-- is strictly inline -->
+ <p><dfn><em class="class" xml:lang="en">text</em></dfn></p>
+
+ <!-- can be empty -->
+ <p>text <em></em></p>
+ <p>text <dfn><em></em></dfn></p>
+
+ <!-- can contain interactive -->
+ <p><em><a>text</a></em></p>
+ <p><dfn><em><a>text</a></em></dfn></p>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/embed/001-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/embed/001-novalid.xhtml
new file mode 100644
index 00000000000..9c4d55879ac
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/embed/001-novalid.xhtml
@@ -0,0 +1,8 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>element embed with bad height value</title>
+</head>
+<body>
+<embed height="20%"/>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/embed/002-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/embed/002-novalid.xhtml
new file mode 100644
index 00000000000..08e4e1935dd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/embed/002-novalid.xhtml
@@ -0,0 +1,8 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>element embed with bad type value</title>
+</head>
+<body>
+<embed type="foo"/>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/embed/003-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/embed/003-novalid.xhtml
new file mode 100644
index 00000000000..a635e11cfb9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/embed/003-novalid.xhtml
@@ -0,0 +1,8 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>element embed with bad width value</title>
+</head>
+<body>
+<embed width="20%"/>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/figure/002-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/figure/002-novalid.xhtml
new file mode 100644
index 00000000000..7c4681dd934
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/figure/002-novalid.xhtml
@@ -0,0 +1,12 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>Element before figcaption and text after</title>
+</head>
+<body>
+<figure>
+<img src='foo' alt='bar'/>
+<figcaption>Bar</figcaption>
+text
+</figure>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/figure/101-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/figure/101-novalid.xhtml
new file mode 100644
index 00000000000..213644e19d3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/figure/101-novalid.xhtml
@@ -0,0 +1,12 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>Text before legend and element after</title>
+</head>
+<body>
+<figure>
+text
+<figcaption>Bar</figcaption>
+<img src='foo' alt='bar'/>
+</figure>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/figure/102-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/figure/102-novalid.xhtml
new file mode 100644
index 00000000000..7c4681dd934
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/figure/102-novalid.xhtml
@@ -0,0 +1,12 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>Element before figcaption and text after</title>
+</head>
+<body>
+<figure>
+<img src='foo' alt='bar'/>
+<figcaption>Bar</figcaption>
+text
+</figure>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/figure/103-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/figure/103-novalid.xhtml
new file mode 100644
index 00000000000..1b6506c1672
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/figure/103-novalid.xhtml
@@ -0,0 +1,12 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>Text before figcaption and text after</title>
+</head>
+<body>
+<figure>
+text
+<figcaption>Bar</figcaption>
+text
+</figure>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/figure/104-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/figure/104-novalid.xhtml
new file mode 100644
index 00000000000..ca4c2ae615f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/figure/104-novalid.xhtml
@@ -0,0 +1,12 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>Element before figcaption and element after</title>
+</head>
+<body>
+<figure>
+<img src='foo' alt='bar'/>
+<figcaption>Bar</figcaption>
+<img src='foo' alt='bar'/>
+</figure>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/figure/304-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/figure/304-novalid.xhtml
new file mode 100644
index 00000000000..ca4c2ae615f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/figure/304-novalid.xhtml
@@ -0,0 +1,12 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>Element before figcaption and element after</title>
+</head>
+<body>
+<figure>
+<img src='foo' alt='bar'/>
+<figcaption>Bar</figcaption>
+<img src='foo' alt='bar'/>
+</figure>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/footer/001-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/footer/001-novalid.xhtml
new file mode 100644
index 00000000000..9a503cf53b6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/footer/001-novalid.xhtml
@@ -0,0 +1,10 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>"footer" with "footer" descendant</title>
+</head>
+<body>
+<footer>
+<footer></footer>
+</footer>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/footer/003-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/footer/003-novalid.xhtml
new file mode 100644
index 00000000000..b08041b74f9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/footer/003-novalid.xhtml
@@ -0,0 +1,10 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>"footer" with "header" descendant</title>
+</head>
+<body>
+<footer>
+<header></header>
+</footer>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/header/001-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/header/001-novalid.xhtml
new file mode 100644
index 00000000000..8ff80389c6e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/header/001-novalid.xhtml
@@ -0,0 +1,10 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>"header" with "footer" descendant</title>
+</head>
+<body>
+<header>
+<footer></footer>
+</header>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/header/002-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/header/002-novalid.xhtml
new file mode 100644
index 00000000000..bd69cf84b05
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/header/002-novalid.xhtml
@@ -0,0 +1,10 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>"header" with "header" descendant</title>
+</head>
+<body>
+<header>
+<header></header>
+</header>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/iframe/042-isvalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/iframe/042-isvalid.xhtml
new file mode 100644
index 00000000000..236e5d069e4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/iframe/042-isvalid.xhtml
@@ -0,0 +1,19 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>&lt;iframe&gt;</title>
+</head>
+<body>
+ <!-- is structured inline -->
+ <p><iframe
+ src="uri"
+ class="class"
+ xml:lang="en"></iframe></p>
+
+ <!-- is strictly inline -->
+ <p><dfn><iframe
+ src="uri"
+ class="class"
+ xml:lang="en"></iframe></dfn></p>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/iframe/042-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/iframe/042-novalid.xhtml
new file mode 100644
index 00000000000..6977dfeef08
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/iframe/042-novalid.xhtml
@@ -0,0 +1,8 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>The iframe element must be empty in XML documents</title>
+</head>
+<body>
+ <iframe>text</iframe>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/img/003-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/img/003-novalid.xhtml
new file mode 100644
index 00000000000..7cc3479b6cb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/img/003-novalid.xhtml
@@ -0,0 +1,8 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>invalid ismap</title>
+</head>
+<body>
+ <p><img src='foo' alt='bar' ismap='ismap'/></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/img/004-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/img/004-novalid.xhtml
new file mode 100644
index 00000000000..a771247e3cc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/img/004-novalid.xhtml
@@ -0,0 +1,9 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>invalid img@usemap as descendant of &lt;a> element</title>
+</head>
+<body>
+ <map name="bar"/>
+ <p id="foo"><a href="#foo"><img src="http://www.w3.org/Icons/w3c_main.png" usemap="#bar" alt=""/></a></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/img/043-isvalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/img/043-isvalid.xhtml
new file mode 100644
index 00000000000..21a73c76108
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/img/043-isvalid.xhtml
@@ -0,0 +1,29 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>&lt;img&gt;</title>
+</head>
+<body>
+ <!-- is structured inline -->
+ <p><a href='foo'><img
+ src="url"
+ alt="text"
+ width="42"
+ height="095"
+ ismap="ismap"
+ class="class"
+ xml:lang="en"></img></a></p>
+
+ <!-- is strictly inline -->
+ <p><a href='foo'><dfn><img
+ src="url"
+ alt="text"
+ width="42"
+ height="095"
+ ismap="ismap"
+ class="class"
+ xml:lang="en"></img></dfn></a></p>
+
+ <!-- src and alt are required, others optional -->
+ <p><img src="ur" alt="text"></img></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/img/051-isvalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/img/051-isvalid.xhtml
new file mode 100644
index 00000000000..660051a3ba9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/img/051-isvalid.xhtml
@@ -0,0 +1,8 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>img with 0 value for width and height</title>
+</head>
+<body>
+<img src="url" width="0" height="0" alt="bar"/>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/img/051-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/img/051-novalid.xhtml
new file mode 100644
index 00000000000..5ba54ab82a6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/img/051-novalid.xhtml
@@ -0,0 +1,8 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>img with 0 value for width and height</title>
+</head>
+<body>
+<img src="url" width="-1" height="-1"/>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/img/052-isvalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/img/052-isvalid.xhtml
new file mode 100644
index 00000000000..0f7fe87022b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/img/052-isvalid.xhtml
@@ -0,0 +1,8 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>img with positive values for width and height</title>
+</head>
+<body>
+<img src="url" width="10" height="10" alt="bar"/>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/img/302-isvalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/img/302-isvalid.xhtml
new file mode 100644
index 00000000000..400af64899b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/img/302-isvalid.xhtml
@@ -0,0 +1,9 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>valid img@usemap</title>
+</head>
+<body>
+ <map name="bar"/>
+ <p><img src="foo.png" usemap="#bar" alt="bar"/></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/input/003-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/input/003-novalid.xhtml
new file mode 100644
index 00000000000..b098e9cfa88
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/input/003-novalid.xhtml
@@ -0,0 +1,9 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>valid input/@list reference to datalist/@id</title>
+</head>
+<body>
+<datalist id="foo"></datalist>
+<input type="text" list="bar"></input>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/ins/040-isvalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/ins/040-isvalid.xhtml
new file mode 100644
index 00000000000..ef6da600ff2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/ins/040-isvalid.xhtml
@@ -0,0 +1,25 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>&lt;ins&gt;</title>
+</head>
+<body>
+ <!-- can contain strictly inline while in strictly inline context -->
+ <p><dfn>strictly inline
+ <ins>
+ <em>text</em>
+ </ins>
+ </dfn></p>
+
+ <!-- can contain interactive if ancestor does not forbid it -->
+ <p>paragraph
+ <ins>
+ <a>link</a>
+ </ins>
+ </p>
+ <p><dfn>strictly inline
+ <ins>
+ <a>link</a>
+ </ins>
+ </dfn></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/054-isvalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/054-isvalid.xhtml
new file mode 100644
index 00000000000..b7bcb2021e1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/054-isvalid.xhtml
@@ -0,0 +1,8 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>empty keygen with no attributes</title>
+</head>
+<body>
+<keygen></keygen>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/054-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/054-novalid.xhtml
new file mode 100644
index 00000000000..d7fb2a61b5a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/054-novalid.xhtml
@@ -0,0 +1,8 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>no-void keygen</title>
+</head>
+<body>
+<keygen>foo</keygen>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/055-isvalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/055-isvalid.xhtml
new file mode 100644
index 00000000000..95cf40f3000
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/055-isvalid.xhtml
@@ -0,0 +1,8 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>keygen with "challenge" attribute</title>
+</head>
+<body>
+<keygen challenge="123456"/>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/056-isvalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/056-isvalid.xhtml
new file mode 100644
index 00000000000..979638cf6b5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/056-isvalid.xhtml
@@ -0,0 +1,8 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>keygen with "keytype" attribute</title>
+</head>
+<body>
+<keygen keytype="rsa"/>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/056-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/056-novalid.xhtml
new file mode 100644
index 00000000000..093af9bbeda
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/056-novalid.xhtml
@@ -0,0 +1,8 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>keygen with invalid value for "keytype" attribute</title>
+</head>
+<body>
+<keygen keytype="dsa"/>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/057-isvalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/057-isvalid.xhtml
new file mode 100644
index 00000000000..9a42f1f283b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/057-isvalid.xhtml
@@ -0,0 +1,8 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>keygen with empty "challenge" attribute</title>
+</head>
+<body>
+<keygen challenge=""/>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/057-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/057-novalid.xhtml
new file mode 100644
index 00000000000..7421a0ef6e6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/057-novalid.xhtml
@@ -0,0 +1,8 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>keygen with invalid empty "keytype" attribute</title>
+</head>
+<body>
+<keygen keytype=""/>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/058-isvalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/058-isvalid.xhtml
new file mode 100644
index 00000000000..3a4b6c38fd7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/058-isvalid.xhtml
@@ -0,0 +1,10 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>keygen as &lt;label descendant</title>
+</head>
+<body>
+<label for="foo">
+<keygen id="foo"/>
+</label>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/058-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/058-novalid.xhtml
new file mode 100644
index 00000000000..943fbd16f9f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/058-novalid.xhtml
@@ -0,0 +1,10 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>keygen as &lt;label descendant, with wrong ID</title>
+</head>
+<body>
+<label for="foo">
+<keygen id="bar"/>
+</label>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/059-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/059-novalid.xhtml
new file mode 100644
index 00000000000..fff964f990f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/059-novalid.xhtml
@@ -0,0 +1,10 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>keygen as &lt;label descendant, with no ID</title>
+</head>
+<body>
+<label for="foo">
+<keygen/>
+</label>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/060-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/060-novalid.xhtml
new file mode 100644
index 00000000000..0c0003a0916
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/060-novalid.xhtml
@@ -0,0 +1,11 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>keygen as redundant &lt;label descendant</title>
+</head>
+<body>
+<label for="foo">
+<input id="foo"/>
+<keygen/>
+</label>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/061-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/061-novalid.xhtml
new file mode 100644
index 00000000000..d6f7be84034
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/061-novalid.xhtml
@@ -0,0 +1,10 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>keygen as an invalid &lt;a> descendant</title>
+</head>
+<body>
+<a href="url">
+<keygen/>
+</a>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/154-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/154-novalid.xhtml
new file mode 100644
index 00000000000..d7fb2a61b5a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/154-novalid.xhtml
@@ -0,0 +1,8 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>no-void keygen</title>
+</head>
+<body>
+<keygen>foo</keygen>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/157-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/157-novalid.xhtml
new file mode 100644
index 00000000000..7421a0ef6e6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/157-novalid.xhtml
@@ -0,0 +1,8 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>keygen with invalid empty "keytype" attribute</title>
+</head>
+<body>
+<keygen keytype=""/>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/359-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/359-novalid.xhtml
new file mode 100644
index 00000000000..fff964f990f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/359-novalid.xhtml
@@ -0,0 +1,10 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>keygen as &lt;label descendant, with no ID</title>
+</head>
+<body>
+<label for="foo">
+<keygen/>
+</label>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/360-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/360-novalid.xhtml
new file mode 100644
index 00000000000..0c0003a0916
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/360-novalid.xhtml
@@ -0,0 +1,11 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>keygen as redundant &lt;label descendant</title>
+</head>
+<body>
+<label for="foo">
+<input id="foo"/>
+<keygen/>
+</label>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/361-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/361-novalid.xhtml
new file mode 100644
index 00000000000..d6f7be84034
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/keygen/361-novalid.xhtml
@@ -0,0 +1,10 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>keygen as an invalid &lt;a> descendant</title>
+</head>
+<body>
+<a href="url">
+<keygen/>
+</a>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/link/001-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/link/001-novalid.xhtml
new file mode 100644
index 00000000000..cf6cd35e7a6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/link/001-novalid.xhtml
@@ -0,0 +1,8 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>link element missing href attribute</title>
+<link rel="stylesheet"/>
+</head>
+<body>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/map/048-isvalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/map/048-isvalid.xhtml
new file mode 100644
index 00000000000..5b5ed705941
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/map/048-isvalid.xhtml
@@ -0,0 +1,21 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>&lt;map&gt;</title>
+</head>
+<body>
+ <!-- is block, contains blocks and <area> -->
+ <map class="class" id="id" name="id" xml:lang="en">
+ <h2>header</h2>
+ <p><area alt="text" coords="1,2,3,4" href='foo'></area>p</p>
+ <p>text</p>
+ <p><area alt="text" coords="3,2,5,4" href='foo'></area>p</p>
+ <p>text2</p>
+ </map>
+
+ <!-- can contain interactive -->
+ <map id='foo' name='foo'>
+ <p><a>text</a></p>
+ <p><area alt="text" coords="3,2,5,4" href='foo'></area>p</p>
+ </map>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/mark/009-isvalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/mark/009-isvalid.xhtml
new file mode 100644
index 00000000000..ac1328d74e3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/mark/009-isvalid.xhtml
@@ -0,0 +1,21 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>&lt;m&gt;</title>
+</head>
+<body>
+ <!-- is structured inline -->
+ <p><mark class="class" xml:lang="en">text</mark></p>
+
+ <!-- is strictly inline -->
+ <p><dfn><mark class="class" xml:lang="en">text</mark></dfn></p>
+
+ <!-- can be empty -->
+ <p>text <mark></mark></p>
+ <p>text <dfn><mark></mark></dfn></p>
+
+ <!-- can contain interactive -->
+ <p><mark><a>text</a></mark></p>
+ <p><dfn><mark><a>text</a></mark></dfn></p>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/menu/001-haswarn.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/menu/001-haswarn.xhtml
new file mode 100644
index 00000000000..acce02af469
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/menu/001-haswarn.xhtml
@@ -0,0 +1,21 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>valid contextmenus</title>
+</head>
+<body>
+ <menu id='foo'>
+ <menuitem id='com' label='The Command'/>
+ </menu>
+ <menu id='bar'>
+ <menuitem id='com2' label='The Command'/>
+ </menu>
+ <menu id='foo2'>
+ <menuitem id='com3' label='The Command'/>
+ </menu>
+ <menu id='bar2'>
+ <menuitem id='com4' label='The Command'/>
+ </menu>
+ <p contextmenu='foo'>foo</p>
+ <p contextmenu='bar'>bar</p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/menu/001-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/menu/001-novalid.xhtml
new file mode 100644
index 00000000000..06e0ca28123
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/menu/001-novalid.xhtml
@@ -0,0 +1,14 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>invalid contextmenu</title>
+</head>
+<body>
+ <menu id='foo'>
+ <menuitem id='com' label='The Command'/>
+ </menu>
+ <menu id='bar'>
+ <menuitem id='com2' label='The Command'/>
+ </menu>
+ <p contextmenu='baz'>foo</p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/meter/002-isvalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/meter/002-isvalid.xhtml
new file mode 100644
index 00000000000..efb4dfa5756
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/meter/002-isvalid.xhtml
@@ -0,0 +1,26 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>&lt;t&gt;</title>
+</head>
+<body>
+ <!-- is structured inline -->
+ <p><meter value='0.5'>text</meter></p>
+
+ <!-- is strictly inline -->
+ <p><dfn><meter value='0.5'>text</meter></dfn></p>
+
+ <!-- can be empty -->
+ <p>text <meter value='0.5'></meter></p>
+ <p>text <dfn><meter value='0.5'></meter></dfn></p>
+
+ <!-- can contain interactive -->
+ <p><meter value='0.5'><a>text</a></meter></p>
+ <p><dfn><meter value='0.5'><a>text</a></meter></dfn></p>
+
+ <!-- textContent -->
+ <!-- * <p><meter>text 1.88 text 33.881 text</meter></p> -->
+ <!-- * <p><meter>text 1.88 % text</meter></p> -->
+ <!-- * <p><meter>text 1.88 &#x2031; text</meter></p> -->
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/meter/003-isvalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/meter/003-isvalid.xhtml
new file mode 100644
index 00000000000..8149b2fa62f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/meter/003-isvalid.xhtml
@@ -0,0 +1,8 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>valid meter</title>
+</head>
+<body>
+<meter min='0.0' value='0.1' low='0.2' optimum='0.3' high='0.4' max='0.5'/>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/meter/010-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/meter/010-novalid.xhtml
new file mode 100644
index 00000000000..cbf6b0909a5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/meter/010-novalid.xhtml
@@ -0,0 +1,8 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>invalid meter</title>
+</head>
+<body>
+<meter min='0.2' value='0.1'/>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/meter/011-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/meter/011-novalid.xhtml
new file mode 100644
index 00000000000..32b5eb91463
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/meter/011-novalid.xhtml
@@ -0,0 +1,8 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>invalid meter</title>
+</head>
+<body>
+<meter min='0.3' low='0.2'/>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/meter/012-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/meter/012-novalid.xhtml
new file mode 100644
index 00000000000..8372b78b8eb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/meter/012-novalid.xhtml
@@ -0,0 +1,8 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>invalid meter</title>
+</head>
+<body>
+<meter min='0.4' optimum='0.3'/>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/meter/110-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/meter/110-novalid.xhtml
new file mode 100644
index 00000000000..cbf6b0909a5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/meter/110-novalid.xhtml
@@ -0,0 +1,8 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>invalid meter</title>
+</head>
+<body>
+<meter min='0.2' value='0.1'/>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/meter/312-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/meter/312-novalid.xhtml
new file mode 100644
index 00000000000..8372b78b8eb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/meter/312-novalid.xhtml
@@ -0,0 +1,8 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>invalid meter</title>
+</head>
+<body>
+<meter min='0.4' optimum='0.3'/>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/object/001-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/object/001-novalid.xhtml
new file mode 100644
index 00000000000..0869f60e382
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/object/001-novalid.xhtml
@@ -0,0 +1,9 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta charset="utf-8"/>
+<title>object element missing data and type attributes</title>
+</head>
+<body>
+<object></object>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/object/044-isvalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/object/044-isvalid.xhtml
new file mode 100644
index 00000000000..4669fe6e6bd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/object/044-isvalid.xhtml
@@ -0,0 +1,75 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>&lt;object&gt;</title>
+</head>
+<body>
+ <map name="idref"></map>
+ <!-- is structured inline -->
+ <p><object
+ data="uri"
+ height="40"
+ usemap="#idref"
+ width="40"
+ class="class"
+ xml:lang="en"></object></p>
+
+ <!-- is strictly inline -->
+ <p><dfn><object
+ data="uri"
+ height="40"
+ usemap="#idref"
+ width="40"
+ class="class"
+ xml:lang="en"></object></dfn></p>
+
+ <!-- can contain inline while in inline context, but param must come first -->
+ <p>paragraph
+ <object data='bar.ogg'>
+ <em>some</em>
+ </object>
+ </p>
+ <p>paragraph
+ <object data='bar.ogg'>
+ <param name="foo" value='bar'></param><param name="bar" value='foo'></param>
+ <em>some</em>
+ </object>
+ </p>
+
+ <!-- can contain strictly inline while in strictly inline context, but param must come first -->
+ <p><dfn>strictly inline
+ <object data='bar.ogg'>
+ <em>text</em>
+ </object>
+ </dfn></p>
+ <p><dfn>strictly inline
+ <object data='bar.ogg'>
+ <param name="foo" value='bar'></param><param name="bar" value='foo'></param>
+ <em>text</em>
+ </object>
+ </dfn></p>
+
+ <!-- can contain interactive if ancestor does not forbid it, but param must come first -->
+ <p>paragraph
+ <object data='bar.ogg'>
+ <a>link</a>
+ </object>
+ </p>
+ <p>paragraph
+ <object data='bar.ogg'>
+ <param name="foo" value='bar'></param><param name="bar" value='foo'></param>
+ <a>link</a>
+ </object>
+ </p>
+ <p><dfn>strictly inline
+ <object data='foo.mov'>
+ <a>link</a>
+ </object>
+ </dfn></p>
+ <p><dfn>strictly inline
+ <object type='text/plain'>
+ <param name="foo" value='bar'></param><param name="bar" value='foo'></param>
+ <a>link</a>
+ </object>
+ </dfn></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/ol/031-isvalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/ol/031-isvalid.xhtml
new file mode 100644
index 00000000000..341b94d576e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/ol/031-isvalid.xhtml
@@ -0,0 +1,36 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>Ordered List: &lt;ol&gt; &lt;li&gt;</title>
+</head>
+<body>
+ <!-- is block -->
+ <ol class="class" id="id" xml:lang="en" start="05">
+ <li class="class" id="id2" xml:lang="en" value="9">text</li>
+ </ol>
+
+ <!-- can be empty -->
+ <ol></ol>
+ <ol>
+ <li></li>
+ <li></li>
+ </ol>
+
+ <!-- can contain structured inline -->
+ <ol>
+ <li>some <em>text</em>
+ <pre>more text</pre>
+ </li>
+ </ol>
+
+ <!-- can contain blocks -->
+ <ol>
+ <li>
+ <p>some</p>
+ <p>text</p>
+ </li>
+ </ol>
+
+ <!-- can contain interactive -->
+ <ol><li><a>text</a></li></ol>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/p/025-isvalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/p/025-isvalid.xhtml
new file mode 100644
index 00000000000..a2b95280b22
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/p/025-isvalid.xhtml
@@ -0,0 +1,12 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>&lt;p&gt;</title>
+</head>
+<body>
+ <!-- is block -->
+ <p class="class" id="id" xml:lang="en">text</p>
+
+ <!-- can contain interactive -->
+ <p><a>text</a></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/pre/027-isvalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/pre/027-isvalid.xhtml
new file mode 100644
index 00000000000..6239c17dcaf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/pre/027-isvalid.xhtml
@@ -0,0 +1,15 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>&lt;pre&gt;</title>
+</head>
+<body>
+ <!-- is block -->
+ <pre class="class" id="id" xml:lang="en">text</pre>
+
+ <!-- can contain interactive -->
+ <pre><a>text</a></pre>
+
+ <!-- can contain strictly inline -->
+ <pre>text <em>elem</em></pre>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/progress/002-isvalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/progress/002-isvalid.xhtml
new file mode 100644
index 00000000000..64af31ef845
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/progress/002-isvalid.xhtml
@@ -0,0 +1,10 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>valid progress</title>
+</head>
+<body>
+<progress value='0.5'/>
+<progress value='2.05' max='2.1' />
+<progress value='2.05' max='2.05' />
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/progress/008-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/progress/008-novalid.xhtml
new file mode 100644
index 00000000000..1c5475b85d6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/progress/008-novalid.xhtml
@@ -0,0 +1,8 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>invalid progress</title>
+</head>
+<body>
+<progress value='1.1'/>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/progress/009-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/progress/009-novalid.xhtml
new file mode 100644
index 00000000000..4837071a653
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/progress/009-novalid.xhtml
@@ -0,0 +1,8 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>invalid progress</title>
+</head>
+<body>
+<progress value='0.9' max='0.5'/>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/progress/108-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/progress/108-novalid.xhtml
new file mode 100644
index 00000000000..1c5475b85d6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/progress/108-novalid.xhtml
@@ -0,0 +1,8 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>invalid progress</title>
+</head>
+<body>
+<progress value='1.1'/>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/progress/309-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/progress/309-novalid.xhtml
new file mode 100644
index 00000000000..4837071a653
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/progress/309-novalid.xhtml
@@ -0,0 +1,8 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>invalid progress</title>
+</head>
+<body>
+<progress value='0.9' max='0.5'/>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/q/013-isvalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/q/013-isvalid.xhtml
new file mode 100644
index 00000000000..f2bce489052
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/q/013-isvalid.xhtml
@@ -0,0 +1,20 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>&lt;q&gt;</title>
+</head>
+<body>
+ <!-- is structured inline -->
+ <p><q cite="url" class="class" xml:lang="en">text</q></p>
+
+ <!-- is strictly inline -->
+ <p><dfn><q cite="url" class="class" xml:lang="en">text</q></dfn></p>
+
+ <!-- can be empty -->
+ <p>text <q></q></p>
+ <p>text <dfn><q></q></dfn></p>
+
+ <!-- can contain interactive -->
+ <p><q><a>text</a></q></p>
+ <p><dfn><q><a>text</a></q></dfn></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/ruby/001-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/ruby/001-novalid.xhtml
new file mode 100644
index 00000000000..9ca30a58544
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/ruby/001-novalid.xhtml
@@ -0,0 +1,8 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>ruby element missing rt child</title>
+</head>
+<body>
+<ruby></ruby>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/ruby/002-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/ruby/002-novalid.xhtml
new file mode 100644
index 00000000000..139f5d7393d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/ruby/002-novalid.xhtml
@@ -0,0 +1,8 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>ruby element missing rt child</title>
+</head>
+<body>
+<ruby><rt></rt><rp></rp><rp></rp></ruby>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/samp/011-isvalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/samp/011-isvalid.xhtml
new file mode 100644
index 00000000000..70683839215
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/samp/011-isvalid.xhtml
@@ -0,0 +1,20 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>&lt;samp&gt;</title>
+</head>
+<body>
+ <!-- is structured inline -->
+ <p><samp class="class" xml:lang="en">text</samp></p>
+
+ <!-- is strictly inline -->
+ <p><dfn><samp class="class" xml:lang="en">text</samp></dfn></p>
+
+ <!-- can be empty -->
+ <p>text <samp></samp></p>
+ <p>text <dfn><samp></samp></dfn></p>
+
+ <!-- can contain interactive -->
+ <p><samp><a>text</a></samp></p>
+ <p><dfn><samp><a>text</a></samp></dfn></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/script/001-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/script/001-novalid.xhtml
new file mode 100644
index 00000000000..dd911944f8b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/script/001-novalid.xhtml
@@ -0,0 +1,8 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>the "language" attribute is obsolete</title>
+</head>
+<body>
+<script language="vbscript"></script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/span/014-isvalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/span/014-isvalid.xhtml
new file mode 100644
index 00000000000..d35d50680f4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/span/014-isvalid.xhtml
@@ -0,0 +1,20 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>&lt;span&gt;</title>
+</head>
+<body>
+ <!-- is structured inline -->
+ <p><span class="class" xml:lang="en">text</span></p>
+
+ <!-- is strictly inline -->
+ <p><dfn><span class="class" xml:lang="en">text</span></dfn></p>
+
+ <!-- can be empty -->
+ <p>text <span></span></p>
+ <p>text <dfn><span></span></dfn></p>
+
+ <!-- can contain interactive -->
+ <p><span><a>text</a></span></p>
+ <p><dfn><span><a>text</a></span></dfn></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/strong/007-isvalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/strong/007-isvalid.xhtml
new file mode 100644
index 00000000000..e048214968a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/strong/007-isvalid.xhtml
@@ -0,0 +1,20 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>&lt;strong&gt;</title>
+</head>
+<body>
+ <!-- is structured inline -->
+ <p><strong class="class" xml:lang="en">text</strong></p>
+
+ <!-- is strictly inline -->
+ <p><dfn><strong class="class" xml:lang="en">text</strong></dfn></p>
+
+ <!-- can be empty -->
+ <p>text <strong></strong></p>
+ <p>text <dfn><strong></strong></dfn></p>
+
+ <!-- can contain interactive -->
+ <p><strong><a>text</a></strong></p>
+ <p><dfn><strong><a>text</a></strong></dfn></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/strong/008-isvalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/strong/008-isvalid.xhtml
new file mode 100644
index 00000000000..1ecc22f8334
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/strong/008-isvalid.xhtml
@@ -0,0 +1,20 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>&lt;small&gt;</title>
+</head>
+<body>
+ <!-- is structured inline -->
+ <p><small class="class" xml:lang="en">text</small></p>
+
+ <!-- is strictly inline -->
+ <p><dfn><small class="class" xml:lang="en">text</small></dfn></p>
+
+ <!-- can be empty -->
+ <p>text <small></small></p>
+ <p>text <dfn><small></small></dfn></p>
+
+ <!-- can contain interactive -->
+ <p><small><a>text</a></small></p>
+ <p><dfn><small><a>text</a></small></dfn></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/table/201-isvalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/table/201-isvalid.xhtml
new file mode 100644
index 00000000000..57514cfb1da
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/table/201-isvalid.xhtml
@@ -0,0 +1,13 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Conforming HTML table</title>
+</head>
+<body>
+<table>
+<tbody>
+<tr><td>1</td><td>2</td></tr>
+<tr><td>3</td><td>4</td></tr>
+</tbody>
+</table>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/table/201-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/table/201-novalid.xhtml
new file mode 100644
index 00000000000..36e0080cfe9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/table/201-novalid.xhtml
@@ -0,0 +1,11 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Non-Conforming HTML table (rowspan past end of row group)</title>
+</head>
+<body>
+<table>
+<tbody><tr><td>1</td><td rowspan="2">2</td><td>3</td><td>4</td></tr></tbody>
+<tbody><tr><td>5</td><td>6</td><td>7</td></tr></tbody>
+</table>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/table/202-isvalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/table/202-isvalid.xhtml
new file mode 100644
index 00000000000..8cd628ea290
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/table/202-isvalid.xhtml
@@ -0,0 +1,11 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Conforming HTML table</title>
+</head>
+<body>
+<table>
+<tr><td colspan='2'>1</td><td>2</td></tr>
+<tr><td>3</td><td colspan='2'>4</td></tr>
+</table>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/table/202-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/table/202-novalid.xhtml
new file mode 100644
index 00000000000..45df2d36bd6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/table/202-novalid.xhtml
@@ -0,0 +1,11 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Non-Conforming HTML table (Cell 5 overlaps cell 2)</title>
+</head>
+<body>
+<table>
+<tr><td>1</td><td rowspan="2">2</td><td>3</td><td>4</td></tr>
+<tr><td colspan="2">5</td></tr>
+</table>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/table/203-isvalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/table/203-isvalid.xhtml
new file mode 100644
index 00000000000..6db28a81e15
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/table/203-isvalid.xhtml
@@ -0,0 +1,12 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Conforming HTML table</title>
+</head>
+<body>
+<table>
+<tr><td rowspan='2'>1</td><td>2</td></tr>
+<tr><td rowspan='2'>3</td></tr>
+<tr><td>4</td></tr>
+</table>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/table/203-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/table/203-novalid.xhtml
new file mode 100644
index 00000000000..1d3ab03a484
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/table/203-novalid.xhtml
@@ -0,0 +1,11 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Non-Conforming HTML table (no cell starts in 3rd column)</title>
+</head>
+<body>
+<table>
+<tr><td colspan='3'>1</td><td>2</td></tr>
+<tr><td>3</td><td colspan='3'>4</td></tr>
+</table>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/table/204-isvalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/table/204-isvalid.xhtml
new file mode 100644
index 00000000000..0ef76ca45e3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/table/204-isvalid.xhtml
@@ -0,0 +1,8892 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>Big Table</title>
+</head>
+<body>
+<table>
+ <tbody>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td colspan="1" rowspan="0"></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td colspan="30" rowspan="5"></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td colspan="4" rowspan="9"></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td colspan="57" rowspan="1"></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td colspan="3" rowspan="5"></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td colspan="6" rowspan="6"></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td colspan="20" rowspan="6"></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td colspan="13" rowspan="3"></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td colspan="9" rowspan="10"></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td colspan="19" rowspan="4"></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td colspan="13" rowspan="7"></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td colspan="8" rowspan="8"></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td colspan="15" rowspan="4"></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td colspan="9" rowspan="8"></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td colspan="22" rowspan="2"></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td colspan="17" rowspan="5"></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td colspan="14" rowspan="7"></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td colspan="2" rowspan="14"></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td colspan="13" rowspan="6"></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
+ </tbody>
+</table>
+</body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/table/204-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/table/204-novalid.xhtml
new file mode 100644
index 00000000000..4c38ca263de
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/table/204-novalid.xhtml
@@ -0,0 +1,13 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Non-Conforming HTML table (3rd row has no cells beginning in it)</title>
+</head>
+<body>
+<table>
+<tr><td rowspan='3'>1</td><td>2</td></tr>
+<tr><td rowspan='3'>3</td></tr>
+<tr></tr>
+<tr><td>4</td></tr>
+</table>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/table/205-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/table/205-novalid.xhtml
new file mode 100644
index 00000000000..a6515e851c0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/table/205-novalid.xhtml
@@ -0,0 +1,13 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Conforming HTML table</title>
+</head>
+<body>
+<table>
+<col/><col/><col/>
+<tr><td rowspan='0'>1</td><td>2</td></tr>
+<tr><td rowspan='2'>3</td></tr>
+<tr><td>4</td></tr>
+</table>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/time/001-isvalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/time/001-isvalid.xhtml
new file mode 100644
index 00000000000..ed9c3d9a0de
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/time/001-isvalid.xhtml
@@ -0,0 +1,55 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>&lt;t&gt;</title>
+</head>
+<body>
+ <!-- is structured inline -->
+ <p><time datetime='2006-11-20'>text</time></p>
+
+ <!-- is strictly inline -->
+ <p><dfn><time datetime='2006-11-20'>text</time></dfn></p>
+
+ <!-- can be empty -->
+ <p>text <time datetime='2006-11-20'></time></p>
+ <p>text <dfn><time datetime='2006-11-20'></time></dfn></p>
+
+ <!-- can contain interactive -->
+ <p><time datetime='2006-11-20'><a>text</a></time></p>
+ <p><dfn><time datetime='2006-11-20'><a>text</a></time></dfn></p>
+
+ <!-- vague moment of time in attribute -->
+ <p><time datetime='2006-11-20T16:24'>text</time></p>
+ <p><time datetime='2006-11-20T16:24:33'>text</time></p>
+ <p><time datetime='2006-11-20T16:24:33.89'>text</time></p>
+
+ <p><time datetime='2006-11-20T16:24Z'>text</time></p>
+ <p><time datetime='2006-11-20T16:24:33Z'>text</time></p>
+ <p><time datetime='2006-11-20T16:24:33.89Z'>text</time></p>
+
+ <p><time datetime='2006-11-20T16:24+02:00'>text</time></p>
+ <p><time datetime='2006-11-20T16:24:33+02:00'>text</time></p>
+ <p><time datetime='2006-11-20T16:24:33.89+02:00'>text</time></p>
+
+ <p><time datetime='16:24'>text</time></p>
+ <p><time datetime='16:24:33'>text</time></p>
+ <p><time datetime='16:24:33.89'>text</time></p>
+
+ <!-- vague moment of time in content -->
+ <p><time>2006-11-20T16:24</time></p>
+ <p><time>2006-11-20T16:24:33</time></p>
+ <p><time>2006-11-20T16:24:33.89</time></p>
+
+ <p><time>2006-11-20T16:24Z</time></p>
+ <p><time>2006-11-20T16:24:33Z</time></p>
+ <p><time>2006-11-20T16:24:33.89Z</time></p>
+
+ <p><time>2006-11-20T16:24+02:00</time></p>
+ <p><time>2006-11-20T16:24:33+02:00</time></p>
+ <p><time>2006-11-20T16:24:33.89+02:00</time></p>
+
+ <p><time>16:24</time></p>
+ <p><time>16:24:33</time></p>
+ <p><time>16:24:33.89</time></p>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/ul/030-isvalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/ul/030-isvalid.xhtml
new file mode 100644
index 00000000000..da9df2f5444
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/elements/ul/030-isvalid.xhtml
@@ -0,0 +1,35 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>Unordered List: &lt;ul&gt; &lt;li&gt;</title>
+</head>
+<body>
+ <!-- is block -->
+ <ul class="class" id="id" xml:lang="en">
+ <li class="class" id="id2" xml:lang="en">text</li>
+ </ul>
+
+ <!-- can be empty -->
+ <ul></ul>
+ <ul>
+ <li></li>
+ <li></li>
+ </ul>
+
+ <!-- can contain structured inline -->
+ <ul>
+ <li>some <em>text</em>
+ <pre>more text</pre>
+ </li>
+ </ul>
+ <!-- can contain blocks -->
+ <ul>
+ <li>
+ <p>some</p>
+ <p>text</p>
+ </li>
+ </ul>
+
+ <!-- can contain interactive -->
+ <ul><li><a>text</a></li></ul>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/media-queries/119-isvalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/media-queries/119-isvalid.xhtml
new file mode 100644
index 00000000000..857c16dea38
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/media-queries/119-isvalid.xhtml
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta charset="utf-8"/>
+<title>Check that device-aspect-ratio allows CR before and after slash</title>
+<link href='foo' media='screen and (device-aspect-ratio: 16&#x0d;/&#x0d;9)' rel='stylesheet'/> <!-- CR before & after slash -->
+</head>
+<body>
+<p>Check that device-aspect-ratio allows CR before andafter slash</p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/conformance-checkers/xhtml/other/045-novalid.xhtml b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/other/045-novalid.xhtml
new file mode 100644
index 00000000000..eab5bd7c667
--- /dev/null
+++ b/tests/wpt/web-platform-tests/conformance-checkers/xhtml/other/045-novalid.xhtml
@@ -0,0 +1,105 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>&lt;applet&gt;</title>
+</head>
+<body>
+ <!-- is structured inline -->
+ <p><applet
+ archive="uri1,uri2"
+ code="foo"
+ codebase="uri"
+ height="40"
+ width="40"
+ name="sth"
+ class="class"
+ xml:lang="en"></applet></p>
+
+ <!-- is strictly inline -->
+ <p><dfn><applet
+ archive="uri1,uri2"
+ code="foo"
+ codebase="uri"
+ height="40"
+ width="40"
+ name="sth"
+ class="class"
+ xml:lang="en"></applet></dfn></p>
+
+ <!-- is block -->
+ <applet
+ archive="uri1,uri2"
+ code="foo"
+ codebase="uri"
+ height="40"
+ width="40"
+ name="sth"
+ class="class"
+ xml:lang="en"></applet>
+
+ <!-- can contain inline while in inline context, but param must come first -->
+ <p>paragraph
+ <applet code="foo" width="10" height="10">
+ <em>some</em> <ul><li>inline</li></ul> content
+ </applet>
+ </p>
+ <p>paragraph
+ <applet code="foo" width="10" height="10">
+ <param name="foo"></param><param name="bar"></param>
+ <em>some</em> <ul><li>inline</li></ul> content
+ </applet>
+ </p>
+
+ <!-- can contain strictly inline while in strictly inline context, but param must come first -->
+ <p><dfn>strictly inline
+ <applet code="foo" width="10" height="10">
+ <em>text</em>
+ </applet>
+ </dfn></p>
+ <p><dfn>strictly inline
+ <applet code="foo" width="10" height="10">
+ <param name="foo"></param><param name="bar"></param>
+ <em>text</em>
+ </applet>
+ </dfn></p>
+
+ <!-- can contain blocks while in block context, but param must come first -->
+ <applet code="foo" width="10" height="10">
+ <p>text</p>
+ </applet>
+ <applet code="foo" width="10" height="10">
+ <param name="foo"></param><param name="bar"></param>
+ <p>text</p>
+ </applet>
+
+ <!-- can contain interactive if ancestor does not forbid it, but param must come first -->
+ <p>paragraph
+ <applet code="foo" width="10" height="10">
+ <a>link</a>
+ </applet>
+ </p>
+ <p>paragraph
+ <applet code="foo" width="10" height="10">
+ <param name="foo"></param><param name="bar"></param>
+ <a>link</a>
+ </applet>
+ </p>
+ <p><dfn>strictly inline
+ <applet code="foo" width="10" height="10">
+ <a>link</a>
+ </applet>
+ </dfn></p>
+ <p><dfn>strictly inline
+ <applet code="foo" width="10" height="10">
+ <param name="foo"></param><param name="bar"></param>
+ <a>link</a>
+ </applet>
+ </dfn></p>
+ <applet code="foo" width="10" height="10">
+ <p><a>link</a></p>
+ </applet>
+ <applet code="foo" width="10" height="10">
+ <param name="foo"></param><param name="bar"></param>
+ <p><a>link</a></p>
+ </applet>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/content-security-policy/README.css b/tests/wpt/web-platform-tests/content-security-policy/README.css
new file mode 100644
index 00000000000..d47a5034ba0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/README.css
@@ -0,0 +1,27 @@
+
+.code {
+ font-family: monospace;
+ color: darkorange;
+}
+
+.codeTitle {
+ font-family: sans-serif;
+ padding: .3em;
+ margin-bottom: -1em;
+ background: #ffe;
+ border-color: #ccc;
+ border-width: 1px;
+ border-style: groove;
+}
+
+.highlight1 {
+ background: yellow;
+}
+
+.highlight2 {
+ background: pink;
+}
+
+body {
+ font-family: sans-serif;
+}
diff --git a/tests/wpt/web-platform-tests/content-security-policy/README.html b/tests/wpt/web-platform-tests/content-security-policy/README.html
new file mode 100644
index 00000000000..6d71659cbb7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/README.html
@@ -0,0 +1,119 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+ <title>Introduction to Writing Content Security Policy Tests</title>
+ <link rel="stylesheet" type="text/css" href="README.css"></link>
+ <link rel="stylesheet" type="text/css" href="http://cdnjs.cloudflare.com/ajax/libs/highlight.js/8.1/styles/default.min.css">
+ <script src="http://cdnjs.cloudflare.com/ajax/libs/highlight.js/8.1/highlight.min.js"></script>
+ <script>
+ hljs.initHighlightingOnLoad();
+ </script>
+</head>
+
+<body>
+ <h1>Introduction to Writing Content Security Policy Tests</h1>
+ <p>The CSP test suite uses the standard W3C testharness.js framework, but there are a few additional things you'll need to do because of the unique way CSP works, even if you're already an expert at writing W3C tests. These tests require the use of the
+ <a href="https://github.com/w3c/wptserve">wptserve</a> server (included in the <a href="https://github.com/w3c/web-platform-tests">web-platform-tests repository</a>) to operate correctly.</p>
+
+ <h2>What's different about writing CSP tests?</h2>
+
+ <h3>Headers</h3>
+ <p>Content Security Policy is preferentially set through an HTTP header. This means we can't do our tests just as a simple set of HTML+CSS+JS files. Luckily the wptserver framework provides an easy method to add headers to a file.</p>
+ <p>If my file is named <span class=code>example.html</span> then I can create a file
+ <span class=code>example.html.headers</span> to define the headers that will be served with it. If I need to do template substitutions in the headers, I can instead create a file named <span class=code>example.html.sub.headers</span>.</p>
+
+ <h3>Negative Test Cases and Blocked Script Execution</h3>
+ <p>Another interesting feature of CSP is that it <em>prevents</em> things from happening. It even can and prevent script from running. How do we write tests that detect something didn't happen?</p>
+
+ <h3>Checking Reports</h3>
+ <p>CSP also has a feature to send a report. We ideally want to check that whenever a policy is enforced, a report is sent. This also helps us with the previous problem - if it is difficult to observe something not happening, we can still check that a report fired.</p>
+
+ <h2>Putting it Together</h2>
+ <p>Here's an example of a simple test. (ignore the highlights for now...) This file lives in the
+ <span class=code>/content-security-policy/script-src/</span> directory.</p>
+
+ <p class=codeTitle>script-src-1_1.html</p>
+ <pre><code class="html">&lt;!DOCTYPE HTML&gt;
+&lt;html&gt;
+&lt;head&gt;
+ &lt;script src=&#39;/resources/testharness.js&#39;&gt;&lt;/script&gt;
+ &lt;script src=&#39;/resources/testharnessreport.js&#39;&gt;&lt;/script&gt;
+ &lt;link rel=&#39;stylesheet&#39; href=&#39;/resources/testharness.css&#39;&gt;
+&lt;/head&gt;
+&lt;body&gt;
+ &lt;h1&gt;Inline script should not run without &#39;unsafe-inline&#39; script-src directive.&lt;/h1&gt;
+ &lt;div id=&#39;log&#39;&gt;&lt;/div&gt;
+
+ &lt;script&gt;
+ test(function() {
+ asset_unreached(&#39;Unsafe inline script ran.&#39;)},
+ &#39;Inline script in a script tag should not run without an unsafe-inline directive&#39;
+ );
+ &lt;/script&gt;
+
+ &lt;img src=&#39;doesnotexist.jpg&#39; onerror=&#39;test(function() { assert_false(true, &quot;Unsafe inline event handler ran.&quot;) }, &quot;Inline event handlers should not run without an unsafe-inline directive&quot;);&#39;&gt;
+
+ &lt;script async defer src=&#39;../support/checkReport.sub.js?reportField=violated-directive&amp;reportValue=<span class=highlight1>script-src%20%27self%27</span>&#39;&gt;&lt;/script&gt;
+
+&lt;/body&gt;
+&lt;/html&gt;
+ </code></pre>
+
+
+ <p>This code includes three tests. The first one in the script block will generate a failure if it runs. The second one, in the onerror handler for the img which does not exist should also generate a failure if it runs. But for a successful CSP implementation, neither of these tests does run. The final test is run by the link to <span class=code>../support/checkReport.sub.js</span>. It will load some script in the page (make sure its not blocked by your policy!) which contacts the server asynchronously and sees if the expected report was sent. This should always run an generate a positive or negative result even if the inline tests are blocked as we expect.</p>
+
+ <p>Now, to acutally exercise these tests against a policy, we'll need to set headers. In the same directory we'll place this file:</p>
+
+ <p class=codeTitle>script-src-1_1.html.sub.headers</p>
+ <pre><code class="html">
+Expires: Mon, 26 Jul 1997 05:00:00 GMT
+Cache-Control: no-store, no-cache, must-revalidate
+Cache-Control: post-check=0, pre-check=0, false
+Pragma: no-cache
+Set-Cookie: <span class=highlight2>script-src-1_1</span>={{$id:uuid()}}; Path=<span class=highlight2>/content-security-policy/script-src/</span>
+Content-Security-Policy: <span class=highlight1>script-src 'self'</span>; report-uri <span class=highlight2>..</span>/support/report.py?op=put&reportID={{$id}}
+ </code></pre>
+ <p>This sets some headers to prevent caching (just so we are more likely to see our latest changes if we're actively developing this test) sets a cookie (more on that later) and sets the relevant <span class=code>Content-Security-Policy</span> header for our test case.</p>
+
+ <h4>What about those highlights?</h4>
+ <p>In production code we don't like to repeat ourselves. For this test suite, we'll relax that rule a little bit. Why? It's easier to have many people contributing "safe" files using some template substitutions than require every file to be executable content like Python or PHP which would require much more careful code review. The highlights show where you have to be careful as you repeat yourself in more limited static files.
+ </p>
+
+ <p>The <span class=highlight1>YELLOW</span> highlighted text is information that must be the same between both files for report checking to work correctly. In the html file, we're telling
+ <span class=code>checkReport.sub.js</span> to check the value of the <span class=code>
+ violated-directive</span> key in the report JSON. So it needs to match (after URL encoding) the directive we set in the header.</p>
+
+ <p>The <span class=highlight2>PINK</span> highlighted text is information that must be repeated from the path and filename of your test file into the headers file. The name of the cookie must match the name of the test file without its extension, the path for the cookie must be correct, and the relative path component to the report-uri must also be corrected if you nest your tests more than one directory deep.</p>
+
+ <h2>Check Your Effects!</h2>
+ <p>A good test case should also verify the state of the DOM in addition to checking the report - after all, a browser might send a report without actually blocking the banned content. Note that in a browser without CSP support there will be three failures on the example page as the inline script executes.</p>
+ <p>How exactly you check your effects will depend on the directive, but don't hesitate to use script for testing to see if computed styles are as expected, if layouts changed or if certain elements were added to the DOM. Checking that the report also fired is just the final step of verifing correct behavior.</p>
+
+ <p>Note that avoiding inline script is good style and good habits, but not 100% necessary for every test case. Go ahead and specify 'unsafe-inline' if it makes your life easier.</p>
+
+ <h2>Report Existence Only and Double-Negative Tests</h2>
+ <p>If you want to check that a report exists, or verify that a report <em>wasn't</em> sent for a double-negative test case,
+ you can pass <strong>?reportExists=</strong><em>[true|false]</em> to <span class=code>checkReport.sub.js</span> instead of <strong>reportField</strong> and <strong>reportValue</strong>.</p>
+
+ <h2>How does the magic happen?</h2>
+ <p>Behind the scenes, a few things are going on in the framework.</p>
+ <ol>
+ <li>The {{$id:uuid}} templating marker in the headers file tells the wptserve HTTP server to create a new unique id and assign it to a variable, which we can re-use as {{$id}}.</li>
+ <li>We'll use this UUID in two places:
+ <ol>
+ <li>As a GET parameter to our reporting script, to uniquely identify this instance of the test case so our report can be stored and retrieved.
+ </li>
+ <li>As a cookie value associated with the filename, so script in the page context can learn what UUID the report was sent under.</li>
+ </ol>
+ </li>
+ <li>The report listener is a simple python file that stashes the report value under its UUID and allows it to be retrieved again, exactly once.</li>
+ <li><span class=code>checkReport.sub.js</span> then grabs the current path information and uses that to find the cookie holding the report UUID. It deletes that cookie (otherwise the test suite would overrun the maximum size of a cookie header allowed) then makes an XMLHttpRequest to the report listener to retrieve the report, parse it and verify the contents as per the parameters it was loaded with.</li>
+ </ol>
+
+ <p>Why all these gymnastics? CSP reports are delivered by an <em>anonymous fetch</em>. This means that the browser does not process the response headers, body, or allow any state changes as a result. So we can't pull a trick like just echoing the report contents back in a Set-Cookie header or writing them to local storage.</p>
+
+ <p>Luckily, you shouldn't have to worry about this magic much, as long as you get the incantation correct.</p>
+</body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_10.html b/tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_10.html
new file mode 100644
index 00000000000..703e50b4460
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_10.html
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>test implicit port number matching (requires port 80)</title>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+ <script>
+ var head = document.getElementsByTagName('head')[0];
+ var script = document.createElement('script');
+ script.type = 'text/javascript';
+ script.src = "http://www." + location.hostname + "/content-security-policy/generic/positiveTest.js";
+ head.appendChild(script);
+ </script>
+</head>
+<body>
+ <h1>test implicit port number matching (requires port 80)</h1>
+ <div id='log'></div>
+
+ <script async defer src='../support/checkReport.sub.js?reportExists=false'></script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_10.html.sub.headers b/tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_10.html.sub.headers
new file mode 100644
index 00000000000..c58b0536ff7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_10.html.sub.headers
@@ -0,0 +1,6 @@
+Expires: Mon, 26 Jul 1997 05:00:00 GMT
+Cache-Control: no-store, no-cache, must-revalidate
+Cache-Control: post-check=0, pre-check=0, false
+Pragma: no-cache
+Set-Cookie: generic-0_10={{$id:uuid()}}; Path=/content-security-policy/generic/
+Content-Security-Policy: script-src 'self' www.{{host}} 'unsafe-inline'; report-uri ../support/report.py?op=put&reportID={{$id}}
diff --git a/tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_10_1.sub.html b/tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_10_1.sub.html
new file mode 100644
index 00000000000..c66640de333
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_10_1.sub.html
@@ -0,0 +1,22 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>implicit port number matching fails with a different port</title>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+ <script src='negativeTests.js'></script>
+ <script>
+ var head = document.getElementsByTagName('head')[0];
+ var script = document.createElement('script');
+ script.type = 'text/javascript';
+ script.src = "http://www." + location.hostname + ":{{ports[http][1]}}/content-security-policy/generic/unreached.js";
+ head.appendChild(script);
+ </script>
+</head>
+<body>
+ <h1>implicit port number matching fails with a different port</h1>
+ <div id='log'></div>
+
+ <script async defer src='../support/checkReport.sub.js?reportField=violated-directive&reportValue=script-src%20%27self%27%20www.{{host}}%20%27unsafe-inline%27'></script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_10_1.sub.html.sub.headers b/tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_10_1.sub.html.sub.headers
new file mode 100644
index 00000000000..e8fcf07c203
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_10_1.sub.html.sub.headers
@@ -0,0 +1,6 @@
+Expires: Mon, 26 Jul 1997 05:00:00 GMT
+Cache-Control: no-store, no-cache, must-revalidate
+Cache-Control: post-check=0, pre-check=0, false
+Pragma: no-cache
+Set-Cookie: generic-0_10_1={{$id:uuid()}}; Path=/content-security-policy/generic/
+Content-Security-Policy: script-src 'self' www.{{host}} 'unsafe-inline'; report-uri ../support/report.py?op=put&reportID={{$id}}
diff --git a/tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_2.html b/tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_2.html
new file mode 100644
index 00000000000..130bfadad96
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_2.html
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>'self' keyword positive test</title>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+ <script src='positiveTest.js'></script>
+</head>
+<body>
+ <h1>'self' keyword positive test</h1>
+ <div id='log'></div>
+
+ <script async defer src='../support/checkReport.sub.js?reportExists=false'></script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_2.html.sub.headers b/tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_2.html.sub.headers
new file mode 100644
index 00000000000..776112de60d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_2.html.sub.headers
@@ -0,0 +1,6 @@
+Expires: Mon, 26 Jul 1997 05:00:00 GMT
+Cache-Control: no-store, no-cache, must-revalidate
+Cache-Control: post-check=0, pre-check=0, false
+Pragma: no-cache
+Set-Cookie: generic-0_2={{$id:uuid()}}; Path=/content-security-policy/generic/
+Content-Security-Policy: script-src 'self'; report-uri ../support/report.py?op=put&reportID={{$id}}
diff --git a/tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_2_2.sub.html b/tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_2_2.sub.html
new file mode 100644
index 00000000000..9d274ea597e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_2_2.sub.html
@@ -0,0 +1,22 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>'self' fails with a different port</title>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+ <script src='negativeTests.js'></script>
+ <script>
+ var head = document.getElementsByTagName('head')[0];
+ var script = document.createElement('script');
+ script.type = 'text/javascript';
+ script.src = "http://" + location.hostname + ":{{ports[http][1]}}/content-security-policy/generic/unreached.js";
+ head.appendChild(script);
+ </script>
+</head>
+<body>
+ <h1>'self' fails with a different port</h1>
+ <div id='log'></div>
+
+ <script async defer src='../support/checkReport.sub.js?reportField=violated-directive&reportValue=script-src%20%27self%27%20%27unsafe-inline%27'></script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_2_2.sub.html.sub.headers b/tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_2_2.sub.html.sub.headers
new file mode 100644
index 00000000000..769ccc154e5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_2_2.sub.html.sub.headers
@@ -0,0 +1,6 @@
+Expires: Mon, 26 Jul 1997 05:00:00 GMT
+Cache-Control: no-store, no-cache, must-revalidate
+Cache-Control: post-check=0, pre-check=0, false
+Pragma: no-cache
+Set-Cookie: generic-0_2_2={{$id:uuid()}}; Path=/content-security-policy/generic/
+Content-Security-Policy: script-src 'self' 'unsafe-inline'; report-uri ../support/report.py?op=put&reportID={{$id}}
diff --git a/tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_2_3.html b/tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_2_3.html
new file mode 100644
index 00000000000..ff4b8db8a78
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_2_3.html
@@ -0,0 +1,22 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>'self' fails with a different host (including sub-host e.g. foo.com as self with content from bar.foo.com)</title>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+ <script src='negativeTests.js'></script>
+ <script>
+ var head = document.getElementsByTagName('head')[0];
+ var script = document.createElement('script');
+ script.type = 'text/javascript';
+ script.src = "http://www." + location.hostname + ":" + location.port + "/content-security-policy/generic/unreached.js";
+ head.appendChild(script);
+ </script>
+</head>
+<body>
+ <h1>'self' fails with a different host (including sub-host e.g. foo.com as self with content from bar.foo.com)</h1>
+ <div id='log'></div>
+
+ <script async defer src='../support/checkReport.sub.js?reportField=violated-directive&reportValue=script-src%20%27self%27%20%27unsafe-inline%27'></script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_2_3.html.sub.headers b/tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_2_3.html.sub.headers
new file mode 100644
index 00000000000..0a8defccd6c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_2_3.html.sub.headers
@@ -0,0 +1,6 @@
+Expires: Mon, 26 Jul 1997 05:00:00 GMT
+Cache-Control: no-store, no-cache, must-revalidate
+Cache-Control: post-check=0, pre-check=0, false
+Pragma: no-cache
+Set-Cookie: generic-0_2_3={{$id:uuid()}}; Path=/content-security-policy/generic/
+Content-Security-Policy: script-src 'self' 'unsafe-inline'; report-uri ../support/report.py?op=put&reportID={{$id}}
diff --git a/tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_8.html b/tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_8.html
new file mode 100644
index 00000000000..2e7df3776ad
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_8.html
@@ -0,0 +1,22 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>test wildcard host name matching (*.web-platform.test is good)</title>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+ <script src='wildcardHostTest.js'></script>
+ <script>
+ var head = document.getElementsByTagName('head')[0];
+ var script = document.createElement('script');
+ script.type = 'text/javascript';
+ script.src = "http://www." + location.hostname + ":" + location.port + "/content-security-policy/generic/wildcardHostTestSuceeds.js";
+ head.appendChild(script);
+ </script>
+</head>
+<body>
+ <h1>test wildcard host name matching (*.web-platform.test is good)</h1>
+ <div id='log'></div>
+
+ <script async defer src='../support/checkReport.sub.js?reportExists=false'></script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_8.html.sub.headers b/tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_8.html.sub.headers
new file mode 100644
index 00000000000..34756f9dbe0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_8.html.sub.headers
@@ -0,0 +1,6 @@
+Expires: Mon, 26 Jul 1997 05:00:00 GMT
+Cache-Control: no-store, no-cache, must-revalidate
+Cache-Control: post-check=0, pre-check=0, false
+Pragma: no-cache
+Set-Cookie: generic-0_8={{$id:uuid()}}; Path=/content-security-policy/generic/
+Content-Security-Policy: script-src 'self' *.{{host}}:{{ports[http][0]}} 'unsafe-inline'; report-uri ../support/report.py?op=put&reportID={{$id}}
diff --git a/tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_8_1.sub.html b/tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_8_1.sub.html
new file mode 100644
index 00000000000..167b4458da7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_8_1.sub.html
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>test wildcard host name matching (www*.web-platform.test is bad, *www.web-platform.test is bad)</title>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+ <script src='wildcardHostTestFailure.js'></script>
+ <script>
+ var head = document.getElementsByTagName('head')[0];
+ var script = document.createElement('script');
+ script.type = 'text/javascript';
+ script.src = "http://www." + location.hostname + ":" + location.port + "/content-security-policy/generic/wildcardHostTestSuceeds.js";
+ head.appendChild(script);
+ </script>
+</head>
+<body>
+ <h1>test wildcard host name matching (www*.web-platform.test is bad, *www.web-platform.test is bad)</h1>
+ <div id='log'></div>
+ <script async defer src='../support/checkReport.sub.js?reportField=violated-directive&reportValue=script-src%20%27self%27%20*w.{{host}}:{{ports[http][0]}}%20w*.{{host}}:{{ports[http][0]}}%20%27unsafe-inline%27'></script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_8_1.sub.html.sub.headers b/tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_8_1.sub.html.sub.headers
new file mode 100644
index 00000000000..57a038a0539
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_8_1.sub.html.sub.headers
@@ -0,0 +1,6 @@
+Expires: Mon, 26 Jul 1997 05:00:00 GMT
+Cache-Control: no-store, no-cache, must-revalidate
+Cache-Control: post-check=0, pre-check=0, false
+Pragma: no-cache
+Set-Cookie: generic-0_8_1={{$id:uuid()}}; Path=/content-security-policy/generic/
+Content-Security-Policy: script-src 'self' *w.{{host}}:{{ports[http][0]}} w*.{{host}}:{{ports[http][0]}} 'unsafe-inline'; report-uri ../support/report.py?op=put&reportID={{$id}}
diff --git a/tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_9.sub.html b/tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_9.sub.html
new file mode 100644
index 00000000000..cadeb178f3a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_9.sub.html
@@ -0,0 +1,22 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>test wildcard port number matching</title>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+ <script src='wildcardPortTest.js'></script>
+ <script>
+ var head = document.getElementsByTagName('head')[0];
+ var script = document.createElement('script');
+ script.type = 'text/javascript';
+ script.src = "http://" + location.hostname + ":{{ports[http][1]}}/content-security-policy/generic/wildcardPortTestSuceeds.js";
+ head.appendChild(script);
+ </script>
+</head>
+<body>
+ <h1>test wildcard port number matching</h1>
+ <div id='log'></div>
+
+ <script async defer src='../support/checkReport.sub.js?reportExists=false'></script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_9.sub.html.sub.headers b/tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_9.sub.html.sub.headers
new file mode 100644
index 00000000000..2f23360097d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/generic/generic-0_9.sub.html.sub.headers
@@ -0,0 +1,6 @@
+Expires: Mon, 26 Jul 1997 05:00:00 GMT
+Cache-Control: no-store, no-cache, must-revalidate
+Cache-Control: post-check=0, pre-check=0, false
+Pragma: no-cache
+Set-Cookie: generic-0_9={{$id:uuid()}}; Path=/content-security-policy/generic/
+Content-Security-Policy: script-src 'self' {{host}}:* 'unsafe-inline'; report-uri ../support/report.py?op=put&reportID={{$id}}
diff --git a/tests/wpt/web-platform-tests/content-security-policy/generic/negativeTests.js b/tests/wpt/web-platform-tests/content-security-policy/generic/negativeTests.js
new file mode 100644
index 00000000000..44b4d7f683d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/generic/negativeTests.js
@@ -0,0 +1,3 @@
+var t1 = async_test("Prevents access to external scripts.");
+
+onload = function() {t1.done();}
diff --git a/tests/wpt/web-platform-tests/content-security-policy/generic/positiveTest.js b/tests/wpt/web-platform-tests/content-security-policy/generic/positiveTest.js
new file mode 100644
index 00000000000..63c99919623
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/generic/positiveTest.js
@@ -0,0 +1,6 @@
+onload = function() {
+ test(function() {
+ assert_true(true, 'Script ran.')},
+ "Allows scripts from the same host."
+ );
+}
diff --git a/tests/wpt/web-platform-tests/content-security-policy/generic/unreached.js b/tests/wpt/web-platform-tests/content-security-policy/generic/unreached.js
new file mode 100644
index 00000000000..893fb5eba10
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/generic/unreached.js
@@ -0,0 +1,3 @@
+onload = function() {
+ t1.step(function() {assert_unreached("Script should not have ran.");});
+}
diff --git a/tests/wpt/web-platform-tests/content-security-policy/generic/wildcardHostTest.js b/tests/wpt/web-platform-tests/content-security-policy/generic/wildcardHostTest.js
new file mode 100644
index 00000000000..da3e2790f53
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/generic/wildcardHostTest.js
@@ -0,0 +1,8 @@
+wildcardHostTestRan = false;
+
+onload = function() {
+ test(function() {
+ assert_true(wildcardHostTestRan, 'Script should have ran.')},
+ "Wildcard host matching works."
+ );
+}
diff --git a/tests/wpt/web-platform-tests/content-security-policy/generic/wildcardHostTestFailure.js b/tests/wpt/web-platform-tests/content-security-policy/generic/wildcardHostTestFailure.js
new file mode 100644
index 00000000000..75ec8cf80e0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/generic/wildcardHostTestFailure.js
@@ -0,0 +1,8 @@
+wildcardHostTestRan = false;
+
+onload = function() {
+ test(function() {
+ assert_false(wildcardHostTestRan, 'Script should not have ran.')},
+ "Wildcard host matching works."
+ );
+}
diff --git a/tests/wpt/web-platform-tests/content-security-policy/generic/wildcardHostTestSuceeds.js b/tests/wpt/web-platform-tests/content-security-policy/generic/wildcardHostTestSuceeds.js
new file mode 100644
index 00000000000..8b115d7fc45
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/generic/wildcardHostTestSuceeds.js
@@ -0,0 +1 @@
+wildcardHostTestRan = true;
diff --git a/tests/wpt/web-platform-tests/content-security-policy/generic/wildcardPortTest.js b/tests/wpt/web-platform-tests/content-security-policy/generic/wildcardPortTest.js
new file mode 100644
index 00000000000..3cd1d2eaedf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/generic/wildcardPortTest.js
@@ -0,0 +1,8 @@
+wildcardPortTestRan = false;
+
+onload = function() {
+ test(function() {
+ assert_true(wildcardPortTestRan, 'Script should have ran.')},
+ "Wildcard port matching works."
+ );
+}
diff --git a/tests/wpt/web-platform-tests/content-security-policy/generic/wildcardPortTestSuceeds.js b/tests/wpt/web-platform-tests/content-security-policy/generic/wildcardPortTestSuceeds.js
new file mode 100644
index 00000000000..0138deb2eef
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/generic/wildcardPortTestSuceeds.js
@@ -0,0 +1 @@
+wildcardPortTestRan = true; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/content-security-policy/img-src/img-src-4_1.html b/tests/wpt/web-platform-tests/content-security-policy/img-src/img-src-4_1.html
new file mode 100644
index 00000000000..edf04fb193f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/img-src/img-src-4_1.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>img element src attribute must match src list.</title>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+</head>
+<body>
+ <h1>img element src attribute must match src list.</h1>
+ <p>
+ <div id='log'></div>
+
+ <script type="text/javascript">
+ var t1 = async_test("img-src for relative path should load.");
+ var t2 = async_test("img-src from unapproved domains should not load");
+ var t3 = async_test("img-src from approved domains should load");
+ </script>
+
+ <img src='/content-security-policy/support/pass.png'
+ onerror='t1.step(function() { assert_unreached("The img should have loaded."); t1.done() });'
+ onload='t1.done();'>
+
+ <img src='http://www1.web-platform.test/content-security-policy/support/fail.png'
+ onerror='t2.done();'
+ onload='t2.step(function() { assert_unreached("Image from unapproved domain was loaded."); t2.done()} );'>
+
+ <div id='t3'></div>
+
+ <script>
+ var t3img = document.createElement('img');
+ t3img.onerror = function() {t3.step(function() { assert_unreached(); t3.done();})}
+ t3img.onload = function() {t3.done();}
+ t3img.src = location.protocol + '//www.' + location.hostname + ':' + location.port +
+ '/content-security-policy/support/pass.png';
+ var t3div = document.getElementById('t3');
+ t3div.appendChild(t3img);
+
+ var report = document.createElement('script');
+ report.src = '../support/checkReport.sub.js?reportField=violated-directive&reportValue=img-src%20%27self%27%20www.' + location.hostname + (location.port ? ':' + location.port : '');
+ t3div.appendChild(report);
+
+ </script>
+
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/content-security-policy/img-src/img-src-4_1.html.sub.headers b/tests/wpt/web-platform-tests/content-security-policy/img-src/img-src-4_1.html.sub.headers
new file mode 100644
index 00000000000..543e48c1425
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/img-src/img-src-4_1.html.sub.headers
@@ -0,0 +1,6 @@
+Expires: Mon, 26 Jul 1997 05:00:00 GMT
+Cache-Control: no-store, no-cache, must-revalidate
+Cache-Control: post-check=0, pre-check=0, false
+Pragma: no-cache
+Set-Cookie: img-src-4_1={{$id:uuid()}}; Path=/content-security-policy/img-src/
+Content-Security-Policy: img-src 'self' www.{{host}}:{{ports[http][0]}}; report-uri ../support/report.py?op=put&reportID={{$id}}
diff --git a/tests/wpt/web-platform-tests/content-security-policy/media-src/media-src-7_1.html b/tests/wpt/web-platform-tests/content-security-policy/media-src/media-src-7_1.html
new file mode 100644
index 00000000000..d912b86bb8b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/media-src/media-src-7_1.html
@@ -0,0 +1,44 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Video element src attribute must match src list - positive test</title>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+</head>
+<body>
+ <h1>Video element src attribute must match src list - positive test</h1>
+ <div id='log'></div>
+
+ <script>
+ var src_test = async_test("In-policy async video src");
+ var source_test = async_test("In-policy async video source element");
+
+ function media_loaded(t) {
+ t.done();
+ }
+
+ function media_error_handler(t) {
+ t.step( function () {
+ assert_unreached("Media error handler should be triggered for non-allowed domain.");
+ });
+ t.done();
+ }
+ </script>
+
+ <video id="videoObject" width="320" height="240" controls
+ onloadeddata="media_loaded(source_test)">
+ <source id="videoSourceObject"
+ type="video/mp4"
+ onerror="media_error_handler(source_test)"
+ src="/media/white.mp4">
+ </video>
+ <video id="videoObject2" width="320" height="240" controls
+ onerror="media_error_handler(src_test)"
+ onloadeddata="media_loaded(src_test)"
+ src="/media/white.mp4">
+
+ <script async defer src="../support/checkReport.sub.js?reportExists=false">
+ </script>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/content-security-policy/media-src/media-src-7_1.html.sub.headers b/tests/wpt/web-platform-tests/content-security-policy/media-src/media-src-7_1.html.sub.headers
new file mode 100644
index 00000000000..9361207e899
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/media-src/media-src-7_1.html.sub.headers
@@ -0,0 +1,6 @@
+Expires: Mon, 26 Jul 1997 05:00:00 GMT
+Cache-Control: no-store, no-cache, must-revalidate
+Cache-Control: post-check=0, pre-check=0, false
+Pragma: no-cache
+Set-Cookie: media-src-7_1={{$id:uuid()}}; Path=/content-security-policy/media-src/
+Content-Security-Policy: script-src * 'unsafe-inline'; media-src 'self'; report-uri ../support/report.py?op=put&reportID={{$id}}
diff --git a/tests/wpt/web-platform-tests/content-security-policy/media-src/media-src-7_1_2.html b/tests/wpt/web-platform-tests/content-security-policy/media-src/media-src-7_1_2.html
new file mode 100644
index 00000000000..c1b9f72f48d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/media-src/media-src-7_1_2.html
@@ -0,0 +1,54 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Video element src attribute must match src list - negative test</title>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+</head>
+<body>
+ <h1>Video element src attribute must match src list - negative test</h1>
+ <div id='log'></div>
+
+ <script>
+ var src_test = async_test("Disallowed async video src");
+ var source_test = async_test("Disallowed async video source element");
+
+ // we assume tests are run from 'hostname' and 'www.hostname' or 'www2.hostname' is a valid alias
+ var mediaURL = location.protocol +
+ "//www2." +
+ location.hostname +
+ ":" +
+ location.port +
+ "/media/white.mp4";
+
+ function media_loaded(t) {
+ t.step( function () {
+ assert_unreached("Media error handler should be triggered for non-allowed domain.");
+ });
+ t.done();
+ }
+
+ function media_error_handler(t) {
+ t.done();
+ }
+ </script>
+
+ <video id="videoObject" width="320" height="240" controls
+ onloadeddata="media_loaded(source_test)">
+ <source id="videoSourceObject"
+ type="video/mp4"
+ onerror="media_error_handler(source_test)">
+ </video>
+ <video id="videoObject2" width="320" height="240" controls
+ onerror="media_error_handler(src_test)"
+ onloadeddata="media_loaded(src_test)">
+
+ <script>
+ document.getElementById("videoSourceObject").src = mediaURL;
+ document.getElementById("videoObject2").src = mediaURL;
+ </script>
+
+ <script async defer src='../support/checkReport.sub.js?reportField=violated-directive&reportValue=media-src%20%27self%27'></script>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/content-security-policy/media-src/media-src-7_1_2.html.sub.headers b/tests/wpt/web-platform-tests/content-security-policy/media-src/media-src-7_1_2.html.sub.headers
new file mode 100644
index 00000000000..036da86739e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/media-src/media-src-7_1_2.html.sub.headers
@@ -0,0 +1,6 @@
+Expires: Mon, 26 Jul 1997 05:00:00 GMT
+Cache-Control: no-store, no-cache, must-revalidate
+Cache-Control: post-check=0, pre-check=0, false
+Pragma: no-cache
+Set-Cookie: media-src-7_1_2={{$id:uuid()}}; Path=/content-security-policy/media-src/
+Content-Security-Policy: script-src * 'unsafe-inline'; media-src 'self'; report-uri ../support/report.py?op=put&reportID={{$id}}
diff --git a/tests/wpt/web-platform-tests/content-security-policy/media-src/media-src-7_2.html b/tests/wpt/web-platform-tests/content-security-policy/media-src/media-src-7_2.html
new file mode 100644
index 00000000000..7509d7b051a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/media-src/media-src-7_2.html
@@ -0,0 +1,44 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Audio element src attribute must match src list - positive test</title>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+</head>
+<body>
+ <h1>Audio element src attribute must match src list - positive test</h1>
+ <div id='log'></div>
+
+ <script>
+ var src_test = async_test("In-policy audio src");
+ var source_test = async_test("In-policy audio source element");
+
+ function media_loaded(t) {
+ t.done();
+ }
+
+ function media_error_handler(t) {
+ t.step( function () {
+ assert_unreached("Media error handler should be triggered for non-allowed domain.");
+ });
+ t.done();
+ }
+ </script>
+
+ <audio id="audioObject" width="320" height="240" controls
+ onloadeddata="media_loaded(source_test)">
+ <source id="audioSourceObject"
+ type="audio/mpeg"
+ onerror="media_error_handler(source_test)"
+ src="/media/sound_5.mp3">
+ </audio>
+ <audio id="audioObject2" width="320" height="240" controls
+ onerror="media_error_handler(src_test)"
+ onloadeddata="media_loaded(src_test)"
+ src="/media/sound_5.mp3">
+
+ <script async defer src="../support/checkReport.sub.js?reportExists=false">
+ </script>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/content-security-policy/media-src/media-src-7_2.html.sub.headers b/tests/wpt/web-platform-tests/content-security-policy/media-src/media-src-7_2.html.sub.headers
new file mode 100644
index 00000000000..0f59cd9ffd1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/media-src/media-src-7_2.html.sub.headers
@@ -0,0 +1,6 @@
+Expires: Mon, 26 Jul 1997 05:00:00 GMT
+Cache-Control: no-store, no-cache, must-revalidate
+Cache-Control: post-check=0, pre-check=0, false
+Pragma: no-cache
+Set-Cookie: media-src-7_2={{$id:uuid()}}; Path=/content-security-policy/media-src/
+Content-Security-Policy: script-src * 'unsafe-inline'; media-src 'self'; report-uri ../support/report.py?op=put&reportID={{$id}}
diff --git a/tests/wpt/web-platform-tests/content-security-policy/media-src/media-src-7_2_2.html b/tests/wpt/web-platform-tests/content-security-policy/media-src/media-src-7_2_2.html
new file mode 100644
index 00000000000..573b5389e2a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/media-src/media-src-7_2_2.html
@@ -0,0 +1,54 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Audio element src attribute must match src list - negative test</title>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+</head>
+<body>
+ <h1>Audio element src attribute must match src list - negative test</h1>
+ <div id='log'></div>
+
+ <script>
+ var src_test = async_test("Disallaowed audio src");
+ var source_test = async_test("Disallowed audio source element");
+
+ // we assume tests are run from 'hostname' and 'www.hostname' or 'www2.hostname' is a valid alias
+ var mediaURL = location.protocol +
+ "//www2." +
+ location.hostname +
+ ":" +
+ location.port +
+ "/media/sound_5.mp3";
+
+ function media_loaded(t) {
+ t.step( function () {
+ assert_unreached("Media error handler should be triggered for non-allowed domain.");
+ });
+ t.done();
+ }
+
+ function media_error_handler(t) {
+ t.done();
+ }
+ </script>
+
+ <audio id="audioObject" width="320" height="240" controls
+ onloadeddata="media_loaded(source_test)">
+ <source id="audioSourceObject"
+ type="audio/mpeg"
+ onerror="media_error_handler(source_test)">
+ </audio>
+ <audio id="audioObject2" width="320" height="240" controls
+ onerror="media_error_handler(src_test)"
+ onloadeddata="media_loaded(src_test)">
+
+ <script>
+ document.getElementById("audioSourceObject").src = mediaURL;
+ document.getElementById("audioObject2").src = mediaURL;
+ </script>
+
+ <script async defer src='../support/checkReport.sub.js?reportField=violated-directive&reportValue=media-src%20%27self%27'></script>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/content-security-policy/media-src/media-src-7_2_2.html.sub.headers b/tests/wpt/web-platform-tests/content-security-policy/media-src/media-src-7_2_2.html.sub.headers
new file mode 100644
index 00000000000..685978de3a9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/media-src/media-src-7_2_2.html.sub.headers
@@ -0,0 +1,6 @@
+Expires: Mon, 26 Jul 1997 05:00:00 GMT
+Cache-Control: no-store, no-cache, must-revalidate
+Cache-Control: post-check=0, pre-check=0, false
+Pragma: no-cache
+Set-Cookie: media-src-7_2_2={{$id:uuid()}}; Path=/content-security-policy/media-src/
+Content-Security-Policy: script-src * 'unsafe-inline'; media-src 'self'; report-uri ../support/report.py?op=put&reportID={{$id}}
diff --git a/tests/wpt/web-platform-tests/content-security-policy/media-src/media-src-7_3.html b/tests/wpt/web-platform-tests/content-security-policy/media-src/media-src-7_3.html
new file mode 100644
index 00000000000..32187708239
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/media-src/media-src-7_3.html
@@ -0,0 +1,53 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Video track src attribute must match src list - positive test</title>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+</head>
+<body>
+ <h1>Video track src attribute must match src list - positive test</h1>
+ <div id='log'></div>
+
+ <script>
+ var source_test = async_test("In-policy track element");
+
+ var trackURL = location.protocol +
+ "//www." +
+ location.hostname +
+ ":" +
+ location.port +
+ "/media/foo.vtt";
+
+ function media_loaded(t) {
+ t.done();
+ }
+
+ function media_error_handler(t) {
+ t.step( function () {
+ assert_unreached("Error handler called for allowed track source.");
+ });
+ t.done();
+ }
+ </script>
+
+ <video id="videoObject" width="320" height="240" controls
+ onloadeddata="media_loaded(source_test)" crossorigin>
+ <source id="audioSourceObject"
+ type="audio/mpeg"
+ src="/media/white.mp4">
+ <track id="trackObject"
+ kind="subtitles"
+ srclang="en"
+ label="English"
+ onerror="media_error_handler(source_test)">
+ </video>
+ <script>
+ document.getElementById("trackObject").src = trackURL;
+ </script>
+
+ <script async defer src="../support/checkReport.sub.js?reportExists=false">
+ </script>
+
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/content-security-policy/media-src/media-src-7_3.html.sub.headers b/tests/wpt/web-platform-tests/content-security-policy/media-src/media-src-7_3.html.sub.headers
new file mode 100644
index 00000000000..b764189ad96
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/media-src/media-src-7_3.html.sub.headers
@@ -0,0 +1,6 @@
+Expires: Mon, 26 Jul 1997 05:00:00 GMT
+Cache-Control: no-store, no-cache, must-revalidate
+Cache-Control: post-check=0, pre-check=0, false
+Pragma: no-cache
+Set-Cookie: media-src-7_3={{$id:uuid()}}; Path=/content-security-policy/media-src/
+Content-Security-Policy: script-src * 'unsafe-inline'; media-src 'self' www.{{host}}:{{ports[http][0]}}; report-uri ../support/report.py?op=put&reportID={{$id}}
diff --git a/tests/wpt/web-platform-tests/content-security-policy/media-src/media-src-7_3_2.html b/tests/wpt/web-platform-tests/content-security-policy/media-src/media-src-7_3_2.html
new file mode 100644
index 00000000000..7ead63f88e8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/media-src/media-src-7_3_2.html
@@ -0,0 +1,53 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Video track src attribute must match src list - negative test</title>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+</head>
+<body>
+ <h1>Video track src attribute must match src list - negative test</h1>
+ <div id='log'></div>
+
+ <script>
+ var source_test = async_test("Disallowed track element");
+
+ var trackURL = location.protocol +
+ "//www." +
+ location.hostname +
+ ":" +
+ location.port +
+ "/media/foo.vtt";
+
+ function media_loaded(t) {
+ t.step( function () {
+ assert_unreached("Disllowed track source loaded.");
+ });
+ t.done();
+ }
+
+ function media_error_handler(t) {
+ t.done();
+ }
+ </script>
+
+ <video id="videoObject" width="320" height="240" controls
+ onloadeddata="media_loaded(source_test)" crossorigin>
+ <source id="audioSourceObject"
+ type="audio/mpeg"
+ src="/media/white.mp4">
+ <track id="trackObject"
+ kind="subtitles"
+ srclang="en"
+ label="English"
+ onerror="media_error_handler(source_test)">
+ </video>
+ <script>
+ document.getElementById("trackObject").src = trackURL;
+ </script>
+
+ <script async defer src="../support/checkReport.sub.js?reportField=violated-directive&reportValue=media-src%20%27self%27">
+ </script>
+
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/content-security-policy/media-src/media-src-7_3_2.html.sub.headers b/tests/wpt/web-platform-tests/content-security-policy/media-src/media-src-7_3_2.html.sub.headers
new file mode 100644
index 00000000000..2cfe51fe8e2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/media-src/media-src-7_3_2.html.sub.headers
@@ -0,0 +1,6 @@
+Expires: Mon, 26 Jul 1997 05:00:00 GMT
+Cache-Control: no-store, no-cache, must-revalidate
+Cache-Control: post-check=0, pre-check=0, false
+Pragma: no-cache
+Set-Cookie: media-src-7_3_2={{$id:uuid()}}; Path=/content-security-policy/media-src/
+Content-Security-Policy: script-src * 'unsafe-inline'; media-src 'self'; report-uri ../support/report.py?op=put&reportID={{$id}}
diff --git a/tests/wpt/web-platform-tests/content-security-policy/object-src/object-src-2_1.html b/tests/wpt/web-platform-tests/content-security-policy/object-src/object-src-2_1.html
new file mode 100644
index 00000000000..aaf67bf740a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/object-src/object-src-2_1.html
@@ -0,0 +1,56 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Objects loaded using data attribute of &lt;object&gt; tag are blocked unless their host is listed as an allowed source in the object-src directive</title>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+</head>
+<body onLoad="object_loaded()">
+ <h1>Objects loaded using data attribute of &lt;object&gt; tag are blocked unless their host is listed as an allowed source in the object-src directive</h1>
+ <div id="log"></div>
+
+ <script>
+ var relativeMediaURL = "/support/media/flash.swf";
+ var pageURL = window.location.toString();
+ var temp1 = pageURL.split("//");
+ var temp2 = temp1[1].substring (0, temp1[1].lastIndexOf("/object-src/"));
+ var mediaURL = "http://www2." + temp2 + relativeMediaURL;
+ var htmlStr = "<object id='flashObject' type='application/x-shockwave-flash' data='" + mediaURL + "' width='200' height='200'></object>";
+ document.write (htmlStr);
+ </script>
+
+ <script>
+ var len = navigator.mimeTypes.length;
+ var allTypes = "";
+ var flashMimeType = "application/x-shockwave-flash";
+ for ( var i=0;i<len;i++ ) {
+ allTypes+=navigator.mimeTypes[i].type;
+ }
+
+ var hasMimeType = allTypes.indexOf(flashMimeType) != -1;
+
+ <!-- The actual test. -->
+ var test1 = async_test("Async SWF load test")
+
+ function object_loaded() {
+ var elem = document.getElementById("flashObject");
+ var is_loaded = false;
+ try {
+ <!-- The Flash Player exposes values to JavaScript if a SWF has successfully been loaded. -->
+ var pct_loaded = elem.PercentLoaded();
+ is_loaded = true;
+ } catch (e) {}
+
+ if (hasMimeType) {
+ test1.step(function() {assert_false(is_loaded, "External object loaded.")});
+ } else {
+ test1.step(function() {assert_true(hasMimeType, "No Flash Player, cannot run test.")});
+ }
+ test1.done();
+ }
+ </script>
+
+ <script async defer src="../support/checkReport.sub.js?reportField=violated-directive&reportValue=object-src%20%27self%27"></script>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/content-security-policy/object-src/object-src-2_1.html.sub.headers b/tests/wpt/web-platform-tests/content-security-policy/object-src/object-src-2_1.html.sub.headers
new file mode 100644
index 00000000000..83fe95d3451
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/object-src/object-src-2_1.html.sub.headers
@@ -0,0 +1,6 @@
+Expires: Mon, 26 Jul 1997 05:00:00 GMT
+Cache-Control: no-store, no-cache, must-revalidate
+Cache-Control: post-check=0, pre-check=0, false
+Pragma: no-cache
+Set-Cookie: object-src-2_1={{$id:uuid()}}; Path=/content-security-policy/object-src/
+Content-Security-Policy: script-src * 'unsafe-inline'; object-src 'self'; report-uri ../support/report.py?op=put&reportID={{$id}} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/content-security-policy/object-src/object-src-2_2.html b/tests/wpt/web-platform-tests/content-security-policy/object-src/object-src-2_2.html
new file mode 100644
index 00000000000..63b85604f5e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/object-src/object-src-2_2.html
@@ -0,0 +1,56 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Objects loaded using src attribute of &lt;embed&gt; tag are blocked unless their host is listed as an allowed source in the object-src directive</title>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+</head>
+<body onLoad="object_loaded()">
+ <h1>Objects loaded using src attribute of &lt;embed&gt; tag are blocked unless their host is listed as an allowed source in the object-src directive</h1>
+ <div id="log"></div>
+
+ <script>
+ var relativeMediaURL = "/support/media/flash.swf";
+ var pageURL = window.location.toString();
+ var temp1 = pageURL.split("//");
+ var temp2 = temp1[1].substring (0, temp1[1].lastIndexOf("/object-src/"));
+ var mediaURL = "http://www2." + temp2 + relativeMediaURL;
+ var htmlStr = "<embed id='flashObject' type='application/x-shockwave-flash' src='" + mediaURL + "' width='200' height='200'></object>";
+ document.write (htmlStr);
+ </script>
+
+ <script>
+ var len = navigator.mimeTypes.length;
+ var allTypes = "";
+ var flashMimeType = "application/x-shockwave-flash";
+ for ( var i=0;i<len;i++ ) {
+ allTypes+=navigator.mimeTypes[i].type;
+ }
+
+ var hasMimeType = allTypes.indexOf(flashMimeType) != -1;
+
+ <!-- The actual test. -->
+ var test1 = async_test("Async SWF load test")
+
+ function object_loaded() {
+ var elem = document.getElementById("flashObject");
+ var is_loaded = false;
+ try {
+ <!-- The Flash Player exposes values to JavaScript if a SWF has successfully been loaded. -->
+ var pct_loaded = elem.PercentLoaded();
+ is_loaded = true;
+ } catch (e) {}
+
+ if (hasMimeType) {
+ test1.step(function() {assert_false(is_loaded, "External object loaded.")});
+ } else {
+ test1.step(function() {assert_true(hasMimeType, "No Flash Player, cannot run test.")});
+ }
+ test1.done();
+ }
+ </script>
+
+ <script async defer src="../support/checkReport.sub.js?reportField=violated-directive&reportValue=object-src%20%27self%27"></script>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/content-security-policy/object-src/object-src-2_2.html.sub.headers b/tests/wpt/web-platform-tests/content-security-policy/object-src/object-src-2_2.html.sub.headers
new file mode 100644
index 00000000000..0ee665ea323
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/object-src/object-src-2_2.html.sub.headers
@@ -0,0 +1,6 @@
+Expires: Mon, 26 Jul 1997 05:00:00 GMT
+Cache-Control: no-store, no-cache, must-revalidate
+Cache-Control: post-check=0, pre-check=0, false
+Pragma: no-cache
+Set-Cookie: object-src-2_2={{$id:uuid()}}; Path=/content-security-policy/object-src/
+Content-Security-Policy: script-src * 'unsafe-inline'; object-src 'self'; report-uri ../support/report.py?op=put&reportID={{$id}}
diff --git a/tests/wpt/web-platform-tests/content-security-policy/script-src/10_1_support_1.js b/tests/wpt/web-platform-tests/content-security-policy/script-src/10_1_support_1.js
new file mode 100644
index 00000000000..7b6e85210d0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/script-src/10_1_support_1.js
@@ -0,0 +1 @@
+var dataScriptRan = false; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/content-security-policy/script-src/10_1_support_2.js b/tests/wpt/web-platform-tests/content-security-policy/script-src/10_1_support_2.js
new file mode 100644
index 00000000000..ba586810f5f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/script-src/10_1_support_2.js
@@ -0,0 +1,3 @@
+test(function () {
+ assert_true(dataScriptRan, "data script ran");
+ }, "Verify that data: as script src runs with this policy"); \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/content-security-policy/script-src/addInlineTestsWithDOMManipulation.js b/tests/wpt/web-platform-tests/content-security-policy/script-src/addInlineTestsWithDOMManipulation.js
new file mode 100644
index 00000000000..cd093ac9423
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/script-src/addInlineTestsWithDOMManipulation.js
@@ -0,0 +1,18 @@
+(function () {
+
+ var dmTest = async_test("DOM manipulation inline tests");
+ var attachPoint = document.getElementById('attachHere');
+ var inlineScript = document.createElement('script');
+ var scriptText = document.createTextNode('dmTest.step(function() {assert_unreached("Unsafe inline script ran - createTextNode.")});');
+
+ inlineScript.appendChild(scriptText);
+ attachPoint.appendChild(inlineScript);
+
+ document.getElementById('emptyScript').innerHTML = 'dmTest.step(function() {assert_unreached("Unsafe inline script ran - innerHTML.")});';
+ document.getElementById('emptyDiv').outerHTML = '<script id=outerHTMLScript>dmTest.step(function() {assert_unreached("Unsafe inline script ran - outerHTML.")});</script>';
+
+ document.write('<script>dmTest.step(function() {assert_unreached("Unsafe inline script ran - document.write")});</script>');
+ document.writeln('<script>dmTest.step(function() {assert_unreached("Unsafe inline script ran - document.writeln")});</script>');
+
+ dmTest.done();
+})(); \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/content-security-policy/script-src/buildInlineWorker.js b/tests/wpt/web-platform-tests/content-security-policy/script-src/buildInlineWorker.js
new file mode 100644
index 00000000000..4fc3bb71c1e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/script-src/buildInlineWorker.js
@@ -0,0 +1,21 @@
+(function ()
+{
+ var test = new async_test("test inline worker");
+ var workerSource = document.getElementById('inlineWorker');
+
+ var blob = new Blob([workerSource.textContent]);
+
+ // can I create a new script tag like this? ack...
+ var url = window.URL.createObjectURL(blob);
+
+ var worker = new Worker(url);
+
+ worker.addEventListener('message', function(e) {
+ test.step(function () {
+ assert_not_equals(e.data, 'fail', 'inline script ran');
+ test.done();
+ })
+ }, false);
+
+ worker.postMessage('');
+})();
diff --git a/tests/wpt/web-platform-tests/content-security-policy/script-src/inlineSuccessTest.js b/tests/wpt/web-platform-tests/content-security-policy/script-src/inlineSuccessTest.js
new file mode 100644
index 00000000000..ea2be272a20
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/script-src/inlineSuccessTest.js
@@ -0,0 +1,8 @@
+var inlineRan = false;
+
+onload = function() {
+ test(function() {
+ assert_true(inlineRan, 'Unsafe inline script ran.')},
+ 'Inline script in a script tag should run with an unsafe-inline directive'
+ );
+} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/content-security-policy/script-src/inlineTests.js b/tests/wpt/web-platform-tests/content-security-policy/script-src/inlineTests.js
new file mode 100644
index 00000000000..6e76b0a1781
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/script-src/inlineTests.js
@@ -0,0 +1,4 @@
+var t1 = async_test("Inline script block");
+var t2 = async_test("Inline event handler");
+
+onload = function() {t1.done(); t2.done()} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/content-security-policy/script-src/script-src-1_1.html b/tests/wpt/web-platform-tests/content-security-policy/script-src/script-src-1_1.html
new file mode 100644
index 00000000000..c8eff3b6b23
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/script-src/script-src-1_1.html
@@ -0,0 +1,22 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Inline script should not run without 'unsafe-inline' script-src directive.</title>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+ <script src='inlineTests.js'></script>
+</head>
+<body>
+ <h1>Inline script should not run without 'unsafe-inline' script-src directive.</h1>
+ <div id='log'></div>
+
+ <script>
+ t1.step(function() {assert_unreached('Unsafe inline script ran.');});
+ </script>
+
+ <img src='doesnotexist.jpg' onerror='t2.step(function() { assert_unreached("Unsafe inline event handler ran.") });'>
+
+ <script async defer src='../support/checkReport.sub.js?reportField=violated-directive&reportValue=script-src%20%27self%27'></script>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/content-security-policy/script-src/script-src-1_1.html.sub.headers b/tests/wpt/web-platform-tests/content-security-policy/script-src/script-src-1_1.html.sub.headers
new file mode 100644
index 00000000000..d91fe1c87f1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/script-src/script-src-1_1.html.sub.headers
@@ -0,0 +1,6 @@
+Expires: Mon, 26 Jul 1997 05:00:00 GMT
+Cache-Control: no-store, no-cache, must-revalidate
+Cache-Control: post-check=0, pre-check=0, false
+Pragma: no-cache
+Set-Cookie: script-src-1_1={{$id:uuid()}}; Path=/content-security-policy/script-src/
+Content-Security-Policy: script-src 'self'; report-uri ../support/report.py?op=put&reportID={{$id}} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/content-security-policy/script-src/script-src-1_10.html b/tests/wpt/web-platform-tests/content-security-policy/script-src/script-src-1_10.html
new file mode 100644
index 00000000000..137a16421db
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/script-src/script-src-1_10.html
@@ -0,0 +1,27 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>data: as script src should not run with a policy that doesn't specify data: as an allowed source</title>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+</head>
+<body>
+ <h1>data: as script src should not run with a policy that doesn't specify data: as an allowed source</h1>
+ <div id='log'></div>
+
+ <script>
+ var dataScriptRan = false;
+ </script>
+
+ <!-- This is our test case, but we don't expect it to actually execute if CSP is working. -->
+ <script src="data:text/javascript;charset=utf-8;base64,ZGF0YVNjcmlwdFJhbiA9IHRydWU7"></script>
+
+ <script>
+ test(function () {
+ assert_false(dataScriptRan, "data script ran");
+ }, "Verify that data: as script src doesn't run with this policy");
+ </script>
+
+ <script async defer src='../support/checkReport.sub.js?reportField=violated-directive&reportValue=default-src%20%27self%27+%27unsafe-inline%27'></script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/content-security-policy/script-src/script-src-1_10.html.sub.headers b/tests/wpt/web-platform-tests/content-security-policy/script-src/script-src-1_10.html.sub.headers
new file mode 100644
index 00000000000..6c0c0fd0a76
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/script-src/script-src-1_10.html.sub.headers
@@ -0,0 +1,6 @@
+Expires: Mon, 26 Jul 1997 05:00:00 GMT
+Cache-Control: no-store, no-cache, must-revalidate
+Cache-Control: post-check=0, pre-check=0, false
+Pragma: no-cache
+Set-Cookie: script-src-1_10={{$id:uuid()}}; Path=/content-security-policy/script-src/
+Content-Security-Policy: default-src 'self' 'unsafe-inline'; report-uri ../support/report.py?op=put&reportID={{$id}}
diff --git a/tests/wpt/web-platform-tests/content-security-policy/script-src/script-src-1_10_1.html b/tests/wpt/web-platform-tests/content-security-policy/script-src/script-src-1_10_1.html
new file mode 100644
index 00000000000..f1bfee2000a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/script-src/script-src-1_10_1.html
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>data: as script src should run with a policy that specifies data: as an allowed source but not 'unsafe-inline'</title>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+</head>
+<body>
+ <h1>data: as script src should run with a policy that specifies data: as an allowed source but not 'unsafe-inline'</h1>
+ <div id='log'></div>
+
+ <script src="10_1_support_1.js"></script>
+
+ <script src="data:text/javascript;charset=utf-8;base64,ZGF0YVNjcmlwdFJhbiA9IHRydWU7"></script>
+
+ <script src="10_1_support_2.js"></script>
+
+ <script async defer src='../support/checkReport.sub.js?reportExists=false'></script>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/content-security-policy/script-src/script-src-1_10_1.html.sub.headers b/tests/wpt/web-platform-tests/content-security-policy/script-src/script-src-1_10_1.html.sub.headers
new file mode 100644
index 00000000000..dfb6f345fc7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/script-src/script-src-1_10_1.html.sub.headers
@@ -0,0 +1,6 @@
+Expires: Mon, 26 Jul 1997 05:00:00 GMT
+Cache-Control: no-store, no-cache, must-revalidate
+Cache-Control: post-check=0, pre-check=0, false
+Pragma: no-cache
+Set-Cookie: script-src-1_10_1={{$id:uuid()}}; Path=/content-security-policy/script-src/
+Content-Security-Policy: script-src 'self' data:; report-uri ../support/report.py?op=put&reportID={{$id}} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/content-security-policy/script-src/script-src-1_2_1.html b/tests/wpt/web-platform-tests/content-security-policy/script-src/script-src-1_2_1.html
new file mode 100644
index 00000000000..255f5df9ce1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/script-src/script-src-1_2_1.html
@@ -0,0 +1,23 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Inline script attached by DOM manipulation should not run without an 'unsafe-inline' script-src policy, even with default-src *</title>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+</head>
+<body>
+ <h1>Inline script attached by DOM manipulation should not run without an 'unsafe-inline' script-src policy, even with default-src *</h1>
+ <div id="log"></div>
+
+ <div id=attachHere></div>
+
+ <script id=emptyScript></script>
+
+ <div id=emptyDiv></div>
+
+ <script src="addInlineTestsWithDOMManipulation.js"></script>
+
+ <script async defer src="../support/checkReport.sub.js?reportField=violated-directive&reportValue=script-src%20*"></script>
+
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/content-security-policy/script-src/script-src-1_2_1.html.sub.headers b/tests/wpt/web-platform-tests/content-security-policy/script-src/script-src-1_2_1.html.sub.headers
new file mode 100644
index 00000000000..9c58f0efcd5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/script-src/script-src-1_2_1.html.sub.headers
@@ -0,0 +1,6 @@
+Expires: Mon, 26 Jul 1997 05:00:00 GMT
+Cache-Control: no-store, no-cache, must-revalidate
+Cache-Control: post-check=0, pre-check=0, false
+Pragma: no-cache
+Set-Cookie: script-src-1_2_1={{$id:uuid()}}; Path=/content-security-policy/script-src/
+Content-Security-Policy: script-src *; report-uri ../support/report.py?op=put&reportID={{$id}} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/content-security-policy/script-src/script-src-1_3.html b/tests/wpt/web-platform-tests/content-security-policy/script-src/script-src-1_3.html
new file mode 100644
index 00000000000..30e6f6870a8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/script-src/script-src-1_3.html
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Positive test case: Inline script should run 'unsafe-inline' script-src directive.</title>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+ <script src='inlineSuccessTest.js'></script>
+</head>
+<body>
+ <h1>Positive test case: Inline script should run 'unsafe-inline' script-src directive.</h1>
+ <div id='log'></div>
+
+ <script>
+ inlineRan = true;
+ </script>
+
+ <script async defer src='../support/checkReport.sub.js?reportExists=false'></script>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/content-security-policy/script-src/script-src-1_3.html.sub.headers b/tests/wpt/web-platform-tests/content-security-policy/script-src/script-src-1_3.html.sub.headers
new file mode 100644
index 00000000000..8227c6272dc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/script-src/script-src-1_3.html.sub.headers
@@ -0,0 +1,6 @@
+Expires: Mon, 26 Jul 1997 05:00:00 GMT
+Cache-Control: no-store, no-cache, must-revalidate
+Cache-Control: post-check=0, pre-check=0, false
+Pragma: no-cache
+Set-Cookie: script-src-1_3={{$id:uuid()}}; Path=/content-security-policy/script-src/
+Content-Security-Policy: script-src 'self' 'unsafe-inline'; report-uri ../support/report.py?op=put&reportID={{$id}} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/content-security-policy/script-src/script-src-1_4.html b/tests/wpt/web-platform-tests/content-security-policy/script-src/script-src-1_4.html
new file mode 100644
index 00000000000..ba5265aa744
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/script-src/script-src-1_4.html
@@ -0,0 +1,22 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>eval() should not run without 'unsafe-eval' script-src directive.</title>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+</head>
+<body>
+ <h1>eval() should not run without 'unsafe-eval' script-src directive.</h1>
+ <div id='log'></div>
+
+ <script>
+
+ var evalRan = false;
+
+ test(function() {assert_throws(new EvalError(), function() { eval('evalRan = true;') })}, "eval() should throw without 'unsafe-eval' keyword source in script-src directive.");
+ </script>
+
+ <script async defer src='../support/checkReport.sub.js?reportField=violated-directive&reportValue=script-src%20%27self%27+%27unsafe-inline%27'></script>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/content-security-policy/script-src/script-src-1_4.html.sub.headers b/tests/wpt/web-platform-tests/content-security-policy/script-src/script-src-1_4.html.sub.headers
new file mode 100644
index 00000000000..28ad14b609d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/script-src/script-src-1_4.html.sub.headers
@@ -0,0 +1,6 @@
+Expires: Mon, 26 Jul 1997 05:00:00 GMT
+Cache-Control: no-store, no-cache, must-revalidate
+Cache-Control: post-check=0, pre-check=0, false
+Pragma: no-cache
+Set-Cookie: script-src-1_4={{$id:uuid()}}; Path=/content-security-policy/script-src/
+Content-Security-Policy: script-src 'self' 'unsafe-inline'; report-uri ../support/report.py?op=put&reportID={{$id}} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/content-security-policy/script-src/script-src-1_9.html b/tests/wpt/web-platform-tests/content-security-policy/script-src/script-src-1_9.html
new file mode 100644
index 00000000000..923eab82629
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/script-src/script-src-1_9.html
@@ -0,0 +1,22 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Worker created from inline text and loaded via blob URI should not run with policy default-src *</title>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+</head>
+<body>
+ <h1>Worker created from inline text and loaded via blob URI should not run with policy default-src *</h1>
+ <div id='log'></div>
+
+ <script id="inlineWorker" type="app/worker">
+ addEventListener('message', function() {
+ postMessage('fail');
+ }, false);
+ </script>
+
+ <script src="buildInlineWorker.js"></script>
+ <script async defer src='../support/checkReport.sub.js?reportField=violated-directive&reportValue=default-src%20*'></script>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/content-security-policy/script-src/script-src-1_9.html.sub.headers b/tests/wpt/web-platform-tests/content-security-policy/script-src/script-src-1_9.html.sub.headers
new file mode 100644
index 00000000000..89a05ef03b2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/script-src/script-src-1_9.html.sub.headers
@@ -0,0 +1,6 @@
+Expires: Mon, 26 Jul 1997 05:00:00 GMT
+Cache-Control: no-store, no-cache, must-revalidate
+Cache-Control: post-check=0, pre-check=0, false
+Pragma: no-cache
+Set-Cookie: script-src-1_9={{$id:uuid()}}; Path=/content-security-policy/script-src/
+Content-Security-Policy: default-src *; report-uri ../support/report.py?op=put&reportID={{$id}} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/content-security-policy/style-src/3_3.css b/tests/wpt/web-platform-tests/content-security-policy/style-src/3_3.css
new file mode 100644
index 00000000000..8086244b298
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/style-src/3_3.css
@@ -0,0 +1 @@
+#content {margin-left: 2px;} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/content-security-policy/style-src/style-src-3_1.html b/tests/wpt/web-platform-tests/content-security-policy/style-src/style-src-3_1.html
new file mode 100644
index 00000000000..6c4c1a32036
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/style-src/style-src-3_1.html
@@ -0,0 +1,33 @@
+<!doctype html>
+<html>
+<head>
+ <title></title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ <style>
+ /* none of this should be applied */
+ #log {
+ margin-left: 200px;
+ }
+ </style>
+</head>
+<body>
+ <h1>
+ Inline style should not be applied
+ without unsafe-inline directive
+ </h1>
+ <div id='log'></div>
+
+ <script>
+ test(function() {
+ var logEl = document.getElementById("log");
+ var marginLeftVal = getComputedStyle(logEl).getPropertyValue('margin-left');
+ assert_false(marginLeftVal == "200px")},
+ "Inline style should not be applied"
+ );
+ </script>
+
+ <script async defer src='../support/checkReport.sub.js?reportField=violated-directive&reportValue=style-src%20%27self%27'></script>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/content-security-policy/style-src/style-src-3_1.html.sub.headers b/tests/wpt/web-platform-tests/content-security-policy/style-src/style-src-3_1.html.sub.headers
new file mode 100644
index 00000000000..c550a46c209
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/style-src/style-src-3_1.html.sub.headers
@@ -0,0 +1,6 @@
+Expires: Mon, 26 Jul 1997 05:00:00 GMT
+Cache-Control: no-store, no-cache, must-revalidate
+Cache-Control: post-check=0, pre-check=0, false
+Pragma: no-cache
+Set-Cookie: style-src-3_1={{$id:uuid()}}; Path=/content-security-policy/style-src/
+Content-Security-Policy: style-src 'self'; report-uri ../support/report.py?op=put&reportID={{$id}} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/content-security-policy/style-src/style-src-3_2.html b/tests/wpt/web-platform-tests/content-security-policy/style-src/style-src-3_2.html
new file mode 100644
index 00000000000..ce904d96bc5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/style-src/style-src-3_2.html
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Inline style attributes should not be applied without 'unsafe-inline' style-src directive.</title>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+ <script>
+ onload = function() {
+ test(function() {
+ var text = document.getElementById("content");
+ assert_true(getComputedStyle(text).marginLeft != "2px", "Inline style attribute should not be applied to text");
+ });
+ }
+ </script>
+</head>
+<body>
+ <h1>Inline style attributes should not be applied without 'unsafe-inline' style-src directive.</h1>
+ <div id='log'></div>
+
+ <div id="content" style="margin-left: 2px">This text should not have a margin-left of 2</div>
+
+ <script async defer src='../support/checkReport.sub.js?reportField=violated-directive&reportValue=style-src%20%27self%27'></script>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/content-security-policy/style-src/style-src-3_2.html.sub.headers b/tests/wpt/web-platform-tests/content-security-policy/style-src/style-src-3_2.html.sub.headers
new file mode 100644
index 00000000000..3343ccee99e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/style-src/style-src-3_2.html.sub.headers
@@ -0,0 +1,6 @@
+Expires: Mon, 26 Jul 1997 05:00:00 GMT
+Cache-Control: no-store, no-cache, must-revalidate
+Cache-Control: post-check=0, pre-check=0, false
+Pragma: no-cache
+Set-Cookie: style-src-3_2={{$id:uuid()}}; Path=/content-security-policy/style-src/
+Content-Security-Policy: script-src 'self' 'unsafe-inline'; style-src 'self'; report-uri ../support/report.py?op=put&reportID={{$id}} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/content-security-policy/style-src/style-src-3_3.html b/tests/wpt/web-platform-tests/content-security-policy/style-src/style-src-3_3.html
new file mode 100644
index 00000000000..d836b351cdc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/style-src/style-src-3_3.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>href of link with rel=stylesheet must be in src list</title>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+ <script>
+ var head = document.getElementsByTagName('head')[0];
+ var link = document.createElement('link');
+ link.setAttribute('rel', 'stylesheet');
+ link.setAttribute('type', 'text/css');
+ link.setAttribute('href', location.protocol +
+ '//www1.' +
+ location.hostname +
+ ':' +
+ location.port +
+ '/content-security-policy/style-src/3_3.css');
+ head.appendChild(link);
+
+ onload = function doTest() {
+ test(function() {
+ var text = document.getElementById("content");
+ assert_true(getComputedStyle(text).marginLeft != "2px", "Style sheet loaded from origin not in style-src directive should be blocked");
+ });
+ }
+ </script>
+</head>
+<body>
+ <h1>href of link with rel=stylesheet must be in src list</h1>
+ <div id='log'></div>
+
+ <div id="content">This text should not have a margin-left of 2</div>
+
+ <script async defer src='../support/checkReport.sub.js?reportField=violated-directive&reportValue=style-src%20%27self%27'></script>
+
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/content-security-policy/style-src/style-src-3_3.html.sub.headers b/tests/wpt/web-platform-tests/content-security-policy/style-src/style-src-3_3.html.sub.headers
new file mode 100644
index 00000000000..ca1adc553a3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/style-src/style-src-3_3.html.sub.headers
@@ -0,0 +1,6 @@
+Expires: Mon, 26 Jul 1997 05:00:00 GMT
+Cache-Control: no-store, no-cache, must-revalidate
+Cache-Control: post-check=0, pre-check=0, false
+Pragma: no-cache
+Set-Cookie: style-src-3_3={{$id:uuid()}}; Path=/content-security-policy/style-src/
+Content-Security-Policy: script-src 'self' 'unsafe-inline'; style-src 'self'; report-uri ../support/report.py?op=put&reportID={{$id}} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/content-security-policy/style-src/style-src-3_4-import.css b/tests/wpt/web-platform-tests/content-security-policy/style-src/style-src-3_4-import.css
new file mode 100644
index 00000000000..8ef865fdc7d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/style-src/style-src-3_4-import.css
@@ -0,0 +1,3 @@
+#log {
+ margin-left: 200px;
+}
diff --git a/tests/wpt/web-platform-tests/content-security-policy/style-src/style-src-3_4.css b/tests/wpt/web-platform-tests/content-security-policy/style-src/style-src-3_4.css
new file mode 100644
index 00000000000..11729ce7a93
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/style-src/style-src-3_4.css
@@ -0,0 +1 @@
+@import "http://{{host}}:{{ports[http][1]}}/content-security-policy/style-src/style-src-3_4-import.css";
diff --git a/tests/wpt/web-platform-tests/content-security-policy/style-src/style-src-3_4.html b/tests/wpt/web-platform-tests/content-security-policy/style-src/style-src-3_4.html
new file mode 100644
index 00000000000..92553dd6755
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/style-src/style-src-3_4.html
@@ -0,0 +1,27 @@
+<!doctype html>
+<html>
+<head>
+ <title></title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link href="style-src-3_4.css?pipe=sub" rel=stylesheet type=text/css>
+</head>
+<body>
+ <h1>
+ @import stylesheet should not be loaded
+ if its URL doesn't match style-src.
+ </h1>
+ <div id='log'></div>
+
+ <script>
+ test(function() {
+ var logEl = document.getElementById("log");
+ var marginLeftVal = getComputedStyle(logEl).getPropertyValue('margin-left');
+ assert_false(marginLeftVal == "200px")},
+ "@import stylesheet should not be applied"
+ );
+ </script>
+
+ <script async defer src='../support/checkReport.sub.js?reportField=violated-directive&reportValue=style-src%20%27self%27'></script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/content-security-policy/style-src/style-src-3_4.html.sub.headers b/tests/wpt/web-platform-tests/content-security-policy/style-src/style-src-3_4.html.sub.headers
new file mode 100644
index 00000000000..9a9e1a288f7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/style-src/style-src-3_4.html.sub.headers
@@ -0,0 +1,6 @@
+Expires: Mon, 26 Jul 1997 05:00:00 GMT
+Cache-Control: no-store, no-cache, must-revalidate
+Cache-Control: post-check=0, pre-check=0, false
+Pragma: no-cache
+Set-Cookie: style-src-3_4={{$id:uuid()}}; Path=/content-security-policy/style-src/
+Content-Security-Policy: style-src 'self'; report-uri ../support/report.py?op=put&reportID={{$id}} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/content-security-policy/support/checkReport.sub.js b/tests/wpt/web-platform-tests/content-security-policy/support/checkReport.sub.js
new file mode 100644
index 00000000000..dfaec7ac54d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/support/checkReport.sub.js
@@ -0,0 +1,62 @@
+(function () {
+
+ // Get values from the substitution engine.
+ // We can't just pull these from the document context
+ // because this script is intended to be transcluded into
+ // another document, and we want the GET values used to request it,
+ // not the values for the including document
+
+ // XXX these are unencoded, so there's an unavoidable
+ // injection vulnerability in constructing this file...
+ // need to upgrade the template engine.
+ var reportField = "{{GET[reportField]}}";
+ var reportValue = "{{GET[reportValue]}}";
+ var reportExists = "{{GET[reportExists]}}";
+
+ var location = window.location;
+ var thisTestName = location.pathname.split('/')[location.pathname.split('/').length - 1].split('.')[0];
+
+ var reportID = "";
+
+ var cookies = document.cookie.split(';');
+ for (var i = 0; i < cookies.length; i++) {
+ var cookieName = cookies[i].split('=')[0].trim();
+ var cookieValue = cookies[i].split('=')[1].trim();
+
+ if (cookieName == thisTestName) {
+ reportID = cookieValue;
+ var cookieToDelete = cookieName + "=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=" + document.location.pathname.substring(0, document.location.pathname.lastIndexOf('/') + 1);
+ document.cookie = cookieToDelete;
+ break;
+ }
+ }
+
+ var reportLocation = location.protocol + "//" + location.host + "/content-security-policy/support/report.py?op=take&timeout=5&reportID=" + reportID;
+
+ var reportTest = async_test("Violation report status OK.");
+ reportTest.step(function () {
+
+ var report = new XMLHttpRequest();
+ report.onload = reportTest.step_func(function () {
+
+ var data = JSON.parse(report.responseText);
+
+ if (data.error) {
+ assert_equals("false", reportExists, reportExists ? "Report sent in error" : "No report sent.");
+ } else {
+ // Firefox expands 'self' or origins in a policy to the actual origin value
+ // so "www.example.com" becomes "http://www.example.com:80".
+ // Accomodate this by just testing that the correct directive name
+ // is reported, not the details...
+
+ assert_true(data["csp-report"][reportField].indexOf(reportValue.split(" ")[0]) != -1, reportField + " value of \"" + data["csp-report"][reportField] + "\" did not match " + reportValue.split(" ")[0] + ".");
+ }
+
+ reportTest.done();
+ });
+
+ report.open("GET", reportLocation, true);
+ report.send();
+ });
+
+})();
diff --git a/tests/wpt/web-platform-tests/content-security-policy/support/fail.png b/tests/wpt/web-platform-tests/content-security-policy/support/fail.png
new file mode 100644
index 00000000000..b5933803338
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/support/fail.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/content-security-policy/support/media/flash.swf b/tests/wpt/web-platform-tests/content-security-policy/support/media/flash.swf
new file mode 100644
index 00000000000..80bf47e207c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/support/media/flash.swf
Binary files differ
diff --git a/tests/wpt/web-platform-tests/content-security-policy/support/pass.png b/tests/wpt/web-platform-tests/content-security-policy/support/pass.png
new file mode 100644
index 00000000000..2fa1e0ac066
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/support/pass.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/content-security-policy/support/report.py b/tests/wpt/web-platform-tests/content-security-policy/support/report.py
new file mode 100644
index 00000000000..f8c0c463c03
--- /dev/null
+++ b/tests/wpt/web-platform-tests/content-security-policy/support/report.py
@@ -0,0 +1,26 @@
+import time
+import json
+
+def main(request, response):
+
+ op = request.GET.first("op");
+ key = request.GET.first("reportID")
+
+ if op == "take":
+ timeout = float(request.GET.first("timeout"))
+ value = request.server.stash.take(key=key)
+ if value is not None:
+ return [("Content-Type", "application/json")], value
+ else:
+ time.sleep(timeout)
+ value = request.server.stash.take(key=key)
+ if value is not None:
+ return [("Content-Type", "application/json")], value
+ else:
+ return [("Content-Type", "application/json")], json.dumps({'error': 'No such report.' , 'guid' : key})
+ else:
+ report = request.body
+ report.rstrip()
+ request.server.stash.take(key=key)
+ request.server.stash.put(key=key, value=report)
+ return [("Content-Type", "text/plain")], "Recorded report " + report \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/cors/allow-headers.htm b/tests/wpt/web-platform-tests/cors/allow-headers.htm
new file mode 100644
index 00000000000..08e00a5270f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cors/allow-headers.htm
@@ -0,0 +1,89 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Access-Control-Allow-Headers handling</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js?pipe=sub></script>
+
+<h1>Access-Control-Allow-Headers handling</h1>
+
+<div id=log></div>
+
+<script>
+
+/*
+ * Origin header
+ */
+function shouldPass(origin) {
+ test(function () {
+ var client = new XMLHttpRequest()
+ client.open('GET', CROSSDOMAIN
+ + '/resources/cors-makeheader.py?origin='
+ + encodeURIComponent(origin),
+ false)
+ client.send()
+ r = JSON.parse(client.response)
+ var host = location.protocol + "//" + location.host
+ assert_equals(r['origin'], host, 'Request Origin: should be ' + host)
+ }, 'Allow origin: ' + origin.replace(/\t/g, "[tab]").replace(/ /g, '_'));
+}
+
+shouldPass('*');
+shouldPass(' * ');
+shouldPass(' *');
+shouldPass(location.protocol + "//" + location.host);
+shouldPass(" "+location.protocol + "//" + location.host);
+shouldPass(" "+location.protocol + "//" + location.host + " ");
+shouldPass(" "+location.protocol + "//" + location.host);
+
+
+function shouldFail(origin) {
+ test(function () {
+ var client = new XMLHttpRequest()
+ client.open('GET', CROSSDOMAIN
+ + '/resources/cors-makeheader.py?origin='
+ + encodeURIComponent(origin),
+ false)
+ assert_throws(null, function() { client.send() }, 'send')
+ }, 'Disallow origin: ' + origin.replace('\0', '\\0'));
+}
+
+shouldFail(location.protocol + "//" + SUBDOMAIN + "." + location.host)
+shouldFail("//" + location.host)
+shouldFail("://" + location.host)
+shouldFail("ftp://" + location.host)
+shouldFail("http:://" + location.host)
+shouldFail("http:/" + location.host)
+shouldFail("http:" + location.host)
+shouldFail(location.host)
+shouldFail(location.protocol + "//" + location.host + "?")
+shouldFail(location.protocol + "//" + location.host + "/")
+shouldFail(location.protocol + "//" + location.host + " /")
+shouldFail(location.protocol + "//" + location.host + "#")
+shouldFail(location.protocol + "//" + location.host + "%23")
+shouldFail(location.protocol + "//" + location.host + ":80")
+shouldFail(location.protocol + "//" + location.host + ", *")
+shouldFail(location.protocol + "//" + location.host + "\0")
+shouldFail((location.protocol + "//" + location.host).toUpperCase())
+shouldFail(location.protocol.toUpperCase() + "//" + location.host)
+shouldFail("-")
+shouldFail("**")
+shouldFail("\0*")
+shouldFail("*\0")
+shouldFail("'*'")
+shouldFail('"*"')
+shouldFail("* *")
+shouldFail("*" + location.protocol + "//" + "*")
+shouldFail("*" + location.protocol + "//" + location.host)
+shouldFail("* " + location.protocol + "//" + location.host)
+shouldFail("*, " + location.protocol + "//" + location.host)
+shouldFail("\0" + location.protocol + "//" + location.host)
+shouldFail("null " + location.protocol + "//" + location.host)
+shouldFail('http://example.net')
+shouldFail('null')
+shouldFail('')
+shouldFail(location.href)
+shouldFail(dirname(location.href))
+shouldFail(CROSSDOMAIN)
+
+</script>
diff --git a/tests/wpt/web-platform-tests/cors/basic.htm b/tests/wpt/web-platform-tests/cors/basic.htm
new file mode 100644
index 00000000000..c46e9a0a15f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cors/basic.htm
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Basic CORS</title>
+<meta name=help href=http://dvcs.w3.org/hg/cors/raw-file/tip/Overview.html#simple-cross-origin-request-0>
+<meta name=author title="Odin Hørthe Omdal" href="mailto:odiho@opera.com">
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js?pipe=sub></script>
+<div id=log></div>
+
+<script>
+
+var counter = 0;
+
+function cors(desc, scheme, subdomain, port) {
+ if (!scheme) {
+ var url = "";
+ } else {
+ if (!port) {
+ port = location.port;
+ }
+ var url = scheme + "://" + (subdomain ? subdomain + "." : "") + location.hostname + ":" + port + dirname(location.pathname)
+ }
+ async_test(desc).step(function() {
+ var client = new XMLHttpRequest();
+ this.count = counter++;
+
+ client.open("GET", url + "resources/cors-makeheader.py?get_value=hest_er_best&origin=none&" + this.count);
+
+ client.onreadystatechange = this.step_func(function(e) {
+ // First request, test that it fails with no origin
+ if (client.readyState < 4) return;
+ if (!url)
+ assert_true(client.response.indexOf("hest_er_best") != -1, "Got response");
+ else
+ assert_false(!!client.response, "Got CORS-disallowed response");
+
+ client = new XMLHttpRequest();
+ client.open("GET", url + "resources/cors-makeheader.py?get_value=hest_er_best&" + this.count);
+ client.onreadystatechange = this.step_func(function(e) {
+ // Second request, test that it passes with the allowed-origin
+ if (client.readyState < 4) return;
+ assert_true(client.response.indexOf("hest_er_best") != -1, "Got CORS-allowed response");
+ this.done();
+ });
+ client.send();
+ });
+ client.send();
+ });
+}
+
+cors("Same domain basic usage");
+cors("Cross domain basic usage", "http", "www1");
+cors("Same domain different port", "http", undefined, PORT);
+
+cors("Cross domain different port", "http", "www1", PORT);
+
+cors("Cross domain different protocol", "https", "www1", PORTS);
+
+cors("Same domain different protocol different port", "https", undefined, PORTS);
+
+</script>
diff --git a/tests/wpt/web-platform-tests/cors/credentials-flag.htm b/tests/wpt/web-platform-tests/cors/credentials-flag.htm
new file mode 100644
index 00000000000..e631f2bb4ca
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cors/credentials-flag.htm
@@ -0,0 +1,129 @@
+<!DOCTYPE html>
+<title>CORS - Access-Control-Allow-Credentials</title>
+<meta name=author title="Odin Hørthe Omdal" href="mailto:odiho@opera.com">
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js?pipe=sub></script>
+
+<h1>CORS - Access-Control-Allow-Credentials</h1>
+<div id=log></div>
+<script>
+
+var url = CROSSDOMAIN + 'resources/cors-cookie.py?ident='
+
+
+/*
+ * widthCredentials
+ */
+// XXX Do some https tests here as well
+test(function () {
+ var client = new XMLHttpRequest()
+ client.open('GET', CROSSDOMAIN, false)
+ assert_throws(null, function() { client.withCredentials = true; }, 'setting withCredentials')
+}, 'Setting withCredentials on a sync XHR object should throw')
+
+async_test(function () {
+ var id = new Date().getTime() + '_1',
+ client = new XMLHttpRequest()
+ client.open("GET", url + id, true)
+ client.onload = this.step_func(function() {
+ assert_equals(client.response, "NO_COOKIE")
+ client.open("GET", url + id, true)
+ client.onload = this.step_func(function() {
+ assert_equals(client.response, "NO_COOKIE")
+ this.done()
+ })
+ client.send(null)
+ })
+ client.send(null)
+
+}, "Don't send cookie by default");
+
+async_test(function () {
+ var id = new Date().getTime() + '_2',
+ client = new XMLHttpRequest()
+
+ client.open("GET", url + id, true)
+ client.withCredentials = true
+ client.onload = this.step_func(function() {
+ assert_equals(client.response, "NO_COOKIE", "No cookie in initial request");
+
+ /* We have cookie, but the browser shouldn't send */
+ client.open("GET", url + id, true)
+ client.withCredentials = false
+ client.onload = this.step_func(function() {
+ assert_equals(client.response, "NO_COOKIE", "No cookie after withCredentials=false sync request")
+
+ /* Reads and deletes the cookie */
+ client.open("GET", url + id, true)
+ client.withCredentials = true
+ client.onload = this.step_func(function() {
+ assert_equals(client.response, "COOKIE", "Cookie sent in withCredentials=true sync request")
+ this.done()
+ })
+ client.send(null)
+ })
+ client.send(null)
+ })
+ client.send(null)
+}, "Don't send cookie part 2");
+
+async_test(function () {
+ var id = new Date().getTime() + '_3',
+ client = new XMLHttpRequest()
+
+ /* Shouldn't set the response cookie */
+ client.open("GET", url + id, true)
+ client.withCredentials = false
+ client.onload = this.step_func(function() {
+ console.log(client.response + '_', client.response)
+ assert_equals(client.response, "NO_COOKIE", "first");
+
+ /* Sets the cookie */
+ client.open("GET", url + id, true)
+ client.withCredentials = true
+ client.onload = this.step_func(function() {
+ assert_equals(client.response, "NO_COOKIE", "second")
+
+ /* Reads and deletes the cookie */
+ client.open("GET", url + id, true)
+ client.withCredentials = true
+ client.onload = this.step_func(function() {
+ assert_equals(client.response, "COOKIE", "third")
+ this.done()
+ })
+ client.send(null)
+ })
+ client.send(null)
+ })
+ client.send(null)
+}, "Don't obey Set-Cookie when withCredentials=false");
+
+function test_response_header(allow) {
+ var resp_test = async_test('Access-Control-Allow-Credentials: ' + allow + ' should be disallowed (async)')
+ resp_test.step(function() {
+ var client = new XMLHttpRequest()
+ client.open('GET',
+ CROSSDOMAIN + 'resources/cors-makeheader.py?credentials=' + allow,
+ true)
+ client.withCredentials = true;
+ client.onload = resp_test.step_func(function() {
+ assert_unreached("onload")
+ })
+ client.onerror = resp_test.step_func(function () {
+ assert_equals(client.readyState, client.DONE, 'readyState')
+ resp_test.done()
+ })
+ client.send()
+ })
+}
+
+test_response_header('TRUE')
+test_response_header('True')
+test_response_header('"true"')
+test_response_header('false')
+test_response_header('1')
+test_response_header('0')
+
+</script>
diff --git a/tests/wpt/web-platform-tests/cors/late-upload-events.htm b/tests/wpt/web-platform-tests/cors/late-upload-events.htm
new file mode 100644
index 00000000000..367955aa4b8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cors/late-upload-events.htm
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Adding upload event listeners after send()</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js?pipe=sub></script>
+
+<h1>Adding upload event listeners after send()</h1>
+
+<div id=log></div>
+
+<script>
+function doTest(desc, headers, expectEvents) {
+ async_test("Late listeners: " + desc).step(function() {
+ var client = new XMLHttpRequest();
+ var eventCounter = 0;
+ client.open("POST", CROSSDOMAIN + "resources/status.py?headers=custom-header");
+
+ for (var name in headers) {
+ client.setRequestHeader(name, headers[name]);
+ }
+
+ client.onreadystatechange = this.step_func(function(e) {
+ // Irrelevant if request is not finished
+ if (client.readyState < 4) return;
+ assert_equals(client.status, 200);
+ if (expectEvents) {
+ assert_true(eventCounter > 3, 'Events did fire');
+ } else {
+ assert_equals(eventCounter, 0, 'No events did fire');
+ }
+ this.done();
+ });
+ client.send((new Array(3000)).join('xo'));
+ client.upload.onprogress = client.upload.onloadend = client.upload.onloadstart = client.upload.onload = this.step_func(function(e) {
+ eventCounter++;
+ if (!expectEvents) {
+ assert_unreached("Upload events should not fire, but did: " + e.type);
+ }
+ });
+ });
+}
+
+doTest("No preflight", {}, false);
+doTest("Preflight", {"custom-header":"test"}, true);
+</script>
diff --git a/tests/wpt/web-platform-tests/cors/origin.htm b/tests/wpt/web-platform-tests/cors/origin.htm
new file mode 100644
index 00000000000..a090b3340fc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cors/origin.htm
@@ -0,0 +1,119 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Access-Control-Allow-Origin handling</title>
+<meta name=help href=http://dvcs.w3.org/hg/cors/raw-file/tip/Overview.html#resource-sharing-check>
+<meta name=author title="Odin Hørthe Omdal" href="mailto:odiho@opera.com">
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js?pipe=sub></script>
+
+<h1>Access-Control-Allow-Origin handling</h1>
+
+<div id=log></div>
+
+<script>
+
+/*
+ * Origin header
+ */
+function shouldPass(origin) {
+ test(function () {
+ var client = new XMLHttpRequest()
+ client.open('GET', CROSSDOMAIN
+ + '/resources/cors-makeheader.py?origin='
+ + encodeURIComponent(origin),
+ false)
+ client.send()
+ r = JSON.parse(client.response)
+ var host = location.protocol + "//" + location.host
+ assert_equals(r['origin'], host, 'Request Origin: should be ' + host)
+ }, 'Allow origin: ' + origin.replace(/\t/g, "[tab]").replace(/ /g, '_'));
+}
+
+shouldPass('*');
+shouldPass(' * ');
+shouldPass(' *');
+shouldPass(location.protocol + "//" + location.host);
+shouldPass(" "+location.protocol + "//" + location.host);
+shouldPass(" "+location.protocol + "//" + location.host + " ");
+shouldPass(" "+location.protocol + "//" + location.host);
+
+
+function shouldFail(origin) {
+ test(function () {
+ var client = new XMLHttpRequest()
+ client.open('GET', CROSSDOMAIN
+ + '/resources/cors-makeheader.py?origin='
+ + encodeURIComponent(origin),
+ false)
+ assert_throws(null, function() { client.send() }, 'send')
+ }, 'Disallow origin: ' + origin.replace(/\0/g, "\\0"));
+}
+
+shouldFail(location.protocol + "//" + SUBDOMAIN + "." + location.host)
+shouldFail("//" + location.host)
+shouldFail("://" + location.host)
+shouldFail("ftp://" + location.host)
+shouldFail("http:://" + location.host)
+shouldFail("http:/" + location.host)
+shouldFail("http:" + location.host)
+shouldFail(location.host)
+shouldFail(location.protocol + "//" + location.host + "?")
+shouldFail(location.protocol + "//" + location.host + "/")
+shouldFail(location.protocol + "//" + location.host + " /")
+shouldFail(location.protocol + "//" + location.host + "#")
+shouldFail(location.protocol + "//" + location.host + "%23")
+shouldFail(location.protocol + "//" + location.host + ":80")
+shouldFail(location.protocol + "//" + location.host + ", *")
+shouldFail(location.protocol + "//" + location.host + "\0")
+shouldFail((location.protocol + "//" + location.host).toUpperCase())
+shouldFail(location.protocol.toUpperCase() + "//" + location.host)
+shouldFail("-")
+shouldFail("**")
+shouldFail("\0*")
+shouldFail("*\0")
+shouldFail("'*'")
+shouldFail('"*"')
+shouldFail("* *")
+shouldFail("* null")
+shouldFail("*" + location.protocol + "//" + "*")
+shouldFail("*" + location.protocol + "//" + location.host)
+shouldFail("* " + location.protocol + "//" + location.host)
+shouldFail("*, " + location.protocol + "//" + location.host)
+shouldFail("\0" + location.protocol + "//" + location.host)
+shouldFail("null " + location.protocol + "//" + location.host)
+shouldFail('http://example.net')
+shouldFail('null')
+shouldFail('null *')
+shouldFail('')
+shouldFail(location.href)
+shouldFail(dirname(location.href))
+shouldFail(CROSSDOMAIN)
+shouldFail(location.host.replace(/^[^\.]+\./, ""))
+shouldFail("." + location.host.replace(/^[^\.]+\./, ""))
+shouldFail("*." + location.host.replace(/^[^\.]+\./, ""))
+shouldFail("http://" + location.host.replace(/^[^\.]+\./, ""))
+shouldFail("http://." + location.host.replace(/^[^\.]+\./, ""))
+shouldFail("http://*." + location.host.replace(/^[^\.]+\./, ""))
+
+function doubleOrigin(origin, origin2) {
+ test(function () {
+ var client = new XMLHttpRequest()
+ client.open('GET', CROSSDOMAIN
+ + '/resources/cors-makeheader.py?origin='
+ + encodeURIComponent(origin)
+ + '&origin2=' + encodeURIComponent(origin2),
+ false)
+ assert_throws(null, function() { client.send() }, 'send')
+ }, 'Disallow multiple headers (' + origin + ', ' + origin2 + ')');
+}
+
+doubleOrigin('', '*');
+doubleOrigin('*', '');
+doubleOrigin('*', '*');
+doubleOrigin('', location.protocol + "//" + location.host);
+doubleOrigin('*', location.protocol + "//" + location.host);
+doubleOrigin(location.protocol + "//" + location.host, location.protocol + "//" + location.host);
+
+</script>
diff --git a/tests/wpt/web-platform-tests/cors/preflight-cache.htm b/tests/wpt/web-platform-tests/cors/preflight-cache.htm
new file mode 100644
index 00000000000..f84c15ab3ca
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cors/preflight-cache.htm
@@ -0,0 +1,140 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>CORS - preflight cache</title>
+<meta name=author title="Odin Hørthe Omdal" href="mailto:odiho@opera.com">
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=/common/utils.js></script>
+<script src=support.js?pipe=sub></script>
+
+<h1>Preflight cache</h1>
+
+<div id=log></div>
+<script>
+
+/*
+ * Cache
+ */
+
+function did_preflight(expect, client, settings) {
+ var uuid_token = (settings && settings.token) || token();
+ if(!settings)
+ settings = {}
+
+ set = {
+ method: 'method' in settings ? settings.method : 'GET',
+ extra: 'extra' in settings ? '&' + settings.extra : ''
+ }
+
+ client.open(set.method,
+ CROSSDOMAIN + 'resources/preflight.py?token=' + uuid_token + set.extra,
+ false)
+ client.setRequestHeader('x-print', uuid_token)
+ client.send()
+
+ client.open('GET', 'resources/preflight.py?check&token=' + uuid_token, false)
+ client.send()
+ assert_equals(client.response, expect === true ? '1' : '0', "did preflight")
+ return uuid_token;
+}
+
+/*
+ * Should run preflight
+ */
+
+test(function() {
+ var time = new Date().getTime()
+ var client = new XMLHttpRequest()
+ did_preflight(true, client);
+},
+'Test preflight')
+
+test(function() {
+ var time = new Date().getTime()
+ var client = new XMLHttpRequest()
+
+ var id = did_preflight(true, client)
+ did_preflight(false, client, {token: id})
+},
+'preflight for x-print should be cached')
+
+test(function() {
+ var time = new Date().getTime()
+ var client = new XMLHttpRequest()
+
+ var id = did_preflight(true, client, {extra:'max_age=0'})
+ did_preflight(true, client, {extra:'max_age=0', token: id})
+},
+'age = 0, should not be cached')
+
+test(function() {
+ var time = new Date().getTime()
+ var client = new XMLHttpRequest()
+
+ var id = did_preflight(true, client, {extra:'max_age=-1'})
+ did_preflight(true, client, {extra:'max_age=-1', token: id})
+},
+'age = -1, should not be cached');
+
+(function() {
+ var test = async_test("preflight first request, second from cache, wait, third should preflight again", { timeout: 6000 }),
+ time = new Date().getTime(),
+ dothing = function (url, msg, set_request, func) {
+ client = new XMLHttpRequest(),
+ client.open('GET', url, true)
+ if (set_request)
+ client.setRequestHeader('x-print', msg)
+ client.onload = test.step_func(function() {
+ assert_equals(client.response, msg, "response " + url)
+ if (func)
+ test.step(func)
+ })
+ client.onerror = test.step_func(function(e) {
+ assert_unreached("Got unexpected error event on the XHR object")
+ })
+ client.send()
+ }
+
+ var token1 = token();
+ test.step(function() {
+ /* First cycle, gets x-print into the cache, with timeout 1 */
+ var request_url = CROSSDOMAIN + 'resources/preflight.py?max_age=1&token=' + token1;
+ dothing(request_url,
+ 'first', true, function() {
+ test = test;
+
+ /* Check if we did a preflight like we expected */
+ dothing('resources/preflight.py?check&1&token=' + token1,
+ '1', false, function() {
+ test = test;
+ dothing(request_url,
+ 'second', true, function() {
+ test = test;
+
+ /* Check that we didn't do a preflight (hasn't gone 1 second yet) */
+ dothing('resources/preflight.py?check&2&token=' + token1,
+ '0', false, function() {
+ test = test;
+
+ /* Wait until the preflight cache age is old (and thus cleared) */
+ setTimeout(test.step_func(function(){
+ dothing(request_url,
+ 'third', true, function() {
+ test = test;
+
+ /* Expect that we did indeed do a preflight */
+ dothing('resources/preflight.py?check&3&token=' + token1,
+ '1', false, function() {
+ test.done()
+ })
+ })
+ }), 1500)
+ })
+ })
+ })
+ })
+ })
+})();
+
+</script>
diff --git a/tests/wpt/web-platform-tests/cors/redirect-origin.htm b/tests/wpt/web-platform-tests/cors/redirect-origin.htm
new file mode 100644
index 00000000000..5463292fa5d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cors/redirect-origin.htm
@@ -0,0 +1,195 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>CORS - redirect</title>
+<meta name=author title="Odin Hørthe Omdal" href="mailto:odiho@opera.com">
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js?pipe=sub></script>
+
+<h1>CORS redirect handling</h1>
+
+<div id=log></div>
+
+<script>
+
+ // Test count for cache busting and easy identifying of request in traffic analyzer
+ var num_test = 0,
+
+ origin = location.protocol + "//" + location.host,
+ remote_origin = origin.replace('://', '://' + SUBDOMAIN + '.'),
+
+ local = dirname(location.href) + 'resources/cors-makeheader.py',
+ remote = local.replace('://', '://' + SUBDOMAIN + '.'),
+ remote2 = local.replace('://', '://' + SUBDOMAIN2 + '.');
+
+
+ /* First page Redirect to Expect what */
+
+ // local -> remote
+
+ redir_test([ 'local', '*' ], [ 'remote', '*' ], origin );
+ redir_test([ 'local', '*' ], [ 'remote', origin ], origin );
+ redir_test([ 'local', '*' ], [ 'remote', 'null' ], 'disallow');
+ redir_test([ 'local', '*' ], [ 'remote', 'none' ], 'disallow');
+
+ redir_test([ 'local', origin ], [ 'remote', '*' ], origin );
+ redir_test([ 'local', origin ], [ 'remote', origin ], origin );
+ redir_test([ 'local', origin ], [ 'remote', 'null' ], 'disallow');
+ redir_test([ 'local', origin ], [ 'remote', 'none' ], 'disallow');
+
+ redir_test([ 'local', 'null' ], [ 'remote', '*' ], origin );
+ redir_test([ 'local', 'none' ], [ 'remote', '*' ], origin );
+
+
+ // remote -> local
+
+ redir_test([ 'remote', '*' ], [ 'local', '*' ], 'null' );
+ redir_test([ 'remote', '*' ], [ 'local', origin ], 'disallow');
+ redir_test([ 'remote', '*' ], [ 'local', 'null' ], 'null' );
+ redir_test([ 'remote', '*' ], [ 'local', 'none' ], 'disallow');
+
+ redir_test([ 'remote', origin ], [ 'local', '*' ], 'null' );
+ redir_test([ 'remote', origin ], [ 'local', origin ], 'disallow');
+ redir_test([ 'remote', origin ], [ 'local', 'null' ], 'null' );
+ redir_test([ 'remote', origin ], [ 'local', 'none' ], 'disallow');
+
+ redir_test([ 'remote', 'null' ], [ 'local', '*' ], 'disallow');
+ redir_test([ 'remote', 'none' ], [ 'local', '*' ], 'disallow');
+
+
+ // remote -> remote
+
+ redir_test([ 'remote', '*' ], [ 'remote', '*' ], origin );
+ redir_test([ 'remote', '*' ], [ 'remote', origin ], origin );
+ redir_test([ 'remote', '*' ], [ 'remote', 'null' ], 'disallow');
+ redir_test([ 'remote', '*' ], [ 'remote', 'none' ], 'disallow');
+
+ redir_test([ 'remote', origin ], [ 'remote', '*' ], origin );
+ redir_test([ 'remote', origin ], [ 'remote', origin ], origin );
+ redir_test([ 'remote', origin ], [ 'remote', 'null' ], 'disallow');
+ redir_test([ 'remote', origin ], [ 'remote', 'none' ], 'disallow');
+
+ redir_test([ 'remote', 'null' ], [ 'remote', '*' ], 'disallow');
+ redir_test([ 'remote', 'none' ], [ 'remote', '*' ], 'disallow');
+
+
+ // remote -> remote2
+
+ redir_test([ 'remote', '*' ], [ 'remote2', '*' ], 'null' );
+ redir_test([ 'remote', '*' ], [ 'remote2', origin ], 'disallow');
+ redir_test([ 'remote', '*' ], [ 'remote2', 'null' ], 'null' );
+ redir_test([ 'remote', '*' ], [ 'remote2', 'none' ], 'disallow');
+
+ redir_test([ 'remote', origin ], [ 'remote2', '*' ], 'null' );
+ redir_test([ 'remote', origin ], [ 'remote2', origin ], 'disallow');
+ redir_test([ 'remote', origin ], [ 'remote2', 'null' ], 'null');
+ redir_test([ 'remote', origin ], [ 'remote2', 'none' ], 'disallow');
+
+ redir_test([ 'remote', 'null' ], [ 'remote2', '*' ], 'disallow');
+ redir_test([ 'remote', 'none' ], [ 'remote2', '*' ], 'disallow');
+
+
+ // Bonus weird edge checks
+
+ redir_test([ 'remote', '*' ], [ 'remote', remote_origin ], 'disallow');
+ redir_test([ 'remote', '*' ], [ 'remote2', remote_origin ], 'disallow');
+ redir_test([ 'remote', remote_origin ], [ 'remote', "*" ], 'disallow');
+
+
+
+ /*
+ * The helpers
+ */
+
+ function redir_test(first, second, expect_origin) {
+ var first_url, second_url,
+ urls = { "remote": remote, "local": local, "remote2": remote2 };
+
+ first_url = urls[first[0]] + "?origin=" + first[1];
+ second_url = urls[second[0]] + "?origin=" + second[1];
+
+ if (expect_origin=="disallow") {
+ shouldFail(first[0]+" ("+first[1]+") to "
+ + second[0]+" ("+second[1]+"), expect to fail", [ first_url, second_url ]);
+ }
+ else {
+ shouldPass(first[0]+" ("+first[1]+") to "
+ + second[0]+" ("+second[1]+"), expect origin="+expect_origin, expect_origin, [ first_url, second_url ]);
+ }
+
+ }
+
+ function shouldPass(desc, expected_origin, urls) {
+ var test_id = num_test,
+ t = async_test(desc);
+
+ num_test++;
+
+ t.step(function() {
+ var final_url,
+ client = new XMLHttpRequest();
+
+ client.open('GET', buildURL(urls, test_id));
+
+ client.onreadystatechange = t.step_func(function() {
+ if (client.readyState != client.DONE)
+ return;
+ assert_true(!!client.response, "Got response");
+ r = JSON.parse(client.response)
+ assert_equals(r['origin'], expected_origin, 'Origin Header')
+ assert_equals(r['get_value'], 'last', 'get_value')
+ t.done();
+ });
+ client.send(null)
+ });
+ }
+
+ function shouldFail(desc, urls) {
+ var test_id = num_test,
+ t = async_test(desc);
+
+ num_test++;
+
+ t.step(function() {
+ var client = new XMLHttpRequest();
+
+ client.open('GET', buildURL(urls, test_id));
+
+ client.onreadystatechange = t.step_func(function() {
+ if (client.readyState != client.DONE)
+ return;
+ assert_false(!!client.response, "Got response");
+ });
+ client.onerror = t.step_func(function(e) {
+ t.done();
+ });
+
+ client.send(null)
+ });
+ }
+
+
+ function buildURL(urls, id) {
+ var tmp_url;
+
+ if (typeof(urls) == "string") {
+ return urls + "&" + id + "_0";
+ }
+
+ for (var i = urls.length; i--; ) {
+ if (!tmp_url)
+ {
+ tmp_url = urls[i] + "&get_value=last&" + id + "_" + i;
+ continue;
+ }
+ tmp_url = urls[i]
+ + "&location="
+ + encodeURIComponent(tmp_url)
+ + "&" + id + "_" + i;
+ }
+
+ return tmp_url;
+ }
+
+</script>
diff --git a/tests/wpt/web-platform-tests/cors/redirect-preflight-2.htm b/tests/wpt/web-platform-tests/cors/redirect-preflight-2.htm
new file mode 100644
index 00000000000..fe58d90a26e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cors/redirect-preflight-2.htm
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>CORS - preflight after a redirect</title>
+<meta name=author title="Odin Hørthe Omdal" href="mailto:odiho@opera.com">
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js?pipe=sub></script>
+<script src=/common/utils.js></script>
+
+<h1>Preflight after redirect</h1>
+
+<div id=log></div>
+<script>
+
+async_test(function() {
+ var test_id = "fail_" + new Date().getTime()
+ var client = new XMLHttpRequest()
+ var last_url = CROSSDOMAIN + 'resources/cors-makeheader.py?origin=*&ident=' + test_id
+
+ client.open('GET', 'resources/cors-makeheader.py?origin=*&location=' + encodeURIComponent(last_url))
+ client.setRequestHeader('custom-header', 'admin')
+ client.onerror = this.step_func(function() {
+ this.done()
+ })
+ client.onload = this.step_func(function(e) { assert_unreached("Request should not succeed!") })
+ client.send()
+}, "Same-origin custom-header request, redirect to cross-origin fails after doing a non-successful preflight")
+
+
+async_test(function() {
+ var client = new XMLHttpRequest()
+ var uuid_token = token();
+ var last_url = CROSSDOMAIN + 'resources/cors-makeheader.py?headers=custom-header&origin=*&token=' + uuid_token;
+
+ client.open('GET', 'resources/cors-makeheader.py?origin=*&location=' + encodeURIComponent(last_url))
+ client.setRequestHeader('custom-header', 'admin')
+ client.onload = this.step_func(function() {
+ // Test that I got custom-header
+
+ /* To check whether we did a preflight */
+ client.open('GET', 'resources/cors-makeheader.py?check&token=' + uuid_token)
+ client.onload = this.step_func(function() {
+ assert_equals(client.response, "1", "did preflight")
+ this.done()
+ })
+ client.onerror = this.step_func(function(e) { assert_unreached("Error on getting preflight data") })
+ client.send()
+ })
+ client.onerror = this.step_func(function(e) { assert_unreached("Error during request", e) })
+ client.send()
+}, "Same-origin custom-header request, redirect to cross-origin succeeds after doing a preflight")
+
+
+</script>
diff --git a/tests/wpt/web-platform-tests/cors/redirect-preflight.htm b/tests/wpt/web-platform-tests/cors/redirect-preflight.htm
new file mode 100644
index 00000000000..bb47f2cae5d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cors/redirect-preflight.htm
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>CORS - redirect with preflight</title>
+<meta name=author title="Odin Hørthe Omdal" href="mailto:odiho@opera.com">
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js?pipe=sub></script>
+
+<h1>Redirect with preflight</h1>
+
+<div id=log></div>
+<script>
+
+var req_c = 0 // Request count for cache busting and easy identifying of request in traffic analyzer
+
+/*
+ * Redirection with preflights
+ */
+
+function redir_preflight(code) {
+ test(function() {
+ var client = new XMLHttpRequest(),
+ redirect = CROSSDOMAIN + 'resources/cors-makeheader.py?headers=x-test&' + req_c++
+
+ client.open('GET', CROSSDOMAIN + 'resources/cors-makeheader.py?'
+ + 'headers=x-test&location=' + encodeURIComponent(redirect)
+ + '&code=' + code + '&preflight=' + code + '&' + req_c++,
+ false)
+ client.setRequestHeader('x-test', 'test')
+ assert_throws(null, function() { client.send(null) });
+
+ },
+ 'Redirect ' + code + ' on preflight')
+}
+redir_preflight(301)
+redir_preflight(302)
+redir_preflight(303)
+redir_preflight(307)
+redir_preflight(308)
+
+/* Even thought the preflight was allowed (200), CORS should not follow
+ a subsequent redirect */
+function redir_after_preflight(code) {
+ test(function() {
+ var client = new XMLHttpRequest(),
+ redirect = CROSSDOMAIN + 'resources/cors-makeheader.py?headers=x-test&' + req_c++
+
+ client.open('GET', CROSSDOMAIN + 'resources/cors-makeheader.py?'
+ + 'preflight=200&headers=x-test&location='
+ + encodeURIComponent(redirect) + '&code=' + code + '&' + req_c++,
+ false)
+ client.setRequestHeader('x-test', 'test')
+ assert_throws(null, function() { client.send(null) });
+
+ },
+ 'Disallow redirect ' + code + ' after succesful (200) preflight')
+}
+redir_after_preflight(301)
+redir_after_preflight(302)
+redir_after_preflight(303)
+redir_after_preflight(307)
+redir_after_preflight(308)
+
+</script>
diff --git a/tests/wpt/web-platform-tests/cors/redirect-userinfo.htm b/tests/wpt/web-platform-tests/cors/redirect-userinfo.htm
new file mode 100644
index 00000000000..1775d30dfb1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cors/redirect-userinfo.htm
@@ -0,0 +1,110 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>CORS - redirect with userinfo</title>
+<meta name=author title="Odin Hørthe Omdal" href="mailto:odinho@opera.com">
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js?pipe=sub></script>
+
+<h1>CORS userinfo redirect handling</h1>
+
+<div id=log></div>
+
+<script>
+
+ // Test count for cache busting and easy identifying of request in traffic analyzer
+ var num_test = 0
+
+ shouldFail("Disallow redirect with userinfo (//user:pass@)", [
+ CROSSDOMAIN + "resources/cors-makeheader.py?",
+ CROSSDOMAIN.replace("http://", "http://test:test@") + "resources/cors-makeheader.py?"]);
+
+ shouldFail("Disallow redirect with userinfo (//user:@)", [
+ CROSSDOMAIN + "resources/cors-makeheader.py?",
+ CROSSDOMAIN.replace("http://", "http://user:@") + "resources/cors-makeheader.py?"]);
+
+ shouldFail("Disallow redirect with userinfo (//user@)", [
+ CROSSDOMAIN + "resources/cors-makeheader.py?",
+ CROSSDOMAIN.replace("http://", "http://user:@") + "resources/cors-makeheader.py?"]);
+
+ shouldFail("Disallow redirect with userinfo (//:@)", [
+ CROSSDOMAIN + "resources/cors-makeheader.py?",
+ CROSSDOMAIN.replace("http://", "http://:@") + "resources/cors-makeheader.py?"]);
+
+ shouldFail("Disallow redirect with userinfo (//:pass@)", [
+ CROSSDOMAIN + "resources/cors-makeheader.py?",
+ CROSSDOMAIN.replace("http://", "http://:pass@") + "resources/cors-makeheader.py?"]);
+
+ shouldPass("Allow redirect with userinfo (//@)", [
+ CROSSDOMAIN + "resources/cors-makeheader.py?",
+ CROSSDOMAIN.replace("http://", "http://@") + "resources/cors-makeheader.py?"]);
+
+ function shouldFail(desc, urls) {
+ var test_id = num_test,
+ t = async_test(desc);
+
+ num_test++;
+
+ t.step(function() {
+ var client = new XMLHttpRequest();
+
+ client.open('GET', buildURL(urls, test_id));
+
+ client.onload = t.step_func(function() {
+ assert_false(!!client.response, "Got response");
+ });
+ client.onerror = t.step_func(function(e) {
+ t.done();
+ });
+
+ client.send(null)
+ });
+ }
+
+ function shouldPass(desc, urls) {
+ var test_id = num_test,
+ t = async_test(desc);
+
+ num_test++;
+
+ t.step(function() {
+ var client = new XMLHttpRequest();
+
+ client.open('GET', buildURL(urls, test_id));
+
+ client.onreadystatechange = t.step_func(function() {
+ if (client.readyState != client.DONE)
+ return;
+ assert_true(!!client.response, "Got response");
+ r = JSON.parse(client.response)
+ assert_equals(r['get_value'], 'last', 'get_value')
+ t.done();
+ });
+ client.send(null)
+ });
+ }
+
+ function buildURL(urls, id) {
+ var tmp_url;
+
+ if (typeof(urls) == "string") {
+ return urls + "&" + id + "_0";
+ }
+
+ for (var i = urls.length; i--; ) {
+ if (!tmp_url)
+ {
+ tmp_url = urls[i] + "&get_value=last&" + id + "_" + i;
+ continue;
+ }
+ tmp_url = urls[i]
+ + "&location="
+ + encodeURIComponent(tmp_url)
+ + "&" + id + "_" + i;
+ }
+
+ return tmp_url;
+ }
+
+</script>
diff --git a/tests/wpt/web-platform-tests/cors/remote-origin.htm b/tests/wpt/web-platform-tests/cors/remote-origin.htm
new file mode 100644
index 00000000000..a0a0d74cabf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cors/remote-origin.htm
@@ -0,0 +1,122 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Access-Control-Allow-Origin handling</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js?pipe=sub></script>
+
+<h1>Access-Control-Allow-Origin handling</h1>
+
+<div id=log></div>
+
+<script>
+
+var remote_tests = [];
+var iframe = document.createElement("iframe")
+iframe.src = CROSSDOMAIN + 'resources/remote-xhrer.html';
+document.body.appendChild(iframe);
+
+function reverseOrigin(expect_pass, origin)
+{
+ var real_origin = origin.replace("<host>", REMOTE_HOST)
+ .replace("<remote_origin>", location.protocol + "//" + location.host)
+ .replace("<origin>", REMOTE_ORIGIN)
+ .replace("<protocol>", REMOTE_PROTOCOL)
+ .replace("<HOST>", REMOTE_HOST.toUpperCase())
+ .replace("<ORIGIN>", REMOTE_ORIGIN.toUpperCase())
+ .replace("<PROTOCOL>", REMOTE_PROTOCOL.toUpperCase());
+
+ var t = async_test((expect_pass ? 'Allow origin: ' : 'Disallow origin: ') + real_origin
+ .replace(/\0/g, "\\0")
+ .replace(/\t/g, "[tab]")
+ .replace(/ /g, '_'));
+ t.step(function() {
+ this.test_url = dirname(location.href)
+ + 'resources/cors-makeheader.py?origin='
+ + encodeURIComponent(real_origin);
+ iframe.contentWindow.postMessage({ url: this.test_url, origin: origin }, "*");
+ });
+
+ if (expect_pass)
+ {
+ t.callback = t.step_func(function(e) {
+ assert_equals(e.state, "load");
+ r = JSON.parse(e.response)
+ assert_equals(r['origin'], REMOTE_ORIGIN, 'Request Origin: should be ' + REMOTE_ORIGIN)
+ this.done();
+ });
+ }
+ else
+ {
+ t.callback = t.step_func(function(e) {
+ if (e.response) console.log(e.response);
+ assert_equals(e.state, "error");
+ assert_equals(e.response, "");
+ this.done();
+ });
+ }
+
+ remote_tests[origin] = t;
+}
+
+function shouldPass(origin) { reverseOrigin(true, origin); }
+function shouldFail(origin) { reverseOrigin(false, origin); }
+
+
+iframe.onload = function() {
+ shouldPass('*');
+ shouldPass(' * ');
+ shouldPass(' *');
+ shouldPass("<origin>");
+ shouldPass(" <origin>");
+ shouldPass(" <origin> ");
+ shouldPass(" <origin>");
+
+ shouldFail("<remote_origin>")
+ shouldFail("//" + "<host>")
+ shouldFail("://" + "<host>")
+ shouldFail("ftp://" + "<host>")
+ shouldFail("http:://" + "<host>")
+ shouldFail("http:/" + "<host>")
+ shouldFail("http:" + "<host>")
+ shouldFail("<host>")
+ shouldFail("<origin>" + "?")
+ shouldFail("<origin>" + "/")
+ shouldFail("<origin>" + " /")
+ shouldFail("<origin>" + "#")
+ shouldFail("<origin>" + "%23")
+ shouldFail("<origin>" + ":80")
+ shouldFail("<origin>" + ", *")
+ shouldFail("<origin>" + "\0")
+ shouldFail(("<ORIGIN>"))
+ shouldFail("<PROTOCOL>//<host>")
+ shouldFail("<protocol>//<HOST>")
+ shouldFail("-")
+ shouldFail("**")
+ shouldFail("\0*")
+ shouldFail("*\0")
+ shouldFail("'*'")
+ shouldFail('"*"')
+ shouldFail("* *")
+ shouldFail("*" + "<protocol>" + "//" + "*")
+ shouldFail("*" + "<origin>")
+ shouldFail("* " + "<origin>")
+ shouldFail("*, " + "<origin>")
+ shouldFail("\0" + "<origin>")
+ shouldFail("null " + "<origin>")
+ shouldFail('http://example.net')
+ shouldFail('null')
+ shouldFail('')
+ shouldFail(location.href)
+ shouldFail(dirname(location.href))
+ shouldFail(CROSSDOMAIN)
+}
+
+window.addEventListener("message", function(e) {
+ remote_tests[e.data.origin].callback(e.data);
+});
+
+add_completion_callback(function() {
+ iframe.parentElement.removeChild(iframe);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/cors/request-headers.htm b/tests/wpt/web-platform-tests/cors/request-headers.htm
new file mode 100644
index 00000000000..8adaeb4f8bd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cors/request-headers.htm
@@ -0,0 +1,80 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>CORS - request headers - Access-Control-Allow-Headers</title>
+<meta name=author title="Odin Hørthe Omdal" href="mailto:odiho@opera.com">
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js?pipe=sub></script>
+
+<h1>Request headers</h1>
+<div id=log></div>
+<script>
+
+/*
+ * Request Headers
+ */
+
+test(function() {
+ var client = new XMLHttpRequest()
+ client.open('GET', CROSSDOMAIN + 'resources/cors-makeheader.py?headers=x-print', false)
+ client.setRequestHeader('x-print', 'unicorn')
+ client.send(null)
+
+ res = JSON.parse(client.response)
+ assert_equals(res['x-print'], 'unicorn')
+}, 'basic request header')
+
+test(function() {
+ var client = new XMLHttpRequest()
+ client.open('GET', CROSSDOMAIN + 'resources/cors-makeheader.py?headers=x-print,', false)
+ client.setRequestHeader('x-print', 'unicorn')
+ client.setRequestHeader('content-type', 'text/plain')
+ client.setRequestHeader('accept', 'test')
+ client.setRequestHeader('accept-language', 'nn')
+ client.setRequestHeader('content-language', 'nn')
+ client.send(null)
+
+ res = JSON.parse(client.response)
+ assert_equals(res['x-print'], 'unicorn')
+ assert_equals(res['content-type'], 'text/plain')
+ assert_equals(res['accept'], 'test')
+ assert_equals(res['accept-language'], 'nn')
+ assert_equals(res['content-language'], 'nn')
+}, 'Simple request headers need not be in allow-headers')
+
+test(function() {
+ var client = new XMLHttpRequest()
+ client.open('GET', CROSSDOMAIN + 'resources/cors-makeheader.py?headers=x-print', false)
+ client.setRequestHeader('x-print', 'unicorn')
+ client.setRequestHeader('y-print', 'unicorn')
+ assert_throws(null, function() { client.send(null) })
+}, 'Unspecified request headers are disallowed')
+
+test(function() {
+ var client = new XMLHttpRequest()
+ client.open('GET', CROSSDOMAIN + 'resources/cors-makeheader.py?headers=,y-lol,x-PriNT,%20,,,Y-PRINT', false)
+ client.setRequestHeader('x-print', 'unicorn')
+ client.setRequestHeader('y-print', 'narwhal')
+ client.send(null)
+
+ res = JSON.parse(client.response)
+ assert_equals(res['x-print'], 'unicorn')
+ assert_equals(res['y-print'], 'narwhal')
+}, 'Strange allowheaders (case insensitive)')
+
+test(function() {
+ var client = new XMLHttpRequest()
+ assert_throws('INVALID_STATE_ERR', function() { client.setRequestHeader('x-print', 'unicorn') })
+},
+'INVALID_STATE_ERR on setRequestHeader before open()')
+
+test(function() {
+ var client = new XMLHttpRequest()
+ client.open('GET', CROSSDOMAIN + 'resources/cors-makeheader.py?headers=,y-lol,x-PriNT,%20,,,Y-PRINT', false)
+ client.send()
+ assert_throws('INVALID_STATE_ERR', function() { client.setRequestHeader('x-print', 'unicorn') })
+},
+'INVALID_STATE_ERR on setRequestHeader after send()')
+
+</script>
diff --git a/tests/wpt/web-platform-tests/cors/resources/.gitignore b/tests/wpt/web-platform-tests/cors/resources/.gitignore
new file mode 100644
index 00000000000..7b987d03655
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cors/resources/.gitignore
@@ -0,0 +1 @@
+logs.txt
diff --git a/tests/wpt/web-platform-tests/cors/resources/checkandremove.py b/tests/wpt/web-platform-tests/cors/resources/checkandremove.py
new file mode 100644
index 00000000000..f713d990afc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cors/resources/checkandremove.py
@@ -0,0 +1,6 @@
+def main(request, response):
+ token = request.GET.first("token")
+ if request.server.stash.remove(token) is not None:
+ return "1"
+ else:
+ return "0"
diff --git a/tests/wpt/web-platform-tests/cors/resources/cors-cookie.py b/tests/wpt/web-platform-tests/cors/resources/cors-cookie.py
new file mode 100644
index 00000000000..76fa6c165ba
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cors/resources/cors-cookie.py
@@ -0,0 +1,21 @@
+
+def main(request, response):
+ origin = request.GET.first("origin", request.headers["origin"])
+ credentials = request.GET.first("credentials", "true")
+
+ headers = [("Content-Type", "text/plain")]
+ if origin != 'none':
+ headers.append(("Access-Control-Allow-Origin", origin))
+ if credentials != 'none':
+ headers.append(("Access-Control-Allow-Credentials", credentials))
+
+ ident = request.GET.first('ident', 'test')
+
+ if ident in request.cookies:
+ body = request.cookies[ident].value
+ response.delete_cookie(ident)
+ else:
+ response.set_cookie(ident, "COOKIE");
+ body = "NO_COOKIE"
+
+ return headers, body
diff --git a/tests/wpt/web-platform-tests/cors/resources/cors-headers.asis b/tests/wpt/web-platform-tests/cors/resources/cors-headers.asis
new file mode 100644
index 00000000000..ce21245f124
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cors/resources/cors-headers.asis
@@ -0,0 +1,24 @@
+HTTP/1.1 200 OK
+Access-Control-Allow-Origin: *
+Access-Control-Expose-Headers: X-Custom-Header, X-Custom-Header-Empty, X-Custom-Header-Comma, X-Custom-Header-Bytes
+Access-Control-Expose-Headers: X-Second-Expose
+Access-Control-Expose-Headers: Date
+Content-Type: text/plain
+X-Custom-Header: test
+X-Custom-Header: test
+Set-Cookie: test1=t1;max-age=2
+Set-Cookie2: test2=t2;Max-Age=2
+X-Custom-Header-Empty:
+X-Custom-Header-Comma: 1
+X-Custom-Header-Comma: 2
+X-Custom-Header-Bytes: …
+X-Nonexposed: unicorn
+X-Second-Expose: flyingpig
+Cache-Control: no-cache
+Content-Language: nn
+Expires: Thu, 01 Dec 1994 16:00:00 GMT
+Last-Modified: Thu, 01 Dec 1994 10:00:00 GMT
+Pragma: no-cache
+Date: Wed, 22 Oct 2013 10:00:00 GMT
+
+TEST
diff --git a/tests/wpt/web-platform-tests/cors/resources/cors-makeheader.py b/tests/wpt/web-platform-tests/cors/resources/cors-makeheader.py
new file mode 100644
index 00000000000..afd9e3642ee
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cors/resources/cors-makeheader.py
@@ -0,0 +1,64 @@
+import json
+
+def main(request, response):
+ origin = request.GET.first("origin", request.headers.get('origin'))
+
+ if "check" in request.GET:
+ token = request.GET.first("token")
+ value = request.server.stash.take(token)
+ if value is not None:
+ if request.GET.first("check", None) == "keep":
+ request.server.stash.put(token, value)
+ body = "1"
+ else:
+ body = "0"
+ return [("Content-Type", "text/plain")], body
+
+
+ if origin != 'none':
+ response.headers.set("Access-Control-Allow-Origin", origin)
+ if 'origin2' in request.GET:
+ response.headers.append("Access-Control-Allow-Origin", request.GET.first('origin2'))
+
+ #Preflight
+ if 'headers' in request.GET:
+ response.headers.set("Access-Control-Allow-Headers", request.GET.first('headers'))
+ if 'credentials' in request.GET:
+ response.headers.set("Access-Control-Allow-Credentials", request.GET.first('credentials'))
+ if 'methods' in request.GET:
+ response.headers.set("Access-Control-Allow-Methods", request.GET.first('methods'))
+
+ code = request.GET.first('code', None)
+ if request.method == 'OPTIONS':
+ #Override the response code if we're in a preflight and it's asked
+ if 'preflight' in request.GET:
+ code = int(request.GET.first('preflight'))
+
+ #Log that the preflight actually happened if we have an ident
+ if 'token' in request.GET:
+ request.server.stash.put(request.GET['token'])
+
+ if 'location' in request.GET:
+ if code is None:
+ code = 302
+
+ if code >= 300 and code < 400:
+ response.headers.set("Location", request.GET.first('location'))
+
+ headers = {}
+ for name, values in request.headers.iteritems():
+ if len(values) == 1:
+ headers[name] = values[0]
+ else:
+ #I have no idea, really
+ headers[name] = values
+
+ headers['get_value'] = request.GET.first('get_value', '')
+
+ body = json.dumps(headers)
+
+ if code:
+ return (code, "StatusText"), [], body
+ else:
+ return body
+
diff --git a/tests/wpt/web-platform-tests/cors/resources/preflight.py b/tests/wpt/web-platform-tests/cors/resources/preflight.py
new file mode 100644
index 00000000000..978e97c5d1e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cors/resources/preflight.py
@@ -0,0 +1,35 @@
+def main(request, response):
+ headers = [("Content-Type", "text/plain")]
+
+ if "check" in request.GET:
+ token = request.GET.first("token")
+ value = request.server.stash.take(token)
+ if value == None:
+ body = "0"
+ else:
+ if request.GET.first("check", None) == "keep":
+ request.server.stash.put(token, value)
+ body = "1"
+
+ return headers, body
+
+ if request.method == "OPTIONS":
+ if not "Access-Control-Request-Method" in request.headers:
+ response.set_error(400, "No Access-Control-Request-Method header")
+ return "ERROR: No access-control-request-method in preflight!"
+
+ headers.append(("Access-Control-Allow-Methods",
+ request.headers['Access-Control-Request-Method']))
+
+ if "max_age" in request.GET:
+ headers.append(("Access-Control-Max-Age", request.GET['max_age']))
+
+ if "token" in request.GET:
+ request.server.stash.put(request.GET.first("token"), 1)
+
+ headers.append(("Access-Control-Allow-Origin", "*"))
+ headers.append(("Access-Control-Allow-Headers", "x-print"))
+
+ body = request.headers.get("x-print", "NO")
+
+ return headers, body
diff --git a/tests/wpt/web-platform-tests/cors/resources/remote-xhrer.html b/tests/wpt/web-platform-tests/cors/resources/remote-xhrer.html
new file mode 100644
index 00000000000..73a7cb444ff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cors/resources/remote-xhrer.html
@@ -0,0 +1,28 @@
+<!doctype html>
+<title>Child helper</title>
+
+<script>
+window.addEventListener("message", function(e) {
+// e.source.postMessage(e.data, e.origin);
+
+ var client = new XMLHttpRequest();
+ var localurl = e.data.url
+ .replace("<host>", location.host)
+ .replace("<protocol>", location.protocol);
+
+ client.open('GET', localurl, true);
+ client.onload = function() {
+ e.data.state = "load";
+ e.data.response = client.response;
+ e.source.postMessage(e.data, e.origin);
+ }
+ client.onerror = function() {
+ e.data.state = "error";
+ e.data.response = client.response;
+ e.source.postMessage(e.data, e.origin);
+ }
+ client.send();
+});
+</script>
+
+The remote window
diff --git a/tests/wpt/web-platform-tests/cors/resources/status.py b/tests/wpt/web-platform-tests/cors/resources/status.py
new file mode 100644
index 00000000000..8d441f06e7c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cors/resources/status.py
@@ -0,0 +1,37 @@
+def main(request, response):
+ response.headers.set("Access-Control-Allow-Origin", request.headers.get("origin") )
+ response.headers.set("Access-Control-Expose-Headers", "X-Request-Method")
+
+ if request.method == 'OPTIONS':
+ response.headers.set("Access-Control-Allow-Methods", "GET, CHICKEN, HEAD, POST, PUT")
+
+ if 'headers' in request.GET:
+ response.headers.set("Access-Control-Allow-Headers", request.GET.first('headers'))
+
+ response.headers.set("X-Request-Method", request.method)
+
+ response.headers.set("X-A-C-Request-Method", request.headers.get("Access-Control-Request-Method", ""));
+
+
+ #This should reasonably work for most response codes.
+ try:
+ code = int(request.GET.first("code", 200))
+ except ValueError:
+ code = 200
+
+ text = request.GET.first("text", "OMG")
+
+ if request.method == "OPTIONS" and "preflight" in request.GET:
+ try:
+ code = int(request.GET.first('preflight'))
+ except KeyError, ValueError:
+ pass
+
+ status = code, text
+
+ if "type" in request.GET:
+ response.headers.set("Content-Type", request.GET.first('type'))
+
+ body = request.GET.first('content', "")
+
+ return status, [], body
diff --git a/tests/wpt/web-platform-tests/cors/response-headers.htm b/tests/wpt/web-platform-tests/cors/response-headers.htm
new file mode 100644
index 00000000000..b1c5bf2c068
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cors/response-headers.htm
@@ -0,0 +1,103 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>CORS - Response headers</title>
+<meta name=author title="Odin Hørthe Omdal" href="mailto:odiho@opera.com">
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js?pipe=sub></script>
+
+<h1>Response headers</h1>
+<div id=log></div>
+<script>
+
+/*
+ * Response Headers
+ */
+
+function check_response_header(head, value, desc) {
+ test(function() {
+ var client = new XMLHttpRequest()
+ client.open('GET', CROSSDOMAIN + 'resources/cors-headers.asis', false)
+ client.send(null)
+
+ if (typeof value === 'function')
+ value(client, head)
+ else
+ assert_equals(client.getResponseHeader(head), value, head)
+ },
+ desc)
+}
+check_response_header('X-Custom-Header-Comma', '1, 2', 'getResponseHeader: Expose Access-Control-Expose-Headers (x-custom-header-comma)')
+check_response_header('X-Second-Expose', 'flyingpig', 'getResponseHeader: Expose second Access-Control-Expose-Headers (x-second-expose)')
+check_response_header(' x-custom-header', null, 'getResponseHeader: Don\'t trim whitespace')
+check_response_header('x-custom-header-bytes', "\xE2\x80\xA6", 'getResponseHeader: x-custom-header bytes')
+check_response_header('Date',
+ function(client, head) { assert_true(client.getResponseHeader(head).length > 2) },
+ 'getResponseHeader: Exposed server field readable (Date)')
+
+function default_readable(head, value) {
+ check_response_header(head, value, 'getResponseHeader: '+head+': readable by default')
+}
+default_readable("Cache-Control", "no-cache");
+default_readable("Content-Language", "nn");
+default_readable("Expires", "Thu, 01 Dec 1994 16:00:00 GMT");
+default_readable("Last-Modified", "Thu, 01 Dec 1994 10:00:00 GMT");
+default_readable("Pragma", "no-cache");
+
+
+function default_unreadable(head) {
+ check_response_header(head, null, 'getResponseHeader: '+head+': unreadable by default')
+}
+default_unreadable("Server")
+default_unreadable("X-Powered-By")
+
+
+async_test("getResponseHeader: Combined testing of cors response headers")
+.step(function()
+{
+ var client = new XMLHttpRequest();
+ client.open("GET", CROSSDOMAIN + 'resources/cors-headers.asis')
+ window.c=client;
+ client.onreadystatechange = this.step_func(function()
+ {
+ if (client.readyState == 1)
+ {
+ assert_equals(client.getResponseHeader("x-custom-header"), null, 'x-custom-header')
+ }
+ if (client.readyState > 1)
+ {
+ assert_equals(client.getResponseHeader("x-custom-header"), "test", 'x-custom-header')
+ assert_equals(client.getResponseHeader("x-custom-header-empty"), "", 'x-custom-header-empty')
+ assert_equals(client.getResponseHeader("set-cookie"), null)
+ assert_equals(client.getResponseHeader("set-cookie2"), null)
+ assert_equals(client.getResponseHeader("x-non-existent-header"), null)
+ assert_equals(client.getResponseHeader("x-nonexposed"), null)
+ }
+ if (client.readyState == 4)
+ {
+ this.done()
+ }
+ })
+ client.send()
+})
+
+test(function() {
+ var client = new XMLHttpRequest()
+ client.open('GET', CROSSDOMAIN + 'resources/cors-headers.asis', false)
+ client.send(null)
+ assert_equals(client.getResponseHeader("x-custom-header"), "test", 'x-custom-header')
+ assert_equals(client.getResponseHeader("x-nonexposed"), null, 'x-nonexposed')
+}, "getResponse: don't expose x-nonexposed")
+
+test(function() {
+ var client = new XMLHttpRequest()
+ client.open('GET', CROSSDOMAIN + 'resources/cors-headers.asis', false)
+ client.send(null)
+
+ h = client.getAllResponseHeaders().toLowerCase()
+ assert_true( h.indexOf('x-custom-header') >= 0, 'x-custom-header present')
+ assert_true( h.indexOf('x-nonexposed') === -1, 'x-nonexposed not present')
+}, "getAllResponseHeaders: don't expose x-nonexposed")
+
+</script>
diff --git a/tests/wpt/web-platform-tests/cors/simple-requests.htm b/tests/wpt/web-platform-tests/cors/simple-requests.htm
new file mode 100644
index 00000000000..441a8c1ace2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cors/simple-requests.htm
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>CORS - simple requests</title>
+<meta name=author title="Odin Hørthe Omdal" href="mailto:odiho@opera.com">
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js?pipe=sub></script>
+<script src=/common/utils.js></script>
+
+<h1>Simple requests</h1>
+<p>Simple requests shouldn't trigger preflight</p>
+
+<div id=log></div>
+<script>
+
+var test_c = 0;
+
+function check_simple(method, headers)
+{
+ test(function() {
+ var client = new XMLHttpRequest()
+ var uuid_token = token();
+ client.open(method, CROSSDOMAIN + 'resources/preflight.py?token='
+ + uuid_token, false)
+ for (head in headers)
+ client.setRequestHeader(head, headers[head])
+ client.send("data")
+ assert_equals(client.getResponseHeader('content-type'), "text/plain")
+ if (method == 'HEAD')
+ assert_equals(client.response, '', 'response')
+ else
+ assert_equals(client.response, 'NO', 'response')
+
+ client.open('GET', 'resources/preflight.py?check&token='
+ + uuid_token, false)
+ client.send("data")
+ assert_equals(client.response, "0", "Found preflight log")
+ },
+ 'No preflight ' + method + ' and ' + JSON.stringify(headers))
+}
+
+function check_simple_headers(headers) {
+ check_simple('GET', headers)
+ check_simple('HEAD', headers)
+ check_simple('POST', headers)
+}
+
+check_simple_headers({'Accept': 'test'})
+check_simple_headers({'accept-language': 'test'})
+check_simple_headers({'CONTENT-language': 'test'})
+
+check_simple_headers({'Content-Type': 'application/x-www-form-urlencoded'})
+check_simple_headers({'content-type': 'multipart/form-data'})
+check_simple_headers({'content-type': 'text/plain'})
+
+check_simple_headers({
+ 'accept': 'test',
+ 'accept-language': 'test',
+ 'content-language': 'test',
+ 'content-type': 'text/plain; parameter=whatever'
+ })
+
+check_simple('Get', {'content-type': 'text/plain; parameter=extra_bonus'})
+check_simple('post', {'content-type': 'text/plain'})
+
+
+/* Extra async test */
+
+var simple_async = async_test("Check simple headers (async)")
+simple_async.step(function (){
+ var time = new Date().getTime(),
+ client = new XMLHttpRequest()
+ var uuid_token = token();
+ client.open('POST', CROSSDOMAIN + 'resources/preflight.py?token='
+ + uuid_token, true)
+
+ client.setRequestHeader('Accept', 'jewelry')
+ client.setRequestHeader('accept-language', 'nn_NO,nn,en')
+ client.setRequestHeader('content-type', 'text/plain; parameter=extra')
+ client.setRequestHeader('content-Language', 'nn_NO')
+
+ client.onload = simple_async.step_func(function() {
+ assert_equals(client.getResponseHeader('content-type'), "text/plain", 'content-type response header')
+ assert_equals(client.response, 'NO', 'response')
+ simple_async.done()
+ })
+ client.onerror = simple_async.step_func(function () { assert_unreached('onerror') })
+ client.send()
+})
+</script>
diff --git a/tests/wpt/web-platform-tests/cors/status-async.htm b/tests/wpt/web-platform-tests/cors/status-async.htm
new file mode 100644
index 00000000000..3573ee88f98
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cors/status-async.htm
@@ -0,0 +1,114 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>CORS - status</title>
+<meta name=author title="Odin Hørthe Omdal" href="mailto:odiho@opera.com">
+<meta name=timeout content=long>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js?pipe=sub></script>
+
+<h1>Status returned</h1>
+
+<div id=log></div>
+<script>
+
+function statusRequest(method, code, text, content, type) {
+ async_test("Status on " + method + " " + code, { timeout: 15000 })
+ .step(function() {
+ var client = new XMLHttpRequest()
+ client.open(method, CROSSDOMAIN + "resources/status.py?code="
+ + code + "&text=" + text + "&content=" + content + "&type=" + type, true)
+ client.onreadystatechange = this.step_func(function() {
+ if (client.readyState != client.DONE)
+ return
+
+ assert_equals(client.status, code, 'response status')
+ assert_equals(client.statusText, text, 'response status text')
+ assert_equals(client.getResponseHeader("X-Request-Method"), method, 'method')
+ if(method != "HEAD") {
+ if(type == "text/xml") {
+ assert_equals(client.responseXML.documentElement.localName,
+ "x", 'responseXML')
+ }
+ assert_equals(client.response, content, 'response content')
+ }
+ this.done()
+ })
+
+ client.send(null)
+ })
+}
+
+ /* method code text content type */
+ statusRequest("GET", 200, 'OK', 'Not today.', '')
+ statusRequest("GET", 201, 'OK/Created', 'Not today 01.', '')
+ statusRequest("GET", 202, 'OK/Accepted', 'Not today 02.', '')
+ statusRequest("GET", 203, 'OK/Non-Authoritative Information', 'Not today 03.', '')
+ statusRequest("GET", 204, 'OK/No Content', '', '') // specifically no-content
+ statusRequest("GET", 205, 'OK/Reset Content', '', '') // specifically no-content
+ statusRequest("GET", 206, 'OK/Partial Content', 'Not today 06.', '')
+ statusRequest("GET", 209, 'OK', 'Not today 09.', '')
+ statusRequest("GET", 299, 'OK', 'Not today 99.', '')
+ statusRequest("POST", 200, 'OK', '<x>402<\/x>', 'text/xml')
+ statusRequest("HEAD", 200, 'OK', 'Nice!', 'text/doesnotmatter')
+ statusRequest("PUT", 200, 'OK', '400', 'text/plain')
+ statusRequest("CHICKEN", 200, 'OK', 'bah', '')
+
+
+function statusRequestFail(method, code, expect_code, nonsimple) {
+ if (expect_code === undefined)
+ expect_code = code
+
+ async_test("Status on " + method + " " + code + (nonsimple?' (nonsimple)':''), { timeout: 15000 })
+ .step(function() {
+ var client = new XMLHttpRequest()
+
+ client.open(method, CROSSDOMAIN + "resources/status.py?code="
+ + code + '&headers=x-nonsimple&text=OHAI', true)
+
+ if (nonsimple)
+ client.setRequestHeader('x-nonsimple', true)
+
+ client.onreadystatechange = this.step_func(function() {
+ if (client.readyState < client.HEADERS_RECEIVED)
+ return
+ assert_equals(client.response, "", "response data")
+ assert_equals(client.status, expect_code, "response status")
+ /* Response code 200 forces webserver to send OK(?) */
+ if(expect_code == 200)
+ assert_equals(client.statusText, "OK", "response statusText")
+ else
+ assert_equals(client.statusText, (expect_code == 0 ? "" : "OHAI"), "response statusText")
+ if (client.readyState == client.DONE)
+ this.done()
+ })
+
+ client.onerror = this.step_func(function(e) {
+ assert_unreached("Got error event.")
+ })
+
+ client.send()
+ })
+}
+
+ /* expect
+ method code status */
+ statusRequestFail("GET", 400)
+ statusRequestFail("HEAD", 401)
+ statusRequestFail("POST", 404)
+ statusRequestFail("POST", 500)
+
+ /* Preflight response status is not 200, so the algorithm set status to 0. */
+ statusRequestFail("PUT", 699, 0)
+ statusRequestFail("CHICKEN", 501, 0)
+
+ /* "forced"
+ preflight */
+ statusRequestFail("GET", 400, 0, true)
+ statusRequestFail("HEAD", 401, 0, true)
+ statusRequestFail("POST", 404, 0, true)
+ statusRequestFail("PUT", 699, 0, true)
+ statusRequestFail("CHICKEN", 501, 0, true)
+
+</script>
diff --git a/tests/wpt/web-platform-tests/cors/status-preflight.htm b/tests/wpt/web-platform-tests/cors/status-preflight.htm
new file mode 100644
index 00000000000..54b9e8e84d9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cors/status-preflight.htm
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>CORS - status after preflight</title>
+<meta name=author title="Odin Hørthe Omdal" href="mailto:odiho@opera.com">
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js?pipe=sub></script>
+
+<h1>Status after preflight</h1>
+
+<div id=log></div>
+<script>
+var counter = 0
+
+function statusAfterPreflight(method, code) {
+ counter++
+
+ async_test(document.title + " on " + method + " " + code).step(function() {
+ var client = new XMLHttpRequest()
+ client.open(method, CROSSDOMAIN + "resources/status.py?" + counter
+ +"&code=" + code + '&headers=x-nonsimple&preflight=200', true)
+
+ client.setRequestHeader('x-nonsimple', true)
+ client.onreadystatechange = this.step_func(function() {
+ if (client.readyState < client.HEADERS_RECEIVED)
+ return
+ assert_equals(client.response, "", "response data")
+ assert_equals(client.status, code, "response status")
+ if (client.readyState == client.DONE)
+ /* Wait for spurious error events */
+ setTimeout(this.step_func(function() { this.done() }), 10)
+ })
+
+ client.onerror = this.step_func(function() {
+ assert_unreached("Shouldn't throw no error event!")
+ })
+
+ client.send()
+ })
+}
+
+/* method code */
+statusAfterPreflight("GET", 200)
+statusAfterPreflight("GET", 204)
+statusAfterPreflight("GET", 400)
+statusAfterPreflight("GET", 401)
+
+statusAfterPreflight("HEAD", 200)
+statusAfterPreflight("HEAD", 204)
+statusAfterPreflight("HEAD", 400)
+statusAfterPreflight("HEAD", 401)
+statusAfterPreflight("HEAD", 501)
+statusAfterPreflight("HEAD", 699)
+
+statusAfterPreflight("POST", 204)
+statusAfterPreflight("POST", 400)
+statusAfterPreflight("POST", 401)
+statusAfterPreflight("POST", 404)
+
+statusAfterPreflight("PUT", 699)
+statusAfterPreflight("CHICKEN", 501)
+
+</script>
diff --git a/tests/wpt/web-platform-tests/cors/status.htm b/tests/wpt/web-platform-tests/cors/status.htm
new file mode 100644
index 00000000000..4997ddab07e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cors/status.htm
@@ -0,0 +1,80 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>CORS status</title>
+<meta name=help href=http://dvcs.w3.org/hg/cors/raw-file/tip/Overview.html#cross-origin-request-with-preflight-0>
+<meta name=author title="Odin Hørthe Omdal" href="mailto:odiho@opera.com">
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js?pipe=sub"></script>
+
+<h1>The returned status code in different scenarios</h1>
+
+<script>
+
+ var counter = 0
+
+ function testit(allow, preflight, response, status) {
+ async_test(
+ (++counter) + '. ' +
+ (allow ? 'CORS allowed' : 'CORS disallowed') +
+ (preflight ? ', preflight status '+preflight : '') +
+ (response ? ', response status '+response : '') +
+ '.'
+ ).step(function() {
+ var client = new XMLHttpRequest()
+ client.open('GET', CROSSDOMAIN + 'resources/cors-makeheader.py?' + counter +
+ (allow ? '&headers=x-custom': '&origin=none') +
+ (response ? '&code='+response : '') +
+ (preflight ? '&preflight='+preflight : '')
+ )
+
+ if (preflight)
+ client.setRequestHeader('X-Custom', 'preflight')
+
+ client.onload = this.step_func(function() {
+ if (!status)
+ assert_unreached("load event")
+
+ /* Allow spurious error events to fire */
+ setTimeout(this.step_func(function() {
+ assert_equals(client.status, status, "status")
+ this.done()
+ }), 10)
+ })
+
+ client.onerror = this.step_func(function() {
+ if (status)
+ assert_unreached("error event")
+
+ assert_equals(client.readyState, client.DONE, 'readyState')
+ assert_equals(client.status, 0, 'status')
+ this.done()
+ })
+
+ client.send()
+
+ })
+ }
+
+ /* allow pref resp status */
+ testit(false, null, 400, 0)
+ testit(false, 200, null, 0)
+ testit(true, null, 400, 400)
+ testit(true, 200, 400, 400)
+ testit(true, 400, null, 0)
+
+</script>
+
+<pre>
+ allowed preflight response | status |
+ ------- --------- -------- | ------ |
+ 1 no x 400 | 0 |
+ 2 no 200 x | 0 |
+ 3 yes x 400 | 400 |
+ 4 yes 200 400 | 400 |
+ 5 yes 400 x | 0 |
+</pre>
+
+<div id=log></div>
+
diff --git a/tests/wpt/web-platform-tests/cors/support.js b/tests/wpt/web-platform-tests/cors/support.js
new file mode 100644
index 00000000000..551eb70d0b5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/cors/support.js
@@ -0,0 +1,30 @@
+// For ignoring exception names (just for testing)
+/*
+_real_assert_throws = assert_throws;
+function assert_throws(d, func, desc) {
+ try {
+ func();
+ } catch(e) {
+ return true;
+ }
+ assert_unreached("Didn't throw!");
+}
+*/
+
+function dirname(path) {
+ return path.replace(/\/[^\/]*$/, '/')
+}
+
+/* This subdomain should point to this same location */
+var SUBDOMAIN = 'www1'
+var SUBDOMAIN2 = 'www2'
+var PORT = {{ports[http][1]}}
+//XXX HTTPS
+var PORTS = {{ports[https][0]}}
+
+/* Changes http://example.com/abc/def/cool.htm to http://www1.example.com/abc/def/ */
+var CROSSDOMAIN = dirname(location.href)
+ .replace('://', '://' + SUBDOMAIN + '.')
+var REMOTE_HOST = SUBDOMAIN + '.' + location.host
+var REMOTE_PROTOCOL = location.protocol
+var REMOTE_ORIGIN = REMOTE_PROTOCOL + '//' + REMOTE_HOST
diff --git a/tests/wpt/web-platform-tests/csp/assert_undefined.py b/tests/wpt/web-platform-tests/csp/assert_undefined.py
new file mode 100644
index 00000000000..1f45ee8e60d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/csp/assert_undefined.py
@@ -0,0 +1,8 @@
+def main(request, response):
+ code = """
+test(function() {
+ assert_equals(self.%s, undefined);
+});
+""" % request.GET["varName"]
+
+ return ([("Content-Type", "text/javascript")], code)
diff --git a/tests/wpt/web-platform-tests/csp/csp-inline-script.html b/tests/wpt/web-platform-tests/csp/csp-inline-script.html
new file mode 100644
index 00000000000..4caa25a4b8a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/csp/csp-inline-script.html
@@ -0,0 +1,11 @@
+<!doctype html>
+<meta charset=UTF-8>
+<link rel="author" title="tanvi@mozilla.com">
+<title>No inline script</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+unsafeScript = false;
+</script>
+<script src="assert_undefined.py?varName=unsafeScript"></script>
diff --git a/tests/wpt/web-platform-tests/csp/csp-inline-script.html.headers b/tests/wpt/web-platform-tests/csp/csp-inline-script.html.headers
new file mode 100644
index 00000000000..4c6fa3c26a7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/csp/csp-inline-script.html.headers
@@ -0,0 +1 @@
+Content-Security-Policy: default-src 'self'
diff --git a/tests/wpt/web-platform-tests/custom-elements/concepts/custom-elements-type-allowed-chars-first-char.html b/tests/wpt/web-platform-tests/custom-elements/concepts/custom-elements-type-allowed-chars-first-char.html
new file mode 100644
index 00000000000..7dc855a9358
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/concepts/custom-elements-type-allowed-chars-first-char.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>First char allowed for custom element type </title>
+<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="assert" content="The custom element type identifies a custom element interface and is a sequence of characters that must match the NCName production">
+<link rel="help" href="https://dvcs.w3.org/hg/webcomponents/raw-file/default/spec/custom/index.html#concepts">
+<link rel="help" href="http://www.w3.org/TR/1999/REC-xml-names-19990114/#NT-NCName">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+function composeName(charCode) {
+ return String.fromCharCode(charCode) + '-x' + charCode.toString(16);
+}
+
+// NCName definition from http://www.w3.org/TR/1999/REC-xml-names-19990114/#NT-NCName
+// NCName ::= (Letter | '_') (NCNameChar)*
+// NCNameChar ::= Letter | Digit | '.' | '-' | '_' | CombiningChar | Extender
+// Letter ::= BaseChar | Ideographic
+
+test(function() {
+ testCharCode(getCharCode('_'), composeName, checkValidName);
+}, 'Registering valid custom element name starting with \'_\' char');
+
+test(function() {
+ baseCharsSingle.testEach(composeName, checkValidName);
+ baseCharsRanges.testEach(composeName, checkValidName);
+}, 'Registering valid custom element name starting with base char');
+
+test(function() {
+ ideographicCharsSingle.testEach(composeName, checkValidName);
+ ideographicCharsRanges.testEach(composeName, checkValidName);
+}, 'Registering valid custom element name starting with ideographic char');
+
+test(function() {
+ (new CharsArray(['.', '-', ':', '+', '='])).testEach(composeName, checkInvalidName);
+}, 'Registering custom element starting with invalid character (general) should fail');
+
+test(function() {
+ combiningChars.testEach(composeName, checkInvalidName);
+}, 'Registering custom element starting with invalid character (combining char) should fail');
+
+test(function() {
+ extenderChars.testEach(composeName, checkInvalidName);
+}, 'Registering custom element starting with invalid character (extender char) should fail');
+
+test(function() {
+ digitCharsRanges.testEach(composeName, checkInvalidName);
+}, 'Registering custom element starting with invalid character (digit char) should fail');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/concepts/custom-elements-type-allowed-chars.html b/tests/wpt/web-platform-tests/custom-elements/concepts/custom-elements-type-allowed-chars.html
new file mode 100644
index 00000000000..f10d0209646
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/concepts/custom-elements-type-allowed-chars.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Chars allowed for custom element type </title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<meta name="assert" content="The custom element type identifies a custom element interface and is a sequence of characters that must match the NCName production">
+<link rel="help" href="https://dvcs.w3.org/hg/webcomponents/raw-file/default/spec/custom/index.html#concepts">
+<link rel="help" href="http://www.w3.org/TR/1999/REC-xml-names-19990114/#NT-NCName">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+function composeName(charCode) {
+ return 'x-' + String.fromCharCode(charCode) + '-x' + charCode.toString(16);
+}
+
+// NCName definition from http://www.w3.org/TR/1999/REC-xml-names-19990114/#NT-NCName
+// NCName ::= (Letter | '_') (NCNameChar)*
+// NCNameChar ::= Letter | Digit | '.' | '-' | '_' | CombiningChar | Extender
+// Letter ::= BaseChar | Ideographic
+
+test(function() {
+ baseCharsSingle.testEach(composeName, checkValidName);
+ baseCharsRanges.testEach(composeName, checkValidName);
+}, 'Registering valid custom element types with base char');
+
+test(function() {
+ ideographicCharsSingle.testEach(composeName, checkValidName);
+ ideographicCharsRanges.testEach(composeName, checkValidName);
+}, 'Registering valid custom element types with ideographic char');
+
+test(function() {
+ digitCharsRanges.testEach(composeName, checkValidName);
+}, 'Registering valid custom element types with digit chars');
+
+test(function() {
+ (new CharsArray(['.', '-', '_'])).testEach(composeName, checkValidName)
+}, 'Registering valid custom element types with characters \'.\', \'-\', \'_\'');
+
+test(function() {
+ combiningChars.testEach(composeName, checkValidName);
+}, 'Registering valid custom element types with combining char');
+
+test(function() {
+ extenderChars.testEach(composeName, checkValidName);
+}, 'Registering valid custom element types with extender char');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/concepts/custom-elements-type-naming.html b/tests/wpt/web-platform-tests/custom-elements/concepts/custom-elements-type-naming.html
new file mode 100644
index 00000000000..58989a2f7aa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/concepts/custom-elements-type-naming.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>The custom element type is a sequence of characters that must match the NCName production and contain a minus character</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="assert" content="The custom element type is a sequence of characters that must match the NCName production and contain a U+002D HYPHEN-MINUS character">
+<link rel="help" href="https://dvcs.w3.org/hg/webcomponents/raw-file/default/spec/custom/index.html#concepts">
+<link rel="help" href="http://www.w3.org/TR/1999/REC-xml-names-19990114/#NT-NCName">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ var doc = newHTMLDocument();
+ var validNames = ['x-frame', 'xx-frame', 'x--frame', '_-frame', 'x-', 'x--',
+ 'x-1', 'x-_', '_-_', '__-', '_-1', '_-..'];
+ HTML5_ELEMENTS.forEach(function(value) {
+ validNames.push('x-' + value);
+ validNames.push('Y-' + value.toUpperCase());
+ });
+ validNames.forEach(function(value) {
+ try {
+ doc.registerElement(value);
+ } catch (e) {
+ assert_unreached('Exception should not be thrown in case of attempt ' +
+ 'to register a custom element with a name \'' + value + '\'');
+ }
+ });
+}, 'Registering valid custom element types');
+
+test(function() {
+ var doc = newHTMLDocument();
+ var invalidNames = ['xframe', 'x_frame', 'x.frame', 'x1frame', '-xframe', '1-frame',
+ '1x-frame', '.-frame', '_frame', 'x-f!rame', 'x-:frame'];
+ invalidNames.forEach(function(value) {
+ assert_throws('SyntaxError', function() {
+ doc.registerElement(value);
+ }, 'Exception should be thrown in case of attempt to register element ' +
+ 'with the name \'' + value + '\'');
+ });
+}, 'Registering invalid custom element types should fail');
+
+test(function() {
+ var doc = newHTMLDocument();
+ var forbiddenNames = ['annotation-xml',
+ 'color-profile',
+ 'font-face',
+ 'font-face-src',
+ 'font-face-uri',
+ 'font-face-format',
+ 'font-face-name',
+ 'missing-glyph'];
+ forbiddenNames.forEach(function(value) {
+ assert_throws('SyntaxError', function() {
+ doc.registerElement(value);
+ }, 'Exception should be thrown in case of attempt to register element ' +
+ 'with the name \'' + value + '\'');
+ });
+}, 'Registering forbidden custom element types should fail');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/creating-and-passing-registries/new-registry-test.html b/tests/wpt/web-platform-tests/custom-elements/creating-and-passing-registries/new-registry-test.html
new file mode 100644
index 00000000000..d0dc751361c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/creating-and-passing-registries/new-registry-test.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>When an HTML Document is loaded in a browsing context, a new registry must be created and associated with this document</title>
+<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="assert" content="When an HTML Document is loaded in a browsing context, a new registry must be created and associated with this document.">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#creating-and-passing-registries">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+testInIFrame('../resources/blank.html', function(doc) {
+ try {
+ doc.registerElement('x-element');
+ } catch (e) {
+ assert_unreached('Unexpected exception, while registering a valid custom element');
+ }
+}, 'Document, loaded into browsing context, must have a new empty registry');
+
+
+testInIFrame('../resources/blank.html', function(loadedDocument) {
+ var createdDocument = document.implementation.createHTMLDocument('Test Document');
+ // Let's check that loadedDocument and createdDocument use different registeries.
+ createdDocument.registerElement('x-element');
+ try {
+ loadedDocument.registerElement('x-element');
+ } catch (e) {
+ assert_unreached('Unexpected exception while registering a custom element ' +
+ 'in a document, which has it\'s own registry');
+ }
+}, 'Document, loaded into browsing context, must have a new empty registry, ' +
+ 'which is different from other documents\' registries');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/creating-and-passing-registries/no-registry-test.html b/tests/wpt/web-platform-tests/custom-elements/creating-and-passing-registries/no-registry-test.html
new file mode 100644
index 00000000000..9cfa68b9213
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/creating-and-passing-registries/no-registry-test.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>New document without browsing context must not have a registry</title>
+<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="assert" content="In all other cases, new documents must not have a registry.">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#creating-and-passing-registries">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ var doc = document.implementation.createDocument(null, 'test', null);
+ assert_throws(
+ 'NotSupportedError',
+ function() { doc.registerElement('x-element'); },
+ 'Registering valid custom element in a document ' +
+ 'without registry should fail');
+}, 'Document of type other than HTML, not loaded into browsing context, must not have a registry');
+
+async_test(function(t) {
+ var request = new XMLHttpRequest();
+ request.onreadystatechange = t.step_func(function() {
+ if (request.readyState == 4){
+ assert_equals(200, request.status, 'Test document is not loaded correctly');
+ var doc = request.response;
+ assert_true(doc instanceof HTMLDocument,
+ 'XMLHttpRequest\'s asynchronous response should be HTML document');
+ assert_throws(
+ 'NotSupportedError',
+ function() { doc.registerElement('x-element'); },
+ 'Registering valid custom element in ' +
+ 'an XMLHttpRequest\'s response document should fail');
+ t.done();
+ }
+ });
+
+ request.open('GET', '../resources/blank.html', true);
+ request.responseType = 'document';
+ request.send();
+}, 'XMLHttpRequest\'s asynchronous response HTML document must not have a registry');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/creating-and-passing-registries/share-registry-create-document.html b/tests/wpt/web-platform-tests/custom-elements/creating-and-passing-registries/share-registry-create-document.html
new file mode 100644
index 00000000000..715aba8ddf6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/creating-and-passing-registries/share-registry-create-document.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Document, created with createHTMLDocument or createDocument with HTML namespace, should share registry with the associated document</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="assert" content="When DOMImplementation's createDocument method is invoked with namespace set to HTML Namespace or when the createHTMLDocument method is invoked, use the registry of the associated document to the new instance.">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#creating-and-passing-registries">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ var doc = newHTMLDocument();
+ var name = 'x-frame';
+
+ var GeneratedConstructor = doc.registerElement(name);
+ var doc2 = doc.implementation.createHTMLDocument('Document 2');
+ assert_throws(
+ 'NotSupportedError',
+ function() { doc2.registerElement(name); },
+ 'Registering a custom element type name that is already registered in a shared ' +
+ 'registry should throw an exception');
+
+ var xframe = doc2.createElement(name);
+ assert_true(xframe instanceof GeneratedConstructor,
+ 'Created element should be x-frame instance');
+}, 'Document created by createHTMLDocument should share an existing registry');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var name = 'x-frame-1';
+
+ var GeneratedConstructor = doc.registerElement(name);
+ var doc2 = doc.implementation.createDocument(HTML_NAMESPACE, 'html', null);
+ assert_throws(
+ 'NotSupportedError',
+ function() { doc2.registerElement(name); },
+ 'Exception should be thrown for custom element, ' +
+ 'which is already registered in shared registry');
+
+ var xframe = doc2.createElement(name);
+ assert_true(xframe instanceof GeneratedConstructor,
+ 'Created element should be x-frame instance');
+}, 'Document created by createDocument with HTML namespace should share an existing registry');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/creating-and-passing-registries/share-registry-import-document.html b/tests/wpt/web-platform-tests/custom-elements/creating-and-passing-registries/share-registry-import-document.html
new file mode 100644
index 00000000000..24c8468e15e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/creating-and-passing-registries/share-registry-import-document.html
@@ -0,0 +1,96 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>When creating an import, use the registry of the master document</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="assert" content="When creating an import, use the registry of the master document.">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#creating-and-passing-registries">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var test1 = async_test('Registry of the imported document should be shared with master document. ' +
+ 'Import is asynchronous');
+test1.step(function() {
+ var iframe = newIFrame('../resources/import-master-async.html');
+ document.body.appendChild(iframe);
+ iframe.onload = test1.step_func(function() {
+ var doc = iframe.contentDocument;
+ var link = doc.querySelector('link[rel=import]');
+ link.onload = test1.step_func(function() {
+ try {
+ var doc2 = link.import;
+ var name = 'x-frame';
+ doc.registerElement(name);
+ assert_throws(
+ 'NotSupportedError',
+ function() { doc2.registerElement(name); },
+ 'Registering a custom element type name that is already registered in a shared ' +
+ 'registry should throw an exception');
+ test1.done();
+ } finally {
+ iframe.remove();
+ }
+ });
+ });
+});
+
+
+var test2 = async_test('Registry of the master document should be shared with imported document. ' +
+ 'Import is asynchronous');
+test2.step(function() {
+ var iframe = newIFrame('../resources/import-master-async.html');
+ document.body.appendChild(iframe);
+ iframe.onload = test2.step_func(function() {
+ var doc = iframe.contentDocument;
+ var link = doc.querySelector('link[rel=import]');
+ link.onload = test2.step_func(function() {
+ try {
+ var doc2 = link.import;
+ var name = 'x-frame';
+ doc2.registerElement(name);
+ assert_throws(
+ 'NotSupportedError',
+ function() { doc.registerElement(name); },
+ 'Registering a custom element type name that is already registered in a shared ' +
+ 'registry should throw an exception');
+ test2.done();
+ } finally {
+ iframe.remove();
+ }
+ });
+ });
+});
+
+
+testInIFrame('../resources/import-master.html', function(doc) {
+ var link = doc.querySelector('link[rel=import]');
+ var doc2 = link.import;
+ var name = 'x-frame';
+ doc.registerElement(name);
+ assert_throws(
+ 'NotSupportedError',
+ function() { doc2.registerElement(name); },
+ 'Registering a custom element type name that is already registered in a shared ' +
+ 'registry should throw an exception');
+}, 'Registry of the imported document should be shared with master document. Import is syncronous');
+
+
+testInIFrame('../resources/import-master.html', function(doc) {
+ var link = doc.querySelector('link[rel=import]');
+ var doc2 = link.import;
+ var name = 'x-frame';
+ doc2.registerElement(name);
+ assert_throws(
+ 'NotSupportedError',
+ function() { doc.registerElement(name); },
+ 'Registering a custom element type name that is already registered in a shared ' +
+ 'registry should throw an exception');
+}, 'Registry of the master document should be shared with imported document. Import is syncronous');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/custom-element-lifecycle/enqueuing-and-invoking-callbacks/invoke-callbacks.html b/tests/wpt/web-platform-tests/custom-elements/custom-element-lifecycle/enqueuing-and-invoking-callbacks/invoke-callbacks.html
new file mode 100644
index 00000000000..7b72e678520
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/custom-element-lifecycle/enqueuing-and-invoking-callbacks/invoke-callbacks.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Invoke CALLBACK with ELEMENT as callback this value</title>
+<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="assert" content="Invoke CALLBACK with ELEMENT as callback this value">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#enqueuing-and-invoking-callbacks">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = newHTMLElementPrototype();
+ var GeneratedConstructor = doc.registerElement('x-a', {prototype: proto});
+ var customElement = new GeneratedConstructor();
+
+ doc.body.innerHTML = '<x-a id="x-a"></x-a>';
+ assert_equals(doc.querySelector('#x-a'), proto.createdCallbackThis,
+ '\'this\' value of the created callback should be the custom element');
+}, 'Test \'this\' value inside created callback.');
+
+
+testInIFrame('../../resources/x-element.html', function(doc) {
+ var proto = newHTMLElementPrototype();
+ doc.registerElement('x-element', {prototype: proto});
+
+ assert_equals(doc.querySelector('#x-element'), proto.attachedCallbackThis,
+ '\'this\' value of the attached callback should be the custom element');
+}, 'Test \'this\' value inside attached callback.');
+
+
+testInIFrame('../../resources/x-element.html', function(doc) {
+ var proto = newHTMLElementPrototype();
+ doc.registerElement('x-element', {prototype: proto});
+
+ var customElement = doc.querySelector('#x-element');
+ doc.body.removeChild(customElement);
+ assert_equals(customElement, proto.detachedCallbackThis,
+ '\'this\' value of the detached callback should be the custom element');
+}, 'Test \'this\' value inside detached callback.');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = newHTMLElementPrototype();
+ var GeneratedConstructor = doc.registerElement('x-b', {prototype: proto});
+ var customElement = new GeneratedConstructor();
+
+ customElement.setAttribute('class', 'someClass');
+ assert_equals(customElement, proto.attributeChangedCallbackThis,
+ '\'this\' value of the attributeChanged callback should be the custom element');
+}, 'Test \'this\' value inside attributeChanged callback.');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/custom-element-lifecycle/types-of-callbacks/attached-callback-move-element-test.html b/tests/wpt/web-platform-tests/custom-elements/custom-element-lifecycle/types-of-callbacks/attached-callback-move-element-test.html
new file mode 100644
index 00000000000..85b90d9c23a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/custom-element-lifecycle/types-of-callbacks/attached-callback-move-element-test.html
@@ -0,0 +1,160 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Attached callback of a custom element should be called if element is moved</title>
+<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<meta name="assert" content="attached callback ... must be enqueued whenever custom element is inserted into a document and this document has a browsing context.">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#types-of-callbacks">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = newHTMLElementPrototype();
+ doc.registerElement('x-a', {prototype: proto});
+ var customElement = doc.createElement('x-a');
+
+ doc.body.appendChild(customElement);
+ assert_equals(proto.attachedCallbackCalledCounter, 0, 'Callback attached ' +
+ 'should not be called in documents that do not have a browsing context');
+
+ var divElement = doc.createElement('div');
+ doc.body.appendChild(divElement);
+ divElement.appendChild(customElement);
+ assert_equals(proto.attachedCallbackCalledCounter, 0, 'Callback attached ' +
+ 'should not be called in documents that do not have a browsing context');
+}, 'Test attached callback if moving custom element inside document ' +
+ 'without browsing context');
+
+
+testInIFrame('../../resources/blank.html', function(docWithBrowsingContext) {
+ var docNoBrowsingContext = newHTMLDocument();
+ var proto1 = newHTMLElementPrototype();
+ docNoBrowsingContext.registerElement('x-b', {prototype: proto1});
+
+ var customElement = docNoBrowsingContext.createElement('x-b');
+ docNoBrowsingContext.body.appendChild(customElement);
+ assert_equals(proto1.attachedCallbackCalledCounter, 0,
+ 'Callback attached should not be called ' +
+ 'in documents that do not have a browsing context');
+
+ var proto2 = newHTMLElementPrototype();
+ docWithBrowsingContext.registerElement('x-b', {prototype: proto2});
+ docWithBrowsingContext.body.appendChild(customElement);
+ assert_equals(proto1.attachedCallbackCalledCounter, 1,
+ 'Callback attached should be called in documents with browsing context');
+ assert_equals(proto2.attachedCallbackCalledCounter, 0,
+ 'Callback attached, defined in receiving document, should not be called');
+}, 'Test attached callback if moving custom element from ' +
+ 'document without browsing context to document with browsing context');
+
+
+testInIFrame('../../resources/blank.html', function(docWithBrowsingContext) {
+ var proto1 = newHTMLElementPrototype();
+ docWithBrowsingContext.registerElement('x-c', {prototype: proto1});
+
+ var customElement = docWithBrowsingContext.createElement('x-c');
+ docWithBrowsingContext.body.appendChild(customElement);
+ assert_equals(proto1.attachedCallbackCalledCounter, 1,
+ 'Callback attached should be called in documents with browsing context');
+
+ var docNoBrowsingContext = newHTMLDocument();
+ var proto2 = newHTMLElementPrototype();
+ docNoBrowsingContext.registerElement('x-c', {prototype: proto2});
+ docNoBrowsingContext.body.appendChild(customElement);
+ assert_equals(proto1.attachedCallbackCalledCounter, 1, 'Callback attached should not be called ' +
+ 'in documents that do not have a browsing context');
+ assert_equals(proto2.attachedCallbackCalledCounter, 0,
+ 'Callback attached, defined in receiving document, should not be called');
+}, 'Test attached callback if moving custom element from ' +
+ 'document with browsing context to document without browsing context');
+
+
+testInIFrame('../../resources/blank.html', function(doc) {
+ var proto = newHTMLElementPrototype();
+ doc.registerElement('x-d', {prototype: proto});
+
+ var customElement = doc.createElement('x-d');
+ doc.body.appendChild(customElement);
+ assert_equals(proto.attachedCallbackCalledCounter, 1,
+ 'Callback attached should be called in documents with browsing context');
+
+ var divElement = doc.createElement('div');
+ doc.body.appendChild(divElement);
+ divElement.appendChild(customElement);
+ assert_equals(proto.attachedCallbackCalledCounter, 2,
+ 'Callback attached should be called in documents with browsing context');
+}, 'Test attached callback if moving custom element inside document ' +
+ 'with browsing context');
+
+
+testInIFrame('../../resources/blank.html', function(doc) {
+ var proto = newHTMLElementPrototype();
+ doc.registerElement('x-e', {prototype: proto});
+
+ var customElement = doc.createElement('x-e');
+ doc.body.appendChild(customElement);
+ assert_equals(proto.attachedCallbackCalledCounter, 1,
+ 'Callback attached should be called in documents with browsing context');
+
+ var divElement = doc.createElement('div');
+ divElement.appendChild(customElement);
+ assert_equals(proto.attachedCallbackCalledCounter, 1,
+ 'Callback attached should not be called if element is not appended to the document');
+
+ doc.body.appendChild(divElement);
+ assert_equals(proto.attachedCallbackCalledCounter, 2,
+ 'Callback attached should be called in documents with browsing context');
+}, 'Test attached callback if indirectly moving custom element inside document ' +
+ 'with browsing context');
+
+
+var moveTest = async_test('Test attached callback if moving custom element from ' +
+ 'document with browsing context to document with browsing context');
+
+moveTest.step(function() {
+ var iframe1 = newIFrame('../../resources/blank.html');
+ iframe1.onload = moveTest.step_func(function() {
+ var doc1 = iframe1.contentDocument;
+
+ // register custom element type
+ var proto1 = newHTMLElementPrototype();
+ doc1.registerElement('x-f', {prototype: proto1});
+
+ // create custom element
+ var customElement = doc1.createElement('x-f');
+ doc1.body.appendChild(customElement);
+ assert_equals(proto1.attachedCallbackCalledCounter, 1,
+ 'Callback attached should be called in documents with browsing context');
+
+ // create second iframe
+ var iframe2 = newIFrame('../../resources/x-element.html');
+ iframe2.onload = moveTest.step_func(function() {
+ var doc2 = iframe2.contentDocument;
+
+ // register custom element type
+ var proto2 = newHTMLElementPrototype();
+ doc2.registerElement('x-f', {prototype: proto2});
+
+ // move element
+ doc2.body.appendChild(customElement);
+ assert_equals(proto1.attachedCallbackCalledCounter, 2,
+ 'Callback attached should be called in documents with browsing context');
+ assert_equals(proto2.attachedCallbackCalledCounter, 0,
+ 'Callback attached, defined in receiving document, should not be called');
+
+ // test clean up
+ iframe1.remove();
+ iframe2.remove();
+ moveTest.done();
+ });
+ });
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/custom-element-lifecycle/types-of-callbacks/attached-callback-test.html b/tests/wpt/web-platform-tests/custom-elements/custom-element-lifecycle/types-of-callbacks/attached-callback-test.html
new file mode 100644
index 00000000000..d96805e077e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/custom-element-lifecycle/types-of-callbacks/attached-callback-test.html
@@ -0,0 +1,117 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Attached callback of a custom element should be called </title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="assert" content="attached callback ... must be enqueued whenever custom element is inserted into a document and this document has a browsing context.">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#types-of-callbacks">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = newHTMLElementPrototype();
+ var GeneratedConstructor = doc.registerElement('x-a', {prototype: proto});
+ var customElement = new GeneratedConstructor();
+ assert_equals(proto.attachedCallbackCalledCounter, 0, 'Callback attached ' +
+ 'should not be called in documents that do not have a browsing context');
+}, 'Test attached callback if custom element is instantiated via constructor. ' +
+ 'Document has no browsing context');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = newHTMLElementPrototype();
+ doc.registerElement('x-b', {prototype: proto});
+ doc.body.innerHTML = '<x-b></x-b>';
+ assert_equals(proto.attachedCallbackCalledCounter, 0, 'Callback attached ' +
+ 'should not be called in documents that do not have a browsing context');
+}, 'Test attached callback if custom element is created via innerHTML property. ' +
+ 'Document has no browsing context');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ doc.body.innerHTML = '<x-c></x-c>';
+ var proto = newHTMLElementPrototype();
+ doc.registerElement('x-c', {prototype: proto});
+ assert_equals(proto.attachedCallbackCalledCounter, 0, 'Callback attached ' +
+ 'should not be called in documents that do not have a browsing context');
+}, 'Test attached callback if custom element is created via innerHTML property before ' +
+ 'registration. Document has no browsing context');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ doc.body.innerHTML = '<x-d id="x-d"></x-d>';
+ var customElement = doc.querySelector('#x-d');
+
+ var proto = newHTMLElementPrototype();
+ var GeneratedConstructor = doc.registerElement('x-d', {prototype: proto});
+
+ customElement.constructor.prototype = proto;
+ assert_equals(proto.attachedCallbackCalledCounter, 0, 'Callback attached should ' +
+ 'not be called for unregistered custom element in document without browsing context');
+}, 'Test attached callback if custom element is unregistered');
+
+
+testInIFrame('../../resources/x-element.html', function(doc) {
+ var proto = newHTMLElementPrototype();
+ doc.registerElement('x-element', {prototype: proto});
+ assert_equals(proto.attachedCallbackCalledCounter, 1, 'Callback attached should be ' +
+ 'called in documents with browsing context');
+}, 'Test attached callback. Document has browsing context');
+
+
+testInIFrame('../../resources/blank.html', function(doc) {
+ var proto = newHTMLElementPrototype();
+ doc.registerElement('x-element', {prototype: proto});
+
+ var x = doc.createElement('x-element');
+ assert_equals(proto.attachedCallbackCalledCounter, 0, 'Callback attached should not ' +
+ 'be called before element is added to document with browsing context');
+
+ doc.body.appendChild(x);
+ assert_equals(proto.attachedCallbackCalledCounter, 1, 'Callback attached should be called ' +
+ 'in documents with browsing context');
+}, 'Test attached callback. Registered element is created via document.createElement(). ' +
+ 'Document has browsing context');
+
+
+testInIFrame('../../resources/blank.html', function(doc) {
+ var x = doc.createElement('x-element');
+ doc.body.appendChild(x);
+ var proto = newHTMLElementPrototype();
+ doc.registerElement('x-element', {prototype: proto});
+ assert_equals(proto.attachedCallbackCalledCounter, 1, 'Callback attached should ' +
+ 'be called in documents with browsing context');
+}, 'Test attached callback. Unregistered element is created via document.createElement(). ' +
+ 'Document has browsing context');
+
+
+testInIFrame('../../resources/blank.html', function(doc) {
+ var proto = newHTMLElementPrototype();
+ doc.registerElement('x-element', {prototype: proto});
+ doc.body.innerHTML = '<x-element></x-element>';
+ assert_equals(proto.attachedCallbackCalledCounter, 1, 'Callback attached should ' +
+ 'be called in documents with browsing context');
+}, 'Test attached callback. Registered element is created via innerHTML property. ' +
+ 'Document has browsing context');
+
+
+testInIFrame('../../resources/blank.html', function(doc) {
+ doc.body.innerHTML = '<x-element></x-element>';
+ var proto = newHTMLElementPrototype();
+ doc.registerElement('x-element', {prototype: proto});
+ assert_equals(proto.attachedCallbackCalledCounter, 1, 'Callback attached should ' +
+ 'be called in documents with browsing context');
+}, 'Test attached callback. Unresolved element is created via innerHTML property. ' +
+ 'Document has browsing context');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/custom-element-lifecycle/types-of-callbacks/attribute-changed-callback-change-attribute-test.html b/tests/wpt/web-platform-tests/custom-elements/custom-element-lifecycle/types-of-callbacks/attribute-changed-callback-change-attribute-test.html
new file mode 100644
index 00000000000..2b620705eaa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/custom-element-lifecycle/types-of-callbacks/attribute-changed-callback-change-attribute-test.html
@@ -0,0 +1,230 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Test attributeChanged callback is called if custom element attribute value is changed</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<meta name="assert" content="attributeChanged callback must be enqueued whenever custom element's attribute is added, changed or removed">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#types-of-callbacks">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = newHTMLElementPrototype();
+ var GeneratedConstructor = doc.registerElement('x-a', {prototype: proto});
+ var customElement = new GeneratedConstructor();
+
+ customElement.setAttribute('class', 'someClass');
+ proto.attributeChangedCallbackCalledCounter = 0;
+ customElement.setAttribute('class', 'someClass2');
+ assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
+ 'Callback attributeChanged should be called');
+}, 'Test attributeChanged callback is called if attribute value is changed by method ' +
+ 'setAttribute(). The custom element is created via constructor');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = newHTMLElementPrototype();
+ doc.registerElement('x-b', {prototype: proto});
+
+ doc.body.innerHTML = '<x-b id="x-b" class="oldValue"></x-b>';
+ var customElement = doc.querySelector('#x-b');
+ customElement.setAttribute('class', 'newValue');
+ assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
+ 'Callback attributeChanged should be called');
+ assert_array_equals(proto.attributeChangedCallbackArgs,
+ ['class', 'oldValue', 'newValue'],
+ 'Unexpected callback attributeChanged arguments');
+}, 'Test attributeChanged callback arguments if attribute value is changed by method ' +
+ 'setAttribute(). The custom element is created via innerHTML property');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = newHTMLElementPrototype();
+ var GeneratedConstructor = doc.registerElement('x-c', {prototype: proto});
+ var customElement = new GeneratedConstructor();
+
+ customElement.setAttribute('class', 'someClass');
+ proto.attributeChangedCallbackCalledCounter = 0;
+ customElement.classList.add('someClass3');
+ assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
+ 'Callback attributeChanged should be called');
+}, 'Test attributeChanged callback is called if attribute value is changed by method ' +
+ 'classList.add(). The custom element is created via constructor');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = newHTMLElementPrototype();
+ doc.registerElement('x-d', {prototype: proto});
+
+ doc.body.innerHTML = '<x-d id="x-d" class="oldValue"></x-d>';
+ var customElement = doc.querySelector('#x-d');
+ customElement.classList.add('newestValue');
+ assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
+ 'Callback attributeChanged should be called');
+ assert_array_equals(proto.attributeChangedCallbackArgs,
+ ['class', 'oldValue', 'oldValue newestValue'],
+ 'Unexpected callback attributeChanged arguments');
+}, 'Test attributeChanged callback arguments if attribute value is changed by method ' +
+ 'classList.add(). The custom element is created via innerHTML property');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = newHTMLElementPrototype();
+ var GeneratedConstructor = doc.registerElement('x-e', {prototype: proto});
+ var customElement = new GeneratedConstructor();
+
+ customElement.setAttribute('class', 'someClass');
+ proto.attributeChangedCallbackCalledCounter = 0;
+ customElement.id = 'someId';
+ assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
+ 'Callback attributeChanged should be called');
+}, 'Test attributeChanged callback is called if attribute value is changed as property. ' +
+ 'The custom element is created via constructor');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = newHTMLElementPrototype();
+ doc.registerElement('x-f', {prototype: proto});
+
+ doc.body.innerHTML = '<x-f id="x-f" class="oldValue"></x-f>';
+ var customElement = doc.querySelector('#x-f');
+ customElement.className = 'lastValue';
+ assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
+ 'Callback attributeChanged should be called');
+ assert_array_equals(proto.attributeChangedCallbackArgs,
+ ['class', 'oldValue', 'lastValue'],
+ 'Unexpected callback attributeChanged arguments');
+}, 'Test attributeChanged callback arguments if attribute value is changed as property. ' +
+ 'The custom element is created via innerHTML property');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = newHTMLElementPrototype();
+ var GeneratedConstructor = doc.registerElement('x-g', {prototype: proto});
+ var customElement = new GeneratedConstructor();
+
+ customElement.setAttribute('class', 'someClass someSuperClass');
+ proto.attributeChangedCallbackCalledCounter = 0;
+ customElement.classList.toggle('someClass');
+ assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
+ 'Callback attributeChanged should be called');
+}, 'Test attributeChanged callback is called if attribute value is changed by classList.toggle(). ' +
+ 'The custom element is created via constructor');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = newHTMLElementPrototype();
+ doc.registerElement('x-h', {prototype: proto});
+
+ doc.body.innerHTML = '<x-h id="x-h" class="oldValue lastValue"></x-h>';
+ var customElement = doc.querySelector('#x-h');
+ customElement.classList.toggle('lastValue');
+ assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
+ 'Callback attributeChanged should be called');
+ assert_array_equals(proto.attributeChangedCallbackArgs,
+ ['class', 'oldValue lastValue', 'oldValue'],
+ 'Unexpected callback attributeChanged arguments');
+}, 'Test attributeChanged callback arguments if attribute value is changed by classList.toggle(). ' +
+ 'The custom element is created via innerHTML property');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ doc.body.innerHTML = '<x-i id="x-i" class="oldValue"></x-i>';
+ var customElement = doc.querySelector('#x-i');
+ customElement.setAttribute('class', 'newValue');
+ customElement.setAttribute('class', 'newestValue');
+
+ var proto = newHTMLElementPrototype();
+ doc.registerElement('x-i', {prototype: proto});
+
+ assert_equals(proto.attributeChangedCallbackCalledCounter, 0,
+ 'Callback attributeChanged should not be called');
+
+ customElement.setAttribute('class', 'rightValue');
+ assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
+ 'Callback attributeChanged should not be called');
+ assert_array_equals(proto.attributeChangedCallbackArgs,
+ ['class', 'newestValue', 'rightValue'],
+ 'Unexpected callback attributeChanged arguments');
+}, 'Test attributeChanged callback is not called if custom element is not registered');
+
+
+testInIFrame('../../resources/x-element.html', function(doc) {
+ var proto = newHTMLElementPrototype();
+ doc.registerElement('x-element', {prototype: proto});
+
+ var customElement = doc.querySelector('#x-element');
+ customElement.setAttribute('class', 'firstValue');
+ customElement.setAttribute('class', 'secondValue');
+ assert_equals(proto.attributeChangedCallbackCalledCounter, 2, 'Callback ' +
+ 'attributeChanged should be called after call to setAttribute()');
+
+ customElement.classList.add('someClass3');
+ assert_equals(proto.attributeChangedCallbackCalledCounter, 3, 'Callback ' +
+ 'attributeChanged should be called after call to classList.add()');
+
+ customElement.id = 'someId';
+ assert_equals(proto.attributeChangedCallbackCalledCounter, 4, 'Callback ' +
+ 'attributeChanged should be called after changing attribute as property');
+}, 'Test attributeChanged callback is called if attribute value is changed. ' +
+ 'The document has browsing context');
+
+
+testInIFrame('../../resources/x-element.html', function(doc) {
+ var proto = newHTMLElementPrototype();
+ doc.registerElement('x-element', {prototype: proto});
+ var customElement = doc.querySelector('#x-element');
+
+ customElement.setAttribute('class', 'firstValue');
+ customElement.setAttribute('class', 'secondValue');
+ assert_array_equals(proto.attributeChangedCallbackArgs,
+ ['class', 'firstValue', 'secondValue'],
+ 'Unexpected callback attributeChanged arguments after call to setAttribute()');
+
+ customElement.classList.add('newestValue');
+ assert_array_equals(proto.attributeChangedCallbackArgs,
+ ['class', 'secondValue', 'secondValue newestValue'],
+ 'Unexpected callback attributeChanged arguments after call to classList.add()');
+
+ customElement.className = 'lastValue';
+ assert_array_equals(proto.attributeChangedCallbackArgs,
+ ['class', 'secondValue newestValue', 'lastValue'],
+ 'Unexpected callback attributeChanged arguments after changing attribute as property');
+}, 'Test attributeChanged callback arguments if attribute value is changed. ' +
+ 'The document has browsing context');
+
+
+testInIFrame('../../resources/x-element.html', function(doc) {
+ var customElement = doc.querySelector('#x-element');
+ customElement.setAttribute('class', 'firstValue');
+ customElement.setAttribute('class', 'secondValue');
+
+ var proto = newHTMLElementPrototype();
+ doc.registerElement('x-element', {prototype: proto});
+ customElement.setAttribute('class', 'thirdValue');
+
+ assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
+ 'Callback attributeChanged should be called');
+ assert_array_equals(proto.attributeChangedCallbackArgs,
+ ['class', 'secondValue', 'thirdValue'],
+ 'Unexpected callback attributeChanged arguments after setAttribute() call');
+}, 'Test attributeChanged callback is not called if custom element is not registered. ' +
+ 'The document has browsing context');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/custom-element-lifecycle/types-of-callbacks/attribute-changed-callback-remove-attribute-test.html b/tests/wpt/web-platform-tests/custom-elements/custom-element-lifecycle/types-of-callbacks/attribute-changed-callback-remove-attribute-test.html
new file mode 100644
index 00000000000..30e892c3943
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/custom-element-lifecycle/types-of-callbacks/attribute-changed-callback-remove-attribute-test.html
@@ -0,0 +1,167 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Test attribute removing to check attributeChanged callback of a custom element</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="assert" content="attributeChanged callback must be enqueued whenever custom element's attribute is removed">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#types-of-callbacks">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = newHTMLElementPrototype();
+ var GeneratedConstructor = doc.registerElement('x-a', {prototype: proto});
+
+ var customElement = new GeneratedConstructor();
+ //attributeChangedCallback should be called the first time here
+ customElement.setAttribute('class', 'someClass');
+ //attributeChangedCallback should be called the second time here
+ customElement.removeAttribute('class');
+ assert_equals(proto.attributeChangedCallbackCalledCounter, 2, 'Callback attributeChanged should be called ' +
+ 'after setAttribute() and removeAttribute() calls');
+}, 'Test attributeChanged callback if attribute is removed. ' +
+ 'The custom element created via constructor');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ HTML5_ELEMENTS.forEach(function(element) {
+ var obj = doc.createElement(element);
+ var proto = newCustomElementPrototype(obj.constructor.prototype);
+ var GeneratedConstructor = doc.registerElement('x-' + element + '-' + element + '-1', {
+ prototype: proto,
+ extends: element
+ });
+
+ var customElement = new GeneratedConstructor();
+ //attributeChangedCallback should be called the first time here
+ customElement.setAttribute('class', 'someClass');
+ //attributeChangedCallback should be called the second time here
+ customElement.removeAttribute('class');
+ assert_equals(proto.attributeChangedCallbackCalledCounter, 2,
+ 'Callback attributeChanged should be called ' +
+ 'after setAttribute() and removeAttribute() calls for "' + element + '"');
+ });
+}, 'Test attributeChanged callback if attribute is removed. ' +
+ 'The custom element created via constructor and extends HTML element');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = newHTMLElementPrototype();
+ doc.registerElement('x-b', {prototype: proto});
+
+ doc.body.innerHTML = '<x-b id="x-b" class="theClass"></x-b>';
+ var customElement = doc.querySelector('#x-b');
+ customElement.removeAttribute('class');
+ assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
+ 'Callback attributeChanged should be called ' +
+ 'after removeAttribute() call');
+}, 'Test attributeChanged callback if attribute is removed. ' +
+ 'The custom element created via innerHTML property');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = newHTMLElementPrototype();
+ doc.registerElement('x-c', {prototype: proto});
+
+ doc.body.innerHTML = '<x-c id="x-c" class="theClass"></x-c>';
+ var customElement = doc.querySelector('#x-c');
+ customElement.removeAttribute('class');
+ assert_equals(proto.attributeChangedCallbackArgs[2], null,
+ 'Removing an attribute should invoke ' +
+ 'the attributeChanged callback with a null new value');
+ assert_array_equals(proto.attributeChangedCallbackArgs,
+ ['class', 'theClass', null],
+ 'Unexpected attributeChanged callback arguments');
+}, 'Test attributeChanged callback arguments if attribute is removed. ' +
+ 'The custom element created via innerHTML property');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = newHTMLElementPrototype();
+
+ doc.body.innerHTML = '<x-d id="x-d" class="theClass"></x-d>';
+ var customElement = doc.querySelector('#x-d');
+ // this should not call or enqueue attributeChangedCallback
+ customElement.setAttribute('class', 'someClass');
+ // this one should not too
+ customElement.removeAttribute('class');
+ assert_equals(proto.attributeChangedCallbackCalledCounter, 0,
+ 'Callback attributeChanged should not be called');
+
+ doc.registerElement('x-d', {prototype: proto});
+ // this call invokes attributeChangedCallback
+ customElement.setAttribute('name', 'someName');
+ // and this one
+ customElement.removeAttribute('name');
+ assert_equals(proto.attributeChangedCallbackCalledCounter, 2,
+ 'Callback attributeChanged should be called ' +
+ 'after setAttribute() and removeAttribute() calls');
+}, 'Test attributeChanged callback is not called if attribute is removed. ' +
+ 'The custom element created via innerHTML property and unresolved at first');
+
+
+testInIFrame('../../resources/x-element.html', function(doc) {
+ var proto = newHTMLElementPrototype();
+ doc.registerElement('x-element', {prototype: proto});
+
+ var customElement = doc.querySelector('#x-element');
+ customElement.setAttribute('class', 'someClass');
+ customElement.removeAttribute('class');
+ assert_equals(proto.attributeChangedCallbackCalledCounter, 2,
+ 'Callback attributeChanged should be called ' +
+ 'after setAttribute() and removeAttribute() calls');
+}, 'Test attributeChanged callback is called if attribute is removed. ' +
+ 'The custom element created via constructor and the document has browsing context');
+
+
+testInIFrame('../../resources/x-element.html', function(doc) {
+ var proto = newHTMLElementPrototype();
+ doc.registerElement('x-element', {prototype: proto});
+
+ doc.body.innerHTML = '<x-element id="x-element" class="theClass"></x-element>';
+ var customElement = doc.querySelector('#x-element');
+ customElement.removeAttribute('class');
+ assert_equals(proto.attributeChangedCallbackArgs[2], null,
+ 'Removing an attribute should invoke ' +
+ 'the attributeChanged callback with a null new value');
+ assert_array_equals(proto.attributeChangedCallbackArgs,
+ ['class', 'theClass', null],
+ 'Unexpected attributeChanged callback arguments');
+}, 'Test attributeChanged callback arguments if attribute is removed. ' +
+ 'The custom element created via innerHTML property and the document has browsing context');
+
+
+testInIFrame('../../resources/x-element.html', function(doc) {
+ var customElement = doc.querySelector('#x-element');
+ // this should not call or enqueue attributeChangedCallback
+ customElement.setAttribute('name', 'someName');
+ // this one too
+ customElement.removeAttribute('name');
+
+ var proto = newHTMLElementPrototype();
+ doc.registerElement('x-element', {prototype: proto});
+ assert_equals(proto.attributeChangedCallbackCalledCounter, 0,
+ 'Callback attributeChanged should not be called');
+ // this call invokes attributeChangedCallback
+ customElement.setAttribute('class', 'someClass');
+ // this call invokes attributeChangedCallback at second time
+ customElement.removeAttribute('class');
+ assert_equals(proto.attributeChangedCallbackCalledCounter, 2,
+ 'Callback attributeChanged should be called ' +
+ 'after setAttribute() and removeAttribute() calls');
+}, 'Test attributeChanged callback if attribute is removed. ' +
+ 'The custom element created via innerHTML property and unresolved at first. ' +
+ 'The document has browsing context');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/custom-element-lifecycle/types-of-callbacks/attribute-changed-callback-set-attribute-test.html b/tests/wpt/web-platform-tests/custom-elements/custom-element-lifecycle/types-of-callbacks/attribute-changed-callback-set-attribute-test.html
new file mode 100644
index 00000000000..cf15e12d759
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/custom-element-lifecycle/types-of-callbacks/attribute-changed-callback-set-attribute-test.html
@@ -0,0 +1,339 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Test attributeChanged callback is called if custom element attribute value is set</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<meta name="assert" content="attributeChanged callback ... must be enqueued whenever custom element's attribute is added, changed or removed.">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#types-of-callbacks">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = newHTMLElementPrototype();
+ var GeneratedConstructor = doc.registerElement('x-a', {prototype: proto});
+
+ var customElement = new GeneratedConstructor();
+ customElement.setAttribute('class', 'someClass');
+ assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
+ 'Callback attributeChanged should be called');
+}, 'Test attributeChanged callback is called if attribute value is set by method ' +
+ 'setAttribute(). The custom element is created via constructor.');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = newHTMLElementPrototype();
+ var GeneratedConstructor = doc.registerElement('x-b', {prototype: proto});
+
+ var customElement = new GeneratedConstructor();
+ customElement.setAttribute('class', 'someClass');
+ assert_array_equals(proto.attributeChangedCallbackArgs, ['class', null, 'someClass'],
+ 'Unexpected callback attributeChanged arguments');
+}, 'Test attributeChanged callback arguments if attribute value is set by method ' +
+ 'setAttribute(). The custom element is created via constructor.');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = newHTMLElementPrototype();
+ var GeneratedConstructor = doc.registerElement('x-c', {prototype: proto});
+
+ var customElement = new GeneratedConstructor();
+ customElement.classList.add('someClass');
+ assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
+ 'Callback attributeChanged should be called');
+}, 'Test attributeChanged callback is called if attribute value is set by method ' +
+ 'classList.add(). The custom element is created via constructor.');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = newHTMLElementPrototype();
+ var GeneratedConstructor = doc.registerElement('x-d', {prototype: proto});
+
+ var customElement = new GeneratedConstructor();
+ customElement.classList.add('someClass');
+ assert_array_equals(proto.attributeChangedCallbackArgs, ['class', null, 'someClass'],
+ 'Unexpected callback attributeChanged arguments');
+}, 'Test attributeChanged callback arguments if attribute value is set by method ' +
+ 'classList.add(). The custom element is created via constructor.');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = newHTMLElementPrototype();
+ var GeneratedConstructor = doc.registerElement('x-e', {prototype: proto});
+
+ var customElement = new GeneratedConstructor();
+ customElement.classList.toggle('someClass');
+ assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
+ 'Callback attributeChanged should be called');
+}, 'Test attributeChanged callback is called if attribute value is set by method ' +
+ 'classList.toggle(). The custom element is created via constructor.');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = newHTMLElementPrototype();
+ var GeneratedConstructor = doc.registerElement('x-f', {prototype: proto});
+
+ var customElement = new GeneratedConstructor();
+ customElement.classList.toggle('someClass');
+ assert_array_equals(proto.attributeChangedCallbackArgs, ['class', null, 'someClass'],
+ 'Unexpected callback attributeChanged arguments');
+}, 'Test attributeChanged callback arguments if attribute value is set by method ' +
+ 'classList.toggle(). The custom element is created via constructor.');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = newHTMLElementPrototype();
+ var GeneratedConstructor = doc.registerElement('x-g', {prototype: proto});
+
+ var customElement = new GeneratedConstructor();
+ customElement.className = 'someClass';
+ assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
+ 'Callback attributeChanged should be called');
+}, 'Test attributeChanged callback is called if attribute value is set as property. ' +
+ 'The custom element is created via constructor.');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = newHTMLElementPrototype();
+ var GeneratedConstructor = doc.registerElement('x-h', {prototype: proto});
+
+ var customElement = new GeneratedConstructor();
+ customElement.className = 'someClass';
+ assert_array_equals(proto.attributeChangedCallbackArgs, ['class', null, 'someClass'],
+ 'Unexpected callback attributeChanged arguments');
+}, 'Test attributeChanged callback arguments if attribute value is set as property. '+
+ 'The custom element is created via constructor.');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = newHTMLElementPrototype();
+ doc.registerElement('x-i', {prototype: proto});
+
+ doc.body.innerHTML = '<x-i id="x-i" class="theClass"></x-i>';
+ assert_equals(proto.attributeChangedCallbackCalledCounter, 0,
+ 'Callback attributeChanged should not be called');
+}, 'Test attributeChanged callback is not called if attribute value is specified in HTML. '+
+ 'The custom element is created via innerHTML property.');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = newHTMLElementPrototype();
+ doc.registerElement('x-j', {prototype: proto});
+
+ doc.body.innerHTML = '<x-j id="x-j" class="theClass"></x-j>';
+ var customElement = doc.querySelector('#x-j');
+ customElement.setAttribute('class', 'someClass');
+ assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
+ 'Callback attributeChanged should be called');
+}, 'Test attributeChanged callback is called if attribute value is set by method setAttribute(). '+
+ 'The custom element is created via innerHTML property.');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = newHTMLElementPrototype();
+ doc.registerElement('x-k', {prototype: proto});
+
+ doc.body.innerHTML = '<x-k id="x-k"></x-k>';
+ var customElement = doc.querySelector('#x-k');
+ customElement.setAttribute('class', 'someClass');
+ assert_array_equals(proto.attributeChangedCallbackArgs, ['class', null, 'someClass'],
+ 'Unexpected callback attributeChanged arguments');
+}, 'Test attributeChanged callback arguments if attribute value is set by method setAttribute(). '+
+ 'The custom element is created via innerHTML property.');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+
+ doc.body.innerHTML = '<x-l id="x-l"></x-l>';
+ var customElement = doc.querySelector('#x-l');
+ // this call shouldn't invoke or enqueue the callback
+ customElement.setAttribute('class', 'someClass');
+
+ var proto = newHTMLElementPrototype();
+ doc.registerElement('x-l', {prototype: proto});
+ assert_equals(proto.attributeChangedCallbackCalledCounter, 0,
+ 'Callback attributeChanged should not be called');
+ // this one should
+ customElement.setAttribute('class', 'someClass2');
+ assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
+ 'Callback attributeChanged should be called');
+}, 'Test attributeChanged callback is not called if attribute value of unresolved element '+
+ 'is set by method setAttribute().');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ HTML5_ELEMENTS.forEach(function(element) {
+ var obj = doc.createElement(element);
+ var proto = newCustomElementPrototype(obj.constructor.prototype);
+ var GeneratedConstructor = doc.registerElement('x-' + element + '-' + element + '-1', {
+ prototype: proto,
+ extends: element
+ });
+
+ var customElement = new GeneratedConstructor();
+ customElement.setAttribute('class', 'someClass');
+ assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
+ 'Callback attributeChanged should be called');
+ });
+}, 'Test attributeChanged callback of the custom element that extends some HTML element. ' +
+ 'Test that the callback is called');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ HTML5_ELEMENTS.forEach(function(element) {
+ var obj = doc.createElement(element);
+ var proto = newCustomElementPrototype(obj.constructor.prototype);
+ var GeneratedConstructor = doc.registerElement('x-' + element + '-' + element + '-1-1', {
+ prototype: proto,
+ extends: element
+ });
+
+ var customElement = new GeneratedConstructor();
+ customElement.classList.add('someClass');
+ assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
+ 'Callback attributeChanged should be called');
+ });
+}, 'Test attributeChanged callback is called if attribute is set by method classList.add(). '+
+ 'The custom element extends some HTML element.');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ HTML5_ELEMENTS.forEach(function(element) {
+ var obj = doc.createElement(element);
+ var proto = newCustomElementPrototype(obj.constructor.prototype);
+ var GeneratedConstructor = doc.registerElement('x-' + element + '-' + element + '-2', {
+ prototype: proto,
+ extends: element
+ });
+
+ var customElement = new GeneratedConstructor();
+ customElement.setAttribute('class', 'someClass');
+ assert_array_equals(proto.attributeChangedCallbackArgs, ['class', null, 'someClass'],
+ 'Unexpected callback attributeChanged arguments');
+ });
+}, 'Test attributeChanged callback arguments if attribute value is set by method setAttribute(). '+
+ 'The custom element extends some HTML element.');
+
+
+testInIFrame('../../resources/x-element.html', function(doc) {
+ var proto = newHTMLElementPrototype();
+ doc.registerElement('x-element', {prototype: proto});
+
+ var customElement = doc.querySelector('#x-element');
+ customElement.setAttribute('class', 'someClass');
+ assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
+ 'Callback attributeChanged should be called');
+}, 'Test attributeChanged callback is called if attribute value is set by method setAttribute(). '+
+ 'The document has browsing context.');
+
+
+testInIFrame('../../resources/x-element.html', function(doc) {
+ var proto = newHTMLElementPrototype();
+ doc.registerElement('x-element', {prototype: proto});
+
+ var customElement = doc.querySelector('#x-element');
+ customElement.setAttribute('class', 'someClass');
+ assert_array_equals(proto.attributeChangedCallbackArgs, ['class', null, 'someClass'],
+ 'Unexpected callback attributeChanged arguments');
+}, 'Test attributeChanged callback arguments if attribute value is set by method setAttribute(). '+
+ 'The document has browsing context.');
+
+
+testInIFrame('../../resources/x-element.html', function(doc) {
+ var proto = newHTMLElementPrototype();
+ doc.registerElement('x-element', {prototype: proto});
+
+ var customElement = doc.querySelector('#x-element');
+ customElement.classList.add('someClass');
+ assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
+ 'Callback attributeChanged should be called');
+}, 'Test attributeChanged callback is called if attribute value is set by method classList.add(). '+
+ 'The document has browsing context.');
+
+
+testInIFrame('../../resources/x-element.html', function(doc) {
+ var proto = newHTMLElementPrototype();
+ doc.registerElement('x-element', {prototype: proto});
+
+ var customElement = doc.querySelector('#x-element');
+ customElement.classList.add('someClass');
+ assert_array_equals(proto.attributeChangedCallbackArgs, ['class', null, 'someClass'],
+ 'Unexpected callback attributeChanged arguments');
+}, 'Test attributeChanged callback arguments if attribute value is set by method classList.add(). '+
+ 'The document has browsing context.');
+
+
+testInIFrame('../../resources/x-element.html', function(doc) {
+ var customElement = doc.querySelector('#x-element');
+ // this call shouldn't invoke or enqueue the callback
+ customElement.setAttribute('name', 'someName');
+
+ var proto = newHTMLElementPrototype();
+ doc.registerElement('x-element', {prototype: proto});
+ assert_equals(proto.attributeChangedCallbackCalledCounter, 0,
+ 'Callback attributeChanged should not be called');
+ // this one should
+ customElement.setAttribute('class', 'someClass');
+ assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
+ 'Callback attributeChanged should be called');
+}, 'Test attributeChanged callback is not called if attribute value of unresolved element '+
+ 'is set by method setAttribute(). The document has browsing context.');
+
+
+testInIFrame('../../resources/x-element.html', function(doc) {
+ HTML5_ELEMENTS.forEach(function(element) {
+ var obj = doc.createElement(element);
+ var proto = newCustomElementPrototype(obj.constructor.prototype);
+ var GeneratedConstructor = doc.registerElement('x-' + element + '-' + element + '-1', {
+ prototype: proto,
+ extends: element
+ });
+
+ var customElement = new GeneratedConstructor();
+ customElement.setAttribute('class', 'someClass');
+ assert_equals(proto.attributeChangedCallbackCalledCounter, 1,
+ 'Callback attributeChanged should be called');
+ });
+}, 'Test attributeChanged callback is called if attribute value is set by method setAttribute(). '+
+ 'The document has browsing context. The custom element extends some HTML element.');
+
+
+testInIFrame('../../resources/x-element.html', function(doc) {
+ HTML5_ELEMENTS.forEach(function(element) {
+ var obj = doc.createElement(element);
+ var proto = newCustomElementPrototype(obj.constructor.prototype);
+ var GeneratedConstructor = doc.registerElement('x-' + element + '-' + element + '-2', {
+ prototype: proto,
+ extends: element
+ });
+
+ var customElement = new GeneratedConstructor();
+ customElement.setAttribute('class', 'someClass');
+ assert_array_equals(proto.attributeChangedCallbackArgs, ['class', null, 'someClass'],
+ 'Unexpected callback attributeChanged arguments');
+ });
+}, 'Test attributeChanged callback arguments if attribute value is set by method setAttribute(). '+
+ 'The document has browsing context. The custom element extends some HTML element.');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/custom-element-lifecycle/types-of-callbacks/created-callback-element-prototype-test.html b/tests/wpt/web-platform-tests/custom-elements/custom-element-lifecycle/types-of-callbacks/created-callback-element-prototype-test.html
new file mode 100644
index 00000000000..a7e6294755d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/custom-element-lifecycle/types-of-callbacks/created-callback-element-prototype-test.html
@@ -0,0 +1,88 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>The custom element prototype must be set just prior to invoking created callback</title>
+<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="assert" content="The custom element prototype must be set just prior to invoking callback.">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#types-of-callbacks">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = newHTMLElementPrototype();
+
+ doc.body.innerHTML = '<x-a></x-a>';
+ doc.registerElement('x-a', {prototype: proto});
+ assert_equals(proto.createdCallbackThis.constructor.prototype, proto,
+ 'The custom element prototype is incorrect inside created callback');
+}, 'Test custom element prototype inside created callback when custom element is created ' +
+ 'in HTML before registration of a custom element');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = newHTMLElementPrototype();
+
+ doc.registerElement('x-b', {prototype: proto});
+ doc.body.innerHTML = '<x-b></x-b>';
+ assert_equals(proto.createdCallbackThis.constructor.prototype, proto,
+ 'The custom element prototype is incorrect inside created callback');
+}, 'Test custom element prototype inside created callback when custom element is created ' +
+ 'in HTML after registration of a custom element');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = newHTMLElementPrototype();
+ var customElement = doc.createElement('x-c');
+
+ doc.body.appendChild(customElement);
+ doc.registerElement('x-c', {prototype: proto});
+ assert_equals(proto.createdCallbackThis.constructor.prototype, proto,
+ 'The custom element prototype is incorrect inside created callback');
+}, 'Test custom element prototype inside created callback when custom element is created ' +
+ 'via document.createElement() before registration of a custom element');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = newHTMLElementPrototype();
+ doc.registerElement('x-d', {prototype: proto});
+
+ var customElement = doc.createElement('x-d');
+ doc.body.appendChild(customElement);
+ assert_equals(proto.createdCallbackThis.constructor.prototype, proto,
+ 'The custom element prototype is incorrect inside created callback');
+}, 'Test custom element prototype inside created callback when custom element is created ' +
+ 'via document.createElement() after registration of a custom element');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = newHTMLElementPrototype();
+ var GeneratedConstructor = doc.registerElement('x-e', {prototype: proto});
+ var customElement = new GeneratedConstructor();
+
+ assert_equals(proto.createdCallbackThis.constructor.prototype, proto,
+ 'The custom element prototype is incorrect inside created callback');
+}, 'Test custom element prototype inside created callback when custom element is created ' +
+ 'via constructor returned by method registerElement');
+
+
+testInIFrame('../../resources/x-element.html', function(doc) {
+ var proto = newHTMLElementPrototype();
+ doc.registerElement('x-element', {prototype: proto});
+ assert_equals(proto.createdCallbackThis.constructor.prototype, proto,
+ 'The custom element prototype is incorrect inside created callback');
+}, 'Test custom element prototype inside created callback when custom element is created ' +
+ 'by UA parser before registration of a custom element');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/custom-element-lifecycle/types-of-callbacks/created-callback-invocation-order-test.html b/tests/wpt/web-platform-tests/custom-elements/custom-element-lifecycle/types-of-callbacks/created-callback-invocation-order-test.html
new file mode 100644
index 00000000000..e617ecd7ef8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/custom-element-lifecycle/types-of-callbacks/created-callback-invocation-order-test.html
@@ -0,0 +1,243 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>All other callbacks must not be enqueued until after the created callback's invocation had started</title>
+<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="assert" content="All other callbacks must not be enqueued until after the created callback's invocation had started.">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#types-of-callbacks">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+function newPrototypeWithCallbackLog() {
+ var proto = Object.create(HTMLElement.prototype);
+ proto.callbackLog = [];
+ proto.createdCallback = function() {
+ proto.callbackLog.push('created');
+ };
+ proto.attachedCallback = function() {
+ proto.callbackLog.push('attached');
+ };
+ proto.attributeChangedCallback = function() {
+ proto.callbackLog.push('attributeChanged');
+ };
+ proto.detachedCallback = function() {
+ proto.callbackLog.push('detached');
+ };
+ return proto;
+}
+
+testInIFrame('../../resources/blank.html', function(doc) {
+ var proto = newPrototypeWithCallbackLog();
+ doc.registerElement('x-a', {prototype: proto});
+ doc.body.innerHTML = '<x-a></x-a>';
+
+ assert_equals(proto.callbackLog[0], 'created', 'The callback ' +
+ proto.callbackLog[0] + ' should be enqueued after created callback');
+ assert_in_array('attached', proto.callbackLog, 'The callback ' +
+ 'attached should be called');
+}, 'Test attached callback is enqueued after created callback');
+
+
+testInIFrame('../../resources/blank.html', function(doc) {
+ var proto = newPrototypeWithCallbackLog();
+ doc.registerElement('x-b', {prototype: proto});
+ doc.body.innerHTML = '<x-b id="x-b"></x-b>';
+ var customElement = doc.querySelector('#x-b');
+ customElement.setAttribute('key', 'value');
+
+ assert_equals(proto.callbackLog[0], 'created', 'The callback ' +
+ proto.callbackLog[0] + ' should not be enqueued before created callback');
+ assert_in_array('attributeChanged', proto.callbackLog,
+ 'The callback attributeChanged should be called');
+}, 'Test attributeChanged callback is enqueued after created callback. ' +
+ 'Document has browsing context');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = newPrototypeWithCallbackLog();
+ doc.registerElement('x-c', {prototype: proto});
+ doc.body.innerHTML = '<x-c id="x-c"></x-c>';
+ var customElement = doc.querySelector('#x-c');
+ customElement.setAttribute('key', 'value');
+ assert_equals(proto.callbackLog[0], 'created', 'The callback ' +
+ proto.callbackLog[0] + ' should not be enqueued before created callback');
+ assert_in_array('attributeChanged', proto.callbackLog,
+ 'The callback attributeChanged should be called');
+}, 'Test attributeChanged callback is enqueued after created callback. ' +
+ 'Document has no browsing context');
+
+
+testInIFrame('../../resources/x-element.html', function(doc) {
+ var proto = newPrototypeWithCallbackLog();
+ doc.registerElement('x-element', {prototype: proto});
+ var customElement = doc.querySelector('#x-element');
+ doc.body.removeChild(customElement);
+
+ assert_equals(proto.callbackLog[0], 'created', 'The callback ' +
+ proto.callbackLog[0] + ' should not be enqueued before created callback');
+ assert_in_array('detached', proto.callbackLog,
+ 'The callback detached should be called');
+}, 'Test detached callback is enqueued after created callback.');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var proto1 = newPrototypeWithCallbackLog();
+ proto1.createdCallback = function() {
+ proto1.callbackLog.push('created');
+ var xe = doc.querySelector('#x-e');
+ xe.setAttribute('key', 'value');
+ };
+ var proto2 = newPrototypeWithCallbackLog();
+
+ doc.registerElement('x-d', {prototype: proto1});
+ doc.registerElement('x-e', {prototype: proto2});
+ doc.body.innerHTML = '<x-d><x-e id="x-e"></x-e></x-d>';
+
+ assert_array_equals(proto2.callbackLog, ['created'],
+ 'attributeChanged callback should not be enqueued before created callback');
+}, 'Test attributeChanged callback is not enqueued before created callback started. ' +
+ 'Document has no browsing context');
+
+
+testInIFrame('../../resources/blank.html', function(doc) {
+ var proto1 = newPrototypeWithCallbackLog();
+ proto1.createdCallback = function() {
+ proto1.callbackLog.push('created');
+ var xe = doc.querySelector('#x-g');
+ xe.setAttribute('key', 'value');
+ };
+ var proto2 = newPrototypeWithCallbackLog();
+
+ doc.registerElement('x-f', {prototype: proto1});
+ doc.registerElement('x-g', {prototype: proto2});
+ doc.body.innerHTML = '<x-f><x-g id="x-g"></x-g></x-f>';
+
+ assert_array_equals(proto2.callbackLog, ['created', 'attached'],
+ 'attributeChanged callback should not be called before created callback started');
+}, 'Test attributeChanged callback is not enqueued before created callback started. ' +
+ 'Document has browsing context');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = newPrototypeWithCallbackLog();
+ proto.createdCallback = function() {
+ proto.callbackLog.push('created');
+ this.setAttribute('key', 'value');
+ };
+ doc.registerElement('x-h', {prototype: proto});
+ doc.body.innerHTML = '<x-h></x-h>';
+
+ assert_array_equals(proto.callbackLog, ['created', 'attributeChanged'],
+ 'attributeChanged callback should be enqueued after created callback');
+}, 'Test attributeChanged callback is enqueued after created callback started. ' +
+ 'Document has no browsing context');
+
+
+testInIFrame('../../resources/blank.html', function(docWithBrowsingContext) {
+ var docNoBrowsingContext = newHTMLDocument();
+
+ var proto1 = newPrototypeWithCallbackLog();
+ var proto2 = newPrototypeWithCallbackLog();
+ proto1.createdCallback = function() {
+ proto1.callbackLog.push('created');
+ var xk = docNoBrowsingContext.querySelector('#x-k');
+ assert_equals(proto2.callbackLog.length, 0, 'Created callback for x-k ' +
+ 'should not be called before created callback for x-i');
+ docWithBrowsingContext.body.appendChild(xk);
+ };
+
+ docNoBrowsingContext.registerElement('x-i', {prototype: proto1});
+ docNoBrowsingContext.registerElement('x-k', {prototype: proto2});
+ docNoBrowsingContext.body.innerHTML = '<x-i><x-k id="x-k"></x-k></x-i>';
+
+ // Though at the moment of inserting <x-k> into docWithBrowsingContext
+ // created callback is not called for <x-k> yet, attached calback is enqueued
+ // anyway. Because specification for setting custom element prototype algorithm reads:
+ // ....
+ // 3. If ELEMENT is in a document and this document has a browsing context:
+ // 1. Enqueue attached callback for ELEMENT
+ //
+ // Changes in the specification will follow, to reflect this exceptional case.
+ assert_array_equals(proto2.callbackLog, ['created', 'attached'],
+ 'attached callback should be enqueued when custom element prototype is set');
+}, 'Test attached callback is enqueued after created callback, but before created callback had started');
+
+
+testInIFrame('../../resources/blank.html', function(docWithBrowsingContext) {
+ var docNoBrowsingContext = newHTMLDocument();
+
+ var proto = newPrototypeWithCallbackLog();
+ proto.createdCallback = function() {
+ proto.callbackLog.push('created');
+ docWithBrowsingContext.body.appendChild(this);
+ };
+
+ docNoBrowsingContext.registerElement('x-l', {prototype: proto});
+ docNoBrowsingContext.body.innerHTML = '<x-l></x-l>';
+ assert_array_equals(proto.callbackLog, ['created', 'attached'],
+ 'attached callback should be enqueued after created callback had started');
+}, 'Test attached callback is enqueued after created callback had started');
+
+
+testInIFrame('../../resources/blank.html', function(doc) {
+ var proto1 = newPrototypeWithCallbackLog();
+ var proto2 = newPrototypeWithCallbackLog();
+ proto1.createdCallback = function() {
+ proto1.callbackLog.push('created');
+ var xn = doc.querySelector('#x-n');
+ assert_equals(proto2.callbackLog.length, 0, 'Created callback for x-n ' +
+ 'should not be called before created callback for x-m');
+ this.removeChild(xn);
+ };
+
+ doc.registerElement('x-m', {prototype: proto1});
+ doc.registerElement('x-n', {prototype: proto2});
+ doc.body.innerHTML = '<x-m><x-n id="x-n"></x-n></x-m>';
+ assert_array_equals(proto2.callbackLog, ['created'],
+ 'detached callback should not be enqueued before created callback had started');
+}, 'Test detached callback is not enqueued before created callback had started');
+
+
+testInIFrame('../../resources/blank.html', function(doc) {
+ var proto = newPrototypeWithCallbackLog();
+ proto.createdCallback = function() {
+ proto.callbackLog.push('created');
+ this.remove();
+ };
+
+ doc.registerElement('x-o', {prototype: proto});
+ doc.body.innerHTML = '<x-o></x-o>';
+
+ assert_array_equals(proto.callbackLog, ['created', 'attached', 'detached'],
+ 'detached callback should be enqueued after created callback had started');
+}, 'Test detached callback is enqueued after created callback had started');
+
+
+testInIFrame('../../resources/x-element.html', function(doc) {
+ var proto = newPrototypeWithCallbackLog();
+ doc.registerElement('x-element', {prototype: proto});
+
+ // Though at the moment of inserting <x-element> into the document
+ // created callback is not called for <x-element> yet, attached calback is enqueued
+ // anyway. Because specification for setting custom element prototype algorithm reads:
+ // ....
+ // 3. If ELEMENT is in a document and this document has a browsing context:
+ // 1. Enqueue attached callback for ELEMENT
+ //
+ // Changes in the specification will follow, to reflect this exceptional case.
+ assert_array_equals(proto.callbackLog, ['created', 'attached'],
+ 'attached callback should be enqueued when custom element prototype is set');
+}, 'Test attached callback is enqueued after created callback after registration ' +
+ 'of custom element type');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/custom-element-lifecycle/types-of-callbacks/created-callback-invocation-test.html b/tests/wpt/web-platform-tests/custom-elements/custom-element-lifecycle/types-of-callbacks/created-callback-invocation-test.html
new file mode 100644
index 00000000000..186ec794355
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/custom-element-lifecycle/types-of-callbacks/created-callback-invocation-test.html
@@ -0,0 +1,168 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Created callback of a custom element should be invoked after custom element instance is created and its definition is registered</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<meta name="assert" content="CREATED callback is invoked after custom element instance is created and its definition is registered">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#types-of-callbacks">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = newHTMLElementPrototype();
+ var GeneratedConstructor = doc.registerElement('x-a', {prototype: proto});
+ assert_equals(proto.createdCallbackCalledCounter, 0,
+ 'Callback created should not be called before element instance was created');
+ var customElement = new GeneratedConstructor();
+ assert_equals(proto.createdCallbackCalledCounter, 1,
+ 'Callback created should be called after element instance was created');
+}, 'Test created callback when custom element is created by constructor');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = newHTMLElementPrototype();
+ doc.registerElement('x-b', {prototype: proto});
+ assert_equals(proto.createdCallbackCalledCounter, 0,
+ 'Callback created should not be called before element instance was created');
+ doc.body.innerHTML = '<x-b></x-b>';
+ assert_equals(proto.createdCallbackCalledCounter, 1,
+ 'Callback created should be called after element instance was created');
+}, 'Test created callback when custom element is created in HTML');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = newHTMLElementPrototype();
+ doc.registerElement('x-c', {prototype: proto});
+ assert_equals(proto.createdCallbackCalledCounter, 0,
+ 'Callback created should not be called before element instance was created');
+ doc.body.innerHTML = '<div><x-c></x-c></div>';
+ assert_equals(proto.createdCallbackCalledCounter, 1,
+ 'Callback created should be called after element instance was created');
+}, 'Test created callback when custom element is created in HTML as descendant of ' +
+ 'another element');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = newHTMLElementPrototype();
+ doc.registerElement('x-d', {prototype: proto});
+ assert_equals(proto.createdCallbackCalledCounter, 0,
+ 'Callback created should not be called before element instance was created');
+ var customElement = doc.createElement('x-d');
+ assert_equals(proto.createdCallbackCalledCounter, 1,
+ 'Callback created should be called after element instance was created');
+}, 'Test created callback when custom element is created by createElement');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = newHTMLElementPrototype();
+
+ doc.body.innerHTML = '<x-e></x-e>';
+ doc.registerElement('x-e', {prototype: proto});
+ assert_equals(proto.createdCallbackCalledCounter, 1,
+ 'Callback created should be called after element instance was created');
+}, 'Test created callback when custom element is created in HTML before ' +
+ 'registration of a custom element');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = newHTMLElementPrototype();
+ doc.registerElement('x-f', {prototype: proto});
+ doc.body.innerHTML = '<x-f-unresolved id="x-f-unresolved"></x-f-unresolved>';
+ assert_equals(proto.createdCallbackCalledCounter, 0,
+ 'Callback created should not be called if custom element is unresolved');
+
+ var customElement = doc.querySelector('#x-f-unresolved');
+ customElement.constructor.prototype = proto;
+ assert_equals(proto.createdCallbackCalledCounter, 0,
+ 'Created callback should not be called if custom element is unresolved');
+}, 'Test created callback if custom element is unresolved.');
+
+
+testInIFrame('../../resources/x-element.html', function(doc) {
+ var proto = newHTMLElementPrototype();
+ doc.registerElement('x-element', {prototype: proto});
+ assert_equals(proto.createdCallbackCalledCounter, 1, 'Callback created should be called');
+}, 'Test created callback is called after custom element is created and registered. ' +
+ 'Document has browsing context');
+
+
+testInIFrame('../../resources/register-and-create-custom-element.html', function(doc) {
+ assert_equals(doc.querySelector('#log').innerText, 'Created callback was called',
+ 'Callback created should be called');
+}, 'Test created callback is called after custom element is registered and created. ' +
+ 'Document has browsing context');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = newHTMLElementPrototype();
+ var customElement = doc.createElement('x-g');
+
+ doc.registerElement('x-g', {prototype: proto});
+ assert_equals(proto.createdCallbackCalledCounter, 1,
+ 'Callback created should be called after registration of custom element');
+}, 'Test created callback when custom element is created by createElement '+
+ 'before registration of a custom element');
+
+
+test(function(){
+ var doc = newHTMLDocument();
+ var proto = newHTMLElementPrototype();
+ var GeneratedConstructor = doc.registerElement('x-h', {prototype: proto});
+
+ var customElement1 = new GeneratedConstructor();
+ assert_equals(proto.createdCallbackCalledCounter, 1, 'Callback created should be called');
+
+ var customElement2 = doc.createElement('x-h');
+ assert_equals(proto.createdCallbackCalledCounter, 2,
+ 'Callback created should be called after element instance was created');
+
+ doc.body.innerHTML = '<x-h></x-h>';
+ assert_equals(proto.createdCallbackCalledCounter, 3,
+ 'Callback created should be called after element instance was created');
+
+ doc.body.innerHTML = '<div><x-h></x-h></div>';
+ assert_equals(proto.createdCallbackCalledCounter, 4,
+ 'Callback created should be called after element instance was created');
+}, 'Test created callback. Create several custom elements using different ways');
+
+
+testInIFrame('../../resources/x-element.html', function(doc) {
+ var proto = newHTMLElementPrototype();
+
+ var GeneratedConstructor = doc.registerElement('x-element', {prototype: proto});
+ assert_equals(proto.createdCallbackCalledCounter, 1,
+ 'Callback created should be called for custom element in loaded document');
+
+ var customElement2 = new GeneratedConstructor();
+ assert_equals(proto.createdCallbackCalledCounter, 2,
+ 'Callback created should be called after element instance was created');
+
+ var customElement3 = doc.createElement('x-element');
+ assert_equals(proto.createdCallbackCalledCounter, 3,
+ 'Callback created should be called after element instance was created');
+
+ doc.body.innerHTML = '<x-element></x-element>';
+ assert_equals(proto.createdCallbackCalledCounter, 4,
+ 'Callback created should be called after element instance was created');
+
+ doc.body.innerHTML = '<div><x-element></x-element></div>';
+ assert_equals(proto.createdCallbackCalledCounter, 5,
+ 'Callback created should be called after element instance was created');
+}, 'Test created callback. Create several custom elements using different ways. ' +
+ 'Document has browsing context');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/custom-element-lifecycle/types-of-callbacks/detached-callback-move-element-test.html b/tests/wpt/web-platform-tests/custom-elements/custom-element-lifecycle/types-of-callbacks/detached-callback-move-element-test.html
new file mode 100644
index 00000000000..960c0ad8448
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/custom-element-lifecycle/types-of-callbacks/detached-callback-move-element-test.html
@@ -0,0 +1,131 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Test detached callback of a custom element when moving custom element between different documents</title>
+<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<meta name="assert" content="detached callback ... must be enqueued whenever custom element is removed from the document and this document has a browsing context.">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#types-of-callbacks">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = newHTMLElementPrototype();
+ doc.registerElement('x-a', {prototype: proto});
+
+ var customElement = doc.createElement('x-a');
+ doc.body.appendChild(customElement);
+
+ var divElement = doc.createElement('div');
+ doc.body.appendChild(divElement);
+ divElement.appendChild(customElement);
+
+ assert_equals(proto.detachedCallbackCalledCounter, 0,
+ 'Callback detached should not be called in document without a browsing context');
+}, 'Test detached callback is not called if moving custom element inside document ' +
+ 'without browsing context');
+
+
+testInIFrame('../../resources/blank.html', function(docWithBrowsingContext) {
+ var docNoBrowsingContext = newHTMLDocument();
+ var proto1 = newHTMLElementPrototype();
+ docNoBrowsingContext.registerElement('x-b', {prototype: proto1});
+
+ var customElement = docNoBrowsingContext.createElement('x-b');
+ docNoBrowsingContext.body.appendChild(customElement);
+ var proto2 = newHTMLElementPrototype();
+ docWithBrowsingContext.registerElement('x-b', {prototype: proto2});
+ docWithBrowsingContext.body.appendChild(customElement);
+
+ assert_equals(proto1.detachedCallbackCalledCounter, 0,
+ 'Callback detached should not be called in document without browsing context');
+ assert_equals(proto2.detachedCallbackCalledCounter, 0,
+ 'Callback detached, defined in receiving document, should not be called');
+}, 'Test detached callback is not called if moving custom element from ' +
+ 'document without browsing context to document with browsing context');
+
+
+testInIFrame('../../resources/blank.html', function(docWithBrowsingContext) {
+ var proto1 = newHTMLElementPrototype();
+ docWithBrowsingContext.registerElement('x-c', {prototype: proto1});
+
+ var customElement = docWithBrowsingContext.createElement('x-c');
+ docWithBrowsingContext.body.appendChild(customElement);
+
+ var docNoBrowsingContext = newHTMLDocument();
+ var proto2 = newHTMLElementPrototype();
+ docNoBrowsingContext.registerElement('x-c', {prototype: proto2});
+ docNoBrowsingContext.body.appendChild(customElement);
+ assert_equals(proto1.detachedCallbackCalledCounter, 1,
+ 'Callback detached should be called in documents with browsing context');
+ assert_equals(proto2.detachedCallbackCalledCounter, 0,
+ 'Callback detached, defined in receiving document, should not be called');
+}, 'Test detached callback if moving custom element from ' +
+ 'document with browsing context to document without browsing context');
+
+
+testInIFrame('../../resources/blank.html', function(doc) {
+ var proto = newHTMLElementPrototype();
+ doc.registerElement('x-d', {prototype: proto});
+
+ var customElement = doc.createElement('x-d');
+ doc.body.appendChild(customElement);
+ var divElement = doc.createElement('div');
+ doc.body.appendChild(divElement);
+ divElement.appendChild(customElement);
+ assert_equals(proto.detachedCallbackCalledCounter, 1,
+ 'Callback detached should be called in documents with browsing context');
+}, 'Test detached callback if moving custom element inside document ' +
+ 'with browsing context');
+
+
+var moveTest = async_test('Test detached callback if moving custom element from ' +
+ 'document with browsing context to document with browsing context');
+
+moveTest.step(function() {
+ var iframe1 = newIFrame('../../resources/blank.html');
+ iframe1.onload = moveTest.step_func(function() {
+ var doc1 = iframe1.contentDocument;
+
+ // register custom element type
+ var proto1 = newHTMLElementPrototype();
+ doc1.registerElement('x-e', {prototype: proto1});
+
+ // create custom element
+ var customElement = doc1.createElement('x-e');
+ doc1.body.appendChild(customElement);
+ assert_equals(proto1.detachedCallbackCalledCounter, 0,
+ 'Callback detached should not be called when element is created');
+
+ // create second iframe
+ var iframe2 = newIFrame('../../resources/x-element.html');
+ iframe2.onload = moveTest.step_func(function() {
+ var doc2 = iframe2.contentDocument;
+
+ // register custom element type
+ var proto2 = newHTMLElementPrototype();
+ doc2.registerElement('x-e', {prototype: proto2});
+
+ // move element
+ doc2.body.appendChild(customElement);
+ assert_equals(proto1.detachedCallbackCalledCounter, 1,
+ 'Callback detached should be called in documents with browsing context');
+ assert_equals(proto2.detachedCallbackCalledCounter, 0,
+ 'Callback detached, defined in receiving document, should not be called');
+
+ // test clean up
+ iframe1.remove();
+ iframe2.remove();
+ moveTest.done();
+ });
+
+ });
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/custom-element-lifecycle/types-of-callbacks/detached-callback-no-browsing-context-test.html b/tests/wpt/web-platform-tests/custom-elements/custom-element-lifecycle/types-of-callbacks/detached-callback-no-browsing-context-test.html
new file mode 100644
index 00000000000..fd401c8e4f8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/custom-element-lifecycle/types-of-callbacks/detached-callback-no-browsing-context-test.html
@@ -0,0 +1,148 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Detached callback of a custom element should not be called if document has no browsing context</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<meta name="assert" content="detached callback ... must be enqueued whenever custom element is removed from the document and this document has a browsing context.">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#types-of-callbacks">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = newHTMLElementPrototype();
+ doc.registerElement('x-a', {prototype: proto});
+ doc.body.innerHTML = '<x-a id="x-a"></x-a>';
+ var customElement = doc.querySelector('#x-a');
+ doc.body.removeChild(customElement);
+
+ assert_equals(proto.detachedCallbackCalledCounter, 0,
+ 'Callback detached should not be called if the document has no browsing context');
+}, 'Test detached callback if custom element is created via innerHTML property. ' +
+ 'Document has no browsing context');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = newHTMLElementPrototype();
+ doc.body.innerHTML = '<x-b id="x-b"></x-b>';
+ doc.registerElement('x-b', {prototype: proto});
+ var customElement = doc.querySelector('#x-b');
+ doc.body.removeChild(customElement);
+
+ assert_equals(proto.detachedCallbackCalledCounter, 0,
+ 'Callback detached should not be called if the document has no browsing context');
+}, 'Test detached callback if custom element is via innerHTML property before ' +
+ 'registration of a custom element. Document has no browsing context');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ doc.body.innerHTML = '<x-c id="x-c"></x-c>';
+ var customElement = doc.querySelector('#x-c');
+
+ var proto = newHTMLElementPrototype();
+ customElement.constructor.prototype = proto;
+ doc.body.removeChild(customElement);
+
+ assert_equals(proto.detachedCallbackCalledCounter, 0,
+ 'Callback detached should not be called if the document has no browsing context');
+}, 'Test detached callback if custom element is unregistered. ' +
+ 'Document has no browsing context');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = newHTMLElementPrototype();
+
+ doc.registerElement('x-d', {prototype: proto});
+ doc.body.innerHTML = '<x-d id="x-d"></x-d>';
+ doc.body.innerHTML = '';
+
+ assert_equals(proto.detachedCallbackCalledCounter, 0,
+ 'Callback detached should not be called if the document has no browsing context');
+}, 'Test detached callback if removing custom element via innerHTML property. ' +
+ 'Document has no browsing context');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = newHTMLElementPrototype();
+
+ doc.registerElement('x-e', {prototype: proto});
+ doc.body.innerHTML = '<div id="customParent"><x-e id="x-e"></x-e></div>';
+ var parent = doc.querySelector('#customParent');
+ doc.body.removeChild(parent);
+
+ assert_equals(proto.detachedCallbackCalledCounter, 0,
+ 'Callback detached should not be called if the document has no browsing context');
+}, 'Test detached callback if removing perent of custom element. ' +
+ 'Document has no browsing context');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = newHTMLElementPrototype();
+
+ doc.registerElement('x-f', {prototype: proto});
+ doc.body.innerHTML = '<div><x-f id="x-f"></x-f></div>';
+ doc.body.innerHTML = '';
+
+ assert_equals(proto.detachedCallbackCalledCounter, 0,
+ 'Callback detached should not be called if the document has no browsing context');
+}, 'Test detached callback if removing perent of custom element via innerHTML property. ' +
+ 'Document has no browsing context');
+
+
+var loseBrowsingContextTest = async_test('Test detached callback is not called ' +
+ 'if document lose browsing context and custom element is removed');
+
+loseBrowsingContextTest.step(function() {
+ var iframe = newIFrame('../../resources/x-element.html');
+ iframe.onload = loseBrowsingContextTest.step_func(function(){
+ var doc = iframe.contentDocument;
+ var proto = newHTMLElementPrototype();
+ doc.registerElement('x-element', {prototype: proto});
+
+ var customElement = doc.querySelector('#x-element');
+ iframe.remove();
+ customElement.remove();
+
+ assert_equals(proto.detachedCallbackCalledCounter, 0,
+ 'Callback detached should not be called if the document has no browsing context');
+ loseBrowsingContextTest.done();
+ });
+});
+
+
+var navigateTest = async_test('Test detached callback is not called, ' +
+ 'if document\'s window is navigated to another document and custom element is removed');
+
+navigateTest.step(function() {
+ var iframe = newIFrame('../../resources/x-element.html');
+ iframe.onload = navigateTest.step_func(function() {
+ var doc = iframe.contentDocument;
+ var proto = newHTMLElementPrototype();
+ doc.registerElement('x-element', {prototype: proto});
+ customElement = doc.querySelector('#x-element');
+
+ iframe.onload = navigateTest.step_func(function() {
+ customElement.remove();
+ assert_equals(proto.detachedCallbackCalledCounter, 0,
+ 'Callback detached should not be called ' +
+ 'if the document has no browsing context');
+ navigateTest.done();
+ iframe.remove();
+ });
+ iframe.src = '../../resources/blank.html';
+ });
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/custom-element-lifecycle/types-of-callbacks/detached-callback-with-browsing-context-test.html b/tests/wpt/web-platform-tests/custom-elements/custom-element-lifecycle/types-of-callbacks/detached-callback-with-browsing-context-test.html
new file mode 100644
index 00000000000..3f6681bada4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/custom-element-lifecycle/types-of-callbacks/detached-callback-with-browsing-context-test.html
@@ -0,0 +1,86 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Detached callback of a custom element should be called if document has browsing context</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<meta name="assert" content="detached callback ... must be enqueued whenever custom element is removed from the document and this document has a browsing context.">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#types-of-callbacks">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+testInIFrame('../../resources/x-element.html', function(doc) {
+ var proto = newHTMLElementPrototype();
+ doc.registerElement('x-element', {prototype: proto});
+ var customElement = doc.querySelector('#x-element');
+ doc.body.removeChild(customElement);
+ assert_equals(proto.detachedCallbackCalledCounter, 1, 'Callback detached should be ' +
+ 'called if custom element is removed from the document with browsing context');
+}, 'Test detached callback is called if custom element is removed by method removeChild() ' +
+ 'from document with browsing context');
+
+
+testInIFrame('../../resources/blank.html', function(doc) {
+ doc.body.innerHTML = '<div id="x-a-parent"><x-a id="x-a"></x-a></div>';
+ var proto = newHTMLElementPrototype();
+ doc.registerElement('x-a', {prototype: proto});
+ var div = doc.querySelector('#x-a-parent');
+ doc.body.removeChild(div);
+ assert_equals(proto.detachedCallbackCalledCounter, 1, 'Callback detached should be ' +
+ 'called if custom element is removed from the document with browsing context');
+}, 'Test detached callback is called if ancestor node of custom element ' +
+ 'is removed by method removeChild() from document with browsing context');
+
+
+testInIFrame('../../resources/x-element.html', function(doc) {
+ var proto = newHTMLElementPrototype();
+ doc.registerElement('x-element', {prototype: proto});
+ var customElement = doc.querySelector('#x-element');
+ var div = doc.createElement('div');
+ doc.body.replaceChild(div, customElement);
+ assert_equals(proto.detachedCallbackCalledCounter, 1, 'Callback detached should be ' +
+ 'called if custom element is removed from the document with browsing context');
+}, 'Test detached callback is called if custom element is removed by method replaceChild() ' +
+ 'from document with browsing context');
+
+
+testInIFrame('../../resources/blank.html', function(doc) {
+ var proto = newHTMLElementPrototype();
+ doc.registerElement('x-b', {prototype: proto});
+ doc.body.innerHTML = '<div id="x-b-parent"><x-b id="x-b"></x-b></div>';
+ var parent = doc.querySelector('#x-b-parent');
+ var replacement = doc.createElement('div');
+ doc.body.replaceChild(replacement, parent);
+ assert_equals(proto.detachedCallbackCalledCounter, 1, 'Callback detached should be ' +
+ 'called if custom element is removed from the document with browsing context');
+}, 'Test detached callback is called if ancestor node of custom element ' +
+ 'is removed by method replaceChild() from document with browsing context');
+
+
+testInIFrame('../../resources/x-element.html', function(doc) {
+ var proto = newHTMLElementPrototype();
+ doc.registerElement('x-element', {prototype: proto});
+ doc.body.innerHTML = '';
+ assert_equals(proto.detachedCallbackCalledCounter, 1, 'Callback detached should be ' +
+ 'called if custom element is removed from the document with browsing context');
+}, 'Test detached callback is called after changing custom element direct parent ' +
+ 'innerHTML property in the document with browsing context');
+
+
+testInIFrame('../../resources/blank.html', function(doc) {
+ doc.body.innerHTML = '<div><x-c></x-c></div>';
+ var proto = newHTMLElementPrototype();
+ doc.registerElement('x-c', {prototype: proto});
+ doc.body.innerHTML = '';
+ assert_equals(proto.detachedCallbackCalledCounter, 1, 'Callback detached should be ' +
+ 'called if custom element is removed from the document with browsing context');
+}, 'Test detached callback is called after changing custom element ancestor ' +
+ 'innerHTML property in the document with browsing context');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/changing-is-attribute.html b/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/changing-is-attribute.html
new file mode 100644
index 00000000000..91ab563d4d2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/changing-is-attribute.html
@@ -0,0 +1,159 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Changing IS attribute of the custom element must not affect this element's custom element type, after element is instantiated</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<meta name="assert" content="After a custom element is instantiated, changing the value of the IS attribute must not affect this element's custom element type">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#instantiating-custom-elements">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ var doc = newHTMLDocument();
+ var GeneratedConstructor = doc.registerElement('x-a');
+ var customElement = new GeneratedConstructor();
+ doc.registerElement('x-b');
+ customElement.setAttribute('is', 'x-b');
+ assert_equals(Object.getPrototypeOf(customElement), GeneratedConstructor.prototype,
+ 'Custom element type should be x-a');
+}, 'Test custom element type, after assigning IS attribute value. ' +
+ 'Element is created by constructor');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var GeneratedConstructor = doc.registerElement('x-c');
+ doc.registerElement('x-d');
+ doc.body.innerHTML = '<x-c id="x-c"></x-c>';
+ var customElement = doc.querySelector('#x-c');
+ customElement.setAttribute('is', 'x-d');
+ assert_equals(Object.getPrototypeOf(customElement), GeneratedConstructor.prototype,
+ 'Custom element type should be x-c');
+}, 'Test custom element type, after assigning IS attribute value. ' +
+ 'Element is created via innerHTML property');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ doc.body.innerHTML = '<x-e id="x-e"></x-e>';
+ var customElement = doc.querySelector('#x-e');
+ customElement.setAttribute('is', 'x-f');
+ var GeneratedConstructor = doc.registerElement('x-e');
+ doc.registerElement('x-f');
+ assert_equals(Object.getPrototypeOf(customElement), GeneratedConstructor.prototype,
+ 'Custom element type should be x-e');
+}, 'Test custom element type, after assigning IS attribute value to unresolved element. ' +
+ 'Element is created via innerHTML property');
+
+
+testInIFrame('../resources/x-element.html', function(doc) {
+ var GeneratedConstructor = doc.registerElement('x-element');
+ doc.registerElement('y-element');
+ var customElement = doc.querySelector('#x-element');
+ customElement.setAttribute('is', 'y-element');
+ assert_equals(Object.getPrototypeOf(customElement), GeneratedConstructor.prototype,
+ 'Custom element type should be x-element');
+}, 'Test custom element type, after assigning IS attribute value. ' +
+ 'Element is defined in loaded HTML document');
+
+
+testInIFrame('../resources/x-element.html', function(doc) {
+ var customElement = doc.querySelector('#x-element');
+ customElement.setAttribute('is', 'y-element');
+ var GeneratedConstructor = doc.registerElement('x-element');
+ doc.registerElement('y-element');
+ assert_equals(Object.getPrototypeOf(customElement), GeneratedConstructor.prototype,
+ 'Custom element type should be x-element');
+}, 'Test custom element type, after assigning IS attribute value to unresolved element. ' +
+ 'Element is defined in loaded HTML document');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ HTML5_ELEMENTS.forEach(function(tagName) {
+ if (HTML5_DOCUMENT_ELEMENTS.indexOf(tagName) !== -1) {
+ return;
+ }
+ var name = 'y-' + tagName;
+ var obj = doc.createElement(tagName);
+ var proto = Object.create(obj.constructor.prototype);
+ var GeneratedConstructor = doc.registerElement(name, {prototype: proto, extends: tagName});
+ if (HTML5_TABLE_ELEMENTS.indexOf(tagName) !== -1) {
+ doc.body.innerHTML =
+ '<table>' +
+ '<' + tagName + ' id="custom-element" is="' + name + '"></' + tagName + '>' +
+ '</table>';
+ } else {
+ doc.body.innerHTML =
+ '<' + tagName + ' id="custom-element" is="' + name + '"></' + tagName + '>';
+ }
+ var customElement = doc.querySelector('#custom-element');
+ assert_equals(Object.getPrototypeOf(customElement), GeneratedConstructor.prototype,
+ 'Custom element type should be '+ name);
+
+ var name2 = 'y-a-' + tagName;
+ doc.registerElement(name2);
+ customElement.setAttribute('is', name2);
+ assert_equals(Object.getPrototypeOf(customElement), GeneratedConstructor.prototype,
+ 'Custom element type should be ' + name);
+ });
+}, 'Test custom element type after changing IS attribute value. ' +
+ 'Element is HTML5 element with IS attribute referring to custom element type');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var localName = 'z-a';
+ var obj = doc.createElement('a');
+ var proto = Object.create(obj.constructor.prototype);
+ var GeneratedConstructor = doc.registerElement(localName, {prototype: proto, extends: 'a'});
+ doc.body.innerHTML = '<a id="custom-element" is="' + localName + '"></a>';
+ var customElement = doc.querySelector('#custom-element');
+
+ HTML5_ELEMENTS.forEach(function(tagName) {
+ var name = 'z-a-' + tagName;
+ var htmlElement = doc.createElement(tagName);
+ var htmlElementProto = Object.create(htmlElement.constructor.prototype);
+ doc.registerElement(name, {prototype: htmlElementProto, extends: tagName});
+ customElement.setAttribute('is', name);
+ assert_equals(Object.getPrototypeOf(customElement), GeneratedConstructor.prototype,
+ 'Custom element type should be ' + localName);
+ });
+}, 'Test custom element type after changing IS attribute value several times. ' +
+ 'Element is HTML5 element with IS attribute referring to custom element type');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var GeneratedConstructor = doc.registerElement('x-g');
+ doc.registerElement('x-h');
+ doc.body.innerHTML = '<x-g id="x-g" is="x-h"></x-g>';
+ var customElement = doc.querySelector('#x-g');
+ customElement.removeAttribute('is');
+ assert_equals(Object.getPrototypeOf(customElement), GeneratedConstructor.prototype,
+ 'Custom element type should be x-g');
+}, 'Test custom element type, after removing IS attribute value. ' +
+ 'Element is created via innerHTML property');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var obj = doc.createElement('a');
+ var proto = Object.create(obj.constructor.prototype);
+ var GeneratedConstructor = doc.registerElement('x-i', {prototype: proto, extends: 'a'});
+ doc.body.innerHTML = '<a id="x-i" is="x-i"></a>';
+ var customElement = doc.querySelector('#x-i');
+ customElement.removeAttribute('is');
+ assert_equals(Object.getPrototypeOf(customElement), GeneratedConstructor.prototype,
+ 'Custom element type should be x-i');
+}, 'Test custom element type, after removing IS attribute value. ' +
+ 'Element is HTML5 element with IS attribute referring to custom element type');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/custom-element-constructor-is-attribute.html b/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/custom-element-constructor-is-attribute.html
new file mode 100644
index 00000000000..aef9135b187
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/custom-element-constructor-is-attribute.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Custom element constructor sets value of IS attribute to custom element type, if it is not equal to name</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="assert" content="If TYPE is not the same as NAME, set the value of ELEMENT's IS attribute to TYPE">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#instantiating-custom-elements">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ var doc = newHTMLDocument();
+ HTML5_ELEMENTS.forEach(function(tagName) {
+ if (HTML5_DOCUMENT_ELEMENTS.indexOf(tagName) !== -1) {
+ return;
+ }
+ var obj = doc.createElement(tagName);
+ var name = 'x-a-' + tagName;
+ var proto = Object.create(obj.constructor.prototype);
+ var GeneratedConstructor = doc.registerElement(name, {prototype: proto, extends: tagName});
+ var customElement = new GeneratedConstructor();
+
+ assert_equals(customElement.getAttribute('is'), name,
+ 'Value of the IS attribute should be set to type');
+ });
+}, 'Test that the constructor of a type extension sets the IS attribute value to the type');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ HTML5_ELEMENTS.forEach(function(tagName) {
+ if (HTML5_DOCUMENT_ELEMENTS.indexOf(tagName) !== -1) {
+ return;
+ }
+ var name = 'x-b-' + tagName;
+ var GeneratedConstructor = doc.registerElement(name);
+ var customElement = new GeneratedConstructor();
+
+ assert_false(customElement.hasAttribute('is'),
+ 'IS attribute should not present if local name is the same as type');
+ });
+}, 'Test that the constructor of a custom element does not set the IS attribute if local name is the same as type');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/custom-element-constructor-local-name.html b/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/custom-element-constructor-local-name.html
new file mode 100644
index 00000000000..6929c36df68
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/custom-element-constructor-local-name.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Custom element constructor sets local name to the name from custom element definition</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<meta name="assert" content="Set ELEMENT's local name to NAME">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#instantiating-custom-elements">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ var doc = newHTMLDocument();
+ var GeneratedConstructor = doc.registerElement('x-a');
+ var customElement = new GeneratedConstructor();
+ assert_equals(customElement.localName, 'x-a',
+ 'Custom element local name should be equal to the name in custom element definition');
+}, 'Custom element constructor sets local name to the name from custom element definition');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ HTML5_ELEMENTS.forEach(function(tagName) {
+ var obj = doc.createElement(tagName);
+ var name = 'x-b-' + tagName;
+ var proto = Object.create(obj.constructor.prototype);
+ var GeneratedConstructor = doc.registerElement(name, {
+ prototype: proto,
+ extends: tagName
+ });
+ var customElement = new GeneratedConstructor();
+
+ assert_equals(customElement.localName, tagName,
+ 'Custom element local name should be equal to the name in custom element definition');
+ });
+}, 'Custom element constructor sets local name to the name from custom element definition. ' +
+ 'Test constructor of extended HTML element');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/custom-element-constructor-namespace.html b/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/custom-element-constructor-namespace.html
new file mode 100644
index 00000000000..c0de2b1edb9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/custom-element-constructor-namespace.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Custom element constructor sets local namespace to the namespace from custom element definition</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="assert" content="Custom element constructor sets custom element namespace to the namespace in custom element definition">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#instantiating-custom-elements">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ var doc = newHTMLDocument();
+ var GeneratedConstructor = doc.registerElement('x-a');
+ var customElement = new GeneratedConstructor();
+ assert_equals(customElement.namespaceURI, HTML_NAMESPACE,
+ 'Custom element namespace should be equal to namespace in custom element definition');
+}, 'Custom element constructor sets namespace to the namespace from custom element definition');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ HTML5_ELEMENTS.forEach(function(tagName) {
+ var obj = doc.createElement(tagName);
+ var name = 'x-b-' + tagName;
+ var proto = Object.create(obj.constructor.prototype);
+ var GeneratedConstructor = doc.registerElement(name, {
+ prototype: proto,
+ extends: tagName
+ });
+ var customElement = new GeneratedConstructor();
+
+ assert_equals(customElement.namespaceURI, HTML_NAMESPACE,
+ 'Custom element namespace should be equal to namespace in custom element definition');
+ });
+}, 'Custom element constructor sets namespace to the namespace from custom element definition. ' +
+ 'Test constructor of extended HTML element');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/custom-element-constructor-node-document.html b/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/custom-element-constructor-node-document.html
new file mode 100644
index 00000000000..b56c1a08fa3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/custom-element-constructor-node-document.html
@@ -0,0 +1,101 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Custom element constructor sets owner document to the document, where custom element type is registered</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="assert" content="Custom element constructor sets custom element node document to the document, where custom element type is registered">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#instantiating-custom-elements">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ var doc = newHTMLDocument();
+ var GeneratedConstructor = doc.registerElement('x-a');
+ var customElement = new GeneratedConstructor();
+ assert_equals(customElement.ownerDocument, doc,
+ 'Custom element owner document should be the document, where custom element ' +
+ 'type is registered');
+}, 'Custom element constructor sets owner document to the document, where custom element ' +
+ 'type is registered');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ HTML5_ELEMENTS.forEach(function(tagName) {
+ var obj = doc.createElement(tagName);
+ var name = 'x-b-' + tagName;
+ var proto = Object.create(obj.constructor.prototype);
+ var GeneratedConstructor = doc.registerElement(name, {
+ prototype: proto,
+ extends: tagName
+ });
+ var customElement = new GeneratedConstructor();
+
+ assert_equals(customElement.ownerDocument, doc,
+ 'Custom element owner document should be the document, where custom element ' +
+ 'type is registered');
+ });
+}, 'Custom element constructor sets owner document to the document, where custom element ' +
+ 'type is registered. Test constructor of extended HTML element');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var sharedRegistryDocument = doc.implementation.createHTMLDocument('Document 2');
+
+ var name = 'x-c';
+ var GeneratedConstructor = doc.registerElement(name);
+ var customElement = new GeneratedConstructor();
+ assert_equals(customElement.ownerDocument, doc,
+ 'Custom element owner document should be the document, where custom element ' +
+ 'type is registered');
+
+ var name2 = 'x-d';
+ var GeneratedConstructor2 = sharedRegistryDocument.registerElement(name2);
+ var customElement2 = new GeneratedConstructor2();
+ assert_equals(customElement2.ownerDocument, sharedRegistryDocument,
+ 'Custom element owner document should be the document, where custom element ' +
+ 'type is registered');
+}, 'Custom element constructor sets owner document to the document, where custom element ' +
+ 'type is registered. Test different documents with shared registry');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var sharedRegistryDocument = doc.implementation.createHTMLDocument('Document 2');
+ HTML5_ELEMENTS.forEach(function(tagName) {
+ var obj = doc.createElement(tagName);
+ var name = 'x-e-' + tagName;
+ var proto = Object.create(obj.constructor.prototype);
+ var GeneratedConstructor = doc.registerElement(name, {
+ prototype: proto,
+ extends: tagName
+ });
+ var customElement = new GeneratedConstructor();
+ assert_equals(customElement.ownerDocument, doc,
+ 'Custom element owner document should be the document, where custom element ' +
+ 'type is registered');
+
+ var obj2 = sharedRegistryDocument.createElement(tagName);
+ var name2 = 'x-f-' + tagName;
+ var proto2 = Object.create(obj2.constructor.prototype);
+ var GeneratedConstructor2 = sharedRegistryDocument.registerElement(name2, {
+ prototype: proto2,
+ extends: tagName
+ });
+ var customElement2 = new GeneratedConstructor2();
+ assert_equals(customElement2.ownerDocument, sharedRegistryDocument,
+ 'Custom element owner document should be the document, where custom element ' +
+ 'type is registered');
+ });
+}, 'Custom element constructor sets owner document to the document, where custom element ' +
+ 'type is registered. Test constructor of extended HTML element for different documents ' +
+ 'with shared registry');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/custom-element-constructor-prototype.html b/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/custom-element-constructor-prototype.html
new file mode 100644
index 00000000000..f5e14d490d6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/custom-element-constructor-prototype.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Custom element constructor prototype is the prototype object specified in element definition</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="assert" content="Custom element constructor prototype is the prototype object specified in element definition">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#registering-custom-elements">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = Object.create(SVGElement.prototype);
+ var GeneratedConstructor = doc.registerElement('x-a', {
+ prototype: proto,
+ extends: 'p'
+ });
+ assert_true(GeneratedConstructor.prototype === proto,
+ 'Custom element constructor must have the prototype specified in registerElement()');
+}, 'If custom element type is registered with prototype, the custom element ' +
+ 'constructor should have the prototype specified in registerElement() call');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/custom-element-prototype.html b/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/custom-element-prototype.html
new file mode 100644
index 00000000000..ab0fd8589c3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/custom-element-prototype.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Custom element prototype is the prototype object specified in element definition</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="assert" content="Custom element prototype is the prototype object specified in element definition">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#instantiating-custom-elements">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = Object.create(SVGElement.prototype);
+ var GeneratedConstructor = doc.registerElement('x-a', {
+ prototype: proto,
+ extends: 'p'
+ });
+ var customElement = new GeneratedConstructor();
+
+ assert_true(Object.getPrototypeOf(customElement) === proto,
+ 'Custom element instance must have the prototype specified in registerElement()');
+}, 'If custom element type is registered with prototype, the custom element ' +
+ 'instance should have the prototype specified in registerElement() call');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/custom-element-type-is-attribute.html b/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/custom-element-type-is-attribute.html
new file mode 100644
index 00000000000..e16d84c6726
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/custom-element-type-is-attribute.html
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Instantiation of custom element: custom element type is given as the value of the IS attribute</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<meta name="assert" content="The custom element type is given to a custom element at the time of its instantation in one of the two ways: ... 2. As the value of the IS attribute of the custom element.">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#instantiating-custom-elements">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ var doc = newHTMLDocument();
+ HTML5_ELEMENTS.forEach(function(tagName) {
+ if (HTML5_DOCUMENT_ELEMENTS.indexOf(tagName) !== -1) {
+ return;
+ }
+ var obj = doc.createElement(tagName);
+ var name = 'x-a-' + tagName;
+ var proto = Object.create(obj.constructor.prototype);
+ var GeneratedConstructor = doc.registerElement(name, {prototype: proto, extends: tagName});
+
+ if (HTML5_TABLE_ELEMENTS.indexOf(tagName) !== -1) {
+ doc.body.innerHTML =
+ '<table>' +
+ '<' + tagName + ' id="custom-element" is="' + name + '"></' + tagName + '>' +
+ '</table>';
+ } else {
+ doc.body.innerHTML =
+ '<' + tagName + ' id="custom-element" is="' + name + '"></' + tagName + '>';
+ }
+ var customElement = doc.querySelector('#custom-element');
+ assert_equals(Object.getPrototypeOf(customElement), GeneratedConstructor.prototype,
+ 'Custom element type should be the type, specified as value of IS attribute');
+ });
+}, 'Instantiation of custom element: custom element type is given as the value of ' +
+ 'the IS attribute');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ HTML5_ELEMENTS.forEach(function(tagName) {
+ if (HTML5_DOCUMENT_ELEMENTS.indexOf(tagName) !== -1) {
+ return;
+ }
+ var obj = doc.createElement(tagName);
+ var name = 'x-b-' + tagName;
+ if (HTML5_TABLE_ELEMENTS.indexOf(tagName) !== -1) {
+ doc.body.innerHTML =
+ '<table>' +
+ '<' + tagName + ' id="custom-element" is="' + name + '"></' + tagName + '>' +
+ '</table>';
+ } else {
+ doc.body.innerHTML =
+ '<' + tagName + ' id="custom-element" is="' + name + '"></' + tagName + '>';
+ }
+ var proto = Object.create(obj.constructor.prototype);
+ var GeneratedConstructor = doc.registerElement(name, {prototype: proto, extends: tagName});
+
+ var customElement = doc.querySelector('#custom-element');
+
+ assert_equals(Object.getPrototypeOf(customElement), GeneratedConstructor.prototype,
+ 'Custom element type should be the type, specified as value of IS attribute');
+ });
+}, 'Instantiation of custom element: custom element type is given as the value ' +
+ 'of the IS attribute. Custom element is unresolved at first');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/custom-element-type-local-name-and-is-attribute.html b/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/custom-element-type-local-name-and-is-attribute.html
new file mode 100644
index 00000000000..9751ec36159
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/custom-element-type-local-name-and-is-attribute.html
@@ -0,0 +1,102 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Instantiation of custom element: the custom tag must win over the type extension</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<meta name="assert" content="If both types of custom element types are provided at the time of element's instantiation, the custom tag must win over the type extension">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#instantiating-custom-elements">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ var doc = newHTMLDocument();
+ var GeneratedConstructor = doc.registerElement('x-a');
+ doc.registerElement('x-b');
+ doc.body.innerHTML = '<x-a id="x-a" is="x-b"></x-a>';
+ var customElement = doc.querySelector('#x-a');
+
+ assert_equals(Object.getPrototypeOf(customElement), GeneratedConstructor.prototype,
+ 'Custom element type should be the type, specified in the local name of the element');
+}, 'Custom element type must be taken from the local name of the element even ' +
+ 'if IS attribute provided.');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ doc.registerElement('x-d');
+ doc.body.innerHTML = '<x-c id="x-c" is="x-d"></x-c>';
+ var customElement = doc.querySelector('#x-c');
+
+ var GeneratedConstructor = doc.registerElement('x-c');
+ assert_equals(Object.getPrototypeOf(customElement), GeneratedConstructor.prototype,
+ 'Custom element type should be the type, specified in the local name of the element');
+}, 'Custom element type must be taken from the local name of the element even ' +
+ 'if IS attribute provided. Custom element is unresolved at first');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var GeneratedConstructor = doc.registerElement('x-f');
+ doc.body.innerHTML = '<x-f id="x-f" is="x-e"></x-f>';
+ var customElement = doc.querySelector('#x-f');
+ assert_equals(Object.getPrototypeOf(customElement), GeneratedConstructor.prototype,
+ 'Custom element type should be the type, specified in local name of the element');
+
+ doc.registerElement('x-e');
+ assert_equals(Object.getPrototypeOf(customElement), GeneratedConstructor.prototype,
+ 'Custom element type should be the type, specified in local name of the element');
+}, 'Custom element type must be taken from the local name of the element even if IS ' +
+ 'attribute provided. There\'s no definition for the value of IS attribute at first');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var GeneratedConstructor = doc.registerElement('x-element');
+ HTML5_ELEMENTS.forEach(function(tagName) {
+ var obj = doc.createElement(tagName);
+ var name = 'x-d-' + tagName;
+ doc.registerElement(name, {
+ prototype: Object.create(obj.constructor.prototype),
+ extends: tagName
+ });
+ doc.body.innerHTML = '<x-element id="x-element" is="' + name + '"></x-element>';
+ var customElement = doc.querySelector('#x-element');
+ assert_equals(Object.getPrototypeOf(customElement), GeneratedConstructor.prototype,
+ 'Custom element type should be the local name of the custom element');
+ });
+}, 'Custom element type must be taken from the local name of the element even ' +
+ 'if IS attribute provided. IS attribute refers to another custom element type, ' +
+ 'which extends HTML5 elements');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ doc.registerElement('y-element');
+
+ HTML5_ELEMENTS.forEach(function(tagName) {
+ var obj = doc.createElement(tagName);
+ var name = 'x-e-' + tagName;
+ var id = 'x-e-' + tagName;
+ doc.registerElement(name, {
+ prototype: Object.create(obj.constructor.prototype),
+ extends: tagName
+ });
+ doc.body.innerHTML = '<' + name + ' id="' + id + '" is="y-element"></' + name + '>';
+ var customElement = doc.querySelector('#' + id);
+ // We have <x-e-a is='y-element'>. Custom element type for this will be
+ // HTMLElement, not x-e-a (for x-e-a there should be <a is='x-e-a'>...)
+ assert_class_string(customElement, 'HTMLElement',
+ 'Custom element type should be HTMLElement');
+ });
+}, 'Custom element type must be taken from the local name of the custom element even ' +
+ 'if IS attribute provided. The element extends HTML5 elements, IS attribute refers ' +
+ 'to another custom element type.');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/custom-element-type-local-name.html b/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/custom-element-type-local-name.html
new file mode 100644
index 00000000000..96873132acf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/custom-element-type-local-name.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Instantiation of custom element: custom element type is given via the local name of the custom element</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<meta name="assert" content="The custom element type is given to a custom element at the time of its instantation in one of the two ways: 1. As the local name of the custom element.">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#instantiating-custom-elements">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ var doc = newHTMLDocument();
+ var GeneratedConstructor = doc.registerElement('x-a');
+ doc.body.innerHTML = '<x-a id="x-a"></x-a>';
+ var customElement = doc.querySelector('#x-a');
+ assert_equals(Object.getPrototypeOf(customElement), GeneratedConstructor.prototype,
+ 'Custom element type should be the type, specified by the local name of ' +
+ 'the custom element');
+}, 'Test custom element type, which is given via the local name of the custom element. ' +
+ 'Custom element created via innerHTML property');
+
+
+testInIFrame('../resources/x-element.html', function(doc) {
+ var GeneratedConstructor = doc.registerElement('x-element');
+ var xelement = doc.querySelector('#x-element');
+ assert_equals(Object.getPrototypeOf(xelement), GeneratedConstructor.prototype,
+ 'Custom element type should be the type, specified by the local name of ' +
+ 'the custom element');
+}, 'Test custom element type, which is given via the local name of the custom element. ' +
+ 'Custom element is defined in loaded HTML document');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/extensions-to-document-interface/create-element-interface-type-is-a-local-name.html b/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/extensions-to-document-interface/create-element-interface-type-is-a-local-name.html
new file mode 100644
index 00000000000..306cfd34ae7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/extensions-to-document-interface/create-element-interface-type-is-a-local-name.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Document.createElement() and Document.createElementNS() create custom element of type, specified by localName argument</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="assert" content="If an element definition with matching localName, namespace, and TYPE is not registered with token's document, set TYPE to localName">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#extensions-to-document-interface-to-instantiate">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ var doc = newHTMLDocument();
+ var name1 = 'x-a';
+ var name2 = 'x-b';
+ var GeneratedConstructor = doc.registerElement(name1);
+ var customElement = doc.createElement(name1, name2);
+
+ assert_equals(Object.getPrototypeOf(customElement), GeneratedConstructor.prototype,
+ 'Custom element type should be the local name of the custom element');
+}, 'Test Document.createElement() creates custom element of type, ' +
+ 'specified by localName argument, if an element definition with matching localName, ' +
+ 'namespace, and type is not registered');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var name1 = 'x-c';
+ var name2 = 'x-d';
+ var GeneratedConstructor = doc.registerElement(name1);
+ var customElement = doc.createElementNS(HTML_NAMESPACE, name1, name2);
+
+ assert_equals(Object.getPrototypeOf(customElement), GeneratedConstructor.prototype,
+ 'Custom element type should be the local name of the custom element');
+}, 'Test Document.createElementNS() creates custom element of type, ' +
+ 'specified by localName argument, if an element definition with matching ' +
+ 'localName, namespace, and type is not registered');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/extensions-to-document-interface/create-element-interface-type-is-a-type-extension.html b/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/extensions-to-document-interface/create-element-interface-type-is-a-type-extension.html
new file mode 100644
index 00000000000..1aefe3225ea
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/extensions-to-document-interface/create-element-interface-type-is-a-type-extension.html
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Document.createElement() and Document.createElementNS() create custom element of type, specified by typeExtension argument</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="assert" content="If an element definition with matching localName, namespace, and TYPE is registered then typeExtension is a TYPE">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#extensions-to-document-interface-to-instantiate">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ var doc = newHTMLDocument();
+ var name1 = 'x-a';
+ var GeneratedConstructor1 = doc.registerElement(name1);
+ var name2 = 'x-b';
+ var GeneratedConstructor2 = doc.registerElement(name2);
+ var customElement = doc.createElement(name1, name2);
+
+ assert_equals(Object.getPrototypeOf(customElement), GeneratedConstructor2.prototype,
+ 'Custom element type should be the type extension of the custom element');
+}, 'Test Document.createElement() creates custom element of type, ' +
+ 'specified by typeExtension argument');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var name1 = 'x-c';
+ var GeneratedConstructor1 = doc.registerElement(name1);
+ var name2 = 'x-d';
+ var GeneratedConstructor2 = doc.registerElement(name2);
+ var customElement = doc.createElementNS(HTML_NAMESPACE, name1, name2);
+
+ assert_equals(Object.getPrototypeOf(customElement), GeneratedConstructor2.prototype,
+ 'Custom element type should be the type extension of the custom element');
+}, 'Test Document.createElementNS() creates custom element of type, ' +
+ 'specified by typeExtension argument');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var name1 = 'x-e';
+ var name2 = 'x-f';
+ var GeneratedConstructor2 = doc.registerElement(name2);
+ var customElement = doc.createElement(name1, name2);
+
+ assert_equals(Object.getPrototypeOf(customElement), GeneratedConstructor2.prototype,
+ 'Custom element type should be the type extension of the custom element');
+}, 'Test Document.createElement() creates custom element of type, ' +
+ 'specified by typeExtension argument. Definition for localName is absent');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var name1 = 'x-g';
+ var name2 = 'x-h';
+ var GeneratedConstructor2 = doc.registerElement(name2);
+ var customElement = doc.createElementNS(HTML_NAMESPACE, name1, name2);
+
+ assert_equals(Object.getPrototypeOf(customElement), GeneratedConstructor2.prototype,
+ 'Custom element type should be the type extension of the custom element');
+}, 'Test Document.createElementNS() creates custom element of type, ' +
+ 'specified by typeExtension argument. Definition for localName is absent');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/extensions-to-document-interface/create-element-is-attribute.html b/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/extensions-to-document-interface/create-element-is-attribute.html
new file mode 100644
index 00000000000..bcb1bd04749
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/extensions-to-document-interface/create-element-is-attribute.html
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Document.createElement() and Document.createElementNS() set IS attribute to type</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="assert" content="If TYPE is not the same as localName, set the value of ELEMENT's IS attribute to TYPE">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#extensions-to-document-interface-to-instantiate">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ var doc = newHTMLDocument();
+ HTML5_ELEMENTS.forEach(function(tagName) {
+ var obj = doc.createElement(tagName);
+ var name = 'x-a-' + tagName;
+ var proto = Object.create(obj.constructor.prototype);
+ doc.registerElement(name, {prototype: proto, extends: tagName});
+ var customElement = doc.createElement(tagName, name);
+ assert_equals(customElement.getAttribute('is'), name,
+ 'Value of the IS attribute should be set to type by Document.createElement()');
+ });
+}, 'Test Document.createElement() sets the element\'s IS attribute value to type, ' +
+ 'if type is not the same as localName');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ HTML5_ELEMENTS.forEach(function(tagName) {
+ var name = 'x-b-' + tagName;
+ var customElement = doc.createElement(tagName, name);
+ assert_equals(customElement.getAttribute('is'), name,
+ 'Value of the IS attribute should be set to type by Document.createElement()');
+ });
+}, 'Test Document.createElement() sets the element\'s IS attribute value to type, ' +
+ 'if type is not the same as localName and an element definition with matching ' +
+ 'localName, namespace, and type is not registered');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ HTML5_ELEMENTS.forEach(function(tagName) {
+ var obj = doc.createElement(tagName);
+ var name = 'x-c-' + tagName;
+ var proto = Object.create(obj.constructor.prototype);
+ doc.registerElement(name, {prototype: proto, extends: tagName});
+ var customElement = doc.createElementNS(HTML_NAMESPACE, tagName, name);
+ assert_equals(customElement.getAttribute('is'), name,
+ 'Value of the IS attribute should be set to type by Document.createElementNS()');
+ });
+}, 'Test Document.createElementNS() sets the element\'s IS attribute value to type, ' +
+ 'if type is not the same as localName');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ HTML5_ELEMENTS.forEach(function(tagName) {
+ var name = 'x-d-' + tagName;
+ var customElement = doc.createElementNS(HTML_NAMESPACE, tagName, name);
+ assert_equals(customElement.getAttribute('is'), name,
+ 'Value of the IS attribute should be set to type by Document.createElementNS()');
+ });
+}, 'Test Document.createElementNS() sets the element\'s IS attribute value to type, ' +
+ 'if type is not the same as localNameand and an element definition with matching ' +
+ 'localName, namespace, and type is not registered ');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/extensions-to-document-interface/create-element-namespace.html b/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/extensions-to-document-interface/create-element-namespace.html
new file mode 100644
index 00000000000..2f58b0d3d7a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/extensions-to-document-interface/create-element-namespace.html
@@ -0,0 +1,69 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Document.createElement() sets custom element namespace to HTML Namespace</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="assert" content="Namespace for createElement is HTML Namespace">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#extensions-to-document-interface-to-instantiate">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ var doc = newHTMLDocument();
+ var name = 'x-a';
+ doc.registerElement(name);
+ var customElement = doc.createElement(name);
+ assert_equals(customElement.namespaceURI, HTML_NAMESPACE,
+ 'Custom element namespace should be HTML Namespace');
+}, 'Test Document.createElement() sets custom element namespace to HTML Namespace');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var name = 'x-b';
+ var customElement = doc.createElement(name);
+ assert_equals(customElement.namespaceURI, HTML_NAMESPACE,
+ 'Custom element namespace should be HTML Namespace');
+}, 'Test Document.createElement() sets custom element namespace to HTML Namespace ' +
+ 'and an element definition with matching localName, namespace, and type is not registered');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ HTML5_ELEMENTS.forEach(function(tagName) {
+ var obj = doc.createElement(tagName);
+ var name = 'x-c-' + tagName;
+ var proto = Object.create(obj.constructor.prototype);
+ doc.registerElement(name, {
+ prototype: Object.create(proto),
+ extends: tagName
+ });
+ var customElement = doc.createElement(tagName, name);
+ assert_equals(customElement.namespaceURI, HTML_NAMESPACE,
+ 'Custom element namespace for the element extending ' + tagName +
+ ' should be HTML Namespace');
+ });
+}, 'Document.createElement() sets custom element namespace to HTML Namespace. ' +
+ 'Custom element is extending standard HTML tag');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ HTML5_ELEMENTS.forEach(function(tagName) {
+ var name = 'x-d-' + tagName;
+ var customElement = doc.createElement(tagName, name);
+ assert_equals(customElement.namespaceURI, HTML_NAMESPACE,
+ 'Custom element namespace for the element with tag name ' + tagName +
+ ' and type name ' + name + ' should be HTML Namespace');
+ });
+}, 'Document.createElement() sets custom element namespace to HTML Namespace. ' +
+ 'Document.createElement() is called with standard HTML tag name and ' +
+ 'type without registered custom element of such type');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/extensions-to-document-interface/create-element-type-extension-is-a-type.html b/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/extensions-to-document-interface/create-element-type-extension-is-a-type.html
new file mode 100644
index 00000000000..080639ff292
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/extensions-to-document-interface/create-element-type-extension-is-a-type.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Document.createElement() and Document.createElementNS() create custom element of type, specified by typeExtension argument</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="assert" content="Let TYPE be typeExtension, or localName if typeExtension is not present">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#extensions-to-document-interface-to-instantiate">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ var doc = newHTMLDocument();
+ HTML5_ELEMENTS.forEach(function(tagName) {
+ var obj = doc.createElement(tagName);
+ var name = 'x-a-' + tagName;
+ var proto = Object.create(obj.constructor.prototype);
+ var GeneratedConstructor = doc.registerElement(name, {prototype: proto, extends: tagName});
+ var customElement = doc.createElement(tagName, name);
+
+ assert_equals(Object.getPrototypeOf(customElement), GeneratedConstructor.prototype,
+ 'Custom element type should be ' + name);
+ });
+}, 'Test Document.createElement() creates custom element of type, ' +
+ 'specified by typeExtension argument');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ HTML5_ELEMENTS.forEach(function(tagName) {
+ var obj = doc.createElement(tagName);
+ var name = 'x-b-' + tagName;
+ var proto = Object.create(obj.constructor.prototype);
+ var GeneratedConstructor = doc.registerElement(name, {prototype: proto, extends: tagName});
+ var customElement = doc.createElementNS(HTML_NAMESPACE, tagName, name);
+
+ assert_equals(Object.getPrototypeOf(customElement), GeneratedConstructor.prototype,
+ 'Custom element type should be ' + name);
+ });
+}, 'Test Document.createElementNS() creates custom element of type, ' +
+ 'specified by typeExtension argument');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/extensions-to-document-interface/create-element-type-extension-unresolved.html b/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/extensions-to-document-interface/create-element-type-extension-unresolved.html
new file mode 100644
index 00000000000..9df65fdc39b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/extensions-to-document-interface/create-element-type-extension-unresolved.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Document.createElement() and Document.createElementNS() create custom element of type, specified by localName argument</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="assert" content="If an element definition with matching localName, namespace, and TYPE is not registered with token's document, set TYPE to localName">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#extensions-to-document-interface-to-instantiate">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test (function() {
+ var doc = newHTMLDocument();
+ HTML5_ELEMENTS.forEach(function(tagName) {
+ var obj = doc.createElement(tagName);
+ var name = 'x-a-' + tagName;
+ var proto = Object.create(obj.constructor.prototype);
+ var customElement = doc.createElement(tagName, name);
+ assert_equals(Object.getPrototypeOf(customElement), Object.getPrototypeOf(obj),
+ 'Unregistered custom element type should be a local name');
+
+ var GeneratedConstructor = doc.registerElement(name, {prototype: proto, extends: tagName});
+ assert_equals(Object.getPrototypeOf(customElement), GeneratedConstructor.prototype,
+ 'Registered custom element type should be the type extension');
+ });
+}, 'If typeExtension is unresolved when createElement called then local name is a type');
+
+
+test (function() {
+ var doc = newHTMLDocument();
+ HTML5_ELEMENTS.forEach(function(tagName) {
+ var obj = doc.createElement(tagName);
+ var name = 'x-b-' + tagName;
+ var proto = Object.create(obj.constructor.prototype);
+ var customElement = doc.createElementNS(HTML_NAMESPACE, tagName, name);
+ assert_equals(Object.getPrototypeOf(customElement), Object.getPrototypeOf(obj),
+ 'Custom element type should be a local name');
+
+ var GeneratedConstructor = doc.registerElement(name, {prototype: proto, extends: tagName});
+ assert_equals(Object.getPrototypeOf(customElement), GeneratedConstructor.prototype,
+ 'Custom element type should be the type extension');
+ });
+}, 'If typeExtension is unresolved when createElementNS called then local name is a type');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/extensions-to-document-interface/create-element-type-is-a-local-name.html b/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/extensions-to-document-interface/create-element-type-is-a-local-name.html
new file mode 100644
index 00000000000..1d5097762fa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/extensions-to-document-interface/create-element-type-is-a-local-name.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Document.createElement() and Document.createElementNS() create custom element of type, specified by single localName argument</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="assert" content="Let TYPE be typeExtension, or localName if typeExtension is not present">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#extensions-to-document-interface-to-instantiate">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ var doc = newHTMLDocument();
+ var name = 'x-a';
+ var GeneratedConstructor = doc.registerElement(name);
+ var customElement = doc.createElement(name);
+
+ assert_equals(Object.getPrototypeOf(customElement), GeneratedConstructor.prototype,
+ 'Custom element type should be the local name of the custom element');
+}, 'Test Document.createElement() creates custom element of type, ' +
+ 'specified by single localName argument');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var name = 'x-b';
+ var GeneratedConstructor = doc.registerElement(name);
+ var customElement = doc.createElementNS(HTML_NAMESPACE, name);
+ assert_equals(Object.getPrototypeOf(customElement), GeneratedConstructor.prototype,
+ 'Custom element type should be the local name of the custom element');
+}, 'Test Document.createElementNS() creates custom element of type, ' +
+ 'specified by localName argument. Argument typeExtension is not passed');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/extensions-to-document-interface/created-callback-create-element-ns.html b/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/extensions-to-document-interface/created-callback-create-element-ns.html
new file mode 100644
index 00000000000..7f0bf985f36
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/extensions-to-document-interface/created-callback-create-element-ns.html
@@ -0,0 +1,73 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Document.createElementNS() must enqueue created callback for registered custom element type</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="assert" content="Document.createElementNS() must enqueue created callback for registered custom element type">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#extensions-to-document-interface-to-instantiate">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#types-of-callbacks">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = newHTMLElementPrototype();
+ var name = 'x-a';
+
+ doc.registerElement(name, {prototype: proto});
+ var customElement = doc.createElementNS(HTML_NAMESPACE, name);
+ assert_equals(proto.createdCallbackCalledCounter, 1,
+ 'Callback created should be enqueued by Document.createElementNS()');
+}, 'Test Document.createElementNS() without typeExtension argument enqueues created callback');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = newHTMLElementPrototype();
+ var name = 'x-b';
+
+ doc.registerElement(name, {prototype: proto});
+ var customElement = doc.createElementNS(HTML_NAMESPACE, name, name);
+ assert_equals(proto.createdCallbackCalledCounter, 1,
+ 'Callback created should be enqueued by Document.createElementNS()');
+}, 'Test Document.createElementNS() with typeExtension argument enqueues created callback');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = newHTMLElementPrototype();
+ var name = 'x-c';
+ var customElement = doc.createElementNS(HTML_NAMESPACE, name);
+ assert_equals(proto.createdCallbackCalledCounter, 0,
+ 'Document.createElementNS() should not enqueue created callback ' +
+ 'for unresolved custom element');
+
+ doc.registerElement(name, {prototype: proto});
+ assert_equals(proto.createdCallbackCalledCounter, 1,
+ 'Callback created should be called after custom element is registered');
+}, 'Document.createElementNS() should not enqueue created callback ' +
+ 'for unresolved custom element');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ HTML5_ELEMENTS.forEach(function(tagName) {
+ var obj = doc.createElement(tagName);
+ var name = 'x-d-' + tagName;
+ var proto = newCustomElementPrototype(Object.create(obj.constructor.prototype));
+ doc.registerElement(name, {prototype: proto, extends: tagName});
+ var customElement = doc.createElementNS(HTML_NAMESPACE, tagName, name);
+
+ assert_equals(proto.createdCallbackCalledCounter, 1,
+ 'Callback created should be enqueued by Document.createElementNS()');
+ });
+}, 'Test Document.createElementNS() enqueues created callback for custom elements ' +
+ 'that are extensions of HTML5 elements');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/extensions-to-document-interface/created-callback-create-element.html b/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/extensions-to-document-interface/created-callback-create-element.html
new file mode 100644
index 00000000000..0a557e5f85e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/extensions-to-document-interface/created-callback-create-element.html
@@ -0,0 +1,73 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Document.createElement() must enqueue created callback for registered custom element type</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="assert" content="Document.createElement() must enqueue created callback for registered custom element type">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#extensions-to-document-interface-to-instantiate">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#types-of-callbacks">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = newHTMLElementPrototype();
+ var name = 'x-a';
+
+ doc.registerElement(name, {prototype: proto});
+ var customElement = doc.createElement(name);
+ assert_equals(proto.createdCallbackCalledCounter, 1,
+ 'Callback created should be enqueued by Document.createElement()');
+}, 'Test Document.createElement() without typeExtension argument enqueues created callback');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = newHTMLElementPrototype();
+ var name = 'x-b';
+
+ doc.registerElement(name, {prototype: proto});
+ var customElement = doc.createElement(name, name);
+ assert_equals(proto.createdCallbackCalledCounter, 1,
+ 'Callback created should be enqueued by Document.createElement()');
+}, 'Test Document.createElement() with typeExtension argument enqueues created callback');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = newHTMLElementPrototype();
+ var name = 'x-c';
+ var customElement = doc.createElement(name);
+ assert_equals(proto.createdCallbackCalledCounter, 0,
+ 'Document.createElement() should not enqueue created callback ' +
+ 'for unresolved custom element');
+
+ doc.registerElement(name, {prototype: proto});
+ assert_equals(proto.createdCallbackCalledCounter, 1,
+ 'Callback created should be called after custom element is registered');
+}, 'Document.createElement() should not enqueue created callback ' +
+ 'for unresolved custom element');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ HTML5_ELEMENTS.forEach(function(tagName) {
+ var obj = doc.createElement(tagName);
+ var name = 'x-d-' + tagName;
+ var proto = newCustomElementPrototype(Object.create(obj.constructor.prototype));
+ doc.registerElement(name, {prototype: proto, extends: tagName});
+ var customElement = doc.createElement(tagName, name);
+
+ assert_equals(proto.createdCallbackCalledCounter, 1,
+ 'Callback created should be enqueued by Document.createElement()');
+ });
+}, 'Test Document.createElement() enqueues created callback for custom elements ' +
+ 'that are extensions of HTML5 elements');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/non-configurable-constructor-property.html b/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/non-configurable-constructor-property.html
new file mode 100644
index 00000000000..c4ba0767ff7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/non-configurable-constructor-property.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>If prototype has a non-configurable property named constructor, Document.registerElement() throws NotSupportedError</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="assert" content="If PROTOTYPE has a non-configurable property named constructor, throw a NotSupportedError and stop">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#instantiating-custom-elements">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = Object.create(HTMLElement.prototype);
+ Object.defineProperty(proto, 'constructor', {configurable: false});
+ assert_throws('NotSupportedError', function() {
+ doc.registerElement('x-a', {prototype: proto});
+ }, 'Exception should be thrown in case of attempt to register element ' +
+ 'with a non-configurable property named constructor');
+}, 'Test Document.registerElement() throws NotSupportedError ' +
+ 'if prototype has a non-configurable property named constructor');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = Object.create(HTMLElement.prototype);
+ Object.defineProperty(proto, 'constructor', {configurable: true});
+ try {
+ doc.registerElement('x-b', {prototype: proto});
+ } catch (e) {
+ assert_unreached('Exception should not be thrown in case of attempt to register ' +
+ 'element with a configurable property named constructor');
+ }
+}, 'Test Document.registerElement() accepts prototype with a configurable ' +
+ 'property named constructor without throwing errors');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/prototype-is-interface-prototype-object.html b/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/prototype-is-interface-prototype-object.html
new file mode 100644
index 00000000000..25121c3495b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/prototype-is-interface-prototype-object.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>If prototype is already an interface prototype object, Document.registerElement() throws a NotSupportedError</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="assert" content="If PROTOTYPE is already an interface prototype object for any interface object, throw a NotSupportedError and stop">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#instantiating-custom-elements">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ var doc = newHTMLDocument();
+ HTML5_ELEMENTS.forEach(function(tagName) {
+ var obj = doc.createElement(tagName);
+ var name = 'x-a-' + tagName;
+ assert_throws('NotSupportedError', function() {
+ doc.registerElement(name, {prototype: obj.constructor.prototype});
+ }, 'Exception should be thrown in case of attempt to register element ' +
+ 'if prototype is already an interface prototype object (' + name + ')');
+ });
+}, 'Test Document.registerElement() throws NotSupportedError ' +
+ 'if prototype is already an interface prototype object');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = Object.create(HTMLElement.prototype);
+ doc.registerElement('x-b', {
+ prototype: proto
+ });
+ assert_throws('NotSupportedError', function() {
+ doc.registerElement('x-b', {
+ prototype: proto
+ });
+ }, 'Exception should be thrown if registring custom element type with already used prototype');
+}, 'Test Document.registerElement() throws NotSupportedError ' +
+ 'if prototype is already used for another custom element type');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/unchanged-attribute.html b/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/unchanged-attribute.html
new file mode 100644
index 00000000000..3baa174cb5f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/instantiating-custom-elements/unchanged-attribute.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Custom element's type is immutable.</title>
+<meta name="author" title="Bon-Yong Lee" href="mailto:bylee78@gmail.com">
+<meta name="assert" content="After a custom element is instantiated, changing the value of the is attribute must not affect this element's custom element type.">
+<link rel="help" href="http://w3c.github.io/webcomponents/spec/custom/#instantiating-custom-elements">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script type="text/javascript">
+test(function() {
+ var CustomButton = document.registerElement('custom-button', {
+ prototype: Object.create(HTMLButtonElement.prototype),
+ extends: 'button'
+ });
+ var customButton = document.createElement('button', 'custom-button');
+
+ assert_true(customButton instanceof CustomButton,
+ 'A custom element is of the custom element type after ' +
+ 'instantiation');
+ customButton.setAttribute('is', 'dirty');
+ assert_equals('dirty', customButton.getAttribute('is'),
+ 'An attribute must be changed by method "setAttribute"');
+
+ assert_true(customButton instanceof CustomButton,
+ 'A custom element is of the original custom element type even ' +
+ 'after changing the \'is\' attribute');
+}, 'After a custom element is instantiated, changing the value of the is attribute must not affect this element\'s custom element type.');
+</script>
diff --git a/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/definition-construction-algorithm-default-namespace.html b/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/definition-construction-algorithm-default-namespace.html
new file mode 100644
index 00000000000..02f57d86b1a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/definition-construction-algorithm-default-namespace.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Default namespace is HTML namespace</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="assert" content="Default namespace is HTML namespace">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#registering-custom-elements">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ var doc = newHTMLDocument();
+ var GeneratedConstructor = doc.registerElement('x-a');
+ var customElement = new GeneratedConstructor();
+
+ assert_equals(customElement.namespaceURI, HTML_NAMESPACE,
+ 'Custom element namespace should be HTML namespace');
+}, 'Default namespace is HTML namespace');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ HTML5_ELEMENTS.forEach(function(tagName) {
+ var obj = doc.createElement(tagName);
+ var name = 'x-b-' + tagName;
+ var proto = Object.create(obj.constructor.prototype);
+ var GeneratedConstructor = doc.registerElement(name, {
+ prototype: proto,
+ extends: tagName
+ });
+ var customElement = new GeneratedConstructor();
+
+ assert_equals(customElement.namespaceURI, HTML_NAMESPACE,
+ 'Custom element namespace should be HTML namespace');
+ });
+}, 'Default namespace is HTML namespace. Test constructor of extended HTML element');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/definition-construction-algorithm-duplicate-definition.html b/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/definition-construction-algorithm-duplicate-definition.html
new file mode 100644
index 00000000000..3f718979c06
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/definition-construction-algorithm-duplicate-definition.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Check duplicate definition</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="assert" content="If there already exists a definition with the same TYPE, set ERROR to DuplicateDefinition and stop">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#registering-custom-elements">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ var doc = newHTMLDocument();
+ var name = 'x-a';
+ doc.registerElement(name);
+ assert_throws('NotSupportedError', function() {
+ doc.registerElement(name);
+ }, 'Exception should be thrown if definition with the same type already exists');
+}, 'Check duplicate definition');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var name = 'x-b';
+ doc.registerElement(name);
+ HTML5_ELEMENTS.forEach(function(tagName) {
+ assert_throws('NotSupportedError', function() {
+ doc.registerElement(name, {
+ extends: tagName
+ });
+ }, 'Exception should be thrown if definition with the same type already exists');
+ });
+}, 'Check duplicate definition. Specify constructor');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var name = 'x-c';
+ doc.registerElement(name, {
+ prototype: Object.create(HTMLAnchorElement.prototype),
+ extends: 'a'
+ });
+ HTML5_ELEMENTS.forEach(function(tagName) {
+ assert_throws('NotSupportedError', function() {
+ doc.registerElement(name, {
+ extends: tagName
+ });
+ }, 'Exception should be thrown if definition with the same type already exists');
+ });
+}, 'Check duplicate definition. Test different prototypes and extends');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/definition-construction-algorithm-invalid-type.html b/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/definition-construction-algorithm-invalid-type.html
new file mode 100644
index 00000000000..1718db63985
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/definition-construction-algorithm-invalid-type.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>If TYPE is an invalid custom element type, throw SyntaxError</title>
+<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<meta name="assert" content="If TYPE is an invalid custom element type, set ERROR to InvalidType and stop.">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#registering-custom-elements">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ var doc = newHTMLDocument();
+ assert_throws('SyntaxError', function() { doc.registerElement('1xa2'); },
+ 'Registering invalid custom element type should throw SyntaxError');
+}, 'Registering invalid custom element type should throw SyntaxError');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/definition-construction-algorithm-local-name-lowercased.html b/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/definition-construction-algorithm-local-name-lowercased.html
new file mode 100644
index 00000000000..125e15969aa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/definition-construction-algorithm-local-name-lowercased.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Custom element local name should be converted to lower case if document is an HTML document</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="assert" content="If DOCUMENT is an HTML document, convert NAME to lowercase">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#registering-custom-elements">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ var doc = newHTMLDocument();
+ HTML5_ELEMENTS.forEach(function(tagName) {
+ var obj = doc.createElement(tagName);
+ var name = 'x-a-' + tagName;
+ var proto = Object.create(obj.constructor.prototype);
+ var GeneratedConstructor = doc.registerElement(name, {
+ prototype: proto,
+ extends: tagName.toUpperCase()
+ });
+ var customElement = new GeneratedConstructor();
+
+ assert_equals(customElement.localName, tagName, 'Local name should be lowercased');
+ });
+}, 'Custom element local name should be lowercased if document is an HTML document');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/definition-construction-algorithm-name-is-null.html b/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/definition-construction-algorithm-name-is-null.html
new file mode 100644
index 00000000000..2aa80c64afb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/definition-construction-algorithm-name-is-null.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>If NAME is null then localName must be set to TYPE</title>
+<meta name="author" title="Vasiliy Degtyarev" href="mailto:vasya@unipro.ru">
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="assert" content="If NAME is null then localName must be set to TYPE">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#registering-custom-elements">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ var doc = newHTMLDocument();
+ var name = 'x-a';
+ var proto = Object.create(HTMLElement.prototype);
+ var GeneratedConstructor = doc.registerElement(name, {prototype: proto});
+ var customElement = new GeneratedConstructor();
+
+ assert_equals(customElement.localName, name, 'LocalName should be a type in case of ' +
+ 'attempt to register a custom element and local name is not provided');
+}, 'If NAME is not specified then localName must be set to TYPE');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var name = 'x-b';
+ var proto = Object.create(HTMLElement.prototype);
+ var GeneratedConstructor = doc.registerElement(name, {prototype: proto, extends: null});
+ var customElement = new GeneratedConstructor();
+
+ assert_equals(customElement.localName, name, 'LocalName should be a type in case of ' +
+ 'attempt to register a custom element and name is null');
+}, 'If NAME is null then localName must be set to TYPE');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/definition-construction-algorithm-no-interface-for-name.html b/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/definition-construction-algorithm-no-interface-for-name.html
new file mode 100644
index 00000000000..71c906b36bf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/definition-construction-algorithm-no-interface-for-name.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>If element interface for name doesn't exists then error must be thrown</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="assert" content="If NAME was provided and is not null and if element interface for the name and namespace does not exist or is an interface for a custom element, set ERROR to InvalidName and stop">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#registering-custom-elements">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ var doc = newHTMLDocument();
+ doc.registerElement('x-a');
+ assert_throws('NotSupportedError', function() {
+ doc.registerElement('x-b', {extends: 'x-a'});
+ }, 'Exception should be thrown in case of attempt to register ' +
+ 'a custom element which extends another custom element');
+}, 'Exception should be thrown in case of attempt to register ' +
+ 'a custom element which extends another custom element');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/definition-construction-algorithm-svg-namespace-name-is-null.html b/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/definition-construction-algorithm-svg-namespace-name-is-null.html
new file mode 100644
index 00000000000..5acf176854e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/definition-construction-algorithm-svg-namespace-name-is-null.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>If namespace is SVG namespace and name is null then error must be thrown</title>
+<meta name="author" title="Vasiliy Degtyarev" href="mailto:vasya@unipro.ru">
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="assert" content="If namespace is SVG namespace and name is null then error must be thrown">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#registering-custom-elements">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = Object.create(SVGElement.prototype);
+ assert_throws('NotSupportedError', function() {
+ doc.registerElement('x-svg-a', {prototype: proto});
+ }, 'Exception should be thrown in case of attempt to register ' +
+ 'a custom element with SVG namespace and name is not specified');
+}, 'Error should be thrown if namespace is SVG and local name is not specified');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = Object.create(SVGElement.prototype);
+ assert_throws('NotSupportedError', function() {
+ doc.registerElement('x-svg-b', {prototype: proto, extends: null});
+ }, 'Exception should be thrown in case of attempt to register ' +
+ 'a custom element with SVG namespace and name is null');
+}, 'Error should be thrown if namespace is SVG and local name is null');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/definition-construction-algorithm-svg-namespace.html b/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/definition-construction-algorithm-svg-namespace.html
new file mode 100644
index 00000000000..940db300064
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/definition-construction-algorithm-svg-namespace.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>For SVG prototype namespace is SVG namespace</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="assert" content="If PROTOTYPE's interface inherits from SVGElement, set NAMESPACE to SVG Namespace">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#registering-custom-elements">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ var doc = newHTMLDocument();
+ var proto = Object.create(SVGElement.prototype);
+ var GeneratedConstructor = doc.registerElement('x-a', {prototype: proto, extends: 'a'});
+ var customElement = new GeneratedConstructor();
+
+ assert_equals(customElement.namespaceURI, SVG_NAMESPACE,
+ 'Custom element namespace should be SVG namespace');
+}, 'For SVG prototype namespace is SVG namespace');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/definition-construction-algorithm-type-name-lowercased.html b/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/definition-construction-algorithm-type-name-lowercased.html
new file mode 100644
index 00000000000..9e1bf3e4167
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/definition-construction-algorithm-type-name-lowercased.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Custom element type should be converted to lower case</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="assert" content="Custom element type should be lowercased">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#registering-custom-elements">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ var doc = newHTMLDocument();
+ var GeneratedConstructor = doc.registerElement('X-A');
+ var customElement = new GeneratedConstructor();
+
+ assert_equals(customElement.localName, 'x-a', 'Custom element type should be lowercased');
+}, 'Custom element type should be lowercased. Test constructor');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ HTML5_ELEMENTS.forEach(function(tagName) {
+ var obj = doc.createElement(tagName);
+ var name = 'x-a-' + tagName;
+ var proto = Object.create(obj.constructor.prototype);
+ var GeneratedConstructor = doc.registerElement(name, {
+ prototype: proto,
+ extends: tagName.toUpperCase()
+ });
+ var customElement = new GeneratedConstructor();
+
+ assert_equals(customElement.localName, tagName, 'Local name should be lowercased');
+ });
+}, 'Custom element type should be lowercased. Test constructor of extended HTML element');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/element-registration-algorithm-no-registry.html b/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/element-registration-algorithm-no-registry.html
new file mode 100644
index 00000000000..1dfd7788c9b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/element-registration-algorithm-no-registry.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>If document has no registry NotSupportedError is thrown</title>
+<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<meta name="assert" content="If REGISTRY does not exist, set ERROR to NoRegistry and stop.">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#dfn-element-registration-algorithm">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ var doc = document.implementation.createDocument(null, 'test', null);
+ assert_throws('NotSupportedError', function(){
+ doc.registerElement('x-a');
+ }, 'Registering valid custom element in document ' +
+ 'without registry should throw NotSupportedError');
+
+}, 'Registering valid custom element without options in document ' +
+ 'without registry should throw NotSupportedError');
+
+
+test(function() {
+ var doc = document.implementation.createDocument(null, 'test', null);
+ var proto = Object.create(HTMLElement.prototype);
+
+ assert_throws('NotSupportedError', function(){
+ doc.registerElement('x-b', { prototype: proto, extends: 'a'});
+ }, 'Registering valid custom element in document ' +
+ 'without registry should throw NotSupportedError');
+
+}, 'Registering valid custom element with options in document ' +
+ 'without registry should throw NotSupportedError');
+</script>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/extensions-to-document-interface/custom-element-name.html b/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/extensions-to-document-interface/custom-element-name.html
new file mode 100644
index 00000000000..fd02d63dacf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/extensions-to-document-interface/custom-element-name.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Custom element local name is the lowercased value of the EXTENDS property, supplied to Document.registerElement()</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="assert" content="Custom element local name is the lowercased value of the EXTENDS property">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#extensions-to-document-interface-to-register">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ var doc = newHTMLDocument();
+
+ HTML5_ELEMENTS.forEach(function(tagName) {
+ var name = 'x-' + tagName;
+ var obj = doc.createElement(tagName);
+ var proto = Object.create(obj.constructor.prototype);
+ var GeneratedConstructor = doc.registerElement(name, {
+ prototype: proto,
+ extends: tagName
+ });
+ var customElement = new GeneratedConstructor();
+
+ assert_equals(customElement.localName, tagName.toLowerCase(),
+ 'Custom element local name should be a lowercased value of the EXTENDS property, ' +
+ 'supplied to Document.registerElement()');
+ });
+}, 'Custom element local name is the lowercased value of the EXTENDS property, ' +
+ 'supplied to Document.registerElement()');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/extensions-to-document-interface/custom-element-prototype.html b/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/extensions-to-document-interface/custom-element-prototype.html
new file mode 100644
index 00000000000..476f5c80415
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/extensions-to-document-interface/custom-element-prototype.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Test prototype object of a custom element</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="assert" content="If PROTOTYPE is null, let PROTOTYPE be the result of invoking Object.create with HTMLElement's interface prototype object as only argument">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#extensions-to-document-interface-to-register">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ var doc = newHTMLDocument();
+ var GeneratedConstructor = doc.registerElement('x-a');
+ var customElement = new GeneratedConstructor();
+
+ assert_class_string(customElement, 'HTMLElement',
+ 'Custom element should be a HTMLElement, ' +
+ 'if its type is registered without prototype');
+}, 'Custom element should have HTMLElement prototype, ' +
+ 'if its type is registered without prototype');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-custom-tag-ref.html b/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-custom-tag-ref.html
new file mode 100644
index 00000000000..33c36463ceb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-custom-tag-ref.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+<title>The :unresolved pseudoclass reference file</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<style>
+ body {
+ background-color: white;
+ }
+</style>
+<body>
+ <p>Test passes if x-element background below is red</p>
+ <x-element style="background-color: red;">
+ x-element
+ </x-element>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-custom-tag.html b/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-custom-tag.html
new file mode 100644
index 00000000000..290e5b15cfc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-custom-tag.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<title>The :unresolved pseudoclass matching custom tag</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="assert" content="The :unresolved pseudoclass must match all custom elements whose created callback has not yet been invoked">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#unresolved-element-pseudoclass">
+<link rel="match" href="unresolved-element-pseudoclass-css-test-custom-tag-ref.html">
+<style>
+ :unresolved {
+ background-color: red;
+ }
+ body {
+ background-color: white;
+ }
+</style>
+<body>
+ <p>Test passes if x-element background below is red</p>
+ <x-element>
+ x-element
+ </x-element>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-registered-custom-tag-ref.html b/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-registered-custom-tag-ref.html
new file mode 100644
index 00000000000..d49f3d768fd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-registered-custom-tag-ref.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+<title>The :unresolved pseudoclass reference file</title>
+<link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<style>
+ body {
+ background-color: white;
+ }
+</style>
+<body>
+ <p>Test passes if x-element background below is yellow</p>
+ <x-element style="background-color: yellow;">
+ x-element
+ </x-element>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-registered-custom-tag.html b/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-registered-custom-tag.html
new file mode 100644
index 00000000000..3cd7b41d6e7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-registered-custom-tag.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<title>The :unresolved pseudoclass matching custom tag</title>
+<link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<meta name="assert" content="The :unresolved pseudoclass must match all custom elements whose created callback has not yet been invoked">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#unresolved-element-pseudoclass">
+<link rel="match" href="unresolved-element-pseudoclass-css-test-registered-custom-tag-ref.html">
+<style>
+ :unresolved {
+ background-color: red;
+ }
+ x-element {
+ background-color: yellow;
+ }
+ body {
+ background-color: white;
+ }
+</style>
+<body onload="document.registerElement('x-element');">
+ <p>Test passes if x-element background below is yellow</p>
+ <x-element>
+ x-element
+ </x-element>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-registered-type-extension-ref.html b/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-registered-type-extension-ref.html
new file mode 100644
index 00000000000..90baf95544c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-registered-type-extension-ref.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+<title>The :unresolved pseudoclass reference file</title>
+<link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<style>
+ body {
+ background-color: white;
+ }
+</style>
+<body>
+ <p>Test passes if x-element background below is yellow</p>
+ <a is="x-element" style="background-color: yellow;">
+ x-element
+ </a>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-registered-type-extension.html b/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-registered-type-extension.html
new file mode 100644
index 00000000000..65921bd4147
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-registered-type-extension.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html>
+<title>The :unresolved pseudoclass matching type extension</title>
+<link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<meta name="assert" content="The :unresolved pseudoclass must match all custom elements whose created callback has not yet been invoked">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#unresolved-element-pseudoclass">
+<link rel="match" href="unresolved-element-pseudoclass-css-test-registered-type-extension-ref.html">
+<style>
+ :unresolved {
+ background-color: red;
+ }
+ a {
+ background-color: yellow;
+ }
+ body {
+ background-color: white;
+ }
+</style>
+<script>
+function registerXElement() {
+ var obj = document.createElement('a');
+ var proto = Object.create(obj.constructor.prototype);
+ document.registerElement('x-element', { prototype: proto, extends: 'a'});
+}
+</script>
+<body onload="registerXElement();">
+ <p>Test passes if x-element background below is yellow</p>
+ <a is="x-element">
+ x-element
+ </a>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-type-extension-ref.html b/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-type-extension-ref.html
new file mode 100644
index 00000000000..9865f2e3926
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-type-extension-ref.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<title>The :unresolved pseudoclass reference file</title>
+<link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<style>
+ body {
+ background-color: white;
+ }
+</style>
+<body>
+ <p>Test passes if x-element background below is red</p>
+ <a is="x-element" style="background-color: red;">
+ x-element
+ </a>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-type-extension.html b/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-type-extension.html
new file mode 100644
index 00000000000..60f39125a0b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-type-extension.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<title>The :unresolved pseudoclass matching type extension</title>
+<link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<meta name="assert" content="The :unresolved pseudoclass must match all custom elements whose created callback has not yet been invoked">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#unresolved-element-pseudoclass">
+<link rel="match" href="unresolved-element-pseudoclass-css-test-type-extension-ref.html">
+<style>
+ :unresolved {
+ background-color: red;
+ }
+ body {
+ background-color: white;
+ }
+</style>
+<body>
+ <p>Test passes if x-element background below is red</p>
+ <a is="x-element">
+ x-element
+ </a>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-matching-query-selector-all.html b/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-matching-query-selector-all.html
new file mode 100644
index 00000000000..aa8147acc6f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-matching-query-selector-all.html
@@ -0,0 +1,191 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>The :unresolved pseudoclass matching with Document.querySelectorAll()</title>
+<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="assert" content="The :unresolved pseudoclass must match all custom elements whose created callback has not yet been invoked">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#unresolved-element-pseudoclass">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ var doc = newHTMLDocument();
+ doc.body.innerHTML = '<x-a></x-a>';
+ var queryResult = doc.querySelectorAll(':unresolved');
+
+ assert_equals(queryResult.length, 1,
+ 'Unresolved custom element should be accessible by :unresolved pseudoclass');
+ assert_equals(queryResult.item(0).localName, 'x-a',
+ 'Document.querySelectorAll(\':unresolved\') should return x-a element');
+}, 'Test that single unresolved custom element is accessible ' +
+ 'by Document.querySelectorAll(\':unresolved\')');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ doc.body.innerHTML = '<x-b></x-b>';
+ var queryResult = doc.querySelectorAll(':unresolved');
+
+ assert_equals(queryResult.length, 1,
+ 'Unresolved custom element should be accessible by :unresolved pseudoclass');
+ assert_equals(queryResult.item(0).localName, 'x-b',
+ 'Document.querySelectorAll(\':unresolved\') should return x-b element');
+
+ doc.registerElement('x-b');
+ queryResult = doc.querySelectorAll(':unresolved');
+
+ assert_equals(queryResult.length, 0,
+ 'Registered custom element should not be accessible by :unresolved pseudoclass');
+}, 'Test that single registered custom element is not accessible by :unresolved');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ doc.body.innerHTML = '<x-c></x-c><x-d></x-d>';
+ var queryResult = doc.querySelectorAll(':unresolved');
+
+ assert_equals(queryResult.length, 2,
+ 'All unresolved custom element should be accessible by :unresolved pseudoclass');
+ assert_equals(queryResult.item(0).localName, 'x-c',
+ 'First custom element returned by Document.querySelectorAll(\':unresolved\') ' +
+ 'should be x-c');
+ assert_equals(queryResult.item(1).localName, 'x-d',
+ 'Second custom element returned by Document.querySelectorAll(\':unresolved\') ' +
+ 'should be x-d');
+
+ doc.registerElement('x-c');
+ queryResult = doc.querySelectorAll(':unresolved');
+
+ assert_equals(queryResult.length, 1,
+ 'Only unresolved custom elements should be accessible by :unresolved pseudoclass');
+ assert_equals(queryResult.item(0).localName, 'x-d',
+ 'Custom element returned by Document.querySelectorAll(\':unresolved\') ' +
+ 'should be x-d');
+}, 'If there are more than one unresolved custom element then all of them accessible ' +
+ 'by Document.querySelectorAll(\':unresolved\')');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var customElement = doc.createElement('x-e');
+ doc.body.appendChild(customElement);
+ var queryResult = doc.querySelectorAll(':unresolved');
+
+ assert_equals(queryResult.length, 1,
+ 'Unresolved custom element should be accessible by :unresolved pseudoclass');
+ assert_equals(queryResult.item(0).localName, 'x-e',
+ 'Custom element returned by Document.querySelectorAll(\':unresolved\') ' +
+ 'should be x-e');
+}, 'Unresolved custom element, created via Document.createElement(), should be ' +
+ 'accessible by Document.querySelectorAll(\':unresolved\')');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ doc.body.innerHTML = '<x-f><x-g></x-g></x-f>';
+ var queryResult = doc.querySelectorAll(':unresolved');
+
+ assert_equals(queryResult.length, 2,
+ 'All unresolved custom element should be accessible by :unresolved pseudoclass');
+ assert_equals(queryResult.item(0).localName, 'x-f',
+ 'First custom element returned by Document.querySelectorAll(\':unresolved\') ' +
+ 'should be x-f');
+ assert_equals(queryResult.item(1).localName, 'x-g',
+ 'Second custom element returned by Document.querySelectorAll(\':unresolved\') ' +
+ 'should be x-g');
+
+ doc.registerElement('x-g');
+ queryResult = doc.querySelectorAll(':unresolved');
+
+ assert_equals(queryResult.length, 1,
+ 'Only unresolved custom elements should be accessible by :unresolved pseudoclass');
+ assert_equals(queryResult.item(0).localName, 'x-f',
+ 'Custom element returned by Document.querySelectorAll(\':unresolved\') ' +
+ 'should be x-f');
+}, 'All unresolved custom element including nested ones are accessible ' +
+ 'by Document.querySelectorAll(\':unresolved\')');
+
+
+testInIFrame('../../resources/x-element.html', function(doc) {
+ var queryResult = doc.querySelectorAll(':unresolved');
+
+ assert_equals(queryResult.length, 1,
+ 'Unresolved custom element should be accessible by ' +
+ 'Document.querySelectorAll(\':unresolved\')');
+ assert_equals(queryResult.item(0).localName, 'x-element',
+ 'Custom element returned by Document.querySelectorAll(\':unresolved\') ' +
+ 'should be x-element');
+}, 'Unresolved custom element should be accessible by ' +
+ 'Document.querySelectorAll(\':unresolved\') in a loaded document');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+
+ HTML5_ELEMENTS.forEach(function(tagName) {
+ if (HTML5_DOCUMENT_ELEMENTS.indexOf(tagName) === -1) {
+ var obj = doc.createElement(tagName);
+ var name = 'x-h-' + tagName;
+ var id = 'x-h-' + tagName + '-id';
+ if (HTML5_TABLE_ELEMENTS.indexOf(tagName) !== -1) {
+ doc.body.innerHTML =
+ '<table>' +
+ '<' + tagName + ' id="' + id + '" is="' + name + '"></' + tagName + '>' +
+ '</table>';
+ } else {
+ doc.body.innerHTML =
+ '<' + tagName + ' id="' + id + '" is="' + name + '"></' + tagName + '>';
+ }
+ var queryResult = doc.querySelectorAll(':unresolved');
+
+ assert_not_equals(queryResult, null,
+ 'Unresolved custom element should be accessible by :unresolved pseudoclass');
+ assert_equals(queryResult.item(0).id, id,
+ 'ID of element returned by Document.querySelectorAll(\':unresolved\') ' +
+ 'should be ' + id);
+
+ var proto = Object.create(obj.constructor.prototype);
+ doc.registerElement(name, {prototype: proto, extends: tagName});
+ var queryResult2 = doc.querySelectorAll(':unresolved');
+
+ assert_equals(queryResult2.length, 0,
+ 'Registered custom element should not be accessible by :unresolved pseudoclass');
+ }
+ });
+}, 'Test that Document.querySelectorAll(\':unresolved\') returns unresolved custom elements, ' +
+ 'extending HTML elements by IS attribute');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ doc.body.innerHTML = '<x-i><a is="x-j"></a></x-i><x-k></x-k><b is="x-l"/>';
+ var queryResult = doc.querySelectorAll(':unresolved');
+
+ assert_equals(queryResult.length, 4,
+ 'All unresolved custom element should be accessible by :unresolved pseudoclass');
+
+ var elementNames = [
+ queryResult.item(0).localName,
+ queryResult.item(1).localName,
+ queryResult.item(2).localName,
+ queryResult.item(3).localName];
+ assert_array_equals(elementNames, ['x-i', 'a', 'x-k', 'b'],
+ 'Document.querySelectorAll(\':unresolved\') return unexpected result');
+
+ var isAttributes = [
+ queryResult.item(0).getAttribute('is'),
+ queryResult.item(1).getAttribute('is'),
+ queryResult.item(2).getAttribute('is'),
+ queryResult.item(3).getAttribute('is')];
+ assert_array_equals(isAttributes, [null, 'x-j', null, 'x-l'],
+ 'Document.querySelectorAll(\':unresolved\') return unexpected result');
+}, 'Test Document.querySelectorAll(\':unresolved\') returns mix of custom elements of different types');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-matching-query-selector.html b/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-matching-query-selector.html
new file mode 100644
index 00000000000..b4dff826bb3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-matching-query-selector.html
@@ -0,0 +1,162 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>The :unresolved pseudoclass matching with Document.querySelector()</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<meta name="assert" content="The :unresolved pseudoclass must match all custom elements whose created callback has not yet been invoked">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#unresolved-element-pseudoclass">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ var doc = newHTMLDocument();
+ doc.body.innerHTML = '<x-a></x-a>';
+ var customElement = doc.querySelector(':unresolved');
+
+ assert_not_equals(customElement, null,
+ 'Unresolved custom element should be accessible by :unresolved');
+ assert_equals(customElement.localName, 'x-a',
+ 'Custom element returned by Document.querySelector(\':unresolved\') should be x-a');
+}, 'Test that unresolved custom element is accessible by Document.querySelector(\':unresolved\')');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ doc.body.innerHTML = '<x-b></x-b>';
+ var customElement = doc.querySelector(':unresolved');
+ assert_not_equals(customElement, null,
+ 'Unresolved custom element should be accessible by :unresolved');
+ assert_equals(customElement.localName, 'x-b',
+ 'Custom element returned by Document.querySelector(\':unresolved\') should be x-b');
+
+ doc.registerElement('x-b');
+ customElement = doc.querySelector(':unresolved');
+ assert_equals(customElement, null,
+ 'Registered custom element should not be accessible by :unresolved pseudoclass');
+}, 'Test that registered custom element are not accessible by :unresolved');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ doc.body.innerHTML = '<x-c></x-c><x-d></x-d>';
+ var customElement = doc.querySelector(':unresolved');
+ assert_not_equals(customElement, null,
+ 'Unresolved custom element should be accessible by :unresolved pseudoclass');
+ assert_equals(customElement.localName, 'x-c',
+ 'Custom element returned by Document.querySelector(\':unresolved\') should be x-c');
+
+ doc.registerElement('x-c');
+ customElement = doc.querySelector(':unresolved');
+ assert_not_equals(customElement, null,
+ 'Unresolved custom elements should be accessible by :unresolved pseudoclass');
+ assert_equals(customElement.localName, 'x-d',
+ 'Custom element returned by Document.querySelector(\':unresolved\') should be x-d');
+}, 'If there are more than one unresolved custom element, all of them should be ' +
+ 'accessible by :unresolved pseudoclass');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var customElement = doc.createElement('x-e');
+ doc.body.appendChild(customElement);
+ var queryResult = doc.querySelector(':unresolved');
+
+ assert_not_equals(queryResult, null,
+ 'Unresolved custom element should be accessible by :unresolved');
+ assert_equals(queryResult.localName, 'x-e',
+ 'Custom element returned by Document.querySelector(\':unresolved\') should be x-e');
+}, 'Unresolved custom element, created via Document.createElement(), should be ' +
+ 'accessible by Document.querySelector(\':unresolved\')');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ doc.body.innerHTML = '<div><x-f></x-f><div>';
+ var customElement = doc.querySelector(':unresolved');
+
+ assert_not_equals(customElement, null,
+ 'Unresolved custom element should be accessible by :unresolved');
+ assert_equals(customElement.localName, 'x-f',
+ 'Custom element returned by Document.querySelector(\':unresolved\') should be x-f');
+}, 'Unresolved custom element inside div element should be accessible by ' +
+ ':unresolved pseudoclass');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ doc.body.innerHTML = '<x-h><x-g></x-g></x-h>';
+ var customElement = doc.querySelector(':unresolved');
+
+ assert_not_equals(customElement, null,
+ 'Unresolved custom element should be accessible by :unresolved pseudoclass');
+ assert_equals(customElement.localName, 'x-h',
+ 'Custom element returned by Document.querySelector(\':unresolved\') ' +
+ 'should be x-h');
+
+ doc.registerElement('x-h');
+ customElement = doc.querySelector(':unresolved');
+
+ assert_not_equals(customElement, null,
+ 'Unresolved custom element should be accessible by :unresolved pseudoclass');
+ assert_equals(customElement.localName, 'x-g',
+ 'Custom element returned by Document.querySelector(\':unresolved\') ' +
+ 'should be x-g');
+}, 'All unresolved custom element including nested ones should be accessible ' +
+ 'by Document.querySelector(\':unresolved\')');
+
+
+testInIFrame('../../resources/x-element.html', function(doc) {
+ var customElement = doc.querySelector(':unresolved');
+
+ assert_not_equals(customElement, null,
+ 'Unresolved custom element should be accessible by :unresolved');
+ assert_equals(customElement.localName, 'x-element',
+ 'Custom element returned by Document.querySelector(\':unresolved\') should be x-element');
+}, 'Document.querySelector(): Unresolved custom element should be accessible by :unresolved ' +
+ 'in loaded document');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+
+ HTML5_ELEMENTS.forEach(function(tagName) {
+ if (HTML5_DOCUMENT_ELEMENTS.indexOf(tagName) === -1) {
+ var obj = doc.createElement(tagName);
+ var name = 'x-i-' + tagName;
+ var id = 'x-i-' + tagName + '-id';
+ if (HTML5_TABLE_ELEMENTS.indexOf(tagName) !== -1) {
+ doc.body.innerHTML =
+ '<table>' +
+ '<' + tagName + ' id="' + id + '" is="' + name + '"></' + tagName + '>' +
+ '</table>';
+ } else {
+ doc.body.innerHTML =
+ '<' + tagName + ' id="' + id + '" is="' + name + '"></' + tagName + '>';
+ }
+ var customElement = doc.querySelector(':unresolved');
+
+ assert_not_equals(customElement, null,
+ 'Unresolved custom element should be accessible by :unresolved pseudoclass');
+ assert_equals(customElement.id, id,
+ 'ID of element returned by Document.querySelector(\':unresolved\') ' +
+ 'should be ' + id);
+
+ var proto = Object.create(obj.constructor.prototype);
+ doc.registerElement(name, {prototype: proto, extends: tagName});
+ var customElement2 = doc.querySelector(':unresolved');
+
+ assert_equals(customElement2, null,
+ 'Registered custom element should not be accessible by :unresolved pseudoclass');
+ }
+ });
+}, 'Test that Document.querySelector(\':unresolved\') returns custom element, ' +
+ 'extending HTML elements by IS attribute');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/unresolved-elements-interface-html-element.html b/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/unresolved-elements-interface-html-element.html
new file mode 100644
index 00000000000..e8d66d1bf60
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/unresolved-elements-interface-html-element.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Unresolved element interface must be HTMLElement, if the namespace is HTML Namespace</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<meta name="assert" content="When an unresolved element is created, it's element interface must be HTMLElement, if the namespace is HTML Namespace">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#registering-custom-elements">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ var doc = newHTMLDocument();
+ doc.body.innerHTML = '<x-a id="x-a"></x-a>';
+ var customElement = doc.querySelector('#x-a');
+
+ assert_not_equals(customElement, null, 'Unregistered custom element should not be null');
+
+ assert_class_string(customElement, 'HTMLElement',
+ 'Unresolved custom element must be a HTML element');
+}, 'Test interface of unresolved element, created via innerHTML property');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var customElement = doc.createElement('x-b');
+
+ assert_class_string(customElement, 'HTMLElement',
+ 'Unresolved custom element must be a HTML element');
+}, 'Test interface of unresolved element, created by Document.createElement');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var customElement = doc.createElementNS(HTML_NAMESPACE, 'x-c');
+
+ assert_class_string(customElement, 'HTMLElement',
+ 'Unresolved custom element must be a HTML element');
+}, 'Test interface of unresolved element, created by Document.createElementNS');
+
+
+testInIFrame('../resources/x-element.html', function(doc) {
+ var customElement = doc.getElementById('x-element');
+
+ assert_not_equals(customElement, null, 'Unregistered custom element should not be null');
+
+ assert_class_string(customElement, 'HTMLElement',
+ 'Unresolved custom element must be a HTML element');
+}, 'Test unresolved element interface in loaded HTML document');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/unresolved-elements-interface-html-unknown-element.html b/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/unresolved-elements-interface-html-unknown-element.html
new file mode 100644
index 00000000000..cc3c2c2500d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/unresolved-elements-interface-html-unknown-element.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Unresolved element interface must be HTMLUnknownElement, if the namespace is neither HTML Namespace nor SVG Namespace</title>
+<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<meta name="assert" content="When an unresolved element is created, it's element interface must be HTMLUnknownElement, if the namespace is neither HTML Namespace nor SVG Namespace">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#registering-custom-elements">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var MATHML_NAMESPACE = 'http://www.w3.org/1998/Math/MathML';
+
+test(function() {
+ var doc = newHTMLDocument();
+ doc.body.innerHTML =
+ '<math xmlns="' + MATHML_NAMESPACE + '">' +
+ '<x-a id="x-a"></x-a>' +
+ '</math>';
+ var xa = doc.querySelector('#x-a');
+
+ assert_not_equals(xa, null, 'Unregistered custom element should not be null');
+
+ // According https://code.google.com/p/chromium/issues/detail?id=336377
+ // expected class string is Element
+ assert_class_string(xa, 'Element', 'Unresolved custom element must be an Element');
+}, 'Test interface of unresolved element with MathML namespace, created via innerHTML property');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var xa = doc.createElementNS(MATHML_NAMESPACE, 'x-b');
+
+ assert_class_string(xa, 'Element',
+ 'Unresolved custom element must be a HTMLUnknownElement');
+}, 'Test interface of unresolved element with MathML namespace, ' +
+ 'created by Document.createElementNS');
+
+
+testInIFrame('../resources/x-mathml-element.html', function(doc) {
+ var customElement = doc.getElementById('x-math-element');
+
+ assert_not_equals(customElement, null, 'Unregistered custom element should not be null');
+
+ assert_class_string(customElement, 'Element',
+ 'Unresolved custom element must be a Element');
+}, 'Test interface of unresolved element in loaded HTML document with embedded MathML elements');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/unresolved-elements-interface-svg-element.html b/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/unresolved-elements-interface-svg-element.html
new file mode 100644
index 00000000000..202035081b3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/registering-custom-elements/unresolved-elements-interface-svg-element.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Unresolved element interface must be SVGElement, if the namespace is SVG Namespace</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="author" title="Vasiliy Degtyarev" href="mailto:vasya@unipro.ru">
+<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<meta name="assert" content="When an unresolved element is created, it's element interface must be SVGElement if the namespace is SVG Namespace">
+<link rel="help" href="http://www.w3.org/TR/custom-elements/#registering-custom-elements">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ var doc = newHTMLDocument();
+ var xsvg = doc.createElementNS(SVG_NAMESPACE, 'x-svg');
+
+ assert_class_string(xsvg, 'SVGElement', 'Unresolved custom element must be a SVG element');
+}, 'Test interface of unresolved element with valid name, created by Document.createElementNS()');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ doc.body.innerHTML =
+ '<svg xmlns=' + SVG_NAMESPACE + ' version="1.1">' +
+ '<x-svg-a id="x-svg"></x-svg-a>' +
+ '</svg>';
+ var xsvg = doc.querySelector('#x-svg');
+
+ assert_class_string(xsvg, 'SVGElement', 'Unresolved custom element must be a SVG element');
+}, 'Test interface of unresolved element with valid name, created via innerHTML property');
+
+
+testInIFrame('../resources/x-svg-element.html', function(doc) {
+ var xsvg = doc.getElementById('x-svg-element');
+
+ assert_not_equals(xsvg, null, 'Unresolved custom element should not be null');
+
+ assert_class_string(xsvg, 'SVGElement',
+ 'Unresolved custom element must be a SVG element');
+}, 'Test interface of unresolved element in loaded HTML document with embedded SVG elements');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/resources/blank.html b/tests/wpt/web-platform-tests/custom-elements/resources/blank.html
new file mode 100644
index 00000000000..2e5697ba1fd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/resources/blank.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Blank document</title>
+ <link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+</head>
+<body>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/resources/import-master-async.html b/tests/wpt/web-platform-tests/custom-elements/resources/import-master-async.html
new file mode 100644
index 00000000000..0ecaafb29b7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/resources/import-master-async.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Import Master Document (asynchronous)</title>
+ <link rel="import" href="import.html" async>
+ </head>
+ <body>
+ <p>Master document body</p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/resources/import-master.html b/tests/wpt/web-platform-tests/custom-elements/resources/import-master.html
new file mode 100644
index 00000000000..d91bcb9cdb6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/resources/import-master.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Import Master Document</title>
+ <link rel="import" href="import.html">
+ </head>
+ <body>
+ <p>Master document body</p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/resources/import.html b/tests/wpt/web-platform-tests/custom-elements/resources/import.html
new file mode 100644
index 00000000000..dddc4670181
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/resources/import.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Import Document</title>
+ </head>
+ <body>
+ <p>Import Document body</p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/resources/register-and-create-custom-element.html b/tests/wpt/web-platform-tests/custom-elements/resources/register-and-create-custom-element.html
new file mode 100644
index 00000000000..c128cbf413c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/resources/register-and-create-custom-element.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Register and create custom element</title>
+ <link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+ <link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+</head>
+<body>
+ <div id="log"></div>
+ <script>
+ var proto = Object.create(HTMLElement.prototype);
+ proto.createdCallback = function() {
+ document.querySelector('#log').innerText = 'Created callback was called';
+ };
+ document.registerElement('x-element', {prototype: proto});
+ </script>
+ <x-element id="x-element"></x-element>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/resources/x-element.html b/tests/wpt/web-platform-tests/custom-elements/resources/x-element.html
new file mode 100644
index 00000000000..0c0d2daad6a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/resources/x-element.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>x-element custom element</title>
+ <link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+</head>
+<body>
+ <x-element id="x-element"></x-element>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/resources/x-mathml-element.html b/tests/wpt/web-platform-tests/custom-elements/resources/x-mathml-element.html
new file mode 100644
index 00000000000..3efdc2d0088
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/resources/x-mathml-element.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Custom element in MathML namespace</title>
+ <link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+</head>
+<body>
+ <math xmlns="http://www.w3.org/1998/Math/MathML">
+ <x-math-element id="x-math-element"></x-math-element>
+ </math>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/resources/x-svg-element.html b/tests/wpt/web-platform-tests/custom-elements/resources/x-svg-element.html
new file mode 100644
index 00000000000..6cea8575882
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/resources/x-svg-element.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>SVG custom element</title>
+ <link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+</head>
+<body>
+ <svg height="100" width="100">
+ <x-svg-element id="x-svg-element"></x-element>
+ </svg>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/custom-elements/testcommon.js b/tests/wpt/web-platform-tests/custom-elements/testcommon.js
new file mode 100644
index 00000000000..5cddbe8bc72
--- /dev/null
+++ b/tests/wpt/web-platform-tests/custom-elements/testcommon.js
@@ -0,0 +1,286 @@
+/*
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+ */
+
+"use strict";
+
+var HTML5_ELEMENTS = [ 'a', 'abbr', 'address', 'area', 'article', 'aside',
+ 'audio', 'b', 'base', 'bdi', 'bdo', 'blockquote', 'body', 'br',
+ 'button', 'canvas', 'caption', 'cite', 'code', 'col', 'colgroup',
+ 'command', 'datalist', 'dd', 'del', 'details', 'dfn', 'dialog', 'div',
+ 'dl', 'dt', 'em', 'embed', 'fieldset', 'figcaption', 'figure',
+ 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header',
+ 'hgroup', 'hr', 'html', 'i', 'iframe', 'img', 'input', 'ins', 'kbd',
+ 'keygen', 'label', 'legend', 'li', 'link', 'map', 'mark', 'menu',
+ 'meta', 'meter', 'nav', 'noscript', 'object', 'ol', 'optgroup',
+ 'option', 'output', 'p', 'param', 'pre', 'progress', 'q', 'rp', 'rt',
+ 'ruby', 's', 'samp', 'script', 'section', 'select', 'small', 'source',
+ 'span', 'strong', 'style', 'sub', 'table', 'tbody', 'td', 'textarea',
+ 'tfoot', 'th', 'thead', 'time', 'title', 'tr', 'track', 'u', 'ul',
+ 'var', 'video', 'wbr' ];
+
+var HTML5_DOCUMENT_ELEMENTS = [ 'html', 'head', 'body' ];
+
+var HTML5_TABLE_ELEMENTS = [ 'caption', 'col', 'colgroup', 'tbody', 'td',
+ 'tfoot', 'th', 'thead', 'tr' ];
+
+var EXTENDER_CHARS = [ 0x00B7, 0x02D0, 0x02D1, 0x0387, 0x0640, 0x0E46, 0x0EC6,
+ 0x3005, 0x3031, 0x3032, 0x3033, 0x3034, 0x3035, 0x309D, 0x309E, 0x30FC,
+ 0x30FD, 0x30FE ];
+
+var COMBINING_CHARS = [ 0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0305, 0x0306,
+ 0x0307, 0x0308, 0x0309, 0x030A, 0x030B, 0x030C, 0x030D, 0x030E, 0x030F,
+ 0x0310, 0x0311, 0x0312, 0x0313, 0x0314, 0x0315, 0x0316, 0x0317, 0x0318,
+ 0x0319, 0x031A, 0x031B, 0x031C, 0x031D, 0x031E, 0x031F, 0x0320, 0x0321,
+ 0x0322, 0x0323, 0x0324, 0x0325, 0x0326, 0x0327, 0x0328, 0x0329, 0x032A,
+ 0x032B, 0x032C, 0x032D, 0x032E, 0x032F, 0x0330, 0x0331, 0x0332, 0x0333,
+ 0x0334, 0x0335, 0x0336, 0x0337, 0x0338, 0x0339, 0x033A, 0x033B, 0x033C,
+ 0x033D, 0x033E, 0x033F, 0x0340, 0x0341, 0x0342, 0x0343, 0x0344, 0x0345,
+ 0x0360, 0x0361, 0x0483, 0x0484, 0x0485, 0x0486, 0x0591, 0x0592, 0x0593,
+ 0x0594, 0x0595, 0x0596, 0x0597, 0x0598, 0x0599, 0x05A0, 0x05A1, 0x05A3,
+ 0x05A4, 0x05A5, 0x05A6, 0x05A7, 0x05A8, 0x05A9, 0x05AA, 0x05AB, 0x05AC,
+ 0x05AD, 0x05AE, 0x05AF, 0x05B0, 0x05B1, 0x05B2, 0x05B3, 0x05B4, 0x05B5,
+ 0x05B6, 0x05B7, 0x05B8, 0x05B9, 0x05BB, 0x05BC, 0x05BD, 0x05BF, 0x05C1,
+ 0x05C2, 0x05C4, 0x064B, 0x064C, 0x064D, 0x064E, 0x064F, 0x0650, 0x0651,
+ 0x0652, 0x0670, 0x06D6, 0x06D7, 0x06D8, 0x06D9, 0x06DA, 0x06DB, 0x06DC,
+ 0x06DD, 0x06DE, 0x06DF, 0x06E0, 0x06E1, 0x06E2, 0x06E3, 0x06E4, 0x06E7,
+ 0x06E8, 0x06EA, 0x06EB, 0x06EC, 0x06ED, 0x0901, 0x0902, 0x0903, 0x093C,
+ 0x093E, 0x093F, 0x0940, 0x0941, 0x0942, 0x0943, 0x0944, 0x0945, 0x0946,
+ 0x0947, 0x0948, 0x0949, 0x094A, 0x094B, 0x094C, 0x094D, 0x0951, 0x0952,
+ 0x0953, 0x0954, 0x0962, 0x0963, 0x0981, 0x0982, 0x0983, 0x09BC, 0x09BE,
+ 0x09BF, 0x09C0, 0x09C1, 0x09C2, 0x09C3, 0x09C4, 0x09C7, 0x09C8, 0x09CB,
+ 0x09CC, 0x09CD, 0x09D7, 0x09E2, 0x09E3, 0x0A02, 0x0A3C, 0x0A3E, 0x0A3F,
+ 0x0A40, 0x0A41, 0x0A42, 0x0A47, 0x0A48, 0x0A4B, 0x0A4C, 0x0A4D, 0x0A70,
+ 0x0A71, 0x0A81, 0x0A82, 0x0A83, 0x0ABC, 0x0ABE, 0x0ABF, 0x0AC0, 0x0AC1,
+ 0x0AC2, 0x0AC3, 0x0AC4, 0x0AC5, 0x0AC7, 0x0AC8, 0x0AC9, 0x0ACB, 0x0ACC,
+ 0x0ACD, 0x0B01, 0x0B02, 0x0B03, 0x0B3C, 0x0B3E, 0x0B3F, 0x0B40, 0x0B41,
+ 0x0B42, 0x0B43, 0x0B47, 0x0B48, 0x0B4B, 0x0B4C, 0x0B4D, 0x0B56, 0x0B57,
+ 0x0B82, 0x0B83, 0x0BBE, 0x0BBF, 0x0BC0, 0x0BC1, 0x0BC2, 0x0BC6, 0x0BC7,
+ 0x0BC8, 0x0BCA, 0x0BCB, 0x0BCC, 0x0BCD, 0x0BD7, 0x0C01, 0x0C02, 0x0C03,
+ 0x0C3E, 0x0C3F, 0x0C40, 0x0C41, 0x0C42, 0x0C43, 0x0C44, 0x0C46, 0x0C47,
+ 0x0C48, 0x0C4A, 0x0C4B, 0x0C4C, 0x0C4D, 0x0C55, 0x0C56, 0x0C82, 0x0C83,
+ 0x0CBE, 0x0CBF, 0x0CC0, 0x0CC1, 0x0CC2, 0x0CC3, 0x0CC4, 0x0CC6, 0x0CC7,
+ 0x0CC8, 0x0CCA, 0x0CCB, 0x0CCC, 0x0CCD, 0x0CD5, 0x0CD6, 0x0D02, 0x0D03,
+ 0x0D3E, 0x0D3F, 0x0D40, 0x0D41, 0x0D42, 0x0D43, 0x0D46, 0x0D47, 0x0D48,
+ 0x0D4A, 0x0D4B, 0x0D4C, 0x0D4D, 0x0D57, 0x0E31, 0x0E34, 0x0E35, 0x0E36,
+ 0x0E37, 0x0E38, 0x0E39, 0x0E3A, 0x0E47, 0x0E48, 0x0E49, 0x0E4A, 0x0E4B,
+ 0x0E4C, 0x0E4D, 0x0E4E, 0x0EB1, 0x0EB4, 0x0EB5, 0x0EB6, 0x0EB7, 0x0EB8,
+ 0x0EB9, 0x0EBB, 0x0EBC, 0x0EC8, 0x0EC9, 0x0ECA, 0x0ECB, 0x0ECC, 0x0ECD,
+ 0x0F18, 0x0F19, 0x0F35, 0x0F37, 0x0F39, 0x0F3E, 0x0F3F, 0x0F71, 0x0F72,
+ 0x0F73, 0x0F74, 0x0F75, 0x0F76, 0x0F77, 0x0F78, 0x0F79, 0x0F7A, 0x0F7B,
+ 0x0F7C, 0x0F7D, 0x0F7E, 0x0F7F, 0x0F80, 0x0F81, 0x0F82, 0x0F83, 0x0F84,
+ 0x0F86, 0x0F87, 0x0F88, 0x0F89, 0x0F8A, 0x0F8B, 0x0F90, 0x0F91, 0x0F92,
+ 0x0F93, 0x0F94, 0x0F95, 0x0F97, 0x0F99, 0x0F9A, 0x0F9B, 0x0F9C, 0x0F9D,
+ 0x0F9E, 0x0F9F, 0x0FA0, 0x0FA1, 0x0FA2, 0x0FA3, 0x0FA4, 0x0FA5, 0x0FA6,
+ 0x0FA7, 0x0FA8, 0x0FA9, 0x0FAA, 0x0FAB, 0x0FAC, 0x0FAD, 0x0FB1, 0x0FB2,
+ 0x0FB3, 0x0FB4, 0x0FB5, 0x0FB6, 0x0FB7, 0x0FB9, 0x20D0, 0x20D1, 0x20D2,
+ 0x20D3, 0x20D4, 0x20D5, 0x20D6, 0x20D7, 0x20D8, 0x20D9, 0x20DA, 0x20DB,
+ 0x20DC, 0x20E1, 0x302A, 0x302B, 0x302C, 0x302D, 0x302E, 0x302F, 0x3099,
+ 0x309A ];
+
+var BASE_CHARS_SINGLE = [ 0x0386, 0x038C, 0x03DA, 0x03DC, 0x03DE, 0x03E0,
+ 0x0559, 0x06D5, 0x093D, 0x09B2, 0x0A5E, 0x0A8D, 0x0ABD, 0x0AE0, 0x0B3D,
+ 0x0B9C, 0x0CDE, 0x0E30, 0x0E84, 0x0E8A, 0x0E8D, 0x0EA5, 0x0EA7, 0x0EB0,
+ 0x0EBD, 0x1100, 0x1109, 0x113C, 0x113E, 0x1140, 0x114C, 0x114E, 0x1150,
+ 0x1159, 0x1163, 0x1165, 0x1167, 0x1169, 0x1175, 0x119E, 0x11A8, 0x11AB,
+ 0x11BA, 0x11EB, 0x11F0, 0x11F9, 0x1F59, 0x1F5B, 0x1F5D, 0x1FBE, 0x2126,
+ 0x212E ];
+
+var BASE_CHARS_RANGES = [ 0x0041, 0x005A, 0x0061, 0x007A, 0x00C0, 0x00D6,
+ 0x00D8, 0x00F6, 0x00F8, 0x00FF, 0x0100, 0x0131, 0x0134, 0x013E, 0x0141,
+ 0x0148, 0x014A, 0x017E, 0x0180, 0x01C3, 0x01CD, 0x01F0, 0x01F4, 0x01F5,
+ 0x01FA, 0x0217, 0x0250, 0x02A8, 0x02BB, 0x02C1, 0x0388, 0x038A, 0x038E,
+ 0x03A1, 0x03A3, 0x03CE, 0x03D0, 0x03D6, 0x03E2, 0x03F3, 0x0401, 0x040C,
+ 0x040E, 0x044F, 0x0451, 0x045C, 0x045E, 0x0481, 0x0490, 0x04C4, 0x04C7,
+ 0x04C8, 0x04CB, 0x04CC, 0x04D0, 0x04EB, 0x04EE, 0x04F5, 0x04F8, 0x04F9,
+ 0x0531, 0x0556, 0x0561, 0x0586, 0x05D0, 0x05EA, 0x05F0, 0x05F2, 0x0621,
+ 0x063A, 0x0641, 0x064A, 0x0671, 0x06B7, 0x06BA, 0x06BE, 0x06C0, 0x06CE,
+ 0x06D0, 0x06D3, 0x06E5, 0x06E6, 0x0905, 0x0939, 0x0958, 0x0961, 0x0985,
+ 0x098C, 0x098F, 0x0990, 0x0993, 0x09A8, 0x09AA, 0x09B0, 0x09B6, 0x09B9,
+ 0x09DC, 0x09DD, 0x09DF, 0x09E1, 0x09F0, 0x09F1, 0x0A05, 0x0A0A, 0x0A0F,
+ 0x0A10, 0x0A13, 0x0A28, 0x0A2A, 0x0A30, 0x0A32, 0x0A33, 0x0A35, 0x0A36,
+ 0x0A38, 0x0A39, 0x0A59, 0x0A5C, 0x0A72, 0x0A74, 0x0A85, 0x0A8B, 0x0A8F,
+ 0x0A91, 0x0A93, 0x0AA8, 0x0AAA, 0x0AB0, 0x0AB2, 0x0AB3, 0x0AB5, 0x0AB9,
+ 0x0B05, 0x0B0C, 0x0B0F, 0x0B10, 0x0B13, 0x0B28, 0x0B2A, 0x0B30, 0x0B32,
+ 0x0B33, 0x0B36, 0x0B39, 0x0B5C, 0x0B5D, 0x0B5F, 0x0B61, 0x0B85, 0x0B8A,
+ 0x0B8E, 0x0B90, 0x0B92, 0x0B95, 0x0B99, 0x0B9A, 0x0B9E, 0x0B9F, 0x0BA3,
+ 0x0BA4, 0x0BA8, 0x0BAA, 0x0BAE, 0x0BB5, 0x0BB7, 0x0BB9, 0x0C05, 0x0C0C,
+ 0x0C0E, 0x0C10, 0x0C12, 0x0C28, 0x0C2A, 0x0C33, 0x0C35, 0x0C39, 0x0C60,
+ 0x0C61, 0x0C85, 0x0C8C, 0x0C8E, 0x0C90, 0x0C92, 0x0CA8, 0x0CAA, 0x0CB3,
+ 0x0CB5, 0x0CB9, 0x0CE0, 0x0CE1, 0x0D05, 0x0D0C, 0x0D0E, 0x0D10, 0x0D12,
+ 0x0D28, 0x0D2A, 0x0D39, 0x0D60, 0x0D61, 0x0E01, 0x0E2E, 0x0E32, 0x0E33,
+ 0x0E40, 0x0E45, 0x0E81, 0x0E82, 0x0E87, 0x0E88, 0x0E94, 0x0E97, 0x0E99,
+ 0x0E9F, 0x0EA1, 0x0EA3, 0x0EAA, 0x0EAB, 0x0EAD, 0x0EAE, 0x0EB2, 0x0EB3,
+ 0x0EC0, 0x0EC4, 0x0F40, 0x0F47, 0x0F49, 0x0F69, 0x10A0, 0x10C5, 0x10D0,
+ 0x10F6, 0x1102, 0x1103, 0x1105, 0x1107, 0x110B, 0x110C, 0x110E, 0x1112,
+ 0x1154, 0x1155, 0x115F, 0x1161, 0x116D, 0x116E, 0x1172, 0x1173, 0x11AE,
+ 0x11AF, 0x11B7, 0x11B8, 0x11BC, 0x11C2, 0x1E00, 0x1E9B, 0x1EA0, 0x1EF9,
+ 0x1F00, 0x1F15, 0x1F18, 0x1F1D, 0x1F20, 0x1F45, 0x1F48, 0x1F4D, 0x1F50,
+ 0x1F57, 0x1F5F, 0x1F7D, 0x1F80, 0x1FB4, 0x1FB6, 0x1FBC, 0x1FC2, 0x1FC4,
+ 0x1FC6, 0x1FCC, 0x1FD0, 0x1FD3, 0x1FD6, 0x1FDB, 0x1FE0, 0x1FEC, 0x1FF2,
+ 0x1FF4, 0x1FF6, 0x1FFC, 0x212A, 0x212B, 0x2180, 0x2182, 0x3041, 0x3094,
+ 0x30A1, 0x30FA, 0x3105, 0x312C, 0xAC00, 0xD7A3 ];
+
+var IDEOGRAPHIC_CHARS_SINGLE = [ 0x3007 ];
+
+var IDEOGRAPHIC_CHARS_RANGES = [ 0x3021, 0x3029, 0x4E00, 0x9FA5 ];
+
+var DIGIT_CHARS_RANGES = [ 0x0030, 0x0039, 0x0660, 0x0669, 0x06F0, 0x06F9,
+ 0x0966, 0x096F, 0x09E6, 0x09EF, 0x0A66, 0x0A6F, 0x0AE6, 0x0AEF, 0x0B66,
+ 0x0B6F, 0x0BE7, 0x0BEF, 0x0C66, 0x0C6F, 0x0CE6, 0x0CEF, 0x0D66, 0x0D6F,
+ 0x0E50, 0x0E59, 0x0ED0, 0x0ED9, 0x0F20, 0x0F29 ];
+
+function CharsArray(array) {
+ this.array = array;
+}
+
+CharsArray.prototype.testEach = function(namingFunction, checkFunction) {
+ if (this.array != null) {
+ this.array.forEach(function(value) {
+ checkFunction(namingFunction(getCharCode(value)));
+ });
+ }
+};
+
+function CharRangesArray(array) {
+ this.array = array;
+}
+
+CharRangesArray.prototype.testEach = function(namingFunction, checkFunction) {
+ if (this.array != null) {
+ for (var i = 0; i < this.array.length; i += 2) {
+ var rangeStart = getCharCode(this.array[i]);
+ var rangeEnd = getCharCode(this.array[i+1]);
+ for (var c = rangeStart; c <= rangeEnd; c++) {
+ checkFunction(namingFunction(c));
+ }
+ }
+ }
+};
+
+function testCharCode(charCode, namingFunction, checkFunction) {
+ checkFunction(namingFunction(charCode));
+}
+
+var extenderChars = new CharsArray(EXTENDER_CHARS);
+var combiningChars = new CharsArray(COMBINING_CHARS);
+var baseCharsSingle = new CharsArray(BASE_CHARS_SINGLE);
+var baseCharsRanges = new CharRangesArray(BASE_CHARS_RANGES);
+var ideographicCharsSingle = new CharsArray(IDEOGRAPHIC_CHARS_SINGLE);
+var ideographicCharsRanges = new CharRangesArray(IDEOGRAPHIC_CHARS_RANGES);
+var digitCharsRanges = new CharRangesArray(DIGIT_CHARS_RANGES);
+
+// Helper function, which verifies that given custom element name is valid
+function checkValidName(name) {
+ var doc = newHTMLDocument();
+ try {
+ doc.registerElement(name);
+ } catch (e) {
+ assert_unreached('The custom element name \'' + name +
+ '\' should be registered without errors');
+ }
+}
+
+// Helper function, which verifies that given custom element name is invalid
+function checkInvalidName(name) {
+ var doc = newHTMLDocument();
+ assert_throws('SyntaxError', function() {
+ doc.registerElement(name);
+ }, 'Registering invalid custom element name \'' + name + '\' should fail');
+}
+
+// Helper function to extract character code from given object
+// expected input: either charater code or one character long string.
+function getCharCode(c) {
+ if (typeof(c) === 'string') {
+ assert_equals(1, c.length, 'Error in test: input string should be one character long');
+ c = c.charCodeAt(0);
+ }
+ assert_equals('number', typeof(c), 'Error in test: unexpected type for charater code');
+ return c;
+}
+
+var HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';
+var SVG_NAMESPACE = 'http://www.w3.org/2000/svg';
+
+function newHTMLDocument() {
+ return document.implementation.createHTMLDocument('Test Document');
+}
+
+// Creates new iframe and loads given url into it.
+// Returns reference to created iframe.
+function newIFrame(url) {
+ assert_not_equals(url, null, 'argument url should not be null');
+ var iframe = document.createElement('iframe');
+ iframe.src = url;
+ document.body.appendChild(iframe);
+ return iframe;
+}
+
+// Creates new iframe and loads given url into it.
+// Function f is bound to the iframe's onload event.
+// Function f receives iframe's contentDocument as argument.
+// The iframe is disposed after function f is executed.
+function testInIFrame(url, f, testName, testProps) {
+ var t = async_test(testName, testProps);
+ t.step(function() {
+ var iframe = newIFrame(url);
+ iframe.onload = t.step_func(function() {
+ try {
+ f(iframe.contentDocument);
+ t.done();
+ } finally {
+ iframe.remove();
+ }
+ });
+ });
+}
+
+// Helper function to create a prototype for custom element
+// with predefined callbacks
+function newHTMLElementPrototype() {
+ return newCustomElementPrototype(HTMLElement.prototype);
+}
+
+// Helper function to create a prototype for custom element
+// with predefined callbacks
+function newCustomElementPrototype(parent) {
+ var proto = Object.create(parent);
+ proto.createdCallbackThis = null;
+ proto.createdCallbackCalledCounter = 0;
+
+ proto.attachedCallbackThis = null;
+ proto.attachedCallbackCalledCounter = 0;
+
+ proto.detachedCallbackThis = null;
+ proto.detachedCallbackCalledCounter = 0;
+
+ proto.attributeChangedCallbackThis = null;
+ proto.attributeChangedCallbackCalledCounter = 0;
+ proto.attributeChangedCallbackArgs = null;
+
+ proto.createdCallback = function() {
+ proto.createdCallbackThis = this;
+ proto.createdCallbackCalledCounter++;
+ };
+ proto.attachedCallback = function() {
+ proto.attachedCallbackThis = this;
+ proto.attachedCallbackCalledCounter++;
+ };
+ proto.detachedCallback = function() {
+ proto.detachedCallbackThis = this;
+ proto.detachedCallbackCalledCounter++;
+ };
+ proto.attributeChangedCallback = function(arg1, arg2, arg3) {
+ proto.attributeChangedCallbackThis = this;
+ proto.attributeChangedCallbackCalledCounter++;
+ proto.attributeChangedCallbackArgs = [arg1, arg2, arg3];
+ };
+ return proto;
+}
diff --git a/tests/wpt/web-platform-tests/docs/configuration.md b/tests/wpt/web-platform-tests/docs/configuration.md
new file mode 100644
index 00000000000..b526c986942
--- /dev/null
+++ b/tests/wpt/web-platform-tests/docs/configuration.md
@@ -0,0 +1,78 @@
+Web-platform-tests are designed to run in a self-contained environment
+on the local computer. All the required resources are packaged with
+the web-platform-tests repository.
+
+## Requirements
+
+ * [git](http://git-scm.com/)
+ * [Python 2.7](http://python.org)
+ * [OpenSSL](https://www.openssl.org)
+
+## Hosts configuration
+
+The tests depend on certain domains being available. These are
+typically configured locally with `web-platform.test` as the top level
+domain and five subdomains. To configure these domains you need to edit
+your
+[`hosts` file](http://en.wikipedia.org/wiki/Hosts_%28file%29%23Location_in_the_file_system). The
+following entries are required:
+
+```
+127.0.0.1 web-platform.test
+127.0.0.1 www.web-platform.test
+127.0.0.1 www1.web-platform.test
+127.0.0.1 www2.web-platform.test
+127.0.0.1 xn--n8j6ds53lwwkrqhv28a.web-platform.test
+127.0.0.1 xn--lve-6lad.web-platform.test
+```
+
+## Cloning the Repository
+
+If you have not done so, clone the web-platform-tests repository:
+
+ git clone --recursive git@github.com:w3c/web-platform-tests.git
+
+If you have already made a clone, but did not specify `--recursive`
+update all submodules:
+
+ git submodule update --init --recursive
+
+## Font Files
+
+Many layout tests require a set of test-specific fonts, notably
+Ahem. These are available from the
+[CSS Fonts](http://www.w3.org/Style/CSS/Test/Fonts/) website. These
+must be installed according to the normal font-install procedure for
+your operating system.
+
+## Running the Test Server
+
+The test environment can be started using
+
+ ./serve
+
+This will start HTTP servers on two ports and a websockets server on
+one port. By default one web server starts on port 8000 and the other
+ports are randomly-chosen free ports. Tests must be loaded from the
+*first* HTTP server in the output. To change the ports, copy the
+`config.default.json` file to `config.json` and edit the new file,
+replacing the part that reads:
+
+```
+"http": [8000, "auto"]
+```
+
+to some port of your choice e.g.
+
+```
+"http": [1234, "auto"]
+```
+
+If you installed OpenSSL in such a way that running `openssl` at a
+command line doesn't work, you also need to adjust the path to the
+OpenSSL binary. This can be done by adding a section to `config.json`
+like:
+
+```
+"ssl": {"openssl": {"binary": "/path/to/openssl"}}
+```
diff --git a/tests/wpt/web-platform-tests/docs/css-metadata.md b/tests/wpt/web-platform-tests/docs/css-metadata.md
new file mode 100644
index 00000000000..c2de47cfe95
--- /dev/null
+++ b/tests/wpt/web-platform-tests/docs/css-metadata.md
@@ -0,0 +1,391 @@
+CSS tests have some particular requirements for metadata.
+
+## Title element
+
+``` html
+<title>[Test Area]: [Title/Scope of Test]</title>
+or
+<title>[Test Area] Reference File</title>
+```
+
+The title appears in the generated index, so make sure it is
+concise and descriptive. The role of the title is to
+identify what specific detail of a feature or combination of
+features is being tested, so that someone looking through an index
+can see quickly what's tested in which file. In most cases, this
+description should not require more than 5 or 6 words. There is no
+need to provide the chapter or section in the title. For reference
+file, the titles should not be specific to a test case as these
+files may be used by multiple different tests.
+
+Bad examples:
+
+``` html
+<title>CSS Test: Border Conflict Resolution</title>
+<title>CSS Regions auto-height Reference</title>
+```
+
+Good examples:
+
+``` html
+<title>CSS Test: Border Conflict Resolution (width) - hidden/double
+</title>
+<title>CSS Reference File</title>
+```
+
+For CSS specifications other than CSS 2.1, you can include the
+module name somewhere before the colon, like "CSS Selectors Test:"
+or "CSS Test (Selectors):". Do not include the module version
+number, since the test might get reused for the next version.
+
+### Credits
+
+``` html
+<link rel="author" title="NAME_OF_AUTHOR"
+href="[mailto:some@address or http://some.url]" />
+```
+
+Credits provide a way to identify the person or organization that
+created the test and/or holds copyright in the test. This is useful
+for reviewing purposes and for asking questions about the individual
+test. A test can have multiple author credits if necessary.
+
+Example 1:
+
+``` html
+<link rel="author" title="Boris Zbarsky"
+href="mailto:bzbarsky@mit.edu" />
+```
+
+Example 2:
+
+``` html
+<link rel="author" title="Bert Bos"
+href="http://www.w3.org/People/Bos/" />
+```
+
+Example 3:
+
+``` html
+<link rel="author" title="Microsoft" href="http://microsoft.com/" />
+```
+
+### Reviewer
+
+``` html
+<link rel="reviewer" title="NAME_OF_REVIEWER" href="[mailto:some@address
+or http://some.url]" /> <!-- YYYY-MM-DD -->
+```
+
+If a test has passed review, then the reviewer should note this by
+adding his or her name as a reviewer, along with the date of the
+review. A test can have multiple reviewers if necessary. A reviewer
+must be a person, not an organization.
+
+Example 1:
+
+``` html
+<link rel="reviewer" title="Boris Zbarsky"
+href="mailto:bzbarsky@mit.edu" /> <!-- 2008-02-19 -->
+```
+
+Example 2:
+
+``` html
+<link rel="reviewer" title="Bert Bos"
+href="http://www.w3.org/People/Bos/" /> <!-- 2005-05-03 -->
+```
+
+If a test would pass review with some (non-metadata) changes and the
+reviewer chooses to make these changes, then the reviewer should add
+his or her name as a reviewer-author, along with the date of the
+review, when checking in those changes. This indicates that the
+reviewer-author approves of the original author's test when taken
+with these proposed changes, and that someone else (possibly the
+original author) must review the changes. The test is fully reviewed
+only when the latest reviewer did not also contribute changes to the
+test at the time of the review.
+
+Example of a fully-reviewed test:
+
+``` html
+<link rel="author" title="Bert Bos"
+href="http://www.w3.org/People/Bos/" />
+<link rel="reviewer author" title="Boris Zbarsky"
+href="mailto:bzbarsky@mit.edu" /> <!-- 2008-02-19 -->
+<link rel="reviewer" title="Bert Bos"
+href="http://www.w3.org/People/Bos/" /> <!-- 2008-04-22 -->
+```
+
+This test was written by Bert Bos, then reviewed by Boris Zbarsky,
+who made some corrections before deeming it acceptable. Those
+corrections were then reviewed and accepted by Bert Bos.
+
+### Specification Links
+
+Specification Links
+
+``` html
+<link rel="help" href="RELEVANT_SPEC_SECTION" />
+```
+
+The specification link elements provide a way to align the test with
+information in the specification being tested.
+
+* Links should link to relevant sections within the specification
+* Use the anchors from the specification's Table of Contents
+* A test can have multiple specification links
+ * Always list the primary section that is being tested as the
+ first item in the list of specification links
+ * Order the list from the most used/specific to least used/specific
+ * There is no need to list common incidental features like the
+ color green if it is being used to validate the test unless the
+ case is specifically testing the color green
+* If the test is part of multiple test suites, link to the relevant
+ sections of each spec.
+
+Example 1:
+
+``` html
+<link rel="help"
+href="http://www.w3.org/TR/CSS21/text.html#alignment-prop" />
+```
+
+Example 2:
+
+``` html
+<link rel="help"
+href="http://www.w3.org/TR/CSS21/text.html#alignment-prop" />
+<link rel="help" href="http://www.w3.org/TR/CSS21/visudet.html#q7" />
+<link rel="help"
+href="http://www.w3.org/TR/CSS21/visudet.html#line-height" />
+<link rel="help"
+href="http://www.w3.org/TR/CSS21/colors.html#background-properties" />
+```
+
+### Reference Links
+
+*Reftests only*
+
+``` html
+<link rel="match" href="RELATIVE_PATH_TO_REFERENCE_FILE" />
+<link rel="mismatch" href="RELATIVE_PATH_TO_REFERENCE_FILE" />
+```
+
+The reference link elements are used in reftests and provide
+the list of reference file(s) that the test should be compared to.
+
+* ```match``` references must be files that render identically to
+ the test, but use an alternate means to do so
+* Multiple match references are used when the test can match any of
+ the reference files
+ * If a test requires multiple match references that all need to
+ match (for example, to catch when a reference fails in the same
+ way the test does), then chain the references together, i.e.:
+ place reference links to the additional match references in the
+ reference files. It is recommended that the chained reference
+ files form a loop (e.g.: a → b → c → a) so that a test linking
+ to any reference in the chain will find all the references.
+* ```mismatch``` references are files that render differently than
+ the test file. A test may have any number of mismatch references.
+ The test is considered to fail if it renders the same as any of
+ the mismatch references.
+ * Note that reference files may themselves have mismatch
+ references. In that case the reference file must not render the
+ same as any of its mismatch references in order to be considered
+ valid. If a reference is considered invalid (by the fact of not
+ matching any of its match references, or matching any of its
+ mismatch references), then a test that refers to the reference
+ will be considered to have failed.
+* Reference files may be dedicated reference files, images, or other
+ tests
+
+Example 1:
+
+``` html
+<link rel="match" href="green-box-ref.xht" />
+```
+
+Example 2:
+
+``` html
+<link rel="match" href="green-box-ref.xht" />
+<link rel="match" href="blue-box-ref.xht" />
+<link rel="mismatch" href="red-box-notref.xht" />
+<link rel="mismatch" href="red-box-notref.xht" />
+```
+
+### Requirement Flags
+
+<table>
+<tr>
+ <th>Token</th>
+ <th>Description</th>
+</tr>
+<tr>
+ <td>ahem</td>
+ <td>Test requires
+ <a href="http://www.w3.org/Style/CSS/Test/Fonts/Ahem">Ahem font</a>
+ </td>
+</tr>
+<tr>
+ <td>animated</td>
+ <td>Test is animated in final state. (Cannot be verified using
+ reftests/screenshots.)</td>
+</tr>
+<tr>
+ <td>asis</td>
+ <td>The test has particular markup formatting requirements and
+ cannot be re-serialized.</td>
+</tr>
+<tr>
+ <td>combo</td>
+ <td>Test, which must have an unsuffixed filename number, is
+ strictly the union of all the suffixed tests with the same name
+ and number. (See File name format, below.)</td>
+</tr>
+<tr>
+ <td>dom</td>
+ <td>Requires support for JavaScript and the Document Object Model (
+ DOM)</td>
+</tr>
+<tr>
+ <td>font</td>
+ <td>Requires a specific font to be installed. (Details must be
+ provided and/or the font linked to in the test description)</td>
+</tr>
+<tr>
+ <td>history</td>
+ <td>User agent session history is required. Testing :visited is a
+ good example where this may be used.</td>
+</tr>
+<tr>
+ <td>HTMLonly</td>
+ <td>Test case is only valid for HTML</td>
+</tr>
+<tr>
+ <td>http</td>
+ <td>Requires HTTP headers</td>
+</tr>
+<tr>
+ <td>image</td>
+ <td>Requires support for bitmap graphics and the graphic to load
+ </td>
+</tr>
+<tr>
+ <td>interact</td>
+ <td>Requires human interaction (such as for testing scrolling
+ behavior)</td>
+</tr>
+<tr>
+ <td>invalid</td>
+ <td>Tests handling of invalid CSS. Note: This case contains CSS
+ properties and syntax that may not validate.</td>
+</tr>
+<tr>
+ <td>may</td>
+ <td>Behavior tested is preferred but OPTIONAL.
+ <a href="http://www.ietf.org/rfc/rfc2119.txt">[RFC2119]</a></td>
+</tr>
+<tr>
+ <td>namespace</td>
+ <td>Requires support for XML Namespaces</td>
+</tr>
+<tr>
+ <td>nonHTML</td>
+ <td>Test case is only valid for formats besides HTML (e.g. XHTML
+ or arbitrary XML)</td>
+</tr>
+<tr>
+ <td>paged</td>
+ <td>Only valid for paged media</td>
+</tr>
+<tr>
+ <td>scroll</td>
+ <td>Only valid for continuous (scrolling) media</td>
+</tr>
+<tr>
+ <td>should</td>
+ <td>Behavior tested is RECOMMENDED, but not REQUIRED. <a
+ href="http://www.ietf.org/rfc/rfc2119.txt">[RFC2119]</a></td>
+</tr>
+<tr>
+ <td>speech</td>
+ <td>Device supports audio output. Text-to-speech (TTS) engine
+ installed</td>
+</tr>
+<tr>
+ <td>svg</td>
+ <td>Requires support for vector graphics (SVG)</td>
+</tr>
+<tr>
+ <td>userstyle</td>
+ <td>Requires a user style sheet to be set</td>
+</tr>
+<tr>
+ <td>32bit</td>
+ <td>Assumes a 32-bit integer as the minimum (-2147483648) or
+ maximum (2147483647) value</td>
+</tr>
+<tr>
+ <td>96dpi</td>
+ <td>Assumes 96dpi display</td>
+</tr>
+</table>
+
+
+Example 1 (one token applies):
+``` html
+<meta name="flags" content="invalid" />
+```
+
+Example 2 (multiple tokens apply):
+
+``` html
+<meta name="flags" content="ahem image scroll" />
+```
+
+Example 3 (no tokens apply):
+
+``` html
+<meta name="flags" content="" />
+```
+
+### Test Assertions
+
+``` html
+<meta name="assert" content="TEST ASSERTION" />
+```
+
+This element should contain a complete detailed statement expressing
+what specifically the test is attempting to prove. If the assertion
+is only valid in certain cases, those conditions should be described
+in the statement.
+
+The assertion should not be:
+
+* A copy of the title text
+* A copy of the test verification instructions
+* A duplicate of another assertion in the test suite
+* A line or reference from the CSS specification unless that line is
+ a complete assertion when taken out of context.
+
+The test assertion is **optional**. It helps the reviewer understand
+the goal of the test so that he or she can make sure it is being
+tested correctly. Also, in case a problem is found with the test
+later, the testing method (e.g. using 'color' to determine pass/fail)
+can be changed (e.g. to using 'background-color') while preserving
+the intent of the test (e.g. testing support for ID selectors).
+
+Examples of good test assertions:
+
+* "This test checks that a background image with no intrinsic size
+ covers the entire padding box."
+* "This test checks that 'word-spacing' affects each space (U+0020)
+ and non-breaking space (U+00A0)."
+* "This test checks that if 'top' and 'bottom' offsets are specified
+ on an absolutely-positioned replaced element, then any remaining
+ space is split amongst the 'auto' vertical margins."
+* "This test checks that 'text-indent' affects only the first line
+ of a block container if that line is also the first formatted line
+ of an element."
diff --git a/tests/wpt/web-platform-tests/docs/css-naming.md b/tests/wpt/web-platform-tests/docs/css-naming.md
new file mode 100644
index 00000000000..9652b0b9ce1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/docs/css-naming.md
@@ -0,0 +1,65 @@
+CSS tests require a specific naming convention. This is also a good,
+but not mandatory, style to use for other tests.
+
+## File Name
+
+The file name format is ```test-topic-###.ext``` where ```test-
+topic``` somewhat describes the test and ### is a zero-filled number
+used to keep the file names unique.
+
+**test-topic**
+
+A short identifier that describes the test. The test-topic should
+avoid conjunctions, articles, and prepositions. It is a file name,
+not an English phrase: it should be as concise as possible.
+
+Examples:
+```
+ margin-collapsing-###.ext
+ border-solid-###.ext
+ float-clear-###.ext
+```
+
+**###**
+
+This is a zero-filled number used to keep the file names unique when
+files have the same test-topic name.
+
+Note: The number format is limited to 999 cases. If you go over this
+number it is recommended that you reevaluate your test-topic name.
+
+For example, in the case of margin-collapsing there are multiple
+cases so each case could have the same test-topic but different
+numbers:
+
+```
+ margin-collapsing-001.xht
+ margin-collapsing-002.xht
+ margin-collapsing-003.xht
+```
+
+There may also be a letter affixed after the number, which can be
+used to indicate variants of a test.
+
+For example, ```float-wrap-001l.xht``` and ```float-wrap-001r.xht```
+might be left and right variants of a float test.
+
+If tests using both the unsuffixed number and the suffixed number
+exist, the suffixed tests must be subsets of the unsuffixed test.
+
+For example, if ```bidi-004``` and ```bidi-004a``` both exist,
+```bidi-004a``` must be a subset of ```bidi-004```.
+
+If the unsuffixed test is strictly the union of the suffixed tests,
+i.e. covers all aspects of the suffixed tests (such that a user agent
+passing the unsuffixed test will, by design, pass all the suffixed
+tests), then the unsuffixed test should be marked with the combo flag.
+
+If ```bidi-004a``` and ```bidi-004b``` cover all aspects of ```bidi-
+004``` (except their interaction), then bidi-004 should be given the
+combo flag.
+
+**ext**
+
+The file extension or format of the file, usually ```.xht``` for
+test files.
diff --git a/tests/wpt/web-platform-tests/docs/css-user-styles.md b/tests/wpt/web-platform-tests/docs/css-user-styles.md
new file mode 100644
index 00000000000..2eeff97ec7c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/docs/css-user-styles.md
@@ -0,0 +1,85 @@
+Some test may require special user style sheets to be applied in order
+for the case to be verified. In order for proper indications and
+prerequisite to be displayed every user style sheet should contain the
+following rules.
+
+``` css
+#user-stylesheet-indication
+{
+ /* Used by the harness to display an indication there is a user
+ style sheet applied */
+ display: block!important;
+}
+```
+
+The rule ```#user-stylesheet-indication``` is to be used by any
+harness running the test suite.
+
+A harness should identify test that need a user style sheet by
+looking at their flags meta tag. It then should display appropriate
+messages indicating if a style sheet is applied or if a style sheet
+should not be applied.
+
+Harness style sheet rules:
+
+``` css
+#userstyle
+{
+ color: green;
+ display: none;
+}
+#nouserstyle
+{
+ color: red;
+ display: none;
+}
+```
+
+Harness userstyle flag found:
+
+``` html
+<p id="user-stylesheet-indication" class="userstyle">A user style
+sheet is applied.</p>
+```
+
+Harness userstyle flag NOT found:
+
+``` html
+<p id="user-stylesheet-indication" class="nouserstyle">A user style
+sheet is applied.</p>
+```
+
+Within the test case it is recommended that the case itself indicate
+the necessary user style sheet that is required.
+
+Examples: (code for the cascade.css file)
+
+``` css
+#cascade /* ID name should match user style sheet file name */
+{
+ /* Used by the test to hide the prerequisite */
+ display: none;
+}
+```
+
+The rule ```#cascade``` in the example above is used by the test
+page to hide the prerequisite text. The rule name should match the
+user style sheet CSS file name in order to keep this orderly.
+
+Examples: (code for the cascade-### XHTML files)
+
+``` html
+<p id="cascade">
+ PREREQUISITE: The <a href="support/cascade.css">
+ "cascade.css"</a> file is enabled as the user agent's user style
+ sheet.
+</p>
+```
+
+The id value should match the user style sheet CSS file name and the
+user style sheet rule that is used to hide this text when the style
+sheet is properly applied.
+
+Please flag test that require user style sheets with the userstyle
+flag so people running the tests know that a user style sheet is
+required.
diff --git a/tests/wpt/web-platform-tests/docs/github-101.md b/tests/wpt/web-platform-tests/docs/github-101.md
new file mode 100644
index 00000000000..d76bf6f6d17
--- /dev/null
+++ b/tests/wpt/web-platform-tests/docs/github-101.md
@@ -0,0 +1,361 @@
+All the basics that you need to know are documented on this page, but for the
+full GitHub documentation, visit [help.github.com][help].
+
+If you are already an experienced Git/GitHub user, all you need to
+know is that we use the normal GitHub Pull Request workflow for test
+submissions. The only unusual thing is that, to help with code review,
+we ask that you do not amend or otherwise squash your submission as
+you go along, but keep pushing updates as new commits.
+
+If you are a first-time GitHub user, read on for more details of the workflow.
+
+## Setup
+
+1. Create a GitHub account if you do not already have one on
+ [github.com][github]
+
+2. Download and install the latest version of Git:
+ [http://git-scm.com/downloads][git]. Please refer to the instruction there
+ for different platforms.
+
+3. Configure your settings so your commits are properly labeled:
+
+ On Mac or Linux or Solaris, open the Terminal.
+
+ On Windows, open Git Bash (From the Start Menu > Git > Git Bash).
+
+ At the prompt, type:
+
+ $ git config --global user.name "Your Name"
+
+ _This will be the name that is displayed with your test submissions_
+
+ Next, type:
+
+ $ git config --global user.email "your_email@address.com"
+
+ _This should be the email address you used to create the account in Step 1._
+
+ Next, type:
+
+ $ git config --global push.default upstream
+
+ This ensures that git push will never unintentionally create or update
+ a remote branch.
+
+4. (Optional) If you don't want to enter your username and password every
+ time you talk to the remote server, you'll need to set up password caching.
+ See [Caching your GitHub password in Git][password-caching].
+
+## Test Repositories
+
+The test repository that you contribute to will depend on the specification
+that you are testing. Currently there are two test repositories, one for CSS
+specification tests and the main W3C repository that contains tests for all
+other specificatons:
+
+**Main W3C test repository**: [github.com/w3c/web-platform-tests][main-repo]
+
+**CSS specification test repository**: [github.com/w3c/csswg-test][css-repo]
+
+## Fork
+
+Now that you have Git set up, you will need to fork the test repository. This
+will enable you to [submit][submit] your tests using a pull request (more on this
+[below][submit]).
+
+1. In the browser, go the the GitHub page for the test repository:
+
+ CSS test repository: [github.com/w3c/csswg-test][css-repo]
+
+ Main W3C test repository: [github.com/w3c/web-platform-tests][main-repo]
+
+2. Click the ![fork][forkbtn] button in the upper right.
+
+3. The fork will take several seconds, then you will be redirected to your
+ GitHub page for this forked repository. If you forked the HTML test repo
+ (for example), you will now be at
+ **https://github.com/username/web-platform-tests**.
+
+4. After the fork is complete, you're ready to [clone](#clone).
+
+## Clone
+
+If your [fork](#fork) was successful, the next step is to clone (download a copy of the files).
+
+### Clone the test repo
+At the command prompt, cd into the directory where you want to keep the tests.
+
+* If you forked the W3C Web Platform tests:
+
+ $ git clone --recursive https://github.com/username/web-platform-tests.git
+
+ If you forked the CSS tests:
+
+ $ git clone --recursive https://github.com/username/csswg-test.git
+
+ _This will download the tests into a directory named for the repo:_
+ `./web-platform-tests` _or_ `./csswg-test`.
+
+* You should now have a full copy of the test repository on your local
+ machine. Feel free to browse the directories on your hard drive. You can also
+ browse them on [github.com][github-w3c] and see the full history of contributions
+ there.
+
+### Clone the submodules
+
+* If you cloned the test repo and used the `--recursive` option, you'll find its submodules in `[repo-root]/resources/`.
+
+* If you cloned the the test repo and did not use the `--recursive` option, you will likely have an empty `resources` directory at the root of your cloned repo. You can clone the submodules with these additional steps:
+
+ $ cd test-repo-root
+ $ git submodule update --init --recursive
+
+ _You should now see the submodules in the repository. For example,_ `testharness` _files in should be in the resources directory._
+
+
+## Configure Remote / Upstream
+Synchronizing your forked repository with the W3C repository will enable you to
+keep your forked local copy up-to-date with the latest commits in the W3C
+repository.
+
+1. On the command line, navigate to to the directory where your forked copy of
+ the repository is located.
+
+2. Make sure that you are on the master branch. This will be the case if you
+ just forked, otherwise switch to master.
+
+ $ git checkout master
+
+3. Next, add the remote of the repository your forked. This assigns the
+ original repository to a remote called "upstream"
+
+ If you forked the [Web Platform Tests repository][main-repo]:
+
+ $ git remote add upstream https://github.com/w3c/web-platform-tests.git
+
+ If you forked the [CSSWG-test repository][css-repo]:
+
+ $ git remote add upstream https://github.com/w3c/csswg-test.git
+
+4. To pull in changes in the original repository that are not present in your
+ local repository first fetch them:
+
+ $ git fetch upstream
+
+ Then merge them into your local repository:
+
+ $ git merge upstream/master
+
+ For additional information, please see the [GitHub docs][github-fork-docs].
+
+## Branch
+
+Now that you have everything locally, create a branch for your tests.
+
+_Note: If you have already been through these steps and created a branch
+and now want to create another branch, you should always do so from the
+master branch. To do this follow the steps from the beginning of the [previous
+section][remote-upstream]. If you don't start with a clean master
+branch you will end up with a big nested mess._
+
+At the command line:
+
+ $ git checkout -b topic
+
+This will create a branch named `topic` and immediately
+switch this to be your active working branch.
+
+_The branch name should describe specifically what you are testing.
+For Example:_
+
+ $ git checkout -b flexbox-flex-direction-prop
+
+You're ready to start writing tests! Come back to this page you're ready to
+[commit][commit] them or [submit][submit] them for review.
+
+
+## Commit
+
+Before you submit your tests for review and contribution to the main test
+repo, you'll need to first commit them locally, where you now have your own
+personal version control system with git. In fact, as you are writing your
+tests, you may want to save versions of your work as you go before you submit
+them to be reviewed and merged.
+
+1. When you're ready to save a version of your work, go to the command
+ prompt and cd to the directory where your files are.
+
+2. First, ask git what new or modified files you have:
+
+ $ git status
+
+ _This will show you files that have been added or modified_.
+
+3. For all new or modified files, you need to tell git to add them to the
+ list of things you'd like to commit:
+
+ $ git add [file1] [file2] ... [fileN]
+
+ Or:
+
+ $ git add [directory_of_files]
+
+4. Run `git status` again to see what you have on the 'Changes to be
+ committed' list. These files are now 'staged'.
+
+5. Alternatively, you can run `git diff --staged`, which will show you the
+ diff of things to be committed.
+
+6. Once you've added everything, you can commit and add a message to this
+ set of changes:
+
+ $ git commit -m "Tests for indexed getters in the HTMLExampleInterface"
+
+7. Repeat these steps as many times as you'd like before you submit.
+
+## Submit
+
+If you're here now looking for more instructions, that means you've written
+some awesome tests and are ready to submit them. Congratulations and welcome
+back!
+
+1. The first thing you do before submitting them to the W3C repo is to push
+them back up to the server:
+
+ $ git push origin topic
+
+ _Note: Here,_ `origin` _refers to remote repo from which you cloned
+ (downloaded) the files after you forked, referred to as
+ web-platform-tests.git in the previous example;_
+ `topic` _refers to the name of your local branch that
+ you want to push_.
+
+2. Now you can send a message that you have changes or additions you'd like
+ to be reviewed and merged into the main (original) test repository. You do
+ this by using a pull request. In a browser, open the GitHub page for your
+ forked repository: **https://github.com/username/web-platform-tests**.
+
+3. Now create the pull request. There are several ways to create a PR in the
+GitHub UI. Below is one method and others can be found on
+[GitHub.com][github-createpr]
+
+ a. Click the ![pull request link][pullrequestlink] link on the right side
+ of the UI, then click the ![new pull request][pullrequestbtn] button.
+
+ b. On the left, you should see the base repo is the
+ w3c/web-platform-tests. On the right, you should see your fork of that
+ repo. In the branch menu of your forked repo, switch to
+ `topic`
+ **Note:** If you see _'There isn't anything to compare'_, click the
+ ![edit][editbtn] button and make sure your fork and your
+ `topic` branch is selected on the right side.
+
+ c. Select the ![create pull request][createprlink] link at the top.
+
+ d. Scroll down and review the diff
+
+ e. Scroll back up and in the Title field, enter a brief description for
+ your submission.
+
+ Example: "Tests for CSS Transforms skew() function."
+
+ f. If you'd like to add more detailed comments, use the comment field
+ below.
+
+ g. Click ![the send pull request button][sendpullrequest]
+
+
+4. Wait for feedback on your pull request and once your pull request is
+accepted, detele youre branch (see '
+[When Pull Request is Accepted][cleanup]').
+
+That's it! If you're currently at a Test the Web Forward event, find an
+expert nearby and ask for a review. If you're doing this on your own
+(AWESOME!), your pull request will go into a queue and will be reviewed
+soon.
+
+## Modify
+
+Once you submit your pull request, a reviewer will check your proposed changes
+for correctness and style. It is likely that this process will lead to some
+comments asking for modifications to your code. When you are ready to make the
+changes, follow these steps:
+
+1. Check out the branch corresponding to your changes e.g. if your branch was
+ called `topic`
+ run:
+
+ $ git checkout topic
+
+2. Make the changes needed to address the comments, and commit them just like
+ before.
+
+3. Push the changes to the remote branch containing the pull request:
+
+ $ git push origin topic
+
+4. The pull request will automatically be updated with the new commit. Note
+ for advanced users: it is generally discouraged to rebase your pull request
+ before review is complete. Tests typically have few conflicts so this
+ should not be a problem in the common case.
+
+Sometimes it takes multiple iterations through a review before the changes are
+finally accepted. Don't worry about this; it's totally normal. The goal of test
+review is to work together to create the best possible set of tests for the web
+platform.
+
+## Cleanup
+Once your pull request has been accepted, you will be notified in the GitHub
+UI and you may get an email. At this point, your changes have been merged
+into the main test repository. You do not need to take any further action
+on the test but you should delete your branch. This can easily be done in
+the GitHub UI by navigating to the pull requests and clicking the
+'Delete Branch' button.
+
+![pull request accepted delete branch][praccepteddelete]
+
+Alternatively, you can delete the branch on the command line.
+
+ $ git push origin --delete <branchName>
+
+## Tips & Tricks
+
+The following workflow is recommended:
+
+1. Start branch based on latest w3c/master
+2. Write tests
+3. Rebase onto latest w3c/master
+4. Submit tests
+5. Stop fiddling with the branch base until review is done
+6. After the PR has been accepted, delete the branch. (Every new PR should
+come from a new branch.)
+7. Synchronize your fork with the W3C repository by fetching your upstream and
+ merging it. (See '[Configure Remote / Upstream][remote-upstream]')
+
+You need to be able to set up remote upstream, etc. Please refer to [Pro Git
+Book][git-book] and enjoy reading.
+
+[branch]: #branch
+[commit]: #commit
+[clone]: #clone
+[css-repo]: https://github.com/w3c/csswg-test
+[forkbtn]: /assets/forkbtn.png
+[git]: http://git-scm.com/downloads
+[git-book]: http://git-scm.com/book
+[github]: https://github.com/
+[github-w3c]: https://github.com/w3c
+[github-fork-docs]: https://help.github.com/articles/fork-a-repo
+[github-createpr]: https://help.github.com/articles/creating-a-pull-request
+[help]: https://help.github.com/
+[main-repo]: https://github.com/w3c/web-platform-tests
+[password-caching]: https://help.github.com/articles/caching-your-github-password-in-git
+[pullrequestlink]: /assets/pullrequestlink.png
+[pullrequestbtn]: /assets/pullrequestbtn.png
+[editbtn]: /assets/editbtn.png
+[createprlink]: /assets/createprlink.png
+[sendpullrequest]: /assets/sendpullrequest.png
+[praccepteddelete]: /assets/praccepteddelete.png
+[submit]: #submit
+[remote-upstream]: #configure-remote-upstream
+[cleanup]: #cleanup
diff --git a/tests/wpt/web-platform-tests/docs/manual-test.md b/tests/wpt/web-platform-tests/docs/manual-test.md
new file mode 100644
index 00000000000..4b5469589fe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/docs/manual-test.md
@@ -0,0 +1,72 @@
+Some testing scenarios are intrinsically difficult to automate and
+require a human to run the test and check the pass condition.
+
+## When to Write Manual Tests
+
+Whenever possible it's best to write a fully automated test. For a
+browser vendor it's possible to run an automated test hundreds of
+times a day, but manual tests are likely to be run a handful of times
+a year. This makes them significantly less useful for catching
+regressions than automated tests.
+
+However, there are certain scenarios in which this is not yet
+possible. For example:
+
+* Tests that require interaction with browser security UI (e.g. a test
+ in which a user refuses a geolocation permissions grant)
+
+* Tests that require interaction with the underlying OS e.g. tests for
+ drag and drop from the desktop onto the browser
+
+* Tests that require non-default browser configuration e.g. images
+ disabled
+
+* Tests that require interaction with the physical environment
+ e.g. tests that the vibration API causes the device to vibrate or
+ that various sensor APIs respond in the expected way.
+
+There are also some rare cases where it isn't possible to write a layout
+test as a reftest, and a manual test must be written instead.
+
+## Requirements for a Manual Test
+
+Manual tests are distinguished by their filename; all manual tests
+have filenames of the form `name-manual.ext` i.e. a `-manual`
+suffix after the main filename but before the extension.
+
+Manual tests must be fully
+[self-describing](test-style-guielines.html#self-describing-tests). It
+is particularly important for these tests that it is easy to determine
+the result from the information presented to the tester, because a
+tester may have hundreds of tests to get through, and little
+understanding of the features that they are testing. Therefore
+minimalism is a virtue. An ideal self-describing test will have:
+
+* Step-by-step instructions for performing the test (if required)
+
+* A clear statement of the test outcome (if it can be automatically
+ determined after some setup) or of how to determine the outcome.
+
+Any information other than this (e.g. quotes from the spec) should be
+avoided.
+
+## Using testharness.js for Manual Tests
+
+A convenient way to present the results of a test that can have the
+result determined by script after some manual setup steps is to use
+testharness.js to determine and present the result. In this case one
+must pass `{explicit_timeout: true}` in a call to `setup()` in order
+to disable the automatic timeout of the test. For example:
+
+```html
+<!doctype html>
+<title>Manual click on button triggers onclick handler</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+setup({explicit_timeout: true})
+</script>
+<p>Click on the button below. If a "PASS" result appears the test
+passes, otherwise it fails</p>
+<button onclick="done()">Click Here</button>
+```
diff --git a/tests/wpt/web-platform-tests/docs/reftests.md b/tests/wpt/web-platform-tests/docs/reftests.md
new file mode 100644
index 00000000000..d92e3514a10
--- /dev/null
+++ b/tests/wpt/web-platform-tests/docs/reftests.md
@@ -0,0 +1,152 @@
+A reftest is a test that compares the visual output of one file (the
+test case) with the output of one or more other files (the
+references). The test and the reference must be carefully written so
+that when the test passes they have identical rendering, but different
+rendering when the test fails.
+
+## How to Run Reftests
+
+Reftests can be run manually simply by opening the test and the
+reference file in multiple windows or tabs and either placing them
+side-by side or flipping between the two. In automation the comparison
+is done in an automated fashion, which can lead to differences too
+small for the human eye to notice causing tests to fail.
+
+## Components of a Reftest
+
+In the simplest case, a reftest consists of a pair of files called the
+*test* and the *reference*.
+
+The *test* file is the one that makes use of the technology being
+tested. It also contains a `link` element with `rel="match"` or
+`rel="mismatch"` and `href` attribute pointing to the *reference* file
+e.g. `<link rel=match href=references/green-box-ref.html>`.
+
+The *reference* file is typically written to be as simple as possible,
+and does not use the technology under test. It is desirable that the
+reference be rendered correctly even in UAs with relatively poor
+support for CSS and no support for the technology under test.
+
+When the `<link>` element in the *test* has `rel="match"`, the test
+only passes if the *test* and *reference* have pixel-perfect identical
+rendering. `rel="mismatch"` inverts this so the test only passes when
+the renderings differ.
+
+In general the files used in a reftest should follow the
+[format][format] and [style][style] guidelines. The *test* should also
+be [self-describing][selfdesc], to allow a human to determine whether
+the the rendering is as expected.
+
+Note that references can be shared between tests; this is strongly
+encouraged since it permits optimizations when running tests.
+
+## Controlling When Comparison Occurs
+
+By default reftest screenshots are taken in response to the `load`
+event firing. In some cases it is necessary to delay the screenshot
+later than this, for example becase some DOM manipulation is
+required to set up the desired test conditions. To enable this, the
+test may have a `class="reftest-wait"` attribute specified on the root
+element. This will cause the screenshot to be delayed until the load
+event has fired and the reftest-wait class has been removed from the
+root element (technical note: the implementation in wptrunner uses
+mutation observers so the screenshot will be triggered in the
+microtask checkpoint after the class is removed. Because the harness
+isn't synchronized with the browser event loop it is dangerous to rely
+on precise timing here).
+
+## Matching Multiple References
+
+Sometimes it is desirable for a file to match multiple references or,
+in rare cases, to allow it to match more than one possible
+reference. Note: *this is not currently supported by test runners and
+so best avoided if possible until that support improves*.
+
+Multiple references linked from a single file are interpreted as
+multiple possible renderings for that file. `<link rel=[mis]match>`
+elements in a reference create further conditions that must be met in
+order for the test to pass. For example, consider a situation where
+a.html has `<link rel=match href=b.html>` and `<link rel=match
+href=c.html>`, b.html has `<link rel=match href=b1.html>` and c.html
+has `<link rel=mismatch href=c1.html>`. In this case, to pass we must
+either have a.html, b.html and b1.html all rendering identically, or
+a.html and c.html rendering identically, but c.html rendering
+differently from c1.html.
+
+## Fuzzy Matching
+
+In some situations a test may have subtle differences in rendering
+compared to the reference due to e.g. antialiasing. This may cause the
+test to pass on some platforms but fail on others. In this case some
+affordance for subtle discrepancies is desirable. However no mechanism
+to allow this has yet been standardized.
+
+## Limitations
+
+In some cases, a test cannot be a reftest. For example, there is no
+way to create a reference for underlining, since the position and
+thickness of the underline depends on the UA, the font, and/or the
+platform. However, once it's established that underlining an inline
+element works, it's possible to construct a reftest for underlining
+a block element, by constructing a reference using underlines on a
+```<span>``` that wraps all the content inside the block.
+
+## Example Reftests
+
+These examples are all [self-describing][selfdesc] tests as they
+each have a simple statement on the page describing how it should
+render to pass the tests.
+
+### HTML example
+
+### Test File
+
+This test verifies that a right-to-left rendering of **SAW** within a
+```<bdo>``` element displays as **WAS**.
+
+([view page rendering][html-reftest-example])
+
+```html
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>BDO element dir=rtl</title>
+<link rel="help" href="http://www.whatwg.org/specs/web-apps/current-work/#the-bdo-element">
+<meta name="assert" content="BDO element's DIR content attribute renders corrently given value of 'rtl'.">
+<link rel="match" href="test-bdo-001.html">
+<p>Pass if you see WAS displayed below.</p>
+<bdo dir="rtl">SAW</bdo>
+```
+
+### Reference File
+
+The reference file must look exactly like the test file,
+except that the code behind it is different.
+
+* All metadata is removed.
+* The ```title``` need not match.
+* The markup that created the actual test data is
+ different: here, the same effect is created with
+ very mundane, dependable technology.
+
+([view page rendering][html-reffile-example])
+
+```html
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Reference File</title>
+<p>Pass if you see WAS displayed below.</p>
+<p>WAS</p>
+```
+
+[testharness]: ./testharness-documentation.html
+[format]: ./test-format-guidelines.html
+[style]: ./test-style-guidelines.html
+[selfdesc]: ./test-style-guidelines.html#self-describing-tests
+[reference-links]: ./test-templates.html#reference-links
+[html-reftest-example]: ./html-reftest-example.html
+[html-reffile-example]: ./html-reffile-example.html
+[css-reftest-example]: http://test.csswg.org/source/css21/borders/border-bottom-applies-to-009.xht
+[css-reffile-example]: http://test.csswg.org/source/css21/borders/border-bottom-applies-to-001-ref.xht
+[svg-reftest-example]: http://test.csswg.org/source/css-transforms-1/translate/svg-translate-001.html
+[svg-reffile-example]: http://test.csswg.org/source/css-transforms-1/translate/reference/svg-translate-ref.html
+[indicating-failure]: ./test-style-guidelines.html#failure
diff --git a/tests/wpt/web-platform-tests/docs/review-checklist.md b/tests/wpt/web-platform-tests/docs/review-checklist.md
new file mode 100644
index 00000000000..f6d490d3d89
--- /dev/null
+++ b/tests/wpt/web-platform-tests/docs/review-checklist.md
@@ -0,0 +1,122 @@
+When reviewing a test, make sure the test follows the
+[format][format] and [style][style] guidelines.
+
+In addition, the test should be checked for the following:
+
+## All tests
+<input type="checkbox">
+The test passes when it's supposed to pass
+
+<input type="checkbox">
+The test fails when it's supposed to fail
+
+<input type="checkbox">
+The test is testing what it thinks it's testing
+
+<input type="checkbox">
+The spec backs up the expected behavior in the test.
+
+<input type="checkbox">
+The test is automated as either [reftest][reftest] or a
+[script test][scripttest] unless there's a very good reason why the
+test must be manual.
+
+<input type="checkbox">
+The test does not use external resources.
+
+<input type="checkbox">
+The test does not use proprietary features (vendor-prefixed or otherwise).
+
+
+## Reftests Only
+<input type="checkbox">
+The test has a [self-describing][selftest] statement
+
+<input type="checkbox">
+The self-describing statement is accurate, precise, simple, and
+self-explanatory. Your mother/husband/roommate/brother/bus driver
+should be able to say whether the test passed or failed within a few
+seconds, and not need to spend several minutes thinking or asking
+questions.
+
+<input type="checkbox">
+The reference file is accurate and will render pixel-perfect
+identically to the test on all platforms.
+
+<input type="checkbox">
+The reference file uses a different technique that won't fail in
+the same way as the test.
+
+<input type="checkbox">
+The title is descriptive but not too wordy.
+
+<input type="checkbox">
+The test is as cross-platform as reasonably possible, working
+across different devices, screen resolutions, paper sizes, etc. If
+there are limitations (e.g. the test will only work on 96dpi
+devices, or screens wider than 200 pixels) that these are documented
+in the instructions.
+
+
+## Script Tests Only
+
+<input type="checkbox">
+The test uses the most specific asserts possible (e.g. doesn't use
+`assert_true` for everything).
+
+<input type="checkbox">
+The number of tests in each file and the test names are consistent
+across runs and browsers. It is best to avoid the pattern where there is
+a test that asserts that the feature is supported and bails out without
+running the rest of the tests in the file if it isn't.
+
+<input type="checkbox">
+The test avoids patterns that make it less likely to be stable.
+In particular, tests should avoid setting internal timeouts, since the
+time taken to run it may vary on different devices; events should be used
+instead (if at all possible).
+
+<input type="checkbox">
+The test uses `idlharness.js` if it covers the use case.
+
+<input type="checkbox">
+Tests in a single file are separated by one empty line.
+
+
+## In depth Checklist
+
+<input type="checkbox">
+A test does not use self-closing start tag ("/" (U+002F)) when using the
+HTML syntax.
+
+<input type="checkbox">
+The test does not use the Unicode byte order mark (BOM U+FEFF). The test
+uses Unix line endings (LF, no CR). The executable bit is not set
+unnecessarily.
+
+<input type="checkbox">
+For indentation, spaces are preferred over tabs.
+
+<input type="checkbox">
+The test does not contain trailing whitespace (whitespace at the end of
+lines).
+
+<input type="checkbox">
+The test does not contain commented-out code.
+
+<input type="checkbox">
+The test is placed in the relevant directory, based on the /TR latest
+version link if available.
+
+<input type="checkbox">
+If the test needs code running on the server side, the server code must
+be written in python, and the python code must be reviewed carefully to
+ensure it isn't doing anything dangerous.
+
+
+
+[format]: ./test-format-guidelines.html
+[style]: ./test-style-guidelines.html
+[reftest]: ./reftests.html
+[scripttest]: ./testharness-documentation.html
+[selftest]: ./test-style-guidelines.html#self-describing
diff --git a/tests/wpt/web-platform-tests/docs/review-process.md b/tests/wpt/web-platform-tests/docs/review-process.md
new file mode 100644
index 00000000000..e983bb2f333
--- /dev/null
+++ b/tests/wpt/web-platform-tests/docs/review-process.md
@@ -0,0 +1,56 @@
+## Test Review Policy
+
+In order to encourage a high level of quality in the W3C test
+suites, test contributions must be reviewed by a peer.
+
+The reviewer can be anyone (other than the original test author) that
+has the required experience with both the spec under test and with the
+test [format][format] and [style][style] guidelines. Review must
+happen in public, but the exact review location is flexible. In
+particular if a vendor is submitting tests that have already been
+reviewed in their own review system, that review may be carried
+forward, as long as the original review is clearly linked in the
+GitHub pull request.
+
+To assist with test reviews, a [review checklist][review-checklist]
+is available.
+
+## Review Tools
+
+All new code submissions must use the GitHub pull request
+workflow. The GitHub UI for code review may be used, but other tools
+may also be used as long as the review is clearly linked.
+
+### Critic
+
+[Critic][critic] is a code review tool that is frequently used for
+reviewing web-platform-tests sumbissions. Although it has a steeper
+learning curve than the GitHub tools, it has more features that aid in
+conducting non-trivial reviews.
+
+If you want to use Critic to review code, visit the [homepage][critic]
+and log (authentication is via GitHub). On the homepage, click "Add
+Filter". In the resulting dialog, select the web-platform-tests
+repository and add the path of the folder(s) where you want to review
+code, e.g. `/` to review any submissions or `XMLHttpRequest/` to
+review only submissions in the XHMLHttpRequest directory. Ensure that
+your email address is added so that you receive notifications of new
+reviews matching your filters, and activity on existing reviews.
+
+## Labels
+
+Pull requests get automatically labelled in the Github repository. Check
+out the [list of labels in Github][issues]
+to see the open pull requests for a given specification or a given Working Group.
+
+## Status
+
+The
+[web-platform-tests dashboard](http://testthewebforward.org/dashboard/#all)
+shows the number of open review requests, and can be filtered by testsuite.
+
+[format]: ./test-format-guidelines.html
+[style]: ./test-style-guidelines.html
+[review-checklist]: ./review-checklist.html
+[issues]: https://github.com/w3c/web-platform-tests/issues
+[critic]: https://critic.hoppipolla.co.uk
diff --git a/tests/wpt/web-platform-tests/docs/running_tests.md b/tests/wpt/web-platform-tests/docs/running_tests.md
new file mode 100644
index 00000000000..affbc90059d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/docs/running_tests.md
@@ -0,0 +1,34 @@
+In simple cases individual tests can be run by simply loading the page
+in a browser window. For running larger groups of tests, or running
+tests frequently, this is not a practical approach, and several better
+options exist.
+
+## From Inside a Browser
+
+For running multiple tests inside a browser, there is the test runner,
+located at
+
+ /tools/runner/index.html
+
+This allows all the tests, or those matching a specific prefix
+(e.g. all tests under `/dom/`) to be run. For testharness.js tests,
+the results will be automatically collected, whilst the runner
+provides a simple UI for manually comparing reftest rendering and
+running manual tests.
+
+Because it runs entirely in-browser, this runner cannot deal with
+edge-cases like tests that cause the browser to crash or hang.
+
+## By Automating the Browser
+
+For automated test running designed to be robust enough to use in a CI
+environment, the [wptrunner](http://github.com/w3c/wptrunner) test runner
+can be used. This is a test runner written in Python and designed to
+control the browser from the outside using some remote control
+protocol such as WebDriver. This allows it to handle cases such as the
+browser crashing that connot be handled by an in-browser harness. It
+also has the ability to automatically run both testharness-based tests
+and reftests.
+
+Full instructions for using wptrunner are provided in its own
+[documentation](http://wptrunner.readthedocs.org).
diff --git a/tests/wpt/web-platform-tests/docs/submission-process.md b/tests/wpt/web-platform-tests/docs/submission-process.md
new file mode 100644
index 00000000000..fd5d763ba76
--- /dev/null
+++ b/tests/wpt/web-platform-tests/docs/submission-process.md
@@ -0,0 +1,42 @@
+Test submission is via the typical GitHub workflow.
+
+* Fork the [GitHub repository][repo] (and make sure you're still relatively in
+sync with it if you forked a while ago)
+
+* Create a branch for your changes. Being a key of effective Git flow, it is
+strongly recommended that the **topic branch** tradition be followed here,
+i.e. the branch naming convention is based on the "topic" you will be working
+on, e.g. `git checkout -b topic-name`
+
+* Make your changes
+
+* Run the `lint` script in the root of your checkout to detect common
+ mistakes in test submissions. This will also be run after submission
+ and any errors will prevent your PR being accepted. If it detects an
+ error that forms an essential part of your test, edit the list of
+ exceptions stored in `tools/lint/lint.whitelist`.
+
+* Commit your changes.
+
+* Push your local branch to your GitHub repository.
+
+* Using the GitHub UI create a Pull Request for your branch.
+
+* When you get review comments, make more commits to your branch to
+ address the comments (**note**: Do *not* rewrite existing commits using
+ e.g. `git commit --amend` or `git rebase -i`. The review system
+ depends on the full branch history).
+
+* Once everything is reviewed and all issues are addressed, your pull
+ request will be automatically merged.
+
+For detailed guidelines on setup and each of these steps, please refer to the
+[Github Test Submission][github101] documentation.
+
+Hop on to [irc or the mailing list][discuss] if you have an
+issue. There is no need to announce your review request, as soon as
+you make a Pull Request GitHub will inform interested parties.
+
+[repo]: https://github.com/w3c/web-platform-tests/
+[github101]: ./github-101.html
+[discuss]: /discuss.html
diff --git a/tests/wpt/web-platform-tests/docs/test-format-guidelines.md b/tests/wpt/web-platform-tests/docs/test-format-guidelines.md
new file mode 100644
index 00000000000..4c7a3572fc2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/docs/test-format-guidelines.md
@@ -0,0 +1,324 @@
+This page describes the available test types and the requirements for
+authoring that apply to all test types. There is also a supplementary
+[guide to writing good testcases](test-style-guidelines.html).
+
+## Test Locations
+
+Each top level directory in the repository corresponds to tests for a
+single specification. For W3C specs, these directories are named after
+the shortname of the spec (i.e. the name used for snapshot
+publications under `/TR/`).
+
+Within the specification-specific directory there are two common ways
+of laying out tests. The first is a flat structure which is sometimes
+adopted for very short specifications. The alternative is a nested
+structure with each subdirectory corresponding to the id of a heading
+in the specification. This layout provides some implicit metadata
+about the part of a specification being tested according to its
+location in the filesystem, and is preferred for larger
+specifications.
+
+When adding new tests to existing specifications, try to follow the
+structure of existing tests.
+
+Because of path length limitations on Windows, test paths must be less
+that 150 characters relative to the test root directory (this gives
+vendors just over 100 characters for their own paths when running in
+automation).
+
+## Choosing the Test Type
+
+Tests should be written using the mechanism that is most conducive to
+running in automation. In general the following order of preference holds:
+
+* [idlharness.js](testharness-idlharness.html) tests - for testing
+ anything in a WebIDL block.
+
+* [testharness.js](testharness.html) tests - for any test that can be
+ written using script alone.
+
+* [Reftests][reftests] - for most tests of rendering.
+
+* WebDriver tests - for testing the webdriver protocol itself or (in
+ the future) for certain tests that require access to privileged APIs.
+
+* Manual tests - as a last resort for anything that can't be tested
+ using one of the above techniques.
+
+Some scenarios demand certain test types. For example:
+
+* Tests for layout will generally be reftests. In some cases it will
+ not be possible to construct a reference and a test that will always
+ render the same, in which case a manual test, accompanied by
+ testharness tests that inspect the layout via the DOM must be
+ written.
+
+* Features that require human interaction for security reasons
+ (e.g. to pick a file from the local filesystem) typically have to be
+ manual tests.
+
+## General Test Design Requirements
+
+### Short
+
+Tests should be as short as possible. For reftests in particular
+scrollbars at 800&#xD7;600px window size must be avoided unless scrolling
+behaviour is specifically being tested. For all tests extraneous
+elements on the page should be avoided so it is clear what is part of
+the test (for a typical testharness test, the only content on the page
+will be rendered by the harness itself).
+
+### Minimal
+
+Tests should generally avoid depending on edge case behaviour of
+features that they don't explicitly intend to test. For example,
+except where testing parsing, tests should contain no
+[parse errors][validator]. Of course tests which intentionally address
+the interactions between multiple platform features are not only
+acceptable but encouraged.
+
+### Cross-platform
+
+Tests should be as cross-platform as reasonably possible, working
+across different devices, screen resolutions, paper sizes, etc.
+Exceptions should document their assumptions.
+
+### Self-Contained
+
+Tests must not depend on external network resources, including
+w3c-test.org. When these tests are run on CI systems they are
+typically configured with access to external resources disabled, so
+tests that try to access them will fail. Where tests want to use
+multiple hosts this is possible thorough a known set of subdomains and
+features of wptserve (see
+["Tests Involving Multiple Origins"](#tests-involving-multiple-origins)).
+
+## File Names
+
+Generally file names should be somewhat descriptive of what is being
+tested; very generic names like `001.html` are discouraged. A common
+format, required by CSS tests, is described in
+[CSS Naming Conventions](css-naming.html).
+
+## File Formats
+
+Tests must be HTML, XHTML or SVG files.
+
+Note: For CSS tests, the test source will be parsed and
+re-serialized. This re-serialization will cause minor changes to the
+test file, notably: attribute values will always be quoted, whitespace
+between attributes will be collapsed to a single space, duplicate
+attributes will be removed, optional closing tags will be inserted,
+and invalid markup will be normalized. If these changes should make
+the test inoperable, for example if the test is testing markup error
+recovery, add the [flag][requirement-flags] 'asis' to prevent
+re-serialization. This flag will also prevent format conversions so it
+may be necessary to provide alternate versions of the test in other
+formats (XHTML, HTML, etc.)
+
+## Character Encoding
+
+Except when specifically testing encoding, tests must be encoded in
+UTF-8, marked through the use of e.g. `<meta charset=utf-8>`, or in
+pure ASCII.
+
+## Support files
+
+Various support files are available in in the `/common/` and `/media/`
+directories (web-platform-tests) and `/support/` (CSS). Reusing
+existing resources is encouraged where possible, as is adding
+generally useful files to these common areas rather than to specific
+testsuites.
+
+For CSS tests the following standard images are available in the
+support directory:
+
+ * 1x1 color swatches
+ * 15x15 color swatches
+ * 15x15 bordered color swatches
+ * assorted rulers and red/green grids
+ * a cat
+ * a 4-part picture
+
+## Tools
+Sometimes you may want to add a script to the repository that's meant
+to be used from the command line, not from a browser (e.g., a script
+for generating test files). If you want to ensure (e.g., or security
+reasons) that such scripts won't be handled by the HTTP server, but
+will instead only be usable from the command line, then place them
+in either:
+
+* the `tools` subdir at the root of the repository, or
+* the `tools` subdir at the root of any top-level directory in the
+ repo which contains the tests the script is meant to be used with
+
+Any files in those `tools` directories won't be handled by the HTTP
+server; instead the server will return a 404 if a user navigates to
+the URL for a file within them.
+
+If you want to add a script for use with a particular set of tests
+but there isn't yet any `tools` subdir at the root of a top-level
+directory in the repository containing those tests, you can create
+a `tools` subdir at the root of that top-level directory and place
+your scripts there.
+
+For example, if you wanted to add a script for use with tests in the
+`notifications` directory, create the `notifications/tools` subdir
+and put your script there.
+
+## Style Rules
+
+A number of style rules should be applied to the test file. These are
+not uniformly enforced throughout the existing tests, but will be for
+new tests. Any of these rules may be broken if the test demands it:
+
+ * No trailing whitespace
+
+ * Use spaces rather than tabs for indentation
+
+ * Use UNIX-style line endings (i.e. no CR characters at EOL).
+
+## Advanced Testing Features
+
+Certain test scenarios require more than just static HTML
+generation. This is supported through the
+[wptserve](http://github.com/w3c/wptserve) server. Several scenarios
+in particular are common:
+
+### Standalone workers tests
+
+Tests that only require assertions in a dedicated worker scope can use
+standalone workers tests. In this case, the test is a JavaScript file
+with extension `.worker.js` that imports `testharness.js`. The test can
+then use all the usual APIs, and can be run from the path to the
+JavaScript file with the `.js` removed.
+
+For example, one could write a test for the `Blob` constructor by
+creating a `FileAPI/Blob-constructor.worker.js` as follows:
+
+ importScripts("/resources/testharness.js");
+ test(function () {
+ var blob = new Blob();
+ assert_equals(blob.size, 0);
+ assert_equals(blob.type, "");
+ assert_false(blob.isClosed);
+ }, "The Blob constructor.");
+ done();
+
+This test could then be run from `FileAPI/Blob-constructor.worker`.
+
+### Tests Involving Multiple Origins
+
+In the test environment, five subdomains are available; `www`, `www1`,
+`www2`, `天気の良い日` and `élève`. These must be used for
+cross-origin tests. In addition two ports are available for http and
+one for websockets. Tests must not hardcode the hostname of the server
+that they expect to be running on or the port numbers, as these are
+not guaranteed by the test environment. Instead tests can get this
+information in one of two ways:
+
+* From script, using the `location` API.
+
+* By using a textual substitution feature of the server.
+
+In order for the latter to work, a file must either have a name of the
+form `{name}.sub.{ext}` e.g. `example-test.sub.html` or be referenced
+through a URL containing `pipe=sub` in the query string
+e.g. `example-test.html?pipe=sub`. The substitution syntax uses {% raw %} `{{
+}}` {% endraw %} to delimit items for substitution. For example to substitute in
+the host name on which the tests are running, one would write:
+
+{% raw %}
+ {{host}}
+{% endraw %}
+
+As well as the host, one can get full domains, including subdomains
+using the `domains` dictionary. For example:
+
+{% raw %}
+ {{domains[www]}}
+{% endraw %}
+
+would be replaced by the fully qualified domain name of the `www`
+subdomain. Ports are also available on a per-protocol basis e.g.
+
+{% raw %}
+ {{ports[ws][0]}}
+{% endraw %}
+
+is replaced with the first (and only) websockets port, whilst
+
+{% raw %}
+ {{ports[http][1]}}
+{% endraw %}
+
+is replaced with the second HTTP port.
+
+The request URL itself can be used as part of the substitution using
+the `location` dictionary, which has entries matching the
+`window.location` API. For example
+
+{% raw %}
+ {{location[host]}}
+{% endraw %}
+
+is replaced by hostname:port for the current request.
+
+### Tests Requiring Special Headers
+
+For tests requiring that a certain HTTP header is set to some static
+value, a file with the same path as the test file except for an an
+additional `.headers` suffix may be created. For example for
+`/example/test.html`, the headers file would be
+`/example/test.html.headers`. This file consists of lines of the form
+
+ header-name: header-value
+
+For example
+
+ Content-Type: text/html; charset=big5
+
+To apply the same headers to all files in a directory use a
+`__dir__.headers` file. This will only apply to the immediate
+directory and not subdirectories.
+
+Headers files may be used in combination with substitutions by naming
+the file e.g. `test.html.sub.headers`.
+
+### Tests Requiring Full Control Over The HTTP Response
+
+For full control over the request and response the server provides the
+ability to write `.asis` files; these are served as literal HTTP
+responses. It also provides the ability to write python scripts that
+have access to request data and can manipulate the content and timing
+of the response. For details see the
+[wptserve documentation](http://wptserve.readthedocs.org).
+
+## CSS-Specific Requirements
+
+Tests for CSS specs have some additional requirements that have to be
+met in order to be included in an official specification testsuite.
+
+* [Naming conventions](css-naming.html)
+
+* [User style sheets](css-user-styles.html)
+
+* [Metadata](css-metadata.html)
+
+## Test Lint
+
+A lint tool is available to catch common mistakes in tests. It may be
+run from the web-platform-tests home directory using:
+
+ python tools/script/lint.py
+
+The lint is run automatically on every pull request and any violations
+of the rules will be regarded as an error. In order to silence
+unwanted linter errors, add the error to the whitelist in
+`tools/scripts/lint.whitelist`.
+
+[reftests]: ./reftests.html
+[test-templates]: ./test-templates.html
+[requirement-flags]: ./test-templates.html#requirement-flags
+[testharness-documentation]: ./testharness-documentation.html
+[validator]: http://validator.w3.org
diff --git a/tests/wpt/web-platform-tests/docs/test-style-guidelines.md b/tests/wpt/web-platform-tests/docs/test-style-guidelines.md
new file mode 100644
index 00000000000..77a75357dfd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/docs/test-style-guidelines.md
@@ -0,0 +1,438 @@
+## Key Aspects of a Well Designed Test
+
+A badly written test can lead to false passes or false failures, as
+well as inaccurate interpretations of the specs. Therefore it is
+important that the tests all be of a high standard. All tests must
+follow the [test format guidelines][test-format] and well designed
+tests should meet the following criteria:
+
+* **The test passes when it's supposed to pass**
+* **The test fails when it's supposed to fail**
+* **It's testing what it claims to be testing**
+
+## Self-Describing Tests
+
+As the tests are likely to be used by many other people, making them
+easy to understand is very important. Ideally, tests are written as
+self-describing, which is a test page that describes what the page
+should look like when the test has passed. A human examining the
+test page can then determine from the description whether the test
+has passed or failed.
+
+_Note: The terms "the test has passed" and "the test has failed"
+refer to whether the user agent has passed or failed a
+particular test — a test can pass in one web browser and fail in
+another. In general, the language "the test has passed" is used
+when it is clear from context that a particular user agent is
+being tested, and the term "this-or-that-user-agent has passed
+the test" is used when multiple user agents are being compared._
+
+Self-describing tests have some advantages:
+
+* They can be run easily on any layout engine.
+* They can test areas of the spec that are not precise enough to be
+ comparable to a reference rendering. (For example, underlining
+ cannot be compared to a reference because the position and
+ thickness of the underline is UA-dependent.)
+* Failures can (should) be easily determined by a human viewing the
+ test without needing special tools.
+
+### Manual Tests
+
+While it is highly encouraged to write automatable tests either as [
+reftests][reftests] or [script tests][scripttests], in rare cases a
+test can only be executed manually. All manual tests must be
+self-describing tests. Additionally, manual tests should be:
+
+* Easy & quick to determine the result
+* Self explanatory & not require an understanding of the
+ specification to determine the result
+* Short (a paragraph or so) and certainly not require scrolling
+ on even the most modest of screens, unless the test is
+ specifically for scrolling or paginating behaviour.
+
+### Reftests
+
+[Reftests][reftests] should be self-describing tests wherever
+possible. This means the the descriptive statement included in the
+test file must also appear in the reference file so their renderings
+may be automatically compared.
+
+### Script Tests
+
+[Script tests][scripttests] may also be self-describing, but rather
+than including a supplemental statement on the page, this is
+generally done in the test results output from ```testharness.js```.
+
+### Self-Describing Test Examples
+
+The following are some examples of self-describing tests, using some
+common [techniques](#techniques) to identify passes:
+
+* [Identical Renderings][identical-renderings]
+* [Green Background][green-background]
+* [No Red 1][no-red-1]
+* [No Red 2][no-red-2]
+* [Described Alignment][described-alignment]
+* [Overlapping][overlapping]
+* [Imprecise Description 1][imprecise-1]
+* [Imprecise Description 2][imprecise-2]
+
+## Techniques
+
+In addition to the [self describing](#self-describing) statement
+visible in the test, there are many techniques commonly used to add
+clarity and robustness to tests. Particularly for reftests, which
+rely wholly on how the page is rendered, the following should be
+considered and used when designing new tests.
+
+### Indicating success
+
+#### The green paragraph
+
+This is the simplest form of test, and is most often used when
+testing the things that are independent of the rendering, like
+the CSS cascade or selectors. Such tests consist of a single line of
+text describing the pass condition, which will be one of the
+following:
+
+<span style="color: green">This line should be green.</span>
+
+<span style="border: 5px solid green">This line should have a green
+ border.</span>
+
+<span style="background: green; color: white">This line should have
+ a green background.</span>
+
+#### The green page
+
+This is a variant on the green paragraph test. There are certain
+parts of CSS that will affect the entire page, when testing these
+this category of test may be used. Care has to be taken when writing
+tests like this that the test will not result in a single green
+paragraph if it fails. This is usually done by forcing the short
+descriptive paragraph to have a neutral color (e.g. white).
+
+This [example][green-page] is poorly designed, because it does not
+look red when it has failed.
+
+#### The green square
+
+This is the best type of test for cases where a particular rendering
+rule is being tested. The test usually consists of two boxes of some
+kind that are (through the use of positioning, negative margins,
+zero line height, transforms, or other mechanisms) carefully placed
+over each other. The bottom box is colored red, and the top box is
+colored green. Should the top box be misplaced by a faulty user
+agent, it will cause the red to be shown. (These tests sometimes
+come in pairs, one checking that the first box is no bigger than the
+second, and the other checking the reverse.) These tests frequently
+look like:
+
+<p>Test passes if there is a green square and no red.</p>
+<div style="width: 100px; height: 100px; background: green"></div>
+
+#### The green paragraph and the blank page
+
+These tests appear to be identical to the green paragraph tests
+mentioned above. In reality, however, they actually have more in
+common with the green square tests, but with the green square
+colored white instead. This type of test is used when the
+displacement that could be expected in the case of failure is
+likely to be very small, and so any red must be made as obvious as
+possible. Because of this, test would appear totally blank when the
+test has passed. This is a problem because a blank page is the
+symptom of a badly handled network error. For this reason, a single
+line of green text is added to the top of the test, reading
+something like:
+
+<p style="color: green">This line should be green and there should
+be no red on this page.</p>
+[Example][green-paragraph]
+
+#### The two identical renderings
+
+It is often hard to make a test that is purely green when the test
+passes and visibly red when the test fails. For these cases, it may
+be easier to make a particular pattern using the feature that is
+being tested, and then have a reference rendering next to the test
+showing exactly what the test should look like.
+
+The reference rendering could be either an image, in the case where
+the rendering should be identical, to the pixel, on any machine, or
+the same pattern made using different features. (Doing the second
+has the advantage of making the test a test of both the feature
+under test and the features used to make the reference rendering.)
+
+[Visual Example 1][identical-visual-1]
+
+[Visual Example 2][identical-visual-2]
+
+[Text-only Example][identical-text]
+
+### Indicating failure
+
+In addition to having clearly defined characteristics when
+they pass, well designed tests should have some clear signs when
+they fail. It can sometimes be hard to make a test do something only
+when the test fails, because it is very hard to predict how user
+agents will fail! Furthermore, in a rather ironic twist, the best
+tests are those that catch the most unpredictable failures!
+
+Having said that, here are the best ways to indicate failures:
+
+#### Red
+
+Using the color red is probably the best way of highlighting
+failures. Tests should be designed so that if the rendering is a few
+pixels off some red is uncovered or otherwise rendered on the page.
+
+[Visual Example][red-visual]
+
+[Text-only Example][red-text]
+
+_View the pages' source to see the usage of the color
+red to denote failure._
+
+#### Overlapped text
+
+Tests of the 'line-height', 'font-size' and similar properties can
+sometimes be devised in such a way that a failure will result in the
+text overlapping.
+
+#### The word "FAIL"
+
+Some properties lend themselves well to this kind of test, for
+example 'quotes' and 'content'. The idea is that if the word "FAIL"
+appears anywhere, something must have gone wrong.
+
+[Example][fail-example]
+
+_View the page's source to see the usage of the word FAIL._
+
+### Special Fonts
+
+#### Ahem
+Todd Fahrner has developed a font called [Ahem][ahem-readme], which
+consists of some very well defined glyphs of precise sizes and
+shapes. This font is especially useful for testing font and text
+properties. Without this font it would be very hard to use the
+overlapping technique with text.
+
+The font's em-square is exactly square. It's ascent and descent is
+exactly the size of the em square. This means that the font's extent
+is exactly the same as its line-height, meaning that it can be
+exactly aligned with padding, borders, margins, and so forth.
+
+The font's alphabetic baseline is 0.2em above its bottom, and 0.8em
+below its top.
+
+The font has four glyphs:
+
+* X U+0058 A square exactly 1em in height and width.
+* p U+0070 A rectangle exactly 0.2em high, 1em wide, and aligned so
+that its top is flush with the baseline.
+* É U+00C9 A rectangle exactly 0.8em high, 1em wide, and aligned so
+that its bottom is flush with the baseline.
+* U+0020 A transparent space exactly 1em high and wide.
+
+Most other US-ASCII characters in the font have the same glyph as X.
+
+#### Ahem Usage
+__If the test uses the Ahem font, make sure its computed font-size
+is a multiple of 5px__, otherwise baseline alignment may be rendered
+inconsistently (due to rounding errors introduced by certain
+platforms' font APIs). We suggest to use a minimum computed font-
+size of 20px.
+
+E.g. Bad:
+
+``` css
+{font: 1in/1em Ahem;} /* Computed font-size is 96px */
+{font: 1in Ahem;}
+{font: 1em/1em Ahem} /* with computed 1em font-size being 16px */
+{font: 1em Ahem;} /* with computed 1em font-size being 16px */
+```
+
+E.g. Good:
+
+``` css
+{font: 100px/1 Ahem;}
+{font: 1.25em/1 Ahem;} /* with computed 1.25em font-size being 20px
+*/
+```
+
+__If the test uses the Ahem font, make sure the line-height on block
+elements is specified; avoid 'line-height: normal'__. Also, for
+absolute reliability, the difference between computed line-height
+and computed font-size should be dividable by 2.
+
+E.g. Bad:
+
+``` css
+{font: 1.25em Ahem;} /* computed line-height value is 'normal' */
+{font: 20px Ahem;} /* computed line-height value is 'normal' */
+{font-size: 25px; line-height: 50px;} /* the difference between
+computed line-height and computed font-size is not dividable by 2. */
+```
+
+E.g. Good:
+
+``` css
+{font-size: 25px; line-height: 51px;} /* the difference between
+computed line-height and computed font-size is dividable by 2. */
+```
+
+[Example test using Ahem][ahem-example]
+
+_View the page's source to see how the Ahem font is used._
+
+
+##### Installing Ahem
+
+1. Download the [TrueType version of Ahem][download-ahem].
+2. Open the folder where you downloaded the font file.
+3. Right-click the downloaded font file and select "Install".
+
+### Explanatory Text
+
+For tests that must be long (e.g. scrolling tests), it is important
+to make it clear that the filler text is not relevant, otherwise the
+tester may think he is missing something and therefore waste time
+reading the filler text. Good text for use in these situations is,
+quite simply, "This is filler text. This is filler text. This is
+filler text.". If it looks boring, it's working!
+
+### Color
+
+In general, using colors in a consistent manner is recommended.
+Specifically, the following convention has been developed:
+
+#### Red
+Any red indicates failure.
+
+#### Green
+In the absence of any red, green indicates success.
+
+#### Blue
+Tests that do not use red or green to indicate success or failure
+should use blue to indicate that the tester should read the text
+carefully to determine the pass conditions.
+
+#### Black
+Descriptive text is usually black.
+
+#### Fuchsia, Yellow, Teal, Orange
+These are useful colors when making complicated patterns for tests
+of the two identical renderings type.
+
+#### Dark Gray
+Descriptive lines, such as borders around nested boxes, are usually
+dark gray. These lines come in useful when trying to reduce the test
+for engineers.
+
+#### Silver / Light Gray
+
+Sometimes used for filler text to indicate that it is irrelevant.
+
+### Methodical testing
+
+Some web features can be tested quite thoroughly with a very
+methodical approach. For example, testing that all the length units
+work for each property taking lengths is relatively easy, and can be
+done methodically simply by creating a test for each property/unit
+combination.
+
+In practice, the important thing to decide is when to be methodical
+and when to simply test, in an ad hoc fashion, a cross section of
+the possibilities.
+
+This example is a methodical test of the :not() pseudo-class with
+each attribute selector in turn, first for long values and then for
+short values:
+
+http://www.hixie.ch/tests/adhoc/css/selectors/not/010.xml
+
+### Overlapping
+
+This technique should not be cast aside as a curiosity -- it is in
+fact one of the most useful techniques for testing CSS, especially
+for areas like positioning and the table model.
+
+The basic idea is that a red box is first placed using one set of
+properties, e.g. the block box model's margin, height and width
+properties, and then a second box, green, is placed on top of the
+red one using a different set of properties, e.g. using absolute
+positioning.
+
+This idea can be extended to any kind of overlapping, for example
+overlapping to lines of identical text of different colors.
+
+## Tests to avoid
+
+### The long test
+
+Any manual test that is so long that is needs to be scrolled to be
+completed is too long. The reason for this becomes obvious when you
+consider how manual tests will be run. Typically, the tester will be
+running a program (such as "Loaderman") which cycles through a list
+of several hundred tests. Whenever a failure is detected, the tester
+will do something (such as hit a key) that takes a note of the test
+case name. Each test will be on the screen for about two or three
+seconds. If the tester has to scroll the page, that means he has to
+stop the test to do so.
+
+Of course, there are exceptions -- the most obvious one being any
+tests that examine the scrolling mechanism! However, these tests are
+considered tests of user interaction and are not run with the
+majority of the tests.
+
+Any test that is so long that it needs scrolling can usually be
+split into several smaller tests, so in practice this isn't much of
+a problem.
+
+This is an [example][long-test] of a test that is too long.
+
+### The counterintuitive "this should be red" test
+
+As mentioned many times in this document, red indicates a bug, so
+nothing should ever be red in a test.
+
+There is one important exception to this rule... the test for the
+'red' value for the color properties!
+
+### Unobvious tests
+
+A test that has half a sentence of normal text with the second half
+bold if the test has passed is not very obvious, even if the
+sentence in question explains what should happen.
+
+There are various ways to avoid this kind of test, but no general
+rule can be given since the affected tests are so varied.
+
+The last [subtest on this page][unobvious-test] shows this problem.
+
+[test-format]: ./test-format-guidelines.html
+[reftests]: ./reftests.html
+[scripttests]: ./testharness-documentation.html
+[identical-renderings]: http://test.csswg.org/source/css21/syntax/escapes-000.xht
+[green-background]: http://test.csswg.org/source/css21/syntax/escapes-002.xht
+[no-red-1]: http://test.csswg.org/source/css21/positioning/abspos-containing-block-003.xht
+[no-red-2]: http://test.csswg.org/source/css21/tables/border-conflict-w-079.xht
+[described-alignment]: http://test.csswg.org/source/css21/margin-padding-clear/margin-collapse-clear-007.xht
+[overlapping]: http://test.csswg.org/source/css21/tables/table-anonymous-objects-021.xht
+[imprecise-1]: http://test.csswg.org/source/css21/tables/border-style-inset-001.xht
+[imprecise-2]: http://test.csswg.org/source/css21/text/text-decoration-001.xht
+[green-page]: http://www.hixie.ch/tests/adhoc/css/background/18.xml
+[green-paragraph]: http://www.hixie.ch/tests/adhoc/css/fonts/size/002.xml
+[identical-visual-1]: http://test.csswg.org/source/css21/floats-clear/margin-collapse-123.xht
+[identical-visual-2]: http://test.csswg.org/source/css21/normal-flow/inlines-016.xht
+[identical-text]: http://test.csswg.org/source/css21/fonts/shand-font-000.xht
+[red-visual]: http://test.csswg.org/source/css21/positioning/absolute-replaced-height-018.xht
+[red-text]: http://test.csswg.org/source/css21/syntax/comments-003.xht
+[fail-example]: http://test.csswg.org/source/css21/positioning/abspos-overflow-005.xht
+[ahem-example]: http://test.csswg.org/source/css21/positioning/absolute-non-replaced-width-001.xht
+[ahem-readme]: http://www.w3.org/Style/CSS/Test/Fonts/Ahem/README
+[download-ahem]: http://www.w3.org/Style/CSS/Test/Fonts/Ahem/AHEM____.TTF
+[long-test]: http://www.hixie.ch/tests/evil/mixed/lineheight3.html
+[unobvious-test]: http://www.w3.org/Style/CSS/Test/CSS1/current/sec525.htm
diff --git a/tests/wpt/web-platform-tests/docs/test-templates.md b/tests/wpt/web-platform-tests/docs/test-templates.md
new file mode 100644
index 00000000000..e90060858b7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/docs/test-templates.md
@@ -0,0 +1,136 @@
+This page contains templates for creating tests. The template syntax
+is compatible with several popular editors including TextMate, Sublime
+Text, and emacs' YASnippet mode.
+
+Each template is given in two forms, one minimal and one including
+[extra metadata](css-metadata.html). Usually the metadata is required
+by CSS tests and optional for other tests.
+
+Templates for filenames are also given. In this case `{}` is used to
+delimit text to be replaced `#` represents a digit and `ext` is a
+filename extension.
+
+## Reftests
+
+### Minimal Reftest
+
+``` html
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>${1:Test title}</title>
+<link rel="match" href="${2:URL of match}">
+<style>
+ ${3:Test CSS}
+</style>
+<body>
+ ${4:Test content}
+</body>
+```
+
+Filename: `{test-topic}-###.ext`
+
+### Reftest Including Metadata
+
+``` html
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>${1:Test area}: ${2:Scope of test}</title>
+<link rel="author" title="${3:Author's name}" href="${4:Contact link}">
+<link rel="help" href="${5:Link to tested section}">
+<link rel="match" href="${6:URL of match}">
+<meta name="flags" content="${7:Requirement flags}">
+<meta name="assert" content="${8:Description of what you're trying to test}">
+<style>
+ ${9:Test CSS}
+</style>
+<body>
+ ${10:Test content}
+</body>
+```
+
+Filename: `{test-topic}-###.ext`
+
+### Minimal Reftest Reference:
+
+``` html
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>${1:Reference title}</title>
+<style>
+ ${2:Reference CSS}
+</style>
+<body>
+ ${3:Reference content}
+</body>
+```
+
+Filename: `{description}.ext` or `{test-topic}-###-ref.ext`
+
+### Reference Including Metadata
+
+``` html
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>${1:Reference title}</title>
+<link rel="author" title="${2:Author's name}" href="${3:Contact link}">
+<style>
+ ${4:Reference CSS}
+</style>
+<body>
+ ${5:Reference content}
+</body>
+```
+
+Filename: `{description}.ext` or `{test-topic}-###-ref.ext`
+
+## testharness.js tests
+
+### Minimal Script Test
+
+``` html
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>${1:Test title}</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+${2:Test body}
+</script>
+```
+
+Filename: `{test-topic}-###.ext`
+
+### Script Test With Metadata
+
+``` html
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>${1:Test title}</title>
+<link rel="author" title="${2:Author's name}" href="${3:Contact link}">
+<link rel="help" href="${4:Link to tested section}">
+<meta name="flags" content="${5:Requirement flags}">
+<meta name="assert" content="${6:Description of what you're trying to test}">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+${7:Test body}
+</script>
+```
+
+Filename: `{test-topic}-###.ext`
+
+### Manual Test
+
+``` html
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>${1:Test title}</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+setup({explicit_timeout: true});
+${2:Test body}
+</script>
+```
+
+Filename: `{test-topic}-###-manual.ext`
diff --git a/tests/wpt/web-platform-tests/dom/collections/HTMLCollection-empty-name.html b/tests/wpt/web-platform-tests/dom/collections/HTMLCollection-empty-name.html
new file mode 100644
index 00000000000..4fc34db7f5f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/collections/HTMLCollection-empty-name.html
@@ -0,0 +1,65 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>HTMLCollection and empty names</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<div id=test>
+<div class=a id></div>
+<div class=a name></div>
+<a class=a name></a>
+</div>
+<script>
+test(function() {
+ var c = document.getElementsByTagName("*");
+ assert_false("" in c, "Empty string should not be in the collection.");
+ assert_equals(c[""], undefined, "Named getter should return undefined for empty string.");
+ assert_equals(c.namedItem(""), null, "namedItem should return null for empty string.");
+}, "Empty string as a name for Document.getElementsByTagName");
+
+test(function() {
+ var div = document.getElementById("test");
+ var c = div.getElementsByTagName("*");
+ assert_false("" in c, "Empty string should not be in the collection.");
+ assert_equals(c[""], undefined, "Named getter should return undefined for empty string.");
+ assert_equals(c.namedItem(""), null, "namedItem should return null for empty string.");
+}, "Empty string as a name for Element.getElementsByTagName");
+
+test(function() {
+ var c = document.getElementsByTagNameNS("http://www.w3.org/1999/xhtml", "a");
+ assert_false("" in c, "Empty string should not be in the collection.");
+ assert_equals(c[""], undefined, "Named getter should return undefined for empty string.");
+ assert_equals(c.namedItem(""), null, "namedItem should return null for empty string.");
+}, "Empty string as a name for Document.getElementsByTagNameNS");
+
+test(function() {
+ var div = document.getElementById("test");
+ var c = div.getElementsByTagNameNS("http://www.w3.org/1999/xhtml", "a");
+ assert_false("" in c, "Empty string should not be in the collection.");
+ assert_equals(c[""], undefined, "Named getter should return undefined for empty string.");
+ assert_equals(c.namedItem(""), null, "namedItem should return null for empty string.");
+}, "Empty string as a name for Element.getElementsByTagNameNS");
+
+test(function() {
+ var c = document.getElementsByClassName("a");
+ assert_false("" in c, "Empty string should not be in the collection.");
+ assert_equals(c[""], undefined, "Named getter should return undefined for empty string.");
+ assert_equals(c.namedItem(""), null, "namedItem should return null for empty string.");
+}, "Empty string as a name for Document.getElementsByClassName");
+
+test(function() {
+ var div = document.getElementById("test");
+ var c = div.getElementsByClassName("a");
+ assert_false("" in c, "Empty string should not be in the collection.");
+ assert_equals(c[""], undefined, "Named getter should return undefined for empty string.");
+ assert_equals(c.namedItem(""), null, "namedItem should return null for empty string.");
+}, "Empty string as a name for Element.getElementsByClassName");
+
+test(function() {
+ var div = document.getElementById("test");
+ var c = div.children;
+ assert_false("" in c, "Empty string should not be in the collection.");
+ assert_equals(c[""], undefined, "Named getter should return undefined for empty string.");
+ assert_equals(c.namedItem(""), null, "namedItem should return null for empty string.");
+}, "Empty string as a name for Element.children");
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/common.js b/tests/wpt/web-platform-tests/dom/common.js
new file mode 100644
index 00000000000..8f982eb6cec
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/common.js
@@ -0,0 +1,968 @@
+"use strict";
+// Written by Aryeh Gregor <ayg@aryeh.name>
+
+// TODO: iframes, contenteditable/designMode
+
+// Everything is done in functions in this test harness, so we have to declare
+// all the variables before use to make sure they can be reused.
+var testDiv, paras, detachedDiv, detachedPara1, detachedPara2,
+ foreignDoc, foreignPara1, foreignPara2, xmlDoc, xmlElement,
+ detachedXmlElement, detachedTextNode, foreignTextNode,
+ detachedForeignTextNode, xmlTextNode, detachedXmlTextNode,
+ processingInstruction, detachedProcessingInstruction, comment,
+ detachedComment, foreignComment, detachedForeignComment, xmlComment,
+ detachedXmlComment, docfrag, foreignDocfrag, xmlDocfrag, doctype,
+ foreignDoctype, xmlDoctype;
+var testRangesShort, testRanges, testPoints, testNodesShort, testNodes;
+
+function setupRangeTests() {
+ testDiv = document.querySelector("#test");
+ if (testDiv) {
+ testDiv.parentNode.removeChild(testDiv);
+ }
+ testDiv = document.createElement("div");
+ testDiv.id = "test";
+ document.body.insertBefore(testDiv, document.body.firstChild);
+
+ paras = [];
+ paras.push(document.createElement("p"));
+ paras[0].setAttribute("id", "a");
+ // Test some diacritics, to make sure browsers are using code units here
+ // and not something like grapheme clusters.
+ paras[0].textContent = "A\u0308b\u0308c\u0308d\u0308e\u0308f\u0308g\u0308h\u0308\n";
+ testDiv.appendChild(paras[0]);
+
+ paras.push(document.createElement("p"));
+ paras[1].setAttribute("id", "b");
+ paras[1].setAttribute("style", "display:none");
+ paras[1].textContent = "Ijklmnop\n";
+ testDiv.appendChild(paras[1]);
+
+ paras.push(document.createElement("p"));
+ paras[2].setAttribute("id", "c");
+ paras[2].textContent = "Qrstuvwx";
+ testDiv.appendChild(paras[2]);
+
+ paras.push(document.createElement("p"));
+ paras[3].setAttribute("id", "d");
+ paras[3].setAttribute("style", "display:none");
+ paras[3].textContent = "Yzabcdef";
+ testDiv.appendChild(paras[3]);
+
+ paras.push(document.createElement("p"));
+ paras[4].setAttribute("id", "e");
+ paras[4].setAttribute("style", "display:none");
+ paras[4].textContent = "Ghijklmn";
+ testDiv.appendChild(paras[4]);
+
+ detachedDiv = document.createElement("div");
+ detachedPara1 = document.createElement("p");
+ detachedPara1.appendChild(document.createTextNode("Opqrstuv"));
+ detachedPara2 = document.createElement("p");
+ detachedPara2.appendChild(document.createTextNode("Wxyzabcd"));
+ detachedDiv.appendChild(detachedPara1);
+ detachedDiv.appendChild(detachedPara2);
+
+ // Opera doesn't automatically create a doctype for a new HTML document,
+ // contrary to spec. It also doesn't let you add doctypes to documents
+ // after the fact through any means I've tried. So foreignDoc in Opera
+ // will have no doctype, foreignDoctype will be null, and Opera will fail
+ // some tests somewhat mysteriously as a result.
+ foreignDoc = document.implementation.createHTMLDocument("");
+ foreignPara1 = foreignDoc.createElement("p");
+ foreignPara1.appendChild(foreignDoc.createTextNode("Efghijkl"));
+ foreignPara2 = foreignDoc.createElement("p");
+ foreignPara2.appendChild(foreignDoc.createTextNode("Mnopqrst"));
+ foreignDoc.body.appendChild(foreignPara1);
+ foreignDoc.body.appendChild(foreignPara2);
+
+ // Now we get to do really silly stuff, which nobody in the universe is
+ // ever going to actually do, but the spec defines behavior, so too bad.
+ // Testing is fun!
+ xmlDoctype = document.implementation.createDocumentType("qorflesnorf", "abcde", "x\"'y");
+ xmlDoc = document.implementation.createDocument(null, null, xmlDoctype);
+ detachedXmlElement = xmlDoc.createElement("everyone-hates-hyphenated-element-names");
+ detachedTextNode = document.createTextNode("Uvwxyzab");
+ detachedForeignTextNode = foreignDoc.createTextNode("Cdefghij");
+ detachedXmlTextNode = xmlDoc.createTextNode("Klmnopqr");
+ // PIs only exist in XML documents, so don't bother with document or
+ // foreignDoc.
+ detachedProcessingInstruction = xmlDoc.createProcessingInstruction("whippoorwill", "chirp chirp chirp");
+ detachedComment = document.createComment("Stuvwxyz");
+ // Hurrah, we finally got to "z" at the end!
+ detachedForeignComment = foreignDoc.createComment("אריה יהודה");
+ detachedXmlComment = xmlDoc.createComment("בן חיים אליעזר");
+
+ // We should also test with document fragments that actually contain stuff
+ // . . . but, maybe later.
+ docfrag = document.createDocumentFragment();
+ foreignDocfrag = foreignDoc.createDocumentFragment();
+ xmlDocfrag = xmlDoc.createDocumentFragment();
+
+ xmlElement = xmlDoc.createElement("igiveuponcreativenames");
+ xmlTextNode = xmlDoc.createTextNode("do re mi fa so la ti");
+ xmlElement.appendChild(xmlTextNode);
+ processingInstruction = xmlDoc.createProcessingInstruction("somePI", 'Did you know that ":syn sync fromstart" is very useful when using vim to edit large amounts of JavaScript embedded in HTML?');
+ xmlDoc.appendChild(xmlElement);
+ xmlDoc.appendChild(processingInstruction);
+ xmlComment = xmlDoc.createComment("I maliciously created a comment that will break incautious XML serializers, but Firefox threw an exception, so all I got was this lousy T-shirt");
+ xmlDoc.appendChild(xmlComment);
+
+ comment = document.createComment("Alphabet soup?");
+ testDiv.appendChild(comment);
+
+ foreignComment = foreignDoc.createComment('"Commenter" and "commentator" mean different things. I\'ve seen non-native speakers trip up on this.');
+ foreignDoc.appendChild(foreignComment);
+ foreignTextNode = foreignDoc.createTextNode("I admit that I harbor doubts about whether we really need so many things to test, but it's too late to stop now.");
+ foreignDoc.body.appendChild(foreignTextNode);
+
+ doctype = document.doctype;
+ foreignDoctype = foreignDoc.doctype;
+
+ testRangesShort = [
+ // Various ranges within the text node children of different
+ // paragraphs. All should be valid.
+ "[paras[0].firstChild, 0, paras[0].firstChild, 0]",
+ "[paras[0].firstChild, 0, paras[0].firstChild, 1]",
+ "[paras[0].firstChild, 2, paras[0].firstChild, 8]",
+ "[paras[0].firstChild, 2, paras[0].firstChild, 9]",
+ "[paras[1].firstChild, 0, paras[1].firstChild, 0]",
+ "[paras[1].firstChild, 2, paras[1].firstChild, 9]",
+ "[detachedPara1.firstChild, 0, detachedPara1.firstChild, 0]",
+ "[detachedPara1.firstChild, 2, detachedPara1.firstChild, 8]",
+ "[foreignPara1.firstChild, 0, foreignPara1.firstChild, 0]",
+ "[foreignPara1.firstChild, 2, foreignPara1.firstChild, 8]",
+ // Now try testing some elements, not just text nodes.
+ "[document.documentElement, 0, document.documentElement, 1]",
+ "[document.documentElement, 0, document.documentElement, 2]",
+ "[document.documentElement, 1, document.documentElement, 2]",
+ "[document.head, 1, document.head, 1]",
+ "[document.body, 4, document.body, 5]",
+ "[foreignDoc.documentElement, 0, foreignDoc.documentElement, 1]",
+ "[paras[0], 0, paras[0], 1]",
+ "[detachedPara1, 0, detachedPara1, 1]",
+ // Now try some ranges that span elements.
+ "[paras[0].firstChild, 0, paras[1].firstChild, 0]",
+ "[paras[0].firstChild, 0, paras[1].firstChild, 8]",
+ "[paras[0].firstChild, 3, paras[3], 1]",
+ // How about something that spans a node and its descendant?
+ "[paras[0], 0, paras[0].firstChild, 7]",
+ "[testDiv, 2, paras[4], 1]",
+ // Then a few more interesting things just for good measure.
+ "[document, 0, document, 1]",
+ "[document, 0, document, 2]",
+ "[comment, 2, comment, 3]",
+ "[testDiv, 0, comment, 5]",
+ "[foreignDoc, 1, foreignComment, 2]",
+ "[foreignDoc.body, 0, foreignTextNode, 36]",
+ "[xmlDoc, 1, xmlComment, 0]",
+ "[detachedTextNode, 0, detachedTextNode, 8]",
+ "[detachedForeignTextNode, 0, detachedForeignTextNode, 8]",
+ "[detachedXmlTextNode, 0, detachedXmlTextNode, 8]",
+ "[detachedComment, 3, detachedComment, 4]",
+ "[detachedForeignComment, 0, detachedForeignComment, 1]",
+ "[detachedXmlComment, 2, detachedXmlComment, 6]",
+ "[docfrag, 0, docfrag, 0]",
+ ];
+
+ testRanges = testRangesShort.concat([
+ "[paras[1].firstChild, 0, paras[1].firstChild, 1]",
+ "[paras[1].firstChild, 2, paras[1].firstChild, 8]",
+ "[detachedPara1.firstChild, 0, detachedPara1.firstChild, 1]",
+ "[foreignPara1.firstChild, 0, foreignPara1.firstChild, 1]",
+ "[foreignDoc.head, 1, foreignDoc.head, 1]",
+ "[foreignDoc.body, 0, foreignDoc.body, 0]",
+ "[paras[0], 0, paras[0], 0]",
+ "[detachedPara1, 0, detachedPara1, 0]",
+ "[testDiv, 1, paras[2].firstChild, 5]",
+ "[document.documentElement, 1, document.body, 0]",
+ "[foreignDoc.documentElement, 1, foreignDoc.body, 0]",
+ "[document, 1, document, 2]",
+ "[paras[2].firstChild, 4, comment, 2]",
+ "[paras[3], 1, comment, 8]",
+ "[foreignDoc, 0, foreignDoc, 0]",
+ "[xmlDoc, 0, xmlDoc, 0]",
+ "[detachedForeignTextNode, 7, detachedForeignTextNode, 7]",
+ "[detachedXmlTextNode, 7, detachedXmlTextNode, 7]",
+ "[detachedComment, 5, detachedComment, 5]",
+ "[detachedForeignComment, 4, detachedForeignComment, 4]",
+ "[foreignDocfrag, 0, foreignDocfrag, 0]",
+ "[xmlDocfrag, 0, xmlDocfrag, 0]",
+ ]);
+
+ testPoints = [
+ // Various positions within the page, some invalid. Remember that
+ // paras[0] is visible, and paras[1] is display: none.
+ "[paras[0].firstChild, -1]",
+ "[paras[0].firstChild, 0]",
+ "[paras[0].firstChild, 1]",
+ "[paras[0].firstChild, 2]",
+ "[paras[0].firstChild, 8]",
+ "[paras[0].firstChild, 9]",
+ "[paras[0].firstChild, 10]",
+ "[paras[0].firstChild, 65535]",
+ "[paras[1].firstChild, -1]",
+ "[paras[1].firstChild, 0]",
+ "[paras[1].firstChild, 1]",
+ "[paras[1].firstChild, 2]",
+ "[paras[1].firstChild, 8]",
+ "[paras[1].firstChild, 9]",
+ "[paras[1].firstChild, 10]",
+ "[paras[1].firstChild, 65535]",
+ "[detachedPara1.firstChild, 0]",
+ "[detachedPara1.firstChild, 1]",
+ "[detachedPara1.firstChild, 8]",
+ "[detachedPara1.firstChild, 9]",
+ "[foreignPara1.firstChild, 0]",
+ "[foreignPara1.firstChild, 1]",
+ "[foreignPara1.firstChild, 8]",
+ "[foreignPara1.firstChild, 9]",
+ // Now try testing some elements, not just text nodes.
+ "[document.documentElement, -1]",
+ "[document.documentElement, 0]",
+ "[document.documentElement, 1]",
+ "[document.documentElement, 2]",
+ "[document.documentElement, 7]",
+ "[document.head, 1]",
+ "[document.body, 3]",
+ "[foreignDoc.documentElement, 0]",
+ "[foreignDoc.documentElement, 1]",
+ "[foreignDoc.head, 0]",
+ "[foreignDoc.body, 1]",
+ "[paras[0], 0]",
+ "[paras[0], 1]",
+ "[paras[0], 2]",
+ "[paras[1], 0]",
+ "[paras[1], 1]",
+ "[paras[1], 2]",
+ "[detachedPara1, 0]",
+ "[detachedPara1, 1]",
+ "[testDiv, 0]",
+ "[testDiv, 3]",
+ // Then a few more interesting things just for good measure.
+ "[document, -1]",
+ "[document, 0]",
+ "[document, 1]",
+ "[document, 2]",
+ "[document, 3]",
+ "[comment, -1]",
+ "[comment, 0]",
+ "[comment, 4]",
+ "[comment, 96]",
+ "[foreignDoc, 0]",
+ "[foreignDoc, 1]",
+ "[foreignComment, 2]",
+ "[foreignTextNode, 0]",
+ "[foreignTextNode, 36]",
+ "[xmlDoc, -1]",
+ "[xmlDoc, 0]",
+ "[xmlDoc, 1]",
+ "[xmlDoc, 5]",
+ "[xmlComment, 0]",
+ "[xmlComment, 4]",
+ "[processingInstruction, 0]",
+ "[processingInstruction, 5]",
+ "[processingInstruction, 9]",
+ "[detachedTextNode, 0]",
+ "[detachedTextNode, 8]",
+ "[detachedForeignTextNode, 0]",
+ "[detachedForeignTextNode, 8]",
+ "[detachedXmlTextNode, 0]",
+ "[detachedXmlTextNode, 8]",
+ "[detachedProcessingInstruction, 12]",
+ "[detachedComment, 3]",
+ "[detachedComment, 5]",
+ "[detachedForeignComment, 0]",
+ "[detachedForeignComment, 4]",
+ "[detachedXmlComment, 2]",
+ "[docfrag, 0]",
+ "[foreignDocfrag, 0]",
+ "[xmlDocfrag, 0]",
+ "[doctype, 0]",
+ "[doctype, -17]",
+ "[doctype, 1]",
+ "[foreignDoctype, 0]",
+ "[xmlDoctype, 0]",
+ ];
+
+ testNodesShort = [
+ "paras[0]",
+ "paras[0].firstChild",
+ "paras[1].firstChild",
+ "foreignPara1",
+ "foreignPara1.firstChild",
+ "detachedPara1",
+ "detachedPara1.firstChild",
+ "document",
+ "detachedDiv",
+ "foreignDoc",
+ "foreignPara2",
+ "xmlDoc",
+ "xmlElement",
+ "detachedTextNode",
+ "foreignTextNode",
+ "processingInstruction",
+ "detachedProcessingInstruction",
+ "comment",
+ "detachedComment",
+ "docfrag",
+ "doctype",
+ "foreignDoctype",
+ ];
+
+ testNodes = testNodesShort.concat([
+ "paras[1]",
+ "detachedPara2",
+ "detachedPara2.firstChild",
+ "testDiv",
+ "detachedXmlElement",
+ "detachedForeignTextNode",
+ "xmlTextNode",
+ "detachedXmlTextNode",
+ "xmlComment",
+ "foreignComment",
+ "detachedForeignComment",
+ "detachedXmlComment",
+ "foreignDocfrag",
+ "xmlDocfrag",
+ "xmlDoctype",
+ ]);
+}
+if ("setup" in window) {
+ setup(setupRangeTests);
+} else {
+ // Presumably we're running from within an iframe or something
+ setupRangeTests();
+}
+
+/**
+ * The "length" of a node as defined by the Ranges section of DOM4.
+ */
+function nodeLength(node) {
+ // "The length of a node node depends on node:
+ //
+ // "DocumentType
+ // "0."
+ if (node.nodeType == Node.DOCUMENT_TYPE_NODE) {
+ return 0;
+ }
+ // "Text
+ // "ProcessingInstruction
+ // "Comment
+ // "Its length attribute value."
+ // Browsers don't historically support the length attribute on
+ // ProcessingInstruction, so to avoid spurious failures, do
+ // node.data.length instead of node.length.
+ if (node.nodeType == Node.TEXT_NODE || node.nodeType == Node.PROCESSING_INSTRUCTION_NODE || node.nodeType == Node.COMMENT_NODE) {
+ return node.data.length;
+ }
+ // "Any other node
+ // "Its number of children."
+ return node.childNodes.length;
+}
+
+/**
+ * Returns the furthest ancestor of a Node as defined by the spec.
+ */
+function furthestAncestor(node) {
+ var root = node;
+ while (root.parentNode != null) {
+ root = root.parentNode;
+ }
+ return root;
+}
+
+/**
+ * "The ancestor containers of a Node are the Node itself and all its
+ * ancestors."
+ *
+ * Is node1 an ancestor container of node2?
+ */
+function isAncestorContainer(node1, node2) {
+ return node1 == node2 ||
+ (node2.compareDocumentPosition(node1) & Node.DOCUMENT_POSITION_CONTAINS);
+}
+
+/**
+ * Returns the first Node that's after node in tree order, or null if node is
+ * the last Node.
+ */
+function nextNode(node) {
+ if (node.hasChildNodes()) {
+ return node.firstChild;
+ }
+ return nextNodeDescendants(node);
+}
+
+/**
+ * Returns the last Node that's before node in tree order, or null if node is
+ * the first Node.
+ */
+function previousNode(node) {
+ if (node.previousSibling) {
+ node = node.previousSibling;
+ while (node.hasChildNodes()) {
+ node = node.lastChild;
+ }
+ return node;
+ }
+ return node.parentNode;
+}
+
+/**
+ * Returns the next Node that's after node and all its descendants in tree
+ * order, or null if node is the last Node or an ancestor of it.
+ */
+function nextNodeDescendants(node) {
+ while (node && !node.nextSibling) {
+ node = node.parentNode;
+ }
+ if (!node) {
+ return null;
+ }
+ return node.nextSibling;
+}
+
+/**
+ * Returns the ownerDocument of the Node, or the Node itself if it's a
+ * Document.
+ */
+function ownerDocument(node) {
+ return node.nodeType == Node.DOCUMENT_NODE
+ ? node
+ : node.ownerDocument;
+}
+
+/**
+ * Returns true if ancestor is an ancestor of descendant, false otherwise.
+ */
+function isAncestor(ancestor, descendant) {
+ if (!ancestor || !descendant) {
+ return false;
+ }
+ while (descendant && descendant != ancestor) {
+ descendant = descendant.parentNode;
+ }
+ return descendant == ancestor;
+}
+
+/**
+ * Returns true if ancestor is an inclusive ancestor of descendant, false
+ * otherwise.
+ */
+function isInclusiveAncestor(ancestor, descendant) {
+ return ancestor === descendant || isAncestor(ancestor, descendant);
+}
+
+/**
+ * Returns true if descendant is a descendant of ancestor, false otherwise.
+ */
+function isDescendant(descendant, ancestor) {
+ return isAncestor(ancestor, descendant);
+}
+
+/**
+ * Returns true if descendant is an inclusive descendant of ancestor, false
+ * otherwise.
+ */
+function isInclusiveDescendant(descendant, ancestor) {
+ return descendant === ancestor || isDescendant(descendant, ancestor);
+}
+
+/**
+ * The position of two boundary points relative to one another, as defined by
+ * the spec.
+ */
+function getPosition(nodeA, offsetA, nodeB, offsetB) {
+ // "If node A is the same as node B, return equal if offset A equals offset
+ // B, before if offset A is less than offset B, and after if offset A is
+ // greater than offset B."
+ if (nodeA == nodeB) {
+ if (offsetA == offsetB) {
+ return "equal";
+ }
+ if (offsetA < offsetB) {
+ return "before";
+ }
+ if (offsetA > offsetB) {
+ return "after";
+ }
+ }
+
+ // "If node A is after node B in tree order, compute the position of (node
+ // B, offset B) relative to (node A, offset A). If it is before, return
+ // after. If it is after, return before."
+ if (nodeB.compareDocumentPosition(nodeA) & Node.DOCUMENT_POSITION_FOLLOWING) {
+ var pos = getPosition(nodeB, offsetB, nodeA, offsetA);
+ if (pos == "before") {
+ return "after";
+ }
+ if (pos == "after") {
+ return "before";
+ }
+ }
+
+ // "If node A is an ancestor of node B:"
+ if (nodeB.compareDocumentPosition(nodeA) & Node.DOCUMENT_POSITION_CONTAINS) {
+ // "Let child equal node B."
+ var child = nodeB;
+
+ // "While child is not a child of node A, set child to its parent."
+ while (child.parentNode != nodeA) {
+ child = child.parentNode;
+ }
+
+ // "If the index of child is less than offset A, return after."
+ if (indexOf(child) < offsetA) {
+ return "after";
+ }
+ }
+
+ // "Return before."
+ return "before";
+}
+
+/**
+ * "contained" as defined by DOM Range: "A Node node is contained in a range
+ * range if node's furthest ancestor is the same as range's root, and (node, 0)
+ * is after range's start, and (node, length of node) is before range's end."
+ */
+function isContained(node, range) {
+ var pos1 = getPosition(node, 0, range.startContainer, range.startOffset);
+ var pos2 = getPosition(node, nodeLength(node), range.endContainer, range.endOffset);
+
+ return furthestAncestor(node) == furthestAncestor(range.startContainer)
+ && pos1 == "after"
+ && pos2 == "before";
+}
+
+/**
+ * "partially contained" as defined by DOM Range: "A Node is partially
+ * contained in a range if it is an ancestor container of the range's start but
+ * not its end, or vice versa."
+ */
+function isPartiallyContained(node, range) {
+ var cond1 = isAncestorContainer(node, range.startContainer);
+ var cond2 = isAncestorContainer(node, range.endContainer);
+ return (cond1 && !cond2) || (cond2 && !cond1);
+}
+
+/**
+ * Index of a node as defined by the spec.
+ */
+function indexOf(node) {
+ if (!node.parentNode) {
+ // No preceding sibling nodes, right?
+ return 0;
+ }
+ var i = 0;
+ while (node != node.parentNode.childNodes[i]) {
+ i++;
+ }
+ return i;
+}
+
+/**
+ * extractContents() implementation, following the spec. If an exception is
+ * supposed to be thrown, will return a string with the name (e.g.,
+ * "HIERARCHY_REQUEST_ERR") instead of a document fragment. It might also
+ * return an arbitrary human-readable string if a condition is hit that implies
+ * a spec bug.
+ */
+function myExtractContents(range) {
+ // "If the context object's detached flag is set, raise an
+ // INVALID_STATE_ERR exception and abort these steps."
+ try {
+ range.collapsed;
+ } catch (e) {
+ return "INVALID_STATE_ERR";
+ }
+
+ // "Let frag be a new DocumentFragment whose ownerDocument is the same as
+ // the ownerDocument of the context object's start node."
+ var ownerDoc = range.startContainer.nodeType == Node.DOCUMENT_NODE
+ ? range.startContainer
+ : range.startContainer.ownerDocument;
+ var frag = ownerDoc.createDocumentFragment();
+
+ // "If the context object's start and end are the same, abort this method,
+ // returning frag."
+ if (range.startContainer == range.endContainer
+ && range.startOffset == range.endOffset) {
+ return frag;
+ }
+
+ // "Let original start node, original start offset, original end node, and
+ // original end offset be the context object's start and end nodes and
+ // offsets, respectively."
+ var originalStartNode = range.startContainer;
+ var originalStartOffset = range.startOffset;
+ var originalEndNode = range.endContainer;
+ var originalEndOffset = range.endOffset;
+
+ // "If original start node and original end node are the same, and they are
+ // a Text or Comment node:"
+ if (range.startContainer == range.endContainer
+ && (range.startContainer.nodeType == Node.TEXT_NODE
+ || range.startContainer.nodeType == Node.COMMENT_NODE)) {
+ // "Let clone be the result of calling cloneNode(false) on original
+ // start node."
+ var clone = originalStartNode.cloneNode(false);
+
+ // "Set the data of clone to the result of calling
+ // substringData(original start offset, original end offset − original
+ // start offset) on original start node."
+ clone.data = originalStartNode.substringData(originalStartOffset,
+ originalEndOffset - originalStartOffset);
+
+ // "Append clone as the last child of frag."
+ frag.appendChild(clone);
+
+ // "Call deleteData(original start offset, original end offset −
+ // original start offset) on original start node."
+ originalStartNode.deleteData(originalStartOffset,
+ originalEndOffset - originalStartOffset);
+
+ // "Abort this method, returning frag."
+ return frag;
+ }
+
+ // "Let common ancestor equal original start node."
+ var commonAncestor = originalStartNode;
+
+ // "While common ancestor is not an ancestor container of original end
+ // node, set common ancestor to its own parent."
+ while (!isAncestorContainer(commonAncestor, originalEndNode)) {
+ commonAncestor = commonAncestor.parentNode;
+ }
+
+ // "If original start node is an ancestor container of original end node,
+ // let first partially contained child be null."
+ var firstPartiallyContainedChild;
+ if (isAncestorContainer(originalStartNode, originalEndNode)) {
+ firstPartiallyContainedChild = null;
+ // "Otherwise, let first partially contained child be the first child of
+ // common ancestor that is partially contained in the context object."
+ } else {
+ for (var i = 0; i < commonAncestor.childNodes.length; i++) {
+ if (isPartiallyContained(commonAncestor.childNodes[i], range)) {
+ firstPartiallyContainedChild = commonAncestor.childNodes[i];
+ break;
+ }
+ }
+ if (!firstPartiallyContainedChild) {
+ throw "Spec bug: no first partially contained child!";
+ }
+ }
+
+ // "If original end node is an ancestor container of original start node,
+ // let last partially contained child be null."
+ var lastPartiallyContainedChild;
+ if (isAncestorContainer(originalEndNode, originalStartNode)) {
+ lastPartiallyContainedChild = null;
+ // "Otherwise, let last partially contained child be the last child of
+ // common ancestor that is partially contained in the context object."
+ } else {
+ for (var i = commonAncestor.childNodes.length - 1; i >= 0; i--) {
+ if (isPartiallyContained(commonAncestor.childNodes[i], range)) {
+ lastPartiallyContainedChild = commonAncestor.childNodes[i];
+ break;
+ }
+ }
+ if (!lastPartiallyContainedChild) {
+ throw "Spec bug: no last partially contained child!";
+ }
+ }
+
+ // "Let contained children be a list of all children of common ancestor
+ // that are contained in the context object, in tree order."
+ //
+ // "If any member of contained children is a DocumentType, raise a
+ // HIERARCHY_REQUEST_ERR exception and abort these steps."
+ var containedChildren = [];
+ for (var i = 0; i < commonAncestor.childNodes.length; i++) {
+ if (isContained(commonAncestor.childNodes[i], range)) {
+ if (commonAncestor.childNodes[i].nodeType
+ == Node.DOCUMENT_TYPE_NODE) {
+ return "HIERARCHY_REQUEST_ERR";
+ }
+ containedChildren.push(commonAncestor.childNodes[i]);
+ }
+ }
+
+ // "If original start node is an ancestor container of original end node,
+ // set new node to original start node and new offset to original start
+ // offset."
+ var newNode, newOffset;
+ if (isAncestorContainer(originalStartNode, originalEndNode)) {
+ newNode = originalStartNode;
+ newOffset = originalStartOffset;
+ // "Otherwise:"
+ } else {
+ // "Let reference node equal original start node."
+ var referenceNode = originalStartNode;
+
+ // "While reference node's parent is not null and is not an ancestor
+ // container of original end node, set reference node to its parent."
+ while (referenceNode.parentNode
+ && !isAncestorContainer(referenceNode.parentNode, originalEndNode)) {
+ referenceNode = referenceNode.parentNode;
+ }
+
+ // "Set new node to the parent of reference node, and new offset to one
+ // plus the index of reference node."
+ newNode = referenceNode.parentNode;
+ newOffset = 1 + indexOf(referenceNode);
+ }
+
+ // "If first partially contained child is a Text or Comment node:"
+ if (firstPartiallyContainedChild
+ && (firstPartiallyContainedChild.nodeType == Node.TEXT_NODE
+ || firstPartiallyContainedChild.nodeType == Node.COMMENT_NODE)) {
+ // "Let clone be the result of calling cloneNode(false) on original
+ // start node."
+ var clone = originalStartNode.cloneNode(false);
+
+ // "Set the data of clone to the result of calling substringData() on
+ // original start node, with original start offset as the first
+ // argument and (length of original start node − original start offset)
+ // as the second."
+ clone.data = originalStartNode.substringData(originalStartOffset,
+ nodeLength(originalStartNode) - originalStartOffset);
+
+ // "Append clone as the last child of frag."
+ frag.appendChild(clone);
+
+ // "Call deleteData() on original start node, with original start
+ // offset as the first argument and (length of original start node −
+ // original start offset) as the second."
+ originalStartNode.deleteData(originalStartOffset,
+ nodeLength(originalStartNode) - originalStartOffset);
+ // "Otherwise, if first partially contained child is not null:"
+ } else if (firstPartiallyContainedChild) {
+ // "Let clone be the result of calling cloneNode(false) on first
+ // partially contained child."
+ var clone = firstPartiallyContainedChild.cloneNode(false);
+
+ // "Append clone as the last child of frag."
+ frag.appendChild(clone);
+
+ // "Let subrange be a new Range whose start is (original start node,
+ // original start offset) and whose end is (first partially contained
+ // child, length of first partially contained child)."
+ var subrange = ownerDoc.createRange();
+ subrange.setStart(originalStartNode, originalStartOffset);
+ subrange.setEnd(firstPartiallyContainedChild,
+ nodeLength(firstPartiallyContainedChild));
+
+ // "Let subfrag be the result of calling extractContents() on
+ // subrange."
+ var subfrag = myExtractContents(subrange);
+
+ // "For each child of subfrag, in order, append that child to clone as
+ // its last child."
+ for (var i = 0; i < subfrag.childNodes.length; i++) {
+ clone.appendChild(subfrag.childNodes[i]);
+ }
+ }
+
+ // "For each contained child in contained children, append contained child
+ // as the last child of frag."
+ for (var i = 0; i < containedChildren.length; i++) {
+ frag.appendChild(containedChildren[i]);
+ }
+
+ // "If last partially contained child is a Text or Comment node:"
+ if (lastPartiallyContainedChild
+ && (lastPartiallyContainedChild.nodeType == Node.TEXT_NODE
+ || lastPartiallyContainedChild.nodeType == Node.COMMENT_NODE)) {
+ // "Let clone be the result of calling cloneNode(false) on original
+ // end node."
+ var clone = originalEndNode.cloneNode(false);
+
+ // "Set the data of clone to the result of calling substringData(0,
+ // original end offset) on original end node."
+ clone.data = originalEndNode.substringData(0, originalEndOffset);
+
+ // "Append clone as the last child of frag."
+ frag.appendChild(clone);
+
+ // "Call deleteData(0, original end offset) on original end node."
+ originalEndNode.deleteData(0, originalEndOffset);
+ // "Otherwise, if last partially contained child is not null:"
+ } else if (lastPartiallyContainedChild) {
+ // "Let clone be the result of calling cloneNode(false) on last
+ // partially contained child."
+ var clone = lastPartiallyContainedChild.cloneNode(false);
+
+ // "Append clone as the last child of frag."
+ frag.appendChild(clone);
+
+ // "Let subrange be a new Range whose start is (last partially
+ // contained child, 0) and whose end is (original end node, original
+ // end offset)."
+ var subrange = ownerDoc.createRange();
+ subrange.setStart(lastPartiallyContainedChild, 0);
+ subrange.setEnd(originalEndNode, originalEndOffset);
+
+ // "Let subfrag be the result of calling extractContents() on
+ // subrange."
+ var subfrag = myExtractContents(subrange);
+
+ // "For each child of subfrag, in order, append that child to clone as
+ // its last child."
+ for (var i = 0; i < subfrag.childNodes.length; i++) {
+ clone.appendChild(subfrag.childNodes[i]);
+ }
+ }
+
+ // "Set the context object's start and end to (new node, new offset)."
+ range.setStart(newNode, newOffset);
+ range.setEnd(newNode, newOffset);
+
+ // "Return frag."
+ return frag;
+}
+
+/**
+ * insertNode() implementation, following the spec. If an exception is
+ * supposed to be thrown, will return a string with the name (e.g.,
+ * "HIERARCHY_REQUEST_ERR") instead of a document fragment. It might also
+ * return an arbitrary human-readable string if a condition is hit that implies
+ * a spec bug.
+ */
+function myInsertNode(range, node) {
+ // "If the detached flag is set, throw an "InvalidStateError" exception and
+ // terminate these steps."
+ //
+ // Assume that if accessing collapsed throws, it's detached.
+ try {
+ range.collapsed;
+ } catch (e) {
+ return "INVALID_STATE_ERR";
+ }
+
+ // "If start node is a Comment node, or a Text node whose parent is null,
+ // throw an "HierarchyRequestError" exception and terminate these steps."
+ if (range.startContainer.nodeType == Node.COMMENT_NODE
+ || (range.startContainer.nodeType == Node.TEXT_NODE
+ && !range.startContainer.parentNode)) {
+ return "HIERARCHY_REQUEST_ERR";
+ }
+
+ // "If start node is a Text node, split it with offset context object's
+ // start offset, and let reference node be the result."
+ var referenceNode;
+ if (range.startContainer.nodeType == Node.TEXT_NODE) {
+ // We aren't testing how ranges vary under mutations, and browsers vary
+ // in how they mutate for splitText, so let's just force the correct
+ // way.
+ var start = [range.startContainer, range.startOffset];
+ var end = [range.endContainer, range.endOffset];
+
+ referenceNode = range.startContainer.splitText(range.startOffset);
+
+ if (start[0] == end[0]
+ && end[1] > start[1]) {
+ end[0] = referenceNode;
+ end[1] -= start[1];
+ } else if (end[0] == start[0].parentNode
+ && end[1] > indexOf(referenceNode)) {
+ end[1]++;
+ }
+ range.setStart(start[0], start[1]);
+ range.setEnd(end[0], end[1]);
+
+ // "Otherwise, let reference node be the child of start node whose index is
+ // start offset, or null if there is no such child."
+ } else {
+ referenceNode = range.startContainer.childNodes[range.startOffset];
+ if (typeof referenceNode == "undefined") {
+ referenceNode = null;
+ }
+ }
+
+ // "If reference node is null, let parent be start node."
+ var parent_;
+ if (!referenceNode) {
+ parent_ = range.startContainer;
+
+ // "Otherwise, let parent be the parent of reference node."
+ } else {
+ parent_ = referenceNode.parentNode;
+ }
+
+ // "Let new offset be the index of reference node, or parent's length if
+ // reference node is null."
+ var newOffset = referenceNode ? indexOf(referenceNode) : nodeLength(parent_);
+
+ // "Add node's length to new offset, if node is a DocumentFragment.
+ // Otherwise add one to new offset."
+ newOffset += node.nodeType == Node.DOCUMENT_FRAGMENT_NODE
+ ? nodeLength(node)
+ : 1;
+
+ // "Pre-insert node into parent before reference node."
+ try {
+ parent_.insertBefore(node, referenceNode);
+ } catch (e) {
+ return getDomExceptionName(e);
+ }
+
+ // "If start and end are the same, set end to (parent, new offset)."
+ if (range.collapsed) {
+ range.setEnd(parent_, newOffset);
+ }
+}
+
+/**
+ * Asserts that two nodes are equal, in the sense of isEqualNode(). If they
+ * aren't, tries to print a relatively informative reason why not. TODO: Move
+ * this to testharness.js?
+ */
+function assertNodesEqual(actual, expected, msg) {
+ if (!actual.isEqualNode(expected)) {
+ msg = "Actual and expected mismatch for " + msg + ". ";
+
+ while (actual && expected) {
+ assert_true(actual.nodeType === expected.nodeType
+ && actual.nodeName === expected.nodeName
+ && actual.nodeValue === expected.nodeValue
+ && actual.childNodes.length === expected.childNodes.length,
+ "First differing node: expected " + format_value(expected)
+ + ", got " + format_value(actual) + " [" + msg + "]");
+ actual = nextNode(actual);
+ expected = nextNode(expected);
+ }
+
+ assert_unreached("DOMs were not equal but we couldn't figure out why");
+ }
+}
+
+/**
+ * Given a DOMException, return the name (e.g., "HIERARCHY_REQUEST_ERR").
+ */
+function getDomExceptionName(e) {
+ var ret = null;
+ for (var prop in e) {
+ if (/^[A-Z_]+_ERR$/.test(prop) && e[prop] == e.code) {
+ return prop;
+ }
+ }
+
+ throw "Exception seems to not be a DOMException? " + e;
+}
+
+/**
+ * Given an array of endpoint data [start container, start offset, end
+ * container, end offset], returns a Range with those endpoints.
+ */
+function rangeFromEndpoints(endpoints) {
+ // If we just use document instead of the ownerDocument of endpoints[0],
+ // WebKit will throw on setStart/setEnd. This is a WebKit bug, but it's in
+ // range, not selection, so we don't want to fail anything for it.
+ var range = ownerDocument(endpoints[0]).createRange();
+ range.setStart(endpoints[0], endpoints[1]);
+ range.setEnd(endpoints[2], endpoints[3]);
+ return range;
+}
diff --git a/tests/wpt/web-platform-tests/dom/constants.js b/tests/wpt/web-platform-tests/dom/constants.js
new file mode 100644
index 00000000000..397df96fbc5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/constants.js
@@ -0,0 +1,11 @@
+function testConstants(objects, constants, msg) {
+ objects.forEach(function(arr) {
+ var o = arr[0], desc = arr[1];
+ test(function() {
+ constants.forEach(function(d) {
+ assert_true(d[0] in o, "Object " + o + " doesn't have " + d[0])
+ assert_equals(o[d[0]], d[1], "Object " + o + " value for " + d[0] + " is wrong")
+ })
+ }, "Constants for " + msg + " on " + desc + ".")
+ })
+}
diff --git a/tests/wpt/web-platform-tests/dom/events/Event-constants.html b/tests/wpt/web-platform-tests/dom/events/Event-constants.html
new file mode 100644
index 00000000000..635e9894d9a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/events/Event-constants.html
@@ -0,0 +1,23 @@
+<!doctype html>
+<title>Event constants</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../constants.js"></script>
+<div id="log"></div>
+<script>
+var objects;
+setup(function() {
+ objects = [
+ [Event, "Event interface object"],
+ [Event.prototype, "Event prototype object"],
+ [document.createEvent("Event"), "Event object"],
+ [document.createEvent("CustomEvent"), "CustomEvent object"]
+ ]
+})
+testConstants(objects, [
+ ["NONE", 0],
+ ["CAPTURING_PHASE", 1],
+ ["AT_TARGET", 2],
+ ["BUBBLING_PHASE", 3]
+], "eventPhase")
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/events/Event-constructors.html b/tests/wpt/web-platform-tests/dom/events/Event-constructors.html
new file mode 100644
index 00000000000..25cbdc4aeaf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/events/Event-constructors.html
@@ -0,0 +1,124 @@
+<!doctype html>
+<title>Event constructors</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function() {
+ assert_throws(new TypeError(), function() {
+ new Event()
+ })
+})
+test(function() {
+ var test_error = { name: "test" }
+ assert_throws(test_error, function() {
+ new Event({ toString: function() { throw test_error; } })
+ })
+})
+test(function() {
+ var ev = new Event("")
+ assert_equals(ev.type, "")
+ assert_equals(ev.target, null)
+ assert_equals(ev.currentTarget, null)
+ assert_equals(ev.eventPhase, Event.NONE)
+ assert_equals(ev.bubbles, false)
+ assert_equals(ev.cancelable, false)
+ assert_equals(ev.defaultPrevented, false)
+ assert_equals(ev.isTrusted, false)
+ assert_true(ev.timeStamp > 0)
+ assert_true("initEvent" in ev)
+})
+test(function() {
+ var ev = new Event("test")
+ assert_equals(ev.type, "test")
+ assert_equals(ev.target, null)
+ assert_equals(ev.currentTarget, null)
+ assert_equals(ev.eventPhase, Event.NONE)
+ assert_equals(ev.bubbles, false)
+ assert_equals(ev.cancelable, false)
+ assert_equals(ev.defaultPrevented, false)
+ assert_equals(ev.isTrusted, false)
+ assert_true(ev.timeStamp > 0)
+ assert_true("initEvent" in ev)
+})
+test(function() {
+ var ev = Event("test")
+ assert_equals(ev.type, "test")
+ assert_equals(ev.target, null)
+ assert_equals(ev.currentTarget, null)
+ assert_equals(ev.eventPhase, Event.NONE)
+ assert_equals(ev.bubbles, false)
+ assert_equals(ev.cancelable, false)
+ assert_equals(ev.defaultPrevented, false)
+ assert_equals(ev.isTrusted, false)
+ assert_true(ev.timeStamp > 0)
+ assert_true("initEvent" in ev)
+})
+test(function() {
+ var ev = new Event("I am an event", { bubbles: true, cancelable: false})
+ assert_equals(ev.type, "I am an event")
+ assert_equals(ev.bubbles, true)
+ assert_equals(ev.cancelable, false)
+})
+test(function() {
+ var ev = new Event("@", { bubblesIGNORED: true, cancelable: true})
+ assert_equals(ev.type, "@")
+ assert_equals(ev.bubbles, false)
+ assert_equals(ev.cancelable, true)
+})
+test(function() {
+ var ev = new Event("@", { "bubbles\0IGNORED": true, cancelable: true})
+ assert_equals(ev.type, "@")
+ assert_equals(ev.bubbles, false)
+ assert_equals(ev.cancelable, true)
+})
+test(function() {
+ var ev = new Event("Xx", { cancelable: true})
+ assert_equals(ev.type, "Xx")
+ assert_equals(ev.bubbles, false)
+ assert_equals(ev.cancelable, true)
+})
+test(function() {
+ var ev = new Event("Xx", {})
+ assert_equals(ev.type, "Xx")
+ assert_equals(ev.bubbles, false)
+ assert_equals(ev.cancelable, false)
+})
+test(function() {
+ var ev = new Event("Xx", {bubbles: true, cancelable: false, sweet: "x"})
+ assert_equals(ev.type, "Xx")
+ assert_equals(ev.bubbles, true)
+ assert_equals(ev.cancelable, false)
+ assert_equals(ev.sweet, undefined)
+})
+test(function() {
+ var called = []
+ var ev = new Event("Xx", {
+ get cancelable() {
+ called.push("cancelable")
+ return false
+ },
+ get bubbles() {
+ called.push("bubbles")
+ return true;
+ },
+ get sweet() {
+ called.push("sweet")
+ return "x"
+ }
+ })
+ assert_array_equals(called, ["bubbles", "cancelable"])
+ assert_equals(ev.type, "Xx")
+ assert_equals(ev.bubbles, true)
+ assert_equals(ev.cancelable, false)
+ assert_equals(ev.sweet, undefined)
+})
+test(function() {
+ var ev = new CustomEvent("$", {detail: 54, sweet: "x", sweet2: "x", cancelable:true})
+ assert_equals(ev.type, "$")
+ assert_equals(ev.bubbles, false)
+ assert_equals(ev.cancelable, true)
+ assert_equals(ev.sweet, undefined)
+ assert_equals(ev.detail, 54)
+})
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/events/Event-defaultPrevented.html b/tests/wpt/web-platform-tests/dom/events/Event-defaultPrevented.html
new file mode 100644
index 00000000000..dfcd4389e10
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/events/Event-defaultPrevented.html
@@ -0,0 +1,42 @@
+<!doctype html>
+<title>Event.defaultPrevented</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var ev;
+test(function() {
+ ev = document.createEvent("Event");
+ assert_equals(ev.defaultPrevented, false, "defaultPrevented");
+}, "When an event is created, defaultPrevented should be initialized to false.");
+test(function() {
+ ev.initEvent("foo", true, false);
+ assert_equals(ev.bubbles, true, "bubbles");
+ assert_equals(ev.cancelable, false, "cancelable");
+ assert_equals(ev.defaultPrevented, false, "defaultPrevented");
+}, "initEvent should work correctly (not cancelable).");
+test(function() {
+ assert_equals(ev.cancelable, false, "cancelable (before)");
+ ev.preventDefault();
+ assert_equals(ev.cancelable, false, "cancelable (after)");
+ assert_equals(ev.defaultPrevented, false, "defaultPrevented");
+}, "preventDefault() should not change defaultPrevented if cancelable is false.");
+test(function() {
+ ev.initEvent("foo", true, true);
+ assert_equals(ev.bubbles, true, "bubbles");
+ assert_equals(ev.cancelable, true, "cancelable");
+ assert_equals(ev.defaultPrevented, false, "defaultPrevented");
+}, "initEvent should work correctly (cancelable).");
+test(function() {
+ assert_equals(ev.cancelable, true, "cancelable (before)");
+ ev.preventDefault();
+ assert_equals(ev.cancelable, true, "cancelable (after)");
+ assert_equals(ev.defaultPrevented, true, "defaultPrevented");
+}, "preventDefault() should change defaultPrevented if cancelable is false.");
+test(function() {
+ ev.initEvent("foo", true, true);
+ assert_equals(ev.bubbles, true, "bubbles");
+ assert_equals(ev.cancelable, true, "cancelable");
+ assert_equals(ev.defaultPrevented, false, "defaultPrevented");
+}, "initEvent should unset defaultPrevented.");
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/events/Event-dispatch-bubbles-false.html b/tests/wpt/web-platform-tests/dom/events/Event-dispatch-bubbles-false.html
new file mode 100644
index 00000000000..c381459f5e4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/events/Event-dispatch-bubbles-false.html
@@ -0,0 +1,68 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title> Event.bubbles attribute is set to false </title>
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-event-initevent">
+<link rel="help" href="https://dom.spec.whatwg.org/#concept-event-dispatch">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<table id="table" border="1" style="display: none">
+ <tbody id="table-body">
+ <tr id="table-row">
+ <td id="table-cell">Shady Grove</td>
+ <td>Aeolian</td>
+ </tr>
+ <tr id="parent">
+ <td id="target">Over the river, Charlie</td>
+ <td>Dorian</td>
+ </tr>
+ </tbody>
+</table>
+<script>
+test(function() {
+ var event_type = "click";
+ var target = document.getElementById("target");
+ var targets = [
+ window,
+ document,
+ document.documentElement,
+ document.body,
+ document.getElementById("table"),
+ document.getElementById("table-body"),
+ document.getElementById("parent"),
+ target,
+ ];
+ var expected_targets = targets.concat(target);
+ var phases = [
+ Event.CAPTURING_PHASE,
+ Event.CAPTURING_PHASE,
+ Event.CAPTURING_PHASE,
+ Event.CAPTURING_PHASE,
+ Event.CAPTURING_PHASE,
+ Event.CAPTURING_PHASE,
+ Event.CAPTURING_PHASE,
+ Event.AT_TARGET,
+ Event.AT_TARGET,
+ ];
+
+
+ var actual_targets = [], actual_phases = [];
+ var test_event = function(evt) {
+ actual_targets.push(evt.currentTarget);
+ actual_phases.push(evt.eventPhase);
+ }
+
+ for (var i = 0; i < targets.length; i++) {
+ targets[i].addEventListener(event_type, test_event, true);
+ targets[i].addEventListener(event_type, test_event, false);
+ }
+
+ var evt = document.createEvent("Event");
+ evt.initEvent(event_type, false, true);
+
+ target.dispatchEvent(evt);
+
+ assert_array_equals(actual_targets, expected_targets, "targets");
+ assert_array_equals(actual_phases, phases, "phases");
+}, "Event.dispatchEvent with Event.bubbles set to false.");
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/events/Event-dispatch-handlers-changed.html b/tests/wpt/web-platform-tests/dom/events/Event-dispatch-handlers-changed.html
new file mode 100644
index 00000000000..b325d5c5dc6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/events/Event-dispatch-handlers-changed.html
@@ -0,0 +1,92 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title> Dispatch additional events inside an event listener </title>
+<link rel="help" href="https://dom.spec.whatwg.org/#concept-event-dispatch">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+
+<table id="table" border="1" style="display: none">
+ <tbody id="table-body">
+ <tr id="table-row">
+ <td id="table-cell">Shady Grove</td>
+ <td>Aeolian</td>
+ </tr>
+ <tr id="parent">
+ <td id="target">Over the river, Charlie</td>
+ <td>Dorian</td>
+ </tr>
+ </tbody>
+</table>
+
+<script>
+async_test(function() {
+ var event_type = "bar";
+ var target = document.getElementById("target");
+ var parent = document.getElementById("parent");
+ var tbody = document.getElementById("table-body");
+ var table = document.getElementById("table");
+ var body = document.body;
+ var html = document.documentElement;
+ var targets = [window, document, html, body, table, tbody, parent, target];
+ var expected_targets = [
+ window,
+ document,
+ html,
+ body,
+ table,
+ tbody,
+ parent,
+ target,
+ target,
+ parent,
+ tbody,
+ table,
+ body,
+ html,
+ document,
+ window
+ ];
+ var expected_listeners = [0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1];
+
+ var actual_targets = [], actual_listeners = [];
+ var test_event_function = function(i) {
+ return this.step_func(function(evt) {
+ actual_targets.push(evt.currentTarget);
+ actual_listeners.push(i);
+
+ if (evt.eventPhase != evt.BUBBLING_PHASE && evt.currentTarget.foo != 1) {
+ evt.currentTarget.removeEventListener(event_type, event_handlers[0], true);
+ evt.currentTarget.addEventListener(event_type, event_handlers[2], true);
+ evt.currentTarget.foo = 1;
+ }
+
+ if (evt.eventPhase != evt.CAPTURING_PHASE && evt.currentTarget.foo != 3) {
+ evt.currentTarget.removeEventListener(event_type, event_handlers[0], false);
+ evt.currentTarget.addEventListener(event_type, event_handlers[3], false);
+ evt.currentTarget.foo = 3;
+ }
+ });
+ }.bind(this);
+ var event_handlers = [
+ test_event_function(0),
+ test_event_function(1),
+ test_event_function(2),
+ test_event_function(3),
+ ];
+
+ for (var i = 0; i < targets.length; ++i) {
+ targets[i].addEventListener(event_type, event_handlers[0], true);
+ targets[i].addEventListener(event_type, event_handlers[1], false);
+ }
+
+ var evt = document.createEvent("Event");
+ evt.initEvent(event_type, true, true);
+ target.dispatchEvent(evt);
+
+ assert_array_equals(actual_targets, expected_targets, "actual_targets");
+ assert_array_equals(actual_listeners, expected_listeners, "actual_listeners");
+
+ this.done();
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/events/Event-dispatch-omitted-capture.html b/tests/wpt/web-platform-tests/dom/events/Event-dispatch-omitted-capture.html
new file mode 100644
index 00000000000..77074d9a3ec
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/events/Event-dispatch-omitted-capture.html
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>EventTarget.addEventListener: capture argument omitted</title>
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-eventtarget-addeventlistener">
+<link rel="help" href="https://dom.spec.whatwg.org/#concept-event-dispatch">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<table id="table" border="1" style="display: none">
+ <tbody id="table-body">
+ <tr id="table-row">
+ <td id="table-cell">Shady Grove</td>
+ <td>Aeolian</td>
+ </tr>
+ <tr id="parent">
+ <td id="target">Over the river, Charlie</td>
+ <td>Dorian</td>
+ </tr>
+ </tbody>
+</table>
+<script>
+test(function() {
+ var event_type = "foo";
+ var target = document.getElementById("target");
+ var targets = [
+ target,
+ document.getElementById("parent"),
+ document.getElementById("table-body"),
+ document.getElementById("table"),
+ document.body,
+ document.documentElement,
+ document,
+ window
+ ];
+ var phases = [
+ Event.AT_TARGET,
+ Event.BUBBLING_PHASE,
+ Event.BUBBLING_PHASE,
+ Event.BUBBLING_PHASE,
+ Event.BUBBLING_PHASE,
+ Event.BUBBLING_PHASE,
+ Event.BUBBLING_PHASE,
+ Event.BUBBLING_PHASE
+ ];
+
+ var actual_targets = [], actual_phases = [];
+ var test_event = function(evt) {
+ actual_targets.push(evt.currentTarget);
+ actual_phases.push(evt.eventPhase);
+ }
+
+ for (var i = 0; i < targets.length; i++) {
+ targets[i].addEventListener(event_type, test_event);
+ }
+
+ var evt = document.createEvent("Event");
+ evt.initEvent(event_type, true, true);
+
+ target.dispatchEvent(evt);
+
+ for (var i = 0; i < targets.length; i++) {
+ targets[i].removeEventListener(event_type, test_event);
+ }
+
+ target.dispatchEvent(evt);
+
+ assert_array_equals(actual_targets, targets, "targets");
+ assert_array_equals(actual_phases, phases, "phases");
+}, "EventTarget.addEventListener with the capture argument omitted");
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/events/Event-dispatch-redispatch.html b/tests/wpt/web-platform-tests/dom/events/Event-dispatch-redispatch.html
new file mode 100644
index 00000000000..4027587bff4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/events/Event-dispatch-redispatch.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<meta charset=urf-8>
+<title>EventTarget#dispatchEvent(): redispatching a native event</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+ var event;
+ document.addEventListener("DOMContentLoaded", this.step_func(function(e) {
+ assert_true(e.isTrusted, "Should be trusted when first handled");
+ event = e;
+ }), true);
+
+ window.onload = this.step_func_done(function() {
+ var received = 0;
+ var target = document.createElement("span");
+ target.addEventListener("DOMContentLoaded", this.step_func(function(e) {
+ assert_false(e.isTrusted, "Should not be trusted during redispatching");
+ ++received;
+ }), true);
+ assert_true(event.isTrusted, "Should be trusted before redispatching");
+ target.dispatchEvent(event);
+ assert_false(event.isTrusted, "Should not be trusted after redispatching");
+ assert_equals(received, 1);
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/events/Event-dispatch-reenter.html b/tests/wpt/web-platform-tests/dom/events/Event-dispatch-reenter.html
new file mode 100644
index 00000000000..71f8517bdd9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/events/Event-dispatch-reenter.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title> Dispatch additional events inside an event listener </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<table id="table" border="1" style="display: none">
+ <tbody id="table-body">
+ <tr id="table-row">
+ <td id="table-cell">Shady Grove</td>
+ <td>Aeolian</td>
+ </tr>
+ <tr id="parent">
+ <td id="target">Over the river, Charlie</td>
+ <td>Dorian</td>
+ </tr>
+ </tbody>
+</table>
+<script>
+test(function() {
+ var event_type = "foo";
+ var target = document.getElementById("target");
+ var parent = document.getElementById("parent");
+ var tbody = document.getElementById("table-body");
+ var table = document.getElementById("table");
+ var body = document.body;
+ var html = document.documentElement;
+ var targets = [window, document, html, body, table, tbody, parent, target];
+ var expected_targets = [
+ window, document, html, body, table,
+ target, parent, tbody,
+ table, body, html, document, window,
+ tbody, parent, target];
+ var actual_targets = [];
+ var expected_types = [
+ "foo", "foo", "foo", "foo", "foo",
+ "bar", "bar", "bar",
+ "bar", "bar", "bar", "bar", "bar",
+ "foo", "foo", "foo"
+ ];
+
+ var actual_targets = [], actual_types = [];
+ var test_event = this.step_func(function(evt) {
+ actual_targets.push(evt.currentTarget);
+ actual_types.push(evt.type);
+
+ if (table == evt.currentTarget && event_type == evt.type) {
+ var e = document.createEvent("Event");
+ e.initEvent("bar", true, true);
+ target.dispatchEvent(e);
+ }
+ });
+
+ for (var i = 0; i < targets.length; ++i) {
+ targets[i].addEventListener(event_type, test_event, true);
+ targets[i].addEventListener("bar", test_event, false);
+ }
+
+ var evt = document.createEvent("Event");
+ evt.initEvent(event_type, false, true);
+ target.dispatchEvent(evt);
+
+ assert_array_equals(actual_targets, expected_targets, "actual_targets");
+ assert_array_equals(actual_types, expected_types, "actual_types");
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/events/Event-dispatch-target-moved.html b/tests/wpt/web-platform-tests/dom/events/Event-dispatch-target-moved.html
new file mode 100644
index 00000000000..facb2c7b956
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/events/Event-dispatch-target-moved.html
@@ -0,0 +1,73 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title> Determined event propagation path - target moved </title>
+<link rel="help" href="https://dom.spec.whatwg.org/#concept-event-dispatch">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<table id="table" border="1" style="display: none">
+ <tbody id="table-body">
+ <tr id="table-row">
+ <td id="table-cell">Shady Grove</td>
+ <td>Aeolian</td>
+ </tr>
+ <tr id="parent">
+ <td id="target">Over the river, Charlie</td>
+ <td>Dorian</td>
+ </tr>
+ </tbody>
+</table>
+<script>
+test(function() {
+ var event_type = "foo";
+ var target = document.getElementById("target");
+ var parent = document.getElementById("parent");
+ var tbody = document.getElementById("table-body");
+ var table = document.getElementById("table");
+ var body = document.body;
+ var html = document.documentElement;
+ var targets = [window, document, html, body, table, tbody, parent, target];
+ var expected_targets = targets.concat([target, parent, tbody, table, body, html, document, window]);
+ var phases = [
+ Event.CAPTURING_PHASE,
+ Event.CAPTURING_PHASE,
+ Event.CAPTURING_PHASE,
+ Event.CAPTURING_PHASE,
+ Event.CAPTURING_PHASE,
+ Event.CAPTURING_PHASE,
+ Event.CAPTURING_PHASE,
+ Event.AT_TARGET,
+ Event.AT_TARGET,
+ Event.BUBBLING_PHASE,
+ Event.BUBBLING_PHASE,
+ Event.BUBBLING_PHASE,
+ Event.BUBBLING_PHASE,
+ Event.BUBBLING_PHASE,
+ Event.BUBBLING_PHASE,
+ Event.BUBBLING_PHASE,
+ ];
+
+ var actual_targets = [], actual_phases = [];
+ var test_event = this.step_func(function(evt) {
+ if (parent === target.parentNode) {
+ var table_row = document.getElementById("table-row");
+ table_row.appendChild(parent.removeChild(target));
+ }
+
+ actual_targets.push(evt.currentTarget);
+ actual_phases.push(evt.eventPhase);
+ });
+
+ for (var i = 0; i < targets.length; i++) {
+ targets[i].addEventListener(event_type, test_event, true);
+ targets[i].addEventListener(event_type, test_event, false);
+ }
+
+ var evt = document.createEvent("Event");
+ evt.initEvent(event_type, true, true);
+ target.dispatchEvent(evt);
+
+ assert_array_equals(actual_targets, expected_targets, "targets");
+ assert_array_equals(actual_phases, phases, "phases");
+}, "Event propagation path when an element in it is moved within the DOM");
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/events/Event-dispatch-target-removed.html b/tests/wpt/web-platform-tests/dom/events/Event-dispatch-target-removed.html
new file mode 100644
index 00000000000..531799c3ade
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/events/Event-dispatch-target-removed.html
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Determined event propagation path - target removed</title>
+<link rel="help" href="https://dom.spec.whatwg.org/#concept-event-dispatch">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<table id="table" border="1" style="display: none">
+ <tbody id="table-body">
+ <tr id="table-row">
+ <td id="table-cell">Shady Grove</td>
+ <td>Aeolian</td>
+ </tr>
+ <tr id="parent">
+ <td id="target">Over the river, Charlie</td>
+ <td>Dorian</td>
+ </tr>
+ </tbody>
+</table>
+<script>
+test(function() {
+ var event_type = "foo";
+ var target = document.getElementById("target");
+ var parent = document.getElementById("parent");
+ var tbody = document.getElementById("table-body");
+ var table = document.getElementById("table");
+ var body = document.body;
+ var html = document.documentElement;
+ var targets = [window, document, html, body, table, tbody, parent, target];
+ var expected_targets = targets.concat([target, parent, tbody, table, body, html, document, window]);
+ var phases = [
+ Event.CAPTURING_PHASE,
+ Event.CAPTURING_PHASE,
+ Event.CAPTURING_PHASE,
+ Event.CAPTURING_PHASE,
+ Event.CAPTURING_PHASE,
+ Event.CAPTURING_PHASE,
+ Event.CAPTURING_PHASE,
+ Event.AT_TARGET,
+ Event.AT_TARGET,
+ Event.BUBBLING_PHASE,
+ Event.BUBBLING_PHASE,
+ Event.BUBBLING_PHASE,
+ Event.BUBBLING_PHASE,
+ Event.BUBBLING_PHASE,
+ Event.BUBBLING_PHASE,
+ Event.BUBBLING_PHASE,
+ ];
+
+ var actual_targets = [], actual_phases = [];
+ var test_event = this.step_func(function(evt) {
+ if (parent === target.parentNode) {
+ parent.removeChild(target);
+ }
+
+ actual_targets.push(evt.currentTarget);
+ actual_phases.push(evt.eventPhase);
+ });
+
+ for (var i = 0; i < targets.length; i++) {
+ targets[i].addEventListener(event_type, test_event, true);
+ targets[i].addEventListener(event_type, test_event, false);
+ }
+
+ var evt = document.createEvent("Event");
+ evt.initEvent(event_type, true, true);
+ target.dispatchEvent(evt);
+
+ assert_array_equals(actual_targets, expected_targets, "targets");
+ assert_array_equals(actual_phases, phases, "phases");
+}, "Event propagation path when an element in it is removed from the DOM");
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/events/Event-initEvent.html b/tests/wpt/web-platform-tests/dom/events/Event-initEvent.html
new file mode 100644
index 00000000000..28f7faf349e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/events/Event-initEvent.html
@@ -0,0 +1,121 @@
+<!DOCTYPE html>
+<title>Event.initEvent</title>
+<link rel="author" title="Ms2ger" href="mailto:Ms2ger@gmail.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var booleans = [true, false];
+booleans.forEach(function(bubbles) {
+ booleans.forEach(function(cancelable) {
+ test(function() {
+ var e = document.createEvent("Event")
+ e.initEvent("type", bubbles, cancelable)
+
+ // Step 3.
+ // Can't test the stop propagation flag and stop immediate propagation flag.
+ assert_equals(e.defaultPrevented, false, "defaultPrevented")
+ // Step 4.
+ assert_equals(e.isTrusted, false, "isTrusted")
+ // Step 5.
+ assert_equals(e.target, null, "target")
+ // Step 6.
+ assert_equals(e.type, "type", "type")
+ // Step 7.
+ assert_equals(e.bubbles, bubbles, "bubbles")
+ // Step 8.
+ assert_equals(e.cancelable, cancelable, "cancelable")
+ }, "Properties of initEvent(type, " + bubbles + ", " + cancelable + ")")
+ })
+})
+
+test(function() {
+ var e = document.createEvent("Event")
+ e.initEvent("type 1", true, false)
+ assert_equals(e.type, "type 1", "type (first init)")
+ assert_equals(e.bubbles, true, "bubbles (first init)")
+ assert_equals(e.cancelable, false, "cancelable (first init)")
+
+ e.initEvent("type 2", false, true)
+ assert_equals(e.type, "type 2", "type (second init)")
+ assert_equals(e.bubbles, false, "bubbles (second init)")
+ assert_equals(e.cancelable, true, "cancelable (second init)")
+}, "Calling initEvent multiple times (getting type).")
+
+test(function() {
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=998809
+ var e = document.createEvent("Event")
+ e.initEvent("type 1", true, false)
+ assert_equals(e.bubbles, true, "bubbles (first init)")
+ assert_equals(e.cancelable, false, "cancelable (first init)")
+
+ e.initEvent("type 2", false, true)
+ assert_equals(e.type, "type 2", "type (second init)")
+ assert_equals(e.bubbles, false, "bubbles (second init)")
+ assert_equals(e.cancelable, true, "cancelable (second init)")
+}, "Calling initEvent multiple times (not getting type).")
+
+// Step 2.
+async_test(function() {
+ // https://www.w3.org/Bugs/Public/show_bug.cgi?id=17715
+
+ var e = document.createEvent("Event")
+ e.initEvent("type", false, false)
+ assert_equals(e.type, "type", "type (first init)")
+ assert_equals(e.bubbles, false, "bubbles (first init)")
+ assert_equals(e.cancelable, false, "cancelable (first init)")
+
+ var target = document.createElement("div")
+ target.addEventListener("type", this.step_func(function() {
+ e.initEvent("fail", true, true)
+ assert_equals(e.type, "type", "type (second init)")
+ assert_equals(e.bubbles, false, "bubbles (second init)")
+ assert_equals(e.cancelable, false, "cancelable (second init)")
+ }), false)
+
+ assert_equals(target.dispatchEvent(e), true, "dispatchEvent must return true")
+
+ this.done()
+}, "Calling initEvent must not have an effect during dispatching.")
+
+async_test(function() {
+ var e = document.createEvent("Event")
+ e.initEvent("type", false, false)
+ e.stopPropagation()
+
+ var target = document.createElement("div")
+ target.addEventListener("type", this.step_func(function() {
+ assert_unreached("")
+ }), false)
+ assert_equals(target.dispatchEvent(e), true, "dispatchEvent must return true")
+ assert_equals(target.dispatchEvent(e), true, "dispatchEvent must return true")
+
+ e.initEvent("type", false, false)
+ var called = false
+ var target = document.createElement("div")
+ target.addEventListener("type", this.step_func(function() {
+ called = true
+ }), false)
+ assert_false(called)
+ assert_equals(target.dispatchEvent(e), true, "dispatchEvent must return true")
+ assert_true(called)
+
+ this.done()
+}, "Calling initEvent must unset the stop propagation flag.")
+
+async_test(function() {
+ var e = document.createEvent("Event")
+ e.initEvent("type", false, false)
+
+ var target = document.createElement("div")
+ target.addEventListener("type", this.step_func(function() {
+ e.initEvent("type2", true, true);
+ assert_equals(e.type, "type", "initEvent type setter should short-circuit");
+ assert_false(e.bubbles, "initEvent bubbles setter should short-circuit");
+ assert_false(e.cancelable, "initEvent cancelable setter should short-circuit");
+ }), false)
+ assert_equals(target.dispatchEvent(e), true, "dispatchEvent must return true")
+
+ this.done()
+}, "Calling initEvent during propagation.")
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/events/Event-propagation.html b/tests/wpt/web-platform-tests/dom/events/Event-propagation.html
new file mode 100644
index 00000000000..c57c7e9b255
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/events/Event-propagation.html
@@ -0,0 +1,38 @@
+<!doctype html>
+<title>Event propagation tests</title>
+<link rel=author title="Aryeh Gregor" href=ayg@aryeh.name>
+<div id=log></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+"use strict";
+
+function testPropagationFlag(ev, expected, desc) {
+ test(function() {
+ var called = false;
+ var callback = function() { called = true };
+ document.head.addEventListener("foo", callback);
+ document.head.dispatchEvent(ev);
+ // Gecko resets the flags after dispatching; it will happily dispatch
+ // the event the second time around.
+ document.head.dispatchEvent(ev);
+ assert_equals(called, expected, "Propagation flag");
+ document.head.removeEventListener("foo", callback);
+ }, desc);
+}
+
+var ev = document.createEvent("Event");
+ev.initEvent("foo", true, false);
+testPropagationFlag(ev, true, "Newly-created Event");
+ev.stopPropagation();
+testPropagationFlag(ev, false, "After stopPropagation()");
+ev.initEvent("foo", true, false);
+testPropagationFlag(ev, true, "Reinitialized after stopPropagation()");
+
+var ev = document.createEvent("Event");
+ev.initEvent("foo", true, false);
+ev.stopImmediatePropagation();
+testPropagationFlag(ev, false, "After stopImmediatePropagation()");
+ev.initEvent("foo", true, false);
+testPropagationFlag(ev, true, "Reinitialized after stopImmediatePropagation()");
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/events/Event-type-empty.html b/tests/wpt/web-platform-tests/dom/events/Event-type-empty.html
new file mode 100644
index 00000000000..225b85a613a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/events/Event-type-empty.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<title>Event.type set to the empty string</title>
+<link rel="author" title="Ms2ger" href="mailto:Ms2ger@gmail.com">
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-event-type">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+function do_test(t, e) {
+ assert_equals(e.type, "", "type");
+ assert_equals(e.bubbles, false, "bubbles");
+ assert_equals(e.cancelable, false, "cancelable");
+
+ var target = document.createElement("div");
+ var handled = false;
+ target.addEventListener("", t.step_func(function(e) {
+ handled = true;
+ }));
+ assert_true(target.dispatchEvent(e));
+ assert_true(handled);
+}
+
+async_test(function() {
+ var e = document.createEvent("Event");
+ e.initEvent("", false, false);
+ do_test(this, e);
+ this.done();
+}, "initEvent");
+
+async_test(function() {
+ var e = new Event("");
+ do_test(this, e);
+ this.done();
+}, "Constructor");
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/events/Event-type.html b/tests/wpt/web-platform-tests/dom/events/Event-type.html
new file mode 100644
index 00000000000..22792f5c6c7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/events/Event-type.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<title>Event.type</title>
+<link rel="author" title="Ms2ger" href="mailto:Ms2ger@gmail.com">
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-event-type">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ var e = document.createEvent("Event")
+ assert_equals(e.type, "");
+}, "Event.type should initially be the empty string");
+test(function() {
+ var e = document.createEvent("Event")
+ e.initEvent("foo", false, false)
+ assert_equals(e.type, "foo")
+}, "Event.type should be initialized by initEvent");
+test(function() {
+ var e = new Event("bar")
+ assert_equals(e.type, "bar")
+}, "Event.type should be initialized by the constructor");
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/events/EventTarget-addEventListener.html b/tests/wpt/web-platform-tests/dom/events/EventTarget-addEventListener.html
new file mode 100644
index 00000000000..e2a46e5813e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/events/EventTarget-addEventListener.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>EventTarget.addEventListener</title>
+<link rel="author" title="Ms2ger" href="mailto:Ms2ger@gmail.com">
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-eventtarget-addeventlistener">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+// Step 1.
+test(function() {
+ assert_equals(document.addEventListener("x", null, false), undefined);
+ assert_equals(document.addEventListener("x", null, true), undefined);
+ assert_equals(document.addEventListener("x", null), undefined);
+}, "Adding a null event listener should succeed");
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/events/EventTarget-dispatchEvent-returnvalue.html b/tests/wpt/web-platform-tests/dom/events/EventTarget-dispatchEvent-returnvalue.html
new file mode 100644
index 00000000000..8804c38a53b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/events/EventTarget-dispatchEvent-returnvalue.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>EventTarget.dispatchEvent: return value</title>
+<link rel="help" href="https://dom.spec.whatwg.org/#concept-event-dispatch">
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-event-preventdefault">
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-event-defaultprevented">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<table id="table" border="1" style="display: none">
+ <tbody id="table-body">
+ <tr id="table-row">
+ <td id="table-cell">Shady Grove</td>
+ <td>Aeolian</td>
+ </tr>
+ <tr id="parent">
+ <td id="target">Over the river, Charlie</td>
+ <td>Dorian</td>
+ </tr>
+ </tbody>
+</table>
+<script>
+test(function() {
+ var event_type = "foo";
+ var target = document.getElementById("target");
+ var parent = document.getElementById("parent");
+ var default_prevented;
+
+ parent.addEventListener(event_type, function(e) {}, true);
+ target.addEventListener(event_type, function(e) {
+ evt.preventDefault();
+ default_prevented = evt.defaultPrevented;
+ }, true);
+ target.addEventListener(event_type, function(e) {}, true);
+
+ var evt = document.createEvent("Event");
+ evt.initEvent(event_type, true, true);
+
+ assert_true(parent.dispatchEvent(evt));
+ assert_false(target.dispatchEvent(evt));
+ assert_true(default_prevented);
+}, "Return value of EventTarget.dispatchEvent.");
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/events/EventTarget-dispatchEvent.html b/tests/wpt/web-platform-tests/dom/events/EventTarget-dispatchEvent.html
new file mode 100644
index 00000000000..354441aa03e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/events/EventTarget-dispatchEvent.html
@@ -0,0 +1,104 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>EventTarget.dispatchEvent</title>
+<link rel="author" title="Olli Pettay" href="mailto:Olli.Pettay@gmail.com">
+<link rel="author" title="Ms2ger" href="mailto:Ms2ger@gmail.com">
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-eventtarget-dispatchevent">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/dom/nodes/Document-createEvent.js"></script>
+<div id="log"></div>
+<script>
+setup({
+ "allow_uncaught_exception": true,
+})
+
+test(function() {
+ assert_throws(new TypeError(), function() { document.dispatchEvent(null) })
+}, "Calling dispatchEvent(null).")
+
+aliases.forEach(function(alias) {
+ test(function() {
+ var e = document.createEvent(alias[0])
+ assert_equals(e.type, "", "Event type should be empty string before initialization")
+ assert_throws("InvalidStateError", function() { document.dispatchEvent(e) })
+ }, "If the event's initialized flag is not set, an InvalidStateError must be thrown (" + alias [0] + ").")
+})
+
+var dispatch_dispatch = async_test("If the event's dispatch flag is set, an InvalidStateError must be thrown.")
+dispatch_dispatch.step(function() {
+ var e = document.createEvent("Event")
+ e.initEvent("type", false, false)
+
+ var target = document.createElement("div")
+ target.addEventListener("type", dispatch_dispatch.step_func(function() {
+ assert_throws("InvalidStateError", function() {
+ target.dispatchEvent(e)
+ })
+ assert_throws("InvalidStateError", function() {
+ document.dispatchEvent(e)
+ })
+ }), false)
+
+ assert_equals(target.dispatchEvent(e), true, "dispatchEvent must return true")
+
+ dispatch_dispatch.done()
+})
+
+test(function() {
+ // https://www.w3.org/Bugs/Public/show_bug.cgi?id=17713
+ // https://www.w3.org/Bugs/Public/show_bug.cgi?id=17714
+
+ var e = document.createEvent("Event")
+ e.initEvent("type", false, false)
+
+ var called = []
+
+ var target = document.createElement("div")
+ target.addEventListener("type", function() {
+ called.push("First")
+ throw new Error()
+ }, false)
+
+ target.addEventListener("type", function() {
+ called.push("Second")
+ }, false)
+
+ assert_equals(target.dispatchEvent(e), true, "dispatchEvent must return true")
+ assert_array_equals(called, ["First", "Second"],
+ "Should have continued to call other event listeners")
+}, "Exceptions from event listeners must not be propagated.")
+
+async_test(function() {
+ var results = []
+ var outerb = document.createElement("b")
+ var middleb = outerb.appendChild(document.createElement("b"))
+ var innerb = middleb.appendChild(document.createElement("b"))
+ outerb.addEventListener("x", this.step_func(function() {
+ middleb.addEventListener("x", this.step_func(function() {
+ results.push("middle")
+ }), true)
+ results.push("outer")
+ }), true)
+ innerb.dispatchEvent(new Event("x"))
+ assert_array_equals(results, ["outer", "middle"])
+ this.done()
+}, "Event listeners added during dispatch should be called");
+
+async_test(function() {
+ var results = []
+ var b = document.createElement("b")
+ b.addEventListener("x", this.step_func(function() {
+ results.push(1)
+ }), true)
+ b.addEventListener("x", this.step_func(function() {
+ results.push(2)
+ }), false)
+ b.addEventListener("x", this.step_func(function() {
+ results.push(3)
+ }), true)
+ b.dispatchEvent(new Event("x"))
+ assert_array_equals(results, [1, 2, 3])
+ this.done()
+}, "Event listeners should be called in order of addition")
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/events/EventTarget-removeEventListener.html b/tests/wpt/web-platform-tests/dom/events/EventTarget-removeEventListener.html
new file mode 100644
index 00000000000..da2d7db3c4d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/events/EventTarget-removeEventListener.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>EventTarget.removeEventListener</title>
+<link rel="author" title="Ms2ger" href="mailto:Ms2ger@gmail.com">
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-eventtarget-removeeventlistener">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+// Step 1.
+test(function() {
+ assert_equals(document.removeEventListener("x", null, false), undefined);
+ assert_equals(document.removeEventListener("x", null, true), undefined);
+ assert_equals(document.removeEventListener("x", null), undefined);
+}, "removing a null event listener should succeed");
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/events/ProgressEvent.html b/tests/wpt/web-platform-tests/dom/events/ProgressEvent.html
new file mode 100644
index 00000000000..2b2f7bc51b7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/events/ProgressEvent.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<title>ProgressEvent constructor</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function() {
+ var ev = new ProgressEvent("test")
+ assert_equals(ev.type, "test")
+ assert_equals(ev.target, null)
+ assert_equals(ev.currentTarget, null)
+ assert_equals(ev.eventPhase, Event.NONE)
+ assert_equals(ev.bubbles, false)
+ assert_equals(ev.cancelable, false)
+ assert_equals(ev.defaultPrevented, false)
+ assert_equals(ev.isTrusted, false)
+ assert_true(ev.timeStamp > 0)
+ assert_true("initEvent" in ev)
+}, "Default event values.")
+test(function() {
+ assert_throws("NotSupportedError", function() {
+ document.createEvent("ProgressEvent")
+ })
+}, "document.createEvent() should not work with ProgressEvent.")
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/historical.html b/tests/wpt/web-platform-tests/dom/historical.html
new file mode 100644
index 00000000000..6c02ecbd5cc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/historical.html
@@ -0,0 +1,133 @@
+<!DOCTYPE html>
+<title>Historical DOM features must be removed</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+function isInterfaceNuked(name) {
+ test(function() {
+ assert_equals(window[name], undefined)
+ }, "Historical DOM features must be removed: " + name)
+}
+var nukedInterfaces = [
+ "CDATASection",
+ "DOMConfiguration",
+ "DOMError",
+ "DOMErrorHandler",
+ "DOMImplementationList",
+ "DOMImplementationSource",
+ "DOMLocator",
+ "DOMObject",
+ "DOMUserData",
+ "Entity",
+ "EntityReference",
+ "EventException", // DOM Events
+ "NameList",
+ "Notation",
+ "TypeInfo",
+ "UserDataHandler",
+ "RangeException" // DOM Range
+]
+nukedInterfaces.forEach(isInterfaceNuked)
+
+function isNukedFromDocument(name) {
+ test(function() {
+ var doc = document.implementation.createDocument(null,null,null)
+ assert_equals(document[name], undefined)
+ assert_equals(doc[name], undefined)
+ }, "Historical DOM features must be removed: " + name)
+}
+var documentNuked = [
+ "createCDATASection",
+ "createEntityReference",
+ "xmlEncoding",
+ "xmlStandalone",
+ "xmlVersion",
+ "strictErrorChecking",
+ "domConfig",
+ "normalizeDocument",
+ "renameNode",
+ "charset",
+ "defaultCharset",
+ "height",
+ "width"
+]
+documentNuked.forEach(isNukedFromDocument)
+
+test(function() {
+ assert_equals(document.implementation["getFeature"], undefined)
+}, "DOMImplementation.getFeature() must be nuked.")
+
+function isNukedFromElement(name) {
+ test(function() {
+ var ele = document.createElementNS("test", "test")
+ assert_equals(document.body[name], undefined)
+ assert_equals(ele[name], undefined)
+ }, "Historical DOM features must be removed: " + name)
+}
+var elementNuked = [
+ "schemaTypeInfo",
+ "setIdAttribute",
+ "setIdAttributeNS",
+ "setIdAttributeNode"
+]
+elementNuked.forEach(isNukedFromElement)
+
+function isNukedFromDoctype(name) {
+ test(function() {
+ var doctype = document.implementation.createDocumentType("test", "", "")
+ assert_equals(doctype[name], undefined)
+ }, "DocumentType member must be nuked: " + name)
+}
+var doctypeNuked = [
+ "entities",
+ "notations",
+ "internalSubset"
+]
+doctypeNuked.forEach(isNukedFromDoctype)
+
+function isNukedFromText(name) {
+ test(function() {
+ var text = document.createTextNode("test")
+ assert_equals(text[name], undefined)
+ }, "Text member must be nuked: " + name)
+}
+var textNuked = [
+ "isElementContentWhitespace",
+ "replaceWholeText"
+]
+textNuked.forEach(isNukedFromText)
+
+function isNukedFromNode(name) {
+ test(function() {
+ var doc = document.implementation.createDocument(null,null,null)
+ var doctype = document.implementation.createDocumentType("test", "", "")
+ var text = document.createTextNode("test")
+ assert_equals(doc[name], undefined)
+ assert_equals(doctype[name], undefined)
+ assert_equals(text[name], undefined)
+ }, "Node member must be nuked: " + name)
+}
+var nodeNuked = [
+ "hasAttributes",
+ "attributes",
+ "namespaceURI",
+ "prefix",
+ "localName",
+ "isSupported",
+ "getFeature",
+ "getUserData",
+ "setUserData"
+]
+nodeNuked.forEach(isNukedFromNode)
+
+function isNukedFromWindow(name) {
+ test(function() {
+ assert_equals(window[name], undefined)
+ }, "Window member must be nuked: " + name)
+}
+var windowNuked = [
+ "attachEvent"
+]
+windowNuked.forEach(isNukedFromWindow)
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/interface-objects.html b/tests/wpt/web-platform-tests/dom/interface-objects.html
new file mode 100644
index 00000000000..c0697b566c1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/interface-objects.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<title>Interfaces</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+function testInterfaceDeletable(iface) {
+ test(function() {
+ assert_true(!!window[iface], "Interface should exist.")
+ assert_true(delete window[iface], "The delete operator should return true.")
+ assert_equals(window[iface], undefined, "Interface should be gone.")
+ }, "Should be able to delete " + iface + ".")
+}
+var interfaces = [
+ "Event",
+ "CustomEvent",
+ "EventTarget",
+ "Node",
+ "Document",
+ "DOMImplementation",
+ "DocumentFragment",
+ "ProcessingInstruction",
+ "DocumentType",
+ "Element",
+ "Attr",
+ "CharacterData",
+ "Text",
+ "Comment",
+ "NodeIterator",
+ "TreeWalker",
+ "NodeFilter",
+ "NodeList",
+ "HTMLCollection",
+ "DOMStringList",
+ "DOMTokenList",
+ "DOMSettableTokenList"
+];
+test(function() {
+ for (var p in window) {
+ interfaces.forEach(function(i) {
+ assert_not_equals(p, i)
+ })
+ }
+}, "Interface objects properties should not be Enumerable")
+interfaces.forEach(testInterfaceDeletable);
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/interfaces.html b/tests/wpt/web-platform-tests/dom/interfaces.html
new file mode 100644
index 00000000000..69ae1561c9c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/interfaces.html
@@ -0,0 +1,504 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>DOM IDL tests</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=/resources/WebIDLParser.js></script>
+<script src=/resources/idlharness.js></script>
+
+<h1>DOM IDL tests</h1>
+<div id=log></div>
+
+<script type=text/plain>
+[Constructor(DOMString type, optional EventInit eventInitDict)/*,
+ Exposed=(Window,Worker)*/]
+interface Event {
+ readonly attribute DOMString type;
+ readonly attribute EventTarget? target;
+ readonly attribute EventTarget? currentTarget;
+
+ const unsigned short NONE = 0;
+ const unsigned short CAPTURING_PHASE = 1;
+ const unsigned short AT_TARGET = 2;
+ const unsigned short BUBBLING_PHASE = 3;
+ readonly attribute unsigned short eventPhase;
+
+ void stopPropagation();
+ void stopImmediatePropagation();
+
+ readonly attribute boolean bubbles;
+ readonly attribute boolean cancelable;
+ void preventDefault();
+ readonly attribute boolean defaultPrevented;
+
+ [Unforgeable] readonly attribute boolean isTrusted;
+ readonly attribute DOMTimeStamp timeStamp;
+
+ void initEvent(DOMString type, boolean bubbles, boolean cancelable);
+};
+
+dictionary EventInit {
+ boolean bubbles = false;
+ boolean cancelable = false;
+};
+
+[Constructor(DOMString type, optional CustomEventInit eventInitDict)/*,
+ Exposed=(Window,Worker)*/]
+interface CustomEvent : Event {
+ readonly attribute any detail;
+
+ void initCustomEvent(DOMString type, boolean bubbles, boolean cancelable, any detail);
+};
+
+dictionary CustomEventInit : EventInit {
+ any detail = null;
+};
+
+//[Exposed=(Window,Worker)]
+interface EventTarget {
+ void addEventListener(DOMString type, EventListener? callback, optional boolean capture = false);
+ void removeEventListener(DOMString type, EventListener? callback, optional boolean capture = false);
+ boolean dispatchEvent(Event event);
+};
+
+callback interface EventListener {
+ void handleEvent(Event event);
+};
+
+[NoInterfaceObject]
+interface NonElementParentNode {
+ Element? getElementById(DOMString elementId);
+};
+Document implements NonElementParentNode;
+DocumentFragment implements NonElementParentNode;
+
+[NoInterfaceObject]
+interface ParentNode {
+ [SameObject] readonly attribute HTMLCollection children;
+ readonly attribute Element? firstElementChild;
+ readonly attribute Element? lastElementChild;
+ readonly attribute unsigned long childElementCount;
+
+ [Unscopeable] void prepend((Node or DOMString)... nodes);
+ [Unscopeable] void append((Node or DOMString)... nodes);
+
+ [Unscopeable] Element? query(DOMString relativeSelectors);
+ [NewObject, Unscopeable] Elements queryAll(DOMString relativeSelectors);
+ Element? querySelector(DOMString selectors);
+ [NewObject] NodeList querySelectorAll(DOMString selectors);
+};
+Document implements ParentNode;
+DocumentFragment implements ParentNode;
+Element implements ParentNode;
+
+[NoInterfaceObject]
+interface NonDocumentTypeChildNode {
+ readonly attribute Element? previousElementSibling;
+ readonly attribute Element? nextElementSibling;
+};
+Element implements NonDocumentTypeChildNode;
+CharacterData implements NonDocumentTypeChildNode;
+
+[NoInterfaceObject]
+interface ChildNode {
+ [Unscopeable] void before((Node or DOMString)... nodes);
+ [Unscopeable] void after((Node or DOMString)... nodes);
+ [Unscopeable] void replaceWith((Node or DOMString)... nodes);
+ [Unscopeable] void remove();
+};
+DocumentType implements ChildNode;
+Element implements ChildNode;
+CharacterData implements ChildNode;
+
+// XXX unrecognized tokens "class", "extends"
+// https://www.w3.org/Bugs/Public/show_bug.cgi?id=20020
+// https://www.w3.org/Bugs/Public/show_bug.cgi?id=23225
+//class Elements extends Array {
+// Element? query(DOMString relativeSelectors);
+// Elements queryAll(DOMString relativeSelectors);
+//};
+
+interface NodeList {
+ getter Node? item(unsigned long index);
+ readonly attribute unsigned long length;
+// iterable<Node>;
+};
+
+interface HTMLCollection {
+ readonly attribute unsigned long length;
+ getter Element? item(unsigned long index);
+ getter Element? namedItem(DOMString name);
+};
+
+[Constructor(MutationCallback callback)]
+interface MutationObserver {
+ void observe(Node target, MutationObserverInit options);
+ void disconnect();
+ sequence<MutationRecord> takeRecords();
+};
+
+callback MutationCallback = void (sequence<MutationRecord> mutations, MutationObserver observer);
+
+dictionary MutationObserverInit {
+ boolean childList = false;
+ boolean attributes;
+ boolean characterData;
+ boolean subtree = false;
+ boolean attributeOldValue;
+ boolean characterDataOldValue;
+ sequence<DOMString> attributeFilter;
+};
+
+interface MutationRecord {
+ readonly attribute DOMString type;
+ readonly attribute Node target;
+ [SameObject] readonly attribute NodeList addedNodes;
+ [SameObject] readonly attribute NodeList removedNodes;
+ readonly attribute Node? previousSibling;
+ readonly attribute Node? nextSibling;
+ readonly attribute DOMString? attributeName;
+ readonly attribute DOMString? attributeNamespace;
+ readonly attribute DOMString? oldValue;
+};
+
+interface Node : EventTarget {
+ const unsigned short ELEMENT_NODE = 1;
+ const unsigned short ATTRIBUTE_NODE = 2; // historical
+ const unsigned short TEXT_NODE = 3;
+ const unsigned short CDATA_SECTION_NODE = 4; // historical
+ const unsigned short ENTITY_REFERENCE_NODE = 5; // historical
+ const unsigned short ENTITY_NODE = 6; // historical
+ const unsigned short PROCESSING_INSTRUCTION_NODE = 7;
+ const unsigned short COMMENT_NODE = 8;
+ const unsigned short DOCUMENT_NODE = 9;
+ const unsigned short DOCUMENT_TYPE_NODE = 10;
+ const unsigned short DOCUMENT_FRAGMENT_NODE = 11;
+ const unsigned short NOTATION_NODE = 12; // historical
+ readonly attribute unsigned short nodeType;
+ readonly attribute DOMString nodeName;
+
+ readonly attribute DOMString? baseURI;
+
+ readonly attribute Document? ownerDocument;
+ readonly attribute Node? parentNode;
+ readonly attribute Element? parentElement;
+ boolean hasChildNodes();
+ [SameObject] readonly attribute NodeList childNodes;
+ readonly attribute Node? firstChild;
+ readonly attribute Node? lastChild;
+ readonly attribute Node? previousSibling;
+ readonly attribute Node? nextSibling;
+
+ attribute DOMString? nodeValue;
+ attribute DOMString? textContent;
+ void normalize();
+
+ [NewObject] Node cloneNode(optional boolean deep = false);
+ boolean isEqualNode(Node? node);
+
+ const unsigned short DOCUMENT_POSITION_DISCONNECTED = 0x01;
+ const unsigned short DOCUMENT_POSITION_PRECEDING = 0x02;
+ const unsigned short DOCUMENT_POSITION_FOLLOWING = 0x04;
+ const unsigned short DOCUMENT_POSITION_CONTAINS = 0x08;
+ const unsigned short DOCUMENT_POSITION_CONTAINED_BY = 0x10;
+ const unsigned short DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0x20;
+ unsigned short compareDocumentPosition(Node other);
+ boolean contains(Node? other);
+
+ DOMString? lookupPrefix(DOMString? namespace);
+ DOMString? lookupNamespaceURI(DOMString? prefix);
+ boolean isDefaultNamespace(DOMString? namespace);
+
+ Node insertBefore(Node node, Node? child);
+ Node appendChild(Node node);
+ Node replaceChild(Node node, Node child);
+ Node removeChild(Node child);
+};
+
+[Constructor]
+interface Document : Node {
+ [SameObject] readonly attribute DOMImplementation implementation;
+ readonly attribute DOMString URL;
+ readonly attribute DOMString documentURI;
+ readonly attribute DOMString origin;
+ readonly attribute DOMString compatMode;
+ readonly attribute DOMString characterSet;
+ readonly attribute DOMString inputEncoding; // legacy alias of .characterSet
+ readonly attribute DOMString contentType;
+
+ readonly attribute DocumentType? doctype;
+ readonly attribute Element? documentElement;
+ HTMLCollection getElementsByTagName(DOMString localName);
+ HTMLCollection getElementsByTagNameNS(DOMString? namespace, DOMString localName);
+ HTMLCollection getElementsByClassName(DOMString classNames);
+
+ [NewObject] Element createElement(DOMString localName);
+ [NewObject] Element createElementNS(DOMString? namespace, DOMString qualifiedName);
+ [NewObject] DocumentFragment createDocumentFragment();
+ [NewObject] Text createTextNode(DOMString data);
+ [NewObject] Comment createComment(DOMString data);
+ [NewObject] ProcessingInstruction createProcessingInstruction(DOMString target, DOMString data);
+
+ [NewObject] Node importNode(Node node, optional boolean deep = false);
+ Node adoptNode(Node node);
+
+ [NewObject] Attr createAttribute(DOMString localName);
+ [NewObject] Attr createAttributeNS(DOMString? namespace, DOMString name);
+
+ [NewObject] Event createEvent(DOMString interface);
+
+ [NewObject] Range createRange();
+
+ // NodeFilter.SHOW_ALL = 0xFFFFFFFF
+ [NewObject] NodeIterator createNodeIterator(Node root, optional unsigned long whatToShow = 0xFFFFFFFF, optional NodeFilter? filter = null);
+ [NewObject] TreeWalker createTreeWalker(Node root, optional unsigned long whatToShow = 0xFFFFFFFF, optional NodeFilter? filter = null);
+};
+
+interface XMLDocument : Document {};
+
+interface DOMImplementation {
+ [NewObject] DocumentType createDocumentType(DOMString qualifiedName, DOMString publicId, DOMString systemId);
+ [NewObject] XMLDocument createDocument(DOMString? namespace, [TreatNullAs=EmptyString] DOMString qualifiedName, optional DocumentType? doctype = null);
+ [NewObject] Document createHTMLDocument(optional DOMString title);
+
+ boolean hasFeature(); // useless; always returns true
+};
+
+[Constructor]
+interface DocumentFragment : Node {
+};
+
+interface DocumentType : Node {
+ readonly attribute DOMString name;
+ readonly attribute DOMString publicId;
+ readonly attribute DOMString systemId;
+};
+
+interface Element : Node {
+ readonly attribute DOMString? namespaceURI;
+ readonly attribute DOMString? prefix;
+ readonly attribute DOMString localName;
+ readonly attribute DOMString tagName;
+
+ attribute DOMString id;
+ attribute DOMString className;
+ [SameObject] readonly attribute DOMTokenList classList;
+
+ boolean hasAttributes();
+ [SameObject] readonly attribute NamedNodeMap attributes;
+ DOMString? getAttribute(DOMString name);
+ DOMString? getAttributeNS(DOMString? namespace, DOMString localName);
+ void setAttribute(DOMString name, DOMString value);
+ void setAttributeNS(DOMString? namespace, DOMString name, DOMString value);
+ void removeAttribute(DOMString name);
+ void removeAttributeNS(DOMString? namespace, DOMString localName);
+ boolean hasAttribute(DOMString name);
+ boolean hasAttributeNS(DOMString? namespace, DOMString localName);
+
+ Attr? getAttributeNode(DOMString name);
+ Attr? getAttributeNodeNS(DOMString? namespace, DOMString localName);
+ Attr? setAttributeNode(Attr attr);
+ Attr? setAttributeNodeNS(Attr attr);
+ Attr removeAttributeNode(Attr attr);
+
+ Element? closest(DOMString selectors);
+ boolean matches(DOMString selectors);
+
+ HTMLCollection getElementsByTagName(DOMString localName);
+ HTMLCollection getElementsByTagNameNS(DOMString? namespace, DOMString localName);
+ HTMLCollection getElementsByClassName(DOMString classNames);
+};
+
+interface NamedNodeMap {
+ readonly attribute unsigned long length;
+ getter Attr? item(unsigned long index);
+ getter Attr? getNamedItem(DOMString name);
+ Attr? getNamedItemNS(DOMString? namespace, DOMString localName);
+ Attr? setNamedItem(Attr attr);
+ Attr? setNamedItemNS(Attr attr);
+ Attr removeNamedItem(DOMString name);
+ Attr removeNamedItemNS(DOMString? namespace, DOMString localName);
+};
+
+interface Attr {
+ readonly attribute DOMString? namespaceURI;
+ readonly attribute DOMString? prefix;
+ readonly attribute DOMString localName;
+ readonly attribute DOMString name;
+ attribute DOMString value;
+ attribute DOMString nodeValue; // legacy alias of .value
+ attribute DOMString textContent; // legacy alias of .value
+
+ readonly attribute Element? ownerElement;
+
+ readonly attribute boolean specified; // useless; always returns true
+};
+
+interface CharacterData : Node {
+ [TreatNullAs=EmptyString] attribute DOMString data;
+ readonly attribute unsigned long length;
+ DOMString substringData(unsigned long offset, unsigned long count);
+ void appendData(DOMString data);
+ void insertData(unsigned long offset, DOMString data);
+ void deleteData(unsigned long offset, unsigned long count);
+ void replaceData(unsigned long offset, unsigned long count, DOMString data);
+};
+
+[Constructor(optional DOMString data = "")]
+interface Text : CharacterData {
+ [NewObject] Text splitText(unsigned long offset);
+ readonly attribute DOMString wholeText;
+};
+
+interface ProcessingInstruction : CharacterData {
+ readonly attribute DOMString target;
+};
+
+[Constructor(optional DOMString data = "")]
+interface Comment : CharacterData {
+};
+
+[Constructor]
+interface Range {
+ readonly attribute Node startContainer;
+ readonly attribute unsigned long startOffset;
+ readonly attribute Node endContainer;
+ readonly attribute unsigned long endOffset;
+ readonly attribute boolean collapsed;
+ readonly attribute Node commonAncestorContainer;
+
+ void setStart(Node node, unsigned long offset);
+ void setEnd(Node node, unsigned long offset);
+ void setStartBefore(Node node);
+ void setStartAfter(Node node);
+ void setEndBefore(Node node);
+ void setEndAfter(Node node);
+ void collapse(optional boolean toStart = false);
+ void selectNode(Node node);
+ void selectNodeContents(Node node);
+
+ const unsigned short START_TO_START = 0;
+ const unsigned short START_TO_END = 1;
+ const unsigned short END_TO_END = 2;
+ const unsigned short END_TO_START = 3;
+ short compareBoundaryPoints(unsigned short how, Range sourceRange);
+
+ void deleteContents();
+ [NewObject] DocumentFragment extractContents();
+ [NewObject] DocumentFragment cloneContents();
+ void insertNode(Node node);
+ void surroundContents(Node newParent);
+
+ [NewObject] Range cloneRange();
+ void detach();
+
+ boolean isPointInRange(Node node, unsigned long offset);
+ short comparePoint(Node node, unsigned long offset);
+
+ boolean intersectsNode(Node node);
+
+ stringifier;
+};
+
+interface NodeIterator {
+ [SameObject] readonly attribute Node root;
+ readonly attribute Node referenceNode;
+ readonly attribute boolean pointerBeforeReferenceNode;
+ readonly attribute unsigned long whatToShow;
+ readonly attribute NodeFilter? filter;
+
+ Node? nextNode();
+ Node? previousNode();
+
+ void detach();
+};
+
+interface TreeWalker {
+ [SameObject] readonly attribute Node root;
+ readonly attribute unsigned long whatToShow;
+ readonly attribute NodeFilter? filter;
+ attribute Node currentNode;
+
+ Node? parentNode();
+ Node? firstChild();
+ Node? lastChild();
+ Node? previousSibling();
+ Node? nextSibling();
+ Node? previousNode();
+ Node? nextNode();
+};
+
+callback interface NodeFilter {
+ // Constants for acceptNode()
+ const unsigned short FILTER_ACCEPT = 1;
+ const unsigned short FILTER_REJECT = 2;
+ const unsigned short FILTER_SKIP = 3;
+
+ // Constants for whatToShow
+ const unsigned long SHOW_ALL = 0xFFFFFFFF;
+ const unsigned long SHOW_ELEMENT = 0x1;
+ const unsigned long SHOW_ATTRIBUTE = 0x2; // historical
+ const unsigned long SHOW_TEXT = 0x4;
+ const unsigned long SHOW_CDATA_SECTION = 0x8; // historical
+ const unsigned long SHOW_ENTITY_REFERENCE = 0x10; // historical
+ const unsigned long SHOW_ENTITY = 0x20; // historical
+ const unsigned long SHOW_PROCESSING_INSTRUCTION = 0x40;
+ const unsigned long SHOW_COMMENT = 0x80;
+ const unsigned long SHOW_DOCUMENT = 0x100;
+ const unsigned long SHOW_DOCUMENT_TYPE = 0x200;
+ const unsigned long SHOW_DOCUMENT_FRAGMENT = 0x400;
+ const unsigned long SHOW_NOTATION = 0x800; // historical
+
+ unsigned short acceptNode(Node node);
+};
+
+interface DOMTokenList {
+ readonly attribute unsigned long length;
+ getter DOMString? item(unsigned long index);
+ boolean contains(DOMString token);
+ void add(DOMString... tokens);
+ void remove(DOMString... tokens);
+ boolean toggle(DOMString token, optional boolean force);
+ stringifier;
+// iterable<DOMString>;
+};
+
+interface DOMSettableTokenList : DOMTokenList {
+ attribute DOMString value;
+};
+</script>
+<script>
+"use strict";
+var xmlDoc, detachedRange, element;
+var idlArray;
+setup(function() {
+ xmlDoc = document.implementation.createDocument(null, "", null);
+ detachedRange = document.createRange();
+ detachedRange.detach();
+ element = xmlDoc.createElementNS(null, "test");
+ element.setAttribute("bar", "baz");
+
+ idlArray = new IdlArray();
+ idlArray.add_idls(document.querySelector("script[type=text\\/plain]").textContent);
+ idlArray.add_objects({
+ Event: ['document.createEvent("Event")', 'new Event("foo")'],
+ CustomEvent: ['new CustomEvent("foo")'],
+ XMLDocument: ['xmlDoc'],
+ DOMImplementation: ['document.implementation'],
+ DocumentFragment: ['document.createDocumentFragment()'],
+ DocumentType: ['document.doctype'],
+ Element: ['element'],
+ Attr: ['document.querySelector("[id]").attributes[0]'],
+ Text: ['document.createTextNode("abc")'],
+ ProcessingInstruction: ['xmlDoc.createProcessingInstruction("abc", "def")'],
+ Comment: ['document.createComment("abc")'],
+ Range: ['document.createRange()', 'detachedRange'],
+ NodeIterator: ['document.createNodeIterator(document.body, NodeFilter.SHOW_ALL, null, false)'],
+ TreeWalker: ['document.createTreeWalker(document.body, NodeFilter.SHOW_ALL, null, false)'],
+ NodeList: ['document.querySelectorAll("script")'],
+ HTMLCollection: ['document.body.children'],
+ DOMTokenList: ['document.body.classList'],
+ });
+});
+idlArray.test();
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/lists/DOMTokenList-stringifier.html b/tests/wpt/web-platform-tests/dom/lists/DOMTokenList-stringifier.html
new file mode 100644
index 00000000000..d5ff1612593
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/lists/DOMTokenList-stringifier.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>DOMTokenList stringifier</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-domtokenlist-stringifier">
+<link rel=author title=Ms2ger href="mailto:Ms2ger@gmail.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<span class=" a a b"></span>
+<script>
+test(function() {
+ var span = document.querySelector("span");
+ assert_equals(span.getAttribute("class"), " a a b",
+ "getAttribute should return the literal value");
+ assert_equals(span.className, " a a b",
+ "className should return the literal value");
+ assert_equals(String(span.classList), "a b",
+ "String(classList) should compress whitespace");
+ assert_equals(span.classList.toString(), "a b",
+ "classList.toString() should compress whitespace");
+ assert_class_string(span.classList, "DOMTokenList");
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/CharacterData-appendData.html b/tests/wpt/web-platform-tests/dom/nodes/CharacterData-appendData.html
new file mode 100644
index 00000000000..5e84e970551
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/CharacterData-appendData.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>CharacterData.appendData</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-appenddata">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-data">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+function testNode(node) {
+ test(function() {
+ assert_equals(node.data, "test")
+ node.appendData("test")
+ assert_equals(node.data, "testtest")
+ })
+}
+test(function() {
+ testNode(document.createTextNode("test"))
+ testNode(document.createComment("test"))
+})
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/CharacterData-deleteData.html b/tests/wpt/web-platform-tests/dom/nodes/CharacterData-deleteData.html
new file mode 100644
index 00000000000..25654bafedc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/CharacterData-deleteData.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>CharacterData.deleteData</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-deletedata">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-data">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+function testNode(node) {
+ test(function() {
+ assert_throws("INDEX_SIZE_ERR", function() { node.deleteData(5, 10) })
+ assert_throws("INDEX_SIZE_ERR", function() { node.deleteData(5, 0) })
+ node.deleteData(2, 10)
+ assert_equals(node.data, "te")
+ })
+ test(function() {
+ node.data = "test"
+ assert_equals(node.data, "test")
+ node.deleteData(1, 1)
+ assert_equals(node.data, "tst")
+ })
+}
+test(function() {
+ testNode(document.createTextNode("test"))
+ testNode(document.createComment("test"))
+})
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/CharacterData-insertData.html b/tests/wpt/web-platform-tests/dom/nodes/CharacterData-insertData.html
new file mode 100644
index 00000000000..a1f1b390c0e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/CharacterData-insertData.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>CharacterData.insertData</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-insertdata">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-data">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+function testNode(node) {
+ test(function() {
+ assert_throws("INDEX_SIZE_ERR", function() { node.insertData(5, "x") })
+ assert_throws("INDEX_SIZE_ERR", function() { node.insertData(5, "") })
+ node.insertData(2, "X")
+ assert_equals(node.data, "teXst")
+ })
+ test(function() {
+ node.data = "test"
+ assert_equals(node.data, "test")
+ node.insertData(4, "ing")
+ assert_equals(node.data, "testing")
+ })
+}
+test(function() {
+ testNode(document.createTextNode("test"))
+ testNode(document.createComment("test"))
+})
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/CharacterData-remove.html b/tests/wpt/web-platform-tests/dom/nodes/CharacterData-remove.html
new file mode 100644
index 00000000000..aef9d56bfa1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/CharacterData-remove.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>CharacterData.remove</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-childnode-remove">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="ChildNode-remove.js"></script>
+<div id=log></div>
+<script>
+var text, text_parent,
+ comment, comment_parent,
+ pi, pi_parent;
+setup(function() {
+ text = document.createTextNode("text");
+ text_parent = document.createElement("div");
+ comment = document.createComment("comment");
+ comment_parent = document.createElement("div");
+ pi = document.createProcessingInstruction("foo", "bar");
+ pi_parent = document.createElement("div");
+});
+testRemove(text, text_parent, "text");
+testRemove(comment, comment_parent, "comment");
+testRemove(pi, pi_parent, "PI");
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/CharacterData-replaceData.html b/tests/wpt/web-platform-tests/dom/nodes/CharacterData-replaceData.html
new file mode 100644
index 00000000000..fa97fe60d9a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/CharacterData-replaceData.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>CharacterData.replaceData</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-replacedata">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-data">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+function testNode(node) {
+ test(function() {
+ assert_throws("INDEX_SIZE_ERR", function() { node.replaceData(5, 1, "x") })
+ assert_throws("INDEX_SIZE_ERR", function() { node.replaceData(5, 0, "") })
+ node.replaceData(2, 10, "yo")
+ assert_equals(node.data, "teyo")
+ })
+ test(function() {
+ node.data = "test"
+ assert_equals(node.data, "test")
+ node.replaceData(1, 1, "waddup")
+ assert_equals(node.data, "twaddupst")
+ node.replaceData(1, 1, "yup")
+ assert_equals(node.data, "tyupaddupst")
+ })
+}
+test(function() {
+ testNode(document.createTextNode("test"))
+ testNode(document.createComment("test"))
+})
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/ChildNode-remove.js b/tests/wpt/web-platform-tests/dom/nodes/ChildNode-remove.js
new file mode 100644
index 00000000000..c36ba0d1174
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/ChildNode-remove.js
@@ -0,0 +1,30 @@
+function testRemove(node, parent, type) {
+ test(function() {
+ assert_true("remove" in node);
+ assert_equals(typeof node.remove, "function");
+ assert_equals(node.remove.length, 0);
+ }, type + " should support remove()");
+ test(function() {
+ assert_equals(node.parentNode, null, "Node should not have a parent");
+ assert_equals(node.remove(), undefined);
+ assert_equals(node.parentNode, null, "Removed new node should not have a parent");
+ }, "remove() should work if " + type + " doesn't have a parent");
+ test(function() {
+ assert_equals(node.parentNode, null, "Node should not have a parent");
+ parent.appendChild(node);
+ assert_equals(node.parentNode, parent, "Appended node should have a parent");
+ assert_equals(node.remove(), undefined);
+ assert_equals(node.parentNode, null, "Removed node should not have a parent");
+ assert_array_equals(parent.childNodes, [], "Parent should not have children");
+ }, "remove() should work if " + type + " does have a parent");
+ test(function() {
+ assert_equals(node.parentNode, null, "Node should not have a parent");
+ var before = parent.appendChild(document.createComment("before"));
+ parent.appendChild(node);
+ var after = parent.appendChild(document.createComment("after"));
+ assert_equals(node.parentNode, parent, "Appended node should have a parent");
+ assert_equals(node.remove(), undefined);
+ assert_equals(node.parentNode, null, "Removed node should not have a parent");
+ assert_array_equals(parent.childNodes, [before, after], "Parent should have two children left");
+ }, "remove() should work if " + type + " does have a parent and siblings");
+}
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Comment-Text-constructor.js b/tests/wpt/web-platform-tests/dom/nodes/Comment-Text-constructor.js
new file mode 100644
index 00000000000..360b9760e3e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Comment-Text-constructor.js
@@ -0,0 +1,77 @@
+function test_constructor(ctor) {
+ test(function() {
+ var object = new window[ctor]();
+ assert_equals(Object.getPrototypeOf(object),
+ window[ctor].prototype, "Prototype chain: " + ctor);
+ assert_equals(Object.getPrototypeOf(Object.getPrototypeOf(object)),
+ CharacterData.prototype, "Prototype chain: CharacterData");
+ assert_equals(Object.getPrototypeOf(Object.getPrototypeOf(Object.getPrototypeOf(object))),
+ Node.prototype, "Prototype chain: Node");
+ }, "new " + ctor + "(): prototype chain");
+
+ test(function() {
+ var object = new window[ctor]();
+ assert_true(object instanceof Node, "Should be a Node");
+ assert_true(object instanceof CharacterData, "Should be a CharacterData");
+ assert_true(object instanceof window[ctor], "Should be a " + ctor);
+ }, "new " + ctor + "(): instanceof");
+
+ test(function() {
+ var object = new window[ctor]();
+ assert_equals(object.data, "");
+ assert_equals(object.nodeValue, "");
+ assert_equals(object.ownerDocument, document);
+ }, "new " + ctor + "(): no arguments");
+
+ var arguments = [
+ [undefined, ""],
+ [null, "null"],
+ [42, "42"],
+ ["", ""],
+ ["-", "-"],
+ ["--", "--"],
+ ["-->", "-->"],
+ ["<!--", "<!--"],
+ ["\u0000", "\u0000"],
+ ["\u0000test", "\u0000test"],
+ ["&amp;", "&amp;"],
+ ];
+
+ arguments.forEach(function(a) {
+ var argument = a[0], expected = a[1];
+ test(function() {
+ var object = new window[ctor](argument);
+ assert_equals(object.data, expected);
+ assert_equals(object.nodeValue, expected);
+ assert_equals(object.ownerDocument, document);
+ }, "new " + ctor + "(): " + format_value(argument));
+ });
+
+ test(function() {
+ var called = [];
+ var object = new window[ctor]({
+ toString: function() {
+ called.push("first");
+ return "text";
+ }
+ }, {
+ toString: function() {
+ called.push("second");
+ assert_unreached("Should not look at the second argument.");
+ }
+ });
+ assert_equals(object.data, "text");
+ assert_equals(object.nodeValue, "text");
+ assert_equals(object.ownerDocument, document);
+ assert_array_equals(called, ["first"]);
+ }, "new " + ctor + "(): two arguments")
+
+ async_test("new " + ctor + "() should get the correct ownerDocument across globals").step(function() {
+ var iframe = document.createElement("iframe");
+ iframe.onload = this.step_func_done(function() {
+ var object = new iframe.contentWindow[ctor]();
+ assert_equals(object.ownerDocument, iframe.contentDocument);
+ });
+ document.body.appendChild(iframe);
+ });
+}
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Comment-constructor.html b/tests/wpt/web-platform-tests/dom/nodes/Comment-constructor.html
new file mode 100644
index 00000000000..5091316bd3c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Comment-constructor.html
@@ -0,0 +1,11 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Comment constructor</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-comment">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="Comment-Text-constructor.js"></script>
+<div id="log"></div>
+<script>
+test_constructor("Comment");
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/DOMImplementation-createDocument.html b/tests/wpt/web-platform-tests/dom/nodes/DOMImplementation-createDocument.html
new file mode 100644
index 00000000000..42ed42eb850
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/DOMImplementation-createDocument.html
@@ -0,0 +1,116 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>DOMImplementation.createDocument(namespace, qualifiedName, doctype)</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-domimplementation-createdocument">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-document-createelementns">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-node-nodetype">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-document-documentelement">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-document-doctype">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="Document-createElementNS.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ var tests = createElementNS_tests.map(function(t) {
+ return [t[0], t[1], null, t[2]]
+ }).concat([
+ /* Arrays with four elements:
+ * the namespace argument
+ * the qualifiedName argument
+ * the doctype argument
+ * the expected exception, or null if none
+ */
+ [null, null, false, new TypeError()],
+ [null, null, null, null],
+ [null, "", null, null],
+ [undefined, null, undefined, null],
+ [undefined, undefined, undefined, null],
+ [undefined, "", undefined, null],
+ ["http://example.com/", null, null, null],
+ ["http://example.com/", "", null, null],
+ ["/", null, null, null],
+ ["/", "", null, null],
+ ["http://www.w3.org/XML/1998/namespace", null, null, null],
+ ["http://www.w3.org/XML/1998/namespace", "", null, null],
+ ["http://www.w3.org/2000/xmlns/", null, null, null],
+ ["http://www.w3.org/2000/xmlns/", "", null, null],
+ ["foo:", null, null, null],
+ ["foo:", "", null, null],
+ [null, null, document.implementation.createDocumentType("foo", "", ""), null],
+ [null, null, document.doctype, null], // This causes a horrible WebKit bug (now fixed in trunk).
+ [null, null, function() {
+ var foo = document.implementation.createDocumentType("foo", "", "");
+ document.implementation.createDocument(null, null, foo);
+ return foo;
+ }(), null], // DOCTYPE already associated with a document.
+ [null, null, function() {
+ var bar = document.implementation.createDocument(null, null, null);
+ return bar.implementation.createDocumentType("bar", "", "");
+ }(), null], // DOCTYPE created by a different implementation.
+ [null, null, function() {
+ var bar = document.implementation.createDocument(null, null, null);
+ var magic = bar.implementation.createDocumentType("bar", "", "");
+ bar.implementation.createDocument(null, null, magic);
+ return magic;
+ }(), null], // DOCTYPE created by a different implementation and already associated with a document.
+ [null, "foo", document.implementation.createDocumentType("foo", "", ""), null],
+ ["foo", null, document.implementation.createDocumentType("foo", "", ""), null],
+ ["foo", "bar", document.implementation.createDocumentType("foo", "", ""), null],
+ ])
+
+ tests.forEach(function(t, i) {
+ var namespace = t[0], qualifiedName = t[1], doctype = t[2], expected = t[3]
+ test(function() {
+ if (expected != null) {
+ assert_throws(expected, function() { document.implementation.createDocument(namespace, qualifiedName, doctype) })
+ } else {
+ var doc = document.implementation.createDocument(namespace, qualifiedName, doctype)
+ assert_equals(doc.nodeType, Node.DOCUMENT_NODE)
+ assert_equals(doc.nodeType, doc.DOCUMENT_NODE)
+ assert_equals(doc.nodeName, "#document")
+ assert_equals(doc.nodeValue, null)
+ var omitRootElement = qualifiedName === null || String(qualifiedName) === ""
+ if (omitRootElement) {
+ assert_equals(doc.documentElement, null)
+ } else {
+ var element = doc.documentElement
+ assert_not_equals(element, null)
+ assert_equals(element.nodeType, Node.ELEMENT_NODE)
+ assert_equals(element.ownerDocument, doc)
+ var qualified = String(qualifiedName), names = []
+ if (qualified.indexOf(":") >= 0) {
+ names = qualified.split(":", 2)
+ } else {
+ names = [null, qualified]
+ }
+ assert_equals(element.prefix, names[0])
+ assert_equals(element.localName, names[1])
+ assert_equals(element.namespaceURI, namespace === undefined ? null : namespace)
+ }
+ if (!doctype) {
+ assert_equals(doc.doctype, null)
+ } else {
+ assert_equals(doc.doctype, doctype)
+ assert_equals(doc.doctype.ownerDocument, doc)
+ }
+ assert_equals(doc.childNodes.length, !omitRootElement + !!doctype)
+ }
+ }, "createDocument test " + i + ": " + t.map(function(el) { return format_value(el) }))
+
+ if (expected === null) {
+ test(function() {
+ var doc = document.implementation.createDocument(namespace, qualifiedName, doctype)
+ assert_equals(doc.compatMode, "CSS1Compat")
+ assert_equals(doc.characterSet, "UTF-8")
+ assert_equals(doc.inputEncoding, "UTF-8")
+ assert_equals(doc.contentType, "application/xml")
+ assert_equals(doc.URL, "about:blank")
+ assert_equals(doc.documentURI, "about:blank")
+ assert_equals(doc.createElement("DIV").localName, "DIV");
+ }, "createDocument test " + i + ": metadata for " +
+ [namespace, qualifiedName, doctype].map(function(el) { return format_value(el) }))
+ }
+ })
+})
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/DOMImplementation-createDocumentType.html b/tests/wpt/web-platform-tests/dom/nodes/DOMImplementation-createDocumentType.html
new file mode 100644
index 00000000000..ac79ddd7340
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/DOMImplementation-createDocumentType.html
@@ -0,0 +1,123 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>DOMImplementation.createDocumentType(qualifiedName, publicId, systemId)</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-domimplementation-createdocumenttype">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-documenttype-name">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-documenttype-publicid">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-documenttype-systemid">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-node-ownerdocument">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ var tests = [
+ ["", "", "", "INVALID_CHARACTER_ERR"],
+ ["test:root", "1234", "", null],
+ ["test:root", "1234", "test", null],
+ ["test:root", "test", "", null],
+ ["test:root", "test", "test", null],
+ ["_:_", "", "", null],
+ ["_:h0", "", "", null],
+ ["_:test", "", "", null],
+ ["_:_.", "", "", null],
+ ["_:a-", "", "", null],
+ ["l_:_", "", "", null],
+ ["ns:_0", "", "", null],
+ ["ns:a0", "", "", null],
+ ["ns0:test", "", "", null],
+ ["ns:EEE.", "", "", null],
+ ["ns:_-", "", "", null],
+ ["a.b:c", "", "", null],
+ ["a-b:c.j", "", "", null],
+ ["a-b:c", "", "", null],
+ ["foo", "", "", null],
+ ["1foo", "", "", "INVALID_CHARACTER_ERR"],
+ ["foo1", "", "", null],
+ ["f1oo", "", "", null],
+ ["@foo", "", "", "INVALID_CHARACTER_ERR"],
+ ["foo@", "", "", "INVALID_CHARACTER_ERR"],
+ ["f@oo", "", "", "INVALID_CHARACTER_ERR"],
+ ["edi:{", "", "", "INVALID_CHARACTER_ERR"],
+ ["edi:}", "", "", "INVALID_CHARACTER_ERR"],
+ ["edi:~", "", "", "INVALID_CHARACTER_ERR"],
+ ["edi:'", "", "", "INVALID_CHARACTER_ERR"],
+ ["edi:!", "", "", "INVALID_CHARACTER_ERR"],
+ ["edi:@", "", "", "INVALID_CHARACTER_ERR"],
+ ["edi:#", "", "", "INVALID_CHARACTER_ERR"],
+ ["edi:$", "", "", "INVALID_CHARACTER_ERR"],
+ ["edi:%", "", "", "INVALID_CHARACTER_ERR"],
+ ["edi:^", "", "", "INVALID_CHARACTER_ERR"],
+ ["edi:&", "", "", "INVALID_CHARACTER_ERR"],
+ ["edi:*", "", "", "INVALID_CHARACTER_ERR"],
+ ["edi:(", "", "", "INVALID_CHARACTER_ERR"],
+ ["edi:)", "", "", "INVALID_CHARACTER_ERR"],
+ ["edi:+", "", "", "INVALID_CHARACTER_ERR"],
+ ["edi:=", "", "", "INVALID_CHARACTER_ERR"],
+ ["edi:[", "", "", "INVALID_CHARACTER_ERR"],
+ ["edi:]", "", "", "INVALID_CHARACTER_ERR"],
+ ["edi:\\", "", "", "INVALID_CHARACTER_ERR"],
+ ["edi:/", "", "", "INVALID_CHARACTER_ERR"],
+ ["edi:;", "", "", "INVALID_CHARACTER_ERR"],
+ ["edi:`", "", "", "INVALID_CHARACTER_ERR"],
+ ["edi:<", "", "", "INVALID_CHARACTER_ERR"],
+ ["edi:>", "", "", "INVALID_CHARACTER_ERR"],
+ ["edi:,", "", "", "INVALID_CHARACTER_ERR"],
+ ["edi:a ", "", "", "INVALID_CHARACTER_ERR"],
+ ["edi:\"", "", "", "INVALID_CHARACTER_ERR"],
+ ["{", "", "", "INVALID_CHARACTER_ERR"],
+ ["}", "", "", "INVALID_CHARACTER_ERR"],
+ ["'", "", "", "INVALID_CHARACTER_ERR"],
+ ["~", "", "", "INVALID_CHARACTER_ERR"],
+ ["`", "", "", "INVALID_CHARACTER_ERR"],
+ ["@", "", "", "INVALID_CHARACTER_ERR"],
+ ["#", "", "", "INVALID_CHARACTER_ERR"],
+ ["$", "", "", "INVALID_CHARACTER_ERR"],
+ ["%", "", "", "INVALID_CHARACTER_ERR"],
+ ["^", "", "", "INVALID_CHARACTER_ERR"],
+ ["&", "", "", "INVALID_CHARACTER_ERR"],
+ ["*", "", "", "INVALID_CHARACTER_ERR"],
+ ["(", "", "", "INVALID_CHARACTER_ERR"],
+ [")", "", "", "INVALID_CHARACTER_ERR"],
+ ["f:oo", "", "", null],
+ [":foo", "", "", "NAMESPACE_ERR"],
+ ["foo:", "", "", "NAMESPACE_ERR"],
+ ["prefix::local", "", "", "NAMESPACE_ERR"],
+ ["foo", "foo", "", null],
+ ["foo", "", "foo", null],
+ ["foo", "f'oo", "", null],
+ ["foo", "", "f'oo", null],
+ ["foo", 'f"oo', "", null],
+ ["foo", "", 'f"oo', null],
+ ["foo", "f'o\"o", "", null],
+ ["foo", "", "f'o\"o", null],
+ ["foo", "foo>", "", null],
+ ["foo", "", "foo>", null]
+ ]
+
+ var doc = document.implementation.createHTMLDocument("title");
+ var doTest = function(aDocument, aQualifiedName, aPublicId, aSystemId) {
+ var doctype = aDocument.implementation.createDocumentType(aQualifiedName, aPublicId, aSystemId);
+ assert_equals(doctype.name, aQualifiedName, "name")
+ assert_equals(doctype.nodeName, aQualifiedName, "nodeName")
+ assert_equals(doctype.publicId, aPublicId, "publicId")
+ assert_equals(doctype.systemId, aSystemId, "systemId")
+ assert_equals(doctype.ownerDocument, aDocument, "ownerDocument")
+ assert_equals(doctype.nodeValue, null, "nodeValue")
+ }
+ tests.forEach(function(t) {
+ var qualifiedName = t[0], publicId = t[1], systemId = t[2], expected = t[3]
+ test(function() {
+ if (expected) {
+ assert_throws(expected, function() {
+ document.implementation.createDocumentType(qualifiedName, publicId, systemId)
+ })
+ } else {
+ doTest(document, qualifiedName, publicId, systemId);
+ doTest(doc, qualifiedName, publicId, systemId);
+ }
+ }, "createDocumentType(" + format_value(qualifiedName) + ", " + format_value(publicId) + ", " + format_value(systemId) + ") should " +
+ (expected ? "throw " + expected : "work"));
+ });
+})
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/DOMImplementation-createHTMLDocument.html b/tests/wpt/web-platform-tests/dom/nodes/DOMImplementation-createHTMLDocument.html
new file mode 100644
index 00000000000..89dc3834739
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/DOMImplementation-createHTMLDocument.html
@@ -0,0 +1,84 @@
+<!DOCTYPE html>
+<meta charset=windows-1252>
+<!-- Using windows-1252 to ensure that DOMImplementation.createHTMLDocument()
+ doesn't inherit utf-8 from the parent document. -->
+<title>DOMImplementation.createHTMLDocument</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-domimplementation-createhtmldocument">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-documenttype-name">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-documenttype-publicid">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-documenttype-systemid">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-document-documentelement">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="DOMImplementation-createHTMLDocument.js"></script>
+<div id="log"></div>
+<script>
+createHTMLDocuments(function(doc, expectedtitle, normalizedtitle) {
+ assert_true(doc instanceof Document, "Should be a Document")
+ assert_true(doc instanceof Node, "Should be a Node")
+ assert_equals(doc.childNodes.length, 2,
+ "Document should have two child nodes")
+
+ var doctype = doc.doctype
+ assert_true(doctype instanceof DocumentType,
+ "Doctype should be a DocumentType")
+ assert_true(doctype instanceof Node, "Doctype should be a Node")
+ assert_equals(doctype.name, "html")
+ assert_equals(doctype.publicId, "")
+ assert_equals(doctype.systemId, "")
+
+ var documentElement = doc.documentElement
+ assert_true(documentElement instanceof HTMLHtmlElement,
+ "Document element should be a HTMLHtmlElement")
+ assert_equals(documentElement.childNodes.length, 2,
+ "Document element should have two child nodes")
+ assert_equals(documentElement.localName, "html")
+ assert_equals(documentElement.tagName, "HTML")
+
+ var head = documentElement.firstChild
+ assert_true(head instanceof HTMLHeadElement,
+ "Head should be a HTMLHeadElement")
+ assert_equals(head.localName, "head")
+ assert_equals(head.tagName, "HEAD")
+
+ if (expectedtitle !== undefined) {
+ assert_equals(head.childNodes.length, 1)
+
+ var title = head.firstChild
+ assert_true(title instanceof HTMLTitleElement,
+ "Title should be a HTMLTitleElement")
+ assert_equals(title.localName, "title")
+ assert_equals(title.tagName, "TITLE")
+ assert_equals(title.childNodes.length, 1)
+ assert_equals(title.firstChild.data, expectedtitle)
+ } else {
+ assert_equals(head.childNodes.length, 0)
+ }
+
+ var body = documentElement.lastChild
+ assert_true(body instanceof HTMLBodyElement,
+ "Body should be a HTMLBodyElement")
+ assert_equals(body.localName, "body")
+ assert_equals(body.tagName, "BODY")
+ assert_equals(body.childNodes.length, 0)
+})
+
+test(function() {
+ var doc = document.implementation.createHTMLDocument("test");
+ assert_equals(doc.URL, "about:blank");
+ assert_equals(doc.documentURI, "about:blank");
+ assert_equals(doc.compatMode, "CSS1Compat");
+ assert_equals(doc.characterSet, "UTF-8");
+ assert_equals(doc.inputEncoding, "UTF-8");
+ assert_equals(doc.contentType, "text/html");
+ assert_equals(doc.createElement("DIV").localName, "div");
+}, "createHTMLDocument(): metadata")
+
+test(function() {
+ var doc = document.implementation.createHTMLDocument("test");
+ var a = doc.createElement("a");
+ // In UTF-8: 0xC3 0xA4
+ a.href = "http://example.org/?\u00E4";
+ assert_equals(a.href, "http://example.org/?%C3%A4");
+}, "createHTMLDocument(): URL parsing")
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/DOMImplementation-createHTMLDocument.js b/tests/wpt/web-platform-tests/dom/nodes/DOMImplementation-createHTMLDocument.js
new file mode 100644
index 00000000000..3e7e9aa9b78
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/DOMImplementation-createHTMLDocument.js
@@ -0,0 +1,25 @@
+function createHTMLDocuments(checkDoc) {
+ var tests = [
+ ["", "", ""],
+ [null, "null", "null"],
+ [undefined, undefined, ""],
+ ["foo bar baz", "foo bar baz", "foo bar baz"],
+ ["foo\t\tbar baz", "foo\t\tbar baz", "foo bar baz"],
+ ["foo\n\nbar baz", "foo\n\nbar baz", "foo bar baz"],
+ ["foo\f\fbar baz", "foo\f\fbar baz", "foo bar baz"],
+ ["foo\r\rbar baz", "foo\r\rbar baz", "foo bar baz"],
+ ]
+
+ tests.forEach(function(t, i) {
+ var title = t[0], expectedtitle = t[1], normalizedtitle = t[2]
+ test(function() {
+ var doc = document.implementation.createHTMLDocument(title);
+ checkDoc(doc, expectedtitle, normalizedtitle)
+ }, "createHTMLDocument test " + i + ": " + t.map(function(el) { return format_value(el) }))
+ })
+
+ test(function() {
+ var doc = document.implementation.createHTMLDocument();
+ checkDoc(doc, undefined, "")
+ }, "Missing title argument");
+}
diff --git a/tests/wpt/web-platform-tests/dom/nodes/DOMImplementation-hasFeature.html b/tests/wpt/web-platform-tests/dom/nodes/DOMImplementation-hasFeature.html
new file mode 100644
index 00000000000..2912051e731
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/DOMImplementation-hasFeature.html
@@ -0,0 +1,141 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>DOMImplementation.hasFeature(feature, version)</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-domimplementation-hasfeature">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ var tests = [
+ ["Core", "1.0"],
+ ["Core", "2.0"],
+ ["Core", "3.0"],
+ ["Core", "100.0"],
+ ["XML", "1.0"],
+ ["XML", "2.0"],
+ ["XML", "3.0"],
+ ["XML", "100.0"],
+ ["Core", "1"],
+ ["Core", "2"],
+ ["Core", "3"],
+ ["Core", "100"],
+ ["XML", "1"],
+ ["XML", "2"],
+ ["XML", "3"],
+ ["XML", "100"],
+ ["Core", "1.1"],
+ ["Core", "2.1"],
+ ["Core", "3.1"],
+ ["Core", "100.1"],
+ ["XML", "1.1"],
+ ["XML", "2.1"],
+ ["XML", "3.1"],
+ ["XML", "100.1"],
+ ["Core", ""],
+ ["XML", ""],
+ ["core", ""],
+ ["xml", ""],
+ ["CoRe", ""],
+ ["XmL", ""],
+ [" Core", ""],
+ [" XML", ""],
+ ["Core ", ""],
+ ["XML ", ""],
+ ["Co re", ""],
+ ["XM L", ""],
+ ["aCore", ""],
+ ["aXML", ""],
+ ["Corea", ""],
+ ["XMLa", ""],
+ ["Coare", ""],
+ ["XMaL", ""],
+ ["Core", " "],
+ ["XML", " "],
+ ["Core", " 1.0"],
+ ["Core", " 2.0"],
+ ["Core", " 3.0"],
+ ["Core", " 100.0"],
+ ["XML", " 1.0"],
+ ["XML", " 2.0"],
+ ["XML", " 3.0"],
+ ["XML", " 100.0"],
+ ["Core", "1.0 "],
+ ["Core", "2.0 "],
+ ["Core", "3.0 "],
+ ["Core", "100.0 "],
+ ["XML", "1.0 "],
+ ["XML", "2.0 "],
+ ["XML", "3.0 "],
+ ["XML", "100.0 "],
+ ["Core", "1. 0"],
+ ["Core", "2. 0"],
+ ["Core", "3. 0"],
+ ["Core", "100. 0"],
+ ["XML", "1. 0"],
+ ["XML", "2. 0"],
+ ["XML", "3. 0"],
+ ["XML", "100. 0"],
+ ["Core", "a1.0"],
+ ["Core", "a2.0"],
+ ["Core", "a3.0"],
+ ["Core", "a100.0"],
+ ["XML", "a1.0"],
+ ["XML", "a2.0"],
+ ["XML", "a3.0"],
+ ["XML", "a100.0"],
+ ["Core", "1.0a"],
+ ["Core", "2.0a"],
+ ["Core", "3.0a"],
+ ["Core", "100.0a"],
+ ["XML", "1.0a"],
+ ["XML", "2.0a"],
+ ["XML", "3.0a"],
+ ["XML", "100.0a"],
+ ["Core", "1.a0"],
+ ["Core", "2.a0"],
+ ["Core", "3.a0"],
+ ["Core", "100.a0"],
+ ["XML", "1.a0"],
+ ["XML", "2.a0"],
+ ["XML", "3.a0"],
+ ["XML", "100.a0"],
+ ["Core", 1],
+ ["Core", 2],
+ ["Core", 3],
+ ["Core", 100],
+ ["XML", 1],
+ ["XML", 2],
+ ["XML", 3],
+ ["XML", 100],
+ ["Core", null],
+ ["XML", null],
+ ["core", null],
+ ["xml", null],
+ ["CoRe", null],
+ ["XmL", null],
+ [" Core", null],
+ [" XML", null],
+ ["Core ", null],
+ ["XML ", null],
+ ["Co re", null],
+ ["XM L", null],
+ ["aCore", null],
+ ["aXML", null],
+ ["Corea", null],
+ ["XMLa", null],
+ ["Coare", null],
+ ["XMaL", null],
+ ["Core", undefined],
+ ["XML", undefined],
+ ["This is filler text.", ""],
+ [null, ""],
+ [undefined, ""],
+ ];
+ tests.forEach(function(data) {
+ test(function() {
+ assert_equals(document.implementation.hasFeature(data[0], data[1]), true)
+ }, "hasFeature(" + format_value(data[0]) + ", " + format_value(data[1]) + ")")
+ })
+})
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-Element-getElementsByTagName.js b/tests/wpt/web-platform-tests/dom/nodes/Document-Element-getElementsByTagName.js
new file mode 100644
index 00000000000..7402bbe2cd2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-Element-getElementsByTagName.js
@@ -0,0 +1,166 @@
+function test_getElementsByTagName(context, element) {
+ // TODO: getElementsByTagName("*")
+ test(function() {
+ assert_false(context.getElementsByTagName("html") instanceof NodeList,
+ "Should not return a NodeList")
+ assert_true(context.getElementsByTagName("html") instanceof HTMLCollection,
+ "Should return an HTMLCollection")
+ }, "Interfaces")
+
+ test(function() {
+ var firstCollection = context.getElementsByTagName("html"),
+ secondCollection = context.getElementsByTagName("html")
+ assert_true(firstCollection !== secondCollection ||
+ firstCollection === secondCollection)
+ }, "Caching is allowed")
+
+ test(function() {
+ var l = context.getElementsByTagName("nosuchtag")
+ l[5] = "foopy"
+ assert_equals(l[5], undefined)
+ assert_equals(l.item(5), null)
+ }, "Shouldn't be able to set unsigned properties on a HTMLCollection (non-strict mode)")
+
+ test(function() {
+ var l = context.getElementsByTagName("nosuchtag")
+ assert_throws(new TypeError(), function() {
+ "use strict";
+ l[5] = "foopy"
+ })
+ assert_equals(l[5], undefined)
+ assert_equals(l.item(5), null)
+ }, "Shouldn't be able to set unsigned properties on a HTMLCollection (strict mode)")
+
+ test(function() {
+ var l = context.getElementsByTagName("nosuchtag")
+ var fn = l.item;
+ assert_equals(fn, HTMLCollection.prototype.item);
+ l.item = "pass"
+ assert_equals(l.item, "pass")
+ assert_equals(HTMLCollection.prototype.item, fn);
+ }, "Should be able to set expando shadowing a proto prop (item)")
+
+ test(function() {
+ var l = context.getElementsByTagName("nosuchtag")
+ var fn = l.namedItem;
+ assert_equals(fn, HTMLCollection.prototype.namedItem);
+ l.namedItem = "pass"
+ assert_equals(l.namedItem, "pass")
+ assert_equals(HTMLCollection.prototype.namedItem, fn);
+ }, "Should be able to set expando shadowing a proto prop (namedItem)")
+
+ test(function() {
+ var t = element.appendChild(document.createElement("pre"));
+ t.id = "x";
+ this.add_cleanup(function() {element.removeChild(t)});
+
+ var list = context.getElementsByTagName('pre');
+ var pre = list[0];
+ assert_equals(pre.id, "x");
+ assert_equals(list['x'], pre);
+
+ assert_true('x' in list, "'x' in list");
+ assert_true(list.hasOwnProperty('x'), "list.hasOwnProperty('x')");
+
+ assert_array_equals(Object.getOwnPropertyNames(list).sort(), ["0", "x"]);
+
+ var desc = Object.getOwnPropertyDescriptor(list, '0');
+ assert_equals(typeof desc, "object", "descriptor should be an object");
+ assert_true(desc.enumerable, "desc.enumerable");
+ assert_true(desc.configurable, "desc.configurable");
+
+ desc = Object.getOwnPropertyDescriptor(list, 'x');
+ assert_equals(typeof desc, "object", "descriptor should be an object");
+ assert_false(desc.enumerable, "desc.enumerable");
+ assert_true(desc.configurable, "desc.configurable");
+ }, "hasOwnProperty, getOwnPropertyDescriptor, getOwnPropertyNames")
+
+ test(function() {
+ assert_equals(document.createElementNS("http://www.w3.org/1999/xhtml", "i").localName, "i") // Sanity
+ var t = element.appendChild(document.createElementNS("http://www.w3.org/1999/xhtml", "I"))
+ this.add_cleanup(function() {element.removeChild(t)})
+ assert_equals(t.localName, "I")
+ assert_equals(t.tagName, "I")
+ assert_equals(context.getElementsByTagName("I").length, 0)
+ assert_equals(context.getElementsByTagName("i").length, 0)
+ }, "HTML element with uppercase tagName never matches in HTML Documents")
+
+ test(function() {
+ var t = element.appendChild(document.createElementNS("test", "st"))
+ this.add_cleanup(function() {element.removeChild(t)})
+ assert_array_equals(context.getElementsByTagName("st"), [t])
+ assert_array_equals(context.getElementsByTagName("ST"), [])
+ }, "Element in non-HTML namespace, no prefix, lowercase name")
+
+ test(function() {
+ var t = element.appendChild(document.createElementNS("test", "ST"))
+ this.add_cleanup(function() {element.removeChild(t)})
+ assert_array_equals(context.getElementsByTagName("ST"), [t])
+ assert_array_equals(context.getElementsByTagName("st"), [])
+ }, "Element in non-HTML namespace, no prefix, uppercase name")
+
+ test(function() {
+ var t = element.appendChild(document.createElementNS("test", "te:st"))
+ this.add_cleanup(function() {element.removeChild(t)})
+ assert_array_equals(context.getElementsByTagName("st"), [t])
+ assert_array_equals(context.getElementsByTagName("ST"), [])
+ }, "Element in non-HTML namespace, prefix, lowercase name")
+
+ test(function() {
+ var t = element.appendChild(document.createElementNS("test", "te:ST"))
+ this.add_cleanup(function() {element.removeChild(t)})
+ assert_array_equals(context.getElementsByTagName("ST"), [t])
+ assert_array_equals(context.getElementsByTagName("st"), [])
+ assert_array_equals(context.getElementsByTagName("te:st"), [])
+ assert_array_equals(context.getElementsByTagName("te:ST"), [])
+ }, "Element in non-HTML namespace, prefix, uppercase name")
+
+ test(function() {
+ var t = element.appendChild(document.createElement("aÇ"))
+ this.add_cleanup(function() {element.removeChild(t)})
+ assert_equals(t.localName, "aÇ")
+ assert_array_equals(context.getElementsByTagName("AÇ"), [t], "All uppercase input")
+ assert_array_equals(context.getElementsByTagName("aÇ"), [t], "Ascii lowercase input")
+ assert_array_equals(context.getElementsByTagName("aç"), [], "All lowercase input")
+ }, "Element in HTML namespace, no prefix, non-ascii characters in name")
+
+ test(function() {
+ var t = element.appendChild(document.createElementNS("test", "AÇ"))
+ this.add_cleanup(function() {element.removeChild(t)})
+ assert_array_equals(context.getElementsByTagName("AÇ"), [t])
+ assert_array_equals(context.getElementsByTagName("aÇ"), [])
+ assert_array_equals(context.getElementsByTagName("aç"), [])
+ }, "Element in non-HTML namespace, non-ascii characters in name")
+
+ test(function() {
+ var t = element.appendChild(document.createElementNS("http://www.w3.org/1999/xhtml", "test:aÇ"))
+ this.add_cleanup(function() {element.removeChild(t)})
+ assert_array_equals(context.getElementsByTagName("AÇ"), [t], "All uppercase input")
+ assert_array_equals(context.getElementsByTagName("aÇ"), [t], "Ascii lowercase input")
+ assert_array_equals(context.getElementsByTagName("aç"), [], "All lowercase input")
+ }, "Element in HTML namespace, prefix, non-ascii characters in name")
+
+ test(function() {
+ var t = element.appendChild(document.createElementNS("test", "test:AÇ"))
+ this.add_cleanup(function() {element.removeChild(t)})
+ assert_array_equals(context.getElementsByTagName("AÇ"), [t], "All uppercase input")
+ assert_array_equals(context.getElementsByTagName("aÇ"), [], "Ascii lowercase input")
+ assert_array_equals(context.getElementsByTagName("aç"), [], "All lowercase input")
+ }, "Element in non-HTML namespace, prefix, non-ascii characters in name")
+
+ test(function() {
+ var actual = context.getElementsByTagName("*");
+ var expected = [];
+ var get_elements = function(node) {
+ for (var i = 0; i < node.childNodes.length; i++) {
+ var child = node.childNodes[i];
+ if (child.nodeType === child.ELEMENT_NODE) {
+ expected.push(child);
+ get_elements(child);
+ }
+ }
+ }
+ get_elements(context);
+ assert_array_equals(actual, expected);
+ }, "getElementsByTagName('*')")
+}
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-Element-getElementsByTagNameNS.js b/tests/wpt/web-platform-tests/dom/nodes/Document-Element-getElementsByTagNameNS.js
new file mode 100644
index 00000000000..a1bb3158745
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-Element-getElementsByTagNameNS.js
@@ -0,0 +1,128 @@
+function test_getElementsByTagNameNS(context, element) {
+ test(function() {
+ assert_false(context.getElementsByTagNameNS("http://www.w3.org/1999/xhtml", "html") instanceof NodeList, "NodeList")
+ assert_true(context.getElementsByTagNameNS("http://www.w3.org/1999/xhtml", "html") instanceof HTMLCollection, "HTMLCollection")
+ var firstCollection = context.getElementsByTagNameNS("http://www.w3.org/1999/xhtml", "html"),
+ secondCollection = context.getElementsByTagNameNS("http://www.w3.org/1999/xhtml", "html")
+ assert_true(firstCollection !== secondCollection || firstCollection === secondCollection,
+ "Caching is allowed.")
+ })
+
+ test(function() {
+ var t = element.appendChild(document.createElementNS("test", "body"))
+ this.add_cleanup(function() {element.removeChild(t)})
+ var actual = context.getElementsByTagNameNS("*", "body");
+ var expected = [];
+ var get_elements = function(node) {
+ for (var i = 0; i < node.childNodes.length; i++) {
+ var child = node.childNodes[i];
+ if (child.nodeType === child.ELEMENT_NODE) {
+ if (child.localName == "body") {
+ expected.push(child);
+ }
+ get_elements(child);
+ }
+ }
+ }
+ get_elements(context);
+ assert_array_equals(actual, expected);
+ }, "getElementsByTagNameNS('*', 'body')")
+
+ test(function() {
+ assert_array_equals(context.getElementsByTagNameNS("", "*"), []);
+ var t = element.appendChild(document.createElementNS("", "body"))
+ this.add_cleanup(function() {element.removeChild(t)})
+ assert_array_equals(context.getElementsByTagNameNS("", "*"), [t]);
+ }, "Empty string namespace")
+
+ test(function() {
+ var t = element.appendChild(document.createElementNS("test", "body"))
+ this.add_cleanup(function() {element.removeChild(t)})
+ assert_array_equals(context.getElementsByTagNameNS("test", "body"), [t]);
+ }, "body element in test namespace, no prefix")
+
+ test(function() {
+ var t = element.appendChild(document.createElementNS("test", "test:body"))
+ this.add_cleanup(function() {element.removeChild(t)})
+ assert_array_equals(context.getElementsByTagNameNS("test", "body"), [t]);
+ }, "body element in test namespace, prefix")
+
+ test(function() {
+ var t = element.appendChild(document.createElementNS("test", "BODY"))
+ this.add_cleanup(function() {element.removeChild(t)})
+ assert_array_equals(context.getElementsByTagNameNS("test", "BODY"), [t]);
+ assert_array_equals(context.getElementsByTagNameNS("test", "body"), []);
+ }, "BODY element in test namespace, no prefix")
+
+ test(function() {
+ var t = element.appendChild(document.createElementNS("http://www.w3.org/1999/xhtml", "abc"))
+ this.add_cleanup(function() {element.removeChild(t)})
+ assert_array_equals(context.getElementsByTagNameNS("http://www.w3.org/1999/xhtml", "abc"), [t]);
+ assert_array_equals(context.getElementsByTagNameNS("http://www.w3.org/1999/xhtml", "ABC"), []);
+ assert_array_equals(context.getElementsByTagNameNS("test", "ABC"), []);
+ }, "abc element in html namespace")
+
+ test(function() {
+ var t = element.appendChild(document.createElementNS("http://www.w3.org/1999/xhtml", "ABC"))
+ this.add_cleanup(function() {element.removeChild(t)})
+ assert_array_equals(context.getElementsByTagNameNS("http://www.w3.org/1999/xhtml", "abc"), []);
+ assert_array_equals(context.getElementsByTagNameNS("http://www.w3.org/1999/xhtml", "ABC"), [t]);
+ }, "ABC element in html namespace")
+
+ test(function() {
+ var t = element.appendChild(document.createElementNS("http://www.w3.org/1999/xhtml", "AÇ"))
+ this.add_cleanup(function() {element.removeChild(t)})
+ assert_array_equals(context.getElementsByTagNameNS("http://www.w3.org/1999/xhtml", "AÇ"), [t]);
+ assert_array_equals(context.getElementsByTagNameNS("test", "aÇ"), []);
+ assert_array_equals(context.getElementsByTagNameNS("test", "aç"), []);
+ }, "AÇ, case sensitivity")
+
+ test(function() {
+ var t = element.appendChild(document.createElementNS("test", "test:BODY"))
+ this.add_cleanup(function() {element.removeChild(t)})
+ assert_array_equals(context.getElementsByTagNameNS("test", "BODY"), [t]);
+ assert_array_equals(context.getElementsByTagNameNS("test", "body"), []);
+ }, "BODY element in test namespace, prefix")
+
+ test(function() {
+ var t = element.appendChild(document.createElementNS("test", "test:test"))
+ this.add_cleanup(function() {element.removeChild(t)})
+ var actual = context.getElementsByTagNameNS("http://www.w3.org/1999/xhtml", "*");
+ var expected = [];
+ var get_elements = function(node) {
+ for (var i = 0; i < node.childNodes.length; i++) {
+ var child = node.childNodes[i];
+ if (child.nodeType === child.ELEMENT_NODE) {
+ if (child !== t) {
+ expected.push(child);
+ }
+ get_elements(child);
+ }
+ }
+ }
+ get_elements(context);
+ assert_array_equals(actual, expected);
+ }, "getElementsByTagNameNS('http://www.w3.org/1999/xhtml', '*')")
+
+ test(function() {
+ var actual = context.getElementsByTagNameNS("*", "*");
+ var expected = [];
+ var get_elements = function(node) {
+ for (var i = 0; i < node.childNodes.length; i++) {
+ var child = node.childNodes[i];
+ if (child.nodeType === child.ELEMENT_NODE) {
+ expected.push(child);
+ get_elements(child);
+ }
+ }
+ }
+ get_elements(context);
+ assert_array_equals(actual, expected);
+ }, "getElementsByTagNameNS('*', '*')")
+
+ test(function() {
+ assert_array_equals(context.getElementsByTagNameNS("**", "*"), []);
+ assert_array_equals(context.getElementsByTagNameNS(null, "0"), []);
+ assert_array_equals(context.getElementsByTagNameNS(null, "div"), []);
+ }, "Empty lists")
+}
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-URL.sub.html b/tests/wpt/web-platform-tests/dom/nodes/Document-URL.sub.html
new file mode 100644
index 00000000000..8e9601107aa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-URL.sub.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Document.URL with redirect</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+ var iframe = document.createElement("iframe");
+ iframe.src = "/common/redirect.py?location=/common/blank.html";
+ document.body.appendChild(iframe);
+ this.add_cleanup(function() { document.body.removeChild(iframe); });
+ iframe.onload = this.step_func_done(function() {
+ assert_equals(iframe.contentDocument.URL,
+ "http://{{host}}:{{ports[http][0]}}/common/blank.html");
+ });
+})
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-adoptNode.html b/tests/wpt/web-platform-tests/dom/nodes/Document-adoptNode.html
new file mode 100644
index 00000000000..584d5d9fe03
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-adoptNode.html
@@ -0,0 +1,50 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Document.adoptNode</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-document-adoptnode">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<!--creates an element with local name "x<": --><x<>x</x<>
+<script>
+test(function() {
+ var y = document.getElementsByTagName("x<")[0]
+ var child = y.firstChild
+ assert_equals(y.parentNode, document.body)
+ assert_equals(y.ownerDocument, document)
+ assert_equals(document.adoptNode(y), y)
+ assert_equals(y.parentNode, null)
+ assert_equals(y.firstChild, child)
+ assert_equals(y.ownerDocument, document)
+ assert_equals(child.ownerDocument, document)
+ var doc = document.implementation.createDocument(null, null, null)
+ assert_equals(doc.adoptNode(y), y)
+ assert_equals(y.parentNode, null)
+ assert_equals(y.firstChild, child)
+ assert_equals(y.ownerDocument, doc)
+ assert_equals(child.ownerDocument, doc)
+}, "Adopting an Element called 'x<' should work.")
+
+test(function() {
+ var x = document.createElement(":good:times:")
+ assert_equals(document.adoptNode(x), x);
+ var doc = document.implementation.createDocument(null, null, null)
+ assert_equals(doc.adoptNode(x), x)
+ assert_equals(x.parentNode, null)
+ assert_equals(x.ownerDocument, doc)
+}, "Adopting an Element called ':good:times:' should work.")
+
+test(function() {
+ var doctype = document.doctype;
+ assert_equals(doctype.parentNode, document)
+ assert_equals(doctype.ownerDocument, document)
+ assert_equals(document.adoptNode(doctype), doctype)
+ assert_equals(doctype.parentNode, null)
+ assert_equals(doctype.ownerDocument, document)
+}, "Explicitly adopting a DocumentType should work.")
+
+test(function() {
+ var doc = document.implementation.createDocument(null, null, null)
+ assert_throws("NOT_SUPPORTED_ERR", function() { document.adoptNode(doc) })
+}, "Adopting a Document should throw.")
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-characterSet-normalization.html b/tests/wpt/web-platform-tests/dom/nodes/Document-characterSet-normalization.html
new file mode 100644
index 00000000000..b78ad45053c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-characterSet-normalization.html
@@ -0,0 +1,381 @@
+<!doctype html>
+<title>document.characterSet and inputEncoding normalization tests</title>
+<link rel=author title="Aryeh Gregor" href=ayg@aryeh.name>
+<meta name=timeout content=long>
+<div id=log></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<style>iframe { display: none }</style>
+<script>
+"use strict";
+
+// Taken straight from https://encoding.spec.whatwg.org/
+var encodingMap = {
+ "utf-8": [
+ "unicode-1-1-utf-8",
+ "utf-8",
+ "utf8",
+ // As we use <meta>, utf-16 will map to utf-8 per
+ // https://html.spec.whatwg.org/multipage/#documentEncoding
+ "utf-16",
+ "utf-16le",
+ "utf-16be",
+ ],
+ "ibm866": [
+ "866",
+ "cp866",
+ "csibm866",
+ "ibm866",
+ ],
+ "iso-8859-2": [
+ "csisolatin2",
+ "iso-8859-2",
+ "iso-ir-101",
+ "iso8859-2",
+ "iso88592",
+ "iso_8859-2",
+ "iso_8859-2:1987",
+ "l2",
+ "latin2",
+ ],
+ "iso-8859-3": [
+ "csisolatin3",
+ "iso-8859-3",
+ "iso-ir-109",
+ "iso8859-3",
+ "iso88593",
+ "iso_8859-3",
+ "iso_8859-3:1988",
+ "l3",
+ "latin3",
+ ],
+ "iso-8859-4": [
+ "csisolatin4",
+ "iso-8859-4",
+ "iso-ir-110",
+ "iso8859-4",
+ "iso88594",
+ "iso_8859-4",
+ "iso_8859-4:1988",
+ "l4",
+ "latin4",
+ ],
+ "iso-8859-5": [
+ "csisolatincyrillic",
+ "cyrillic",
+ "iso-8859-5",
+ "iso-ir-144",
+ "iso8859-5",
+ "iso88595",
+ "iso_8859-5",
+ "iso_8859-5:1988",
+ ],
+ "iso-8859-6": [
+ "arabic",
+ "asmo-708",
+ "csiso88596e",
+ "csiso88596i",
+ "csisolatinarabic",
+ "ecma-114",
+ "iso-8859-6",
+ "iso-8859-6-e",
+ "iso-8859-6-i",
+ "iso-ir-127",
+ "iso8859-6",
+ "iso88596",
+ "iso_8859-6",
+ "iso_8859-6:1987",
+ ],
+ "iso-8859-7": [
+ "csisolatingreek",
+ "ecma-118",
+ "elot_928",
+ "greek",
+ "greek8",
+ "iso-8859-7",
+ "iso-ir-126",
+ "iso8859-7",
+ "iso88597",
+ "iso_8859-7",
+ "iso_8859-7:1987",
+ "sun_eu_greek",
+ ],
+ "iso-8859-8": [
+ "csiso88598e",
+ "csisolatinhebrew",
+ "hebrew",
+ "iso-8859-8",
+ "iso-8859-8-e",
+ "iso-ir-138",
+ "iso8859-8",
+ "iso88598",
+ "iso_8859-8",
+ "iso_8859-8:1988",
+ "visual",
+ ],
+ "iso-8859-8-i": [
+ "csiso88598i",
+ "iso-8859-8-i",
+ "logical",
+ ],
+ "iso-8859-10": [
+ "csisolatin6",
+ "iso-8859-10",
+ "iso-ir-157",
+ "iso8859-10",
+ "iso885910",
+ "l6",
+ "latin6",
+ ],
+ "iso-8859-13": [
+ "iso-8859-13",
+ "iso8859-13",
+ "iso885913",
+ ],
+ "iso-8859-14": [
+ "iso-8859-14",
+ "iso8859-14",
+ "iso885914",
+ ],
+ "iso-8859-15": [
+ "csisolatin9",
+ "iso-8859-15",
+ "iso8859-15",
+ "iso885915",
+ "iso_8859-15",
+ "l9",
+ ],
+ "iso-8859-16": [
+ "iso-8859-16",
+ ],
+ "koi8-r": [
+ "cskoi8r",
+ "koi",
+ "koi8",
+ "koi8-r",
+ "koi8_r",
+ ],
+ "koi8-u": [
+ "koi8-u",
+ ],
+ "macintosh": [
+ "csmacintosh",
+ "mac",
+ "macintosh",
+ "x-mac-roman",
+ ],
+ "windows-874": [
+ "dos-874",
+ "iso-8859-11",
+ "iso8859-11",
+ "iso885911",
+ "tis-620",
+ "windows-874",
+ ],
+ "windows-1250": [
+ "cp1250",
+ "windows-1250",
+ "x-cp1250",
+ ],
+ "windows-1251": [
+ "cp1251",
+ "windows-1251",
+ "x-cp1251",
+ ],
+ "windows-1252": [
+ "ansi_x3.4-1968",
+ "ascii",
+ "cp1252",
+ "cp819",
+ "csisolatin1",
+ "ibm819",
+ "iso-8859-1",
+ "iso-ir-100",
+ "iso8859-1",
+ "iso88591",
+ "iso_8859-1",
+ "iso_8859-1:1987",
+ "l1",
+ "latin1",
+ "us-ascii",
+ "windows-1252",
+ "x-cp1252",
+ // As we use <meta>, x-user-defined will map to windows-1252 per
+ // https://html.spec.whatwg.org/multipage/#documentEncoding
+ "x-user-defined"
+ ],
+ "windows-1253": [
+ "cp1253",
+ "windows-1253",
+ "x-cp1253",
+ ],
+ "windows-1254": [
+ "cp1254",
+ "csisolatin5",
+ "iso-8859-9",
+ "iso-ir-148",
+ "iso8859-9",
+ "iso88599",
+ "iso_8859-9",
+ "iso_8859-9:1989",
+ "l5",
+ "latin5",
+ "windows-1254",
+ "x-cp1254",
+ ],
+ "windows-1255": [
+ "cp1255",
+ "windows-1255",
+ "x-cp1255",
+ ],
+ "windows-1256": [
+ "cp1256",
+ "windows-1256",
+ "x-cp1256",
+ ],
+ "windows-1257": [
+ "cp1257",
+ "windows-1257",
+ "x-cp1257",
+ ],
+ "windows-1258": [
+ "cp1258",
+ "windows-1258",
+ "x-cp1258",
+ ],
+ "x-mac-cyrillic": [
+ "x-mac-cyrillic",
+ "x-mac-ukrainian",
+ ],
+ "gbk": [
+ "chinese",
+ "csgb2312",
+ "csiso58gb231280",
+ "gb2312",
+ "gb_2312",
+ "gb_2312-80",
+ "gbk",
+ "iso-ir-58",
+ "x-gbk",
+ ],
+ "gb18030": [
+ "gb18030",
+ ],
+ "hz-gb-2312": [
+ "hz-gb-2312",
+ ],
+ "big5": [
+ "big5",
+ "big5-hkscs",
+ "cn-big5",
+ "csbig5",
+ "x-x-big5",
+ ],
+ "euc-jp": [
+ "cseucpkdfmtjapanese",
+ "euc-jp",
+ "x-euc-jp",
+ ],
+ "iso-2022-jp": [
+ "csiso2022jp",
+ "iso-2022-jp",
+ ],
+ "shift_jis": [
+ "csshiftjis",
+ "ms_kanji",
+ "shift-jis",
+ "shift_jis",
+ "sjis",
+ "windows-31j",
+ "x-sjis",
+ ],
+ "euc-kr": [
+ "cseuckr",
+ "csksc56011987",
+ "euc-kr",
+ "iso-ir-149",
+ "korean",
+ "ks_c_5601-1987",
+ "ks_c_5601-1989",
+ "ksc5601",
+ "ksc_5601",
+ "windows-949",
+ ],
+ "replacement": [
+ "csiso2022kr",
+ "iso-2022-cn",
+ "iso-2022-cn-ext",
+ "iso-2022-kr",
+ ],
+};
+
+// Add spaces and mix up case
+Object.keys(encodingMap).forEach(function(name) {
+ var lower = encodingMap[name];
+ var upper = encodingMap[name].map(function(s) { return s.toUpperCase() });
+ var mixed = encodingMap[name].map(function(s) {
+ var ret = "";
+ for (var i = 0; i < s.length; i += 2) {
+ ret += s[i].toUpperCase();
+ if (i + 1 < s.length) {
+ ret += s[i + 1];
+ }
+ }
+ return ret;
+ });
+ var spacey = encodingMap[name].map(function(s) {
+ return " \t\n\f\r" + s + " \t\n\f\r";
+ });
+ encodingMap[name] = [];
+ for (var i = 0; i < lower.length; i++) {
+ encodingMap[name].push(lower[i]);
+ /*
+ if (lower[i] != upper[i]) {
+ encodingMap[name].push(upper[i]);
+ }
+ if (lower[i] != mixed[i] && upper[i] != mixed[i]) {
+ encodingMap[name].push(mixed[i]);
+ }
+ encodingMap[name].push(spacey[i]);
+ */
+ }
+});
+
+function expected_case(encoding_label) {
+ if (encoding_label === 'big5') {
+ return 'Big5';
+ }
+ if (encoding_label === 'shift_jis') {
+ return 'Shift_JIS';
+ }
+ return encoding_label.toUpperCase();
+}
+
+Object.keys(encodingMap).forEach(function(name) {
+ encodingMap[name].forEach(function(label) {
+ var iframe = document.createElement("iframe");
+ var t = async_test("Name " + format_value(name) +
+ " has label " + format_value(label) + " (characterSet)");
+ var t2 = async_test("Name " + format_value(name) +
+ " has label " + format_value(label) + " (inputEncoding)");
+ /*
+ iframe.src = "data:text/html,<!doctype html>" +
+ '<meta charset="' + label + '">';
+ */
+ iframe.src = "encoding.py?label=" + label;
+ iframe.onload = function() {
+ t.step(function() {
+ assert_equals(iframe.contentDocument.characterSet, expected_case(name));
+ });
+ t2.step(function() {
+ assert_equals(iframe.contentDocument.inputEncoding, expected_case(name));
+ });
+ document.body.removeChild(iframe);
+ t.done();
+ t2.done();
+ };
+ document.body.appendChild(iframe);
+ });
+});
+</script>
+<!-- vim: set expandtab tabstop=2 shiftwidth=2: -->
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-constructor.html b/tests/wpt/web-platform-tests/dom/nodes/Document-constructor.html
new file mode 100644
index 00000000000..fb728828cff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-constructor.html
@@ -0,0 +1,47 @@
+<!doctype html>
+<meta charset=windows-1252>
+<!-- Using windows-1252 to ensure that new Document() doesn't inherit utf-8
+ from the parent document. -->
+<title>Document constructor</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-document">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ var doc = new Document();
+ assert_true(doc instanceof Node, "Should be a Node");
+ assert_true(doc instanceof Document, "Should be a Document");
+ assert_false(doc instanceof XMLDocument, "Should not be an XMLDocument");
+ assert_equals(Object.getPrototypeOf(doc), Document.prototype,
+ "Document should be the primary interface");
+}, "new Document(): interfaces")
+
+test(function() {
+ var doc = new Document();
+ assert_equals(doc.firstChild, null, "firstChild");
+ assert_equals(doc.lastChild, null, "lastChild");
+ assert_equals(doc.doctype, null, "doctype");
+ assert_equals(doc.documentElement, null, "documentElement");
+ assert_array_equals(doc.childNodes, [], "childNodes");
+}, "new Document(): children")
+
+test(function() {
+ var doc = new Document();
+ assert_equals(doc.URL, "about:blank");
+ assert_equals(doc.documentURI, "about:blank");
+ assert_equals(doc.compatMode, "CSS1Compat");
+ assert_equals(doc.characterSet, "UTF-8");
+ assert_equals(doc.inputEncoding, "UTF-8");
+ assert_equals(doc.contentType, "application/xml");
+ assert_equals(doc.createElement("DIV").localName, "DIV");
+}, "new Document(): metadata")
+
+test(function() {
+ var doc = new Document();
+ var a = doc.createElement("a");
+ // In UTF-8: 0xC3 0xA4
+ a.href = "http://example.org/?\u00E4";
+ assert_equals(a.href, "http://example.org/?%C3%A4");
+}, "new Document(): URL parsing")
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_bmp.html b/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_bmp.html
new file mode 100644
index 00000000000..12df40147b7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_bmp.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<title>BMP document.contentType === 'image/bmp'</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<iframe style="display:none"></iframe>
+<div id=log></div>
+<script>
+async_test(function() {
+ var iframe = document.getElementsByTagName('iframe')[0];
+ iframe.addEventListener('load', this.step_func_done(function() {
+ assert_equals(iframe.contentDocument.contentType, "image/bmp");
+ }), false);
+ iframe.src = "../resources/t.bmp";
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_css.html b/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_css.html
new file mode 100644
index 00000000000..1e405828417
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_css.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<title>CSS document.contentType === 'text/css'</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<iframe style="display:none"></iframe>
+<script>
+async_test(function() {
+ var iframe = document.getElementsByTagName('iframe')[0];
+ iframe.addEventListener('load', this.step_func_done(function() {
+ assert_equals(iframe.contentDocument.contentType, "text/css");
+ }), false);
+ iframe.src = "../resources/style.css";
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_datauri_01.html b/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_datauri_01.html
new file mode 100644
index 00000000000..383fa9cca19
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_datauri_01.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<title>Data URI document.contentType === 'text/plain' when data URI MIME type is not set</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<iframe style="display:none"></iframe>
+<script>
+async_test(function() {
+ var iframe = document.getElementsByTagName('iframe')[0];
+ iframe.addEventListener('load', this.step_func_done(function() {
+ assert_equals(iframe.contentDocument.contentType, "text/plain");
+ }), false);
+ iframe.src = "data:;,<!DOCTYPE html>";
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_datauri_02.html b/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_datauri_02.html
new file mode 100644
index 00000000000..0c4d42d5ece
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_datauri_02.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<title>Data URI document.contentType === 'text/html' when data URI MIME type is set</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<iframe style="display:none"></iframe>
+<script>
+async_test(function() {
+ var iframe = document.getElementsByTagName('iframe')[0];
+ iframe.addEventListener('load', this.step_func_done(function() {
+ assert_equals(iframe.contentDocument.contentType, "text/html");
+ }), false);
+ iframe.src = "data:text/html;charset=utf-8,<!DOCTYPE html>";
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_gif.html b/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_gif.html
new file mode 100644
index 00000000000..a848b7a851c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_gif.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<title>GIF document.contentType === 'image/gif'</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<iframe style="display:none"></iframe>
+<script>
+async_test(function() {
+ var iframe = document.getElementsByTagName('iframe')[0];
+ iframe.addEventListener('load', this.step_func_done(function() {
+ assert_equals(iframe.contentDocument.contentType, "image/gif");
+ }), false);
+ iframe.src = "../resources/t.gif";
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_html.html b/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_html.html
new file mode 100644
index 00000000000..818e37f1e77
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_html.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<title>HTM document.contentType === 'text/html'</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<iframe style="display:none"></iframe>
+<script>
+async_test(function() {
+ var iframe = document.getElementsByTagName('iframe')[0];
+ iframe.addEventListener('load', this.step_func_done(function() {
+ assert_equals(iframe.contentDocument.contentType, "text/html");
+ }), false);
+ iframe.src = "../resources/blob.htm";
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_javascripturi.html b/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_javascripturi.html
new file mode 100644
index 00000000000..34706967003
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_javascripturi.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<title>Javascript URI document.contentType === 'text/html'</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<iframe style="display:none"></iframe>
+<script>
+async_test(function() {
+ var iframe = document.getElementsByTagName('iframe')[0];
+ iframe.addEventListener('load', this.step_func_done(function() {
+ assert_equals(iframe.contentDocument.contentType, "text/html");
+ assert_equals(iframe.contentDocument.documentElement.textContent, "text/html");
+ }), false);
+ iframe.src = "javascript:document.contentType";
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_jpg.html b/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_jpg.html
new file mode 100644
index 00000000000..c41c38a8720
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_jpg.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<title>JPG document.contentType === 'image/jpeg'</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<iframe style="display:none"></iframe>
+<script>
+async_test(function() {
+ var iframe = document.getElementsByTagName('iframe')[0];
+ iframe.addEventListener('load', this.step_func_done(function() {
+ assert_equals(iframe.contentDocument.contentType, "image/jpeg");
+ }), false);
+ iframe.src = "../resources/t.jpg";
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_mimeheader_01.html b/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_mimeheader_01.html
new file mode 100644
index 00000000000..a0c63d1fc43
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_mimeheader_01.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<title>Custom document.contentType === 'text/xml' when explicitly set to this value</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<iframe style="display:none"></iframe>
+<script>
+async_test(function() {
+ var iframe = document.getElementsByTagName('iframe')[0];
+ iframe.addEventListener('load', this.step_func_done(function() {
+ assert_equals(iframe.contentDocument.contentType, "text/xml");
+ }), false);
+ iframe.src = "../support/contenttype_setter.py?type=text&subtype=xml";
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_mimeheader_02.html b/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_mimeheader_02.html
new file mode 100644
index 00000000000..f147269edee
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_mimeheader_02.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<title>Custom document.contentType === 'text/html' when explicitly set to this value and an attempt is made to override this value in an HTML meta header</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<iframe style="display:none"></iframe>
+<script>
+async_test(function() {
+ var iframe = document.getElementsByTagName('iframe')[0];
+ iframe.addEventListener('load', this.step_func_done(function() {
+ assert_equals(iframe.contentDocument.contentType, "text/html");
+ }), false);
+ iframe.src = "../support/contenttype_setter.py?type=text&subtype=html&mimeHead=text%2Fxml";
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_png.html b/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_png.html
new file mode 100644
index 00000000000..15cc7a66b2a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_png.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<title>PNG document.contentType === 'image/png'</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<iframe style="display:none"></iframe>
+<script>
+async_test(function() {
+ var iframe = document.getElementsByTagName('iframe')[0];
+ iframe.addEventListener('load', this.step_func_done(function() {
+ assert_equals(iframe.contentDocument.contentType, "image/png");
+ }), false);
+ iframe.src = "../resources/t.png";
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_txt.html b/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_txt.html
new file mode 100644
index 00000000000..c25bdc30d69
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_txt.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<title>TXT document.contentType === 'text/plain'</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<iframe style="display:none"></iframe>
+<script>
+async_test(function() {
+ var iframe = document.getElementsByTagName('iframe')[0];
+ iframe.addEventListener('load', this.step_func_done(function() {
+ assert_equals(iframe.contentDocument.contentType, "text/plain");
+ }), false);
+ iframe.src = "../resources/blob.txt";
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_xml.html b/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_xml.html
new file mode 100644
index 00000000000..4256621cf9e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/contenttype_xml.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<title>XML document.contentType === 'application/xml'</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<iframe style="display:none"></iframe>
+<script>
+async_test(function() {
+ var iframe = document.getElementsByTagName('iframe')[0];
+ iframe.addEventListener('load', this.step_func_done(function() {
+ assert_equals(iframe.contentDocument.contentType, "application/xml");
+ }), false);
+ iframe.src = "../resources/blob.xml";
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/createDocument.html b/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/createDocument.html
new file mode 100644
index 00000000000..1e4a22d712a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/createDocument.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<title>document.implementation.createDocument: document.contentType === 'application/xml'</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+test(function() {
+ var doc = document.implementation.createDocument("http://www.w3.org/1999/xhtml", "html", null);
+ assert_equals(doc.contentType, "application/xml");
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/createHTMLDocument.html b/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/createHTMLDocument.html
new file mode 100644
index 00000000000..185e3c8c92b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/createHTMLDocument.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<title>document.implementation.createHTMLDocument: document.contentType === 'text/html'</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+test(function() {
+ var doc = document.implementation.createHTMLDocument("test");
+ assert_equals(doc.contentType, "text/html");
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/xhr_responseType_document.html b/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/xhr_responseType_document.html
new file mode 100644
index 00000000000..c2fb6c19fd8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/contentType/xhr_responseType_document.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<title>XHR - retrieve HTML document: document.contentType === 'application/xml'</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+ var xhr = new XMLHttpRequest();
+ xhr.open("GET", "../resources/blob.xml");
+ xhr.responseType = "document";
+ xhr.onload = this.step_func_done(function(response) {
+ assert_equals(xhr.readyState, 4);
+ assert_equals(xhr.status, 200);
+ assert_equals(xhr.responseXML.contentType, "application/xml");
+ });
+ xhr.send(null);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/resources/blob.htm b/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/resources/blob.htm
new file mode 100644
index 00000000000..9d235ed07cd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/resources/blob.htm
@@ -0,0 +1 @@
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/resources/blob.txt b/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/resources/blob.txt
new file mode 100644
index 00000000000..9d235ed07cd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/resources/blob.txt
@@ -0,0 +1 @@
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/resources/blob.xml b/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/resources/blob.xml
new file mode 100644
index 00000000000..0922ed14b8b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/resources/blob.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<blob>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</blob> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/resources/lib.js b/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/resources/lib.js
new file mode 100644
index 00000000000..c41d336c085
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/resources/lib.js
@@ -0,0 +1 @@
+var t; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/resources/style.css b/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/resources/style.css
new file mode 100644
index 00000000000..bb4ff575b78
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/resources/style.css
@@ -0,0 +1,12 @@
+.unknown
+{
+ background-color:lightblue;
+}
+.pass
+{
+ background-color:lime;
+}
+.fail
+{
+ background-color:red;
+}
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/resources/t.bmp b/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/resources/t.bmp
new file mode 100644
index 00000000000..5697c0aef4a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/resources/t.bmp
Binary files differ
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/resources/t.gif b/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/resources/t.gif
new file mode 100644
index 00000000000..91f269207ac
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/resources/t.gif
Binary files differ
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/resources/t.jpg b/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/resources/t.jpg
new file mode 100644
index 00000000000..72b51899e48
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/resources/t.jpg
Binary files differ
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/resources/t.png b/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/resources/t.png
new file mode 100644
index 00000000000..447d9e30129
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/resources/t.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/support/contenttype_setter.py b/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/support/contenttype_setter.py
new file mode 100644
index 00000000000..02eff653ccf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-contentType/support/contenttype_setter.py
@@ -0,0 +1,20 @@
+def main(request, response):
+ type = request.GET.first("type", None)
+ subtype = request.GET.first("subtype", None)
+ if type and subtype:
+ response.headers["Content-Type"] = type + "/" + subtype
+
+ removeContentType = request.GET.first("removeContentType", None)
+ if removeContentType:
+ try:
+ del response.headers["Content-Type"]
+ except KeyError:
+ pass
+
+ content = '<head>'
+ mimeHead = request.GET.first("mime", None);
+ if mimeHead:
+ content += '<meta http-equiv="Content-Type" content="%s; charset=utf-8"/>' % mimeHead
+ content += "</head>"
+
+ return content
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-createAttribute.html b/tests/wpt/web-platform-tests/dom/nodes/Document-createAttribute.html
new file mode 100644
index 00000000000..a95737387c1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-createAttribute.html
@@ -0,0 +1,26 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Document.createAttribute</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=attributes.js></script>
+<script src=productions.js></script>
+<div id=log>
+<script>
+invalid_names.forEach(function(name) {
+ test(function() {
+ assert_throws("INVALID_CHARACTER_ERR", function() {
+ document.createAttribute(name, "test");
+ });
+ }, "createAttribute(" + format_value(name) + ")");
+});
+
+var tests = ["title", "TITLE", null, undefined];
+tests.forEach(function(name) {
+ test(function() {
+ var attribute = document.createAttribute(name);
+ attr_is(attribute, "", String(name), null, null, String(name));
+ assert_equals(attribute.ownerElement, null);
+ }, "createAttribute(" + format_value(name) + ")");
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-createComment-createTextNode.js b/tests/wpt/web-platform-tests/dom/nodes/Document-createComment-createTextNode.js
new file mode 100644
index 00000000000..62a38d380da
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-createComment-createTextNode.js
@@ -0,0 +1,22 @@
+function test_create(method, iface, nodeType, nodeName) {
+ ["\u000b", "a -- b", "a-", "-b", null, undefined].forEach(function(value) {
+ test(function() {
+ var c = document[method](value);
+ var expected = String(value);
+ assert_true(c instanceof iface);
+ assert_true(c instanceof CharacterData);
+ assert_true(c instanceof Node);
+ assert_equals(c.ownerDocument, document);
+ assert_equals(c.data, expected, "data");
+ assert_equals(c.nodeValue, expected, "nodeValue");
+ assert_equals(c.textContent, expected, "textContent");
+ assert_equals(c.length, expected.length);
+ assert_equals(c.nodeType, nodeType);
+ assert_equals(c.nodeName, nodeName);
+ assert_equals(c.hasChildNodes(), false);
+ assert_equals(c.childNodes.length, 0);
+ assert_equals(c.firstChild, null);
+ assert_equals(c.lastChild, null);
+ }, method + "(" + format_value(value) + ")");
+ });
+}
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-createComment.html b/tests/wpt/web-platform-tests/dom/nodes/Document-createComment.html
new file mode 100644
index 00000000000..a175c3a2f84
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-createComment.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Document.createComment</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-document-createcomment">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-node-ownerdocument">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-data">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-node-nodevalue">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-node-textcontent">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-length">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-node-nodetype">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-node-haschildnodes">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-node-childnodes">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-node-firstchild">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-node-lastchild">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="Document-createComment-createTextNode.js"></script>
+<div id="log"></div>
+<script>
+test_create("createComment", Comment, 8, "#comment");
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/bare_mathml.html b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/bare_mathml.html
new file mode 100644
index 00000000000..b80a99a7849
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/bare_mathml.html
@@ -0,0 +1 @@
+<math></math> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/bare_mathml.svg b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/bare_mathml.svg
new file mode 100644
index 00000000000..b80a99a7849
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/bare_mathml.svg
@@ -0,0 +1 @@
+<math></math> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/bare_mathml.xhtml b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/bare_mathml.xhtml
new file mode 100644
index 00000000000..b80a99a7849
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/bare_mathml.xhtml
@@ -0,0 +1 @@
+<math></math> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/bare_mathml.xml b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/bare_mathml.xml
new file mode 100644
index 00000000000..b80a99a7849
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/bare_mathml.xml
@@ -0,0 +1 @@
+<math></math> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/bare_svg.html b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/bare_svg.html
new file mode 100644
index 00000000000..dc1ced5b6b3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/bare_svg.html
@@ -0,0 +1 @@
+<svg></svg> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/bare_svg.svg b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/bare_svg.svg
new file mode 100644
index 00000000000..dc1ced5b6b3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/bare_svg.svg
@@ -0,0 +1 @@
+<svg></svg> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/bare_svg.xhtml b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/bare_svg.xhtml
new file mode 100644
index 00000000000..dc1ced5b6b3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/bare_svg.xhtml
@@ -0,0 +1 @@
+<svg></svg> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/bare_svg.xml b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/bare_svg.xml
new file mode 100644
index 00000000000..dc1ced5b6b3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/bare_svg.xml
@@ -0,0 +1 @@
+<svg></svg> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/bare_xhtml.html b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/bare_xhtml.html
new file mode 100644
index 00000000000..6c70bcfe4d4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/bare_xhtml.html
@@ -0,0 +1 @@
+<html></html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/bare_xhtml.svg b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/bare_xhtml.svg
new file mode 100644
index 00000000000..6c70bcfe4d4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/bare_xhtml.svg
@@ -0,0 +1 @@
+<html></html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/bare_xhtml.xhtml b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/bare_xhtml.xhtml
new file mode 100644
index 00000000000..6c70bcfe4d4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/bare_xhtml.xhtml
@@ -0,0 +1 @@
+<html></html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/bare_xhtml.xml b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/bare_xhtml.xml
new file mode 100644
index 00000000000..6c70bcfe4d4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/bare_xhtml.xml
@@ -0,0 +1 @@
+<html></html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/empty.html b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/empty.html
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/empty.html
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/empty.svg b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/empty.svg
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/empty.svg
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/empty.xhtml b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/empty.xhtml
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/empty.xhtml
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/empty.xml b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/empty.xml
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/empty.xml
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/generate.py b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/generate.py
new file mode 100755
index 00000000000..88c4da198b1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/generate.py
@@ -0,0 +1,77 @@
+#!/usr/bin/python
+import os
+import sys
+
+THIS_NAME = "generate.py"
+
+# Note: these lists must be kept in sync with the lists in
+# Document-createElement-namespace.html, and this script must be run whenever
+# the lists are updated. (We could keep the lists in a shared JSON file, but
+# seems like too much effort.)
+FILES = (
+ ("empty", ""),
+ ("minimal_html", "<!doctype html><title></title>"),
+
+ ("xhtml", '<html xmlns="http://www.w3.org/1999/xhtml"></html>'),
+ ("svg", '<svg xmlns="http://www.w3.org/2000/svg"></svg>'),
+ ("mathml", '<mathml xmlns="http://www.w3.org/1998/Math/MathML"></mathml>'),
+
+ ("bare_xhtml", "<html></html>"),
+ ("bare_svg", "<svg></svg>"),
+ ("bare_mathml", "<math></math>"),
+
+ ("xhtml_ns_removed", """\
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head><script>
+ var newRoot = document.createElementNS(null, "html");
+ document.removeChild(document.documentElement);
+ document.appendChild(newRoot);
+ </script></head>
+</html>
+"""),
+ ("xhtml_ns_changed", """\
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head><script>
+ var newRoot = document.createElementNS("http://www.w3.org/2000/svg", "abc");
+ document.removeChild(document.documentElement);
+ document.appendChild(newRoot);
+ </script></head>
+</html>
+"""),
+)
+
+EXTENSIONS = (
+ "html",
+ "xhtml",
+ "xml",
+ "svg",
+ # Was not able to get server MIME type working properly :(
+ #"mml",
+)
+
+def __main__():
+ if len(sys.argv) > 1:
+ print "No arguments expected, aborting"
+ return
+
+ if not os.access(THIS_NAME, os.F_OK):
+ print "Must be run from the directory of " + THIS_NAME + ", aborting"
+ return
+
+ for name in os.listdir("."):
+ if name == THIS_NAME:
+ continue
+ os.remove(name)
+
+ manifest = open("MANIFEST", "w")
+
+ for name, contents in FILES:
+ for extension in EXTENSIONS:
+ f = open(name + "." + extension, "w")
+ f.write(contents)
+ f.close()
+ manifest.write("support " + name + "." + extension + "\n")
+
+ manifest.close()
+
+__main__()
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/mathml.html b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/mathml.html
new file mode 100644
index 00000000000..0bec8e99e4a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/mathml.html
@@ -0,0 +1 @@
+<mathml xmlns="http://www.w3.org/1998/Math/MathML"></mathml> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/mathml.svg b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/mathml.svg
new file mode 100644
index 00000000000..0bec8e99e4a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/mathml.svg
@@ -0,0 +1 @@
+<mathml xmlns="http://www.w3.org/1998/Math/MathML"></mathml> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/mathml.xhtml b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/mathml.xhtml
new file mode 100644
index 00000000000..0bec8e99e4a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/mathml.xhtml
@@ -0,0 +1 @@
+<mathml xmlns="http://www.w3.org/1998/Math/MathML"></mathml> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/mathml.xml b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/mathml.xml
new file mode 100644
index 00000000000..0bec8e99e4a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/mathml.xml
@@ -0,0 +1 @@
+<mathml xmlns="http://www.w3.org/1998/Math/MathML"></mathml> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/minimal_html.html b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/minimal_html.html
new file mode 100644
index 00000000000..a33d9859afa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/minimal_html.html
@@ -0,0 +1 @@
+<!doctype html><title></title> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/minimal_html.svg b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/minimal_html.svg
new file mode 100644
index 00000000000..a33d9859afa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/minimal_html.svg
@@ -0,0 +1 @@
+<!doctype html><title></title> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/minimal_html.xhtml b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/minimal_html.xhtml
new file mode 100644
index 00000000000..a33d9859afa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/minimal_html.xhtml
@@ -0,0 +1 @@
+<!doctype html><title></title> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/minimal_html.xml b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/minimal_html.xml
new file mode 100644
index 00000000000..a33d9859afa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/minimal_html.xml
@@ -0,0 +1 @@
+<!doctype html><title></title> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/svg.html b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/svg.html
new file mode 100644
index 00000000000..64def4af7f7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/svg.html
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg"></svg> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/svg.svg b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/svg.svg
new file mode 100644
index 00000000000..64def4af7f7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/svg.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg"></svg> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/svg.xhtml b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/svg.xhtml
new file mode 100644
index 00000000000..64def4af7f7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/svg.xhtml
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg"></svg> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/svg.xml b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/svg.xml
new file mode 100644
index 00000000000..64def4af7f7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/svg.xml
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg"></svg> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/xhtml.html b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/xhtml.html
new file mode 100644
index 00000000000..1cba9982413
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/xhtml.html
@@ -0,0 +1 @@
+<html xmlns="http://www.w3.org/1999/xhtml"></html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/xhtml.svg b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/xhtml.svg
new file mode 100644
index 00000000000..1cba9982413
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/xhtml.svg
@@ -0,0 +1 @@
+<html xmlns="http://www.w3.org/1999/xhtml"></html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/xhtml.xhtml b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/xhtml.xhtml
new file mode 100644
index 00000000000..1cba9982413
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/xhtml.xhtml
@@ -0,0 +1 @@
+<html xmlns="http://www.w3.org/1999/xhtml"></html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/xhtml.xml b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/xhtml.xml
new file mode 100644
index 00000000000..1cba9982413
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/xhtml.xml
@@ -0,0 +1 @@
+<html xmlns="http://www.w3.org/1999/xhtml"></html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_changed.html b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_changed.html
new file mode 100644
index 00000000000..b228c7f7403
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_changed.html
@@ -0,0 +1,7 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head><script>
+ var newRoot = document.createElementNS("http://www.w3.org/2000/svg", "abc");
+ document.removeChild(document.documentElement);
+ document.appendChild(newRoot);
+ </script></head>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_changed.svg b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_changed.svg
new file mode 100644
index 00000000000..b228c7f7403
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_changed.svg
@@ -0,0 +1,7 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head><script>
+ var newRoot = document.createElementNS("http://www.w3.org/2000/svg", "abc");
+ document.removeChild(document.documentElement);
+ document.appendChild(newRoot);
+ </script></head>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_changed.xhtml b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_changed.xhtml
new file mode 100644
index 00000000000..b228c7f7403
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_changed.xhtml
@@ -0,0 +1,7 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head><script>
+ var newRoot = document.createElementNS("http://www.w3.org/2000/svg", "abc");
+ document.removeChild(document.documentElement);
+ document.appendChild(newRoot);
+ </script></head>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_changed.xml b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_changed.xml
new file mode 100644
index 00000000000..b228c7f7403
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_changed.xml
@@ -0,0 +1,7 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head><script>
+ var newRoot = document.createElementNS("http://www.w3.org/2000/svg", "abc");
+ document.removeChild(document.documentElement);
+ document.appendChild(newRoot);
+ </script></head>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_removed.html b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_removed.html
new file mode 100644
index 00000000000..dba395fed06
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_removed.html
@@ -0,0 +1,7 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head><script>
+ var newRoot = document.createElementNS(null, "html");
+ document.removeChild(document.documentElement);
+ document.appendChild(newRoot);
+ </script></head>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_removed.svg b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_removed.svg
new file mode 100644
index 00000000000..dba395fed06
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_removed.svg
@@ -0,0 +1,7 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head><script>
+ var newRoot = document.createElementNS(null, "html");
+ document.removeChild(document.documentElement);
+ document.appendChild(newRoot);
+ </script></head>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_removed.xhtml b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_removed.xhtml
new file mode 100644
index 00000000000..dba395fed06
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_removed.xhtml
@@ -0,0 +1,7 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head><script>
+ var newRoot = document.createElementNS(null, "html");
+ document.removeChild(document.documentElement);
+ document.appendChild(newRoot);
+ </script></head>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_removed.xml b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_removed.xml
new file mode 100644
index 00000000000..dba395fed06
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace-tests/xhtml_ns_removed.xml
@@ -0,0 +1,7 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head><script>
+ var newRoot = document.createElementNS(null, "html");
+ document.removeChild(document.documentElement);
+ document.appendChild(newRoot);
+ </script></head>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace.html b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace.html
new file mode 100644
index 00000000000..b81bf8f08fd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement-namespace.html
@@ -0,0 +1,103 @@
+<!doctype html>
+<title>document.createElement() namespace tests</title>
+<link rel=author title="Aryeh Gregor" href=ayg@aryeh.name>
+<div id=log></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+"use strict";
+/**
+ * This tests the namespace of elements created by the Document interface's
+ * createElement() method. See bug:
+ * https://www.w3.org/Bugs/Public/show_bug.cgi?id=19431
+ */
+
+/**
+ * Test that an element created using the Document object doc has the namespace
+ * that would be expected for the given contentType.
+ */
+function testDoc(doc, contentType) {
+ // WebKit doesn't support document.contentType, so they don't get this sanity
+ // check :(
+ if (doc.contentType !== undefined) {
+ assert_equals(doc.contentType, contentType,
+ "Wrong MIME type -- incorrect server config?");
+ }
+
+ var expectedNamespace = contentType == "text/html" ||
+ contentType == "application/xhtml+xml"
+ ? "http://www.w3.org/1999/xhtml" : null;
+
+ assert_equals(doc.createElement("x").namespaceURI, expectedNamespace);
+}
+
+// First test various objects we create in JS
+test(function() {
+ testDoc(document, "text/html")
+}, "Created element's namespace in current document");
+test(function() {
+ testDoc(document.implementation.createHTMLDocument(""), "text/html");
+}, "Created element's namespace in created HTML document");
+test(function() {
+ testDoc(document.implementation.createDocument(null, "", null),
+ "application/xml");
+}, "Created element's namespace in created XML document");
+test(function() {
+ testDoc(document.implementation.createDocument("http://www.w3.org/1999/xhtml", "html", null),
+ "application/xml");
+}, "Created element's namespace in created XHTML document");
+test(function() {
+ testDoc(document.implementation.createDocument("http://www.w3.org/2000/svg", "svg", null),
+ "application/xml");
+}, "Created element's namespace in created SVG document");
+test(function() {
+ testDoc(document.implementation.createDocument("http://www.w3.org/1998/Math/MathML", "math", null),
+ "application/xml");
+}, "Created element's namespace in created MathML document");
+
+// Now for various externally-loaded files. Note: these lists must be kept
+// synced with the lists in generate.py in the subdirectory, and that script
+// must be run whenever the lists are updated. (We could keep the lists in a
+// shared JSON file, but it seems like too much effort.)
+var testExtensions = {
+ html: "text/html",
+ xhtml: "application/xhtml+xml",
+ xml: "application/xml",
+ svg: "image/svg+xml",
+ // Was not able to get server MIME type working properly :(
+ //mml: "application/mathml+xml",
+};
+
+var tests = [
+ "empty",
+ "minimal_html",
+
+ "xhtml",
+ "svg",
+ "mathml",
+
+ "bare_xhtml",
+ "bare_svg",
+ "bare_mathml",
+
+ "xhtml_ns_removed",
+ "xhtml_ns_changed",
+];
+
+tests.forEach(function(testName) {
+ Object.keys(testExtensions).forEach(function(ext) {
+ var iframe = document.createElement("iframe");
+ iframe.src = "Document-createElement-namespace-tests/" +
+ testName + "." + ext;
+ var t = async_test("Created element's namespace in " + testName + "." + ext);
+ iframe.onload = function() {
+ t.step(function() {
+ testDoc(iframe.contentDocument, testExtensions[ext]);
+ });
+ document.body.removeChild(iframe);
+ t.done();
+ };
+ document.body.appendChild(iframe);
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-createElement.html b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement.html
new file mode 100644
index 00000000000..59fa02d83f5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-createElement.html
@@ -0,0 +1,85 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Document.createElement</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-document-createelement">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-element-localname">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-element-tagname">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-element-prefix">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-element-namespaceuri">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+function toASCIIUppercase(str) {
+ var diff = "a".charCodeAt(0) - "A".charCodeAt(0);
+ var res = "";
+ for (var i = 0; i < str.length; ++i) {
+ if ("a" <= str[i] && str[i] <= "z") {
+ res += String.fromCharCode(str.charCodeAt(i) - diff);
+ } else {
+ res += str[i];
+ }
+ }
+ return res;
+}
+test(function() {
+ var HTMLNS = "http://www.w3.org/1999/xhtml",
+ valid = [
+ //[input, localName],
+ [undefined, "undefined"],
+ [null, "null"],
+ ["foo", "foo"],
+ ["f1oo", "f1oo"],
+ ["foo1", "foo1"],
+ ["f\u0300oo", "f\u0300oo"],
+ ["foo\u0300", "foo\u0300"],
+ [":foo", ":foo"],
+ ["f:oo", "f:oo"],
+ ["foo:", "foo:"],
+ ["xml", "xml"],
+ ["xmlns", "xmlns"],
+ ["xmlfoo", "xmlfoo"],
+ ["xml:foo", "xml:foo"],
+ ["xmlns:foo", "xmlns:foo"],
+ ["xmlfoo:bar", "xmlfoo:bar"],
+ ["svg", "svg"],
+ ["math", "math"],
+ ["FOO", "foo"],
+ ["mar\u212a", "mar\u212a"],
+ ["\u0130nput", "\u0130nput"],
+ ["\u0131nput", "\u0131nput"]
+ ],
+ invalid = [
+ "",
+ "1foo",
+ "\u0300foo",
+ "}foo",
+ "f}oo",
+ "foo}",
+ "\ufffffoo",
+ "f\uffffoo",
+ "foo\uffff",
+ "<foo",
+ "foo>",
+ "<foo>",
+ "f<oo"
+ ]
+
+ valid.forEach(function(t) {
+ test(function() {
+ var elt = document.createElement(t[0])
+ assert_true(elt instanceof Element)
+ assert_true(elt instanceof Node)
+ assert_equals(elt.localName, t[1])
+ assert_equals(elt.tagName, toASCIIUppercase(t[1]))
+ assert_equals(elt.prefix, null)
+ assert_equals(elt.namespaceURI, HTMLNS)
+ }, "createElement(" + format_value(t[0]) + ")");
+ });
+ invalid.forEach(function(arg) {
+ test(function() {
+ assert_throws("INVALID_CHARACTER_ERR", function() { document.createElement(arg) })
+ }, "createElement(" + format_value(arg) + ")");
+ });
+})
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-createElementNS.html b/tests/wpt/web-platform-tests/dom/nodes/Document-createElementNS.html
new file mode 100644
index 00000000000..a13c407e8d3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-createElementNS.html
@@ -0,0 +1,199 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Document.createElementNS</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-document-createelementns">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="Document-createElementNS.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ var tests = createElementNS_tests.concat([
+ /* Arrays with three elements:
+ * the namespace argument
+ * the qualifiedName argument
+ * the expected exception, or null if none
+ */
+ ["", "", "INVALID_CHARACTER_ERR"],
+ [null, null, null],
+ [null, "", "INVALID_CHARACTER_ERR"],
+ [undefined, null, null],
+ [undefined, undefined, null],
+ [undefined, "", "INVALID_CHARACTER_ERR"],
+ ["http://example.com/", null, null],
+ ["http://example.com/", "", "INVALID_CHARACTER_ERR"],
+ ["/", null, null],
+ ["/", "", "INVALID_CHARACTER_ERR"],
+ ["http://www.w3.org/XML/1998/namespace", null, null],
+ ["http://www.w3.org/XML/1998/namespace", "", "INVALID_CHARACTER_ERR"],
+ ["http://www.w3.org/2000/xmlns/", null, "NAMESPACE_ERR"],
+ ["http://www.w3.org/2000/xmlns/", "", "INVALID_CHARACTER_ERR"],
+ ["foo:", null, null],
+ ["foo:", "", "INVALID_CHARACTER_ERR"],
+ ])
+
+ tests.forEach(function(t, i) {
+ test(function() {
+ var namespace = t[0], qualifiedName = t[1], expected = t[2]
+ if (expected != null) {
+ assert_throws(expected, function() { document.createElementNS(namespace, qualifiedName) })
+ } else {
+ var element = document.createElementNS(namespace, qualifiedName)
+ assert_not_equals(element, null)
+ assert_equals(element.nodeType, Node.ELEMENT_NODE)
+ assert_equals(element.nodeType, element.ELEMENT_NODE)
+ assert_equals(element.nodeValue, null)
+ assert_equals(element.ownerDocument, document)
+ var qualified = String(qualifiedName), names = []
+ if (qualified.indexOf(":") >= 0) {
+ names = qualified.split(":", 2)
+ } else {
+ names = [null, qualified]
+ }
+ assert_equals(element.prefix, names[0])
+ assert_equals(element.localName, names[1])
+ assert_equals(element.tagName, qualified)
+ assert_equals(element.nodeName, qualified)
+ assert_equals(element.namespaceURI, namespace === undefined ? null : namespace)
+ }
+ }, "createElementNS test " + i + ": " + t.map(function(el) { return format_value(el) }))
+ })
+})
+
+test(function() {
+ var HTMLNS = "http://www.w3.org/1999/xhtml";
+ var element = document.createElementNS(HTMLNS, "span");
+ assert_equals(element.namespaceURI, HTMLNS);
+ assert_equals(element.prefix, null);
+ assert_equals(element.localName, "span");
+ assert_equals(element.tagName, "SPAN");
+ assert_true(element instanceof Node, "Should be a Node");
+ assert_true(element instanceof Element, "Should be an Element");
+ assert_true(element instanceof HTMLElement, "Should be an HTMLElement");
+ assert_true(element instanceof HTMLSpanElement, "Should be an HTMLSpanElement");
+}, "Lower-case HTML element without a prefix");
+
+test(function() {
+ var HTMLNS = "http://www.w3.org/1999/xhtml";
+ var element = document.createElementNS(HTMLNS, "html:span");
+ assert_equals(element.namespaceURI, HTMLNS);
+ assert_equals(element.prefix, "html");
+ assert_equals(element.localName, "span");
+ assert_equals(element.tagName, "HTML:SPAN");
+ assert_true(element instanceof Node, "Should be a Node");
+ assert_true(element instanceof Element, "Should be an Element");
+ assert_true(element instanceof HTMLElement, "Should be an HTMLElement");
+ assert_true(element instanceof HTMLSpanElement, "Should be an HTMLSpanElement");
+}, "Lower-case HTML element with a prefix");
+
+test(function() {
+ var element = document.createElementNS("test", "span");
+ assert_equals(element.namespaceURI, "test");
+ assert_equals(element.prefix, null);
+ assert_equals(element.localName, "span");
+ assert_equals(element.tagName, "span");
+ assert_true(element instanceof Node, "Should be a Node");
+ assert_true(element instanceof Element, "Should be an Element");
+ assert_false(element instanceof HTMLElement, "Should not be an HTMLElement");
+ assert_false(element instanceof HTMLSpanElement, "Should not be an HTMLSpanElement");
+}, "Lower-case non-HTML element without a prefix");
+
+test(function() {
+ var element = document.createElementNS("test", "html:span");
+ assert_equals(element.namespaceURI, "test");
+ assert_equals(element.prefix, "html");
+ assert_equals(element.localName, "span");
+ assert_equals(element.tagName, "html:span");
+ assert_true(element instanceof Node, "Should be a Node");
+ assert_true(element instanceof Element, "Should be an Element");
+ assert_false(element instanceof HTMLElement, "Should not be an HTMLElement");
+ assert_false(element instanceof HTMLSpanElement, "Should not be an HTMLSpanElement");
+}, "Lower-case non-HTML element with a prefix");
+
+test(function() {
+ var HTMLNS = "http://www.w3.org/1999/xhtml";
+ var element = document.createElementNS(HTMLNS, "SPAN");
+ assert_equals(element.namespaceURI, HTMLNS);
+ assert_equals(element.prefix, null);
+ assert_equals(element.localName, "SPAN");
+ assert_equals(element.tagName, "SPAN");
+ assert_true(element instanceof Node, "Should be a Node");
+ assert_true(element instanceof Element, "Should be an Element");
+ assert_true(element instanceof HTMLElement, "Should be an HTMLElement");
+ assert_true(element instanceof HTMLUnknownElement, "Should be an HTMLUnknownElement");
+ assert_false(element instanceof HTMLSpanElement, "Should not be an HTMLSpanElement");
+}, "Upper-case HTML element without a prefix");
+
+test(function() {
+ var HTMLNS = "http://www.w3.org/1999/xhtml";
+ var element = document.createElementNS(HTMLNS, "html:SPAN");
+ assert_equals(element.namespaceURI, HTMLNS);
+ assert_equals(element.prefix, "html");
+ assert_equals(element.localName, "SPAN");
+ assert_equals(element.tagName, "HTML:SPAN");
+ assert_true(element instanceof Node, "Should be a Node");
+ assert_true(element instanceof Element, "Should be an Element");
+ assert_true(element instanceof HTMLElement, "Should be an HTMLElement");
+ assert_false(element instanceof HTMLSpanElement, "Should not be an HTMLSpanElement");
+}, "Upper-case HTML element with a prefix");
+
+test(function() {
+ var element = document.createElementNS("test", "SPAN");
+ assert_equals(element.namespaceURI, "test");
+ assert_equals(element.prefix, null);
+ assert_equals(element.localName, "SPAN");
+ assert_equals(element.tagName, "SPAN");
+ assert_true(element instanceof Node, "Should be a Node");
+ assert_true(element instanceof Element, "Should be an Element");
+ assert_false(element instanceof HTMLElement, "Should not be an HTMLElement");
+ assert_false(element instanceof HTMLSpanElement, "Should not be an HTMLSpanElement");
+}, "Upper-case non-HTML element without a prefix");
+
+test(function() {
+ var element = document.createElementNS("test", "html:SPAN");
+ assert_equals(element.namespaceURI, "test");
+ assert_equals(element.prefix, "html");
+ assert_equals(element.localName, "SPAN");
+ assert_equals(element.tagName, "html:SPAN");
+ assert_true(element instanceof Node, "Should be a Node");
+ assert_true(element instanceof Element, "Should be an Element");
+ assert_false(element instanceof HTMLElement, "Should not be an HTMLElement");
+ assert_false(element instanceof HTMLSpanElement, "Should not be an HTMLSpanElement");
+}, "Upper-case non-HTML element with a prefix");
+
+test(function() {
+ var element = document.createElementNS(null, "span");
+ assert_equals(element.namespaceURI, null);
+ assert_equals(element.prefix, null);
+ assert_equals(element.localName, "span");
+ assert_equals(element.tagName, "span");
+ assert_true(element instanceof Node, "Should be a Node");
+ assert_true(element instanceof Element, "Should be an Element");
+ assert_false(element instanceof HTMLElement, "Should not be an HTMLElement");
+ assert_false(element instanceof HTMLSpanElement, "Should not be an HTMLSpanElement");
+}, "null namespace");
+
+test(function() {
+ var element = document.createElementNS(undefined, "span");
+ assert_equals(element.namespaceURI, null);
+ assert_equals(element.prefix, null);
+ assert_equals(element.localName, "span");
+ assert_equals(element.tagName, "span");
+ assert_true(element instanceof Node, "Should be a Node");
+ assert_true(element instanceof Element, "Should be an Element");
+ assert_false(element instanceof HTMLElement, "Should not be an HTMLElement");
+ assert_false(element instanceof HTMLSpanElement, "Should not be an HTMLSpanElement");
+}, "undefined namespace");
+
+test(function() {
+ var element = document.createElementNS("", "span");
+ assert_equals(element.namespaceURI, null);
+ assert_equals(element.prefix, null);
+ assert_equals(element.localName, "span");
+ assert_equals(element.tagName, "span");
+ assert_true(element instanceof Node, "Should be a Node");
+ assert_true(element instanceof Element, "Should be an Element");
+ assert_false(element instanceof HTMLElement, "Should not be an HTMLElement");
+ assert_false(element instanceof HTMLSpanElement, "Should not be an HTMLSpanElement");
+}, "empty string namespace");
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-createElementNS.js b/tests/wpt/web-platform-tests/dom/nodes/Document-createElementNS.js
new file mode 100644
index 00000000000..84888777730
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-createElementNS.js
@@ -0,0 +1,162 @@
+var createElementNS_tests = [
+ /* Arrays with three elements:
+ * the namespace argument
+ * the qualifiedName argument
+ * the expected exception, or null if none
+ */
+ [null, undefined, null],
+ [null, "foo", null],
+ [null, "1foo", "INVALID_CHARACTER_ERR"],
+ [null, "f1oo", null],
+ [null, "foo1", null],
+ [null, "1foo", "INVALID_CHARACTER_ERR"],
+ [null, "\u0300foo", "INVALID_CHARACTER_ERR"],
+ [null, "}foo", "INVALID_CHARACTER_ERR"],
+ [null, "f}oo", "INVALID_CHARACTER_ERR"],
+ [null, "foo}", "INVALID_CHARACTER_ERR"],
+ [null, "\uFFFFfoo", "INVALID_CHARACTER_ERR"],
+ [null, "f\uFFFFoo", "INVALID_CHARACTER_ERR"],
+ [null, "foo\uFFFF", "INVALID_CHARACTER_ERR"],
+ [null, "<foo", "INVALID_CHARACTER_ERR"],
+ [null, "foo>", "INVALID_CHARACTER_ERR"],
+ [null, "<foo>", "INVALID_CHARACTER_ERR"],
+ [null, "f<oo", "INVALID_CHARACTER_ERR"],
+ [null, "^^", "INVALID_CHARACTER_ERR"],
+ [null, ":foo", "NAMESPACE_ERR"],
+ [null, "f:oo", "NAMESPACE_ERR"],
+ [null, "foo:", "NAMESPACE_ERR"],
+ [null, ":", "NAMESPACE_ERR"],
+ [null, "xml", null],
+ [null, "xmlns", "NAMESPACE_ERR"],
+ [null, "xmlfoo", null],
+ [null, "xml:foo", "NAMESPACE_ERR"],
+ [null, "xmlns:foo", "NAMESPACE_ERR"],
+ [null, "xmlfoo:bar", "NAMESPACE_ERR"],
+ [null, "null:xml", "NAMESPACE_ERR"],
+ ["", ":foo", "NAMESPACE_ERR"],
+ ["", "f:oo", "NAMESPACE_ERR"],
+ ["", "foo:", "NAMESPACE_ERR"],
+ [undefined, undefined, null],
+ [undefined, "foo", null],
+ [undefined, "1foo", "INVALID_CHARACTER_ERR"],
+ [undefined, "f1oo", null],
+ [undefined, "foo1", null],
+ [undefined, ":foo", "NAMESPACE_ERR"],
+ [undefined, "f:oo", "NAMESPACE_ERR"],
+ [undefined, "foo:", "NAMESPACE_ERR"],
+ [undefined, "xml", null],
+ [undefined, "xmlns", "NAMESPACE_ERR"],
+ [undefined, "xmlfoo", null],
+ [undefined, "xml:foo", "NAMESPACE_ERR"],
+ [undefined, "xmlns:foo", "NAMESPACE_ERR"],
+ [undefined, "xmlfoo:bar", "NAMESPACE_ERR"],
+ ["http://example.com/", "foo", null],
+ ["http://example.com/", "1foo", "INVALID_CHARACTER_ERR"],
+ ["http://example.com/", "f1oo", null],
+ ["http://example.com/", "foo1", null],
+ ["http://example.com/", ":foo", "NAMESPACE_ERR"],
+ ["http://example.com/", "f:oo", null],
+ ["http://example.com/", "foo:", "NAMESPACE_ERR"],
+ ["http://example.com/", "_:_", null],
+ ["http://example.com/", "_:h0", null],
+ ["http://example.com/", "_:test", null],
+ ["http://example.com/", "l_:_", null],
+ ["http://example.com/", "ns:_0", null],
+ ["http://example.com/", "ns:a0", null],
+ ["http://example.com/", "ns0:test", null],
+ ["http://example.com/", "a.b:c", null],
+ ["http://example.com/", "a-b:c", null],
+ ["http://example.com/", "a-b:c", null],
+ ["http://example.com/", "xml", null],
+ ["http://example.com/", "xmlns", "NAMESPACE_ERR"],
+ ["http://example.com/", "XMLNS", null],
+ ["http://example.com/", "xmlfoo", null],
+ ["http://example.com/", "xml:foo", "NAMESPACE_ERR"],
+ ["http://example.com/", "XML:foo", null],
+ ["http://example.com/", "xmlns:foo", "NAMESPACE_ERR"],
+ ["http://example.com/", "XMLNS:foo", null],
+ ["http://example.com/", "xmlfoo:bar", null],
+ ["http://example.com/", "prefix::local", "NAMESPACE_ERR"],
+ ["http://example.com/", "namespaceURI:{", "INVALID_CHARACTER_ERR"],
+ ["http://example.com/", "namespaceURI:}", "INVALID_CHARACTER_ERR"],
+ ["http://example.com/", "namespaceURI:~", "INVALID_CHARACTER_ERR"],
+ ["http://example.com/", "namespaceURI:'", "INVALID_CHARACTER_ERR"],
+ ["http://example.com/", "namespaceURI:!", "INVALID_CHARACTER_ERR"],
+ ["http://example.com/", "namespaceURI:@", "INVALID_CHARACTER_ERR"],
+ ["http://example.com/", "namespaceURI:#", "INVALID_CHARACTER_ERR"],
+ ["http://example.com/", "namespaceURI:$", "INVALID_CHARACTER_ERR"],
+ ["http://example.com/", "namespaceURI:%", "INVALID_CHARACTER_ERR"],
+ ["http://example.com/", "namespaceURI:^", "INVALID_CHARACTER_ERR"],
+ ["http://example.com/", "namespaceURI:&", "INVALID_CHARACTER_ERR"],
+ ["http://example.com/", "namespaceURI:*", "INVALID_CHARACTER_ERR"],
+ ["http://example.com/", "namespaceURI:(", "INVALID_CHARACTER_ERR"],
+ ["http://example.com/", "namespaceURI:)", "INVALID_CHARACTER_ERR"],
+ ["http://example.com/", "namespaceURI:+", "INVALID_CHARACTER_ERR"],
+ ["http://example.com/", "namespaceURI:=", "INVALID_CHARACTER_ERR"],
+ ["http://example.com/", "namespaceURI:[", "INVALID_CHARACTER_ERR"],
+ ["http://example.com/", "namespaceURI:]", "INVALID_CHARACTER_ERR"],
+ ["http://example.com/", "namespaceURI:\\", "INVALID_CHARACTER_ERR"],
+ ["http://example.com/", "namespaceURI:/", "INVALID_CHARACTER_ERR"],
+ ["http://example.com/", "namespaceURI:;", "INVALID_CHARACTER_ERR"],
+ ["http://example.com/", "namespaceURI:`", "INVALID_CHARACTER_ERR"],
+ ["http://example.com/", "namespaceURI:<", "INVALID_CHARACTER_ERR"],
+ ["http://example.com/", "namespaceURI:>", "INVALID_CHARACTER_ERR"],
+ ["http://example.com/", "namespaceURI:,", "INVALID_CHARACTER_ERR"],
+ ["http://example.com/", "namespaceURI:a ", "INVALID_CHARACTER_ERR"],
+ ["http://example.com/", "namespaceURI:\"", "INVALID_CHARACTER_ERR"],
+ ["/", "foo", null],
+ ["/", "1foo", "INVALID_CHARACTER_ERR"],
+ ["/", "f1oo", null],
+ ["/", "foo1", null],
+ ["/", ":foo", "NAMESPACE_ERR"],
+ ["/", "f:oo", null],
+ ["/", "foo:", "NAMESPACE_ERR"],
+ ["/", "xml", null],
+ ["/", "xmlns", "NAMESPACE_ERR"],
+ ["/", "xmlfoo", null],
+ ["/", "xml:foo", "NAMESPACE_ERR"],
+ ["/", "xmlns:foo", "NAMESPACE_ERR"],
+ ["/", "xmlfoo:bar", null],
+ ["http://www.w3.org/XML/1998/namespace", "foo", null],
+ ["http://www.w3.org/XML/1998/namespace", "1foo", "INVALID_CHARACTER_ERR"],
+ ["http://www.w3.org/XML/1998/namespace", "f1oo", null],
+ ["http://www.w3.org/XML/1998/namespace", "foo1", null],
+ ["http://www.w3.org/XML/1998/namespace", ":foo", "NAMESPACE_ERR"],
+ ["http://www.w3.org/XML/1998/namespace", "f:oo", null],
+ ["http://www.w3.org/XML/1998/namespace", "foo:", "NAMESPACE_ERR"],
+ ["http://www.w3.org/XML/1998/namespace", "xml", null],
+ ["http://www.w3.org/XML/1998/namespace", "xmlns", "NAMESPACE_ERR"],
+ ["http://www.w3.org/XML/1998/namespace", "xmlfoo", null],
+ ["http://www.w3.org/XML/1998/namespace", "xml:foo", null],
+ ["http://www.w3.org/XML/1998/namespace", "xmlns:foo", "NAMESPACE_ERR"],
+ ["http://www.w3.org/XML/1998/namespace", "xmlfoo:bar", null],
+ ["http://www.w3.org/XML/1998/namespaces", "xml:foo", "NAMESPACE_ERR"],
+ ["http://www.w3.org/xml/1998/namespace", "xml:foo", "NAMESPACE_ERR"],
+ ["http://www.w3.org/2000/xmlns/", "foo", "NAMESPACE_ERR"],
+ ["http://www.w3.org/2000/xmlns/", "1foo", "INVALID_CHARACTER_ERR"],
+ ["http://www.w3.org/2000/xmlns/", "f1oo", "NAMESPACE_ERR"],
+ ["http://www.w3.org/2000/xmlns/", "foo1", "NAMESPACE_ERR"],
+ ["http://www.w3.org/2000/xmlns/", ":foo", "NAMESPACE_ERR"],
+ ["http://www.w3.org/2000/xmlns/", "f:oo", "NAMESPACE_ERR"],
+ ["http://www.w3.org/2000/xmlns/", "foo:", "NAMESPACE_ERR"],
+ ["http://www.w3.org/2000/xmlns/", "xml", "NAMESPACE_ERR"],
+ ["http://www.w3.org/2000/xmlns/", "xmlns", null],
+ ["http://www.w3.org/2000/xmlns/", "xmlfoo", "NAMESPACE_ERR"],
+ ["http://www.w3.org/2000/xmlns/", "xml:foo", "NAMESPACE_ERR"],
+ ["http://www.w3.org/2000/xmlns/", "xmlns:foo", null],
+ ["http://www.w3.org/2000/xmlns/", "xmlfoo:bar", "NAMESPACE_ERR"],
+ ["http://www.w3.org/2000/xmlns/", "foo:xmlns", "NAMESPACE_ERR"],
+ ["foo:", "foo", null],
+ ["foo:", "1foo", "INVALID_CHARACTER_ERR"],
+ ["foo:", "f1oo", null],
+ ["foo:", "foo1", null],
+ ["foo:", ":foo", "NAMESPACE_ERR"],
+ ["foo:", "f:oo", null],
+ ["foo:", "foo:", "NAMESPACE_ERR"],
+ ["foo:", "xml", null],
+ ["foo:", "xmlns", "NAMESPACE_ERR"],
+ ["foo:", "xmlfoo", null],
+ ["foo:", "xml:foo", "NAMESPACE_ERR"],
+ ["foo:", "xmlns:foo", "NAMESPACE_ERR"],
+ ["foo:", "xmlfoo:bar", null],
+]
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-createEvent.html b/tests/wpt/web-platform-tests/dom/nodes/Document-createEvent.html
new file mode 100644
index 00000000000..37704519321
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-createEvent.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Document.createEvent</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-document-createevent">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="Document-createEvent.js"></script>
+<div id="log"></div>
+<script>
+function testAlias(arg, iface) {
+ var ev;
+ test(function() {
+ ev = document.createEvent(arg);
+ assert_true(ev instanceof window[iface]);
+ assert_true(ev instanceof Event);
+ }, arg + " should be an alias for " + iface + ".");
+ test(function() {
+ assert_equals(ev.type, "",
+ "type should be initialized to the empty string");
+ assert_equals(ev.target, null,
+ "target should be initialized to null");
+ assert_equals(ev.currentTarget, null,
+ "currentTarget should be initialized to null");
+ assert_equals(ev.eventPhase, 0,
+ "eventPhase should be initialized to NONE (0)");
+ assert_equals(ev.bubbles, false,
+ "bubbles should be initialized to false");
+ assert_equals(ev.cancelable, false,
+ "cancelable should be initialized to false");
+ assert_equals(ev.defaultPrevented, false,
+ "defaultPrevented should be initialized to false");
+ assert_equals(ev.isTrusted, false,
+ "isTrusted should be initialized to false");
+ }, "createEvent('" + arg + "') should be initialized correctly.");
+}
+aliases.forEach(function(alias) {
+ testAlias(alias[0], alias[1]);
+ testAlias(alias[0].toLowerCase(), alias[1]);
+ testAlias(alias[0].toUpperCase(), alias[1]);
+});
+
+test(function() {
+ assert_throws("NOT_SUPPORTED_ERR", function() {
+ var evt = document.createEvent("foo");
+ });
+ assert_throws("NOT_SUPPORTED_ERR", function() {
+ // 'LATIN CAPITAL LETTER I WITH DOT ABOVE' (U+0130)
+ var evt = document.createEvent("U\u0130Event");
+ });
+ assert_throws("NOT_SUPPORTED_ERR", function() {
+ // 'LATIN SMALL LETTER DOTLESS I' (U+0131)
+ var evt = document.createEvent("U\u0131Event");
+ });
+}, "Should throw NOT_SUPPORTED_ERR for unrecognized arguments");
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-createEvent.js b/tests/wpt/web-platform-tests/dom/nodes/Document-createEvent.js
new file mode 100644
index 00000000000..90cc73c08cd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-createEvent.js
@@ -0,0 +1,14 @@
+var aliases = [
+ ["CustomEvent", "CustomEvent"],
+ ["Event", "Event"],
+ ["Events", "Event"],
+ ["HTMLEvents", "Event"],
+ ["KeyboardEvent", "KeyboardEvent"],
+ ["KeyEvents", "KeyboardEvent"],
+ ["MessageEvent", "MessageEvent"],
+ ["MouseEvent", "MouseEvent"],
+ ["MouseEvents", "MouseEvent"],
+ ["TouchEvent", "TouchEvent"],
+ ["UIEvent", "UIEvent"],
+ ["UIEvents", "UIEvent"]
+];
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-createProcessingInstruction.html b/tests/wpt/web-platform-tests/dom/nodes/Document-createProcessingInstruction.html
new file mode 100644
index 00000000000..c57a792face
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-createProcessingInstruction.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Document.createProcessingInstruction in HTML documents</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-document-createprocessinginstruction">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-processinginstruction-target">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-data">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-node-ownerdocument">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src="Document-createProcessingInstruction.js"></script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-createProcessingInstruction.js b/tests/wpt/web-platform-tests/dom/nodes/Document-createProcessingInstruction.js
new file mode 100644
index 00000000000..114ac35d9f8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-createProcessingInstruction.js
@@ -0,0 +1,39 @@
+test(function() {
+ var invalid = [
+ ["A", "?>"],
+ ["\u00B7A", "x"],
+ ["\u00D7A", "x"],
+ ["A\u00D7", "x"],
+ ["\\A", "x"],
+ ["\f", "x"],
+ [0, "x"],
+ ["0", "x"]
+ ],
+ valid = [
+ ["xml:fail", "x"],
+ ["A\u00B7A", "x"],
+ ["a0", "x"]
+ ]
+
+ for (var i = 0, il = invalid.length; i < il; i++) {
+ test(function() {
+ assert_throws("INVALID_CHARACTER_ERR", function() {
+ document.createProcessingInstruction(invalid[i][0], invalid[i][1])
+ })
+ }, "Should throw an INVALID_CHARACTER_ERR for target " +
+ format_value(invalid[i][0]) + " and data " +
+ format_value(invalid[i][1]) + ".")
+ }
+ for (var i = 0, il = valid.length; i < il; ++i) {
+ test(function() {
+ var pi = document.createProcessingInstruction(valid[i][0], valid[i][1]);
+ assert_equals(pi.target, valid[i][0]);
+ assert_equals(pi.data, valid[i][1]);
+ assert_equals(pi.ownerDocument, document);
+ assert_true(pi instanceof ProcessingInstruction);
+ assert_true(pi instanceof Node);
+ }, "Should get a ProcessingInstruction for target " +
+ format_value(valid[i][0]) + " and data " +
+ format_value(valid[i][1]) + ".")
+ }
+})
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-createProcessingInstruction.xhtml b/tests/wpt/web-platform-tests/dom/nodes/Document-createProcessingInstruction.xhtml
new file mode 100644
index 00000000000..d06f70fdcba
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-createProcessingInstruction.xhtml
@@ -0,0 +1,15 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Document.createProcessingInstruction in XML documents</title>
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-document-createprocessinginstruction"/>
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-processinginstruction-target"/>
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-characterdata-data"/>
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-node-ownerdocument"/>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id="log"/>
+<script src="Document-createProcessingInstruction.js"/>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-createTextNode.html b/tests/wpt/web-platform-tests/dom/nodes/Document-createTextNode.html
new file mode 100644
index 00000000000..ccc1b1b77f5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-createTextNode.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Document.createTextNode</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-document-createtextnode">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-node-ownerdocument">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-data">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-node-nodevalue">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-node-textcontent">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-characterdata-length">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-node-nodetype">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-node-haschildnodes">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-node-childnodes">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-node-firstchild">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-node-lastchild">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="Document-createComment-createTextNode.js"></script>
+<div id="log"></div>
+<script>
+test_create("createTextNode", Text, 3, "#text");
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-createTreeWalker.html b/tests/wpt/web-platform-tests/dom/nodes/Document-createTreeWalker.html
new file mode 100644
index 00000000000..f8f04b068fd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-createTreeWalker.html
@@ -0,0 +1,42 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Document.createTreeWalker</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function() {
+ assert_throws(new TypeError(), function() {
+ document.createTreeWalker();
+ });
+}, "Required arguments to createTreeWalker should be required.");
+test(function() {
+ var tw = document.createTreeWalker(document.body);
+ assert_equals(tw.root, document.body);
+ assert_equals(tw.currentNode, document.body);
+ assert_equals(tw.whatToShow, 0xFFFFFFFF);
+ assert_equals(tw.filter, null);
+}, "Optional arguments to createTreeWalker should be optional (1 passed).");
+test(function() {
+ var tw = document.createTreeWalker(document.body, 42);
+ assert_equals(tw.root, document.body);
+ assert_equals(tw.currentNode, document.body);
+ assert_equals(tw.whatToShow, 42);
+ assert_equals(tw.filter, null);
+}, "Optional arguments to createTreeWalker should be optional (2 passed).");
+test(function() {
+ var tw = document.createTreeWalker(document.body, 42, null);
+ assert_equals(tw.root, document.body);
+ assert_equals(tw.currentNode, document.body);
+ assert_equals(tw.whatToShow, 42);
+ assert_equals(tw.filter, null);
+}, "Optional arguments to createTreeWalker should be optional (3 passed, null).");
+test(function() {
+ var fn = function() {};
+ var tw = document.createTreeWalker(document.body, 42, fn);
+ assert_equals(tw.root, document.body);
+ assert_equals(tw.currentNode, document.body);
+ assert_equals(tw.whatToShow, 42);
+ assert_equals(tw.filter, fn);
+}, "Optional arguments to createTreeWalker should be optional (3 passed, function).");
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-doctype.html b/tests/wpt/web-platform-tests/dom/nodes/Document-doctype.html
new file mode 100644
index 00000000000..75bfd8506d4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-doctype.html
@@ -0,0 +1,21 @@
+<!-- comment -->
+<!doctype html>
+<meta charset=utf-8>
+<title>Document.doctype</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-document-doctype">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ assert_true(document.doctype instanceof DocumentType,
+ "Doctype should be a DocumentType");
+ assert_equals(document.doctype, document.childNodes[1]);
+}, "Window document with doctype");
+
+test(function() {
+ var newdoc = new Document();
+ newdoc.appendChild(newdoc.createElement("html"));
+ assert_equals(newdoc.doctype, null);
+}, "new Document()");
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-getElementById.html b/tests/wpt/web-platform-tests/dom/nodes/Document-getElementById.html
new file mode 100644
index 00000000000..66ca0e7c81b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-getElementById.html
@@ -0,0 +1,312 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Document.getElementById</title>
+<link rel="author" title="Tetsuharu OHZEKI" href="mailto:saneyuki.snyk@gmail.com">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-document-getelementbyid">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+ <div id="log"></div>
+
+ <!-- test 0 -->
+ <div id=""></div>
+
+ <!-- test 1 -->
+ <div id="test1"></div>
+
+ <!-- test 5 -->
+ <div id="test5" data-name="1st">
+ <p id="test5" data-name="2nd">P</p>
+ <input id="test5" type="submit" value="Submit" data-name="3rd">
+ </div>
+
+<script>
+ var gBody = document.getElementsByTagName("body")[0];
+
+ test(function() {
+ assert_equals(document.getElementById(""), null);
+ }, "Calling document.getElementById with an empty string argument.");
+
+
+ test(function() {
+ var bar = document.getElementById("test1");
+ assert_not_equals(bar, null, "should not be null");
+ assert_equals(bar.tagName, "DIV", "should have expected tag name.");
+ assert_true(bar instanceof HTMLDivElement, "should be a valid Element instance");
+ }, "on static page");
+
+
+ test(function() {
+ var TEST_ID = "test2";
+
+ var test = document.createElement("div");
+ test.setAttribute("id", TEST_ID);
+ gBody.appendChild(test);
+
+ // test: appended element
+ var result = document.getElementById(TEST_ID);
+ assert_not_equals(result, null, "should not be null.");
+ assert_equals(result.tagName, "DIV", "should have appended element's tag name");
+ assert_true(result instanceof HTMLDivElement, "should be a valid Element instance");
+
+ // test: removed element
+ gBody.removeChild(test);
+ var removed = document.getElementById(TEST_ID);
+ // `document.getElementById()` returns `null` if there is none.
+ // https://dom.spec.whatwg.org/#dom-nonelementparentnode-getelementbyid
+ assert_equals(removed, null, "should not get removed element.");
+ }, "Document.getElementById with a script-inserted element");
+
+
+ test(function() {
+ // setup fixtures.
+ var TEST_ID = "test3";
+ var test = document.createElement("div");
+ test.setAttribute("id", TEST_ID);
+ gBody.appendChild(test);
+
+ // update id
+ var UPDATED_ID = "test3-updated";
+ test.setAttribute("id", UPDATED_ID);
+ var e = document.getElementById(UPDATED_ID);
+ assert_equals(e, test, "should get the element with id.");
+
+ var old = document.getElementById(TEST_ID);
+ assert_equals(old, null, "shouldn't get the element by the old id.");
+
+ // remove id.
+ test.removeAttribute("id");
+ var e2 = document.getElementById(UPDATED_ID);
+ assert_equals(e2, null, "should return null when the passed id is none in document.");
+ }, "update `id` attribute via setAttribute/removeAttribute");
+
+
+ test(function() {
+ var TEST_ID = "test4-should-not-exist";
+
+ var e = document.createElement('div');
+ e.setAttribute("id", TEST_ID);
+
+ assert_equals(document.getElementById(TEST_ID), null, "should be null");
+ document.body.appendChild(e);
+ assert_equals(document.getElementById(TEST_ID), e, "should be the appended element");
+ }, "Ensure that the id attribute only affects elements present in a document");
+
+
+ test(function() {
+ // the method should return the 1st element.
+ var TEST_ID = "test5";
+ var target = document.getElementById(TEST_ID);
+ assert_not_equals(target, null, "should not be null");
+ assert_equals(target.getAttribute("data-name"), "1st", "should return the 1st");
+
+ // even if after the new element was appended.
+ var element4 = document.createElement("div");
+ element4.setAttribute("id", TEST_ID);
+ element4.setAttribute("data-name", "4th");
+ gBody.appendChild(element4);
+ var target2 = document.getElementById(TEST_ID);
+ assert_not_equals(target2, null, "should not be null");
+ assert_equals(target2.getAttribute("data-name"), "1st", "should be the 1st");
+
+ // should return the next element after removed the subtree including the 1st element.
+ target2.parentNode.removeChild(target2);
+ var target3 = document.getElementById(TEST_ID);
+ assert_not_equals(target3, null, "should not be null");
+ assert_equals(target3.getAttribute("data-name"), "4th", "should be the 4th");
+ }, "in tree order, within the context object's tree");
+
+
+ test(function() {
+ var TEST_ID = "test6";
+ var s = document.createElement("div");
+ s.setAttribute("id", TEST_ID);
+ // append to Element, not Document.
+ document.createElement("div").appendChild(s);
+
+ assert_equals(document.getElementById(TEST_ID), null, "should be null");
+ }, "Modern browsers optimize this method with using internal id cache. " +
+ "This test checks that their optimization should effect only append to `Document`, not append to `Node`.");
+
+
+ test(function() {
+ var TEST_ID = "test7"
+ var element = document.createElement("div");
+ element.setAttribute("id", TEST_ID);
+ gBody.appendChild(element);
+
+ var target = document.getElementById(TEST_ID);
+ assert_equals(target, element, "should return the element before changing the value");
+
+ element.attributes[0].value = TEST_ID + "-updated";
+ var target2 = document.getElementById(TEST_ID);
+ assert_equals(target2, null, "should return null after updated id via Attr.value");
+ var target3 = document.getElementById(TEST_ID + "-updated");
+ assert_equals(target3, element, "should be equal to the updated element.");
+ }, "changing attribute's value via `Attr` gotten from `Element.attribute`.");
+
+
+ test(function() {
+ var TEST_ID = "test8";
+
+ // setup fixture
+ var element = document.createElement("div");
+ element.setAttribute("id", TEST_ID + "-fixture");
+ gBody.appendChild(element);
+
+ // add id-ed element with using innerHTML
+ element.innerHTML = "<div id='"+ TEST_ID +"'></div>";
+ var test = document.getElementById(TEST_ID);
+ assert_equals(test, element.firstChild, "should not be null");
+ assert_equals(test.tagName, "DIV", "should have expected tag name.");
+ assert_true(test instanceof HTMLDivElement, "should be a valid Element instance");
+ }, "add id attribute via innerHTML");
+
+
+ test(function() {
+ var TEST_ID = "test9";
+
+ // add fixture
+ var fixture = document.createElement("div");
+ fixture.setAttribute("id", TEST_ID + "-fixture");
+ gBody.appendChild(fixture);
+
+ var element = document.createElement("div");
+ element.setAttribute("id", TEST_ID);
+ fixture.appendChild(element);
+
+ // check 'getElementById' should get the 'element'
+ assert_equals(document.getElementById(TEST_ID), element, "should not be null");
+
+ // remove id-ed element with using innerHTML (clear 'element')
+ fixture.innerHTML = "";
+ var test = document.getElementById(TEST_ID);
+ assert_equals(test, null, "should be null.");
+ }, "remove id attribute via innerHTML");
+
+
+ test(function() {
+ var TEST_ID = "test10";
+
+ // setup fixture
+ var element = document.createElement("div");
+ element.setAttribute("id", TEST_ID + "-fixture");
+ gBody.appendChild(element);
+
+ // add id-ed element with using outerHTML
+ element.outerHTML = "<div id='"+ TEST_ID +"'></div>";
+ var test = document.getElementById(TEST_ID);
+ assert_not_equals(test, null, "should not be null");
+ assert_equals(test.tagName, "DIV", "should have expected tag name.");
+ assert_true(test instanceof HTMLDivElement,"should be a valid Element instance");
+ }, "add id attribute via outerHTML");
+
+
+ test(function() {
+ var TEST_ID = "test11";
+
+ var element = document.createElement("div");
+ element.setAttribute("id", TEST_ID);
+ gBody.appendChild(element);
+
+ var test = document.getElementById(TEST_ID);
+ assert_equals(test, element, "should be equal to the appended element.");
+
+ // remove id-ed element with using outerHTML
+ element.outerHTML = "<div></div>";
+ var test = document.getElementById(TEST_ID);
+ assert_equals(test, null, "should be null.");
+ }, "remove id attribute via outerHTML");
+
+
+ test(function() {
+ // setup fixtures.
+ var TEST_ID = "test12";
+ var test = document.createElement("div");
+ test.id = TEST_ID;
+ gBody.appendChild(test);
+
+ // update id
+ var UPDATED_ID = TEST_ID + "-updated";
+ test.id = UPDATED_ID;
+ var e = document.getElementById(UPDATED_ID);
+ assert_equals(e, test, "should get the element with id.");
+
+ var old = document.getElementById(TEST_ID);
+ assert_equals(old, null, "shouldn't get the element by the old id.");
+
+ // remove id.
+ test.id = "";
+ var e2 = document.getElementById(UPDATED_ID);
+ assert_equals(e2, null, "should return null when the passed id is none in document.");
+ }, "update `id` attribute via element.id");
+
+
+ test(function() {
+ var TEST_ID = "test13";
+
+ var create_same_id_element = function (order) {
+ var element = document.createElement("div");
+ element.setAttribute("id", TEST_ID);
+ element.setAttribute("data-order", order);// for debug
+ return element;
+ };
+
+ // create fixture
+ var container = document.createElement("div");
+ container.setAttribute("id", TEST_ID + "-fixture");
+ gBody.appendChild(container);
+
+ var element1 = create_same_id_element("1");
+ var element2 = create_same_id_element("2");
+ var element3 = create_same_id_element("3");
+ var element4 = create_same_id_element("4");
+
+ // append element: 2 -> 4 -> 3 -> 1
+ container.appendChild(element2);
+ container.appendChild(element4);
+ container.insertBefore(element3, element4);
+ container.insertBefore(element1, element2);
+
+
+ var test = document.getElementById(TEST_ID);
+ assert_equals(test, element1, "should return 1st element");
+ container.removeChild(element1);
+
+ test = document.getElementById(TEST_ID);
+ assert_equals(test, element2, "should return 2nd element");
+ container.removeChild(element2);
+
+ test = document.getElementById(TEST_ID);
+ assert_equals(test, element3, "should return 3rd element");
+ container.removeChild(element3);
+
+ test = document.getElementById(TEST_ID);
+ assert_equals(test, element4, "should return 4th element");
+ container.removeChild(element4);
+
+
+ }, "where insertion order and tree order don't match");
+
+ test(function() {
+ var TEST_ID = "test14";
+ var a = document.createElement("a");
+ var b = document.createElement("b");
+ a.appendChild(b);
+ b.id = TEST_ID;
+ assert_equals(document.getElementById(TEST_ID), null);
+
+ gBody.appendChild(a);
+ assert_equals(document.getElementById(TEST_ID), b);
+ }, "Inserting an id by inserting its parent node");
+
+ // TODO:
+ // id attribute in a namespace
+
+
+ // TODO:
+ // SVG + MathML elements with id attributes
+
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-getElementsByTagName.html b/tests/wpt/web-platform-tests/dom/nodes/Document-getElementsByTagName.html
new file mode 100644
index 00000000000..00e3435c4c3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-getElementsByTagName.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Document.getElementsByTagName</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-document-getelementsbytagname">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="Document-Element-getElementsByTagName.js"></script>
+<div id="log"></div>
+<script>
+test_getElementsByTagName(document, document.body);
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-getElementsByTagName.xhtml b/tests/wpt/web-platform-tests/dom/nodes/Document-getElementsByTagName.xhtml
new file mode 100644
index 00000000000..e3aae85704d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-getElementsByTagName.xhtml
@@ -0,0 +1,102 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Document.getElementsByTagName</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id="log"></div>
+<pre id="x"></pre>
+<script>
+test(function() {
+ var t = document.body.appendChild(document.createElementNS("http://www.w3.org/1999/xhtml", "I"))
+ this.add_cleanup(function() {document.body.removeChild(t)})
+ assert_equals(t.localName, "I")
+ assert_equals(t.tagName, "I")
+ assert_array_equals(document.getElementsByTagName("I"), [t])
+ assert_array_equals(document.getElementsByTagName("i"), [])
+ assert_array_equals(document.body.getElementsByTagName("I"), [t])
+ assert_array_equals(document.body.getElementsByTagName("i"), [])
+}, "HTML element with uppercase tag name matches in XHTML documents")
+
+test(function() {
+ var t = document.body.appendChild(document.createElementNS("test", "st"))
+ this.add_cleanup(function() {document.body.removeChild(t)})
+ assert_array_equals(document.getElementsByTagName("st"), [t])
+ assert_array_equals(document.getElementsByTagName("ST"), [])
+}, "Element in non-HTML namespace, no prefix, lowercase name")
+
+test(function() {
+ var t = document.body.appendChild(document.createElementNS("test", "ST"))
+ this.add_cleanup(function() {document.body.removeChild(t)})
+ assert_array_equals(document.getElementsByTagName("ST"), [t])
+ assert_array_equals(document.getElementsByTagName("st"), [])
+}, "Element in non-HTML namespace, no prefix, uppercase name")
+
+test(function() {
+ var t = document.body.appendChild(document.createElementNS("test", "te:st"))
+ this.add_cleanup(function() {document.body.removeChild(t)})
+ assert_array_equals(document.getElementsByTagName("st"), [t])
+ assert_array_equals(document.getElementsByTagName("ST"), [])
+}, "Element in non-HTML namespace, prefix, lowercase name")
+
+test(function() {
+ var t = document.body.appendChild(document.createElementNS("test", "te:ST"))
+ this.add_cleanup(function() {document.body.removeChild(t)})
+ assert_array_equals(document.getElementsByTagName("ST"), [t])
+ assert_array_equals(document.getElementsByTagName("st"), [])
+ assert_array_equals(document.getElementsByTagName("te:st"), [])
+ assert_array_equals(document.getElementsByTagName("te:ST"), [])
+}, "Element in non-HTML namespace, prefix, uppercase name")
+
+test(function() {
+ var t = document.body.appendChild(document.createElement("AÇ"))
+ this.add_cleanup(function() {document.body.removeChild(t)})
+ assert_array_equals(document.getElementsByTagName("AÇ"), [t], "All uppercase input")
+ assert_array_equals(document.getElementsByTagName("aÇ"), [], "Ascii lowercase input")
+ assert_array_equals(document.getElementsByTagName("aç"), [], "All lowercase input")
+}, "Element in HTML namespace, no prefix, non-ascii characters in name")
+
+test(function() {
+ var t = document.body.appendChild(document.createElementNS("test", "AÇ"))
+ this.add_cleanup(function() {document.body.removeChild(t)})
+ assert_array_equals(document.getElementsByTagName("AÇ"), [t], "All uppercase input")
+ assert_array_equals(document.getElementsByTagName("aÇ"), [], "Ascii lowercase input")
+ assert_array_equals(document.getElementsByTagName("aç"), [], "All lowercase input")
+}, "Element in non-HTML namespace, non-ascii characters in name")
+
+test(function() {
+ var t = document.body.appendChild(document.createElementNS("http://www.w3.org/1999/xhtml", "test:aÇ"))
+ this.add_cleanup(function() {document.body.removeChild(t)})
+ assert_array_equals(document.getElementsByTagName("AÇ"), [], "All uppercase input")
+ assert_array_equals(document.getElementsByTagName("aÇ"), [t], "Ascii lowercase input")
+ assert_array_equals(document.getElementsByTagName("aç"), [], "All lowercase input")
+}, "Element in HTML namespace, prefix, non-ascii characters in name")
+
+test(function() {
+ var t = document.body.appendChild(document.createElementNS("test", "test:AÇ"))
+ this.add_cleanup(function() {document.body.removeChild(t)})
+ assert_array_equals(document.getElementsByTagName("AÇ"), [t], "All uppercase input")
+ assert_array_equals(document.getElementsByTagName("aÇ"), [], "Ascii lowercase input")
+ assert_array_equals(document.getElementsByTagName("aç"), [], "All lowercase input")
+}, "Element in non-HTML namespace, prefix, non-ascii characters in name")
+
+test(function() {
+ var actual = document.getElementsByTagName("*");
+ var expected = [];
+ var get_elements = function(node) {
+ for (var i = 0; i &lt; node.childNodes.length; i++) {
+ var child = node.childNodes[i];
+ if (child.nodeType === child.ELEMENT_NODE) {
+ expected.push(child);
+ get_elements(child);
+ }
+ }
+ }
+ get_elements(document);
+ assert_array_equals(actual, expected);
+}, "getElementsByTagName('*')")
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-getElementsByTagNameNS.html b/tests/wpt/web-platform-tests/dom/nodes/Document-getElementsByTagNameNS.html
new file mode 100644
index 00000000000..063dc982158
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-getElementsByTagNameNS.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Document.getElementsByTagNameNS</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-document-getelementsbytagnamens">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="Document-Element-getElementsByTagNameNS.js"></script>
+<div id="log"></div>
+<script>
+test_getElementsByTagNameNS(document, document.body);
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-implementation.html b/tests/wpt/web-platform-tests/dom/nodes/Document-implementation.html
new file mode 100644
index 00000000000..aed5259659b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-implementation.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Document.implementation</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-document-implementation">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ var implementation = document.implementation;
+ assert_true(implementation instanceof DOMImplementation,
+ "implementation should implement DOMImplementation");
+ assert_equals(document.implementation, implementation);
+}, "Getting implementation off the same document");
+
+test(function() {
+ var doc = document.implementation.createHTMLDocument();
+ assert_not_equals(document.implementation, doc.implementation);
+}, "Getting implementation off different documents");
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Document-importNode.html b/tests/wpt/web-platform-tests/dom/nodes/Document-importNode.html
new file mode 100644
index 00000000000..32e2f316979
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Document-importNode.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Document.importNode</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-document-importnode">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ var doc = document.implementation.createHTMLDocument("Title");
+ var div = doc.body.appendChild(doc.createElement("div"));
+ div.appendChild(doc.createElement("span"));
+ assert_equals(div.ownerDocument, doc);
+ assert_equals(div.firstChild.ownerDocument, doc);
+ var newDiv = document.importNode(div);
+ assert_equals(div.ownerDocument, doc);
+ assert_equals(div.firstChild.ownerDocument, doc);
+ assert_equals(newDiv.ownerDocument, document);
+ assert_equals(newDiv.firstChild, null);
+}, "No 'deep' argument.")
+test(function() {
+ var doc = document.implementation.createHTMLDocument("Title");
+ var div = doc.body.appendChild(doc.createElement("div"));
+ div.appendChild(doc.createElement("span"));
+ assert_equals(div.ownerDocument, doc);
+ assert_equals(div.firstChild.ownerDocument, doc);
+ var newDiv = document.importNode(div, undefined);
+ assert_equals(div.ownerDocument, doc);
+ assert_equals(div.firstChild.ownerDocument, doc);
+ assert_equals(newDiv.ownerDocument, document);
+ assert_equals(newDiv.firstChild, null);
+}, "Undefined 'deep' argument.")
+test(function() {
+ var doc = document.implementation.createHTMLDocument("Title");
+ var div = doc.body.appendChild(doc.createElement("div"));
+ div.appendChild(doc.createElement("span"));
+ assert_equals(div.ownerDocument, doc);
+ assert_equals(div.firstChild.ownerDocument, doc);
+ var newDiv = document.importNode(div, true);
+ assert_equals(div.ownerDocument, doc);
+ assert_equals(div.firstChild.ownerDocument, doc);
+ assert_equals(newDiv.ownerDocument, document);
+ assert_equals(newDiv.firstChild.ownerDocument, document);
+}, "True 'deep' argument.")
+test(function() {
+ var doc = document.implementation.createHTMLDocument("Title");
+ var div = doc.body.appendChild(doc.createElement("div"));
+ div.appendChild(doc.createElement("span"));
+ assert_equals(div.ownerDocument, doc);
+ assert_equals(div.firstChild.ownerDocument, doc);
+ var newDiv = document.importNode(div, false);
+ assert_equals(div.ownerDocument, doc);
+ assert_equals(div.firstChild.ownerDocument, doc);
+ assert_equals(newDiv.ownerDocument, document);
+ assert_equals(newDiv.firstChild, null);
+}, "False 'deep' argument.")
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/DocumentType-literal.html b/tests/wpt/web-platform-tests/dom/nodes/DocumentType-literal.html
new file mode 100644
index 00000000000..a755c397b0e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/DocumentType-literal.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html PUBLIC "STAFF" "staffNS.dtd">
+<title>DocumentType literals</title>
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-documenttype-name">
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-documenttype-publicid">
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-documenttype-systemid">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ var doctype = document.firstChild;
+ assert_true(doctype instanceof DocumentType)
+ assert_equals(doctype.name, "html")
+ assert_equals(doctype.publicId, 'STAFF')
+ assert_equals(doctype.systemId, 'staffNS.dtd')
+})
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/DocumentType-literal.xhtml b/tests/wpt/web-platform-tests/dom/nodes/DocumentType-literal.xhtml
new file mode 100644
index 00000000000..2b6965c14be
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/DocumentType-literal.xhtml
@@ -0,0 +1,23 @@
+<!DOCTYPE html PUBLIC "STAFF" "staffNS.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>DocumentType literals</title>
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-documenttype-name"/>
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-documenttype-publicid"/>
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-documenttype-systemid"/>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id="log"/>
+<script>
+test(function() {
+ var doctype = document.firstChild;
+ assert_true(doctype instanceof DocumentType)
+ assert_equals(doctype.name, "html")
+ assert_equals(doctype.publicId, 'STAFF')
+ assert_equals(doctype.systemId, 'staffNS.dtd')
+})
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/DocumentType-remove.html b/tests/wpt/web-platform-tests/dom/nodes/DocumentType-remove.html
new file mode 100644
index 00000000000..9e18d3511ad
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/DocumentType-remove.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>DocumentType.remove</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-childnode-remove">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="ChildNode-remove.js"></script>
+<div id=log></div>
+<script>
+var node, parentNode;
+setup(function() {
+ node = document.implementation.createDocumentType("html", "", "");
+ parentNode = document.implementation.createDocument(null, "", null);
+});
+testRemove(node, parentNode, "doctype");
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Element-childElement-null.html b/tests/wpt/web-platform-tests/dom/nodes/Element-childElement-null.html
new file mode 100644
index 00000000000..1863a41da57
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Element-childElement-null.html
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>Null test</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<h1>Test of firstElementChild and lastChildElement returning null</h1>
+<div id="log"></div>
+<p id="parentEl" style="font-weight:bold;">Test.</p>
+<script>
+test(function() {
+ var parentEl = document.getElementById("parentEl")
+ assert_equals(parentEl.firstElementChild, null)
+ assert_equals(parentEl.lastElementChild, null)
+})
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Element-childElement-null.svg b/tests/wpt/web-platform-tests/dom/nodes/Element-childElement-null.svg
new file mode 100644
index 00000000000..388482874b1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Element-childElement-null.svg
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:h="http://www.w3.org/1999/xhtml"
+ version="1.1"
+ width="100%" height="100%" viewBox="0 0 400 400">
+<title>Null test</title>
+<h:script src="/resources/testharness.js"/>
+<h:script src="/resources/testharnessreport.js"/>
+
+<text x="200" y="40" font-size="25" fill="black" text-anchor="middle">Test of firstElementChild and lastChildElement returning null</text>
+<text id="parentEl" x="200" y="70" font-size="20" fill="black" text-anchor="middle" font-weight="bold">Test</text>
+
+<h:script><![CDATA[
+test(function() {
+ var parentEl = document.getElementById("parentEl")
+ assert_equals(parentEl.firstElementChild, null)
+ assert_equals(parentEl.lastElementChild, null)
+})
+]]></h:script>
+</svg>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Element-childElement-null.xhtml b/tests/wpt/web-platform-tests/dom/nodes/Element-childElement-null.xhtml
new file mode 100644
index 00000000000..daedab6d971
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Element-childElement-null.xhtml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Null Test</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<h1>Test of firstElementChild and lastChildElement returning null</h1>
+<div id="log"></div>
+<p id="parentEl" style="font-weight:bold;">Test.</p>
+<script><![CDATA[
+test(function() {
+ var parentEl = document.getElementById("parentEl")
+ assert_equals(parentEl.firstElementChild, null)
+ assert_equals(parentEl.lastElementChild, null)
+})
+]]></script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Element-childElementCount-dynamic-add.html b/tests/wpt/web-platform-tests/dom/nodes/Element-childElementCount-dynamic-add.html
new file mode 100644
index 00000000000..3e7490b21d6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Element-childElementCount-dynamic-add.html
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>Dynamic Adding of Elements</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<h1>Test of Dynamic Adding of Elements</h1>
+<div id="log"></div>
+<p id="parentEl">The result of this test is
+<span id="first_element_child" style="font-weight:bold;">logged above.</span></p>
+<script>
+test(function() {
+ var parentEl = document.getElementById("parentEl");
+ var newChild = document.createElement("span");
+ parentEl.appendChild(newChild);
+ assert_equals(parentEl.childElementCount, 2)
+})
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Element-childElementCount-dynamic-add.svg b/tests/wpt/web-platform-tests/dom/nodes/Element-childElementCount-dynamic-add.svg
new file mode 100644
index 00000000000..d149f1ea3f1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Element-childElementCount-dynamic-add.svg
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:h="http://www.w3.org/1999/xhtml"
+ version="1.1"
+ width="100%" height="100%" viewBox="0 0 400 400">
+<title>Dynamic Adding of Elements</title>
+<h:script src="/resources/testharness.js"/>
+<h:script src="/resources/testharnessreport.js"/>
+
+<text x="200" y="40" font-size="25" fill="black" text-anchor="middle">Test of Dynamic Adding of Elements</text>
+<text id="parentEl" x="200" y="70" font-size="20" fill="black" text-anchor="middle">The result of this test is
+<tspan id="first_element_child" font-weight="bold">unknown.</tspan></text>
+
+<h:script><![CDATA[
+test(function() {
+ var parentEl = document.getElementById("parentEl");
+ var newChild = document.createElementNS("http://www.w3.org/2000/svg", "tspan");
+ parentEl.appendChild(newChild);
+ assert_equals(parentEl.childElementCount, 2)
+})
+]]></h:script>
+</svg>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Element-childElementCount-dynamic-add.xhtml b/tests/wpt/web-platform-tests/dom/nodes/Element-childElementCount-dynamic-add.xhtml
new file mode 100644
index 00000000000..c97ed1965b5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Element-childElementCount-dynamic-add.xhtml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Dynamic Adding of Elements</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<h1>Test of Dynamic Adding of Elements</h1>
+<div id="log"></div>
+<p id="parentEl">The result of this test is
+<span id="first_element_child" style="font-weight:bold;">logged above.</span></p>
+<script><![CDATA[
+test(function() {
+ var parentEl = document.getElementById("parentEl");
+ var newChild = document.createElement("span");
+ parentEl.appendChild(newChild);
+ assert_equals(parentEl.childElementCount, 2)
+})
+]]></script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Element-childElementCount-dynamic-remove.html b/tests/wpt/web-platform-tests/dom/nodes/Element-childElementCount-dynamic-remove.html
new file mode 100644
index 00000000000..3f7e7c7eadc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Element-childElementCount-dynamic-remove.html
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>Dynamic Removal of Elements</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<h1>Test of Dynamic Removal of Elements</h1>
+<div id="log"></div>
+<p id="parentEl">The result of this test is
+<span id="first_element_child" style="font-weight:bold;">unknown.</span><span id="last_element_child"> </span></p>
+<script>
+test(function() {
+ var parentEl = document.getElementById("parentEl");
+ var lec = parentEl.lastElementChild;
+ parentEl.removeChild(lec);
+ assert_equals(parentEl.childElementCount, 1)
+})
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Element-childElementCount-dynamic-remove.svg b/tests/wpt/web-platform-tests/dom/nodes/Element-childElementCount-dynamic-remove.svg
new file mode 100644
index 00000000000..bf99de65aa9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Element-childElementCount-dynamic-remove.svg
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:h="http://www.w3.org/1999/xhtml"
+ version="1.1"
+ width="100%" height="100%" viewBox="0 0 400 400">
+<title>Dynamic Removal of Elements</title>
+<h:script src="/resources/testharness.js"/>
+<h:script src="/resources/testharnessreport.js"/>
+
+<text x="200" y="40" font-size="25" fill="black" text-anchor="middle">Test of Dynamic Removal of Elements</text>
+<text id="parentEl" x="200" y="70" font-size="20" fill="black" text-anchor="middle">The result of this test is
+<tspan id="first_element_child" font-weight="bold">unknown.</tspan><tspan id="last_element_child"> </tspan></text>
+
+<h:script><![CDATA[
+test(function() {
+ var parentEl = document.getElementById("parentEl");
+ var lec = parentEl.lastElementChild;
+ parentEl.removeChild(lec);
+ assert_equals(parentEl.childElementCount, 1)
+})
+]]></h:script>
+</svg>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Element-childElementCount-dynamic-remove.xhtml b/tests/wpt/web-platform-tests/dom/nodes/Element-childElementCount-dynamic-remove.xhtml
new file mode 100644
index 00000000000..f0009b0a778
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Element-childElementCount-dynamic-remove.xhtml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Dynamic Removal of Elements</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<h1>Test of Removal Adding of Elements</h1>
+<div id="log"></div>
+<p id="parentEl">The result of this test is
+<span id="first_element_child" style="font-weight:bold;">logged above.</span><span id="last_element_child"> </span></p>
+<script><![CDATA[
+test(function() {
+ var parentEl = document.getElementById("parentEl");
+ var lec = parentEl.lastElementChild;
+ parentEl.removeChild(lec);
+ assert_equals(parentEl.childElementCount, 1)
+})
+]]></script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Element-childElementCount-nochild.html b/tests/wpt/web-platform-tests/dom/nodes/Element-childElementCount-nochild.html
new file mode 100644
index 00000000000..fb52fb205c8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Element-childElementCount-nochild.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>childElementCount without Child Element Nodes</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<h1>Test of childElementCount with No Child Element Nodes</h1>
+<div id="log"></div>
+<p id="parentEl" style="font-weight:bold;">Test.</p>
+<script>
+test(function() {
+ var parentEl = document.getElementById("parentEl")
+ assert_equals(parentEl.childElementCount, 0)
+})
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Element-childElementCount-nochild.svg b/tests/wpt/web-platform-tests/dom/nodes/Element-childElementCount-nochild.svg
new file mode 100644
index 00000000000..8ba57436070
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Element-childElementCount-nochild.svg
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:h="http://www.w3.org/1999/xhtml"
+ version="1.1"
+ width="100%" height="100%" viewBox="0 0 400 400">
+<title>childElementCount</title>
+<h:script src="/resources/testharness.js"/>
+<h:script src="/resources/testharnessreport.js"/>
+
+<text x="200" y="40" font-size="25" fill="black" text-anchor="middle">Test of childElementCount with No Child Element Nodes</text>
+<text id="parentEl" x="200" y="70" font-size="20" fill="black" text-anchor="middle" font-weight="bold">Test</text>
+
+<h:script><![CDATA[
+test(function() {
+ var parentEl = document.getElementById("parentEl")
+ assert_equals(parentEl.childElementCount, 0)
+})
+]]></h:script>
+</svg>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Element-childElementCount-nochild.xhtml b/tests/wpt/web-platform-tests/dom/nodes/Element-childElementCount-nochild.xhtml
new file mode 100644
index 00000000000..f567a20c234
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Element-childElementCount-nochild.xhtml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>childElementCount without Child Element Nodes</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<h1>Test of childElementCount with No Child Element Nodes</h1>
+<div id="log"></div>
+<p id="parentEl" style="font-weight:bold;">Test.</p>
+<script><![CDATA[
+test(function() {
+ var parentEl = document.getElementById("parentEl")
+ assert_equals(parentEl.childElementCount, 0)
+})
+]]></script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Element-childElementCount.html b/tests/wpt/web-platform-tests/dom/nodes/Element-childElementCount.html
new file mode 100644
index 00000000000..8cfe567f914
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Element-childElementCount.html
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>childElementCount</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<h1>Test of childElementCount</h1>
+<div id="log"></div>
+<p id="parentEl">The result of <span id="first_element_child"><span>this</span> <span>test</span></span> is
+<span id="middle_element_child" style="font-weight:bold;">given above.</span>
+
+
+
+<span id="last_element_child" style="display:none;">fnord</span> </p>
+<script>
+test(function() {
+ var parentEl = document.getElementById("parentEl")
+ assert_true("childElementCount" in parentEl)
+ assert_equals(parentEl.childElementCount, 3)
+})
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Element-childElementCount.svg b/tests/wpt/web-platform-tests/dom/nodes/Element-childElementCount.svg
new file mode 100644
index 00000000000..ff93eff625a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Element-childElementCount.svg
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:h="http://www.w3.org/1999/xhtml"
+ version="1.1"
+ width="100%" height="100%" viewBox="0 0 400 400">
+<title>childElementCount</title>
+<h:script src="/resources/testharness.js"/>
+<h:script src="/resources/testharnessreport.js"/>
+
+<text x="200" y="40" font-size="25" fill="black" text-anchor="middle">Test of childElementCount</text>
+<text id="parentEl" x="200" y="70" font-size="20" fill="black" text-anchor="middle">The result of <tspan id="first_element_child"><tspan>this</tspan> <tspan>test</tspan></tspan> is
+<tspan id="middle_element_child" font-weight="bold">unknown.</tspan>
+
+
+
+<tspan id="last_element_child" style="display:none;">fnord</tspan> </text>
+
+<h:script><![CDATA[
+test(function() {
+ var parentEl = document.getElementById("parentEl")
+ assert_true("childElementCount" in parentEl)
+ assert_equals(parentEl.childElementCount, 3)
+})
+]]></h:script>
+</svg>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Element-childElementCount.xhtml b/tests/wpt/web-platform-tests/dom/nodes/Element-childElementCount.xhtml
new file mode 100644
index 00000000000..6b719ff7a83
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Element-childElementCount.xhtml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>childElementCount</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<h1>Test of childElementCount</h1>
+<div id="log"></div>
+<p id="parentEl">The result of <span id="first_element_child"><span>this</span> <span>test</span></span> is
+<span id="middle_element_child" style="font-weight:bold;">unknown.</span>
+
+
+
+<span id="last_element_child" style="display:none;">fnord</span> </p>
+<script><![CDATA[
+test(function() {
+ var parentEl = document.getElementById("parentEl")
+ assert_true("childElementCount" in parentEl)
+ assert_equals(parentEl.childElementCount, 3)
+})
+]]></script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Element-children.html b/tests/wpt/web-platform-tests/dom/nodes/Element-children.html
new file mode 100644
index 00000000000..b3ce08ceefe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Element-children.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>HTMLCollection edge cases</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<div id="test"><img><img id=foo><img id=foo></div>
+<script>
+test(function() {
+ var container = document.getElementById("test");
+ var result = container.children.item("foo");
+ assert_true(result instanceof Element, "Expected an Element.");
+ assert_false(result.hasAttribute("id"), "Expected the IDless Element.")
+})
+test(function() {
+ var container = document.getElementById("test");
+ var list = container.children;
+ var result = [];
+ for (var p in list) {
+ if (list.hasOwnProperty(p)) {
+ result.push(p);
+ }
+ }
+ assert_array_equals(result, ['0', '1', '2']);
+ result = Object.getOwnPropertyNames(list);
+ assert_array_equals(result, ['0', '1', '2', 'foo']);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Element-classlist.html b/tests/wpt/web-platform-tests/dom/nodes/Element-classlist.html
new file mode 100644
index 00000000000..e8ef26fcdb5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Element-classlist.html
@@ -0,0 +1,309 @@
+<!doctype html>
+<html>
+ <head class="test test">
+ <title class=" ">Element.classList in case-sensitive documents</title>
+ <link rel="help" href="https://dom.spec.whatwg.org/#concept-class">
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <style type="text/css">
+.foo { font-style: italic; }
+ </style>
+ <script type="text/javascript">
+var elem = document.getElementsByTagName('title')[0], secondelem = document.getElementsByTagName('head')[0];
+test(function () {
+ assert_equals( typeof elem.classList, 'object', 'critical test; ignore any results after this' );
+}, 'Element.classList must exist as an object');
+test(function () {
+ assert_equals( typeof document.documentElement.classList, 'object' );
+}, 'Element.classList must exist as an object even if the element has no class attribute');
+test(function () {
+ assert_true( !!window.DOMTokenList );
+}, 'DOMTokenList should be exposed for prototyping');
+test(function () {
+ DOMTokenList.prototype.customProperty = true;
+ assert_true( elem.classList.customProperty );
+}, 'prototyping DOMTokenList should work');
+test(function () {
+ assert_true( elem.classList instanceof window.DOMTokenList );
+ assert_equals( elem.classList.constructor, window.DOMTokenList );
+}, 'Element.classList must implement DOMTokenList');
+test(function () {
+ assert_not_equals( getComputedStyle(elem,null).fontStyle, 'italic', 'critical test; required by the testsuite' );
+}, 'CSS .foo selectors must not match elements without any class');
+test(function () {
+ assert_equals( secondelem.classList.length, 1, 'duplicates in initial string should be removed per https://dom.spec.whatwg.org/#concept-class' );
+ assert_equals( secondelem.classList.item(0), 'test' );
+ assert_true( secondelem.classList.contains('test') );
+}, 'classList must be correct for an element that has classes');
+test(function () {
+ assert_equals( elem.classList.length, 0 );
+}, 'classList.length must be 0 for an element that has no classes');
+test(function () {
+ assert_false( elem.classList.contains('foo') );
+}, 'classList must not contain an undefined class');
+test(function () {
+ assert_equals( elem.classList.item(0), null );
+}, 'classList.item() must return null for out-of-range index');
+test(function () {
+ assert_equals( elem.classList.item(-1), null );
+}, 'classList.item() must return null for negative index');
+test(function () {
+ /* the normative part of the spec states that:
+ "unless tokens is empty, in which case there are no supported property indices"
+ ...
+ "The term[...] supported property indices [is] used as defined in the WebIDL specification."
+ WebIDL creates actual OwnProperties and then [] just acts as a normal property lookup */
+ assert_equals( elem.classList[0], undefined );
+}, 'classList[index] must be undefined for out-of-range index');
+test(function () {
+ assert_equals( elem.classList[-1], undefined );
+}, 'classList[index] must be undefined for negative index');
+test(function () {
+ assert_equals( elem.className, ' ' );
+}, 'className should contain initial markup whitespace');
+test(function () {
+ assert_equals( elem.classList + '', '', 'implicit' );
+ assert_equals( elem.classList.toString(), '', 'explicit' );
+}, 'empty classList should return the empty string since the ordered set parser skip the whitespaces');
+test(function () {
+ assert_throws( 'SYNTAX_ERR', function () { elem.classList.contains(''); } );
+}, '.contains(empty_string) must throw a SYNTAX_ERR');
+test(function () {
+ assert_throws( 'SYNTAX_ERR', function () { elem.classList.add(''); } );
+}, '.add(empty_string) must throw a SYNTAX_ERR');
+test(function () {
+ assert_throws( 'SYNTAX_ERR', function () { elem.classList.remove(''); } );
+}, '.remove(empty_string) must throw a SYNTAX_ERR');
+test(function () {
+ assert_throws( 'SYNTAX_ERR', function () { elem.classList.toggle(''); } );
+}, '.toggle(empty_string) must throw a SYNTAX_ERR');
+test(function () {
+ assert_throws( 'INVALID_CHARACTER_ERR', function () { elem.classList.contains('a b'); } );
+}, '.contains(string_with_spaces) must throw an INVALID_CHARACTER_ERR');
+test(function () {
+ assert_throws( 'INVALID_CHARACTER_ERR', function () { elem.classList.add('a b'); } );
+}, '.add(string_with_spaces) must throw an INVALID_CHARACTER_ERR');
+test(function () {
+ assert_throws( 'INVALID_CHARACTER_ERR', function () { elem.classList.remove('a b'); } );
+}, '.remove(string_with_spaces) must throw an INVALID_CHARACTER_ERR');
+test(function () {
+ assert_throws( 'INVALID_CHARACTER_ERR', function () { elem.classList.toggle('a b'); } );
+}, '.toggle(string_with_spaces) must throw an INVALID_CHARACTER_ERR');
+elem.className = 'foo';
+test(function () {
+ assert_equals( getComputedStyle(elem,null).fontStyle, 'italic', 'critical test; required by the testsuite' );
+}, 'computed style must update when setting .className');
+test(function () {
+ assert_true( elem.classList.contains('foo') );
+}, 'classList.contains must update when .className is changed');
+test(function () {
+ assert_false( elem.classList.contains('FOO') );
+}, 'classList.contains must be case sensitive');
+test(function () {
+ assert_false( elem.classList.contains('foo.') );
+ assert_false( elem.classList.contains('foo)') );
+ assert_false( elem.classList.contains('foo\'') );
+ assert_false( elem.classList.contains('foo$') );
+ assert_false( elem.classList.contains('foo~') );
+ assert_false( elem.classList.contains('foo?') );
+ assert_false( elem.classList.contains('foo\\') );
+}, 'classList.contains must not match when punctuation characters are added');
+test(function () {
+ elem.classList.add('FOO');
+ assert_equals( getComputedStyle(elem,null).fontStyle, 'italic' );
+}, 'classList.add must not cause the CSS selector to stop matching');
+test(function () {
+ assert_true( elem.classList.contains('foo') );
+}, 'classList.add must not remove existing classes');
+test(function () {
+ assert_true( elem.classList.contains('FOO') );
+}, 'classList.contains case sensitivity must match a case-specific string');
+test(function () {
+ assert_equals( elem.classList.length, 2 );
+}, 'classList.length must correctly reflect the number of tokens');
+test(function () {
+ assert_equals( elem.classList.item(0), 'foo' );
+}, 'classList.item(0) must return the first token');
+test(function () {
+ assert_equals( elem.classList.item(1), 'FOO' );
+}, 'classList.item must return case-sensitive strings and preserve token order');
+test(function () {
+ assert_equals( elem.classList[0], 'foo' );
+}, 'classList[0] must return the first token');
+test(function () {
+ assert_equals( elem.classList[1], 'FOO' );
+}, 'classList[index] must return case-sensitive strings and preserve token order');
+test(function () {
+ /* the normative part of the spec states that:
+ "The object's supported property indices are the numbers in the range zero to the number of tokens in tokens minus one"
+ ...
+ "The term[...] supported property indices [is] used as defined in the WebIDL specification."
+ WebIDL creates actual OwnProperties and then [] just acts as a normal property lookup */
+ assert_equals( elem.classList[2], undefined );
+}, 'classList[index] must still be undefined for out-of-range index when earlier indexes exist');
+test(function () {
+ assert_equals( elem.className, 'foo FOO' );
+}, 'className must update correctly when items have been added through classList');
+test(function () {
+ assert_equals( elem.classList + '', 'foo FOO', 'implicit' );
+ assert_equals( elem.classList.toString(), 'foo FOO', 'explicit' );
+}, 'classList must stringify correctly when items have been added');
+test(function () {
+ elem.classList.add('foo');
+ assert_equals( elem.classList.length, 2 );
+ assert_equals( elem.classList + '', 'foo FOO', 'implicit' );
+ assert_equals( elem.classList.toString(), 'foo FOO', 'explicit' );
+}, 'classList.add should not add a token if it already exists');
+test(function () {
+ elem.classList.remove('bar');
+ assert_equals( elem.classList.length, 2 );
+ assert_equals( elem.classList + '', 'foo FOO', 'implicit' );
+ assert_equals( elem.classList.toString(), 'foo FOO', 'explicit' );
+}, 'classList.remove removes arguments passed, if they are present.');
+test(function () {
+ elem.classList.remove('foo');
+ assert_equals( elem.classList.length, 1 );
+ assert_equals( elem.classList + '', 'FOO', 'implicit' );
+ assert_equals( elem.classList.toString(), 'FOO', 'explicit' );
+ assert_false( elem.classList.contains('foo') );
+ assert_true( elem.classList.contains('FOO') );
+}, 'classList.remove must remove existing tokens');
+test(function () {
+ assert_not_equals( getComputedStyle(elem,null).fontStyle, 'italic' );
+}, 'classList.remove must not break case-sensitive CSS selector matching');
+test(function () {
+ secondelem.classList.remove('test');
+ assert_equals( secondelem.classList.length, 0 );
+ assert_false( secondelem.classList.contains('test') );
+}, 'classList.remove must remove duplicated tokens');
+test(function () {
+ secondelem.className = 'token1 token2 token3';
+ secondelem.classList.remove('token2');
+ assert_equals( secondelem.classList + '', 'token1 token3', 'implicit' );
+ assert_equals( secondelem.classList.toString(), 'token1 token3', 'explicit' );
+}, 'classList.remove must collapse whitespace around removed tokens');
+test(function () {
+ secondelem.className = ' token1 token2 ';
+ secondelem.classList.remove('token2');
+ assert_equals( secondelem.classList + '', 'token1', 'implicit' );
+ assert_equals( secondelem.classList.toString(), 'token1', 'explicit' );
+}, 'classList.remove must collapse whitespaces around each token');
+test(function () {
+ secondelem.className = ' token1 token2 token1 ';
+ secondelem.classList.remove('token2');
+ assert_equals( secondelem.classList + '', 'token1', 'implicit' );
+ assert_equals( secondelem.classList.toString(), 'token1', 'explicit' );
+}, 'classList.remove must collapse whitespaces around each token and remove duplicates');
+test(function () {
+ secondelem.className = ' token1 token2 token1 ';
+ secondelem.classList.remove('token1');
+ assert_equals( secondelem.classList + '', 'token2', 'implicit' );
+ assert_equals( secondelem.classList.toString(), 'token2', 'explicit' );
+}, 'classList.remove must collapse whitespace when removing duplicate tokens');
+test(function () {
+ secondelem.className = ' token1 token1 ';
+ secondelem.classList.add('token1');
+ assert_equals( secondelem.classList + '', 'token1', 'implicit' );
+ assert_equals( secondelem.classList.toString(), 'token1', 'explicit' );
+}, 'classList.add must collapse whitespaces and remove duplicates when adding a token that already exists');
+test(function () {
+ assert_true(elem.classList.toggle('foo'));
+ assert_equals( elem.classList.length, 2 );
+ assert_true( elem.classList.contains('foo') );
+ assert_true( elem.classList.contains('FOO') );
+}, 'classList.toggle must toggle tokens case-sensitively when adding');
+test(function () {
+ assert_equals( getComputedStyle(elem,null).fontStyle, 'italic' );
+}, 'classList.toggle must not break case-sensitive CSS selector matching');
+test(function () {
+ assert_false(elem.classList.toggle('foo'));
+}, 'classList.toggle must be able to remove tokens');
+test(function () {
+ //will return true if the last test incorrectly removed both
+ assert_false(elem.classList.toggle('FOO'));
+ assert_false( elem.classList.contains('foo') );
+ assert_false( elem.classList.contains('FOO') );
+}, 'classList.toggle must be case-sensitive when removing tokens');
+test(function () {
+ assert_not_equals( getComputedStyle(elem,null).fontStyle, 'italic' );
+}, 'CSS class selectors must stop matching when all classes have been removed');
+test(function () {
+ assert_equals( elem.className, '' );
+}, 'className must be empty when all classes have been removed');
+test(function () {
+ assert_equals( elem.classList + '', '', 'implicit' );
+ assert_equals( elem.classList.toString(), '', 'explicit' );
+}, 'classList must stringify to an empty string when all classes have been removed');
+test(function () {
+ assert_equals( elem.classList.item(0), null );
+}, 'classList.item(0) must return null when all classes have been removed');
+test(function () {
+ /* the normative part of the spec states that:
+ "unless the length is zero, in which case there are no supported property indices"
+ ...
+ "The term[...] supported property indices [is] used as defined in the WebIDL specification."
+ WebIDL creates actual OwnProperties and then [] just acts as a normal property lookup */
+ assert_equals( elem.classList[0], undefined );
+}, 'classList[0] must be undefined when all classes have been removed');
+// The ordered set parser must skip ASCII whitespace (U+0009, U+000A, U+000C, U+000D, and U+0020.)
+test(function () {
+ var foo = document.createElement('div');
+ foo.className = 'a ';
+ foo.classList.add('b');
+ assert_equals(foo.className,'a b');
+}, 'classList.add should treat " " as a space');
+test(function () {
+ var foo = document.createElement('div');
+ foo.className = 'a\t';
+ foo.classList.add('b');
+ assert_equals(foo.className,'a b');
+}, 'classList.add should treat \\t as a space');
+test(function () {
+ var foo = document.createElement('div');
+ foo.className = 'a\r';
+ foo.classList.add('b');
+ assert_equals(foo.className,'a b');
+}, 'classList.add should treat \\r as a space');
+test(function () {
+ var foo = document.createElement('div');
+ foo.className = 'a\n';
+ foo.classList.add('b');
+ assert_equals(foo.className,'a b');
+}, 'classList.add should treat \\n as a space');
+test(function () {
+ var foo = document.createElement('div');
+ foo.className = 'a\f';
+ foo.classList.add('b');
+ assert_equals(foo.className,'a b');
+}, 'classList.add should treat \\f as a space');
+test(function () {
+ //WebIDL and ECMAScript 5 - a readonly property has a getter but not a setter
+ //ES5 makes [[Put]] fail but not throw
+ var failed = false;
+ secondelem.className = 'token1';
+ try {
+ secondelem.classList.length = 0;
+ } catch(e) {
+ failed = e;
+ }
+ assert_equals(secondelem.classList.length,1);
+ assert_false(failed,'an error was thrown');
+}, 'classList.length must be read-only');
+test(function () {
+ var failed = false, realList = secondelem.classList;
+ try {
+ secondelem.classList = '';
+ } catch(e) {
+ failed = e;
+ }
+ assert_equals(secondelem.classList,realList);
+ assert_false(failed,'an error was thrown');
+}, 'classList must be read-only');
+ </script>
+ </head>
+ <body>
+
+ <div id="log"></div>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Element-closest.html b/tests/wpt/web-platform-tests/dom/nodes/Element-closest.html
new file mode 100644
index 00000000000..386e3bd251b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Element-closest.html
@@ -0,0 +1,73 @@
+<!DOCTYPE HTML>
+<meta charset=utf8>
+<title>Test for Element.closest</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body id="body">
+ <div id="test8" class="div3" style="display:none">
+ <div id="test7" class="div2">
+ <div id="test6" class="div1">
+ <form id="test10" class="form2"></form>
+ <form id="test5" class="form1" name="form-a">
+ <input id="test1" class="input1" required>
+ <fieldset class="fieldset2" id="test2">
+ <select id="test3" class="select1" required>
+ <option default id="test4" value="">Test4</option>
+ <option selected id="test11">Test11</option>
+ <option id="test12">Test12</option>
+ <option id="test13">Test13</option>
+ </select>
+ <input id="test9" type="text" required>
+ </fieldset>
+ </form>
+ </div>
+ </div>
+ </div>
+ <div id=log></div>
+<script>
+ do_test("select" , "test12", "test3");
+ do_test("fieldset" , "test13", "test2");
+ do_test("div" , "test13", "test6");
+ do_test("body" , "test3" , "body");
+
+ do_test("[default]" , "test4" , "test4");
+ do_test("[selected]" , "test4" , "");
+ do_test("[selected]" , "test11", "test11");
+ do_test('[name="form-a"]' , "test12", "test5");
+ do_test('form[name="form-a"]' , "test13", "test5");
+ do_test("input[required]" , "test9" , "test9");
+ do_test("select[required]" , "test9" , "");
+
+ do_test("div:not(.div1)" , "test13", "test7");
+ do_test("div.div3" , "test6" , "test8");
+ do_test("div#test7" , "test1" , "test7");
+
+ do_test(".div3 > .div2" , "test12", "test7");
+ do_test(".div3 > .div1" , "test12", "");
+ do_test("form > input[required]" , "test9" , "");
+ do_test("fieldset > select[required]", "test12", "test3");
+
+ do_test("input + fieldset" , "test6" , "");
+ do_test("form + form" , "test3" , "test5");
+ do_test("form + form" , "test5" , "test5");
+
+ do_test(":empty" , "test10", "test10");
+ do_test(":last-child" , "test11", "test2");
+ do_test(":first-child" , "test12", "test3");
+ do_test(":invalid" , "test11", "test2");
+
+ do_test(":scope" , "test4", "test4");
+ do_test("select > :scope" , "test4", "test4");
+ do_test("div > :scope" , "test4", "");
+ do_test(":has(> :scope)" , "test4", "test3");
+function do_test(aSelector, aElementId, aTargetId) {
+ test(function() {
+ var el = document.getElementById(aElementId).closest(aSelector);
+ if (el === null) {
+ assert_equals("", aTargetId, aSelector);
+ } else {
+ assert_equals(el.id, aTargetId, aSelector);
+ }
+ }, "Element.closest with context node '" + aElementId + "' and selector '" + aSelector + "'");
+}
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Element-firstElementChild-entity.svg b/tests/wpt/web-platform-tests/dom/nodes/Element-firstElementChild-entity.svg
new file mode 100644
index 00000000000..3a20ea79ab0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Element-firstElementChild-entity.svg
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"
+[
+<!ENTITY tree "<tspan id='first_element_child' font-weight='bold'>unknown.</tspan>">
+]>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:h="http://www.w3.org/1999/xhtml"
+ version="1.1"
+ width="100%" height="100%" viewBox="0 0 400 400">
+<title>Entity References</title>
+<h:script src="/resources/testharness.js"/>
+<h:script src="/resources/testharnessreport.js"/>
+
+<text x="200" y="40" font-size="25" fill="black" text-anchor="middle">Test of Entity References</text>
+<text id="parentEl" x="200" y="70" font-size="20" fill="black" text-anchor="middle">The result of this test is &tree;</text>
+
+<h:script><![CDATA[
+test(function() {
+ var parentEl = document.getElementById("parentEl")
+ var fec = parentEl.firstElementChild;
+ assert_true(!!fec)
+ assert_equals(fec.nodeType, 1)
+ assert_equals(fec.getAttribute("id"), "first_element_child")
+})
+]]></h:script>
+</svg>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Element-firstElementChild-entity.xhtml b/tests/wpt/web-platform-tests/dom/nodes/Element-firstElementChild-entity.xhtml
new file mode 100644
index 00000000000..f28005e9c89
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Element-firstElementChild-entity.xhtml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
+[
+<!ENTITY tree "<span id='first_element_child' style='font-weight:bold;'>unknown.</span>">
+]>
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<title>Entity References</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<h1>Test of Entity References</h1>
+<div id="log"></div>
+<p id="parentEl">The result of this test is &tree;</p>
+<script><![CDATA[
+test(function() {
+ var parentEl = document.getElementById("parentEl")
+ var fec = parentEl.firstElementChild;
+ assert_true(!!fec)
+ assert_equals(fec.nodeType, 1)
+ assert_equals(fec.getAttribute("id"), "first_element_child")
+})
+]]></script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Element-firstElementChild-namespace.html b/tests/wpt/web-platform-tests/dom/nodes/Element-firstElementChild-namespace.html
new file mode 100644
index 00000000000..629deab3ae0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Element-firstElementChild-namespace.html
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>firstElementChild with namespaces</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<h1>Test of firstElementChild with namespaces</h1>
+<div id="log"></div>
+<p id="parentEl">The result of this test is a unknown.</p>
+<script>
+test(function() {
+ var parentEl = document.getElementById("parentEl")
+ var el = document.createElementNS("http://ns.example.org/pickle", "pickle:dill")
+ el.setAttribute("id", "first_element_child")
+ parentEl.appendChild(el)
+ var fec = parentEl.firstElementChild
+ assert_true(!!fec)
+ assert_equals(fec.nodeType, 1)
+ assert_equals(fec.getAttribute("id"), "first_element_child")
+ assert_equals(fec.localName, "dill")
+})
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Element-firstElementChild-namespace.svg b/tests/wpt/web-platform-tests/dom/nodes/Element-firstElementChild-namespace.svg
new file mode 100644
index 00000000000..d42c08777c8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Element-firstElementChild-namespace.svg
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:h="http://www.w3.org/1999/xhtml"
+ xmlns:pickle="http://ns.example.org/pickle"
+ version="1.1"
+ width="100%" height="100%" viewBox="0 0 400 400">
+<title>firstElementChild with namespaces</title>
+<h:script src="/resources/testharness.js"/>
+<h:script src="/resources/testharnessreport.js"/>
+
+<text x="200" y="40" font-size="25" fill="black" text-anchor="middle">Test of firstElementChild with namespaces</text>
+<g id="parentEl">
+ <pickle:dill id="first_element_child"/>
+</g>
+
+<h:script><![CDATA[
+test(function() {
+ var parentEl = document.getElementById("parentEl");
+ var fec = parentEl.firstElementChild;
+ assert_true(!!fec)
+ assert_equals(fec.nodeType, 1)
+ assert_equals(fec.getAttribute("id"), "first_element_child")
+ assert_equals(fec.localName, "dill")
+})
+]]></h:script>
+</svg>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Element-firstElementChild-namespace.xhtml b/tests/wpt/web-platform-tests/dom/nodes/Element-firstElementChild-namespace.xhtml
new file mode 100644
index 00000000000..29441d2786a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Element-firstElementChild-namespace.xhtml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:pickle="http://ns.example.org/pickle">
+<head>
+<title>firstElementChild with namespaces</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<h1>Test of firstElementChild with namespaces</h1>
+<div id="parentEl">
+ <pickle:dill id="first_element_child"/>
+</div>
+<div id="log"></div>
+<p id="parentEl">The result of this test is
+<span id="first_element_child" style="font-weight:bold;">logged above.</span></p>
+<script><![CDATA[
+test(function() {
+ var parentEl = document.getElementById("parentEl");
+ var fec = parentEl.firstElementChild;
+ assert_true(!!fec)
+ assert_equals(fec.nodeType, 1)
+ assert_equals(fec.getAttribute("id"), "first_element_child")
+ assert_equals(fec.localName, "dill")
+})
+]]></script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Element-firstElementChild.html b/tests/wpt/web-platform-tests/dom/nodes/Element-firstElementChild.html
new file mode 100644
index 00000000000..12a0c5946e5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Element-firstElementChild.html
@@ -0,0 +1,18 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>firstElementChild</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<h1>Test of firstElementChild</h1>
+<div id="log"></div>
+<p id="parentEl">The result of this test is
+<span id="first_element_child" style="font-weight:bold;">logged above.</span></p>
+<script>
+test(function() {
+ var parentEl = document.getElementById("parentEl");
+ var fec = parentEl.firstElementChild;
+ assert_true(!!fec)
+ assert_equals(fec.nodeType, 1)
+ assert_equals(fec.getAttribute("id"), "first_element_child")
+})
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Element-firstElementChild.svg b/tests/wpt/web-platform-tests/dom/nodes/Element-firstElementChild.svg
new file mode 100644
index 00000000000..359c5b82ca2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Element-firstElementChild.svg
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:h="http://www.w3.org/1999/xhtml"
+ version="1.1"
+ width="100%" height="100%" viewBox="0 0 400 400">
+<title>firstElementChild</title>
+<h:script src="/resources/testharness.js"/>
+<h:script src="/resources/testharnessreport.js"/>
+
+<text x="200" y="40" font-size="25" fill="black" text-anchor="middle">Test of firstElementChild</text>
+<text id="parentEl" x="200" y="70" font-size="20" fill="black" text-anchor="middle">The result of this test is
+<tspan id="first_element_child" font-weight="bold">unknown.</tspan></text>
+
+<h:script><![CDATA[
+test(function() {
+ var parentEl = document.getElementById("parentEl");
+ var fec = parentEl.firstElementChild;
+ assert_true(!!fec)
+ assert_equals(fec.nodeType, 1)
+ assert_equals(fec.getAttribute("id"), "first_element_child")
+})
+]]></h:script>
+</svg>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Element-firstElementChild.xhtml b/tests/wpt/web-platform-tests/dom/nodes/Element-firstElementChild.xhtml
new file mode 100644
index 00000000000..302052b0fc7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Element-firstElementChild.xhtml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>firstElementChild</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<h1>Test of firstElementChild</h1>
+<div id="log"></div>
+<p id="parentEl">The result of this test is
+<span id="first_element_child" style="font-weight:bold;">logged above.</span></p>
+<script><![CDATA[
+test(function() {
+ var parentEl = document.getElementById("parentEl");
+ var fec = parentEl.firstElementChild;
+ assert_true(!!fec)
+ assert_equals(fec.nodeType, 1)
+ assert_equals(fec.getAttribute("id"), "first_element_child")
+})
+]]></script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Element-getElementsByClassName.html b/tests/wpt/web-platform-tests/dom/nodes/Element-getElementsByClassName.html
new file mode 100644
index 00000000000..332c3060f1a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Element-getElementsByClassName.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<title>Element.getElementsByClassName</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ var a = document.createElement("a"), b = document.createElement("b")
+ b.className = "foo"
+ a.appendChild(b)
+ var list = a.getElementsByClassName("foo")
+ assert_array_equals(list, [b])
+ var secondList = a.getElementsByClassName("foo")
+ assert_true(list === secondList || list !== secondList, "Caching is allowed.")
+}, "getElementsByClassName should work on disconnected subtrees.")
+test(function() {
+ var list = document.getElementsByClassName("foo")
+ assert_false(list instanceof NodeList, "NodeList")
+ assert_true(list instanceof HTMLCollection, "HTMLCollection")
+}, "Interface should be correct.")
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Element-getElementsByTagName.html b/tests/wpt/web-platform-tests/dom/nodes/Element-getElementsByTagName.html
new file mode 100644
index 00000000000..87c4fe934a0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Element-getElementsByTagName.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Element.getElementsByTagName</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-element-getelementsbytagname">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="Document-Element-getElementsByTagName.js"></script>
+<div id="log"></div>
+<script>
+var element;
+setup(function() {
+ element = document.createElement("div");
+ element.appendChild(document.createTextNode("text"));
+ var p = element.appendChild(document.createElement("p"));
+ p.appendChild(document.createElement("a"))
+ .appendChild(document.createTextNode("link"));
+ p.appendChild(document.createElement("b"))
+ .appendChild(document.createTextNode("bold"));
+ p.appendChild(document.createElement("em"))
+ .appendChild(document.createElement("u"))
+ .appendChild(document.createTextNode("emphasized"));
+ element.appendChild(document.createComment("comment"));
+});
+
+test_getElementsByTagName(element, element);
+
+test(function() {
+ assert_array_equals(element.getElementsByTagName(element.localName), []);
+}, "Matching the context object");
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Element-getElementsByTagNameNS.html b/tests/wpt/web-platform-tests/dom/nodes/Element-getElementsByTagNameNS.html
new file mode 100644
index 00000000000..f826afc3915
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Element-getElementsByTagNameNS.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Element.getElementsByTagNameNS</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-element-getelementsbytagnamens">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="Document-Element-getElementsByTagNameNS.js"></script>
+<div id="log"></div>
+<script>
+var element;
+setup(function() {
+ element = document.createElement("div");
+ element.appendChild(document.createTextNode("text"));
+ var p = element.appendChild(document.createElement("p"));
+ p.appendChild(document.createElement("a"))
+ .appendChild(document.createTextNode("link"));
+ p.appendChild(document.createElement("b"))
+ .appendChild(document.createTextNode("bold"));
+ p.appendChild(document.createElement("em"))
+ .appendChild(document.createElement("u"))
+ .appendChild(document.createTextNode("emphasized"));
+ element.appendChild(document.createComment("comment"));
+});
+
+test_getElementsByTagNameNS(element, element);
+
+test(function() {
+ assert_array_equals(element.getElementsByTagNameNS("*", element.localName), []);
+}, "Matching the context object (wildcard namespace)");
+
+test(function() {
+ assert_array_equals(
+ element.getElementsByTagNameNS("http://www.w3.org/1999/xhtml",
+ element.localName),
+ []);
+}, "Matching the context object (specific namespace)");
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Element-lastElementChild.html b/tests/wpt/web-platform-tests/dom/nodes/Element-lastElementChild.html
new file mode 100644
index 00000000000..de7aebdf241
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Element-lastElementChild.html
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>lastElementChild</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<h1>Test of lastElementChild</h1>
+<div id="log"></div>
+<p id="parentEl">The result of <span id="first_element_child">this test</span> is <span id="last_element_child" style="font-weight:bold;">logged</span> above.</p>
+<script>
+test(function() {
+ var parentEl = document.getElementById("parentEl");
+ var lec = parentEl.lastElementChild;
+ assert_true(!!lec)
+ assert_equals(lec.nodeType, 1)
+ assert_equals(lec.getAttribute("id"), "last_element_child")
+})
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Element-lastElementChild.svg b/tests/wpt/web-platform-tests/dom/nodes/Element-lastElementChild.svg
new file mode 100644
index 00000000000..1cec4a13084
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Element-lastElementChild.svg
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:h="http://www.w3.org/1999/xhtml"
+ version="1.1"
+ width="100%" height="100%" viewBox="0 0 400 400">
+<title>lastElementChild</title>
+<h:script src="/resources/testharness.js"/>
+<h:script src="/resources/testharnessreport.js"/>
+
+<text x="200" y="40" font-size="25" fill="black" text-anchor="middle">Test of lastElementChild</text>
+<text id="parentEl" x="200" y="70" font-size="20" fill="black" text-anchor="middle">The result of <tspan id="first_element_child">this test</tspan> is <tspan id="last_element_child" font-weight="bold">not</tspan> known.</text>
+
+<h:script><![CDATA[
+test(function() {
+ var parentEl = document.getElementById("parentEl");
+ var lec = parentEl.lastElementChild;
+ assert_true(!!lec)
+ assert_equals(lec.nodeType, 1)
+ assert_equals(lec.getAttribute("id"), "last_element_child")
+})
+]]></h:script>
+</svg>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Element-lastElementChild.xhtml b/tests/wpt/web-platform-tests/dom/nodes/Element-lastElementChild.xhtml
new file mode 100644
index 00000000000..3150b92a42c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Element-lastElementChild.xhtml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>firstElementChild</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<h1>Test of firstElementChild</h1>
+<div id="log"></div>
+<p id="parentEl">The result of <span id="first_element_child">this test</span> is <span id="last_element_child" style="font-weight:bold;">logged</span> above.</p>
+<script><![CDATA[
+test(function() {
+ var parentEl = document.getElementById("parentEl");
+ var lec = parentEl.lastElementChild;
+ assert_true(!!lec)
+ assert_equals(lec.nodeType, 1)
+ assert_equals(lec.getAttribute("id"), "last_element_child")
+})
+]]></script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Element-matches.html b/tests/wpt/web-platform-tests/dom/nodes/Element-matches.html
new file mode 100644
index 00000000000..44e5112ee35
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Element-matches.html
@@ -0,0 +1,87 @@
+<!DOCTYPE html>
+<meta charset="UTF-8">
+<title>Selectors-API Level 2 Test Suite: HTML with Selectors Level 3</title>
+<!-- Selectors API Test Suite Version 3 -->
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/dom/nodes/selectors.js"></script>
+<script src="/dom/nodes/ParentNode-querySelector-All.js"></script>
+<script src="Element-matches.js"></script>
+<style>iframe { visibility: hidden; position: absolute; }</style>
+
+<div id="log">This test requires JavaScript.</div>
+
+<script>
+var docType = "html"; // Only run tests suitable for HTML
+
+var frame = document.createElement("iframe"),
+ doc;
+
+frame.onload = init;
+frame.src = "/dom/nodes/ParentNode-querySelector-All-content.html#target";
+document.body.appendChild(frame);
+
+function init() {
+ /*
+ * This test suite tests Selectors API methods in 4 different contexts:
+ * 1. Document node
+ * 2. In-document Element node
+ * 3. Detached Element node (an element with no parent, not in the document)
+ * 4. Document Fragment node
+ *
+ * For each context, the following tests are run:
+ *
+ * The interface check tests ensure that each type of node exposes the Selectors API methods.
+ *
+ * The matches() tests are run
+ * All the selectors tested for both the valid and invalid selector tests are found in selectors.js.
+ * See comments in that file for documentation of the format used.
+ *
+ * The level2-lib.js file contains all the common test functions for running each of the aforementioned tests
+ */
+
+ // Prepare the nodes for testing
+ doc = frame.contentDocument; // Document Node tests
+
+ var element = doc.getElementById("root"); // In-document Element Node tests
+
+ //Setup the namespace tests
+ setupSpecialElements(element);
+
+ var outOfScope = element.cloneNode(true); // Append this to the body before running the in-document
+ // Element tests, but after running the Document tests. This
+ // tests that no elements that are not descendants of element
+ // are selected.
+
+ traverse(outOfScope, function(elem) { // Annotate each element as being a clone; used for verifying
+ elem.setAttribute("data-clone", ""); // that none of these elements ever match.
+ });
+
+
+ var detached = element.cloneNode(true); // Detached Element Node tests
+
+ var fragment = doc.createDocumentFragment(); // Fragment Node tests
+ fragment.appendChild(element.cloneNode(true));
+
+ // Setup Tests
+ interfaceCheckMatches("Document", doc);
+ interfaceCheckMatches("Detached Element", detached);
+ interfaceCheckMatches("Fragment", fragment);
+ interfaceCheckMatches("In-document Element", element);
+
+ runSpecialMatchesTests("DIV Element", element);
+ runSpecialMatchesTests("NULL Element", document.createElement("null"));
+ runSpecialMatchesTests("UNDEFINED Element", document.createElement("undefined"));
+
+ runInvalidSelectorTestMatches("Document", doc, invalidSelectors);
+ runInvalidSelectorTestMatches("Detached Element", detached, invalidSelectors);
+ runInvalidSelectorTestMatches("Fragment", fragment, invalidSelectors);
+ runInvalidSelectorTestMatches("In-document Element", element, invalidSelectors);
+
+ runMatchesTest("In-document", doc, validSelectors, "html");
+ runMatchesTest("Detached", detached, validSelectors, "html");
+ runMatchesTest("Fragment", fragment, validSelectors, "html");
+
+ runMatchesTest("In-document", doc, scopedSelectors, "html");
+}
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Element-matches.js b/tests/wpt/web-platform-tests/dom/nodes/Element-matches.js
new file mode 100644
index 00000000000..1bc0f3d0887
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Element-matches.js
@@ -0,0 +1,127 @@
+/*
+ * Check that the matches() method exists on the given Node
+ */
+function interfaceCheckMatches(type, obj) {
+ if (obj.nodeType === obj.ELEMENT_NODE) {
+ test(function() {
+ assert_idl_attribute(obj, "matches", type + " supports matches");
+ }, type + " supports matches")
+ }
+}
+
+function runSpecialMatchesTests(type, element) {
+ test(function() { // 1
+ if (element.tagName.toLowerCase() === "null") {
+ assert_true(element.matches(null), "An element with the tag name '" + element.tagName.toLowerCase() + "' should match.");
+ } else {
+ assert_false(element.matches(null), "An element with the tag name '" + element.tagName.toLowerCase() + "' should not match.");
+ }
+ }, type + ".matches(null)")
+
+ test(function() { // 2
+ if (element.tagName.toLowerCase() === "undefined") {
+ assert_true(element.matches(undefined), "An element with the tag name '" + element.tagName.toLowerCase() + "' should match.");
+ } else {
+ assert_false(element.matches(undefined), "An element with the tag name '" + element.tagName.toLowerCase() + "' should not match.");
+ }
+ }, type + ".matches(undefined)")
+
+ test(function() { // 3
+ assert_throws(TypeError(), function() {
+ element.matches();
+ }, "This should throw a TypeError.")
+ }, type + ".matches no parameter")
+}
+
+/*
+ * Execute queries with the specified invalid selectors for matches()
+ * Only run these tests when errors are expected. Don't run for valid selector tests.
+ */
+function runInvalidSelectorTestMatches(type, root, selectors) {
+ if (root.nodeType === root.ELEMENT_NODE) {
+ for (var i = 0; i < selectors.length; i++) {
+ var s = selectors[i];
+ var n = s["name"];
+ var q = s["selector"];
+
+ test(function() {
+ assert_throws("SyntaxError", function() {
+ root.matches(q)
+ })
+ }, type + ".matches: " + n + ": " + q);
+ }
+ }
+}
+
+function runMatchesTest(type, root, selectors, docType) {
+ var nodeType = getNodeType(root);
+
+ for (var i = 0; i < selectors.length; i++) {
+ var s = selectors[i];
+ var n = s["name"];
+ var q = s["selector"];
+ var e = s["expect"];
+ var u = s["unexpected"];
+
+ var ctx = s["ctx"];
+ var ref = s["ref"];
+
+ if ((!s["exclude"] || (s["exclude"].indexOf(nodeType) === -1 && s["exclude"].indexOf(docType) === -1))
+ && (s["testType"] & TEST_MATCH) ) {
+
+ if (ctx && !ref) {
+ test(function() {
+ var j, element, refNode;
+ for (j = 0; j < e.length; j++) {
+ element = root.querySelector("#" + e[j]);
+ refNode = root.querySelector(ctx);
+ assert_true(element.matches(q, refNode), "The element #" + e[j] + " should match the selector.")
+ }
+
+ if (u) {
+ for (j = 0; j < u.length; j++) {
+ element = root.querySelector("#" + u[j]);
+ refNode = root.querySelector(ctx);
+ assert_false(element.matches(q, refNode), "The element #" + u[j] + " should not match the selector.")
+ }
+ }
+ }, type + " Element.matches: " + n + " (with refNode Element): " + q);
+ }
+
+ if (ref) {
+ test(function() {
+ var j, element, refNodes;
+ for (j = 0; j < e.length; j++) {
+ element = root.querySelector("#" + e[j]);
+ refNodes = root.querySelectorAll(ref);
+ assert_true(element.matches(q, refNodes), "The element #" + e[j] + " should match the selector.")
+ }
+
+ if (u) {
+ for (j = 0; j < u.length; j++) {
+ element = root.querySelector("#" + u[j]);
+ refNodes = root.querySelectorAll(ref);
+ assert_false(element.matches(q, refNodes), "The element #" + u[j] + " should not match the selector.")
+ }
+ }
+ }, type + " Element.matches: " + n + " (with refNodes NodeList): " + q);
+ }
+
+ if (!ctx && !ref) {
+ test(function() {
+ for (var j = 0; j < e.length; j++) {
+ var element = root.querySelector("#" + e[j]);
+ assert_true(element.matches(q), "The element #" + e[j] + " should match the selector.")
+ }
+
+ if (u) {
+ for (j = 0; j < u.length; j++) {
+ element = root.querySelector("#" + u[j]);
+ assert_false(element.matches(q), "The element #" + u[j] + " should not match the selector.")
+ }
+ }
+ }, type + " Element.matches: " + n + " (with no refNodes): " + q);
+ }
+ }
+ }
+}
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Element-nextElementSibling.html b/tests/wpt/web-platform-tests/dom/nodes/Element-nextElementSibling.html
new file mode 100644
index 00000000000..985c602f418
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Element-nextElementSibling.html
@@ -0,0 +1,18 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>nextElementSibling</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<h1>Test of nextElementSibling</h1>
+<div id="log"></div>
+<p id="parentEl">The result of <span id="first_element_child">this test</span> is <span id="last_element_child" style="font-weight:bold;">unknown.</span></p>
+<script>
+test(function() {
+ var parentEl = document.getElementById("parentEl");
+ var fec = document.getElementById("first_element_child");
+ var nes = fec.nextElementSibling;
+ assert_true(!!nes)
+ assert_equals(nes.nodeType, 1)
+ assert_equals(nes.getAttribute("id"), "last_element_child")
+})
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Element-nextElementSibling.svg b/tests/wpt/web-platform-tests/dom/nodes/Element-nextElementSibling.svg
new file mode 100644
index 00000000000..3e17cad20c4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Element-nextElementSibling.svg
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:h="http://www.w3.org/1999/xhtml"
+ version="1.1"
+ width="100%" height="100%" viewBox="0 0 400 400">
+<title>nextElementSibling</title>
+<h:script src="/resources/testharness.js"/>
+<h:script src="/resources/testharnessreport.js"/>
+
+<text x="200" y="40" font-size="25" fill="black" text-anchor="middle">Test of nextElementSibling</text>
+<text id="parentEl" x="200" y="70" font-size="20" fill="black" text-anchor="middle">The result of <tspan id="first_element_child">this test</tspan> is <tspan id="last_element_child" font-weight="bold">unknown.</tspan></text>
+
+<h:script><![CDATA[
+test(function() {
+ var parentEl = document.getElementById("parentEl");
+ var fec = document.getElementById("first_element_child");
+ var nes = fec.nextElementSibling;
+ assert_true(!!nes)
+ assert_equals(nes.nodeType, 1)
+ assert_equals(nes.getAttribute("id"), "last_element_child")
+})
+]]></h:script>
+</svg>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Element-nextElementSibling.xhtml b/tests/wpt/web-platform-tests/dom/nodes/Element-nextElementSibling.xhtml
new file mode 100644
index 00000000000..915209bda26
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Element-nextElementSibling.xhtml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>nextElementSibling</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<h1>Test of nextElementSibling</h1>
+<div id="log"></div>
+<p id="parentEl">The result of <span id="first_element_child">this test</span> is <span id="last_element_child" style="font-weight:bold;">unknown.</span></p>
+<script><![CDATA[
+test(function() {
+ var parentEl = document.getElementById("parentEl");
+ var fec = document.getElementById("first_element_child");
+ var nes = fec.nextElementSibling;
+ assert_true(!!nes)
+ assert_equals(nes.nodeType, 1)
+ assert_equals(nes.getAttribute("id"), "last_element_child")
+})
+]]></script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Element-previousElementSibling.html b/tests/wpt/web-platform-tests/dom/nodes/Element-previousElementSibling.html
new file mode 100644
index 00000000000..02c7b16df57
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Element-previousElementSibling.html
@@ -0,0 +1,23 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>previousElementSibling</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<h1>Test of previousElementSibling</h1>
+<div id="log"></div>
+<p id="parentEl">The result of <span id="first_element_child">this test</span> is
+<span id="middle_element_child" style="font-weight:bold;">unknown.</span>
+
+
+
+<span id="last_element_child" style="display:none;">fnord</span> </p>
+<script>
+test(function() {
+ var parentEl = document.getElementById("parentEl");
+ var lec = document.getElementById("last_element_child");
+ var pes = lec.previousElementSibling;
+ assert_true(!!pes)
+ assert_equals(pes.nodeType, 1)
+ assert_equals(pes.getAttribute("id"), "middle_element_child")
+})
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Element-previousElementSibling.svg b/tests/wpt/web-platform-tests/dom/nodes/Element-previousElementSibling.svg
new file mode 100644
index 00000000000..671d2c87f2e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Element-previousElementSibling.svg
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:h="http://www.w3.org/1999/xhtml"
+ version="1.1"
+ width="100%" height="100%" viewBox="0 0 400 400">
+<title>previousElementSibling</title>
+<h:script src="/resources/testharness.js"/>
+<h:script src="/resources/testharnessreport.js"/>
+
+<text x="200" y="40" font-size="25" fill="black" text-anchor="middle">Test of previousElementSibling</text>
+<text id="parentEl" x="200" y="70" font-size="20" fill="black" text-anchor="middle">The result of <tspan id="first_element_child">this test</tspan> is
+<tspan id="middle_element_child" font-weight="bold">unknown.</tspan>
+
+
+
+<tspan id="last_element_child" display="none">fnord</tspan> </text>
+
+<h:script><![CDATA[
+test(function() {
+ var parentEl = document.getElementById("parentEl");
+ var lec = document.getElementById("last_element_child");
+ var pes = lec.previousElementSibling;
+ assert_true(!!pes)
+ assert_equals(pes.nodeType, 1)
+ assert_equals(pes.getAttribute("id"), "middle_element_child")
+})
+]]></h:script>
+</svg>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Element-previousElementSibling.xhtml b/tests/wpt/web-platform-tests/dom/nodes/Element-previousElementSibling.xhtml
new file mode 100644
index 00000000000..7fbbc6d384e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Element-previousElementSibling.xhtml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>previousElementSibling</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<h1>Test of previousElementSibling</h1>
+<div id="log"></div>
+<p id="parentEl">The result of <span id="first_element_child">this test</span> is
+<span id="middle_element_child" style="font-weight:bold;">unknown.</span>
+
+
+
+<span id="last_element_child" style="display:none;">fnord</span> </p>
+<script><![CDATA[
+test(function() {
+ var parentEl = document.getElementById("parentEl");
+ var lec = document.getElementById("last_element_child");
+ var pes = lec.previousElementSibling;
+ assert_true(!!pes)
+ assert_equals(pes.nodeType, 1)
+ assert_equals(pes.getAttribute("id"), "middle_element_child")
+})
+]]></script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Element-remove.html b/tests/wpt/web-platform-tests/dom/nodes/Element-remove.html
new file mode 100644
index 00000000000..ab642d660b9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Element-remove.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Element.remove</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-childnode-remove">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="ChildNode-remove.js"></script>
+<div id=log></div>
+<script>
+var node, parentNode;
+setup(function() {
+ node = document.createElement("div");
+ parentNode = document.createElement("div");
+});
+testRemove(node, parentNode, "element");
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Element-removeAttributeNS.html b/tests/wpt/web-platform-tests/dom/nodes/Element-removeAttributeNS.html
new file mode 100644
index 00000000000..a2773e6f1e0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Element-removeAttributeNS.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<title>Element.removeAttributeNS</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="attributes.js"></script>
+<div id="log"></div>
+<script>
+var XML = "http://www.w3.org/XML/1998/namespace"
+
+test(function() {
+ var el = document.createElement("foo")
+ el.setAttributeNS(XML, "a:bb", "pass")
+ attr_is(el.attributes[0], "pass", "bb", XML, "a", "a:bb")
+ el.removeAttributeNS(XML, "a:bb")
+ assert_equals(el.attributes.length, 1)
+ attr_is(el.attributes[0], "pass", "bb", XML, "a", "a:bb")
+}, "removeAttributeNS should take a local name.")
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Element-siblingElement-null.html b/tests/wpt/web-platform-tests/dom/nodes/Element-siblingElement-null.html
new file mode 100644
index 00000000000..a7920b4fb89
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Element-siblingElement-null.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>Null test</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<h1>Test of previousElementSibling and nextElementSibling returning null</h1>
+<div id="log"></div>
+<p id="parentEl">The result of this test is <span id="first_element_child" style="font-weight:bold;">unknown.</span></p>
+<script>
+test(function() {
+ var fec = document.getElementById("first_element_child");
+ assert_equals(fec.previousElementSibling, null)
+ assert_equals(fec.nextElementSibling, null)
+})
+</script>
+
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Element-siblingElement-null.svg b/tests/wpt/web-platform-tests/dom/nodes/Element-siblingElement-null.svg
new file mode 100644
index 00000000000..48c981b8c8e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Element-siblingElement-null.svg
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:h="http://www.w3.org/1999/xhtml"
+ version="1.1"
+ width="100%" height="100%" viewBox="0 0 400 400">
+<title>Null test</title>
+<h:script src="/resources/testharness.js"/>
+<h:script src="/resources/testharnessreport.js"/>
+
+<text x="200" y="40" font-size="25" fill="black" text-anchor="middle">Test of previousElementSibling and nextElementSibling returning null</text>
+<text id="parentEl" x="200" y="70" font-size="20" fill="black" text-anchor="middle">The result of this test is <tspan id="first_element_child" font-weight="bold">unknown.</tspan></text>
+
+<h:script><![CDATA[
+test(function() {
+ var fec = document.getElementById("first_element_child");
+ assert_equals(fec.previousElementSibling, null)
+ assert_equals(fec.nextElementSibling, null)
+})
+]]></h:script>
+</svg>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Element-siblingElement-null.xhtml b/tests/wpt/web-platform-tests/dom/nodes/Element-siblingElement-null.xhtml
new file mode 100644
index 00000000000..fcf4d54ff9f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Element-siblingElement-null.xhtml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Null Test</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<h1>Test of previousElementSibling and nextElementSibling returning null</h1>
+<div id="log"></div>
+<p id="parentEl">The result of this test is <span id="first_element_child" style="font-weight:bold;">unknown.</span></p>
+<script><![CDATA[
+test(function() {
+ var fec = document.getElementById("first_element_child");
+ assert_equals(fec.previousElementSibling, null)
+ assert_equals(fec.nextElementSibling, null)
+})
+]]></script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Element-tagName.html b/tests/wpt/web-platform-tests/dom/nodes/Element-tagName.html
new file mode 100644
index 00000000000..035a23cc5e8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Element-tagName.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<title>Element.tagName</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ var HTMLNS = "http://www.w3.org/1999/xhtml"
+ assert_equals(document.createElementNS(HTMLNS, "I").tagName, "I")
+ assert_equals(document.createElementNS(HTMLNS, "i").tagName, "I")
+ assert_equals(document.createElementNS(HTMLNS, "x:b").tagName, "X:B")
+}, "tagName should upper-case for HTML elements in HTML documents.")
+
+test(function() {
+ var SVGNS = "http://www.w3.org/2000/svg"
+ assert_equals(document.createElementNS(SVGNS, "svg").tagName, "svg")
+ assert_equals(document.createElementNS(SVGNS, "SVG").tagName, "SVG")
+ assert_equals(document.createElementNS(SVGNS, "s:svg").tagName, "s:svg")
+ assert_equals(document.createElementNS(SVGNS, "s:SVG").tagName, "s:SVG")
+}, "tagName should not upper-case for SVG elements in HTML documents.")
+
+test(function() {
+ if ("DOMParser" in window) {
+ var xmlel = new DOMParser()
+ .parseFromString('<div xmlns="http://www.w3.org/1999/xhtml">Test</div>', 'text/xml')
+ .documentElement;
+ assert_equals(xmlel.tagName, "div", "tagName should be lowercase in XML")
+ var htmlel = document.importNode(xmlel, true)
+ assert_equals(htmlel.tagName, "DIV", "tagName should be uppercase in HTML")
+ }
+}, "tagName should be updated when changing ownerDocument")
+
+test(function() {
+ var xmlel = document.implementation
+ .createDocument("http://www.w3.org/1999/xhtml", "div", null)
+ .documentElement;
+ assert_equals(xmlel.tagName, "div", "tagName should be lowercase in XML")
+ var htmlel = document.importNode(xmlel, true)
+ assert_equals(htmlel.tagName, "DIV", "tagName should be uppercase in HTML")
+}, "tagName should be updated when changing ownerDocument (createDocument without prefix)")
+
+test(function() {
+ var xmlel = document.implementation
+ .createDocument("http://www.w3.org/1999/xhtml", "foo:div", null)
+ .documentElement;
+ assert_equals(xmlel.tagName, "foo:div", "tagName should be lowercase in XML")
+ var htmlel = document.importNode(xmlel, true)
+ assert_equals(htmlel.tagName, "FOO:DIV", "tagName should be uppercase in HTML")
+}, "tagName should be updated when changing ownerDocument (createDocument with prefix)")
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/MutationObserver-attributes.html b/tests/wpt/web-platform-tests/dom/nodes/MutationObserver-attributes.html
new file mode 100644
index 00000000000..6721b7eecd1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/MutationObserver-attributes.html
@@ -0,0 +1,406 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>MutationObservers: attributes mutations</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="mutationobservers.js"></script>
+<h1>MutationObservers: attributes mutations</h1>
+<div id="log"></div>
+
+<section style="display: none">
+<p id='n'></p>
+
+<p id='n00'></p>
+<p id='n01'></p>
+<p id='n02'></p>
+<p id='n03'></p>
+<input id="n04" type="text">
+
+<p id='n10'></p>
+<p id='n11'></p>
+<p id='n12' class='c01'></p>
+<p id='n13' class='c01 c02'></p>
+
+<p id='n20'></p>
+<p id='n21'></p>
+<p id='n22'></p>
+<p id='n23'></p>
+<p id='n24' class="c01 c02"></p>
+
+<p id='n30' class="c01 c02"></p>
+<p id='n31' class="c01 c02"></p>
+<p id='n32' class="c01 c02"></p>
+
+<p id='n40' class="c01 c02"></p>
+<p id='n41' class="c01 c02"></p>
+<p id='n42' class="c01 c02"></p>
+<p id='n43' class="c01 c02"></p>
+<p id='n44' class="c01 c02"></p>
+<p id='n45' class="c01 c02"></p>
+
+<p id='n50' class="c01 c02"></p>
+<p id='n51'></p>
+
+<p id='n60'></p>
+<p id='n61' class="c01"></p>
+<p id='n62'></p>
+
+<p id='n70' class="c01"></p>
+<p id='n71'></p>
+<input id="n72" type="text">
+
+<p id='n80'></p>
+<p id='n81'></p>
+
+<p id='n90'></p>
+<p id='n91'></p>
+<p id='n92'></p>
+
+<p id='n1000'></p>
+<p id='n1001' class='c01'></p>
+
+<p id='n2000'></p>
+<p id='n2001' class='c01'></p>
+
+<p id='n3000'></p>
+
+</section>
+
+<script>
+
+var n = document.getElementById('n');
+
+runMutationTest(n,
+ {"attributes":true},
+ [{type: "attributes", attributeName: "id"}],
+ function() { n.id = "n000";},
+ "attributes Element.id: update, no oldValue, mutation");
+
+var n00 = document.getElementById('n00');
+runMutationTest(n00,
+ {"attributes":true, "attributeOldValue": true},
+ [{type: "attributes", oldValue: "n00", attributeName: "id"}],
+ function() { n00.id = "n000";},
+ "attributes Element.id: update mutation");
+
+var n01 = document.getElementById('n01');
+runMutationTest(n01,
+ {"attributes":true, "attributeOldValue": true},
+ [{type: "attributes", oldValue: "n01", attributeName: "id"}],
+ function() { n01.id = "";},
+ "attributes Element.id: empty string update mutation");
+
+var n02 = document.getElementById('n02');
+runMutationTest(n02,
+ {"attributes":true, "attributeOldValue": true},
+ [{type: "attributes", oldValue: "n02", attributeName: "id"}, {type: "attributes", attributeName: "class"}],
+ function() { n02.id = "n02"; n02.setAttribute("class", "c01");},
+ "attributes Element.id: same value mutation");
+
+var n03 = document.getElementById('n03');
+runMutationTest(n03,
+ {"attributes":true, "attributeOldValue": true},
+ [{type: "attributes", oldValue: "n03", attributeName: "id"}],
+ function() { n03.unknown = "c02"; n03.id = "n030";},
+ "attributes Element.unknown: IDL attribute no mutation");
+
+var n04 = document.getElementById('n04');
+runMutationTest(n04,
+ {"attributes":true, "attributeOldValue": true},
+ [{type: "attributes", oldValue: "text", attributeName: "type"}, {type: "attributes", oldValue: "n04", attributeName: "id"}],
+ function() { n04.type = "unknown"; n04.id = "n040";},
+ "attributes HTMLInputElement.type: type update mutation");
+
+ var n10 = document.getElementById('n10');
+runMutationTest(n10,
+ {"attributes":true, "attributeOldValue": true},
+ [{type: "attributes", attributeName: "class"}],
+ function() { n10.className = "c01";},
+ "attributes Element.className: new value mutation");
+
+ var n11 = document.getElementById('n11');
+runMutationTest(n11,
+ {"attributes":true, "attributeOldValue": true},
+ [{type: "attributes", attributeName: "class"}],
+ function() { n11.className = "";},
+ "attributes Element.className: empty string update mutation");
+
+ var n12 = document.getElementById('n12');
+runMutationTest(n12,
+ {"attributes":true, "attributeOldValue": true},
+ [{type: "attributes", oldValue: "c01", attributeName: "class"}],
+ function() { n12.className = "c01";},
+ "attributes Element.className: same value mutation");
+
+ var n13 = document.getElementById('n13');
+runMutationTest(n13,
+ {"attributes":true, "attributeOldValue": true},
+ [{type: "attributes", oldValue: "c01 c02", attributeName: "class"}],
+ function() { n13.className = "c01 c02";},
+ "attributes Element.className: same multiple values mutation");
+
+ var n20 = document.getElementById('n20');
+runMutationTest(n20,
+ {"attributes":true, "attributeOldValue": true},
+ [{type: "attributes", attributeName: "class"}],
+ function() { n20.classList.add("c01");},
+ "attributes Element.classList.add: single token addition mutation");
+
+ var n21 = document.getElementById('n21');
+runMutationTest(n21,
+ {"attributes":true, "attributeOldValue": true},
+ [{type: "attributes", attributeName: "class"}],
+ function() { n21.classList.add("c01", "c02", "c03");},
+ "attributes Element.classList.add: multiple tokens addition mutation");
+
+ var n22 = document.getElementById('n22');
+runMutationTest(n22,
+ {"attributes":true, "attributeOldValue": true},
+ [{type: "attributes", oldValue: "n22", attributeName: "id"}],
+ function() { try { n22.classList.add("c01", "", "c03"); } catch (e) { };
+ n22.id = "n220"; },
+ "attributes Element.classList.add: syntax err/no mutation");
+
+ var n23 = document.getElementById('n23');
+runMutationTest(n23,
+ {"attributes":true, "attributeOldValue": true},
+ [{type: "attributes", oldValue: "n23", attributeName: "id"}],
+ function() { try { n23.classList.add("c01", "c 02", "c03"); } catch (e) { };
+ n23.id = "n230"; },
+ "attributes Element.classList.add: invalid character/no mutation");
+
+ var n24 = document.getElementById('n24');
+runMutationTest(n24,
+ {"attributes":true, "attributeOldValue": true},
+ [{type: "attributes", oldValue: "c01 c02", attributeName: "class"}, {type: "attributes", oldValue: "n24", attributeName: "id"}],
+ function() { n24.classList.add("c02"); n24.id = "n240";},
+ "attributes Element.classList.add: same value mutation");
+
+ var n30 = document.getElementById('n30');
+runMutationTest(n30,
+ {"attributes":true, "attributeOldValue": true},
+ [{type: "attributes", oldValue: "c01 c02", attributeName: "class"}],
+ function() { n30.classList.remove("c01");},
+ "attributes Element.classList.remove: single token removal mutation");
+
+ var n31 = document.getElementById('n31');
+runMutationTest(n31,
+ {"attributes":true, "attributeOldValue": true},
+ [{type: "attributes", oldValue: "c01 c02", attributeName: "class"}],
+ function() { n31.classList.remove("c01", "c02");},
+ "attributes Element.classList.remove: multiple tokens removal mutation");
+
+ var n32 = document.getElementById('n32');
+runMutationTest(n32,
+ {"attributes":true, "attributeOldValue": true},
+ [{type: "attributes", oldValue: "c01 c02", attributeName: "class"}, {type: "attributes", oldValue: "n32", attributeName: "id"}],
+ function() { n32.classList.remove("c03"); n32.id = "n320";},
+ "attributes Element.classList.remove: missing token removal mutation");
+
+ var n40 = document.getElementById('n40');
+runMutationTest(n40,
+ {"attributes":true, "attributeOldValue": true},
+ [{type: "attributes", oldValue: "c01 c02", attributeName: "class"}],
+ function() { n40.classList.toggle("c01");},
+ "attributes Element.classList.toggle: token removal mutation");
+
+ var n41 = document.getElementById('n41');
+runMutationTest(n41,
+ {"attributes":true, "attributeOldValue": true},
+ [{type: "attributes", oldValue: "c01 c02", attributeName: "class"}],
+ function() { n41.classList.toggle("c03");},
+ "attributes Element.classList.toggle: token addition mutation");
+
+ var n42 = document.getElementById('n42');
+runMutationTest(n42,
+ {"attributes":true, "attributeOldValue": true},
+ [{type: "attributes", oldValue: "c01 c02", attributeName: "class"}],
+ function() { n42.classList.toggle("c01", false);},
+ "attributes Element.classList.toggle: forced token removal mutation");
+
+ var n43 = document.getElementById('n43');
+runMutationTest(n43,
+ {"attributes":true, "attributeOldValue": true},
+ [{type: "attributes", oldValue: "n43", attributeName: "id"}],
+ function() { n43.classList.toggle("c03", false); n43.id = "n430"; },
+ "attributes Element.classList.toggle: forced missing token removal no mutation");
+
+ var n44 = document.getElementById('n44');
+runMutationTest(n44,
+ {"attributes":true, "attributeOldValue": true},
+ [{type: "attributes", oldValue: "n44", attributeName: "id"}],
+ function() { n44.classList.toggle("c01", true); n44.id = "n440"; },
+ "attributes Element.classList.toggle: forced existing token addition no mutation");
+
+ var n45 = document.getElementById('n45');
+runMutationTest(n45,
+ {"attributes":true, "attributeOldValue": true},
+ [{type: "attributes", oldValue: "c01 c02", attributeName: "class"}],
+ function() { n45.classList.toggle("c03", true);},
+ "attributes Element.classList.toggle: forced token addition mutation");
+
+ var n50 = document.getElementById('n50');
+runMutationTest(n50,
+ {"attributes":true, "attributeOldValue": true},
+ [{type: "attributes", oldValue: "c01 c02", attributeName: "class"}],
+ function() {
+ for (var i = 0; i < n50.attributes.length; i++) {
+ var attr = n50.attributes[i];
+ if (attr.localName === "class") {
+ attr.value = "c03";
+ }
+ };
+ },
+ "attributes Element.attributes.value: update mutation");
+
+ var n51 = document.getElementById('n51');
+runMutationTest(n51,
+ {"attributes":true, "attributeOldValue": true},
+ [{type: "attributes", oldValue: "n51", attributeName: "id"}],
+ function() {
+ n51.attributes[0].value = "n51";
+ },
+ "attributes Element.attributes.value: same id mutation");
+
+ var n60 = document.getElementById('n60');
+runMutationTest(n60,
+ {"attributes":true, "attributeOldValue": true},
+ [{type: "attributes", oldValue: "n60", attributeName: "id"}],
+ function() {
+ n60.setAttribute("id", "n601");
+ },
+ "attributes Element.setAttribute: id mutation");
+
+ var n61 = document.getElementById('n61');
+runMutationTest(n61,
+ {"attributes":true, "attributeOldValue": true},
+ [{type: "attributes", oldValue: "c01", attributeName: "class"}],
+ function() {
+ n61.setAttribute("class", "c01");
+ },
+ "attributes Element.setAttribute: same class mutation");
+
+ var n62 = document.getElementById('n62');
+runMutationTest(n62,
+ {"attributes":true, "attributeOldValue": true},
+ [{type: "attributes", attributeName: "classname"}],
+ function() {
+ n62.setAttribute("classname", "c01");
+ },
+ "attributes Element.setAttribute: classname mutation");
+
+ var n70 = document.getElementById('n70');
+runMutationTest(n70,
+ {"attributes":true, "attributeOldValue": true},
+ [{type: "attributes", oldValue: "c01", attributeName: "class"}],
+ function() {
+ n70.removeAttribute("class");
+ },
+ "attributes Element.removeAttribute: removal mutation");
+
+ var n71 = document.getElementById('n71');
+runMutationTest(n71,
+ {"attributes":true, "attributeOldValue": true},
+ [{type: "attributes", oldValue: "n71", attributeName: "id"}],
+ function() {
+ n71.removeAttribute("class");
+ n71.id = "n710";
+ },
+ "attributes Element.removeAttribute: removal no mutation");
+
+ var n72 = document.getElementById('n72');
+runMutationTest(n72,
+ {"attributes":true, "attributeOldValue": true},
+ [{type: "attributes", oldValue: "text", attributeName: "type"}, {type: "attributes", oldValue: "n72", attributeName: "id"}],
+ function() {
+ n72.removeAttribute("type");
+ n72.id = "n720";
+ },
+ "childList HTMLInputElement.removeAttribute: type removal mutation");
+
+ var n80 = document.getElementById('n80');
+runMutationTest(n80,
+ {"attributes":true, "attributeOldValue": true},
+ [{type: "attributes", attributeName: "private", attributeNamespace: "http://example.org/"}],
+ function() {
+ n80.setAttributeNS("http://example.org/", "private", "42");
+ },
+ "attributes Element.setAttributeNS: creation mutation");
+
+ var n81 = document.getElementById('n81');
+runMutationTest(n81,
+ {"attributes":true, "attributeOldValue": true},
+ [{type: "attributes", attributeName: "lang", attributeNamespace: "http://www.w3.org/XML/1998/namespace"}],
+ function() {
+ n81.setAttributeNS("http://www.w3.org/XML/1998/namespace", "xml:lang", "42");
+ },
+ "attributes Element.setAttributeNS: prefixed attribute creation mutation");
+
+ var n90 = document.getElementById('n90');
+ n90.setAttributeNS("http://example.org/", "private", "42");
+runMutationTest(n90,
+ {"attributes":true, "attributeOldValue": true},
+ [{type: "attributes", oldValue: "42", attributeName: "private", attributeNamespace: "http://example.org/"}],
+ function() {
+ n90.removeAttributeNS("http://example.org/", "private");
+ },
+ "attributes Element.removeAttributeNS: removal mutation");
+
+ var n91 = document.getElementById('n91');
+runMutationTest(n91,
+ {"attributes":true, "attributeOldValue": true},
+ [{type: "attributes", oldValue: "n91", attributeName: "id"}],
+ function() {
+ n91.removeAttributeNS("http://example.org/", "private");
+ n91.id = "n910";
+ },
+ "attributes Element.removeAttributeNS: removal no mutation");
+
+ var n92 = document.getElementById('n92');
+runMutationTest(n92,
+ {"attributes":true, "attributeOldValue": true},
+ [{type: "attributes", oldValue: "n92", attributeName: "id"}],
+ function() {
+ n92.removeAttributeNS("http://www.w3.org/XML/1998/namespace", "xml:lang");
+ n92.id = "n920";
+ },
+ "attributes Element.removeAttributeNS: prefixed attribute removal no mutation");
+
+ var n1000 = document.getElementById('n1000');
+runMutationTest(n1000,
+ {"attributes":true, "attributeOldValue": true,"attributeFilter": ["id"]},
+ [{type: "attributes", oldValue: "n1000", attributeName: "id"}],
+ function() { n1000.id = "abc"; n1000.className = "c01"},
+ "attributes/attributeFilter Element.id/Element.className: update mutation");
+
+ var n1001 = document.getElementById('n1001');
+runMutationTest(n1001,
+ {"attributes":true, "attributeOldValue": true,"attributeFilter": ["id", "class"]},
+ [{type: "attributes", oldValue: "n1001", attributeName: "id"},
+ {type: "attributes", oldValue: "c01", attributeName: "class"}],
+ function() { n1001.id = "abc"; n1001.className = "c02"; n1001.setAttribute("lang", "fr");},
+ "attributes/attributeFilter Element.id/Element.className: multiple filter update mutation");
+
+ var n2000 = document.getElementById('n2000');
+runMutationTest(n2000,
+ {"attributeOldValue": true},
+ [{type: "attributes", oldValue: "n2000", attributeName: "id"}],
+ function() { n2000.id = "abc";},
+ "attributeOldValue alone Element.id: update mutation");
+
+ var n2001 = document.getElementById('n2001');
+runMutationTest(n2001,
+ {"attributeFilter": ["id", "class"]},
+ [{type: "attributes", attributeName: "id"},
+ {type: "attributes", attributeName: "class"}],
+ function() { n2001.id = "abcd"; n2001.className = "c02"; n2001.setAttribute("lang", "fr");},
+ "attributeFilter alone Element.id/Element.className: multiple filter update mutation");
+
+ var n3000 = document.getElementById('n3000');
+runMutationTest(n3000,
+ {"subtree": true, "childList":false, "attributes" : true},
+ [{type: "attributes", attributeName: "id" }],
+ function() { n3000.textContent = "CHANGED"; n3000.id = "abc";},
+ "childList false: no childList mutation");
+
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/MutationObserver-characterData.html b/tests/wpt/web-platform-tests/dom/nodes/MutationObserver-characterData.html
new file mode 100644
index 00000000000..addaef03da1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/MutationObserver-characterData.html
@@ -0,0 +1,215 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>MutationObservers: characterData mutations</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="mutationobservers.js"></script>
+<h1>MutationObservers: characterData mutations</h1>
+<div id="log"></div>
+
+<section style="display: none">
+
+<p id='n'>text content</p>
+
+<p id='n00'>text content</p>
+
+<p id='n10'>CHAN</p>
+<p id='n11'>CHANGED</p>
+<p id='n12'>CHANGED</p>
+
+<p id='n20'>CHGED</p>
+<p id='n21'>CHANGED</p>
+<p id='n22'>CHANGED</p>
+
+<p id='n30'>CCCHANGED</p>
+<p id='n31'>CHANGED</p>
+
+<p id='n40'>CCCHANGED</p>
+<p id='n41'>CHANGED</p>
+
+<p id="n50"><?processing data?></p>
+
+<p id="n60"><!-- data --></p>
+
+<p id='n70'>CHANN</p>
+<p id='n71'>CHANN</p>
+
+<p id='n80'>CHANN</p>
+<p id='n81'>CHANN</p>
+
+<p id='n90'>CHANN</p>
+
+</section>
+
+<script>
+ var n = document.getElementById('n').firstChild;
+runMutationTest(n,
+ {"characterData":true},
+ [{type: "characterData"}],
+ function() { n.data = "NEW VALUE"; },
+ "characterData Text.data: simple mutation without oldValue");
+
+ var n00 = document.getElementById('n00').firstChild;
+runMutationTest(n00,
+ {"characterData":true,"characterDataOldValue":true},
+ [{type: "characterData", oldValue: "text content" }],
+ function() { n00.data = "CHANGED"; },
+ "characterData Text.data: simple mutation");
+
+ var n10 = document.getElementById('n10').firstChild;
+runMutationTest(n10,
+ {"characterData":true,"characterDataOldValue":true},
+ [{type: "characterData", oldValue: "CHAN" }],
+ function() { n10.appendData("GED"); },
+ "characterData Text.appendData: simple mutation");
+
+ var n11 = document.getElementById('n11').firstChild;
+runMutationTest(n11,
+ {"characterData":true,"characterDataOldValue":true},
+ [{type: "characterData", oldValue: "CHANGED" }],
+ function() { n11.appendData(""); },
+ "characterData Text.appendData: empty string mutation");
+
+ var n12 = document.getElementById('n12').firstChild;
+runMutationTest(n12,
+ {"characterData":true,"characterDataOldValue":true},
+ [{type: "characterData", oldValue: "CHANGED" }],
+ function() { n12.appendData(null); },
+ "characterData Text.appendData: null string mutation");
+
+ var n20 = document.getElementById('n20').firstChild;
+runMutationTest(n20,
+ {"characterData":true,"characterDataOldValue":true},
+ [{type: "characterData", oldValue: "CHGED" }],
+ function() { n20.insertData(2, "AN"); },
+ "characterData Text.insertData: simple mutation");
+
+ var n21 = document.getElementById('n21').firstChild;
+runMutationTest(n21,
+ {"characterData":true,"characterDataOldValue":true},
+ [{type: "characterData", oldValue: "CHANGED" }],
+ function() { n21.insertData(2, ""); },
+ "characterData Text.insertData: empty string mutation");
+
+ var n22 = document.getElementById('n22').firstChild;
+runMutationTest(n22,
+ {"characterData":true,"characterDataOldValue":true},
+ [{type: "characterData", oldValue: "CHANGED" }],
+ function() { n22.insertData(2, null); },
+ "characterData Text.insertData: null string mutation");
+
+ var n30 = document.getElementById('n30').firstChild;
+runMutationTest(n30,
+ {"characterData":true,"characterDataOldValue":true},
+ [{type: "characterData", oldValue: "CCCHANGED" }],
+ function() { n30.deleteData(0, 2); },
+ "characterData Text.deleteData: simple mutation");
+
+ var n31 = document.getElementById('n31').firstChild;
+runMutationTest(n31,
+ {"characterData":true,"characterDataOldValue":true},
+ [{type: "characterData", oldValue: "CHANGED" }, {type: "characterData", oldValue: "CHANGED" }],
+ function() { n31.deleteData(0, 0); n31.data = "n31"; },
+ "characterData Text.deleteData: empty mutation");
+
+ var n40 = document.getElementById('n40').firstChild;
+runMutationTest(n40,
+ {"characterData":true,"characterDataOldValue":true},
+ [{type: "characterData", oldValue: "CCCHANGED" }],
+ function() { n40.replaceData(0, 2, "CH"); },
+ "characterData Text.replaceData: simple mutation");
+
+ var n41 = document.getElementById('n41').firstChild;
+runMutationTest(n41,
+ {"characterData":true,"characterDataOldValue":true},
+ [{type: "characterData", oldValue: "CHANGED" }],
+ function() { n41.replaceData(0, 0, "CH"); },
+ "characterData Text.replaceData: empty mutation");
+
+ var n50 = document.getElementById('n50').firstChild;
+runMutationTest(n50,
+ {"characterData":true,"characterDataOldValue":true},
+ [{type: "characterData", oldValue: "?processing data?" },{type: "characterData", oldValue: "CHANGED" },{type: "characterData", oldValue: "CHANGED" }],
+ function() {
+ n50.data = "CHANGED";
+ n50.deleteData(0, 0);
+ n50.replaceData(0, 2, "CH"); },
+ "characterData ProcessingInstruction: data mutations");
+
+ var n60 = document.getElementById('n60').firstChild;
+runMutationTest(n60,
+ {"characterData":true,"characterDataOldValue":true},
+ [{type: "characterData", oldValue: " data " },{type: "characterData", oldValue: "CHANGED" },{type: "characterData", oldValue: "CHANGED" }],
+ function() {
+ n60.data = "CHANGED";
+ n60.deleteData(0, 0);
+ n60.replaceData(0, 2, "CH"); },
+ "characterData Comment: data mutations");
+
+ var n70 = document.getElementById('n70');
+ var r70 = null;
+ test(function () {
+ n70.appendChild(document.createTextNode("NNN"));
+ n70.appendChild(document.createTextNode("NGED"));
+ r70 = document.createRange();
+ r70.setStart(n70.firstChild, 4);
+ r70.setEnd(n70.lastChild, 1);
+ }, "Range (r70) is created");
+runMutationTest(n70.firstChild,
+ {"characterData":true,"characterDataOldValue":true},
+ [{type: "characterData", oldValue: "CHANN" }],
+ function() { r70.deleteContents(); },
+ "characterData Range.deleteContents: child and data removal mutation");
+
+ var n71 = document.getElementById('n71');
+ var r71 = null;
+ test(function () {
+ n71.appendChild(document.createTextNode("NNN"));
+ n71.appendChild(document.createTextNode("NGED"));
+ r71 = document.createRange();
+ r71.setStart(n71.firstChild, 4);
+ r71.setEnd(n71.lastChild, 1);
+ }, "Range (r71) is created");
+runMutationTest(n71.lastChild,
+ {"characterData":true,"characterDataOldValue":true},
+ [{type: "characterData", oldValue: "NGED"}],
+ function() { r71.deleteContents(); },
+ "characterData Range.deleteContents: child and data removal mutation (2)");
+
+ var n80 = document.getElementById('n80');
+ var r80 = null;
+ test(function () {
+ n80.appendChild(document.createTextNode("NNN"));
+ n80.appendChild(document.createTextNode("NGED"));
+ r80 = document.createRange();
+ r80.setStart(n80.firstChild, 4);
+ r80.setEnd(n80.lastChild, 1);
+ }, "Range (r80) is created");
+runMutationTest(n80.firstChild,
+ {"characterData":true,"characterDataOldValue":true},
+ [{type: "characterData", oldValue: "CHANN" }],
+ function() { r80.extractContents(); },
+ "characterData Range.extractContents: child and data removal mutation");
+
+ var n81 = document.getElementById('n81');
+ var r81 = null;
+ test(function () {
+ n81.appendChild(document.createTextNode("NNN"));
+ n81.appendChild(document.createTextNode("NGED"));
+ r81 = document.createRange();
+ r81.setStart(n81.firstChild, 4);
+ r81.setEnd(n81.lastChild, 1);
+ }, "Range (r81) is created");
+runMutationTest(n81.lastChild,
+ {"characterData":true,"characterDataOldValue":true},
+ [{type: "characterData", oldValue: "NGED" }],
+ function() { r81.extractContents(); },
+ "characterData Range.extractContents: child and data removal mutation (2)");
+
+ var n90 = document.getElementById('n90').firstChild;
+runMutationTest(n90,
+ {"characterDataOldValue":true},
+ [{type: "characterData", oldValue: "CHANN" }],
+ function() { n90.data = "CHANGED"; },
+ "characterData/characterDataOldValue alone Text.data: simple mutation");
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/MutationObserver-childList.html b/tests/wpt/web-platform-tests/dom/nodes/MutationObserver-childList.html
new file mode 100644
index 00000000000..c95b1681ec1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/MutationObserver-childList.html
@@ -0,0 +1,423 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>MutationObservers: childList mutations</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="mutationobservers.js"></script>
+<h1>MutationObservers: childList mutations</h1>
+<div id="log"></div>
+
+<section style="display: none">
+<p id='dummies'>
+<span id='d30'>text content</span>
+<span id='d35'>text content</span>
+<span id='d40'>text content</span>
+<span id='d45'>text content</span>
+<span id='d50'>text content</span>
+<span id='d51'>text content</span>
+</p>
+
+</section>
+<section style="display: none">
+<p id='n00'><span>text content</span></p>
+
+<p id='n10'><span>text content</span></p>
+<p id='n11'></p>
+<p id='n12'></p>
+<p id='n13'><span>text content</span></p>
+
+<p id='n20'>PAS</p>
+<p id='n21'>CH</p>
+
+<p id='n30'><span>text content</span></p>
+<p id='n31'><span>text content</span></p>
+<p id='n32'><span>AN</span><span>CH</span><span>GED</span></p>
+<p id='n33'><span>text content</span></p>
+<p id='n34'><span>text content</span></p>
+<p id='n35'><span>text content</span></p>
+
+<p id='n40'><span>text content</span></p>
+<p id='n41'><span>text content</span></p>
+<p id='n42'><span>CH</span><span>GED</span><span>AN</span></p>
+<p id='n43'><span>text content</span></p>
+<p id='n44'><span>text content</span></p>
+<p id='n45'><span>text content</span></p>
+
+
+<p id='n50'><span>text content</span></p>
+<p id='n51'><span>text content</span></p>
+<p id='n52'><span>NO </span><span>CHANGED</span></p>
+
+<p id='n60'><span>text content</span></p>
+
+<p id='n70'><span>NO </span><span>CHANGED</span></p>
+<p id='n71'>CHANN</p>
+
+<p id='n80'><span>NO </span><span>CHANGED</span></p>
+<p id='n81'>CHANN</p>
+
+<p id='n90'><span>CHA</span><span>ED</span></p>
+<p id='n91'>CHAE</p>
+
+<p id='n100'><span id="s1">CHAN</span><span id="s2">GED</span></p>
+
+</section>
+
+<script>
+ var dummies = document.getElementById('dummies');
+
+ function createFragment() {
+ var fragment = document.createDocumentFragment();
+ fragment.appendChild(document.createTextNode("11"));
+ fragment.appendChild(document.createTextNode("22"));
+ return fragment;
+ }
+
+ var n00 = document.getElementById('n00');
+
+ runMutationTest(n00,
+ {"childList":true, "attributes":true},
+ [{type: "attributes", attributeName: "class"}],
+ function() { n00.nodeValue = ""; n00.setAttribute("class", "dummy");},
+ "childList Node.nodeValue: no mutation");
+
+ var n10 = document.getElementById('n10');
+ runMutationTest(n10,
+ {"childList":true},
+ [{type: "childList",
+ removedNodes: [n10.firstChild],
+ addedNodes: function() {return [n10.firstChild]}}],
+ function() { n10.textContent = "new data"; },
+ "childList Node.textContent: replace content mutation");
+
+ var n11 = document.getElementById('n11');
+ runMutationTest(n11,
+ {"childList":true},
+ [{type: "childList",
+ addedNodes: function() {return [n11.firstChild]}}],
+ function() { n11.textContent = "new data"; },
+ "childList Node.textContent: no previous content mutation");
+
+ var n12 = document.getElementById('n12');
+ runMutationTest(n12,
+ {"childList":true, "attributes":true},
+ [{type: "attributes", attributeName: "class"}],
+ function() { n12.textContent = ""; n12.setAttribute("class", "dummy");},
+ "childList Node.textContent: textContent no mutation");
+
+ var n13 = document.getElementById('n13');
+ runMutationTest(n13,
+ {"childList":true},
+ [{type: "childList", removedNodes: [n13.firstChild]}],
+ function() { n13.textContent = ""; },
+ "childList Node.textContent: empty string mutation");
+
+ var n20 = document.getElementById('n20');
+ n20.appendChild(document.createTextNode("S"));
+ runMutationTest(n20,
+ {"childList":true},
+ [{type: "childList",
+ removedNodes: [n20.lastChild],
+ previousSibling: n20.firstChild}],
+ function() { n20.normalize(); },
+ "childList Node.normalize mutation");
+
+ var n21 = document.getElementById('n21');
+ n21.appendChild(document.createTextNode("AN"));
+ n21.appendChild(document.createTextNode("GED"));
+ runMutationTest(n21,
+ {"childList":true},
+ [{type: "childList",
+ removedNodes: [n21.lastChild.previousSibling],
+ previousSibling: n21.firstChild,
+ nextSibling: n21.lastChild},
+ {type: "childList",
+ removedNodes: [n21.lastChild],
+ previousSibling: n21.firstChild}],
+ function() { n21.normalize(); },
+ "childList Node.normalize mutations");
+
+ var n30 = document.getElementById('n30');
+ var d30 = document.getElementById('d30');
+ runMutationTest(n30,
+ {"childList":true},
+ [{type: "childList",
+ addedNodes: [d30],
+ nextSibling: n30.firstChild}],
+ function() { n30.insertBefore(d30, n30.firstChild); },
+ "childList Node.insertBefore: addition mutation");
+
+ var n31 = document.getElementById('n31');
+ runMutationTest(n31,
+ {"childList":true},
+ [{type: "childList",
+ removedNodes: [n31.firstChild]}],
+ function() { dummies.insertBefore(n31.firstChild, dummies.firstChild); },
+ "childList Node.insertBefore: removal mutation");
+
+ var n32 = document.getElementById('n32');
+ runMutationTest(n32,
+ {"childList":true},
+ [{type: "childList",
+ removedNodes: [n32.firstChild.nextSibling],
+ previousSibling: n32.firstChild, nextSibling: n32.lastChild},
+ {type: "childList",
+ addedNodes: [n32.firstChild.nextSibling],
+ nextSibling: n32.firstChild}],
+ function() { n32.insertBefore(n32.firstChild.nextSibling, n32.firstChild); },
+ "childList Node.insertBefore: removal and addition mutations");
+
+ var n33 = document.getElementById('n33');
+ var f33 = createFragment();
+ runMutationTest(n33,
+ {"childList":true},
+ [{type: "childList",
+ addedNodes: [f33.firstChild, f33.lastChild],
+ nextSibling: n33.firstChild}],
+ function() { n33.insertBefore(f33, n33.firstChild); },
+ "childList Node.insertBefore: fragment addition mutations");
+
+ var n34 = document.getElementById('n34');
+ var f34 = createFragment();
+ runMutationTest(f34,
+ {"childList":true},
+ [{type: "childList",
+ removedNodes: [f34.firstChild, f34.lastChild]}],
+ function() { n34.insertBefore(f34, n34.firstChild); },
+ "childList Node.insertBefore: fragment removal mutations");
+
+ var n35 = document.getElementById('n35');
+ var d35 = document.getElementById('d35');
+ runMutationTest(n35,
+ {"childList":true},
+ [{type: "childList",
+ addedNodes: [d35],
+ previousSibling: n35.firstChild}],
+ function() { n35.insertBefore(d35, null); },
+ "childList Node.insertBefore: last child addition mutation");
+
+ var n40 = document.getElementById('n40');
+ var d40 = document.getElementById('d40');
+ runMutationTest(n40,
+ {"childList":true},
+ [{type: "childList",
+ addedNodes: [d40],
+ previousSibling: n40.firstChild}],
+ function() { n40.appendChild(d40); },
+ "childList Node.appendChild: addition mutation");
+
+ var n41 = document.getElementById('n41');
+ runMutationTest(n41,
+ {"childList":true},
+ [{type: "childList",
+ removedNodes: [n41.firstChild]}],
+ function() { dummies.appendChild(n41.firstChild); },
+ "childList Node.appendChild: removal mutation");
+
+ var n42 = document.getElementById('n42');
+ runMutationTest(n42,
+ {"childList":true},
+ [{type: "childList",
+ removedNodes: [n42.firstChild.nextSibling],
+ previousSibling: n42.firstChild, nextSibling: n42.lastChild},
+ {type: "childList",
+ addedNodes: [n42.firstChild.nextSibling],
+ previousSibling: n42.lastChild}],
+ function() { n42.appendChild(n42.firstChild.nextSibling); },
+ "childList Node.appendChild: removal and addition mutations");
+
+ var n43 = document.getElementById('n43');
+ var f43 = createFragment();
+ runMutationTest(n43,
+ {"childList":true},
+ [{type: "childList",
+ addedNodes: [f43.firstChild, f43.lastChild],
+ previousSibling: n43.firstChild}],
+ function() { n43.appendChild(f43); },
+ "childList Node.appendChild: fragment addition mutations");
+
+ var n44 = document.getElementById('n44');
+ var f44 = createFragment();
+ runMutationTest(f44,
+ {"childList":true},
+ [{type: "childList",
+ removedNodes: [f44.firstChild, f44.lastChild]}],
+ function() { n44.appendChild(f44); },
+ "childList Node.appendChild: fragment removal mutations");
+
+ var n45 = document.createElement('p');
+ var d45 = document.createElement('span');
+ runMutationTest(n45,
+ {"childList":true},
+ [{type: "childList",
+ addedNodes: [d45]}],
+ function() { n45.appendChild(d45); },
+ "childList Node.appendChild: addition outside document tree mutation");
+
+ var n50 = document.getElementById('n50');
+ var d50 = document.getElementById('d50');
+ runMutationTest(n50,
+ {"childList":true},
+ [{type: "childList",
+ removedNodes: [n50.firstChild],
+ addedNodes: [d50]}],
+ function() { n50.replaceChild(d50, n50.firstChild); },
+ "childList Node.replaceChild: replacement mutation");
+
+ var n51 = document.getElementById('n51');
+ var d51 = document.getElementById('d51');
+ runMutationTest(n51,
+ {"childList":true},
+ [{type: "childList",
+ removedNodes: [n51.firstChild]}],
+ function() { d51.parentNode.replaceChild(n51.firstChild, d51); },
+ "childList Node.replaceChild: removal mutation");
+
+ var n52 = document.getElementById('n52');
+ runMutationTest(n52,
+ {"childList":true},
+ [{type: "childList",
+ removedNodes: [n52.lastChild],
+ previousSibling: n52.firstChild},
+ {type: "childList",
+ removedNodes: [n52.firstChild],
+ addedNodes: [n52.lastChild]}],
+ function() { n52.replaceChild(n52.lastChild, n52.firstChild); },
+ "childList Node.replaceChild: internal replacement mutation");
+
+ var n60 = document.getElementById('n60');
+ runMutationTest(n60,
+ {"childList":true},
+ [{type: "childList",
+ removedNodes: [n60.firstChild]}],
+ function() { n60.removeChild(n60.firstChild); },
+ "childList Node.removeChild: removal mutation");
+
+ var n70 = document.getElementById('n70');
+ var r70 = null;
+ test(function () {
+ r70 = document.createRange();
+ r70.setStartBefore(n70.firstChild);
+ r70.setEndAfter(n70.firstChild);
+ }, "Range (r70) is created");
+ runMutationTest(n70,
+ {"childList":true},
+ [{type: "childList",
+ removedNodes: [n70.firstChild],
+ nextSibling: n70.lastChild}],
+ function() { r70.deleteContents(); },
+ "childList Range.deleteContents: child removal mutation");
+
+ var n71 = document.getElementById('n71');
+ var r71 = null;
+ test(function () {
+ n71.appendChild(document.createTextNode("NNN"));
+ n71.appendChild(document.createTextNode("NGED"));
+ r71 = document.createRange();
+ r71.setStart(n71.firstChild, 4);
+ r71.setEnd(n71.lastChild, 1);
+ }, "Range (r71) is created");
+ runMutationTest(n71,
+ {"childList":true},
+ [{type: "childList",
+ removedNodes: [n71.firstChild.nextSibling],
+ previousSibling: n71.firstChild,
+ nextSibling: n71.lastChild}],
+ function() { r71.deleteContents(); },
+ "childList Range.deleteContents: child and data removal mutation");
+
+ var n80 = document.getElementById('n80');
+ var r80 = null;
+ test(function () {
+ r80 = document.createRange();
+ r80.setStartBefore(n80.firstChild);
+ r80.setEndAfter(n80.firstChild);
+ }, "Range (r80) is created");
+ runMutationTest(n80,
+ {"childList":true},
+ [{type: "childList",
+ removedNodes: [n80.firstChild],
+ nextSibling: n80.lastChild}],
+ function() { r80.extractContents(); },
+ "childList Range.extractContents: child removal mutation");
+
+ var n81 = document.getElementById('n81');
+ var r81 = null;
+ test(function () {
+ n81.appendChild(document.createTextNode("NNN"));
+ n81.appendChild(document.createTextNode("NGED"));
+ r81 = document.createRange();
+ r81.setStart(n81.firstChild, 4);
+ r81.setEnd(n81.lastChild, 1);
+ }, "Range (r81) is created");
+ runMutationTest(n81,
+ {"childList":true},
+ [{type: "childList",
+ removedNodes: [n81.firstChild.nextSibling],
+ previousSibling: n81.firstChild,
+ nextSibling: n81.lastChild}],
+ function() { r81.extractContents(); },
+ "childList Range.extractContents: child and data removal mutation");
+
+ var n90 = document.getElementById('n90');
+ var f90 = document.createTextNode("NG");
+ var r90 = null;
+ test(function () {
+ r90 = document.createRange();
+ r90.setStartAfter(n90.firstChild);
+ r90.setEndBefore(n90.lastChild);
+ }, "Range (r90) is created");
+ runMutationTest(n90,
+ {"childList":true},
+ [{type: "childList",
+ addedNodes: [f90],
+ previousSibling: n90.firstChild,
+ nextSibling: n90.lastChild}],
+ function() { r90.insertNode(f90); },
+ "childList Range.insertNode: child insertion mutation");
+
+ var n91 = document.getElementById('n91');
+ var f91 = document.createTextNode("NG");
+ var r91 = null;
+ test(function () {
+ n91.appendChild(document.createTextNode("D"));
+ r91 = document.createRange();
+ r91.setStart(n91.firstChild, 3);
+ r91.setEnd(n91.lastChild, 0);
+ }, "Range (r91) is created");
+ runMutationTest(n91,
+ {"childList":true},
+ [{type: "childList",
+ addedNodes: function() { return [n91.lastChild.previousSibling]; },
+ previousSibling: n91.firstChild,
+ nextSibling: n91.lastChild},
+ {type: "childList",
+ addedNodes: [f91],
+ previousSibling: n91.firstChild,
+ nextSibling: function () { return n91.lastChild.previousSibling; } }],
+ function() { r91.insertNode(f91); },
+ "childList Range.insertNode: children insertion mutation");
+
+ var n100 = document.getElementById('n100');
+ var f100 = document.createElement("span");
+ var r100 = null;
+ test(function () {
+ r100 = document.createRange();
+ r100.setStartBefore(n100.firstChild);
+ r100.setEndAfter(n100.lastChild);
+ }, "Range (r100) is created");
+ runMutationTest(n100,
+ {"childList":true},
+ [{type: "childList",
+ removedNodes: [n100.firstChild],
+ nextSibling: n100.lastChild},
+ {type: "childList",
+ removedNodes: [n100.lastChild]},
+ {type: "childList",
+ addedNodes: [f100] }],
+ function() { r100.surroundContents(f100); },
+ "childList Range.surroundContents: children removal and addition mutation");
+
+</script>
+
+
diff --git a/tests/wpt/web-platform-tests/dom/nodes/MutationObserver-disconnect.html b/tests/wpt/web-platform-tests/dom/nodes/MutationObserver-disconnect.html
new file mode 100644
index 00000000000..883edecf744
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/MutationObserver-disconnect.html
@@ -0,0 +1,48 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>MutationObservers: disconnect</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<h1>MutationObservers: disconnect</h1>
+<div id="log"></div>
+<section style="display: none">
+<p id='n00'></p>
+</section>
+<script>
+var n00 = document.getElementById('n00');
+var parentTest = async_test("subtree mutations");
+function masterMO(sequence, obs) {
+ parentTest.step(function() {
+ assert_equals(sequence.length, 4, "mutation records must match");
+ });
+ parentTest.done();
+}
+parentTest.step(function() {
+ (new MutationObserver(masterMO)).observe(n00.parentNode, {"subtree": true, "attributes": true});
+});
+
+var disconnectTest = async_test("disconnect discarded some mutations");
+function observerCallback(sequence, obs) {
+ disconnectTest.step(function() {
+ assert_equals(sequence.length, 1);
+ assert_equals(sequence[0].type, "attributes");
+ assert_equals(sequence[0].attributeName, "id");
+ assert_equals(sequence[0].oldValue, "latest");
+ disconnectTest.done();
+ });
+}
+
+var observer;
+disconnectTest.step(function() {
+ observer = new MutationObserver(observerCallback);
+ observer.observe(n00, {"attributes": true});
+ n00.id = "foo";
+ n00.id = "bar";
+ observer.disconnect();
+ observer.observe(n00, {"attributes": true, "attributeOldValue": true});
+ n00.id = "latest";
+ observer.disconnect();
+ observer.observe(n00, {"attributes": true, "attributeOldValue": true});
+ n00.id = "n0000";
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/MutationObserver-document.html b/tests/wpt/web-platform-tests/dom/nodes/MutationObserver-document.html
new file mode 100644
index 00000000000..2ab812679ec
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/MutationObserver-document.html
@@ -0,0 +1,167 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>MutationObservers: takeRecords</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="mutationobservers.js"></script>
+<h1>MutationObservers: document mutations</h1>
+<div id="log"></div>
+
+<script id='s001'>
+ var setupTest = async_test("setup test");
+ var insertionTest = async_test("parser insertion mutations");
+ var insertionTest2 = async_test("parser script insertion mutation");
+ var testCounter = 0;
+
+ function masterMO(sequence, obs) {
+ testCounter++;
+ if (testCounter == 1) {
+ insertionTest.step(
+ function () {
+ checkRecords(document, sequence,
+ [{type: "childList",
+ addedNodes: function () {
+ return [ document.getElementById("n00") ];
+ },
+ previousSibling: function () {
+ return document.getElementById("s001");
+ },
+ target: document.body},
+ {type: "childList",
+ addedNodes: function () {
+ return [ document.getElementById("s002") ];
+ },
+ previousSibling: function () {
+ return document.getElementById("n00");
+ },
+ target: document.body},
+ {type: "childList",
+ addedNodes: function () {
+ return [ document.getElementById("s002").firstChild ];
+ },
+ target: function () {
+ return document.getElementById("s002");
+ }}]);
+ });
+ } else if (testCounter == 2) {
+ insertionTest2.step(
+ function () {
+ checkRecords(document, sequence,
+ [{type: "childList",
+ addedNodes: function () {
+ return [ document.getElementById("inserted_element") ];
+ },
+ previousSibling: function () {
+ return document.getElementById("s002");
+ },
+ target: document.body},
+ {type: "childList",
+ addedNodes: function () {
+ return [ document.getElementById("inserted_script") ];
+ },
+ target: function () {
+ return document.getElementById("n00");
+ }}
+ ]);
+ });
+ }
+ }
+ var document_observer;
+ var newElement;
+ setupTest.step(function() {
+ document_observer = new MutationObserver(masterMO);
+ newElement = document.createElement("span");
+ document_observer.observe(document, {subtree:true,childList:true});
+ newElement.id = "inserted_element";
+ newElement.setAttribute("style", "display: none");
+ newElement.textContent = "my new span for n00";
+ });
+</script><p id='n00'></p><script id='s002'>
+ var newScript = document.createElement("script");
+ setupTest.step(function() {
+ newScript.textContent = "document.body.appendChild(newElement);";
+ newScript.id = "inserted_script";
+ document.getElementById("n00").appendChild(newScript);
+ });
+ if (testCounter < 1) {
+ insertionTest.step(
+ function () {
+ assert_unreached("document observer did not trigger");
+ });
+ }
+</script><script id='s003'>
+ setupTest.step(function() {
+ document_observer.disconnect();
+ });
+ if (testCounter < 2) {
+ insertionTest2.step(
+ function () {
+ assert_unreached("document observer did not trigger");
+ });
+ }
+ insertionTest.done();
+ insertionTest2.done();
+</script>
+
+<p id='n012'></p><div id='d01'>
+<script id='s011'>
+ var removalTest = async_test("removal of parent during parsing");
+ var d01 = document.getElementById("d01");
+ testCounter = 0;
+
+ function removalMO(sequence, obs) {
+ testCounter++;
+ if (testCounter == 1) {
+ removalTest.step(
+ function () {
+ checkRecords(document, sequence,
+ [{type: "childList",
+ removedNodes: function () {
+ return [ d01 ];
+ },
+ previousSibling: function () {
+ return document.getElementById("n012");
+ },
+ target: document.body}]);
+ });
+ } else if (testCounter == 2) {
+ removalTest.step(
+ function () {
+ checkRecords(document, sequence,
+ [{type: "childList",
+ addedNodes: function () {
+ return [ document.getElementById("s012") ];
+ },
+ previousSibling: function () {
+ return document.getElementById("n012");
+ },
+ target: document.body},
+ {type: "childList",
+ addedNodes: function () {
+ return [ document.getElementById("s012").firstChild ];
+ },
+ target: function () {
+ return document.getElementById("s012");
+ }}]);
+ });
+ }
+ }
+ var document2_observer;
+ setupTest.step(function() {
+ document2_observer = new MutationObserver(removalMO);
+ document2_observer.observe(document, {subtree:true,childList:true});
+ d01.parentNode.removeChild(d01);
+ });
+</script><p id='n01'></p></div><script id='s012'>
+ setupTest.step(function() {
+ document2_observer.disconnect();
+ });
+ if (testCounter < 2) {
+ removalTest.step(
+ function () {
+ assert_unreached("document observer did not trigger");
+ });
+ }
+ removalTest.done();
+ setupTest.done();
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/MutationObserver-inner-outer.html b/tests/wpt/web-platform-tests/dom/nodes/MutationObserver-inner-outer.html
new file mode 100644
index 00000000000..9f6d871417d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/MutationObserver-inner-outer.html
@@ -0,0 +1,65 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>MutationObservers: innerHTML, outerHTML mutations</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="mutationobservers.js"></script>
+<h1>MutationObservers: innerHTML, outerHTML mutations</h1>
+<div id="log"></div>
+
+<section style="display: none">
+
+<p id='n00'>old text</p>
+
+<p id='n01'>old text</p>
+
+<div id='n02'><p>old text</p></div>
+</section>
+
+<script>
+ var n00;
+ var n00oldText;
+ var n01;
+ var n01oldText;
+ var n02;
+
+ setup(function() {
+ n00 = document.getElementById('n00');
+ n00oldText = n00.firstChild;
+ n01 = document.getElementById('n01');
+ n01oldText = n01.firstChild;
+ n02 = document.getElementById('n02');
+ })
+
+ runMutationTest(n00,
+ {childList:true,attributes:true},
+ [{type: "childList",
+ removedNodes: [n00oldText],
+ addedNodes: function() {
+ return [document.getElementById("n00").firstChild];
+ }},
+ {type: "attributes", attributeName: "class"}],
+ function() { n00.innerHTML = "new text"; n00.className = "c01"},
+ "innerHTML mutation");
+
+ runMutationTest(n01,
+ {childList:true},
+ [{type: "childList",
+ removedNodes: [n01oldText],
+ addedNodes: function() {
+ return [document.getElementById("n01").firstChild,
+ document.getElementById("n01").lastChild];
+ }}],
+ function() { n01.innerHTML = "<span>new</span><span>text</span>"; },
+ "innerHTML with 2 children mutation");
+
+ runMutationTest(n02,
+ {childList:true},
+ [{type: "childList",
+ removedNodes: [n02.firstChild],
+ addedNodes: function() {
+ return [n02.firstChild];
+ }}],
+ function() { n02.firstChild.outerHTML = "<p>next text</p>"; },
+ "outerHTML mutation");
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/MutationObserver-takeRecords.html b/tests/wpt/web-platform-tests/dom/nodes/MutationObserver-takeRecords.html
new file mode 100644
index 00000000000..6a27ef77eca
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/MutationObserver-takeRecords.html
@@ -0,0 +1,53 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>MutationObservers: takeRecords</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="mutationobservers.js"></script>
+<h1>MutationObservers: takeRecords</h1>
+<div id="log"></div>
+
+<section style="display: none">
+
+<p id='n00'></p>
+
+</section>
+
+<script>
+
+ var n00 = document.getElementById('n00');
+
+ var unused = async_test("unreachabled test");
+
+ var observer;
+ unused.step(function () {
+ observer = new MutationObserver(unused.unreached_func("the observer callback should not fire"));
+ observer.observe(n00, { "subtree": true,
+ "childList": true,
+ "attributes": true,
+ "characterData": true,
+ "attributeOldValue": true,
+ "characterDataOldValue": true});
+ n00.id = "foo";
+ n00.id = "bar";
+ n00.className = "bar";
+ n00.textContent = "old data";
+ n00.firstChild.data = "new data";
+ });
+
+ test(function() {
+ checkRecords(n00, observer.takeRecords(), [{type: "attributes", attributeName: "id", oldValue: "n00"},
+ {type: "attributes", attributeName: "id", oldValue: "foo"},
+ {type: "attributes", attributeName: "class"},
+ {type: "childList", addedNodes: [n00.firstChild]},
+ {type: "characterData", oldValue: "old data", target: n00.firstChild}]);
+ }, "All records present");
+
+ test(function() {
+ checkRecords(n00, observer.takeRecords(), []);
+ }, "No more records present");
+</script>
+<script>
+ unused.done();
+
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Node-appendChild.html b/tests/wpt/web-platform-tests/dom/nodes/Node-appendChild.html
new file mode 100644
index 00000000000..684607961a7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Node-appendChild.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Node.appendChild</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-node-appendchild">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<iframe src=about:blank></iframe>
+<script>
+// TODO: Exhaustive tests
+function testLeaf(node, desc) {
+ // WebIDL.
+ test(function() {
+ assert_throws(new TypeError(), function() { node.appendChild(null) })
+ }, "Appending null to a " + desc)
+
+ // Pre-insert step 1.
+ test(function() {
+ assert_throws("HIERARCHY_REQUEST_ERR", function() { node.appendChild(document.createTextNode("fail")) })
+ }, "Appending to a " + desc)
+}
+
+// WebIDL.
+test(function() {
+ assert_throws(new TypeError(), function() { document.body.appendChild(null) })
+ assert_throws(new TypeError(), function() { document.body.appendChild({'a':'b'}) })
+}, "WebIDL tests")
+
+// WebIDL and pre-insert step 1.
+test(function() {
+ testLeaf(document.createTextNode("Foo"), "text node")
+ testLeaf(document.createComment("Foo"), "comment")
+ testLeaf(document.doctype, "doctype")
+}, "Appending to a leaf node.")
+
+// Pre-insert step 5.
+test(function() {
+ var frameDoc = frames[0].document
+ assert_throws("HIERARCHY_REQUEST_ERR", function() { document.body.appendChild(frameDoc) })
+}, "Appending a document")
+
+// Pre-insert step 8.
+test(function() {
+ var frameDoc = frames[0].document
+ var s = frameDoc.createElement("a")
+ assert_equals(s.ownerDocument, frameDoc)
+ document.body.appendChild(s)
+ assert_equals(s.ownerDocument, document)
+}, "Adopting an orphan")
+test(function() {
+ var frameDoc = frames[0].document
+ var s = frameDoc.createElement("b")
+ assert_equals(s.ownerDocument, frameDoc)
+ frameDoc.body.appendChild(s)
+ assert_equals(s.ownerDocument, frameDoc)
+ document.body.appendChild(s)
+ assert_equals(s.ownerDocument, document)
+}, "Adopting a non-orphan")
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Node-childNodes.html b/tests/wpt/web-platform-tests/dom/nodes/Node-childNodes.html
new file mode 100644
index 00000000000..d08dd2e1fa5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Node-childNodes.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Node.childNodes</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-node-childnodes">
+<link rel=author title="Tim Taubert" href="mailto:ttaubert@mozilla.com">
+<link rel=author title="Ms2ger" href="mailto:Ms2ger@gmail.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ var element = document.createElement("p");
+ assert_equals(element.childNodes, element.childNodes);
+}, "Caching of Node.childNodes");
+
+var check_parent_node = function(node) {
+ assert_array_equals(node.childNodes, []);
+
+ var children = node.childNodes;
+ var child = document.createElement("p");
+ node.appendChild(child);
+ assert_equals(node.childNodes, children);
+ assert_array_equals(children, [child]);
+ assert_equals(children.item(0), child);
+
+ var child2 = document.createComment("comment");
+ node.appendChild(child2);
+ assert_array_equals(children, [child, child2]);
+ assert_equals(children.item(0), child);
+ assert_equals(children.item(1), child2);
+
+ assert_false(2 in children);
+ assert_equals(children[2], undefined);
+ assert_equals(children.item(2), null);
+};
+
+test(function() {
+ check_parent_node(document.createElement("p"));
+}, "Node.childNodes on an Element.");
+
+test(function() {
+ check_parent_node(document.createDocumentFragment());
+}, "Node.childNodes on a DocumentFragment.");
+
+test(function() {
+ check_parent_node(new Document());
+}, "Node.childNodes on a Document.");
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Node-cloneNode.html b/tests/wpt/web-platform-tests/dom/nodes/Node-cloneNode.html
new file mode 100644
index 00000000000..9b98bc97b6f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Node-cloneNode.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Node.cloneNode</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-node-clonenode">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+function assert_equal_node(nodeA, nodeB) {
+ assert_equals(nodeB.nodeType, nodeA.nodeType, "nodeType");
+ assert_equals(nodeB.nodeName, nodeA.nodeName, "nodeName");
+
+ if (nodeA.nodeType === Node.ELEMENT_NODE) {
+ assert_equals(nodeB.prefix, nodeA.prefix);
+ assert_equals(nodeB.namespaceURI, nodeA.namespaceURI);
+ assert_equals(nodeB.localName, nodeA.localName);
+ assert_equals(nodeB.tagName, nodeA.tagName);
+ assert_not_equals(nodeB.attributes != nodeA.attributes);
+ assert_equals(nodeB.attributes.length, nodeA.attributes.length);
+ for (var i = 0, il = nodeA.attributes.length; i < il; ++i) {
+ assert_not_equals(nodeB.attributes[i], nodeA.attributes[i]);
+ assert_equals(nodeB.attributes[i].name, nodeA.attributes[i].name);
+ assert_equals(nodeB.attributes[i].prefix, nodeA.attributes[i].prefix);
+ assert_equals(nodeB.attributes[i].namespaceURI, nodeA.attributes[i].namespaceURI);
+ assert_equals(nodeB.attributes[i].value, nodeA.attributes[i].value);
+ }
+ }
+}
+
+test(function() {
+ var el = document.createElement("foo");
+ el.appendChild(document.createElement("bar"));
+ el.setAttribute("a", "b");
+ el.setAttribute("c", "d");
+ var c = el.cloneNode(false);
+ assert_equal_node(el, c);
+ assert_equals(c.childNodes.length, 0);
+}, "Unprefixed HTML element")
+
+test(function() {
+ var el = document.createElementNS("http://www.w3.org/1999/xhtml", "foo:div");
+ var c = el.cloneNode(false);
+ assert_equal_node(el, c);
+}, "Prefixed HTML element")
+
+test(function() {
+ var el = document.createElementNS("http://www.example.com/", "foo:div");
+ var c = el.cloneNode(false);
+ assert_equal_node(el, c);
+}, "Prefixed non-HTML element")
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Node-compareDocumentPosition.html b/tests/wpt/web-platform-tests/dom/nodes/Node-compareDocumentPosition.html
new file mode 100644
index 00000000000..afae60aad1e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Node-compareDocumentPosition.html
@@ -0,0 +1,87 @@
+<!doctype html>
+<title>Node.compareDocumentPosition() tests</title>
+<link rel=author title="Aryeh Gregor" href=ayg@aryeh.name>
+<div id=log></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../common.js></script>
+<script>
+"use strict";
+
+testNodes.forEach(function(referenceName) {
+ var reference = eval(referenceName);
+ testNodes.forEach(function(otherName) {
+ var other = eval(otherName);
+ test(function() {
+ var result = reference.compareDocumentPosition(other);
+
+ // "If other and reference are the same object, return zero and
+ // terminate these steps."
+ if (other === reference) {
+ assert_equals(result, 0);
+ return;
+ }
+
+ // "If other and reference are not in the same tree, return the result of
+ // adding DOCUMENT_POSITION_DISCONNECTED,
+ // DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC, and either
+ // DOCUMENT_POSITION_PRECEDING or DOCUMENT_POSITION_FOLLOWING, with the
+ // constraint that this is to be consistent, together and terminate these
+ // steps."
+ if (furthestAncestor(reference) !== furthestAncestor(other)) {
+ // TODO: Test that it's consistent.
+ assert_in_array(result, [Node.DOCUMENT_POSITION_DISCONNECTED +
+ Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC +
+ Node.DOCUMENT_POSITION_PRECEDING,
+ Node.DOCUMENT_POSITION_DISCONNECTED +
+ Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC +
+ Node.DOCUMENT_POSITION_FOLLOWING]);
+ return;
+ }
+
+ // "If other is an ancestor of reference, return the result of
+ // adding DOCUMENT_POSITION_CONTAINS to DOCUMENT_POSITION_PRECEDING
+ // and terminate these steps."
+ var ancestor = reference.parentNode;
+ while (ancestor && ancestor !== other) {
+ ancestor = ancestor.parentNode;
+ }
+ if (ancestor === other) {
+ assert_equals(result, Node.DOCUMENT_POSITION_CONTAINS +
+ Node.DOCUMENT_POSITION_PRECEDING);
+ return;
+ }
+
+ // "If other is a descendant of reference, return the result of adding
+ // DOCUMENT_POSITION_CONTAINED_BY to DOCUMENT_POSITION_FOLLOWING and
+ // terminate these steps."
+ ancestor = other.parentNode;
+ while (ancestor && ancestor !== reference) {
+ ancestor = ancestor.parentNode;
+ }
+ if (ancestor === reference) {
+ assert_equals(result, Node.DOCUMENT_POSITION_CONTAINED_BY +
+ Node.DOCUMENT_POSITION_FOLLOWING);
+ return;
+ }
+
+ // "If other is preceding reference return DOCUMENT_POSITION_PRECEDING
+ // and terminate these steps."
+ var prev = previousNode(reference);
+ while (prev && prev !== other) {
+ prev = previousNode(prev);
+ }
+ if (prev === other) {
+ assert_equals(result, Node.DOCUMENT_POSITION_PRECEDING);
+ return;
+ }
+
+ // "Return DOCUMENT_POSITION_FOLLOWING."
+ assert_equals(result, Node.DOCUMENT_POSITION_FOLLOWING);
+ }, referenceName + ".compareDocumentPosition(" + otherName + ")");
+ });
+});
+
+testDiv.parentNode.removeChild(testDiv);
+</script>
+<!-- vim: set expandtab tabstop=2 shiftwidth=2: -->
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Node-constants.html b/tests/wpt/web-platform-tests/dom/nodes/Node-constants.html
new file mode 100644
index 00000000000..33e7c10e73e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Node-constants.html
@@ -0,0 +1,39 @@
+<!doctype html>
+<title>Node constants</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../constants.js"></script>
+<div id="log"></div>
+<script>
+var objects;
+setup(function() {
+ objects = [
+ [Node, "Node interface object"],
+ [Node.prototype, "Node prototype object"],
+ [document.createElement("foo"), "Element object"],
+ [document.createTextNode("bar"), "Text object"]
+ ]
+})
+testConstants(objects, [
+ ["ELEMENT_NODE", 1],
+ ["ATTRIBUTE_NODE", 2],
+ ["TEXT_NODE", 3],
+ ["CDATA_SECTION_NODE", 4],
+ ["ENTITY_REFERENCE_NODE", 5],
+ ["ENTITY_NODE", 6],
+ ["PROCESSING_INSTRUCTION_NODE", 7],
+ ["COMMENT_NODE", 8],
+ ["DOCUMENT_NODE", 9],
+ ["DOCUMENT_TYPE_NODE", 10],
+ ["DOCUMENT_FRAGMENT_NODE", 11],
+ ["NOTATION_NODE", 12]
+], "nodeType")
+testConstants(objects, [
+ ["DOCUMENT_POSITION_DISCONNECTED", 0x01],
+ ["DOCUMENT_POSITION_PRECEDING", 0x02],
+ ["DOCUMENT_POSITION_FOLLOWING", 0x04],
+ ["DOCUMENT_POSITION_CONTAINS", 0x08],
+ ["DOCUMENT_POSITION_CONTAINED_BY", 0x10],
+ ["DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC", 0x20]
+], "createDocumentPosition")
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Node-contains.html b/tests/wpt/web-platform-tests/dom/nodes/Node-contains.html
new file mode 100644
index 00000000000..a3d6448664f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Node-contains.html
@@ -0,0 +1,36 @@
+<!doctype html>
+<title>Node.contains() tests</title>
+<link rel=author title="Aryeh Gregor" href=ayg@aryeh.name>
+<div id=log></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../common.js></script>
+<script>
+"use strict";
+
+testNodes.forEach(function(referenceName) {
+ var reference = eval(referenceName);
+
+ test(function() {
+ assert_false(reference.contains(null));
+ }, referenceName + ".contains(null)");
+
+ testNodes.forEach(function(otherName) {
+ var other = eval(otherName);
+ test(function() {
+ var ancestor = other;
+ while (ancestor && ancestor !== reference) {
+ ancestor = ancestor.parentNode;
+ }
+ if (ancestor === reference) {
+ assert_true(reference.contains(other));
+ } else {
+ assert_false(reference.contains(other));
+ }
+ }, referenceName + ".compareDocumentPosition(" + otherName + ")");
+ });
+});
+
+testDiv.parentNode.removeChild(testDiv);
+</script>
+<!-- vim: set expandtab tabstop=2 shiftwidth=2: -->
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Node-contains.xml b/tests/wpt/web-platform-tests/dom/nodes/Node-contains.xml
new file mode 100644
index 00000000000..b95b7ffd1bd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Node-contains.xml
@@ -0,0 +1,83 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Node.nodeName</title>
+<link rel="author" title="Olli Pettay" href="mailto:Olli@Pettay.fi"/>
+<link rel="author" title="Ms2ger" href="mailto:Ms2ger@gmail.com"/>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id="log"/>
+<div id="test">
+ <input type="button" id="testbutton"/>
+ <a id="link">Link text</a>
+</div>
+<script>
+<![CDATA[
+test(function() {
+ assert_throws(new TypeError(), function() {
+ document.contains();
+ });
+ assert_throws(new TypeError(), function() {
+ document.contains(9);
+ });
+}, "Should throw TypeError if the arguments are wrong.");
+
+test(function() {
+ assert_equals(document.contains(null), false, "Document shouldn't contain null.");
+}, "contains(null) should be false");
+
+test(function() {
+ assert_equals(document.contains(document), true, "Document should contain itself!");
+ assert_equals(document.contains(document.createElement("foo")), false, "Document shouldn't contain element which is't in the document");
+ assert_equals(document.contains(document.createTextNode("foo")), false, "Document shouldn't contain text node which is't in the document");
+}, "document.contains");
+
+test(function() {
+ var tb = document.getElementById("testbutton");
+ assert_equals(tb.contains(tb), true, "Element should contain itself.")
+ assert_equals(document.contains(tb), true, "Document should contain element in it!");
+ assert_equals(document.documentElement.contains(tb), true, "Element should contain element in it!");
+}, "contains with a button");
+
+test(function() {
+ var link = document.getElementById("link");
+ var text = link.firstChild;
+ assert_equals(document.contains(text), true, "Document should contain a text node in it.");
+ assert_equals(link.contains(text), true, "Element should contain a text node in it.");
+ assert_equals(text.contains(text), true, "Text node should contain itself.");
+ assert_equals(text.contains(link), false, "text node shouldn't contain its parent.");
+}, "contains with a text node");
+
+test(function() {
+ var pi = document.createProcessingInstruction("adf", "asd");
+ assert_equals(pi.contains(document), false, "Processing instruction shouldn't contain document");
+ assert_equals(document.contains(pi), false, "Document shouldn't contain newly created processing instruction");
+ document.documentElement.appendChild(pi);
+ document.contains(pi, true, "Document should contain processing instruction");
+}, "contains with a processing instruction");
+
+test(function() {
+ if ("createContextualFragment" in document.createRange()) {
+ var df = document.createRange().createContextualFragment("<div>foo</div>");
+ assert_equals(df.contains(df.firstChild), true, "Document fragment should contain its child");
+ assert_equals(df.contains(df.firstChild.firstChild), true,
+ "Document fragment should contain its descendant");
+ assert_equals(df.contains(df), true, "Document fragment should contain itself.");
+ }
+}, "contains with a document fragment");
+
+test(function() {
+ var d = document.implementation.createHTMLDocument("");
+ assert_equals(document.contains(d), false,
+ "Document shouldn't contain another document.");
+ assert_equals(document.contains(d.createElement("div")), false,
+ "Document shouldn't contain an element from another document.");
+ assert_equals(document.contains(d.documentElement), false,
+ "Document shouldn't contain an element from another document.");
+}, "contaibs with another document");
+]]>
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Node-insertBefore.html b/tests/wpt/web-platform-tests/dom/nodes/Node-insertBefore.html
new file mode 100644
index 00000000000..5e8581472c3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Node-insertBefore.html
@@ -0,0 +1,306 @@
+<!DOCTYPE html>
+<title>Node.insertBefore</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+function testLeafNode(nodeName, createNodeFunction) {
+ test(function() {
+ var node = createNodeFunction();
+ assert_throws(new TypeError(), function() { node.insertBefore(null, null) })
+ }, "Calling insertBefore with a non-Node first argument on a leaf node " + nodeName + " must throw TypeError.")
+ test(function() {
+ var node = createNodeFunction();
+ assert_throws("HIERARCHY_REQUEST_ERR", function() { node.insertBefore(document.createTextNode("fail"), null) })
+ // Would be step 2.
+ assert_throws("HIERARCHY_REQUEST_ERR", function() { node.insertBefore(node, null) })
+ // Would be step 3.
+ assert_throws("HIERARCHY_REQUEST_ERR", function() { node.insertBefore(node, document.createTextNode("child")) })
+ }, "Calling insertBefore an a leaf node " + nodeName + " must throw HIERARCHY_REQUEST_ERR.")
+}
+
+test(function() {
+ // WebIDL.
+ assert_throws(new TypeError(), function() { document.body.insertBefore(null, null) })
+ assert_throws(new TypeError(), function() { document.body.insertBefore(null, document.body.firstChild) })
+ assert_throws(new TypeError(), function() { document.body.insertBefore({'a':'b'}, document.body.firstChild) })
+}, "Calling insertBefore with a non-Node first argument must throw TypeError.")
+
+testLeafNode("DocumentType", function () { return document.doctype; } )
+testLeafNode("Text", function () { return document.createTextNode("Foo") })
+testLeafNode("Comment", function () { return document.createComment("Foo") })
+testLeafNode("ProcessingInstruction", function () { return document.createProcessingInstruction("foo", "bar") })
+
+test(function() {
+ // Step 2.
+ assert_throws("HIERARCHY_REQUEST_ERR", function() { document.body.insertBefore(document.body, document.getElementById("log")) })
+ assert_throws("HIERARCHY_REQUEST_ERR", function() { document.body.insertBefore(document.documentElement, document.getElementById("log")) })
+}, "Calling insertBefore with an inclusive ancestor of the context object must throw HIERARCHY_REQUEST_ERR.")
+
+// Step 3.
+test(function() {
+ var a = document.createElement("div");
+ var b = document.createElement("div");
+ var c = document.createElement("div");
+ assert_throws("NotFoundError", function() {
+ a.insertBefore(b, c);
+ });
+}, "Calling insertBefore with a reference child whose parent is not the context node must throw a NotFoundError.")
+
+// Step 4.1.
+test(function() {
+ var doc = document.implementation.createHTMLDocument("title");
+ var doc2 = document.implementation.createHTMLDocument("title2");
+ assert_throws("HierarchyRequestError", function() {
+ doc.insertBefore(doc2, doc.documentElement);
+ });
+
+ assert_throws("HierarchyRequestError", function() {
+ doc.insertBefore(doc.createTextNode("text"), doc.documentElement);
+ });
+}, "If the context node is a document, inserting a document or text node should throw a HierarchyRequestError.")
+
+// Step 4.2.1.
+test(function() {
+ var doc = document.implementation.createHTMLDocument("title");
+ doc.removeChild(doc.documentElement);
+
+ var df = doc.createDocumentFragment();
+ df.appendChild(doc.createElement("a"));
+ df.appendChild(doc.createElement("b"));
+ assert_throws("HierarchyRequestError", function() {
+ doc.insertBefore(df, null);
+ });
+
+ df = doc.createDocumentFragment();
+ df.appendChild(doc.createTextNode("text"));
+ assert_throws("HierarchyRequestError", function() {
+ doc.insertBefore(df, null);
+ });
+
+ df = doc.createDocumentFragment();
+ df.appendChild(doc.createComment("comment"));
+ df.appendChild(doc.createTextNode("text"));
+ assert_throws("HierarchyRequestError", function() {
+ doc.insertBefore(df, null);
+ });
+}, "If the context node is a document, appending a DocumentFragment that contains a text node or too many elements should throw a HierarchyRequestError.")
+test(function() {
+ var doc = document.implementation.createHTMLDocument("title");
+ doc.removeChild(doc.documentElement);
+
+ var df = doc.createDocumentFragment();
+ df.appendChild(doc.createElement("a"));
+ df.appendChild(doc.createElement("b"));
+ assert_throws("HierarchyRequestError", function() {
+ doc.insertBefore(df, doc.firstChild);
+ });
+
+ df = doc.createDocumentFragment();
+ df.appendChild(doc.createTextNode("text"));
+ assert_throws("HierarchyRequestError", function() {
+ doc.insertBefore(df, doc.firstChild);
+ });
+
+ df = doc.createDocumentFragment();
+ df.appendChild(doc.createComment("comment"));
+ df.appendChild(doc.createTextNode("text"));
+ assert_throws("HierarchyRequestError", function() {
+ doc.insertBefore(df, doc.firstChild);
+ });
+}, "If the context node is a document, inserting a DocumentFragment that contains a text node or too many elements should throw a HierarchyRequestError.")
+
+// Step 4.2.2.
+test(function() {
+ // The context node has an element child.
+ var doc = document.implementation.createHTMLDocument("title");
+ var comment = doc.appendChild(doc.createComment("foo"));
+ assert_array_equals(doc.childNodes, [doc.doctype, doc.documentElement, comment]);
+
+ var df = doc.createDocumentFragment();
+ df.appendChild(doc.createElement("a"));
+ assert_throws("HierarchyRequestError", function() {
+ doc.insertBefore(df, doc.doctype);
+ });
+ assert_throws("HierarchyRequestError", function() {
+ doc.insertBefore(df, doc.documentElement);
+ });
+ assert_throws("HierarchyRequestError", function() {
+ doc.insertBefore(df, comment);
+ });
+ assert_throws("HierarchyRequestError", function() {
+ doc.insertBefore(df, null);
+ });
+}, "If the context node is a document, inserting a DocumentFragment with an element if there already is an element child should throw a HierarchyRequestError.")
+test(function() {
+ // /child/ is a doctype.
+ var doc = document.implementation.createHTMLDocument("title");
+ var comment = doc.insertBefore(doc.createComment("foo"), doc.firstChild);
+ doc.removeChild(doc.documentElement);
+ assert_array_equals(doc.childNodes, [comment, doc.doctype]);
+
+ var df = doc.createDocumentFragment();
+ df.appendChild(doc.createElement("a"));
+ assert_throws("HierarchyRequestError", function() {
+ doc.insertBefore(df, doc.doctype);
+ });
+}, "If the context node is a document and a doctype is following the reference child, inserting a DocumentFragment with an element should throw a HierarchyRequestError.")
+test(function() {
+ // /child/ is not null and a doctype is following /child/.
+ var doc = document.implementation.createHTMLDocument("title");
+ var comment = doc.insertBefore(doc.createComment("foo"), doc.firstChild);
+ doc.removeChild(doc.documentElement);
+ assert_array_equals(doc.childNodes, [comment, doc.doctype]);
+
+ var df = doc.createDocumentFragment();
+ df.appendChild(doc.createElement("a"));
+ assert_throws("HierarchyRequestError", function() {
+ doc.insertBefore(df, comment);
+ });
+}, "If the context node is a document, inserting a DocumentFragment with an element before the doctype should throw a HierarchyRequestError.")
+
+// Step 4.3.
+test(function() {
+ // The context node has an element child.
+ var doc = document.implementation.createHTMLDocument("title");
+ var comment = doc.appendChild(doc.createComment("foo"));
+ assert_array_equals(doc.childNodes, [doc.doctype, doc.documentElement, comment]);
+
+ var a = doc.createElement("a");
+ assert_throws("HierarchyRequestError", function() {
+ doc.insertBefore(a, doc.doctype);
+ });
+ assert_throws("HierarchyRequestError", function() {
+ doc.insertBefore(a, doc.documentElement);
+ });
+ assert_throws("HierarchyRequestError", function() {
+ doc.insertBefore(a, comment);
+ });
+ assert_throws("HierarchyRequestError", function() {
+ doc.insertBefore(a, null);
+ });
+}, "If the context node is a document, inserting an element if there already is an element child should throw a HierarchyRequestError.")
+test(function() {
+ // /child/ is a doctype.
+ var doc = document.implementation.createHTMLDocument("title");
+ var comment = doc.insertBefore(doc.createComment("foo"), doc.firstChild);
+ doc.removeChild(doc.documentElement);
+ assert_array_equals(doc.childNodes, [comment, doc.doctype]);
+
+ var a = doc.createElement("a");
+ assert_throws("HierarchyRequestError", function() {
+ doc.insertBefore(a, doc.doctype);
+ });
+}, "If the context node is a document, inserting an element before the doctype should throw a HierarchyRequestError.")
+test(function() {
+ // /child/ is not null and a doctype is following /child/.
+ var doc = document.implementation.createHTMLDocument("title");
+ var comment = doc.insertBefore(doc.createComment("foo"), doc.firstChild);
+ doc.removeChild(doc.documentElement);
+ assert_array_equals(doc.childNodes, [comment, doc.doctype]);
+
+ var a = doc.createElement("a");
+ assert_throws("HierarchyRequestError", function() {
+ doc.insertBefore(a, comment);
+ });
+}, "If the context node is a document and a doctype is following the reference child, inserting an element should throw a HierarchyRequestError.")
+
+// Step 4.4.
+test(function() {
+ var doc = document.implementation.createHTMLDocument("title");
+ var comment = doc.insertBefore(doc.createComment("foo"), doc.firstChild);
+ assert_array_equals(doc.childNodes, [comment, doc.doctype, doc.documentElement]);
+
+ var doctype = document.implementation.createDocumentType("html", "", "");
+ assert_throws("HierarchyRequestError", function() {
+ doc.insertBefore(doctype, comment);
+ });
+ assert_throws("HierarchyRequestError", function() {
+ doc.insertBefore(doctype, doc.doctype);
+ });
+ assert_throws("HierarchyRequestError", function() {
+ doc.insertBefore(doctype, doc.documentElement);
+ });
+ assert_throws("HierarchyRequestError", function() {
+ doc.insertBefore(doctype, null);
+ });
+}, "If the context node is a document, inserting a doctype if there already is a doctype child should throw a HierarchyRequestError.")
+test(function() {
+ var doc = document.implementation.createHTMLDocument("title");
+ var comment = doc.appendChild(doc.createComment("foo"));
+ doc.removeChild(doc.doctype);
+ assert_array_equals(doc.childNodes, [doc.documentElement, comment]);
+
+ var doctype = document.implementation.createDocumentType("html", "", "");
+ assert_throws("HierarchyRequestError", function() {
+ doc.insertBefore(doctype, comment);
+ });
+}, "If the context node is a document, inserting a doctype after the document element should throw a HierarchyRequestError.")
+test(function() {
+ var doc = document.implementation.createHTMLDocument("title");
+ var comment = doc.appendChild(doc.createComment("foo"));
+ doc.removeChild(doc.doctype);
+ assert_array_equals(doc.childNodes, [doc.documentElement, comment]);
+
+ var doctype = document.implementation.createDocumentType("html", "", "");
+ assert_throws("HierarchyRequestError", function() {
+ doc.insertBefore(doctype, null);
+ });
+}, "If the context node is a document with and element child, appending a doctype should throw a HierarchyRequestError.")
+
+// Step 5.
+test(function() {
+ var df = document.createDocumentFragment();
+ var a = df.appendChild(document.createElement("a"));
+
+ var doc = document.implementation.createHTMLDocument("title");
+ assert_throws("HierarchyRequestError", function() {
+ df.insertBefore(doc, a);
+ });
+ assert_throws("HierarchyRequestError", function() {
+ df.insertBefore(doc, null);
+ });
+
+ var doctype = document.implementation.createDocumentType("html", "", "");
+ assert_throws("HierarchyRequestError", function() {
+ df.insertBefore(doctype, a);
+ });
+ assert_throws("HierarchyRequestError", function() {
+ df.insertBefore(doctype, null);
+ });
+}, "If the context node is a DocumentFragment, inserting a document or a doctype should throw a HierarchyRequestError.")
+test(function() {
+ var el = document.createElement("div");
+ var a = el.appendChild(document.createElement("a"));
+
+ var doc = document.implementation.createHTMLDocument("title");
+ assert_throws("HierarchyRequestError", function() {
+ el.insertBefore(doc, a);
+ });
+ assert_throws("HierarchyRequestError", function() {
+ el.insertBefore(doc, null);
+ });
+
+ var doctype = document.implementation.createDocumentType("html", "", "");
+ assert_throws("HierarchyRequestError", function() {
+ el.insertBefore(doctype, a);
+ });
+ assert_throws("HierarchyRequestError", function() {
+ el.insertBefore(doctype, null);
+ });
+}, "If the context node is an element, inserting a document or a doctype should throw a HierarchyRequestError.")
+
+// Step 7.
+test(function() {
+ var a = document.createElement("div");
+ var b = document.createElement("div");
+ var c = document.createElement("div");
+ a.appendChild(b);
+ a.appendChild(c);
+ assert_array_equals(a.childNodes, [b, c]);
+ assert_equals(a.replaceChild(b, b), b);
+ assert_array_equals(a.childNodes, [b, c]);
+ assert_equals(a.replaceChild(c, c), c);
+ assert_array_equals(a.childNodes, [b, c]);
+}, "Inserting a node before itself should not move the node");
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Node-isEqualNode.xhtml b/tests/wpt/web-platform-tests/dom/nodes/Node-isEqualNode.xhtml
new file mode 100644
index 00000000000..d33406a74cf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Node-isEqualNode.xhtml
@@ -0,0 +1,60 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Node.isEqualNode</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id="log"/>
+<script>
+function testNullHandling(node) {
+ test(function() {
+ assert_false(node.isEqualNode(null))
+ assert_false(node.isEqualNode(undefined))
+ })
+}
+[
+ document.createElement("foo"),
+ document.createTextNode("foo"),
+ document.createProcessingInstruction("foo", "bar"),
+ document.createComment("foo"),
+ document,
+ document.implementation.createDocumentType("html", "", ""),
+ document.createDocumentFragment()
+].forEach(testNullHandling)
+
+test(function() {
+ var a = document.createElement("foo")
+ a.setAttribute("a", "bar")
+ a.setAttribute("b", "baz")
+ var b = document.createElement("foo")
+ b.setAttribute("b", "baz")
+ b.setAttribute("a", "bar")
+ assert_true(a.isEqualNode(b))
+}, "isEqualNode should return true when the attributes are in a different order")
+
+test(function() {
+ var a = document.createElement("foo")
+ a.setAttributeNS("ns", "x:a", "bar")
+ var b = document.createElement("foo")
+ b.setAttributeNS("ns", "y:a", "bar")
+ assert_true(a.isEqualNode(b))
+}, "isEqualNode should return true when the attributes have different prefixes")
+var internalSubset = async_test("isEqualNode should return true when only the internal subsets of DocumentTypes differ.")
+var wait = 2;
+function iframeLoaded() {
+ if (!--wait) {
+ internalSubset.step(function() {
+ var doc1 = document.getElementById("subset1").contentDocument
+ var doc2 = document.getElementById("subset2").contentDocument
+ assert_true(doc1.doctype.isEqualNode(doc2.doctype), "doc1.doctype.isEqualNode(doc2.doctype)")
+ assert_true(doc1.isEqualNode(doc2), "doc1.isEqualNode(doc2)")
+ })
+ internalSubset.done()
+ }
+}
+</script>
+<iframe id="subset1" onload="iframeLoaded()" src="data:application/xml,&lt;!DOCTYPE foo [ &lt;!ELEMENT foo (%23PCDATA)> ]>&lt;foo/>" />
+<iframe id="subset2" onload="iframeLoaded()" src="data:application/xml,&lt;!DOCTYPE foo [ &lt;!ELEMENT foo EMPTY> ]>&lt;foo/>" />
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Node-lookupPrefix.xhtml b/tests/wpt/web-platform-tests/dom/nodes/Node-lookupPrefix.xhtml
new file mode 100644
index 00000000000..50a487c58c6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Node-lookupPrefix.xhtml
@@ -0,0 +1,31 @@
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:x="test">
+<head>
+<title>Node.lookupPrefix</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body xmlns:s="test">
+<div id="log"/>
+<x xmlns:t="test"><!--comment--><?test test?>TEST<x/></x>
+<script>
+function lookupPrefix(node, ns, prefix) {
+ test(function() {
+ assert_equals(node.lookupPrefix(ns), prefix)
+ })
+}
+var x = document.getElementsByTagName("x")[0];
+lookupPrefix(document, "test", "x") // XXX add test for when there is no documentElement
+lookupPrefix(document, null, null)
+lookupPrefix(x, "http://www.w3.org/1999/xhtml", null)
+lookupPrefix(x, "something", null)
+lookupPrefix(x, null, null)
+lookupPrefix(x, "test", "t")
+lookupPrefix(x.parentNode, "test", "s")
+lookupPrefix(x.firstChild, "test", "t")
+lookupPrefix(x.childNodes[1], "test", "t")
+lookupPrefix(x.childNodes[2], "test", "t")
+lookupPrefix(x.lastChild, "test", "t")
+x.parentNode.removeChild(x)
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Node-nodeName.html b/tests/wpt/web-platform-tests/dom/nodes/Node-nodeName.html
new file mode 100644
index 00000000000..911f93455c7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Node-nodeName.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<title>Node.nodeName</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ var HTMLNS = "http://www.w3.org/1999/xhtml",
+ SVGNS = "http://www.w3.org/2000/svg"
+ assert_equals(document.createElementNS(HTMLNS, "I").nodeName, "I")
+ assert_equals(document.createElementNS(HTMLNS, "i").nodeName, "I")
+ assert_equals(document.createElementNS(SVGNS, "svg").nodeName, "svg")
+ assert_equals(document.createElementNS(SVGNS, "SVG").nodeName, "SVG")
+ assert_equals(document.createElementNS(HTMLNS, "x:b").nodeName, "X:B")
+}, "For Element nodes, nodeName should return the same as tagName.")
+test(function() {
+ assert_equals(document.createTextNode("foo").nodeName, "#text")
+}, "For Text nodes, nodeName should return \"#text\".")
+test(function() {
+ assert_equals(document.createComment("foo").nodeName, "#comment")
+}, "For Comment nodes, nodeName should return \"#comment\".")
+test(function() {
+ assert_equals(document.nodeName, "#document")
+}, "For Document nodes, nodeName should return \"#document\".")
+test(function() {
+ assert_equals(document.doctype.nodeName, "html")
+}, "For DocumentType nodes, nodeName should return the name.")
+test(function() {
+ assert_equals(document.createDocumentFragment().nodeName,
+ "#document-fragment")
+}, "For DocumentFragment nodes, nodeName should return \"#document-fragment\".")
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Node-nodeName.xhtml b/tests/wpt/web-platform-tests/dom/nodes/Node-nodeName.xhtml
new file mode 100644
index 00000000000..bc478af8b68
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Node-nodeName.xhtml
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Node.nodeName</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id="log"/>
+<script>
+test(function() {
+ var HTMLNS = "http://www.w3.org/1999/xhtml",
+ SVGNS = "http://www.w3.org/2000/svg"
+ assert_equals(document.createElementNS(HTMLNS, "I").nodeName, "I")
+ assert_equals(document.createElementNS(HTMLNS, "i").nodeName, "i")
+ assert_equals(document.createElementNS(SVGNS, "svg").nodeName, "svg")
+ assert_equals(document.createElementNS(SVGNS, "SVG").nodeName, "SVG")
+ assert_equals(document.createElementNS(HTMLNS, "x:b").nodeName, "x:b")
+}, "For Element nodes, nodeName should return the same as tagName.")
+test(function() {
+ assert_equals(document.createTextNode("foo").nodeName, "#text")
+}, "For Text nodes, nodeName should return \"#text\".")
+test(function() {
+ assert_equals(document.createProcessingInstruction("foo", "bar").nodeName,
+ "foo")
+}, "For ProcessingInstruction nodes, nodeName should return the target.")
+test(function() {
+ assert_equals(document.createComment("foo").nodeName, "#comment")
+}, "For Comment nodes, nodeName should return \"#comment\".")
+test(function() {
+ assert_equals(document.nodeName, "#document")
+}, "For Document nodes, nodeName should return \"#document\".")
+test(function() {
+ assert_equals(document.doctype.nodeName, "html")
+}, "For DocumentType nodes, nodeName should return the name.")
+test(function() {
+ assert_equals(document.createDocumentFragment().nodeName,
+ "#document-fragment")
+}, "For DocumentFragment nodes, nodeName should return \"#document-fragment\".")
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Node-nodeValue.html b/tests/wpt/web-platform-tests/dom/nodes/Node-nodeValue.html
new file mode 100644
index 00000000000..79ce80b8756
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Node-nodeValue.html
@@ -0,0 +1,71 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Node.nodeValue</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-node-nodevalue">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function() {
+ var the_text = document.createTextNode("A span!");
+ assert_equals(the_text.nodeValue, "A span!");
+ assert_equals(the_text.data, "A span!");
+ the_text.nodeValue = "test again";
+ assert_equals(the_text.nodeValue, "test again");
+ assert_equals(the_text.data, "test again");
+ the_text.nodeValue = null;
+ assert_equals(the_text.nodeValue, "");
+ assert_equals(the_text.data, "");
+}, "Text.nodeValue");
+
+test(function() {
+ var the_comment = document.createComment("A comment!");
+ assert_equals(the_comment.nodeValue, "A comment!");
+ assert_equals(the_comment.data, "A comment!");
+ the_comment.nodeValue = "test again";
+ assert_equals(the_comment.nodeValue, "test again");
+ assert_equals(the_comment.data, "test again");
+ the_comment.nodeValue = null;
+ assert_equals(the_comment.nodeValue, "");
+ assert_equals(the_comment.data, "");
+}, "Comment.nodeValue");
+
+test(function() {
+ var the_pi = document.createProcessingInstruction("pi", "A PI!");
+ assert_equals(the_pi.nodeValue, "A PI!");
+ assert_equals(the_pi.data, "A PI!");
+ the_pi.nodeValue = "test again";
+ assert_equals(the_pi.nodeValue, "test again");
+ assert_equals(the_pi.data, "test again");
+ the_pi.nodeValue = null;
+ assert_equals(the_pi.nodeValue, "");
+ assert_equals(the_pi.data, "");
+}, "ProcessingInstruction.nodeValue");
+
+test(function() {
+ var the_link = document.createElement("a");
+ assert_equals(the_link.nodeValue, null);
+ the_link.nodeValue = "foo";
+ assert_equals(the_link.nodeValue, null);
+}, "Element.nodeValue");
+
+test(function() {
+ assert_equals(document.nodeValue, null);
+ document.nodeValue = "foo";
+ assert_equals(document.nodeValue, null);
+}, "Document.nodeValue");
+
+test(function() {
+ var the_frag = document.createDocumentFragment();
+ assert_equals(the_frag.nodeValue, null);
+ the_frag.nodeValue = "foo";
+ assert_equals(the_frag.nodeValue, null);
+}, "DocumentFragment.nodeValue");
+
+test(function() {
+ var the_doctype = document.doctype;
+ assert_equals(the_doctype.nodeValue, null);
+ the_doctype.nodeValue = "foo";
+ assert_equals(the_doctype.nodeValue, null);
+}, "DocumentType.nodeValue");
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Node-normalize.html b/tests/wpt/web-platform-tests/dom/nodes/Node-normalize.html
new file mode 100644
index 00000000000..7598852e60a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Node-normalize.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<title>Node.normalize()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+test(function() {
+ var df = document.createDocumentFragment(),
+ t1 = document.createTextNode("1"),
+ t2 = document.createTextNode("2"),
+ t3 = document.createTextNode("3"),
+ t4 = document.createTextNode("4")
+ df.appendChild(t1)
+ df.appendChild(t2)
+ assert_equals(df.childNodes.length, 2)
+ assert_equals(df.textContent, "12")
+ var el = document.createElement('x')
+ df.appendChild(el)
+ el.appendChild(t3)
+ el.appendChild(t4)
+ document.normalize()
+ assert_equals(el.childNodes.length, 2)
+ assert_equals(el.textContent, "34")
+ assert_equals(df.childNodes.length, 3)
+ assert_equals(t1.data, "1")
+ df.normalize()
+ assert_equals(df.childNodes.length, 2)
+ assert_equals(df.firstChild, t1)
+ assert_equals(t1.data, "12")
+ assert_equals(t2.data, "2")
+ assert_equals(el.firstChild, t3)
+ assert_equals(t3.data, "34")
+ assert_equals(t4.data, "4")
+})
+
+// https://www.w3.org/Bugs/Public/show_bug.cgi?id=19837
+test(function() {
+ var div = document.createElement("div")
+ var t1 = div.appendChild(document.createTextNode(""))
+ var t2 = div.appendChild(document.createTextNode("a"))
+ var t3 = div.appendChild(document.createTextNode(""))
+ assert_array_equals(div.childNodes, [t1, t2, t3])
+ div.normalize();
+ assert_array_equals(div.childNodes, [t2])
+}, "Empty text nodes separated by a non-empty text node")
+test(function() {
+ var div = document.createElement("div")
+ var t1 = div.appendChild(document.createTextNode(""))
+ var t2 = div.appendChild(document.createTextNode(""))
+ assert_array_equals(div.childNodes, [t1, t2])
+ div.normalize();
+ assert_array_equals(div.childNodes, [])
+}, "Empty text nodes")
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Node-parentElement.html b/tests/wpt/web-platform-tests/dom/nodes/Node-parentElement.html
new file mode 100644
index 00000000000..8aedbc0960d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Node-parentElement.html
@@ -0,0 +1,83 @@
+<!DOCTYPE html>
+<title>Node.parentElement</title>
+<link rel="stylesheet" href="/resources/testharness.css">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ assert_equals(document.parentElement, null)
+}, "When the parent is null, parentElement should be null")
+test(function() {
+ assert_equals(document.doctype.parentElement, null)
+}, "When the parent is a document, parentElement should be null (doctype)")
+test(function() {
+ assert_equals(document.documentElement.parentElement, null)
+}, "When the parent is a document, parentElement should be null (element)")
+test(function() {
+ var comment = document.appendChild(document.createComment("foo"))
+ assert_equals(comment.parentElement, null)
+}, "When the parent is a document, parentElement should be null (comment)")
+test(function() {
+ var df = document.createDocumentFragment()
+ assert_equals(df.parentElement, null)
+ var el = document.createElement("div")
+ assert_equals(el.parentElement, null)
+ df.appendChild(el)
+ assert_equals(el.parentNode, df)
+ assert_equals(el.parentElement, null)
+}, "parentElement should return null for children of DocumentFragments (element)")
+test(function() {
+ var df = document.createDocumentFragment()
+ assert_equals(df.parentElement, null)
+ var text = document.createTextNode("bar")
+ assert_equals(text.parentElement, null)
+ df.appendChild(text)
+ assert_equals(text.parentNode, df)
+ assert_equals(text.parentElement, null)
+}, "parentElement should return null for children of DocumentFragments (text)")
+test(function() {
+ var df = document.createDocumentFragment()
+ var parent = document.createElement("div")
+ df.appendChild(parent)
+ var el = document.createElement("div")
+ assert_equals(el.parentElement, null)
+ parent.appendChild(el)
+ assert_equals(el.parentElement, parent)
+}, "parentElement should work correctly with DocumentFragments (element)")
+test(function() {
+ var df = document.createDocumentFragment()
+ var parent = document.createElement("div")
+ df.appendChild(parent)
+ var text = document.createTextNode("bar")
+ assert_equals(text.parentElement, null)
+ parent.appendChild(text)
+ assert_equals(text.parentElement, parent)
+}, "parentElement should work correctly with DocumentFragments (text)")
+test(function() {
+ var parent = document.createElement("div")
+ var el = document.createElement("div")
+ assert_equals(el.parentElement, null)
+ parent.appendChild(el)
+ assert_equals(el.parentElement, parent)
+}, "parentElement should work correctly in disconnected subtrees (element)")
+test(function() {
+ var parent = document.createElement("div")
+ var text = document.createTextNode("bar")
+ assert_equals(text.parentElement, null)
+ parent.appendChild(text)
+ assert_equals(text.parentElement, parent)
+}, "parentElement should work correctly in disconnected subtrees (text)")
+test(function() {
+ var el = document.createElement("div")
+ assert_equals(el.parentElement, null)
+ document.body.appendChild(el)
+ assert_equals(el.parentElement, document.body)
+}, "parentElement should work correctly in a document (element)")
+test(function() {
+ var text = document.createElement("div")
+ assert_equals(text.parentElement, null)
+ document.body.appendChild(text)
+ assert_equals(text.parentElement, document.body)
+}, "parentElement should work correctly in a document (text)")
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Node-parentNode-iframe.html b/tests/wpt/web-platform-tests/dom/nodes/Node-parentNode-iframe.html
new file mode 100644
index 00000000000..88bc5ab4365
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Node-parentNode-iframe.html
@@ -0,0 +1 @@
+<a name='c'>c</a> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Node-parentNode.html b/tests/wpt/web-platform-tests/dom/nodes/Node-parentNode.html
new file mode 100644
index 00000000000..cff61786276
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Node-parentNode.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<title>Node.parentNode</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+// XXX need to test for more node types
+test(function() {
+ assert_equals(document.parentNode, null)
+}, "Document")
+test(function() {
+ assert_equals(document.doctype.parentNode, document)
+}, "Doctype")
+test(function() {
+ assert_equals(document.documentElement.parentNode, document)
+}, "Root element")
+test(function() {
+ var el = document.createElement("div")
+ assert_equals(el.parentNode, null)
+ document.body.appendChild(el)
+ assert_equals(el.parentNode, document.body)
+}, "Element")
+var t = async_test("Removed iframe");
+function testIframe(iframe) {
+ t.step(function() {
+ var doc = iframe.contentDocument;
+ iframe.parentNode.removeChild(iframe);
+ assert_equals(doc.firstChild.parentNode, doc);
+ });
+ t.done();
+}
+</script>
+<iframe id=a src="Node-parentNode-iframe.html" onload="testIframe(this)"></iframe>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Node-properties.html b/tests/wpt/web-platform-tests/dom/nodes/Node-properties.html
new file mode 100644
index 00000000000..798ba14d544
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Node-properties.html
@@ -0,0 +1,689 @@
+<!doctype html>
+<title>Node assorted property tests</title>
+<link rel=author title="Aryeh Gregor" href=ayg@aryeh.name>
+<meta charset=utf-8>
+<div id=log></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../common.js></script>
+<script>
+"use strict";
+/**
+ * First we define a data structure to tell us what tests to run. The keys
+ * will be eval()ed, and are mostly global variables defined in common.js. The
+ * values are objects, which maps properties to expected values. So
+ *
+ * foo: {
+ * bar: "baz",
+ * quz: 7,
+ * },
+ *
+ * will test that eval("foo.bar") === "baz" and eval("foo.quz") === 7. "foo"
+ * and "bar" could thus be expressions, like "document.documentElement" and
+ * "childNodes[4]" respectively.
+ *
+ * To avoid repetition, some values are automatically added based on others.
+ * For instance, if we specify nodeType: Node.TEXT_NODE, we'll automatically
+ * also test nodeName: "#text". This is handled by code after this variable is
+ * defined.
+ */
+var expected = {
+ testDiv: {
+ // Node
+ nodeType: Node.ELEMENT_NODE,
+ ownerDocument: document,
+ parentNode: document.body,
+ parentElement: document.body,
+ "childNodes.length": 6,
+ "childNodes[0]": paras[0],
+ "childNodes[1]": paras[1],
+ "childNodes[2]": paras[2],
+ "childNodes[3]": paras[3],
+ "childNodes[4]": paras[4],
+ "childNodes[5]": comment,
+ previousSibling: null,
+ nextSibling: document.getElementById("log"),
+ textContent: "A\u0308b\u0308c\u0308d\u0308e\u0308f\u0308g\u0308h\u0308\nIjklmnop\nQrstuvwxYzabcdefGhijklmn",
+
+ // Element
+ namespaceURI: "http://www.w3.org/1999/xhtml",
+ prefix: null,
+ localName: "div",
+ tagName: "DIV",
+ id: "test",
+ "children[0]": paras[0],
+ "children[1]": paras[1],
+ "children[2]": paras[2],
+ "children[3]": paras[3],
+ "children[4]": paras[4],
+ previousElementSibling: null,
+ // nextSibling isn't explicitly set
+ //nextElementSibling: ,
+ childElementCount: 5,
+ },
+ detachedDiv: {
+ // Node
+ nodeType: Node.ELEMENT_NODE,
+ ownerDocument: document,
+ parentNode: null,
+ parentElement: null,
+ "childNodes.length": 2,
+ "childNodes[0]": detachedPara1,
+ "childNodes[1]": detachedPara2,
+ previousSibling: null,
+ nextSibling: null,
+ textContent: "OpqrstuvWxyzabcd",
+
+ // Element
+ namespaceURI: "http://www.w3.org/1999/xhtml",
+ prefix: null,
+ localName: "div",
+ tagName: "DIV",
+ "children[0]": detachedPara1,
+ "children[1]": detachedPara2,
+ previousElementSibling: null,
+ nextElementSibling: null,
+ childElementCount: 2,
+ },
+ detachedPara1: {
+ // Node
+ nodeType: Node.ELEMENT_NODE,
+ ownerDocument: document,
+ parentNode: detachedDiv,
+ parentElement: detachedDiv,
+ "childNodes.length": 1,
+ previousSibling: null,
+ nextSibling: detachedPara2,
+ textContent: "Opqrstuv",
+
+ // Element
+ namespaceURI: "http://www.w3.org/1999/xhtml",
+ prefix: null,
+ localName: "p",
+ tagName: "P",
+ previousElementSibling: null,
+ nextElementSibling: detachedPara2,
+ childElementCount: 0,
+ },
+ detachedPara2: {
+ // Node
+ nodeType: Node.ELEMENT_NODE,
+ ownerDocument: document,
+ parentNode: detachedDiv,
+ parentElement: detachedDiv,
+ "childNodes.length": 1,
+ previousSibling: detachedPara1,
+ nextSibling: null,
+ textContent: "Wxyzabcd",
+
+ // Element
+ namespaceURI: "http://www.w3.org/1999/xhtml",
+ prefix: null,
+ localName: "p",
+ tagName: "P",
+ previousElementSibling: detachedPara1,
+ nextElementSibling: null,
+ childElementCount: 0,
+ },
+ document: {
+ // Node
+ nodeType: Node.DOCUMENT_NODE,
+ "childNodes.length": 2,
+ "childNodes[0]": document.doctype,
+ "childNodes[1]": document.documentElement,
+
+ // Document
+ URL: String(location),
+ compatMode: "CSS1Compat",
+ characterSet: "UTF-8",
+ inputEncoding: "UTF-8",
+ contentType: "text/html",
+ doctype: doctype,
+ //documentElement: ,
+ },
+ foreignDoc: {
+ // Node
+ nodeType: Node.DOCUMENT_NODE,
+ "childNodes.length": 3,
+ "childNodes[0]": foreignDoc.doctype,
+ "childNodes[1]": foreignDoc.documentElement,
+ "childNodes[2]": foreignComment,
+
+ // Document
+ URL: "about:blank",
+ compatMode: "CSS1Compat",
+ characterSet: "UTF-8",
+ inputEncoding: "UTF-8",
+ contentType: "text/html",
+ //doctype: ,
+ //documentElement: ,
+ },
+ foreignPara1: {
+ // Node
+ nodeType: Node.ELEMENT_NODE,
+ ownerDocument: foreignDoc,
+ parentNode: foreignDoc.body,
+ parentElement: foreignDoc.body,
+ "childNodes.length": 1,
+ previousSibling: null,
+ nextSibling: foreignPara2,
+ textContent: "Efghijkl",
+
+ // Element
+ namespaceURI: "http://www.w3.org/1999/xhtml",
+ prefix: null,
+ localName: "p",
+ tagName: "P",
+ previousElementSibling: null,
+ nextElementSibling: foreignPara2,
+ childElementCount: 0,
+ },
+ foreignPara2: {
+ // Node
+ nodeType: Node.ELEMENT_NODE,
+ ownerDocument: foreignDoc,
+ parentNode: foreignDoc.body,
+ parentElement: foreignDoc.body,
+ "childNodes.length": 1,
+ previousSibling: foreignPara1,
+ nextSibling: foreignTextNode,
+ textContent: "Mnopqrst",
+
+ // Element
+ namespaceURI: "http://www.w3.org/1999/xhtml",
+ prefix: null,
+ localName: "p",
+ tagName: "P",
+ previousElementSibling: foreignPara1,
+ nextElementSibling: null,
+ childElementCount: 0,
+ },
+ xmlDoc: {
+ // Node
+ nodeType: Node.DOCUMENT_NODE,
+ "childNodes.length": 4,
+ "childNodes[0]": xmlDoctype,
+ "childNodes[1]": xmlElement,
+ "childNodes[2]": processingInstruction,
+ "childNodes[3]": xmlComment,
+
+ // Document
+ URL: "about:blank",
+ compatMode: "CSS1Compat",
+ characterSet: "UTF-8",
+ inputEncoding: "UTF-8",
+ contentType: "application/xml",
+ //doctype: ,
+ //documentElement: ,
+ },
+ xmlElement: {
+ // Node
+ nodeType: Node.ELEMENT_NODE,
+ ownerDocument: xmlDoc,
+ parentNode: xmlDoc,
+ parentElement: null,
+ "childNodes.length": 1,
+ "childNodes[0]": xmlTextNode,
+ previousSibling: xmlDoctype,
+ nextSibling: processingInstruction,
+ textContent: "do re mi fa so la ti",
+
+ // Element
+ namespaceURI: "http://www.w3.org/1999/xhtml",
+ prefix: null,
+ localName: "igiveuponcreativenames",
+ tagName: "igiveuponcreativenames",
+ previousElementSibling: null,
+ nextElementSibling: null,
+ childElementCount: 0,
+ },
+ detachedXmlElement: {
+ // Node
+ nodeType: Node.ELEMENT_NODE,
+ ownerDocument: xmlDoc,
+ parentNode: null,
+ parentElement: null,
+ "childNodes.length": 0,
+ previousSibling: null,
+ nextSibling: null,
+ textContent: "",
+
+ // Element
+ namespaceURI: "http://www.w3.org/1999/xhtml",
+ prefix: null,
+ localName: "everyone-hates-hyphenated-element-names",
+ tagName: "everyone-hates-hyphenated-element-names",
+ previousElementSibling: null,
+ nextElementSibling: null,
+ childElementCount: 0,
+ },
+ detachedTextNode: {
+ // Node
+ nodeType: Node.TEXT_NODE,
+ ownerDocument: document,
+ parentNode: null,
+ parentElement: null,
+ previousSibling: null,
+ nextSibling: null,
+ nodeValue: "Uvwxyzab",
+
+ // Text
+ wholeText: "Uvwxyzab",
+ },
+ foreignTextNode: {
+ // Node
+ nodeType: Node.TEXT_NODE,
+ ownerDocument: foreignDoc,
+ parentNode: foreignDoc.body,
+ parentElement: foreignDoc.body,
+ previousSibling: foreignPara2,
+ nextSibling: null,
+ nodeValue: "I admit that I harbor doubts about whether we really need so many things to test, but it's too late to stop now.",
+
+ // Text
+ wholeText: "I admit that I harbor doubts about whether we really need so many things to test, but it's too late to stop now.",
+ },
+ detachedForeignTextNode: {
+ // Node
+ nodeType: Node.TEXT_NODE,
+ ownerDocument: foreignDoc,
+ parentNode: null,
+ parentElement: null,
+ previousSibling: null,
+ nextSibling: null,
+ nodeValue: "Cdefghij",
+
+ // Text
+ wholeText: "Cdefghij",
+ },
+ xmlTextNode: {
+ // Node
+ nodeType: Node.TEXT_NODE,
+ ownerDocument: xmlDoc,
+ parentNode: xmlElement,
+ parentElement: xmlElement,
+ previousSibling: null,
+ nextSibling: null,
+ nodeValue: "do re mi fa so la ti",
+
+ // Text
+ wholeText: "do re mi fa so la ti",
+ },
+ detachedXmlTextNode: {
+ // Node
+ nodeType: Node.TEXT_NODE,
+ ownerDocument: xmlDoc,
+ parentNode: null,
+ parentElement: null,
+ previousSibling: null,
+ nextSibling: null,
+ nodeValue: "Klmnopqr",
+
+ // Text
+ wholeText: "Klmnopqr",
+ },
+ processingInstruction: {
+ // Node
+ nodeType: Node.PROCESSING_INSTRUCTION_NODE,
+ ownerDocument: xmlDoc,
+ parentNode: xmlDoc,
+ parentElement: null,
+ previousSibling: xmlElement,
+ nextSibling: xmlComment,
+ nodeValue: 'Did you know that ":syn sync fromstart" is very useful when using vim to edit large amounts of JavaScript embedded in HTML?',
+
+ // ProcessingInstruction
+ target: "somePI",
+ },
+ detachedProcessingInstruction: {
+ // Node
+ nodeType: Node.PROCESSING_INSTRUCTION_NODE,
+ ownerDocument: xmlDoc,
+ parentNode: null,
+ parentElement: null,
+ previousSibling: null,
+ nextSibling: null,
+ nodeValue: "chirp chirp chirp",
+
+ // ProcessingInstruction
+ target: "whippoorwill",
+ },
+ comment: {
+ // Node
+ nodeType: Node.COMMENT_NODE,
+ ownerDocument: document,
+ parentNode: testDiv,
+ parentElement: testDiv,
+ previousSibling: paras[4],
+ nextSibling: null,
+ nodeValue: "Alphabet soup?",
+ },
+ detachedComment: {
+ // Node
+ nodeType: Node.COMMENT_NODE,
+ ownerDocument: document,
+ parentNode: null,
+ parentElement: null,
+ previousSibling: null,
+ nextSibling: null,
+ nodeValue: "Stuvwxyz",
+ },
+ foreignComment: {
+ // Node
+ nodeType: Node.COMMENT_NODE,
+ ownerDocument: foreignDoc,
+ parentNode: foreignDoc,
+ parentElement: null,
+ previousSibling: foreignDoc.documentElement,
+ nextSibling: null,
+ nodeValue: '"Commenter" and "commentator" mean different things. I\'ve seen non-native speakers trip up on this.',
+ },
+ detachedForeignComment: {
+ // Node
+ nodeType: Node.COMMENT_NODE,
+ ownerDocument: foreignDoc,
+ parentNode: null,
+ parentElement: null,
+ previousSibling: null,
+ nextSibling: null,
+ nodeValue: "אריה יהודה",
+ },
+ xmlComment: {
+ // Node
+ nodeType: Node.COMMENT_NODE,
+ ownerDocument: xmlDoc,
+ parentNode: xmlDoc,
+ parentElement: null,
+ previousSibling: processingInstruction,
+ nextSibling: null,
+ nodeValue: "I maliciously created a comment that will break incautious XML serializers, but Firefox threw an exception, so all I got was this lousy T-shirt",
+ },
+ detachedXmlComment: {
+ // Node
+ nodeType: Node.COMMENT_NODE,
+ ownerDocument: xmlDoc,
+ parentNode: null,
+ parentElement: null,
+ previousSibling: null,
+ nextSibling: null,
+ nodeValue: "בן חיים אליעזר",
+ },
+ docfrag: {
+ // Node
+ nodeType: Node.DOCUMENT_FRAGMENT_NODE,
+ ownerDocument: document,
+ "childNodes.length": 0,
+ textContent: "",
+ },
+ foreignDocfrag: {
+ // Node
+ nodeType: Node.DOCUMENT_FRAGMENT_NODE,
+ ownerDocument: foreignDoc,
+ "childNodes.length": 0,
+ textContent: "",
+ },
+ xmlDocfrag: {
+ // Node
+ nodeType: Node.DOCUMENT_FRAGMENT_NODE,
+ ownerDocument: xmlDoc,
+ "childNodes.length": 0,
+ textContent: "",
+ },
+ doctype: {
+ // Node
+ nodeType: Node.DOCUMENT_TYPE_NODE,
+ ownerDocument: document,
+ parentNode: document,
+ previousSibling: null,
+ nextSibling: document.documentElement,
+
+ // DocumentType
+ name: "html",
+ publicId: "",
+ systemId: "",
+ },
+ foreignDoctype: {
+ // Node
+ nodeType: Node.DOCUMENT_TYPE_NODE,
+ ownerDocument: foreignDoc,
+ parentNode: foreignDoc,
+ previousSibling: null,
+ nextSibling: foreignDoc.documentElement,
+
+ // DocumentType
+ name: "html",
+ publicId: "",
+ systemId: "",
+ },
+ xmlDoctype: {
+ // Node
+ nodeType: Node.DOCUMENT_TYPE_NODE,
+ ownerDocument: xmlDoc,
+ parentNode: xmlDoc,
+ previousSibling: null,
+ nextSibling: xmlElement,
+
+ // DocumentType
+ name: "qorflesnorf",
+ publicId: "abcde",
+ systemId: "x\"'y",
+ },
+ "paras[0]": {
+ // Node
+ nodeType: Node.ELEMENT_NODE,
+ ownerDocument: document,
+ parentNode: testDiv,
+ parentElement: testDiv,
+ "childNodes.length": 1,
+ previousSibling: null,
+ nextSibling: paras[1],
+ textContent: "A\u0308b\u0308c\u0308d\u0308e\u0308f\u0308g\u0308h\u0308\n",
+
+ // Element
+ namespaceURI: "http://www.w3.org/1999/xhtml",
+ prefix: null,
+ localName: "p",
+ tagName: "P",
+ id: "a",
+ previousElementSibling: null,
+ nextElementSibling: paras[1],
+ childElementCount: 0,
+ },
+ "paras[1]": {
+ // Node
+ nodeType: Node.ELEMENT_NODE,
+ ownerDocument: document,
+ parentNode: testDiv,
+ parentElement: testDiv,
+ "childNodes.length": 1,
+ previousSibling: paras[0],
+ nextSibling: paras[2],
+ textContent: "Ijklmnop\n",
+
+ // Element
+ namespaceURI: "http://www.w3.org/1999/xhtml",
+ prefix: null,
+ localName: "p",
+ tagName: "P",
+ id: "b",
+ previousElementSibling: paras[0],
+ nextElementSibling: paras[2],
+ childElementCount: 0,
+ },
+ "paras[2]": {
+ // Node
+ nodeType: Node.ELEMENT_NODE,
+ ownerDocument: document,
+ parentNode: testDiv,
+ parentElement: testDiv,
+ "childNodes.length": 1,
+ previousSibling: paras[1],
+ nextSibling: paras[3],
+ textContent: "Qrstuvwx",
+
+ // Element
+ namespaceURI: "http://www.w3.org/1999/xhtml",
+ prefix: null,
+ localName: "p",
+ tagName: "P",
+ id: "c",
+ previousElementSibling: paras[1],
+ nextElementSibling: paras[3],
+ childElementCount: 0,
+ },
+ "paras[3]": {
+ // Node
+ nodeType: Node.ELEMENT_NODE,
+ ownerDocument: document,
+ parentNode: testDiv,
+ parentElement: testDiv,
+ "childNodes.length": 1,
+ previousSibling: paras[2],
+ nextSibling: paras[4],
+ textContent: "Yzabcdef",
+
+ // Element
+ namespaceURI: "http://www.w3.org/1999/xhtml",
+ prefix: null,
+ localName: "p",
+ tagName: "P",
+ id: "d",
+ previousElementSibling: paras[2],
+ nextElementSibling: paras[4],
+ childElementCount: 0,
+ },
+ "paras[4]": {
+ // Node
+ nodeType: Node.ELEMENT_NODE,
+ ownerDocument: document,
+ parentNode: testDiv,
+ parentElement: testDiv,
+ "childNodes.length": 1,
+ previousSibling: paras[3],
+ nextSibling: comment,
+ textContent: "Ghijklmn",
+
+ // Element
+ namespaceURI: "http://www.w3.org/1999/xhtml",
+ prefix: null,
+ localName: "p",
+ tagName: "P",
+ id: "e",
+ previousElementSibling: paras[3],
+ nextElementSibling: null,
+ childElementCount: 0,
+ },
+};
+
+for (var node in expected) {
+ // Now we set various default values by node type.
+ switch (expected[node].nodeType) {
+ case Node.ELEMENT_NODE:
+ expected[node].nodeName = expected[node].tagName;
+ expected[node].nodeValue = null;
+ expected[node]["children.length"] = expected[node].childElementCount;
+
+ if (expected[node].id === undefined) {
+ expected[node].id = "";
+ }
+ if (expected[node].className === undefined) {
+ expected[node].className = "";
+ }
+
+ var len = expected[node].childElementCount;
+ if (len === 0) {
+ expected[node].firstElementChild =
+ expected[node].lastElementChild = null;
+ } else {
+ // If we have expectations for the first/last child in children,
+ // use those. Otherwise, at least check that .firstElementChild ==
+ // .children[0] and .lastElementChild == .children[len - 1], even
+ // if we aren't sure what they should be.
+ expected[node].firstElementChild = expected[node]["children[0]"]
+ ? expected[node]["children[0]"]
+ : eval(node).children[0];
+ expected[node].lastElementChild =
+ expected[node]["children[" + (len - 1) + "]"]
+ ? expected[node]["children[" + (len - 1) + "]"]
+ : eval(node).children[len - 1];
+ }
+ break;
+
+ case Node.TEXT_NODE:
+ expected[node].nodeName = "#text";
+ expected[node]["childNodes.length"] = 0;
+ expected[node].textContent = expected[node].data =
+ expected[node].nodeValue;
+ expected[node].length = expected[node].nodeValue.length;
+ break;
+
+ case Node.PROCESSING_INSTRUCTION_NODE:
+ expected[node].nodeName = expected[node].target;
+ expected[node]["childNodes.length"] = 0;
+ expected[node].textContent = expected[node].data =
+ expected[node].nodeValue;
+ expected[node].length = expected[node].nodeValue.length;
+ break;
+
+ case Node.COMMENT_NODE:
+ expected[node].nodeName = "#comment";
+ expected[node]["childNodes.length"] = 0;
+ expected[node].textContent = expected[node].data =
+ expected[node].nodeValue;
+ expected[node].length = expected[node].nodeValue.length;
+ break;
+
+ case Node.DOCUMENT_NODE:
+ expected[node].nodeName = "#document";
+ expected[node].ownerDocument = expected[node].parentNode =
+ expected[node].parentElement = expected[node].previousSibling =
+ expected[node].nextSibling = expected[node].nodeValue =
+ expected[node].textContent = null;
+ expected[node].documentURI = expected[node].URL;
+ break;
+
+ case Node.DOCUMENT_TYPE_NODE:
+ expected[node].nodeName = expected[node].name;
+ expected[node]["childNodes.length"] = 0;
+ expected[node].parentElement = expected[node].nodeValue =
+ expected[node].textContent = null;
+ break;
+
+ case Node.DOCUMENT_FRAGMENT_NODE:
+ expected[node].nodeName = "#document-fragment";
+ expected[node].parentNode = expected[node].parentElement =
+ expected[node].previousSibling = expected[node].nextSibling =
+ expected[node].nodeValue = null;
+ break;
+ }
+
+ // Now we set some further default values that are independent of node
+ // type.
+ var len = expected[node]["childNodes.length"];
+ if (len === 0) {
+ expected[node].firstChild = expected[node].lastChild = null;
+ } else {
+ // If we have expectations for the first/last child in childNodes, use
+ // those. Otherwise, at least check that .firstChild == .childNodes[0]
+ // and .lastChild == .childNodes[len - 1], even if we aren't sure what
+ // they should be.
+ expected[node].firstChild = expected[node]["childNodes[0]"]
+ ? expected[node]["childNodes[0]"]
+ : eval(node).childNodes[0];
+ expected[node].lastChild =
+ expected[node]["childNodes[" + (len - 1) + "]"]
+ ? expected[node]["childNodes[" + (len - 1) + "]"]
+ : eval(node).childNodes[len - 1];
+ }
+ expected[node]["hasChildNodes()"] = !!expected[node]["childNodes.length"];
+
+ // Finally, we test!
+ for (var prop in expected[node]) {
+ test(function() {
+ assert_equals(eval(node + "." + prop), expected[node][prop]);
+ }, node + "." + prop);
+ }
+}
+
+testDiv.parentNode.removeChild(testDiv);
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Node-removeChild.html b/tests/wpt/web-platform-tests/dom/nodes/Node-removeChild.html
new file mode 100644
index 00000000000..fb225832220
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Node-removeChild.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<title>Node.removeChild</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="creators.js"></script>
+<div id="log"></div>
+<iframe src=about:blank></iframe>
+<script>
+var documents = [
+ [function() { return document }, "the main document"],
+ [function() { return frames[0].document }, "a frame document"],
+ [function() { return document.implementation.createHTMLDocument() },
+ "a synthetic document"],
+];
+
+documents.forEach(function(d) {
+ var get = d[0], description = d[1]
+ for (var p in creators) {
+ var creator = creators[p];
+ test(function() {
+ var doc = get();
+ var s = doc[creator]("a")
+ assert_equals(s.ownerDocument, doc)
+ assert_throws("NOT_FOUND_ERR", function() { document.body.removeChild(s) })
+ assert_equals(s.ownerDocument, doc)
+ }, "Passing a detached " + p + " from " + description +
+ " to removeChild should not affect it.")
+
+ test(function() {
+ var doc = get();
+ var s = doc[creator]("b")
+ doc.documentElement.appendChild(s)
+ assert_equals(s.ownerDocument, doc)
+ assert_throws("NOT_FOUND_ERR", function() { document.body.removeChild(s) })
+ assert_equals(s.ownerDocument, doc)
+ }, "Passing a non-detached " + p + " from " + description +
+ " to removeChild should not affect it.")
+
+ test(function() {
+ var doc = get();
+ var s = doc[creator]("test")
+ doc.body.appendChild(s)
+ assert_equals(s.ownerDocument, doc)
+ assert_throws("NOT_FOUND_ERR", function() { s.removeChild(doc) })
+ }, "Calling removeChild on a " + p + " from " + description +
+ " with no children should throw NOT_FOUND_ERR.")
+ }
+});
+
+test(function() {
+ assert_throws(new TypeError(), function() { document.body.removeChild(null) })
+ assert_throws(new TypeError(), function() { document.body.removeChild({'a':'b'}) })
+}, "Passing a value that is not a Node reference to removeChild should throw TypeError.")
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Node-replaceChild.html b/tests/wpt/web-platform-tests/dom/nodes/Node-replaceChild.html
new file mode 100644
index 00000000000..3b1bb7e04ff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Node-replaceChild.html
@@ -0,0 +1,321 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Node.replaceChild</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body><a><b></b><c></c></a>
+<div id="log"></div>
+<script>
+// IDL.
+test(function() {
+ var a = document.createElement("div");
+ assert_throws(new TypeError(), function() {
+ a.replaceChild(null, null);
+ });
+
+ var b = document.createElement("div");
+ assert_throws(new TypeError(), function() {
+ a.replaceChild(b, null);
+ });
+ assert_throws(new TypeError(), function() {
+ a.replaceChild(null, b);
+ });
+}, "Passing null to replaceChild should throw a TypeError.")
+
+// Step 1.
+test(function() {
+ var a = document.createElement("div");
+ var b = document.createElement("div");
+ var c = document.createElement("div");
+ assert_throws("NotFoundError", function() {
+ a.replaceChild(b, c);
+ });
+
+ var d = document.createElement("div");
+ d.appendChild(b);
+ assert_throws("NotFoundError", function() {
+ a.replaceChild(b, c);
+ });
+ assert_throws("NotFoundError", function() {
+ a.replaceChild(a, c);
+ });
+ assert_throws("NotFoundError", function() {
+ a.replaceChild(b, a);
+ });
+ assert_throws("NotFoundError", function() {
+ a.replaceChild(a, a);
+ });
+}, "If child's parent is not the context node, a NotFoundError exception should be thrown")
+test(function() {
+ var nodes = [
+ document.implementation.createDocumentType("html", "", ""),
+ document.createTextNode("text"),
+ document.implementation.createDocument(null, "foo", null).createProcessingInstruction("foo", "bar"),
+ document.createComment("comment")
+ ];
+
+ var a = document.createElement("div");
+ var b = document.createElement("div");
+ nodes.forEach(function(node) {
+ assert_throws("HierarchyRequestError", function() {
+ node.replaceChild(a, b);
+ });
+ });
+}, "If the context node is not a node that can contain children, a NotFoundError exception should be thrown")
+
+// Step 2.
+test(function() {
+ var a = document.createElement("div");
+ var b = document.createElement("div");
+ a.appendChild(b);
+ assert_throws("HierarchyRequestError", function() {
+ a.replaceChild(a, b);
+ });
+
+ var c = document.createElement("div");
+ c.appendChild(a);
+ assert_throws("HierarchyRequestError", function() {
+ a.replaceChild(c, b);
+ });
+}, "If node is an inclusive ancestor of the context node, a HierarchyRequestError should be thrown.")
+
+// Step 3.1.
+test(function() {
+ var doc = document.implementation.createHTMLDocument("title");
+ var doc2 = document.implementation.createHTMLDocument("title2");
+ assert_throws("HierarchyRequestError", function() {
+ doc.replaceChild(doc2, doc.documentElement);
+ });
+
+ assert_throws("HierarchyRequestError", function() {
+ doc.replaceChild(doc.createTextNode("text"), doc.documentElement);
+ });
+}, "If the context node is a document, inserting a document or text node should throw a HierarchyRequestError.")
+
+// Step 3.2.1.
+test(function() {
+ var doc = document.implementation.createHTMLDocument("title");
+
+ var df = doc.createDocumentFragment();
+ df.appendChild(doc.createElement("a"));
+ df.appendChild(doc.createElement("b"));
+ assert_throws("HierarchyRequestError", function() {
+ doc.replaceChild(df, doc.documentElement);
+ });
+
+ df = doc.createDocumentFragment();
+ df.appendChild(doc.createTextNode("text"));
+ assert_throws("HierarchyRequestError", function() {
+ doc.replaceChild(df, doc.documentElement);
+ });
+
+ df = doc.createDocumentFragment();
+ df.appendChild(doc.createComment("comment"));
+ df.appendChild(doc.createTextNode("text"));
+ assert_throws("HierarchyRequestError", function() {
+ doc.replaceChild(df, doc.documentElement);
+ });
+}, "If the context node is a document, inserting a DocumentFragment that contains a text node or too many elements should throw a HierarchyRequestError.")
+test(function() {
+ var doc = document.implementation.createHTMLDocument("title");
+ doc.removeChild(doc.documentElement);
+
+ var df = doc.createDocumentFragment();
+ df.appendChild(doc.createElement("a"));
+ df.appendChild(doc.createElement("b"));
+ assert_throws("HierarchyRequestError", function() {
+ doc.replaceChild(df, doc.doctype);
+ });
+}, "If the context node is a document (without element children), inserting a DocumentFragment that contains multiple elements should throw a HierarchyRequestError.")
+
+// Step 3.2.2.
+test(function() {
+ // The context node has an element child that is not /child/.
+ var doc = document.implementation.createHTMLDocument("title");
+ var comment = doc.appendChild(doc.createComment("foo"));
+ assert_array_equals(doc.childNodes, [doc.doctype, doc.documentElement, comment]);
+
+ var df = doc.createDocumentFragment();
+ df.appendChild(doc.createElement("a"));
+ assert_throws("HierarchyRequestError", function() {
+ doc.replaceChild(df, comment);
+ });
+ assert_throws("HierarchyRequestError", function() {
+ doc.replaceChild(df, doc.doctype);
+ });
+}, "If the context node is a document, inserting a DocumentFragment with an element if there already is an element child should throw a HierarchyRequestError.")
+test(function() {
+ // A doctype is following /child/.
+ var doc = document.implementation.createHTMLDocument("title");
+ var comment = doc.insertBefore(doc.createComment("foo"), doc.firstChild);
+ doc.removeChild(doc.documentElement);
+ assert_array_equals(doc.childNodes, [comment, doc.doctype]);
+
+ var df = doc.createDocumentFragment();
+ df.appendChild(doc.createElement("a"));
+ assert_throws("HierarchyRequestError", function() {
+ doc.replaceChild(df, comment);
+ });
+}, "If the context node is a document, inserting a DocumentFragment with an element before the doctype should throw a HierarchyRequestError.")
+
+// Step 3.3.
+test(function() {
+ var doc = document.implementation.createHTMLDocument("title");
+ var comment = doc.appendChild(doc.createComment("foo"));
+ assert_array_equals(doc.childNodes, [doc.doctype, doc.documentElement, comment]);
+
+ var a = doc.createElement("a");
+ assert_throws("HierarchyRequestError", function() {
+ doc.replaceChild(a, comment);
+ });
+ assert_throws("HierarchyRequestError", function() {
+ doc.replaceChild(a, doc.doctype);
+ });
+}, "If the context node is a document, inserting an element if there already is an element child should throw a HierarchyRequestError.")
+test(function() {
+ var doc = document.implementation.createHTMLDocument("title");
+ var comment = doc.insertBefore(doc.createComment("foo"), doc.firstChild);
+ doc.removeChild(doc.documentElement);
+ assert_array_equals(doc.childNodes, [comment, doc.doctype]);
+
+ var a = doc.createElement("a");
+ assert_throws("HierarchyRequestError", function() {
+ doc.replaceChild(a, comment);
+ });
+}, "If the context node is a document, inserting an element before the doctype should throw a HierarchyRequestError.")
+
+// Step 3.4.
+test(function() {
+ var doc = document.implementation.createHTMLDocument("title");
+ var comment = doc.insertBefore(doc.createComment("foo"), doc.firstChild);
+ assert_array_equals(doc.childNodes, [comment, doc.doctype, doc.documentElement]);
+
+ var doctype = document.implementation.createDocumentType("html", "", "");
+ assert_throws("HierarchyRequestError", function() {
+ doc.replaceChild(doctype, comment);
+ });
+ assert_throws("HierarchyRequestError", function() {
+ doc.replaceChild(doctype, doc.documentElement);
+ });
+}, "If the context node is a document, inserting a doctype if there already is a doctype child should throw a HierarchyRequestError.")
+test(function() {
+ var doc = document.implementation.createHTMLDocument("title");
+ var comment = doc.appendChild(doc.createComment("foo"));
+ doc.removeChild(doc.doctype);
+ assert_array_equals(doc.childNodes, [doc.documentElement, comment]);
+
+ var doctype = document.implementation.createDocumentType("html", "", "");
+ assert_throws("HierarchyRequestError", function() {
+ doc.replaceChild(doctype, comment);
+ });
+}, "If the context node is a document, inserting a doctype after the document element should throw a HierarchyRequestError.")
+
+// Step 4.
+test(function() {
+ var df = document.createDocumentFragment();
+ var a = df.appendChild(document.createElement("a"));
+
+ var doc = document.implementation.createHTMLDocument("title");
+ assert_throws("HierarchyRequestError", function() {
+ df.replaceChild(doc, a);
+ });
+
+ var doctype = document.implementation.createDocumentType("html", "", "");
+ assert_throws("HierarchyRequestError", function() {
+ df.replaceChild(doctype, a);
+ });
+}, "If the context node is a DocumentFragment, inserting a document or a doctype should throw a HierarchyRequestError.")
+test(function() {
+ var el = document.createElement("div");
+ var a = el.appendChild(document.createElement("a"));
+
+ var doc = document.implementation.createHTMLDocument("title");
+ assert_throws("HierarchyRequestError", function() {
+ el.replaceChild(doc, a);
+ });
+
+ var doctype = document.implementation.createDocumentType("html", "", "");
+ assert_throws("HierarchyRequestError", function() {
+ el.replaceChild(doctype, a);
+ });
+}, "If the context node is an element, inserting a document or a doctype should throw a HierarchyRequestError.")
+
+// Step 6.
+test(function() {
+ var a = document.createElement("div");
+ var b = document.createElement("div");
+ var c = document.createElement("div");
+ a.appendChild(b);
+ a.appendChild(c);
+ assert_array_equals(a.childNodes, [b, c]);
+ assert_equals(a.replaceChild(c, b), b);
+ assert_array_equals(a.childNodes, [c]);
+}, "Replacing a node with its next sibling should work (2 children)");
+test(function() {
+ var a = document.createElement("div");
+ var b = document.createElement("div");
+ var c = document.createElement("div");
+ var d = document.createElement("div");
+ var e = document.createElement("div");
+ a.appendChild(b);
+ a.appendChild(c);
+ a.appendChild(d);
+ a.appendChild(e);
+ assert_array_equals(a.childNodes, [b, c, d, e]);
+ assert_equals(a.replaceChild(d, c), c);
+ assert_array_equals(a.childNodes, [b, d, e]);
+}, "Replacing a node with its next sibling should work (4 children)");
+
+// Step 7.
+test(function() {
+ var doc = document.implementation.createHTMLDocument("title");
+ var doctype = doc.doctype;
+ assert_array_equals(doc.childNodes, [doctype, doc.documentElement]);
+
+ var doc2 = document.implementation.createHTMLDocument("title2");
+ var doctype2 = doc2.doctype;
+ assert_array_equals(doc2.childNodes, [doctype2, doc2.documentElement]);
+
+ doc.replaceChild(doc2.doctype, doc.doctype);
+ assert_array_equals(doc.childNodes, [doctype2, doc.documentElement]);
+ assert_array_equals(doc2.childNodes, [doc2.documentElement]);
+ assert_equals(doctype.parentNode, null);
+ assert_equals(doctype.ownerDocument, doc);
+ assert_equals(doctype2.parentNode, doc);
+ assert_equals(doctype2.ownerDocument, doc);
+}, "If the context node is a document, inserting a new doctype should work.")
+
+// Bugs.
+test(function() {
+ var doc = document.implementation.createHTMLDocument("title");
+ var df = doc.createDocumentFragment();
+ var a = df.appendChild(doc.createElement("a"));
+ assert_equals(doc.documentElement, doc.replaceChild(df, doc.documentElement));
+ assert_array_equals(doc.childNodes, [doc.doctype, a]);
+}, "Replacing the document element with a DocumentFragment containing a single element should work.");
+test(function() {
+ var doc = document.implementation.createHTMLDocument("title");
+ var df = doc.createDocumentFragment();
+ var a = df.appendChild(doc.createComment("a"));
+ var b = df.appendChild(doc.createElement("b"));
+ var c = df.appendChild(doc.createComment("c"));
+ assert_equals(doc.documentElement, doc.replaceChild(df, doc.documentElement));
+ assert_array_equals(doc.childNodes, [doc.doctype, a, b, c]);
+}, "Replacing the document element with a DocumentFragment containing a single element and comments should work.");
+test(function() {
+ var doc = document.implementation.createHTMLDocument("title");
+ var a = doc.createElement("a");
+ assert_equals(doc.documentElement, doc.replaceChild(a, doc.documentElement));
+ assert_array_equals(doc.childNodes, [doc.doctype, a]);
+}, "Replacing the document element with a single element should work.");
+test(function() {
+ document.addEventListener("DOMNodeRemoved", function(e) {
+ document.body.appendChild(document.createElement("x"));
+ }, false);
+ var a = document.body.firstChild, b = a.firstChild, c = b.nextSibling;
+ assert_equals(a.replaceChild(c, b), b);
+ assert_equals(b.parentNode, null);
+ assert_equals(a.firstChild, c);
+ assert_equals(c.parentNode, a);
+}, "replaceChild should work in the presence of mutation events.")
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Node-textContent.html b/tests/wpt/web-platform-tests/dom/nodes/Node-textContent.html
new file mode 100644
index 00000000000..9378dec806c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Node-textContent.html
@@ -0,0 +1,265 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Node.textContent</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+// XXX mutation observers?
+// XXX Range gravitation?
+
+var documents, doctypes;
+setup(function() {
+ documents = [
+ [document, "parser"],
+ [document.implementation.createDocument("", "test", null), "createDocument"],
+ [document.implementation.createHTMLDocument("title"), "createHTMLDocument"],
+ ]
+ doctypes = [
+ [document.doctype, "parser"],
+ [document.implementation.createDocumentType("x", "", ""), "script"],
+ ]
+})
+
+// Getting
+// DocumentFragment, Element:
+test(function() {
+ var element = document.createElement("div")
+ assert_equals(element.textContent, "")
+}, "For an empty Element, textContent should be the empty string")
+
+test(function() {
+ assert_equals(document.createDocumentFragment().textContent, "")
+}, "For an empty DocumentFragment, textContent should be the empty string")
+
+test(function() {
+ var el = document.createElement("div")
+ el.appendChild(document.createComment(" abc "))
+ el.appendChild(document.createTextNode("\tDEF\t"))
+ el.appendChild(document.createProcessingInstruction("x", " ghi "))
+ assert_equals(el.textContent, "\tDEF\t")
+}, "Element with children")
+
+test(function() {
+ var el = document.createElement("div")
+ var child = document.createElement("div")
+ el.appendChild(child)
+ child.appendChild(document.createComment(" abc "))
+ child.appendChild(document.createTextNode("\tDEF\t"))
+ child.appendChild(document.createProcessingInstruction("x", " ghi "))
+ assert_equals(el.textContent, "\tDEF\t")
+}, "Element with descendants")
+
+test(function() {
+ var df = document.createDocumentFragment()
+ df.appendChild(document.createComment(" abc "))
+ df.appendChild(document.createTextNode("\tDEF\t"))
+ df.appendChild(document.createProcessingInstruction("x", " ghi "))
+ assert_equals(df.textContent, "\tDEF\t")
+}, "DocumentFragment with children")
+
+test(function() {
+ var df = document.createDocumentFragment()
+ var child = document.createElement("div")
+ df.appendChild(child)
+ child.appendChild(document.createComment(" abc "))
+ child.appendChild(document.createTextNode("\tDEF\t"))
+ child.appendChild(document.createProcessingInstruction("x", " ghi "))
+ assert_equals(df.textContent, "\tDEF\t")
+}, "DocumentFragment with descendants")
+
+// Text, ProcessingInstruction, Comment:
+test(function() {
+ assert_equals(document.createTextNode("").textContent, "")
+}, "For an empty Text, textContent should be the empty string")
+
+test(function() {
+ assert_equals(document.createProcessingInstruction("x", "").textContent, "")
+}, "For an empty ProcessingInstruction, textContent should be the empty string")
+
+test(function() {
+ assert_equals(document.createComment("").textContent, "")
+}, "For an empty Comment, textContent should be the empty string")
+
+test(function() {
+ assert_equals(document.createTextNode("abc").textContent, "abc")
+}, "For a Text with data, textContent should be that data")
+
+test(function() {
+ assert_equals(document.createProcessingInstruction("x", "abc").textContent,
+ "abc")
+}, "For a ProcessingInstruction with data, textContent should be that data")
+
+test(function() {
+ assert_equals(document.createComment("abc").textContent, "abc")
+}, "For a Comment with data, textContent should be that data")
+
+// Any other node:
+documents.forEach(function(argument) {
+ var doc = argument[0], creator = argument[1]
+ test(function() {
+ assert_equals(doc.textContent, null)
+ }, "For Documents created by " + creator + ", textContent should be null")
+})
+
+doctypes.forEach(function(argument) {
+ var doctype = argument[0], creator = argument[1]
+ test(function() {
+ assert_equals(doctype.textContent, null)
+ }, "For DocumentType created by " + creator + ", textContent should be null")
+})
+
+// Setting
+// DocumentFragment, Element:
+var arguments = [
+ [null, null],
+ [undefined, null],
+ ["", null],
+ [42, "42"],
+ ["abc", "abc"],
+ ["<b>xyz<\/b>", "<b>xyz<\/b>"],
+ ["d\0e", "d\0e"]
+ // XXX unpaired surrogate?
+]
+arguments.forEach(function(aValue) {
+ var argument = aValue[0], expectation = aValue[1]
+ var check = function(aElementOrDocumentFragment) {
+ if (expectation === null) {
+ assert_equals(aElementOrDocumentFragment.textContent, "")
+ assert_equals(aElementOrDocumentFragment.firstChild, null)
+ } else {
+ assert_equals(aElementOrDocumentFragment.textContent, expectation)
+ assert_equals(aElementOrDocumentFragment.childNodes.length, 1,
+ "Should have one child")
+ var firstChild = aElementOrDocumentFragment.firstChild
+ assert_true(firstChild instanceof Text, "child should be a Text")
+ assert_equals(firstChild.data, expectation)
+ }
+ }
+
+ test(function() {
+ var el = document.createElement("div")
+ el.textContent = argument
+ check(el)
+ }, "Element without children set to " + format_value(argument))
+
+ test(function() {
+ var el = document.createElement("div")
+ var text = el.appendChild(document.createTextNode(""))
+ el.textContent = argument
+ check(el)
+ assert_equals(text.parentNode, null,
+ "Preexisting Text should have been removed")
+ }, "Element with empty text node as child set to " + format_value(argument))
+
+ test(function() {
+ var el = document.createElement("div")
+ el.appendChild(document.createComment(" abc "))
+ el.appendChild(document.createTextNode("\tDEF\t"))
+ el.appendChild(document.createProcessingInstruction("x", " ghi "))
+ el.textContent = argument
+ check(el)
+ }, "Element with children set to " + format_value(argument))
+
+ test(function() {
+ var el = document.createElement("div")
+ var child = document.createElement("div")
+ el.appendChild(child)
+ child.appendChild(document.createComment(" abc "))
+ child.appendChild(document.createTextNode("\tDEF\t"))
+ child.appendChild(document.createProcessingInstruction("x", " ghi "))
+ el.textContent = argument
+ check(el)
+ assert_equals(child.childNodes.length, 3,
+ "Should not have changed the internal structure of the removed nodes.")
+ }, "Element with descendants set to " + format_value(argument))
+
+ test(function() {
+ var df = document.createDocumentFragment()
+ df.textContent = argument
+ check(df)
+ }, "DocumentFragment without children set to " + format_value(argument))
+
+ test(function() {
+ var df = document.createDocumentFragment()
+ var text = df.appendChild(document.createTextNode(""))
+ df.textContent = argument
+ check(df)
+ assert_equals(text.parentNode, null,
+ "Preexisting Text should have been removed")
+ }, "DocumentFragment with empty text node as child set to " + format_value(argument))
+
+ test(function() {
+ var df = document.createDocumentFragment()
+ df.appendChild(document.createComment(" abc "))
+ df.appendChild(document.createTextNode("\tDEF\t"))
+ df.appendChild(document.createProcessingInstruction("x", " ghi "))
+ df.textContent = argument
+ check(df)
+ }, "DocumentFragment with children set to " + format_value(argument))
+
+ test(function() {
+ var df = document.createDocumentFragment()
+ var child = document.createElement("div")
+ df.appendChild(child)
+ child.appendChild(document.createComment(" abc "))
+ child.appendChild(document.createTextNode("\tDEF\t"))
+ child.appendChild(document.createProcessingInstruction("x", " ghi "))
+ df.textContent = argument
+ check(df)
+ assert_equals(child.childNodes.length, 3,
+ "Should not have changed the internal structure of the removed nodes.")
+ }, "DocumentFragment with descendants set to " + format_value(argument))
+})
+
+// Text, ProcessingInstruction, Comment:
+test(function() {
+ var text = document.createTextNode("abc")
+ text.textContent = "def"
+ assert_equals(text.textContent, "def")
+ assert_equals(text.data, "def")
+}, "For a Text, textContent should set the data")
+
+test(function() {
+ var pi = document.createProcessingInstruction("x", "abc")
+ pi.textContent = "def"
+ assert_equals(pi.textContent, "def")
+ assert_equals(pi.data, "def")
+ assert_equals(pi.target, "x")
+}, "For a ProcessingInstruction, textContent should set the data")
+
+test(function() {
+ var comment = document.createComment("abc")
+ comment.textContent = "def"
+ assert_equals(comment.textContent, "def")
+ assert_equals(comment.data, "def")
+}, "For a Comment, textContent should set the data")
+
+// Any other node:
+documents.forEach(function(argument) {
+ var doc = argument[0], creator = argument[1]
+ test(function() {
+ var root = doc.documentElement
+ doc.textContent = "a"
+ assert_equals(doc.textContent, null)
+ assert_equals(doc.documentElement, root)
+ }, "For Documents created by " + creator + ", setting textContent should do nothing")
+})
+
+doctypes.forEach(function(argument) {
+ var doctype = argument[0], creator = argument[1]
+ test(function() {
+ var props = {
+ name: doctype.name,
+ publicId: doctype.publicId,
+ systemId: doctype.systemId,
+ }
+ doctype.textContent = "b"
+ assert_equals(doctype.textContent, null)
+ assert_equals(doctype.name, props.name, "name should not change")
+ assert_equals(doctype.publicId, props.publicId, "publicId should not change")
+ assert_equals(doctype.systemId, props.systemId, "systemId should not change")
+ }, "For DocumentType created by " + creator + ", setting textContent should do nothing")
+})
+
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/ParentNode-querySelector-All-content.html b/tests/wpt/web-platform-tests/dom/nodes/ParentNode-querySelector-All-content.html
new file mode 100644
index 00000000000..affb00af2bf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/ParentNode-querySelector-All-content.html
@@ -0,0 +1,377 @@
+<!DOCTYPE html>
+<html id="html" lang="en">
+<head id="head">
+ <meta id="meta" charset="UTF-8">
+ <title id="title">Selectors-API Test Suite: HTML with Selectors Level 2 using TestHarness: Test Document</title>
+
+ <!-- Links for :link and :visited pseudo-class test -->
+ <link id="pseudo-link-link1" href="">
+ <link id="pseudo-link-link2" href="http://example.org/">
+ <link id="pseudo-link-link3">
+ <style>
+ @namespace ns "http://www.w3.org/1999/xhtml";
+ /* Declare the namespace prefix used in tests. This declaration should not be used by the API. */
+ </style>
+</head>
+<body id="body">
+<div id="root">
+ <div id="target"></div>
+
+ <div id="universal">
+ <p id="universal-p1">Universal selector tests inside element with <code id="universal-code1">id="universal"</code>.</p>
+ <hr id="universal-hr1">
+ <pre id="universal-pre1">Some preformatted text with some <span id="universal-span1">embedded code</span></pre>
+ <p id="universal-p2">This is a normal link: <a id="universal-a1" href="http://www.w3.org/">W3C</a></p>
+ <address id="universal-address1">Some more nested elements <code id="universal-code2"><a href="#" id="universal-a2">code hyperlink</a></code></address>
+ </div>
+
+ <div id="attr-presence">
+ <div class="attr-presence-div1" id="attr-presence-div1" align="center"></div>
+ <div class="attr-presence-div2" id="attr-presence-div2" align=""></div>
+ <div class="attr-presence-div3" id="attr-presence-div3" valign="center"></div>
+ <div class="attr-presence-div4" id="attr-presence-div4" alignv="center"></div>
+ <p id="attr-presence-p1"><a id="attr-presence-a1" tItLe=""></a><span id="attr-presence-span1" TITLE="attr-presence-span1"></span></p>
+ <pre id="attr-presence-pre1" data-attr-presence="pre1"></pre>
+ <blockquote id="attr-presence-blockquote1" data-attr-presence="blockquote1"></blockquote>
+ <ul id="attr-presence-ul1" data-中文=""></ul>
+
+ <select id="attr-presence-select1">
+ <option id="attr-presence-select1-option1">A</option>
+ <option id="attr-presence-select1-option2">B</option>
+ <option id="attr-presence-select1-option3">C</option>
+ <option id="attr-presence-select1-option4">D</option>
+ </select>
+ <select id="attr-presence-select2">
+ <option id="attr-presence-select2-option1">A</option>
+ <option id="attr-presence-select2-option2">B</option>
+ <option id="attr-presence-select2-option3">C</option>
+ <option id="attr-presence-select2-option4" selected="selected">D</option>
+ </select>
+ <select id="attr-presence-select3" multiple="multiple">
+ <option id="attr-presence-select3-option1">A</option>
+ <option id="attr-presence-select3-option2" selected="">B</option>
+ <option id="attr-presence-select3-option3" selected="selected">C</option>
+ <option id="attr-presence-select3-option4">D</option>
+ </select>
+ </div>
+
+ <div id="attr-value">
+ <div id="attr-value-div1" align="center"></div>
+ <div id="attr-value-div2" align=""></div>
+ <div id="attr-value-div3" data-attr-value="&#xE9;"></div>
+ <div id="attr-value-div4" data-attr-value_foo="&#xE9;"></div>
+
+ <form id="attr-value-form1">
+ <input id="attr-value-input1" type="text">
+ <input id="attr-value-input2" type="password">
+ <input id="attr-value-input3" type="hidden">
+ <input id="attr-value-input4" type="radio">
+ <input id="attr-value-input5" type="checkbox">
+ <input id="attr-value-input6" type="radio">
+ <input id="attr-value-input7" type="text">
+ <input id="attr-value-input8" type="hidden">
+ <input id="attr-value-input9" type="radio">
+ </form>
+
+ <div id="attr-value-div5" data-attr-value="中文"></div>
+ </div>
+
+ <div id="attr-whitespace">
+ <div id="attr-whitespace-div1" class="foo div1 bar"></div>
+ <div id="attr-whitespace-div2" class=""></div>
+ <div id="attr-whitespace-div3" class="foo div3 bar"></div>
+
+ <div id="attr-whitespace-div4" data-attr-whitespace="foo &#xE9; bar"></div>
+ <div id="attr-whitespace-div5" data-attr-whitespace_foo="&#xE9; foo"></div>
+
+ <a id="attr-whitespace-a1" rel="next bookmark"></a>
+ <a id="attr-whitespace-a2" rel="tag nofollow"></a>
+ <a id="attr-whitespace-a3" rel="tag bookmark"></a>
+ <a id="attr-whitespace-a4" rel="book mark"></a> <!-- Intentional space in "book mark" -->
+ <a id="attr-whitespace-a5" rel="nofollow"></a>
+ <a id="attr-whitespace-a6" rev="bookmark nofollow"></a>
+ <a id="attr-whitespace-a7" rel="prev next tag alternate nofollow author help icon noreferrer prefetch search stylesheet tag"></a>
+
+ <p id="attr-whitespace-p1" title="Chinese 中文 characters"></p>
+ </div>
+
+ <div id="attr-hyphen">
+ <div id="attr-hyphen-div1"></div>
+ <div id="attr-hyphen-div2" lang="fr"></div>
+ <div id="attr-hyphen-div3" lang="en-AU"></div>
+ <div id="attr-hyphen-div4" lang="es"></div>
+ </div>
+
+ <div id="attr-begins">
+ <a id="attr-begins-a1" href="http://www.example.org"></a>
+ <a id="attr-begins-a2" href="http://example.org/"></a>
+ <a id="attr-begins-a3" href="http://www.example.com/"></a>
+
+ <div id="attr-begins-div1" lang="fr"></div>
+ <div id="attr-begins-div2" lang="en-AU"></div>
+ <div id="attr-begins-div3" lang="es"></div>
+ <div id="attr-begins-div4" lang="en-US"></div>
+ <div id="attr-begins-div5" lang="en"></div>
+
+ <p id="attr-begins-p1" class=" apple"></p> <!-- Intentional space in class value " apple". -->
+ </div>
+
+ <div id="attr-ends">
+ <a id="attr-ends-a1" href="http://www.example.org"></a>
+ <a id="attr-ends-a2" href="http://example.org/"></a>
+ <a id="attr-ends-a3" href="http://www.example.org"></a>
+
+ <div id="attr-ends-div1" lang="fr"></div>
+ <div id="attr-ends-div2" lang="de-CH"></div>
+ <div id="attr-ends-div3" lang="es"></div>
+ <div id="attr-ends-div4" lang="fr-CH"></div>
+
+ <p id="attr-ends-p1" class="apple "></p> <!-- Intentional space in class value "apple ". -->
+ </div>
+
+ <div id="attr-contains">
+ <a id="attr-contains-a1" href="http://www.example.org"></a>
+ <a id="attr-contains-a2" href="http://example.org/"></a>
+ <a id="attr-contains-a3" href="http://www.example.com/"></a>
+
+ <div id="attr-contains-div1" lang="fr"></div>
+ <div id="attr-contains-div2" lang="en-AU"></div>
+ <div id="attr-contains-div3" lang="de-CH"></div>
+ <div id="attr-contains-div4" lang="es"></div>
+ <div id="attr-contains-div5" lang="fr-CH"></div>
+ <div id="attr-contains-div6" lang="en-US"></div>
+
+ <p id="attr-contains-p1" class=" apple banana orange "></p>
+ </div>
+
+ <div id="pseudo-nth">
+ <table id="pseudo-nth-table1">
+ <tr id="pseudo-nth-tr1"><td id="pseudo-nth-td1"></td><td id="pseudo-nth-td2"></td><td id="pseudo-nth-td3"></td><td id="pseudo-nth-td4"></td><td id="pseudo-nth--td5"></td><td id="pseudo-nth-td6"></td></tr>
+ <tr id="pseudo-nth-tr2"><td id="pseudo-nth-td7"></td><td id="pseudo-nth-td8"></td><td id="pseudo-nth-td9"></td><td id="pseudo-nth-td10"></td><td id="pseudo-nth-td11"></td><td id="pseudo-nth-td12"></td></tr>
+ <tr id="pseudo-nth-tr3"><td id="pseudo-nth-td13"></td><td id="pseudo-nth-td14"></td><td id="pseudo-nth-td15"></td><td id="pseudo-nth-td16"></td><td id="pseudo-nth-td17"></td><td id="pseudo-nth-td18"></td></tr>
+ </table>
+
+ <ol id="pseudo-nth-ol1">
+ <li id="pseudo-nth-li1"></li>
+ <li id="pseudo-nth-li2"></li>
+ <li id="pseudo-nth-li3"></li>
+ <li id="pseudo-nth-li4"></li>
+ <li id="pseudo-nth-li5"></li>
+ <li id="pseudo-nth-li6"></li>
+ <li id="pseudo-nth-li7"></li>
+ <li id="pseudo-nth-li8"></li>
+ <li id="pseudo-nth-li9"></li>
+ <li id="pseudo-nth-li10"></li>
+ <li id="pseudo-nth-li11"></li>
+ <li id="pseudo-nth-li12"></li>
+ </ol>
+
+ <p id="pseudo-nth-p1">
+ <span id="pseudo-nth-span1">span1</span>
+ <em id="pseudo-nth-em1">em1</em>
+ <!-- comment node-->
+ <em id="pseudo-nth-em2">em2</em>
+ <span id="pseudo-nth-span2">span2</span>
+ <strong id="pseudo-nth-strong1">strong1</strong>
+ <em id="pseudo-nth-em3">em3</em>
+ <span id="pseudo-nth-span3">span3</span>
+ <span id="pseudo-nth-span4">span4</span>
+ <strong id="pseudo-nth-strong2">strong2</strong>
+ <em id="pseudo-nth-em4">em4</em>
+ </p>
+ </div>
+
+ <div id="pseudo-first-child">
+ <div id="pseudo-first-child-div1"></div>
+ <div id="pseudo-first-child-div2"></div>
+ <div id="pseudo-first-child-div3"></div>
+
+ <p id="pseudo-first-child-p1"><span id="pseudo-first-child-span1"></span><span id="pseudo-first-child-span2"></span></p>
+ <p id="pseudo-first-child-p2"><span id="pseudo-first-child-span3"></span><span id="pseudo-first-child-span4"></span></p>
+ <p id="pseudo-first-child-p3"><span id="pseudo-first-child-span5"></span><span id="pseudo-first-child-span6"></span></p>
+ </div>
+
+ <div id="pseudo-last-child">
+ <p id="pseudo-last-child-p1"><span id="pseudo-last-child-span1"></span><span id="pseudo-last-child-span2"></span></p>
+ <p id="pseudo-last-child-p2"><span id="pseudo-last-child-span3"></span><span id="pseudo-last-child-span4"></span></p>
+ <p id="pseudo-last-child-p3"><span id="pseudo-last-child-span5"></span><span id="pseudo-last-child-span6"></span></p>
+
+ <div id="pseudo-last-child-div1"></div>
+ <div id="pseudo-last-child-div2"></div>
+ <div id="pseudo-last-child-div3"></div>
+ </div>
+
+ <div id="pseudo-only">
+ <p id="pseudo-only-p1">
+ <span id="pseudo-only-span1"></span>
+ </p>
+ <p id="pseudo-only-p2">
+ <span id="pseudo-only-span2"></span>
+ <span id="pseudo-only-span3"></span>
+ </p>
+ <p id="pseudo-only-p3">
+ <span id="pseudo-only-span4"></span>
+ <em id="pseudo-only-em1"></em>
+ <span id="pseudo-only-span5"></span>
+ </p>
+ </div>>
+
+ <div id="pseudo-empty">
+ <p id="pseudo-empty-p1"></p>
+ <p id="pseudo-empty-p2"><!-- comment node --></p>
+ <p id="pseudo-empty-p3"> </p>
+ <p id="pseudo-empty-p4">Text node</p>
+ <p id="pseudo-empty-p5"><span id="pseudo-empty-span1"></span></p>
+ </div>
+
+ <div id="pseudo-link">
+ <a id="pseudo-link-a1" href="">with href</a>
+ <a id="pseudo-link-a2" href="http://example.org/">with href</a>
+ <a id="pseudo-link-a3">without href</a>
+ <map name="pseudo-link-map1" id="pseudo-link-map1">
+ <area id="pseudo-link-area1" href="">
+ <area id="pseudo-link-area2">
+ </map>
+ </div>
+
+ <div id="pseudo-lang">
+ <div id="pseudo-lang-div1"></div>
+ <div id="pseudo-lang-div2" lang="fr"></div>
+ <div id="pseudo-lang-div3" lang="en-AU"></div>
+ <div id="pseudo-lang-div4" lang="es"></div>
+ </div>
+
+ <div id="pseudo-ui">
+ <input id="pseudo-ui-input1" type="text">
+ <input id="pseudo-ui-input2" type="password">
+ <input id="pseudo-ui-input3" type="radio">
+ <input id="pseudo-ui-input4" type="radio" checked="checked">
+ <input id="pseudo-ui-input5" type="checkbox">
+ <input id="pseudo-ui-input6" type="checkbox" checked="checked">
+ <input id="pseudo-ui-input7" type="submit">
+ <input id="pseudo-ui-input8" type="button">
+ <input id="pseudo-ui-input9" type="hidden">
+ <textarea id="pseudo-ui-textarea1"></textarea>
+ <button id="pseudo-ui-button1">Enabled</button>
+
+ <input id="pseudo-ui-input10" disabled="disabled" type="text">
+ <input id="pseudo-ui-input11" disabled="disabled" type="password">
+ <input id="pseudo-ui-input12" disabled="disabled" type="radio">
+ <input id="pseudo-ui-input13" disabled="disabled" type="radio" checked="checked">
+ <input id="pseudo-ui-input14" disabled="disabled" type="checkbox">
+ <input id="pseudo-ui-input15" disabled="disabled" type="checkbox" checked="checked">
+ <input id="pseudo-ui-input16" disabled="disabled" type="submit">
+ <input id="pseudo-ui-input17" disabled="disabled" type="button">
+ <input id="pseudo-ui-input18" disabled="disabled" type="hidden">
+ <textarea id="pseudo-ui-textarea2" disabled="disabled"></textarea>
+ <button id="pseudo-ui-button2" disabled="disabled">Disabled</button>
+ </div>
+
+ <div id="not">
+ <div id="not-div1"></div>
+ <div id="not-div2"></div>
+ <div id="not-div3"></div>
+
+ <p id="not-p1"><span id="not-span1"></span><em id="not-em1"></em></p>
+ <p id="not-p2"><span id="not-span2"></span><em id="not-em2"></em></p>
+ <p id="not-p3"><span id="not-span3"></span><em id="not-em3"></em></p>
+ </div>
+
+ <div id="pseudo-element">All pseudo-element tests</div>
+
+ <div id="class">
+ <p id="class-p1" class="foo class-p bar"></p>
+ <p id="class-p2" class="class-p foo bar"></p>
+ <p id="class-p3" class="foo bar class-p"></p>
+
+ <!-- All permutations of the classes should match -->
+ <div id="class-div1" class="apple orange banana"></div>
+ <div id="class-div2" class="apple banana orange"></div>
+ <p id="class-p4" class="orange apple banana"></p>
+ <div id="class-div3" class="orange banana apple"></div>
+ <p id="class-p6" class="banana apple orange"></p>
+ <div id="class-div4" class="banana orange apple"></div>
+ <div id="class-div5" class="apple orange"></div>
+ <div id="class-div6" class="apple banana"></div>
+ <div id="class-div7" class="orange banana"></div>
+
+ <span id="class-span1" class="台北Táiběi 台北"></span>
+ <span id="class-span2" class="台北"></span>
+
+ <span id="class-span3" class="foo:bar"></span>
+ <span id="class-span4" class="test.foo[5]bar"></span>
+ </div>
+
+ <div id="id">
+ <div id="id-div1"></div>
+ <div id="id-div2"></div>
+
+ <ul id="id-ul1">
+ <li id="id-li-duplicate"></li>
+ <li id="id-li-duplicate"></li>
+ <li id="id-li-duplicate"></li>
+ <li id="id-li-duplicate"></li>
+ </ul>
+
+ <span id="台北Táiběi"></span>
+ <span id="台北"></span>
+
+ <span id="#foo:bar"></span>
+ <span id="test.foo[5]bar"></span>
+ </div>
+
+ <div id="descendant">
+ <div id="descendant-div1" class="descendant-div1">
+ <div id="descendant-div2" class="descendant-div2">
+ <div id="descendant-div3" class="descendant-div3">
+ </div>
+ </div>
+ </div>
+ <div id="descendant-div4" class="descendant-div4"></div>
+ </div>
+
+ <div id="child">
+ <div id="child-div1" class="child-div1">
+ <div id="child-div2" class="child-div2">
+ <div id="child-div3" class="child-div3">
+ </div>
+ </div>
+ </div>
+ <div id="child-div4" class="child-div4"></div>
+ </div>
+
+ <div id="adjacent">
+ <div id="adjacent-div1" class="adjacent-div1"></div>
+ <div id="adjacent-div2" class="adjacent-div2">
+ <div id="adjacent-div3" class="adjacent-div3"></div>
+ </div>
+ <div id="adjacent-div4" class="adjacent-div4">
+ <p id="adjacent-p1" class="adjacent-p1"></p>
+ <div id="adjacent-div5" class="adjacent-div5"></div>
+ </div>
+ <div id="adjacent-div6" class="adjacent-div6"></div>
+ <p id="adjacent-p2" class="adjacent-p2"></p>
+ <p id="adjacent-p3" class="adjacent-p3"></p>
+ </div>
+
+ <div id="sibling">
+ <div id="sibling-div1" class="sibling-div"></div>
+ <div id="sibling-div2" class="sibling-div">
+ <div id="sibling-div3" class="sibling-div"></div>
+ </div>
+ <div id="sibling-div4" class="sibling-div">
+ <p id="sibling-p1" class="sibling-p"></p>
+ <div id="sibling-div5" class="sibling-div"></div>
+ </div>
+ <div id="sibling-div6" class="sibling-div"></div>
+ <p id="sibling-p2" class="sibling-p"></p>
+ <p id="sibling-p3" class="sibling-p"></p>
+ </div>
+
+ <div id="group">
+ <em id="group-em1"></em>
+ <strong id="group-strong1"></strong>
+ </div>
+</div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/ParentNode-querySelector-All-content.xht b/tests/wpt/web-platform-tests/dom/nodes/ParentNode-querySelector-All-content.xht
new file mode 100644
index 00000000000..14faa9bd4db
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/ParentNode-querySelector-All-content.xht
@@ -0,0 +1,372 @@
+<!DOCTYPE html>
+<html id="html" lang="en" xmlns="http://www.w3.org/1999/xhtml">
+<head id="head">
+ <title id="title">Selectors-API Test Suite: HTML with Selectors Level 2 using TestHarness: Test Document</title>
+
+ <!-- Links for :link and :visited pseudo-class test -->
+ <link id="pseudo-link-link1" href=""/>
+ <link id="pseudo-link-link2" href="http://example.org/"/>
+ <link id="pseudo-link-link3"/>
+</head>
+<body id="body">
+<div id="root">
+ <div id="target"></div>
+
+ <div id="universal">
+ <p id="universal-p1">Universal selector tests inside element with <code id="universal-code1">id="universal"</code>.</p>
+ <hr id="universal-hr1"/>
+ <pre id="universal-pre1">Some preformatted text with some <span id="universal-span1">embedded code</span></pre>
+ <p id="universal-p2">This is a normal link: <a id="universal-a1" href="http://www.w3.org/">W3C</a></p>
+ <address id="universal-address1">Some more nested elements <code id="universal-code2"><a href="#" id="universal-a2">code hyperlink</a></code></address>
+ </div>
+
+ <div id="attr-presence">
+ <div class="attr-presence-div1" id="attr-presence-div1" align="center"></div>
+ <div class="attr-presence-div2" id="attr-presence-div2" align=""></div>
+ <div class="attr-presence-div3" id="attr-presence-div3" valign="center"></div>
+ <div class="attr-presence-div4" id="attr-presence-div4" alignv="center"></div>
+ <p id="attr-presence-p1"><a id="attr-presence-a1" tItLe=""></a><span id="attr-presence-span1" TITLE="attr-presence-span1"></span></p>
+ <pre id="attr-presence-pre1" data-attr-presence="pre1"></pre>
+ <blockquote id="attr-presence-blockquote1" data-attr-presence="blockquote1"></blockquote>
+ <ul id="attr-presence-ul1" data-中文=""></ul>
+
+ <select id="attr-presence-select1">
+ <option id="attr-presence-select1-option1">A</option>
+ <option id="attr-presence-select1-option2">B</option>
+ <option id="attr-presence-select1-option3">C</option>
+ <option id="attr-presence-select1-option4">D</option>
+ </select>
+ <select id="attr-presence-select2">
+ <option id="attr-presence-select2-option1">A</option>
+ <option id="attr-presence-select2-option2">B</option>
+ <option id="attr-presence-select2-option3">C</option>
+ <option id="attr-presence-select2-option4" selected="selected">D</option>
+ </select>
+ <select id="attr-presence-select3" multiple="multiple">
+ <option id="attr-presence-select3-option1">A</option>
+ <option id="attr-presence-select3-option2" selected="">B</option>
+ <option id="attr-presence-select3-option3" selected="selected">C</option>
+ <option id="attr-presence-select3-option4">D</option>
+ </select>
+ </div>
+
+ <div id="attr-value">
+ <div id="attr-value-div1" align="center"></div>
+ <div id="attr-value-div2" align=""></div>
+ <div id="attr-value-div3" data-attr-value="&#xE9;"></div>
+ <div id="attr-value-div4" data-attr-value_foo="&#xE9;"></div>
+
+ <form id="attr-value-form1">
+ <input id="attr-value-input1" type="text"/>
+ <input id="attr-value-input2" type="password"/>
+ <input id="attr-value-input3" type="hidden"/>
+ <input id="attr-value-input4" type="radio"/>
+ <input id="attr-value-input5" type="checkbox"/>
+ <input id="attr-value-input6" type="radio"/>
+ <input id="attr-value-input7" type="text"/>
+ <input id="attr-value-input8" type="hidden"/>
+ <input id="attr-value-input9" type="radio"/>
+ </form>
+
+ <div id="attr-value-div5" data-attr-value="中文"></div>
+ </div>
+
+ <div id="attr-whitespace">
+ <div id="attr-whitespace-div1" class="foo div1 bar"></div>
+ <div id="attr-whitespace-div2" class=""></div>
+ <div id="attr-whitespace-div3" class="foo div3 bar"></div>
+
+ <div id="attr-whitespace-div4" data-attr-whitespace="foo &#xE9; bar"></div>
+ <div id="attr-whitespace-div5" data-attr-whitespace_foo="&#xE9; foo"></div>
+
+ <a id="attr-whitespace-a1" rel="next bookmark"></a>
+ <a id="attr-whitespace-a2" rel="tag nofollow"></a>
+ <a id="attr-whitespace-a3" rel="tag bookmark"></a>
+ <a id="attr-whitespace-a4" rel="book mark"></a> <!-- Intentional space in "book mark" -->
+ <a id="attr-whitespace-a5" rel="nofollow"></a>
+ <a id="attr-whitespace-a6" rev="bookmark nofollow"></a>
+ <a id="attr-whitespace-a7" rel="prev next tag alternate nofollow author help icon noreferrer prefetch search stylesheet tag"></a>
+
+ <p id="attr-whitespace-p1" title="Chinese 中文 characters"></p>
+ </div>
+
+ <div id="attr-hyphen">
+ <div id="attr-hyphen-div1"></div>
+ <div id="attr-hyphen-div2" lang="fr"></div>
+ <div id="attr-hyphen-div3" lang="en-AU"></div>
+ <div id="attr-hyphen-div4" lang="es"></div>
+ </div>
+
+ <div id="attr-begins">
+ <a id="attr-begins-a1" href="http://www.example.org"></a>
+ <a id="attr-begins-a2" href="http://example.org/"></a>
+ <a id="attr-begins-a3" href="http://www.example.com/"></a>
+
+ <div id="attr-begins-div1" lang="fr"></div>
+ <div id="attr-begins-div2" lang="en-AU"></div>
+ <div id="attr-begins-div3" lang="es"></div>
+ <div id="attr-begins-div4" lang="en-US"></div>
+ <div id="attr-begins-div5" lang="en"></div>
+
+ <p id="attr-begins-p1" class=" apple"></p> <!-- Intentional space in class value " apple". -->
+ </div>
+
+ <div id="attr-ends">
+ <a id="attr-ends-a1" href="http://www.example.org"></a>
+ <a id="attr-ends-a2" href="http://example.org/"></a>
+ <a id="attr-ends-a3" href="http://www.example.org"></a>
+
+ <div id="attr-ends-div1" lang="fr"></div>
+ <div id="attr-ends-div2" lang="de-CH"></div>
+ <div id="attr-ends-div3" lang="es"></div>
+ <div id="attr-ends-div4" lang="fr-CH"></div>
+
+ <p id="attr-ends-p1" class="apple "></p> <!-- Intentional space in class value "apple ". -->
+ </div>
+
+ <div id="attr-contains">
+ <a id="attr-contains-a1" href="http://www.example.org"></a>
+ <a id="attr-contains-a2" href="http://example.org/"></a>
+ <a id="attr-contains-a3" href="http://www.example.com/"></a>
+
+ <div id="attr-contains-div1" lang="fr"></div>
+ <div id="attr-contains-div2" lang="en-AU"></div>
+ <div id="attr-contains-div3" lang="de-CH"></div>
+ <div id="attr-contains-div4" lang="es"></div>
+ <div id="attr-contains-div5" lang="fr-CH"></div>
+ <div id="attr-contains-div6" lang="en-US"></div>
+
+ <p id="attr-contains-p1" class=" apple banana orange "></p>
+ </div>
+
+ <div id="pseudo-nth">
+ <table id="pseudo-nth-table1">
+ <tr id="pseudo-nth-tr1"><td id="pseudo-nth-td1"></td><td id="pseudo-nth-td2"></td><td id="pseudo-nth-td3"></td><td id="pseudo-nth-td4"></td><td id="pseudo-nth--td5"></td><td id="pseudo-nth-td6"></td></tr>
+ <tr id="pseudo-nth-tr2"><td id="pseudo-nth-td7"></td><td id="pseudo-nth-td8"></td><td id="pseudo-nth-td9"></td><td id="pseudo-nth-td10"></td><td id="pseudo-nth-td11"></td><td id="pseudo-nth-td12"></td></tr>
+ <tr id="pseudo-nth-tr3"><td id="pseudo-nth-td13"></td><td id="pseudo-nth-td14"></td><td id="pseudo-nth-td15"></td><td id="pseudo-nth-td16"></td><td id="pseudo-nth-td17"></td><td id="pseudo-nth-td18"></td></tr>
+ </table>
+
+ <ol id="pseudo-nth-ol1">
+ <li id="pseudo-nth-li1"></li>
+ <li id="pseudo-nth-li2"></li>
+ <li id="pseudo-nth-li3"></li>
+ <li id="pseudo-nth-li4"></li>
+ <li id="pseudo-nth-li5"></li>
+ <li id="pseudo-nth-li6"></li>
+ <li id="pseudo-nth-li7"></li>
+ <li id="pseudo-nth-li8"></li>
+ <li id="pseudo-nth-li9"></li>
+ <li id="pseudo-nth-li10"></li>
+ <li id="pseudo-nth-li11"></li>
+ <li id="pseudo-nth-li12"></li>
+ </ol>
+
+ <p id="pseudo-nth-p1">
+ <span id="pseudo-nth-span1">span1</span>
+ <em id="pseudo-nth-em1">em1</em>
+ <!-- comment node-->
+ <em id="pseudo-nth-em2">em2</em>
+ <span id="pseudo-nth-span2">span2</span>
+ <strong id="pseudo-nth-strong1">strong1</strong>
+ <em id="pseudo-nth-em3">em3</em>
+ <span id="pseudo-nth-span3">span3</span>
+ <span id="pseudo-nth-span4">span4</span>
+ <strong id="pseudo-nth-strong2">strong2</strong>
+ <em id="pseudo-nth-em4">em4</em>
+ </p>
+ </div>
+
+ <div id="pseudo-first-child">
+ <div id="pseudo-first-child-div1"></div>
+ <div id="pseudo-first-child-div2"></div>
+ <div id="pseudo-first-child-div3"></div>
+
+ <p id="pseudo-first-child-p1"><span id="pseudo-first-child-span1"></span><span id="pseudo-first-child-span2"></span></p>
+ <p id="pseudo-first-child-p2"><span id="pseudo-first-child-span3"></span><span id="pseudo-first-child-span4"></span></p>
+ <p id="pseudo-first-child-p3"><span id="pseudo-first-child-span5"></span><span id="pseudo-first-child-span6"></span></p>
+ </div>
+
+ <div id="pseudo-last-child">
+ <p id="pseudo-last-child-p1"><span id="pseudo-last-child-span1"></span><span id="pseudo-last-child-span2"></span></p>
+ <p id="pseudo-last-child-p2"><span id="pseudo-last-child-span3"></span><span id="pseudo-last-child-span4"></span></p>
+ <p id="pseudo-last-child-p3"><span id="pseudo-last-child-span5"></span><span id="pseudo-last-child-span6"></span></p>
+
+ <div id="pseudo-last-child-div1"></div>
+ <div id="pseudo-last-child-div2"></div>
+ <div id="pseudo-last-child-div3"></div>
+ </div>
+
+ <div id="pseudo-only">
+ <p id="pseudo-only-p1">
+ <span id="pseudo-only-span1"></span>
+ </p>
+ <p id="pseudo-only-p2">
+ <span id="pseudo-only-span2"></span>
+ <span id="pseudo-only-span3"></span>
+ </p>
+ <p id="pseudo-only-p3">
+ <span id="pseudo-only-span4"></span>
+ <em id="pseudo-only-em1"></em>
+ <span id="pseudo-only-span5"></span>
+ </p>
+ </div>>
+
+ <div id="pseudo-empty">
+ <p id="pseudo-empty-p1"></p>
+ <p id="pseudo-empty-p2"><!-- comment node --></p>
+ <p id="pseudo-empty-p3"> </p>
+ <p id="pseudo-empty-p4">Text node</p>
+ <p id="pseudo-empty-p5"><span id="pseudo-empty-span1"></span></p>
+ </div>
+
+ <div id="pseudo-link">
+ <a id="pseudo-link-a1" href="">with href</a>
+ <a id="pseudo-link-a2" href="http://example.org/">with href</a>
+ <a id="pseudo-link-a3">without href</a>
+ <map name="pseudo-link-map1" id="pseudo-link-map1">
+ <area id="pseudo-link-area1" href=""/>
+ <area id="pseudo-link-area2"/>
+ </map>
+ </div>
+
+ <div id="pseudo-lang">
+ <div id="pseudo-lang-div1"></div>
+ <div id="pseudo-lang-div2" lang="fr"></div>
+ <div id="pseudo-lang-div3" lang="en-AU"></div>
+ <div id="pseudo-lang-div4" lang="es"></div>
+ </div>
+
+ <div id="pseudo-ui">
+ <input id="pseudo-ui-input1" type="text"/>
+ <input id="pseudo-ui-input2" type="password"/>
+ <input id="pseudo-ui-input3" type="radio"/>
+ <input id="pseudo-ui-input4" type="radio" checked="checked"/>
+ <input id="pseudo-ui-input5" type="checkbox"/>
+ <input id="pseudo-ui-input6" type="checkbox" checked="checked"/>
+ <input id="pseudo-ui-input7" type="submit"/>
+ <input id="pseudo-ui-input8" type="button"/>
+ <input id="pseudo-ui-input9" type="hidden"/>
+ <textarea id="pseudo-ui-textarea1"></textarea>
+ <button id="pseudo-ui-button1">Enabled</button>
+
+ <input id="pseudo-ui-input10" disabled="disabled" type="text"/>
+ <input id="pseudo-ui-input11" disabled="disabled" type="password"/>
+ <input id="pseudo-ui-input12" disabled="disabled" type="radio"/>
+ <input id="pseudo-ui-input13" disabled="disabled" type="radio" checked="checked"/>
+ <input id="pseudo-ui-input14" disabled="disabled" type="checkbox"/>
+ <input id="pseudo-ui-input15" disabled="disabled" type="checkbox" checked="checked"/>
+ <input id="pseudo-ui-input16" disabled="disabled" type="submit"/>
+ <input id="pseudo-ui-input17" disabled="disabled" type="button"/>
+ <input id="pseudo-ui-input18" disabled="disabled" type="hidden"/>
+ <textarea id="pseudo-ui-textarea2" disabled="disabled"></textarea>
+ <button id="pseudo-ui-button2" disabled="disabled">Disabled</button>
+ </div>
+
+ <div id="not">
+ <div id="not-div1"></div>
+ <div id="not-div2"></div>
+ <div id="not-div3"></div>
+
+ <p id="not-p1"><span id="not-span1"></span><em id="not-em1"></em></p>
+ <p id="not-p2"><span id="not-span2"></span><em id="not-em2"></em></p>
+ <p id="not-p3"><span id="not-span3"></span><em id="not-em3"></em></p>
+ </div>
+
+ <div id="pseudo-element">All pseudo-element tests</div>
+
+ <div id="class">
+ <p id="class-p1" class="foo class-p bar"></p>
+ <p id="class-p2" class="class-p foo bar"></p>
+ <p id="class-p3" class="foo bar class-p"></p>
+
+ <!-- All permutations of the classes should match -->
+ <div id="class-div1" class="apple orange banana"></div>
+ <div id="class-div2" class="apple banana orange"></div>
+ <p id="class-p4" class="orange apple banana"></p>
+ <div id="class-div3" class="orange banana apple"></div>
+ <p id="class-p6" class="banana apple orange"></p>
+ <div id="class-div4" class="banana orange apple"></div>
+ <div id="class-div5" class="apple orange"></div>
+ <div id="class-div6" class="apple banana"></div>
+ <div id="class-div7" class="orange banana"></div>
+
+ <span id="class-span1" class="台北Táiběi 台北"></span>
+ <span id="class-span2" class="台北"></span>
+
+ <span id="class-span3" class="foo:bar"></span>
+ <span id="class-span4" class="test.foo[5]bar"></span>
+ </div>
+
+ <div id="id">
+ <div id="id-div1"></div>
+ <div id="id-div2"></div>
+
+ <ul id="id-ul1">
+ <li id="id-li-duplicate"></li>
+ <li id="id-li-duplicate"></li>
+ <li id="id-li-duplicate"></li>
+ <li id="id-li-duplicate"></li>
+ </ul>
+
+ <span id="台北Táiběi"></span>
+ <span id="台北"></span>
+
+ <span id="#foo:bar"></span>
+ <span id="test.foo[5]bar"></span>
+ </div>
+
+ <div id="descendant">
+ <div id="descendant-div1" class="descendant-div1">
+ <div id="descendant-div2" class="descendant-div2">
+ <div id="descendant-div3" class="descendant-div3">
+ </div>
+ </div>
+ </div>
+ <div id="descendant-div4" class="descendant-div4"></div>
+ </div>
+
+ <div id="child">
+ <div id="child-div1" class="child-div1">
+ <div id="child-div2" class="child-div2">
+ <div id="child-div3" class="child-div3">
+ </div>
+ </div>
+ </div>
+ <div id="child-div4" class="child-div4"></div>
+ </div>
+
+ <div id="adjacent">
+ <div id="adjacent-div1" class="adjacent-div1"></div>
+ <div id="adjacent-div2" class="adjacent-div2">
+ <div id="adjacent-div3" class="adjacent-div3"></div>
+ </div>
+ <div id="adjacent-div4" class="adjacent-div4">
+ <p id="adjacent-p1" class="adjacent-p1"></p>
+ <div id="adjacent-div5" class="adjacent-div5"></div>
+ </div>
+ <div id="adjacent-div6" class="adjacent-div6"></div>
+ <p id="adjacent-p2" class="adjacent-p2"></p>
+ <p id="adjacent-p3" class="adjacent-p3"></p>
+ </div>
+
+ <div id="sibling">
+ <div id="sibling-div1" class="sibling-div"></div>
+ <div id="sibling-div2" class="sibling-div">
+ <div id="sibling-div3" class="sibling-div"></div>
+ </div>
+ <div id="sibling-div4" class="sibling-div">
+ <p id="sibling-p1" class="sibling-p"></p>
+ <div id="sibling-div5" class="sibling-div"></div>
+ </div>
+ <div id="sibling-div6" class="sibling-div"></div>
+ <p id="sibling-p2" class="sibling-p"></p>
+ <p id="sibling-p3" class="sibling-p"></p>
+ </div>
+
+ <div id="group">
+ <em id="group-em1"></em>
+ <strong id="group-strong1"></strong>
+ </div>
+</div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/ParentNode-querySelector-All.html b/tests/wpt/web-platform-tests/dom/nodes/ParentNode-querySelector-All.html
new file mode 100644
index 00000000000..1899882ed6a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/ParentNode-querySelector-All.html
@@ -0,0 +1,110 @@
+<!DOCTYPE html>
+<meta charset="UTF-8">
+<title>Selectors-API Test Suite: HTML</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="selectors.js"></script>
+<script src="ParentNode-querySelector-All.js"></script>
+<style>iframe { visibility: hidden; position: absolute; }</style>
+
+<div id="log">This test requires JavaScript.</div>
+
+<script>
+var testType = TEST_QSA;
+var docType = "html"; // Only run tests suitable for HTML
+
+var frame = document.createElement("iframe"),
+ doc;
+
+frame.onload = init;
+frame.src = "ParentNode-querySelector-All-content.html#target";
+document.body.appendChild(frame);
+
+function init() {
+ /*
+ * This test suite tests Selectors API methods in 4 different contexts:
+ * 1. Document node
+ * 2. In-document Element node
+ * 3. Detached Element node (an element with no parent, not in the document)
+ * 4. Document Fragment node
+ *
+ * For each context, the following tests are run:
+ *
+ * The interface check tests ensure that each type of node exposes the Selectors API methods
+ *
+ * The special selector tests verify the result of passing special values for the selector parameter,
+ * to ensure that the correct WebIDL processing is performed, such as stringification of null and
+ * undefined and missing parameter. The universal selector is also tested here, rather than with the
+ * rest of ordinary selectors for practical reasons.
+ *
+ * The static list verification tests ensure that the node lists returned by the method remain unchanged
+ * due to subsequent document modication, and that a new list is generated each time the method is
+ * invoked based on the current state of the document.
+ *
+ * The invalid selector tests ensure that SyntaxError is thrown for invalid forms of selectors
+ *
+ * The valid selector tests check the result from querying many different types of selectors, with a
+ * list of expected elements. This checks that querySelector() always returns the first result from
+ * querySelectorAll(), and that all matching elements are correctly returned in tree-order. The tests
+ * can be limited by specifying the test types to run, using the testType variable. The constants for this
+ * can be found in selectors.js.
+ *
+ * All the selectors tested for both the valid and invalid selector tests are found in selectors.js.
+ * See comments in that file for documentation of the format used.
+ *
+ * The ParentNode-querySelector-All.js file contains all the common test functions for running each of the aforementioned tests
+ */
+
+ // Prepare the nodes for testing
+ doc = frame.contentDocument; // Document Node tests
+
+ var element = doc.getElementById("root"); // In-document Element Node tests
+
+ //Setup the namespace tests
+ setupSpecialElements(element);
+
+ var outOfScope = element.cloneNode(true); // Append this to the body before running the in-document
+ // Element tests, but after running the Document tests. This
+ // tests that no elements that are not descendants of element
+ // are selected.
+
+ traverse(outOfScope, function(elem) { // Annotate each element as being a clone; used for verifying
+ elem.setAttribute("data-clone", ""); // that none of these elements ever match.
+ });
+
+
+ var detached = element.cloneNode(true); // Detached Element Node tests
+
+ var fragment = doc.createDocumentFragment(); // Fragment Node tests
+ fragment.appendChild(element.cloneNode(true));
+
+ // Setup Tests
+ interfaceCheck("Document", doc);
+ interfaceCheck("Detached Element", detached);
+ interfaceCheck("Fragment", fragment);
+ interfaceCheck("In-document Element", element);
+
+ runSpecialSelectorTests("Document", doc);
+ runSpecialSelectorTests("Detached Element", detached);
+ runSpecialSelectorTests("Fragment", fragment);
+ runSpecialSelectorTests("In-document Element", element);
+
+ verifyStaticList("Document", doc);
+ verifyStaticList("Detached Element", detached);
+ verifyStaticList("Fragment", fragment);
+ verifyStaticList("In-document Element", element);
+
+ runInvalidSelectorTest("Document", doc, invalidSelectors);
+ runInvalidSelectorTest("Detached Element", detached, invalidSelectors);
+ runInvalidSelectorTest("Fragment", fragment, invalidSelectors);
+ runInvalidSelectorTest("In-document Element", element, invalidSelectors);
+
+ runValidSelectorTest("Document", doc, validSelectors, testType, docType);
+ runValidSelectorTest("Detached Element", detached, validSelectors, testType, docType);
+ runValidSelectorTest("Fragment", fragment, validSelectors, testType, docType);
+
+ doc.body.appendChild(outOfScope); // Append before in-document Element tests.
+ // None of these elements should match
+ runValidSelectorTest("In-document Element", element, validSelectors, testType, docType);
+}
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/ParentNode-querySelector-All.js b/tests/wpt/web-platform-tests/dom/nodes/ParentNode-querySelector-All.js
new file mode 100644
index 00000000000..064c1dcc7b2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/ParentNode-querySelector-All.js
@@ -0,0 +1,255 @@
+// Require selectors.js to be included before this.
+
+/*
+ * Create and append special elements that cannot be created correctly with HTML markup alone.
+ */
+function setupSpecialElements(parent) {
+ // Setup null and undefined tests
+ parent.appendChild(doc.createElement("null"));
+ parent.appendChild(doc.createElement("undefined"));
+
+ // Setup namespace tests
+ var anyNS = doc.createElement("div");
+ var noNS = doc.createElement("div");
+ anyNS.id = "any-namespace";
+ noNS.id = "no-namespace";
+
+ var divs;
+ div = [doc.createElement("div"),
+ doc.createElementNS("http://www.w3.org/1999/xhtml", "div"),
+ doc.createElementNS("", "div"),
+ doc.createElementNS("http://www.example.org/ns", "div")];
+
+ div[0].id = "any-namespace-div1";
+ div[1].id = "any-namespace-div2";
+ div[2].setAttribute("id", "any-namespace-div3"); // Non-HTML elements can't use .id property
+ div[3].setAttribute("id", "any-namespace-div4");
+
+ for (var i = 0; i < div.length; i++) {
+ anyNS.appendChild(div[i])
+ }
+
+ div = [doc.createElement("div"),
+ doc.createElementNS("http://www.w3.org/1999/xhtml", "div"),
+ doc.createElementNS("", "div"),
+ doc.createElementNS("http://www.example.org/ns", "div")];
+
+ div[0].id = "no-namespace-div1";
+ div[1].id = "no-namespace-div2";
+ div[2].setAttribute("id", "no-namespace-div3"); // Non-HTML elements can't use .id property
+ div[3].setAttribute("id", "no-namespace-div4");
+
+ for (i = 0; i < div.length; i++) {
+ noNS.appendChild(div[i])
+ }
+
+ parent.appendChild(anyNS);
+ parent.appendChild(noNS);
+}
+
+/*
+ * Check that the querySelector and querySelectorAll methods exist on the given Node
+ */
+function interfaceCheck(type, obj) {
+ test(function() {
+ var q = typeof obj.querySelector === "function";
+ assert_true(q, type + " supports querySelector.");
+ }, type + " supports querySelector")
+
+ test(function() {
+ var qa = typeof obj.querySelectorAll === "function";
+ assert_true( qa, type + " supports querySelectorAll.");
+ }, type + " supports querySelectorAll")
+
+ test(function() {
+ var list = obj.querySelectorAll("div");
+ if (obj.ownerDocument) { // The object is not a Document
+ assert_true(list instanceof obj.ownerDocument.defaultView.NodeList, "The result should be an instance of a NodeList")
+ } else { // The object is a Document
+ assert_true(list instanceof obj.defaultView.NodeList, "The result should be an instance of a NodeList")
+ }
+ }, type + ".querySelectorAll returns NodeList instance")
+}
+
+/*
+ * Verify that the NodeList returned by querySelectorAll is static and and that a new list is created after
+ * each call. A static list should not be affected by subsequent changes to the DOM.
+ */
+function verifyStaticList(type, root) {
+ var pre, post, preLength;
+
+ test(function() {
+ pre = root.querySelectorAll("div");
+ preLength = pre.length;
+
+ var div = doc.createElement("div");
+ (root.body || root).appendChild(div);
+
+ assert_equals(pre.length, preLength, "The length of the NodeList should not change.")
+ }, type + ": static NodeList")
+
+ test(function() {
+ post = root.querySelectorAll("div"),
+ assert_equals(post.length, preLength + 1, "The length of the new NodeList should be 1 more than the previous list.")
+ }, type + ": new NodeList")
+}
+
+/*
+ * Verify handling of special values for the selector parameter, including stringification of
+ * null and undefined, and the handling of the empty string.
+ */
+function runSpecialSelectorTests(type, root) {
+ test(function() { // 1
+ assert_equals(root.querySelectorAll(null).length, 1, "This should find one element with the tag name 'NULL'.");
+ }, type + ".querySelectorAll null")
+
+ test(function() { // 2
+ assert_equals(root.querySelectorAll(undefined).length, 1, "This should find one element with the tag name 'UNDEFINED'.");
+ }, type + ".querySelectorAll undefined")
+
+ test(function() { // 3
+ assert_throws(TypeError(), function() {
+ root.querySelectorAll();
+ }, "This should throw a TypeError.")
+ }, type + ".querySelectorAll no parameter")
+
+ test(function() { // 4
+ var elm = root.querySelector(null)
+ assert_not_equals(elm, null, "This should find an element.");
+ assert_equals(elm.tagName.toUpperCase(), "NULL", "The tag name should be 'NULL'.")
+ }, type + ".querySelector null")
+
+ test(function() { // 5
+ var elm = root.querySelector(undefined)
+ assert_not_equals(elm, undefined, "This should find an element.");
+ assert_equals(elm.tagName.toUpperCase(), "UNDEFINED", "The tag name should be 'UNDEFINED'.")
+ }, type + ".querySelector undefined")
+
+ test(function() { // 6
+ assert_throws(TypeError(), function() {
+ root.querySelector();
+ }, "This should throw a TypeError.")
+ }, type + ".querySelector no parameter")
+
+ test(function() { // 7
+ result = root.querySelectorAll("*");
+ var i = 0;
+ traverse(root, function(elem) {
+ if (elem !== root) {
+ assert_equals(elem, result[i], "The result in index " + i + " should be in tree order.");
+ i++;
+ }
+ })
+ }, type + ".querySelectorAll tree order");
+}
+
+/*
+ * Execute queries with the specified valid selectors for both querySelector() and querySelectorAll()
+ * Only run these tests when results are expected. Don't run for syntax error tests.
+ */
+function runValidSelectorTest(type, root, selectors, testType, docType) {
+ var nodeType = "";
+ switch (root.nodeType) {
+ case Node.DOCUMENT_NODE:
+ nodeType = "document";
+ break;
+ case Node.ELEMENT_NODE:
+ nodeType = root.parentNode ? "element" : "detached";
+ break;
+ case Node.DOCUMENT_FRAGMENT_NODE:
+ nodeType = "fragment";
+ break;
+ default:
+ console.log("Reached unreachable code path.");
+ nodeType = "unknown"; // This should never happen.
+ }
+
+ for (var i = 0; i < selectors.length; i++) {
+ var s = selectors[i];
+ var n = s["name"];
+ var q = s["selector"];
+ var e = s["expect"];
+
+ if ((!s["exclude"] || (s["exclude"].indexOf(nodeType) === -1 && s["exclude"].indexOf(docType) === -1))
+ && (s["testType"] & testType) ) {
+ //console.log("Running tests " + nodeType + ": " + s["testType"] + "&" + testType + "=" + (s["testType"] & testType) + ": " + JSON.stringify(s))
+ var foundall, found;
+
+ test(function() {
+ foundall = root.querySelectorAll(q);
+ assert_not_equals(foundall, null, "The method should not return null.")
+ assert_equals(foundall.length, e.length, "The method should return the expected number of matches.")
+
+ for (var i = 0; i < e.length; i++) {
+ assert_not_equals(foundall[i], null, "The item in index " + i + " should not be null.")
+ assert_equals(foundall[i].getAttribute("id"), e[i], "The item in index " + i + " should have the expected ID.");
+ assert_false(foundall[i].hasAttribute("data-clone"), "This should not be a cloned element.");
+ }
+ }, type + ".querySelectorAll: " + n + ": " + q);
+
+ test(function() {
+ found = root.querySelector(q);
+
+ if (e.length > 0) {
+ assert_not_equals(found, null, "The method should return a match.")
+ assert_equals(found.getAttribute("id"), e[0], "The method should return the first match.");
+ assert_equals(found, foundall[0], "The result should match the first item from querySelectorAll.");
+ assert_false(found.hasAttribute("data-clone"), "This should not be annotated as a cloned element.");
+ } else {
+ assert_equals(found, null, "The method should not match anything.");
+ }
+ }, type + ".querySelector: " + n + ": " + q);
+ } else {
+ //console.log("Excluding for " + nodeType + ": " + s["testType"] + "&" + testType + "=" + (s["testType"] & testType) + ": " + JSON.stringify(s))
+ }
+ }
+}
+
+/*
+ * Execute queries with the specified invalid selectors for both querySelector() and querySelectorAll()
+ * Only run these tests when errors are expected. Don't run for valid selector tests.
+ */
+function runInvalidSelectorTest(type, root, selectors) {
+ for (var i = 0; i < selectors.length; i++) {
+ var s = selectors[i];
+ var n = s["name"];
+ var q = s["selector"];
+
+ test(function() {
+ assert_throws("SyntaxError", function() {
+ root.querySelector(q)
+ })
+ }, type + ".querySelector: " + n + ": " + q);
+
+ test(function() {
+ assert_throws("SyntaxError", function() {
+ root.querySelectorAll(q)
+ })
+ }, type + ".querySelectorAll: " + n + ": " + q);
+ }
+}
+
+function traverse(elem, fn) {
+ if (elem.nodeType === elem.ELEMENT_NODE) {
+ fn(elem);
+ }
+ elem = elem.firstChild;
+ while (elem) {
+ traverse(elem, fn);
+ elem = elem.nextSibling;
+ }
+}
+
+function getNodeType(node) {
+ switch (node.nodeType) {
+ case Node.DOCUMENT_NODE:
+ return "document";
+ case Node.ELEMENT_NODE:
+ return node.parentNode ? "element" : "detached";
+ case Node.DOCUMENT_FRAGMENT_NODE:
+ return "fragment";
+ default:
+ console.log("Reached unreachable code path.");
+ return "unknown"; // This should never happen.
+ }
+}
diff --git a/tests/wpt/web-platform-tests/dom/nodes/ParentNode-querySelector-All.xht b/tests/wpt/web-platform-tests/dom/nodes/ParentNode-querySelector-All.xht
new file mode 100644
index 00000000000..4abd11e8fa0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/ParentNode-querySelector-All.xht
@@ -0,0 +1,114 @@
+<!DOCTYPE html>
+<html id="html" lang="en" xmlns="http://www.w3.org/1999/xhtml">
+<head id="head">
+<title>Selectors-API Test Suite: XHTML</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="selectors.js"></script>
+<script src="ParentNode-querySelector-All.js"></script>
+<style>iframe { visibility: hidden; position: absolute; }</style>
+</head>
+<body>
+<div id="log">This test requires JavaScript.</div>
+
+<script><![CDATA[
+var testType = TEST_QSA;
+var docType = "xhtml"; // Only run tests suitable for XHTML
+
+var frame = document.createElement("iframe"),
+ doc;
+
+frame.onload = init;
+frame.src = "ParentNode-querySelector-All-content.xht#target";
+document.body.appendChild(frame);
+
+function init() {
+ /*
+ * This test suite tests Selectors API methods in 4 different contexts:
+ * 1. Document node
+ * 2. In-document Element node
+ * 3. Detached Element node (an element with no parent, not in the document)
+ * 4. Document Fragment node
+ *
+ * For each context, the following tests are run:
+ *
+ * The interface check tests ensure that each type of node exposes the Selectors API methods
+ *
+ * The special selector tests verify the result of passing special values for the selector parameter,
+ * to ensure that the correct WebIDL processing is performed, such as stringification of null and
+ * undefined and missing parameter. The universal selector is also tested here, rather than with the
+ * rest of ordinary selectors for practical reasons.
+ *
+ * The static list verification tests ensure that the node lists returned by the method remain unchanged
+ * due to subsequent document modication, and that a new list is generated each time the method is
+ * invoked based on the current state of the document.
+ *
+ * The invalid selector tests ensure that SyntaxError is thrown for invalid forms of selectors
+ *
+ * The valid selector tests check the result from querying many different types of selectors, with a
+ * list of expected elements. This checks that querySelector() always returns the first result from
+ * querySelectorAll(), and that all matching elements are correctly returned in tree-order. The tests
+ * can be limited by specifying the test types to run, using the testType variable. The constants for this
+ * can be found in selectors.js.
+ *
+ * All the selectors tested for both the valid and invalid selector tests are found in selectors.js.
+ * See comments in that file for documentation of the format used.
+ *
+ * The ParentNode-querySelector-All.js file contains all the common test functions for running each of the aforementioned tests
+ */
+
+ // Prepare the nodes for testing
+ doc = frame.contentDocument; // Document Node tests
+
+ var element = doc.getElementById("root"); // In-document Element Node tests
+
+ //Setup the namespace tests
+ setupSpecialElements(element);
+
+ var outOfScope = element.cloneNode(true); // Append this to the body before running the in-document
+ // Element tests, but after running the Document tests. This
+ // tests that no elements that are not descendants of element
+ // are selected.
+
+ traverse(outOfScope, function(elem) { // Annotate each element as being a clone; used for verifying
+ elem.setAttribute("data-clone", ""); // that none of these elements ever match.
+ });
+
+
+ var detached = element.cloneNode(true); // Detached Element Node tests
+
+ var fragment = doc.createDocumentFragment(); // Fragment Node tests
+ fragment.appendChild(element.cloneNode(true));
+
+ // Setup Tests
+ interfaceCheck("Document", doc);
+ interfaceCheck("Detached Element", detached);
+ interfaceCheck("Fragment", fragment);
+ interfaceCheck("In-document Element", element);
+
+ runSpecialSelectorTests("Document", doc);
+ runSpecialSelectorTests("Detached Element", detached);
+ runSpecialSelectorTests("Fragment", fragment);
+ runSpecialSelectorTests("In-document Element", element);
+
+ verifyStaticList("Document", doc);
+ verifyStaticList("Detached Element", detached);
+ verifyStaticList("Fragment", fragment);
+ verifyStaticList("In-document Element", element);
+
+ runInvalidSelectorTest("Document", doc, invalidSelectors);
+ runInvalidSelectorTest("Detached Element", detached, invalidSelectors);
+ runInvalidSelectorTest("Fragment", fragment, invalidSelectors);
+ runInvalidSelectorTest("In-document Element", element, invalidSelectors);
+
+ runValidSelectorTest("Document", doc, validSelectors, testType, docType);
+ runValidSelectorTest("Detached Element", detached, validSelectors, testType, docType);
+ runValidSelectorTest("Fragment", fragment, validSelectors, testType, docType);
+
+ doc.body.appendChild(outOfScope); // Append before in-document Element tests.
+ // None of these elements should match
+ runValidSelectorTest("In-document Element", element, validSelectors, testType, docType);
+}
+]]></script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/ProcessingInstruction-literal-1.xhtml b/tests/wpt/web-platform-tests/dom/nodes/ProcessingInstruction-literal-1.xhtml
new file mode 100644
index 00000000000..4eaf86cbdce
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/ProcessingInstruction-literal-1.xhtml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>&lt;?xml?> is not a ProcessingInstruction</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id="log"/>
+<script>
+test(function() {
+ assert_equals(document.firstChild, document.documentElement)
+})
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/ProcessingInstruction-literal-2.xhtml b/tests/wpt/web-platform-tests/dom/nodes/ProcessingInstruction-literal-2.xhtml
new file mode 100644
index 00000000000..d878c697c07
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/ProcessingInstruction-literal-2.xhtml
@@ -0,0 +1,21 @@
+<?xml-stylesheet href="support/style.css" type="text/css"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>ProcessingInstruction literals</title>
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-processinginstruction-target"/>
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-characterdata-data"/>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id="log"/>
+<script>
+test(function() {
+ var pienc = document.firstChild;
+ assert_true(pienc instanceof ProcessingInstruction)
+ assert_equals(pienc.target, "xml-stylesheet")
+ assert_equals(pienc.data, 'href="support/style.css" type="text/css"')
+})
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/Text-constructor.html b/tests/wpt/web-platform-tests/dom/nodes/Text-constructor.html
new file mode 100644
index 00000000000..dbd9a0be01c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/Text-constructor.html
@@ -0,0 +1,11 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Text constructor</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-text">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="Comment-Text-constructor.js"></script>
+<div id="log"></div>
+<script>
+test_constructor("Text");
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/attributes.html b/tests/wpt/web-platform-tests/dom/nodes/attributes.html
new file mode 100644
index 00000000000..f4a993a252f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/attributes.html
@@ -0,0 +1,388 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Attributes tests</title>
+<link rel=help href="https://dom.spec.whatwg.org/#attr">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-element-setattribute">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-element-setattributens">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="attributes.js"></script>
+<script src="productions.js"></script>
+<div id="log"></div>
+<span id="test1"></span>
+<span class="&amp;&lt;&gt;foo"></span>
+<script>
+var XML = "http://www.w3.org/XML/1998/namespace"
+var XMLNS = "http://www.w3.org/2000/xmlns/"
+
+// AttrExodus
+test(function() {
+ document.body.setAttribute("abc", "pass")
+ var attr = document.body.attributes[0]
+ assert_true(attr instanceof Attr)
+ assert_false(attr instanceof Node)
+ assert_throws(new TypeError(), function() { attr.appendChild(document.createTextNode("fail")) })
+ assert_throws(new TypeError(), function() { attr.appendChild(null) })
+ assert_equals(attr.value, "pass")
+ assert_false("childNodes" in attr, "Should not have childNodes")
+}, "AttrExodus")
+
+// setAttribute exhaustive tests
+// Step 1
+test(function() {
+ var el = document.createElement("foo")
+ for (var i = 0; i < invalid_names.length; i++) {
+ assert_throws("INVALID_CHARACTER_ERR", function() { el.setAttribute(invalid_names[i], "test") })
+ }
+}, "When qualifiedName does not match the Name production, an " +
+ "INVALID_CHARACTER_ERR exception is to be thrown. (setAttribute)")
+
+// Step 2
+test(function() {
+ var el = document.createElement("div")
+ el.setAttribute("ALIGN", "left")
+ assert_equals(el.getAttributeNS("", "ALIGN"), null)
+ assert_equals(el.getAttributeNS("", "align"), "left")
+ assert_equals(el.getAttribute("align"), "left")
+}, "setAttribute should lowercase its name argument (upper case attribute)")
+test(function() {
+ var el = document.createElement("div")
+ el.setAttribute("CHEEseCaKe", "tasty")
+ assert_equals(el.getAttributeNS("", "CHEEseCaKe"), null)
+ assert_equals(el.getAttributeNS("", "cheesecake"), "tasty")
+ assert_equals(el.getAttribute("cheesecake"), "tasty")
+}, "setAttribute should lowercase its name argument (mixed case attribute)")
+
+// Step 3
+test(function() {
+ var el = document.createElement("foo")
+ var tests = ["xmlns", "xmlns:a", "xmlnsx", "xmlns0"]
+ for (var i = 0; i < tests.length; i++) {
+ el.setAttribute(tests[i], "success");
+ }
+}, "setAttribute should not throw even when qualifiedName starts with 'xmlns'")
+
+// Step 4
+test(function() {
+ var el = document.createElement("foo")
+ for (var i = 0; i < valid_names.length; i++) {
+ el.setAttribute(valid_names[i], "test")
+ assert_equals(el.getAttribute(valid_names[i]), "test")
+ }
+}, "Basic functionality should be intact.")
+
+// Step 5
+test(function() {
+ var el = document.createElement("foo")
+ el.setAttribute("a", "1")
+ el.setAttribute("b", "2")
+ el.setAttribute("a", "3")
+ el.setAttribute("c", "4")
+ attributes_are(el, [["a", "3"],
+ ["b", "2"],
+ ["c", "4"]])
+}, "setAttribute should not change the order of previously set attributes.")
+test(function() {
+ var el = document.createElement("baz")
+ el.setAttributeNS("ab", "attr", "fail")
+ el.setAttributeNS("kl", "attr", "pass")
+ el.setAttribute("attr", "pass")
+ attributes_are(el, [["attr", "pass", "ab"],
+ ["attr", "pass", "kl"]])
+}, "setAttribute should set the first attribute with the given name")
+test(function() {
+ // Based on a test by David Flanagan.
+ var el = document.createElement("baz")
+ el.setAttributeNS("foo", "foo:bar", "1");
+ assert_equals(el.getAttribute("foo:bar"), "1")
+ attr_is(el.attributes[0], "1", "bar", "foo", "foo", "foo:bar")
+ el.setAttribute("foo:bar", "2");
+ assert_equals(el.getAttribute("foo:bar"), "2")
+ attr_is(el.attributes[0], "2", "bar", "foo", "foo", "foo:bar")
+}, "setAttribute should set the attribute with the given qualified name")
+
+// setAttributeNS exhaustive tests
+// Step 1
+test(function() {
+ var el = document.createElement("foo")
+ for (var i = 0, il = invalid_names.length; i < il; ++i) {
+ assert_throws("INVALID_CHARACTER_ERR",
+ function() { el.setAttributeNS("a", invalid_names[i], "fail") })
+ }
+}, "When qualifiedName does not match the Name production, an " +
+ "INVALID_CHARACTER_ERR exception is to be thrown. (setAttributeNS)")
+
+// Step 2
+test(function() {
+ var el = document.createElement("foo")
+ for (var i = 0, il = invalid_qnames.length; i < il; ++i) {
+ assert_throws("NAMESPACE_ERR",
+ function() { el.setAttributeNS("a", invalid_qnames[i], "fail") },
+ "Expected exception for " + invalid_qnames[i] + ".")
+ }
+}, "When qualifiedName does not match the QName production, an " +
+ "NAMESPACE_ERR exception is to be thrown.")
+
+// Step 3
+test(function() {
+ var el = document.createElement("foo")
+ el.setAttributeNS(null, "aa", "bb")
+ el.setAttributeNS("", "xx", "bb")
+ attributes_are(el, [["aa", "bb"],
+ ["xx", "bb"]])
+}, "null and the empty string should result in a null namespace.")
+
+// Step 4
+test(function() {
+ var el = document.createElement("foo")
+ assert_throws("NAMESPACE_ERR",
+ function() { el.setAttributeNS("", "aa:bb", "fail") })
+ assert_throws("NAMESPACE_ERR",
+ function() { el.setAttributeNS(null, "aa:bb", "fail") })
+}, "A namespace is required to use a prefix.")
+
+// Step 5
+test(function() {
+ var el = document.createElement("foo")
+ assert_throws("NAMESPACE_ERR",
+ function() { el.setAttributeNS("a", "xml:bb", "fail") })
+}, "The xml prefix should not be allowed for arbitrary namespaces")
+test(function() {
+ var el = document.createElement("foo")
+ el.setAttributeNS(XML, "a:bb", "pass")
+ assert_equals(el.attributes.length, 1)
+ attr_is(el.attributes[0], "pass", "bb", XML, "a", "a:bb")
+}, "XML-namespaced attributes don't need an xml prefix")
+
+// Step 6
+test(function() {
+ var el = document.createElement("foo")
+ assert_throws("NAMESPACE_ERR",
+ function() { el.setAttributeNS("a", "xmlns:bb", "fail") })
+}, "The xmlns prefix should not be allowed for arbitrary namespaces")
+test(function() {
+ var el = document.createElement("foo")
+ assert_throws("NAMESPACE_ERR",
+ function() { el.setAttributeNS("a", "xmlns", "fail") })
+}, "The xmlns qualified name should not be allowed for arbitrary namespaces")
+test(function() {
+ var el = document.createElement("foo")
+ el.setAttributeNS("ns", "a:xmlns", "pass")
+ assert_equals(el.attributes.length, 1)
+ attr_is(el.attributes[0], "pass", "xmlns", "ns", "a", "a:xmlns")
+}, "xmlns should be allowed as local name")
+
+// Step 7
+test(function() {
+ var el = document.createElement("foo")
+ assert_throws("NAMESPACE_ERR",
+ function() { el.setAttributeNS(XMLNS, "a:xmlns", "fail") })
+ assert_throws("NAMESPACE_ERR",
+ function() { el.setAttributeNS(XMLNS, "b:foo", "fail") })
+}, "The XMLNS namespace should require xmlns as prefix or qualified name")
+test(function() {
+ var el = document.createElement("foo")
+ el.setAttributeNS(XMLNS, "xmlns:a", "pass")
+ assert_equals(el.attributes.length, 1)
+ attr_is(el.attributes[0], "pass", "a", XMLNS, "xmlns", "xmlns:a")
+}, "xmlns should be allowed as prefix in the XMLNS namespace")
+test(function() {
+ var el = document.createElement("foo")
+ el.setAttributeNS(XMLNS, "xmlns", "pass")
+ assert_equals(el.attributes.length, 1)
+ attr_is(el.attributes[0], "pass", "xmlns", XMLNS, null, "xmlns")
+}, "xmlns should be allowed as qualified name in the XMLNS namespace")
+
+// Step 8-9
+test(function() {
+ var el = document.createElement("foo")
+ el.setAttributeNS("a", "foo:bar", "X")
+ assert_equals(el.attributes.length, 1)
+ attr_is(el.attributes[0], "X", "bar", "a", "foo", "foo:bar")
+
+ el.setAttributeNS("a", "quux:bar", "Y")
+ assert_equals(el.attributes.length, 1)
+ attr_is(el.attributes[0], "Y", "bar", "a", "foo", "foo:bar")
+ el.removeAttributeNS("a", "bar")
+}, "Setting the same attribute with another prefix should not change the prefix")
+
+// Miscellaneous tests
+test(function() {
+ var el = document.createElement("iframe")
+ el.setAttribute("src", "file:///home")
+ assert_equals(el.getAttribute("src"), "file:///home")
+}, "setAttribute should not throw even if a load is not allowed")
+test(function() {
+ var docFragment = document.createDocumentFragment()
+ var newOne = document.createElement("newElement")
+ newOne.setAttribute("newdomestic", "Yes")
+ docFragment.appendChild(newOne)
+ var domesticNode = docFragment.firstChild
+ var attr = domesticNode.attributes.item(0)
+ attr_is(attr, "Yes", "newdomestic", null, null, "newdomestic")
+}, "Attributes should work in document fragments.")
+test(function() {
+ var el = document.createElement("foo")
+ el.setAttribute("x", "y")
+ var attr = el.attributes[0]
+ attr.value = "Y&lt;"
+ attr_is(attr, "Y&lt;", "x", null, null, "x")
+ assert_equals(el.getAttribute("x"), "Y&lt;")
+}, "Attribute values should not be parsed.")
+test(function() {
+ var el = document.getElementsByTagName("span")[0]
+ attr_is(el.attributes[0], "test1", "id", null, null, "id")
+}, "Specified attributes should be accessible.")
+test(function() {
+ var el = document.getElementsByTagName("span")[1]
+ attr_is(el.attributes[0], "&<>foo", "class", null, null, "class")
+}, "Entities in attributes should have been expanded while parsing.")
+
+test(function() {
+ var el = document.createElement("div")
+ assert_equals(el.hasAttribute("bar"), false)
+ assert_equals(el.hasAttributeNS(null, "bar"), false)
+ assert_equals(el.hasAttributeNS("", "bar"), false)
+ assert_equals(el.getAttribute("bar"), null)
+ assert_equals(el.getAttributeNS(null, "bar"), null)
+ assert_equals(el.getAttributeNS("", "bar"), null)
+}, "Unset attributes return null")
+test(function() {
+ var el = document.createElement("div")
+ el.setAttributeNS("ab", "attr", "t1")
+ el.setAttributeNS("kl", "attr", "t2")
+ assert_equals(el.hasAttribute("attr"), true)
+ assert_equals(el.hasAttributeNS("ab", "attr"), true)
+ assert_equals(el.hasAttributeNS("kl", "attr"), true)
+ assert_equals(el.getAttribute("attr"), "t1")
+ assert_equals(el.getAttributeNS("ab", "attr"), "t1")
+ assert_equals(el.getAttributeNS("kl", "attr"), "t2")
+ assert_equals(el.getAttributeNS(null, "attr"), null)
+ assert_equals(el.getAttributeNS("", "attr"), null)
+}, "First set attribute is returned by getAttribute")
+test(function() {
+ var el = document.createElement("div")
+ el.setAttribute("style", "color:#fff;")
+ assert_equals(el.hasAttribute("style"), true)
+ assert_equals(el.hasAttributeNS(null, "style"), true)
+ assert_equals(el.hasAttributeNS("", "style"), true)
+ assert_equals(el.getAttribute("style"), "color:#fff;")
+ assert_equals(el.getAttributeNS(null, "style"), "color:#fff;")
+ assert_equals(el.getAttributeNS("", "style"), "color:#fff;")
+}, "Style attributes are not normalized")
+test(function() {
+ var el = document.createElement("div")
+ el.setAttributeNS("", "ALIGN", "left")
+ assert_equals(el.hasAttribute("ALIGN"), false)
+ assert_equals(el.hasAttribute("align"), false)
+ assert_equals(el.hasAttributeNS(null, "ALIGN"), true)
+ assert_equals(el.hasAttributeNS(null, "align"), false)
+ assert_equals(el.hasAttributeNS("", "ALIGN"), true)
+ assert_equals(el.hasAttributeNS("", "align"), false)
+ assert_equals(el.getAttribute("ALIGN"), null)
+ assert_equals(el.getAttribute("align"), null)
+ assert_equals(el.getAttributeNS(null, "ALIGN"), "left")
+ assert_equals(el.getAttributeNS("", "ALIGN"), "left")
+ assert_equals(el.getAttributeNS(null, "align"), null)
+ assert_equals(el.getAttributeNS("", "align"), null)
+ el.removeAttributeNS("", "ALIGN")
+}, "Only lowercase attributes are returned on HTML elements (upper case attribute)")
+test(function() {
+ var el = document.createElement("div")
+ el.setAttributeNS("", "CHEEseCaKe", "tasty")
+ assert_equals(el.hasAttribute("CHEESECAKE"), false)
+ assert_equals(el.hasAttribute("CHEEseCaKe"), false)
+ assert_equals(el.hasAttribute("cheesecake"), false)
+ assert_equals(el.hasAttributeNS("", "CHEESECAKE"), false)
+ assert_equals(el.hasAttributeNS("", "CHEEseCaKe"), true)
+ assert_equals(el.hasAttributeNS("", "cheesecake"), false)
+ assert_equals(el.hasAttributeNS(null, "CHEESECAKE"), false)
+ assert_equals(el.hasAttributeNS(null, "CHEEseCaKe"), true)
+ assert_equals(el.hasAttributeNS(null, "cheesecake"), false)
+ assert_equals(el.getAttribute("CHEESECAKE"), null)
+ assert_equals(el.getAttribute("CHEEseCaKe"), null)
+ assert_equals(el.getAttribute("cheesecake"), null)
+ assert_equals(el.getAttributeNS(null, "CHEESECAKE"), null)
+ assert_equals(el.getAttributeNS("", "CHEESECAKE"), null)
+ assert_equals(el.getAttributeNS(null, "CHEEseCaKe"), "tasty")
+ assert_equals(el.getAttributeNS("", "CHEEseCaKe"), "tasty")
+ assert_equals(el.getAttributeNS(null, "cheesecake"), null)
+ assert_equals(el.getAttributeNS("", "cheesecake"), null)
+ el.removeAttributeNS("", "CHEEseCaKe")
+}, "Only lowercase attributes are returned on HTML elements (mixed case attribute)")
+test(function() {
+ var el = document.createElement("div")
+ document.body.appendChild(el)
+ el.setAttributeNS("", "align", "left")
+ el.setAttributeNS("xx", "align", "right")
+ el.setAttributeNS("", "foo", "left")
+ el.setAttributeNS("xx", "foo", "right")
+ assert_equals(el.hasAttribute("align"), true)
+ assert_equals(el.hasAttribute("foo"), true)
+ assert_equals(el.hasAttributeNS("xx", "align"), true)
+ assert_equals(el.hasAttributeNS(null, "foo"), true)
+ assert_equals(el.getAttribute("align"), "left")
+ assert_equals(el.getAttribute("foo"), "left")
+ assert_equals(el.getAttributeNS("xx", "align"), "right")
+ assert_equals(el.getAttributeNS(null, "foo"), "left")
+ assert_equals(el.getAttributeNS("", "foo"), "left")
+ el.removeAttributeNS("", "align")
+ el.removeAttributeNS("xx", "align")
+ el.removeAttributeNS("", "foo")
+ el.removeAttributeNS("xx", "foo")
+ document.body.removeChild(el)
+}, "First set attribute is returned with mapped attribute set first")
+test(function() {
+ var el = document.createElement("div")
+ el.setAttributeNS("xx", "align", "right")
+ el.setAttributeNS("", "align", "left")
+ el.setAttributeNS("xx", "foo", "right")
+ el.setAttributeNS("", "foo", "left")
+ assert_equals(el.hasAttribute("align"), true)
+ assert_equals(el.hasAttribute("foo"), true)
+ assert_equals(el.hasAttributeNS("xx", "align"), true)
+ assert_equals(el.hasAttributeNS(null, "foo"), true)
+ assert_equals(el.getAttribute("align"), "right")
+ assert_equals(el.getAttribute("foo"), "right")
+ assert_equals(el.getAttributeNS("xx", "align"), "right")
+ assert_equals(el.getAttributeNS(null, "foo"), "left")
+ assert_equals(el.getAttributeNS("", "foo"), "left")
+ el.removeAttributeNS("", "align")
+ el.removeAttributeNS("xx", "align")
+ el.removeAttributeNS("", "foo")
+ el.removeAttributeNS("xx", "foo")
+}, "First set attribute is returned with mapped attribute set later")
+
+test(function() {
+ var el = document.createElementNS("http://www.example.com", "foo")
+ el.setAttribute("A", "test")
+ assert_equals(el.hasAttribute("A"), true, "hasAttribute()")
+ assert_equals(el.hasAttributeNS("", "A"), true, "el.hasAttributeNS(\"\")")
+ assert_equals(el.hasAttributeNS(null, "A"), true, "el.hasAttributeNS(null)")
+ assert_equals(el.hasAttributeNS(undefined, "A"), true, "el.hasAttributeNS(undefined)")
+ assert_equals(el.hasAttributeNS("foo", "A"), false, "el.hasAttributeNS(\"foo\")")
+
+ assert_equals(el.getAttribute("A"), "test", "getAttribute()")
+ assert_equals(el.getAttributeNS("", "A"), "test", "el.getAttributeNS(\"\")")
+ assert_equals(el.getAttributeNS(null, "A"), "test", "el.getAttributeNS(null)")
+ assert_equals(el.getAttributeNS(undefined, "A"), "test", "el.getAttributeNS(undefined)")
+ assert_equals(el.getAttributeNS("foo", "A"), null, "el.getAttributeNS(\"foo\")")
+}, "Non-HTML element with upper-case attribute")
+
+test(function() {
+ var el = document.createElement("div")
+ el.setAttribute("pre:fix", "value 1")
+ el.setAttribute("fix", "value 2")
+
+ var prefixed = el.attributes[0]
+ assert_equals(prefixed.localName, "pre:fix", "prefixed local name")
+ assert_equals(prefixed.namespaceURI, null, "prefixed namespace")
+
+ var unprefixed = el.attributes[1]
+ assert_equals(unprefixed.localName, "fix", "unprefixed local name")
+ assert_equals(unprefixed.namespaceURI, null, "unprefixed namespace")
+
+ el.removeAttributeNS(null, "pre:fix")
+ assert_equals(el.attributes[0], unprefixed)
+}, "Attribute with prefix in local name")
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/attributes.js b/tests/wpt/web-platform-tests/dom/nodes/attributes.js
new file mode 100644
index 00000000000..096dd5fd7a3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/attributes.js
@@ -0,0 +1,17 @@
+function attr_is(attr, v, ln, ns, p, n) {
+ assert_equals(attr.value, v)
+ assert_equals(attr.nodeValue, v)
+ assert_equals(attr.textContent, v)
+ assert_equals(attr.localName, ln)
+ assert_equals(attr.namespaceURI, ns)
+ assert_equals(attr.prefix, p)
+ assert_equals(attr.name, n)
+ assert_equals(attr.specified, true)
+}
+
+function attributes_are(el, l) {
+ for (var i = 0, il = l.length; i < il; i++) {
+ attr_is(el.attributes[i], l[i][1], l[i][0], (l[i].length < 3) ? null : l[i][2], null, l[i][0])
+ assert_equals(el.attributes[i].ownerElement, el)
+ }
+}
diff --git a/tests/wpt/web-platform-tests/dom/nodes/case.html b/tests/wpt/web-platform-tests/dom/nodes/case.html
new file mode 100644
index 00000000000..c3c195141c3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/case.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Tests for case-sensitivity in APIs</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-document-createelement">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-document-createelementns">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-document-getelementsbytagname">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-document-getelementsbytagnamens">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-element-setattribute">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-element-setattributens">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-element-hasattribute">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-element-hasattributens">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-element-getelementsbytagname">
+<link rel=help href="https://dom.spec.whatwg.org/#dom-element-getelementsbytagnamens">
+<script>var is_html = true;</script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="case.js"></script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/case.js b/tests/wpt/web-platform-tests/dom/nodes/case.js
new file mode 100644
index 00000000000..fb28b9514a3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/case.js
@@ -0,0 +1,179 @@
+/*
+ * document.createElement(NS)
+ *
+ * document.getElementsByTagName(NS)
+ *
+ * Element.setAttribute(NS)
+ *
+ * Element.getAttribute(NS)
+ * Element.hasAttribute(NS)
+ * Element.getElementsByTagName(NS)
+ */
+
+var tests = [];
+setup(function() {
+ var name_inputs = ["abc", "Abc", "ABC", "ä", "Ä"];
+ var namespaces = ["http://www.w3.org/1999/xhtml", "http://www.w3.org/2000/svg", "http://FOO"];
+ name_inputs.forEach(function(x) {
+ tests.push(["createElement " + x, test_create_element, [x]]);
+ tests.push(["setAttribute " +x, test_set_attribute, [x]]);
+ tests.push(["getAttribute " +x, test_get_attribute, [x]]);
+ tests.push(["getElementsByTagName a:" +x, test_get_elements_tag_name,
+ [outer_product(namespaces, ["a"], name_inputs),
+ x]]);
+ tests.push(["getElementsByTagName " +x, test_get_elements_tag_name,
+ [outer_product(namespaces, [null], name_inputs),
+ x]]);
+ });
+ outer_product(namespaces, name_inputs, name_inputs).forEach(function(x) {
+ tests.push(["createElementNS " + x, test_create_element_ns, x]);
+ tests.push(["setAttributeNS " + x, test_set_attribute_ns, x]);
+ tests.push(["getAttributeNS " + x, test_get_attribute_ns, x]);
+ });
+ outer_product([null].concat(namespaces), name_inputs).forEach(function(x) {
+ tests.push(["getElementsByTagNameNS " + x, test_get_elements_tag_name_ns,
+ outer_product(namespaces, name_inputs), x]);
+ });
+ name_inputs.forEach(function(x) {
+ tests.push(["createElementNS " + x, test_create_element_ns, [null, null, x]]);
+ tests.push(["setAttributeNS " + x, test_set_attribute_ns, [null, null, x]]);
+ tests.push(["getAttributeNS " + x, test_get_attribute_ns, [null, null, x]]);
+ });
+
+ });
+function outer_product() {
+ var rv = [];
+ function compute_outer_product() {
+ var args = Array.prototype.slice.call(arguments);
+ var index = args[0];
+ if (index < args.length) {
+ args[index].forEach(function(x) {
+ compute_outer_product.apply(this, [index+1].concat(args.slice(1, index), x, args.slice(index+1)));
+ });
+ } else {
+ rv.push(args.slice(1));
+ }
+ }
+ compute_outer_product.apply(this, [1].concat(Array.prototype.slice.call(arguments)));
+ return rv;
+}
+
+function expected_case(input) {
+ //is_html gets set by a global on the page loading the tests
+ if (is_html) {
+ return ascii_lowercase(input);
+ } else {
+ return input;
+ }
+}
+
+function ascii_lowercase(input) {
+ return input.replace(/[A-Z]/g, function(x) {
+ return x.toLowerCase();
+ });
+}
+
+function test_create_element(name) {
+ var node = document.createElement(name);
+ assert_equals(node.localName, expected_case(name));
+}
+
+function test_create_element_ns(namespace, prefix, local_name) {
+ var qualified_name = prefix ? prefix + ":" + local_name : local_name;
+ var node = document.createElementNS(namespace, qualified_name);
+ assert_equals(node.prefix, prefix, "prefix");
+ assert_equals(node.localName, local_name, "localName");
+}
+
+function test_set_attribute(name) {
+ var node = document.createElement("div");
+ node.setAttribute(name, "test");
+ assert_equals(node.attributes[0].localName, expected_case(name));
+}
+
+function test_set_attribute_ns(namespace, prefix, local_name) {
+ var qualified_name = prefix ? prefix + ":" + local_name : local_name;
+ var node = document.createElement("div");
+ node.setAttributeNS(namespace, qualified_name, "test");
+ var attr = node.attributes[0];
+ assert_equals(attr.prefix, prefix, "prefix");
+ assert_equals(attr.localName, local_name, "localName");
+}
+
+function test_get_attribute(name) {
+ var node = document.createElement("div");
+ node.setAttribute(name, "test");
+ var expected_name = expected_case(name);
+ assert_equals(node.getAttribute(expected_name), "test");
+ if (expected_name != name) {
+ assert_equals(node.getAttribute(expected_name), "test");
+ } else if (name !== ascii_lowercase(name)) {
+ assert_equals(node.getAttribute(ascii_lowercase(name)), null);
+ }
+}
+
+function test_get_attribute_ns(namespace, prefix, local_name) {
+ var qualified_name = prefix ? prefix + ":" + local_name : local_name;
+ var node = document.createElement("div");
+ node.setAttributeNS(namespace, qualified_name, "test");
+ var expected_name = local_name;
+ assert_equals(node.getAttributeNS(namespace, expected_name), "test");
+ if (local_name !== ascii_lowercase(local_name)) {
+ assert_equals(node.getAttributeNS(namespace, ascii_lowercase(local_name)), null);
+ }
+}
+
+function test_get_elements_tag_name(elements_to_create, search_string) {
+ var container = document.createElement("div");
+ elements_to_create.forEach(function(x) {
+ var qualified_name = x[1] ? x[1] + ":" + x[2] : x[2];
+ var element = document.createElementNS(x[0], qualified_name);
+ container.appendChild(element);
+ });
+ var expected = Array.prototype.filter.call(container.childNodes,
+ function(node) {
+ if (is_html && node.namespaceURI === "http://www.w3.org/1999/xhtml") {
+ return node.localName === expected_case(search_string);
+ } else {
+ return node.localName === search_string;
+ }
+ });
+ document.documentElement.appendChild(container);
+ try {
+ assert_array_equals(document.getElementsByTagName(search_string), expected);
+ } finally {
+ document.documentElement.removeChild(container);
+ }
+}
+
+function test_get_elements_tag_name_ns(elements_to_create, search_input) {
+ var search_uri = search_input[0];
+ var search_name = search_input[1];
+ var container = document.createElement("div");
+ elements_to_create.forEach(function(x) {
+ var qualified_name = x[1] ? x[1] + ":" + x[2] : x[2];
+ var element = document.createElementNS(x[0], qualified_name);
+ container.appendChild(element);
+ });
+ var expected = Array.prototype.filter.call(container.childNodes,
+ function(node) {
+ return node.namespaceURI === search_uri;
+ return node.localName === search_name;
+ });
+ document.documentElement.appendChild(container);
+ try {
+ assert_array_equals(document.getElementsByTagNameNS(search_uri, search_name), expected);
+ } catch(e) {
+ throw e;
+ } finally {
+ document.documentElement.removeChild(container);
+ }
+}
+
+function test_func() {
+ var func = arguments[0];
+ var rest = arguments[1];
+ func.apply(this, rest);
+}
+
+generate_tests(test_func, tests);
diff --git a/tests/wpt/web-platform-tests/dom/nodes/creators.js b/tests/wpt/web-platform-tests/dom/nodes/creators.js
new file mode 100644
index 00000000000..8b7415d13f0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/creators.js
@@ -0,0 +1,5 @@
+var creators = {
+ "element": "createElement",
+ "text": "createTextNode",
+ "comment": "createComment"
+};
diff --git a/tests/wpt/web-platform-tests/dom/nodes/encoding.py b/tests/wpt/web-platform-tests/dom/nodes/encoding.py
new file mode 100644
index 00000000000..5f889e8db2a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/encoding.py
@@ -0,0 +1,5 @@
+from cgi import escape
+
+def main(request, response):
+ label = request.GET.first('label')
+ return """<!doctype html><meta charset="%s">""" % escape(label)
diff --git a/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-01.htm b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-01.htm
new file mode 100644
index 00000000000..457d6c400f4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-01.htm
@@ -0,0 +1,13 @@
+<!doctype html>
+<html class="a">
+ <head>
+ <title>document.getElementsByClassName(): simple</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body class="a">
+ <div id="log"></div>
+ <script> test(function() {assert_array_equals(document.getElementsByClassName("\ta\n"),
+ [document.documentElement, document.body])}) </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-02.htm b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-02.htm
new file mode 100644
index 00000000000..d5e513fa88a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-02.htm
@@ -0,0 +1,14 @@
+<!doctype html>
+<html class="a
+b">
+ <head>
+ <title>document.getElementsByClassName(): also simple</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body class="a
+">
+ <div id="log"></div>
+ <script> test(function() {assert_array_equals(document.getElementsByClassName("a\n"), [document.documentElement, document.body])}) </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-03.htm b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-03.htm
new file mode 100644
index 00000000000..a9e2d3af1a3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-03.htm
@@ -0,0 +1,18 @@
+<!doctype html>
+<html class="a">
+ <head>
+ <title>document.getElementsByClassName(): changing classes</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body class="a">
+ <div id="log"></div>
+ <script>
+ test(function() {
+ var collection = document.getElementsByClassName("a")
+ document.body.className = "b"
+ assert_array_equals(collection, [document.documentElement])
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-04.htm b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-04.htm
new file mode 100644
index 00000000000..0c62fed2c52
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-04.htm
@@ -0,0 +1,18 @@
+<!doctype html>
+<html class="a">
+ <head>
+ <title>document.getElementsByClassName(): changing classes</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body class="a">
+ <div id="log"></div>
+ <script>
+ test(function() {
+ var collection = document.getElementsByClassName("a");
+ document.body.className += "\tb";
+ assert_array_equals(collection, [document.documentElement, document.body]);
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-05.htm b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-05.htm
new file mode 100644
index 00000000000..98245f64278
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-05.htm
@@ -0,0 +1,18 @@
+<!doctype html>
+<html class="a">
+ <head>
+ <title>document.getElementsByClassName(): changing classes</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body class="a">
+ <div id="log"></div>
+ <script>
+ test(function() {
+ var collection = document.getElementsByClassName("a");
+ document.body.removeAttribute("class");
+ assert_array_equals(collection, [document.documentElement]);
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-06.htm b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-06.htm
new file mode 100644
index 00000000000..4975a89e091
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-06.htm
@@ -0,0 +1,20 @@
+<!doctype html>
+<html>
+ <head>
+ <title>document.getElementsByClassName(): adding element with class</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body class="a">
+ <div id="log"></div>
+ <script>
+ test(function() {
+ var collection = document.getElementsByClassName("a");
+ var ele = document.createElement("foo");
+ ele.setAttribute("class", "a");
+ document.body.appendChild(ele);
+ assert_array_equals(collection, [document.body, ele]);
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-07.htm b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-07.htm
new file mode 100644
index 00000000000..b0102fb2e6a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-07.htm
@@ -0,0 +1,15 @@
+<!doctype html>
+<html>
+ <head>
+ <title>document.getElementsByClassName(): multiple classes</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body class="a b">
+ <div id="log"></div>
+ <script> test(function() {
+ assert_array_equals(document.getElementsByClassName("b\t\f\n\na\rb"), [document.body]);
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-08.htm b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-08.htm
new file mode 100644
index 00000000000..a248af49299
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-08.htm
@@ -0,0 +1,15 @@
+<!doctype html>
+<html>
+ <head>
+ <title>document.getElementsByClassName(): multiple classes</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body class="a">
+ <div id="log"></div>
+ <script> test(function() {
+ document.getElementsByClassName("a\fa"), [document.body]
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-09.htm b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-09.htm
new file mode 100644
index 00000000000..9011f3068cf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-09.htm
@@ -0,0 +1,15 @@
+<!doctype html>
+<html class="a A">
+ <head>
+ <title>document.getElementsByClassName(): case sensitive</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body class="a a">
+ <div id="log"></div>
+ <script>test(function() {
+ assert_array_equals(document.getElementsByClassName("A a"), [document.documentElement])
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-10.xml b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-10.xml
new file mode 100644
index 00000000000..42bd6adb792
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-10.xml
@@ -0,0 +1,17 @@
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:g="http://www.w3.org/2000/svg">
+ <head>
+ <title>document.getElementsByClassName(): compound</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"/>
+ <x class="a"/>
+ <g:x class="a"/>
+ <script>test(function() {
+ assert_array_equals(document.getElementsByClassName("a"),
+ document.getElementsByTagName("x"));
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-11.xml b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-11.xml
new file mode 100644
index 00000000000..1d618ddb9a2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-11.xml
@@ -0,0 +1,22 @@
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:g="http://www.w3.org/2000/svg" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:t="http://tc.labs.opera.com/#test">
+ <head>
+ <title>document.getElementsByClassName(): "tricky" compound</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log" />
+ <x class="a"/>
+ <g:x class="a"/>
+ <x t:class="a" h:class="a" g:class="a"/>
+ <g:x t:class="a" h:class="a" g:class="a"/>
+ <t:x class="a" t:class="a" h:class="a" g:class="a"/>
+ <script>
+ test(function() {
+ var collection = document.getElementsByClassName("a");
+ var test = document.getElementsByTagName("x");
+ assert_array_equals(collection, [test[0], test[1]]);
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-12.htm b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-12.htm
new file mode 100644
index 00000000000..3b7f328b47b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-12.htm
@@ -0,0 +1,15 @@
+<!doctype html>
+<html class="a">
+ <head>
+ <title>element.getElementsByClassName(): simple</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body class="a">
+ <div id="log"></div>
+ <script>test(function() {
+ assert_array_equals(document.body.getElementsByClassName("a"), [])
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-13.htm b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-13.htm
new file mode 100644
index 00000000000..f3af106aedf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-13.htm
@@ -0,0 +1,19 @@
+<!doctype html>
+<html class="a">
+ <head>
+ <title>element.getElementsByClassName(): adding an element</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body class="a">
+ <div id="log"></div>
+ <script>test(function() {
+ var collection = document.body.getElementsByClassName("a");
+ var ele = document.createElement("x-y-z");
+ ele.className = "a";
+ document.body.appendChild(ele);
+ assert_array_equals(collection, [ele]);
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-14.htm b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-14.htm
new file mode 100644
index 00000000000..77de16298a5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-14.htm
@@ -0,0 +1,16 @@
+<!-- quirks mode -->
+<html class="a A">
+ <head>
+ <title>document.getElementsByClassName(): case-insensitive (quirks mode)</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body class="a a">
+ <div id="log"></div>
+ <script>test(function() {
+ assert_array_equals(document.getElementsByClassName("A a"),
+ [document.documentElement, document.body]);
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-15.htm b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-15.htm
new file mode 100644
index 00000000000..89614de30dc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-15.htm
@@ -0,0 +1,18 @@
+<!doctype html>
+<html class="a
+b">
+ <head>
+ <title>document.getElementsByClassName(array): "a\n"</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body class="a
+">
+ <div id="log"></div>
+ <script>test(function () {
+ assert_array_equals(document.getElementsByClassName(["a\n"]),
+ [document.documentElement, document.body]);
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-16.htm b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-16.htm
new file mode 100644
index 00000000000..3f987a7ae0e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-16.htm
@@ -0,0 +1,16 @@
+<!doctype html>
+<html class="a
+b">
+ <head>
+ <title>document.getElementsByClassName(array): "b","a"</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body class="b,a">
+ <div id="log"></div>
+ <script>test(function() {
+ assert_array_equals(document.getElementsByClassName(["b", "a"]), [document.body]);
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-17.htm b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-17.htm
new file mode 100644
index 00000000000..ae5ebda6e2a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-17.htm
@@ -0,0 +1,15 @@
+<!doctype html>
+<html>
+ <head>
+ <title>document.getElementsByClassName(array): "b a"</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body class="a b">
+ <div id="log"></div>
+ <script>test(function() {
+ assert_array_equals(document.getElementsByClassName(["b a"]), [document.body]);
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-18.htm b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-18.htm
new file mode 100644
index 00000000000..9f6cf75a50e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-18.htm
@@ -0,0 +1,17 @@
+<!doctype html>
+<html class="a,b">
+ <head>
+ <title>element.getElementsByClassName(array): "a", "b"</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body class="a,b x">
+ <div id="log"></div>
+ <p id="r" class="a,bx"></p>
+ <script class="xa,b">test(function() {
+ assert_array_equals(document.documentElement.getElementsByClassName(["\fa","b\n"]),
+ [document.body])
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-19.htm b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-19.htm
new file mode 100644
index 00000000000..da233c743a9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-19.htm
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html><head>
+ <title>getElementsByClassName</title>
+ <meta content="get elements in document" name="description">
+ <link href="https://dom.spec.whatwg.org/#dom-document-getelementsbyclassname" rel="help">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+ <body>
+ <div id="log"></div>
+ <div>
+ <div>
+ <a class="text link" href="#foo">test link #foo</a>
+ </div>
+ <b class="text">text</b>
+ </div>
+ <table>
+ <caption class="text caption">text caption</caption>
+ <thead>
+ <tr>
+ <td class="TEXT head">TEXT head</td>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td class="td text1">td text1</td>
+ </tr>
+ <tr>
+ <td class="td text">td text</td>
+ </tr>
+ <tr>
+ <td class="td te xt">td te xt</td>
+ </tr>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td class="TEXT foot">TEXT foot</td>
+ </tr>
+ </tfoot>
+ </table>
+ <div class="xt te">xt te</div>
+
+ <script type="text/javascript">
+ test(function ()
+ {
+ var collection = document.getElementsByClassName("text");
+ assert_equals(collection.length, 4);
+ assert_equals(collection[0].parentNode.nodeName, "DIV");
+ assert_equals(collection[1].parentNode.nodeName, "DIV");
+ assert_equals(collection[2].parentNode.nodeName, "TABLE");
+ assert_equals(collection[3].parentNode.nodeName, "TR");
+ }, "get elements in document");
+ </script>
+</body></html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-20.htm b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-20.htm
new file mode 100644
index 00000000000..6429e37bb5b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-20.htm
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<html><head>
+ <title>getElementsByClassName</title>
+ <meta content="get elements in document then add element to collection" name="description">
+ <link href="https://dom.spec.whatwg.org/#dom-document-getelementsbyclassname" rel="help">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+ <body>
+ <div id="log"></div>
+ <div>
+ <div>
+ <a class="text link" href="#foo">test link #foo</a>
+ </div>
+ <b class="text">text</b>
+ </div>
+ <table>
+ <caption class="text caption">text caption</caption>
+ <thead>
+ <tr>
+ <td class="TEXT head">TEXT head</td>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td class="td text1">td text1</td>
+ </tr>
+ <tr>
+ <td class="td text">td text</td>
+ </tr>
+ <tr>
+ <td class="td te xt">td te xt</td>
+ </tr>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td class="TEXT foot">TEXT foot</td>
+ </tr>
+ </tfoot>
+ </table>
+ <div class="xt te">xt te</div>
+
+ <script type="text/javascript">
+ test(function()
+ {
+ var collection = document.getElementsByClassName("text");
+ assert_equals(collection.length, 4);
+ var newDiv = document.createElement("div");
+ newDiv.setAttribute("class", "text");
+ newDiv.innerHTML = "text newDiv";
+ document.getElementsByTagName("table")[0].tBodies[0].rows[0].cells[0].appendChild(newDiv);
+
+ assert_equals(collection.length, 5);
+ assert_equals(collection[0].parentNode.nodeName, "DIV");
+ assert_equals(collection[1].parentNode.nodeName, "DIV");
+ assert_equals(collection[2].parentNode.nodeName, "TABLE");
+ assert_equals(collection[3].parentNode.nodeName, "TD");
+ assert_equals(collection[4].parentNode.nodeName, "TR");
+ }, "get elements in document then add element to collection");
+ </script>
+</body></html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-21.htm b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-21.htm
new file mode 100644
index 00000000000..339ff2d3e12
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-21.htm
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<html><head>
+ <title>getElementsByClassName</title>
+ <meta content="delete element from collection" name="description">
+ <link href="https://dom.spec.whatwg.org/#dom-document-getelementsbyclassname" rel="help">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+ <body>
+ <div id="log"></div>
+ <div>
+ <div>
+ <a class="text link" href="#foo">test link #foo</a>
+ </div>
+ <b class="text">text</b>
+ </div>
+ <table>
+ <caption class="text caption">text caption</caption>
+ <thead>
+ <tr>
+ <td class="TEXT head">TEXT head</td>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td class="td text1">td text1</td>
+ </tr>
+ <tr>
+ <td class="td text">td text</td>
+ </tr>
+ <tr>
+ <td class="td te xt">td te xt</td>
+ </tr>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td class="TEXT foot">TEXT foot</td>
+ </tr>
+ </tfoot>
+ </table>
+ <div class="xt te">xt te</div>
+
+ <script type="text/javascript">
+ test(function()
+ {
+ var collection = document.getElementsByClassName("text1");
+ assert_equals(collection.length, 1)
+ document.getElementsByTagName("table")[0].deleteRow(1);
+ assert_equals(collection.length, 0);
+ }, "delete element from collection");
+ </script>
+</body></html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-22.htm b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-22.htm
new file mode 100644
index 00000000000..c203967007c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-22.htm
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html><head>
+ <title>getElementsByClassName</title>
+ <meta content="move item in collection order" name="description">
+ <link href="https://dom.spec.whatwg.org/#dom-document-getelementsbyclassname" rel="help">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+ <body>
+ <div id="log"></div>
+ <div>
+ <div>
+ <a class="text link" href="#foo">test link #foo</a>
+ </div>
+ <b class="text">text</b>
+ </div>
+ <table>
+ <caption class="text caption">text caption</caption>
+ <thead>
+ <tr>
+ <td class="TEXT head">TEXT head</td>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td class="td text1">td text1</td>
+ </tr>
+ <tr>
+ <td class="td text">td text</td>
+ </tr>
+ <tr>
+ <td class="td te xt">td te xt</td>
+ </tr>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td class="TEXT foot">TEXT foot</td>
+ </tr>
+ </tfoot>
+ </table>
+ <div class="xt te">xt te</div>
+
+ <script type="text/javascript">
+ test(function()
+ {
+ var collection = document.getElementsByClassName("text");
+ assert_equals(collection.length, 4);
+ var boldText = document.getElementsByTagName("b")[0];
+ document.getElementsByTagName("table")[0].tBodies[0].rows[0].cells[0].appendChild(boldText);
+
+ assert_equals(collection.length, 4);
+ assert_equals(collection[0].parentNode.nodeName, "DIV");
+ assert_equals(collection[1].parentNode.nodeName, "TABLE");
+ assert_equals(collection[2].parentNode.nodeName, "TD");
+ assert_equals(collection[3].parentNode.nodeName, "TR");
+ }, "move item in collection order");
+ </script>
+</body></html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-23.htm b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-23.htm
new file mode 100644
index 00000000000..0af8a09952a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-23.htm
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<html><head>
+ <title>getElementsByClassName</title>
+ <meta content="multiple defined classes" name="description">
+ <link href="https://dom.spec.whatwg.org/#dom-document-getelementsbyclassname" rel="help">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+ <body>
+ <div id="log"></div>
+ <div>
+ <div>
+ <a class="text link" href="#foo">test link #foo</a>
+ </div>
+ <b class="text">text</b>
+ </div>
+ <table>
+ <caption class="text caption">text caption</caption>
+ <thead>
+ <tr>
+ <td class="TEXT head">TEXT head</td>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td class="td text1">td text1</td>
+ </tr>
+ <tr>
+ <td class="td text">td text</td>
+ </tr>
+ <tr>
+ <td class="td te xt">td te xt</td>
+ </tr>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td class="TEXT foot">TEXT foot</td>
+ </tr>
+ </tfoot>
+ </table>
+ <div class="xt te">xt te</div>
+
+ <script type="text/javascript">
+ test(function()
+ {
+ var collection = document.getElementsByClassName("te xt");
+ assert_equals(collection.length, 2);
+ assert_equals(collection[0].parentNode.nodeName, "TR");
+ assert_equals(collection[1].parentNode.nodeName, "BODY");
+ }, "multiple defined classes");
+ </script>
+</body></html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-24.htm b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-24.htm
new file mode 100644
index 00000000000..838987ad0c2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-24.htm
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html><head>
+ <meta charset='utf-8'>
+ <title>getElementsByClassName</title>
+ <meta content="handle unicode chars" name="description">
+ <link href="https://dom.spec.whatwg.org/#dom-document-getelementsbyclassname" rel="help">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+ <body>
+ <div id="log"></div>
+ <div>
+ <div>
+ <a class="ΔЙあ叶葉 말 link" href="#foo">ΔЙあ叶葉 말 link</a>
+ </div>
+ <b class="text">text</b>
+ </div>
+ <div class="ΔЙあ叶葉 קم">ΔЙあ叶葉 קم</div>
+
+ <script type="text/javascript">
+ test(function()
+ {
+ var collection = document.getElementsByClassName("ΔЙあ叶葉");
+ assert_equals(collection.length, 2);
+ assert_equals(collection[0].parentNode.nodeName, "DIV");
+ assert_equals(collection[1].parentNode.nodeName, "BODY");
+ }, "handle unicode chars");
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-25.htm b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-25.htm
new file mode 100644
index 00000000000..21f2a9ff7af
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-25.htm
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<html><head>
+ <title>getElementsByClassName</title>
+ <meta content="verify spacing is handled correctly" name="description">
+ <link href="https://dom.spec.whatwg.org/#dom-document-getelementsbyclassname" rel="help">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+ <body>
+ <div id="log"></div>
+ <div>
+ <div>
+ <a class="text link" href="#foo">test link #foo</a>
+ </div>
+ <b class="text">text</b>
+ </div>
+ <table>
+ <caption class="text caption">text caption</caption>
+ <thead>
+ <tr>
+ <td class="TEXT head">TEXT head</td>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td class="td text1">td text1</td>
+ </tr>
+ <tr>
+ <td class="td text">td text</td>
+ </tr>
+ <tr>
+ <td class="td te xt">td te xt</td>
+ </tr>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td class="TEXT foot">TEXT foot</td>
+ </tr>
+ </tfoot>
+ </table>
+ <div class="xt te">xt te</div>
+
+ <script type="text/javascript">
+ test(function()
+ {
+ var collection = document.getElementsByClassName("text ");
+ assert_equals(collection.length, 4);
+ var boldText = document.getElementsByTagName("b")[0];
+ document.getElementsByTagName("table")[0].tBodies[0].rows[0].cells[0].appendChild(boldText);
+ assert_equals(collection.length, 4);
+ assert_equals(collection[0].parentNode.nodeName, "DIV");
+ assert_equals(collection[1].parentNode.nodeName, "TABLE");
+ assert_equals(collection[2].parentNode.nodeName, "TD");
+ assert_equals(collection[3].parentNode.nodeName, "TR");
+ }, "verify spacing is handled correctly");
+ </script>
+</body></html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-26.htm b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-26.htm
new file mode 100644
index 00000000000..0d7ff1ba1f7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-26.htm
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html><head>
+ <title>getElementsByClassName</title>
+ <meta content="multiple class attributes" name="description">
+ <link href="https://dom.spec.whatwg.org/#dom-document-getelementsbyclassname" rel="help">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+ <body>
+ <div id="log"></div>
+ <div class="te xt">
+ te xt
+ <div class="te">
+ te; xt
+ <a class="text link" href="#foo">test link #foo</a>
+ </div>
+ <b class="text">text</b>
+ </div>
+ <div class="xt te">xt te</div>
+ <script type="text/javascript">
+ test(function()
+ {
+ var collection = document.getElementsByClassName("te xt");
+
+ assert_equals(collection.length, 2);
+ assert_equals(collection[0].parentNode.nodeName, "BODY");
+ assert_equals(collection[1].parentNode.nodeName, "BODY");
+ }, "multiple class attributes");
+ </script>
+</body></html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-27.htm b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-27.htm
new file mode 100644
index 00000000000..95fc674428e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-27.htm
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html><head>
+ <title>getElementsByClassName</title>
+ <meta content="generic element listed" name="description">
+ <link href="https://dom.spec.whatwg.org/#dom-document-getelementsbyclassname" rel="help">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+ <body>
+ <div id="log"></div>
+ <div class="te xt">
+ te xt
+ <div class="te">
+ te; xt
+ <a class="text link" href="#foo">test link #foo</a>
+ <foo class="te xt">dummy tag</foo>
+ </div>
+ <b class="text">text</b>
+ </div>
+ <div class="xt te">xt te</div>
+ <script type="text/javascript">
+ test(function()
+ {
+ var collection = document.getElementsByClassName("te xt");
+
+ assert_equals(collection.length, 3);
+ assert_equals(collection[0].parentNode.nodeName, "BODY");
+ assert_equals(collection[1].parentNode.nodeName, "DIV");
+ assert_equals(collection[2].parentNode.nodeName, "BODY");
+ }, "generic element listed");
+ </script>
+</body></html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-28.htm b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-28.htm
new file mode 100644
index 00000000000..1fc94d807c2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-28.htm
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html><head>
+ <title>getElementsByClassName</title>
+ <meta content="generic element listed" name="description">
+ <link href="https://dom.spec.whatwg.org/#dom-document-getelementsbyclassname" rel="help">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+ <body>
+ <div id="log"></div>
+ <div class="te xt">
+ te xt
+ <div class="te">
+ te; xt
+ <a class="text link" href="#foo">test link #foo</a>
+ <fooU00003Abar class="te xt namespace">te xt namespace
+ </fooU00003Abar></div>
+ <b class="text">text</b>
+ </div>
+ <div class="xt te">xt te</div>
+ <script type="text/javascript">
+ test(function()
+ {
+ var collection = document.getElementsByClassName("te xt");
+ assert_equals(collection.length, 3);
+ assert_equals(collection[0].parentNode.nodeName, "BODY");
+ assert_equals(collection[1].parentNode.nodeName, "DIV");
+ assert_equals(collection[2].parentNode.nodeName, "BODY");
+ }, "generic element listed");
+ </script>
+</body></html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-29.htm b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-29.htm
new file mode 100644
index 00000000000..ad489752cc5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-29.htm
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html><head>
+ <title>getElementsByClassName</title>
+ <meta content="get class from children of element" name="description">
+ <link href="https://dom.spec.whatwg.org/#dom-document-getelementsbyclassname" rel="help">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+ <body>
+ <div id='log'></div>
+ <div>
+ <div>
+ <a class="text link" href="#foo">test link #foo</a>
+ </div>
+ <b class="text">text</b>
+ </div>
+ <table>
+ <caption class="text caption">text caption</caption>
+ <thead>
+ <tr>
+ <td class="TEXT head">TEXT head</td>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td class="td text1">td text1</td>
+ </tr>
+ <tr>
+ <td class="td text">td text</td>
+ </tr>
+ <tr>
+ <td class="td te xt">td te xt</td>
+ </tr>
+ </tbody>
+ <tfoot>
+ <tr>
+ <td class="TEXT foot">TEXT foot</td>
+ </tr>
+ </tfoot>
+ </table>
+ <div class="xt te">xt te</div>
+
+ <script type="text/javascript">
+ test(function()
+ {
+ var collection = document.getElementsByTagName("table")[0].getElementsByClassName("te xt");
+ assert_equals(collection.length, 1);
+ assert_equals(collection[0].parentNode.nodeName, "TR");
+ }, "get class from children of element");
+ </script>
+</body></html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-30.htm b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-30.htm
new file mode 100644
index 00000000000..c0b4faf2d48
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-30.htm
@@ -0,0 +1,190 @@
+<!DOCTYPE html>
+<html><head class="foo">
+ <title class="foo">getElementsByClassName</title>
+ <meta class="foo" content="big element listing" name="description">
+ <link class="foo">
+ <base class="foo">
+ <script class="foo"></script>
+ <style class="foo"></style>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link href="https://dom.spec.whatwg.org/#dom-document-getelementsbyclassname" rel="help">
+</head>
+ <body class="foo">
+ <div id='log'></div>
+ <a class="foo">a</a>
+ <abbr class="foo">abbr</abbr>
+ <acronym class="foo">acronym</acronym>
+ <address class="foo">address</address>
+ <applet class="foo">applet</applet>
+ <b class="foo">b</b>
+ <bdo class="foo">bdo</bdo>
+ <big class="foo">big</big>
+ <blockquote class="foo">blockquote</blockquote>
+ <br class="foo">
+ <button class="foo">button</button>
+ <center class="foo">center</center>
+ <cite class="foo">cite</cite>
+ <code class="foo">code</code>
+ <del class="foo">del</del>
+ <dfn class="foo">dfn</dfn>
+ <dir class="foo">dir
+ <li class="foo">li</li>
+ </dir>
+ <div class="foo">div</div>
+ <dl class="foo">
+ <dt class="foo">
+ </dt><dd class="foo">dd</dd>
+ </dl>
+ <em class="foo">em</em>
+ <font class="foo">font</font>
+ <form class="foo">
+ <label class="foo">label</label>
+ <fieldset class="foo">
+ <legend class="foo">legend</legend>
+ </fieldset>
+ </form>
+ <h1 class="foo">h1</h1>
+ <hr class="foo">
+ <i class="foo">i</i>
+ <iframe class="foo">iframe</iframe>
+ <img class="foo">
+ <input class="foo">
+ <ins class="foo">ins</ins>
+ <kbd class="foo">kbd</kbd>
+ <map class="foo">
+ <area class="foo"></area>
+ </map>
+ <menu class="foo">menu</menu>
+ <noscript class="foo">noscript</noscript>
+ <object class="foo">
+ <param class="foo">
+ </object>
+ <ol class="foo">ol</ol>
+ <p class="foo">p</p>
+ <pre class="foo">pre</pre>
+ <q class="foo">q</q>
+ <s class="foo">s</s>
+ <samp class="foo">samp</samp>
+ <select class="foo">
+ <optgroup class="foo">optgroup</optgroup>
+ <option class="foo">option</option>
+ </select>
+ <small class="foo">small</small>
+ <span class="foo">span</span>
+ <strike class="foo">strike</strike>
+ <strong class="foo">strong</strong>
+ <sub class="foo">sub</sub>
+ <sup class="foo">sup</sup>
+ colgroup<table class="foo">
+ <caption class="foo">caption</caption>
+ <colgroup><col class="foo">
+ </colgroup><colgroup class="foo"></colgroup>
+ <thead class="foo">
+ <tr><th class="foo">th</th>
+ </tr></thead>
+ <tbody class="foo">
+ <tr class="foo">
+ <td class="foo">td</td>
+ </tr>
+ </tbody>
+ <tfoot class="foo"></tfoot>
+ </table>
+ <textarea class="foo">textarea</textarea>
+ <tt class="foo">tt</tt>
+ <u class="foo">u</u>
+ <ul class="foo">ul</ul>
+ <var class="foo">var</var>
+ <script type="text/javascript">
+ test(function ()
+ {
+ var arrElements = [
+ "HEAD",
+ "TITLE",
+ "META",
+ "LINK",
+ "BASE",
+ "SCRIPT",
+ "STYLE",
+ "BODY",
+ "A",
+ "ABBR",
+ "ACRONYM",
+ "ADDRESS",
+ "APPLET",
+ "B",
+ "BDO",
+ "BIG",
+ "BLOCKQUOTE",
+ "BR",
+ "BUTTON",
+ "CENTER",
+ "CITE",
+ "CODE",
+ "DEL",
+ "DFN",
+ "DIR",
+ "LI",
+ "DIV",
+ "DL",
+ "DT",
+ "DD",
+ "EM",
+ "FONT",
+ "FORM",
+ "LABEL",
+ "FIELDSET",
+ "LEGEND",
+ "H1",
+ "HR",
+ "I",
+ "IFRAME",
+ "IMG",
+ "INPUT",
+ "INS",
+ "KBD",
+ "MAP",
+ "AREA",
+ "MENU",
+ "NOSCRIPT",
+ "OBJECT",
+ "PARAM",
+ "OL",
+ "P",
+ "PRE",
+ "Q",
+ "S",
+ "SAMP",
+ "SELECT",
+ "OPTGROUP",
+ "OPTION",
+ "SMALL",
+ "SPAN",
+ "STRIKE",
+ "STRONG",
+ "SUB",
+ "SUP",
+ "TABLE",
+ "CAPTION",
+ "COL",
+ "COLGROUP",
+ "THEAD",
+ "TH",
+ "TBODY",
+ "TR",
+ "TD",
+ "TFOOT",
+ "TEXTAREA",
+ "TT",
+ "U",
+ "UL",
+ "VAR"];
+
+ var collection = document.getElementsByClassName("foo");
+ for (var x = 0; x < collection.length; x++)
+ {
+ assert_equals(collection[x].nodeName, arrElements[x]);
+ }
+}, "big element listing");
+ </script>
+</body></html>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-31.htm b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-31.htm
new file mode 100644
index 00000000000..0e1ac014aee
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassName-31.htm
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html class=foo>
+<meta charset=utf-8>
+<title>getElementsByClassName across documents</title>
+<link rel=help href="https://dom.spec.whatwg.org/#dom-document-getelementsbyclassname">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script class=foo>
+async_test(function() {
+ var iframe = document.createElement("iframe");
+ iframe.onload = this.step_func_done(function() {
+ var collection = iframe.contentDocument.getElementsByClassName("foo");
+ assert_equals(collection.length, 3);
+ assert_equals(collection[0].localName, "html");
+ assert_equals(collection[1].localName, "head");
+ assert_equals(collection[2].localName, "body");
+ });
+ iframe.src = "getElementsByClassNameFrame.htm";
+ document.body.appendChild(iframe);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassNameFrame.htm b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassNameFrame.htm
new file mode 100644
index 00000000000..544df60a991
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/getElementsByClassNameFrame.htm
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<html class=foo>
+<head class=foo>
+<meta charset=utf-8>
+<title>getElementsByClassName</title>
+<body class=foo>
diff --git a/tests/wpt/web-platform-tests/dom/nodes/mutationobservers.js b/tests/wpt/web-platform-tests/dom/nodes/mutationobservers.js
new file mode 100644
index 00000000000..772f280bee9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/mutationobservers.js
@@ -0,0 +1,76 @@
+// Compares a mutation record to a predefined one
+// mutationToCheck is a mutation record from the user agent
+// expectedRecord is a mutation record minted by the test
+// for expectedRecord, if properties are ommitted, they get default ones
+function checkRecords(target, mutationToCheck, expectedRecord) {
+ var mr1;
+ var mr2;
+
+
+ function checkField(property, isArray) {
+ var field = mr2[property];
+ if (isArray === undefined) {
+ isArray = false;
+ }
+ if (field instanceof Function) {
+ field = field();
+ } else if (field === undefined) {
+ if (isArray) {
+ field = new Array();
+ } else {
+ field = null;
+ }
+ }
+ if (isArray) {
+ assert_array_equals(mr1[property], field, property + " didn't match");
+ } else {
+ assert_equals(mr1[property], field, property + " didn't match");
+ }
+ }
+
+ assert_equals(mutationToCheck.length, expectedRecord.length, "mutation records must match");
+ for (var item = 0; item < mutationToCheck.length; item++) {
+ mr1 = mutationToCheck[item];
+ mr2 = expectedRecord[item];
+
+ if (mr2.target instanceof Function) {
+ assert_equals(mr1.target, mr2.target(), "target node must match");
+ } else if (mr2.target !== undefined) {
+ assert_equals(mr1.target, mr2.target, "target node must match");
+ } else {
+ assert_equals(mr1.target, target, "target node must match");
+ }
+
+ checkField("type");
+ checkField("addedNodes", true);
+ checkField("removedNodes", true);
+ checkField("previousSibling");
+ checkField("nextSibling");
+ checkField("attributeName");
+ checkField("attributeNamespace");
+ checkField("oldValue");
+ };
+}
+
+function runMutationTest(node, mutationObserverOptions, mutationRecordSequence, mutationFunction, description, target) {
+ var test = async_test(description);
+
+
+ function moc(mrl, obs) {
+ test.step(
+ function () {
+ if (target === undefined) target = node;
+ checkRecords(target, mrl, mutationRecordSequence);
+ test.done();
+ }
+ );
+ }
+
+ test.step(
+ function () {
+ (new MutationObserver(moc)).observe(node, mutationObserverOptions);
+ mutationFunction();
+ }
+ );
+ return mutationRecordSequence.length
+}
diff --git a/tests/wpt/web-platform-tests/dom/nodes/productions.js b/tests/wpt/web-platform-tests/dom/nodes/productions.js
new file mode 100644
index 00000000000..2b9959041c1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/productions.js
@@ -0,0 +1,3 @@
+var invalid_names = ["", "invalid^Name", "\\", "'", '"', "0", "0:a"] // XXX
+var valid_names = ["x", ":", "a:0"]
+var invalid_qnames = [":a", "b:", "x:y:z"] // XXX
diff --git a/tests/wpt/web-platform-tests/dom/nodes/selectors.js b/tests/wpt/web-platform-tests/dom/nodes/selectors.js
new file mode 100644
index 00000000000..e0d68bd98a6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/nodes/selectors.js
@@ -0,0 +1,721 @@
+// Bit-mapped flags to indicate which tests the selector is suitable for
+var TEST_QSA = 0x01; // querySelector() and querySelectorAll() tests
+var TEST_FIND = 0x04; // find() and findAll() tests, may be unsuitable for querySelector[All]
+var TEST_MATCH = 0x10; // matches() tests
+
+/*
+ * All of these invalid selectors should result in a SyntaxError being thrown by the APIs.
+ *
+ * name: A descriptive name of the selector being tested
+ * selector: The selector to test
+ */
+var invalidSelectors = [
+ {name: "Empty String", selector: ""},
+ {name: "Invalid character", selector: "["},
+ {name: "Invalid character", selector: "]"},
+ {name: "Invalid character", selector: "("},
+ {name: "Invalid character", selector: ")"},
+ {name: "Invalid character", selector: "{"},
+ {name: "Invalid character", selector: "}"},
+ {name: "Invalid character", selector: "<"},
+ {name: "Invalid character", selector: ">"},
+ {name: "Invalid ID", selector: "#"},
+ {name: "Invalid group of selectors", selector: "div,"},
+ {name: "Invalid class", selector: "."},
+ {name: "Invalid class", selector: ".5cm"},
+ {name: "Invalid class", selector: "..test"},
+ {name: "Invalid class", selector: ".foo..quux"},
+ {name: "Invalid class", selector: ".bar."},
+ {name: "Invalid combinator", selector: "div & address, p"},
+ {name: "Invalid combinator", selector: "div >> address, p"},
+ {name: "Invalid combinator", selector: "div ++ address, p"},
+ {name: "Invalid combinator", selector: "div ~~ address, p"},
+ {name: "Invalid [att=value] selector", selector: "[*=test]"},
+ {name: "Invalid [att=value] selector", selector: "[*|*=test]"},
+ {name: "Invalid [att=value] selector", selector: "[class= space unquoted ]"},
+ {name: "Unknown pseudo-class", selector: "div:example"},
+ {name: "Unknown pseudo-class", selector: ":example"},
+ {name: "Unknown pseudo-element", selector: "div::example"},
+ {name: "Unknown pseudo-element", selector: "::example"},
+ {name: "Invalid pseudo-element", selector: ":::before"},
+ {name: "Undeclared namespace", selector: "ns|div"},
+ {name: "Undeclared namespace", selector: ":not(ns|div)"},
+ {name: "Invalid namespace", selector: "^|div"},
+ {name: "Invalid namespace", selector: "$|div"}
+];
+
+/*
+ * All of these should be valid selectors, expected to match zero or more elements in the document.
+ * None should throw any errors.
+ *
+ * name: A descriptive name of the selector being tested
+ * selector: The selector to test
+ * expect: A list of IDs of the elements expected to be matched. List must be given in tree order.
+ * exclude: An array of contexts to exclude from testing. The valid values are:
+ * ["document", "element", "fragment", "detached", "html", "xhtml"]
+ * The "html" and "xhtml" values represent the type of document being queried. These are useful
+ * for tests that are affected by differences between HTML and XML, such as case sensitivity.
+ * level: An integer indicating the CSS or Selectors level in which the selector being tested was introduced.
+ * testType: A bit-mapped flag indicating the type of test.
+ *
+ * Note: Interactive pseudo-classes (:active :hover and :focus) have not been tested in this test suite.
+ */
+var validSelectors = [
+ // Type Selector
+ {name: "Type selector, matching html element", selector: "html", expect: ["html"], exclude: ["element", "fragment", "detached"], level: 1, testType: TEST_QSA | TEST_MATCH},
+ {name: "Type selector, matching html element", selector: "html", expect: [] /*no matches*/, exclude: ["document"], level: 1, testType: TEST_QSA},
+ {name: "Type selector, matching body element", selector: "body", expect: ["body"], exclude: ["element", "fragment", "detached"], level: 1, testType: TEST_QSA | TEST_MATCH},
+ {name: "Type selector, matching body element", selector: "body", expect: [] /*no matches*/, exclude: ["document"], level: 1, testType: TEST_QSA},
+
+ // Universal Selector
+ // Testing "*" for entire an entire context node is handled separately.
+ {name: "Universal selector, matching all children of element with specified ID", selector: "#universal>*", expect: ["universal-p1", "universal-hr1", "universal-pre1", "universal-p2", "universal-address1"], level: 2, testType: TEST_QSA | TEST_MATCH},
+ {name: "Universal selector, matching all grandchildren of element with specified ID", selector: "#universal>*>*", expect: ["universal-code1", "universal-span1", "universal-a1", "universal-code2"], level: 2, testType: TEST_QSA | TEST_MATCH},
+ {name: "Universal selector, matching all children of empty element with specified ID", selector: "#empty>*", expect: [] /*no matches*/, level: 2, testType: TEST_QSA},
+ {name: "Universal selector, matching all descendants of element with specified ID", selector: "#universal *", expect: ["universal-p1", "universal-code1", "universal-hr1", "universal-pre1", "universal-span1", "universal-p2", "universal-a1", "universal-address1", "universal-code2", "universal-a2"], level: 2, testType: TEST_QSA | TEST_MATCH},
+
+ // Attribute Selectors
+ // - presence [att]
+ {name: "Attribute presence selector, matching align attribute with value", selector: ".attr-presence-div1[align]", expect: ["attr-presence-div1"], level: 2, testType: TEST_QSA | TEST_MATCH},
+ {name: "Attribute presence selector, matching align attribute with empty value", selector: ".attr-presence-div2[align]", expect: ["attr-presence-div2"], level: 2, testType: TEST_QSA | TEST_MATCH},
+ {name: "Attribute presence selector, matching title attribute, case insensitivity", selector: "#attr-presence [TiTlE]", expect: ["attr-presence-a1", "attr-presence-span1"], exclude: ["xhtml"], level: 2, testType: TEST_QSA | TEST_MATCH},
+ {name: "Attribute presence selector, not matching title attribute, case sensitivity", selector: "#attr-presence [TiTlE]", expect: [], exclude: ["html"], level: 2, testType: TEST_QSA | TEST_MATCH},
+ {name: "Attribute presence selector, matching custom data-* attribute", selector: "[data-attr-presence]", expect: ["attr-presence-pre1", "attr-presence-blockquote1"], level: 2, testType: TEST_QSA | TEST_MATCH},
+ {name: "Attribute presence selector, not matching attribute with similar name", selector: ".attr-presence-div3[align], .attr-presence-div4[align]", expect: [] /*no matches*/, level: 2, testType: TEST_QSA},
+ {name: "Attribute presence selector, matching attribute with non-ASCII characters", selector: "ul[data-中文]", expect: ["attr-presence-ul1"], level: 2, testType: TEST_QSA | TEST_MATCH},
+ {name: "Attribute presence selector, not matching default option without selected attribute", selector: "#attr-presence-select1 option[selected]", expect: [] /* no matches */, level: 2, testType: TEST_QSA},
+ {name: "Attribute presence selector, matching option with selected attribute", selector: "#attr-presence-select2 option[selected]", expect: ["attr-presence-select2-option4"], level: 2, testType: TEST_QSA | TEST_MATCH},
+ {name: "Attribute presence selector, matching multiple options with selected attributes", selector: "#attr-presence-select3 option[selected]", expect: ["attr-presence-select3-option2", "attr-presence-select3-option3"], level: 2, testType: TEST_QSA | TEST_MATCH},
+
+ // - value [att=val]
+ {name: "Attribute value selector, matching align attribute with value", selector: "#attr-value [align=\"center\"]", expect: ["attr-value-div1"], level: 2, testType: TEST_QSA | TEST_MATCH},
+ {name: "Attribute value selector, matching align attribute with empty value", selector: "#attr-value [align=\"\"]", expect: ["attr-value-div2"], level: 2, testType: TEST_QSA | TEST_MATCH},
+ {name: "Attribute value selector, not matching align attribute with partial value", selector: "#attr-value [align=\"c\"]", expect: [] /*no matches*/, level: 2, testType: TEST_QSA},
+ {name: "Attribute value selector, not matching align attribute with incorrect value", selector: "#attr-value [align=\"centera\"]", expect: [] /*no matches*/, level: 2, testType: TEST_QSA},
+ {name: "Attribute value selector, matching custom data-* attribute with unicode escaped value", selector: "[data-attr-value=\"\\e9\"]", expect: ["attr-value-div3"], level: 2, testType: TEST_QSA | TEST_MATCH},
+ {name: "Attribute value selector, matching custom data-* attribute with escaped character", selector: "[data-attr-value\_foo=\"\\e9\"]", expect: ["attr-value-div4"], level: 2, testType: TEST_QSA | TEST_MATCH},
+ {name: "Attribute value selector with single-quoted value, matching multiple inputs with type attributes", selector: "#attr-value input[type='hidden'],#attr-value input[type='radio']", expect: ["attr-value-input3", "attr-value-input4", "attr-value-input6", "attr-value-input8", "attr-value-input9"], level: 2, testType: TEST_QSA | TEST_MATCH},
+ {name: "Attribute value selector with double-quoted value, matching multiple inputs with type attributes", selector: "#attr-value input[type=\"hidden\"],#attr-value input[type='radio']", expect: ["attr-value-input3", "attr-value-input4", "attr-value-input6", "attr-value-input8", "attr-value-input9"], level: 2, testType: TEST_QSA | TEST_MATCH},
+ {name: "Attribute value selector with unquoted value, matching multiple inputs with type attributes", selector: "#attr-value input[type=hidden],#attr-value input[type=radio]", expect: ["attr-value-input3", "attr-value-input4", "attr-value-input6", "attr-value-input8", "attr-value-input9"], level: 2, testType: TEST_QSA | TEST_MATCH},
+ {name: "Attribute value selector, matching attribute with value using non-ASCII characters", selector: "[data-attr-value=中文]", expect: ["attr-value-div5"], level: 2, testType: TEST_QSA | TEST_MATCH},
+
+ // - whitespace-separated list [att~=val]
+ {name: "Attribute whitespace-separated list selector, matching class attribute with value", selector: "#attr-whitespace [class~=\"div1\"]", expect: ["attr-whitespace-div1"], level: 2, testType: TEST_QSA | TEST_MATCH},
+ {name: "Attribute whitespace-separated list selector, not matching class attribute with empty value", selector: "#attr-whitespace [class~=\"\"]", expect: [] /*no matches*/ , level: 2, testType: TEST_QSA},
+ {name: "Attribute whitespace-separated list selector, not matching class attribute with partial value", selector: "[data-attr-whitespace~=\"div\"]", expect: [] /*no matches*/ , level: 2, testType: TEST_QSA},
+ {name: "Attribute whitespace-separated list selector, matching custom data-* attribute with unicode escaped value", selector: "[data-attr-whitespace~=\"\\0000e9\"]", expect: ["attr-whitespace-div4"], level: 2, testType: TEST_QSA | TEST_MATCH},
+ {name: "Attribute whitespace-separated list selector, matching custom data-* attribute with escaped character", selector: "[data-attr-whitespace\_foo~=\"\\e9\"]", expect: ["attr-whitespace-div5"], level: 2, testType: TEST_QSA | TEST_MATCH},
+ {name: "Attribute whitespace-separated list selector with single-quoted value, matching multiple links with rel attributes", selector: "#attr-whitespace a[rel~='bookmark'], #attr-whitespace a[rel~='nofollow']", expect: ["attr-whitespace-a1", "attr-whitespace-a2", "attr-whitespace-a3", "attr-whitespace-a5", "attr-whitespace-a7"], level: 2, testType: TEST_QSA | TEST_MATCH},
+ {name: "Attribute whitespace-separated list selector with double-quoted value, matching multiple links with rel attributes", selector: "#attr-whitespace a[rel~=\"bookmark\"],#attr-whitespace a[rel~='nofollow']", expect: ["attr-whitespace-a1", "attr-whitespace-a2", "attr-whitespace-a3", "attr-whitespace-a5", "attr-whitespace-a7"], level: 2, testType: TEST_QSA | TEST_MATCH},
+ {name: "Attribute whitespace-separated list selector with unquoted value, matching multiple links with rel attributes", selector: "#attr-whitespace a[rel~=bookmark], #attr-whitespace a[rel~=nofollow]", expect: ["attr-whitespace-a1", "attr-whitespace-a2", "attr-whitespace-a3", "attr-whitespace-a5", "attr-whitespace-a7"], level: 2, testType: TEST_QSA | TEST_MATCH},
+ {name: "Attribute whitespace-separated list selector with double-quoted value, not matching value with space", selector: "#attr-whitespace a[rel~=\"book mark\"]", expect: [] /* no matches */, level: 2, testType: TEST_QSA},
+ {name: "Attribute whitespace-separated list selector, matching title attribute with value using non-ASCII characters", selector: "#attr-whitespace [title~=中文]", expect: ["attr-whitespace-p1"], level: 2, testType: TEST_QSA | TEST_MATCH},
+
+ // - hyphen-separated list [att|=val]
+ {name: "Attribute hyphen-separated list selector, not matching unspecified lang attribute", selector: "#attr-hyphen-div1[lang|=\"en\"]", expect: [] /*no matches*/, level: 2, testType: TEST_QSA},
+ {name: "Attribute hyphen-separated list selector, matching lang attribute with exact value", selector: "#attr-hyphen-div2[lang|=\"fr\"]", expect: ["attr-hyphen-div2"], level: 2, testType: TEST_QSA | TEST_MATCH},
+ {name: "Attribute hyphen-separated list selector, matching lang attribute with partial value", selector: "#attr-hyphen-div3[lang|=\"en\"]", expect: ["attr-hyphen-div3"], level: 2, testType: TEST_QSA | TEST_MATCH},
+ {name: "Attribute hyphen-separated list selector, not matching incorrect value", selector: "#attr-hyphen-div4[lang|=\"es-AR\"]", expect: [] /*no matches*/, level: 2, testType: TEST_QSA},
+
+ // - substring begins-with [att^=val] (Level 3)
+ {name: "Attribute begins with selector, matching href attributes beginning with specified substring", selector: "#attr-begins a[href^=\"http://www\"]", expect: ["attr-begins-a1", "attr-begins-a3"], level: 3, testType: TEST_QSA | TEST_MATCH},
+ {name: "Attribute begins with selector, matching lang attributes beginning with specified substring, ", selector: "#attr-begins [lang^=\"en-\"]", expect: ["attr-begins-div2", "attr-begins-div4"], level: 3, testType: TEST_QSA | TEST_MATCH},
+ {name: "Attribute begins with selector, not matching class attribute not beginning with specified substring", selector: "#attr-begins [class^=apple]", expect: [] /*no matches*/, level: 3, testType: TEST_QSA},
+ {name: "Attribute begins with selector with single-quoted value, matching class attribute beginning with specified substring", selector: "#attr-begins [class^=' apple']", expect: ["attr-begins-p1"], level: 3, testType: TEST_QSA | TEST_MATCH},
+ {name: "Attribute begins with selector with double-quoted value, matching class attribute beginning with specified substring", selector: "#attr-begins [class^=\" apple\"]", expect: ["attr-begins-p1"], level: 3, testType: TEST_QSA | TEST_MATCH},
+ {name: "Attribute begins with selector with unquoted value, not matching class attribute not beginning with specified substring", selector: "#attr-begins [class^= apple]", expect: [] /*no matches*/, level: 3, testType: TEST_QSA},
+
+ // - substring ends-with [att$=val] (Level 3)
+ {name: "Attribute ends with selector, matching href attributes ending with specified substring", selector: "#attr-ends a[href$=\".org\"]", expect: ["attr-ends-a1", "attr-ends-a3"], level: 3, testType: TEST_QSA | TEST_MATCH},
+ {name: "Attribute ends with selector, matching lang attributes ending with specified substring, ", selector: "#attr-ends [lang$=\"-CH\"]", expect: ["attr-ends-div2", "attr-ends-div4"], level: 3, testType: TEST_QSA | TEST_MATCH},
+ {name: "Attribute ends with selector, not matching class attribute not ending with specified substring", selector: "#attr-ends [class$=apple]", expect: [] /*no matches*/, level: 3, testType: TEST_QSA},
+ {name: "Attribute ends with selector with single-quoted value, matching class attribute ending with specified substring", selector: "#attr-ends [class$='apple ']", expect: ["attr-ends-p1"], level: 3, testType: TEST_QSA | TEST_MATCH},
+ {name: "Attribute ends with selector with double-quoted value, matching class attribute ending with specified substring", selector: "#attr-ends [class$=\"apple \"]", expect: ["attr-ends-p1"], level: 3, testType: TEST_QSA | TEST_MATCH},
+ {name: "Attribute ends with selector with unquoted value, not matching class attribute not ending with specified substring", selector: "#attr-ends [class$=apple ]", expect: [] /*no matches*/, level: 3, testType: TEST_QSA},
+
+ // - substring contains [att*=val] (Level 3)
+ {name: "Attribute contains selector, matching href attributes beginning with specified substring", selector: "#attr-contains a[href*=\"http://www\"]", expect: ["attr-contains-a1", "attr-contains-a3"], level: 3, testType: TEST_QSA | TEST_MATCH},
+ {name: "Attribute contains selector, matching href attributes ending with specified substring", selector: "#attr-contains a[href*=\".org\"]", expect: ["attr-contains-a1", "attr-contains-a2"], level: 3, testType: TEST_QSA | TEST_MATCH},
+ {name: "Attribute contains selector, matching href attributes containing specified substring", selector: "#attr-contains a[href*=\".example.\"]", expect: ["attr-contains-a1", "attr-contains-a3"], level: 3, testType: TEST_QSA | TEST_MATCH},
+ {name: "Attribute contains selector, matching lang attributes beginning with specified substring, ", selector: "#attr-contains [lang*=\"en-\"]", expect: ["attr-contains-div2", "attr-contains-div6"], level: 3, testType: TEST_QSA | TEST_MATCH},
+ {name: "Attribute contains selector, matching lang attributes ending with specified substring, ", selector: "#attr-contains [lang*=\"-CH\"]", expect: ["attr-contains-div3", "attr-contains-div5"], level: 3, testType: TEST_QSA | TEST_MATCH},
+ {name: "Attribute contains selector with single-quoted value, matching class attribute beginning with specified substring", selector: "#attr-contains [class*=' apple']", expect: ["attr-contains-p1"], level: 3, testType: TEST_QSA | TEST_MATCH},
+ {name: "Attribute contains selector with single-quoted value, matching class attribute ending with specified substring", selector: "#attr-contains [class*='orange ']", expect: ["attr-contains-p1"], level: 3, testType: TEST_QSA | TEST_MATCH},
+ {name: "Attribute contains selector with single-quoted value, matching class attribute containing specified substring", selector: "#attr-contains [class*='ple banana ora']", expect: ["attr-contains-p1"], level: 3, testType: TEST_QSA | TEST_MATCH},
+ {name: "Attribute contains selector with double-quoted value, matching class attribute beginning with specified substring", selector: "#attr-contains [class*=\" apple\"]", expect: ["attr-contains-p1"], level: 3, testType: TEST_QSA | TEST_MATCH},
+ {name: "Attribute contains selector with double-quoted value, matching class attribute ending with specified substring", selector: "#attr-contains [class*=\"orange \"]", expect: ["attr-contains-p1"], level: 3, testType: TEST_QSA | TEST_MATCH},
+ {name: "Attribute contains selector with double-quoted value, matching class attribute containing specified substring", selector: "#attr-contains [class*=\"ple banana ora\"]", expect: ["attr-contains-p1"], level: 3, testType: TEST_QSA | TEST_MATCH},
+ {name: "Attribute contains selector with unquoted value, matching class attribute beginning with specified substring", selector: "#attr-contains [class*= apple]", expect: ["attr-contains-p1"], level: 3, testType: TEST_QSA | TEST_MATCH},
+ {name: "Attribute contains selector with unquoted value, matching class attribute ending with specified substring", selector: "#attr-contains [class*=orange ]", expect: ["attr-contains-p1"], level: 3, testType: TEST_QSA | TEST_MATCH},
+ {name: "Attribute contains selector with unquoted value, matching class attribute containing specified substring", selector: "#attr-contains [class*= banana ]", expect: ["attr-contains-p1"], level: 3, testType: TEST_QSA | TEST_MATCH},
+
+ // Pseudo-classes
+ // - :root (Level 3)
+ {name: ":root pseudo-class selector, matching document root element", selector: ":root", expect: ["html"], exclude: ["element", "fragment", "detached"], level: 3, testType: TEST_QSA | TEST_MATCH},
+ {name: ":root pseudo-class selector, not matching document root element", selector: ":root", expect: [] /*no matches*/, exclude: ["document"], level: 3, testType: TEST_QSA},
+
+ // - :nth-child(n) (Level 3)
+ // XXX write descriptions
+ {name: ":nth-child selector, matching the third child element", selector: "#pseudo-nth-table1 :nth-child(3)", expect: ["pseudo-nth-td3", "pseudo-nth-td9", "pseudo-nth-tr3", "pseudo-nth-td15"], level: 3, testType: TEST_QSA | TEST_MATCH},
+ {name: ":nth-child selector, matching every third child element", selector: "#pseudo-nth li:nth-child(3n)", expect: ["pseudo-nth-li3", "pseudo-nth-li6", "pseudo-nth-li9", "pseudo-nth-li12"], level: 3, testType: TEST_QSA | TEST_MATCH},
+ {name: ":nth-child selector, matching every second child element, starting from the fourth", selector: "#pseudo-nth li:nth-child(2n+4)", expect: ["pseudo-nth-li4", "pseudo-nth-li6", "pseudo-nth-li8", "pseudo-nth-li10", "pseudo-nth-li12"], level: 3, testType: TEST_QSA | TEST_MATCH},
+ {name: ":nth-child selector, matching every fourth child element, starting from the third", selector: "#pseudo-nth-p1 :nth-child(4n-1)", expect: ["pseudo-nth-em2", "pseudo-nth-span3"], level: 3, testType: TEST_QSA | TEST_MATCH},
+
+ // - :nth-last-child (Level 3)
+ {name: ":nth-last-child selector, matching the third last child element", selector: "#pseudo-nth-table1 :nth-last-child(3)", expect: ["pseudo-nth-tr1", "pseudo-nth-td4", "pseudo-nth-td10", "pseudo-nth-td16"], level: 3, testType: TEST_QSA | TEST_MATCH},
+ {name: ":nth-last-child selector, matching every third child element from the end", selector: "#pseudo-nth li:nth-last-child(3n)", expect: ["pseudo-nth-li1", "pseudo-nth-li4", "pseudo-nth-li7", "pseudo-nth-li10"], level: 3, testType: TEST_QSA | TEST_MATCH},
+ {name: ":nth-last-child selector, matching every second child element from the end, starting from the fourth last", selector: "#pseudo-nth li:nth-last-child(2n+4)", expect: ["pseudo-nth-li1", "pseudo-nth-li3", "pseudo-nth-li5", "pseudo-nth-li7", "pseudo-nth-li9"], level: 3, testType: TEST_QSA | TEST_MATCH},
+ {name: ":nth-last-child selector, matching every fourth element from the end, starting from the third last", selector: "#pseudo-nth-p1 :nth-last-child(4n-1)", expect: ["pseudo-nth-span2", "pseudo-nth-span4"], level: 3, testType: TEST_QSA | TEST_MATCH},
+
+ // - :nth-of-type(n) (Level 3)
+ {name: ":nth-of-type selector, matching the third em element", selector: "#pseudo-nth-p1 em:nth-of-type(3)", expect: ["pseudo-nth-em3"], level: 3, testType: TEST_QSA | TEST_MATCH},
+ {name: ":nth-of-type selector, matching every second element of their type", selector: "#pseudo-nth-p1 :nth-of-type(2n)", expect: ["pseudo-nth-em2", "pseudo-nth-span2", "pseudo-nth-span4", "pseudo-nth-strong2", "pseudo-nth-em4"], level: 3, testType: TEST_QSA | TEST_MATCH},
+ {name: ":nth-of-type selector, matching every second elemetn of their type, starting from the first", selector: "#pseudo-nth-p1 span:nth-of-type(2n-1)", expect: ["pseudo-nth-span1", "pseudo-nth-span3"], level: 3, testType: TEST_QSA | TEST_MATCH},
+
+ // - :nth-last-of-type(n) (Level 3)
+ {name: ":nth-last-of-type selector, matching the thrid last em element", selector: "#pseudo-nth-p1 em:nth-last-of-type(3)", expect: ["pseudo-nth-em2"], level: 3, testType: TEST_QSA | TEST_MATCH},
+ {name: ":nth-last-of-type selector, matching every second last element of their type", selector: "#pseudo-nth-p1 :nth-last-of-type(2n)", expect: ["pseudo-nth-span1", "pseudo-nth-em1", "pseudo-nth-strong1", "pseudo-nth-em3", "pseudo-nth-span3"], level: 3, testType: TEST_QSA | TEST_MATCH},
+ {name: ":nth-last-of-type selector, matching every second last element of their type, starting from the last", selector: "#pseudo-nth-p1 span:nth-last-of-type(2n-1)", expect: ["pseudo-nth-span2", "pseudo-nth-span4"], level: 3, testType: TEST_QSA | TEST_MATCH},
+
+ // - :first-of-type (Level 3)
+ {name: ":first-of-type selector, matching the first em element", selector: "#pseudo-nth-p1 em:first-of-type", expect: ["pseudo-nth-em1"], level: 3, testType: TEST_QSA | TEST_MATCH},
+ {name: ":first-of-type selector, matching the first of every type of element", selector: "#pseudo-nth-p1 :first-of-type", expect: ["pseudo-nth-span1", "pseudo-nth-em1", "pseudo-nth-strong1"], level: 3, testType: TEST_QSA | TEST_MATCH},
+ {name: ":first-of-type selector, matching the first td element in each table row", selector: "#pseudo-nth-table1 tr :first-of-type", expect: ["pseudo-nth-td1", "pseudo-nth-td7", "pseudo-nth-td13"], level: 3, testType: TEST_QSA | TEST_MATCH},
+
+ // - :last-of-type (Level 3)
+ {name: ":last-of-type selector, matching the last em elemnet", selector: "#pseudo-nth-p1 em:last-of-type", expect: ["pseudo-nth-em4"], level: 3, testType: TEST_QSA | TEST_MATCH},
+ {name: ":last-of-type selector, matching the last of every type of element", selector: "#pseudo-nth-p1 :last-of-type", expect: ["pseudo-nth-span4", "pseudo-nth-strong2", "pseudo-nth-em4"], level: 3, testType: TEST_QSA | TEST_MATCH},
+ {name: ":last-of-type selector, matching the last td element in each table row", selector: "#pseudo-nth-table1 tr :last-of-type", expect: ["pseudo-nth-td6", "pseudo-nth-td12", "pseudo-nth-td18"], level: 3, testType: TEST_QSA | TEST_MATCH},
+
+ // - :first-child
+ {name: ":first-child pseudo-class selector, matching first child div element", selector: "#pseudo-first-child div:first-child", expect: ["pseudo-first-child-div1"], level: 2, testType: TEST_QSA | TEST_MATCH},
+ {name: ":first-child pseudo-class selector, doesn't match non-first-child elements", selector: ".pseudo-first-child-div2:first-child, .pseudo-first-child-div3:first-child", expect: [] /*no matches*/, level: 2, testType: TEST_QSA},
+ {name: ":first-child pseudo-class selector, matching first-child of multiple elements", selector: "#pseudo-first-child span:first-child", expect: ["pseudo-first-child-span1", "pseudo-first-child-span3", "pseudo-first-child-span5"], level: 2, testType: TEST_QSA | TEST_MATCH},
+
+ // - :last-child (Level 3)
+ {name: ":last-child pseudo-class selector, matching last child div element", selector: "#pseudo-last-child div:last-child", expect: ["pseudo-last-child-div3"], level: 3, testType: TEST_QSA | TEST_MATCH},
+ {name: ":last-child pseudo-class selector, doesn't match non-last-child elements", selector: ".pseudo-last-child-div1:last-child, .pseudo-last-child-div2:first-child", expect: [] /*no matches*/, level: 3, testType: TEST_QSA},
+ {name: ":last-child pseudo-class selector, matching first-child of multiple elements", selector: "#pseudo-last-child span:last-child", expect: ["pseudo-last-child-span2", "pseudo-last-child-span4", "pseudo-last-child-span6"], level: 3, testType: TEST_QSA | TEST_MATCH},
+
+ // - :only-child (Level 3)
+ {name: ":pseudo-only-child pseudo-class selector, matching all only-child elements", selector: "#pseudo-only :only-child", expect: ["pseudo-only-span1"], level: 3, testType: TEST_QSA | TEST_MATCH},
+ {name: ":pseudo-only-child pseudo-class selector, matching only-child em elements", selector: "#pseudo-only em:only-child", expect: [] /*no matches*/, level: 3, testType: TEST_QSA},
+
+ // - :only-of-type (Level 3)
+ {name: ":pseudo-only-of-type pseudo-class selector, matching all elements with no siblings of the same type", selector: "#pseudo-only :only-of-type", expect: ["pseudo-only-span1", "pseudo-only-em1"], level: 3, testType: TEST_QSA | TEST_MATCH},
+ {name: ":pseudo-only-of-type pseudo-class selector, matching em elements with no siblings of the same type", selector: "#pseudo-only em:only-of-type", expect: ["pseudo-only-em1"], level: 3, testType: TEST_QSA | TEST_MATCH},
+
+ // - :empty (Level 3)
+ {name: ":empty pseudo-class selector, matching empty p elements", selector: "#pseudo-empty p:empty", expect: ["pseudo-empty-p1", "pseudo-empty-p2"], level: 3, testType: TEST_QSA | TEST_MATCH},
+ {name: ":empty pseudo-class selector, matching all empty elements", selector: "#pseudo-empty :empty", expect: ["pseudo-empty-p1", "pseudo-empty-p2", "pseudo-empty-span1"], level: 3, testType: TEST_QSA | TEST_MATCH},
+
+ // - :link and :visited
+ // Implementations may treat all visited links as unvisited, so these cannot be tested separately.
+ // The only guarantee is that ":link,:visited" matches the set of all visited and unvisited links and that they are individually mutually exclusive sets.
+ {name: ":link and :visited pseudo-class selectors, matching a and area elements with href attributes", selector: "#pseudo-link :link, #pseudo-link :visited", expect: ["pseudo-link-a1", "pseudo-link-a2", "pseudo-link-area1"], level: 1, testType: TEST_QSA | TEST_MATCH},
+ {name: ":link and :visited pseudo-class selectors, matching link elements with href attributes", selector: "#head :link, #head :visited", expect: ["pseudo-link-link1", "pseudo-link-link2"], exclude: ["element", "fragment", "detached"], level: 1, testType: TEST_QSA | TEST_MATCH},
+ {name: ":link and :visited pseudo-class selectors, not matching link elements with href attributes", selector: "#head :link, #head :visited", expect: [] /*no matches*/, exclude: ["document"], level: 1, testType: TEST_QSA},
+ {name: ":link and :visited pseudo-class selectors, chained, mutually exclusive pseudo-classes match nothing", selector: ":link:visited", expect: [] /*no matches*/, exclude: ["document"], level: 1, testType: TEST_QSA},
+
+ // - :target (Level 3)
+ {name: ":target pseudo-class selector, matching the element referenced by the URL fragment identifier", selector: ":target", expect: [] /*no matches*/, exclude: ["document", "element"], level: 3, testType: TEST_QSA},
+ {name: ":target pseudo-class selector, matching the element referenced by the URL fragment identifier", selector: ":target", expect: ["target"], exclude: ["fragment", "detached"], level: 3, testType: TEST_QSA | TEST_MATCH},
+
+ // - :lang()
+ {name: ":lang pseudo-class selector, matching inherited language", selector: "#pseudo-lang-div1:lang(en)", expect: ["pseudo-lang-div1"], exclude: ["detached", "fragment"], level: 2, testType: TEST_QSA | TEST_MATCH},
+ {name: ":lang pseudo-class selector, not matching element with no inherited language", selector: "#pseudo-lang-div1:lang(en)", expect: [] /*no matches*/, exclude: ["document", "element"], level: 2, testType: TEST_QSA},
+ {name: ":lang pseudo-class selector, matching specified language with exact value", selector: "#pseudo-lang-div2:lang(fr)", expect: ["pseudo-lang-div2"], level: 2, testType: TEST_QSA | TEST_MATCH},
+ {name: ":lang pseudo-class selector, matching specified language with partial value", selector: "#pseudo-lang-div3:lang(en)", expect: ["pseudo-lang-div3"], level: 2, testType: TEST_QSA | TEST_MATCH},
+ {name: ":lang pseudo-class selector, not matching incorrect language", selector: "#pseudo-lang-div4:lang(es-AR)", expect: [] /*no matches*/, level: 2, testType: TEST_QSA},
+
+ // - :enabled (Level 3)
+ {name: ":enabled pseudo-class selector, matching all enabled form controls", selector: "#pseudo-ui :enabled", expect: ["pseudo-ui-input1", "pseudo-ui-input2", "pseudo-ui-input3", "pseudo-ui-input4", "pseudo-ui-input5", "pseudo-ui-input6",
+ "pseudo-ui-input7", "pseudo-ui-input8", "pseudo-ui-input9", "pseudo-ui-textarea1", "pseudo-ui-button1"], level: 3, testType: TEST_QSA | TEST_MATCH},
+
+ // - :disabled (Level 3)
+ {name: ":enabled pseudo-class selector, matching all disabled form controls", selector: "#pseudo-ui :disabled", expect: ["pseudo-ui-input10", "pseudo-ui-input11", "pseudo-ui-input12", "pseudo-ui-input13", "pseudo-ui-input14", "pseudo-ui-input15",
+ "pseudo-ui-input16", "pseudo-ui-input17", "pseudo-ui-input18", "pseudo-ui-textarea2", "pseudo-ui-button2"], level: 3, testType: TEST_QSA | TEST_MATCH},
+
+ // - :checked (Level 3)
+ {name: ":checked pseudo-class selector, matching checked radio buttons and checkboxes", selector: "#pseudo-ui :checked", expect: ["pseudo-ui-input4", "pseudo-ui-input6", "pseudo-ui-input13", "pseudo-ui-input15"], level: 3, testType: TEST_QSA | TEST_MATCH},
+
+ // - :not(s) (Level 3)
+ {name: ":not pseudo-class selector, matching ", selector: "#not>:not(div)", expect: ["not-p1", "not-p2", "not-p3"], level: 3, testType: TEST_QSA | TEST_MATCH},
+ {name: ":not pseudo-class selector, matching ", selector: "#not * :not(:first-child)", expect: ["not-em1", "not-em2", "not-em3"], level: 3, testType: TEST_QSA | TEST_MATCH},
+ {name: ":not pseudo-class selector, matching nothing", selector: ":not(*)", expect: [] /* no matches */, level: 3, testType: TEST_QSA},
+ {name: ":not pseudo-class selector, matching nothing", selector: ":not(*|*)", expect: [] /* no matches */, level: 3, testType: TEST_QSA},
+
+ // Pseudo-elements
+ // - ::first-line
+ {name: ":first-line pseudo-element (one-colon syntax) selector, not matching any elements", selector: "#pseudo-element:first-line", expect: [] /*no matches*/, level: 2, testType: TEST_QSA},
+ {name: "::first-line pseudo-element (two-colon syntax) selector, not matching any elements", selector: "#pseudo-element::first-line", expect: [] /*no matches*/, level: 3, testType: TEST_QSA},
+
+ // - ::first-letter
+ {name: ":first-letter pseudo-element (one-colon syntax) selector, not matching any elements", selector: "#pseudo-element:first-letter", expect: [] /*no matches*/, level: 2, testType: TEST_QSA},
+ {name: "::first-letter pseudo-element (two-colon syntax) selector, not matching any elements", selector: "#pseudo-element::first-letter", expect: [] /*no matches*/, level: 3, testType: TEST_QSA},
+
+ // - ::before
+ {name: ":before pseudo-element (one-colon syntax) selector, not matching any elements", selector: "#pseudo-element:before", expect: [] /*no matches*/, level: 2, testType: TEST_QSA},
+ {name: "::before pseudo-element (two-colon syntax) selector, not matching any elements", selector: "#pseudo-element::before", expect: [] /*no matches*/, level: 3, testType: TEST_QSA},
+
+ // - ::after
+ {name: ":after pseudo-element (one-colon syntax) selector, not matching any elements", selector: "#pseudo-element:after", expect: [] /*no matches*/, level: 2, testType: TEST_QSA},
+ {name: "::after pseudo-element (two-colon syntax) selector, not matching any elements", selector: "#pseudo-element::after", expect: [] /*no matches*/, level: 3, testType: TEST_QSA},
+
+ // Class Selectors
+ {name: "Class selector, matching element with specified class", selector: ".class-p", expect: ["class-p1","class-p2", "class-p3"], level: 1, testType: TEST_QSA | TEST_MATCH},
+ {name: "Class selector, chained, matching only elements with all specified classes", selector: "#class .apple.orange.banana", expect: ["class-div1", "class-div2", "class-p4", "class-div3", "class-p6", "class-div4"], level: 1, testType: TEST_QSA | TEST_MATCH},
+ {name: "Class Selector, chained, with type selector", selector: "div.apple.banana.orange", expect: ["class-div1", "class-div2", "class-div3", "class-div4"], level: 1, testType: TEST_QSA | TEST_MATCH},
+ // Caution: If copying and pasting the folowing non-ASCII classes, ensure unicode normalisation is not performed in the process.
+ {name: "Class selector, matching element with class value using non-ASCII characters", selector: ".台北Táiběi", expect: ["class-span1"], level: 1, testType: TEST_QSA | TEST_MATCH},
+ {name: "Class selector, matching multiple elements with class value using non-ASCII characters", selector: ".台北", expect: ["class-span1","class-span2"], level: 1, testType: TEST_QSA | TEST_MATCH},
+ {name: "Class selector, chained, matching element with multiple class values using non-ASCII characters", selector: ".台北Táiběi.台北", expect: ["class-span1"], level: 1, testType: TEST_QSA | TEST_MATCH},
+ {name: "Class selector, matching element with class with escaped character", selector: ".foo\\:bar", expect: ["class-span3"], level: 1, testType: TEST_QSA | TEST_MATCH},
+ {name: "Class selector, matching element with class with escaped character", selector: ".test\\.foo\\[5\\]bar", expect: ["class-span4"], level: 1, testType: TEST_QSA | TEST_MATCH},
+
+ // ID Selectors
+ {name: "ID selector, matching element with specified id", selector: "#id #id-div1", expect: ["id-div1"], level: 1, testType: TEST_QSA | TEST_MATCH},
+ {name: "ID selector, chained, matching element with specified id", selector: "#id-div1, #id-div1", expect: ["id-div1"], level: 1, testType: TEST_QSA | TEST_MATCH},
+ {name: "ID selector, chained, matching element with specified id", selector: "#id-div1, #id-div2", expect: ["id-div1", "id-div2"], level: 1, testType: TEST_QSA | TEST_MATCH},
+ {name: "ID Selector, chained, with type selector", selector: "div#id-div1, div#id-div2", expect: ["id-div1", "id-div2"], level: 1, testType: TEST_QSA | TEST_MATCH},
+ {name: "ID selector, not matching non-existent descendant", selector: "#id #none", expect: [] /*no matches*/, level: 1, testType: TEST_QSA},
+ {name: "ID selector, not matching non-existent ancestor", selector: "#none #id-div1", expect: [] /*no matches*/, level: 1, testType: TEST_QSA},
+ {name: "ID selector, matching multiple elements with duplicate id", selector: "#id-li-duplicate", expect: ["id-li-duplicate", "id-li-duplicate", "id-li-duplicate", "id-li-duplicate"], level: 1, testType: TEST_QSA | TEST_MATCH},
+
+ // Caution: If copying and pasting the folowing non-ASCII IDs, ensure unicode normalisation is not performed in the process.
+ {name: "ID selector, matching id value using non-ASCII characters", selector: "#台北Táiběi", expect: ["台北Táiběi"], level: 1, testType: TEST_QSA | TEST_MATCH},
+ {name: "ID selector, matching id value using non-ASCII characters", selector: "#台北", expect: ["台北"], level: 1, testType: TEST_QSA | TEST_MATCH},
+ {name: "ID selector, matching id values using non-ASCII characters", selector: "#台北Táiběi, #台北", expect: ["台北Táiběi", "台北"], level: 1, testType: TEST_QSA | TEST_MATCH},
+
+ // XXX runMatchesTest() in level2-lib.js can't handle this because obtaining the expected nodes requires escaping characters when generating the selector from 'expect' values
+ {name: "ID selector, matching element with id with escaped character", selector: "#\\#foo\\:bar", expect: ["#foo:bar"], level: 1, testType: TEST_QSA},
+ {name: "ID selector, matching element with id with escaped character", selector: "#test\\.foo\\[5\\]bar", expect: ["test.foo[5]bar"], level: 1, testType: TEST_QSA},
+
+ // Namespaces
+ // XXX runMatchesTest() in level2-lib.js can't handle these because non-HTML elements don't have a recognised id
+ {name: "Namespace selector, matching element with any namespace", selector: "#any-namespace *|div", expect: ["any-namespace-div1", "any-namespace-div2", "any-namespace-div3", "any-namespace-div4"], level: 3, testType: TEST_QSA},
+ {name: "Namespace selector, matching div elements in no namespace only", selector: "#no-namespace |div", expect: ["no-namespace-div3"], level: 3, testType: TEST_QSA},
+ {name: "Namespace selector, matching any elements in no namespace only", selector: "#no-namespace |*", expect: ["no-namespace-div3"], level: 3, testType: TEST_QSA},
+
+ // Combinators
+ // - Descendant combinator ' '
+ {name: "Descendant combinator, matching element that is a descendant of an element with id", selector: "#descendant div", expect: ["descendant-div1", "descendant-div2", "descendant-div3", "descendant-div4"], level: 1, testType: TEST_QSA | TEST_MATCH},
+ {name: "Descendant combinator, matching element with id that is a descendant of an element", selector: "body #descendant-div1", expect: ["descendant-div1"], exclude: ["detached", "fragment"], level: 1, testType: TEST_QSA | TEST_MATCH},
+ {name: "Descendant combinator, matching element with id that is a descendant of an element", selector: "div #descendant-div1", expect: ["descendant-div1"], level: 1, testType: TEST_QSA | TEST_MATCH},
+ {name: "Descendant combinator, matching element with id that is a descendant of an element with id", selector: "#descendant #descendant-div2", expect: ["descendant-div2"], level: 1, testType: TEST_QSA | TEST_MATCH},
+ {name: "Descendant combinator, matching element with class that is a descendant of an element with id", selector: "#descendant .descendant-div2", expect: ["descendant-div2"], level: 1, testType: TEST_QSA | TEST_MATCH},
+ {name: "Descendant combinator, matching element with class that is a descendant of an element with class", selector: ".descendant-div1 .descendant-div3", expect: ["descendant-div3"], level: 1, testType: TEST_QSA | TEST_MATCH},
+ {name: "Descendant combinator, not matching element with id that is not a descendant of an element with id", selector: "#descendant-div1 #descendant-div4", expect: [] /*no matches*/, level: 1, testType: TEST_QSA},
+ {name: "Descendant combinator, whitespace characters", selector: "#descendant\t\r\n#descendant-div2", expect: ["descendant-div2"], level: 1, testType: TEST_QSA | TEST_MATCH},
+
+ // - Child combinator '>'
+ {name: "Child combinator, matching element that is a child of an element with id", selector: "#child>div", expect: ["child-div1", "child-div4"], level: 2, testType: TEST_QSA | TEST_MATCH},
+ {name: "Child combinator, matching element with id that is a child of an element", selector: "div>#child-div1", expect: ["child-div1"], level: 2, testType: TEST_QSA | TEST_MATCH},
+ {name: "Child combinator, matching element with id that is a child of an element with id", selector: "#child>#child-div1", expect: ["child-div1"], level: 2, testType: TEST_QSA | TEST_MATCH},
+ {name: "Child combinator, matching element with id that is a child of an element with class", selector: "#child-div1>.child-div2", expect: ["child-div2"], level: 2, testType: TEST_QSA | TEST_MATCH},
+ {name: "Child combinator, matching element with class that is a child of an element with class", selector: ".child-div1>.child-div2", expect: ["child-div2"], level: 2, testType: TEST_QSA | TEST_MATCH},
+ {name: "Child combinator, not matching element with id that is not a child of an element with id", selector: "#child>#child-div3", expect: [] /*no matches*/, level: 2, testType: TEST_QSA},
+ {name: "Child combinator, not matching element with id that is not a child of an element with class", selector: "#child-div1>.child-div3", expect: [] /*no matches*/, level: 2, testType: TEST_QSA},
+ {name: "Child combinator, not matching element with class that is not a child of an element with class", selector: ".child-div1>.child-div3", expect: [] /*no matches*/, level: 2, testType: TEST_QSA},
+ {name: "Child combinator, surrounded by whitespace", selector: "#child-div1\t\r\n>\t\r\n#child-div2", expect: ["child-div2"], level: 2, testType: TEST_QSA | TEST_MATCH},
+ {name: "Child combinator, whitespace after", selector: "#child-div1>\t\r\n#child-div2", expect: ["child-div2"], level: 2, testType: TEST_QSA | TEST_MATCH},
+ {name: "Child combinator, whitespace before", selector: "#child-div1\t\r\n>#child-div2", expect: ["child-div2"], level: 2, testType: TEST_QSA | TEST_MATCH},
+ {name: "Child combinator, no whitespace", selector: "#child-div1>#child-div2", expect: ["child-div2"], level: 2, testType: TEST_QSA | TEST_MATCH},
+
+ // - Adjacent sibling combinator '+'
+ {name: "Adjacent sibling combinator, matching element that is an adjacent sibling of an element with id", selector: "#adjacent-div2+div", expect: ["adjacent-div4"], level: 2, testType: TEST_QSA | TEST_MATCH},
+ {name: "Adjacent sibling combinator, matching element with id that is an adjacent sibling of an element", selector: "div+#adjacent-div4", expect: ["adjacent-div4"], level: 2, testType: TEST_QSA | TEST_MATCH},
+ {name: "Adjacent sibling combinator, matching element with id that is an adjacent sibling of an element with id", selector: "#adjacent-div2+#adjacent-div4", expect: ["adjacent-div4"], level: 2, testType: TEST_QSA | TEST_MATCH},
+ {name: "Adjacent sibling combinator, matching element with class that is an adjacent sibling of an element with id", selector: "#adjacent-div2+.adjacent-div4", expect: ["adjacent-div4"], level: 2, testType: TEST_QSA | TEST_MATCH},
+ {name: "Adjacent sibling combinator, matching element with class that is an adjacent sibling of an element with class", selector: ".adjacent-div2+.adjacent-div4", expect: ["adjacent-div4"], level: 2, testType: TEST_QSA | TEST_MATCH},
+ {name: "Adjacent sibling combinator, matching p element that is an adjacent sibling of a div element", selector: "#adjacent div+p", expect: ["adjacent-p2"], level: 2, testType: TEST_QSA | TEST_MATCH},
+ {name: "Adjacent sibling combinator, not matching element with id that is not an adjacent sibling of an element with id", selector: "#adjacent-div2+#adjacent-p2, #adjacent-div2+#adjacent-div1", expect: [] /*no matches*/, level: 2, testType: TEST_QSA},
+ {name: "Adjacent sibling combinator, surrounded by whitespace", selector: "#adjacent-p2\t\r\n+\t\r\n#adjacent-p3", expect: ["adjacent-p3"], level: 2, testType: TEST_QSA | TEST_MATCH},
+ {name: "Adjacent sibling combinator, whitespace after", selector: "#adjacent-p2+\t\r\n#adjacent-p3", expect: ["adjacent-p3"], level: 2, testType: TEST_QSA | TEST_MATCH},
+ {name: "Adjacent sibling combinator, whitespace before", selector: "#adjacent-p2\t\r\n+#adjacent-p3", expect: ["adjacent-p3"], level: 2, testType: TEST_QSA | TEST_MATCH},
+ {name: "Adjacent sibling combinator, no whitespace", selector: "#adjacent-p2+#adjacent-p3", expect: ["adjacent-p3"], level: 2, testType: TEST_QSA | TEST_MATCH},
+
+ // - General sibling combinator ~ (Level 3)
+ {name: "General sibling combinator, matching element that is a sibling of an element with id", selector: "#sibling-div2~div", expect: ["sibling-div4", "sibling-div6"], level: 3, testType: TEST_QSA | TEST_MATCH},
+ {name: "General sibling combinator, matching element with id that is a sibling of an element", selector: "div~#sibling-div4", expect: ["sibling-div4"], level: 3, testType: TEST_QSA | TEST_MATCH},
+ {name: "General sibling combinator, matching element with id that is a sibling of an element with id", selector: "#sibling-div2~#sibling-div4", expect: ["sibling-div4"], level: 3, testType: TEST_QSA | TEST_MATCH},
+ {name: "General sibling combinator, matching element with class that is a sibling of an element with id", selector: "#sibling-div2~.sibling-div", expect: ["sibling-div4", "sibling-div6"], level: 3, testType: TEST_QSA | TEST_MATCH},
+ {name: "General sibling combinator, matching p element that is a sibling of a div element", selector: "#sibling div~p", expect: ["sibling-p2", "sibling-p3"], level: 3, testType: TEST_QSA | TEST_MATCH},
+ {name: "General sibling combinator, not matching element with id that is not a sibling after a p element", selector: "#sibling>p~div", expect: [] /*no matches*/, level: 3, testType: TEST_QSA},
+ {name: "General sibling combinator, not matching element with id that is not a sibling after an element with id", selector: "#sibling-div2~#sibling-div3, #sibling-div2~#sibling-div1", expect: [] /*no matches*/, level: 3, testType: TEST_QSA},
+ {name: "General sibling combinator, surrounded by whitespace", selector: "#sibling-p2\t\r\n~\t\r\n#sibling-p3", expect: ["sibling-p3"], level: 3, testType: TEST_QSA | TEST_MATCH},
+ {name: "General sibling combinator, whitespace after", selector: "#sibling-p2~\t\r\n#sibling-p3", expect: ["sibling-p3"], level: 3, testType: TEST_QSA | TEST_MATCH},
+ {name: "General sibling combinator, whitespace before", selector: "#sibling-p2\t\r\n~#sibling-p3", expect: ["sibling-p3"], level: 3, testType: TEST_QSA | TEST_MATCH},
+ {name: "General sibling combinator, no whitespace", selector: "#sibling-p2~#sibling-p3", expect: ["sibling-p3"], level: 3, testType: TEST_QSA | TEST_MATCH},
+
+ // Group of selectors (comma)
+ {name: "Syntax, group of selectors separator, surrounded by whitespace", selector: "#group em\t\r \n,\t\r \n#group strong", expect: ["group-em1", "group-strong1"], level: 1, testType: TEST_QSA | TEST_MATCH},
+ {name: "Syntax, group of selectors separator, whitespace after", selector: "#group em,\t\r\n#group strong", expect: ["group-em1", "group-strong1"], level: 1, testType: TEST_QSA | TEST_MATCH},
+ {name: "Syntax, group of selectors separator, whitespace before", selector: "#group em\t\r\n,#group strong", expect: ["group-em1", "group-strong1"], level: 1, testType: TEST_QSA | TEST_MATCH},
+ {name: "Syntax, group of selectors separator, no whitespace", selector: "#group em,#group strong", expect: ["group-em1", "group-strong1"], level: 1, testType: TEST_QSA | TEST_MATCH},
+];
+
+
+/*
+ * These selectors are intended to be used with the find(), findAll() and matches() methods. Expected results
+ * should be determined under the assumption that :scope will be prepended to the selector where appropriate,
+ * in accordance with the specification.
+ *
+ * All of these should be valid relative selectors, expected to match zero or more elements in the document.
+ * None should throw any errors.
+ *
+ * name: A descriptive name of the selector being tested
+ *
+ * selector: The selector to test
+ *
+ * ctx: A selector to obtain the context object to use for tests invoking context.find(),
+ * and to use as a single reference node for tests invoking document.find().
+ * Note: context = root.querySelector(ctx);
+ *
+ * ref: A selector to obtain the reference nodes to be used for the selector.
+ * Note: If root is the document or an in-document element:
+ * refNodes = document.querySelectorAll(ref);
+ * Otherwise, if root is a fragment or detached element:
+ * refNodes = root.querySelectorAll(ref);
+ *
+ * expect: A list of IDs of the elements expected to be matched. List must be given in tree order.
+ *
+ * unexpected: A list of IDs of some elements that are not expected to match the given selector.
+ * This is used to verify that unexpected.matches(selector, refNode) does not match.
+ *
+ * exclude: An array of contexts to exclude from testing. The valid values are:
+ * ["document", "element", "fragment", "detached", "html", "xhtml"]
+ * The "html" and "xhtml" values represent the type of document being queried. These are useful
+ * for tests that are affected by differences between HTML and XML, such as case sensitivity.
+ *
+ * level: An integer indicating the CSS or Selectors level in which the selector being tested was introduced.
+ *
+ * testType: A bit-mapped flag indicating the type of test.
+ *
+ * The test function for these tests accepts a specified root node, on which the methods will be invoked during the tests.
+ *
+ * Based on whether either 'context' or 'refNodes', or both, are specified the tests will execute the following methods:
+ *
+ * Where testType is TEST_FIND:
+ *
+ * context.findAll(selector, refNodes)
+ * context.findAll(selector) // Only if refNodes is not specified
+ * root.findAll(selector, context) // Only if refNodes is not specified
+ * root.findAll(selector, refNodes) // Only if context is not specified
+ * root.findAll(selector) // Only if neither context nor refNodes is specified
+ *
+ * Where testType is TEST_QSA
+ *
+ * context.querySelectorAll(selector)
+ * root.querySelectorAll(selector) // Only if neither context nor refNodes is specified
+ *
+ * Equivalent tests will be run for .find() as well.
+ * Note: Do not specify a testType of TEST_QSA where either implied :scope or explicit refNodes
+ * are required.
+ *
+ * Where testType is TEST_MATCH:
+ * For each expected result given, within the specified root:
+ *
+ * expect.matches(selector, context) // Only where refNodes is not specified
+ * expect.matches(selector, refNodes)
+ * expect.matches(selector) // Only if neither context nor refNodes is specified
+ *
+ * The tests involving refNodes for both find(), findAll() and matches() will each be run by passing the
+ * collection as a NodeList, an Array and, if there is only a single element, an Element node.
+ *
+ * Note: Interactive pseudo-classes (:active :hover and :focus) have not been tested in this test suite.
+ */
+
+var scopedSelectors = [
+ //{name: "", selector: "", ctx: "", ref: "", expect: [], level: 1, testType: TEST_FIND | TEST_MATCH},
+
+ // Universal Selector
+ {name: "Universal selector, matching all children of the specified reference element", selector: ">*", ctx: "#universal", expect: ["universal-p1", "universal-hr1", "universal-pre1", "universal-p2", "universal-address1"], unexpected: ["universal", "empty"], level: 2, testType: TEST_FIND | TEST_MATCH},
+ {name: "Universal selector, matching all grandchildren of the specified reference element", selector: ">*>*", ctx: "#universal", expect: ["universal-code1", "universal-span1", "universal-a1", "universal-code2"], unexpected: ["universal", "empty"], level: 2, testType: TEST_FIND | TEST_MATCH},
+ {name: "Universal selector, matching all children of the specified empty reference element", selector: ">*", ctx: "#empty", expect: [] /*no matches*/, unexpected: ["universal", "empty"], level: 2, testType: TEST_QSA},
+ {name: "Universal selector, matching all descendants of the specified reference element", selector: "*", ctx: "#universal", expect: ["universal-p1", "universal-code1", "universal-hr1", "universal-pre1", "universal-span1",
+ "universal-p2", "universal-a1", "universal-address1", "universal-code2", "universal-a2"], unexpected: ["universal", "empty"], level: 2, testType: TEST_FIND | TEST_MATCH},
+
+ // Attribute Selectors
+ // - presence [att]
+ {name: "Attribute presence selector, matching align attribute with value", selector: ".attr-presence-div1[align]", ctx: "#attr-presence", expect: ["attr-presence-div1"], level: 2, testType: TEST_FIND | TEST_MATCH},
+ {name: "Attribute presence selector, matching align attribute with empty value", selector: ".attr-presence-div2[align]", ctx: "#attr-presence", expect: ["attr-presence-div2"], level: 2, testType: TEST_FIND | TEST_MATCH},
+ {name: "Attribute presence selector, matching title attribute, case insensitivity", selector: "[TiTlE]", ctx: "#attr-presence", expect: ["attr-presence-a1", "attr-presence-span1"], exclude: ["xhtml"], level: 2, testType: TEST_FIND | TEST_MATCH},
+ {name: "Attribute presence selector, not matching title attribute, case sensitivity", selector: "[TiTlE]", ctx: "#attr-presence", expect: [], exclude: ["html"], level: 2, testType: TEST_FIND | TEST_MATCH},
+ {name: "Attribute presence selector, matching custom data-* attribute", selector: "[data-attr-presence]", ctx: "#attr-presence", expect: ["attr-presence-pre1", "attr-presence-blockquote1"], level: 2, testType: TEST_FIND | TEST_MATCH},
+ {name: "Attribute presence selector, not matching attribute with similar name", selector: ".attr-presence-div3[align], .attr-presence-div4[align]", ctx: "#attr-presence", expect: [] /*no matches*/, level: 2, testType: TEST_FIND},
+ {name: "Attribute presence selector, matching attribute with non-ASCII characters", selector: "ul[data-中文]", ctx: "#attr-presence", expect: ["attr-presence-ul1"], level: 2, testType: TEST_FIND | TEST_MATCH},
+ {name: "Attribute presence selector, not matching default option without selected attribute", selector: "#attr-presence-select1 option[selected]", ctx: "#attr-presence", expect: [] /* no matches */, level: 2, testType: TEST_FIND},
+ {name: "Attribute presence selector, matching option with selected attribute", selector: "#attr-presence-select2 option[selected]", ctx: "#attr-presence", expect: ["attr-presence-select2-option4"], level: 2, testType: TEST_FIND | TEST_MATCH},
+ {name: "Attribute presence selector, matching multiple options with selected attributes", selector: "#attr-presence-select3 option[selected]", ctx: "#attr-presence", expect: ["attr-presence-select3-option2", "attr-presence-select3-option3"], level: 2, testType: TEST_FIND | TEST_MATCH},
+
+ // - value [att=val]
+ {name: "Attribute value selector, matching align attribute with value", selector: "[align=\"center\"]", ctx: "#attr-value", expect: ["attr-value-div1"], level: 2, testType: TEST_FIND | TEST_MATCH},
+ {name: "Attribute value selector, matching align attribute with empty value", selector: "[align=\"\"]", ctx: "#attr-value", expect: ["attr-value-div2"], level: 2, testType: TEST_FIND | TEST_MATCH},
+ {name: "Attribute value selector, not matching align attribute with partial value", selector: "[align=\"c\"]", ctx: "#attr-value", expect: [] /*no matches*/, level: 2, testType: TEST_FIND},
+ {name: "Attribute value selector, not matching align attribute with incorrect value", selector: "[align=\"centera\"]", ctx: "#attr-value", expect: [] /*no matches*/, level: 2, testType: TEST_FIND},
+ {name: "Attribute value selector, matching custom data-* attribute with unicode escaped value", selector: "[data-attr-value=\"\\e9\"]", ctx: "#attr-value", expect: ["attr-value-div3"], level: 2, testType: TEST_FIND | TEST_MATCH},
+ {name: "Attribute value selector, matching custom data-* attribute with escaped character", selector: "[data-attr-value\_foo=\"\\e9\"]", ctx: "#attr-value", expect: ["attr-value-div4"], level: 2, testType: TEST_FIND | TEST_MATCH},
+ {name: "Attribute value selector with single-quoted value, matching multiple inputs with type attributes", selector: "input[type='hidden'],#attr-value input[type='radio']", ctx: "#attr-value", expect: ["attr-value-input3", "attr-value-input4", "attr-value-input6", "attr-value-input8", "attr-value-input9"], level: 2, testType: TEST_FIND | TEST_MATCH},
+ {name: "Attribute value selector with double-quoted value, matching multiple inputs with type attributes", selector: "input[type=\"hidden\"],#attr-value input[type='radio']", ctx: "#attr-value", expect: ["attr-value-input3", "attr-value-input4", "attr-value-input6", "attr-value-input8", "attr-value-input9"], level: 2, testType: TEST_FIND | TEST_MATCH},
+ {name: "Attribute value selector with unquoted value, matching multiple inputs with type attributes", selector: "input[type=hidden],#attr-value input[type=radio]", ctx: "#attr-value", expect: ["attr-value-input3", "attr-value-input4", "attr-value-input6", "attr-value-input8", "attr-value-input9"], level: 2, testType: TEST_FIND | TEST_MATCH},
+ {name: "Attribute value selector, matching attribute with value using non-ASCII characters", selector: "[data-attr-value=中文]", ctx: "#attr-value", expect: ["attr-value-div5"], level: 2, testType: TEST_FIND | TEST_MATCH},
+
+ // - whitespace-separated list [att~=val]
+ {name: "Attribute whitespace-separated list selector, matching class attribute with value", selector: "[class~=\"div1\"]", ctx: "#attr-whitespace", expect: ["attr-whitespace-div1"], level: 2, testType: TEST_FIND | TEST_MATCH},
+ {name: "Attribute whitespace-separated list selector, not matching class attribute with empty value", selector: "[class~=\"\"]", ctx: "#attr-whitespace", expect: [] /*no matches*/ , level: 2, testType: TEST_FIND},
+ {name: "Attribute whitespace-separated list selector, not matching class attribute with partial value", selector: "[data-attr-whitespace~=\"div\"]", ctx: "#attr-whitespace", expect: [] /*no matches*/ , level: 2, testType: TEST_FIND},
+ {name: "Attribute whitespace-separated list selector, matching custom data-* attribute with unicode escaped value", selector: "[data-attr-whitespace~=\"\\0000e9\"]", ctx: "#attr-whitespace", expect: ["attr-whitespace-div4"], level: 2, testType: TEST_FIND | TEST_MATCH},
+ {name: "Attribute whitespace-separated list selector, matching custom data-* attribute with escaped character", selector: "[data-attr-whitespace\_foo~=\"\\e9\"]", ctx: "#attr-whitespace", expect: ["attr-whitespace-div5"], level: 2, testType: TEST_FIND | TEST_MATCH},
+ {name: "Attribute whitespace-separated list selector with single-quoted value, matching multiple links with rel attributes", selector: "a[rel~='bookmark'], #attr-whitespace a[rel~='nofollow']", ctx: "#attr-whitespace", expect: ["attr-whitespace-a1", "attr-whitespace-a2", "attr-whitespace-a3", "attr-whitespace-a5", "attr-whitespace-a7"], level: 2, testType: TEST_FIND | TEST_MATCH},
+ {name: "Attribute whitespace-separated list selector with double-quoted value, matching multiple links with rel attributes", selector: "a[rel~=\"bookmark\"],#attr-whitespace a[rel~='nofollow']", ctx: "#attr-whitespace", expect: ["attr-whitespace-a1", "attr-whitespace-a2", "attr-whitespace-a3", "attr-whitespace-a5", "attr-whitespace-a7"], level: 2, testType: TEST_FIND | TEST_MATCH},
+ {name: "Attribute whitespace-separated list selector with unquoted value, matching multiple links with rel attributes", selector: "a[rel~=bookmark], #attr-whitespace a[rel~=nofollow]", ctx: "#attr-whitespace", expect: ["attr-whitespace-a1", "attr-whitespace-a2", "attr-whitespace-a3", "attr-whitespace-a5", "attr-whitespace-a7"], level: 2, testType: TEST_FIND | TEST_MATCH},
+ {name: "Attribute whitespace-separated list selector with double-quoted value, not matching value with space", selector: "a[rel~=\"book mark\"]", ctx: "#attr-whitespace", expect: [] /* no matches */, level: 2, testType: TEST_FIND},
+ {name: "Attribute whitespace-separated list selector, matching title attribute with value using non-ASCII characters", selector: "[title~=中文]", ctx: "#attr-whitespace", expect: ["attr-whitespace-p1"], level: 2, testType: TEST_FIND | TEST_MATCH},
+
+ // - hyphen-separated list [att|=val]
+ {name: "Attribute hyphen-separated list selector, not matching unspecified lang attribute", selector: "#attr-hyphen-div1[lang|=\"en\"]", ctx: "#attr-hyphen", expect: [] /*no matches*/, level: 2, testType: TEST_FIND},
+ {name: "Attribute hyphen-separated list selector, matching lang attribute with exact value", selector: "#attr-hyphen-div2[lang|=\"fr\"]", ctx: "#attr-hyphen", expect: ["attr-hyphen-div2"], level: 2, testType: TEST_FIND | TEST_MATCH},
+ {name: "Attribute hyphen-separated list selector, matching lang attribute with partial value", selector: "#attr-hyphen-div3[lang|=\"en\"]", ctx: "#attr-hyphen", expect: ["attr-hyphen-div3"], level: 2, testType: TEST_FIND | TEST_MATCH},
+ {name: "Attribute hyphen-separated list selector, not matching incorrect value", selector: "#attr-hyphen-div4[lang|=\"es-AR\"]", ctx: "#attr-hyphen", expect: [] /*no matches*/, level: 2, testType: TEST_FIND},
+
+ // - substring begins-with [att^=val] (Level 3)
+ {name: "Attribute begins with selector, matching href attributes beginning with specified substring", selector: "a[href^=\"http://www\"]", ctx: "#attr-begins", expect: ["attr-begins-a1", "attr-begins-a3"], level: 3, testType: TEST_FIND | TEST_MATCH},
+ {name: "Attribute begins with selector, matching lang attributes beginning with specified substring, ", selector: "[lang^=\"en-\"]", ctx: "#attr-begins", expect: ["attr-begins-div2", "attr-begins-div4"], level: 3, testType: TEST_FIND | TEST_MATCH},
+ {name: "Attribute begins with selector, not matching class attribute not beginning with specified substring", selector: "[class^=apple]", ctx: "#attr-begins", expect: [] /*no matches*/, level: 3, testType: TEST_FIND},
+ {name: "Attribute begins with selector with single-quoted value, matching class attribute beginning with specified substring", selector: "[class^=' apple']", ctx: "#attr-begins", expect: ["attr-begins-p1"], level: 3, testType: TEST_FIND | TEST_MATCH},
+ {name: "Attribute begins with selector with double-quoted value, matching class attribute beginning with specified substring", selector: "[class^=\" apple\"]", ctx: "#attr-begins", expect: ["attr-begins-p1"], level: 3, testType: TEST_FIND | TEST_MATCH},
+ {name: "Attribute begins with selector with unquoted value, not matching class attribute not beginning with specified substring", selector: "[class^= apple]", ctx: "#attr-begins", expect: [] /*no matches*/, level: 3, testType: TEST_FIND},
+
+ // - substring ends-with [att$=val] (Level 3)
+ {name: "Attribute ends with selector, matching href attributes ending with specified substring", selector: "a[href$=\".org\"]", ctx: "#attr-ends", expect: ["attr-ends-a1", "attr-ends-a3"], level: 3, testType: TEST_FIND | TEST_MATCH},
+ {name: "Attribute ends with selector, matching lang attributes ending with specified substring, ", selector: "[lang$=\"-CH\"]", ctx: "#attr-ends", expect: ["attr-ends-div2", "attr-ends-div4"], level: 3, testType: TEST_FIND | TEST_MATCH},
+ {name: "Attribute ends with selector, not matching class attribute not ending with specified substring", selector: "[class$=apple]", ctx: "#attr-ends", expect: [] /*no matches*/, level: 3, testType: TEST_FIND},
+ {name: "Attribute ends with selector with single-quoted value, matching class attribute ending with specified substring", selector: "[class$='apple ']", ctx: "#attr-ends", expect: ["attr-ends-p1"], level: 3, testType: TEST_FIND | TEST_MATCH},
+ {name: "Attribute ends with selector with double-quoted value, matching class attribute ending with specified substring", selector: "[class$=\"apple \"]", ctx: "#attr-ends", expect: ["attr-ends-p1"], level: 3, testType: TEST_FIND | TEST_MATCH},
+ {name: "Attribute ends with selector with unquoted value, not matching class attribute not ending with specified substring", selector: "[class$=apple ]", ctx: "#attr-ends", expect: [] /*no matches*/, level: 3, testType: TEST_FIND},
+
+ // - substring contains [att*=val] (Level 3)
+ {name: "Attribute contains selector, matching href attributes beginning with specified substring", selector: "a[href*=\"http://www\"]", ctx: "#attr-contains", expect: ["attr-contains-a1", "attr-contains-a3"], level: 3, testType: TEST_FIND | TEST_MATCH},
+ {name: "Attribute contains selector, matching href attributes ending with specified substring", selector: "a[href*=\".org\"]", ctx: "#attr-contains", expect: ["attr-contains-a1", "attr-contains-a2"], level: 3, testType: TEST_FIND | TEST_MATCH},
+ {name: "Attribute contains selector, matching href attributes containing specified substring", selector: "a[href*=\".example.\"]", ctx: "#attr-contains", expect: ["attr-contains-a1", "attr-contains-a3"], level: 3, testType: TEST_FIND | TEST_MATCH},
+ {name: "Attribute contains selector, matching lang attributes beginning with specified substring, ", selector: "[lang*=\"en-\"]", ctx: "#attr-contains", expect: ["attr-contains-div2", "attr-contains-div6"], level: 3, testType: TEST_FIND | TEST_MATCH},
+ {name: "Attribute contains selector, matching lang attributes ending with specified substring, ", selector: "[lang*=\"-CH\"]", ctx: "#attr-contains", expect: ["attr-contains-div3", "attr-contains-div5"], level: 3, testType: TEST_FIND | TEST_MATCH},
+ {name: "Attribute contains selector with single-quoted value, matching class attribute beginning with specified substring", selector: "[class*=' apple']", ctx: "#attr-contains", expect: ["attr-contains-p1"], level: 3, testType: TEST_FIND | TEST_MATCH},
+ {name: "Attribute contains selector with single-quoted value, matching class attribute ending with specified substring", selector: "[class*='orange ']", ctx: "#attr-contains", expect: ["attr-contains-p1"], level: 3, testType: TEST_FIND | TEST_MATCH},
+ {name: "Attribute contains selector with single-quoted value, matching class attribute containing specified substring", selector: "[class*='ple banana ora']", ctx: "#attr-contains", expect: ["attr-contains-p1"], level: 3, testType: TEST_FIND | TEST_MATCH},
+ {name: "Attribute contains selector with double-quoted value, matching class attribute beginning with specified substring", selector: "[class*=\" apple\"]", ctx: "#attr-contains", expect: ["attr-contains-p1"], level: 3, testType: TEST_FIND | TEST_MATCH},
+ {name: "Attribute contains selector with double-quoted value, matching class attribute ending with specified substring", selector: "[class*=\"orange \"]", ctx: "#attr-contains", expect: ["attr-contains-p1"], level: 3, testType: TEST_FIND | TEST_MATCH},
+ {name: "Attribute contains selector with double-quoted value, matching class attribute containing specified substring", selector: "[class*=\"ple banana ora\"]", ctx: "#attr-contains", expect: ["attr-contains-p1"], level: 3, testType: TEST_FIND | TEST_MATCH},
+ {name: "Attribute contains selector with unquoted value, matching class attribute beginning with specified substring", selector: "[class*= apple]", ctx: "#attr-contains", expect: ["attr-contains-p1"], level: 3, testType: TEST_FIND | TEST_MATCH},
+ {name: "Attribute contains selector with unquoted value, matching class attribute ending with specified substring", selector: "[class*=orange ]", ctx: "#attr-contains", expect: ["attr-contains-p1"], level: 3, testType: TEST_FIND | TEST_MATCH},
+ {name: "Attribute contains selector with unquoted value, matching class attribute containing specified substring", selector: "[class*= banana ]", ctx: "#attr-contains", expect: ["attr-contains-p1"], level: 3, testType: TEST_FIND | TEST_MATCH},
+
+ // Pseudo-classes
+ // - :root (Level 3)
+ {name: ":root pseudo-class selector, matching document root element", selector: ":root", expect: ["html"], exclude: ["element", "fragment", "detached"], level: 3, testType: TEST_FIND},
+ {name: ":root pseudo-class selector, not matching document root element", selector: ":root", expect: [] /*no matches*/, exclude: ["document"], level: 3, testType: TEST_FIND},
+ {name: ":root pseudo-class selector, not matching document root element", selector: ":root", ctx: "#html", expect: [] /*no matches*/, exclude: ["fragment", "detached"], level: 3, testType: TEST_FIND},
+
+ // - :nth-child(n) (Level 3)
+ {name: ":nth-child selector, matching the third child element", selector: ":nth-child(3)", ctx: "#pseudo-nth-table1", expect: ["pseudo-nth-td3", "pseudo-nth-td9", "pseudo-nth-tr3", "pseudo-nth-td15"], level: 3, testType: TEST_FIND | TEST_MATCH},
+ {name: ":nth-child selector, matching every third child element", selector: "li:nth-child(3n)", ctx: "#pseudo-nth", expect: ["pseudo-nth-li3", "pseudo-nth-li6", "pseudo-nth-li9", "pseudo-nth-li12"], level: 3, testType: TEST_FIND | TEST_MATCH},
+ {name: ":nth-child selector, matching every second child element, starting from the fourth", selector: "li:nth-child(2n+4)", ctx: "#pseudo-nth", expect: ["pseudo-nth-li4", "pseudo-nth-li6", "pseudo-nth-li8", "pseudo-nth-li10", "pseudo-nth-li12"], level: 3, testType: TEST_FIND | TEST_MATCH},
+ {name: ":nth-child selector, matching every fourth child element, starting from the third", selector: ":nth-child(4n-1)", ctx: "#pseudo-nth-p1", expect: ["pseudo-nth-em2", "pseudo-nth-span3"], level: 3, testType: TEST_FIND | TEST_MATCH},
+
+ // - :nth-last-child (Level 3)
+ {name: ":nth-last-child selector, matching the third last child element", selector: ":nth-last-child(3)", ctx: "#pseudo-nth-table1", expect: ["pseudo-nth-tr1", "pseudo-nth-td4", "pseudo-nth-td10", "pseudo-nth-td16"], level: 3, testType: TEST_FIND | TEST_MATCH},
+ {name: ":nth-last-child selector, matching every third child element from the end", selector: "li:nth-last-child(3n)", ctx: "pseudo-nth", expect: ["pseudo-nth-li1", "pseudo-nth-li4", "pseudo-nth-li7", "pseudo-nth-li10"], level: 3, testType: TEST_FIND | TEST_MATCH},
+ {name: ":nth-last-child selector, matching every second child element from the end, starting from the fourth last", selector: "li:nth-last-child(2n+4)", ctx: "pseudo-nth", expect: ["pseudo-nth-li1", "pseudo-nth-li3", "pseudo-nth-li5", "pseudo-nth-li7", "pseudo-nth-li9"], level: 3, testType: TEST_FIND | TEST_MATCH},
+ {name: ":nth-last-child selector, matching every fourth element from the end, starting from the third last", selector: ":nth-last-child(4n-1)", ctx: "#pseudo-nth-p1", expect: ["pseudo-nth-span2", "pseudo-nth-span4"], level: 3, testType: TEST_FIND | TEST_MATCH},
+
+ // - :nth-of-type(n) (Level 3)
+ {name: ":nth-of-type selector, matching the third em element", selector: "em:nth-of-type(3)", ctx: "#pseudo-nth-p1", expect: ["pseudo-nth-em3"], level: 3, testType: TEST_FIND | TEST_MATCH},
+ {name: ":nth-of-type selector, matching every second element of their type", selector: ":nth-of-type(2n)", ctx: "#pseudo-nth-p1", expect: ["pseudo-nth-em2", "pseudo-nth-span2", "pseudo-nth-span4", "pseudo-nth-strong2", "pseudo-nth-em4"], level: 3, testType: TEST_FIND | TEST_MATCH},
+ {name: ":nth-of-type selector, matching every second elemetn of their type, starting from the first", selector: "span:nth-of-type(2n-1)", ctx: "#pseudo-nth-p1", expect: ["pseudo-nth-span1", "pseudo-nth-span3"], level: 3, testType: TEST_FIND | TEST_MATCH},
+
+ // - :nth-last-of-type(n) (Level 3)
+ {name: ":nth-last-of-type selector, matching the thrid last em element", selector: "em:nth-last-of-type(3)", ctx: "#pseudo-nth-p1", expect: ["pseudo-nth-em2"], level: 3, testType: TEST_FIND | TEST_MATCH},
+ {name: ":nth-last-of-type selector, matching every second last element of their type", selector: ":nth-last-of-type(2n)", ctx: "#pseudo-nth-p1", expect: ["pseudo-nth-span1", "pseudo-nth-em1", "pseudo-nth-strong1", "pseudo-nth-em3", "pseudo-nth-span3"], level: 3, testType: TEST_FIND | TEST_MATCH},
+ {name: ":nth-last-of-type selector, matching every second last element of their type, starting from the last", selector: "span:nth-last-of-type(2n-1)", ctx: "#pseudo-nth-p1", expect: ["pseudo-nth-span2", "pseudo-nth-span4"], level: 3, testType: TEST_FIND | TEST_MATCH},
+
+ // - :first-of-type (Level 3)
+ {name: ":first-of-type selector, matching the first em element", selector: "em:first-of-type", ctx: "#pseudo-nth-p1", expect: ["pseudo-nth-em1"], level: 3, testType: TEST_FIND | TEST_MATCH},
+ {name: ":first-of-type selector, matching the first of every type of element", selector: ":first-of-type", ctx: "#pseudo-nth-p1", expect: ["pseudo-nth-span1", "pseudo-nth-em1", "pseudo-nth-strong1"], level: 3, testType: TEST_FIND | TEST_MATCH},
+ {name: ":first-of-type selector, matching the first td element in each table row", selector: "tr :first-of-type", ctx: "#pseudo-nth-table1", expect: ["pseudo-nth-td1", "pseudo-nth-td7", "pseudo-nth-td13"], level: 3, testType: TEST_FIND | TEST_MATCH},
+
+ // - :last-of-type (Level 3)
+ {name: ":last-of-type selector, matching the last em elemnet", selector: "em:last-of-type", ctx: "#pseudo-nth-p1", expect: ["pseudo-nth-em4"], level: 3, testType: TEST_FIND | TEST_MATCH},
+ {name: ":last-of-type selector, matching the last of every type of element", selector: ":last-of-type", ctx: "#pseudo-nth-p1", expect: ["pseudo-nth-span4", "pseudo-nth-strong2", "pseudo-nth-em4"], level: 3, testType: TEST_FIND | TEST_MATCH},
+ {name: ":last-of-type selector, matching the last td element in each table row", selector: "tr :last-of-type", ctx: "#pseudo-nth-table1", expect: ["pseudo-nth-td6", "pseudo-nth-td12", "pseudo-nth-td18"], level: 3, testType: TEST_FIND | TEST_MATCH},
+
+ // - :first-child
+ {name: ":first-child pseudo-class selector, matching first child div element", selector: "div:first-child", ctx: "#pseudo-first-child", expect: ["pseudo-first-child-div1"], level: 2, testType: TEST_FIND | TEST_MATCH},
+ {name: ":first-child pseudo-class selector, doesn't match non-first-child elements", selector: ".pseudo-first-child-div2:first-child, .pseudo-first-child-div3:first-child", ctx: "#pseudo-first-child", expect: [] /*no matches*/, level: 2, testType: TEST_FIND},
+ {name: ":first-child pseudo-class selector, matching first-child of multiple elements", selector: "span:first-child", ctx: "#pseudo-first-child", expect: ["pseudo-first-child-span1", "pseudo-first-child-span3", "pseudo-first-child-span5"], level: 2, testType: TEST_FIND | TEST_MATCH},
+
+ // - :last-child (Level 3)
+ {name: ":last-child pseudo-class selector, matching last child div element", selector: "div:last-child", ctx: "#pseudo-last-child", expect: ["pseudo-last-child-div3"], level: 3, testType: TEST_FIND | TEST_MATCH},
+ {name: ":last-child pseudo-class selector, doesn't match non-last-child elements", selector: ".pseudo-last-child-div1:last-child, .pseudo-last-child-div2:first-child", ctx: "#pseudo-last-child", expect: [] /*no matches*/, level: 3, testType: TEST_FIND},
+ {name: ":last-child pseudo-class selector, matching first-child of multiple elements", selector: "span:last-child", ctx: "#pseudo-last-child", expect: ["pseudo-last-child-span2", "pseudo-last-child-span4", "pseudo-last-child-span6"], level: 3, testType: TEST_FIND | TEST_MATCH},
+
+ // - :only-child (Level 3)
+ {name: ":pseudo-only-child pseudo-class selector, matching all only-child elements", selector: ":only-child", ctx: "#pseudo-only", expect: ["pseudo-only-span1"], level: 3, testType: TEST_FIND | TEST_MATCH},
+ {name: ":pseudo-only-child pseudo-class selector, matching only-child em elements", selector: "em:only-child", ctx: "#pseudo-only", expect: [] /*no matches*/, level: 3, testType: TEST_FIND},
+
+ // - :only-of-type (Level 3)
+ {name: ":pseudo-only-of-type pseudo-class selector, matching all elements with no siblings of the same type", selector: " :only-of-type", ctx: "#pseudo-only", expect: ["pseudo-only-span1", "pseudo-only-em1"], level: 3, testType: TEST_FIND | TEST_MATCH},
+ {name: ":pseudo-only-of-type pseudo-class selector, matching em elements with no siblings of the same type", selector: " em:only-of-type", ctx: "#pseudo-only", expect: ["pseudo-only-em1"], level: 3, testType: TEST_FIND | TEST_MATCH},
+
+ // - :empty (Level 3)
+ {name: ":empty pseudo-class selector, matching empty p elements", selector: "p:empty", ctx: "#pseudo-empty", expect: ["pseudo-empty-p1", "pseudo-empty-p2"], level: 3, testType: TEST_FIND | TEST_MATCH},
+ {name: ":empty pseudo-class selector, matching all empty elements", selector: ":empty", ctx: "#pseudo-empty", expect: ["pseudo-empty-p1", "pseudo-empty-p2", "pseudo-empty-span1"], level: 3, testType: TEST_FIND | TEST_MATCH},
+
+ // - :link and :visited
+ // Implementations may treat all visited links as unvisited, so these cannot be tested separately.
+ // The only guarantee is that ":link,:visited" matches the set of all visited and unvisited links and that they are individually mutually exclusive sets.
+ {name: ":link and :visited pseudo-class selectors, matching a and area elements with href attributes", selector: " :link, #pseudo-link :visited", ctx: "#pseudo-link", expect: ["pseudo-link-a1", "pseudo-link-a2", "pseudo-link-area1"], level: 1, testType: TEST_FIND | TEST_MATCH},
+ {name: ":link and :visited pseudo-class selectors, matching link elements with href attributes", selector: " :link, #head :visited", ctx: "#head", expect: ["pseudo-link-link1", "pseudo-link-link2"], exclude: ["element", "fragment", "detached"], level: 1, testType: TEST_FIND | TEST_MATCH},
+ {name: ":link and :visited pseudo-class selectors, not matching link elements with href attributes", selector: " :link, #head :visited", ctx: "#head", expect: [] /*no matches*/, exclude: ["document"], level: 1, testType: TEST_FIND},
+ {name: ":link and :visited pseudo-class selectors, chained, mutually exclusive pseudo-classes match nothing", selector: ":link:visited", ctx: "#html", expect: [] /*no matches*/, exclude: ["document"], level: 1, testType: TEST_FIND},
+
+// XXX Figure out context or refNodes for this
+ // - :target (Level 3)
+ {name: ":target pseudo-class selector, matching the element referenced by the URL fragment identifier", selector: ":target", ctx: "", expect: [] /*no matches*/, exclude: ["document", "element"], level: 3, testType: TEST_FIND},
+ {name: ":target pseudo-class selector, matching the element referenced by the URL fragment identifier", selector: ":target", ctx: "", expect: ["target"], exclude: ["fragment", "detached"], level: 3, testType: TEST_FIND},
+
+// XXX Fix ctx in tests below
+
+ // - :lang()
+ {name: ":lang pseudo-class selector, matching inherited language (1)", selector: "#pseudo-lang-div1:lang(en)", ctx: "", expect: ["pseudo-lang-div1"], exclude: ["detached", "fragment"], level: 2, testType: TEST_FIND | TEST_MATCH},
+ {name: ":lang pseudo-class selector, not matching element with no inherited language", selector: "#pseudo-lang-div1:lang(en)", ctx: "", expect: [] /*no matches*/, exclude: ["document", "element"], level: 2, testType: TEST_FIND},
+ {name: ":lang pseudo-class selector, matching specified language with exact value (1)", selector: "#pseudo-lang-div2:lang(fr)", ctx: "", expect: ["pseudo-lang-div2"], level: 2, testType: TEST_FIND | TEST_MATCH},
+ {name: ":lang pseudo-class selector, matching specified language with partial value (1)", selector: "#pseudo-lang-div3:lang(en)", ctx: "", expect: ["pseudo-lang-div3"], level: 2, testType: TEST_FIND | TEST_MATCH},
+ {name: ":lang pseudo-class selector, not matching incorrect language", selector: "#pseudo-lang-div4:lang(es-AR)", ctx: "", expect: [] /*no matches*/, level: 2, testType: TEST_FIND},
+
+ // - :enabled (Level 3)
+ {name: ":enabled pseudo-class selector, matching all enabled form controls (1)", selector: "#pseudo-ui :enabled", ctx: "", expect: ["pseudo-ui-input1", "pseudo-ui-input2", "pseudo-ui-input3", "pseudo-ui-input4", "pseudo-ui-input5", "pseudo-ui-input6",
+ "pseudo-ui-input7", "pseudo-ui-input8", "pseudo-ui-input9", "pseudo-ui-textarea1", "pseudo-ui-button1"], level: 3, testType: TEST_FIND | TEST_MATCH},
+
+ // - :disabled (Level 3)
+ {name: ":enabled pseudo-class selector, matching all disabled form controls (1)", selector: "#pseudo-ui :disabled", ctx: "", expect: ["pseudo-ui-input10", "pseudo-ui-input11", "pseudo-ui-input12", "pseudo-ui-input13", "pseudo-ui-input14", "pseudo-ui-input15",
+ "pseudo-ui-input16", "pseudo-ui-input17", "pseudo-ui-input18", "pseudo-ui-textarea2", "pseudo-ui-button2"], level: 3, testType: TEST_FIND | TEST_MATCH},
+
+ // - :checked (Level 3)
+ {name: ":checked pseudo-class selector, matching checked radio buttons and checkboxes (1)", selector: "#pseudo-ui :checked", ctx: "", expect: ["pseudo-ui-input4", "pseudo-ui-input6", "pseudo-ui-input13", "pseudo-ui-input15"], level: 3, testType: TEST_FIND | TEST_MATCH},
+
+ // - :not(s) (Level 3)
+ {name: ":not pseudo-class selector, matching (1)", selector: "#not>:not(div)", ctx: "", expect: ["not-p1", "not-p2", "not-p3"], level: 3, testType: TEST_FIND | TEST_MATCH},
+ {name: ":not pseudo-class selector, matching (1)", selector: "#not * :not(:first-child)", ctx: "", expect: ["not-em1", "not-em2", "not-em3"], level: 3, testType: TEST_FIND | TEST_MATCH},
+ {name: ":not pseudo-class selector, matching nothing", selector: ":not(*)", ctx: "", expect: [] /* no matches */, level: 3, testType: TEST_FIND},
+ {name: ":not pseudo-class selector, matching nothing", selector: ":not(*|*)", ctx: "", expect: [] /* no matches */, level: 3, testType: TEST_FIND},
+
+ // Pseudo-elements
+ // - ::first-line
+ {name: ":first-line pseudo-element (one-colon syntax) selector, not matching any elements", selector: "#pseudo-element:first-line", ctx: "", expect: [] /*no matches*/, level: 2, testType: TEST_FIND},
+ {name: "::first-line pseudo-element (two-colon syntax) selector, not matching any elements", selector: "#pseudo-element::first-line", ctx: "", expect: [] /*no matches*/, level: 3, testType: TEST_FIND},
+
+ // - ::first-letter
+ {name: ":first-letter pseudo-element (one-colon syntax) selector, not matching any elements", selector: "#pseudo-element:first-letter", ctx: "", expect: [] /*no matches*/, level: 2, testType: TEST_FIND},
+ {name: "::first-letter pseudo-element (two-colon syntax) selector, not matching any elements", selector: "#pseudo-element::first-letter", ctx: "", expect: [] /*no matches*/, level: 3, testType: TEST_FIND},
+
+ // - ::before
+ {name: ":before pseudo-element (one-colon syntax) selector, not matching any elements", selector: "#pseudo-element:before", ctx: "", expect: [] /*no matches*/, level: 2, testType: TEST_FIND},
+ {name: "::before pseudo-element (two-colon syntax) selector, not matching any elements", selector: "#pseudo-element::before", ctx: "", expect: [] /*no matches*/, level: 3, testType: TEST_FIND},
+
+ // - ::after
+ {name: ":after pseudo-element (one-colon syntax) selector, not matching any elements", selector: "#pseudo-element:after", ctx: "", expect: [] /*no matches*/, level: 2, testType: TEST_FIND},
+ {name: "::after pseudo-element (two-colon syntax) selector, not matching any elements", selector: "#pseudo-element::after", ctx: "", expect: [] /*no matches*/, level: 3, testType: TEST_FIND},
+
+ // Class Selectors
+ {name: "Class selector, matching element with specified class (1)", selector: ".class-p", ctx: "", expect: ["class-p1","class-p2", "class-p3"], level: 1, testType: TEST_FIND | TEST_MATCH},
+ {name: "Class selector, chained, matching only elements with all specified classes (1)", selector: "#class .apple.orange.banana", ctx: "", expect: ["class-div1", "class-div2", "class-p4", "class-div3", "class-p6", "class-div4"], level: 1, testType: TEST_FIND | TEST_MATCH},
+ {name: "Class Selector, chained, with type selector (1)", selector: "div.apple.banana.orange", ctx: "", expect: ["class-div1", "class-div2", "class-div3", "class-div4"], level: 1, testType: TEST_FIND | TEST_MATCH},
+ // Caution: If copying and pasting the folowing non-ASCII classes, ensure unicode normalisation is not performed in the process.
+ {name: "Class selector, matching element with class value using non-ASCII characters", selector: ".台北Táiběi", ctx: "", expect: ["class-span1"], level: 1, testType: TEST_FIND | TEST_MATCH},
+ {name: "Class selector, matching multiple elements with class value using non-ASCII characters (1)", selector: ".台北", ctx: "", expect: ["class-span1","class-span2"], level: 1, testType: TEST_FIND | TEST_MATCH},
+ {name: "Class selector, chained, matching element with multiple class values using non-ASCII characters", selector: ".台北Táiběi.台北", ctx: "", expect: ["class-span1"], level: 1, testType: TEST_FIND | TEST_MATCH},
+ {name: "Class selector, matching element with class with escaped character (1)", selector: ".foo\\:bar", ctx: "", expect: ["class-span3"], level: 1, testType: TEST_FIND | TEST_MATCH},
+ {name: "Class selector, matching element with class with escaped character (1)", selector: ".test\\.foo\\[5\\]bar", ctx: "", expect: ["class-span4"], level: 1, testType: TEST_FIND | TEST_MATCH},
+
+ // ID Selectors
+ {name: "ID selector, matching element with specified id (1)", selector: "#id #id-div1", ctx: "", expect: ["id-div1"], level: 1, testType: TEST_FIND | TEST_MATCH},
+ {name: "ID selector, chained, matching element with specified id (1)", selector: "#id-div1, #id-div1", ctx: "", expect: ["id-div1"], level: 1, testType: TEST_FIND | TEST_MATCH},
+ {name: "ID selector, chained, matching element with specified id (1)", selector: "#id-div1, #id-div2", ctx: "", expect: ["id-div1", "id-div2"], level: 1, testType: TEST_FIND | TEST_MATCH},
+ {name: "ID Selector, chained, with type selector (1)", selector: "div#id-div1, div#id-div2", ctx: "", expect: ["id-div1", "id-div2"], level: 1, testType: TEST_FIND | TEST_MATCH},
+ {name: "ID selector, not matching non-existent descendant", selector: "#id #none", ctx: "", expect: [] /*no matches*/, level: 1, testType: TEST_FIND},
+ {name: "ID selector, not matching non-existent ancestor", selector: "#none #id-div1", ctx: "", expect: [] /*no matches*/, level: 1, testType: TEST_FIND},
+ {name: "ID selector, matching multiple elements with duplicate id (1)", selector: "#id-li-duplicate", ctx: "", expect: ["id-li-duplicate", "id-li-duplicate", "id-li-duplicate", "id-li-duplicate"], level: 1, testType: TEST_FIND | TEST_MATCH},
+
+ // Caution: If copying and pasting the folowing non-ASCII IDs, ensure unicode normalisation is not performed in the process.
+ {name: "ID selector, matching id value using non-ASCII characters", selector: "#台北Táiběi", ctx: "", expect: ["台北Táiběi"], level: 1, testType: TEST_FIND | TEST_MATCH},
+ {name: "ID selector, matching id value using non-ASCII characters (1)", selector: "#台北", ctx: "", expect: ["台北"], level: 1, testType: TEST_FIND | TEST_MATCH},
+ {name: "ID selector, matching id values using non-ASCII characters", selector: "#台北Táiběi, #台北", ctx: "", expect: ["台北Táiběi", "台北"], level: 1, testType: TEST_FIND | TEST_MATCH},
+
+ // XXX runMatchesTest() in level2-lib.js can't handle this because obtaining the expected nodes requires escaping characters when generating the selector from 'expect' values
+ {name: "ID selector, matching element with id with escaped character", selector: "#\\#foo\\:bar", ctx: "", expect: ["#foo:bar"], level: 1, testType: TEST_FIND},
+ {name: "ID selector, matching element with id with escaped character", selector: "#test\\.foo\\[5\\]bar", ctx: "", expect: ["test.foo[5]bar"], level: 1, testType: TEST_FIND},
+
+ // Namespaces
+ // XXX runMatchesTest() in level2-lib.js can't handle these because non-HTML elements don't have a recognised id
+ {name: "Namespace selector, matching element with any namespace", selector: "#any-namespace *|div", ctx: "", expect: ["any-namespace-div1", "any-namespace-div2", "any-namespace-div3", "any-namespace-div4"], level: 3, testType: TEST_FIND},
+ {name: "Namespace selector, matching div elements in no namespace only", selector: "#no-namespace |div", ctx: "", expect: ["no-namespace-div3"], level: 3, testType: TEST_FIND},
+ {name: "Namespace selector, matching any elements in no namespace only", selector: "#no-namespace |*", ctx: "", expect: ["no-namespace-div3"], level: 3, testType: TEST_FIND},
+
+ // Combinators
+ // - Descendant combinator ' '
+ {name: "Descendant combinator, matching element that is a descendant of an element with id (1)", selector: "#descendant div", ctx: "", expect: ["descendant-div1", "descendant-div2", "descendant-div3", "descendant-div4"], level: 1, testType: TEST_FIND | TEST_MATCH},
+ {name: "Descendant combinator, matching element with id that is a descendant of an element (1)", selector: "body #descendant-div1", ctx: "", expect: ["descendant-div1"], exclude: ["detached", "fragment"], level: 1, testType: TEST_FIND | TEST_MATCH},
+ {name: "Descendant combinator, matching element with id that is a descendant of an element (1)", selector: "div #descendant-div1", ctx: "", expect: ["descendant-div1"], level: 1, testType: TEST_FIND | TEST_MATCH},
+ {name: "Descendant combinator, matching element with id that is a descendant of an element with id (1)", selector: "#descendant #descendant-div2", ctx: "", expect: ["descendant-div2"], level: 1, testType: TEST_FIND | TEST_MATCH},
+ {name: "Descendant combinator, matching element with class that is a descendant of an element with id (1)", selector: "#descendant .descendant-div2", ctx: "", expect: ["descendant-div2"], level: 1, testType: TEST_FIND | TEST_MATCH},
+ {name: "Descendant combinator, matching element with class that is a descendant of an element with class (1)", selector: ".descendant-div1 .descendant-div3", ctx: "", expect: ["descendant-div3"], level: 1, testType: TEST_FIND | TEST_MATCH},
+ {name: "Descendant combinator, not matching element with id that is not a descendant of an element with id", selector: "#descendant-div1 #descendant-div4", ctx: "", expect: [] /*no matches*/, level: 1, testType: TEST_FIND},
+ {name: "Descendant combinator, whitespace characters (1)", selector: "#descendant\t\r\n#descendant-div2", ctx: "", expect: ["descendant-div2"], level: 1, testType: TEST_FIND | TEST_MATCH},
+
+ // - Child combinator '>'
+ {name: "Child combinator, matching element that is a child of an element with id (1)", selector: "#child>div", ctx: "", expect: ["child-div1", "child-div4"], level: 2, testType: TEST_FIND | TEST_MATCH},
+ {name: "Child combinator, matching element with id that is a child of an element (1)", selector: "div>#child-div1", ctx: "", expect: ["child-div1"], level: 2, testType: TEST_FIND | TEST_MATCH},
+ {name: "Child combinator, matching element with id that is a child of an element with id (1)", selector: "#child>#child-div1", ctx: "", expect: ["child-div1"], level: 2, testType: TEST_FIND | TEST_MATCH},
+ {name: "Child combinator, matching element with id that is a child of an element with class (1)", selector: "#child-div1>.child-div2", ctx: "", expect: ["child-div2"], level: 2, testType: TEST_FIND | TEST_MATCH},
+ {name: "Child combinator, matching element with class that is a child of an element with class (1)", selector: ".child-div1>.child-div2", ctx: "", expect: ["child-div2"], level: 2, testType: TEST_FIND | TEST_MATCH},
+ {name: "Child combinator, not matching element with id that is not a child of an element with id", selector: "#child>#child-div3", ctx: "", expect: [] /*no matches*/, level: 2, testType: TEST_FIND},
+ {name: "Child combinator, not matching element with id that is not a child of an element with class", selector: "#child-div1>.child-div3", ctx: "", expect: [] /*no matches*/, level: 2, testType: TEST_FIND},
+ {name: "Child combinator, not matching element with class that is not a child of an element with class", selector: ".child-div1>.child-div3", ctx: "", expect: [] /*no matches*/, level: 2, testType: TEST_FIND},
+ {name: "Child combinator, surrounded by whitespace (1)", selector: "#child-div1\t\r\n>\t\r\n#child-div2", ctx: "", expect: ["child-div2"], level: 2, testType: TEST_FIND | TEST_MATCH},
+ {name: "Child combinator, whitespace after (1)", selector: "#child-div1>\t\r\n#child-div2", ctx: "", expect: ["child-div2"], level: 2, testType: TEST_FIND | TEST_MATCH},
+ {name: "Child combinator, whitespace before (1)", selector: "#child-div1\t\r\n>#child-div2", ctx: "", expect: ["child-div2"], level: 2, testType: TEST_FIND | TEST_MATCH},
+ {name: "Child combinator, no whitespace (1)", selector: "#child-div1>#child-div2", ctx: "", expect: ["child-div2"], level: 2, testType: TEST_FIND | TEST_MATCH},
+
+ // - Adjacent sibling combinator '+'
+ {name: "Adjacent sibling combinator, matching element that is an adjacent sibling of an element with id (1)", selector: "#adjacent-div2+div", ctx: "", expect: ["adjacent-div4"], level: 2, testType: TEST_FIND | TEST_MATCH},
+ {name: "Adjacent sibling combinator, matching element with id that is an adjacent sibling of an element (1)", selector: "div+#adjacent-div4", ctx: "", expect: ["adjacent-div4"], level: 2, testType: TEST_FIND | TEST_MATCH},
+ {name: "Adjacent sibling combinator, matching element with id that is an adjacent sibling of an element with id (1)", selector: "#adjacent-div2+#adjacent-div4", ctx: "", expect: ["adjacent-div4"], level: 2, testType: TEST_FIND | TEST_MATCH},
+ {name: "Adjacent sibling combinator, matching element with class that is an adjacent sibling of an element with id (1)", selector: "#adjacent-div2+.adjacent-div4", ctx: "", expect: ["adjacent-div4"], level: 2, testType: TEST_FIND | TEST_MATCH},
+ {name: "Adjacent sibling combinator, matching element with class that is an adjacent sibling of an element with class (1)", selector: ".adjacent-div2+.adjacent-div4", ctx: "", expect: ["adjacent-div4"], level: 2, testType: TEST_FIND | TEST_MATCH},
+ {name: "Adjacent sibling combinator, matching p element that is an adjacent sibling of a div element (1)", selector: "#adjacent div+p", ctx: "", expect: ["adjacent-p2"], level: 2, testType: TEST_FIND | TEST_MATCH},
+ {name: "Adjacent sibling combinator, not matching element with id that is not an adjacent sibling of an element with id", selector: "#adjacent-div2+#adjacent-p2, #adjacent-div2+#adjacent-div1", ctx: "", expect: [] /*no matches*/, level: 2, testType: TEST_FIND},
+ {name: "Adjacent sibling combinator, surrounded by whitespace (1)", selector: "#adjacent-p2\t\r\n+\t\r\n#adjacent-p3", ctx: "", expect: ["adjacent-p3"], level: 2, testType: TEST_FIND | TEST_MATCH},
+ {name: "Adjacent sibling combinator, whitespace after (1)", selector: "#adjacent-p2+\t\r\n#adjacent-p3", ctx: "", expect: ["adjacent-p3"], level: 2, testType: TEST_FIND | TEST_MATCH},
+ {name: "Adjacent sibling combinator, whitespace before (1)", selector: "#adjacent-p2\t\r\n+#adjacent-p3", ctx: "", expect: ["adjacent-p3"], level: 2, testType: TEST_FIND | TEST_MATCH},
+ {name: "Adjacent sibling combinator, no whitespace (1)", selector: "#adjacent-p2+#adjacent-p3", ctx: "", expect: ["adjacent-p3"], level: 2, testType: TEST_FIND | TEST_MATCH},
+
+ // - General sibling combinator ~ (Level 3)
+ {name: "General sibling combinator, matching element that is a sibling of an element with id (1)", selector: "#sibling-div2~div", ctx: "", expect: ["sibling-div4", "sibling-div6"], level: 3, testType: TEST_FIND | TEST_MATCH},
+ {name: "General sibling combinator, matching element with id that is a sibling of an element (1)", selector: "div~#sibling-div4", ctx: "", expect: ["sibling-div4"], level: 3, testType: TEST_FIND | TEST_MATCH},
+ {name: "General sibling combinator, matching element with id that is a sibling of an element with id (1)", selector: "#sibling-div2~#sibling-div4", ctx: "", expect: ["sibling-div4"], level: 3, testType: TEST_FIND | TEST_MATCH},
+ {name: "General sibling combinator, matching element with class that is a sibling of an element with id (1)", selector: "#sibling-div2~.sibling-div", ctx: "", expect: ["sibling-div4", "sibling-div6"], level: 3, testType: TEST_FIND | TEST_MATCH},
+ {name: "General sibling combinator, matching p element that is a sibling of a div element (1)", selector: "#sibling div~p", ctx: "", expect: ["sibling-p2", "sibling-p3"], level: 3, testType: TEST_FIND | TEST_MATCH},
+ {name: "General sibling combinator, not matching element with id that is not a sibling after a p element (1)", selector: "#sibling>p~div", ctx: "", expect: [] /*no matches*/, level: 3, testType: TEST_FIND},
+ {name: "General sibling combinator, not matching element with id that is not a sibling after an element with id", selector: "#sibling-div2~#sibling-div3, #sibling-div2~#sibling-div1", ctx: "", expect: [] /*no matches*/, level: 3, testType: TEST_FIND},
+ {name: "General sibling combinator, surrounded by whitespace (1)", selector: "#sibling-p2\t\r\n~\t\r\n#sibling-p3", ctx: "", expect: ["sibling-p3"], level: 3, testType: TEST_FIND | TEST_MATCH},
+ {name: "General sibling combinator, whitespace after (1)", selector: "#sibling-p2~\t\r\n#sibling-p3", ctx: "", expect: ["sibling-p3"], level: 3, testType: TEST_FIND | TEST_MATCH},
+ {name: "General sibling combinator, whitespace before (1)", selector: "#sibling-p2\t\r\n~#sibling-p3", ctx: "", expect: ["sibling-p3"], level: 3, testType: TEST_FIND | TEST_MATCH},
+ {name: "General sibling combinator, no whitespace (1)", selector: "#sibling-p2~#sibling-p3", ctx: "", expect: ["sibling-p3"], level: 3, testType: TEST_FIND | TEST_MATCH},
+
+ // Group of selectors (comma)
+ {name: "Syntax, group of selectors separator, surrounded by whitespace (1)", selector: "#group em\t\r \n,\t\r \n#group strong", ctx: "", expect: ["group-em1", "group-strong1"], level: 1, testType: TEST_FIND | TEST_MATCH},
+ {name: "Syntax, group of selectors separator, whitespace after (1)", selector: "#group em,\t\r\n#group strong", ctx: "", expect: ["group-em1", "group-strong1"], level: 1, testType: TEST_FIND | TEST_MATCH},
+ {name: "Syntax, group of selectors separator, whitespace before (1)", selector: "#group em\t\r\n,#group strong", ctx: "", expect: ["group-em1", "group-strong1"], level: 1, testType: TEST_FIND | TEST_MATCH},
+ {name: "Syntax, group of selectors separator, no whitespace (1)", selector: "#group em,#group strong", ctx: "", expect: ["group-em1", "group-strong1"], level: 1, testType: TEST_FIND | TEST_MATCH},
+];
diff --git a/tests/wpt/web-platform-tests/dom/ranges/Range-attributes.html b/tests/wpt/web-platform-tests/dom/ranges/Range-attributes.html
new file mode 100644
index 00000000000..ced47edc507
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/ranges/Range-attributes.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<title>Range attributes</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<meta name=timeout content=long>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function() {
+ var r = document.createRange();
+ assert_equals(r.startContainer, document)
+ assert_equals(r.endContainer, document)
+ assert_equals(r.startOffset, 0)
+ assert_equals(r.endOffset, 0)
+ assert_true(r.collapsed)
+ r.detach()
+ assert_equals(r.startContainer, document)
+ assert_equals(r.endContainer, document)
+ assert_equals(r.startOffset, 0)
+ assert_equals(r.endOffset, 0)
+ assert_true(r.collapsed)
+})
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/ranges/Range-cloneContents.html b/tests/wpt/web-platform-tests/dom/ranges/Range-cloneContents.html
new file mode 100644
index 00000000000..07a95cb055c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/ranges/Range-cloneContents.html
@@ -0,0 +1,454 @@
+<!doctype html>
+<title>Range.cloneContents() tests</title>
+<link rel="author" title="Aryeh Gregor" href=ayg@aryeh.name>
+<meta name=timeout content=long>
+<p>To debug test failures, add a query parameter "subtest" with the test id (like
+"?subtest=5"). Only that test will be run. Then you can look at the resulting
+iframe in the DOM.
+<div id=log></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../common.js></script>
+<script>
+"use strict";
+
+testDiv.parentNode.removeChild(testDiv);
+
+var actualIframe = document.createElement("iframe");
+actualIframe.style.display = "none";
+document.body.appendChild(actualIframe);
+
+var expectedIframe = document.createElement("iframe");
+expectedIframe.style.display = "none";
+document.body.appendChild(expectedIframe);
+
+function myCloneContents(range) {
+ // "Let frag be a new DocumentFragment whose ownerDocument is the same as
+ // the ownerDocument of the context object's start node."
+ var ownerDoc = range.startContainer.nodeType == Node.DOCUMENT_NODE
+ ? range.startContainer
+ : range.startContainer.ownerDocument;
+ var frag = ownerDoc.createDocumentFragment();
+
+ // "If the context object's start and end are the same, abort this method,
+ // returning frag."
+ if (range.startContainer == range.endContainer
+ && range.startOffset == range.endOffset) {
+ return frag;
+ }
+
+ // "Let original start node, original start offset, original end node, and
+ // original end offset be the context object's start and end nodes and
+ // offsets, respectively."
+ var originalStartNode = range.startContainer;
+ var originalStartOffset = range.startOffset;
+ var originalEndNode = range.endContainer;
+ var originalEndOffset = range.endOffset;
+
+ // "If original start node and original end node are the same, and they are
+ // a Text or Comment node:"
+ if (range.startContainer == range.endContainer
+ && (range.startContainer.nodeType == Node.TEXT_NODE
+ || range.startContainer.nodeType == Node.COMMENT_NODE)) {
+ // "Let clone be the result of calling cloneNode(false) on original
+ // start node."
+ var clone = originalStartNode.cloneNode(false);
+
+ // "Set the data of clone to the result of calling
+ // substringData(original start offset, original end offset − original
+ // start offset) on original start node."
+ clone.data = originalStartNode.substringData(originalStartOffset,
+ originalEndOffset - originalStartOffset);
+
+ // "Append clone as the last child of frag."
+ frag.appendChild(clone);
+
+ // "Abort this method, returning frag."
+ return frag;
+ }
+
+ // "Let common ancestor equal original start node."
+ var commonAncestor = originalStartNode;
+
+ // "While common ancestor is not an ancestor container of original end
+ // node, set common ancestor to its own parent."
+ while (!isAncestorContainer(commonAncestor, originalEndNode)) {
+ commonAncestor = commonAncestor.parentNode;
+ }
+
+ // "If original start node is an ancestor container of original end node,
+ // let first partially contained child be null."
+ var firstPartiallyContainedChild;
+ if (isAncestorContainer(originalStartNode, originalEndNode)) {
+ firstPartiallyContainedChild = null;
+ // "Otherwise, let first partially contained child be the first child of
+ // common ancestor that is partially contained in the context object."
+ } else {
+ for (var i = 0; i < commonAncestor.childNodes.length; i++) {
+ if (isPartiallyContained(commonAncestor.childNodes[i], range)) {
+ firstPartiallyContainedChild = commonAncestor.childNodes[i];
+ break;
+ }
+ }
+ if (!firstPartiallyContainedChild) {
+ throw "Spec bug: no first partially contained child!";
+ }
+ }
+
+ // "If original end node is an ancestor container of original start node,
+ // let last partially contained child be null."
+ var lastPartiallyContainedChild;
+ if (isAncestorContainer(originalEndNode, originalStartNode)) {
+ lastPartiallyContainedChild = null;
+ // "Otherwise, let last partially contained child be the last child of
+ // common ancestor that is partially contained in the context object."
+ } else {
+ for (var i = commonAncestor.childNodes.length - 1; i >= 0; i--) {
+ if (isPartiallyContained(commonAncestor.childNodes[i], range)) {
+ lastPartiallyContainedChild = commonAncestor.childNodes[i];
+ break;
+ }
+ }
+ if (!lastPartiallyContainedChild) {
+ throw "Spec bug: no last partially contained child!";
+ }
+ }
+
+ // "Let contained children be a list of all children of common ancestor
+ // that are contained in the context object, in tree order."
+ //
+ // "If any member of contained children is a DocumentType, raise a
+ // HIERARCHY_REQUEST_ERR exception and abort these steps."
+ var containedChildren = [];
+ for (var i = 0; i < commonAncestor.childNodes.length; i++) {
+ if (isContained(commonAncestor.childNodes[i], range)) {
+ if (commonAncestor.childNodes[i].nodeType
+ == Node.DOCUMENT_TYPE_NODE) {
+ return "HIERARCHY_REQUEST_ERR";
+ }
+ containedChildren.push(commonAncestor.childNodes[i]);
+ }
+ }
+
+ // "If first partially contained child is a Text or Comment node:"
+ if (firstPartiallyContainedChild
+ && (firstPartiallyContainedChild.nodeType == Node.TEXT_NODE
+ || firstPartiallyContainedChild.nodeType == Node.COMMENT_NODE)) {
+ // "Let clone be the result of calling cloneNode(false) on original
+ // start node."
+ var clone = originalStartNode.cloneNode(false);
+
+ // "Set the data of clone to the result of calling substringData() on
+ // original start node, with original start offset as the first
+ // argument and (length of original start node − original start offset)
+ // as the second."
+ clone.data = originalStartNode.substringData(originalStartOffset,
+ nodeLength(originalStartNode) - originalStartOffset);
+
+ // "Append clone as the last child of frag."
+ frag.appendChild(clone);
+ // "Otherwise, if first partially contained child is not null:"
+ } else if (firstPartiallyContainedChild) {
+ // "Let clone be the result of calling cloneNode(false) on first
+ // partially contained child."
+ var clone = firstPartiallyContainedChild.cloneNode(false);
+
+ // "Append clone as the last child of frag."
+ frag.appendChild(clone);
+
+ // "Let subrange be a new Range whose start is (original start node,
+ // original start offset) and whose end is (first partially contained
+ // child, length of first partially contained child)."
+ var subrange = ownerDoc.createRange();
+ subrange.setStart(originalStartNode, originalStartOffset);
+ subrange.setEnd(firstPartiallyContainedChild,
+ nodeLength(firstPartiallyContainedChild));
+
+ // "Let subfrag be the result of calling cloneContents() on
+ // subrange."
+ var subfrag = myCloneContents(subrange);
+
+ // "For each child of subfrag, in order, append that child to clone as
+ // its last child."
+ for (var i = 0; i < subfrag.childNodes.length; i++) {
+ clone.appendChild(subfrag.childNodes[i]);
+ }
+ }
+
+ // "For each contained child in contained children:"
+ for (var i = 0; i < containedChildren.length; i++) {
+ // "Let clone be the result of calling cloneNode(true) of contained
+ // child."
+ var clone = containedChildren[i].cloneNode(true);
+
+ // "Append clone as the last child of frag."
+ frag.appendChild(clone);
+ }
+
+ // "If last partially contained child is a Text or Comment node:"
+ if (lastPartiallyContainedChild
+ && (lastPartiallyContainedChild.nodeType == Node.TEXT_NODE
+ || lastPartiallyContainedChild.nodeType == Node.COMMENT_NODE)) {
+ // "Let clone be the result of calling cloneNode(false) on original
+ // end node."
+ var clone = originalEndNode.cloneNode(false);
+
+ // "Set the data of clone to the result of calling substringData(0,
+ // original end offset) on original end node."
+ clone.data = originalEndNode.substringData(0, originalEndOffset);
+
+ // "Append clone as the last child of frag."
+ frag.appendChild(clone);
+ // "Otherwise, if last partially contained child is not null:"
+ } else if (lastPartiallyContainedChild) {
+ // "Let clone be the result of calling cloneNode(false) on last
+ // partially contained child."
+ var clone = lastPartiallyContainedChild.cloneNode(false);
+
+ // "Append clone as the last child of frag."
+ frag.appendChild(clone);
+
+ // "Let subrange be a new Range whose start is (last partially
+ // contained child, 0) and whose end is (original end node, original
+ // end offset)."
+ var subrange = ownerDoc.createRange();
+ subrange.setStart(lastPartiallyContainedChild, 0);
+ subrange.setEnd(originalEndNode, originalEndOffset);
+
+ // "Let subfrag be the result of calling cloneContents() on
+ // subrange."
+ var subfrag = myCloneContents(subrange);
+
+ // "For each child of subfrag, in order, append that child to clone as
+ // its last child."
+ for (var i = 0; i < subfrag.childNodes.length; i++) {
+ clone.appendChild(subfrag.childNodes[i]);
+ }
+ }
+
+ // "Return frag."
+ return frag;
+}
+
+function restoreIframe(iframe, i) {
+ // Most of this function is designed to work around the fact that Opera
+ // doesn't let you add a doctype to a document that no longer has one, in
+ // any way I can figure out. I eventually compromised on something that
+ // will still let Opera pass most tests that don't actually involve
+ // doctypes.
+ while (iframe.contentDocument.firstChild
+ && iframe.contentDocument.firstChild.nodeType != Node.DOCUMENT_TYPE_NODE) {
+ iframe.contentDocument.removeChild(iframe.contentDocument.firstChild);
+ }
+
+ while (iframe.contentDocument.lastChild
+ && iframe.contentDocument.lastChild.nodeType != Node.DOCUMENT_TYPE_NODE) {
+ iframe.contentDocument.removeChild(iframe.contentDocument.lastChild);
+ }
+
+ if (!iframe.contentDocument.firstChild) {
+ // This will throw an exception in Opera if we reach here, which is why
+ // I try to avoid it. It will never happen in a browser that obeys the
+ // spec, so it's really just insurance. I don't think it actually gets
+ // hit by anything.
+ iframe.contentDocument.appendChild(iframe.contentDocument.implementation.createDocumentType("html", "", ""));
+ }
+ iframe.contentDocument.appendChild(referenceDoc.documentElement.cloneNode(true));
+ iframe.contentWindow.setupRangeTests();
+ iframe.contentWindow.testRangeInput = testRanges[i];
+ iframe.contentWindow.run();
+}
+
+function testCloneContents(i) {
+ restoreIframe(actualIframe, i);
+ restoreIframe(expectedIframe, i);
+
+ var actualRange = actualIframe.contentWindow.testRange;
+ var expectedRange = expectedIframe.contentWindow.testRange;
+ var actualFrag, expectedFrag;
+ var actualRoots, expectedRoots;
+
+ domTests[i].step(function() {
+ assert_equals(actualIframe.contentWindow.unexpectedException, null,
+ "Unexpected exception thrown when setting up Range for actual cloneContents()");
+ assert_equals(expectedIframe.contentWindow.unexpectedException, null,
+ "Unexpected exception thrown when setting up Range for simulated cloneContents()");
+ assert_equals(typeof actualRange, "object",
+ "typeof Range produced in actual iframe");
+ assert_equals(typeof expectedRange, "object",
+ "typeof Range produced in expected iframe");
+
+ // NOTE: We could just assume that cloneContents() doesn't change
+ // anything. That would simplify these tests, taken in isolation. But
+ // once we've already set up the whole apparatus for extractContents()
+ // and deleteContents(), we just reuse it here, on the theory of "why
+ // not test some more stuff if it's easy to do".
+ //
+ // Just to be pedantic, we'll test not only that the tree we're
+ // modifying is the same in expected vs. actual, but also that all the
+ // nodes originally in it were the same. Typically some nodes will
+ // become detached when the algorithm is run, but they still exist and
+ // references can still be kept to them, so they should also remain the
+ // same.
+ //
+ // We initialize the list to all nodes, and later on remove all the
+ // ones which still have parents, since the parents will presumably be
+ // tested for isEqualNode() and checking the children would be
+ // redundant.
+ var actualAllNodes = [];
+ var node = furthestAncestor(actualRange.startContainer);
+ do {
+ actualAllNodes.push(node);
+ } while (node = nextNode(node));
+
+ var expectedAllNodes = [];
+ var node = furthestAncestor(expectedRange.startContainer);
+ do {
+ expectedAllNodes.push(node);
+ } while (node = nextNode(node));
+
+ expectedFrag = myCloneContents(expectedRange);
+ if (typeof expectedFrag == "string") {
+ assert_throws(expectedFrag, function() {
+ actualRange.cloneContents();
+ });
+ } else {
+ actualFrag = actualRange.cloneContents();
+ }
+
+ actualRoots = [];
+ for (var j = 0; j < actualAllNodes.length; j++) {
+ if (!actualAllNodes[j].parentNode) {
+ actualRoots.push(actualAllNodes[j]);
+ }
+ }
+
+ expectedRoots = [];
+ for (var j = 0; j < expectedAllNodes.length; j++) {
+ if (!expectedAllNodes[j].parentNode) {
+ expectedRoots.push(expectedAllNodes[j]);
+ }
+ }
+
+ for (var j = 0; j < actualRoots.length; j++) {
+ assertNodesEqual(actualRoots[j], expectedRoots[j], j ? "detached node #" + j : "tree root");
+
+ if (j == 0) {
+ // Clearly something is wrong if the node lists are different
+ // lengths. We want to report this only after we've already
+ // checked the main tree for equality, though, so it doesn't
+ // mask more interesting errors.
+ assert_equals(actualRoots.length, expectedRoots.length,
+ "Actual and expected DOMs were broken up into a different number of pieces by cloneContents() (this probably means you created or detached nodes when you weren't supposed to)");
+ }
+ }
+ });
+ domTests[i].done();
+
+ positionTests[i].step(function() {
+ assert_equals(actualIframe.contentWindow.unexpectedException, null,
+ "Unexpected exception thrown when setting up Range for actual cloneContents()");
+ assert_equals(expectedIframe.contentWindow.unexpectedException, null,
+ "Unexpected exception thrown when setting up Range for simulated cloneContents()");
+ assert_equals(typeof actualRange, "object",
+ "typeof Range produced in actual iframe");
+ assert_equals(typeof expectedRange, "object",
+ "typeof Range produced in expected iframe");
+
+ assert_true(actualRoots[0].isEqualNode(expectedRoots[0]),
+ "The resulting DOMs were not equal, so comparing positions makes no sense");
+
+ if (typeof expectedFrag == "string") {
+ // It's no longer true that, e.g., startContainer and endContainer
+ // must always be the same
+ return;
+ }
+
+ assert_equals(actualRange.startOffset, expectedRange.startOffset,
+ "Unexpected startOffset after cloneContents()");
+ // How do we decide that the two nodes are equal, since they're in
+ // different trees? Since the DOMs are the same, it's enough to check
+ // that the index in the parent is the same all the way up the tree.
+ // But we can first cheat by just checking they're actually equal.
+ assert_true(actualRange.startContainer.isEqualNode(expectedRange.startContainer),
+ "Unexpected startContainer after cloneContents(), expected " +
+ expectedRange.startContainer.nodeName.toLowerCase() + " but got " +
+ actualRange.startContainer.nodeName.toLowerCase());
+ var currentActual = actualRange.startContainer;
+ var currentExpected = expectedRange.startContainer;
+ var actual = "";
+ var expected = "";
+ while (currentActual && currentExpected) {
+ actual = indexOf(currentActual) + "-" + actual;
+ expected = indexOf(currentExpected) + "-" + expected;
+
+ currentActual = currentActual.parentNode;
+ currentExpected = currentExpected.parentNode;
+ }
+ actual = actual.substr(0, actual.length - 1);
+ expected = expected.substr(0, expected.length - 1);
+ assert_equals(actual, expected,
+ "startContainer superficially looks right but is actually the wrong node if you trace back its index in all its ancestors (I'm surprised this actually happened");
+ });
+ positionTests[i].done();
+
+ fragTests[i].step(function() {
+ assert_equals(actualIframe.contentWindow.unexpectedException, null,
+ "Unexpected exception thrown when setting up Range for actual cloneContents()");
+ assert_equals(expectedIframe.contentWindow.unexpectedException, null,
+ "Unexpected exception thrown when setting up Range for simulated cloneContents()");
+ assert_equals(typeof actualRange, "object",
+ "typeof Range produced in actual iframe");
+ assert_equals(typeof expectedRange, "object",
+ "typeof Range produced in expected iframe");
+
+ if (typeof expectedFrag == "string") {
+ // Comparing makes no sense
+ return;
+ }
+ assertNodesEqual(actualFrag, expectedFrag,
+ "returned fragment");
+ });
+ fragTests[i].done();
+}
+
+// First test a Range that has the no-op detach() called on it, synchronously
+test(function() {
+ var range = document.createRange();
+ range.detach();
+ assert_array_equals(range.cloneContents().childNodes, []);
+}, "Range.detach()");
+
+var iStart = 0;
+var iStop = testRanges.length;
+
+if (/subtest=[0-9]+/.test(location.search)) {
+ var matches = /subtest=([0-9]+)/.exec(location.search);
+ iStart = Number(matches[1]);
+ iStop = Number(matches[1]) + 1;
+}
+
+var domTests = [];
+var positionTests = [];
+var fragTests = [];
+
+for (var i = iStart; i < iStop; i++) {
+ domTests[i] = async_test("Resulting DOM for range " + i + " " + testRanges[i]);
+ positionTests[i] = async_test("Resulting cursor position for range " + i + " " + testRanges[i]);
+ fragTests[i] = async_test("Returned fragment for range " + i + " " + testRanges[i]);
+}
+
+var referenceDoc = document.implementation.createHTMLDocument("");
+referenceDoc.removeChild(referenceDoc.documentElement);
+
+actualIframe.onload = function() {
+ expectedIframe.onload = function() {
+ for (var i = iStart; i < iStop; i++) {
+ testCloneContents(i);
+ }
+ }
+ expectedIframe.src = "Range-test-iframe.html";
+ referenceDoc.appendChild(actualIframe.contentDocument.documentElement.cloneNode(true));
+}
+actualIframe.src = "Range-test-iframe.html";
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/ranges/Range-cloneRange.html b/tests/wpt/web-platform-tests/dom/ranges/Range-cloneRange.html
new file mode 100644
index 00000000000..6c736df29f0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/ranges/Range-cloneRange.html
@@ -0,0 +1,112 @@
+<!doctype html>
+<title>Range.cloneRange() and document.createRange() tests</title>
+<link rel="author" title="Aryeh Gregor" href=ayg@aryeh.name>
+<meta name=timeout content=long>
+<div id=log></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../common.js></script>
+<script>
+"use strict";
+
+function testCloneRange(rangeEndpoints) {
+ var range;
+ if (rangeEndpoints == "detached") {
+ range = document.createRange();
+ range.detach();
+ var clonedRange = range.cloneRange();
+ assert_equals(clonedRange.startContainer, range.startContainer,
+ "startContainers must be equal after cloneRange()");
+ assert_equals(clonedRange.startOffset, range.startOffset,
+ "startOffsets must be equal after cloneRange()");
+ assert_equals(clonedRange.endContainer, range.endContainer,
+ "endContainers must be equal after cloneRange()");
+ assert_equals(clonedRange.endOffset, range.endOffset,
+ "endOffsets must be equal after cloneRange()");
+ return;
+ }
+
+ // Have to account for Ranges involving Documents! We could just create
+ // the Range from the current document unconditionally, but some browsers
+ // (WebKit) don't implement setStart() and setEnd() per spec and will throw
+ // spurious exceptions at the time of this writing. No need to mask other
+ // bugs.
+ var ownerDoc = rangeEndpoints[0].nodeType == Node.DOCUMENT_NODE
+ ? rangeEndpoints[0]
+ : rangeEndpoints[0].ownerDocument;
+ range = ownerDoc.createRange();
+ // Here we throw in some createRange() tests, because why not. Have to
+ // test it someplace.
+ assert_equals(range.startContainer, ownerDoc,
+ "doc.createRange() must create Range whose startContainer is doc");
+ assert_equals(range.endContainer, ownerDoc,
+ "doc.createRange() must create Range whose endContainer is doc");
+ assert_equals(range.startOffset, 0,
+ "doc.createRange() must create Range whose startOffset is 0");
+ assert_equals(range.endOffset, 0,
+ "doc.createRange() must create Range whose endOffset is 0");
+
+ range.setStart(rangeEndpoints[0], rangeEndpoints[1]);
+ range.setEnd(rangeEndpoints[2], rangeEndpoints[3]);
+
+ // Make sure we bail out now if setStart or setEnd are buggy, so it doesn't
+ // create misleading failures later.
+ assert_equals(range.startContainer, rangeEndpoints[0],
+ "Sanity check on setStart()");
+ assert_equals(range.startOffset, rangeEndpoints[1],
+ "Sanity check on setStart()");
+ assert_equals(range.endContainer, rangeEndpoints[2],
+ "Sanity check on setEnd()");
+ assert_equals(range.endOffset, rangeEndpoints[3],
+ "Sanity check on setEnd()");
+
+ var clonedRange = range.cloneRange();
+
+ assert_equals(clonedRange.startContainer, range.startContainer,
+ "startContainers must be equal after cloneRange()");
+ assert_equals(clonedRange.startOffset, range.startOffset,
+ "startOffsets must be equal after cloneRange()");
+ assert_equals(clonedRange.endContainer, range.endContainer,
+ "endContainers must be equal after cloneRange()");
+ assert_equals(clonedRange.endOffset, range.endOffset,
+ "endOffsets must be equal after cloneRange()");
+
+ // Make sure that modifying one doesn't affect the other.
+ var testNode1 = ownerDoc.createTextNode("testing");
+ var testNode2 = ownerDoc.createTextNode("testing with different length");
+
+ range.setStart(testNode1, 1);
+ range.setEnd(testNode1, 2);
+ assert_equals(clonedRange.startContainer, rangeEndpoints[0],
+ "Modifying a Range must not modify its clone's startContainer");
+ assert_equals(clonedRange.startOffset, rangeEndpoints[1],
+ "Modifying a Range must not modify its clone's startOffset");
+ assert_equals(clonedRange.endContainer, rangeEndpoints[2],
+ "Modifying a Range must not modify its clone's endContainer");
+ assert_equals(clonedRange.endOffset, rangeEndpoints[3],
+ "Modifying a Range must not modify its clone's endOffset");
+
+ clonedRange.setStart(testNode2, 3);
+ clonedRange.setStart(testNode2, 4);
+
+ assert_equals(range.startContainer, testNode1,
+ "Modifying a clone must not modify the original Range's startContainer");
+ assert_equals(range.startOffset, 1,
+ "Modifying a clone must not modify the original Range's startOffset");
+ assert_equals(range.endContainer, testNode1,
+ "Modifying a clone must not modify the original Range's endContainer");
+ assert_equals(range.endOffset, 2,
+ "Modifying a clone must not modify the original Range's endOffset");
+}
+
+var tests = [];
+for (var i = 0; i < testRanges.length; i++) {
+ tests.push([
+ "Range " + i + " " + testRanges[i],
+ eval(testRanges[i])
+ ]);
+}
+generate_tests(testCloneRange, tests);
+
+testDiv.style.display = "none";
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/ranges/Range-collapse.html b/tests/wpt/web-platform-tests/dom/ranges/Range-collapse.html
new file mode 100644
index 00000000000..78e1d9fb4ba
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/ranges/Range-collapse.html
@@ -0,0 +1,75 @@
+<!doctype html>
+<title>Range.collapse() and .collapsed tests</title>
+<link rel="author" title="Aryeh Gregor" href=ayg@aryeh.name>
+<meta name=timeout content=long>
+<div id=log></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../common.js></script>
+<script>
+"use strict";
+
+function testCollapse(rangeEndpoints, toStart) {
+ var range;
+ if (rangeEndpoints == "detached") {
+ range = document.createRange();
+ range.detach(); // should be a no-op and therefore the following should not throw
+ range.collapse(toStart);
+ assert_equals(true, range.collapsed);
+ }
+
+ // Have to account for Ranges involving Documents!
+ var ownerDoc = rangeEndpoints[0].nodeType == Node.DOCUMENT_NODE
+ ? rangeEndpoints[0]
+ : rangeEndpoints[0].ownerDocument;
+ range = ownerDoc.createRange();
+ range.setStart(rangeEndpoints[0], rangeEndpoints[1]);
+ range.setEnd(rangeEndpoints[2], rangeEndpoints[3]);
+
+ var expectedContainer = toStart ? range.startContainer : range.endContainer;
+ var expectedOffset = toStart ? range.startOffset : range.endOffset;
+
+ assert_equals(range.collapsed, range.startContainer == range.endContainer
+ && range.startOffset == range.endOffset,
+ "collapsed must be true if and only if the start and end are equal");
+
+ if (toStart === undefined) {
+ range.collapse();
+ } else {
+ range.collapse(toStart);
+ }
+
+ assert_equals(range.startContainer, expectedContainer,
+ "Wrong startContainer");
+ assert_equals(range.endContainer, expectedContainer,
+ "Wrong endContainer");
+ assert_equals(range.startOffset, expectedOffset,
+ "Wrong startOffset");
+ assert_equals(range.endOffset, expectedOffset,
+ "Wrong endOffset");
+ assert_true(range.collapsed,
+ ".collapsed must be set after .collapsed()");
+}
+
+var tests = [];
+for (var i = 0; i < testRanges.length; i++) {
+ tests.push([
+ "Range " + i + " " + testRanges[i] + ", toStart true",
+ eval(testRanges[i]),
+ true
+ ]);
+ tests.push([
+ "Range " + i + " " + testRanges[i] + ", toStart false",
+ eval(testRanges[i]),
+ false
+ ]);
+ tests.push([
+ "Range " + i + " " + testRanges[i] + ", toStart omitted",
+ eval(testRanges[i]),
+ undefined
+ ]);
+}
+generate_tests(testCollapse, tests);
+
+testDiv.style.display = "none";
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/ranges/Range-commonAncestorContainer-2.html b/tests/wpt/web-platform-tests/dom/ranges/Range-commonAncestorContainer-2.html
new file mode 100644
index 00000000000..f0a3e451cd0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/ranges/Range-commonAncestorContainer-2.html
@@ -0,0 +1,33 @@
+<!doctype html>
+<title>Range.commonAncestorContainer</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function() {
+ var range = document.createRange();
+ range.detach();
+ assert_equals(range.commonAncestorContainer, document);
+}, "Detached Range")
+test(function() {
+ var df = document.createDocumentFragment();
+ var foo = df.appendChild(document.createElement("foo"));
+ foo.appendChild(document.createTextNode("Foo"));
+ var bar = df.appendChild(document.createElement("bar"));
+ bar.appendChild(document.createComment("Bar"));
+ [
+ // start node, start offset, end node, end offset, expected cAC
+ [foo, 0, bar, 0, df],
+ [foo, 0, foo.firstChild, 3, foo],
+ [foo.firstChild, 0, bar, 0, df],
+ [foo.firstChild, 3, bar.firstChild, 2, df]
+ ].forEach(function(t) {
+ test(function() {
+ var range = document.createRange();
+ range.setStart(t[0], t[1]);
+ range.setEnd(t[2], t[3]);
+ assert_equals(range.commonAncestorContainer, t[4]);
+ })
+ });
+}, "Normal Ranges")
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/ranges/Range-commonAncestorContainer.html b/tests/wpt/web-platform-tests/dom/ranges/Range-commonAncestorContainer.html
new file mode 100644
index 00000000000..7882ccc31fe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/ranges/Range-commonAncestorContainer.html
@@ -0,0 +1,40 @@
+<!doctype html>
+<title>Range.commonAncestorContainer tests</title>
+<link rel="author" title="Aryeh Gregor" href=ayg@aryeh.name>
+<meta name=timeout content=long>
+<div id=log></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../common.js></script>
+<script>
+"use strict";
+
+testRanges.unshift("[detached]");
+
+for (var i = 0; i < testRanges.length; i++) {
+ test(function() {
+ var range;
+ if (i == 0) {
+ range = document.createRange();
+ range.detach();
+ } else {
+ range = rangeFromEndpoints(eval(testRanges[i]));
+ }
+
+ // "Let container be start node."
+ var container = range.startContainer;
+
+ // "While container is not an inclusive ancestor of end node, let
+ // container be container's parent."
+ while (container != range.endContainer
+ && !isAncestor(container, range.endContainer)) {
+ container = container.parentNode;
+ }
+
+ // "Return container."
+ assert_equals(range.commonAncestorContainer, container);
+ }, i + ": range " + testRanges[i]);
+}
+
+testDiv.style.display = "none";
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/ranges/Range-compareBoundaryPoints.html b/tests/wpt/web-platform-tests/dom/ranges/Range-compareBoundaryPoints.html
new file mode 100644
index 00000000000..48413ecd81e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/ranges/Range-compareBoundaryPoints.html
@@ -0,0 +1,182 @@
+<!doctype html>
+<title>Range.compareBoundaryPoints() tests</title>
+<link rel="author" title="Aryeh Gregor" href=ayg@aryeh.name>
+<meta name=timeout content=long>
+
+<div id=log></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../common.js></script>
+<script>
+"use strict";
+
+var testRangesCached = [];
+testRangesCached.push(document.createRange());
+testRangesCached[0].detach();
+for (var i = 0; i < testRangesShort.length; i++) {
+ try {
+ testRangesCached.push(rangeFromEndpoints(eval(testRangesShort[i])));
+ } catch(e) {
+ testRangesCached.push(null);
+ }
+}
+
+var testRangesCachedClones = [];
+testRangesCachedClones.push(document.createRange());
+testRangesCachedClones[0].detach();
+for (var i = 1; i < testRangesCached.length; i++) {
+ if (testRangesCached[i]) {
+ testRangesCachedClones.push(testRangesCached[i].cloneRange());
+ } else {
+ testRangesCachedClones.push(null);
+ }
+}
+
+// We want to run a whole bunch of extra tests with invalid "how" values (not
+// 0-3), but it's excessive to run them for every single pair of ranges --
+// there are too many of them. So just run them for a handful of the tests.
+var extraTests = [0, // detached
+ 1 + testRanges.indexOf("[paras[0].firstChild, 2, paras[0].firstChild, 8]"),
+ 1 + testRanges.indexOf("[paras[0].firstChild, 3, paras[3], 1]"),
+ 1 + testRanges.indexOf("[testDiv, 0, comment, 5]"),
+ 1 + testRanges.indexOf("[foreignDoc.documentElement, 0, foreignDoc.documentElement, 1]")];
+
+for (var i = 0; i < testRangesCached.length; i++) {
+ var range1 = testRangesCached[i];
+ var range1Desc = i + " " + (i == 0 ? "[detached]" : testRanges[i - 1]);
+ for (var j = 0; j <= testRangesCachedClones.length; j++) {
+ var range2;
+ var range2Desc;
+ if (j == testRangesCachedClones.length) {
+ range2 = range1;
+ range2Desc = "same as first range";
+ } else {
+ range2 = testRangesCachedClones[j];
+ range2Desc = j + " " + (j == 0 ? "[detached]" : testRanges[j - 1]);
+ }
+
+ var hows = [Range.START_TO_START, Range.START_TO_END, Range.END_TO_END,
+ Range.END_TO_START];
+ if (extraTests.indexOf(i) != -1 && extraTests.indexOf(j) != -1) {
+ // TODO: Make some type of reusable utility function to do this
+ // work.
+ hows.push(-1, 4, 5, NaN, -0, +Infinity, -Infinity);
+ [65536, -65536, 65536*65536, 0.5, -0.5, -72.5].forEach(function(addend) {
+ hows.push(-1 + addend, 0 + addend, 1 + addend,
+ 2 + addend, 3 + addend, 4 + addend);
+ });
+ hows.forEach(function(how) { hows.push(String(how)) });
+ hows.push("6.5536e4", null, undefined, true, false, "", "quasit");
+ }
+
+ for (var k = 0; k < hows.length; k++) {
+ var how = hows[k];
+ test(function() {
+ assert_not_equals(range1, null,
+ "Creating context range threw an exception");
+ assert_not_equals(range2, null,
+ "Creating argument range threw an exception");
+
+ // Convert how per WebIDL. TODO: Make some type of reusable
+ // utility function to do this work.
+ // "Let number be the result of calling ToNumber on the input
+ // argument."
+ var convertedHow = Number(how);
+
+ // "If number is NaN, +0, −0, +∞, or −∞, return +0."
+ if (isNaN(convertedHow)
+ || convertedHow == 0
+ || convertedHow == Infinity
+ || convertedHow == -Infinity) {
+ convertedHow = 0;
+ } else {
+ // "Let posInt be sign(number) * floor(abs(number))."
+ var posInt = (convertedHow < 0 ? -1 : 1) * Math.floor(Math.abs(convertedHow));
+
+ // "Let int16bit be posInt modulo 2^16; that is, a finite
+ // integer value k of Number type with positive sign and
+ // less than 2^16 in magnitude such that the mathematical
+ // difference of posInt and k is mathematically an integer
+ // multiple of 2^16."
+ //
+ // "Return int16bit."
+ convertedHow = posInt % 65536;
+ if (convertedHow < 0) {
+ convertedHow += 65536;
+ }
+ }
+
+ // Now to the actual algorithm.
+ // "If how is not one of
+ // START_TO_START,
+ // START_TO_END,
+ // END_TO_END, and
+ // END_TO_START,
+ // throw a "NotSupportedError" exception and terminate these
+ // steps."
+ if (convertedHow != Range.START_TO_START
+ && convertedHow != Range.START_TO_END
+ && convertedHow != Range.END_TO_END
+ && convertedHow != Range.END_TO_START) {
+ assert_throws("NOT_SUPPORTED_ERR", function() {
+ range1.compareBoundaryPoints(how, range2);
+ }, "NotSupportedError required if first parameter doesn't convert to 0-3 per WebIDL");
+ return;
+ }
+
+ // "If context object's root is not the same as sourceRange's
+ // root, throw a "WrongDocumentError" exception and terminate
+ // these steps."
+ if (furthestAncestor(range1.startContainer) != furthestAncestor(range2.startContainer)) {
+ assert_throws("WRONG_DOCUMENT_ERR", function() {
+ range1.compareBoundaryPoints(how, range2);
+ }, "WrongDocumentError required if the ranges don't share a root");
+ return;
+ }
+
+ // "If how is:
+ // START_TO_START:
+ // Let this point be the context object's start.
+ // Let other point be sourceRange's start.
+ // START_TO_END:
+ // Let this point be the context object's end.
+ // Let other point be sourceRange's start.
+ // END_TO_END:
+ // Let this point be the context object's end.
+ // Let other point be sourceRange's end.
+ // END_TO_START:
+ // Let this point be the context object's start.
+ // Let other point be sourceRange's end."
+ var thisPoint = convertedHow == Range.START_TO_START || convertedHow == Range.END_TO_START
+ ? [range1.startContainer, range1.startOffset]
+ : [range1.endContainer, range1.endOffset];
+ var otherPoint = convertedHow == Range.START_TO_START || convertedHow == Range.START_TO_END
+ ? [range2.startContainer, range2.startOffset]
+ : [range2.endContainer, range2.endOffset];
+
+ // "If the position of this point relative to other point is
+ // before
+ // Return −1.
+ // equal
+ // Return 0.
+ // after
+ // Return 1."
+ var position = getPosition(thisPoint[0], thisPoint[1], otherPoint[0], otherPoint[1]);
+ var expected;
+ if (position == "before") {
+ expected = -1;
+ } else if (position == "equal") {
+ expected = 0;
+ } else if (position == "after") {
+ expected = 1;
+ }
+
+ assert_equals(range1.compareBoundaryPoints(how, range2), expected,
+ "Wrong return value");
+ }, i + "," + j + "," + k + ": context range " + range1Desc + ", argument range " + range2Desc + ", how " + format_value(how));
+ }
+ }
+}
+
+testDiv.style.display = "none";
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/ranges/Range-comparePoint-2.html b/tests/wpt/web-platform-tests/dom/ranges/Range-comparePoint-2.html
new file mode 100644
index 00000000000..356c8d351fb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/ranges/Range-comparePoint-2.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<title>Range.comparePoint</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<meta name=timeout content=long>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function() {
+ var r = document.createRange();
+ r.detach()
+ assert_equals(r.comparePoint(document.body, 0), 1)
+})
+test(function() {
+ var r = document.createRange();
+ assert_throws(new TypeError(), function() { r.comparePoint(null, 0) })
+})
+test(function() {
+ var doc = document.implementation.createHTMLDocument("tralala")
+ var r = document.createRange();
+ assert_throws("WRONG_DOCUMENT_ERR", function() { r.comparePoint(doc.body, 0) })
+})
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/ranges/Range-comparePoint.html b/tests/wpt/web-platform-tests/dom/ranges/Range-comparePoint.html
new file mode 100644
index 00000000000..95264796be8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/ranges/Range-comparePoint.html
@@ -0,0 +1,92 @@
+<!doctype html>
+<title>Range.comparePoint() tests</title>
+<link rel="author" title="Aryeh Gregor" href=ayg@aryeh.name>
+<meta name=timeout content=long>
+<div id=log></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../common.js></script>
+<script>
+"use strict";
+
+// Will be filled in on the first run for that range
+var testRangesCached = [];
+
+for (var i = 0; i < testPoints.length; i++) {
+ var node = eval(testPoints[i])[0];
+ var offset = eval(testPoints[i])[1];
+
+ // comparePoint is an unsigned long, so per WebIDL, we need to treat it as
+ // though it wrapped to an unsigned 32-bit integer.
+ var normalizedOffset = offset % Math.pow(2, 32);
+ if (normalizedOffset < 0) {
+ normalizedOffset += Math.pow(2, 32);
+ }
+
+ for (var j = 0; j < testRanges.length; j++) {
+ test(function() {
+ if (testRangesCached[j] === undefined) {
+ try {
+ testRangesCached[j] = rangeFromEndpoints(eval(testRanges[i]));
+ } catch(e) {
+ testRangesCached[j] = null;
+ }
+ }
+ assert_not_equals(testRangesCached[j], null,
+ "Setting up the range failed");
+
+ var range = testRangesCached[j].cloneRange();
+
+ // "If node's root is different from the context object's root,
+ // throw a "WrongDocumentError" exception and terminate these
+ // steps."
+ if (furthestAncestor(node) !== furthestAncestor(range.startContainer)) {
+ assert_throws("WRONG_DOCUMENT_ERR", function() {
+ range.comparePoint(node, offset);
+ }, "Must throw WrongDocumentError if node and range have different roots");
+ return;
+ }
+
+ // "If node is a doctype, throw an "InvalidNodeTypeError" exception
+ // and terminate these steps."
+ if (node.nodeType == Node.DOCUMENT_TYPE_NODE) {
+ assert_throws("INVALID_NODE_TYPE_ERR", function() {
+ range.comparePoint(node, offset);
+ }, "Must throw InvalidNodeTypeError if node is a doctype");
+ return;
+ }
+
+ // "If offset is greater than node's length, throw an
+ // "IndexSizeError" exception and terminate these steps."
+ if (normalizedOffset > nodeLength(node)) {
+ assert_throws("INDEX_SIZE_ERR", function() {
+ range.comparePoint(node, offset);
+ }, "Must throw IndexSizeError if offset is greater than length");
+ return;
+ }
+
+ // "If (node, offset) is before start, return −1 and terminate
+ // these steps."
+ if (getPosition(node, normalizedOffset, range.startContainer, range.startOffset) === "before") {
+ assert_equals(range.comparePoint(node, offset), -1,
+ "Must return -1 if point is before start");
+ return;
+ }
+
+ // "If (node, offset) is after end, return 1 and terminate these
+ // steps."
+ if (getPosition(node, normalizedOffset, range.endContainer, range.endOffset) === "after") {
+ assert_equals(range.comparePoint(node, offset), 1,
+ "Must return 1 if point is after end");
+ return;
+ }
+
+ // "Return 0."
+ assert_equals(range.comparePoint(node, offset), 0,
+ "Must return 0 if point is neither before start nor after end");
+ }, "Point " + i + " " + testPoints[i] + ", range " + j + " " + testRanges[j]);
+ }
+}
+
+testDiv.style.display = "none";
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/ranges/Range-deleteContents.html b/tests/wpt/web-platform-tests/dom/ranges/Range-deleteContents.html
new file mode 100644
index 00000000000..c3eca6c5bd7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/ranges/Range-deleteContents.html
@@ -0,0 +1,331 @@
+<!doctype html>
+<title>Range.deleteContents() tests</title>
+<link rel="author" title="Aryeh Gregor" href=ayg@aryeh.name>
+<meta name=timeout content=long>
+<p>To debug test failures, add a query parameter "subtest" with the test id (like
+"?subtest=5"). Only that test will be run. Then you can look at the resulting
+iframe in the DOM.
+<div id=log></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../common.js></script>
+<script>
+"use strict";
+
+testDiv.parentNode.removeChild(testDiv);
+
+var actualIframe = document.createElement("iframe");
+actualIframe.style.display = "none";
+document.body.appendChild(actualIframe);
+
+var expectedIframe = document.createElement("iframe");
+expectedIframe.style.display = "none";
+document.body.appendChild(expectedIframe);
+
+function restoreIframe(iframe, i) {
+ // Most of this function is designed to work around the fact that Opera
+ // doesn't let you add a doctype to a document that no longer has one, in
+ // any way I can figure out. I eventually compromised on something that
+ // will still let Opera pass most tests that don't actually involve
+ // doctypes.
+ while (iframe.contentDocument.firstChild
+ && iframe.contentDocument.firstChild.nodeType != Node.DOCUMENT_TYPE_NODE) {
+ iframe.contentDocument.removeChild(iframe.contentDocument.firstChild);
+ }
+
+ while (iframe.contentDocument.lastChild
+ && iframe.contentDocument.lastChild.nodeType != Node.DOCUMENT_TYPE_NODE) {
+ iframe.contentDocument.removeChild(iframe.contentDocument.lastChild);
+ }
+
+ if (!iframe.contentDocument.firstChild) {
+ // This will throw an exception in Opera if we reach here, which is why
+ // I try to avoid it. It will never happen in a browser that obeys the
+ // spec, so it's really just insurance. I don't think it actually gets
+ // hit by anything.
+ iframe.contentDocument.appendChild(iframe.contentDocument.implementation.createDocumentType("html", "", ""));
+ }
+ iframe.contentDocument.appendChild(referenceDoc.documentElement.cloneNode(true));
+ iframe.contentWindow.setupRangeTests();
+ iframe.contentWindow.testRangeInput = testRanges[i];
+ iframe.contentWindow.run();
+}
+
+function myDeleteContents(range) {
+ // "If the context object's start and end are the same, abort this method."
+ if (range.startContainer == range.endContainer
+ && range.startOffset == range.endOffset) {
+ return;
+ }
+
+ // "Let original start node, original start offset, original end node, and
+ // original end offset be the context object's start and end nodes and
+ // offsets, respectively."
+ var originalStartNode = range.startContainer;
+ var originalStartOffset = range.startOffset;
+ var originalEndNode = range.endContainer;
+ var originalEndOffset = range.endOffset;
+
+ // "If original start node and original end node are the same, and they are
+ // a Text or Comment node, call deleteData(original start offset, original
+ // end offset − original start offset) on that node, and abort these
+ // steps."
+ if (originalStartNode == originalEndNode
+ && (range.startContainer.nodeType == Node.TEXT_NODE
+ || range.startContainer.nodeType == Node.COMMENT_NODE)) {
+ originalStartNode.deleteData(originalStartOffset, originalEndOffset - originalStartOffset);
+ return;
+ }
+
+ // "Let nodes to remove be a list of all the Nodes that are contained in
+ // the context object, in tree order, omitting any Node whose parent is
+ // also contained in the context object."
+ //
+ // We rely on the fact that the contained nodes must lie in tree order
+ // between the start node, and the end node's last descendant (inclusive).
+ var nodesToRemove = [];
+ var stop = nextNodeDescendants(range.endContainer);
+ for (var node = range.startContainer; node != stop; node = nextNode(node)) {
+ if (isContained(node, range)
+ && !(node.parentNode && isContained(node.parentNode, range))) {
+ nodesToRemove.push(node);
+ }
+ }
+
+ // "If original start node is an ancestor container of original end node,
+ // set new node to original start node and new offset to original start
+ // offset."
+ var newNode;
+ var newOffset;
+ if (originalStartNode == originalEndNode
+ || originalEndNode.compareDocumentPosition(originalStartNode) & Node.DOCUMENT_POSITION_CONTAINS) {
+ newNode = originalStartNode;
+ newOffset = originalStartOffset;
+ // "Otherwise:"
+ } else {
+ // "Let reference node equal original start node."
+ var referenceNode = originalStartNode;
+
+ // "While reference node's parent is not null and is not an ancestor
+ // container of original end node, set reference node to its parent."
+ while (referenceNode.parentNode
+ && referenceNode.parentNode != originalEndNode
+ && !(originalEndNode.compareDocumentPosition(referenceNode.parentNode) & Node.DOCUMENT_POSITION_CONTAINS)) {
+ referenceNode = referenceNode.parentNode;
+ }
+
+ // "Set new node to the parent of reference node, and new offset to one
+ // plus the index of reference node."
+ newNode = referenceNode.parentNode;
+ newOffset = 1 + indexOf(referenceNode);
+ }
+
+ // "If original start node is a Text or Comment node, run deleteData() on
+ // it, with original start offset as the first argument and (length of
+ // original start node − original start offset) as the second."
+ if (originalStartNode.nodeType == Node.TEXT_NODE
+ || originalStartNode.nodeType == Node.COMMENT_NODE) {
+ originalStartNode.deleteData(originalStartOffset, nodeLength(originalStartNode) - originalStartOffset);
+ }
+
+ // "For each node in nodes to remove, in order, remove node from its
+ // parent."
+ for (var i = 0; i < nodesToRemove.length; i++) {
+ nodesToRemove[i].parentNode.removeChild(nodesToRemove[i]);
+ }
+
+ // "If original end node is a Text or Comment node, run deleteData(0,
+ // original end offset) on it."
+ if (originalEndNode.nodeType == Node.TEXT_NODE
+ || originalEndNode.nodeType == Node.COMMENT_NODE) {
+ originalEndNode.deleteData(0, originalEndOffset);
+ }
+
+ // "Set the context object's start and end to (new node, new offset)."
+ range.setStart(newNode, newOffset);
+ range.setEnd(newNode, newOffset);
+}
+
+function testDeleteContents(i) {
+ restoreIframe(actualIframe, i);
+ restoreIframe(expectedIframe, i);
+
+ var actualRange = actualIframe.contentWindow.testRange;
+ var expectedRange = expectedIframe.contentWindow.testRange;
+ var actualRoots, expectedRoots;
+
+ domTests[i].step(function() {
+ assert_equals(actualIframe.contentWindow.unexpectedException, null,
+ "Unexpected exception thrown when setting up Range for actual deleteContents()");
+ assert_equals(expectedIframe.contentWindow.unexpectedException, null,
+ "Unexpected exception thrown when setting up Range for simulated deleteContents()");
+ assert_equals(typeof actualRange, "object",
+ "typeof Range produced in actual iframe");
+ assert_equals(typeof expectedRange, "object",
+ "typeof Range produced in expected iframe");
+
+ // Just to be pedantic, we'll test not only that the tree we're
+ // modifying is the same in expected vs. actual, but also that all the
+ // nodes originally in it were the same. Typically some nodes will
+ // become detached when the algorithm is run, but they still exist and
+ // references can still be kept to them, so they should also remain the
+ // same.
+ //
+ // We initialize the list to all nodes, and later on remove all the
+ // ones which still have parents, since the parents will presumably be
+ // tested for isEqualNode() and checking the children would be
+ // redundant.
+ var actualAllNodes = [];
+ var node = furthestAncestor(actualRange.startContainer);
+ do {
+ actualAllNodes.push(node);
+ } while (node = nextNode(node));
+
+ var expectedAllNodes = [];
+ var node = furthestAncestor(expectedRange.startContainer);
+ do {
+ expectedAllNodes.push(node);
+ } while (node = nextNode(node));
+
+ actualRange.deleteContents();
+ myDeleteContents(expectedRange);
+
+ actualRoots = [];
+ for (var j = 0; j < actualAllNodes.length; j++) {
+ if (!actualAllNodes[j].parentNode) {
+ actualRoots.push(actualAllNodes[j]);
+ }
+ }
+
+ expectedRoots = [];
+ for (var j = 0; j < expectedAllNodes.length; j++) {
+ if (!expectedAllNodes[j].parentNode) {
+ expectedRoots.push(expectedAllNodes[j]);
+ }
+ }
+
+ for (var j = 0; j < actualRoots.length; j++) {
+ if (!actualRoots[j].isEqualNode(expectedRoots[j])) {
+ var msg = j ? "detached node #" + j : "tree root";
+ msg = "Actual and expected mismatch for " + msg + ". ";
+
+ // Find the specific error
+ var actual = actualRoots[j];
+ var expected = expectedRoots[j];
+
+ while (actual && expected) {
+ assert_equals(actual.nodeType, expected.nodeType,
+ msg + "First difference: differing nodeType");
+ assert_equals(actual.nodeName, expected.nodeName,
+ msg + "First difference: differing nodeName");
+ assert_equals(actual.nodeValue, expected.nodeValue,
+ msg + 'First difference: differing nodeValue (nodeName = "' + actual.nodeName + '")');
+ assert_equals(actual.childNodes.length, expected.childNodes.length,
+ msg + 'First difference: differing number of children (nodeName = "' + actual.nodeName + '")');
+ actual = nextNode(actual);
+ expected = nextNode(expected);
+ }
+
+ assert_unreached("DOMs were not equal but we couldn't figure out why");
+ }
+
+ if (j == 0) {
+ // Clearly something is wrong if the node lists are different
+ // lengths. We want to report this only after we've already
+ // checked the main tree for equality, though, so it doesn't
+ // mask more interesting errors.
+ assert_equals(actualRoots.length, expectedRoots.length,
+ "Actual and expected DOMs were broken up into a different number of pieces by deleteContents() (this probably means you created or detached nodes when you weren't supposed to)");
+ }
+ }
+ });
+ domTests[i].done();
+
+ positionTests[i].step(function() {
+ assert_equals(actualIframe.contentWindow.unexpectedException, null,
+ "Unexpected exception thrown when setting up Range for actual deleteContents()");
+ assert_equals(expectedIframe.contentWindow.unexpectedException, null,
+ "Unexpected exception thrown when setting up Range for simulated deleteContents()");
+ assert_equals(typeof actualRange, "object",
+ "typeof Range produced in actual iframe");
+ assert_equals(typeof expectedRange, "object",
+ "typeof Range produced in expected iframe");
+ assert_true(actualRoots[0].isEqualNode(expectedRoots[0]),
+ "The resulting DOMs were not equal, so comparing positions makes no sense");
+
+ assert_equals(actualRange.startContainer, actualRange.endContainer,
+ "startContainer and endContainer must always be the same after deleteContents()");
+ assert_equals(actualRange.startOffset, actualRange.endOffset,
+ "startOffset and endOffset must always be the same after deleteContents()");
+ assert_equals(expectedRange.startContainer, expectedRange.endContainer,
+ "Test bug! Expected startContainer and endContainer must always be the same after deleteContents()");
+ assert_equals(expectedRange.startOffset, expectedRange.endOffset,
+ "Test bug! Expected startOffset and endOffset must always be the same after deleteContents()");
+
+ assert_equals(actualRange.startOffset, expectedRange.startOffset,
+ "Unexpected startOffset after deleteContents()");
+ // How do we decide that the two nodes are equal, since they're in
+ // different trees? Since the DOMs are the same, it's enough to check
+ // that the index in the parent is the same all the way up the tree.
+ // But we can first cheat by just checking they're actually equal.
+ assert_true(actualRange.startContainer.isEqualNode(expectedRange.startContainer),
+ "Unexpected startContainer after deleteContents(), expected " +
+ expectedRange.startContainer.nodeName.toLowerCase() + " but got " +
+ actualRange.startContainer.nodeName.toLowerCase());
+ var currentActual = actualRange.startContainer;
+ var currentExpected = expectedRange.startContainer;
+ var actual = "";
+ var expected = "";
+ while (currentActual && currentExpected) {
+ actual = indexOf(currentActual) + "-" + actual;
+ expected = indexOf(currentExpected) + "-" + expected;
+
+ currentActual = currentActual.parentNode;
+ currentExpected = currentExpected.parentNode;
+ }
+ actual = actual.substr(0, actual.length - 1);
+ expected = expected.substr(0, expected.length - 1);
+ assert_equals(actual, expected,
+ "startContainer superficially looks right but is actually the wrong node if you trace back its index in all its ancestors (I'm surprised this actually happened");
+ });
+ positionTests[i].done();
+}
+
+// First test a detached Range, synchronously
+test(function() {
+ var range = document.createRange();
+ range.detach();
+ range.deleteContents();
+}, "Detached Range");
+
+var iStart = 0;
+var iStop = testRanges.length;
+
+if (/subtest=[0-9]+/.test(location.search)) {
+ var matches = /subtest=([0-9]+)/.exec(location.search);
+ iStart = Number(matches[1]);
+ iStop = Number(matches[1]) + 1;
+}
+
+var domTests = [];
+var positionTests = [];
+
+for (var i = iStart; i < iStop; i++) {
+ domTests[i] = async_test("Resulting DOM for range " + i + " " + testRanges[i]);
+ positionTests[i] = async_test("Resulting cursor position for range " + i + " " + testRanges[i]);
+}
+
+var referenceDoc = document.implementation.createHTMLDocument("");
+referenceDoc.removeChild(referenceDoc.documentElement);
+
+actualIframe.onload = function() {
+ expectedIframe.onload = function() {
+ for (var i = iStart; i < iStop; i++) {
+ testDeleteContents(i);
+ }
+ }
+ expectedIframe.src = "Range-test-iframe.html";
+ referenceDoc.appendChild(actualIframe.contentDocument.documentElement.cloneNode(true));
+}
+actualIframe.src = "Range-test-iframe.html";
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/ranges/Range-detach.html b/tests/wpt/web-platform-tests/dom/ranges/Range-detach.html
new file mode 100644
index 00000000000..ac35d71369a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/ranges/Range-detach.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<title>Range.detach</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<meta name=timeout content=long>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function() {
+ var r = document.createRange();
+ r.detach()
+ r.detach()
+})
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/ranges/Range-extractContents.html b/tests/wpt/web-platform-tests/dom/ranges/Range-extractContents.html
new file mode 100644
index 00000000000..098837f0ce5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/ranges/Range-extractContents.html
@@ -0,0 +1,248 @@
+<!doctype html>
+<title>Range.extractContents() tests</title>
+<link rel="author" title="Aryeh Gregor" href=ayg@aryeh.name>
+<meta name=timeout content=long>
+<p>To debug test failures, add a query parameter "subtest" with the test id (like
+"?subtest=5"). Only that test will be run. Then you can look at the resulting
+iframe in the DOM.
+<div id=log></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../common.js></script>
+<script>
+"use strict";
+
+testDiv.parentNode.removeChild(testDiv);
+
+var actualIframe = document.createElement("iframe");
+actualIframe.style.display = "none";
+document.body.appendChild(actualIframe);
+
+var expectedIframe = document.createElement("iframe");
+expectedIframe.style.display = "none";
+document.body.appendChild(expectedIframe);
+
+function restoreIframe(iframe, i) {
+ // Most of this function is designed to work around the fact that Opera
+ // doesn't let you add a doctype to a document that no longer has one, in
+ // any way I can figure out. I eventually compromised on something that
+ // will still let Opera pass most tests that don't actually involve
+ // doctypes.
+ while (iframe.contentDocument.firstChild
+ && iframe.contentDocument.firstChild.nodeType != Node.DOCUMENT_TYPE_NODE) {
+ iframe.contentDocument.removeChild(iframe.contentDocument.firstChild);
+ }
+
+ while (iframe.contentDocument.lastChild
+ && iframe.contentDocument.lastChild.nodeType != Node.DOCUMENT_TYPE_NODE) {
+ iframe.contentDocument.removeChild(iframe.contentDocument.lastChild);
+ }
+
+ if (!iframe.contentDocument.firstChild) {
+ // This will throw an exception in Opera if we reach here, which is why
+ // I try to avoid it. It will never happen in a browser that obeys the
+ // spec, so it's really just insurance. I don't think it actually gets
+ // hit by anything.
+ iframe.contentDocument.appendChild(iframe.contentDocument.implementation.createDocumentType("html", "", ""));
+ }
+ iframe.contentDocument.appendChild(referenceDoc.documentElement.cloneNode(true));
+ iframe.contentWindow.setupRangeTests();
+ iframe.contentWindow.testRangeInput = testRanges[i];
+ iframe.contentWindow.run();
+}
+
+function testExtractContents(i) {
+ restoreIframe(actualIframe, i);
+ restoreIframe(expectedIframe, i);
+
+ var actualRange = actualIframe.contentWindow.testRange;
+ var expectedRange = expectedIframe.contentWindow.testRange;
+ var actualFrag, expectedFrag;
+ var actualRoots, expectedRoots;
+
+ domTests[i].step(function() {
+ assert_equals(actualIframe.contentWindow.unexpectedException, null,
+ "Unexpected exception thrown when setting up Range for actual extractContents()");
+ assert_equals(expectedIframe.contentWindow.unexpectedException, null,
+ "Unexpected exception thrown when setting up Range for simulated extractContents()");
+ assert_equals(typeof actualRange, "object",
+ "typeof Range produced in actual iframe");
+ assert_equals(typeof expectedRange, "object",
+ "typeof Range produced in expected iframe");
+
+ // Just to be pedantic, we'll test not only that the tree we're
+ // modifying is the same in expected vs. actual, but also that all the
+ // nodes originally in it were the same. Typically some nodes will
+ // become detached when the algorithm is run, but they still exist and
+ // references can still be kept to them, so they should also remain the
+ // same.
+ //
+ // We initialize the list to all nodes, and later on remove all the
+ // ones which still have parents, since the parents will presumably be
+ // tested for isEqualNode() and checking the children would be
+ // redundant.
+ var actualAllNodes = [];
+ var node = furthestAncestor(actualRange.startContainer);
+ do {
+ actualAllNodes.push(node);
+ } while (node = nextNode(node));
+
+ var expectedAllNodes = [];
+ var node = furthestAncestor(expectedRange.startContainer);
+ do {
+ expectedAllNodes.push(node);
+ } while (node = nextNode(node));
+
+ expectedFrag = myExtractContents(expectedRange);
+ if (typeof expectedFrag == "string") {
+ assert_throws(expectedFrag, function() {
+ actualRange.extractContents();
+ });
+ } else {
+ actualFrag = actualRange.extractContents();
+ }
+
+ actualRoots = [];
+ for (var j = 0; j < actualAllNodes.length; j++) {
+ if (!actualAllNodes[j].parentNode) {
+ actualRoots.push(actualAllNodes[j]);
+ }
+ }
+
+ expectedRoots = [];
+ for (var j = 0; j < expectedAllNodes.length; j++) {
+ if (!expectedAllNodes[j].parentNode) {
+ expectedRoots.push(expectedAllNodes[j]);
+ }
+ }
+
+ for (var j = 0; j < actualRoots.length; j++) {
+ assertNodesEqual(actualRoots[j], expectedRoots[j], j ? "detached node #" + j : "tree root");
+
+ if (j == 0) {
+ // Clearly something is wrong if the node lists are different
+ // lengths. We want to report this only after we've already
+ // checked the main tree for equality, though, so it doesn't
+ // mask more interesting errors.
+ assert_equals(actualRoots.length, expectedRoots.length,
+ "Actual and expected DOMs were broken up into a different number of pieces by extractContents() (this probably means you created or detached nodes when you weren't supposed to)");
+ }
+ }
+ });
+ domTests[i].done();
+
+ positionTests[i].step(function() {
+ assert_equals(actualIframe.contentWindow.unexpectedException, null,
+ "Unexpected exception thrown when setting up Range for actual extractContents()");
+ assert_equals(expectedIframe.contentWindow.unexpectedException, null,
+ "Unexpected exception thrown when setting up Range for simulated extractContents()");
+ assert_equals(typeof actualRange, "object",
+ "typeof Range produced in actual iframe");
+ assert_equals(typeof expectedRange, "object",
+ "typeof Range produced in expected iframe");
+
+ assert_true(actualRoots[0].isEqualNode(expectedRoots[0]),
+ "The resulting DOMs were not equal, so comparing positions makes no sense");
+
+ if (typeof expectedFrag == "string") {
+ // It's no longer true that, e.g., startContainer and endContainer
+ // must always be the same
+ return;
+ }
+ assert_equals(actualRange.startContainer, actualRange.endContainer,
+ "startContainer and endContainer must always be the same after extractContents()");
+ assert_equals(actualRange.startOffset, actualRange.endOffset,
+ "startOffset and endOffset must always be the same after extractContents()");
+ assert_equals(expectedRange.startContainer, expectedRange.endContainer,
+ "Test bug! Expected startContainer and endContainer must always be the same after extractContents()");
+ assert_equals(expectedRange.startOffset, expectedRange.endOffset,
+ "Test bug! Expected startOffset and endOffset must always be the same after extractContents()");
+
+ assert_equals(actualRange.startOffset, expectedRange.startOffset,
+ "Unexpected startOffset after extractContents()");
+ // How do we decide that the two nodes are equal, since they're in
+ // different trees? Since the DOMs are the same, it's enough to check
+ // that the index in the parent is the same all the way up the tree.
+ // But we can first cheat by just checking they're actually equal.
+ assert_true(actualRange.startContainer.isEqualNode(expectedRange.startContainer),
+ "Unexpected startContainer after extractContents(), expected " +
+ expectedRange.startContainer.nodeName.toLowerCase() + " but got " +
+ actualRange.startContainer.nodeName.toLowerCase());
+ var currentActual = actualRange.startContainer;
+ var currentExpected = expectedRange.startContainer;
+ var actual = "";
+ var expected = "";
+ while (currentActual && currentExpected) {
+ actual = indexOf(currentActual) + "-" + actual;
+ expected = indexOf(currentExpected) + "-" + expected;
+
+ currentActual = currentActual.parentNode;
+ currentExpected = currentExpected.parentNode;
+ }
+ actual = actual.substr(0, actual.length - 1);
+ expected = expected.substr(0, expected.length - 1);
+ assert_equals(actual, expected,
+ "startContainer superficially looks right but is actually the wrong node if you trace back its index in all its ancestors (I'm surprised this actually happened");
+ });
+ positionTests[i].done();
+
+ fragTests[i].step(function() {
+ assert_equals(actualIframe.contentWindow.unexpectedException, null,
+ "Unexpected exception thrown when setting up Range for actual extractContents()");
+ assert_equals(expectedIframe.contentWindow.unexpectedException, null,
+ "Unexpected exception thrown when setting up Range for simulated extractContents()");
+ assert_equals(typeof actualRange, "object",
+ "typeof Range produced in actual iframe");
+ assert_equals(typeof expectedRange, "object",
+ "typeof Range produced in expected iframe");
+
+ if (typeof expectedFrag == "string") {
+ // Comparing makes no sense
+ return;
+ }
+ assertNodesEqual(actualFrag, expectedFrag,
+ "returned fragment");
+ });
+ fragTests[i].done();
+}
+
+// First test a detached Range, synchronously
+test(function() {
+ var range = document.createRange();
+ range.detach();
+ assert_array_equals(range.extractContents().childNodes, []);
+}, "Detached Range");
+
+var iStart = 0;
+var iStop = testRanges.length;
+
+if (/subtest=[0-9]+/.test(location.search)) {
+ var matches = /subtest=([0-9]+)/.exec(location.search);
+ iStart = Number(matches[1]);
+ iStop = Number(matches[1]) + 1;
+}
+
+var domTests = [];
+var positionTests = [];
+var fragTests = [];
+
+for (var i = iStart; i < iStop; i++) {
+ domTests[i] = async_test("Resulting DOM for range " + i + " " + testRanges[i]);
+ positionTests[i] = async_test("Resulting cursor position for range " + i + " " + testRanges[i]);
+ fragTests[i] = async_test("Returned fragment for range " + i + " " + testRanges[i]);
+}
+
+var referenceDoc = document.implementation.createHTMLDocument("");
+referenceDoc.removeChild(referenceDoc.documentElement);
+
+actualIframe.onload = function() {
+ expectedIframe.onload = function() {
+ for (var i = iStart; i < iStop; i++) {
+ testExtractContents(i);
+ }
+ }
+ expectedIframe.src = "Range-test-iframe.html";
+ referenceDoc.appendChild(actualIframe.contentDocument.documentElement.cloneNode(true));
+}
+actualIframe.src = "Range-test-iframe.html";
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/ranges/Range-insertNode.html b/tests/wpt/web-platform-tests/dom/ranges/Range-insertNode.html
new file mode 100644
index 00000000000..4c4073b2156
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/ranges/Range-insertNode.html
@@ -0,0 +1,286 @@
+<!doctype html>
+<title>Range.insertNode() tests</title>
+<link rel="author" title="Aryeh Gregor" href=ayg@aryeh.name>
+<meta name=timeout content=long>
+<p>To debug test failures, add a query parameter "subtest" with the test id (like
+"?subtest=5,16"). Only that test will be run. Then you can look at the resulting
+iframes in the DOM.
+<div id=log></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../common.js></script>
+<script>
+"use strict";
+
+testDiv.parentNode.removeChild(testDiv);
+
+function restoreIframe(iframe, i, j) {
+ // Most of this function is designed to work around the fact that Opera
+ // doesn't let you add a doctype to a document that no longer has one, in
+ // any way I can figure out. I eventually compromised on something that
+ // will still let Opera pass most tests that don't actually involve
+ // doctypes.
+ while (iframe.contentDocument.firstChild
+ && iframe.contentDocument.firstChild.nodeType != Node.DOCUMENT_TYPE_NODE) {
+ iframe.contentDocument.removeChild(iframe.contentDocument.firstChild);
+ }
+
+ while (iframe.contentDocument.lastChild
+ && iframe.contentDocument.lastChild.nodeType != Node.DOCUMENT_TYPE_NODE) {
+ iframe.contentDocument.removeChild(iframe.contentDocument.lastChild);
+ }
+
+ if (!iframe.contentDocument.firstChild) {
+ // This will throw an exception in Opera if we reach here, which is why
+ // I try to avoid it. It will never happen in a browser that obeys the
+ // spec, so it's really just insurance. I don't think it actually gets
+ // hit by anything.
+ iframe.contentDocument.appendChild(iframe.contentDocument.implementation.createDocumentType("html", "", ""));
+ }
+ iframe.contentDocument.appendChild(referenceDoc.documentElement.cloneNode(true));
+ iframe.contentWindow.setupRangeTests();
+ iframe.contentWindow.testRangeInput = testRangesShort[i];
+ iframe.contentWindow.testNodeInput = testNodesShort[j];
+ iframe.contentWindow.run();
+}
+
+function testInsertNode(i, j) {
+ var actualRange;
+ var expectedRange;
+ var actualNode;
+ var expectedNode;
+ var actualRoots = [];
+ var expectedRoots = [];
+
+ var detached = false;
+
+ domTests[i][j].step(function() {
+ restoreIframe(actualIframe, i, j);
+ restoreIframe(expectedIframe, i, j);
+
+ actualRange = actualIframe.contentWindow.testRange;
+ expectedRange = expectedIframe.contentWindow.testRange;
+ actualNode = actualIframe.contentWindow.testNode;
+ expectedNode = expectedIframe.contentWindow.testNode;
+
+ try {
+ actualRange.collapsed;
+ } catch (e) {
+ detached = true;
+ }
+
+ assert_equals(actualIframe.contentWindow.unexpectedException, null,
+ "Unexpected exception thrown when setting up Range for actual insertNode()");
+ assert_equals(expectedIframe.contentWindow.unexpectedException, null,
+ "Unexpected exception thrown when setting up Range for simulated insertNode()");
+ assert_equals(typeof actualRange, "object",
+ "typeof Range produced in actual iframe");
+ assert_false(actualRange === null,
+ "Range produced in actual iframe was null");
+ assert_equals(typeof expectedRange, "object",
+ "typeof Range produced in expected iframe");
+ assert_false(expectedRange === null,
+ "Range produced in expected iframe was null");
+ assert_equals(typeof actualNode, "object",
+ "typeof Node produced in actual iframe");
+ assert_false(actualNode === null,
+ "Node produced in actual iframe was null");
+ assert_equals(typeof expectedNode, "object",
+ "typeof Node produced in expected iframe");
+ assert_false(expectedNode === null,
+ "Node produced in expected iframe was null");
+
+ // We want to test that the trees containing the ranges are equal, and
+ // also the trees containing the moved nodes. These might not be the
+ // same, if we're inserting a node from a detached tree or a different
+ // document.
+ //
+ // Detached ranges are always in the contentDocument.
+ if (detached) {
+ actualRoots.push(actualIframe.contentDocument);
+ expectedRoots.push(expectedIframe.contentDocument);
+ } else {
+ actualRoots.push(furthestAncestor(actualRange.startContainer));
+ expectedRoots.push(furthestAncestor(expectedRange.startContainer));
+ }
+
+ if (furthestAncestor(actualNode) != actualRoots[0]) {
+ actualRoots.push(furthestAncestor(actualNode));
+ }
+ if (furthestAncestor(expectedNode) != expectedRoots[0]) {
+ expectedRoots.push(furthestAncestor(expectedNode));
+ }
+
+ assert_equals(actualRoots.length, expectedRoots.length,
+ "Either the actual node and actual range are in the same tree but the expected are in different trees, or vice versa");
+
+ // This doctype stuff is to work around the fact that Opera 11.00 will
+ // move around doctypes within a document, even to totally invalid
+ // positions, but it won't allow a new doctype to be added to a
+ // document in any way I can figure out. So if we try moving a doctype
+ // to some invalid place, in Opera it will actually succeed, and then
+ // restoreIframe() will remove the doctype along with the root element,
+ // and then nothing can re-add the doctype. So instead, we catch it
+ // during the test itself and move it back to the right place while we
+ // still can.
+ //
+ // I spent *way* too much time debugging and working around this bug.
+ var actualDoctype = actualIframe.contentDocument.doctype;
+ var expectedDoctype = expectedIframe.contentDocument.doctype;
+
+ var result;
+ try {
+ result = myInsertNode(expectedRange, expectedNode);
+ } catch (e) {
+ if (expectedDoctype != expectedIframe.contentDocument.firstChild) {
+ expectedIframe.contentDocument.insertBefore(expectedDoctype, expectedIframe.contentDocument.firstChild);
+ }
+ throw e;
+ }
+ if (typeof result == "string") {
+ assert_throws(result, function() {
+ try {
+ actualRange.insertNode(actualNode);
+ } catch (e) {
+ if (expectedDoctype != expectedIframe.contentDocument.firstChild) {
+ expectedIframe.contentDocument.insertBefore(expectedDoctype, expectedIframe.contentDocument.firstChild);
+ }
+ if (actualDoctype != actualIframe.contentDocument.firstChild) {
+ actualIframe.contentDocument.insertBefore(actualDoctype, actualIframe.contentDocument.firstChild);
+ }
+ throw e;
+ }
+ }, "A " + result + " DOMException must be thrown in this case");
+ // Don't return, we still need to test DOM equality
+ } else {
+ try {
+ actualRange.insertNode(actualNode);
+ } catch (e) {
+ if (expectedDoctype != expectedIframe.contentDocument.firstChild) {
+ expectedIframe.contentDocument.insertBefore(expectedDoctype, expectedIframe.contentDocument.firstChild);
+ }
+ if (actualDoctype != actualIframe.contentDocument.firstChild) {
+ actualIframe.contentDocument.insertBefore(actualDoctype, actualIframe.contentDocument.firstChild);
+ }
+ throw e;
+ }
+ }
+
+ for (var k = 0; k < actualRoots.length; k++) {
+ assertNodesEqual(actualRoots[k], expectedRoots[k], k ? "moved node's tree root" : "range's tree root");
+ }
+ });
+ domTests[i][j].done();
+
+ positionTests[i][j].step(function() {
+ assert_equals(actualIframe.contentWindow.unexpectedException, null,
+ "Unexpected exception thrown when setting up Range for actual insertNode()");
+ assert_equals(expectedIframe.contentWindow.unexpectedException, null,
+ "Unexpected exception thrown when setting up Range for simulated insertNode()");
+ assert_equals(typeof actualRange, "object",
+ "typeof Range produced in actual iframe");
+ assert_false(actualRange === null,
+ "Range produced in actual iframe was null");
+ assert_equals(typeof expectedRange, "object",
+ "typeof Range produced in expected iframe");
+ assert_false(expectedRange === null,
+ "Range produced in expected iframe was null");
+ assert_equals(typeof actualNode, "object",
+ "typeof Node produced in actual iframe");
+ assert_false(actualNode === null,
+ "Node produced in actual iframe was null");
+ assert_equals(typeof expectedNode, "object",
+ "typeof Node produced in expected iframe");
+ assert_false(expectedNode === null,
+ "Node produced in expected iframe was null");
+
+ for (var k = 0; k < actualRoots.length; k++) {
+ assertNodesEqual(actualRoots[k], expectedRoots[k], k ? "moved node's tree root" : "range's tree root");
+ }
+
+ if (detached) {
+ // No further tests we can do
+ return;
+ }
+
+ assert_equals(actualRange.startOffset, expectedRange.startOffset,
+ "Unexpected startOffset after insertNode()");
+ assert_equals(actualRange.endOffset, expectedRange.endOffset,
+ "Unexpected endOffset after insertNode()");
+ // How do we decide that the two nodes are equal, since they're in
+ // different trees? Since the DOMs are the same, it's enough to check
+ // that the index in the parent is the same all the way up the tree.
+ // But we can first cheat by just checking they're actually equal.
+ assert_true(actualRange.startContainer.isEqualNode(expectedRange.startContainer),
+ "Unexpected startContainer after insertNode(), expected " +
+ expectedRange.startContainer.nodeName.toLowerCase() + " but got " +
+ actualRange.startContainer.nodeName.toLowerCase());
+ var currentActual = actualRange.startContainer;
+ var currentExpected = expectedRange.startContainer;
+ var actual = "";
+ var expected = "";
+ while (currentActual && currentExpected) {
+ actual = indexOf(currentActual) + "-" + actual;
+ expected = indexOf(currentExpected) + "-" + expected;
+
+ currentActual = currentActual.parentNode;
+ currentExpected = currentExpected.parentNode;
+ }
+ actual = actual.substr(0, actual.length - 1);
+ expected = expected.substr(0, expected.length - 1);
+ assert_equals(actual, expected,
+ "startContainer superficially looks right but is actually the wrong node if you trace back its index in all its ancestors (I'm surprised this actually happened");
+ });
+ positionTests[i][j].done();
+}
+
+testRanges.unshift('"detached"');
+
+var iStart = 0;
+var iStop = testRangesShort.length;
+var jStart = 0;
+var jStop = testNodesShort.length;
+
+if (/subtest=[0-9]+,[0-9]+/.test(location.search)) {
+ var matches = /subtest=([0-9]+),([0-9]+)/.exec(location.search);
+ iStart = Number(matches[1]);
+ iStop = Number(matches[1]) + 1;
+ jStart = Number(matches[2]) + 0;
+ jStop = Number(matches[2]) + 1;
+}
+
+var domTests = [];
+var positionTests = [];
+for (var i = iStart; i < iStop; i++) {
+ domTests[i] = [];
+ positionTests[i] = [];
+ for (var j = jStart; j < jStop; j++) {
+ domTests[i][j] = async_test(i + "," + j + ": resulting DOM for range " + testRangesShort[i] + ", node " + testNodesShort[j]);
+ positionTests[i][j] = async_test(i + "," + j + ": resulting range position for range " + testRangesShort[i] + ", node " + testNodesShort[j]);
+ }
+}
+
+var actualIframe = document.createElement("iframe");
+actualIframe.style.display = "none";
+document.body.appendChild(actualIframe);
+
+var expectedIframe = document.createElement("iframe");
+expectedIframe.style.display = "none";
+document.body.appendChild(expectedIframe);
+
+var referenceDoc = document.implementation.createHTMLDocument("");
+referenceDoc.removeChild(referenceDoc.documentElement);
+
+actualIframe.onload = function() {
+ expectedIframe.onload = function() {
+ for (var i = iStart; i < iStop; i++) {
+ for (var j = jStart; j < jStop; j++) {
+ testInsertNode(i, j);
+ }
+ }
+ }
+ expectedIframe.src = "Range-test-iframe.html";
+ referenceDoc.appendChild(actualIframe.contentDocument.documentElement.cloneNode(true));
+}
+actualIframe.src = "Range-test-iframe.html";
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/ranges/Range-intersectsNode-binding.html b/tests/wpt/web-platform-tests/dom/ranges/Range-intersectsNode-binding.html
new file mode 100644
index 00000000000..729388428ec
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/ranges/Range-intersectsNode-binding.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<title>Range.intersectsNode</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<meta name=timeout content=long>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function() {
+ var r = document.createRange();
+ assert_throws(new TypeError(), function() { r.intersectsNode(); });
+ assert_throws(new TypeError(), function() { r.intersectsNode(null); });
+ assert_throws(new TypeError(), function() { r.intersectsNode(undefined); });
+ assert_throws(new TypeError(), function() { r.intersectsNode(42); });
+ assert_throws(new TypeError(), function() { r.intersectsNode("foo"); });
+ assert_throws(new TypeError(), function() { r.intersectsNode({}); });
+ r.detach();
+ assert_throws(new TypeError(), function() { r.intersectsNode(); });
+ assert_throws(new TypeError(), function() { r.intersectsNode(null); });
+ assert_throws(new TypeError(), function() { r.intersectsNode(undefined); });
+ assert_throws(new TypeError(), function() { r.intersectsNode(42); });
+ assert_throws(new TypeError(), function() { r.intersectsNode("foo"); });
+ assert_throws(new TypeError(), function() { r.intersectsNode({}); });
+}, "Calling intersectsNode without an argument or with an invalid argument should throw a TypeError.")
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/ranges/Range-intersectsNode.html b/tests/wpt/web-platform-tests/dom/ranges/Range-intersectsNode.html
new file mode 100644
index 00000000000..3a0e1635a3b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/ranges/Range-intersectsNode.html
@@ -0,0 +1,78 @@
+<!doctype html>
+<title>Range.intersectsNode() tests</title>
+<link rel="author" title="Aryeh Gregor" href=ayg@aryeh.name>
+<meta name=timeout content=long>
+<div id=log></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../common.js></script>
+<script>
+"use strict";
+
+// Will be filled in on the first run for that range
+var testRangesCached = [];
+
+for (var i = 0; i < testNodes.length; i++) {
+ var node = eval(testNodes[i]);
+
+ // "If the detached flag is set, throw an "InvalidStateError" exception and
+ // terminate these steps."
+ test(function() {
+ var range = document.createRange();
+ range.detach();
+ assert_equals(range.intersectsNode(node), node === document);
+ }, "Node " + i + " " + testNodes[i] + ", detached range");
+
+ for (var j = 0; j < testRanges.length; j++) {
+ test(function() {
+ if (testRangesCached[j] === undefined) {
+ try {
+ testRangesCached[j] = rangeFromEndpoints(eval(testRanges[i]));
+ } catch(e) {
+ testRangesCached[j] = null;
+ }
+ }
+ assert_not_equals(testRangesCached[j], null,
+ "Setting up the range failed");
+
+ var range = testRangesCached[j].cloneRange();
+
+ // "If node's root is different from the context object's root,
+ // return false and terminate these steps."
+ if (furthestAncestor(node) !== furthestAncestor(range.startContainer)) {
+ assert_equals(range.intersectsNode(node), false,
+ "Must return false if node and range have different roots");
+ return;
+ }
+
+ // "Let parent be node's parent."
+ var parent_ = node.parentNode;
+
+ // "If parent is null, return true and terminate these steps."
+ if (!parent_) {
+ assert_equals(range.intersectsNode(node), true,
+ "Must return true if node's parent is null");
+ return;
+ }
+
+ // "Let offset be node's index."
+ var offset = indexOf(node);
+
+ // "If (parent, offset) is before end and (parent, offset + 1) is
+ // after start, return true and terminate these steps."
+ if (getPosition(parent_, offset, range.endContainer, range.endOffset) === "before"
+ && getPosition(parent_, offset + 1, range.startContainer, range.startOffset) === "after") {
+ assert_equals(range.intersectsNode(node), true,
+ "Must return true if (parent, offset) is before range end and (parent, offset + 1) is after range start");
+ return;
+ }
+
+ // "Return false."
+ assert_equals(range.intersectsNode(node), false,
+ "Must return false if (parent, offset) is not before range end or (parent, offset + 1) is not after range start");
+ }, "Node " + i + " " + testNodes[i] + ", range " + j + " " + testRanges[j]);
+ }
+}
+
+testDiv.style.display = "none";
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/ranges/Range-isPointInRange.html b/tests/wpt/web-platform-tests/dom/ranges/Range-isPointInRange.html
new file mode 100644
index 00000000000..fa87442b8ab
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/ranges/Range-isPointInRange.html
@@ -0,0 +1,83 @@
+<!doctype html>
+<title>Range.isPointInRange() tests</title>
+<link rel="author" title="Aryeh Gregor" href=ayg@aryeh.name>
+<meta name=timeout content=long>
+<div id=log></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../common.js></script>
+<script>
+"use strict";
+
+var testRangesCached = [];
+test(function() {
+ for (var j = 0; j < testRanges.length; j++) {
+ test(function() {
+ testRangesCached[j] = rangeFromEndpoints(eval(testRanges[j]));
+ }, "Set up for range " + j + " " + testRanges[j]);
+ }
+ var detachedRange = document.createRange();
+ detachedRange.detach();
+ testRanges.push("detached");
+ testRangesCached.push(detachedRange);
+}, "Setup");
+
+for (var i = 0; i < testPoints.length; i++) {
+ var node = eval(testPoints[i])[0];
+ var offset = eval(testPoints[i])[1];
+
+ // isPointInRange is an unsigned long, so per WebIDL, we need to treat it
+ // as though it wrapped to an unsigned 32-bit integer.
+ var normalizedOffset = offset % Math.pow(2, 32);
+ if (normalizedOffset < 0) {
+ normalizedOffset += Math.pow(2, 32);
+ }
+
+ for (var j = 0; j < testRanges.length; j++) {
+ test(function() {
+ var range = testRangesCached[j].cloneRange();
+
+ // "If node's root is different from the context object's root,
+ // return false and terminate these steps."
+ if (furthestAncestor(node) !== furthestAncestor(range.startContainer)) {
+ assert_false(range.isPointInRange(node, offset),
+ "Must return false if node has a different root from the context object");
+ return;
+ }
+
+ // "If node is a doctype, throw an "InvalidNodeTypeError" exception
+ // and terminate these steps."
+ if (node.nodeType == Node.DOCUMENT_TYPE_NODE) {
+ assert_throws("INVALID_NODE_TYPE_ERR", function() {
+ range.isPointInRange(node, offset);
+ }, "Must throw InvalidNodeTypeError if node is a doctype");
+ return;
+ }
+
+ // "If offset is greater than node's length, throw an
+ // "IndexSizeError" exception and terminate these steps."
+ if (normalizedOffset > nodeLength(node)) {
+ assert_throws("INDEX_SIZE_ERR", function() {
+ range.isPointInRange(node, offset);
+ }, "Must throw IndexSizeError if offset is greater than length");
+ return;
+ }
+
+ // "If (node, offset) is before start or after end, return false
+ // and terminate these steps."
+ if (getPosition(node, normalizedOffset, range.startContainer, range.startOffset) === "before"
+ || getPosition(node, normalizedOffset, range.endContainer, range.endOffset) === "after") {
+ assert_false(range.isPointInRange(node, offset),
+ "Must return false if point is before start or after end");
+ return;
+ }
+
+ // "Return true."
+ assert_true(range.isPointInRange(node, offset),
+ "Must return true if point is not before start, after end, or in different tree");
+ }, "Point " + i + " " + testPoints[i] + ", range " + j + " " + testRanges[j]);
+ }
+}
+
+testDiv.style.display = "none";
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/ranges/Range-mutations.html b/tests/wpt/web-platform-tests/dom/ranges/Range-mutations.html
new file mode 100644
index 00000000000..aa740d4a6aa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/ranges/Range-mutations.html
@@ -0,0 +1,959 @@
+<!doctype html>
+<title>Range mutation tests</title>
+<link rel="author" title="Aryeh Gregor" href=ayg@aryeh.name>
+<meta name=timeout content=long>
+
+<div id=log></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../common.js></script>
+<script>
+"use strict";
+
+// These tests probably use too much abstraction and too little copy-paste.
+// Reader beware.
+//
+// TODO:
+//
+// * replaceWholeText() tests
+// * Lots and lots and lots more different types of ranges
+// * insertBefore() with DocumentFragments
+// * Fill out other insert/remove tests
+// * normalize() (https://www.w3.org/Bugs/Public/show_bug.cgi?id=13843)
+
+// Give a textual description of the range we're testing, for the test names.
+function describeRange(startContainer, startOffset, endContainer, endOffset) {
+ if (startContainer == endContainer && startOffset == endOffset) {
+ return "range collapsed at (" + startContainer + ", " + startOffset + ")";
+ } else if (startContainer == endContainer) {
+ return "range on " + startContainer + " from " + startOffset + " to " + endOffset;
+ } else {
+ return "range from (" + startContainer + ", " + startOffset + ") to (" + endContainer + ", " + endOffset + ")";
+ }
+}
+
+// Lists of the various types of nodes we'll want to use. We use strings that
+// we can later eval(), so that we can produce legible test names.
+var textNodes = [
+ "paras[0].firstChild",
+ "paras[1].firstChild",
+ "foreignTextNode",
+ "xmlTextNode",
+ "detachedTextNode",
+ "detachedForeignTextNode",
+ "detachedXmlTextNode",
+];
+var commentNodes = [
+ "comment",
+ "foreignComment",
+ "xmlComment",
+ "detachedComment",
+ "detachedForeignComment",
+ "detachedXmlComment",
+];
+var characterDataNodes = textNodes.concat(commentNodes);
+
+// This function is slightly scary, but it works well enough, so . . .
+// sourceTests is an array of test data that will be altered in mysterious ways
+// before being passed off to doTest, descFn is something that takes an element
+// of sourceTests and produces the first part of a human-readable description
+// of the test, testFn is the function that doTest will call to do the actual
+// work and tell it what results to expect.
+function doTests(sourceTests, descFn, testFn) {
+ var tests = [];
+ for (var i = 0; i < sourceTests.length; i++) {
+ var params = sourceTests[i];
+ var len = params.length;
+ tests.push([
+ descFn(params) + ", with unselected " + describeRange(params[len - 4], params[len - 3], params[len - 2], params[len - 1]),
+ // The closure here ensures that the params that testFn get are the
+ // current version of params, not the version from the last
+ // iteration of this loop. We test that none of the parameters
+ // evaluate to undefined to catch bugs in our eval'ing, like
+ // mistyping a property name.
+ function(params) { return function() {
+ var evaledParams = params.map(eval);
+ for (var i = 0; i < evaledParams.length; i++) {
+ assert_true(typeof evaledParams[i] != "undefined",
+ "Test bug: " + params[i] + " is undefined");
+ }
+ return testFn.apply(null, evaledParams);
+ } }(params),
+ false,
+ params[len - 4],
+ params[len - 3],
+ params[len - 2],
+ params[len - 1]
+ ]);
+ tests.push([
+ descFn(params) + ", with selected " + describeRange(params[len - 4], params[len - 3], params[len - 2], params[len - 1]),
+ function(params) { return function() {
+ var evaledParams = params.map(eval);
+ for (var i = 0; i < evaledParams.length; i++) {
+ assert_true(typeof evaledParams[i] != "undefined",
+ "Test bug: " + params[i] + " is undefined");
+ }
+ return testFn.apply(null, evaledParams);
+ } }(params),
+ true,
+ params[len - 4],
+ params[len - 3],
+ params[len - 2],
+ params[len - 1]
+ ]);
+ }
+ generate_tests(doTest, tests);
+}
+
+// Set up the range, call the callback function to do the DOM modification and
+// tell us what to expect. The callback function needs to return a
+// four-element array with the expected start/end containers/offsets, and
+// receives no arguments. useSelection tells us whether the Range should be
+// added to a Selection and the Selection tested to ensure that the mutation
+// affects user selections as well as other ranges; every test is run with this
+// both false and true, because when it's set to true WebKit and Opera fail all
+// tests' sanity checks, which is unhelpful. The last four parameters just
+// tell us what range to build.
+function doTest(callback, useSelection, startContainer, startOffset, endContainer, endOffset) {
+ // Recreate all the test nodes in case they were altered by the last test
+ // run.
+ setupRangeTests();
+ startContainer = eval(startContainer);
+ startOffset = eval(startOffset);
+ endContainer = eval(endContainer);
+ endOffset = eval(endOffset);
+
+ var ownerDoc = startContainer.nodeType == Node.DOCUMENT_NODE
+ ? startContainer
+ : startContainer.ownerDocument;
+ var range = ownerDoc.createRange();
+ range.setStart(startContainer, startOffset);
+ range.setEnd(endContainer, endOffset);
+
+ if (useSelection) {
+ getSelection().removeAllRanges();
+ getSelection().addRange(range);
+
+ assert_equals(getSelection().rangeCount, 1,
+ "Sanity check: selection must have exactly one range after adding the range");
+ assert_equals(getSelection().getRangeAt(0), range,
+ "Sanity check: selection's range must initially be the same as the range we added");
+ assert_equals(range.startContainer, startContainer,
+ "Sanity check: range's startContainer must initially be the one we set");
+ assert_equals(range.endContainer, endContainer,
+ "Sanity check: range's endContainer must initially be the one we set");
+ assert_equals(range.startOffset, startOffset,
+ "Sanity check: range's startOffset must initially be the one we set");
+ assert_equals(range.endOffset, endOffset,
+ "Sanity check: range's endOffset must initially be the one we set");
+ }
+
+ var expected = callback();
+
+ if (useSelection) {
+ assert_equals(getSelection().getRangeAt(0), range,
+ "The range we added must not be removed from the selection");
+ }
+ assert_equals(range.startContainer, expected[0],
+ "Wrong start container");
+ assert_equals(range.startOffset, expected[1],
+ "Wrong start offset");
+ assert_equals(range.endContainer, expected[2],
+ "Wrong end container");
+ assert_equals(range.endOffset, expected[3],
+ "Wrong end offset");
+}
+
+
+// Now we get to the specific tests.
+
+function testSplitText(oldNode, offset, startContainer, startOffset, endContainer, endOffset) {
+ // Save these for later
+ var originalStartOffset = startOffset;
+ var originalEndOffset = endOffset;
+ var originalLength = oldNode.length;
+
+ var newNode;
+ try {
+ newNode = oldNode.splitText(offset);
+ } catch (e) {
+ // Should only happen if offset is negative
+ return [startContainer, startOffset, endContainer, endOffset];
+ }
+
+ // First we adjust for replacing data:
+ //
+ // "Replace data with offset offset, count count, and data the empty
+ // string."
+ //
+ // That translates to offset = offset, count = originalLength - offset,
+ // data = "". node is oldNode.
+ //
+ // "For every boundary point whose node is node, and whose offset is
+ // greater than offset but less than or equal to offset plus count, set its
+ // offset to offset."
+ if (startContainer == oldNode
+ && startOffset > offset
+ && startOffset <= originalLength) {
+ startOffset = offset;
+ }
+
+ if (endContainer == oldNode
+ && endOffset > offset
+ && endOffset <= originalLength) {
+ endOffset = offset;
+ }
+
+ // "For every boundary point whose node is node, and whose offset is
+ // greater than offset plus count, add the length of data to its offset,
+ // then subtract count from it."
+ //
+ // Can't happen: offset plus count is originalLength.
+
+ // Now we insert a node, if oldNode's parent isn't null: "For each boundary
+ // point whose node is the new parent of the affected node and whose offset
+ // is greater than the new index of the affected node, add one to the
+ // boundary point's offset."
+ if (startContainer == oldNode.parentNode
+ && startOffset > 1 + indexOf(oldNode)) {
+ startOffset++;
+ }
+
+ if (endContainer == oldNode.parentNode
+ && endOffset > 1 + indexOf(oldNode)) {
+ endOffset++;
+ }
+
+ // Finally, the splitText stuff itself:
+ //
+ // "If parent is not null, run these substeps:
+ //
+ // * "For each range whose start node is node and start offset is greater
+ // than offset, set its start node to new node and decrease its start
+ // offset by offset.
+ //
+ // * "For each range whose end node is node and end offset is greater
+ // than offset, set its end node to new node and decrease its end offset
+ // by offset.
+ //
+ // * "For each range whose start node is parent and start offset is equal
+ // to the index of node + 1, increase its start offset by one.
+ //
+ // * "For each range whose end node is parent and end offset is equal to
+ // the index of node + 1, increase its end offset by one."
+ if (oldNode.parentNode) {
+ if (startContainer == oldNode && originalStartOffset > offset) {
+ startContainer = newNode;
+ startOffset = originalStartOffset - offset;
+ }
+
+ if (endContainer == oldNode && originalEndOffset > offset) {
+ endContainer = newNode;
+ endOffset = originalEndOffset - offset;
+ }
+
+ if (startContainer == oldNode.parentNode
+ && startOffset == 1 + indexOf(oldNode)) {
+ startOffset++;
+ }
+
+ if (endContainer == oldNode.parentNode
+ && endOffset == 1 + indexOf(oldNode)) {
+ endOffset++;
+ }
+ }
+
+ return [startContainer, startOffset, endContainer, endOffset];
+}
+
+// The offset argument is unsigned, so per WebIDL -1 should wrap to 4294967295,
+// which is probably longer than the length, so it should throw an exception.
+// This is no different from the other cases where the offset is longer than
+// the length, and the wrapping complicates my testing slightly, so I won't
+// bother testing negative values here or in other cases.
+var splitTextTests = [];
+for (var i = 0; i < textNodes.length; i++) {
+ var node = textNodes[i];
+ splitTextTests.push([node, 376, node, 0, node, 1]);
+ splitTextTests.push([node, 0, node, 0, node, 0]);
+ splitTextTests.push([node, 1, node, 1, node, 1]);
+ splitTextTests.push([node, node + ".length", node, node + ".length", node, node + ".length"]);
+ splitTextTests.push([node, 1, node, 1, node, 3]);
+ splitTextTests.push([node, 2, node, 1, node, 3]);
+ splitTextTests.push([node, 3, node, 1, node, 3]);
+}
+
+splitTextTests.push(
+ ["paras[0].firstChild", 1, "paras[0]", 0, "paras[0]", 0],
+ ["paras[0].firstChild", 1, "paras[0]", 0, "paras[0]", 1],
+ ["paras[0].firstChild", 1, "paras[0]", 1, "paras[0]", 1],
+ ["paras[0].firstChild", 1, "paras[0].firstChild", 1, "paras[0]", 1],
+ ["paras[0].firstChild", 2, "paras[0].firstChild", 1, "paras[0]", 1],
+ ["paras[0].firstChild", 3, "paras[0].firstChild", 1, "paras[0]", 1],
+ ["paras[0].firstChild", 1, "paras[0]", 0, "paras[0].firstChild", 3],
+ ["paras[0].firstChild", 2, "paras[0]", 0, "paras[0].firstChild", 3],
+ ["paras[0].firstChild", 3, "paras[0]", 0, "paras[0].firstChild", 3]
+);
+
+
+function testReplaceDataAlgorithm(node, offset, count, data, callback, startContainer, startOffset, endContainer, endOffset) {
+ // Mutation works the same any time DOM Core's "replace data" algorithm is
+ // invoked. node, offset, count, data are as in that algorithm. The
+ // callback is what does the actual setting. Not to be confused with
+ // testReplaceData, which tests the replaceData() method.
+
+ // Barring any provision to the contrary, the containers and offsets must
+ // not change.
+ var expectedStartContainer = startContainer;
+ var expectedStartOffset = startOffset;
+ var expectedEndContainer = endContainer;
+ var expectedEndOffset = endOffset;
+
+ var originalParent = node.parentNode;
+ var originalData = node.data;
+
+ var exceptionThrown = false;
+ try {
+ callback();
+ } catch (e) {
+ // Should only happen if offset is greater than length
+ exceptionThrown = true;
+ }
+
+ assert_equals(node.parentNode, originalParent,
+ "Sanity check failed: changing data changed the parent");
+
+ // "User agents must run the following steps whenever they replace data of
+ // a CharacterData node, as though they were written in the specification
+ // for that algorithm after all other steps. In particular, the steps must
+ // not be executed if the algorithm threw an exception."
+ if (exceptionThrown) {
+ assert_equals(node.data, originalData,
+ "Sanity check failed: exception thrown but data changed");
+ } else {
+ assert_equals(node.data,
+ originalData.substr(0, offset) + data + originalData.substr(offset + count),
+ "Sanity check failed: data not changed as expected");
+ }
+
+ // "For every boundary point whose node is node, and whose offset is
+ // greater than offset but less than or equal to offset plus count, set
+ // its offset to offset."
+ if (!exceptionThrown
+ && startContainer == node
+ && startOffset > offset
+ && startOffset <= offset + count) {
+ expectedStartOffset = offset;
+ }
+
+ if (!exceptionThrown
+ && endContainer == node
+ && endOffset > offset
+ && endOffset <= offset + count) {
+ expectedEndOffset = offset;
+ }
+
+ // "For every boundary point whose node is node, and whose offset is
+ // greater than offset plus count, add the length of data to its offset,
+ // then subtract count from it."
+ if (!exceptionThrown
+ && startContainer == node
+ && startOffset > offset + count) {
+ expectedStartOffset += data.length - count;
+ }
+
+ if (!exceptionThrown
+ && endContainer == node
+ && endOffset > offset + count) {
+ expectedEndOffset += data.length - count;
+ }
+
+ return [expectedStartContainer, expectedStartOffset, expectedEndContainer, expectedEndOffset];
+}
+
+function testInsertData(node, offset, data, startContainer, startOffset, endContainer, endOffset) {
+ return testReplaceDataAlgorithm(node, offset, 0, data,
+ function() { node.insertData(offset, data) },
+ startContainer, startOffset, endContainer, endOffset);
+}
+
+var insertDataTests = [];
+for (var i = 0; i < characterDataNodes.length; i++) {
+ var node = characterDataNodes[i];
+ insertDataTests.push([node, 376, '"foo"', node, 0, node, 1]);
+ insertDataTests.push([node, 0, '"foo"', node, 0, node, 0]);
+ insertDataTests.push([node, 1, '"foo"', node, 1, node, 1]);
+ insertDataTests.push([node, node + ".length", '"foo"', node, node + ".length", node, node + ".length"]);
+ insertDataTests.push([node, 1, '"foo"', node, 1, node, 3]);
+ insertDataTests.push([node, 2, '"foo"', node, 1, node, 3]);
+ insertDataTests.push([node, 3, '"foo"', node, 1, node, 3]);
+
+ insertDataTests.push([node, 376, '""', node, 0, node, 1]);
+ insertDataTests.push([node, 0, '""', node, 0, node, 0]);
+ insertDataTests.push([node, 1, '""', node, 1, node, 1]);
+ insertDataTests.push([node, node + ".length", '""', node, node + ".length", node, node + ".length"]);
+ insertDataTests.push([node, 1, '""', node, 1, node, 3]);
+ insertDataTests.push([node, 2, '""', node, 1, node, 3]);
+ insertDataTests.push([node, 3, '""', node, 1, node, 3]);
+}
+
+insertDataTests.push(
+ ["paras[0].firstChild", 1, '"foo"', "paras[0]", 0, "paras[0]", 0],
+ ["paras[0].firstChild", 1, '"foo"', "paras[0]", 0, "paras[0]", 1],
+ ["paras[0].firstChild", 1, '"foo"', "paras[0]", 1, "paras[0]", 1],
+ ["paras[0].firstChild", 1, '"foo"', "paras[0].firstChild", 1, "paras[0]", 1],
+ ["paras[0].firstChild", 2, '"foo"', "paras[0].firstChild", 1, "paras[0]", 1],
+ ["paras[0].firstChild", 3, '"foo"', "paras[0].firstChild", 1, "paras[0]", 1],
+ ["paras[0].firstChild", 1, '"foo"', "paras[0]", 0, "paras[0].firstChild", 3],
+ ["paras[0].firstChild", 2, '"foo"', "paras[0]", 0, "paras[0].firstChild", 3],
+ ["paras[0].firstChild", 3, '"foo"', "paras[0]", 0, "paras[0].firstChild", 3]
+);
+
+
+function testAppendData(node, data, startContainer, startOffset, endContainer, endOffset) {
+ return testReplaceDataAlgorithm(node, node.length, 0, data,
+ function() { node.appendData(data) },
+ startContainer, startOffset, endContainer, endOffset);
+}
+
+var appendDataTests = [];
+for (var i = 0; i < characterDataNodes.length; i++) {
+ var node = characterDataNodes[i];
+ appendDataTests.push([node, '"foo"', node, 0, node, 1]);
+ appendDataTests.push([node, '"foo"', node, 0, node, 0]);
+ appendDataTests.push([node, '"foo"', node, 1, node, 1]);
+ appendDataTests.push([node, '"foo"', node, 0, node, node + ".length"]);
+ appendDataTests.push([node, '"foo"', node, 1, node, node + ".length"]);
+ appendDataTests.push([node, '"foo"', node, node + ".length", node, node + ".length"]);
+ appendDataTests.push([node, '"foo"', node, 1, node, 3]);
+
+ appendDataTests.push([node, '""', node, 0, node, 1]);
+ appendDataTests.push([node, '""', node, 0, node, 0]);
+ appendDataTests.push([node, '""', node, 1, node, 1]);
+ appendDataTests.push([node, '""', node, 0, node, node + ".length"]);
+ appendDataTests.push([node, '""', node, 1, node, node + ".length"]);
+ appendDataTests.push([node, '""', node, node + ".length", node, node + ".length"]);
+ appendDataTests.push([node, '""', node, 1, node, 3]);
+}
+
+appendDataTests.push(
+ ["paras[0].firstChild", '""', "paras[0]", 0, "paras[0]", 0],
+ ["paras[0].firstChild", '""', "paras[0]", 0, "paras[0]", 1],
+ ["paras[0].firstChild", '""', "paras[0]", 1, "paras[0]", 1],
+ ["paras[0].firstChild", '""', "paras[0].firstChild", 1, "paras[0]", 1],
+ ["paras[0].firstChild", '""', "paras[0]", 0, "paras[0].firstChild", 3],
+
+ ["paras[0].firstChild", '"foo"', "paras[0]", 0, "paras[0]", 0],
+ ["paras[0].firstChild", '"foo"', "paras[0]", 0, "paras[0]", 1],
+ ["paras[0].firstChild", '"foo"', "paras[0]", 1, "paras[0]", 1],
+ ["paras[0].firstChild", '"foo"', "paras[0].firstChild", 1, "paras[0]", 1],
+ ["paras[0].firstChild", '"foo"', "paras[0]", 0, "paras[0].firstChild", 3]
+);
+
+
+function testDeleteData(node, offset, count, startContainer, startOffset, endContainer, endOffset) {
+ return testReplaceDataAlgorithm(node, offset, count, "",
+ function() { node.deleteData(offset, count) },
+ startContainer, startOffset, endContainer, endOffset);
+}
+
+var deleteDataTests = [];
+for (var i = 0; i < characterDataNodes.length; i++) {
+ var node = characterDataNodes[i];
+ deleteDataTests.push([node, 376, 2, node, 0, node, 1]);
+ deleteDataTests.push([node, 0, 2, node, 0, node, 0]);
+ deleteDataTests.push([node, 1, 2, node, 1, node, 1]);
+ deleteDataTests.push([node, node + ".length", 2, node, node + ".length", node, node + ".length"]);
+ deleteDataTests.push([node, 1, 2, node, 1, node, 3]);
+ deleteDataTests.push([node, 2, 2, node, 1, node, 3]);
+ deleteDataTests.push([node, 3, 2, node, 1, node, 3]);
+
+ deleteDataTests.push([node, 376, 0, node, 0, node, 1]);
+ deleteDataTests.push([node, 0, 0, node, 0, node, 0]);
+ deleteDataTests.push([node, 1, 0, node, 1, node, 1]);
+ deleteDataTests.push([node, node + ".length", 0, node, node + ".length", node, node + ".length"]);
+ deleteDataTests.push([node, 1, 0, node, 1, node, 3]);
+ deleteDataTests.push([node, 2, 0, node, 1, node, 3]);
+ deleteDataTests.push([node, 3, 0, node, 1, node, 3]);
+
+ deleteDataTests.push([node, 376, 631, node, 0, node, 1]);
+ deleteDataTests.push([node, 0, 631, node, 0, node, 0]);
+ deleteDataTests.push([node, 1, 631, node, 1, node, 1]);
+ deleteDataTests.push([node, node + ".length", 631, node, node + ".length", node, node + ".length"]);
+ deleteDataTests.push([node, 1, 631, node, 1, node, 3]);
+ deleteDataTests.push([node, 2, 631, node, 1, node, 3]);
+ deleteDataTests.push([node, 3, 631, node, 1, node, 3]);
+}
+
+deleteDataTests.push(
+ ["paras[0].firstChild", 1, 2, "paras[0]", 0, "paras[0]", 0],
+ ["paras[0].firstChild", 1, 2, "paras[0]", 0, "paras[0]", 1],
+ ["paras[0].firstChild", 1, 2, "paras[0]", 1, "paras[0]", 1],
+ ["paras[0].firstChild", 1, 2, "paras[0].firstChild", 1, "paras[0]", 1],
+ ["paras[0].firstChild", 2, 2, "paras[0].firstChild", 1, "paras[0]", 1],
+ ["paras[0].firstChild", 3, 2, "paras[0].firstChild", 1, "paras[0]", 1],
+ ["paras[0].firstChild", 1, 2, "paras[0]", 0, "paras[0].firstChild", 3],
+ ["paras[0].firstChild", 2, 2, "paras[0]", 0, "paras[0].firstChild", 3],
+ ["paras[0].firstChild", 3, 2, "paras[0]", 0, "paras[0].firstChild", 3]
+);
+
+
+function testReplaceData(node, offset, count, data, startContainer, startOffset, endContainer, endOffset) {
+ return testReplaceDataAlgorithm(node, offset, count, data,
+ function() { node.replaceData(offset, count, data) },
+ startContainer, startOffset, endContainer, endOffset);
+}
+
+var replaceDataTests = [];
+for (var i = 0; i < characterDataNodes.length; i++) {
+ var node = characterDataNodes[i];
+ replaceDataTests.push([node, 376, 0, '"foo"', node, 0, node, 1]);
+ replaceDataTests.push([node, 0, 0, '"foo"', node, 0, node, 0]);
+ replaceDataTests.push([node, 1, 0, '"foo"', node, 1, node, 1]);
+ replaceDataTests.push([node, node + ".length", 0, '"foo"', node, node + ".length", node, node + ".length"]);
+ replaceDataTests.push([node, 1, 0, '"foo"', node, 1, node, 3]);
+ replaceDataTests.push([node, 2, 0, '"foo"', node, 1, node, 3]);
+ replaceDataTests.push([node, 3, 0, '"foo"', node, 1, node, 3]);
+
+ replaceDataTests.push([node, 376, 0, '""', node, 0, node, 1]);
+ replaceDataTests.push([node, 0, 0, '""', node, 0, node, 0]);
+ replaceDataTests.push([node, 1, 0, '""', node, 1, node, 1]);
+ replaceDataTests.push([node, node + ".length", 0, '""', node, node + ".length", node, node + ".length"]);
+ replaceDataTests.push([node, 1, 0, '""', node, 1, node, 3]);
+ replaceDataTests.push([node, 2, 0, '""', node, 1, node, 3]);
+ replaceDataTests.push([node, 3, 0, '""', node, 1, node, 3]);
+
+ replaceDataTests.push([node, 376, 1, '"foo"', node, 0, node, 1]);
+ replaceDataTests.push([node, 0, 1, '"foo"', node, 0, node, 0]);
+ replaceDataTests.push([node, 1, 1, '"foo"', node, 1, node, 1]);
+ replaceDataTests.push([node, node + ".length", 1, '"foo"', node, node + ".length", node, node + ".length"]);
+ replaceDataTests.push([node, 1, 1, '"foo"', node, 1, node, 3]);
+ replaceDataTests.push([node, 2, 1, '"foo"', node, 1, node, 3]);
+ replaceDataTests.push([node, 3, 1, '"foo"', node, 1, node, 3]);
+
+ replaceDataTests.push([node, 376, 1, '""', node, 0, node, 1]);
+ replaceDataTests.push([node, 0, 1, '""', node, 0, node, 0]);
+ replaceDataTests.push([node, 1, 1, '""', node, 1, node, 1]);
+ replaceDataTests.push([node, node + ".length", 1, '""', node, node + ".length", node, node + ".length"]);
+ replaceDataTests.push([node, 1, 1, '""', node, 1, node, 3]);
+ replaceDataTests.push([node, 2, 1, '""', node, 1, node, 3]);
+ replaceDataTests.push([node, 3, 1, '""', node, 1, node, 3]);
+
+ replaceDataTests.push([node, 376, 47, '"foo"', node, 0, node, 1]);
+ replaceDataTests.push([node, 0, 47, '"foo"', node, 0, node, 0]);
+ replaceDataTests.push([node, 1, 47, '"foo"', node, 1, node, 1]);
+ replaceDataTests.push([node, node + ".length", 47, '"foo"', node, node + ".length", node, node + ".length"]);
+ replaceDataTests.push([node, 1, 47, '"foo"', node, 1, node, 3]);
+ replaceDataTests.push([node, 2, 47, '"foo"', node, 1, node, 3]);
+ replaceDataTests.push([node, 3, 47, '"foo"', node, 1, node, 3]);
+
+ replaceDataTests.push([node, 376, 47, '""', node, 0, node, 1]);
+ replaceDataTests.push([node, 0, 47, '""', node, 0, node, 0]);
+ replaceDataTests.push([node, 1, 47, '""', node, 1, node, 1]);
+ replaceDataTests.push([node, node + ".length", 47, '""', node, node + ".length", node, node + ".length"]);
+ replaceDataTests.push([node, 1, 47, '""', node, 1, node, 3]);
+ replaceDataTests.push([node, 2, 47, '""', node, 1, node, 3]);
+ replaceDataTests.push([node, 3, 47, '""', node, 1, node, 3]);
+}
+
+replaceDataTests.push(
+ ["paras[0].firstChild", 1, 0, '"foo"', "paras[0]", 0, "paras[0]", 0],
+ ["paras[0].firstChild", 1, 0, '"foo"', "paras[0]", 0, "paras[0]", 1],
+ ["paras[0].firstChild", 1, 0, '"foo"', "paras[0]", 1, "paras[0]", 1],
+ ["paras[0].firstChild", 1, 0, '"foo"', "paras[0].firstChild", 1, "paras[0]", 1],
+ ["paras[0].firstChild", 2, 0, '"foo"', "paras[0].firstChild", 1, "paras[0]", 1],
+ ["paras[0].firstChild", 3, 0, '"foo"', "paras[0].firstChild", 1, "paras[0]", 1],
+ ["paras[0].firstChild", 1, 0, '"foo"', "paras[0]", 0, "paras[0].firstChild", 3],
+ ["paras[0].firstChild", 2, 0, '"foo"', "paras[0]", 0, "paras[0].firstChild", 3],
+ ["paras[0].firstChild", 3, 0, '"foo"', "paras[0]", 0, "paras[0].firstChild", 3],
+
+ ["paras[0].firstChild", 1, 1, '"foo"', "paras[0]", 0, "paras[0]", 0],
+ ["paras[0].firstChild", 1, 1, '"foo"', "paras[0]", 0, "paras[0]", 1],
+ ["paras[0].firstChild", 1, 1, '"foo"', "paras[0]", 1, "paras[0]", 1],
+ ["paras[0].firstChild", 1, 1, '"foo"', "paras[0].firstChild", 1, "paras[0]", 1],
+ ["paras[0].firstChild", 2, 1, '"foo"', "paras[0].firstChild", 1, "paras[0]", 1],
+ ["paras[0].firstChild", 3, 1, '"foo"', "paras[0].firstChild", 1, "paras[0]", 1],
+ ["paras[0].firstChild", 1, 1, '"foo"', "paras[0]", 0, "paras[0].firstChild", 3],
+ ["paras[0].firstChild", 2, 1, '"foo"', "paras[0]", 0, "paras[0].firstChild", 3],
+ ["paras[0].firstChild", 3, 1, '"foo"', "paras[0]", 0, "paras[0].firstChild", 3],
+
+ ["paras[0].firstChild", 1, 47, '"foo"', "paras[0]", 0, "paras[0]", 0],
+ ["paras[0].firstChild", 1, 47, '"foo"', "paras[0]", 0, "paras[0]", 1],
+ ["paras[0].firstChild", 1, 47, '"foo"', "paras[0]", 1, "paras[0]", 1],
+ ["paras[0].firstChild", 1, 47, '"foo"', "paras[0].firstChild", 1, "paras[0]", 1],
+ ["paras[0].firstChild", 2, 47, '"foo"', "paras[0].firstChild", 1, "paras[0]", 1],
+ ["paras[0].firstChild", 3, 47, '"foo"', "paras[0].firstChild", 1, "paras[0]", 1],
+ ["paras[0].firstChild", 1, 47, '"foo"', "paras[0]", 0, "paras[0].firstChild", 3],
+ ["paras[0].firstChild", 2, 47, '"foo"', "paras[0]", 0, "paras[0].firstChild", 3],
+ ["paras[0].firstChild", 3, 47, '"foo"', "paras[0]", 0, "paras[0].firstChild", 3]
+);
+
+
+// There are lots of ways to set data, so we pass a callback that does the
+// actual setting.
+function testDataChange(node, attr, op, rval, startContainer, startOffset, endContainer, endOffset) {
+ return testReplaceDataAlgorithm(node, 0, node.length, op == "=" ? rval : node[attr] + rval,
+ function() {
+ if (op == "=") {
+ node[attr] = rval;
+ } else if (op == "+=") {
+ node[attr] += rval;
+ } else {
+ throw "Unknown op " + op;
+ }
+ },
+ startContainer, startOffset, endContainer, endOffset);
+}
+
+var dataChangeTests = [];
+var dataChangeTestAttrs = ["data", "textContent", "nodeValue"];
+for (var i = 0; i < characterDataNodes.length; i++) {
+ var node = characterDataNodes[i];
+ var dataChangeTestRanges = [
+ [node, 0, node, 0],
+ [node, 0, node, 1],
+ [node, 1, node, 1],
+ [node, 0, node, node + ".length"],
+ [node, 1, node, node + ".length"],
+ [node, node + ".length", node, node + ".length"],
+ ];
+
+ for (var j = 0; j < dataChangeTestRanges.length; j++) {
+ for (var k = 0; k < dataChangeTestAttrs.length; k++) {
+ dataChangeTests.push([
+ node,
+ '"' + dataChangeTestAttrs[k] + '"',
+ '"="',
+ '""',
+ ].concat(dataChangeTestRanges[j]));
+
+ dataChangeTests.push([
+ node,
+ '"' + dataChangeTestAttrs[k] + '"',
+ '"="',
+ '"foo"',
+ ].concat(dataChangeTestRanges[j]));
+
+ dataChangeTests.push([
+ node,
+ '"' + dataChangeTestAttrs[k] + '"',
+ '"="',
+ node + "." + dataChangeTestAttrs[k],
+ ].concat(dataChangeTestRanges[j]));
+
+ dataChangeTests.push([
+ node,
+ '"' + dataChangeTestAttrs[k] + '"',
+ '"+="',
+ '""',
+ ].concat(dataChangeTestRanges[j]));
+
+ dataChangeTests.push([
+ node,
+ '"' + dataChangeTestAttrs[k] + '"',
+ '"+="',
+ '"foo"',
+ ].concat(dataChangeTestRanges[j]));
+
+ dataChangeTests.push([
+ node,
+ '"' + dataChangeTestAttrs[k] + '"',
+ '"+="',
+ node + "." + dataChangeTestAttrs[k]
+ ].concat(dataChangeTestRanges[j]));
+ }
+ }
+}
+
+
+// Now we test node insertions and deletions, as opposed to just data changes.
+// To avoid loads of repetition, we define modifyForRemove() and
+// modifyForInsert().
+
+// If we were to remove removedNode from its parent, what would the boundary
+// point [node, offset] become? Returns [new node, new offset]. Must be
+// called BEFORE the node is actually removed, so its parent is not null. (If
+// the parent is null, it will do nothing.)
+function modifyForRemove(removedNode, point) {
+ var oldParent = removedNode.parentNode;
+ var oldIndex = indexOf(removedNode);
+ if (!oldParent) {
+ return point;
+ }
+
+ // "For each boundary point whose node is removed node or a descendant of
+ // it, set the boundary point to (old parent, old index)."
+ if (point[0] == removedNode || isDescendant(point[0], removedNode)) {
+ return [oldParent, oldIndex];
+ }
+
+ // "For each boundary point whose node is old parent and whose offset is
+ // greater than old index, subtract one from its offset."
+ if (point[0] == oldParent && point[1] > oldIndex) {
+ return [point[0], point[1] - 1];
+ }
+
+ return point;
+}
+
+// Update the given boundary point [node, offset] to account for the fact that
+// insertedNode was just inserted into its current position. This must be
+// called AFTER insertedNode was already inserted.
+function modifyForInsert(insertedNode, point) {
+ // "For each boundary point whose node is the new parent of the affected
+ // node and whose offset is greater than the new index of the affected
+ // node, add one to the boundary point's offset."
+ if (point[0] == insertedNode.parentNode && point[1] > indexOf(insertedNode)) {
+ return [point[0], point[1] + 1];
+ }
+
+ return point;
+}
+
+
+function testInsertBefore(newParent, affectedNode, refNode, startContainer, startOffset, endContainer, endOffset) {
+ var expectedStart = [startContainer, startOffset];
+ var expectedEnd = [endContainer, endOffset];
+
+ expectedStart = modifyForRemove(affectedNode, expectedStart);
+ expectedEnd = modifyForRemove(affectedNode, expectedEnd);
+
+ try {
+ newParent.insertBefore(affectedNode, refNode);
+ } catch (e) {
+ // For our purposes, assume that DOM Core is true -- i.e., ignore
+ // mutation events and similar.
+ return [startContainer, startOffset, endContainer, endOffset];
+ }
+
+ expectedStart = modifyForInsert(affectedNode, expectedStart);
+ expectedEnd = modifyForInsert(affectedNode, expectedEnd);
+
+ return expectedStart.concat(expectedEnd);
+}
+
+var insertBeforeTests = [
+ // Moving a node to its current position
+ ["testDiv", "paras[0]", "paras[1]", "paras[0]", 0, "paras[0]", 0],
+ ["testDiv", "paras[0]", "paras[1]", "paras[0]", 0, "paras[0]", 1],
+ ["testDiv", "paras[0]", "paras[1]", "paras[0]", 1, "paras[0]", 1],
+ ["testDiv", "paras[0]", "paras[1]", "testDiv", 0, "testDiv", 2],
+ ["testDiv", "paras[0]", "paras[1]", "testDiv", 1, "testDiv", 1],
+ ["testDiv", "paras[0]", "paras[1]", "testDiv", 1, "testDiv", 2],
+ ["testDiv", "paras[0]", "paras[1]", "testDiv", 2, "testDiv", 2],
+
+ // Stuff that actually moves something. Note that paras[0] and paras[1]
+ // are both children of testDiv.
+ ["paras[0]", "paras[1]", "paras[0].firstChild", "paras[0]", 0, "paras[0]", 0],
+ ["paras[0]", "paras[1]", "paras[0].firstChild", "paras[0]", 0, "paras[0]", 1],
+ ["paras[0]", "paras[1]", "paras[0].firstChild", "paras[0]", 1, "paras[0]", 1],
+ ["paras[0]", "paras[1]", "paras[0].firstChild", "testDiv", 0, "testDiv", 1],
+ ["paras[0]", "paras[1]", "paras[0].firstChild", "testDiv", 0, "testDiv", 2],
+ ["paras[0]", "paras[1]", "paras[0].firstChild", "testDiv", 1, "testDiv", 1],
+ ["paras[0]", "paras[1]", "paras[0].firstChild", "testDiv", 1, "testDiv", 2],
+ ["paras[0]", "paras[1]", "null", "paras[0]", 0, "paras[0]", 0],
+ ["paras[0]", "paras[1]", "null", "paras[0]", 0, "paras[0]", 1],
+ ["paras[0]", "paras[1]", "null", "paras[0]", 1, "paras[0]", 1],
+ ["paras[0]", "paras[1]", "null", "testDiv", 0, "testDiv", 1],
+ ["paras[0]", "paras[1]", "null", "testDiv", 0, "testDiv", 2],
+ ["paras[0]", "paras[1]", "null", "testDiv", 1, "testDiv", 1],
+ ["paras[0]", "paras[1]", "null", "testDiv", 1, "testDiv", 2],
+ ["foreignDoc", "detachedComment", "foreignDoc.documentElement", "foreignDoc", 0, "foreignDoc", 0],
+ ["foreignDoc", "detachedComment", "foreignDoc.documentElement", "foreignDoc", 0, "foreignDoc", 1],
+ ["foreignDoc", "detachedComment", "foreignDoc.documentElement", "foreignDoc", 0, "foreignDoc", 2],
+ ["foreignDoc", "detachedComment", "foreignDoc.documentElement", "foreignDoc", 1, "foreignDoc", 1],
+ ["foreignDoc", "detachedComment", "foreignDoc.doctype", "foreignDoc", 0, "foreignDoc", 0],
+ ["foreignDoc", "detachedComment", "foreignDoc.doctype", "foreignDoc", 0, "foreignDoc", 1],
+ ["foreignDoc", "detachedComment", "foreignDoc.doctype", "foreignDoc", 0, "foreignDoc", 2],
+ ["foreignDoc", "detachedComment", "foreignDoc.doctype", "foreignDoc", 1, "foreignDoc", 1],
+ ["foreignDoc", "detachedComment", "null", "foreignDoc", 0, "foreignDoc", 1],
+ ["paras[0]", "xmlTextNode", "paras[0].firstChild", "paras[0]", 0, "paras[0]", 0],
+ ["paras[0]", "xmlTextNode", "paras[0].firstChild", "paras[0]", 0, "paras[0]", 1],
+ ["paras[0]", "xmlTextNode", "paras[0].firstChild", "paras[0]", 1, "paras[0]", 1],
+
+ // Stuff that throws exceptions
+ ["paras[0]", "paras[0]", "paras[0].firstChild", "paras[0]", 0, "paras[0]", 1],
+ ["paras[0]", "testDiv", "paras[0].firstChild", "paras[0]", 0, "paras[0]", 1],
+ ["paras[0]", "document", "paras[0].firstChild", "paras[0]", 0, "paras[0]", 1],
+ ["paras[0]", "foreignDoc", "paras[0].firstChild", "paras[0]", 0, "paras[0]", 1],
+ ["paras[0]", "document.doctype", "paras[0].firstChild", "paras[0]", 0, "paras[0]", 1],
+];
+
+
+function testReplaceChild(newParent, newChild, oldChild, startContainer, startOffset, endContainer, endOffset) {
+ var expectedStart = [startContainer, startOffset];
+ var expectedEnd = [endContainer, endOffset];
+
+ expectedStart = modifyForRemove(oldChild, expectedStart);
+ expectedEnd = modifyForRemove(oldChild, expectedEnd);
+
+ if (newChild != oldChild) {
+ // Don't do this twice, if they're the same!
+ expectedStart = modifyForRemove(newChild, expectedStart);
+ expectedEnd = modifyForRemove(newChild, expectedEnd);
+ }
+
+ try {
+ newParent.replaceChild(newChild, oldChild);
+ } catch (e) {
+ return [startContainer, startOffset, endContainer, endOffset];
+ }
+
+ expectedStart = modifyForInsert(newChild, expectedStart);
+ expectedEnd = modifyForInsert(newChild, expectedEnd);
+
+ return expectedStart.concat(expectedEnd);
+}
+
+var replaceChildTests = [
+ // Moving a node to its current position. Doesn't match most browsers'
+ // behavior, but we probably want to keep the spec the same anyway:
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=647603
+ ["testDiv", "paras[0]", "paras[0]", "paras[0]", 0, "paras[0]", 0],
+ ["testDiv", "paras[0]", "paras[0]", "paras[0]", 0, "paras[0]", 1],
+ ["testDiv", "paras[0]", "paras[0]", "paras[0]", 1, "paras[0]", 1],
+ ["testDiv", "paras[0]", "paras[0]", "testDiv", 0, "testDiv", 2],
+ ["testDiv", "paras[0]", "paras[0]", "testDiv", 1, "testDiv", 1],
+ ["testDiv", "paras[0]", "paras[0]", "testDiv", 1, "testDiv", 2],
+ ["testDiv", "paras[0]", "paras[0]", "testDiv", 2, "testDiv", 2],
+
+ // Stuff that actually moves something.
+ ["paras[0]", "paras[1]", "paras[0].firstChild", "paras[0]", 0, "paras[0]", 0],
+ ["paras[0]", "paras[1]", "paras[0].firstChild", "paras[0]", 0, "paras[0]", 1],
+ ["paras[0]", "paras[1]", "paras[0].firstChild", "paras[0]", 1, "paras[0]", 1],
+ ["paras[0]", "paras[1]", "paras[0].firstChild", "testDiv", 0, "testDiv", 1],
+ ["paras[0]", "paras[1]", "paras[0].firstChild", "testDiv", 0, "testDiv", 2],
+ ["paras[0]", "paras[1]", "paras[0].firstChild", "testDiv", 1, "testDiv", 1],
+ ["paras[0]", "paras[1]", "paras[0].firstChild", "testDiv", 1, "testDiv", 2],
+ ["foreignDoc", "detachedComment", "foreignDoc.documentElement", "foreignDoc", 0, "foreignDoc", 0],
+ ["foreignDoc", "detachedComment", "foreignDoc.documentElement", "foreignDoc", 0, "foreignDoc", 1],
+ ["foreignDoc", "detachedComment", "foreignDoc.documentElement", "foreignDoc", 0, "foreignDoc", 2],
+ ["foreignDoc", "detachedComment", "foreignDoc.documentElement", "foreignDoc", 1, "foreignDoc", 1],
+ ["foreignDoc", "detachedComment", "foreignDoc.doctype", "foreignDoc", 0, "foreignDoc", 0],
+ ["foreignDoc", "detachedComment", "foreignDoc.doctype", "foreignDoc", 0, "foreignDoc", 1],
+ ["foreignDoc", "detachedComment", "foreignDoc.doctype", "foreignDoc", 0, "foreignDoc", 2],
+ ["foreignDoc", "detachedComment", "foreignDoc.doctype", "foreignDoc", 1, "foreignDoc", 1],
+ ["paras[0]", "xmlTextNode", "paras[0].firstChild", "paras[0]", 0, "paras[0]", 0],
+ ["paras[0]", "xmlTextNode", "paras[0].firstChild", "paras[0]", 0, "paras[0]", 1],
+ ["paras[0]", "xmlTextNode", "paras[0].firstChild", "paras[0]", 1, "paras[0]", 1],
+
+ // Stuff that throws exceptions
+ ["paras[0]", "paras[0]", "paras[0].firstChild", "paras[0]", 0, "paras[0]", 1],
+ ["paras[0]", "testDiv", "paras[0].firstChild", "paras[0]", 0, "paras[0]", 1],
+ ["paras[0]", "document", "paras[0].firstChild", "paras[0]", 0, "paras[0]", 1],
+ ["paras[0]", "foreignDoc", "paras[0].firstChild", "paras[0]", 0, "paras[0]", 1],
+ ["paras[0]", "document.doctype", "paras[0].firstChild", "paras[0]", 0, "paras[0]", 1],
+];
+
+
+function testAppendChild(newParent, affectedNode, startContainer, startOffset, endContainer, endOffset) {
+ var expectedStart = [startContainer, startOffset];
+ var expectedEnd = [endContainer, endOffset];
+
+ expectedStart = modifyForRemove(affectedNode, expectedStart);
+ expectedEnd = modifyForRemove(affectedNode, expectedEnd);
+
+ try {
+ newParent.appendChild(affectedNode);
+ } catch (e) {
+ return [startContainer, startOffset, endContainer, endOffset];
+ }
+
+ // These two lines will actually never do anything, if you think about it,
+ // but let's leave them in so correctness is more obvious.
+ expectedStart = modifyForInsert(affectedNode, expectedStart);
+ expectedEnd = modifyForInsert(affectedNode, expectedEnd);
+
+ return expectedStart.concat(expectedEnd);
+}
+
+var appendChildTests = [
+ // Moving a node to its current position
+ ["testDiv", "testDiv.lastChild", "testDiv.lastChild", 0, "testDiv.lastChild", 0],
+ ["testDiv", "testDiv.lastChild", "testDiv.lastChild", 0, "testDiv.lastChild", 1],
+ ["testDiv", "testDiv.lastChild", "testDiv.lastChild", 1, "testDiv.lastChild", 1],
+ ["testDiv", "testDiv.lastChild", "testDiv", "testDiv.childNodes.length - 2", "testDiv", "testDiv.childNodes.length"],
+ ["testDiv", "testDiv.lastChild", "testDiv", "testDiv.childNodes.length - 2", "testDiv", "testDiv.childNodes.length - 1"],
+ ["testDiv", "testDiv.lastChild", "testDiv", "testDiv.childNodes.length - 1", "testDiv", "testDiv.childNodes.length"],
+ ["testDiv", "testDiv.lastChild", "testDiv", "testDiv.childNodes.length - 1", "testDiv", "testDiv.childNodes.length - 1"],
+ ["testDiv", "testDiv.lastChild", "testDiv", "testDiv.childNodes.length", "testDiv", "testDiv.childNodes.length"],
+ ["detachedDiv", "detachedDiv.lastChild", "detachedDiv.lastChild", 0, "detachedDiv.lastChild", 0],
+ ["detachedDiv", "detachedDiv.lastChild", "detachedDiv.lastChild", 0, "detachedDiv.lastChild", 1],
+ ["detachedDiv", "detachedDiv.lastChild", "detachedDiv.lastChild", 1, "detachedDiv.lastChild", 1],
+ ["detachedDiv", "detachedDiv.lastChild", "detachedDiv", "detachedDiv.childNodes.length - 2", "detachedDiv", "detachedDiv.childNodes.length"],
+ ["detachedDiv", "detachedDiv.lastChild", "detachedDiv", "detachedDiv.childNodes.length - 2", "detachedDiv", "detachedDiv.childNodes.length - 1"],
+ ["detachedDiv", "detachedDiv.lastChild", "detachedDiv", "detachedDiv.childNodes.length - 1", "detachedDiv", "detachedDiv.childNodes.length"],
+ ["detachedDiv", "detachedDiv.lastChild", "detachedDiv", "detachedDiv.childNodes.length - 1", "detachedDiv", "detachedDiv.childNodes.length - 1"],
+ ["detachedDiv", "detachedDiv.lastChild", "detachedDiv", "detachedDiv.childNodes.length", "detachedDiv", "detachedDiv.childNodes.length"],
+
+ // Stuff that actually moves something
+ ["paras[0]", "paras[1]", "paras[0]", 0, "paras[0]", 0],
+ ["paras[0]", "paras[1]", "paras[0]", 0, "paras[0]", 1],
+ ["paras[0]", "paras[1]", "paras[0]", 1, "paras[0]", 1],
+ ["paras[0]", "paras[1]", "testDiv", 0, "testDiv", 1],
+ ["paras[0]", "paras[1]", "testDiv", 0, "testDiv", 2],
+ ["paras[0]", "paras[1]", "testDiv", 1, "testDiv", 1],
+ ["paras[0]", "paras[1]", "testDiv", 1, "testDiv", 2],
+ ["foreignDoc", "detachedComment", "foreignDoc", "foreignDoc.childNodes.length - 1", "foreignDoc", "foreignDoc.childNodes.length"],
+ ["foreignDoc", "detachedComment", "foreignDoc", "foreignDoc.childNodes.length - 1", "foreignDoc", "foreignDoc.childNodes.length - 1"],
+ ["foreignDoc", "detachedComment", "foreignDoc", "foreignDoc.childNodes.length", "foreignDoc", "foreignDoc.childNodes.length"],
+ ["foreignDoc", "detachedComment", "detachedComment", 0, "detachedComment", 5],
+ ["paras[0]", "xmlTextNode", "paras[0]", 0, "paras[0]", 0],
+ ["paras[0]", "xmlTextNode", "paras[0]", 0, "paras[0]", 1],
+ ["paras[0]", "xmlTextNode", "paras[0]", 1, "paras[0]", 1],
+
+ // Stuff that throws exceptions
+ ["paras[0]", "paras[0]", "paras[0]", 0, "paras[0]", 1],
+ ["paras[0]", "testDiv", "paras[0]", 0, "paras[0]", 1],
+ ["paras[0]", "document", "paras[0]", 0, "paras[0]", 1],
+ ["paras[0]", "foreignDoc", "paras[0]", 0, "paras[0]", 1],
+ ["paras[0]", "document.doctype", "paras[0]", 0, "paras[0]", 1],
+];
+
+
+function testRemoveChild(affectedNode, startContainer, startOffset, endContainer, endOffset) {
+ var expectedStart = [startContainer, startOffset];
+ var expectedEnd = [endContainer, endOffset];
+
+ expectedStart = modifyForRemove(affectedNode, expectedStart);
+ expectedEnd = modifyForRemove(affectedNode, expectedEnd);
+
+ // We don't test cases where the parent is wrong, so this should never
+ // throw an exception.
+ affectedNode.parentNode.removeChild(affectedNode);
+
+ return expectedStart.concat(expectedEnd);
+}
+
+var removeChildTests = [
+ ["paras[0]", "paras[0]", 0, "paras[0]", 0],
+ ["paras[0]", "paras[0]", 0, "paras[0]", 1],
+ ["paras[0]", "paras[0]", 1, "paras[0]", 1],
+ ["paras[0]", "testDiv", 0, "testDiv", 0],
+ ["paras[0]", "testDiv", 0, "testDiv", 1],
+ ["paras[0]", "testDiv", 1, "testDiv", 1],
+ ["paras[0]", "testDiv", 0, "testDiv", 2],
+ ["paras[0]", "testDiv", 1, "testDiv", 2],
+ ["paras[0]", "testDiv", 2, "testDiv", 2],
+
+ ["foreignDoc.documentElement", "foreignDoc", 0, "foreignDoc", "foreignDoc.childNodes.length"],
+];
+
+
+// Finally run everything. All grouped together at the end so that I can
+// easily comment out some of them, so I don't have to wait for all test types
+// to debug only some of them.
+doTests(splitTextTests, function(params) { return params[0] + ".splitText(" + params[1] + ")" }, testSplitText);
+doTests(insertDataTests, function(params) { return params[0] + ".insertData(" + params[1] + ", " + params[2] + ")" }, testInsertData);
+doTests(appendDataTests, function(params) { return params[0] + ".appendData(" + params[1] + ")" }, testAppendData);
+doTests(deleteDataTests, function(params) { return params[0] + ".deleteData(" + params[1] + ", " + params[2] + ")" }, testDeleteData);
+doTests(replaceDataTests, function(params) { return params[0] + ".replaceData(" + params[1] + ", " + params[2] + ", " + params[3] + ")" }, testReplaceData);
+doTests(dataChangeTests, function(params) { return params[0] + "." + eval(params[1]) + " " + eval(params[2]) + ' ' + params[3] }, testDataChange);
+doTests(insertBeforeTests, function(params) { return params[0] + ".insertBefore(" + params[1] + ", " + params[2] + ")" }, testInsertBefore);
+doTests(replaceChildTests, function(params) { return params[0] + ".replaceChild(" + params[1] + ", " + params[2] + ")" }, testReplaceChild);
+doTests(appendChildTests, function(params) { return params[0] + ".appendChild(" + params[1] + ")" }, testAppendChild);
+doTests(removeChildTests, function(params) { return params[0] + ".parentNode.removeChild(" + params[0] + ")" }, testRemoveChild);
+
+
+testDiv.style.display = "none";
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/ranges/Range-selectNode.html b/tests/wpt/web-platform-tests/dom/ranges/Range-selectNode.html
new file mode 100644
index 00000000000..2d9ec6b9a78
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/ranges/Range-selectNode.html
@@ -0,0 +1,99 @@
+<!doctype html>
+<title>Range.selectNode() and .selectNodeContents() tests</title>
+<link rel="author" title="Aryeh Gregor" href=ayg@aryeh.name>
+<meta name=timeout content=long>
+<div id=log></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../common.js></script>
+<script>
+"use strict";
+
+function testSelectNode(range, node) {
+ try {
+ range.collapsed;
+ } catch (e) {
+ // Range is detached
+ assert_throws("INVALID_STATE_ERR", function () {
+ range.selectNode(node);
+ }, "selectNode() on a detached node must throw INVALID_STATE_ERR");
+ assert_throws("INVALID_STATE_ERR", function () {
+ range.selectNodeContents(node);
+ }, "selectNodeContents() on a detached node must throw INVALID_STATE_ERR");
+ return;
+ }
+
+ if (!node.parentNode) {
+ assert_throws("INVALID_NODE_TYPE_ERR", function() {
+ range.selectNode(node);
+ }, "selectNode() on a node with no parent must throw INVALID_NODE_TYPE_ERR");
+ } else {
+ var index = 0;
+ while (node.parentNode.childNodes[index] != node) {
+ index++;
+ }
+
+ range.selectNode(node);
+ assert_equals(range.startContainer, node.parentNode,
+ "After selectNode(), startContainer must equal parent node");
+ assert_equals(range.endContainer, node.parentNode,
+ "After selectNode(), endContainer must equal parent node");
+ assert_equals(range.startOffset, index,
+ "After selectNode(), startOffset must be index of node in parent (" + index + ")");
+ assert_equals(range.endOffset, index + 1,
+ "After selectNode(), endOffset must be one plus index of node in parent (" + (index + 1) + ")");
+ }
+
+ if (node.nodeType == Node.DOCUMENT_TYPE_NODE) {
+ assert_throws("INVALID_NODE_TYPE_ERR", function () {
+ range.selectNodeContents(node);
+ }, "selectNodeContents() on a doctype must throw INVALID_NODE_TYPE_ERR");
+ } else {
+ range.selectNodeContents(node);
+ assert_equals(range.startContainer, node,
+ "After selectNodeContents(), startContainer must equal node");
+ assert_equals(range.endContainer, node,
+ "After selectNodeContents(), endContainer must equal node");
+ assert_equals(range.startOffset, 0,
+ "After selectNodeContents(), startOffset must equal 0");
+ var len = nodeLength(node);
+ assert_equals(range.endOffset, len,
+ "After selectNodeContents(), endOffset must equal node length (" + len + ")");
+ }
+}
+
+var range = document.createRange();
+var foreignRange = foreignDoc.createRange();
+var xmlRange = xmlDoc.createRange();
+var detachedRange = document.createRange();
+detachedRange.detach();
+var tests = [];
+function testTree(root, marker) {
+ if (root.nodeType == Node.ELEMENT_NODE && root.id == "log") {
+ // This is being modified during the tests, so let's not test it.
+ return;
+ }
+ tests.push([marker + root.nodeName.toLowerCase() + " node, current doc's range, type " + root.nodeType, range, root]);
+ tests.push([marker + root.nodeName.toLowerCase() + " node, foreign doc's range, type " + root.nodeType, foreignRange, root]);
+ tests.push([marker + root.nodeName.toLowerCase() + " node, XML doc's range, type " + root.nodeType, xmlRange, root]);
+ tests.push([marker + root.nodeName.toLowerCase() + " node, detached range, type " + root.nodeType, detachedRange, root]);
+ for (var i = 0; i < root.childNodes.length; i++) {
+ testTree(root.childNodes[i], "**" + marker);
+ }
+}
+testTree(document, " current doc: ");
+testTree(foreignDoc, " foreign doc: ");
+testTree(detachedDiv, " detached div in current doc: ");
+
+var otherTests = [xmlDoc, xmlElement, detachedTextNode, foreignTextNode,
+xmlTextNode, processingInstruction, comment, foreignComment, xmlComment,
+docfrag, foreignDocfrag, xmlDocfrag];
+
+for (var i = 0; i < otherTests.length; i++) {
+ testTree(otherTests[i], " ");
+}
+
+generate_tests(testSelectNode, tests);
+
+testDiv.style.display = "none";
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/ranges/Range-set.html b/tests/wpt/web-platform-tests/dom/ranges/Range-set.html
new file mode 100644
index 00000000000..5b43c04f418
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/ranges/Range-set.html
@@ -0,0 +1,221 @@
+<!doctype html>
+<title>Range setting tests</title>
+<link rel="author" title="Aryeh Gregor" href=ayg@aryeh.name>
+<meta name=timeout content=long>
+
+<div id=log></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../common.js></script>
+<script>
+"use strict";
+
+function testSetStart(range, node, offset) {
+ if (node.nodeType == Node.DOCUMENT_TYPE_NODE) {
+ assert_throws("INVALID_NODE_TYPE_ERR", function() {
+ range.setStart(node, offset);
+ }, "setStart() to a doctype must throw INVALID_NODE_TYPE_ERR");
+ return;
+ }
+
+ if (offset < 0 || offset > nodeLength(node)) {
+ assert_throws("INDEX_SIZE_ERR", function() {
+ range.setStart(node, offset);
+ }, "setStart() to a too-large offset must throw INDEX_SIZE_ERR");
+ return;
+ }
+
+ var newRange = range.cloneRange();
+ newRange.setStart(node, offset);
+
+ assert_equals(newRange.startContainer, node,
+ "setStart() must change startContainer to the new node");
+ assert_equals(newRange.startOffset, offset,
+ "setStart() must change startOffset to the new offset");
+
+ // FIXME: I'm assuming comparePoint() is correct, but the tests for that
+ // will depend on setStart()/setEnd().
+ if (furthestAncestor(node) != furthestAncestor(range.startContainer)
+ || range.comparePoint(node, offset) > 0) {
+ assert_equals(newRange.endContainer, node,
+ "setStart(node, offset) where node is after current end or in different document must set the end node to node too");
+ assert_equals(newRange.endOffset, offset,
+ "setStart(node, offset) where node is after current end or in different document must set the end offset to offset too");
+ } else {
+ assert_equals(newRange.endContainer, range.endContainer,
+ "setStart() must not change the end node if the new start is before the old end");
+ assert_equals(newRange.endOffset, range.endOffset,
+ "setStart() must not change the end offset if the new start is before the old end");
+ }
+}
+
+function testSetEnd(range, node, offset) {
+ if (node.nodeType == Node.DOCUMENT_TYPE_NODE) {
+ assert_throws("INVALID_NODE_TYPE_ERR", function() {
+ range.setEnd(node, offset);
+ }, "setEnd() to a doctype must throw INVALID_NODE_TYPE_ERR");
+ return;
+ }
+
+ if (offset < 0 || offset > nodeLength(node)) {
+ assert_throws("INDEX_SIZE_ERR", function() {
+ range.setEnd(node, offset);
+ }, "setEnd() to a too-large offset must throw INDEX_SIZE_ERR");
+ return;
+ }
+
+ var newRange = range.cloneRange();
+ newRange.setEnd(node, offset);
+
+ // FIXME: I'm assuming comparePoint() is correct, but the tests for that
+ // will depend on setStart()/setEnd().
+ if (furthestAncestor(node) != furthestAncestor(range.startContainer)
+ || range.comparePoint(node, offset) < 0) {
+ assert_equals(newRange.startContainer, node,
+ "setEnd(node, offset) where node is before current start or in different document must set the end node to node too");
+ assert_equals(newRange.startOffset, offset,
+ "setEnd(node, offset) where node is before current start or in different document must set the end offset to offset too");
+ } else {
+ assert_equals(newRange.startContainer, range.startContainer,
+ "setEnd() must not change the start node if the new end is after the old start");
+ assert_equals(newRange.startOffset, range.startOffset,
+ "setEnd() must not change the start offset if the new end is after the old start");
+ }
+
+ assert_equals(newRange.endContainer, node,
+ "setEnd() must change endContainer to the new node");
+ assert_equals(newRange.endOffset, offset,
+ "setEnd() must change endOffset to the new offset");
+}
+
+function testSetStartBefore(range, node) {
+ var parent = node.parentNode;
+ if (parent === null) {
+ assert_throws("INVALID_NODE_TYPE_ERR", function () {
+ range.setStartBefore(node);
+ }, "setStartBefore() to a node with null parent must throw INVALID_NODE_TYPE_ERR");
+ return;
+ }
+
+ var idx = 0;
+ while (node.parentNode.childNodes[idx] != node) {
+ idx++;
+ }
+
+ testSetStart(range, node.parentNode, idx);
+}
+
+function testSetStartAfter(range, node) {
+ var parent = node.parentNode;
+ if (parent === null) {
+ assert_throws("INVALID_NODE_TYPE_ERR", function () {
+ range.setStartAfter(node);
+ }, "setStartAfter() to a node with null parent must throw INVALID_NODE_TYPE_ERR");
+ return;
+ }
+
+ var idx = 0;
+ while (node.parentNode.childNodes[idx] != node) {
+ idx++;
+ }
+
+ testSetStart(range, node.parentNode, idx + 1);
+}
+
+function testSetEndBefore(range, node) {
+ var parent = node.parentNode;
+ if (parent === null) {
+ assert_throws("INVALID_NODE_TYPE_ERR", function () {
+ range.setEndBefore(node);
+ }, "setEndBefore() to a node with null parent must throw INVALID_NODE_TYPE_ERR");
+ return;
+ }
+
+ var idx = 0;
+ while (node.parentNode.childNodes[idx] != node) {
+ idx++;
+ }
+
+ testSetEnd(range, node.parentNode, idx);
+}
+
+function testSetEndAfter(range, node) {
+ var parent = node.parentNode;
+ if (parent === null) {
+ assert_throws("INVALID_NODE_TYPE_ERR", function () {
+ range.setEndAfter(node);
+ }, "setEndAfter() to a node with null parent must throw INVALID_NODE_TYPE_ERR");
+ return;
+ }
+
+ var idx = 0;
+ while (node.parentNode.childNodes[idx] != node) {
+ idx++;
+ }
+
+ testSetEnd(range, node.parentNode, idx + 1);
+}
+
+
+var startTests = [];
+var endTests = [];
+var startBeforeTests = [];
+var startAfterTests = [];
+var endBeforeTests = [];
+var endAfterTests = [];
+
+// Don't want to eval() each point a bazillion times
+var testPointsCached = testPoints.map(eval);
+var testNodesCached = testNodesShort.map(eval);
+
+for (var i = 0; i < testRangesShort.length; i++) {
+ var endpoints = eval(testRangesShort[i]);
+ var range;
+ test(function() {
+ range = ownerDocument(endpoints[0]).createRange();
+ range.setStart(endpoints[0], endpoints[1]);
+ range.setEnd(endpoints[2], endpoints[3]);
+ }, "Set up range " + i + " " + testRangesShort[i]);
+
+ for (var j = 0; j < testPoints.length; j++) {
+ startTests.push(["setStart() with range " + i + " " + testRangesShort[i] + ", point " + j + " " + testPoints[j],
+ range,
+ testPointsCached[j][0],
+ testPointsCached[j][1]
+ ]);
+ endTests.push(["setEnd() with range " + i + " " + testRangesShort[i] + ", point " + j + " " + testPoints[j],
+ range,
+ testPointsCached[j][0],
+ testPointsCached[j][1]
+ ]);
+ }
+
+ for (var j = 0; j < testNodesShort.length; j++) {
+ startBeforeTests.push(["setStartBefore() with range " + i + " " + testRangesShort[i] + ", node " + j + " " + testNodesShort[j],
+ range,
+ testNodesCached[j]
+ ]);
+ startAfterTests.push(["setStartAfter() with range " + i + " " + testRangesShort[i] + ", node " + j + " " + testNodesShort[j],
+ range,
+ testNodesCached[j]
+ ]);
+ endBeforeTests.push(["setEndBefore() with range " + i + " " + testRangesShort[i] + ", node " + j + " " + testNodesShort[j],
+ range,
+ testNodesCached[j]
+ ]);
+ endAfterTests.push(["setEndAfter() with range " + i + " " + testRangesShort[i] + ", node " + j + " " + testNodesShort[j],
+ range,
+ testNodesCached[j]
+ ]);
+ }
+}
+
+generate_tests(testSetStart, startTests);
+generate_tests(testSetEnd, endTests);
+generate_tests(testSetStartBefore, startBeforeTests);
+generate_tests(testSetStartAfter, startAfterTests);
+generate_tests(testSetEndBefore, endBeforeTests);
+generate_tests(testSetEndAfter, endAfterTests);
+
+testDiv.style.display = "none";
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/ranges/Range-surroundContents.html b/tests/wpt/web-platform-tests/dom/ranges/Range-surroundContents.html
new file mode 100644
index 00000000000..1574e2221f2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/ranges/Range-surroundContents.html
@@ -0,0 +1,354 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Range.surroundContents() tests</title>
+<link rel="author" title="Aryeh Gregor" href=ayg@aryeh.name>
+<meta name=timeout content=long>
+<p>To debug test failures, add a query parameter "subtest" with the test id (like
+"?subtest=5,16"). Only that test will be run. Then you can look at the resulting
+iframes in the DOM.
+<div id=log></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../common.js></script>
+<script>
+"use strict";
+
+testDiv.parentNode.removeChild(testDiv);
+
+function mySurroundContents(range, newParent) {
+ try {
+ // "If the detached flag is set, throw an "InvalidStateError" exception
+ // and terminate these steps."
+ try {
+ range.collapsed;
+ } catch (e) {
+ return "INVALID_STATE_ERR";
+ }
+
+ // "If a non-Text node is partially contained in the context object,
+ // throw a "InvalidStateError" exception and terminate these steps."
+ var node = range.commonAncestorContainer;
+ var stop = nextNodeDescendants(node);
+ for (; node != stop; node = nextNode(node)) {
+ if (node.nodeType != Node.TEXT_NODE
+ && isPartiallyContained(node, range)) {
+ return "INVALID_STATE_ERR";
+ }
+ }
+
+ // "If newParent is a Document, DocumentType, or DocumentFragment node,
+ // throw an "InvalidNodeTypeError" exception and terminate these
+ // steps."
+ if (newParent.nodeType == Node.DOCUMENT_NODE
+ || newParent.nodeType == Node.DOCUMENT_TYPE_NODE
+ || newParent.nodeType == Node.DOCUMENT_FRAGMENT_NODE) {
+ return "INVALID_NODE_TYPE_ERR";
+ }
+
+ // "Call extractContents() on the context object, and let fragment be
+ // the result."
+ var fragment = myExtractContents(range);
+ if (typeof fragment == "string") {
+ return fragment;
+ }
+
+ // "While newParent has children, remove its first child."
+ while (newParent.childNodes.length) {
+ newParent.removeChild(newParent.firstChild);
+ }
+
+ // "Call insertNode(newParent) on the context object."
+ var ret = myInsertNode(range, newParent);
+ if (typeof ret == "string") {
+ return ret;
+ }
+
+ // "Call appendChild(fragment) on newParent."
+ newParent.appendChild(fragment);
+
+ // "Call selectNode(newParent) on the context object."
+ //
+ // We just reimplement this in-place.
+ if (!newParent.parentNode) {
+ return "INVALID_NODE_TYPE_ERR";
+ }
+ var index = indexOf(newParent);
+ range.setStart(newParent.parentNode, index);
+ range.setEnd(newParent.parentNode, index + 1);
+ } catch (e) {
+ return getDomExceptionName(e);
+ }
+}
+
+function restoreIframe(iframe, i, j) {
+ // Most of this function is designed to work around the fact that Opera
+ // doesn't let you add a doctype to a document that no longer has one, in
+ // any way I can figure out. I eventually compromised on something that
+ // will still let Opera pass most tests that don't actually involve
+ // doctypes.
+ while (iframe.contentDocument.firstChild
+ && iframe.contentDocument.firstChild.nodeType != Node.DOCUMENT_TYPE_NODE) {
+ iframe.contentDocument.removeChild(iframe.contentDocument.firstChild);
+ }
+
+ while (iframe.contentDocument.lastChild
+ && iframe.contentDocument.lastChild.nodeType != Node.DOCUMENT_TYPE_NODE) {
+ iframe.contentDocument.removeChild(iframe.contentDocument.lastChild);
+ }
+
+ if (!iframe.contentDocument.firstChild) {
+ // This will throw an exception in Opera if we reach here, which is why
+ // I try to avoid it. It will never happen in a browser that obeys the
+ // spec, so it's really just insurance. I don't think it actually gets
+ // hit by anything.
+ iframe.contentDocument.appendChild(iframe.contentDocument.implementation.createDocumentType("html", "", ""));
+ }
+ iframe.contentDocument.appendChild(referenceDoc.documentElement.cloneNode(true));
+ iframe.contentWindow.setupRangeTests();
+ iframe.contentWindow.testRangeInput = testRangesShort[i];
+ iframe.contentWindow.testNodeInput = testNodesShort[j];
+ iframe.contentWindow.run();
+}
+
+function testSurroundContents(i, j) {
+ var actualRange;
+ var expectedRange;
+ var actualNode;
+ var expectedNode;
+ var actualRoots = [];
+ var expectedRoots = [];
+
+ var detached = false;
+
+ domTests[i][j].step(function() {
+ restoreIframe(actualIframe, i, j);
+ restoreIframe(expectedIframe, i, j);
+
+ actualRange = actualIframe.contentWindow.testRange;
+ expectedRange = expectedIframe.contentWindow.testRange;
+ actualNode = actualIframe.contentWindow.testNode;
+ expectedNode = expectedIframe.contentWindow.testNode;
+
+ try {
+ actualRange.collapsed;
+ } catch (e) {
+ detached = true;
+ }
+
+ assert_equals(actualIframe.contentWindow.unexpectedException, null,
+ "Unexpected exception thrown when setting up Range for actual surroundContents()");
+ assert_equals(expectedIframe.contentWindow.unexpectedException, null,
+ "Unexpected exception thrown when setting up Range for simulated surroundContents()");
+ assert_equals(typeof actualRange, "object",
+ "typeof Range produced in actual iframe");
+ assert_false(actualRange === null,
+ "Range produced in actual iframe was null");
+ assert_equals(typeof expectedRange, "object",
+ "typeof Range produced in expected iframe");
+ assert_false(expectedRange === null,
+ "Range produced in expected iframe was null");
+ assert_equals(typeof actualNode, "object",
+ "typeof Node produced in actual iframe");
+ assert_false(actualNode === null,
+ "Node produced in actual iframe was null");
+ assert_equals(typeof expectedNode, "object",
+ "typeof Node produced in expected iframe");
+ assert_false(expectedNode === null,
+ "Node produced in expected iframe was null");
+
+ // We want to test that the trees containing the ranges are equal, and
+ // also the trees containing the moved nodes. These might not be the
+ // same, if we're inserting a node from a detached tree or a different
+ // document.
+ //
+ // Detached ranges are always in the contentDocument.
+ if (detached) {
+ actualRoots.push(actualIframe.contentDocument);
+ expectedRoots.push(expectedIframe.contentDocument);
+ } else {
+ actualRoots.push(furthestAncestor(actualRange.startContainer));
+ expectedRoots.push(furthestAncestor(expectedRange.startContainer));
+ }
+
+ if (furthestAncestor(actualNode) != actualRoots[0]) {
+ actualRoots.push(furthestAncestor(actualNode));
+ }
+ if (furthestAncestor(expectedNode) != expectedRoots[0]) {
+ expectedRoots.push(furthestAncestor(expectedNode));
+ }
+
+ assert_equals(actualRoots.length, expectedRoots.length,
+ "Either the actual node and actual range are in the same tree but the expected are in different trees, or vice versa");
+
+ // This doctype stuff is to work around the fact that Opera 11.00 will
+ // move around doctypes within a document, even to totally invalid
+ // positions, but it won't allow a new doctype to be added to a
+ // document in any way I can figure out. So if we try moving a doctype
+ // to some invalid place, in Opera it will actually succeed, and then
+ // restoreIframe() will remove the doctype along with the root element,
+ // and then nothing can re-add the doctype. So instead, we catch it
+ // during the test itself and move it back to the right place while we
+ // still can.
+ //
+ // I spent *way* too much time debugging and working around this bug.
+ var actualDoctype = actualIframe.contentDocument.doctype;
+ var expectedDoctype = expectedIframe.contentDocument.doctype;
+
+ var result;
+ try {
+ result = mySurroundContents(expectedRange, expectedNode);
+ } catch (e) {
+ if (expectedDoctype != expectedIframe.contentDocument.firstChild) {
+ expectedIframe.contentDocument.insertBefore(expectedDoctype, expectedIframe.contentDocument.firstChild);
+ }
+ throw e;
+ }
+ if (typeof result == "string") {
+ assert_throws(result, function() {
+ try {
+ actualRange.surroundContents(actualNode);
+ } catch (e) {
+ if (expectedDoctype != expectedIframe.contentDocument.firstChild) {
+ expectedIframe.contentDocument.insertBefore(expectedDoctype, expectedIframe.contentDocument.firstChild);
+ }
+ if (actualDoctype != actualIframe.contentDocument.firstChild) {
+ actualIframe.contentDocument.insertBefore(actualDoctype, actualIframe.contentDocument.firstChild);
+ }
+ throw e;
+ }
+ }, "A " + result + " must be thrown in this case");
+ // Don't return, we still need to test DOM equality
+ } else {
+ try {
+ actualRange.surroundContents(actualNode);
+ } catch (e) {
+ if (expectedDoctype != expectedIframe.contentDocument.firstChild) {
+ expectedIframe.contentDocument.insertBefore(expectedDoctype, expectedIframe.contentDocument.firstChild);
+ }
+ if (actualDoctype != actualIframe.contentDocument.firstChild) {
+ actualIframe.contentDocument.insertBefore(actualDoctype, actualIframe.contentDocument.firstChild);
+ }
+ throw e;
+ }
+ }
+
+ for (var k = 0; k < actualRoots.length; k++) {
+ assertNodesEqual(actualRoots[k], expectedRoots[k], k ? "moved node's tree root" : "range's tree root");
+ }
+ });
+ domTests[i][j].done();
+
+ positionTests[i][j].step(function() {
+ assert_equals(actualIframe.contentWindow.unexpectedException, null,
+ "Unexpected exception thrown when setting up Range for actual surroundContents()");
+ assert_equals(expectedIframe.contentWindow.unexpectedException, null,
+ "Unexpected exception thrown when setting up Range for simulated surroundContents()");
+ assert_equals(typeof actualRange, "object",
+ "typeof Range produced in actual iframe");
+ assert_false(actualRange === null,
+ "Range produced in actual iframe was null");
+ assert_equals(typeof expectedRange, "object",
+ "typeof Range produced in expected iframe");
+ assert_false(expectedRange === null,
+ "Range produced in expected iframe was null");
+ assert_equals(typeof actualNode, "object",
+ "typeof Node produced in actual iframe");
+ assert_false(actualNode === null,
+ "Node produced in actual iframe was null");
+ assert_equals(typeof expectedNode, "object",
+ "typeof Node produced in expected iframe");
+ assert_false(expectedNode === null,
+ "Node produced in expected iframe was null");
+
+ for (var k = 0; k < actualRoots.length; k++) {
+ assertNodesEqual(actualRoots[k], expectedRoots[k], k ? "moved node's tree root" : "range's tree root");
+ }
+
+ if (detached) {
+ // No further tests we can do
+ return;
+ }
+
+ assert_equals(actualRange.startOffset, expectedRange.startOffset,
+ "Unexpected startOffset after surroundContents()");
+ assert_equals(actualRange.endOffset, expectedRange.endOffset,
+ "Unexpected endOffset after surroundContents()");
+ // How do we decide that the two nodes are equal, since they're in
+ // different trees? Since the DOMs are the same, it's enough to check
+ // that the index in the parent is the same all the way up the tree.
+ // But we can first cheat by just checking they're actually equal.
+ assert_true(actualRange.startContainer.isEqualNode(expectedRange.startContainer),
+ "Unexpected startContainer after surroundContents(), expected " +
+ expectedRange.startContainer.nodeName.toLowerCase() + " but got " +
+ actualRange.startContainer.nodeName.toLowerCase());
+ var currentActual = actualRange.startContainer;
+ var currentExpected = expectedRange.startContainer;
+ var actual = "";
+ var expected = "";
+ while (currentActual && currentExpected) {
+ actual = indexOf(currentActual) + "-" + actual;
+ expected = indexOf(currentExpected) + "-" + expected;
+
+ currentActual = currentActual.parentNode;
+ currentExpected = currentExpected.parentNode;
+ }
+ actual = actual.substr(0, actual.length - 1);
+ expected = expected.substr(0, expected.length - 1);
+ assert_equals(actual, expected,
+ "startContainer superficially looks right but is actually the wrong node if you trace back its index in all its ancestors (I'm surprised this actually happened");
+ });
+ positionTests[i][j].done();
+}
+
+testRanges.unshift('"detached"');
+
+var iStart = 0;
+var iStop = testRangesShort.length;
+var jStart = 0;
+var jStop = testNodesShort.length;
+
+if (/subtest=[0-9]+,[0-9]+/.test(location.search)) {
+ var matches = /subtest=([0-9]+),([0-9]+)/.exec(location.search);
+ iStart = Number(matches[1]);
+ iStop = Number(matches[1]) + 1;
+ jStart = Number(matches[2]) + 0;
+ jStop = Number(matches[2]) + 1;
+}
+
+var domTests = [];
+var positionTests = [];
+for (var i = iStart; i < iStop; i++) {
+ domTests[i] = [];
+ positionTests[i] = [];
+ for (var j = jStart; j < jStop; j++) {
+ domTests[i][j] = async_test(i + "," + j + ": resulting DOM for range " + testRangesShort[i] + ", node " + testNodesShort[j]);
+ positionTests[i][j] = async_test(i + "," + j + ": resulting range position for range " + testRangesShort[i] + ", node " + testNodesShort[j]);
+ }
+}
+
+var actualIframe = document.createElement("iframe");
+actualIframe.style.display = "none";
+actualIframe.id = "actual";
+document.body.appendChild(actualIframe);
+
+var expectedIframe = document.createElement("iframe");
+expectedIframe.style.display = "none";
+expectedIframe.id = "expected";
+document.body.appendChild(expectedIframe);
+
+var referenceDoc = document.implementation.createHTMLDocument("");
+referenceDoc.removeChild(referenceDoc.documentElement);
+
+actualIframe.onload = function() {
+ expectedIframe.onload = function() {
+ for (var i = iStart; i < iStop; i++) {
+ for (var j = jStart; j < jStop; j++) {
+ testSurroundContents(i, j);
+ }
+ }
+ }
+ expectedIframe.src = "Range-test-iframe.html";
+ referenceDoc.appendChild(actualIframe.contentDocument.documentElement.cloneNode(true));
+}
+actualIframe.src = "Range-test-iframe.html";
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/ranges/Range-test-iframe.html b/tests/wpt/web-platform-tests/dom/ranges/Range-test-iframe.html
new file mode 100644
index 00000000000..f354ff758fc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/ranges/Range-test-iframe.html
@@ -0,0 +1,56 @@
+<!doctype html>
+<title>Range test iframe</title>
+<link rel="author" title="Aryeh Gregor" href=ayg@aryeh.name>
+<meta name=timeout content=long>
+<body onload=run()>
+<script src=../common.js></script>
+<script>
+"use strict";
+
+// This script only exists because we want to evaluate the range endpoints
+// in each iframe using that iframe's local variables set up by common.js. It
+// just creates the range and does nothing else. The data is returned via
+// window.testRange, and if an exception is thrown, it's put in
+// window.unexpectedException.
+window.unexpectedException = null;
+
+function run() {
+ try {
+ window.unexpectedException = null;
+
+ if (typeof window.testNodeInput != "undefined") {
+ window.testNode = eval(window.testNodeInput);
+ }
+
+ var rangeEndpoints;
+ if (typeof window.testRangeInput == "undefined") {
+ // Use the hash (old way of doing things, bad because it requires
+ // navigation)
+ if (location.hash == "") {
+ return;
+ }
+ rangeEndpoints = eval(location.hash.substr(1));
+ } else {
+ // Get the variable directly off the window, faster and can be done
+ // synchronously
+ rangeEndpoints = eval(window.testRangeInput);
+ }
+
+ var range;
+ if (rangeEndpoints == "detached") {
+ range = document.createRange();
+ range.detach();
+ } else {
+ range = ownerDocument(rangeEndpoints[0]).createRange();
+ range.setStart(rangeEndpoints[0], rangeEndpoints[1]);
+ range.setEnd(rangeEndpoints[2], rangeEndpoints[3]);
+ }
+
+ window.testRange = range;
+ } catch(e) {
+ window.unexpectedException = e;
+ }
+}
+
+testDiv.style.display = "none";
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/traversal/NodeFilter-constants.html b/tests/wpt/web-platform-tests/dom/traversal/NodeFilter-constants.html
new file mode 100644
index 00000000000..1ce4736cc61
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/traversal/NodeFilter-constants.html
@@ -0,0 +1,34 @@
+<!doctype html>
+<title>NodeFilter constants</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../constants.js"></script>
+<div id="log"></div>
+<script>
+var objects;
+setup(function() {
+ objects = [
+ [NodeFilter, "NodeFilter interface object"],
+ ]
+})
+testConstants(objects, [
+ ["FILTER_ACCEPT", 1],
+ ["FILTER_REJECT", 2],
+ ["FILTER_SKIP", 3]
+], "acceptNode")
+testConstants(objects, [
+ ["SHOW_ALL", 0xFFFFFFFF],
+ ["SHOW_ELEMENT", 0x1],
+ ["SHOW_ATTRIBUTE", 0x2],
+ ["SHOW_TEXT", 0x4],
+ ["SHOW_CDATA_SECTION", 0x8],
+ ["SHOW_ENTITY_REFERENCE", 0x10],
+ ["SHOW_ENTITY", 0x20],
+ ["SHOW_PROCESSING_INSTRUCTION", 0x40],
+ ["SHOW_COMMENT", 0x80],
+ ["SHOW_DOCUMENT", 0x100],
+ ["SHOW_DOCUMENT_TYPE", 0x200],
+ ["SHOW_DOCUMENT_FRAGMENT", 0x400],
+ ["SHOW_NOTATION", 0x800]
+], "whatToShow")
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/traversal/NodeIterator-removal.html b/tests/wpt/web-platform-tests/dom/traversal/NodeIterator-removal.html
new file mode 100644
index 00000000000..b5fc69541ab
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/traversal/NodeIterator-removal.html
@@ -0,0 +1,100 @@
+<!doctype html>
+<title>NodeIterator removal tests</title>
+<link rel="author" title="Aryeh Gregor" href=ayg@aryeh.name>
+<meta name=timeout content=long>
+<div id=log></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../common.js></script>
+<script>
+"use strict";
+
+for (var i = 0; i < testNodes.length; i++) {
+ var node = eval(testNodes[i]);
+ if (!node.parentNode) {
+ // Nothing to test
+ continue;
+ }
+ test(function() {
+ var iters = [];
+ var descs = [];
+ var expectedReferenceNodes = [];
+ var expectedPointers = [];
+
+ for (var j = 0; j < testNodes.length; j++) {
+ var root = eval(testNodes[j]);
+ // Add all distinct iterators with this root, calling nextNode()
+ // repeatedly until it winds up with the same iterator.
+ for (var k = 0; ; k++) {
+ var iter = document.createNodeIterator(root);
+ for (var l = 0; l < k; l++) {
+ iter.nextNode();
+ }
+ if (k && iter.referenceNode == iters[iters.length - 1].referenceNode
+ && iter.pointerBeforeReferenceNode
+ == iters[iters.length - 1].pointerBeforeReferenceNode) {
+ break;
+ } else {
+ iters.push(iter);
+ descs.push("document.createNodeIterator(" + testNodes[j]
+ + ") advanced " + k + " times");
+ expectedReferenceNodes.push(iter.referenceNode);
+ expectedPointers.push(iter.pointerBeforeReferenceNode);
+
+ var idx = iters.length - 1;
+
+ // "If the node is root or is not an inclusive ancestor of the
+ // referenceNode attribute value, terminate these steps."
+ //
+ // We also have to rule out the case where node is an ancestor of
+ // root, which is implicitly handled by the spec since such a node
+ // was not part of the iterator collection to start with.
+ if (isInclusiveAncestor(node, root)
+ || !isInclusiveAncestor(node, iter.referenceNode)) {
+ continue;
+ }
+
+ // "If the pointerBeforeReferenceNode attribute value is false, set
+ // the referenceNode attribute to the first node preceding the node
+ // that is being removed, and terminate these steps."
+ if (!iter.pointerBeforeReferenceNode) {
+ expectedReferenceNodes[idx] = previousNode(node);
+ continue;
+ }
+
+ // "If there is a node following the last inclusive descendant of the
+ // node that is being removed, set the referenceNode attribute to the
+ // first such node, and terminate these steps."
+ var next = nextNodeDescendants(node);
+ if (next) {
+ expectedReferenceNodes[idx] = next;
+ continue;
+ }
+
+ // "Set the referenceNode attribute to the first node preceding the
+ // node that is being removed and set the pointerBeforeReferenceNode
+ // attribute to false."
+ expectedReferenceNodes[idx] = previousNode(node);
+ expectedPointers[idx] = false;
+ }
+ }
+ }
+
+ var oldParent = node.parentNode;
+ var oldSibling = node.nextSibling;
+ oldParent.removeChild(node);
+
+ for (var j = 0; j < iters.length; j++) {
+ var iter = iters[j];
+ assert_equals(iter.referenceNode, expectedReferenceNodes[j],
+ ".referenceNode of " + descs[j]);
+ assert_equals(iter.pointerBeforeReferenceNode, expectedPointers[j],
+ ".pointerBeforeReferenceNode of " + descs[j]);
+ }
+
+ oldParent.insertBefore(node, oldSibling);
+ }, "Test removing node " + testNodes[i]);
+}
+
+testDiv.style.display = "none";
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/traversal/NodeIterator.html b/tests/wpt/web-platform-tests/dom/traversal/NodeIterator.html
new file mode 100644
index 00000000000..edcbf2c4e4b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/traversal/NodeIterator.html
@@ -0,0 +1,177 @@
+<!doctype html>
+<title>NodeIterator tests</title>
+<link rel="author" title="Aryeh Gregor" href=ayg@aryeh.name>
+<meta name=timeout content=long>
+<div id=log></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../common.js></script>
+<script>
+"use strict";
+
+test(function() {
+ var iter = document.createNodeIterator(document);
+ iter.detach();
+ iter.detach();
+}, "detach() should be a no-op");
+
+test(function() {
+ var iter = document.createNodeIterator(document);
+ assert_equals(iter.whatToShow, 0xFFFFFFFF, "whatToShow");
+ assert_equals(iter.filter, null, "filter");
+}, "createNodeIterator() parameter defaults");
+
+test(function() {
+ var iter = document.createNodeIterator(document, NodeFilter.SHOW_ALL,
+ function() { throw {name: "failed"} });
+ assert_throws({name: "failed"}, function() { iter.nextNode() });
+}, "Propagate exception from filter function");
+
+function testIterator(root, whatToShow, filter) {
+ var iter = document.createNodeIterator(root, whatToShow, filter);
+
+ assert_equals(iter.root, root, ".root");
+ assert_equals(iter.referenceNode, root, "Initial .referenceNode");
+ assert_equals(iter.pointerBeforeReferenceNode, true,
+ ".pointerBeforeReferenceNode");
+ assert_equals(iter.whatToShow, whatToShow, ".whatToShow");
+ assert_equals(iter.filter, filter, ".filter");
+
+ var expectedReferenceNode = root;
+ var expectedBeforeNode = true;
+ // "Let node be the value of the referenceNode attribute."
+ var node = root;
+ // "Let before node be the value of the pointerBeforeReferenceNode
+ // attribute."
+ var beforeNode = true;
+ var i = 1;
+ // Each loop iteration runs nextNode() once.
+ while (node) {
+ do {
+ if (!beforeNode) {
+ // "If before node is false, let node be the first node following node
+ // in the iterator collection. If there is no such node return null."
+ node = nextNode(node);
+ if (!isInclusiveDescendant(node, root)) {
+ node = null;
+ break;
+ }
+ } else {
+ // "If before node is true, set it to false."
+ beforeNode = false;
+ }
+ // "Filter node and let result be the return value.
+ //
+ // "If result is FILTER_ACCEPT, go to the next step in the overall set of
+ // steps.
+ //
+ // "Otherwise, run these substeps again."
+ if (!((1 << (node.nodeType - 1)) & whatToShow)
+ || (filter && filter(node) != NodeFilter.FILTER_ACCEPT)) {
+ continue;
+ }
+
+ // "Set the referenceNode attribute to node, set the
+ // pointerBeforeReferenceNode attribute to before node, and return node."
+ expectedReferenceNode = node;
+ expectedBeforeNode = beforeNode;
+
+ break;
+ } while (true);
+
+ assert_equals(iter.nextNode(), node, ".nextNode() " + i + " time(s)");
+ assert_equals(iter.referenceNode, expectedReferenceNode,
+ ".referenceNode after nextNode() " + i + " time(s)");
+ assert_equals(iter.pointerBeforeReferenceNode, expectedBeforeNode,
+ ".pointerBeforeReferenceNode after nextNode() " + i + " time(s)");
+
+ i++;
+ }
+
+ // Same but for previousNode() (mostly copy-pasted, oh well)
+ var iter = document.createNodeIterator(root, whatToShow, filter);
+
+ var expectedReferenceNode = root;
+ var expectedBeforeNode = true;
+ // "Let node be the value of the referenceNode attribute."
+ var node = root;
+ // "Let before node be the value of the pointerBeforeReferenceNode
+ // attribute."
+ var beforeNode = true;
+ var i = 1;
+ // Each loop iteration runs previousNode() once.
+ while (node) {
+ do {
+ if (beforeNode) {
+ // "If before node is true, let node be the first node preceding node
+ // in the iterator collection. If there is no such node return null."
+ node = previousNode(node);
+ if (!isInclusiveDescendant(node, root)) {
+ node = null;
+ break;
+ }
+ } else {
+ // "If before node is false, set it to true."
+ beforeNode = true;
+ }
+ // "Filter node and let result be the return value.
+ //
+ // "If result is FILTER_ACCEPT, go to the next step in the overall set of
+ // steps.
+ //
+ // "Otherwise, run these substeps again."
+ if (!((1 << (node.nodeType - 1)) & whatToShow)
+ || (filter && filter(node) != NodeFilter.FILTER_ACCEPT)) {
+ continue;
+ }
+
+ // "Set the referenceNode attribute to node, set the
+ // pointerBeforeReferenceNode attribute to before node, and return node."
+ expectedReferenceNode = node;
+ expectedBeforeNode = beforeNode;
+
+ break;
+ } while (true);
+
+ assert_equals(iter.previousNode(), node, ".previousNode() " + i + " time(s)");
+ assert_equals(iter.referenceNode, expectedReferenceNode,
+ ".referenceNode after previousNode() " + i + " time(s)");
+ assert_equals(iter.pointerBeforeReferenceNode, expectedBeforeNode,
+ ".pointerBeforeReferenceNode after previousNode() " + i + " time(s)");
+
+ i++;
+ }
+}
+
+var whatToShows = [
+ "0",
+ "0xFFFFFFFF",
+ "NodeFilter.SHOW_ELEMENT",
+ "NodeFilter.SHOW_ATTRIBUTE",
+ "NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_DOCUMENT",
+];
+
+var callbacks = [
+ "null",
+ "(function(node) { return true })",
+ "(function(node) { return false })",
+ "(function(node) { return node.nodeName[0] == '#' })",
+];
+
+var tests = [];
+for (var i = 0; i < testNodes.length; i++) {
+ for (var j = 0; j < whatToShows.length; j++) {
+ for (var k = 0; k < callbacks.length; k++) {
+ tests.push([
+ "document.createNodeIterator(" + testNodes[i]
+ + ", " + whatToShows[j] + ", " + callbacks[k] + ")",
+ eval(testNodes[i]), eval(whatToShows[j]), eval(callbacks[k])
+ ]);
+ }
+ }
+}
+
+generate_tests(testIterator, tests);
+
+testDiv.style.display = "none";
+</script>
diff --git a/tests/wpt/web-platform-tests/dom/traversal/TreeWalker-acceptNode-filter.html b/tests/wpt/web-platform-tests/dom/traversal/TreeWalker-acceptNode-filter.html
new file mode 100644
index 00000000000..1bd28f3b885
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/traversal/TreeWalker-acceptNode-filter.html
@@ -0,0 +1,160 @@
+<!DOCTYPE html>
+<html>
+<!--
+Test adapted from https://mxr.mozilla.org/chromium/source/src/third_party/WebKit/LayoutTests/fast/dom/TreeWalker/script-tests/acceptNode-filter.js
+-->
+<head>
+<title>TreeWalker: acceptNode-filter</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="traversal-support.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+<div id=log></div>
+</head>
+<body>
+<p>Test JS objects as NodeFilters</p>
+<script>
+var testElement;
+setup(function() {
+ testElement = document.createElement("div");
+ testElement.id = 'root';
+ //testElement.innerHTML='<div id="A1"><div id="B1"></div><div id="B2"></div></div>';
+
+ // XXX for Servo, build the tree without using innerHTML
+ var a1 = document.createElement("div");
+ a1.id = "A1";
+ var b1 = document.createElement("div");
+ b1.id = "B1";
+ var b2 = document.createElement("div");
+ b2.id = "B2";
+ testElement.appendChild(a1);
+ a1.appendChild(b1);
+ a1.appendChild(b2);
+});
+
+test(function()
+{
+ function filter(node)
+ {
+ if (node.id == "B1")
+ return /*NodeFilter.*/FILTER_SKIP;
+ return /*NodeFilter.*/FILTER_ACCEPT;
+ }
+
+ var walker = document.createTreeWalker(testElement, /*NodeFilter.*/SHOW_ELEMENT, filter);
+ assert_node(walker.currentNode, { type: Element, id: 'root' });
+ assert_node(walker.firstChild(), { type: Element, id: 'A1' });
+ assert_node(walker.currentNode, { type: Element, id: 'A1' });
+ assert_node(walker.nextNode(), { type: Element, id: 'B2' });
+ assert_node(walker.currentNode, { type: Element, id: 'B2' });
+}, 'Testing with raw function filter');
+
+test(function()
+{
+ var walker = document.createTreeWalker(testElement, /*NodeFilter.*/SHOW_ELEMENT, {
+ acceptNode : function(node) {
+ if (node.id == "B1")
+ return /*NodeFilter.*/FILTER_SKIP;
+ return /*NodeFilter.*/FILTER_ACCEPT;
+ }
+ });
+ assert_node(walker.currentNode, { type: Element, id: 'root' });
+ assert_node(walker.firstChild(), { type: Element, id: 'A1' });
+ assert_node(walker.currentNode, { type: Element, id: 'A1' });
+ assert_node(walker.nextNode(), { type: Element, id: 'B2' });
+ assert_node(walker.currentNode, { type: Element, id: 'B2' });
+}, 'Testing with object filter');
+
+test(function()
+{
+ var walker = document.createTreeWalker(testElement, /*NodeFilter.*/SHOW_ELEMENT, null);
+ assert_node(walker.currentNode, { type: Element, id: 'root' });
+ assert_node(walker.firstChild(), { type: Element, id: 'A1' });
+ assert_node(walker.currentNode, { type: Element, id: 'A1' });
+ assert_node(walker.nextNode(), { type: Element, id: 'B1' });
+ assert_node(walker.currentNode, { type: Element, id: 'B1' });
+}, 'Testing with null filter');
+
+test(function()
+{
+ var walker = document.createTreeWalker(testElement, /*NodeFilter.*/SHOW_ELEMENT, undefined);
+ assert_node(walker.currentNode, { type: Element, id: 'root' });
+ assert_node(walker.firstChild(), { type: Element, id: 'A1' });
+ assert_node(walker.currentNode, { type: Element, id: 'A1' });
+ assert_node(walker.nextNode(), { type: Element, id: 'B1' });
+ assert_node(walker.currentNode, { type: Element, id: 'B1' });
+}, 'Testing with undefined filter');
+
+// XXX Servo breaks the test when a callback isn't callable
+test(function()
+{
+ var walker = document.createTreeWalker(testElement, /*NodeFilter.*/SHOW_ELEMENT, {});
+ assert_throws(null, function () { walker.firstChild(); });
+ assert_node(walker.currentNode, { type: Element, id: 'root' });
+ assert_throws(null, function () { walker.nextNode(); });
+ assert_node(walker.currentNode, { type: Element, id: 'root' });
+}, 'Testing with object lacking acceptNode property');
+
+// XXX Servo breaks the test when a callback isn't callable
+test(function()
+{
+ var walker = document.createTreeWalker(testElement, /*NodeFilter.*/SHOW_ELEMENT, { acceptNode: "foo" });
+ assert_throws(null, function () { walker.firstChild(); });
+ assert_node(walker.currentNode, { type: Element, id: 'root' });
+ assert_throws(null, function () { walker.nextNode(); });
+ assert_node(walker.currentNode, { type: Element, id: 'root' });
+}, 'Testing with object with non-function acceptNode property');
+
+test(function()
+{
+ var filter = function() { return /*NodeFilter.*/FILTER_ACCEPT; };
+ filter.acceptNode = function(node) { return /*NodeFilter.*/FILTER_SKIP; };
+ var walker = document.createTreeWalker(testElement, /*NodeFilter.*/SHOW_ELEMENT, filter);
+ assert_node(walker.firstChild(), { type: Element, id: 'A1' });
+ assert_node(walker.nextNode(), { type: Element, id: 'B1' });
+}, 'Testing with function having acceptNode function');
+
+test(function()
+{
+ var filter = {
+ acceptNode: function(node) {
+ return /*NodeFilter.*/FILTER_ACCEPT;
+ }
+ };
+ var walker = document.createTreeWalker(testElement, /*NodeFilter.*/SHOW_ELEMENT, filter);
+ assert_node(walker.firstChild(), { type: Element, id: 'A1' });
+}, 'Testing acceptNode callee');
+
+// XXX Looks like Servo is doing something wrong when a callback function throws
+test(function()
+{
+ var walker = document.createTreeWalker(testElement, /*NodeFilter.*/SHOW_ELEMENT,
+ function(node) {
+ throw('filter exception');
+ return /*NodeFilter.*/FILTER_ACCEPT;
+ });
+ assert_throws(null, function () { walker.firstChild(); });
+ assert_node(walker.currentNode, { type: Element, id: 'root' });
+ assert_throws(null, function () { walker.nextNode(); });
+ assert_node(walker.currentNode, { type: Element, id: 'root' });
+}, 'Testing with filter function that throws');
+
+// XXX Looks like Servo is doing something wrong when a callback function throws
+test(function()
+{
+ var walker = document.createTreeWalker(testElement, /*NodeFilter.*/SHOW_ELEMENT,
+ {
+ acceptNode : function(node) {
+ throw('filter exception');
+ return /*NodeFilter.*/FILTER_ACCEPT;
+ }
+ });
+ assert_throws(null, function () { walker.firstChild(); });
+ assert_node(walker.currentNode, { type: Element, id: 'root' });
+ assert_throws(null, function () { walker.nextNode(); });
+ assert_node(walker.currentNode, { type: Element, id: 'root' });
+}, 'Testing with filter object that throws');
+
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/traversal/TreeWalker-basic.html b/tests/wpt/web-platform-tests/dom/traversal/TreeWalker-basic.html
new file mode 100644
index 00000000000..0720c7c1c6a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/traversal/TreeWalker-basic.html
@@ -0,0 +1,146 @@
+<!DOCTYPE html>
+<html>
+<!--
+Test adapted from https://mxr.mozilla.org/chromium/source/src/third_party/WebKit/LayoutTests/fast/dom/TreeWalker/TreeWalker-basic.html
+-->
+<head>
+<title>TreeWalker: Basic test</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="traversal-support.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+<div id=log></div>
+</head>
+<body>
+<p>This test checks the basic functionality of TreeWalker.</p>
+<script>
+function createSampleDOM()
+{
+ // Tree structure:
+ // #a
+ // |
+ // +----+----+
+ // | |
+ // "b" #c
+ // |
+ // +----+----+
+ // | |
+ // #d <!--j-->
+ // |
+ // +----+----+
+ // | | |
+ // "e" #f "i"
+ // |
+ // +--+--+
+ // | |
+ // "g" <!--h-->
+ var div = document.createElement('div');
+ div.id = 'a';
+ // div.innerHTML = 'b<div id="c"><div id="d">e<span id="f">g<!--h--></span>i</div><!--j--></div>';
+
+ div.appendChild(document.createTextNode("b"));
+
+ var c = document.createElement("div");
+ c.id = 'c';
+ div.appendChild(c);
+
+ var d = document.createElement("div");
+ d.id = 'd';
+ c.appendChild(d);
+
+ var e = document.createTextNode("e");
+ d.appendChild(e);
+
+ var f = document.createElement("span");
+ f.id = 'f';
+ d.appendChild(f);
+
+ var g = document.createTextNode("g");
+ f.appendChild(g);
+
+ var h = document.createComment("h");
+ f.appendChild(h);
+
+ var i = document.createTextNode("i");
+ d.appendChild(i);
+
+ var j = document.createComment("j");
+ c.appendChild(j);
+
+ return div;
+}
+
+function check_walker(walker, root)
+{
+ assert_equals(walker.toString(), '[object TreeWalker]');
+ assert_equals(walker.root, root);
+ assert_equals(walker.whatToShow, 0xFFFFFFFF);
+ assert_equals(walker.filter, null);
+ assert_equals(walker.currentNode, root);
+ assert_readonly(walker, 'root');
+ assert_readonly(walker, 'whatToShow');
+ assert_readonly(walker, 'filter');
+}
+
+test(function ()
+{
+ var root = createSampleDOM();
+ var walker = document.createTreeWalker(root);
+ check_walker(walker, root);
+}, 'Construct a TreeWalker by document.createTreeWalker(root).');
+
+test(function ()
+{
+ var root = createSampleDOM();
+ var walker = document.createTreeWalker(root, undefined, undefined);
+ check_walker(walker, root);
+}, 'Construct a TreeWalker by document.createTreeWalker(root, undefined, undefined).');
+
+test(function ()
+{
+ assert_throws(new TypeError(), function () { document.createTreeWalker(); });
+ assert_throws(new TypeError(), function () { document.createTreeWalker(null); });
+ assert_throws(new TypeError(), function () { document.createTreeWalker(undefined); });
+ assert_throws(new TypeError(), function () { document.createTreeWalker(new Object()); });
+ assert_throws(new TypeError(), function () { document.createTreeWalker(1); });
+}, 'Give an invalid root node to document.createTreeWalker().');
+
+test(function ()
+{
+ var root = createSampleDOM();
+ var walker = document.createTreeWalker(root);
+ var f = root.lastChild.firstChild.childNodes[1]; // An element node: div#f.
+
+ assert_node(walker.currentNode, { type: Element, id: 'a' });
+ assert_equals(walker.parentNode(), null);
+ assert_node(walker.currentNode, { type: Element, id: 'a' });
+ assert_node(walker.firstChild(), { type: Text, nodeValue: 'b' });
+ assert_node(walker.currentNode, { type: Text, nodeValue: 'b' });
+ assert_node(walker.nextSibling(), { type: Element, id: 'c' });
+ assert_node(walker.currentNode, { type: Element, id: 'c' });
+ assert_node(walker.lastChild(), { type: Comment, nodeValue: 'j' });
+ assert_node(walker.currentNode, { type: Comment, nodeValue: 'j' });
+ assert_node(walker.previousSibling(), { type: Element, id: 'd' });
+ assert_node(walker.currentNode, { type: Element, id: 'd' });
+ assert_node(walker.nextNode(), { type: Text, nodeValue: 'e' });
+ assert_node(walker.currentNode, { type: Text, nodeValue: 'e' });
+ assert_node(walker.parentNode(), { type: Element, id: 'd' });
+ assert_node(walker.currentNode, { type: Element, id: 'd' });
+ assert_node(walker.previousNode(), { type: Element, id: 'c' });
+ assert_node(walker.currentNode, { type: Element, id: 'c' });
+ assert_equals(walker.nextSibling(), null);
+ assert_node(walker.currentNode, { type: Element, id: 'c' });
+ walker.currentNode = f;
+ assert_equals(walker.currentNode, f);
+}, 'Walk over nodes.');
+
+test(function() {
+ var treeWalker = document.createTreeWalker(document.body, 42, null);
+ assert_equals(treeWalker.root, document.body);
+ assert_equals(treeWalker.currentNode, document.body);
+ assert_equals(treeWalker.whatToShow, 42);
+ assert_equals(treeWalker.filter, null);
+}, "Optional arguments to createTreeWalker should be optional (3 passed, null).");
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/traversal/TreeWalker-currentNode.html b/tests/wpt/web-platform-tests/dom/traversal/TreeWalker-currentNode.html
new file mode 100644
index 00000000000..dc6a1e28258
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/traversal/TreeWalker-currentNode.html
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<html>
+<!--
+Test adapted from https://mxr.mozilla.org/chromium/source/src/third_party/WebKit/LayoutTests/fast/dom/TreeWalker/resources/TreeWalker-currentNode.js
+-->
+<head>
+<title>TreeWalker: currentNode</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="traversal-support.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+<div id=log></div>
+</head>
+<body>
+<div id='parent'>
+<div id='subTree'><p>Lorem ipsum <span>dolor <b>sit</b> amet</span>, consectetur <i>adipisicing</i> elit, sed do eiusmod <tt>tempor <b><i>incididunt ut</i> labore</b> et dolore magna</tt> aliqua.</p></div>
+</div>
+<p>Test TreeWalker currentNode functionality</p>
+<script>
+// var subTree = document.createElement('div');
+// subTree.innerHTML = "<p>Lorem ipsum <span>dolor <b>sit</b> amet</span>, consectetur <i>adipisicing</i> elit, sed do eiusmod <tt>tempor <b><i>incididunt ut</i> labore</b> et dolore magna</tt> aliqua.</p>"
+// document.body.appendChild(subTree);
+var subTree = document.getElementById("subTree");
+
+var all = function(node) { return true; }
+
+test(function()
+{
+ var w = document.createTreeWalker(subTree, /*NodeFilter.*/SHOW_ELEMENT, all);
+ assert_node(w.currentNode, { type: Element, id: 'subTree' });
+ assert_equals(w.parentNode(), null);
+ assert_node(w.currentNode, { type: Element, id: 'subTree' });
+}, "Test that TreeWalker.parent() doesn't set the currentNode to a node not under the root.");
+
+test(function()
+{
+ var w = document.createTreeWalker(subTree,
+ /*NodeFilter.*/SHOW_ELEMENT
+ | /*NodeFilter.*/SHOW_COMMENT,
+ all);
+ w.currentNode = document.documentElement;
+ assert_equals(w.parentNode(), null);
+ assert_equals(w.currentNode, document.documentElement);
+ w.currentNode = document.documentElement;
+ assert_equals(w.nextNode(), document.documentElement.firstChild);
+ assert_equals(w.currentNode, document.documentElement.firstChild);
+ w.currentNode = document.documentElement;
+ assert_equals(w.previousNode(), null);
+ assert_equals(w.currentNode, document.documentElement);
+ w.currentNode = document.documentElement;
+ assert_equals(w.firstChild(), document.documentElement.firstChild);
+ assert_equals(w.currentNode, document.documentElement.firstChild);
+ w.currentNode = document.documentElement;
+ assert_equals(w.lastChild(), document.documentElement.lastChild);
+ assert_equals(w.currentNode, document.documentElement.lastChild);
+ w.currentNode = document.documentElement;
+ assert_equals(w.nextSibling(), null);
+ assert_equals(w.currentNode, document.documentElement);
+ w.currentNode = document.documentElement;
+ assert_equals(w.previousSibling(), null);
+ assert_equals(w.currentNode, document.documentElement);
+}, "Test that we handle setting the currentNode to arbitrary nodes not under the root element.");
+
+test(function()
+{
+ var w = document.createTreeWalker(subTree, /*NodeFilter.*/SHOW_ELEMENT, all);
+ w.currentNode = subTree.previousSibling;
+ assert_equals(w.nextNode(), subTree);
+ w.currentNode = document.getElementById("parent");
+ assert_equals(w.firstChild(), subTree);
+}, "Test how we handle the case when the traversed to node is within the root, but the currentElement is not.");
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/traversal/TreeWalker-previousNodeLastChildReject.html b/tests/wpt/web-platform-tests/dom/traversal/TreeWalker-previousNodeLastChildReject.html
new file mode 100644
index 00000000000..b1ae7787a94
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/traversal/TreeWalker-previousNodeLastChildReject.html
@@ -0,0 +1,88 @@
+<!DOCTYPE html>
+<html>
+<!--
+Test adapted from https://mxr.mozilla.org/chromium/source/src/third_party/WebKit/LayoutTests/fast/dom/TreeWalker/script-tests/previousNodeLastChildReject.js
+-->
+<head>
+<title>TreeWalker: previousNodeLastChildReject</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="traversal-support.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+<div id=log></div>
+</head>
+<body>
+<p>Test that previousNode properly respects the filter.</p>
+<script>
+var testElement;
+setup(function() {
+ testElement = document.createElement("div");
+ testElement.id = 'root';
+ // testElement.innerHTML='<div id="A1"><div id="B1"><div id="C1"></div><div id="C2"><div id="D1"></div><div id="D2"></div></div></div><div id="B2"><div id="C3"></div><div id="C4"></div></div></div>';
+ // testElement.innerHTML='
+ // <div id="A1">
+ // <div id="B1">
+ // <div id="C1">
+ // </div>
+ // <div id="C2">
+ // <div id="D1">
+ // </div>
+ // <div id="D2">
+ // </div>
+ // </div>
+ // </div>
+ // <div id="B2">
+ // <div id="C3">
+ // </div>
+ // <div id="C4">
+ // </div>
+ // </div>
+ // </div>';
+
+ // XXX for Servo, build the tree without using innerHTML
+ var a1 = document.createElement("div"); a1.id = "A1";
+ var b1 = document.createElement("div"); b1.id = "B1";
+ var b2 = document.createElement("div"); b2.id = "B2";
+ var c1 = document.createElement("div"); c1.id = "C1";
+ var c2 = document.createElement("div"); c2.id = "C2";
+ var c3 = document.createElement("div"); c3.id = "C3";
+ var c4 = document.createElement("div"); c4.id = "C4";
+ var d1 = document.createElement("div"); d1.id = "D1";
+ var d2 = document.createElement("div"); d2.id = "D2";
+
+ testElement.appendChild(a1);
+ a1.appendChild(b1);
+ a1.appendChild(b2);
+ b1.appendChild(c1);
+ b1.appendChild(c2);
+ b2.appendChild(c3);
+ b2.appendChild(c4);
+ c2.appendChild(d1);
+ c2.appendChild(d2);
+});
+
+test(function()
+{
+ function filter(node)
+ {
+ if (node.id == "C2")
+ return /*NodeFilter.*/FILTER_REJECT;
+ return /*NodeFilter.*/FILTER_ACCEPT;
+ }
+
+ var walker = document.createTreeWalker(testElement, /*NodeFilter.*/SHOW_ELEMENT, filter);
+ assert_node(walker.currentNode, { type: Element, id: 'root' });
+ assert_node(walker.firstChild(), { type: Element, id: 'A1' });
+ assert_node(walker.currentNode, { type: Element, id: 'A1' });
+ assert_node(walker.nextNode(), { type: Element, id: 'B1' });
+ assert_node(walker.currentNode, { type: Element, id: 'B1' });
+ assert_node(walker.nextNode(), { type: Element, id: 'C1' });
+ assert_node(walker.currentNode, { type: Element, id: 'C1' });
+ assert_node(walker.nextNode(), { type: Element, id: 'B2' });
+ assert_node(walker.currentNode, { type: Element, id: 'B2' });
+ assert_node(walker.previousNode(), { type: Element, id: 'C1' });
+ assert_node(walker.currentNode, { type: Element, id: 'C1' });
+}, 'Test that previousNode properly respects the filter.');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/traversal/TreeWalker-previousSiblingLastChildSkip.html b/tests/wpt/web-platform-tests/dom/traversal/TreeWalker-previousSiblingLastChildSkip.html
new file mode 100644
index 00000000000..b7c8fadde74
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/traversal/TreeWalker-previousSiblingLastChildSkip.html
@@ -0,0 +1,92 @@
+<!DOCTYPE html>
+<html>
+<!--
+Test adapted from https://mxr.mozilla.org/chromium/source/src/third_party/WebKit/LayoutTests/fast/dom/TreeWalker/script-tests/previousSiblingLastChildSkip.js
+-->
+<head>
+<title>TreeWalker: previousSiblingLastChildSkip</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="traversal-support.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+<div id=log></div>
+</head>
+<body>
+<p>Test that previousSibling properly respects the filter.</p>
+<script>
+var testElement;
+setup(function() {
+ testElement = document.createElement("div");
+ testElement.id = 'root';
+ // testElement.innerHTML='<div id="A1"><div id="B1"><div id="C1"></div><div id="C2"><div id="D1"></div><div id="D2"></div></div></div><div id="B2"><div id="C3"></div><div id="C4"></div></div></div>';
+ // testElement.innerHTML='
+ // <div id="A1">
+ // <div id="B1">
+ // <div id="C1">
+ // </div>
+ // <div id="C2">
+ // <div id="D1">
+ // </div>
+ // <div id="D2">
+ // </div>
+ // </div>
+ // </div>
+ // <div id="B2">
+ // <div id="C3">
+ // </div>
+ // <div id="C4">
+ // </div>
+ // </div>
+ // </div>';
+
+ // XXX for Servo, build the tree without using innerHTML
+ var a1 = document.createElement("div"); a1.id = "A1";
+ var b1 = document.createElement("div"); b1.id = "B1";
+ var b2 = document.createElement("div"); b2.id = "B2";
+ var c1 = document.createElement("div"); c1.id = "C1";
+ var c2 = document.createElement("div"); c2.id = "C2";
+ var c3 = document.createElement("div"); c3.id = "C3";
+ var c4 = document.createElement("div"); c4.id = "C4";
+ var d1 = document.createElement("div"); d1.id = "D1";
+ var d2 = document.createElement("div"); d2.id = "D2";
+
+ testElement.appendChild(a1);
+ a1.appendChild(b1);
+ a1.appendChild(b2);
+ b1.appendChild(c1);
+ b1.appendChild(c2);
+ b2.appendChild(c3);
+ b2.appendChild(c4);
+ c2.appendChild(d1);
+ c2.appendChild(d2);
+});
+
+test(function()
+{
+ function filter(node)
+ {
+ if (node.id == "B1")
+ return /*NodeFilter.*/FILTER_SKIP;
+ return /*NodeFilter.*/FILTER_ACCEPT;
+ }
+
+ var walker = document.createTreeWalker(testElement, /*NodeFilter.*/SHOW_ELEMENT, filter);
+ assert_node(walker.currentNode, { type: Element, id: 'root' });
+ assert_node(walker.firstChild(), { type: Element, id: 'A1' });
+ assert_node(walker.currentNode, { type: Element, id: 'A1' });
+ assert_node(walker.nextNode(), { type: Element, id: 'C1' });
+ assert_node(walker.currentNode, { type: Element, id: 'C1' });
+ assert_node(walker.nextNode(), { type: Element, id: 'C2' });
+ assert_node(walker.currentNode, { type: Element, id: 'C2' });
+ assert_node(walker.nextNode(), { type: Element, id: 'D1' });
+ assert_node(walker.currentNode, { type: Element, id: 'D1' });
+ assert_node(walker.nextNode(), { type: Element, id: 'D2' });
+ assert_node(walker.currentNode, { type: Element, id: 'D2' });
+ assert_node(walker.nextNode(), { type: Element, id: 'B2' });
+ assert_node(walker.currentNode, { type: Element, id: 'B2' });
+ assert_node(walker.previousSibling(), { type: Element, id: 'C2' });
+ assert_node(walker.currentNode, { type: Element, id: 'C2' });
+}, 'Test that previousSibling properly respects the filter.');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/traversal/TreeWalker-traversal-reject.html b/tests/wpt/web-platform-tests/dom/traversal/TreeWalker-traversal-reject.html
new file mode 100644
index 00000000000..e04487560b6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/traversal/TreeWalker-traversal-reject.html
@@ -0,0 +1,110 @@
+<!DOCTYPE html>
+<html>
+<!--
+Test adapted from https://mxr.mozilla.org/chromium/source/src/third_party/WebKit/LayoutTests/fast/dom/TreeWalker/script-tests/traversal-reject.js
+-->
+<head>
+<title>TreeWalker: traversal-reject</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="traversal-support.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+<div id=log></div>
+</head>
+<body>
+<p>Test TreeWalker with rejection</p>
+<script>
+var testElement;
+setup(function() {
+ testElement = document.createElement("div");
+ testElement.id = 'root';
+ //testElement.innerHTML='<div id="A1"> <div id="B1"> <div id="C1"></div> </div> <div id="B2"></div><div id="B3"></div> </div>';
+ // <div id="A1">
+ // <div id="B1">
+ // <div id="C1"></div>
+ // </div>
+ // <div id="B2"></div>
+ // <div id="B3"></div>
+ // </div>
+
+
+ // XXX for Servo, build the tree without using innerHTML
+ var a1 = document.createElement("div"); a1.id = "A1";
+ var b1 = document.createElement("div"); b1.id = "B1";
+ var b2 = document.createElement("div"); b2.id = "B2";
+ var b3 = document.createElement("div"); b3.id = "B3";
+ var c1 = document.createElement("div"); c1.id = "C1";
+
+ testElement.appendChild(a1);
+ a1.appendChild(b1);
+ a1.appendChild(b2);
+ a1.appendChild(b3);
+ b1.appendChild(c1);
+});
+
+var rejectB1Filter = {
+ acceptNode: function(node) {
+ if (node.id == 'B1')
+ return /*NodeFilter.*/FILTER_REJECT;
+
+ return /*NodeFilter.*/FILTER_ACCEPT;
+ }
+}
+
+var skipB2Filter = {
+ acceptNode: function(node) {
+ if (node.id == 'B2')
+ return /*NodeFilter.*/FILTER_SKIP;
+
+ return /*NodeFilter.*/FILTER_ACCEPT;
+ }
+}
+
+test(function()
+{
+ var walker = document.createTreeWalker(testElement, /*NodeFilter.*/SHOW_ELEMENT, rejectB1Filter);
+ assert_node(walker.nextNode(), { type: Element, id: 'A1' });
+ assert_node(walker.nextNode(), { type: Element, id: 'B2' });
+ assert_node(walker.nextNode(), { type: Element, id: 'B3' });
+}, 'Testing nextNode');
+
+test(function()
+{
+ var walker = document.createTreeWalker(testElement, /*NodeFilter.*/SHOW_ELEMENT, rejectB1Filter);
+ assert_node(walker.firstChild(), { type: Element, id: 'A1' });
+ assert_node(walker.firstChild(), { type: Element, id: 'B2' });
+}, 'Testing firstChild');
+
+test(function()
+{
+ var walker = document.createTreeWalker(testElement, /*NodeFilter.*/SHOW_ELEMENT, skipB2Filter);
+ assert_node(walker.firstChild(), { type: Element, id: 'A1' });
+ assert_node(walker.firstChild(), { type: Element, id: 'B1' });
+ assert_node(walker.nextSibling(), { type: Element, id: 'B3' });
+}, 'Testing nextSibling');
+
+test(function()
+{
+ var walker = document.createTreeWalker(testElement, /*NodeFilter.*/SHOW_ELEMENT, rejectB1Filter);
+ walker.currentNode = testElement.querySelectorAll('#C1')[0];
+ assert_node(walker.parentNode(), { type: Element, id: 'A1' });
+}, 'Testing parentNode');
+
+test(function()
+{
+ var walker = document.createTreeWalker(testElement, /*NodeFilter.*/SHOW_ELEMENT, skipB2Filter);
+ walker.currentNode = testElement.querySelectorAll('#B3')[0];
+ assert_node(walker.previousSibling(), { type: Element, id: 'B1' });
+}, 'Testing previousSibling');
+
+test(function()
+{
+ var walker = document.createTreeWalker(testElement, /*NodeFilter.*/SHOW_ELEMENT, rejectB1Filter);
+ walker.currentNode = testElement.querySelectorAll('#B3')[0];
+ assert_node(walker.previousNode(), { type: Element, id: 'B2' });
+ assert_node(walker.previousNode(), { type: Element, id: 'A1' });
+}, 'Testing previousNode');
+
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/traversal/TreeWalker-traversal-skip-most.html b/tests/wpt/web-platform-tests/dom/traversal/TreeWalker-traversal-skip-most.html
new file mode 100644
index 00000000000..24250363e39
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/traversal/TreeWalker-traversal-skip-most.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<html>
+<!--
+Test adapted from https://mxr.mozilla.org/chromium/source/src/third_party/WebKit/LayoutTests/fast/dom/TreeWalker/script-tests/traversal-skip-most.js
+-->
+<head>
+<title>TreeWalker: traversal-skip-most</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="traversal-support.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+<div id=log></div>
+</head>
+<body>
+<p>Test TreeWalker with skipping</p>
+<script>
+var testElement;
+setup(function() {
+ testElement = document.createElement("div");
+ testElement.id = 'root';
+ // testElement.innerHTML='<div id="A1"><div id="B1" class="keep"></div><div id="B2">this text matters</div><div id="B3" class="keep"></div></div>';
+ // <div id="A1">
+ // <div id="B1" class="keep"></div>
+ // <div id="B2">this text matters</div>
+ // <div id="B3" class="keep"></div>
+ // </div>
+
+
+ // XXX for Servo, build the tree without using innerHTML
+ var a1 = document.createElement("div"); a1.id = "A1";
+ var b1 = document.createElement("div"); b1.id = "B1"; b1.className = "keep";
+ var b2 = document.createElement("div"); b2.id = "B2";
+ var b3 = document.createElement("div"); b3.id = "B3"; b3.className = "keep";
+
+ testElement.appendChild(a1);
+ a1.appendChild(b1);
+ a1.appendChild(b2)
+ .appendChild(document.createTextNode("this text matters"));
+ a1.appendChild(b3);
+});
+
+var filter = {
+ acceptNode: function(node) {
+ if (node.className == 'keep')
+ return /*NodeFilter.*/FILTER_ACCEPT;
+
+ return /*NodeFilter.*/FILTER_SKIP;
+ }
+}
+
+test(function()
+{
+ var walker = document.createTreeWalker(testElement, /*NodeFilter.*/SHOW_ELEMENT, filter);
+ assert_node(walker.firstChild(), { type: Element, id: 'B1' });
+ assert_node(walker.nextSibling(), { type: Element, id: 'B3' });
+}, 'Testing nextSibling');
+
+test(function()
+{
+ var walker = document.createTreeWalker(testElement, /*NodeFilter.*/SHOW_ELEMENT, filter);
+ walker.currentNode = testElement.querySelectorAll('#B3')[0];
+ assert_node(walker.previousSibling(), { type: Element, id: 'B1' });
+}, 'Testing previousSibling');
+
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/traversal/TreeWalker-traversal-skip.html b/tests/wpt/web-platform-tests/dom/traversal/TreeWalker-traversal-skip.html
new file mode 100644
index 00000000000..1c71f6b284d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/traversal/TreeWalker-traversal-skip.html
@@ -0,0 +1,112 @@
+<!DOCTYPE html>
+<html>
+<!--
+Test adapted from https://mxr.mozilla.org/chromium/source/src/third_party/WebKit/LayoutTests/fast/dom/TreeWalker/script-tests/traversal-skip.js
+-->
+<head>
+<title>TreeWalker: traversal-skip</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="traversal-support.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+<div id=log></div>
+</head>
+<body>
+<p>Test TreeWalker with skipping</p>
+<script>
+var testElement;
+setup(function() {
+ testElement = document.createElement("div");
+ testElement.id = 'root';
+ // testElement.innerHTML='<div id="A1"> <div id="B1"> <div id="C1"></div> </div> <div id="B2"></div><div id="B3"></div> </div>';
+ // <div id="A1">
+ // <div id="B1">
+ // <div id="C1"></div>
+ // </div>
+ // <div id="B2"></div>
+ // <div id="B3"></div>
+ // </div>
+
+
+ // XXX for Servo, build the tree without using innerHTML
+ var a1 = document.createElement("div"); a1.id = "A1";
+ var b1 = document.createElement("div"); b1.id = "B1";
+ var b2 = document.createElement("div"); b2.id = "B2";
+ var b3 = document.createElement("div"); b3.id = "B3";
+ var c1 = document.createElement("div"); c1.id = "C1";
+
+ testElement.appendChild(a1);
+ a1.appendChild(b1);
+ a1.appendChild(b2);
+ a1.appendChild(b3);
+ b1.appendChild(c1);
+});
+
+var skipB1Filter = {
+ acceptNode: function(node) {
+ if (node.id == 'B1')
+ return /*NodeFilter.*/FILTER_SKIP;
+
+ return /*NodeFilter.*/FILTER_ACCEPT;
+ }
+}
+
+var skipB2Filter = {
+ acceptNode: function(node) {
+ if (node.id == 'B2')
+ return /*NodeFilter.*/FILTER_SKIP;
+
+ return /*NodeFilter.*/FILTER_ACCEPT;
+ }
+}
+
+test(function()
+{
+ var walker = document.createTreeWalker(testElement, /*NodeFilter.*/SHOW_ELEMENT, skipB1Filter);
+ assert_node(walker.nextNode(), { type: Element, id: 'A1' });
+ assert_node(walker.nextNode(), { type: Element, id: 'C1' });
+ assert_node(walker.nextNode(), { type: Element, id: 'B2' });
+ assert_node(walker.nextNode(), { type: Element, id: 'B3' });
+}, 'Testing nextNode');
+
+test(function()
+{
+ var walker = document.createTreeWalker(testElement, /*NodeFilter.*/SHOW_ELEMENT, skipB1Filter);
+ assert_node(walker.firstChild(), { type: Element, id: 'A1' });
+ assert_node(walker.firstChild(), { type: Element, id: 'C1' });
+}, 'Testing firstChild');
+
+test(function()
+{
+ var walker = document.createTreeWalker(testElement, /*NodeFilter.*/SHOW_ELEMENT, skipB2Filter);
+ assert_node(walker.firstChild(), { type: Element, id: 'A1' });
+ assert_node(walker.firstChild(), { type: Element, id: 'B1' });
+ assert_node(walker.nextSibling(), { type: Element, id: 'B3' });
+}, 'Testing nextSibling');
+
+test(function()
+{
+ var walker = document.createTreeWalker(testElement, /*NodeFilter.*/SHOW_ELEMENT, skipB1Filter);
+ walker.currentNode = testElement.querySelectorAll('#C1')[0];
+ assert_node(walker.parentNode(), { type: Element, id: 'A1' });
+}, 'Testing parentNode');
+
+test(function()
+{
+ var walker = document.createTreeWalker(testElement, /*NodeFilter.*/SHOW_ELEMENT, skipB2Filter);
+ walker.currentNode = testElement.querySelectorAll('#B3')[0];
+ assert_node(walker.previousSibling(), { type: Element, id: 'B1' });
+}, 'Testing previousSibling');
+
+test(function()
+{
+ var walker = document.createTreeWalker(testElement, /*NodeFilter.*/SHOW_ELEMENT, skipB1Filter);
+ walker.currentNode = testElement.querySelectorAll('#B3')[0];
+ assert_node(walker.previousNode(), { type: Element, id: 'B2' });
+ assert_node(walker.previousNode(), { type: Element, id: 'C1' });
+ assert_node(walker.previousNode(), { type: Element, id: 'A1' });
+}, 'Testing previousNode');
+
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/traversal/TreeWalker-walking-outside-a-tree.html b/tests/wpt/web-platform-tests/dom/traversal/TreeWalker-walking-outside-a-tree.html
new file mode 100644
index 00000000000..4efae976cac
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/traversal/TreeWalker-walking-outside-a-tree.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+<!--
+Test adapted from https://github.com/operasoftware/presto-testo/blob/master/core/standards/acid3/individual/006a.html
+-->
+<head>
+<title>TreeWalker: walking-outside-a-tree</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="traversal-support.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+<div id=log></div>
+</head>
+<body>
+<p>[Acid3 - Test 006a] walking outside a tree</p>
+<script>
+test(function () {
+ // test 6: walking outside a tree
+ var doc = document.createElement("div");
+ var head = document.createElement('head');
+ var title = document.createElement('title');
+ var body = document.createElement('body');
+ var p = document.createElement('p');
+ doc.appendChild(head);
+ head.appendChild(title);
+ doc.appendChild(body);
+ body.appendChild(p);
+
+ var w = document.createTreeWalker(body, 0xFFFFFFFF, null);
+ doc.removeChild(body);
+ assert_equals(w.lastChild(), p, "TreeWalker failed after removing the current node from the tree");
+ doc.appendChild(p);
+ assert_equals(w.previousNode(), title, "failed to handle regrafting correctly");
+ p.appendChild(body);
+ assert_equals(w.nextNode(), p, "couldn't retrace steps");
+ assert_equals(w.nextNode(), body, "couldn't step back into root");
+ assert_equals(w.previousNode(), null, "root didn't retake its rootish position");
+}, "walking outside a tree");
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/traversal/traversal-support.js b/tests/wpt/web-platform-tests/dom/traversal/traversal-support.js
new file mode 100644
index 00000000000..b21428d5419
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/traversal/traversal-support.js
@@ -0,0 +1,28 @@
+// |expected| should be an object indicating the expected type of node.
+function assert_node(actual, expected)
+{
+ assert_true(actual instanceof expected.type,
+ 'Node type mismatch: actual = ' + actual.nodeType + ', expected = ' + expected.nodeType);
+ if (typeof(expected.id) !== 'undefined')
+ assert_equals(actual.id, expected.id);
+ if (typeof(expected.nodeValue) !== 'undefined')
+ assert_equals(actual.nodeValue, expected.nodeValue);
+}
+
+// XXX Servo doesn't have these constants in NodeFilter yet
+var FILTER_ACCEPT = 1;
+var FILTER_REJECT = 2;
+var FILTER_SKIP = 3;
+var SHOW_ALL = 0xFFFFFFFF;
+var SHOW_ELEMENT = 0x1;
+var SHOW_ATTRIBUTE = 0x2;
+var SHOW_TEXT = 0x4;
+var SHOW_CDATA_SECTION = 0x8;
+var SHOW_ENTITY_REFERENCE = 0x10;
+var SHOW_ENTITY = 0x20;
+var SHOW_PROCESSING_INSTRUCTION = 0x40;
+var SHOW_COMMENT = 0x80;
+var SHOW_DOCUMENT = 0x100;
+var SHOW_DOCUMENT_TYPE = 0x200;
+var SHOW_DOCUMENT_FRAGMENT = 0x400;
+var SHOW_NOTATION = 0x800;
diff --git a/tests/wpt/web-platform-tests/dom/traversal/unfinished/001.xml b/tests/wpt/web-platform-tests/dom/traversal/unfinished/001.xml
new file mode 100644
index 00000000000..08bce72fcf5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/traversal/unfinished/001.xml
@@ -0,0 +1,53 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>DOM Traversal: NodeIterator: Basics</title>
+ <script type="text/javascript"> <![CDATA[
+ function doTest() {
+ var iterator = document.createNodeIterator(document, NodeFilter.SHOW_ALL, null, false);
+ var expected = new Array(9, // document
+ 1, // html
+ 3, 1, // head
+ 3, 1, 3, // title
+ 3, 1, 3, 4, // script and CDATA block
+ 3, 3, 1, // body
+ 3, 1, 3, // pre
+ 3, // </body>
+ 3, 8, // <!-- -->
+ 3, 7, // <? ?>,
+ 3, 4, 3); // CDATA
+ var found = new Array();
+
+ // walk document
+ var node;
+ while (node = iterator.nextNode())
+ found.push(node.nodeType);
+
+ // check results
+ var errors = 0;
+ var s = '';
+ var length = (found.length > expected.length) ? found.length : expected.length;
+ s += 'EXPECTED FOUND\n';
+ for (var i = 0; i < length; i += 1) {
+ s += ' ' + (expected[i] ? expected[i] : '-') +
+ ' ' + (found[i] ? found[i] : '-');
+ if (found[i] != expected[i]) {
+ s += ' MISMATCH';
+ errors += 1;
+ }
+ s += '\n';
+ }
+ var p = document.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'pre')[0];
+ if (errors)
+ p.firstChild.data = 'FAIL: ' + errors + ' errors found:\n\n' + s;
+ else
+ p.firstChild.data = 'PASS';
+ }
+ ]]></script>
+ </head>
+ <body onload="doTest()">
+ <pre id="result">FAIL: Script failed to run.</pre>
+ </body>
+ <!-- some more nodes to test this: -->
+ <?test node?>
+ <![CDATA[]]>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/dom/traversal/unfinished/002.xml b/tests/wpt/web-platform-tests/dom/traversal/unfinished/002.xml
new file mode 100644
index 00000000000..bf3489688c3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/traversal/unfinished/002.xml
@@ -0,0 +1,54 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>DOM Traversal: NodeIterator: Basics Backwards</title>
+ <script type="text/javascript"> <![CDATA[
+ function doTest() {
+ var iterator = document.createNodeIterator(document, NodeFilter.SHOW_ALL, null, false);
+ var expected = new Array(9, // document
+ 1, // html
+ 3, 1, // head
+ 3, 1, 3, // title
+ 3, 1, 3, 4, // script and CDATA block
+ 3, 3, 1, // body
+ 3, 1, 3, // pre
+ 3, // </body>
+ 3, 8, // <!-- -->
+ 3, 7, // <? ?>,
+ 3, 4, 3); // CDATA
+ var found = new Array();
+
+ // walk document
+ var node;
+ while (node = iterator.nextNode());
+ while (node = iterator.previousNode())
+ found.unshift(node.nodeType);
+
+ // check results
+ var errors = 0;
+ var s = '';
+ var length = (found.length > expected.length) ? found.length : expected.length;
+ s += 'EXPECTED FOUND\n';
+ for (var i = 0; i < length; i += 1) {
+ s += ' ' + (expected[i] ? expected[i] : '-') +
+ ' ' + (found[i] ? found[i] : '-');
+ if (found[i] != expected[i]) {
+ s += ' MISMATCH';
+ errors += 1;
+ }
+ s += '\n';
+ }
+ var p = document.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'pre')[0];
+ if (errors)
+ p.firstChild.data = 'FAIL: ' + errors + ' errors found:\n\n' + s;
+ else
+ p.firstChild.data = 'PASS';
+ }
+ ]]></script>
+ </head>
+ <body onload="doTest()">
+ <pre id="result">FAIL: Script failed to run.</pre>
+ </body>
+ <!-- some more nodes to test this: -->
+ <?test node?>
+ <![CDATA[]]>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/dom/traversal/unfinished/003.xml b/tests/wpt/web-platform-tests/dom/traversal/unfinished/003.xml
new file mode 100644
index 00000000000..268e6bb4d74
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/traversal/unfinished/003.xml
@@ -0,0 +1,58 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>DOM Traversal: NodeIterator: Removal of nodes that should have no effect</title>
+ <!--
+ This tests these cases that should have no effect:
+ 1. Remove a node unrelated to the reference node
+ 2. Remove an ancestor of the root node
+ 3. Remove the root node itself
+ 4. Remove descendant of reference node
+ -->
+ <script type="text/javascript"> <![CDATA[
+ var errors = 0;
+ var log = '';
+ function doTest() {
+ var iterator = document.createNodeIterator(document.getElementById('root'), NodeFilter.SHOW_ALL, null, false);
+ var root = document.getElementById('root');
+ var A = document.getElementById('A');
+ var B = document.getElementById('B');
+ var C = document.getElementById('C');
+ var D = document.getElementById('D');
+ var E = document.getElementById('E');
+ check(iterator.nextNode(), root);
+ remove(document.getElementById('X'));
+ check(iterator.nextNode(), A);
+ remove(document.getElementById('Y'));
+ check(iterator.nextNode(), B);
+ remove(root);
+ check(iterator.nextNode(), C);
+ remove(E);
+ check(iterator.nextNode(), D);
+ if (errors)
+ document.getElementById('result').firstChild.data = 'FAIL: ' + errors + ' errors:\n' + log;
+ else
+ document.getElementById('result').firstChild.data = 'PASS';
+ }
+ function check(a, b) {
+ if (!a) {
+ errors += 1;
+ log += 'Found null but expected ' + b + ' (' + b.id + ').\n';
+ } else if (a != b) {
+ errors += 1;
+ log += 'Found ' + a + ' (' + a.id + ') but expected ' + b + ' (' + b.id + ').\n';
+ }
+ }
+ function remove(a) {
+ if (!a) {
+ errors += 1;
+ log += 'Tried removing null node.\n';
+ } else
+ a.parentNode.removeChild(a);
+ }
+ ]]></script>
+ </head>
+ <body onload="doTest()">
+ <pre id="result">FAIL: Script did not complete.</pre>
+ <p><span id="X"></span><span id="Y"><span id="root"><span id="A"><span id="B"><span id="C"><span id="D"><span id="E"></span></span></span></span></span></span></span></p>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/dom/traversal/unfinished/004.xml b/tests/wpt/web-platform-tests/dom/traversal/unfinished/004.xml
new file mode 100644
index 00000000000..618978f021e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/traversal/unfinished/004.xml
@@ -0,0 +1,49 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>DOM Traversal: NodeIterator: Removal of the Reference Node</title>
+ <script type="text/javascript"> <![CDATA[
+ var errors = 0;
+ var log = '';
+ function doTest() {
+ var iterator = document.createNodeIterator(document.getElementById('root'), NodeFilter.SHOW_ALL, null, false);
+ var root = document.getElementById('root');
+ var A = document.getElementById('A');
+ var AA = document.getElementById('AA');
+ var B = document.getElementById('B');
+ var C = document.getElementById('C');
+ check(iterator.nextNode(), root);
+ check(iterator.nextNode(), A);
+ check(iterator.nextNode(), AA);
+ check(iterator.nextNode(), B);
+ remove(B);
+ check(iterator.previousNode(), AA);
+ remove(AA);
+ check(iterator.nextNode(), C);
+ if (errors)
+ document.getElementById('result').firstChild.data = 'FAIL: ' + errors + ' errors:\n' + log;
+ else
+ document.getElementById('result').firstChild.data = 'PASS';
+ }
+ function check(a, b) {
+ if (!a) {
+ errors += 1;
+ log += 'Found null but expected ' + b + ' (' + b.id + ').\n';
+ } else if (a != b) {
+ errors += 1;
+ log += 'Found ' + a + ' (' + a.id + ') but expected ' + b + ' (' + b.id + ').\n';
+ }
+ }
+ function remove(a) {
+ if (!a) {
+ errors += 1;
+ log += 'Tried removing null node.\n';
+ } else
+ a.parentNode.removeChild(a);
+ }
+ ]]></script>
+ </head>
+ <body onload="doTest()">
+ <pre id="result">FAIL: Script did not complete.</pre>
+ <p><span id="root"><span id="A"><span id="AA"></span></span><span id="B"></span><span id="C"><span id="CC"></span></span></span></p>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/dom/traversal/unfinished/005.xml b/tests/wpt/web-platform-tests/dom/traversal/unfinished/005.xml
new file mode 100644
index 00000000000..643e2f1cd4f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/traversal/unfinished/005.xml
@@ -0,0 +1,57 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>DOM Traversal: NodeIterator: Removal of the Reference Node (deep check)</title>
+ <script type="text/javascript"> <![CDATA[
+ var errors = 0;
+ var log = '';
+ function doTest() {
+ var iterator = document.createNodeIterator(document.getElementById('root'), NodeFilter.SHOW_ALL, null, false);
+ var root = document.getElementById('root');
+ var A = document.getElementById('A');
+ var AA = document.getElementById('AA');
+ var B = document.getElementById('B');
+ var C = document.getElementById('C');
+ check(iterator.nextNode(), root);
+ check(iterator.nextNode(), A);
+ check(iterator.nextNode(), AA);
+ check(iterator.nextNode(), B);
+ remove(B);
+ var X = addChildTo(AA);
+ check(iterator.nextNode(), X);
+ check(iterator.previousNode(), X);
+ remove(X);
+ var Y = addChildTo(AA);
+ check(iterator.previousNode(), Y);
+ if (errors)
+ document.getElementById('result').firstChild.data = 'FAIL: ' + errors + ' errors:\n' + log;
+ else
+ document.getElementById('result').firstChild.data = 'PASS';
+ }
+ function check(a, b) {
+ if (!a) {
+ errors += 1;
+ log += 'Found null but expected ' + b + ' (' + b.id + ').\n';
+ } else if (a != b) {
+ errors += 1;
+ log += 'Found ' + a + ' (' + a.id + ') but expected ' + b + ' (' + b.id + ').\n';
+ }
+ }
+ function remove(a) {
+ if (!a) {
+ errors += 1;
+ log += 'Tried removing null node.\n';
+ } else
+ a.parentNode.removeChild(a);
+ }
+ function addChildTo(a) {
+ var x = document.createElementNS('http://www.w3.org/1999/xhtml', 'span');
+ a.appendChild(x);
+ return x;
+ }
+ ]]></script>
+ </head>
+ <body onload="doTest()">
+ <pre id="result">FAIL: Script did not complete.</pre>
+ <p><span id="root"><span id="A"><span id="AA"></span></span><span id="B"></span><span id="C"><span id="CC"></span></span></span></p>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/dom/traversal/unfinished/006.xml b/tests/wpt/web-platform-tests/dom/traversal/unfinished/006.xml
new file mode 100644
index 00000000000..c2302af8366
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/traversal/unfinished/006.xml
@@ -0,0 +1,47 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>DOM Traversal: NodeIterator: Removal of an ancestor of the Reference Node (forwards)</title>
+ <script type="text/javascript"> <![CDATA[
+ var errors = 0;
+ var log = '';
+ function doTest() {
+ var iterator = document.createNodeIterator(document.getElementById('root'), NodeFilter.SHOW_ALL, null, false);
+ var root = document.getElementById('root');
+ var A = document.getElementById('A');
+ var B = document.getElementById('B');
+ var BB = document.getElementById('BB');
+ var C = document.getElementById('C');
+ check(iterator.nextNode(), root);
+ check(iterator.nextNode(), A);
+ check(iterator.nextNode(), B);
+ check(iterator.nextNode(), BB);
+ remove(B);
+ check(iterator.previousNode(), A);
+ if (errors)
+ document.getElementById('result').firstChild.data = 'FAIL: ' + errors + ' errors:\n' + log;
+ else
+ document.getElementById('result').firstChild.data = 'PASS';
+ }
+ function check(a, b) {
+ if (!a) {
+ errors += 1;
+ log += 'Found null but expected ' + b + ' (' + b.id + ').\n';
+ } else if (a != b) {
+ errors += 1;
+ log += 'Found ' + a + ' (' + a.id + ') but expected ' + b + ' (' + b.id + ').\n';
+ }
+ }
+ function remove(a) {
+ if (!a) {
+ errors += 1;
+ log += 'Tried removing null node.\n';
+ } else
+ a.parentNode.removeChild(a);
+ }
+ ]]></script>
+ </head>
+ <body onload="doTest()">
+ <pre id="result">FAIL: Script did not complete.</pre>
+ <p><span id="root"><span id="A"></span><span id="B"><span id="BB"></span></span><span id="C"></span></span></p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/traversal/unfinished/007.xml b/tests/wpt/web-platform-tests/dom/traversal/unfinished/007.xml
new file mode 100644
index 00000000000..98b212e4e5f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/traversal/unfinished/007.xml
@@ -0,0 +1,54 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>DOM Traversal: NodeIterator: Removal of an ancestor of the Reference Node (forwards) (deep check)</title>
+ <script type="text/javascript"> <![CDATA[
+ var errors = 0;
+ var log = '';
+ function doTest() {
+ var iterator = document.createNodeIterator(document.getElementById('root'), NodeFilter.SHOW_ALL, null, false);
+ var root = document.getElementById('root');
+ var A = document.getElementById('A');
+ var B = document.getElementById('B');
+ var BB = document.getElementById('BB');
+ var C = document.getElementById('C');
+ check(iterator.nextNode(), root);
+ check(iterator.nextNode(), A);
+ check(iterator.nextNode(), B);
+ check(iterator.nextNode(), BB);
+ remove(B);
+ var X = addChildTo(A);
+ check(iterator.nextNode(), X);
+ if (errors)
+ document.getElementById('result').firstChild.data = 'FAIL: ' + errors + ' errors:\n' + log;
+ else
+ document.getElementById('result').firstChild.data = 'PASS';
+ }
+ function check(a, b) {
+ if (!a) {
+ errors += 1;
+ log += 'Found null but expected ' + b + ' (' + b.id + ').\n';
+ } else if (a != b) {
+ errors += 1;
+ log += 'Found ' + a + ' (' + a.id + ') but expected ' + b + ' (' + b.id + ').\n';
+ }
+ }
+ function remove(a) {
+ if (!a) {
+ errors += 1;
+ log += 'Tried removing null node.\n';
+ } else
+ a.parentNode.removeChild(a);
+ }
+ function addChildTo(a) {
+ var x = document.createElementNS('http://www.w3.org/1999/xhtml', 'span');
+ x.id = 'X';
+ a.appendChild(x);
+ return x;
+ }
+ ]]></script>
+ </head>
+ <body onload="doTest()">
+ <pre id="result">FAIL: Script did not complete.</pre>
+ <p><span id="root"><span id="A"></span><span id="B"><span id="BB"></span></span><span id="C"></span></span></p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/traversal/unfinished/008.xml b/tests/wpt/web-platform-tests/dom/traversal/unfinished/008.xml
new file mode 100644
index 00000000000..41d7008ae42
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/traversal/unfinished/008.xml
@@ -0,0 +1,48 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>DOM Traversal: NodeIterator: Removal of an ancestor of the Reference Node (backwards)</title>
+ <script type="text/javascript"> <![CDATA[
+ var errors = 0;
+ var log = '';
+ function doTest() {
+ var iterator = document.createNodeIterator(document.getElementById('root'), NodeFilter.SHOW_ALL, null, false);
+ var root = document.getElementById('root');
+ var A = document.getElementById('A');
+ var B = document.getElementById('B');
+ var BB = document.getElementById('BB');
+ var C = document.getElementById('C');
+ check(iterator.nextNode(), root);
+ check(iterator.nextNode(), A);
+ check(iterator.nextNode(), B);
+ check(iterator.nextNode(), BB);
+ check(iterator.previousNode(), BB);
+ remove(B);
+ check(iterator.nextNode(), C);
+ if (errors)
+ document.getElementById('result').firstChild.data = 'FAIL: ' + errors + ' errors:\n' + log;
+ else
+ document.getElementById('result').firstChild.data = 'PASS';
+ }
+ function check(a, b) {
+ if (!a) {
+ errors += 1;
+ log += 'Found null but expected ' + b + ' (' + b.id + ').\n';
+ } else if (a != b) {
+ errors += 1;
+ log += 'Found ' + a + ' (' + a.id + ') but expected ' + b + ' (' + b.id + ').\n';
+ }
+ }
+ function remove(a) {
+ if (!a) {
+ errors += 1;
+ log += 'Tried removing null node.\n';
+ } else
+ a.parentNode.removeChild(a);
+ }
+ ]]></script>
+ </head>
+ <body onload="doTest()">
+ <pre id="result">FAIL: Script did not complete.</pre>
+ <p><span id="root"><span id="A"></span><span id="B"><span id="BB"></span></span><span id="C"></span></span></p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/traversal/unfinished/009.xml b/tests/wpt/web-platform-tests/dom/traversal/unfinished/009.xml
new file mode 100644
index 00000000000..c3006ecbd6f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/traversal/unfinished/009.xml
@@ -0,0 +1,55 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>DOM Traversal: NodeIterator: Removal of an ancestor of the Reference Node (backwards) (deep check)</title>
+ <script type="text/javascript"> <![CDATA[
+ var errors = 0;
+ var log = '';
+ function doTest() {
+ var iterator = document.createNodeIterator(document.getElementById('root'), NodeFilter.SHOW_ALL, null, false);
+ var root = document.getElementById('root');
+ var A = document.getElementById('A');
+ var B = document.getElementById('B');
+ var BB = document.getElementById('BB');
+ var C = document.getElementById('C');
+ check(iterator.nextNode(), root);
+ check(iterator.nextNode(), A);
+ check(iterator.nextNode(), B);
+ check(iterator.nextNode(), BB);
+ check(iterator.previousNode(), BB);
+ remove(B);
+ var X = addChildTo(A);
+ check(iterator.previousNode(), X);
+ if (errors)
+ document.getElementById('result').firstChild.data = 'FAIL: ' + errors + ' errors:\n' + log;
+ else
+ document.getElementById('result').firstChild.data = 'PASS';
+ }
+ function check(a, b) {
+ if (!a) {
+ errors += 1;
+ log += 'Found null but expected ' + b + ' (' + b.id + ').\n';
+ } else if (a != b) {
+ errors += 1;
+ log += 'Found ' + a + ' (' + a.id + ') but expected ' + b + ' (' + b.id + ').\n';
+ }
+ }
+ function remove(a) {
+ if (!a) {
+ errors += 1;
+ log += 'Tried removing null node.\n';
+ } else
+ a.parentNode.removeChild(a);
+ }
+ function addChildTo(a) {
+ var x = document.createElementNS('http://www.w3.org/1999/xhtml', 'span');
+ x.id = 'X';
+ a.appendChild(x);
+ return x;
+ }
+ ]]></script>
+ </head>
+ <body onload="doTest()">
+ <pre id="result">FAIL: Script did not complete.</pre>
+ <p><span id="root"><span id="A"></span><span id="B"><span id="BB"></span></span><span id="C"></span></span></p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/dom/traversal/unfinished/010.xml b/tests/wpt/web-platform-tests/dom/traversal/unfinished/010.xml
new file mode 100644
index 00000000000..63263a5fd73
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/traversal/unfinished/010.xml
@@ -0,0 +1,64 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>DOM Traversal: NodeIterator: Filters</title>
+ <script type="text/javascript"> <![CDATA[
+ function doTest() {
+ var iterator = document.createNodeIterator(document, NodeFilter.SHOW_ALL, testFilter, false);
+ // skips text nodes and body element
+ var expected = new Array(9, // document
+ 1, // html
+ 1, // head
+ 1, // title
+ 1, 4, // script and CDATA block
+ // body (skipped)
+ 1, // pre
+ // </body>
+ 8, // <!-- -->
+ // PI skipped
+ 4); // CDATA
+ var found = new Array();
+
+ // walk document
+ var node;
+ while (node = iterator.nextNode())
+ found.push(node.nodeType);
+
+ // check results
+ var errors = 0;
+ var s = '';
+ var length = (found.length > expected.length) ? found.length : expected.length;
+ s += 'EXPECTED FOUND\n';
+ for (var i = 0; i < length; i += 1) {
+ s += ' ' + (expected[i] ? expected[i] : '-') +
+ ' ' + (found[i] ? found[i] : '-');
+ if (found[i] != expected[i]) {
+ s += ' MISMATCH';
+ errors += 1;
+ }
+ s += '\n';
+ }
+ var p = document.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', 'pre')[0];
+ if (errors)
+ p.firstChild.data = 'FAIL: ' + errors + ' errors found:\n\n' + s;
+ else
+ p.firstChild.data = 'PASS';
+ }
+
+ function testFilter(n) {
+ if (n.nodeType == 3) {
+ return NodeFilter.FILTER_SKIP;
+ } else if (n.nodeName == 'body') {
+ return NodeFilter.FILTER_REJECT; // same as _SKIP
+ }
+ return 1; // FILTER_ACCEPT
+ }
+
+ ]]></script>
+ </head>
+ <body onload="doTest()">
+ <pre id="result">FAIL: Script failed to run.</pre>
+ </body>
+ <!-- some more nodes to test this: -->
+ <?body test?>
+ <![CDATA[]]>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/dom/traversal/unfinished/TODO b/tests/wpt/web-platform-tests/dom/traversal/unfinished/TODO
new file mode 100644
index 00000000000..cecdf98b08a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/dom/traversal/unfinished/TODO
@@ -0,0 +1 @@
+Check what happens when a NodeFilter turns a number not in the range 1..3 \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/domparsing/DOMParser-parseFromString-html.html b/tests/wpt/web-platform-tests/domparsing/DOMParser-parseFromString-html.html
new file mode 100644
index 00000000000..a00b619ce59
--- /dev/null
+++ b/tests/wpt/web-platform-tests/domparsing/DOMParser-parseFromString-html.html
@@ -0,0 +1,39 @@
+<!doctype html>
+<title>DOMParser basic test of HTML parsing</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+// |expected| should be an object indicating the expected type of node.
+function assert_node(actual, expected) {
+ assert_true(actual instanceof expected.type,
+ 'Node type mismatch: actual = ' + actual.nodeType + ', expected = ' + expected.nodeType);
+ if (typeof(expected.id) !== 'undefined')
+ assert_equals(actual.id, expected.id, expected.idMessage);
+ if (typeof(expected.nodeValue) !== 'undefined')
+ assert_equals(actual.nodeValue, expected.nodeValue, expected.nodeValueMessage);
+}
+
+var doc;
+setup(function() {
+ var parser = new DOMParser();
+ var input = '<html id="root"><head></head><body></body></html>';
+ doc = parser.parseFromString(input, 'text/html');
+});
+
+test(function() {
+ var root = doc.documentElement;
+ assert_node(root, { type: HTMLHtmlElement, id: 'root',
+ idMessage: 'documentElement id attribute should be root.' });
+}, 'Parsing of id attribute');
+
+test(function() {
+ assert_equals(document.documentURI, doc.documentURI,
+ 'The document must have a URL value equal to the URL of the active document.');
+}, 'URL value');
+
+test(function() {
+ assert_equals(doc.location, null,
+ 'The document must have a location value of null.');
+}, 'Location value');
+
+</script>
diff --git a/tests/wpt/web-platform-tests/domparsing/insert-adjacent.html b/tests/wpt/web-platform-tests/domparsing/insert-adjacent.html
new file mode 100644
index 00000000000..f43ec406e4b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/domparsing/insert-adjacent.html
@@ -0,0 +1,38 @@
+<!doctype html>
+<title>insertAdjacentHTML</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+#element {
+ display: none;
+}
+</style>
+
+<div id="element"></div>
+<div id="log"></div>
+
+<script>
+function wrap(text) {
+ return '<h3>' + text + '</h3>';
+}
+
+var possiblePositions = {
+ 'beforebegin': 'previousSibling'
+ , 'afterbegin': 'firstChild'
+ , 'beforeend': 'lastChild'
+ , 'afterend': 'nextSibling'
+}
+
+var el = document.querySelector('#element');
+
+Object.keys(possiblePositions).forEach(function(position) {
+ var html = wrap(position);
+ test(function() {
+ el.insertAdjacentHTML(position, html);
+ var heading = document.createElement('h3');
+ heading.innerHTML = position;
+ assert_equals(el[possiblePositions[position]].nodeName, "H3");
+ assert_equals(el[possiblePositions[position]].firstChild.nodeType, Node.TEXT_NODE);
+ }, 'insertAdjacentHTML(' + position + ', ' + html + ' )');
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/domxpath/001.html b/tests/wpt/web-platform-tests/domxpath/001.html
new file mode 100644
index 00000000000..c26795a3115
--- /dev/null
+++ b/tests/wpt/web-platform-tests/domxpath/001.html
@@ -0,0 +1,60 @@
+<!doctype html>
+<meta charset="utf8">
+<title>XPath in text/html: elements</title>
+<link rel="help" href="http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html#Interfaces">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<div id="log"><span></span></div>
+<div><span></span></div>
+<dØdd></dØdd>
+<svg>
+<path />
+<path />
+</svg>
+
+<script>
+function test_xpath_succeeds(path, expected, resolver) {
+ resolver = resolver ? resolver : null;
+ var res = document.evaluate(path, document, resolver, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
+ actual = [];
+ for (var i=0;;i++) {
+ var node = res.snapshotItem(i);
+ if (node === null) {
+ break;
+ }
+ actual.push(node);
+ }
+ assert_array_equals(actual, expected);
+}
+
+function test_xpath_throws(path, error_code, resolver) {
+ resolver = resolver ? resolver : null;
+ assert_throws(error_code, function() {document.evaluate(path, document, resolver, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null)})
+}
+
+function ns_resolver(x) {
+ map = {"html":"http://www.w3.org/1999/xhtml",
+ "svg":"http://www.w3.org/2000/svg",
+ "math":"http://www.w3.org/1998/Math/MathML"};
+ var rv = map.hasOwnProperty(x) ? map[x] : null;
+ return rv;
+}
+
+generate_tests(test_xpath_succeeds,[
+ ["HTML elements no namespace prefix", "//div", document.getElementsByTagName("div")],
+ ["HTML elements namespace prefix", "//html:div", document.getElementsByTagName("div"), ns_resolver],
+ ["HTML elements mixed use of prefix", "//html:div/span", document.getElementsByTagName("span"), ns_resolver],
+ ["SVG elements no namespace prefix", "//path", []],
+ ["SVG elements namespace prefix", "//svg:path", document.getElementsByTagName("path"), ns_resolver],
+ ["HTML elements mixed case", "//DiV", document.getElementsByTagName("div")],
+ ["SVG elements mixed case selector", "//svg:PatH", [], ns_resolver],
+ ["Non-ascii HTML element", "//dØdd", document.getElementsByTagName("dØdd"), ns_resolver],
+ ["Non-ascii HTML element2", "//dødd", [], ns_resolver],
+ ["Non-ascii HTML element3", "//DØDD", document.getElementsByTagName("dØdd"), ns_resolver]
+])
+
+generate_tests(test_xpath_throws, [
+ ["Throw with invalid prefix", "//invalid:path", "NAMESPACE_ERR"],
+])
+</script>
diff --git a/tests/wpt/web-platform-tests/domxpath/002.html b/tests/wpt/web-platform-tests/domxpath/002.html
new file mode 100644
index 00000000000..95b4afc4c10
--- /dev/null
+++ b/tests/wpt/web-platform-tests/domxpath/002.html
@@ -0,0 +1,60 @@
+<!doctype html>
+<meta charset="utf8">
+<title>XPath in text/html: attributes</title>
+<link rel="help" href="http://www.w3.org/TR/DOM-Level-3-XPath/xpath.html#Interfaces">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<div id="log" nonÄsciiAttribute><span></span></div>
+<svg xmlns="http://www.w3.org/2000/svg", xmlns:xlink="http://www.w3.org/1999/xlink">
+<path id="a" refx />
+<path id="b" nonÄscii xlink:href />
+</svg>
+
+<script>
+function test_xpath_succeeds(path, expected, resolver) {
+ resolver = resolver ? resolver : null;
+ var res = document.evaluate(path, document, resolver, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
+ actual = [];
+ for (var i=0;;i++) {
+ var node = res.snapshotItem(i);
+ if (node === null) {
+ break;
+ }
+ actual.push(node);
+ }
+ assert_array_equals(actual, expected);
+}
+
+function test_xpath_throws(path, error_code, resolver) {
+ resolver = resolver ? resolver : null;
+ assert_throws(error_code, function() {document.evaluate(path, document, resolver, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null)})
+}
+
+function ns_resolver(x) {
+ map = {"html":"http://www.w3.org/1999/xhtml",
+ "svg":"http://www.w3.org/2000/svg",
+ "math":"http://www.w3.org/1998/Math/MathML",
+ "xlink":"http://www.w3.org/1999/xlink"};
+ var rv = map.hasOwnProperty(x) ? map[x] : null;
+ return rv;
+}
+
+generate_tests(test_xpath_succeeds,[
+ ["Select html element based on attribute", "//div[@id='log']", [document.getElementById("log")]],
+ ["Select html element based on attribute mixed case", "//div[@Id='log']", [document.getElementById("log")]],
+ ["Select both HTML and SVG elements based on attribute", "//*[@id]", [document.getElementById("log")].concat(Array.prototype.slice.call(document.getElementsByTagName("path")))],
+ ["Select HTML element with non-ascii attribute 1", "//*[@nonÄsciiattribute]", [document.getElementById("log")]],
+ ["Select HTML element with non-ascii attribute 2", "//*[@nonäsciiattribute]", []],
+ ["Select HTML element with non-ascii attribute 3", "//*[@nonÄsciiAttribute]", [document.getElementById("log")]],
+ ["Select SVG element based on mixed case attribute", "//svg:path[@Id]", [], ns_resolver],
+ ["Select both HTML and SVG elements based on mixed case attribute", "//*[@Id]", [document.getElementById("log")]],
+ ["Select SVG elements with refX attribute", "//*[@refX]", [document.getElementById("a")]],
+ ["Select SVG elements with refX attribute incorrect case", "//*[@Refx]", []],
+ ["Select SVG elements with refX attribute lowercase", "//*[@refx]", []],
+ ["Select SVG element with non-ascii attribute 1", "//*[@nonÄscii]", [document.getElementById("b")]],
+ ["Select SVG element with non-ascii attribute 2", "//*[@nonäscii]", []],
+ ["xmlns attribute", "//*[@xmlns]", []],
+ ["svg element with XLink attribute", "//*[@xlink:href]", [document.getElementById("b")], ns_resolver]
+])
+</script>
diff --git a/tests/wpt/web-platform-tests/domxpath/evaluator-constructor.html b/tests/wpt/web-platform-tests/domxpath/evaluator-constructor.html
new file mode 100644
index 00000000000..e69b84b6f1b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/domxpath/evaluator-constructor.html
@@ -0,0 +1,17 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>XPathEvaluator constructor</title>
+<link rel=help href="http://wiki.whatwg.org/wiki/DOM_XPath">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function() {
+ var x = new XPathEvaluator();
+ assert_true(x instanceof XPathEvaluator);
+}, "Constructor with 'new'");
+test(function() {
+ var x = XPathEvaluator();
+ assert_true(x instanceof XPathEvaluator);
+}, "Constructor without 'new'");
+</script>
diff --git a/tests/wpt/web-platform-tests/encoding/api-basics.html b/tests/wpt/web-platform-tests/encoding/api-basics.html
new file mode 100644
index 00000000000..084575655c9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/encoding/api-basics.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<title>Encoding API: Basics</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+
+test(function() {
+ assert_equals((new TextEncoder).encoding, 'utf-8', 'default encoding is utf-8');
+ assert_equals((new TextDecoder).encoding, 'utf-8', 'default encoding is utf-8');
+}, 'Default encodings');
+
+test(function() {
+ assert_array_equals(new TextEncoder().encode(), [], 'input default should be empty string')
+ assert_array_equals(new TextEncoder().encode(undefined), [], 'input default should be empty string')
+}, 'Default inputs');
+
+
+function testEncodeDecodeSample(encoding, string, bytes) {
+ test(function() {
+ var encoded = new TextEncoder(encoding).encode(string);
+ assert_array_equals([].slice.call(encoded), bytes);
+ assert_equals(new TextDecoder(encoding).decode(new Uint8Array(bytes)), string);
+ assert_equals(new TextDecoder(encoding).decode(new Uint8Array(bytes).buffer), string);
+ }, 'Encode/decode round trip: ' + encoding);
+}
+
+// z (ASCII U+007A), cent (Latin-1 U+00A2), CJK water (BMP U+6C34),
+// G-Clef (non-BMP U+1D11E), PUA (BMP U+F8FF), PUA (non-BMP U+10FFFD)
+// byte-swapped BOM (non-character U+FFFE)
+var sample = 'z\xA2\u6C34\uD834\uDD1E\uF8FF\uDBFF\uDFFD\uFFFE';
+
+testEncodeDecodeSample(
+ 'utf-8',
+ sample,
+ [0x7A, 0xC2, 0xA2, 0xE6, 0xB0, 0xB4, 0xF0, 0x9D, 0x84, 0x9E, 0xEF, 0xA3, 0xBF, 0xF4, 0x8F, 0xBF, 0xBD, 0xEF, 0xBF, 0xBE]
+);
+
+testEncodeDecodeSample(
+ 'utf-16le',
+ sample,
+ [0x7A, 0x00, 0xA2, 0x00, 0x34, 0x6C, 0x34, 0xD8, 0x1E, 0xDD, 0xFF, 0xF8, 0xFF, 0xDB, 0xFD, 0xDF, 0xFE, 0xFF]
+);
+
+testEncodeDecodeSample(
+ 'utf-16be',
+ sample,
+ [0x00, 0x7A, 0x00, 0xA2, 0x6C, 0x34, 0xD8, 0x34, 0xDD, 0x1E, 0xF8, 0xFF, 0xDB, 0xFF, 0xDF, 0xFD, 0xFF, 0xFE]
+);
+
+testEncodeDecodeSample(
+ 'utf-16',
+ sample,
+ [0x7A, 0x00, 0xA2, 0x00, 0x34, 0x6C, 0x34, 0xD8, 0x1E, 0xDD, 0xFF, 0xF8, 0xFF, 0xDB, 0xFD, 0xDF, 0xFE, 0xFF]
+);
+
+</script>
diff --git a/tests/wpt/web-platform-tests/encoding/api-replacement-encodings.html b/tests/wpt/web-platform-tests/encoding/api-replacement-encodings.html
new file mode 100644
index 00000000000..d0accbc8de8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/encoding/api-replacement-encodings.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Encoding API: replacement encoding</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/encodings.js"></script>
+<script>
+
+test(function() {
+ assert_throws({name: 'RangeError'}, function() { new TextEncoder('replacement'); });
+ assert_throws({name: 'RangeError'}, function() { new TextDecoder('replacement'); });
+}, 'The "replacement" label should not be a known encoding.');
+
+encodings_table.forEach(function(section) {
+ section.encodings.filter(function(encoding) {
+ return encoding.name === 'replacement';
+ }).forEach(function(encoding) {
+ encoding.labels.forEach(function(label) {
+ test(function() {
+ assert_throws({name: 'RangeError'}, function() { new TextEncoder(label); });
+ assert_throws({name: 'RangeError'}, function() { new TextDecoder(label); });
+ }, 'Label for "replacement" should be rejected by API: ' + label);
+ });
+ });
+});
+
+</script>
diff --git a/tests/wpt/web-platform-tests/encoding/api-surrogates-utf8.html b/tests/wpt/web-platform-tests/encoding/api-surrogates-utf8.html
new file mode 100644
index 00000000000..caa185943c7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/encoding/api-surrogates-utf8.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<title>Encoding API: Invalid UTF-16 surrogates with UTF-8 encoding</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+
+var badStrings = [
+ {
+ input: 'abc123',
+ expected: [0x61, 0x62, 0x63, 0x31, 0x32, 0x33],
+ decoded: 'abc123',
+ name: 'Sanity check'
+ },
+ {
+ input: '\uD800',
+ expected: [0xef, 0xbf, 0xbd],
+ decoded: '\uFFFD',
+ name: 'Surrogate half (low)'
+ },
+ {
+ input: '\uDC00',
+ expected: [0xef, 0xbf, 0xbd],
+ decoded: '\uFFFD',
+ name: 'Surrogate half (high)'
+ },
+ {
+ input: 'abc\uD800123',
+ expected: [0x61, 0x62, 0x63, 0xef, 0xbf, 0xbd, 0x31, 0x32, 0x33],
+ decoded: 'abc\uFFFD123',
+ name: 'Surrogate half (low), in a string'
+ },
+ {
+ input: 'abc\uDC00123',
+ expected: [0x61, 0x62, 0x63, 0xef, 0xbf, 0xbd, 0x31, 0x32, 0x33],
+ decoded: 'abc\uFFFD123',
+ name: 'Surrogate half (high), in a string'
+ },
+ {
+ input: '\uDC00\uD800',
+ expected: [0xef, 0xbf, 0xbd, 0xef, 0xbf, 0xbd],
+ decoded: '\uFFFD\uFFFD',
+ name: 'Wrong order'
+ }
+];
+
+badStrings.forEach(function(t) {
+ test(function() {
+ var encoded = new TextEncoder('utf-8').encode(t.input);
+ assert_array_equals([].slice.call(encoded), t.expected);
+ assert_equals(new TextDecoder('utf-8').decode(encoded), t.decoded);
+ }, 'Invalid surrogates encoded into UTF-8: ' + t.name);
+});
+
+</script>
diff --git a/tests/wpt/web-platform-tests/encoding/gb18030-encoder.html b/tests/wpt/web-platform-tests/encoding/gb18030-encoder.html
new file mode 100644
index 00000000000..799d69274ef
--- /dev/null
+++ b/tests/wpt/web-platform-tests/encoding/gb18030-encoder.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<meta charset=gb18030> <!-- if the server overrides this, it is stupid, as this is a testsuite -->
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+ function encode(input, output, desc) {
+ test(function() {
+ var a = document.createElement("a") // <a> uses document encoding for URL's query
+ a.href = "https://example.com/?" + input
+ assert_equals(a.search.substr(1), output) // remove leading "?"
+ }, "gb18030 encoder: " + desc)
+ }
+
+ encode("s", "s", "very basic")
+ encode("\u20AC", "%A2%E3", "Euro")
+ encode("\u4E02", "%81@", "character")
+ encode("\uE4C6", "%A1@", "PUA")
+ encode("\uE4C5", "%FE%FE", "PUA #2")
+ encode("\ud83d\udca9", "%949%DA3", "poo")
+</script>
diff --git a/tests/wpt/web-platform-tests/encoding/gbk-encoder.html b/tests/wpt/web-platform-tests/encoding/gbk-encoder.html
new file mode 100644
index 00000000000..a6074f975d3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/encoding/gbk-encoder.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<meta charset=gbk> <!-- if the server overrides this, it is stupid, as this is a testsuite -->
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+ function encode(input, output, desc) {
+ test(function() {
+ var a = document.createElement("a") // <a> uses document encoding for URL's query
+ a.href = "https://example.com/?" + input
+ assert_equals(a.search.substr(1), output) // remove leading "?"
+ }, "gbk encoder: " + desc)
+ }
+
+ encode("s", "s", "very basic")
+ encode("\u20AC", "%80", "Euro")
+ encode("\u4E02", "%81@", "character")
+ encode("\uE4C6", "%A1@", "PUA")
+ encode("\uE4C5", "%FE%FE", "PUA #2")
+ encode("\ud83d\udca9", "%26%23128169%3B", "poo")
+</script>
diff --git a/tests/wpt/web-platform-tests/encoding/idlharness.html b/tests/wpt/web-platform-tests/encoding/idlharness.html
new file mode 100644
index 00000000000..ce44f6d3e0b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/encoding/idlharness.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>idlharness test: Encoding Living Standard API</title>
+<link rel="author" title="Joshua Bell" href="mailto:jsbell@google.com" />
+<link rel="help" href="https://encoding.spec.whatwg.org/#api"/>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/WebIDLParser.js"></script>
+<script src="/resources/idlharness.js"></script>
+
+<h1>idlharness test</h1>
+<p>This test validates the WebIDL included in the Encoding Living Standard.</p>
+
+<script type="text/plain" class="untested-idl">
+interface Window {};
+</script>
+
+<script type="text/plain" class="idl">
+// 8.1 Interface TextDecoder
+
+dictionary TextDecoderOptions {
+ boolean fatal = false;
+ boolean ignoreBOM = false;
+};
+
+dictionary TextDecodeOptions {
+ boolean stream = false;
+};
+
+[Constructor(optional DOMString label = "utf-8", optional TextDecoderOptions options),
+ Exposed=Window,Worker]
+interface TextDecoder {
+ readonly attribute DOMString encoding;
+ readonly attribute boolean fatal;
+ readonly attribute boolean ignoreBOM;
+ USVString decode(optional BufferSource input, optional TextDecodeOptions options);
+};
+
+// 8.2 Interface TextDecoder
+
+[Constructor(optional DOMString utfLabel = "utf-8"),
+ Exposed=Window,Worker]
+interface TextEncoder {
+ readonly attribute DOMString encoding;
+ [NewObject] Uint8Array encode(optional USVString input = "");
+};
+</script>
+
+<script>
+function select(selector) {
+ return [].slice.call(document.querySelectorAll(selector))
+ .map(function(e) { return e.textContent; })
+ .join('\n\n');
+}
+
+var idl = select('.idl')
+var untested = select('.untested-idl');
+var idl_array = new IdlArray();
+idl_array.add_untested_idls(untested);
+idl_array.add_idls(idl);
+idl_array.add_objects({
+ TextEncoder: ['new TextEncoder()'],
+ TextDecoder: ['new TextDecoder()']
+});
+idl_array.test();
+</script>
diff --git a/tests/wpt/web-platform-tests/encoding/iso-2022-jp-decoder.html b/tests/wpt/web-platform-tests/encoding/iso-2022-jp-decoder.html
new file mode 100644
index 00000000000..c86ffc15899
--- /dev/null
+++ b/tests/wpt/web-platform-tests/encoding/iso-2022-jp-decoder.html
@@ -0,0 +1,57 @@
+<!doctype html>
+<meta charset=utf-8>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+ function decode(input, output, desc) {
+ test(function() {
+ var d = new TextDecoder("iso-2022-jp"),
+ buffer = new ArrayBuffer(input.length),
+ view = new Int8Array(buffer)
+ for(var i = 0, l = input.length; i < l; i++) {
+ view[i] = input[i]
+ }
+ assert_equals(d.decode(view), output)
+ }, "iso-2022-jp decoder: " + desc)
+ }
+ decode([0x1b, 0x24], "�$", "Error ESC")
+ decode([0x1b, 0x24, 0x50], "�$P", "Error ESC, character")
+ decode([0x1b, 0x28, 0x42, 0x50], "�P", "ASCII ESC, character")
+ decode([0x1b, 0x28, 0x42, 0x1b, 0x28, 0x42, 0x50], "��P", "Double ASCII ESC, character")
+ decode([0x50, 0x1b, 0x28, 0x42, 0x50], "PP", "character, ASCII ESC, character")
+ decode([0x5C, 0x5D, 0x7E], "\\]~", "characters")
+ decode([0x0D, 0x0E, 0x0F, 0x10], "\x0D��\x10", "SO / SI")
+
+ decode([0x1b, 0x28, 0x4A, 0x5C, 0x5D, 0x7E], "¥]‾", "Roman ESC, characters")
+ decode([0x1b, 0x28, 0x4A, 0x0D, 0x0E, 0x0F, 0x10], "\x0D��\x10", "Roman ESC, SO / SI")
+ decode([0x1b, 0x28, 0x4A, 0x1b, 0x1b, 0x28, 0x49, 0x50], "�ミ", "Roman ESC, error ESC, Katakana ESC")
+
+ decode([0x1b, 0x28, 0x49, 0x50], "ミ", "Katakana ESC, character")
+ decode([0x1b, 0x28, 0x49, 0x1b, 0x24, 0x40, 0x50, 0x50], "�佩", "Katakana ESC, multibyte ESC, character")
+ decode([0x1b, 0x28, 0x49, 0x1b, 0x50], "�ミ", "Katakana ESC, error ESC, character")
+ decode([0x1b, 0x28, 0x49, 0x1b, 0x24, 0x50], "�、ミ", "Katakana ESC, error ESC #2, character")
+ decode([0x1b, 0x28, 0x49, 0x50, 0x1b, 0x28, 0x49, 0x50], "ミミ", "Katakana ESC, character, Katakana ESC, character")
+ decode([0x1b, 0x28, 0x49, 0x0D, 0x0E, 0x0F, 0x10], "����", "Katakana ESC, SO / SI")
+
+ decode([0x1b, 0x24, 0x40, 0x50, 0x50], "佩", "Multibyte ESC, character")
+ decode([0x1b, 0x24, 0x42, 0x50, 0x50], "佩", "Multibyte ESC #2, character")
+ decode([0x1b, 0x24, 0x42, 0x1b, 0x50, 0x50], "�佩", "Multibyte ESC, error ESC, character")
+ decode([0x1b, 0x24, 0x40, 0x1b, 0x24, 0x40], "�", "Double multibyte ESC")
+ decode([0x1b, 0x24, 0x40, 0x1b, 0x24, 0x40, 0x50, 0x50], "�佩", "Double multibyte ESC, character")
+ decode([0x1b, 0x24, 0x40, 0x1b, 0x24, 0x42, 0x50, 0x50], "�佩", "Double multibyte ESC #2, character")
+ decode([0x1b, 0x24, 0x40, 0x1b, 0x24, 0x50, 0x50], "�ば�", "Multibyte ESC, error ESC #2, character")
+
+ decode([0x1b, 0x24, 0x40, 0x50, 0x1b, 0x24, 0x40, 0x50, 0x50], "�佩", "Multibyte ESC, single byte, multibyte ESC, character")
+ decode([0x1b, 0x24, 0x40, 0x20, 0x50], "��", "Multibyte ESC, lead error byte")
+ decode([0x1b, 0x24, 0x40, 0x50, 0x20], "�", "Multibyte ESC, trail error byte")
+
+ decode([0x50, 0x1b], "P�", "character, error ESC")
+ decode([0x50, 0x1b, 0x24], "P�$", "character, error ESC #2")
+ decode([0x50, 0x1b, 0x50], "P�P", "character, error ESC #3")
+ decode([0x50, 0x1b, 0x28, 0x42], "P", "character, ASCII ESC")
+ decode([0x50, 0x1b, 0x28, 0x4A], "P", "character, Roman ESC")
+ decode([0x50, 0x1b, 0x28, 0x49], "P", "character, Katakana ESC")
+ decode([0x50, 0x1b, 0x24, 0x40], "P", "character, Multibyte ESC")
+ decode([0x50, 0x1b, 0x24, 0x42], "P", "character, Multibyte ESC #2")
+</script>
diff --git a/tests/wpt/web-platform-tests/encoding/iso-2022-jp-encoder.html b/tests/wpt/web-platform-tests/encoding/iso-2022-jp-encoder.html
new file mode 100644
index 00000000000..d3124e5f54b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/encoding/iso-2022-jp-encoder.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=iso-2022-jp> <!-- if the server overrides this, it is stupid, as this is a testsuite -->
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+ function encode(input, output, desc) {
+ test(function() {
+ var a = document.createElement("a") // <a> uses document encoding for URL's query
+ a.href = "https://example.com/?" + input
+ assert_equals(a.search.substr(1), output) // remove leading "?"
+ }, "iso-2022-jp encoder: " + desc)
+ }
+
+ encode("s", "s", "very basic")
+ encode("\u00A5\u203Es\\\uFF90\u4F69", "%1B(J\\~s%1B(B\\%1B$B%_PP%1B(B", "basics")
+ encode("\x0E\x0F\x1Bx", "%0E%0F%1Bx", "SO/SI ESC")
+</script>
diff --git a/tests/wpt/web-platform-tests/encoding/resources/encodings.js b/tests/wpt/web-platform-tests/encoding/resources/encodings.js
new file mode 100644
index 00000000000..6771a44967a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/encoding/resources/encodings.js
@@ -0,0 +1,489 @@
+// Based on https://dom.spec.whatwg.org/#dom-document-characterset
+
+var compatibility_names = {
+ "utf-8": "UTF-8",
+ "ibm866": "IBM866",
+ "iso-8859-2": "ISO-8859-2",
+ "iso-8859-3": "ISO-8859-3",
+ "iso-8859-4": "ISO-8859-4",
+ "iso-8859-5": "ISO-8859-5",
+ "iso-8859-6": "ISO-8859-6",
+ "iso-8859-7": "ISO-8859-7",
+ "iso-8859-8": "ISO-8859-8",
+ "iso-8859-8-i": "ISO-8859-8-I",
+ "iso-8859-10": "ISO-8859-10",
+ "iso-8859-13": "ISO-8859-13",
+ "iso-8859-14": "ISO-8859-14",
+ "iso-8859-15": "ISO-8859-15",
+ "iso-8859-16": "ISO-8859-16",
+ "koi8-r": "KOI8-R",
+ "koi8-u": "KOI8-U",
+ "gbk": "GBK",
+ "big5": "Big5",
+ "euc-jp": "EUC-JP",
+ "iso-2022-jp": "ISO-2022-JP",
+ "shift_jis": "Shift_JIS",
+ "euc-kr": "EUC-KR",
+ "utf-16be": "UTF-16BE",
+ "utf-16le": "UTF-16LE"
+};
+
+// Based on https://encoding.spec.whatwg.org/
+
+var utf_encodings = ['utf-8', 'utf-16le', 'utf-16be'];
+
+var encodings_table =
+[
+ {
+ "encodings": [
+ {
+ "labels": [
+ "unicode-1-1-utf-8",
+ "utf-8",
+ "utf8"
+ ],
+ "name": "utf-8"
+ }
+ ],
+ "heading": "The Encoding"
+ },
+ {
+ "encodings": [
+ {
+ "labels": [
+ "866",
+ "cp866",
+ "csibm866",
+ "ibm866"
+ ],
+ "name": "ibm866"
+ },
+ {
+ "labels": [
+ "csisolatin2",
+ "iso-8859-2",
+ "iso-ir-101",
+ "iso8859-2",
+ "iso88592",
+ "iso_8859-2",
+ "iso_8859-2:1987",
+ "l2",
+ "latin2"
+ ],
+ "name": "iso-8859-2"
+ },
+ {
+ "labels": [
+ "csisolatin3",
+ "iso-8859-3",
+ "iso-ir-109",
+ "iso8859-3",
+ "iso88593",
+ "iso_8859-3",
+ "iso_8859-3:1988",
+ "l3",
+ "latin3"
+ ],
+ "name": "iso-8859-3"
+ },
+ {
+ "labels": [
+ "csisolatin4",
+ "iso-8859-4",
+ "iso-ir-110",
+ "iso8859-4",
+ "iso88594",
+ "iso_8859-4",
+ "iso_8859-4:1988",
+ "l4",
+ "latin4"
+ ],
+ "name": "iso-8859-4"
+ },
+ {
+ "labels": [
+ "csisolatincyrillic",
+ "cyrillic",
+ "iso-8859-5",
+ "iso-ir-144",
+ "iso8859-5",
+ "iso88595",
+ "iso_8859-5",
+ "iso_8859-5:1988"
+ ],
+ "name": "iso-8859-5"
+ },
+ {
+ "labels": [
+ "arabic",
+ "asmo-708",
+ "csiso88596e",
+ "csiso88596i",
+ "csisolatinarabic",
+ "ecma-114",
+ "iso-8859-6",
+ "iso-8859-6-e",
+ "iso-8859-6-i",
+ "iso-ir-127",
+ "iso8859-6",
+ "iso88596",
+ "iso_8859-6",
+ "iso_8859-6:1987"
+ ],
+ "name": "iso-8859-6"
+ },
+ {
+ "labels": [
+ "csisolatingreek",
+ "ecma-118",
+ "elot_928",
+ "greek",
+ "greek8",
+ "iso-8859-7",
+ "iso-ir-126",
+ "iso8859-7",
+ "iso88597",
+ "iso_8859-7",
+ "iso_8859-7:1987",
+ "sun_eu_greek"
+ ],
+ "name": "iso-8859-7"
+ },
+ {
+ "labels": [
+ "csiso88598e",
+ "csisolatinhebrew",
+ "hebrew",
+ "iso-8859-8",
+ "iso-8859-8-e",
+ "iso-ir-138",
+ "iso8859-8",
+ "iso88598",
+ "iso_8859-8",
+ "iso_8859-8:1988",
+ "visual"
+ ],
+ "name": "iso-8859-8"
+ },
+ {
+ "labels": [
+ "csiso88598i",
+ "iso-8859-8-i",
+ "logical"
+ ],
+ "name": "iso-8859-8-i"
+ },
+ {
+ "labels": [
+ "csisolatin6",
+ "iso-8859-10",
+ "iso-ir-157",
+ "iso8859-10",
+ "iso885910",
+ "l6",
+ "latin6"
+ ],
+ "name": "iso-8859-10"
+ },
+ {
+ "labels": [
+ "iso-8859-13",
+ "iso8859-13",
+ "iso885913"
+ ],
+ "name": "iso-8859-13"
+ },
+ {
+ "labels": [
+ "iso-8859-14",
+ "iso8859-14",
+ "iso885914"
+ ],
+ "name": "iso-8859-14"
+ },
+ {
+ "labels": [
+ "csisolatin9",
+ "iso-8859-15",
+ "iso8859-15",
+ "iso885915",
+ "iso_8859-15",
+ "l9"
+ ],
+ "name": "iso-8859-15"
+ },
+ {
+ "labels": [
+ "iso-8859-16"
+ ],
+ "name": "iso-8859-16"
+ },
+ {
+ "labels": [
+ "cskoi8r",
+ "koi",
+ "koi8",
+ "koi8-r",
+ "koi8_r"
+ ],
+ "name": "koi8-r"
+ },
+ {
+ "labels": [
+ "koi8-u"
+ ],
+ "name": "koi8-u"
+ },
+ {
+ "labels": [
+ "csmacintosh",
+ "mac",
+ "macintosh",
+ "x-mac-roman"
+ ],
+ "name": "macintosh"
+ },
+ {
+ "labels": [
+ "dos-874",
+ "iso-8859-11",
+ "iso8859-11",
+ "iso885911",
+ "tis-620",
+ "windows-874"
+ ],
+ "name": "windows-874"
+ },
+ {
+ "labels": [
+ "cp1250",
+ "windows-1250",
+ "x-cp1250"
+ ],
+ "name": "windows-1250"
+ },
+ {
+ "labels": [
+ "cp1251",
+ "windows-1251",
+ "x-cp1251"
+ ],
+ "name": "windows-1251"
+ },
+ {
+ "labels": [
+ "ansi_x3.4-1968",
+ "ascii",
+ "cp1252",
+ "cp819",
+ "csisolatin1",
+ "ibm819",
+ "iso-8859-1",
+ "iso-ir-100",
+ "iso8859-1",
+ "iso88591",
+ "iso_8859-1",
+ "iso_8859-1:1987",
+ "l1",
+ "latin1",
+ "us-ascii",
+ "windows-1252",
+ "x-cp1252"
+ ],
+ "name": "windows-1252"
+ },
+ {
+ "labels": [
+ "cp1253",
+ "windows-1253",
+ "x-cp1253"
+ ],
+ "name": "windows-1253"
+ },
+ {
+ "labels": [
+ "cp1254",
+ "csisolatin5",
+ "iso-8859-9",
+ "iso-ir-148",
+ "iso8859-9",
+ "iso88599",
+ "iso_8859-9",
+ "iso_8859-9:1989",
+ "l5",
+ "latin5",
+ "windows-1254",
+ "x-cp1254"
+ ],
+ "name": "windows-1254"
+ },
+ {
+ "labels": [
+ "cp1255",
+ "windows-1255",
+ "x-cp1255"
+ ],
+ "name": "windows-1255"
+ },
+ {
+ "labels": [
+ "cp1256",
+ "windows-1256",
+ "x-cp1256"
+ ],
+ "name": "windows-1256"
+ },
+ {
+ "labels": [
+ "cp1257",
+ "windows-1257",
+ "x-cp1257"
+ ],
+ "name": "windows-1257"
+ },
+ {
+ "labels": [
+ "cp1258",
+ "windows-1258",
+ "x-cp1258"
+ ],
+ "name": "windows-1258"
+ },
+ {
+ "labels": [
+ "x-mac-cyrillic",
+ "x-mac-ukrainian"
+ ],
+ "name": "x-mac-cyrillic"
+ }
+ ],
+ "heading": "Legacy single-byte encodings"
+ },
+ {
+ "encodings": [
+ {
+ "labels": [
+ "chinese",
+ "csgb2312",
+ "csiso58gb231280",
+ "gb2312",
+ "gb_2312",
+ "gb_2312-80",
+ "gbk",
+ "iso-ir-58",
+ "x-gbk"
+ ],
+ "name": "gbk"
+ },
+ {
+ "labels": [
+ "gb18030"
+ ],
+ "name": "gb18030"
+ }
+ ],
+ "heading": "Legacy multi-byte Chinese (simplified) encodings"
+ },
+ {
+ "encodings": [
+ {
+ "labels": [
+ "big5",
+ "big5-hkscs",
+ "cn-big5",
+ "csbig5",
+ "x-x-big5"
+ ],
+ "name": "big5"
+ }
+ ],
+ "heading": "Legacy multi-byte Chinese (traditional) encodings"
+ },
+ {
+ "encodings": [
+ {
+ "labels": [
+ "cseucpkdfmtjapanese",
+ "euc-jp",
+ "x-euc-jp"
+ ],
+ "name": "euc-jp"
+ },
+ {
+ "labels": [
+ "csiso2022jp",
+ "iso-2022-jp"
+ ],
+ "name": "iso-2022-jp"
+ },
+ {
+ "labels": [
+ "csshiftjis",
+ "ms_kanji",
+ "shift-jis",
+ "shift_jis",
+ "sjis",
+ "windows-31j",
+ "x-sjis"
+ ],
+ "name": "shift_jis"
+ }
+ ],
+ "heading": "Legacy multi-byte Japanese encodings"
+ },
+ {
+ "encodings": [
+ {
+ "labels": [
+ "cseuckr",
+ "csksc56011987",
+ "euc-kr",
+ "iso-ir-149",
+ "korean",
+ "ks_c_5601-1987",
+ "ks_c_5601-1989",
+ "ksc5601",
+ "ksc_5601",
+ "windows-949"
+ ],
+ "name": "euc-kr"
+ }
+ ],
+ "heading": "Legacy multi-byte Korean encodings"
+ },
+ {
+ "encodings": [
+ {
+ "labels": [
+ "csiso2022kr",
+ "hz-gb-2312",
+ "iso-2022-cn",
+ "iso-2022-cn-ext",
+ "iso-2022-kr"
+ ],
+ "name": "replacement"
+ },
+ {
+ "labels": [
+ "utf-16be"
+ ],
+ "name": "utf-16be"
+ },
+ {
+ "labels": [
+ "utf-16",
+ "utf-16le"
+ ],
+ "name": "utf-16le"
+ },
+ {
+ "labels": [
+ "x-user-defined"
+ ],
+ "name": "x-user-defined"
+ }
+ ],
+ "heading": "Legacy miscellaneous encodings"
+ }
+]
+;
diff --git a/tests/wpt/web-platform-tests/encoding/resources/single-byte-raw.py b/tests/wpt/web-platform-tests/encoding/resources/single-byte-raw.py
new file mode 100644
index 00000000000..b4a6c90405e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/encoding/resources/single-byte-raw.py
@@ -0,0 +1,3 @@
+def main(request, response):
+ response.headers.set("Content-Type", "text/plain;charset=" + request.GET.first("label"))
+ response.content = "".join(chr(byte) for byte in xrange(255))
diff --git a/tests/wpt/web-platform-tests/encoding/single-byte-decoder.html b/tests/wpt/web-platform-tests/encoding/single-byte-decoder.html
new file mode 100644
index 00000000000..62e34cfb306
--- /dev/null
+++ b/tests/wpt/web-platform-tests/encoding/single-byte-decoder.html
@@ -0,0 +1,99 @@
+<!doctype html>
+<meta name=timeout content=long>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=resources/encodings.js></script>
+<div id=log></div>
+<script>
+
+ var singleByteEncodings = encodings_table.filter(function(group) {
+ return group.heading === "Legacy single-byte encodings";
+ })[0].encodings,
+ // https://encoding.spec.whatwg.org/indexes.json
+ singleByteIndexes = {
+ "ibm866":[1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,9617,9618,9619,9474,9508,9569,9570,9558,9557,9571,9553,9559,9565,9564,9563,9488,9492,9524,9516,9500,9472,9532,9566,9567,9562,9556,9577,9574,9568,9552,9580,9575,9576,9572,9573,9561,9560,9554,9555,9579,9578,9496,9484,9608,9604,9612,9616,9600,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,1025,1105,1028,1108,1031,1111,1038,1118,176,8729,183,8730,8470,164,9632,160],
+ "iso-8859-2":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,260,728,321,164,317,346,167,168,352,350,356,377,173,381,379,176,261,731,322,180,318,347,711,184,353,351,357,378,733,382,380,340,193,194,258,196,313,262,199,268,201,280,203,282,205,206,270,272,323,327,211,212,336,214,215,344,366,218,368,220,221,354,223,341,225,226,259,228,314,263,231,269,233,281,235,283,237,238,271,273,324,328,243,244,337,246,247,345,367,250,369,252,253,355,729],
+ "iso-8859-3":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,294,728,163,164,null,292,167,168,304,350,286,308,173,null,379,176,295,178,179,180,181,293,183,184,305,351,287,309,189,null,380,192,193,194,null,196,266,264,199,200,201,202,203,204,205,206,207,null,209,210,211,212,288,214,215,284,217,218,219,220,364,348,223,224,225,226,null,228,267,265,231,232,233,234,235,236,237,238,239,null,241,242,243,244,289,246,247,285,249,250,251,252,365,349,729],
+ "iso-8859-4":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,260,312,342,164,296,315,167,168,352,274,290,358,173,381,175,176,261,731,343,180,297,316,711,184,353,275,291,359,330,382,331,256,193,194,195,196,197,198,302,268,201,280,203,278,205,206,298,272,325,332,310,212,213,214,215,216,370,218,219,220,360,362,223,257,225,226,227,228,229,230,303,269,233,281,235,279,237,238,299,273,326,333,311,244,245,246,247,248,371,250,251,252,361,363,729],
+ "iso-8859-5":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,1025,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,173,1038,1039,1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,8470,1105,1106,1107,1108,1109,1110,1111,1112,1113,1114,1115,1116,167,1118,1119],
+ "iso-8859-6":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,null,null,null,164,null,null,null,null,null,null,null,1548,173,null,null,null,null,null,null,null,null,null,null,null,null,null,1563,null,null,null,1567,null,1569,1570,1571,1572,1573,1574,1575,1576,1577,1578,1579,1580,1581,1582,1583,1584,1585,1586,1587,1588,1589,1590,1591,1592,1593,1594,null,null,null,null,null,1600,1601,1602,1603,1604,1605,1606,1607,1608,1609,1610,1611,1612,1613,1614,1615,1616,1617,1618,null,null,null,null,null,null,null,null,null,null,null,null,null],
+ "iso-8859-7":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,8216,8217,163,8364,8367,166,167,168,169,890,171,172,173,null,8213,176,177,178,179,900,901,902,183,904,905,906,187,908,189,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,null,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,962,963,964,965,966,967,968,969,970,971,972,973,974,null],
+ "iso-8859-8":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,null,162,163,164,165,166,167,168,169,215,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,247,187,188,189,190,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,8215,1488,1489,1490,1491,1492,1493,1494,1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,1510,1511,1512,1513,1514,null,null,8206,8207,null],
+ "iso-8859-10":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,260,274,290,298,296,310,167,315,272,352,358,381,173,362,330,176,261,275,291,299,297,311,183,316,273,353,359,382,8213,363,331,256,193,194,195,196,197,198,302,268,201,280,203,278,205,206,207,208,325,332,211,212,213,214,360,216,370,218,219,220,221,222,223,257,225,226,227,228,229,230,303,269,233,281,235,279,237,238,239,240,326,333,243,244,245,246,361,248,371,250,251,252,253,254,312],
+ "iso-8859-13":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,8221,162,163,164,8222,166,167,216,169,342,171,172,173,174,198,176,177,178,179,8220,181,182,183,248,185,343,187,188,189,190,230,260,302,256,262,196,197,280,274,268,201,377,278,290,310,298,315,352,323,325,211,332,213,214,215,370,321,346,362,220,379,381,223,261,303,257,263,228,229,281,275,269,233,378,279,291,311,299,316,353,324,326,243,333,245,246,247,371,322,347,363,252,380,382,8217],
+ "iso-8859-14":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,7682,7683,163,266,267,7690,167,7808,169,7810,7691,7922,173,174,376,7710,7711,288,289,7744,7745,182,7766,7809,7767,7811,7776,7923,7812,7813,7777,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,372,209,210,211,212,213,214,7786,216,217,218,219,220,221,374,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,373,241,242,243,244,245,246,7787,248,249,250,251,252,253,375,255],
+ "iso-8859-15":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,8364,165,352,167,353,169,170,171,172,173,174,175,176,177,178,179,381,181,182,183,382,185,186,187,338,339,376,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255],
+ "iso-8859-16":[128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,260,261,321,8364,8222,352,167,353,169,536,171,377,173,378,379,176,177,268,322,381,8221,182,183,382,269,537,187,338,339,376,380,192,193,194,258,196,262,198,199,200,201,202,203,204,205,206,207,272,323,210,211,212,336,214,346,368,217,218,219,220,280,538,223,224,225,226,259,228,263,230,231,232,233,234,235,236,237,238,239,273,324,242,243,244,337,246,347,369,249,250,251,252,281,539,255],
+ "koi8-r":[9472,9474,9484,9488,9492,9496,9500,9508,9516,9524,9532,9600,9604,9608,9612,9616,9617,9618,9619,8992,9632,8729,8730,8776,8804,8805,160,8993,176,178,183,247,9552,9553,9554,1105,9555,9556,9557,9558,9559,9560,9561,9562,9563,9564,9565,9566,9567,9568,9569,1025,9570,9571,9572,9573,9574,9575,9576,9577,9578,9579,9580,169,1102,1072,1073,1094,1076,1077,1092,1075,1093,1080,1081,1082,1083,1084,1085,1086,1087,1103,1088,1089,1090,1091,1078,1074,1100,1099,1079,1096,1101,1097,1095,1098,1070,1040,1041,1062,1044,1045,1060,1043,1061,1048,1049,1050,1051,1052,1053,1054,1055,1071,1056,1057,1058,1059,1046,1042,1068,1067,1047,1064,1069,1065,1063,1066],
+ "koi8-u":[9472,9474,9484,9488,9492,9496,9500,9508,9516,9524,9532,9600,9604,9608,9612,9616,9617,9618,9619,8992,9632,8729,8730,8776,8804,8805,160,8993,176,178,183,247,9552,9553,9554,1105,1108,9556,1110,1111,9559,9560,9561,9562,9563,1169,9565,9566,9567,9568,9569,1025,1028,9571,1030,1031,9574,9575,9576,9577,9578,1168,9580,169,1102,1072,1073,1094,1076,1077,1092,1075,1093,1080,1081,1082,1083,1084,1085,1086,1087,1103,1088,1089,1090,1091,1078,1074,1100,1099,1079,1096,1101,1097,1095,1098,1070,1040,1041,1062,1044,1045,1060,1043,1061,1048,1049,1050,1051,1052,1053,1054,1055,1071,1056,1057,1058,1059,1046,1042,1068,1067,1047,1064,1069,1065,1063,1066],
+ "macintosh":[196,197,199,201,209,214,220,225,224,226,228,227,229,231,233,232,234,235,237,236,238,239,241,243,242,244,246,245,250,249,251,252,8224,176,162,163,167,8226,182,223,174,169,8482,180,168,8800,198,216,8734,177,8804,8805,165,181,8706,8721,8719,960,8747,170,186,937,230,248,191,161,172,8730,402,8776,8710,171,187,8230,160,192,195,213,338,339,8211,8212,8220,8221,8216,8217,247,9674,255,376,8260,8364,8249,8250,64257,64258,8225,183,8218,8222,8240,194,202,193,203,200,205,206,207,204,211,212,63743,210,218,219,217,305,710,732,175,728,729,730,184,733,731,711],
+ "windows-874":[8364,129,130,131,132,8230,134,135,136,137,138,139,140,141,142,143,144,8216,8217,8220,8221,8226,8211,8212,152,153,154,155,156,157,158,159,160,3585,3586,3587,3588,3589,3590,3591,3592,3593,3594,3595,3596,3597,3598,3599,3600,3601,3602,3603,3604,3605,3606,3607,3608,3609,3610,3611,3612,3613,3614,3615,3616,3617,3618,3619,3620,3621,3622,3623,3624,3625,3626,3627,3628,3629,3630,3631,3632,3633,3634,3635,3636,3637,3638,3639,3640,3641,3642,null,null,null,null,3647,3648,3649,3650,3651,3652,3653,3654,3655,3656,3657,3658,3659,3660,3661,3662,3663,3664,3665,3666,3667,3668,3669,3670,3671,3672,3673,3674,3675,null,null,null,null],
+ "windows-1250":[8364,129,8218,131,8222,8230,8224,8225,136,8240,352,8249,346,356,381,377,144,8216,8217,8220,8221,8226,8211,8212,152,8482,353,8250,347,357,382,378,160,711,728,321,164,260,166,167,168,169,350,171,172,173,174,379,176,177,731,322,180,181,182,183,184,261,351,187,317,733,318,380,340,193,194,258,196,313,262,199,268,201,280,203,282,205,206,270,272,323,327,211,212,336,214,215,344,366,218,368,220,221,354,223,341,225,226,259,228,314,263,231,269,233,281,235,283,237,238,271,273,324,328,243,244,337,246,247,345,367,250,369,252,253,355,729],
+ "windows-1251":[1026,1027,8218,1107,8222,8230,8224,8225,8364,8240,1033,8249,1034,1036,1035,1039,1106,8216,8217,8220,8221,8226,8211,8212,152,8482,1113,8250,1114,1116,1115,1119,160,1038,1118,1032,164,1168,166,167,1025,169,1028,171,172,173,174,1031,176,177,1030,1110,1169,181,182,183,1105,8470,1108,187,1112,1029,1109,1111,1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103],
+ "windows-1252":[8364,129,8218,402,8222,8230,8224,8225,710,8240,352,8249,338,141,381,143,144,8216,8217,8220,8221,8226,8211,8212,732,8482,353,8250,339,157,382,376,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255],
+ "windows-1253":[8364,129,8218,402,8222,8230,8224,8225,136,8240,138,8249,140,141,142,143,144,8216,8217,8220,8221,8226,8211,8212,152,8482,154,8250,156,157,158,159,160,901,902,163,164,165,166,167,168,169,null,171,172,173,174,8213,176,177,178,179,900,181,182,183,904,905,906,187,908,189,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,null,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,962,963,964,965,966,967,968,969,970,971,972,973,974,null],
+ "windows-1254":[8364,129,8218,402,8222,8230,8224,8225,710,8240,352,8249,338,141,142,143,144,8216,8217,8220,8221,8226,8211,8212,732,8482,353,8250,339,157,158,376,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,286,209,210,211,212,213,214,215,216,217,218,219,220,304,350,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,287,241,242,243,244,245,246,247,248,249,250,251,252,305,351,255],
+ "windows-1255":[8364,129,8218,402,8222,8230,8224,8225,710,8240,138,8249,140,141,142,143,144,8216,8217,8220,8221,8226,8211,8212,732,8482,154,8250,156,157,158,159,160,161,162,163,8362,165,166,167,168,169,215,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,247,187,188,189,190,191,1456,1457,1458,1459,1460,1461,1462,1463,1464,1465,null,1467,1468,1469,1470,1471,1472,1473,1474,1475,1520,1521,1522,1523,1524,null,null,null,null,null,null,null,1488,1489,1490,1491,1492,1493,1494,1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,1510,1511,1512,1513,1514,null,null,8206,8207,null],
+ "windows-1256":[8364,1662,8218,402,8222,8230,8224,8225,710,8240,1657,8249,338,1670,1688,1672,1711,8216,8217,8220,8221,8226,8211,8212,1705,8482,1681,8250,339,8204,8205,1722,160,1548,162,163,164,165,166,167,168,169,1726,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,1563,187,188,189,190,1567,1729,1569,1570,1571,1572,1573,1574,1575,1576,1577,1578,1579,1580,1581,1582,1583,1584,1585,1586,1587,1588,1589,1590,215,1591,1592,1593,1594,1600,1601,1602,1603,224,1604,226,1605,1606,1607,1608,231,232,233,234,235,1609,1610,238,239,1611,1612,1613,1614,244,1615,1616,247,1617,249,1618,251,252,8206,8207,1746],
+ "windows-1257":[8364,129,8218,131,8222,8230,8224,8225,136,8240,138,8249,140,168,711,184,144,8216,8217,8220,8221,8226,8211,8212,152,8482,154,8250,156,175,731,159,160,null,162,163,164,null,166,167,216,169,342,171,172,173,174,198,176,177,178,179,180,181,182,183,248,185,343,187,188,189,190,230,260,302,256,262,196,197,280,274,268,201,377,278,290,310,298,315,352,323,325,211,332,213,214,215,370,321,346,362,220,379,381,223,261,303,257,263,228,229,281,275,269,233,378,279,291,311,299,316,353,324,326,243,333,245,246,247,371,322,347,363,252,380,382,729],
+ "windows-1258":[8364,129,8218,402,8222,8230,8224,8225,710,8240,138,8249,338,141,142,143,144,8216,8217,8220,8221,8226,8211,8212,732,8482,154,8250,339,157,158,376,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,258,196,197,198,199,200,201,202,203,768,205,206,207,272,209,777,211,212,416,214,215,216,217,218,219,220,431,771,223,224,225,226,259,228,229,230,231,232,233,234,235,769,237,238,239,273,241,803,243,244,417,246,247,248,249,250,251,252,432,8363,255],
+ "x-mac-cyrillic":[1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,8224,176,1168,163,167,8226,182,1030,174,169,8482,1026,1106,8800,1027,1107,8734,177,8804,8805,1110,181,1169,1032,1028,1108,1031,1111,1033,1113,1034,1114,1112,1029,172,8730,402,8776,8710,171,187,8230,160,1035,1115,1036,1116,1109,8211,8212,8220,8221,8216,8217,247,8222,1038,1118,1039,1119,8470,1025,1105,1103,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,8364]
+ }
+
+ // For TextDecoder tests
+ var buffer = new ArrayBuffer(255),
+ view = new Uint8Array(buffer)
+ for(var i = 0, l = view.byteLength; i < l; i++) {
+ view[i] = i
+ }
+
+ // For XMLHttpRequest and TextDecoder tests
+ function assert_decode(data, encoding) {
+ if(encoding == "iso-8859-8-i") {
+ encoding = "iso-8859-8"
+ }
+ for(var i = 0, l = data.length; i < l; i++) {
+ var cp = data.charCodeAt(i),
+ expectedCp = (i < 0x80) ? i : singleByteIndexes[encoding][i-0x80]
+ if(expectedCp == null) {
+ expectedCp = 0xFFFD
+ }
+ assert_equals(cp, expectedCp, encoding + ":" + i)
+ }
+ }
+
+ // Setting up all the tests
+ for(var i = 0, l = singleByteEncodings.length; i < l; i++) {
+ var encoding = singleByteEncodings[i]
+ for(var ii = 0, ll = encoding.labels.length; ii < ll; ii++) {
+ var label = encoding.labels[ii]
+
+ async_test(function(t) {
+ var xhr = new XMLHttpRequest,
+ name = encoding.name // need scoped variable
+ xhr.open("GET", "resources/single-byte-raw.py?label=" + label)
+ xhr.send(null)
+ xhr.onload = t.step_func_done(function() { assert_decode(xhr.responseText, name) })
+ }, encoding.name + ": " + label + " (XMLHttpRequest)")
+
+ test(function() {
+ var d = new TextDecoder(label),
+ data = d.decode(view)
+ assert_equals(d.encoding, encoding.name)
+ assert_decode(data, encoding.name)
+ }, encoding.name + ": " + label + " (TextDecoder)")
+
+ async_test(function(t) {
+ var frame = document.createElement("iframe"),
+ name = compatibility_names[encoding.name] || encoding.name;
+ frame.src = "resources/single-byte-raw.py?label=" + label
+ frame.onload = t.step_func_done(function() {
+ assert_equals(frame.contentDocument.characterSet, name)
+ assert_equals(frame.contentDocument.inputEncoding, name)
+ })
+ t.add_cleanup(function() { document.body.removeChild(frame) })
+ document.body.appendChild(frame)
+ }, encoding.name + ": " + label + " (document.characterSet and document.inputEncoding)")
+ }
+ }
+</script>
diff --git a/tests/wpt/web-platform-tests/encoding/textdecoder-byte-order-marks.html b/tests/wpt/web-platform-tests/encoding/textdecoder-byte-order-marks.html
new file mode 100644
index 00000000000..8ef16794381
--- /dev/null
+++ b/tests/wpt/web-platform-tests/encoding/textdecoder-byte-order-marks.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<title>Encoding API: Byte-order marks</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+
+var testCases = [
+ {
+ encoding: 'utf-8',
+ bom: [0xEF, 0xBB, 0xBF],
+ bytes: [0x7A, 0xC2, 0xA2, 0xE6, 0xB0, 0xB4, 0xF0, 0x9D, 0x84, 0x9E, 0xF4, 0x8F, 0xBF, 0xBD]
+ },
+ {
+ encoding: 'utf-16le',
+ bom: [0xff, 0xfe],
+ bytes: [0x7A, 0x00, 0xA2, 0x00, 0x34, 0x6C, 0x34, 0xD8, 0x1E, 0xDD, 0xFF, 0xDB, 0xFD, 0xDF]
+ },
+ {
+ encoding: 'utf-16be',
+ bom: [0xfe, 0xff],
+ bytes: [0x00, 0x7A, 0x00, 0xA2, 0x6C, 0x34, 0xD8, 0x34, 0xDD, 0x1E, 0xDB, 0xFF, 0xDF, 0xFD]
+ }
+];
+
+var string = 'z\xA2\u6C34\uD834\uDD1E\uDBFF\uDFFD'; // z, cent, CJK water, G-Clef, Private-use character
+
+testCases.forEach(function(t) {
+ test(function() {
+
+ var decoder = new TextDecoder(t.encoding);
+ assert_equals(decoder.decode(new Uint8Array(t.bytes)), string,
+ 'Sequence without BOM should decode successfully');
+
+ assert_equals(decoder.decode(new Uint8Array(t.bom.concat(t.bytes))), string,
+ 'Sequence with BOM should decode successfully (with no BOM present in output)');
+
+ testCases.forEach(function(o) {
+ if (o === t)
+ return;
+
+ assert_not_equals(decoder.decode(new Uint8Array(o.bom.concat(t.bytes))), string,
+ 'Mismatching BOM should not be ignored - treated as garbage bytes.');
+ });
+
+ }, 'Byte-order marks: ' + t.encoding);
+});
+
+</script>
diff --git a/tests/wpt/web-platform-tests/encoding/textdecoder-fatal-streaming.html b/tests/wpt/web-platform-tests/encoding/textdecoder-fatal-streaming.html
new file mode 100644
index 00000000000..2ccac9f230d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/encoding/textdecoder-fatal-streaming.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<title>Encoding API: End-of-file</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+
+test(function() {
+ [
+ {encoding: 'utf-8', sequence: [0xC0]},
+ {encoding: 'utf-16le', sequence: [0x00]},
+ {encoding: 'utf-16be', sequence: [0x00]}
+ ].forEach(function(testCase) {
+
+ assert_throws(new TypeError(), function() {
+ var decoder = new TextDecoder(testCase.encoding, {fatal: true});
+ decoder.decode(new Uint8Array(testCase.sequence));
+ }, 'Unterminated ' + testCase.encoding + ' sequence should throw if fatal flag is set');
+
+ assert_equals(
+ new TextDecoder(testCase.encoding).decode(new Uint8Array([testCase.sequence])),
+ '\uFFFD',
+ 'Unterminated UTF-8 sequence should emit replacement character if fatal flag is unset');
+ });
+}, 'Fatal flag, non-streaming cases');
+
+test(function() {
+
+ var decoder = new TextDecoder('utf-16le', {fatal: true});
+ var odd = new Uint8Array([0x00]);
+ var even = new Uint8Array([0x00, 0x00]);
+
+ assert_equals(decoder.decode(odd, {stream: true}), '');
+ assert_equals(decoder.decode(odd), '\u0000');
+
+ assert_throws(new TypeError(), function() {
+ decoder.decode(even, {stream: true});
+ decoder.decode(odd)
+ });
+
+ assert_throws(new TypeError(), function() {
+ decoder.decode(odd, {stream: true});
+ decoder.decode(even);
+ });
+
+ assert_equals(decoder.decode(even, {stream: true}), '\u0000');
+ assert_equals(decoder.decode(even), '\u0000');
+
+}, 'Fatal flag, streaming cases');
+
+</script>
diff --git a/tests/wpt/web-platform-tests/encoding/textdecoder-fatal.html b/tests/wpt/web-platform-tests/encoding/textdecoder-fatal.html
new file mode 100644
index 00000000000..4cd38e88b34
--- /dev/null
+++ b/tests/wpt/web-platform-tests/encoding/textdecoder-fatal.html
@@ -0,0 +1,73 @@
+<!DOCTYPE html>
+<title>Encoding API: Fatal flag</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/shared.js"></script>
+<script>
+
+var bad = [
+ { encoding: 'utf-8', input: [0xFF], name: 'invalid code' },
+ { encoding: 'utf-8', input: [0xC0], name: 'ends early' },
+ { encoding: 'utf-8', input: [0xE0], name: 'ends early 2' },
+ { encoding: 'utf-8', input: [0xC0, 0x00], name: 'invalid trail' },
+ { encoding: 'utf-8', input: [0xC0, 0xC0], name: 'invalid trail 2' },
+ { encoding: 'utf-8', input: [0xE0, 0x00], name: 'invalid trail 3' },
+ { encoding: 'utf-8', input: [0xE0, 0xC0], name: 'invalid trail 4' },
+ { encoding: 'utf-8', input: [0xE0, 0x80, 0x00], name: 'invalid trail 5' },
+ { encoding: 'utf-8', input: [0xE0, 0x80, 0xC0], name: 'invalid trail 6' },
+ { encoding: 'utf-8', input: [0xFC, 0x80, 0x80, 0x80, 0x80, 0x80], name: '> 0x10FFFF' },
+ { encoding: 'utf-8', input: [0xFE, 0x80, 0x80, 0x80, 0x80, 0x80], name: 'obsolete lead byte' },
+
+ // Overlong encodings
+ { encoding: 'utf-8', input: [0xC0, 0x80], name: 'overlong U+0000 - 2 bytes' },
+ { encoding: 'utf-8', input: [0xE0, 0x80, 0x80], name: 'overlong U+0000 - 3 bytes' },
+ { encoding: 'utf-8', input: [0xF0, 0x80, 0x80, 0x80], name: 'overlong U+0000 - 4 bytes' },
+ { encoding: 'utf-8', input: [0xF8, 0x80, 0x80, 0x80, 0x80], name: 'overlong U+0000 - 5 bytes' },
+ { encoding: 'utf-8', input: [0xFC, 0x80, 0x80, 0x80, 0x80, 0x80], name: 'overlong U+0000 - 6 bytes' },
+
+ { encoding: 'utf-8', input: [0xC1, 0xBF], name: 'overlong U+007F - 2 bytes' },
+ { encoding: 'utf-8', input: [0xE0, 0x81, 0xBF], name: 'overlong U+007F - 3 bytes' },
+ { encoding: 'utf-8', input: [0xF0, 0x80, 0x81, 0xBF], name: 'overlong U+007F - 4 bytes' },
+ { encoding: 'utf-8', input: [0xF8, 0x80, 0x80, 0x81, 0xBF], name: 'overlong U+007F - 5 bytes' },
+ { encoding: 'utf-8', input: [0xFC, 0x80, 0x80, 0x80, 0x81, 0xBF], name: 'overlong U+007F - 6 bytes' },
+
+ { encoding: 'utf-8', input: [0xE0, 0x9F, 0xBF], name: 'overlong U+07FF - 3 bytes' },
+ { encoding: 'utf-8', input: [0xF0, 0x80, 0x9F, 0xBF], name: 'overlong U+07FF - 4 bytes' },
+ { encoding: 'utf-8', input: [0xF8, 0x80, 0x80, 0x9F, 0xBF], name: 'overlong U+07FF - 5 bytes' },
+ { encoding: 'utf-8', input: [0xFC, 0x80, 0x80, 0x80, 0x9F, 0xBF], name: 'overlong U+07FF - 6 bytes' },
+
+ { encoding: 'utf-8', input: [0xF0, 0x8F, 0xBF, 0xBF], name: 'overlong U+FFFF - 4 bytes' },
+ { encoding: 'utf-8', input: [0xF8, 0x80, 0x8F, 0xBF, 0xBF], name: 'overlong U+FFFF - 5 bytes' },
+ { encoding: 'utf-8', input: [0xFC, 0x80, 0x80, 0x8F, 0xBF, 0xBF], name: 'overlong U+FFFF - 6 bytes' },
+
+ { encoding: 'utf-8', input: [0xF8, 0x84, 0x8F, 0xBF, 0xBF], name: 'overlong U+10FFFF - 5 bytes' },
+ { encoding: 'utf-8', input: [0xFC, 0x80, 0x84, 0x8F, 0xBF, 0xBF], name: 'overlong U+10FFFF - 6 bytes' },
+
+ // UTF-16 surrogates encoded as code points in UTF-8
+ { encoding: 'utf-8', input: [0xED, 0xA0, 0x80], name: 'lead surrogate' },
+ { encoding: 'utf-8', input: [0xED, 0xB0, 0x80], name: 'trail surrogate' },
+ { encoding: 'utf-8', input: [0xED, 0xA0, 0x80, 0xED, 0xB0, 0x80], name: 'surrogate pair' },
+
+ { encoding: 'utf-16le', input: [0x00], name: 'truncated code unit' },
+ // Mismatched UTF-16 surrogates are exercised in utf16-surrogates.html
+
+ // FIXME: Add legacy encoding cases
+];
+
+bad.forEach(function(t) {
+ test(function() {
+ assert_throws(new TypeError(), function() {
+ new TextDecoder(t.encoding, {fatal: true}).decode(new Uint8Array(t.input))
+ });
+ }, 'Fatal flag: ' + t.encoding + ' - ' + t.name);
+});
+
+test(function() {
+ assert_true('fatal' in new TextDecoder(), 'The fatal attribute should exist on TextDecoder.');
+ assert_equals(typeof new TextDecoder().fatal, 'boolean', 'The type of the fatal attribute should be boolean.');
+ assert_false(new TextDecoder().fatal, 'The fatal attribute should default to false.');
+ assert_true(new TextDecoder('utf-8', {fatal: true}).fatal, 'The fatal attribute can be set using an option.');
+
+}, 'The fatal attribute of TextDecoder');
+
+</script>
diff --git a/tests/wpt/web-platform-tests/encoding/textdecoder-ignorebom.html b/tests/wpt/web-platform-tests/encoding/textdecoder-ignorebom.html
new file mode 100644
index 00000000000..26381568f59
--- /dev/null
+++ b/tests/wpt/web-platform-tests/encoding/textdecoder-ignorebom.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<title>Encoding API: TextDecoder ignoreBOM option</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+
+var cases = [
+ {encoding: 'utf-8', bytes: [0xEF, 0xBB, 0xBF, 0x61, 0x62, 0x63]},
+ {encoding: 'utf-16le', bytes: [0xFF, 0xFE, 0x61, 0x00, 0x62, 0x00, 0x63, 0x00]},
+ {encoding: 'utf-16be', bytes: [0xFE, 0xFF, 0x00, 0x61, 0x00, 0x62, 0x00, 0x63]}
+];
+
+cases.forEach(function(testCase) {
+ test(function() {
+ var BOM = '\uFEFF';
+ var decoder = new TextDecoder(testCase.encoding, {ignoreBOM: true});
+ var bytes = new Uint8Array(testCase.bytes);
+ assert_equals(
+ decoder.decode(bytes),
+ BOM + 'abc',
+ testCase.encoding + ': BOM should be present in decoded string if ignored');
+
+ decoder = new TextDecoder(testCase.encoding, {ignoreBOM: false});
+ assert_equals(
+ decoder.decode(bytes),
+ 'abc',
+ testCase.encoding + ': BOM should be absent from decoded string if not ignored');
+
+ decoder = new TextDecoder(testCase.encoding);
+ assert_equals(
+ decoder.decode(bytes),
+ 'abc',
+ testCase.encoding + ': BOM should be absent from decoded string by default');
+ }, 'BOM is ignored if ignoreBOM option is specified: ' + testCase.encoding);
+});
+
+test(function() {
+ assert_true('ignoreBOM' in new TextDecoder(), 'The ignoreBOM attribute should exist on TextDecoder.');
+ assert_equals(typeof new TextDecoder().ignoreBOM, 'boolean', 'The type of the ignoreBOM attribute should be boolean.');
+ assert_false(new TextDecoder().ignoreBOM, 'The ignoreBOM attribute should default to false.');
+ assert_true(new TextDecoder('utf-8', {ignoreBOM: true}).ignoreBOM, 'The ignoreBOM attribute can be set using an option.');
+
+}, 'The ignoreBOM attribute of TextDecoder');
+
+</script>
diff --git a/tests/wpt/web-platform-tests/encoding/textdecoder-labels.html b/tests/wpt/web-platform-tests/encoding/textdecoder-labels.html
new file mode 100644
index 00000000000..5a56ff9cb6d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/encoding/textdecoder-labels.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<title>Encoding API: Encoding labels</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/encodings.js"></script>
+<script>
+
+encodings_table.forEach(function(section) {
+ section.encodings.filter(function(encoding) {
+ return encoding.name !== 'replacement';
+ }).forEach(function(encoding) {
+ var name = encoding.name;
+ encoding.labels.forEach(function(label) {
+ test(function(){
+ assert_equals(new TextDecoder(label).encoding, encoding.name,
+ 'label for encoding should match');
+ assert_equals(new TextDecoder(label.toUpperCase()).encoding,
+ encoding.name,
+ 'label matching should be case-insensitive');
+ }, 'name=' + name + ' label=' + label);
+ });
+ });
+});
+
+</script>
diff --git a/tests/wpt/web-platform-tests/encoding/textdecoder-streaming.html b/tests/wpt/web-platform-tests/encoding/textdecoder-streaming.html
new file mode 100644
index 00000000000..d514a180648
--- /dev/null
+++ b/tests/wpt/web-platform-tests/encoding/textdecoder-streaming.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Encoding API: Streaming decode</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/encodings.js"></script>
+<script>
+
+var string = '\\x00123ABCabc\\x80\\xFF\\u0100\\u1000\\uFFFD\\uD800\\uDC00\\uDBFF\\uDFFF';
+
+utf_encodings.forEach(function (encoding) {
+ for (var len = 1; len <= 5; ++len) {
+ test(function() {
+ var encoded = new TextEncoder(encoding).encode(string);
+
+ var out = '';
+ var decoder = new TextDecoder(encoding);
+ for (var i = 0; i < encoded.length; i += len) {
+ var sub = [];
+ for (var j = i; j < encoded.length && j < i + len; ++j)
+ sub.push(encoded[j]);
+ out += decoder.decode(new Uint8Array(sub), {stream: true});
+ }
+ out += decoder.decode();
+ assert_equals(out, string);
+ }, 'Streaming decode: ' + encoding + ', ' + len + ' byte window');
+ }
+});
+
+</script>
diff --git a/tests/wpt/web-platform-tests/encoding/textdecoder-utf16-surrogates.html b/tests/wpt/web-platform-tests/encoding/textdecoder-utf16-surrogates.html
new file mode 100644
index 00000000000..ae95ab70b8e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/encoding/textdecoder-utf16-surrogates.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<title>Encoding API: UTF-16 surrogate handling</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/shared.js"></script>
+<script>
+
+var bad = [
+ {
+ encoding: 'utf-16le',
+ input: [0x00, 0xd8],
+ expected: '\uFFFD',
+ name: 'lone surrogate lead'
+ },
+ {
+ encoding: 'utf-16le',
+ input: [0x00, 0xdc],
+ expected: '\uFFFD',
+ name: 'lone surrogate trail'
+ },
+ {
+ encoding: 'utf-16le',
+ input: [0x00, 0xd8, 0x00, 0x00],
+ expected: '\uFFFD\u0000',
+ name: 'unmatched surrogate lead'
+ },
+ {
+ encoding: 'utf-16le',
+ input: [0x00, 0xdc, 0x00, 0x00],
+ expected: '\uFFFD\u0000',
+ name: 'unmatched surrogate trail'
+ },
+ {
+ encoding: 'utf-16le',
+ input: [0x00, 0xdc, 0x00, 0xd8],
+ expected: '\uFFFD\uFFFD',
+ name: 'swapped surrogate pair'
+ }
+];
+
+bad.forEach(function(t) {
+ test(function() {
+ assert_equals(new TextDecoder(t.encoding).decode(new Uint8Array(t.input)), t.expected);
+ }, t.encoding + ' - ' + t.name);
+ test(function() {
+ assert_throws(new TypeError(), function() {
+ new TextDecoder(t.encoding, {fatal: true}).decode(new Uint8Array(t.input))
+ });
+ }, t.encoding + ' - ' + t.name + ' (fatal flag set)');
+});
+
+</script>
diff --git a/tests/wpt/web-platform-tests/encoding/textencoder-constructor-non-utf.html b/tests/wpt/web-platform-tests/encoding/textencoder-constructor-non-utf.html
new file mode 100644
index 00000000000..f284ad0aa74
--- /dev/null
+++ b/tests/wpt/web-platform-tests/encoding/textencoder-constructor-non-utf.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Encoding API: Legacy encodings</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/encodings.js"></script>
+<script>
+
+encodings_table.forEach(function(section) {
+ section.encodings.filter(function(encoding) {
+ return encoding.name !== 'replacement';
+ }).forEach(function(encoding) {
+ if (utf_encodings.indexOf(encoding.name) !== -1) {
+ test(function() {
+ assert_equals(new TextDecoder(encoding.name).encoding, encoding.name);
+ assert_equals(new TextEncoder(encoding.name).encoding, encoding.name);
+ }, 'UTF encodings are supported for encode and decode: ' + encoding.name);
+ } else {
+ test(function() {
+ assert_equals(new TextDecoder(encoding.name).encoding, encoding.name);
+ assert_throws({name: 'RangeError'}, function() { new TextEncoder(encoding.name); });
+ }, 'Non-UTF encodings supported only for decode, not encode: ' + encoding.name);
+ }
+ });
+});
+
+</script>
diff --git a/tests/wpt/web-platform-tests/encoding/textencoder-utf16-surrogates.html b/tests/wpt/web-platform-tests/encoding/textencoder-utf16-surrogates.html
new file mode 100644
index 00000000000..9af28fdf7e9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/encoding/textencoder-utf16-surrogates.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<title>Encoding API: USVString surrogate handling when encoding</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/shared.js"></script>
+<script>
+
+var bad = [
+ {
+ input: '\uD800',
+ expected: '\uFFFD',
+ name: 'lone surrogate lead'
+ },
+ {
+ input: '\uDC00',
+ expected: '\uFFFD',
+ name: 'lone surrogate trail'
+ },
+ {
+ input: '\uD800\u0000',
+ expected: '\uFFFD\u0000',
+ name: 'unmatched surrogate lead'
+ },
+ {
+ input: '\uDC00\u0000',
+ expected: '\uFFFD\u0000',
+ name: 'unmatched surrogate trail'
+ },
+ {
+ input: '\uDC00\uD800',
+ expected: '\uFFFD\uFFFD',
+ name: 'swapped surrogate pair'
+ },
+ {
+ input: '\uD834\uDD1E',
+ expected: '\uD834\uDD1E',
+ name: 'properly encoded MUSICAL SYMBOL G CLEF (U+1D11E)'
+ }
+];
+
+var encoding = 'utf-8';
+
+bad.forEach(function(t) {
+ test(function() {
+ var encoded = new TextEncoder(encoding).encode(t.input);
+ var decoded = new TextDecoder(encoding).decode(encoded);
+ assert_equals(decoded, t.expected);
+ }, 'USVString handling: ' + t.name);
+});
+
+test(function() {
+ assert_equals(new TextEncoder(encoding).encode().length, 0, 'Should default to empty string');
+}, 'USVString default');
+
+</script>
diff --git a/tests/wpt/web-platform-tests/eventsource/README.md b/tests/wpt/web-platform-tests/eventsource/README.md
new file mode 100644
index 00000000000..6b58a1ef51e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/README.md
@@ -0,0 +1,54 @@
+# Server-Sent Events Test Collection
+
+Server-Sent Events [latest draft](http://dev.w3.org/html5/eventsource/).
+
+Following up work done during the TestTWF 2012 Paris event:
+
+Most tests comes from [Opera](http://tc.labs.opera.com/apis/EventSource/), are from august 2010 and probably only valid against [spec rev. ~1.139](http://dev.w3.org/cvsweb/~checkout~/html5/eventsource/Overview.html?rev=1.139;content-type=text%2Fhtml). You can check the following diff :
+
+[diff between 1.139 (23 Jul 2010) and 1.229 (25 Oct. 2012) revisions](http://dev.w3.org/cvsweb/html5/eventsource/Overview.html.diff?r1=text&tr1=1.139&r2=text&tr2=1.229)
+
+to get an idea of what needs to get updated.
+
+##DONE (updated against rev. 1.229):
+- **eventsource-constructor-url-bogus.htm**: whatwg r6602: renamed SYNTAX_ERR to SyntaxError
+
+- **eventsource-constructor-stringify.htm**: still valid. bugfix.
+
+##TODO (need to be updated against rev. 1.229):
+- **eventsource-cross-origin.htm**, **eventsource-constructor-non-same-origin.htm**: whatwg 6255 6257: allow CORS
+
+##TOCHECK (need to check if the test is still valid against rev.1.229):
+eventsource-close.htm
+eventsource-constructor-document-domain.htm
+eventsource-constructor-url-multi-window.htm
+eventsource-eventtarget.htm
+eventsource-onmessage.htm
+eventsource-onopen.htm
+eventsource-prototype.htm
+eventsource-reconnect.htm
+eventsource-url.htm
+format-bom-2.htm
+format-bom.htm
+format-comments.htm
+format-field-data.htm
+format-field-event-empty.htm
+format-field-event.htm
+format-field-id-2.htm
+format-field-id.htm
+format-field-parsing.htm
+format-field-retry-bogus.htm
+format-field-retry-empty.htm
+format-field-retry.htm
+format-field-unknown.htm
+format-leading-space.htm
+format-mime-bogus.htm
+format-mime-trailing-semicolon.htm
+format-mime-valid-bogus.htm
+format-newlines.htm
+format-utf-8.htm
+request-accept.htm
+request-cache-control.htm
+request-credentials.htm
+request-redirect.htm
+request-status-error.htm
diff --git a/tests/wpt/web-platform-tests/eventsource/dedicated-worker/eventsource-close.htm b/tests/wpt/web-platform-tests/eventsource/dedicated-worker/eventsource-close.htm
new file mode 100644
index 00000000000..42ebb1da875
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/dedicated-worker/eventsource-close.htm
@@ -0,0 +1,36 @@
+<!--
+try {
+ var source = new EventSource("../resources/message.py")
+ source.onopen = function(e) {
+ this.close()
+ postMessage([true, this.readyState])
+ }
+} catch(e) {
+ postMessage([false, String(e)])
+}
+/*-->
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>dedicated worker - EventSource: close()</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test();
+ test.step(function() {
+ var worker = new Worker('#')
+ worker.onmessage = function(e) {
+ test.step(function() {
+ assert_true(e.data[0], e.data[1])
+ assert_equals(e.data[1], EventSource.CLOSED, 'this.readyState')
+ })
+ test.done()
+ }
+ })
+ </script>
+ </body>
+</html>
+<!--*/ //-->
diff --git a/tests/wpt/web-platform-tests/eventsource/dedicated-worker/eventsource-constructor-non-same-origin.htm b/tests/wpt/web-platform-tests/eventsource/dedicated-worker/eventsource-constructor-non-same-origin.htm
new file mode 100644
index 00000000000..9fe515d2a70
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/dedicated-worker/eventsource-constructor-non-same-origin.htm
@@ -0,0 +1,49 @@
+<!--
+try {
+ var url = decodeURIComponent(location.hash.substr(1))
+ var source = new EventSource(url)
+ source.onerror = function(e) {
+ postMessage([true, this.readyState, 'data' in e])
+ this.close();
+ }
+} catch(e) {
+ postMessage([false, String(e)])
+}
+/*-->
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>dedicated worker - EventSource: constructor (act as if there is a network error)</title>
+ <meta name=timeout content=long>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ function fetchFail(url) {
+ var test = async_test(document.title + " (" + url + ")", { timeout: 20000 })
+ test.step(function() {
+ var worker = new Worker('#'+encodeURIComponent(url))
+ worker.onmessage = function(e) {
+ test.step(function() {
+ assert_true(e.data[0], e.data[1])
+ assert_equals(e.data[1], EventSource.CLOSED, 'source.readyState')
+ assert_false(e.data[2], "'data' in e");
+ })
+ test.done()
+ }
+ })
+ }
+ fetchFail("http://example.not/")
+ fetchFail("https://example.not/test")
+ fetchFail("ftp://example.not/")
+ fetchFail("about:blank")
+ fetchFail("mailto:whatwg@awesome.example")
+ fetchFail("javascript:alert('FAIL')")
+ </script>
+ <!-- This tests "fails the connection" as well as making sure a simple
+ event is dispatched and not a MessageEvent -->
+ </body>
+</html>
+<!--*/ //-->
diff --git a/tests/wpt/web-platform-tests/eventsource/dedicated-worker/eventsource-constructor-url-bogus.htm b/tests/wpt/web-platform-tests/eventsource/dedicated-worker/eventsource-constructor-url-bogus.htm
new file mode 100644
index 00000000000..5ffdec81ffe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/dedicated-worker/eventsource-constructor-url-bogus.htm
@@ -0,0 +1,34 @@
+<!--
+try {
+ var source = new EventSource("http://this is invalid/")
+ postMessage([false, 'no exception thrown'])
+ source.close()
+} catch(e) {
+ postMessage([true, e.code])
+}
+/*-->
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>dedicated worker - EventSource: constructor (invalid URL)</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+ var worker = new Worker('#')
+ worker.onmessage = function(e) {
+ test.step(function() {
+ assert_true(e.data[0], e.data[1])
+ assert_equals(e.data[1], DOMException.SYNTAX_ERR, 'e.code')
+ })
+ test.done()
+ }
+ })
+ </script>
+ </body>
+</html>
+<!--*/ //--> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/eventsource/dedicated-worker/eventsource-eventtarget.htm b/tests/wpt/web-platform-tests/eventsource/dedicated-worker/eventsource-eventtarget.htm
new file mode 100644
index 00000000000..ff40c59d513
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/dedicated-worker/eventsource-eventtarget.htm
@@ -0,0 +1,37 @@
+<!--
+try {
+ var source = new EventSource("../resources/message.py")
+ source.addEventListener("message", listener, false)
+ function listener(e) {
+ postMessage([true, e.data])
+ this.close()
+ }
+} catch(e) {
+ postMessage([false, String(e)])
+}
+/*-->
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>dedicated worker - EventSource: addEventListener()</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+ var worker = new Worker('#')
+ worker.onmessage = function(e) {
+ test.step(function() {
+ assert_true(e.data[0], e.data[1])
+ assert_equals(e.data[1], 'data', 'e.data')
+ })
+ test.done()
+ }
+ })
+ </script>
+ </body>
+</html>
+<!--*/ //-->
diff --git a/tests/wpt/web-platform-tests/eventsource/dedicated-worker/eventsource-onmesage.htm b/tests/wpt/web-platform-tests/eventsource/dedicated-worker/eventsource-onmesage.htm
new file mode 100644
index 00000000000..2de142ca5af
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/dedicated-worker/eventsource-onmesage.htm
@@ -0,0 +1,36 @@
+<!--
+try {
+ var source = new EventSource("../resources/message.py")
+ source.onmessage = function(e) {
+ postMessage([true, e.data])
+ this.close()
+ }
+} catch(e) {
+ postMessage([false, String(e)])
+}
+/*-->
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>dedicated worker - EventSource: onmessage</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+ var worker = new Worker('#')
+ worker.onmessage = function(e) {
+ test.step(function() {
+ assert_true(e.data[0], e.data[1])
+ assert_equals(e.data[1], "data", 'e.data')
+ })
+ test.done()
+ }
+ })
+ </script>
+ </body>
+</html>
+<!--*/ //-->
diff --git a/tests/wpt/web-platform-tests/eventsource/dedicated-worker/eventsource-onopen.htm b/tests/wpt/web-platform-tests/eventsource/dedicated-worker/eventsource-onopen.htm
new file mode 100644
index 00000000000..e753b42f7b5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/dedicated-worker/eventsource-onopen.htm
@@ -0,0 +1,39 @@
+<!--
+try {
+ var source = new EventSource("../resources/message.py")
+ source.onopen = function(e) {
+ postMessage([true, source.readyState, 'data' in e, e.bubbles, e.cancelable])
+ this.close()
+ }
+} catch(e) {
+ postMessage([false, String(e)])
+}
+/*-->
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>dedicated worker - EventSource: onopen (announcing the connection)</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+ var worker = new Worker('#')
+ worker.onmessage = function(e) {
+ test.step(function() {
+ assert_true(e.data[0], e.data[1])
+ assert_equals(e.data[1], EventSource.OPEN, 'source.readyState')
+ assert_false(e.data[2], "'data' in e")
+ assert_false(e.data[3], 'e.bubbles')
+ assert_false(e.data[4], 'e.calcelable')
+ })
+ test.done()
+ }
+ })
+ </script>
+ </body>
+</html>
+<!--*/ //-->
diff --git a/tests/wpt/web-platform-tests/eventsource/dedicated-worker/eventsource-prototype.htm b/tests/wpt/web-platform-tests/eventsource/dedicated-worker/eventsource-prototype.htm
new file mode 100644
index 00000000000..b16e24c8617
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/dedicated-worker/eventsource-prototype.htm
@@ -0,0 +1,36 @@
+<!--
+try {
+ EventSource.prototype.ReturnTrue = function() { return true }
+ var source = new EventSource("../resources/message.py")
+ postMessage([true, source.ReturnTrue(), 'EventSource' in self])
+ source.close()
+} catch(e) {
+ postMessage([false, String(e)])
+}
+/*-->
+<!DoCtYpE hTMl>
+<html>
+ <heAd>
+ <title>dedicated worker - EventSource: prototype et al</tiTle>
+ <scrIpt src="/resources/testharness.js"></scripT>
+ <scriPt src="/resources/testharnessreport.js"></Script>
+ </heaD>
+ <boDy>
+ <diV iD="log"></Div>
+ <sCript>
+ var test = async_test();
+ test.step(function() {
+ var worker = new Worker('#')
+ worker.onmessage = function(e) {
+ test.step(function() {
+ assert_true(e.data[0], e.data[1])
+ assert_true(e.data[1], 'source.ReturnTrue()')
+ assert_true(e.data[2], "'EventSource' in self")
+ })
+ test.done()
+ }
+ })
+ </scrIpt>
+ </bOdy>
+</htMl>
+<!--*/ //-->
diff --git a/tests/wpt/web-platform-tests/eventsource/dedicated-worker/eventsource-url.htm b/tests/wpt/web-platform-tests/eventsource/dedicated-worker/eventsource-url.htm
new file mode 100644
index 00000000000..c1ed0782713
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/dedicated-worker/eventsource-url.htm
@@ -0,0 +1,35 @@
+<!--
+try {
+ var source = new EventSource("../resources/message.py")
+ postMessage([true, source.url])
+ source.close()
+} catch(e) {
+ postMessage([false, String(e)])
+}
+/*-->
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>dedicated worker - EventSource: url</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test();
+ test.step(function() {
+ var url = "resources/message.py"
+ var worker = new Worker('#')
+ worker.onmessage = function(e) {
+ test.step(function() {
+ assert_true(e.data[0], e.data[1]);
+ assert_equals(e.data[1].substr(-(url.length)), url)
+ })
+ test.done()
+ }
+ })
+ </script>
+ </body>
+</html>
+<!--*/ //-->
diff --git a/tests/wpt/web-platform-tests/eventsource/event-data.html b/tests/wpt/web-platform-tests/eventsource/event-data.html
new file mode 100644
index 00000000000..8f74a017835
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/event-data.html
@@ -0,0 +1,44 @@
+<!doctype html>
+<html>
+ <head>
+ <title>EventSource: lines and data parsing</title>
+ <meta rel=help href="http://dev.w3.org/html5/eventsource/#event-stream-interpretation">
+ <meta rel=assert title="If the line is empty (a blank line) Dispatch the event, as defined below.">
+ <meta rel=assert title="If the line starts with a U+003A COLON character (:) Ignore the line.">
+ <meta rel=assert title="If the line contains a U+003A COLON character (:)
+ Collect the characters on the line before the first U+003A COLON character (:), and let field be that string.
+ Collect the characters on the line after the first U+003A COLON character (:), and let value be that string. If value starts with a U+0020 SPACE character, remove it from value.
+ Process the field using the steps described below, using field as the field name and value as the field value.
+ ">
+ <meta rel=assert title="Otherwise, the string is not empty but does not contain a U+003A COLON character (:)
+Process the field using the steps described below, using the whole line as the field name, and the empty string as the field value.
+ ">
+
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test(document.title);
+ test.step(function() {
+ var source = new EventSource("resources/message2.py"),
+ counter = 0;
+ source.onmessage = test.step_func(function(e) {
+ if(counter == 0) {
+ assert_equals(e.data,"msg\nmsg");
+ } else if(counter == 1) {
+ assert_equals(e.data,"");
+ } else if(counter == 2) {
+ assert_equals(e.data,"end");
+ source.close();
+ test.done();
+ } else {
+ assert_unreached();
+ }
+ counter++;
+ });
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/eventsource/eventsource-close.htm b/tests/wpt/web-platform-tests/eventsource/eventsource-close.htm
new file mode 100644
index 00000000000..92d98ded797
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/eventsource-close.htm
@@ -0,0 +1,82 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>EventSource: close()</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+ var source = new EventSource("resources/message.py")
+ assert_equals(source.readyState, source.CONNECTING, "connecting readyState");
+ source.onopen = this.step_func(function() {
+ assert_equals(source.readyState, source.OPEN, "open readyState");
+ source.close()
+ assert_equals(source.readyState, source.CLOSED, "closed readyState");
+ this.done()
+ })
+ })
+
+ var test2 = async_test(document.title + ", test events", { timeout: 9000 });
+ test2.step(function() {
+ var count = 0, reconnected = false,
+ source = new EventSource("resources/reconnect-fail.py?id=" + new Date().getTime());
+
+ source.onerror = this.step_func(function(e) {
+ assert_equals(e.type, 'error');
+ switch(count) {
+ // reconnecting after first message
+ case 1:
+ assert_equals(source.readyState, source.CONNECTING, "reconnecting readyState");
+
+ reconnected = true;
+ break;
+
+ // one more reconnect to get to the closing
+ case 2:
+ assert_equals(source.readyState, source.CONNECTING, "last reconnecting readyState");
+ count++;
+ break;
+
+ // close
+ case 3:
+ assert_equals(source.readyState, source.CLOSED, "closed readyState");
+
+ // give some time for errors to hit us
+ setTimeout(this.step_func(function() { this.done(); }), 100);
+ break;
+
+ default:
+ assert_unreached("Error handler with msg count " + count);
+ }
+
+ });
+
+ source.onmessage = this.step_func(function(e) {
+ switch(count) {
+ case 0:
+ assert_true(!reconnected, "no error event run");
+ assert_equals(e.data, "opened", "data");
+ break;
+
+ case 1:
+ assert_true(reconnected, "have reconnected");
+ assert_equals(e.data, "reconnected", "data");
+ break;
+
+ default:
+ assert_unreached("Dunno what to do with message number " + count);
+ }
+
+ count++;
+ });
+
+ });
+
+ </script>
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/eventsource/eventsource-constructor-document-domain.htm b/tests/wpt/web-platform-tests/eventsource/eventsource-constructor-document-domain.htm
new file mode 100644
index 00000000000..8fd7420baff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/eventsource-constructor-document-domain.htm
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>EventSource: document.domain</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+ document.domain = document.domain
+ source = new EventSource("resources/message.py")
+ source.onopen = function(e) {
+ test.step(function() {
+ assert_equals(source.readyState, source.OPEN)
+ assert_false(e.hasOwnProperty('data'))
+ assert_false(e.bubbles)
+ assert_false(e.cancelable)
+ this.close()
+ }, this)
+ test.done()
+ }
+ })
+ </script>
+ <!-- Apart from document.domain equivalent to the onopen test. -->
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/eventsource/eventsource-constructor-non-same-origin.htm b/tests/wpt/web-platform-tests/eventsource/eventsource-constructor-non-same-origin.htm
new file mode 100644
index 00000000000..dd4ab84a52a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/eventsource-constructor-non-same-origin.htm
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>EventSource: constructor (act as if there is a network error)</title>
+ <meta name=timeout content=long>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ function fetchFail(url) {
+ var test = async_test(document.title + " (" + url + ")", { timeout: 20000 })
+ test.step(function() {
+ var source = new EventSource(url)
+ source.onerror = function(e) {
+ test.step(function() {
+ assert_equals(source.readyState, source.CLOSED)
+ assert_false(e.hasOwnProperty('data'))
+ })
+ test.done()
+ }
+ })
+ }
+ fetchFail("http://example.not/")
+ fetchFail("https://example.not/test")
+ fetchFail("ftp://example.not/")
+ fetchFail("about:blank")
+ fetchFail("mailto:whatwg@awesome.example")
+ fetchFail("javascript:alert('FAIL')")
+ </script>
+ <!-- This tests "fails the connection" as well as making sure a simple
+ event is dispatched and not a MessageEvent -->
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/eventsource/eventsource-constructor-stringify.htm b/tests/wpt/web-platform-tests/eventsource/eventsource-constructor-stringify.htm
new file mode 100644
index 00000000000..162fa342dc2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/eventsource-constructor-stringify.htm
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>EventSource: stringify argument</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ async_test(function (test) {
+ test.step(function() {
+ var source = new EventSource({toString:function(){return "resources/message.py";}})
+ source.onopen = function(e) {
+ test.step(function() {
+ assert_false(e.hasOwnProperty('data'))
+ source.close()
+ test.done()
+ })
+ }
+ });
+ }, document.title + ', object');
+
+ test(function(){
+ var source = new EventSource(1);
+ assert_regexp_match(source.url, /\/1$/);
+ }, document.title + ', 1');
+ test(function(){
+ var source = new EventSource(null);
+ assert_regexp_match(source.url, /\/null$/);
+ }, document.title + ', null');
+ test(function(){
+ var source = new EventSource(undefined);
+ assert_regexp_match(source.url, /\/undefined$/);
+ }, document.title + ', undefined');
+ </script>
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/eventsource/eventsource-constructor-url-bogus.htm b/tests/wpt/web-platform-tests/eventsource/eventsource-constructor-url-bogus.htm
new file mode 100644
index 00000000000..8e769ed712c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/eventsource-constructor-url-bogus.htm
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>EventSource: constructor (invalid URL)</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ test(function() {
+ assert_throws("SyntaxError", function() { new EventSource("http://this is invalid/") })
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/eventsource/eventsource-constructor-url-multi-window.htm b/tests/wpt/web-platform-tests/eventsource/eventsource-constructor-url-multi-window.htm
new file mode 100644
index 00000000000..99fecb972c0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/eventsource-constructor-url-multi-window.htm
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>EventSource: resolving URLs</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ function init() {
+ test.step(function() {
+ source = new self[0].EventSource("message.py")
+ source.onopen = function(e) {
+ test.step(function() {
+ assert_equals(source.readyState, source.OPEN)
+ assert_false(e.hasOwnProperty('data'))
+ assert_false(e.bubbles)
+ assert_false(e.cancelable)
+ this.close()
+ test.done()
+ }, this)
+ }
+ source.onerror = function(e) {
+ test.step(function() {
+ assert_unreached()
+ source.close()
+ test.done()
+ })
+ }
+ })
+ }
+ </script>
+ <iframe src="resources/init.htm"></iframe>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/eventsource/eventsource-cross-origin.htm b/tests/wpt/web-platform-tests/eventsource/eventsource-cross-origin.htm
new file mode 100644
index 00000000000..b753bad7d98
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/eventsource-cross-origin.htm
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>EventSource: cross-origin</title>
+ <meta name=author title="Odin Hørthe Omdal" href="mailto:odiho@opera.com">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var crossdomain = location.href
+ .replace('://', '://www2.')
+ .replace(/\/[^\/]*$/, '/')
+
+ function doCORS(url, title) {
+ async_test(document.title + " " + title).step(function() {
+ var source = new EventSource(url, { withCredentials: true })
+ source.onmessage = this.step_func(function(e) {
+ assert_equals(e.data, "data")
+ source.close()
+ this.done()
+ })
+ })
+ }
+
+ doCORS(crossdomain + "resources/cors.py?run=message",
+ "basic use")
+ doCORS(crossdomain + "resources/cors.py?run=redirect&location=/eventsource/resources/cors.py?run=message",
+ "redirect use")
+ doCORS(crossdomain + "resources/cors.py?run=status-reconnect&status=200",
+ "redirect use recon")
+
+ function failCORS(url, title) {
+ async_test(document.title + " " + title).step(function() {
+ var source = new EventSource(url)
+ source.onerror = this.step_func(function(e) {
+ assert_equals(source.readyState, source.CLOSED, 'readyState')
+ assert_false(e.hasOwnProperty('data'))
+ source.close()
+ this.done()
+ })
+
+ /* Shouldn't happen */
+ source.onmessage = this.step_func(function(e) {
+ assert_unreached("shouldn't fire message event")
+ })
+ source.onopen = this.step_func(function(e) {
+ assert_unreached("shouldn't fire open event")
+ })
+ })
+ }
+
+ failCORS(crossdomain + "resources/cors.py?run=message&origin=http://example.org",
+ "allow-origin: http://example.org should fail")
+ failCORS(crossdomain + "resources/cors.py?run=message&origin=",
+ "allow-origin:'' should fail")
+ failCORS(crossdomain + "resources/message.py",
+ "No allow-origin should fail")
+ </script>
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/eventsource/eventsource-eventtarget.htm b/tests/wpt/web-platform-tests/eventsource/eventsource-eventtarget.htm
new file mode 100644
index 00000000000..6e600fc7b78
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/eventsource-eventtarget.htm
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>EventSource: addEventListener()</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+ var source = new EventSource("resources/message.py")
+ source.addEventListener("message", listener, false)
+ })
+ function listener(e) {
+ test.step(function() {
+ assert_equals("data", e.data)
+ this.close()
+ }, this)
+ test.done()
+ }
+ </script>
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/eventsource/eventsource-onmessage.htm b/tests/wpt/web-platform-tests/eventsource/eventsource-onmessage.htm
new file mode 100644
index 00000000000..b683ebc8517
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/eventsource-onmessage.htm
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>EventSource: onmessage</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+ var source = new EventSource("resources/message.py")
+ source.onmessage = function(e) {
+ test.step(function() {
+ assert_equals("data", e.data)
+ source.close()
+ })
+ test.done()
+ }
+ })
+ </script>
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/eventsource/eventsource-onopen.htm b/tests/wpt/web-platform-tests/eventsource/eventsource-onopen.htm
new file mode 100644
index 00000000000..1c9bfe03c86
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/eventsource-onopen.htm
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>EventSource: onopen (announcing the connection)</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+ source = new EventSource("resources/message.py")
+ source.onopen = function(e) {
+ test.step(function() {
+ assert_equals(source.readyState, source.OPEN)
+ assert_false(e.hasOwnProperty('data'))
+ assert_false(e.bubbles)
+ assert_false(e.cancelable)
+ this.close()
+ }, this)
+ test.done()
+ }
+ })
+ </script>
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/eventsource/eventsource-prototype.htm b/tests/wpt/web-platform-tests/eventsource/eventsource-prototype.htm
new file mode 100644
index 00000000000..38f63eb5f00
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/eventsource-prototype.htm
@@ -0,0 +1,21 @@
+<!DoCtYpE hTMl>
+<html>
+ <heAd>
+ <title>EventSource: prototype et al</tiTle>
+ <scrIpt src="/resources/testharness.js"></scripT>
+ <scriPt src="/resources/testharnessreport.js"></Script>
+ </heaD>
+ <boDy>
+ <diV iD="log"></Div>
+ <sCript>
+ test(function() {
+ EventSource.prototype.ReturnTrue = function() { return true }
+ var source = new EventSource("resources/message.py")
+ assert_true(source.ReturnTrue())
+ assert_exists(window, "EventSource")
+ source.close()
+ })
+ </scrIpt>
+ </bOdy>
+</htMl>
+
diff --git a/tests/wpt/web-platform-tests/eventsource/eventsource-reconnect.htm b/tests/wpt/web-platform-tests/eventsource/eventsource-reconnect.htm
new file mode 100644
index 00000000000..a23885f08bf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/eventsource-reconnect.htm
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>EventSource: reconnection</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ function doReconn(url, title) {
+ var test = async_test(document.title + " " + title)
+ test.step(function() {
+ var source = new EventSource(url)
+ source.onmessage = test.step_func(function(e) {
+ assert_equals(e.data, "data")
+ source.close()
+ test.done()
+ })
+ })
+ }
+
+ doReconn("resources/status-reconnect.py?status=200",
+ "200")
+
+
+ var t = async_test(document.title + ", test reconnection events", { timeout: 9000 });
+ t.step(function() {
+ var opened = false, reconnected = false,
+ source = new EventSource("resources/status-reconnect.py?status=200&ok_first&id=2");
+
+ source.onerror = t.step_func(function(e) {
+ assert_equals(e.type, 'error');
+ assert_equals(source.readyState, source.CONNECTING, "readyState");
+ assert_true(opened, "connection is opened earlier");
+
+ reconnected = true;
+ });
+
+ source.onmessage = t.step_func(function(e) {
+ if (!opened) {
+ opened = true;
+ assert_false(reconnected, "have reconnected before first message");
+ assert_equals(e.data, "ok");
+ }
+ else {
+ assert_true(reconnected, "Got reconnection event");
+ assert_equals(e.data, "data");
+ source.close()
+ t.done()
+ }
+ });
+ });
+
+ </script>
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/eventsource/eventsource-request-cancellation.htm b/tests/wpt/web-platform-tests/eventsource/eventsource-request-cancellation.htm
new file mode 100644
index 00000000000..5fb2320e19b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/eventsource-request-cancellation.htm
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>EventSource: request cancellation</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test(null, {timeout: 5000});
+ var url = "resources/message.py?sleep=1000&message=" + encodeURIComponent("retry:1000\ndata:abc\n\n");
+ var es = new EventSource(url);
+ var lastEventTime = 0;
+ var lastEventType = "";
+ var readyStateAtLastEvent = -1;
+ es.onmessage =
+ es.onerror =
+ es.onopen = function (event) {
+ lastEventTime = (new Date()).getTime();
+ lastEventType = event.type;
+ readyStateAtLastEvent = es.readyState;
+ };
+ setTimeout(function () {
+ if (typeof window.stop === "function") {
+ window.stop();
+ }
+ }, 100);
+ setTimeout(function () {
+ test.step(function () {
+ var isActive = ((new Date()).getTime() - lastEventTime) < 2500;
+ if (es.readyState === EventSource.CLOSED) {
+ assert_true(!isActive, "In case EventSource was stopped, it should not be active");
+ assert_equals(lastEventType, "error", "In case EventSource was stopped, the last event should be an error event");
+ assert_equals(readyStateAtLastEvent, EventSource.CLOSED, "In case EventSource was stopped, readyState at last event should be closed");
+ } else {
+ assert_true(isActive, "EventSource is active, but readyState is not EventSource.CLOSED.");
+ }
+ });
+ es.close();
+ test.done();
+ }, 4000);
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/eventsource/eventsource-url.htm b/tests/wpt/web-platform-tests/eventsource/eventsource-url.htm
new file mode 100644
index 00000000000..8b9262bfeff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/eventsource-url.htm
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>EventSource: url</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ test(function() {
+ var url = "resources/message.py",
+ source = new EventSource(url)
+ assert_equals(source.url.substr(-(url.length)), url)
+ source.close()
+ })
+ </script>
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/eventsource/format-bom-2.htm b/tests/wpt/web-platform-tests/eventsource/format-bom-2.htm
new file mode 100644
index 00000000000..6f267a05a38
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/format-bom-2.htm
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>EventSource: Double BOM</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test(),
+ hasbeenone = false,
+ hasbeentwo = false
+ test.step(function() {
+ var source = new EventSource("resources/message.py?message=%EF%BB%BF%EF%BB%BFdata%3A1%0A%0Adata%3A2%0A%0Adata%3A3")
+ source.addEventListener("message", listener, false)
+ })
+ function listener(e) {
+ test.step(function() {
+ if(e.data == "1")
+ hasbeenone = true
+ if(e.data == "2")
+ hasbeentwo = true
+ if(e.data == "3") {
+ assert_false(hasbeenone)
+ assert_true(hasbeentwo)
+ this.close()
+ test.done()
+ }
+ }, this)
+ }
+ </script>
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/eventsource/format-bom.htm b/tests/wpt/web-platform-tests/eventsource/format-bom.htm
new file mode 100644
index 00000000000..921602278be
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/format-bom.htm
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>EventSource: BOM</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test(),
+ hasbeenone = false,
+ hasbeentwo = false
+ test.step(function() {
+ var source = new EventSource("resources/message.py?message=%EF%BB%BFdata%3A1%0A%0A%EF%BB%BFdata%3A2%0A%0Adata%3A3")
+ source.addEventListener("message", listener, false)
+ })
+ function listener(e) {
+ test.step(function() {
+ if(e.data == "1")
+ hasbeenone = true
+ if(e.data == "2")
+ hasbeentwo = true
+ if(e.data == "3") {
+ assert_true(hasbeenone)
+ assert_false(hasbeentwo)
+ this.close()
+ test.done()
+ }
+ }, this)
+ }
+ </script>
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/eventsource/format-comments.htm b/tests/wpt/web-platform-tests/eventsource/format-comments.htm
new file mode 100644
index 00000000000..fde360db002
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/format-comments.htm
@@ -0,0 +1,27 @@
+<!doctype html>
+<html>
+ <head>
+ <title>EventSource: comment fest</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+ var longstring = (new Array(2*1024+1)).join("x"), // cannot make the string too long; causes timeout
+ message = encodeURI("data:1\r:\0\n:\r\ndata:2\n:" + longstring + "\rdata:3\n:data:fail\r:" + longstring + "\ndata:4\n"),
+ source = new EventSource("resources/message.py?message=" + message + "&newline=none")
+ source.onmessage = function(e) {
+ test.step(function() {
+ assert_equals("1\n2\n3\n4", e.data)
+ source.close()
+ })
+ test.done()
+ }
+ })
+ </script>
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/eventsource/format-data-before-final-empty-line.htm b/tests/wpt/web-platform-tests/eventsource/format-data-before-final-empty-line.htm
new file mode 100644
index 00000000000..e429d7f264f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/format-data-before-final-empty-line.htm
@@ -0,0 +1,29 @@
+<!doctype html>
+<html>
+ <head>
+ <title>EventSource: a data before final empty line</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+ var source = new EventSource("resources/message.py?newline=none&message=" + encodeURIComponent("retry:1000\ndata:test1\n\nid:test\ndata:test2"))
+ var count = 0;
+ source.onmessage = function(e) {
+ if (++count === 2) {
+ test.step(function() {
+ assert_equals(e.lastEventId, "", "lastEventId")
+ assert_equals(e.data, "test1", "data")
+ source.close()
+ })
+ test.done()
+ }
+ }
+ })
+ </script>
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/eventsource/format-field-data.htm b/tests/wpt/web-platform-tests/eventsource/format-field-data.htm
new file mode 100644
index 00000000000..a7313556811
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/format-field-data.htm
@@ -0,0 +1,34 @@
+<!doctype html>
+<html>
+ <head>
+ <title>EventSource: data field parsing</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+ var source = new EventSource("resources/message.py?message=data%3A%0A%0Adata%0Adata%0A%0Adata%3Atest"),
+ counter = 0
+ source.onmessage = function(e) {
+ test.step(function() {
+ if(counter == 0) {
+ assert_equals("", e.data)
+ } else if(counter == 1) {
+ assert_equals("\n", e.data)
+ } else if(counter == 2) {
+ assert_equals("test", e.data)
+ source.close()
+ test.done()
+ } else {
+ assert_unreached()
+ }
+ counter++
+ })
+ }
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/eventsource/format-field-event-empty.htm b/tests/wpt/web-platform-tests/eventsource/format-field-event-empty.htm
new file mode 100644
index 00000000000..20a6d6d9f9b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/format-field-event-empty.htm
@@ -0,0 +1,25 @@
+<!doctype html>
+<html>
+ <head>
+ <title>EventSource: empty "event" field</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+ var source = new EventSource("resources/message.py?message=event%3A%20%0Adata%3Adata")
+ source.onmessage = function(e) {
+ test.step(function() {
+ assert_equals("data", e.data)
+ this.close()
+ }, this)
+ test.done()
+ }
+ })
+ </script>
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/eventsource/format-field-event.htm b/tests/wpt/web-platform-tests/eventsource/format-field-event.htm
new file mode 100644
index 00000000000..3c3267f7c88
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/format-field-event.htm
@@ -0,0 +1,27 @@
+<!doctype html>
+<html>
+ <head>
+ <title>EventSource: custom event name</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test(),
+ dispatchedtest = false
+ test.step(function() {
+ var source = new EventSource("resources/message.py?message=event%3Atest%0Adata%3Ax%0A%0Adata%3Ax")
+ source.addEventListener("test", function() { test.step(function() { dispatchedtest = true }) }, false)
+ source.onmessage = function() {
+ test.step(function() {
+ assert_true(dispatchedtest)
+ this.close()
+ }, this)
+ test.done()
+ }
+ })
+ </script>
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/eventsource/format-field-id-2.htm b/tests/wpt/web-platform-tests/eventsource/format-field-id-2.htm
new file mode 100644
index 00000000000..ac521fc134e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/format-field-id-2.htm
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>EventSource: Last-Event-ID (2)</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+ var source = new EventSource("resources/last-event-id.py"),
+ counter = 0
+ source.onmessage = function(e) {
+ test.step(function() {
+ if(e.data == "hello" && counter == 0) {
+ counter++
+ assert_equals(e.lastEventId, "…")
+ } else if(counter == 1) {
+ counter++
+ assert_equals("…", e.data)
+ assert_equals("…", e.lastEventId)
+ } else if(counter == 2) {
+ counter++
+ assert_equals("…", e.data)
+ assert_equals("…", e.lastEventId)
+ source.close()
+ test.done()
+ } else
+ assert_unreached()
+ })
+ }
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/eventsource/format-field-id.htm b/tests/wpt/web-platform-tests/eventsource/format-field-id.htm
new file mode 100644
index 00000000000..19ada954c3b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/format-field-id.htm
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>EventSource: Last-Event-ID</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+ var source = new EventSource("resources/last-event-id.py"),
+ seenhello = false
+ source.onmessage = function(e) {
+ test.step(function() {
+ if(e.data == "hello" && !seenhello) {
+ seenhello = true
+ assert_equals(e.lastEventId, "…")
+ } else if(seenhello) {
+ assert_equals("…", e.data)
+ assert_equals("…", e.lastEventId)
+ source.close()
+ test.done()
+ } else
+ assert_unreached()
+ })
+ }
+ })
+ </script>
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/eventsource/format-field-parsing.htm b/tests/wpt/web-platform-tests/eventsource/format-field-parsing.htm
new file mode 100644
index 00000000000..da2217620b2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/format-field-parsing.htm
@@ -0,0 +1,26 @@
+<!doctype html>
+<html>
+ <head>
+ <title>EventSource: field parsing</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+ var message = encodeURI("data:\0\ndata: 2\rData:1\ndata\0:2\ndata:1\r\0data:4\nda-ta:3\rdata_5\ndata:3\rdata:\r\n data:32\ndata:4\n"),
+ source = new EventSource("resources/message.py?message=" + message + "&newline=none")
+ source.onmessage = function(e) {
+ test.step(function() {
+ assert_equals(e.data, "\0\n 2\n1\n3\n\n4")
+ source.close()
+ })
+ test.done()
+ }
+ })
+ </script>
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/eventsource/format-field-retry-bogus.htm b/tests/wpt/web-platform-tests/eventsource/format-field-retry-bogus.htm
new file mode 100644
index 00000000000..0cdf9b4f186
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/format-field-retry-bogus.htm
@@ -0,0 +1,31 @@
+<!doctype html>
+<html>
+ <head>
+ <title>EventSource: "retry" field (bogus)</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test(document.title)
+ test.step(function() {
+ var timeoutms = 3000,
+ source = new EventSource("resources/message.py?message=retry%3A3000%0Aretry%3A1000x%0Adata%3Ax"),
+ opened = 0
+ source.onopen = function() {
+ test.step(function() {
+ if(opened == 0)
+ opened = new Date().getTime()
+ else {
+ var diff = (new Date().getTime()) - opened
+ assert_true(Math.abs(1 - diff / timeoutms) < 0.25) // allow 25% difference
+ this.close();
+ test.done()
+ }
+ }, this)
+ }
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/eventsource/format-field-retry-empty.htm b/tests/wpt/web-platform-tests/eventsource/format-field-retry-empty.htm
new file mode 100644
index 00000000000..27574861814
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/format-field-retry-empty.htm
@@ -0,0 +1,25 @@
+<!doctype html>
+<html>
+ <head>
+ <title>EventSource: empty retry field</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+ var source = new EventSource("resources/message.py?message=retry%0Adata%3Atest")
+ source.onmessage = function(e) {
+ test.step(function() {
+ assert_equals("test", e.data)
+ source.close()
+ })
+ test.done()
+ }
+ })
+ </script>
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/eventsource/format-field-retry.htm b/tests/wpt/web-platform-tests/eventsource/format-field-retry.htm
new file mode 100644
index 00000000000..133794f6290
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/format-field-retry.htm
@@ -0,0 +1,33 @@
+<!doctype html>
+<html>
+ <head>
+ <title>EventSource: "retry" field</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test(document.title);
+ test.step(function() {
+ var timeoutms = 3000,
+ timeoutstr = "03000", // 1536 in octal, but should be 3000
+ source = new EventSource("resources/message.py?message=retry%3A" + timeoutstr + "%0Adata%3Ax"),
+ opened = 0
+ source.onopen = function() {
+ test.step(function() {
+ if(opened == 0)
+ opened = new Date().getTime()
+ else {
+ var diff = (new Date().getTime()) - opened
+ assert_true(Math.abs(1 - diff / timeoutms) < 0.25) // allow 25% difference
+ this.close();
+ test.done()
+ }
+ }, this)
+ }
+ })
+ </script>
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/eventsource/format-field-unknown.htm b/tests/wpt/web-platform-tests/eventsource/format-field-unknown.htm
new file mode 100644
index 00000000000..3b6efd5420e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/format-field-unknown.htm
@@ -0,0 +1,25 @@
+<!doctype html>
+<html>
+ <head>
+ <title>EventSource: unknown fields and parsing fun</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+ var source = new EventSource("resources/message.py?message=data%3Atest%0A%20data%0Adata%0Afoobar%3Axxx%0Ajustsometext%0A%3Athisisacommentyay%0Adata%3Atest")
+ source.onmessage = function(e) {
+ test.step(function() {
+ assert_equals("test\n\ntest", e.data)
+ source.close()
+ })
+ test.done()
+ }
+ })
+ </script>
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/eventsource/format-leading-space.htm b/tests/wpt/web-platform-tests/eventsource/format-leading-space.htm
new file mode 100644
index 00000000000..b70ba89c253
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/format-leading-space.htm
@@ -0,0 +1,26 @@
+<!doctype html>
+<html>
+ <head>
+ <title>EventSource: leading space</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+ var source = new EventSource("resources/message.py?message=data%3A%09test%0Ddata%3A%20%0Adata%3Atest")
+ source.onmessage = function(e) {
+ test.step(function() {
+ assert_equals("\ttest\n\ntest", e.data)
+ source.close()
+ })
+ test.done()
+ }
+ })
+ </script>
+ <!-- also used a CR as newline once -->
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/eventsource/format-mime-bogus.htm b/tests/wpt/web-platform-tests/eventsource/format-mime-bogus.htm
new file mode 100644
index 00000000000..caf9cb4a9a7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/format-mime-bogus.htm
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>EventSource: bogus MIME type</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+ var source = new EventSource("resources/message.py?mime=x%20bogus")
+ source.onmessage = function() {
+ test.step(function() {
+ assert_unreached()
+ source.close()
+ })
+ test.done()
+ }
+ source.onerror = function(e) {
+ test.step(function() {
+ assert_equals(this.readyState, this.CLOSED)
+ assert_false(e.hasOwnProperty('data'))
+ assert_false(e.bubbles)
+ assert_false(e.cancelable)
+ this.close()
+ }, this)
+ test.done()
+ }
+ })
+ </script>
+ <!-- This tests "fails the connection" as well as making sure a simple
+ event is dispatched and not a MessageEvent -->
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/eventsource/format-mime-trailing-semicolon.htm b/tests/wpt/web-platform-tests/eventsource/format-mime-trailing-semicolon.htm
new file mode 100644
index 00000000000..6bcac838288
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/format-mime-trailing-semicolon.htm
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>EventSource: MIME type with trailing ;</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+ var source = new EventSource("resources/message.py?mime=text/event-stream%3B")
+ source.onopen = function() {
+ test.step(function() {
+ assert_equals(source.readyState, source.OPEN)
+ source.close()
+ })
+ test.done()
+ }
+ source.onerror = function() {
+ test.step(function() {
+ assert_unreached()
+ source.close()
+ })
+ test.done()
+ }
+ })
+ </script>
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/eventsource/format-mime-valid-bogus.htm b/tests/wpt/web-platform-tests/eventsource/format-mime-valid-bogus.htm
new file mode 100644
index 00000000000..211f841a60b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/format-mime-valid-bogus.htm
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>EventSource: incorrect valid MIME type</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+ var source = new EventSource("resources/message.py?mime=text/x-bogus")
+ source.onmessage = function() {
+ test.step(function() {
+ assert_unreached()
+ source.close()
+ })
+ test.done()
+ }
+ source.onerror = function(e) {
+ test.step(function() {
+ assert_equals(source.readyState, source.CLOSED)
+ assert_false(e.hasOwnProperty('data'))
+ assert_false(e.bubbles)
+ assert_false(e.cancelable)
+ })
+ test.done()
+ }
+ })
+ </script>
+ <!-- This tests "fails the connection" as well as making sure a simple
+ event is dispatched and not a MessageEvent -->
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/eventsource/format-newlines.htm b/tests/wpt/web-platform-tests/eventsource/format-newlines.htm
new file mode 100644
index 00000000000..87d6a569e62
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/format-newlines.htm
@@ -0,0 +1,25 @@
+<!doctype html>
+<html>
+ <head>
+ <title>EventSource: newline fest</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+ var source = new EventSource("resources/message.py?message=data%3Atest%0D%0Adata%0Adata%3Atest%0D%0A%0D&newline=none")
+ source.onmessage = function(e) {
+ test.step(function() {
+ assert_equals("test\n\ntest", e.data)
+ source.close()
+ })
+ test.done()
+ }
+ })
+ </script>
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/eventsource/format-null-character.html b/tests/wpt/web-platform-tests/eventsource/format-null-character.html
new file mode 100644
index 00000000000..0640530d73b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/format-null-character.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>EventSource: null character in response</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+ var source = new EventSource("resources/message.py?message=data%3A%00%0A%0A")
+ source.onmessage = function(e) {
+ test.step(function() {
+ assert_equals("\x00", e.data)
+ source.close()
+ }, this)
+ test.done()
+ }
+ source.onerror = function() {
+ test.step(function() { assert_unreached() })
+ test.done()
+ }
+ })
+ </script>
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/eventsource/format-utf-8.htm b/tests/wpt/web-platform-tests/eventsource/format-utf-8.htm
new file mode 100644
index 00000000000..d7858a16c06
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/format-utf-8.htm
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>EventSource: always UTF-8</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ async_test().step(function() {
+ var source = new EventSource("resources/message.py?mime=text/event-stream;charset=windows-1252&message=data%3Aok%E2%80%A6")
+ source.onmessage = this.step_func(function(e) {
+ assert_equals('ok…', e.data, 'decoded data')
+ source.close()
+ this.done()
+ })
+ source.onerror = this.step_func(function() {
+ assert_unreached("Got error event")
+ })
+ })
+ </script>
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/eventsource/interfaces.html b/tests/wpt/web-platform-tests/eventsource/interfaces.html
new file mode 100644
index 00000000000..d41a80d3903
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/interfaces.html
@@ -0,0 +1,58 @@
+<!doctype html>
+<title>EventSource IDL tests</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=/resources/WebIDLParser.js></script>
+<script src=/resources/idlharness.js></script>
+
+<h1>EventSource IDL tests</h1>
+<div id=log></div>
+
+<script type=text/plain>
+[Constructor(DOMString url, optional EventSourceInit eventSourceInitDict)]
+interface EventSource : EventTarget {
+ readonly attribute DOMString url;
+ readonly attribute boolean withCredentials;
+
+ // ready state
+ const unsigned short CONNECTING = 0;
+ const unsigned short OPEN = 1;
+ const unsigned short CLOSED = 2;
+ readonly attribute unsigned short readyState;
+
+ // networking
+ attribute EventHandler onopen;
+ attribute EventHandler onmessage;
+ attribute EventHandler onerror;
+ void close();
+};
+
+dictionary EventSourceInit {
+ boolean withCredentials = false;
+};
+
+[TreatNonCallableAsNull]
+callback EventHandlerNonNull = any (Event event);
+typedef EventHandlerNonNull? EventHandler;
+</script>
+<script>
+"use strict";
+var idlArray;
+setup(function() {
+ idlArray = new IdlArray();
+ [].forEach.call(document.querySelectorAll("script[type=text\\/plain]"), function(node) {
+ if (node.className == "untested") {
+ idlArray.add_untested_idls(node.textContent);
+ } else {
+ idlArray.add_idls(node.textContent);
+ }
+ });
+}, {explicit_done:true});
+window.onload = function() {
+ idlArray.add_objects({
+ EventSource: ['new EventSource("http://foo")'],
+ });
+ idlArray.test();
+ done();
+};
+</script>
diff --git a/tests/wpt/web-platform-tests/eventsource/request-accept.htm b/tests/wpt/web-platform-tests/eventsource/request-accept.htm
new file mode 100644
index 00000000000..6032cb6ff35
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/request-accept.htm
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>EventSource: Accept header</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+ var source = new EventSource("resources/accept.event_stream?pipe=sub")
+ source.onmessage = function(e) {
+ test.step(function() {
+ assert_equals(e.data, "text/event-stream")
+ this.close()
+ }, this)
+ test.done()
+ }
+ })
+ </script>
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/eventsource/request-cache-control.htm b/tests/wpt/web-platform-tests/eventsource/request-cache-control.htm
new file mode 100644
index 00000000000..b3965929257
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/request-cache-control.htm
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>EventSource: Cache-Control</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var crossdomain = location.href
+ .replace('://', '://www2.')
+ .replace(/\/[^\/]*$/, '/')
+
+ // running it twice to check whether it stays consistent
+ function cacheTest(runAgain, url) {
+ var test = async_test()
+ test.step(function() {
+ var source = new EventSource(url)
+ source.onmessage = function(e) {
+ test.step(function() {
+ assert_equals(e.data, "no-cache")
+ this.close()
+ if(runAgain)
+ cacheTest(false, url) // this nests tests
+ }, this)
+ test.done()
+ }
+ })
+ }
+
+ cacheTest(true, "resources/cache-control.event_stream?pipe=sub")
+ cacheTest(true, crossdomain + "resources/cors.py?run=cache-control")
+ </script>
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/eventsource/request-credentials.htm b/tests/wpt/web-platform-tests/eventsource/request-credentials.htm
new file mode 100644
index 00000000000..c3c178a7791
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/request-credentials.htm
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>EventSource: credentials</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var crossdomain = location.href
+ .replace('://', '://www2.')
+ .replace(/\/[^\/]*$/, '/')
+
+ function testCookie(desc, success, props, id) {
+ var test = async_test(document.title + ': credentials ' + desc)
+ test.step(function() {
+ var source = new EventSource(crossdomain + "resources/cors-cookie.py?ident=" + id, props)
+
+ source.onmessage = test.step_func(function(e) {
+ if(e.data.indexOf("first") == 0) {
+ assert_equals(e.data, "first NO_COOKIE", "cookie status")
+ }
+ else if(e.data.indexOf("second") == 0) {
+ if (success)
+ assert_equals(e.data, "second COOKIE", "cookie status")
+ else
+ assert_equals(e.data, "second NO_COOKIE", "cookie status")
+
+ source.close()
+ test.done()
+ }
+ else {
+ assert_unreached("unrecognized data returned: " + e.data)
+ source.close()
+ test.done()
+ }
+ })
+ })
+ }
+
+ testCookie('enabled', true, { withCredentials: true }, '1_' + new Date().getTime())
+ testCookie('disabled', false, { withCredentials: false }, '2_' + new Date().getTime())
+ testCookie('default', false, { }, '3_' + new Date().getTime())
+
+ </script>
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/eventsource/request-redirect.htm b/tests/wpt/web-platform-tests/eventsource/request-redirect.htm
new file mode 100644
index 00000000000..794c878feaa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/request-redirect.htm
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>EventSource: redirect</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ function redirectTest(status) {
+ var test = async_test(document.title + " (" + status +")")
+ test.step(function() {
+ var source = new EventSource("/common/redirect.py?location=/eventsource/resources/message.py&status=" + status)
+ source.onopen = function() {
+ test.step(function() {
+ assert_equals(this.readyState, this.OPEN)
+ this.close()
+ }, this)
+ test.done()
+ }
+ source.onerror = function() {
+ test.step(function() { assert_unreached() })
+ test.done()
+ }
+ })
+ }
+
+ redirectTest("301")
+ redirectTest("302")
+ redirectTest("303")
+ redirectTest("307")
+ </script>
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/eventsource/request-status-error.htm b/tests/wpt/web-platform-tests/eventsource/request-status-error.htm
new file mode 100644
index 00000000000..d881a4ddd27
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/request-status-error.htm
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>EventSource: incorrect HTTP status code</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ function statusTest(status) {
+ var test = async_test(document.title + " (" + status +")")
+ test.step(function() {
+ var source = new EventSource("resources/status-error.py?status=" + status)
+ source.onmessage = function() {
+ test.step(function() {
+ assert_unreached()
+ })
+ test.done()
+ }
+ source.onerror = function() {
+ test.step(function() {
+ assert_equals(this.readyState, this.CLOSED)
+ }, this)
+ test.done()
+ }
+ })
+ }
+ statusTest("204")
+ statusTest("205")
+ statusTest("210")
+ statusTest("299")
+ statusTest("404")
+ statusTest("410")
+ statusTest("503")
+ </script>
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/eventsource/resources/accept.event_stream b/tests/wpt/web-platform-tests/eventsource/resources/accept.event_stream
new file mode 100644
index 00000000000..24da5482678
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/resources/accept.event_stream
@@ -0,0 +1,2 @@
+data: {{headers[accept]}}
+
diff --git a/tests/wpt/web-platform-tests/eventsource/resources/cache-control.event_stream b/tests/wpt/web-platform-tests/eventsource/resources/cache-control.event_stream
new file mode 100644
index 00000000000..aa9f2d6c090
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/resources/cache-control.event_stream
@@ -0,0 +1,2 @@
+data: {{headers[cache-control]}}
+
diff --git a/tests/wpt/web-platform-tests/eventsource/resources/cors-cookie.py b/tests/wpt/web-platform-tests/eventsource/resources/cors-cookie.py
new file mode 100644
index 00000000000..7deaff498d7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/resources/cors-cookie.py
@@ -0,0 +1,31 @@
+from datetime import datetime
+
+def main(request, response):
+ last_event_id = request.headers.get("Last-Event-Id", "")
+ ident = request.GET.first('ident', "test")
+ cookie = "COOKIE" if ident in request.cookies else "NO_COOKIE"
+ origin = request.GET.first('origin', request.headers["origin"])
+ credentials = request.GET.first('credentials', 'true')
+
+ headers = []
+
+ if origin != 'none':
+ headers.append(("Access-Control-Allow-Origin", origin));
+
+ if credentials != 'none':
+ headers.append(("Access-Control-Allow-Credentials", credentials));
+
+ if last_event_id == '':
+ headers.append(("Content-Type", "text/event-stream"))
+ response.set_cookie(ident, "COOKIE")
+ data = "id: 1\nretry: 200\ndata: first %s\n\n" % cookie
+ elif last_event_id == '1':
+ headers.append(("Content-Type", "text/event-stream"))
+ long_long_time_ago = datetime.now().replace(year=2001, month=7, day=27)
+ response.set_cookie(ident, "COOKIE", expires=long_long_time_ago)
+ data = "id: 2\ndata: second %s\n\n" % cookie
+ else:
+ headers.append(("Content-Type", "stop"))
+ data = "data: " + last_event_id + cookie + "\n\n";
+
+ return headers, data
diff --git a/tests/wpt/web-platform-tests/eventsource/resources/cors.py b/tests/wpt/web-platform-tests/eventsource/resources/cors.py
new file mode 100644
index 00000000000..8be80523603
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/resources/cors.py
@@ -0,0 +1,34 @@
+import os
+from wptserve import pipes
+
+def run_other(request, response, path):
+ #This is a terrible hack
+ environ = {"__file__": path}
+ execfile(path, environ, environ)
+ rv = environ["main"](request, response)
+ return rv
+
+def main(request, response):
+ origin = request.GET.first("origin", request.headers["origin"])
+ credentials = request.GET.first("credentials", "true")
+
+ response.headers.update([("Access-Control-Allow-Origin", origin),
+ ("Access-Control-Allow-Credentials", credentials)])
+
+ handler = request.GET.first('run')
+ if handler in ["status-reconnect",
+ "message",
+ "redirect",
+ "cache-control"]:
+ if handler == "cache-control":
+ response.headers.set("Content-Type", "text/event-stream")
+ rv = open(os.path.join(request.doc_root, "eventsource", "resources", "cache-control.event_stream")).read()
+ response.content = rv
+ pipes.sub(request, response)
+ return
+ elif handler == "redirect":
+ return run_other(request, response, os.path.join(request.doc_root, "common", "redirect.py"))
+ else:
+ return run_other(request, response, os.path.join(os.path.split(__file__)[0], handler + ".py"))
+ else:
+ return
diff --git a/tests/wpt/web-platform-tests/eventsource/resources/init.htm b/tests/wpt/web-platform-tests/eventsource/resources/init.htm
new file mode 100644
index 00000000000..7c56d88800d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/resources/init.htm
@@ -0,0 +1,9 @@
+<!doctype html>
+<html>
+ <head>
+ <title>support init file</title>
+ </head>
+ <body>
+ <script> parent.init() </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/eventsource/resources/last-event-id.py b/tests/wpt/web-platform-tests/eventsource/resources/last-event-id.py
new file mode 100644
index 00000000000..4306fbaa3f1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/resources/last-event-id.py
@@ -0,0 +1,11 @@
+ # -*- coding: utf-8 -*-
+
+def main(request, response):
+ response.headers.set("Content-Type", "text/event-stream")
+ last_event_id = request.headers.get('Last-Event-ID', None)
+
+ if(last_event_id):
+ return "data: " + last_event_id + "\n\n"
+ else:
+ return "id: …\nretry: 200\ndata: hello\n\n"
+
diff --git a/tests/wpt/web-platform-tests/eventsource/resources/message.py b/tests/wpt/web-platform-tests/eventsource/resources/message.py
new file mode 100644
index 00000000000..6d04b1fbe40
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/resources/message.py
@@ -0,0 +1,14 @@
+import time
+
+def main(request, response):
+ mime = request.GET.first("mime", "text/event-stream")
+ message = request.GET.first("message", "data: data");
+ newline = "" if request.GET.first("newline", None) == "none" else "\n\n";
+ sleep = int(request.GET.first("sleep", "0"))
+
+ headers = [("Content-Type", mime)]
+ body = message + newline + "\n"
+ if sleep != 0:
+ time.sleep(sleep/1000)
+
+ return headers, body
diff --git a/tests/wpt/web-platform-tests/eventsource/resources/message2.py b/tests/wpt/web-platform-tests/eventsource/resources/message2.py
new file mode 100644
index 00000000000..ce339d927e3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/resources/message2.py
@@ -0,0 +1,35 @@
+import time
+
+def main(request, response):
+ response.headers.set('Content-Type', 'text/event-stream')
+ response.headers.set('Cache-Control', 'no-cache')
+
+ response.explicit_flush = True
+ response.write_status_headers()
+
+ while True:
+ response.writer.write("data:msg")
+ response.writer.write("\n")
+ response.writer.write("data: msg")
+ response.writer.write("\n\n")
+
+ response.writer.write(":")
+ response.writer.write("\n")
+
+ response.writer.write("falsefield:msg")
+ response.writer.write("\n\n")
+
+ response.writer.write("falsefield:msg")
+ response.writer.write("\n")
+
+ response.writer.write("Data:data")
+ response.writer.write("\n\n")
+
+ response.writer.write("data")
+ response.writer.write("\n\n")
+
+ response.writer.write("data:end")
+ response.writer.write("\n\n")
+
+ response.writer.flush()
+ time.sleep(2)
diff --git a/tests/wpt/web-platform-tests/eventsource/resources/reconnect-fail.py b/tests/wpt/web-platform-tests/eventsource/resources/reconnect-fail.py
new file mode 100644
index 00000000000..80a247d5974
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/resources/reconnect-fail.py
@@ -0,0 +1,24 @@
+def main(request, response):
+ name = "recon_fail_" + request.GET.first("id")
+
+ headers = [("Content-Type", "text/event-stream")]
+ cookie = request.cookies.first(name, None)
+ state = cookie.value if cookie is not None else None
+
+ if state == 'opened':
+ status = (200, "RECONNECT")
+ response.set_cookie(name, "reconnected");
+ body = "data: reconnected\n\n";
+
+ elif state == 'reconnected':
+ status = (204, "NO CONTENT (CLOSE)")
+ response.delete_cookie(name);
+ body = "data: closed\n\n" # Will never get through
+
+ else:
+ status = (200, "OPEN");
+ response.set_cookie(name, "opened");
+ body = "retry: 2\ndata: opened\n\n";
+
+ return status, headers, body
+
diff --git a/tests/wpt/web-platform-tests/eventsource/resources/status-error.py b/tests/wpt/web-platform-tests/eventsource/resources/status-error.py
new file mode 100644
index 00000000000..8aa230c724c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/resources/status-error.py
@@ -0,0 +1,4 @@
+def main(request, response):
+ status = (request.GET.first("status", "404"), "HAHAHAHA")
+ headers = [("Content-Type", "text/event-stream")]
+ return status, headers, "data: data\n\n"
diff --git a/tests/wpt/web-platform-tests/eventsource/resources/status-reconnect.py b/tests/wpt/web-platform-tests/eventsource/resources/status-reconnect.py
new file mode 100644
index 00000000000..16c6502e366
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/resources/status-reconnect.py
@@ -0,0 +1,21 @@
+def main(request, response):
+ status_code = request.GET.first("status", "204")
+ name = request.GET.first("id", status_code)
+
+ headers = [("Content-Type", "text/event-stream")]
+
+ cookie_name = "request" + name
+
+ if request.cookies.first(cookie_name, "") == status_code:
+ status = 200
+ response.delete_cookie(cookie_name)
+ body = "data: data\n\n"
+ else:
+ response.set_cookie(cookie_name, status_code);
+ status = (int(status_code), "TEST")
+ body = "retry: 2\n"
+ if "ok_first" in request.GET:
+ body += "data: ok\n\n"
+
+ return status, headers, body
+
diff --git a/tests/wpt/web-platform-tests/eventsource/shared-worker/eventsource-close.htm b/tests/wpt/web-platform-tests/eventsource/shared-worker/eventsource-close.htm
new file mode 100644
index 00000000000..0a0bdc7b866
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/shared-worker/eventsource-close.htm
@@ -0,0 +1,39 @@
+<!--
+onconnect = function(e) {
+try {
+ var port = e.ports[0]
+ var source = new EventSource("../resources/message.py")
+ source.onopen = function(e) {
+ this.close()
+ port.postMessage([true, this.readyState])
+ }
+} catch(e) {
+ port.postMessage([false, String(e)])
+}
+}
+/*-->
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>shared worker - EventSource: close()</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test();
+ test.step(function() {
+ var worker = new SharedWorker('#')
+ worker.port.onmessage = function(e) {
+ test.step(function() {
+ assert_true(e.data[0], e.data[1])
+ assert_equals(e.data[1], EventSource.CLOSED, 'this.readyState')
+ })
+ test.done()
+ }
+ })
+ </script>
+ </body>
+</html>
+<!--*/ //-->
diff --git a/tests/wpt/web-platform-tests/eventsource/shared-worker/eventsource-constructor-non-same-origin.htm b/tests/wpt/web-platform-tests/eventsource/shared-worker/eventsource-constructor-non-same-origin.htm
new file mode 100644
index 00000000000..277fbd40102
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/shared-worker/eventsource-constructor-non-same-origin.htm
@@ -0,0 +1,52 @@
+<!--
+onconnect = function(e) {
+try {
+ var port = e.ports[0]
+ var url = decodeURIComponent(location.hash.substr(1))
+ var source = new EventSource(url)
+ source.onerror = function(e) {
+ port.postMessage([true, this.readyState, 'data' in e])
+ this.close();
+ }
+} catch(e) {
+ port.postMessage([false, String(e)])
+}
+}
+/*-->
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>shared worker - EventSource: constructor (act as if there is a network error)</title>
+ <meta name=timeout content=long>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ function fetchFail(url) {
+ var test = async_test(document.title + " (" + url + ")", { timeout: 20000 })
+ test.step(function() {
+ var worker = new SharedWorker('#'+encodeURIComponent(url))
+ worker.port.onmessage = function(e) {
+ test.step(function() {
+ assert_true(e.data[0], e.data[1])
+ assert_equals(e.data[1], EventSource.CLOSED, 'source.readyState')
+ assert_false(e.data[2], "'data' in e");
+ })
+ test.done()
+ }
+ })
+ }
+ fetchFail("http://example.not")
+ fetchFail("https://example.not/test")
+ fetchFail("ftp://example.not")
+ fetchFail("about:blank")
+ fetchFail("mailto:whatwg@awesome.example")
+ fetchFail("javascript:alert('FAIL')")
+ </script>
+ <!-- This tests "fails the connection" as well as making sure a simple
+ event is dispatched and not a MessageEvent -->
+ </body>
+</html>
+<!--*/ //-->
diff --git a/tests/wpt/web-platform-tests/eventsource/shared-worker/eventsource-constructor-url-bogus.htm b/tests/wpt/web-platform-tests/eventsource/shared-worker/eventsource-constructor-url-bogus.htm
new file mode 100644
index 00000000000..88fa21e3bf9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/shared-worker/eventsource-constructor-url-bogus.htm
@@ -0,0 +1,37 @@
+<!--
+onconnect = function(e) {
+try {
+ var port = e.ports[0]
+ var source = new EventSource("http://this is invalid/")
+ port.postMessage([false, 'no exception thrown'])
+ source.close()
+} catch(e) {
+ port.postMessage([true, e.code])
+}
+}
+/*-->
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>shared worker - EventSource: constructor (invalid URL)</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+ var worker = new SharedWorker('#')
+ worker.port.onmessage = function(e) {
+ test.step(function() {
+ assert_true(e.data[0], e.data[1])
+ assert_equals(e.data[1], DOMException.SYNTAX_ERR, 'e.code')
+ })
+ test.done()
+ }
+ })
+ </script>
+ </body>
+</html>
+<!--*/ //--> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/eventsource/shared-worker/eventsource-eventtarget.htm b/tests/wpt/web-platform-tests/eventsource/shared-worker/eventsource-eventtarget.htm
new file mode 100644
index 00000000000..f5f9439d127
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/shared-worker/eventsource-eventtarget.htm
@@ -0,0 +1,40 @@
+<!--
+onconnect = function(e) {
+try {
+ var port = e.ports[0]
+ var source = new EventSource("../resources/message.py")
+ source.addEventListener("message", listener, false)
+ function listener(e) {
+ port.postMessage([true, e.data])
+ this.close()
+ }
+} catch(e) {
+ port.postMessage([false, String(e)])
+}
+}
+/*-->
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>shared worker - EventSource: addEventListener()</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+ var worker = new SharedWorker('#')
+ worker.port.onmessage = function(e) {
+ test.step(function() {
+ assert_true(e.data[0], e.data[1])
+ assert_equals(e.data[1], 'data', 'e.data')
+ })
+ test.done()
+ }
+ })
+ </script>
+ </body>
+</html>
+<!--*/ //-->
diff --git a/tests/wpt/web-platform-tests/eventsource/shared-worker/eventsource-onmesage.htm b/tests/wpt/web-platform-tests/eventsource/shared-worker/eventsource-onmesage.htm
new file mode 100644
index 00000000000..82c3ce7f238
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/shared-worker/eventsource-onmesage.htm
@@ -0,0 +1,39 @@
+<!--
+onconnect = function(e) {
+try {
+ var port = e.ports[0]
+ var source = new EventSource("../resources/message.py")
+ source.onmessage = function(e) {
+ port.postMessage([true, e.data])
+ this.close()
+ }
+} catch(e) {
+ port.postMessage([false, String(e)])
+}
+}
+/*-->
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>shared worker - EventSource: onmessage</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+ var worker = new SharedWorker('#')
+ worker.port.onmessage = function(e) {
+ test.step(function() {
+ assert_true(e.data[0], e.data[1])
+ assert_equals(e.data[1], "data", 'e.data')
+ })
+ test.done()
+ }
+ })
+ </script>
+ </body>
+</html>
+<!--*/ //-->
diff --git a/tests/wpt/web-platform-tests/eventsource/shared-worker/eventsource-onopen.htm b/tests/wpt/web-platform-tests/eventsource/shared-worker/eventsource-onopen.htm
new file mode 100644
index 00000000000..25467817ff9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/shared-worker/eventsource-onopen.htm
@@ -0,0 +1,42 @@
+<!--
+onconnect = function(e) {
+try {
+ var port = e.ports[0]
+ var source = new EventSource("../resources/message.py")
+ source.onopen = function(e) {
+ port.postMessage([true, source.readyState, 'data' in e, e.bubbles, e.cancelable])
+ this.close()
+ }
+} catch(e) {
+ port.postMessage([false, String(e)])
+}
+}
+/*-->
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>shared worker - EventSource: onopen (announcing the connection)</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test()
+ test.step(function() {
+ var worker = new SharedWorker('#')
+ worker.port.onmessage = function(e) {
+ test.step(function() {
+ assert_true(e.data[0], e.data[1])
+ assert_equals(e.data[1], EventSource.OPEN, 'source.readyState')
+ assert_false(e.data[2], "'data' in e")
+ assert_false(e.data[3], 'e.bubbles')
+ assert_false(e.data[4], 'e.calcelable')
+ })
+ test.done()
+ }
+ })
+ </script>
+ </body>
+</html>
+<!--*/ //-->
diff --git a/tests/wpt/web-platform-tests/eventsource/shared-worker/eventsource-prototype.htm b/tests/wpt/web-platform-tests/eventsource/shared-worker/eventsource-prototype.htm
new file mode 100644
index 00000000000..27d51a8587b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/shared-worker/eventsource-prototype.htm
@@ -0,0 +1,39 @@
+<!--
+onconnect = function(e) {
+try {
+ var port = e.ports[0]
+ EventSource.prototype.ReturnTrue = function() { return true }
+ var source = new EventSource("../resources/message.py")
+ port.postMessage([true, source.ReturnTrue(), 'EventSource' in self])
+ source.close()
+} catch(e) {
+ port.postMessage([false, String(e)])
+}
+}
+/*-->
+<!DoCtYpE hTMl>
+<html>
+ <heAd>
+ <title>shared worker - EventSource: prototype et al</tiTle>
+ <scrIpt src="/resources/testharness.js"></scripT>
+ <scriPt src="/resources/testharnessreport.js"></Script>
+ </heaD>
+ <boDy>
+ <diV iD="log"></Div>
+ <sCript>
+ var test = async_test();
+ test.step(function() {
+ var worker = new SharedWorker('#')
+ worker.port.onmessage = function(e) {
+ test.step(function() {
+ assert_true(e.data[0], e.data[1])
+ assert_true(e.data[1], 'source.ReturnTrue()')
+ assert_true(e.data[2], "'EventSource' in self")
+ })
+ test.done()
+ }
+ })
+ </scrIpt>
+ </bOdy>
+</htMl>
+<!--*/ //-->
diff --git a/tests/wpt/web-platform-tests/eventsource/shared-worker/eventsource-url.htm b/tests/wpt/web-platform-tests/eventsource/shared-worker/eventsource-url.htm
new file mode 100644
index 00000000000..0491085e9e3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/eventsource/shared-worker/eventsource-url.htm
@@ -0,0 +1,38 @@
+<!--
+onconnect = function(e) {
+try {
+ var port = e.ports[0]
+ var source = new EventSource("../resources/message.py")
+ port.postMessage([true, source.url])
+ source.close()
+} catch(e) {
+ port.postMessage([false, String(e)])
+}
+}
+/*-->
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>shared worker - EventSource: url</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test();
+ test.step(function() {
+ var url = "resources/message.py"
+ var worker = new SharedWorker('#')
+ worker.port.onmessage = function(e) {
+ test.step(function() {
+ assert_true(e.data[0], e.data[1]);
+ assert_equals(e.data[1].substr(-(url.length)), url)
+ })
+ test.done()
+ }
+ })
+ </script>
+ </body>
+</html>
+<!--*/ //-->
diff --git a/tests/wpt/web-platform-tests/ext-xhtml-pubid/the-xhtml-syntax/parsing-xhtml-documents/xhtml-local.dtd b/tests/wpt/web-platform-tests/ext-xhtml-pubid/the-xhtml-syntax/parsing-xhtml-documents/xhtml-local.dtd
new file mode 100644
index 00000000000..03e583876bf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/ext-xhtml-pubid/the-xhtml-syntax/parsing-xhtml-documents/xhtml-local.dtd
@@ -0,0 +1,3 @@
+<!ENTITY Sqrt "Sqrt">
+<!ENTITY lang "lang">
+<!ENTITY nbsp "nbsp">
diff --git a/tests/wpt/web-platform-tests/ext-xhtml-pubid/the-xhtml-syntax/parsing-xhtml-documents/xhtml-pubid-1.html b/tests/wpt/web-platform-tests/ext-xhtml-pubid/the-xhtml-syntax/parsing-xhtml-documents/xhtml-pubid-1.html
new file mode 100644
index 00000000000..f73de750dd6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/ext-xhtml-pubid/the-xhtml-syntax/parsing-xhtml-documents/xhtml-pubid-1.html
@@ -0,0 +1,83 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "xhtml-local.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>XHTML Doctype test 1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<h1>XHTML Doctype test 1</h1>
+
+<div id="log" style="display:block"></div>
+
+
+<iframe id="xhtml1" src="xhtml-pubid-1.xhtml" onload="t1()"></iframe><br/>
+<iframe id="xhtml2" src="xhtml-pubid-2.xhtml" onload="t2()"></iframe><br/>
+<iframe id="xhtml3" src="xhtml-pubid-3.xhtml" onload="t3()"></iframe>
+
+<script>
+
+
+
+
+function t1 () {
+var txt;
+try{
+txt = window.frames[0].document.getElementById("sqrt").firstChild.nodeValue;
+} catch (e) {
+txt=null;
+}
+test(function() {
+assert_equals(txt,'\u221a');
+},"Sqrt entity is U+221a with legacy DTD");
+
+try{
+txt = window.frames[0].document.getElementById("lang").firstChild.nodeValue;
+} catch (e) {
+txt=null;
+}
+test(function() {
+assert_equals(txt,'\u27e8');
+},"lang entity is U+27E8 not U+2329 with legacy DTD");
+}
+
+function t2 () {
+var txt2;
+try{
+txt2 = window.frames[1].document.getElementById("nbsp").firstChild.nodeValue;
+} catch (e) {
+txt2=null;
+}
+test(function() {
+assert_object_equals(txt2,null);
+},"nbsp should not be recognised without known PUBLIC identifier");
+}
+
+function t3 () {
+var txt3;
+try{
+txt3 = window.frames[2].document.getElementById("sqrt").firstChild.nodeValue;
+} catch (e) {
+txt3=null;
+}
+test(function() {
+assert_equals(txt3,'\u221a');
+},"Sqrt entity is U+221a with XHTML PUBID Extension spec");
+
+try{
+txt3 = window.frames[2].document.getElementById("lang").firstChild.nodeValue;
+} catch (e) {
+txt3=null;
+}
+test(function() {
+assert_equals(txt3,'\u27e8');
+},"lang entity is U+27E8 with XHTML PUBID Extension spec");
+}
+
+
+
+</script>
+
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/ext-xhtml-pubid/the-xhtml-syntax/parsing-xhtml-documents/xhtml-pubid-1.xhtml b/tests/wpt/web-platform-tests/ext-xhtml-pubid/the-xhtml-syntax/parsing-xhtml-documents/xhtml-pubid-1.xhtml
new file mode 100644
index 00000000000..068641afeb3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/ext-xhtml-pubid/the-xhtml-syntax/parsing-xhtml-documents/xhtml-pubid-1.xhtml
@@ -0,0 +1,16 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "xhtml-local.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>XHTML Doctype Example 1</title>
+</head>
+<body>
+
+<div>
+<span id="sqrt">&Sqrt;</span>
+<span id="lang">&lang;</span>
+</div>
+
+
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/ext-xhtml-pubid/the-xhtml-syntax/parsing-xhtml-documents/xhtml-pubid-2.xhtml b/tests/wpt/web-platform-tests/ext-xhtml-pubid/the-xhtml-syntax/parsing-xhtml-documents/xhtml-pubid-2.xhtml
new file mode 100644
index 00000000000..99171a691d6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/ext-xhtml-pubid/the-xhtml-syntax/parsing-xhtml-documents/xhtml-pubid-2.xhtml
@@ -0,0 +1,15 @@
+<!DOCTYPE html SYSTEM "xhtml-local.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>XHTML Doctype Example 2</title>
+</head>
+<body>
+
+<div>
+<span id="nbsp">&nbsp;</span>
+</div>
+
+
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/ext-xhtml-pubid/the-xhtml-syntax/parsing-xhtml-documents/xhtml-pubid-3.xhtml b/tests/wpt/web-platform-tests/ext-xhtml-pubid/the-xhtml-syntax/parsing-xhtml-documents/xhtml-pubid-3.xhtml
new file mode 100644
index 00000000000..f6fffea3d7e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/ext-xhtml-pubid/the-xhtml-syntax/parsing-xhtml-documents/xhtml-pubid-3.xhtml
@@ -0,0 +1,16 @@
+<!DOCTYPE html PUBLIC "-//W3C//ENTITIES HTML MathML Set//EN//XML" "xhtml-local.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>XHTML Doctype Example 3</title>
+</head>
+<body>
+
+<div>
+<span id="nbsp">&Sqrt;</span>
+<span id="lang">&lang;</span>
+</div>
+
+
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/fonts/CanvasTest.sfd b/tests/wpt/web-platform-tests/fonts/CanvasTest.sfd
new file mode 100644
index 00000000000..6dbe8e287fd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/fonts/CanvasTest.sfd
@@ -0,0 +1,321 @@
+SplineFontDB: 3.0
+FontName: CanvasTest
+FullName: CanvasTest
+FamilyName: CanvasTest
+Weight: Medium
+Copyright: Copyright (c) 2010 Philip Taylor.\n\nReleased under the MIT License: http://www.opensource.org/licenses/mit-license.php
+UComments: "2010-2-26: Created."
+Version: 001.000
+ItalicAngle: 0
+UnderlinePosition: -102
+UnderlineWidth: 51
+Ascent: 768
+Descent: 256
+LayerCount: 2
+Layer: 0 0 "Back" 1
+Layer: 1 0 "Fore" 0
+NeedsXUIDChange: 1
+XUID: [1021 923 651290676 15069128]
+BaseHoriz: 4 'hang' 'ideo' 'math' 'romn'
+BaseScript: 'DFLT' 3 512 128 384 0
+FSType: 0
+OS2Version: 0
+OS2_WeightWidthSlopeOnly: 0
+OS2_UseTypoMetrics: 1
+CreationTime: 1267213266
+ModificationTime: 1267289643
+OS2TypoAscent: 0
+OS2TypoAOffset: 1
+OS2TypoDescent: 0
+OS2TypoDOffset: 1
+OS2TypoLinegap: 92
+OS2WinAscent: 0
+OS2WinAOffset: 1
+OS2WinDescent: 0
+OS2WinDOffset: 1
+HheadAscent: 0
+HheadAOffset: 1
+HheadDescent: 0
+HheadDOffset: 1
+DEI: 91125
+LangName: 1033
+Encoding: ISO8859-1
+UnicodeInterp: none
+NameList: Adobe Glyph List
+DisplaySize: -24
+AntiAlias: 1
+FitToEm: 1
+WinInfo: 0 39 15
+BeginChars: 256 11
+
+StartChar: A
+Encoding: 65 65 0
+Width: 1024
+VWidth: 0
+Flags: H
+LayerCount: 2
+Fore
+SplineSet
+0 768 m 25
+ 1024 768 l 25
+ 1024 0 l 29
+ 0 0 l 25
+ 0 768 l 25
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: B
+Encoding: 66 66 1
+Width: 1024
+VWidth: 0
+Flags: H
+LayerCount: 2
+Fore
+SplineSet
+0 0 m 29
+ 1024 0 l 25
+ 1024 -256 l 25
+ 0 -256 l 25
+ 0 0 l 29
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: C
+Encoding: 67 67 2
+Width: 1024
+VWidth: 0
+Flags: H
+LayerCount: 2
+Fore
+SplineSet
+280 1640 m 1
+ 350 1735 l 1
+ 493 1594 l 1
+ 620 1745 l 1
+ 705 1660 l 1
+ 577 1511 l 1
+ 715 1375 l 1
+ 635 1280 l 1
+ 498 1418 l 1
+ 380 1280 l 1
+ 305 1370 l 1
+ 416 1502 l 1
+ 280 1640 l 1
+0 768 m 25
+ 1024 768 l 25
+ 1024 -256 l 25
+ 0 -256 l 25
+ 0 768 l 25
+620 -340 m 1
+ 705 -425 l 1
+ 577 -574 l 1
+ 715 -710 l 1
+ 635 -805 l 1
+ 498 -667 l 1
+ 380 -805 l 1
+ 305 -715 l 1
+ 416 -583 l 1
+ 280 -445 l 1
+ 350 -350 l 1
+ 493 -491 l 1
+ 620 -340 l 1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: D
+Encoding: 68 68 3
+Width: 1024
+VWidth: 0
+Flags: HW
+LayerCount: 2
+Fore
+SplineSet
+-1003 450 m 1
+ -933 545 l 1
+ -790 404 l 1
+ -663 555 l 1
+ -578 470 l 1
+ -706 321 l 1
+ -568 185 l 1
+ -648 90 l 1
+ -785 228 l 1
+ -903 90 l 1
+ -978 180 l 1
+ -867 312 l 1
+ -1003 450 l 1
+0 768 m 25
+ 1024 768 l 25
+ 1024 -256 l 25
+ 0 -256 l 29
+ 0 768 l 25
+1485 591 m 1
+ 1570 506 l 1
+ 1442 357 l 1
+ 1580 221 l 1
+ 1500 126 l 1
+ 1363 264 l 1
+ 1245 126 l 1
+ 1170 216 l 1
+ 1281 348 l 1
+ 1145 486 l 1
+ 1215 581 l 1
+ 1358 440 l 1
+ 1485 591 l 1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: space
+Encoding: 32 32 4
+Width: 1024
+VWidth: 0
+Flags: HW
+LayerCount: 2
+EndChar
+
+StartChar: E
+Encoding: 69 69 5
+Width: 1024
+VWidth: 0
+Flags: HW
+LayerCount: 2
+Fore
+SplineSet
+0 768 m 25
+ 1024 768 l 25
+ 1024 -256 l 25
+ 0 -256 l 25
+ 0 768 l 25
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: uni000B
+Encoding: 11 11 6
+Width: 1024
+VWidth: 0
+Flags: HW
+LayerCount: 2
+Fore
+SplineSet
+28 644 m 1
+ 98 739 l 1
+ 241 598 l 1
+ 368 749 l 1
+ 453 664 l 1
+ 325 515 l 1
+ 463 379 l 1
+ 383 284 l 1
+ 246 422 l 1
+ 128 284 l 1
+ 53 374 l 1
+ 164 506 l 1
+ 28 644 l 1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: uni000C
+Encoding: 12 12 7
+Width: 1024
+VWidth: 0
+Flags: HW
+LayerCount: 2
+Fore
+SplineSet
+28 644 m 1
+ 98 739 l 1
+ 241 598 l 1
+ 368 749 l 1
+ 453 664 l 1
+ 325 515 l 1
+ 463 379 l 1
+ 383 284 l 1
+ 246 422 l 1
+ 128 284 l 1
+ 53 374 l 1
+ 164 506 l 1
+ 28 644 l 1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: uni000D
+Encoding: 13 13 8
+Width: 1024
+VWidth: 0
+Flags: HW
+LayerCount: 2
+Fore
+SplineSet
+28 644 m 1
+ 98 739 l 1
+ 241 598 l 1
+ 368 749 l 1
+ 453 664 l 1
+ 325 515 l 1
+ 463 379 l 1
+ 383 284 l 1
+ 246 422 l 1
+ 128 284 l 1
+ 53 374 l 1
+ 164 506 l 1
+ 28 644 l 1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: uni000A
+Encoding: 10 10 9
+Width: 1024
+VWidth: 0
+Flags: HW
+LayerCount: 2
+Fore
+SplineSet
+28 644 m 1
+ 98 739 l 1
+ 241 598 l 1
+ 368 749 l 1
+ 453 664 l 1
+ 325 515 l 1
+ 463 379 l 1
+ 383 284 l 1
+ 246 422 l 1
+ 128 284 l 1
+ 53 374 l 1
+ 164 506 l 1
+ 28 644 l 1
+EndSplineSet
+Validated: 1
+EndChar
+
+StartChar: uni0009
+Encoding: 9 9 10
+Width: 1024
+VWidth: 0
+Flags: HW
+LayerCount: 2
+Fore
+SplineSet
+28 644 m 1
+ 98 739 l 1
+ 241 598 l 1
+ 368 749 l 1
+ 453 664 l 1
+ 325 515 l 1
+ 463 379 l 1
+ 383 284 l 1
+ 246 422 l 1
+ 128 284 l 1
+ 53 374 l 1
+ 164 506 l 1
+ 28 644 l 1
+EndSplineSet
+Validated: 1
+EndChar
+EndChars
+EndSplineFont
diff --git a/tests/wpt/web-platform-tests/fonts/CanvasTest.ttf b/tests/wpt/web-platform-tests/fonts/CanvasTest.ttf
new file mode 100644
index 00000000000..9023592ef5a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/fonts/CanvasTest.ttf
Binary files differ
diff --git a/tests/wpt/web-platform-tests/gamepad/events-manual.html b/tests/wpt/web-platform-tests/gamepad/events-manual.html
new file mode 100644
index 00000000000..321c9b2b0c3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/gamepad/events-manual.html
@@ -0,0 +1,34 @@
+<!doctype html>
+<html>
+<head>
+<title>Manual Gamepad events tests</title>
+<link rel="help" href="https://dvcs.w3.org/hg/gamepad/raw-file/default/gamepad.html#the-gamepadconnected-event">
+<link rel="help" href="https://dvcs.w3.org/hg/gamepad/raw-file/default/gamepad.html#the-gamepaddisconnected-event">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+setup({explicit_timeout: true});
+
+function set_instructions(text) {
+ document.getElementById("instructions").textContent = text;
+}
+
+var index = -1;
+addEventListener("gamepadconnected", function (e) {
+ assert_equals(index, -1, "Too many connected events?");
+ assert_class_string(e, "GamepadEvent");
+ assert_class_string(e.gamepad, "Gamepad");
+ index = e.gamepad.index;
+ set_instructions("Found a gamepad. Now disconnect the gamepad.");
+});
+addEventListener("gamepaddisconnected", function (e) {
+ assert_class_string(e, "GamepadEvent");
+ assert_equals(e.gamepad.index, index);
+ done();
+});
+</script>
+</head>
+<body>
+<p id="instructions">This test requires a gamepad. Connect one and press any button to start the test.</p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/gamepad/getgamepads-polling-manual.html b/tests/wpt/web-platform-tests/gamepad/getgamepads-polling-manual.html
new file mode 100644
index 00000000000..bcbb5eb2fd9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/gamepad/getgamepads-polling-manual.html
@@ -0,0 +1,30 @@
+<!doctype html>
+<html>
+<head>
+<title>Manual Gamepad getGamepads polling tests</title>
+<link rel="help" href="https://dvcs.w3.org/hg/gamepad/raw-file/default/gamepad.html#navigator-interface-extension">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+setup({explicit_timeout: true});
+// Poll until we see a gamepad.
+var id = setInterval(function() {
+ var gamepads = navigator.getGamepads();
+ var found = null;
+ for (var i = 0; i < gamepads.length; i++) {
+ if (gamepads[i]) {
+ found = gamepads[i];
+ break;
+ }
+ }
+ if (found) {
+ clearInterval(id);
+ done();
+ }
+}, 15);
+</script>
+</head>
+<body>
+<p>This test requires a gamepad. Connect one and press any button to start the test.</p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/gamepad/idlharness-manual.html b/tests/wpt/web-platform-tests/gamepad/idlharness-manual.html
new file mode 100644
index 00000000000..54f25796e04
--- /dev/null
+++ b/tests/wpt/web-platform-tests/gamepad/idlharness-manual.html
@@ -0,0 +1,78 @@
+<!doctype html>
+<html>
+<head>
+<title>Manual Gamepad IDL tests</title>
+<link rel="help" href="https://dvcs.w3.org/hg/gamepad/raw-file/default/gamepad.html#gamepad-interface">
+<link rel="help" href="https://dvcs.w3.org/hg/gamepad/raw-file/default/gamepad.html#gamepadbutton-interface">
+<link rel="help" href="https://dvcs.w3.org/hg/gamepad/raw-file/default/gamepad.html#gamepadevent-interface">
+<link rel="help" href="https://dvcs.w3.org/hg/gamepad/raw-file/default/gamepad.html#navigator-interface-extension">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/WebIDLParser.js"></script>
+<script src="/resources/idlharness.js"></script>
+<script>
+setup({explicit_done: true, explicit_timeout: true});
+
+addEventListener("gamepadconnected", function (e) {
+ var idl_array = new IdlArray();
+ idl_array.add_untested_idls(document.getElementById("untested_idl").textContent);
+ idl_array.add_idls(document.getElementById("idl").textContent);
+ idl_array.add_objects({
+ GamepadEvent: [e],
+ Gamepad: [e.gamepad],
+ GamepadButton: [e.gamepad.buttons[0]],
+ Navigator: ["navigator"],
+ });
+ idl_array.test();
+ done();
+});
+</script>
+</head>
+<body>
+<pre id="untested_idl" style="display: none">
+interface Navigator {
+};
+
+interface Event {
+};
+</pre>
+<pre id="idl" style="display: none">
+interface Gamepad {
+ readonly attribute DOMString id;
+ readonly attribute long index;
+ readonly attribute boolean connected;
+ readonly attribute DOMHighResTimeStamp timestamp;
+ readonly attribute GamepadMappingType mapping;
+ readonly attribute double[] axes;
+ readonly attribute GamepadButton[] buttons;
+};
+
+enum GamepadMappingType {
+ "",
+ "standard"
+};
+
+interface GamepadButton {
+ readonly attribute boolean pressed;
+ readonly attribute double value;
+};
+
+[Constructor(DOMString type, optional GamepadEventInit eventInitDict)]
+interface GamepadEvent : Event
+{
+ readonly attribute Gamepad? gamepad;
+};
+
+dictionary GamepadEventInit : EventInit
+{
+ Gamepad? gamepad = null;
+};
+
+partial interface Navigator {
+ Gamepad[] getGamepads();
+};
+</pre>
+<p id="instructions">This test requires a gamepad. Connect one and press any button to start the test.</p>
+<div id="log"></div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/gamepad/idlharness.html b/tests/wpt/web-platform-tests/gamepad/idlharness.html
new file mode 100644
index 00000000000..5ec141ec82d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/gamepad/idlharness.html
@@ -0,0 +1,70 @@
+<!doctype html>
+<html>
+<head>
+<title>Gamepad IDL tests</title>
+<link rel="help" href="https://dvcs.w3.org/hg/gamepad/raw-file/default/gamepad.html#gamepad-interface">
+<link rel="help" href="https://dvcs.w3.org/hg/gamepad/raw-file/default/gamepad.html#gamepadbutton-interface">
+<link rel="help" href="https://dvcs.w3.org/hg/gamepad/raw-file/default/gamepad.html#gamepadevent-interface">
+<link rel="help" href="https://dvcs.w3.org/hg/gamepad/raw-file/default/gamepad.html#navigator-interface-extension">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/WebIDLParser.js"></script>
+<script src="/resources/idlharness.js"></script>
+</head>
+<body>
+<pre id="untested_idl" style="display: none">
+interface Navigator {
+};
+
+interface Event {
+};
+</pre>
+<pre id="idl" style="display: none">
+interface Gamepad {
+ readonly attribute DOMString id;
+ readonly attribute long index;
+ readonly attribute boolean connected;
+ readonly attribute DOMHighResTimeStamp timestamp;
+ readonly attribute GamepadMappingType mapping;
+ readonly attribute double[] axes;
+ readonly attribute GamepadButton[] buttons;
+};
+
+enum GamepadMappingType {
+ "",
+ "standard"
+};
+
+interface GamepadButton {
+ readonly attribute boolean pressed;
+ readonly attribute double value;
+};
+
+[Constructor(DOMString type, optional GamepadEventInit eventInitDict)]
+interface GamepadEvent : Event
+{
+ readonly attribute Gamepad? gamepad;
+};
+
+dictionary GamepadEventInit : EventInit
+{
+ Gamepad? gamepad = null;
+};
+
+partial interface Navigator {
+ Gamepad[] getGamepads();
+};
+</pre>
+<script>
+var idl_array = new IdlArray();
+idl_array.add_untested_idls(document.getElementById("untested_idl").textContent);
+idl_array.add_idls(document.getElementById("idl").textContent);
+idl_array.add_objects({
+ GamepadEvent: [new GamepadEvent("something")],
+ Navigator: ["navigator"],
+ });
+idl_array.test();
+</script>
+<div id="log"></div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/gamepad/timestamp-manual.html b/tests/wpt/web-platform-tests/gamepad/timestamp-manual.html
new file mode 100644
index 00000000000..dec74a000ce
--- /dev/null
+++ b/tests/wpt/web-platform-tests/gamepad/timestamp-manual.html
@@ -0,0 +1,58 @@
+<!doctype html>
+<html>
+<head>
+<title>Manual Gamepad timestamp tests</title>
+<link rel="help" href="https://dvcs.w3.org/hg/gamepad/raw-file/default/gamepad.html#widl-Gamepad-timestamp">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+setup({explicit_timeout: true});
+
+function set_instructions(text) {
+ document.getElementById("instructions").textContent = text;
+}
+
+var index = -1;
+var lastTimestamp = performance.now();
+var id = -1;
+addEventListener("gamepadconnected", function (e) {
+ assert_equals(index, -1, "Too many connected events?");
+ index = e.gamepad.index;
+ assert_greater_than(e.gamepad.timestamp, lastTimestamp, "timestamp should be increasing");
+ lastTimestamp = e.gamepad.timestamp;
+ set_instructions("Found a gamepad. Now release the button you pressed and press it again.");
+ // There may not be a button pressed here, so handle it cleanly either way.
+ if (e.gamepad.buttons.some(function (b) { return b.pressed; })) {
+ id = setInterval(waitForButtonRelease, 15);
+ } else {
+ id = setInterval(waitForButtonPress, 15);
+ }
+});
+
+function waitForButtonRelease() {
+ var gamepad = navigator.getGamepads()[index];
+ assert_true(!!gamepad);
+ if (gamepad.buttons.every(function (b) { return !b.pressed; })) {
+ assert_greater_than(gamepad.timestamp, lastTimestamp, "timestamp should be increasing");
+ lastTimestamp = gamepad.timestamp;
+ clearInterval(id);
+ id = setInterval(waitForButtonPress, 15);
+ }
+}
+
+function waitForButtonPress() {
+ var gamepad = navigator.getGamepads()[index];
+ assert_true(!!gamepad);
+ if (gamepad.buttons.some(function (b) { return b.pressed; })) {
+ assert_greater_than(gamepad.timestamp, lastTimestamp, "timestamp should be increasing");
+ clearInterval(id);
+ done();
+ }
+}
+
+</script>
+</head>
+<body>
+<p id="instructions">This test requires a gamepad. Connect one and press any button to start the test.</p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/geolocation-API/PositionOptions.html b/tests/wpt/web-platform-tests/geolocation-API/PositionOptions.html
new file mode 100644
index 00000000000..9d4985eb779
--- /dev/null
+++ b/tests/wpt/web-platform-tests/geolocation-API/PositionOptions.html
@@ -0,0 +1,113 @@
+<!DOCTYPE HTML>
+<meta charset="utf-8">
+<title>Geolocation Test: PositionOptions tests</title>
+<link rel="help" href="http://www.w3.org/TR/geolocation-API/#position_options_interface">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src='support.js'></script>
+
+<p>Clear all Geolocation permissions before running this test. If prompted for permission, please allow.</p>
+<div id="log"></div>
+
+<script>
+// Rewrite http://dev.w3.org/geo/api/test-suite/t.html?00123
+test(function() {
+ try {
+ geo.getCurrentPosition(dummyFunction, null, {enableHighAccuracy: "boom"});
+ geo.getCurrentPosition(dummyFunction, null, {enableHighAccuracy: 321});
+ geo.getCurrentPosition(dummyFunction, null, {enableHighAccuracy: -Infinity});
+ geo.getCurrentPosition(dummyFunction, null, {enableHighAccuracy: {foo: 5}});
+ } catch(e) {
+ assert_unreached('An exception was thrown unexpectedly: ' + e.message);
+ }
+}, 'Call getCurrentPosition with wrong type for enableHighAccuracy. No exception expected.');
+
+// Rewrite http://dev.w3.org/geo/api/test-suite/t.html?00124
+test(function() {
+ try {
+ geo.watchPosition(dummyFunction, null, {enableHighAccuracy: "boom"});
+ geo.watchPosition(dummyFunction, null, {enableHighAccuracy: 321});
+ geo.watchPosition(dummyFunction, null, {enableHighAccuracy: -Infinity});
+ geo.watchPosition(dummyFunction, null, {enableHighAccuracy: {foo: 5}});
+ } catch(e) {
+ assert_unreached('An exception was thrown unexpectedly: ' + e.message);
+ }
+}, 'Call watchPosition with wrong type for enableHighAccuracy. No exception expected.');
+
+// Rewrite http://dev.w3.org/geo/api/test-suite/t.html?00086, 00088, 00091 and 00092
+test(function() {
+ var t86 = async_test('Set timeout and maximumAge to 0, check that timeout error raised (getCurrentPosition)'),
+ t88 = async_test('Set timeout and maximumAge to 0, check that timeout error raised (watchPosition)'),
+ t91 = async_test('Check that a negative timeout value is equivalent to a 0 timeout value (getCurrentLocation)'),
+ t92 = async_test('Check that a negative timeout value is equivalent to a 0 timeout value (watchPosition)');
+
+ try {
+ geo.getCurrentPosition(
+ t86.step_func(function(pos) {
+ assert_unreached('A success callback was invoked unexpectedly');
+ }),
+ t86.step_func(function(err) {
+ assert_equals(err.code, err.TIMEOUT);
+ t86.done();
+ }),
+ {timeout: 0, maximumAge: 0}
+ );
+ } catch(e) {
+ t86.step(function() {
+ assert_unreached('An exception was thrown unexpectedly: ' + e.message);
+ });
+ }
+
+ try {
+ geo.watchPosition(
+ t88.step_func(function(pos) {
+ assert_unreached('A success callback was invoked unexpectedly');
+ }),
+ t88.step_func(function(err) {
+ assert_equals(err.code, err.TIMEOUT);
+ t88.done();
+ }),
+ {timeout: 0, maximumAge: 0}
+ );
+ } catch(e) {
+ t88.step(function() {
+ assert_unreached('An exception was thrown unexpectedly: ' + e.message);
+ });
+ }
+
+ try {
+ geo.getCurrentPosition(
+ t91.step_func(function(pos) {
+ assert_unreached('A success callback was invoked unexpectedly');
+ }),
+ t91.step_func(function(err) {
+ assert_equals(err.code, err.TIMEOUT);
+ t91.done();
+ }),
+ {timeout:-1, maximumAge: 0}
+ );
+ } catch(e) {
+ t91.step(function() {
+ assert_unreached('An exception was thrown unexpectedly: ' + e.message);
+ });
+ }
+
+ try {
+ geo.watchPosition(
+ t92.step_func(function(pos) {
+ assert_unreached('A success callback was invoked unexpectedly');
+ done();
+ }),
+ t92.step_func(function(err) {
+ assert_equals(err.code, err.TIMEOUT);
+ done();
+ }),
+ {timeout: -1, maximumAge: 0}
+ );
+ } catch(e) {
+ t92.step(function() {
+ assert_unreached('An exception was thrown unexpectedly: ' + e.message);
+ });
+ }
+}, 'PositionOptions tests');
+</script>
diff --git a/tests/wpt/web-platform-tests/geolocation-API/clearWatch_TypeError.html b/tests/wpt/web-platform-tests/geolocation-API/clearWatch_TypeError.html
new file mode 100644
index 00000000000..d752ebac1c9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/geolocation-API/clearWatch_TypeError.html
@@ -0,0 +1,23 @@
+<!DOCTYPE HTML>
+<meta charset='utf-8'>
+<title>Geolocation Test: clearWatch TypeError tests</title>
+<link rel='help' href='http://www.w3.org/TR/geolocation-API/#clear-watch'>
+<script src='/resources/testharness.js'></script>
+<script src='/resources/testharnessreport.js'></script>
+<script src='support.js'></script>
+
+<div id='log'></div>
+
+<script>
+// Rewrite http://dev.w3.org/geo/api/test-suite/t.html?00080
+test(function() {
+ try {
+ geo.clearWatch(-1);
+ geo.clearWatch(0);
+ geo.clearWatch(1);
+ } catch(e) {
+ assert_unreached('An exception was thrown unexpectedly: ' + e.message);
+ }
+ done();
+}, 'Test that calling clearWatch with invalid watch IDs does not cause an exception');
+</script>
diff --git a/tests/wpt/web-platform-tests/geolocation-API/getCurrentPosition_IDL.html b/tests/wpt/web-platform-tests/geolocation-API/getCurrentPosition_IDL.html
new file mode 100644
index 00000000000..2a85505b843
--- /dev/null
+++ b/tests/wpt/web-platform-tests/geolocation-API/getCurrentPosition_IDL.html
@@ -0,0 +1,152 @@
+<!DOCTYPE HTML>
+<meta charset="utf-8">
+<title>Geolocation Test: getCurrentPosition tests</title>
+<link rel="help" href="http://www.w3.org/TR/geolocation-API/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<p>Clear all Geolocation permissions before running this test. If prompted for permission, please allow.</p>
+<div id="log"></div>
+<script>
+var geo, success, fail;
+
+setup(function() {
+ geo = navigator.geolocation;
+}, {explicit_done: true});
+
+function successCallback(position)
+{
+ var ii, oldval;
+
+ /*
+ [NoInterfaceObject]
+ interface Position {
+ readonly attribute Coordinates coords;
+ readonly attribute DOMTimeStamp timestamp;
+ };
+ */
+
+ test(function() {
+ assert_equals(position.toString(), "[object Position]",
+ "Position.toString should result in '[object Position]' was: " + position.toString());
+ }, "Position toString");
+
+ test(function() {
+ assert_equals(position.coords.toString(), "[object Coordinates]",
+ "position.coords.toString should result in '[object Coordinates]' was: " + position.coords.toString());
+ }, "Position.coordinates toString");
+
+ test(function() {
+ assert_equals(typeof(position.timestamp), "number",
+ "Position.timestamp should be of type 'number' was: " + typeof(position.timestamp));
+ }, "Position.timestamp is type number");
+
+ /*
+ [NoInterfaceObject]
+ interface Coordinates {
+ readonly attribute double latitude;
+ readonly attribute double longitude;
+ readonly attribute double? altitude;
+ readonly attribute double accuracy;
+ readonly attribute double? altitudeAccuracy;
+ readonly attribute double? heading;
+ readonly attribute double? speed;
+ };
+ */
+
+ for (ii in position.coords) {
+ // these four can be numbers or null
+ if (ii == "altitude" || ii == "altitudeAccuracy" || ii == "heading" || ii == "speed") {
+ test(function() {
+ assert_true(position.coords[ii] === null || typeof(position.coords[ii]) === "number",
+ ii + " must be null or 'number' type, was: " + typeof(position.coords[ii]));
+ }, ii+ " is null or number");
+ } else {
+ test(function() {
+ assert_equals(typeof(position.coords[ii]), "number",
+ ii + " should be type 'number' but typeof returned: " + typeof(position.coords[ii]));
+ }, ii + " is type number");
+ }
+
+ oldval = position.coords[ii];
+ position.coords[ii] = 666;
+
+ test(function() {
+ assert_equals(position.coords[ii], oldval,
+ ii + " should be readonly, wrote: " + position.coords[ii] + " old value was " + oldval);
+ }, ii + " readonly");
+
+ }
+
+ success.done();
+ done();
+}
+
+function BadErrorCallback(error)
+{
+ success.step(function() {
+ assert_unreached("Error callback called in error");
+ });
+ success.done();
+ done();
+}
+
+function BadSuccessCallback(position)
+{
+ fail.step(function() {
+ assert_unreached("Success callback called in error");
+ });
+ fail.done();
+}
+
+function errorCallback(error)
+{
+ test(function() {
+ assert_equals(error.toString(), "[object PositionError]",
+ "PositionError.toString should result in '[object PositionError]' was: " +
+ error.toString());
+ }, "PositionError toString");
+
+ test(function() {
+ assert_equals(error.PERMISSION_DENIED, 1,
+ "PERMISSION_DENIED should be 1 was: " + error.POSITION_DENIED);
+ }, "PERMISSION_DENIED value is 1");
+
+ test(function() {
+ assert_equals(error.POSITION_UNAVAILABLE, 2,
+ "POSITION_UNAVAILABLE should be 2' was: " + error.POSITION_UNAVAILABLE);
+ }, "POSITION_UNAVAILABLE is 2");
+
+ test(function() {
+ assert_equals(error.TIMEOUT, 3,
+ "TIMEOUT should be 3 was: " + error.TIMEOUT);
+ }, "TIMEOUT value is 3");
+
+ fail.done();
+}
+
+success = async_test("getCurrentPosition success callback tests", {timeout:20000});
+
+// with a longer timeout and with the user accepting the position request,
+// this should test the successcallback
+success.step(function() {
+ geo.getCurrentPosition(
+ successCallback,
+ BadErrorCallback,
+ {maximumAge:600000, timeout:10000}
+ );
+});
+
+fail = async_test("getCurrentPosition error callback tests");
+
+// with a timeout of 0 the error callback is hopefully consistently called
+fail.step(function() {
+ geo.getCurrentPosition(
+ BadSuccessCallback,
+ errorCallback,
+ {maximumAge:00, timeout:0}
+ );
+});
+
+</script>
+
diff --git a/tests/wpt/web-platform-tests/geolocation-API/getCurrentPosition_TypeError.html b/tests/wpt/web-platform-tests/geolocation-API/getCurrentPosition_TypeError.html
new file mode 100644
index 00000000000..a2e57846979
--- /dev/null
+++ b/tests/wpt/web-platform-tests/geolocation-API/getCurrentPosition_TypeError.html
@@ -0,0 +1,55 @@
+<!DOCTYPE HTML>
+<meta charset='utf-8'>
+<title>Geolocation Test: getCurrentPosition TypeError tests</title>
+<link rel='help' href='http://www.w3.org/TR/geolocation-API/'>
+<script src='/resources/testharness.js'></script>
+<script src='/resources/testharnessreport.js'></script>
+<script src='support.js'></script>
+
+<div id='log'></div>
+
+<script>
+// Rewrite http://dev.w3.org/geo/api/test-suite/t.html?00027
+test(function() {
+ assert_throws(new TypeError(), function() {
+ geo.getCurrentPosition();
+ });
+}, 'Call getCurrentPosition without arguments, check that exception is thrown');
+
+// Rewrite http://dev.w3.org/geo/api/test-suite/t.html?00011
+test(function() {
+ assert_throws(new TypeError(), function() {
+ geo.getCurrentPosition(null);
+ });
+}, 'Call getCurrentPosition with null success callback, check that exception is thrown');
+
+// Rewrite http://dev.w3.org/geo/api/test-suite/t.html?00013
+test(function() {
+ assert_throws(new TypeError(), function() {
+ geo.getCurrentPosition(null, null);
+ });
+}, 'Call getCurrentPosition with null success and error callbacks, check that exception is thrown');
+
+// Rewrite http://dev.w3.org/geo/api/test-suite/t.html?00028
+test(function() {
+ assert_throws(new TypeError(), function() {
+ geo.getCurrentPosition(3);
+ });
+}, 'Call getCurrentPosition() with wrong type for first argument. Exception expected.');
+
+// Rewrite http://dev.w3.org/geo/api/test-suite/t.html?00029
+test(function() {
+ assert_throws(new TypeError(), function() {
+ geo.getCurrentPosition(dummyFunction, 4);
+ });
+}, 'Call getCurrentPosition() with wrong type for second argument. Exception expected.');
+
+// Rewrite http://dev.w3.org/geo/api/test-suite/t.html?00030
+test(function() {
+ assert_throws(new TypeError(), function() {
+ geo.getCurrentPosition(dummyFunction, dummyFunction, 4);
+ });
+}, 'Call getCurrentPosition() with wrong type for third argument. Exception expected.');
+
+done();
+</script>
diff --git a/tests/wpt/web-platform-tests/geolocation-API/getCurrentPosition_permission-manual.html b/tests/wpt/web-platform-tests/geolocation-API/getCurrentPosition_permission-manual.html
new file mode 100644
index 00000000000..20003cdff1d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/geolocation-API/getCurrentPosition_permission-manual.html
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML>
+<meta charset='utf-8'>
+<title>Call getCurrentPosition, check that there is UI appearing with the document host</title>
+<link rel='help' href='http://www.w3.org/TR/geolocation-API/#privacy_for_uas'>
+
+<p>Clear all Geolocation permissions before running this test.</p>
+
+<p>Test passes if there is a permission prompt including the host <strong id='host'></strong> and no FAIL.</p>
+<div id='log'></div>
+
+<script>
+// Rewrite http://dev.w3.org/geo/api/test-suite/t.html?00018
+try {
+ var dummyFunction = function() {};
+ window.navigator.geolocation.getCurrentPosition(dummyFunction, dummyFunction);
+
+ document.getElementById('host').innerHTML = window.location.hostname;
+} catch (e) {
+ document.getElementById('log').innerHTML = 'FAIL: an exception was thrown unexpectedly: ' + e.message;
+}
+</script>
diff --git a/tests/wpt/web-platform-tests/geolocation-API/getCurrentPosition_permission_allow-manual.html b/tests/wpt/web-platform-tests/geolocation-API/getCurrentPosition_permission_allow-manual.html
new file mode 100644
index 00000000000..4628275e321
--- /dev/null
+++ b/tests/wpt/web-platform-tests/geolocation-API/getCurrentPosition_permission_allow-manual.html
@@ -0,0 +1,32 @@
+<!DOCTYPE HTML>
+<meta charset='utf-8'>
+<title>User asked to approve/remember, then asked to revoke, then reload. The permission dialogue should reappear</title>
+<link rel='help' href='http://www.w3.org/TR/geolocation-API/#get-current-position'>
+
+<p>Clear all Geolocation permissions before running this test. If prompted for permission, please allow.</p>
+
+<div id='log'></div>
+
+<script>
+// Rewrite http://dev.w3.org/geo/api/test-suite/t.html?00141
+var nextStep, onError, isUsingPreemptivePermission = false;
+
+nextStep = function() {
+ document.querySelector('p').innerHTML =
+ 'Now revoke permissions for this origin (where applicable) and reload the page. Tests passes if there is a permission prompt again and no FAIL.';
+};
+
+onError = function(err) {
+ if (!isUsingPreemptivePermission && err.code === err.POSITION_UNAVAILABLE) {
+ nextStep();
+ } else {
+ document.getElementById('log').innerHTML = 'FAIL: an error callback was invoked unexpectedly: ' + err.message;
+ }
+};
+
+try {
+ window.navigator.geolocation.getCurrentPosition(nextStep, onError);
+} catch (e) {
+ document.getElementById('log').innerHTML = 'FAIL: an exception was thrown unexpectedly: ' + e.message;
+}
+</script>
diff --git a/tests/wpt/web-platform-tests/geolocation-API/getCurrentPosition_permission_allow.html b/tests/wpt/web-platform-tests/geolocation-API/getCurrentPosition_permission_allow.html
new file mode 100644
index 00000000000..dfadcb09d19
--- /dev/null
+++ b/tests/wpt/web-platform-tests/geolocation-API/getCurrentPosition_permission_allow.html
@@ -0,0 +1,44 @@
+<!DOCTYPE HTML>
+<meta charset='utf-8'>
+<title>Geolocation Test: getCurrentPosition location access allowed</title>
+<link rel='help' href='http://www.w3.org/TR/geolocation-API/#get-current-position'>
+<script src='/resources/testharness.js'></script>
+<script src='/resources/testharnessreport.js'></script>
+<script src='support.js'></script>
+
+<p>Clear all Geolocation permissions before running this test. If prompted for permission, please allow.</p>
+<div id='log'></div>
+
+<script>
+// Rewrite http://dev.w3.org/geo/api/test-suite/t.html?00002
+var t = async_test('User allows access, check that success callback is called or error callback is called with correct code.'),
+ onSuccess, onError, hasMethodReturned = false;
+
+onSuccess = t.step_func(function(pos) {
+ // Rewrite http://dev.w3.org/geo/api/test-suite/t.html?00031
+ test(function() {
+ assert_true(hasMethodReturned);
+ }, 'Check that getCurrentPosition returns synchronously before any callbacks are invoked.');
+
+ done();
+});
+
+onError = t.step_func(function(err) {
+ // Rewrite http://dev.w3.org/geo/api/test-suite/t.html?00031
+ test(function() {
+ assert_true(hasMethodReturned);
+ }, 'Check that getCurrentPosition returns synchronously before any callbacks are invoked.');
+
+ assert_true(!isUsingPreemptivePermission && err.code === err.POSITION_UNAVAILABLE);
+ done();
+});
+
+try {
+ geo.getCurrentPosition(onSuccess, onError);
+ hasMethodReturned = true;
+} catch(e) {
+ t.step(function() {
+ assert_unreached('An exception was thrown unexpectedly: ' + e.message);
+ });
+}
+</script>
diff --git a/tests/wpt/web-platform-tests/geolocation-API/getCurrentPosition_permission_deny-manual.html b/tests/wpt/web-platform-tests/geolocation-API/getCurrentPosition_permission_deny-manual.html
new file mode 100644
index 00000000000..b468a65da2b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/geolocation-API/getCurrentPosition_permission_deny-manual.html
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML>
+<meta charset='utf-8'>
+<title>User asked to deny/remember, then asked to revoke, then reload. The permission dialogue should reappear</title>
+<link rel='help' href='http://www.w3.org/TR/geolocation-API/#get-current-position'>
+
+<p>Clear all Geolocation permissions before running this test. If prompted for permission, please deny.</p>
+
+<div id='log'></div>
+
+<script>
+// Rewrite http://dev.w3.org/geo/api/test-suite/t.html?00142
+var onSuccess, nextStep, isUsingPreemptivePermission = false;
+
+onSuccess = function() {
+ document.getElementById('log').innerHTML = 'FAIL: a success callback was invoked unexpectedly.';
+};
+
+nextStep = function(err) {
+ if ((err.code === err.PERMISSION_DENIED) ||
+ (!isUsingPreemptivePermission && err.code === err.POSITION_UNAVAILABLE)) {
+ document.querySelector('p').innerHTML =
+ 'Now revoke permissions for this origin (where applicable) and reload the page. Tests passes if there is a permission prompt again and no FAIL.';
+ } else {
+ document.getElementById('log').innerHTML =
+ 'FAIL: an error callback was invoked with unexpected error code: ' + err.code + ', error message: ' + err.message;
+ }
+};
+
+try {
+ navigator.geolocation.getCurrentPosition(onSuccess, nextStep);
+} catch (e) {
+ document.getElementById('log').innerHTML = 'FAIL: an exception was thrown unexpectedly: ' + e.message;
+}
+</script>
diff --git a/tests/wpt/web-platform-tests/geolocation-API/getCurrentPosition_permission_deny.html b/tests/wpt/web-platform-tests/geolocation-API/getCurrentPosition_permission_deny.html
new file mode 100644
index 00000000000..26fe8899eda
--- /dev/null
+++ b/tests/wpt/web-platform-tests/geolocation-API/getCurrentPosition_permission_deny.html
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML>
+<meta charset='utf-8'>
+<title>Geolocation Test: getCurrentPosition location access denied</title>
+<link rel='help' href='http://www.w3.org/TR/geolocation-API/#privacy_for_uas'>
+<script src='/resources/testharness.js'></script>
+<script src='/resources/testharnessreport.js'></script>
+<script src='support.js'></script>
+
+<p>Clear all Geolocation permissions before running this test. If prompted for permission, please deny.</p>
+<div id='log'></div>
+
+<script>
+// Rewrite http://dev.w3.org/geo/api/test-suite/t.html?00001
+var t = async_test('User denies access, check that error callback is called with correct code'),
+ onSuccess, onError, hasMethodReturned = false;
+
+t.step(function() {
+ onSuccess = t.step_func(function(pos) {
+ assert_unreached('A success callback was invoked unexpectedly with position ' + positionToString(pos));
+ });
+
+ onError = t.step_func(function(err) {
+ // http://dev.w3.org/geo/api/test-suite/t.html?00031
+ assert_true(hasMethodReturned, 'Check that getCurrentPosition returns synchronously before any callbacks are invoked');
+ assert_equals(err.code, err.PERMISSION_DENIED,
+ 'PossitionError code: ' + err.code, + ', message: ' + err.message);
+ done();
+ });
+
+ geo.getCurrentPosition(onSuccess, onError);
+ hasMethodReturned = true;
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/geolocation-API/interfaces.html b/tests/wpt/web-platform-tests/geolocation-API/interfaces.html
new file mode 100644
index 00000000000..0db4204653d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/geolocation-API/interfaces.html
@@ -0,0 +1,95 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Geolocation API IDL tests</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="http://www.w3.org/TR/geolocation-API/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/WebIDLParser.js"></script>
+<script src="/resources/idlharness.js"></script>
+
+<h1>Geolocation API IDL tests</h1>
+<div id="log"></div>
+
+<script type=text/plain class=untested>
+interface Navigator {
+};
+
+typedef unsigned long long DOMTimeStamp;
+</script>
+
+<script type=text/plain>
+partial interface Navigator {
+ readonly attribute Geolocation geolocation;
+};
+
+[NoInterfaceObject]
+interface Geolocation {
+ void getCurrentPosition(PositionCallback successCallback,
+ optional PositionErrorCallback errorCallback,
+ optional PositionOptions options);
+
+ long watchPosition(PositionCallback successCallback,
+ optional PositionErrorCallback errorCallback,
+ optional PositionOptions options);
+
+ void clearWatch(long watchId);
+};
+
+callback PositionCallback = void (Position position);
+
+callback PositionErrorCallback = void (PositionError positionError);
+
+dictionary PositionOptions {
+ boolean enableHighAccuracy = false;
+ [Clamp] unsigned long timeout = 0xFFFFFFFF;
+ [Clamp] unsigned long maximumAge = 0;
+};
+
+[NoInterfaceObject]
+interface Position {
+ readonly attribute Coordinates coords;
+ readonly attribute DOMTimeStamp timestamp;
+};
+
+[NoInterfaceObject]
+interface Coordinates {
+ readonly attribute double latitude;
+ readonly attribute double longitude;
+ readonly attribute double? altitude;
+ readonly attribute double accuracy;
+ readonly attribute double? altitudeAccuracy;
+ readonly attribute double? heading;
+ readonly attribute double? speed;
+};
+
+[NoInterfaceObject]
+interface PositionError {
+ const unsigned short PERMISSION_DENIED = 1;
+ const unsigned short POSITION_UNAVAILABLE = 2;
+ const unsigned short TIMEOUT = 3;
+ readonly attribute unsigned short code;
+ readonly attribute DOMString message;
+};
+</script>
+
+<script>
+"use strict";
+var idlArray;
+setup(function() {
+ idlArray = new IdlArray();
+ [].forEach.call(document.querySelectorAll("script[type=text\\/plain]"), function(node) {
+ if (node.className == "untested") {
+ idlArray.add_untested_idls(node.textContent);
+ } else {
+ idlArray.add_idls(node.textContent);
+ }
+ });
+ idlArray.add_objects({
+ Navigator: ["navigator"],
+ Geolocation: ["navigator.geolocation"]
+ });
+});
+idlArray.test();
+</script>
+
diff --git a/tests/wpt/web-platform-tests/geolocation-API/support.js b/tests/wpt/web-platform-tests/geolocation-API/support.js
new file mode 100644
index 00000000000..c85b5c87f91
--- /dev/null
+++ b/tests/wpt/web-platform-tests/geolocation-API/support.js
@@ -0,0 +1,30 @@
+var geo;
+
+setup(function() {
+ geo = navigator.geolocation;
+}, {explicit_done: true});
+
+// The spec states that an implementation SHOULD acquire user permission before
+// beggining the position acquisition steps. If an implementation follows this
+// advice, set the following flag to aid debugging.
+var isUsingPreemptivePermission = false;
+
+
+var dummyFunction = function() {};
+
+var positionToString = function(pos) {
+ var c = pos.coords;
+ return '[lat: ' + c.latitude + ', lon: ' + c.longitude + ', acc: ' + c.accuracy + ']';
+};
+
+var errorToString = function(err) {
+ var codeString;
+ switch(err.code) {
+ case err.UNKNOWN_ERROR: codeString = 'UNKNOWN_ERROR'; break;
+ case err.PERMISSION_DENIED: codeString = 'PERMISSION_DENIED'; break;
+ case err.POSITION_UNAVAILABLE: codeString = 'POSITION_UNAVAILABLE'; break;
+ case err.TIMEOUT: codeString = 'TIMEOUT'; break;
+ default: codeString = 'undefined error code'; break;
+ }
+ return '[code: ' + codeString + ' (' + err.code + '), message: ' + (err.message ? err.message : '(empty)') + ']';
+};
diff --git a/tests/wpt/web-platform-tests/geolocation-API/watchPosition_TypeError.html b/tests/wpt/web-platform-tests/geolocation-API/watchPosition_TypeError.html
new file mode 100644
index 00000000000..9d7efd5e7b9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/geolocation-API/watchPosition_TypeError.html
@@ -0,0 +1,55 @@
+<!DOCTYPE HTML>
+<meta charset='utf-8'>
+<title>Geolocation Test: watchPosition TypeError tests</title>
+<link rel='help' href='http://www.w3.org/TR/geolocation-API/'>
+<script src='/resources/testharness.js'></script>
+<script src='/resources/testharnessreport.js'></script>
+<script src='support.js'></script>
+
+<div id='log'></div>
+
+<script>
+// Rewrite http://dev.w3.org/geo/api/test-suite/t.html?00058
+test(function() {
+ assert_throws(new TypeError(), function() {
+ geo.watchPosition();
+ });
+}, 'Call watchPosition without arguments, check that exception is thrown');
+
+// Rewrite http://dev.w3.org/geo/api/test-suite/t.html?00015
+test(function() {
+ assert_throws(new TypeError(), function() {
+ geo.watchPosition(null);
+ });
+}, 'Call watchPosition with null success callback, check that exception is thrown');
+
+// Rewrite http://dev.w3.org/geo/api/test-suite/t.html?00017
+test(function() {
+ assert_throws(new TypeError(), function() {
+ geo.watchPosition(null, null);
+ });
+}, 'Call watchPosition with null success and error callbacks, check that exception is thrown');
+
+// Rewrite http://dev.w3.org/geo/api/test-suite/t.html?00059
+test(function() {
+ assert_throws(new TypeError(), function() {
+ geo.watchPosition(3);
+ });
+}, 'Call watchPosition() with wrong type for first argument. Exception expected.');
+
+// Rewrite http://dev.w3.org/geo/api/test-suite/t.html?00060
+test(function() {
+ assert_throws(new TypeError(), function() {
+ geo.watchPosition(dummyFunction, 4);
+ });
+}, 'Call watchPosition() with wrong type for second argument. Exception expected.');
+
+// Rewrite http://dev.w3.org/geo/api/test-suite/t.html?00061
+test(function() {
+ assert_throws(new TypeError(), function() {
+ geo.watchPosition(dummyFunction, dummyFunction, 4);
+ });
+}, 'Call watchPosition() with wrong type for third argument. Exception expected.');
+
+done();
+</script>
diff --git a/tests/wpt/web-platform-tests/geolocation-API/watchPosition_permission-manual.html b/tests/wpt/web-platform-tests/geolocation-API/watchPosition_permission-manual.html
new file mode 100644
index 00000000000..e00980192d5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/geolocation-API/watchPosition_permission-manual.html
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML>
+<meta charset='utf-8'>
+<title>Call watchPosition, check that there is UI appearing with the document host</title>
+<link rel='help' href='http://www.w3.org/TR/geolocation-API/#privacy_for_uas'>
+
+<p>Clear all Geolocation permissions before running this test.</p>
+
+<p>Test passes if there is a permission prompt including the host <strong id='host'></strong> and no FAIL.</p>
+<div id='log'></div>
+
+<script>
+// Rewrite http://dev.w3.org/geo/api/test-suite/t.html?00019
+try {
+ var dummyFunction = function() {};
+ window.navigator.geolocation.watchPosition(dummyFunction, dummyFunction);
+
+ document.getElementById('host').innerHTML = window.location.hostname;
+} catch (e) {
+ document.getElementById('log').innerHTML = 'FAIL: ' + e.message;
+}
+</script>
diff --git a/tests/wpt/web-platform-tests/geolocation-API/watchPosition_permission_deny.html b/tests/wpt/web-platform-tests/geolocation-API/watchPosition_permission_deny.html
new file mode 100644
index 00000000000..831a1544fdf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/geolocation-API/watchPosition_permission_deny.html
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML>
+<meta charset='utf-8'>
+<title>Geolocation Test: watchPosition location access denied</title>
+<link rel='help' href='http://www.w3.org/TR/geolocation-API/#watch-position'>
+<script src='/resources/testharness.js'></script>
+<script src='/resources/testharnessreport.js'></script>
+<script src='support.js'></script>
+
+<p>Clear all Geolocation permissions before running this test. If prompted for permission, please deny.</p>
+<div id='log'></div>
+
+<script>
+// Rewrite http://dev.w3.org/geo/api/test-suite/t.html?00062
+var t = async_test('Check that watchPosition returns synchronously before any callbacks are invoked.'),
+ id, checkMethodHasReturned, hasMethodReturned = false;
+
+checkMethodHasReturned = t.step_func(function() {
+ assert_true(hasMethodReturned);
+ done();
+});
+
+try {
+ id = geo.watchPosition(checkMethodHasReturned, checkMethodHasReturned);
+ hasMethodReturned = true;
+} catch(e) {
+ t.step(function() {
+ assert_unreached('An exception was thrown unexpectedly: ' + e.message);
+ });
+}
+
+// Rewrite http://dev.w3.org/geo/api/test-suite/t.html?00151
+test(function() {
+ assert_greater_than_equal(id, -2147483648);
+ assert_less_than_equal(id, 2147483647);
+}, 'Check that watchPosition returns a long');
+</script>
diff --git a/tests/wpt/web-platform-tests/hr-time/basic.html b/tests/wpt/web-platform-tests/hr-time/basic.html
new file mode 100644
index 00000000000..959657e8281
--- /dev/null
+++ b/tests/wpt/web-platform-tests/hr-time/basic.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8" />
+<title>window.performance.now exists</title>
+<link rel="author" title="W3C" href="http://www.w3.org/" />
+<link rel="help" href="http://www.w3.org/TR/hr-time/#sec-extenstions-performance-interface"/>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css" />
+<script>
+test(function() {
+ assert_equals(typeof window.performance, "object");
+}, "window.performance is defined", {assert: "The window.performance attribute provides a hosting area for performance related attributes."});
+
+test(function() {
+ assert_not_equals(window.performance.now, undefined, 'window.performance.now is defined');
+}, "High Resolution Time extension to the Performance interface", {assert: "window.performance.now exists"});
+
+test(function() {
+ assert_equals(typeof window.performance.now, "function", "window.performance.now is a function");
+}, "window.performance.now() function", {assert: "window.performance.now is a function"});
+
+test(function() {
+ assert_equals(typeof window.performance.now(), "number", "window.performance.now() returns a number");
+}, "window.performance.now() returns a number", {assert: "The now method MUST return a DOMHighResTimeStamp"});
+</script>
+</head>
+<body>
+<h1>Description</h1>
+<p>This test validates that window.performance.now() exist and is a function.</p>
+
+<div id="log"></div>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/hr-time/idlharness.html b/tests/wpt/web-platform-tests/hr-time/idlharness.html
new file mode 100644
index 00000000000..0b1fd7d3260
--- /dev/null
+++ b/tests/wpt/web-platform-tests/hr-time/idlharness.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>High Resolution Time IDL tests</title>
+<link rel="author" title="W3C" href="http://www.w3.org/" />
+<link rel="help" href="http://www.w3.org/TR/hr-time/#sec-extenstions-performance-interface"/>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/WebIDLParser.js"></script>
+<script src="/resources/idlharness.js"></script>
+</head>
+<body>
+<h1>High Resolution Time IDL tests</h1>
+<div id="log"></div>
+
+<pre id='untested_idl' style='display:none'>
+
+interface Window {
+};
+
+interface Performance {
+};
+
+partial interface Window {
+ [Replaceable] readonly attribute Performance performance;
+};
+</pre>
+
+<pre id='idl'>
+typedef double DOMHighResTimeStamp;
+
+partial interface Performance {
+ DOMHighResTimeStamp now();
+};
+</pre>
+
+<script>
+
+(function() {
+ var idl_array = new IdlArray();
+
+ idl_array.add_untested_idls(document.getElementById("untested_idl").textContent);
+ idl_array.add_idls(document.getElementById("idl").textContent);
+
+ idl_array.add_objects({Performance: ["window.performance"]});
+
+ idl_array.test();
+})();
+
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/hr-time/monotonic-clock.html b/tests/wpt/web-platform-tests/hr-time/monotonic-clock.html
new file mode 100644
index 00000000000..4833edba592
--- /dev/null
+++ b/tests/wpt/web-platform-tests/hr-time/monotonic-clock.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8" />
+<title>window.performance.now() chronology</title>
+<link rel="author" title="W3C" href="http://www.w3.org/" />
+<link rel="help" href="http://www.w3.org/TR/hr-time/#sec-monotonic-clock"/>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css" />
+<script>
+test(function() {
+ assert_true(window.performance.now() > 0, "window.performance.now() returns positive numbers");
+}, "window.performance.now() returns a positive number", {assert: "The time values returned when calling the now method MUST be monotonically increasing and not subject to system clock adjustments or system clock skew."});
+
+test(function() {
+ var now1 = window.performance.now();
+ var now2 = window.performance.now();
+ assert_true((now2-now1) >= 0, "window.performance.now() difference is not negative");
+ },
+ "window.performance.now() difference is not negative",
+ {
+ assert: "The difference between any two chronologically recorded time values returned from the now method MUST never be negative."
+ }
+);
+
+</script>
+</head>
+<body>
+<h1>Description</h1>
+<p>This test validates that window.performance.now() follows the monotonic clock requirements.</p>
+
+<div id="log"></div>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/hr-time/resources/now_frame.html b/tests/wpt/web-platform-tests/hr-time/resources/now_frame.html
new file mode 100644
index 00000000000..5bec688af9c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/hr-time/resources/now_frame.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
+ <title>window.performance.now frame</title>
+ <link rel="author" title="Google" href="http://www.google.com/" />
+ </head>
+ <body></body>
+</html>
diff --git a/tests/wpt/web-platform-tests/hr-time/test_cross_frame_start.html b/tests/wpt/web-platform-tests/hr-time/test_cross_frame_start.html
new file mode 100644
index 00000000000..4633a73843e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/hr-time/test_cross_frame_start.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" >
+ <title>window.performance.now across frames</title>
+ <link rel="author" title="Google" href="http://www.google.com/">
+ <link rel="help" href="http://www.w3.org/TR/hr-time/#sec-extenstions-performance-interface">
+
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ <script type="text/javascript">
+ setup({explicit_done: true});
+
+ function start_test() {
+ setTimeout(function() {
+ var iframe = document.createElement('iframe');
+ iframe.id = 'frameContext';
+ iframe.onload = finish_test;
+ iframe.src = "resources/now_frame.html";
+ document.body.appendChild(iframe);
+ }, 1000);
+ }
+
+ function finish_test() {
+ var childWindow = document.getElementById('frameContext').contentWindow;
+
+ // Verify a positive number is returned for both the frame and parent.
+ test(function() { assert_true(window.performance.now() > 0); }, 'parent performance.now() > 0');
+ test(function() { assert_true(childWindow.performance.now() > 0); }, 'child performance.now() > 0');
+
+ // Verify that the test properly created the child at least a second after the parent.
+ test(function () { assert_true(childWindow.performance.timing.navigationStart > (window.performance.timing.navigationStart + 1000)); },
+ 'Child created at least 1 second after parent');
+
+ test(function () {
+ var parentNow = window.performance.now();
+ var childNow = childWindow.performance.now();
+ var childParentSkew = Math.abs(childNow - parentNow);
+ assert_true(childParentSkew > 1000, 'Child and parent\'s now()s have different bases (skewed more than 1 second)');
+
+ var childLoadTime = childWindow.performance.timing.loadEventStart - childWindow.performance.timing.navigationStart;
+ assert_true(1000 > (childNow - childLoadTime), 'Child\'s now() is based on its document\'s navigationStart');
+ }, 'Child and parent time bases are correct');
+
+ done();
+ }
+ </script>
+
+ </head>
+ <body onload="start_test()">
+ <h1>Description</h1>
+ <p>This test validates the values of the window.performance.now() are based on the current document's navigationStart.</p>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html-imports/document/document-method-changes.html b/tests/wpt/web-platform-tests/html-imports/document/document-method-changes.html
new file mode 100644
index 00000000000..b50f3e3c5d2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html-imports/document/document-method-changes.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>The import attribute</title>
+<link rel="help" href="http://w3c.github.io/webcomponents/spec/imports/#interface-import">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+
+<link id="importLink" rel="import" href="resources/body-only.html">
+<link rel="import" href="resources/test-in-import.html">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ assert_throws('INVALID_STATE_ERR', function() { importLink.import.open(); }, 'document.open()');
+ assert_throws('INVALID_STATE_ERR', function() { importLink.import.write('Hello'); }, 'document.write()');
+ assert_throws('INVALID_STATE_ERR', function() { importLink.import.open(); }, 'document.close()');
+}, 'Throws an InvalidStateError exception if the Document is an import: From the master document');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html-imports/document/resources/body-only.html b/tests/wpt/web-platform-tests/html-imports/document/resources/body-only.html
new file mode 100644
index 00000000000..0ed2a55bbc8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html-imports/document/resources/body-only.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<html>
+<body id="body-only">Hello</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html-imports/document/resources/test-in-import.html b/tests/wpt/web-platform-tests/html-imports/document/resources/test-in-import.html
new file mode 100644
index 00000000000..fc25e85a406
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html-imports/document/resources/test-in-import.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script>
+test(function() {
+ var doc = document.currentScript.ownerDocument;
+ assert_throws('INVALID_STATE_ERR', function() { doc.open(); }, 'document.open()');
+ assert_throws('INVALID_STATE_ERR', function() { doc.write('Hello'); }, 'document.write()');
+ assert_throws('INVALID_STATE_ERR', function() { doc.open(); }, 'document.close()');
+}, 'Throws an InvalidStateError exception if the Document is an import: From an import');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html-imports/fetching/already-in-import-map.html b/tests/wpt/web-platform-tests/html-imports/fetching/already-in-import-map.html
new file mode 100644
index 00000000000..b721faed98f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html-imports/fetching/already-in-import-map.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Fetching import</title>
+<link rel="help" href="http://w3c.github.io/webcomponents/spec/imports/#fetching-import">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+
+<link id="first" rel="import" href="resources/hello.html">
+<link id="shouldBeInImportMap" rel="import" href="resources/hello.html">
+<link id="parentOfFirst" rel="import" href="resources/parent-of-hello.html">
+
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ assert_true(window.first.import === window.shouldBeInImportMap.import);
+}, 'If LOCATION is already in the import map, let IMPORT be the imported document for LOCATION and stop. (1)');
+
+test(function() {
+ console.log(window.parentOfFirst);
+ assert_true(window.first.import === window.parentOfFirst.import.getElementById('child').import);
+}, 'If LOCATION is already in the import map, let IMPORT be the imported document for LOCATION and stop. (2)');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html-imports/fetching/loading-attempt.html b/tests/wpt/web-platform-tests/html-imports/fetching/loading-attempt.html
new file mode 100644
index 00000000000..fe9fd61f9ff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html-imports/fetching/loading-attempt.html
@@ -0,0 +1,77 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Fetching import</title>
+<link rel="help" href="http://w3c.github.io/webcomponents/spec/imports/#fetching-import">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+
+<script>
+var onloadWasCalledOnSuccess = false;
+var onerrorWasCalledOnSuccess = false;
+function helloLoadHandler() { onloadWasCalledOnSuccess = true; }
+function helloErrorHandler() { onerrorWasCalledOnSuccess = true; }
+
+var onloadWasCalledOnFail = false;
+var onerrorWasCalledOnFail = false;
+function nosuchLoadHandler() { onloadWasCalledOnFail = true; }
+function nosuchErrorHandler() { onerrorWasCalledOnFail = true; }
+</script>
+
+<link rel="import" href="resources/hello.html" onload="helloLoadHandler()" onerror="helloLoadHandler()">
+<link rel="import" href="resources/no-such.html" onload="nosuchLoadHandler()" onerror="nosuchErrorHandler()">
+
+<script>
+test(function() {
+ assert_true(onloadWasCalledOnSuccess);
+ assert_false(onerrorWasCalledOnSuccess);
+}, 'The loading attempt must be considered successful if IMPORT is not null on the algorithm completion, and failed otherwise. (1)');
+
+test(function() {
+ assert_false(onloadWasCalledOnFail);
+ assert_true(onerrorWasCalledOnFail);
+}, 'The loading attempt must be considered successful if IMPORT is not null on the algorithm completion, and failed otherwise. (2)');
+
+t1 = async_test('The loading attempt must be considered successful if IMPORT is not null on the algorithm completion, and failed otherwise. (3)')
+t1.step(function() {
+ var importElement = document.createElement('link');
+ importElement.setAttribute('rel', 'import');
+ importElement.setAttribute('href', 'resources/dynamic.html');
+ importElement.addEventListener("error", assert_unreached);
+ importElement.addEventListener("load", function() {
+ t1.done();
+ });
+
+ document.head.appendChild(importElement);
+});
+
+var onloadWasCalledOnAsync = false;
+var onerrorWasCalledOnAsync = false;
+var asyncAttemptDone = function() { assert_unreached(); };
+
+function asyncLoadHandler() {
+ onloadWasCalledOnAsync = true;
+ asyncAttemptDone();
+}
+function asyncErrorHandler() {
+ onerrorWasCalledOnAsync = true;
+ asyncAttemptDone();
+}
+
+t2 = async_test('Every import that is not marked as async delays the load event in the Document.');
+asyncAttemptDone = function() {
+ t2.step(function() {
+ assert_true(onloadWasCalledOnAsync);
+ assert_false(onerrorWasCalledOnAsync);
+ t2.done();
+ });
+};
+
+</script>
+<link rel="import" href="resources/async.html" onload="asyncLoadHandler()" onerror="asyncErrorHandler()" async>
+</head>
+<body>
+<div id="log"></div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html-imports/fetching/resources/async.html b/tests/wpt/web-platform-tests/html-imports/fetching/resources/async.html
new file mode 100644
index 00000000000..18de0861803
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html-imports/fetching/resources/async.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<body>Async</body>
diff --git a/tests/wpt/web-platform-tests/html-imports/fetching/resources/dynamic.html b/tests/wpt/web-platform-tests/html-imports/fetching/resources/dynamic.html
new file mode 100644
index 00000000000..bf17a13bae9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html-imports/fetching/resources/dynamic.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<body>Dyamic</body>
diff --git a/tests/wpt/web-platform-tests/html-imports/fetching/resources/hello.html b/tests/wpt/web-platform-tests/html-imports/fetching/resources/hello.html
new file mode 100644
index 00000000000..949f6c66abb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html-imports/fetching/resources/hello.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<body>Hello</body>
diff --git a/tests/wpt/web-platform-tests/html-imports/fetching/resources/parent-of-hello.html b/tests/wpt/web-platform-tests/html-imports/fetching/resources/parent-of-hello.html
new file mode 100644
index 00000000000..195e37adde0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html-imports/fetching/resources/parent-of-hello.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<link id="child" rel="import" href="hello.html">
diff --git a/tests/wpt/web-platform-tests/html-imports/html-link-element/import-attribute.html b/tests/wpt/web-platform-tests/html-imports/html-link-element/import-attribute.html
new file mode 100644
index 00000000000..7fb9e98742c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html-imports/html-link-element/import-attribute.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>The import attribute</title>
+<link rel="help" href="http://w3c.github.io/webcomponents/spec/imports/#interface-import">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+
+<link id="nonImportLink" rel="stylesheet" href="resources/hello.css">
+<link id="goOutFromDocument" rel="import" href="resources/body-only-0.html">
+<link id="importLink" rel="import" href="resources/body-only-1.html">
+<link id="anotherImportLink" rel="import" href="resources/body-only-2.html">
+
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ assert_equals(nonImportLink.import, null);
+}, 'The import attribute must return null if the link does not represent an import.');
+
+test(function() {
+ var link = goOutFromDocument;
+ assert_true(link.import != null);
+ document.head.removeChild(link);
+ assert_equals(link.import, null);
+}, 'The import attribute must return null if the link element is not in a Document.');
+
+test(function() {
+ assert_equals(importLink.import.body.id, 'body-only-1');
+}, 'The attribute must return the imported document for the import.');
+
+test(function() {
+ var importA = importLink.import;
+ var importB = document.querySelector('#importLink').import;
+ var anotherImport = document.querySelector('#anotherImportLink').import;
+ assert_true(importA === importB);
+ assert_true(importA !== anotherImport);
+}, 'The same object must be returned each time.');
+</script>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/html-imports/html-link-element/resources/body-only-0.html b/tests/wpt/web-platform-tests/html-imports/html-link-element/resources/body-only-0.html
new file mode 100644
index 00000000000..cac33c7a316
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html-imports/html-link-element/resources/body-only-0.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<html>
+<body id="body-only-0">Hello</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html-imports/html-link-element/resources/body-only-1.html b/tests/wpt/web-platform-tests/html-imports/html-link-element/resources/body-only-1.html
new file mode 100644
index 00000000000..c0eedf4e48e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html-imports/html-link-element/resources/body-only-1.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<html>
+<body id="body-only-1">Hello</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html-imports/html-link-element/resources/body-only-2.html b/tests/wpt/web-platform-tests/html-imports/html-link-element/resources/body-only-2.html
new file mode 100644
index 00000000000..9a6a1e4381b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html-imports/html-link-element/resources/body-only-2.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<html>
+<body id="body-only-2">Hello</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html-imports/html-link-element/resources/hello.css b/tests/wpt/web-platform-tests/html-imports/html-link-element/resources/hello.css
new file mode 100644
index 00000000000..9054080ffcc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html-imports/html-link-element/resources/hello.css
@@ -0,0 +1,3 @@
+h1 {
+ color: red;
+} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html-longdesc/README.html b/tests/wpt/web-platform-tests/html-longdesc/README.html
new file mode 100644
index 00000000000..c4779a229b0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html-longdesc/README.html
@@ -0,0 +1,109 @@
+
+<!doctype html>
+<html>
+<head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
+<title>Multifunction tests</title>
+
+</head>
+<body>
+<h1>longdesc-tests</h1>
+
+<p>Proposed tests for the <a href="http://www.w3.org/TR/html-longdesc">HTML Image Description Extension specification</a>. These tests are © chaals, and available under the <a href="http://www.w3.org/Consortium/Legal/copyright-software">W3C Software license</a></p>
+
+<h2>Multifunction tests</h2>
+
+<p>These 15 tests include descriptions under different combinations of circumstances - images included "normally", as data: URIs, or missing, with the descriptions internal or external to the page, as a data: URI, or in a location only reachable by taking into account the base element.</p>
+
+<p>The same tests are used to provide 3 results:
+1 Can the user discover there is an image that has a long description available?
+2 Can the user access the description? To pass, the user should arrive at the "pass page" which has a heading "Pass" followed by a description, or the focus must be on the text "Pass, if the focus is here" which is followed by a description of the image.
+3 Is the long description available to system accessibility APIs</p>
+
+<h3>Longdesc value as data:URI</h3>
+
+<ul>
+<li><a href="data-uri-image-data-uri-description-manual.html">data:URI image with data:URI description</a></li>
+<li><a href="empty-image-data-uri-description-manual.html">Empty image with data:URI description</a></li>
+<li><a href="external-image-data-uri-description-girt-by-spaces-manual.html">External image with data:URI description (with extra spaces)</a></li>
+<li><a href="external-image-data-uri-description-manual.html">External image with data:URI description</a></li>
+</ul>
+
+
+<h3>Longdesc value as external URI</h3>
+
+<ul>
+<li><a href="data-uri-image-external-description-manual.html">data:URI with External description</a></li>
+<li><a href="empty-image-external-description-manual.html">Empty image with an External description</a></li>
+<li><a href="external-image-external-description-girt-by-spaces-manual.html">External image with External description (with extra spaces)</a></li>
+<li><a href="external-image-external-description-manual.html">External image with External description</a></li>
+</ul>
+
+
+<h3>Longdesc value as internal URI (same page link)</h3>
+
+<ul>
+<li><a href="data-uri-image-internal-description-manual.html">data:URI with Internal description</a></li>
+<li><a href="empty-image-internal-description-manual.html">Empty image with an Internal description</a></li>
+<li><a href="external-image-internal-description-girt-by-spaces-manual.html">External image with an Internal description (with extra spaces)</a></li>
+<li><a href="external-image-internal-description-manual.html">External image with an Internal description</a></li>
+</ul>
+
+
+<h3>Longdesc value as a fragment in an external resource</h3>
+
+<ul>
+<li><a href="data-uri-image-external-description-fragment-manual.html">data:URI with External description fragment</a></li>
+<li><a href="empty-image-external-description-fragment-manual.html">Empty image with an External description fragment</a></li>
+<li><a href="external-image-external-description-fragment-girt-by-spaces-manual.html">External image with External description fragment (with extra spaces around the URL)</a></li>
+<li><a href="external-image-external-description-fragment-manual.html">External image with External description fragment</a></li>
+</ul>
+
+
+<h3>Longdesc value as external URI in presence of <code>&lt;base&gt;</code> element</h3>
+
+<ul>
+<li><a href="external-image-with-relative-base-external-description-manual.html">External image with External Description (relative base element set)</a></li>
+<li><a href="external-image-with-absolute-base-external-description-manual.html">External image with External Description (absolute base element set)</a></li>
+</ul>
+
+
+<h3>Longdesc for an image within an iframe</h3>
+
+<ul>
+<li><a href="iframe-discoverability-manual.html">Image in an <code>&lt;iframe&gt;</code> with External Description</a></li>
+</ul>
+
+
+<h2>Automated tests</h2>
+
+<p><a href="reflected-changing-longdesc-manual.html">Longdesc value updated by javascript</a> tests that the HTML attribute reflects changes made by javascript. To pass, the browser must redirect to the "Longdesc test Pass Page" which has the word "Pass" as a heading, followed by a description of the image. Displaying the "Longdesc test Fail Page" would indicate a failure of this test.</p>
+
+<h2>Validation / Repair tool tests</h2>
+
+<p><a href="invalid-longdesc-manual.html">Invalid long description (plain text)</a> contains an invalid long description (plain text) and can be used to test User Agent and validation tool handling. <em>NOTE: Handling of invalid longdescs by user agents is currently undefined.</em>
+<a href="empty-longdesc-manual.html">Invalid long description (empty attribute)</a> contains an invalid long description (plain text) and can be used to test User Agent and validation tool handling. <em>NOTE: Handling of invalid longdescs by user agents is currently undefined.</em>
+<a href="fail-fragment-pointer-manual.html">Pointer to an invalid long description (not contained in a well-formed fragment)</a> points to a long description in a <a href="fail-fragment-pointer-manual.html">page fragment whose target is an empty element</a>. Validation tools should at least generate a warning, since an empty element is almost certainly not an adequate description, and is likely instead to reflect not passing the relevant authoring requirement.</p>
+
+<h2>Test results</h2>
+
+<p>Preliminary <a href="test-results.html">test results</a> are available for some platforms. More results are welcome.</p>
+
+<h2>Supporting files</h2>
+
+<p>The following files are required to make one or more of the tests work:</p>
+
+<ul>
+<li><a href="README.html">README.html</a> - this documentation</li>
+<li><a href="fail.html">fail.html</a></li>
+<li><a href="pass.html">pass.html</a></li>
+<li><a href="fail-fragment.html">fail-fragment.html</a></li>
+<li><a href="pass-fragment.html">pass-fragment.html</a></li>
+<li><a href="picture.png">picture.png</a></li>
+<li><a href="rebased/picture2.png">rebased/picture2.png</a>)</li>
+<li><a href="rebased/fail.html">rebased/fail.html</a> (actually a pass page, used to test what happens in the presence of a <code>&lt;base&gt;</code> element)</li>
+</ul>
+
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html-longdesc/data-uri-image-data-uri-description-manual.html b/tests/wpt/web-platform-tests/html-longdesc/data-uri-image-data-uri-description-manual.html
new file mode 100644
index 00000000000..5166dfc292a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html-longdesc/data-uri-image-data-uri-description-manual.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Longdesc test: data: URI image, data: URI description</title>
+ </head>
+ <body>
+ <img src="data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%01%B2%00%00%01%07%04%03%00%00%01N%5D%EE%7F%00%00%00%04gAMA%00%00%AF%C87%05%8A%E9%00%00%00%1BPLTE%F8%FC%F8%00%00%00%F8%E8%B8%00%FC%F8%F8%00%00%00%FC%00%F8%90%40%00%00%F8%F8%00%F8d%FA%E4%E4%00%00%00%07tIME%07%CF%0B%01%07%1E%01E%0FIy%00%00%00%15tEXtSoftware%00XPaint%202.4.9P%0E%BDz%00%00%10%AFIDATx%9C%ED%5DKs%E3%B8%11f%AB%A6%A6rlH%8Aj%8E%B2f%B6r%5D%8D%92%BB%9Dh%EF%BB%D9%F2%DDs%F19%95_%B0%B9%ED%CF%0E%F1~%10%20%1B%20%40S%2Auy%3C%B2%40%E0%C3%87G%A3%D1x%B0%EB%1A%09v%80%FD%AF9%02c%D1%FB0%18%8B%AB%9E%F1c%E8%7F%882%E8t%3Ay%C1n%E4%EE%EB%E5%BB%0Er%13%92%9F%9Fv%DF%9Dg%99%0F%FE%ED%97%7F%A7sm%93%8D%08c%2C%1D8K%BC%B2%D8%06%81nI%C2h%60X%25%5E%E0%15G%02_%9E%C7b%06%81%1D5%B0%7B~%19%09%3Cv%EFo%C9%40%D6%7DN%06%82%0C%8C%B70%86%5E%CCA%2B%FD%02%C9%A6%89%E8%85%8C%B5%E0%A6%82%A3%F8%0C%87%BD%21%F57%8E%84E%609%7F%88%3D%C7%12%1D%DA%A4%0F%FA%F7%E9t%F4b%99%E0%FEgw%F9Y%FE%A1%BA%AC%1B%7C9%FFl%13%0A%BA%D9%F5%F5%E7d%A6%2F%97t%18c%F3T%DC%B48%3DN~r%0A%C9%E9%AA%C3%B0%91x%9F%AEea%FB%FDs%F8%95%13%EF9%F2%AD%0AK%86%F4%F2%04%EF%A92%ECq%92%FD%97%F7%D0d%D9%F7%1D4%897%3E%A8%0C5%BD%CD%CB%07J~%2B%1B%C6h%C7%20%912%19P%28E%F4%F2%1C%27%0C%CC%B4I%00%04%ADI%A6JGg%04%99%CD%13%8C%E1%0C2%E8%A6%D2%89%CEe%D4%11%1F%D1%7B9%86h%E0%E9P%D4%B1d%CCX%BC%40BC%C0%E6%E1%DB%F5%97%D7%DF%FDx0f7%E8%8CG%E2%91%E4%C4%A5%20%5E%9F%A9R%F5%08%F9f%90%8A%912%1Ac%DF%1F%DE%7Dy%8B%25%CB%8E%91%C4"%C0%E1%23%85%F10V%93%84x%9F%AE%11%05%3C%1D%0F%F6%D7%EB%D0%82"%E0%F5%F1%AE%D1%80%09%D9%BF%5CC3%91%16%EF%9F%D8%25%AAh%5C%8E%FD%BF%3Ebf%2C%A9%5B%40%C7%23%E7%B8o%F2%BC%ED%BE%FF%C8%C4%EBu%207%8E%24%3Fz%F9%40%27%9AKr%A6%84%5D%17%D7%0Ci%135%01%C4SaV%017%9B%A7%DC%AE%D8J%A0%D7%1F%D9zv%83%86%C9%8F%01%8A%29eR%2B%8ED%1C%95Hz%AD%EC%0B%98%9CT%94%04%9903%1C%3B%7FO%E2%B1%F0%8BxD%90%DD%0F%F5%0F%A8%87Q%7F%8A%83%19%C3%C6%26%A3%CC%8D%D1%CC9%26%89%26%C7l%B4d%8F%97%93%25mG%C9%89%13w%90%84%60%1Ba%0783%2AE%00%D0E%14A%3AA%11%8D%5B9%DFc%A6%5D%A4v%ECW%9B%CB%CE%8F6%14%A1%8B%FA_%ACs%D0%CE%01Z%87%5Ee9%9F%DD%3E%B1%B9%9C%2F%BB%EF%0E%B7D%AE%82%D0%CD%DF%AF%FFx%8Dq%83%A8%E1%A3%BF%1BDKE%F0%A3F%A2M%89%88%16V%00MDu%FF%94%1D%8D%1B%7D%25f%DF%0Cc%B1%CC%CD%C8%B0%0C%EE%D7%DCh%CC%FB%AF%96D%92%0B%AC%D9%98%C9%13%B5f%BD%B9%F2%5B%14l%FB%9F%B2h%85h%85%D1"_%12%A2%C5%1C%88%D3%D1%A2%E6%2F%29%DA%B0%FD%90%A2%3D%7Fp%B4I%81k%D1%94%80G%1B%F3%E1%A6%A4%0C%AD%EB%99yhD%ABe%8F%A2%7F%0D%5Cb%E3%C2%F8%EC%E3%B3%9E%B5%D0%0D%A4%CD%93%80%CB%9CD%C8%F4%B3%A3%F5%03%3D%E3s%E1l4%C6%07%FF%DC%19%99%1C%1D%B2%A3%A1%40%FB%9C%88%96%D2%AD%DC%FE%02%CE-%1E-%AD%C9E%C8_%FE%18%09L%0A7%9B0V%D5%C8K%2C%9AS%D4%ABY%D9%26td%99%8B%10%27%07%86%5BI%C0%8CCf%CANy%C8G%89c%3E%15x%CF%C8%20%A9%80%A2%E4%D2mi2%BD%B2%D9%E60YrY%8D%AEF%0F%A4J%2F%A1%262%BAnV%1D%B0%1AZi%21e%D5%84Q%AB%A5%EE%89%C1%F2%27%EA%F4%40%CCZ%EA%EAC%F0%3FA%17%ACdb0%9F-%07%D2%B3w%F1%89%89%95i4e%AB%96%2BPg%C2%ACit%D4%82%B4%23%93Y%D81%03%0F%A7%108%B4l%CA%E0%7CKg%E3%7C2%20%A8%FF%F3Vk%FC%CC%14%0D%BC%F6it%B3%2BU%09%98%87P%E9%1B%F7%F1xz%CCJ%14%8D%A7%20%FDx%F2%1BpI%84%A5%E9f1%B6%9C%B9y%D2X%DB%A7%09z%2A%5E%CA%2F%12%3E%17%FBk%F3uw9%EF%84%0Bb%0A%CDV%04%C5%85%20%9E%D4%C5e%D1.%DC%01%D4%03%C6%D0%D0%CBe%DC%94%19%2A%17%86%FAIf%3A%A1F%93%CC%E2%DC%26%08%8Ci%B1%98%7B%B1G%EBg%3C%FFz%7D%7D%FD%3DZ%92%C9%F4%28%23%DC0%EE%04%9A%8F%98%BD%1A%10f%96%806O%BCN%DE%1C%ADs%8Bd%F3%F5rI%B7%92%DA"%BD%B4B%16%40%93%5D%B5%CC%E3W%0C%95%D0%93%0D%A5%D5%D2F%04%A9%2F%C9%E5%D0%04%E2%A2h%95%2C%E3%40%D8%84%D00%FB%B2%27%99%96u%D0%18%B0%EDi%FA1.%87d%00%B90%B1%1F%ED%89%7B8%2A%A0%01%5B%92%5B%3F%3C%2F%88%D6%D7%EF%86%F8h%0D%B4%97%EB%9E%E8%8C%AD%80%F6%89%3BUi%DE%D8%0Ah%7B%81Fr%E2VB%DB%D3%F6%9E%CCGC%BE%AD%26%EA%EB%D72%A5Dr%D4%09%DB%0Bj%23%15WS%E9%82%AA%B7%12%A7%7D9Z%D1f%A3%7C%E9%D1D%2FH%E7%A7%26%DA%A7%EB%8B%A8%5E%B1%5C%17%AB%E8%BA%83%F3U%8D%00ry%D0%5B%B1%AF%8A%23e%A3%0C%D0%CF%02-%7BCT%96%F46%D3F%CD%E7%0F%CD%D1%A4KA9GZ%A3%89S4%8C%EF%C7%E0%D3%7F%08%B7%C05%B0%A6%ACO%0B%82V%D2%00%0B%11%B4%BD%FB9w%97%5E%FE%A4%13%F8L%9E%EF%B4%03%F0%D0%26%7D%0D%D8%E5%EF%16%00%EEUS%0E%9B%F7%1F%B1%0D0I%29%29t%A6v%ED%F0%8F%7Ft%B6KS%D2%F2%1D%23%04%01%B0%05bZ%0B1%AAv%8A%C1%D4%C6.%1BCg%0F%AD%D3%A6%E1%B4%C5%5D%E4%AD%0B%13%9D%B6Z%3F%14%DF%CB%F4X%5E%7B%C8C%EEU%60%91UZ.%11U%D3%08%2F%E9%8B%2BQe%E3%C3%EC%A8v%2CP%D5%98%F6%F7L%D7Nvqb2%0E%A5%A4%F2%D6%9F%CD%12%5Eq2%B9x%2A%96%9D%B1f%FAh%CB%F0%CA%85%5E%10u%F0%88%A5%11%DFE%9E%2F%C5%C5%D9%DC%B0%BA%194%7D%81%01%29%D6%DC%D6%9B%B7O%81%C8m%F4%06%06za%10%D0%EC%AE%08%E4%BE%E6%C8%3E%9BDBEh%A8%16%C0%A93%88%3C4%E6%07%C2%F0%A1%A0%5C1%92%C5%2C49%23%02%B9UbP%B4~%BC%8C%3D%18%3E%1A%A8Y%1E%EA%1D%05%E8%EC%CD%90Y%09a%F2%9B%B5%5E%9A%D3%5B-%0C%8E%BB%83D%7F%0A6%BBx%FB3%28"%8B%C2pp%E6mz%5B%87I%0B%07h%85%04%9D%88%A1%03-%A6r%D1o%F9t4L%FD%09%CE%BF0%2C%98%1B%E7rsJK"%C8%FD%25%E2%B3%293%0C%D3%C50%F6%94%04%8DW%14%9B%DC%DC%A2%D1%24%90%29h%97O%886%E9%28%07%3Fc%FE%EEWu%F2%9C%E9%83Rn%1A1%A7%C8%D6%AE%AE%1F%93%F4%3C%F5%E763%0B%E4f%C1%E6p%80f%A8%C5NDx%98%96M%2C%21G%98QV%03%B4%9D%DE%A7%10C%1Bz%8B%B5%12%9E%A8x%88%AFg%F7h%E7%CBe%B7%BB%EC%A6%D04%24%D2%D4C%D4%CE%DA%EEv%E7%DD%8E%84f%EA%02h%8B%2F%11%C8-%07%DA%EDX%1C%AD%0BUQ%1C%C3b%839%E3%1B%B5%E9%B7%02%2C%C5%AD%F3%00%E2%7B%9E%06_%3A%1B%BE%87%DC%CE%12-%DAJLr%A9%82K%98%A5%29k%B5G%E3%27%F3%D8.%C9mD%C6%2A%2F%1A%B4%DD%E9%7DA1%B4%D11w%C2%BA%87%C8%C7q%B4t%8A%04%CB%DE%3EBE%8B%E0e%9C%C8%D3q%E9hN%ED%E4%9F%25%0Fm%09%02ZgM%93l%09%3C%C14%B4%19%E2%15zs4%AF%3D%8D%8F%01u%C4V%C2%12hV%EC%D8%FD%D3%A2h%25W%A7%E4J%F6%EE%A3JxK%60-%89%E6%EE%C4n_%92%0F%B4%9BG%FB%ED%BE%B8yX%CD%BB%DC%1D%A2%85%18%A1P%0D%2AZ%EE%C2%13%FF%A1%D0%D0%80h%81%D5%E1%C6%9F%3C%92%9E%EC%92%FBj%E8%FBD%D8%F4%DC%B9%26%1A%B2%ED%7F%97C%A3%EF%B2%AD%85v%5C%0C%0D%D8iAn%C06%DF%96Ccls%5C%12%8D%3Ah%DC%1AZ%AF%B7%AE%40%F4%3BV%E0%C6%AF%AE%23%EEz%AD%81%26v%BD%92%C8%DD%28%1A%A9%28%2B%A0elW%AE%84%B6_%98%1Bis%F4l4%E0h%2F%8B%A1%E1%24%B7%29%83%24%C74%D1h%CB%ECB%40Y%90%0B%A3-s%3E%60Y4Ph%CF%8B%A2-%CBm%B1s%1D%2F%2Cz%1Dl%13%E1hb%FC%5EB%18G%E3%9B%EF%E4I%8B%C6%60%3D%DAVh%A7%F7%F6G%1F%80%21%BC%9Cz%2B%08%D8%A1%3D%1AW%A4%E2%5C%07hr%0D5%18_%85%EA6OG%E0eyh%7Df%85%0F%12%B8y%12%09%2B%B4%B7%86hb%29O%EC%96%E9T%ABl%8D%A6%EF%1Fg%CD%D1%E4%E9%18%266s%CA%A2l%8A%26n%D6%92%1BJd%27x%9B%8CT%2A%80%E2%98%85X%D3%E6o%B8%F9%DC%B4%07%C8%9BY%B8sF%2C%00%B3%EC%132%D9h%D6%F3%E4%A3%D5%D7%D2%3D%1A%E3we%A3%D8%12-%EA%CDh%AE%26h%CA%FF%27%FE%CAF%CB%DBM%09%8C7%10D%F9%B6%17%D9%263%D0r%3D%93%AC%D3%17%06%F3%1F%3C%E4%B4%92%C8%E6%B6%294%E8%CC%BD%C2%3DZfw%CB%DD%B1%275%97%ECn%7D%C1%BCg%F8%17%BA.~%0F%DF%18%1A%27%D7%D7%9A%28O%D6%7D%F9_%96%978%17M%1CFS%1B%DE%7B%E4%2Fy%3Ei%C8%DD-%A7%12Gq%88%0A%DE3%BC%D12%1E%CBj%2C%20%CAR%A8f%8DF%27%27%2FD%CCx%7F%98%F1%60s%94%5C4%E7%CE%2B2%1C%82%F6%9B%ABe%05z%E4%7Ca%12%07%B5%82v%2F%BC%AE%2F%20%19%A9%5D%0F%B2%95%B4%B4%D2%DD%86X%93%5B%E2~%27%8B%15%5C%D8U%01%D04B%B9%A5%D1o%14%92%E72%F3%9D%87%3C%E4%21%0Fy%C8-%CB%D0%8F%FD%D19%9A%25S%9E%F8%85%F6%AEU%94%1C%1Bz%B1%CA%9Bu%90%12%CA%1AY%DB%B3%CC%1A%A4%18f%5E%CFY%E0%25%9F%5D%CA%5C%1D%8BT%27%5B%8D7%5Di%14j%5E%EB%BEY%ACa%A7s%CF%F8%8C%EBfh%A4%B9%AB_%3E%ADd%24Qg%0F%DD%02%FB%1EkC%2C%7D%C4%7CL%EA%92%A3%CD%2A%17%9B%7BV%24G%DC%C2%B8%5C%CDVSP%ABcVk9%99%D8%CC%DA2%F3un%A5%96OL%A6%F0%CDb%94%0Ch%27%AE%FD%A6R%C2%B4%C7%88%CC%0A%ADH%3F%23%95%0A%91%C8%8C%96_s%E2%5C%1DZ%CEr%D8%9B%0F%ABb%26%CF%E7%82%D7%A2%5C%27%2C%21%B3l%F0a%A6Ta%A6h9%F9%0F%2C%0A%B1%04%3Fj%C9%98R%A9%A6%AB%88%03%F5%F01%90%EBn%CC9%95%EE%E6%C9%CF%9Fn%A0%E9%81%D8%14%5D%3D%EF7%ED%29%09%DC%F7%1B%F3%2Aw%A6%8E%F8%9Be%066%CE%8C%25%82%3A%15y%2C%B4HF%DF%D4%80%CAK%A3%AE%92bN%26%18%AA%95%2C%B4U%16a%26%0E%5B%8B%C5%1D%0C%82%BC"%B5%C4%2A%0E%9C%26%25%9D%BAVh.%86%D4u%EE%83%FC%17%B2%CEe%E6M%CD%BD%06%EA%1Fq%1F0%8B%5C%3ARC%EC%2A%8FM%1D%BB%A0%F0%3C%CD%A7%EFG%D1w5%E8%CCx%9D%11%DDDY7%C2%CC%AF%A5%FA%CC%20lJ%1E%04x_%A4%98%B9%7D%C4c%E6h%19%93NB%17%D6g6x%FB%89%078%28t%D0%8A%03F%999%2C%D0%0FI%DD%60R%9D%D9%A0%ED%C5%98%C9%F5V%B3%0E%0A%EAY%3B%1C%0F%3E%C9dA%27%11%01%0C%99%D4g%E6rC%FB%BD%82%B3w%F4%281%95h%99%81V%ED%E6%83zN%AE%7B%83_I%B6%A2%7D%19%FC%7D%8A%0AE%83%A2%F9m%DEz%EF%7C%AF%F3%17%AE%E8%9A%F6%05%A6b%E4%EF%B4%AD%E8%A9%D6%E1%5D%0A%5Ev%ACTa%96%86%D0%03%97%C53OL%F1qD%ED%1D%F0%0Bn%9A%D9%D3%25%94%F3%3Cf%E0%7D%04_%C7%18f%25%03%AB%BF_%21%28%93%18%B3%5DO%E6%C2vg%C6%FA%9F%FE%23%8DY%A0%83%9D%00%BF%DF%A1%3Frwe%A4Tl%86%C9%2AN1%3B%EF%04%27%5Ecs%99%05%D3%0Ai%FE%06%B1%CA%25%99%B3%183~S%D1%F9r%CEd%96%B8A%C7%F9.%9B%05a%3D%D0%DA3%A1%F1%1Fe%B6%3B%170%8B%99%20.~%86%EBvt%FE%A5%28%8AG%DC%9Bs%C3v%19%D5%20%86W%01%B3y%CEg%B2c~%F8%60%F8E%94%D9%99%BFRO%F73%AAn%F4ty%89%07%3F%DF%A53%EA%2A%AD%A7%F5%E7x%1Df%D4sr12%C6L%9D.%BB%BCJ%A1%8Ege%0B%9E%15%5C%D4Q%E0%81%BA%9A%C1%AC%CB%5CW%AD%B8%86%16%A9%F3%CA%CC%B8%8C%D8%7B-%17%D0%C2%8Ak%C0L%88C%8F~Q%DE%5C%F1PZ1%FB%20qZ%E5%B0y%DE4%B3%CE%92%BB%3Ff%5CX8%BD%E52c%16%B3%2A%89%B8%A2OO%A1%1D%CA%D8%0D2%1BJtN%FDz%B7%CC%EE%A2%CE%3Am%CE%DE%CD%3EIO%7C%5E%F7Q_B%EE%B0%CA%00%93%F2%D1Y%9B%29%0Ff%B7%27CfR%85%DC%23%B3%5E%FE%FA%EB%BD2%BB%D3%D6x%0F%CC%40%F7%AA%A8%DC2%B9%91%FA%BA%F1j%1BZ%8Ba%B55%04%AE%97%F6a%EA%F2%CF%09%A9xO%8Cr%27%D7"%B7%1Ef%D2%B3%C5%D8%B6Z%8A%5C%F2m%DDC%F5KF%40%F0"%DF%E8I%94Cv%D1%D7g%C6%A4B%3E%FD%8Dx%7D%28MV%C1L%D6Y%E5%1B%E5%D7%C0%0C%B5%0F%89z%E7%2BI%D6%C0%0CD%95%C1%5D2%E3%CDq%7B%3A%91%AE%83%A4%CA%2A%98%09%E5%88%95_%DC%B0%06fL%0Eh%C7%BA%A9%AE%82%99%A0%06%C7%BA%A9%AE%84%19%A7v%AC%7Bbl%05%CC%F8%ED%CDl%7F%E5w%01%BFT%F4%FE%AD%80%99%B8nR%ADj%BDT%B4%F8W%C0%0C%AEV%5E%AA%A5%BA6f%F5%EE%E5%5D%033vmQik%60%B6%BF%7Bf%FB%AA%3A%E4%C3%99%F5c%98%C7%ACZG%FBpf%60%98%BD%D4U%21%F9%DE%82%CA%1E%2C%60%FA%BE~Us%25%83%F5%3A%BD%85%9A%99n%93%25%2Ad%A5%CCp%EFVYQ%A5%AD%93%19%84%CC%0A%2Am%9D%97%F0%0D%98%15T%C0%3A%99q%83xnk%BC%11fw%D3%1A%7B%BD%CF%F9%3C%EFQ%8Fk%F9%CDq%A5%CC%A4E%FC%2C%96%C4%7BrE%B7%04%ADS9%A2d%26%2F%9F%E6%F7%94%DB%D5.z%1A%0D%F3W%2A%9C%0Co%86%5B%EE%06%91%E2%AE%F8L%1C%21Y%F1%EE%29%DE%04ysd%A7%A38%98%C6%D9%1Dh%8BY%2Bd%E3%88%20%D6%F1%B7%B8m%8E%F2p%FF%A0%D6%C8G%B0V%25b%E5%9B%2B6%EE%D3%07%7D%B4%D1%A7%96%AC%B4%B5%2AD.jM%1F9%B3%A7%23%EA%B3%9EA%83L%D5%CD%CA%99%E9%17D%9C%9E%D45%ED%82%2A%B2%9Bg%D6%E9%13%AD%08%A0%0F%1F%8BwT%1Cn%9A%99%AC1y-%88b%A6%8E%B6z%95v%9B%CCD%0D%81%20%26_5%80%3A%E80%C9l%C5%CAQ%ED%09%12%2Fd%01%E0%2F%BF%90%97%17%A8%D7%1C%1Cnw%40C%7D%A6%95%BF%D3%86%2F%C8%A0%F3%3A%05%D0%CC%D2%26%D6%BA%99q%E1%EB%D4b%05%CD%B9%3F%A7%1F%C0%0F%89%C6%08k%B6%A9%84%80%DD%A06%7CC%C3%18%B3Er7G%005%19%BF%0A%C4%A7%BE%16S%DD%EC%16%98%89%E1%8C%09%DD%C8%2F%1F%40%F7%3A%A7%D6%CC%EA%DE%3C%1B%08%8A%DDq%E2%1E%94%9E%25%13%B7%5E%E9%BBvz%15%A2%94%FE0O%F3%91y%8F%86%86w-"%9AK0%D4%BEPs%EB%04%9A%B1%3A%A2%F4%AB%E4%08%B0%293%91%B6%B6%ADP%DF%E8%C2%5B%A7%AA%B2%1F1%05X%23G%D0%F6M%21%A8j%8D%BF7P%FCt%FAn%171%0C%7C%F93%BE%C5%B7%063%D6V%13%E9%7C%0B%EB%03%E556%D2%20%E6%26%E5%9F%8A%D8%E0b%93%2A%AD%88%B5%D5%B12%DB%28%60P_%3C%24v%A0w%F0C%BBEt%AD%D5%1D%A0%99%BD%F3%A3Se%0B%15%C9%8A%CD%E6%CA%12%D6w%01%AA%F9%28%FC%F8%F1%86%5E%A5%D5%ED%F0j%C4%E1%BFA2%C3%AAJE%D6%08%9A%0B%95%C04%D1%9E%196d%06%F6%B8%BCh.%7C%3CeUo%7Bg%2A%E3%E6%8EC%DD%FA%D4%D1%87F%CC%EA%DF%0B%1E%C1%D0%03%99%F0%F5%C8%D6%C9E%DC%F3%E8%F5%B3%B5%DA%BFi%09NqX%02%01%B3%F5%DB%8B%03%01%A7%DD%057q%B9%03%DA%873%B3%D3%A7%9CX%8AW%E0%D0%16%03%80%AE%C4%0Fg%E6%89%E2%E7e9%F6P%B4%0F%D9%AFEi%AD%8BYJV%3E%29~%C8C%1E%B2%A8%FC%1F%80U%F1%8F%E3%25%60p%00%00%00%00IEND%AEB%60%82" alt="the image" longdesc="data:text/html;charset=utf-8,%3C%21DOCTYPE%20html%3E%0D%0A%3Chtml%3E%0D%0A%20%3Chead%3E%0D%0A%20%20%3Ctitle%3ELongdesc%20test%20Pass%20page%3C%2Ftitle%3E%0D%0A%20%3C%2Fhead%3E%0D%0A%20%3Cbody%3E%0D%0A%20%20%3Ch1%3EPass%3C%2Fh1%3E%0D%0A%20%3C%2Fbody%3E%0D%0A%3C%2Fhtml%3E">
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html-longdesc/data-uri-image-external-description-fragment-manual.html b/tests/wpt/web-platform-tests/html-longdesc/data-uri-image-external-description-fragment-manual.html
new file mode 100644
index 00000000000..44b2ca3b093
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html-longdesc/data-uri-image-external-description-fragment-manual.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Longdesc test: data: URI image, external description in a fragment</title>
+ </head>
+ <body>
+ <img src="data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%01%B2%00%00%01%07%04%03%00%00%01N%5D%EE%7F%00%00%00%04gAMA%00%00%AF%C87%05%8A%E9%00%00%00%1BPLTE%F8%FC%F8%00%00%00%F8%E8%B8%00%FC%F8%F8%00%00%00%FC%00%F8%90%40%00%00%F8%F8%00%F8d%FA%E4%E4%00%00%00%07tIME%07%CF%0B%01%07%1E%01E%0FIy%00%00%00%15tEXtSoftware%00XPaint%202.4.9P%0E%BDz%00%00%10%AFIDATx%9C%ED%5DKs%E3%B8%11f%AB%A6%A6rlH%8Aj%8E%B2f%B6r%5D%8D%92%BB%9Dh%EF%BB%D9%F2%DDs%F19%95_%B0%B9%ED%CF%0E%F1~%10%20%1B%20%40S%2Auy%3C%B2%40%E0%C3%87G%A3%D1x%B0%EB%1A%09v%80%FD%AF9%02c%D1%FB0%18%8B%AB%9E%F1c%E8%7F%882%E8t%3Ay%C1n%E4%EE%EB%E5%BB%0Er%13%92%9F%9Fv%DF%9Dg%99%0F%FE%ED%97%7F%A7sm%93%8D%08c%2C%1D8K%BC%B2%D8%06%81nI%C2h%60X%25%5E%E0%15G%02_%9E%C7b%06%81%1D5%B0%7B~%19%09%3Cv%EFo%C9%40%D6%7DN%06%82%0C%8C%B70%86%5E%CCA%2B%FD%02%C9%A6%89%E8%85%8C%B5%E0%A6%82%A3%F8%0C%87%BD%21%F57%8E%84E%609%7F%88%3D%C7%12%1D%DA%A4%0F%FA%F7%E9t%F4b%99%E0%FEgw%F9Y%FE%A1%BA%AC%1B%7C9%FFl%13%0A%BA%D9%F5%F5%E7d%A6%2F%97t%18c%F3T%DC%B48%3DN~r%0A%C9%E9%AA%C3%B0%91x%9F%AEea%FB%FDs%F8%95%13%EF9%F2%AD%0AK%86%F4%F2%04%EF%A92%ECq%92%FD%97%F7%D0d%D9%F7%1D4%897%3E%A8%0C5%BD%CD%CB%07J~%2B%1B%C6h%C7%20%912%19P%28E%F4%F2%1C%27%0C%CC%B4I%00%04%ADI%A6JGg%04%99%CD%13%8C%E1%0C2%E8%A6%D2%89%CEe%D4%11%1F%D1%7B9%86h%E0%E9P%D4%B1d%CCX%BC%40BC%C0%E6%E1%DB%F5%97%D7%DF%FDx0f7%E8%8CG%E2%91%E4%C4%A5%20%5E%9F%A9R%F5%08%F9f%90%8A%912%1Ac%DF%1F%DE%7Dy%8B%25%CB%8E%91%C4"%C0%E1%23%85%F10V%93%84x%9F%AE%11%05%3C%1D%0F%F6%D7%EB%D0%82"%E0%F5%F1%AE%D1%80%09%D9%BF%5CC3%91%16%EF%9F%D8%25%AAh%5C%8E%FD%BF%3Ebf%2C%A9%5B%40%C7%23%E7%B8o%F2%BC%ED%BE%FF%C8%C4%EBu%207%8E%24%3Fz%F9%40%27%9AKr%A6%84%5D%17%D7%0Ci%135%01%C4SaV%017%9B%A7%DC%AE%D8J%A0%D7%1F%D9zv%83%86%C9%8F%01%8A%29eR%2B%8ED%1C%95Hz%AD%EC%0B%98%9CT%94%04%9903%1C%3B%7FO%E2%B1%F0%8BxD%90%DD%0F%F5%0F%A8%87Q%7F%8A%83%19%C3%C6%26%A3%CC%8D%D1%CC9%26%89%26%C7l%B4d%8F%97%93%25mG%C9%89%13w%90%84%60%1Ba%0783%2AE%00%D0E%14A%3AA%11%8D%5B9%DFc%A6%5D%A4v%ECW%9B%CB%CE%8F6%14%A1%8B%FA_%ACs%D0%CE%01Z%87%5Ee9%9F%DD%3E%B1%B9%9C%2F%BB%EF%0E%B7D%AE%82%D0%CD%DF%AF%FFx%8Dq%83%A8%E1%A3%BF%1BDKE%F0%A3F%A2M%89%88%16V%00MDu%FF%94%1D%8D%1B%7D%25f%DF%0Cc%B1%CC%CD%C8%B0%0C%EE%D7%DCh%CC%FB%AF%96D%92%0B%AC%D9%98%C9%13%B5f%BD%B9%F2%5B%14l%FB%9F%B2h%85h%85%D1"_%12%A2%C5%1C%88%D3%D1%A2%E6%2F%29%DA%B0%FD%90%A2%3D%7Fp%B4I%81k%D1%94%80G%1B%F3%E1%A6%A4%0C%AD%EB%99yhD%ABe%8F%A2%7F%0D%5Cb%E3%C2%F8%EC%E3%B3%9E%B5%D0%0D%A4%CD%93%80%CB%9CD%C8%F4%B3%A3%F5%03%3D%E3s%E1l4%C6%07%FF%DC%19%99%1C%1D%B2%A3%A1%40%FB%9C%88%96%D2%AD%DC%FE%02%CE-%1E-%AD%C9E%C8_%FE%18%09L%0A7%9B0V%D5%C8K%2C%9AS%D4%ABY%D9%26td%99%8B%10%27%07%86%5BI%C0%8CCf%CANy%C8G%89c%3E%15x%CF%C8%20%A9%80%A2%E4%D2mi2%BD%B2%D9%E60YrY%8D%AEF%0F%A4J%2F%A1%262%BAnV%1D%B0%1AZi%21e%D5%84Q%AB%A5%EE%89%C1%F2%27%EA%F4%40%CCZ%EA%EAC%F0%3FA%17%ACdb0%9F-%07%D2%B3w%F1%89%89%95i4e%AB%96%2BPg%C2%ACit%D4%82%B4%23%93Y%D81%03%0F%A7%108%B4l%CA%E0%7CKg%E3%7C2%20%A8%FF%F3Vk%FC%CC%14%0D%BC%F6it%B3%2BU%09%98%87P%E9%1B%F7%F1xz%CCJ%14%8D%A7%20%FDx%F2%1BpI%84%A5%E9f1%B6%9C%B9y%D2X%DB%A7%09z%2A%5E%CA%2F%12%3E%17%FBk%F3uw9%EF%84%0Bb%0A%CDV%04%C5%85%20%9E%D4%C5e%D1.%DC%01%D4%03%C6%D0%D0%CBe%DC%94%19%2A%17%86%FAIf%3A%A1F%93%CC%E2%DC%26%08%8Ci%B1%98%7B%B1G%EBg%3C%FFz%7D%7D%FD%3DZ%92%C9%F4%28%23%DC0%EE%04%9A%8F%98%BD%1A%10f%96%806O%BCN%DE%1C%ADs%8Bd%F3%F5rI%B7%92%DA"%BD%B4B%16%40%93%5D%B5%CC%E3W%0C%95%D0%93%0D%A5%D5%D2F%04%A9%2F%C9%E5%D0%04%E2%A2h%95%2C%E3%40%D8%84%D00%FB%B2%27%99%96u%D0%18%B0%EDi%FA1.%87d%00%B90%B1%1F%ED%89%7B8%2A%A0%01%5B%92%5B%3F%3C%2F%88%D6%D7%EF%86%F8h%0D%B4%97%EB%9E%E8%8C%AD%80%F6%89%3BUi%DE%D8%0Ah%7B%81Fr%E2VB%DB%D3%F6%9E%CCGC%BE%AD%26%EA%EB%D72%A5Dr%D4%09%DB%0Bj%23%15WS%E9%82%AA%B7%12%A7%7D9Z%D1f%A3%7C%E9%D1D%2FH%E7%A7%26%DA%A7%EB%8B%A8%5E%B1%5C%17%AB%E8%BA%83%F3U%8D%00ry%D0%5B%B1%AF%8A%23e%A3%0C%D0%CF%02-%7BCT%96%F46%D3F%CD%E7%0F%CD%D1%A4KA9GZ%A3%89S4%8C%EF%C7%E0%D3%7F%08%B7%C05%B0%A6%ACO%0B%82V%D2%00%0B%11%B4%BD%FB9w%97%5E%FE%A4%13%F8L%9E%EF%B4%03%F0%D0%26%7D%0D%D8%E5%EF%16%00%EEUS%0E%9B%F7%1F%B1%0D0I%29%29t%A6v%ED%F0%8F%7Ft%B6KS%D2%F2%1D%23%04%01%B0%05bZ%0B1%AAv%8A%C1%D4%C6.%1BCg%0F%AD%D3%A6%E1%B4%C5%5D%E4%AD%0B%13%9D%B6Z%3F%14%DF%CB%F4X%5E%7B%C8C%EEU%60%91UZ.%11U%D3%08%2F%E9%8B%2BQe%E3%C3%EC%A8v%2CP%D5%98%F6%F7L%D7Nvqb2%0E%A5%A4%F2%D6%9F%CD%12%5Eq2%B9x%2A%96%9D%B1f%FAh%CB%F0%CA%85%5E%10u%F0%88%A5%11%DFE%9E%2F%C5%C5%D9%DC%B0%BA%194%7D%81%01%29%D6%DC%D6%9B%B7O%81%C8m%F4%06%06za%10%D0%EC%AE%08%E4%BE%E6%C8%3E%9BDBEh%A8%16%C0%A93%88%3C4%E6%07%C2%F0%A1%A0%5C1%92%C5%2C49%23%02%B9UbP%B4~%BC%8C%3D%18%3E%1A%A8Y%1E%EA%1D%05%E8%EC%CD%90Y%09a%F2%9B%B5%5E%9A%D3%5B-%0C%8E%BB%83D%7F%0A6%BBx%FB3%28"%8B%C2pp%E6mz%5B%87I%0B%07h%85%04%9D%88%A1%03-%A6r%D1o%F9t4L%FD%09%CE%BF0%2C%98%1B%E7rsJK"%C8%FD%25%E2%B3%293%0C%D3%C50%F6%94%04%8DW%14%9B%DC%DC%A2%D1%24%90%29h%97O%886%E9%28%07%3Fc%FE%EEWu%F2%9C%E9%83Rn%1A1%A7%C8%D6%AE%AE%1F%93%F4%3C%F5%E763%0B%E4f%C1%E6p%80f%A8%C5NDx%98%96M%2C%21G%98QV%03%B4%9D%DE%A7%10C%1Bz%8B%B5%12%9E%A8x%88%AFg%F7h%E7%CBe%B7%BB%EC%A6%D04%24%D2%D4C%D4%CE%DA%EEv%E7%DD%8E%84f%EA%02h%8B%2F%11%C8-%07%DA%EDX%1C%AD%0BUQ%1C%C3b%839%E3%1B%B5%E9%B7%02%2C%C5%AD%F3%00%E2%7B%9E%06_%3A%1B%BE%87%DC%CE%12-%DAJLr%A9%82K%98%A5%29k%B5G%E3%27%F3%D8.%C9mD%C6%2A%2F%1A%B4%DD%E9%7DA1%B4%D11w%C2%BA%87%C8%C7q%B4t%8A%04%CB%DE%3EBE%8B%E0e%9C%C8%D3q%E9hN%ED%E4%9F%25%0Fm%09%02ZgM%93l%09%3C%C14%B4%19%E2%15zs4%AF%3D%8D%8F%01u%C4V%C2%12hV%EC%D8%FD%D3%A2h%25W%A7%E4J%F6%EE%A3JxK%60-%89%E6%EE%C4n_%92%0F%B4%9BG%FB%ED%BE%B8yX%CD%BB%DC%1D%A2%85%18%A1P%0D%2AZ%EE%C2%13%FF%A1%D0%D0%80h%81%D5%E1%C6%9F%3C%92%9E%EC%92%FBj%E8%FBD%D8%F4%DC%B9%26%1A%B2%ED%7F%97C%A3%EF%B2%AD%85v%5C%0C%0D%D8iAn%C06%DF%96Ccls%5C%12%8D%3Ah%DC%1AZ%AF%B7%AE%40%F4%3BV%E0%C6%AF%AE%23%EEz%AD%81%26v%BD%92%C8%DD%28%1A%A9%28%2B%A0elW%AE%84%B6_%98%1Bis%F4l4%E0h%2F%8B%A1%E1%24%B7%29%83%24%C74%D1h%CB%ECB%40Y%90%0B%A3-s%3E%60Y4Ph%CF%8B%A2-%CBm%B1s%1D%2F%2Cz%1Dl%13%E1hb%FC%5EB%18G%E3%9B%EF%E4I%8B%C6%60%3D%DAVh%A7%F7%F6G%1F%80%21%BC%9Cz%2B%08%D8%A1%3D%1AW%A4%E2%5C%07hr%0D5%18_%85%EA6OG%E0eyh%7Df%85%0F%12%B8y%12%09%2B%B4%B7%86hb%29O%EC%96%E9T%ABl%8D%A6%EF%1Fg%CD%D1%E4%E9%18%266s%CA%A2l%8A%26n%D6%92%1BJd%27x%9B%8CT%2A%80%E2%98%85X%D3%E6o%B8%F9%DC%B4%07%C8%9BY%B8sF%2C%00%B3%EC%132%D9h%D6%F3%E4%A3%D5%D7%D2%3D%1A%E3we%A3%D8%12-%EA%CDh%AE%26h%CA%FF%27%FE%CAF%CB%DBM%09%8C7%10D%F9%B6%17%D9%263%D0r%3D%93%AC%D3%17%06%F3%1F%3C%E4%B4%92%C8%E6%B6%294%E8%CC%BD%C2%3DZfw%CB%DD%B1%275%97%ECn%7D%C1%BCg%F8%17%BA.~%0F%DF%18%1A%27%D7%D7%9A%28O%D6%7D%F9_%96%978%17M%1CFS%1B%DE%7B%E4%2Fy%3Ei%C8%DD-%A7%12Gq%88%0A%DE3%BC%D12%1E%CBj%2C%20%CAR%A8f%8DF%27%27%2FD%CCx%7F%98%F1%60s%94%5C4%E7%CE%2B2%1C%82%F6%9B%ABe%05z%E4%7Ca%12%07%B5%82v%2F%BC%AE%2F%20%19%A9%5D%0F%B2%95%B4%B4%D2%DD%86X%93%5B%E2~%27%8B%15%5C%D8U%01%D04B%B9%A5%D1o%14%92%E72%F3%9D%87%3C%E4%21%0Fy%C8-%CB%D0%8F%FD%D19%9A%25S%9E%F8%85%F6%AEU%94%1C%1Bz%B1%CA%9Bu%90%12%CA%1AY%DB%B3%CC%1A%A4%18f%5E%CFY%E0%25%9F%5D%CA%5C%1D%8BT%27%5B%8D7%5Di%14j%5E%EB%BEY%ACa%A7s%CF%F8%8C%EBfh%A4%B9%AB_%3E%ADd%24Qg%0F%DD%02%FB%1EkC%2C%7D%C4%7CL%EA%92%A3%CD%2A%17%9B%7BV%24G%DC%C2%B8%5C%CDVSP%ABcVk9%99%D8%CC%DA2%F3un%A5%96OL%A6%F0%CDb%94%0Ch%27%AE%FD%A6R%C2%B4%C7%88%CC%0A%ADH%3F%23%95%0A%91%C8%8C%96_s%E2%5C%1DZ%CEr%D8%9B%0F%ABb%26%CF%E7%82%D7%A2%5C%27%2C%21%B3l%F0a%A6Ta%A6h9%F9%0F%2C%0A%B1%04%3Fj%C9%98R%A9%A6%AB%88%03%F5%F01%90%EBn%CC9%95%EE%E6%C9%CF%9Fn%A0%E9%81%D8%14%5D%3D%EF7%ED%29%09%DC%F7%1B%F3%2Aw%A6%8E%F8%9Be%066%CE%8C%25%82%3A%15y%2C%B4HF%DF%D4%80%CAK%A3%AE%92bN%26%18%AA%95%2C%B4U%16a%26%0E%5B%8B%C5%1D%0C%82%BC"%B5%C4%2A%0E%9C%26%25%9D%BAVh.%86%D4u%EE%83%FC%17%B2%CEe%E6M%CD%BD%06%EA%1Fq%1F0%8B%5C%3ARC%EC%2A%8FM%1D%BB%A0%F0%3C%CD%A7%EFG%D1w5%E8%CCx%9D%11%DDDY7%C2%CC%AF%A5%FA%CC%20lJ%1E%04x_%A4%98%B9%7D%C4c%E6h%19%93NB%17%D6g6x%FB%89%078%28t%D0%8A%03F%999%2C%D0%0FI%DD%60R%9D%D9%A0%ED%C5%98%C9%F5V%B3%0E%0A%EAY%3B%1C%0F%3E%C9dA%27%11%01%0C%99%D4g%E6rC%FB%BD%82%B3w%F4%281%95h%99%81V%ED%E6%83zN%AE%7B%83_I%B6%A2%7D%19%FC%7D%8A%0AE%83%A2%F9m%DEz%EF%7C%AF%F3%17%AE%E8%9A%F6%05%A6b%E4%EF%B4%AD%E8%A9%D6%E1%5D%0A%5Ev%ACTa%96%86%D0%03%97%C53OL%F1qD%ED%1D%F0%0Bn%9A%D9%D3%25%94%F3%3Cf%E0%7D%04_%C7%18f%25%03%AB%BF_%21%28%93%18%B3%5DO%E6%C2vg%C6%FA%9F%FE%23%8DY%A0%83%9D%00%BF%DF%A1%3Frwe%A4Tl%86%C9%2AN1%3B%EF%04%27%5Ecs%99%05%D3%0Ai%FE%06%B1%CA%25%99%B3%183~S%D1%F9r%CEd%96%B8A%C7%F9.%9B%05a%3D%D0%DA3%A1%F1%1Fe%B6%3B%170%8B%99%20.~%86%EBvt%FE%A5%28%8AG%DC%9Bs%C3v%19%D5%20%86W%01%B3y%CEg%B2c~%F8%60%F8E%94%D9%99%BFRO%F73%AAn%F4ty%89%07%3F%DF%A53%EA%2A%AD%A7%F5%E7x%1Df%D4sr12%C6L%9D.%BB%BCJ%A1%8Ege%0B%9E%15%5C%D4Q%E0%81%BA%9A%C1%AC%CB%5CW%AD%B8%86%16%A9%F3%CA%CC%B8%8C%D8%7B-%17%D0%C2%8Ak%C0L%88C%8F~Q%DE%5C%F1PZ1%FB%20qZ%E5%B0y%DE4%B3%CE%92%BB%3Ff%5CX8%BD%E52c%16%B3%2A%89%B8%A2OO%A1%1D%CA%D8%0D2%1BJtN%FDz%B7%CC%EE%A2%CE%3Am%CE%DE%CD%3EIO%7C%5E%F7Q_B%EE%B0%CA%00%93%F2%D1Y%9B%29%0Ff%B7%27CfR%85%DC%23%B3%5E%FE%FA%EB%BD2%BB%D3%D6x%0F%CC%40%F7%AA%A8%DC2%B9%91%FA%BA%F1j%1BZ%8Ba%B55%04%AE%97%F6a%EA%F2%CF%09%A9xO%8Cr%27%D7"%B7%1Ef%D2%B3%C5%D8%B6Z%8A%5C%F2m%DDC%F5KF%40%F0"%DF%E8I%94Cv%D1%D7g%C6%A4B%3E%FD%8Dx%7D%28MV%C1L%D6Y%E5%1B%E5%D7%C0%0C%B5%0F%89z%E7%2BI%D6%C0%0CD%95%C1%5D2%E3%CDq%7B%3A%91%AE%83%A4%CA%2A%98%09%E5%88%95_%DC%B0%06fL%0Eh%C7%BA%A9%AE%82%99%A0%06%C7%BA%A9%AE%84%19%A7v%AC%7Bbl%05%CC%F8%ED%CDl%7F%E5w%01%BFT%F4%FE%AD%80%99%B8nR%ADj%BDT%B4%F8W%C0%0C%AEV%5E%AA%A5%BA6f%F5%EE%E5%5D%033vmQik%60%B6%BF%7Bf%FB%AA%3A%E4%C3%99%F5c%98%C7%ACZG%FBpf%60%98%BD%D4U%21%F9%DE%82%CA%1E%2C%60%FA%BE~Us%25%83%F5%3A%BD%85%9A%99n%93%25%2Ad%A5%CCp%EFVYQ%A5%AD%93%19%84%CC%0A%2Am%9D%97%F0%0D%98%15T%C0%3A%99q%83xnk%BC%11fw%D3%1A%7B%BD%CF%F9%3C%EFQ%8Fk%F9%CDq%A5%CC%A4E%FC%2C%96%C4%7BrE%B7%04%ADS9%A2d%26%2F%9F%E6%F7%94%DB%D5.z%1A%0D%F3W%2A%9C%0Co%86%5B%EE%06%91%E2%AE%F8L%1C%21Y%F1%EE%29%DE%04ysd%A7%A38%98%C6%D9%1Dh%8BY%2Bd%E3%88%20%D6%F1%B7%B8m%8E%F2p%FF%A0%D6%C8G%B0V%25b%E5%9B%2B6%EE%D3%07%7D%B4%D1%A7%96%AC%B4%B5%2AD.jM%1F9%B3%A7%23%EA%B3%9EA%83L%D5%CD%CA%99%E9%17D%9C%9E%D45%ED%82%2A%B2%9Bg%D6%E9%13%AD%08%A0%0F%1F%8BwT%1Cn%9A%99%AC1y-%88b%A6%8E%B6z%95v%9B%CCD%0D%81%20%26_5%80%3A%E80%C9l%C5%CAQ%ED%09%12%2Fd%01%E0%2F%BF%90%97%17%A8%D7%1C%1Cnw%40C%7D%A6%95%BF%D3%86%2F%C8%A0%F3%3A%05%D0%CC%D2%26%D6%BA%99q%E1%EB%D4b%05%CD%B9%3F%A7%1F%C0%0F%89%C6%08k%B6%A9%84%80%DD%A06%7CC%C3%18%B3Er7G%005%19%BF%0A%C4%A7%BE%16S%DD%EC%16%98%89%E1%8C%09%DD%C8%2F%1F%40%F7%3A%A7%D6%CC%EA%DE%3C%1B%08%8A%DDq%E2%1E%94%9E%25%13%B7%5E%E9%BBvz%15%A2%94%FE0O%F3%91y%8F%86%86w-"%9AK0%D4%BEPs%EB%04%9A%B1%3A%A2%F4%AB%E4%08%B0%293%91%B6%B6%ADP%DF%E8%C2%5B%A7%AA%B2%1F1%05X%23G%D0%F6M%21%A8j%8D%BF7P%FCt%FAn%171%0C%7C%F93%BE%C5%B7%063%D6V%13%E9%7C%0B%EB%03%E556%D2%20%E6%26%E5%9F%8A%D8%E0b%93%2A%AD%88%B5%D5%B12%DB%28%60P_%3C%24v%A0w%F0C%BBEt%AD%D5%1D%A0%99%BD%F3%A3Se%0B%15%C9%8A%CD%E6%CA%12%D6w%01%AA%F9%28%FC%F8%F1%86%5E%A5%D5%ED%F0j%C4%E1%BFA2%C3%AAJE%D6%08%9A%0B%95%C04%D1%9E%196d%06%F6%B8%BCh.%7C%3CeUo%7Bg%2A%E3%E6%8EC%DD%FA%D4%D1%87F%CC%EA%DF%0B%1E%C1%D0%03%99%F0%F5%C8%D6%C9E%DC%F3%E8%F5%B3%B5%DA%BFi%09NqX%02%01%B3%F5%DB%8B%03%01%A7%DD%057q%B9%03%DA%873%B3%D3%A7%9CX%8AW%E0%D0%16%03%80%AE%C4%0Fg%E6%89%E2%E7e9%F6P%B4%0F%D9%AFEi%AD%8BYJV%3E%29~%C8C%1E%B2%A8%FC%1F%80U%F1%8F%E3%25%60p%00%00%00%00IEND%AEB%60%82" alt="the image" longdesc="pass-fragment.html#fragment">
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html-longdesc/data-uri-image-external-description-manual.html b/tests/wpt/web-platform-tests/html-longdesc/data-uri-image-external-description-manual.html
new file mode 100644
index 00000000000..56f9aa79e4d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html-longdesc/data-uri-image-external-description-manual.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Longdesc test: data: URI image, external description</title>
+ </head>
+ <body>
+ <img src="data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%01%B2%00%00%01%07%04%03%00%00%01N%5D%EE%7F%00%00%00%04gAMA%00%00%AF%C87%05%8A%E9%00%00%00%1BPLTE%F8%FC%F8%00%00%00%F8%E8%B8%00%FC%F8%F8%00%00%00%FC%00%F8%90%40%00%00%F8%F8%00%F8d%FA%E4%E4%00%00%00%07tIME%07%CF%0B%01%07%1E%01E%0FIy%00%00%00%15tEXtSoftware%00XPaint%202.4.9P%0E%BDz%00%00%10%AFIDATx%9C%ED%5DKs%E3%B8%11f%AB%A6%A6rlH%8Aj%8E%B2f%B6r%5D%8D%92%BB%9Dh%EF%BB%D9%F2%DDs%F19%95_%B0%B9%ED%CF%0E%F1~%10%20%1B%20%40S%2Auy%3C%B2%40%E0%C3%87G%A3%D1x%B0%EB%1A%09v%80%FD%AF9%02c%D1%FB0%18%8B%AB%9E%F1c%E8%7F%882%E8t%3Ay%C1n%E4%EE%EB%E5%BB%0Er%13%92%9F%9Fv%DF%9Dg%99%0F%FE%ED%97%7F%A7sm%93%8D%08c%2C%1D8K%BC%B2%D8%06%81nI%C2h%60X%25%5E%E0%15G%02_%9E%C7b%06%81%1D5%B0%7B~%19%09%3Cv%EFo%C9%40%D6%7DN%06%82%0C%8C%B70%86%5E%CCA%2B%FD%02%C9%A6%89%E8%85%8C%B5%E0%A6%82%A3%F8%0C%87%BD%21%F57%8E%84E%609%7F%88%3D%C7%12%1D%DA%A4%0F%FA%F7%E9t%F4b%99%E0%FEgw%F9Y%FE%A1%BA%AC%1B%7C9%FFl%13%0A%BA%D9%F5%F5%E7d%A6%2F%97t%18c%F3T%DC%B48%3DN~r%0A%C9%E9%AA%C3%B0%91x%9F%AEea%FB%FDs%F8%95%13%EF9%F2%AD%0AK%86%F4%F2%04%EF%A92%ECq%92%FD%97%F7%D0d%D9%F7%1D4%897%3E%A8%0C5%BD%CD%CB%07J~%2B%1B%C6h%C7%20%912%19P%28E%F4%F2%1C%27%0C%CC%B4I%00%04%ADI%A6JGg%04%99%CD%13%8C%E1%0C2%E8%A6%D2%89%CEe%D4%11%1F%D1%7B9%86h%E0%E9P%D4%B1d%CCX%BC%40BC%C0%E6%E1%DB%F5%97%D7%DF%FDx0f7%E8%8CG%E2%91%E4%C4%A5%20%5E%9F%A9R%F5%08%F9f%90%8A%912%1Ac%DF%1F%DE%7Dy%8B%25%CB%8E%91%C4"%C0%E1%23%85%F10V%93%84x%9F%AE%11%05%3C%1D%0F%F6%D7%EB%D0%82"%E0%F5%F1%AE%D1%80%09%D9%BF%5CC3%91%16%EF%9F%D8%25%AAh%5C%8E%FD%BF%3Ebf%2C%A9%5B%40%C7%23%E7%B8o%F2%BC%ED%BE%FF%C8%C4%EBu%207%8E%24%3Fz%F9%40%27%9AKr%A6%84%5D%17%D7%0Ci%135%01%C4SaV%017%9B%A7%DC%AE%D8J%A0%D7%1F%D9zv%83%86%C9%8F%01%8A%29eR%2B%8ED%1C%95Hz%AD%EC%0B%98%9CT%94%04%9903%1C%3B%7FO%E2%B1%F0%8BxD%90%DD%0F%F5%0F%A8%87Q%7F%8A%83%19%C3%C6%26%A3%CC%8D%D1%CC9%26%89%26%C7l%B4d%8F%97%93%25mG%C9%89%13w%90%84%60%1Ba%0783%2AE%00%D0E%14A%3AA%11%8D%5B9%DFc%A6%5D%A4v%ECW%9B%CB%CE%8F6%14%A1%8B%FA_%ACs%D0%CE%01Z%87%5Ee9%9F%DD%3E%B1%B9%9C%2F%BB%EF%0E%B7D%AE%82%D0%CD%DF%AF%FFx%8Dq%83%A8%E1%A3%BF%1BDKE%F0%A3F%A2M%89%88%16V%00MDu%FF%94%1D%8D%1B%7D%25f%DF%0Cc%B1%CC%CD%C8%B0%0C%EE%D7%DCh%CC%FB%AF%96D%92%0B%AC%D9%98%C9%13%B5f%BD%B9%F2%5B%14l%FB%9F%B2h%85h%85%D1"_%12%A2%C5%1C%88%D3%D1%A2%E6%2F%29%DA%B0%FD%90%A2%3D%7Fp%B4I%81k%D1%94%80G%1B%F3%E1%A6%A4%0C%AD%EB%99yhD%ABe%8F%A2%7F%0D%5Cb%E3%C2%F8%EC%E3%B3%9E%B5%D0%0D%A4%CD%93%80%CB%9CD%C8%F4%B3%A3%F5%03%3D%E3s%E1l4%C6%07%FF%DC%19%99%1C%1D%B2%A3%A1%40%FB%9C%88%96%D2%AD%DC%FE%02%CE-%1E-%AD%C9E%C8_%FE%18%09L%0A7%9B0V%D5%C8K%2C%9AS%D4%ABY%D9%26td%99%8B%10%27%07%86%5BI%C0%8CCf%CANy%C8G%89c%3E%15x%CF%C8%20%A9%80%A2%E4%D2mi2%BD%B2%D9%E60YrY%8D%AEF%0F%A4J%2F%A1%262%BAnV%1D%B0%1AZi%21e%D5%84Q%AB%A5%EE%89%C1%F2%27%EA%F4%40%CCZ%EA%EAC%F0%3FA%17%ACdb0%9F-%07%D2%B3w%F1%89%89%95i4e%AB%96%2BPg%C2%ACit%D4%82%B4%23%93Y%D81%03%0F%A7%108%B4l%CA%E0%7CKg%E3%7C2%20%A8%FF%F3Vk%FC%CC%14%0D%BC%F6it%B3%2BU%09%98%87P%E9%1B%F7%F1xz%CCJ%14%8D%A7%20%FDx%F2%1BpI%84%A5%E9f1%B6%9C%B9y%D2X%DB%A7%09z%2A%5E%CA%2F%12%3E%17%FBk%F3uw9%EF%84%0Bb%0A%CDV%04%C5%85%20%9E%D4%C5e%D1.%DC%01%D4%03%C6%D0%D0%CBe%DC%94%19%2A%17%86%FAIf%3A%A1F%93%CC%E2%DC%26%08%8Ci%B1%98%7B%B1G%EBg%3C%FFz%7D%7D%FD%3DZ%92%C9%F4%28%23%DC0%EE%04%9A%8F%98%BD%1A%10f%96%806O%BCN%DE%1C%ADs%8Bd%F3%F5rI%B7%92%DA"%BD%B4B%16%40%93%5D%B5%CC%E3W%0C%95%D0%93%0D%A5%D5%D2F%04%A9%2F%C9%E5%D0%04%E2%A2h%95%2C%E3%40%D8%84%D00%FB%B2%27%99%96u%D0%18%B0%EDi%FA1.%87d%00%B90%B1%1F%ED%89%7B8%2A%A0%01%5B%92%5B%3F%3C%2F%88%D6%D7%EF%86%F8h%0D%B4%97%EB%9E%E8%8C%AD%80%F6%89%3BUi%DE%D8%0Ah%7B%81Fr%E2VB%DB%D3%F6%9E%CCGC%BE%AD%26%EA%EB%D72%A5Dr%D4%09%DB%0Bj%23%15WS%E9%82%AA%B7%12%A7%7D9Z%D1f%A3%7C%E9%D1D%2FH%E7%A7%26%DA%A7%EB%8B%A8%5E%B1%5C%17%AB%E8%BA%83%F3U%8D%00ry%D0%5B%B1%AF%8A%23e%A3%0C%D0%CF%02-%7BCT%96%F46%D3F%CD%E7%0F%CD%D1%A4KA9GZ%A3%89S4%8C%EF%C7%E0%D3%7F%08%B7%C05%B0%A6%ACO%0B%82V%D2%00%0B%11%B4%BD%FB9w%97%5E%FE%A4%13%F8L%9E%EF%B4%03%F0%D0%26%7D%0D%D8%E5%EF%16%00%EEUS%0E%9B%F7%1F%B1%0D0I%29%29t%A6v%ED%F0%8F%7Ft%B6KS%D2%F2%1D%23%04%01%B0%05bZ%0B1%AAv%8A%C1%D4%C6.%1BCg%0F%AD%D3%A6%E1%B4%C5%5D%E4%AD%0B%13%9D%B6Z%3F%14%DF%CB%F4X%5E%7B%C8C%EEU%60%91UZ.%11U%D3%08%2F%E9%8B%2BQe%E3%C3%EC%A8v%2CP%D5%98%F6%F7L%D7Nvqb2%0E%A5%A4%F2%D6%9F%CD%12%5Eq2%B9x%2A%96%9D%B1f%FAh%CB%F0%CA%85%5E%10u%F0%88%A5%11%DFE%9E%2F%C5%C5%D9%DC%B0%BA%194%7D%81%01%29%D6%DC%D6%9B%B7O%81%C8m%F4%06%06za%10%D0%EC%AE%08%E4%BE%E6%C8%3E%9BDBEh%A8%16%C0%A93%88%3C4%E6%07%C2%F0%A1%A0%5C1%92%C5%2C49%23%02%B9UbP%B4~%BC%8C%3D%18%3E%1A%A8Y%1E%EA%1D%05%E8%EC%CD%90Y%09a%F2%9B%B5%5E%9A%D3%5B-%0C%8E%BB%83D%7F%0A6%BBx%FB3%28"%8B%C2pp%E6mz%5B%87I%0B%07h%85%04%9D%88%A1%03-%A6r%D1o%F9t4L%FD%09%CE%BF0%2C%98%1B%E7rsJK"%C8%FD%25%E2%B3%293%0C%D3%C50%F6%94%04%8DW%14%9B%DC%DC%A2%D1%24%90%29h%97O%886%E9%28%07%3Fc%FE%EEWu%F2%9C%E9%83Rn%1A1%A7%C8%D6%AE%AE%1F%93%F4%3C%F5%E763%0B%E4f%C1%E6p%80f%A8%C5NDx%98%96M%2C%21G%98QV%03%B4%9D%DE%A7%10C%1Bz%8B%B5%12%9E%A8x%88%AFg%F7h%E7%CBe%B7%BB%EC%A6%D04%24%D2%D4C%D4%CE%DA%EEv%E7%DD%8E%84f%EA%02h%8B%2F%11%C8-%07%DA%EDX%1C%AD%0BUQ%1C%C3b%839%E3%1B%B5%E9%B7%02%2C%C5%AD%F3%00%E2%7B%9E%06_%3A%1B%BE%87%DC%CE%12-%DAJLr%A9%82K%98%A5%29k%B5G%E3%27%F3%D8.%C9mD%C6%2A%2F%1A%B4%DD%E9%7DA1%B4%D11w%C2%BA%87%C8%C7q%B4t%8A%04%CB%DE%3EBE%8B%E0e%9C%C8%D3q%E9hN%ED%E4%9F%25%0Fm%09%02ZgM%93l%09%3C%C14%B4%19%E2%15zs4%AF%3D%8D%8F%01u%C4V%C2%12hV%EC%D8%FD%D3%A2h%25W%A7%E4J%F6%EE%A3JxK%60-%89%E6%EE%C4n_%92%0F%B4%9BG%FB%ED%BE%B8yX%CD%BB%DC%1D%A2%85%18%A1P%0D%2AZ%EE%C2%13%FF%A1%D0%D0%80h%81%D5%E1%C6%9F%3C%92%9E%EC%92%FBj%E8%FBD%D8%F4%DC%B9%26%1A%B2%ED%7F%97C%A3%EF%B2%AD%85v%5C%0C%0D%D8iAn%C06%DF%96Ccls%5C%12%8D%3Ah%DC%1AZ%AF%B7%AE%40%F4%3BV%E0%C6%AF%AE%23%EEz%AD%81%26v%BD%92%C8%DD%28%1A%A9%28%2B%A0elW%AE%84%B6_%98%1Bis%F4l4%E0h%2F%8B%A1%E1%24%B7%29%83%24%C74%D1h%CB%ECB%40Y%90%0B%A3-s%3E%60Y4Ph%CF%8B%A2-%CBm%B1s%1D%2F%2Cz%1Dl%13%E1hb%FC%5EB%18G%E3%9B%EF%E4I%8B%C6%60%3D%DAVh%A7%F7%F6G%1F%80%21%BC%9Cz%2B%08%D8%A1%3D%1AW%A4%E2%5C%07hr%0D5%18_%85%EA6OG%E0eyh%7Df%85%0F%12%B8y%12%09%2B%B4%B7%86hb%29O%EC%96%E9T%ABl%8D%A6%EF%1Fg%CD%D1%E4%E9%18%266s%CA%A2l%8A%26n%D6%92%1BJd%27x%9B%8CT%2A%80%E2%98%85X%D3%E6o%B8%F9%DC%B4%07%C8%9BY%B8sF%2C%00%B3%EC%132%D9h%D6%F3%E4%A3%D5%D7%D2%3D%1A%E3we%A3%D8%12-%EA%CDh%AE%26h%CA%FF%27%FE%CAF%CB%DBM%09%8C7%10D%F9%B6%17%D9%263%D0r%3D%93%AC%D3%17%06%F3%1F%3C%E4%B4%92%C8%E6%B6%294%E8%CC%BD%C2%3DZfw%CB%DD%B1%275%97%ECn%7D%C1%BCg%F8%17%BA.~%0F%DF%18%1A%27%D7%D7%9A%28O%D6%7D%F9_%96%978%17M%1CFS%1B%DE%7B%E4%2Fy%3Ei%C8%DD-%A7%12Gq%88%0A%DE3%BC%D12%1E%CBj%2C%20%CAR%A8f%8DF%27%27%2FD%CCx%7F%98%F1%60s%94%5C4%E7%CE%2B2%1C%82%F6%9B%ABe%05z%E4%7Ca%12%07%B5%82v%2F%BC%AE%2F%20%19%A9%5D%0F%B2%95%B4%B4%D2%DD%86X%93%5B%E2~%27%8B%15%5C%D8U%01%D04B%B9%A5%D1o%14%92%E72%F3%9D%87%3C%E4%21%0Fy%C8-%CB%D0%8F%FD%D19%9A%25S%9E%F8%85%F6%AEU%94%1C%1Bz%B1%CA%9Bu%90%12%CA%1AY%DB%B3%CC%1A%A4%18f%5E%CFY%E0%25%9F%5D%CA%5C%1D%8BT%27%5B%8D7%5Di%14j%5E%EB%BEY%ACa%A7s%CF%F8%8C%EBfh%A4%B9%AB_%3E%ADd%24Qg%0F%DD%02%FB%1EkC%2C%7D%C4%7CL%EA%92%A3%CD%2A%17%9B%7BV%24G%DC%C2%B8%5C%CDVSP%ABcVk9%99%D8%CC%DA2%F3un%A5%96OL%A6%F0%CDb%94%0Ch%27%AE%FD%A6R%C2%B4%C7%88%CC%0A%ADH%3F%23%95%0A%91%C8%8C%96_s%E2%5C%1DZ%CEr%D8%9B%0F%ABb%26%CF%E7%82%D7%A2%5C%27%2C%21%B3l%F0a%A6Ta%A6h9%F9%0F%2C%0A%B1%04%3Fj%C9%98R%A9%A6%AB%88%03%F5%F01%90%EBn%CC9%95%EE%E6%C9%CF%9Fn%A0%E9%81%D8%14%5D%3D%EF7%ED%29%09%DC%F7%1B%F3%2Aw%A6%8E%F8%9Be%066%CE%8C%25%82%3A%15y%2C%B4HF%DF%D4%80%CAK%A3%AE%92bN%26%18%AA%95%2C%B4U%16a%26%0E%5B%8B%C5%1D%0C%82%BC"%B5%C4%2A%0E%9C%26%25%9D%BAVh.%86%D4u%EE%83%FC%17%B2%CEe%E6M%CD%BD%06%EA%1Fq%1F0%8B%5C%3ARC%EC%2A%8FM%1D%BB%A0%F0%3C%CD%A7%EFG%D1w5%E8%CCx%9D%11%DDDY7%C2%CC%AF%A5%FA%CC%20lJ%1E%04x_%A4%98%B9%7D%C4c%E6h%19%93NB%17%D6g6x%FB%89%078%28t%D0%8A%03F%999%2C%D0%0FI%DD%60R%9D%D9%A0%ED%C5%98%C9%F5V%B3%0E%0A%EAY%3B%1C%0F%3E%C9dA%27%11%01%0C%99%D4g%E6rC%FB%BD%82%B3w%F4%281%95h%99%81V%ED%E6%83zN%AE%7B%83_I%B6%A2%7D%19%FC%7D%8A%0AE%83%A2%F9m%DEz%EF%7C%AF%F3%17%AE%E8%9A%F6%05%A6b%E4%EF%B4%AD%E8%A9%D6%E1%5D%0A%5Ev%ACTa%96%86%D0%03%97%C53OL%F1qD%ED%1D%F0%0Bn%9A%D9%D3%25%94%F3%3Cf%E0%7D%04_%C7%18f%25%03%AB%BF_%21%28%93%18%B3%5DO%E6%C2vg%C6%FA%9F%FE%23%8DY%A0%83%9D%00%BF%DF%A1%3Frwe%A4Tl%86%C9%2AN1%3B%EF%04%27%5Ecs%99%05%D3%0Ai%FE%06%B1%CA%25%99%B3%183~S%D1%F9r%CEd%96%B8A%C7%F9.%9B%05a%3D%D0%DA3%A1%F1%1Fe%B6%3B%170%8B%99%20.~%86%EBvt%FE%A5%28%8AG%DC%9Bs%C3v%19%D5%20%86W%01%B3y%CEg%B2c~%F8%60%F8E%94%D9%99%BFRO%F73%AAn%F4ty%89%07%3F%DF%A53%EA%2A%AD%A7%F5%E7x%1Df%D4sr12%C6L%9D.%BB%BCJ%A1%8Ege%0B%9E%15%5C%D4Q%E0%81%BA%9A%C1%AC%CB%5CW%AD%B8%86%16%A9%F3%CA%CC%B8%8C%D8%7B-%17%D0%C2%8Ak%C0L%88C%8F~Q%DE%5C%F1PZ1%FB%20qZ%E5%B0y%DE4%B3%CE%92%BB%3Ff%5CX8%BD%E52c%16%B3%2A%89%B8%A2OO%A1%1D%CA%D8%0D2%1BJtN%FDz%B7%CC%EE%A2%CE%3Am%CE%DE%CD%3EIO%7C%5E%F7Q_B%EE%B0%CA%00%93%F2%D1Y%9B%29%0Ff%B7%27CfR%85%DC%23%B3%5E%FE%FA%EB%BD2%BB%D3%D6x%0F%CC%40%F7%AA%A8%DC2%B9%91%FA%BA%F1j%1BZ%8Ba%B55%04%AE%97%F6a%EA%F2%CF%09%A9xO%8Cr%27%D7"%B7%1Ef%D2%B3%C5%D8%B6Z%8A%5C%F2m%DDC%F5KF%40%F0"%DF%E8I%94Cv%D1%D7g%C6%A4B%3E%FD%8Dx%7D%28MV%C1L%D6Y%E5%1B%E5%D7%C0%0C%B5%0F%89z%E7%2BI%D6%C0%0CD%95%C1%5D2%E3%CDq%7B%3A%91%AE%83%A4%CA%2A%98%09%E5%88%95_%DC%B0%06fL%0Eh%C7%BA%A9%AE%82%99%A0%06%C7%BA%A9%AE%84%19%A7v%AC%7Bbl%05%CC%F8%ED%CDl%7F%E5w%01%BFT%F4%FE%AD%80%99%B8nR%ADj%BDT%B4%F8W%C0%0C%AEV%5E%AA%A5%BA6f%F5%EE%E5%5D%033vmQik%60%B6%BF%7Bf%FB%AA%3A%E4%C3%99%F5c%98%C7%ACZG%FBpf%60%98%BD%D4U%21%F9%DE%82%CA%1E%2C%60%FA%BE~Us%25%83%F5%3A%BD%85%9A%99n%93%25%2Ad%A5%CCp%EFVYQ%A5%AD%93%19%84%CC%0A%2Am%9D%97%F0%0D%98%15T%C0%3A%99q%83xnk%BC%11fw%D3%1A%7B%BD%CF%F9%3C%EFQ%8Fk%F9%CDq%A5%CC%A4E%FC%2C%96%C4%7BrE%B7%04%ADS9%A2d%26%2F%9F%E6%F7%94%DB%D5.z%1A%0D%F3W%2A%9C%0Co%86%5B%EE%06%91%E2%AE%F8L%1C%21Y%F1%EE%29%DE%04ysd%A7%A38%98%C6%D9%1Dh%8BY%2Bd%E3%88%20%D6%F1%B7%B8m%8E%F2p%FF%A0%D6%C8G%B0V%25b%E5%9B%2B6%EE%D3%07%7D%B4%D1%A7%96%AC%B4%B5%2AD.jM%1F9%B3%A7%23%EA%B3%9EA%83L%D5%CD%CA%99%E9%17D%9C%9E%D45%ED%82%2A%B2%9Bg%D6%E9%13%AD%08%A0%0F%1F%8BwT%1Cn%9A%99%AC1y-%88b%A6%8E%B6z%95v%9B%CCD%0D%81%20%26_5%80%3A%E80%C9l%C5%CAQ%ED%09%12%2Fd%01%E0%2F%BF%90%97%17%A8%D7%1C%1Cnw%40C%7D%A6%95%BF%D3%86%2F%C8%A0%F3%3A%05%D0%CC%D2%26%D6%BA%99q%E1%EB%D4b%05%CD%B9%3F%A7%1F%C0%0F%89%C6%08k%B6%A9%84%80%DD%A06%7CC%C3%18%B3Er7G%005%19%BF%0A%C4%A7%BE%16S%DD%EC%16%98%89%E1%8C%09%DD%C8%2F%1F%40%F7%3A%A7%D6%CC%EA%DE%3C%1B%08%8A%DDq%E2%1E%94%9E%25%13%B7%5E%E9%BBvz%15%A2%94%FE0O%F3%91y%8F%86%86w-"%9AK0%D4%BEPs%EB%04%9A%B1%3A%A2%F4%AB%E4%08%B0%293%91%B6%B6%ADP%DF%E8%C2%5B%A7%AA%B2%1F1%05X%23G%D0%F6M%21%A8j%8D%BF7P%FCt%FAn%171%0C%7C%F93%BE%C5%B7%063%D6V%13%E9%7C%0B%EB%03%E556%D2%20%E6%26%E5%9F%8A%D8%E0b%93%2A%AD%88%B5%D5%B12%DB%28%60P_%3C%24v%A0w%F0C%BBEt%AD%D5%1D%A0%99%BD%F3%A3Se%0B%15%C9%8A%CD%E6%CA%12%D6w%01%AA%F9%28%FC%F8%F1%86%5E%A5%D5%ED%F0j%C4%E1%BFA2%C3%AAJE%D6%08%9A%0B%95%C04%D1%9E%196d%06%F6%B8%BCh.%7C%3CeUo%7Bg%2A%E3%E6%8EC%DD%FA%D4%D1%87F%CC%EA%DF%0B%1E%C1%D0%03%99%F0%F5%C8%D6%C9E%DC%F3%E8%F5%B3%B5%DA%BFi%09NqX%02%01%B3%F5%DB%8B%03%01%A7%DD%057q%B9%03%DA%873%B3%D3%A7%9CX%8AW%E0%D0%16%03%80%AE%C4%0Fg%E6%89%E2%E7e9%F6P%B4%0F%D9%AFEi%AD%8BYJV%3E%29~%C8C%1E%B2%A8%FC%1F%80U%F1%8F%E3%25%60p%00%00%00%00IEND%AEB%60%82" alt="the image" longdesc="pass.html">
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html-longdesc/data-uri-image-internal-description-manual.html b/tests/wpt/web-platform-tests/html-longdesc/data-uri-image-internal-description-manual.html
new file mode 100644
index 00000000000..b6a8270b602
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html-longdesc/data-uri-image-internal-description-manual.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Longdesc test: data: URI image, internal description</title>
+ </head>
+ <body>
+ <img src="data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%01%B2%00%00%01%07%04%03%00%00%01N%5D%EE%7F%00%00%00%04gAMA%00%00%AF%C87%05%8A%E9%00%00%00%1BPLTE%F8%FC%F8%00%00%00%F8%E8%B8%00%FC%F8%F8%00%00%00%FC%00%F8%90%40%00%00%F8%F8%00%F8d%FA%E4%E4%00%00%00%07tIME%07%CF%0B%01%07%1E%01E%0FIy%00%00%00%15tEXtSoftware%00XPaint%202.4.9P%0E%BDz%00%00%10%AFIDATx%9C%ED%5DKs%E3%B8%11f%AB%A6%A6rlH%8Aj%8E%B2f%B6r%5D%8D%92%BB%9Dh%EF%BB%D9%F2%DDs%F19%95_%B0%B9%ED%CF%0E%F1~%10%20%1B%20%40S%2Auy%3C%B2%40%E0%C3%87G%A3%D1x%B0%EB%1A%09v%80%FD%AF9%02c%D1%FB0%18%8B%AB%9E%F1c%E8%7F%882%E8t%3Ay%C1n%E4%EE%EB%E5%BB%0Er%13%92%9F%9Fv%DF%9Dg%99%0F%FE%ED%97%7F%A7sm%93%8D%08c%2C%1D8K%BC%B2%D8%06%81nI%C2h%60X%25%5E%E0%15G%02_%9E%C7b%06%81%1D5%B0%7B~%19%09%3Cv%EFo%C9%40%D6%7DN%06%82%0C%8C%B70%86%5E%CCA%2B%FD%02%C9%A6%89%E8%85%8C%B5%E0%A6%82%A3%F8%0C%87%BD%21%F57%8E%84E%609%7F%88%3D%C7%12%1D%DA%A4%0F%FA%F7%E9t%F4b%99%E0%FEgw%F9Y%FE%A1%BA%AC%1B%7C9%FFl%13%0A%BA%D9%F5%F5%E7d%A6%2F%97t%18c%F3T%DC%B48%3DN~r%0A%C9%E9%AA%C3%B0%91x%9F%AEea%FB%FDs%F8%95%13%EF9%F2%AD%0AK%86%F4%F2%04%EF%A92%ECq%92%FD%97%F7%D0d%D9%F7%1D4%897%3E%A8%0C5%BD%CD%CB%07J~%2B%1B%C6h%C7%20%912%19P%28E%F4%F2%1C%27%0C%CC%B4I%00%04%ADI%A6JGg%04%99%CD%13%8C%E1%0C2%E8%A6%D2%89%CEe%D4%11%1F%D1%7B9%86h%E0%E9P%D4%B1d%CCX%BC%40BC%C0%E6%E1%DB%F5%97%D7%DF%FDx0f7%E8%8CG%E2%91%E4%C4%A5%20%5E%9F%A9R%F5%08%F9f%90%8A%912%1Ac%DF%1F%DE%7Dy%8B%25%CB%8E%91%C4"%C0%E1%23%85%F10V%93%84x%9F%AE%11%05%3C%1D%0F%F6%D7%EB%D0%82"%E0%F5%F1%AE%D1%80%09%D9%BF%5CC3%91%16%EF%9F%D8%25%AAh%5C%8E%FD%BF%3Ebf%2C%A9%5B%40%C7%23%E7%B8o%F2%BC%ED%BE%FF%C8%C4%EBu%207%8E%24%3Fz%F9%40%27%9AKr%A6%84%5D%17%D7%0Ci%135%01%C4SaV%017%9B%A7%DC%AE%D8J%A0%D7%1F%D9zv%83%86%C9%8F%01%8A%29eR%2B%8ED%1C%95Hz%AD%EC%0B%98%9CT%94%04%9903%1C%3B%7FO%E2%B1%F0%8BxD%90%DD%0F%F5%0F%A8%87Q%7F%8A%83%19%C3%C6%26%A3%CC%8D%D1%CC9%26%89%26%C7l%B4d%8F%97%93%25mG%C9%89%13w%90%84%60%1Ba%0783%2AE%00%D0E%14A%3AA%11%8D%5B9%DFc%A6%5D%A4v%ECW%9B%CB%CE%8F6%14%A1%8B%FA_%ACs%D0%CE%01Z%87%5Ee9%9F%DD%3E%B1%B9%9C%2F%BB%EF%0E%B7D%AE%82%D0%CD%DF%AF%FFx%8Dq%83%A8%E1%A3%BF%1BDKE%F0%A3F%A2M%89%88%16V%00MDu%FF%94%1D%8D%1B%7D%25f%DF%0Cc%B1%CC%CD%C8%B0%0C%EE%D7%DCh%CC%FB%AF%96D%92%0B%AC%D9%98%C9%13%B5f%BD%B9%F2%5B%14l%FB%9F%B2h%85h%85%D1"_%12%A2%C5%1C%88%D3%D1%A2%E6%2F%29%DA%B0%FD%90%A2%3D%7Fp%B4I%81k%D1%94%80G%1B%F3%E1%A6%A4%0C%AD%EB%99yhD%ABe%8F%A2%7F%0D%5Cb%E3%C2%F8%EC%E3%B3%9E%B5%D0%0D%A4%CD%93%80%CB%9CD%C8%F4%B3%A3%F5%03%3D%E3s%E1l4%C6%07%FF%DC%19%99%1C%1D%B2%A3%A1%40%FB%9C%88%96%D2%AD%DC%FE%02%CE-%1E-%AD%C9E%C8_%FE%18%09L%0A7%9B0V%D5%C8K%2C%9AS%D4%ABY%D9%26td%99%8B%10%27%07%86%5BI%C0%8CCf%CANy%C8G%89c%3E%15x%CF%C8%20%A9%80%A2%E4%D2mi2%BD%B2%D9%E60YrY%8D%AEF%0F%A4J%2F%A1%262%BAnV%1D%B0%1AZi%21e%D5%84Q%AB%A5%EE%89%C1%F2%27%EA%F4%40%CCZ%EA%EAC%F0%3FA%17%ACdb0%9F-%07%D2%B3w%F1%89%89%95i4e%AB%96%2BPg%C2%ACit%D4%82%B4%23%93Y%D81%03%0F%A7%108%B4l%CA%E0%7CKg%E3%7C2%20%A8%FF%F3Vk%FC%CC%14%0D%BC%F6it%B3%2BU%09%98%87P%E9%1B%F7%F1xz%CCJ%14%8D%A7%20%FDx%F2%1BpI%84%A5%E9f1%B6%9C%B9y%D2X%DB%A7%09z%2A%5E%CA%2F%12%3E%17%FBk%F3uw9%EF%84%0Bb%0A%CDV%04%C5%85%20%9E%D4%C5e%D1.%DC%01%D4%03%C6%D0%D0%CBe%DC%94%19%2A%17%86%FAIf%3A%A1F%93%CC%E2%DC%26%08%8Ci%B1%98%7B%B1G%EBg%3C%FFz%7D%7D%FD%3DZ%92%C9%F4%28%23%DC0%EE%04%9A%8F%98%BD%1A%10f%96%806O%BCN%DE%1C%ADs%8Bd%F3%F5rI%B7%92%DA"%BD%B4B%16%40%93%5D%B5%CC%E3W%0C%95%D0%93%0D%A5%D5%D2F%04%A9%2F%C9%E5%D0%04%E2%A2h%95%2C%E3%40%D8%84%D00%FB%B2%27%99%96u%D0%18%B0%EDi%FA1.%87d%00%B90%B1%1F%ED%89%7B8%2A%A0%01%5B%92%5B%3F%3C%2F%88%D6%D7%EF%86%F8h%0D%B4%97%EB%9E%E8%8C%AD%80%F6%89%3BUi%DE%D8%0Ah%7B%81Fr%E2VB%DB%D3%F6%9E%CCGC%BE%AD%26%EA%EB%D72%A5Dr%D4%09%DB%0Bj%23%15WS%E9%82%AA%B7%12%A7%7D9Z%D1f%A3%7C%E9%D1D%2FH%E7%A7%26%DA%A7%EB%8B%A8%5E%B1%5C%17%AB%E8%BA%83%F3U%8D%00ry%D0%5B%B1%AF%8A%23e%A3%0C%D0%CF%02-%7BCT%96%F46%D3F%CD%E7%0F%CD%D1%A4KA9GZ%A3%89S4%8C%EF%C7%E0%D3%7F%08%B7%C05%B0%A6%ACO%0B%82V%D2%00%0B%11%B4%BD%FB9w%97%5E%FE%A4%13%F8L%9E%EF%B4%03%F0%D0%26%7D%0D%D8%E5%EF%16%00%EEUS%0E%9B%F7%1F%B1%0D0I%29%29t%A6v%ED%F0%8F%7Ft%B6KS%D2%F2%1D%23%04%01%B0%05bZ%0B1%AAv%8A%C1%D4%C6.%1BCg%0F%AD%D3%A6%E1%B4%C5%5D%E4%AD%0B%13%9D%B6Z%3F%14%DF%CB%F4X%5E%7B%C8C%EEU%60%91UZ.%11U%D3%08%2F%E9%8B%2BQe%E3%C3%EC%A8v%2CP%D5%98%F6%F7L%D7Nvqb2%0E%A5%A4%F2%D6%9F%CD%12%5Eq2%B9x%2A%96%9D%B1f%FAh%CB%F0%CA%85%5E%10u%F0%88%A5%11%DFE%9E%2F%C5%C5%D9%DC%B0%BA%194%7D%81%01%29%D6%DC%D6%9B%B7O%81%C8m%F4%06%06za%10%D0%EC%AE%08%E4%BE%E6%C8%3E%9BDBEh%A8%16%C0%A93%88%3C4%E6%07%C2%F0%A1%A0%5C1%92%C5%2C49%23%02%B9UbP%B4~%BC%8C%3D%18%3E%1A%A8Y%1E%EA%1D%05%E8%EC%CD%90Y%09a%F2%9B%B5%5E%9A%D3%5B-%0C%8E%BB%83D%7F%0A6%BBx%FB3%28"%8B%C2pp%E6mz%5B%87I%0B%07h%85%04%9D%88%A1%03-%A6r%D1o%F9t4L%FD%09%CE%BF0%2C%98%1B%E7rsJK"%C8%FD%25%E2%B3%293%0C%D3%C50%F6%94%04%8DW%14%9B%DC%DC%A2%D1%24%90%29h%97O%886%E9%28%07%3Fc%FE%EEWu%F2%9C%E9%83Rn%1A1%A7%C8%D6%AE%AE%1F%93%F4%3C%F5%E763%0B%E4f%C1%E6p%80f%A8%C5NDx%98%96M%2C%21G%98QV%03%B4%9D%DE%A7%10C%1Bz%8B%B5%12%9E%A8x%88%AFg%F7h%E7%CBe%B7%BB%EC%A6%D04%24%D2%D4C%D4%CE%DA%EEv%E7%DD%8E%84f%EA%02h%8B%2F%11%C8-%07%DA%EDX%1C%AD%0BUQ%1C%C3b%839%E3%1B%B5%E9%B7%02%2C%C5%AD%F3%00%E2%7B%9E%06_%3A%1B%BE%87%DC%CE%12-%DAJLr%A9%82K%98%A5%29k%B5G%E3%27%F3%D8.%C9mD%C6%2A%2F%1A%B4%DD%E9%7DA1%B4%D11w%C2%BA%87%C8%C7q%B4t%8A%04%CB%DE%3EBE%8B%E0e%9C%C8%D3q%E9hN%ED%E4%9F%25%0Fm%09%02ZgM%93l%09%3C%C14%B4%19%E2%15zs4%AF%3D%8D%8F%01u%C4V%C2%12hV%EC%D8%FD%D3%A2h%25W%A7%E4J%F6%EE%A3JxK%60-%89%E6%EE%C4n_%92%0F%B4%9BG%FB%ED%BE%B8yX%CD%BB%DC%1D%A2%85%18%A1P%0D%2AZ%EE%C2%13%FF%A1%D0%D0%80h%81%D5%E1%C6%9F%3C%92%9E%EC%92%FBj%E8%FBD%D8%F4%DC%B9%26%1A%B2%ED%7F%97C%A3%EF%B2%AD%85v%5C%0C%0D%D8iAn%C06%DF%96Ccls%5C%12%8D%3Ah%DC%1AZ%AF%B7%AE%40%F4%3BV%E0%C6%AF%AE%23%EEz%AD%81%26v%BD%92%C8%DD%28%1A%A9%28%2B%A0elW%AE%84%B6_%98%1Bis%F4l4%E0h%2F%8B%A1%E1%24%B7%29%83%24%C74%D1h%CB%ECB%40Y%90%0B%A3-s%3E%60Y4Ph%CF%8B%A2-%CBm%B1s%1D%2F%2Cz%1Dl%13%E1hb%FC%5EB%18G%E3%9B%EF%E4I%8B%C6%60%3D%DAVh%A7%F7%F6G%1F%80%21%BC%9Cz%2B%08%D8%A1%3D%1AW%A4%E2%5C%07hr%0D5%18_%85%EA6OG%E0eyh%7Df%85%0F%12%B8y%12%09%2B%B4%B7%86hb%29O%EC%96%E9T%ABl%8D%A6%EF%1Fg%CD%D1%E4%E9%18%266s%CA%A2l%8A%26n%D6%92%1BJd%27x%9B%8CT%2A%80%E2%98%85X%D3%E6o%B8%F9%DC%B4%07%C8%9BY%B8sF%2C%00%B3%EC%132%D9h%D6%F3%E4%A3%D5%D7%D2%3D%1A%E3we%A3%D8%12-%EA%CDh%AE%26h%CA%FF%27%FE%CAF%CB%DBM%09%8C7%10D%F9%B6%17%D9%263%D0r%3D%93%AC%D3%17%06%F3%1F%3C%E4%B4%92%C8%E6%B6%294%E8%CC%BD%C2%3DZfw%CB%DD%B1%275%97%ECn%7D%C1%BCg%F8%17%BA.~%0F%DF%18%1A%27%D7%D7%9A%28O%D6%7D%F9_%96%978%17M%1CFS%1B%DE%7B%E4%2Fy%3Ei%C8%DD-%A7%12Gq%88%0A%DE3%BC%D12%1E%CBj%2C%20%CAR%A8f%8DF%27%27%2FD%CCx%7F%98%F1%60s%94%5C4%E7%CE%2B2%1C%82%F6%9B%ABe%05z%E4%7Ca%12%07%B5%82v%2F%BC%AE%2F%20%19%A9%5D%0F%B2%95%B4%B4%D2%DD%86X%93%5B%E2~%27%8B%15%5C%D8U%01%D04B%B9%A5%D1o%14%92%E72%F3%9D%87%3C%E4%21%0Fy%C8-%CB%D0%8F%FD%D19%9A%25S%9E%F8%85%F6%AEU%94%1C%1Bz%B1%CA%9Bu%90%12%CA%1AY%DB%B3%CC%1A%A4%18f%5E%CFY%E0%25%9F%5D%CA%5C%1D%8BT%27%5B%8D7%5Di%14j%5E%EB%BEY%ACa%A7s%CF%F8%8C%EBfh%A4%B9%AB_%3E%ADd%24Qg%0F%DD%02%FB%1EkC%2C%7D%C4%7CL%EA%92%A3%CD%2A%17%9B%7BV%24G%DC%C2%B8%5C%CDVSP%ABcVk9%99%D8%CC%DA2%F3un%A5%96OL%A6%F0%CDb%94%0Ch%27%AE%FD%A6R%C2%B4%C7%88%CC%0A%ADH%3F%23%95%0A%91%C8%8C%96_s%E2%5C%1DZ%CEr%D8%9B%0F%ABb%26%CF%E7%82%D7%A2%5C%27%2C%21%B3l%F0a%A6Ta%A6h9%F9%0F%2C%0A%B1%04%3Fj%C9%98R%A9%A6%AB%88%03%F5%F01%90%EBn%CC9%95%EE%E6%C9%CF%9Fn%A0%E9%81%D8%14%5D%3D%EF7%ED%29%09%DC%F7%1B%F3%2Aw%A6%8E%F8%9Be%066%CE%8C%25%82%3A%15y%2C%B4HF%DF%D4%80%CAK%A3%AE%92bN%26%18%AA%95%2C%B4U%16a%26%0E%5B%8B%C5%1D%0C%82%BC"%B5%C4%2A%0E%9C%26%25%9D%BAVh.%86%D4u%EE%83%FC%17%B2%CEe%E6M%CD%BD%06%EA%1Fq%1F0%8B%5C%3ARC%EC%2A%8FM%1D%BB%A0%F0%3C%CD%A7%EFG%D1w5%E8%CCx%9D%11%DDDY7%C2%CC%AF%A5%FA%CC%20lJ%1E%04x_%A4%98%B9%7D%C4c%E6h%19%93NB%17%D6g6x%FB%89%078%28t%D0%8A%03F%999%2C%D0%0FI%DD%60R%9D%D9%A0%ED%C5%98%C9%F5V%B3%0E%0A%EAY%3B%1C%0F%3E%C9dA%27%11%01%0C%99%D4g%E6rC%FB%BD%82%B3w%F4%281%95h%99%81V%ED%E6%83zN%AE%7B%83_I%B6%A2%7D%19%FC%7D%8A%0AE%83%A2%F9m%DEz%EF%7C%AF%F3%17%AE%E8%9A%F6%05%A6b%E4%EF%B4%AD%E8%A9%D6%E1%5D%0A%5Ev%ACTa%96%86%D0%03%97%C53OL%F1qD%ED%1D%F0%0Bn%9A%D9%D3%25%94%F3%3Cf%E0%7D%04_%C7%18f%25%03%AB%BF_%21%28%93%18%B3%5DO%E6%C2vg%C6%FA%9F%FE%23%8DY%A0%83%9D%00%BF%DF%A1%3Frwe%A4Tl%86%C9%2AN1%3B%EF%04%27%5Ecs%99%05%D3%0Ai%FE%06%B1%CA%25%99%B3%183~S%D1%F9r%CEd%96%B8A%C7%F9.%9B%05a%3D%D0%DA3%A1%F1%1Fe%B6%3B%170%8B%99%20.~%86%EBvt%FE%A5%28%8AG%DC%9Bs%C3v%19%D5%20%86W%01%B3y%CEg%B2c~%F8%60%F8E%94%D9%99%BFRO%F73%AAn%F4ty%89%07%3F%DF%A53%EA%2A%AD%A7%F5%E7x%1Df%D4sr12%C6L%9D.%BB%BCJ%A1%8Ege%0B%9E%15%5C%D4Q%E0%81%BA%9A%C1%AC%CB%5CW%AD%B8%86%16%A9%F3%CA%CC%B8%8C%D8%7B-%17%D0%C2%8Ak%C0L%88C%8F~Q%DE%5C%F1PZ1%FB%20qZ%E5%B0y%DE4%B3%CE%92%BB%3Ff%5CX8%BD%E52c%16%B3%2A%89%B8%A2OO%A1%1D%CA%D8%0D2%1BJtN%FDz%B7%CC%EE%A2%CE%3Am%CE%DE%CD%3EIO%7C%5E%F7Q_B%EE%B0%CA%00%93%F2%D1Y%9B%29%0Ff%B7%27CfR%85%DC%23%B3%5E%FE%FA%EB%BD2%BB%D3%D6x%0F%CC%40%F7%AA%A8%DC2%B9%91%FA%BA%F1j%1BZ%8Ba%B55%04%AE%97%F6a%EA%F2%CF%09%A9xO%8Cr%27%D7"%B7%1Ef%D2%B3%C5%D8%B6Z%8A%5C%F2m%DDC%F5KF%40%F0"%DF%E8I%94Cv%D1%D7g%C6%A4B%3E%FD%8Dx%7D%28MV%C1L%D6Y%E5%1B%E5%D7%C0%0C%B5%0F%89z%E7%2BI%D6%C0%0CD%95%C1%5D2%E3%CDq%7B%3A%91%AE%83%A4%CA%2A%98%09%E5%88%95_%DC%B0%06fL%0Eh%C7%BA%A9%AE%82%99%A0%06%C7%BA%A9%AE%84%19%A7v%AC%7Bbl%05%CC%F8%ED%CDl%7F%E5w%01%BFT%F4%FE%AD%80%99%B8nR%ADj%BDT%B4%F8W%C0%0C%AEV%5E%AA%A5%BA6f%F5%EE%E5%5D%033vmQik%60%B6%BF%7Bf%FB%AA%3A%E4%C3%99%F5c%98%C7%ACZG%FBpf%60%98%BD%D4U%21%F9%DE%82%CA%1E%2C%60%FA%BE~Us%25%83%F5%3A%BD%85%9A%99n%93%25%2Ad%A5%CCp%EFVYQ%A5%AD%93%19%84%CC%0A%2Am%9D%97%F0%0D%98%15T%C0%3A%99q%83xnk%BC%11fw%D3%1A%7B%BD%CF%F9%3C%EFQ%8Fk%F9%CDq%A5%CC%A4E%FC%2C%96%C4%7BrE%B7%04%ADS9%A2d%26%2F%9F%E6%F7%94%DB%D5.z%1A%0D%F3W%2A%9C%0Co%86%5B%EE%06%91%E2%AE%F8L%1C%21Y%F1%EE%29%DE%04ysd%A7%A38%98%C6%D9%1Dh%8BY%2Bd%E3%88%20%D6%F1%B7%B8m%8E%F2p%FF%A0%D6%C8G%B0V%25b%E5%9B%2B6%EE%D3%07%7D%B4%D1%A7%96%AC%B4%B5%2AD.jM%1F9%B3%A7%23%EA%B3%9EA%83L%D5%CD%CA%99%E9%17D%9C%9E%D45%ED%82%2A%B2%9Bg%D6%E9%13%AD%08%A0%0F%1F%8BwT%1Cn%9A%99%AC1y-%88b%A6%8E%B6z%95v%9B%CCD%0D%81%20%26_5%80%3A%E80%C9l%C5%CAQ%ED%09%12%2Fd%01%E0%2F%BF%90%97%17%A8%D7%1C%1Cnw%40C%7D%A6%95%BF%D3%86%2F%C8%A0%F3%3A%05%D0%CC%D2%26%D6%BA%99q%E1%EB%D4b%05%CD%B9%3F%A7%1F%C0%0F%89%C6%08k%B6%A9%84%80%DD%A06%7CC%C3%18%B3Er7G%005%19%BF%0A%C4%A7%BE%16S%DD%EC%16%98%89%E1%8C%09%DD%C8%2F%1F%40%F7%3A%A7%D6%CC%EA%DE%3C%1B%08%8A%DDq%E2%1E%94%9E%25%13%B7%5E%E9%BBvz%15%A2%94%FE0O%F3%91y%8F%86%86w-"%9AK0%D4%BEPs%EB%04%9A%B1%3A%A2%F4%AB%E4%08%B0%293%91%B6%B6%ADP%DF%E8%C2%5B%A7%AA%B2%1F1%05X%23G%D0%F6M%21%A8j%8D%BF7P%FCt%FAn%171%0C%7C%F93%BE%C5%B7%063%D6V%13%E9%7C%0B%EB%03%E556%D2%20%E6%26%E5%9F%8A%D8%E0b%93%2A%AD%88%B5%D5%B12%DB%28%60P_%3C%24v%A0w%F0C%BBEt%AD%D5%1D%A0%99%BD%F3%A3Se%0B%15%C9%8A%CD%E6%CA%12%D6w%01%AA%F9%28%FC%F8%F1%86%5E%A5%D5%ED%F0j%C4%E1%BFA2%C3%AAJE%D6%08%9A%0B%95%C04%D1%9E%196d%06%F6%B8%BCh.%7C%3CeUo%7Bg%2A%E3%E6%8EC%DD%FA%D4%D1%87F%CC%EA%DF%0B%1E%C1%D0%03%99%F0%F5%C8%D6%C9E%DC%F3%E8%F5%B3%B5%DA%BFi%09NqX%02%01%B3%F5%DB%8B%03%01%A7%DD%057q%B9%03%DA%873%B3%D3%A7%9CX%8AW%E0%D0%16%03%80%AE%C4%0Fg%E6%89%E2%E7e9%F6P%B4%0F%D9%AFEi%AD%8BYJV%3E%29~%C8C%1E%B2%A8%FC%1F%80U%F1%8F%E3%25%60p%00%00%00%00IEND%AEB%60%82" alt="the image" longdesc="#pass">
+<div style="height:50em"></div>
+<p id="pass">Pass, if the focus is here</p>
+<p>The image is a drawn cartoon, on the left is a parson in a wheelchair in profile, facing toward the centre of the image, under a banner with the text "e-democracy?" on it. In front of the person is stairs, at the top of the stairs is a table. On the table is a computer, whose screen says "Vote!" and has a red and a green button</p>
+ <p>The image is signed in the space under the floor that is at the top of the stairs with an "R" rune flipped backwards, somewhat resembling a "Я" with top and bottom border lines sloping upward from left to right, and is marked ©2013. It was actually drawn by Charles McCathie Nevile.</p>
+<div style="height:50em"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html-longdesc/empty-image-data-uri-description-manual.html b/tests/wpt/web-platform-tests/html-longdesc/empty-image-data-uri-description-manual.html
new file mode 100644
index 00000000000..fc0ae768a42
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html-longdesc/empty-image-data-uri-description-manual.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Longdesc test: Empty image, data: URI description</title>
+ </head>
+ <body>
+ <img src="" alt="the image" longdesc="data:text/html;charset=utf-8,%3C%21DOCTYPE%20html%3E%0D%0A%3Chtml%3E%0D%0A%20%3Chead%3E%0D%0A%20%20%3Ctitle%3ELongdesc%20test%20Pass%20page%3C%2Ftitle%3E%0D%0A%20%3C%2Fhead%3E%0D%0A%20%3Cbody%3E%0D%0A%20%20%3Ch1%3EPass%3C%2Fh1%3E%0D%0A%20%3C%2Fbody%3E%0D%0A%3C%2Fhtml%3E">
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html-longdesc/empty-image-external-description-fragment-manual.html b/tests/wpt/web-platform-tests/html-longdesc/empty-image-external-description-fragment-manual.html
new file mode 100644
index 00000000000..ae3f8d1c4bc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html-longdesc/empty-image-external-description-fragment-manual.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Longdesc test: Empty image, external description fragment</title>
+ </head>
+ <body>
+ <img src="" alt="the image" longdesc="pass-fragment.html#fragment">
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html-longdesc/empty-image-external-description-manual.html b/tests/wpt/web-platform-tests/html-longdesc/empty-image-external-description-manual.html
new file mode 100644
index 00000000000..567eea50261
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html-longdesc/empty-image-external-description-manual.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Longdesc test: Empty image, external description</title>
+ </head>
+ <body>
+ <img src="" alt="the image" longdesc="pass.html">
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html-longdesc/empty-image-internal-description-manual.html b/tests/wpt/web-platform-tests/html-longdesc/empty-image-internal-description-manual.html
new file mode 100644
index 00000000000..aeb81104c6d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html-longdesc/empty-image-internal-description-manual.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Longdesc test: Empty image, internal description</title>
+ </head>
+ <body>
+ <img src="" alt="the image" longdesc="#pass">
+<div style="height:50em"></div>
+<p id="pass">Pass, if the focus is here</p>
+<p>The image is a drawn cartoon, on the left is a parson in a wheelchair in profile, facing toward the centre of the image, under a banner with the text "e-democracy?" on it. In front of the person is stairs, at the top of the stairs is a table. On the table is a computer, whose screen says "Vote!" and has a red and a green button</p>
+ <p>The image is signed in the space under the floor that is at the top of the stairs with an "R" rune flipped backwards, somewhat resembling a "Я" with top and bottom border lines sloping upward from left to right, and is marked ©2013. It was actually drawn by Charles McCathie Nevile.</p>
+<div style="height:50em"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html-longdesc/empty-longdesc-manual.html b/tests/wpt/web-platform-tests/html-longdesc/empty-longdesc-manual.html
new file mode 100644
index 00000000000..9c582590ec1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html-longdesc/empty-longdesc-manual.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Longdesc test: empty longdesc</title>
+ </head>
+ <body>
+<h1>Longdesc test: empty longdesc value</h1>
+<p><img src="picture.png" alt="the image" longdesc=""></p>
+<p>The longdesc attribute value is null, and therefore the longdesc is not valid.</p>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html-longdesc/external-image-data-uri-description-girt-by-spaces-manual.html b/tests/wpt/web-platform-tests/html-longdesc/external-image-data-uri-description-girt-by-spaces-manual.html
new file mode 100644
index 00000000000..ce23fe55e7f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html-longdesc/external-image-data-uri-description-girt-by-spaces-manual.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Longdesc test: External image, data: URI description surrounded by spaces</title>
+ </head>
+ <body>
+ <img src="picture.png" alt="the image" longdesc=" data:text/html;charset=utf-8,%3C%21DOCTYPE%20html%3E%0D%0A%3Chtml%3E%0D%0A%20%3Chead%3E%0D%0A%20%20%3Ctitle%3ELongdesc%20test%20Pass%20page%3C%2Ftitle%3E%0D%0A%20%3C%2Fhead%3E%0D%0A%20%3Cbody%3E%0D%0A%20%20%3Ch1%3EPass%3C%2Fh1%3E%0D%0A%20%3C%2Fbody%3E%0D%0A%3C%2Fhtml%3E ">
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html-longdesc/external-image-data-uri-description-manual.html b/tests/wpt/web-platform-tests/html-longdesc/external-image-data-uri-description-manual.html
new file mode 100644
index 00000000000..f8f3d0a616f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html-longdesc/external-image-data-uri-description-manual.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Longdesc test: External image, data: URI description</title>
+ </head>
+ <body>
+ <img src="picture.png" alt="the image" longdesc="data:text/html;charset=utf-8,%3C%21DOCTYPE%20html%3E%0D%0A%3Chtml%3E%0D%0A%20%3Chead%3E%0D%0A%20%20%3Ctitle%3ELongdesc%20test%20Pass%20page%3C%2Ftitle%3E%0D%0A%20%3C%2Fhead%3E%0D%0A%20%3Cbody%3E%0D%0A%20%20%3Ch1%3EPass%3C%2Fh1%3E%0D%0A%20%3C%2Fbody%3E%0D%0A%3C%2Fhtml%3E">
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html-longdesc/external-image-external-description-fragment-girt-by-spaces-manual.html b/tests/wpt/web-platform-tests/html-longdesc/external-image-external-description-fragment-girt-by-spaces-manual.html
new file mode 100644
index 00000000000..d9cd73cd4bd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html-longdesc/external-image-external-description-fragment-girt-by-spaces-manual.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Longdesc test: External image, external description fragment surrounded by spaces</title>
+ </head>
+ <body>
+ <img src="picture.png" alt="the image" longdesc=" pass-fragment.html#fragment ">
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html-longdesc/external-image-external-description-fragment-manual.html b/tests/wpt/web-platform-tests/html-longdesc/external-image-external-description-fragment-manual.html
new file mode 100644
index 00000000000..605d0d0f249
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html-longdesc/external-image-external-description-fragment-manual.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Longdesc test: External image, external description fragment</title>
+ </head>
+ <body>
+ <img src="picture.png" alt="the image" longdesc="pass-fragment.html#fragment">
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html-longdesc/external-image-external-description-girt-by-spaces-manual.html b/tests/wpt/web-platform-tests/html-longdesc/external-image-external-description-girt-by-spaces-manual.html
new file mode 100644
index 00000000000..d44bc4ed9ae
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html-longdesc/external-image-external-description-girt-by-spaces-manual.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Longdesc test: External image, external description surrounded by spaces</title>
+ </head>
+ <body>
+ <img src="picture.png" alt="the image" longdesc=" pass.html ">
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html-longdesc/external-image-external-description-manual.html b/tests/wpt/web-platform-tests/html-longdesc/external-image-external-description-manual.html
new file mode 100644
index 00000000000..468a0db8fb3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html-longdesc/external-image-external-description-manual.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Longdesc test: External image, external description</title>
+ </head>
+ <body>
+ <img src="picture.png" alt="the image" longdesc="pass.html">
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html-longdesc/external-image-internal-description-girt-by-spaces-manual.html b/tests/wpt/web-platform-tests/html-longdesc/external-image-internal-description-girt-by-spaces-manual.html
new file mode 100644
index 00000000000..693079085d1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html-longdesc/external-image-internal-description-girt-by-spaces-manual.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Longdesc test: External image, internal description surrounded by spaces</title>
+ </head>
+ <body>
+ <img src="picture.png" alt="the image" longdesc=" #pass ">
+<div style="height:50em"></div>
+<p id="pass">Pass, if the focus is here</p>
+<p>The image is a drawn cartoon, on the left is a parson in a wheelchair in profile, facing toward the centre of the image, under a banner with the text "e-democracy?" on it. In front of the person is stairs, at the top of the stairs is a table. On the table is a computer, whose screen says "Vote!" and has a red and a green button</p>
+ <p>The image is signed in the space under the floor that is at the top of the stairs with an "R" rune flipped backwards, somewhat resembling a "Я" with top and bottom border lines sloping upward from left to right, and is marked ©2013. It was actually drawn by Charles McCathie Nevile.</p>
+<div style="height:50em"></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html-longdesc/external-image-internal-description-manual.html b/tests/wpt/web-platform-tests/html-longdesc/external-image-internal-description-manual.html
new file mode 100644
index 00000000000..2e984bad233
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html-longdesc/external-image-internal-description-manual.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Longdesc test: External image, internal description</title>
+ </head>
+ <body>
+ <img src="picture.png" alt="the image" longdesc="#pass">
+<div style="height:50em"></div>
+<p id="pass">Pass, if the focus is here</p>
+<p>The image is a drawn cartoon, on the left is a parson in a wheelchair in profile, facing toward the centre of the image, under a banner with the text "e-democracy?" on it. In front of the person is stairs, at the top of the stairs is a table. On the table is a computer, whose screen says "Vote!" and has a red and a green button</p>
+ <p>The image is signed in the space under the floor that is at the top of the stairs with an "R" rune flipped backwards, somewhat resembling a "Я" with top and bottom border lines sloping upward from left to right, and is marked ©2013. It was actually drawn by Charles McCathie Nevile.</p>
+<div style="height:50em"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html-longdesc/external-image-with-absolute-base-external-description-manual.html b/tests/wpt/web-platform-tests/html-longdesc/external-image-with-absolute-base-external-description-manual.html
new file mode 100644
index 00000000000..a861d351a34
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html-longdesc/external-image-with-absolute-base-external-description-manual.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Longdesc test: External image, external description, absolute base</title>
+ <base href="https://rawgithub.com/chaals/longdesc-tests/master/rebased/">
+ </head>
+ <body>
+ <p>Note that this test currently uses a target URL for the base that is not necessarily reliable long-term. It should be updated by anyone who wants to use the test "for real", pointing to some reliably stable repository</p>
+ <img src="picture2.png" alt="the image" longdesc="fail.html">
+ <p>If the image is broken, the base element has not been interpreted correctly so the test result is unknowable</p>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html-longdesc/external-image-with-relative-base-external-description-manual.html b/tests/wpt/web-platform-tests/html-longdesc/external-image-with-relative-base-external-description-manual.html
new file mode 100644
index 00000000000..edd64812a89
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html-longdesc/external-image-with-relative-base-external-description-manual.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Longdesc test: External image, external description, relative base</title>
+ <base href="./rebased/">
+ </head>
+ <body>
+ <img src="picture2.png" alt="the image" longdesc="fail.html">
+ <p>If the image is broken, the base element has not been interpreted correctly so the test result is unknowable</p>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html-longdesc/fail-fragment-pointer-manual.html b/tests/wpt/web-platform-tests/html-longdesc/fail-fragment-pointer-manual.html
new file mode 100644
index 00000000000..50b710b09ce
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html-longdesc/fail-fragment-pointer-manual.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Longdesc test: External image, external description fragment</title>
+ </head>
+ <body>
+ <img src="picture.png" alt="the image" longdesc="fail-fragment.html#fragment">
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html-longdesc/fail-fragment.html b/tests/wpt/web-platform-tests/html-longdesc/fail-fragment.html
new file mode 100644
index 00000000000..a4e2ead8c6a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html-longdesc/fail-fragment.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+ <meta charset="utf-8">
+ <head>
+ <title>Invalid longdesc test page</title>
+ </head>
+ <body>
+ <h1>Fail if you land here</h1>
+<div>
+<p>Testing tools such as validators should give a warning that this page is probably violating the SHOULD-level requirement that external descriptions which are a fragment of a document should be a well-formed fragment. Using an empty element as a description is almost certainly an inadequate description</p>
+</div>
+<div>
+ <h1><a id="fragment"></a>The description</h1>
+ <p>The image is a drawn cartoon, on the left is a parson in a wheelchair in profile, facing toward the centre of the image, under a banner with the text "e-democracy?" on it. In front of the person is stairs, at the top of the stairs is a table. On the table is a computer, whose screen says "Vote!" and has a red and a green button</p>
+ <p>The image is signed in the space under the floor that is at the top of the stairs with an "R" rune flipped backwards, somewhat resembling a "Я" with top and bottom border lines sloping upward from left to right, and is marked ©2013. It was actually drawn by Charles McCathie Nevile.</p>
+</div>
+<p>This paragraph is not part of the description. As of September 2013 there is no conformance requirement making it a failure to read this paragraph, but best practice would be to present only the description, and not this part.</p>
+<p>The description is encapsulated in a well-formed fragment, but since the target of a link is an empty element it is not possible to positively identify it.</p>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html-longdesc/fail.html b/tests/wpt/web-platform-tests/html-longdesc/fail.html
new file mode 100644
index 00000000000..37893ef50f5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html-longdesc/fail.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Longdesc test Fail page</title>
+ </head>
+ <body>
+ <h1>Fail</h1>
+ <p>Apparently, something went wrong and the test has been failed.</p>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html-longdesc/iframe-discoverability-manual.html b/tests/wpt/web-platform-tests/html-longdesc/iframe-discoverability-manual.html
new file mode 100644
index 00000000000..5cea9f61746
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html-longdesc/iframe-discoverability-manual.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Longdesc test: iframe discoverability</title>
+ </head>
+ <body>
+ <iframe src="external-image-external-description-manual.html" width="480" height="320">
+ <p>If there is no document included here with an image, the result of the test is unknowable</p>
+ </iframe>
+ <p>In order to pass, it should be possible to discover that there is an image with a longdesc included in this document (inside an iframe).
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html-longdesc/invalid-longdesc-manual.html b/tests/wpt/web-platform-tests/html-longdesc/invalid-longdesc-manual.html
new file mode 100644
index 00000000000..3cef0a5f31b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html-longdesc/invalid-longdesc-manual.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Longdesc test: invalid longdesc</title>
+ </head>
+ <body>
+ <img src="picture.png" alt="the image" longdesc="This is not a valid longdesc so this document should fail validation">
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html-longdesc/pass-fragment.html b/tests/wpt/web-platform-tests/html-longdesc/pass-fragment.html
new file mode 100644
index 00000000000..076f4f05ec6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html-longdesc/pass-fragment.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+ <meta charset="utf-8">
+ <head>
+ <title>Longdesc test Pass page</title>
+ </head>
+ <body>
+ <h1>Fail if you land here</h1>
+<div style="height:200em">
+<p>This is a landing page for tests of the longdesc attribute. To pass, when opening a longdesc that points to this page, the focus should be on a heading with the text "pass" followed by a description of an image</p>
+</div>
+<div id="fragment" style="min-height:20em">
+ <h1>Pass</h1>
+ <p>The image is a drawn cartoon, on the left is a parson in a wheelchair in profile, facing toward the centre of the image, under a banner with the text "e-democracy?" on it. In front of the person is stairs, at the top of the stairs is a table. On the table is a computer, whose screen says "Vote!" and has a red and a green button</p>
+ <p>The image is signed in the space under the floor that is at the top of the stairs with an "R" rune flipped backwards, somewhat resembling a "Я" with top and bottom border lines sloping upward from left to right, and is marked ©2013. It was actually drawn by Charles McCathie Nevile.</p>
+</div>
+<p>This paragraph is not part of the description. As of September 2013 there is no conformance requirement making it a failure to read this paragraph, best practice would be to present only the description, and not this part.</p>
+<p>The description is encapsulated in a well-formed div element, so it is possible to identify it.</p>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html-longdesc/pass.html b/tests/wpt/web-platform-tests/html-longdesc/pass.html
new file mode 100644
index 00000000000..d3ee981d854
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html-longdesc/pass.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <meta charset="utf-8">
+ <head>
+ <title>Longdesc test Pass page</title>
+ </head>
+ <body>
+ <h1>Pass</h1>
+ <p>The image is a drawn cartoon, on the left is a parson in a wheelchair in profile, facing toward the centre of the image, under a banner with the text "e-democracy?" on it. In front of the person is stairs, at the top of the stairs is a table. On the table is a computer, whose screen says "Vote!" and has a red and a green button</p>
+ <p>The image is signed in the space under the floor that is at the top of the stairs with an "R" rune flipped backwards, somewhat resembling a "Я" with top and bottom border lines sloping upward from left to right, and is marked ©2013. It was actually drawn by Charles McCathie Nevile.</p>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html-longdesc/picture.png b/tests/wpt/web-platform-tests/html-longdesc/picture.png
new file mode 100644
index 00000000000..e4ebb708c7f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html-longdesc/picture.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html-longdesc/rebased/fail.html b/tests/wpt/web-platform-tests/html-longdesc/rebased/fail.html
new file mode 100644
index 00000000000..291ad8fc723
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html-longdesc/rebased/fail.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+ <meta charset="utf-8">
+ <head>
+ <title>Longdesc test Pass page</title>
+ </head>
+ <body>
+ <h1>Pass</h1>
+ <p>(The image is a drawn cartoon, on the right is a parson a wheelchair in profile, facing toward the centre of the image, under a banner with the text "e-democracy?" on it. In front of the person are some stairs, at the top of the stairs is a table. On the table is a computer, whose screen says "Vote!" and has a red and a green button)</p>
+ <p>The image is signed (in the space under the floor that is at the top of the stairs) with an "R" rune flipped backwards, somewhat resembling a "Я" with top and bottom border lines sloping upward from left to right, and is marked ©1999. It was actually drawn by Charles McCathie Nevile.</p>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html-longdesc/rebased/picture2.png b/tests/wpt/web-platform-tests/html-longdesc/rebased/picture2.png
new file mode 100644
index 00000000000..3697d0c8b19
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html-longdesc/rebased/picture2.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html-longdesc/reflected-changing-longdesc-manual.html b/tests/wpt/web-platform-tests/html-longdesc/reflected-changing-longdesc-manual.html
new file mode 100644
index 00000000000..5e3ac13757a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html-longdesc/reflected-changing-longdesc-manual.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Longdesc test: Reflection when longdesc changes</title>
+ </head>
+ <body>
+ <img src="picture.png" alt="the image" longdesc="fail.html">
+ <script>
+ var failingResult = document.querySelector('img[longdesc]').longDesc;
+ var newValue = '<img src="picture.png" alt="the image" longdesc="pass.html">';
+
+ document.querySelector('img').outerHTML = newValue;
+ document.location.href = document.querySelector('img[longdesc]').longDesc;
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html-media-capture/capture_audio-manual.html b/tests/wpt/web-platform-tests/html-media-capture/capture_audio-manual.html
new file mode 100644
index 00000000000..a1f0c3716ef
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html-media-capture/capture_audio-manual.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<meta charset='utf-8'>
+<title>HTML Media Capture Test: capture audio to produce one audio file</title>
+<link rel='author' title='Intel' href='http://www.intel.com'>
+<link rel='help' href='http://dev.w3.org/2009/dap/camera/#attributes'>
+<link rel='help' href='http://www.w3.org/TR/html5/forms.html#attr-input-accept'>
+<meta name='flags' content='interact'>
+<meta name="timeout" content="long">
+<script src='/resources/testharness.js'></script>
+<script src='/resources/testharnessreport.js'></script>
+
+<p>Clear all microphone permissions before running this test. If prompted for permission, please allow.</p>
+
+<p>After hitting the button below, capture an audio and then confirm the capturing.</p>
+
+<p>Note: All the actions need to be done in 60 seconds, otherwise it will get TIMEOUT.</p>
+
+<input type='file' accept='audio/*' capture>
+
+<div id='log'></div>
+
+<script>
+ var input;
+
+ setup(function() {
+ input = document.querySelector('input[type=file]');
+ }, {explicit_done: true});
+
+ async_test(function(t) {
+ input.onchange = t.step_func_done(function() {
+ assert_equals(input.files.length, 1, 'Should capture one file');
+ assert_regexp_match(input.files[0].type, /^audio\//, 'The captured file should be type of audio');
+ });
+ done();
+ });
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html-media-capture/capture_audio_cancel-manual.html b/tests/wpt/web-platform-tests/html-media-capture/capture_audio_cancel-manual.html
new file mode 100644
index 00000000000..73e486000d4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html-media-capture/capture_audio_cancel-manual.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<meta charset='utf-8'>
+<title>HTML Media Capture Test: user denial of captured audio leading to no capture</title>
+<link rel='author' title='Intel' href='http://www.intel.com'>
+<link rel='help' href='http://dev.w3.org/2009/dap/camera/#attributes'>
+<link rel='help' href='http://www.w3.org/TR/html5/forms.html#attr-input-accept'>
+<meta name='flags' content='interact'>
+
+<p>Clear all microphone permissions before running this test. If prompted for permission, please allow.</p>
+
+<p>After hitting the button below</p>
+
+<ul>
+
+ <li>capture an audio and then cancel the capturing;</li>
+
+ <li>capture an audio and then confirm the capturing.</li>
+
+</ul>
+
+<p>Test passes if there is no captured audio saved to the system's data storage.</p>
+
+<input type='file' accept='audio/*' capture>
+
diff --git a/tests/wpt/web-platform-tests/html-media-capture/capture_fallback_file_upload.html b/tests/wpt/web-platform-tests/html-media-capture/capture_fallback_file_upload.html
new file mode 100644
index 00000000000..2d25aa14f84
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html-media-capture/capture_fallback_file_upload.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset='utf-8'>
+ <title>HTML Media Capture Test: capture_fallback_file_upload</title>
+ <link rel='author' title='Intel' href='http://www.intel.com'>
+ <link rel='help' href='http://www.w3.org/TR/html-media-capture/#the-capture-attribute'>
+ <link rel='help' href='http://www.w3.org/TR/html5/forms.html#file-upload-state-(type=file)'>
+ <meta name='flags' content='interact'>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+ </head>
+ <body>
+ <p>This test validates that the user agent must act as if there was no capture attribute, when the accept attribute value is set to a MIME type that has no associated capture control type.</p>
+
+ <p>Test steps:</p>
+ <ol>
+ <li>Download <a href='support/upload.txt'>upload.txt</a> to local.</li>
+ <li>Select the local upload.txt file to run the test.</li>
+ </ol>
+
+ <form>
+ <input id='fileChooser' type='file' accept='text/plain' capture>
+ </form>
+
+ <div id='log'></div>
+
+ <script>
+ setup({explicit_done: true, explicit_timeout: true});
+
+ var fileInput = document.querySelector('#fileChooser');
+
+ on_event(fileInput, 'change', function(evt) {
+ test(function() {
+ var fileList = document.querySelector('#fileChooser').files;
+ assert_equals(fileList.length, 1, 'fileList length is 1');
+ assert_equals(fileList.item(0).name, 'upload.txt', 'file name string is "upload.txt"');
+ }, 'Check if input.capture fallback to file upload when the accept attribute value is set to a MIME type that has no associated capture control type');
+
+ done();
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html-media-capture/capture_image-manual.html b/tests/wpt/web-platform-tests/html-media-capture/capture_image-manual.html
new file mode 100644
index 00000000000..1b15fb3691f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html-media-capture/capture_image-manual.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<meta charset='utf-8'>
+<title>HTML Media Capture Test: capture image to produce one image file</title>
+<link rel='author' title='Intel' href='http://www.intel.com'>
+<link rel='help' href='http://dev.w3.org/2009/dap/camera/#attributes'>
+<link rel='help' href='http://www.w3.org/TR/html5/forms.html#attr-input-accept'>
+<meta name='flags' content='interact'>
+<meta name="timeout" content="long">
+<script src='/resources/testharness.js'></script>
+<script src='/resources/testharnessreport.js'></script>
+
+<p>Clear all camera permissions before running this test. If prompted for permission, please allow.</p>
+
+<p>After hitting the button below, capture an image and then confirm the capturing.</p>
+
+<p>Note: All the actions need to be done in 60 seconds, otherwise it will get TIMEOUT.</p>
+
+<input type='file' accept='image/*' capture>
+
+<div id='log'></div>
+
+<script>
+ var input;
+
+ setup(function() {
+ input = document.querySelector('input[type=file]');
+ }, {explicit_done: true});
+
+ async_test(function(t) {
+ input.onchange = t.step_func_done(function() {
+ assert_equals(input.files.length, 1, 'Should capture one file');
+ assert_regexp_match(input.files[0].type, /^image\//, 'The captured file should be type of image');
+ });
+ done();
+ });
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html-media-capture/capture_image_cancel-manual.html b/tests/wpt/web-platform-tests/html-media-capture/capture_image_cancel-manual.html
new file mode 100644
index 00000000000..fafb5d5118f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html-media-capture/capture_image_cancel-manual.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<meta charset='utf-8'>
+<title>HTML Media Capture Test: user denial of captured image leading to no capture</title>
+<link rel='author' title='Intel' href='http://www.intel.com'>
+<link rel='help' href='http://dev.w3.org/2009/dap/camera/#attributes'>
+<link rel='help' href='http://www.w3.org/TR/html5/forms.html#attr-input-accept'>
+<meta name='flags' content='interact'>
+
+<p>Clear all camera permissions before running this test. If prompted for permission, please allow.</p>
+
+<p>After hitting the button below</p>
+
+<ul>
+
+ <li>capture an image and then cancel the capturing;</li>
+
+ <li>capture an image and then confirm the capturing.</li>
+
+</ul>
+
+<p>Test passes if there is no captured image saved to the system's data storage.</p>
+
+<input type='file' accept='image/*' capture>
+
diff --git a/tests/wpt/web-platform-tests/html-media-capture/capture_reflect.html b/tests/wpt/web-platform-tests/html-media-capture/capture_reflect.html
new file mode 100644
index 00000000000..6dd40cc9b0e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html-media-capture/capture_reflect.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset='utf-8'>
+ <title>HTML Media Capture Test: capture_reflect</title>
+ <link rel='author' title='Intel' href='http://www.intel.com/'>
+ <link rel='help' href='http://www.w3.org/TR/html-media-capture/#the-capture-attribute'>
+ <link rel='help' href='http://www.w3.org/html/wg/drafts/html/CR/infrastructure.html#reflect'>
+ <link rel='help' href='http://www.w3.org/html/wg/drafts/html/CR/infrastructure.html#boolean-attributes'>
+ <meta name='flags' content='dom'>
+ <meta name='assert' content='Test checks that the capture IDL attribute must reflect the content attribute of the same name.'>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+ </head>
+ <body>
+ <pre style='display:none'>
+ partial interface HTMLInputElement {
+ attribute boolean capture;
+ };
+ </pre>
+
+ <div style='display:none'>
+ <input id='absent' type='file' accept='image/*'>
+ <input id='present' type='file' accept='image/*' capture>
+ <input id='present-empty-string' type='file' accept='image/*' capture=''>
+ <input id='present-canonical-name' type='file' accept='image/*' capture=capture>
+ </div>
+
+ <div id='log'></div>
+
+ <script>
+ test(function() {
+ var inputs = document.querySelectorAll('input');
+ for (var i=0, obj; i<inputs.length, obj=inputs[i]; i++) {
+ assert_own_property(obj, 'capture');
+ assert_equals(typeof obj.capture, 'boolean');
+ }
+ }, 'Element input should have own property capture');
+
+ test(function() {
+ assert_false(document.querySelector('#absent').capture);
+ }, 'input.capture is false when the capture attribute is absent');
+
+ test(function() {
+ assert_true(document.querySelector('#present').capture);
+ }, 'input.capture is true when the capture attribute is present');
+
+ test(function() {
+ assert_true(document.querySelector('#present-empty-string').capture);
+ }, 'input.capture is true when the capture attribute is present as empty string');
+
+ test(function() {
+ assert_true(document.querySelector('#present-canonical-name').capture);
+ }, 'input.capture is true when the capture attribute is present as canonical name');
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html-media-capture/capture_video-manual.html b/tests/wpt/web-platform-tests/html-media-capture/capture_video-manual.html
new file mode 100644
index 00000000000..b54abae0eb5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html-media-capture/capture_video-manual.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<meta charset='utf-8'>
+<title>HTML Media Capture Test: capture video to produce one video file</title>
+<link rel='author' title='Intel' href='http://www.intel.com'>
+<link rel='help' href='http://dev.w3.org/2009/dap/camera/#attributes'>
+<link rel='help' href='http://www.w3.org/TR/html5/forms.html#attr-input-accept'>
+<meta name='flags' content='interact'>
+<meta name="timeout" content="long">
+<script src='/resources/testharness.js'></script>
+<script src='/resources/testharnessreport.js'></script>
+
+<p>Clear all camera/microphone permissions before running this test. If prompted for permission, please allow.</p>
+
+<p>After hitting the button below, capture an video and then confirm the capturing.</p>
+
+<p>Note: All the actions need to be done in 60 seconds, otherwise it will get TIMEOUT.</p>
+
+<input type='file' accept='video/*' capture>
+
+<div id='log'></div>
+
+<script>
+ var input;
+
+ setup(function() {
+ input = document.querySelector('input[type=file]');
+ }, {explicit_done: true});
+
+ async_test(function(t) {
+ input.onchange = t.step_func_done(function() {
+ assert_equals(input.files.length, 1, 'Should capture one file');
+ assert_regexp_match(input.files[0].type, /^video\//, 'The captured file should be type of video');
+ });
+ done();
+ });
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html-media-capture/capture_video_cancel-manual.html b/tests/wpt/web-platform-tests/html-media-capture/capture_video_cancel-manual.html
new file mode 100644
index 00000000000..645473701c8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html-media-capture/capture_video_cancel-manual.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<meta charset='utf-8'>
+<title>HTML Media Capture Test: user denial of captured video leading to no capture</title>
+<link rel='author' title='Intel' href='http://www.intel.com'>
+<link rel='help' href='http://dev.w3.org/2009/dap/camera/#attributes'>
+<link rel='help' href='http://www.w3.org/TR/html5/forms.html#attr-input-accept'>
+<meta name='flags' content='interact'>
+
+<p>Clear all camera/microphone permissions before running this test. If prompted for permission, please allow.</p>
+
+<p>After hitting the button below</p>
+
+<ul>
+
+ <li>capture an video and then cancel the capturing;</li>
+
+ <li>capture an video and then confirm the capturing.</li>
+
+</ul>
+
+<p>Test passes if there is no captured video saved to the system's data storage.</p>
+
+<input type='file' accept='video/*' capture>
+
diff --git a/tests/wpt/web-platform-tests/html-media-capture/idlharness.html b/tests/wpt/web-platform-tests/html-media-capture/idlharness.html
new file mode 100644
index 00000000000..a204764ae87
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html-media-capture/idlharness.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset='utf-8'>
+ <title>HTML Media Capture IDL tests</title>
+ <link rel='author' title='Intel' href='http://www.intel.com/'>
+ <link rel='help' href='http://www.w3.org/TR/html-media-capture/#conformance'>
+ <link rel='help' href='http://www.w3.org/TR/html-media-capture/#the-capture-attribute'>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+ <script src='/resources/WebIDLParser.js'></script>
+ <script src='/resources/idlharness.js'></script>
+ </head>
+ <body>
+ <h1>HTML Media Capture IDL tests</h1>
+ <div id='log'></div>
+
+ <pre id='untested_idl' style='display:none'>
+ interface HTMLInputElement {
+ };
+ interface HTMLElement {
+ };
+ interface Element{
+ };
+ </pre>
+
+ <pre id='idl' style='display:none'>
+ partial interface HTMLInputElement {
+ attribute boolean capture;
+ };
+ </pre>
+
+ <form style='display:none'>
+ <input id='testElement' type='file' accept='image/*' capture>
+ </form>
+
+ <script>
+ (function() {
+ var idl_array = new IdlArray();
+
+ idl_array.add_untested_idls(document.getElementById('untested_idl').textContent);
+ idl_array.add_idls(document.getElementById('idl').textContent);
+
+ var testElement = document.getElementById('testElement');
+ idl_array.add_objects({HTMLInputElement: [testElement]});
+ idl_array.test();
+ })();
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html-media-capture/support/upload.txt b/tests/wpt/web-platform-tests/html-media-capture/support/upload.txt
new file mode 100644
index 00000000000..e965047ad7c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html-media-capture/support/upload.txt
@@ -0,0 +1 @@
+Hello
diff --git a/tests/wpt/web-platform-tests/html/browsers/.gitkeep b/tests/wpt/web-platform-tests/html/browsers/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/.gitkeep b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/aborting-a-document-load/.gitkeep b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/aborting-a-document-load/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/aborting-a-document-load/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/history-traversal/.gitkeep b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/history-traversal/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/history-traversal/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/history-traversal/PopStateEvent.html b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/history-traversal/PopStateEvent.html
new file mode 100644
index 00000000000..fcb7288c8f8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/history-traversal/PopStateEvent.html
@@ -0,0 +1,31 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Synthetic popstate events</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function () {
+ assert_throws('NotSupportedError', function() {
+ document.createEvent('PopStateEvent');
+ }, 'document.createEvent("PopStateEvent") should not be supported');
+}, 'document.createEvent');
+
+test(function () {
+ assert_false('initPopStateEvent' in PopStateEvent.prototype,
+ 'There should be no PopStateEvent#initPopStateEvent');
+}, 'initPopStateEvent');
+
+test(function () {
+ var state = history.state;
+ var data;
+ window.addEventListener('popstate', function (e) {
+ data = e.state;
+ });
+ window.dispatchEvent(new PopStateEvent('popstate', {
+ 'state': {testdata:true}
+ }));
+ assert_true(data.testdata,'state data was corrupted');
+ assert_equals(history.state, state, "history.state was NOT set by dispatching the event");
+}, 'Dispatching a synthetic PopStateEvent');
+</script>
diff --git a/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/history-traversal/contains.json b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/history-traversal/contains.json
new file mode 100644
index 00000000000..90b3466688c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/history-traversal/contains.json
@@ -0,0 +1,6 @@
+[
+ {
+ "id": "event-definitions-0",
+ "original_id": "event-definitions-0"
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/navigating-across-documents/.gitkeep b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/navigating-across-documents/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/navigating-across-documents/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/read-html/.gitkeep b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/read-html/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/read-html/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/read-media/.gitkeep b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/read-media/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/read-media/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/read-media/pageload-image.html b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/read-media/pageload-image.html
new file mode 100644
index 00000000000..52151b8deb7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/read-media/pageload-image.html
@@ -0,0 +1,30 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Media documents: image</title>
+ <link rel="author" title="Michael Ventnor" href="mailto:mventnor@mozilla.com">
+ <link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#read-media">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+<script>
+ var t = async_test("The document for a standalone media file should have one child in the body.");
+
+ function frameLoaded() {
+ var testframe = document.getElementById('testframe');
+ var testframeChildren = testframe.contentDocument.body.childNodes;
+ assert_equals(testframeChildren.length, 1, "Body of image document has 1 child");
+ assert_equals(testframeChildren[0].nodeName, "IMG", "Only child of body must be an <img> element");
+ assert_equals(testframeChildren[0].namespaceURI, "http://www.w3.org/1999/xhtml",
+ "Only child of body must be an HTML element");
+ t.done();
+ }
+</script>
+</head>
+<body>
+ <div id="log"></div>
+ <iframe id="testframe" onload="t.step(frameLoaded)"
+ src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAAXNSR0IArs4c6QAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9oMFgQGMyFwHucAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAADElEQVQI12P4//8/AAX+Av7czFnnAAAAAElFTkSuQmCC"></iframe>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/read-media/pageload-video.html b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/read-media/pageload-video.html
new file mode 100644
index 00000000000..13bc5db4a43
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/read-media/pageload-video.html
@@ -0,0 +1,30 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Media documents: video</title>
+ <link rel="author" title="Michael Ventnor" href="mailto:mventnor@mozilla.com">
+ <link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#read-media">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+<script>
+ var t = async_test("The document for a standalone media file should have one child in the body.");
+
+ function frameLoaded() {
+ var testframe = document.getElementById('testframe');
+ var testframeChildren = testframe.contentDocument.body.childNodes;
+ assert_equals(testframeChildren.length, 1, "Body of image document has 1 child");
+ assert_equals(testframeChildren[0].nodeName, "VIDEO", "Only child of body must be an <video> element");
+ assert_equals(testframeChildren[0].namespaceURI, "http://www.w3.org/1999/xhtml",
+ "Only child of body must be an HTML element");
+ t.done();
+ }
+</script>
+</head>
+<body>
+ <div id="log"></div>
+ <iframe id="testframe" onload="t.step(frameLoaded)"
+ src="data:video/webm,"></iframe>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/read-multipart-x-mixed-replace/.gitkeep b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/read-multipart-x-mixed-replace/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/read-multipart-x-mixed-replace/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/read-plugin/.gitkeep b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/read-plugin/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/read-plugin/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/read-text/.gitkeep b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/read-text/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/read-text/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/read-text/load-text-plain.html b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/read-text/load-text-plain.html
new file mode 100644
index 00000000000..5c7f08444a3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/read-text/load-text-plain.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<title>Page load processing model for text files</title>
+<link rel="author" title="Ms2ger" href="ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#read-text">
+<link rel="stylesheet" href="/resources/testharness.css">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var t = async_test("Checking document metadata for text file");
+var tD = async_test("Checking DOM for text file");
+var tC = async_test("Checking contents for text file");
+var iframe = document.body.appendChild(document.createElement("iframe"));
+iframe.onload = function(e) {
+ var doc = iframe.contentDocument;
+ t.step(function() {
+ assert_equals(doc.compatMode, "BackCompat");
+ assert_equals(doc.contentType, "text/plain");
+ assert_equals(doc.doctype, null);
+ t.done();
+ })
+ tD.step(function() {
+ assert_equals(doc.childNodes.length, 1, "Document should have 1 child")
+ assert_equals(doc.documentElement.tagName, "HTML");
+ assert_equals(doc.documentElement.childNodes.length, 2,
+ "Root element should have 2 children")
+ assert_equals(doc.documentElement.firstChild.tagName, "HEAD");
+ assert_equals(doc.documentElement.lastChild.tagName, "BODY");
+ assert_equals(doc.documentElement.lastChild.childNodes.length, 1,
+ "Body element should have 1 child")
+ assert_equals(doc.documentElement.lastChild.firstChild.tagName, "PRE");
+ tD.done();
+ })
+ tC.step(function() {
+ assert_equals(doc.documentElement.lastChild.firstChild.firstChild.data,
+ "This is a sample text/plain document.\n\nThis is not an HTML document.\n\n");
+ tC.done();
+ })
+};
+iframe.src = "../../../../common/text-plain.txt";
+</script>
diff --git a/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/read-ua-inline/.gitkeep b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/read-ua-inline/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/read-ua-inline/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/read-xml/.gitkeep b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/read-xml/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/read-xml/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/scroll-to-fragid/.gitkeep b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/scroll-to-fragid/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/scroll-to-fragid/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/.gitkeep b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/001-1.html b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/001-1.html
new file mode 100644
index 00000000000..72f41ae3e8d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/001-1.html
@@ -0,0 +1,23 @@
+<!DOCTYPE HTML>
+<script>
+ t = opener.t;
+ do_test = t.step(function () {
+ localStorage.test6564729 += '4';
+ var d = document;
+ var e = document.open(); // has no effect (ignore-opens-during-unload > 0)
+ localStorage.test6564729 += (e == d) ? '5' : 'A [' + e + '] ';
+ document.write('FAIL - document.write executed and blocked navigation!'); // has no effect (ignore-opens-during-unload > 0)
+ localStorage.test6564729 += document.body.textContent.match('FAIL') ? 'B' : '6';
+ document.close(); // has no effect (no script-created parser)
+ localStorage.test6564729 += '7';
+ })
+onload = t.step_func(function() {
+ localStorage.test6564729 = '0';
+ setTimeout(t.step_func(function() {document.links[0].click()}));
+});
+</script>
+<body onbeforeunload="localStorage.test6564729 += '1'"
+ onpagehide="localStorage.test6564729 += '3'"
+ onunload="do_test()">
+<p><a href="001a.html">Follow this link to run the test.</a>
+<p><iframe src="001b.html"></iframe>
diff --git a/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/001.html b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/001.html
new file mode 100644
index 00000000000..b9e018df538
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/001.html
@@ -0,0 +1,15 @@
+<!doctype html>
+<title>document.open in unload</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var t = async_test();
+var win;
+
+t.step(function() {
+ win = window.open("001-1.html");
+});
+
+add_completion_callback(function() {win.close()});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/001a.html b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/001a.html
new file mode 100644
index 00000000000..36d4188b9e6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/001a.html
@@ -0,0 +1,7 @@
+<!DOCTYPE HTML>
+<script>
+opener.t.step(function() {
+ opener.assert_equals(localStorage.test6564729, '0123456789');
+ opener.t.done();
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/001b.html b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/001b.html
new file mode 100644
index 00000000000..eaafc371a12
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/001b.html
@@ -0,0 +1,5 @@
+<!DOCTYPE HTML>
+<body onbeforeunload="localStorage.test6564729 += '2'"
+ onpagehide="localStorage.test6564729 += '8'"
+ onunload="localStorage.test6564729 += '9'">
+<p>Inner frame \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/002-1.html b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/002-1.html
new file mode 100644
index 00000000000..0e6f7d967be
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/002-1.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML>
+<script>
+ var t = opener.t;
+
+ var do_test = t.step_func(function() {
+ localStorage.test6564729 += '1';
+ var d = document;
+ var e = document.open(); // unload triggered here - beforeunload 2, 3 in 002b; pagehide 4, unload 5, pagehide 6 in 002b, unload 7 in 002b
+ localStorage.test6564729 += (e == d) ? '8' : 'X';
+ var s = 'FAIL if you see this | ' + localStorage.test6564729;
+ document.write(s);
+ localStorage.test6564729 += document.body.textContent == s ? '9' : 'x';
+ document.close();
+ localStorage.test6564729 += 'Z';
+ document.body.textContent += ' // ' + localStorage.test6564729;
+ location = '002a.html'; // unload triggers again here, but they're not registered event listeners any more
+ });
+
+onload = t.step_func(function() {
+ localStorage.test6564729 = '0';
+ setTimeout(function() {document.getElementsByTagName("input")[0].click()}, 100);
+});
+</script>
+<body onbeforeunload="localStorage.test6564729 += '2'"
+ onpagehide="localStorage.test6564729 += '4'"
+ onunload="localStorage.test6564729 += '5'">
+<input type=button value="Activate this button to run the test" onclick="do_test()">
+<p><iframe src="002b.html"></iframe>
diff --git a/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/002.html b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/002.html
new file mode 100644
index 00000000000..0d4cfd4359d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/002.html
@@ -0,0 +1,15 @@
+<!doctype html>
+<title>document.open in unload</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var t = async_test();
+var win;
+
+t.step(function() {
+ win = window.open("002-1.html");
+});
+
+add_completion_callback(function() {win.close()});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/002a.html b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/002a.html
new file mode 100644
index 00000000000..d11f670869c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/002a.html
@@ -0,0 +1,7 @@
+<!DOCTYPE HTML>
+<script>
+ opener.t.step(function() {
+ opener.assert_equals(localStorage.test6564729, '0123456789Z');
+ opener.t.done();
+ });
+</script>
diff --git a/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/002b.html b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/002b.html
new file mode 100644
index 00000000000..d08a7a8addf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/002b.html
@@ -0,0 +1,5 @@
+<!DOCTYPE HTML>
+<body onbeforeunload="localStorage.test6564729 += '3'"
+ onpagehide="localStorage.test6564729 += '6'"
+ onunload="localStorage.test6564729 += '7'">
+<p>Inner frame \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/003-1.html b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/003-1.html
new file mode 100644
index 00000000000..b3a4754b851
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/003-1.html
@@ -0,0 +1,23 @@
+<!DOCTYPE HTML>
+<script>
+ var t = opener.t;
+ var do_test = t.step_func(function() {
+ localStorage.test6564729 += '1';
+ var d = document;
+ var e = document.open(); // has no effect (ignore-opens-during-unload > 0 because we're in beforeunload)
+ localStorage.test6564729 += (e == d) ? '2' : 'A [' + e + '] ';
+ document.write('FAIL - document.write executed and blocked navigation!'); // has no effect (ignore-opens-during-unload > 0)
+ localStorage.test6564729 += document.body.textContent.match('FAIL') ? 'B' : '3';
+ document.close(); // has no effect (no script-created parser)
+ localStorage.test6564729 += '4';
+ })
+
+ onload=t.step_func(function() {localStorage.test6564729 = '0'; setTimeout(t.step_func(function() {document.links[0].click()}), 100)})
+
+</script>
+<body
+ onbeforeunload="do_test()"
+ onpagehide="localStorage.test6564729 += '6'"
+ onunload="localStorage.test6564729 += '7'">
+<p><a href="003a.html">Follow this link to run the test.</a>
+<p><iframe src="003b.html"></iframe>
diff --git a/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/003.html b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/003.html
new file mode 100644
index 00000000000..e303b40f08c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/003.html
@@ -0,0 +1,15 @@
+<!doctype html>
+<title>document.open in beforeunload with link</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var t = async_test();
+var win;
+
+t.step(function() {
+ win = window.open("003-1.html");
+});
+
+add_completion_callback(function() {win.close()});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/003a.html b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/003a.html
new file mode 100644
index 00000000000..5393fa221e9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/003a.html
@@ -0,0 +1,8 @@
+<!DOCTYPE HTML>
+<p>FAIL</p>
+<script>
+opener.t.step(function() {
+ opener.assert_equals(localStorage.test6564729, '0123456789')
+ opener.t.done();
+})
+</script>
diff --git a/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/003b.html b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/003b.html
new file mode 100644
index 00000000000..c8f1917b85f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/003b.html
@@ -0,0 +1,5 @@
+<!DOCTYPE HTML>
+<body onbeforeunload="localStorage.test6564729 += '5'"
+ onpagehide="localStorage.test6564729 += '8'"
+ onunload="localStorage.test6564729 += '9'">
+<p>Inner frame \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/004-1.html b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/004-1.html
new file mode 100644
index 00000000000..06aba08af61
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/004-1.html
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML>
+<script>
+ var t = opener.t;
+ var do_test = t.step_func(function() {
+ localStorage.test6564729 += 'B';
+ var d = document;
+ var e = document.open(); // unload triggered here - beforeunload C, D in 004b; pagehide E, unload F, pagehide G in 004b, unload HIJK in 004b
+ localStorage.test6564729 += (e == d) ? 'L' : 'Y';
+ var s = 'FAIL if you see this | ' + localStorage.test6564729;
+ document.write(s);
+ localStorage.test6564729 += document.body.textContent == s ? 'M' : 'y';
+ document.close();
+ localStorage.test6564729 += 'N';
+ location = '004a.html'; // unload triggers again here, but they're not registered event listeners any more
+ })
+onload = t.step_func(function() {
+ localStorage.test6564729 = 'A';
+ setTimeout(t.step_func(function() {document.getElementsByTagName("input")[0].click()}), 100);
+})
+</script>
+<body onbeforeunload="localStorage.test6564729 += 'C'"
+ onpagehide="localStorage.test6564729 += 'E'"
+ onunload="localStorage.test6564729 += 'F'">
+<input type=button value="Activate this button to run the test" onclick="do_test()">
+<p><iframe src="004b.html"></iframe>
diff --git a/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/004.html b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/004.html
new file mode 100644
index 00000000000..15bd42341c6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/004.html
@@ -0,0 +1,15 @@
+<!doctype html>
+<title>document.open in beforeunload with button</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var t = async_test();
+var win;
+
+t.step(function() {
+ win = window.open("004-1.html");
+});
+
+add_completion_callback(function() {win.close()});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/004a.html b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/004a.html
new file mode 100644
index 00000000000..117e2b94ae3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/004a.html
@@ -0,0 +1,8 @@
+<!DOCTYPE HTML>
+<p>FAIL</p>
+<script>
+opener.t.step(function() {
+ opener.assert_equals(localStorage.test6564729, 'ABCDEFGHIJKLMN');
+ opener.t.done();
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/004b.html b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/004b.html
new file mode 100644
index 00000000000..788937a0b04
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/004b.html
@@ -0,0 +1,18 @@
+<!DOCTYPE HTML>
+<script>
+ function testRun() {
+ localStorage.test6564729 += 'H';
+ var d = parent.document;
+ var e = parent.document.open(); // no effect, since that document is already in unload
+ localStorage.test6564729 += (e == d) ? 'I' : 'X';
+ var s = 'FAIL';
+ document.write(s);
+ localStorage.test6564729 += document.body.textContent == s ? 'x' : 'J';
+ document.close();
+ localStorage.test6564729 += 'K';
+ }
+</script>
+<body onbeforeunload="localStorage.test6564729 += 'D'"
+ onpagehide="localStorage.test6564729 += 'G'"
+ onunload="testRun()">
+<p>Inner frame \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/005-1.html b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/005-1.html
new file mode 100644
index 00000000000..7b81a9f115d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/005-1.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML>
+<script>
+onload = opener.t.step_func(function() {
+ localStorage.test6564729 = '0'
+ setTimeout(opener.t.step_func(function() {document.links[0].click()}), 100);
+});
+</script>
+<body
+ onbeforeunload="localStorage.test6564729 += '1'"
+ onpagehide="localStorage.test6564729 += '3'"
+ onunload="localStorage.test6564729 += '4'">
+<p><a href="005a.html">Follow this link to run the test.</a>
+<p><iframe src="005b.html"></iframe>
diff --git a/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/005.html b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/005.html
new file mode 100644
index 00000000000..61033c81c0a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/005.html
@@ -0,0 +1,15 @@
+<!doctype html>
+<title>document.open in pagehide in iframe</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var t = async_test();
+var win;
+
+t.step(function() {
+ win = window.open("005-1.html");
+});
+
+add_completion_callback(function() {win.close()});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/005a.html b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/005a.html
new file mode 100644
index 00000000000..5185d3b9214
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/005a.html
@@ -0,0 +1,8 @@
+<!DOCTYPE HTML>
+<p>FAIL</p>
+<script>
+opener.t.step(function() {
+ opener.assert_equals(localStorage.test6564729, '012345678')
+ opener.t.done();
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/005b.html b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/005b.html
new file mode 100644
index 00000000000..476e8e38c49
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/005b.html
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML>
+<script>
+ var t = parent.opener.t;
+ var do_test = t.step_func(function () {
+ localStorage.test6564729 += '5';
+ var s = 'FAIL: document.open() has canceled the navigation (' + localStorage.test6564729 + ')';
+ parent.document.open();
+ parent.document.write(s);
+ parent.document.close();
+ localStorage.test6564729 += parent.document.body.textContent.match('FAIL') == s ? 'X' : '6';
+ localStorage.test6564729 += '7';
+ });
+</script>
+<body onbeforeunload="localStorage.test6564729 += '2'"
+ onpagehide="do_test()"
+ onunload="localStorage.test6564729 += '8'">
+<p>Inner frame
diff --git a/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/contains.json b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/contains.json
new file mode 100644
index 00000000000..4ebca09bfda
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/unloading-documents/contains.json
@@ -0,0 +1,6 @@
+[
+ {
+ "id": "event-definition",
+ "original_id": "event-definition"
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/.gitkeep b/tests/wpt/web-platform-tests/html/browsers/history/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/history/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/history-notes/.gitkeep b/tests/wpt/web-platform-tests/html/browsers/history/history-notes/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/history/history-notes/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/.gitkeep b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/001.html b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/001.html
new file mode 100644
index 00000000000..0e5632bbcdf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/001.html
@@ -0,0 +1,333 @@
+<!doctype html>
+<html>
+ <head>
+ <title>history.pushState tests</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript">
+//does not test for firing of popstate onload, because this was dropped from the specification on 25 March 2011
+//covers history.state after load, in accordance with the specification draft from 25 March 2011
+//history.state before load is tested in 006 and 007
+//does not test for structured cloning of FileList, File or Blob interfaces, as these require manual file selection
+
+//**This test assumes that assignments to location.hash will be synchronous - this is how all browsers implement it.
+//The spec (as of 25 March 2011) disagrees.**//
+
+var histlength, atstep = 0, lasttimer;
+setup({explicit_done:true}); //tests should take under 6 seconds + execution time
+
+window.onload = function () {
+ if( location.protocol == 'file:' ) {
+ document.getElementsByTagName('p')[0].innerHTML = 'ERROR: This test cannot be run from file: (URL resolving will not work). It must be loaded over HTTP.';
+ return;
+ } else if( location.protocol == 'https:' ) {
+ document.getElementsByTagName('p')[0].innerHTML += '<br>WARNING: Browsers may intentionally fail to update history.length when pages are loaded over HTTPS, as a privacy restriction. If possible, load this page over HTTP.';
+ }
+ //use a timeout, because some browsers intentionally do not add history entries for URL changes in the onload thread
+ setTimeout(testinit,100);
+};
+function testinit() {
+ atstep = 1;
+ histlength = history.length;
+ iframe = document.getElementsByTagName('iframe')[0].src = 'blank2.html';
+ //reportload will now be called by the onload handler for the iframe
+}
+function reportload() {
+ var iframe = document.getElementsByTagName('iframe')[0], hashchng = false;
+ var canvassup = false, cloneobj;
+
+ function tests1() {
+ //Firefox may fail when reloading, because it recovers iframe state, and therefore does not see the need to alter history length
+ test(function () { assert_equals( history.length, histlength + 1, 'make sure that you loaded the test in a new tab/window' ); }, 'history.length should update when loading pages in an iframe');
+ histlength = history.length;
+ iframe.contentWindow.location.hash = 'test'; //should be synchronous **SEE COMMENT AT TOP OF FILE
+ test(function () {
+ assert_equals( history.length, histlength + 1, 'make sure that you loaded the test in a new tab/window' );
+ }, 'history.length should update when setting location.hash');
+ test(function () { assert_true( !!history.pushState, 'critical test; ignore any failures after this' ); }, 'history.pushState must exist'); //assert_exists does not allow prototype inheritance
+ test(function () { assert_true( !!iframe.contentWindow.history.pushState, 'critical test; ignore any failures after this' ); }, 'history.pushState must exist within iframes');
+ test(function () {
+ assert_equals( iframe.contentWindow.history.state, null );
+ }, 'initial history.state should be null');
+ test(function () {
+ histlength = history.length;
+ iframe.contentWindow.history.pushState('','');
+ assert_equals( history.length, histlength + 1 );
+ }, 'history.length should update when pushing a state');
+ test(function () {
+ assert_equals( iframe.contentWindow.history.state, '' );
+ }, 'history.state should update after a state is pushed');
+ histlength = history.length;
+ history.back();
+ setTimeout(tests2,50); //.back is queued to end of thread
+ }
+ function tests2() {
+ test(function () {
+ assert_equals( history.length, histlength );
+ }, 'history.length should not decrease after going back');
+ test(function () {
+ assert_equals( iframe.contentWindow.location.hash.replace(/^#/,''), 'test' );
+ }, 'traversing history must traverse pushed states');
+ history.go(-1);
+ setTimeout(tests3,50); //.go is queued to end of thread
+ }
+ function tests3() {
+ test(function () {
+ assert_equals( iframe.contentWindow.location.hash.replace(/^#/,''), '', '(this could cause other failures later on)' );
+ }, 'traversing history must also traverse hash changes');
+ //Safari 5.0.3 fails here - it navigates *this* document to the *iframe's* location, instead of just navigating the iframe
+ history.go(2);
+ setTimeout(tests4,50); //.go is queued to end of thread
+ }
+ function tests4() {
+ test(function () {
+ //Firefox 4 beta 11 has a messed up error object, which does not have the right error type or .SECURITY_ERR property
+ assert_throws('SECURITY_ERR',function () { history.pushState('','','//exa mple'); });
+ }, 'pushState must not be allowed to create invalid URLs');
+ test(function () {
+ assert_throws('SECURITY_ERR',function () { history.pushState('','','http://www.example.com/'); });
+ }, 'pushState must not be allowed to create cross-origin URLs');
+ test(function () {
+ assert_throws('SECURITY_ERR',function () { history.pushState('','','about:blank'); });
+ }, 'pushState must not be allowed to create cross-origin URLs (about:blank)');
+ test(function () {
+ assert_throws('SECURITY_ERR',function () { history.pushState('','','data:text/html,'); });
+ }, 'pushState must not be allowed to create cross-origin URLs (data:URI)');
+ test(function () {
+ assert_throws('SECURITY_ERR',function () { iframe.contentWindow.history.pushState('','','http://www.example.com/'); },iframe.contentWindow);
+ }, 'security errors are expected to be thrown in the context of the document that owns the history object');
+ test(function () {
+ iframe.contentWindow.location.hash = 'test2';
+ assert_equals( iframe.contentWindow.location.hash.replace(/^#/,''), 'test2', 'location.hash did not change when told to' );
+ }, 'location.hash must be allowed to change (part 1)');
+ history.go(-1);
+ setTimeout(tests5,50); //.go is queued to end of thread
+ }
+ function tests5() {
+ test(function () {
+ assert_equals( iframe.contentWindow.location.hash.replace(/^#/,''), 'test', 'location.hash did not change when going back' );
+ }, 'location.hash must be allowed to change (part 2)');
+ test(function () {
+ iframe.contentWindow.history.pushState('','');
+ assert_equals( iframe.contentWindow.location.hash.replace(/^#/,''), 'test', 'location.hash changed when an unrelated state was pushed' );
+ }, 'pushState must not alter location.hash when no URL is provided');
+ history.go(1); //should do nothing, since the pushState should have removed the forward history
+ setTimeout(tests6,50); //.go is queued to end of thread
+ }
+ function tests6() {
+ test(function () {
+ assert_equals( iframe.contentWindow.location.hash.replace(/^#/,''), 'test' );
+ }, 'pushState must remove all history after the current state');
+ test(function () {
+ iframe.contentWindow.history.pushState('','','#test3');
+ assert_equals( iframe.contentWindow.location.hash.replace(/^#/,''), 'test3' );
+ }, 'pushState must be able to set location.hash');
+ //begin setup for "remove any tasks queued by the history traversal task source"
+ iframe.contentWindow.location.hash = '#test4';
+ iframe.contentWindow.history.go(-1); //must be queued
+ try {
+ //must remove the queued navigation in the same browsing context
+ iframe.contentWindow.history.pushState('','');
+ } catch(unsuperr) {}
+ //allow the browser to mistakenly run the .go if it is going to
+ //do not put two .go commands in the same thread, in case the browser mistakenly calculates the history position when
+ //calling .go instead of when executing the traversal task - that could give a false PASS in the next test otherwise
+ setTimeout(tests7,50);
+ }
+ function tests7() {
+ iframe.contentWindow.history.go(-1); //must be queued, but should not be removed this time
+ setTimeout(tests8,50); //.go is queued to end of thread
+ }
+ function tests8() {
+ test(function () {
+ assert_equals( iframe.contentWindow.location.hash.replace(/^#/,''), 'test4' );
+ }, 'pushState must remove any tasks queued by the history traversal task source');
+ //end "remove any tasks queued by the history traversal task source"
+ window.addEventListener('hashchange',function () { hashchng = true; },false);
+ try {
+ //push a state that changes the hash
+ iframe.contentWindow.history.pushState('','',iframe.contentWindow.location.pathname+'#test5');
+ } catch(unsuperr) {}
+ setTimeout(tests9,50); //allow the hashchange event to process, if the browser has mistakenly fired it
+ }
+ function tests9() {
+ test(function () {
+ assert_false( hashchng );
+ }, 'pushState must not fire hashchange events');
+ test(function () {
+ iframe.contentWindow.history.pushState('','','/testing_ignore_me_404');
+ assert_equals( iframe.contentWindow.location.pathname, '/testing_ignore_me_404' );
+ }, 'pushState must be able to set location.pathname');
+ test(function () {
+ var newURL = location.href.replace(/\/[^\/]*$/)+'/testing_ignore_me_404/';
+ iframe.contentWindow.history.pushState('','',newURL);
+ assert_equals( iframe.contentWindow.location.href, newURL );
+ }, 'pushState must be able to set absolute URLs to the same host');
+ test(function () {
+ assert_throws( 'DATA_CLONE_ERR', function () {
+ history.pushState({dummy:function () {}},'');
+ } );
+ }, 'pushState must not be able to use a function as data');
+ test(function () {
+ assert_throws( 'DATA_CLONE_ERR', function () {
+ history.pushState({dummy:window},'');
+ } );
+ }, 'pushState must not be able to use a DOM node as data');
+ test(function () {
+ try { a.b = c; } catch(errdata) {
+ assert_throws( 'DATA_CLONE_ERR', function () {
+ history.pushState({dummy:errdata},'');
+ } );
+ }
+ }, 'pushState must not be able to use an error object as data');
+ test(function () {
+ assert_throws( 'DATA_CLONE_ERR', function () {
+ iframe.contentWindow.history.pushState(document,'');
+ }, iframe.contentWindow );
+ }, 'security errors are expected to be thrown in the context of the document that owns the history object (2)');
+ cloneobj = {
+ nulldata: null,
+ udefdata: window.undefined,
+ booldata: true,
+ numdata: 1,
+ strdata: 'string data',
+ boolobj: new Boolean(true),
+ numobj: new Number(1),
+ strobj: new String('string data'),
+ datedata: new Date(),
+ regdata: /a/g,
+ arrdata: [1]
+ };
+ cloneobj.regdata.lastIndex = 1;
+ cloneobj.looped = cloneobj;
+ //test the ImageData type, if the browser supports it
+ var canvas = document.createElement('canvas');
+ if( canvas.getContext && ( canvas = canvas.getContext('2d') ) && canvas.createImageData ) {
+ canvassup = true;
+ cloneobj.imgdata = canvas.createImageData(1,1);
+ }
+ test(function () {
+ try {
+ iframe.contentWindow.history.pushState(cloneobj,'new title');
+ } catch(e) {
+ cloneobj.looped = null;
+ //try again because this object is needed for future tests
+ iframe.contentWindow.history.pushState(cloneobj,'new title');
+ //rethrow so the browser gets a FAIL for not coping with the circular reference; "internal structured cloning algorithm" step 1
+ throw(e);
+ }
+ }, 'pushState must be able to make structured clones of complex objects');
+ test(function () {
+ assert_equals( iframe.contentWindow.history.state && iframe.contentWindow.history.state.strdata, 'string data' );
+ }, 'history.state should also reference a clone of the original object');
+ test(function () {
+ assert_false( cloneobj === iframe.contentWindow.history.state );
+ }, 'history.state should be a clone of the original object, not a reference to it');
+ /*
+ behaviour is not defined per spec, and no known implementations do this
+ test(function () {
+ assert_equals( iframe.contentDocument.title, 'new title', 'not required for specification conformance' );
+ }, 'pushState MIGHT set the document title');
+ */
+ history.go(-1);
+ setTimeout(tests10,50); //.go is queued to end of thread
+ }
+ function tests10() {
+ var eventtime = setTimeout(function () { tests11(false); },500); //should be cleared by the event handler long before it has a chance to fire
+ iframe.contentWindow.addEventListener('popstate',function (e) { clearTimeout(eventtime); tests11(true,e); },false);
+ history.forward();
+ }
+ function tests11(hasFired,ev) {
+ test(function () {
+ assert_true( hasFired );
+ }, 'popstate event should fire when navigation occurs');
+ test(function () {
+ assert_true( !!ev && typeof(ev.state) != 'undefined', 'state information was not passed' );
+ assert_true( !!ev.state, 'state information does not contain the expected value - browser is probably stuck in the wrong history position' );
+ assert_equals( ev.state.nulldata, null, 'state null data was not correct' );
+ assert_equals( ev.state.udefdata, window.undefined, 'state undefined data was not correct' );
+ assert_true( ev.state.booldata, 'state boolean data was not correct' );
+ assert_equals( ev.state.numdata, 1, 'state numeric data was not correct' );
+ assert_equals( ev.state.strdata, 'string data', 'state string data was not correct' );
+ assert_true( !!ev.state.datedata.getTime, 'state date data was not correct' );
+ assert_exists( ev.state, 'regdata', 'state regex data was not correct' );
+ assert_equals( ev.state.regdata.source, 'a', 'state regex pattern data was not correct' );
+ assert_true( ev.state.regdata.global, 'state regex flag data was not correct' );
+ assert_equals( ev.state.regdata.lastIndex, 0, 'state regex lastIndex data was not correct' );
+ assert_equals( ev.state.arrdata.length, 1, 'state array data was not correct' );
+ assert_true( ev.state.boolobj.valueOf(), 'state boolean data was not correct' );
+ assert_equals( ev.state.numobj.valueOf(), 1, 'state numeric data was not correct' );
+ assert_equals( ev.state.strobj.valueOf(), 'string data', 'state string data was not correct' );
+ if( canvassup ) {
+ assert_equals( ev.state.imgdata.width, 1, 'state ImageData was not correct' );
+ }
+ }, 'popstate event should pass the state data');
+ test(function () {
+ assert_equals( ev.state.looped, ev.state );
+ }, 'state data should cope with circular object references');
+ test(function () {
+ assert_false( cloneobj === ev.state );
+ }, 'state data should be a clone of the original object, not a reference to it');
+ test(function () {
+ assert_equals( iframe.contentWindow.history.state && iframe.contentWindow.history.state.strdata, 'string data' );
+ }, 'history.state should also reference a clone of the original object (2)');
+ test(function () {
+ assert_false( cloneobj === iframe.contentWindow.history.state );
+ }, 'history.state should be a clone of the original object, not a reference to it (2)');
+ test(function () {
+ assert_false( iframe.contentWindow.history.state === ev.state );
+ }, 'history.state should be a separate clone of the object, not a reference to the object passed to the event handler');
+ try {
+ iframe.contentWindow.persistval = true;
+ iframe.contentWindow.history.pushState('','', location.href.replace(/\/[^\/]*$/,'/blank3.html') );
+ } catch(unsuperr) {}
+ //it's already cached, so this should be very fast if the browser mistakenly loads it
+ //it should not need to load at all, since it's just a pushed state
+ setTimeout(tests12,1000);
+ }
+ function tests12() {
+ test(function () {
+ assert_true( iframe.contentWindow.persistval && !iframe.contentWindow.forreal );
+ }, 'pushState should not actually load the new URL');
+ atstep = 3;
+ iframe.contentWindow.location.reload(); //load the real URL
+ lasttimer = setTimeout(function () { tests13(false); },3000); //should be cleared by the onload handler long before it has a chance to fire
+ }
+ function tests13(passed) {
+ test(function () {
+ assert_true( passed, 'expected a load event to fire when reloading the URL from cache, gave up waiting after 3 seconds' );
+ }, 'reloading a pushed state should actually load the new URL');
+ //try to make browsers behave when reloading so that the correct URL is recovered - does not always work
+ iframe.contentWindow.location.href = location.href.replace(/\/[^\/]*$/,'/blank.html');
+ done();
+ }
+
+ if( atstep == 1 ) {
+ //blank2 has loaded
+ atstep = 2;
+ //use a timeout, because some browsers intentionally do not add history entries for URL changes in an onload thread
+ setTimeout(tests1,100);
+ } else if( atstep == 3 ) {
+ //blank3 should now have loaded after the .reload() command
+ atstep = 4;
+ clearTimeout(lasttimer);
+ tests13(true);
+ }
+}
+
+
+
+ </script>
+ </head>
+ <body>
+
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <p>WARNING: This test should always be loaded in a new tab/window, to avoid browsers attempting to recover the state of frames, and history length. Do not reload the test.</p>
+ <div id="log">Running test...</div>
+ <p><iframe onload="reportload();" src="blank.html"></iframe></p>
+ <p><iframe src="blank.html"></iframe></p>
+ <p><iframe src="blank2.html"></iframe></p>
+ <p><iframe src="blank3.html"></iframe></p>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/002.html b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/002.html
new file mode 100644
index 00000000000..eb0c15aab89
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/002.html
@@ -0,0 +1,308 @@
+<!doctype html>
+<html>
+ <head>
+ <title>history.replaceState tests</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript">
+//does not test for firing of popstate onload, because this was dropped from the specification on 25 March 2011
+//covers history.state after load, in accordance with the specification draft from 25 March 2011
+//history.state before load is tested in 006 and 007
+//does not test for structured cloning of FileList, File or Blob interfaces, as these require manual file selection
+
+//**This test assumes that assignments to location.hash will be synchronous - this is how all browsers implement it.
+//The spec (as of 25 March 2011) disagrees.
+
+var histlength, atstep = 0, lasttimer;
+setup({explicit_done:true}); //tests should take under 6 seconds + execution time
+
+window.onload = function () {
+ if( location.protocol == 'file:' ) {
+ document.getElementsByTagName('p')[0].innerHTML = 'ERROR: This test cannot be run from file: (URL resolving will not work). It must be loaded over HTTP.';
+ return;
+ } else if( location.protocol == 'https:' ) {
+ document.getElementsByTagName('p')[0].innerHTML += '<br>WARNING: Browsers may intentionally fail to update history.length when pages are loaded over HTTPS, as a privacy restriction. If possible, load this page over HTTP.';
+ }
+ //use a timeout, because some browsers intentionally do not add history entries for URL changes in the onload thread
+ setTimeout(testinit,100);
+};
+function testinit() {
+ atstep = 1;
+ histlength = history.length;
+ iframe = document.getElementsByTagName('iframe')[0].src = 'blank2.html';
+ //reportload will now be called by the onload handler for the iframe
+}
+function reportload() {
+ var iframe = document.getElementsByTagName('iframe')[0], hashchng = false;
+ var canvassup = false, cloneobj;
+
+ function tests1() {
+ test(function () { assert_equals( history.length, histlength + 1, 'make sure that you loaded the test in a new tab/window' ); }, 'history.length should update when loading pages in an iframe');
+ histlength = history.length;
+ iframe.contentWindow.location.hash = 'test'; //should be synchronous **SEE COMMENT AT TOP OF FILE
+ test(function () {
+ assert_equals( history.length, histlength + 1, 'make sure that you loaded the test in a new tab/window' );
+ }, 'history.length should update when setting location.hash');
+ test(function () { assert_true( !!history.replaceState, 'critical test; ignore any failures after this' ); }, 'history.replaceState must exist'); //assert_exists does not allow prototype inheritance
+ test(function () { assert_true( !!iframe.contentWindow.history.replaceState, 'critical test; ignore any failures after this' ); }, 'history.replaceState must exist within iframes');
+ test(function () {
+ assert_equals( iframe.contentWindow.history.state, null );
+ }, 'initial history.state should be null');
+ iframe.contentWindow.location.hash = 'test2';
+ history.back();
+ setTimeout(tests2,50); //.go is queued to end of thread
+ }
+ function tests2() {
+ test(function () {
+ histlength = history.length;
+ iframe.contentWindow.history.replaceState('','');
+ assert_equals( history.length, histlength );
+ }, 'history.length should not update when replacing a state with no URL');
+ test(function () {
+ assert_equals( iframe.contentWindow.history.state, '' );
+ }, 'history.state should update after a state is pushed');
+ test(function () {
+ assert_equals( iframe.contentWindow.location.hash.replace(/^#/,''), 'test' );
+ }, 'hash should not change when replaceState is called without a URL');
+ test(function () {
+ histlength = history.length;
+ iframe.contentWindow.history.replaceState('','','#test3');
+ assert_equals( history.length, histlength );
+ }, 'history.length should not update when replacing a state with a URL');
+ test(function () {
+ assert_equals( iframe.contentWindow.location.hash.replace(/^#/,''), 'test3' );
+ }, 'hash should change when replaceState is called with a URL');
+ history.go(-1);
+ setTimeout(tests3,50); //.go is queued to end of thread
+ }
+ function tests3() {
+ test(function () {
+ assert_equals( iframe.contentWindow.location.hash.replace(/^#/,''), '' );
+ }, 'replaceState must replace the existing state and not add an extra one');
+ history.go(2);
+ setTimeout(tests4,50); //.go is queued to end of thread
+ }
+ function tests4() {
+ test(function () {
+ assert_equals( iframe.contentWindow.location.hash.replace(/^#/,''), 'test2' );
+ }, 'replaceState must replace the existing state without altering the forward history');
+ test(function () {
+ assert_throws('SECURITY_ERR',function () { history.replaceState('','','//exa mple'); });
+ }, 'replaceState must not be allowed to create invalid URLs');
+ test(function () {
+ assert_throws('SECURITY_ERR',function () { history.replaceState('','','http://www.example.com/'); });
+ }, 'replaceState must not be allowed to create cross-origin URLs');
+ test(function () {
+ assert_throws('SECURITY_ERR',function () { history.replaceState('','','about:blank'); });
+ }, 'replaceState must not be allowed to create cross-origin URLs (about:blank)');
+ test(function () {
+ assert_throws('SECURITY_ERR',function () { history.replaceState('','','data:text/html,'); });
+ }, 'replaceState must not be allowed to create cross-origin URLs (data:URI)');
+ test(function () {
+ assert_throws('SECURITY_ERR',function () { iframe.contentWindow.history.replaceState('','','http://www.example.com/'); },iframe.contentWindow);
+ }, 'security errors are expected to be thrown in the context of the document that owns the history object');
+ test(function () {
+ //avoids browsers running .go synchronously when only a hash change is involved
+ iframe.contentWindow.history.replaceState('','','/testing_ignore_me_404#test4');
+ assert_equals( iframe.contentWindow.location.pathname, '/testing_ignore_me_404' );
+ }, 'replaceState must be able to set location.pathname');
+ test(function () {
+ var newURL = location.href.replace(/\/[^\/]*$/)+'/testing_ignore_me_404/';
+ iframe.contentWindow.history.replaceState('','',newURL);
+ assert_equals( iframe.contentWindow.location.href, newURL );
+ }, 'replaceState must be able to set absolute URLs to the same host');
+ //begin setup for "[must not] remove any tasks queued by the history traversal task source"
+ iframe.contentWindow.history.go(-1); //must be queued so the next command takes place *beforehand*
+ try {
+ //must not remove the queued navigation in the same browsing context
+ iframe.contentWindow.history.replaceState('','',iframe.contentWindow.location.pathname+'#test5');
+ } catch(unsuperr2) {}
+ //allow the browser to run the .go
+ setTimeout(tests5,50);
+ }
+ function tests5() {
+ test(function () {
+ assert_equals( iframe.contentWindow.location.hash.replace(/^#/,''), 'test3' );
+ }, 'replaceState must not remove any tasks queued by the history traversal task source');
+ //Safari 5.0.3 fails here - it navigates *this* document to the *iframe's* location, instead of just navigating the iframe
+ history.go(1);
+ setTimeout(tests6,50); //.go is queued to end of thread
+ }
+ function tests6() {
+ test(function () {
+ assert_equals( iframe.contentWindow.location.hash.replace(/^#/,''), 'test5' );
+ }, '.go must queue a task with the history traversal task source (run asynchronously)');
+ //end "[must not] remove any tasks queued by the history traversal task source"
+ window.addEventListener('hashchange',function () { hashchng = true; },false);
+ try {
+ //push a state that changes the hash
+ iframe.contentWindow.history.replaceState('','',iframe.contentWindow.location.pathname+'#test6');
+ } catch(unsuperr) {}
+ setTimeout(tests7,50); //allow the hashchange event to process, if the browser has mistakenly fired it
+ }
+ function tests7() {
+ test(function () {
+ assert_false( hashchng );
+ }, 'replaceState must not fire hashchange events');
+ test(function () {
+ assert_throws( 'DATA_CLONE_ERR', function () {
+ history.replaceState({dummy:function () {}},'');
+ } );
+ }, 'replaceState must not be able to use a function as data');
+ test(function () {
+ assert_throws( 'DATA_CLONE_ERR', function () {
+ history.replaceState({dummy:window},'');
+ } );
+ }, 'replaceState must not be able to use a DOM node as data');
+ test(function () {
+ try { a.b = c; } catch(errdata) {
+ assert_throws( 'DATA_CLONE_ERR', function () {
+ history.replaceState({dummy:errdata},'');
+ } );
+ }
+ }, 'replaceState must not be able to use an error object as data');
+ test(function () {
+ assert_throws( 'DATA_CLONE_ERR', function () {
+ iframe.contentWindow.history.replaceState(document,'');
+ }, iframe.contentWindow );
+ }, 'security errors are expected to be thrown in the context of the document that owns the history object (2)');
+ cloneobj = {
+ nulldata: null,
+ udefdata: window.undefined,
+ booldata: true,
+ numdata: 1,
+ strdata: 'string data',
+ boolobj: new Boolean(true),
+ numobj: new Number(1),
+ strobj: new String('string data'),
+ datedata: new Date(),
+ regdata: /a/g,
+ arrdata: [1]
+ };
+ cloneobj.regdata.lastIndex = 1;
+ cloneobj.looped = cloneobj;
+ //test the ImageData type, if the browser supports it
+ var canvas = document.createElement('canvas');
+ if( canvas.getContext && ( canvas = canvas.getContext('2d') ) && canvas.createImageData ) {
+ canvassup = true;
+ cloneobj.imgdata = canvas.createImageData(1,1);
+ }
+ test(function () {
+ try {
+ iframe.contentWindow.history.replaceState(cloneobj,'new title');
+ } catch(e) {
+ cloneobj.looped = null;
+ //try again because this object is needed for future tests
+ iframe.contentWindow.history.replaceState(cloneobj,'new title');
+ //rethrow so the browser gets a FAIL for not coping with the circular reference; "internal structured cloning algorithm" step 1
+ throw(e);
+ }
+ }, 'replaceState must be able to make structured clones of complex objects');
+ test(function () {
+ assert_equals( iframe.contentWindow.history.state && iframe.contentWindow.history.state.strdata, 'string data' );
+ }, 'history.state should also reference a clone of the original object');
+ test(function () {
+ assert_false( cloneobj === iframe.contentWindow.history.state );
+ }, 'history.state should be a clone of the original object, not a reference to it');
+ history.go(-1);
+ setTimeout(tests8,50); //.go is queued to end of thread
+ }
+ function tests8() {
+ var eventtime = setTimeout(function () { tests9(false); },500); //should be cleared by the event handler long before it has a chance to fire
+ iframe.contentWindow.addEventListener('popstate',function (e) { clearTimeout(eventtime); tests9(true,e); },false);
+ history.forward();
+ }
+ function tests9(hasFired,ev) {
+ test(function () {
+ assert_true( hasFired );
+ }, 'popstate event should fire when navigation occurs');
+ test(function () {
+ assert_true( !!ev && typeof(ev.state) != 'undefined', 'state information was not passed' );
+ assert_true( !!ev.state, 'state information does not contain the expected value - browser is probably stuck in the wrong history position' );
+ assert_equals( ev.state.nulldata, null, 'state null data was not correct' );
+ assert_equals( ev.state.udefdata, window.undefined, 'state undefined data was not correct' );
+ assert_true( ev.state.booldata, 'state boolean data was not correct' );
+ assert_equals( ev.state.numdata, 1, 'state numeric data was not correct' );
+ assert_equals( ev.state.strdata, 'string data', 'state string data was not correct' );
+ assert_true( !!ev.state.datedata.getTime, 'state date data was not correct' );
+ assert_exists( ev.state, 'regdata', 'state regex data was not correct' );
+ assert_equals( ev.state.regdata.source, 'a', 'state regex pattern data was not correct' );
+ assert_true( ev.state.regdata.global, 'state regex flag data was not correct' );
+ assert_equals( ev.state.regdata.lastIndex, 0, 'state regex lastIndex data was not correct' );
+ assert_equals( ev.state.arrdata.length, 1, 'state array data was not correct' );
+ assert_true( ev.state.boolobj.valueOf(), 'state boolean data was not correct' );
+ assert_equals( ev.state.numobj.valueOf(), 1, 'state numeric data was not correct' );
+ assert_equals( ev.state.strobj.valueOf(), 'string data', 'state string data was not correct' );
+ if( canvassup ) {
+ assert_equals( ev.state.imgdata.width, 1, 'state ImageData was not correct' );
+ }
+ }, 'popstate event should pass the state data');
+ test(function () {
+ assert_equals( ev.state.looped, ev.state );
+ }, 'state data should cope with circular object references');
+ test(function () {
+ assert_false( cloneobj === ev.state );
+ }, 'state data should be a clone of the original object, not a reference to it');
+ test(function () {
+ assert_equals( iframe.contentWindow.history.state && iframe.contentWindow.history.state.strdata, 'string data' );
+ }, 'history.state should also reference a clone of the original object (2)');
+ test(function () {
+ assert_false( cloneobj === iframe.contentWindow.history.state );
+ }, 'history.state should be a clone of the original object, not a reference to it (2)');
+ test(function () {
+ assert_false( iframe.contentWindow.history.state === ev.state );
+ }, 'history.state should be a separate clone of the object, not a reference to the object passed to the event handler');
+ try {
+ iframe.contentWindow.persistval = true;
+ iframe.contentWindow.history.replaceState('','', location.href.replace(/\/[^\/]*$/,'/blank3.html') );
+ } catch(unsuperr) {}
+ //it's already cached, so this should be very fast if the browser mistakenly loads it
+ //it should not need to load at all, since it's just a pushed state
+ setTimeout(tests10,1000);
+ }
+ function tests10() {
+ test(function () {
+ assert_true( iframe.contentWindow.persistval && !iframe.contentWindow.forreal );
+ }, 'replaceState should not actually load the new URL');
+ atstep = 3;
+ iframe.contentWindow.location.reload(); //load the real URL
+ lasttimer = setTimeout(function () { tests11(false); },3000); //should be cleared by the onload handler long before it has a chance to fire
+ }
+ function tests11(passed) {
+ test(function () {
+ assert_true( passed, 'expected a load event to fire when reloading the URL from cache, gave up waiting after 3 seconds' );
+ }, 'reloading a replaced state should actually load the new URL');
+ //try to make browsers behave when reloading so that the correct URL is recovered - does not always work
+ iframe.contentWindow.location.href = location.href.replace(/\/[^\/]*$/,'/blank.html');
+ done();
+ }
+
+ if( atstep == 1 ) {
+ //blank2 has loaded
+ atstep = 2;
+ //use a timeout, because some browsers intentionally do not add history entries for URL changes in an onload thread
+ setTimeout(tests1,100);
+ } else if( atstep == 3 ) {
+ //blank3 should now have loaded after the .reload() command
+ atstep = 4;
+ clearTimeout(lasttimer);
+ tests11(true);
+ }
+}
+
+
+
+ </script>
+ </head>
+ <body>
+
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <p>WARNING: This test should always be loaded in a new tab/window, to avoid browsers attempting to recover the state of frames, and history length. Do not reload the test.</p>
+ <div id="log">Running test...</div>
+ <p><iframe onload="reportload();" src="blank.html"></iframe></p>
+ <p><iframe src="blank.html"></iframe></p>
+ <p><iframe src="blank2.html"></iframe></p>
+ <p><iframe src="blank3.html"></iframe></p>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/004.html b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/004.html
new file mode 100644
index 00000000000..e69889724f0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/004.html
@@ -0,0 +1,62 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Final history position for history.go should be calculated when executing the task</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript">
+setup({explicit_done:true});
+window.onload = function () {
+ var hashcount = 0;
+ if( location.hash && location.hash != '#' ) {
+ location.href = location.href.replace(/#.*$/,'');
+ return;
+ }
+ setTimeout(add1,100);
+ function add1() {
+ location.hash = '#foo';
+ setTimeout(add2,100);
+ }
+ function add2() {
+ location.hash = '#bar';
+ setTimeout(add3,100);
+ }
+ function add3() {
+ location.hash = '#baz';
+ setTimeout(dojumps,100);
+ }
+ function dojumps() {
+ window.onhashchange = function () {
+ hashcount++;
+ };
+ history.go(-2);
+ test(function () {
+ //many browsers special-case jumps that only imply hash changes and will do them synchronously - the spec does allow this
+ assert_equals( hashcount, 0, 'hashchange fired even though the location should not have changed' );
+ assert_equals( location.hash.replace(/^#/,''), 'baz', 'the browser navigated synchronously' );
+ }, '.go commands should be queued until the thread has ended');
+ history.go(-1);
+ setTimeout(checkjumps,100);
+ }
+ function checkjumps() {
+ test(function () {
+ assert_true( !!hashcount, 'this testcase requires haschange support; the test cannot be used in this browser' );
+ }, 'browser needs to support hashchange events for this testcase');
+ test(function () {
+ assert_equals( hashcount, 2, 'the wrong number of queued commands were executed' );
+ }, 'queued .go commands should all be executed when the queue is processed');
+ test(function () {
+ assert_equals( location.hash.replace(/^#/,''), '' );
+ }, 'history position should be calculated when executing, not when calling the .go command');
+ done();
+ }
+};
+ </script>
+ </head>
+ <body>
+
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <div id="log"></div>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/005.html b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/005.html
new file mode 100644
index 00000000000..2152e85a3ec
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/005.html
@@ -0,0 +1,47 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Popstate event listener registration</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript">
+
+//this test checks that onpopstate works on the body element
+
+var readyForPop = false, bodypop = false, inlinepop = false;
+setup({explicit_done:true});
+
+//use a timeout to avoid "popstate fires onload" from setting the variables too early
+setTimeout(step1,1000);
+function step1() {
+ readyForPop = true;
+ test(function () {
+ history.pushState('','');
+ history.pushState('','');
+ }, 'history.pushState support is needed for this testcase');
+ history.go(-1);
+ setTimeout(step2,50); //.go is queued to end of thread
+}
+function step2() {
+ test(function () {
+ assert_true( bodypop );
+ }, '<body onpopstate="..."> should register a listener for the popstate event');
+ window.onpopstate = function () { inlinepop = true; };
+ history.go(-1);
+ setTimeout(step3,50); //.go is queued to end of thread
+}
+function step3() {
+ test(function () {
+ assert_true( inlinepop );
+ }, 'window.onpopstate should register a listener for the popstate event');
+ done();
+}
+ </script>
+ </head>
+ <body onpopstate="if( readyForPop ) { bodypop = true; }">
+
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <div id="log"></div>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/006.html b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/006.html
new file mode 100644
index 00000000000..442b6f8f1e6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/006.html
@@ -0,0 +1,53 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Firing popstate after onload, even if there is no pushed/replaced state</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript">
+
+//spec (25 March 2011 draft) states that popstate must not fire after onload unless there is a pushed/replaced state that is navigated
+var popfired = false;
+setup({explicit_done:true});
+window.addEventListener('popstate',function (e) { popfired = true; },false);
+test(function () {
+ assert_equals( history.state, null );
+}, 'history.state should initially be null');
+window.onload = function () {
+ test(function () {
+ assert_false( popfired );
+ }, 'popstate event should not fire before onload fires');
+ test(function () {
+ assert_equals( history.state, null );
+ }, 'history.state should still be null onload');
+ popfired = false;
+ setTimeout(function () {
+ test(function () {
+ assert_false( popfired );
+ }, 'popstate event should not fire after onload fires');
+ test(function () {
+ assert_equals( history.state, null );
+ }, 'history.state should still be null after onload');
+ test(function () {
+ var failed = false, realstate = history.state;
+ try {
+ history.state = '';
+ } catch(e) {
+ failed = e;
+ }
+ assert_equals(history.state,realstate,'property was read/write');
+ assert_false(failed);
+ }, 'writing to history.state should be silently ignored and not throw an error');
+ done();
+ },100);
+};
+
+ </script>
+ </head>
+ <body>
+
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <div id="log"></div>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/007.html b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/007.html
new file mode 100644
index 00000000000..29ed8bf0e00
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/007.html
@@ -0,0 +1,56 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Firing popstate after onload with pushed state</title>
+ <meta name=timeout content=long>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <div id="log">It looks like the browser stopped loading the page when encountering a .go(-1) command pointing to a pushed state. This will break the tests.</div>
+ <script type="text/javascript">
+
+//spec (25 March 2011 draft) states that popstate must fire before onload if there is a pushed/replaced state that is navigated
+var popfired = false;
+setup({explicit_done:true});
+test(function () {
+ assert_equals( history.state, null );
+}, 'history.state should initially be null');
+window.addEventListener('popstate',function (e) { popfired = e.state; },false);
+test(function () {
+ history.pushState('state1','');
+ history.pushState('state2','');
+}, 'history.pushState support is needed for this testcase');
+test(function () {
+ assert_equals( history.state, 'state2' );
+}, 'history.state should reflect pushed state');
+if( history.pushState ) { history.go(-1); }
+window.onload = function () {
+ test(function () {
+ assert_true( !!popfired );
+ }, 'popstate event should fire before onload fires');
+ test(function () {
+ assert_equals( popfired, 'state1' );
+ }, 'the correct state should be restored when navigating during initial load');
+ test(function () {
+ assert_equals( history.state, 'state1' );
+ }, 'history.state should reflect the navigated state onload');
+ popfired = false;
+ setTimeout(function () {
+ test(function () {
+ assert_false( !!popfired );
+ }, 'popstate event should not fire after onload fires');
+ test(function () {
+ assert_equals( history.state, 'state1' );
+ }, 'history.state should reflect the navigated state after onload');
+ done();
+ if( history.pushState ) { history.go(-1); } //go back to the start to avoid state recovery when reloading
+ },100);
+};
+
+ </script>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/008.html b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/008.html
new file mode 100644
index 00000000000..c8071e31566
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/008.html
@@ -0,0 +1,40 @@
+<!doctype html>
+<html>
+
+<!-- configure this test below to point to the script -->
+
+ <head>
+ <title>history.pushState/replaceState resolving</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+
+ <p></p>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+/*
+Location of the script (which must be hosted on a separate domain from this test) containing the test code:
+var beforehref = location.href;
+test(function () {
+ history.pushState('','','/testing_ignore_me_404');
+ assert_equals(location.href,beforehref.replace(/^(\w*:\/\/[^\/]*\/)[\w\W]*$/,'$1testing_ignore_me_404'));
+}, 'history.pushState URL resolving should be done relative to the document, not the script');
+test(function () {
+ history.replaceState('','','/testing_ignore_me_404_2');
+ assert_equals(location.href,beforehref.replace(/^(\w*:\/\/[^\/]*\/)[\w\W]*$/,'$1testing_ignore_me_404_2'));
+}, 'history.replaceState URL resolving should be done relative to the document, not the script');
+*/
+var scriptlocation = 'http://www.' + location.host + location.pathname.split("/").slice(0,-1).join("/") + "/008.js";
+
+if( location.protocol == 'file:' ) {
+ document.getElementsByTagName('p')[0].innerHTML = 'ERROR: This test cannot be run from file: (URL resolving will not work). It must be loaded over HTTP.';
+} else {
+ document.write('<script type="text\/javascript" src="'+scriptlocation+'"><\/script>');
+}
+ </script>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/009-1.html b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/009-1.html
new file mode 100644
index 00000000000..00b72e8ec65
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/009-1.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<html>
+ <head>
+ <title>history.pushState/replaceState and referer headers</title>
+ </head>
+ <body>
+
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <div id="log"></div>
+ <script type="text/javascript">
+window.onload = function () {
+ setTimeout(function () {
+ try { history.pushState('','','009-2.html?1234'); } catch(e) {}
+ location.href = '009-3.html?pipe=sub';
+ },10);
+};
+ </script>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/009-3.html b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/009-3.html
new file mode 100644
index 00000000000..e58b8fa5e7c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/009-3.html
@@ -0,0 +1,28 @@
+<!doctype html>
+<html>
+ <head>
+ <title>history.pushState/replaceState and referer headers</title>
+ </head>
+ <body>
+
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <div id="log"></div>
+ <script type="text/javascript">
+var httpReferer = "{{headers[referer]}}";
+var lastUrl = location.href.replace(/\/[^\/]*$/,'\/009-2.html?1234');
+parent.test(function () {
+ parent.assert_equals( httpReferer, lastUrl );
+}, 'HTTP Referer should use the pushed state');
+parent.test(function () {
+ parent.assert_equals( document.referrer, lastUrl );
+}, 'document.referrer should use the pushed state');
+window.onload = function () {
+ setTimeout(function () {
+ try { history.pushState('','','009-4.html?2345'); } catch(e) {}
+ location.href = '009-5.html?pipe=sub';
+ },10);
+};
+ </script>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/009-5.html b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/009-5.html
new file mode 100644
index 00000000000..068a089af4f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/009-5.html
@@ -0,0 +1,23 @@
+<!doctype html>
+<html>
+ <head>
+ <title>history.pushState/replaceState and referer headers</title>
+ </head>
+ <body>
+
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <div id="log"></div>
+ <script type="text/javascript">
+var httpReferer = unescape("{{headers[referer]}}");
+var lastUrl = location.href.replace(/\/[^\/]*$/,'\/009-4.html?2345');
+parent.test(function () {
+ parent.assert_equals( httpReferer, lastUrl );
+}, 'HTTP Referer should use the replaced state');
+parent.test(function () {
+ parent.assert_equals( document.referrer, lastUrl );
+}, 'document.referrer should use the replaced state');
+parent.done();
+ </script>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/009.html b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/009.html
new file mode 100644
index 00000000000..c1ae0bbe03b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/009.html
@@ -0,0 +1,22 @@
+<!doctype html>
+<html>
+ <head>
+ <title>history.pushState/replaceState and referer headers</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <div id="log"></div>
+ <script type="text/javascript">
+setup({explicit_done:true});
+var iframe = document.createElement('iframe');
+window.onload = function () {
+ iframe.setAttribute('src','009-1.html');
+ document.body.appendChild(iframe)
+};
+ </script>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/010-1.html b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/010-1.html
new file mode 100644
index 00000000000..683397745cd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/010-1.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<html>
+ <head>
+ <title>history.pushState/replaceState and referer headers (before onload)</title>
+ </head>
+ <body>
+
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <div id="log"></div>
+ <script type="text/javascript">
+try { history.pushState('','','010-2.html?1234'); } catch(e) {}
+location.href = '010-3.html?pipe=sub';
+ </script>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/010-3.html b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/010-3.html
new file mode 100644
index 00000000000..b80f56c3dd1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/010-3.html
@@ -0,0 +1,24 @@
+<!doctype html>
+<html>
+ <head>
+ <title>history.pushState/replaceState and referer headers (before onload)</title>
+ </head>
+ <body>
+
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <div id="log"></div>
+ <script type="text/javascript">
+ var httpReferer = "{{headers[referer]}}";
+var lastUrl = location.href.replace(/\/[^\/]*$/,'\/010-2.html?1234');
+parent.test(function () {
+ parent.assert_equals( httpReferer, lastUrl );
+}, 'HTTP Referer should use the pushed state (before onload)');
+parent.test(function () {
+ parent.assert_equals( document.referrer, lastUrl );
+}, 'document.referrer should use the pushed state (before onload)');
+try { history.pushState('','','010-4.html?2345'); } catch(e) {}
+location.href = '010-5.html?pipe=sub';
+ </script>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/010-5.html b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/010-5.html
new file mode 100644
index 00000000000..d150449eb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/010-5.html
@@ -0,0 +1,23 @@
+<!doctype html>
+<html>
+ <head>
+ <title>history.pushState/replaceState and referer headers (before onload)</title>
+ </head>
+ <body>
+
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <div id="log"></div>
+ <script type="text/javascript">
+var httpReferer = "{{headers[referer]}}";
+var lastUrl = location.href.replace(/\/[^\/]*$/,'\/010-4.html?2345');
+parent.test(function () {
+ parent.assert_equals( httpReferer, lastUrl );
+}, 'HTTP Referer should use the replaced state (before onload)');
+parent.test(function () {
+ parent.assert_equals( document.referrer, lastUrl );
+}, 'document.referrer should use the replaced state (before onload)');
+parent.done();
+ </script>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/010.html b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/010.html
new file mode 100644
index 00000000000..ca109a744b6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/010.html
@@ -0,0 +1,22 @@
+<!doctype html>
+<html>
+ <head>
+ <title>history.pushState/replaceState and referer headers (before onload)</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <div id="log"></div>
+ <script type="text/javascript">
+setup({explicit_done:true});
+var iframe = document.createElement('iframe');
+window.onload = function () {
+ iframe.setAttribute('src','010-1.html');
+ document.body.appendChild(iframe)
+};
+ </script>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/011.html b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/011.html
new file mode 100644
index 00000000000..4043aff7fd6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/011.html
@@ -0,0 +1,32 @@
+<!doctype html>
+<html>
+ <head>
+ <title>history.pushState before onload</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <div id="log"></div>
+ <script type="text/javascript">
+var newUrl = location.href.replace(/\/[^\/]*$/,'\/011-1.html');
+setup({explicit_done:true});
+test(function () {
+ history.pushState('','','011-1.html');
+}, 'pushState should be able to set the location state');
+test(function () {
+ assert_equals( location.href, newUrl );
+}, 'pushed location should be reflected immediately');
+window.onload = function () {
+ setTimeout(function () {
+ test(function () {
+ assert_equals( location.href, newUrl );
+ }, 'pushed location should be retained after the page has loaded');
+ done();
+ },10);
+};
+ </script>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/012.html b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/012.html
new file mode 100644
index 00000000000..f5e62516717
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/012.html
@@ -0,0 +1,32 @@
+<!doctype html>
+<html>
+ <head>
+ <title>history.replaceState before onload</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <div id="log"></div>
+ <script type="text/javascript">
+var newUrl = location.href.replace(/\/[^\/]*$/,'\/011-1.html');
+setup({explicit_done:true});
+test(function () {
+ history.replaceState('','','011-1.html');
+}, 'replaceState should be able to set the location state');
+test(function () {
+ assert_equals( location.href, newUrl );
+}, 'replaced location should be reflected immediately');
+window.onload = function () {
+ setTimeout(function () {
+ test(function () {
+ assert_equals( location.href, newUrl );
+ }, 'replaced location should be retained after the page has loaded');
+ done();
+ },10);
+};
+ </script>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/blank.html b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/blank.html
new file mode 100644
index 00000000000..89c8724c09d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/blank.html
@@ -0,0 +1,8 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Dummy page 1</title>
+ </head>
+ <body>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/blank2.html b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/blank2.html
new file mode 100644
index 00000000000..f79982e328c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/blank2.html
@@ -0,0 +1,13 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Dummy page 2</title>
+ </head>
+ <body>
+ <script type="text/javascript">
+if( self == top || !parent.reportload ) {
+ document.write("<p>FAIL. Browser got confused when navigating forwards, and navigated the whole window to the iframe's location, instead of just navigating the iframe. It is not possible to run the testsuite.<\/p>");
+}
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/blank3.html b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/blank3.html
new file mode 100644
index 00000000000..2a8989f2725
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/blank3.html
@@ -0,0 +1,11 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Dummy page 3</title>
+ <script type="text/javascript">
+var forreal = true;
+ </script>
+ </head>
+ <body>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/combination_history_001.html b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/combination_history_001.html
new file mode 100644
index 00000000000..21ba22f6fe3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/combination_history_001.html
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>combination_history_001(Combine pushState and replaceSate methods.)</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ test(function () {
+ window.history.pushState(1, document.title, '?x=1');
+ assert_equals(history.state, 1, "first");
+
+ window.history.replaceState(2, document.title, '?x=1');
+ assert_equals(history.state, 2, "second")
+ }, "Combine pushState and replaceSate methods");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/combination_history_002.html b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/combination_history_002.html
new file mode 100644
index 00000000000..29e82f51bea
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/combination_history_002.html
@@ -0,0 +1,22 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>combination_history_002(After calling of pushState method, check length.)</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ test(function () {
+ var first;
+ var second;
+ first = window.history.length;
+ window.history.pushState(1, document.title, '?x=1');
+ second = window.history.length;
+
+ assert_equals(second - first, 1, "second - first");
+ }, "After calling of pushState method, check length");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/combination_history_003.html b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/combination_history_003.html
new file mode 100644
index 00000000000..7467d9b294b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/combination_history_003.html
@@ -0,0 +1,26 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>combination_history_003(After calling of pushState and replaceState methods, check length.)</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ test(function () {
+ var first;
+ var second;
+ var third;
+ first = window.history.length;
+ window.history.pushState(1, document.title, '?x=1');
+ second = window.history.length;
+ window.history.replaceState(2, document.title, '?x=2');
+ third = window.history.length;
+
+ assert_equals(second - first, 1, "second - first");
+ assert_equals(third, second, "third");
+ }, "After calling of pushState and replaceState methods, check length");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/combination_history_004.html b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/combination_history_004.html
new file mode 100644
index 00000000000..4e38b56205e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/combination_history_004.html
@@ -0,0 +1,29 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>combination_history_004(After calling of back method, check length.)</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var t = async_test("After calling of back method, check length");
+
+ var last;
+ t.step(function () {
+ window.history.pushState(1, document.title, '?x=1');
+ window.history.pushState(2, document.title, '?x=2');
+ last = window.history.length;
+
+ window.history.back();
+ });
+
+ window.addEventListener('popstate', t.step_func(function(e) {
+ assert_equals(e.state, 1, "state");
+ assert_equals(window.history.length, last, "last");
+ t.done();
+ }), false);
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/combination_history_005.html b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/combination_history_005.html
new file mode 100644
index 00000000000..44876780151
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/combination_history_005.html
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>combination_history_005(After calling of forward method, check length.)</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var t = async_test("After calling of forward method, check length");
+
+ var last;
+ var fired = false;
+ t.step(function () {
+ window.history.pushState(1, document.title, '?x=1');
+ window.history.pushState(2, document.title, '?x=2');
+ last = window.history.length;
+
+ window.history.back();
+ });
+
+ window.addEventListener('popstate', t.step_func(function(e) {
+ if(fired) {
+ assert_equals(e.state, 2, "state");
+ assert_equals(window.history.length, last, "last");
+ t.done();
+ }
+ fired = true;
+ window.history.forward();
+ }), false);
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/combination_history_006.html b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/combination_history_006.html
new file mode 100644
index 00000000000..305f593c093
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/combination_history_006.html
@@ -0,0 +1,30 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>combination_history_006(After calling of go method, check length.)</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var t = async_test("After calling of go method, check length");
+
+ var last;
+ t.step(function () {
+ window.history.pushState(1, document.title, '?x=1');
+ window.history.pushState(2, document.title, '?x=2');
+
+ last = window.history.length;
+
+ window.history.go(-1);
+ });
+
+ window.addEventListener('popstate', t.step_func(function(e) {
+ assert_equals(e.state, 1, "state");
+ assert_equals(window.history.length, last, "last");
+ t.done();
+ }), false);
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/combination_history_007.html b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/combination_history_007.html
new file mode 100644
index 00000000000..cec9ea09810
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/combination_history_007.html
@@ -0,0 +1,32 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>combination_history_007(After calling of back and pushState method, check length.)</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var t = async_test("After calling of back and pushState method, check length");
+
+ var last;
+ t.step(function () {
+ window.history.pushState(1, document.title, '?x=1');
+ window.history.pushState(2, document.title, '?x=2');
+
+ last = window.history.length;
+
+ window.history.back();
+ });
+
+ window.addEventListener('popstate', t.step_func(function(e) {
+ assert_equals(e.state, 1, "state");
+ assert_equals(window.history.length, last, "last");
+ window.history.pushState(3, document.title, '?x=3');
+ assert_equals(window.history.length, last, "last");
+ t.done();
+ }), false);
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/history_back.html b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/history_back.html
new file mode 100644
index 00000000000..042da4e61b2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/history_back.html
@@ -0,0 +1,27 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>history_back</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var t = async_test("history back");
+
+ t.step(function () {
+ window.history.pushState(1, document.title, '?x=1');
+ window.history.pushState(2, document.title, '?x=2');
+
+ window.history.back();
+ });
+
+ window.addEventListener('popstate', t.step_func(function(e) {
+ assert_equals(e.state, 1, "history state");
+
+ t.done();
+ }), false);
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/history_forward.html b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/history_forward.html
new file mode 100644
index 00000000000..6c37f252159
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/history_forward.html
@@ -0,0 +1,32 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>history_forward</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var t = async_test("history forward");
+
+ var fired = false;
+ t.step(function () {
+ window.history.pushState(1, document.title, '?x=1');
+ window.history.pushState(2, document.title, '?x=2');
+
+ window.history.back();
+ });
+
+ window.addEventListener('popstate', t.step_func(function(e) {
+ if(fired) {
+ assert_equals(e.state, 2, "history state");
+
+ t.done();
+ }
+ fired = true;
+ window.history.forward();
+ }), false);
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/history_go_minus.html b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/history_go_minus.html
new file mode 100644
index 00000000000..b8fe75573db
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/history_go_minus.html
@@ -0,0 +1,27 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>history_go_minus</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var t = async_test("history go minus");
+
+ t.step(function () {
+ window.history.pushState(1, document.title, '?x=1');
+ window.history.pushState(2, document.title, '?x=2');
+
+ window.history.go(-1);
+ });
+
+ window.addEventListener('popstate', t.step_func(function(e) {
+ assert_equals(e.state, 1, "history state");
+
+ t.done();
+ }), false);
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/history_go_plus.html b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/history_go_plus.html
new file mode 100644
index 00000000000..74d4c588ca0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/history_go_plus.html
@@ -0,0 +1,33 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>history_go_plus</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var t = async_test("history go plus");
+
+ var fired = false;
+ t.step(function () {
+ window.history.pushState(1, document.title, '?x=1');
+ window.history.pushState(2, document.title, '?x=2');
+
+ window.history.back();
+ });
+
+ window.addEventListener('popstate', t.step_func(function(e) {
+ if(fired) {
+ assert_equals(e.state, 2, "history state");
+
+ t.done();
+ }
+ fired = true;
+ window.history.go(1);
+
+ }), false);
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/history_pushstate.html b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/history_pushstate.html
new file mode 100644
index 00000000000..5180a3f6e52
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/history_pushstate.html
@@ -0,0 +1,19 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>history_pushState</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ test(function () {
+ window.history.pushState(1, document.title, '?x=1');
+ var state;
+ state = window.history.state;
+ assert_equals(state, 1, "history state");
+ }, "history pushState");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/history_pushstate_err.html b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/history_pushstate_err.html
new file mode 100644
index 00000000000..82afc04f2dd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/history_pushstate_err.html
@@ -0,0 +1,18 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>history_pushState SECURITY_ERR</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ test(function () {
+ assert_throws("SecurityError", function () {
+ window.history.pushState(1, document.title, 'http://www.microsoft.com/test.html');
+ });
+ }, "history pushState SECURITY_ERR");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/history_pushstate_nooptionalparam.html b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/history_pushstate_nooptionalparam.html
new file mode 100644
index 00000000000..8e4b049a19e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/history_pushstate_nooptionalparam.html
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>history_pushState_NoOptionalParam</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ test(function () {
+ window.history.pushState(1, document.title);
+
+ var state;
+ state = window.history.state;
+ assert_equals(state, 1, "history state");
+ }, "history pushState NoOptionalParam");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/history_replacestate.html b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/history_replacestate.html
new file mode 100644
index 00000000000..794c2f37130
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/history_replacestate.html
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>history_replaceState</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ test(function () {
+ window.history.replaceState(1, document.title, '?x=1');
+
+ var second;
+ second = window.history.state;
+ assert_equals(second, 1, "history state");
+ }, "history replaceState");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/history_replacestate_err.html b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/history_replacestate_err.html
new file mode 100644
index 00000000000..3060cf1f128
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/history_replacestate_err.html
@@ -0,0 +1,18 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>history_replaceState SECURITY_ERR</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ test(function () {
+ assert_throws("SecurityError", function () {
+ window.history.replaceState(1, document.title, 'http://www.microsoft.com/test.html');
+ });
+ }, "history replaceState SECURITY_ERR");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/history_replacestate_nooptionalparam.html b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/history_replacestate_nooptionalparam.html
new file mode 100644
index 00000000000..838467d7827
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/history_replacestate_nooptionalparam.html
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>history_replaceStateNoOptionalParam</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ test(function () {
+ window.history.replaceState(1, document.title);
+
+ var second;
+ second = window.history.state;
+ assert_equals(second, 1, "history state");
+ }, "history replaceStateNoOptionalParam");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/history_state.html b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/history_state.html
new file mode 100644
index 00000000000..2ee2356b1ac
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/history/the-history-interface/history_state.html
@@ -0,0 +1,24 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>history_state</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ test(function () {
+ var first;
+ var second;
+
+ first = window.history.state;
+ window.history.pushState(1, document.title, '?x=1');
+
+ second = window.history.state;
+ assert_equals(first, null, "first");
+ assert_equals(second, 1, "second");
+ }, "history state");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/the-location-interface/.gitkeep b/tests/wpt/web-platform-tests/html/browsers/history/the-location-interface/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/history/the-location-interface/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/the-location-interface/contains.json b/tests/wpt/web-platform-tests/html/browsers/history/the-location-interface/contains.json
new file mode 100644
index 00000000000..d311dbb31e3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/history/the-location-interface/contains.json
@@ -0,0 +1,6 @@
+[
+ {
+ "id": "security-location",
+ "original_id": "security-location"
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/the-location-interface/location-stringifier.html b/tests/wpt/web-platform-tests/html/browsers/history/the-location-interface/location-stringifier.html
new file mode 100644
index 00000000000..d23323b3731
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/history/the-location-interface/location-stringifier.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<title>Location stringifier</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://heycam.github.io/webidl/#es-stringifier">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=/common/stringifiers.js></script>
+<div id=log></div>
+<script>
+test_stringifier_attribute(location, "href", true);
+</script>
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/the-location-interface/location_assign.html b/tests/wpt/web-platform-tests/html/browsers/history/the-location-interface/location_assign.html
new file mode 100644
index 00000000000..6f7da1a5332
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/history/the-location-interface/location_assign.html
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>location_assign</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ test(function () {
+ var href = location.href;
+ location.assign('#x');
+
+ assert_equals((href + "#x"), location.href, "location href");
+
+ }, "location assign");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/the-location-interface/location_hash.html b/tests/wpt/web-platform-tests/html/browsers/history/the-location-interface/location_hash.html
new file mode 100644
index 00000000000..91c3f8205d3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/history/the-location-interface/location_hash.html
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>location_hash</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ test(function () {
+ window.history.pushState(1, document.title, '#x=1');
+ var hash = location.hash;
+
+ assert_equals(hash, "#x=1", "hash");
+
+ }, "location hash");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/the-location-interface/location_host.html b/tests/wpt/web-platform-tests/html/browsers/history/the-location-interface/location_host.html
new file mode 100644
index 00000000000..d93bf47e506
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/history/the-location-interface/location_host.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>location_host</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ test(function () {
+ var host = location.host;
+ var url = location.href;
+
+ var pos = url.indexOf("//");
+ if (pos != -1) {
+ url = url.substr(pos+2, url.length-pos-2);
+ pos = url.indexOf("/");
+ if (pos != -1)
+ url = url.substr(0, pos);
+ }
+
+ assert_equals(host, url, "host");
+
+ }, "location host");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/the-location-interface/location_hostname.html b/tests/wpt/web-platform-tests/html/browsers/history/the-location-interface/location_hostname.html
new file mode 100644
index 00000000000..2ffa0e5fc85
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/history/the-location-interface/location_hostname.html
@@ -0,0 +1,33 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>location_hostname</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ test(function () {
+ var hostname = location.hostname;
+ var url = location.href;
+
+ var pos = url.indexOf("//");
+ if (pos != -1) {
+ url = url.substr(pos+2, url.length-pos-2);
+ pos = url.indexOf(":");
+ if (pos != -1) {
+ url = url.substr(0, pos);
+ } else {
+ pos = url.indexOf("/");
+ if (pos != -1)
+ url = url.substr(0, pos);
+ }
+ }
+
+ assert_equals(hostname, url, "hostname");
+
+ }, "location hostname");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/the-location-interface/location_href.html b/tests/wpt/web-platform-tests/html/browsers/history/the-location-interface/location_href.html
new file mode 100644
index 00000000000..1aa85dcdc87
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/history/the-location-interface/location_href.html
@@ -0,0 +1,19 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>location_href</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ test(function () {
+ var href = location.href;
+
+ assert_equals(href, document.URL, "href");
+
+ }, "location href");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/the-location-interface/location_pathname.html b/tests/wpt/web-platform-tests/html/browsers/history/the-location-interface/location_pathname.html
new file mode 100644
index 00000000000..dea05d2f37b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/history/the-location-interface/location_pathname.html
@@ -0,0 +1,22 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>location_pathname</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ test(function () {
+ var pathname = location.pathname;
+ var url = location.href
+
+ url = url.replace(location.protocol + "//" + location.host, "");
+
+ assert_equals(pathname, url, "pathname");
+
+ }, "location pathname");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/the-location-interface/location_port.html b/tests/wpt/web-platform-tests/html/browsers/history/the-location-interface/location_port.html
new file mode 100644
index 00000000000..fa1308ca5d5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/history/the-location-interface/location_port.html
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>location_port</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ test(function () {
+ var port = location.port;
+ var url = location.href;
+
+ var pos = url.indexOf("//");
+ if (pos != -1) {
+ url = url.substr(pos+2, url.length-pos-2);
+ pos = url.indexOf("/");
+ if (pos != -1)
+ url = url.substr(0, pos);
+ pos = url.indexOf(":");
+ if (pos != -1)
+ url = url.substr(pos+1, url.length-pos-1);
+ }
+
+ assert_equals(port, url, "port");
+
+ }, "location port");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/the-location-interface/location_protocol.html b/tests/wpt/web-platform-tests/html/browsers/history/the-location-interface/location_protocol.html
new file mode 100644
index 00000000000..d28bd563933
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/history/the-location-interface/location_protocol.html
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>location_protocol</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ test(function () {
+ var protocol = location.protocol;
+ var url = location.href;
+
+ var pos = url.indexOf("//");
+ if (pos != -1) {
+ url = url.substr(0, pos);
+ }
+
+ assert_equals(protocol, url, "protocol");
+
+ }, "location protocol");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/the-location-interface/location_replace.html b/tests/wpt/web-platform-tests/html/browsers/history/the-location-interface/location_replace.html
new file mode 100644
index 00000000000..2f2d5730845
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/history/the-location-interface/location_replace.html
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>location_replace</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ test(function () {
+ var href = location.href;
+ location.replace('#x');
+
+ assert_equals((href + "#x"), location.href, "location href");
+
+ }, "location replace");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/the-location-interface/location_search.html b/tests/wpt/web-platform-tests/html/browsers/history/the-location-interface/location_search.html
new file mode 100644
index 00000000000..f9db757841f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/history/the-location-interface/location_search.html
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>location_search</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ test(function () {
+ window.history.pushState(1, document.title, '?x=1');
+ var search = location.search;
+
+ assert_equals(search, "?x=1", "search");
+
+ }, "location search");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/the-location-interface/security_location_0.sub.htm b/tests/wpt/web-platform-tests/html/browsers/history/the-location-interface/security_location_0.sub.htm
new file mode 100644
index 00000000000..b6ebbc28a45
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/history/the-location-interface/security_location_0.sub.htm
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Location interface Security</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#security-location" />
+ <meta name="assert" content="access location object from different origins doesn't raise SECURITY_ERR exception" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <p>Access location object from different origins doesn't raise SECURITY_ERR exception</p>
+ <div id=log></div>
+ <script>
+ var runTest = async_test("Accessing location object from different origins doesn't raise SECURITY_ERR exception").step_func_done(function() {
+ var frame = document.getElementById('testframe');
+ frame.setAttribute('onload', '');
+ frame.contentWindow.location = 'http://{{domains[www1]}}:{{ports[http][0]}}/'
+ });
+ </script>
+ <iframe id='testframe' src="http://{{domains[www]}}:{{ports[http][0]}}/" onload="runTest()">Test Frame</iframe>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/history/the-session-history-of-browsing-contexts/.gitkeep b/tests/wpt/web-platform-tests/html/browsers/history/the-session-history-of-browsing-contexts/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/history/the-session-history-of-browsing-contexts/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/browsers/offline/.gitkeep b/tests/wpt/web-platform-tests/html/browsers/offline/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/offline/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/browsers/offline/appcache/.gitkeep b/tests/wpt/web-platform-tests/html/browsers/offline/appcache/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/offline/appcache/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/browsers/offline/application-cache-api/.gitkeep b/tests/wpt/web-platform-tests/html/browsers/offline/application-cache-api/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/offline/application-cache-api/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/browsers/offline/application-cache-api/api_status_checking-manual.html b/tests/wpt/web-platform-tests/html/browsers/offline/application-cache-api/api_status_checking-manual.html
new file mode 100644
index 00000000000..a4a3b41a7d5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/offline/application-cache-api/api_status_checking-manual.html
@@ -0,0 +1,23 @@
+<!DOCTYPE HTML>
+<html manifest="../resources/manifest/clock.manifest">
+ <head>
+ <title>Offline Application Cache - API_status_CHECKING</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <ol>
+ <li>Refresh the page.</li>
+ </ol>
+
+ <div id="log"></div>
+ <script>
+ var t = async_test("checking status test"),
+ cache = window.applicationCache;
+
+ cache.onchecking = t.step_func_done(function() {
+ assert_equals(cache.status, cache.CHECKING, "cache.status should equals cache.CHECKING");
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/offline/application-cache-api/api_status_downloading-manual.html b/tests/wpt/web-platform-tests/html/browsers/offline/application-cache-api/api_status_downloading-manual.html
new file mode 100644
index 00000000000..c09d11d787f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/offline/application-cache-api/api_status_downloading-manual.html
@@ -0,0 +1,24 @@
+<!DOCTYPE HTML>
+<html manifest="../resources/manifest/clock.manifest">
+ <head>
+ <title>Offline Application Cache - API_status_DOWNLOADING</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <ol>
+ <li>Modify the commented part in the manifest file (manifest/clock.manifest) on the server.</li>
+ <li>Refresh the page.</li>
+ </ol>
+ <div id="log"></div>
+
+ <script>
+ var t = async_test("downloading status test"),
+ cache = window.applicationCache;
+
+ cache.ondownloading = t.step_func_done(function() {
+ assert_equals(cache.status, cache.DOWNLOADING, "cache.status should equals cache.DOWNLOADING");
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/offline/application-cache-api/api_status_idle.html b/tests/wpt/web-platform-tests/html/browsers/offline/application-cache-api/api_status_idle.html
new file mode 100644
index 00000000000..21725bb00d0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/offline/application-cache-api/api_status_idle.html
@@ -0,0 +1,22 @@
+<!DOCTYPE HTML>
+<html manifest="../resources/manifest/clock.manifest">
+ <head>
+ <title>Offline Application Cache - API_status_IDLE</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var t = async_test("idle status test"),
+ cache = window.applicationCache;
+
+ setTimeout(function(){
+ t.step(function() {
+ assert_equals(cache.status, cache.IDLE, "cache.status should equals cache.IDLE");
+ });
+ t.done();
+ }, 3000);
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/offline/application-cache-api/api_status_obsolete-manual.html b/tests/wpt/web-platform-tests/html/browsers/offline/application-cache-api/api_status_obsolete-manual.html
new file mode 100644
index 00000000000..77005644a2f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/offline/application-cache-api/api_status_obsolete-manual.html
@@ -0,0 +1,24 @@
+<!DOCTYPE HTML>
+<html manifest="../resources/manifest/clock.manifest">
+ <head>
+ <title>Offline Application Cache - API_status_OBSOLETE</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <ol>
+ <li>Remove the manifest file (manifest/clock.manifest) from the server.</li>
+ <li>Refresh the page.</li>
+ </ol>
+ <div id="log"></div>
+
+ <script>
+ var t = async_test("obsolete status test"),
+ cache = window.applicationCache;
+
+ cache.onobsolete = t.step_func_done(function() {
+ assert_equals(cache.status, cache.OBSOLETE, "cache.status should equals cache.OBSOLETE");
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/offline/application-cache-api/api_status_uncached.html b/tests/wpt/web-platform-tests/html/browsers/offline/application-cache-api/api_status_uncached.html
new file mode 100644
index 00000000000..300c4a1b182
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/offline/application-cache-api/api_status_uncached.html
@@ -0,0 +1,19 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Offline Application Cache - API_status_UNCACHED</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+
+ <script>
+ var cache = window.applicationCache;
+
+ test(function(){
+ assert_equals(cache.status, cache.UNCACHED, "uncached status test");
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/offline/application-cache-api/api_status_updateready-manual.html b/tests/wpt/web-platform-tests/html/browsers/offline/application-cache-api/api_status_updateready-manual.html
new file mode 100644
index 00000000000..7e1533374b9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/offline/application-cache-api/api_status_updateready-manual.html
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML>
+<html manifest="../resources/manifest/clock.manifest">
+ <head>
+ <title>Offline Application Cache - API_status_UPDATEREADY</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <ol>
+ <li>Modify the commented part in the manifest file (manifest/clock.manifest) on the server.</li>
+ <li>Refresh the page.</li>
+ </ol>
+
+ <div id="log"></div>
+
+ <script>
+ var t = async_test("updateready status test"),
+ cache = window.applicationCache;
+
+ cache.onupdateready = t.step_func_done(function() {
+ assert_equals(cache.status, cache.UPDATEREADY, "cache.status should equals cache.UPDATEREADY");
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/offline/application-cache-api/api_swapcache-manual.html b/tests/wpt/web-platform-tests/html/browsers/offline/application-cache-api/api_swapcache-manual.html
new file mode 100644
index 00000000000..6649d980f6a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/offline/application-cache-api/api_swapcache-manual.html
@@ -0,0 +1,30 @@
+<!DOCTYPE HTML>
+<html manifest="../resources/manifest/clock.manifest">
+ <head>
+ <title>Offline Application Cache - API_swapCache</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <ol>
+ <li>Modify the part of comment in manifest file of server.</li>
+ <li>Refresh the page.</li>
+ </ol>
+
+ <div id="log"></div>
+
+ <script>
+ var t = async_test("swapCache method test");
+ var cache = window.applicationCache;
+
+ cache.onupdateready = t.step_func(function() {
+ try {
+ cache.swapCache();
+ t.done();
+ } catch (e) {
+ assert_unreached("swapCache method failed.");
+ }
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/offline/application-cache-api/api_swapcache_error.html b/tests/wpt/web-platform-tests/html/browsers/offline/application-cache-api/api_swapcache_error.html
new file mode 100644
index 00000000000..02e7b3cd8c0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/offline/application-cache-api/api_swapcache_error.html
@@ -0,0 +1,19 @@
+<!DOCTYPE HTML>
+<html manifest="../resources/manifest/clock.manifest">
+ <head>
+ <title>Offline Application Cache - API_swapCache_error</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+
+ <script>
+ var cache = window.applicationCache;
+
+ test(function() {
+ assert_throws("INVALID_STATE_ERR", function(){cache.swapCache();});
+ }, "INVALID_STATE_ERR error test")
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/offline/application-cache-api/api_update.html b/tests/wpt/web-platform-tests/html/browsers/offline/application-cache-api/api_update.html
new file mode 100644
index 00000000000..452daa711df
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/offline/application-cache-api/api_update.html
@@ -0,0 +1,24 @@
+<!DOCTYPE HTML>
+<html manifest="../resources/manifest/clock.manifest">
+ <head>
+ <title>Offline Application Cache - API_update</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+
+ <script>
+ var cache = window.applicationCache;
+
+ test(function() {
+ try {
+ cache.update()
+ assert_true(true, "update method test")
+ } catch (e) {
+ assert_unreached("update method failed.");
+ }
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/offline/application-cache-api/api_update_error.html b/tests/wpt/web-platform-tests/html/browsers/offline/application-cache-api/api_update_error.html
new file mode 100644
index 00000000000..ef88158cd0e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/offline/application-cache-api/api_update_error.html
@@ -0,0 +1,24 @@
+<!DOCTYPE HTML>
+<html manifest="../resources/manifest/clock.manifest">
+ <head>
+ <title>Offline Application Cache - API_update_error</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <ol>
+ <li>Remove the manifest file (manifest/clock.manifest) from the server.</li>
+ <li>Refresh the page, then calling update() will throw InvalidStateError exception.</li>
+ </ol>
+
+ <div id="log"></div>
+
+ <script>
+ var cache = window.applicationCache;
+ test(function() {
+ assert_throws("INVALID_STATE_ERR", function(){cache.update();});
+ }, "INVALID_STATE_ERR error test")
+ </script>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/offline/browser-state/.gitkeep b/tests/wpt/web-platform-tests/html/browsers/offline/browser-state/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/offline/browser-state/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/browsers/offline/browser-state/navigator_online_event-manual.html b/tests/wpt/web-platform-tests/html/browsers/offline/browser-state/navigator_online_event-manual.html
new file mode 100644
index 00000000000..b100f177eb1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/offline/browser-state/navigator_online_event-manual.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Offline Application Cache</title>
+ <link rel="stylesheet" href="../resources/css/result.css">
+ </head>
+ <body>
+ <h1>navigator_online_event</h1>
+
+ <ol>
+ <li>Change the 'work offline' mode.</li>
+ <li>If actual result and expected result are same, then test is <span class="manualpass">Pass</span>, otherwise <span class="manualfail">Fail</span>.</li>
+ </ol>
+
+ <hr>
+
+ <h2>Actual Result</h2>
+ <div id="actualResult">
+ <span id="actualMsg"></span>
+ </div>
+
+ <h2>Expected Result</h2>
+ <div id="expectedResult">
+ <span id="expectedMsg">apply 'work offline': offline event is raised.<p>release 'work offline': online event is raised.</span>
+ </div>
+ <script>
+
+ function showOnline() {
+ document.getElementById('actualMsg').innerHTML = 'online event is raised.';
+ }
+
+ function showOffline() {
+ document.getElementById('actualMsg').innerHTML = 'offline event is raised.';
+ }
+
+ window.addEventListener("online", showOnline, false);
+ window.addEventListener("offline", showOffline, false);
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/offline/browser-state/navigator_online_online.html b/tests/wpt/web-platform-tests/html/browsers/offline/browser-state/navigator_online_online.html
new file mode 100644
index 00000000000..81547c3fb99
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/offline/browser-state/navigator_online_online.html
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Offline Application Cache - navigator_online_online</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+
+ <script>
+ test(function() {
+ assert_true(navigator.onLine, "onLine test");
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/offline/changestonetworkingmodel/.gitkeep b/tests/wpt/web-platform-tests/html/browsers/offline/changestonetworkingmodel/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/offline/changestonetworkingmodel/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/browsers/offline/changestonetworkingmodel/original-id.json b/tests/wpt/web-platform-tests/html/browsers/offline/changestonetworkingmodel/original-id.json
new file mode 100644
index 00000000000..2f77367c8f9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/offline/changestonetworkingmodel/original-id.json
@@ -0,0 +1 @@
+{"original_id":"changesToNetworkingModel"} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/browsers/offline/disk-space/.gitkeep b/tests/wpt/web-platform-tests/html/browsers/offline/disk-space/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/offline/disk-space/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/browsers/offline/downloading-or-updating-an-application-cache/.gitkeep b/tests/wpt/web-platform-tests/html/browsers/offline/downloading-or-updating-an-application-cache/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/offline/downloading-or-updating-an-application-cache/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/browsers/offline/expiring-application-caches/.gitkeep b/tests/wpt/web-platform-tests/html/browsers/offline/expiring-application-caches/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/offline/expiring-application-caches/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/browsers/offline/introduction-4/.gitkeep b/tests/wpt/web-platform-tests/html/browsers/offline/introduction-4/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/offline/introduction-4/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/browsers/offline/introduction-4/contains.json b/tests/wpt/web-platform-tests/html/browsers/offline/introduction-4/contains.json
new file mode 100644
index 00000000000..799caa23abe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/offline/introduction-4/contains.json
@@ -0,0 +1,10 @@
+[
+ {
+ "id": "supporting-offline-caching-for-legacy-applications",
+ "original_id": "supporting-offline-caching-for-legacy-applications"
+ },
+ {
+ "id": "appcacheevents",
+ "original_id": "appcacheevents"
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/browsers/offline/introduction-4/event_cached.html b/tests/wpt/web-platform-tests/html/browsers/offline/introduction-4/event_cached.html
new file mode 100644
index 00000000000..24f57769fc5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/offline/introduction-4/event_cached.html
@@ -0,0 +1,18 @@
+<!DOCTYPE HTML>
+<html manifest="../resources/manifest/clock.manifest">
+ <head>
+ <title>Offline Application Cache - Event_cached</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+
+ <script>
+ var t = async_test("cached event test");
+ var cache = window.applicationCache;
+
+ cache.oncached = t.done();
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/offline/introduction-4/event_checking.html b/tests/wpt/web-platform-tests/html/browsers/offline/introduction-4/event_checking.html
new file mode 100644
index 00000000000..c180eca9d92
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/offline/introduction-4/event_checking.html
@@ -0,0 +1,18 @@
+<!DOCTYPE HTML>
+<html manifest="../resources/manifest/clock.manifest">
+ <head>
+ <title>Offline Application Cache - Event_checking</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+
+ <script>
+ var t = async_test("checking event test");
+ var cache = window.applicationCache;
+
+ cache.onchecking = t.done();
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/offline/introduction-4/event_downloading-manual.html b/tests/wpt/web-platform-tests/html/browsers/offline/introduction-4/event_downloading-manual.html
new file mode 100644
index 00000000000..26b003f06e5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/offline/introduction-4/event_downloading-manual.html
@@ -0,0 +1,23 @@
+<!DOCTYPE HTML>
+<html manifest="../resources/manifest/clock.manifest">
+ <head>
+ <title>Offline Application Cache - Event_downloading</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <ol>
+ <li>Modify the commented part of the manifest file (manifest/clock.manifest) on the server.</li>
+ <li>Refresh the page.</li>
+ </ol>
+
+ <div id="log"></div>
+
+ <script>
+ var t = async_test("downloading event test");
+ var cache = window.applicationCache;
+
+ cache.ondownloading = t.done();
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/offline/introduction-4/event_error-manual.html b/tests/wpt/web-platform-tests/html/browsers/offline/introduction-4/event_error-manual.html
new file mode 100644
index 00000000000..19abb3d6bf3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/offline/introduction-4/event_error-manual.html
@@ -0,0 +1,23 @@
+<!DOCTYPE HTML>
+<html manifest="../resources/manifest/clock.manifest">
+ <head>
+ <title>Offline Application Cache - Event_error</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <ol>
+ <li>Add a dummy file in the manifest file (manifest/clock.manifest).</li>
+ <li>Refresh the page.</li>
+ </ol>
+
+ <div id="log"></div>
+
+ <script>
+ var t = async_test("error event test");
+ var cache = window.applicationCache;
+
+ cache.onerror = t.done();
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/offline/introduction-4/event_noupdate.html b/tests/wpt/web-platform-tests/html/browsers/offline/introduction-4/event_noupdate.html
new file mode 100644
index 00000000000..1e4dd89cf31
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/offline/introduction-4/event_noupdate.html
@@ -0,0 +1,19 @@
+<!DOCTYPE HTML>
+<html manifest="../resources/manifest/clock.manifest">
+ <head>
+ <title>Offline Application Cache - Event_noupdate</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+
+ <script>
+ var t = async_test("noupdate event test");
+ var cache = window.applicationCache;
+
+ cache.onnoupdate = t.done();
+ </script>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/offline/introduction-4/event_obsolete-manual.html b/tests/wpt/web-platform-tests/html/browsers/offline/introduction-4/event_obsolete-manual.html
new file mode 100644
index 00000000000..cab5e01cc7e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/offline/introduction-4/event_obsolete-manual.html
@@ -0,0 +1,23 @@
+<!DOCTYPE HTML>
+<html manifest="../resources/manifest/clock.manifest">
+ <head>
+ <title>Offline Application Cache - Event_obsolete</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <ol>
+ <li>Remove the manifest file (manifest/clock.manifest) from the server.</li>
+ <li>Refresh the page.</li>
+ </ol>
+
+ <div id="log"></div>
+
+ <script>
+ var t = async_test("obsolete event test");
+ var cache = window.applicationCache;
+
+ cache.onobsolete = t.done();
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/offline/introduction-4/event_progress.html b/tests/wpt/web-platform-tests/html/browsers/offline/introduction-4/event_progress.html
new file mode 100644
index 00000000000..a808db75704
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/offline/introduction-4/event_progress.html
@@ -0,0 +1,18 @@
+<!DOCTYPE HTML>
+<html manifest="../resources/manifest/clock.manifest">
+ <head>
+ <title>Offline Application Cache - Event_progress</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+
+ <script>
+ var t = async_test("progress event test");
+ var cache = window.applicationCache;
+
+ cache.onprogress = t.done();
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/offline/introduction-4/event_updateready-manual.html b/tests/wpt/web-platform-tests/html/browsers/offline/introduction-4/event_updateready-manual.html
new file mode 100644
index 00000000000..4de435144d8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/offline/introduction-4/event_updateready-manual.html
@@ -0,0 +1,22 @@
+<!DOCTYPE HTML>
+<html manifest="../resources/manifest/clock.manifest">
+ <head>
+ <title>Offline Application Cache - Event_updateready</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <ol>
+ <li>Modify the commented part in the manifest file (manifest/clock.manifest) on the server.</li>
+ <li>Refresh the page.</li>
+ </ol>
+ <div id="log"></div>
+
+ <script>
+ var t = async_test("updateready event test");
+ var cache = window.applicationCache;
+
+ cache.onupdateready = t.done();
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/offline/introduction-4/event_updateready_swapcache-manual.html b/tests/wpt/web-platform-tests/html/browsers/offline/introduction-4/event_updateready_swapcache-manual.html
new file mode 100644
index 00000000000..da6cead026e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/offline/introduction-4/event_updateready_swapcache-manual.html
@@ -0,0 +1,30 @@
+<!DOCTYPE HTML>
+<html manifest="../resources/manifest/clock.manifest">
+ <head>
+ <title>Offline Application Cache - Event_updateready_swapCache</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <ol>
+ <li>Modify the commented part in manifest file (manifest/clock.manifest) on the server.</li>
+ <li>Refresh the page.</li>
+ </ol>
+
+ <div id="log"></div>
+
+ <script>
+ var t = async_test("swapCache method test after updateready event is raised");
+ var cache = window.applicationCache;
+
+ cache.onupdateready = t.step_func(function() {
+ try {
+ cache.swapCache();
+ t.done();
+ } catch (e) {
+ assert_unreached("swapCache method failed.");
+ }
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/offline/manifest_main_empty-manual.html b/tests/wpt/web-platform-tests/html/browsers/offline/manifest_main_empty-manual.html
new file mode 100644
index 00000000000..317aaa11379
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/offline/manifest_main_empty-manual.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML>
+<html manifest="resources/manifest/clock.manifest">
+ <head>
+ <title>Offline Application Cache - manifest_main_empty</title>
+ <link rel="stylesheet" href="resources/css/result.css">
+ </head>
+ <body>
+ <ol>
+ <li>Disable the network connection.</li>
+ <li>Refresh the page.</li>
+ <li>If the page is normally displayed, then test is <span class="manualpass"><b>PASS</b></span>, otherwise <span class="manualfail"><b>FAIL</b></span>.</li>
+ </ol>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/offline/manifest_notchanged_online-manual.html b/tests/wpt/web-platform-tests/html/browsers/offline/manifest_notchanged_online-manual.html
new file mode 100644
index 00000000000..a464b426a71
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/offline/manifest_notchanged_online-manual.html
@@ -0,0 +1,19 @@
+<!DOCTYPE HTML>
+<html manifest="resources/manifest/clock.manifest">
+ <head>
+ <title>Offline Application Cache - manifest_notchanged_online</title>
+ <script src="resources/js/clock.js"></script>
+ <link rel="stylesheet" href="resources/css/result.css">
+ <link rel="stylesheet" href="resources/css/clock.css">
+ <link rel="stylesheet" href="resources/css/online.css" type="text/css" media="screen">
+ </head>
+ <body>
+ <ol>
+ <li>Remove time element of this html document and not change manifest file.</li>
+ <li>Refresh the page.</li>
+ <li>If the page is normally displayed, then test is <span class="manualpass"><b>PASS</b></span>, otherwise <span class="manualfail"><b>FAIL</b></span>.</li>
+ </ol>
+
+ <p class="connectivity" width="600">The time is: <output id="clock"></output></p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/offline/manifest_section_empty-manual.html b/tests/wpt/web-platform-tests/html/browsers/offline/manifest_section_empty-manual.html
new file mode 100644
index 00000000000..eea2dbba357
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/offline/manifest_section_empty-manual.html
@@ -0,0 +1,19 @@
+<!DOCTYPE HTML>
+<html manifest="resources/manifest/section_empty.manifest">
+ <head>
+ <title>Offline Application Cache - manifest_section_empty</title>
+ <script src="resources/js/clock.js"></script>
+ <link rel="stylesheet" href="resources/css/result.css">
+ <link rel="stylesheet" href="resources/css/clock.css">
+ <link rel="stylesheet" href="resources/css/online.css" type="text/css" media="screen">
+ </head>
+ <body>
+ <ol>
+ <li>Disable the network connection.</li>
+ <li>Refresh the page.</li>
+ <li>If the time element and colors of result elements are normally displayed, then test is <span class="manualpass"><b>PASS</b></span>, otherwise <span class="manualfail"><b>FAIL</b></span>.</li>
+ </ol>
+
+ <p class="connectivity" width="600">The time is: <output id="clock"></output></p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/offline/manifest_section_many-manual.html b/tests/wpt/web-platform-tests/html/browsers/offline/manifest_section_many-manual.html
new file mode 100644
index 00000000000..9378df1b40f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/offline/manifest_section_many-manual.html
@@ -0,0 +1,19 @@
+<!DOCTYPE HTML>
+<html manifest="resources/manifest/section_many.manifest">
+ <head>
+ <title>Offline Application Cache - manifest_section_many</title>
+ <script src="resources/js/clock.js"></script>
+ <link rel="stylesheet" href="resources/css/result.css">
+ <link rel="stylesheet" href="resources/css/clock.css">
+ <link rel="stylesheet" href="resources/css/online.css" type="text/css" media="screen">
+ </head>
+ <body>
+ <ol type="1">
+ <li>Disable the network connection.</li>
+ <li>Refresh the page.</li>
+ <li>If the time element and colors of result elements are normally displayed, then test is <span class="manualpass"><b>PASS</b></span>, otherwise <span class="manualfail"><b>FAIL</b></span>.</li>
+ </ol>
+
+ <p class="connectivity" width="600">The time is: <output id="clock"></output></p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/offline/manifest_url_check.html b/tests/wpt/web-platform-tests/html/browsers/offline/manifest_url_check.html
new file mode 100644
index 00000000000..02bf70b163d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/offline/manifest_url_check.html
@@ -0,0 +1,18 @@
+<!DOCTYPE HTML>
+<html manifest="resources/manifest/url_check.manifest">
+ <head>
+ <title>Offline Application Cache - URL_#</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+
+ <script>
+ var t = async_test("url check test");
+ var cache = window.applicationCache;
+
+ cache.onerror = t.done();
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/offline/manifests/.gitkeep b/tests/wpt/web-platform-tests/html/browsers/offline/manifests/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/offline/manifests/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/browsers/offline/manifests/contains.json b/tests/wpt/web-platform-tests/html/browsers/offline/manifests/contains.json
new file mode 100644
index 00000000000..3fe509a781c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/offline/manifests/contains.json
@@ -0,0 +1,14 @@
+[
+ {
+ "id": "some-sample-manifests",
+ "original_id": "some-sample-manifests"
+ },
+ {
+ "id": "writing-cache-manifests",
+ "original_id": "writing-cache-manifests"
+ },
+ {
+ "id": "parsing-cache-manifests",
+ "original_id": "parsing-cache-manifests"
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/browsers/offline/resources/css/clock.css b/tests/wpt/web-platform-tests/html/browsers/offline/resources/css/clock.css
new file mode 100644
index 00000000000..fa406d0fbed
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/offline/resources/css/clock.css
@@ -0,0 +1 @@
+output { font: 1em sans-serif; } \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/browsers/offline/resources/css/offline.css b/tests/wpt/web-platform-tests/html/browsers/offline/resources/css/offline.css
new file mode 100644
index 00000000000..76b7f39853c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/offline/resources/css/offline.css
@@ -0,0 +1,5 @@
+.connectivity {
+ color: #fff;
+ background: red;
+ padding: 20px;
+} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/browsers/offline/resources/css/online.css b/tests/wpt/web-platform-tests/html/browsers/offline/resources/css/online.css
new file mode 100644
index 00000000000..39efcb2ab42
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/offline/resources/css/online.css
@@ -0,0 +1,5 @@
+.connectivity {
+ color: #fff;
+ background: blue;
+ padding: 20px;
+} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/browsers/offline/resources/css/result.css b/tests/wpt/web-platform-tests/html/browsers/offline/resources/css/result.css
new file mode 100644
index 00000000000..7d784b8ab5c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/offline/resources/css/result.css
@@ -0,0 +1,11 @@
+.manualpass {
+ color: green;
+}
+.manualfail {
+ color: red;
+}.pass {
+ color: green;
+}
+.fail {
+ color: red;
+}
diff --git a/tests/wpt/web-platform-tests/html/browsers/offline/resources/html/clock.html b/tests/wpt/web-platform-tests/html/browsers/offline/resources/html/clock.html
new file mode 100644
index 00000000000..6b8949a6b19
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/offline/resources/html/clock.html
@@ -0,0 +1,12 @@
+<!-- clock.html -->
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Clock</title>
+ <script src="../js/clock.js"></script>
+ <link rel="stylesheet" href="../css/clock.css">
+ </head>
+ <body>
+ <p>The time is: <output id="clock"></output></p>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/browsers/offline/resources/js/clock.js b/tests/wpt/web-platform-tests/html/browsers/offline/resources/js/clock.js
new file mode 100644
index 00000000000..1ac0dca539f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/offline/resources/js/clock.js
@@ -0,0 +1,3 @@
+setTimeout(function () {
+ document.getElementById('clock').value = new Date();
+}, 1000); \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/browsers/offline/resources/manifest/clock.manifest b/tests/wpt/web-platform-tests/html/browsers/offline/resources/manifest/clock.manifest
new file mode 100644
index 00000000000..a61aae6c619
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/offline/resources/manifest/clock.manifest
@@ -0,0 +1,17 @@
+CACHE MANIFEST
+
+# Version 1
+
+CACHE:
+../css/clock.css
+../js/clock.js
+../css/result.css
+../css/offline.css
+/resources/testharness.js
+/resources/testharnessreport.js
+
+NETWORK:
+../html/clock.html
+
+FALLBACK:
+../css/online.css ../css/offline.css \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/browsers/offline/resources/manifest/section_empty.manifest b/tests/wpt/web-platform-tests/html/browsers/offline/resources/manifest/section_empty.manifest
new file mode 100644
index 00000000000..a23b9013be3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/offline/resources/manifest/section_empty.manifest
@@ -0,0 +1,10 @@
+CACHE MANIFEST
+
+# Version 1
+
+../css/clock.css
+../js/clock.js
+../css/result.css
+../css/online.css
+/resources/testharness.js
+/resources/testharnessreport.js \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/browsers/offline/resources/manifest/section_many.manifest b/tests/wpt/web-platform-tests/html/browsers/offline/resources/manifest/section_many.manifest
new file mode 100644
index 00000000000..7e5e5e99958
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/offline/resources/manifest/section_many.manifest
@@ -0,0 +1,19 @@
+CACHE MANIFEST
+
+# Version 1
+
+CACHE:
+../css/clock.css
+../js/clock.js
+
+CACHE:
+../css/result.css
+../css/offline.css
+/resources/testharness.js
+/resources/testharnessreport.js
+
+NETWORK:
+../html/clock.html
+
+FALLBACK:
+../css/online.css ../css/offline.css \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/browsers/offline/resources/manifest/url_check.manifest b/tests/wpt/web-platform-tests/html/browsers/offline/resources/manifest/url_check.manifest
new file mode 100644
index 00000000000..041df5e55f5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/offline/resources/manifest/url_check.manifest
@@ -0,0 +1,17 @@
+CACHE MANIFEST
+
+# Version 1
+
+CACHE:
+../css/cl#ock.css
+../js/clock.js
+../css/result.css
+../css/offline.css
+/resources/testharness.js
+/resources/testharnessreport.js
+
+NETWORK:
+../html/clock.html
+
+FALLBACK:
+../css/online.css ../css/offline.css \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/browsers/offline/section_network_offline-manual.html b/tests/wpt/web-platform-tests/html/browsers/offline/section_network_offline-manual.html
new file mode 100644
index 00000000000..c4121f5bc53
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/offline/section_network_offline-manual.html
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML>
+<html manifest="resources/manifest/clock.manifest">
+ <head>
+ <title>Offline Application Cache - Section_network_offline</title>
+ <link rel="stylesheet" href="resources/css/result.css">
+ </head>
+ <body>
+ <ol>
+ <li>Disable the network connection.</li>
+ <li>Refresh the page.</li>
+ <li>If only the frame element can't be loaded, then test is <span class="manualpass"><b>PASS</b></span>, otherwise <span class="manualfail"><b>FAIL</b></span>.</li>
+ </ol>
+
+ <IFRAME id="TestFrame" name="TestWindow" src="html/clock.html" width="600" height="50" scrolling="auto" frameborder="1">
+ </IFRAME>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/offline/section_network_online-manual.html b/tests/wpt/web-platform-tests/html/browsers/offline/section_network_online-manual.html
new file mode 100644
index 00000000000..a5d8e59406e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/offline/section_network_online-manual.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML>
+<html manifest="resources/manifest/clock.manifest">
+ <head>
+ <title>Offline Application Cache - Section_network_online</title>
+ <link rel="stylesheet" href="resources/css/result.css">
+ </head>
+ <body>
+ <ol>
+ <li>Refresh the page.</li>
+ <li>If the frame element is loaded, then test is <span class="manualpass"><b>PASS</b></span>, otherwise <span class="manualfail"><b>FAIL</b></span>.</li>
+ </ol>
+
+ <IFRAME id="TestFrame" name="TestWindow" src="html/clock.html" width="600" height="50" scrolling="auto" frameborder="1">
+ </IFRAME>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/offline/the-application-cache-selection-algorithm/.gitkeep b/tests/wpt/web-platform-tests/html/browsers/offline/the-application-cache-selection-algorithm/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/offline/the-application-cache-selection-algorithm/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/browsers/origin/.gitkeep b/tests/wpt/web-platform-tests/html/browsers/origin/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/origin/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/browsers/origin/cross-origin-objects/cross-origin-objects.html b/tests/wpt/web-platform-tests/html/browsers/origin/cross-origin-objects/cross-origin-objects.html
new file mode 100644
index 00000000000..350f999366a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/origin/cross-origin-objects/cross-origin-objects.html
@@ -0,0 +1,336 @@
+<!doctype html>
+<meta charset=utf-8>
+<meta name="timeout" content="long">
+<title>Cross-origin behavior of Window and Location</title>
+<link rel="author" title="Bobby Holley (:bholley)" href="bobbyholley@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#security-window">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#security-location">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<iframe id="B"></iframe>
+<iframe id="C"></iframe>
+<script>
+
+/*
+ * Setup boilerplate. This gives us a same-origin window "B" and a cross-origin
+ * window "C".
+ */
+
+setup({explicit_done: true});
+path = location.pathname.substring(0, location.pathname.lastIndexOf('/')) + '/frame.html';
+var B = document.getElementById('B').contentWindow;
+var C = document.getElementById('C').contentWindow;
+B.frameElement.uriToLoad = path;
+C.frameElement.uriToLoad = 'http://www1.web-platform.test:' + location.port + path;
+
+function reloadSubframes(cb) {
+ var iframes = document.getElementsByTagName('iframe');
+ iframes.forEach = Array.prototype.forEach;
+ var count = 0;
+ function frameLoaded() {
+ this.onload = null;
+ if (++count == iframes.length)
+ cb();
+ }
+ iframes.forEach(function(ifr) { ifr.onload = frameLoaded; ifr.setAttribute('src', ifr.uriToLoad); });
+}
+function isObject(x) { return Object(x) === x; }
+
+/*
+ * Note: we eschew assert_equals in a lot of these tests, since the harness ends
+ * up throwing when it tries to format a message involving a cross-origin object.
+ */
+
+var testList = [];
+function addTest(fun, desc) { testList.push([fun, desc]); }
+
+
+/*
+ * Basic sanity testing.
+ */
+
+addTest(function() {
+ assert_equals(location.host, 'web-platform.test:8000', 'Need to run the top-level test from web-platform.test:8000');
+ assert_equals(B.parent, window, "window.parent works same-origin");
+ assert_equals(C.parent, window, "window.parent works cross-origin");
+ assert_equals(B.location.pathname, path, "location.href works same-origin");
+ assert_throws(null, function() { C.location.pathname; }, "location.pathname throws cross-origin");
+ assert_equals(B.frames, 'override', "Overrides visible in the same-origin case");
+ assert_equals(C.frames, C, "Overrides invisible in the cross-origin case");
+}, "Basic sanity-checking");
+
+/*
+ * Whitelist behavior.
+ *
+ * Also tests for [[GetOwnProperty]] and [[HasOwnProperty]] behavior.
+ */
+
+var whitelistedWindowProps = ['location', 'postMessage', 'window', 'frames', 'self', 'top', 'parent',
+ 'opener', 'closed', 'close', 'blur', 'focus', 'length'];
+addTest(function() {
+ for (var prop in window) {
+ if (whitelistedWindowProps.indexOf(prop) != -1) {
+ C[prop]; // Shouldn't throw.
+ Object.getOwnPropertyDescriptor(C, prop); // Shouldn't throw.
+ assert_true(Object.prototype.hasOwnProperty.call(C, prop), "hasOwnProperty for " + prop);
+ } else {
+ assert_throws(null, function() { C[prop]; }, "Should throw when accessing " + prop + " on Window");
+ assert_throws(null, function() { Object.getOwnPropertyDescriptor(C, prop); },
+ "Should throw when accessing property descriptor for " + prop + " on Window");
+ assert_throws(null, function() { Object.prototype.hasOwnProperty.call(C, prop); },
+ "Should throw when invoking hasOwnProperty for " + prop + " on Window");
+ }
+ if (prop != 'location')
+ assert_throws(null, function() { C[prop] = undefined; }, "Should throw when writing to " + prop + " on Window");
+ }
+ for (var prop in location) {
+ if (prop == 'replace') {
+ C.location[prop]; // Shouldn't throw.
+ Object.getOwnPropertyDescriptor(C.location, prop); // Shouldn't throw.
+ assert_true(Object.prototype.hasOwnProperty.call(C.location, prop), "hasOwnProperty for " + prop);
+ }
+ else {
+ assert_throws(null, function() { C[prop]; }, "Should throw when accessing " + prop + " on Location");
+ assert_throws(null, function() { Object.getOwnPropertyDescriptor(C, prop); },
+ "Should throw when accessing property descriptor for " + prop + " on Location");
+ assert_throws(null, function() { Object.prototype.hasOwnProperty.call(C, prop); },
+ "Should throw when invoking hasOwnProperty for " + prop + " on Location");
+ }
+ if (prop != 'href')
+ assert_throws(null, function() { C[prop] = undefined; }, "Should throw when writing to " + prop + " on Location");
+ }
+}, "Only whitelisted properties are accessible cross-origin");
+
+/*
+ * ES Internal Methods.
+ */
+
+/*
+ * [[GetPrototypeOf]]
+ */
+addTest(function() {
+ assert_true(Object.getPrototypeOf(C) === null, "cross-origin Window proto is null");
+ assert_true(Object.getPrototypeOf(C.location) === null, "cross-origin Location proto is null (__proto__)");
+ var protoGetter = Object.getOwnPropertyDescriptor(Object.prototype, '__proto__').get;
+ assert_true(protoGetter.call(C) === null, "cross-origin Window proto is null");
+ assert_true(protoGetter.call(C.location) === null, "cross-origin Location proto is null (__proto__)");
+ assert_throws(null, function() { C.__proto__; }, "__proto__ property not available cross-origin");
+ assert_throws(null, function() { C.location.__proto__; }, "__proto__ property not available cross-origin");
+
+}, "[[GetPrototypeOf]] should return null");
+
+/*
+ * [[SetPrototypeOf]]
+ */
+addTest(function() {
+ assert_throws(null, function() { C.__proto__ = new Object(); }, "proto set on cross-origin Window");
+ assert_throws(null, function() { C.location.__proto__ = new Object(); }, "proto set on cross-origin Location");
+ var setters = [Object.getOwnPropertyDescriptor(Object.prototype, '__proto__').set];
+ if (Object.setPrototypeOf)
+ setters.push(function(p) { Object.setPrototypeOf(this, p); });
+ setters.forEach(function(protoSetter) {
+ assert_throws(null, function() { protoSetter.call(C, new Object()); }, "proto setter |call| on cross-origin Window");
+ assert_throws(null, function() { protoSetter.call(C.location, new Object()); }, "proto setter |call| on cross-origin Location");
+ });
+}, "[[SetPrototypeOf]] should throw");
+
+/*
+ * [[IsExtensible]]
+ */
+addTest(function() {
+ assert_true(Object.isExtensible(C), "cross-origin Window should be extensible");
+ assert_true(Object.isExtensible(C.location), "cross-origin Location should be extensible");
+}, "[[IsExtensible]] should return true for cross-origin objects");
+
+/*
+ * [[PreventExtensions]]
+ */
+addTest(function() {
+ assert_throws(null, function() { Object.preventExtensions(C) },
+ "preventExtensions on cross-origin Window should throw");
+ assert_throws(null, function() { Object.preventExtensions(C.location) },
+ "preventExtensions on cross-origin Location should throw");
+}, "[[PreventExtensions]] should throw for cross-origin objects");
+
+/*
+ * [[GetOwnProperty]]
+ */
+
+addTest(function() {
+ assert_true(isObject(Object.getOwnPropertyDescriptor(C, 'close')), "C.close is |own|");
+ assert_true(isObject(Object.getOwnPropertyDescriptor(C, 'top')), "C.top is |own|");
+ assert_true(isObject(Object.getOwnPropertyDescriptor(C.location, 'href')), "C.location.href is |own|");
+ assert_true(isObject(Object.getOwnPropertyDescriptor(C.location, 'replace')), "C.location.replace is |own|");
+}, "[[GetOwnProperty]] - Properties on cross-origin objects should be reported |own|");
+
+function checkPropertyDescriptor(desc, propName, expectWritable) {
+ assert_true(isObject(desc), "property descriptor for " + propName + " should exist");
+ assert_equals(desc.enumerable, false, "property descriptor for " + propName + " should be non-enumerable");
+ assert_equals(desc.configurable, true, "property descriptor for " + propName + " should be configurable");
+ if ('value' in desc)
+ assert_equals(desc.writable, expectWritable, "property descriptor for " + propName + " should have writable: " + expectWritable);
+ else
+ assert_equals(typeof desc.set != 'undefined', expectWritable,
+ "property descriptor for " + propName + " should " + (expectWritable ? "" : "not ") + "have setter");
+}
+
+addTest(function() {
+ whitelistedWindowProps.forEach(function(prop) {
+ var desc = Object.getOwnPropertyDescriptor(C, prop);
+ checkPropertyDescriptor(desc, prop, prop == 'location');
+ });
+ checkPropertyDescriptor(Object.getOwnPropertyDescriptor(C.location, 'replace'), 'replace', false);
+ checkPropertyDescriptor(Object.getOwnPropertyDescriptor(C.location, 'href'), 'href', true);
+ assert_equals(typeof Object.getOwnPropertyDescriptor(C.location, 'href').get, 'undefined', "Cross-origin location should have no href getter");
+}, "[[GetOwnProperty]] - Property descriptors for cross-origin properties should be set up correctly");
+
+/*
+ * [[Delete]]
+ */
+addTest(function() {
+ assert_throws(null, function() { delete C.location; }, "Can't delete cross-origin property");
+ assert_throws(null, function() { delete C.parent; }, "Can't delete cross-origin property");
+ assert_throws(null, function() { delete C.length; }, "Can't delete cross-origin property");
+ assert_throws(null, function() { delete C.document; }, "Can't delete cross-origin property");
+ assert_throws(null, function() { delete C.foopy; }, "Can't delete cross-origin property");
+ assert_throws(null, function() { delete C.location.href; }, "Can't delete cross-origin property");
+ assert_throws(null, function() { delete C.location.replace; }, "Can't delete cross-origin property");
+ assert_throws(null, function() { delete C.location.port; }, "Can't delete cross-origin property");
+ assert_throws(null, function() { delete C.location.foopy; }, "Can't delete cross-origin property");
+}, "[[Delete]] Should throw on cross-origin objects");
+
+/*
+ * [[DefineOwnProperty]]
+ */
+function checkDefine(obj, prop) {
+ var valueDesc = { configurable: true, enumerable: false, writable: false, value: 2 };
+ var accessorDesc = { configurable: true, enumerable: false, get: function() {} };
+ assert_throws(null, function() { Object.defineProperty(obj, prop, valueDesc); }, "Can't define cross-origin value property " + prop);
+ assert_throws(null, function() { Object.defineProperty(obj, prop, accessorDesc); }, "Can't define cross-origin accessor property " + prop);
+}
+addTest(function() {
+ checkDefine(C, 'length');
+ checkDefine(C, 'parent');
+ checkDefine(C, 'location');
+ checkDefine(C, 'document');
+ checkDefine(C, 'foopy');
+ checkDefine(C.location, 'href');
+ checkDefine(C.location, 'replace');
+ checkDefine(C.location, 'port');
+ checkDefine(C.location, 'foopy');
+}, "[[DefineOwnProperty]] Should throw for cross-origin objects");
+
+/*
+ * [[Enumerate]]
+ */
+
+addTest(function() {
+ for (var prop in C)
+ assert_unreached("Shouldn't have been able to enumerate " + prop + " on cross-origin Window");
+ for (var prop in C.location)
+ assert_unreached("Shouldn't have been able to enumerate " + prop + " on cross-origin Location");
+}, "[[Enumerate]] should return an empty iterator");
+
+/*
+ * [[OwnPropertyKeys]]
+ */
+
+addTest(function() {
+ assert_array_equals(whitelistedWindowProps.sort(), Object.getOwnPropertyNames(C).sort(),
+ "Object.getOwnPropertyNames() gives the right answer for cross-origin Window");
+ assert_array_equals(Object.getOwnPropertyNames(C.location).sort(), ['href', 'replace'],
+ "Object.getOwnPropertyNames() gives the right answer for cross-origin Location");
+}, "[[OwnPropertyKeys]] should return all properties from cross-origin objects");
+
+addTest(function() {
+ assert_true(B.eval('parent.C') === C, "A and B observe the same identity for C's Window");
+ assert_true(B.eval('parent.C.location') === C.location, "A and B observe the same identity for C's Location");
+}, "A and B jointly observe the same identity for cross-origin Window and Location");
+
+function checkFunction(f, proto) {
+ var name = f.name || '<missing name>';
+ assert_equals(typeof f, 'function', name + " is a function");
+ assert_equals(Object.getPrototypeOf(f), proto, f.name + " has the right prototype");
+}
+
+addTest(function() {
+ checkFunction(C.close, Function.prototype);
+ checkFunction(C.location.replace, Function.prototype);
+}, "Cross-origin functions get local Function.prototype");
+
+addTest(function() {
+ assert_true(isObject(Object.getOwnPropertyDescriptor(C, 'parent')),
+ "Need to be able to use Object.getOwnPropertyDescriptor do this test");
+ checkFunction(Object.getOwnPropertyDescriptor(C, 'parent').get, Function.prototype);
+ checkFunction(Object.getOwnPropertyDescriptor(C.location, 'href').set, Function.prototype);
+}, "Cross-origin Window accessors get local Function.prototype");
+
+addTest(function() {
+ checkFunction(close, Function.prototype);
+ assert_true(close != B.close, 'same-origin Window functions get their own object');
+ assert_true(close != C.close, 'cross-origin Window functions get their own object');
+ var close_B = B.eval('parent.C.close');
+ assert_true(close != close_B, 'close_B is unique when viewed by the parent');
+ assert_true(close_B != C.close, 'different Window functions per-incumbent script settings object');
+ checkFunction(close_B, B.Function.prototype);
+
+ checkFunction(location.replace, Function.prototype);
+ assert_true(location.replace != C.location.replace, "cross-origin Location functions get their own object");
+ var replace_B = B.eval('parent.C.location.replace');
+ assert_true(replace_B != C.location.replace, 'different Location functions per-incumbent script settings object');
+ checkFunction(replace_B, B.Function.prototype);
+}, "Same-origin observers get different functions for cross-origin objects");
+
+addTest(function() {
+ assert_true(isObject(Object.getOwnPropertyDescriptor(C, 'parent')),
+ "Need to be able to use Object.getOwnPropertyDescriptor do this test");
+ var get_self_parent = Object.getOwnPropertyDescriptor(window, 'parent').get;
+ var get_parent_A = Object.getOwnPropertyDescriptor(C, 'parent').get;
+ var get_parent_B = B.eval('Object.getOwnPropertyDescriptor(parent.C, "parent").get');
+ assert_true(get_self_parent != get_parent_A, 'different Window accessors per-incumbent script settings object');
+ assert_true(get_parent_A != get_parent_B, 'different Window accessors per-incumbent script settings object');
+ checkFunction(get_self_parent, Function.prototype);
+ checkFunction(get_parent_A, Function.prototype);
+ checkFunction(get_parent_B, B.Function.prototype);
+}, "Same-origin obsevers get different accessors for cross-origin Window");
+
+addTest(function() {
+ var set_self_href = Object.getOwnPropertyDescriptor(window.location, 'href').set;
+ var set_href_A = Object.getOwnPropertyDescriptor(C.location, 'href').set;
+ var set_href_B = B.eval('Object.getOwnPropertyDescriptor(parent.C.location, "href").set');
+ assert_true(set_self_href != set_href_A, 'different Location accessors per-incumbent script settings object');
+ assert_true(set_href_A != set_href_B, 'different Location accessors per-incumbent script settings object');
+ checkFunction(set_self_href, Function.prototype);
+ checkFunction(set_href_A, Function.prototype);
+ checkFunction(set_href_B, B.Function.prototype);
+}, "Same-origin observers get different accessors for cross-origin Location");
+
+function doDocumentDomainTest(cb) {
+ window.addEventListener('message', function onmessage(evt) {
+ window.removeEventListener('message', onmessage);
+ test(function() {
+ var results = evt.data;
+ assert_true(results.length > 0, 'Need results');
+ results.forEach(function(r) { assert_true(r.pass, r.message); });
+ }, "Cross-origin object identity preserved across document.domain");
+ win.close();
+ cb();
+ });
+ var win = window.open('win-documentdomain.html');
+}
+
+// We do a fresh load of the subframes for each test to minimize side-effects.
+// It would be nice to reload ourselves as well, but we can't do that without
+// disrupting the test harness.
+function runNextTest() {
+ var entry = testList.shift();
+ test(entry[0], entry[1]);
+ if (testList.length != 0)
+ reloadSubframes(runNextTest);
+ else
+ doDocumentDomainTest(done); // Asynchronous.
+}
+reloadSubframes(runNextTest);
+
+</script>
diff --git a/tests/wpt/web-platform-tests/html/browsers/origin/cross-origin-objects/frame.html b/tests/wpt/web-platform-tests/html/browsers/origin/cross-origin-objects/frame.html
new file mode 100644
index 00000000000..c3093ebdac3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/origin/cross-origin-objects/frame.html
@@ -0,0 +1,35 @@
+<!doctype html>
+<html>
+<head>
+<script>
+ // Override the |frames| property to test that such overrides are
+ // properly ignored cross-origin.
+ window.frames = "override";
+
+ // If we get a postMessage, we grab references to everything and set
+ // document.domain to trim off our topmost subdomain.
+ window.onmessage = function(evt) {
+ window.windowReferences = [];
+ window.locationReferences = [];
+ for (var i = 0; i < parent.length; ++i) {
+ windowReferences.push(parent[i]);
+ locationReferences.push(parent[i].location);
+ }
+ document.domain = document.domain.substring(document.domain.indexOf('.') + 1);
+ evt.source.postMessage('', '*');
+ }
+
+ function checkWindowReferences() {
+ for (var i = 0; i < parent.length; ++i) {
+ if (windowReferences[i] != parent[i])
+ throw new Error("Window references don't match for " + i + " after document.domain");
+ if (locationReferences[i] != parent[i].location)
+ throw new Error("Location references don't match for " + i + " after document.domain");
+ }
+ return true;
+ }
+</script>
+</head>
+<body>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/origin/cross-origin-objects/win-documentdomain.html b/tests/wpt/web-platform-tests/html/browsers/origin/cross-origin-objects/win-documentdomain.html
new file mode 100644
index 00000000000..363819c3252
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/origin/cross-origin-objects/win-documentdomain.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script>
+ function loadFrames() {
+ window.A = document.getElementById('A').contentWindow;
+ window.B = document.getElementById('B').contentWindow;
+ window.C = document.getElementById('C').contentWindow;
+ window.D = document.getElementById('D').contentWindow;
+
+ var path = location.pathname.substring(0, location.pathname.lastIndexOf('/')) + '/frame.html';
+ A.location = 'frame.html';
+ B.location = frameURI = 'http://www2.web-platform.test:' + location.port + path;
+ C.location = frameURI = 'http://www2.web-platform.test:' + location.port + path;
+ D.location = frameURI = 'http://www1.web-platform.test:' + location.port + path;
+
+ var loadCount = 0;
+ function frameLoaded() {
+ if (++loadCount == 4)
+ go();
+ }
+ Array.forEach(document.getElementsByTagName('iframe'), function(ifr) { ifr.onload = frameLoaded; });
+ }
+
+
+ var results = [];
+ function assert(cond, msg) {
+ results.push({pass: !!cond, message: msg});
+ }
+
+ function go() {
+ window.onmessage = function() {
+ assert(B.checkWindowReferences(), "B's Window references are still self-consistent after document.domain");
+ for (var i = 0; i < window.length; ++i) {
+ assert(window[i] === B.windowReferences[i],
+ "Window reference " + i + " consistent between globals after document.domain");
+ assert(window[i].location === B.locationReferences[i],
+ "Location reference " + i + " consistent between globals after document.domain");
+ }
+ opener.postMessage(results, '*');
+ };
+ A.document.domain = A.document.domain;
+ document.domain = document.domain;
+ B.postMessage('', '*');
+ }
+
+ </script>
+</head>
+<body onload="loadFrames()">
+ <iframe id="A"></iframe>
+ <iframe id="B"></iframe>
+ <iframe id="C"></iframe>
+ <iframe id="D"></iframe>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/origin/relaxing-the-same-origin-restriction/.gitkeep b/tests/wpt/web-platform-tests/html/browsers/origin/relaxing-the-same-origin-restriction/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/origin/relaxing-the-same-origin-restriction/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/browsers/sandboxing/.gitkeep b/tests/wpt/web-platform-tests/html/browsers/sandboxing/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/sandboxing/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/browsers/the-window-object/.gitkeep b/tests/wpt/web-platform-tests/html/browsers/the-window-object/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/the-window-object/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/browsers/the-window-object/accessing-other-browsing-contexts/.gitkeep b/tests/wpt/web-platform-tests/html/browsers/the-window-object/accessing-other-browsing-contexts/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/the-window-object/accessing-other-browsing-contexts/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/browsers/the-window-object/accessing-other-browsing-contexts/indexed-browsing-contexts-01.html b/tests/wpt/web-platform-tests/html/browsers/the-window-object/accessing-other-browsing-contexts/indexed-browsing-contexts-01.html
new file mode 100644
index 00000000000..9710d15fb26
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/the-window-object/accessing-other-browsing-contexts/indexed-browsing-contexts-01.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: the browsing contexts must be sorted in the order that their containers were inserted into the Document</title>
+<link rel="author" title="Intel" href="http://www.intel.com/" />
+<link rel="help" href="https://html.spec.whatwg.org/multipage/multipage/browsers.html#accessing-other-browsing-contexts" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+
+var t1 = async_test("The window's length must return the number of child browsing contexts(in iframe)");
+function on_load1(fr) {
+ t1.step(function () {
+ var doc = fr.contentDocument;
+ var fr3 = doc.createElement("iframe");
+ fr3.setAttribute("id", "fr3");
+ doc.body.insertBefore(fr3, doc.getElementById("tbl"));
+
+ assert_equals(fr.contentWindow.length, 3, "The window.length should be 3.");
+ assert_array_equals([fr.contentWindow[0].frameElement, fr.contentWindow[1].frameElement, fr.contentWindow[2].frameElement],
+ [fr.contentDocument.getElementById("fr4"), fr.contentDocument.getElementById("fr5"), fr.contentDocument.getElementById("fr3")],
+ "The child browsing contexts must be sorted in the order that their containers were inserted into the Document.");
+ });
+ t1.done();
+}
+
+var t2 = async_test("The window's length must return zero if it has no child browsing context");
+function on_load2(fr) {
+ t2.step(function () {
+ assert_equals(fr.contentWindow.length, 0, "The window.length should be 0.");
+ });
+ t2.done();
+}
+
+</script>
+<iframe id="fr1" src="test1.html" style="display:none" onload="on_load1(this)"></iframe>
+<iframe id="fr2" src="test2.html" style="display:none" onload="on_load2(this)"></iframe>
+<script>
+
+test(function () {
+ assert_equals(window.length, 2, "The window.length should be 2.");
+ assert_array_equals([window[0].frameElement, window[1].frameElement],
+ [document.getElementById("fr1"), document.getElementById("fr2")],
+ "The child browsing contexts must be sorted in the tree order.");
+}, "The window's length must return the number of child browsing contexts");
+
+</script>
diff --git a/tests/wpt/web-platform-tests/html/browsers/the-window-object/accessing-other-browsing-contexts/indexed-browsing-contexts-02.html b/tests/wpt/web-platform-tests/html/browsers/the-window-object/accessing-other-browsing-contexts/indexed-browsing-contexts-02.html
new file mode 100644
index 00000000000..d09c944fd84
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/the-window-object/accessing-other-browsing-contexts/indexed-browsing-contexts-02.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<head>
+ <meta charset="utf-8">
+ <title>HTML Test: the browsing contexts created by various container elements</title>
+ <link rel="author" title="Intel" href="http://www.intel.com/" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+
+ var t1 = async_test("Accessing child browsing contexts 1");
+ var t2 = async_test("Accessing child browsing contexts 2");
+ var t3 = async_test("Accessing child browsing contexts 3");
+ function on_load() {
+ //Child browsing contexts created by iframe, object and embed elements.
+ t1.step(function () {
+ assert_equals(window.length, 3, "The top browsing context should have 3 child browsing contexts.");
+ });
+ t1.step(function () {
+ assert_equals(window[0].name, "win1", "The browsing context name should be 'win1'.");
+ assert_equals(window[1].name, "win2", "The browsing context name should be 'win2'.");
+ assert_equals(window[2].name, "win3", "The browsing context name should be 'win3'.");
+ });
+ t1.done();
+
+ //Child browsing contexts created by frame elements.
+ t2.step(function () {
+ assert_equals(document.getElementById("fr").contentWindow.length, 2,
+ "The child browsing context created by the iframe element should have 2 child browsing contexts.");
+ });
+ t2.step(function () {
+ assert_equals(document.getElementById("fr").contentWindow[0].name, "win4",
+ "The browsing context name should be 'win4'.");
+ assert_equals(document.getElementById("fr").contentWindow[1].name, "win5",
+ "The browsing context name should be 'win5'.");
+ });
+ t2.done();
+
+ //The child browsing context will be removed if the data attribute of the associated object element is removed.
+ t3.step(function () {
+ document.getElementById("obj").removeAttribute("type");
+ assert_equals(window.length, 3, "The top browsing context should have 3 child browsing contexts.");
+ document.getElementById("obj").removeAttribute("data");
+ assert_equals(window.length, 3, "The top browsing context should have 3 child browsing contexts.");
+
+ setTimeout(function () {
+ assert_equals(window.length, 2, "The top browsing context should have 2 child browsing contexts.");
+ }, 1);
+ });
+ t3.done();
+ }
+
+ </script>
+</head>
+<body onload="on_load()">
+ <div id="log"></div>
+ <div style="display:none">
+ <iframe id="fr" name="win1" src="test3.html"></iframe>
+ <object id="obj" name="win2" type="text/html" data="about:blank"></object>
+ <object type="image/png" src="/images/green.png"></object>
+ <embed id="emb" name="win3" type="image/svg+xml" src="/images/green.svg"></embed>
+ </div>
+</body>
diff --git a/tests/wpt/web-platform-tests/html/browsers/the-window-object/accessing-other-browsing-contexts/indexed-browsing-contexts-03.html b/tests/wpt/web-platform-tests/html/browsers/the-window-object/accessing-other-browsing-contexts/indexed-browsing-contexts-03.html
new file mode 100644
index 00000000000..15488911757
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/the-window-object/accessing-other-browsing-contexts/indexed-browsing-contexts-03.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<head>
+ <meta charset="utf-8">
+ <title>HTML Test: indexed property of a Window object</title>
+ <link rel="author" title="Intel" href="http://www.intel.com/" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+
+ var t1 = async_test("Indexed child browsing contexts");
+ function on_load() {
+ t1.step(function () {
+ assert_equals(window[0], document.getElementsByTagName("object")[0].contentWindow,
+ "The first child browsing context's container should be the object element.");
+ assert_equals(window[1], document.getElementsByTagName("iframe")[0].contentWindow,
+ "The second child browsing context's container should be the iframe element.");
+ });
+ t1.done();
+ }
+
+ </script>
+</head>
+<body onload="on_load()">
+ <div id="log"></div>
+ <div style="display:none">
+ <div id="0"></div>
+ <object name="0" type="text/html" data="test2.html"></object>
+ <iframe name="0" src="about:blank"></iframe>
+ </div>
+</body>
diff --git a/tests/wpt/web-platform-tests/html/browsers/the-window-object/accessing-other-browsing-contexts/test1.html b/tests/wpt/web-platform-tests/html/browsers/the-window-object/accessing-other-browsing-contexts/test1.html
new file mode 100644
index 00000000000..f85f90f7c6d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/the-window-object/accessing-other-browsing-contexts/test1.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: child browsing contexts created by iframe elements</title>
+<link rel="author" title="Intel" href="http://www.intel.com/" />
+<table id="tbl">
+ <tr>
+ <td>
+ <iframe id="fr4" src=""></iframe>
+ </td>
+ </tr>
+ <iframe id="fr5" src="about:blank"></iframe>
+</table>
diff --git a/tests/wpt/web-platform-tests/html/browsers/the-window-object/accessing-other-browsing-contexts/test2.html b/tests/wpt/web-platform-tests/html/browsers/the-window-object/accessing-other-browsing-contexts/test2.html
new file mode 100644
index 00000000000..d6a16647fe3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/the-window-object/accessing-other-browsing-contexts/test2.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: child browsing contexts created by object and embed elements</title>
+<link rel="author" title="Intel" href="http://www.intel.com/" />
+<object type="image/png" src="/images/green.png"></object>
+<embed type="image/png" src="/images/green.png"></embed>
diff --git a/tests/wpt/web-platform-tests/html/browsers/the-window-object/accessing-other-browsing-contexts/test3.html b/tests/wpt/web-platform-tests/html/browsers/the-window-object/accessing-other-browsing-contexts/test3.html
new file mode 100644
index 00000000000..a62fdbaae7d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/the-window-object/accessing-other-browsing-contexts/test3.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: child browsing contexts created by frame elements</title>
+<link rel="author" title="Intel" href="http://www.intel.com/" />
+<frameset>
+ <frame name="win4"></frame>
+ <frame name="win5"></frame>
+</frameset>
diff --git a/tests/wpt/web-platform-tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/.gitkeep b/tests/wpt/web-platform-tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/creating_browsing_context_test_01.html b/tests/wpt/web-platform-tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/creating_browsing_context_test_01.html
new file mode 100644
index 00000000000..89cd5b9fa7c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/creating_browsing_context_test_01.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>[Browsing Context] : [APIs for creating browsing_contexts by name]</title>
+<link rel="author" title="Duhyeong Kim" href="mailto:dduskim@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#apis-for-creating-and-navigating-browsing-contexts-by-name">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+ var currentUrl = 'http://' + window.location.host + '/';
+ var win = window.open(currentUrl, '', 'height=1,width=1');
+ this.add_cleanup(function() { win.close(); });
+ win.onload = this.step_func_done(function () {
+ assert_equals(win.location.href, currentUrl, 'should be equal to result url');
+ });
+}, 'first argument: absolute url');
+
+test(function() {
+ var win = window.open('', '', 'height=1,width=1');
+ this.add_cleanup(function() { win.close(); });
+ assert_equals(win.location.href, 'about:blank', 'win.location.href');
+}, 'first argument: empty url');
+
+test(function () {
+ var win = window.open('', 'testWindow', 'height=1,width=1');
+ win.close();
+ assert_equals(win.name, 'testWindow', 'should have a browsing context name');
+}, 'second argument: passing a non-empty name');
+
+test(function () {
+ var win = window.open('', '', 'height=1,width=1');
+ this.add_cleanup(function() { win.close(); });
+ assert_equals(win.name, '', 'window should not have a name');
+ win.name = 'testWindow';
+ assert_equals(win.name, 'testWindow', 'window should have a name');
+}, 'second argument: setting name after opening');
+</script>
diff --git a/tests/wpt/web-platform-tests/html/browsers/the-window-object/browser-interface-elements/.gitkeep b/tests/wpt/web-platform-tests/html/browsers/the-window-object/browser-interface-elements/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/the-window-object/browser-interface-elements/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/browsers/the-window-object/closing-browsing-contexts/.gitkeep b/tests/wpt/web-platform-tests/html/browsers/the-window-object/closing-browsing-contexts/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/the-window-object/closing-browsing-contexts/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/.gitkeep b/tests/wpt/web-platform-tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/browsers/the-window-object/named-access-on-the-window-object/.gitkeep b/tests/wpt/web-platform-tests/html/browsers/the-window-object/named-access-on-the-window-object/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/the-window-object/named-access-on-the-window-object/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/browsers/the-window-object/named-access-on-the-window-object/named-objects.html b/tests/wpt/web-platform-tests/html/browsers/the-window-object/named-access-on-the-window-object/named-objects.html
new file mode 100644
index 00000000000..05a831e87a6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/the-window-object/named-access-on-the-window-object/named-objects.html
@@ -0,0 +1,80 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: Named access on the Window object</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/multipage/browsers.html#named-access-on-the-window-object">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<div style="display:none">
+ <p name="a" id="p1"></p>
+ <a name="a" id="a1" href="#"></a>
+ <applet name="a" id="app1"></applet>
+ <area name="a" id="area1"></area>
+ <embed name="a" id="embed1"></embed>
+ <form name="a" id="form1"></form>
+ <img name="a" id="img1">
+ <object name="a" id="obj1"></object>
+ <span name="a" id="span1"></span>
+
+ <b id="b" name="c"></b>
+ <a name="c"></a>
+ <iframe name="c" id="fm1"></iframe>
+ <iframe name="c" id="fm2" src="test.html" onload="on_load()"></iframe>
+ <input id="b"></input>
+ <span id="d"></span>
+ <a name=""></a>
+ <b id=""></b>
+</div>
+<script>
+
+test(function() {
+ assert_equals(window['c'], document.getElementById("fm1").contentWindow, "The first iframe's window should be returned.");
+}, "Check if the first nested browsing context is returned by window['c']");
+
+test(function() {
+ assert_equals(window['a'].length, 7, "The length should be 7.");
+ assert_true(window['a'] instanceof HTMLCollection);
+ assert_array_equals(window['a'],
+ [ document.getElementById('a1'), document.getElementById('app1'),
+ document.getElementById('area1'), document.getElementById('embed1'),
+ document.getElementById('form1'), document.getElementById('img1'),
+ document.getElementById('obj1') ],
+ "The elements are not in tree order.");
+
+ document.getElementById('a1').setAttribute("name", "");
+ document.getElementById('area1').setAttribute("name", "");
+ assert_array_equals(window['a'],
+ [ document.getElementById('app1'), document.getElementById('embed1'),
+ document.getElementById('form1'), document.getElementById('img1'),
+ document.getElementById('obj1') ],
+ "Window['a'] should not contain the elements with empty name attribute.");
+}, "Check if window['a'] contains all a, applet, area, embed, form, img, and object elements, and their order");
+
+var t = async_test("Check if window['fs'] return the frameset element with name='fs'");
+function on_load () {
+ t.step(function () {
+ assert_equals(document.getElementById('fm2').contentWindow['fs'],
+ document.getElementById('fm2').contentDocument.getElementById('fs1'),
+ "The frameset element should be returned.");
+ });
+ t.done();
+}
+
+test(function() {
+ assert_true(window['b'] instanceof HTMLCollection);
+ assert_array_equals(window['b'], [document.getElementsByTagName('b')[0], document.getElementsByTagName('input')[0]]);
+
+ document.getElementsByTagName('b')[0].setAttribute("id", "");
+ assert_equals(window['b'], document.getElementsByTagName('input')[0],
+ "The window['b'] should not contain the elements with empty id attribute.");
+}, "Check if window['b'] returns the elements with the id='b'");
+
+test(function() {
+ assert_equals(window['d'], document.getElementById('d'));
+}, "Check if window['d'] returns the element with id='d'");
+
+test(function() {
+ assert_equals(window[''], undefined, "The window[''] should be undefined");
+}, "Check widow[''] when there are some elements with empty id or name attribute");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/browsers/the-window-object/named-access-on-the-window-object/test.html b/tests/wpt/web-platform-tests/html/browsers/the-window-object/named-access-on-the-window-object/test.html
new file mode 100644
index 00000000000..c3b3cc18525
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/the-window-object/named-access-on-the-window-object/test.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: Named Object</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<frameset name="fs" id="fs1">
+ <frame></frame>
+</frameset>
diff --git a/tests/wpt/web-platform-tests/html/browsers/the-window-object/named-access-on-the-window-object/window-null-names.html b/tests/wpt/web-platform-tests/html/browsers/the-window-object/named-access-on-the-window-object/window-null-names.html
new file mode 100644
index 00000000000..760bd418db8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/the-window-object/named-access-on-the-window-object/window-null-names.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Named access with null characters</title>
+<link rel="author" title="Ms2ger" href="ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#window">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-window-nameditem">
+<link rel="help" href="https://heycam.github.io/webidl/#named-properties-object">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+test(function() {
+ var iframe = document.createElement("iframe")
+ iframe.name = "a\0b"
+ document.body.appendChild(iframe)
+ assert_equals(window["a\0b"], iframe.contentWindow)
+ assert_equals(window["ab"], undefined)
+ assert_equals(window["a"], undefined)
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/browsers/the-window-object/security-window/.gitkeep b/tests/wpt/web-platform-tests/html/browsers/the-window-object/security-window/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/the-window-object/security-window/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/browsers/the-window-object/security-window/window-security.sub.html b/tests/wpt/web-platform-tests/html/browsers/the-window-object/security-window/window-security.sub.html
new file mode 100644
index 00000000000..213c7bdda84
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/the-window-object/security-window/window-security.sub.html
@@ -0,0 +1,194 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: Window Security</title>
+<link rel="author" title="Intel" href="http://www.intel.com/" />
+<link rel="help" href="https://html.spec.whatwg.org/multipage/multipage/browsers.html#the-window-object" />
+<link rel="help" href="https://html.spec.whatwg.org/multipage/multipage/timers.html#timers" />
+<link rel="help" href="https://html.spec.whatwg.org/multipage/multipage/webappapis.html#atob" />
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#windowsessionstorage" />
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#windowlocalstorage" />
+<link rel="help" href="https://html.spec.whatwg.org/multipage/multipage/browsers.html#window" />
+<link rel="help" href="http://dev.w3.org/csswg/cssom/#extensions-to-the-window-interface" />
+<link rel="help" href="http://dev.w3.org/csswg/cssom-view/#extensions-to-the-window-interface" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<iframe id="fr" src="http://{{domains[www1]}}:{{ports[http][0]}}/" onload="fr_load()" style="display:none"></iframe>
+<script>
+
+var t = async_test("Window Security testing");
+
+function fr_load() {
+ fr = document.getElementById("fr");
+
+ t.step(function () {
+ //SecurityError should be thrown
+ [
+ //attributes
+ {name: "applicationCache"},
+ {name: "devicePixelRatio"},
+ {name: "document"},
+ {name: "external"},
+ {name: "frameElement"},
+ {name: "history"},
+ {name: "innerWidth"},
+ {name: "innerHeight"},
+ {name: "locationbar"},
+ {name: "localStorage"},
+ {name: "menubar"},
+ {name: "name"},
+ {name: "navigator"},
+ {name: "onabort"},
+ {name: "onafterprint"},
+ {name: "onbeforeprint"},
+ {name: "onbeforeunload"},
+ {name: "onblur"},
+ {name: "oncancel"},
+ {name: "oncanplay"},
+ {name: "oncanplaythrough"},
+ {name: "onchange"},
+ {name: "onclick"},
+ {name: "onclose"},
+ {name: "oncontextmenu"},
+ {name: "oncuechange"},
+ {name: "ondblclick"},
+ {name: "ondrag"},
+ {name: "ondragend"},
+ {name: "ondragenter"},
+ {name: "ondragleave"},
+ {name: "ondragover"},
+ {name: "ondragstart"},
+ {name: "ondrop"},
+ {name: "ondurationchange"},
+ {name: "onemptied"},
+ {name: "onended"},
+ {name: "onerror"},
+ {name: "onfocus"},
+ {name: "onhashchange"},
+ {name: "oninput"},
+ {name: "oninvalid"},
+ {name: "onkeydown"},
+ {name: "onkeypress"},
+ {name: "onkeyup"},
+ {name: "onload"},
+ {name: "onloadeddata"},
+ {name: "onloadedmetadata"},
+ {name: "onloadstart"},
+ {name: "onmessage"},
+ {name: "onmousedown"},
+ {name: "onmousemove"},
+ {name: "onmouseout"},
+ {name: "onmouseover"},
+ {name: "onmouseup"},
+ {name: "onmousewheel"},
+ {name: "onoffline"},
+ {name: "ononline"},
+ {name: "onpause"},
+ {name: "onplay"},
+ {name: "onplaying"},
+ {name: "onpagehide"},
+ {name: "onpageshow"},
+ {name: "onpopstate"},
+ {name: "onprogress"},
+ {name: "onratechange"},
+ {name: "onreset"},
+ {name: "onresize"},
+ {name: "onscroll"},
+ {name: "onseeked"},
+ {name: "onseeking"},
+ {name: "onselect"},
+ {name: "onshow"},
+ {name: "onstalled"},
+ {name: "onstorage"},
+ {name: "onsubmit"},
+ {name: "onsuspend"},
+ {name: "ontimeupdate"},
+ {name: "onunload"},
+ {name: "onvolumechange"},
+ {name: "onwaiting"},
+ {name: "pageXOffset"},
+ {name: "pageYOffset"},
+ {name: "personalbar"},
+ {name: "screen"},
+ {name: "scrollbars"},
+ {name: "statusbar"},
+ {name: "status"},
+ {name: "screenX"},
+ {name: "screenY"},
+ {name: "sessionStorage"},
+ {name: "toolbar"},
+ //methods
+ {name: "alert", isMethod: true},
+ {name: "clearInterval", isMethod: true, args:[1]},
+ {name: "clearTimeout", isMethod: true, args:[function () {}, 1]},
+ {name: "confirm", isMethod: true},
+ {name: "getComputedStyle", isMethod: true, args:[document.body, null]},
+ {name: "getSelection", isMethod: true},
+ {name: "matchMedia", isMethod: true, args:["(min-width:50px)"]},
+ {name: "moveBy", isMethod: true, args:[10, 10]},
+ {name: "moveTo", isMethod: true, args:[10, 10]},
+ {name: "open", isMethod: true},
+ {name: "print", isMethod: true},
+ {name: "prompt", isMethod: true},
+ {name: "resizeTo", isMethod: true, args:[10, 10]},
+ {name: "resizeBy", isMethod: true, args:[10, 10]},
+ {name: "scroll", isMethod: true, args:[10, 10]},
+ {name: "scrollTo", isMethod: true, args:[10, 10]},
+ {name: "scrollBy", isMethod: true, args:[10, 10]},
+ {name: "setInterval", isMethod: true, args:[function () {}, 1]},
+ {name: "setTimeout", isMethod: true, args:[function () {}, 1]},
+ {name: "showModalDialog", isMethod: true, args:["auto:blank", "dialog"]},
+ {name: "stop", isMethod: true},
+ ].forEach(function (item) {
+ test(function () {
+ assert_true(item.name in window, "window." + item.name + " should exist.");
+ assert_throws("SecurityError", function () {
+ if (item.isMethod)
+ if (item.args)
+ fr.contentWindow[item.name](item.args[0], item.args[1]);
+ else
+ fr.contentWindow[item.name]();
+ else
+ fr.contentWindow[item.name];
+ }, "A SecurityError exception should be thrown.");
+ }, "A SecurityError exception must be thrown when window." + item.name + " is accessed from a different origin.");
+ });
+
+ //SecurityError should not be thrown
+ [
+ //attributes
+ {name: "closed"},
+ {name: "frames"},
+ {name: "length"},
+ {name: "location"},
+ {name: "opener"},
+ {name: "parent"},
+ {name: "self"},
+ {name: "top"},
+ {name: "window"},
+ //methods
+ {name: "blur", isMethod: true},
+ {name: "close", isMethod: true},
+ {name: "focus", isMethod: true},
+ {name: "postMessage", isMethod: true, args: [{msg: 'foo'}, "*"]}
+ ].forEach(function (item) {
+ test(function () {
+ assert_true(item.name in window, "window." + item.name + " should exist.");
+ try {
+ if (item.isMethod)
+ if (item.args)
+ fr.contentWindow[item.name](item.args[0], item.args[1]);
+ else
+ fr.contentWindow[item.name]();
+ else
+ fr.contentWindow[item.name];
+ } catch (e) {
+ assert_unreached("An unexpected exception was thrown.");
+ }
+ }, "A SecurityError exception should not be thrown when window." + item.name + " is accessed from a different origin.");
+ });
+ });
+ t.done();
+}
+
+</script>
diff --git a/tests/wpt/web-platform-tests/html/browsers/the-window-object/the-windowproxy-object/.gitkeep b/tests/wpt/web-platform-tests/html/browsers/the-window-object/the-windowproxy-object/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/the-window-object/the-windowproxy-object/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/browsers/the-window-object/the-windowproxy-object/test-window-proxy-locationbar-manual.html b/tests/wpt/web-platform-tests/html/browsers/the-window-object/the-windowproxy-object/test-window-proxy-locationbar-manual.html
new file mode 100644
index 00000000000..4331b3b6600
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/the-window-object/the-windowproxy-object/test-window-proxy-locationbar-manual.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <title>Window Proxy locationbar visible flag Test</title>
+ <link rel="author" title='JuneyoungOh' href="juneyoung85@gmail.com">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <h1>Description</h1>
+ <p>WindowProxy.locationbar Test</p>
+
+ <h1>Manual Test Steps:</h1>
+ <ol>
+ <li>Make the locationbar visible in the user agent before executing this test.</li>
+ <li>You may need to manually reload afterwards.</li>
+ </ol>
+
+ <div id="log"></div>
+
+ <script>
+ test(function() {
+ assert_not_equals(typeof window.locationbar, undefined, 'window.locationbar is undefined');
+ assert_true(window.locationbar.visible)
+ }, "window.locationbar.visible");
+ </script>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/browsers/the-window-object/the-windowproxy-object/test-window-proxy-menubar-manual.html b/tests/wpt/web-platform-tests/html/browsers/the-window-object/the-windowproxy-object/test-window-proxy-menubar-manual.html
new file mode 100644
index 00000000000..43345934a58
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/the-window-object/the-windowproxy-object/test-window-proxy-menubar-manual.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <title>Window Proxy menubar visible flag Test</title>
+ <link rel="author" title='JuneyoungOh' href="juneyoung85@gmail.com">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <h1>Description</h1>
+ <p>WindowProxy.menubar Test</p>
+
+ <h1>Manual Test Steps:</h1>
+ <ol>
+ <li>Make the menubar visible in the user agent before executing this test.</li>
+ <li>You may need to manually reload afterwards.</li>
+ </ol>
+
+ <div id="log"></div>
+
+ <script>
+ test(function() {
+ assert_not_equals(typeof window.menubar, undefined, 'window.menubar is undefined');
+ assert_true(window.menubar.visible);
+ }, "window.menubar.visible");
+ </script>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/browsers/the-window-object/the-windowproxy-object/test-window-proxy-personalbar-manual.html b/tests/wpt/web-platform-tests/html/browsers/the-window-object/the-windowproxy-object/test-window-proxy-personalbar-manual.html
new file mode 100644
index 00000000000..d7f109840dc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/the-window-object/the-windowproxy-object/test-window-proxy-personalbar-manual.html
@@ -0,0 +1,29 @@
+<!doctype html>
+<html lang="en">
+<head>
+ <meta charset="utf-8" />
+ <title>Window Proxy personalbar visible flag Test</title>
+ <link rel="author" title="vanessa" href="mailto:vanessaohsy@gmail.com">
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <h1>Description</h1>
+ <p>WindowProxy.personalbar Test</p>
+
+ <h1>Manual Test Steps:</h1>
+ <ol>
+ <li>Make the personalbar visible in the user agent before executing this test.</li>
+ <li>You may need to manually reload afterwards.</li>
+ </ol>
+
+ <div id="log"></div>
+
+ <script type="text/javascript" >
+ test(function () {
+ assert_not_equals(window.personalbar, undefined, "window.personalbar is undefined");
+ assert_true(window.personalbar.visible, "window.personalbar.visible");
+ });
+ </script>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/browsers/the-window-object/the-windowproxy-object/test-window-proxy-scrollbars-manual.html b/tests/wpt/web-platform-tests/html/browsers/the-window-object/the-windowproxy-object/test-window-proxy-scrollbars-manual.html
new file mode 100644
index 00000000000..c412bdbe5ee
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/the-window-object/the-windowproxy-object/test-window-proxy-scrollbars-manual.html
@@ -0,0 +1,29 @@
+<!doctype html>
+<html lang="en">
+<head>
+ <meta charset="utf-8" />
+ <title>Window Proxy scrollbars visible flag Test</title>
+ <link rel="author" title="vanessa" href="vanessaohsy@gmail.com">
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <h1>Description</h1>
+ <p>WindowProxy.scrollbars Test</p>
+
+ <h1>Manual Test Steps:</h1>
+ <ol>
+ <li>Make the scrollbars visible in the user agent before executing this test.</li>
+ <li>You may need to manually reload afterwards.</li>
+ </ol>
+
+ <div id="log"></div>
+
+ <script type="text/javascript" >
+ test(function () {
+ assert_not_equals(window.scrollbars, undefined, "window.scrollbars is undefined");
+ assert_true(window.scrollbars.visible, "window.scrollbars.visible");
+ });
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/the-window-object/the-windowproxy-object/test-window-proxy-statusbar-manual.html b/tests/wpt/web-platform-tests/html/browsers/the-window-object/the-windowproxy-object/test-window-proxy-statusbar-manual.html
new file mode 100644
index 00000000000..b09fcc01758
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/the-window-object/the-windowproxy-object/test-window-proxy-statusbar-manual.html
@@ -0,0 +1,29 @@
+<!doctype html>
+<html>
+<head>
+ <meta charset="utf-8" />
+ <title>WindowProxy statusbar visible flag Test</title>
+ <link rel="author" title="dokenzy" href="dokenzy@gmail.com">
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <h1>Description</h1>
+ <p>WindowProxy.statusbar Test</p>
+
+ <h1>Manual Test Steps:</h1>
+ <ol>
+ <li>Make the statusbar visible in the user agent before executing this test.</li>
+ <li>You may need to manually reload afterwards.</li>
+ </ol>
+
+ <div id="log"></div>
+
+ <script type="text/javascript" >
+ test(function () {
+ assert_not_equals(typeof window.statusbar.visible, undefined, 'window.statusbar.visible');
+ assert_true(window.statusbar.visible, 'window.statusbar.visible');
+ }, "BarProp attribute: window.statusbar.visible");
+ </script>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/browsers/the-window-object/the-windowproxy-object/test-window-proxy-toolbar-manual.html b/tests/wpt/web-platform-tests/html/browsers/the-window-object/the-windowproxy-object/test-window-proxy-toolbar-manual.html
new file mode 100644
index 00000000000..ba465443151
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/the-window-object/the-windowproxy-object/test-window-proxy-toolbar-manual.html
@@ -0,0 +1,29 @@
+<!doctype html>
+<html>
+<head>
+ <meta charset="utf-8" />
+ <title>WindowProxy toolbar visible flag Test</title>
+ <link rel="author" title="dokenzy" href="dokenzy@gmail.com">
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <h1>Description</h1>
+ <p>WindowProxy.toolbar Test</p>
+
+ <h1>Manual Test Steps:</h1>
+ <ol>
+ <li>Make the toolbar visible in the user agent before executing this test.</li>
+ <li>You may need to manually reload afterwards.</li>
+ </ol>
+
+ <div id="log"></div>
+
+ <script type="text/javascript" >
+ test(function () {
+ assert_not_equals(typeof window.toolbar.visible, undefined, 'window.toolbar.visible');
+ assert_true(window.toolbar.visible, 'window.toolbar.visible');
+ }, "BarProp attribute: window.toolbar.visible");
+ </script>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/browsers/the-window-object/window-aliases.html b/tests/wpt/web-platform-tests/html/browsers/the-window-object/window-aliases.html
new file mode 100644
index 00000000000..135be02a30a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/the-window-object/window-aliases.html
@@ -0,0 +1,28 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Aliases of the window object</title>
+<link rel="author" title="Ms2ger" href="mailto:Ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-window">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-frames">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-self">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var global = this;
+
+test(function() {
+ assert_equals(window, global);
+ assert_equals(window.window, global);
+}, "window should be the global object");
+
+test(function() {
+ assert_equals(frames, global);
+ assert_equals(window.frames, global);
+}, "frames should be the global object");
+
+test(function() {
+ assert_equals(self, global);
+ assert_equals(window.self, global);
+}, "self should be the global object");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/browsers/the-window-object/window-indexed-properties-strict.html b/tests/wpt/web-platform-tests/html/browsers/the-window-object/window-indexed-properties-strict.html
new file mode 100644
index 00000000000..610941fc879
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/the-window-object/window-indexed-properties-strict.html
@@ -0,0 +1,43 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Indexed properties of the window object (strict mode)</title>
+<link rel="author" title="Ms2ger" href="ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#window">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-window-item">
+<link rel="help" href="https://heycam.github.io/webidl/#getownproperty">
+<link rel="help" href="https://heycam.github.io/webidl/#defineownproperty">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<iframe></iframe>
+<script>
+test(function() {
+ "use strict";
+ assert_false("-1" in window, "-1 not in window");
+ assert_equals(window[-1], undefined);
+ window[-1] = "foo";
+ assert_equals(window[-1], "foo");
+});
+test(function() {
+ "use strict";
+ assert_throws(new TypeError(), function() {
+ window[0] = "foo";
+ });
+ assert_equals(window[0],
+ document.getElementsByTagName("iframe")[0].contentWindow);
+});
+test(function() {
+ "use strict";
+ assert_throws(new TypeError(), function() {
+ window[1] = "foo";
+ });
+ assert_equals(window[1], undefined);
+});
+test(function() {
+ "use strict";
+ var proto = Window.prototype;
+ [-1, 0, 1].forEach(function(idx) {
+ assert_false(idx in proto, idx + " in proto");
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/browsers/the-window-object/window-indexed-properties.html b/tests/wpt/web-platform-tests/html/browsers/the-window-object/window-indexed-properties.html
new file mode 100644
index 00000000000..9577ab8fbce
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/the-window-object/window-indexed-properties.html
@@ -0,0 +1,35 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Indexed properties of the window object (non-strict mode)</title>
+<link rel="author" title="Ms2ger" href="ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#window">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-window-item">
+<link rel="help" href="https://heycam.github.io/webidl/#getownproperty">
+<link rel="help" href="https://heycam.github.io/webidl/#defineownproperty">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<iframe></iframe>
+<script>
+test(function() {
+ assert_false("-1" in window, "-1 not in window");
+ assert_equals(window[-1], undefined);
+ window[-1] = "foo";
+ assert_equals(window[-1], "foo");
+});
+test(function() {
+ window[0] = "foo";
+ assert_equals(window[0],
+ document.getElementsByTagName("iframe")[0].contentWindow);
+});
+test(function() {
+ window[1] = "foo";
+ assert_equals(window[1], undefined);
+});
+test(function() {
+ var proto = Window.prototype;
+ [-1, 0, 1].forEach(function(idx) {
+ assert_false(idx in proto, idx + " in proto");
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/browsers/the-window-object/window-named-properties.html b/tests/wpt/web-platform-tests/html/browsers/the-window-object/window-named-properties.html
new file mode 100644
index 00000000000..5cf6e446dcb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/the-window-object/window-named-properties.html
@@ -0,0 +1,70 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Changes to named properties of the window object</title>
+<link rel="author" title="Ms2ger" href="ms2ger@gmail.com">
+<link rel="author" title="Boris Zbarsky" href="bzbarsky@mit.edu">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#window">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-window-nameditem">
+<link rel="help" href="https://heycam.github.io/webidl/#named-properties-object">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<iframe name="bar"></iframe>
+<iframe name="constructor"></iframe>
+<script>
+function assert_data_propdesc(pd, Writable, Enumerable, Configurable) {
+ assert_equals(typeof pd, "object");
+ assert_equals(pd.writable, Writable);
+ assert_equals(pd.enumerable, Enumerable);
+ assert_equals(pd.configurable, Configurable);
+}
+test(function() {
+ assert_true("bar" in window, "bar not in window");
+ assert_equals(window["bar"],
+ document.getElementsByTagName("iframe")[0].contentWindow);
+}, "Static name");
+test(function() {
+ assert_true("bar" in Window.prototype, "bar in Window.prototype");
+ assert_false(Window.prototype.hasOwnProperty("bar"), "Window.prototype.hasOwnProperty(\"bar\")");
+
+ var gsp = Object.getPrototypeOf(Object.getPrototypeOf(window));
+ assert_true("bar" in gsp, "bar in gsp");
+ assert_true(gsp.hasOwnProperty("bar"), "gsp.hasOwnProperty(\"bar\")");
+ assert_data_propdesc(Object.getOwnPropertyDescriptor(gsp, "bar"),
+ false, true, true);
+}, "Static name on the prototype");
+test(function() {
+ assert_equals(window.constructor, Window);
+ assert_false(window.hasOwnProperty("constructor"), "window.constructor should not be an own property.");
+
+ var proto = Object.getPrototypeOf(window);
+ assert_equals(proto.constructor, Window);
+ assert_true("constructor" in proto, "constructor in proto");
+ assert_data_propdesc(Object.getOwnPropertyDescriptor(proto, "constructor"),
+ true, false, true);
+
+ var gsp = Object.getPrototypeOf(proto);
+ assert_true("constructor" in gsp, "constructor in gsp");
+ assert_true(gsp.hasOwnProperty("constructor"), "gsp.hasOwnProperty(\"constructor\")");
+ assert_data_propdesc(Object.getOwnPropertyDescriptor(gsp, "constructor"),
+ false, true, true);
+}, "constructor");
+var t = async_test("Dynamic name")
+var t2 = async_test("Ghost name")
+t.step(function() {
+ var iframe = document.getElementsByTagName("iframe")[0];
+ iframe.setAttribute("src", "data:text/html,<script>window.name='foo'<\/script>");
+ iframe.onload = function() {
+ t.step(function() {
+ assert_true("foo" in window, "foo not in window");
+ assert_equals(window["foo"], iframe.contentWindow);
+ });
+ t.done();
+ t2.step(function() {
+ assert_false("bar" in window, "bar still in window");
+ assert_equals(window["bar"], undefined);
+ });
+ t2.done();
+ };
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/browsers/the-window-object/window-properties.html b/tests/wpt/web-platform-tests/html/browsers/the-window-object/window-properties.html
new file mode 100644
index 00000000000..843b671534f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/the-window-object/window-properties.html
@@ -0,0 +1,322 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Properties of the window object</title>
+<link rel="author" title="Ms2ger" href="mailto:Ms2ger@gmail.com">
+<link rel="help" href="http://ecma-international.org/ecma-262/5.1/#sec-15.1">
+<link rel="help" href="https://heycam.github.io/webidl/#interface-prototype-object">
+<link rel="help" href="https://heycam.github.io/webidl/#es-attributes">
+<link rel="help" href="https://heycam.github.io/webidl/#es-operations">
+<link rel="help" href="https://dom.spec.whatwg.org/#eventtarget">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#window">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#windowtimers">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#windowbase64">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#windowsessionstorage">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#windowlocalstorage">
+<link rel="help" href="https://dvcs.w3.org/hg/editing/raw-file/tip/editing.html#dom-window-getselection">
+<link rel="help" href="http://dev.w3.org/csswg/cssom/#widl-def-Window">
+<link rel="help" href="http://dev.w3.org/csswg/cssom-view/#widl-def-Window">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+function assert_data_propdesc(pd, Writable, Enumerable, Configurable) {
+ assert_equals(typeof pd, "object");
+ assert_equals(pd.writable, Writable);
+ assert_equals(pd.enumerable, Enumerable);
+ assert_equals(pd.configurable, Configurable);
+}
+function assert_accessor_propdesc(pd, hasSetter, Enumerable, Configurable) {
+ assert_equals(typeof pd, "object");
+ assert_equals(typeof pd.get, "function");
+ assert_true("set" in pd,
+ "Should always have a setter property on the property descriptor");
+ assert_equals(typeof pd.set, hasSetter ? "function" : "undefined");
+ assert_equals(pd.enumerable, Enumerable);
+ assert_equals(pd.configurable, Configurable);
+}
+
+var unforgeableAttributes = [
+ "window",
+ "document",
+ "location",
+ "top"
+];
+
+var replacableAttributes = [
+ "self",
+ "locationbar",
+ "menubar",
+ "personalbar",
+ "scrollbars",
+ "statusbar",
+ "toolbar",
+ "frames",
+ "length"
+];
+
+var methods = [
+ "close",
+ "stop",
+ "focus",
+ "blur",
+ "open",
+ "alert",
+ "confirm",
+ "prompt",
+ "print",
+ // See below: "showModalDialog",
+ "postMessage",
+
+ // WindowBase64
+ "btoa",
+ "atob",
+
+ // WindowTimers
+ "setTimeout",
+ "clearTimeout",
+ "setInterval",
+ "clearInterval",
+
+ // HTML Editing APIs
+ "getSelection",
+
+ // CSSOM
+ "getComputedStyle",
+
+ // CSSOM-View
+ "matchMedia",
+ "scroll",
+ "scrollTo",
+ "scrollBy"
+];
+
+// We would like to remove showModalDialog from the platform,
+// see <https://www.w3.org/Bugs/Public/show_bug.cgi?id=26437>.
+if ("showModalDialog" in window) {
+ methods.push("showModalDialog");
+}
+
+var readonlyAttributes = [
+ "history",
+ "parent",
+ "frameElement",
+ "navigator",
+ "external",
+ "applicationCache",
+
+ // WindowSessionStorage
+ "sessionStorage",
+
+ // WindowLocalStorage
+ "localStorage",
+
+ // CSSOM-View
+ "screen",
+ "innerWidth",
+ "innerHeight",
+ "scrollX",
+ "pageXOffset",
+ "scrollY",
+ "pageYOffset",
+ "screenX",
+ "screenY",
+ "outerWidth",
+ "outerHeight"
+];
+
+var writableAttributes = [
+ "name",
+ "status",
+ "opener",
+ "onabort",
+ "onafterprint",
+ "onbeforeprint",
+ "onbeforeunload",
+ "onblur",
+ "oncancel",
+ "oncanplay",
+ "oncanplaythrough",
+ "onchange",
+ "onclick",
+ "onclose",
+ "oncontextmenu",
+ "oncuechange",
+ "ondblclick",
+ "ondrag",
+ "ondragend",
+ "ondragenter",
+ "ondragleave",
+ "ondragover",
+ "ondragstart",
+ "ondrop",
+ "ondurationchange",
+ "onemptied",
+ "onended",
+ "onerror",
+ "onfocus",
+ "onhashchange",
+ "oninput",
+ "oninvalid",
+ "onkeydown",
+ "onkeypress",
+ "onkeyup",
+ "onload",
+ "onloadeddata",
+ "onloadedmetadata",
+ "onloadstart",
+ "onmessage",
+ "onmousedown",
+ "onmousemove",
+ "onmouseout",
+ "onmouseover",
+ "onmouseup",
+ "onmousewheel",
+ "onoffline",
+ "ononline",
+ "onpause",
+ "onplay",
+ "onplaying",
+ "onpagehide",
+ "onpageshow",
+ "onpopstate",
+ "onprogress",
+ "onratechange",
+ "onreset",
+ "onresize",
+ "onscroll",
+ "onseeked",
+ "onseeking",
+ "onselect",
+ "onshow",
+ "onstalled",
+ "onstorage",
+ "onsubmit",
+ "onsuspend",
+ "ontimeupdate",
+ "onunload",
+ "onvolumechange",
+ "onwaiting"
+];
+
+test(function() {
+ // 15.1.1 Value Properties of the Global Object
+ ["NaN", "Infinity", "undefined"].forEach(function(id) {
+ test(function() {
+ assert_true(id in window, id + " in window");
+ assert_data_propdesc(Object.getOwnPropertyDescriptor(window, id),
+ false, false, false);
+ }, "Value Property: " + id);
+ });
+}, "Value Properties of the Global Object");
+test(function() {
+ // 15.1.2 Function Properties of the Global Object
+ ["eval", "parseInt", "parseFloat", "isNaN", "isFinite"].forEach(function(id) {
+ test(function() {
+ assert_true(id in window, id + " in window");
+ assert_data_propdesc(Object.getOwnPropertyDescriptor(window, id),
+ true, false, true);
+ }, "Function Property: " + id);
+ });
+}, "Function Properties of the Global Object");
+test(function() {
+ // 15.1.3 URI Handling Function Properties
+ ["decodeURI", "decodeURIComponent", "encodeURI", "encodeURIComponent"].forEach(function(id) {
+ test(function() {
+ assert_true(id in window, id + " in window");
+ assert_data_propdesc(Object.getOwnPropertyDescriptor(window, id),
+ true, false, true);
+ }, "URI Handling Function Property: " + id);
+ });
+}, "URI Handling Function Properties");
+test(function() {
+ // 15.1.4 Constructor Properties of the Global Object
+ ["Object", "Function", "Array", "String", "Boolean", "Number", "Date",
+ "RegExp", "Error", "EvalError", "RangeError", "ReferenceError",
+ "SyntaxError", "TypeError", "URIError"].forEach(function(id) {
+ test(function() {
+ assert_true(id in window, id + " in window");
+ assert_data_propdesc(Object.getOwnPropertyDescriptor(window, id),
+ true, false, true);
+ }, "Constructor Property: " + id);
+ });
+}, "Constructor Properties of the Global Object");
+test(function() {
+ // 15.1.5 Other Properties of the Global Object
+ ["Math", "JSON"].forEach(function(id) {
+ test(function() {
+ assert_true(id in window, id + " in window");
+ assert_data_propdesc(Object.getOwnPropertyDescriptor(window, id),
+ true, false, true);
+ }, "Other Property: " + id);
+ });
+}, "Other Properties of the Global Object");
+test(function() {
+ // EventTarget interface
+ ["addEventListener", "removeEventListener", "dispatchEvent"].forEach(function(id) {
+ test(function() {
+ var EventTargetProto = EventTarget.prototype;
+ assert_true(id in window, id + " in window");
+ assert_equals(window[id], EventTargetProto[id]);
+ assert_data_propdesc(Object.getOwnPropertyDescriptor(EventTargetProto, id),
+ true, true, true);
+ assert_data_propdesc(Object.getOwnPropertyDescriptor(window, id),
+ true, true, true);
+ }, "EventTarget method: " + id);
+ });
+}, "EventTarget interface");
+test(function() {
+ // Window interface
+ methods.forEach(function(id) {
+ test(function() {
+ var WindowProto = Window.prototype;
+ assert_true(id in window, id + " in window");
+ assert_false(id in WindowProto, id + " in Window.prototype");
+ assert_data_propdesc(Object.getOwnPropertyDescriptor(window, id),
+ true, true, true);
+ }, "Window method: " + id);
+ });
+ readonlyAttributes.forEach(function(id) {
+ test(function() {
+ var WindowProto = Window.prototype;
+ assert_true(id in window, id + " in window");
+ assert_false(id in WindowProto, id + " in Window.prototype");
+ assert_accessor_propdesc(Object.getOwnPropertyDescriptor(window, id),
+ false, true, true);
+ }, "Window readonly attribute: " + id);
+ });
+ writableAttributes.forEach(function(id) {
+ test(function() {
+ var WindowProto = Window.prototype;
+ assert_true(id in window, id + " in window");
+ assert_false(id in WindowProto, id + " in Window.prototype");
+ assert_accessor_propdesc(Object.getOwnPropertyDescriptor(window, id),
+ true, true, true);
+ }, "Window attribute: " + id);
+ });
+ unforgeableAttributes.forEach(function(id) {
+ test(function() {
+ var WindowProto = Window.prototype;
+ assert_true(id in window, id + " in window");
+ assert_false(id in WindowProto, id + " in Window.prototype");
+ // location has a [PutForwards] extended attribute.
+ assert_accessor_propdesc(Object.getOwnPropertyDescriptor(window, id),
+ id === "location", true, false);
+ }, "Window unforgeable attribute: " + id);
+ });
+ replacableAttributes.forEach(function(id) {
+ test(function() {
+ var WindowProto = Window.prototype;
+ assert_true(id in window, id + " in window");
+ assert_false(id in WindowProto, id + " in Window.prototype");
+ assert_accessor_propdesc(Object.getOwnPropertyDescriptor(window, id),
+ true, true, true);
+ }, "Window replaceable attribute: " + id);
+ });
+}, "Window interface");
+test(function() {
+ assert_equals(window.constructor, Window);
+ assert_false(window.hasOwnProperty("constructor"), "window.constructor should not be an own property.");
+ assert_data_propdesc(Object.getOwnPropertyDescriptor(Window.prototype, "constructor"),
+ true, false, true);
+}, "constructor");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/browsers/the-window-object/window-prototype-chain.html b/tests/wpt/web-platform-tests/html/browsers/the-window-object/window-prototype-chain.html
new file mode 100644
index 00000000000..d29a8e11f43
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/the-window-object/window-prototype-chain.html
@@ -0,0 +1,35 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Prototype chain of the window object</title>
+<link rel="author" title="Ms2ger" href="ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#window">
+<link rel="help" href="https://dom.spec.whatwg.org/#eventtarget">
+<link rel="help" href="https://heycam.github.io/webidl/#interface-prototype-object">
+<link rel="help" href="https://heycam.github.io/webidl/#named-properties-object">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+test(function() {
+ assert_class_string(window, "Window");
+}, "window object");
+test(function() {
+ var proto = Object.getPrototypeOf(window);
+ assert_class_string(proto, "WindowPrototype");
+ assert_equals(proto, Window.prototype);
+}, "Window.prototype");
+test(function() {
+ var gsp = Object.getPrototypeOf(Object.getPrototypeOf(window));
+ assert_class_string(gsp, "WindowProperties");
+}, "Global scope polluter");
+test(function() {
+ var protoproto = Object.getPrototypeOf(Object.getPrototypeOf(Object.getPrototypeOf(window)));
+ assert_class_string(protoproto, "EventTargetPrototype");
+ assert_equals(protoproto, EventTarget.prototype);
+}, "EventTarget.prototype");
+test(function() {
+ var protoprotoproto = Object.getPrototypeOf(Object.getPrototypeOf(Object.getPrototypeOf(Object.getPrototypeOf(window))));
+ assert_class_string(protoprotoproto, "Object");
+ assert_equals(protoprotoproto, Object.prototype);
+}, "Object.prototype");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/browsers/windows/.gitkeep b/tests/wpt/web-platform-tests/html/browsers/windows/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/windows/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/browsers/windows/auxiliary-browsing-contexts/.gitkeep b/tests/wpt/web-platform-tests/html/browsers/windows/auxiliary-browsing-contexts/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/windows/auxiliary-browsing-contexts/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/browsers/windows/auxiliary-browsing-contexts/contains.json b/tests/wpt/web-platform-tests/html/browsers/windows/auxiliary-browsing-contexts/contains.json
new file mode 100644
index 00000000000..9f2ca3b6fa5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/windows/auxiliary-browsing-contexts/contains.json
@@ -0,0 +1,6 @@
+[
+ {
+ "id": "navigating-auxiliary-browsing-contexts-in-the-dom",
+ "original_id": "navigating-auxiliary-browsing-contexts-in-the-dom"
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/browsers/windows/browsing-context-first-created.xhtml b/tests/wpt/web-platform-tests/html/browsers/windows/browsing-context-first-created.xhtml
new file mode 100644
index 00000000000..a059eec4cc4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/windows/browsing-context-first-created.xhtml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>HTML Test: Browsing context is first created</title>
+ <link rel="author" title="Intel" href="http://www.intel.com/" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ <![CDATA[
+
+ var doc, iframe;
+
+ setup(function () {
+ iframe = document.createElement("iframe");
+ document.body.appendChild(iframe);
+ doc = iframe.contentDocument;
+ });
+
+ test(function () {
+ assert_equals(iframe.contentWindow.history.length, 1, "The history.length should be 1.");
+ }, "Check the history.length of the first created browsing context");
+
+ test(function () {
+ assert_equals(doc.documentURI, "about:blank", "The document's address should be 'about:blank'.");
+ assert_equals(doc.URL, "about:blank", "The document's address should be 'about:blank'.");
+ assert_equals(doc.contentType, "text/html", "The document should be an HTML document.");
+ assert_equals(doc.doctype, null, "The docType of a document without a document type declaration should be null.");
+ assert_equals(doc.compatMode, "BackCompat", "The compatMode of a document without a document type declaration should be 'BackCompat'.");
+ assert_equals(doc.characterSet, "UTF-8", "The document's encoding should be 'UTF-8'.");
+ assert_equals(iframe.contentWindow.parent.document, document);
+ assert_equals(doc.referrer, document.URL, "The document's referrer should be its creator document's address.");
+ }, "Check the document's meta data");
+
+ test(function () {
+ assert_equals(doc.readyState, "complete", "The readyState attribute should be 'complete'.");
+ }, "Check the document's status");
+
+ test(function () {
+ assert_equals(doc.childNodes.length, 1, "The document must have only one child.");
+ assert_equals(doc.documentElement.tagName, "HTML");
+ assert_equals(doc.documentElement.childNodes.length, 2, "The HTML element should have 2 children.");
+ assert_equals(doc.documentElement.childNodes[0].tagName, "HEAD", "The first child of HTML element should be a HEAD element.");
+ assert_false(doc.documentElement.childNodes[0].hasChildNodes(), "The HEAD element should not have children.");
+ assert_equals(doc.documentElement.childNodes[1].tagName, "BODY", "The second child of HTML element should be a BODY element.");
+ assert_false(doc.documentElement.childNodes[1].hasChildNodes(), "The BODY element should not have children.");
+ }, "Check the document's content");
+
+ ]]>
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/browsers/windows/browsing-context-names/.gitkeep b/tests/wpt/web-platform-tests/html/browsers/windows/browsing-context-names/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/windows/browsing-context-names/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/browsers/windows/browsing-context-names/browsing-context-choose-existing.html b/tests/wpt/web-platform-tests/html/browsers/windows/browsing-context-names/browsing-context-choose-existing.html
new file mode 100644
index 00000000000..2eaba22f6fa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/windows/browsing-context-names/browsing-context-choose-existing.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: Choose browsing context - the given name is same as an existing browsing context's name</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<iframe src="existing.html" style="display:none"></iframe>
+<iframe name="existWin" style="display:none"></iframe>
+<script>
+
+var t = async_test("The browsing context must be chosen if the given name is same as its name");
+
+window.addEventListener("message", function (e) {
+ t.step(function() {
+ assert_equals(e.data.name, "existWin", "The browsing context name should be 'existWin'.");
+ });
+ t.done();
+}, false);
+
+frames[0].onload = t.step_func(function(e) {
+ frames[0].do_test();
+});
+
+</script>
diff --git a/tests/wpt/web-platform-tests/html/browsers/windows/browsing-context-names/browsing-context-choose-parent.html b/tests/wpt/web-platform-tests/html/browsers/windows/browsing-context-names/browsing-context-choose-parent.html
new file mode 100644
index 00000000000..c771a8fd71b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/windows/browsing-context-names/browsing-context-choose-parent.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: Choose browsing context - the given name is '_parent'</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<iframe src="parent1.html" name="parentWin" style="display:none"></iframe>
+<script>
+
+var t = async_test("The parent browsing context must be chosen if the given name is '_parent'");
+
+window.addEventListener("message", function (e) {
+ t.step(function() {
+ assert_equals(e.data.name, "parentWin", "The browsing context name should be 'parentWin'.");
+ });
+ t.done();
+}, false);
+
+</script>
diff --git a/tests/wpt/web-platform-tests/html/browsers/windows/browsing-context-names/browsing-context-choose-self-1.html b/tests/wpt/web-platform-tests/html/browsers/windows/browsing-context-names/browsing-context-choose-self-1.html
new file mode 100644
index 00000000000..99d7fe7d3fe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/windows/browsing-context-names/browsing-context-choose-self-1.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: Choose browsing context - the given name is '_self'</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<iframe src="self1.html" style="display:none"></iframe>
+<script>
+
+var t = async_test("The current browsing context must be chosen if the given name is '_self'");
+
+window.addEventListener("message", function (e) {
+ t.step(function () {
+ assert_equals(e.data.name, "selfWin1", "The browsing context name should be 'selfWin1'.");
+ });
+ t.done();
+}, false);
+
+</script>
diff --git a/tests/wpt/web-platform-tests/html/browsers/windows/browsing-context-names/browsing-context-choose-self-2.html b/tests/wpt/web-platform-tests/html/browsers/windows/browsing-context-names/browsing-context-choose-self-2.html
new file mode 100644
index 00000000000..e25a5b44240
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/windows/browsing-context-names/browsing-context-choose-self-2.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: Choose browsing context - the given name is empty string</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<iframe src="self2.html" style="display:none"></iframe>
+<script>
+
+var t = async_test("The current browsing context must be chosen if the given name is empty string");
+
+window.addEventListener("message", function (e) {
+ t.step(function () {
+ assert_equals(e.data.name, "selfWin2", "The browsing context name should be 'selfWin2'.");
+ });
+ t.done();
+}, false);
+
+</script>
diff --git a/tests/wpt/web-platform-tests/html/browsers/windows/browsing-context-names/browsing-context-default-name.html b/tests/wpt/web-platform-tests/html/browsers/windows/browsing-context-names/browsing-context-default-name.html
new file mode 100644
index 00000000000..0bad8e606ed
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/windows/browsing-context-names/browsing-context-default-name.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: Browsing context - Default name</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<iframe src="message.html" style="display:none"></iframe>
+<script>
+
+test(function () {
+ assert_equals(window.frames[0].name, "", "The browsing context should not have a default name.");
+}, "A embedded browsing context has no default name");
+
+test(function () {
+ var win = window.open("about:blank", "_blank");
+ assert_equals(win.name, "", "The browsing context should not have a name.");
+ win.close();
+}, "A browsing context which is opened by window.open() method with '_blank' parameter has no default name");
+
+//This test must be run when the current browsing context's name is not set
+test(function () {
+ assert_equals(window.name, "", "The browsing context should not have a name.");
+}, "A browsing context has no default name");
+
+</script>
diff --git a/tests/wpt/web-platform-tests/html/browsers/windows/browsing-context-names/existing.html b/tests/wpt/web-platform-tests/html/browsers/windows/browsing-context-names/existing.html
new file mode 100644
index 00000000000..13d2c6ab4e0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/windows/browsing-context-names/existing.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>This is a test page</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<script>
+
+function do_test() {
+ window.open("message.html", "existWin");
+}
+
+</script>
diff --git a/tests/wpt/web-platform-tests/html/browsers/windows/browsing-context-names/message.html b/tests/wpt/web-platform-tests/html/browsers/windows/browsing-context-names/message.html
new file mode 100644
index 00000000000..90720d46a9d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/windows/browsing-context-names/message.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: post window's name to top browsing context</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<script>
+
+top.postMessage({name: window.name}, "*");
+
+</script>
diff --git a/tests/wpt/web-platform-tests/html/browsers/windows/browsing-context-names/parent1.html b/tests/wpt/web-platform-tests/html/browsers/windows/browsing-context-names/parent1.html
new file mode 100644
index 00000000000..fb34b2fe707
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/windows/browsing-context-names/parent1.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: browsing context name - parent</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<iframe src="parent2.html"></iframe>
diff --git a/tests/wpt/web-platform-tests/html/browsers/windows/browsing-context-names/parent2.html b/tests/wpt/web-platform-tests/html/browsers/windows/browsing-context-names/parent2.html
new file mode 100644
index 00000000000..34eb1c76bf5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/windows/browsing-context-names/parent2.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: browsing context name - parent</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<script>
+
+window.open("message.html", "_parent");
+
+</script>
diff --git a/tests/wpt/web-platform-tests/html/browsers/windows/browsing-context-names/self1.html b/tests/wpt/web-platform-tests/html/browsers/windows/browsing-context-names/self1.html
new file mode 100644
index 00000000000..2c8e3a414c9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/windows/browsing-context-names/self1.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: browsing context name - self</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<script>
+
+window.name = "selfWin1";
+var win = window.open("message.html", "_self");
+win.close();
+
+</script>
diff --git a/tests/wpt/web-platform-tests/html/browsers/windows/browsing-context-names/self2.html b/tests/wpt/web-platform-tests/html/browsers/windows/browsing-context-names/self2.html
new file mode 100644
index 00000000000..57276fadafe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/windows/browsing-context-names/self2.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: browsing context name - self</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<script>
+
+window.name = "selfWin2";
+var win = window.open("message.html", "");
+win.close();
+
+</script>
diff --git a/tests/wpt/web-platform-tests/html/browsers/windows/groupings-of-browsing-contexts/.gitkeep b/tests/wpt/web-platform-tests/html/browsers/windows/groupings-of-browsing-contexts/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/windows/groupings-of-browsing-contexts/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/browsers/windows/nested-browsing-contexts/.gitkeep b/tests/wpt/web-platform-tests/html/browsers/windows/nested-browsing-contexts/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/windows/nested-browsing-contexts/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/browsers/windows/nested-browsing-contexts/contains.json b/tests/wpt/web-platform-tests/html/browsers/windows/nested-browsing-contexts/contains.json
new file mode 100644
index 00000000000..121284dca14
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/windows/nested-browsing-contexts/contains.json
@@ -0,0 +1,6 @@
+[
+ {
+ "id": "navigating-nested-browsing-contexts-in-the-dom",
+ "original_id": "navigating-nested-browsing-contexts-in-the-dom"
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/browsers/windows/nested-browsing-contexts/frameElement.sub.html b/tests/wpt/web-platform-tests/html/browsers/windows/nested-browsing-contexts/frameElement.sub.html
new file mode 100644
index 00000000000..ffc4a2c0d16
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/windows/nested-browsing-contexts/frameElement.sub.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<meta charset="utf-8"/>
+<title>HTML Test: window.frameElement</title>
+<link rel="author" title="Intel" href="http://www.intel.com/" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+
+var t1 = async_test("The window's frameElement attribute must return its container element if it is a nested browsing context");
+var t2 = async_test("The SecurityError must be thrown if the container's document does not have the same effective script origin");
+
+function on_load() {
+ t1.step(function () {
+ assert_equals(frames[0].frameElement, document.getElementById("fr1"),
+ "The frameElement attribute should be the first iframe element.");
+ assert_equals(window["win2"].frameElement, document.getElementById("obj"),
+ "The frameElement attribute should be the object element.");
+ assert_equals(window["win3"].frameElement, document.getElementById("emb"),
+ "The frameElement attribute should be the embed element.");
+ assert_equals(document.getElementById("fr3").contentWindow[0].frameElement,
+ document.getElementById("fr3").contentDocument.getElementById("f1"),
+ "The frameElement attribute should be the frame element in 'test.html'.");
+ });
+ t1.done();
+
+ t2.step(function () {
+ assert_throws("SecurityError", function () { frames[1].frameElement; },
+ "The SecurityError exception should be thrown.");
+ });
+ t2.done();
+}
+
+</script>
+<body onload="on_load()">
+ <div id="log"></div>
+ <iframe id="fr1"></iframe>
+ <iframe id="fr2" src="test.html"></iframe>
+ <iframe id="fr3" src="" style="display:none"></iframe>
+ <object id="obj" name="win2" type="text/html" data="about:blank"></object>
+ <embed id="emb" name="win3" type="image/svg+xml" src="/images/green.svg" />
+ <script>
+
+ setup(function () {
+ var src = "http://{{domains[www1]}}:{{ports[http][0]}}";
+ src += document.location.pathname.substring(0, document.location.pathname.lastIndexOf("/") + 1);
+ src += "test.html";
+ document.getElementById("fr2").src = src;
+ });
+
+ test(function () {
+ assert_equals(window.frameElement, null,
+ "The frameElement attribute should be null.");
+ }, "The window's frameElement attribute must return null if it is not a nested browsing context");
+
+ </script>
+</body>
diff --git a/tests/wpt/web-platform-tests/html/browsers/windows/nested-browsing-contexts/test.html b/tests/wpt/web-platform-tests/html/browsers/windows/nested-browsing-contexts/test.html
new file mode 100644
index 00000000000..d066b8d4cb2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/windows/nested-browsing-contexts/test.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<meta charset="utf-8"/>
+<title>HTML Test: child browsing context created by the frame element</title>
+<link rel="author" title="Intel" href="http://www.intel.com/" />
+<frameset>
+ <frame id="f1" name="frame">
+</frameset>
diff --git a/tests/wpt/web-platform-tests/html/browsers/windows/secondary-browsing-contexts/.gitkeep b/tests/wpt/web-platform-tests/html/browsers/windows/secondary-browsing-contexts/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/windows/secondary-browsing-contexts/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/browsers/windows/security-nav/.gitkeep b/tests/wpt/web-platform-tests/html/browsers/windows/security-nav/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/browsers/windows/security-nav/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/dom/.gitkeep b/tests/wpt/web-platform-tests/html/dom/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/dom/documents/.gitkeep b/tests/wpt/web-platform-tests/html/dom/documents/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/documents/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/.gitkeep b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/Document.currentScript.html b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/Document.currentScript.html
new file mode 100644
index 00000000000..f865c52a9ae
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/Document.currentScript.html
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>Document.currentScript</title>
+<link rel=help href="https://html.spec.whatwg.org/multipage/#dom-document-currentscript">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#execute-the-script-block">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var expected = [
+ "parse-inline",
+ "parse-ext",
+ "dom-inline",
+ "dom-ext",
+];
+var tests = {};
+expected.forEach(function(id) {
+ tests[id] = async_test("Script " + id);
+});
+function verifyScript(id) {
+ tests[id].step(function() {
+ assert_equals(document.currentScript, document.getElementById(id));
+ this.done();
+ });
+}
+</script>
+
+<!-- Test parser inserted scripts -->
+<script id="parse-inline">
+verifyScript("parse-inline");
+</script>
+<script id="parse-ext" src="data:text/plain,verifyScript('parse-ext');"></script>
+
+<!-- Test DOM inserted scripts -->
+<script>
+var s = document.createElement("script");
+s.textContent = "verifyScript('dom-inline');";
+s.id = "dom-inline";
+document.body.appendChild(s);
+
+s = document.createElement("script");
+s.src = "data:text/plain,verifyScript('dom-ext');";
+s.id = "dom-ext";
+document.body.appendChild(s);
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/Document.getElementsByClassName-null-undef.html b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/Document.getElementsByClassName-null-undef.html
new file mode 100644
index 00000000000..38e66443d53
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/Document.getElementsByClassName-null-undef.html
@@ -0,0 +1,31 @@
+<!doctype html>
+<title>getElementsByClassName and null/undefined</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-getelementsbyclassname">
+<link rel="stylesheet" href="/resources/testharness.css">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<div id="test">
+<p id="p1"></p>
+<p class="undefined" id="p2"></p>
+<p class="null" id="p3"></p>
+<p class="undefined null" id="p4"></p>
+</div>
+<script>
+test(function() {
+ var wrapper = document.getElementById("test");
+ assert_equals(document.getElementsByClassName(undefined).length, 2);
+ assert_equals(document.getElementsByClassName(undefined)[0],
+ document.getElementById("p2"));
+ assert_equals(document.getElementsByClassName(undefined)[1],
+ document.getElementById("p4"));
+/*
+ assert_equals(document.getElementsByClassName(null).length, 2);
+ assert_equals(document.getElementsByClassName(null)[0],
+ document.getElementById("p3"));
+ assert_equals(document.getElementsByClassName(null)[1],
+ document.getElementById("p4"));
+*/
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/Element.getElementsByClassName-null-undef.html b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/Element.getElementsByClassName-null-undef.html
new file mode 100644
index 00000000000..bbb871c02f2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/Element.getElementsByClassName-null-undef.html
@@ -0,0 +1,31 @@
+<!doctype html>
+<title>getElementsByClassName and null/undefined</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-getelementsbyclassname">
+<link rel="stylesheet" href="/resources/testharness.css">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<div id="test">
+<p id="p1"></p>
+<p class="undefined" id="p2"></p>
+<p class="null" id="p3"></p>
+<p class="undefined null" id="p4"></p>
+</div>
+<script>
+test(function() {
+ var wrapper = document.getElementById("test");
+ assert_equals(wrapper.getElementsByClassName(undefined).length, 2);
+ assert_equals(wrapper.getElementsByClassName(undefined)[0],
+ document.getElementById("p2"));
+ assert_equals(wrapper.getElementsByClassName(undefined)[1],
+ document.getElementById("p4"));
+/*
+ assert_equals(wrapper.getElementsByClassName(null).length, 2);
+ assert_equals(wrapper.getElementsByClassName(null)[0],
+ document.getElementById("p3"));
+ assert_equals(wrapper.getElementsByClassName(null)[1],
+ document.getElementById("p4"));
+*/
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.body-getter.html b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.body-getter.html
new file mode 100644
index 00000000000..90ca7e59a03
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.body-getter.html
@@ -0,0 +1,121 @@
+<!DOCTYPE html>
+<title>Document.body</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-document-body">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+function createDocument() {
+ var doc = document.implementation.createHTMLDocument("");
+ doc.removeChild(doc.documentElement);
+ return doc;
+}
+test(function() {
+ var doc = createDocument();
+ assert_equals(doc.body, null);
+}, "Childless document");
+test(function() {
+ var doc = createDocument();
+ doc.appendChild(doc.createElement("html"));
+ assert_equals(doc.body, null);
+}, "Childless html element");
+test(function() {
+ var doc = createDocument();
+ var html = doc.appendChild(doc.createElement("html"));
+ var b =
+ html.appendChild(doc.createElement("body"));
+ html.appendChild(doc.createElement("frameset"));
+ assert_equals(doc.body, b);
+}, "Body followed by frameset inside the html element");
+test(function() {
+ var doc = createDocument();
+ var html = doc.appendChild(doc.createElement("html"));
+ var f =
+ html.appendChild(doc.createElement("frameset"));
+ html.appendChild(doc.createElement("body"));
+ assert_equals(doc.body, f);
+}, "Frameset followed by body inside the html element");
+test(function() {
+ var doc = createDocument();
+ var html =
+ doc.appendChild(doc.createElementNS("http://example.org/test", "html"));
+ html.appendChild(doc.createElement("body"));
+ html.appendChild(doc.createElement("frameset"));
+ assert_equals(doc.body, null);
+}, "Body followed by frameset inside a non-HTML html element");
+test(function() {
+ var doc = createDocument();
+ var html =
+ doc.appendChild(doc.createElementNS("http://example.org/test", "html"));
+ html.appendChild(doc.createElement("frameset"));
+ html.appendChild(doc.createElement("body"));
+ assert_equals(doc.body, null);
+}, "Frameset followed by body inside a non-HTML html element");
+test(function() {
+ var doc = createDocument();
+ var html = doc.appendChild(doc.createElement("html"));
+ html.appendChild(
+ doc.createElementNS("http://example.org/test", "body"));
+ var b = html.appendChild(doc.createElement("body"));
+ assert_equals(doc.body, b);
+}, "Non-HTML body followed by body inside the html element");
+test(function() {
+ var doc = createDocument();
+ var html = doc.appendChild(doc.createElement("html"));
+ html.appendChild(
+ doc.createElementNS("http://example.org/test", "frameset"));
+ var b = html.appendChild(doc.createElement("body"));
+ assert_equals(doc.body, b);
+}, "Non-HTML frameset followed by body inside the html element");
+test(function() {
+ var doc = createDocument();
+ var html = doc.appendChild(doc.createElement("html"));
+ var x = html.appendChild(doc.createElement("x"));
+ x.appendChild(doc.createElement("body"));
+ var body = html.appendChild(doc.createElement("body"));
+ assert_equals(doc.body, body);
+}, "Body inside an x element followed by a body");
+test(function() {
+ var doc = createDocument();
+ var html = doc.appendChild(doc.createElement("html"));
+ var x = html.appendChild(doc.createElement("x"));
+ x.appendChild(doc.createElement("frameset"));
+ var frameset = html.appendChild(doc.createElement("frameset"));
+ assert_equals(doc.body, frameset);
+}, "Frameset inside an x element followed by a frameset");
+
+// Root node is not a html element.
+test(function() {
+ var doc = createDocument();
+ doc.appendChild(doc.createElement("body"));
+ assert_equals(doc.body, null);
+}, "Body as the root node");
+test(function() {
+ var doc = createDocument();
+ doc.appendChild(doc.createElement("frameset"));
+ assert_equals(doc.body, null);
+}, "Frameset as the root node");
+test(function() {
+ var doc = createDocument();
+ var body = doc.appendChild(doc.createElement("body"));
+ body.appendChild(doc.createElement("frameset"));
+ assert_equals(doc.body, null);
+}, "Body as the root node with a frameset child");
+test(function() {
+ var doc = createDocument();
+ var frameset = doc.appendChild(doc.createElement("frameset"));
+ frameset.appendChild(doc.createElement("body"));
+ assert_equals(doc.body, null);
+}, "Frameset as the root node with a body child");
+test(function() {
+ var doc = createDocument();
+ doc.appendChild(doc.createElementNS("http://example.org/test", "body"));
+ assert_equals(doc.body, null);
+}, "Non-HTML body as the root node");
+test(function() {
+ var doc = createDocument();
+ doc.appendChild(doc.createElementNS("http://example.org/test", "frameset"));
+ assert_equals(doc.body, null);
+}, "Non-HTML frameset as the root node");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.body-setter-01.html b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.body-setter-01.html
new file mode 100644
index 00000000000..f3a1638116c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.body-setter-01.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<title>Setting document.body to incorrect values</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-document-body">
+<link rel="help" href="https://heycam.github.io/webidl/#es-interface">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var originalBody = document.body;
+test(function() {
+ assert_throws(new TypeError(), function() {
+ document.body = "text"
+ })
+}, "Should throw a TypeError when trying to set document.body to a string.")
+test(function() {
+ assert_throws("HierarchyRequestError", function() {
+ document.body = document.createElement("div")
+ })
+}, "Should throw a HierarchyRequestError when trying to set document.body to a div element.")
+test(function() {
+ var doc = document.implementation.createHTMLDocument("")
+ doc.removeChild(doc.documentElement)
+ assert_throws("HierarchyRequestError", function() {
+ doc.body = document.createElement("body")
+ })
+}, "Should throw a HierarchyRequestError when trying to set document.body when there's no root element.")
+test(function() {
+ assert_equals(document.body, originalBody);
+}, "document.body has not changed")
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.embeds-document.plugins-01.html b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.embeds-document.plugins-01.html
new file mode 100644
index 00000000000..b4fe36d2430
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.embeds-document.plugins-01.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<title>document.embeds and document.plugins</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-document-embeds">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-document-plugins">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ assert_equals(document.embeds, document.embeds,
+ "embeds should be constant");
+ assert_equals(document.plugins, document.plugins,
+ "plugins should be constant");
+ assert_equals(document.embeds, document.plugins,
+ "embeds should be the same as plugins");
+ assert_equals(document.embeds.length, 0);
+ assert_equals(document.plugins.length, 0);
+}, "No plugins");
+
+test(function() {
+ var embed = document.body.appendChild(document.createElement("embed"));
+ this.add_cleanup(function() { document.body.removeChild(embed) });
+
+ assert_array_equals(document.embeds, [embed]);
+ assert_array_equals(document.plugins, [embed]);
+
+ assert_equals(document.embeds, document.embeds,
+ "embeds should be constant");
+ assert_equals(document.plugins, document.plugins,
+ "plugins should be constant");
+ assert_equals(document.embeds, document.plugins,
+ "embeds should be the same as plugins");
+}, "One plugin");
+
+test(function() {
+ var embed1 = document.createElement("embed"),
+ embed2 = document.createElement("embed");
+
+ document.body.appendChild(embed2);
+ this.add_cleanup(function() { document.body.removeChild(embed2) });
+ document.body.insertBefore(embed1, embed2);
+ this.add_cleanup(function() { document.body.removeChild(embed1) });
+
+ assert_array_equals(document.embeds, [embed1, embed2]);
+ assert_array_equals(document.plugins, [embed1, embed2]);
+
+ assert_equals(document.embeds, document.embeds,
+ "embeds should be constant");
+ assert_equals(document.plugins, document.plugins,
+ "plugins should be constant");
+ assert_equals(document.embeds, document.plugins,
+ "embeds should be the same as plugins");
+}, "Two plugins");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.forms.html b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.forms.html
new file mode 100644
index 00000000000..d6ca1be3826
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.forms.html
@@ -0,0 +1,58 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Document.forms</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<form id="form1">
+<input type="button" name="thebutton" value="alpha">
+<input type=radio name=r1 value=a>
+<input type=radio name=r1 value=b>
+<input type=radio name=r1 value=c>
+<input type=radio name=r1 value=d>
+<input type=radio name=r1 value=e>
+</form>
+
+<form id="form2">
+<input type="button" name="thebutton" value="alpha">
+<input type=radio name=r1 value="a">
+<input type=radio name=r1 value="b">
+<input type=radio name=r1 value="c">
+<input type=radio name=r1 value="d">
+<input type=radio name=r1 value="e">
+</form>
+
+<form id=""></form>
+<script>
+test(function() {
+ assert_equals(document.forms.length, 3);
+ assert_equals(document.forms[0].id, "form1");
+ assert_equals(document.forms[1].id, "form2");
+ assert_equals(document.forms.form1.id, "form1");
+ assert_equals(document.forms.form2.id, "form2");
+ assert_equals(document.forms.item(0).id, "form1");
+ assert_equals(document.forms.item(1).id, "form2");
+ assert_equals(document.forms.namedItem("form1").id, "form1");
+ assert_equals(document.forms.namedItem("form2").id, "form2");
+ assert_equals(document.forms.item("form1").id, "form1");
+ assert_equals(document.forms.item("form2").id, "form2");
+}, "document.forms")
+
+test(function() {
+ assert_equals(document.forms[""], undefined);
+ assert_equals(document.forms.namedItem(""), null);
+}, "document.forms with empty string")
+
+test(function() {
+ var result = [];
+ for (var p in document.forms) {
+ result.push(p);
+ }
+ assert_array_equals(result, ["0", "1", "2", "item", "namedItem", "length"])
+}, "document.forms iteration")
+
+test(function() {
+ var result = Object.getOwnPropertyNames(document.forms);
+ assert_array_equals(result, ["0", "1", "2", "form1", "form2"])
+}, "document.forms getOwnPropertyNames")
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByClassName-same.html b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByClassName-same.html
new file mode 100644
index 00000000000..598475939af
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByClassName-same.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<title>Calling getElementsByClassName with the same argument</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-getelementsbyclassname">
+<link rel="stylesheet" href="/resources/testharness.css">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<div id="test">
+<div class="abcd"></div>
+</div>
+<script>
+test(function() {
+ var list1 = document.getElementsByClassName("abcd");
+ var list2 = document.getElementsByClassName("abcd");
+ assert_true(list1 === list2 || list1 !== list2);
+}, "The user agent may return the same object as the object returned by the earlier call.");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-case.html b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-case.html
new file mode 100644
index 00000000000..d19008c4453
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-case.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<title>getElementsByName and case</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-document-getelementsbyname">
+<link rel="stylesheet" href="/resources/testharness.css">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<div id="test">
+<div name="abcd"></div>
+</div>
+<script>
+test(function() {
+ assert_equals(document.getElementsByName("ABCD").length, 0);
+ assert_equals(document.getElementsByName("abcd").length, 1);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-case.xhtml b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-case.xhtml
new file mode 100644
index 00000000000..48150d6aedc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-case.xhtml
@@ -0,0 +1,22 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>getElementsByName and case</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com"/>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-document-getelementsbyname"/>
+<link rel="stylesheet" href="/resources/testharness.css"/>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id="log"></div>
+<div id="test">
+<div name="abcd"></div>
+</div>
+<script>
+test(function() {
+ assert_equals(document.getElementsByName("ABCD").length, 0);
+ assert_equals(document.getElementsByName("abcd").length, 1);
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-id.html b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-id.html
new file mode 100644
index 00000000000..02c6089d467
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-id.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<title>getElementsByName and ids</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-document-getelementsbyname">
+<link rel="stylesheet" href="/resources/testharness.css">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<div id="test">
+<div id="abcd"></div>
+</div>
+<script>
+test(function() {
+ assert_equals(document.getElementsByName("abcd").length, 0);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-id.xhtml b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-id.xhtml
new file mode 100644
index 00000000000..6c3d608c133
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-id.xhtml
@@ -0,0 +1,21 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>getElementsByName and ids</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com"/>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-document-getelementsbyname"/>
+<link rel="stylesheet" href="/resources/testharness.css"/>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id="log"></div>
+<div id="test">
+<div id="abcd"></div>
+</div>
+<script>
+test(function() {
+ assert_equals(document.getElementsByName("abcd").length, 0);
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-interface.html b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-interface.html
new file mode 100644
index 00000000000..97646e39cfc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-interface.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<title>Document.getElementsByName: interfaces</title>
+<link rel="author" title="Ms2ger" href="mailto:Ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-document-getelementsbyname">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ var collection = document.getElementsByName("name");
+ assert_class_string(collection, "NodeList");
+ assert_true(collection instanceof NodeList, "Should be a NodeList");
+ assert_false(collection instanceof HTMLCollection,
+ "Should not be a HTMLCollection");
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-namespace.html b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-namespace.html
new file mode 100644
index 00000000000..cc74a05f978
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-namespace.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<title>getElementsByName and foreign namespaces</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-document-getelementsbyname">
+<link rel="stylesheet" href="/resources/testharness.css">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<div id="test">
+<p name="math"><math name="math">
+<mi>a</mi>
+<mo>+</mo>
+<mi>b</mi>
+</math>
+<p name="svg"><svg width="300" height="100" name="svg">
+<rect width="300" height="100" fill="rgb(0,0,255)"/>
+</svg>
+</div>
+<script>
+test(function() {
+ var ps = document.getElementById("test")
+ .getElementsByTagName("p");
+ assert_equals(document.getElementsByName("math").length, 1);
+ assert_equals(document.getElementsByName("math")[0], ps[0]);
+ assert_equals(document.getElementsByName("svg").length, 1);
+ assert_equals(document.getElementsByName("svg")[0], ps[1]);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-namespace.xhtml b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-namespace.xhtml
new file mode 100644
index 00000000000..20f516dd9f8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-namespace.xhtml
@@ -0,0 +1,33 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>getElementsByName and foreign namespaces</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com"/>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-document-getelementsbyname"/>
+<link rel="stylesheet" href="/resources/testharness.css"/>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id="log"></div>
+<div id="test">
+<p name="math"><math name="math" xmlns="http://www.w3.org/1998/Math/MathML">
+<mi>a</mi>
+<mo>+</mo>
+<mi>b</mi>
+</math></p>
+<p name="svg"><svg width="300" height="100" name="svg" xmlns="http://www.w3.org/2000/svg">
+<rect width="300" height="100" fill="rgb(0,0,255)"/>
+</svg></p>
+</div>
+<script>
+test(function() {
+ var ps = document.getElementById("test")
+ .getElementsByTagName("p");
+ assert_equals(document.getElementsByName("math").length, 1);
+ assert_equals(document.getElementsByName("math")[0], ps[0]);
+ assert_equals(document.getElementsByName("svg").length, 1);
+ assert_equals(document.getElementsByName("svg")[0], ps[1]);
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-newelements.html b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-newelements.html
new file mode 100644
index 00000000000..4050caa0bc3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-newelements.html
@@ -0,0 +1,122 @@
+<!DOCTYPE html>
+<title>getElementsByName and newly introduced HTML elements</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-document-getelementsbyname">
+<link rel="stylesheet" href="/resources/testharness.css">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<div id="test">
+<section name="section"></section>
+<article name="article"></article>
+<aside name="aside"></aside>
+<hgroup name="hgroup"></hgroup>
+<header name="header"></header>
+<footer name="footer"></footer>
+<nav name="nav"></nav>
+<dialog name="dialog"></dialog>
+<figure name="figure"></figure>
+<audio name="audio"></audio>
+<video name="video"></video>
+<embed name="embed"></embed>
+<mark name="mark"></mark>
+<meter name="meter"></meter>
+<progress name="progress"></progress>
+<time name="time"></time>
+<canvas name="canvas"></canvas>
+<command name="command"></command>
+<menu name="menu"></menu>
+<details name="details"></details>
+<datalist name="datalist"></datalist>
+<keygen name="keygen"></keygen>
+<output name="output"></output>
+<ruby name="ruby"></ruby>
+<rt name="rt"></rt>
+<rp name="rp"></rp>
+<source name="source">
+</div>
+<script>
+test(function() {
+ assert_equals(document.getElementsByName("section").length, 1);
+ assert_equals(document.getElementsByName("section")[0],
+ document.getElementsByTagName("section")[0]);
+ assert_equals(document.getElementsByName("article").length, 1);
+ assert_equals(document.getElementsByName("article")[0],
+ document.getElementsByTagName("article")[0]);
+ assert_equals(document.getElementsByName("aside").length, 1);
+ assert_equals(document.getElementsByName("aside")[0],
+ document.getElementsByTagName("aside")[0]);
+ assert_equals(document.getElementsByName("hgroup").length, 1);
+ assert_equals(document.getElementsByName("hgroup")[0],
+ document.getElementsByTagName("hgroup")[0]);
+ assert_equals(document.getElementsByName("header").length, 1);
+ assert_equals(document.getElementsByName("header")[0],
+ document.getElementsByTagName("header")[0]);
+ assert_equals(document.getElementsByName("footer").length, 1);
+ assert_equals(document.getElementsByName("footer")[0],
+ document.getElementsByTagName("footer")[0]);
+ assert_equals(document.getElementsByName("nav").length, 1);
+ assert_equals(document.getElementsByName("nav")[0],
+ document.getElementsByTagName("nav")[0]);
+ assert_equals(document.getElementsByName("dialog").length, 1);
+ assert_equals(document.getElementsByName("dialog")[0],
+ document.getElementsByTagName("dialog")[0]);
+ assert_equals(document.getElementsByName("figure").length, 1);
+ assert_equals(document.getElementsByName("figure")[0],
+ document.getElementsByTagName("figure")[0]);
+ assert_equals(document.getElementsByName("audio").length, 1);
+ assert_equals(document.getElementsByName("audio")[0],
+ document.getElementsByTagName("audio")[0]);
+ assert_equals(document.getElementsByName("video").length, 1);
+ assert_equals(document.getElementsByName("video")[0],
+ document.getElementsByTagName("video")[0]);
+ assert_equals(document.getElementsByName("embed").length, 1);
+ assert_equals(document.getElementsByName("embed")[0],
+ document.getElementsByTagName("embed")[0]);
+ assert_equals(document.getElementsByName("mark").length, 1);
+ assert_equals(document.getElementsByName("mark")[0],
+ document.getElementsByTagName("mark")[0]);
+ assert_equals(document.getElementsByName("meter").length, 1);
+ assert_equals(document.getElementsByName("meter")[0],
+ document.getElementsByTagName("meter")[0]);
+ assert_equals(document.getElementsByName("progress").length, 1);
+ assert_equals(document.getElementsByName("progress")[0],
+ document.getElementsByTagName("progress")[0]);
+ assert_equals(document.getElementsByName("time").length, 1);
+ assert_equals(document.getElementsByName("time")[0],
+ document.getElementsByTagName("time")[0]);
+ assert_equals(document.getElementsByName("canvas").length, 1);
+ assert_equals(document.getElementsByName("canvas")[0],
+ document.getElementsByTagName("canvas")[0]);
+ assert_equals(document.getElementsByName("command").length, 1);
+ assert_equals(document.getElementsByName("command")[0],
+ document.getElementsByTagName("command")[0]);
+ assert_equals(document.getElementsByName("menu").length, 1);
+ assert_equals(document.getElementsByName("menu")[0],
+ document.getElementsByTagName("menu")[0]);
+ assert_equals(document.getElementsByName("details").length, 1);
+ assert_equals(document.getElementsByName("details")[0],
+ document.getElementsByTagName("details")[0]);
+ assert_equals(document.getElementsByName("datalist").length, 1);
+ assert_equals(document.getElementsByName("datalist")[0],
+ document.getElementsByTagName("datalist")[0]);
+ assert_equals(document.getElementsByName("keygen").length, 1);
+ assert_equals(document.getElementsByName("keygen")[0],
+ document.getElementsByTagName("keygen")[0]);
+ assert_equals(document.getElementsByName("output").length, 1);
+ assert_equals(document.getElementsByName("output")[0],
+ document.getElementsByTagName("output")[0]);
+ assert_equals(document.getElementsByName("ruby").length, 1);
+ assert_equals(document.getElementsByName("ruby")[0],
+ document.getElementsByTagName("ruby")[0]);
+ assert_equals(document.getElementsByName("rt").length, 1);
+ assert_equals(document.getElementsByName("rt")[0],
+ document.getElementsByTagName("rt")[0]);
+ assert_equals(document.getElementsByName("rp").length, 1);
+ assert_equals(document.getElementsByName("rp")[0],
+ document.getElementsByTagName("rp")[0]);
+ assert_equals(document.getElementsByName("source").length, 1);
+ assert_equals(document.getElementsByName("source")[0],
+ document.getElementsByTagName("source")[0]);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-newelements.xhtml b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-newelements.xhtml
new file mode 100644
index 00000000000..1a4843a43b7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-newelements.xhtml
@@ -0,0 +1,127 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>getElementsByName and newly introduced HTML elements</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com"/>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-document-getelementsbyname"/>
+<link rel="stylesheet" href="/resources/testharness.css"/>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id="log"></div>
+<div id="test">
+<section name="section"></section>
+<article name="article"></article>
+<aside name="aside"></aside>
+<hgroup name="hgroup"></hgroup>
+<header name="header"></header>
+<footer name="footer"></footer>
+<nav name="nav"></nav>
+<dialog name="dialog"></dialog>
+<figure name="figure"></figure>
+<audio name="audio"></audio>
+<video name="video"></video>
+<embed name="embed"></embed>
+<mark name="mark"></mark>
+<meter name="meter"></meter>
+<progress name="progress"></progress>
+<time name="time"></time>
+<canvas name="canvas"></canvas>
+<command name="command"></command>
+<menu name="menu"></menu>
+<details name="details"></details>
+<datalist name="datalist"></datalist>
+<keygen name="keygen"></keygen>
+<output name="output"></output>
+<ruby name="ruby"></ruby>
+<rt name="rt"></rt>
+<rp name="rp"></rp>
+<source name="source"/>
+</div>
+<script>
+test(function() {
+ assert_equals(document.getElementsByName("section").length, 1);
+ assert_equals(document.getElementsByName("section")[0],
+ document.getElementsByTagName("section")[0]);
+ assert_equals(document.getElementsByName("article").length, 1);
+ assert_equals(document.getElementsByName("article")[0],
+ document.getElementsByTagName("article")[0]);
+ assert_equals(document.getElementsByName("aside").length, 1);
+ assert_equals(document.getElementsByName("aside")[0],
+ document.getElementsByTagName("aside")[0]);
+ assert_equals(document.getElementsByName("hgroup").length, 1);
+ assert_equals(document.getElementsByName("hgroup")[0],
+ document.getElementsByTagName("hgroup")[0]);
+ assert_equals(document.getElementsByName("header").length, 1);
+ assert_equals(document.getElementsByName("header")[0],
+ document.getElementsByTagName("header")[0]);
+ assert_equals(document.getElementsByName("footer").length, 1);
+ assert_equals(document.getElementsByName("footer")[0],
+ document.getElementsByTagName("footer")[0]);
+ assert_equals(document.getElementsByName("nav").length, 1);
+ assert_equals(document.getElementsByName("nav")[0],
+ document.getElementsByTagName("nav")[0]);
+ assert_equals(document.getElementsByName("dialog").length, 1);
+ assert_equals(document.getElementsByName("dialog")[0],
+ document.getElementsByTagName("dialog")[0]);
+ assert_equals(document.getElementsByName("figure").length, 1);
+ assert_equals(document.getElementsByName("figure")[0],
+ document.getElementsByTagName("figure")[0]);
+ assert_equals(document.getElementsByName("audio").length, 1);
+ assert_equals(document.getElementsByName("audio")[0],
+ document.getElementsByTagName("audio")[0]);
+ assert_equals(document.getElementsByName("video").length, 1);
+ assert_equals(document.getElementsByName("video")[0],
+ document.getElementsByTagName("video")[0]);
+ assert_equals(document.getElementsByName("embed").length, 1);
+ assert_equals(document.getElementsByName("embed")[0],
+ document.getElementsByTagName("embed")[0]);
+ assert_equals(document.getElementsByName("mark").length, 1);
+ assert_equals(document.getElementsByName("mark")[0],
+ document.getElementsByTagName("mark")[0]);
+ assert_equals(document.getElementsByName("meter").length, 1);
+ assert_equals(document.getElementsByName("meter")[0],
+ document.getElementsByTagName("meter")[0]);
+ assert_equals(document.getElementsByName("progress").length, 1);
+ assert_equals(document.getElementsByName("progress")[0],
+ document.getElementsByTagName("progress")[0]);
+ assert_equals(document.getElementsByName("time").length, 1);
+ assert_equals(document.getElementsByName("time")[0],
+ document.getElementsByTagName("time")[0]);
+ assert_equals(document.getElementsByName("canvas").length, 1);
+ assert_equals(document.getElementsByName("canvas")[0],
+ document.getElementsByTagName("canvas")[0]);
+ assert_equals(document.getElementsByName("command").length, 1);
+ assert_equals(document.getElementsByName("command")[0],
+ document.getElementsByTagName("command")[0]);
+ assert_equals(document.getElementsByName("menu").length, 1);
+ assert_equals(document.getElementsByName("menu")[0],
+ document.getElementsByTagName("menu")[0]);
+ assert_equals(document.getElementsByName("details").length, 1);
+ assert_equals(document.getElementsByName("details")[0],
+ document.getElementsByTagName("details")[0]);
+ assert_equals(document.getElementsByName("datalist").length, 1);
+ assert_equals(document.getElementsByName("datalist")[0],
+ document.getElementsByTagName("datalist")[0]);
+ assert_equals(document.getElementsByName("keygen").length, 1);
+ assert_equals(document.getElementsByName("keygen")[0],
+ document.getElementsByTagName("keygen")[0]);
+ assert_equals(document.getElementsByName("output").length, 1);
+ assert_equals(document.getElementsByName("output")[0],
+ document.getElementsByTagName("output")[0]);
+ assert_equals(document.getElementsByName("ruby").length, 1);
+ assert_equals(document.getElementsByName("ruby")[0],
+ document.getElementsByTagName("ruby")[0]);
+ assert_equals(document.getElementsByName("rt").length, 1);
+ assert_equals(document.getElementsByName("rt")[0],
+ document.getElementsByTagName("rt")[0]);
+ assert_equals(document.getElementsByName("rp").length, 1);
+ assert_equals(document.getElementsByName("rp")[0],
+ document.getElementsByTagName("rp")[0]);
+ assert_equals(document.getElementsByName("source").length, 1);
+ assert_equals(document.getElementsByName("source")[0],
+ document.getElementsByTagName("source")[0]);
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-null-undef.html b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-null-undef.html
new file mode 100644
index 00000000000..72734aedaa9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-null-undef.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<title>Calling getElementsByName with null and undefined</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-document-getelementsbyname">
+<link rel="help" href="https://heycam.github.io/webidl/#es-DOMString">
+<link rel="help" href="http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf#page=57">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ var n = document.createElement("div");
+ n.setAttribute("name", "null");
+
+ document.body.appendChild(n);
+ this.add_cleanup(function() { document.body.removeChild(n) });
+
+ assert_equals(document.getElementsByName(null)[0], n);
+}, "getElementsByName(null)");
+
+test(function() {
+ var u = document.createElement("div");
+ u.setAttribute("name", "undefined");
+
+ document.body.appendChild(u);
+ this.add_cleanup(function() { document.body.removeChild(u) });
+
+ assert_equals(document.getElementsByName(undefined)[0], u);
+}, "getElementsByName(undefined)");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-null-undef.xhtml b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-null-undef.xhtml
new file mode 100644
index 00000000000..9e79c84dad5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-null-undef.xhtml
@@ -0,0 +1,35 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Calling getElementsByName with null and undefined</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com"/>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-document-getelementsbyname"/>
+<link rel="help" href="https://heycam.github.io/webidl/#es-DOMString"/>
+<link rel="help" href="http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf#page=57"/>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ var n = document.createElement("div");
+ n.setAttribute("name", "null");
+
+ document.body.appendChild(n);
+ this.add_cleanup(function() { document.body.removeChild(n) });
+
+ assert_equals(document.getElementsByName(null)[0], n);
+}, "getElementsByName(null)");
+
+test(function() {
+ var u = document.createElement("div");
+ u.setAttribute("name", "undefined");
+
+ document.body.appendChild(u);
+ this.add_cleanup(function() { document.body.removeChild(u) });
+
+ assert_equals(document.getElementsByName(undefined)[0], u);
+}, "getElementsByName(undefined)");
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-param.html b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-param.html
new file mode 100644
index 00000000000..a406a55c23c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-param.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<title>getElementsByName and the param element</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-document-getelementsbyname">
+<link rel="stylesheet" href="/resources/testharness.css">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<div id="test">
+<param name="test1">
+<object>
+<param name="test2">
+</object>
+</div>
+<script>
+test(function() {
+ assert_equals(document.getElementsByName("test1").length, 1);
+ assert_equals(document.getElementsByName("test1")[0],
+ document.getElementsByTagName("param")[0]);
+ assert_equals(document.getElementsByName("test2").length, 1);
+ assert_equals(document.getElementsByName("test2")[0],
+ document.getElementsByTagName("param")[1]);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-param.xhtml b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-param.xhtml
new file mode 100644
index 00000000000..b64aec0ceb5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-param.xhtml
@@ -0,0 +1,29 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>getElementsByName and the param element</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com"/>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-document-getelementsbyname"/>
+<link rel="stylesheet" href="/resources/testharness.css"/>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id="log"></div>
+<div id="test">
+<param name="test1"/>
+<object>
+<param name="test2"/>
+</object>
+</div>
+<script>
+test(function() {
+ assert_equals(document.getElementsByName("test1").length, 1);
+ assert_equals(document.getElementsByName("test1")[0],
+ document.getElementsByTagName("param")[0]);
+ assert_equals(document.getElementsByName("test2").length, 1);
+ assert_equals(document.getElementsByName("test2")[0],
+ document.getElementsByTagName("param")[1]);
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-same.html b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-same.html
new file mode 100644
index 00000000000..2ca51324103
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-same.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<title>Calling getElementsByName with the same argument</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-document-getelementsbyname">
+<link rel="stylesheet" href="/resources/testharness.css">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<div id="test">
+<div name="abcd"></div>
+</div>
+<script>
+test(function() {
+ var list1 = document.getElementsByName("abcd");
+ var list2 = document.getElementsByName("abcd");
+ assert_true(list1 === list2 || list1 !== list2);
+}, "The user agent may return the same object as the object returned by the earlier call.");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.head-01.html b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.head-01.html
new file mode 100644
index 00000000000..0a05e2a3e2f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.head-01.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<title>document.head</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-document-head">
+<link rel="stylesheet" href="/resources/testharness.css">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ var head = document.getElementsByTagName("head")[0];
+ assert_equals(document.head, head);
+ document.head = "";
+ assert_equals(document.head, head);
+ document.head = document.createElement("head");
+ assert_equals(document.head, head);
+ document.documentElement.appendChild(document.createElement("head"));
+ assert_equals(document.head, head);
+ var head2 = document.createElement("head");
+ document.documentElement.insertBefore(head2, head);
+ assert_equals(document.head, head2);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.head-02.html b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.head-02.html
new file mode 100644
index 00000000000..acbc2bd6c5d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.head-02.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<title>document.head</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-document-head">
+<link rel="stylesheet" href="/resources/testharness.css">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var HTML = "http://www.w3.org/1999/xhtml";
+test(function() {
+ var head = document.getElementsByTagName("head")[0];
+ assert_equals(document.head, head);
+ var head2 = document.createElementNS(HTML, "blah:head");
+ document.documentElement.insertBefore(head2, head);
+ assert_equals(document.head, head2);
+ var head3 = document.createElementNS("http://www.example.org/", "blah:head");
+ document.documentElement.insertBefore(head3, head2);
+ assert_equals(document.head, head2);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.images.html b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.images.html
new file mode 100644
index 00000000000..558fdebc3a0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.images.html
@@ -0,0 +1,105 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Document.images</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<div id=test>
+<img>
+<img id=x><img name=y><img id=z1 name=z2>
+<img id=a><img id=a>
+<img name=b><img name=b>
+<img id=><img name=>
+<input type=image name=input>
+</div>
+<script>
+function assert_all(aAssertFunc, aCollection) {
+ for (var i = 0; i < aCollection.length; ++i) {
+ aAssertFunc(aCollection[i]);
+ }
+}
+
+var XHTML = "http://www.w3.org/1999/xhtml";
+var div, images, c;
+
+setup(function() {
+ div = document.getElementById("test");
+ var foreign =
+ div.appendChild(document.createElementNS("http://example.org", "img"));
+ foreign.setAttribute("id", "f");
+
+ images = [].slice.call(div.getElementsByTagNameNS(XHTML, "img"));
+
+ c = document.images;
+});
+
+test(function() {
+ assert_equals(c.length, 10);
+ assert_array_equals(c, images);
+
+ assert_all(function (aElement) {
+ assert_equals(aElement.namespaceURI, XHTML);
+ }, c);
+}, "document.images should contain all HTML img elements");
+
+test(function() {
+ assert_equals(c.x, images[1]);
+ assert_equals(c.namedItem("x"), images[1]);
+ assert_true("x" in c, '"x" in c');
+}, "img with id");
+
+test(function() {
+ assert_equals(c.y, images[2]);
+ assert_equals(c.namedItem("y"), images[2]);
+ assert_true("y" in c, '"y" in c');
+}, "img with name");
+
+test(function() {
+ assert_equals(c.z1, images[3]);
+ assert_equals(c.namedItem("z1"), images[3]);
+ assert_true("z1" in c, '"z1" in c');
+ assert_equals(c.z2, images[3]);
+ assert_equals(c.namedItem("z2"), images[3]);
+ assert_true("z2" in c, '"z2" in c');
+}, "img with id and name");
+
+test(function() {
+ assert_equals(c.a, images[4]);
+ assert_equals(c.namedItem("a"), images[4]);
+ assert_true("a" in c, '"a" in c');
+}, "Two img elements with the same id");
+
+test(function() {
+ assert_equals(c.b, images[6]);
+ assert_equals(c.namedItem("b"), images[6]);
+ assert_true("b" in c, '"b" in c');
+}, "Two img elements with the same name");
+
+test(function() {
+ assert_equals(c.c, undefined);
+ assert_equals(c.namedItem("c"), null);
+ assert_false("c" in c, '"c" in c');
+}, "Unknown name should not be in the collection");
+
+test(function() {
+ assert_equals(c.f, undefined);
+ assert_equals(c.namedItem("f"), null);
+ assert_false("f" in c, '"f" in c');
+}, "Foreign element should not be in the collection");
+
+test(function() {
+ assert_equals(c.input, undefined);
+ assert_equals(c.namedItem("input"), null);
+ assert_false("input" in c, '"input" in c');
+ var input = div.getElementsByTagName("input")[0];
+ assert_all(function (aElement) {
+ assert_not_equals(aElement.namespaceURI, input);
+ }, c);
+}, "Input elements should not be in the collection");
+
+test(function() {
+ assert_equals(c[""], undefined);
+ assert_equals(c.namedItem(""), null);
+ assert_false("" in c, '"" in c');
+}, "The empty string should not be in the collections");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.title-01.html b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.title-01.html
new file mode 100644
index 00000000000..0e59b59ad50
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.title-01.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<title>document.title with head blown away</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#document.title">
+<link rel="stylesheet" href="/resources/testharness.css">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ assert_equals(document.title, "document.title with head blown away");
+})
+test(function() {
+ var head = document.getElementsByTagName("head")[0];
+ assert_true(!!head, "Head gone?!")
+ head.parentNode.removeChild(head);
+ assert_false(!!document.getElementsByTagName("head")[0], "Head still there?!")
+ document.title = "FAIL";
+ assert_equals(document.title, "");
+})
+test(function() {
+ var title2 = document.createElement("title");
+ title2.appendChild(document.createTextNode("PASS"));
+ document.body.appendChild(title2);
+ assert_equals(document.title, "PASS");
+})
+test(function() {
+ var title3 = document.createElement("title");
+ title3.appendChild(document.createTextNode("PASS2"));
+ document.documentElement.insertBefore(title3, document.body);
+ assert_equals(document.title, "PASS2");
+})
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.title-02.xhtml b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.title-02.xhtml
new file mode 100644
index 00000000000..6c75a58369b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.title-02.xhtml
@@ -0,0 +1,38 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>document.title with head blown away</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com"/>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#document.title"/>
+<link rel="stylesheet" href="/resources/testharness.css"/>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ assert_equals(document.title, "document.title with head blown away");
+})
+test(function() {
+ var head = document.getElementsByTagName("head")[0];
+ assert_true(!!head, "Head gone?!")
+ head.parentNode.removeChild(head);
+ assert_false(!!document.getElementsByTagName("head")[0], "Head still there?!")
+ document.title = "FAIL";
+ assert_equals(document.title, "");
+})
+test(function() {
+ var title2 = document.createElement("title");
+ title2.appendChild(document.createTextNode("PASS"));
+ document.body.appendChild(title2);
+ assert_equals(document.title, "PASS");
+})
+test(function() {
+ var title3 = document.createElement("title");
+ title3.appendChild(document.createTextNode("PASS2"));
+ document.documentElement.insertBefore(title3, document.body);
+ assert_equals(document.title, "PASS2");
+})
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.title-03.html b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.title-03.html
new file mode 100644
index 00000000000..487d5867b18
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.title-03.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<title> document.title and space normalization </title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#document.title">
+<link rel="stylesheet" href="/resources/testharness.css">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ // Single space characters must be normalized. (WHATWG r4353)
+ assert_equals(document.title, "document.title and space normalization");
+
+ document.title = "one space";
+ assert_equals(document.title, "one space");
+
+ document.title = "two spaces";
+ assert_equals(document.title, "two spaces");
+
+ document.title = "one\ttab";
+ assert_equals(document.title, "one tab");
+
+ document.title = "two\t\ttabs";
+ assert_equals(document.title, "two tabs");
+
+ document.title = "one\nnewline";
+ assert_equals(document.title, "one newline");
+
+ document.title = "two\n\nnewlines";
+ assert_equals(document.title, "two newlines");
+
+ document.title = "one\fform feed";
+ assert_equals(document.title, "one form feed");
+
+ document.title = "two\f\fform feeds";
+ assert_equals(document.title, "two form feeds");
+
+ document.title = "one\rcarriage return";
+ assert_equals(document.title, "one carriage return");
+
+ document.title = "two\r\rcarriage returns";
+ assert_equals(document.title, "two carriage returns");
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.title-04.xhtml b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.title-04.xhtml
new file mode 100644
index 00000000000..c089ea041d0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.title-04.xhtml
@@ -0,0 +1,49 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title> document.title and space normalization </title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com"/>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#document.title"/>
+<link rel="stylesheet" href="/resources/testharness.css"/>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ // Single space characters must be normalized. (WHATWG r4353)
+ assert_equals(document.title, "document.title and space normalization");
+
+ document.title = "one space";
+ assert_equals(document.title, "one space");
+
+ document.title = "two spaces";
+ assert_equals(document.title, "two spaces");
+
+ document.title = "one\ttab";
+ assert_equals(document.title, "one tab");
+
+ document.title = "two\t\ttabs";
+ assert_equals(document.title, "two tabs");
+
+ document.title = "one\nnewline";
+ assert_equals(document.title, "one newline");
+
+ document.title = "two\n\nnewlines";
+ assert_equals(document.title, "two newlines");
+
+ document.title = "one\fform feed";
+ assert_equals(document.title, "one form feed");
+
+ document.title = "two\f\fform feeds";
+ assert_equals(document.title, "two form feeds");
+
+ document.title = "one\rcarriage return";
+ assert_equals(document.title, "one carriage return");
+
+ document.title = "two\r\rcarriage returns";
+ assert_equals(document.title, "two carriage returns");
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.title-05.html b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.title-05.html
new file mode 100644
index 00000000000..df6ffc30f88
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.title-05.html
@@ -0,0 +1,42 @@
+<!doctype html>
+<title>document.title and White_Space characters</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#document.title">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var White_Space = [
+ "\u000B",
+ "\u0085",
+ "\u00A0",
+ "\u1680",
+ "\u180E",
+ "\u2000",
+ "\u2001",
+ "\u2002",
+ "\u2003",
+ "\u2004",
+ "\u2005",
+ "\u2006",
+ "\u2007",
+ "\u2008",
+ "\u2009",
+ "\u200A",
+ "\u2028",
+ "\u2029",
+ "\u202F",
+ "\u205F",
+ "\u3000"
+];
+
+White_Space.forEach(function(character, i) {
+ test(function() {
+ var s = character + "a" + character + character + "b" + character + "c" +
+ String(i) + character;
+ document.title = s;
+ assert_equals(document.title, s);
+ }, "Removing whitespace in document.title: U+" +
+ character.charCodeAt(0).toString(16));
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.title-06.html b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.title-06.html
new file mode 100644
index 00000000000..a80723f238c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.title-06.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<title>document.title and the empty string</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#document.title">
+<meta name="assert" content="On setting document.title to the empty string, no text node must be created.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ var head = document.documentElement.firstChild;
+ head.removeChild(head.firstChild);
+ assert_equals(document.title, "");
+ document.title = "";
+ assert_equals(document.title, "");
+ assert_true(head.lastChild instanceof HTMLTitleElement, "Need a title element.");
+ assert_equals(head.lastChild.firstChild, null);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.title-07.html b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.title-07.html
new file mode 100644
index 00000000000..9723d3f8115
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.title-07.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<title>Document.title and DOMImplementation.createHTMLDocument</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/dom/nodes/DOMImplementation-createHTMLDocument.js"></script>
+<div id="log"></div>
+<script>
+createHTMLDocuments(function(doc, expectedtitle, normalizedtitle) {
+ assert_equals(doc.title, normalizedtitle)
+})
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.title-08.html b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.title-08.html
new file mode 100644
index 00000000000..a643b75f4e9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/document.title-08.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#document.title">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ assert_equals(document.title, "");
+}, "No title element");
+
+test(function() {
+ var title = document.createElement("title");
+ title.appendChild(document.createTextNode("PASS"));
+ document.head.appendChild(title);
+ assert_equals(document.title, "PASS");
+
+ title.appendChild(document.createTextNode("PASS2"));
+ title.appendChild(document.createTextNode("PASS3"));
+ assert_equals(document.title, "PASSPASS2PASS3");
+}, "title element contains multiple child text nodes");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/nameditem-01.html b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/nameditem-01.html
new file mode 100644
index 00000000000..2b428aa65bd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/nameditem-01.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Named items: img id &amp; name</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-document-nameditem">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<div id="test">
+<img id="a" name="b">
+</div>
+<script>
+test(function() {
+ assert_equals(document.a, document.getElementsByTagName("img")[0]);
+ assert_equals(document['a'], document.getElementsByTagName("img")[0]);
+ assert_equals(document.b, document.getElementsByTagName("img")[0]);
+ assert_equals(document['b'], document.getElementsByTagName("img")[0]);
+}, "img elements that have a name and id attribute, should be accessible by both values.");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/nameditem-02.html b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/nameditem-02.html
new file mode 100644
index 00000000000..8c3155e7e4c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/nameditem-02.html
@@ -0,0 +1,99 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Named items: iframes</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-document-nameditem">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<div id="test">
+<iframe name="test1"></iframe>
+
+<iframe name="test2"></iframe>
+<iframe name="test2"></iframe>
+
+<iframe name="test3"></iframe>
+<img name="test3">
+
+<img name="test4">
+<iframe name="test4"></iframe>
+
+<iframe id="test5"></iframe>
+
+<iframe name="test6" id="fail"></iframe>
+
+<iframe name="fail" id="test7"></iframe>
+
+<iframe name="42"></iframe>
+</div>
+<script>
+test(function() {
+ var iframe = document.getElementsByTagName("iframe")[0];
+ assert_equals(iframe.name, "test1");
+
+ assert_true("test1" in document, '"test1" in document should be true');
+ assert_equals(document.test1, iframe.contentWindow);
+}, "If the only named item is an iframe, the contentWindow should be returned.");
+
+test(function() {
+ var iframe1 = document.getElementsByTagName("iframe")[1];
+ assert_equals(iframe1.name, "test2");
+ var iframe2 = document.getElementsByTagName("iframe")[2];
+ assert_equals(iframe2.name, "test2");
+
+ assert_true("test2" in document, '"test2" in document should be true');
+ var collection = document.test2;
+ assert_class_string(collection, "HTMLCollection", "collection should be an HTMLCollection");
+ assert_array_equals(collection, [iframe1, iframe2]);
+}, "If there are two iframes, a collection should be returned.");
+
+test(function() {
+ var iframe = document.getElementsByTagName("iframe")[3];
+ assert_equals(iframe.name, "test3");
+ var img = document.getElementsByTagName("img")[0];
+ assert_equals(img.name, "test3");
+
+ assert_true("test3" in document, '"test3" in document should be true');
+ var collection = document.test3;
+ assert_class_string(collection, "HTMLCollection", "collection should be an HTMLCollection");
+ assert_array_equals(collection, [iframe, img]);
+}, "If there are an iframe and another element (iframe first), a collection should be returned.");
+
+test(function() {
+ var iframe = document.getElementsByTagName("iframe")[4];
+ assert_equals(iframe.name, "test4");
+ var img = document.getElementsByTagName("img")[1];
+ assert_equals(img.name, "test4");
+
+ assert_true("test4" in document, '"test4" in document should be true');
+ var collection = document.test4;
+ assert_class_string(collection, "HTMLCollection", "collection should be an HTMLCollection");
+ assert_array_equals(collection, [img, iframe]);
+}, "If there are an iframe and another element (iframe last), a collection should be returned.");
+
+test(function() {
+ assert_false("test5" in document, '"test5" in document should be false');
+ assert_equals(document.test5, undefined);
+}, "If an iframe has an id and no name, it should not be returned.");
+
+test(function() {
+ var iframe = document.getElementsByTagName("iframe")[6];
+ assert_equals(iframe.name, "test6");
+
+ assert_true("test6" in document, '"test6" in document should be true');
+ assert_equals(document.test6, iframe.contentWindow);
+}, "If an iframe has a name and a different id, it should be returned by its name.");
+
+test(function() {
+ assert_false("test7" in document, '"test7" in document should be false');
+ assert_equals(document.test7, undefined);
+}, "If an iframe has an id and a different name, it should not be returned by its id.");
+
+test(function() {
+ var iframe = document.getElementsByTagName("iframe")[8];
+ assert_equals(iframe.name, "42");
+
+ assert_true(42 in document, '42 in document should be true');
+ assert_equals(document[42], iframe.contentWindow);
+}, "An iframe whose name looks like an array index should work.");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/nameditem-03.html b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/nameditem-03.html
new file mode 100644
index 00000000000..4c330b6a367
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/nameditem-03.html
@@ -0,0 +1,110 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Named items: applets</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-document-nameditem">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<div id="test">
+<applet name=test1></applet>
+
+<applet name=test2></applet>
+<applet name=test2></applet>
+
+<applet id=test3></applet>
+
+<applet id=test4></applet>
+<applet id=test4></applet>
+
+<applet name=test5></applet>
+<applet id=test5></applet>
+
+<applet id=test6></applet>
+<applet name=test6></applet>
+
+<applet id=test7 name=fail></applet>
+
+<applet name=test8 id=fail></applet>
+</div>
+<script>
+test(function() {
+ var applet = document.getElementsByTagName("applet")[0];
+ assert_equals(applet.name, "test1");
+
+ assert_true("test1" in document, '"test1" in document should be true');
+ assert_equals(document.test1, applet);
+}, "If there is one applet, it should be returned (name)");
+
+test(function() {
+ var applet1 = document.getElementsByTagName("applet")[1];
+ assert_equals(applet1.name, "test2");
+ var applet2 = document.getElementsByTagName("applet")[2];
+ assert_equals(applet2.name, "test2");
+
+ assert_true("test2" in document, '"test2" in document should be true');
+ var collection = document.test2;
+ assert_class_string(collection, "HTMLCollection", "collection should be an HTMLCollection");
+ assert_array_equals(collection, [applet1, applet2]);
+}, "If there are two applets, a collection should be returned. (name)");
+
+test(function() {
+ var applet = document.getElementsByTagName("applet")[3];
+ assert_equals(applet.id, "test3");
+
+ assert_true("test3" in document, '"test3" in document should be true');
+ assert_equals(document.test3, applet);
+}, "If there is one applet, it should be returned (id)");
+
+test(function() {
+ var applet1 = document.getElementsByTagName("applet")[4];
+ assert_equals(applet1.id, "test4");
+ var applet2 = document.getElementsByTagName("applet")[5];
+ assert_equals(applet2.id, "test4");
+
+ assert_true("test4" in document, '"test4" in document should be true');
+ var collection = document.test4;
+ assert_class_string(collection, "HTMLCollection", "collection should be an HTMLCollection");
+ assert_array_equals(collection, [applet1, applet2]);
+}, "If there are two applets, a collection should be returned. (id)");
+
+test(function() {
+ var applet1 = document.getElementsByTagName("applet")[6];
+ assert_equals(applet1.name, "test5");
+ var applet2 = document.getElementsByTagName("applet")[7];
+ assert_equals(applet2.id, "test5");
+
+ assert_true("test5" in document, '"test5" in document should be true');
+ var collection = document.test5;
+ assert_class_string(collection, "HTMLCollection", "collection should be an HTMLCollection");
+ assert_array_equals(collection, [applet1, applet2]);
+}, "If there are two applets, a collection should be returned. (name and id)");
+
+test(function() {
+ var applet1 = document.getElementsByTagName("applet")[8];
+ assert_equals(applet1.id, "test6");
+ var applet2 = document.getElementsByTagName("applet")[9];
+ assert_equals(applet2.name, "test6");
+
+ assert_true("test6" in document, '"test6" in document should be true');
+ var collection = document.test6;
+ assert_class_string(collection, "HTMLCollection", "collection should be an HTMLCollection");
+ assert_array_equals(collection, [applet1, applet2]);
+}, "If there are two applets, a collection should be returned. (id and name)");
+
+test(function() {
+ var applet = document.getElementsByTagName("applet")[10];
+ assert_equals(applet.id, "test7");
+
+ assert_true("test7" in document, '"test7" in document should be true');
+ assert_equals(document.test7, applet);
+}, "A name shouldn't affect getting an applet by id");
+
+test(function() {
+ var applet = document.getElementsByTagName("applet")[11];
+ assert_equals(applet.name, "test8");
+
+ assert_true("test8" in document, '"test8" in document should be true');
+ assert_equals(document.test8, applet);
+}, "An id shouldn't affect getting an applet by name");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/nameditem-04.html b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/nameditem-04.html
new file mode 100644
index 00000000000..b7c3ef8e9bb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/nameditem-04.html
@@ -0,0 +1,104 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Named items: forms</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-document-nameditem">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<div id="test">
+<form name=test1></form>
+
+<form name=test2></form>
+<form name=test2></form>
+
+<form id=test3></form>
+
+<form id=test4></form>
+<form id=test4></form>
+
+<form name=test5></form>
+<form id=test5></form>
+
+<form id=test6></form>
+<form name=test6></form>
+
+<form id=test7 name=fail></form>
+
+<form name=test8 id=fail></form>
+</div>
+<script>
+test(function() {
+ var form = document.getElementsByTagName("form")[0];
+ assert_equals(form.name, "test1");
+
+ assert_true("test1" in document, '"test1" in document should be true');
+ assert_equals(document.test1, form);
+}, "If there is one form, it should be returned (name)");
+
+test(function() {
+ var form1 = document.getElementsByTagName("form")[1];
+ assert_equals(form1.name, "test2");
+ var form2 = document.getElementsByTagName("form")[2];
+ assert_equals(form2.name, "test2");
+
+ assert_true("test2" in document, '"test2" in document should be true');
+ var collection = document.test2;
+ assert_class_string(collection, "HTMLCollection", "collection should be an HTMLCollection");
+ assert_array_equals(collection, [form1, form2]);
+}, "If there are two forms, a collection should be returned. (name)");
+
+test(function() {
+ var form = document.getElementsByTagName("form")[3];
+ assert_equals(form.id, "test3");
+
+ assert_false("test3" in document, '"test3" in document should be false');
+ assert_equals(document.test3, undefined);
+}, "If there is one form, it should not be returned (id)");
+
+test(function() {
+ var form1 = document.getElementsByTagName("form")[4];
+ assert_equals(form1.id, "test4");
+ var form2 = document.getElementsByTagName("form")[5];
+ assert_equals(form2.id, "test4");
+
+ assert_false("test4" in document, '"test4" in document should be false');
+ assert_equals(document.test4, undefined);
+}, "If there are two forms, nothing should be returned. (id)");
+
+test(function() {
+ var form1 = document.getElementsByTagName("form")[6];
+ assert_equals(form1.name, "test5");
+ var form2 = document.getElementsByTagName("form")[7];
+ assert_equals(form2.id, "test5");
+
+ assert_true("test5" in document, '"test5" in document should be true');
+ assert_equals(document.test5, form1);
+}, "If there are two forms, a collection should be returned. (name and id)");
+
+test(function() {
+ var form1 = document.getElementsByTagName("form")[8];
+ assert_equals(form1.id, "test6");
+ var form2 = document.getElementsByTagName("form")[9];
+ assert_equals(form2.name, "test6");
+
+ assert_true("test6" in document, '"test6" in document should be true');
+ assert_equals(document.test6, form2);
+}, "If there are two forms, a collection should be returned. (id and name)");
+
+test(function() {
+ var form = document.getElementsByTagName("form")[10];
+ assert_equals(form.id, "test7");
+
+ assert_false("test7" in document, '"test7" in document should be false');
+ assert_equals(document.test7, undefined);
+}, "A name shouldn't affect getting an form by id");
+
+test(function() {
+ var form = document.getElementsByTagName("form")[11];
+ assert_equals(form.name, "test8");
+
+ assert_true("test8" in document, '"test8" in document should be true');
+ assert_equals(document.test8, form);
+}, "An id shouldn't affect getting an form by name");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/nameditem-05.html b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/nameditem-05.html
new file mode 100644
index 00000000000..843ce357962
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/nameditem-05.html
@@ -0,0 +1,104 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Named items: embeds</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-document-nameditem">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<div id="test">
+<embed name=test1></embed>
+
+<embed name=test2></embed>
+<embed name=test2></embed>
+
+<embed id=test3></embed>
+
+<embed id=test4></embed>
+<embed id=test4></embed>
+
+<embed name=test5></embed>
+<embed id=test5></embed>
+
+<embed id=test6></embed>
+<embed name=test6></embed>
+
+<embed id=test7 name=fail></embed>
+
+<embed name=test8 id=fail></embed>
+</div>
+<script>
+test(function() {
+ var embed = document.getElementsByTagName("embed")[0];
+ assert_equals(embed.name, "test1");
+
+ assert_true("test1" in document, '"test1" in document should be true');
+ assert_equals(document.test1, embed);
+}, "If there is one embed, it should be returned (name)");
+
+test(function() {
+ var embed1 = document.getElementsByTagName("embed")[1];
+ assert_equals(embed1.name, "test2");
+ var embed2 = document.getElementsByTagName("embed")[2];
+ assert_equals(embed2.name, "test2");
+
+ assert_true("test2" in document, '"test2" in document should be true');
+ var collection = document.test2;
+ assert_class_string(collection, "HTMLCollection", "collection should be an HTMLCollection");
+ assert_array_equals(collection, [embed1, embed2]);
+}, "If there are two embeds, a collection should be returned. (name)");
+
+test(function() {
+ var embed = document.getElementsByTagName("embed")[3];
+ assert_equals(embed.id, "test3");
+
+ assert_false("test3" in document, '"test3" in document should be false');
+ assert_equals(document.test3, undefined);
+}, "If there is one embed, it should not be returned (id)");
+
+test(function() {
+ var embed1 = document.getElementsByTagName("embed")[4];
+ assert_equals(embed1.id, "test4");
+ var embed2 = document.getElementsByTagName("embed")[5];
+ assert_equals(embed2.id, "test4");
+
+ assert_false("test4" in document, '"test4" in document should be false');
+ assert_equals(document.test4, undefined);
+}, "If there are two embeds, nothing should be returned. (id)");
+
+test(function() {
+ var embed1 = document.getElementsByTagName("embed")[6];
+ assert_equals(embed1.name, "test5");
+ var embed2 = document.getElementsByTagName("embed")[7];
+ assert_equals(embed2.id, "test5");
+
+ assert_true("test5" in document, '"test5" in document should be true');
+ assert_equals(document.test5, embed1);
+}, "If there are two embeds, a collection should be returned. (name and id)");
+
+test(function() {
+ var embed1 = document.getElementsByTagName("embed")[8];
+ assert_equals(embed1.id, "test6");
+ var embed2 = document.getElementsByTagName("embed")[9];
+ assert_equals(embed2.name, "test6");
+
+ assert_true("test6" in document, '"test6" in document should be true');
+ assert_equals(document.test6, embed2);
+}, "If there are two embeds, a collection should be returned. (id and name)");
+
+test(function() {
+ var embed = document.getElementsByTagName("embed")[10];
+ assert_equals(embed.id, "test7");
+
+ assert_false("test7" in document, '"test7" in document should be false');
+ assert_equals(document.test7, undefined);
+}, "A name shouldn't affect getting an embed by id");
+
+test(function() {
+ var embed = document.getElementsByTagName("embed")[11];
+ assert_equals(embed.name, "test8");
+
+ assert_true("test8" in document, '"test8" in document should be true');
+ assert_equals(document.test8, embed);
+}, "An id shouldn't affect getting an embed by name");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/nameditem-06.html b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/nameditem-06.html
new file mode 100644
index 00000000000..1ff039915e1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/documents/dom-tree-accessors/nameditem-06.html
@@ -0,0 +1,106 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Named items: imgs</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-document-nameditem">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<div id="test">
+<img name=test1>
+
+<img name=test2>
+<img name=test2>
+
+<img id=test3>
+
+<img id=test4>
+<img id=test4>
+
+<img name=test5>
+<img id=test5>
+
+<img id=test6>
+<img name=test6>
+
+<img id=test7 name=fail>
+
+<img name=test8 id=fail>
+</div>
+<script>
+test(function() {
+ var img = document.getElementsByTagName("img")[0];
+ assert_equals(img.name, "test1");
+
+ assert_true("test1" in document, '"test1" in document should be true');
+ assert_equals(document.test1, img);
+}, "If there is one img, it should be returned (name)");
+
+test(function() {
+ var img1 = document.getElementsByTagName("img")[1];
+ assert_equals(img1.name, "test2");
+ var img2 = document.getElementsByTagName("img")[2];
+ assert_equals(img2.name, "test2");
+
+ assert_true("test2" in document, '"test2" in document should be true');
+ var collection = document.test2;
+ assert_class_string(collection, "HTMLCollection", "collection should be an HTMLCollection");
+ assert_array_equals(collection, [img1, img2]);
+}, "If there are two imgs, a collection should be returned. (name)");
+
+test(function() {
+ var img = document.getElementsByTagName("img")[3];
+ assert_equals(img.id, "test3");
+
+ assert_false("test3" in document, '"test3" in document should be false');
+ assert_equals(document.test3, undefined);
+}, "If there is one img, it should not be returned (id)");
+
+test(function() {
+ var img1 = document.getElementsByTagName("img")[4];
+ assert_equals(img1.id, "test4");
+ var img2 = document.getElementsByTagName("img")[5];
+ assert_equals(img2.id, "test4");
+
+ assert_false("test4" in document, '"test4" in document should be false');
+ var collection = document.test4;
+ assert_class_string(collection, "HTMLCollection", "collection should be an HTMLCollection");
+ assert_array_equals(collection, [img1, img2]);
+}, "If there are two imgs, nothing should be returned. (id)");
+
+test(function() {
+ var img1 = document.getElementsByTagName("img")[6];
+ assert_equals(img1.name, "test5");
+ var img2 = document.getElementsByTagName("img")[7];
+ assert_equals(img2.id, "test5");
+
+ assert_true("test5" in document, '"test5" in document should be true');
+ assert_equals(document.test5, img1);
+}, "If there are two imgs, the one with a name should be returned. (name and id)");
+
+test(function() {
+ var img1 = document.getElementsByTagName("img")[8];
+ assert_equals(img1.id, "test6");
+ var img2 = document.getElementsByTagName("img")[9];
+ assert_equals(img2.name, "test6");
+
+ assert_true("test6" in document, '"test6" in document should be true');
+ assert_equals(document.test6, img2);
+}, "If there are two imgs, the one with a name should be returned. (id and name)");
+
+test(function() {
+ var img = document.getElementsByTagName("img")[10];
+ assert_equals(img.id, "test7");
+
+ assert_true("test7" in document, '"test7" in document should be true');
+ assert_equals(document.test7, img);
+}, "A name should affect getting an img by id");
+
+test(function() {
+ var img = document.getElementsByTagName("img")[11];
+ assert_equals(img.name, "test8");
+
+ assert_true("test8" in document, '"test8" in document should be true');
+ assert_equals(document.test8, img);
+}, "An id shouldn't affect getting an img by name");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/documents/loading-xml-documents/.gitkeep b/tests/wpt/web-platform-tests/html/dom/documents/loading-xml-documents/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/documents/loading-xml-documents/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/dom/documents/resource-metadata-management/.gitkeep b/tests/wpt/web-platform-tests/html/dom/documents/resource-metadata-management/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/documents/resource-metadata-management/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/dom/documents/resource-metadata-management/document-compatmode-01.html b/tests/wpt/web-platform-tests/html/dom/documents/resource-metadata-management/document-compatmode-01.html
new file mode 100644
index 00000000000..218a3fe8438
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/documents/resource-metadata-management/document-compatmode-01.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<title>document.compatMode: Standards</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-document-compatmode">
+<body>
+<div id="log"></div>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+test(function() {
+ assert_equals(document.compatMode, "CSS1Compat");
+})
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/documents/resource-metadata-management/document-compatmode-02.html b/tests/wpt/web-platform-tests/html/dom/documents/resource-metadata-management/document-compatmode-02.html
new file mode 100644
index 00000000000..6da40d61eec
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/documents/resource-metadata-management/document-compatmode-02.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<title>document.compatMode: Almost standards</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-document-compatmode">
+<body>
+<div id="log"></div>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+test(function() {
+ assert_equals(document.compatMode, "CSS1Compat");
+})
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/documents/resource-metadata-management/document-compatmode-03.html b/tests/wpt/web-platform-tests/html/dom/documents/resource-metadata-management/document-compatmode-03.html
new file mode 100644
index 00000000000..3d55d6e835e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/documents/resource-metadata-management/document-compatmode-03.html
@@ -0,0 +1,12 @@
+<title>document.compatMode: Quirks</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-document-compatmode">
+<body>
+<div id="log"></div>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+test(function() {
+ assert_equals(document.compatMode, "BackCompat");
+})
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/documents/resource-metadata-management/document-compatmode-04.xhtml b/tests/wpt/web-platform-tests/html/dom/documents/resource-metadata-management/document-compatmode-04.xhtml
new file mode 100644
index 00000000000..a71c1d9dd36
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/documents/resource-metadata-management/document-compatmode-04.xhtml
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>document.compatMode: Standards</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com"/>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-document-compatmode"/>
+</head>
+<body>
+<div id="log"></div>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+test(function() {
+ assert_equals(document.compatMode, "CSS1Compat");
+})
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/documents/resource-metadata-management/document-compatmode-05.xhtml b/tests/wpt/web-platform-tests/html/dom/documents/resource-metadata-management/document-compatmode-05.xhtml
new file mode 100644
index 00000000000..3fde06e5af4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/documents/resource-metadata-management/document-compatmode-05.xhtml
@@ -0,0 +1,19 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>document.compatMode: Standards</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com"/>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-document-compatmode"/>
+</head>
+<body>
+<div id="log"></div>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+test(function() {
+ assert_equals(document.compatMode, "CSS1Compat");
+})
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/documents/resource-metadata-management/document-compatmode-06.xhtml b/tests/wpt/web-platform-tests/html/dom/documents/resource-metadata-management/document-compatmode-06.xhtml
new file mode 100644
index 00000000000..eb64dfb90ee
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/documents/resource-metadata-management/document-compatmode-06.xhtml
@@ -0,0 +1,17 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>document.compatMode: Standards</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com"/>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-document-compatmode"/>
+</head>
+<body>
+<div id="log"></div>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+test(function() {
+ assert_equals(document.compatMode, "CSS1Compat");
+})
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/documents/resource-metadata-management/document-cookie.html b/tests/wpt/web-platform-tests/html/dom/documents/resource-metadata-management/document-cookie.html
new file mode 100644
index 00000000000..802e2d5ad5e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/documents/resource-metadata-management/document-cookie.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>document.cookie</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#resource-metadata-management">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function(){
+ assert_equals(document.cookie, "");
+}, "document has no cookie");
+
+test(function(){
+ var doc = document.implementation.createHTMLDocument("doc");
+ assert_equals(doc.cookie, "");
+ doc.cookie = "test=foobar";
+ assert_equals(doc.cookie, "");
+}, "getting cookie for a cookie-averse document returns empty string, setting does nothing");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/documents/resource-metadata-management/document-lastModified-01.html b/tests/wpt/web-platform-tests/html/dom/documents/resource-metadata-management/document-lastModified-01.html
new file mode 100644
index 00000000000..a3d5990ea49
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/documents/resource-metadata-management/document-lastModified-01.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<title>document.lastModified should return current local time</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+ var d = new Date();
+ var last_modified = document.lastModified;
+ var initial_modified = Date.parse(last_modified) / 1000;
+ var expected = Math.round(d / 1000);
+
+ test(function() {
+ assert_approx_equals(initial_modified, expected, 2.5);
+ }, "Date returned by lastModified is current at page load");
+
+ var pattern = /[0-9]{2}\/[0-9]{2}\/[0-9]{4} ([0-9]{2}):([0-9]{2}):([0-9]{2})/
+
+ test(function() {
+ assert_regexp_match(last_modified, pattern,
+ "Format should match the pattern \"NN/NN/NNNN NN:NN:NN\".");
+ }, "Date returned by lastModified is in the form \"MM/DD/YYYY hh:mm:ss\".");
+
+
+ var hours = d.getHours()
+ var minutes = d.getMinutes()
+ var seconds = d.getSeconds()
+
+ test(function() {
+ var local_time = hours * 60 * 60 + minutes * 60 + seconds;
+ var m = pattern.exec(last_modified);
+ var last_modified_time = parseInt(m[1]) * 60 * 60 + parseInt(m[2]) * 60 + parseInt(m[3]);
+ assert_approx_equals(last_modified_time, local_time, 2,
+ "Hours and minutes should match local time.");
+ }, "Date returned by lastModified is in the user's local time zone.");
+
+ var t = async_test("Date returned by lastModified is current after timeout.");
+
+ setTimeout(function() {
+ t.step(function() {
+ var new_modified = Date.parse(document.lastModified) / 1000;
+ var new_expected = Math.round(new Date() / 1000);
+ assert_approx_equals(new_modified, new_expected, 2.5,
+ "(initial value was " + initial_modified + ")");
+ t.done();
+ });
+ }, 4000);
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/documents/resource-metadata-management/document-lastModified.html b/tests/wpt/web-platform-tests/html/dom/documents/resource-metadata-management/document-lastModified.html
new file mode 100644
index 00000000000..9e0a07d8ebf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/documents/resource-metadata-management/document-lastModified.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>document.lastModified</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#resource-metadata-management">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+ test(function(){
+ var date = new Date("Thu, 01 Jan 1970 01:23:45 GMT");
+ var result = ('0' + (date.getMonth()+1)).slice(-2) + '/' + ('0' + date.getDate()).slice(-2) + '/' + date.getFullYear() + " " + [date.getHours(),date.getMinutes(),date.getSeconds()].map(function(n){return ("0" + n).slice(-2);}).join(":");
+ assert_equals(document.lastModified, result);
+ }, "lastModified should return the last modified date and time");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/documents/resource-metadata-management/document-lastModified.html.headers b/tests/wpt/web-platform-tests/html/dom/documents/resource-metadata-management/document-lastModified.html.headers
new file mode 100644
index 00000000000..377e3b52dcb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/documents/resource-metadata-management/document-lastModified.html.headers
@@ -0,0 +1 @@
+Last-Modified: Thu, 01 Jan 1970 01:23:45 GMT
diff --git a/tests/wpt/web-platform-tests/html/dom/documents/resource-metadata-management/document-readyState.html b/tests/wpt/web-platform-tests/html/dom/documents/resource-metadata-management/document-readyState.html
new file mode 100644
index 00000000000..8c91e0a0019
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/documents/resource-metadata-management/document-readyState.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>document.readyState</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#resource-metadata-management">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+ var t1 = async_test("readyState equals 'complete' when the document has loaded"),
+ t2 = async_test("readyState equals 'interactive' when the document is finished parsing"),
+ t3 = async_test("readystatechange event is fired each time document.readyState changes");
+
+ window.onload = t1.step_func_done(function(){
+ assert_equals(document.readyState, "complete");
+ });
+
+ document.addEventListener("DOMContentLoaded", function(event) {
+ t2.step(function() {
+ assert_equals(document.readyState, "interactive")
+ });
+ t2.done();
+ });
+
+ var states = [document.readyState];
+ document.onreadystatechange = t3.step_func(function(){
+ states.push(document.readyState);
+ if (document.readyState === "complete") {
+ assert_array_equals(states, ["loading", "interactive", "complete"]);
+ t3.done();
+ }
+ })
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/documents/security-document/.gitkeep b/tests/wpt/web-platform-tests/html/dom/documents/security-document/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/documents/security-document/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/dom/documents/the-document-object/.gitkeep b/tests/wpt/web-platform-tests/html/dom/documents/the-document-object/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/documents/the-document-object/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/.gitkeep b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/closing-the-input-stream/.gitkeep b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/closing-the-input-stream/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/closing-the-input-stream/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/closing-the-input-stream/document.close-01.xhtml b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/closing-the-input-stream/document.close-01.xhtml
new file mode 100644
index 00000000000..cccc26bf17e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/closing-the-input-stream/document.close-01.xhtml
@@ -0,0 +1,19 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>document.close in XHTML</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com"/>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#closing-the-input-stream"/>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ assert_throws("INVALID_STATE_ERR", function() {
+ document.close();
+ }, "document.close in XHTML should throw an INVALID_STATE_ERR ");
+}, "document.close in XHTML");
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/.gitkeep b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/001.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/001.html
new file mode 100644
index 00000000000..3ac6423f4a8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/001.html
@@ -0,0 +1,12 @@
+<!doctype html>
+<title>document.write</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+test(
+function() {
+ document.write("PASS");
+ assert_equals(document.body.textContent, "PASS");
+}
+);
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/002.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/002.html
new file mode 100644
index 00000000000..08975bca7be
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/002.html
@@ -0,0 +1,13 @@
+<!doctype html>
+<title>document.write</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+test(
+function() {
+ document.write("<i>Filler Text");
+ assert_equals(document.body.firstChild.localName, "i");
+ assert_equals(document.body.firstChild.textContent, "Filler Text");
+}
+);
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/003.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/003.html
new file mode 100644
index 00000000000..915e1f6d610
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/003.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<title>document.write</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+test(
+function() {
+ document.write("<");
+ document.write("i>Filler Text");
+ assert_equals(document.body.firstChild.localName, "i");
+ assert_equals(document.body.firstChild.textContent, "Filler Text");
+}
+);
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/004.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/004.html
new file mode 100644
index 00000000000..dd017258603
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/004.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<title>document.write</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+test(
+function() {
+ document.write("<i");
+ document.write(">Filler Text");
+ assert_equals(document.body.firstChild.localName, "i");
+ assert_equals(document.body.firstChild.textContent, "Filler Text");
+}
+);
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/005.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/005.html
new file mode 100644
index 00000000000..4c161c4d47f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/005.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<title>document.write</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+test(
+function() {
+ document.write("<i>");
+ document.write("Filler Text");
+ assert_equals(document.body.firstChild.localName, "i");
+ assert_equals(document.body.firstChild.textContent, "Filler Text");
+}
+);
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/005.js b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/005.js
new file mode 100644
index 00000000000..ebfd7e25852
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/005.js
@@ -0,0 +1 @@
+order.push(3); \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/006.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/006.html
new file mode 100644
index 00000000000..92bfb44c3ac
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/006.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<title>document.write</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+test(
+function() {
+ document.write("<i id='test'>Filler Text");
+ assert_equals(document.body.firstChild.localName, "i");
+ assert_equals(document.body.firstChild.getAttribute("id"), "test");
+ assert_equals(document.body.firstChild.textContent, "Filler Text");
+}
+);
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/006.js b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/006.js
new file mode 100644
index 00000000000..ebfd7e25852
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/006.js
@@ -0,0 +1 @@
+order.push(3); \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/007.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/007.html
new file mode 100644
index 00000000000..753316b89ce
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/007.html
@@ -0,0 +1,15 @@
+<!doctype html>
+<title>document.write</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+test(
+function() {
+ document.write("<i ");
+ document.write("id='test'>Filler Text");
+ assert_equals(document.body.firstChild.localName, "i");
+ assert_equals(document.body.firstChild.getAttribute("id"), "test");
+ assert_equals(document.body.firstChild.textContent, "Filler Text");
+}
+);
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/007.js b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/007.js
new file mode 100644
index 00000000000..31fcf18d493
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/007.js
@@ -0,0 +1,4 @@
+t.step(function() {
+ order.push(2);
+ document.write("<script>t.step(function() {order.push(3)})</script>");
+ }); \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/008-1.js b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/008-1.js
new file mode 100644
index 00000000000..ef90c722b79
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/008-1.js
@@ -0,0 +1,3 @@
+t.step(function() {
+ order.push(3);
+ }); \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/008.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/008.html
new file mode 100644
index 00000000000..4818bc388f4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/008.html
@@ -0,0 +1,15 @@
+<!doctype html>
+<title>document.write</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+test(
+function() {
+ document.write("<i i");
+ document.write("d='test'>Filler Text");
+ assert_equals(document.body.firstChild.localName, "i");
+ assert_equals(document.body.firstChild.getAttribute("id"), "test");
+ assert_equals(document.body.firstChild.textContent, "Filler Text");
+}
+);
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/008.js b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/008.js
new file mode 100644
index 00000000000..367597515d7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/008.js
@@ -0,0 +1,4 @@
+t.step(function() {
+ order.push(2);
+ document.write("<script src=\"008-1.js\"></script>");
+ }); \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/009.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/009.html
new file mode 100644
index 00000000000..d7b78333b86
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/009.html
@@ -0,0 +1,15 @@
+<!doctype html>
+<title>document.write</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+test(
+function() {
+ document.write("<i id");
+ document.write("='test'>Filler Text");
+ assert_equals(document.body.firstChild.localName, "i");
+ assert_equals(document.body.firstChild.getAttribute("id"), "test");
+ assert_equals(document.body.firstChild.textContent, "Filler Text");
+}
+);
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/010-1.js b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/010-1.js
new file mode 100644
index 00000000000..fd815bab771
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/010-1.js
@@ -0,0 +1,4 @@
+t.step(function() {
+ order.push(4);
+ assert_equals(document.getElementsByTagName("meta").length, 1);
+ }); \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/010.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/010.html
new file mode 100644
index 00000000000..c8b99582589
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/010.html
@@ -0,0 +1,15 @@
+<!doctype html>
+<title>document.write</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+test(
+function() {
+ document.write("<i id=");
+ document.write("'test'>Filler Text");
+ assert_equals(document.body.firstChild.localName, "i");
+ assert_equals(document.body.firstChild.getAttribute("id"), "test");
+ assert_equals(document.body.firstChild.textContent, "Filler Text");
+}
+);
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/010.js b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/010.js
new file mode 100644
index 00000000000..bb328ad55af
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/010.js
@@ -0,0 +1,4 @@
+t.step(function() {
+ order.push(3);
+ assert_equals(document.getElementsByTagName("meta").length, 0);
+ });
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/011-1.js b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/011-1.js
new file mode 100644
index 00000000000..944b70d2d0b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/011-1.js
@@ -0,0 +1,5 @@
+t.step(function() {
+ order.push(4);
+ document.write("<meta>");
+ assert_equals(document.getElementsByTagName("meta").length, 1);
+ }); \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/011.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/011.html
new file mode 100644
index 00000000000..33464429e6f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/011.html
@@ -0,0 +1,15 @@
+<!doctype html>
+<title>document.write</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+test(
+function() {
+ document.write("<i id='");
+ document.write("test'>Filler Text");
+ assert_equals(document.body.firstChild.localName, "i");
+ assert_equals(document.body.firstChild.getAttribute("id"), "test");
+ assert_equals(document.body.firstChild.textContent, "Filler Text");
+}
+);
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/011.js b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/011.js
new file mode 100644
index 00000000000..ce47bcd283f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/011.js
@@ -0,0 +1,5 @@
+t.step(function() {
+ order.push(3);
+ document.write("<script src='011-1.js'></script" + "><meta>");
+ assert_equals(document.getElementsByTagName("meta").length, 0);
+ }); \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/012.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/012.html
new file mode 100644
index 00000000000..c9902a4875a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/012.html
@@ -0,0 +1,15 @@
+<!doctype html>
+<title>document.write</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+test(
+function() {
+ document.write("<i id='te");
+ document.write("st'>Filler Text");
+ assert_equals(document.body.firstChild.localName, "i");
+ assert_equals(document.body.firstChild.getAttribute("id"), "test");
+ assert_equals(document.body.firstChild.textContent, "Filler Text");
+}
+);
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/012.js b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/012.js
new file mode 100644
index 00000000000..7ab4c6b386f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/012.js
@@ -0,0 +1,5 @@
+t.step(
+function() {
+ order.push(5);
+ assert_equals(document.getElementsByTagName("meta").length, 0);
+}); \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/013.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/013.html
new file mode 100644
index 00000000000..7b87d289769
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/013.html
@@ -0,0 +1,15 @@
+<!doctype html>
+<title>document.write</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+test(
+function() {
+ document.write("<i id='test");
+ document.write("'>Filler Text");
+ assert_equals(document.body.firstChild.localName, "i");
+ assert_equals(document.body.firstChild.getAttribute("id"), "test");
+ assert_equals(document.body.firstChild.textContent, "Filler Text");
+}
+);
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/013.js b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/013.js
new file mode 100644
index 00000000000..b5ce5f27da0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/013.js
@@ -0,0 +1 @@
+document.write('<svg><![CDATA['); \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/014.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/014.html
new file mode 100644
index 00000000000..75518a89810
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/014.html
@@ -0,0 +1,15 @@
+<!doctype html>
+<title>document.write</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+test(
+function() {
+ document.write("<i id='test'");
+ document.write(">Filler Text");
+ assert_equals(document.body.firstChild.localName, "i");
+ assert_equals(document.body.firstChild.getAttribute("id"), "test");
+ assert_equals(document.body.firstChild.textContent, "Filler Text");
+}
+);
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/015.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/015.html
new file mode 100644
index 00000000000..3dd79a63efa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/015.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<title>document.write</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+test(
+function() {
+ document.write("<i id='test'");
+ document.write("class='a'>Filler Text");
+ assert_equals(document.body.firstChild.localName, "i");
+ assert_equals(document.body.firstChild.getAttribute("id"), "test");
+ assert_equals(document.body.firstChild.getAttribute("class"), "a");
+ assert_equals(document.body.firstChild.textContent, "Filler Text");
+}
+);
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/016.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/016.html
new file mode 100644
index 00000000000..4c2f58912ab
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/016.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<title>document.write</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+test(
+function() {
+ document.write("<i>Filler Text");
+ document.write("</i><b>Filler Text");
+ assert_equals(document.body.firstChild.localName, "i");
+ assert_equals(document.body.firstChild.textContent, "Filler Text");
+ assert_equals(document.body.childNodes[1].localName, "b");
+ assert_equals(document.body.childNodes[1].textContent, "Filler Text");
+}
+);
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/017.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/017.html
new file mode 100644
index 00000000000..8d1b24b06ee
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/017.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<title>document.write</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+test(
+function() {
+ var s = "<i id=test>Filler Text</i><b>Filler Text"
+ for (var i=0; i<s.length; i++) {
+ document.write(s[i]);
+ }
+ assert_equals(document.body.firstChild.localName, "i");
+ assert_equals(document.body.firstChild.getAttribute('id'), "test");
+ assert_equals(document.body.firstChild.textContent, "Filler Text");
+ assert_equals(document.body.childNodes[1].localName, "b");
+ assert_equals(document.body.childNodes[1].textContent, "Filler Text");
+}
+);
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/018.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/018.html
new file mode 100644
index 00000000000..cf8dddbc548
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/018.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<title>document.write</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+test(
+function() {
+ document.write("<body>");
+ var s = "<!--comment--><i>Filler Text</i>"
+ for (var i=0; i<s.length; i++) {
+ document.write(s[i]);
+ }
+ assert_equals(document.body.firstChild.nodeType, document.COMMENT_NODE);
+ assert_equals(document.body.firstChild.data, "comment");
+ assert_equals(document.body.childNodes[1].localName, "i");
+ assert_equals(document.body.childNodes[1].textContent, "Filler Text");
+}
+);
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/019.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/019.html
new file mode 100644
index 00000000000..5e988f79efa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/019.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<title>document.write</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+var t = async_test();
+t.step(function() {
+ document.write("<i");
+});
+</script>
+>Filler Text</i>
+<script>
+t.step(function() {
+ assert_equals(document.body.childNodes[0].localName, "i");
+ assert_equals(document.body.childNodes[0].textContent, "Filler Text");
+}
+);
+t.done();
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/020.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/020.html
new file mode 100644
index 00000000000..1d31bbf35d4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/020.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<title>document.write</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+var t = async_test();
+t.step(function() {
+ document.write("<body><");
+});
+</script>!--comment-->
+<script>
+t.step(function() {
+ assert_equals(document.body.childNodes[0].nodeType, document.COMMENT_NODE);
+ assert_equals(document.body.childNodes[0].data, "comment");
+}
+);
+t.done();
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/021.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/021.html
new file mode 100644
index 00000000000..500bb193980
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/021.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<title>document.write</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+var t = async_test();
+t.step(function() {
+ document.write("<body><sp");
+});
+</script>an>Filler Text</span>
+<script>
+t.step(function() {
+ assert_equals(document.body.childNodes[0].localName, "span");
+ assert_equals(document.body.childNodes[0].textContent, "Filler Text");
+}
+);
+t.done();
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/022.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/022.html
new file mode 100644
index 00000000000..53ba299012c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/022.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<title>document.write</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+var t = async_test();
+t.step(function() {
+ document.write("<body><span>");
+});
+</script>Filler Text</span>
+<script>
+t.step(function() {
+ assert_equals(document.body.childNodes[0].localName, "span");
+ assert_equals(document.body.childNodes[0].textContent, "Filler Text");
+}
+);
+t.done();
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/023.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/023.html
new file mode 100644
index 00000000000..ca89e0e0bcd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/023.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<title>document.write</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+var t = async_test();
+t.step(function() {
+ document.write("<body><span ");
+});
+</script>id=a>Filler Text</span>
+<script>
+t.step(function() {
+ assert_equals(document.body.childNodes[0].localName, "span");
+ assert_equals(document.body.childNodes[0].getAttribute("id"), "a");
+ assert_equals(document.body.childNodes[0].textContent, "Filler Text");
+}
+);
+t.done();
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/024.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/024.html
new file mode 100644
index 00000000000..2a47d76cb38
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/024.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<title>document.write</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+var t = async_test();
+t.step(function() {
+ document.write("<body><span i");
+});
+</script>d=a>Filler Text</span>
+<script>
+t.step(function() {
+ assert_equals(document.body.childNodes[0].localName, "span");
+ assert_equals(document.body.childNodes[0].getAttribute("id"), "a");
+ assert_equals(document.body.childNodes[0].textContent, "Filler Text");
+}
+);
+t.done();
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/025.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/025.html
new file mode 100644
index 00000000000..31c68cf7df2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/025.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<title>document.write</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+var t = async_test();
+t.step(function() {
+ document.write("<body><span id");
+});
+</script>=a>Filler Text</span>
+<script>
+t.step(function() {
+ assert_equals(document.body.childNodes[0].localName, "span");
+ assert_equals(document.body.childNodes[0].getAttribute("id"), "a");
+ assert_equals(document.body.childNodes[0].textContent, "Filler Text");
+}
+);
+t.done();
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/026.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/026.html
new file mode 100644
index 00000000000..a9bce7743e9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/026.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<title>document.write</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+var t = async_test();
+t.step(function() {
+ document.write("<body><span id=");
+});
+</script>a>Filler Text</span>
+<script>
+t.step(function() {
+ assert_equals(document.body.childNodes[0].localName, "span");
+ assert_equals(document.body.childNodes[0].getAttribute("id"), "a");
+ assert_equals(document.body.childNodes[0].textContent, "Filler Text");
+}
+);
+t.done();
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/027.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/027.html
new file mode 100644
index 00000000000..dcfd67c0f75
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/027.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<title>document.write</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+var t = async_test();
+t.step(function() {
+ document.write("<body><span id=a");
+});
+</script>>Filler Text</span>
+<script>
+t.step(function() {
+ assert_equals(document.body.childNodes[0].localName, "span");
+ assert_equals(document.body.childNodes[0].getAttribute("id"), "a");
+ assert_equals(document.body.childNodes[0].textContent, "Filler Text");
+}
+);
+t.done();
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/028.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/028.html
new file mode 100644
index 00000000000..f5b7e9ef2b8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/028.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<title>document.write</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+var t = async_test();
+t.step(function() {
+ document.write("<body><span id=a>Filler Text<");
+});
+</script>/span><b>Filler Text</b></span>
+<script>
+t.step(function() {
+ assert_equals(document.body.childNodes[0].localName, "span");
+ assert_equals(document.body.childNodes[0].getAttribute("id"), "a");
+ assert_equals(document.body.childNodes[0].textContent, "Filler Text");
+ assert_equals(document.body.childNodes[1].localName, "b");
+ assert_equals(document.body.childNodes[1].textContent, "Filler Text");
+}
+);
+t.done();
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/029.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/029.html
new file mode 100644
index 00000000000..f005a72227a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/029.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<title>document.write</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+var t = async_test();
+t.step(function() {
+ document.write("<body><span id=a>Filler Text</");
+});
+</script>span><b>Filler Text</b></span>
+<script>
+t.step(function() {
+ assert_equals(document.body.childNodes[0].localName, "span");
+ assert_equals(document.body.childNodes[0].getAttribute("id"), "a");
+ assert_equals(document.body.childNodes[0].textContent, "Filler Text");
+ assert_equals(document.body.childNodes[1].localName, "b");
+ assert_equals(document.body.childNodes[1].textContent, "Filler Text");
+}
+);
+t.done();
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/030.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/030.html
new file mode 100644
index 00000000000..cc361d3aaff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/030.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<title>document.write</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+var t = async_test();
+t.step(function() {
+ document.write("<body><span id=a>Filler Text</sp");
+});
+</script>an><b>Filler Text</b></span>
+<script>
+t.step(function() {
+ assert_equals(document.body.childNodes[0].localName, "span");
+ assert_equals(document.body.childNodes[0].getAttribute("id"), "a");
+ assert_equals(document.body.childNodes[0].textContent, "Filler Text");
+ assert_equals(document.body.childNodes[1].localName, "b");
+ assert_equals(document.body.childNodes[1].textContent, "Filler Text");
+}
+);
+t.done();
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/031.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/031.html
new file mode 100644
index 00000000000..32c97c5056f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/031.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<title>document.write</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+var t = async_test();
+t.step(function() {
+ document.write("<body><span id=a>Filler Text</span");
+});
+</script>><b>Filler Text</b></span>
+<script>
+t.step(function() {
+ assert_equals(document.body.childNodes[0].localName, "span");
+ assert_equals(document.body.childNodes[0].getAttribute("id"), "a");
+ assert_equals(document.body.childNodes[0].textContent, "Filler Text");
+ assert_equals(document.body.childNodes[1].localName, "b");
+ assert_equals(document.body.childNodes[1].textContent, "Filler Text");
+}
+);
+t.done();
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/032.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/032.html
new file mode 100644
index 00000000000..1a33408f1b5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/032.html
@@ -0,0 +1,22 @@
+<!doctype html>
+<title>document.write</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+var t = async_test();
+t.step(function() {
+ var tag_name_length = 100000;
+ var tag_name = "";
+ for (var i=0; i<tag_name_length; i++) {
+ tag_name += "a";
+ }
+ document.write("<body><" + tag_name + ">Filler Text</" + tag_name + ">");
+});
+</script>
+<script>
+t.step(function() {
+ assert_equals(document.body.childNodes[0].textContent, "Filler Text");
+}
+);
+t.done();
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/033.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/033.html
new file mode 100644
index 00000000000..1b8e1c27062
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/033.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<title>document.write</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+test(
+ function() {
+ document.writeln("<i");
+ var s = " b='a'>Filler"
+ for (var i=0; i<s.length; i++) {
+ document.write(s[i]+"\n");
+ }
+ document.writeln("</i");
+ document.writeln(">");
+ assert_equals(document.body.childNodes[0].localName, "i");
+ assert_equals(document.body.childNodes[0].getAttribute("b"), "\na\n");
+ assert_equals(document.body.childNodes[0].textContent, "\nF\ni\nl\nl\ne\nr\n");
+ }
+);
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/034.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/034.html
new file mode 100644
index 00000000000..abd481a64d9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/034.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<title>document.write</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+var t = async_test();
+t.step(function() {
+ var s = "<svg><![CDATA[Filler Text]]></svg>";
+ for (var i=0; i<s.length; i++) {
+ document.write(s[i]);
+ }
+});
+</script>
+<script>
+t.step(function() {
+ assert_equals(document.body.childNodes[0].localName, "svg");
+ assert_equals(document.body.childNodes[0].textContent, "Filler Text");
+}
+);
+t.done();
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/035.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/035.html
new file mode 100644
index 00000000000..a1e7f9ee671
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/035.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<title>document.write</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+var t = async_test();
+t.step(function() {
+ var s = "<svg><!";
+ for (var i=0; i<s.length; i++) {
+ document.write(s[i]);
+ }
+});
+</script>[CDATA[Filler Text]]></svg>
+<script>
+t.step(function() {
+ assert_equals(document.body.childNodes[0].localName, "svg");
+ assert_equals(document.body.childNodes[0].textContent, "Filler Text");
+}
+);
+t.done();
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/036.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/036.html
new file mode 100644
index 00000000000..8719e0598d9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/036.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<title>document.write</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+var t = async_test();
+t.step(function() {
+ var s = "<svg><![CDATA[Filler Text]";
+ for (var i=0; i<s.length; i++) {
+ document.write(s[i]);
+ }
+});
+</script>]></svg>
+<script>
+t.step(function() {
+ assert_equals(document.body.childNodes[0].localName, "svg");
+ assert_equals(document.body.childNodes[0].textContent, "Filler Text");
+}
+);
+t.done();
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/037.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/037.html
new file mode 100644
index 00000000000..cf0787ce761
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/037.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<title>document.write</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+var t = async_test();
+t.step(function() {
+ var s = "<body><!DOCTYPE html>";
+ for (var i=0; i<s.length; i++) {
+ document.write(s[i]);
+ }
+});
+</script><script>
+t.step(function() {
+ //Nothing should be inserted into the DOM for the doctype node so
+ //just checking nothing odd happens
+ assert_equals(document.body.childNodes[0].localName, "script");
+}
+);
+t.done();
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/038.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/038.html
new file mode 100644
index 00000000000..4ae9d32b232
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/038.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<title>document.write</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+var t = async_test();
+t.step(function() {
+ var s = "<body><";
+ for (var i=0; i<s.length; i++) {
+ document.write(s[i]);
+ }
+});
+</script>!DOCTYPE html><script>
+t.step(function() {
+ //Nothing should be inserted into the DOM for the doctype node so
+ //just checking nothing odd happens
+ assert_equals(document.body.childNodes[0].localName, "script");
+}
+);
+t.done();
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/039.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/039.html
new file mode 100644
index 00000000000..611a01390cd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/039.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<title>document.write</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+var t = async_test();
+t.step(function() {
+ var s = "<body><!";
+ for (var i=0; i<s.length; i++) {
+ document.write(s[i]);
+ }
+});
+</script>DOCTYPE html><script>
+t.step(function() {
+ //Nothing should be inserted into the DOM for the doctype node so
+ //just checking nothing odd happens
+ assert_equals(document.body.childNodes[0].localName, "script");
+}
+);
+t.done();
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/040.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/040.html
new file mode 100644
index 00000000000..d76deffa40f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/040.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>document.write entity</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+var t = test(function() {
+ document.write("<body><span>&notin;abc");
+ assert_equals(document.body.childNodes[0].textContent, "\u2209abc");
+});
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/041.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/041.html
new file mode 100644
index 00000000000..592711c94fd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/041.html
@@ -0,0 +1,13 @@
+<!doctype html>
+<title>document.write entity</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+var t = test(function() {
+ var s = "<body><span>&notin;abc";
+ for (var i=0; i<s.length; i++) {
+ document.write(s[i]);
+ }
+ assert_equals(document.body.childNodes[0].textContent, "\u2209abc");
+});
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/042.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/042.html
new file mode 100644
index 00000000000..e15f1d0c0f6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/042.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<title>document.write entity</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+var t = async_test();
+t.step(function() {
+ document.write("<body><span>&not");
+});
+</script>in;abc</span>
+<script>
+t.step(function() {
+ assert_equals(document.body.childNodes[0].textContent, "\u2209abc");
+})
+t.done();
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/043.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/043.html
new file mode 100644
index 00000000000..4058e7a8233
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/043.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<title>document.write entity</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+var t = async_test();
+t.step(function() {
+ document.write("<body><span>&");
+});
+</script>notabc</span>
+<script>
+t.step(function() {
+ assert_equals(document.body.childNodes[0].textContent, "\u00ACabc");
+})
+t.done();
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/044.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/044.html
new file mode 100644
index 00000000000..4c9f50273cd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/044.html
@@ -0,0 +1,17 @@
+<!doctype html>
+<title>document.write</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+var t = async_test();
+t.step(function() {
+ document.write("<body><textarea><span>Filler</span></textarea>");
+});
+</script>
+<script>
+t.step(function() {
+ assert_equals(document.body.childNodes[0].localName, "textarea");
+ assert_equals(document.body.childNodes[0].textContent, "<span>Filler</span>");
+})
+t.done();
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/045.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/045.html
new file mode 100644
index 00000000000..987eabf0f45
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/045.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<title>document.write</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+var t = async_test();
+t.step(function() {
+ var s = "<body><textarea><span>Filler</span></textarea>";
+ for (var i=0; i<s.length; i++) {
+ document.write(s[i]);
+ }
+});
+</script>
+<script>
+t.step(function() {
+ assert_equals(document.body.childNodes[0].localName, "textarea");
+ assert_equals(document.body.childNodes[0].textContent, "<span>Filler</span>");
+})
+t.done();
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/046.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/046.html
new file mode 100644
index 00000000000..e87e9cc825d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/046.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<title>document.write</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+var t = async_test();
+t.step(function() {
+ var s = "<body><textarea>";
+ for (var i=0; i<s.length; i++) {
+ document.write(s[i]);
+ }
+});
+</script><span>Filler</span></textarea>
+<script>
+t.step(function() {
+ assert_equals(document.body.childNodes[0].localName, "textarea");
+ assert_equals(document.body.childNodes[0].textContent, "<span>Filler</span>");
+})
+t.done();
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/047.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/047.html
new file mode 100644
index 00000000000..51faf6c85f1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/047.html
@@ -0,0 +1,15 @@
+<!doctype html>
+<title>document.write</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+var t = async_test();
+onload = function() {
+ t.step(function() {
+ document.write("<body>Filler Text<div id='log'></div>");
+ assert_equals(document.body.textContent, "Filler Text");
+ });
+ t.done();
+};
+</script>
+<body>FAIL
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/048.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/048.html
new file mode 100644
index 00000000000..51faf6c85f1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/048.html
@@ -0,0 +1,15 @@
+<!doctype html>
+<title>document.write</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+var t = async_test();
+onload = function() {
+ t.step(function() {
+ document.write("<body>Filler Text<div id='log'></div>");
+ assert_equals(document.body.textContent, "Filler Text");
+ });
+ t.done();
+};
+</script>
+<body>FAIL
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/049.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/049.html
new file mode 100644
index 00000000000..0ec282f2bc5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/049.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<title>document.write plaintext</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<div id="log"></div><script>
+test(function() {
+ var s = "<table><tr><td>Text</tr><plaintext><tr><td>Filler ";
+ for (var i=0; i<s.length; i++) {
+ document.write(s[i]);
+ }
+ document.close();
+ assert_equals(document.body.childNodes[2].nodeType, document.ELEMENT_NODE);
+ assert_equals(document.body.childNodes[2].localName, "plaintext");
+ assert_equals(document.body.childNodes[2].textContent, "<tr><td>Filler ");
+ assert_equals(document.body.childNodes[3].nodeType, document.ELEMENT_NODE);
+ assert_equals(document.body.childNodes[3].localName, "table");
+ assert_equals(document.body.childNodes[3].textContent, "Text");
+});
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/050.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/050.html
new file mode 100644
index 00000000000..0a37fa4c5f6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/050.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<title>document.write plaintext</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<div id="log"></div><script>
+var t = async_test();
+
+t.step(function() {
+ document.write("<plaintext>");
+ assert_equals(document.body.childNodes[2].nodeType, document.ELEMENT_NODE);
+ assert_equals(document.body.childNodes[2].localName, "plaintext");
+ var s = "Filler ";
+ for (var i=0; i<s.length; i++) {
+ document.write(s[i]);
+ assert_equals(document.body.childNodes[2].textContent, s.slice(0,i+1));
+ }
+ document.close();
+});
+
+onload = function() {
+ t.step(function() {
+ assert_equals(document.body.childNodes[2].textContent, "Filler Text\n");
+ });
+ t.done();
+}
+</script>Text
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/051.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/051.html
new file mode 100644
index 00000000000..cdbad22b558
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/051.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<title>document.write \r\n</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<div id="log"></div><script>
+var t = async_test()
+t.step(function() {
+ document.write("\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\nA");
+})
+
+onload = function() {
+ t.step(function() {
+ assert_equals(document.body.lastChild.data, "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nA\n");
+ });
+ t.done();
+};
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/document.write-01.xhtml b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/document.write-01.xhtml
new file mode 100644
index 00000000000..ec8702a744e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/document.write-01.xhtml
@@ -0,0 +1,19 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>document.write in XHTML</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com"/>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#document.write%28%29"/>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ assert_throws("INVALID_STATE_ERR", function() {
+ document.write("Failure: document.write actually worked");
+ }, "document.write in XHTML should throw an INVALID_STATE_ERR ");
+}, "document.write in XHTML");
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/document.write-02.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/document.write-02.html
new file mode 100644
index 00000000000..4c25da8b68a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/document.write-02.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>document.write and null/undefined</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-document-write%28%29">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#documents-in-the-dom">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ var iframe = document.createElement("iframe");
+ document.body.appendChild(iframe);
+ doc = iframe.contentDocument;
+ test(function() {
+ doc.open();
+ doc.write(null);
+ doc.close();
+ assert_equals(doc.documentElement.textContent, "null");
+ }, "document.write(null)");
+ test(function() {
+ doc.open();
+ doc.write(undefined);
+ doc.close();
+ assert_equals(doc.documentElement.textContent, "undefined");
+ }, "document.write(undefined)");
+}, "Calling document.write with null and undefined");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/iframe_001.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/iframe_001.html
new file mode 100644
index 00000000000..8b54560c6ce
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/iframe_001.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<title>document.write into iframe</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<iframe id="test"></iframe>
+<script>
+test(
+function() {
+ var iframe = document.getElementById("test");
+ iframe.contentDocument.write("Filler Text");
+ iframe.contentDocument.close();
+ assert_equals(iframe.contentDocument.body.textContent, "Filler Text");
+});
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/iframe_002.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/iframe_002.html
new file mode 100644
index 00000000000..f77819adb60
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/iframe_002.html
@@ -0,0 +1,22 @@
+<!doctype html>
+<title>document.write into iframe</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<iframe id="test"></iframe>
+<script>
+test(
+function() {
+ var iframe = document.getElementById("test");
+ var s = "<i id='a'>Filler Text</i><b id=b>Filler Text</b>"
+ for (var i=0; i<s.length; i++) {
+ iframe.contentDocument.write(s[i]);
+ }
+ iframe.contentDocument.close();
+ assert_equals(iframe.contentDocument.body.childNodes[0].textContent, "Filler Text");
+ assert_equals(iframe.contentDocument.body.childNodes[0].localName, "i");
+ assert_equals(iframe.contentDocument.body.childNodes[0].getAttribute('id'), "a");
+ assert_equals(iframe.contentDocument.body.childNodes[1].textContent, "Filler Text");
+ assert_equals(iframe.contentDocument.body.childNodes[1].localName, "b");
+ assert_equals(iframe.contentDocument.body.childNodes[1].getAttribute('id'), "b");
+});
+</script>
+<div id="log"></div> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/iframe_003.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/iframe_003.html
new file mode 100644
index 00000000000..9865874da40
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/iframe_003.html
@@ -0,0 +1,23 @@
+<!doctype html>
+<title>document.write script into iframe</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<iframe id="test"></iframe>
+<script>
+test(
+function() {
+ var iframe = document.getElementById("test");
+ var s = "<script>document.write(\"<i id='a'>Filler Text</i>\")</script" + "><b id=b>Filler Text</b>"
+ for (var i=0; i<s.length; i++) {
+ iframe.contentDocument.write(s[i]);
+ }
+ iframe.contentDocument.close();
+ //Note: <script> ends up in <head>
+ assert_equals(iframe.contentDocument.body.childNodes[0].textContent, "Filler Text");
+ assert_equals(iframe.contentDocument.body.childNodes[0].localName, "i");
+ assert_equals(iframe.contentDocument.body.childNodes[0].getAttribute('id'), "a");
+ assert_equals(iframe.contentDocument.body.childNodes[1].textContent, "Filler Text");
+ assert_equals(iframe.contentDocument.body.childNodes[1].localName, "b");
+ assert_equals(iframe.contentDocument.body.childNodes[1].getAttribute('id'), "b");
+});
+</script>
+<div id="log"></div> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/iframe_004.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/iframe_004.html
new file mode 100644
index 00000000000..a4d7b1ddad9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/iframe_004.html
@@ -0,0 +1,22 @@
+<!doctype html>
+<title>document.write script into iframe write back into parent</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<iframe id="test"></iframe>
+<script>
+var t = async_test();
+var iframe = document.getElementById("test");
+var order = [];
+t.step(function() {
+ order.push(1);
+ var s = "<script>parent.order.push(2); parent.document.write('<script>order.push(3);</script'+'>'); parent.order.push(4)</script" + ">";
+ for (var i=0; i<s.length; i++) {
+ iframe.contentDocument.write(s[i]);
+ }
+ iframe.contentDocument.close();
+ order.push(5);
+ assert_array_equals(order, [1,2,3,4,5])
+}
+);
+t.done();
+</script>
+<div id="log"></div> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/iframe_005.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/iframe_005.html
new file mode 100644
index 00000000000..7bc3ed6c29b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/iframe_005.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<title>document.write external script into iframe write back into parent</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<iframe id="test"></iframe>
+<script>
+var t = async_test();
+var iframe = document.getElementById("test");
+var order = [];
+t.step(function() {
+ order.push(1);
+ var s = "<script src='iframe_005.js'></script" + ">";
+ iframe.contentDocument.write(s);
+ iframe.contentDocument.close();
+ order.push(2);
+ assert_array_equals(order, [1,2])
+}
+);
+addEventListener("load", function() {
+ t.step(function() {
+ assert_array_equals(order, [1,2,3,4,5])
+ });
+ t.done();
+}, false);
+</script>
+<div id="log"></div> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/iframe_005.js b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/iframe_005.js
new file mode 100644
index 00000000000..bf038f70049
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/iframe_005.js
@@ -0,0 +1,3 @@
+parent.order.push(3);
+document.write("<script>parent.order.push(4)</script>");
+parent.order.push(5); \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/iframe_006.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/iframe_006.html
new file mode 100644
index 00000000000..d080ee3673c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/iframe_006.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<title>document.write external script into iframe write back into parent</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<iframe id="test"></iframe>
+<script>
+var t = async_test();
+var iframe = document.getElementById("test");
+var order = [];
+t.step(function() {
+ order.push(1);
+ var s = "<script>parent.order.push(2); parent.document.write('<script>order.push(3); iframe.contentDocument.write(\"<script>parent.order.push(4)</script\"+\">\");order.push(5);</script' + '>'); parent.order.push(6)</script"+">";
+ iframe.contentDocument.write(s);
+ iframe.contentDocument.close();
+ order.push(7);
+ assert_array_equals(order, [1,2,3,4,5,6,7]);
+});
+t.done();
+</script>
+<div id="log"></div> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/iframe_007.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/iframe_007.html
new file mode 100644
index 00000000000..c00aa7062df
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/iframe_007.html
@@ -0,0 +1,17 @@
+<!doctype html>
+<title>document.write comment into iframe</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<iframe id="test"></iframe>
+<script>
+test(function() {
+ var iframe = document.getElementById("test");
+ var s = "<!--Filler-->";
+ for (var i=0; i<s.length; i++) {
+ iframe.contentDocument.write(s);
+ }
+ iframe.contentDocument.close();
+ assert_equals(iframe.contentDocument.childNodes[0].nodeType, document.COMMENT_NODE);
+ assert_equals(iframe.contentDocument.childNodes[0].data, "Filler");
+});
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/iframe_008.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/iframe_008.html
new file mode 100644
index 00000000000..c814958d19c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/iframe_008.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<title>document.write plaintext into iframe</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<iframe id="test"></iframe>
+<script>
+test(function() {
+ var iframe = document.getElementById("test");
+ var s = "<plaintext><span>Filler Text";
+ for (var i=0; i<s.length; i++) {
+ iframe.contentDocument.write(s[i]);
+ }
+ iframe.contentDocument.close();
+ assert_equals(iframe.contentDocument.body.childNodes[0].nodeType, document.ELEMENT_NODE);
+ assert_equals(iframe.contentDocument.body.childNodes[0].localName, "plaintext");
+ assert_equals(iframe.contentDocument.body.childNodes[0].textContent, "<span>Filler Text");
+});
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/iframe_009.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/iframe_009.html
new file mode 100644
index 00000000000..8b271c7a033
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/iframe_009.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<title>document.write plaintext into iframe</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<iframe id="test"></iframe>
+<script>
+test(function() {
+ var iframe = document.getElementById("test");
+ var s = "<table><tr><td>Text</tr><plaintext><tr><td>Filler ";
+ for (var i=0; i<s.length; i++) {
+ iframe.contentDocument.write(s[i]);
+ }
+ iframe.contentDocument.close();
+ assert_equals(iframe.contentDocument.body.childNodes[0].nodeType, document.ELEMENT_NODE);
+ assert_equals(iframe.contentDocument.body.childNodes[0].localName, "plaintext");
+ assert_equals(iframe.contentDocument.body.childNodes[0].textContent, "<tr><td>Filler ");
+ assert_equals(iframe.contentDocument.body.childNodes[1].nodeType, document.ELEMENT_NODE);
+ assert_equals(iframe.contentDocument.body.childNodes[1].localName, "table");
+ assert_equals(iframe.contentDocument.body.childNodes[1].textContent, "Text");
+});
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/iframe_010.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/iframe_010.html
new file mode 100644
index 00000000000..8dc21a013a5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/iframe_010.html
@@ -0,0 +1,23 @@
+<!doctype html>
+<title>document.write plaintext</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<iframe id="test"></iframe>
+<script>
+var t = async_test();
+var iframe = document.getElementById("test");
+
+function check_dom() {
+ assert_equals(iframe.contentDocument.body.childNodes[0].localName, "plaintext")
+ assert_equals(iframe.contentDocument.body.childNodes[0].textContent, "Filler ")
+ assert_equals(iframe.contentDocument.body.childNodes[1].localName, "table")
+}
+
+t.step(function() {
+ var s = "<script>document.write('<table><plaintext>Filler '); document.close(); top.t.step(function() {top.check_dom()})</script" + ">";
+ for (var i=0; i<s.length; i++) {
+ iframe.contentDocument.write(s[i]);
+ }
+ t.done();
+});
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/nested-document-write-1.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/nested-document-write-1.html
new file mode 100644
index 00000000000..c7a7a1db4e7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/nested-document-write-1.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<body>You should see the word "worked" below<br><script>document.write("\u003cscript>document.write(\"\\u003cscript src='nested-document-write-external.js'>\\u003c/script>r\"); document.write(\"k\");\u003c/script>e"); document.write("d");</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/nested-document-write-2.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/nested-document-write-2.html
new file mode 100644
index 00000000000..60b8eae1efe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/nested-document-write-2.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<body>
+You should see the word "worked" in the frame below.<br>
+<iframe></iframe>
+<script>
+var doc = document.getElementsByTagName("iframe")[0].contentDocument;
+doc.open(); doc.write("\u003cscript>document.write(\"\\u003cscript src='nested-document-write-external.js'>\\u003c/script>r\"); document.write(\"k\");\u003c/script>e"); doc.write("d"); doc.close();</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/nested-document-write-external.js b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/nested-document-write-external.js
new file mode 100644
index 00000000000..bf91daf986e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/nested-document-write-external.js
@@ -0,0 +1 @@
+document.write("w"); document.write("o");
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/original-id.json b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/original-id.json
new file mode 100644
index 00000000000..08bd4d0d4e3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/original-id.json
@@ -0,0 +1 @@
+{"original_id":"document.write()"} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/script_001.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/script_001.html
new file mode 100644
index 00000000000..43c7adb4d4d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/script_001.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>document.write script</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+var t = async_test();
+t.step(function() {
+ document.write("<script>t.done();<"+"/script>");
+});
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/script_002.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/script_002.html
new file mode 100644
index 00000000000..3879d8489f1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/script_002.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<title>document.write script executed synchronously</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+var t = async_test();
+var order = [];
+t.step(function() {
+ document.write("<script>t.step(function() {order.push(1);});<"+"/script>");
+ order.push(2);
+});
+</script>
+<script>
+t.step(function() {
+ order.push(3);
+ assert_array_equals(order, [1,2,3]);
+})
+t.done();
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/script_003.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/script_003.html
new file mode 100644
index 00000000000..e669252f755
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/script_003.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>document.write script writing a further script</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+var t = async_test();
+t.step(function() {
+ document.write("<script>document.write('<script>t.done()</script'+'>')<"+"/script>");
+});
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/script_004.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/script_004.html
new file mode 100644
index 00000000000..15fda325b10
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/script_004.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<title>document.write script writing script; order of execution</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+var t = async_test();
+var order = [];
+t.step(function() {
+ order.push(1);
+ document.write("<script>order.push(2); document.write('<script>order.push(3);</script'+'>'); order.push(4);<"+"/script>");
+ order.push(5);
+});
+</script>
+<script>
+t.step(function() {
+ assert_array_equals(order, [1,2,3,4,5]);
+});
+t.done();
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/script_005.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/script_005.html
new file mode 100644
index 00000000000..b99196c7d09
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/script_005.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<title>document.write external script</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+var t = async_test();
+var order = [];
+t.step(function() {
+ order.push(1);
+ document.write("<script src='005.js'><"+"/script>");
+ order.push(2);
+});
+</script>
+<script>
+order.push(4);
+t.step(function() {
+ assert_array_equals(order, [1,2,3,4]);
+});
+t.done();
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/script_006.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/script_006.html
new file mode 100644
index 00000000000..c8dd9a5f9ae
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/script_006.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<title>document.write external script followed by internal script</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+var t = async_test();
+var order = [];
+t.step(function() {
+ order.push(1);
+ document.write("<script src='006.js'><"+"/script><script>t.step(function(){order.push(4)})</script"+">");
+ order.push(2);
+});
+</script>
+<script>
+t.step(function() {
+ order.push(5);
+ assert_array_equals(order, [1,2,3,4,5]);
+});
+t.done();
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/script_007.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/script_007.html
new file mode 100644
index 00000000000..fbbe5b2f864
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/script_007.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<title>document.write external script that document.writes inline script</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+var t = async_test();
+var order = [];
+t.step(function() {
+ order.push(1);
+});
+</script>
+<script src="007.js"></script>
+<script>
+t.step(function() {
+ order.push(4);
+ assert_array_equals(order, [1,2,3,4]);
+});
+t.done();
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/script_008.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/script_008.html
new file mode 100644
index 00000000000..c5a44dc7002
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/script_008.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<title>document.write external script that document.writes external script</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+var t = async_test();
+var order = [];
+t.step(function() {
+ order.push(1);
+});
+</script>
+<script src="008.js"></script>
+<script>
+t.step(function() {
+ order.push(4);
+ assert_array_equals(order, [1,2,3,4]);
+});
+t.done();
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/script_009.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/script_009.html
new file mode 100644
index 00000000000..d12d934ea05
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/script_009.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<title>document.write script that document.writes script</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+var t = async_test();
+var order = [];
+t.step(function() {
+ order.push(1);
+ document.write("<script>order.push(2); document.write('<script>order.push(3); document.write(\"<script>order.push(4);</script\"+\">\"); order.push(5);</script' + '>'); order.push(6);</script" + ">");
+ order.push(7);
+});
+</script>
+<script>
+t.step(function() {
+ assert_array_equals(order, [1,2,3,4,5,6,7]);
+});
+t.done();
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/script_010.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/script_010.html
new file mode 100644
index 00000000000..93728d6f27e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/script_010.html
@@ -0,0 +1,22 @@
+<!doctype html>
+<title>document.write external script tokenizer order</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+var t = async_test();
+var order = [];
+t.step(function() {
+ order.push(1);
+ document.write("<script src='010.js'></script" + "><meta><script src='010-1.js'></script" + ">");
+ order.push(2);
+ assert_equals(document.getElementsByTagName("meta").length, 0);
+});
+</script>
+<script>
+t.step(function() {
+ order.push(5);
+ assert_equals(document.getElementsByTagName("meta").length, 1);
+ assert_array_equals(order, [1,2,3,4,5]);
+});
+t.done();
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/script_011.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/script_011.html
new file mode 100644
index 00000000000..2bbcaf976e7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/script_011.html
@@ -0,0 +1,22 @@
+<!doctype html>
+<title>document.write external script that document.writes external script</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+var t = async_test();
+var order = [];
+t.step(function() {
+ order.push(1);
+ document.write("<script src='011.js'></script" + "><meta>");
+ order.push(2);
+ assert_equals(document.getElementsByTagName("meta").length, 0);
+});
+</script>
+<script>
+t.step(function() {
+ order.push(5);
+ assert_equals(document.getElementsByTagName("meta").length, 3, "Number of meta elements at end");
+ assert_array_equals(order, [1,2,3,4,5]);
+});
+t.done();
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/script_012.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/script_012.html
new file mode 100644
index 00000000000..57755f4c94d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/script_012.html
@@ -0,0 +1,22 @@
+<!doctype html>
+<title>document.write external script tokenizer order</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+var t = async_test();
+var order = [];
+t.step(function() {
+ order.push(1);
+ document.write("<script>order.push(2); document.write('<script src=\"012.js\"></script' + '><meta>'); order.push(3); t.step(function() {assert_equals(document.getElementsByTagName('meta').length, 0)});</script" + "><meta>");
+ order.push(4);
+ assert_equals(document.getElementsByTagName("meta").length, 0);
+});
+</script>
+<script>
+t.step(function() {
+ order.push(6);
+ assert_equals(document.getElementsByTagName("meta").length, 2);
+ assert_array_equals(order, [1,2,3,4,5,6]);
+});
+t.done();
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/script_013.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/script_013.html
new file mode 100644
index 00000000000..0e71e5eb0cd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-write/script_013.html
@@ -0,0 +1,24 @@
+<!doctype html>
+<title>document.write</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script>
+var t = async_test();
+t.step(function() {
+ var s = "<script src='013.js'><" + "/script></svg>]]><path></svg>";
+ for (var i=0; i<s.length; i++) {
+ document.write(s[i]);
+ }
+});
+</script><script>
+t.step(function() {
+ assert_equals(document.body.childNodes[0].nodeType, document.ELEMENT_NODE);
+ assert_equals(document.body.childNodes[0].localName, "svg");
+ assert_equals(document.body.childNodes[0].childNodes[0].nodeType, document.TEXT_NODE);
+ assert_equals(document.body.childNodes[0].childNodes[0].data, "</svg>");
+ assert_equals(document.body.childNodes[0].childNodes[1].nodeType, document.ELEMENT_NODE);
+ assert_equals(document.body.childNodes[0].childNodes[1].localName, "path");
+}
+);
+t.done();
+</script>
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-writeln/.gitkeep b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-writeln/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-writeln/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-writeln/document.writeln-01.xhtml b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-writeln/document.writeln-01.xhtml
new file mode 100644
index 00000000000..3d59bcd20b4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-writeln/document.writeln-01.xhtml
@@ -0,0 +1,19 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>document.writeln in XHTML</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com"/>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#document.writeln%28%29"/>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ assert_throws("INVALID_STATE_ERR", function() {
+ document.writeln("Failure: document.writeln actually worked");
+ }, "document.writeln in XHTML should throw an INVALID_STATE_ERR ");
+}, "document.writeln in XHTML");
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-writeln/document.writeln-02.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-writeln/document.writeln-02.html
new file mode 100644
index 00000000000..2a64ac75618
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-writeln/document.writeln-02.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>document.writeln and null/undefined</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-document-writeln%28%29">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#documents-in-the-dom">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ var iframe = document.createElement("iframe");
+ document.body.appendChild(iframe);
+ doc = iframe.contentDocument;
+ test(function() {
+ doc.open();
+ doc.writeln(null);
+ doc.close();
+ assert_equals(doc.documentElement.textContent, "null\n");
+ }, "document.writeln(null)");
+ test(function() {
+ doc.open();
+ doc.writeln(undefined);
+ doc.close();
+ assert_equals(doc.documentElement.textContent, "undefined\n");
+ }, "document.writeln(undefined)");
+}, "Calling document.writeln with null and undefined");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-writeln/original-id.json b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-writeln/original-id.json
new file mode 100644
index 00000000000..0cc32be6a23
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/document-writeln/original-id.json
@@ -0,0 +1 @@
+{"original_id":"document.writeln()"} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/.gitkeep b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/001.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/001.html
new file mode 100644
index 00000000000..f82d80be7b6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/001.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<title>Replacement of window object after document.open</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<iframe></iframe>
+<script>
+var t = async_test();
+
+onload = t.step_func(function() {
+ var iframe = document.getElementsByTagName("iframe")[0];
+ iframe.contentWindow.state = 1;
+ var handle = iframe.contentWindow;
+ iframe.contentDocument.open();
+ assert_false("state" in iframe.contentWindow, "Variables are not preserved after document.open");
+ assert_equals(iframe.contentWindow.state, undefined, "Variables are not preserved after document.open");
+ assert_equals(iframe.contentWindow, handle);
+ t.done();
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/002.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/002.html
new file mode 100644
index 00000000000..42f6c580cae
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/002.html
@@ -0,0 +1,12 @@
+<!doctype html>
+<title>document.open during parsing</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ var log = document.getElementById("log");
+ document.open()
+ assert_equals(document.getElementById("log"), log)
+})
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/004-1.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/004-1.html
new file mode 100644
index 00000000000..c50eddd41fa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/004-1.html
@@ -0,0 +1 @@
+<!doctype html>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/004.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/004.html
new file mode 100644
index 00000000000..f489caa72fe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/004.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<title>Reuse of document object after document.open</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<iframe src="004-1.html"></iframe>
+<script>
+var t = async_test();
+var iframe;
+onload = t.step_func(function() {
+ var iframe = document.getElementsByTagName("iframe")[0];
+ var handle = iframe.contentDocument;
+ iframe.contentDocument.test_state = 1;
+ iframe.contentDocument.open();
+ assert_equals(iframe.contentDocument.test_state, 1);
+ assert_equals(iframe.contentDocument, handle);
+ t.done();
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/005.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/005.html
new file mode 100644
index 00000000000..6bd8505203f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/005.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<title>Cancelling timeout after document.open</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<iframe src="004-1.html"></iframe>
+<script>
+var t = async_test();
+var iframe;
+onload = t.step_func(function() {
+ var iframe = document.getElementsByTagName("iframe")[0];
+ iframe.contentWindow.setTimeout(t.step_func(function() {assert_unreached()}), 100);
+ iframe.contentDocument.open()
+ setTimeout(function() {t.done();}, 200);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/006.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/006.html
new file mode 100644
index 00000000000..692d06d98fb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/006.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<title>Cancelling error after document.open</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<iframe src="004-1.html"></iframe>
+<script>
+var t = async_test();
+var iframe;
+onload = t.step_func(function() {
+ var iframe = document.getElementsByTagName("iframe")[0];
+ var img = iframe.contentDocument.createElement("img");
+ img.onerror = t.step_func(function() {assert_unreached()})
+ img.src = "missing";
+ iframe.contentDocument.body.appendChild(img);
+ iframe.contentDocument.open()
+ setTimeout(function() {t.done();}, 500);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/007.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/007.html
new file mode 100644
index 00000000000..e5f0d1561ef
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/007.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<title>Unregistering event handlers after document.open</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<iframe src="004-1.html"></iframe>
+<script>
+var t = async_test();
+var iframe;
+onload = t.step_func(function() {
+ var iframe = document.getElementsByTagName("iframe")[0];
+ iframe.contentDocument.onclick = t.step_func(function() {assert_unreached()})
+ iframe.contentDocument.open();
+ var e = iframe.contentDocument.createEvent("mouseevents")
+ e.initEvent("click", false, false);
+ iframe.contentDocument.dispatchEvent(e);
+ setTimeout(function() {t.done();}, 500);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/008.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/008.html
new file mode 100644
index 00000000000..08fd4aa4394
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/008.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<title>Replacement of document prototype object after document.open</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<iframe src="004-1.html"></iframe>
+<script>
+var t = async_test();
+var iframe;
+onload = t.step_func(function() {
+ var iframe = document.getElementsByTagName("iframe")[0];
+ var handle = Object.getPrototypeOf(iframe.contentDocument);
+ handle.test_state = 1;
+ iframe.contentDocument.open();
+ var new_handle = Object.getPrototypeOf(iframe.contentDocument);
+ assert_equals(new_handle.test_state, undefined);
+ assert_not_equals(new_handle, handle);
+ t.done();
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/009.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/009.html
new file mode 100644
index 00000000000..4fc5163ea44
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/009.html
@@ -0,0 +1,34 @@
+<!doctype html>
+<title>document.open replacing singleton</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<iframe src="004-1.html"></iframe>
+<script>
+var iframe = document.getElementsByTagName("iframe")[0];
+var steps;
+iframe.onload = function() {
+steps = ["window", "location", "history", "navigator", "applicationCache", "sessionStorage", "localStorage", "locationbar"].map(
+function(x) {
+ var t = async_test(document.title + " " + x);
+ var handle = iframe.contentWindow[x];
+ handle.test_state = 1;
+ return t.step_func(
+ function() {
+ var new_handle = iframe.contentWindow[x];
+ assert_equals(new_handle.test_state, undefined);
+ if (x !== "window") {
+ assert_not_equals(new_handle, handle);
+ } else {
+ assert_equals(new_handle, handle);
+ }
+ t.done();
+ });
+ }
+);
+}
+onload = function() {
+ iframe.contentDocument.open();
+ steps.forEach(function(x) {x()});
+}
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/010-1.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/010-1.html
new file mode 100644
index 00000000000..317e13691d4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/010-1.html
@@ -0,0 +1,2 @@
+<!doctype html>
+010-1
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/010-2.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/010-2.html
new file mode 100644
index 00000000000..ea537fcd601
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/010-2.html
@@ -0,0 +1,5 @@
+<!doctype html>
+010-2
+<script>
+onload = function() {history.back()}
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/010.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/010.html
new file mode 100644
index 00000000000..f37e8855dcf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/010.html
@@ -0,0 +1,22 @@
+<!doctype html>
+<title>Salvagability of document.opened document</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<iframe src="010-1.html"></iframe>
+<script>
+var iframe;
+var t = async_test();
+onload = t.step_func(function() {
+ iframe = document.getElementsByTagName("iframe")[0];
+ iframe.contentDocument.open();
+ iframe.contentDocument.close();
+
+ iframe.contentWindow.setTimeout(t.step_func(function() {t.done();}), 500);
+
+ onload = null;
+
+ iframe.src = "010-2.html"
+ setTimeout(t.step_func(function() {assert_unreached()}), 1000)
+})
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/011-1.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/011-1.html
new file mode 100644
index 00000000000..e12d78f4ac3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/011-1.html
@@ -0,0 +1,5 @@
+<script>
+document.open()
+setTimeout(parent.t.step_func(function() {parent.t.done()}), 0);
+document.close();
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/011.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/011.html
new file mode 100644
index 00000000000..2acc884c548
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/011.html
@@ -0,0 +1,9 @@
+<!doctype html>
+<title>Timeout after document.open</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var t = async_test();
+</script>
+<iframe src="011-1.html"></iframe>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/012-1.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/012-1.html
new file mode 100644
index 00000000000..b1937b2f854
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/012-1.html
@@ -0,0 +1,7 @@
+<script>
+onload = parent.t.step_func(function() {
+ document.open()
+ setTimeout(parent.t.step_func(function() {parent.t.done()}), 0);
+ document.close();
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/012.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/012.html
new file mode 100644
index 00000000000..518454858de
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/012.html
@@ -0,0 +1,9 @@
+<!doctype html>
+<title>Timeout after document.open in load event</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var t = async_test();
+</script>
+<iframe src="012-1.html"></iframe>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/013-1.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/013-1.html
new file mode 100644
index 00000000000..ed8843bbdbb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/013-1.html
@@ -0,0 +1,7 @@
+<script>
+addEventListener("DOMContentLoaded", parent.t.step_func(function() {
+ document.open()
+ setTimeout(parent.t.step_func(function() {parent.t.done()}), 0);
+ document.close();
+}), false);
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/013.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/013.html
new file mode 100644
index 00000000000..5749361aa8a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/013.html
@@ -0,0 +1,9 @@
+<!doctype html>
+<title>Timeout after document.open in DOMContentLoaded event</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var t = async_test();
+</script>
+<iframe src="013-1.html"></iframe>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/014-1.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/014-1.html
new file mode 100644
index 00000000000..6d04da5651c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/014-1.html
@@ -0,0 +1,9 @@
+<script>
+onload = parent.t.step_func(function() {
+ setTimeout(parent.t.step_func(function() {
+ document.open()
+ setTimeout(parent.t.step_func(function() {parent.t.done()}), 0);
+ document.close();
+ }), 100)
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/014.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/014.html
new file mode 100644
index 00000000000..b4e4b17cf4f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/014.html
@@ -0,0 +1,9 @@
+<!doctype html>
+<title>Timeout after document.open after document is completely loaded</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var t = async_test();
+</script>
+<iframe src="014-1.html"></iframe>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/015-1.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/015-1.html
new file mode 100644
index 00000000000..670710090e1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/015-1.html
@@ -0,0 +1,17 @@
+<script>
+onload = function() {
+ window.test_prop = 1;
+ parent.tests[0].step(function() {parent.assert_equals(test_prop, 1)});
+ document.open();
+ document.write("<script>test_prop = 2;<\/script>");
+ document.close();
+ parent.tests[0].step(function() {parent.assert_equals(test_prop, 1)});
+ parent.tests[1].step(function() {parent.assert_equals(window.test_prop, 2)});
+ parent.tests[2].step(function() {parent.assert_equals(get_this(), window)});
+ parent.tests_done();
+};
+
+function get_this() {
+ return this;
+}
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/015.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/015.html
new file mode 100644
index 00000000000..5ef06176ba0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/015.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<title>Window vs global scope after document.open</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var tests = [async_test("global scope unchanged"),
+ async_test("window object changed"),
+ async_test("this is the window object")];
+function tests_done() {
+ tests.forEach(function(t) {t.done()});
+}
+</script>
+<iframe src="015-1.html"></iframe>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/016-1.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/016-1.html
new file mode 100644
index 00000000000..17f5140ec9f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/016-1.html
@@ -0,0 +1,39 @@
+<script>
+window.test_prop = 1;
+</script>
+<script>
+onload = function() {
+ document.open();
+ document.write("<script>test_prop = 2; timeout_fired=false;<\/script>");
+ document.close();
+
+ setTimeout(function() {
+ parent.tests[0].step(function() {
+ parent.assert_equals(test_prop, 1, "Global scope from original window timeout");
+ parent.assert_equals(window.test_prop, 2, "Window property from original window timeout")
+ });
+ parent.tests[1].step(function() {
+ var t = get_this();
+ parent.assert_equals(t.test_prop, 2, "Window property from original window timeout");
+ parent.assert_equals(t, window, "Global scope from original window timeout");
+ });
+ }, 0);
+
+ window.setTimeout(function() {
+ parent.tests[2].step(function() {
+ parent.assert_equals(test_prop, 1, "Global scope from original window timeout");
+ parent.assert_equals(window.test_prop, 2, "Window property from original window timeout")
+ });
+ parent.tests[3].step(function() {
+ var t = get_this();
+ parent.assert_equals(t.test_prop, 2, "Window property from original window timeout");
+ parent.assert_equals(t, window, "Global scope from original window timeout");
+ });
+ parent.tests_done();
+ }, 100);
+};
+
+function get_this() {
+ return this;
+}
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/016.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/016.html
new file mode 100644
index 00000000000..1c70fce591a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/016.html
@@ -0,0 +1,15 @@
+<!doctype html>
+<title>setTimeout document.open</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var tests = [async_test("Timeout on original window, scope"),
+ async_test("Timeout on original window, this object"),
+ async_test("Timeout on new window, scope"),
+ async_test("Timeout on new window, this object")];
+function tests_done() {
+ tests.forEach(function(t) {t.done()});
+}
+</script>
+<iframe src="016-1.html"></iframe>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/document.open-01.xhtml b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/document.open-01.xhtml
new file mode 100644
index 00000000000..974702ae8cb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/document.open-01.xhtml
@@ -0,0 +1,19 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>document.open in XHTML</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com"/>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#opening-the-input-stream"/>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ assert_throws("INVALID_STATE_ERR", function() {
+ document.open();
+ }, "document.open in XHTML should throw an INVALID_STATE_ERR ");
+}, "document.open in XHTML");
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/document.open-02.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/document.open-02.html
new file mode 100644
index 00000000000..b56e3a836f4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/document.open-02.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>document.open with three arguments</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-document-open">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+function open() {
+ assert_unreached("The call should be redirected to the real window.open")
+}
+test(function(t) {
+ var w;
+ t.add_cleanup(function() {try {w.close()} catch(e) {}});
+ w = document.open("/resources/testharness.js", "", "");
+ assert_true(w instanceof w.Window, "Expected a window");
+}, "document.open should redirect to window.open when called with three arguments");
+
+test(function() {
+ var parser = new DOMParser();
+ var doc = parser.parseFromString("", "text/html");
+ assert_equals(doc.defaultView, null);
+ assert_throws("INVALID_ACCESS_ERR", function() {
+ doc.open("/resources/testharness.js", "", "");
+ });
+}, "document.open should throw when it has no window and is called with three arguments");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/document.open-03-frame.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/document.open-03-frame.html
new file mode 100644
index 00000000000..b5252dceab6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/document.open-03-frame.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<script>
+onload = function() {
+ document.open();
+ document.close();
+ parent.report(window.setTimeout === setTimeout, false, "setTimeout");
+ parent.report(window === this, true, "this");
+ parent.done();
+}
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/document.open-03.html b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/document.open-03.html
new file mode 100644
index 00000000000..fc325d54db2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/dynamic-markup-insertion/opening-the-input-stream/document.open-03.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<title>document.open and singleton replacement</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-document-open">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var t = async_test();
+function report(actual, expected, message) {
+ t.step(function() {
+ assert_equals(actual, expected, message);
+ });
+}
+function done() {
+ t.done();
+}
+</script>
+<iframe src=document.open-03-frame.html></iframe>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements-embedded.js b/tests/wpt/web-platform-tests/html/dom/elements-embedded.js
new file mode 100644
index 00000000000..a948b62ff83
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements-embedded.js
@@ -0,0 +1,152 @@
+// Up-to-date as of 2013-04-06.
+var embeddedElements = {
+ img: {
+ // Conforming
+ alt: "string",
+ src: "url",
+ srcset: "string",
+ crossOrigin: {type: "enum", keywords: ["", "anonymous", "use-credentials"]},
+ useMap: "string",
+ isMap: "boolean",
+ width: {type: "unsigned long", customGetter: true},
+ height: {type: "unsigned long", customGetter: true},
+
+ // Obsolete
+ name: "string",
+ lowsrc: {type: "url"},
+ align: "string",
+ hspace: "unsigned long",
+ vspace: "unsigned long",
+ longDesc: "url",
+ border: {type: "string", treatNullAsEmptyString: true},
+ },
+ iframe: {
+ // Conforming
+ src: "url",
+ srcdoc: "string",
+ name: "string",
+ sandbox: "settable tokenlist",
+ seamless: "boolean",
+ allowFullscreen: "boolean",
+ width: "string",
+ height: "string",
+
+ // Obsolete
+ align: "string",
+ scrolling: "string",
+ frameBorder: "string",
+ longDesc: "url",
+ marginHeight: {type: "string", treatNullAsEmptyString: true},
+ marginWidth: {type: "string", treatNullAsEmptyString: true}
+ },
+ embed: {
+ // Conforming
+ src: "url",
+ type: "string",
+ width: "string",
+ height: "string",
+
+ // Obsolete
+ align: "string",
+ name: "string"
+ },
+ object: {
+ // Conforming
+ data: "url",
+ type: "string",
+ typeMustMatch: "boolean",
+ name: "string",
+ useMap: "string",
+ width: "string",
+ height: "string",
+
+ // Obsolete
+ align: "string",
+ archive: "string",
+ code: "string",
+ declare: "boolean",
+ hspace: "unsigned long",
+ standby: "string",
+ vspace: "unsigned long",
+ codeBase: "url",
+ codeType: "string",
+ border: {type: "string", treatNullAsEmptyString: true}
+ },
+ param: {
+ // Conforming
+ name: "string",
+ value: "string",
+
+ // Obsolete
+ type: "string",
+ valueType: "string"
+ },
+ video: {
+ // HTMLMediaElement
+ src: "url",
+ crossOrigin: {type: "enum", keywords: ["anonymous", "use-credentials"], nonCanon:{"": "anonymous"}},
+ // As with "keytype", we have no missing value default defined here.
+ preload: {type: "enum", keywords: ["none", "metadata", "auto"], nonCanon: {"": "auto"}, defaultVal: null},
+ autoplay: "boolean",
+ loop: "boolean",
+ mediaGroup: "string",
+ controls: "boolean",
+ defaultMuted: {type: "boolean", domAttrName: "muted"},
+
+ width: "unsigned long",
+ height: "unsigned long",
+ poster: "url"
+ },
+ audio: {
+ // HTMLMediaElement
+ src: "url",
+ crossOrigin: {type: "enum", keywords: ["anonymous", "use-credentials"], nonCanon:{"": "anonymous"}},
+ // As with "keytype", we have no missing value default defined here.
+ preload: {type: "enum", keywords: ["none", "metadata", "auto"], nonCanon: {"": "auto"}, defaultVal: null},
+ autoplay: "boolean",
+ loop: "boolean",
+ mediaGroup: "string",
+ controls: "boolean",
+ defaultMuted: {type: "boolean", domAttrName: "muted"}
+ },
+ source: {
+ src: "url",
+ type: "string",
+ media: "string"
+ },
+ track: {
+ kind: {type: "enum", keywords: ["subtitles", "captions", "descriptions", "chapters", "metadata"], defaultVal: "captions"},
+ src: "url",
+ srclang: "string",
+ label: "string",
+ "default": "boolean"
+ },
+ canvas: {
+ width: {type: "unsigned long", defaultVal: 300},
+ height: {type: "unsigned long", defaultVal: 150}
+ },
+ map: {
+ name: "string"
+ },
+ area: {
+ // Conforming
+ alt: "string",
+ coords: "string",
+ shape: "string",
+ target: "string",
+ download: "string",
+ ping: "urls",
+ rel: "string",
+ relList: {type: "tokenlist", domAttrName: "rel"},
+ hreflang: "string",
+ type: "string",
+
+ //URLUtils
+ href: "url",
+
+ // Obsolete
+ noHref: "boolean"
+ },
+};
+
+mergeElements(embeddedElements);
diff --git a/tests/wpt/web-platform-tests/html/dom/elements-forms.js b/tests/wpt/web-platform-tests/html/dom/elements-forms.js
new file mode 100644
index 00000000000..d5eca7508b0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements-forms.js
@@ -0,0 +1,143 @@
+// Up-to-date as of 2013-04-07.
+var formElements = {
+ form: {
+ acceptCharset: {type: "string", domAttrName: "accept-charset"},
+ // TODO: action is special
+ // action: "url",
+ autocomplete: {type: "enum", keywords: ["on", "off"], defaultVal: "on"},
+ enctype: {type: "enum", keywords: ["application/x-www-form-urlencoded", "multipart/form-data", "text/plain"], defaultVal: "application/x-www-form-urlencoded"},
+ encoding: {type: "enum", keywords: ["application/x-www-form-urlencoded", "multipart/form-data", "text/plain"], defaultVal: "application/x-www-form-urlencoded", domAttrName: "enctype"},
+ method: {type: "enum", keywords: ["get", "post", "dialog"], defaultVal: "get"},
+ name: "string",
+ noValidate: "boolean",
+ target: "string",
+ },
+ fieldset: {
+ disabled: "boolean",
+ name: "string",
+ },
+ legend: {
+ // Obsolete
+ align: "string",
+ },
+ label: {
+ htmlFor: {type: "string", domAttrName: "for"},
+ },
+ input: {
+ // Conforming
+ accept: "string",
+ alt: "string",
+ // TODO: autocomplete is special.
+ // autocomplete: {type: "enum", keywords: ["on", "off"], defaultVal: "on"},
+ autofocus: "boolean",
+ defaultChecked: {type: "boolean", domAttrName: "checked"},
+ dirName: "string",
+ disabled: "boolean",
+ // TODO: formAction is special
+ // formAction: "url",
+ formEnctype: {type: "enum", keywords: ["application/x-www-form-urlencoded", "multipart/form-data", "text/plain"], invalidVal: "application/x-www-form-urlencoded"},
+ formMethod: {type: "enum", keywords: ["get", "post"], invalidVal: "get"},
+ formNoValidate: "boolean",
+ formTarget: "string",
+ //TODO: only reflected on setting
+ //height: "unsigned long",
+ inputMode: {type: "enum", keywords: ["verbatim", "latin", "latin-name", "latin-prose", "full-width-latin", "kana", "katakana", "numeric", "tel", "email", "url"]},
+ max: "string",
+ maxLength: "limited long",
+ min: "string",
+ multiple: "boolean",
+ name: "string",
+ pattern: "string",
+ placeholder: "string",
+ readOnly: "boolean",
+ required: "boolean",
+ // https://html.spec.whatwg.org/multipage/#attr-input-size
+ size: {type: "limited unsigned long", defaultVal: 20},
+ src: "url",
+ step: "string",
+ type: {type: "enum", keywords: ["hidden", "text", "search", "tel",
+ "url", "email", "password", "datetime", "date", "month", "week",
+ "time", "datetime-local", "number", "range", "color", "checkbox",
+ "radio", "file", "submit", "image", "reset", "button"], defaultVal:
+ "text"},
+ //TODO: only reflected on setting
+ //width: "unsigned long",
+ defaultValue: {type: "string", domAttrName: "value"},
+
+ // Obsolete
+ align: "string",
+ useMap: "string",
+ },
+ button: {
+ autofocus: "boolean",
+ disabled: "boolean",
+ // TODO: formAction is special
+ // formAction: "url",
+ formEnctype: {type: "enum", keywords: ["application/x-www-form-urlencoded", "multipart/form-data", "text/plain"], invalidVal: "application/x-www-form-urlencoded"},
+ formMethod: {type: "enum", keywords: ["get", "post", "dialog"], invalidVal: "get"},
+ formNoValidate: "boolean",
+ formTarget: "string",
+ name: "string",
+ type: {type: "enum", keywords: ["submit", "reset", "button"], defaultVal: "submit"},
+ value: "string",
+ // TODO: menu
+ },
+ select: {
+ autofocus: "boolean",
+ disabled: "boolean",
+ multiple: "boolean",
+ name: "string",
+ required: "boolean",
+ size: {type: "unsigned long", defaultVal: 0},
+ },
+ datalist: {},
+ optgroup: {
+ disabled: "boolean",
+ label: "string",
+ },
+ option: {
+ disabled: "boolean",
+ label: {type: "string", customGetter: true},
+ defaultSelected: {type: "boolean", domAttrName: "selected"},
+ value: {type: "string", customGetter: true},
+ },
+ textarea: {
+ // TODO: autocomplete is special.
+ // autocomplete: {type: "enum", keywords: ["on", "off"], defaultVal: "on"},
+ autofocus: "boolean",
+ cols: {type: "limited unsigned long", defaultVal: 20},
+ dirName: "string",
+ disabled: "boolean",
+ inputMode: {type: "enum", keywords: ["verbatim", "latin", "latin-name", "latin-prose", "full-width-latin", "kana", "katakana", "numeric", "tel", "email", "url"]},
+ maxLength: "limited long",
+ name: "string",
+ placeholder: "string",
+ readOnly: "boolean",
+ required: "boolean",
+ rows: {type: "limited unsigned long", defaultVal: 2},
+ wrap: "string",
+ },
+ keygen: {
+ autofocus: "boolean",
+ challenge: "string",
+ disabled: "boolean",
+ // The invalid value default is the "unknown" state, which for our
+ // purposes seems to be the same as having no invalid value default.
+ // The missing value default depends on whether "rsa" is implemented,
+ // so we use null, which is magically reserved for "don't try testing
+ // this", since no one default is required. (TODO: we could test that
+ // it's either the RSA state or the unknown state.)
+ keytype: {type: "enum", keywords: ["rsa"], defaultVal: null},
+ name: "string",
+ },
+ output: {
+ htmlFor: {type: "settable tokenlist", domAttrName: "for" },
+ name: "string",
+ },
+ progress: {
+ max: {type: "limited double", defaultVal: 1.0},
+ },
+ meter: {},
+};
+
+mergeElements(formElements);
diff --git a/tests/wpt/web-platform-tests/html/dom/elements-grouping.js b/tests/wpt/web-platform-tests/html/dom/elements-grouping.js
new file mode 100644
index 00000000000..c33f49da1bf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements-grouping.js
@@ -0,0 +1,60 @@
+// Up-to-date as of 2013-04-08.
+var groupingElements = {
+ p: {
+ // Obsolete
+ align: "string",
+ },
+ hr: {
+ // Obsolete
+ align: "string",
+ color: "string",
+ noShade: "boolean",
+ size: "string",
+ width: "string",
+ },
+ pre: {
+ // Obsolete
+ width: "long",
+ },
+ blockquote: {
+ cite: "url",
+ },
+ ol: {
+ // Conforming
+ reversed: "boolean",
+ // TODO: This should have a default value of the list's length if the
+ // reversed attribute is set.
+ start: {type: "long", defaultVal: 1},
+ type: "string",
+
+ // Obsolete
+ compact: "boolean",
+ },
+ ul: {
+ // Obsolete
+ compact: "boolean",
+ type: "string",
+ },
+ li: {
+ // Conforming
+ value: "long",
+
+ // Obsolete
+ type: "string",
+ },
+ dl: {
+ // Obsolete
+ compact: "boolean",
+ },
+ dt: {},
+ dd: {},
+ figure: {},
+ figcaption: {},
+ main: {},
+ div: {
+ // Obsolete
+ align: "string",
+ },
+};
+
+mergeElements(groupingElements);
diff --git a/tests/wpt/web-platform-tests/html/dom/elements-metadata.js b/tests/wpt/web-platform-tests/html/dom/elements-metadata.js
new file mode 100644
index 00000000000..1a8285bc338
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements-metadata.js
@@ -0,0 +1,41 @@
+// Up-to-date as of 2013-04-08.
+var metadataElements = {
+ head: {},
+ title: {},
+ base: {
+ // XXX href is weird. href: "url",
+ target: "string",
+ },
+ link: {
+ // Conforming
+ href: "url",
+ crossOrigin: {type: "enum", keywords: ["anonymous", "use-credentials"], nonCanon:{"": "anonymous"}},
+ rel: "string",
+ relList: {type: "tokenlist", domAttrName: "rel"},
+ media: "string",
+ hreflang: "string",
+ type: "string",
+ sizes: "settable tokenlist",
+
+ // Obsolete
+ charset: "string",
+ rev: "string",
+ target: "string",
+ },
+ meta: {
+ // Conforming
+ name: "string",
+ httpEquiv: {type: "string", domAttrName: "http-equiv"},
+ content: "string",
+
+ // Obsolete
+ scheme: "string",
+ },
+ style: {
+ media: "string",
+ type: "string",
+ scoped: "boolean",
+ },
+};
+
+mergeElements(metadataElements);
diff --git a/tests/wpt/web-platform-tests/html/dom/elements-microdata.js b/tests/wpt/web-platform-tests/html/dom/elements-microdata.js
new file mode 100644
index 00000000000..1680ab79e20
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements-microdata.js
@@ -0,0 +1,35 @@
+// Up-to-date as of 2013-04-19.
+// Things defined in the W3C's microdata draft, not the main HTML5 draft.
+// Note: must be included last so that it hits all elements.
+
+for (var element in elements) {
+ elements[element].itemScope = "boolean";
+ elements[element].itemType = "settable tokenlist";
+ elements[element].itemId = "url";
+ elements[element].itemRef = "settable tokenlist";
+ elements[element].itemProp = "settable tokenlist";
+}
+extraTests.push(function() {
+ // itemValue only reflects in certain circumstances. The syntax for our big
+ // array thing above doesn't currently support one IDL attribute that reflects
+ // different content attributes, so just do this explicitly until that's fixed.
+ var reflectItemValue = function(data, localName, attribute) {
+ var element = document.createElement(localName);
+ element.setAttribute("itemprop", "");
+ ReflectionTests.reflects(data, "itemValue", element, attribute);
+ }
+ reflectItemValue("string", "meta", "content");
+ reflectItemValue("url", "audio", "src");
+ reflectItemValue("url", "embed", "src");
+ reflectItemValue("url", "iframe", "src");
+ reflectItemValue("url", "img", "src");
+ reflectItemValue("url", "source", "src");
+ reflectItemValue("url", "track", "src");
+ reflectItemValue("url", "video", "src");
+ reflectItemValue("url", "a", "href");
+ reflectItemValue("url", "area", "href");
+ reflectItemValue("url", "link", "href");
+ reflectItemValue("url", "object", "data");
+ reflectItemValue("string", "data", "value");
+ //TODO: time is more complex
+});
diff --git a/tests/wpt/web-platform-tests/html/dom/elements-misc.js b/tests/wpt/web-platform-tests/html/dom/elements-misc.js
new file mode 100644
index 00000000000..b495d83d4ce
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements-misc.js
@@ -0,0 +1,58 @@
+// Up-to-date as of 2013-04-09.
+var miscElements = {
+ // "The root element" section
+ html: {
+ // Obsolete
+ version: "string",
+ },
+
+ // "Scripting" section
+ script: {
+ src: "url",
+ type: "string",
+ charset: "string",
+ // TODO: async attribute (complicated).
+ defer: "boolean",
+ crossOrigin: {type: "enum", keywords: ["anonymous", "use-credentials"], nonCanon:{"": "anonymous"}},
+ },
+ noscript: {},
+
+ // "Edits" section
+ ins: {
+ cite: "url",
+ dateTime: "string",
+ },
+ del: {
+ cite: "url",
+ dateTime: "string",
+ },
+
+ // "Interactive elements" section
+ details: {
+ open: "boolean",
+ },
+ summary: {},
+ menu: {
+ // Conforming
+ //TODO: check that missing value default is popup if parent's type is popup
+ type: {type: "enum", keywords:["popup", "toolbar"], defaultVal: "toolbar"},
+ label: "string",
+
+ // Obsolete
+ compact: "boolean",
+ },
+ menuitem: {
+ type: {type: "enum", keywords: ["command", "checkbox", "radio"], defaultVal: "command"},
+ label: "string",
+ icon: "url",
+ disabled: "boolean",
+ checked: "boolean",
+ radiogroup: "string",
+ "default": "boolean",
+ },
+
+ // Global attributes should exist even on unknown elements
+ undefinedelement: {},
+};
+
+mergeElements(miscElements);
diff --git a/tests/wpt/web-platform-tests/html/dom/elements-obsolete.js b/tests/wpt/web-platform-tests/html/dom/elements-obsolete.js
new file mode 100644
index 00000000000..820e2909d06
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements-obsolete.js
@@ -0,0 +1,52 @@
+// Up-to-date as of 2013-04-13.
+var obsoleteElements = {
+ applet: {
+ align: "string",
+ alt: "string",
+ archive: "string",
+ code: "string",
+ codeBase: "url",
+ height: "string",
+ hspace: "unsigned long",
+ name: "string",
+ object: "url",
+ vspace: "unsigned long",
+ width: "string",
+ },
+ marquee: {
+ behavior: "string",
+ bgColor: "string",
+ direction: "string",
+ height: "string",
+ hspace: "unsigned long",
+ scrollAmount: {type: "unsigned long", defaultVal: 6},
+ scrollDelay: {type: "unsigned long", defaultVal: 85},
+ trueSpeed: "boolean",
+ vspace: "unsigned long",
+ width: "string",
+ },
+ frameset: {
+ cols: "string",
+ rows: "string",
+ },
+ frame: {
+ name: "string",
+ scrolling: "string",
+ src: "url",
+ frameBorder: "string",
+ longDesc: "url",
+ noResize: "boolean",
+ marginHeight: {type: "string", treatNullAsEmptyString: true},
+ marginWidth: {type: "string", treatNullAsEmptyString: true},
+ },
+ dir: {
+ compact: "boolean",
+ },
+ font: {
+ color: {type: "string", treatNullAsEmptyString: true},
+ face: "string",
+ size: "string",
+ },
+};
+
+mergeElements(obsoleteElements);
diff --git a/tests/wpt/web-platform-tests/html/dom/elements-sections.js b/tests/wpt/web-platform-tests/html/dom/elements-sections.js
new file mode 100644
index 00000000000..a22aed9f696
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements-sections.js
@@ -0,0 +1,63 @@
+// Up-to-date as of 2013-04-12.
+var sectionElements = {
+ body: {
+ // Obsolete
+ text: {type: "string", treatNullAsEmptyString: true},
+ link: {type: "string", treatNullAsEmptyString: true},
+ vLink: {type: "string", treatNullAsEmptyString: true},
+ aLink: {type: "string", treatNullAsEmptyString: true},
+ bgColor: {type: "string", treatNullAsEmptyString: true},
+ background: "string",
+ },
+ article: {},
+ section: {},
+ nav: {},
+ aside: {},
+ h1: {
+ // Obsolete
+ align: "string",
+ },
+ h2: {
+ // Obsolete
+ align: "string",
+ },
+ h3: {
+ // Obsolete
+ align: "string",
+ },
+ h4: {
+ // Obsolete
+ align: "string",
+ },
+ h5: {
+ // Obsolete
+ align: "string",
+ },
+ h6: {
+ // Obsolete
+ align: "string",
+ },
+ hgroup: {},
+ header: {},
+ footer: {},
+ address: {},
+};
+
+mergeElements(sectionElements);
+
+extraTests.push(function() {
+ ReflectionTests.reflects({type: "enum", keywords: ["ltr", "rtl", "auto"]}, "dir", document, "dir", document.documentElement);
+ // TODO: these behave differently if the body element is a frameset. Also
+ // should probably test with multiple bodies.
+ ReflectionTests.reflects({type: "string", treatNullAsEmptyString: true}, "fgColor", document, "text", document.body);
+ ReflectionTests.reflects({type: "string", treatNullAsEmptyString: true}, "linkColor", document, "link", document.body);
+ ReflectionTests.reflects({type: "string", treatNullAsEmptyString: true}, "vlinkColor", document, "vlink", document.body);
+ ReflectionTests.reflects({type: "string", treatNullAsEmptyString: true}, "alinkColor", document, "alink", document.body);
+ ReflectionTests.reflects({type: "string", treatNullAsEmptyString: true}, "bgColor", document, "bgcolor", document.body);
+ // Don't mess up the colors :)
+ document.documentElement.removeAttribute("dir");
+ var attrs = ["text", "bgcolor", "link", "alink", "vlink"];
+ for (var i = 0; i < attrs.length; i++) {
+ document.body.removeAttribute(attrs[i]);
+ }
+});
diff --git a/tests/wpt/web-platform-tests/html/dom/elements-tabular.js b/tests/wpt/web-platform-tests/html/dom/elements-tabular.js
new file mode 100644
index 00000000000..9feff99f105
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements-tabular.js
@@ -0,0 +1,120 @@
+// Up-to-date as of 2013-04-12.
+var tabularElements = {
+ table: {
+ // Conforming
+ sortable: "boolean",
+
+ // Obsolete
+ align: "string",
+ border: "string",
+ frame: "string",
+ rules: "string",
+ summary: "string",
+ width: "string",
+ bgColor: {type: "string", treatNullAsEmptyString: true},
+ cellPadding: {type: "string", treatNullAsEmptyString: true},
+ cellSpacing: {type: "string", treatNullAsEmptyString: true},
+ },
+ caption: {
+ // Obsolete
+ align: "string",
+ },
+ colgroup: {
+ span: "limited unsigned long",
+
+ // Obsolete
+ align: "string",
+ ch: {type: "string", domAttrName: "char"},
+ chOff: {type: "string", domAttrName: "charoff"},
+ vAlign: "string",
+ width: "string",
+ },
+ col: {
+ // Conforming
+ span: "limited unsigned long",
+
+ // Obsolete
+ align: "string",
+ ch: {type: "string", domAttrName: "char"},
+ chOff: {type: "string", domAttrName: "charoff"},
+ vAlign: "string",
+ width: "string",
+ },
+ tbody: {
+ // Obsolete
+ align: "string",
+ ch: {type: "string", domAttrName: "char"},
+ chOff: {type: "string", domAttrName: "charoff"},
+ vAlign: "string",
+ },
+ thead: {
+ // Obsolete
+ align: "string",
+ ch: {type: "string", domAttrName: "char"},
+ chOff: {type: "string", domAttrName: "charoff"},
+ vAlign: "string",
+ },
+ tfoot: {
+ // Obsolete
+ align: "string",
+ ch: {type: "string", domAttrName: "char"},
+ chOff: {type: "string", domAttrName: "charoff"},
+ vAlign: "string",
+ },
+ tr: {
+ // Obsolete
+ align: "string",
+ ch: {type: "string", domAttrName: "char"},
+ chOff: {type: "string", domAttrName: "charoff"},
+ vAlign: "string",
+ bgColor: {type: "string", treatNullAsEmptyString: true},
+ },
+ td: {
+ // HTMLTableCellElement (Conforming)
+ colSpan: {type: "unsigned long", defaultVal: 1},
+ rowSpan: {type: "unsigned long", defaultVal: 1},
+ headers: "settable tokenlist",
+
+ // HTMLTableCellElement (Obsolete)
+ align: "string",
+ axis: "string",
+ height: "string",
+ width: "string",
+ ch: {type: "string", domAttrName: "char"},
+ chOff: {type: "string", domAttrName: "charoff"},
+ noWrap: "boolean",
+ vAlign: "string",
+ bgColor: {type: "string", treatNullAsEmptyString: true},
+
+ // HTMLTableDataCellElement (Obsolete)
+ abbr: "string",
+ },
+ th: {
+ // HTMLTableCellElement (Conforming)
+ colSpan: {type: "unsigned long", defaultVal: 1},
+ rowSpan: {type: "unsigned long", defaultVal: 1},
+ headers: "settable tokenlist",
+
+ // HTMLTableCellElement (Obsolete)
+ align: "string",
+ axis: "string",
+ height: "string",
+ width: "string",
+ ch: {type: "string", domAttrName: "char"},
+ chOff: {type: "string", domAttrName: "charoff"},
+ noWrap: "boolean",
+ vAlign: "string",
+ bgColor: {type: "string", treatNullAsEmptyString: true},
+
+ // HTMLTableHeaderCellElement (Conforming)
+ // TODO: double-check that the way we're treating missing value
+ // defaults is consistent here. scope has an auto state with no
+ // associated keyword, which is the missing value default -- is this
+ // the right syntax for that?
+ scope: {type: "enum", keywords: ["row", "col", "rowgroup", "colgroup"]},
+ abbr: "string",
+ sorted: "string",
+ },
+};
+
+mergeElements(tabularElements);
diff --git a/tests/wpt/web-platform-tests/html/dom/elements-text.js b/tests/wpt/web-platform-tests/html/dom/elements-text.js
new file mode 100644
index 00000000000..bcfcb8f00ff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements-text.js
@@ -0,0 +1,64 @@
+// Up-to-date as of 2013-04-19.
+var textElements = {
+ a: {
+ // Conforming
+ target: "string",
+ download: "string",
+ ping: "urls",
+ rel: "string",
+ relList: {type: "tokenlist", domAttrName: "rel"},
+ hreflang: "string",
+ type: "string",
+
+ // URLUtils
+ href: "url",
+
+ // Obsolete
+ coords: "string",
+ charset: "string",
+ name: "string",
+ rev: "string",
+ shape: "string",
+ },
+ em: {},
+ strong: {},
+ small: {},
+ s: {},
+ cite: {},
+ q: {
+ cite: "url",
+ },
+ dfn: {},
+ abbr: {},
+ data: {
+ value: "string",
+ },
+ time: {
+ dateTime: "string",
+ },
+ code: {},
+ // Opera 11.50 doesn't allow unquoted "var" here, although ES5 does and
+ // other browsers support it.
+ "var": {},
+ samp: {},
+ kbd: {},
+ sub: {},
+ sup: {},
+ i: {},
+ b: {},
+ u: {},
+ mark: {},
+ ruby: {},
+ rt: {},
+ rp: {},
+ bdi: {},
+ bdo: {},
+ span: {},
+ br: {
+ // Obsolete
+ clear: "string",
+ },
+ wbr: {},
+};
+
+mergeElements(textElements);
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/.gitkeep b/tests/wpt/web-platform-tests/html/dom/elements/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/content-models/.gitkeep b/tests/wpt/web-platform-tests/html/dom/elements/content-models/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/content-models/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/content-models/contains.json b/tests/wpt/web-platform-tests/html/dom/elements/content-models/contains.json
new file mode 100644
index 00000000000..42f158d3674
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/content-models/contains.json
@@ -0,0 +1,48 @@
+[
+ {
+ "id": "kinds-of-content",
+ "original_id": "kinds-of-content",
+ "children": [
+ {
+ "id": "metadata-content",
+ "original_id": "metadata-content"
+ },
+ {
+ "id": "flow-content",
+ "original_id": "flow-content"
+ },
+ {
+ "id": "sectioning-content",
+ "original_id": "sectioning-content"
+ },
+ {
+ "id": "heading-content",
+ "original_id": "heading-content"
+ },
+ {
+ "id": "phrasing-content",
+ "original_id": "phrasing-content"
+ },
+ {
+ "id": "embedded-content",
+ "original_id": "embedded-content"
+ },
+ {
+ "id": "interactive-content",
+ "original_id": "interactive-content"
+ },
+ {
+ "id": "palpable-content",
+ "original_id": "palpable-content"
+ }
+ ]
+ },
+ {
+ "id": "transparent-content-models",
+ "original_id": "transparent-content-models"
+ },
+ {
+ "id": "paragraphs",
+ "original_id": "paragraphs"
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/element-definitions/.gitkeep b/tests/wpt/web-platform-tests/html/dom/elements/element-definitions/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/element-definitions/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/element-definitions/contains.json b/tests/wpt/web-platform-tests/html/dom/elements/element-definitions/contains.json
new file mode 100644
index 00000000000..a942e85a239
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/element-definitions/contains.json
@@ -0,0 +1,6 @@
+[
+ {
+ "id": "attributes",
+ "original_id": "attributes"
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/elements-in-the-dom/.gitkeep b/tests/wpt/web-platform-tests/html/dom/elements/elements-in-the-dom/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/elements-in-the-dom/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/elements-in-the-dom/unknown-element.html b/tests/wpt/web-platform-tests/html/dom/elements/elements-in-the-dom/unknown-element.html
new file mode 100644
index 00000000000..907b14837a6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/elements-in-the-dom/unknown-element.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<title>HTMLUnknownElement</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#htmlunknownelement">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ var elt = document.createElement("xxx");
+ assert_true(window.HTMLUnknownElement && elt instanceof HTMLUnknownElement,
+ "not an instance of HTMLUnknownElement");
+ assert_true(window.HTMLSpanElement && !(elt instanceof HTMLSpanElement),
+ "an instance of HTMLSpanElement");
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/.gitkeep b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/.htaccess b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/.htaccess
new file mode 100644
index 00000000000..94e9a4f1908
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/.htaccess
@@ -0,0 +1,16 @@
+AddType 'text/html; charset=UTF-8' html
+<Files 'the-lang-attribute-003.html'>
+AddLanguage 'ko' .html
+</Files>
+<Files 'the-lang-attribute-005.html'>
+AddLanguage 'zh' .html
+</Files>
+<Files 'the-lang-attribute-006.html'>
+AddLanguage 'zh' .html
+</Files>
+<Files 'the-lang-attribute-009.html'>
+AddLanguage 'ko' .html
+</Files>
+<Files 'the-lang-attribute-011.html'>
+AddLanguage 'ko,zh,ja' .html
+</Files>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/classlist-nonstring.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/classlist-nonstring.html
new file mode 100644
index 00000000000..5b0560b3172
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/classlist-nonstring.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<title>classList: non-string contains</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#classes">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#domtokenlist">
+<link rel="help" href="https://heycam.github.io/webidl/#es-DOMString">
+<link rel="help" href="http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf#page=57">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<div id="test">
+<ul>
+<li class=undefined>
+<li class=null>
+<li class=0>
+<li class=NaN>
+<li class=Infinity>
+<li class=-Infinity>
+</ul>
+<script>
+var items = document.getElementById("test")
+ .getElementsByTagName("li");
+var tests = [undefined, null, -0, +0, NaN, +Infinity, -Infinity];
+var results = [
+ [true, false, false, false, false, false, false], // "undefined"
+ [false, true, false, false, false, false, false], // "null"
+ [false, false, true, true, false, false, false], // "0"
+ [false, false, false, false, true, false, false], // "NaN"
+ [false, false, false, false, false, true, false], // "Infinity"
+ [false, false, false, false, false, false, true ] // "-Infinity"
+];
+</script>
+</div>
+<script>
+test(function() {
+ for (var i = 0, il = items.length; i < il; ++i) {
+ test(function() {
+ for (var j = 0, jl = tests.length; j < jl; ++j) {
+ assert_equals(items[i].classList.contains(tests[j]), results[i][j]);
+ }
+ })
+ }
+})
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/contains.json b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/contains.json
new file mode 100644
index 00000000000..c413488b504
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/contains.json
@@ -0,0 +1,38 @@
+[
+ {
+ "id": "the-id-attribute",
+ "original_id": "the-id-attribute"
+ },
+ {
+ "id": "the-title-attribute",
+ "original_id": "the-title-attribute"
+ },
+ {
+ "id": "the-lang-and-xml-lang-attributes",
+ "original_id": "the-lang-and-xml:lang-attributes"
+ },
+ {
+ "id": "the-translate-attribute",
+ "original_id": "the-translate-attribute"
+ },
+ {
+ "id": "the-xml-base-attribute-xml-only",
+ "original_id": "the-xml:base-attribute-(xml-only)"
+ },
+ {
+ "id": "the-dir-attribute",
+ "original_id": "the-dir-attribute"
+ },
+ {
+ "id": "classes",
+ "original_id": "classes"
+ },
+ {
+ "id": "the-style-attribute",
+ "original_id": "the-style-attribute"
+ },
+ {
+ "id": "embedding-custom-non-visible-data-with-the-data-attributes",
+ "original_id": "embedding-custom-non-visible-data-with-the-data-*-attributes"
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/custom-attrs.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/custom-attrs.html
new file mode 100644
index 00000000000..a1e41dac256
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/custom-attrs.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Element Custom Attributes</title>
+ <link rel="author" title="Bruno de Oliveira Abinader" href="mailto:bruno.d@partner.samsung.com">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-dataset">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#xml">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/dom/nodes/attributes.js"></script>
+ </head>
+ <body>
+ <h1>Element Custom Attributes</h1>
+ <div id="log"></div>
+ <script>
+ test(function() {
+ var div = document.createElement("div");
+ div.setAttributeNS("foo", "data-my-custom-attr", "first");
+ div.setAttributeNS("bar", "data-my-custom-attr", "second");
+ div.dataset.myCustomAttr = "third";
+
+ assert_equals(div.attributes.length, 3);
+ attributes_are(div, [["data-my-custom-attr", "first", "foo"],
+ ["data-my-custom-attr", "second", "bar"],
+ ["data-my-custom-attr", "third", null]]);
+ }, "Setting an Element's dataset property should not interfere with namespaced attributes with same name");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/data_unicode_attr.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/data_unicode_attr.html
new file mode 100644
index 00000000000..17077dafd1f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/data_unicode_attr.html
@@ -0,0 +1,22 @@
+<!DOCTYPE HTML>
+<meta charset="utf-8">
+<title>HTML Test: dataset attribute</title>
+<link rel="author" title="ElegantPig" href="mailto:neil.ep@hotmail.com">
+<link rel="author" title="Xiaojun Wu" href="mailto:xiaojunx.a.wu@intel.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id='log'></div>
+<div id="d1" data-weapons="laser 2" data-中文属性="中文"></div>
+<script>
+
+test(function() {
+ var d1 = document.getElementById("d1");
+ assert_equals(d1.dataset.weapons, "laser 2");
+}, "dataset - SBCS");
+
+test(function() {
+ var d1 = document.getElementById("d1");
+ assert_equals(d1.dataset.中文属性, "中文");
+}, "dataset - UNICODE");
+
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dataset-delete.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dataset-delete.html
new file mode 100644
index 00000000000..65e131f445a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dataset-delete.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Dataset - Delete</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <h1>Dataset - Delete</h1>
+ <div id="log"></div>
+ <script>
+ function testDelete(attr, prop)
+ {
+ var d = document.createElement("div");
+ d.setAttribute(attr, "value");
+ delete d.dataset[prop];
+ return d.hasAttribute(attr) === false && d.getAttribute(attr) != "value";
+ }
+
+ function testDeleteNoAdd(prop)
+ {
+ var d = document.createElement("div");
+ delete d.dataset[prop];
+ return true;
+ }
+
+ test(function() { assert_true(testDelete('data-foo', 'foo')); },
+ "Deleting element.dataset['foo'] should also remove an attribute with name 'data-foo' should it exist.");
+ test(function() { assert_true(testDelete('data-foo-bar', 'fooBar')); },
+ "Deleting element.dataset['fooBar'] should also remove an attribute with name 'data-foo-bar' should it exist.");
+ test(function() { assert_true(testDelete('data--', '-')); },
+ "Deleting element.dataset['-'] should also remove an attribute with name 'data--' should it exist.");
+ test(function() { assert_true(testDelete('data--foo', 'Foo')); },
+ "Deleting element.dataset['Foo'] should also remove an attribute with name 'data--foo' should it exist.");
+ test(function() { assert_true(testDeleteNoAdd('data--foo', '-foo')); },
+ "Deleting element.dataset['-foo'] should also remove an attribute with name 'data--foo' should it exist.");
+ test(function() { assert_true(testDelete('data---foo', '-Foo')); },
+ "Deleting element.dataset['-Foo'] should also remove an attribute with name 'data---foo' should it exist.");
+ test(function() { assert_true(testDelete('data-', '')); },
+ "Deleting element.dataset[''] should also remove an attribute with name 'data-' should it exist.");
+ test(function() { assert_true(testDelete('data-\xE0', '\xE0')); },
+ "Deleting element.dataset['\xE0'] should also remove an attribute with name 'data-\xE0' should it exist.");
+ test(function() { assert_true(testDeleteNoAdd('foo')); },
+ "Deleting element.dataset['foo'] should not throw if even if the element does now have an attribute with the name data-foo.");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dataset-enumeration.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dataset-enumeration.html
new file mode 100644
index 00000000000..4b1063379c7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dataset-enumeration.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Dataset - Enumeration</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <h1>Dataset - Enumeration</h1>
+ <div id="log"></div>
+ <script>
+ function testEnumeration(array)
+ {
+ var d = document.createElement("div");
+ for (var i = 0; i < array.length; ++i)
+ d.setAttribute(array[i], "value");
+
+ var count = 0;
+ for (var item in d.dataset)
+ count++;
+
+ return count;
+ }
+
+ test(function() { assert_equals(testEnumeration(['data-foo', 'data-bar', 'data-baz']), 3); },
+ "A dataset should be enumeratable.");
+ test(function() { assert_equals(testEnumeration(['data-foo', 'data-bar', 'dataFoo']), 2); },
+ "Only attributes who qualify as dataset properties should be enumeratable in the dataset.");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dataset-get.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dataset-get.html
new file mode 100644
index 00000000000..ab4078c4fbf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dataset-get.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Dataset - Get</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <h1>Dataset - Get</h1>
+ <div id="log"></div>
+ <script>
+ function testGet(attr, expected)
+ {
+ var d = document.createElement("div");
+ d.setAttribute(attr, "value");
+ return d.dataset[expected] == "value";
+ }
+
+ test(function() { assert_true(testGet('data-foo', 'foo')); },
+ "Getting element.dataset['foo'] should return the value of element.getAttribute('data-foo')'");
+ test(function() { assert_true(testGet('data-foo-bar', 'fooBar')); },
+ "Getting element.dataset['fooBar'] should return the value of element.getAttribute('data-foo-bar')'");
+ test(function() { assert_true(testGet('data--', '-')); },
+ "Getting element.dataset['-'] should return the value of element.getAttribute('data--')'");
+ test(function() { assert_true(testGet('data--foo', 'Foo')); },
+ "Getting element.dataset['Foo'] should return the value of element.getAttribute('data--foo')'");
+ test(function() { assert_true(testGet('data---foo', '-Foo')); },
+ "Getting element.dataset['-Foo'] should return the value of element.getAttribute('data---foo')'");
+ test(function() { assert_true(testGet('data-Foo', 'foo')); },
+ "Getting element.dataset['foo'] should return the value of element.getAttribute('data-Foo')'");
+ test(function() { assert_true(testGet('data-', '')); },
+ "Getting element.dataset[''] should return the value of element.getAttribute('data-')'");
+ test(function() { assert_true(testGet('data-\xE0', '\xE0')); },
+ "Getting element.dataset['\xE0'] should return the value of element.getAttribute('data-\xE0')'");
+ test(function() { assert_true(testGet('data-to-string', 'toString')); },
+ "Getting element.dataset['toString'] should return the value of element.getAttribute('data-to-string')'");
+
+ function matchesNothingInDataset(attr)
+ {
+ var d = document.createElement("div");
+ d.setAttribute(attr, "value");
+
+ if (!d.dataset)
+ return false;
+
+ var count = 0;
+ for (var item in d.dataset)
+ count++;
+ return count == 0;
+ }
+
+ test(function() { assert_true(matchesNothingInDataset('dataFoo')); },
+ "Tests that an attribute named dataFoo does not make an entry in the dataset DOMStringMap.");
+
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dataset-prototype.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dataset-prototype.html
new file mode 100644
index 00000000000..6b166184612
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dataset-prototype.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Dataset - element.dataset is an instance of DOMStringMap</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <h1>Dataset - element.dataset is an instance of DOMStringMap</h1>
+ <div id="log"></div>
+ <script>
+ test(function() { assert_true(document.createElement("div").dataset instanceof window.DOMStringMap); },
+ "An elements dataset property is an instance of a DOMStringMap");
+ test(function() {
+ var dataset = document.createElement("div").dataset;
+ assert_true("toString" in dataset, '"toString" in dataset');
+ assert_equals(dataset.toString, Object.prototype.toString);
+ assert_false("expando" in dataset, '"expando" in dataset');
+ assert_equals(dataset.expando, undefined);
+ Object.prototype.expando = 42;
+ assert_true("expando" in dataset, '"expando" in dataset');
+ assert_equals(dataset.expando, 42);
+ }, "Properties on Object.prototype should shine through.");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dataset-set.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dataset-set.html
new file mode 100644
index 00000000000..722b17977e4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dataset-set.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Dataset - Set</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <h1>Dataset - Set</h1>
+ <div id="log"></div>
+ <script>
+ function testSet(prop, expected)
+ {
+ var d = document.createElement("div");
+ d.dataset[prop] = "value";
+ return d.getAttribute(expected) == "value";
+ }
+
+ test(function() { assert_true(testSet('foo', 'data-foo')); },
+ "Setting element.dataset['foo'] should also change the value of element.getAttribute('data-foo')'");
+ test(function() { assert_true(testSet('fooBar', 'data-foo-bar')); },
+ "Setting element.dataset['fooBar'] should also change the value of element.getAttribute('data-foo-bar')'");
+ test(function() { assert_true(testSet('-', 'data--')); },
+ "Setting element.dataset['-'] should also change the value of element.getAttribute('data--')'");
+ test(function() { assert_true(testSet('Foo', 'data--foo')); },
+ "Setting element.dataset['Foo'] should also change the value of element.getAttribute('data--foo')'");
+ test(function() { assert_true(testSet('-Foo', 'data---foo')); },
+ "Setting element.dataset['-Foo'] should also change the value of element.getAttribute('data---foo')'");
+ test(function() { assert_true(testSet('', 'data-')); },
+ "Setting element.dataset[''] should also change the value of element.getAttribute('data-')'");
+ test(function() { assert_true(testSet('\xE0', 'data-\xE0')); },
+ "Setting element.dataset['\xE0'] should also change the value of element.getAttribute('data-\xE0')'");
+ test(function() { assert_throws('SYNTAX_ERR', function() { testSet('-foo', 'dummy') }); },
+ "Setting element.dataset['-foo'] should throw a SYNTAX_ERR'");
+ test(function() { assert_throws('INVALID_CHARACTER_ERR', function() { testSet('foo\x20', 'dummy') }); },
+ "Setting element.dataset['foo\x20'] should throw an INVALID_CHARACTER_ERR'");
+ test(function() { assert_throws('INVALID_CHARACTER_ERR', function() { testSet('foo\uF900', 'dummy') }); },
+ "Setting element.dataset['foo\uF900'] should throw an INVALID_CHARACTER_ERR'");
+
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dataset.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dataset.html
new file mode 100644
index 00000000000..fe3e032d528
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dataset.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<title>dataset: should return 'undefined' for non-existent properties</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var div = document.createElement("div");
+test(function() {
+ assert_false("foo" in div.dataset);
+ assert_equals(div.dataset.foo, undefined);
+}, "Should return 'undefined' before setting an attribute")
+test(function() {
+ div.setAttribute("data-foo", "value");
+ assert_true("foo" in div.dataset);
+ assert_equals(div.dataset.foo, "value");
+}, "Should return 'value' if that's the value")
+test(function() {
+ div.setAttribute("data-foo", "");
+ assert_true("foo" in div.dataset);
+ assert_equals(div.dataset.foo, "");
+}, "Should return the empty string if that's the value")
+test(function() {
+ div.removeAttribute("data-foo");
+ assert_false("foo" in div.dataset);
+ assert_equals(div.dataset.foo, undefined);
+}, "Should return 'undefined' after removing an attribute")
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-EN-L-ref.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-EN-L-ref.html
new file mode 100644
index 00000000000..3dfe4db839c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-EN-L-ref.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: dir=auto, start with EN, then L</title>
+ <link rel="match" href="dir_auto-EN-L-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of the text.
+ In this test, it is the Latin letter A since digits are not strongly
+ directional, thus the direction must be resolved as LTR." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <p dir="ltr">123ABC&#x05D0;&#x05D1;&#x05D2;.</p>
+ </div>
+ <div dir="rtl">
+ <p dir="ltr">123ABC&#x05D0;&#x05D1;&#x05D2;.</p>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <p dir="ltr">123ABC&#x05D0;&#x05D1;&#x05D2;.</p>
+ </div>
+ <div dir="rtl">
+ <p dir="ltr">123ABC&#x05D0;&#x05D1;&#x05D2;.</p>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-EN-L.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-EN-L.html
new file mode 100644
index 00000000000..fa8d793bd04
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-EN-L.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: dir=auto, start with EN, then L</title>
+ <link rel="match" href="dir_auto-EN-L-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of the text.
+ In this test, it is the Latin letter A since digits are not strongly
+ directional, thus the direction must be resolved as LTR." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <p dir="auto">123ABC&#x05D0;&#x05D1;&#x05D2;.</p>
+ </div>
+ <div dir="rtl">
+ <p dir="auto">123ABC&#x05D0;&#x05D1;&#x05D2;.</p>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <p dir="ltr">123ABC&#x05D0;&#x05D1;&#x05D2;.</p>
+ </div>
+ <div dir="rtl">
+ <p dir="ltr">123ABC&#x05D0;&#x05D1;&#x05D2;.</p>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-EN-R-ref.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-EN-R-ref.html
new file mode 100644
index 00000000000..f91155bc898
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-EN-R-ref.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: dir=auto, start with EN, then R</title>
+ <link rel="match" href="dir_auto-EN-R-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of the text.
+ In this test, it is the Hebrew letter Alef since digits are not strongly
+ directional, thus the direction must be resolved as RTL." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <p dir="rtl">123&#x05D0;&#x05D1;&#x05D2;ABC.</p>
+ </div>
+ <div dir="rtl">
+ <p dir="rtl">123&#x05D0;&#x05D1;&#x05D2;ABC.</p>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <p dir="rtl">123&#x05D0;&#x05D1;&#x05D2;ABC.</p>
+ </div>
+ <div dir="rtl">
+ <p dir="rtl">123&#x05D0;&#x05D1;&#x05D2;ABC.</p>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-EN-R.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-EN-R.html
new file mode 100644
index 00000000000..7165de583dd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-EN-R.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: dir=auto, start with EN, then R</title>
+ <link rel="match" href="dir_auto-EN-R-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of the text.
+ In this test, it is the Hebrew letter Alef since digits are not strongly
+ directional, thus the direction must be resolved as RTL." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <p dir="auto">123&#x05D0;&#x05D1;&#x05D2;ABC.</p>
+ </div>
+ <div dir="rtl">
+ <p dir="auto">123&#x05D0;&#x05D1;&#x05D2;ABC.</p>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <p dir="rtl">123&#x05D0;&#x05D1;&#x05D2;ABC.</p>
+ </div>
+ <div dir="rtl">
+ <p dir="rtl">123&#x05D0;&#x05D1;&#x05D2;ABC.</p>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-L-ref.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-L-ref.html
new file mode 100644
index 00000000000..2e85732ec22
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-L-ref.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: dir=auto, start with L</title>
+ <link rel="match" href="dir_auto-L-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of the text.
+ In this test, it is the Latin letter A, thus the direction must be
+ resolved as LTR." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <p dir="ltr">ABC&#x05D0;&#x05D1;&#x05D2;.</p>
+ </div>
+ <div dir="rtl">
+ <p dir="ltr">ABC&#x05D0;&#x05D1;&#x05D2;.</p>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <p dir="ltr">ABC&#x05D0;&#x05D1;&#x05D2;.</p>
+ </div>
+ <div dir="rtl">
+ <p dir="ltr">ABC&#x05D0;&#x05D1;&#x05D2;.</p>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-L.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-L.html
new file mode 100644
index 00000000000..3896bcb76bd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-L.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: dir=auto, start with L</title>
+ <link rel="match" href="dir_auto-L-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of the text.
+ In this test, it is the Latin letter A, thus the direction must be
+ resolved as LTR." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <p dir="auto">ABC&#x05D0;&#x05D1;&#x05D2;.</p>
+ </div>
+ <div dir="rtl">
+ <p dir="auto">ABC&#x05D0;&#x05D1;&#x05D2;.</p>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <p dir="ltr">ABC&#x05D0;&#x05D1;&#x05D2;.</p>
+ </div>
+ <div dir="rtl">
+ <p dir="ltr">ABC&#x05D0;&#x05D1;&#x05D2;.</p>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-N-EN-L-ref.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-N-EN-L-ref.html
new file mode 100644
index 00000000000..818cd74f9fb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-N-EN-L-ref.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: dir=auto, start with N, then EN, then L</title>
+ <link rel="match" href="dir_auto-N-EN-L-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of the text.
+ In this test, it is the Latin letter A since neutrals and digits are not
+ strongly directional, thus the direction must be resolved as LTR." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <p dir="ltr">.-=123ABC&#x05D0;&#x05D1;&#x05D2;.</p>
+ </div>
+ <div dir="rtl">
+ <p dir="ltr">.-=123ABC&#x05D0;&#x05D1;&#x05D2;.</p>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <p dir="ltr">.-=123ABC&#x05D0;&#x05D1;&#x05D2;.</p>
+ </div>
+ <div dir="rtl">
+ <p dir="ltr">.-=123ABC&#x05D0;&#x05D1;&#x05D2;.</p>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-N-EN-L.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-N-EN-L.html
new file mode 100644
index 00000000000..21ca0338dc4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-N-EN-L.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: dir=auto, start with N, then EN, then L</title>
+ <link rel="match" href="dir_auto-N-EN-L-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of the text.
+ In this test, it is the Latin letter A since neutrals and digits are not
+ strongly directional, thus the direction must be resolved as LTR." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <p dir="auto">.-=123ABC&#x05D0;&#x05D1;&#x05D2;.</p>
+ </div>
+ <div dir="rtl">
+ <p dir="auto">.-=123ABC&#x05D0;&#x05D1;&#x05D2;.</p>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <p dir="ltr">.-=123ABC&#x05D0;&#x05D1;&#x05D2;.</p>
+ </div>
+ <div dir="rtl">
+ <p dir="ltr">.-=123ABC&#x05D0;&#x05D1;&#x05D2;.</p>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-N-EN-R-ref.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-N-EN-R-ref.html
new file mode 100644
index 00000000000..2b6b2fd7e18
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-N-EN-R-ref.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: dir=auto, start with N, then EN, then R</title>
+ <link rel="match" href="dir_auto-N-EN-R-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of the text.
+ In this test, it is the Hebrew letter Alef since neutrals and digits are not
+ strongly directional, thus the direction must be resolved as RTL." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <p dir="rtl">.-=123&#x05D0;&#x05D1;&#x05D2;ABC.</p>
+ </div>
+ <div dir="rtl">
+ <p dir="rtl">.-=123&#x05D0;&#x05D1;&#x05D2;ABC.</p>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <p dir="rtl">.-=123&#x05D0;&#x05D1;&#x05D2;ABC.</p>
+ </div>
+ <div dir="rtl">
+ <p dir="rtl">.-=123&#x05D0;&#x05D1;&#x05D2;ABC.</p>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-N-EN-R.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-N-EN-R.html
new file mode 100644
index 00000000000..b10a52b1a8c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-N-EN-R.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: dir=auto, start with N, then EN, then R</title>
+ <link rel="match" href="dir_auto-N-EN-R-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of the text.
+ In this test, it is the Hebrew letter Alef since neutrals and digits are not
+ strongly directional, thus the direction must be resolved as RTL." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <p dir="auto">.-=123&#x05D0;&#x05D1;&#x05D2;ABC.</p>
+ </div>
+ <div dir="rtl">
+ <p dir="auto">.-=123&#x05D0;&#x05D1;&#x05D2;ABC.</p>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <p dir="rtl">.-=123&#x05D0;&#x05D1;&#x05D2;ABC.</p>
+ </div>
+ <div dir="rtl">
+ <p dir="rtl">.-=123&#x05D0;&#x05D1;&#x05D2;ABC.</p>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-N-EN-ref.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-N-EN-ref.html
new file mode 100644
index 00000000000..154d56aaf9a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-N-EN-ref.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: dir=auto, start with N, then EN, then L</title>
+ <link rel="match" href="dir_auto-N-EN-L-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of the text, ignoring neutrals and numbers.
+ If there is no strong character, as in this test, the direction defaults to LTR." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="test">
+ <div dir="ltr">
+ <p dir="ltr">@123!</p>
+ </div>
+ <div dir="rtl">
+ <p dir="ltr">@123!</p>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <p dir="ltr">@123!</p>
+ </div>
+ <div dir="rtl">
+ <p dir="ltr">@123!</p>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-N-EN.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-N-EN.html
new file mode 100644
index 00000000000..5d948d34568
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-N-EN.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: dir=auto, start with N, then EN, then L</title>
+ <link rel="match" href="dir_auto-N-EN-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of the text, ignoring neutrals and numbers.
+ If there is no strong character, as in this test, the direction defaults to LTR." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="test">
+ <div dir="ltr">
+ <p dir="auto">@123!</p>
+ </div>
+ <div dir="rtl">
+ <p dir="auto">@123!</p>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <p dir="ltr">@123!</p>
+ </div>
+ <div dir="rtl">
+ <p dir="ltr">@123!</p>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-N-L-ref.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-N-L-ref.html
new file mode 100644
index 00000000000..801eb83dd55
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-N-L-ref.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: dir=auto, start with N, then L</title>
+ <link rel="match" href="dir_auto-N-L-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of the text.
+ In this test, it is the Latin letter A since neutrals are not
+ strongly directional, thus the direction must be resolved as LTR." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <p dir="ltr">.-=ABC&#x05D0;&#x05D1;&#x05D2;.</p>
+ </div>
+ <div dir="rtl">
+ <p dir="ltr">.-=ABC&#x05D0;&#x05D1;&#x05D2;.</p>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <p dir="ltr">.-=ABC&#x05D0;&#x05D1;&#x05D2;.</p>
+ </div>
+ <div dir="rtl">
+ <p dir="ltr">.-=ABC&#x05D0;&#x05D1;&#x05D2;.</p>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-N-L.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-N-L.html
new file mode 100644
index 00000000000..945fa067796
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-N-L.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: dir=auto, start with N, then L</title>
+ <link rel="match" href="dir_auto-N-L-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of the text.
+ In this test, it is the Latin letter A since neutrals are not
+ strongly directional, thus the direction must be resolved as LTR." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <p dir="auto">.-=ABC&#x05D0;&#x05D1;&#x05D2;.</p>
+ </div>
+ <div dir="rtl">
+ <p dir="auto">.-=ABC&#x05D0;&#x05D1;&#x05D2;.</p>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <p dir="ltr">.-=ABC&#x05D0;&#x05D1;&#x05D2;.</p>
+ </div>
+ <div dir="rtl">
+ <p dir="ltr">.-=ABC&#x05D0;&#x05D1;&#x05D2;.</p>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-N-R-ref.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-N-R-ref.html
new file mode 100644
index 00000000000..ded5977d573
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-N-R-ref.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: dir=auto, start with N, then R</title>
+ <link rel="match" href="dir_auto-N-R-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of the text.
+ In this test, it is the Hebrew letter Alef since neutrals are not
+ strongly directional, thus the direction must be resolved as RTL." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <p dir="rtl">.-=&#x05D0;&#x05D1;&#x05D2;ABC.</p>
+ </div>
+ <div dir="rtl">
+ <p dir="rtl">.-=&#x05D0;&#x05D1;&#x05D2;ABC.</p>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <p dir="rtl">.-=&#x05D0;&#x05D1;&#x05D2;ABC.</p>
+ </div>
+ <div dir="rtl">
+ <p dir="rtl">.-=&#x05D0;&#x05D1;&#x05D2;ABC.</p>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-N-R.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-N-R.html
new file mode 100644
index 00000000000..bf27a16a226
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-N-R.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: dir=auto, start with N, then R</title>
+ <link rel="match" href="dir_auto-N-R-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of the text.
+ In this test, it is the Hebrew letter Alef since neutrals are not
+ strongly directional, thus the direction must be resolved as RTL." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <p dir="auto">.-=&#x05D0;&#x05D1;&#x05D2;ABC.</p>
+ </div>
+ <div dir="rtl">
+ <p dir="auto">.-=&#x05D0;&#x05D1;&#x05D2;ABC.</p>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <p dir="rtl">.-=&#x05D0;&#x05D1;&#x05D2;ABC.</p>
+ </div>
+ <div dir="rtl">
+ <p dir="rtl">.-=&#x05D0;&#x05D1;&#x05D2;ABC.</p>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-R-ref.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-R-ref.html
new file mode 100644
index 00000000000..7b20566be62
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-R-ref.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: dir=auto, start with R</title>
+ <link rel="match" href="dir_auto-R-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of the text.
+ In this test, it is the Hebrew letter Alef, thus the direction must be
+ resolved as RTL." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <p dir="rtl">&#x05D0;&#x05D1;&#x05D2;ABC.</p>
+ </div>
+ <div dir="rtl">
+ <p dir="rtl">&#x05D0;&#x05D1;&#x05D2;ABC.</p>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <p dir="rtl">&#x05D0;&#x05D1;&#x05D2;ABC.</p>
+ </div>
+ <div dir="rtl">
+ <p dir="rtl">&#x05D0;&#x05D1;&#x05D2;ABC.</p>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-R.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-R.html
new file mode 100644
index 00000000000..69a62fc6379
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-R.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: dir=auto, start with R</title>
+ <link rel="match" href="dir_auto-R-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of the text.
+ In this test, it is the Hebrew letter Alef, thus the direction must be
+ resolved as RTL." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <p dir="auto">&#x05D0;&#x05D1;&#x05D2;ABC.</p>
+ </div>
+ <div dir="rtl">
+ <p dir="auto">&#x05D0;&#x05D1;&#x05D2;ABC.</p>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <p dir="rtl">&#x05D0;&#x05D1;&#x05D2;ABC.</p>
+ </div>
+ <div dir="rtl">
+ <p dir="rtl">&#x05D0;&#x05D1;&#x05D2;ABC.</p>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-L-ref.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-L-ref.html
new file mode 100644
index 00000000000..421c107acc5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-L-ref.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: dir=auto, start with L within contained element</title>
+ <link rel="match" href="dir_auto-contained-L-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of the text, including text within contained elements.
+ In this test, it is the Latin letter A, thus the direction must be
+ resolved as LTR." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ &#x05D3; - The Hebrew letter Dalet (strongly RTL).
+ &#x05D4; - The Hebrew letter He (strongly RTL).
+ &#x05D5; - The Hebrew letter Vav (strongly RTL).
+ &#x05D6; - The Hebrew letter Zayin (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <div dir="ltr"><div><div>ABC&#x05D0;&#x05D1;&#x05D2;.</div>&#x05D3;&#x05D4;</div>&#x05D5;</div>
+ </div>
+ <div dir="rtl">
+ <div dir="ltr"><div><div>ABC&#x05D0;&#x05D1;&#x05D2;.</div>&#x05D3;&#x05D4;</div>&#x05D5;</div>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <div dir="ltr"><div><div>ABC&#x05D0;&#x05D1;&#x05D2;.</div>&#x05D3;&#x05D4;</div>&#x05D5;</div>
+ </div>
+ <div dir="rtl">
+ <div dir="ltr"><div><div>ABC&#x05D0;&#x05D1;&#x05D2;.</div>&#x05D3;&#x05D4;</div>&#x05D5;</div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-L.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-L.html
new file mode 100644
index 00000000000..f71f318bfd1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-L.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: dir=auto, start with L within contained element</title>
+ <link rel="match" href="dir_auto-contained-L-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of the text, including text within contained elements.
+ In this test, it is the Latin letter A, thus the direction must be
+ resolved as LTR." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ &#x05D3; - The Hebrew letter Dalet (strongly RTL).
+ &#x05D4; - The Hebrew letter He (strongly RTL).
+ &#x05D5; - The Hebrew letter Vav (strongly RTL).
+ &#x05D6; - The Hebrew letter Zayin (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <div dir="auto"><div><div>ABC&#x05D0;&#x05D1;&#x05D2;.</div>&#x05D3;&#x05D4;</div>&#x05D5;</div>
+ </div>
+ <div dir="rtl">
+ <div dir="auto"><div><div>ABC&#x05D0;&#x05D1;&#x05D2;.</div>&#x05D3;&#x05D4;</div>&#x05D5;</div>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <div dir="ltr"><div><div>ABC&#x05D0;&#x05D1;&#x05D2;.</div>&#x05D3;&#x05D4;</div>&#x05D5;</div>
+ </div>
+ <div dir="rtl">
+ <div dir="ltr"><div><div>ABC&#x05D0;&#x05D1;&#x05D2;.</div>&#x05D3;&#x05D4;</div>&#x05D5;</div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-R-ref.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-R-ref.html
new file mode 100644
index 00000000000..04a286f1484
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-R-ref.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: dir=auto, start with R within contained element</title>
+ <link rel="match" href="dir_auto-contained-R-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of the text, including text within contained elements.
+ In this test, it is the Hebrew letter Alef, thus the direction must be
+ resolved as RTL." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <div dir="rtl"><div><div>&#x05D0;&#x05D1;&#x05D2;ABC.</div>XY</div>Z</div>
+ </div>
+ <div dir="rtl">
+ <div dir="rtl"><div><div>&#x05D0;&#x05D1;&#x05D2;ABC.</div>XY</div>Z</div>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <div dir="rtl"><div><div>&#x05D0;&#x05D1;&#x05D2;ABC.</div>XY</div>Z</div>
+ </div>
+ <div dir="rtl">
+ <div dir="rtl"><div><div>&#x05D0;&#x05D1;&#x05D2;ABC.</div>XY</div>Z</div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-R.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-R.html
new file mode 100644
index 00000000000..2ba63426e38
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-R.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: dir=auto, start with R within contained element</title>
+ <link rel="match" href="dir_auto-contained-R-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of the text, including text within contained elements.
+ In this test, it is the Hebrew letter Alef, thus the direction must be
+ resolved as RTL." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <div dir="auto"><div><div>&#x05D0;&#x05D1;&#x05D2;ABC.</div>XY</div>Z</div>
+ </div>
+ <div dir="rtl">
+ <div dir="auto"><div><div>&#x05D0;&#x05D1;&#x05D2;ABC.</div>XY</div>Z</div>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <div dir="rtl"><div><div>&#x05D0;&#x05D1;&#x05D2;ABC.</div>XY</div>Z</div>
+ </div>
+ <div dir="rtl">
+ <div dir="rtl"><div><div>&#x05D0;&#x05D1;&#x05D2;ABC.</div>XY</div>Z</div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-bdi-L-ref.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-bdi-L-ref.html
new file mode 100644
index 00000000000..691e0bfd8c2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-bdi-L-ref.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: dir=auto, start with bdi, then L</title>
+ <link rel="match" href="dir_auto-contained-bdi-L-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of the text while ignoring bdi elements.
+ In this test, it is the Latin letter A, thus the direction must be
+ resolved as LTR." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ &#x05D3; - The Hebrew letter Dalet (strongly RTL).
+ &#x05D4; - The Hebrew letter He (strongly RTL).
+ &#x05D5; - The Hebrew letter Vav (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <div dir="ltr"><bdi>&#x05D3;&#x05D4;&#x05D5;</bdi>ABC&#x05D0;&#x05D1;&#x05D2;.</div>
+ </div>
+ <div dir="rtl">
+ <div dir="ltr"><bdi>&#x05D3;&#x05D4;&#x05D5;</bdi>ABC&#x05D0;&#x05D1;&#x05D2;.</div>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <div dir="ltr"><bdi>&#x05D3;&#x05D4;&#x05D5;</bdi>ABC&#x05D0;&#x05D1;&#x05D2;.</div>
+ </div>
+ <div dir="rtl">
+ <div dir="ltr"><bdi>&#x05D3;&#x05D4;&#x05D5;</bdi>ABC&#x05D0;&#x05D1;&#x05D2;.</div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-bdi-L.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-bdi-L.html
new file mode 100644
index 00000000000..f35abfe3fdb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-bdi-L.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: dir=auto, start with bdi, then L</title>
+ <link rel="match" href="dir_auto-contained-bdi-L-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of the text while ignoring bdi elements.
+ In this test, it is the Latin letter A, thus the direction must be
+ resolved as LTR." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ &#x05D3; - The Hebrew letter Dalet (strongly RTL).
+ &#x05D4; - The Hebrew letter He (strongly RTL).
+ &#x05D5; - The Hebrew letter Vav (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <div dir="auto"><bdi>&#x05D3;&#x05D4;&#x05D5;</bdi>ABC&#x05D0;&#x05D1;&#x05D2;.</div>
+ </div>
+ <div dir="rtl">
+ <div dir="auto"><bdi>&#x05D3;&#x05D4;&#x05D5;</bdi>ABC&#x05D0;&#x05D1;&#x05D2;.</div>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <div dir="ltr"><bdi>&#x05D3;&#x05D4;&#x05D5;</bdi>ABC&#x05D0;&#x05D1;&#x05D2;.</div>
+ </div>
+ <div dir="rtl">
+ <div dir="ltr"><bdi>&#x05D3;&#x05D4;&#x05D5;</bdi>ABC&#x05D0;&#x05D1;&#x05D2;.</div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-bdi-R-ref.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-bdi-R-ref.html
new file mode 100644
index 00000000000..ff6532e02a8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-bdi-R-ref.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: dir=auto, start with bdi, then R</title>
+ <link rel="match" href="dir_auto-contained-bdi-R-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of the text while ignoring bdi elements.
+ In this test, it is the Hebrew letter Alef, thus the direction must be
+ resolved as RTL." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <div dir="rtl"><bdi>DEF</bdi>&#x05D0;&#x05D1;&#x05D2;ABC.</div>
+ </div>
+ <div dir="rtl">
+ <div dir="rtl"><bdi>DEF</bdi>&#x05D0;&#x05D1;&#x05D2;ABC.</div>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <div dir="rtl"><bdi>DEF</bdi>&#x05D0;&#x05D1;&#x05D2;ABC.</div>
+ </div>
+ <div dir="rtl">
+ <div dir="rtl"><bdi>DEF</bdi>&#x05D0;&#x05D1;&#x05D2;ABC.</div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-bdi-R.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-bdi-R.html
new file mode 100644
index 00000000000..8ac3244618a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-bdi-R.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: dir=auto, start with bdi, then R</title>
+ <link rel="match" href="dir_auto-contained-bdi-R-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of the text while ignoring bdi elements.
+ In this test, it is the Hebrew letter Alef, thus the direction must be
+ resolved as RTL." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <div dir="auto"><bdi>DEF</bdi>&#x05D0;&#x05D1;&#x05D2;ABC.</div>
+ </div>
+ <div dir="rtl">
+ <div dir="auto"><bdi>DEF</bdi>&#x05D0;&#x05D1;&#x05D2;ABC.</div>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <div dir="rtl"><bdi>DEF</bdi>&#x05D0;&#x05D1;&#x05D2;ABC.</div>
+ </div>
+ <div dir="rtl">
+ <div dir="rtl"><bdi>DEF</bdi>&#x05D0;&#x05D1;&#x05D2;ABC.</div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-dir-L-ref.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-dir-L-ref.html
new file mode 100644
index 00000000000..f5a8a8a856c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-dir-L-ref.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: dir=auto, start with dir, then L</title>
+ <link rel="match" href="dir_auto-contained-dir-L-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of the text while ignoring contained elements with an explicit dir of their own.
+ In this test, it is the Latin letter A, thus the direction must be
+ resolved as LTR." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ &#x05D3; - The Hebrew letter Dalet (strongly RTL).
+ &#x05D4; - The Hebrew letter He (strongly RTL).
+ &#x05D5; - The Hebrew letter Vav (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <div dir="ltr"><p dir="rtl">&#x05D3;&#x05D4;&#x05D5;</p>ABC&#x05D0;&#x05D1;&#x05D2;.</div>
+ </div>
+ <div dir="rtl">
+ <div dir="ltr"><p dir="rtl">&#x05D3;&#x05D4;&#x05D5;</p>ABC&#x05D0;&#x05D1;&#x05D2;.</div>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <div dir="ltr"><p dir="rtl">&#x05D3;&#x05D4;&#x05D5;</p>ABC&#x05D0;&#x05D1;&#x05D2;.</div>
+ </div>
+ <div dir="rtl">
+ <div dir="ltr"><p dir="rtl">&#x05D3;&#x05D4;&#x05D5;</p>ABC&#x05D0;&#x05D1;&#x05D2;.</div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-dir-L.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-dir-L.html
new file mode 100644
index 00000000000..1f424682fa3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-dir-L.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: dir=auto, start with dir, then L</title>
+ <link rel="match" href="dir_auto-contained-dir-L-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of the text while ignoring contained elements with an explicit dir of their own.
+ In this test, it is the Latin letter A, thus the direction must be
+ resolved as LTR." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ &#x05D3; - The Hebrew letter Dalet (strongly RTL).
+ &#x05D4; - The Hebrew letter He (strongly RTL).
+ &#x05D5; - The Hebrew letter Vav (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <div dir="auto"><p dir="rtl">&#x05D3;&#x05D4;&#x05D5;</p>ABC&#x05D0;&#x05D1;&#x05D2;.</div>
+ </div>
+ <div dir="rtl">
+ <div dir="auto"><p dir="rtl">&#x05D3;&#x05D4;&#x05D5;</p>ABC&#x05D0;&#x05D1;&#x05D2;.</div>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <div dir="ltr"><p dir="rtl">&#x05D3;&#x05D4;&#x05D5;</p>ABC&#x05D0;&#x05D1;&#x05D2;.</div>
+ </div>
+ <div dir="rtl">
+ <div dir="ltr"><p dir="rtl">&#x05D3;&#x05D4;&#x05D5;</p>ABC&#x05D0;&#x05D1;&#x05D2;.</div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-dir-R-ref.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-dir-R-ref.html
new file mode 100644
index 00000000000..b34f43f0d28
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-dir-R-ref.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: dir=auto, start with dir, then R</title>
+ <link rel="match" href="dir_auto-contained-dir-R-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of the text while ignoring contained elements with an explicit dir of their own.
+ In this test, it is the Hebrew letter Alef, thus the direction must be
+ resolved as RTL." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <div dir="rtl"><p dir="ltr">DEF</p>&#x05D0;&#x05D1;&#x05D2;ABC.</div>
+ </div>
+ <div dir="rtl">
+ <div dir="rtl"><p dir="ltr">DEF</p>&#x05D0;&#x05D1;&#x05D2;ABC.</div>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <div dir="rtl"><p dir="ltr">DEF</p>&#x05D0;&#x05D1;&#x05D2;ABC.</div>
+ </div>
+ <div dir="rtl">
+ <div dir="rtl"><p dir="ltr">DEF</p>&#x05D0;&#x05D1;&#x05D2;ABC.</div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-dir-R.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-dir-R.html
new file mode 100644
index 00000000000..daab191498f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-dir-R.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: dir=auto, start with dir, then R</title>
+ <link rel="match" href="dir_auto-contained-dir-R-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of the text while ignoring contained elements with an explicit dir of their own.
+ In this test, it is the Hebrew letter Alef, thus the direction must be
+ resolved as RTL." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <div dir="auto"><p dir="ltr">DEF</p>&#x05D0;&#x05D1;&#x05D2;ABC.</div>
+ </div>
+ <div dir="rtl">
+ <div dir="auto"><p dir="ltr">DEF</p>&#x05D0;&#x05D1;&#x05D2;ABC.</div>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <div dir="rtl"><p dir="ltr">DEF</p>&#x05D0;&#x05D1;&#x05D2;ABC.</div>
+ </div>
+ <div dir="rtl">
+ <div dir="rtl"><p dir="ltr">DEF</p>&#x05D0;&#x05D1;&#x05D2;ABC.</div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-dir_auto-L-ref.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-dir_auto-L-ref.html
new file mode 100644
index 00000000000..f04559ba3fd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-dir_auto-L-ref.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: dir=auto, start with dir=auto, then L</title>
+ <link rel="match" href="dir_auto-contained-dir_auto-L-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of the text while ignoring contained elements with an explicit dir of their own.
+ In this test, it is the Latin letter A, thus the direction must be
+ resolved as LTR." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ &#x05D3; - The Hebrew letter Dalet (strongly RTL).
+ &#x05D4; - The Hebrew letter He (strongly RTL).
+ &#x05D5; - The Hebrew letter Vav (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <div dir="ltr"><p dir="rtl">&#x05D3;&#x05D4;&#x05D5;</p>ABC&#x05D0;&#x05D1;&#x05D2;.</div>
+ </div>
+ <div dir="rtl">
+ <div dir="ltr"><p dir="rtl">&#x05D3;&#x05D4;&#x05D5;</p>ABC&#x05D0;&#x05D1;&#x05D2;.</div>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <div dir="ltr"><p dir="rtl">&#x05D3;&#x05D4;&#x05D5;</p>ABC&#x05D0;&#x05D1;&#x05D2;.</div>
+ </div>
+ <div dir="rtl">
+ <div dir="ltr"><p dir="rtl">&#x05D3;&#x05D4;&#x05D5;</p>ABC&#x05D0;&#x05D1;&#x05D2;.</div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-dir_auto-L.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-dir_auto-L.html
new file mode 100644
index 00000000000..f491f616588
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-dir_auto-L.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: dir=auto, start with dir=auto, then L</title>
+ <link rel="match" href="dir_auto-contained-dir_auto-L-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of the text while ignoring contained elements with an explicit dir of their own.
+ In this test, it is the Latin letter A, thus the direction must be
+ resolved as LTR." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ &#x05D3; - The Hebrew letter Dalet (strongly RTL).
+ &#x05D4; - The Hebrew letter He (strongly RTL).
+ &#x05D5; - The Hebrew letter Vav (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <div dir="auto"><p dir="auto">&#x05D3;&#x05D4;&#x05D5;</p>ABC&#x05D0;&#x05D1;&#x05D2;.</div>
+ </div>
+ <div dir="rtl">
+ <div dir="auto"><p dir="auto">&#x05D3;&#x05D4;&#x05D5;</p>ABC&#x05D0;&#x05D1;&#x05D2;.</div>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <div dir="ltr"><p dir="rtl">&#x05D3;&#x05D4;&#x05D5;</p>ABC&#x05D0;&#x05D1;&#x05D2;.</div>
+ </div>
+ <div dir="rtl">
+ <div dir="ltr"><p dir="rtl">&#x05D3;&#x05D4;&#x05D5;</p>ABC&#x05D0;&#x05D1;&#x05D2;.</div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-dir_auto-R-ref.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-dir_auto-R-ref.html
new file mode 100644
index 00000000000..e4104befb0a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-dir_auto-R-ref.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: dir=auto, start with dir=auto, then R</title>
+ <link rel="match" href="dir_auto-contained-dir_auto-R-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of the text while ignoring contained elements with an explicit dir of their own.
+ In this test, it is the Hebrew letter Alef, thus the direction must be
+ resolved as RTL." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <div dir="rtl"><p dir="ltr">DEF</p>.-=123&#x05D0;&#x05D1;&#x05D2;ABC.</div>
+ </div>
+ <div dir="rtl">
+ <div dir="rtl"><p dir="ltr">DEF</p>.-=123&#x05D0;&#x05D1;&#x05D2;ABC.</div>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <div dir="rtl"><p dir="ltr">DEF</p>.-=123&#x05D0;&#x05D1;&#x05D2;ABC.</div>
+ </div>
+ <div dir="rtl">
+ <div dir="rtl"><p dir="ltr">DEF</p>.-=123&#x05D0;&#x05D1;&#x05D2;ABC.</div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-dir_auto-R.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-dir_auto-R.html
new file mode 100644
index 00000000000..e3131c89b34
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-dir_auto-R.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: dir=auto, start with dir=auto, then R</title>
+ <link rel="match" href="dir_auto-contained-dir_auto-R-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of the text while ignoring contained elements with an explicit dir of their own.
+ In this test, it is the Hebrew letter Alef, thus the direction must be
+ resolved as RTL." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <div dir="auto"><p dir="auto">DEF</p>.-=123&#x05D0;&#x05D1;&#x05D2;ABC.</div>
+ </div>
+ <div dir="rtl">
+ <div dir="auto"><p dir="auto">DEF</p>.-=123&#x05D0;&#x05D1;&#x05D2;ABC.</div>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <div dir="rtl"><p dir="ltr">DEF</p>.-=123&#x05D0;&#x05D1;&#x05D2;ABC.</div>
+ </div>
+ <div dir="rtl">
+ <div dir="rtl"><p dir="ltr">DEF</p>.-=123&#x05D0;&#x05D1;&#x05D2;ABC.</div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-script-L-ref.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-script-L-ref.html
new file mode 100644
index 00000000000..69d2ef6cbfb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-script-L-ref.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: dir=auto, start with script, then L</title>
+ <link rel="match" href="dir_auto-contained-script-L-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of descendant text while ignoring descendant script elements.
+ In this test, it is the Latin letter A, thus the direction must be
+ resolved as LTR." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <div dir="ltr"><script>&#x05D0; = 3;</script>ABC&#x05D0;&#x05D1;&#x05D2;.</div>
+ </div>
+ <div dir="rtl">
+ <div dir="ltr"><script>&#x05D0; = 3;</script>ABC&#x05D0;&#x05D1;&#x05D2;.</div>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <div dir="ltr"><script>&#x05D0; = 3;</script>ABC&#x05D0;&#x05D1;&#x05D2;.</div>
+ </div>
+ <div dir="rtl">
+ <div dir="ltr"><script>&#x05D0; = 3;</script>ABC&#x05D0;&#x05D1;&#x05D2;.</div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-script-L.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-script-L.html
new file mode 100644
index 00000000000..59a2e77751a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-script-L.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: dir=auto, start with script, then L</title>
+ <link rel="match" href="dir_auto-contained-script-L-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of descendant text while ignoring descendant script elements.
+ In this test, it is the Latin letter A, thus the direction must be
+ resolved as LTR." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <div dir="auto"><script>&#x05D0; = 3;</script>ABC&#x05D0;&#x05D1;&#x05D2;.</div>
+ </div>
+ <div dir="rtl">
+ <div dir="auto"><script>&#x05D0; = 3;</script>ABC&#x05D0;&#x05D1;&#x05D2;.</div>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <div dir="ltr"><script>&#x05D0; = 3;</script>ABC&#x05D0;&#x05D1;&#x05D2;.</div>
+ </div>
+ <div dir="rtl">
+ <div dir="ltr"><script>&#x05D0; = 3;</script>ABC&#x05D0;&#x05D1;&#x05D2;.</div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-script-R-ref.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-script-R-ref.html
new file mode 100644
index 00000000000..ea452c1ce8d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-script-R-ref.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: dir=auto, start with script, then R</title>
+ <link rel="match" href="dir_auto-contained-script-R-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of descendant text while ignoring descendant script elements.
+ In this test, it is the Hebrew letter Alef, thus the direction must be
+ resolved as RTL." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <div dir="rtl"><script>x = 3;</script>&#x05D0;&#x05D1;&#x05D2;ABC.</div>
+ </div>
+ <div dir="rtl">
+ <div dir="rtl"><script>x = 3;</script>&#x05D0;&#x05D1;&#x05D2;ABC.</div>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <div dir="rtl"><script>x = 3;</script>&#x05D0;&#x05D1;&#x05D2;ABC.</div>
+ </div>
+ <div dir="rtl">
+ <div dir="rtl"><script>x = 3;</script>&#x05D0;&#x05D1;&#x05D2;ABC.</div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-script-R.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-script-R.html
new file mode 100644
index 00000000000..a76515d22fa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-script-R.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: dir=auto, start with script, then R</title>
+ <link rel="match" href="dir_auto-contained-script-R-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of descendant text while ignoring descendant script elements.
+ In this test, it is the Hebrew letter Alef, thus the direction must be
+ resolved as RTL." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <div dir="auto"><script>x = 3;</script>&#x05D0;&#x05D1;&#x05D2;ABC.</div>
+ </div>
+ <div dir="rtl">
+ <div dir="auto"><script>x = 3;</script>&#x05D0;&#x05D1;&#x05D2;ABC.</div>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <div dir="rtl"><script>x = 3;</script>&#x05D0;&#x05D1;&#x05D2;ABC.</div>
+ </div>
+ <div dir="rtl">
+ <div dir="rtl"><script>x = 3;</script>&#x05D0;&#x05D1;&#x05D2;ABC.</div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-style-L-ref.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-style-L-ref.html
new file mode 100644
index 00000000000..d9a73560539
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-style-L-ref.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: dir=auto, start with style, then L</title>
+ <link rel="match" href="dir_auto-contained-style-L-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of descendant text while ignoring descendant style elements.
+ In this test, it is the Latin letter A, thus the direction must be
+ resolved as LTR." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <div dir="ltr"><style>body {color:black;}</style>ABC&#x05D0;&#x05D1;&#x05D2;.</div>
+ </div>
+ <div dir="rtl">
+ <div dir="ltr"><style>body {color:black;}</style>ABC&#x05D0;&#x05D1;&#x05D2;.</div>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <div dir="ltr"><style>body {color:black;}</style>ABC&#x05D0;&#x05D1;&#x05D2;.</div>
+ </div>
+ <div dir="rtl">
+ <div dir="ltr"><style>body {color:black;}</style>ABC&#x05D0;&#x05D1;&#x05D2;.</div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-style-L.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-style-L.html
new file mode 100644
index 00000000000..cc74d4c9394
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-style-L.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: dir=auto, start with style, then L</title>
+ <link rel="match" href="dir_auto-contained-style-L-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of descendant text while ignoring descendant style elements.
+ In this test, it is the Latin letter A, thus the direction must be
+ resolved as LTR." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <div dir="auto"><style>body {color:black;}</style>ABC&#x05D0;&#x05D1;&#x05D2;.</div>
+ </div>
+ <div dir="rtl">
+ <div dir="auto"><style>body {color:black;}</style>ABC&#x05D0;&#x05D1;&#x05D2;.</div>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <div dir="ltr"><style>body {color:black;}</style>ABC&#x05D0;&#x05D1;&#x05D2;.</div>
+ </div>
+ <div dir="rtl">
+ <div dir="ltr"><style>body {color:black;}</style>ABC&#x05D0;&#x05D1;&#x05D2;.</div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-style-R-ref.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-style-R-ref.html
new file mode 100644
index 00000000000..32c918f1026
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-style-R-ref.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: dir=auto, start with style, then R</title>
+ <link rel="match" href="dir_auto-contained-style-R-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of descendant text while ignoring descendant style elements.
+ In this test, it is the Hebrew letter Alef, thus the direction must be
+ resolved as RTL." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <div dir="rtl"><style>body {color:black;}</style>&#x05D0;&#x05D1;&#x05D2;ABC.</div>
+ </div>
+ <div dir="rtl">
+ <div dir="rtl"><style>body {color:black;}</style>&#x05D0;&#x05D1;&#x05D2;ABC.</div>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <div dir="rtl"><style>body {color:black;}</style>&#x05D0;&#x05D1;&#x05D2;ABC.</div>
+ </div>
+ <div dir="rtl">
+ <div dir="rtl"><style>body {color:black;}</style>&#x05D0;&#x05D1;&#x05D2;ABC.</div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-style-R.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-style-R.html
new file mode 100644
index 00000000000..4aa70cdb2e0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-style-R.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: dir=auto, start with style, then R</title>
+ <link rel="match" href="dir_auto-contained-style-R-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of descendant text while ignoring descendant style elements.
+ In this test, it is the Hebrew letter Alef, thus the direction must be
+ resolved as RTL." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <div dir="auto"><style>body {color:black;}</style>&#x05D0;&#x05D1;&#x05D2;ABC.</div>
+ </div>
+ <div dir="rtl">
+ <div dir="auto"><style>body {color:black;}</style>&#x05D0;&#x05D1;&#x05D2;ABC.</div>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <div dir="rtl"><style>body {color:black;}</style>&#x05D0;&#x05D1;&#x05D2;ABC.</div>
+ </div>
+ <div dir="rtl">
+ <div dir="rtl"><style>body {color:black;}</style>&#x05D0;&#x05D1;&#x05D2;ABC.</div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-textarea-L-ref.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-textarea-L-ref.html
new file mode 100644
index 00000000000..4e0d0e10136
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-textarea-L-ref.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: dir=auto, start with textarea, then L</title>
+ <link rel="match" href="dir_auto-contained-textarea-L-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of descendant text while ignoring descendant textarea elements.
+ In this test, it is the Latin letter A, thus the direction must be
+ resolved as LTR." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ &#x05D3; - The Hebrew letter Dalet (strongly RTL).
+ &#x05D4; - The Hebrew letter He (strongly RTL).
+ &#x05D5; - The Hebrew letter Vav (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <div dir="ltr"><textarea>&#x05D3;&#x05D4;&#x05D5;</textarea>ABC&#x05D0;&#x05D1;&#x05D2;.</div>
+ </div>
+ <div dir="rtl">
+ <div dir="ltr"><textarea>&#x05D3;&#x05D4;&#x05D5;</textarea>ABC&#x05D0;&#x05D1;&#x05D2;.</div>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <div dir="ltr"><textarea>&#x05D3;&#x05D4;&#x05D5;</textarea>ABC&#x05D0;&#x05D1;&#x05D2;.</div>
+ </div>
+ <div dir="rtl">
+ <div dir="ltr"><textarea>&#x05D3;&#x05D4;&#x05D5;</textarea>ABC&#x05D0;&#x05D1;&#x05D2;.</div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-textarea-L.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-textarea-L.html
new file mode 100644
index 00000000000..0de041fe019
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-textarea-L.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: dir=auto, start with textarea, then L</title>
+ <link rel="match" href="dir_auto-contained-textarea-L-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of descendant text while ignoring descendant textarea elements.
+ In this test, it is the Latin letter A, thus the direction must be
+ resolved as LTR." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ &#x05D3; - The Hebrew letter Dalet (strongly RTL).
+ &#x05D4; - The Hebrew letter He (strongly RTL).
+ &#x05D5; - The Hebrew letter Vav (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <div dir="auto"><textarea>&#x05D3;&#x05D4;&#x05D5;</textarea>ABC&#x05D0;&#x05D1;&#x05D2;.</div>
+ </div>
+ <div dir="rtl">
+ <div dir="auto"><textarea>&#x05D3;&#x05D4;&#x05D5;</textarea>ABC&#x05D0;&#x05D1;&#x05D2;.</div>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <div dir="ltr"><textarea>&#x05D3;&#x05D4;&#x05D5;</textarea>ABC&#x05D0;&#x05D1;&#x05D2;.</div>
+ </div>
+ <div dir="rtl">
+ <div dir="ltr"><textarea>&#x05D3;&#x05D4;&#x05D5;</textarea>ABC&#x05D0;&#x05D1;&#x05D2;.</div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-textarea-R-ref.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-textarea-R-ref.html
new file mode 100644
index 00000000000..f53d15ed5ca
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-textarea-R-ref.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: dir=auto, start with textarea, then R</title>
+ <link rel="match" href="dir_auto-contained-textarea-R-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of descendant text while ignoring descendant textarea elements.
+ In this test, it is the Hebrew letter Alef, thus the direction must be
+ resolved as RTL." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <div dir="rtl"><textarea>DEF</textarea>&#x05D0;&#x05D1;&#x05D2;ABC.</div>
+ </div>
+ <div dir="rtl">
+ <div dir="rtl"><textarea>DEF</textarea>&#x05D0;&#x05D1;&#x05D2;ABC.</div>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <div dir="rtl"><textarea>DEF</textarea>&#x05D0;&#x05D1;&#x05D2;ABC.</div>
+ </div>
+ <div dir="rtl">
+ <div dir="rtl"><textarea>DEF</textarea>&#x05D0;&#x05D1;&#x05D2;ABC.</div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-textarea-R.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-textarea-R.html
new file mode 100644
index 00000000000..852de6073cf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-contained-textarea-R.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: dir=auto, start with textarea, then R</title>
+ <link rel="match" href="dir_auto-contained-textarea-R-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of descendant text while ignoring descendant textarea elements.
+ In this test, it is the Hebrew letter Alef, thus the direction must be
+ resolved as RTL." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <div dir="auto"><textarea>DEF</textarea>&#x05D0;&#x05D1;&#x05D2;ABC.</div>
+ </div>
+ <div dir="rtl">
+ <div dir="auto"><textarea>DEF</textarea>&#x05D0;&#x05D1;&#x05D2;ABC.</div>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <div dir="rtl"><textarea>DEF</textarea>&#x05D0;&#x05D1;&#x05D2;ABC.</div>
+ </div>
+ <div dir="rtl">
+ <div dir="rtl"><textarea>DEF</textarea>&#x05D0;&#x05D1;&#x05D2;ABC.</div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-EN-L-ref.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-EN-L-ref.html
new file mode 100644
index 00000000000..58937597d52
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-EN-L-ref.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: input with dir=auto, start with EN+L</title>
+ <link rel="match" href="dir_auto-input-EN-L-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="Shai Berger" href="mailto:shai@platonix.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction of an input element is set according to
+ the first strong character of its value.
+ In this test, it is the Latin letter A since digits are not strongly
+ directional, thus the direction must be resolved as LTR." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <input type="text" dir="ltr" value="123ABC&#x05D0;&#x05D1;&#x05D2;." />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="ltr" value="123ABC&#x05D0;&#x05D1;&#x05D2;." />
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <input type="text" dir="ltr" value="123ABC&#x05D0;&#x05D1;&#x05D2;." />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="ltr" value="123ABC&#x05D0;&#x05D1;&#x05D2;." />
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-EN-L.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-EN-L.html
new file mode 100644
index 00000000000..d5ade6c0962
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-EN-L.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: input with dir=auto, start with EN+L</title>
+ <link rel="match" href="dir_auto-input-EN-L-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="Shai Berger" href="mailto:shai@platonix.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction of an input element is set according to
+ the first strong character of its value.
+ In this test, it is the Latin letter A since digits are not strongly
+ directional, thus the direction must be resolved as LTR." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <input type="text" dir="auto" value="123ABC&#x05D0;&#x05D1;&#x05D2;." />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="auto" value="123ABC&#x05D0;&#x05D1;&#x05D2;." />
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <input type="text" dir="ltr" value="123ABC&#x05D0;&#x05D1;&#x05D2;." />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="ltr" value="123ABC&#x05D0;&#x05D1;&#x05D2;." />
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-EN-R-ref.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-EN-R-ref.html
new file mode 100644
index 00000000000..2a7eb7a1dba
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-EN-R-ref.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: input with dir=auto, start with EN+R</title>
+ <link rel="match" href="dir_auto-input-EN-R-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="Shai Berger" href="mailto:shai@platonix.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction of an input element is set according to
+ the first strong character of its value.
+ In this test, it is the Hebrew letter Alef since digits are not strongly
+ directional, thus the direction must be resolved as RTL." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <input type="text" dir="rtl" value="123&#x05D0;&#x05D1;&#x05D2;ABC." />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="rtl" value="123&#x05D0;&#x05D1;&#x05D2;ABC." />
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <input type="text" dir="rtl" value="123&#x05D0;&#x05D1;&#x05D2;ABC." />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="rtl" value="123&#x05D0;&#x05D1;&#x05D2;ABC." />
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-EN-R.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-EN-R.html
new file mode 100644
index 00000000000..08ef3ecd703
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-EN-R.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: input with dir=auto, start with EN+R</title>
+ <link rel="match" href="dir_auto-input-EN-R-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="Shai Berger" href="mailto:shai@platonix.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction of an input element is set according to
+ the first strong character of its value.
+ In this test, it is the Hebrew letter Alef since digits are not strongly
+ directional, thus the direction must be resolved as RTL." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <input type="text" dir="auto" value="123&#x05D0;&#x05D1;&#x05D2;ABC." />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="auto" value="123&#x05D0;&#x05D1;&#x05D2;ABC." />
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <input type="text" dir="rtl" value="123&#x05D0;&#x05D1;&#x05D2;ABC." />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="rtl" value="123&#x05D0;&#x05D1;&#x05D2;ABC." />
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-L-ref.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-L-ref.html
new file mode 100644
index 00000000000..6e8643769b3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-L-ref.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: input with dir=auto, start with L</title>
+ <link rel="match" href="dir_auto-input-L-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="Shai Berger" href="mailto:shai@platonix.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction of an input element is set according to
+ the first strong character of its value.
+ In this test, it is the Latin letter A, thus the direction must be
+ resolved as LTR." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <input type="text" dir="ltr" value="ABC&#x05d0;&#x05d1;&#x05d2;." />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="ltr" value="ABC&#x05d0;&#x05d1;&#x05d2;." />
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <input type="text" dir="ltr" value="ABC&#x05d0;&#x05d1;&#x05d2;." />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="ltr" value="ABC&#x05d0;&#x05d1;&#x05d2;." />
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-L.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-L.html
new file mode 100644
index 00000000000..0a23f2b86de
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-L.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: input with dir=auto, start with L</title>
+ <link rel="match" href="dir_auto-input-L-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="Shai Berger" href="mailto:shai@platonix.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction of an input element is set according to
+ the first strong character of its value.
+ In this test, it is the Latin letter A, thus the direction must be
+ resolved as LTR." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <input type="text" dir="auto" value="ABC&#x05d0;&#x05d1;&#x05d2;." />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="auto" value="ABC&#x05d0;&#x05d1;&#x05d2;." />
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <input type="text" dir="ltr" value="ABC&#x05d0;&#x05d1;&#x05d2;." />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="ltr" value="ABC&#x05d0;&#x05d1;&#x05d2;." />
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-N-EN-L-ref.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-N-EN-L-ref.html
new file mode 100644
index 00000000000..5a442cdd381
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-N-EN-L-ref.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: input with dir=auto, start with N+EN+L</title>
+ <link rel="match" href="dir_auto-input-N-EN-L-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="Shai Berger" href="mailto:shai@platonix.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction of an input element is set according to
+ the first strong character of its value.
+ In this test, it is the Latin letter A since neutrals and digits are not
+ strongly directional, thus the direction must be resolved as LTR." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <input type="text" dir="ltr" value=".-=123ABC&#x05D0;&#x05D1;&#x05D2;." />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="ltr" value=".-=123ABC&#x05D0;&#x05D1;&#x05D2;." />
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <input type="text" dir="ltr" value=".-=123ABC&#x05D0;&#x05D1;&#x05D2;." />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="ltr" value=".-=123ABC&#x05D0;&#x05D1;&#x05D2;." />
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-N-EN-L.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-N-EN-L.html
new file mode 100644
index 00000000000..03f85526da9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-N-EN-L.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: input with dir=auto, start with N+EN+L</title>
+ <link rel="match" href="dir_auto-input-N-EN-L-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="Shai Berger" href="mailto:shai@platonix.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction of an input element is set according to
+ the first strong character of its value.
+ In this test, it is the Latin letter A since neutrals and digits are not
+ strongly directional, thus the direction must be resolved as LTR." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <input type="text" dir="auto" value=".-=123ABC&#x05D0;&#x05D1;&#x05D2;." />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="auto" value=".-=123ABC&#x05D0;&#x05D1;&#x05D2;." />
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <input type="text" dir="ltr" value=".-=123ABC&#x05D0;&#x05D1;&#x05D2;." />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="ltr" value=".-=123ABC&#x05D0;&#x05D1;&#x05D2;." />
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-N-EN-R-ref.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-N-EN-R-ref.html
new file mode 100644
index 00000000000..36cb32f64e2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-N-EN-R-ref.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: input with dir=auto, start with N+EN+R</title>
+ <link rel="match" href="dir_auto-input-N-EN-R-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="Shai Berger" href="mailto:shai@platonix.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction of an input element is set according to
+ the first strong character of its value.
+ In this test, it is the Hebrew letter Alef since neutrals and digits are not
+ strongly directional, thus the direction must be resolved as RTL." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <input type="text" dir="rtl" value=".-=123&#x05D0;&#x05D1;&#x05D2;ABC." />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="rtl" value=".-=123&#x05D0;&#x05D1;&#x05D2;ABC." />
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <input type="text" dir="rtl" value=".-=123&#x05D0;&#x05D1;&#x05D2;ABC." />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="rtl" value=".-=123&#x05D0;&#x05D1;&#x05D2;ABC." />
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-N-EN-R.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-N-EN-R.html
new file mode 100644
index 00000000000..13193d3d728
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-N-EN-R.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: input with dir=auto, start with N+EN+R</title>
+ <link rel="match" href="dir_auto-input-N-EN-R-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="Shai Berger" href="mailto:shai@platonix.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction of an input element is set according to
+ the first strong character of its value.
+ In this test, it is the Hebrew letter Alef since neutrals and digits are not
+ strongly directional, thus the direction must be resolved as RTL." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <input type="text" dir="auto" value=".-=123&#x05D0;&#x05D1;&#x05D2;ABC." />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="auto" value=".-=123&#x05D0;&#x05D1;&#x05D2;ABC." />
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <input type="text" dir="rtl" value=".-=123&#x05D0;&#x05D1;&#x05D2;ABC." />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="rtl" value=".-=123&#x05D0;&#x05D1;&#x05D2;ABC." />
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-N-EN-ref.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-N-EN-ref.html
new file mode 100644
index 00000000000..b1a8a23c049
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-N-EN-ref.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: input with dir=auto, all N+EN</title>
+ <link rel="match" href="dir_auto-input-N-EN-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="Shai Berger" href="mailto:shai@platonix.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction of an input element is set according to
+ the first strong character of its value, or to LTR if there is no such
+ character.
+ In this test, there is no strongly directional character in the value,
+ thus the direction must be resolved as LTR." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="test">
+ <div dir="ltr">
+ <input type="text" dir="ltr" value="@123!" />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="ltr" value="@123!" />
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <input type="text" dir="ltr" value="@123!" />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="ltr" value="@123!" />
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-N-EN.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-N-EN.html
new file mode 100644
index 00000000000..03df3c6dcce
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-N-EN.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: input with dir=auto, all N+EN</title>
+ <link rel="match" href="dir_auto-input-N-EN-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="Shai Berger" href="mailto:shai@platonix.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction of an input element is set according to
+ the first strong character of its value, or to LTR if there is no such
+ character.
+ In this test, there is no strongly directional character in the value,
+ thus the direction must be resolved as LTR." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="test">
+ <div dir="ltr">
+ <input type="text" dir="auto" value="@123!" />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="auto" value="@123!" />
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <input type="text" dir="ltr" value="@123!" />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="ltr" value="@123!" />
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-N-L-ref.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-N-L-ref.html
new file mode 100644
index 00000000000..fcf594f02fe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-N-L-ref.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: input with dir=auto, start with N+L</title>
+ <link rel="match" href="dir_auto-input-N-L-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="Shai Berger" href="mailto:shai@platonix.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction of an input element is set according to
+ the first strong character of its value.
+ In this test, it is the Latin letter A since neutrals are not
+ strongly directional, thus the direction must be resolved as LTR." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <input type="text" dir="ltr" value=".-=ABC&#x05D0;&#x05D1;&#x05D2;." />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="ltr" value=".-=ABC&#x05D0;&#x05D1;&#x05D2;." />
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <input type="text" dir="ltr" value=".-=ABC&#x05D0;&#x05D1;&#x05D2;." />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="ltr" value=".-=ABC&#x05D0;&#x05D1;&#x05D2;." />
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-N-L.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-N-L.html
new file mode 100644
index 00000000000..9c1d3bceece
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-N-L.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: input with dir=auto, start with N+L</title>
+ <link rel="match" href="dir_auto-input-N-L-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="Shai Berger" href="mailto:shai@platonix.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction of an input element is set according to
+ the first strong character of its value.
+ In this test, it is the Latin letter A since neutrals are not
+ strongly directional, thus the direction must be resolved as LTR." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <input type="text" dir="auto" value=".-=ABC&#x05D0;&#x05D1;&#x05D2;." />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="auto" value=".-=ABC&#x05D0;&#x05D1;&#x05D2;." />
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <input type="text" dir="ltr" value=".-=ABC&#x05D0;&#x05D1;&#x05D2;." />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="ltr" value=".-=ABC&#x05D0;&#x05D1;&#x05D2;." />
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-N-R-ref.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-N-R-ref.html
new file mode 100644
index 00000000000..28c0e4dd12f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-N-R-ref.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: input with dir=auto, start with N+R</title>
+ <link rel="match" href="dir_auto-input-N-R-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="Shai Berger" href="mailto:shai@platonix.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction of an input element is set according to
+ the first strong character of its value.
+ In this test, it is the Hebrew letter Alef since neutrals are not
+ strongly directional, thus the direction must be resolved as RTL." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <input type="text" dir="rtl" value=".-=&#x05D0;&#x05D1;&#x05D2;ABC." />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="rtl" value=".-=&#x05D0;&#x05D1;&#x05D2;ABC." />
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <input type="text" dir="rtl" value=".-=&#x05D0;&#x05D1;&#x05D2;ABC." />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="rtl" value=".-=&#x05D0;&#x05D1;&#x05D2;ABC." />
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-N-R.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-N-R.html
new file mode 100644
index 00000000000..dbf54f73442
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-N-R.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: input with dir=auto, start with N+R</title>
+ <link rel="match" href="dir_auto-input-N-R-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="Shai Berger" href="mailto:shai@platonix.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction of an input element is set according to
+ the first strong character of its value.
+ In this test, it is the Hebrew letter Alef since neutrals are not
+ strongly directional, thus the direction must be resolved as RTL." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <input type="text" dir="auto" value=".-=&#x05D0;&#x05D1;&#x05D2;ABC." />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="auto" value=".-=&#x05D0;&#x05D1;&#x05D2;ABC." />
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <input type="text" dir="rtl" value=".-=&#x05D0;&#x05D1;&#x05D2;ABC." />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="rtl" value=".-=&#x05D0;&#x05D1;&#x05D2;ABC." />
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-R-ref.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-R-ref.html
new file mode 100644
index 00000000000..65fc8a80165
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-R-ref.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: input with dir=auto, start with R</title>
+ <link rel="match" href="dir_auto-input-R-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="Shai Berger" href="mailto:shai@platonix.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction of an input element is set according to
+ the first strong character of its value.
+ In this test, it is the Hebrew letter Alef, thus the direction must be
+ resolved as RTL." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <input type="text" dir="rtl" value="&#x05D0;&#x05D1;&#x05D2;ABC." />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="rtl" value="&#x05D0;&#x05D1;&#x05D2;ABC." />
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <input type="text" dir="rtl" value="&#x05D0;&#x05D1;&#x05D2;ABC." />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="rtl" value="&#x05D0;&#x05D1;&#x05D2;ABC." />
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-R.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-R.html
new file mode 100644
index 00000000000..6d2612b3166
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-R.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: input with dir=auto, start with R</title>
+ <link rel="match" href="dir_auto-input-R-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="Shai Berger" href="mailto:shai@platonix.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction of an input element is set according to
+ the first strong character of its value.
+ In this test, it is the Hebrew letter Alef, thus the direction must be
+ resolved as RTL." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <input type="text" dir="auto" value="&#x05D0;&#x05D1;&#x05D2;ABC." />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="auto" value="&#x05D0;&#x05D1;&#x05D2;ABC." />
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <input type="text" dir="rtl" value="&#x05D0;&#x05D1;&#x05D2;ABC." />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="rtl" value="&#x05D0;&#x05D1;&#x05D2;ABC." />
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-EN-L-ref.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-EN-L-ref.html
new file mode 100644
index 00000000000..a60e93ed5ad
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-EN-L-ref.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: input with dir=auto, script assigns to start with EN+L</title>
+ <link rel="match" href="dir_auto-input-script-EN-L-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="Shai Berger" href="mailto:shai@platonix.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction of an input element is set according to
+ the first strong character of its value.
+ In this test, it is the Latin letter A since digits are not strongly
+ directional, thus the direction must be resolved as LTR." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <input type="text" dir="ltr" value="123ABC&#x05D0;&#x05D1;&#x05D2;." />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="ltr" value="123ABC&#x05D0;&#x05D1;&#x05D2;." />
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <input type="text" dir="ltr" value="123ABC&#x05D0;&#x05D1;&#x05D2;." />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="ltr" value="123ABC&#x05D0;&#x05D1;&#x05D2;." />
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-EN-L.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-EN-L.html
new file mode 100644
index 00000000000..d0a9e2bb9b0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-EN-L.html
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: input with dir=auto, script assigns to start with EN+L</title>
+ <link rel="match" href="dir_auto-input-script-EN-L-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="Shai Berger" href="mailto:shai@platonix.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction of an input element is set according to
+ the first strong character of its value.
+ In this test, it is the Latin letter A since digits are not strongly
+ directional, thus the direction must be resolved as LTR." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ This test makes sure that the direction is set correctly for an input whose value is set
+ dynamically by script.
+ </div>
+ <div id="test" class="test">
+ <script>
+ window.onload = function() {
+ var test = document.getElementById('test');
+ var inputs = test.getElementsByTagName('input');
+ for (var i = 0; i != inputs.length; i++) {
+ inputs[i].value = '123ABC\u05D0\u05D1\u05D2.';
+ }
+ }
+ </script>
+ <div dir="ltr">
+ <input type="text" dir="auto" value="&#x05D0;" />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="auto" value="&#x05D0;" />
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <input type="text" dir="ltr" value="123ABC&#x05D0;&#x05D1;&#x05D2;." />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="ltr" value="123ABC&#x05D0;&#x05D1;&#x05D2;." />
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-EN-R-ref.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-EN-R-ref.html
new file mode 100644
index 00000000000..c58523b17a5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-EN-R-ref.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: input with dir=auto, script assigns to start with EN+R</title>
+ <link rel="match" href="dir_auto-input-script-EN-R-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="Shai Berger" href="mailto:shai@platonix.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction of an input element is set according to
+ the first strong character of its value.
+ In this test, it is the Hebrew letter Alef since digits are not strongly
+ directional, thus the direction must be resolved as RTL." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <input type="text" dir="rtl" value="123&#x05D0;&#x05D1;&#x05D2;ABC." />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="rtl" value="123&#x05D0;&#x05D1;&#x05D2;ABC." />
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <input type="text" dir="rtl" value="123&#x05D0;&#x05D1;&#x05D2;ABC." />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="rtl" value="123&#x05D0;&#x05D1;&#x05D2;ABC." />
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-EN-R.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-EN-R.html
new file mode 100644
index 00000000000..e444b90dc2c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-EN-R.html
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: input with dir=auto, script assigns to start with EN+R</title>
+ <link rel="match" href="dir_auto-input-script-EN-R-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="Shai Berger" href="mailto:shai@platonix.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction of an input element is set according to
+ the first strong character of its value.
+ In this test, it is the Hebrew letter Alef since digits are not strongly
+ directional, thus the direction must be resolved as RTL." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ This test makes sure that the direction is set correctly for an input whose value is set
+ dynamically by script.
+ </div>
+ <div id="test" class="test">
+ <script>
+ window.onload = function() {
+ var test = document.getElementById('test');
+ var inputs = test.getElementsByTagName('input');
+ for (var i = 0; i != inputs.length; i++) {
+ inputs[i].value = '123\u05D0\u05D1\u05D2ABC.';
+ }
+ }
+ </script>
+ <div dir="ltr">
+ <input type="text" dir="auto" value="a" />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="auto" value="a" />
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <input type="text" dir="rtl" value="123&#x05D0;&#x05D1;&#x05D2;ABC." />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="rtl" value="123&#x05D0;&#x05D1;&#x05D2;ABC." />
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-L-ref.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-L-ref.html
new file mode 100644
index 00000000000..eec4fb959eb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-L-ref.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: input with dir=auto, script assigns to start with L</title>
+ <link rel="match" href="dir_auto-input-script-L-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="Shai Berger" href="mailto:shai@platonix.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction of an input element is set according to
+ the first strong character of its value.
+ In this test, it is the Latin letter A, thus the direction must be
+ resolved as LTR." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <input type="text" dir="ltr" value="ABC&#x05D0;&#x05D1;&#x05D2;." />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="ltr" value="ABC&#x05D0;&#x05D1;&#x05D2;." />
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <input type="text" dir="ltr" value="ABC&#x05D0;&#x05D1;&#x05D2;." />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="ltr" value="ABC&#x05D0;&#x05D1;&#x05D2;." />
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-L.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-L.html
new file mode 100644
index 00000000000..e6aa700ad05
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-L.html
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: input with dir=auto, script assigns to start with L</title>
+ <link rel="match" href="dir_auto-input-script-L-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="Shai Berger" href="mailto:shai@platonix.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction of an input element is set according to
+ the first strong character of its value.
+ In this test, it is the Latin letter A, thus the direction must be
+ resolved as LTR." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ This test makes sure that the direction is set correctly for an input whose value is set
+ dynamically by script.
+ </div>
+ <div id="test" class="test">
+ <script>
+ window.onload = function() {
+ var test = document.getElementById('test');
+ var inputs = test.getElementsByTagName('input');
+ for (var i = 0; i != inputs.length; i++) {
+ inputs[i].value = 'ABC\u05D0\u05D1\u05D2.';
+ }
+ }
+ </script>
+ <div dir="ltr">
+ <input type="text" dir="auto" value="&#x05D0;" />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="auto" value="&#x05D0;" />
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <input type="text" dir="ltr" value="ABC&#x05D0;&#x05D1;&#x05D2;." />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="ltr" value="ABC&#x05D0;&#x05D1;&#x05D2;." />
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-N-EN-L-ref.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-N-EN-L-ref.html
new file mode 100644
index 00000000000..78591478c34
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-N-EN-L-ref.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: input with dir=auto, script assigns to start with N+EN+L</title>
+ <link rel="match" href="dir_auto-input-script-N-EN-L-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="Shai Berger" href="mailto:shai@platonix.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction of an input element is set according to
+ the first strong character of its value.
+ In this test, it is the Latin letter A since neutrals and digits are not
+ strongly directional, thus the direction must be resolved as LTR." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <input type="text" dir="ltr" value=".-=123ABC&#x05D0;&#x05D1;&#x05D2;." />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="ltr" value=".-=123ABC&#x05D0;&#x05D1;&#x05D2;." />
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <input type="text" dir="ltr" value=".-=123ABC&#x05D0;&#x05D1;&#x05D2;." />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="ltr" value=".-=123ABC&#x05D0;&#x05D1;&#x05D2;." />
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-N-EN-L.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-N-EN-L.html
new file mode 100644
index 00000000000..7905cee9461
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-N-EN-L.html
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: input with dir=auto, script assigns to start with N+EN+L</title>
+ <link rel="match" href="dir_auto-input-script-N-EN-L-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="Shai Berger" href="mailto:shai@platonix.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction of an input element is set according to
+ the first strong character of its value.
+ In this test, it is the Latin letter A since neutrals and digits are not
+ strongly directional, thus the direction must be resolved as LTR." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ This test makes sure that the direction is set correctly for an input whose value is set
+ dynamically by script.
+ </div>
+ <div id="test" class="test">
+ <script>
+ window.onload = function() {
+ var test = document.getElementById('test');
+ var inputs = test.getElementsByTagName('input');
+ for (var i = 0; i != inputs.length; i++) {
+ inputs[i].value = '.-=123ABC\u05D0\u05D1\u05D2.';
+ }
+ }
+ </script>
+ <div dir="ltr">
+ <input type="text" dir="auto" value="&#x05D0;" />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="auto" value="&#x05D0;" />
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <input type="text" dir="ltr" value=".-=123ABC&#x05D0;&#x05D1;&#x05D2;." />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="ltr" value=".-=123ABC&#x05D0;&#x05D1;&#x05D2;." />
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-N-EN-R-ref.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-N-EN-R-ref.html
new file mode 100644
index 00000000000..3b3f7b91d6a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-N-EN-R-ref.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: input with dir=auto, script assigns to start with N+EN+R</title>
+ <link rel="match" href="dir_auto-input-script-N-EN-R-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="Shai Berger" href="mailto:shai@platonix.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction of an input element is set according to
+ the first strong character of its value.
+ In this test, it is the Hebrew letter Alef since neutrals and digits are not
+ strongly directional, thus the direction must be resolved as RTL." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <input type="text" dir="rtl" value=".-=123&#x05D0;&#x05D1;&#x05D2;ABC." />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="rtl" value=".-=123&#x05D0;&#x05D1;&#x05D2;ABC." />
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <input type="text" dir="rtl" value=".-=123&#x05D0;&#x05D1;&#x05D2;ABC." />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="rtl" value=".-=123&#x05D0;&#x05D1;&#x05D2;ABC." />
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-N-EN-R.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-N-EN-R.html
new file mode 100644
index 00000000000..95faa72ea73
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-N-EN-R.html
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: input with dir=auto, script assigns to start with N+EN+R</title>
+ <link rel="match" href="dir_auto-input-script-N-EN-R-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="Shai Berger" href="mailto:shai@platonix.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction of an input element is set according to
+ the first strong character of its value.
+ In this test, it is the Hebrew letter Alef since neutrals and digits are not
+ strongly directional, thus the direction must be resolved as RTL." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ This test makes sure that the direction is set correctly for an input whose value is set
+ dynamically by script.
+ </div>
+ <div id="test" class="test">
+ <script>
+ window.onload = function() {
+ var test = document.getElementById('test');
+ var inputs = test.getElementsByTagName('input');
+ for (var i = 0; i != inputs.length; i++) {
+ inputs[i].value = '.-=123\u05D0\u05D1\u05D2ABC.';
+ }
+ }
+ </script>
+ <div dir="ltr">
+ <input type="text" dir="auto" value="a" />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="auto" value="a" />
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <input type="text" dir="rtl" value=".-=123&#x05D0;&#x05D1;&#x05D2;ABC." />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="rtl" value=".-=123&#x05D0;&#x05D1;&#x05D2;ABC." />
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-N-EN-ref.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-N-EN-ref.html
new file mode 100644
index 00000000000..b0ab0710dda
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-N-EN-ref.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: input with dir=auto, script assigns to all N+EN</title>
+ <link rel="match" href="dir_auto-input-script-N-EN-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="Shai Berger" href="mailto:shai@platonix.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction of an input element is set according to
+ the first strong character of its value, or to LTR if there is no such
+ character.
+ In this test, there is no strongly directional character in the value,
+ thus the direction must be resolved as LTR." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="test">
+ <div dir="ltr">
+ <input type="text" dir="ltr" value="@123!" />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="ltr" value="@123!" />
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <input type="text" dir="ltr" value="@123!" />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="ltr" value="@123!" />
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-N-EN.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-N-EN.html
new file mode 100644
index 00000000000..2721affaefc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-N-EN.html
@@ -0,0 +1,69 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: input with dir=auto, script assigns to all N+EN</title>
+ <link rel="match" href="dir_auto-input-script-N-EN-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="Shai Berger" href="mailto:shai@platonix.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction of an input element is set according to
+ the first strong character of its value, or to LTR if there is no such
+ character.
+ In this test, there is no strongly directional character in the value,
+ thus the direction must be resolved as LTR." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ This test makes sure that the direction is set correctly for an input whose value is set
+ dynamically by script.
+ </div>
+ <div id="test" class="test">
+ <script>
+ window.onload = function() {
+ var test = document.getElementById('test');
+ var inputs = test.getElementsByTagName('input');
+ for (var i = 0; i != inputs.length; i++) {
+ inputs[i].value = '@123!';
+ }
+ };
+ </script>
+ <div dir="ltr">
+ <input type="text" dir="auto" value="&#x05D0;" />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="auto" value="&#x05D0;" />
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <input type="text" dir="ltr" value="@123!" />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="ltr" value="@123!" />
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-N-L-ref.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-N-L-ref.html
new file mode 100644
index 00000000000..a807b2758c3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-N-L-ref.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: input with dir=auto, script assigns to start with N+L</title>
+ <link rel="match" href="dir_auto-input-script-N-L-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="Shai Berger" href="mailto:shai@platonix.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction of an input element is set according to
+ the first strong character of its value.
+ In this test, it is the Latin letter A since neutrals are not
+ strongly directional, thus the direction must be resolved as LTR." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <input type="text" dir="ltr" value=".-=ABC&#x05D0;&#x05D1;&#x05D2;." />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="ltr" value=".-=ABC&#x05D0;&#x05D1;&#x05D2;." />
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <input type="text" dir="ltr" value=".-=ABC&#x05D0;&#x05D1;&#x05D2;." />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="ltr" value=".-=ABC&#x05D0;&#x05D1;&#x05D2;." />
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-N-L.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-N-L.html
new file mode 100644
index 00000000000..2ff24db28c2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-N-L.html
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: input with dir=auto, script assigns to start with N+L</title>
+ <link rel="match" href="dir_auto-input-script-N-L-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="Shai Berger" href="mailto:shai@platonix.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction of an input element is set according to
+ the first strong character of its value.
+ In this test, it is the Latin letter A since neutrals are not
+ strongly directional, thus the direction must be resolved as LTR." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ This test makes sure that the direction is set correctly for an input whose value is set
+ dynamically by script.
+ </div>
+ <div id="test" class="test">
+ <script>
+ window.onload = function() {
+ var test = document.getElementById('test');
+ var inputs = test.getElementsByTagName('input');
+ for (var i = 0; i != inputs.length; i++) {
+ inputs[i].value = '.-=ABC\u05D0\u05D1\u05D2.';
+ }
+ }
+ </script>
+ <div dir="ltr">
+ <input type="text" dir="auto" value="&#x05D0;" />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="auto" value="&#x05D0;" />
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <input type="text" dir="ltr" value=".-=ABC&#x05D0;&#x05D1;&#x05D2;." />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="ltr" value=".-=ABC&#x05D0;&#x05D1;&#x05D2;." />
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-N-R-ref.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-N-R-ref.html
new file mode 100644
index 00000000000..c267f281c8d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-N-R-ref.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: input with dir=auto, script assigns to start with N+R</title>
+ <link rel="match" href="dir_auto-input-script-N-R-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="Shai Berger" href="mailto:shai@platonix.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction of an input element is set according to
+ the first strong character of its value.
+ In this test, it is the Hebrew letter Alef since neutrals are not
+ strongly directional, thus the direction must be resolved as RTL." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <input type="text" dir="rtl" value=".-=&#x05D0;&#x05D1;&#x05D2;ABC." />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="rtl" value=".-=&#x05D0;&#x05D1;&#x05D2;ABC." />
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <input type="text" dir="rtl" value=".-=&#x05D0;&#x05D1;&#x05D2;ABC." />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="rtl" value=".-=&#x05D0;&#x05D1;&#x05D2;ABC." />
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-N-R.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-N-R.html
new file mode 100644
index 00000000000..0663b28ad29
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-N-R.html
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: input with dir=auto, script assigns to start with N+R</title>
+ <link rel="match" href="dir_auto-input-script-N-R-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="Shai Berger" href="mailto:shai@platonix.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction of an input element is set according to
+ the first strong character of its value.
+ In this test, it is the Hebrew letter Alef since neutrals are not
+ strongly directional, thus the direction must be resolved as RTL." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ This test makes sure that the direction is set correctly for an input whose value is set
+ dynamically by script.
+ </div>
+ <div id="test" class="test">
+ <script>
+ window.onload = function() {
+ var test = document.getElementById('test');
+ var inputs = test.getElementsByTagName('input');
+ for (var i = 0; i != inputs.length; i++) {
+ inputs[i].value = '.-=\u05D0\u05D1\u05D2ABC.';
+ }
+ }
+ </script>
+ <div dir="ltr">
+ <input type="text" dir="auto" value="a" />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="auto" value="a" />
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <input type="text" dir="rtl" value=".-=&#x05D0;&#x05D1;&#x05D2;ABC." />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="rtl" value=".-=&#x05D0;&#x05D1;&#x05D2;ABC." />
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-R-ref.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-R-ref.html
new file mode 100644
index 00000000000..1cc14df38dc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-R-ref.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: input with dir=auto, script assigns to start with R</title>
+ <link rel="match" href="dir_auto-input-script-R-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="Shai Berger" href="mailto:shai@platonix.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction of an input element is set according to
+ the first strong character of its value.
+ In this test, it is the Hebrew letter Alef, thus the direction must be
+ resolved as RTL." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <input type="text" dir="rtl" value="&#x05D0;&#x05D1;&#x05D2;ABC." />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="rtl" value="&#x05D0;&#x05D1;&#x05D2;ABC." />
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <input type="text" dir="rtl" value="&#x05D0;&#x05D1;&#x05D2;ABC." />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="rtl" value="&#x05D0;&#x05D1;&#x05D2;ABC." />
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-R.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-R.html
new file mode 100644
index 00000000000..07becaaccd2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-input-script-R.html
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: input with dir=auto, script assigns to start with R</title>
+ <link rel="match" href="dir_auto-input-script-R-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="Shai Berger" href="mailto:shai@platonix.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction of an input element is set according to
+ the first strong character of its value.
+ In this test, it is the Hebrew letter Alef, thus the direction must be
+ resolved as RTL." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x05D1; - The Hebrew letter Bet (strongly RTL).
+ &#x05D2; - The Hebrew letter Gimel (strongly RTL).
+ This test makes sure that the direction is set correctly for an input whose value is set
+ dynamically by script.
+ </div>
+ <div id="test" class="test">
+ <script>
+ window.onload = function() {
+ var test = document.getElementById('test');
+ var inputs = test.getElementsByTagName('input');
+ for (var i = 0; i != inputs.length; i++) {
+ inputs[i].value = '\u05D0\u05D1\u05D2ABC.';
+ }
+ }
+ </script>
+ <div dir="ltr">
+ <input type="text" dir="auto" value="a" />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="auto" value="a" />
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <input type="text" dir="rtl" value="&#x05D0;&#x05D1;&#x05D2;ABC." />
+ </div>
+ <div dir="rtl">
+ <input type="text" dir="rtl" value="&#x05D0;&#x05D1;&#x05D2;ABC." />
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-isolate-ref.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-isolate-ref.html
new file mode 100644
index 00000000000..442a2d3b895
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-isolate-ref.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: dir=auto, isolated in LTR text</title>
+ <link rel="match" href="dir_auto-isolate-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of the text, but the element behaves externally as a neutral character.
+ In this test, it allows a preceding R to form a single directional run
+ with a succeeding number." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x202D; - The LRO (left-to-right override) formatting character.
+ &#x202C; - The PDF (pop directional formatting) formatting character; closes LRO.
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ &#x202D;1 a! &#x05D0;&#x202C;
+ </div>
+ <div dir="rtl">
+ &#x202D;a !&#x05D0; 1&#x202C;
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ &#x202D;1 a! &#x05D0;&#x202C;
+ </div>
+ <div dir="rtl">
+ &#x202D;a !&#x05D0; 1&#x202C;
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-isolate.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-isolate.html
new file mode 100644
index 00000000000..14272c0531e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-isolate.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: dir=auto, isolated in LTR text</title>
+ <link rel="match" href="dir_auto-isolate-ref.html" />
+ <link rel="author" title="Matitiahu Allouche" href="mailto:matitiahu.allouche@google.com" />
+ <link rel="author" title="Oren Roth" href="mailto:oren.roth@gmail.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of the text, but the element behaves externally as a neutral character.
+ In this test, it allows a preceding R to form a single directional run
+ with a succeeding number." />
+ <style>
+ input, textarea {
+ font-size:1em;
+ }
+ body {
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ &#x202D; - The LRO (left-to-right override) formatting character.
+ &#x202C; - The PDF (pop directional formatting) formatting character; closes LRO.
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ &#x05D0; <span dir="auto">a!</span> 1
+ </div>
+ <div dir="rtl">
+ a <span dir="auto">&#x05D0;!</span> 1
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ &#x202D;1 a! &#x05D0;&#x202C;
+ </div>
+ <div dir="rtl">
+ &#x202D;a !&#x05D0; 1&#x202C;
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-pre-N-EN-ref.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-pre-N-EN-ref.html
new file mode 100644
index 00000000000..c951c30b202
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-pre-N-EN-ref.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <style>
+ body {
+ font-size:18px;
+ text-align:left;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="test">
+ <div dir="ltr">
+ <pre dir="ltr">
+@123!
+ </pre>
+ </div>
+ <div dir="rtl">
+ <pre dir="ltr">
+@123!
+ </pre>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <pre dir="ltr">
+@123!
+ </pre>
+ </div>
+ <div dir="rtl">
+ <pre dir="ltr">
+@123!
+ </pre>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-pre-N-EN.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-pre-N-EN.html
new file mode 100644
index 00000000000..cd721d725e9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-pre-N-EN.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: pre with dir=auto, all N+EN</title>
+ <link rel="match" href="dir_auto-pre-N-EN-ref.html" />
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <link rel="help" href="http://dev.w3.org/csswg/css3-writing-modes/#unicode-bidi0" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of the text.
+ For textarea and pre elements, the heuristic is applied on a per-paragraph level.
+ If there is no strong character, as in this test, the direction defaults to LTR." />
+ <style>
+ body {
+ font-size:18px;
+ text-align:left;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x200E; - LRM, the invisible left-to-right mark (strongly LTR).
+ &#x200F; - RLM, the invisible right-to-left mark (strongly RTL).
+ We use text-align:left because neither the dir="auto" nor the unicode-bidi:plaintext
+ specification states whether text-align:start and text-align:end should obey the paragraph
+ direction or the direction property in a unicode-bidi:plaintext element.
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <pre dir="auto">
+@123!
+ </pre>
+ </div>
+ <div dir="rtl">
+ <pre dir="auto">
+@123!
+ </pre>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <pre dir="ltr">
+@123!
+ </pre>
+ </div>
+ <div dir="rtl">
+ <pre dir="ltr">
+@123!
+ </pre>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-pre-N-between-Rs-ref.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-pre-N-between-Rs-ref.html
new file mode 100644
index 00000000000..2d9caf062d2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-pre-N-between-Rs-ref.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <style>
+ body {
+ font-size:18px;
+ text-align:left;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <pre dir="rtl">
+&#x05D0;
+!...
+&#x05D0;
+ </pre>
+ </div>
+ <div dir="rtl">
+ <pre dir="rtl">
+&#x05D0;
+!...
+&#x05D0;
+ </pre>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <pre dir="rtl">
+&#x05D0;
+!...
+&#x05D0;
+ </pre>
+ </div>
+ <div dir="rtl">
+ <pre dir="rtl">
+&#x05D0;
+!...
+&#x05D0;
+ </pre>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-pre-N-between-Rs.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-pre-N-between-Rs.html
new file mode 100644
index 00000000000..adca24d88f5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-pre-N-between-Rs.html
@@ -0,0 +1,76 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: pre with dir=auto, all-N between all-Rs</title>
+ <link rel="match" href="dir_auto-pre-N-between-Rs-ref.html" />
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <link rel="help" href="http://dev.w3.org/csswg/css3-writing-modes/#unicode-bidi0" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of the text.
+ For textarea and pre elements, the heuristic is applied on a per-paragraph level.
+ If there is no strong character, as in this test, the direction defaults to LTR." />
+ <style>
+ body {
+ font-size:18px;
+ text-align:left;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ We use text-align:left because neither the dir="auto" nor the unicode-bidi:plaintext
+ specification states whether text-align:start and text-align:end should obey the paragraph
+ direction or the direction property in a unicode-bidi:plaintext element.
+ The ...! paragraph, being neutral, is supposed to be displayed LTR (i.e. as ...!, not as !...)
+ despite both the paragraph before it and the paragraph after it being all-RTL, which makes the
+ element as a whole RTL.
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <pre dir="auto">
+&#x05D0;
+...!
+&#x05D0;
+ </pre>
+ </div>
+ <div dir="rtl">
+ <pre dir="auto">
+&#x05D0;
+...!
+&#x05D0;
+ </pre>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <pre dir="rtl">
+&#x05D0;
+!...
+&#x05D0;
+ </pre>
+ </div>
+ <div dir="rtl">
+ <pre dir="rtl">
+&#x05D0;
+!...
+&#x05D0;
+ </pre>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-pre-mixed-ref.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-pre-mixed-ref.html
new file mode 100644
index 00000000000..10bd02433b4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-pre-mixed-ref.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <style>
+ body {
+ font-size:18px;
+ text-align:left;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="test">
+ <div dir="ltr">
+ <pre dir="ltr">
+@123!
+@123!
+@123!
+@123!
+ </pre>
+ </div>
+ <div dir="rtl">
+ <pre dir="ltr">
+@123!
+@123!
+@123!
+@123!
+ </pre>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <pre dir="ltr">
+@123!
+@123!
+@123!
+@123!
+ </pre>
+ </div>
+ <div dir="rtl">
+ <pre dir="ltr">
+@123!
+@123!
+@123!
+@123!
+ </pre>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-pre-mixed.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-pre-mixed.html
new file mode 100644
index 00000000000..906365621dd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-pre-mixed.html
@@ -0,0 +1,77 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: pre with dir=auto, mixed L and R paragraphs</title>
+ <link rel="match" href="dir_auto-pre-mixed-ref.html" />
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <link rel="help" href="http://dev.w3.org/csswg/css3-writing-modes/#unicode-bidi0" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of the text.
+ For textarea and pre elements, the heuristic is applied on a per-paragraph level." />
+ <style>
+ body {
+ font-size:18px;
+ text-align:left;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x200E; - LRM, the invisible left-to-right mark (strongly LTR).
+ &#x200F; - RLM, the invisible right-to-left mark (strongly RTL).
+ We use text-align:left because neither the dir="auto" nor the unicode-bidi:plaintext
+ specification states whether text-align:start and text-align:end should obey the paragraph
+ direction or the direction property in a unicode-bidi:plaintext element.
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <pre dir="auto">
+@&#x200E;123&#x200F;!
+!&#x200F;123&#x200E;@
+@123&#x200E;&#x200F;!
+!123&#x200F;&#x200E;@
+ </pre>
+ </div>
+ <div dir="rtl">
+ <pre dir="auto">
+@&#x200E;123&#x200F;!
+!&#x200F;123&#x200E;@
+@123&#x200E;&#x200F;!
+!123&#x200F;&#x200E;@
+ </pre>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <pre dir="ltr">
+@123!
+@123!
+@123!
+@123!
+ </pre>
+ </div>
+ <div dir="rtl">
+ <pre dir="ltr">
+@123!
+@123!
+@123!
+@123!
+ </pre>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-textarea-N-EN-ref.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-textarea-N-EN-ref.html
new file mode 100644
index 00000000000..253b84459ee
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-textarea-N-EN-ref.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <style>
+ body, textarea {
+ font-size:18px;
+ text-align:left;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="test">
+ <div dir="ltr">
+ <textarea rows="2" dir="ltr">
+@123!
+ </textarea>
+ </div>
+ <div dir="rtl">
+ <textarea rows="2" dir="ltr">
+@123!
+ </textarea>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <textarea rows="2" dir="ltr">
+@123!
+ </textarea>
+ </div>
+ <div dir="rtl">
+ <textarea rows="2" dir="ltr">
+@123!
+ </textarea>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-textarea-N-EN.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-textarea-N-EN.html
new file mode 100644
index 00000000000..f0fa2161a16
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-textarea-N-EN.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: textarea with dir=auto, all N+EN</title>
+ <link rel="match" href="dir_auto-textarea-N-EN-ref.html" />
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <link rel="help" href="http://dev.w3.org/csswg/css3-writing-modes/#unicode-bidi0" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of the text.
+ For textarea and pre elements, the heuristic is applied on a per-paragraph level.
+ If there is no strong character, as in this test, the direction defaults to LTR." />
+ <style>
+ body, textarea {
+ font-size:18px;
+ text-align:left;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x200E; - LRM, the invisible left-to-right mark (strongly LTR).
+ &#x200F; - RLM, the invisible right-to-left mark (strongly RTL).
+ We use text-align:left because neither the dir="auto" nor the unicode-bidi:plaintext
+ specification states whether text-align:start and text-align:end should obey the paragraph
+ direction or the direction property in a unicode-bidi:plaintext element.
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <textarea rows="2" dir="auto">
+@123!
+ </textarea>
+ </div>
+ <div dir="rtl">
+ <textarea rows="2" dir="auto">
+@123!
+ </textarea>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <textarea rows="2" dir="ltr">
+@123!
+ </textarea>
+ </div>
+ <div dir="rtl">
+ <textarea rows="2" dir="ltr">
+@123!
+ </textarea>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-textarea-N-between-Rs-ref.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-textarea-N-between-Rs-ref.html
new file mode 100644
index 00000000000..afeef08cbf2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-textarea-N-between-Rs-ref.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <style>
+ body, textarea {
+ font-size:18px;
+ text-align:left;
+ }
+ textarea {
+ resize: none;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <textarea rows="4" dir="rtl">
+&#x05D0;
+!...
+&#x05D0;
+ </textarea>
+ </div>
+ <div dir="rtl">
+ <textarea rows="4" dir="rtl">
+&#x05D0;
+!...
+&#x05D0;
+ </textarea>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <textarea rows="4" dir="rtl">
+&#x05D0;
+!...
+&#x05D0;
+ </textarea>
+ </div>
+ <div dir="rtl">
+ <textarea rows="4" dir="rtl">
+&#x05D0;
+!...
+&#x05D0;
+ </textarea>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-textarea-N-between-Rs.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-textarea-N-between-Rs.html
new file mode 100644
index 00000000000..ddae91054ae
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-textarea-N-between-Rs.html
@@ -0,0 +1,79 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: textarea with dir=auto, all-N between all-Rs</title>
+ <link rel="match" href="dir_auto-textarea-N-between-Rs-ref.html" />
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <link rel="help" href="http://dev.w3.org/csswg/css3-writing-modes/#unicode-bidi0" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of the text.
+ For textarea and pre elements, the heuristic is applied on a per-paragraph level.
+ If there is no strong character, as in this test, the direction defaults to LTR." />
+ <style>
+ body, textarea {
+ font-size:18px;
+ text-align:left;
+ }
+ textarea {
+ resize: none;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ We use text-align:left because neither the dir="auto" nor the unicode-bidi:plaintext
+ specification states whether text-align:start and text-align:end should obey the paragraph
+ direction or the direction property in a unicode-bidi:plaintext element.
+ The ...! paragraph, being neutral, is supposed to be displayed LTR (i.e. as ...!, not as !...)
+ despite both the paragraph before it and the paragraph after it being all-RTL, which makes the
+ element as a whole RTL.
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <textarea rows="4" dir="auto">
+&#x05D0;
+...!
+&#x05D0;
+ </textarea>
+ </div>
+ <div dir="rtl">
+ <textarea rows="4" dir="auto">
+&#x05D0;
+...!
+&#x05D0;
+ </textarea>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <textarea rows="4" dir="rtl">
+&#x05D0;
+!...
+&#x05D0;
+ </textarea>
+ </div>
+ <div dir="rtl">
+ <textarea rows="4" dir="rtl">
+&#x05D0;
+!...
+&#x05D0;
+ </textarea>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-textarea-mixed-ref.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-textarea-mixed-ref.html
new file mode 100644
index 00000000000..a5a84480f6f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-textarea-mixed-ref.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <style>
+ body, textarea {
+ font-size:18px;
+ text-align:left;
+ }
+ textarea {
+ resize: none;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="test">
+ <div dir="ltr">
+ <textarea rows="5" dir="rtl">
+!123@
+!123@
+!123@
+!123@
+ </textarea>
+ </div>
+ <div dir="rtl">
+ <textarea rows="5" dir="ltr">
+@123!
+@123!
+@123!
+@123!
+ </textarea>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <textarea rows="5" dir="rtl">
+!123@
+!123@
+!123@
+!123@
+ </textarea>
+ </div>
+ <div dir="rtl">
+ <textarea rows="5" dir="ltr">
+@123!
+@123!
+@123!
+@123!
+ </textarea>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-textarea-mixed.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-textarea-mixed.html
new file mode 100644
index 00000000000..4947124c999
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-textarea-mixed.html
@@ -0,0 +1,80 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: textarea with dir=auto, mixed L and R paragraphs</title>
+ <link rel="match" href="dir_auto-textarea-mixed-ref.html" />
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <link rel="help" href="http://dev.w3.org/csswg/css3-writing-modes/#unicode-bidi0" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of the text.
+ For textarea and pre elements, the heuristic is applied on a per-paragraph level." />
+ <style>
+ body, textarea {
+ font-size:18px;
+ text-align:left;
+ }
+ textarea {
+ resize: none;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x200E; - LRM, the invisible left-to-right mark (strongly LTR).
+ &#x200F; - RLM, the invisible right-to-left mark (strongly RTL).
+ We use text-align:left because neither the dir="auto" nor the unicode-bidi:plaintext
+ specification states whether text-align:start and text-align:end should obey the paragraph
+ direction or the direction property in a unicode-bidi:plaintext element.
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <textarea rows="5" dir="auto">
+!&#x200F;123&#x200E;@
+@&#x200E;123&#x200F;!
+!123&#x200F;&#x200E;@
+@123&#x200E;&#x200F;!
+ </textarea>
+ </div>
+ <div dir="rtl">
+ <textarea rows="5" dir="auto">
+@&#x200E;123&#x200F;!
+!&#x200F;123&#x200E;@
+@123&#x200E;&#x200F;!
+!123&#x200F;&#x200E;@
+ </textarea>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <textarea rows="5" dir="rtl">
+!123@
+!123@
+!123@
+!123@
+ </textarea>
+ </div>
+ <div dir="rtl">
+ <textarea rows="5" dir="ltr">
+@123!
+@123!
+@123!
+@123!
+ </textarea>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-textarea-script-N-EN-ref.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-textarea-script-N-EN-ref.html
new file mode 100644
index 00000000000..253b84459ee
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-textarea-script-N-EN-ref.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <style>
+ body, textarea {
+ font-size:18px;
+ text-align:left;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="test">
+ <div dir="ltr">
+ <textarea rows="2" dir="ltr">
+@123!
+ </textarea>
+ </div>
+ <div dir="rtl">
+ <textarea rows="2" dir="ltr">
+@123!
+ </textarea>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <textarea rows="2" dir="ltr">
+@123!
+ </textarea>
+ </div>
+ <div dir="rtl">
+ <textarea rows="2" dir="ltr">
+@123!
+ </textarea>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-textarea-script-N-EN.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-textarea-script-N-EN.html
new file mode 100644
index 00000000000..3c674e2f82a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-textarea-script-N-EN.html
@@ -0,0 +1,77 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: textarea with dir=auto, script assigns to all N+EN</title>
+ <link rel="match" href="dir_auto-textarea-script-N-EN-ref.html" />
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <link rel="help" href="http://dev.w3.org/csswg/css3-writing-modes/#unicode-bidi0" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of the text.
+ For textarea and pre elements, the heuristic is applied on a per-paragraph level.
+ If there is no strong character, as in this test, the direction defaults to LTR." />
+ <style>
+ body, textarea {
+ font-size:18px;
+ text-align:left;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x200E; - LRM, the invisible left-to-right mark (strongly LTR).
+ &#x200F; - RLM, the invisible right-to-left mark (strongly RTL).
+ This test makes sure that the direction is set correctly for a textarea whose value is set
+ dynamically by script.
+ We use text-align:left because neither the dir="auto" nor the unicode-bidi:plaintext
+ specification states whether text-align:start and text-align:end should obey the paragraph
+ direction or the direction property in a unicode-bidi:plaintext element.
+ </div>
+ <div id="test" class="test">
+ <script>
+ window.onload = function() {
+ var test = document.getElementById('test');
+ var textareas = test.getElementsByTagName('textarea');
+ for (var i = 0; i != textareas.length; i++) {
+ textareas[i].value = '@123!\n';
+ }
+ }
+ </script>
+ <div dir="ltr">
+ <textarea rows="2" dir="auto">
+&#x200F;
+ </textarea>
+ </div>
+ <div dir="rtl">
+ <textarea rows="2" dir="auto">
+&#x200F;
+ </textarea>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <textarea rows="2" dir="ltr">
+@123!
+ </textarea>
+ </div>
+ <div dir="rtl">
+ <textarea rows="2" dir="ltr">
+@123!
+ </textarea>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-textarea-script-N-between-Rs-ref.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-textarea-script-N-between-Rs-ref.html
new file mode 100644
index 00000000000..814e7b65697
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-textarea-script-N-between-Rs-ref.html
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <link rel="match" href="dir_auto-textarea-N-between-Rs-ref.html" />
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <style>
+ body, textarea {
+ font-size:18px;
+ text-align:left;
+ }
+ textarea {
+ resize: none;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ <textarea rows="4" dir="rtl">
+&#x05D0;
+!...
+&#x05D0;
+ </textarea>
+ </div>
+ <div dir="rtl">
+ <textarea rows="4" dir="rtl">
+&#x05D0;
+!...
+&#x05D0;
+ </textarea>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <textarea rows="4" dir="rtl">
+&#x05D0;
+!...
+&#x05D0;
+ </textarea>
+ </div>
+ <div dir="rtl">
+ <textarea rows="4" dir="rtl">
+&#x05D0;
+!...
+&#x05D0;
+ </textarea>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-textarea-script-N-between-Rs.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-textarea-script-N-between-Rs.html
new file mode 100644
index 00000000000..d16837b2f72
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-textarea-script-N-between-Rs.html
@@ -0,0 +1,86 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: textarea with dir=auto, script assigns to all-N between all-Rs</title>
+ <link rel="match" href="dir_auto-textarea-script-N-between-Rs-ref.html" />
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <link rel="help" href="http://dev.w3.org/csswg/css3-writing-modes/#unicode-bidi0" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of the text.
+ For textarea and pre elements, the heuristic is applied on a per-paragraph level.
+ If there is no strong character, as in this test, the direction defaults to LTR." />
+ <style>
+ body, textarea {
+ font-size:18px;
+ text-align:left;
+ }
+ textarea {
+ resize: none;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; - The Hebrew letter Alef (strongly RTL).
+ This test makes sure that the direction is set correctly for a textarea whose value is set
+ dynamically by script.
+ We use text-align:left because neither the dir="auto" nor the unicode-bidi:plaintext
+ specification states whether text-align:start and text-align:end should obey the paragraph
+ direction or the direction property in a unicode-bidi:plaintext element.
+ The ...! paragraph, being neutral, is supposed to be displayed LTR (i.e. as ...!, not as !...)
+ despite both the paragraph before it and the paragraph after it being all-RTL, which makes the
+ element as a whole RTL.
+ </div>
+ <div id="test" class="test">
+ <script>
+ window.onload = function() {
+ var test = document.getElementById('test');
+ var textareas = test.getElementsByTagName('textarea');
+ for (var i = 0; i != textareas.length; i++) {
+ textareas[i].value = '\u05D0\n...!\n\u05D0';
+ }
+ }
+ </script>
+ <div dir="ltr">
+ <textarea rows="4" dir="auto">
+LTR text
+ </textarea>
+ </div>
+ <div dir="rtl">
+ <textarea rows="4" dir="auto">
+LTR text
+ </textarea>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <textarea rows="4" dir="rtl">
+&#x05D0;
+!...
+&#x05D0;
+ </textarea>
+ </div>
+ <div dir="rtl">
+ <textarea rows="4" dir="rtl">
+&#x05D0;
+!...
+&#x05D0;
+ </textarea>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-textarea-script-mixed-ref.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-textarea-script-mixed-ref.html
new file mode 100644
index 00000000000..a5a84480f6f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-textarea-script-mixed-ref.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <style>
+ body, textarea {
+ font-size:18px;
+ text-align:left;
+ }
+ textarea {
+ resize: none;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="test">
+ <div dir="ltr">
+ <textarea rows="5" dir="rtl">
+!123@
+!123@
+!123@
+!123@
+ </textarea>
+ </div>
+ <div dir="rtl">
+ <textarea rows="5" dir="ltr">
+@123!
+@123!
+@123!
+@123!
+ </textarea>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <textarea rows="5" dir="rtl">
+!123@
+!123@
+!123@
+!123@
+ </textarea>
+ </div>
+ <div dir="rtl">
+ <textarea rows="5" dir="ltr">
+@123!
+@123!
+@123!
+@123!
+ </textarea>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-textarea-script-mixed.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-textarea-script-mixed.html
new file mode 100644
index 00000000000..f0c6d4fe44b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/dir_auto-textarea-script-mixed.html
@@ -0,0 +1,100 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: textarea with dir=auto, script assigns to mixed L and R paragraphs</title>
+ <link rel="match" href="dir_auto-textarea-script-mixed-ref.html" />
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dir-attribute" />
+ <link rel="help" href="http://dev.w3.org/csswg/css3-writing-modes/#unicode-bidi0" />
+ <meta name="assert" content="
+ When dir='auto', the direction is set according to the first strong character
+ of the text.
+ For textarea and pre elements, the heuristic is applied on a per-paragraph level." />
+ <style>
+ body, textarea {
+ font-size:18px;
+ text-align:left;
+ }
+ textarea {
+ resize: none;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x200E; - LRM, the invisible left-to-right mark (strongly LTR).
+ &#x200F; - RLM, the invisible right-to-left mark (strongly RTL).
+ This test makes sure that the direction is set correctly for a textarea whose value is set
+ dynamically by script.
+ We use text-align:left because neither the dir="auto" nor the unicode-bidi:plaintext
+ specification states whether text-align:start and text-align:end should obey the paragraph
+ direction or the direction property in a unicode-bidi:plaintext element.
+ </div>
+ <div id="test" class="test">
+ <script>
+ window.onload = function() {
+ var test = document.getElementById('test');
+ var textareas = test.getElementsByTagName('textarea');
+ for (var i = 0; i != textareas.length; i++) {
+ var input = textareas[i];
+ if (input.parentNode.dir == 'ltr') {
+ // Assign a value whose first strong is RTL.
+ input.value =
+ '!\u200F123\u200E@\n' +
+ '@\u200E123\u200F!\n' +
+ '!123\u200F\u200E@\n' +
+ '@123\u200E\u200F!\n';
+ } else {
+ // Assign a value whose first strong is LTR.
+ input.value =
+ '@\u200E123\u200F!\n' +
+ '!\u200F123\u200E@\n' +
+ '@123\u200E\u200F!\n' +
+ '!123\u200F\u200E@\n';
+ }
+ }
+ }
+ </script>
+ <div dir="ltr">
+ <textarea rows="5" dir="auto">
+&#x200E;
+ </textarea>
+ </div>
+ <div dir="rtl">
+ <textarea rows="5" dir="auto">
+&#x200F;
+ </textarea>
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ <textarea rows="5" dir="rtl">
+!123@
+!123@
+!123@
+!123@
+ </textarea>
+ </div>
+ <div dir="rtl">
+ <textarea rows="5" dir="ltr">
+@123!
+@123!
+@123!
+@123!
+ </textarea>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/document-dir.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/document-dir.html
new file mode 100644
index 00000000000..675b4bc9d93
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/document-dir.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html dir="LTR">
+<title>document.dir</title>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-document-dir">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#reflect">
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ assert_equals(document.dir, "ltr");
+ assert_equals(document.documentElement.getAttribute("dir"), "LTR");
+}, "Markup attribute")
+test(function() {
+ document.dir = "x-garbage";
+ assert_equals(document.dir, "");
+ assert_equals(document.documentElement.getAttribute("dir"), "x-garbage");
+}, "Setting the idl attribute to a garbage value")
+test(function() {
+ document.dir = "";
+ assert_true(document.documentElement.hasAttribute("dir"), "Attribute should still be around");
+ assert_equals(document.dir, "");
+ assert_equals(document.documentElement.getAttribute("dir"), "");
+}, "Setting the idl attribute to the empty string")
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/id-attribute.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/id-attribute.html
new file mode 100644
index 00000000000..0171148fb1e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/id-attribute.html
@@ -0,0 +1,130 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>The id attribute</title>
+<meta charset=utf8>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-id-attribute">
+<style>
+
+#abcd {
+ position: absolute;
+ z-index: 1;
+}
+
+#ABCD {
+ position: absolute;
+ z-index: 2;
+}
+
+#a\ b {
+ position: absolute;
+ z-index: 3;
+}
+
+#xyz {
+ position: absolute;
+ z-index: 4;
+}
+
+#foobar {
+ position: absolute;
+ z-index: 5;
+}
+
+#åèiöú {
+ position: absolute;
+ z-index: 6;
+}
+
+</style>
+</head>
+<body>
+<h1>The id attribute</h1>
+<div id="log"></div>
+<i id="abcd"></i>
+<i id="ABCD"></i>
+<i id="a b"></i>
+<i id="åèiöú"></i>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+ // id is associated for purposes of getElementById
+ test(function() {
+ assert_equals(document.getElementById("abcd"), document.getElementsByTagName("i")[0]);
+ }, "User agents must associate the element with an id value for purposes of getElementById.");
+
+ test(function() {
+ assert_equals(document.getElementById("ABCD"), document.getElementsByTagName("i")[1]);
+ }, "Association is exact and therefore case-sensitive for getElementById.");
+
+ test(function() {
+ assert_equals(document.getElementById("a b"), document.getElementsByTagName("i")[2]);
+ }, "Spaces are allowed in an id and still make an association for getElementByID.");
+
+ test(function() {
+ assert_equals(document.getElementById("åèiöú"), document.getElementsByTagName("i")[3]);
+ }, "Non-ASCII is allowed in an id and still make an association for getElementById.");
+
+
+ // id is associated for purposes of CSS
+ test(function() {
+ assert_equals(document.defaultView.getComputedStyle(document.getElementById("abcd"), false).zIndex, "1");
+ }, "User agents must associate the element with an id value for purposes of CSS.");
+
+ test(function() {
+ assert_equals(document.defaultView.getComputedStyle(document.getElementById("ABCD"), false).zIndex, "2");
+ }, "Association for CSS is exact and therefore case-sensitive.");
+
+ test(function() {
+ assert_equals(document.defaultView.getComputedStyle(document.getElementById("a b"), false).zIndex, "3");
+ }, "Spaces are allowed in an id and still make an association.");
+
+ test(function() {
+ assert_equals(document.defaultView.getComputedStyle(document.getElementById("åèiöú"), false).zIndex, "6");
+ }, "Non-ASCII is allowed in an id and still make an association for CSS.");
+
+
+ // id IDL attribute reflects the content attribute
+ var firstSpan = document.getElementById("abcd");
+
+ test(function() {
+ assert_equals(firstSpan.id, "abcd");
+ }, "The id IDL attribute must reflect the id content attribute, for getting.");
+
+ test(function() {
+ firstSpan.id = "xyz";
+ assert_equals(firstSpan.getAttribute("id"), "xyz");
+ }, "The id IDL attribute must reflect the id content attribute, for setting via IDL attribute.");
+
+ test(function() {
+ assert_equals(document.getElementById("xyz"), firstSpan);
+ }, "After setting id via id attribute, getElementById find the element by the new id.");
+
+ test(function() {
+ assert_equals(document.getElementById("abcd"), null);
+ }, "After setting id via id attribute, getElementById doesn't find the element by the old id.");
+
+ test(function() {
+ assert_equals(document.defaultView.getComputedStyle(firstSpan, false).zIndex, "4");
+ }, "After setting id via id attribute, CSS association is via the new ID.");
+
+ test(function() {
+ firstSpan.setAttribute("id", "foobar");
+ assert_equals(firstSpan.id, "foobar");
+ }, "The id IDL attribute must reflect the id content attribute, for setting via setAttribute.");
+
+ test(function() {
+ assert_equals(document.getElementById("foobar"), firstSpan);
+ }, "After setting id via setAttribute attribute, getElementById find the element by the new id.");
+
+ test(function() {
+ assert_equals(document.getElementById("xyz"), null);
+ }, "After setting id via setAttribute attribute, getElementById doesn't find the element by the old id.");
+
+ test(function() {
+ assert_equals(document.defaultView.getComputedStyle(firstSpan, false).zIndex, "5");
+ }, "After setting id via setAttribute attribute, CSS association is via the new ID.");
+
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/id-name-specialcase.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/id-name-specialcase.html
new file mode 100644
index 00000000000..a28f79e6fcb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/id-name-specialcase.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<title>HTML5: test id with none pure alpha characters </title>
+<link rel="author" title="justin.shen" href=mailto:cosmichut@msn.com">
+<link rel="stylesheet" href="/resources/testharness.css">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<div style="display:none">
+ <input id="123" value="123"></input>
+ <input id="1test" value="1test"></input>
+ <input id="_test" value="_test"></input>
+ <input id="." value="."></input>
+ <input id="中国" value="china"></input>
+</div>
+<script>
+test(function() {
+ assert_equals(document.getElementById("123").value, "123");
+}, "id with digits only");
+test(function() {
+ assert_equals(document.getElementById("1test").value, "1test");
+},"id start with digits");
+test(function() {
+ assert_equals(document.getElementById("_test").value, "_test");
+},"id start with underscore");
+test(function() {
+ assert_equals(document.getElementById(".").value, ".");
+},"id with punctuation only");
+test(function() {
+ assert_equals(document.getElementById("中国").value, "china");
+},"id with chinese character");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/id-name.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/id-name.html
new file mode 100644
index 00000000000..9946b680de1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/id-name.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<title>id and name attributes and getElementById</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-id-attribute">
+<link rel="stylesheet" href="/resources/testharness.css">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<div id="test">
+<div name="abcd"></div>
+<p name="abcd" id="abcd"></p>
+</div>
+<script>
+test(function() {
+ assert_equals(document.getElementById("abcd").nodeName, "P");
+ assert_equals(document.getElementById("abcd").localName, "p");
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/lang-xmllang-01-ref.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/lang-xmllang-01-ref.html
new file mode 100644
index 00000000000..1606bca2158
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/lang-xmllang-01-ref.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<title>Languages</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-lang-and-xml:lang-attributes">
+<link tel="help" href="http://www.w3.org/TR/CSS2/selector.html#lang">
+<meta name="flags" content="css21">
+<style>
+#test > * { background: limegreen; }
+</style>
+<body>
+<p>All lines below should have a green background.</p>
+<div id="test">
+<div><p>{}{lang}{en}</p></div>
+<div><p>{}{xml:lang}{en}</p></div>
+<div><div><p>Parent: {}{lang}{en}</p></div></div>
+<div><div><p>Parent: {}{xml:lang}{en}</p></div></div>
+<div><p>{xml}{lang}{en}</p></div>
+<div><p>{xml}{lang}{en} - {lang}{de}</p></div>
+<div><p>{xml}{lang}{de} - {lang}{en}</p></div>
+</div>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/lang-xmllang-01.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/lang-xmllang-01.html
new file mode 100644
index 00000000000..9538f15ca8c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/lang-xmllang-01.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<title>Languages</title>
+<link rel="match" href="lang-xmllang-01-ref.html">
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-lang-and-xml:lang-attributes">
+<link tel="help" href="http://www.w3.org/TR/CSS2/selector.html#lang">
+<meta name="flags" content="css21">
+<style>
+#test #a :lang(en) { background: limegreen; }
+#test #b :lang(nl) { background: limegreen; }
+#test #c :lang(en) { background: limegreen; }
+#test #d :lang(nl) { background: limegreen; }
+#test #e :lang(en) { background: limegreen; }
+#test #f :lang(en) { background: limegreen; }
+#test #g :lang(de) { background: limegreen; }
+</style>
+<body>
+<p>All lines below should have a green background.</p>
+<div id="test" lang="nl">
+<div id="a"><p lang="en">{}{lang}{en}</p></div>
+<div id="b"><p xml:lang="en">{}{xml:lang}{en}</p></div>
+<div id="c"><div lang="en"><p>Parent: {}{lang}{en}</p></div></div>
+<div id="d"><div xml:lang="en"><p>Parent: {}{xml:lang}{en}</p></div></div>
+</div>
+<script>
+try {
+ var XML = "http://www.w3.org/XML/1998/namespace";
+ var container = document.getElementById("test");
+
+ var div = document.createElement("div");
+ div.id = "e";
+ var testNode = document.createElement("p");
+ testNode.appendChild(document.createTextNode("{xml}{lang}{en}"));
+ testNode.setAttributeNS(XML, "xml:lang", "en");
+ div.appendChild(testNode);
+ container.appendChild(div);
+
+ div = document.createElement("div");
+ div.id = "f";
+ testNode = document.createElement("p");
+ testNode.appendChild(document.createTextNode("{xml}{lang}{en} - {lang}{de}"));
+ testNode.setAttributeNS(XML, "xml:lang", "en");
+ testNode.setAttributeNS(null, "lang", "de");
+ div.appendChild(testNode);
+ container.appendChild(div);
+
+ div = document.createElement("div");
+ div.id = "g";
+ testNode = document.createElement("p");
+ testNode.appendChild(document.createTextNode("{xml}{lang}{de} - {lang}{en}"));
+ testNode.setAttributeNS(XML, "xml:lang", "de");
+ testNode.setAttributeNS(null, "lang", "en");
+ container.appendChild(testNode);
+ div.appendChild(testNode);
+ container.appendChild(div);
+} catch (e) {
+}
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/lang-xyzzy-ref.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/lang-xyzzy-ref.html
new file mode 100644
index 00000000000..b2037182b93
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/lang-xyzzy-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<title>Invalid languages</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<meta name="flags" content="css21">
+<style>#testp { color: green; }</style>
+<body>
+<div id="test">
+<p id="testp" lang="xyzzy">ABC</p>
+</div>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/lang-xyzzy.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/lang-xyzzy.html
new file mode 100644
index 00000000000..d6e6aeb6475
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/lang-xyzzy.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<title>Invalid languages</title>
+<link rel="match" href="lang-xyzzy-ref.html">
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-lang-and-xml:lang-attributes">
+<link tel="help" href="http://www.w3.org/TR/CSS2/selector.html#lang">
+<meta name="flags" content="css21">
+<style>:lang(xyzzy) { color: green; }</style>
+<body>
+<div id="test">
+<p id="testp" lang="xyzzy">ABC</p>
+</div>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/style-01-ref.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/style-01-ref.html
new file mode 100644
index 00000000000..be8175e61d4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/style-01-ref.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<title>The style attribute</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-style-attribute">
+<link rel="help" href="http://www.w3.org/TR/css-style-attr/#syntax">
+<link rel="help" href="http://www.w3.org/TR/CSS21/cascade.html#cascading-order">
+<link rel="help" href="http://www.w3.org/TR/CSS21/cascade.html#specificity">
+<style>
+#test p { background: limegreen; }
+</style>
+<div id="test">
+<p>This line should have a green background.
+<p>This line should have a green background.
+<p>This line should have a green background.
+<p>This line should have a green background.
+<p>This line should have a green background.
+<p>This line should have a green background.
+<p>This line should have a green background.
+<p>This line should have a green background.
+<p>This line should have a green background.
+<p>This line should have a green background.
+<p>This line should have a green background.
+<p>This line should have a green background.
+</div>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/style-01.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/style-01.html
new file mode 100644
index 00000000000..c0e09958065
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/style-01.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>The style attribute</title>
+<link rel="match" href="style-01-ref.html">
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-style-attribute">
+<link rel="help" href="http://www.w3.org/TR/css-style-attr/#syntax">
+<link rel="help" href="http://www.w3.org/TR/CSS21/cascade.html#cascading-order">
+<link rel="help" href="http://www.w3.org/TR/CSS21/cascade.html#specificity">
+<style>
+#idsel { background: red; }
+#idsel2 { background: limegreen !important; }
+</style>
+<div id="test">
+<p style="background:limegreen">This line should have a green background.
+<p style="/**/background:limegreen">This line should have a green background.
+<p style="background/**/:limegreen">This line should have a green background.
+<p style="background:/**/limegreen">This line should have a green background.
+<p style="background:limegreen/**/">This line should have a green background.
+<p id="idsel1" style="background:limegreen">This line should have a green background.
+<p id="idsel2" style="background:red">This line should have a green background.
+<p style="background:limegreen; background:r/**/ed">This line should have a green background.
+<p style="background:limegreen;}">This line should have a green background.
+<p style="};background:limegreen">This line should have a green background.
+<p style="background:red;};background:limegreen">This line should have a green background.
+<p style="background:limegreen;{background:red}">This line should have a green background.
+</div>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-001.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-001.html
new file mode 100644
index 00000000000..c2966f36206
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-001.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html lang="ko" >
+<head>
+<meta charset="utf-8"/>
+<title>lang attribute in html tag</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='https://html.spec.whatwg.org/multipage/#the-lang-and-xml:lang-attributes'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<meta name='flags' content='dom'>
+<style type='text/css'>
+ #colonlangcontroltest { color: red; font-weight: bold; width: 400px; }
+ #colonlangcontroltest:lang(xx) { display:none; }
+.test div { width: 50px; }
+#box:lang(ko) { width: 100px; }
+</style>
+</head>
+<body>
+
+
+
+<div class="test"><div id="box">&#xA0;</div></div>
+<p lang='xx' id='colonlangcontroltest'>This test failed because it relies on :lang for results, but :lang is not supported by this browser.</p>
+
+
+<!--Notes:
+
+This test uses :lang to detect whether the language has been set. If :lang is not supported, a message will appear and the test will fail.
+
+-->
+<script>
+test(function() {
+assert_equals(document.getElementById('colonlangcontroltest').offsetWidth, 0)
+assert_equals(document.getElementById('box').offsetWidth, 100);
+}, "The browser will recognize a language declared in a lang attribute on the html tag.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-002.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-002.html
new file mode 100644
index 00000000000..205bc35f2de
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-002.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html xml:lang="ko" >
+<head>
+<meta charset="utf-8"/>
+<title>xml:lang attribute in html tag</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='https://html.spec.whatwg.org/multipage/#the-lang-and-xml:lang-attributes'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<meta name='flags' content='dom'>
+<style type='text/css'>
+ #colonlangcontroltest { color: red; font-weight: bold; width: 400px; }
+ #colonlangcontroltest:lang(xx) { display:none; }
+.test div { width: 50px; }
+#box:lang(ko) { width: 100px; }
+</style>
+</head>
+<body>
+
+
+
+<div class="test"><div id="box">&#xA0;</div></div>
+<p lang='xx' id='colonlangcontroltest'>This test failed because it relies on :lang for results, but :lang is not supported by this browser.</p>
+
+
+<!--Notes:
+
+This test uses :lang to detect whether the language has been set. If :lang is not supported, a message will appear and the test will fail.
+
+-->
+<script>
+test(function() {
+assert_equals(document.getElementById('colonlangcontroltest').offsetWidth, 0)
+assert_equals(document.getElementById('box').offsetWidth, 50);
+}, "The browser will NOT recognize a language declared in an xml:lang attribute on the html tag.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-003.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-003.html
new file mode 100644
index 00000000000..717aa12e689
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-003.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html >
+<head>
+<meta charset="utf-8"/>
+<title>HTTP header</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='https://html.spec.whatwg.org/multipage/#the-lang-and-xml:lang-attributes'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<meta name='flags' content='http dom'>
+<style type='text/css'>
+ #colonlangcontroltest { color: red; font-weight: bold; width: 400px; }
+ #colonlangcontroltest:lang(xx) { display:none; }
+.test div { width: 50px; }
+#box:lang(ko) { width: 100px; }
+</style>
+</head>
+<body>
+
+
+
+<div class="test"><div id="box">&#xA0;</div></div>
+<p lang='xx' id='colonlangcontroltest'>This test failed because it relies on :lang for results, but :lang is not supported by this browser.</p>
+
+
+<!--Notes:
+
+This test uses :lang to detect whether the language has been set. If :lang is not supported, a message will appear and the test will fail.
+
+-->
+<script>
+test(function() {
+assert_equals(document.getElementById('colonlangcontroltest').offsetWidth, 0)
+assert_equals(document.getElementById('box').offsetWidth, 100);
+}, "The browser will recognize a language declared in the HTTP header, when there is no internal language declaration.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-003.html.headers b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-003.html.headers
new file mode 100644
index 00000000000..0c47ecd4fa7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-003.html.headers
@@ -0,0 +1 @@
+Content-Language: ko
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-004.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-004.html
new file mode 100644
index 00000000000..ff36f75add8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-004.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html >
+<head>
+<meta charset="utf-8"/>
+ <meta http-equiv="Content-Language" content="ko" >
+<title>pragma-set default</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='https://html.spec.whatwg.org/multipage/#the-lang-and-xml:lang-attributes'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<meta name='flags' content='dom'>
+<style type='text/css'>
+ #colonlangcontroltest { color: red; font-weight: bold; width: 400px; }
+ #colonlangcontroltest:lang(xx) { display:none; }
+.test div { width: 50px; }
+#box:lang(ko) { width: 100px; }
+</style>
+</head>
+<body>
+
+
+
+<div class="test"><div id="box">&#xA0;</div></div>
+<p lang='xx' id='colonlangcontroltest'>This test failed because it relies on :lang for results, but :lang is not supported by this browser.</p>
+
+
+<!--Notes:
+
+This test uses :lang to detect whether the language has been set. If :lang is not supported, a message will appear and the test will fail.
+
+-->
+<script>
+test(function() {
+assert_equals(document.getElementById('colonlangcontroltest').offsetWidth, 0)
+assert_equals(document.getElementById('box').offsetWidth, 100);
+}, "The browser will recognize a language declared in a meta element in the head using http-equiv='Content-Language' content='..' (with a single language tag value), when there is no other language declaration inside the document.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-005.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-005.html
new file mode 100644
index 00000000000..63fb8e3bbbd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-005.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html lang="ko" >
+<head>
+<meta charset="utf-8"/>
+<title>HTTP header and html lang</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='https://html.spec.whatwg.org/multipage/#the-lang-and-xml:lang-attributes'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<meta name='flags' content='http dom'>
+<style type='text/css'>
+ #colonlangcontroltest { color: red; font-weight: bold; width: 400px; }
+ #colonlangcontroltest:lang(xx) { display:none; }
+.test div { width: 50px; }
+#box:lang(ko) { width: 100px; }
+</style>
+</head>
+<body>
+
+
+
+<div class="test"><div id="box">&#xA0;</div></div>
+<p lang='xx' id='colonlangcontroltest'>This test failed because it relies on :lang for results, but :lang is not supported by this browser.</p>
+
+
+<!--Notes:
+
+This test uses :lang to detect whether the language has been set. If :lang is not supported, a message will appear and the test will fail.
+
+-->
+<script>
+test(function() {
+assert_equals(document.getElementById('colonlangcontroltest').offsetWidth, 0)
+assert_equals(document.getElementById('box').offsetWidth, 100);
+}, "If there is a conflict between the language declarations in the HTTP header and the html element using lang, the browser will recognize the language declared in the html element.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-005.html.headers b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-005.html.headers
new file mode 100644
index 00000000000..1b971b697a7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-005.html.headers
@@ -0,0 +1 @@
+Content-Language: zh
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-006.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-006.html
new file mode 100644
index 00000000000..ede49120255
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-006.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html >
+<head>
+<meta charset="utf-8"/>
+ <meta http-equiv="Content-Language" content="ko" >
+<title>HTTP header and meta element</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='https://html.spec.whatwg.org/multipage/#the-lang-and-xml:lang-attributes'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<meta name='flags' content='http dom'>
+<style type='text/css'>
+ #colonlangcontroltest { color: red; font-weight: bold; width: 400px; }
+ #colonlangcontroltest:lang(xx) { display:none; }
+.test div { width: 50px; }
+#box:lang(ko) { width: 100px; }
+</style>
+</head>
+<body>
+
+
+
+<div class="test"><div id="box">&#xA0;</div></div>
+<p lang='xx' id='colonlangcontroltest'>This test failed because it relies on :lang for results, but :lang is not supported by this browser.</p>
+
+
+<!--Notes:
+
+This test uses :lang to detect whether the language has been set. If :lang is not supported, a message will appear and the test will fail.
+
+-->
+<script>
+test(function() {
+assert_equals(document.getElementById('colonlangcontroltest').offsetWidth, 0)
+assert_equals(document.getElementById('box').offsetWidth, 100);
+}, "If there is a conflict between the language declarations in the HTTP header and the Content-Language meta element, the UA will recognize the language declared in the meta element.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-006.html.headers b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-006.html.headers
new file mode 100644
index 00000000000..1b971b697a7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-006.html.headers
@@ -0,0 +1 @@
+Content-Language: zh
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-007.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-007.html
new file mode 100644
index 00000000000..8fafef036f6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-007.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html lang="ko" >
+<head>
+<meta charset="utf-8"/>
+ <meta http-equiv="Content-Language" content="zh" >
+<title>html lang and meta elements</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='https://html.spec.whatwg.org/multipage/#the-lang-and-xml:lang-attributes'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<meta name='flags' content='dom'>
+<style type='text/css'>
+ #colonlangcontroltest { color: red; font-weight: bold; width: 400px; }
+ #colonlangcontroltest:lang(xx) { display:none; }
+.test div { width: 50px; }
+#box:lang(ko) { width: 100px; }
+</style>
+</head>
+<body>
+
+
+
+<div class="test"><div id="box">&#xA0;</div></div>
+<p lang='xx' id='colonlangcontroltest'>This test failed because it relies on :lang for results, but :lang is not supported by this browser.</p>
+
+
+<!--Notes:
+
+This test uses :lang to detect whether the language has been set. If :lang is not supported, a message will appear and the test will fail.
+
+-->
+<script>
+test(function() {
+assert_equals(document.getElementById('colonlangcontroltest').offsetWidth, 0)
+assert_equals(document.getElementById('box').offsetWidth, 100);
+}, "If there is a conflict between the language declared using lang in the html element and that in the meta element, the UA will recognize the language declared in the html element.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-008.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-008.html
new file mode 100644
index 00000000000..3be54154c14
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-008.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html >
+<head>
+<meta charset="utf-8"/>
+<title>lang="..." vs lang=""</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='https://html.spec.whatwg.org/multipage/#the-lang-and-xml:lang-attributes'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<meta name='flags' content='dom'>
+<style type='text/css'>
+ #colonlangcontroltest { color: red; font-weight: bold; width: 400px; }
+ #colonlangcontroltest:lang(xx) { display:none; }
+.test div { width: 50px; }
+#box:lang(ko) { width: 100px; }
+</style>
+</head>
+<body>
+
+
+
+<div class="test" lang="ko"><div id="box" lang="">&#xA0;</div></div>
+<p lang='xx' id='colonlangcontroltest'>This test failed because it relies on :lang for results, but :lang is not supported by this browser.</p>
+
+
+<!--Notes:
+
+This test uses :lang to detect whether the language has been set. If :lang is not supported, a message will appear and the test will fail.
+
+-->
+<script>
+test(function() {
+assert_equals(document.getElementById('colonlangcontroltest').offsetWidth, 0)
+assert_equals(document.getElementById('box').offsetWidth, 50);
+}, "If an element contains a lang attribute with an empty value, the value of a lang attribute higher up the document tree will no longer be applied to the content of that element.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-009.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-009.html
new file mode 100644
index 00000000000..3a927028ef9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-009.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html lang="" >
+<head>
+<meta charset="utf-8"/>
+<title>lang="" vs HTTP</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='https://html.spec.whatwg.org/multipage/#the-lang-and-xml:lang-attributes'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<meta name='flags' content='http dom'>
+<style type='text/css'>
+ #colonlangcontroltest { color: red; font-weight: bold; width: 400px; }
+ #colonlangcontroltest:lang(xx) { display:none; }
+.test div { width: 50px; }
+#box:lang(ko) { width: 100px; }
+</style>
+</head>
+<body>
+
+
+
+<div class="test"><div id="box">&#xA0;</div></div>
+<p lang='xx' id='colonlangcontroltest'>This test failed because it relies on :lang for results, but :lang is not supported by this browser.</p>
+
+
+<!--Notes:
+
+This test uses :lang to detect whether the language has been set. If :lang is not supported, a message will appear and the test will fail.
+
+-->
+<script>
+test(function() {
+assert_equals(document.getElementById('colonlangcontroltest').offsetWidth, 0)
+assert_equals(document.getElementById('box').offsetWidth, 50);
+}, "If the HTTP header contains a language declaration but the html element uses an empty lang value, the UA will not recognize the language declared in the HTTP header.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-009.html.headers b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-009.html.headers
new file mode 100644
index 00000000000..0c47ecd4fa7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-009.html.headers
@@ -0,0 +1 @@
+Content-Language: ko
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-010.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-010.html
new file mode 100644
index 00000000000..2c217374713
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-010.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html lang="" >
+<head>
+<meta charset="utf-8"/>
+ <meta http-equiv="Content-Language" content="ko" >
+<title>lang="" vs meta Content-Language</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='https://html.spec.whatwg.org/multipage/#the-lang-and-xml:lang-attributes'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<meta name='flags' content='dom'>
+<style type='text/css'>
+ #colonlangcontroltest { color: red; font-weight: bold; width: 400px; }
+ #colonlangcontroltest:lang(xx) { display:none; }
+.test div { width: 50px; }
+#box:lang(ko) { width: 100px; }
+</style>
+</head>
+<body>
+
+
+
+<div class="test"><div id="box">&#xA0;</div></div>
+<p lang='xx' id='colonlangcontroltest'>This test failed because it relies on :lang for results, but :lang is not supported by this browser.</p>
+
+
+<!--Notes:
+
+This test uses :lang to detect whether the language has been set. If :lang is not supported, a message will appear and the test will fail.
+
+-->
+<script>
+test(function() {
+assert_equals(document.getElementById('colonlangcontroltest').offsetWidth, 0)
+assert_equals(document.getElementById('box').offsetWidth, 50);
+}, "If the meta Content-Language element contains a language declaration but the html element uses an empty lang value, the UA will not recognize the language declared in the meta Content-Language element.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-011.html.headers b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-011.html.headers
new file mode 100644
index 00000000000..827b4348f49
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-lang-attribute-011.html.headers
@@ -0,0 +1 @@
+Content-Language: ko,zh,ja
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-translate-attribute-007.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-translate-attribute-007.html
new file mode 100644
index 00000000000..abce2858a22
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-translate-attribute-007.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+<meta charset="utf-8"/>
+<title>no translate attribute</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='https://html.spec.whatwg.org/multipage/#the-translate-attribute'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style type='text/css'>
+</style>
+</head>
+<body>
+
+
+
+<div class="test"><div id="box">&nbsp;</div></div>
+
+
+<script>
+test(function() {
+assert_true(document.getElementById('box').translate);
+}, "In the default case, ie. with no translate attribute in the page, javascript will detect the translation mode of text as translate-enabled.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-translate-attribute-008.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-translate-attribute-008.html
new file mode 100644
index 00000000000..70486fe59b8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-translate-attribute-008.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+<meta charset="utf-8"/>
+<title>translate=yes</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='https://html.spec.whatwg.org/multipage/#the-translate-attribute'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style type='text/css'>
+</style>
+</head>
+<body>
+
+
+
+<div class="test"><div id="box" translate="yes">&nbsp;</div></div>
+
+
+<script>
+test(function() {
+assert_true(document.getElementById('box').translate);
+}, "If the translate attribute is set to yes, javascript will detect the translation mode of text as translate-enabled.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-translate-attribute-009.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-translate-attribute-009.html
new file mode 100644
index 00000000000..1ab49b0307d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-translate-attribute-009.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+<meta charset="utf-8"/>
+<title>translate=no</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='https://html.spec.whatwg.org/multipage/#the-translate-attribute'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style type='text/css'>
+</style>
+</head>
+<body>
+
+
+
+<div class="test"><div id="box" translate="no">&nbsp;</div></div>
+
+
+<script>
+test(function() {
+assert_false(document.getElementById('box').translate);
+}, "If the translate attribute is set to no, javascript will detect the translation mode of text as no-translate.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-translate-attribute-010.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-translate-attribute-010.html
new file mode 100644
index 00000000000..c45965e0049
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-translate-attribute-010.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+<meta charset="utf-8"/>
+<title>translate inherits no</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='https://html.spec.whatwg.org/multipage/#the-translate-attribute'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style type='text/css'>
+</style>
+</head>
+<body>
+
+
+
+<div class="test"><div id="box" translate="no">&nbsp; <span id="spantest">&nbsp;</span></div></div>
+
+
+<script>
+test(function() {
+assert_false(document.getElementById('spantest').translate);
+}, "If the translate attribute is set to no, javascript will detect the translation mode of elements inside that element with no translate flag as no-translate.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-translate-attribute-011.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-translate-attribute-011.html
new file mode 100644
index 00000000000..101f70e2e7b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-translate-attribute-011.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+<meta charset="utf-8"/>
+<title>translate=yes inside translate=no</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='https://html.spec.whatwg.org/multipage/#the-translate-attribute'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style type='text/css'>
+</style>
+</head>
+<body>
+
+
+
+<div class="test"><div id="box" translate="no">&nbsp; <span id="spantest" translate="yes">&nbsp;</span></div></div>
+
+
+<script>
+test(function() {
+assert_true(document.getElementById('spantest').translate);
+}, "If the translate attribute is set to yes on an element inside an element with the translate attribute set to no, javascript will detect the translation mode of text in the inner element as translate-enabled.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-translate-attribute-012.html b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-translate-attribute-012.html
new file mode 100644
index 00000000000..1d81cfd8b11
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/global-attributes/the-translate-attribute-012.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+<meta charset="utf-8"/>
+<title>translate=""</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='https://html.spec.whatwg.org/multipage/#the-translate-attribute'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style type='text/css'>
+</style>
+</head>
+<body>
+
+
+
+<div class="test"><div id="box" translate="">&nbsp;</div></div>
+
+
+<script>
+test(function() {
+assert_true(document.getElementById('box').translate);
+}, "If the translate attribute is set to a null string, javascript will detect the translation mode of text as translate-enabled.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/.gitkeep b/tests/wpt/web-platform-tests/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/semantics-0/.gitkeep b/tests/wpt/web-platform-tests/html/dom/elements/semantics-0/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/semantics-0/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/wai-aria/.gitkeep b/tests/wpt/web-platform-tests/html/dom/elements/wai-aria/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/wai-aria/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/wai-aria/README.md b/tests/wpt/web-platform-tests/html/dom/elements/wai-aria/README.md
new file mode 100644
index 00000000000..bea30702d1a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/wai-aria/README.md
@@ -0,0 +1 @@
+The test suite for WAI-ARIA is available at: <https://www.w3.org/WAI/PF/testharness/>.
diff --git a/tests/wpt/web-platform-tests/html/dom/elements/wai-aria/contains.json b/tests/wpt/web-platform-tests/html/dom/elements/wai-aria/contains.json
new file mode 100644
index 00000000000..031cde580b2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/elements/wai-aria/contains.json
@@ -0,0 +1,18 @@
+[
+ {
+ "id": "aria-role-attribute",
+ "original_id": "aria-role-attribute"
+ },
+ {
+ "id": "state-and-property-attributes",
+ "original_id": "state-and-property-attributes"
+ },
+ {
+ "id": "sec-strong-native-semantics",
+ "original_id": "sec-strong-native-semantics"
+ },
+ {
+ "id": "sec-implicit-aria-semantics",
+ "original_id": "sec-implicit-aria-semantics"
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/dom/interactions-with-xpath-and-xslt/.gitkeep b/tests/wpt/web-platform-tests/html/dom/interactions-with-xpath-and-xslt/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/interactions-with-xpath-and-xslt/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/dom/interfaces.html b/tests/wpt/web-platform-tests/html/dom/interfaces.html
new file mode 100644
index 00000000000..660ff6693be
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/interfaces.html
@@ -0,0 +1,3382 @@
+<!doctype html>
+<meta charset=utf-8>
+<!-- WARNING: These tests are preliminary and probably partly incorrect. -->
+<title>HTML IDL tests</title>
+<meta name=timeout content=long>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=/resources/WebIDLParser.js></script>
+<script src=/resources/idlharness.js></script>
+
+<h1>HTML IDL tests</h1>
+<div id=log></div>
+
+<!-- URLUtils* stubs -->
+<script type=text/plain class=untested>
+interface URLUtils {
+ stringifier;
+};
+interface URLUtilsReadOnly {
+ stringifier;
+};
+</script>
+<!-- DOM IDLs -->
+<script type=text/plain class=untested>
+[Constructor(DOMString type, optional EventInit eventInitDict)/*,
+ Exposed=(Window,Worker)*/]
+interface Event {
+ readonly attribute DOMString type;
+ readonly attribute EventTarget? target;
+ readonly attribute EventTarget? currentTarget;
+
+ const unsigned short NONE = 0;
+ const unsigned short CAPTURING_PHASE = 1;
+ const unsigned short AT_TARGET = 2;
+ const unsigned short BUBBLING_PHASE = 3;
+ readonly attribute unsigned short eventPhase;
+
+ void stopPropagation();
+ void stopImmediatePropagation();
+
+ readonly attribute boolean bubbles;
+ readonly attribute boolean cancelable;
+ void preventDefault();
+ readonly attribute boolean defaultPrevented;
+
+ [Unforgeable] readonly attribute boolean isTrusted;
+ readonly attribute DOMTimeStamp timeStamp;
+
+ void initEvent(DOMString type, boolean bubbles, boolean cancelable);
+};
+
+dictionary EventInit {
+ boolean bubbles = false;
+ boolean cancelable = false;
+};
+
+[Constructor(DOMString type, optional CustomEventInit eventInitDict)/*,
+ Exposed=(Window,Worker)*/]
+interface CustomEvent : Event {
+ readonly attribute any detail;
+
+ void initCustomEvent(DOMString type, boolean bubbles, boolean cancelable, any detail);
+};
+
+dictionary CustomEventInit : EventInit {
+ any detail = null;
+};
+
+//[Exposed=(Window,Worker)]
+interface EventTarget {
+ void addEventListener(DOMString type, EventListener? callback, optional boolean capture = false);
+ void removeEventListener(DOMString type, EventListener? callback, optional boolean capture = false);
+ boolean dispatchEvent(Event event);
+};
+
+callback interface EventListener {
+ void handleEvent(Event event);
+};
+
+[NoInterfaceObject]
+interface NonElementParentNode {
+ Element? getElementById(DOMString elementId);
+};
+Document implements NonElementParentNode;
+DocumentFragment implements NonElementParentNode;
+
+[NoInterfaceObject]
+interface ParentNode {
+ [SameObject] readonly attribute HTMLCollection children;
+ readonly attribute Element? firstElementChild;
+ readonly attribute Element? lastElementChild;
+ readonly attribute unsigned long childElementCount;
+
+ [Unscopeable] void prepend((Node or DOMString)... nodes);
+ [Unscopeable] void append((Node or DOMString)... nodes);
+
+ [Unscopeable] Element? query(DOMString relativeSelectors);
+ [NewObject, Unscopeable] Elements queryAll(DOMString relativeSelectors);
+ Element? querySelector(DOMString selectors);
+ [NewObject] NodeList querySelectorAll(DOMString selectors);
+};
+Document implements ParentNode;
+DocumentFragment implements ParentNode;
+Element implements ParentNode;
+
+[NoInterfaceObject]
+interface NonDocumentTypeChildNode {
+ readonly attribute Element? previousElementSibling;
+ readonly attribute Element? nextElementSibling;
+};
+Element implements NonDocumentTypeChildNode;
+CharacterData implements NonDocumentTypeChildNode;
+
+[NoInterfaceObject]
+interface ChildNode {
+ [Unscopeable] void before((Node or DOMString)... nodes);
+ [Unscopeable] void after((Node or DOMString)... nodes);
+ [Unscopeable] void replaceWith((Node or DOMString)... nodes);
+ [Unscopeable] void remove();
+};
+DocumentType implements ChildNode;
+Element implements ChildNode;
+CharacterData implements ChildNode;
+
+// XXX unrecognized tokens "class", "extends"
+// https://www.w3.org/Bugs/Public/show_bug.cgi?id=20020
+// https://www.w3.org/Bugs/Public/show_bug.cgi?id=23225
+//class Elements extends Array {
+// Element? query(DOMString relativeSelectors);
+// Elements queryAll(DOMString relativeSelectors);
+//};
+
+interface NodeList {
+ getter Node? item(unsigned long index);
+ readonly attribute unsigned long length;
+// iterable<Node>;
+};
+
+interface HTMLCollection {
+ readonly attribute unsigned long length;
+ getter Element? item(unsigned long index);
+ getter Element? namedItem(DOMString name);
+};
+
+[Constructor(MutationCallback callback)]
+interface MutationObserver {
+ void observe(Node target, MutationObserverInit options);
+ void disconnect();
+ sequence<MutationRecord> takeRecords();
+};
+
+callback MutationCallback = void (sequence<MutationRecord> mutations, MutationObserver observer);
+
+dictionary MutationObserverInit {
+ boolean childList = false;
+ boolean attributes;
+ boolean characterData;
+ boolean subtree = false;
+ boolean attributeOldValue;
+ boolean characterDataOldValue;
+ sequence<DOMString> attributeFilter;
+};
+
+interface MutationRecord {
+ readonly attribute DOMString type;
+ readonly attribute Node target;
+ [SameObject] readonly attribute NodeList addedNodes;
+ [SameObject] readonly attribute NodeList removedNodes;
+ readonly attribute Node? previousSibling;
+ readonly attribute Node? nextSibling;
+ readonly attribute DOMString? attributeName;
+ readonly attribute DOMString? attributeNamespace;
+ readonly attribute DOMString? oldValue;
+};
+
+interface Node : EventTarget {
+ const unsigned short ELEMENT_NODE = 1;
+ const unsigned short ATTRIBUTE_NODE = 2; // historical
+ const unsigned short TEXT_NODE = 3;
+ const unsigned short CDATA_SECTION_NODE = 4; // historical
+ const unsigned short ENTITY_REFERENCE_NODE = 5; // historical
+ const unsigned short ENTITY_NODE = 6; // historical
+ const unsigned short PROCESSING_INSTRUCTION_NODE = 7;
+ const unsigned short COMMENT_NODE = 8;
+ const unsigned short DOCUMENT_NODE = 9;
+ const unsigned short DOCUMENT_TYPE_NODE = 10;
+ const unsigned short DOCUMENT_FRAGMENT_NODE = 11;
+ const unsigned short NOTATION_NODE = 12; // historical
+ readonly attribute unsigned short nodeType;
+ readonly attribute DOMString nodeName;
+
+ readonly attribute DOMString? baseURI;
+
+ readonly attribute Document? ownerDocument;
+ readonly attribute Node? parentNode;
+ readonly attribute Element? parentElement;
+ boolean hasChildNodes();
+ [SameObject] readonly attribute NodeList childNodes;
+ readonly attribute Node? firstChild;
+ readonly attribute Node? lastChild;
+ readonly attribute Node? previousSibling;
+ readonly attribute Node? nextSibling;
+
+ attribute DOMString? nodeValue;
+ attribute DOMString? textContent;
+ void normalize();
+
+ [NewObject] Node cloneNode(optional boolean deep = false);
+ boolean isEqualNode(Node? node);
+
+ const unsigned short DOCUMENT_POSITION_DISCONNECTED = 0x01;
+ const unsigned short DOCUMENT_POSITION_PRECEDING = 0x02;
+ const unsigned short DOCUMENT_POSITION_FOLLOWING = 0x04;
+ const unsigned short DOCUMENT_POSITION_CONTAINS = 0x08;
+ const unsigned short DOCUMENT_POSITION_CONTAINED_BY = 0x10;
+ const unsigned short DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0x20;
+ unsigned short compareDocumentPosition(Node other);
+ boolean contains(Node? other);
+
+ DOMString? lookupPrefix(DOMString? namespace);
+ DOMString? lookupNamespaceURI(DOMString? prefix);
+ boolean isDefaultNamespace(DOMString? namespace);
+
+ Node insertBefore(Node node, Node? child);
+ Node appendChild(Node node);
+ Node replaceChild(Node node, Node child);
+ Node removeChild(Node child);
+};
+
+[Constructor]
+interface Document : Node {
+ [SameObject] readonly attribute DOMImplementation implementation;
+ readonly attribute DOMString URL;
+ readonly attribute DOMString documentURI;
+ readonly attribute DOMString origin;
+ readonly attribute DOMString compatMode;
+ readonly attribute DOMString characterSet;
+ readonly attribute DOMString inputEncoding; // legacy alias of .characterSet
+ readonly attribute DOMString contentType;
+
+ readonly attribute DocumentType? doctype;
+ readonly attribute Element? documentElement;
+ HTMLCollection getElementsByTagName(DOMString localName);
+ HTMLCollection getElementsByTagNameNS(DOMString? namespace, DOMString localName);
+ HTMLCollection getElementsByClassName(DOMString classNames);
+
+ [NewObject] Element createElement(DOMString localName);
+ [NewObject] Element createElementNS(DOMString? namespace, DOMString qualifiedName);
+ [NewObject] DocumentFragment createDocumentFragment();
+ [NewObject] Text createTextNode(DOMString data);
+ [NewObject] Comment createComment(DOMString data);
+ [NewObject] ProcessingInstruction createProcessingInstruction(DOMString target, DOMString data);
+
+ [NewObject] Node importNode(Node node, optional boolean deep = false);
+ Node adoptNode(Node node);
+
+ [NewObject] Attr createAttribute(DOMString localName);
+ [NewObject] Attr createAttributeNS(DOMString? namespace, DOMString name);
+
+ [NewObject] Event createEvent(DOMString interface);
+
+ [NewObject] Range createRange();
+
+ // NodeFilter.SHOW_ALL = 0xFFFFFFFF
+ [NewObject] NodeIterator createNodeIterator(Node root, optional unsigned long whatToShow = 0xFFFFFFFF, optional NodeFilter? filter = null);
+ [NewObject] TreeWalker createTreeWalker(Node root, optional unsigned long whatToShow = 0xFFFFFFFF, optional NodeFilter? filter = null);
+};
+
+interface XMLDocument : Document {};
+
+interface DOMImplementation {
+ [NewObject] DocumentType createDocumentType(DOMString qualifiedName, DOMString publicId, DOMString systemId);
+ [NewObject] XMLDocument createDocument(DOMString? namespace, [TreatNullAs=EmptyString] DOMString qualifiedName, optional DocumentType? doctype = null);
+ [NewObject] Document createHTMLDocument(optional DOMString title);
+
+ boolean hasFeature(); // useless; always returns true
+};
+
+[Constructor]
+interface DocumentFragment : Node {
+};
+
+interface DocumentType : Node {
+ readonly attribute DOMString name;
+ readonly attribute DOMString publicId;
+ readonly attribute DOMString systemId;
+};
+
+interface Element : Node {
+ readonly attribute DOMString? namespaceURI;
+ readonly attribute DOMString? prefix;
+ readonly attribute DOMString localName;
+ readonly attribute DOMString tagName;
+
+ attribute DOMString id;
+ attribute DOMString className;
+ [SameObject] readonly attribute DOMTokenList classList;
+
+ boolean hasAttributes();
+ [SameObject] readonly attribute NamedNodeMap attributes;
+ DOMString? getAttribute(DOMString name);
+ DOMString? getAttributeNS(DOMString? namespace, DOMString localName);
+ void setAttribute(DOMString name, DOMString value);
+ void setAttributeNS(DOMString? namespace, DOMString name, DOMString value);
+ void removeAttribute(DOMString name);
+ void removeAttributeNS(DOMString? namespace, DOMString localName);
+ boolean hasAttribute(DOMString name);
+ boolean hasAttributeNS(DOMString? namespace, DOMString localName);
+
+ Attr? getAttributeNode(DOMString name);
+ Attr? getAttributeNodeNS(DOMString? namespace, DOMString localName);
+ Attr? setAttributeNode(Attr attr);
+ Attr? setAttributeNodeNS(Attr attr);
+ Attr removeAttributeNode(Attr attr);
+
+ Element? closest(DOMString selectors);
+ boolean matches(DOMString selectors);
+
+ HTMLCollection getElementsByTagName(DOMString localName);
+ HTMLCollection getElementsByTagNameNS(DOMString? namespace, DOMString localName);
+ HTMLCollection getElementsByClassName(DOMString classNames);
+};
+
+interface NamedNodeMap {
+ readonly attribute unsigned long length;
+ getter Attr? item(unsigned long index);
+ getter Attr? getNamedItem(DOMString name);
+ Attr? getNamedItemNS(DOMString? namespace, DOMString localName);
+ Attr? setNamedItem(Attr attr);
+ Attr? setNamedItemNS(Attr attr);
+ Attr removeNamedItem(DOMString name);
+ Attr removeNamedItemNS(DOMString? namespace, DOMString localName);
+};
+
+interface Attr {
+ readonly attribute DOMString? namespaceURI;
+ readonly attribute DOMString? prefix;
+ readonly attribute DOMString localName;
+ readonly attribute DOMString name;
+ attribute DOMString value;
+ attribute DOMString nodeValue; // legacy alias of .value
+ attribute DOMString textContent; // legacy alias of .value
+
+ readonly attribute Element? ownerElement;
+
+ readonly attribute boolean specified; // useless; always returns true
+};
+
+interface CharacterData : Node {
+ [TreatNullAs=EmptyString] attribute DOMString data;
+ readonly attribute unsigned long length;
+ DOMString substringData(unsigned long offset, unsigned long count);
+ void appendData(DOMString data);
+ void insertData(unsigned long offset, DOMString data);
+ void deleteData(unsigned long offset, unsigned long count);
+ void replaceData(unsigned long offset, unsigned long count, DOMString data);
+};
+
+[Constructor(optional DOMString data = "")]
+interface Text : CharacterData {
+ [NewObject] Text splitText(unsigned long offset);
+ readonly attribute DOMString wholeText;
+};
+
+interface ProcessingInstruction : CharacterData {
+ readonly attribute DOMString target;
+};
+
+[Constructor(optional DOMString data = "")]
+interface Comment : CharacterData {
+};
+
+[Constructor]
+interface Range {
+ readonly attribute Node startContainer;
+ readonly attribute unsigned long startOffset;
+ readonly attribute Node endContainer;
+ readonly attribute unsigned long endOffset;
+ readonly attribute boolean collapsed;
+ readonly attribute Node commonAncestorContainer;
+
+ void setStart(Node node, unsigned long offset);
+ void setEnd(Node node, unsigned long offset);
+ void setStartBefore(Node node);
+ void setStartAfter(Node node);
+ void setEndBefore(Node node);
+ void setEndAfter(Node node);
+ void collapse(optional boolean toStart = false);
+ void selectNode(Node node);
+ void selectNodeContents(Node node);
+
+ const unsigned short START_TO_START = 0;
+ const unsigned short START_TO_END = 1;
+ const unsigned short END_TO_END = 2;
+ const unsigned short END_TO_START = 3;
+ short compareBoundaryPoints(unsigned short how, Range sourceRange);
+
+ void deleteContents();
+ [NewObject] DocumentFragment extractContents();
+ [NewObject] DocumentFragment cloneContents();
+ void insertNode(Node node);
+ void surroundContents(Node newParent);
+
+ [NewObject] Range cloneRange();
+ void detach();
+
+ boolean isPointInRange(Node node, unsigned long offset);
+ short comparePoint(Node node, unsigned long offset);
+
+ boolean intersectsNode(Node node);
+
+ stringifier;
+};
+
+interface NodeIterator {
+ [SameObject] readonly attribute Node root;
+ readonly attribute Node referenceNode;
+ readonly attribute boolean pointerBeforeReferenceNode;
+ readonly attribute unsigned long whatToShow;
+ readonly attribute NodeFilter? filter;
+
+ Node? nextNode();
+ Node? previousNode();
+
+ void detach();
+};
+
+interface TreeWalker {
+ [SameObject] readonly attribute Node root;
+ readonly attribute unsigned long whatToShow;
+ readonly attribute NodeFilter? filter;
+ attribute Node currentNode;
+
+ Node? parentNode();
+ Node? firstChild();
+ Node? lastChild();
+ Node? previousSibling();
+ Node? nextSibling();
+ Node? previousNode();
+ Node? nextNode();
+};
+
+callback interface NodeFilter {
+ // Constants for acceptNode()
+ const unsigned short FILTER_ACCEPT = 1;
+ const unsigned short FILTER_REJECT = 2;
+ const unsigned short FILTER_SKIP = 3;
+
+ // Constants for whatToShow
+ const unsigned long SHOW_ALL = 0xFFFFFFFF;
+ const unsigned long SHOW_ELEMENT = 0x1;
+ const unsigned long SHOW_ATTRIBUTE = 0x2; // historical
+ const unsigned long SHOW_TEXT = 0x4;
+ const unsigned long SHOW_CDATA_SECTION = 0x8; // historical
+ const unsigned long SHOW_ENTITY_REFERENCE = 0x10; // historical
+ const unsigned long SHOW_ENTITY = 0x20; // historical
+ const unsigned long SHOW_PROCESSING_INSTRUCTION = 0x40;
+ const unsigned long SHOW_COMMENT = 0x80;
+ const unsigned long SHOW_DOCUMENT = 0x100;
+ const unsigned long SHOW_DOCUMENT_TYPE = 0x200;
+ const unsigned long SHOW_DOCUMENT_FRAGMENT = 0x400;
+ const unsigned long SHOW_NOTATION = 0x800; // historical
+
+ unsigned short acceptNode(Node node);
+};
+
+interface DOMTokenList {
+ readonly attribute unsigned long length;
+ getter DOMString? item(unsigned long index);
+ boolean contains(DOMString token);
+ void add(DOMString... tokens);
+ void remove(DOMString... tokens);
+ boolean toggle(DOMString token, optional boolean force);
+ stringifier;
+// iterable<DOMString>;
+};
+
+interface DOMSettableTokenList : DOMTokenList {
+ attribute DOMString value;
+};
+</script>
+<!-- UI Events IDLs -->
+<script type=text/plain class=untested>
+[Constructor(DOMString type, optional UIEventInit eventInitDict)]
+interface UIEvent : Event {
+ readonly attribute WindowProxy? view;
+ readonly attribute long detail;
+};
+
+dictionary UIEventInit : EventInit {
+ WindowProxy? view = null;
+ long detail = 0;
+};
+
+[Constructor(DOMString typeArg, optional MouseEventInit mouseEventInitDict)]
+interface MouseEvent : UIEvent {
+ readonly attribute long screenX;
+ readonly attribute long screenY;
+ readonly attribute long clientX;
+ readonly attribute long clientY;
+ readonly attribute boolean ctrlKey;
+ readonly attribute boolean shiftKey;
+ readonly attribute boolean altKey;
+ readonly attribute boolean metaKey;
+ readonly attribute short button;
+ readonly attribute EventTarget? relatedTarget;
+ // Introduced in DOM Level 3
+ readonly attribute unsigned short buttons;
+ boolean getModifierState (DOMString keyArg);
+};
+
+dictionary MouseEventInit : SharedKeyboardAndMouseEventInit {
+ long screenX = 0;
+ long screenY = 0;
+ long clientX = 0;
+ long clientY = 0;
+ short button = 0;
+ unsigned short buttons = 0;
+ EventTarget? relatedTarget = null;
+};
+
+dictionary SharedKeyboardAndMouseEventInit : UIEventInit {
+ boolean ctrlKey = false;
+ boolean shiftKey = false;
+ boolean altKey = false;
+ boolean metaKey = false;
+ boolean keyModifierStateAltGraph = false;
+ boolean keyModifierStateCapsLock = false;
+ boolean keyModifierStateFn = false;
+ boolean keyModifierStateFnLock = false;
+ boolean keyModifierStateHyper = false;
+ boolean keyModifierStateNumLock = false;
+ boolean keyModifierStateOS = false;
+ boolean keyModifierStateScrollLock = false;
+ boolean keyModifierStateSuper = false;
+ boolean keyModifierStateSymbol = false;
+ boolean keyModifierStateSymbolLock = false;
+};
+
+partial interface MouseEvent {
+ // Deprecated in DOM Level 3
+ void initMouseEvent (DOMString typeArg, boolean bubblesArg, boolean cancelableArg, Window? viewArg, long detailArg, long screenXArg, long screenYArg, long clientXArg, long clientYArg, boolean ctrlKeyArg, boolean altKeyArg, boolean shiftKeyArg, boolean metaKeyArg, short buttonArg, EventTarget? relatedTargetArg);
+};
+</script>
+<!-- Touch Events IDLs -->
+<script type=text/plain class=untested>
+interface Touch {
+ readonly attribute long identifier;
+ readonly attribute EventTarget target;
+ readonly attribute long screenX;
+ readonly attribute long screenY;
+ readonly attribute long clientX;
+ readonly attribute long clientY;
+ readonly attribute long pageX;
+ readonly attribute long pageY;
+};
+</script>
+<!-- CSSOM IDLs -->
+<script type=text/plain class=untested>
+interface MediaList {
+ stringifier attribute DOMString mediaText;
+ readonly attribute unsigned long length;
+ getter DOMString item(unsigned long index);
+ void appendMedium(DOMString medium);
+ void deleteMedium(DOMString medium);
+};
+
+interface StyleSheet {
+ readonly attribute DOMString type;
+ readonly attribute DOMString href;
+ readonly attribute Node ownerNode;
+ readonly attribute StyleSheet parentStyleSheet;
+ readonly attribute DOMString title;
+ [PutForwards=mediaText] readonly attribute MediaList media;
+ attribute boolean disabled;
+};
+
+interface CSSStyleSheet : StyleSheet {
+ readonly attribute CSSRule ownerRule;
+ readonly attribute CSSRuleList cssRules;
+ unsigned long insertRule(DOMString rule, unsigned long index);
+ void deleteRule(unsigned long index);
+};
+
+typedef sequence<StyleSheet> StyleSheetList;
+
+partial interface Document {
+ readonly attribute StyleSheetList styleSheets;
+ attribute DOMString? selectedStyleSheetSet;
+ readonly attribute DOMString? lastStyleSheetSet;
+ readonly attribute DOMString? preferredStyleSheetSet;
+ readonly attribute DOMStringList styleSheetSets;
+ void enableStyleSheetsForSet(DOMString? name);
+};
+
+[NoInterfaceObject] interface LinkStyle {
+ readonly attribute StyleSheet sheet;
+};
+
+ProcessingInstruction implements LinkStyle;
+
+typedef sequence<CSSRule> CSSRuleList;
+
+interface CSSRule {
+ // Types
+ const unsigned short STYLE_RULE = 1;
+ const unsigned short IMPORT_RULE = 3;
+ const unsigned short MEDIA_RULE = 4;
+ const unsigned short FONT_FACE_RULE = 5;
+ const unsigned short PAGE_RULE = 6;
+ const unsigned short NAMESPACE_RULE = 10;
+ readonly attribute unsigned short type;
+
+ // Parsing and serialization
+ attribute DOMString cssText;
+
+ // Context
+ readonly attribute CSSRule parentRule;
+ readonly attribute CSSStyleSheet parentStyleSheet;
+};
+
+interface CSSStyleRule : CSSRule {
+ attribute DOMString selectorText;
+ readonly attribute CSSStyleDeclaration style;
+};
+
+interface CSSImportRule : CSSRule {
+ readonly attribute DOMString href;
+ [PutForwards=mediaText] readonly attribute MediaList media;
+ readonly attribute CSSStyleSheet styleSheet;
+};
+
+interface CSSMediaRule : CSSRule {
+ [PutForwards=mediaText] readonly attribute MediaList media;
+ readonly attribute CSSRuleList cssRules;
+ unsigned long insertRule(DOMString rule, unsigned long index);
+ void deleteRule(unsigned long index);
+};
+
+interface CSSFontFaceRule : CSSRule {
+ readonly attribute CSSStyleDeclaration style;
+};
+
+interface CSSPageRule : CSSRule {
+ attribute DOMString selectorText;
+ readonly attribute CSSStyleDeclaration style;
+};
+
+interface CSSNamespaceRule : CSSRule {
+ readonly attribute DOMString namespaceURI;
+ readonly attribute DOMString? prefix;
+};
+
+interface CSSStyleDeclaration {
+ attribute DOMString cssText;
+
+ readonly attribute unsigned long length;
+ DOMString item(unsigned long index);
+
+ DOMString getPropertyValue(DOMString property);
+ DOMString getPropertyPriority(DOMString property);
+ void setProperty(DOMString property, DOMString value, optional DOMString priority);
+ DOMString removeProperty(DOMString property);
+
+ readonly attribute CSSStyleDeclarationValue values;
+
+ readonly attribute CSSRule parentRule;
+
+ // CSS Properties
+ attribute DOMString azimuth;
+ attribute DOMString background;
+ attribute DOMString backgroundAttachment;
+ attribute DOMString backgroundColor;
+ attribute DOMString backgroundImage;
+ attribute DOMString backgroundPosition;
+ attribute DOMString backgroundRepeat;
+ attribute DOMString border;
+ attribute DOMString borderCollapse;
+ attribute DOMString borderColor;
+ attribute DOMString borderSpacing;
+ attribute DOMString borderStyle;
+ attribute DOMString borderTop;
+ attribute DOMString borderRight;
+ attribute DOMString borderBottom;
+ attribute DOMString borderLeft;
+ attribute DOMString borderTopColor;
+ attribute DOMString borderRightColor;
+ attribute DOMString borderBottomColor;
+ attribute DOMString borderLeftColor;
+ attribute DOMString borderTopStyle;
+ attribute DOMString borderRightStyle;
+ attribute DOMString borderBottomStyle;
+ attribute DOMString borderLeftStyle;
+ attribute DOMString borderTopWidth;
+ attribute DOMString borderRightWidth;
+ attribute DOMString borderBottomWidth;
+ attribute DOMString borderLeftWidth;
+ attribute DOMString borderWidth;
+ attribute DOMString bottom;
+ attribute DOMString captionSide;
+ attribute DOMString clear;
+ attribute DOMString clip;
+ attribute DOMString color;
+ attribute DOMString content;
+ attribute DOMString counterIncrement;
+ attribute DOMString counterReset;
+ attribute DOMString cue;
+ attribute DOMString cueAfter;
+ attribute DOMString cueBefore;
+ attribute DOMString cursor;
+ attribute DOMString direction;
+ attribute DOMString display;
+ attribute DOMString elevation;
+ attribute DOMString emptyCells;
+ attribute DOMString cssFloat;
+ attribute DOMString font;
+ attribute DOMString fontFamily;
+ attribute DOMString fontSize;
+ attribute DOMString fontSizeAdjust;
+ attribute DOMString fontStretch;
+ attribute DOMString fontStyle;
+ attribute DOMString fontVariant;
+ attribute DOMString fontWeight;
+ attribute DOMString height;
+ attribute DOMString left;
+ attribute DOMString letterSpacing;
+ attribute DOMString lineHeight;
+ attribute DOMString listStyle;
+ attribute DOMString listStyleImage;
+ attribute DOMString listStylePosition;
+ attribute DOMString listStyleType;
+ attribute DOMString margin;
+ attribute DOMString marginTop;
+ attribute DOMString marginRight;
+ attribute DOMString marginBottom;
+ attribute DOMString marginLeft;
+ attribute DOMString markerOffset;
+ attribute DOMString marks;
+ attribute DOMString maxHeight;
+ attribute DOMString maxWidth;
+ attribute DOMString minHeight;
+ attribute DOMString minWidth;
+ attribute DOMString orphans;
+ attribute DOMString outline;
+ attribute DOMString outlineColor;
+ attribute DOMString outlineStyle;
+ attribute DOMString outlineWidth;
+ attribute DOMString overflow;
+ attribute DOMString padding;
+ attribute DOMString paddingTop;
+ attribute DOMString paddingRight;
+ attribute DOMString paddingBottom;
+ attribute DOMString paddingLeft;
+ attribute DOMString page;
+ attribute DOMString pageBreakAfter;
+ attribute DOMString pageBreakBefore;
+ attribute DOMString pageBreakInside;
+ attribute DOMString pause;
+ attribute DOMString pauseAfter;
+ attribute DOMString pauseBefore;
+ attribute DOMString pitch;
+ attribute DOMString pitchRange;
+ attribute DOMString playDuring;
+ attribute DOMString position;
+ attribute DOMString quotes;
+ attribute DOMString richness;
+ attribute DOMString right;
+ attribute DOMString size;
+ attribute DOMString speak;
+ attribute DOMString speakHeader;
+ attribute DOMString speakNumeral;
+ attribute DOMString speakPunctuation;
+ attribute DOMString speechRate;
+ attribute DOMString stress;
+ attribute DOMString tableLayout;
+ attribute DOMString textAlign;
+ attribute DOMString textDecoration;
+ attribute DOMString textIndent;
+ attribute DOMString textShadow;
+ attribute DOMString textTransform;
+ attribute DOMString top;
+ attribute DOMString unicodeBidi;
+ attribute DOMString verticalAlign;
+ attribute DOMString visibility;
+ attribute DOMString voiceFamily;
+ attribute DOMString volume;
+ attribute DOMString whiteSpace;
+ attribute DOMString widows;
+ attribute DOMString width;
+ attribute DOMString wordSpacing;
+ attribute DOMString zIndex;
+};
+
+interface CSSStyleDeclarationValue {
+ // ...
+
+ // CSS Properties
+
+};
+
+interface CSSPropertyValue {
+ attribute DOMString cssText;
+};
+
+[NoInterfaceObject] interface CSSMapValue {
+ getter CSSValue (DOMString name);
+};
+
+[NoInterfaceObject] interface CSSPropertyValueList {
+ readonly attribute CSSValue[] list;
+};
+
+[NoInterfaceObject] interface CSSComponentValue {
+ readonly attribute DOMString type;
+ attribute any value;
+};
+
+[NoInterfaceObject] interface CSSStringComponentValue {
+ attribute DOMString string;
+};
+
+[NoInterfaceObject] interface CSSKeywordComponentValue {
+ attribute DOMString keyword;
+};
+
+[NoInterfaceObject] interface CSSIdentifierComponentValue {
+ attribute DOMString identifier;
+};
+
+[NoInterfaceObject] interface CSSColorComponentValue {
+ attribute short red;
+ attribute short green;
+ attribute short blue;
+ attribute float alpha;
+};
+
+[NoInterfaceObject] interface CSSLengthComponentValue {
+ attribute float em;
+ attribute float ex;
+ attribute float px;
+ // figure out what to do with absolute lengths
+};
+
+[NoInterfaceObject] interface CSSPercentageComponentValue {
+ attribute float percent;
+};
+
+[NoInterfaceObject] interface CSSURLComponentValue {
+ attribute DOMString? url;
+};
+
+[NoInterfaceObject] interface ElementCSSInlineStyle {
+ readonly attribute CSSStyleDeclaration style;
+};
+
+//partial interface Window {
+// CSSStyleDeclaration getComputedStyle(Element elt);
+// CSSStyleDeclaration getComputedStyle(Element elt, DOMString pseudoElt);
+//};
+</script>
+
+<!-- HTML IDLs -->
+<script type=text/plain>
+typedef (Int8Array or Uint8Array or Uint8ClampedArray or
+ Int16Array or Uint16Array or
+ Int32Array or Uint32Array or
+ Float32Array or Float64Array or
+ DataView) ArrayBufferView;
+
+interface HTMLAllCollection : HTMLCollection {
+ // inherits length and 'getter'
+ Element? item(unsigned long index);
+ (HTMLCollection or Element)? item(DOMString name);
+ legacycaller getter (HTMLCollection or Element)? namedItem(DOMString name); // shadows inherited namedItem()
+};
+
+interface HTMLFormControlsCollection : HTMLCollection {
+ // inherits length and item()
+ legacycaller getter (RadioNodeList or Element)? namedItem(DOMString name); // shadows inherited namedItem()
+};
+
+interface RadioNodeList : NodeList {
+ attribute DOMString value;
+};
+
+interface HTMLOptionsCollection : HTMLCollection {
+ // inherits item()
+ attribute unsigned long length; // shadows inherited length
+ legacycaller HTMLOptionElement? (DOMString name);
+ setter creator void (unsigned long index, HTMLOptionElement? option);
+ void add((HTMLOptionElement or HTMLOptGroupElement) element, optional (HTMLElement or long)? before = null);
+ void remove(long index);
+ attribute long selectedIndex;
+};
+
+interface HTMLPropertiesCollection : HTMLCollection {
+ // inherits length and item()
+ getter PropertyNodeList? namedItem(DOMString name); // shadows inherited namedItem()
+ readonly attribute DOMString[] names;
+};
+
+typedef sequence<any> PropertyValueArray;
+
+interface PropertyNodeList : NodeList {
+ PropertyValueArray getValues();
+};
+
+[OverrideBuiltins, Exposed=Window,Worker]
+interface DOMStringMap {
+ getter DOMString (DOMString name);
+ setter creator void (DOMString name, DOMString value);
+ deleter void (DOMString name);
+};
+
+interface DOMElementMap {
+ getter Element (DOMString name);
+ setter creator void (DOMString name, Element value);
+ deleter void (DOMString name);
+};
+
+typedef (ArrayBuffer or CanvasProxy or MessagePort) Transferable;
+
+callback FileCallback = void (File file);
+
+enum DocumentReadyState { "loading", "interactive", "complete" };
+
+[OverrideBuiltins]
+partial /*sealed*/ interface Document {
+ // resource metadata management
+ [PutForwards=href, Unforgeable] readonly attribute Location? location;
+ attribute DOMString domain;
+ readonly attribute DOMString referrer;
+ attribute DOMString cookie;
+ readonly attribute DOMString lastModified;
+ readonly attribute DocumentReadyState readyState;
+
+ // DOM tree accessors
+ getter object (DOMString name);
+ attribute DOMString title;
+ attribute DOMString dir;
+ attribute HTMLElement? body;
+ readonly attribute HTMLHeadElement? head;
+ readonly attribute HTMLCollection images;
+ readonly attribute HTMLCollection embeds;
+ readonly attribute HTMLCollection plugins;
+ readonly attribute HTMLCollection links;
+ readonly attribute HTMLCollection forms;
+ readonly attribute HTMLCollection scripts;
+ NodeList getElementsByName(DOMString elementName);
+ NodeList getItems(optional DOMString typeNames = ""); // microdata
+ readonly attribute DOMElementMap cssElementMap;
+ readonly attribute HTMLScriptElement? currentScript;
+
+ // dynamic markup insertion
+ Document open(optional DOMString type = "text/html", optional DOMString replace = "");
+ WindowProxy open(DOMString url, DOMString name, DOMString features, optional boolean replace = false);
+ void close();
+ void write(DOMString... text);
+ void writeln(DOMString... text);
+
+ // user interaction
+ readonly attribute WindowProxy? defaultView;
+ readonly attribute Element? activeElement;
+ boolean hasFocus();
+ attribute DOMString designMode;
+ boolean execCommand(DOMString commandId, optional boolean showUI = false, optional DOMString value = "");
+ boolean queryCommandEnabled(DOMString commandId);
+ boolean queryCommandIndeterm(DOMString commandId);
+ boolean queryCommandState(DOMString commandId);
+ boolean queryCommandSupported(DOMString commandId);
+ DOMString queryCommandValue(DOMString commandId);
+ readonly attribute HTMLCollection commands;
+
+ // special event handler IDL attributes that only apply to Document objects
+ [LenientThis] attribute EventHandler onreadystatechange;
+
+ // also has obsolete members
+};
+Document implements GlobalEventHandlers;
+
+partial interface XMLDocument {
+ boolean load(DOMString url);
+};
+
+interface HTMLElement : Element {
+ // metadata attributes
+ attribute DOMString title;
+ attribute DOMString lang;
+ attribute boolean translate;
+ attribute DOMString dir;
+ readonly attribute DOMStringMap dataset;
+
+ // microdata
+ attribute boolean itemScope;
+ [PutForwards=value] readonly attribute DOMSettableTokenList itemType;
+ attribute DOMString itemId;
+ [PutForwards=value] readonly attribute DOMSettableTokenList itemRef;
+ [PutForwards=value] readonly attribute DOMSettableTokenList itemProp;
+ readonly attribute HTMLPropertiesCollection properties;
+ attribute any itemValue; // acts as DOMString on setting
+
+ // user interaction
+ attribute boolean hidden;
+ void click();
+ attribute long tabIndex;
+ void focus();
+ void blur();
+ attribute DOMString accessKey;
+ readonly attribute DOMString accessKeyLabel;
+ attribute boolean draggable;
+ [PutForwards=value] readonly attribute DOMSettableTokenList dropzone;
+ attribute DOMString contentEditable;
+ readonly attribute boolean isContentEditable;
+ attribute HTMLMenuElement? contextMenu;
+ attribute boolean spellcheck;
+ void forceSpellCheck();
+
+ // command API
+ readonly attribute DOMString? commandType;
+ readonly attribute DOMString? commandLabel;
+ readonly attribute DOMString? commandIcon;
+ readonly attribute boolean? commandHidden;
+ readonly attribute boolean? commandDisabled;
+ readonly attribute boolean? commandChecked;
+};
+HTMLElement implements GlobalEventHandlers;
+
+interface HTMLUnknownElement : HTMLElement { };
+
+interface HTMLHtmlElement : HTMLElement {
+ // also has obsolete members
+};
+
+interface HTMLHeadElement : HTMLElement {};
+
+interface HTMLTitleElement : HTMLElement {
+ attribute DOMString text;
+};
+
+interface HTMLBaseElement : HTMLElement {
+ attribute DOMString href;
+ attribute DOMString target;
+};
+
+interface HTMLLinkElement : HTMLElement {
+ attribute DOMString href;
+ attribute DOMString crossOrigin;
+ attribute DOMString rel;
+ readonly attribute DOMTokenList relList;
+ attribute DOMString media;
+ attribute DOMString hreflang;
+ attribute DOMString type;
+ [PutForwards=value] readonly attribute DOMSettableTokenList sizes;
+
+ // also has obsolete members
+};
+HTMLLinkElement implements LinkStyle;
+
+interface HTMLMetaElement : HTMLElement {
+ attribute DOMString name;
+ attribute DOMString httpEquiv;
+ attribute DOMString content;
+
+ // also has obsolete members
+};
+
+interface HTMLStyleElement : HTMLElement {
+ attribute DOMString media;
+ attribute DOMString type;
+ attribute boolean scoped;
+};
+HTMLStyleElement implements LinkStyle;
+
+interface HTMLBodyElement : HTMLElement {
+
+ // also has obsolete members
+};
+HTMLBodyElement implements WindowEventHandlers;
+
+interface HTMLHeadingElement : HTMLElement {
+ // also has obsolete members
+};
+
+interface HTMLParagraphElement : HTMLElement {
+ // also has obsolete members
+};
+
+interface HTMLHRElement : HTMLElement {
+ // also has obsolete members
+};
+
+interface HTMLPreElement : HTMLElement {
+ // also has obsolete members
+};
+
+interface HTMLQuoteElement : HTMLElement {
+ attribute DOMString cite;
+};
+
+interface HTMLOListElement : HTMLElement {
+ attribute boolean reversed;
+ attribute long start;
+ attribute DOMString type;
+
+ // also has obsolete members
+};
+
+interface HTMLUListElement : HTMLElement {
+ // also has obsolete members
+};
+
+interface HTMLLIElement : HTMLElement {
+ attribute long value;
+
+ // also has obsolete members
+};
+
+interface HTMLDListElement : HTMLElement {
+ // also has obsolete members
+};
+
+interface HTMLDivElement : HTMLElement {
+ // also has obsolete members
+};
+
+interface HTMLAnchorElement : HTMLElement {
+ attribute DOMString target;
+ attribute DOMString download;
+ [PutForwards=value] attribute DOMSettableTokenList ping;
+ attribute DOMString rel;
+ readonly attribute DOMTokenList relList;
+ attribute DOMString hreflang;
+ attribute DOMString type;
+
+ attribute DOMString text;
+
+ // also has obsolete members
+};
+HTMLAnchorElement implements URLUtils;
+
+interface HTMLDataElement : HTMLElement {
+ attribute DOMString value;
+};
+
+interface HTMLTimeElement : HTMLElement {
+ attribute DOMString dateTime;
+};
+
+interface HTMLSpanElement : HTMLElement {};
+
+interface HTMLBRElement : HTMLElement {
+ // also has obsolete members
+};
+
+interface HTMLModElement : HTMLElement {
+ attribute DOMString cite;
+ attribute DOMString dateTime;
+};
+
+interface HTMLPictureElement : HTMLElement {};
+
+partial interface HTMLSourceElement {
+ attribute DOMString srcset;
+ attribute DOMString sizes;
+ attribute DOMString media;
+};
+
+[NamedConstructor=Image(optional unsigned long width, optional unsigned long height)]
+interface HTMLImageElement : HTMLElement {
+ attribute DOMString alt;
+ attribute DOMString src;
+ attribute DOMString srcset;
+ attribute DOMString sizes;
+ attribute DOMString crossOrigin;
+ attribute DOMString useMap;
+ attribute boolean isMap;
+ attribute unsigned long width;
+ attribute unsigned long height;
+ readonly attribute unsigned long naturalWidth;
+ readonly attribute unsigned long naturalHeight;
+ readonly attribute boolean complete;
+ readonly attribute DOMString currentSrc;
+
+ // also has obsolete members
+};
+
+interface HTMLIFrameElement : HTMLElement {
+ attribute DOMString src;
+ attribute DOMString srcdoc;
+ attribute DOMString name;
+ [PutForwards=value] readonly attribute DOMSettableTokenList sandbox;
+ attribute boolean seamless;
+ attribute boolean allowFullscreen;
+ attribute DOMString width;
+ attribute DOMString height;
+ readonly attribute Document? contentDocument;
+ readonly attribute WindowProxy? contentWindow;
+
+ // also has obsolete members
+};
+
+interface HTMLEmbedElement : HTMLElement {
+ attribute DOMString src;
+ attribute DOMString type;
+ attribute DOMString width;
+ attribute DOMString height;
+ Document getSVGDocument();
+ legacycaller any (any... arguments);
+
+ // also has obsolete members
+};
+
+interface HTMLObjectElement : HTMLElement {
+ attribute DOMString data;
+ attribute DOMString type;
+ attribute boolean typeMustMatch;
+ attribute DOMString name;
+ attribute DOMString useMap;
+ readonly attribute HTMLFormElement? form;
+ attribute DOMString width;
+ attribute DOMString height;
+ readonly attribute Document? contentDocument;
+ readonly attribute WindowProxy? contentWindow;
+
+ readonly attribute boolean willValidate;
+ readonly attribute ValidityState validity;
+ readonly attribute DOMString validationMessage;
+ boolean checkValidity();
+ boolean reportValidity();
+ void setCustomValidity(DOMString error);
+
+ legacycaller any (any... arguments);
+
+ // also has obsolete members
+};
+
+interface HTMLParamElement : HTMLElement {
+ attribute DOMString name;
+ attribute DOMString value;
+
+ // also has obsolete members
+};
+
+interface HTMLVideoElement : HTMLMediaElement {
+ attribute unsigned long width;
+ attribute unsigned long height;
+ readonly attribute unsigned long videoWidth;
+ readonly attribute unsigned long videoHeight;
+ attribute DOMString poster;
+};
+
+[NamedConstructor=Audio(optional DOMString src)]
+interface HTMLAudioElement : HTMLMediaElement {};
+
+interface HTMLSourceElement : HTMLElement {
+ attribute DOMString src;
+ attribute DOMString type;
+
+ // also has obsolete members
+};
+
+interface HTMLTrackElement : HTMLElement {
+ attribute DOMString kind;
+ attribute DOMString src;
+ attribute DOMString srclang;
+ attribute DOMString label;
+ attribute boolean default;
+
+ const unsigned short NONE = 0;
+ const unsigned short LOADING = 1;
+ const unsigned short LOADED = 2;
+ const unsigned short ERROR = 3;
+ readonly attribute unsigned short readyState;
+
+ readonly attribute TextTrack track;
+};
+
+enum CanPlayTypeResult { "" /* empty string */, "maybe", "probably" };
+interface HTMLMediaElement : HTMLElement {
+
+ // error state
+ readonly attribute MediaError? error;
+
+ // network state
+ attribute DOMString src;
+ readonly attribute DOMString currentSrc;
+ attribute DOMString crossOrigin;
+ const unsigned short NETWORK_EMPTY = 0;
+ const unsigned short NETWORK_IDLE = 1;
+ const unsigned short NETWORK_LOADING = 2;
+ const unsigned short NETWORK_NO_SOURCE = 3;
+ readonly attribute unsigned short networkState;
+ attribute DOMString preload;
+ readonly attribute TimeRanges buffered;
+ void load();
+ CanPlayTypeResult canPlayType(DOMString type);
+
+ // ready state
+ const unsigned short HAVE_NOTHING = 0;
+ const unsigned short HAVE_METADATA = 1;
+ const unsigned short HAVE_CURRENT_DATA = 2;
+ const unsigned short HAVE_FUTURE_DATA = 3;
+ const unsigned short HAVE_ENOUGH_DATA = 4;
+ readonly attribute unsigned short readyState;
+ readonly attribute boolean seeking;
+
+ // playback state
+ attribute double currentTime;
+ void fastSeek(double time);
+ readonly attribute unrestricted double duration;
+ Date getStartDate();
+ readonly attribute boolean paused;
+ attribute double defaultPlaybackRate;
+ attribute double playbackRate;
+ readonly attribute TimeRanges played;
+ readonly attribute TimeRanges seekable;
+ readonly attribute boolean ended;
+ attribute boolean autoplay;
+ attribute boolean loop;
+ void play();
+ void pause();
+
+ // media controller
+ attribute DOMString mediaGroup;
+ attribute MediaController? controller;
+
+ // controls
+ attribute boolean controls;
+ attribute double volume;
+ attribute boolean muted;
+ attribute boolean defaultMuted;
+
+ // tracks
+ readonly attribute AudioTrackList audioTracks;
+ readonly attribute VideoTrackList videoTracks;
+ readonly attribute TextTrackList textTracks;
+ TextTrack addTextTrack(TextTrackKind kind, optional DOMString label = "", optional DOMString language = "");
+};
+
+interface MediaError {
+ const unsigned short MEDIA_ERR_ABORTED = 1;
+ const unsigned short MEDIA_ERR_NETWORK = 2;
+ const unsigned short MEDIA_ERR_DECODE = 3;
+ const unsigned short MEDIA_ERR_SRC_NOT_SUPPORTED = 4;
+ readonly attribute unsigned short code;
+};
+
+interface AudioTrackList : EventTarget {
+ readonly attribute unsigned long length;
+ getter AudioTrack (unsigned long index);
+ AudioTrack? getTrackById(DOMString id);
+
+ attribute EventHandler onchange;
+ attribute EventHandler onaddtrack;
+ attribute EventHandler onremovetrack;
+};
+
+interface AudioTrack {
+ readonly attribute DOMString id;
+ readonly attribute DOMString kind;
+ readonly attribute DOMString label;
+ readonly attribute DOMString language;
+ attribute boolean enabled;
+};
+
+interface VideoTrackList : EventTarget {
+ readonly attribute unsigned long length;
+ getter VideoTrack (unsigned long index);
+ VideoTrack? getTrackById(DOMString id);
+ readonly attribute long selectedIndex;
+
+ attribute EventHandler onchange;
+ attribute EventHandler onaddtrack;
+ attribute EventHandler onremovetrack;
+};
+
+interface VideoTrack {
+ readonly attribute DOMString id;
+ readonly attribute DOMString kind;
+ readonly attribute DOMString label;
+ readonly attribute DOMString language;
+ attribute boolean selected;
+};
+
+enum MediaControllerPlaybackState { "waiting", "playing", "ended" };
+[Constructor]
+interface MediaController : EventTarget {
+ readonly attribute unsigned short readyState; // uses HTMLMediaElement.readyState's values
+
+ readonly attribute TimeRanges buffered;
+ readonly attribute TimeRanges seekable;
+ readonly attribute unrestricted double duration;
+ attribute double currentTime;
+
+ readonly attribute boolean paused;
+ readonly attribute MediaControllerPlaybackState playbackState;
+ readonly attribute TimeRanges played;
+ void pause();
+ void unpause();
+ void play(); // calls play() on all media elements as well
+
+ attribute double defaultPlaybackRate;
+ attribute double playbackRate;
+
+ attribute double volume;
+ attribute boolean muted;
+
+ attribute EventHandler onemptied;
+ attribute EventHandler onloadedmetadata;
+ attribute EventHandler onloadeddata;
+ attribute EventHandler oncanplay;
+ attribute EventHandler oncanplaythrough;
+ attribute EventHandler onplaying;
+ attribute EventHandler onended;
+ attribute EventHandler onwaiting;
+
+ attribute EventHandler ondurationchange;
+ attribute EventHandler ontimeupdate;
+ attribute EventHandler onplay;
+ attribute EventHandler onpause;
+ attribute EventHandler onratechange;
+ attribute EventHandler onvolumechange;
+};
+
+interface TextTrackList : EventTarget {
+ readonly attribute unsigned long length;
+ getter TextTrack (unsigned long index);
+ TextTrack? getTrackById(DOMString id);
+
+ attribute EventHandler onchange;
+ attribute EventHandler onaddtrack;
+ attribute EventHandler onremovetrack;
+};
+
+enum TextTrackMode { "disabled", "hidden", "showing" };
+enum TextTrackKind { "subtitles", "captions", "descriptions", "chapters", "metadata" };
+interface TextTrack : EventTarget {
+ readonly attribute TextTrackKind kind;
+ readonly attribute DOMString label;
+ readonly attribute DOMString language;
+
+ readonly attribute DOMString id;
+ readonly attribute DOMString inBandMetadataTrackDispatchType;
+
+ attribute TextTrackMode mode;
+
+ readonly attribute TextTrackCueList? cues;
+ readonly attribute TextTrackCueList? activeCues;
+
+ void addCue(TextTrackCue cue);
+ void removeCue(TextTrackCue cue);
+
+ attribute EventHandler oncuechange;
+};
+
+interface TextTrackCueList {
+ readonly attribute unsigned long length;
+ getter TextTrackCue (unsigned long index);
+ TextTrackCue? getCueById(DOMString id);
+};
+
+interface TextTrackCue : EventTarget {
+ readonly attribute TextTrack? track;
+
+ attribute DOMString id;
+ attribute double startTime;
+ attribute double endTime;
+ attribute boolean pauseOnExit;
+
+ attribute EventHandler onenter;
+ attribute EventHandler onexit;
+};
+
+interface TimeRanges {
+ readonly attribute unsigned long length;
+ double start(unsigned long index);
+ double end(unsigned long index);
+};
+
+[Constructor(DOMString type, optional TrackEventInit eventInitDict)]
+interface TrackEvent : Event {
+ readonly attribute (VideoTrack or AudioTrack or TextTrack) track;
+};
+
+dictionary TrackEventInit : EventInit {
+ (VideoTrack or AudioTrack or TextTrack) track;
+};
+
+interface HTMLMapElement : HTMLElement {
+ attribute DOMString name;
+ readonly attribute HTMLCollection areas;
+ readonly attribute HTMLCollection images;
+};
+
+interface HTMLAreaElement : HTMLElement {
+ attribute DOMString alt;
+ attribute DOMString coords;
+ attribute DOMString shape;
+ attribute DOMString target;
+ attribute DOMString download;
+ [PutForwards=value] attribute DOMSettableTokenList ping;
+ attribute DOMString rel;
+ readonly attribute DOMTokenList relList;
+ attribute DOMString hreflang;
+ attribute DOMString type;
+
+ // also has obsolete members
+};
+HTMLAreaElement implements URLUtils;
+
+interface HTMLTableElement : HTMLElement {
+ attribute HTMLTableCaptionElement? caption;
+ HTMLElement createCaption();
+ void deleteCaption();
+ attribute HTMLTableSectionElement? tHead;
+ HTMLElement createTHead();
+ void deleteTHead();
+ attribute HTMLTableSectionElement? tFoot;
+ HTMLElement createTFoot();
+ void deleteTFoot();
+ readonly attribute HTMLCollection tBodies;
+ HTMLElement createTBody();
+ readonly attribute HTMLCollection rows;
+ HTMLElement insertRow(optional long index = -1);
+ void deleteRow(long index);
+ attribute boolean sortable;
+ void stopSorting();
+
+ // also has obsolete members
+};
+
+interface HTMLTableCaptionElement : HTMLElement {
+ // also has obsolete members
+};
+
+interface HTMLTableColElement : HTMLElement {
+ attribute unsigned long span;
+
+ // also has obsolete members
+};
+
+interface HTMLTableSectionElement : HTMLElement {
+ readonly attribute HTMLCollection rows;
+ HTMLElement insertRow(optional long index = -1);
+ void deleteRow(long index);
+
+ // also has obsolete members
+};
+
+interface HTMLTableRowElement : HTMLElement {
+ readonly attribute long rowIndex;
+ readonly attribute long sectionRowIndex;
+ readonly attribute HTMLCollection cells;
+ HTMLElement insertCell(optional long index = -1);
+ void deleteCell(long index);
+
+ // also has obsolete members
+};
+
+interface HTMLTableDataCellElement : HTMLTableCellElement {
+ // also has obsolete members
+};
+
+interface HTMLTableHeaderCellElement : HTMLTableCellElement {
+ attribute DOMString scope;
+ attribute DOMString abbr;
+ attribute DOMString sorted;
+ void sort();
+};
+
+interface HTMLTableCellElement : HTMLElement {
+ attribute unsigned long colSpan;
+ attribute unsigned long rowSpan;
+ [PutForwards=value] readonly attribute DOMSettableTokenList headers;
+ readonly attribute long cellIndex;
+
+ // also has obsolete members
+};
+
+[OverrideBuiltins]
+interface HTMLFormElement : HTMLElement {
+ attribute DOMString acceptCharset;
+ attribute DOMString action;
+ attribute DOMString autocomplete;
+ attribute DOMString enctype;
+ attribute DOMString encoding;
+ attribute DOMString method;
+ attribute DOMString name;
+ attribute boolean noValidate;
+ attribute DOMString target;
+
+ readonly attribute HTMLFormControlsCollection elements;
+ readonly attribute long length;
+ getter Element (unsigned long index);
+ getter (RadioNodeList or Element) (DOMString name);
+
+ void submit();
+ void reset();
+ boolean checkValidity();
+ boolean reportValidity();
+
+ void requestAutocomplete();
+};
+
+interface HTMLLabelElement : HTMLElement {
+ readonly attribute HTMLFormElement? form;
+ attribute DOMString htmlFor;
+ readonly attribute HTMLElement? control;
+};
+
+interface HTMLInputElement : HTMLElement {
+ attribute DOMString accept;
+ attribute DOMString alt;
+ attribute DOMString autocomplete;
+ attribute boolean autofocus;
+ attribute boolean defaultChecked;
+ attribute boolean checked;
+ attribute DOMString dirName;
+ attribute boolean disabled;
+ readonly attribute HTMLFormElement? form;
+ readonly attribute FileList? files;
+ attribute DOMString formAction;
+ attribute DOMString formEnctype;
+ attribute DOMString formMethod;
+ attribute boolean formNoValidate;
+ attribute DOMString formTarget;
+ attribute unsigned long height;
+ attribute boolean indeterminate;
+ attribute DOMString inputMode;
+ readonly attribute HTMLElement? list;
+ attribute DOMString max;
+ attribute long maxLength;
+ attribute DOMString min;
+ attribute long minLength;
+ attribute boolean multiple;
+ attribute DOMString name;
+ attribute DOMString pattern;
+ attribute DOMString placeholder;
+ attribute boolean readOnly;
+ attribute boolean required;
+ attribute unsigned long size;
+ attribute DOMString src;
+ attribute DOMString step;
+ attribute DOMString type;
+ attribute DOMString defaultValue;
+ [TreatNullAs=EmptyString] attribute DOMString value;
+ attribute Date? valueAsDate;
+ attribute unrestricted double valueAsNumber;
+ attribute double valueLow;
+ attribute double valueHigh;
+ attribute unsigned long width;
+
+ void stepUp(optional long n = 1);
+ void stepDown(optional long n = 1);
+
+ readonly attribute boolean willValidate;
+ readonly attribute ValidityState validity;
+ readonly attribute DOMString validationMessage;
+ boolean checkValidity();
+ boolean reportValidity();
+ void setCustomValidity(DOMString error);
+
+ readonly attribute NodeList labels;
+
+ void select();
+ attribute unsigned long selectionStart;
+ attribute unsigned long selectionEnd;
+ attribute DOMString selectionDirection;
+ void setRangeText(DOMString replacement);
+ void setRangeText(DOMString replacement, unsigned long start, unsigned long end, optional SelectionMode selectionMode = "preserve");
+ void setSelectionRange(unsigned long start, unsigned long end, optional DOMString direction);
+
+ // also has obsolete members
+};
+
+interface HTMLButtonElement : HTMLElement {
+ attribute boolean autofocus;
+ attribute boolean disabled;
+ readonly attribute HTMLFormElement? form;
+ attribute DOMString formAction;
+ attribute DOMString formEnctype;
+ attribute DOMString formMethod;
+ attribute boolean formNoValidate;
+ attribute DOMString formTarget;
+ attribute DOMString name;
+ attribute DOMString type;
+ attribute DOMString value;
+ attribute HTMLMenuElement? menu;
+
+ readonly attribute boolean willValidate;
+ readonly attribute ValidityState validity;
+ readonly attribute DOMString validationMessage;
+ boolean checkValidity();
+ boolean reportValidity();
+ void setCustomValidity(DOMString error);
+
+ readonly attribute NodeList labels;
+};
+
+interface HTMLSelectElement : HTMLElement {
+ attribute DOMString autocomplete;
+ attribute boolean autofocus;
+ attribute boolean disabled;
+ readonly attribute HTMLFormElement? form;
+ attribute boolean multiple;
+ attribute DOMString name;
+ attribute boolean required;
+ attribute unsigned long size;
+
+ readonly attribute DOMString type;
+
+ readonly attribute HTMLOptionsCollection options;
+ attribute unsigned long length;
+ getter Element? item(unsigned long index);
+ HTMLOptionElement? namedItem(DOMString name);
+ void add((HTMLOptionElement or HTMLOptGroupElement) element, optional (HTMLElement or long)? before = null);
+ void remove(); // ChildNode overload
+ void remove(long index);
+ setter creator void (unsigned long index, HTMLOptionElement? option);
+
+ readonly attribute HTMLCollection selectedOptions;
+ attribute long selectedIndex;
+ attribute DOMString value;
+
+ readonly attribute boolean willValidate;
+ readonly attribute ValidityState validity;
+ readonly attribute DOMString validationMessage;
+ boolean checkValidity();
+ boolean reportValidity();
+ void setCustomValidity(DOMString error);
+
+ readonly attribute NodeList labels;
+};
+
+interface HTMLDataListElement : HTMLElement {
+ readonly attribute HTMLCollection options;
+};
+
+interface HTMLOptGroupElement : HTMLElement {
+ attribute boolean disabled;
+ attribute DOMString label;
+};
+
+[NamedConstructor=Option(optional DOMString text = "", optional DOMString value, optional boolean defaultSelected = false, optional boolean selected = false)]
+interface HTMLOptionElement : HTMLElement {
+ attribute boolean disabled;
+ readonly attribute HTMLFormElement? form;
+ attribute DOMString label;
+ attribute boolean defaultSelected;
+ attribute boolean selected;
+ attribute DOMString value;
+
+ attribute DOMString text;
+ readonly attribute long index;
+};
+
+interface HTMLTextAreaElement : HTMLElement {
+ attribute DOMString autocomplete;
+ attribute boolean autofocus;
+ attribute unsigned long cols;
+ attribute DOMString dirName;
+ attribute boolean disabled;
+ readonly attribute HTMLFormElement? form;
+ attribute DOMString inputMode;
+ attribute long maxLength;
+ attribute long minLength;
+ attribute DOMString name;
+ attribute DOMString placeholder;
+ attribute boolean readOnly;
+ attribute boolean required;
+ attribute unsigned long rows;
+ attribute DOMString wrap;
+
+ readonly attribute DOMString type;
+ attribute DOMString defaultValue;
+ [TreatNullAs=EmptyString] attribute DOMString value;
+ readonly attribute unsigned long textLength;
+
+ readonly attribute boolean willValidate;
+ readonly attribute ValidityState validity;
+ readonly attribute DOMString validationMessage;
+ boolean checkValidity();
+ boolean reportValidity();
+ void setCustomValidity(DOMString error);
+
+ readonly attribute NodeList labels;
+
+ void select();
+ attribute unsigned long selectionStart;
+ attribute unsigned long selectionEnd;
+ attribute DOMString selectionDirection;
+ void setRangeText(DOMString replacement);
+ void setRangeText(DOMString replacement, unsigned long start, unsigned long end, optional SelectionMode selectionMode = "preserve");
+ void setSelectionRange(unsigned long start, unsigned long end, optional DOMString direction);
+};
+
+interface HTMLKeygenElement : HTMLElement {
+ attribute boolean autofocus;
+ attribute DOMString challenge;
+ attribute boolean disabled;
+ readonly attribute HTMLFormElement? form;
+ attribute DOMString keytype;
+ attribute DOMString name;
+
+ readonly attribute DOMString type;
+
+ readonly attribute boolean willValidate;
+ readonly attribute ValidityState validity;
+ readonly attribute DOMString validationMessage;
+ boolean checkValidity();
+ boolean reportValidity();
+ void setCustomValidity(DOMString error);
+
+ readonly attribute NodeList labels;
+};
+
+interface HTMLOutputElement : HTMLElement {
+ [PutForwards=value] readonly attribute DOMSettableTokenList htmlFor;
+ readonly attribute HTMLFormElement? form;
+ attribute DOMString name;
+
+ readonly attribute DOMString type;
+ attribute DOMString defaultValue;
+ attribute DOMString value;
+
+ readonly attribute boolean willValidate;
+ readonly attribute ValidityState validity;
+ readonly attribute DOMString validationMessage;
+ boolean checkValidity();
+ boolean reportValidity();
+ void setCustomValidity(DOMString error);
+
+ readonly attribute NodeList labels;
+};
+
+interface HTMLProgressElement : HTMLElement {
+ attribute double value;
+ attribute double max;
+ readonly attribute double position;
+ readonly attribute NodeList labels;
+};
+
+interface HTMLMeterElement : HTMLElement {
+ attribute double value;
+ attribute double min;
+ attribute double max;
+ attribute double low;
+ attribute double high;
+ attribute double optimum;
+ readonly attribute NodeList labels;
+};
+
+interface HTMLFieldSetElement : HTMLElement {
+ attribute boolean disabled;
+ readonly attribute HTMLFormElement? form;
+ attribute DOMString name;
+
+ readonly attribute DOMString type;
+
+ readonly attribute HTMLFormControlsCollection elements;
+
+ readonly attribute boolean willValidate;
+ readonly attribute ValidityState validity;
+ readonly attribute DOMString validationMessage;
+ boolean checkValidity();
+ boolean reportValidity();
+ void setCustomValidity(DOMString error);
+};
+
+interface HTMLLegendElement : HTMLElement {
+ readonly attribute HTMLFormElement? form;
+
+ // also has obsolete members
+};
+
+enum AutocompleteErrorReason { "" /* empty string */, "cancel", "disabled", "invalid" };
+
+[Constructor(DOMString type, optional AutocompleteErrorEventInit eventInitDict)]
+interface AutocompleteErrorEvent : Event {
+ readonly attribute AutocompleteErrorReason reason;
+};
+
+dictionary AutocompleteErrorEventInit : EventInit {
+ AutocompleteErrorReason reason;
+};
+
+enum SelectionMode {
+ "select",
+ "start",
+ "end",
+ "preserve"/*,*/ // default
+};
+
+interface ValidityState {
+ readonly attribute boolean valueMissing;
+ readonly attribute boolean typeMismatch;
+ readonly attribute boolean patternMismatch;
+ readonly attribute boolean tooLong;
+ readonly attribute boolean tooShort;
+ readonly attribute boolean rangeUnderflow;
+ readonly attribute boolean rangeOverflow;
+ readonly attribute boolean stepMismatch;
+ readonly attribute boolean badInput;
+ readonly attribute boolean customError;
+ readonly attribute boolean valid;
+};
+
+interface HTMLDetailsElement : HTMLElement {
+ attribute boolean open;
+};
+
+interface HTMLMenuElement : HTMLElement {
+ attribute DOMString type;
+ attribute DOMString label;
+
+ // also has obsolete members
+};
+
+interface HTMLMenuItemElement : HTMLElement {
+ attribute DOMString type;
+ attribute DOMString label;
+ attribute DOMString icon;
+ attribute boolean disabled;
+ attribute boolean checked;
+ attribute DOMString radiogroup;
+ attribute boolean default;
+ readonly attribute HTMLElement? command;
+};
+
+[Constructor(DOMString type, optional RelatedEventInit eventInitDict)]
+interface RelatedEvent : Event {
+ readonly attribute EventTarget? relatedTarget;
+};
+
+dictionary RelatedEventInit : EventInit {
+ EventTarget? relatedTarget;
+};
+
+interface HTMLDialogElement : HTMLElement {
+ attribute boolean open;
+ attribute DOMString returnValue;
+ void show(optional (MouseEvent or Element) anchor);
+ void showModal(optional (MouseEvent or Element) anchor);
+ void close(optional DOMString returnValue);
+};
+
+interface HTMLScriptElement : HTMLElement {
+ attribute DOMString src;
+ attribute DOMString type;
+ attribute DOMString charset;
+ attribute boolean async;
+ attribute boolean defer;
+ attribute DOMString crossOrigin;
+ attribute DOMString text;
+
+ // also has obsolete members
+};
+
+interface HTMLTemplateElement : HTMLElement {
+ readonly attribute DocumentFragment content;
+};
+
+typedef (CanvasRenderingContext2D or WebGLRenderingContext) RenderingContext;
+
+interface HTMLCanvasElement : HTMLElement {
+ attribute unsigned long width;
+ attribute unsigned long height;
+
+ RenderingContext? getContext(DOMString contextId, any... arguments);
+ boolean probablySupportsContext(DOMString contextId, any... arguments);
+
+ void setContext(RenderingContext context);
+ CanvasProxy transferControlToProxy();
+
+ DOMString toDataURL(optional DOMString type, any... arguments);
+ void toBlob(FileCallback? _callback, optional DOMString type, any... arguments);
+};
+
+[Exposed=Window,Worker]
+interface CanvasProxy {
+ void setContext(RenderingContext context);
+};
+// CanvasProxy implements Transferable;
+
+typedef (HTMLImageElement or
+ HTMLVideoElement or
+ HTMLCanvasElement or
+ CanvasRenderingContext2D or
+ ImageBitmap) CanvasImageSource;
+
+enum CanvasFillRule { "nonzero", "evenodd" };
+
+[Constructor(optional unsigned long width, unsigned long height), Exposed=Window,Worker]
+interface CanvasRenderingContext2D {
+
+ // back-reference to the canvas
+ readonly attribute HTMLCanvasElement canvas;
+
+ // canvas dimensions
+ attribute unsigned long width;
+ attribute unsigned long height;
+
+ // for contexts that aren't directly fixed to a specific canvas
+ void commit(); // push the image to the output bitmap
+
+ // state
+ void save(); // push state on state stack
+ void restore(); // pop state stack and restore state
+
+ // transformations (default transform is the identity matrix)
+ attribute SVGMatrix currentTransform;
+ void scale(unrestricted double x, unrestricted double y);
+ void rotate(unrestricted double angle);
+ void translate(unrestricted double x, unrestricted double y);
+ void transform(unrestricted double a, unrestricted double b, unrestricted double c, unrestricted double d, unrestricted double e, unrestricted double f);
+ void setTransform(unrestricted double a, unrestricted double b, unrestricted double c, unrestricted double d, unrestricted double e, unrestricted double f);
+ void resetTransform();
+
+ // compositing
+ attribute unrestricted double globalAlpha; // (default 1.0)
+ attribute DOMString globalCompositeOperation; // (default source-over)
+
+ // image smoothing
+ attribute boolean imageSmoothingEnabled; // (default true)
+
+ // colours and styles (see also the CanvasDrawingStyles interface)
+ attribute (DOMString or CanvasGradient or CanvasPattern) strokeStyle; // (default black)
+ attribute (DOMString or CanvasGradient or CanvasPattern) fillStyle; // (default black)
+ CanvasGradient createLinearGradient(double x0, double y0, double x1, double y1);
+ CanvasGradient createRadialGradient(double x0, double y0, double r0, double x1, double y1, double r1);
+ CanvasPattern createPattern(CanvasImageSource image, [TreatNullAs=EmptyString] DOMString repetition);
+
+ // shadows
+ attribute unrestricted double shadowOffsetX; // (default 0)
+ attribute unrestricted double shadowOffsetY; // (default 0)
+ attribute unrestricted double shadowBlur; // (default 0)
+ attribute DOMString shadowColor; // (default transparent black)
+
+ // rects
+ void clearRect(unrestricted double x, unrestricted double y, unrestricted double w, unrestricted double h);
+ void fillRect(unrestricted double x, unrestricted double y, unrestricted double w, unrestricted double h);
+ void strokeRect(unrestricted double x, unrestricted double y, unrestricted double w, unrestricted double h);
+
+ // path API (see also CanvasPathMethods)
+ void beginPath();
+ void fill(optional CanvasFillRule fillRule = "nonzero");
+ void fill(Path2D path, optional CanvasFillRule fillRule = "nonzero");
+ void stroke();
+ void stroke(Path2D path);
+ void drawSystemFocusRing(Element element);
+ void drawSystemFocusRing(Path2D path, Element element);
+ boolean drawCustomFocusRing(Element element);
+ boolean drawCustomFocusRing(Path2D path, Element element);
+ void scrollPathIntoView();
+ void scrollPathIntoView(Path2D path);
+ void clip(optional CanvasFillRule fillRule = "nonzero");
+ void clip(Path2D path, optional CanvasFillRule fillRule = "nonzero");
+ void resetClip();
+ boolean isPointInPath(unrestricted double x, unrestricted double y, optional CanvasFillRule fillRule = "nonzero");
+ boolean isPointInPath(Path2D path, unrestricted double x, unrestricted double y, optional CanvasFillRule fillRule = "nonzero");
+ boolean isPointInStroke(unrestricted double x, unrestricted double y);
+ boolean isPointInStroke(Path2D path, unrestricted double x, unrestricted double y);
+
+ // text (see also the CanvasDrawingStyles interface)
+ void fillText(DOMString text, unrestricted double x, unrestricted double y, optional unrestricted double maxWidth);
+ void strokeText(DOMString text, unrestricted double x, unrestricted double y, optional unrestricted double maxWidth);
+ TextMetrics measureText(DOMString text);
+
+ // drawing images
+ void drawImage(CanvasImageSource image, unrestricted double dx, unrestricted double dy);
+ void drawImage(CanvasImageSource image, unrestricted double dx, unrestricted double dy, unrestricted double dw, unrestricted double dh);
+ void drawImage(CanvasImageSource image, unrestricted double sx, unrestricted double sy, unrestricted double sw, unrestricted double sh, unrestricted double dx, unrestricted double dy, unrestricted double dw, unrestricted double dh);
+
+ // hit regions
+ void addHitRegion(optional HitRegionOptions options);
+ void removeHitRegion(DOMString id);
+
+ // pixel manipulation
+ ImageData createImageData(double sw, double sh);
+ ImageData createImageData(ImageData imagedata);
+ ImageData getImageData(double sx, double sy, double sw, double sh);
+ void putImageData(ImageData imagedata, double dx, double dy);
+ void putImageData(ImageData imagedata, double dx, double dy, double dirtyX, double dirtyY, double dirtyWidth, double dirtyHeight);
+};
+CanvasRenderingContext2D implements CanvasDrawingStyles;
+CanvasRenderingContext2D implements CanvasPathMethods;
+
+[NoInterfaceObject, Exposed=Window,Worker]
+interface CanvasDrawingStyles {
+ // line caps/joins
+ attribute unrestricted double lineWidth; // (default 1)
+ attribute DOMString lineCap; // "butt", "round", "square" (default "butt")
+ attribute DOMString lineJoin; // "round", "bevel", "miter" (default "miter")
+ attribute unrestricted double miterLimit; // (default 10)
+
+ // dashed lines
+ void setLineDash(sequence<unrestricted double> segments); // default empty
+ sequence<unrestricted double> getLineDash();
+ attribute unrestricted double lineDashOffset;
+
+ // text
+ attribute DOMString font; // (default 10px sans-serif)
+ attribute DOMString textAlign; // "start", "end", "left", "right", "center" (default: "start")
+ attribute DOMString textBaseline; // "top", "hanging", "middle", "alphabetic", "ideographic", "bottom" (default: "alphabetic")
+ attribute DOMString direction; // "ltr", "rtl", "inherit" (default: "inherit")
+};
+
+[NoInterfaceObject, Exposed=Window,Worker]
+interface CanvasPathMethods {
+ // shared path API methods
+ void closePath();
+ void moveTo(unrestricted double x, unrestricted double y);
+ void lineTo(unrestricted double x, unrestricted double y);
+ void quadraticCurveTo(unrestricted double cpx, unrestricted double cpy, unrestricted double x, unrestricted double y);
+ void bezierCurveTo(unrestricted double cp1x, unrestricted double cp1y, unrestricted double cp2x, unrestricted double cp2y, unrestricted double x, unrestricted double y);
+ void arcTo(unrestricted double x1, unrestricted double y1, unrestricted double x2, unrestricted double y2, unrestricted double radius);
+ void arcTo(unrestricted double x1, unrestricted double y1, unrestricted double x2, unrestricted double y2, unrestricted double radiusX, unrestricted double radiusY, unrestricted double rotation);
+ void rect(unrestricted double x, unrestricted double y, unrestricted double w, unrestricted double h);
+ void arc(unrestricted double x, unrestricted double y, unrestricted double radius, unrestricted double startAngle, unrestricted double endAngle, optional boolean anticlockwise = false);
+ void ellipse(unrestricted double x, unrestricted double y, unrestricted double radiusX, unrestricted double radiusY, unrestricted double rotation, unrestricted double startAngle, unrestricted double endAngle, optional boolean anticlockwise = false);
+};
+
+[Exposed=Window,Worker]
+interface CanvasGradient {
+ // opaque object
+ void addColorStop(double offset, DOMString color);
+};
+
+[Exposed=Window,Worker]
+interface CanvasPattern {
+ // opaque object
+ void setTransform(SVGMatrix transform);
+};
+
+[Exposed=Window,Worker]
+interface TextMetrics {
+ // x-direction
+ readonly attribute double width; // advance width
+ readonly attribute double actualBoundingBoxLeft;
+ readonly attribute double actualBoundingBoxRight;
+
+ // y-direction
+ readonly attribute double fontBoundingBoxAscent;
+ readonly attribute double fontBoundingBoxDescent;
+ readonly attribute double actualBoundingBoxAscent;
+ readonly attribute double actualBoundingBoxDescent;
+ readonly attribute double emHeightAscent;
+ readonly attribute double emHeightDescent;
+ readonly attribute double hangingBaseline;
+ readonly attribute double alphabeticBaseline;
+ readonly attribute double ideographicBaseline;
+};
+
+dictionary HitRegionOptions {
+ Path2D? path = null;
+ CanvasFillRule fillRule = "nonzero";
+ DOMString id = "";
+ DOMString? parentID = null;
+ DOMString cursor = "inherit";
+ // for control-backed regions:
+ Element? control = null;
+ // for unbacked regions:
+ DOMString? label = null;
+ DOMString? role = null;
+};
+
+[Constructor(unsigned long sw, unsigned long sh),
+ Constructor(Uint8ClampedArray data, unsigned long sw, optional unsigned long sh),
+ Exposed=Window,Worker]
+interface ImageData {
+ readonly attribute unsigned long width;
+ readonly attribute unsigned long height;
+ readonly attribute Uint8ClampedArray data;
+};
+
+[Constructor(optional Element scope), Exposed=Window,Worker]
+interface DrawingStyle { };
+DrawingStyle implements CanvasDrawingStyles;
+
+[Constructor,
+ Constructor(Path2D path),
+ Constructor(Path2D[] paths, optional CanvasFillRule fillRule = "nonzero"),
+ Constructor(DOMString d), Exposed=Window,Worker]
+interface Path2D {
+ void addPath(Path2D path, optional SVGMatrix? transformation = null);
+ void addPathByStrokingPath(Path2D path, CanvasDrawingStyles styles, optional SVGMatrix? transformation = null);
+ void addText(DOMString text, CanvasDrawingStyles styles, SVGMatrix? transformation, unrestricted double x, unrestricted double y, optional unrestricted double maxWidth);
+ void addPathByStrokingText(DOMString text, CanvasDrawingStyles styles, SVGMatrix? transformation, unrestricted double x, unrestricted double y, optional unrestricted double maxWidth);
+ void addText(DOMString text, CanvasDrawingStyles styles, SVGMatrix? transformation, Path2D path, optional unrestricted double maxWidth);
+ void addPathByStrokingText(DOMString text, CanvasDrawingStyles styles, SVGMatrix? transformation, Path2D path, optional unrestricted double maxWidth);
+};
+Path2D implements CanvasPathMethods;
+
+partial interface MouseEvent {
+ readonly attribute DOMString? region;
+};
+
+// https://github.com/w3c/testharness.js/issues/84
+//partial dictionary MouseEventInit {
+// DOMString? region;
+//};
+
+partial interface Touch {
+ readonly attribute DOMString? region;
+};
+
+interface DataTransfer {
+ attribute DOMString dropEffect;
+ attribute DOMString effectAllowed;
+
+ readonly attribute DataTransferItemList items;
+
+ void setDragImage(Element image, long x, long y);
+
+ /* old interface */
+ readonly attribute DOMString[] types;
+ DOMString getData(DOMString format);
+ void setData(DOMString format, DOMString data);
+ void clearData(optional DOMString format);
+ readonly attribute FileList files;
+};
+
+interface DataTransferItemList {
+ readonly attribute unsigned long length;
+ getter DataTransferItem (unsigned long index);
+ DataTransferItem? add(DOMString data, DOMString type);
+ DataTransferItem? add(File data);
+ void remove(unsigned long index);
+ void clear();
+};
+
+interface DataTransferItem {
+ readonly attribute DOMString kind;
+ readonly attribute DOMString type;
+ void getAsString(FunctionStringCallback? _callback);
+ File? getAsFile();
+};
+
+callback FunctionStringCallback = void (DOMString data);
+
+[Constructor(DOMString type, optional DragEventInit eventInitDict)]
+interface DragEvent : MouseEvent {
+ readonly attribute DataTransfer? dataTransfer;
+};
+
+dictionary DragEventInit : MouseEventInit {
+ DataTransfer? dataTransfer;
+};
+
+[PrimaryGlobal]
+/*sealed*/ interface Window : EventTarget {
+ // the current browsing context
+ [Unforgeable] readonly attribute WindowProxy window;
+ [Replaceable] readonly attribute WindowProxy self;
+ [Unforgeable] readonly attribute Document document;
+ attribute DOMString name;
+ [PutForwards=href, Unforgeable] readonly attribute Location location;
+ readonly attribute History history;
+ [Replaceable] readonly attribute BarProp locationbar;
+ [Replaceable] readonly attribute BarProp menubar;
+ [Replaceable] readonly attribute BarProp personalbar;
+ [Replaceable] readonly attribute BarProp scrollbars;
+ [Replaceable] readonly attribute BarProp statusbar;
+ [Replaceable] readonly attribute BarProp toolbar;
+ attribute DOMString status;
+ void close();
+ readonly attribute boolean closed;
+ void stop();
+ void focus();
+ void blur();
+
+ // other browsing contexts
+ [Replaceable] readonly attribute WindowProxy frames;
+ [Replaceable] readonly attribute unsigned long length;
+ [Unforgeable] readonly attribute WindowProxy top;
+ attribute any opener;
+ readonly attribute WindowProxy parent;
+ readonly attribute Element? frameElement;
+ WindowProxy open(optional DOMString url = "about:blank", optional DOMString target = "_blank", [TreatNullAs=EmptyString] optional DOMString features = "", optional boolean replace = false);
+ getter WindowProxy (unsigned long index);
+ getter object (DOMString name);
+
+ // the user agent
+ readonly attribute Navigator navigator;
+ [Replaceable] readonly attribute External external;
+ readonly attribute ApplicationCache applicationCache;
+
+ // user prompts
+ void alert();
+ //void alert(DOMString message);
+ boolean confirm(optional DOMString message = "");
+ DOMString? prompt(optional DOMString message = "", optional DOMString default = "");
+ void print();
+ any showModalDialog(DOMString url, optional any argument);
+
+ void postMessage(any message, DOMString targetOrigin, optional sequence<Transferable> transfer);
+
+ // also has obsolete members
+};
+Window implements GlobalEventHandlers;
+Window implements WindowEventHandlers;
+
+interface BarProp {
+ attribute boolean visible;
+};
+
+interface History {
+ readonly attribute long length;
+ readonly attribute any state;
+ void go(optional long delta);
+ void back();
+ void forward();
+ void pushState(any data, DOMString title, optional DOMString? url = null);
+ void replaceState(any data, DOMString title, optional DOMString? url = null);
+};
+
+[Unforgeable] interface Location {
+ void assign(DOMString url);
+ void replace(DOMString url);
+ void reload();
+};
+Location implements URLUtils;
+
+[Constructor(DOMString type, optional PopStateEventInit eventInitDict), Exposed=Window,Worker]
+interface PopStateEvent : Event {
+ readonly attribute any state;
+};
+
+dictionary PopStateEventInit : EventInit {
+ any state;
+};
+
+[Constructor(DOMString type, optional HashChangeEventInit eventInitDict), Exposed=Window,Worker]
+interface HashChangeEvent : Event {
+ readonly attribute DOMString oldURL;
+ readonly attribute DOMString newURL;
+};
+
+dictionary HashChangeEventInit : EventInit {
+ DOMString oldURL;
+ DOMString newURL;
+};
+
+[Constructor(DOMString type, optional PageTransitionEventInit eventInitDict), Exposed=Window,Worker]
+interface PageTransitionEvent : Event {
+ readonly attribute boolean persisted;
+};
+
+dictionary PageTransitionEventInit : EventInit {
+ boolean persisted;
+};
+
+interface BeforeUnloadEvent : Event {
+ attribute DOMString returnValue;
+};
+
+[Exposed=Window,SharedWorker]
+interface ApplicationCache : EventTarget {
+
+ // update status
+ const unsigned short UNCACHED = 0;
+ const unsigned short IDLE = 1;
+ const unsigned short CHECKING = 2;
+ const unsigned short DOWNLOADING = 3;
+ const unsigned short UPDATEREADY = 4;
+ const unsigned short OBSOLETE = 5;
+ readonly attribute unsigned short status;
+
+ // updates
+ void update();
+ void abort();
+ void swapCache();
+
+ // events
+ attribute EventHandler onchecking;
+ attribute EventHandler onerror;
+ attribute EventHandler onnoupdate;
+ attribute EventHandler ondownloading;
+ attribute EventHandler onprogress;
+ attribute EventHandler onupdateready;
+ attribute EventHandler oncached;
+ attribute EventHandler onobsolete;
+};
+
+[NoInterfaceObject, Exposed=Window,Worker]
+interface NavigatorOnLine {
+ readonly attribute boolean onLine;
+};
+
+[Constructor(DOMString type, optional ErrorEventInit eventInitDict), Exposed=Window,Worker]
+interface ErrorEvent : Event {
+ readonly attribute DOMString message;
+ readonly attribute DOMString filename;
+ readonly attribute unsigned long lineno;
+ readonly attribute unsigned long colno;
+ readonly attribute any error;
+};
+
+dictionary ErrorEventInit : EventInit {
+ DOMString message;
+ DOMString filename;
+ unsigned long lineno;
+ unsigned long colno;
+ any error;
+};
+
+[TreatNonCallableAsNull]
+callback EventHandlerNonNull = any (Event event);
+typedef EventHandlerNonNull? EventHandler;
+
+[TreatNonCallableAsNull]
+callback OnErrorEventHandlerNonNull = any ((Event or DOMString) event, optional DOMString source, optional unsigned long lineno, optional unsigned long column, optional any error);
+typedef OnErrorEventHandlerNonNull? OnErrorEventHandler;
+
+[TreatNonCallableAsNull]
+callback OnBeforeUnloadEventHandlerNonNull = DOMString? (Event event);
+typedef OnBeforeUnloadEventHandlerNonNull? OnBeforeUnloadEventHandler;
+
+[NoInterfaceObject]
+interface GlobalEventHandlers {
+ attribute EventHandler onabort;
+ attribute EventHandler onautocomplete;
+ attribute EventHandler onautocompleteerror;
+ attribute EventHandler onblur;
+ attribute EventHandler oncancel;
+ attribute EventHandler oncanplay;
+ attribute EventHandler oncanplaythrough;
+ attribute EventHandler onchange;
+ attribute EventHandler onclick;
+ attribute EventHandler onclose;
+ attribute EventHandler oncontextmenu;
+ attribute EventHandler oncuechange;
+ attribute EventHandler ondblclick;
+ attribute EventHandler ondrag;
+ attribute EventHandler ondragend;
+ attribute EventHandler ondragenter;
+ attribute EventHandler ondragexit;
+ attribute EventHandler ondragleave;
+ attribute EventHandler ondragover;
+ attribute EventHandler ondragstart;
+ attribute EventHandler ondrop;
+ attribute EventHandler ondurationchange;
+ attribute EventHandler onemptied;
+ attribute EventHandler onended;
+ attribute OnErrorEventHandler onerror;
+ attribute EventHandler onfocus;
+ attribute EventHandler oninput;
+ attribute EventHandler oninvalid;
+ attribute EventHandler onkeydown;
+ attribute EventHandler onkeypress;
+ attribute EventHandler onkeyup;
+ attribute EventHandler onload;
+ attribute EventHandler onloadeddata;
+ attribute EventHandler onloadedmetadata;
+ attribute EventHandler onloadstart;
+ attribute EventHandler onmousedown;
+ [LenientThis] attribute EventHandler onmouseenter;
+ [LenientThis] attribute EventHandler onmouseleave;
+ attribute EventHandler onmousemove;
+ attribute EventHandler onmouseout;
+ attribute EventHandler onmouseover;
+ attribute EventHandler onmouseup;
+ attribute EventHandler onmousewheel;
+ attribute EventHandler onpause;
+ attribute EventHandler onplay;
+ attribute EventHandler onplaying;
+ attribute EventHandler onprogress;
+ attribute EventHandler onratechange;
+ attribute EventHandler onreset;
+ attribute EventHandler onresize;
+ attribute EventHandler onscroll;
+ attribute EventHandler onseeked;
+ attribute EventHandler onseeking;
+ attribute EventHandler onselect;
+ attribute EventHandler onshow;
+ attribute EventHandler onsort;
+ attribute EventHandler onstalled;
+ attribute EventHandler onsubmit;
+ attribute EventHandler onsuspend;
+ attribute EventHandler ontimeupdate;
+ attribute EventHandler ontoggle;
+ attribute EventHandler onvolumechange;
+ attribute EventHandler onwaiting;
+};
+
+[NoInterfaceObject]
+interface WindowEventHandlers {
+ attribute EventHandler onafterprint;
+ attribute EventHandler onbeforeprint;
+ attribute OnBeforeUnloadEventHandler onbeforeunload;
+ attribute EventHandler onhashchange;
+ attribute EventHandler onlanguagechange;
+ attribute EventHandler onmessage;
+ attribute EventHandler onoffline;
+ attribute EventHandler ononline;
+ attribute EventHandler onpagehide;
+ attribute EventHandler onpageshow;
+ attribute EventHandler onpopstate;
+ attribute EventHandler onstorage;
+ attribute EventHandler onunload;
+};
+
+[NoInterfaceObject, Exposed=Window,Worker]
+interface WindowBase64 {
+ DOMString btoa(DOMString btoa);
+ DOMString atob(DOMString atob);
+};
+Window implements WindowBase64;
+
+[NoInterfaceObject, Exposed=Window,Worker]
+interface WindowTimers {
+ long setTimeout(Function handler, optional long timeout = 0, any... arguments);
+ long setTimeout(DOMString handler, optional long timeout = 0, any... arguments);
+ void clearTimeout(optional long handle = 0);
+ long setInterval(Function handler, optional long timeout = 0, any... arguments);
+ long setInterval(DOMString handler, optional long timeout = 0, any... arguments);
+ void clearInterval(optional long handle = 0);
+};
+Window implements WindowTimers;
+
+[NoInterfaceObject]
+interface WindowModal {
+ readonly attribute any dialogArguments;
+ attribute any returnValue;
+};
+
+interface Navigator {
+ // objects implementing this interface also implement the interfaces given below
+};
+Navigator implements NavigatorID;
+Navigator implements NavigatorLanguage;
+Navigator implements NavigatorOnLine;
+Navigator implements NavigatorContentUtils;
+Navigator implements NavigatorStorageUtils;
+Navigator implements NavigatorPlugins;
+
+[NoInterfaceObject, Exposed=Window,Worker]
+interface NavigatorID {
+ readonly attribute DOMString appCodeName; // constant "Mozilla"
+ readonly attribute DOMString appName;
+ readonly attribute DOMString appVersion;
+ readonly attribute DOMString platform;
+ readonly attribute DOMString product; // constant "Gecko"
+ boolean taintEnabled(); // constant false
+ readonly attribute DOMString userAgent;
+};
+
+[NoInterfaceObject, Exposed=Window,Worker]
+interface NavigatorLanguage {
+ readonly attribute DOMString? language;
+ readonly attribute DOMString[] languages;
+};
+
+[NoInterfaceObject]
+interface NavigatorContentUtils {
+ // content handler registration
+ void registerProtocolHandler(DOMString scheme, DOMString url, DOMString title);
+ void registerContentHandler(DOMString mimeType, DOMString url, DOMString title);
+ DOMString isProtocolHandlerRegistered(DOMString scheme, DOMString url);
+ DOMString isContentHandlerRegistered(DOMString mimeType, DOMString url);
+ void unregisterProtocolHandler(DOMString scheme, DOMString url);
+ void unregisterContentHandler(DOMString mimeType, DOMString url);
+};
+
+[NoInterfaceObject]
+interface NavigatorStorageUtils {
+ readonly attribute boolean cookieEnabled;
+ void yieldForStorageUpdates();
+};
+
+[NoInterfaceObject]
+interface NavigatorPlugins {
+ readonly attribute PluginArray plugins;
+ readonly attribute MimeTypeArray mimeTypes;
+ readonly attribute boolean javaEnabled;
+};
+
+interface PluginArray {
+ void refresh(optional boolean reload = false);
+ readonly attribute unsigned long length;
+ getter Plugin? item(unsigned long index);
+ getter Plugin? namedItem(DOMString name);
+};
+
+interface MimeTypeArray {
+ readonly attribute unsigned long length;
+ getter MimeType? item(unsigned long index);
+ getter MimeType? namedItem(DOMString name);
+};
+
+interface Plugin {
+ readonly attribute DOMString name;
+ readonly attribute DOMString description;
+ readonly attribute DOMString filename;
+ readonly attribute unsigned long length;
+ getter MimeType? item(unsigned long index);
+ getter MimeType? namedItem(DOMString name);
+};
+
+interface MimeType {
+ readonly attribute DOMString type;
+ readonly attribute DOMString description;
+ readonly attribute DOMString suffixes; // comma-separated
+ readonly attribute Plugin enabledPlugin;
+};
+
+interface External {
+ void AddSearchProvider(DOMString engineURL);
+ unsigned long IsSearchProviderInstalled(DOMString engineURL);
+};
+
+[Exposed=Window,Worker]
+interface ImageBitmap {
+ readonly attribute unsigned long width;
+ readonly attribute unsigned long height;
+};
+
+typedef (HTMLImageElement or
+ HTMLVideoElement or
+ HTMLCanvasElement or
+ Blob or
+ ImageData or
+ CanvasRenderingContext2D or
+ ImageBitmap) ImageBitmapSource;
+
+[NoInterfaceObject, Exposed=Window,Worker]
+interface ImageBitmapFactories {
+ Promise createImageBitmap(ImageBitmapSource image, optional long sx, long sy, long sw, long sh);
+};
+Window implements ImageBitmapFactories;
+WorkerGlobalScope implements ImageBitmapFactories;
+
+[Constructor(DOMString type, optional MessageEventInit eventInitDict), Exposed=Window,Worker]
+interface MessageEvent : Event {
+ readonly attribute any data;
+ readonly attribute DOMString origin;
+ readonly attribute DOMString lastEventId;
+ readonly attribute (WindowProxy or MessagePort)? source;
+ readonly attribute MessagePort[]? ports;
+
+ void initMessageEvent(DOMString typeArg, boolean canBubbleArg, boolean cancelableArg, any dataArg, DOMString originArg, DOMString lastEventIdArg, (WindowProxy or MessagePort) sourceArg, MessagePort[]? portsArg);
+};
+
+dictionary MessageEventInit : EventInit {
+ any data;
+ DOMString origin;
+ DOMString lastEventId;
+ (WindowProxy or MessagePort)? source;
+ sequence<MessagePort> ports;
+};
+
+[Constructor(DOMString url, optional EventSourceInit eventSourceInitDict), Exposed=Window,Worker]
+interface EventSource : EventTarget {
+ readonly attribute DOMString url;
+ readonly attribute boolean withCredentials;
+
+ // ready state
+ const unsigned short CONNECTING = 0;
+ const unsigned short OPEN = 1;
+ const unsigned short CLOSED = 2;
+ readonly attribute unsigned short readyState;
+
+ // networking
+ attribute EventHandler onopen;
+ attribute EventHandler onmessage;
+ attribute EventHandler onerror;
+ void close();
+};
+
+dictionary EventSourceInit {
+ boolean withCredentials = false;
+};
+
+enum BinaryType { "blob", "arraybuffer" };
+[Constructor(DOMString url, optional (DOMString or DOMString[]) protocols), Exposed=Window,Worker]
+interface WebSocket : EventTarget {
+ readonly attribute DOMString url;
+
+ // ready state
+ const unsigned short CONNECTING = 0;
+ const unsigned short OPEN = 1;
+ const unsigned short CLOSING = 2;
+ const unsigned short CLOSED = 3;
+ readonly attribute unsigned short readyState;
+ readonly attribute unsigned long bufferedAmount;
+
+ // networking
+ attribute EventHandler onopen;
+ attribute EventHandler onerror;
+ attribute EventHandler onclose;
+ readonly attribute DOMString extensions;
+ readonly attribute DOMString protocol;
+ void close([Clamp] optional unsigned short code, optional DOMString reason);
+
+ // messaging
+ attribute EventHandler onmessage;
+ attribute BinaryType binaryType;
+ void send(DOMString data);
+ void send(Blob data);
+ void send(ArrayBuffer data);
+ void send(ArrayBufferView data);
+};
+
+[Constructor(DOMString type, optional CloseEventInit eventInitDict), Exposed=Window,Worker]
+interface CloseEvent : Event {
+ readonly attribute boolean wasClean;
+ readonly attribute unsigned short code;
+ readonly attribute DOMString reason;
+};
+
+dictionary CloseEventInit : EventInit {
+ boolean wasClean;
+ unsigned short code;
+ DOMString reason;
+};
+
+[Constructor, Exposed=Window,Worker]
+interface MessageChannel {
+ readonly attribute MessagePort port1;
+ readonly attribute MessagePort port2;
+};
+
+[Exposed=Window,Worker]
+interface MessagePort : EventTarget {
+ void postMessage(any message, optional sequence<Transferable> transfer);
+ void start();
+ void close();
+
+ // event handlers
+ attribute EventHandler onmessage;
+};
+// MessagePort implements Transferable;
+
+[Constructor, Exposed=Window,Worker]
+interface PortCollection {
+ void add(MessagePort port);
+ void remove(MessagePort port);
+ void clear();
+ void iterate(PortCollectionCallback callback);
+};
+
+callback PortCollectionCallback = void (MessagePort port);
+
+[Constructor(DOMString channel), Exposed=Window,Worker]
+interface BroadcastChannel : EventTarget {
+ readonly attribute DOMString name;
+ void postMessage(any message);
+ void close();
+ attribute EventHandler onmessage;
+};
+
+[Exposed=Worker]
+interface WorkerGlobalScope : EventTarget {
+ readonly attribute WorkerGlobalScope self;
+ readonly attribute WorkerLocation location;
+
+ void close();
+ attribute OnErrorEventHandler onerror;
+ attribute EventHandler onlanguagechange;
+ attribute EventHandler onoffline;
+ attribute EventHandler ononline;
+
+ // also has additional members in a partial interface
+};
+
+[Global=Worker,DedicatedWorker]
+/*sealed*/ interface DedicatedWorkerGlobalScope : WorkerGlobalScope {
+ void postMessage(any message, optional sequence<Transferable> transfer);
+ attribute EventHandler onmessage;
+};
+
+[Global=Worker,SharedWorker]
+/*sealed*/ interface SharedWorkerGlobalScope : WorkerGlobalScope {
+ readonly attribute DOMString name;
+ readonly attribute ApplicationCache applicationCache;
+ attribute EventHandler onconnect;
+};
+
+[NoInterfaceObject, Exposed=Window,Worker]
+interface AbstractWorker {
+ attribute EventHandler onerror;
+};
+
+[Constructor(DOMString scriptURL), Exposed=Window,Worker]
+interface Worker : EventTarget {
+ void terminate();
+
+ void postMessage(any message, optional sequence<Transferable> transfer);
+ attribute EventHandler onmessage;
+};
+Worker implements AbstractWorker;
+
+[Constructor(DOMString scriptURL, optional DOMString name), Exposed=Window,Worker]
+interface SharedWorker : EventTarget {
+ readonly attribute MessagePort port;
+};
+SharedWorker implements AbstractWorker;
+
+[Exposed=Worker]
+partial interface WorkerGlobalScope { // not obsolete
+ void importScripts(DOMString... urls);
+ readonly attribute WorkerNavigator navigator;
+};
+WorkerGlobalScope implements WindowTimers;
+WorkerGlobalScope implements WindowBase64;
+
+[Exposed=Worker]
+interface WorkerNavigator {};
+WorkerNavigator implements NavigatorID;
+WorkerNavigator implements NavigatorLanguage;
+WorkerNavigator implements NavigatorOnLine;
+
+[Exposed=Worker]
+interface WorkerLocation { };
+WorkerLocation implements URLUtilsReadOnly;
+
+interface Storage {
+ readonly attribute unsigned long length;
+ DOMString? key(unsigned long index);
+ getter DOMString? getItem(DOMString key);
+ setter creator void setItem(DOMString key, DOMString value);
+ deleter void removeItem(DOMString key);
+ void clear();
+};
+
+[NoInterfaceObject]
+interface WindowSessionStorage {
+ readonly attribute Storage sessionStorage;
+};
+Window implements WindowSessionStorage;
+
+[NoInterfaceObject]
+interface WindowLocalStorage {
+ readonly attribute Storage localStorage;
+};
+Window implements WindowLocalStorage;
+
+[Constructor(DOMString type, optional StorageEventInit eventInitDict)]
+interface StorageEvent : Event {
+ readonly attribute DOMString? key;
+ readonly attribute DOMString? oldValue;
+ readonly attribute DOMString? newValue;
+ readonly attribute DOMString url;
+ readonly attribute Storage? storageArea;
+};
+
+dictionary StorageEventInit : EventInit {
+ DOMString? key;
+ DOMString? oldValue;
+ DOMString? newValue;
+ DOMString url;
+ Storage? storageArea;
+};
+
+interface HTMLAppletElement : HTMLElement {
+ attribute DOMString align;
+ attribute DOMString alt;
+ attribute DOMString archive;
+ attribute DOMString code;
+ attribute DOMString codeBase;
+ attribute DOMString height;
+ attribute unsigned long hspace;
+ attribute DOMString name;
+ attribute DOMString _object; // the underscore is not part of the identifier
+ attribute unsigned long vspace;
+ attribute DOMString width;
+};
+
+interface HTMLMarqueeElement : HTMLElement {
+ attribute DOMString behavior;
+ attribute DOMString bgColor;
+ attribute DOMString direction;
+ attribute DOMString height;
+ attribute unsigned long hspace;
+ attribute long loop;
+ attribute unsigned long scrollAmount;
+ attribute unsigned long scrollDelay;
+ attribute boolean trueSpeed;
+ attribute unsigned long vspace;
+ attribute DOMString width;
+
+ attribute EventHandler onbounce;
+ attribute EventHandler onfinish;
+ attribute EventHandler onstart;
+
+ void start();
+ void stop();
+};
+
+interface HTMLFrameSetElement : HTMLElement {
+ attribute DOMString cols;
+ attribute DOMString rows;
+};
+HTMLFrameSetElement implements WindowEventHandlers;
+
+interface HTMLFrameElement : HTMLElement {
+ attribute DOMString name;
+ attribute DOMString scrolling;
+ attribute DOMString src;
+ attribute DOMString frameBorder;
+ attribute DOMString longDesc;
+ attribute boolean noResize;
+ readonly attribute Document? contentDocument;
+ readonly attribute WindowProxy? contentWindow;
+
+ [TreatNullAs=EmptyString] attribute DOMString marginHeight;
+ [TreatNullAs=EmptyString] attribute DOMString marginWidth;
+};
+
+partial interface HTMLAnchorElement {
+ attribute DOMString coords;
+ attribute DOMString charset;
+ attribute DOMString name;
+ attribute DOMString rev;
+ attribute DOMString shape;
+};
+
+partial interface HTMLAreaElement {
+ attribute boolean noHref;
+};
+
+partial interface HTMLBodyElement {
+ [TreatNullAs=EmptyString] attribute DOMString text;
+ [TreatNullAs=EmptyString] attribute DOMString link;
+ [TreatNullAs=EmptyString] attribute DOMString vLink;
+ [TreatNullAs=EmptyString] attribute DOMString aLink;
+ [TreatNullAs=EmptyString] attribute DOMString bgColor;
+ attribute DOMString background;
+};
+
+partial interface HTMLBRElement {
+ attribute DOMString clear;
+};
+
+partial interface HTMLTableCaptionElement {
+ attribute DOMString align;
+};
+
+partial interface HTMLTableColElement {
+ attribute DOMString align;
+ attribute DOMString ch;
+ attribute DOMString chOff;
+ attribute DOMString vAlign;
+ attribute DOMString width;
+};
+
+interface HTMLDirectoryElement : HTMLElement {
+ attribute boolean compact;
+};
+
+partial interface HTMLDivElement {
+ attribute DOMString align;
+};
+
+partial interface HTMLDListElement {
+ attribute boolean compact;
+};
+
+partial interface HTMLEmbedElement {
+ attribute DOMString align;
+ attribute DOMString name;
+};
+
+interface HTMLFontElement : HTMLElement {
+ [TreatNullAs=EmptyString] attribute DOMString color;
+ attribute DOMString face;
+ attribute DOMString size;
+};
+
+partial interface HTMLHeadingElement {
+ attribute DOMString align;
+};
+
+partial interface HTMLHRElement {
+ attribute DOMString align;
+ attribute DOMString color;
+ attribute boolean noShade;
+ attribute DOMString size;
+ attribute DOMString width;
+};
+
+partial interface HTMLHtmlElement {
+ attribute DOMString version;
+};
+
+partial interface HTMLIFrameElement {
+ attribute DOMString align;
+ attribute DOMString scrolling;
+ attribute DOMString frameBorder;
+ attribute DOMString longDesc;
+
+ [TreatNullAs=EmptyString] attribute DOMString marginHeight;
+ [TreatNullAs=EmptyString] attribute DOMString marginWidth;
+};
+
+partial interface HTMLImageElement {
+ attribute DOMString name;
+ attribute DOMString lowsrc;
+ attribute DOMString align;
+ attribute unsigned long hspace;
+ attribute unsigned long vspace;
+ attribute DOMString longDesc;
+
+ [TreatNullAs=EmptyString] attribute DOMString border;
+};
+
+partial interface HTMLInputElement {
+ attribute DOMString align;
+ attribute DOMString useMap;
+};
+
+partial interface HTMLLegendElement {
+ attribute DOMString align;
+};
+
+partial interface HTMLLIElement {
+ attribute DOMString type;
+};
+
+partial interface HTMLLinkElement {
+ attribute DOMString charset;
+ attribute DOMString rev;
+ attribute DOMString target;
+};
+
+partial interface HTMLMenuElement {
+ attribute boolean compact;
+};
+
+partial interface HTMLMetaElement {
+ attribute DOMString scheme;
+};
+
+partial interface HTMLObjectElement {
+ attribute DOMString align;
+ attribute DOMString archive;
+ attribute DOMString code;
+ attribute boolean declare;
+ attribute unsigned long hspace;
+ attribute DOMString standby;
+ attribute unsigned long vspace;
+ attribute DOMString codeBase;
+ attribute DOMString codeType;
+
+ [TreatNullAs=EmptyString] attribute DOMString border;
+};
+
+partial interface HTMLOListElement {
+ attribute boolean compact;
+};
+
+partial interface HTMLParagraphElement {
+ attribute DOMString align;
+};
+
+partial interface HTMLParamElement {
+ attribute DOMString type;
+ attribute DOMString valueType;
+};
+
+partial interface HTMLPreElement {
+ attribute long width;
+};
+
+partial interface HTMLScriptElement {
+ attribute DOMString event;
+ attribute DOMString htmlFor;
+};
+
+partial interface HTMLTableElement {
+ attribute DOMString align;
+ attribute DOMString border;
+ attribute DOMString frame;
+ attribute DOMString rules;
+ attribute DOMString summary;
+ attribute DOMString width;
+
+ [TreatNullAs=EmptyString] attribute DOMString bgColor;
+ [TreatNullAs=EmptyString] attribute DOMString cellPadding;
+ [TreatNullAs=EmptyString] attribute DOMString cellSpacing;
+};
+
+partial interface HTMLTableSectionElement {
+ attribute DOMString align;
+ attribute DOMString ch;
+ attribute DOMString chOff;
+ attribute DOMString vAlign;
+};
+
+partial interface HTMLTableCellElement {
+ attribute DOMString align;
+ attribute DOMString axis;
+ attribute DOMString height;
+ attribute DOMString width;
+
+ attribute DOMString ch;
+ attribute DOMString chOff;
+ attribute boolean noWrap;
+ attribute DOMString vAlign;
+
+ [TreatNullAs=EmptyString] attribute DOMString bgColor;
+};
+
+partial interface HTMLTableDataCellElement {
+ attribute DOMString abbr;
+};
+
+partial interface HTMLTableRowElement {
+ attribute DOMString align;
+ attribute DOMString ch;
+ attribute DOMString chOff;
+ attribute DOMString vAlign;
+
+ [TreatNullAs=EmptyString] attribute DOMString bgColor;
+};
+
+partial interface HTMLUListElement {
+ attribute boolean compact;
+ attribute DOMString type;
+};
+
+partial interface Document {
+ [TreatNullAs=EmptyString] attribute DOMString fgColor;
+ [TreatNullAs=EmptyString] attribute DOMString linkColor;
+ [TreatNullAs=EmptyString] attribute DOMString vlinkColor;
+ [TreatNullAs=EmptyString] attribute DOMString alinkColor;
+ [TreatNullAs=EmptyString] attribute DOMString bgColor;
+
+ readonly attribute HTMLCollection anchors;
+ readonly attribute HTMLCollection applets;
+
+ void clear();
+ void captureEvents();
+ void releaseEvents();
+
+ readonly attribute HTMLAllCollection all;
+};
+
+partial interface Window {
+ void captureEvents();
+ void releaseEvents();
+};
+
+</script>
+<script>
+"use strict";
+var idlArray;
+var errorVideo; // used to get a MediaError object
+var iframe; // used to get a Document object (can't use `document` because some test clears the page)
+setup(function() {
+ idlArray = new IdlArray();
+ [].forEach.call(document.querySelectorAll("script[type=text\\/plain]"), function(node) {
+ if (node.className == "untested") {
+ idlArray.add_untested_idls(node.textContent);
+ } else {
+ idlArray.add_idls(node.textContent);
+ }
+ });
+ errorVideo = document.createElement('video');
+ errorVideo.src = 'data:,';
+ errorVideo.preload = 'auto';
+ iframe = document.createElement('iframe');
+ iframe.hidden = true;
+ document.body.appendChild(iframe);
+}, {explicit_done:true});
+window.onload = function() {
+ idlArray.add_objects({
+ NodeList: ['document.getElementsByName("name")'],
+ HTMLAllCollection: ['document.all'],
+ HTMLFormControlsCollection: ['document.createElement("form").elements'],
+ RadioNodeList: [],
+ HTMLOptionsCollection: ['document.createElement("select").options'],
+ HTMLPropertiesCollection: ['document.head.properties'],
+ PropertyNodeList: [],
+ DOMStringMap: ['document.head.dataset'],
+ DOMElementMap: ['document.cssElementMap'],
+ Transferable: [],
+ Document: ['iframe.contentDocument'],
+ XMLDocument: ['document.implementation.createDocument(null, "", null)'],
+ HTMLElement: [
+ 'document.createElement("noscript")',
+ 'document.createElement("section")',
+ 'document.createElement("nav")',
+ 'document.createElement("article")',
+ 'document.createElement("aside")',
+ 'document.createElement("hgroup")',
+ 'document.createElement("header")',
+ 'document.createElement("footer")',
+ 'document.createElement("address")',
+ 'document.createElement("dt")',
+ 'document.createElement("dd")',
+ 'document.createElement("figure")',
+ 'document.createElement("figcaption")',
+ 'document.createElement("em")',
+ 'document.createElement("strong")',
+ 'document.createElement("small")',
+ 'document.createElement("s")',
+ 'document.createElement("cite")',
+ 'document.createElement("dfn")',
+ 'document.createElement("abbr")',
+ 'document.createElement("code")',
+ 'document.createElement("var")',
+ 'document.createElement("samp")',
+ 'document.createElement("kbd")',
+ 'document.createElement("sub")',
+ 'document.createElement("sup")',
+ 'document.createElement("i")',
+ 'document.createElement("b")',
+ 'document.createElement("u")',
+ 'document.createElement("mark")',
+ 'document.createElement("ruby")',
+ 'document.createElement("rt")',
+ 'document.createElement("rp")',
+ 'document.createElement("bdi")',
+ 'document.createElement("bdo")',
+ 'document.createElement("wbr")',
+ 'document.createElement("summary")',
+ 'document.createElement("acronym")',
+ ],
+ HTMLUnknownElement: [
+ 'document.createElement("quasit")',
+ 'document.createElement("bgsound")',
+ 'document.createElement("isindex")',
+ 'document.createElement("multicol")',
+ 'document.createElement("nextid")',
+ 'document.createElement("rb")',
+ 'document.createElement("spacer")',
+ 'document.createElement("basefont")',
+ 'document.createElement("directory")',
+ 'document.createElement("mod")',
+ ],
+ HTMLHtmlElement: ['document.createElement("html")'],
+ HTMLHeadElement: ['document.createElement("head")'],
+ HTMLTitleElement: ['document.createElement("title")'],
+ HTMLBaseElement: ['document.createElement("base")'],
+ HTMLLinkElement: ['document.createElement("link")'],
+ HTMLMetaElement: ['document.createElement("meta")'],
+ HTMLStyleElement: ['document.createElement("style")'],
+ HTMLScriptElement: ['document.createElement("script")'],
+ HTMLBodyElement: ['document.createElement("body")'],
+ HTMLHeadingElement: [
+ 'document.createElement("h1")',
+ 'document.createElement("h2")',
+ 'document.createElement("h3")',
+ 'document.createElement("h4")',
+ 'document.createElement("h5")',
+ 'document.createElement("h6")',
+ ],
+ HTMLParagraphElement: ['document.createElement("p")'],
+ HTMLHRElement: ['document.createElement("hr")'],
+ HTMLPreElement: [
+ 'document.createElement("pre")',
+ 'document.createElement("listing")',
+ 'document.createElement("plaintext")',
+ 'document.createElement("xmp")',
+ ],
+ HTMLQuoteElement: [
+ 'document.createElement("blockquote")',
+ 'document.createElement("q")',
+ ],
+ HTMLOlistElement: ['document.createElement("ol")'],
+ HTMLUlistElement: ['document.createElement("ul")'],
+ HTMLLIElement: ['document.createElement("li")'],
+ HTMLDlistElement: ['document.createElement("dl")'],
+ HTMLDivElement: ['document.createElement("div")'],
+ HTMLAnchorElement: ['document.createElement("a")'],
+ HTMLDataElement: ['document.createElement("data")'],
+ HTMLTimeElement: ['document.createElement("time")'],
+ HTMLSpanElement: ['document.createElement("span")'],
+ HTMLBRElement: ['document.createElement("br")'],
+ HTMLModElement: [
+ 'document.createElement("ins")',
+ 'document.createElement("del")',
+ ],
+ HTMLPictureElement: ['document.createElement("picture")'],
+ HTMLImageElement: ['document.createElement("img")', 'new Image()'],
+ HTMLIframeElement: ['document.createElement("iframe")'],
+ HTMLEmbedElement: ['document.createElement("embed")'],
+ HTMLObjectElement: ['document.createElement("object")'],
+ HTMLParamElement: ['document.createElement("param")'],
+ HTMLVideoElement: ['document.createElement("video")'],
+ HTMLAudioElement: ['document.createElement("audio")', 'new Audio()'],
+ HTMLSourceElement: ['document.createElement("source")'],
+ HTMLTrackElement: ['document.createElement("track")'],
+ HTMLMediaElement: [],
+ MediaError: ['errorVideo.error'],
+ AudioTrackList: [],
+ AudioTrack: [],
+ VideoTrackList: [],
+ VideoTrack: [],
+ MediaController: ['new MediaController()'],
+ TextTrackList: ['document.createElement("video").textTracks'],
+ TextTrack: ['document.createElement("track").track'],
+ TextTrackCueList: ['document.createElement("video").addTextTrack("subtitles").cues'],
+ TextTrackCue: [],
+ DataCue: [],
+ TimeRanges: ['document.createElement("video").buffered'],
+ TrackEvent: ['new TrackEvent("addtrack"; {track:document.createElement("track").track})'],
+ HTMLCanvasElement: ['document.createElement("canvas")'],
+ CanvasRenderingContext2D: ['document.createElement("canvas").getContext("2d")'],
+ CanvasGradient: [],
+ CanvasPattern: [],
+ TextMetrics: [],
+ ImageData: [],
+ HTMLMapElement: ['document.createElement("map")'],
+ HTMLAreaElement: ['document.createElement("area")'],
+ HTMLTableElement: ['document.createElement("table")'],
+ HTMLTableCaptionElement: ['document.createElement("caption")'],
+ HTMLTableColElement: [
+ 'document.createElement("colgroup")',
+ 'document.createElement("col")',
+ ],
+ HTMLTableSectionElement: [
+ 'document.createElement("tbody")',
+ 'document.createElement("thead")',
+ 'document.createElement("tfoot")',
+ ],
+ HTMLTableRowElement: ['document.createElement("tr")'],
+ HTMLTableDataCellElement: ['document.createElement("td")'],
+ HTMLTableHeaderCellElement: ['document.createElement("th")'],
+ HTMLTableCellElement: [],
+ HTMLFormElement: ['document.createElement("form")'],
+ HTMLFieldsetElement: ['document.createElement("fieldset")'],
+ HTMLLegendElement: ['document.createElement("legend")'],
+ HTMLLabelElement: ['document.createElement("label")'],
+ HTMLInputElement: ['document.createElement("input")'],
+ HTMLButtonElement: ['document.createElement("button")'],
+ HTMLSelectElement: ['document.createElement("select")'],
+ HTMLDataListElement: ['document.createElement("datalist")'],
+ HTMLOptGroupElement: ['document.createElement("optgroup")'],
+ HTMLOptionElement: ['document.createElement("option")'],
+ HTMLTextAreaElement: ['document.createElement("textarea")'],
+ HTMLKeygenElement: ['document.createElement("keygen")'],
+ HTMLOutputElement: ['document.createElement("output")'],
+ HTMLProgressElement: ['document.createElement("progress")'],
+ HTMLMeterElement: ['document.createElement("meter")'],
+ ValidityState: ['document.createElement("input").validity'],
+ HTMLDetailsElement: ['document.createElement("details")'],
+ HTMLCommandElement: ['document.createElement("command")'],
+ HTMLMenuElement: ['document.createElement("menu")'],
+ Window: ['window'],
+ BarProp: [],
+ History: ['window.history'],
+ Location: ['window.location'],
+ PopStateEvent: ['new PopStateEvent("popstate", { data: {} })'],
+ HashChangeEvent: [],
+ PageTransitionEvent: [],
+ BeforeUnloadEvent: [],
+ ApplicationCache: ['window.applicationCache'],
+ WindowModal: [],
+ Navigator: ['window.navigator'],
+ External: ['window.external'],
+ DataTransfer: [],
+ DataTransferItemList: [],
+ DataTransferItem: [],
+ DragEvent: [],
+ NavigatorUserMediaError: [],
+ MediaStream: [],
+ LocalMediaStream: [],
+ MediaStreamTrack: [],
+ MediaStreamRecorder: [],
+ PeerConnection: [],
+ MediaStreamEvent: [],
+ ErrorEvent: [],
+ AbstractWorker: [],
+ Worker: [],
+ SharedWorker: [],
+ MessageEvent: [],
+ MessageChannel: [],
+ MessagePort: [],
+ HTMLAppletElement: ['document.createElement("applet")'],
+ HTMLMarqueeElement: ['document.createElement("marquee")'],
+ HTMLFrameSetElement: ['document.createElement("frameset")'],
+ HTMLFrameElement: ['document.createElement("frame")'],
+ HTMLDirectoryElement: ['document.createElement("dir")'],
+ HTMLFontElement: ['document.createElement("font")'],
+ });
+ idlArray.prevent_multiple_testing("HTMLElement");
+ idlArray.test();
+ done();
+};
+</script>
diff --git a/tests/wpt/web-platform-tests/html/dom/new-harness.js b/tests/wpt/web-platform-tests/html/dom/new-harness.js
new file mode 100644
index 00000000000..f7481996e12
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/new-harness.js
@@ -0,0 +1,22 @@
+// We override only the things we need to -- the rest we'll just inherit from
+// original-harness.js. Polymorphism, kind of.
+ReflectionHarness.catchUnexpectedExceptions = false;
+
+ReflectionHarness.test = function(expected, actual, description) {
+ test(function() {
+ assert_equals(expected, actual);
+ }, this.getTypeDescription() + ": " + description);
+ // This is the test suite that will rate conformance, so we don't want to
+ // bail out early if a test fails -- we want all tests to always run.
+ return true;
+}
+
+ReflectionHarness.run = function(fun, description) {
+ test(fun, this.getTypeDescription() + ": " + description);
+}
+
+ReflectionHarness.testException = function(exceptionName, fn, description) {
+ test(function() {
+ assert_throws(exceptionName, fn);
+ }, this.getTypeDescription() + ": " + description);
+}
diff --git a/tests/wpt/web-platform-tests/html/dom/original-harness.js b/tests/wpt/web-platform-tests/html/dom/original-harness.js
new file mode 100644
index 00000000000..3cfa05bcb8d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/original-harness.js
@@ -0,0 +1,332 @@
+var ReflectionHarness = {};
+
+// @private
+ReflectionHarness.passed = document.getElementById("passed");
+ReflectionHarness.failed = document.getElementById("failed");
+
+/**
+ * Should we report a failure for unexpected exceptions, or just rethrow them?
+ * The original test framework reports an exception, but testharness.js doesn't
+ * want that.
+ *
+ * @public
+ */
+ReflectionHarness.catchUnexpectedExceptions = true;
+
+/**
+ * Returns a string representing val. Basically just adds quotes for strings,
+ * and passes through other recognized types literally.
+ *
+ * @public
+ */
+ReflectionHarness.stringRep = function(val) {
+ if (val === null) {
+ // typeof is object, so the switch isn't useful
+ return "null";
+ }
+ // In JavaScript, -0 === 0 and String(-0) == "0", so we have to
+ // special-case.
+ if (val === -0 && 1/val === -Infinity) {
+ return "-0";
+ }
+ switch (typeof val) {
+ case "string":
+ for (var i = 0; i < 32; i++) {
+ var replace = "\\";
+ switch (i) {
+ case 0: replace += "0"; break;
+ case 1: replace += "x01"; break;
+ case 2: replace += "x02"; break;
+ case 3: replace += "x03"; break;
+ case 4: replace += "x04"; break;
+ case 5: replace += "x05"; break;
+ case 6: replace += "x06"; break;
+ case 7: replace += "x07"; break;
+ case 8: replace += "b"; break;
+ case 9: replace += "t"; break;
+ case 10: replace += "n"; break;
+ case 11: replace += "v"; break;
+ case 12: replace += "f"; break;
+ case 13: replace += "r"; break;
+ case 14: replace += "x0e"; break;
+ case 15: replace += "x0f"; break;
+ case 16: replace += "x10"; break;
+ case 17: replace += "x11"; break;
+ case 18: replace += "x12"; break;
+ case 19: replace += "x13"; break;
+ case 20: replace += "x14"; break;
+ case 21: replace += "x15"; break;
+ case 22: replace += "x16"; break;
+ case 23: replace += "x17"; break;
+ case 24: replace += "x18"; break;
+ case 25: replace += "x19"; break;
+ case 26: replace += "x1a"; break;
+ case 27: replace += "x1b"; break;
+ case 28: replace += "x1c"; break;
+ case 29: replace += "x1d"; break;
+ case 30: replace += "x1e"; break;
+ case 31: replace += "x1f"; break;
+ }
+ val = val.replace(String.fromCharCode(i), replace);
+ }
+ return '"' + val.replace('"', '\\"') + '"';
+ case "boolean":
+ case "undefined":
+ case "number":
+ return val + "";
+ default:
+ return typeof val + ' "' + val + '"';
+ }
+}
+
+/**
+ * An object representing info about the current test, used for printing out
+ * nice messages and so forth.
+ */
+ReflectionHarness.currentTestInfo = {};
+
+/**
+ * This is called when we want to test a single element/attribute combination.
+ * For the original harness, it does nothing special (just calls the function),
+ * but for testharness.js, it can wrap everything in a test() call.
+ */
+ReflectionHarness.testWrapper = function(fn) {
+ fn();
+}
+
+/**
+ * If question === answer, output a success, else report a failure with the
+ * given description. Currently success and failure both increment counters,
+ * and failures output a message to a <ul>. Which <ul> is decided by the type
+ * parameter -- different attribute types are separated for readability.
+ *
+ * @public
+ */
+ReflectionHarness.test = function(expected, actual, description) {
+ // Special-case -0 yay!
+ if (expected === 0 && actual === 0 && 1/expected === 1/actual) {
+ this.increment(this.passed);
+ return true;
+ } else if (expected === actual) {
+ this.increment(this.passed);
+ return true;
+ } else {
+ this.increment(this.failed);
+ this.reportFailure(description + ' (expected ' + this.stringRep(actual) + ', got ' + this.stringRep(expected) + ')');
+ return false;
+ }
+}
+
+ReflectionHarness.run = function(fun, description) {
+ try {
+ fun();
+ } catch (err) {
+ ReflectionHarness.failure(description);
+ }
+}
+
+/**
+ * If calling fn causes a DOMException of the type given by the string
+ * exceptionName (e.g., "INDEX_SIZE_ERR"), output a success. Otherwise, report
+ * a failure with the given description.
+ *
+ * @public
+ */
+ReflectionHarness.testException = function(exceptionName, fn, description) {
+ try {
+ fn();
+ } catch (e) {
+ if (e instanceof DOMException && e.code == DOMException[exceptionName]) {
+ this.increment(this.passed);
+ return true;
+ }
+ }
+ this.increment(this.failed);
+ this.reportFailure(description);
+ return false;
+}
+
+/**
+ * Get a description of the current type, e.g., "a.href".
+ */
+ReflectionHarness.getTypeDescription = function() {
+ var domNode = this.currentTestInfo.domObj.tagName.toLowerCase();
+ var idlNode = this.currentTestInfo.idlObj.nodeName.toLowerCase();
+ var domName = this.currentTestInfo.domName;
+ var idlName = this.currentTestInfo.idlName;
+ var comment = this.currentTestInfo.data.comment;
+ var typeDesc = idlNode + "." + idlName;
+ if (!comment && (domNode != idlNode || domName != idlName)) {
+ comment = "<" + domNode + " " + domName + ">";
+ }
+ if (comment) {
+ typeDesc += " (" + comment + ")";
+ }
+ return typeDesc;
+}
+
+/**
+ * Report a failure with the given description, adding context from the
+ * currentTestInfo member.
+ *
+ * @private
+ */
+ReflectionHarness.reportFailure = function(description) {
+ var typeDesc = this.getTypeDescription();
+ var idlName = this.currentTestInfo.idlName;
+ var comment = this.currentTestInfo.data.comment;
+ typeDesc = typeDesc.replace("&", "&amp;").replace("<", "&lt;");
+ description = description.replace("&", "&amp;").replace("<", "&lt;");
+
+ var type = this.currentTestInfo.data.type;
+
+ // Special case for undefined attributes, which we don't want getting in
+ // the way of everything else.
+ if (description.search('^typeof IDL attribute \\(expected ".*", got "undefined"\\)$') != -1) {
+ type = "undefined";
+ }
+
+ var done = false;
+ var ul = document.getElementById("errors-" + type.replace(" ", "-"));
+ if (ul === null) {
+ ul = document.createElement("ul");
+ ul.id = "errors-" + type.replace(" ", "-");
+ var div = document.getElementById("errors");
+ p = document.createElement("p");
+ if (type == "undefined") {
+ div.parentNode.insertBefore(ul, div.nextSibling);
+ p.innerHTML = "These IDL attributes were of undefined type, presumably representing unimplemented features (cordoned off into a separate section for tidiness):";
+ } else {
+ div.appendChild(ul);
+ p.innerHTML = "Errors for type " + type + ":";
+ }
+ ul.parentNode.insertBefore(p, ul);
+ } else if (type != "undefined") {
+ var existingErrors = ul.getElementsByClassName("desc");
+ for (var i = 0; i < existingErrors.length; i++) {
+ if (existingErrors[i].innerHTML == description) {
+ var typeSpan = existingErrors[i].parentNode.getElementsByClassName("type")[0];
+ // Check if we have lots of the same error for the same
+ // attribute. If so, we want to collapse them -- the exact
+ // elements that exhibit the error aren't going to be important
+ // to report in this case, and it can take a lot of space if
+ // there's an error in a global attribute like dir or id.
+ var types = typeSpan.innerHTML.split(", ");
+ var count = 0;
+ for (var i = 0; i < types.length; i++) {
+ if (types[i].search("^\\([0-9]* elements\\)\\." + idlName + "$") != -1) {
+ types[i] = "(" + (1 + parseInt(/[0-9]+/.exec(types[i])[0])) + " elements)." + idlName;
+ typeSpan.innerHTML = types.join(", ");
+ return;
+ } else if (types[i].search("\\." + idlName + "$") != -1) {
+ count++;
+ }
+ }
+ if (comment || count < 10) {
+ // Just add the extra error to the end, not many duplicates
+ // (or we have a comment)
+ typeSpan.innerHTML += ", " + typeDesc;
+ } else {
+ var filteredTypes = types.filter(function(type) { return type.search("\\." + idlName + "$") == -1; });
+ if (filteredTypes.length) {
+ typeSpan.innerHTML = filteredTypes.join(", ") + ", ";
+ } else {
+ typeSpan.innerHTML = "";
+ }
+ typeSpan.innerHTML += "(" + (types.length - filteredTypes.length) + " elements)." + idlName;
+ }
+ return;
+ }
+ }
+ }
+
+ if (type == "undefined") {
+ ul.innerHTML += "<li>" + typeDesc;
+ } else {
+ ul.innerHTML += "<li><span class=\"type\">" + typeDesc + "</span>: <span class=\"desc\">" + description + "</span>";
+ }
+}
+
+/**
+ * Shorthand function for when we have a failure outside of test(). Generally
+ * used when the failure is an exception thrown unexpectedly or such, something
+ * not equality-based.
+ *
+ * @public
+ */
+ReflectionHarness.failure = function(message) {
+ this.increment(this.failed);
+ this.reportFailure(message);
+}
+
+/**
+ * Shorthand function for when we have a success outside of test(). Only
+ * called if catchUnexpectedExceptions is true.
+ *
+ * @public
+ */
+ReflectionHarness.success = function() {
+ this.increment(this.passed);
+}
+
+/**
+ * Increment the count in either "passed" or "failed". el should always be one
+ * of those two variables. The implementation of this function amuses me.
+ *
+ * @private
+ */
+ReflectionHarness.increment = function(el) {
+ el.innerHTML = parseInt(el.innerHTML) + 1;
+ var percent = document.getElementById("percent");
+ var passed = document.getElementById("passed");
+ var failed = document.getElementById("failed");
+ percent.innerHTML = (parseInt(passed.innerHTML)/(parseInt(passed.innerHTML) + parseInt(failed.innerHTML))*100).toPrecision(3);
+}
+
+/**
+ * Hide all displayed errors matching a given regex, so it's easier to filter
+ * out repetitive failures. TODO: Fix this so it works right with the new
+ * "lump many errors in one <li>" thing.
+ *
+ * @private (kind of, only called in the original reflection.html)
+ */
+ReflectionHarness.maskErrors = function(regex) {
+ var uls = document.getElementsByTagName("ul");
+ for (var i = 0; i < uls.length; i++) {
+ var lis = uls[i].children;
+ for (var j = 0; j < lis.length; j++) {
+ if (regex !== "" && lis[j].innerHTML.match(regex)) {
+ lis[j].style.display = "none";
+ } else {
+ lis[j].style.display = "list-item";
+ }
+ }
+ }
+}
+
+// Now for some stuff that has nothing to do with ReflectionHarness and
+// everything to do with initialization needed for reflection.js, which seems
+// pointless to put in an extra file.
+
+var elements = {};
+
+var extraTests = [];
+
+/**
+ * Used for combining a number of small arrays of element data into one big
+ * one.
+ */
+function mergeElements(src) {
+ for (var key in src) {
+ if (!src.hasOwnProperty(key)) {
+ // This is inherited from a prototype or something.
+ continue;
+ }
+
+ if (key in elements) {
+ elements[key] = elements[key].concat(src[key]);
+ } else {
+ elements[key] = src[key];
+ }
+ }
+}
diff --git a/tests/wpt/web-platform-tests/html/dom/reflection-embedded.html b/tests/wpt/web-platform-tests/html/dom/reflection-embedded.html
new file mode 100644
index 00000000000..c2b899644d5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/reflection-embedded.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<title>HTML5 reflection tests: embedded elements</title>
+<meta name=timeout content=long>
+<p>Implementers looking to fix bugs might want to use the <a
+href=reflection-original.html>original version</a> of this suite's test
+framework, which conveniently aggregates similar errors and only reports
+failures. This file is (part of) the authoritative conformance test suite, and
+is suitable for incorporation into automated test suites.
+
+<div id=log></div>
+
+<script src="/resources/testharness.js"></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=original-harness.js></script>
+<script src=new-harness.js></script>
+<script src=elements-embedded.js></script>
+<script src=elements-microdata.js></script>
+<script src=reflection.js></script>
diff --git a/tests/wpt/web-platform-tests/html/dom/reflection-forms.html b/tests/wpt/web-platform-tests/html/dom/reflection-forms.html
new file mode 100644
index 00000000000..4ba5b204f50
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/reflection-forms.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<title>HTML5 reflection tests: form elements</title>
+<meta name=timeout content=long>
+<p>Implementers looking to fix bugs might want to use the <a
+href=reflection-original.html>original version</a> of this suite's test
+framework, which conveniently aggregates similar errors and only reports
+failures. This file is (part of) the authoritative conformance test suite, and
+is suitable for incorporation into automated test suites.
+
+<div id=log></div>
+
+<script src="/resources/testharness.js"></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=original-harness.js></script>
+<script src=new-harness.js></script>
+<script src=elements-forms.js></script>
+<script src=elements-microdata.js></script>
+<script src=reflection.js></script>
diff --git a/tests/wpt/web-platform-tests/html/dom/reflection-grouping.html b/tests/wpt/web-platform-tests/html/dom/reflection-grouping.html
new file mode 100644
index 00000000000..d12ff5d4d14
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/reflection-grouping.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<title>HTML5 reflection tests: grouping elements</title>
+<meta name=timeout content=long>
+<p>Implementers looking to fix bugs might want to use the <a
+href=reflection-original.html>original version</a> of this suite's test
+framework, which conveniently aggregates similar errors and only reports
+failures. This file is (part of) the authoritative conformance test suite, and
+is suitable for incorporation into automated test suites.
+
+<div id=log></div>
+
+<script src="/resources/testharness.js"></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=original-harness.js></script>
+<script src=new-harness.js></script>
+<script src=elements-grouping.js></script>
+<script src=elements-microdata.js></script>
+<script src=reflection.js></script>
diff --git a/tests/wpt/web-platform-tests/html/dom/reflection-metadata.html b/tests/wpt/web-platform-tests/html/dom/reflection-metadata.html
new file mode 100644
index 00000000000..90ff608a044
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/reflection-metadata.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<title>HTML5 reflection tests: metadata elements</title>
+<meta name=timeout content=long>
+<p>Implementers looking to fix bugs might want to use the <a
+href=reflection-original.html>original version</a> of this suite's test
+framework, which conveniently aggregates similar errors and only reports
+failures. This file is (part of) the authoritative conformance test suite, and
+is suitable for incorporation into automated test suites.
+
+<div id=log></div>
+
+<script src="/resources/testharness.js"></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=original-harness.js></script>
+<script src=new-harness.js></script>
+<script src=elements-metadata.js></script>
+<script src=elements-microdata.js></script>
+<script src=reflection.js></script>
diff --git a/tests/wpt/web-platform-tests/html/dom/reflection-misc.html b/tests/wpt/web-platform-tests/html/dom/reflection-misc.html
new file mode 100644
index 00000000000..d8baf9cfde3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/reflection-misc.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<title>HTML5 reflection tests: miscellaneous elements</title>
+<meta name=timeout content=long>
+<p>Implementers looking to fix bugs might want to use the <a
+href=reflection-original.html>original version</a> of this suite's test
+framework, which conveniently aggregates similar errors and only reports
+failures. This file is (part of) the authoritative conformance test suite, and
+is suitable for incorporation into automated test suites.
+
+<div id=log></div>
+
+<script src="/resources/testharness.js"></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=original-harness.js></script>
+<script src=new-harness.js></script>
+<script src=elements-misc.js></script>
+<script src=elements-microdata.js></script>
+<script src=reflection.js></script>
diff --git a/tests/wpt/web-platform-tests/html/dom/reflection-obsolete.html b/tests/wpt/web-platform-tests/html/dom/reflection-obsolete.html
new file mode 100644
index 00000000000..9c53774fc77
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/reflection-obsolete.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<title>HTML5 reflection tests: obsolete elements</title>
+<meta name=timeout content=long>
+<p>Implementers looking to fix bugs might want to use the <a
+href=reflection-original.html>original version</a> of this suite's test
+framework, which conveniently aggregates similar errors and only reports
+failures. This file is (part of) the authoritative conformance test suite, and
+is suitable for incorporation into automated test suites.
+
+<div id=log></div>
+
+<script src="/resources/testharness.js"></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=original-harness.js></script>
+<script src=new-harness.js></script>
+<script src=elements-obsolete.js></script>
+<script src=elements-microdata.js></script>
+<script src=reflection.js></script>
diff --git a/tests/wpt/web-platform-tests/html/dom/reflection-original.html b/tests/wpt/web-platform-tests/html/dom/reflection-original.html
new file mode 100644
index 00000000000..f037080402d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/reflection-original.html
@@ -0,0 +1,41 @@
+<!doctype html>
+<title>HTML5 reflection tests</title>
+<meta name=timeout content=long>
+<p>This is <em>not</em> the authoritative conformance test suite for
+reflection. The authoritative tests can be found here, split up into sections:
+
+<ul>
+ <li><a href=reflection-metadata.html>Metadata elements</a>
+ <li><a href=reflection-sections.html>Section elements</a>
+ <li><a href=reflection-grouping.html>Grouping elements</a>
+ <li><a href=reflection-text.html>Text elements</a>
+ <li><a href=reflection-embedded.html>Embedded elements</a>
+ <li><a href=reflection-tabular.html>Tabular elements</a>
+ <li><a href=reflection-forms.html>Form elements</a>
+ <li><a href=reflection-misc.html>Miscellaneous elements</a>
+ <li><a href=reflection-obsolete.html>Obsolete elements</a>
+</ul>
+
+<p>This test suite is provided for implementers' convenience in debugging
+failures. It groups similar failures in a fashion that should help fix them.
+It is not intended to be suitable for incorporation into automated testing
+frameworks.
+
+<p>Filter out errors matching a regex (operates on HTML not text, you have to manually escape entities): <input oninput="maskErrors(this.value)">
+
+<p>Passed: <span id=passed>0</span> (<span id=percent></span>%). Failed: <span id=failed>0</span>. Time to complete: <span id=time>0</span> s.
+
+<div id=errors></div>
+
+<script src=original-harness.js></script>
+<script src=elements-metadata.js></script>
+<script src=elements-sections.js></script>
+<script src=elements-grouping.js></script>
+<script src=elements-text.js></script>
+<script src=elements-embedded.js></script>
+<script src=elements-tabular.js></script>
+<script src=elements-forms.js></script>
+<script src=elements-misc.js></script>
+<script src=elements-obsolete.js></script>
+<script src=elements-microdata.js></script>
+<script src=reflection.js></script>
diff --git a/tests/wpt/web-platform-tests/html/dom/reflection-sections.html b/tests/wpt/web-platform-tests/html/dom/reflection-sections.html
new file mode 100644
index 00000000000..7d4ba16ef29
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/reflection-sections.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<title>HTML5 reflection tests: section elements</title>
+<meta name=timeout content=long>
+<p>Implementers looking to fix bugs might want to use the <a
+href=reflection-original.html>original version</a> of this suite's test
+framework, which conveniently aggregates similar errors and only reports
+failures. This file is (part of) the authoritative conformance test suite, and
+is suitable for incorporation into automated test suites.
+
+<div id=log></div>
+
+<script src="/resources/testharness.js"></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=original-harness.js></script>
+<script src=new-harness.js></script>
+<script src=elements-sections.js></script>
+<script src=elements-microdata.js></script>
+<script src=reflection.js></script>
diff --git a/tests/wpt/web-platform-tests/html/dom/reflection-tabular.html b/tests/wpt/web-platform-tests/html/dom/reflection-tabular.html
new file mode 100644
index 00000000000..e6b9c578737
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/reflection-tabular.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<title>HTML5 reflection tests: tabular elements</title>
+<meta name=timeout content=long>
+<p>Implementers looking to fix bugs might want to use the <a
+href=reflection-original.html>original version</a> of this suite's test
+framework, which conveniently aggregates similar errors and only reports
+failures. This file is (part of) the authoritative conformance test suite, and
+is suitable for incorporation into automated test suites.
+
+<div id=log></div>
+
+<script src="/resources/testharness.js"></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=original-harness.js></script>
+<script src=new-harness.js></script>
+<script src=elements-tabular.js></script>
+<script src=elements-microdata.js></script>
+<script src=reflection.js></script>
diff --git a/tests/wpt/web-platform-tests/html/dom/reflection-text.html b/tests/wpt/web-platform-tests/html/dom/reflection-text.html
new file mode 100644
index 00000000000..f840ef692cf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/reflection-text.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<title>HTML5 reflection tests: text elements</title>
+<meta name=timeout content=long>
+<p>Implementers looking to fix bugs might want to use the <a
+href=reflection-original.html>original version</a> of this suite's test
+framework, which conveniently aggregates similar errors and only reports
+failures. This file is (part of) the authoritative conformance test suite, and
+is suitable for incorporation into automated test suites.
+
+<div id=log></div>
+
+<script src="/resources/testharness.js"></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=original-harness.js></script>
+<script src=new-harness.js></script>
+<script src=elements-text.js></script>
+<script src=elements-microdata.js></script>
+<script src=reflection.js></script>
diff --git a/tests/wpt/web-platform-tests/html/dom/reflection.js b/tests/wpt/web-platform-tests/html/dom/reflection.js
new file mode 100644
index 00000000000..4010d7e3048
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/dom/reflection.js
@@ -0,0 +1,809 @@
+ReflectionTests = {};
+
+ReflectionTests.start = new Date().getTime();
+
+/**
+ * Resolve the given URL to an absolute URL, relative to the current document's
+ * address. There's no API that I know of that exposes this directly, so we
+ * actually just create an <a> element, set its href, and stitch together the
+ * various properties. Seems to work. We don't try to reimplement the
+ * algorithm here, because we're not concerned with its correctness -- we're
+ * only testing HTML reflection, not Web Addresses.
+ *
+ * Return "" if the URL couldn't be resolved, since this is really for
+ * reflected URL attributes, and those are supposed to return "" if the URL
+ * couldn't be resolved.
+ *
+ * It seems like IE9 doesn't implement URL decomposition attributes correctly
+ * for <a>, which causes all these tests to fail. Ideally I'd do this in some
+ * other way, but the failure does stem from an incorrect implementation of
+ * HTML, so I'll leave it alone for now.
+ *
+ * TODO: This relies on reflection to test reflection, so it could mask bugs.
+ * Either get a JS implementation of the "resolve a URL" algorithm, or just
+ * specify expected values manually here. It shouldn't be too hard to write
+ * special cases for all the values we test.
+ */
+ReflectionTests.resolveUrl = function(url) {
+ var el = document.createElement("a");
+ el.href = String(url);
+ var ret = el.protocol + "//" + el.host + el.pathname + el.search + el.hash;
+ if (ret == "//") {
+ return "";
+ } else {
+ return ret;
+ }
+};
+
+/**
+ * Given some input, convert to a multi-URL value for IDL get per the spec.
+ */
+ReflectionTests.urlsExpected = function(urls) {
+ var expected = "";
+ // TODO: Test other whitespace?
+ urls = urls + "";
+ var split = urls.split(" ");
+ for (var j = 0; j < split.length; j++) {
+ if (split[j] == "") {
+ continue;
+ }
+ var append = ReflectionTests.resolveUrl(split[j]);
+ if (append == "") {
+ continue;
+ }
+ if (expected == "") {
+ expected = append;
+ } else {
+ expected += " " + append;
+ }
+ }
+ return expected;
+};
+
+/**
+ * The "rules for parsing non-negative integers" from the HTML spec. They're
+ * mostly used for reflection, so here seems like as good a place to test them
+ * as any. Returns false on error.
+ */
+ReflectionTests.parseNonneg = function(input) {
+ var value = this.parseInt(input);
+ if (value === false || value < 0) {
+ return false;
+ }
+ return value;
+};
+
+/**
+ * The "rules for parsing integers" from the HTML spec. Returns false on
+ * error.
+ */
+ReflectionTests.parseInt = function(input) {
+ var position = 0;
+ var sign = 1;
+ // Skip whitespace
+ while (input.length > position && /^[ \t\n\f\r]$/.test(input[position])) {
+ position++;
+ }
+ if (position >= input.length) {
+ return false;
+ }
+ if (input[position] == "-") {
+ sign = -1;
+ position++;
+ } else if (input[position] == "+") {
+ position++;
+ }
+ if (position >= input.length) {
+ return false;
+ }
+ if (!/^[0-9]$/.test(input[position])) {
+ return false;
+ }
+ var value = 0;
+ while (input.length > position && /^[0-9]$/.test(input[position])) {
+ value *= 10;
+ // Don't use parseInt even for single-digit strings . . .
+ value += input.charCodeAt(position) - "0".charCodeAt(0);
+ position++;
+ }
+ if (value === 0) {
+ return 0;
+ }
+ return sign * value;
+};
+
+// Used in initializing typeMap
+var binaryString = "\x00\x01\x02\x03\x04\x05\x06\x07 "
+ + "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f "
+ + "\x10\x11\x12\x13\x14\x15\x16\x17 "
+ + "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f ";
+var maxInt = 2147483647;
+var minInt = -2147483648;
+var maxUnsigned = 4294967295;
+
+/**
+ * Array containing the tests and other information for each type of reflected
+ * attribute. Meaning of keys:
+ *
+ * "jsType": What typeof idlObj[idlName] is supposed to be.
+ * "defaultVal": The default value to be returned if the attribute is not
+ * present and no default is specifically set for this attribute.
+ * "domTests": What values to test with setAttribute().
+ * "domExpected": What values to expect with IDL get after setAttribute().
+ * Defaults to the same as domTests.
+ * "idlTests": What values to test with IDL set. Defaults to domTests.
+ * "idlDomExpected": What to expect from getAttribute() after IDL set.
+ * Defaults to idlTests.
+ * "idlIdlExpected": What to expect from IDL get after IDL set. Defaults to
+ * idlDomExpected.
+ *
+ * Note that all tests/expected values are only baselines, and can be expanded
+ * with additional tests hardcoded into the function for particular types if
+ * necessary (e.g., enum). null means "default" as a DOM expected value, and
+ * "throw an INDEX_SIZE_ERR exception" as an IDL expected value. (This is a
+ * kind of stupid and fragile convention, but it's simple and works for now.)
+ * Expected DOM values are cast to strings by adding "".
+ *
+ * TODO: Test strings that aren't valid UTF-16. Desired behavior is not clear
+ * here at the time of writing, see
+ * http://www.w3.org/Bugs/Public/show_bug.cgi?id=12100
+ *
+ * TODO: Test deleting an IDL attribute, and maybe doing other fun stuff to it.
+ *
+ * TODO: Test IDL sets of integer types to out-of-range or other weird values.
+ * WebIDL says to wrap, but I'm not sure offhand if that's what we want.
+ *
+ * TODO: tokenlist, settable tokenlist, limited
+ */
+
+
+ReflectionTests.typeMap = {
+ /**
+ * "If a reflecting IDL attribute is a DOMString but doesn't fall into any
+ * of the above categories, then the getting and setting must be done in a
+ * transparent, case-preserving manner."
+ *
+ * The data object passed to reflects() can contain an optional key
+ * treatNullAsEmptyString, whose value is ignored. If it does contain the
+ * key, null will be cast to "" instead of "null", per WebIDL
+ * [TreatNullAs=EmptyString].
+ */
+ "string": {
+ "jsType": "string",
+ "defaultVal": "",
+ "domTests": ["", " " + binaryString + " foo ", undefined, 7, 1.5, true,
+ false, {"test": 6}, NaN, +Infinity, -Infinity, "\0", null,
+ {"toString":function(){return "test-toString";}},
+ {"valueOf":function(){return "test-valueOf";}, toString:null}
+ ]
+ },
+ /**
+ * "If a reflecting IDL attribute is a DOMString attribute whose content
+ * attribute is defined to contain a URL, then on getting, the IDL
+ * attribute must resolve the value of the content attribute relative to
+ * the element and return the resulting absolute URL if that was
+ * successful, or the empty string otherwise; and on setting, must set the
+ * content attribute to the specified literal value. If the content
+ * attribute is absent, the IDL attribute must return the default value, if
+ * the content attribute has one, or else the empty string."
+ */
+ "url": {
+ "jsType": "string",
+ "defaultVal": "",
+ "domTests": ["", " foo ", "http://site.example/",
+ "//site.example/path???@#l", binaryString, undefined, 7, 1.5, true,
+ false, {"test": 6}, NaN, +Infinity, -Infinity, "\0", null,
+ {"toString":function(){return "test-toString";}},
+ {"valueOf":function(){return "test-valueOf";}, toString:null}],
+ "domExpected": ReflectionTests.resolveUrl,
+ "idlIdlExpected": ReflectionTests.resolveUrl
+ },
+ /**
+ * "If a reflecting IDL attribute is a DOMString attribute whose content
+ * attribute is defined to contain one or more URLs, then on getting, the
+ * IDL attribute must split the content attribute on spaces and return the
+ * concatenation of resolving each token URL to an absolute URL relative to
+ * the element, with a single U+0020 SPACE character between each URL,
+ * ignoring any tokens that did not resolve successfully. If the content
+ * attribute is absent, the IDL attribute must return the default value, if
+ * the content attribute has one, or else the empty string. On setting, the
+ * IDL attribute must set the content attribute to the specified literal
+ * value."
+ *
+ * Seems to only be used for ping.
+ */
+ "urls": {
+ "jsType": "string",
+ "defaultVal": "",
+ "domTests": ["", " foo ", "http://site.example/ foo bar baz",
+ "//site.example/path???@#l", binaryString, undefined, 7, 1.5, true,
+ false, {"test": 6}, NaN, +Infinity, -Infinity, "\0", null,
+ {"toString":function(){return "test-toString";}},
+ {"valueOf":function(){return "test-valueOf";}, toString:null}],
+ "domExpected": ReflectionTests.urlsExpected,
+ "idlIdlExpected": ReflectionTests.urlsExpected
+ },
+ /**
+ * "If a reflecting IDL attribute is a DOMString whose content attribute is
+ * an enumerated attribute, and the IDL attribute is limited to only known
+ * values, then, on getting, the IDL attribute must return the conforming
+ * value associated with the state the attribute is in (in its canonical
+ * case), or the empty string if the attribute is in a state that has no
+ * associated keyword value; and on setting, if the new value is an ASCII
+ * case-insensitive match for one of the keywords given for that attribute,
+ * then the content attribute must be set to the conforming value
+ * associated with the state that the attribute would be in if set to the
+ * given new value, otherwise, if the new value is the empty string, then
+ * the content attribute must be removed, otherwise, the content attribute
+ * must be set to the given new value."
+ *
+ * "Some attributes are defined as taking one of a finite set of keywords.
+ * Such attributes are called enumerated attributes. The keywords are each
+ * defined to map to a particular state (several keywords might map to the
+ * same state, in which case some of the keywords are synonyms of each
+ * other; additionally, some of the keywords can be said to be
+ * non-conforming, and are only in the specification for historical
+ * reasons). In addition, two default states can be given. The first is the
+ * invalid value default, the second is the missing value default.
+ *
+ * . . .
+ *
+ * When the attribute is specified, if its value is an ASCII
+ * case-insensitive match for one of the given keywords then that keyword's
+ * state is the state that the attribute represents. If the attribute value
+ * matches none of the given keywords, but the attribute has an invalid
+ * value default, then the attribute represents that state. Otherwise, if
+ * the attribute value matches none of the keywords but there is a missing
+ * value default state defined, then that is the state represented by the
+ * attribute. Otherwise, there is no default, and invalid values must be
+ * ignored.
+ *
+ * When the attribute is not specified, if there is a missing value default
+ * state defined, then that is the state represented by the (missing)
+ * attribute. Otherwise, the absence of the attribute means that there is
+ * no state represented."
+ *
+ * This is only used for enums that are limited to known values, not other
+ * enums (those are treated as generic strings by the spec). The data
+ * object passed to reflects() can contain these keys:
+ *
+ * "defaultVal": missing value default (defaults to "")
+ * "invalidVal": invalid value default (defaults to defaultVal)
+ * "keywords": array of keywords as given by the spec (required)
+ * "nonCanon": dictionary mapping non-canonical values to their
+ * canonical equivalents (defaults to {})
+ *
+ * Tests are mostly hardcoded into reflects(), since they depend on the
+ * keywords. All expected values are computed in reflects() using a helper
+ * function.
+ */
+ "enum": {
+ "jsType": "string",
+ "defaultVal": "",
+ "domTests": ["", " " + binaryString + " foo ", undefined, 7, 1.5, true,
+ false, {"test": 6}, NaN, +Infinity, -Infinity, "\0", null,
+ {"toString":function(){return "test-toString";}},
+ {"valueOf":function(){return "test-valueOf";}, toString:null}]
+ },
+ /**
+ * "If a reflecting IDL attribute is a boolean attribute, then on getting
+ * the IDL attribute must return true if the content attribute is set, and
+ * false if it is absent. On setting, the content attribute must be removed
+ * if the IDL attribute is set to false, and must be set to the empty
+ * string if the IDL attribute is set to true. (This corresponds to the
+ * rules for boolean content attributes.)"
+ */
+ "boolean": {
+ "jsType": "boolean",
+ "defaultVal": false,
+ "domTests": ["", " foo ", undefined, null, 7, 1.5, true, false,
+ {"test": 6}, NaN, +Infinity, -Infinity, "\0",
+ {"toString":function(){return "test-toString";}},
+ {"valueOf":function(){return "test-valueOf";}, toString:null}],
+ "domExpected": function(val) {
+ return true;
+ }
+ },
+ /**
+ * "If a reflecting IDL attribute is a signed integer type (long) then, on
+ * getting, the content attribute must be parsed according to the rules for
+ * parsing signed integers, and if that is successful, and the value is in
+ * the range of the IDL attribute's type, the resulting value must be
+ * returned. If, on the other hand, it fails or returns an out of range
+ * value, or if the attribute is absent, then the default value must be
+ * returned instead, or 0 if there is no default value. On setting, the
+ * given value must be converted to the shortest possible string
+ * representing the number as a valid integer and then that string must be
+ * used as the new content attribute value."
+ */
+ "long": {
+ "jsType": "number",
+ "defaultVal": 0,
+ "domTests": [-36, -1, 0, 1, maxInt, minInt, maxInt + 1, minInt - 1,
+ maxUnsigned, maxUnsigned + 1, "", "-1", "-0", "0", "1",
+ " " + binaryString + " foo ",
+ // Test various different whitespace. Only 20, 9, A, C,
+ // and D are whitespace.
+ "\u00097", "\u000B7", "\u000C7", "\u00207", "\u00A07", "\uFEFF7",
+ "\u000A7", "\u000D7", "\u20287", "\u20297", "\u16807", "\u180E7",
+ "\u20007", "\u20017", "\u20027", "\u20037", "\u20047", "\u20057",
+ "\u20067", "\u20077", "\u20087", "\u20097", "\u200A7", "\u202F7",
+ "\u30007",
+ undefined, 1.5, true, false, {"test": 6}, NaN, +Infinity,
+ -Infinity, "\0",
+ {toString:function() {return 2;}, valueOf: null},
+ {valueOf:function() {return 3;}}],
+ "domExpected": function(val) {
+ var parsed = ReflectionTests.parseInt(String(val));
+ if (parsed === false || parsed > maxInt || parsed < minInt) {
+ return null;
+ }
+ return parsed;
+ },
+ "idlTests": [-36, -1, 0, 1, 2147483647, -2147483648],
+ "idlDomExpected": [-36, -1, 0, 1, 2147483647, -2147483648]
+ },
+ /**
+ * "If a reflecting IDL attribute is a signed integer type (long) that is
+ * limited to only non-negative numbers then, on getting, the content
+ * attribute must be parsed according to the rules for parsing non-negative
+ * integers, and if that is successful, and the value is in the range of
+ * the IDL attribute's type, the resulting value must be returned. If, on
+ * the other hand, it fails or returns an out of range value, or if the
+ * attribute is absent, the default value must be returned instead, or −1
+ * if there is no default value. On setting, if the value is negative, the
+ * user agent must fire an INDEX_SIZE_ERR exception. Otherwise, the given
+ * value must be converted to the shortest possible string representing the
+ * number as a valid non-negative integer and then that string must be used
+ * as the new content attribute value."
+ */
+ "limited long": {
+ "jsType": "number",
+ "defaultVal": -1,
+ "domTests": [minInt - 1, minInt, -36, -1, -0, 0, 1, maxInt, maxInt + 1,
+ maxUnsigned, maxUnsigned + 1, "", "-1", "-0", "0", "1",
+ " " + binaryString + " foo ",
+ "\u00097", "\u000B7", "\u000C7", "\u00207", "\u00A07", "\uFEFF7",
+ "\u000A7", "\u000D7", "\u20287", "\u20297", "\u16807", "\u180E7",
+ "\u20007", "\u20017", "\u20027", "\u20037", "\u20047", "\u20057",
+ "\u20067", "\u20077", "\u20087", "\u20097", "\u200A7", "\u202F7",
+ "\u30007",
+ undefined, 1.5, true, false, {"test": 6}, NaN, +Infinity,
+ -Infinity, "\0",
+ {toString:function() {return 2;}, valueOf: null},
+ {valueOf:function() {return 3;}}],
+ "domExpected": function(val) {
+ var parsed = ReflectionTests.parseNonneg(val + "");
+ if (parsed === false || parsed > maxInt || parsed < minInt) {
+ return null;
+ }
+ return parsed;
+ },
+ "idlTests": [minInt, -36, -1, 0, 1, maxInt],
+ "idlDomExpected": [null, null, null, 0, 1, maxInt]
+ },
+ /**
+ * "If a reflecting IDL attribute is an unsigned integer type (unsigned
+ * long) then, on getting, the content attribute must be parsed according
+ * to the rules for parsing non-negative integers, and if that is
+ * successful, and the value is in the range 0 to 2147483647 inclusive, the
+ * resulting value must be returned. If, on the other hand, it fails or
+ * returns an out of range value, or if the attribute is absent, the
+ * default value must be returned instead, or 0 if there is no default
+ * value. On setting, the given value must be converted to the shortest
+ * possible string representing the number as a valid non-negative integer
+ * and then that string must be used as the new content attribute value."
+ */
+ "unsigned long": {
+ "jsType": "number",
+ "defaultVal": 0,
+ "domTests": [minInt - 1, minInt, -36, -1, 0, 1, 257, maxInt,
+ maxInt + 1, maxUnsigned, maxUnsigned + 1, "", "-1", "-0", "0", "1",
+ "\u00097", "\u000B7", "\u000C7", "\u00207", "\u00A07", "\uFEFF7",
+ "\u000A7", "\u000D7", "\u20287", "\u20297", "\u16807", "\u180E7",
+ "\u20007", "\u20017", "\u20027", "\u20037", "\u20047", "\u20057",
+ "\u20067", "\u20077", "\u20087", "\u20097", "\u200A7", "\u202F7",
+ "\u30007",
+ " " + binaryString + " foo ", undefined, 1.5, true, false,
+ {"test": 6}, NaN, +Infinity, -Infinity, "\0",
+ {toString:function() {return 2;}, valueOf: null},
+ {valueOf:function() {return 3;}}],
+ "domExpected": function(val) {
+ var parsed = ReflectionTests.parseNonneg(val + "");
+ // Note maxInt, not maxUnsigned.
+ if (parsed === false || parsed < 0 || parsed > maxInt) {
+ return null;
+ }
+ return parsed;
+ },
+ "idlTests": [0, 1, 257, 2147483647, "-0"],
+ "idlIdlExpected": [0, 1, 257, 2147483647, 0]
+ },
+ /**
+ * "If a reflecting IDL attribute is an unsigned integer type (unsigned
+ * long) that is limited to only non-negative numbers greater than zero,
+ * then the behavior is similar to the previous case, but zero is not
+ * allowed. On getting, the content attribute must first be parsed
+ * according to the rules for parsing non-negative integers, and if that is
+ * successful, and the value is in the range 1 to 2147483647 inclusive, the
+ * resulting value must be returned. If, on the other hand, it fails or
+ * returns an out of range value, or if the attribute is absent, the
+ * default value must be returned instead, or 1 if there is no default
+ * value. On setting, if the value is zero, the user agent must fire an
+ * INDEX_SIZE_ERR exception. Otherwise, the given value must be converted
+ * to the shortest possible string representing the number as a valid
+ * non-negative integer and then that string must be used as the new
+ * content attribute value."
+ */
+ "limited unsigned long": {
+ "jsType": "number",
+ "defaultVal": 1,
+ "domTests": [minInt - 1, minInt, -36, -1, 0, 1, maxInt,
+ maxInt + 1, maxUnsigned, maxUnsigned + 1, "", "-1", "-0", "0", "1",
+ "\u00097", "\u000B7", "\u000C7", "\u00207", "\u00A07", "\uFEFF7",
+ "\u000A7", "\u000D7", "\u20287", "\u20297", "\u16807", "\u180E7",
+ "\u20007", "\u20017", "\u20027", "\u20037", "\u20047", "\u20057",
+ "\u20067", "\u20077", "\u20087", "\u20097", "\u200A7", "\u202F7",
+ "\u30007",
+ " " + binaryString + " foo ", undefined, 1.5, true, false,
+ {"test": 6}, NaN, +Infinity, -Infinity, "\0",
+ {toString:function() {return 2;}, valueOf: null},
+ {valueOf:function() {return 3;}}],
+ "domExpected": function(val) {
+ var parsed = ReflectionTests.parseNonneg(val + "");
+ // Note maxInt, not maxUnsigned.
+ if (parsed === false || parsed < 1 || parsed > maxInt) {
+ return null;
+ }
+ return parsed;
+ },
+ "idlTests": [0, 1, 2147483647],
+ "idlDomExpected": [null, 1, 2147483647]
+ },
+ /**
+ * "If a reflecting IDL attribute is a floating point number type (double),
+ * then, on getting, the content attribute must be parsed according to the
+ * rules for parsing floating point number values, and if that is
+ * successful, the resulting value must be returned. If, on the other hand,
+ * it fails, or if the attribute is absent, the default value must be
+ * returned instead, or 0.0 if there is no default value. On setting, the
+ * given value must be converted to the best representation of the number
+ * as a floating point number and then that string must be used as the new
+ * content attribute value."
+ *
+ * TODO: Check this:
+ *
+ * "Except where otherwise specified, if an IDL attribute that is a
+ * floating point number type (double) is assigned an Infinity or
+ * Not-a-Number (NaN) value, a NOT_SUPPORTED_ERR exception must be raised."
+ *
+ * TODO: Implement the actual algorithm so we can run lots more tests. For
+ * now we're stuck with manually setting up expected values. Of course,
+ * a lot of care has to be taken in checking equality for floats . . .
+ * maybe we should have some tolerance for comparing them. I'm not even
+ * sure whether setting the content attribute to 0 should return 0.0 or
+ * -0.0 (the former, I hope).
+ */
+ "double": {
+ "jsType": "number",
+ "defaultVal": 0.0,
+ "domTests": [minInt - 1, minInt, -36, -1, 0, 1, maxInt,
+ maxInt + 1, maxUnsigned, maxUnsigned + 1, "",
+ "\u00097", "\u000B7", "\u000C7", "\u00207", "\u00A07", "\uFEFF7",
+ "\u000A7", "\u000D7", "\u20287", "\u20297", "\u16807", "\u180E7",
+ "\u20007", "\u20017", "\u20027", "\u20037", "\u20047", "\u20057",
+ "\u20067", "\u20077", "\u20087", "\u20097", "\u200A7", "\u202F7",
+ "\u30007",
+ " " + binaryString + " foo ", undefined, 1.5, true, false,
+ {"test": 6}, NaN, +Infinity, -Infinity, "\0",
+ {toString:function() {return 2;}, valueOf: null},
+ {valueOf:function() {return 3;}}],
+ "domExpected": [minInt - 1, minInt, -36, -1, 0, 1, maxInt,
+ maxInt + 1, maxUnsigned, maxUnsigned + 1, null,
+ // Leading whitespace tests
+ 7, null, 7, 7, null, null,
+ 7, 7, null, null, null, null,
+ null, null, null, null, null, null,
+ null, null, null, null, null, null,
+ null,
+ // End leading whitespace tests
+ null, null, 1.5, null, null,
+ null, null, null, null, null,
+ 2, 3],
+ // I checked that ES ToString is well-defined for all of these (I
+ // think). Yes, String(-0) == "0".
+ "idlTests": [ -10000000000, -1, -0, 0, 1, 10000000000],
+ "idlDomExpected": ["-10000000000", "-1", "0", "0", "1", "10000000000"],
+ "idlIdlExpected": [ -10000000000, -1, -0, 0, 1, 10000000000]
+ }
+};
+
+for (var type in ReflectionTests.typeMap) {
+ var props = ReflectionTests.typeMap[type];
+ var cast = window[props.jsType[0].toUpperCase() + props.jsType.slice(1)];
+ if (props.domExpected === undefined) {
+ props.domExpected = props.domTests.map(cast);
+ } else if (typeof props.domExpected == "function") {
+ props.domExpected = props.domTests.map(props.domExpected);
+ }
+ if (props.idlTests === undefined) {
+ props.idlTests = props.domTests;
+ }
+ if (props.idlDomExpected === undefined) {
+ props.idlDomExpected = props.idlTests.map(cast);
+ } else if (typeof props.idlDomExpected == "function") {
+ props.idlDomExpected = props.idlTests.map(props.idlDomExpected);
+ }
+ if (props.idlIdlExpected === undefined) {
+ props.idlIdlExpected = props.idlDomExpected;
+ } else if (typeof props.idlIdlExpected == "function") {
+ props.idlIdlExpected = props.idlTests.map(props.idlIdlExpected);
+ }
+}
+
+/**
+ * Tests that the JavaScript attribute named idlName on the object idlObj
+ * reflects the DOM attribute named domName on domObj. The data argument is an
+ * object that must contain at least one key, "type", which contains the
+ * expected type of the IDL attribute ("string", "enum", etc.). The "comment"
+ * key will add a parenthesized comment in the type info if there's a test
+ * failure, to indicate that there's something special about the element you're
+ * testing (like it has an attribute set to some value). Other keys in the
+ * data object are type-specific, e.g., "defaultVal" for numeric types. If the
+ * data object is a string, it's converted to {"type": data}. If idlObj is a
+ * string, we set idlObj = domObj = document.createElement(idlObj).
+ */
+ReflectionTests.reflects = function(data, idlName, idlObj, domName, domObj) {
+ // Do some setup first so that getTypeDescription() works in testWrapper()
+ if (typeof data == "string") {
+ data = {type: data};
+ }
+ if (domName === undefined) {
+ domName = idlName;
+ }
+ if (typeof idlObj == "string") {
+ idlObj = document.createElement(idlObj);
+ }
+ if (domObj === undefined) {
+ domObj = idlObj;
+ }
+
+ // Note: probably a hack? This kind of assumes that the variables here
+ // won't change over the course of the tests, which is wrong, but it's
+ // probably safe enough. Just don't read stuff that will change.
+ ReflectionHarness.currentTestInfo = {data: data, idlName: idlName, idlObj: idlObj, domName: domName, domObj: domObj};
+
+ ReflectionHarness.testWrapper(function() {
+ ReflectionTests.doReflects(data, idlName, idlObj, domName, domObj);
+ });
+};
+
+/**
+ * Actual implementation of the above.
+ */
+ReflectionTests.doReflects = function(data, idlName, idlObj, domName, domObj) {
+ // If we don't recognize the type, testing is impossible.
+ if (this.typeMap[data.type] === undefined) {
+ if (unimplemented.indexOf(data.type) == -1) {
+ unimplemented.push(data.type);
+ }
+ return;
+ }
+
+ var typeInfo = this.typeMap[data.type];
+
+ // Test that typeof idlObj[idlName] is correct. If not, further tests are
+ // probably pointless, so bail out.
+ if (!ReflectionHarness.test(typeof idlObj[idlName], typeInfo.jsType, "typeof IDL attribute")) {
+ return;
+ }
+
+ // Test default
+ var defaultVal = data.defaultVal;
+ if (defaultVal === undefined) {
+ defaultVal = typeInfo.defaultVal;
+ }
+ if (defaultVal !== null) {
+ ReflectionHarness.test(idlObj[idlName], defaultVal, "IDL get with DOM attribute unset");
+ }
+
+ var domTests = typeInfo.domTests.slice(0);
+ var domExpected = typeInfo.domExpected.map(function(val) { return val === null ? defaultVal : val; });
+ var idlTests = typeInfo.idlTests.slice(0);
+ var idlDomExpected = typeInfo.idlDomExpected.slice(0);
+ var idlIdlExpected = typeInfo.idlIdlExpected.slice(0);
+ switch (data.type) {
+ // Extra tests and other special-casing
+ case "boolean":
+ domTests.push(domName);
+ domExpected.push(true);
+ break;
+
+ case "enum":
+ // Whee, enum is complicated.
+ if (typeof data.invalidVal == "undefined") {
+ data.invalidVal = defaultVal;
+ }
+ if (typeof data.nonCanon == "undefined") {
+ data.nonCanon = {};
+ }
+ for (var i = 0; i < data.keywords.length; i++) {
+ if (data.keywords[i] != "") {
+ domTests.push(data.keywords[i], "x" + data.keywords[i], data.keywords[i] + "\0");
+ idlTests.push(data.keywords[i], "x" + data.keywords[i], data.keywords[i] + "\0");
+ }
+
+ if (data.keywords[i].length > 1) {
+ domTests.push(data.keywords[i].slice(1));
+ idlTests.push(data.keywords[i].slice(1));
+ }
+
+ if (data.keywords[i] != data.keywords[i].toLowerCase()) {
+ domTests.push(data.keywords[i].toLowerCase());
+ idlTests.push(data.keywords[i].toLowerCase());
+ }
+ if (data.keywords[i] != data.keywords[i].toUpperCase()) {
+ domTests.push(data.keywords[i].toUpperCase());
+ idlTests.push(data.keywords[i].toUpperCase());
+ }
+ }
+
+ // Per spec, the expected DOM values are the same as the value we set
+ // it to.
+ idlDomExpected = idlTests.slice(0);
+
+ // Now we have the fun of calculating what the expected IDL values are.
+ domExpected = [];
+ idlIdlExpected = [];
+ for (var i = 0; i < domTests.length; i++) {
+ domExpected.push(this.enumExpected(data.keywords, data.nonCanon, data.invalidVal, domTests[i]));
+ }
+ for (var i = 0; i < idlTests.length; i++) {
+ idlIdlExpected.push(this.enumExpected(data.keywords, data.nonCanon, data.invalidVal, idlTests[i]));
+ }
+ break;
+
+ case "string":
+ if ("treatNullAsEmptyString" in data) {
+ for (var i = 0; i < idlTests.length; i++) {
+ if (idlTests[i] === null) {
+ idlDomExpected[i] = idlIdlExpected[i] = "";
+ }
+ }
+ }
+ break;
+ }
+ if (domObj.tagName.toLowerCase() == "canvas" && (domName == "width" || domName == "height")) {
+ // Opera tries to allocate a canvas with the given width and height, so
+ // it OOMs when given excessive sizes. This is permissible under the
+ // hardware-limitations clause, so cut out those checks. TODO: Must be
+ // a way to make this more succinct.
+ domTests = domTests.filter(function(element, index, array) { return domExpected[index] < 1000; });
+ domExpected = domExpected.filter(function(element, index, array) { return element < 1000; });
+ idlTests = idlTests.filter(function(element, index, array) { return idlIdlExpected[index] < 1000; });
+ idlDomExpected = idlDomExpected.filter(function(element, index, array) { return idlIdlExpected[index] < 1000; });
+ idlIdlExpected = idlIdlExpected.filter(function(element, index, array) { return idlIdlExpected[index] < 1000; });
+ }
+
+ if (!data.customGetter) {
+ for (var i = 0; i < domTests.length; i++) {
+ if (domExpected[i] === null) {
+ // If you follow all the complicated logic here, you'll find that
+ // this will only happen if there's no expected value at all (like
+ // for tabIndex, where the default is too complicated). So skip
+ // the test.
+ continue;
+ }
+ try {
+ domObj.setAttribute(domName, domTests[i]);
+ ReflectionHarness.test(domObj.getAttribute(domName), domTests[i] + "", "setAttribute() to " + ReflectionHarness.stringRep(domTests[i]) + " followed by getAttribute()");
+ ReflectionHarness.test(idlObj[idlName], domExpected[i], "setAttribute() to " + ReflectionHarness.stringRep(domTests[i]) + " followed by IDL get");
+ if (ReflectionHarness.catchUnexpectedExceptions) {
+ ReflectionHarness.success();
+ }
+ } catch (err) {
+ if (ReflectionHarness.catchUnexpectedExceptions) {
+ ReflectionHarness.failure("Exception thrown during tests with setAttribute() to " + ReflectionHarness.stringRep(domTests[i]));
+ } else {
+ throw err;
+ }
+ }
+ }
+ }
+
+ for (var i = 0; i < idlTests.length; i++) {
+ if (idlDomExpected[i] === null && data.type != "enum") {
+ ReflectionHarness.testException("INDEX_SIZE_ERR", function() {
+ idlObj[idlName] = idlTests[i];
+ }, "IDL set to " + ReflectionHarness.stringRep(idlTests[i]) + " must throw INDEX_SIZE_ERR");
+ } else {
+ ReflectionHarness.run(function() {
+ idlObj[idlName] = idlTests[i];
+ if (data.type == "boolean") {
+ // Special case yay
+ ReflectionHarness.test(domObj.hasAttribute(domName), Boolean(idlTests[i]), "IDL set to " + ReflectionHarness.stringRep(idlTests[i]) + " followed by hasAttribute()");
+ } else if (idlDomExpected[i] !== null) {
+ ReflectionHarness.test(domObj.getAttribute(domName), idlDomExpected[i] + "", "IDL set to " + ReflectionHarness.stringRep(idlTests[i]) + " followed by getAttribute()");
+ }
+ if (idlIdlExpected[i] !== null) {
+ ReflectionHarness.test(idlObj[idlName], idlIdlExpected[i], "IDL set to " + ReflectionHarness.stringRep(idlTests[i]) + " followed by IDL get");
+ }
+ if (ReflectionHarness.catchUnexpectedExceptions) {
+ ReflectionHarness.success();
+ }
+ }, "IDL set to " + ReflectionHarness.stringRep(idlTests[i]) + " should not throw");
+ }
+ }
+};
+
+/**
+ * If we have an enumerated attribute limited to the array of values in
+ * keywords, with nonCanon being a map of non-canonical values to their
+ * canonical equivalents, and invalidVal being the invalid value default (or ""
+ * for none), then what would we expect from an IDL get if the content
+ * attribute is equal to contentVal?
+ */
+ReflectionTests.enumExpected = function(keywords, nonCanon, invalidVal, contentVal) {
+ var ret = invalidVal;
+ for (var i = 0; i < keywords.length; i++) {
+ if (String(contentVal).toLowerCase() == keywords[i].toLowerCase()) {
+ ret = keywords[i];
+ break;
+ }
+ }
+ if (typeof nonCanon[ret] != "undefined") {
+ return nonCanon[ret];
+ }
+ return ret;
+};
+
+/**
+ * Now we have the data structures that tell us which elements have which
+ * attributes.
+ *
+ * The elements object (which must have been defined in earlier files) is a map
+ * from element name to an object whose keys are IDL attribute names and whose
+ * values are types. A type is of the same format as
+ * ReflectionTests.reflects() accepts, except that there's an extra optional
+ * domAttrName key that gets passed as the fourth argument to reflects() if
+ * it's provided. (TODO: drop the fourth and fifth reflects() arguments and
+ * make it take them from the dictionary instead?)
+ */
+
+// Now we actually run all the tests.
+var unimplemented = [];
+for (var element in elements) {
+ ReflectionTests.reflects("string", "title", element);
+ ReflectionTests.reflects("string", "lang", element);
+ ReflectionTests.reflects({type: "enum", keywords: ["ltr", "rtl", "auto"]}, "dir", element);
+ ReflectionTests.reflects("string", "className", element, "class");
+ ReflectionTests.reflects("tokenlist", "classList", element, "class");
+ ReflectionTests.reflects("boolean", "hidden", element);
+ ReflectionTests.reflects("string", "accessKey", element);
+ // Don't try to test the defaultVal -- it should be either 0 or -1, but the
+ // rules are complicated, and a lot of them are SHOULDs.
+ ReflectionTests.reflects({type: "long", defaultVal: null}, "tabIndex", element);
+ // TODO: classList, contextMenu, itemProp, itemRef, dropzone (require
+ // tokenlist support)
+
+ for (var idlAttrName in elements[element]) {
+ var type = elements[element][idlAttrName];
+ ReflectionTests.reflects(type, idlAttrName, element,
+ typeof type == "object" && "domAttrName" in type ? type.domAttrName : idlAttrName);
+ }
+}
+
+for (var i = 0; i < extraTests.length; i++) {
+ extraTests[i]();
+}
+
+var time = document.getElementById("time");
+if (time) {
+ time.innerHTML = (new Date().getTime() - ReflectionTests.start)/1000;
+}
+
+if (unimplemented.length) {
+ var p = document.createElement("p");
+ p.textContent = "(Note: missing tests for types " + unimplemented.join(", ") + ".)";
+ document.body.appendChild(p);
+}
diff --git a/tests/wpt/web-platform-tests/html/editing/.gitkeep b/tests/wpt/web-platform-tests/html/editing/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/editing/activation/.gitkeep b/tests/wpt/web-platform-tests/html/editing/activation/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/activation/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/editing/assigning-keyboard-shortcuts/.gitkeep b/tests/wpt/web-platform-tests/html/editing/assigning-keyboard-shortcuts/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/assigning-keyboard-shortcuts/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/editing/assigning-keyboard-shortcuts/introduction-6/.gitkeep b/tests/wpt/web-platform-tests/html/editing/assigning-keyboard-shortcuts/introduction-6/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/assigning-keyboard-shortcuts/introduction-6/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/editing/assigning-keyboard-shortcuts/processing-model-4/.gitkeep b/tests/wpt/web-platform-tests/html/editing/assigning-keyboard-shortcuts/processing-model-4/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/assigning-keyboard-shortcuts/processing-model-4/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/editing/assigning-keyboard-shortcuts/the-accesskey-attribute/.gitkeep b/tests/wpt/web-platform-tests/html/editing/assigning-keyboard-shortcuts/the-accesskey-attribute/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/assigning-keyboard-shortcuts/the-accesskey-attribute/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/README b/tests/wpt/web-platform-tests/html/editing/dnd/README
new file mode 100644
index 00000000000..aeda217e294
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/README
@@ -0,0 +1,23 @@
+This is a test suite for the drag and drop API described in the HTML5
+specification:
+
+ http://dev.w3.org/html5/spec/dnd.html#dnd
+
+Tests in target-origin/ relate to a proposed spec extension and are not covered
+by HTML5 drafts at the time of writing. Contact Opera Sofware for details, and
+mention CT-1656.
+
+Tests in synthetic/ relate to incomplete parts of the HTML5 specification,
+which allows synthetic events to be created. For compatibility with others,
+the dataTransfer parameter allows null, undefined and other objects. Objects
+will create a synthetic dataTransfer. To provide maximum functionality,
+synthetic dataTransfer will have its own synthetic data store, detatched from
+the real data store used by real drag events (actual user interaction). For
+security, real dataTransfer objects will remember the real event's protection
+status inside synthetic events (the spec bases their protection only on the
+event type, and does not consider the difference between real and synthetic
+events).
+
+Tests in platform/plugin are based on assumed "good" behaviour, where the
+appropriate events are passed to the plugin. Platforms should determine if any
+deviations from the expected results are problematic. \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/canvas/001.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/canvas/001.xhtml
new file mode 100644
index 00000000000..fbb45211749
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/canvas/001.xhtml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Canvas drag and drop carrying image as dataURL</title>
+<style type="text/css">
+div[ondragenter]
+ {width:105px;
+ min-height:105px;
+ text-align:center;
+ margin-top:20px;
+ padding:10px;
+ border:solid thin navy;}
+p:first-child
+ {padding-left:12px;}
+</style>
+<script type="application/ecmascript">
+function addImage(event)
+ {var c = document.createElement('img');
+ c.setAttribute('src',event.dataTransfer.getData('text/uri-list'));
+ document.querySelector('div').appendChild(c);}
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ event.dataTransfer.setData('text/uri-list', document.querySelector('canvas').toDataURL('image/png'));}
+</script>
+</head>
+<body>
+<p>
+ <canvas width="100" height="100" draggable="true" ondragstart="start(event)">Canvas</canvas>
+</p>
+<p>Drag canvas pattern above to the box below. It should be copied to the box once you drop it there.</p>
+<div
+ ondragenter="event.preventDefault()"
+ ondragover="return false"
+ ondrop="addImage(event)"
+/>
+<script type="application/ecmascript">
+var canvas = document.querySelector('canvas'),
+c = canvas.getContext('2d');
+for(var x = 0; x != 50; x++)
+ {c.fillStyle = (x%2 == 0)?'navy':'white';
+ c.beginPath();
+ c.moveTo(x,x);
+ c.lineTo(100-x,x);
+ c.lineTo(100-x,100-x);
+ c.lineTo(x,100-x);
+ c.closePath();
+ c.fill();}
+</script>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/canvas/002.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/canvas/002.xhtml
new file mode 100644
index 00000000000..9cd8eed0696
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/canvas/002.xhtml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop: dropping block element onto canvas</title>
+<style type="text/css">
+div
+ {width:20px;
+ height:20px;
+ background-color:green;}
+</style>
+<script type="application/ecmascript">
+function paint(color)
+ {var canvas = document.querySelector('canvas'),
+ c = canvas.getContext('2d');
+ c.fillStyle = color;
+ c.beginPath();
+ c.moveTo(0,0);
+ c.lineTo(100,0);
+ c.lineTo(100,100);
+ c.lineTo(0,100);
+ c.closePath();
+ c.fill();}
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ event.dataTransfer.setData('text/plain', 'green');}
+</script>
+</head>
+<body onload="paint('gray')">
+<div draggable="true" ondragstart="start(event)"/>
+<p>Drag green box above to the gray canvas below. Canvas should turn green when you drop green box on it.</p>
+<p>
+ <canvas width="100" height="100" ondragenter="event.preventDefault()" ondragover="return false" ondrop="paint(event.dataTransfer.getData('text/plain'))">Canvas</canvas>
+</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/canvas/003-1.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/canvas/003-1.xhtml
new file mode 100644
index 00000000000..fe1e4ab30de
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/canvas/003-1.xhtml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Canvas drag and drop: helper file</title>
+<style type="text/css">
+div
+ {width:20px;
+ height:20px;
+ background-color:green;}
+</style>
+<script type="application/ecmascript">
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ event.dataTransfer.setData('text/plain', 'green');}
+</script>
+</head>
+<body>
+<div draggable="true" ondragstart="start(event)"/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/canvas/003.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/canvas/003.xhtml
new file mode 100644
index 00000000000..fa98ebe8dc8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/canvas/003.xhtml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop from iframe: dropping block element onto canvas</title>
+<style type="text/css">
+iframe
+ {width:150px;
+ height:150px;
+ border-style:none;}
+</style>
+<script type="application/ecmascript">
+function paint(color)
+ {var canvas = document.querySelector('canvas'),
+ c = canvas.getContext('2d');
+ c.fillStyle = color;
+ c.beginPath();
+ c.moveTo(0,0);
+ c.lineTo(100,0);
+ c.lineTo(100,100);
+ c.lineTo(0,100);
+ c.closePath();
+ c.fill();}
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ event.dataTransfer.setData('text/plain', 'green');}
+</script>
+</head>
+<body onload="paint('gray')">
+<p><iframe src="003-1.xhtml">Green box</iframe></p>
+<p>Drag green box above to the gray canvas below. Canvas should turn green when you drop green box on it.</p>
+<p>
+ <canvas width="100" height="100" ondragenter="event.preventDefault()" ondragover="return false" ondrop="paint(event.dataTransfer.getData('text/plain'))">Canvas</canvas>
+</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/canvas/004.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/canvas/004.xhtml
new file mode 100644
index 00000000000..d1c2ef06e81
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/canvas/004.xhtml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop from object: dropping block element onto canvas</title>
+<style type="text/css">
+object
+ {width:150px;
+ height:150px;
+ border-style:none;}
+</style>
+<script type="application/ecmascript">
+function paint(color)
+ {var canvas = document.querySelector('canvas'),
+ c = canvas.getContext('2d');
+ c.fillStyle = color;
+ c.beginPath();
+ c.moveTo(0,0);
+ c.lineTo(100,0);
+ c.lineTo(100,100);
+ c.lineTo(0,100);
+ c.closePath();
+ c.fill();}
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ event.dataTransfer.setData('text/plain', 'green');}
+</script>
+</head>
+<body onload="paint('gray')">
+<p><object type="application/xhtml+xml" data="data:application/xhtml+xml,%3Chtml%20xmlns%3D%22http%3A//www.w3.org/1999/xhtml%22%3E%3Chead%3E%3Ctitle%3ECanvas%20drag%20and%20drop%3C/title%3E%3Cstyle%20type%3D%22text/css%22%3Ediv%7Bwidth%3A20px%3Bheight%3A20px%3Bbackground-color%3Agreen%3B%7D%3C/style%3E%3Cscript%20type%3D%22application/ecmascript%22%3Efunction%20start%28event%29%7Bevent.dataTransfer.effectAllowed%20%3D%20%27copy%27%3Bevent.dataTransfer.setData%28%27text/plain%27%2C%20%27green%27%29%3B%7D%3C/script%3E%3C/head%3E%3Cbody%3E%3Cdiv%20draggable%3D%22true%22%20ondragstart%3D%22start%28event%29%22/%3E%3C/body%3E%3C/html%3E">Green box</object></p>
+<p>Drag green box above to the gray canvas below. Canvas should turn green when you drop green box on it.</p>
+<p>
+ <canvas width="100" height="100" ondragenter="event.preventDefault()" ondragover="return false" ondrop="paint(event.dataTransfer.getData('text/plain'))">Canvas</canvas>
+</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/canvas/005.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/canvas/005.xhtml
new file mode 100644
index 00000000000..fd9c9389e5b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/canvas/005.xhtml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop to iframe: dropping block element onto canvas</title>
+<style type="text/css">
+div
+ {width:20px;
+ height:20px;
+ background-color:green;}
+iframe
+ {width:200px;
+ height:200px;
+ border-style:none;}
+</style>
+<script type="application/ecmascript">
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ event.dataTransfer.setData('text/plain', 'green');}
+</script>
+</head>
+<body>
+<div draggable="true" ondragstart="start(event)"/>
+<p>Drag green box above to the gray canvas below. Canvas should turn green when you drop green box on it.</p>
+<p><iframe src="helper-drop-here-canvas.xhtml">Canvas</iframe></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/canvas/006.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/canvas/006.xhtml
new file mode 100644
index 00000000000..003df8f06fa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/canvas/006.xhtml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop to object: dropping block element onto canvas</title>
+<style type="text/css">
+div
+ {width:20px;
+ height:20px;
+ background-color:green;}
+object
+ {width:200px;
+ height:200px;}
+</style>
+<script type="application/ecmascript">
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ event.dataTransfer.setData('text/plain', 'green');}
+</script>
+</head>
+<body>
+<div draggable="true" ondragstart="start(event)"/>
+<p>Drag green box above to the gray canvas below. Canvas should turn green when you drop green box on it.</p>
+<p><object type="application/xhtml+xml" data="data:application/xhtml+xml,%3Chtml%20xmlns%3D%22http%3A//www.w3.org/1999/xhtml%22%3E%3Chead%3E%3Ctitle%3ECanvas%20drag%20and%20drop%3C/title%3E%3Cscript%20type%3D%22application/ecmascript%22%3Efunction%20paint%28color%29%7Bvar%20canvas%20%3D%20document.querySelector%28%27canvas%27%29%2Cc%20%3D%20canvas.getContext%28%272d%27%29%3Bc.fillStyle%20%3D%20color%3Bc.beginPath%28%29%3Bc.moveTo%280%2C0%29%3Bc.lineTo%28100%2C0%29%3Bc.lineTo%28100%2C100%29%3Bc.lineTo%280%2C100%29%3Bc.closePath%28%29%3Bc.fill%28%29%3B%7Dfunction%20start%28event%29%7Bevent.dataTransfer.effectAllowed%20%3D%20%27copy%27%3Bevent.dataTransfer.setData%28%27text/plain%27%2C%20document.querySelector%28%27input%27%29.value%29%3B%7D%3C/script%3E%3C/head%3E%3Cbody%20onload%3D%22paint%28%27gray%27%29%22%3E%3Cp%3E%3Ccanvas%20width%3D%22100%22%20height%3D%22100%22%20ondragenter%3D%22event.preventDefault%28%29%22%20ondragover%3D%22return%20false%22%20ondrop%3D%22paint%28event.dataTransfer.getData%28%27text/plain%27%29%29%22%3ECanvas%3C/canvas%3E%3C/p%3E%3C/body%3E%3C/html%3E">Canvas</object></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/canvas/007.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/canvas/007.xhtml
new file mode 100644
index 00000000000..8ee869f0b4a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/canvas/007.xhtml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop between iframes: dropping block element onto canvas</title>
+<style type="text/css">
+iframe
+ {width:300px;
+ height:200px;
+ border-style:none;}
+</style>
+</head>
+<body>
+<p><iframe src="helper-drag-me-green-box.xhtml">Green box</iframe></p>
+<p>Drag green box above to the gray canvas below. Canvas should turn green when you drop green box on it.</p>
+<p><iframe src="helper-drop-here-canvas.xhtml">Canvas</iframe></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/canvas/008.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/canvas/008.xhtml
new file mode 100644
index 00000000000..d3f21acd728
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/canvas/008.xhtml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop from iframe to object: dropping block element onto canvas</title>
+<style type="text/css">
+iframe, object
+ {width:300px;
+ height:200px;
+ border-style:none;}
+</style>
+</head>
+<body>
+<p><iframe src="helper-drag-me-green-box.xhtml">Green box</iframe></p>
+<p>Drag green box above to the gray canvas below. Canvas should turn green when you drop green box on it.</p>
+<p><object type="application/xhtml+xml" data="data:application/xhtml+xml,%3Chtml%20xmlns%3D%22http%3A//www.w3.org/1999/xhtml%22%3E%3Chead%3E%3Ctitle%3ECanvas%20drag%20and%20drop%3C/title%3E%3Cscript%20type%3D%22application/ecmascript%22%3Efunction%20paint%28color%29%7Bvar%20canvas%20%3D%20document.querySelector%28%27canvas%27%29%2Cc%20%3D%20canvas.getContext%28%272d%27%29%3Bc.fillStyle%20%3D%20color%3Bc.beginPath%28%29%3Bc.moveTo%280%2C0%29%3Bc.lineTo%28100%2C0%29%3Bc.lineTo%28100%2C100%29%3Bc.lineTo%280%2C100%29%3Bc.closePath%28%29%3Bc.fill%28%29%3B%7Dfunction%20start%28event%29%7Bevent.dataTransfer.effectAllowed%20%3D%20%27copy%27%3Bevent.dataTransfer.setData%28%27text/plain%27%2C%20document.querySelector%28%27input%27%29.value%29%3B%7D%3C/script%3E%3C/head%3E%3Cbody%20onload%3D%22paint%28%27gray%27%29%22%3E%3Cp%3E%3Ccanvas%20width%3D%22100%22%20height%3D%22100%22%20ondragenter%3D%22event.preventDefault%28%29%22%20ondragover%3D%22return%20false%22%20ondrop%3D%22paint%28event.dataTransfer.getData%28%27text/plain%27%29%29%22%3ECanvas%3C/canvas%3E%3C/p%3E%3C/body%3E%3C/html%3E">Canvas</object></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/canvas/009.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/canvas/009.xhtml
new file mode 100644
index 00000000000..9f73037bb0a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/canvas/009.xhtml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop between objects: dropping block element onto canvas</title>
+<style type="text/css">
+object
+ {width:300px;
+ height:200px;}
+</style>
+</head>
+<body>
+<p><object type="application/xhtml+xml" data="data:application/xhtml+xml,%3Chtml%20xmlns%3D%22http%3A//www.w3.org/1999/xhtml%22%3E%3Chead%3E%3Ctitle%3ECanvas%20drag%20and%20drop%3C/title%3E%3Cstyle%20type%3D%22text/css%22%3Ediv%7Bwidth%3A20px%3Bheight%3A20px%3Bbackground-color%3Agreen%3B%7D%3C/style%3E%3Cscript%20type%3D%22application/ecmascript%22%3Efunction%20start%28event%29%7Bevent.dataTransfer.effectAllowed%20%3D%20%27copy%27%3Bevent.dataTransfer.setData%28%27text/plain%27%2C%20%27green%27%29%3B%7D%3C/script%3E%3C/head%3E%3Cbody%3E%3Cdiv%20draggable%3D%22true%22%20ondragstart%3D%22start%28event%29%22/%3E%3C/body%3E%3C/html%3E">Green box</object></p>
+<p>Drag green box above to the gray canvas below. Canvas should turn green when you drop green box on it.</p>
+<p><object type="application/xhtml+xml" data="data:application/xhtml+xml,%3Chtml%20xmlns%3D%22http%3A//www.w3.org/1999/xhtml%22%3E%3Chead%3E%3Ctitle%3ECanvas%20drag%20and%20drop%3C/title%3E%3Cscript%20type%3D%22application/ecmascript%22%3Efunction%20paint%28color%29%7Bvar%20canvas%20%3D%20document.querySelector%28%27canvas%27%29%2Cc%20%3D%20canvas.getContext%28%272d%27%29%3Bc.fillStyle%20%3D%20color%3Bc.beginPath%28%29%3Bc.moveTo%280%2C0%29%3Bc.lineTo%28100%2C0%29%3Bc.lineTo%28100%2C100%29%3Bc.lineTo%280%2C100%29%3Bc.closePath%28%29%3Bc.fill%28%29%3B%7Dfunction%20start%28event%29%7Bevent.dataTransfer.effectAllowed%20%3D%20%27copy%27%3Bevent.dataTransfer.setData%28%27text/plain%27%2C%20document.querySelector%28%27input%27%29.value%29%3B%7D%3C/script%3E%3C/head%3E%3Cbody%20onload%3D%22paint%28%27gray%27%29%22%3E%3Cp%3E%3Ccanvas%20width%3D%22100%22%20height%3D%22100%22%20ondragenter%3D%22event.preventDefault%28%29%22%20ondragover%3D%22return%20false%22%20ondrop%3D%22paint%28event.dataTransfer.getData%28%27text/plain%27%29%29%22%3ECanvas%3C/canvas%3E%3C/p%3E%3C/body%3E%3C/html%3E">Canvas</object></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/canvas/010-1.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/canvas/010-1.xhtml
new file mode 100644
index 00000000000..0f12e6fcd0f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/canvas/010-1.xhtml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Canvas drag and drop: helper file</title>
+<style type="text/css">
+div
+ {width:20px;
+ height:20px;
+ background-color:green;}
+</style>
+<script type="application/ecmascript">
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ event.dataTransfer.setData('text/plain', 'green');}
+</script>
+</head>
+<body>
+<div draggable="true" ondragstart="start(event)"/>
+<p>Drag green box above to the gray canvas below. Canvas should turn green when you drop green box on it.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/canvas/010.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/canvas/010.xhtml
new file mode 100644
index 00000000000..0b24a3082fe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/canvas/010.xhtml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop between frames: dropping block element onto canvas</title>
+</head>
+<frameset rows="50%, 50%">
+<frame src="010-1.xhtml"/>
+<frame src="helper-drop-here-canvas.xhtml"/>
+</frameset>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/canvas/011.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/canvas/011.xhtml
new file mode 100644
index 00000000000..40da4e9677b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/canvas/011.xhtml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop between dataURL frames: dropping block element onto canvas</title>
+</head>
+<frameset rows="50%, 50%">
+<frame src="data:application/xhtml+xml,%3Chtml%20xmlns%3D%22http%3A//www.w3.org/1999/xhtml%22%3E%3Chead%3E%3Ctitle%3ECanvas%20drag%20and%20drop%3C/title%3E%3Cstyle%20type%3D%22text/css%22%3Ediv%7Bwidth%3A20px%3Bheight%3A20px%3Bbackground-color%3Agreen%3B%7D%3C/style%3E%3Cscript%20type%3D%22application/ecmascript%22%3Efunction%20start%28event%29%7Bevent.dataTransfer.effectAllowed%20%3D%20%27copy%27%3Bevent.dataTransfer.setData%28%27text/plain%27%2C%20%27green%27%29%3B%7D%3C/script%3E%3C/head%3E%3Cbody%3E%3Cdiv%20draggable%3D%22true%22%20ondragstart%3D%22start%28event%29%22/%3E%3Cp%3EDrag%20green%20box%20above%20to%20the%20gray%20canvas%20below.%20Canvas%20should%20turn%20green%20when%20you%20drop%20green%20box%20on%20it.%3C/p%3E%3C/body%3E%3C/html%3E"/>
+<frame src="data:application/xhtml+xml,%3Chtml%20xmlns%3D%22http%3A//www.w3.org/1999/xhtml%22%3E%3Chead%3E%3Ctitle%3ECanvas%20drag%20and%20drop%3C/title%3E%3Cscript%20type%3D%22application/ecmascript%22%3Efunction%20paint%28color%29%7Bvar%20canvas%20%3D%20document.querySelector%28%27canvas%27%29%2Cc%20%3D%20canvas.getContext%28%272d%27%29%3Bc.fillStyle%20%3D%20color%3Bc.beginPath%28%29%3Bc.moveTo%280%2C0%29%3Bc.lineTo%28100%2C0%29%3Bc.lineTo%28100%2C100%29%3Bc.lineTo%280%2C100%29%3Bc.closePath%28%29%3Bc.fill%28%29%3B%7Dfunction%20start%28event%29%7Bevent.dataTransfer.effectAllowed%20%3D%20%27copy%27%3Bevent.dataTransfer.setData%28%27text/plain%27%2C%20document.querySelector%28%27input%27%29.value%29%3B%7D%3C/script%3E%3C/head%3E%3Cbody%20onload%3D%22paint%28%27gray%27%29%22%3E%3Cp%3E%3Ccanvas%20width%3D%22100%22%20height%3D%22100%22%20ondragenter%3D%22event.preventDefault%28%29%22%20ondragover%3D%22return%20false%22%20ondrop%3D%22paint%28event.dataTransfer.getData%28%27text/plain%27%29%29%22%3ECanvas%3C/canvas%3E%3C/p%3E%3C/body%3E%3C/html%3E"/>
+</frameset>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/canvas/012.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/canvas/012.xhtml
new file mode 100644
index 00000000000..d2069142c80
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/canvas/012.xhtml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop and vertical scrolling: dropping block element onto canvas inside scrollable container</title>
+<style type="text/css">
+div[draggable]
+ {width:20px;
+ height:20px;
+ background-color:green;}
+p + div
+ {height:100px;
+ width:150px;
+ overflow-y:scroll;}
+canvas
+ {display:block;
+ margin-top:100px;}
+</style>
+<script type="application/ecmascript">
+function paint(color)
+ {var canvas = document.querySelector('canvas'),
+ c = canvas.getContext('2d');
+ c.fillStyle = color;
+ c.beginPath();
+ c.moveTo(0,0);
+ c.lineTo(100,0);
+ c.lineTo(100,100);
+ c.lineTo(0,100);
+ c.closePath();
+ c.fill();}
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ event.dataTransfer.setData('text/plain', 'green');}
+</script>
+</head>
+<body onload="paint('gray')">
+<div draggable="true" ondragstart="start(event)"/>
+<p>You should be able to drag green box above to the gray canvas at the bottom of scrollable container (dragging towards the bottom edge triggers scrolling). Canvas should be repainted to match dropped color.</p>
+<div>
+ <canvas width="100" height="100" ondragenter="event.preventDefault()" ondragover="return false" ondrop="paint(event.dataTransfer.getData('text/plain'))">Canvas</canvas>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/canvas/013.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/canvas/013.xhtml
new file mode 100644
index 00000000000..c63a5d4d056
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/canvas/013.xhtml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop and horizontal scrolling: dropping block element onto canvas inside scrollable container</title>
+<style type="text/css">
+div[draggable]
+ {width:20px;
+ height:20px;
+ background-color:green;}
+p + div
+ {height:150px;
+ width:100px;
+ overflow-x:scroll;}
+canvas
+ {display:block;
+ margin-left:100px;}
+</style>
+<script type="application/ecmascript">
+function paint(color)
+ {var canvas = document.querySelector('canvas'),
+ c = canvas.getContext('2d');
+ c.fillStyle = color;
+ c.beginPath();
+ c.moveTo(0,0);
+ c.lineTo(100,0);
+ c.lineTo(100,100);
+ c.lineTo(0,100);
+ c.closePath();
+ c.fill();}
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ event.dataTransfer.setData('text/plain', 'green');}
+</script>
+</head>
+<body onload="paint('gray')">
+<div draggable="true" ondragstart="start(event)"/>
+<p>You should be able to drag green box above to the gray canvas at the right edge of scrollable container (dragging towards the right edge triggers scrolling). Canvas should be repainted to match dropped color.</p>
+<div>
+ <canvas width="100" height="100" ondragenter="event.preventDefault()" ondragover="return false" ondrop="paint(event.dataTransfer.getData('text/plain'))">Canvas</canvas>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/canvas/014.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/canvas/014.xhtml
new file mode 100644
index 00000000000..561597eeaa8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/canvas/014.xhtml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop and scrolling: dropping block element onto canvas inside scrollable container</title>
+<style type="text/css">
+div[draggable]
+ {width:20px;
+ height:20px;
+ background-color:green;}
+p + div
+ {height:100px;
+ width:100px;
+ overflow:scroll;}
+canvas
+ {display:block;
+ margin:100px 0 0 100px;}
+</style>
+<script type="application/ecmascript">
+function paint(color)
+ {var canvas = document.querySelector('canvas'),
+ c = canvas.getContext('2d');
+ c.fillStyle = color;
+ c.beginPath();
+ c.moveTo(0,0);
+ c.lineTo(100,0);
+ c.lineTo(100,100);
+ c.lineTo(0,100);
+ c.closePath();
+ c.fill();}
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ event.dataTransfer.setData('text/plain', 'green');}
+</script>
+</head>
+<body onload="paint('gray')">
+<div draggable="true" ondragstart="start(event)"/>
+<p>You should be able to drag green box above to the gray canvas in the right-bottom corner of the scrollable container (dragging towards the corner triggers scrolling). Canvas should be repainted to match dropped color.</p>
+<div>
+ <canvas width="100" height="100" ondragenter="event.preventDefault()" ondragover="return false" ondrop="paint(event.dataTransfer.getData('text/plain'))">Canvas</canvas>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/canvas/cross-domain/001.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/canvas/cross-domain/001.xhtml
new file mode 100644
index 00000000000..d99c73e6e0e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/canvas/cross-domain/001.xhtml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Cross-domain canvas data must not populate the dataTransfer</title>
+<script src="../../resources/crossorigin.js"></script>
+<style type="text/css">
+div {
+ width:105px;
+ min-height:105px;
+ text-align:center;
+ margin-top:20px;
+ padding:10px;
+ border:solid thin navy;
+}
+p:first-child {
+ padding-left:12px;
+}
+#image { visibility: hidden; }
+</style>
+</head>
+<body>
+<p>
+ <canvas width="100" height="100" draggable="true">Canvas</canvas>
+</p>
+<p>Drag the navy square above to the box below.</p>
+<div></div>
+<p><img id="image" alt="" width="100" height="100" /></p>
+
+<script><![CDATA[
+document.getElementsByTagName("img")[0].src = crossOriginUrl("www", "../../resources/100x100-navy.png");
+
+window.onload = function() {
+ var canvas = document.getElementsByTagName('canvas')[0], div = document.getElementsByTagName('div')[0], failed = [];
+ var context = canvas.getContext('2d');
+ var image = document.getElementById('image');
+ context.drawImage(image, 0, 0);
+ div.ondragover = div.ondragenter = function(e) {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'copy';
+ };
+ div.ondrop = canvas.ondragstart = function(e) {
+ if( e.type == 'dragstart' ) {
+ e.dataTransfer.setData('Text', 'dummy text');
+ e.dataTransfer.dropEffect = 'copy';
+ }
+ for( var i = 0; i < e.dataTransfer.types.length; i++ ) {
+ if( e.dataTransfer.types[i].match(/image\//) ) {
+ failed[failed.length] = e.dataTransfer.types[i];
+ }
+ }
+ if( e.type == 'drop' ) {
+ e.preventDefault();
+ document.getElementsByTagName('p')[1].innerHTML = failed.length ? ( 'FAIL (found ' + failed.join() + ')' ) : 'PASS';
+ }
+ };
+};
+]]></script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/canvas/helper-drag-me-green-box.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/canvas/helper-drag-me-green-box.xhtml
new file mode 100644
index 00000000000..cb722babd4e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/canvas/helper-drag-me-green-box.xhtml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Canvas drag and drop: helper file</title>
+<style type="text/css">
+div
+ {width:20px;
+ height:20px;
+ background-color:green;}
+</style>
+<script type="application/ecmascript">
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ event.dataTransfer.setData('text/plain', 'green');}
+</script>
+</head>
+<body>
+<div draggable="true" ondragstart="start(event)"/></body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/canvas/helper-drop-here-canvas.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/canvas/helper-drop-here-canvas.xhtml
new file mode 100644
index 00000000000..dcbf7e33f1f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/canvas/helper-drop-here-canvas.xhtml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Canvas drag and drop: helper file</title>
+<script type="application/ecmascript">
+function paint(color)
+ {var canvas = document.querySelector('canvas'),
+ c = canvas.getContext('2d');
+ c.fillStyle = color;
+ c.beginPath();
+ c.moveTo(0,0);
+ c.lineTo(100,0);
+ c.lineTo(100,100);
+ c.lineTo(0,100);
+ c.closePath();
+ c.fill();}
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ event.dataTransfer.setData('text/plain', 'green');}
+</script>
+</head>
+<body onload="paint('gray')">
+<p>
+ <canvas width="100" height="100" ondragenter="event.preventDefault()" ondragover="return false" ondrop="paint(event.dataTransfer.getData('text/plain'))">Canvas</canvas>
+</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/crashers/dialog-001.html b/tests/wpt/web-platform-tests/html/editing/dnd/crashers/dialog-001.html
new file mode 100644
index 00000000000..23484c7bdd9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/crashers/dialog-001.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<meta charset='utf-8'>
+<title>drag &amp; drop – crash when drag is interrupted by dialogs</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ position: absolute;
+ top: 8px;
+ left: 8px;
+ }
+ body > div * {
+ display: none;
+ }
+ body > div + div {
+ background-color: navy;
+ left: 250px;
+ }
+ p {
+ margin-top: 220px;
+ }
+</style>
+
+<script>
+window.onload = function() {
+ var doneonce = false;
+ document.getElementsByTagName('div')[0].ondragstart = function(e) {
+ alert( doneonce ? 'Dismiss this dialog. PASS if the browser does not crash.' : 'Dismiss this dialog. The browser should not crash. Without re-focusing the page first, try dragging the orange square a second time. If a second alert does not appear, release the drag, and then try dragging the orange square a third time.' );
+ doneonce = true;
+ };
+};
+</script>
+
+<div draggable='true' itemscope></div><div></div>
+
+<p>Try to drag the orange square onto the blue square.</p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/cross-document/001-1.html b/tests/wpt/web-platform-tests/html/editing/dnd/cross-document/001-1.html
new file mode 100644
index 00000000000..8eb79d17f04
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/cross-document/001-1.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - cross-document data drop</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: blue;
+ }
+</style>
+
+<script>
+window.onload = function() {
+ var blue = document.getElementsByTagName('div')[0], fails = [];
+ blue.ondragover = blue.ondragenter = function(e) {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'copy';
+ if( e.dataTransfer.getData('text') ) {
+ fails[fails.length] = '"' + e.dataTransfer.getData('text') + '" exposed during event ' + e.type;
+ }
+ };
+ blue.ondrop = function(e) {
+ e.preventDefault();
+ if( !e.dataTransfer.types.length ) {
+ fails[fails.length] = 'no types found during event drop';
+ }
+ var foundtext = false;
+ for( var i = 0; i < e.dataTransfer.types.length; i++ ) {
+ if( e.dataTransfer.types[i] == 'text/plain' ) {
+ foundtext = true;
+ break;
+ }
+ }
+ if( !foundtext ) {
+ fails[fails.length] = 'text/plain type not found during event drop';
+ }
+ if( e.dataTransfer.getData('text') != 'dummy text' ) {
+ fails[fails.length] = 'getData returned ' + e.dataTransfer.getData('text') + ' instead of "dummy text"';
+ }
+ document.getElementsByTagName('p')[0].innerHTML = fails.length ? ( 'FAIL:<br>' + fails.join('<br>') ) : 'PASS';
+ };
+};
+</script>
+
+<p>Drag the orange square onto the blue square. Fail if this text does not change.</p>
+<div></div>
+
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/cross-document/001.html b/tests/wpt/web-platform-tests/html/editing/dnd/cross-document/001.html
new file mode 100644
index 00000000000..02012e86bbc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/cross-document/001.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - simple cross-document data drop</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ }
+</style>
+
+<script>
+window.onload = function() {
+ var orange = document.getElementsByTagName('div')[0];
+ orange.ondragstart = function(e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text', 'dummy text');
+ };
+};
+</script>
+
+<div draggable="true"></div>
+<p><iframe src="001-1.html" height="300" width="500"></iframe></p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/cross-document/002.html b/tests/wpt/web-platform-tests/html/editing/dnd/cross-document/002.html
new file mode 100644
index 00000000000..7b48d3e16ec
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/cross-document/002.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - cross-domain cross-document data drop</title>
+<script src="../resources/crossorigin.js"></script>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ }
+</style>
+
+<script>
+window.onload = function() {
+ var orange = document.getElementsByTagName('div')[0];
+ orange.ondragstart = function(e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text', 'dummy text');
+ };
+};
+</script>
+
+<div draggable="true"></div>
+<p><iframe height="300" width="500"></iframe></p>
+<script>document.getElementsByTagName("iframe")[0].src = crossOriginUrl("www", "001-1.html");
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/cross-document/003-1.html b/tests/wpt/web-platform-tests/html/editing/dnd/cross-document/003-1.html
new file mode 100644
index 00000000000..b1357c10a45
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/cross-document/003-1.html
@@ -0,0 +1,104 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - cross-document data drop</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: blue;
+ }
+</style>
+
+<script>
+window.onload = function() {
+ var blue = document.getElementsByTagName('div')[0], fails = [];
+ blue.ondragover = blue.ondragenter = function(e) {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'copy';
+ if( !parent.evs[e.type] ) { parent.evs[e.type] = {}; }
+ parent.evs[e.type].dataTransfer = e.dataTransfer;
+ parent.evs[e.type].items = e.dataTransfer.items;
+ parent.evs[e.type].types = e.dataTransfer.types;
+ parent.evs[e.type].files = e.dataTransfer.files;
+ if( parent.evs[e.type].dataTransfer != e.dataTransfer ) {
+ fails[fails.length] = '.dataTransfer is not returning the same object during '+e.type;
+ }
+ if( !e.dataTransfer.items ) {
+ fails[fails.length] = '.items is not returning anything during '+e.type;
+ } else if( parent.evs[e.type].items !== e.dataTransfer.items ) {
+ fails[fails.length] = '.items is not returning the same object during '+e.type;
+ }
+ if( !e.dataTransfer.types ) {
+ fails[fails.length] = '.types is not returning anything during '+e.type;
+ } else if( parent.evs[e.type].types !== e.dataTransfer.types ) {
+ fails[fails.length] = '.types is not returning the same object during '+e.type;
+ }
+ if( !e.dataTransfer.files ) {
+ fails[fails.length] = '.files is not returning anything during '+e.type;
+ } else if( parent.evs[e.type].files !== e.dataTransfer.files ) {
+ fails[fails.length] = '.files is not returning the same object during '+e.type;
+ }
+ //http://dev.w3.org/html5/spec/dnd.html#datatransfer
+ //"The * attribute must return a * object associated with the DataTransfer object."
+ //Note that it is associated with the DataTransfer object, *not* the data store
+ //http://dev.w3.org/html5/spec/dnd.html#dragevent
+ //"when a user agent is required to fire a DND event named e at an element, using a particular drag data store...
+ //Let dataTransfer be a newly created DataTransfer object associated with the given drag data store."
+ //A new DataTransfer object therefore means a new set of properties, not the same ones as last event
+ if( parent.evs.dragstart.dataTransfer === e.dataTransfer ) {
+ fails[fails.length] = '.dataTransfer is returning the same object during '+e.type+' as it did during dragstart';
+ }
+ if( e.dataTransfer.items && parent.evs.dragstart.items === e.dataTransfer.items ) {
+ fails[fails.length] = '.items is returning the same object during '+e.type+' as it did during dragstart';
+ }
+ if( e.dataTransfer.types && parent.evs.dragstart.types === e.dataTransfer.types ) {
+ fails[fails.length] = '.types is returning the same object during '+e.type+' as it did during dragstart';
+ }
+ if( e.dataTransfer.files && parent.evs.dragstart.files === e.dataTransfer.files ) {
+ fails[fails.length] = '.files is returning the same object during '+e.type+' as it did during dragstart';
+ }
+ };
+ blue.ondrop = function(e) {
+ parent.evs[e.type] = {};
+ parent.evs[e.type].dataTransfer = e.dataTransfer;
+ parent.evs[e.type].items = e.dataTransfer.items;
+ parent.evs[e.type].types = e.dataTransfer.types;
+ parent.evs[e.type].files = e.dataTransfer.files;
+ if( parent.evs[e.type].dataTransfer !== e.dataTransfer ) {
+ fails[fails.length] = '.dataTransfer is not returning the same object during '+e.type;
+ }
+ if( !e.dataTransfer.items ) {
+ fails[fails.length] = '.items is not returning anything during '+e.type;
+ } else if( parent.evs[e.type].items !== e.dataTransfer.items ) {
+ fails[fails.length] = '.items is not returning the same object during '+e.type;
+ }
+ if( !e.dataTransfer.types ) {
+ fails[fails.length] = '.types is not returning anything during '+e.type;
+ } else if( parent.evs[e.type].types !== e.dataTransfer.types ) {
+ fails[fails.length] = '.types is not returning the same object during '+e.type;
+ }
+ if( !e.dataTransfer.files ) {
+ fails[fails.length] = '.files is not returning anything during '+e.type;
+ } else if( parent.evs[e.type].files !== e.dataTransfer.files ) {
+ fails[fails.length] = '.files is not returning the same object during '+e.type;
+ }
+ if( parent.evs.dragstart.dataTransfer === e.dataTransfer ) {
+ fails[fails.length] = '.dataTransfer is returning the same object during '+e.type+' as it did during dragstart';
+ }
+ if( e.dataTransfer.items && parent.evs.dragstart.items === e.dataTransfer.items ) {
+ fails[fails.length] = '.items is returning the same object during '+e.type+' as it did during dragstart';
+ }
+ if( e.dataTransfer.types && parent.evs.dragstart.types === e.dataTransfer.types ) {
+ fails[fails.length] = '.types is returning the same object during '+e.type+' as it did during dragstart';
+ }
+ if( e.dataTransfer.files && parent.evs.dragstart.files === e.dataTransfer.files ) {
+ fails[fails.length] = '.files is returning the same object during '+e.type+' as it did during dragstart';
+ }
+ document.getElementsByTagName('p')[0].innerHTML = fails.length ? ( 'FAIL:<br>' + fails.join('<br>') ) : 'PASS';
+ };
+};
+</script>
+
+<p>Drag the orange square onto the blue square. Fail if this text does not change.</p>
+<div></div>
+
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/cross-document/003.html b/tests/wpt/web-platform-tests/html/editing/dnd/cross-document/003.html
new file mode 100644
index 00000000000..6b7c4d07458
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/cross-document/003.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - cross-document variable retention within event handlers</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ }
+</style>
+
+<script>
+var evs = {};
+window.onload = function() {
+ var orange = document.getElementsByTagName('div')[0];
+ orange.ondragstart = function(e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text', 'dummy text');
+ evs[e.type] = {};
+ evs[e.type].dataTransfer = e.dataTransfer;
+ evs[e.type].items = e.dataTransfer.items;
+ evs[e.type].types = e.dataTransfer.types;
+ evs[e.type].files = e.dataTransfer.files;
+ };
+};
+</script>
+
+<div draggable="true"></div>
+<p><iframe src="003-1.html" height="300" width="500"></iframe></p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/001.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/001.xhtml
new file mode 100644
index 00000000000..a6f53871042
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/001.xhtml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>dataTransfer.setData/getData during canvas drag and drop</title>
+<style type="text/css">
+div
+ {height:100px;
+ width:100px;
+ padding:20px;
+ background-color:silver;}
+</style>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text/plain', 'text/uri-list', 'application/xml', 'application/xhtml+xml', 'application/mathml+xml', 'image/svg+xml', 'text/html', 'text/x-example'],
+data = ['PASS', 'data:text/plain,1', '<result>PASS</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>PASS</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">PASS</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>PASS</p></body></html>', 'PASS'];
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], data[i]);}
+ say('items.length (dragstart) : ' + ((event.dataTransfer.items.length >= dataTypes.length)?'PASS':'FAIL'));
+ }
+function dragElement(event)
+ {for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during drag)')}
+ }
+ if(event.dataTransfer.items.length < dataTypes.length)
+ {say('items.length (dragover) : FAIL')}
+ }
+function enterElement(event)
+ {event.preventDefault();
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during dragenter)')}
+ }
+ say('items.length (dragenter) : ' + ((event.dataTransfer.items.length >= dataTypes.length)?'PASS':'FAIL'));}
+function dataDrop(event)
+ {say('items.length (drop) : ' + ((event.dataTransfer.items.length >= dataTypes.length)?'PASS':'FAIL'));
+ for(var i = 0; i != dataTypes.length; i++)
+ {say('getData(' + dataTypes[i] + ') : ' + ((event.dataTransfer.getData(dataTypes[i]) == data[i])?'PASS':'FAIL'));}
+ document.querySelector('div').setAttribute('style','background-color:green');}
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+]]>
+</script>
+</head>
+<body>
+<p>
+ <canvas width="100" height="100" draggable="true" ondragstart="start(event)" ondrag="dragElement(event)">Canvas</canvas>
+</p>
+<p>Drag canvas pattern to the silver box below and drop it. Silver box should turn green and test results should appear below.</p>
+<div ondragenter="enterElement(event)" ondragover="return false;" ondrop="dataDrop(event)"/>
+<pre/>
+<script type="application/ecmascript">
+var canvas = document.querySelector('canvas'),
+c = canvas.getContext('2d');
+for(var x = 0; x != 50; x++)
+ {c.fillStyle = (x%2 == 0)?'navy':'white';
+ c.beginPath();
+ c.moveTo(x,x);
+ c.lineTo(100-x,x);
+ c.lineTo(100-x,100-x);
+ c.lineTo(x,100-x);
+ c.closePath();
+ c.fill();}
+data[1] = canvas.toDataURL('image/png');
+</script>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/002.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/002.xhtml
new file mode 100644
index 00000000000..5bbfb9a4ddd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/002.xhtml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>dataTransfer.setData/getData during PNG image drag and drop</title>
+<style type="text/css">
+div
+ {height:100px;
+ width:100px;
+ padding:20px;
+ background-color:silver;}
+</style>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text/uri-list', 'text/plain', 'application/xml', 'application/xhtml+xml', 'application/mathml+xml', 'image/svg+xml', 'text/html', 'text/x-example'],
+data = ['data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAEq0lEQVR42u1dvU4bQRAeR0RCCilSp0peIoKGB4DSXYRDlcZlFClKBI4bB/kV/AymIDwCTahiicaioEOxhCsjWVTJziyKMfYZn+9ud3bvG2mEZB13u9+nndmf2Rki7fKFXtEBbVKD9o22jB4bPaND6hm9Mjo0enevw/vfevKMfbYl/8vv4HdBUkvFALhltG2A7dN3+pur8jv53fwN/hZkjjRo3eiuAatjdJA7CcnkDOSb/G1uQ6mFzUeDagaQrvl764yEJOU22LbUymXaGrRhOt40OvJOQvLIGUkbP9GLeIn4SM9NJ+tOTVI+Jq0ubY9sVFRNxy6DIWKWmEvpQ/ByQNumI+fBEjHrZ86lT8HJV3ptGn8aDRGzxJxKHwMZFe9Mg6+jJWNCyrX0VbUc0nuj4+jJmPiWsfRZodN+ZvSoNETMjpYjwUCFfKaXpjEnpSVjQsqJYOF5ZLw1elF6MiakXAgmnpw378DegIgZUm4EGw8jA2QsIuUbvXHpM2CmljFfhfsUO5uCA0/j6AudfZV5arv6WuVHcYs+ALwqKTkvHnmLoEwr8CJW9Llts9iNwvj3plzsfeWyIRnzrq37kfIzq6naBpA5a6bzlJgOl/SMkl+rklEFgIX5k5THwTYgIdwzcP2jhM/o19KsOeoArnBS6suaqo2gQnXCJWSwXNwXB4gBMFekNBeTwSGUmiMK4yNktDhsleNaAZRrUvYWmasuQHJOSDdpdKyriEIvo9maexWC70gAIF/bKTvzzFUH4HgbJZ3HdFSw9vC6lfKHpq7X8X07AOOblK2HhLQBindC2g/9Rx+gePcj/cnqHIDoUFm1c9gjwNAy/d0kyXIAMLSYrQ8kqScAhhbH3iLJBwIwtBByTJKkBWBoIeSMJHMOwNBCyG+SdEYAQ4tTvyLJMQUwtBAyJEn8BTC0EHIHQhQSApOlzGTBqaty6jzVAhhaCOlhYahuYYitE02EHGNzURchLZItX4ChhZB9HFBpUjmgwhGuHv0feI0gBw1T3j7CgHT5jzYC5XQRsjUdSsrhjADGl7ka0EylBgRb+ySkMy9rww7A8Waududf2MH9Qh9k3CbXLsGVNh/mqrvojuEeQHI+Qmq4Fq1ndIyeruaDxAEuCWk+ncmB0z3gepubtQenMUHyGTWELJl8xk6B15CeqVAyLtPXtUICsyJnVivWs+J0dAAwbzLOkQRTk2YuKsapTQFkXqPjlDILEinnRcZ1fpXdkGo866xqnH9FNyTjz0JIQZXcuPQCAE5rqo6oMEFBl7RknBRfTg8lj5Yl48JdGT0ueIWiYIvIuHFfPg9l85LJcF42b+JTUFjysZnyVlhy2qfA0asovTo9+0JxYnWC8t0KBQXuFYrdkIy3mBj3LbeNQrejZTuqOlbcl8znGTqcfjXoM3pboqgaPhEPxda1qgcVYsRt5TanDkgISWzcV1N1hCS3jdu4dNxUDMIhlBzXysHGGspkcBtsW2pPh3fGLrZ2ya5cXHFp0qxJ6si3E68EQCpy344vQRZxO5jfye+2d/oqgHsV02Z3lvcl9QTnA+EkLZw5h9MZcY4pTvxldXj/W0+esc+25H/5HQGYon+Q5f+MwFz+8QAAAABJRU5ErkJggg==', 'PASS', '<result>PASS</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>PASS</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">PASS</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>PASS</p></body></html>', 'PASS'];
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], data[i]);}
+ say('items.length (dragstart) : ' + ((event.dataTransfer.items.length >= dataTypes.length)?'PASS':'FAIL'));}
+function dragElement(event)
+ {for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during drag)')}
+ }
+ if(event.dataTransfer.items.length < dataTypes.length)
+ {say('items.length (dragover) : FAIL')}
+ }
+function enterElement(event)
+ {event.preventDefault();
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during dragenter)')}
+ }
+ say('items.length (dragenter) : ' + ((event.dataTransfer.items.length >= dataTypes.length)?'PASS':'FAIL'));}
+function dataDrop(event)
+ {say('items.length (drop) : ' + ((event.dataTransfer.items.length >= dataTypes.length)?'PASS':'FAIL'));
+ for(var i = 0; i != dataTypes.length; i++)
+ {say('getData(' + dataTypes[i] + ') : ' + ((event.dataTransfer.getData(dataTypes[i]) == data[i])?'PASS':'FAIL'));}
+ document.querySelector('div').setAttribute('style','background-color:green');}
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+]]>
+</script>
+</head>
+<body>
+<p><img ondragstart="start(event)" ondrag="dragElement(event)" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAEq0lEQVR42u1dvU4bQRAeR0RCCilSp0peIoKGB4DSXYRDlcZlFClKBI4bB/kV/AymIDwCTahiicaioEOxhCsjWVTJziyKMfYZn+9ud3bvG2mEZB13u9+nndmf2Rki7fKFXtEBbVKD9o22jB4bPaND6hm9Mjo0enevw/vfevKMfbYl/8vv4HdBUkvFALhltG2A7dN3+pur8jv53fwN/hZkjjRo3eiuAatjdJA7CcnkDOSb/G1uQ6mFzUeDagaQrvl764yEJOU22LbUymXaGrRhOt40OvJOQvLIGUkbP9GLeIn4SM9NJ+tOTVI+Jq0ubY9sVFRNxy6DIWKWmEvpQ/ByQNumI+fBEjHrZ86lT8HJV3ptGn8aDRGzxJxKHwMZFe9Mg6+jJWNCyrX0VbUc0nuj4+jJmPiWsfRZodN+ZvSoNETMjpYjwUCFfKaXpjEnpSVjQsqJYOF5ZLw1elF6MiakXAgmnpw378DegIgZUm4EGw8jA2QsIuUbvXHpM2CmljFfhfsUO5uCA0/j6AudfZV5arv6WuVHcYs+ALwqKTkvHnmLoEwr8CJW9Llts9iNwvj3plzsfeWyIRnzrq37kfIzq6naBpA5a6bzlJgOl/SMkl+rklEFgIX5k5THwTYgIdwzcP2jhM/o19KsOeoArnBS6suaqo2gQnXCJWSwXNwXB4gBMFekNBeTwSGUmiMK4yNktDhsleNaAZRrUvYWmasuQHJOSDdpdKyriEIvo9maexWC70gAIF/bKTvzzFUH4HgbJZ3HdFSw9vC6lfKHpq7X8X07AOOblK2HhLQBindC2g/9Rx+gePcj/cnqHIDoUFm1c9gjwNAy/d0kyXIAMLSYrQ8kqScAhhbH3iLJBwIwtBByTJKkBWBoIeSMJHMOwNBCyG+SdEYAQ4tTvyLJMQUwtBAyJEn8BTC0EHIHQhQSApOlzGTBqaty6jzVAhhaCOlhYahuYYitE02EHGNzURchLZItX4ChhZB9HFBpUjmgwhGuHv0feI0gBw1T3j7CgHT5jzYC5XQRsjUdSsrhjADGl7ka0EylBgRb+ySkMy9rww7A8Waududf2MH9Qh9k3CbXLsGVNh/mqrvojuEeQHI+Qmq4Fq1ndIyeruaDxAEuCWk+ncmB0z3gepubtQenMUHyGTWELJl8xk6B15CeqVAyLtPXtUICsyJnVivWs+J0dAAwbzLOkQRTk2YuKsapTQFkXqPjlDILEinnRcZ1fpXdkGo866xqnH9FNyTjz0JIQZXcuPQCAE5rqo6oMEFBl7RknBRfTg8lj5Yl48JdGT0ueIWiYIvIuHFfPg9l85LJcF42b+JTUFjysZnyVlhy2qfA0asovTo9+0JxYnWC8t0KBQXuFYrdkIy3mBj3LbeNQrejZTuqOlbcl8znGTqcfjXoM3pboqgaPhEPxda1qgcVYsRt5TanDkgISWzcV1N1hCS3jdu4dNxUDMIhlBzXysHGGspkcBtsW2pPh3fGLrZ2ya5cXHFp0qxJ6si3E68EQCpy344vQRZxO5jfye+2d/oqgHsV02Z3lvcl9QTnA+EkLZw5h9MZcY4pTvxldXj/W0+esc+25H/5HQGYon+Q5f+MwFz+8QAAAABJRU5ErkJggg==" alt="PNG circle"/></p>
+<p>Drag circle above to the silver box below and drop it. Silver box should turn green and test results should appear below.</p>
+<div ondragenter="enterElement(event)" ondragover="return false;" ondrop="dataDrop(event)"/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/003.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/003.xhtml
new file mode 100644
index 00000000000..dbd5851a501
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/003.xhtml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>dataTransfer.setData/getData during SVG image drag and drop</title>
+<style type="text/css">
+div
+ {height:100px;
+ width:100px;
+ padding:20px;
+ background-color:silver;}
+</style>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text/uri-list', 'text/plain', 'application/xml', 'application/xhtml+xml', 'application/mathml+xml', 'image/svg+xml', 'text/html', 'text/x-example'],
+data = ['data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20version%3D%221.1%22%20width%3D%22100px%22%20height%3D%22100px%22%20viewBox%3D%220%200%20100%20100%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22green%22/%3E%3C/svg%3E', 'PASS', '<result>PASS</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>PASS</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">PASS</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>PASS</p></body></html>', 'PASS'];
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], data[i]);}
+ say('items.length (dragstart) : ' + ((event.dataTransfer.items.length >= dataTypes.length)?'PASS':'FAIL'));
+ }
+function dragElement(event)
+ {for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during drag)')}
+ }
+ if(event.dataTransfer.items.length < dataTypes.length)
+ {say('items.length (dragover) : FAIL')}
+ }
+function enterElement(event)
+ {event.preventDefault();
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during dragenter)')}
+ }
+ say('items.length (dragenter) : ' + ((event.dataTransfer.items.length >= dataTypes.length)?'PASS':'FAIL'));}
+function dataDrop(event)
+ {say('items.length (drop) : ' + ((event.dataTransfer.items.length >= dataTypes.length)?'PASS':'FAIL'));
+ for(var i = 0; i != dataTypes.length; i++)
+ {say('getData(' + dataTypes[i] + ') : ' + ((event.dataTransfer.getData(dataTypes[i]) == data[i])?'PASS':'FAIL'));}
+ document.querySelector('div').setAttribute('style','background-color:green');}
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+]]>
+</script>
+</head>
+<body>
+<p><img ondragstart="start(event)" ondrag="dragElement(event)" src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20version%3D%221.1%22%20width%3D%22100px%22%20height%3D%22100px%22%20viewBox%3D%220%200%20100%20100%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22green%22/%3E%3C/svg%3E" alt="SVG circle"/></p>
+<p>Drag circle above to the silver box below and drop it. Silver box should turn green and test results should appear below.</p>
+<div ondragenter="enterElement(event)" ondragover="return false;" ondrop="dataDrop(event)"/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/004.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/004.xhtml
new file mode 100644
index 00000000000..cdf2d16c7a7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/004.xhtml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>dataTransfer.setData/getData during text input selection drag and drop</title>
+<style type="text/css">
+div
+ {min-height:100px;
+ width:100px;
+ padding:20px;
+ color:white;
+ background-color:navy;}
+</style>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text/plain', 'text/uri-list', 'application/xml', 'application/xhtml+xml', 'application/mathml+xml', 'image/svg+xml', 'text/html', 'text/x-example'],
+data = ['Drag me', 'data:text/plain,1', '<result>PASS</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>PASS</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">PASS</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>PASS</p></body></html>', 'PASS'];
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], data[i]);}
+ say('items.length (dragstart) : ' + ((event.dataTransfer.items.length >= dataTypes.length)?'PASS':'FAIL'));
+ }
+function dragElement(event)
+ {for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during drag)')}
+ }
+ if(event.dataTransfer.items.length < dataTypes.length)
+ {say('items.length (dragover) : FAIL')}
+ }
+function enterElement(event)
+ {event.preventDefault();
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during dragenter)')}
+ }
+ say('items.length (dragenter) : ' + ((event.dataTransfer.items.length >= dataTypes.length)?'PASS':'FAIL'));}
+function dataDrop(event)
+ {say('items.length (drop) : ' + ((event.dataTransfer.items.length >= dataTypes.length)?'PASS':'FAIL'));
+ for(var i = 0; i != dataTypes.length; i++)
+ {say('getData(' + dataTypes[i] + ') : ' + ((event.dataTransfer.getData(dataTypes[i]) == data[i])?'PASS':'FAIL'));}
+ document.querySelector('div').setAttribute('style','background-color:green');}
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+]]>
+</script>
+</head>
+<body onload="document.querySelector('input').select()">
+<p><input value="Drag me" ondragstart="start(event)" ondrag="dragElement(event)"/></p>
+<p>Drag selection above to the navy box below and drop it. Navy box should turn green and test results should appear below.</p>
+<div ondragenter="enterElement(event)" ondragover="return false;" ondrop="dataDrop(event)"/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/005.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/005.xhtml
new file mode 100644
index 00000000000..949e6c3ca7a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/005.xhtml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>dataTransfer.setData/getData during selection drag and drop</title>
+<style type="text/css">
+div
+ {min-height:100px;
+ width:100px;
+ padding:20px;
+ color:white;
+ background-color:navy;}
+</style>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text/plain', 'text/uri-list', 'application/xml', 'application/xhtml+xml', 'application/mathml+xml', 'image/svg+xml', 'text/html', 'text/x-example'],
+data = ['Drag me', 'data:text/plain,1', '<result>PASS</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>PASS</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">PASS</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>PASS</p></body></html>', 'PASS'];
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], data[i]);}
+ say('items.length (dragstart) : ' + ((event.dataTransfer.items.length >= dataTypes.length)?'PASS':'FAIL'));
+ }
+function dragElement(event)
+ {for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during drag)')}
+ }
+ if(event.dataTransfer.items.length < dataTypes.length)
+ {say('items.length (dragover) : FAIL')}
+ }
+function enterElement(event)
+ {event.preventDefault();
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during dragenter)')}
+ }
+ say('items.length (dragenter) : ' + ((event.dataTransfer.items.length >= dataTypes.length)?'PASS':'FAIL'));}
+function dataDrop(event)
+ {say('items.length (drop) : ' + ((event.dataTransfer.items.length >= dataTypes.length)?'PASS':'FAIL'));
+ for(var i = 0; i != dataTypes.length; i++)
+ {say('getData(' + dataTypes[i] + ') : ' + ((event.dataTransfer.getData(dataTypes[i]) == data[i])?'PASS':'FAIL'));}
+ document.querySelector('div').setAttribute('style','background-color:green');}
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+]]>
+</script>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('span'))">
+<p><span ondragstart="start(event)" ondrag="dragElement(event)">Drag me</span></p>
+<p>Drag selection above to the navy box below and drop it. Navy box should turn green and test results should appear below.</p>
+<div ondragenter="enterElement(event)" ondragover="return false;" ondrop="dataDrop(event)"/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/006.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/006.xhtml
new file mode 100644
index 00000000000..24e30bd8307
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/006.xhtml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>dataTransfer.setData/getData during link drag and drop</title>
+<style type="text/css">
+div
+ {height:100px;
+ width:100px;
+ padding:20px;
+ background-color:silver;}
+</style>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text/uri-list', 'text/plain', 'application/xml', 'application/xhtml+xml', 'application/mathml+xml', 'image/svg+xml', 'text/html', 'text/x-example'],
+data = ['data:text/plain,1', 'PASS', '<result>PASS</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>PASS</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">PASS</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>PASS</p></body></html>', 'PASS'];
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], data[i]);}
+ say('items.length (dragstart) : ' + ((event.dataTransfer.items.length >= dataTypes.length)?'PASS':'FAIL'));
+ }
+function dragElement(event)
+ {for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during drag)')}
+ }
+ if(event.dataTransfer.items.length < dataTypes.length)
+ {say('items.length (dragover) : FAIL')}
+ }
+function enterElement(event)
+ {event.preventDefault();
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during dragenter)')}
+ }
+ say('items.length (dragenter) : ' + ((event.dataTransfer.items.length >= dataTypes.length)?'PASS':'FAIL'));}
+function dataDrop(event)
+ {say('items.length (drop) : ' + ((event.dataTransfer.items.length >= dataTypes.length)?'PASS':'FAIL'));
+ for(var i = 0; i != dataTypes.length; i++)
+ {say('getData(' + dataTypes[i] + ') : ' + ((event.dataTransfer.getData(dataTypes[i]) == data[i])?'PASS':'FAIL'));}
+ document.querySelector('div').setAttribute('style','background-color:green');}
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+]]>
+</script>
+</head>
+<body>
+<p><a href="data:text/plain,1" ondragstart="start(event)" ondrag="dragElement(event)">Drag me</a></p>
+<p>Drag link above to the silver box below and drop it. Silver box should turn green and test results should appear below.</p>
+<div ondragenter="enterElement(event)" ondragover="return false;" ondrop="dataDrop(event)"/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/007.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/007.xhtml
new file mode 100644
index 00000000000..66c89a24fdf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/007.xhtml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>dataTransfer.setData/getData during block element drag and drop</title>
+<style type="text/css">
+div
+ {height:100px;
+ width:100px;
+ padding:20px;
+ background-color:green;}
+p + div
+ {background-color:gray;}
+</style>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text/plain', 'text/uri-list', 'application/xml', 'application/xhtml+xml', 'application/mathml+xml', 'image/svg+xml', 'text/html', 'text/x-example'],
+data = ['PASS', 'data:text/plain,1', '<result>PASS</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>PASS</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">PASS</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>PASS</p></body></html>', 'PASS'];
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], data[i]);}
+ say('items.length (dragstart) : ' + ((event.dataTransfer.items.length >= dataTypes.length)?'PASS':'FAIL'));
+ }
+function dragElement(event)
+ {for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during drag)')}
+ }
+ if(event.dataTransfer.items.length < dataTypes.length)
+ {say('items.length (dragover) : FAIL')}
+ }
+function enterElement(event)
+ {event.preventDefault();
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during dragenter)')}
+ }
+ say('items.length (dragenter) : ' + ((event.dataTransfer.items.length >= dataTypes.length)?'PASS':'FAIL'));}
+function dataDrop(event)
+ {say('items.length (drop) : ' + ((event.dataTransfer.items.length >= dataTypes.length)?'PASS':'FAIL'));
+ for(var i = 0; i != dataTypes.length; i++)
+ {say('getData(' + dataTypes[i] + ') : ' + ((event.dataTransfer.getData(dataTypes[i]) == data[i])?'PASS':'FAIL'));}
+ document.querySelector('p + div').setAttribute('style','background-color:green');}
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+]]>
+</script>
+</head>
+<body>
+<div draggable="true" ondragstart="start(event)" ondrag="dragElement(event)"/>
+<p>Drag green box above to the gray box below and drop it. Gray box should turn green and test results should appear below.</p>
+<div ondragenter="enterElement(event)" ondragover="return false;" ondrop="dataDrop(event)"/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/008.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/008.xhtml
new file mode 100644
index 00000000000..1ff328d9e9c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/008.xhtml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Influence of reload during drag and drop on datastore</title>
+<style type="text/css">
+div
+ {height:100px;
+ width:100px;
+ padding:20px;
+ background-color:green;}
+p + div
+ {background-color:gray;}
+</style>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text/plain', 'text/uri-list', 'application/xml', 'application/xhtml+xml', 'application/mathml+xml', 'image/svg+xml', 'text/html', 'text/x-example'],
+data = ['PASS', 'data:text/plain,1', '<result>PASS</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>PASS</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">PASS</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>PASS</p></body></html>', 'PASS'];
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], data[i]);}
+ window.location.reload();}
+function dragElement(event)
+ {for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during drag)')}
+ }
+ if(event.dataTransfer.items.length < dataTypes.length)
+ {say('items.length (dragover) : FAIL')}
+ }
+function enterElement(event)
+ {event.preventDefault();
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during dragenter)')}
+ }
+ say('items.length (dragenter) : ' + ((event.dataTransfer.items.length >= dataTypes.length)?'PASS':'FAIL'));}
+function dataDrop(event)
+ {say('items.length (drop) : ' + ((event.dataTransfer.items.length >= dataTypes.length)?'PASS':'FAIL'));
+ for(var i = 0; i != dataTypes.length; i++)
+ {say('getData(' + dataTypes[i] + ') : ' + ((event.dataTransfer.getData(dataTypes[i]) == data[i])?'PASS':'FAIL'));}
+ document.querySelector('p + div').setAttribute('style','background-color:green');}
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+]]>
+</script>
+</head>
+<body>
+<div draggable="true" ondragstart="start(event)" ondrag="dragElement(event)"/>
+<p>Drag green box above to the gray box below and drop it. Gray box should turn green and test results should appear below.</p>
+<div ondragenter="enterElement(event)" ondragover="return false;" ondrop="dataDrop(event)"/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/009-1.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/009-1.xhtml
new file mode 100644
index 00000000000..ed55dc5a42b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/009-1.xhtml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Redirect during drag and drop: helper file</title>
+<style type="text/css">
+html, body
+ {height:100%;}
+</style>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text/plain', 'text/uri-list', 'application/xml', 'application/xhtml+xml', 'application/mathml+xml', 'image/svg+xml', 'text/html', 'text/x-example'],
+data = ['PASS', 'data:text/plain,1', '<result>PASS</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>PASS</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">PASS</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>PASS</p></body></html>', 'PASS'];
+function enterElement(event)
+ {event.preventDefault();
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during dragenter)')}
+ }
+ say('items.length (dragenter) : ' + ((event.dataTransfer.items.length >= dataTypes.length)?'PASS':'FAIL'));}
+function dataDrop(event)
+ {say('items.length (drop) : ' + ((event.dataTransfer.items.length >= dataTypes.length)?'PASS':'FAIL'));
+ for(var i = 0; i != dataTypes.length; i++)
+ {say('getData(' + dataTypes[i] + ') : ' + ((event.dataTransfer.getData(dataTypes[i]) == data[i])?'PASS':'FAIL'));}
+ document.querySelector('body').setAttribute('style','background-color:teal;color:white;');}
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+]]>
+</script>
+</head>
+<body ondragenter="enterElement(event)" ondragover="return false;" ondrop="dataDrop(event)">
+<p>Drop box here. Page should turn green and test results should appear below.</p>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/009.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/009.xhtml
new file mode 100644
index 00000000000..d0719fdfd4c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/009.xhtml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Influence of redirect during drag and drop on datastore</title>
+<style type="text/css">
+div
+ {height:100px;
+ width:100px;
+ padding:20px;
+ background-color:navy;}
+p + div
+ {background-color:gray;}
+</style>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text/plain', 'text/uri-list', 'application/xml', 'application/xhtml+xml', 'application/mathml+xml', 'image/svg+xml', 'text/html', 'text/x-example'],
+data = ['PASS', 'data:text/plain,1', '<result>PASS</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>PASS</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">PASS</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>PASS</p></body></html>', 'PASS'];
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], data[i]);}
+ window.location = '009-1.xhtml'}
+]]>
+</script>
+</head>
+<body>
+<div draggable="true" ondragstart="start(event)"/>
+<p>Try to drag box above. You should be redirected to the new page and be able to drop it there.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/010-1.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/010-1.xhtml
new file mode 100644
index 00000000000..427624a6ff6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/010-1.xhtml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>History navigation during drag and drop: helper file</title>
+<style type="text/css">
+div[ondragenter]
+ {margin:200px 0 0 200px;
+ width:200px;
+ height:100px;
+ color:white;
+ background-color:navy;}
+div[ondragenter]:before
+ {display:block;
+ content:"";
+ border-style:solid;
+ position:relative;
+ top:-50px;
+ left:-200px;
+ border-width:100px;
+ border-color:transparent navy transparent transparent;}
+</style>
+</head>
+<body>
+<p>Drag box to the blue arrow but don't drop it yet. You should be returned back to start page.</p>
+<div ondragenter="event.preventDefault()" ondragover="history.go(-1)"/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/010.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/010.xhtml
new file mode 100644
index 00000000000..9e32b36f32d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/010.xhtml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Influence of history navigation during drag and drop on datastore</title>
+<style type="text/css">
+div
+ {height:100px;
+ width:100px;
+ padding:20px;
+ background-color:green;}
+p + div
+ {background-color:gray;}
+</style>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text/plain', 'text/uri-list', 'application/xml', 'application/xhtml+xml', 'application/mathml+xml', 'image/svg+xml', 'text/html', 'text/x-example'],
+data = ['PASS', 'data:text/plain,1', '<result>PASS</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>PASS</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">PASS</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>PASS</p></body></html>', 'PASS'];
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], data[i]);}
+ window.location = '010-1.xhtml'}
+function enterElement(event)
+ {event.preventDefault();
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during dragenter)')}
+ }
+ say('items.length (dragenter) : ' + ((event.dataTransfer.items.length >= dataTypes.length)?'PASS':'FAIL'));}
+function dataDrop(event)
+ {say('items.length (drop) : ' + ((event.dataTransfer.items.length >= dataTypes.length)?'PASS':'FAIL'));
+ for(var i = 0; i != dataTypes.length; i++)
+ {say('getData(' + dataTypes[i] + ') : ' + ((event.dataTransfer.getData(dataTypes[i]) == data[i])?'PASS':'FAIL'));}
+ document.querySelector('p + div').setAttribute('style','background-color:green');}
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+]]>
+</script>
+</head>
+<body>
+<div draggable="true" ondragstart="start(event)"/>
+<p>Drag green box above. You will be redirected to new page. When you return back drop it on the gray box below. Gray box should turn green and test results should appear below.</p>
+<div ondragenter="enterElement(event)" ondragover="return false;" ondrop="dataDrop(event)"/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/011.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/011.xhtml
new file mode 100644
index 00000000000..6b51611ebfb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/011.xhtml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop datastore: dragging element to iframe</title>
+<style type="text/css">
+div
+ {height:100px;
+ width:100px;
+ padding:20px;
+ background-color:navy;}
+iframe
+ {width:500px;
+ height:500px;}
+</style>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text/plain', 'text/uri-list', 'application/xml', 'application/xhtml+xml', 'application/mathml+xml', 'image/svg+xml', 'text/html', 'text/x-example'],
+data = ['PASS', 'data:text/plain,1', '<result>PASS</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>PASS</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">PASS</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>PASS</p></body></html>', 'PASS'];
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], data[i]);}
+ }
+]]>
+</script>
+</head>
+<body>
+<div draggable="true" ondragstart="start(event)"/>
+<p>Drag box above to the frame below.</p>
+<iframe src="helper-drop-box-here.xhtml">XHTML document</iframe>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/012.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/012.xhtml
new file mode 100644
index 00000000000..b80ed24fa16
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/012.xhtml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop datastore: dragging element to object</title>
+<style type="text/css">
+div
+ {height:100px;
+ width:100px;
+ padding:20px;
+ background-color:navy;}
+object
+ {width:500px;
+ height:500px;
+ border:solid medium navy;}
+</style>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text/plain', 'text/uri-list', 'application/xml', 'application/xhtml+xml', 'application/mathml+xml', 'image/svg+xml', 'text/html', 'text/x-example'],
+data = ['PASS', 'data:text/plain,1', '<result>PASS</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>PASS</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">PASS</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>PASS</p></body></html>', 'PASS'];
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], data[i]);}
+ }
+]]>
+</script>
+</head>
+<body>
+<div draggable="true" ondragstart="start(event)"/>
+<p>Drag box above to the frame below.</p>
+<object type="application/xhtml+xml" data="helper-drop-box-here.xhtml">XHTML document</object>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/013-1.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/013-1.xhtml
new file mode 100644
index 00000000000..d724679e6d1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/013-1.xhtml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop datastore: helper file</title>
+<style type="text/css">
+div
+ {height:100px;
+ width:100px;
+ padding:20px;
+ background-color:navy;}
+</style>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text/plain', 'text/uri-list', 'application/xml', 'application/xhtml+xml', 'application/mathml+xml', 'image/svg+xml', 'text/html', 'text/x-example'],
+data = ['PASS', 'data:text/plain,1', '<result>PASS</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>PASS</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">PASS</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>PASS</p></body></html>', 'PASS'];
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], data[i]);}
+ }
+]]>
+</script>
+</head>
+<body>
+<div draggable="true" ondragstart="start(event)"/>
+<p>Drag box above to the frame below.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/013.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/013.xhtml
new file mode 100644
index 00000000000..312a66d1f2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/013.xhtml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop datastore: dragging element between frames</title>
+</head>
+<frameset rows="50%, 50%">
+<frame src="013-1.xhtml"/>
+<frame src="helper-drop-box-here.xhtml"/>
+</frameset>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/014-1.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/014-1.xhtml
new file mode 100644
index 00000000000..7a506931777
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/014-1.xhtml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop datastore: helper file</title>
+<style type="text/css">
+div
+ {height:100px;
+ width:100px;
+ padding:20px;
+ background-color:silver;}
+</style>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text/uri-list', 'text/plain', 'application/xml', 'application/xhtml+xml', 'application/mathml+xml', 'image/svg+xml', 'text/html', 'text/x-example'],
+data = ['data:text/plain,1', 'PASS', '<result>PASS</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>PASS</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">PASS</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>PASS</p></body></html>', 'PASS'];
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], data[i]);}
+ say('items.length (dragstart) : ' + ((event.dataTransfer.items.length >= dataTypes.length)?'PASS':'FAIL'));
+ }
+function dragElement(event)
+ {for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during drag)')}
+ }
+ if(event.dataTransfer.items.length < dataTypes.length)
+ {say('items.length (dragover) : FAIL')}
+ }
+function enterElement(event)
+ {event.preventDefault();
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during dragenter)')}
+ }
+ say('items.length (dragenter) : ' + ((event.dataTransfer.items.length >= dataTypes.length)?'PASS':'FAIL'));}
+function dataDrop(event)
+ {say('items.length (drop) : ' + ((event.dataTransfer.items.length >= dataTypes.length)?'PASS':'FAIL'));
+ for(var i = 0; i != dataTypes.length; i++)
+ {say('getData(' + dataTypes[i] + ') : ' + ((event.dataTransfer.getData(dataTypes[i]) == data[i])?'PASS':'FAIL'));}
+ document.querySelector('div').setAttribute('style','background-color:green');}
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+]]>
+</script>
+</head>
+<body>
+<p><a href="data:text/plain,1" ondragstart="start(event)" ondrag="dragElement(event)">Drag me</a></p>
+<p>Drag link from one frame to the silver box in another frame and drop it. Silver box should turn green and test results should appear.</p>
+<div ondragenter="enterElement(event)" ondragover="return false;" ondrop="dataDrop(event)"/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/014.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/014.xhtml
new file mode 100644
index 00000000000..e1892c5a344
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/014.xhtml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop datastore: dragging element between two instances of document</title>
+</head>
+<frameset rows="50%, 50%">
+<frame src="014-1.xhtml"/>
+<frame src="014-1.xhtml"/>
+</frameset>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/015-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/015-manual.html
new file mode 100644
index 00000000000..74fff038d4b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/015-manual.html
@@ -0,0 +1,62 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Using dataTransfer in new thread</title>
+ <style type="text/css">
+blockquote { height: 100px; width: 100px; background: orange; margin: 0; padding: 0; float: left; }
+blockquote + blockquote { background: blue; }
+blockquote + blockquote + blockquote { background: fuchsia; }
+blockquote + div { clear: left; }
+ </style>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript">
+setup(function () {},{explicit_done:true,explicit_timeout:true});
+window.onload = function () {
+
+ var orange = document.getElementsByTagName('blockquote')[0],
+ blue = document.getElementsByTagName('blockquote')[1],
+ fuchsia = document.getElementsByTagName('blockquote')[2],
+ evtdone = {};
+
+ orange.ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text','dragstart real data');
+ var dataTransfer = e.dataTransfer;
+ setTimeout(function () {
+ test(function () {
+ assert_equals( dataTransfer.getData('text'), '', 'step 1' );
+ dataTransfer.setData('text','new thread after dragstart');
+ assert_equals( dataTransfer.getData('text'), '', 'step 2' );
+ },'dragstart data store should be protected after new thread starts');
+ },0);
+ };
+
+ fuchsia.ondragenter = fuchsia.ondragover = function (e) {
+ e.preventDefault();
+ };
+
+ fuchsia.ondrop = function (e) {
+ e.preventDefault();
+ var dataTransfer = e.dataTransfer;
+ setTimeout(function () {
+ test(function () {
+ assert_equals( dataTransfer.getData('text'), '', 'step 1' );
+ dataTransfer.setData('text','new thread after dragstart');
+ assert_equals( dataTransfer.getData('text'), '', 'step 2' );
+ },'drop data store should be protected after new thread starts');
+ done();
+ },0);
+ };
+
+};
+ </script>
+ </head>
+ <body>
+ <p>Drag the orange square over the blue square then the fuchsia square, then release it.</p>
+ <blockquote draggable="true"></blockquote>
+ <blockquote></blockquote>
+ <blockquote></blockquote>
+ <div id="log"></div>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/016.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/016.xhtml
new file mode 100644
index 00000000000..5c5a49a2aff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/016.xhtml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>dataTransfer.clearData during PNG image drag and drop</title>
+<style type="text/css">
+div
+ {height:100px;
+ width:100px;
+ padding:20px;
+ background-color:silver;}
+</style>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text/uri-list', 'text/plain', 'application/xml', 'application/xhtml+xml', 'application/mathml+xml', 'image/svg+xml', 'text/html', 'text/x-example'],
+data = ['data:text/plain,FAIL', 'FAIL', '<result>FAIL</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>FAIL</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">FAIL</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>FAIL</p></body></html>', 'FAIL'],
+l = 0;
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ l = event.dataTransfer.items.length;
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], data[i]);}
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.clearData(dataTypes[i]);}
+ say('items.length (dragstart) : ' + ((event.dataTransfer.items.length < l)?'PASS':'FAIL'));}
+function dragElement(event)
+ {for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during drag)')}
+ }
+ if(event.dataTransfer.items.length > l)
+ {say('items.length (dragover) : FAIL' + event.dataTransfer.items.length)}
+ }
+function enterElement(event)
+ {event.preventDefault();
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during dragenter)')}
+ }
+ say('items.length (dragenter) : ' + ((event.dataTransfer.items.length < l)?'PASS':'FAIL'));}
+function dataDrop(event)
+ {say('items.length (drop) : ' + ((event.dataTransfer.items.length < l)?'PASS':'FAIL'));
+ for(var i = 0; i != dataTypes.length; i++)
+ {say('getData(' + dataTypes[i] + ') : ' + ((event.dataTransfer.getData(dataTypes[i]) == '')?'PASS':'FAIL'));}
+ document.querySelector('div').setAttribute('style','background-color:green');}
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+]]>
+</script>
+</head>
+<body>
+<p><img ondragstart="start(event)" ondrag="dragElement(event)" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAEq0lEQVR42u1dvU4bQRAeR0RCCilSp0peIoKGB4DSXYRDlcZlFClKBI4bB/kV/AymIDwCTahiicaioEOxhCsjWVTJziyKMfYZn+9ud3bvG2mEZB13u9+nndmf2Rki7fKFXtEBbVKD9o22jB4bPaND6hm9Mjo0enevw/vfevKMfbYl/8vv4HdBUkvFALhltG2A7dN3+pur8jv53fwN/hZkjjRo3eiuAatjdJA7CcnkDOSb/G1uQ6mFzUeDagaQrvl764yEJOU22LbUymXaGrRhOt40OvJOQvLIGUkbP9GLeIn4SM9NJ+tOTVI+Jq0ubY9sVFRNxy6DIWKWmEvpQ/ByQNumI+fBEjHrZ86lT8HJV3ptGn8aDRGzxJxKHwMZFe9Mg6+jJWNCyrX0VbUc0nuj4+jJmPiWsfRZodN+ZvSoNETMjpYjwUCFfKaXpjEnpSVjQsqJYOF5ZLw1elF6MiakXAgmnpw378DegIgZUm4EGw8jA2QsIuUbvXHpM2CmljFfhfsUO5uCA0/j6AudfZV5arv6WuVHcYs+ALwqKTkvHnmLoEwr8CJW9Llts9iNwvj3plzsfeWyIRnzrq37kfIzq6naBpA5a6bzlJgOl/SMkl+rklEFgIX5k5THwTYgIdwzcP2jhM/o19KsOeoArnBS6suaqo2gQnXCJWSwXNwXB4gBMFekNBeTwSGUmiMK4yNktDhsleNaAZRrUvYWmasuQHJOSDdpdKyriEIvo9maexWC70gAIF/bKTvzzFUH4HgbJZ3HdFSw9vC6lfKHpq7X8X07AOOblK2HhLQBindC2g/9Rx+gePcj/cnqHIDoUFm1c9gjwNAy/d0kyXIAMLSYrQ8kqScAhhbH3iLJBwIwtBByTJKkBWBoIeSMJHMOwNBCyG+SdEYAQ4tTvyLJMQUwtBAyJEn8BTC0EHIHQhQSApOlzGTBqaty6jzVAhhaCOlhYahuYYitE02EHGNzURchLZItX4ChhZB9HFBpUjmgwhGuHv0feI0gBw1T3j7CgHT5jzYC5XQRsjUdSsrhjADGl7ka0EylBgRb+ySkMy9rww7A8Waududf2MH9Qh9k3CbXLsGVNh/mqrvojuEeQHI+Qmq4Fq1ndIyeruaDxAEuCWk+ncmB0z3gepubtQenMUHyGTWELJl8xk6B15CeqVAyLtPXtUICsyJnVivWs+J0dAAwbzLOkQRTk2YuKsapTQFkXqPjlDILEinnRcZ1fpXdkGo866xqnH9FNyTjz0JIQZXcuPQCAE5rqo6oMEFBl7RknBRfTg8lj5Yl48JdGT0ueIWiYIvIuHFfPg9l85LJcF42b+JTUFjysZnyVlhy2qfA0asovTo9+0JxYnWC8t0KBQXuFYrdkIy3mBj3LbeNQrejZTuqOlbcl8znGTqcfjXoM3pboqgaPhEPxda1qgcVYsRt5TanDkgISWzcV1N1hCS3jdu4dNxUDMIhlBzXysHGGspkcBtsW2pPh3fGLrZ2ya5cXHFp0qxJ6si3E68EQCpy344vQRZxO5jfye+2d/oqgHsV02Z3lvcl9QTnA+EkLZw5h9MZcY4pTvxldXj/W0+esc+25H/5HQGYon+Q5f+MwFz+8QAAAABJRU5ErkJggg==" alt="PNG circle"/></p>
+<p>Drag circle above to the silver box below and drop it. Silver box should turn green and test results should appear below.</p>
+<div ondragenter="enterElement(event)" ondragover="return false;" ondrop="dataDrop(event)"/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/017.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/017.xhtml
new file mode 100644
index 00000000000..2cf031c1238
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/017.xhtml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>dataTransfer.clearData during SVG image drag and drop</title>
+<style type="text/css">
+div
+ {height:100px;
+ width:100px;
+ padding:20px;
+ background-color:silver;}
+</style>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text/uri-list', 'text/plain', 'application/xml', 'application/xhtml+xml', 'application/mathml+xml', 'image/svg+xml', 'text/html', 'text/x-example'],
+data = ['data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20version%3D%221.1%22%20width%3D%22100px%22%20height%3D%22100px%22%20viewBox%3D%220%200%20100%20100%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22green%22/%3E%3C/svg%3E', 'FAIL', '<result>FAIL</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>FAIL</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">FAIL</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>FAIL</p></body></html>', 'FAIL'],
+l = 0;
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ l = event.dataTransfer.items.length;
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], data[i]);}
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.clearData(dataTypes[i]);}
+ say('items.length (dragstart) : ' + ((event.dataTransfer.items.length < l)?'PASS':'FAIL'));}
+function dragElement(event)
+ {for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during drag)')}
+ }
+ if(event.dataTransfer.items.length > l)
+ {say('items.length (dragover) : FAIL' + event.dataTransfer.items.length)}
+ }
+function enterElement(event)
+ {event.preventDefault();
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during dragenter)')}
+ }
+ say('items.length (dragenter) : ' + ((event.dataTransfer.items.length < l)?'PASS':'FAIL'));}
+function dataDrop(event)
+ {say('items.length (drop) : ' + ((event.dataTransfer.items.length < l)?'PASS':'FAIL'));
+ for(var i = 0; i != dataTypes.length; i++)
+ {say('getData(' + dataTypes[i] + ') : ' + ((event.dataTransfer.getData(dataTypes[i]) == '')?'PASS':'FAIL'));}
+ document.querySelector('div').setAttribute('style','background-color:green');}
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+]]>
+</script>
+</head>
+<body>
+<p><img ondragstart="start(event)" ondrag="dragElement(event)" src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20version%3D%221.1%22%20width%3D%22100px%22%20height%3D%22100px%22%20viewBox%3D%220%200%20100%20100%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22green%22/%3E%3C/svg%3E" alt="SVG circle"/></p>
+<p>Drag circle above to the silver box below and drop it. Silver box should turn green and test results should appear below.</p>
+<div ondragenter="enterElement(event)" ondragover="return false;" ondrop="dataDrop(event)"/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/018.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/018.xhtml
new file mode 100644
index 00000000000..ecf703b7325
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/018.xhtml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>dataTransfer.clearData during text input selection drag and drop</title>
+<style type="text/css">
+div
+ {min-height:100px;
+ width:100px;
+ padding:20px;
+ color:white;
+ background-color:navy;}
+</style>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text/plain', 'text/uri-list', 'application/xml', 'application/xhtml+xml', 'application/mathml+xml', 'image/svg+xml', 'text/html', 'text/x-example'],
+data = ['FAIL', 'data:text/plain,FAIL', '<result>FAIL</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>FAIL</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">FAIL</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>FAIL</p></body></html>', 'FAIL'],
+l = 0;
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ l = event.dataTransfer.items.length;
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], data[i]);}
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.clearData(dataTypes[i]);}
+ say('items.length (dragstart) : ' + ((event.dataTransfer.items.length < l)?'PASS':'FAIL'));}
+function dragElement(event)
+ {for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during drag)')}
+ }
+ if(event.dataTransfer.items.length > l)
+ {say('items.length (dragover) : FAIL' + event.dataTransfer.items.length)}
+ }
+function enterElement(event)
+ {event.preventDefault();
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during dragenter)')}
+ }
+ say('items.length (dragenter) : ' + ((event.dataTransfer.items.length < l)?'PASS':'FAIL'));}
+function dataDrop(event)
+ {say('items.length (drop) : ' + ((event.dataTransfer.items.length < l)?'PASS':'FAIL'));
+ for(var i = 0; i != dataTypes.length; i++)
+ {say('getData(' + dataTypes[i] + ') : ' + ((event.dataTransfer.getData(dataTypes[i]) == '')?'PASS':'FAIL'));}
+ document.querySelector('div').setAttribute('style','background-color:green');}
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+]]>
+</script>
+</head>
+<body onload="document.querySelector('input').select()">
+<p><input value="Drag me" ondragstart="start(event)" ondrag="dragElement(event)"/></p>
+<p>Drag selection above to the navy box below and drop it. Navy box should turn green and test results should appear below.</p>
+<div ondragenter="enterElement(event)" ondragover="return false;" ondrop="dataDrop(event)"/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/019.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/019.xhtml
new file mode 100644
index 00000000000..2aa803c614b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/019.xhtml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>dataTransfer.clearData during selection drag and drop</title>
+<style type="text/css">
+div
+ {min-height:100px;
+ width:100px;
+ padding:20px;
+ color:white;
+ background-color:navy;}
+</style>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text/plain', 'text/uri-list', 'application/xml', 'application/xhtml+xml', 'application/mathml+xml', 'image/svg+xml', 'text/html', 'text/x-example'],
+data = ['FAIL', 'data:text/plain,FAIL', '<result>FAIL</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>FAIL</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">FAIL</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>FAIL</p></body></html>', 'FAIL'],
+l = 0;
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ l = event.dataTransfer.items.length;
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], data[i]);}
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.clearData(dataTypes[i]);}
+ say('items.length (dragstart) : ' + ((event.dataTransfer.items.length < l)?'PASS':'FAIL'));}
+function dragElement(event)
+ {for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during drag)')}
+ }
+ if(event.dataTransfer.items.length > l)
+ {say('items.length (dragover) : FAIL' + event.dataTransfer.items.length)}
+ }
+function enterElement(event)
+ {event.preventDefault();
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during dragenter)')}
+ }
+ say('items.length (dragenter) : ' + ((event.dataTransfer.items.length < l)?'PASS':'FAIL'));}
+function dataDrop(event)
+ {say('items.length (drop) : ' + ((event.dataTransfer.items.length < l)?'PASS':'FAIL'));
+ for(var i = 0; i != dataTypes.length; i++)
+ {say('getData(' + dataTypes[i] + ') : ' + ((event.dataTransfer.getData(dataTypes[i]) == '')?'PASS':'FAIL'));}
+ document.querySelector('div').setAttribute('style','background-color:green');}
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+]]>
+</script>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('span'))">
+<p><span ondragstart="start(event)" ondrag="dragElement(event)">Drag me</span></p>
+<p>Drag selection above to the navy box below and drop it. Navy box should turn green and test results should appear below.</p>
+<div ondragenter="enterElement(event)" ondragover="return false;" ondrop="dataDrop(event)"/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/020.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/020.xhtml
new file mode 100644
index 00000000000..73689e1da67
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/020.xhtml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>dataTransfer.clearData during link drag and drop</title>
+<style type="text/css">
+div
+ {height:100px;
+ width:100px;
+ padding:20px;
+ background-color:silver;}
+</style>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text/uri-list', 'text/plain', 'application/xml', 'application/xhtml+xml', 'application/mathml+xml', 'image/svg+xml', 'text/html', 'text/x-example'],
+data = ['data:text/plain,FAIL', 'FAIL', '<result>FAIL</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>FAIL</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">FAIL</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>FAIL</p></body></html>', 'FAIL'],
+l = 0;
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], data[i]);}
+ say('items.length (dragstart) : ' + ((event.dataTransfer.items.length >= dataTypes.length)?'PASS':'FAIL'));
+ }
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ l = event.dataTransfer.items.length;
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], data[i]);}
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.clearData(dataTypes[i]);}
+ say('items.length (dragstart) : ' + ((event.dataTransfer.items.length < l)?'PASS':'FAIL'));}
+function dragElement(event)
+ {for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during drag)')}
+ }
+ if(event.dataTransfer.items.length > l)
+ {say('items.length (dragover) : FAIL' + event.dataTransfer.items.length)}
+ }
+function enterElement(event)
+ {event.preventDefault();
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during dragenter)')}
+ }
+ say('items.length (dragenter) : ' + ((event.dataTransfer.items.length < l)?'PASS':'FAIL'));}
+function dataDrop(event)
+ {say('items.length (drop) : ' + ((event.dataTransfer.items.length < l)?'PASS':'FAIL'));
+ for(var i = 0; i != dataTypes.length; i++)
+ {say('getData(' + dataTypes[i] + ') : ' + ((event.dataTransfer.getData(dataTypes[i]) == '')?'PASS':'FAIL'));}
+ document.querySelector('div').setAttribute('style','background-color:green');}
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+]]>
+</script>
+</head>
+<body>
+<p><a href="data:text/plain,1" ondragstart="start(event)" ondrag="dragElement(event)">Drag me</a></p>
+<p>Drag link above to the silver box below and drop it. Silver box should turn green and test results should appear below.</p>
+<div ondragenter="enterElement(event)" ondragover="return false;" ondrop="dataDrop(event)"/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/021.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/021.xhtml
new file mode 100644
index 00000000000..a32ce7280f1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/021.xhtml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>dataTransfer.clearData during block element drag and drop</title>
+<style type="text/css">
+div
+ {height:100px;
+ width:100px;
+ padding:20px;
+ background-color:green;}
+p + div
+ {background-color:gray;}
+</style>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text/plain', 'text/uri-list', 'application/xml', 'application/xhtml+xml', 'application/mathml+xml', 'image/svg+xml', 'text/html', 'text/x-example'],
+data = ['FAIL', 'data:text/plain,FAIL', '<result>FAIL</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>FAIL</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">FAIL</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>FAIL</p></body></html>', 'FAIL'],
+l = 0;
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ l = event.dataTransfer.items.length;
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], data[i]);}
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.clearData(dataTypes[i]);}
+ say('items.length (dragstart) : ' + ((event.dataTransfer.items.length < l)?'PASS':'FAIL'));}
+function dragElement(event)
+ {for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during drag)')}
+ }
+ if(event.dataTransfer.items.length > l)
+ {say('items.length (dragover) : FAIL' + event.dataTransfer.items.length)}
+ }
+function enterElement(event)
+ {event.preventDefault();
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during dragenter)')}
+ }
+ say('items.length (dragenter) : ' + ((event.dataTransfer.items.length < l)?'PASS':'FAIL'));}
+function dataDrop(event)
+ {say('items.length (drop) : ' + ((event.dataTransfer.items.length < l)?'PASS':'FAIL'));
+ for(var i = 0; i != dataTypes.length; i++)
+ {say('getData(' + dataTypes[i] + ') : ' + ((event.dataTransfer.getData(dataTypes[i]) == '')?'PASS':'FAIL'));}
+ document.querySelector('p + div').setAttribute('style','background-color:green');}
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+]]>
+</script>
+</head>
+<body>
+<div draggable="true" ondragstart="start(event)" ondrag="dragElement(event)"/>
+<p>Drag green box above to the navy box below and drop it. Navy box should turn green and test results should appear below.</p>
+<div ondragenter="enterElement(event)" ondragover="return false;" ondrop="dataDrop(event)"/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/022.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/022.xhtml
new file mode 100644
index 00000000000..1e1eb64ceb4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/022.xhtml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>dataTransfer.clearData during canvas drag and drop</title>
+<style type="text/css">
+div
+ {height:100px;
+ width:100px;
+ padding:20px;
+ background-color:silver;}
+</style>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text/plain', 'text/uri-list', 'application/xml', 'application/xhtml+xml', 'application/mathml+xml', 'image/svg+xml', 'text/html', 'text/x-example'],
+data = ['FAIL', 'data:text/plain,FAIL', '<result>FAIL</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>FAIL</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">FAIL</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>FAIL</p></body></html>', 'FAIL'],
+l = 0;
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ l = event.dataTransfer.items.length;
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], data[i]);}
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.clearData(dataTypes[i]);}
+ say('items.length (dragstart) : ' + ((event.dataTransfer.items.length < l)?'PASS':'FAIL'));}
+function dragElement(event)
+ {for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during drag)')}
+ }
+ if(event.dataTransfer.items.length > l)
+ {say('items.length (dragover) : FAIL' + event.dataTransfer.items.length)}
+ }
+function enterElement(event)
+ {event.preventDefault();
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during dragenter)')}
+ }
+ say('items.length (dragenter) : ' + ((event.dataTransfer.items.length < l)?'PASS':'FAIL'));}
+function dataDrop(event)
+ {say('items.length (drop) : ' + ((event.dataTransfer.items.length < l)?'PASS':'FAIL'));
+ for(var i = 0; i != dataTypes.length; i++)
+ {say('getData(' + dataTypes[i] + ') : ' + ((event.dataTransfer.getData(dataTypes[i]) == '')?'PASS':'FAIL'));}
+ document.querySelector('div').setAttribute('style','background-color:green');}
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+]]>
+</script>
+</head>
+<body>
+<p>
+ <canvas width="100" height="100" draggable="true" ondragstart="start(event)" ondrag="dragElement(event)">Canvas</canvas>
+</p>
+<p>Drag canvas pattern to the silver box below and drop it. Silver box should turn green and test results should appear below.</p>
+<div ondragenter="enterElement(event)" ondragover="return false;" ondrop="dataDrop(event)"/>
+<pre/>
+<script type="application/ecmascript">
+var canvas = document.querySelector('canvas'),
+c = canvas.getContext('2d');
+for(var x = 0; x != 50; x++)
+ {c.fillStyle = (x%2 == 0)?'navy':'white';
+ c.beginPath();
+ c.moveTo(x,x);
+ c.lineTo(100-x,x);
+ c.lineTo(100-x,100-x);
+ c.lineTo(x,100-x);
+ c.closePath();
+ c.fill();}
+data[1] = canvas.toDataURL('image/png');
+</script>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/023.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/023.xhtml
new file mode 100644
index 00000000000..bf58316e61b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/023.xhtml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>dataTransfer.clearData and reload during block element drag and drop</title>
+<style type="text/css">
+div
+ {height:100px;
+ width:100px;
+ padding:20px;
+ background-color:green;}
+p + div
+ {background-color:gray;}
+</style>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text/plain', 'text/uri-list', 'application/xml', 'application/xhtml+xml', 'application/mathml+xml', 'image/svg+xml', 'text/html', 'text/x-example'],
+data = ['FAIL', 'data:text/plain,FAIL', '<result>FAIL</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>FAIL</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">FAIL</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>FAIL</p></body></html>', 'FAIL'];
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], data[i]);}
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.clearData(dataTypes[i]);}
+ window.location.reload();}
+function dragElement(event)
+ {for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during drag)')}
+ }
+ }
+function enterElement(event)
+ {event.preventDefault();
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during dragenter)')}
+ }
+ }
+function dataDrop(event)
+ {for(var i = 0; i != dataTypes.length; i++)
+ {say('getData(' + dataTypes[i] + ') : ' + ((event.dataTransfer.getData(dataTypes[i]) == '')?'PASS':'FAIL'));}
+ document.querySelector('p + div').setAttribute('style','background-color:green');}
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+]]>
+</script>
+</head>
+<body>
+<div draggable="true" ondragstart="start(event)" ondrag="dragElement(event)"/>
+<p>Drag green box above to the navy box below and drop it. Navy box should turn green and test results should appear below.</p>
+<div ondragenter="enterElement(event)" ondragover="return false;" ondrop="dataDrop(event)"/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/024.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/024.xhtml
new file mode 100644
index 00000000000..5629bd746c5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/024.xhtml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Clear datastore data during PNG image drag and drop</title>
+<style type="text/css">
+div
+ {height:100px;
+ width:100px;
+ padding:20px;
+ background-color:silver;}
+</style>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text/uri-list', 'text/plain', 'application/xml', 'application/xhtml+xml', 'application/mathml+xml', 'image/svg+xml', 'text/html', 'text/x-example'],
+data = ['data:text/plain,FAIL', 'FAIL', '<result>FAIL</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>FAIL</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">FAIL</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>FAIL</p></body></html>', 'FAIL'];
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ l = event.dataTransfer.items.length;
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], data[i]);}
+ event.dataTransfer.clearData();
+ say('items.length (dragstart) : ' + ((event.dataTransfer.items.length == 0)?'PASS':'FAIL'));}
+function dragElement(event)
+ {for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during drag)')}
+ }
+ if(event.dataTransfer.items.length != 0)
+ {say('items.length (dragover) : FAIL')}
+ }
+function enterElement(event)
+ {event.preventDefault();
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during dragenter)')}
+ }
+ say('items.length (dragenter) : ' + ((event.dataTransfer.items.length == 0)?'PASS':'FAIL'));}
+function dataDrop(event)
+ {say('items.length (drop) : ' + ((event.dataTransfer.items.length == 0)?'PASS':'FAIL'));
+ for(var i = 0; i != dataTypes.length; i++)
+ {say('getData(' + dataTypes[i] + ') : ' + ((event.dataTransfer.getData(dataTypes[i]) == '')?'PASS':'FAIL'));}
+ document.querySelector('div').setAttribute('style','background-color:green');}
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+]]>
+</script>
+</head>
+<body>
+<p><img ondragstart="start(event)" ondrag="dragElement(event)" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAEq0lEQVR42u1dvU4bQRAeR0RCCilSp0peIoKGB4DSXYRDlcZlFClKBI4bB/kV/AymIDwCTahiicaioEOxhCsjWVTJziyKMfYZn+9ud3bvG2mEZB13u9+nndmf2Rki7fKFXtEBbVKD9o22jB4bPaND6hm9Mjo0enevw/vfevKMfbYl/8vv4HdBUkvFALhltG2A7dN3+pur8jv53fwN/hZkjjRo3eiuAatjdJA7CcnkDOSb/G1uQ6mFzUeDagaQrvl764yEJOU22LbUymXaGrRhOt40OvJOQvLIGUkbP9GLeIn4SM9NJ+tOTVI+Jq0ubY9sVFRNxy6DIWKWmEvpQ/ByQNumI+fBEjHrZ86lT8HJV3ptGn8aDRGzxJxKHwMZFe9Mg6+jJWNCyrX0VbUc0nuj4+jJmPiWsfRZodN+ZvSoNETMjpYjwUCFfKaXpjEnpSVjQsqJYOF5ZLw1elF6MiakXAgmnpw378DegIgZUm4EGw8jA2QsIuUbvXHpM2CmljFfhfsUO5uCA0/j6AudfZV5arv6WuVHcYs+ALwqKTkvHnmLoEwr8CJW9Llts9iNwvj3plzsfeWyIRnzrq37kfIzq6naBpA5a6bzlJgOl/SMkl+rklEFgIX5k5THwTYgIdwzcP2jhM/o19KsOeoArnBS6suaqo2gQnXCJWSwXNwXB4gBMFekNBeTwSGUmiMK4yNktDhsleNaAZRrUvYWmasuQHJOSDdpdKyriEIvo9maexWC70gAIF/bKTvzzFUH4HgbJZ3HdFSw9vC6lfKHpq7X8X07AOOblK2HhLQBindC2g/9Rx+gePcj/cnqHIDoUFm1c9gjwNAy/d0kyXIAMLSYrQ8kqScAhhbH3iLJBwIwtBByTJKkBWBoIeSMJHMOwNBCyG+SdEYAQ4tTvyLJMQUwtBAyJEn8BTC0EHIHQhQSApOlzGTBqaty6jzVAhhaCOlhYahuYYitE02EHGNzURchLZItX4ChhZB9HFBpUjmgwhGuHv0feI0gBw1T3j7CgHT5jzYC5XQRsjUdSsrhjADGl7ka0EylBgRb+ySkMy9rww7A8Waududf2MH9Qh9k3CbXLsGVNh/mqrvojuEeQHI+Qmq4Fq1ndIyeruaDxAEuCWk+ncmB0z3gepubtQenMUHyGTWELJl8xk6B15CeqVAyLtPXtUICsyJnVivWs+J0dAAwbzLOkQRTk2YuKsapTQFkXqPjlDILEinnRcZ1fpXdkGo866xqnH9FNyTjz0JIQZXcuPQCAE5rqo6oMEFBl7RknBRfTg8lj5Yl48JdGT0ueIWiYIvIuHFfPg9l85LJcF42b+JTUFjysZnyVlhy2qfA0asovTo9+0JxYnWC8t0KBQXuFYrdkIy3mBj3LbeNQrejZTuqOlbcl8znGTqcfjXoM3pboqgaPhEPxda1qgcVYsRt5TanDkgISWzcV1N1hCS3jdu4dNxUDMIhlBzXysHGGspkcBtsW2pPh3fGLrZ2ya5cXHFp0qxJ6si3E68EQCpy344vQRZxO5jfye+2d/oqgHsV02Z3lvcl9QTnA+EkLZw5h9MZcY4pTvxldXj/W0+esc+25H/5HQGYon+Q5f+MwFz+8QAAAABJRU5ErkJggg==" alt="PNG circle"/></p>
+<p>Drag circle above to the silver box below and drop it. Silver box should turn green and test results should appear below.</p>
+<div ondragenter="enterElement(event)" ondragover="return false;" ondrop="dataDrop(event)"/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/025.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/025.xhtml
new file mode 100644
index 00000000000..7ac04e6e31f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/025.xhtml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Clear datastore data during SVG image drag and drop</title>
+<style type="text/css">
+div
+ {height:100px;
+ width:100px;
+ padding:20px;
+ background-color:silver;}
+</style>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text/uri-list', 'text/plain', 'application/xml', 'application/xhtml+xml', 'application/mathml+xml', 'image/svg+xml', 'text/html', 'text/x-example'],
+data = ['data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20version%3D%221.1%22%20width%3D%22100px%22%20height%3D%22100px%22%20viewBox%3D%220%200%20100%20100%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22green%22/%3E%3C/svg%3E', 'FAIL', '<result>FAIL</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>FAIL</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">FAIL</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>FAIL</p></body></html>', 'FAIL'];
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ l = event.dataTransfer.items.length;
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], data[i]);}
+ event.dataTransfer.clearData();
+ say('items.length (dragstart) : ' + ((event.dataTransfer.items.length == 0)?'PASS':'FAIL'));}
+function dragElement(event)
+ {for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during drag)')}
+ }
+ if(event.dataTransfer.items.length != 0)
+ {say('items.length (dragover) : FAIL')}
+ }
+function enterElement(event)
+ {event.preventDefault();
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during dragenter)')}
+ }
+ say('items.length (dragenter) : ' + ((event.dataTransfer.items.length == 0)?'PASS':'FAIL'));}
+function dataDrop(event)
+ {say('items.length (drop) : ' + ((event.dataTransfer.items.length == 0)?'PASS':'FAIL'));
+ for(var i = 0; i != dataTypes.length; i++)
+ {say('getData(' + dataTypes[i] + ') : ' + ((event.dataTransfer.getData(dataTypes[i]) == '')?'PASS':'FAIL'));}
+ document.querySelector('div').setAttribute('style','background-color:green');}
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+]]>
+</script>
+</head>
+<body>
+<p><img ondragstart="start(event)" ondrag="dragElement(event)" src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20version%3D%221.1%22%20width%3D%22100px%22%20height%3D%22100px%22%20viewBox%3D%220%200%20100%20100%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22green%22/%3E%3C/svg%3E" alt="SVG circle"/></p>
+<p>Drag circle above to the silver box below and drop it. Silver box should turn green and test results should appear below.</p>
+<div ondragenter="enterElement(event)" ondragover="return false;" ondrop="dataDrop(event)"/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/026.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/026.xhtml
new file mode 100644
index 00000000000..8b2fd371406
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/026.xhtml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Clear datastore data during text input selection drag and drop</title>
+<style type="text/css">
+div
+ {min-height:100px;
+ width:100px;
+ padding:20px;
+ color:white;
+ background-color:navy;}
+</style>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text/plain', 'text/uri-list', 'application/xml', 'application/xhtml+xml', 'application/mathml+xml', 'image/svg+xml', 'text/html', 'text/x-example'],
+data = ['FAIL', 'data:text/plain,FAIL', '<result>FAIL</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>FAIL</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">FAIL</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>FAIL</p></body></html>', 'FAIL'];
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ l = event.dataTransfer.items.length;
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], data[i]);}
+ event.dataTransfer.clearData();
+ say('items.length (dragstart) : ' + ((event.dataTransfer.items.length == 0)?'PASS':'FAIL'));}
+function dragElement(event)
+ {for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during drag)')}
+ }
+ if(event.dataTransfer.items.length != 0)
+ {say('items.length (dragover) : FAIL')}
+ }
+function enterElement(event)
+ {event.preventDefault();
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during dragenter)')}
+ }
+ say('items.length (dragenter) : ' + ((event.dataTransfer.items.length == 0)?'PASS':'FAIL'));}
+function dataDrop(event)
+ {say('items.length (drop) : ' + ((event.dataTransfer.items.length == 0)?'PASS':'FAIL'));
+ for(var i = 0; i != dataTypes.length; i++)
+ {say('getData(' + dataTypes[i] + ') : ' + ((event.dataTransfer.getData(dataTypes[i]) == '')?'PASS':'FAIL'));}
+ document.querySelector('div').setAttribute('style','background-color:green');}
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+]]>
+</script>
+</head>
+<body onload="document.querySelector('input').select()">
+<p><input value="Drag me" ondragstart="start(event)" ondrag="dragElement(event)"/></p>
+<p>Drag selection above to the navy box below and drop it. Navy box should turn green and test results should appear below.</p>
+<div ondragenter="enterElement(event)" ondragover="return false;" ondrop="dataDrop(event)"/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/027.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/027.xhtml
new file mode 100644
index 00000000000..ecd57b3acef
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/027.xhtml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Clear datastore data during selection drag and drop</title>
+<style type="text/css">
+div
+ {min-height:100px;
+ width:100px;
+ padding:20px;
+ color:white;
+ background-color:navy;}
+</style>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text/plain', 'text/uri-list', 'application/xml', 'application/xhtml+xml', 'application/mathml+xml', 'image/svg+xml', 'text/html', 'text/x-example'],
+data = ['FAIL', 'data:text/plain,FAIL', '<result>FAIL</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>FAIL</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">FAIL</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>FAIL</p></body></html>', 'FAIL'],
+l = 0;
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ l = event.dataTransfer.items.length;
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], data[i]);}
+ event.dataTransfer.clearData();
+ say('items.length (dragstart) : ' + ((event.dataTransfer.items.length == 0)?'PASS':'FAIL'));}
+function dragElement(event)
+ {for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during drag)')}
+ }
+ if(event.dataTransfer.items.length != 0)
+ {say('items.length (dragover) : FAIL')}
+ }
+function enterElement(event)
+ {event.preventDefault();
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during dragenter)')}
+ }
+ say('items.length (dragenter) : ' + ((event.dataTransfer.items.length == 0)?'PASS':'FAIL'));}
+function dataDrop(event)
+ {say('items.length (drop) : ' + ((event.dataTransfer.items.length == 0)?'PASS':'FAIL'));
+ for(var i = 0; i != dataTypes.length; i++)
+ {say('getData(' + dataTypes[i] + ') : ' + ((event.dataTransfer.getData(dataTypes[i]) == '')?'PASS':'FAIL'));}
+ document.querySelector('div').setAttribute('style','background-color:green');}
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+]]>
+</script>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('span'))">
+<p><span ondragstart="start(event)" ondrag="dragElement(event)">Drag me</span></p>
+<p>Drag selection above to the navy box below and drop it. Navy box should turn green and test results should appear below.</p>
+<div ondragenter="enterElement(event)" ondragover="return false;" ondrop="dataDrop(event)"/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/028.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/028.xhtml
new file mode 100644
index 00000000000..e6aec005ea3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/028.xhtml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Clear datastore data during link drag and drop</title>
+<style type="text/css">
+div
+ {height:100px;
+ width:100px;
+ padding:20px;
+ background-color:silver;}
+</style>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text/uri-list', 'text/plain', 'application/xml', 'application/xhtml+xml', 'application/mathml+xml', 'image/svg+xml', 'text/html', 'text/x-example'],
+data = ['data:text/plain,FAIL', 'FAIL', '<result>FAIL</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>FAIL</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">FAIL</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>FAIL</p></body></html>', 'FAIL'];
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], data[i]);}
+ say('items.length (dragstart) : ' + ((event.dataTransfer.items.length >= dataTypes.length)?'PASS':'FAIL'));
+ }
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ l = event.dataTransfer.items.length;
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], data[i]);}
+ event.dataTransfer.clearData();
+ say('items.length (dragstart) : ' + ((event.dataTransfer.items.length == 0)?'PASS':'FAIL'));}
+function dragElement(event)
+ {for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during drag)')}
+ }
+ if(event.dataTransfer.items.length != 0)
+ {say('items.length (dragover) : FAIL')}
+ }
+function enterElement(event)
+ {event.preventDefault();
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during dragenter)')}
+ }
+ say('items.length (dragenter) : ' + ((event.dataTransfer.items.length == 0)?'PASS':'FAIL'));}
+function dataDrop(event)
+ {say('items.length (drop) : ' + ((event.dataTransfer.items.length == 0)?'PASS':'FAIL'));
+ for(var i = 0; i != dataTypes.length; i++)
+ {say('getData(' + dataTypes[i] + ') : ' + ((event.dataTransfer.getData(dataTypes[i]) == '')?'PASS':'FAIL'));}
+ document.querySelector('div').setAttribute('style','background-color:green');}
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+]]>
+</script>
+</head>
+<body>
+<p><a href="data:text/plain,1" ondragstart="start(event)" ondrag="dragElement(event)">Drag me</a></p>
+<p>Drag link above to the silver box below and drop it. Silver box should turn green and test results should appear below.</p>
+<div ondragenter="enterElement(event)" ondragover="return false;" ondrop="dataDrop(event)"/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/029.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/029.xhtml
new file mode 100644
index 00000000000..e8471a19878
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/029.xhtml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Clear datastore data during block element drag and drop</title>
+<style type="text/css">
+div
+ {height:100px;
+ width:100px;
+ padding:20px;
+ background-color:green;}
+p + div
+ {background-color:gray;}
+</style>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text/plain', 'text/uri-list', 'application/xml', 'application/xhtml+xml', 'application/mathml+xml', 'image/svg+xml', 'text/html', 'text/x-example'],
+data = ['FAIL', 'data:text/plain,FAIL', '<result>FAIL</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>FAIL</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">FAIL</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>FAIL</p></body></html>', 'FAIL'];
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ l = event.dataTransfer.items.length;
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], data[i]);}
+ event.dataTransfer.clearData();
+ say('items.length (dragstart) : ' + ((event.dataTransfer.items.length == 0)?'PASS':'FAIL'));}
+function dragElement(event)
+ {for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during drag)')}
+ }
+ if(event.dataTransfer.items.length != 0)
+ {say('items.length (dragover) : FAIL')}
+ }
+function enterElement(event)
+ {event.preventDefault();
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during dragenter)')}
+ }
+ say('items.length (dragenter) : ' + ((event.dataTransfer.items.length == 0)?'PASS':'FAIL'));}
+function dataDrop(event)
+ {say('items.length (drop) : ' + ((event.dataTransfer.items.length == 0)?'PASS':'FAIL'));
+ for(var i = 0; i != dataTypes.length; i++)
+ {say('getData(' + dataTypes[i] + ') : ' + ((event.dataTransfer.getData(dataTypes[i]) == '')?'PASS':'FAIL'));}
+ document.querySelector('p + div').setAttribute('style','background-color:green');}
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+]]>
+</script>
+</head>
+<body>
+<div draggable="true" ondragstart="start(event)" ondrag="dragElement(event)"/>
+<p>Drag green box above to the navy box below and drop it. Navy box should turn green and test results should appear below.</p>
+<div ondragenter="enterElement(event)" ondragover="return false;" ondrop="dataDrop(event)"/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/030.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/030.xhtml
new file mode 100644
index 00000000000..31263c3f53b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/030.xhtml
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Clear datastore data during canvas drag and drop</title>
+<style type="text/css">
+div
+ {height:100px;
+ width:100px;
+ padding:20px;
+ background-color:silver;}
+</style>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text/plain', 'text/uri-list', 'application/xml', 'application/xhtml+xml', 'application/mathml+xml', 'image/svg+xml', 'text/html', 'text/x-example'],
+data = ['FAIL', 'data:text/plain,FAIL', '<result>FAIL</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>FAIL</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">FAIL</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>FAIL</p></body></html>', 'FAIL'];
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ l = event.dataTransfer.items.length;
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], data[i]);}
+ event.dataTransfer.clearData();
+ say('items.length (dragstart) : ' + ((event.dataTransfer.items.length == 0)?'PASS':'FAIL'));}
+function dragElement(event)
+ {for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during drag)')}
+ }
+ if(event.dataTransfer.items.length != 0)
+ {say('items.length (dragover) : FAIL')}
+ }
+function enterElement(event)
+ {event.preventDefault();
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during dragenter)')}
+ }
+ say('items.length (dragenter) : ' + ((event.dataTransfer.items.length == 0)?'PASS':'FAIL'));}
+function dataDrop(event)
+ {say('items.length (drop) : ' + ((event.dataTransfer.items.length == 0)?'PASS':'FAIL'));
+ for(var i = 0; i != dataTypes.length; i++)
+ {say('getData(' + dataTypes[i] + ') : ' + ((event.dataTransfer.getData(dataTypes[i]) == '')?'PASS':'FAIL'));}
+ document.querySelector('div').setAttribute('style','background-color:green');}
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+]]>
+</script>
+</head>
+<body>
+<p>
+ <canvas width="100" height="100" draggable="true" ondragstart="start(event)" ondrag="dragElement(event)">Canvas</canvas>
+</p>
+<p>Drag canvas pattern to the silver box below and drop it. Silver box should turn green and test results should appear below.</p>
+<div ondragenter="enterElement(event)" ondragover="return false;" ondrop="dataDrop(event)"/>
+<pre/>
+<script type="application/ecmascript">
+var canvas = document.querySelector('canvas'),
+c = canvas.getContext('2d');
+for(var x = 0; x != 50; x++)
+ {c.fillStyle = (x%2 == 0)?'navy':'white';
+ c.beginPath();
+ c.moveTo(x,x);
+ c.lineTo(100-x,x);
+ c.lineTo(100-x,100-x);
+ c.lineTo(x,100-x);
+ c.closePath();
+ c.fill();}
+data[1] = canvas.toDataURL('image/png');
+</script>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/031.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/031.xhtml
new file mode 100644
index 00000000000..a275fcb748c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/031.xhtml
@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>dataTransfer.items during canvas drag and drop</title>
+<style type="text/css">
+div
+ {height:100px;
+ width:100px;
+ padding:20px;
+ background-color:silver;}
+</style>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text/plain', 'text/uri-list', 'application/xml', 'application/xhtml+xml', 'application/mathml+xml', 'image/svg+xml', 'text/html', 'text/x-example'],
+data = ['PASS', 'data:text/plain,1', '<result>PASS</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>PASS</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">PASS</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>PASS</p></body></html>', 'PASS'],
+e = 0, result = true;
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], data[i]);}
+ for(var i = event.dataTransfer.items.length; i != 0; i--)
+ {if(dataTypes.indexOf(event.dataTransfer.items[i-1].type) == -1)
+ {delete event.dataTransfer.items[i-1]}
+ }
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragstart) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragstart): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragstart): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0] != data[e++])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should pass' + data[e] + ')')}
+ }
+ );
+ }
+ }
+function dragElement(event)
+ {event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondrag) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondrag): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondrag): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to drag event handler)')}
+ }
+ );
+ }
+ }
+function enterElement(event)
+ {event.preventDefault();
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragenter) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {delete event.dataTransfer.items[i];
+ if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragenter): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragenter): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to drag event handler)')}
+ }
+ );
+ }
+ }
+function overElement(event)
+ {event.preventDefault();
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragover) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragover): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragover): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to dragover event handler)')}
+ }
+ );
+ }
+ }
+function dataDrop(event)
+ {e = 0;
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondrop) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {delete event.dataTransfer.items[i];
+ if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondrop): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondrop): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0] != data[e++])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should pass' + data[e] + ')')}
+ }
+ );
+ }
+ document.querySelector('div').setAttribute('style','background-color:' + (result?'green':'red'));}
+function say(it)
+ {result = false;
+ document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+]]>
+</script>
+</head>
+<body>
+<p>
+ <canvas width="100" height="100" draggable="true" ondragstart="start(event)" ondrag="dragElement(event)">Canvas</canvas>
+</p>
+<p>Drag canvas pattern to the silver box below and drop it. Silver box should turn green.</p>
+<div ondragenter="enterElement(event)" ondragover="overElement(event)" ondrop="dataDrop(event)"/>
+<pre/>
+<script type="application/ecmascript">
+var canvas = document.querySelector('canvas'),
+c = canvas.getContext('2d');
+for(var x = 0; x != 50; x++)
+ {c.fillStyle = (x%2 == 0)?'navy':'white';
+ c.beginPath();
+ c.moveTo(x,x);
+ c.lineTo(100-x,x);
+ c.lineTo(100-x,100-x);
+ c.lineTo(x,100-x);
+ c.closePath();
+ c.fill();}
+data[1] = canvas.toDataURL('image/png');
+</script>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/032.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/032.xhtml
new file mode 100644
index 00000000000..9aca2959767
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/032.xhtml
@@ -0,0 +1,125 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>dataTransfer.items during PNG image drag and drop</title>
+<style type="text/css">
+div
+ {height:100px;
+ width:100px;
+ padding:20px;
+ background-color:silver;}
+</style>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text/uri-list', 'text/plain', 'application/xml', 'application/xhtml+xml', 'application/mathml+xml', 'image/svg+xml', 'text/html', 'text/x-example'],
+data = ['data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAEq0lEQVR42u1dvU4bQRAeR0RCCilSp0peIoKGB4DSXYRDlcZlFClKBI4bB/kV/AymIDwCTahiicaioEOxhCsjWVTJziyKMfYZn+9ud3bvG2mEZB13u9+nndmf2Rki7fKFXtEBbVKD9o22jB4bPaND6hm9Mjo0enevw/vfevKMfbYl/8vv4HdBUkvFALhltG2A7dN3+pur8jv53fwN/hZkjjRo3eiuAatjdJA7CcnkDOSb/G1uQ6mFzUeDagaQrvl764yEJOU22LbUymXaGrRhOt40OvJOQvLIGUkbP9GLeIn4SM9NJ+tOTVI+Jq0ubY9sVFRNxy6DIWKWmEvpQ/ByQNumI+fBEjHrZ86lT8HJV3ptGn8aDRGzxJxKHwMZFe9Mg6+jJWNCyrX0VbUc0nuj4+jJmPiWsfRZodN+ZvSoNETMjpYjwUCFfKaXpjEnpSVjQsqJYOF5ZLw1elF6MiakXAgmnpw378DegIgZUm4EGw8jA2QsIuUbvXHpM2CmljFfhfsUO5uCA0/j6AudfZV5arv6WuVHcYs+ALwqKTkvHnmLoEwr8CJW9Llts9iNwvj3plzsfeWyIRnzrq37kfIzq6naBpA5a6bzlJgOl/SMkl+rklEFgIX5k5THwTYgIdwzcP2jhM/o19KsOeoArnBS6suaqo2gQnXCJWSwXNwXB4gBMFekNBeTwSGUmiMK4yNktDhsleNaAZRrUvYWmasuQHJOSDdpdKyriEIvo9maexWC70gAIF/bKTvzzFUH4HgbJZ3HdFSw9vC6lfKHpq7X8X07AOOblK2HhLQBindC2g/9Rx+gePcj/cnqHIDoUFm1c9gjwNAy/d0kyXIAMLSYrQ8kqScAhhbH3iLJBwIwtBByTJKkBWBoIeSMJHMOwNBCyG+SdEYAQ4tTvyLJMQUwtBAyJEn8BTC0EHIHQhQSApOlzGTBqaty6jzVAhhaCOlhYahuYYitE02EHGNzURchLZItX4ChhZB9HFBpUjmgwhGuHv0feI0gBw1T3j7CgHT5jzYC5XQRsjUdSsrhjADGl7ka0EylBgRb+ySkMy9rww7A8Waududf2MH9Qh9k3CbXLsGVNh/mqrvojuEeQHI+Qmq4Fq1ndIyeruaDxAEuCWk+ncmB0z3gepubtQenMUHyGTWELJl8xk6B15CeqVAyLtPXtUICsyJnVivWs+J0dAAwbzLOkQRTk2YuKsapTQFkXqPjlDILEinnRcZ1fpXdkGo866xqnH9FNyTjz0JIQZXcuPQCAE5rqo6oMEFBl7RknBRfTg8lj5Yl48JdGT0ueIWiYIvIuHFfPg9l85LJcF42b+JTUFjysZnyVlhy2qfA0asovTo9+0JxYnWC8t0KBQXuFYrdkIy3mBj3LbeNQrejZTuqOlbcl8znGTqcfjXoM3pboqgaPhEPxda1qgcVYsRt5TanDkgISWzcV1N1hCS3jdu4dNxUDMIhlBzXysHGGspkcBtsW2pPh3fGLrZ2ya5cXHFp0qxJ6si3E68EQCpy344vQRZxO5jfye+2d/oqgHsV02Z3lvcl9QTnA+EkLZw5h9MZcY4pTvxldXj/W0+esc+25H/5HQGYon+Q5f+MwFz+8QAAAABJRU5ErkJggg==', 'PASS', '<result>PASS</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>PASS</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">PASS</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>PASS</p></body></html>', 'PASS'],
+e = 0, result = true;
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], data[i]);}
+ for(var i = event.dataTransfer.items.length; i != 0; i--)
+ {if(dataTypes.indexOf(event.dataTransfer.items[i-1].type) == -1)
+ {delete event.dataTransfer.items[i-1]}
+ }
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragstart) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragstart): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragstart): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0] != data[e++])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should pass' + data[e] + ')')}
+ }
+ );
+ }
+ }
+function dragElement(event)
+ {event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondrag) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondrag): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondrag): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to drag event handler)')}
+ }
+ );
+ }
+ }
+function enterElement(event)
+ {event.preventDefault();
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragenter) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {delete event.dataTransfer.items[i];
+ if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragenter): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragenter): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to drag event handler)')}
+ }
+ );
+ }
+ }
+function overElement(event)
+ {event.preventDefault();
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragover) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragover): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragover): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to dragover event handler)')}
+ }
+ );
+ }
+ }
+function dataDrop(event)
+ {e = 0;
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondrop) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {delete event.dataTransfer.items[i];
+ if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondrop): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondrop): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0] != data[e++])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should pass' + data[e] + ')')}
+ }
+ );
+ }
+ document.querySelector('div').setAttribute('style','background-color:' + (result?'green':'red'));}
+function say(it)
+ {result = false;
+ document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+]]>
+</script>
+</head>
+<body>
+<p><img ondragstart="start(event)" ondrag="dragElement(event)" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAEq0lEQVR42u1dvU4bQRAeR0RCCilSp0peIoKGB4DSXYRDlcZlFClKBI4bB/kV/AymIDwCTahiicaioEOxhCsjWVTJziyKMfYZn+9ud3bvG2mEZB13u9+nndmf2Rki7fKFXtEBbVKD9o22jB4bPaND6hm9Mjo0enevw/vfevKMfbYl/8vv4HdBUkvFALhltG2A7dN3+pur8jv53fwN/hZkjjRo3eiuAatjdJA7CcnkDOSb/G1uQ6mFzUeDagaQrvl764yEJOU22LbUymXaGrRhOt40OvJOQvLIGUkbP9GLeIn4SM9NJ+tOTVI+Jq0ubY9sVFRNxy6DIWKWmEvpQ/ByQNumI+fBEjHrZ86lT8HJV3ptGn8aDRGzxJxKHwMZFe9Mg6+jJWNCyrX0VbUc0nuj4+jJmPiWsfRZodN+ZvSoNETMjpYjwUCFfKaXpjEnpSVjQsqJYOF5ZLw1elF6MiakXAgmnpw378DegIgZUm4EGw8jA2QsIuUbvXHpM2CmljFfhfsUO5uCA0/j6AudfZV5arv6WuVHcYs+ALwqKTkvHnmLoEwr8CJW9Llts9iNwvj3plzsfeWyIRnzrq37kfIzq6naBpA5a6bzlJgOl/SMkl+rklEFgIX5k5THwTYgIdwzcP2jhM/o19KsOeoArnBS6suaqo2gQnXCJWSwXNwXB4gBMFekNBeTwSGUmiMK4yNktDhsleNaAZRrUvYWmasuQHJOSDdpdKyriEIvo9maexWC70gAIF/bKTvzzFUH4HgbJZ3HdFSw9vC6lfKHpq7X8X07AOOblK2HhLQBindC2g/9Rx+gePcj/cnqHIDoUFm1c9gjwNAy/d0kyXIAMLSYrQ8kqScAhhbH3iLJBwIwtBByTJKkBWBoIeSMJHMOwNBCyG+SdEYAQ4tTvyLJMQUwtBAyJEn8BTC0EHIHQhQSApOlzGTBqaty6jzVAhhaCOlhYahuYYitE02EHGNzURchLZItX4ChhZB9HFBpUjmgwhGuHv0feI0gBw1T3j7CgHT5jzYC5XQRsjUdSsrhjADGl7ka0EylBgRb+ySkMy9rww7A8Waududf2MH9Qh9k3CbXLsGVNh/mqrvojuEeQHI+Qmq4Fq1ndIyeruaDxAEuCWk+ncmB0z3gepubtQenMUHyGTWELJl8xk6B15CeqVAyLtPXtUICsyJnVivWs+J0dAAwbzLOkQRTk2YuKsapTQFkXqPjlDILEinnRcZ1fpXdkGo866xqnH9FNyTjz0JIQZXcuPQCAE5rqo6oMEFBl7RknBRfTg8lj5Yl48JdGT0ueIWiYIvIuHFfPg9l85LJcF42b+JTUFjysZnyVlhy2qfA0asovTo9+0JxYnWC8t0KBQXuFYrdkIy3mBj3LbeNQrejZTuqOlbcl8znGTqcfjXoM3pboqgaPhEPxda1qgcVYsRt5TanDkgISWzcV1N1hCS3jdu4dNxUDMIhlBzXysHGGspkcBtsW2pPh3fGLrZ2ya5cXHFp0qxJ6si3E68EQCpy344vQRZxO5jfye+2d/oqgHsV02Z3lvcl9QTnA+EkLZw5h9MZcY4pTvxldXj/W0+esc+25H/5HQGYon+Q5f+MwFz+8QAAAABJRU5ErkJggg==" alt="PNG circle"/></p>
+<p>Drag circle above to the silver box below and drop it. Silver box should turn green.</p>
+<div ondragenter="enterElement(event)" ondragover="overElement(event)" ondrop="dataDrop(event)"/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/033.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/033.xhtml
new file mode 100644
index 00000000000..d7aa67d3a32
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/033.xhtml
@@ -0,0 +1,125 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>dataTransfer.items during SVG image drag and drop</title>
+<style type="text/css">
+div
+ {height:100px;
+ width:100px;
+ padding:20px;
+ background-color:silver;}
+</style>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text/uri-list', 'text/plain', 'application/xml', 'application/xhtml+xml', 'application/mathml+xml', 'image/svg+xml', 'text/html', 'text/x-example'],
+data = ['data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20version%3D%221.1%22%20width%3D%22100px%22%20height%3D%22100px%22%20viewBox%3D%220%200%20100%20100%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22green%22/%3E%3C/svg%3E', 'PASS', '<result>PASS</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>PASS</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">PASS</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>PASS</p></body></html>', 'PASS'],
+e = 0, result = true;
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], data[i]);}
+ for(var i = event.dataTransfer.items.length; i != 0; i--)
+ {if(dataTypes.indexOf(event.dataTransfer.items[i-1].type) == -1)
+ {delete event.dataTransfer.items[i-1]}
+ }
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragstart) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragstart): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragstart): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0] != data[e++])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should pass' + data[e] + ')')}
+ }
+ );
+ }
+ }
+function dragElement(event)
+ {event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondrag) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondrag): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondrag): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to drag event handler)')}
+ }
+ );
+ }
+ }
+function enterElement(event)
+ {event.preventDefault();
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragenter) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {delete event.dataTransfer.items[i];
+ if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragenter): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragenter): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to drag event handler)')}
+ }
+ );
+ }
+ }
+function overElement(event)
+ {event.preventDefault();
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragover) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragover): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragover): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to dragover event handler)')}
+ }
+ );
+ }
+ }
+function dataDrop(event)
+ {e = 0;
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondrop) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {delete event.dataTransfer.items[i];
+ if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondrop): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondrop): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0] != data[e++])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should pass' + data[e] + ')')}
+ }
+ );
+ }
+ document.querySelector('div').setAttribute('style','background-color:' + (result?'green':'red'));}
+function say(it)
+ {result = false;
+ document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+]]>
+</script>
+</head>
+<body>
+<p><img ondragstart="start(event)" ondrag="dragElement(event)" src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20version%3D%221.1%22%20width%3D%22100px%22%20height%3D%22100px%22%20viewBox%3D%220%200%20100%20100%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22green%22/%3E%3C/svg%3E" alt="SVG circle"/></p>
+<p>Drag circle above to the silver box below and drop it. Silver box should turn green.</p>
+<div ondragenter="enterElement(event)" ondragover="overElement(event)" ondrop="dataDrop(event)"/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/034.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/034.xhtml
new file mode 100644
index 00000000000..1eeb227fc11
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/034.xhtml
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>dataTransfer.items during text input selection drag and drop</title>
+<style type="text/css">
+div
+ {min-height:100px;
+ width:100px;
+ padding:20px;
+ color:white;
+ background-color:navy;}
+</style>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text/plain', 'text/uri-list', 'application/xml', 'application/xhtml+xml', 'application/mathml+xml', 'image/svg+xml', 'text/html', 'text/x-example'],
+data = ['Drag me', 'data:text/plain,1', '<result>PASS</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>PASS</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">PASS</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>PASS</p></body></html>', 'PASS'];
+e = 0, result = true;
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], data[i]);}
+ for(var i = event.dataTransfer.items.length; i != 0; i--)
+ {if(dataTypes.indexOf(event.dataTransfer.items[i-1].type) == -1)
+ {delete event.dataTransfer.items[i-1]}
+ }
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragstart) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragstart): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragstart): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0] != data[e++])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should pass' + data[e] + ')')}
+ }
+ );
+ }
+ }
+function dragElement(event)
+ {event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondrag) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondrag): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondrag): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to drag event handler)')}
+ }
+ );
+ }
+ }
+function enterElement(event)
+ {event.preventDefault();
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragenter) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {delete event.dataTransfer.items[i];
+ if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragenter): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragenter): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to drag event handler)')}
+ }
+ );
+ }
+ }
+function overElement(event)
+ {event.preventDefault();
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragover) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragover): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragover): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to dragover event handler)')}
+ }
+ );
+ }
+ }
+function dataDrop(event)
+ {e = 0;
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondrop) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {delete event.dataTransfer.items[i];
+ if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondrop): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondrop): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0] != data[e++])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should pass' + data[e] + ')')}
+ }
+ );
+ }
+ document.querySelector('div').setAttribute('style','background-color:' + (result?'green':'red'));}
+function say(it)
+ {result = false;
+ document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+]]>
+</script>
+</head>
+<body onload="document.querySelector('input').select()">
+<p><input value="Drag me" ondragstart="start(event)" ondrag="dragElement(event)"/></p>
+<p>Drag selection above to the navy box below and drop it. Navy box should turn green.</p>
+<div ondragenter="enterElement(event)" ondragover="overElement(event)" ondrop="dataDrop(event)"/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/035.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/035.xhtml
new file mode 100644
index 00000000000..797f7669e30
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/035.xhtml
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>dataTransfer.items during selection drag and drop</title>
+<style type="text/css">
+div
+ {min-height:100px;
+ width:100px;
+ padding:20px;
+ color:white;
+ background-color:navy;}
+</style>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text/plain', 'text/uri-list', 'application/xml', 'application/xhtml+xml', 'application/mathml+xml', 'image/svg+xml', 'text/html', 'text/x-example'],
+data = ['Drag me', 'data:text/plain,1', '<result>PASS</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>PASS</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">PASS</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>PASS</p></body></html>', 'PASS'];
+e = 0, result = true;
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], data[i]);}
+ for(var i = event.dataTransfer.items.length; i != 0; i--)
+ {if(dataTypes.indexOf(event.dataTransfer.items[i-1].type) == -1)
+ {delete event.dataTransfer.items[i-1]}
+ }
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragstart) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragstart): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragstart): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0] != data[e++])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should pass' + data[e] + ')')}
+ }
+ );
+ }
+ }
+function dragElement(event)
+ {event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondrag) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondrag): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondrag): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to drag event handler)')}
+ }
+ );
+ }
+ }
+function enterElement(event)
+ {event.preventDefault();
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragenter) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {delete event.dataTransfer.items[i];
+ if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragenter): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragenter): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to drag event handler)')}
+ }
+ );
+ }
+ }
+function overElement(event)
+ {event.preventDefault();
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragover) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragover): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragover): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to dragover event handler)')}
+ }
+ );
+ }
+ }
+function dataDrop(event)
+ {e = 0;
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondrop) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {delete event.dataTransfer.items[i];
+ if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondrop): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondrop): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0] != data[e++])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should pass' + data[e] + ')')}
+ }
+ );
+ }
+ document.querySelector('div').setAttribute('style','background-color:' + (result?'green':'red'));}
+function say(it)
+ {result = false;
+ document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+]]>
+</script>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('span'))">
+<p><span ondragstart="start(event)" ondrag="dragElement(event)">Drag me</span></p>
+<p>Drag selection above to the navy box below and drop it. Navy box should turn green and test results should appear below.</p>
+<div ondragenter="enterElement(event)" ondragover="overElement(event)" ondrop="dataDrop(event)"/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/036.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/036.xhtml
new file mode 100644
index 00000000000..ce4bd16abb6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/036.xhtml
@@ -0,0 +1,125 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>dataTransfer.items during link drag and drop</title>
+<style type="text/css">
+div
+ {height:100px;
+ width:100px;
+ padding:20px;
+ background-color:silver;}
+</style>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text/uri-list', 'text/plain', 'application/xml', 'application/xhtml+xml', 'application/mathml+xml', 'image/svg+xml', 'text/html', 'text/x-example'],
+data = ['data:text/plain,1', 'PASS', '<result>PASS</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>PASS</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">PASS</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>PASS</p></body></html>', 'PASS'],
+e = 0, result = true;
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], data[i]);}
+ for(var i = event.dataTransfer.items.length; i != 0; i--)
+ {if(dataTypes.indexOf(event.dataTransfer.items[i-1].type) == -1)
+ {delete event.dataTransfer.items[i-1]}
+ }
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragstart) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragstart): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragstart): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0] != data[e++])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should pass' + data[e] + ')')}
+ }
+ );
+ }
+ }
+function dragElement(event)
+ {event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondrag) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondrag): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondrag): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to drag event handler)')}
+ }
+ );
+ }
+ }
+function enterElement(event)
+ {event.preventDefault();
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragenter) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {delete event.dataTransfer.items[i];
+ if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragenter): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragenter): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to drag event handler)')}
+ }
+ );
+ }
+ }
+function overElement(event)
+ {event.preventDefault();
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragover) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragover): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragover): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to dragover event handler)')}
+ }
+ );
+ }
+ }
+function dataDrop(event)
+ {e = 0;
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondrop) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {delete event.dataTransfer.items[i];
+ if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondrop): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondrop): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0] != data[e++])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should pass' + data[e] + ')')}
+ }
+ );
+ }
+ document.querySelector('div').setAttribute('style','background-color:' + (result?'green':'red'));}
+function say(it)
+ {result = false;
+ document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+]]>
+</script>
+</head>
+<body>
+<p><a href="data:text/plain,1" ondragstart="start(event)" ondrag="dragElement(event)">Drag me</a></p>
+<p>Drag link above to the silver box below and drop it. Silver box should turn green.</p>
+<div ondragenter="enterElement(event)" ondragover="overElement(event)" ondrop="dataDrop(event)"/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/037.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/037.xhtml
new file mode 100644
index 00000000000..4a2023ac73f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/037.xhtml
@@ -0,0 +1,127 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>dataTransfer.items during block element drag and drop</title>
+<style type="text/css">
+div
+ {height:100px;
+ width:100px;
+ padding:20px;
+ background-color:green;}
+p + div
+ {background-color:gray;}
+</style>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text/plain', 'text/uri-list', 'application/xml', 'application/xhtml+xml', 'application/mathml+xml', 'image/svg+xml', 'text/html', 'text/x-example'],
+data = ['PASS', 'data:text/plain,1', '<result>PASS</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>PASS</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">PASS</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>PASS</p></body></html>', 'PASS'],
+e = 0, result = true;
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], data[i]);}
+ for(var i = event.dataTransfer.items.length; i != 0; i--)
+ {if(dataTypes.indexOf(event.dataTransfer.items[i-1].type) == -1)
+ {delete event.dataTransfer.items[i-1]}
+ }
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragstart) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragstart): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragstart): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0] != data[e++])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should pass' + data[e] + ')')}
+ }
+ );
+ }
+ }
+function dragElement(event)
+ {event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondrag) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondrag): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondrag): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to drag event handler)')}
+ }
+ );
+ }
+ }
+function enterElement(event)
+ {event.preventDefault();
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragenter) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {delete event.dataTransfer.items[i];
+ if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragenter): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragenter): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to drag event handler)')}
+ }
+ );
+ }
+ }
+function overElement(event)
+ {event.preventDefault();
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragover) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragover): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragover): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to dragover event handler)')}
+ }
+ );
+ }
+ }
+function dataDrop(event)
+ {e = 0;
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondrop) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {delete event.dataTransfer.items[i];
+ if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondrop): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondrop): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0] != data[e++])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should pass' + data[e] + ')')}
+ }
+ );
+ }
+ document.querySelector('p + div').setAttribute('style','background-color:' + (result?'green':'red'));}
+function say(it)
+ {result = false;
+ document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+]]>
+</script>
+</head>
+<body>
+<div draggable="true" ondragstart="start(event)" ondrag="dragElement(event)"/>
+<p>Drag green box above to the gray box below and drop it. Gray box should turn green.</p>
+<div ondragenter="enterElement(event)" ondragover="overElement(event)" ondrop="dataDrop(event)"/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/038.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/038.xhtml
new file mode 100644
index 00000000000..35826b0cd93
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/038.xhtml
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>dataTransfer.items and getData during canvas drag and drop</title>
+<style type="text/css">
+div
+ {height:100px;
+ width:100px;
+ padding:20px;
+ background-color:silver;}
+</style>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text/plain', 'text/uri-list', 'application/xml', 'application/xhtml+xml', 'application/mathml+xml', 'image/svg+xml', 'text/html', 'text/x-example'],
+data = ['PASS', 'data:text/plain,1', '<result>PASS</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>PASS</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">PASS</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>PASS</p></body></html>', 'PASS'],
+e = 0, result = true;
+function start(event)
+ {event.dataTransfer.items.clear();
+ event.dataTransfer.effectAllowed = 'copy';
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.items.add(data[i],dataTypes[i])}
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragstart) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != dataTypes.length; i++)
+ {if(event.dataTransfer.getData(dataTypes[i]) != data[i])
+ {say('getData (ondragstart): FAIL (getData(' + dataTypes[i] + ') returns wrong data)')}
+ }
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragstart): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragstart): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0] != data[e++])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should pass' + data[e] + ')')}
+ }
+ );
+ }
+ }
+function dragElement(event)
+ {event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondrag) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondrag): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondrag): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to drag event handler)')}
+ }
+ );
+ }
+ }
+function enterElement(event)
+ {event.preventDefault();
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragenter) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {delete event.dataTransfer.items[i];
+ if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragenter): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragenter): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to drag event handler)')}
+ }
+ );
+ }
+ }
+function overElement(event)
+ {event.preventDefault();
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragover) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragover): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragover): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to dragover event handler)')}
+ }
+ );
+ }
+ }
+function dataDrop(event)
+ {e = 0;
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondrop) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != dataTypes.length; i++)
+ {if(event.dataTransfer.getData(dataTypes[i]) != data[i])
+ {say('getData (ondrop): FAIL (getData(' + dataTypes[i] + ') returns wrong data)')}
+ }
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {delete event.dataTransfer.items[i];
+ if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondrop): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondrop): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0] != data[e++])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should pass' + data[e] + ')')}
+ }
+ );
+ }
+ document.querySelector('div').setAttribute('style','background-color:' + (result?'green':'red'));}
+function say(it)
+ {result = false;
+ document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+]]>
+</script>
+</head>
+<body>
+<p>
+ <canvas width="100" height="100" draggable="true" ondragstart="start(event)" ondrag="dragElement(event)">Canvas</canvas>
+</p>
+<p>Drag canvas pattern to the silver box below and drop it. Silver box should turn green.</p>
+<div ondragenter="enterElement(event)" ondragover="overElement(event)" ondrop="dataDrop(event)"/>
+<pre/>
+<script type="application/ecmascript">
+var canvas = document.querySelector('canvas'),
+c = canvas.getContext('2d');
+for(var x = 0; x != 50; x++)
+ {c.fillStyle = (x%2 == 0)?'navy':'white';
+ c.beginPath();
+ c.moveTo(x,x);
+ c.lineTo(100-x,x);
+ c.lineTo(100-x,100-x);
+ c.lineTo(x,100-x);
+ c.closePath();
+ c.fill();}
+data[1] = canvas.toDataURL('image/png');
+</script>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/039.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/039.xhtml
new file mode 100644
index 00000000000..37f165fe1ac
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/039.xhtml
@@ -0,0 +1,131 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>dataTransfer.items and getData during PNG image drag and drop</title>
+<style type="text/css">
+div
+ {height:100px;
+ width:100px;
+ padding:20px;
+ background-color:silver;}
+</style>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text/uri-list', 'text/plain', 'application/xml', 'application/xhtml+xml', 'application/mathml+xml', 'image/svg+xml', 'text/html', 'text/x-example'],
+data = ['data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAEq0lEQVR42u1dvU4bQRAeR0RCCilSp0peIoKGB4DSXYRDlcZlFClKBI4bB/kV/AymIDwCTahiicaioEOxhCsjWVTJziyKMfYZn+9ud3bvG2mEZB13u9+nndmf2Rki7fKFXtEBbVKD9o22jB4bPaND6hm9Mjo0enevw/vfevKMfbYl/8vv4HdBUkvFALhltG2A7dN3+pur8jv53fwN/hZkjjRo3eiuAatjdJA7CcnkDOSb/G1uQ6mFzUeDagaQrvl764yEJOU22LbUymXaGrRhOt40OvJOQvLIGUkbP9GLeIn4SM9NJ+tOTVI+Jq0ubY9sVFRNxy6DIWKWmEvpQ/ByQNumI+fBEjHrZ86lT8HJV3ptGn8aDRGzxJxKHwMZFe9Mg6+jJWNCyrX0VbUc0nuj4+jJmPiWsfRZodN+ZvSoNETMjpYjwUCFfKaXpjEnpSVjQsqJYOF5ZLw1elF6MiakXAgmnpw378DegIgZUm4EGw8jA2QsIuUbvXHpM2CmljFfhfsUO5uCA0/j6AudfZV5arv6WuVHcYs+ALwqKTkvHnmLoEwr8CJW9Llts9iNwvj3plzsfeWyIRnzrq37kfIzq6naBpA5a6bzlJgOl/SMkl+rklEFgIX5k5THwTYgIdwzcP2jhM/o19KsOeoArnBS6suaqo2gQnXCJWSwXNwXB4gBMFekNBeTwSGUmiMK4yNktDhsleNaAZRrUvYWmasuQHJOSDdpdKyriEIvo9maexWC70gAIF/bKTvzzFUH4HgbJZ3HdFSw9vC6lfKHpq7X8X07AOOblK2HhLQBindC2g/9Rx+gePcj/cnqHIDoUFm1c9gjwNAy/d0kyXIAMLSYrQ8kqScAhhbH3iLJBwIwtBByTJKkBWBoIeSMJHMOwNBCyG+SdEYAQ4tTvyLJMQUwtBAyJEn8BTC0EHIHQhQSApOlzGTBqaty6jzVAhhaCOlhYahuYYitE02EHGNzURchLZItX4ChhZB9HFBpUjmgwhGuHv0feI0gBw1T3j7CgHT5jzYC5XQRsjUdSsrhjADGl7ka0EylBgRb+ySkMy9rww7A8Waududf2MH9Qh9k3CbXLsGVNh/mqrvojuEeQHI+Qmq4Fq1ndIyeruaDxAEuCWk+ncmB0z3gepubtQenMUHyGTWELJl8xk6B15CeqVAyLtPXtUICsyJnVivWs+J0dAAwbzLOkQRTk2YuKsapTQFkXqPjlDILEinnRcZ1fpXdkGo866xqnH9FNyTjz0JIQZXcuPQCAE5rqo6oMEFBl7RknBRfTg8lj5Yl48JdGT0ueIWiYIvIuHFfPg9l85LJcF42b+JTUFjysZnyVlhy2qfA0asovTo9+0JxYnWC8t0KBQXuFYrdkIy3mBj3LbeNQrejZTuqOlbcl8znGTqcfjXoM3pboqgaPhEPxda1qgcVYsRt5TanDkgISWzcV1N1hCS3jdu4dNxUDMIhlBzXysHGGspkcBtsW2pPh3fGLrZ2ya5cXHFp0qxJ6si3E68EQCpy344vQRZxO5jfye+2d/oqgHsV02Z3lvcl9QTnA+EkLZw5h9MZcY4pTvxldXj/W0+esc+25H/5HQGYon+Q5f+MwFz+8QAAAABJRU5ErkJggg==', 'PASS', '<result>PASS</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>PASS</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">PASS</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>PASS</p></body></html>', 'PASS'],
+e = 0, result = true;
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ for(var i = event.dataTransfer.items.length; i != 0; i--)
+ {delete event.dataTransfer.items[i-1]}
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.items.add(data[i],dataTypes[i])}
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragstart) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != dataTypes.length; i++)
+ {if(event.dataTransfer.getData(dataTypes[i]) != data[i])
+ {say('getData (ondragstart): FAIL (getData(' + dataTypes[i] + ') returns wrong data)')}
+ }
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragstart): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragstart): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0] != data[e++])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should pass' + data[e] + ')')}
+ }
+ );
+ }
+ }
+function dragElement(event)
+ {event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondrag) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondrag): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondrag): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to drag event handler)')}
+ }
+ );
+ }
+ }
+function enterElement(event)
+ {event.preventDefault();
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragenter) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {delete event.dataTransfer.items[i];
+ if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragenter): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragenter): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to drag event handler)')}
+ }
+ );
+ }
+ }
+function overElement(event)
+ {event.preventDefault();
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragover) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragover): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragover): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to dragover event handler)')}
+ }
+ );
+ }
+ }
+function dataDrop(event)
+ {e = 0;
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondrop) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != dataTypes.length; i++)
+ {if(event.dataTransfer.getData(dataTypes[i]) != data[i])
+ {say('getData (ondrop): FAIL (getData(' + dataTypes[i] + ') returns wrong data)')}
+ }
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {delete event.dataTransfer.items[i];
+ if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondrop): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondrop): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0] != data[e++])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should pass' + data[e] + ')')}
+ }
+ );
+ }
+ document.querySelector('div').setAttribute('style','background-color:' + (result?'green':'red'));}
+function say(it)
+ {result = false;
+ document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+]]>
+</script>
+</head>
+<body>
+<p><img ondragstart="start(event)" ondrag="dragElement(event)" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAEq0lEQVR42u1dvU4bQRAeR0RCCilSp0peIoKGB4DSXYRDlcZlFClKBI4bB/kV/AymIDwCTahiicaioEOxhCsjWVTJziyKMfYZn+9ud3bvG2mEZB13u9+nndmf2Rki7fKFXtEBbVKD9o22jB4bPaND6hm9Mjo0enevw/vfevKMfbYl/8vv4HdBUkvFALhltG2A7dN3+pur8jv53fwN/hZkjjRo3eiuAatjdJA7CcnkDOSb/G1uQ6mFzUeDagaQrvl764yEJOU22LbUymXaGrRhOt40OvJOQvLIGUkbP9GLeIn4SM9NJ+tOTVI+Jq0ubY9sVFRNxy6DIWKWmEvpQ/ByQNumI+fBEjHrZ86lT8HJV3ptGn8aDRGzxJxKHwMZFe9Mg6+jJWNCyrX0VbUc0nuj4+jJmPiWsfRZodN+ZvSoNETMjpYjwUCFfKaXpjEnpSVjQsqJYOF5ZLw1elF6MiakXAgmnpw378DegIgZUm4EGw8jA2QsIuUbvXHpM2CmljFfhfsUO5uCA0/j6AudfZV5arv6WuVHcYs+ALwqKTkvHnmLoEwr8CJW9Llts9iNwvj3plzsfeWyIRnzrq37kfIzq6naBpA5a6bzlJgOl/SMkl+rklEFgIX5k5THwTYgIdwzcP2jhM/o19KsOeoArnBS6suaqo2gQnXCJWSwXNwXB4gBMFekNBeTwSGUmiMK4yNktDhsleNaAZRrUvYWmasuQHJOSDdpdKyriEIvo9maexWC70gAIF/bKTvzzFUH4HgbJZ3HdFSw9vC6lfKHpq7X8X07AOOblK2HhLQBindC2g/9Rx+gePcj/cnqHIDoUFm1c9gjwNAy/d0kyXIAMLSYrQ8kqScAhhbH3iLJBwIwtBByTJKkBWBoIeSMJHMOwNBCyG+SdEYAQ4tTvyLJMQUwtBAyJEn8BTC0EHIHQhQSApOlzGTBqaty6jzVAhhaCOlhYahuYYitE02EHGNzURchLZItX4ChhZB9HFBpUjmgwhGuHv0feI0gBw1T3j7CgHT5jzYC5XQRsjUdSsrhjADGl7ka0EylBgRb+ySkMy9rww7A8Waududf2MH9Qh9k3CbXLsGVNh/mqrvojuEeQHI+Qmq4Fq1ndIyeruaDxAEuCWk+ncmB0z3gepubtQenMUHyGTWELJl8xk6B15CeqVAyLtPXtUICsyJnVivWs+J0dAAwbzLOkQRTk2YuKsapTQFkXqPjlDILEinnRcZ1fpXdkGo866xqnH9FNyTjz0JIQZXcuPQCAE5rqo6oMEFBl7RknBRfTg8lj5Yl48JdGT0ueIWiYIvIuHFfPg9l85LJcF42b+JTUFjysZnyVlhy2qfA0asovTo9+0JxYnWC8t0KBQXuFYrdkIy3mBj3LbeNQrejZTuqOlbcl8znGTqcfjXoM3pboqgaPhEPxda1qgcVYsRt5TanDkgISWzcV1N1hCS3jdu4dNxUDMIhlBzXysHGGspkcBtsW2pPh3fGLrZ2ya5cXHFp0qxJ6si3E68EQCpy344vQRZxO5jfye+2d/oqgHsV02Z3lvcl9QTnA+EkLZw5h9MZcY4pTvxldXj/W0+esc+25H/5HQGYon+Q5f+MwFz+8QAAAABJRU5ErkJggg==" alt="PNG circle"/></p>
+<p>Drag circle above to the silver box below and drop it. Silver box should turn green.</p>
+<div ondragenter="enterElement(event)" ondragover="overElement(event)" ondrop="dataDrop(event)"/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/040.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/040.xhtml
new file mode 100644
index 00000000000..19ed6e146f6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/040.xhtml
@@ -0,0 +1,131 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>dataTransfer.items and getData during SVG image drag and drop</title>
+<style type="text/css">
+div
+ {height:100px;
+ width:100px;
+ padding:20px;
+ background-color:silver;}
+</style>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text/uri-list', 'text/plain', 'application/xml', 'application/xhtml+xml', 'application/mathml+xml', 'image/svg+xml', 'text/html', 'text/x-example'],
+data = ['data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20version%3D%221.1%22%20width%3D%22100px%22%20height%3D%22100px%22%20viewBox%3D%220%200%20100%20100%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22green%22/%3E%3C/svg%3E', 'PASS', '<result>PASS</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>PASS</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">PASS</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>PASS</p></body></html>', 'PASS'],
+e = 0, result = true;
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ for(var i = event.dataTransfer.items.length; i != 0; i--)
+ {delete event.dataTransfer.items[i-1]}
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.items.add(data[i],dataTypes[i])}
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragstart) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != dataTypes.length; i++)
+ {if(event.dataTransfer.getData(dataTypes[i]) != data[i])
+ {say('getData (ondragstart): FAIL (getData(' + dataTypes[i] + ') returns wrong data)')}
+ }
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragstart): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragstart): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0] != data[e++])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should pass' + data[e] + ')')}
+ }
+ );
+ }
+ }
+function dragElement(event)
+ {event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondrag) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondrag): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondrag): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to drag event handler)')}
+ }
+ );
+ }
+ }
+function enterElement(event)
+ {event.preventDefault();
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragenter) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {delete event.dataTransfer.items[i];
+ if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragenter): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragenter): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to drag event handler)')}
+ }
+ );
+ }
+ }
+function overElement(event)
+ {event.preventDefault();
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragover) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragover): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragover): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to dragover event handler)')}
+ }
+ );
+ }
+ }
+function dataDrop(event)
+ {e = 0;
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondrop) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != dataTypes.length; i++)
+ {if(event.dataTransfer.getData(dataTypes[i]) != data[i])
+ {say('getData (ondrop): FAIL (getData(' + dataTypes[i] + ') returns wrong data)')}
+ }
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {delete event.dataTransfer.items[i];
+ if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondrop): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondrop): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0] != data[e++])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should pass' + data[e] + ')')}
+ }
+ );
+ }
+ document.querySelector('div').setAttribute('style','background-color:' + (result?'green':'red'));}
+function say(it)
+ {result = false;
+ document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+]]>
+</script>
+</head>
+<body>
+<p><img ondragstart="start(event)" ondrag="dragElement(event)" src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20version%3D%221.1%22%20width%3D%22100px%22%20height%3D%22100px%22%20viewBox%3D%220%200%20100%20100%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22green%22/%3E%3C/svg%3E" alt="SVG circle"/></p>
+<p>Drag circle above to the silver box below and drop it. Silver box should turn green.</p>
+<div ondragenter="enterElement(event)" ondragover="overElement(event)" ondrop="dataDrop(event)"/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/041.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/041.xhtml
new file mode 100644
index 00000000000..7bd22d848f5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/041.xhtml
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>dataTransfer.items and getData during text input selection drag and drop</title>
+<style type="text/css">
+div
+ {min-height:100px;
+ width:100px;
+ padding:20px;
+ color:white;
+ background-color:navy;}
+</style>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text/plain', 'text/uri-list', 'application/xml', 'application/xhtml+xml', 'application/mathml+xml', 'image/svg+xml', 'text/html', 'text/x-example'],
+data = ['Drag me', 'data:text/plain,1', '<result>PASS</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>PASS</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">PASS</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>PASS</p></body></html>', 'PASS'];
+e = 0, result = true;
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ for(var i = event.dataTransfer.items.length; i != 0; i--)
+ {delete event.dataTransfer.items[i-1]}
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.items.add(data[i],dataTypes[i])}
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragstart) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != dataTypes.length; i++)
+ {if(event.dataTransfer.getData(dataTypes[i]) != data[i])
+ {say('getData (ondragstart): FAIL (getData(' + dataTypes[i] + ') returns wrong data)')}
+ }
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragstart): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragstart): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0] != data[e++])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should pass' + data[e] + ')')}
+ }
+ );
+ }
+ }
+function dragElement(event)
+ {event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondrag) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondrag): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondrag): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to drag event handler)')}
+ }
+ );
+ }
+ }
+function enterElement(event)
+ {event.preventDefault();
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragenter) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {delete event.dataTransfer.items[i];
+ if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragenter): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragenter): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to drag event handler)')}
+ }
+ );
+ }
+ }
+function overElement(event)
+ {event.preventDefault();
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragover) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragover): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragover): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to dragover event handler)')}
+ }
+ );
+ }
+ }
+function dataDrop(event)
+ {e = 0;
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondrop) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != dataTypes.length; i++)
+ {if(event.dataTransfer.getData(dataTypes[i]) != data[i])
+ {say('getData (ondrop): FAIL (getData(' + dataTypes[i] + ') returns wrong data)')}
+ }
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {delete event.dataTransfer.items[i];
+ if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondrop): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondrop): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0] != data[e++])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should pass' + data[e] + ')')}
+ }
+ );
+ }
+ document.querySelector('div').setAttribute('style','background-color:' + (result?'green':'red'));}
+function say(it)
+ {result = false;
+ document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+]]>
+</script>
+</head>
+<body onload="document.querySelector('input').select()">
+<p><input value="Drag me" ondragstart="start(event)" ondrag="dragElement(event)"/></p>
+<p>Drag selection above to the navy box below and drop it. Navy box should turn green.</p>
+<div ondragenter="enterElement(event)" ondragover="overElement(event)" ondrop="dataDrop(event)"/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/042.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/042.xhtml
new file mode 100644
index 00000000000..945de1171fd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/042.xhtml
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>dataTransfer.items and getData during selection drag and drop</title>
+<style type="text/css">
+div
+ {min-height:100px;
+ width:100px;
+ padding:20px;
+ color:white;
+ background-color:navy;}
+</style>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text/plain', 'text/uri-list', 'application/xml', 'application/xhtml+xml', 'application/mathml+xml', 'image/svg+xml', 'text/html', 'text/x-example'],
+data = ['Drag me', 'data:text/plain,1', '<result>PASS</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>PASS</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">PASS</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>PASS</p></body></html>', 'PASS'];
+e = 0, result = true;
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ for(var i = event.dataTransfer.items.length; i != 0; i--)
+ {delete event.dataTransfer.items[i-1]}
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.items.add(data[i],dataTypes[i])}
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragstart) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != dataTypes.length; i++)
+ {if(event.dataTransfer.getData(dataTypes[i]) != data[i])
+ {say('getData (ondragstart): FAIL (getData(' + dataTypes[i] + ') returns wrong data)')}
+ }
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragstart): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragstart): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0] != data[e++])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should pass' + data[e] + ')')}
+ }
+ );
+ }
+ }
+function dragElement(event)
+ {event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondrag) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondrag): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondrag): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to drag event handler)')}
+ }
+ );
+ }
+ }
+function enterElement(event)
+ {event.preventDefault();
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragenter) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {delete event.dataTransfer.items[i];
+ if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragenter): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragenter): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to drag event handler)')}
+ }
+ );
+ }
+ }
+function overElement(event)
+ {event.preventDefault();
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragover) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragover): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragover): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to dragover event handler)')}
+ }
+ );
+ }
+ }
+function dataDrop(event)
+ {e = 0;
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondrop) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != dataTypes.length; i++)
+ {if(event.dataTransfer.getData(dataTypes[i]) != data[i])
+ {say('getData (ondrop): FAIL (getData(' + dataTypes[i] + ') returns wrong data)')}
+ }
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {delete event.dataTransfer.items[i];
+ if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondrop): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondrop): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0] != data[e++])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should pass' + data[e] + ')')}
+ }
+ );
+ }
+ document.querySelector('div').setAttribute('style','background-color:' + (result?'green':'red'));}
+function say(it)
+ {result = false;
+ document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+]]>
+</script>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('span'))">
+<p><span ondragstart="start(event)" ondrag="dragElement(event)">Drag me</span></p>
+<p>Drag selection above to the navy box below and drop it. Navy box should turn green.</p>
+<div ondragenter="enterElement(event)" ondragover="overElement(event)" ondrop="dataDrop(event)"/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/043.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/043.xhtml
new file mode 100644
index 00000000000..c42baa09dfc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/043.xhtml
@@ -0,0 +1,131 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>dataTransfer.items and getData during link drag and drop</title>
+<style type="text/css">
+div
+ {height:100px;
+ width:100px;
+ padding:20px;
+ background-color:silver;}
+</style>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text/uri-list', 'text/plain', 'application/xml', 'application/xhtml+xml', 'application/mathml+xml', 'image/svg+xml', 'text/html', 'text/x-example'],
+data = ['data:text/plain,1', 'PASS', '<result>PASS</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>PASS</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">PASS</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>PASS</p></body></html>', 'PASS'],
+e = 0, result = true;
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ for(var i = event.dataTransfer.items.length; i != 0; i--)
+ {delete event.dataTransfer.items[i-1]}
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.items.add(data[i],dataTypes[i])}
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragstart) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != dataTypes.length; i++)
+ {if(event.dataTransfer.getData(dataTypes[i]) != data[i])
+ {say('getData (ondragstart): FAIL (getData(' + dataTypes[i] + ') returns wrong data)')}
+ }
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragstart): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragstart): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0] != data[e++])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should pass' + data[e] + ')')}
+ }
+ );
+ }
+ }
+function dragElement(event)
+ {event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondrag) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondrag): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondrag): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to drag event handler)')}
+ }
+ );
+ }
+ }
+function enterElement(event)
+ {event.preventDefault();
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragenter) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {delete event.dataTransfer.items[i];
+ if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragenter): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragenter): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to drag event handler)')}
+ }
+ );
+ }
+ }
+function overElement(event)
+ {event.preventDefault();
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragover) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragover): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragover): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to dragover event handler)')}
+ }
+ );
+ }
+ }
+function dataDrop(event)
+ {e = 0;
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondrop) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != dataTypes.length; i++)
+ {if(event.dataTransfer.getData(dataTypes[i]) != data[i])
+ {say('getData (ondrop): FAIL (getData(' + dataTypes[i] + ') returns wrong data)')}
+ }
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {delete event.dataTransfer.items[i];
+ if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondrop): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondrop): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0] != data[e++])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should pass' + data[e] + ')')}
+ }
+ );
+ }
+ document.querySelector('div').setAttribute('style','background-color:' + (result?'green':'red'));}
+function say(it)
+ {result = false;
+ document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+]]>
+</script>
+</head>
+<body>
+<p><a href="data:text/plain,1" ondragstart="start(event)" ondrag="dragElement(event)">Drag me</a></p>
+<p>Drag link above to the silver box below and drop it. Silver box should turn green.</p>
+<div ondragenter="enterElement(event)" ondragover="overElement(event)" ondrop="dataDrop(event)"/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/044.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/044.xhtml
new file mode 100644
index 00000000000..9a1efdcc06a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/044.xhtml
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>dataTransfer.items and getData during block element drag and drop</title>
+<style type="text/css">
+div
+ {height:100px;
+ width:100px;
+ padding:20px;
+ background-color:green;}
+p + div
+ {background-color:gray;}
+</style>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text/plain', 'text/uri-list', 'application/xml', 'application/xhtml+xml', 'application/mathml+xml', 'image/svg+xml', 'text/html', 'text/x-example'],
+data = ['PASS', 'data:text/plain,1', '<result>PASS</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>PASS</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">PASS</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>PASS</p></body></html>', 'PASS'],
+e = 0, result = true;
+function start(event)
+ {event.dataTransfer.items.clear();
+ event.dataTransfer.effectAllowed = 'copy';
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.items.add(data[i],dataTypes[i])}
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragstart) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != dataTypes.length; i++)
+ {if(event.dataTransfer.getData(dataTypes[i]) != data[i])
+ {say('getData (ondragstart): FAIL (getData(' + dataTypes[i] + ') returns wrong data)')}
+ }
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragstart): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragstart): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0] != data[e++])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should pass' + data[e] + ')')}
+ }
+ );
+ }
+ }
+function dragElement(event)
+ {event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondrag) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondrag): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondrag): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to drag event handler)')}
+ }
+ );
+ }
+ }
+function enterElement(event)
+ {event.preventDefault();
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragenter) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {delete event.dataTransfer.items[i];
+ if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragenter): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragenter): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to drag event handler)')}
+ }
+ );
+ }
+ }
+function overElement(event)
+ {event.preventDefault();
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragover) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragover): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragover): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to dragover event handler)')}
+ }
+ );
+ }
+ }
+function dataDrop(event)
+ {e = 0;
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondrop) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != dataTypes.length; i++)
+ {if(event.dataTransfer.getData(dataTypes[i]) != data[i])
+ {say('getData (ondrop): FAIL (getData(' + dataTypes[i] + ') returns wrong data)')}
+ }
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {delete event.dataTransfer.items[i];
+ if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondrop): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondrop): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0] != data[e++])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should pass' + data[e] + ')')}
+ }
+ );
+ }
+ document.querySelector('p + div').setAttribute('style','background-color:' + (result?'green':'red'));}
+function say(it)
+ {result = false;
+ document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+]]>
+</script>
+</head>
+<body>
+<div draggable="true" ondragstart="start(event)" ondrag="dragElement(event)"/>
+<p>Drag green box above to the gray box below and drop it. Gray box should turn green.</p>
+<div ondragenter="enterElement(event)" ondragover="overElement(event)" ondrop="dataDrop(event)"/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/045.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/045.xhtml
new file mode 100644
index 00000000000..e354ff7f143
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/045.xhtml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Text and url aliases</title>
+<style type="text/css">
+div
+ {height:100px;
+ width:100px;
+ padding:20px;
+ background-color:green;}
+p + div
+ {background-color:gray;}
+</style>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text', 'url', 'application/xml', 'application/xhtml+xml', 'application/mathml+xml', 'image/svg+xml', 'text/html', 'text/x-example'],
+data = ['PASS', 'data:text/plain,1', '<result>PASS</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>PASS</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">PASS</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>PASS</p></body></html>', 'PASS'];
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], data[i]);}
+ say('items.length (dragstart) : ' + ((event.dataTransfer.items.length >= dataTypes.length)?'PASS':'FAIL'));
+ }
+function dragElement(event)
+ {for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during drag)')}
+ }
+ if(event.dataTransfer.items.length < dataTypes.length)
+ {say('items.length (dragover) : FAIL')}
+ }
+function enterElement(event)
+ {event.preventDefault();
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during dragenter)')}
+ }
+ say('items.length (dragenter) : ' + ((event.dataTransfer.items.length >= dataTypes.length)?'PASS':'FAIL'));}
+function dataDrop(event)
+ {say('items.length (drop) : ' + ((event.dataTransfer.items.length >= dataTypes.length)?'PASS':'FAIL'));
+ for(var i = 0; i != dataTypes.length; i++)
+ {say('getData(' + dataTypes[i] + ') : ' + ((event.dataTransfer.getData(dataTypes[i]) == data[i])?'PASS':'FAIL'));}
+ document.querySelector('p + div').setAttribute('style','background-color:green');}
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+]]>
+</script>
+</head>
+<body>
+<div draggable="true" ondragstart="start(event)" ondrag="dragElement(event)"/>
+<p>Drag green box above to the gray box below and drop it. Gray box should turn green and test results should appear below.</p>
+<div ondragenter="enterElement(event)" ondragover="return false;" ondrop="dataDrop(event)"/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/046.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/046.xhtml
new file mode 100644
index 00000000000..8a4a3cbaecf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/046.xhtml
@@ -0,0 +1,172 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>dataTransfer.types during canvas drag and drop</title>
+<style type="text/css">
+div
+ {height:100px;
+ width:100px;
+ padding:20px;
+ background-color:silver;}
+</style>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text/plain', 'text/uri-list', 'application/xml', 'application/xhtml+xml', 'application/mathml+xml', 'image/svg+xml', 'text/html', 'text/x-example'],
+data = ['PASS', 'data:text/plain,1', '<result>PASS</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>PASS</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">PASS</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>PASS</p></body></html>', 'PASS'],
+e = 0, result = true;
+function start(event)
+ {event.dataTransfer.items.clear();
+ event.dataTransfer.effectAllowed = 'copy';
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.items.add(data[i],dataTypes[i])}
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragstart) : FAIL (items.length should be' + dataTypes.length + ')')}
+ if(event.dataTransfer.types.length != dataTypes.length)
+ {say('types.length (ondragstart) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != dataTypes.length; i++)
+ {if(event.dataTransfer.getData(dataTypes[i]) != data[i])
+ {say('getData (ondragstart): FAIL (getData(' + dataTypes[i] + ') returns wrong data)')}
+ if(event.dataTransfer.types[i] != dataTypes[i])
+ {say('Types (ondragstart): FAIL (dataTransfer.types[' + i + '] returns wrong value)')}
+ }
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragstart): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragstart): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0] != data[e++])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should pass' + data[e] + ')')}
+ }
+ );
+ }
+ }
+function dragElement(event)
+ {event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondrag) : FAIL (items.length should be' + dataTypes.length + ')')}
+ if(event.dataTransfer.types.length != dataTypes.length)
+ {say('types.length (ondrag) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != dataTypes.length; i++)
+ {if(event.dataTransfer.types[i] != dataTypes[i])
+ {say('Types (ondrag): FAIL (dataTransfer.types[' + i + '] returns wrong value)')}
+ }
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondrag): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondrag): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to drag event handler)')}
+ }
+ );
+ }
+ }
+function enterElement(event)
+ {event.preventDefault();
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragenter) : FAIL (items.length should be' + dataTypes.length + ')')}
+ if(event.dataTransfer.types.length != dataTypes.length)
+ {say('types.length (ondragenter) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != dataTypes.length; i++)
+ {if(event.dataTransfer.types[i] != dataTypes[i])
+ {say('Types (ondragenter): FAIL (dataTransfer.types[' + i + '] returns wrong value)')}
+ }
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {delete event.dataTransfer.items[i];
+ if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragenter): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragenter): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to drag event handler)')}
+ }
+ );
+ }
+ }
+function overElement(event)
+ {event.preventDefault();
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragover) : FAIL (items.length should be' + dataTypes.length + ')')}
+ if(event.dataTransfer.types.length != dataTypes.length)
+ {say('types.length (ondragover) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != dataTypes.length; i++)
+ {if(event.dataTransfer.types[i] != dataTypes[i])
+ {say('Types (ondragover): FAIL (dataTransfer.types[' + i + '] returns wrong value)')}
+ }
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragover): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragover): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to dragover event handler)')}
+ }
+ );
+ }
+ }
+function dataDrop(event)
+ {e = 0;
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondrop) : FAIL (items.length should be' + dataTypes.length + ')')}
+ if(event.dataTransfer.types.length != dataTypes.length)
+ {say('types.length (ondrop) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != dataTypes.length; i++)
+ {if(event.dataTransfer.types[i] != dataTypes[i])
+ {say('Types (ondrop): FAIL (dataTransfer.types[' + i + '] returns wrong value)')}
+ if(event.dataTransfer.getData(dataTypes[i]) != data[i])
+ {say('getData (ondrop): FAIL (getData(' + dataTypes[i] + ') returns wrong data)')}
+ }
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {delete event.dataTransfer.items[i];
+ if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondrop): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondrop): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0] != data[e++])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should pass' + data[e] + ')')}
+ }
+ );
+ }
+ document.querySelector('div').setAttribute('style','background-color:' + (result?'green':'red'));}
+function say(it)
+ {result = false;
+ document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+]]>
+</script>
+</head>
+<body>
+<p>
+ <canvas width="100" height="100" draggable="true" ondragstart="start(event)" ondrag="dragElement(event)">Canvas</canvas>
+</p>
+<p>Drag canvas pattern to the silver box below and drop it. Silver box should turn green.</p>
+<div ondragenter="enterElement(event)" ondragover="overElement(event)" ondrop="dataDrop(event)"/>
+<pre/>
+<script type="application/ecmascript">
+var canvas = document.querySelector('canvas'),
+c = canvas.getContext('2d');
+for(var x = 0; x != 50; x++)
+ {c.fillStyle = (x%2 == 0)?'navy':'white';
+ c.beginPath();
+ c.moveTo(x,x);
+ c.lineTo(100-x,x);
+ c.lineTo(100-x,100-x);
+ c.lineTo(x,100-x);
+ c.closePath();
+ c.fill();}
+data[1] = canvas.toDataURL('image/png');
+</script>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/047.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/047.xhtml
new file mode 100644
index 00000000000..fc43f811ceb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/047.xhtml
@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>dataTransfer.types during PNG image drag and drop</title>
+<style type="text/css">
+div
+ {height:100px;
+ width:100px;
+ padding:20px;
+ background-color:silver;}
+</style>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text/uri-list', 'text/plain', 'application/xml', 'application/xhtml+xml', 'application/mathml+xml', 'image/svg+xml', 'text/html', 'text/x-example'],
+data = ['data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAEq0lEQVR42u1dvU4bQRAeR0RCCilSp0peIoKGB4DSXYRDlcZlFClKBI4bB/kV/AymIDwCTahiicaioEOxhCsjWVTJziyKMfYZn+9ud3bvG2mEZB13u9+nndmf2Rki7fKFXtEBbVKD9o22jB4bPaND6hm9Mjo0enevw/vfevKMfbYl/8vv4HdBUkvFALhltG2A7dN3+pur8jv53fwN/hZkjjRo3eiuAatjdJA7CcnkDOSb/G1uQ6mFzUeDagaQrvl764yEJOU22LbUymXaGrRhOt40OvJOQvLIGUkbP9GLeIn4SM9NJ+tOTVI+Jq0ubY9sVFRNxy6DIWKWmEvpQ/ByQNumI+fBEjHrZ86lT8HJV3ptGn8aDRGzxJxKHwMZFe9Mg6+jJWNCyrX0VbUc0nuj4+jJmPiWsfRZodN+ZvSoNETMjpYjwUCFfKaXpjEnpSVjQsqJYOF5ZLw1elF6MiakXAgmnpw378DegIgZUm4EGw8jA2QsIuUbvXHpM2CmljFfhfsUO5uCA0/j6AudfZV5arv6WuVHcYs+ALwqKTkvHnmLoEwr8CJW9Llts9iNwvj3plzsfeWyIRnzrq37kfIzq6naBpA5a6bzlJgOl/SMkl+rklEFgIX5k5THwTYgIdwzcP2jhM/o19KsOeoArnBS6suaqo2gQnXCJWSwXNwXB4gBMFekNBeTwSGUmiMK4yNktDhsleNaAZRrUvYWmasuQHJOSDdpdKyriEIvo9maexWC70gAIF/bKTvzzFUH4HgbJZ3HdFSw9vC6lfKHpq7X8X07AOOblK2HhLQBindC2g/9Rx+gePcj/cnqHIDoUFm1c9gjwNAy/d0kyXIAMLSYrQ8kqScAhhbH3iLJBwIwtBByTJKkBWBoIeSMJHMOwNBCyG+SdEYAQ4tTvyLJMQUwtBAyJEn8BTC0EHIHQhQSApOlzGTBqaty6jzVAhhaCOlhYahuYYitE02EHGNzURchLZItX4ChhZB9HFBpUjmgwhGuHv0feI0gBw1T3j7CgHT5jzYC5XQRsjUdSsrhjADGl7ka0EylBgRb+ySkMy9rww7A8Waududf2MH9Qh9k3CbXLsGVNh/mqrvojuEeQHI+Qmq4Fq1ndIyeruaDxAEuCWk+ncmB0z3gepubtQenMUHyGTWELJl8xk6B15CeqVAyLtPXtUICsyJnVivWs+J0dAAwbzLOkQRTk2YuKsapTQFkXqPjlDILEinnRcZ1fpXdkGo866xqnH9FNyTjz0JIQZXcuPQCAE5rqo6oMEFBl7RknBRfTg8lj5Yl48JdGT0ueIWiYIvIuHFfPg9l85LJcF42b+JTUFjysZnyVlhy2qfA0asovTo9+0JxYnWC8t0KBQXuFYrdkIy3mBj3LbeNQrejZTuqOlbcl8znGTqcfjXoM3pboqgaPhEPxda1qgcVYsRt5TanDkgISWzcV1N1hCS3jdu4dNxUDMIhlBzXysHGGspkcBtsW2pPh3fGLrZ2ya5cXHFp0qxJ6si3E68EQCpy344vQRZxO5jfye+2d/oqgHsV02Z3lvcl9QTnA+EkLZw5h9MZcY4pTvxldXj/W0+esc+25H/5HQGYon+Q5f+MwFz+8QAAAABJRU5ErkJggg==', 'PASS', '<result>PASS</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>PASS</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">PASS</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>PASS</p></body></html>', 'PASS'],
+e = 0, result = true;
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ for(var i = event.dataTransfer.items.length; i != 0; i--)
+ {delete event.dataTransfer.items[i-1]}
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.items.add(data[i],dataTypes[i])}
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragstart) : FAIL (items.length should be' + dataTypes.length + ')')}
+ if(event.dataTransfer.types.length != dataTypes.length)
+ {say('types.length (ondragstart) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != dataTypes.length; i++)
+ {if(event.dataTransfer.getData(dataTypes[i]) != data[i])
+ {say('getData (ondragstart): FAIL (getData(' + dataTypes[i] + ') returns wrong data)')}
+ if(event.dataTransfer.types[i] != dataTypes[i])
+ {say('Types (ondragstart): FAIL (dataTransfer.types[' + i + '] returns wrong value)')}
+ }
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragstart): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragstart): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0] != data[e++])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should pass' + data[e] + ')')}
+ }
+ );
+ }
+ }
+function dragElement(event)
+ {event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondrag) : FAIL (items.length should be' + dataTypes.length + ')')}
+ if(event.dataTransfer.types.length != dataTypes.length)
+ {say('types.length (ondrag) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != dataTypes.length; i++)
+ {if(event.dataTransfer.types[i] != dataTypes[i])
+ {say('Types (ondrag): FAIL (dataTransfer.types[' + i + '] returns wrong value)')}
+ }
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondrag): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondrag): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to drag event handler)')}
+ }
+ );
+ }
+ }
+function enterElement(event)
+ {event.preventDefault();
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragenter) : FAIL (items.length should be' + dataTypes.length + ')')}
+ if(event.dataTransfer.types.length != dataTypes.length)
+ {say('types.length (ondragenter) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != dataTypes.length; i++)
+ {if(event.dataTransfer.types[i] != dataTypes[i])
+ {say('Types (ondragenter): FAIL (dataTransfer.types[' + i + '] returns wrong value)')}
+ }
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {delete event.dataTransfer.items[i];
+ if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragenter): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragenter): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to drag event handler)')}
+ }
+ );
+ }
+ }
+function overElement(event)
+ {event.preventDefault();
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragover) : FAIL (items.length should be' + dataTypes.length + ')')}
+ if(event.dataTransfer.types.length != dataTypes.length)
+ {say('types.length (ondragover) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != dataTypes.length; i++)
+ {if(event.dataTransfer.types[i] != dataTypes[i])
+ {say('Types (ondragover): FAIL (dataTransfer.types[' + i + '] returns wrong value)')}
+ }
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragover): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragover): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to dragover event handler)')}
+ }
+ );
+ }
+ }
+function dataDrop(event)
+ {e = 0;
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondrop) : FAIL (items.length should be' + dataTypes.length + ')')}
+ if(event.dataTransfer.types.length != dataTypes.length)
+ {say('types.length (ondrop) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != dataTypes.length; i++)
+ {if(event.dataTransfer.types[i] != dataTypes[i])
+ {say('Types (ondrop): FAIL (dataTransfer.types[' + i + '] returns wrong value)')}
+ if(event.dataTransfer.getData(dataTypes[i]) != data[i])
+ {say('getData (ondrop): FAIL (getData(' + dataTypes[i] + ') returns wrong data)')}
+ }
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {delete event.dataTransfer.items[i];
+ if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondrop): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondrop): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0] != data[e++])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should pass' + data[e] + ')')}
+ }
+ );
+ }
+ document.querySelector('div').setAttribute('style','background-color:' + (result?'green':'red'));}
+function say(it)
+ {result = false;
+ document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+]]>
+</script>
+</head>
+<body>
+<p><img ondragstart="start(event)" ondrag="dragElement(event)" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAEq0lEQVR42u1dvU4bQRAeR0RCCilSp0peIoKGB4DSXYRDlcZlFClKBI4bB/kV/AymIDwCTahiicaioEOxhCsjWVTJziyKMfYZn+9ud3bvG2mEZB13u9+nndmf2Rki7fKFXtEBbVKD9o22jB4bPaND6hm9Mjo0enevw/vfevKMfbYl/8vv4HdBUkvFALhltG2A7dN3+pur8jv53fwN/hZkjjRo3eiuAatjdJA7CcnkDOSb/G1uQ6mFzUeDagaQrvl764yEJOU22LbUymXaGrRhOt40OvJOQvLIGUkbP9GLeIn4SM9NJ+tOTVI+Jq0ubY9sVFRNxy6DIWKWmEvpQ/ByQNumI+fBEjHrZ86lT8HJV3ptGn8aDRGzxJxKHwMZFe9Mg6+jJWNCyrX0VbUc0nuj4+jJmPiWsfRZodN+ZvSoNETMjpYjwUCFfKaXpjEnpSVjQsqJYOF5ZLw1elF6MiakXAgmnpw378DegIgZUm4EGw8jA2QsIuUbvXHpM2CmljFfhfsUO5uCA0/j6AudfZV5arv6WuVHcYs+ALwqKTkvHnmLoEwr8CJW9Llts9iNwvj3plzsfeWyIRnzrq37kfIzq6naBpA5a6bzlJgOl/SMkl+rklEFgIX5k5THwTYgIdwzcP2jhM/o19KsOeoArnBS6suaqo2gQnXCJWSwXNwXB4gBMFekNBeTwSGUmiMK4yNktDhsleNaAZRrUvYWmasuQHJOSDdpdKyriEIvo9maexWC70gAIF/bKTvzzFUH4HgbJZ3HdFSw9vC6lfKHpq7X8X07AOOblK2HhLQBindC2g/9Rx+gePcj/cnqHIDoUFm1c9gjwNAy/d0kyXIAMLSYrQ8kqScAhhbH3iLJBwIwtBByTJKkBWBoIeSMJHMOwNBCyG+SdEYAQ4tTvyLJMQUwtBAyJEn8BTC0EHIHQhQSApOlzGTBqaty6jzVAhhaCOlhYahuYYitE02EHGNzURchLZItX4ChhZB9HFBpUjmgwhGuHv0feI0gBw1T3j7CgHT5jzYC5XQRsjUdSsrhjADGl7ka0EylBgRb+ySkMy9rww7A8Waududf2MH9Qh9k3CbXLsGVNh/mqrvojuEeQHI+Qmq4Fq1ndIyeruaDxAEuCWk+ncmB0z3gepubtQenMUHyGTWELJl8xk6B15CeqVAyLtPXtUICsyJnVivWs+J0dAAwbzLOkQRTk2YuKsapTQFkXqPjlDILEinnRcZ1fpXdkGo866xqnH9FNyTjz0JIQZXcuPQCAE5rqo6oMEFBl7RknBRfTg8lj5Yl48JdGT0ueIWiYIvIuHFfPg9l85LJcF42b+JTUFjysZnyVlhy2qfA0asovTo9+0JxYnWC8t0KBQXuFYrdkIy3mBj3LbeNQrejZTuqOlbcl8znGTqcfjXoM3pboqgaPhEPxda1qgcVYsRt5TanDkgISWzcV1N1hCS3jdu4dNxUDMIhlBzXysHGGspkcBtsW2pPh3fGLrZ2ya5cXHFp0qxJ6si3E68EQCpy344vQRZxO5jfye+2d/oqgHsV02Z3lvcl9QTnA+EkLZw5h9MZcY4pTvxldXj/W0+esc+25H/5HQGYon+Q5f+MwFz+8QAAAABJRU5ErkJggg==" alt="PNG circle"/></p>
+<p>Drag circle above to the silver box below and drop it. Silver box should turn green.</p>
+<div ondragenter="enterElement(event)" ondragover="overElement(event)" ondrop="dataDrop(event)"/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/048.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/048.xhtml
new file mode 100644
index 00000000000..49c87f722c8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/048.xhtml
@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>dataTransfer.types during SVG image drag and drop</title>
+<style type="text/css">
+div
+ {height:100px;
+ width:100px;
+ padding:20px;
+ background-color:silver;}
+</style>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text/uri-list', 'text/plain', 'application/xml', 'application/xhtml+xml', 'application/mathml+xml', 'image/svg+xml', 'text/html', 'text/x-example'],
+data = ['data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20version%3D%221.1%22%20width%3D%22100px%22%20height%3D%22100px%22%20viewBox%3D%220%200%20100%20100%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22green%22/%3E%3C/svg%3E', 'PASS', '<result>PASS</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>PASS</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">PASS</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>PASS</p></body></html>', 'PASS'],
+e = 0, result = true;
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ for(var i = event.dataTransfer.items.length; i != 0; i--)
+ {delete event.dataTransfer.items[i-1]}
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.items.add(data[i],dataTypes[i])}
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragstart) : FAIL (items.length should be' + dataTypes.length + ')')}
+ if(event.dataTransfer.types.length != dataTypes.length)
+ {say('types.length (ondragstart) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != dataTypes.length; i++)
+ {if(event.dataTransfer.getData(dataTypes[i]) != data[i])
+ {say('getData (ondragstart): FAIL (getData(' + dataTypes[i] + ') returns wrong data)')}
+ if(event.dataTransfer.types[i] != dataTypes[i])
+ {say('Types (ondragstart): FAIL (dataTransfer.types[' + i + '] returns wrong value)')}
+ }
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragstart): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragstart): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0] != data[e++])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should pass' + data[e] + ')')}
+ }
+ );
+ }
+ }
+function dragElement(event)
+ {event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondrag) : FAIL (items.length should be' + dataTypes.length + ')')}
+ if(event.dataTransfer.types.length != dataTypes.length)
+ {say('types.length (ondrag) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != dataTypes.length; i++)
+ {if(event.dataTransfer.types[i] != dataTypes[i])
+ {say('Types (ondrag): FAIL (dataTransfer.types[' + i + '] returns wrong value)')}
+ }
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondrag): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondrag): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to drag event handler)')}
+ }
+ );
+ }
+ }
+function enterElement(event)
+ {event.preventDefault();
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragenter) : FAIL (items.length should be' + dataTypes.length + ')')}
+ if(event.dataTransfer.types.length != dataTypes.length)
+ {say('types.length (ondragenter) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != dataTypes.length; i++)
+ {if(event.dataTransfer.types[i] != dataTypes[i])
+ {say('Types (ondragenter): FAIL (dataTransfer.types[' + i + '] returns wrong value)')}
+ }
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {delete event.dataTransfer.items[i];
+ if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragenter): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragenter): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to drag event handler)')}
+ }
+ );
+ }
+ }
+function overElement(event)
+ {event.preventDefault();
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragover) : FAIL (items.length should be' + dataTypes.length + ')')}
+ if(event.dataTransfer.types.length != dataTypes.length)
+ {say('types.length (ondragover) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != dataTypes.length; i++)
+ {if(event.dataTransfer.types[i] != dataTypes[i])
+ {say('Types (ondragover): FAIL (dataTransfer.types[' + i + '] returns wrong value)')}
+ }
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragover): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragover): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to dragover event handler)')}
+ }
+ );
+ }
+ }
+function dataDrop(event)
+ {e = 0;
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondrop) : FAIL (items.length should be' + dataTypes.length + ')')}
+ if(event.dataTransfer.types.length != dataTypes.length)
+ {say('types.length (ondrop) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != dataTypes.length; i++)
+ {if(event.dataTransfer.types[i] != dataTypes[i])
+ {say('Types (ondrop): FAIL (dataTransfer.types[' + i + '] returns wrong value)')}
+ if(event.dataTransfer.getData(dataTypes[i]) != data[i])
+ {say('getData (ondrop): FAIL (getData(' + dataTypes[i] + ') returns wrong data)')}
+ }
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {delete event.dataTransfer.items[i];
+ if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondrop): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondrop): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0] != data[e++])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should pass' + data[e] + ')')}
+ }
+ );
+ }
+ document.querySelector('div').setAttribute('style','background-color:' + (result?'green':'red'));}
+function say(it)
+ {result = false;
+ document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+]]>
+</script>
+</head>
+<body>
+<p><img ondragstart="start(event)" ondrag="dragElement(event)" src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20version%3D%221.1%22%20width%3D%22100px%22%20height%3D%22100px%22%20viewBox%3D%220%200%20100%20100%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22green%22/%3E%3C/svg%3E" alt="SVG circle"/></p>
+<p>Drag circle above to the silver box below and drop it. Silver box should turn green.</p>
+<div ondragenter="enterElement(event)" ondragover="overElement(event)" ondrop="dataDrop(event)"/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/049.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/049.xhtml
new file mode 100644
index 00000000000..5c810dd2ad2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/049.xhtml
@@ -0,0 +1,158 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>dataTransfer.types during text input selection drag and drop</title>
+<style type="text/css">
+div
+ {min-height:100px;
+ width:100px;
+ padding:20px;
+ color:white;
+ background-color:navy;}
+</style>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text/plain', 'text/uri-list', 'application/xml', 'application/xhtml+xml', 'application/mathml+xml', 'image/svg+xml', 'text/html', 'text/x-example'],
+data = ['Drag me', 'data:text/plain,1', '<result>PASS</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>PASS</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">PASS</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>PASS</p></body></html>', 'PASS'];
+e = 0, result = true;
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ for(var i = event.dataTransfer.items.length; i != 0; i--)
+ {delete event.dataTransfer.items[i-1]}
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.items.add(data[i],dataTypes[i])}
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragstart) : FAIL (items.length should be' + dataTypes.length + ')')}
+ if(event.dataTransfer.types.length != dataTypes.length)
+ {say('types.length (ondragstart) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != dataTypes.length; i++)
+ {if(event.dataTransfer.getData(dataTypes[i]) != data[i])
+ {say('getData (ondragstart): FAIL (getData(' + dataTypes[i] + ') returns wrong data)')}
+ if(event.dataTransfer.types[i] != dataTypes[i])
+ {say('Types (ondragstart): FAIL (dataTransfer.types[' + i + '] returns wrong value)')}
+ }
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragstart): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragstart): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0] != data[e++])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should pass' + data[e] + ')')}
+ }
+ );
+ }
+ }
+function dragElement(event)
+ {event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondrag) : FAIL (items.length should be' + dataTypes.length + ')')}
+ if(event.dataTransfer.types.length != dataTypes.length)
+ {say('types.length (ondrag) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != dataTypes.length; i++)
+ {if(event.dataTransfer.types[i] != dataTypes[i])
+ {say('Types (ondrag): FAIL (dataTransfer.types[' + i + '] returns wrong value)')}
+ }
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondrag): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondrag): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to drag event handler)')}
+ }
+ );
+ }
+ }
+function enterElement(event)
+ {event.preventDefault();
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragenter) : FAIL (items.length should be' + dataTypes.length + ')')}
+ if(event.dataTransfer.types.length != dataTypes.length)
+ {say('types.length (ondragenter) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != dataTypes.length; i++)
+ {if(event.dataTransfer.types[i] != dataTypes[i])
+ {say('Types (ondragenter): FAIL (dataTransfer.types[' + i + '] returns wrong value)')}
+ }
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {delete event.dataTransfer.items[i];
+ if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragenter): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragenter): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to drag event handler)')}
+ }
+ );
+ }
+ }
+function overElement(event)
+ {event.preventDefault();
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragover) : FAIL (items.length should be' + dataTypes.length + ')')}
+ if(event.dataTransfer.types.length != dataTypes.length)
+ {say('types.length (ondragover) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != dataTypes.length; i++)
+ {if(event.dataTransfer.types[i] != dataTypes[i])
+ {say('Types (ondragover): FAIL (dataTransfer.types[' + i + '] returns wrong value)')}
+ }
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragover): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragover): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to dragover event handler)')}
+ }
+ );
+ }
+ }
+function dataDrop(event)
+ {e = 0;
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondrop) : FAIL (items.length should be' + dataTypes.length + ')')}
+ if(event.dataTransfer.types.length != dataTypes.length)
+ {say('types.length (ondrop) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != dataTypes.length; i++)
+ {if(event.dataTransfer.types[i] != dataTypes[i])
+ {say('Types (ondrop): FAIL (dataTransfer.types[' + i + '] returns wrong value)')}
+ if(event.dataTransfer.getData(dataTypes[i]) != data[i])
+ {say('getData (ondrop): FAIL (getData(' + dataTypes[i] + ') returns wrong data)')}
+ }
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {delete event.dataTransfer.items[i];
+ if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondrop): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondrop): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0] != data[e++])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should pass' + data[e] + ')')}
+ }
+ );
+ }
+ document.querySelector('div').setAttribute('style','background-color:' + (result?'green':'red'));}
+function say(it)
+ {result = false;
+ document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+]]>
+</script>
+</head>
+<body onload="document.querySelector('input').select()">
+<p><input value="Drag me" ondragstart="start(event)" ondrag="dragElement(event)"/></p>
+<p>Drag selection above to the navy box below and drop it. Navy box should turn green.</p>
+<div ondragenter="enterElement(event)" ondragover="overElement(event)" ondrop="dataDrop(event)"/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/050.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/050.xhtml
new file mode 100644
index 00000000000..33e41c65346
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/050.xhtml
@@ -0,0 +1,158 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>dataTransfer.types during selection drag and drop</title>
+<style type="text/css">
+div
+ {min-height:100px;
+ width:100px;
+ padding:20px;
+ color:white;
+ background-color:navy;}
+</style>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text/plain', 'text/uri-list', 'application/xml', 'application/xhtml+xml', 'application/mathml+xml', 'image/svg+xml', 'text/html', 'text/x-example'],
+data = ['Drag me', 'data:text/plain,1', '<result>PASS</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>PASS</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">PASS</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>PASS</p></body></html>', 'PASS'];
+e = 0, result = true;
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ for(var i = event.dataTransfer.items.length; i != 0; i--)
+ {delete event.dataTransfer.items[i-1]}
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.items.add(data[i],dataTypes[i])}
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragstart) : FAIL (items.length should be' + dataTypes.length + ')')}
+ if(event.dataTransfer.types.length != dataTypes.length)
+ {say('types.length (ondragstart) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != dataTypes.length; i++)
+ {if(event.dataTransfer.getData(dataTypes[i]) != data[i])
+ {say('getData (ondragstart): FAIL (getData(' + dataTypes[i] + ') returns wrong data)')}
+ if(event.dataTransfer.types[i] != dataTypes[i])
+ {say('Types (ondragstart): FAIL (dataTransfer.types[' + i + '] returns wrong value)')}
+ }
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragstart): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragstart): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0] != data[e++])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should pass' + data[e] + ')')}
+ }
+ );
+ }
+ }
+function dragElement(event)
+ {event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondrag) : FAIL (items.length should be' + dataTypes.length + ')')}
+ if(event.dataTransfer.types.length != dataTypes.length)
+ {say('types.length (ondrag) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != dataTypes.length; i++)
+ {if(event.dataTransfer.types[i] != dataTypes[i])
+ {say('Types (ondrag): FAIL (dataTransfer.types[' + i + '] returns wrong value)')}
+ }
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondrag): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondrag): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to drag event handler)')}
+ }
+ );
+ }
+ }
+function enterElement(event)
+ {event.preventDefault();
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragenter) : FAIL (items.length should be' + dataTypes.length + ')')}
+ if(event.dataTransfer.types.length != dataTypes.length)
+ {say('types.length (ondragenter) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != dataTypes.length; i++)
+ {if(event.dataTransfer.types[i] != dataTypes[i])
+ {say('Types (ondragenter): FAIL (dataTransfer.types[' + i + '] returns wrong value)')}
+ }
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {delete event.dataTransfer.items[i];
+ if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragenter): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragenter): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to drag event handler)')}
+ }
+ );
+ }
+ }
+function overElement(event)
+ {event.preventDefault();
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragover) : FAIL (items.length should be' + dataTypes.length + ')')}
+ if(event.dataTransfer.types.length != dataTypes.length)
+ {say('types.length (ondragover) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != dataTypes.length; i++)
+ {if(event.dataTransfer.types[i] != dataTypes[i])
+ {say('Types (ondragover): FAIL (dataTransfer.types[' + i + '] returns wrong value)')}
+ }
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragover): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragover): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to dragover event handler)')}
+ }
+ );
+ }
+ }
+function dataDrop(event)
+ {e = 0;
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondrop) : FAIL (items.length should be' + dataTypes.length + ')')}
+ if(event.dataTransfer.types.length != dataTypes.length)
+ {say('types.length (ondrop) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != dataTypes.length; i++)
+ {if(event.dataTransfer.types[i] != dataTypes[i])
+ {say('Types (ondrop): FAIL (dataTransfer.types[' + i + '] returns wrong value)')}
+ if(event.dataTransfer.getData(dataTypes[i]) != data[i])
+ {say('getData (ondrop): FAIL (getData(' + dataTypes[i] + ') returns wrong data)')}
+ }
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {delete event.dataTransfer.items[i];
+ if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondrop): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondrop): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0] != data[e++])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should pass' + data[e] + ')')}
+ }
+ );
+ }
+ document.querySelector('div').setAttribute('style','background-color:' + (result?'green':'red'));}
+function say(it)
+ {result = false;
+ document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+]]>
+</script>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('span'))">
+<p><span ondragstart="start(event)" ondrag="dragElement(event)">Drag me</span></p>
+<p>Drag selection above to the navy box below and drop it. Navy box should turn green.</p>
+<div ondragenter="enterElement(event)" ondragover="overElement(event)" ondrop="dataDrop(event)"/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/051.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/051.xhtml
new file mode 100644
index 00000000000..f073c60786e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/051.xhtml
@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>dataTransfer.types during link drag and drop</title>
+<style type="text/css">
+div
+ {height:100px;
+ width:100px;
+ padding:20px;
+ background-color:silver;}
+</style>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text/uri-list', 'text/plain', 'application/xml', 'application/xhtml+xml', 'application/mathml+xml', 'image/svg+xml', 'text/html', 'text/x-example'],
+data = ['data:text/plain,1', 'PASS', '<result>PASS</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>PASS</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">PASS</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>PASS</p></body></html>', 'PASS'],
+e = 0, result = true;
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ for(var i = event.dataTransfer.items.length; i != 0; i--)
+ {delete event.dataTransfer.items[i-1]}
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.items.add(data[i],dataTypes[i])}
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragstart) : FAIL (items.length should be' + dataTypes.length + ')')}
+ if(event.dataTransfer.types.length != dataTypes.length)
+ {say('types.length (ondragstart) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != dataTypes.length; i++)
+ {if(event.dataTransfer.getData(dataTypes[i]) != data[i])
+ {say('getData (ondragstart): FAIL (getData(' + dataTypes[i] + ') returns wrong data)')}
+ if(event.dataTransfer.types[i] != dataTypes[i])
+ {say('Types (ondragstart): FAIL (dataTransfer.types[' + i + '] returns wrong value)')}
+ }
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragstart): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragstart): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0] != data[e++])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should pass' + data[e] + ')')}
+ }
+ );
+ }
+ }
+function dragElement(event)
+ {event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondrag) : FAIL (items.length should be' + dataTypes.length + ')')}
+ if(event.dataTransfer.types.length != dataTypes.length)
+ {say('types.length (ondrag) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != dataTypes.length; i++)
+ {if(event.dataTransfer.types[i] != dataTypes[i])
+ {say('Types (ondrag): FAIL (dataTransfer.types[' + i + '] returns wrong value)')}
+ }
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondrag): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondrag): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to drag event handler)')}
+ }
+ );
+ }
+ }
+function enterElement(event)
+ {event.preventDefault();
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragenter) : FAIL (items.length should be' + dataTypes.length + ')')}
+ if(event.dataTransfer.types.length != dataTypes.length)
+ {say('types.length (ondragenter) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != dataTypes.length; i++)
+ {if(event.dataTransfer.types[i] != dataTypes[i])
+ {say('Types (ondragenter): FAIL (dataTransfer.types[' + i + '] returns wrong value)')}
+ }
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {delete event.dataTransfer.items[i];
+ if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragenter): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragenter): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to drag event handler)')}
+ }
+ );
+ }
+ }
+function overElement(event)
+ {event.preventDefault();
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragover) : FAIL (items.length should be' + dataTypes.length + ')')}
+ if(event.dataTransfer.types.length != dataTypes.length)
+ {say('types.length (ondragover) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != dataTypes.length; i++)
+ {if(event.dataTransfer.types[i] != dataTypes[i])
+ {say('Types (ondragover): FAIL (dataTransfer.types[' + i + '] returns wrong value)')}
+ }
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragover): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragover): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to dragover event handler)')}
+ }
+ );
+ }
+ }
+function dataDrop(event)
+ {e = 0;
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondrop) : FAIL (items.length should be' + dataTypes.length + ')')}
+ if(event.dataTransfer.types.length != dataTypes.length)
+ {say('types.length (ondrop) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != dataTypes.length; i++)
+ {if(event.dataTransfer.types[i] != dataTypes[i])
+ {say('Types (ondrop): FAIL (dataTransfer.types[' + i + '] returns wrong value)')}
+ if(event.dataTransfer.getData(dataTypes[i]) != data[i])
+ {say('getData (ondrop): FAIL (getData(' + dataTypes[i] + ') returns wrong data)')}
+ }
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {delete event.dataTransfer.items[i];
+ if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondrop): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondrop): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0] != data[e++])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should pass' + data[e] + ')')}
+ }
+ );
+ }
+ document.querySelector('div').setAttribute('style','background-color:' + (result?'green':'red'));}
+function say(it)
+ {result = false;
+ document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+]]>
+</script>
+</head>
+<body>
+<p><a href="data:text/plain,1" ondragstart="start(event)" ondrag="dragElement(event)">Drag me</a></p>
+<p>Drag link above to the silver box below and drop it. Silver box should turn green.</p>
+<div ondragenter="enterElement(event)" ondragover="overElement(event)" ondrop="dataDrop(event)"/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/052.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/052.xhtml
new file mode 100644
index 00000000000..65983990f29
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/052.xhtml
@@ -0,0 +1,158 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>dataTransfer.types during block element drag and drop</title>
+<style type="text/css">
+div
+ {height:100px;
+ width:100px;
+ padding:20px;
+ background-color:green;}
+p + div
+ {background-color:gray;}
+</style>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text/plain', 'text/uri-list', 'application/xml', 'application/xhtml+xml', 'application/mathml+xml', 'image/svg+xml', 'text/html', 'text/x-example'],
+data = ['PASS', 'data:text/plain,1', '<result>PASS</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>PASS</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">PASS</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>PASS</p></body></html>', 'PASS'],
+e = 0, result = true;
+function start(event)
+ {event.dataTransfer.items.clear();
+ event.dataTransfer.effectAllowed = 'copy';
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.items.add(data[i],dataTypes[i])}
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragstart) : FAIL (items.length should be' + dataTypes.length + ')')}
+ if(event.dataTransfer.types.length != dataTypes.length)
+ {say('types.length (ondragstart) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != dataTypes.length; i++)
+ {if(event.dataTransfer.getData(dataTypes[i]) != data[i])
+ {say('getData (ondragstart): FAIL (getData(' + dataTypes[i] + ') returns wrong data)')}
+ if(event.dataTransfer.types[i] != dataTypes[i])
+ {say('Types (ondragstart): FAIL (dataTransfer.types[' + i + '] returns wrong value)')}
+ }
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragstart): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragstart): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0] != data[e++])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should pass' + data[e] + ')')}
+ }
+ );
+ }
+ }
+function dragElement(event)
+ {event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondrag) : FAIL (items.length should be' + dataTypes.length + ')')}
+ if(event.dataTransfer.types.length != dataTypes.length)
+ {say('types.length (ondrag) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != dataTypes.length; i++)
+ {if(event.dataTransfer.types[i] != dataTypes[i])
+ {say('Types (ondrag): FAIL (dataTransfer.types[' + i + '] returns wrong value)')}
+ }
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondrag): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondrag): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to drag event handler)')}
+ }
+ );
+ }
+ }
+function enterElement(event)
+ {event.preventDefault();
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragenter) : FAIL (items.length should be' + dataTypes.length + ')')}
+ if(event.dataTransfer.types.length != dataTypes.length)
+ {say('types.length (ondragenter) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != dataTypes.length; i++)
+ {if(event.dataTransfer.types[i] != dataTypes[i])
+ {say('Types (ondragenter): FAIL (dataTransfer.types[' + i + '] returns wrong value)')}
+ }
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {delete event.dataTransfer.items[i];
+ if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragenter): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragenter): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to drag event handler)')}
+ }
+ );
+ }
+ }
+function overElement(event)
+ {event.preventDefault();
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragover) : FAIL (items.length should be' + dataTypes.length + ')')}
+ if(event.dataTransfer.types.length != dataTypes.length)
+ {say('types.length (ondragover) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != dataTypes.length; i++)
+ {if(event.dataTransfer.types[i] != dataTypes[i])
+ {say('Types (ondragover): FAIL (dataTransfer.types[' + i + '] returns wrong value)')}
+ }
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragover): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragover): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to dragover event handler)')}
+ }
+ );
+ }
+ }
+function dataDrop(event)
+ {e = 0;
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondrop) : FAIL (items.length should be' + dataTypes.length + ')')}
+ if(event.dataTransfer.types.length != dataTypes.length)
+ {say('types.length (ondrop) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != dataTypes.length; i++)
+ {if(event.dataTransfer.types[i] != dataTypes[i])
+ {say('Types (ondrop): FAIL (dataTransfer.types[' + i + '] returns wrong value)')}
+ if(event.dataTransfer.getData(dataTypes[i]) != data[i])
+ {say('getData (ondrop): FAIL (getData(' + dataTypes[i] + ') returns wrong data)')}
+ }
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {delete event.dataTransfer.items[i];
+ if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondrop): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondrop): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0] != data[e++])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should pass' + data[e] + ')')}
+ }
+ );
+ }
+ document.querySelector('p + div').setAttribute('style','background-color:' + (result?'green':'red'));}
+function say(it)
+ {result = false;
+ document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+]]>
+</script>
+</head>
+<body>
+<div draggable="true" ondragstart="start(event)" ondrag="dragElement(event)"/>
+<p>Drag green box above to the gray box below and drop it. Gray box should turn green.</p>
+<div ondragenter="enterElement(event)" ondragover="overElement(event)" ondrop="dataDrop(event)"/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/053.html b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/053.html
new file mode 100644
index 00000000000..9f1a0d730ac
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/053.html
@@ -0,0 +1,83 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Adding a file to dnd data store</title>
+ <style type="text/css">
+span { display: inline-block; height: 100px; width: 100px; background: orange; }
+span + span { background: blue; }
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ var drag = document.getElementsByTagName('span')[0];
+ drag.ondragstart = function (e) {
+ e.dataTransfer.setData('text','PASS');
+ e.dataTransfer.effectAllowed = 'copy';
+ var filein = document.getElementsByTagName('input')[0];
+ if( !filein.files ) {
+ document.getElementsByTagName('p')[0].innerHTML = 'FAIL - file API is not supported.';
+ return;
+ }
+ if( !filein.files[0] ) {
+ document.getElementsByTagName('p')[0].innerHTML = 'FAIL - no file was found in the file input.';
+ return;
+ }
+ var thefile = filein.files[0];
+ try {
+ e.dataTransfer.items.add(thefile);
+ } catch(err) {
+ document.getElementsByTagName('p')[0].innerHTML = 'FAIL - error when adding file';
+ e.preventDefault();
+ return;
+ }
+ if( e.dataTransfer.files.length != 1 ) {
+ document.getElementsByTagName('p')[0].innerHTML = 'FAIL - file was not attached to data store';
+ e.preventDefault();
+ return;
+ }
+ };
+ var drop = document.getElementsByTagName('span')[1];
+ drop.ondragenter = drop.ondragover = function (e) {
+ e.preventDefault();
+ };
+ drop.ondrop = function (e) {
+ e.preventDefault();
+ if( document.getElementsByTagName('p')[0].innerHTML ) { return; }
+ if( e.dataTransfer.files.length != 1 ) {
+ document.getElementsByTagName('p')[0].innerHTML = 'FAIL - file was not attached to data store during drop';
+ e.preventDefault();
+ return;
+ }
+ if( !window.FileReader ) {
+ document.getElementsByTagName('p')[0].innerHTML = 'No FileReader constructor';
+ e.preventDefault();
+ return;
+ }
+ var reader = new FileReader();
+ reader.onload = function () {
+ if( !reader.result ) {
+ document.getElementsByTagName('p')[0].innerHTML = 'No file data after load';
+ } else if( !document.getElementsByTagName('p')[0].innerHTML ) {
+ document.getElementsByTagName('p')[0].innerHTML = 'PASS';
+ }
+ };
+ reader.readAsBinaryString(e.dataTransfer.files[0]);
+ setTimeout(function () {
+ if( !reader.result ) {
+ document.getElementsByTagName('p')[0].innerHTML = 'No file data after timeout';
+ }
+ },1000);
+ };
+};
+ </script>
+ </head>
+ <body>
+ <ol>
+ <li>Select a non-empty file on your computer using the following input: <input type="file"></li>
+ <li>Drag the orange square onto the blue square and release it:<br><span draggable="true"></span> <span></span><br>
+ If a prompt appears, accept it.</li>
+ <li>Fail if new text does not appear below.</li>
+ </ol>
+ <p></p>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/054.html b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/054.html
new file mode 100644
index 00000000000..0c6a1200a30
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/054.html
@@ -0,0 +1,83 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Adding a file to dnd data store with drag out of window</title>
+ <style type="text/css">
+span { display: inline-block; height: 100px; width: 100px; background: orange; }
+span + span { background: blue; }
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ var drag = document.getElementsByTagName('span')[0];
+ drag.ondragstart = function (e) {
+ e.dataTransfer.setData('text','PASS');
+ e.dataTransfer.effectAllowed = 'copy';
+ var filein = document.getElementsByTagName('input')[0];
+ if( !filein.files ) {
+ document.getElementsByTagName('p')[0].innerHTML = 'FAIL - file API is not supported.';
+ return;
+ }
+ if( !filein.files[0] ) {
+ document.getElementsByTagName('p')[0].innerHTML = 'FAIL - no file was found in the file input.';
+ return;
+ }
+ var thefile = filein.files[0];
+ try {
+ e.dataTransfer.items.add(thefile);
+ } catch(err) {
+ document.getElementsByTagName('p')[0].innerHTML = 'FAIL - error when adding file';
+ e.preventDefault();
+ return;
+ }
+ if( e.dataTransfer.files.length != 1 ) {
+ document.getElementsByTagName('p')[0].innerHTML = 'FAIL - file was not attached to data store';
+ e.preventDefault();
+ return;
+ }
+ };
+ var drop = document.getElementsByTagName('span')[1];
+ drop.ondragenter = drop.ondragover = function (e) {
+ e.preventDefault();
+ };
+ drop.ondrop = function (e) {
+ e.preventDefault();
+ if( document.getElementsByTagName('p')[0].innerHTML ) { return; }
+ if( e.dataTransfer.files.length != 1 ) {
+ document.getElementsByTagName('p')[0].innerHTML = 'FAIL - file was not attached to data store during drop';
+ e.preventDefault();
+ return;
+ }
+ if( !window.FileReader ) {
+ document.getElementsByTagName('p')[0].innerHTML = 'No FileReader constructor';
+ e.preventDefault();
+ return;
+ }
+ var reader = new FileReader();
+ reader.onload = function () {
+ if( !reader.result ) {
+ document.getElementsByTagName('p')[0].innerHTML = 'No file data after load';
+ } else if( !document.getElementsByTagName('p')[0].innerHTML ) {
+ document.getElementsByTagName('p')[0].innerHTML = 'PASS';
+ }
+ };
+ reader.readAsBinaryString(e.dataTransfer.files[0]);
+ setTimeout(function () {
+ if( !reader.result ) {
+ document.getElementsByTagName('p')[0].innerHTML = 'No file data after timeout';
+ }
+ },1000);
+ };
+};
+ </script>
+ </head>
+ <body>
+ <ol>
+ <li>Select a non-empty file on your computer using the following input: <input type="file"></li>
+ <li>Drag the orange square outside the browser window (not over the taskbar), then back onto the blue square and release it:<br><span draggable="true"></span> <span></span><br>
+ If a prompt appears, accept it.</li>
+ <li>Fail if new text does not appear below.</li>
+ </ol>
+ <p></p>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/055.html b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/055.html
new file mode 100644
index 00000000000..570571e9bd7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/055.html
@@ -0,0 +1,46 @@
+<!doctype html>
+<html>
+ <head>
+ <title>text/uri-list conversion</title>
+ <style type="text/css">
+div { height: 100px; width: 100px; background: orange; }
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ var drag = document.getElementsByTagName('div')[0], fails = [];
+ drag.ondragstart = function (e) {
+ e.dataTransfer.setData('url','http://example.com/');
+ if( !e.dataTransfer.getData('url') ) {
+ document.getElementsByTagName('p')[0].innerHTML = "FAIL - getData('url') returned nothing";
+ } else if( e.dataTransfer.getData('url') != e.dataTransfer.getData('text/uri-list') ) {
+ document.getElementsByTagName('p')[0].innerHTML = 'FAIL - text/uri-list is not the same as url';
+ } else {
+
+ e.dataTransfer.setData('url','#foo\r\n http://example.com/#bar \r\n http://example.org/');
+ if( e.dataTransfer.getData('url') != 'http://example.com/#bar' ) {
+ document.getElementsByTagName('p')[0].innerHTML = 'FAIL - only the first URL should be returned - "'+e.dataTransfer.getData('url')+'"';
+ } else if( e.dataTransfer.getData('text/uri-list') != '#foo\r\n http://example.com/#bar \r\n http://example.org/' ) {
+ document.getElementsByTagName('p')[0].innerHTML = 'FAIL - text/uri-list should return the full data';
+ } else {
+
+ e.dataTransfer.setData('url',' ');
+ if( e.dataTransfer.getData('url') ) {
+ document.getElementsByTagName('p')[0].innerHTML = 'FAIL - space was not a valid URL so an empty string should have been returned';
+ } else {
+ document.getElementsByTagName('p')[0].innerHTML = 'PASS';
+ }
+
+ }
+
+ }
+ e.preventDefault();
+ };
+};
+ </script>
+ </head>
+ <body>
+ <div draggable="true"></div>
+ <p>Attempt to drag the orange square.</p>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/056.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/056.xhtml
new file mode 100644
index 00000000000..dd85dbe881b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/056.xhtml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Caseinsensitivity in dataTransfer.setData/getData</title>
+<style type="text/css">
+div
+ {height:100px;
+ width:100px;
+ padding:20px;
+ background-color:silver;}
+</style>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text/uri-list', 'text/plain', 'application/xml', 'application/xhtml+xml', 'application/mathml+xml', 'image/svg+xml', 'text/html', 'text/x-example'],
+data = ['data:text/plain,1', 'PASS', '<result>PASS</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>PASS</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">PASS</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>PASS</p></body></html>', 'PASS'];
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData((i%2 == 0)?(dataTypes[i].toUpperCase()):(dataTypes[i].replace(/i/g,'I')), data[i]);}
+ say('items.length (dragstart) : ' + ((event.dataTransfer.items.length >= dataTypes.length)?'PASS':'FAIL'));
+ }
+function dragElement(event)
+ {for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during drag)')}
+ }
+ if(event.dataTransfer.items.length < dataTypes.length)
+ {say('items.length (dragover) : FAIL')}
+ }
+function enterElement(event)
+ {event.preventDefault();
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during dragenter)')}
+ }
+ say('items.length (dragenter) : ' + ((event.dataTransfer.items.length >= dataTypes.length)?'PASS':'FAIL'));}
+function dataDrop(event)
+ {say('items.length (drop) : ' + ((event.dataTransfer.items.length >= dataTypes.length)?'PASS':'FAIL'));
+ for(var i = 0; i != dataTypes.length; i++)
+ {say('getData(' + dataTypes[i] + ') : ' + ((event.dataTransfer.getData((i%2 == 0)?(dataTypes[i].replace(/t/g,'T')):(dataTypes[i].toUpperCase())) == data[i])?'PASS':'FAIL'));}
+ document.querySelector('div').setAttribute('style','background-color:green');}
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+]]>
+</script>
+</head>
+<body>
+<p><a href="data:text/plain,1" ondragstart="start(event)" ondrag="dragElement(event)">Drag me</a></p>
+<p>Drag link above to the silver box below and drop it. Silver box should turn green and test results should appear below.</p>
+<div ondragenter="enterElement(event)" ondragover="return false;" ondrop="dataDrop(event)"/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/057.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/057.xhtml
new file mode 100644
index 00000000000..4c6f6f5798b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/057.xhtml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Various data item type strings in dataTransfer.setData/getData</title>
+<style type="text/css">
+div
+ {min-height:100px;
+ width:100px;
+ padding:20px;
+ color:white;
+ background-color:navy;}
+</style>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text/plain', 'http://', '<?xml version="1.0" encoding="utf-8"?>', '<html xmlns="http://www.w3.org/1999/xhtml"/>', '<mn>1</mn>', '☺', 'type="text/html"', '[({#;:,.`~*-_=+\|/%!?&$@^})]'],
+data = ['Drag me', 'data:text/plain,1', '<result>PASS</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>PASS</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">PASS</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>PASS</p></body></html>', 'PASS'];
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], data[i]);}
+ say('items.length (dragstart) : ' + ((event.dataTransfer.items.length >= dataTypes.length)?'PASS':'FAIL'));
+ }
+function dragElement(event)
+ {for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during drag)')}
+ }
+ if(event.dataTransfer.items.length < dataTypes.length)
+ {say('items.length (dragover) : FAIL')}
+ }
+function enterElement(event)
+ {event.preventDefault();
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during dragenter)')}
+ }
+ say('items.length (dragenter) : ' + ((event.dataTransfer.items.length >= dataTypes.length)?'PASS':'FAIL'));}
+function dataDrop(event)
+ {say('items.length (drop) : ' + ((event.dataTransfer.items.length >= dataTypes.length)?'PASS':'FAIL'));
+ for(var i = 0; i != dataTypes.length; i++)
+ {say('getData(string' + i + ') : ' + ((event.dataTransfer.getData(dataTypes[i]) == data[i])?'PASS':'FAIL'));}
+ document.querySelector('div').setAttribute('style','background-color:green');}
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+]]>
+</script>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('span'))">
+<p><span ondragstart="start(event)" ondrag="dragElement(event)">Drag me</span></p>
+<p>Drag selection above to the navy box below and drop it. Navy box should turn green and test results should appear below.</p>
+<div ondragenter="enterElement(event)" ondragover="return false;" ondrop="dataDrop(event)"/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/058.html b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/058.html
new file mode 100644
index 00000000000..1bf9e58018f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/058.html
@@ -0,0 +1,79 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Dropping file into dropzone</title>
+ <style type="text/css">
+span { display: inline-block; height: 100px; width: 100px; background: orange; }
+span + span { background: blue; }
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ var drag = document.getElementsByTagName('span')[0];
+ drag.ondragstart = function (e) {
+ e.dataTransfer.setData('text','PASS');
+ e.dataTransfer.effectAllowed = 'copy';
+ var filein = document.getElementsByTagName('input')[0];
+ if( !filein.files ) {
+ document.getElementsByTagName('p')[0].innerHTML = 'FAIL - file API is not supported.';
+ return;
+ }
+ if( !filein.files[0] ) {
+ document.getElementsByTagName('p')[0].innerHTML = 'FAIL - no file was found in the file input.';
+ return;
+ }
+ var thefile = filein.files[0];
+ try {
+ e.dataTransfer.items.add(thefile);
+ } catch(err) {
+ document.getElementsByTagName('p')[0].innerHTML = 'FAIL - error when adding file';
+ e.preventDefault();
+ return;
+ }
+ if( e.dataTransfer.files.length != 1 ) {
+ document.getElementsByTagName('p')[0].innerHTML = 'FAIL - file was not attached to data store';
+ e.preventDefault();
+ return;
+ }
+ };
+ document.getElementsByTagName('span')[1].ondrop = function (e) {
+ e.preventDefault();
+ if( document.getElementsByTagName('p')[0].innerHTML ) { return; }
+ if( e.dataTransfer.files.length != 1 ) {
+ document.getElementsByTagName('p')[0].innerHTML = 'FAIL - file was not attached to data store during drop';
+ e.preventDefault();
+ return;
+ }
+ if( !window.FileReader ) {
+ document.getElementsByTagName('p')[0].innerHTML = 'No FileReader constructor';
+ e.preventDefault();
+ return;
+ }
+ var reader = new FileReader();
+ reader.onload = function () {
+ if( !reader.result ) {
+ document.getElementsByTagName('p')[0].innerHTML = 'No file data after load';
+ } else if( !document.getElementsByTagName('p')[0].innerHTML ) {
+ document.getElementsByTagName('p')[0].innerHTML = 'PASS';
+ }
+ };
+ reader.readAsBinaryString(e.dataTransfer.files[0]);
+ setTimeout(function () {
+ if( !reader.result ) {
+ document.getElementsByTagName('p')[0].innerHTML = 'No file data after timeout';
+ }
+ },1000);
+ };
+};
+ </script>
+ </head>
+ <body>
+ <ol>
+ <li>Select a non-empty plain text file on your computer using the following input: <input type="file"></li>
+ <li>Drag the orange square onto the blue square and release it:<br><span draggable="true"></span> <span dropzone="copy file:text/plain"></span><br>
+ If a prompt appears, accept it.</li>
+ <li>Fail if new text does not appear below.</li>
+ </ol>
+ <p></p>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/datastore/helper-drop-box-here.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/helper-drop-box-here.xhtml
new file mode 100644
index 00000000000..70341c5c6f5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/datastore/helper-drop-box-here.xhtml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop datastore: helper file</title>
+<style type="text/css">
+html, body
+ {height:100%;}
+</style>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text/plain', 'text/uri-list', 'application/xml', 'application/xhtml+xml', 'application/mathml+xml', 'image/svg+xml', 'text/html', 'text/x-example'],
+data = ['PASS', 'data:text/plain,1', '<result>PASS</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>PASS</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">PASS</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>PASS</p></body></html>', 'PASS'];
+function enterElement(event)
+ {event.preventDefault();
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during dragenter)')}
+ }
+ say('items.length (dragenter) : ' + ((event.dataTransfer.items.length >= dataTypes.length)?'PASS':'FAIL'));}
+function dataDrop(event)
+ {say('items.length (drop) : ' + ((event.dataTransfer.items.length >= dataTypes.length)?'PASS':'FAIL'));
+ for(var i = 0; i != dataTypes.length; i++)
+ {say('getData(' + dataTypes[i] + ') : ' + ((event.dataTransfer.getData(dataTypes[i]) == data[i])?'PASS':'FAIL'));}
+ document.querySelector('body').setAttribute('style','background-color:teal;color:white;');}
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+]]>
+</script>
+</head>
+<body ondragenter="enterElement(event)" ondragover="return false;" ondrop="dataDrop(event)">
+<p>Drop box here. Frame should turn green and test results should appear below.</p>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/dom/draggable.html b/tests/wpt/web-platform-tests/html/editing/dnd/dom/draggable.html
new file mode 100644
index 00000000000..600b0ee350d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/dom/draggable.html
@@ -0,0 +1,207 @@
+<!DOCTYPE html>
+<meta charset='utf-8'>
+<title>drag &amp; drop – draggable attribute</title>
+<style>div#test_elements { display: none; }</style>
+
+<script src='/resources/testharness.js'></script>
+<script src='/resources/testharnessreport.js'></script>
+
+<noscript><p>Enable JavaScript and reload.</p></noscript>
+
+<div id='log'></div>
+
+<div id='test_elements'>
+
+ <div id='defaults'>
+ <a href='#'>.</a>
+ <div></div>
+ <img src='../resources/1x1-transparent.gif'>
+ </div>
+
+ <div id='draggable'>
+ <a draggable='true' href='#'>.</a>
+ <div draggable='true'></div>
+ <img draggable='true' src='../resources/1x1-transparent.gif'>
+ </div>
+
+ <div id='draggable_false'>
+ <a draggable='false' href='#'>.</a>
+ <div draggable='false'></div>
+ <img draggable='false' src='../resources/1x1-transparent.gif'>
+ </div>
+
+ <div id='draggable_auto'>
+ <a draggable='auto' href='#'>.</a>
+ <div draggable='auto'></div>
+ <img draggable='auto' src='../resources/1x1-transparent.gif'>
+ </div>
+
+ <div id='draggable_foo'>
+ <a draggable='foo' href='#'>.</a>
+ <div draggable='foo'></div>
+ <img draggable='foo' src='../resources/1x1-transparent.gif'>
+ </div>
+
+ <div id='changable_true'>
+ <a href='#'>.</a>
+ <div></div>
+ <img src='../resources/1x1-transparent.gif'>
+ </div>
+
+ <div id='changable_false'>
+ <a href='#'>.</a>
+ <div></div>
+ <img src='../resources/1x1-transparent.gif'>
+ </div>
+
+ <div id='changable_foo'>
+ <a href='#'>.</a>
+ <div></div>
+ <img src='../resources/1x1-transparent.gif'>
+ </div>
+
+
+</div>
+
+<script>
+var foo = document.getElementById('foo');
+
+/* Does the .draggable property exist? */
+test(function () {
+ assert_idl_attribute(document.querySelector('#defaults a'), 'draggable');
+}, 'an <a> element should have a draggable property');
+
+test(function () {
+ assert_idl_attribute(document.querySelector('#defaults div'), 'draggable');
+}, 'a <div> element should have a draggable property');
+
+test(function () {
+ assert_idl_attribute(document.querySelector('#defaults img'), 'draggable');
+}, 'an <img> element should have a draggable property');
+
+
+/* Check the default values on different types of elements */
+test(function () {
+ assert_true(document.querySelector('#defaults a').draggable);
+}, 'an <a> element should be draggable by default');
+
+test(function () {
+ assert_false(document.querySelector('#defaults div').draggable);
+}, 'a <div> element should not be draggable by default');
+
+test(function () {
+ assert_true(document.querySelector('#defaults img').draggable);
+}, 'an <img> element should be draggable by default');
+
+
+/* If draggable="true" is set, all the elements should be draggable */
+test(function () {
+ assert_true(document.querySelector('#draggable a').draggable);
+}, 'an <a> element with draggable="true" should be draggable');
+
+test(function () {
+ assert_true(document.querySelector('#draggable div').draggable);
+}, 'a <div> element with draggable="true" should be draggable');
+
+test(function () {
+ assert_true(document.querySelector('#draggable img').draggable);
+}, 'an <img> element with draggable="true" should be draggable');
+
+
+/* If draggable="false" is set, none of the elements should be draggable */
+test(function () {
+ assert_false(document.querySelector('#draggable_false a').draggable);
+}, 'an <a> element with draggable="false" should not be draggable');
+
+test(function () {
+ assert_false(document.querySelector('#draggable_false div').draggable);
+}, 'a <div> element with draggable="false" should not be draggable');
+
+test(function () {
+ assert_false(document.querySelector('#draggable_false img').draggable);
+}, 'an <img> element with draggable="false" should not be draggable');
+
+
+/* If draggable="auto" is set, fall back to the defaults */
+test(function () {
+ assert_true(document.querySelector('#draggable_auto a').draggable);
+}, 'an <a> element with draggable="auto" should be draggable');
+
+test(function () {
+ assert_false(document.querySelector('#draggable_auto div').draggable);
+}, 'a <div> element with draggable="auto" should not be draggable');
+
+test(function () {
+ assert_true(document.querySelector('#draggable_auto img').draggable);
+}, 'an <img> element with draggable="auto" should be draggable');
+
+
+/* If draggable="foo" is set, fall back to the defaults */
+test(function () {
+ assert_true(document.querySelector('#draggable_foo a').draggable);
+}, 'an <a> element with draggable="foo" should be draggable');
+
+test(function () {
+ assert_false(document.querySelector('#draggable_foo div').draggable);
+}, 'a <div> element with draggable="foo" should not be draggable');
+
+test(function () {
+ assert_true(document.querySelector('#draggable_foo img').draggable);
+}, 'an <img> element with draggable="foo" should be draggable');
+
+
+/* Setting the element.droppable attribute to true for all elements */
+test(function () {
+ document.querySelector('#changable_true a').draggable = true;
+ assert_true(document.querySelector('#changable_true a').draggable);
+}, 'an <a> element with the draggable property set to true through a script should be draggable');
+
+test(function () {
+ document.querySelector('#changable_true div').draggable = true;
+ assert_true(document.querySelector('#changable_true div').draggable);
+}, 'a <div> element with the draggable property set to true through a script should be draggable');
+
+test(function () {
+ document.querySelector('#changable_true img').draggable = true;
+ assert_true(document.querySelector('#changable_true img').draggable);
+}, 'an <img> element with the draggable property set to true through a script should be draggable');
+
+
+/* Setting the element.droppable attribute to false for all elements */
+test(function () {
+ document.querySelector('#changable_false a').draggable = false;
+ assert_false(document.querySelector('#changable_false a').draggable);
+}, 'an <a> element with the draggable property set to false through a script should not be draggable');
+
+test(function () {
+ document.querySelector('#changable_false div').draggable = false;
+ assert_false(document.querySelector('#changable_false div').draggable);
+}, 'a <div> element with the draggable property set to false through a script should not be draggable');
+
+test(function () {
+ document.querySelector('#changable_false img').draggable = false;
+ assert_false(document.querySelector('#changable_false img').draggable);
+}, 'an <img> element with the draggable property set to false through a script should not be draggable');
+
+
+/* Setting the element.droppable attribute to "foo" for all elements */
+test(function () {
+ document.querySelector('#changable_foo a').draggable = 'foo';
+ assert_true(document.querySelector('#changable_foo a').draggable);
+}, 'an <a> element with the draggable property set to "foo" through a script should be draggable');
+
+test(function () {
+ document.querySelector('#changable_foo div').draggable = 'auto';
+ assert_true(document.querySelector('#changable_foo div').draggable);
+}, 'a <div> element with the draggable property set to "foo" through a script should be draggable');
+
+test(function () {
+ document.querySelector('#changable_foo img').draggable = 'foo';
+ assert_true(document.querySelector('#changable_foo img').draggable);
+}, 'an <img> element with the draggable property set to "foo" through a script should be draggable');
+</script>
+
+
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/dom/events.html b/tests/wpt/web-platform-tests/html/editing/dnd/dom/events.html
new file mode 100644
index 00000000000..e2b521f2704
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/dom/events.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<meta charset='utf-8'>
+<title>drag &amp; drop – events</title>
+
+<script src='/resources/testharness.js'></script>
+<script src='/resources/testharnessreport.js'></script>
+
+
+<noscript><p>Enable JavaScript and reload.</p></noscript>
+
+<div id='log'></div>
+
+<script>
+
+var element = document.createElement('div');
+
+test(function () {
+ assert_equals(element.ondragstart, null);
+}, 'element.ondragstart initial value');
+
+test(function () {
+ assert_equals(element.ondrag, null);
+}, 'element.ondrag must initial value');
+
+test(function () {
+ assert_equals(element.ondragenter, null);
+}, 'element.ondragenter initial value');
+
+test(function () {
+ assert_equals(element.ondragleave, null);
+}, 'element.ondragleave initial value');
+
+test(function () {
+ assert_equals(element.ondragover, null);
+}, 'element.ondragover initial value');
+
+test(function () {
+ assert_equals(element.ondrop, null);
+}, 'element.ondrop initial value');
+
+test(function () {
+ assert_equals(element.ondragend, null);
+}, 'element.ondragend initial value');
+
+</script>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/dom/specials.html b/tests/wpt/web-platform-tests/html/editing/dnd/dom/specials.html
new file mode 100644
index 00000000000..e83eb68aadc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/dom/specials.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Exposing drag &amp; drop events on document and window</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+
+ <div id="log">Enable script and reload</div>
+ <script type="text/javascript">
+var allEvents = ['ondragstart','ondrag','ondragover','ondragenter','ondragleave','ondrop','ondragend'];
+var allObjects = [['window',window],['document',document],['HTMLElement',document.createElement('div')]];
+var fails = [];
+for( var i = 0; i < allObjects.length; i++ ) {
+ for( var j = 0; j < allEvents.length; j++ ) {
+ test(function () {
+ assert_true(allEvents[j] in allObjects[i][1]);
+ }, allEvents[j] + ' in ' + allObjects[i][0]);
+ }
+}
+ </script>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/draggable-areas/border-radius.html b/tests/wpt/web-platform-tests/html/editing/dnd/draggable-areas/border-radius.html
new file mode 100644
index 00000000000..f767850f9ef
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/draggable-areas/border-radius.html
@@ -0,0 +1,25 @@
+<!DOCTYPe html>
+<meta charset='utf-8'>
+<title>drag and drop – draggable area boundaries, border-radius</title>
+<style>
+a {
+ display: block;
+ height: 200px;
+ width: 200px;
+ background-color: blue;
+ border-radius: 100px;
+}
+div {
+ border: 1px solid black;
+ height: 200px;
+ width: 200px;
+}
+</style>
+
+<ol>
+ <li>Try dragging the white area within the black square, outside the blue
+ circle. It should <em>not</em> be draggable.</li>
+ <li>Drag the blue circle below. It should be draggable.</li>
+</ol>
+
+<div><a draggable="true" ondragstart="event.dataTransfer.effectAllowed ='copy'"></a></div>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/draggable-areas/border.html b/tests/wpt/web-platform-tests/html/editing/dnd/draggable-areas/border.html
new file mode 100644
index 00000000000..1b6f8e95576
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/draggable-areas/border.html
@@ -0,0 +1,16 @@
+<!DOCTYPe html>
+<meta charset='utf-8'>
+<title>drag and drop – draggable areas – border</title>
+<style>
+a {
+ display: block;
+ height: 200px;
+ width: 200px;
+ background-color: blue;
+ border: 10px solid orange;
+}
+</style>
+
+<p>Try dragging the orange border of the blue box below, in a downwards direction. It should be draggable.</p>
+
+<a href='#' draggable="true" ondragstart="event.dataTransfer.effectAllowed ='copy'"></a>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/draggable-areas/box-shadow.html b/tests/wpt/web-platform-tests/html/editing/dnd/draggable-areas/box-shadow.html
new file mode 100644
index 00000000000..4fc40cb0f84
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/draggable-areas/box-shadow.html
@@ -0,0 +1,16 @@
+<!DOCTYPe html>
+<meta charset='utf-8'>
+<title>drag and drop – draggable areas – box-shadow</title>
+<style>
+a {
+ display: block;
+ height: 200px;
+ width: 200px;
+ background-color: blue;
+ box-shadow: 10px 10px 0 orange;
+}
+</style>
+
+<p>Try dragging the orange area along the sides of the blue box below. It should <em>not</em> be draggable.</p>
+
+<a href='#' draggable="true" ondragstart="event.dataTransfer.effectAllowed ='copy'"></a>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/draggable-areas/outline.html b/tests/wpt/web-platform-tests/html/editing/dnd/draggable-areas/outline.html
new file mode 100644
index 00000000000..8872997fc05
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/draggable-areas/outline.html
@@ -0,0 +1,16 @@
+<!DOCTYPe html>
+<meta charset='utf-8'>
+<title>drag and drop – draggable areas – outline</title>
+<style>
+a {
+ display: block;
+ height: 200px;
+ width: 200px;
+ background-color: blue;
+ outline: 10px solid orange;
+}
+</style>
+
+<p>Try dragging the orange border of the blue box below. It should <em>not</em> be draggable.</p>
+
+<a href='#' draggable="true" ondragstart="event.dataTransfer.effectAllowed ='copy'"></a>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/draggable-areas/transform.html b/tests/wpt/web-platform-tests/html/editing/dnd/draggable-areas/transform.html
new file mode 100644
index 00000000000..6800c64ad44
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/draggable-areas/transform.html
@@ -0,0 +1,22 @@
+<!DOCTYPe html>
+<meta charset='utf-8'>
+<title>drag and drop – draggable area boundaries – transformed elements</title>
+<style>
+a {
+ display: block;
+ height: 200px;
+ width: 200px;
+ background-color: blue;
+ margin-left: 100px;
+ -moz-transform: rotate(-45deg) skew(15deg, 15deg);
+ -o-transform: rotate(-45deg) skew(15deg, 15deg);
+ -webkit-transform: rotate(-45deg) skew(15deg, 15deg);
+ transform: rotate(-45deg) skew(15deg, 15deg);
+}
+</style>
+<ol>
+ <li>Try dragging the blue box below by clicking and holding <em>just</em>
+ outside its skewed edges. It should <em>not</em> be draggable.</li>
+ <li><p>Drag the blue box below. It should be draggable.</p>
+
+<a draggable="true" ondragstart="event.dataTransfer.effectAllowed ='copy'">TEST</a>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/draggable-areas/z-index.html b/tests/wpt/web-platform-tests/html/editing/dnd/draggable-areas/z-index.html
new file mode 100644
index 00000000000..b1f08cb7897
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/draggable-areas/z-index.html
@@ -0,0 +1,35 @@
+<!DOCTYPe html>
+<meta charset='utf-8'>
+<title>drag and drop – feedback overlay for heavily styled elements – 008</title>
+<style>
+a {
+ display: block;
+ height: 200px;
+ width: 200px;
+ background-color: blue;
+ position: absolute;
+ top: 100px;
+ left: 10px;
+ z-index: 1;
+}
+
+div {
+ background-color: orange;
+ position: absolute;
+ height: 200px;
+ width: 200px;
+ top: 150px;
+ left: 20px;
+ z-index: 2;
+ opacity: 0.9;
+}
+
+
+</style>
+
+<p>Click and hold the part of the orange box that overlaps the blue box. Then
+move your pointing device. The blue box should <em>not</em> be dragged.
+
+<a draggable="true" ondragstart="event.dataTransfer.effectAllowed ='copy'">TEST</a>
+
+<div></div>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/drop/001.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/drop/001.xhtml
new file mode 100644
index 00000000000..970e077e688
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/drop/001.xhtml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop: allowed effects 'copy','move','link'</title>
+<style type="text/css">
+div
+ {display:inline-block;
+ vertical-align:top;
+ background-color:olive;
+ color:white;
+ padding:20px;
+ width:100px;
+ height:100px;}
+div:nth-child(2)
+ {background-color:green;}
+div:nth-child(3)
+ {background-color:teal;}
+</style>
+<script type="application/ecmascript">
+var effects = ['copy','move','link'], i = 0;
+function selectText()
+ {window.getSelection().selectAllChildren(document.querySelector('p'))}
+function dropSelection(event)
+ {event.target.appendChild(document.createTextNode((event.dataTransfer.dropEffect == effects[i] &amp;&amp; event.dataTransfer.effectAllowed == effects[i])?' PASS ':' FAIL '));
+ i = (i + 1)%3;
+ selectText();}
+function start(event)
+ {event.dataTransfer.effectAllowed = effects[i]}
+</script>
+</head>
+<body onload="selectText()">
+<p ondragstart="start(event)">Drag me</p>
+<div ondragenter="event.preventDefault()" ondragover="return false" ondrop="dropSelection(event)"/>
+<div ondragenter="event.preventDefault()" ondragover="return false" ondrop="dropSelection(event)"/>
+<div ondragenter="event.preventDefault()" ondragover="return false" ondrop="dropSelection(event)"/>
+<p>You should be able to drag selection and drop it onto any of the green boxes.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/drop/002.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/drop/002.xhtml
new file mode 100644
index 00000000000..13c64251a3d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/drop/002.xhtml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Text input selection drag and drop: allowed effects 'copy','move','link'</title>
+<style type="text/css">
+div
+ {display:inline-block;
+ vertical-align:top;
+ background-color:olive;
+ color:white;
+ padding:20px;
+ width:100px;
+ height:100px;}
+div:nth-child(2)
+ {background-color:green;}
+div:nth-child(3)
+ {background-color:teal;}
+</style>
+<script type="application/ecmascript">
+var effects = ['copy','move','link'], i = 0;
+function selectText()
+ {document.querySelector('input').select()}
+function dropSelection(event)
+ {event.target.appendChild(document.createTextNode((event.dataTransfer.dropEffect == effects[i] &amp;&amp; event.dataTransfer.effectAllowed == effects[i])?' PASS ':' FAIL '));
+ i = (i + 1)%3;
+ selectText();}
+function start(event)
+ {event.dataTransfer.effectAllowed = effects[i]}
+</script>
+</head>
+<body onload="selectText()">
+<p><input value="Drag me" ondragstart="start(event)"/></p>
+<div ondragenter="event.preventDefault()" ondragover="return false" ondrop="dropSelection(event)"/>
+<div ondragenter="event.preventDefault()" ondragover="return false" ondrop="dropSelection(event)"/>
+<div ondragenter="event.preventDefault()" ondragover="return false" ondrop="dropSelection(event)"/>
+<p>You should be able to drag selection and drop it onto any of the green boxes.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/drop/003.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/drop/003.xhtml
new file mode 100644
index 00000000000..44b907ac7d0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/drop/003.xhtml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Link drag and drop: allowed effects 'copy','move','link'</title>
+<style type="text/css">
+div
+ {display:inline-block;
+ vertical-align:top;
+ background-color:olive;
+ color:white;
+ padding:20px;
+ width:100px;
+ height:100px;}
+div:nth-child(2)
+ {background-color:green;}
+div:nth-child(3)
+ {background-color:teal;}
+</style>
+<script type="application/ecmascript">
+var effects = ['copy','move','link'], i = 0;
+function dropSelection(event)
+ {event.target.appendChild(document.createTextNode((event.dataTransfer.dropEffect == effects[i] &amp;&amp; event.dataTransfer.effectAllowed == effects[i])?' PASS ':' FAIL '));
+ i = (i + 1)%3;}
+function start(event)
+ {event.dataTransfer.effectAllowed = effects[i]}
+</script>
+</head>
+<body onload="selectText()">
+<p><a href="data:text/plain,1" ondragstart="start(event)">Drag me</a></p>
+<div ondragenter="event.preventDefault()" ondragover="return false" ondrop="dropSelection(event)"/>
+<div ondragenter="event.preventDefault()" ondragover="return false" ondrop="dropSelection(event)"/>
+<div ondragenter="event.preventDefault()" ondragover="return false" ondrop="dropSelection(event)"/>
+<p>You should be able to drag link and drop it onto any of the green boxes.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/drop/004.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/drop/004.xhtml
new file mode 100644
index 00000000000..7376d045b03
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/drop/004.xhtml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>PNG image drag and drop: allowed effects 'copy','move','link'</title>
+<style type="text/css">
+div
+ {display:inline-block;
+ vertical-align:top;
+ background-color:olive;
+ color:white;
+ padding:20px;
+ width:100px;
+ height:100px;}
+div:nth-child(2)
+ {background-color:green;}
+div:nth-child(3)
+ {background-color:teal;}
+</style>
+<script type="application/ecmascript">
+var effects = ['copy','move','link'], i = 0;
+function dropSelection(event)
+ {event.target.appendChild(document.createTextNode((event.dataTransfer.dropEffect == effects[i] &amp;&amp; event.dataTransfer.effectAllowed == effects[i])?' PASS ':' FAIL '));
+ i = (i + 1)%3;}
+function start(event)
+ {event.dataTransfer.effectAllowed = effects[i]}
+</script>
+</head>
+<body onload="selectText()">
+<p><img ondragstart="start(event)" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAEq0lEQVR42u1dvU4bQRAeR0RCCilSp0peIoKGB4DSXYRDlcZlFClKBI4bB/kV/AymIDwCTahiicaioEOxhCsjWVTJziyKMfYZn+9ud3bvG2mEZB13u9+nndmf2Rki7fKFXtEBbVKD9o22jB4bPaND6hm9Mjo0enevw/vfevKMfbYl/8vv4HdBUkvFALhltG2A7dN3+pur8jv53fwN/hZkjjRo3eiuAatjdJA7CcnkDOSb/G1uQ6mFzUeDagaQrvl764yEJOU22LbUymXaGrRhOt40OvJOQvLIGUkbP9GLeIn4SM9NJ+tOTVI+Jq0ubY9sVFRNxy6DIWKWmEvpQ/ByQNumI+fBEjHrZ86lT8HJV3ptGn8aDRGzxJxKHwMZFe9Mg6+jJWNCyrX0VbUc0nuj4+jJmPiWsfRZodN+ZvSoNETMjpYjwUCFfKaXpjEnpSVjQsqJYOF5ZLw1elF6MiakXAgmnpw378DegIgZUm4EGw8jA2QsIuUbvXHpM2CmljFfhfsUO5uCA0/j6AudfZV5arv6WuVHcYs+ALwqKTkvHnmLoEwr8CJW9Llts9iNwvj3plzsfeWyIRnzrq37kfIzq6naBpA5a6bzlJgOl/SMkl+rklEFgIX5k5THwTYgIdwzcP2jhM/o19KsOeoArnBS6suaqo2gQnXCJWSwXNwXB4gBMFekNBeTwSGUmiMK4yNktDhsleNaAZRrUvYWmasuQHJOSDdpdKyriEIvo9maexWC70gAIF/bKTvzzFUH4HgbJZ3HdFSw9vC6lfKHpq7X8X07AOOblK2HhLQBindC2g/9Rx+gePcj/cnqHIDoUFm1c9gjwNAy/d0kyXIAMLSYrQ8kqScAhhbH3iLJBwIwtBByTJKkBWBoIeSMJHMOwNBCyG+SdEYAQ4tTvyLJMQUwtBAyJEn8BTC0EHIHQhQSApOlzGTBqaty6jzVAhhaCOlhYahuYYitE02EHGNzURchLZItX4ChhZB9HFBpUjmgwhGuHv0feI0gBw1T3j7CgHT5jzYC5XQRsjUdSsrhjADGl7ka0EylBgRb+ySkMy9rww7A8Waududf2MH9Qh9k3CbXLsGVNh/mqrvojuEeQHI+Qmq4Fq1ndIyeruaDxAEuCWk+ncmB0z3gepubtQenMUHyGTWELJl8xk6B15CeqVAyLtPXtUICsyJnVivWs+J0dAAwbzLOkQRTk2YuKsapTQFkXqPjlDILEinnRcZ1fpXdkGo866xqnH9FNyTjz0JIQZXcuPQCAE5rqo6oMEFBl7RknBRfTg8lj5Yl48JdGT0ueIWiYIvIuHFfPg9l85LJcF42b+JTUFjysZnyVlhy2qfA0asovTo9+0JxYnWC8t0KBQXuFYrdkIy3mBj3LbeNQrejZTuqOlbcl8znGTqcfjXoM3pboqgaPhEPxda1qgcVYsRt5TanDkgISWzcV1N1hCS3jdu4dNxUDMIhlBzXysHGGspkcBtsW2pPh3fGLrZ2ya5cXHFp0qxJ6si3E68EQCpy344vQRZxO5jfye+2d/oqgHsV02Z3lvcl9QTnA+EkLZw5h9MZcY4pTvxldXj/W0+esc+25H/5HQGYon+Q5f+MwFz+8QAAAABJRU5ErkJggg==" alt="PNG circle"/></p>
+<div ondragenter="event.preventDefault()" ondragover="return false" ondrop="dropSelection(event)"/>
+<div ondragenter="event.preventDefault()" ondragover="return false" ondrop="dropSelection(event)"/>
+<div ondragenter="event.preventDefault()" ondragover="return false" ondrop="dropSelection(event)"/>
+<p>You should be able to drag circle and drop it onto any of the green boxes.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/drop/005.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/drop/005.xhtml
new file mode 100644
index 00000000000..c74572f0e80
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/drop/005.xhtml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>SVG image drag and drop: allowed effects 'copy','move','link'</title>
+<style type="text/css">
+div
+ {display:inline-block;
+ vertical-align:top;
+ background-color:olive;
+ color:white;
+ padding:20px;
+ width:100px;
+ height:100px;}
+div:nth-child(2)
+ {background-color:green;}
+div:nth-child(3)
+ {background-color:teal;}
+</style>
+<script type="application/ecmascript">
+var effects = ['copy','move','link'], i = 0;
+function dropSelection(event)
+ {event.target.appendChild(document.createTextNode((event.dataTransfer.dropEffect == effects[i] &amp;&amp; event.dataTransfer.effectAllowed == effects[i])?' PASS ':' FAIL '));
+ i = (i + 1)%3;}
+function start(event)
+ {event.dataTransfer.effectAllowed = effects[i]}
+</script>
+</head>
+<body onload="selectText()">
+<p><img ondragstart="start(event)" src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20version%3D%221.1%22%20width%3D%22100px%22%20height%3D%22100px%22%20viewBox%3D%220%200%20100%20100%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22green%22/%3E%3C/svg%3E" alt="SVG circle"/></p>
+<div ondragenter="event.preventDefault()" ondragover="return false" ondrop="dropSelection(event)"/>
+<div ondragenter="event.preventDefault()" ondragover="return false" ondrop="dropSelection(event)"/>
+<div ondragenter="event.preventDefault()" ondragover="return false" ondrop="dropSelection(event)"/>
+<p>You should be able to drag circle and drop it onto any of the green boxes.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/drop/006.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/drop/006.xhtml
new file mode 100644
index 00000000000..03deb62f2b9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/drop/006.xhtml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Canvas drag and drop: allowed effects 'copy','move','link'</title>
+<style type="text/css">
+div
+ {display:inline-block;
+ vertical-align:top;
+ background-color:olive;
+ color:white;
+ padding:20px;
+ width:100px;
+ height:100px;}
+div:nth-child(2)
+ {background-color:green;}
+div:nth-child(3)
+ {background-color:teal;}
+</style>
+<script type="application/ecmascript">
+var effects = ['copy','move','link'], i = 0;
+function dropSelection(event)
+ {event.target.appendChild(document.createTextNode((event.dataTransfer.dropEffect == effects[i] &amp;&amp; event.dataTransfer.effectAllowed == effects[i])?' PASS ':' FAIL '));
+ i = (i + 1)%3;}
+function start(event)
+ {event.dataTransfer.effectAllowed = effects[i]}
+</script>
+</head>
+<body onload="selectText()">
+<p>
+ <canvas width="100" height="100" draggable="true" ondragstart="start(event)" ondragenter="event.preventDefault()" ondragover="return false" ondrop="addImage(event)">Canvas</canvas>
+</p>
+<div ondragenter="event.preventDefault()" ondragover="return false" ondrop="dropSelection(event)"/>
+<div ondragenter="event.preventDefault()" ondragover="return false" ondrop="dropSelection(event)"/>
+<div ondragenter="event.preventDefault()" ondragover="return false" ondrop="dropSelection(event)"/>
+<p>You should be able to drag canvas pattern and drop it onto any of the green boxes.</p>
+<script type="application/ecmascript">
+var canvas = document.querySelector('canvas'),
+c = canvas.getContext('2d');
+for(var x = 0; x != 50; x++)
+ {c.fillStyle = (x%2 == 0)?'navy':'white';
+ c.beginPath();
+ c.moveTo(x,x);
+ c.lineTo(100-x,x);
+ c.lineTo(100-x,100-x);
+ c.lineTo(x,100-x);
+ c.closePath();
+ c.fill();}
+</script>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/drop/007.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/drop/007.xhtml
new file mode 100644
index 00000000000..0072eb12330
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/drop/007.xhtml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop: allowed effects 'copy','copyLink','copyMove'</title>
+<style type="text/css">
+div
+ {display:inline-block;
+ vertical-align:top;
+ background-color:olive;
+ color:white;
+ padding:20px;
+ width:100px;
+ height:100px;}
+div:nth-child(2)
+ {background-color:green;}
+div:nth-child(3)
+ {background-color:teal;}
+</style>
+<script type="application/ecmascript">
+var effects = ['copy','copyLink','copyMove'], i = 0;
+function selectText()
+ {window.getSelection().selectAllChildren(document.querySelector('p'))}
+function dropSelection(event)
+ {event.target.appendChild(document.createTextNode((event.dataTransfer.dropEffect == 'copy' &amp;&amp; event.dataTransfer.effectAllowed == effects[i])?' PASS ':' FAIL '));
+ i = (i + 1)%3;
+ selectText();}
+function start(event)
+ {event.dataTransfer.effectAllowed = effects[i]}
+</script>
+</head>
+<body onload="selectText()">
+<p ondragstart="start(event)">Drag me</p>
+<div ondragenter="event.preventDefault()" ondragover="return false" ondrop="dropSelection(event)"/>
+<div ondragenter="event.preventDefault()" ondragover="return false" ondrop="dropSelection(event)"/>
+<div ondragenter="event.preventDefault()" ondragover="return false" ondrop="dropSelection(event)"/>
+<p>You should be able to drag selection and drop it onto any of the green boxes.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/drop/008.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/drop/008.xhtml
new file mode 100644
index 00000000000..79b743ff901
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/drop/008.xhtml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Link drag and drop: allowed effects 'link','linkMove','uninitialized'</title>
+<style type="text/css">
+div
+ {display:inline-block;
+ vertical-align:top;
+ background-color:olive;
+ color:white;
+ padding:20px;
+ width:100px;
+ height:100px;}
+div:nth-child(2)
+ {background-color:green;}
+div:nth-child(3)
+ {background-color:teal;}
+</style>
+<script type="application/ecmascript">
+var effects = ['link','linkMove','copyMove'], i = 0;
+function dropSelection(event)
+ {event.target.appendChild(document.createTextNode((event.dataTransfer.dropEffect == effects[i].substring(0,4) &amp;&amp; event.dataTransfer.effectAllowed == effects[i])?' PASS ':' FAIL '));
+ i = (i + 1)%3;}
+function start(event)
+ {event.dataTransfer.effectAllowed = effects[i]}
+</script>
+</head>
+<body onload="selectText()">
+<p><a href="data:text/plain,1" ondragstart="start(event)">Drag me</a></p>
+<div ondragenter="event.preventDefault()" ondragover="return false" ondrop="dropSelection(event)"/>
+<div ondragenter="event.preventDefault()" ondragover="return false" ondrop="dropSelection(event)"/>
+<div ondragenter="event.preventDefault()" ondragover="return false" ondrop="dropSelection(event)"/>
+<p>You should be able to drag link and drop it onto any of the green boxes.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/drop/009.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/drop/009.xhtml
new file mode 100644
index 00000000000..fcd38df4ae2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/drop/009.xhtml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Text input selection drag and drop: allowed effects 'move','uninitialized'</title>
+<style type="text/css">
+div
+ {display:inline-block;
+ vertical-align:top;
+ background-color:olive;
+ color:white;
+ padding:20px;
+ width:100px;
+ height:100px;}
+div:nth-child(2)
+ {background-color:green;}
+</style>
+<script type="application/ecmascript">
+var effects = ['move','uninitialized'], i = 0;
+function selectText()
+ {document.querySelector('input').select()}
+function dropSelection(event)
+ {event.target.appendChild(document.createTextNode((event.dataTransfer.dropEffect == 'move' &amp;&amp; event.dataTransfer.effectAllowed == effects[i])?' PASS ':' FAIL '));
+ i = (i + 1)%2;
+ selectText();}
+function start(event)
+ {event.dataTransfer.effectAllowed = effects[i];
+ event.dataTransfer.dropEffect = 'move'}
+</script>
+</head>
+<body onload="selectText()">
+<p><input value="Drag me" ondragstart="start(event)"/></p>
+<div ondragenter="event.preventDefault()" ondragover="return false" ondrop="dropSelection(event)"/>
+<div ondragenter="event.preventDefault()" ondragover="return false" ondrop="dropSelection(event)"/>
+<p>You should be able to drag selection and drop it onto any of the green boxes.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/drop/010.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/drop/010.xhtml
new file mode 100644
index 00000000000..50fc1e2367c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/drop/010.xhtml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop: allowed effects 'all','uninitialized'</title>
+<style type="text/css">
+div
+ {display:inline-block;
+ vertical-align:top;
+ background-color:olive;
+ color:white;
+ padding:20px;
+ width:100px;
+ height:100px;}
+div:nth-child(2)
+ {background-color:green;}
+</style>
+<script type="application/ecmascript">
+var effects = ['all','uninitialized'], i = 0;
+function selectText()
+ {window.getSelection().selectAllChildren(document.querySelector('p'))}
+function dropSelection(event)
+ {event.target.appendChild(document.createTextNode((event.dataTransfer.dropEffect == 'copy' &amp;&amp; event.dataTransfer.effectAllowed == effects[i])?' PASS ':' FAIL '));
+ i = (i + 1)%2;
+ selectText();}
+function start(event)
+ {event.dataTransfer.effectAllowed = effects[i]}
+</script>
+</head>
+<body onload="selectText()">
+<p ondragstart="start(event)">Drag me</p>
+<div ondragenter="event.preventDefault()" ondragover="return false" ondrop="dropSelection(event)"/>
+<div ondragenter="event.preventDefault()" ondragover="return false" ondrop="dropSelection(event)"/>
+<p>You should be able to drag selection and drop it onto any of the green boxes.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/drop/011.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/drop/011.xhtml
new file mode 100644
index 00000000000..aa8c411c79d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/drop/011.xhtml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop: allowed effects 'link','copyLink','linkMove'</title>
+<style type="text/css">
+div
+ {display:inline-block;
+ vertical-align:top;
+ background-color:olive;
+ color:white;
+ padding:20px;
+ width:100px;
+ height:100px;}
+div:nth-child(2)
+ {background-color:green;}
+div:nth-child(3)
+ {background-color:teal;}
+</style>
+<script type="application/ecmascript">
+var effects = ['link','copyLink','linkMove'], i = 0;
+function selectText()
+ {window.getSelection().selectAllChildren(document.querySelector('p'))}
+function dropSelection(event)
+ {event.target.appendChild(document.createTextNode((event.dataTransfer.dropEffect == effects[i].substring(0,4) &amp;&amp; event.dataTransfer.effectAllowed == effects[i])?' PASS ':' FAIL '));
+ i = (i + 1)%3;
+ selectText();}
+function start(event)
+ {event.dataTransfer.effectAllowed = effects[i];}
+</script>
+</head>
+<body onload="selectText()">
+<p ondragstart="start(event)">Drag me</p>
+<div ondragenter="event.preventDefault()" ondragover="return false" ondrop="dropSelection(event)"/>
+<div ondragenter="event.preventDefault()" ondragover="return false" ondrop="dropSelection(event)"/>
+<div ondragenter="event.preventDefault()" ondragover="return false" ondrop="dropSelection(event)"/>
+<p>You should be able to drag selection and drop it onto any of the green boxes.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/drop/012.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/drop/012.xhtml
new file mode 100644
index 00000000000..e5b4b7b5545
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/drop/012.xhtml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop: allowed effects 'move','copyMove','linkMove'</title>
+<style type="text/css">
+div
+ {display:inline-block;
+ vertical-align:top;
+ background-color:olive;
+ color:white;
+ padding:20px;
+ width:100px;
+ height:100px;}
+div:nth-child(2)
+ {background-color:green;}
+div:nth-child(3)
+ {background-color:teal;}
+</style>
+<script type="application/ecmascript">
+var effects = ['move','copyMove','linkMove'], i = 0;
+function selectText()
+ {window.getSelection().selectAllChildren(document.querySelector('p'))}
+function dropSelection(event)
+ {event.target.appendChild(document.createTextNode((event.dataTransfer.dropEffect == effects[i].substring(0,4) &amp;&amp; event.dataTransfer.effectAllowed == effects[i])?' PASS ':' FAIL '));
+ i = (i + 1)%3;
+ selectText();}
+function start(event)
+ {event.dataTransfer.effectAllowed = effects[i];}
+</script>
+</head>
+<body onload="selectText()">
+<p ondragstart="start(event)">Drag me</p>
+<div ondragenter="event.preventDefault()" ondragover="return false" ondrop="dropSelection(event)"/>
+<div ondragenter="event.preventDefault()" ondragover="return false" ondrop="dropSelection(event)"/>
+<div ondragenter="event.preventDefault()" ondragover="return false" ondrop="dropSelection(event)"/>
+<p>You should be able to drag selection and drop it onto any of the green boxes.</p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/drop/013.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/drop/013.xhtml
new file mode 100644
index 00000000000..629b66ddd2b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/drop/013.xhtml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop: allowed effects 'copy','all','uninitialized'</title>
+<style type="text/css">
+div
+ {display:inline-block;
+ vertical-align:top;
+ background-color:olive;
+ color:white;
+ padding:20px;
+ width:100px;
+ height:100px;}
+div:nth-child(2)
+ {background-color:green;}
+div:nth-child(3)
+ {background-color:teal;}
+</style>
+<script type="application/ecmascript">
+var effects = ['copy','all','uninitialized'], i = 0;
+function selectText()
+ {window.getSelection().selectAllChildren(document.querySelector('p'))}
+function dropSelection(event)
+ {event.target.appendChild(document.createTextNode((event.dataTransfer.dropEffect == 'copy' &amp;&amp; event.dataTransfer.effectAllowed == effects[i])?' PASS ':' FAIL '));
+ i = (i + 1)%3;
+ selectText();}
+function start(event)
+ {event.dataTransfer.effectAllowed = effects[i]}
+</script>
+</head>
+<body onload="selectText()">
+<p ondragstart="start(event)">Drag me</p>
+<div ondragenter="event.preventDefault()" ondragover="return false" ondrop="dropSelection(event)"/>
+<div ondragenter="event.preventDefault()" ondragover="return false" ondrop="dropSelection(event)"/>
+<div ondragenter="event.preventDefault()" ondragover="return false" ondrop="dropSelection(event)"/>
+<p>You should be able to drag selection and drop it onto any of the green boxes.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/drop/014.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/drop/014.xhtml
new file mode 100644
index 00000000000..93747099e10
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/drop/014.xhtml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop: allowed effects 'copy','copyMove','invalid'</title>
+<style type="text/css">
+div
+ {display:inline-block;
+ vertical-align:top;
+ background-color:olive;
+ color:white;
+ padding:20px;
+ width:100px;
+ height:100px;}
+div:nth-child(2)
+ {background-color:green;}
+div:nth-child(3)
+ {background-color:teal;}
+</style>
+<script type="application/ecmascript">
+var effects = ['copy','all','uninitialized'], i = 0;
+function selectText()
+ {window.getSelection().selectAllChildren(document.querySelector('p'))}
+function dropSelection(event)
+ {event.target.appendChild(document.createTextNode((event.dataTransfer.dropEffect == 'copy' &amp;&amp; event.dataTransfer.effectAllowed == effects[i])?' PASS ':' FAIL '));
+ i = (i + 1)%3;
+ selectText();}
+function start(event)
+ {event.dataTransfer.effectAllowed = effects[i]}
+</script>
+</head>
+<body onload="selectText()">
+<p ondragstart="start(event)">Drag me</p>
+<div ondragenter="event.preventDefault()" ondragover="return false" ondrop="dropSelection(event)"/>
+<div ondragenter="event.preventDefault()" ondragover="return false" ondrop="dropSelection(event)"/>
+<div ondragenter="event.preventDefault()" ondragover="return false" ondrop="dropSelection(event)"/>
+<p>You should be able to drag selection and drop it onto any of the green boxes.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/drop/015.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/drop/015.xhtml
new file mode 100644
index 00000000000..23b4b43ee10
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/drop/015.xhtml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop: dropzone 'copy','move' and 'link'</title>
+<style type="text/css">
+div
+ {display:inline-block;
+ vertical-align:top;
+ background-color:olive;
+ color:white;
+ padding:20px;
+ width:100px;
+ height:100px;}
+div:nth-child(2)
+ {background-color:green;}
+div:nth-child(3)
+ {background-color:teal;}
+</style>
+<script type="application/ecmascript">
+var effects = ['copy','move','link'];
+function selectText()
+ {window.getSelection().selectAllChildren(document.querySelector('p'))}
+function dropSelection(event,element)
+ {document.querySelectorAll('div')[element].appendChild(document.createTextNode((event.dataTransfer.dropEffect == effects[element])?' PASS ':' FAIL '));
+ selectText();}
+</script>
+</head>
+<body onload="selectText()">
+<div ondrop="dropSelection(event,0)" dropzone="copy string:text/plain"/>
+<div ondrop="dropSelection(event,1)" dropzone="move string:text/plain"/>
+<div ondrop="dropSelection(event,2)" dropzone="link string:text/plain"/>
+<p>Drag me</p>
+<p>You should be able to drag selection and drop it onto any of the green boxes.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/drop/016.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/drop/016.xhtml
new file mode 100644
index 00000000000..23fc81907bc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/drop/016.xhtml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Text input selection drag and drop: dropzone 'copy','move' and 'link'</title>
+<style type="text/css">
+div
+ {display:inline-block;
+ vertical-align:top;
+ background-color:olive;
+ color:white;
+ padding:20px;
+ width:100px;
+ height:100px;}
+div:nth-child(2)
+ {background-color:green;}
+div:nth-child(3)
+ {background-color:teal;}
+</style>
+<script type="application/ecmascript">
+var effects = ['copy','move','link'];
+function selectText()
+ {document.querySelector('input').select()}
+function dropSelection(event,element)
+ {document.querySelectorAll('div')[element].appendChild(document.createTextNode((event.dataTransfer.dropEffect == effects[element])?' PASS ':' FAIL '));
+ selectText();}
+</script>
+</head>
+<body onload="selectText()">
+<div ondrop="dropSelection(event,0)" dropzone="copy string:text/plain"/>
+<div ondrop="dropSelection(event,1)" dropzone="move string:text/plain"/>
+<div ondrop="dropSelection(event,2)" dropzone="link string:text/plain"/>
+<p><input value="Drag me"/></p>
+<p>You should be able to drag selection and drop it onto any of the green boxes.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/drop/017.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/drop/017.xhtml
new file mode 100644
index 00000000000..a9dd0d74d75
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/drop/017.xhtml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Link drag and drop: dropzone 'copy','move' and 'link'</title>
+<style type="text/css">
+div
+ {display:inline-block;
+ vertical-align:top;
+ background-color:olive;
+ color:white;
+ padding:20px;
+ width:100px;
+ height:100px;}
+div:nth-child(2)
+ {background-color:green;}
+div:nth-child(3)
+ {background-color:teal;}
+</style>
+<script type="application/ecmascript">
+var effects = ['copy','move','link'];
+function dropSelection(event,element)
+ {document.querySelectorAll('div')[element].appendChild(document.createTextNode((event.dataTransfer.dropEffect == effects[element])?' PASS ':' FAIL '));}
+</script>
+</head>
+<body>
+<div ondrop="dropSelection(event,0)" dropzone="copy string:text/uri-list"/>
+<div ondrop="dropSelection(event,1)" dropzone="move string:text/uri-list"/>
+<div ondrop="dropSelection(event,2)" dropzone="link string:text/uri-list"/>
+<p><a href="data:text/plain,1">Drag me</a></p>
+<p>You should be able to drag link and drop it onto any of the green boxes.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/drop/018.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/drop/018.xhtml
new file mode 100644
index 00000000000..055448f1d49
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/drop/018.xhtml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop: setting dropzone attribute ondragstart</title>
+<style type="text/css">
+div
+ {display:inline-block;
+ vertical-align:top;
+ background-color:olive;
+ color:white;
+ padding:20px;
+ width:100px;
+ height:100px;}
+div:nth-child(2)
+ {background-color:green;}
+div:nth-child(3)
+ {background-color:teal;}
+</style>
+<script type="application/ecmascript">
+var effects = ['copy','move','link'];
+function selectText()
+ {window.getSelection().selectAllChildren(document.querySelector('p'))}
+function dropSelection(event,element)
+ {document.querySelectorAll('div')[element].appendChild(document.createTextNode((event.dataTransfer.dropEffect == effects[element])?' PASS ':' FAIL '));
+ selectText();}
+function start(event)
+ {for(var i = 0; i != 3; i++)
+ {document.querySelectorAll('div')[i].setAttribute('dropzone',effects[i] + ' string:text/plain')}
+ }
+</script>
+</head>
+<body onload="selectText()">
+<div ondrop="dropSelection(event,0)"/>
+<div ondrop="dropSelection(event,1)"/>
+<div ondrop="dropSelection(event,2)"/>
+<p ondragstart="start(event)">Drag me</p>
+<p>You should be able to drag selection and drop it onto any of the green boxes.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/drop/019.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/drop/019.xhtml
new file mode 100644
index 00000000000..5dd86f21106
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/drop/019.xhtml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Text input selection drag and drop: setting dropzone attribute ondragstart</title>
+<style type="text/css">
+div
+ {display:inline-block;
+ vertical-align:top;
+ background-color:olive;
+ color:white;
+ padding:20px;
+ width:100px;
+ height:100px;}
+div:nth-child(2)
+ {background-color:green;}
+div:nth-child(3)
+ {background-color:teal;}
+</style>
+<script type="application/ecmascript">
+var effects = ['copy','move','link'];
+function selectText()
+ {document.querySelector('input').select()}
+function dropSelection(event,element)
+ {document.querySelectorAll('div')[element].appendChild(document.createTextNode((event.dataTransfer.dropEffect == effects[element])?' PASS ':' FAIL '));
+ selectText();}
+function start(event)
+ {for(var i = 0; i != 3; i++)
+ {document.querySelectorAll('div')[i].setAttribute('dropzone',effects[i] + ' string:text/plain')}
+ }
+</script>
+</head>
+<body onload="selectText()">
+<div ondrop="dropSelection(event,0)"/>
+<div ondrop="dropSelection(event,1)"/>
+<div ondrop="dropSelection(event,2)"/>
+<p ondragstart="start(event)"><input value="Drag me" ondragstart="start(event)"/></p>
+<p>You should be able to drag selection and drop it onto any of the green boxes.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/drop/020.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/drop/020.xhtml
new file mode 100644
index 00000000000..8fa4c0622ef
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/drop/020.xhtml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Link drag and drop: setting dropzone attribute ondragstart</title>
+<style type="text/css">
+div
+ {display:inline-block;
+ vertical-align:top;
+ background-color:olive;
+ color:white;
+ padding:20px;
+ width:100px;
+ height:100px;}
+div:nth-child(2)
+ {background-color:green;}
+div:nth-child(3)
+ {background-color:teal;}
+</style>
+<script type="application/ecmascript">
+var effects = ['copy','move','link'];
+function dropSelection(event,element)
+ {document.querySelectorAll('div')[element].appendChild(document.createTextNode((event.dataTransfer.dropEffect == effects[element])?' PASS ':' FAIL '));}
+function start(event)
+ {for(var i = 0; i != 3; i++)
+ {document.querySelectorAll('div')[i].setAttribute('dropzone',effects[i] + ' string:text/uri-list')}
+ }
+</script>
+</head>
+<body>
+<div ondrop="dropSelection(event,0)"/>
+<div ondrop="dropSelection(event,1)"/>
+<div ondrop="dropSelection(event,2)"/>
+<p ondragstart="start(event)"><a href="data:text/plain,1" ondragstart="start(event)">Drag me</a></p>
+<p>You should be able to drag link and drop it onto any of the green boxes.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/drop/021.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/drop/021.xhtml
new file mode 100644
index 00000000000..5e9f249281d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/drop/021.xhtml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop: removing dropzone attribute ondragstart</title>
+<style type="text/css">
+div
+ {display:inline-block;
+ vertical-align:top;
+ background-color:maroon;
+ color:white;
+ padding:20px;
+ width:100px;
+ height:100px;}
+div:nth-child(2)
+ {background-color:purple;}
+div:nth-child(3)
+ {background-color:fuchsia;}
+</style>
+<script type="application/ecmascript">
+function selectText()
+ {window.getSelection().selectAllChildren(document.querySelector('p'))}
+function dropSelection(event,element)
+ {document.querySelectorAll('div')[element].appendChild(document.createTextNode(' FAIL '));
+ selectText();}
+function start(event)
+ {for(var i = 0; i != 3; i++)
+ {document.querySelectorAll('div')[i].removeAttribute('dropzone')}
+ }
+</script>
+</head>
+<body onload="selectText()">
+<div ondrop="dropSelection(event,0)" dropzone="copy string:text/plain"/>
+<div ondrop="dropSelection(event,1)" dropzone="move string:text/plain"/>
+<div ondrop="dropSelection(event,2)" dropzone="link string:text/plain"/>
+<p ondragstart="start(event)">Drag me</p>
+<p>You should not be able to drop selection onto any of the red boxes above.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/drop/022.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/drop/022.xhtml
new file mode 100644
index 00000000000..ed1b0265969
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/drop/022.xhtml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop: changing dropzone attribute ondragstart</title>
+<style type="text/css">
+div
+ {display:inline-block;
+ vertical-align:top;
+ background-color:olive;
+ color:white;
+ padding:20px;
+ width:100px;
+ height:100px;}
+div:nth-child(2)
+ {background-color:green;}
+div:nth-child(3)
+ {background-color:teal;}
+</style>
+<script type="application/ecmascript">
+var effects = ['copy','move','link'];
+function selectText()
+ {window.getSelection().selectAllChildren(document.querySelector('p'))}
+function dropSelection(event,element)
+ {document.querySelectorAll('div')[element].appendChild(document.createTextNode((event.dataTransfer.dropEffect == effects[element])?' PASS ':' FAIL '));
+ selectText();}
+function start(event)
+ {for(var i = 0; i != 3; i++)
+ {document.querySelectorAll('div')[i].setAttribute('dropzone',effects[i] + ' string:text/plain')}
+ }
+</script>
+</head>
+<body onload="selectText()">
+<div ondrop="dropSelection(event,0)" dropzone="link string:text/plain"/>
+<div ondrop="dropSelection(event,1)" dropzone="copy string:text/plain"/>
+<div ondrop="dropSelection(event,2)" dropzone="move string:text/plain"/>
+<p ondragstart="start(event)">Drag me</p>
+<p>You should be able to drag selection and drop it onto any of the green boxes.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/drop/023.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/drop/023.xhtml
new file mode 100644
index 00000000000..be2ffae9a1b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/drop/023.xhtml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>drofEffect after drop event is cancelled</title>
+<style type="text/css">
+div
+ {display:inline-block;
+ vertical-align:top;
+ background-color:olive;
+ color:white;
+ padding:20px;
+ width:100px;
+ height:100px;}
+div:nth-child(2)
+ {background-color:green;}
+div:nth-child(3)
+ {background-color:teal;}
+</style>
+<script type="application/ecmascript">
+var effects = ['copy','move','link'], result = false, e = 0;
+function selectText()
+ {window.getSelection().selectAllChildren(document.querySelector('p'))}
+function dropSelection(event,element)
+ {event.preventDefault();
+ e = element;
+ if(event.dataTransfer.dropEffect == effects[element])
+ {result = true}
+ selectText();}
+function endDrag(event)
+ {document.querySelectorAll('div')[e].appendChild(document.createTextNode((result &amp;&amp; event.dataTransfer.dropEffect == effects[e])?' PASS ':' FAIL '));}
+</script>
+</head>
+<body onload="selectText()">
+<div ondrop="dropSelection(event,0)" dropzone="copy string:text/plain"/>
+<div ondrop="dropSelection(event,1)" dropzone="move string:text/plain"/>
+<div ondrop="dropSelection(event,2)" dropzone="link string:text/plain"/>
+<p ondragend="endDrag(event)">Drag me</p>
+<p>You should be able to drag selection and drop it onto any of the green boxes.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/drop/024.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/drop/024.xhtml
new file mode 100644
index 00000000000..4f880974e28
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/drop/024.xhtml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop: invalid value of effectAllowed</title>
+<style type="text/css">
+div
+ {display:inline-block;
+ vertical-align:top;
+ background-color:olive;
+ color:white;
+ padding:20px;
+ width:100px;
+ height:100px;}
+div:nth-child(2)
+ {background-color:green;}
+div:nth-child(3)
+ {background-color:teal;}
+</style>
+<script type="application/ecmascript">
+var effects = ['copy','move','link'], i = 0;
+function selectText()
+ {window.getSelection().selectAllChildren(document.querySelector('p'))}
+function dropSelection(event)
+ {event.target.appendChild(document.createTextNode((event.dataTransfer.dropEffect == effects[i] &amp;&amp; event.dataTransfer.effectAllowed == effects[i])?' PASS ':' FAIL '));
+ i = (i + 1)%3;
+ selectText();}
+function start(event)
+ {event.dataTransfer.effectAllowed = effects[i];
+ event.dataTransfer.effectAllowed = 'fail';}
+</script>
+</head>
+<body onload="selectText()">
+<p ondragstart="start(event)">Drag me</p>
+<div ondragenter="event.preventDefault()" ondragover="return false" ondrop="dropSelection(event)"/>
+<div ondragenter="event.preventDefault()" ondragover="return false" ondrop="dropSelection(event)"/>
+<div ondragenter="event.preventDefault()" ondragover="return false" ondrop="dropSelection(event)"/>
+<p>You should be able to drag selection and drop it onto any of the green boxes.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/drop/025.html b/tests/wpt/web-platform-tests/html/editing/dnd/drop/025.html
new file mode 100644
index 00000000000..288836fe4d0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/drop/025.html
@@ -0,0 +1,162 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - writing to dropEffect</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ position: absolute;
+ top: 8px;
+ left: 8px;
+ }
+ body > div * {
+ display: none;
+ }
+ body > div + div {
+ background-color: navy;
+ left: 250px;
+ }
+ body > div + div + div {
+ background-color: fuchsia;
+ left: 500px;
+ }
+ p:first-of-type {
+ margin-top: 220px;
+ }
+</style>
+
+<script>
+
+window.onload = function() {
+ var orange = document.getElementsByTagName('div')[0], fails = [], doneonce = false, seenevent = {};
+ orange.ondragstart = function(e) {
+ e.dataTransfer.setData('Text', 'dummy text');
+ e.dataTransfer.effectAllowed = 'all';
+ if( seenevent[e.type] ) { return; }
+ seenevent[e.type] = true;
+ if( e.dataTransfer.dropEffect != 'none' ) {
+ fails[fails.length] = e.type + ' dropEffect ' + e.dataTransfer.dropEffect + ' instead of none';
+ }
+ try{ e.dataTransfer.dropEffect = 'move' } catch(err) {
+ fails[fails.length] = e.type + ' dropEffect threw on setting';
+ }
+ if( e.dataTransfer.dropEffect != 'move' ) {
+ fails[fails.length] = e.type + ' dropEffect ' + e.dataTransfer.dropEffect + ' instead of move (seems to be readonly)';
+ }
+ };
+ orange.ondrag = orange.nextSibling.ondragleave = function(e) {
+ if( seenevent[e.type] ) { return; }
+ seenevent[e.type] = true;
+ if( e.dataTransfer.dropEffect != 'none' ) {
+ fails[fails.length] = e.type + ' dropEffect ' + e.dataTransfer.dropEffect + ' instead of none';
+ }
+ try{ e.dataTransfer.dropEffect = 'move' } catch(err) {
+ fails[fails.length] = e.type + ' dropEffect threw on setting';
+ }
+ if( e.dataTransfer.dropEffect != 'move' ) {
+ fails[fails.length] = e.type + ' dropEffect ' + e.dataTransfer.dropEffect + ' instead of move (seems to be readonly)';
+ }
+ };
+ orange.nextSibling.ondragenter = function(e) {
+ e.preventDefault();
+ if( seenevent[e.type] ) { return; }
+ seenevent[e.type] = true;
+ if( e.dataTransfer.dropEffect != 'copy' ) {
+ fails[fails.length] = e.type + ' dropEffect ' + e.dataTransfer.dropEffect + ' instead of copy';
+ }
+ try{ e.dataTransfer.dropEffect = 'move' } catch(err) {
+ fails[fails.length] = e.type + ' dropEffect threw on setting';
+ }
+ if( e.dataTransfer.dropEffect != 'move' ) {
+ fails[fails.length] = e.type + ' dropEffect ' + e.dataTransfer.dropEffect + ' instead of move (seems to be readonly)';
+ }
+ };
+ orange.nextSibling.ondragover = function(e) {
+ e.preventDefault();
+ if( seenevent[e.type] ) {
+ e.dataTransfer.dropEffect = 'link';
+ return;
+ }
+ if( !doneonce ) {
+ if( e.dataTransfer.dropEffect != 'copy' ) {
+ fails[fails.length] = e.type + ' dropEffect ' + e.dataTransfer.dropEffect + ' instead of copy';
+ }
+ try{ e.dataTransfer.dropEffect = 'move' } catch(err) {
+ fails[fails.length] = e.type + ' dropEffect threw on setting';
+ }
+ if( e.dataTransfer.dropEffect != 'move' ) {
+ fails[fails.length] = e.type + ' dropEffect ' + e.dataTransfer.dropEffect + ' instead of move (seems to be readonly)';
+ }
+ doneonce = true;
+ } else {
+ seenevent[e.type] = true;
+ if( e.dataTransfer.dropEffect != 'copy' ) {
+ fails[fails.length] = e.type + ' dropEffect ' + e.dataTransfer.dropEffect + ' instead of copy on second attempt';
+ }
+ try{ e.dataTransfer.dropEffect = 'link' } catch(err2) {
+ fails[fails.length] = e.type + ' dropEffect threw on setting';
+ }
+ if( e.dataTransfer.dropEffect != 'link' ) {
+ fails[fails.length] = e.type + ' dropEffect ' + e.dataTransfer.dropEffect + ' instead of link on second attempt (seems to be readonly)';
+ }
+ doneonce = true;
+ }
+ };
+ orange.nextSibling.ondrop = function(e) {
+ e.preventDefault();
+ if( seenevent[e.type] ) { return; }
+ seenevent[e.type] = true;
+ if( e.dataTransfer.dropEffect != 'link' ) {
+ fails[fails.length] = e.type + ' dropEffect ' + e.dataTransfer.dropEffect + ' instead of link';
+ }
+ try{ e.dataTransfer.dropEffect = 'move' } catch(err) {
+ fails[fails.length] = e.type + ' dropEffect threw on setting';
+ }
+ if( e.dataTransfer.dropEffect != 'move' ) {
+ fails[fails.length] = e.type + ' dropEffect ' + e.dataTransfer.dropEffect + ' instead of move (seems to be readonly)';
+ }
+ };
+ orange.ondragend = function(e) {
+ if( seenevent[e.type] ) { return; }
+ seenevent[e.type] = true;
+ if( e.dataTransfer.dropEffect != 'move' ) {
+ //under-specified in the spec, but part of the spec related to cancelling a drag says:
+ //"set the current drag operation to the value of the dropEffect attribute of the DragEvent
+ //object's dataTransfer object as it stood after the event dispatch finished."
+ //this does not cover successful drags, but it makes sense to be consistent
+ fails[fails.length] = e.type + ' dropEffect ' + e.dataTransfer.dropEffect + ' instead of move';
+ }
+ try{ e.dataTransfer.dropEffect = 'copy' } catch(err) {
+ fails[fails.length] = e.type + ' dropEffect threw on setting';
+ }
+ if( e.dataTransfer.dropEffect != 'copy' ) {
+ fails[fails.length] = e.type + ' dropEffect ' + e.dataTransfer.dropEffect + ' instead of copy (seems to be readonly)';
+ }
+ if( !seenevent.dragstart ) {
+ fails[fails.length] = 'dragstart did not fire';
+ }
+ if( !seenevent.drag ) {
+ fails[fails.length] = 'drag did not fire';
+ }
+ if( !seenevent.dragenter ) {
+ fails[fails.length] = 'dragenter did not fire';
+ }
+ if( !seenevent.dragover ) {
+ fails[fails.length] = 'dragover did not fire enough times';
+ }
+ if( !seenevent.dragleave ) {
+ fails[fails.length] = 'dragleave did not fire';
+ }
+ if( !seenevent.drop ) {
+ fails[fails.length] = 'drop did not fire';
+ }
+ document.getElementsByTagName('p')[0].innerHTML = fails.length ? ( 'FAIL: ' + fails.join('<br>') ) : 'PASS';
+ };
+};
+
+</script>
+
+<div draggable='true'></div><div></div><div></div>
+
+<p>Use your pointing device to drag the orange box to the pink box, then back to the blue box, and release it.</p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/drop/026.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/drop/026.xhtml
new file mode 100644
index 00000000000..d3ae0d82756
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/drop/026.xhtml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop: multiple values in dropzone</title>
+<style type="text/css">
+div
+ {display:inline-block;
+ vertical-align:top;
+ background-color:olive;
+ color:white;
+ padding:20px;
+ width:100px;
+ height:100px;}
+div:nth-child(2)
+ {background-color:green;}
+div:nth-child(3)
+ {background-color:teal;}
+</style>
+<script type="application/ecmascript">
+var effects = ['copy','move','link'];
+function selectText()
+ {window.getSelection().selectAllChildren(document.querySelector('p'))}
+function dropSelection(event,element)
+ {document.querySelectorAll('div')[element].appendChild(document.createTextNode((event.dataTransfer.dropEffect == effects[element])?' PASS ':' FAIL '));
+ selectText();}
+</script>
+</head>
+<body onload="selectText()">
+<div ondrop="dropSelection(event,0)" dropzone="copy string:text/plain string:text/x-example"/>
+<div ondrop="dropSelection(event,1)" dropzone="move file:text/plain string:text/plain"/>
+<div ondrop="dropSelection(event,2)" dropzone="link file:image/png string:text/plain"/>
+<p>Drag me</p>
+<p>You should be able to drag selection and drop it onto any of the green boxes.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/drop/027.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/drop/027.xhtml
new file mode 100644
index 00000000000..482a655c182
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/drop/027.xhtml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop: non matching values in dropzone</title>
+<style type="text/css">
+div
+ {display:inline-block;
+ vertical-align:top;
+ background-color:maroon;
+ color:white;
+ padding:20px;
+ width:100px;
+ height:100px;}
+div:nth-child(2)
+ {background-color:purple;}
+div:nth-child(3)
+ {background-color:fuchsia;}
+</style>
+<script type="application/ecmascript">
+function selectText()
+ {window.getSelection().selectAllChildren(document.querySelector('p'))}
+function dropSelection(event,element)
+ {document.querySelectorAll('div')[element].appendChild(document.createTextNode(' FAIL '));
+ selectText();}
+</script>
+</head>
+<body onload="selectText()">
+<div ondrop="dropSelection(event,0)" dropzone="copy file:text/plain"/>
+<div ondrop="dropSelection(event,1)" dropzone="move file:text/plain string:text/x-example"/>
+<div ondrop="dropSelection(event,2)" dropzone="link string:text/x-example"/>
+<p ondragstart="start(event)">Drag me</p>
+<p>You should not be able to drop selection onto any of the red boxes above.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/drop/028.html b/tests/wpt/web-platform-tests/html/editing/dnd/drop/028.html
new file mode 100644
index 00000000000..22b823f70a7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/drop/028.html
@@ -0,0 +1,42 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Dropping element with uninitialized effectAllowed</title>
+ <style type="text/css">
+div, p {
+ margin: 0.2em;
+ height: 70px;
+ width: 400px;
+ background: orange;
+ color: black;
+}
+p {
+ background: navy;
+ color: white;
+}
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ var dragmicro = document.getElementsByTagName('div')[0];
+ dragmicro.ondragstart = function (e) {
+ e.dataTransfer.setData('text/plain','dummy text');
+ };
+ var droptarget = document.getElementsByTagName('p')[0];
+ droptarget.ondragenter = droptarget.ondragover = function (e) {
+ e.preventDefault();
+ };
+ droptarget.ondrop = function (e) {
+ e.preventDefault();
+ this.innerHTML = 'PASS';
+ };
+};
+ </script>
+ </head>
+ <body>
+
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <div draggable="true">Drag this rectangle.</div>
+ <p>Drop onto this rectangle. Fail if this text does not change.</p>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/dropzone/001.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/dropzone/001.xhtml
new file mode 100644
index 00000000000..4fc405af3cc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/dropzone/001.xhtml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Dropzone attribute: copy</title>
+<style type="text/css">
+div
+ {background-color:navy;
+ width:40px;
+ height:40px;
+ padding:40px;
+ color:white;}
+</style>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('p'))">
+<p>Drag me</p>
+<div dropzone="copy string:text/plain" ondrop="document.querySelector('div').appendChild(document.createTextNode((event.dataTransfer.getData('text/plain') == 'Drag me')?'PASS':'FAIL'))"/>
+<p>You should be able to drag selection to navy box below. You should see word PASS once you drop it.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/dropzone/002.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/dropzone/002.xhtml
new file mode 100644
index 00000000000..87a64b3ee76
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/dropzone/002.xhtml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Dropzone attribute: move</title>
+<style type="text/css">
+div
+ {background-color:navy;
+ width:40px;
+ height:40px;
+ padding:40px;
+ color:white;}
+</style>
+</head>
+<body onload="document.querySelector('input').select()">
+<p><input value="Drag me"/></p>
+<div dropzone="move string:text/plain" ondrop="document.querySelector('div').appendChild(document.createTextNode((event.dataTransfer.getData('text/plain') == 'Drag me')?'PASS':'FAIL'))"/>
+<p>You should be able to drag selection to navy box below. You should see word PASS once you drop it.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/dropzone/003.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/dropzone/003.xhtml
new file mode 100644
index 00000000000..7683b1c1757
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/dropzone/003.xhtml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Dropzone attribute: link</title>
+<style type="text/css">
+div
+ {background-color:navy;
+ width:40px;
+ height:40px;
+ padding:40px;
+ color:white;}
+</style>
+</head>
+<body>
+<p><a href="data:text/plain,1">Drag me</a></p>
+<div dropzone="link string:text/plain" ondrop="document.querySelector('div').appendChild(document.createTextNode((event.dataTransfer.getData('text/uri-list').replace(/\r\n$/,'') == 'data:text/plain,1')?'PASS':'FAIL'))"/>
+<p>You should be able to drag link to navy box below. You should see word PASS once you drop it.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/dropzone/004.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/dropzone/004.xhtml
new file mode 100644
index 00000000000..683956899de
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/dropzone/004.xhtml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Dropzone and link drag and drop: allowed effects 'link','copyLink','linkMove' and 'all'</title>
+<style type="text/css">
+div
+ {background-color:gray;
+ width:200px;
+ height:200px;}
+</style>
+<script type="application/ecmascript">
+var effects = ['link','copyLink','linkMove','all'];
+function start(event)
+ {var e = parseInt(event.target.href.substring(16));
+ event.dataTransfer.effectAllowed = effects[e];}
+function finish(event)
+ {var e = parseInt(event.dataTransfer.getData('text/uri-list').substring(16,17));
+ document.querySelectorAll('a')[e].firstChild.nodeValue = (event.dataTransfer.dropEffect == 'link' &amp;&amp; event.dataTransfer.effectAllowed == effects[e])?'PASS':'FAIL';}
+</script>
+</head>
+<body>
+<p>Drag links one by one and drop them into gray box below, link text should be updated as you drop them.</p>
+<p ondragstart="start(event)">
+ <a href="data:text/plain,0">Link</a>
+ <a href="data:text/plain,1">Link</a>
+ <a href="data:text/plain,2">Link</a>
+ <a href="data:text/plain,3">Link</a>
+</p>
+<div dropzone="link string:text/uri-list" ondrop="finish(event)"/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/dropzone/005.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/dropzone/005.xhtml
new file mode 100644
index 00000000000..5cdba423fec
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/dropzone/005.xhtml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Dropzone and link drag and drop: allowed effects 'copy','copyMove','copyLink' and 'all'</title>
+<style type="text/css">
+div
+ {background-color:gray;
+ width:200px;
+ height:200px;}
+</style>
+<script type="application/ecmascript">
+var effects = ['copy','copyMove','copyLink','all'];
+function start(event)
+ {var e = parseInt(event.target.href.substring(16));
+ event.dataTransfer.effectAllowed = effects[e];}
+function finish(event)
+ {var e = parseInt(event.dataTransfer.getData('text/uri-list').substring(16,17));
+ document.querySelectorAll('a')[e].firstChild.nodeValue = (event.dataTransfer.dropEffect == 'copy' &amp;&amp; event.dataTransfer.effectAllowed == effects[e])?'PASS':'FAIL';}
+</script>
+</head>
+<body>
+<p>Drag links one by one and drop them into gray box below, link text should be updated as you drop them.</p>
+<p ondragstart="start(event)">
+ <a href="data:text/plain,0">Link</a>
+ <a href="data:text/plain,1">Link</a>
+ <a href="data:text/plain,2">Link</a>
+ <a href="data:text/plain,3">Link</a>
+</p>
+<div dropzone="copy string:text/uri-list" ondrop="finish(event)"/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/dropzone/006.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/dropzone/006.xhtml
new file mode 100644
index 00000000000..eb5da24fc25
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/dropzone/006.xhtml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Dropzone and link drag and drop: allowed effects 'move','copyMove','linkMove' and 'all'</title>
+<style type="text/css">
+div
+ {background-color:gray;
+ width:200px;
+ height:200px;}
+</style>
+<script type="application/ecmascript">
+var effects = ['move','copyMove','linkMove','all'];
+function start(event)
+ {var e = parseInt(event.target.href.substring(16));
+ event.dataTransfer.effectAllowed = effects[e];}
+function finish(event)
+ {var e = parseInt(event.dataTransfer.getData('text/uri-list').substring(16,17));
+ document.querySelectorAll('a')[e].firstChild.nodeValue = (event.dataTransfer.dropEffect == 'move' &amp;&amp; event.dataTransfer.effectAllowed == effects[e])?'PASS':'FAIL';}
+</script>
+</head>
+<body>
+<p>Drag links one by one and drop them into gray box below, link text should be updated as you drop them.</p>
+<p ondragstart="start(event)">
+ <a href="data:text/plain,0">Link</a>
+ <a href="data:text/plain,1">Link</a>
+ <a href="data:text/plain,2">Link</a>
+ <a href="data:text/plain,3">Link</a>
+</p>
+<div dropzone="move string:text/uri-list" ondrop="finish(event)"/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/dropzone/007.html b/tests/wpt/web-platform-tests/html/editing/dnd/dropzone/007.html
new file mode 100644
index 00000000000..3140e768f72
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/dropzone/007.html
@@ -0,0 +1,54 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Dropzone should not affect the dropEffect seen by dragenter and dragover</title>
+ <style type="text/css">
+div:first-child {
+ height: 100px;
+ width: 100px;
+ background: orange;
+ display: inline-block;
+}
+div:first-child + div {
+ height: 100px;
+ width: 100px;
+ background: blue;
+ display: inline-block;
+}
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ var drag = document.getElementsByTagName('div')[0];
+ drag.ondragstart = function (e) {
+ e.dataTransfer.setData('text','hello');
+ e.dataTransfer.effectAllowed = 'all';
+ };
+ var drop = document.getElementsByTagName('div')[1], dragenter, dragover;
+ drop.ondragenter = function (e) {
+ dragenter = e.dataTransfer.dropEffect;
+ };
+ drop.ondragover = function (e) {
+ dragover = e.dataTransfer.dropEffect;
+ };
+ drop.ondrop = function (e) {
+ var sequence = ([dragenter,dragover,e.dataTransfer.dropEffect]).join('=&gt;')
+ var desiredsequence = (['copy','copy','link']).join('=&gt;')
+ if( sequence == desiredsequence ) {
+ document.getElementsByTagName('div')[2].innerHTML = 'PASS';
+ } else {
+ document.getElementsByTagName('div')[2].innerHTML = 'FAIL, got:<br>'+sequence+'<br>instead of:<br>'+desiredsequence;
+ }
+ };
+};
+ </script>
+ </head>
+ <body>
+
+ <div draggable="true"></div>
+ <div dropzone="link string:text/plain"></div>
+ <div>&nbsp;</div>
+ <p>Drag the orange square onto the blue square and release it.</p>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/dropzone/008.html b/tests/wpt/web-platform-tests/html/editing/dnd/dropzone/008.html
new file mode 100644
index 00000000000..a82813c0430
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/dropzone/008.html
@@ -0,0 +1,56 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Dropzone should not affect the dropEffect if dragover is cancelled</title>
+ <style type="text/css">
+div:first-child {
+ height: 100px;
+ width: 100px;
+ background: orange;
+ display: inline-block;
+}
+div:first-child + div {
+ height: 100px;
+ width: 100px;
+ background: blue;
+ display: inline-block;
+}
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ var drag = document.getElementsByTagName('div')[0];
+ drag.ondragstart = function (e) {
+ e.dataTransfer.setData('text','hello');
+ e.dataTransfer.effectAllowed = 'all';
+ };
+ var drop = document.getElementsByTagName('div')[1], dragenter, dragover;
+ drop.ondragenter = function (e) {
+ dragenter = e.dataTransfer.dropEffect;
+ e.preventDefault();
+ };
+ drop.ondragover = function (e) {
+ dragover = e.dataTransfer.dropEffect;
+ e.preventDefault();
+ };
+ drop.ondrop = function (e) {
+ var sequence = ([dragenter,dragover,e.dataTransfer.dropEffect]).join('=&gt;')
+ var desiredsequence = (['copy','copy','copy']).join('=&gt;')
+ if( sequence == desiredsequence ) {
+ document.getElementsByTagName('div')[2].innerHTML = 'PASS';
+ } else {
+ document.getElementsByTagName('div')[2].innerHTML = 'FAIL, got:<br>'+sequence+'<br>instead of:<br>'+desiredsequence;
+ }
+ };
+};
+ </script>
+ </head>
+ <body>
+
+ <div draggable="true"></div>
+ <div dropzone="link string:text/plain"></div>
+ <div>&nbsp;</div>
+ <p>Drag the orange square onto the blue square and release it.</p>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/dropzone/009.html b/tests/wpt/web-platform-tests/html/editing/dnd/dropzone/009.html
new file mode 100644
index 00000000000..cc94dba0315
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/dropzone/009.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Dropping selection onto dropzone with JS disabled</title>
+ </head>
+ <body>
+
+ <ol>
+ <li>Disable JavaScript</li>
+ <li>Select some text in this sentence.</li>
+ <li dropzone="copy string:text/plain">Drag the selection over this text.</li>
+ <li>If supported by the platform, the mouse cursor should show the drop-allowed cursor.</li>
+ </ol>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/dropzone/010.html b/tests/wpt/web-platform-tests/html/editing/dnd/dropzone/010.html
new file mode 100644
index 00000000000..ff787b829a3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/dropzone/010.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Dropping selection onto dropzone with no padding</title>
+ </head>
+ <body>
+
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <ol>
+ <li>Select some text in this sentence.</li>
+ <li dropzone="copy string:text/plain" ondrop="this.parentNode.getElementsByTagName('li')[2].textContent='PASS';">Drag the selection over this text and release it.</li>
+ <li>This text should change.</li>
+ </ol>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/events/001-1.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/events/001-1.xhtml
new file mode 100644
index 00000000000..14eab24ca2f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/events/001-1.xhtml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Cross frame drag and drop: helper file</title>
+<style type="text/css">
+div
+ {width:0;
+ height:0;
+ border:solid 50px silver;
+ border-radius:50px;
+ margin-left:auto;}
+</style>
+<script type="application/ecmascript">
+var step = 1;
+function start(event)
+ {if(step++ == 1)
+ {setColor('green silver silver silver');}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragstart should be first event to fire.')}
+ }
+function leavePage(event)
+ {if(step++ > 1)
+ {setColor('green green silver silver')}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragleave should fire after dragstart.')}
+ }
+function endDrag(event)
+ {if(step++ > 2)
+ {setColor('green')}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragend should fire after dragstart and dragleave.')}
+ }
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'))}
+function setColor(c)
+ {document.querySelector('div').setAttribute('style','border-color:' + c)}
+</script>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('p'))" ondragleave="leavePage(event)">
+<p ondragstart="start(event)" ondragend="endDrag(event)">Drag me</p>
+<p>Drag selected text to the frame below and drop it there. Both circles should turn green once text is dropped into lower frame.</p>
+<div/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/events/001.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/events/001.xhtml
new file mode 100644
index 00000000000..4c8e7d563eb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/events/001.xhtml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop of selection between frames</title>
+</head>
+<frameset rows="50%, 50%">
+<frame src="001-1.xhtml"/>
+<frame src="helper-drop-here-body-circle.xhtml"/>
+</frameset>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/events/002-1.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/events/002-1.xhtml
new file mode 100644
index 00000000000..ef47895d66b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/events/002-1.xhtml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Cross frame drag and drop: helper file</title>
+<style type="text/css">
+div
+ {width:0;
+ height:0;
+ border:solid 50px silver;
+ border-radius:50px;
+ margin-left:auto;}
+</style>
+<script type="application/ecmascript">
+var step = 1;
+function start(event)
+ {if(step++ == 1)
+ {setColor('green silver silver silver');}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragstart should be first event to fire.')}
+ }
+function leavePage(event)
+ {if(step++ > 1)
+ {setColor('green green silver silver')}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragleave should fire after dragstart.')}
+ }
+function endDrag(event)
+ {if(step++ > 2)
+ {setColor('green')}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragend should fire after dragstart and dragleave.')}
+ }
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'))}
+function setColor(c)
+ {document.querySelector('div').setAttribute('style','border-color:' + c)}
+</script>
+</head>
+<body onload="document.querySelector('input').select()" ondragleave="leavePage(event)">
+<p ondragstart="start(event)" ondragend="endDrag(event)"><input value="Drag me"/></p>
+<p>Drag selected text to the frame below and drop it there. Both circles should turn green once text is dropped into lower frame.</p>
+<div/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/events/002.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/events/002.xhtml
new file mode 100644
index 00000000000..9bd76db260e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/events/002.xhtml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop of text input selection between frames</title>
+</head>
+<frameset rows="50%, 50%">
+<frame src="002-1.xhtml"/>
+<frame src="helper-drop-here-body-circle.xhtml"/>
+</frameset>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/events/003-1.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/events/003-1.xhtml
new file mode 100644
index 00000000000..8990404b1fa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/events/003-1.xhtml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Cross frame drag and drop: helper file</title>
+<style type="text/css">
+div
+ {width:0;
+ height:0;
+ border:solid 50px silver;
+ border-radius:50px;
+ margin-left:auto;}
+</style>
+<script type="application/ecmascript">
+var step = 1;
+function start(event)
+ {if(step++ == 1)
+ {setColor('green silver silver silver');}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragstart should be first event to fire.')}
+ }
+function leavePage(event)
+ {if(step++ > 1)
+ {setColor('green green silver silver')}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragleave should fire after dragstart.')}
+ }
+function endDrag(event)
+ {if(step++ > 2)
+ {setColor('green')}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragend should fire after dragstart and dragleave.')}
+ }
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'))}
+function setColor(c)
+ {document.querySelector('div').setAttribute('style','border-color:' + c)}
+</script>
+</head>
+<body ondragleave="leavePage(event)">
+<p><a href="data:text/plain,1" ondragstart="start(event)" ondragend="endDrag(event)">Drag me</a></p>
+<p>Drag link to the frame below and drop it there. Both circles should turn green once link is dropped into lower frame.</p>
+<div/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/events/003.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/events/003.xhtml
new file mode 100644
index 00000000000..c853e931d5f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/events/003.xhtml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop of link between frames</title>
+</head>
+<frameset rows="50%, 50%">
+<frame src="003-1.xhtml"/>
+<frame src="helper-drop-here-body-circle.xhtml"/>
+</frameset>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/events/004.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/events/004.xhtml
new file mode 100644
index 00000000000..f8a27e69f82
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/events/004.xhtml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop of selection to iframe</title>
+<style type="text/css">
+div
+ {width:0;
+ height:0;
+ border:solid 50px silver;
+ border-radius:50px;
+ margin-left:auto;}
+iframe
+ {width:100%;
+ height:500px;}
+</style>
+<script type="application/ecmascript">
+var step = 1;
+function start(event)
+ {if(step++ == 1)
+ {setColor('green silver silver silver');}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragstart should be first event to fire.')}
+ }
+function leavePage(event)
+ {if(step++ > 1)
+ {setColor('green green silver silver')}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragleave should fire after dragstart.')}
+ }
+function endDrag(event)
+ {if(step++ > 2)
+ {setColor('green')}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragend should fire after dragstart and dragleave.')}
+ }
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'))}
+function setColor(c)
+ {document.querySelector('div').setAttribute('style','border-color:' + c)}
+</script>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('p'))" ondragleave="leavePage(event)">
+<p ondragstart="start(event)" ondragend="endDrag(event)">Drag me</p>
+<p>Drag selected text to the frame below and drop it there. Both circles should turn green once text is dropped into lower frame.</p>
+<div/>
+<pre/>
+<iframe src="helper-drop-here-body-circle.xhtml">XHTML document</iframe>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/events/005.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/events/005.xhtml
new file mode 100644
index 00000000000..b84055fec8d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/events/005.xhtml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop of text input selection to iframe</title>
+<style type="text/css">
+div
+ {width:0;
+ height:0;
+ border:solid 50px silver;
+ border-radius:50px;
+ margin-left:auto;}
+iframe
+ {width:100%;
+ height:500px;}
+</style>
+<script type="application/ecmascript">
+var step = 1;
+function start(event)
+ {if(step++ == 1)
+ {setColor('green silver silver silver');}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragstart should be first event to fire.')}
+ }
+function leavePage(event)
+ {if(step++ > 1)
+ {setColor('green green silver silver')}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragleave should fire after dragstart.')}
+ }
+function endDrag(event)
+ {if(step++ > 2)
+ {setColor('green')}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragend should fire after dragstart and dragleave.')}
+ }
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'))}
+function setColor(c)
+ {document.querySelector('div').setAttribute('style','border-color:' + c)}
+</script>
+</head>
+<body onload="document.querySelector('input').select()" ondragleave="leavePage(event)">
+<p ondragstart="start(event)" ondragend="endDrag(event)"><input value="Drag me"/></p>
+<p>Drag selected text to the frame below and drop it there. Both circles should turn green once text is dropped into lower frame.</p>
+<div/>
+<pre/>
+<iframe src="helper-drop-here-body-circle.xhtml">XHTML document</iframe>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/events/006.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/events/006.xhtml
new file mode 100644
index 00000000000..40369c5701a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/events/006.xhtml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop of link to iframe</title>
+<style type="text/css">
+div
+ {width:0;
+ height:0;
+ border:solid 50px silver;
+ border-radius:50px;
+ margin-left:auto;}
+iframe
+ {width:100%;
+ height:500px;}
+</style>
+<script type="application/ecmascript">
+var step = 1;
+function start(event)
+ {if(step++ == 1)
+ {setColor('green silver silver silver');}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragstart should be first event to fire.')}
+ }
+function leavePage(event)
+ {if(step++ > 1)
+ {setColor('green green silver silver')}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragleave should fire after dragstart.')}
+ }
+function endDrag(event)
+ {if(step++ > 2)
+ {setColor('green')}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragend should fire after dragstart and dragleave.')}
+ }
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'))}
+function setColor(c)
+ {document.querySelector('div').setAttribute('style','border-color:' + c)}
+</script>
+</head>
+<body ondragleave="leavePage(event)">
+<p><a href="data:text/plain,1" ondragstart="start(event)" ondragend="endDrag(event)">Drag me</a></p>
+<p>Drag link to the frame below and drop it there. Both circles should turn green once link is dropped into lower frame.</p>
+<div/>
+<pre/>
+<iframe src="helper-drop-here-body-circle.xhtml">XHTML document</iframe>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/events/007.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/events/007.xhtml
new file mode 100644
index 00000000000..a7e91cdd0ab
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/events/007.xhtml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop of selection to object</title>
+<style type="text/css">
+div
+ {width:0;
+ height:0;
+ border:solid 50px silver;
+ border-radius:50px;
+ margin-left:auto;}
+object
+ {width:100%;
+ height:500px;
+ border:solid medium navy;}
+</style>
+<script type="application/ecmascript">
+var step = 1;
+function start(event)
+ {if(step++ == 1)
+ {setColor('green silver silver silver');}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragstart should be first event to fire.')}
+ }
+function leavePage(event)
+ {if(step++ > 1)
+ {setColor('green green silver silver')}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragleave should fire after dragstart.')}
+ }
+function endDrag(event)
+ {if(step++ > 2)
+ {setColor('green')}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragend should fire after dragstart and dragleave.')}
+ }
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'))}
+function setColor(c)
+ {document.querySelector('div').setAttribute('style','border-color:' + c)}
+</script>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('p'))" ondragleave="leavePage(event)">
+<p ondragstart="start(event)" ondragend="endDrag(event)">Drag me</p>
+<p>Drag selected text to the frame below and drop it there. Both circles should turn green once text is dropped into lower frame.</p>
+<div/>
+<pre/>
+<object type="application/xhtml+xml" data="helper-drop-here-body-circle.xhtml">XHTML document</object>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/events/008.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/events/008.xhtml
new file mode 100644
index 00000000000..8b275241413
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/events/008.xhtml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop of text input selection to object</title>
+<style type="text/css">
+div
+ {width:0;
+ height:0;
+ border:solid 50px silver;
+ border-radius:50px;
+ margin-left:auto;}
+object
+ {width:100%;
+ height:500px;
+ border:solid medium navy;}
+</style>
+<script type="application/ecmascript">
+var step = 1;
+function start(event)
+ {if(step++ == 1)
+ {setColor('green silver silver silver');}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragstart should be first event to fire.')}
+ }
+function leavePage(event)
+ {if(step++ > 1)
+ {setColor('green green silver silver')}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragleave should fire after dragstart.')}
+ }
+function endDrag(event)
+ {if(step++ > 2)
+ {setColor('green')}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragend should fire after dragstart and dragleave.')}
+ }
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'))}
+function setColor(c)
+ {document.querySelector('div').setAttribute('style','border-color:' + c)}
+</script>
+</head>
+<body onload="document.querySelector('input').select()" ondragleave="leavePage(event)">
+<p ondragstart="start(event)" ondragend="endDrag(event)"><input value="Drag me"/></p>
+<p>Drag selected text to the frame below and drop it there. Both circles should turn green once text is dropped into lower frame.</p>
+<div/>
+<pre/>
+<object type="application/xhtml+xml" data="helper-drop-here-body-circle.xhtml">XHTML document</object>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/events/009.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/events/009.xhtml
new file mode 100644
index 00000000000..d2eac96932c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/events/009.xhtml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop of link to object</title>
+<style type="text/css">
+div
+ {width:0;
+ height:0;
+ border:solid 50px silver;
+ border-radius:50px;
+ margin-left:auto;}
+object
+ {width:100%;
+ height:500px;
+ border:solid medium navy;}
+</style>
+<script type="application/ecmascript">
+var step = 1;
+function start(event)
+ {if(step++ == 1)
+ {setColor('green silver silver silver');}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragstart should be first event to fire.')}
+ }
+function leavePage(event)
+ {if(step++ > 1)
+ {setColor('green green silver silver')}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragleave should fire after dragstart.')}
+ }
+function endDrag(event)
+ {if(step++ > 2)
+ {setColor('green')}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragend should fire after dragstart and dragleave.')}
+ }
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'))}
+function setColor(c)
+ {document.querySelector('div').setAttribute('style','border-color:' + c)}
+</script>
+</head>
+<body ondragleave="leavePage(event)">
+<p><a href="data:text/plain,1" ondragstart="start(event)" ondragend="endDrag(event)">Drag me</a></p>
+<p>Drag link to the frame below and drop it there. Both circles should turn green once link is dropped into lower frame.</p>
+<div/>
+<pre/>
+<object type="application/xhtml+xml" data="helper-drop-here-body-circle.xhtml">XHTML document</object>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/events/010.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/events/010.xhtml
new file mode 100644
index 00000000000..1a9566822eb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/events/010.xhtml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop of selection from iframe</title>
+<style type="text/css">
+div
+ {width:0;
+ height:0;
+ border:solid 50px silver;
+ border-radius:50px;
+ margin-left:auto;}
+iframe
+ {width:100%;
+ height:300px;}
+</style>
+<script type="application/ecmascript">
+var step = 1;
+function enterPage(event)
+ {event.preventDefault();
+ if(step++ > 0)
+ {setColor('green silver silver silver');}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragenter should fire before dragover and drop');}
+ }
+function overPage(event)
+ {event.preventDefault();
+ if(step++ > 1)
+ {setColor('green green silver silver');}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragover should fire after dragenter');}
+ }
+function dropIt(event)
+ {if(step++ > 1)
+ {setColor('green');}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragover should fire after dragenter');}
+ }
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'))}
+function setColor(c)
+ {document.querySelector('div').setAttribute('style','border-color:' + c)}
+</script>
+</head>
+<body ondragenter="enterPage(event)" ondragover="overPage(event)" ondrop="dropIt(event)">
+<iframe src="helper-drag-me-p-with-circle.xhtml">XHTML document</iframe>
+<div/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/events/011.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/events/011.xhtml
new file mode 100644
index 00000000000..a4564bcba82
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/events/011.xhtml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop of text input selection from iframe</title>
+<style type="text/css">
+div
+ {width:0;
+ height:0;
+ border:solid 50px silver;
+ border-radius:50px;
+ margin-left:auto;}
+iframe
+ {width:100%;
+ height:300px;}
+</style>
+<script type="application/ecmascript">
+var step = 1;
+function enterPage(event)
+ {event.preventDefault();
+ if(step++ > 0)
+ {setColor('green silver silver silver');}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragenter should fire before dragover and drop');}
+ }
+function overPage(event)
+ {event.preventDefault();
+ if(step++ > 1)
+ {setColor('green green silver silver');}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragover should fire after dragenter');}
+ }
+function dropIt(event)
+ {if(step++ > 1)
+ {setColor('green');}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragover should fire after dragenter');}
+ }
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'))}
+function setColor(c)
+ {document.querySelector('div').setAttribute('style','border-color:' + c)}
+</script>
+</head>
+<body ondragenter="enterPage(event)" ondragover="overPage(event)" ondrop="dropIt(event)">
+<iframe src="helper-drag-me-input-with-circle.xhtml">XHTML document</iframe>
+<div/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/events/012.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/events/012.xhtml
new file mode 100644
index 00000000000..875d4ef562c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/events/012.xhtml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop of link from iframe</title>
+<style type="text/css">
+div
+ {width:0;
+ height:0;
+ border:solid 50px silver;
+ border-radius:50px;
+ margin-left:auto;}
+iframe
+ {width:100%;
+ height:300px;}
+</style>
+<script type="application/ecmascript">
+var step = 1;
+function enterPage(event)
+ {event.preventDefault();
+ if(step++ > 0)
+ {setColor('green silver silver silver');}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragenter should fire before dragover and drop');}
+ }
+function overPage(event)
+ {event.preventDefault();
+ if(step++ > 1)
+ {setColor('green green silver silver');}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragover should fire after dragenter');}
+ }
+function dropIt(event)
+ {if(step++ > 1)
+ {setColor('green');}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragover should fire after dragenter');}
+ }
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'))}
+function setColor(c)
+ {document.querySelector('div').setAttribute('style','border-color:' + c)}
+</script>
+</head>
+<body ondragenter="enterPage(event)" ondragover="overPage(event)" ondrop="dropIt(event)">
+<iframe src="helper-drag-me-link-with-circle.xhtml">XHTML document</iframe>
+<div/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/events/013.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/events/013.xhtml
new file mode 100644
index 00000000000..e6df03c1a25
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/events/013.xhtml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop of selection from object</title>
+<style type="text/css">
+div
+ {width:0;
+ height:0;
+ border:solid 50px silver;
+ border-radius:50px;
+ margin-left:auto;}
+object
+ {width:100%;
+ height:300px;
+ border:solid medium navy;}
+</style>
+<script type="application/ecmascript">
+var step = 1;
+function enterPage(event)
+ {event.preventDefault();
+ if(step++ > 0)
+ {setColor('green silver silver silver');}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragenter should fire before dragover and drop');}
+ }
+function overPage(event)
+ {event.preventDefault();
+ if(step++ > 1)
+ {setColor('green green silver silver');}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragover should fire after dragenter');}
+ }
+function dropIt(event)
+ {if(step++ > 1)
+ {setColor('green');}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragover should fire after dragenter');}
+ }
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'))}
+function setColor(c)
+ {document.querySelector('div').setAttribute('style','border-color:' + c)}
+</script>
+</head>
+<body ondragenter="enterPage(event)" ondragover="overPage(event)" ondrop="dropIt(event)">
+<object type="application/xhtml+xml" data="helper-drag-me-p-with-circle.xhtml">XHTML document</object>
+<div/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/events/014.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/events/014.xhtml
new file mode 100644
index 00000000000..f82d57b1567
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/events/014.xhtml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop of text input selection from object</title>
+<style type="text/css">
+div
+ {width:0;
+ height:0;
+ border:solid 50px silver;
+ border-radius:50px;
+ margin-left:auto;}
+object
+ {width:100%;
+ height:300px;
+ border:solid medium navy;}
+</style>
+<script type="application/ecmascript">
+var step = 1;
+function enterPage(event)
+ {event.preventDefault();
+ if(step++ > 0)
+ {setColor('green silver silver silver');}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragenter should fire before dragover and drop');}
+ }
+function overPage(event)
+ {event.preventDefault();
+ if(step++ > 1)
+ {setColor('green green silver silver');}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragover should fire after dragenter');}
+ }
+function dropIt(event)
+ {if(step++ > 1)
+ {setColor('green');}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragover should fire after dragenter');}
+ }
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'))}
+function setColor(c)
+ {document.querySelector('div').setAttribute('style','border-color:' + c)}
+</script>
+</head>
+<body ondragenter="enterPage(event)" ondragover="overPage(event)" ondrop="dropIt(event)">
+<object type="application/xhtml+xml" data="helper-drag-me-input-with-circle.xhtml">XHTML document</object>
+<div/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/events/015.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/events/015.xhtml
new file mode 100644
index 00000000000..bcd076b2163
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/events/015.xhtml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop of link from object</title>
+<style type="text/css">
+div
+ {width:0;
+ height:0;
+ border:solid 50px silver;
+ border-radius:50px;
+ margin-left:auto;}
+object
+ {width:100%;
+ height:300px;
+ border:solid medium navy;}
+</style>
+<script type="application/ecmascript">
+var step = 1;
+function enterPage(event)
+ {event.preventDefault();
+ if(step++ > 0)
+ {setColor('green silver silver silver');}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragenter should fire before dragover and drop');}
+ }
+function overPage(event)
+ {event.preventDefault();
+ if(step++ > 1)
+ {setColor('green green silver silver');}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragover should fire after dragenter');}
+ }
+function dropIt(event)
+ {if(step++ > 1)
+ {setColor('green');}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragover should fire after dragenter');}
+ }
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'))}
+function setColor(c)
+ {document.querySelector('div').setAttribute('style','border-color:' + c)}
+</script>
+</head>
+<body ondragenter="enterPage(event)" ondragover="overPage(event)" ondrop="dropIt(event)">
+<object type="application/xhtml+xml" data="helper-drag-me-link-with-circle.xhtml">XHTML document</object>
+<div/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/events/016.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/events/016.xhtml
new file mode 100644
index 00000000000..91e991fdb85
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/events/016.xhtml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop: events after dragenter is cancelled</title>
+<script type="application/ecmascript">
+function selectText()
+ {window.getSelection().selectAllChildren(document.querySelector('p'))}
+function start(event)
+ {event.preventDefault();}
+function dragMe(event)
+ {say('FAIL (drag event should not fire if dragstart is cancelled)');}
+function enterBody(event)
+ {event.preventDefault();
+ say('FAIL (dragover event should not fire if dragstart is cancelled)');}
+function overBody(event)
+ {event.preventDefault();
+ say('FAIL (dragover event should not fire if dragstart is cancelled)');}
+function dropIt(event)
+ {say('FAIL (drop event should not fire if dragstart is cancelled)');}
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+</script>
+</head>
+<body onload="selectText()" ondragenter="enterBody(event)" ondragover="overBody(event)" ondrop="dropIt(event)">
+<p ondragstart="start(event)" ondrag="dragMe(event)">Try to drag me</p>
+<p>You should not be able to drag text selection above.</p>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/events/017.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/events/017.xhtml
new file mode 100644
index 00000000000..e679ac0d35d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/events/017.xhtml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Text input selection drag and drop: events after dragenter is cancelled</title>
+<script type="application/ecmascript">
+function selectText()
+ {document.querySelector('input').select()}
+function start(event)
+ {event.preventDefault();}
+function dragMe(event)
+ {say('FAIL (drag event should not fire if dragstart is cancelled)');}
+function enterBody(event)
+ {event.preventDefault();
+ say('FAIL (dragover event should not fire if dragstart is cancelled)');}
+function overBody(event)
+ {event.preventDefault();
+ say('FAIL (dragover event should not fire if dragstart is cancelled)');}
+function dropIt(event)
+ {say('FAIL (drop event should not fire if dragstart is cancelled)');}
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+</script>
+</head>
+<body onload="selectText()" ondragenter="enterBody(event)" ondragover="overBody(event)" ondrop="dropIt(event)">
+<p ondragstart="start(event)"><input value="Try to drag me" ondrag="dragMe(event)"/></p>
+<p>You should not be able to drag text selection above.</p>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/events/018.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/events/018.xhtml
new file mode 100644
index 00000000000..65110f5c2b5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/events/018.xhtml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Link drag and drop: events after dragenter is cancelled</title>
+<script type="application/ecmascript">
+function start(event)
+ {event.preventDefault();}
+function dragMe(event)
+ {say('FAIL (drag event should not fire if dragstart is cancelled)');}
+function enterBody(event)
+ {event.preventDefault();
+ say('FAIL (dragover event should not fire if dragstart is cancelled)');}
+function overBody(event)
+ {event.preventDefault();
+ say('FAIL (dragover event should not fire if dragstart is cancelled)');}
+function dropIt(event)
+ {say('FAIL (drop event should not fire if dragstart is cancelled)');}
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+</script>
+</head>
+<body ondragenter="enterBody(event)" ondragover="overBody(event)" ondrop="dropIt(event)">
+<p><a href="data:text/plain,1" ondragstart="start(event)" ondrag="dragMe(event)">Try to drag me</a></p>
+<p>You should not be able to drag link above.</p>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/events/019.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/events/019.xhtml
new file mode 100644
index 00000000000..3c4928fc2eb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/events/019.xhtml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop: events after drag is cancelled</title>
+<script type="application/ecmascript">
+function selectText()
+ {window.getSelection().selectAllChildren(document.querySelector('p'))}
+function dragMe(event)
+ {event.preventDefault();}
+function dropIt(event)
+ {say('FAIL (no drop should occur after drag is cancelled)')}
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+</script>
+</head>
+<body onload="selectText()" dropzone="copy string:text/plain" ondrop="dropIt(event)">
+<p ondrag="dragMe(event)">Try to drag me</p>
+<p>You should not be able to drop text selection above.</p>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/events/020.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/events/020.xhtml
new file mode 100644
index 00000000000..dfd9138b1df
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/events/020.xhtml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Text input selection drag and drop: events after drag is cancelled</title>
+<script type="application/ecmascript">
+function selectText()
+ {document.querySelector('input').select()}
+function dragMe(event)
+ {event.preventDefault();}
+function dropIt(event)
+ {say('FAIL (no drop should occur after drag is cancelled)')}
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+</script>
+</head>
+<body onload="selectText()" dropzone="copy string:text/plain" ondrop="dropIt(event)">
+<p><input value="Try to drag me" ondrag="dragMe(event)"/></p>
+<p>You should not be able to drop text selection above.</p>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/events/021.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/events/021.xhtml
new file mode 100644
index 00000000000..87313e9db8c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/events/021.xhtml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Link drag and drop: events after drag is cancelled</title>
+<script type="application/ecmascript">
+function dragMe(event)
+ {event.preventDefault();}
+function dropIt(event)
+ {say('FAIL (no drop should occur after drag is cancelled)')}
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+</script>
+</head>
+<body dropzone="copy string:text/uri-list" ondrop="dropIt(event)">
+<p><a href="data:text/plain,1" ondrag="dragMe(event)">Try to drag me</a></p>
+<p>You should not be able to drag link above.</p>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/events/022.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/events/022.xhtml
new file mode 100644
index 00000000000..7d85f4218d8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/events/022.xhtml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop: events after drag and drop is cancelled</title>
+<style type="text/css">
+div
+ {width:0;
+ height:0;
+ border:solid 50px silver;
+ border-radius:50px;}
+</style>
+<script type="application/ecmascript">
+var result = true;
+function selectText()
+ {window.getSelection().selectAllChildren(document.querySelector('p'))}
+function dropIt(event)
+ {result = false;
+ setColor('maroon');
+ say('drop event : FAIL (no drop should occur once drag and drop is cancelled)')}
+function endDrag(event)
+ {if(result)
+ {setColor('teal')}
+ }
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+function setColor(c)
+ {document.querySelector('div').setAttribute('style','border-color:' + c)}
+</script>
+</head>
+<body onload="selectText()" dropzone="copy string:text/plain" ondrop="dropIt(event)">
+<p ondragstart="setColor('teal silver silver silver')" ondragend="endDrag(event)">Drag me</p>
+<p>Drag selected text and press Esc before you drop it. Circle below should turn green once drag and drop is cancelled.</p>
+<div/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/events/023.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/events/023.xhtml
new file mode 100644
index 00000000000..7a10c5b394e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/events/023.xhtml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Text input selection drag and drop: events after drag and drop is cancelled</title>
+<style type="text/css">
+div
+ {width:0;
+ height:0;
+ border:solid 50px silver;
+ border-radius:50px;}
+</style>
+<script type="application/ecmascript">
+var result = true;
+function selectText()
+ {document.querySelector('input').select()}
+function dropIt(event)
+ {result = false;
+ setColor('maroon');
+ say('drop event : FAIL (no drop should occur once drag and drop is cancelled)')}
+function endDrag(event)
+ {if(result)
+ {setColor('teal')}
+ }
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+function setColor(c)
+ {document.querySelector('div').setAttribute('style','border-color:' + c)}
+</script>
+</head>
+<body onload="selectText()" dropzone="copy string:text/plain" ondrop="dropIt(event)">
+<p><input value="Drag me" ondragstart="setColor('teal silver silver silver')" ondragend="endDrag(event)"/></p>
+<p>Drag selected text and press Esc before you drop it. Circle below should turn green once drag and drop is cancelled.</p>
+<div/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/events/024.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/events/024.xhtml
new file mode 100644
index 00000000000..cb079da399a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/events/024.xhtml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Link drag and drop: events after drag and drop is cancelled</title>
+<style type="text/css">
+div
+ {width:0;
+ height:0;
+ border:solid 50px silver;
+ border-radius:50px;}
+</style>
+<script type="application/ecmascript">
+var result = true;
+function dropIt(event)
+ {result = false;
+ setColor('maroon');
+ say('drop event : FAIL (no drop should occur once drag and drop is cancelled)')}
+function endDrag(event)
+ {if(result)
+ {setColor('teal')}
+ }
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'));}
+function setColor(c)
+ {document.querySelector('div').setAttribute('style','border-color:' + c)}
+</script>
+</head>
+<body dropzone="copy string:text/uri-list" ondrop="dropIt(event)">
+<p><a href="data:text/plain,1" ondragstart="setColor('teal silver silver silver')" ondragend="endDrag(event)">Drag me</a></p>
+<p>Drag link and press Esc before you drop it. Circle below should turn green once drag and drop is cancelled.</p>
+<div/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/events/025.html b/tests/wpt/web-platform-tests/html/editing/dnd/events/025.html
new file mode 100644
index 00000000000..043b40eedad
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/events/025.html
@@ -0,0 +1,69 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Dragover repeating</title>
+ <style type="text/css">
+div:first-child {
+ height: 100px;
+ width: 100px;
+ background: orange;
+ display: inline-block;
+}
+div:first-child + div {
+ height: 100px;
+ width: 100px;
+ background: blue;
+ display: inline-block;
+}
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ var numsecs = 5, maxpolltime = 0.550, minpolltime = 0.150;
+ var blue = document.getElementsByTagName('div')[1], p = document.getElementsByTagName('p')[0];
+ var numfired = 0, readytocount = false;
+ document.getElementsByTagName('div')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'all';
+ e.dataTransfer.setData('text','dummy text');
+ };
+ blue.ondrop = function (e) {
+ e.preventDefault();
+ };
+ blue.ondragover = function (e) {
+ e.preventDefault();
+ if( readytocount ) { numfired++; }
+ };
+ blue.ondragenter = function (e) {
+ e.preventDefault();
+ p.innerHTML = 'Keep the mouse perfectly still...';
+ //give the tester a second to get ready
+ setTimeout(function () {
+ readytocount = true;
+ numfired = 0;
+ p.innerHTML = 'Keep the mouse perfectly still for '+numsecs+' seconds';
+ var countsecs = numsecs;
+ var intr = setInterval(function () {
+ countsecs--;
+ if( countsecs ) {
+ p.innerHTML = 'Keep the mouse perfectly still for '+countsecs+' seconds';
+ } else {
+ clearInterval(intr);
+ var passed = numfired >= Math.floor( numsecs / maxpolltime ) && numfired <= Math.floor( numsecs / minpolltime );
+ document.getElementsByTagName('p')[0].innerHTML = ( passed ? 'PASS' : 'FAIL' ) +
+ '<br><br>(Fired ' + numfired + ' times in ' + numsecs + ' seconds, must be between ' +
+ Math.floor( numsecs / maxpolltime ) + ' and ' + Math.floor( numsecs / minpolltime ) + ')<br>You can release the drag now';
+ }
+ },1000);
+ },1000);
+ };
+};
+ </script>
+ </head>
+ <body>
+
+ <div draggable="true"></div>
+ <div></div>
+ <p>Drag the orange square over the blue square, then keep the mouse perfectly still until the result appears.</p>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/events/026.html b/tests/wpt/web-platform-tests/html/editing/dnd/events/026.html
new file mode 100644
index 00000000000..7ea1755538d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/events/026.html
@@ -0,0 +1,61 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Drag repeating</title>
+ <style type="text/css">
+div:first-child {
+ height: 100px;
+ width: 100px;
+ background: orange;
+ display: inline-block;
+}
+div:first-child + div {
+ height: 100px;
+ width: 100px;
+ background: blue;
+ display: inline-block;
+}
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ var numsecs = 5, maxpolltime = 0.550, minpolltime = 0.150;
+ var orange = document.getElementsByTagName('div')[0], p = document.getElementsByTagName('p')[0];
+ var numfired = 0, readytocount = false;
+ document.getElementsByTagName('div')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'all';
+ e.dataTransfer.setData('text','dummy text');
+ p.innerHTML = 'Keep the mouse perfectly still...';
+ //give the tester a second to get ready
+ setTimeout(function () {
+ readytocount = true;
+ numfired = 0;
+ p.innerHTML = 'Keep the mouse perfectly still for '+numsecs+' seconds';
+ var countsecs = numsecs;
+ var intr = setInterval(function () {
+ countsecs--;
+ if( countsecs ) {
+ p.innerHTML = 'Keep the mouse perfectly still for '+countsecs+' seconds';
+ } else {
+ clearInterval(intr);
+ var passed = numfired >= Math.floor( numsecs / maxpolltime ) && numfired <= Math.floor( numsecs / minpolltime );
+ document.getElementsByTagName('p')[0].innerHTML = ( passed ? 'PASS' : 'FAIL' ) +
+ '<br><br>(Fired ' + numfired + ' times in ' + numsecs + ' seconds, must be between ' +
+ Math.floor( numsecs / maxpolltime ) + ' and ' + Math.floor( numsecs / minpolltime ) + ')<br>You can release the drag now';
+ }
+ },1000);
+ },1000);
+ };
+ orange.ondrag = function (e) {
+ if( readytocount ) { numfired++; }
+ };
+};
+ </script>
+ </head>
+ <body>
+
+ <div draggable="true"></div>
+ <p>Drag the orange square sideways until the drag placeholder appears, then keep the mouse perfectly still until the result appears.</p>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/events/027.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/events/027.xhtml
new file mode 100644
index 00000000000..f6103619713
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/events/027.xhtml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>PNG image drag and drop: 'return false' should not cancel event</title>
+<style type="text/css">
+div
+ {height:100px;
+ width:100px;
+ padding:20px;
+ background-color:silver;}
+</style>
+<script type="application/ecmascript">
+function addImage(event)
+ {var c = document.createElement('img');
+ c.setAttribute('src',event.dataTransfer.getData('text/uri-list').replace(/\r\n$/,''));
+ document.querySelector('div').appendChild(c);}
+</script>
+</head>
+<body onload="document.querySelector('img').addEventListener('drag',function (){return false},false)">
+<p><img ondragstart="event.dataTransfer.effectAllowed = 'copy'" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAEq0lEQVR42u1dvU4bQRAeR0RCCilSp0peIoKGB4DSXYRDlcZlFClKBI4bB/kV/AymIDwCTahiicaioEOxhCsjWVTJziyKMfYZn+9ud3bvG2mEZB13u9+nndmf2Rki7fKFXtEBbVKD9o22jB4bPaND6hm9Mjo0enevw/vfevKMfbYl/8vv4HdBUkvFALhltG2A7dN3+pur8jv53fwN/hZkjjRo3eiuAatjdJA7CcnkDOSb/G1uQ6mFzUeDagaQrvl764yEJOU22LbUymXaGrRhOt40OvJOQvLIGUkbP9GLeIn4SM9NJ+tOTVI+Jq0ubY9sVFRNxy6DIWKWmEvpQ/ByQNumI+fBEjHrZ86lT8HJV3ptGn8aDRGzxJxKHwMZFe9Mg6+jJWNCyrX0VbUc0nuj4+jJmPiWsfRZodN+ZvSoNETMjpYjwUCFfKaXpjEnpSVjQsqJYOF5ZLw1elF6MiakXAgmnpw378DegIgZUm4EGw8jA2QsIuUbvXHpM2CmljFfhfsUO5uCA0/j6AudfZV5arv6WuVHcYs+ALwqKTkvHnmLoEwr8CJW9Llts9iNwvj3plzsfeWyIRnzrq37kfIzq6naBpA5a6bzlJgOl/SMkl+rklEFgIX5k5THwTYgIdwzcP2jhM/o19KsOeoArnBS6suaqo2gQnXCJWSwXNwXB4gBMFekNBeTwSGUmiMK4yNktDhsleNaAZRrUvYWmasuQHJOSDdpdKyriEIvo9maexWC70gAIF/bKTvzzFUH4HgbJZ3HdFSw9vC6lfKHpq7X8X07AOOblK2HhLQBindC2g/9Rx+gePcj/cnqHIDoUFm1c9gjwNAy/d0kyXIAMLSYrQ8kqScAhhbH3iLJBwIwtBByTJKkBWBoIeSMJHMOwNBCyG+SdEYAQ4tTvyLJMQUwtBAyJEn8BTC0EHIHQhQSApOlzGTBqaty6jzVAhhaCOlhYahuYYitE02EHGNzURchLZItX4ChhZB9HFBpUjmgwhGuHv0feI0gBw1T3j7CgHT5jzYC5XQRsjUdSsrhjADGl7ka0EylBgRb+ySkMy9rww7A8Waududf2MH9Qh9k3CbXLsGVNh/mqrvojuEeQHI+Qmq4Fq1ndIyeruaDxAEuCWk+ncmB0z3gepubtQenMUHyGTWELJl8xk6B15CeqVAyLtPXtUICsyJnVivWs+J0dAAwbzLOkQRTk2YuKsapTQFkXqPjlDILEinnRcZ1fpXdkGo866xqnH9FNyTjz0JIQZXcuPQCAE5rqo6oMEFBl7RknBRfTg8lj5Yl48JdGT0ueIWiYIvIuHFfPg9l85LJcF42b+JTUFjysZnyVlhy2qfA0asovTo9+0JxYnWC8t0KBQXuFYrdkIy3mBj3LbeNQrejZTuqOlbcl8znGTqcfjXoM3pboqgaPhEPxda1qgcVYsRt5TanDkgISWzcV1N1hCS3jdu4dNxUDMIhlBzXysHGGspkcBtsW2pPh3fGLrZ2ya5cXHFp0qxJ6si3E68EQCpy344vQRZxO5jfye+2d/oqgHsV02Z3lvcl9QTnA+EkLZw5h9MZcY4pTvxldXj/W0+esc+25H/5HQGYon+Q5f+MwFz+8QAAAABJRU5ErkJggg==" alt="PNG circle"/></p>
+<p>Drag green circle to the silver box below and drop it. It should be copied to the box once you drop it there.</p>
+<div ondragenter="event.preventDefault()" ondragover="return false" ondrop="addImage(event)"/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/events/028.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/events/028.xhtml
new file mode 100644
index 00000000000..ce4944106a1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/events/028.xhtml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Link drag and drop: 'return false' should not cancel event</title>
+<style type="text/css">
+div
+ {min-height:100px;
+ width:100px;
+ padding:20px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body onload="document.querySelector('a').addEventListener('drag',function (){return false},false)">
+<p><a href="data:text/plain,1" ondragstart="event.dataTransfer.effectAllowed = 'copy'">Drag me</a></p>
+<p>Drag link above to the navy box below and drop it. You should see word PASS once you drop it in the box.</p>
+<div ondragenter="event.preventDefault()" ondragover="return false" ondrop="document.querySelector('div').appendChild(document.createTextNode((event.dataTransfer.getData('text/uri-list').replace(/\r\n$/,'') == 'data:text/plain,1')?'PASS':'FAIL'))"/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/events/029.html b/tests/wpt/web-platform-tests/html/editing/dnd/events/029.html
new file mode 100644
index 00000000000..c02cd95b3a4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/events/029.html
@@ -0,0 +1,79 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Drag and drop without cancelling dragenter</title>
+ <style type="text/css">
+div:first-child {
+ height: 100px;
+ width: 100px;
+ background: orange;
+ display: inline-block;
+}
+div:first-child + div {
+ height: 100px;
+ width: 100px;
+ background: blue;
+ display: inline-block;
+}
+ </style>
+ <script type="text/javascript">
+
+window.onload = function () {
+ var drag = document.getElementsByTagName('div')[0], sequence = [];
+ drag.ondragstart = function (e) {
+ e.dataTransfer.setData('text','hello');
+ e.dataTransfer.effectAllowed = 'copy';
+ };
+ drag.ondragenter = drag.ondragover = function (e) {
+ e.preventDefault();
+ };
+ var drop = document.getElementsByTagName('div')[1], dragoverhasfired = false;
+ drop.ondragenter = function (e) {
+ dragoverhasfired = true; //events targeting body will be ignored until this event has fired
+ sequence[sequence.length] = 'drop.dragenter';
+ };
+ drop.ondragover = function (e) {
+ e.preventDefault();
+ if( sequence[sequence.length-1] != 'drop.dragover' ) {
+ sequence[sequence.length] = 'drop.dragover';
+ }
+ };
+ drop.ondrop = function (e) {
+ e.preventDefault();
+ sequence[sequence.length] = 'drop.ondrop';
+ };
+ document.body.ondragenter = function (e) {
+ if( e.target != this ) { return; }
+ if( dragoverhasfired ) {
+ sequence[sequence.length] = 'body.dragenter';
+ }
+ };
+ document.body.ondragover = function (e) {
+ if( e.target != this ) { return; }
+ if( dragoverhasfired ) {
+ if( sequence[sequence.length-1] != 'body.dragover' ) {
+ sequence[sequence.length] = 'body.dragover';
+ }
+ }
+ };
+ drag.ondragend = function (e) {
+ sequence = sequence.join('=&gt;')
+ var desiredsequence = (['drop.dragenter','body.dragenter','body.dragover']).join('=&gt;')
+ if( sequence == desiredsequence ) {
+ document.getElementsByTagName('div')[2].innerHTML = 'PASS';
+ } else {
+ document.getElementsByTagName('div')[2].innerHTML = 'FAIL, got:<br>'+sequence+'<br>instead of:<br>'+desiredsequence;
+ }
+ };
+};
+ </script>
+ </head>
+ <body>
+
+ <div draggable="true"></div><div></div>
+ <div>&nbsp;</div>
+ <p>Drag the orange square onto the blue square and release it.</p>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/events/030.html b/tests/wpt/web-platform-tests/html/editing/dnd/events/030.html
new file mode 100644
index 00000000000..5d5eaa28409
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/events/030.html
@@ -0,0 +1,61 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Drag and drop without cancelling dragenter on body</title>
+ <style type="text/css">
+div:first-child {
+ height: 100px;
+ width: 100px;
+ background: orange;
+ display: inline-block;
+}
+div:first-child + div {
+ height: 100px;
+ width: 100px;
+ margin-left: 100px;
+ background: blue;
+ display: inline-block;
+}
+ </style>
+ <script type="text/javascript">
+//If dragenter is cancelled the body should then become the target element, receiving both a dragenter and a dragover event.
+//When the body is the actual immediate user selection (first time over the body), that means it gets *2* dragenter events
+//Then when a div becomes immediate user selection (blue) but does not cancel the dragenter event, dragenter does not need
+//to fire on body because body is already the current target element
+//Then when the body is the actual immediate user selection again (second time over the body), it is already the current
+//target element, so does not get a dragenter event
+window.onload = function () {
+ var drag = document.getElementsByTagName('div')[0], beforecount = 0, aftercount = 0, switchcount = false;
+ drag.ondragstart = function (e) {
+ e.dataTransfer.setData('text','hello');
+ e.dataTransfer.effectAllowed = 'copy';
+ };
+ drag.ondragenter = drag.ondrop = drag.ondragover = function (e) {
+ e.preventDefault();
+ };
+ var drop = document.getElementsByTagName('div')[1];
+ drop.ondragenter = function (e) {
+ switchcount = true;
+ };
+ drop.ondragover = function (e) {
+ e.preventDefault();
+ };
+ document.body.ondragenter = function (e) {
+ if( e.target != this ) { return; }
+ if( switchcount ) { aftercount++; } else { beforecount++; }
+ };
+ drag.ondragend = function (e) {
+ document.getElementsByTagName('div')[2].innerHTML = ( beforecount == 2 && aftercount == 0 ) ? 'PASS' : ( 'FAIL, dragenter fired on body '+beforecount+' time(s) before blue.ondragenter and '+aftercount+' time(s) afterwards, instead of 2 and 0 times respectively' );
+ };
+};
+ </script>
+ </head>
+ <body>
+
+ <div draggable="true"></div><div></div>
+ <div>&nbsp;</div>
+ <p>Drag the orange square onto the blue square, then back to the orange square, and release it.</p>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/events/031-1.html b/tests/wpt/web-platform-tests/html/editing/dnd/events/031-1.html
new file mode 100644
index 00000000000..1574c590471
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/events/031-1.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Non-rendered body should still become current target element</title>
+ <style type="text/css">
+html { background: blue; }
+ </style>
+ </head>
+ <body>
+
+ <script type="text/javascript">
+var seentypes = {};
+document.body.ondragenter = document.body.ondragover = document.body.ondrop = function (e) {
+ e.preventDefault();
+ //document.body.innerHTML += e.type;
+ if( e.type == 'drop' ) {
+ document.body.innerHTML = ( seentypes.dragenter && seentypes.dragover ) ? 'PASS' : 'FAIL';
+ } else {
+ seentypes[e.type] = true;
+ }
+}
+ </script>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/events/031.html b/tests/wpt/web-platform-tests/html/editing/dnd/events/031.html
new file mode 100644
index 00000000000..101edeafb49
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/events/031.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Non-rendered body should still become current target element</title>
+ <style type="text/css">
+span { background: orange; display: inline-block; height: 200px; width: 200px; }
+iframe { border: none; }
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ document.getElementsByTagName('span')[0].ondragstart = function (e) {
+ e.dataTransfer.setData('text','dummy text');
+ e.dataTransfer.effectAllowed = 'copy';
+ };
+};
+ </script>
+ </head>
+ <body>
+
+ <p>Drag the orange square onto the blue square and release it. Fail if text does not appear in the blue square.</p>
+ <p><span draggable="true"></span> <iframe height="200" width="200" src="031-1.html"></iframe></p>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/events/032.html b/tests/wpt/web-platform-tests/html/editing/dnd/events/032.html
new file mode 100644
index 00000000000..af1e2253f1d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/events/032.html
@@ -0,0 +1,81 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Drag and drop passing over body without cancelling dragenter</title>
+ <style type="text/css">
+div:first-child {
+ height: 100px;
+ width: 100px;
+ background: orange;
+ display: inline-block;
+}
+div:first-child + div {
+ height: 100px;
+ width: 100px;
+ margin-left: 200px;
+ background: blue;
+ display: inline-block;
+}
+ </style>
+ <script type="text/javascript">
+//this test enforces the following spec statement:
+//"if this immediate user selection is not the same as the current target element"
+window.onload = function () {
+ var drag = document.getElementsByTagName('div')[0], sequence = [];
+ drag.ondragstart = function (e) {
+ e.dataTransfer.setData('text','hello');
+ e.dataTransfer.effectAllowed = 'copy';
+ };
+ drag.ondragenter = function (e) {
+ sequence[sequence.length] = 'drag.dragenter';
+ };
+ drag.ondragover = function (e) {
+ if( sequence[sequence.length-1] != 'drag.dragover' ) {
+ sequence[sequence.length] = 'drag.dragover';
+ }
+ };
+ var drop = document.getElementsByTagName('div')[1];
+ drop.ondragenter = function (e) {
+ e.preventDefault();
+ sequence[sequence.length] = 'drop.dragenter';
+ };
+ drop.ondragover = function (e) {
+ e.preventDefault();
+ if( sequence[sequence.length-1] != 'drop.dragover' ) {
+ sequence[sequence.length] = 'drop.dragover';
+ }
+ };
+ drop.ondrop = function (e) {
+ e.preventDefault();
+ sequence[sequence.length] = 'drop.ondrop';
+ };
+ document.body.ondragenter = function (e) {
+ sequence[sequence.length] = ( e.target == this ) ? 'body.dragenter' : 'bubble.dragenter';
+ };
+ document.body.ondragover = function (e) {
+ if( e.target != this ) { return; }
+ if( sequence[sequence.length-1] != 'body.dragover' ) {
+ sequence[sequence.length] = 'body.dragover';
+ }
+ };
+ drag.ondragend = function (e) {
+ sequence = sequence.join('=&gt;')
+ var desiredsequence = (['drag.dragenter','bubble.dragenter','body.dragenter','body.dragover','drop.dragenter','bubble.dragenter','drop.dragover','drop.ondrop']).join('=&gt;')
+ if( sequence == desiredsequence ) {
+ document.getElementsByTagName('div')[2].innerHTML = 'PASS';
+ } else {
+ document.getElementsByTagName('div')[2].innerHTML = 'FAIL, got:<br>'+sequence+'<br>instead of:<br>'+desiredsequence;
+ }
+ };
+};
+ </script>
+ </head>
+ <body>
+
+ <div draggable="true"></div><div></div>
+ <div>&nbsp;</div>
+ <p>Drag the orange square onto the blue square and release it.</p>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/events/033.html b/tests/wpt/web-platform-tests/html/editing/dnd/events/033.html
new file mode 100644
index 00000000000..c33aa554606
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/events/033.html
@@ -0,0 +1,79 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Drag and drop without cancelling dragenter from non-target to non-target</title>
+ <style type="text/css">
+div:first-child {
+ height: 100px;
+ width: 100px;
+ background: orange;
+ display: inline-block;
+}
+div:first-child + div {
+ height: 100px;
+ width: 100px;
+ background: blue;
+ display: inline-block;
+}
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ var drag = document.getElementsByTagName('div')[0], sequence = [];
+ drag.ondragstart = function (e) {
+ e.dataTransfer.setData('text','hello');
+ e.dataTransfer.effectAllowed = 'copy';
+ };
+ drag.ondragenter = function (e) {
+ sequence[sequence.length] = 'drag.dragenter';
+ };
+ drag.ondragover = function (e) {
+ if( sequence[sequence.length-1] != 'drag.dragover' ) {
+ sequence[sequence.length] = 'drag.dragover';
+ }
+ };
+ drag.ondragleave = function (e) {
+ sequence[sequence.length] = 'drag.dragleave';
+ };
+ var drop = document.getElementsByTagName('div')[1];
+ drop.ondragenter = function (e) {
+ sequence[sequence.length] = 'drop.dragenter';
+ };
+ drop.ondragover = function (e) {
+ if( sequence[sequence.length-1] != 'drop.dragover' ) {
+ sequence[sequence.length] = 'drop.dragover';
+ }
+ };
+ drop.ondrop = function (e) {
+ e.preventDefault();
+ sequence[sequence.length] = 'drop.ondrop';
+ };
+ document.body.ondragenter = function (e) {
+ sequence[sequence.length] = ( e.target == this ) ? 'body.dragenter' : 'bubble.dragenter';
+ };
+ document.body.ondragover = function (e) {
+ if( e.target != this ) { return; }
+ if( sequence[sequence.length-1] != 'body.dragover' ) {
+ sequence[sequence.length] = 'body.dragover';
+ }
+ };
+ drag.ondragend = function (e) {
+ sequence = sequence.join('=&gt;')
+ var desiredsequence = (['drag.dragenter','bubble.dragenter','body.dragenter','body.dragover','drop.dragenter','bubble.dragenter','body.dragover']).join('=&gt;')
+ if( sequence == desiredsequence ) {
+ document.getElementsByTagName('div')[2].innerHTML = 'PASS';
+ } else {
+ document.getElementsByTagName('div')[2].innerHTML = 'FAIL, got:<br>'+sequence+'<br>instead of:<br>'+desiredsequence;
+ }
+ };
+};
+ </script>
+ </head>
+ <body>
+
+ <div draggable="true"></div><div></div>
+ <div>&nbsp;</div>
+ <p>Drag the orange square onto the blue square and release it.</p>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/events/034.html b/tests/wpt/web-platform-tests/html/editing/dnd/events/034.html
new file mode 100644
index 00000000000..ed13d00ca64
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/events/034.html
@@ -0,0 +1,56 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Drag and drop with cancelling dragenter on body</title>
+ <style type="text/css">
+div:first-child {
+ height: 100px;
+ width: 100px;
+ background: orange;
+ display: inline-block;
+}
+div:first-child + div {
+ height: 100px;
+ width: 100px;
+ margin-left: 100px;
+ background: blue;
+ display: inline-block;
+}
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ var drag = document.getElementsByTagName('div')[0], beforecount = 0, aftercount = 0, switchcount = false;
+ drag.ondragstart = function (e) {
+ e.dataTransfer.setData('text','hello');
+ e.dataTransfer.effectAllowed = 'copy';
+ };
+ drag.ondragenter = drag.ondrop = drag.ondragover = function (e) {
+ e.preventDefault();
+ };
+ var drop = document.getElementsByTagName('div')[1];
+ drop.ondragenter = function (e) {
+ switchcount = true;
+ };
+ drop.ondragover = function (e) {
+ e.preventDefault();
+ };
+ document.body.ondragenter = function (e) {
+ if( e.target != this ) { return; }
+ e.preventDefault(); //don't cancel when it bubbles from the child elements
+ if( switchcount ) { aftercount++; } else { beforecount++; }
+ };
+ drag.ondragend = function (e) {
+ document.getElementsByTagName('div')[2].innerHTML = ( beforecount == 1 && aftercount == 0 ) ? 'PASS' : ( 'FAIL, dragenter fired on body '+beforecount+' time(s) before blue.ondragenter and '+aftercount+' time(s) afterwards, instead of 1 and 0 times respectively' );
+ };
+};
+ </script>
+ </head>
+ <body>
+
+ <div draggable="true"></div><div></div>
+ <div>&nbsp;</div>
+ <p>Drag the orange square onto the blue square, then back to the orange square, and release it.</p>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/events/035.html b/tests/wpt/web-platform-tests/html/editing/dnd/events/035.html
new file mode 100644
index 00000000000..3d1ba04c710
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/events/035.html
@@ -0,0 +1,83 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Drag and drop passing over body with cancelling dragenter</title>
+ <style type="text/css">
+div:first-child {
+ height: 100px;
+ width: 100px;
+ background: orange;
+ display: inline-block;
+}
+div:first-child + div {
+ height: 100px;
+ width: 100px;
+ margin-left: 200px;
+ background: blue;
+ display: inline-block;
+}
+ </style>
+ <script type="text/javascript">
+//this test enforces the following spec statement:
+//"if this immediate user selection is not the same as the current target element"
+window.onload = function () {
+ var drag = document.getElementsByTagName('div')[0], sequence = [];
+ drag.ondragstart = function (e) {
+ e.dataTransfer.setData('text','hello');
+ e.dataTransfer.effectAllowed = 'copy';
+ };
+ drag.ondragenter = function (e) {
+ sequence[sequence.length] = 'drag.dragenter';
+ };
+ drag.ondragover = function (e) {
+ if( sequence[sequence.length-1] != 'drag.dragover' ) {
+ sequence[sequence.length] = 'drag.dragover';
+ }
+ };
+ var drop = document.getElementsByTagName('div')[1];
+ drop.ondragenter = function (e) {
+ e.preventDefault();
+ sequence[sequence.length] = 'drop.dragenter';
+ };
+ drop.ondragover = function (e) {
+ e.preventDefault();
+ if( sequence[sequence.length-1] != 'drop.dragover' ) {
+ sequence[sequence.length] = 'drop.dragover';
+ }
+ };
+ drop.ondrop = function (e) {
+ e.preventDefault();
+ sequence[sequence.length] = 'drop.ondrop';
+ };
+ document.body.ondragenter = function (e) {
+ sequence[sequence.length] = ( e.target == this ) ? 'body.dragenter' : 'bubble.dragenter';
+ if( e.target != this ) { return; }
+ e.preventDefault(); //don't cancel when it bubbles from the child elements
+ };
+ document.body.ondragover = function (e) {
+ if( e.target != this ) { return; }
+ if( sequence[sequence.length-1] != 'body.dragover' ) {
+ sequence[sequence.length] = 'body.dragover';
+ }
+ };
+ drag.ondragend = function (e) {
+ sequence = sequence.join('=&gt;')
+ var desiredsequence = (['drag.dragenter','bubble.dragenter','body.dragenter','body.dragover','drop.dragenter','bubble.dragenter','drop.dragover','drop.ondrop']).join('=&gt;')
+ if( sequence == desiredsequence ) {
+ document.getElementsByTagName('div')[2].innerHTML = 'PASS';
+ } else {
+ document.getElementsByTagName('div')[2].innerHTML = 'FAIL, got:<br>'+sequence+'<br>instead of:<br>'+desiredsequence;
+ }
+ };
+};
+ </script>
+ </head>
+ <body>
+
+ <div draggable="true"></div><div></div>
+ <div>&nbsp;</div>
+ <p>Drag the orange square onto the blue square and release it.</p>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/events/036.html b/tests/wpt/web-platform-tests/html/editing/dnd/events/036.html
new file mode 100644
index 00000000000..5a2d3c337c4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/events/036.html
@@ -0,0 +1,70 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Drag and drop passing over body with all events handled at body</title>
+ <style type="text/css">
+div:first-child {
+ height: 100px;
+ width: 100px;
+ background: orange;
+ display: inline-block;
+}
+div:first-child + div {
+ height: 100px;
+ width: 100px;
+ margin-left: 200px;
+ background: blue;
+ display: inline-block;
+}
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ var drag = document.getElementsByTagName('div')[0], drop = document.getElementsByTagName('div')[1], sequence = [];
+ function targ(el) {
+ if( el == drag ) { return 'drag'; }
+ else if( el == drop ) { return 'drop'; }
+ else if( el == document.body ) { return 'body'; }
+ else { return el; }
+ }
+ document.body.ondragstart = function (e) {
+ e.dataTransfer.setData('text','data');
+ e.dataTransfer.effectAllowed = 'copy';
+ };
+ document.body.ondragenter = function (e) {
+ e.preventDefault();
+ sequence[sequence.length] = targ(e.target)+'.ondragenter';
+ };
+ document.body.ondragover = function (e) {
+ e.preventDefault();
+ var seqname = targ(e.target)+'.ondragover';
+ if( sequence[sequence.length-1] != seqname ) {
+ sequence[sequence.length] = seqname;
+ }
+ };
+ document.body.ondrop = function (e) {
+ e.preventDefault();
+ sequence[sequence.length] = targ(e.target)+'.ondrop';
+ sequence[sequence.length] = e.dataTransfer.getData('text');
+ };
+ document.body.ondragend = function (e) {
+ sequence[sequence.length] = targ(e.target)+'.ondragend';
+ sequence = sequence.join('=&gt;')
+ var desiredsequence = (['drag.ondragenter','drag.ondragover','body.ondragenter','body.ondragover','drop.ondragenter','drop.ondragover','drop.ondrop','data','drag.ondragend']).join('=&gt;')
+ if( sequence == desiredsequence ) {
+ document.getElementsByTagName('div')[2].innerHTML = 'PASS';
+ } else {
+ document.getElementsByTagName('div')[2].innerHTML = 'FAIL, got:<br>'+sequence+'<br>instead of:<br>'+desiredsequence;
+ }
+ };
+};
+ </script>
+ </head>
+ <body>
+
+ <div draggable="true"></div><div></div>
+ <div>&nbsp;</div>
+ <p>Drag the orange square onto the blue square and release it. For the entire duration of the drag, if supported by the platform, the mouse cursor should show as a drop-allowed or drop-copy-allowed cursor.</p>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/events/037-proposed.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/events/037-proposed.xhtml
new file mode 100644
index 00000000000..6fdd1b2f4d7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/events/037-proposed.xhtml
@@ -0,0 +1,86 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Drag and drop without cancelling dragenter and without body</title>
+ <style type="text/css">
+html {
+ padding:20px;
+}
+head + div {
+ height: 100px;
+ width: 100px;
+ background: orange;
+ display: inline-block;
+}
+head + div + div {
+ height: 100px;
+ width: 100px;
+ margin-left: 100px;
+ background: blue;
+ display: inline-block;
+}
+ </style>
+ <script type="text/javascript"><![CDATA[
+//Drag passes from orange to root element. Dragenter fires at root element.
+//Dragenter is not cancelled. Body does not exist. Dragenter fires at root element again.
+//Drag passes from root element to blue. Dragenter fires at blue.
+//Dragenter is not cancelled. Body does not exist. Current target element is root element.
+//Drag passes from blue to root element. Current target element is already root element.
+//Drag passes from root element to orange. Dragenter fires at orange, and is cancelled.
+window.onload = function () {
+ var orange = document.getElementsByTagName('div')[0], sequence = [];
+ orange.ondragstart = function (e) {
+ e.dataTransfer.setData('text','hello');
+ e.dataTransfer.effectAllowed = 'copy';
+ };
+ orange.ondragenter = orange.ondrop = function (e) {
+ sequence[sequence.length] = 'orange.'+e.type;
+ e.preventDefault();
+ };
+ orange.ondragleave = function (e) {
+ sequence[sequence.length] = 'orange.dragleave';
+ };
+ orange.ondragover = function (e) {
+ if( sequence[sequence.length-1] != 'orange.dragover' ) {
+ sequence[sequence.length] = 'orange.dragover';
+ }
+ e.preventDefault();
+ };
+ var blue = document.getElementsByTagName('div')[1];
+ blue.ondragenter = blue.ondragover = blue.ondragleave = function (e) {
+ sequence[sequence.length] = 'blue.'+e.type;
+ };
+ document.documentElement.ondragenter = document.documentElement.ondragleave = function (e) {
+ if( e.target != this ) { return; }
+ sequence[sequence.length] = 'html.'+e.type;
+ };
+ document.documentElement.ondragover = function (e) {
+ if( e.target != this ) { return; }
+ if( sequence[sequence.length-1] != 'html.dragover' ) {
+ sequence[sequence.length] = 'html.dragover';
+ }
+ };
+ document.ondragenter = document.ondragleave = document.ondragover = document.ondragleave = function (e) {
+ if( e.target != this ) { return; }
+ sequence[sequence.length] = 'document.'+e.type;
+ };
+ orange.ondragend = function (e) {
+ sequence = sequence.join('=>')
+ var desiredsequence = (['orange.dragenter','orange.dragover','html.dragenter','html.dragenter','orange.dragleave','html.dragover','blue.dragenter','html.dragover','orange.dragenter','html.dragleave','orange.dragover','orange.drop']).join('=>')
+ if( sequence == desiredsequence ) {
+ document.getElementsByTagName('div')[2].textContent = 'PASS';
+ } else {
+ document.getElementsByTagName('div')[2].textContent = 'FAIL, got: '+sequence+' instead of: '+desiredsequence;
+ }
+ };
+};
+ ]]></script>
+ </head>
+ <!--body-->
+
+ <div draggable="true"></div><div></div>
+ <div>&#160;</div>
+ <p>Drag the orange square onto the blue square, then back to the orange square, and release it.</p>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+
+ <!--/body-->
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/events/037-spec.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/events/037-spec.xhtml
new file mode 100644
index 00000000000..611891cb787
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/events/037-spec.xhtml
@@ -0,0 +1,88 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Drag and drop without cancelling dragenter and without body (spec compliant)</title>
+ <style type="text/css">
+head + div {
+ height: 100px;
+ width: 100px;
+ background: orange;
+ display: inline-block;
+}
+head + div + div {
+ height: 100px;
+ width: 100px;
+ margin-left: 100px;
+ background: blue;
+ display: inline-block;
+}
+ </style>
+ <script type="text/javascript"><![CDATA[
+//Drag passes from orange to root element. Dragenter fires at root element.
+//Dragenter is not cancelled. Body does not exist. Dragenter fires at document.
+//Spec says the body (which does not exist) becomes current target element => null.
+//Drag passes from root element to blue. Dragenter fires at blue.
+//Dragenter is not cancelled. Body does not exist. Current target element is null.
+//Dragenter fires at document. Current target is set to null again.
+//Drag passes from blue to root element. Dragenter fires at root element.
+//Dragenter is not cancelled. Body does not exist. Current target element is null.
+//Dragenter is not cancelled. Body does not exist. Dragenter fires at document.
+//Current target is set to null. Yet again.
+//Drag passes from root element to orange. Dragenter fires at orange, and is cancelled.
+window.onload = function () {
+ var orange = document.getElementsByTagName('div')[0], sequence = [];
+ orange.ondragstart = function (e) {
+ e.dataTransfer.setData('text','hello');
+ e.dataTransfer.effectAllowed = 'copy';
+ };
+ orange.ondragenter = orange.ondrop = function (e) {
+ sequence[sequence.length] = 'orange.'+e.type;
+ e.preventDefault();
+ };
+ orange.ondragleave = function (e) {
+ sequence[sequence.length] = 'orange.dragleave';
+ };
+ orange.ondragover = function (e) {
+ if( sequence[sequence.length-1] != 'orange.dragover' ) {
+ sequence[sequence.length] = 'orange.dragover';
+ }
+ e.preventDefault();
+ };
+ var blue = document.getElementsByTagName('div')[1];
+ blue.ondragenter = blue.ondragover = blue.ondragleave = function (e) {
+ sequence[sequence.length] = 'blue.'+e.type;
+ };
+ document.documentElement.ondragenter = document.documentElement.ondragleave = function (e) {
+ if( e.target != this ) { return; }
+ sequence[sequence.length] = 'html.'+e.type;
+ };
+ document.documentElement.ondragover = function (e) {
+ if( e.target != this ) { return; }
+ if( sequence[sequence.length-1] != 'html.dragover' ) {
+ sequence[sequence.length] = 'html.dragover';
+ }
+ };
+ document.ondragenter = document.ondragleave = document.ondragover = document.ondragleave = function (e) {
+ if( e.target != this ) { return; }
+ sequence[sequence.length] = 'document.'+e.type;
+ };
+ orange.ondragend = function (e) {
+ sequence = sequence.join('=>')
+ var desiredsequence = (['orange.dragenter','orange.dragover','html.dragenter','document.dragenter','orange.dragleave','blue.dragenter','document.dragenter','document.dragenter','orange.dragenter','orange.dragover','orange.drop']).join('=>')
+ if( sequence == desiredsequence ) {
+ document.getElementsByTagName('div')[2].textContent = 'PASS';
+ } else {
+ document.getElementsByTagName('div')[2].textContent = 'FAIL, got: '+sequence+' instead of: '+desiredsequence;
+ }
+ };
+};
+ ]]></script>
+ </head>
+ <!--body-->
+
+ <div draggable="true"></div><div></div>
+ <div>&#160;</div>
+ <p>Drag the orange square onto the blue square, then back to the orange square, and release it.</p>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+
+ <!--/body-->
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/events/038-proposed.html b/tests/wpt/web-platform-tests/html/editing/dnd/events/038-proposed.html
new file mode 100644
index 00000000000..85d987612f4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/events/038-proposed.html
@@ -0,0 +1,84 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Drag and drop without cancelling dragenter and without body or html</title>
+ <style type="text/css">
+body > div:first-child {
+ height: 100px;
+ width: 100px;
+ background: orange;
+ display: inline-block;
+}
+iframe {
+ height: 100px;
+ width: 100px;
+ margin-left: 100px;
+ display: inline-block;
+ border: none;
+}
+ </style>
+ <script type="text/javascript">
+//Drag passes from parent to blue. Dragenter fires at blue. Root element is deleted.
+//Dragenter is not cancelled. Body does not exist. Root element does not exist.
+//Current target element is set to null. Drag now points at unrendered document - null.
+//Current target element remains null.
+//Drag passes over parent to orange. Dragenter fires at orange, and is cancelled.
+window.onload = function () {
+ var orange = document.getElementsByTagName('div')[0], sequence = [];
+ orange.ondragstart = function (e) {
+ e.dataTransfer.setData('text','hello');
+ e.dataTransfer.effectAllowed = 'copy';
+ };
+ orange.ondragenter = orange.ondrop = function (e) {
+ sequence[sequence.length] = 'orange.'+e.type;
+ e.preventDefault();
+ };
+ orange.ondragleave = function (e) {
+ sequence[sequence.length] = 'orange.dragleave';
+ };
+ orange.ondragover = function (e) {
+ if( sequence[sequence.length-1] != 'orange.dragover' ) {
+ sequence[sequence.length] = 'orange.dragover';
+ }
+ e.preventDefault();
+ };
+ var blue = document.getElementsByTagName('iframe')[0].contentDocument;
+ if( !blue.documentElement ) { blue.appendChild(blue.createElement('html')); }
+ blue.documentElement.style.margin = '0';
+ blue.documentElement.style.padding = '0';
+ if( !blue.body ) { blue.documentElement.appendChild(blue.createElement('body')); }
+ blue.body.style.margin = '0';
+ blue.body.style.padding = '0';
+ var bluediv = blue.body.appendChild(blue.createElement('div'));
+ bluediv.style.height = '100px';
+ bluediv.style.width = '100px';
+ bluediv.style.background = 'blue';
+ bluediv.ondragenter = bluediv.ondragover = function (e) {
+ sequence[sequence.length] = 'blue.'+e.type;
+ if( blue.documentElement ) { blue.removeChild(blue.documentElement); }
+ };
+ blue.ondragenter = blue.ondragover = blue.ondragleave = function (e) {
+ if( e.target != this ) { return; }
+ sequence[sequence.length] = 'bluedocument.'+e.type;
+ };
+ orange.ondragend = function (e) {
+ sequence = sequence.join('=&gt;')
+ var desiredsequence = (['orange.dragenter','orange.dragover','orange.dragleave','blue.dragenter','orange.dragenter','orange.dragover','orange.drop']).join('=&gt;')
+ if( sequence == desiredsequence ) {
+ document.getElementsByTagName('div')[1].innerHTML = 'PASS';
+ } else {
+ document.getElementsByTagName('div')[1].innerHTML = 'FAIL, got:<br>'+sequence+'<br>instead of:<br>'+desiredsequence;
+ }
+ };
+};
+ </script>
+ </head>
+ <body>
+
+ <div draggable="true"></div><iframe src="about:blank"></iframe>
+ <div>&nbsp;</div>
+ <p>Drag the orange square onto the blue square, then back to the orange square, and release it.</p>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/events/events-cross-document-suite-HELPER-1.html b/tests/wpt/web-platform-tests/html/editing/dnd/events/events-cross-document-suite-HELPER-1.html
new file mode 100644
index 00000000000..1463066fea7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/events/events-cross-document-suite-HELPER-1.html
@@ -0,0 +1,206 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - event sequence for cross-document drag</title>
+<style type="text/css">
+ /* use margins instead of padding to make sure the body begins at the top of the page */
+ html, body {
+ margin: 0;
+ }
+ body {
+ padding: 116px 8px 8px;
+ }
+ #testhere div {
+ height: 100px;
+ width: 100px;
+ position: absolute;
+ top: 8px;
+ }
+ #orange {
+ background-color: orange;
+ left: 8px;
+ }
+ #fuchsia {
+ background-color: fuchsia;
+ left: 158px;
+ }
+</style>
+<link rel=stylesheet href=/resources/testharness.css>
+
+<script>
+parent.setup(function () {},{explicit_done:true,explicit_timeout:true});
+window.onload = function () {
+ var orange = document.querySelector('#orange')
+ var fuchsia = document.querySelector('#fuchsia')
+ var body = document.body;
+
+ orange.ondragstart = function (e) {
+ parent.events.push('doc1.orange.ondragstart');
+ e.dataTransfer.effectAllowed = 'all';
+ e.dataTransfer.setData('Text', 'foo');
+ };
+ orange.ondrag = function () { parent.events.push('doc1.orange.ondrag'); };
+ orange.ondragenter = function () { parent.events.push('doc1.orange.ondragenter'); };
+ orange.ondragover = function () { parent.events.push('doc1.orange.ondragover'); };
+ orange.ondrop = function () { parent.events.push('doc1.orange.ondrop'); return false; };
+ orange.ondragend = function () { parent.events.push('doc1.orange.ondragend'); setTimeout(finish,100); };
+ orange.onmousedown = function () { parent.events.push('doc1.orange.onmousedown'); };
+ orange.onmouseup = function () { parent.events.push('doc1.orange.onmouseup'); };
+
+ /* Events for the fuchsia box */
+ fuchsia.ondragstart = function () { parent.events.push('doc1.pink.ondragstart'); };
+ fuchsia.ondrag = function () { parent.events.push('doc1.pink.ondrag'); };
+ fuchsia.ondragenter = function () { parent.events.push('doc1.pink.ondragenter'); };
+ fuchsia.ondragover = function () { parent.events.push('doc1.pink.ondragover'); };
+ fuchsia.ondrop = function () { parent.events.push('doc1.pink.ondrop'); return false; };
+ fuchsia.ondragend = function () { parent.events.push('doc1.pink.ondragend'); };
+ fuchsia.onmousedown = function () { parent.events.push('doc1.pink.onmousedown'); };
+ fuchsia.onmouseup = function () { parent.events.push('doc1.pink.onmouseup'); };
+
+ /* Events for the page body */
+ body.ondragstart = function (e) { parent.events.push( ( e.target == body ) ? 'doc1.body.ondragstart': 'doc1.bubble.ondragstart' ); };
+ body.ondrag = function (e) { parent.events.push( ( e.target == body ) ? 'doc1.body.ondrag': 'doc1.bubble.ondrag' ); };
+ body.ondragenter = function (e) { parent.events.push( ( e.target == body ) ? 'doc1.body.ondragenter': 'doc1.bubble.ondragenter' ); };
+ body.ondragover = function (e) { parent.events.push( ( e.target == body ) ? 'doc1.body.ondragover': 'doc1.bubble.ondragover' ); };
+ body.ondrop = function (e) { parent.events.push( ( e.target == body ) ? 'doc1.body.ondrop': 'doc1.bubble.ondrop' ); };
+ body.ondragend = function (e) { parent.events.push( ( e.target == body ) ? 'doc1.body.ondragend': 'doc1.bubble.ondragend' ); };
+ body.onmousedown = function (e) { parent.events.push( ( e.target == body ) ? 'doc1.body.onmousedown': 'doc1.bubble.onmousedown' ); };
+ body.onmouseup = function (e) { parent.events.push( ( e.target == body ) ? 'doc1.body.onmouseup': 'doc1.bubble.onmouseup' ); };
+
+ function finish(e) {
+ var i, evindex;
+ var events = parent.events.join('-');
+ /*
+ Normalise; reduce repeating event sequences to only 2 occurrences.
+ This makes the final event sequence predictable, no matter how many times the drag->dragover sequences repeat.
+ Two occurrances are kept in each case to allow testing to make sure the sequence really is repeating.
+ */
+ //spec compliant - div dragenter is not cancelled, so body dragenter fires and body becomes current target
+ //repeats while drag is over orange or fuchsia or the body
+ events = events.replace(/(-doc1\.orange\.ondrag-doc1\.bubble\.ondrag-doc1\.body\.ondragover){3,}/g,'$1$1');
+ events = events.replace(/(-doc1\.orange\.ondrag-doc1\.bubble\.ondrag-doc2\.body\.ondragover){3,}/g,'$1$1');
+ //repeats while dragging over yellow
+ events = events.replace(/(-doc1\.orange\.ondrag-doc1\.bubble\.ondrag-doc2\.yellow\.ondragover-doc2\.bubble\.ondragover){3,}/g,'$1$1');
+ //repeats while dragging over blue
+ events = events.replace(/(-doc1\.orange\.ondrag-doc1\.bubble\.ondrag-doc2\.blue\.ondragover-doc2\.bubble\.ondragover){3,}/g,'$1$1');
+ //non-spec-compliant repeats while dragging over orange
+ events = events.replace(/(-doc1\.orange\.ondrag-doc1\.bubble\.ondrag-doc1\.orange\.ondragover-doc1\.bubble\.ondragover){3,}/g,'$1$1');
+ //non-spec-compliant repeats while dragging over fuchsia
+ events = events.replace(/(-doc1\.orange\.ondrag-doc1\.bubble\.ondrag-doc1\.pink\.ondragover-doc1\.bubble\.ondragover){3,}/g,'$1$1');
+ events = events.split(/-/g);
+
+ parent.test(function () {
+ parent.assert_array_equals(events,
+
+ ['doc1.orange.onmousedown', //mouse down
+ 'doc1.bubble.onmousedown',
+
+ 'doc1.orange.ondragstart', //dragging begins
+ 'doc1.bubble.ondragstart',
+
+ 'doc1.orange.ondrag', //mouse is over orange
+ 'doc1.bubble.ondrag',
+ 'doc1.orange.ondragenter', //not cancelled
+ 'doc1.bubble.ondragenter',
+ 'doc1.body.ondragenter', //so body becomes current target, and the event fires there as well
+ 'doc1.body.ondragover',
+
+ 'doc1.orange.ondrag', //start repeating (some over orange, some over body)
+ 'doc1.bubble.ondrag',
+ 'doc1.body.ondragover',
+ 'doc1.orange.ondrag', //...twice to make sure it actually repeats
+ 'doc1.bubble.ondrag',
+ 'doc1.body.ondragover', //end repeating
+
+ 'doc1.orange.ondrag', //mouse moves over pink
+ 'doc1.bubble.ondrag',
+ 'doc1.pink.ondragenter', //not cancelled
+ 'doc1.bubble.ondragenter',
+ 'doc1.body.ondragover', //so body becomes current target, but since it was already the target, dragenter does not need to fire again
+
+ 'doc1.orange.ondrag', //start repeating (some over pink, some over body)
+ 'doc1.bubble.ondrag',
+ 'doc1.body.ondragover',
+ 'doc1.orange.ondrag', //...twice to make sure it actually repeats
+ 'doc1.bubble.ondrag',
+ 'doc1.body.ondragover', //end repeating
+
+ 'doc1.orange.ondrag', //mouse moves over second frame
+ 'doc1.bubble.ondrag',
+ 'doc2.body.ondragenter', //not cancelled
+ 'doc2.body.ondragenter', //so it fires again and sets body as current target
+ 'doc2.body.ondragover',
+
+ 'doc1.orange.ondrag', //start repeating (over second body)
+ 'doc1.bubble.ondrag',
+ 'doc2.body.ondragover',
+ 'doc1.orange.ondrag', //...twice to make sure it actually repeats
+ 'doc1.bubble.ondrag',
+ 'doc2.body.ondragover', //end repeating
+
+ 'doc1.orange.ondrag', //mouse moves over yellow
+ 'doc1.bubble.ondrag',
+ 'doc2.yellow.ondragenter',
+ 'doc2.bubble.ondragenter',
+ 'doc2.yellow.ondragover',
+ 'doc2.bubble.ondragover',
+
+ 'doc1.orange.ondrag', //start repeating (over yellow)
+ 'doc1.bubble.ondrag',
+ 'doc2.yellow.ondragover',
+ 'doc2.bubble.ondragover',
+ 'doc1.orange.ondrag', //...twice to make sure it actually repeats
+ 'doc1.bubble.ondrag',
+ 'doc2.yellow.ondragover',
+ 'doc2.bubble.ondragover', //end repeating
+
+ 'doc1.orange.ondrag', //mouse moves over body
+ 'doc1.bubble.ondrag',
+ 'doc2.body.ondragenter', //not cancelled
+ 'doc2.body.ondragenter', //so it fires again and sets body as current target
+ 'doc2.body.ondragover',
+
+ 'doc1.orange.ondrag', //start repeating (over body)
+ 'doc1.bubble.ondrag',
+ 'doc2.body.ondragover',
+ 'doc1.orange.ondrag', //...twice to make sure it actually repeats
+ 'doc1.bubble.ondrag',
+ 'doc2.body.ondragover', //end repeating
+
+ 'doc1.orange.ondrag', //mouse moves over blue
+ 'doc1.bubble.ondrag',
+ 'doc2.blue.ondragenter',
+ 'doc2.bubble.ondragenter',
+ 'doc2.blue.ondragover',
+ 'doc2.bubble.ondragover',
+
+ 'doc1.orange.ondrag', //start repeating (over blue)
+ 'doc1.bubble.ondrag',
+ 'doc2.blue.ondragover',
+ 'doc2.bubble.ondragover',
+ 'doc1.orange.ondrag', //...twice to make sure it actually repeats
+ 'doc1.bubble.ondrag',
+ 'doc2.blue.ondragover',
+ 'doc2.bubble.ondragover', //end repeating
+
+ 'doc2.blue.ondrop', //release
+ 'doc2.bubble.ondrop',
+ 'doc1.orange.ondragend',
+ 'doc1.bubble.ondragend']
+
+ );
+ }, 'Overall sequence');
+ var div = parent.document.createElement("div");
+ div.setAttribute("id", "log");
+ parent.document.documentElement.appendChild(div);
+ parent.done();
+ document.body.appendChild(parent.document.querySelector("div"));
+ }
+};
+</script>
+
+<div id="testhere">
+<div draggable='true' id='orange'></div>
+<div id='fuchsia'></div>
+</div>
+
+<p>If you have already clicked on this page, reload it.</p>
+<p>Use your pointing device to slowly drag the orange square over the pink square, then the grey square, then the yellow square, then the blue square, and release it over the blue square (make sure the mouse remains over each square for at least 1 second, and over the gaps between squares for at least 1 second). Fail if no new text appears below.</p>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/events/events-cross-document-suite-HELPER-2.html b/tests/wpt/web-platform-tests/html/editing/dnd/events/events-cross-document-suite-HELPER-2.html
new file mode 100644
index 00000000000..ba5a250099d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/events/events-cross-document-suite-HELPER-2.html
@@ -0,0 +1,77 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - event sequence for cross-document drag</title>
+<style type="text/css">
+ /* use margins instead of padding to make sure the body begins at the top of the page */
+ html, body {
+ margin: 0;
+ padding: 0;
+ height: 100%;
+ }
+ #testhere div {
+ height: 100px;
+ width: 100px;
+ position: absolute;
+ top: 8px;
+ }
+ body::before {
+ height: 100px;
+ width: 100px;
+ position: absolute;
+ top: 8px;
+ left: 0px;
+ content: "";
+ background-color: silver;
+ }
+ #yellow {
+ background-color: yellow;
+ left: 150px;
+ }
+ #blue {
+ background-color: navy;
+ left: 300px;
+ }
+</style>
+
+<script>
+window.onload = function () {
+ var yellow = document.querySelector('#yellow')
+ var blue = document.querySelector('#blue')
+ var body = document.body;
+
+ /* Events for the fuchsia box */
+ yellow.ondragstart = function () { parent.events.push('doc2.yellow.ondragstart'); };
+ yellow.ondrag = function () { parent.events.push('doc2.yellow.ondrag'); };
+ yellow.ondragenter = function () { parent.events.push('doc2.yellow.ondragenter'); return false; };
+ yellow.ondragover = function () { parent.events.push('doc2.yellow.ondragover'); return false; };
+ yellow.ondrop = function () { parent.events.push('doc2.yellow.ondrop'); return false; };
+ yellow.ondragend = function () { parent.events.push('doc2.yellow.ondragend'); };
+ yellow.onmousedown = function () { parent.events.push('doc2.yellow.onmousedown'); };
+ yellow.onmouseup = function () { parent.events.push('doc2.yellow.onmouseup'); };
+
+ /* Events for the blue box (droppable) */
+ blue.ondragstart = function () { parent.events.push('doc2.blue.ondragstart'); };
+ blue.ondrag = function () { parent.events.push('doc2.blue.ondrag'); };
+ blue.ondragenter = function () { parent.events.push('doc2.blue.ondragenter'); return false; };
+ blue.ondragover = function () { parent.events.push('doc2.blue.ondragover'); return false; };
+ blue.ondrop = function () { parent.events.push('doc2.blue.ondrop'); return false; };
+ blue.ondragend = function () { parent.events.push('doc2.blue.ondragend'); };
+ blue.onmousedown = function () { parent.events.push('doc2.blue.onmousedown'); };
+ blue.onmouseup = function () { parent.events.push('doc2.blue.onmouseup'); };
+
+ /* Events for the page body */
+ body.ondragstart = function (e) { parent.events.push( ( e.target == body ) ? 'doc2.body.ondragstart': 'doc2.bubble.ondragstart' ); };
+ body.ondrag = function (e) { parent.events.push( ( e.target == body ) ? 'doc2.body.ondrag': 'doc2.bubble.ondrag' ); };
+ body.ondragenter = function (e) { parent.events.push( ( e.target == body ) ? 'doc2.body.ondragenter': 'doc2.bubble.ondragenter' ); };
+ body.ondragover = function (e) { parent.events.push( ( e.target == body ) ? 'doc2.body.ondragover': 'doc2.bubble.ondragover' ); };
+ body.ondrop = function (e) { parent.events.push( ( e.target == body ) ? 'doc2.body.ondrop': 'doc2.bubble.ondrop' ); };
+ body.ondragend = function (e) { parent.events.push( ( e.target == body ) ? 'doc2.body.ondragend': 'doc2.bubble.ondragend' ); };
+ body.onmousedown = function (e) { parent.events.push( ( e.target == body ) ? 'doc2.body.onmousedown': 'doc2.bubble.onmousedown' ); };
+ body.onmouseup = function (e) { parent.events.push( ( e.target == body ) ? 'doc2.body.onmouseup': 'doc2.bubble.onmouseup' ); };
+
+};
+</script>
+
+<div id="testhere">
+<div id='yellow'></div>
+<div id='blue'></div>
+</div>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/events/events-cross-document-suite-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/events/events-cross-document-suite-manual.html
new file mode 100644
index 00000000000..689c7523720
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/events/events-cross-document-suite-manual.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - event sequence for cross-document drag</title>
+<script type="text/javascript" src="/resources/testharness.js"></script>
+<script>
+var events = new Array();
+</script>
+
+<frameset cols="308,*" frameborder="no" border="0">
+ <frame src="events-cross-document-suite-HELPER-1.html">
+ <frame src="events-cross-document-suite-HELPER-2.html">
+</frameset>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/events/events-file-suite-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/events/events-file-suite-manual.html
new file mode 100644
index 00000000000..7f78749cf2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/events/events-file-suite-manual.html
@@ -0,0 +1,175 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - event sequence for file drops</title>
+<script type="text/javascript" src="/resources/testharness.js"></script>
+<style type="text/css">
+ /* use margins instead of padding to make sure the body begins at the top of the page */
+ html, body {
+ margin: 0;
+ }
+ body {
+ padding: 116px 8px 8px;
+ }
+ body::before {
+ height: 108px;
+ width: 108px;
+ position: absolute;
+ top: 0px;
+ left: 0px;
+ content: "";
+ background-color: orange;
+ }
+ #testhere div {
+ height: 100px;
+ width: 100px;
+ position: absolute;
+ top: 8px;
+ }
+ #fuchsia {
+ background-color: fuchsia;
+ left: 158px;
+ }
+ #yellow {
+ background-color: yellow;
+ left: 308px;
+ }
+ #blue {
+ background-color: navy;
+ left: 458px;
+ }
+</style>
+
+<script>
+setup(function () {},{explicit_done:true,explicit_timeout:true});
+window.onload = function () {
+ var fuchsia = document.querySelector('#fuchsia')
+ var yellow = document.querySelector('#yellow')
+ var blue = document.querySelector('#blue')
+ var body = document.body;
+
+ var events = new Array
+
+ /* Events for the fuchsia box */
+ fuchsia.ondragstart = function () { events.push('pink.ondragstart'); };
+ fuchsia.ondrag = function () { events.push('pink.ondrag'); };
+ fuchsia.ondragenter = function () { events.push('pink.ondragenter'); };
+ fuchsia.ondragover = function () { events.push('pink.ondragover'); };
+ fuchsia.ondragleave = function () { events.push('pink.ondragleave'); };
+ fuchsia.ondrop = function () { events.push('pink.ondrop'); return false; };
+ fuchsia.ondragend = function () { events.push('pink.ondragend'); };
+ fuchsia.onmousedown = function () { events.push('pink.onmousedown'); };
+ fuchsia.onmouseup = function () { events.push('pink.onmouseup'); };
+
+ /* Events for the fuchsia box */
+ yellow.ondragstart = function () { events.push('yellow.ondragstart'); };
+ yellow.ondrag = function () { events.push('yellow.ondrag'); };
+ yellow.ondragenter = function () { events.push('yellow.ondragenter'); return false; };
+ yellow.ondragover = function () { events.push('yellow.ondragover'); return false; };
+ yellow.ondragleave = function () { events.push('yellow.ondragleave'); };
+ yellow.ondrop = function () { events.push('yellow.ondrop'); return false; };
+ yellow.ondragend = function () { events.push('yellow.ondragend'); };
+ yellow.onmousedown = function () { events.push('yellow.onmousedown'); };
+ yellow.onmouseup = function () { events.push('yellow.onmouseup'); };
+
+ /* Events for the blue box (droppable) */
+ blue.ondragstart = function () { events.push('blue.ondragstart'); };
+ blue.ondrag = function () { events.push('blue.ondrag'); };
+ blue.ondragenter = function () { events.push('blue.ondragenter'); return false; };
+ blue.ondragover = function () { events.push('blue.ondragover'); return false; };
+ blue.ondragleave = function () { events.push('blue.ondragleave'); };
+ blue.ondrop = function () { events.push('blue.ondrop'); return false; };
+ blue.ondragend = function () { events.push('blue.ondragend'); };
+ blue.onmousedown = function () { events.push('blue.onmousedown'); };
+ blue.onmouseup = function () { events.push('blue.onmouseup'); };
+
+ /* Events for the page body */
+ body.ondragstart = function (e) { events.push( ( e.target == body ) ? 'body.ondragstart': 'bubble.ondragstart' ); };
+ body.ondrag = function (e) { events.push( ( e.target == body ) ? 'body.ondrag': 'bubble.ondrag' ); };
+ body.ondragenter = function (e) { events.push( ( e.target == body ) ? 'body.ondragenter': 'bubble.ondragenter' ); };
+ body.ondragover = function (e) { events.push( ( e.target == body ) ? 'body.ondragover': 'bubble.ondragover' ); };
+ body.ondragleave = function (e) { events.push( ( e.target == body ) ? 'body.ondragleave': 'bubble.ondragleave' ); };
+ body.ondrop = function (e) { events.push( ( e.target == body ) ? 'body.ondrop': 'bubble.ondrop' ); setTimeout(finish,200); };
+ body.ondragend = function (e) { events.push( ( e.target == body ) ? 'body.ondragend': 'bubble.ondragend' ); };
+ body.onmousedown = function (e) { events.push( ( e.target == body ) ? 'body.onmousedown': 'bubble.onmousedown' ); };
+ body.onmouseup = function (e) { events.push( ( e.target == body ) ? 'body.onmouseup': 'bubble.onmouseup' ); };
+
+ function finish(e) {
+ var i, evindex;
+ events = events.join('-');
+ /*
+ Normalise; reduce repeating event sequences to only 2 occurrences.
+ This makes the final event sequence predictable, no matter how many times the drag->dragover sequences repeat.
+ Two occurrances are kept in each case to allow testing to make sure the sequence really is repeating.
+ */
+ //spec compliant - div dragenter is not cancelled, so body dragenter fires and body becomes current target
+ //repeats while drag is over fuchsia or the body
+ events = events.replace(/(-body\.ondragover){3,}/g,'$1$1');
+ //repeats while dragging over yellow
+ events = events.replace(/(-yellow\.ondragover-bubble\.ondragover){3,}/g,'$1$1');
+ //repeats while dragging over blue
+ events = events.replace(/(-blue\.ondragover-bubble\.ondragover){3,}/g,'$1$1');
+ //non-spec-compliant repeats while dragging over fuchsia
+ events = events.replace(/(-pink\.ondragover-bubble\.ondragover){3,}/g,'$1$1');
+ events = events.split(/-/g);
+
+ test(function () {
+ assert_array_equals(events,
+
+ [/* 1 */ 'body.ondragenter', //mouse moves over body, which does not cancel event
+ /* 2 */ 'body.ondragenter', //so it fires again and sets body as current target
+
+ /* 3 */ 'body.ondragover', //start repeating over body
+ /* 4 */ 'body.ondragover', //...twice to make sure it actually repeats
+
+ /* 5 */ 'pink.ondragenter', //mouse moves over pink - not cancelled
+ /* 6 */ 'bubble.ondragenter',
+
+ /* 7 */ 'body.ondragover', //so body becomes current target, but since it was already the target, dragenter does not need to fire again
+ /* 8 */ 'body.ondragover', //...twice to make sure it actually repeats
+
+ /* 9 */ 'yellow.ondragenter', //mouse moves over yellow
+ /* 10 */ 'bubble.ondragenter',
+ /* 11 */ 'body.ondragleave',
+
+ /* 12 */ 'yellow.ondragover', //start repeating (over yellow)
+ /* 13 */ 'bubble.ondragover',
+ /* 14 */ 'yellow.ondragover', //...twice to make sure it actually repeats
+ /* 15 */ 'bubble.ondragover', //end repeating
+
+ /* 16 */ 'body.ondragenter', //mouse moves over body, not cancelled
+ /* 17 */ 'body.ondragenter', //so it fires again and sets body as current target
+ /* 18 */ 'yellow.ondragleave',
+ /* 19 */ 'bubble.ondragleave',
+
+ /* 20 */ 'body.ondragover', //start repeating (over body)
+ /* 21 */ 'body.ondragover', //...twice to make sure it actually repeats
+
+ /* 22 */ 'blue.ondragenter', //mouse moves over blue
+ /* 23 */ 'bubble.ondragenter',
+ /* 24 */ 'body.ondragleave',
+
+ /* 25 */ 'blue.ondragover', //start repeating (over blue)
+ /* 26 */ 'bubble.ondragover',
+ /* 27 */ 'blue.ondragover', //...twice to make sure it actually repeats
+ /* 28 */ 'bubble.ondragover',
+
+ /* 29 */ 'blue.ondrop', //release
+ /* 30 */ 'bubble.ondrop']
+
+ );
+ }, 'Overall sequence');
+
+ done();
+ }
+};
+</script>
+
+<div id="testhere">
+<div id='fuchsia'></div>
+<div id='yellow'></div>
+<div id='blue'></div>
+</div>
+
+<p>If you have already clicked on this page, reload it.</p>
+<p>Use your pointing device to slowly drag a file from your system's file manager, over the orange square (ensure that this is the first part of the page that you drag the file over, not an otherwise blank part of the page), then the pink square, then the yellow square, then the blue square, and release it over the blue square (make sure the mouse remains over each square for at least 1 second, and over the gaps between squares for at least 1 second). If a prompt appears, accept it. Fail if no new text appears below.</p>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/events/events-non-draggable-001.html b/tests/wpt/web-platform-tests/html/editing/dnd/events/events-non-draggable-001.html
new file mode 100644
index 00000000000..0315ccdc86a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/events/events-non-draggable-001.html
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<meta charset='utf-8'>
+<title>drag &amp; drop – events should not fire with non-draggable elements – 001</title>
+<style type="text/css">
+ div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ position: absolute;
+ top: 8px;
+ left: 8px;
+ }
+ div + p {
+ margin-top: 220px;
+ }
+</style>
+
+<script>
+window.onload = function() {
+
+ var elem = document.getElementsByTagName('div')[0];
+ var pass = true;
+
+ function fail() {
+ pass = false;
+ }
+
+ elem.addEventListener('drag',fail,false);
+ elem.addEventListener('dragend',fail,false);
+ elem.addEventListener('dragenter',fail,false);
+ elem.addEventListener('dragleave',fail,false);
+ elem.addEventListener('dragover',fail,false);
+ elem.addEventListener('dragstart',fail,false);
+ elem.addEventListener('drop',fail,false);
+
+ elem.ondrag = fail;
+ elem.ondragend = fail;
+ elem.ondragenter = fail;
+ elem.ondragleave = fail;
+ elem.ondragover = fail;
+ elem.ondragstart = fail;
+ elem.ondrop = fail;
+
+ elem.onmouseup = function () {
+ setTimeout(function () {
+ if (pass == true) {
+ document.body.innerHTML = 'PASS';
+ } else {
+ document.body.innerHTML = 'FAIL';
+ }
+ }, 100 );
+ };
+
+}
+</script>
+
+<div></div>
+
+<p>Click once on the orange box above, without moving the mouse while
+clicking. The word &quot;PASS&quot; should appear.</p>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/events/events-non-draggable-002.html b/tests/wpt/web-platform-tests/html/editing/dnd/events/events-non-draggable-002.html
new file mode 100644
index 00000000000..c890cb482ea
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/events/events-non-draggable-002.html
@@ -0,0 +1,101 @@
+<!DOCTYPE html>
+<meta charset='utf-8'>
+<title>drag &amp; drop – events should not fire with non-draggable elements – 002</title>
+<style type="text/css">
+ div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ position: absolute;
+ top: 8px;
+ left: 8px;
+ }
+ div + div {
+ background-color: navy;
+ left: 250px;
+ }
+
+ div + p {
+ margin-top: 220px;
+ }
+</style>
+
+<script>
+window.onload = function() {
+
+ var orange = document.getElementsByTagName('div')[0];
+ var blue = document.getElementsByTagName('div')[1];
+ var body = document.body;
+
+ var pass = true;
+
+ function fail() {
+ pass = false;
+ }
+
+ body.addEventListener('drag',fail,false);
+ body.addEventListener('dragend',fail,false);
+ body.addEventListener('dragenter',fail,false);
+ body.addEventListener('dragleave',fail,false);
+ body.addEventListener('dragover',fail,false);
+ body.addEventListener('dragstart',fail,false);
+ body.addEventListener('drop',fail,false);
+
+ body.ondrag = fail;
+ body.ondragend = fail;
+ body.ondragenter = fail;
+ body.ondragleave = fail;
+ body.ondragover = fail;
+ body.ondragstart = fail;
+ body.ondrop = fail;
+
+ orange.addEventListener('drag',fail,false);
+ orange.addEventListener('dragend',fail,false);
+ orange.addEventListener('dragenter',fail,false);
+ orange.addEventListener('dragleave',fail,false);
+ orange.addEventListener('dragover',fail,false);
+ orange.addEventListener('dragstart',fail,false);
+ orange.addEventListener('drop',fail,false);
+
+ orange.ondrag = fail;
+ orange.ondragend = fail;
+ orange.ondragenter = fail;
+ orange.ondragleave = fail;
+ orange.ondragover = fail;
+ orange.ondragstart = fail;
+ orange.ondrop = fail;
+
+ blue.addEventListener('drag',fail,false);
+ blue.addEventListener('dragend',fail,false);
+ blue.addEventListener('dragenter',fail,false);
+ blue.addEventListener('dragleave',fail,false);
+ blue.addEventListener('dragover',fail,false);
+ blue.addEventListener('dragstart',fail,false);
+ blue.addEventListener('drop',fail,false);
+
+ blue.ondrag = fail;
+ blue.ondragend = fail;
+ blue.ondragenter = fail;
+ blue.ondragleave = fail;
+ blue.ondragover = fail;
+ blue.ondragstart = fail;
+ blue.ondrop = fail;
+
+ body.onmouseup = function () {
+ setTimeout(function () {
+ if (pass == true) {
+ document.body.innerHTML = 'PASS';
+ } else {
+ document.body.innerHTML = 'FAIL';
+ }
+ }, 100 );
+ };
+
+}
+</script>
+
+<div></div>
+<div></div>
+
+<p>Use your pointing device to drag from the orange box to the blue box. The
+word &quot;PASS&quot; should appear.
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/events/events-suite-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/events/events-suite-manual.html
new file mode 100644
index 00000000000..a29ea56a6c6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/events/events-suite-manual.html
@@ -0,0 +1,370 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - event sequence for draggable elements</title>
+<script type="text/javascript" src="/resources/testharness.js"></script>
+<style type="text/css">
+ /* use margins instead of padding to make sure the body begins at the top of the page */
+ html, body {
+ margin: 0;
+ }
+ body {
+ padding: 116px 8px 8px;
+ }
+ #testhere div {
+ height: 100px;
+ width: 100px;
+ position: absolute;
+ top: 8px;
+ }
+ #orange {
+ background-color: orange;
+ left: 8px;
+ }
+ #fuchsia {
+ background-color: fuchsia;
+ left: 158px;
+ }
+ #yellow {
+ background-color: yellow;
+ left: 308px;
+ }
+ #blue {
+ background-color: navy;
+ left: 458px;
+ }
+</style>
+
+<script>
+setup(function () {},{explicit_done:true,explicit_timeout:true});
+window.onload = function () {
+ var orange = document.querySelector('#orange')
+ var fuchsia = document.querySelector('#fuchsia')
+ var yellow = document.querySelector('#yellow')
+ var blue = document.querySelector('#blue')
+ var body = document.body;
+
+ var events = new Array
+
+ orange.ondragstart = function (e) {
+ events.push('orange.ondragstart');
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('Text', 'foo');
+ };
+ orange.ondrag = function () { events.push('orange.ondrag'); };
+ orange.ondragenter = function () { events.push('orange.ondragenter'); };
+ orange.ondragover = function () { events.push('orange.ondragover'); };
+ orange.ondragleave = function () { events.push('orange.ondragleave'); };
+ orange.ondrop = function () { events.push('orange.ondrop'); return false; };
+ orange.ondragend = function () { events.push('orange.ondragend'); };
+ orange.onmousedown = function () { events.push('orange.onmousedown'); };
+ orange.onmouseup = function () { events.push('orange.onmouseup'); };
+
+ /* Events for the fuchsia box */
+ fuchsia.ondragstart = function () { events.push('pink.ondragstart'); };
+ fuchsia.ondrag = function () { events.push('pink.ondrag'); };
+ fuchsia.ondragenter = function () { events.push('pink.ondragenter'); };
+ fuchsia.ondragover = function () { events.push('pink.ondragover'); };
+ fuchsia.ondragleave = function () { events.push('pink.ondragleave'); };
+ fuchsia.ondrop = function () { events.push('pink.ondrop'); return false; };
+ fuchsia.ondragend = function () { events.push('pink.ondragend'); };
+ fuchsia.onmousedown = function () { events.push('pink.onmousedown'); };
+ fuchsia.onmouseup = function () { events.push('pink.onmouseup'); };
+
+ /* Events for the fuchsia box */
+ yellow.ondragstart = function () { events.push('yellow.ondragstart'); };
+ yellow.ondrag = function () { events.push('yellow.ondrag'); };
+ yellow.ondragenter = function () { events.push('yellow.ondragenter'); return false; };
+ yellow.ondragover = function () { events.push('yellow.ondragover'); return false; };
+ yellow.ondragleave = function () { events.push('yellow.ondragleave'); };
+ yellow.ondrop = function () { events.push('yellow.ondrop'); return false; };
+ yellow.ondragend = function () { events.push('yellow.ondragend'); };
+ yellow.onmousedown = function () { events.push('yellow.onmousedown'); };
+ yellow.onmouseup = function () { events.push('yellow.onmouseup'); };
+
+ /* Events for the blue box (droppable) */
+ blue.ondragstart = function () { events.push('blue.ondragstart'); };
+ blue.ondrag = function () { events.push('blue.ondrag'); };
+ blue.ondragenter = function () { events.push('blue.ondragenter'); return false; };
+ blue.ondragover = function () { events.push('blue.ondragover'); return false; };
+ blue.ondragleave = function () { events.push('blue.ondragleave'); };
+ blue.ondrop = function () { events.push('blue.ondrop'); return false; };
+ blue.ondragend = function () { events.push('blue.ondragend'); };
+ blue.onmousedown = function () { events.push('blue.onmousedown'); };
+ blue.onmouseup = function () { events.push('blue.onmouseup'); };
+
+ /* Events for the page body */
+ body.ondragstart = function (e) { events.push( ( e.target == body ) ? 'body.ondragstart': 'bubble.ondragstart' ); };
+ body.ondrag = function (e) { events.push( ( e.target == body ) ? 'body.ondrag': 'bubble.ondrag' ); };
+ body.ondragenter = function (e) { events.push( ( e.target == body ) ? 'body.ondragenter': 'bubble.ondragenter' ); };
+ body.ondragover = function (e) { events.push( ( e.target == body ) ? 'body.ondragover': 'bubble.ondragover' ); };
+ body.ondragleave = function (e) { events.push( ( e.target == body ) ? 'body.ondragleave': 'bubble.ondragleave' ); };
+ body.ondrop = function (e) { events.push( ( e.target == body ) ? 'body.ondrop': 'bubble.ondrop' ); };
+ body.ondragend = function (e) { events.push( ( e.target == body ) ? 'body.ondragend': 'bubble.ondragend' ); setTimeout(finish,100); };
+ body.onmousedown = function (e) { events.push( ( e.target == body ) ? 'body.onmousedown': 'bubble.onmousedown' ); };
+ body.onmouseup = function (e) { events.push( ( e.target == body ) ? 'body.onmouseup': 'bubble.onmouseup' ); };
+
+ function finish(e) {
+ var i, evindex;
+ events = events.join('-');
+ /*
+ Normalise; reduce repeating event sequences to only 2 occurrences.
+ This makes the final event sequence predictable, no matter how many times the drag->dragover sequences repeat.
+ Two occurrances are kept in each case to allow testing to make sure the sequence really is repeating.
+ */
+ //spec compliant - div dragenter is not cancelled, so body dragenter fires and body becomes current target
+ //repeats while drag is over orange or fuchsia or the body
+ events = events.replace(/(-orange\.ondrag-bubble\.ondrag-body\.ondragover){3,}/g,'$1$1');
+ //repeats while dragging over yellow
+ events = events.replace(/(-orange\.ondrag-bubble\.ondrag-yellow\.ondragover-bubble\.ondragover){3,}/g,'$1$1');
+ //repeats while dragging over blue
+ events = events.replace(/(-orange\.ondrag-bubble\.ondrag-blue\.ondragover-bubble\.ondragover){3,}/g,'$1$1');
+ //non-spec-compliant repeats while dragging over orange
+ events = events.replace(/(-orange\.ondrag-bubble\.ondrag-orange\.ondragover-bubble\.ondragover){3,}/g,'$1$1');
+ //non-spec-compliant repeats while dragging over fuchsia
+ events = events.replace(/(-orange\.ondrag-bubble\.ondrag-pink\.ondragover-bubble\.ondragover){3,}/g,'$1$1');
+ events = events.split(/-/g);
+
+ test(function () {
+ assert_array_equals(events,
+
+ [/* 1 */ 'orange.onmousedown', //mouse down
+ /* 2 */ 'bubble.onmousedown',
+
+ /* 3 */ 'orange.ondragstart', //dragging begins
+ /* 4 */ 'bubble.ondragstart',
+
+ /* 5 */ 'orange.ondrag', //mouse is over orange
+ /* 6 */ 'bubble.ondrag',
+ /* 7 */ 'orange.ondragenter', //not cancelled
+ /* 8 */ 'bubble.ondragenter',
+ /* 9 */ 'body.ondragenter', //so body becomes current target, and the event fires there as well
+ /* 10 */ 'body.ondragover',
+
+ /* 11 */ 'orange.ondrag', //start repeating (some over orange, some over body)
+ /* 12 */ 'bubble.ondrag',
+ /* 13 */ 'body.ondragover',
+ /* 14 */ 'orange.ondrag', //...twice to make sure it actually repeats
+ /* 15 */ 'bubble.ondrag',
+ /* 16 */ 'body.ondragover', //end repeating
+
+ /* 17 */ 'orange.ondrag', //mouse moves over pink
+ /* 18 */ 'bubble.ondrag',
+ /* 19 */ 'pink.ondragenter', //not cancelled
+ /* 20 */ 'bubble.ondragenter',
+ /* 21 */ 'body.ondragover', //so body becomes current target, but since it was already the target, dragenter does not need to fire again
+
+ /* 22 */ 'orange.ondrag', //start repeating (some over pink, some over body)
+ /* 23 */ 'bubble.ondrag',
+ /* 24 */ 'body.ondragover',
+ /* 25 */ 'orange.ondrag', //...twice to make sure it actually repeats
+ /* 26 */ 'bubble.ondrag',
+ /* 27 */ 'body.ondragover', //end repeating
+
+ /* 28 */ 'orange.ondrag', //mouse moves over yellow
+ /* 29 */ 'bubble.ondrag',
+ /* 30 */ 'yellow.ondragenter',
+ /* 31 */ 'bubble.ondragenter',
+ /* 32 */ 'body.ondragleave',
+ /* 33 */ 'yellow.ondragover',
+ /* 34 */ 'bubble.ondragover',
+
+ /* 35 */ 'orange.ondrag', //start repeating (over yellow)
+ /* 36 */ 'bubble.ondrag',
+ /* 37 */ 'yellow.ondragover',
+ /* 38 */ 'bubble.ondragover',
+ /* 39 */ 'orange.ondrag', //...twice to make sure it actually repeats
+ /* 40 */ 'bubble.ondrag',
+ /* 41 */ 'yellow.ondragover',
+ /* 42 */ 'bubble.ondragover', //end repeating
+
+ /* 43 */ 'orange.ondrag', //mouse moves over body
+ /* 44 */ 'bubble.ondrag',
+ /* 45 */ 'body.ondragenter', //not cancelled
+ /* 46 */ 'body.ondragenter', //so it fires again and sets body as current target
+ /* 47 */ 'yellow.ondragleave',
+ /* 48 */ 'bubble.ondragleave',
+ /* 49 */ 'body.ondragover',
+
+ /* 50 */ 'orange.ondrag', //start repeating (over body)
+ /* 51 */ 'bubble.ondrag',
+ /* 52 */ 'body.ondragover',
+ /* 53 */ 'orange.ondrag', //...twice to make sure it actually repeats
+ /* 54 */ 'bubble.ondrag',
+ /* 55 */ 'body.ondragover', //end repeating
+
+ /* 56 */ 'orange.ondrag', //mouse moves over blue
+ /* 57 */ 'bubble.ondrag',
+ /* 58 */ 'blue.ondragenter',
+ /* 59 */ 'bubble.ondragenter',
+ /* 60 */ 'body.ondragleave',
+ /* 61 */ 'blue.ondragover',
+ /* 62 */ 'bubble.ondragover',
+
+ /* 63 */ 'orange.ondrag', //start repeating (over blue)
+ /* 64 */ 'bubble.ondrag',
+ /* 65 */ 'blue.ondragover',
+ /* 66 */ 'bubble.ondragover',
+ /* 67 */ 'orange.ondrag', //...twice to make sure it actually repeats
+ /* 68 */ 'bubble.ondrag',
+ /* 69 */ 'blue.ondragover',
+ /* 70 */ 'bubble.ondragover', //end repeating
+
+ /* 71 */ 'blue.ondrop', //release
+ /* 72 */ 'bubble.ondrop',
+ /* 73 */ 'orange.ondragend',
+ /* 74 */ 'bubble.ondragend']
+
+ );
+ }, 'Overall sequence');
+
+ /* ondragstart */
+ test(function () { assert_true( events.indexOf('orange.ondragstart') != -1 ); }, "orange.ondragstart should fire");
+ test(function () { assert_equals( events.filter(function (e) { if (e == 'orange.ondragstart') return e; }).length, 1); }, "orange.ondragstart should fire 1 time");
+ test(function () { assert_equals( events[2], 'orange.ondragstart' ); }, "orange.ondragstart should be event handler #3");
+ test(function () { assert_equals( events.indexOf('pink.ondragstart'), -1 ); }, "pink.ondragstart should not fire");
+ test(function () { assert_equals( events.indexOf('yellow.ondragstart'), -1 ); }, "yellow.ondragstart should not fire");
+ test(function () { assert_equals( events.indexOf('blue.ondragstart'), -1 ); }, "blue.ondragstart should not fire");
+ test(function () { assert_equals( events.indexOf('body.ondragstart'), -1 ); }, "ondragstart should not fire at the body");
+ test(function () { assert_true( events.indexOf('bubble.ondragstart') != -1 ); }, "ondragstart should bubble to body");
+ test(function () { assert_equals( events.filter(function (e) { if (e == 'bubble.ondragstart') return e; }).length, 1); }, "ondragstart should only bubble to body 1 time");
+ test(function () { assert_equals( events[3], 'bubble.ondragstart' ); }, "ondragstart should bubble to body as event handler #4");
+
+ /* ondrag */
+ test(function () { assert_true( events.indexOf('orange.ondrag') != -1 ); }, "orange.ondrag should fire");
+ test(function () { assert_equals( events.filter(function (e) { if (e == 'orange.ondrag') return e; }).length, 15); }, "orange.ondrag should fire 15 times");
+ for( var i = 0, evindex = [4,10,13,16,21,24,27,34,38,42,49,52,55,62,66]; i < evindex.length; i++ ) {
+ test(function () { assert_equals( events[evindex[i]], 'orange.ondrag' ); }, "orange.ondrag should be event handler #"+(evindex[i]+1));
+ }
+ test(function () { assert_equals( events.indexOf('pink.ondrag'), -1 ); }, "pink.ondrag should not fire");
+ test(function () { assert_equals( events.indexOf('yellow.ondrag'), -1 ); }, "yellow.ondrag should not fire");
+ test(function () { assert_equals( events.indexOf('blue.ondrag'), -1 ); }, "blue.ondrag should not fire");
+ test(function () { assert_equals( events.indexOf('body.ondrag'), -1 ); }, "ondrag should not fire at the body");
+ test(function () { assert_true( events.indexOf('bubble.ondrag') != -1 ); }, "ondrag should bubble to body");
+ test(function () { assert_equals( events.filter(function (e) { if (e == 'bubble.ondrag') return e; }).length, 15); }, "ondrag should bubble to body 15 times");
+ for( var i = 0, evindex = [5,11,14,17,22,25,28,35,39,43,50,53,56,63,67]; i < evindex.length; i++ ) {
+ test(function () { assert_equals( events[evindex[i]], 'bubble.ondrag' ); }, "ondrag should bubble to body as event handler #"+(evindex[i]+1));
+ }
+
+ /* ondragenter */
+ test(function () { assert_true( events.indexOf('orange.ondragenter') != -1 ); }, "orange.ondragenter should fire");
+ test(function () { assert_equals( events.filter(function (e) { if (e == 'orange.ondragenter') return e; }).length, 1); }, "orange.ondragenter should fire 1 time");
+ test(function () { assert_equals( events[6], 'orange.ondragenter' ); }, "orange.ondragenter should be event handler #7");
+ test(function () { assert_true( events.indexOf('pink.ondragenter') != -1 ); }, "pink.ondragenter should fire");
+ test(function () { assert_equals( events.filter(function (e) { if (e == 'pink.ondragenter') return e; }).length, 1); }, "pink.ondragenter should fire 1 time");
+ test(function () { assert_equals( events[18], 'pink.ondragenter' ); }, "pink.ondragenter should be event handler #19");
+ test(function () { assert_true( events.indexOf('yellow.ondragenter') != -1 ); }, "yellow.ondragenter should fire");
+ test(function () { assert_equals( events.filter(function (e) { if (e == 'yellow.ondragenter') return e; }).length, 1); }, "yellow.ondragenter should fire 1 time");
+ test(function () { assert_equals( events[29], 'yellow.ondragenter' ); }, "yellow.ondragenter should be event handler #30");
+ test(function () { assert_true( events.indexOf('blue.ondragenter') != -1 ); }, "blue.ondragenter should fire");
+ test(function () { assert_equals( events.filter(function (e) { if (e == 'blue.ondragenter') return e; }).length, 1); }, "blue.ondragenter should fire 1 time");
+ test(function () { assert_equals( events[57], 'blue.ondragenter' ); }, "blue.ondragenter should be event handler #58");
+ test(function () { assert_true( events.indexOf('body.ondragenter') != -1 ); }, "ondragenter should fire at body");
+ test(function () { assert_equals( events.filter(function (e) { if (e == 'body.ondragenter') return e; }).length, 3); }, "ondragenter should fire at body 2 times");
+ for( var i = 0, evindex = [8,44,45]; i < evindex.length; i++ ) {
+ test(function () { assert_equals( events[evindex[i]], 'body.ondragenter' ); }, "ondragenter should fire at body as event handler #"+(evindex[i]+1));
+ }
+ test(function () { assert_true( events.indexOf('bubble.ondragenter') != -1 ); }, "ondragenter should bubble to body");
+ test(function () { assert_equals( events.filter(function (e) { if (e == 'bubble.ondragenter') return e; }).length, 4); }, "ondragenter should bubble to body 4 times");
+ for( var i = 0, evindex = [7,19,30,58]; i < evindex.length; i++ ) {
+ test(function () { assert_equals( events[evindex[i]], 'bubble.ondragenter' ); }, "ondragenter should bubble to body as event handler #"+(evindex[i]+1));
+ }
+
+ /* ondragover */
+ test(function () { assert_equals( events.indexOf('orange.ondragover'), -1 ); }, "orange.ondragover should not fire");
+ test(function () { assert_equals( events.indexOf('pink.ondragover'), -1 ); }, "pink.ondragover should not fire");
+ test(function () { assert_true( events.indexOf('yellow.ondragover') != -1 ); }, "yellow.ondragover should fire");
+ test(function () { assert_equals( events.filter(function (e) { if (e == 'yellow.ondragover') return e; }).length, 3); }, "yellow.ondragover should fire 3 times");
+ for( var i = 0, evindex = [32,36,40]; i < evindex.length; i++ ) {
+ test(function () { assert_equals( events[evindex[i]], 'yellow.ondragover' ); }, "yellow.ondragover should be event handler #"+(evindex[i]+1));
+ }
+ test(function () { assert_true( events.indexOf('blue.ondragover') != -1 ); }, "blue.ondragover should fire");
+ test(function () { assert_equals( events.filter(function (e) { if (e == 'blue.ondragover') return e; }).length, 3); }, "blue.ondragover should fire 9 times");
+ for( var i = 0, evindex = [60,64,68]; i < evindex.length; i++ ) {
+ test(function () { assert_equals( events[evindex[i]], 'blue.ondragover' ); }, "blue.ondragover should be event handler #"+(evindex[i]+1));
+ }
+ test(function () { assert_true( events.indexOf('body.ondragover') != -1 ); }, "ondragover should fire at body");
+ test(function () { assert_equals( events.filter(function (e) { if (e == 'body.ondragover') return e; }).length, 9); }, "ondragover should fire at body 2 times");
+ for( var i = 0, evindex = [9,12,15,20,23,26,48,51,54]; i < evindex.length; i++ ) {
+ test(function () { assert_equals( events[evindex[i]], 'body.ondragover' ); }, "ondragover should fire at body as event handler #"+(evindex[i]+1));
+ }
+ test(function () { assert_true( events.indexOf('bubble.ondragover') != -1 ); }, "ondragover should bubble to body");
+ test(function () { assert_equals( events.filter(function (e) { if (e == 'bubble.ondragover') return e; }).length, 6); }, "ondragover should bubble to body 6 times");
+ for( var i = 0, evindex = [33,37,41,61,65,69]; i < evindex.length; i++ ) {
+ test(function () { assert_equals( events[evindex[i]], 'bubble.ondragover' ); }, "ondragover should bubble to body as event handler #"+(evindex[i]+1));
+ }
+
+ /* ondragleave */
+ test(function () { assert_equals( events.indexOf('orange.ondragleave'), -1 ); }, "orange.ondragleave should not fire");
+ test(function () { assert_equals( events.indexOf('pink.ondragleave'), -1 ); }, "pink.ondragleave should not fire");
+ test(function () { assert_true( events.indexOf('yellow.ondragleave') != -1 ); }, "yellow.ondragleave should fire");
+ test(function () { assert_equals( events.filter(function (e) { if (e == 'yellow.ondragleave') return e; }).length, 1); }, "yellow.ondragleave should fire 1 time");
+ test(function () { assert_equals( events[46], 'yellow.ondragleave' ); }, "yellow.ondragleave should be event handler #47");
+ test(function () { assert_equals( events.indexOf('blue.ondragleave'), -1 ); }, "blue.ondragleave should not fire");
+ test(function () { assert_true( events.indexOf('body.ondragleave') != -1 ); }, "ondragleave should fire at body");
+ test(function () { assert_equals( events.filter(function (e) { if (e == 'body.ondragleave') return e; }).length, 2); }, "ondragleave should fire at body 2 times");
+ for( var i = 0, evindex = [31,59]; i < evindex.length; i++ ) {
+ test(function () { assert_equals( events[evindex[i]], 'body.ondragleave' ); }, "ondragleave should fire at body as event handler #"+(evindex[i]+1));
+ }
+ test(function () { assert_true( events.indexOf('bubble.ondragleave') != -1 ); }, "ondragleave should bubble to body");
+ test(function () { assert_equals( events.filter(function (e) { if (e == 'bubble.ondragleave') return e; }).length, 1); }, "ondragleave should bubble to body 1 time");
+ test(function () { assert_equals( events[47], 'bubble.ondragleave' ); }, "ondragleave should bubble to body as event handler #48");
+
+ /* ondrop */
+ test(function () { assert_equals( events.indexOf('orange.ondrop'), -1 ); }, "orange.ondrop should not fire");
+ test(function () { assert_equals( events.indexOf('pink.ondrop'), -1 ); }, "pink.ondrop should not fire");
+ test(function () { assert_equals( events.indexOf('yellow.ondrop'), -1 ); }, "yellow.ondrop should not fire");
+ test(function () { assert_true( events.indexOf('blue.ondrop') != -1 ); }, "blue.ondrop should fire");
+ test(function () { assert_equals( events.filter(function (e) { if (e == 'blue.ondrop') return e; }).length, 1); }, "blue.ondrop should fire 1 time");
+ test(function () { assert_equals( events[70], 'blue.ondrop' ); }, "blue.ondrop should be event handler #71");
+ test(function () { assert_equals( events.indexOf('body.ondrop'), -1 ); }, "ondrop should not fire at body");
+ test(function () { assert_true( events.indexOf('bubble.ondrop') != -1 ); }, "ondrop should bubble to body");
+ test(function () { assert_equals( events.filter(function (e) { if (e == 'bubble.ondrop') return e; }).length, 1); }, "ondrop should bubble to body 1 time");
+ test(function () { assert_equals( events[71], 'bubble.ondrop' ); }, "ondrop should bubble to body as event handler #72");
+
+ /* ondragend */
+ test(function () { assert_true( events.indexOf('orange.ondragend') != -1 ); }, "orange.ondragend should fire");
+ test(function () { assert_equals( events.filter(function (e) { if (e == 'orange.ondragend') return e; }).length, 1); }, "orange.ondragend should fire 1 time");
+ test(function () { assert_equals( events[72], 'orange.ondragend' ); }, "orange.ondragend should be event handler #73");
+ test(function () { assert_equals( events.indexOf('pink.ondragend'), -1 ); }, "pink.ondragend should not fire");
+ test(function () { assert_equals( events.indexOf('yellow.ondragend'), -1 ); }, "yellow.ondragend should not fire");
+ test(function () { assert_equals( events.indexOf('blue.ondragend'), -1 ); }, "blue.ondragend should not fire");
+ test(function () { assert_equals( events.indexOf('body.ondragend'), -1 ); }, "ondragend should not fire at body");
+ test(function () { assert_true( events.indexOf('bubble.ondragend') != -1 ); }, "ondragend should bubble to body");
+ test(function () { assert_equals( events.filter(function (e) { if (e == 'bubble.ondragend') return e; }).length, 1); }, "ondragend should bubble to body 1 time");
+ test(function () { assert_equals( events[73], 'bubble.ondragend' ); }, "ondragend should bubble to body as event handler #74");
+
+ /* onmousedown */
+ test(function () { assert_true( events.indexOf('orange.onmousedown') != -1 ); }, "orange.onmousedown should fire");
+ test(function () { assert_equals( events.filter(function (e) { if (e == 'orange.onmousedown') return e; }).length, 1); }, "orange.onmousedown should fire 1 time");
+ test(function () { assert_equals( events[0], 'orange.onmousedown' ); }, "orange.onmousedown should be event handler #1");
+ test(function () { assert_equals( events.indexOf('pink.onmousedown'), -1 ); }, "pink.onmousedown should not fire");
+ test(function () { assert_equals( events.indexOf('yellow.onmousedown'), -1 ); }, "yellow.onmousedown should not fire");
+ test(function () { assert_equals( events.indexOf('blue.onmousedown'), -1 ); }, "blue.onmousedown should not fire");
+ test(function () { assert_equals( events.indexOf('body.onmousedown'), -1 ); }, "onmousedown should not fire at body");
+ test(function () { assert_true( events.indexOf('bubble.onmousedown') != -1 ); }, "onmousedown should bubble to body");
+ test(function () { assert_equals( events.filter(function (e) { if (e == 'bubble.onmousedown') return e; }).length, 1); }, "onmousedown should bubble to body 1 time");
+ test(function () { assert_equals( events[1], 'bubble.onmousedown' ); }, "onmousedown should bubble to body as event handler #1");
+
+ /* onmouseup */
+ test(function () { assert_equals( events.indexOf('orange.onmouseup'), -1 ); }, "orange.onmouseup should not fire");
+ test(function () { assert_equals( events.indexOf('pink.onmouseup'), -1 ); }, "pink.onmouseup should not fire");
+ test(function () { assert_equals( events.indexOf('yellow.onmouseup'), -1 ); }, "yellow.onmouseup should not fire");
+ test(function () { assert_equals( events.indexOf('blue.onmouseup'), -1 ); }, "blue.onmouseup should not fire");
+ test(function () { assert_equals( events.indexOf('body.onmouseup'), -1 ); }, "onmouseup should not fire at body");
+ test(function () { assert_equals( events.indexOf('bubble.onmouseup'), -1 ); }, "onmouseup should not bubble to body");
+
+ done();
+ }
+};
+</script>
+
+<div id="testhere">
+<div draggable='true' id='orange'></div>
+<div id='fuchsia'></div>
+<div id='yellow'></div>
+<div id='blue'></div>
+</div>
+
+<p>If you have already clicked on this page, reload it.</p>
+<p>Use your pointing device to slowly drag the orange square over the pink square then the yellow square, then the blue square, and release it over the blue square (make sure the mouse remains over each square for at least 1 second, and over the gaps between squares for at least 1 second). Fail if no new text appears below.</p>
+
+<div id="log"></div>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/events/helper-drag-me-input-with-circle.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/events/helper-drag-me-input-with-circle.xhtml
new file mode 100644
index 00000000000..77e6a1301b8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/events/helper-drag-me-input-with-circle.xhtml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Cross frame drag and drop: helper file</title>
+<style type="text/css">
+div
+ {width:0;
+ height:0;
+ border:solid 50px silver;
+ border-radius:50px;
+ margin-left:auto;}
+</style>
+<script type="application/ecmascript">
+var step = 1;
+function start(event)
+ {if(step++ == 1)
+ {setColor('green silver silver silver');}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragstart should be first event to fire.')}
+ }
+function leavePage(event)
+ {if(step++ > 1)
+ {setColor('green green silver silver')}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragleave should fire after dragstart.')}
+ }
+function endDrag(event)
+ {if(step++ > 2)
+ {setColor('green')}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragend should fire after dragstart and dragleave.')}
+ }
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'))}
+function setColor(c)
+ {document.querySelector('div').setAttribute('style','border-color:' + c)}
+</script>
+</head>
+<body onload="document.querySelector('input').select()" ondragleave="leavePage(event)">
+<p ondragstart="start(event)" ondragend="endDrag(event)"><input value="Drag me"/></p>
+<p>Drag selected text out of frame and drop it somewhere on the page. Both circles should turn green once text is dropped.</p>
+<div/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/events/helper-drag-me-link-with-circle.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/events/helper-drag-me-link-with-circle.xhtml
new file mode 100644
index 00000000000..813a06a7dfa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/events/helper-drag-me-link-with-circle.xhtml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Cross frame drag and drop: helper file</title>
+<style type="text/css">
+div
+ {width:0;
+ height:0;
+ border:solid 50px silver;
+ border-radius:50px;
+ margin-left:auto;}
+</style>
+<script type="application/ecmascript">
+var step = 1;
+function start(event)
+ {if(step++ == 1)
+ {setColor('green silver silver silver');}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragstart should be first event to fire.')}
+ }
+function leavePage(event)
+ {if(step++ > 1)
+ {setColor('green green silver silver')}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragleave should fire after dragstart.')}
+ }
+function endDrag(event)
+ {if(step++ > 2)
+ {setColor('green')}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragend should fire after dragstart and dragleave.')}
+ }
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'))}
+function setColor(c)
+ {document.querySelector('div').setAttribute('style','border-color:' + c)}
+</script>
+</head>
+<body ondragleave="leavePage(event)">
+<p><a href="data:text/plain,1" ondragstart="start(event)" ondragend="endDrag(event)">Drag me</a></p>
+<p>Drag link out of frame and drop it somewhere on the page. Both circles should turn green once link is dropped.</p>
+<div/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/events/helper-drag-me-p-with-circle.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/events/helper-drag-me-p-with-circle.xhtml
new file mode 100644
index 00000000000..bd27af79a60
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/events/helper-drag-me-p-with-circle.xhtml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Cross frame drag and drop: helper file</title>
+<style type="text/css">
+div
+ {width:0;
+ height:0;
+ border:solid 50px silver;
+ border-radius:50px;
+ margin-left:auto;}
+</style>
+<script type="application/ecmascript">
+var step = 1;
+function start(event)
+ {if(step++ == 1)
+ {setColor('green silver silver silver');}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragstart should be first event to fire.')}
+ }
+function leavePage(event)
+ {if(step++ > 1)
+ {setColor('green green silver silver')}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragleave should fire after dragstart.')}
+ }
+function endDrag(event)
+ {if(step++ > 2)
+ {setColor('green')}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragend should fire after dragstart and dragleave.')}
+ }
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'))}
+function setColor(c)
+ {document.querySelector('div').setAttribute('style','border-color:' + c)}
+</script>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('p'))" ondragleave="leavePage(event)">
+<p ondragstart="start(event)" ondragend="endDrag(event)">Drag me</p>
+<p>Drag selected text out of frame and drop it somewhere on the page. Both circles should turn green once text is dropped.</p>
+<div/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/events/helper-drop-here-body-circle.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/events/helper-drop-here-body-circle.xhtml
new file mode 100644
index 00000000000..10f66d764f1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/events/helper-drop-here-body-circle.xhtml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Cross frame drag and drop: helper file</title>
+<style type="text/css">
+div
+ {width:0;
+ height:0;
+ border:solid 50px silver;
+ border-radius:50px;
+ margin-left:auto;}
+</style>
+<script type="application/ecmascript">
+var step = 1;
+function enterPage(event)
+ {event.preventDefault();
+ if(step++ > 0)
+ {setColor('green silver silver silver');}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragenter should fire before dragover and drop');}
+ }
+function overPage(event)
+ {event.preventDefault();
+ if(step++ > 1)
+ {setColor('green green silver silver');}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragover should fire after dragenter');}
+ }
+function dropIt(event)
+ {if(step++ > 1)
+ {setColor('green');}
+ else
+ {step = 0;
+ setColor('maroon');
+ say('Dragover should fire after dragenter');}
+ }
+function say(it)
+ {document.querySelector('pre').appendChild(document.createTextNode(it + '\n'))}
+function setColor(c)
+ {document.querySelector('div').setAttribute('style','border-color:' + c)}
+</script>
+</head>
+<body ondragenter="enterPage(event)" ondragover="overPage(event)" ondrop="dropIt(event)">
+<div/>
+<pre/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/file/001.html b/tests/wpt/web-platform-tests/html/editing/dnd/file/001.html
new file mode 100644
index 00000000000..45a44c394cd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/file/001.html
@@ -0,0 +1,103 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - simple file drop</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ }
+</style>
+
+<script>
+var filename = 'fail.png', filesize = '759', filetype = 'image/png';
+var fails = [], finished = false;
+window.onload = function() {
+ var orange = document.getElementsByTagName('div')[0];
+ orange.ondragover = orange.ondragenter = function(e) {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'copy';
+ if( !e.dataTransfer.files ) {
+ fails[fails.length] = 'No dataTransfer.files for '+e.type;
+ }
+ if( !window.FileList ) {
+ fails[fails.length] = 'No FileList interface object';
+ return;
+ }
+ if( !( e.dataTransfer.files instanceof FileList ) ) {
+ fails[fails.length] = 'dataTransfer.files is not a FileList';
+ }
+ if( e.dataTransfer.files.length ) {
+ fails[fails.length] = 'dataTransfer.files.length is '+e.dataTransfer.files.length+' instead of 0 for '+e.type;
+ }
+ };
+ orange.ondrop = function(e) {
+ e.preventDefault();
+ if( !e.dataTransfer.files ) {
+ fails[fails.length] = 'No dataTransfer.files for '+e.type;
+ }
+ if( !window.FileList ) {
+ fails[fails.length] = 'No FileList interface object';
+ finish();
+ return;
+ }
+ if( !( e.dataTransfer.files instanceof FileList ) ) {
+ fails[fails.length] = 'dataTransfer.files is not a FileList';
+ }
+ if( e.dataTransfer.files.length != 1 ) {
+ fails[fails.length] = 'dataTransfer.files.length is '+e.dataTransfer.files.length+' instead of 1 for '+e.type;
+ }
+ if( !e.dataTransfer.files[0] ) {
+ fails[fails.length] = 'no dataTransfer.files[0] for drop';
+ finish();
+ return;
+ }
+ if( e.dataTransfer.files[0].size != filesize ) {
+ fails[fails.length] = 'dataTransfer.files[0].size '+e.dataTransfer.files[0].size+' instead of '+filesize;
+ }
+ /*
+ if( !e.dataTransfer.files[0].lastModifiedDate ) {
+ fails[fails.length] = 'no dataTransfer.files[0].lastModifiedDate';
+ }
+ */
+ if( e.dataTransfer.files[0].name != filename ) {
+ fails[fails.length] = 'dataTransfer.files[0].name '+e.dataTransfer.files[0].name+' instead of '+filename;
+ }
+ if( e.dataTransfer.files[0].type != filetype ) {
+ fails[fails.length] = 'dataTransfer.files[0].type '+e.dataTransfer.files[0].type+' instead of '+filetype;
+ }
+ if( !window.FileReader ) {
+ fails[fails.length] = 'No FileReader constructor';
+ finish();
+ return;
+ }
+ var reader = new FileReader();
+ reader.onload = function () {
+ if( !reader.result ) {
+ fails[fails.length] = 'No file data after load';
+ }
+ if( reader.result.length != filesize ) {
+ fails[fails.length] = 'File data length '+reader.result.length+' instead of '+filesize;
+ }
+ finish();
+ };
+ reader.readAsBinaryString(e.dataTransfer.files[0]);
+ setTimeout(function () {
+ if( !reader.result ) {
+ fails[fails.length] = 'No file data after timeout';
+ }
+ finish();
+ },1000);
+ };
+
+};
+function finish() {
+ if( finished ) { return; }
+ finished = true;
+ document.getElementsByTagName('p')[0].innerHTML = fails.length ? ( 'FAIL: ' + fails.join('<br>') ) : 'PASS';
+}
+</script>
+
+<div></div>
+
+<p>Save <a href="../resources/fail.png">this image</a> to your desktop. Use your pointing device to drag the saved file from your desktop onto the orange box, and release it. If a confirmation dialog appears, accept it. Fail if nothing happens, or if the browser simply displays the image.</p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/file/002.html b/tests/wpt/web-platform-tests/html/editing/dnd/file/002.html
new file mode 100644
index 00000000000..a60b2b201ce
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/file/002.html
@@ -0,0 +1,146 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - multiple file drop</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ }
+</style>
+
+<script>
+var filename1 = 'fail.png', filesize1 = '759', filetype1 = 'image/png', filename2 = 'fail.txt', filesize2 = '4', filetype2 = 'text/plain';
+var fails = [], finished = false, donecount = 0;
+window.onload = function() {
+ var orange = document.getElementsByTagName('div')[0];
+ orange.ondragover = orange.ondragenter = function(e) {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'copy';
+ if( !e.dataTransfer.files ) {
+ fails[fails.length] = 'No dataTransfer.files for '+e.type;
+ }
+ if( !window.FileList ) {
+ fails[fails.length] = 'No FileList interface object';
+ return;
+ }
+ if( !( e.dataTransfer.files instanceof FileList ) ) {
+ fails[fails.length] = 'dataTransfer.files is not a FileList';
+ }
+ if( e.dataTransfer.files.length ) {
+ fails[fails.length] = 'dataTransfer.files.length is '+e.dataTransfer.files.length+' instead of 0 for '+e.type;
+ }
+ };
+ orange.ondrop = function(e) {
+ e.preventDefault();
+ if( !e.dataTransfer.files ) {
+ fails[fails.length] = 'No dataTransfer.files for '+e.type;
+ }
+ if( !window.FileList ) {
+ fails[fails.length] = 'No FileList interface object';
+ finish();
+ return;
+ }
+ if( !( e.dataTransfer.files instanceof FileList ) ) {
+ fails[fails.length] = 'dataTransfer.files is not a FileList';
+ }
+ if( e.dataTransfer.files.length != 2 ) {
+ fails[fails.length] = 'dataTransfer.files.length is '+e.dataTransfer.files.length+' instead of 2 for '+e.type;
+ }
+ if( !e.dataTransfer.files[0] ) {
+ fails[fails.length] = 'no dataTransfer.files[0] for drop';
+ finish();
+ return;
+ }
+ if( !e.dataTransfer.files[1] ) {
+ fails[fails.length] = 'no dataTransfer.files[1] for drop';
+ finish();
+ return;
+ }
+ //allow files to be dropped in any order, since this will be determined by the OS
+ var i0 = 0, i1 = 1;
+ if( e.dataTransfer.files[0].name == filename2 ) {
+ i0 = 1;
+ i1 = 0;
+ }
+ if( e.dataTransfer.files[i0].size != filesize1 ) {
+ fails[fails.length] = 'dataTransfer.files['+i0+'].size '+e.dataTransfer.files[i0].size+' instead of '+filesize1;
+ }
+ /*
+ if( !e.dataTransfer.files[i0].lastModifiedDate ) {
+ fails[fails.length] = 'no dataTransfer.files['+i0+'].lastModifiedDate';
+ }
+ */
+ if( e.dataTransfer.files[i0].name != filename1 ) {
+ fails[fails.length] = 'dataTransfer.files['+i0+'].name '+e.dataTransfer.files[i0].name+' instead of '+filename1;
+ }
+ if( e.dataTransfer.files[i0].type != filetype1 ) {
+ fails[fails.length] = 'dataTransfer.files['+i0+'].type '+e.dataTransfer.files[i0].type+' instead of '+filetype1;
+ }
+ if( e.dataTransfer.files[i1].size != filesize2 ) {
+ fails[fails.length] = 'dataTransfer.files['+i1+'].size '+e.dataTransfer.files[i1].size+' instead of '+filesize2;
+ }
+ /*
+ if( !e.dataTransfer.files[i1].lastModifiedDate ) {
+ fails[fails.length] = 'no dataTransfer.files['+i1+'].lastModifiedDate';
+ }
+ */
+ if( e.dataTransfer.files[i1].name != filename2 ) {
+ fails[fails.length] = 'dataTransfer.files['+i1+'].name '+e.dataTransfer.files[i1].name+' instead of '+filename2;
+ }
+ if( e.dataTransfer.files[i1].type != filetype2 ) {
+ fails[fails.length] = 'dataTransfer.files['+i1+'].type '+e.dataTransfer.files[i1].type+' instead of '+filetype2;
+ }
+ if( !window.FileReader ) {
+ fails[fails.length] = 'No FileReader constructor';
+ finish();
+ return;
+ }
+ var reader1 = new FileReader();
+ reader1.readAsBinaryString(e.dataTransfer.files[i0]);
+ reader1.onload = function () {
+ if( !reader1.result ) {
+ fails[fails.length] = 'No files['+i0+'] data after load';
+ }
+ if( reader1.result.length != filesize1 ) {
+ fails[fails.length] = 'files['+i0+'] file data length '+reader1.result.length+' instead of '+filesize1;
+ }
+ if( donecount++ ) {
+ finish();
+ }
+ };
+ var reader2 = new FileReader();
+ reader2.onload = function () {
+ if( !reader2.result ) {
+ fails[fails.length] = 'No files['+i1+'] data after load';
+ }
+ if( reader2.result.length != filesize2 ) {
+ fails[fails.length] = 'files['+i1+'] file data length '+reader2.result.length+' instead of '+filesize2;
+ }
+ if( donecount++ ) {
+ finish();
+ }
+ };
+ reader2.readAsBinaryString(e.dataTransfer.files[i1]);
+ setTimeout(function () {
+ if( !reader1.result ) {
+ fails[fails.length] = 'No files['+i0+'] data after timeout';
+ }
+ if( !reader2.result ) {
+ fails[fails.length] = 'No files['+i1+'] data after timeout';
+ }
+ finish();
+ },1000);
+ };
+
+};
+function finish() {
+ if( finished ) { return; }
+ finished = true;
+ document.getElementsByTagName('p')[0].innerHTML = fails.length ? ( 'FAIL: ' + fails.join('<br>') ) : 'PASS';
+}
+</script>
+
+<div></div>
+
+<p>Save <a href="../resources/fail.png">this image</a> and <a href="fail.txt">this text file</a> to your desktop. Use your pointing device to drag both saved files (at the same time) from your desktop onto the orange box, and release them. If a confirmation dialog appears, accept it. Fail if nothing happens, or if the browser simply displays one/both of the files.</p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/file/003.html b/tests/wpt/web-platform-tests/html/editing/dnd/file/003.html
new file mode 100644
index 00000000000..86a3e7fced8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/file/003.html
@@ -0,0 +1,90 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - prompting before exposing files</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ }
+</style>
+
+<script>
+var filename = 'fail.png', filesize = '759', filetype = 'image/png';
+var fails = [], finished = false;
+window.onload = function() {
+ var orange = document.getElementsByTagName('div')[0];
+ orange.ondragover = orange.ondragenter = function(e) {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'copy';
+ };
+ orange.ondrop = function(e) {
+ e.preventDefault();
+ if( !e.dataTransfer.files ) {
+ fails[fails.length] = 'No dataTransfer.files for '+e.type;
+ }
+ if( !window.FileList ) {
+ fails[fails.length] = 'No FileList interface object';
+ finish();
+ return;
+ }
+ if( !( e.dataTransfer.files instanceof FileList ) ) {
+ fails[fails.length] = 'dataTransfer.files is not a FileList';
+ }
+ if( e.dataTransfer.files.length != 1 ) {
+ fails[fails.length] = 'dataTransfer.files.length is '+e.dataTransfer.files.length+' instead of 1 for '+e.type;
+ }
+ if( !e.dataTransfer.files[0] ) {
+ fails[fails.length] = 'no dataTransfer.files[0] for drop';
+ finish();
+ return;
+ }
+ if( e.dataTransfer.files[0].size != filesize ) {
+ fails[fails.length] = 'dataTransfer.files[0].size '+e.dataTransfer.files[0].size+' instead of '+filesize;
+ }
+ /*
+ if( !e.dataTransfer.files[0].lastModifiedDate ) {
+ fails[fails.length] = 'no dataTransfer.files[0].lastModifiedDate';
+ }
+ */
+ if( e.dataTransfer.files[0].name != filename ) {
+ fails[fails.length] = 'dataTransfer.files[0].name '+e.dataTransfer.files[0].name+' instead of '+filename;
+ }
+ if( e.dataTransfer.files[0].type != filetype ) {
+ fails[fails.length] = 'dataTransfer.files[0].type '+e.dataTransfer.files[0].type+' instead of '+filetype;
+ }
+ if( !window.FileReader ) {
+ fails[fails.length] = 'No FileReader constructor';
+ finish();
+ return;
+ }
+ var reader = new FileReader();
+ reader.onload = function () {
+ if( !reader.result ) {
+ fails[fails.length] = 'No file data after load';
+ }
+ if( reader.result.length != filesize ) {
+ fails[fails.length] = 'File data length '+reader.result.length+' instead of '+filesize;
+ }
+ finish();
+ };
+ reader.readAsBinaryString(e.dataTransfer.files[0]);
+ setTimeout(function () {
+ if( !reader.result ) {
+ fails[fails.length] = 'No file data after timeout';
+ }
+ finish();
+ },1000);
+ };
+
+};
+function finish() {
+ if( finished ) { return; }
+ finished = true;
+ document.getElementsByTagName('p')[0].innerHTML = fails.length ? ( 'FAIL: ' + fails.join('<br>') ) : 'PASS';
+}
+</script>
+
+<div></div>
+
+<p>Save <a href="../resources/fail.png">this image</a> to your desktop. Use your pointing device to drag the saved file from your desktop onto the orange box, and release it. <strong>A confirmation dialog must appear, allowing you to choose to cancel the upload</strong>. Accept it. Fail if nothing happens, or if the browser simply displays the image, or if &quot;PASS&quot; appears as the page text <strong>before</strong> you have accepted the upload.</p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/file/004.html b/tests/wpt/web-platform-tests/html/editing/dnd/file/004.html
new file mode 100644
index 00000000000..ea2d3575968
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/file/004.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - cancelling the dropped file upload</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ }
+</style>
+
+<script>
+var fails = [];
+window.onload = function() {
+ var orange = document.getElementsByTagName('div')[0];
+ orange.ondragover = orange.ondragenter = function(e) {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'copy';
+ };
+ orange.ondrop = function(e) {
+ //if the browser simulates a drop, it must do so with an empty FileList
+ e.preventDefault();
+ if( !e.dataTransfer.files ) {
+ fails[fails.length] = 'No dataTransfer.files for '+e.type;
+ }
+ if( !window.FileList ) {
+ fails[fails.length] = 'No FileList interface object';
+ finish();
+ return;
+ }
+ if( !( e.dataTransfer.files instanceof FileList ) ) {
+ fails[fails.length] = 'dataTransfer.files is not a FileList';
+ }
+ if( e.dataTransfer.files.length ) {
+ fails[fails.length] = 'dataTransfer.files.length is '+e.dataTransfer.files.length+' instead of 0 for '+e.type;
+ }
+ if( e.dataTransfer.files[0] ) {
+ fails[fails.length] = 'dataTransfer.files[0] exists for drop';
+ finish();
+ }
+ };
+
+};
+function finish() {
+ document.getElementsByTagName('p')[0].innerHTML = fails.length ? ( 'FAIL: ' + fails.join('<br>') ) : 'PASS';
+}
+</script>
+
+<div></div>
+
+<p>Save <a href="../resources/pass.png">this image</a> to your desktop. Use your pointing device to drag the saved file from your desktop onto the orange box, and release it. <strong>A confirmation dialog must appear, allowing you to choose to cancel the upload</strong>. Refuse it. Pass if nothing happens, or if the browser simply displays the image.</p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/file/005.html b/tests/wpt/web-platform-tests/html/editing/dnd/file/005.html
new file mode 100644
index 00000000000..007d2b20f01
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/file/005.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - dragging text onto a file input</title>
+
+<ol>
+ <li>Save <a href="../resources/filler.html">this file</a> to your computer.</li>
+ <li>Write the full /path/and/name to that file, into the first input below, then select all of the text you just entered.</li>
+ <li>Drag selected text to the file input. If no prompt appears, and the text is not added to the file input, pass and ignore further steps.</li>
+ <li>If a prompt appears, accept it. Fail if the file input's value is set without any prompts.</li>
+ <li>If a prompt appears; fail if the file input's value is not set after accepting the prompt.</li>
+</ol>
+<p><input value="/tmp/filler.html"></p>
+<p><input type="file"></p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/file/006.html b/tests/wpt/web-platform-tests/html/editing/dnd/file/006.html
new file mode 100644
index 00000000000..58d65187019
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/file/006.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - cancelling dragging text onto a file input</title>
+
+<ol>
+ <li>Save <a href="../resources/filler.html">this file</a> to your computer.</li>
+ <li>Write the full /path/and/name to that file, into the first input below, then select all of the text you just entered.</li>
+ <li>Drag selected text to the file input. If no prompt appears, and the text is not added to the file input, pass and ignore further steps.</li>
+ <li>If a prompt appears, refuse it. Fail if the file input's value is set without any prompts.</li>
+ <li>If a prompt appears; fail if the file input's value is set after refusing the prompt.</li>
+</ol>
+<p><input value="/tmp/filler.html"></p>
+<p><input type="file"></p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/file/007.html b/tests/wpt/web-platform-tests/html/editing/dnd/file/007.html
new file mode 100644
index 00000000000..60be19b0aff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/file/007.html
@@ -0,0 +1,99 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - file drop for large file</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ }
+</style>
+
+<script>
+//JavaScript can support file sizes up to 9007199254740992 bytes ... in theory
+//This test uses a more sane value, just for the sake of UI testing - 32 MB
+var filesize1 = 33554432, filesize2 = 134217728;
+var fails = [], finished = false;
+window.onload = function() {
+ var orange = document.getElementsByTagName('div')[0];
+ orange.ondragover = orange.ondragenter = function(e) {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'copy';
+ if( !e.dataTransfer.files ) {
+ fails[fails.length] = 'No dataTransfer.files for '+e.type;
+ }
+ if( !window.FileList ) {
+ fails[fails.length] = 'No FileList interface object';
+ return;
+ }
+ if( !( e.dataTransfer.files instanceof FileList ) ) {
+ fails[fails.length] = 'dataTransfer.files is not a FileList';
+ }
+ if( e.dataTransfer.files.length ) {
+ fails[fails.length] = 'dataTransfer.files.length is '+e.dataTransfer.files.length+' instead of 0 for '+e.type;
+ }
+ };
+ orange.ondrop = function(e) {
+ e.preventDefault();
+ if( !e.dataTransfer.files ) {
+ fails[fails.length] = 'No dataTransfer.files for '+e.type;
+ }
+ if( !window.FileList ) {
+ fails[fails.length] = 'No FileList interface object';
+ finish();
+ return;
+ }
+ if( !( e.dataTransfer.files instanceof FileList ) ) {
+ fails[fails.length] = 'dataTransfer.files is not a FileList';
+ }
+ if( e.dataTransfer.files.length != 1 ) {
+ fails[fails.length] = 'dataTransfer.files.length is '+e.dataTransfer.files.length+' instead of 1 for '+e.type;
+ }
+ if( !e.dataTransfer.files[0] ) {
+ fails[fails.length] = 'no dataTransfer.files[0] for drop';
+ finish();
+ return;
+ }
+ if( e.dataTransfer.files[0].size != filesize1 && e.dataTransfer.files[0].size != filesize2 ) {
+ fails[fails.length] = 'dataTransfer.files[0].size '+e.dataTransfer.files[0].size+' instead of '+filesize1+' or '+filesize2;
+ }
+ /*
+ if( !e.dataTransfer.files[0].lastModifiedDate ) {
+ fails[fails.length] = 'no dataTransfer.files[0].lastModifiedDate';
+ }
+ */
+ if( !window.FileReader ) {
+ fails[fails.length] = 'No FileReader constructor';
+ finish();
+ return;
+ }
+ var reader = new FileReader();
+ reader.readAsBinaryString(e.dataTransfer.files[0]);
+ reader.onload = function () {
+ if( !reader.result ) {
+ fails[fails.length] = 'No file data after load';
+ }
+ if( reader.result.length != filesize1 && reader.result.length != filesize2 ) {
+ fails[fails.length] = 'File data length '+reader.result.length+' instead of '+filesize1+' or '+filesize2;
+ }
+ finish();
+ };
+ setTimeout(function () {
+ if( !reader.result ) {
+ fails[fails.length] = 'No file data after timeout';
+ }
+ finish();
+ },1000);
+ };
+
+};
+function finish() {
+ if( finished ) { return; }
+ finished = true;
+ document.getElementsByTagName('p')[0].innerHTML = fails.length ? ( 'FAIL: ' + fails.join('<br>') ) : 'PASS if the UI did not lock up';
+}
+</script>
+
+<div></div>
+
+<p>Save <a href="/common/large.py?size=32Mb">32MB.txt</a> to your desktop. Use your pointing device to drag the saved file from your desktop onto the orange box, and release it. If a confirmation dialog appears, accept it. Fail if this text is not replaced with a pass message. Fail if the UI locks up immediately after dropping the file.</p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/file/008.html b/tests/wpt/web-platform-tests/html/editing/dnd/file/008.html
new file mode 100644
index 00000000000..d610d8ee60e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/file/008.html
@@ -0,0 +1,113 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - dropping folders</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ }
+</style>
+
+<script>
+var fails = [], finished = false;
+window.onload = function() {
+ var orange = document.getElementsByTagName('div')[0];
+ orange.ondragover = orange.ondragenter = function(e) {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'copy';
+ if( !e.dataTransfer.files ) {
+ fails[fails.length] = 'No dataTransfer.files for '+e.type;
+ }
+ if( !window.FileList ) {
+ fails[fails.length] = 'No FileList interface object';
+ return;
+ }
+ if( !( e.dataTransfer.files instanceof FileList ) ) {
+ fails[fails.length] = 'dataTransfer.files is not a FileList';
+ } else if( e.dataTransfer.files.length ) {
+ fails[fails.length] = 'dataTransfer.files.length is '+e.dataTransfer.files.length+' instead of 0 for '+e.type;
+ }
+ };
+ orange.ondrop = function(e) {
+ e.preventDefault();
+ if( !e.dataTransfer.files ) {
+ fails[fails.length] = 'No dataTransfer.files for '+e.type;
+ }
+ if( !window.FileList ) {
+ fails[fails.length] = 'No FileList interface object';
+ finish();
+ return;
+ }
+ if( !( e.dataTransfer.files instanceof FileList ) ) {
+ fails[fails.length] = 'dataTransfer.files is not a FileList';
+ }
+ //browsers represent it as a single file (name matching the folder)
+ //also allow no files, since that is a valid solution
+ if( e.dataTransfer.files.length > 1 ) {
+ //dropping the contents of the folder would be crazy, since there could literally be millions of files, or the entire disk contents
+ fails[fails.length] = 'dataTransfer.files.length is '+e.dataTransfer.files.length+' instead of 1 for '+e.type;
+ }
+ if( !e.dataTransfer.files[0] ) {
+ finish();
+ return;
+ }
+ /*
+ Windows 7 sometimes randomly assigns size to folders, and that is presented to the browser.
+ Strangely, packing and unpacking that folder can remove its size.
+ Since this is an OS quirk that we have no control over, the test will not check the size.
+ if( e.dataTransfer.files[0].size ) {
+ fails[fails.length] = 'dataTransfer.files[0].size '+e.dataTransfer.files[0].size+' instead of 0';
+ }
+ */
+ /*
+ if( !e.dataTransfer.files[0].lastModifiedDate ) {
+ fails[fails.length] = 'no dataTransfer.files[0].lastModifiedDate';
+ }
+ */
+ if( !window.FileReader ) {
+ fails[fails.length] = 'No FileReader constructor';
+ finish();
+ return;
+ }
+ var reader = new FileReader();
+ reader.onload = function () {
+ fails[fails.length] = 'File managed to load even though it was a folder '+e.type;
+ finish();
+ };
+ reader.onerror = function () {
+ finish();
+ };
+ try {
+ reader.readAsBinaryString(e.dataTransfer.files[0]);
+ } catch(err) {
+ fails[fails.length] = 'Threw an error when trying to read the file '+e.type;
+ finish();
+ return;
+ }
+ setTimeout(function () {
+ fails[fails.length] = 'Onerror failed to fire '+reader.error.code;
+ finish();
+ },1000);
+ };
+
+};
+function finish() {
+ if( finished ) { return; }
+ finished = true;
+ document.getElementsByTagName('p')[0].innerHTML = fails.length ? ( 'FAIL: ' + fails.join('<br>') ) : 'PASS';
+}
+</script>
+
+<div></div>
+
+<p>Drag a folder containing at least 2 files, from your computer's file manager, onto the orange box above. If a no-drop cursor was shown and no text changes when the folder is dropped, pass and ignore further conditions. If a prompt appears, accept it. Fail if the mouse cursor makes it look like it will work but nothing happens.</p>
+<p>This test needs to be repeated with:</p>
+<ul>
+ <li>A regular folder containing at least 2 items</li>
+ <li>A disk drive (if your OS exposes them) containing at least 2 items</li>
+ <li>The system trash/recycle bin folder (if your OS exposes one) containing at least 2 items</li>
+ <li>The &quot;My Computer&quot; folder (if your OS provides it)</li>
+ <li>Your &quot;My Documents&quot; folder (if your OS provides it)</li>
+ <li>A folder that you do not have permissions to access</li>
+</ul>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/file/009.html b/tests/wpt/web-platform-tests/html/editing/dnd/file/009.html
new file mode 100644
index 00000000000..72381863f2f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/file/009.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - no dnd event listeners</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ }
+</style>
+
+<!-- This test assumes that the browser's default behaviour is to open dropped files. Test 010 continues with this assumption. -->
+
+<div></div>
+
+<p>Save <a href="../resources/pass.png">this image</a> to your desktop. Use your pointing device to drag the saved file from your desktop onto the orange box, and release it. Fail if nothing happens.</p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/file/010.html b/tests/wpt/web-platform-tests/html/editing/dnd/file/010.html
new file mode 100644
index 00000000000..ba24ae600cf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/file/010.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - blocked drop</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ }
+</style>
+
+<script>
+//This test assumes that if the page does not want to use the drop, that the browser will revert to default behaviour of opening the file
+window.onload = function() {
+ var orange = document.getElementsByTagName('div')[0];
+ orange.ondragover = orange.ondragenter = function(e) {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'none';
+ };
+ orange.ondrop = function(e) {
+ e.preventDefault();
+ };
+
+};
+</script>
+
+<div></div>
+
+<p>Save <a href="../resources/pass.png">this image</a> to your desktop. Use your pointing device to drag the saved file from your desktop onto the orange box, and release it. Fail if nothing happens.</p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/file/011.html b/tests/wpt/web-platform-tests/html/editing/dnd/file/011.html
new file mode 100644
index 00000000000..f05929c777f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/file/011.html
@@ -0,0 +1,93 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - simple file drop with dropzone attribute</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ }
+</style>
+
+<script>
+var filename = 'fail.png', filesize = '759', filetype = 'image/png';
+var fails = [], finished = false;
+window.onload = function() {
+ var orange = document.getElementsByTagName('div')[0];
+ orange.ondragenter = function(e) {
+ e.dataTransfer.dropEffect = 'copy';
+ };
+/* orange.ondragover = function(e) {
+ e.preventDefault();
+ };
+*/
+ orange.ondrop = function(e) {
+ e.preventDefault();
+ if( !e.dataTransfer.files ) {
+ fails[fails.length] = 'No dataTransfer.files for '+e.type;
+ }
+ if( !window.FileList ) {
+ fails[fails.length] = 'No FileList interface object';
+ finish();
+ return;
+ }
+ if( !( e.dataTransfer.files instanceof FileList ) ) {
+ fails[fails.length] = 'dataTransfer.files is not a FileList';
+ }
+ if( e.dataTransfer.files.length != 1 ) {
+ fails[fails.length] = 'dataTransfer.files.length is '+e.dataTransfer.files.length+' instead of 1 for '+e.type;
+ }
+ if( !e.dataTransfer.files[0] ) {
+ fails[fails.length] = 'no dataTransfer.files[0] for drop';
+ finish();
+ return;
+ }
+ if( e.dataTransfer.files[0].size != filesize ) {
+ fails[fails.length] = 'dataTransfer.files[0].size '+e.dataTransfer.files[0].size+' instead of '+filesize;
+ }
+ /*
+ if( !e.dataTransfer.files[0].lastModifiedDate ) {
+ fails[fails.length] = 'no dataTransfer.files[0].lastModifiedDate';
+ }
+ */
+ if( e.dataTransfer.files[0].name != filename ) {
+ fails[fails.length] = 'dataTransfer.files[0].name '+e.dataTransfer.files[0].name+' instead of '+filename;
+ }
+ if( e.dataTransfer.files[0].type != filetype ) {
+ fails[fails.length] = 'dataTransfer.files[0].type '+e.dataTransfer.files[0].type+' instead of '+filetype;
+ }
+ if( !window.FileReader ) {
+ fails[fails.length] = 'No FileReader constructor';
+ finish();
+ return;
+ }
+ var reader = new FileReader();
+ reader.onload = function () {
+ if( !reader.result ) {
+ fails[fails.length] = 'No file data after load';
+ }
+ if( reader.result.length != filesize ) {
+ fails[fails.length] = 'File data length '+reader.result.length+' instead of '+filesize;
+ }
+ finish();
+ };
+ reader.readAsBinaryString(e.dataTransfer.files[0]);
+ setTimeout(function () {
+ if( !reader.result ) {
+ fails[fails.length] = 'No file data after timeout';
+ }
+ finish();
+ },1000);
+ };
+
+};
+function finish() {
+ if( finished ) { return; }
+ finished = true;
+ document.getElementsByTagName('p')[0].innerHTML = fails.length ? ( 'FAIL: ' + fails.join('<br>') ) : 'PASS';
+}
+</script>
+
+<div dropzone="copy file:image/png"></div>
+
+<p>Save <a href="../resources/fail.png">this image</a> to your desktop. Use your pointing device to drag the saved file from your desktop onto the orange box, and release it. If a confirmation dialog appears, accept it. Fail if nothing happens, or if the browser simply displays the image.</p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/file/fail.txt b/tests/wpt/web-platform-tests/html/editing/dnd/file/fail.txt
new file mode 100644
index 00000000000..fc26162516b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/file/fail.txt
@@ -0,0 +1 @@
+FAIL \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/file/prompt/001.html b/tests/wpt/web-platform-tests/html/editing/dnd/file/prompt/001.html
new file mode 100644
index 00000000000..dc54aac5e14
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/file/prompt/001.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - file drop prompt for basic server name</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ }
+</style>
+
+<script>
+window.onload = function() {
+ if( location.protocol != 'http:' && location.protocol != 'https:' ) {
+ document.getElementsByTagName('p')[0].innerHTML = 'This test should be loaded over http or https.';
+ return;
+ }
+ var orange = document.getElementsByTagName('div')[0];
+ orange.ondragover = orange.ondragenter = orange.ondrop = function(e) {
+ e.preventDefault();
+ };
+ document.getElementsByTagName('span')[0].innerHTML = location.hostname;
+};
+</script>
+
+<div></div>
+
+<p>Drag a file from your desktop onto the orange square. A prompt should appear, correctly identifying the server name as <span></span></p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/file/prompt/002.html b/tests/wpt/web-platform-tests/html/editing/dnd/file/prompt/002.html
new file mode 100644
index 00000000000..7bad40a2f04
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/file/prompt/002.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - file drop prompt for server name and document.domain</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ }
+</style>
+
+<script>
+window.onload = function() {
+ if( location.protocol != 'http:' && location.protocol != 'https:' ) {
+ document.getElementsByTagName('p')[0].innerHTML = 'This test should be loaded over http or https.';
+ return;
+ }
+ if( !location.hostname.match(/[^\.]\.[^\.]+\.[^\.]/) ) {
+ document.getElementsByTagName('p')[0].innerHTML = 'This test should be loaded from a subdomain that allows document.domain to be set to a parent domain (try using a server name that contains at least two or three dots, for example www.example.org).';
+ return;
+ }
+ var realhost = location.hostname, newdomain = location.hostname.replace(/^[^.]+\./,'');
+ try {
+ document.domain = location.hostname.replace(/^[^.]+\./,'');
+ } catch(e) {
+ document.getElementsByTagName('p')[0].innerHTML = 'This test should be loaded from a subdomain that allows document.domain to be set to a parent domain.';
+ return;
+ }
+ var orange = document.getElementsByTagName('div')[0];
+ orange.ondragover = orange.ondragenter = orange.ondrop = function(e) {
+ e.preventDefault();
+ };
+ document.getElementsByTagName('span')[0].innerHTML = realhost;
+};
+</script>
+
+<div></div>
+
+<p>Drag a file from your desktop onto the orange square. A prompt should appear, identifying the server name as <span></span></p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/file/prompt/003.html b/tests/wpt/web-platform-tests/html/editing/dnd/file/prompt/003.html
new file mode 100644
index 00000000000..4b7a98aae06
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/file/prompt/003.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - file drop prompt for ftp server name</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ }
+</style>
+
+<script>
+window.onload = function() {
+ if( location.protocol != 'ftp:' ) {
+ document.getElementsByTagName('p')[0].innerHTML = 'This test should be loaded over ftp.';
+ return;
+ }
+ var orange = document.getElementsByTagName('div')[0];
+ orange.ondragover = orange.ondragenter = orange.ondrop = function(e) {
+ e.preventDefault();
+ };
+ document.getElementsByTagName('span')[0].innerHTML = location.hostname;
+};
+</script>
+
+<div></div>
+
+<p>Drag a file from your desktop onto the orange square. A prompt should appear, correctly identifying the server name as <span></span></p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/file/prompt/004.html b/tests/wpt/web-platform-tests/html/editing/dnd/file/prompt/004.html
new file mode 100644
index 00000000000..53966881922
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/file/prompt/004.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - file drop prompt for file:</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ }
+</style>
+
+<script>
+window.onload = function() {
+ if( location.protocol != 'file:' ) {
+ document.getElementsByTagName('p')[0].innerHTML = 'Save this page to your local filesystem, and load it from there.';
+ return;
+ }
+ var orange = document.getElementsByTagName('div')[0];
+ orange.ondragover = orange.ondragenter = orange.ondrop = function(e) {
+ e.preventDefault();
+ };
+};
+</script>
+
+<div></div>
+
+<p>Drag a file from your desktop onto the orange square. A prompt should appear, either showing the server name as localhost, or otherwise identifying this file as the target of the upload.</p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/file/prompt/005.html b/tests/wpt/web-platform-tests/html/editing/dnd/file/prompt/005.html
new file mode 100644
index 00000000000..395d37d626c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/file/prompt/005.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - file drop prompt for special cases</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ }
+</style>
+
+<script>
+window.onload = function() {
+ if( location.protocol == 'file:' || location.protocol == 'http:' || location.protocol == 'https:' ) {
+ document.getElementsByTagName('p')[0].innerHTML = 'Use the source of this file as the source of special-case URLs within your browser, such as scriptable chrome: or opera: or attachment: URLs (eg. opera:config and send yourself the file as an email attachments and open the attachment in the browser).';
+ return;
+ }
+ var orange = document.getElementsByTagName('div')[0];
+ orange.ondragover = orange.ondragenter = orange.ondrop = function(e) {
+ e.preventDefault();
+ };
+};
+</script>
+
+<div></div>
+
+<p>Drag a file from your desktop onto the orange square. A prompt should appear, either showing the server name as unknown, or otherwise identifying this URL as the target of the upload.</p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/file/prompt/006.html b/tests/wpt/web-platform-tests/html/editing/dnd/file/prompt/006.html
new file mode 100644
index 00000000000..5f0f9b306d1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/file/prompt/006.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - file drop prompt for data URI with inherited origin</title>
+<style>
+iframe { border: none; height: 250px; width: 250px; }
+</style>
+
+<script>
+window.onload = function() {
+ if( location.protocol != 'http:' && location.protocol != 'https:' ) {
+ document.getElementsByTagName('p')[0].innerHTML = 'This test should be loaded over http or https.';
+ return;
+ }
+ var url = "data:text/html,"+escape(
+'<!DOCTYPE html>\
+<title>drag &amp; drop - file drop prompt for data URI with inherited origin<\/title>\
+<style>\
+ body > div {\
+ height: 200px;\
+ width: 200px;\
+ background-color: orange;\
+ }\
+<\/style>\
+<script>\
+window.onload = function() {\
+ var orange = document.getElementsByTagName("div")[0];\
+ orange.ondragover = orange.ondragenter = orange.ondrop = function(e) {\
+ e.preventDefault();\
+ };\
+};\
+<\/script>\
+<div><\/div>'
+ );
+ var frame = document.createElement('iframe');
+ frame.setAttribute('src',url);
+ document.body.appendChild(frame);
+ document.getElementsByTagName('span')[0].innerHTML = location.hostname;
+};
+</script>
+
+<p>Drag a file from your desktop onto the orange square. A prompt should appear, correctly identifying the server name <span></span>.</p>
+<noscript><p>Enable JavaScript and reload</p></noscript> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/file/prompt/007.html b/tests/wpt/web-platform-tests/html/editing/dnd/file/prompt/007.html
new file mode 100644
index 00000000000..5a5b982d6c1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/file/prompt/007.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - file drop prompt for data URI without inherited origin</title>
+<script>
+window.onload = function() {
+ var url = "data:text/html,"+escape(
+'<!DOCTYPE html>\
+<title>drag &amp; drop - file drop prompt for data URI with inherited origin<\/title>\
+<style>\
+ body > div {\
+ height: 200px;\
+ width: 200px;\
+ background-color: orange;\
+ }\
+<\/style>\
+<script>\
+window.onload = function() {\
+ var orange = document.getElementsByTagName("div")[0];\
+ orange.ondragover = orange.ondragenter = orange.ondrop = function(e) {\
+ e.preventDefault();\
+ };\
+};\
+<\/script>\
+<div><\/div>\
+<p>Drag a file from your desktop onto the orange square. A prompt should appear, either showing the server name as unknown, or otherwise identifying this URL as the target of the upload.<\/p>'
+ );
+ document.getElementsByTagName('p')[1].textContent = url;
+};
+</script>
+
+<p>Load the following URL in a new tab (copy &amp; paste it into the address bar):</p>
+<p></p>
+<noscript><p>Enable JavaScript and reload</p></noscript> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/file/prompt/008.html b/tests/wpt/web-platform-tests/html/editing/dnd/file/prompt/008.html
new file mode 100644
index 00000000000..ff07b78deb2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/file/prompt/008.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - file drop prompt for javascript URL with inherited origin</title>
+<style>
+iframe { border: none; height: 250px; width: 250px; }
+</style>
+
+<script>
+window.onload = function() {
+ if( location.protocol != 'http:' && location.protocol != 'https:' ) {
+ document.getElementsByTagName('p')[0].innerHTML = 'This test should be loaded over http or https.';
+ return;
+ }
+ var url = "javascript:'"+escape(
+'<!DOCTYPE html>\
+<title>drag &amp; drop - file drop prompt for data URI with inherited origin<\/title>\
+<style>\
+ body > div {\
+ height: 200px;\
+ width: 200px;\
+ background-color: orange;\
+ }\
+<\/style>\
+<script>\
+window.onload = function() {\
+ var orange = document.getElementsByTagName("div")[0];\
+ orange.ondragover = orange.ondragenter = orange.ondrop = function(e) {\
+ e.preventDefault();\
+ };\
+};\
+<\/script>\
+<div><\/div>'
+ +"'");
+ var frame = document.createElement('iframe');
+ frame.setAttribute('src',url);
+ document.body.appendChild(frame);
+ document.getElementsByTagName('span')[0].innerHTML = location.hostname;
+};
+</script>
+
+<p>Drag a file from your desktop onto the orange square. A prompt should appear, correctly identifying the server name <span></span></p>
+<noscript><p>Enable JavaScript and reload</p></noscript> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/file/prompt/009.html b/tests/wpt/web-platform-tests/html/editing/dnd/file/prompt/009.html
new file mode 100644
index 00000000000..6fa18b97597
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/file/prompt/009.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - file drop prompt for javascript URL without inherited origin</title>
+<script>
+window.onload = function() {
+ var url = "javascript:'"+escape(
+'<!DOCTYPE html>\
+<title>drag &amp; drop - file drop prompt for data URI with inherited origin<\/title>\
+<style>\
+ body > div {\
+ height: 200px;\
+ width: 200px;\
+ background-color: orange;\
+ }\
+<\/style>\
+<script>\
+window.onload = function() {\
+ var orange = document.getElementsByTagName("div")[0];\
+ orange.ondragover = orange.ondragenter = orange.ondrop = function(e) {\
+ e.preventDefault();\
+ };\
+};\
+<\/script>\
+<div><\/div>\
+<p>Drag a file from your desktop onto the orange square. A prompt should appear, either showing the server name as unknown, or otherwise identifying this URL as the target of the upload (it may alternatively identify the security context about:blank).<\/p>'
+ +"'");
+ document.getElementsByTagName('p')[1].textContent = url;
+};
+</script>
+
+<p>Load the following URL in a new tab (copy &amp; paste it into the address bar):</p>
+<p></p>
+<noscript><p>Enable JavaScript and reload</p></noscript> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/images/001.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/images/001.xhtml
new file mode 100644
index 00000000000..e5ea49969b1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/images/001.xhtml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Image drag and drop</title>
+<style type="text/css">
+div[ondragenter]
+ {width:105px;
+ min-height:105px;
+ text-align:center;
+ margin-top:20px;
+ padding:10px;
+ border:solid thin navy;}
+p:first-child
+ {padding-left:12px;}
+</style>
+<script type="application/ecmascript">
+function addImage(event)
+ {var c = document.createElement('img');
+ c.setAttribute('src',event.dataTransfer.getData('text/uri-list').replace(/\r\n$/,''));
+ document.querySelector('div').appendChild(c);}
+</script>
+</head>
+<body>
+<p><img src="../resources/circle.png" alt="PNG circle" ondragstart="event.dataTransfer.effectAllowed = 'copy'"/></p>
+<p>Drag circle above to the box below. It should be copied to the box once you drop it there.</p>
+<div
+ ondragenter="event.preventDefault()"
+ ondragover="return false"
+ ondrop="addImage(event)"
+/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/images/002.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/images/002.xhtml
new file mode 100644
index 00000000000..65584e85733
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/images/002.xhtml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>dataURL image drag and drop</title>
+<style type="text/css">
+div[ondragenter]
+ {width:105px;
+ min-height:105px;
+ text-align:center;
+ margin-top:20px;
+ padding:10px;
+ border:solid thin navy;}
+p:first-child
+ {padding-left:12px;}
+</style>
+<script type="application/ecmascript">
+function addImage(event)
+ {var c = document.createElement('img');
+ c.setAttribute('src',event.dataTransfer.getData('text/uri-list').replace(/\r\n$/,''));
+ document.querySelector('div').appendChild(c);}
+</script>
+</head>
+<body>
+<p><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAEq0lEQVR42u1dvU4bQRAeR0RCCilSp0peIoKGB4DSXYRDlcZlFClKBI4bB/kV/AymIDwCTahiicaioEOxhCsjWVTJziyKMfYZn+9ud3bvG2mEZB13u9+nndmf2Rki7fKFXtEBbVKD9o22jB4bPaND6hm9Mjo0enevw/vfevKMfbYl/8vv4HdBUkvFALhltG2A7dN3+pur8jv53fwN/hZkjjRo3eiuAatjdJA7CcnkDOSb/G1uQ6mFzUeDagaQrvl764yEJOU22LbUymXaGrRhOt40OvJOQvLIGUkbP9GLeIn4SM9NJ+tOTVI+Jq0ubY9sVFRNxy6DIWKWmEvpQ/ByQNumI+fBEjHrZ86lT8HJV3ptGn8aDRGzxJxKHwMZFe9Mg6+jJWNCyrX0VbUc0nuj4+jJmPiWsfRZodN+ZvSoNETMjpYjwUCFfKaXpjEnpSVjQsqJYOF5ZLw1elF6MiakXAgmnpw378DegIgZUm4EGw8jA2QsIuUbvXHpM2CmljFfhfsUO5uCA0/j6AudfZV5arv6WuVHcYs+ALwqKTkvHnmLoEwr8CJW9Llts9iNwvj3plzsfeWyIRnzrq37kfIzq6naBpA5a6bzlJgOl/SMkl+rklEFgIX5k5THwTYgIdwzcP2jhM/o19KsOeoArnBS6suaqo2gQnXCJWSwXNwXB4gBMFekNBeTwSGUmiMK4yNktDhsleNaAZRrUvYWmasuQHJOSDdpdKyriEIvo9maexWC70gAIF/bKTvzzFUH4HgbJZ3HdFSw9vC6lfKHpq7X8X07AOOblK2HhLQBindC2g/9Rx+gePcj/cnqHIDoUFm1c9gjwNAy/d0kyXIAMLSYrQ8kqScAhhbH3iLJBwIwtBByTJKkBWBoIeSMJHMOwNBCyG+SdEYAQ4tTvyLJMQUwtBAyJEn8BTC0EHIHQhQSApOlzGTBqaty6jzVAhhaCOlhYahuYYitE02EHGNzURchLZItX4ChhZB9HFBpUjmgwhGuHv0feI0gBw1T3j7CgHT5jzYC5XQRsjUdSsrhjADGl7ka0EylBgRb+ySkMy9rww7A8Waududf2MH9Qh9k3CbXLsGVNh/mqrvojuEeQHI+Qmq4Fq1ndIyeruaDxAEuCWk+ncmB0z3gepubtQenMUHyGTWELJl8xk6B15CeqVAyLtPXtUICsyJnVivWs+J0dAAwbzLOkQRTk2YuKsapTQFkXqPjlDILEinnRcZ1fpXdkGo866xqnH9FNyTjz0JIQZXcuPQCAE5rqo6oMEFBl7RknBRfTg8lj5Yl48JdGT0ueIWiYIvIuHFfPg9l85LJcF42b+JTUFjysZnyVlhy2qfA0asovTo9+0JxYnWC8t0KBQXuFYrdkIy3mBj3LbeNQrejZTuqOlbcl8znGTqcfjXoM3pboqgaPhEPxda1qgcVYsRt5TanDkgISWzcV1N1hCS3jdu4dNxUDMIhlBzXysHGGspkcBtsW2pPh3fGLrZ2ya5cXHFp0qxJ6si3E68EQCpy344vQRZxO5jfye+2d/oqgHsV02Z3lvcl9QTnA+EkLZw5h9MZcY4pTvxldXj/W0+esc+25H/5HQGYon+Q5f+MwFz+8QAAAABJRU5ErkJggg==" alt="PNG circle" ondragstart="event.dataTransfer.effectAllowed = 'copy'"/></p>
+<p>Drag circle above to the box below. It should be copied to the box once you drop it there.</p>
+<div
+ ondragenter="event.preventDefault()"
+ ondragover="return false"
+ ondrop="addImage(event)"
+/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/images/003.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/images/003.xhtml
new file mode 100644
index 00000000000..ae94a8b3f1e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/images/003.xhtml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Image drag and drop outside browser window</title>
+<style type="text/css">
+div[ondragenter]
+ {width:105px;
+ min-height:105px;
+ text-align:center;
+ margin-top:20px;
+ padding:10px;
+ border:solid thin navy;}
+p:first-child
+ {padding-left:12px;}
+</style>
+<script type="application/ecmascript">
+function addImage(event)
+ {var c = document.createElement('img');
+ c.setAttribute('src',event.dataTransfer.getData('text/uri-list').replace(/\r\n$/,''));
+ document.querySelector('div').appendChild(c);}
+</script>
+</head>
+<body>
+<p><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAEq0lEQVR42u1dvU4bQRAeR0RCCilSp0peIoKGB4DSXYRDlcZlFClKBI4bB/kV/AymIDwCTahiicaioEOxhCsjWVTJziyKMfYZn+9ud3bvG2mEZB13u9+nndmf2Rki7fKFXtEBbVKD9o22jB4bPaND6hm9Mjo0enevw/vfevKMfbYl/8vv4HdBUkvFALhltG2A7dN3+pur8jv53fwN/hZkjjRo3eiuAatjdJA7CcnkDOSb/G1uQ6mFzUeDagaQrvl764yEJOU22LbUymXaGrRhOt40OvJOQvLIGUkbP9GLeIn4SM9NJ+tOTVI+Jq0ubY9sVFRNxy6DIWKWmEvpQ/ByQNumI+fBEjHrZ86lT8HJV3ptGn8aDRGzxJxKHwMZFe9Mg6+jJWNCyrX0VbUc0nuj4+jJmPiWsfRZodN+ZvSoNETMjpYjwUCFfKaXpjEnpSVjQsqJYOF5ZLw1elF6MiakXAgmnpw378DegIgZUm4EGw8jA2QsIuUbvXHpM2CmljFfhfsUO5uCA0/j6AudfZV5arv6WuVHcYs+ALwqKTkvHnmLoEwr8CJW9Llts9iNwvj3plzsfeWyIRnzrq37kfIzq6naBpA5a6bzlJgOl/SMkl+rklEFgIX5k5THwTYgIdwzcP2jhM/o19KsOeoArnBS6suaqo2gQnXCJWSwXNwXB4gBMFekNBeTwSGUmiMK4yNktDhsleNaAZRrUvYWmasuQHJOSDdpdKyriEIvo9maexWC70gAIF/bKTvzzFUH4HgbJZ3HdFSw9vC6lfKHpq7X8X07AOOblK2HhLQBindC2g/9Rx+gePcj/cnqHIDoUFm1c9gjwNAy/d0kyXIAMLSYrQ8kqScAhhbH3iLJBwIwtBByTJKkBWBoIeSMJHMOwNBCyG+SdEYAQ4tTvyLJMQUwtBAyJEn8BTC0EHIHQhQSApOlzGTBqaty6jzVAhhaCOlhYahuYYitE02EHGNzURchLZItX4ChhZB9HFBpUjmgwhGuHv0feI0gBw1T3j7CgHT5jzYC5XQRsjUdSsrhjADGl7ka0EylBgRb+ySkMy9rww7A8Waududf2MH9Qh9k3CbXLsGVNh/mqrvojuEeQHI+Qmq4Fq1ndIyeruaDxAEuCWk+ncmB0z3gepubtQenMUHyGTWELJl8xk6B15CeqVAyLtPXtUICsyJnVivWs+J0dAAwbzLOkQRTk2YuKsapTQFkXqPjlDILEinnRcZ1fpXdkGo866xqnH9FNyTjz0JIQZXcuPQCAE5rqo6oMEFBl7RknBRfTg8lj5Yl48JdGT0ueIWiYIvIuHFfPg9l85LJcF42b+JTUFjysZnyVlhy2qfA0asovTo9+0JxYnWC8t0KBQXuFYrdkIy3mBj3LbeNQrejZTuqOlbcl8znGTqcfjXoM3pboqgaPhEPxda1qgcVYsRt5TanDkgISWzcV1N1hCS3jdu4dNxUDMIhlBzXysHGGspkcBtsW2pPh3fGLrZ2ya5cXHFp0qxJ6si3E68EQCpy344vQRZxO5jfye+2d/oqgHsV02Z3lvcl9QTnA+EkLZw5h9MZcY4pTvxldXj/W0+esc+25H/5HQGYon+Q5f+MwFz+8QAAAABJRU5ErkJggg==" alt="PNG circle" ondragstart="event.dataTransfer.effectAllowed = 'copy'"/></p>
+<p>Drag circle above outside the window and then back inside and drop in the box below. It should be copied to the box once you drop it there.</p>
+<div
+ ondragenter="event.preventDefault()"
+ ondragover="return false"
+ ondrop="addImage(event)"
+/>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/images/004.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/images/004.xhtml
new file mode 100644
index 00000000000..e0fff952380
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/images/004.xhtml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Object with image drag and drop</title>
+<style type="text/css">
+div[ondragenter]
+ {width:105px;
+ min-height:105px;
+ text-align:center;
+ margin-top:20px;
+ padding:10px;
+ border:solid thin navy;}
+p:first-child
+ {padding-left:12px;}
+</style>
+<script type="application/ecmascript">
+function addImage(event)
+ {var c = document.createElement('img');
+ c.setAttribute('src',event.dataTransfer.getData('text/uri-list').replace(/\r\n$/,''));
+ document.querySelector('div').appendChild(c);}
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ event.dataTransfer.setData('text/uri-list', document.querySelector('object').getAttribute('data'));}
+</script>
+</head>
+<body>
+<p><object draggable="true" ondragstart="start(event)" type="image/png" data="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAEq0lEQVR42u1dvU4bQRAeR0RCCilSp0peIoKGB4DSXYRDlcZlFClKBI4bB/kV/AymIDwCTahiicaioEOxhCsjWVTJziyKMfYZn+9ud3bvG2mEZB13u9+nndmf2Rki7fKFXtEBbVKD9o22jB4bPaND6hm9Mjo0enevw/vfevKMfbYl/8vv4HdBUkvFALhltG2A7dN3+pur8jv53fwN/hZkjjRo3eiuAatjdJA7CcnkDOSb/G1uQ6mFzUeDagaQrvl764yEJOU22LbUymXaGrRhOt40OvJOQvLIGUkbP9GLeIn4SM9NJ+tOTVI+Jq0ubY9sVFRNxy6DIWKWmEvpQ/ByQNumI+fBEjHrZ86lT8HJV3ptGn8aDRGzxJxKHwMZFe9Mg6+jJWNCyrX0VbUc0nuj4+jJmPiWsfRZodN+ZvSoNETMjpYjwUCFfKaXpjEnpSVjQsqJYOF5ZLw1elF6MiakXAgmnpw378DegIgZUm4EGw8jA2QsIuUbvXHpM2CmljFfhfsUO5uCA0/j6AudfZV5arv6WuVHcYs+ALwqKTkvHnmLoEwr8CJW9Llts9iNwvj3plzsfeWyIRnzrq37kfIzq6naBpA5a6bzlJgOl/SMkl+rklEFgIX5k5THwTYgIdwzcP2jhM/o19KsOeoArnBS6suaqo2gQnXCJWSwXNwXB4gBMFekNBeTwSGUmiMK4yNktDhsleNaAZRrUvYWmasuQHJOSDdpdKyriEIvo9maexWC70gAIF/bKTvzzFUH4HgbJZ3HdFSw9vC6lfKHpq7X8X07AOOblK2HhLQBindC2g/9Rx+gePcj/cnqHIDoUFm1c9gjwNAy/d0kyXIAMLSYrQ8kqScAhhbH3iLJBwIwtBByTJKkBWBoIeSMJHMOwNBCyG+SdEYAQ4tTvyLJMQUwtBAyJEn8BTC0EHIHQhQSApOlzGTBqaty6jzVAhhaCOlhYahuYYitE02EHGNzURchLZItX4ChhZB9HFBpUjmgwhGuHv0feI0gBw1T3j7CgHT5jzYC5XQRsjUdSsrhjADGl7ka0EylBgRb+ySkMy9rww7A8Waududf2MH9Qh9k3CbXLsGVNh/mqrvojuEeQHI+Qmq4Fq1ndIyeruaDxAEuCWk+ncmB0z3gepubtQenMUHyGTWELJl8xk6B15CeqVAyLtPXtUICsyJnVivWs+J0dAAwbzLOkQRTk2YuKsapTQFkXqPjlDILEinnRcZ1fpXdkGo866xqnH9FNyTjz0JIQZXcuPQCAE5rqo6oMEFBl7RknBRfTg8lj5Yl48JdGT0ueIWiYIvIuHFfPg9l85LJcF42b+JTUFjysZnyVlhy2qfA0asovTo9+0JxYnWC8t0KBQXuFYrdkIy3mBj3LbeNQrejZTuqOlbcl8znGTqcfjXoM3pboqgaPhEPxda1qgcVYsRt5TanDkgISWzcV1N1hCS3jdu4dNxUDMIhlBzXysHGGspkcBtsW2pPh3fGLrZ2ya5cXHFp0qxJ6si3E68EQCpy344vQRZxO5jfye+2d/oqgHsV02Z3lvcl9QTnA+EkLZw5h9MZcY4pTvxldXj/W0+esc+25H/5HQGYon+Q5f+MwFz+8QAAAABJRU5ErkJggg==" alt="PNG circle">PNG image</object></p>
+<p>Drag circle above to the box below. It should be copied to the box once you drop it there.</p>
+<div
+ ondragenter="event.preventDefault()"
+ ondragover="return false"
+ ondrop="addImage(event)"
+/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/images/005.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/images/005.xhtml
new file mode 100644
index 00000000000..49eaabdfc9b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/images/005.xhtml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>JPG image drag and drop</title>
+<style type="text/css">
+div[ondragenter]
+ {width:105px;
+ min-height:105px;
+ text-align:center;
+ margin-top:20px;
+ padding:10px;
+ border:solid thin navy;}
+p:first-child
+ {padding-left:12px;}
+</style>
+<script type="application/ecmascript">
+function addImage(event)
+ {var c = document.createElement('img');
+ c.setAttribute('src',event.dataTransfer.getData('text/uri-list').replace(/\r\n$/,''));
+ document.querySelector('div').appendChild(c);}
+</script>
+</head>
+<body>
+<p><img src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAgAAAQABAAD/2wCEAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAf/EAaIAAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKCxAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6AQADAQEBAQEBAQEBAAAAAAAAAQIDBAUGBwgJCgsRAAIBAgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDThJfEXGBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uLj5OXm5+jp6vLz9PX29/j5+v/AABEIAGQAZAMBIgACEQEDEQH/2gAMAwEAAhEDEQA/AP7+KKK8v+Mvxl+Gn7P3w08V/F74veK9P8GfD/wZp51HXdd1EuVRS6wWtlZWsCy3mp6tqd5LBp+k6Tp8FxqGp6hcQWdnBLPKiHOtWo4ejVxGIq06FChTnVrVqs406VKlTi5VKlSpJqMIQinKUpNKKV2Y4jEUMJQrYrFVqWHw2HpTr4jEV5xpUaFGlFzqVatSbUKdOnBOU5yajGKbbsekXV1a2Frc319cwWdlZwTXV5eXU0dva2trbxtLcXNzcSskUEEESNLNNKyxxxqzuwUE1+B37ZX/AAcDfsvfAK61bwV8BNOm/aZ+ImnyS2U+p6Fqa6J8ItIvIzsk8zx19mv5/FjQEiVE8G6VqOiX6rJB/wAJZYTg7f54f+Clf/BX34z/ALc2tax4C8H3OrfCv9mS1v2TR/h7ZXX2bXfHVvayA2mt/FTULKd11SeaRBfWvhC0nbwvob/ZVZdd1bTo/EU/47V/KHHn0gsQ61bLeB4wp0YN055/iqKqVKzWnNl2ErL2dOn/AC18XTqyqLbDUbKcv4l8TPpR4t4jEZR4cQp0cPTcqU+JsZQVatXa0csqwNePsqVH+TE46nWnVT0wmHtGcv14+PH/AAXF/wCCiHxvub+Kx+LsPwV8NXe8ReGfgpo1t4Ra0jPCGPxndtrHxEFxs/1kkPi63gaTMkVrB8qJ+bPjH44fGr4iXLXnxA+L/wAUfHN2+4vdeMfH/ivxNcvu+9un1rVr2Rt38WW5715bRX87ZpxLxDnVSVTNs6zTMJS6YrG4irBeUKTn7KnHtCnCMV0R/KWc8XcU8Q1ZVs84hznNJTd7Y3McVWpR1vy06EqnsaMO1OlThCP2Yo19P17XNJm+0aVrOraZcbt/n6fqN3Zzb+u/zbeaN93+1nNfV/ws/wCChP7b/wAF7q2ufh3+1N8a9JhtMeRo2qeONX8X+Fl29N3g/wAZTeIPCsvp+90d8r8p+XivjmiuHCZlmOXzVXAY/G4GqndVMJiq+Gmn3U6M4SX3nm4DN81yqoq2WZnmGXVou8auAxuJwlRNdVPD1Kck/mf01/swf8HJ3xp8KXOmaF+1d8LvD/xY8OhkhvvHfw4it/BHxDt4f+Wt/c+HJZT4F8S3I6R6fp6/D+DDZa8ymJP6if2Vv21/2bP2zvCT+K/gB8SNL8VNYxRN4i8JXYbRvHnhGSU7BH4l8I6h5eq2MLTboLbV4Y7rQNTljl/sjVtQjQvX+YXXoXwt+K/xI+CXjnQviX8JfGniDwB478NXQu9G8S+G7+Sw1C2bjzbeXbmC+068jzb6lpOoQ3Wl6pZvLZajZ3VpNLC/7Pwf48cVZHVpUM/m+JMruoz+scsc1ow6yoY2y+sSXxOGO9q6nwLEUF7x/QXAX0l+NOG61HC8T1JcW5LeMan1pxjneHp7OeHzGy+tSXxOnmKryrP3FisNfnP9V6ivwp/4JQf8FjfCv7altYfBP43f2N4G/af0+ykNh9kA0/wr8Y7HT7dprrVPCsMsjLpXi+0tYpLvX/B3msk9vHPr3hkyaYmp6T4a/dav7H4e4iyjinK6Gb5Lio4rB1tP5atCskvaYbE0vio4indc1OXRxnBzpThOX99cK8V5Fxpk2Gz7h7GxxuAxGj+zXw1eKTq4TGUX72HxVHmXPTl0calOU6NSnUkUUUV7h9GVru7tNPtLq/v7q3srGyt5ru9vbuaO2tLS0to2muLm5uJmSGC3ghR5ZppXWOKNWd2Cgmv8/L/gr9/wUq1r9uX40XPg7wFrF9a/syfCvVrqx+HukRtJbW/jvXbbzrHUPiprdr8rzTaorz2vg+2vRv0Pwu6sttp+ra74hjm/ob/4OB/2y7v4Bfsv6b8A/BWrSaf8RP2mJdU0PVLiyl2XmkfCHRFtv+E5fehLW7+Lbi/0vwdGkqbL/Q7/AMXCCRZ7HK/wtV/Jn0gePKzxEeB8srOFGnClic/nTlrWqVEq2Ey6Vv8Al3Tp8mLrx2qSq4Zaexmpfw/9KPxMxDxcPDjKMRKnh6VOhjOJp0pWderVUa+ByqTX/LmlS9njsTDVVZ1sItPYTUiiiiv5aP4vCiiigAooooAKKKKANnw94h13wlr2jeKfC+sal4e8SeHdUsdb0HXdGvJ9O1bRtY0u5jvNO1PTb+1eO5s76yu4Yri1uYJElhmjV0YMK/0If+CRf/BROz/b0+ARj8YXFpa/tBfCSPStA+LWnRJDax+Io7qKZNA+JOk2kISGKx8VpY3S6vZWscUWj+JrPU7aK1tdJudDa6/zxa+5P+CdP7XWr/sUftY/DT4zw3d4ngz+0U8JfFnSrXzGGufDDxJcW1t4mie1jBa9utE2WnizRbYbfM1/w/palxGZAf1Dwp47r8E8SUHWqy/sLM6lLCZxRb/dwhJ8tLMEtlVwMpe0k0rzw3t6O84uP7L4J+JWJ8O+LcNKvXn/AKt5zVo4HPsO5fuqdOcuShmkY7Ktl05+1lJLmqYT6zQ3qRlH/S8oqnp9/Y6tYWWqaZd29/pupWltf6ffWkqT2t7Y3kKXFpd208ZMc1vcQSJNDKhKSRurKSDVyv8AQhO+q1T1TXU/1LTTSad09U1s13R/nq/8Fw/jvc/G/wD4KI/F+zivzeeGvgvHo3wT8MQhhssz4PtjdeMoSq/J53/CxtY8YI8nMphitoZD/o6JH+RNen/G3xlc/Eb4z/Fz4g3jmW78d/E7x74yupCdxkufE/irVdbnctxuLSXrHOBnNeYV/mHxJmlTOuIM6zapJylmGaY3Fa9IVcROVKC/u06XJTgukIpH+OPF2c1OIeKOIc8qyc5ZrnOY41X+zTr4qpKjTX9ylR5KVNfZhCK6BRRRXhnzoUUUUAFFFFABRRRQAUUUUAf6JX/BFr483Xx8/wCCeHwR1HV9Q/tHxN8MYNW+CviSZpfOlWT4eXK2fhZLh2Jka6f4eXfg24uXmJllmneYlvMDH9Vq/gD/AOCc/wC3h4v/AGXvgl4o8A6BdGGz1f4p634wkUTXEf8ApN/4S8EaK7YikRf9V4fhGcZ4+lfff/D4H4l/9BB//Aq9/wDj9f1XknjdWwWS5RgqsKdWrhMrwGFqVZqTnUnQwtKlOpN9ZTlFyk+rZ/bHDn0iq+XcPZFl9anSrVsDk2V4OrWqKUqlWphsFQozqVJdZzlByk+rZ/LrrlhNpetavplzu+06dql/YXG773nWl3Lby7s87t8Zz71lV9i/8FB/hZc/Bf8Abe/am+HVxbfY4dI+NfjnU9FgwRt8LeLtXm8Y+D2+b/nr4V1/R5s/dbflSVINfHVfzFmWEqZfmOPwFVctXBY3FYSonuqmGrzozT9JQZ/HGbYCrlea5nllZONbLswxmAqp7qrhMRUw80/SVNhRRRXCecFFFFABRRRQAUUUUAFFFFAHv3wr+Feu+OPD95qumTarHBb6zcaewsSfK82Ky0+5JbH/AC02XaZ/2dtel/8ADPPi/wD5+/EX5tX9Mn/BCL9jPwZ48/YeuviJ8R9HjuZvHXxr8fat4UnNtBKZPC2j6T4Q8FtlriJj8vinwt4oj+Q+X8n9/fX7P/8ADBnwE/6AEP8A4Baf/wDGK/Xst8Lc6zDLsBj6WFrSpY3BYXF02oTs4YmhCtBrXrGaP3jKPBniLNMpyvM6ODryo5jl2Cx1KSpztKni8NTrwa8nGomfzN/8HJv7MFz4S+Nnww/au0HTHHh34teHofh147voUYwwfETwPbSP4eub+Y8JceJfAfk6fp0K8GH4f38h2t9/+Zev9PP9tj9lXwl+2f8As1/Ej4A+K2hspPFGli88IeIpIzI/hHx7ox+3+EfEsewGbybLVEjg1e3tzHLqXh+71fSPMSPUHNf5pvxW+F3jn4J/Efxn8JviXoN34Z8d+AdfvvDfiXRbxfntdQsZMeZBL/q7zTr6Aw6hpWpW5ez1TTLq01GylmtLqGV/X8eOD6uRcVTz7D0n/ZfEjeI54r3KOaxivrtCVtpYj/foOWtR1cQo/wACR7f0l+Aq3DfGlTibC0X/AGNxbJ4r2kV7mHzuMV/aOHm+ksVZZjTcv4sq+KUNMNM8+ooor8KP5sCiiigAooooAKKKKACt/wAK+GNf8b+J/DngzwppdzrfijxdrukeGfDejWSh7zVte16/t9L0jTLVSQGuL6/ure1hBIBklXJFYFf0zf8ABvV+wJd/EP4lT/ts/EnRpo/Afwru7zR/gxb31uVt/FvxKkgmsdX8VW6y8XWkfD6ynltbScRNBL4y1CCWzvEv/B2oW9fT8H8M4zi/iHLsiwal/tVZPFVktMJgabUsXipdF7KlfkUv4lZ0qK96pFH2PAXB+P474qynhrARl/ttdPGYhK8cDltJqeOxs/sr2NC/s1K3tcRKjQXv1Yo/q4/ZT+BWlfsy/s3/AAY+A2j+S0Pwy8A6H4ev7q3/ANVqniMW/wBt8W64vyR8694pvNY1l/3afPfN8q9K+gqKK/0qwuGo4LC4bB4aCp4fCUKOGw9NbU6NCnGlSgvKMIpH+u2CweHy7B4TL8JTVHCYHDUMHhaUdqWHw1KNGjTXlCnCMV6BX4Uf8Fjf+CUNt+2n4V/4Xf8ABPT7Kw/af8DaMtp9gMlvp9j8Y/Cmn75IvCuqXU7w2tp4u0lXl/4Q/X7uSOCeNj4Y12ZdNk0jUvDf7r0V5XEXD2V8U5Rislzeh7bB4qPSyrUKsf4WJw1Sz9niKMvepys1vCcZ0pzhLxeK+Fcm40yLG8PZ9hvrGAxsd1aNfDV460cZhKrUvY4rDy96nOzXxU6kalGdSnL/ACePEPh7XvCWu6x4X8U6Nqnh3xJ4e1K80bXdB1uxudL1jRtW06d7W/03U9OvI4buyvrO5jkgubW4ijmhlRkdQwrGr/Q4/wCCin/BIv4Cft6WVz4xhMPwk/aEtrSOLTvi1oOlRXMXiNLSFYLTSfiVoMc1iniqxjgjitLLWFubTxNosMVrHbald6TaNoV1/FV+13/wTq/aw/Yo1i7h+M/w01H/AIQxLz7LpXxZ8JJceJPhfrgdxHavD4mtraP+xLq8Y4t9E8WWnh/X5NrsulmICVv4T478KuI+Ca9as6FTM8i5m6OcYWlKUIU+izClHmlgaq0TdT/Z5v8AhV5u8Y/5reJXgnxb4d4mvXlhquccN8zeHz7BUZTpwpX92OaUYc88urxVlKVX/ZKkn+4xNR80Y/DlFFFfl5+NhRRRQAUVv+GPCvifxtr+l+FPBnhzXfFvijW7lbLRvDnhnSL/AF7XtXvHyUtNM0jS4Lq/vrlgCVhtbeWQgE7eK/pH/YD/AODer4lfEO80X4k/tszXfws8BJLBf2/wY0e+gf4meK4VIlS38V6tZSXFj8P9Hu12C5tLWe/8ZyQG6spYPB9+sGoL9PwzwfxDxfjFg8iy6tiveSr4pp08DhE/t4rFyXsqWnvKF3WqWtRpVJe6fY8H8BcVcd4+OA4byqvjPfUcRjXF0stwMX/y8xuOkvY0Uo+8qd5YiqlahRqztE/OT/gmP/wTH+Jf/BQD4lwXNzBqvg/9nbwfqsA+J3xOEAi+0+UI7p/A3gZ7qN7fVPGmqW7xiaYR3On+EtPuU1vW0lkl0bRtd/0Hfhr8N/BPwf8AAPhL4X/Dfw9Y+FPAvgXQ7Hw54Y8P6arC103S9PiEcKb5Gee6uZTuub6/u5Z77Ub6a4v7+4uLy4nmc+G/w18A/B/wT4e+G/wv8JaH4F8C+FLFdN8P+GPDljFp+l6bahmkfZDGMy3N1O8t3f31y019qN9PcX9/cXF5cTTv3Ff3T4ceHGW8AZbKEJLG5zjVH+08z5eXm5dY4XCxfvUsHSlqk/3lep+9q/8ALqlR/wBJPCbwmynwvymdOnOOYcQZhGH9sZxycvPy6xwWCi/eo5fRlqk/3mJqfv69rUaNAooor9IP1sKKKKACqd/YWGq2V1puqWVpqWnX0EtrfWF/bw3lleWsylJra6tbhJILiCVCUkhlRo3UlWUirlFG+j1TBpNNNXT0aezXZn5TfHj/AIIr/wDBO/493N/q198Eofhf4l1De0viL4Katc/Dtkkk5eaPwpaJefDv7Q7/AL2S4m8GSzyyEtK77mz/ACn/ALev/BO/4K/st+Lb7Qfh/wCJ/ijq9pbPdKknjHWvCl/cnyDhdzaL4J8Px8/xYhHtiv8AQJr+On/gsR/yUjVv+u2o/wDoQr+UfG/JMlwNSNXBZRleDq1aXPUqYXAYXDzqTb1nOdKlGUpPrKTbP4l+kZw5w9ltWFfLsiybAVq1KNWtVwWWYLC1atSU/eqVJ0KEJTnLrKTbZ/PJ8LfhrofjfX20rVbrVre3F6Lffp89pFNs3hc7rixuk3f9s8e1f1c/sX/8EJP2H/H/AIM0n4kfES7+NfjiabyvP8Kap4+0jR/C02UEh3N4N8H+F/FS5+7+68UR/L0+b5q/mI/Z8/5HOT/sKL/6NFf6Cn7Av/JBNF/7Y/8ApOtfmXhZluXZhneGpY/AYLHUnXgnTxeFoYmDV9nCtCcX9x+PeCuUZVmnEWEo5nlmX5jRlXpKVLH4LD4um05vRwxFOpFr5Hq/wI/ZR/Zu/Zj0r+x/gL8F/APwyhkhFvd6h4e0OD/hJNVhBBVdd8XX/wBs8Va/t2ja2tazfsuBg8V9CUUV/emGwuFwVGGGweGoYTDUlanh8NRp0KNNdoUqUYwiv8KR/plg8Fg8uw9PB5fhMNgcJRXLRwuDoUsNh6Ue1OjRjCnBeUYoKKKK3OkKKKKAAP/Z" alt="JPG circle" ondragstart="event.dataTransfer.effectAllowed = 'copy'"/></p>
+<p>Drag circle above to the box below. It should be copied to the box once you drop it there.</p>
+<div
+ ondragenter="event.preventDefault()"
+ ondragover="return false"
+ ondrop="addImage(event)"
+/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/images/006.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/images/006.xhtml
new file mode 100644
index 00000000000..4011085ca06
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/images/006.xhtml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>dataURL image drag and drop from iframe</title>
+<style type="text/css">
+div[ondragenter]
+ {width:105px;
+ min-height:105px;
+ text-align:center;
+ margin-top:20px;
+ padding:10px;
+ border:solid thin navy;}
+iframe
+ {width:150px;
+ height:150px;
+ border-style:none;}
+</style>
+<script type="application/ecmascript">
+function addImage(event)
+ {var c = document.createElement('img');
+ c.setAttribute('src',event.dataTransfer.getData('text/uri-list').replace(/\r\n$/,''));
+ document.querySelector('div').appendChild(c);}
+</script>
+</head>
+<body>
+<p><iframe src="helper-drag-me-data-url-image.xhtml">XHTML with image</iframe></p>
+<p>Drag circle above to the box below. It should be copied to the box once you drop it there.</p>
+<div
+ ondragenter="event.preventDefault()"
+ ondragover="return false"
+ ondrop="addImage(event)"
+/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/images/007.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/images/007.xhtml
new file mode 100644
index 00000000000..e257a28c7b4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/images/007.xhtml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>dataURL image drag and drop to iframe</title>
+<style type="text/css">
+iframe
+ {width:160px;
+ height:160px;
+ border-style:none;}
+</style>
+</head>
+<body>
+<p><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAEq0lEQVR42u1dvU4bQRAeR0RCCilSp0peIoKGB4DSXYRDlcZlFClKBI4bB/kV/AymIDwCTahiicaioEOxhCsjWVTJziyKMfYZn+9ud3bvG2mEZB13u9+nndmf2Rki7fKFXtEBbVKD9o22jB4bPaND6hm9Mjo0enevw/vfevKMfbYl/8vv4HdBUkvFALhltG2A7dN3+pur8jv53fwN/hZkjjRo3eiuAatjdJA7CcnkDOSb/G1uQ6mFzUeDagaQrvl764yEJOU22LbUymXaGrRhOt40OvJOQvLIGUkbP9GLeIn4SM9NJ+tOTVI+Jq0ubY9sVFRNxy6DIWKWmEvpQ/ByQNumI+fBEjHrZ86lT8HJV3ptGn8aDRGzxJxKHwMZFe9Mg6+jJWNCyrX0VbUc0nuj4+jJmPiWsfRZodN+ZvSoNETMjpYjwUCFfKaXpjEnpSVjQsqJYOF5ZLw1elF6MiakXAgmnpw378DegIgZUm4EGw8jA2QsIuUbvXHpM2CmljFfhfsUO5uCA0/j6AudfZV5arv6WuVHcYs+ALwqKTkvHnmLoEwr8CJW9Llts9iNwvj3plzsfeWyIRnzrq37kfIzq6naBpA5a6bzlJgOl/SMkl+rklEFgIX5k5THwTYgIdwzcP2jhM/o19KsOeoArnBS6suaqo2gQnXCJWSwXNwXB4gBMFekNBeTwSGUmiMK4yNktDhsleNaAZRrUvYWmasuQHJOSDdpdKyriEIvo9maexWC70gAIF/bKTvzzFUH4HgbJZ3HdFSw9vC6lfKHpq7X8X07AOOblK2HhLQBindC2g/9Rx+gePcj/cnqHIDoUFm1c9gjwNAy/d0kyXIAMLSYrQ8kqScAhhbH3iLJBwIwtBByTJKkBWBoIeSMJHMOwNBCyG+SdEYAQ4tTvyLJMQUwtBAyJEn8BTC0EHIHQhQSApOlzGTBqaty6jzVAhhaCOlhYahuYYitE02EHGNzURchLZItX4ChhZB9HFBpUjmgwhGuHv0feI0gBw1T3j7CgHT5jzYC5XQRsjUdSsrhjADGl7ka0EylBgRb+ySkMy9rww7A8Waududf2MH9Qh9k3CbXLsGVNh/mqrvojuEeQHI+Qmq4Fq1ndIyeruaDxAEuCWk+ncmB0z3gepubtQenMUHyGTWELJl8xk6B15CeqVAyLtPXtUICsyJnVivWs+J0dAAwbzLOkQRTk2YuKsapTQFkXqPjlDILEinnRcZ1fpXdkGo866xqnH9FNyTjz0JIQZXcuPQCAE5rqo6oMEFBl7RknBRfTg8lj5Yl48JdGT0ueIWiYIvIuHFfPg9l85LJcF42b+JTUFjysZnyVlhy2qfA0asovTo9+0JxYnWC8t0KBQXuFYrdkIy3mBj3LbeNQrejZTuqOlbcl8znGTqcfjXoM3pboqgaPhEPxda1qgcVYsRt5TanDkgISWzcV1N1hCS3jdu4dNxUDMIhlBzXysHGGspkcBtsW2pPh3fGLrZ2ya5cXHFp0qxJ6si3E68EQCpy344vQRZxO5jfye+2d/oqgHsV02Z3lvcl9QTnA+EkLZw5h9MZcY4pTvxldXj/W0+esc+25H/5HQGYon+Q5f+MwFz+8QAAAABJRU5ErkJggg==" alt="PNG circle" ondragstart="event.dataTransfer.effectAllowed = 'copy'"/></p>
+<p>Drag circle above to the box below. It should be copied to the box once you drop it there.</p>
+<p><iframe src="helper-drop-image-here.xhtml">XHTML with image</iframe></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/images/008.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/images/008.xhtml
new file mode 100644
index 00000000000..b3f1042c918
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/images/008.xhtml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>dataURL image drag and drop between iframes</title>
+<style type="text/css">
+iframe
+ {width:160px;
+ height:160px;
+ border-style:none;}
+</style>
+</head>
+<body>
+<p><iframe src="helper-drag-me-data-url-image.xhtml">XHTML with image</iframe></p>
+<p>Drag circle above to the box below. It should be copied to the box once you drop it there.</p>
+<p><iframe src="helper-drop-image-here.xhtml">XHTML with image</iframe></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/images/009.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/images/009.xhtml
new file mode 100644
index 00000000000..c8da488e83d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/images/009.xhtml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Image drag and drop from iframe</title>
+<style type="text/css">
+div[ondragenter]
+ {width:105px;
+ min-height:105px;
+ text-align:center;
+ margin-top:20px;
+ padding:10px;
+ border:solid thin navy;}
+iframe
+ {width:150px;
+ height:150px;
+ border-style:none;}
+</style>
+<script type="application/ecmascript">
+function addImage(event)
+ {var c = document.createElement('img');
+ c.setAttribute('src',event.dataTransfer.getData('text/uri-list').replace(/\r\n$/,''));
+ document.querySelector('div').appendChild(c);}
+</script>
+</head>
+<body>
+<p><iframe src="helper-circle.xhtml">XHTML with image</iframe></p>
+<p>Drag circle above to the box below. It should be copied to the box once you drop it there.</p>
+<div
+ ondragenter="event.preventDefault()"
+ ondragover="return false"
+ ondrop="addImage(event)"
+/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/images/010.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/images/010.xhtml
new file mode 100644
index 00000000000..bec92d9f7c8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/images/010.xhtml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Image drag and drop to iframe</title>
+<style type="text/css">
+p:first-child
+ {padding-left:20px;}
+iframe
+ {width:160px;
+ height:160px;
+ border-style:none;}
+</style>
+</head>
+<body>
+<p><img src="../resources/circle.png" alt="PNG circle" ondragstart="event.dataTransfer.effectAllowed = 'copy'"/></p>
+<p>Drag circle above to the box below. It should be copied to the box once you drop it there.</p>
+<p><iframe src="helper-drop-image-here.xhtml">XHTML with image</iframe></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/images/011.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/images/011.xhtml
new file mode 100644
index 00000000000..4fa7c3eff8b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/images/011.xhtml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Image drag and drop between iframes</title>
+<style type="text/css">
+iframe
+ {width:160px;
+ height:160px;
+ border-style:none;}
+</style>
+</head>
+<body>
+<p><iframe src="helper-circle.xhtml">XHTML with image</iframe></p>
+<p>Drag circle above to the box below. It should be copied to the box once you drop it there.</p>
+<p><iframe src="helper-drop-image-here.xhtml">XHTML with image</iframe></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/images/012-1.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/images/012-1.xhtml
new file mode 100644
index 00000000000..3dc4f80641f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/images/012-1.xhtml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Image drag and drop: helper file</title>
+</head>
+<body>
+<p><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAEq0lEQVR42u1dvU4bQRAeR0RCCilSp0peIoKGB4DSXYRDlcZlFClKBI4bB/kV/AymIDwCTahiicaioEOxhCsjWVTJziyKMfYZn+9ud3bvG2mEZB13u9+nndmf2Rki7fKFXtEBbVKD9o22jB4bPaND6hm9Mjo0enevw/vfevKMfbYl/8vv4HdBUkvFALhltG2A7dN3+pur8jv53fwN/hZkjjRo3eiuAatjdJA7CcnkDOSb/G1uQ6mFzUeDagaQrvl764yEJOU22LbUymXaGrRhOt40OvJOQvLIGUkbP9GLeIn4SM9NJ+tOTVI+Jq0ubY9sVFRNxy6DIWKWmEvpQ/ByQNumI+fBEjHrZ86lT8HJV3ptGn8aDRGzxJxKHwMZFe9Mg6+jJWNCyrX0VbUc0nuj4+jJmPiWsfRZodN+ZvSoNETMjpYjwUCFfKaXpjEnpSVjQsqJYOF5ZLw1elF6MiakXAgmnpw378DegIgZUm4EGw8jA2QsIuUbvXHpM2CmljFfhfsUO5uCA0/j6AudfZV5arv6WuVHcYs+ALwqKTkvHnmLoEwr8CJW9Llts9iNwvj3plzsfeWyIRnzrq37kfIzq6naBpA5a6bzlJgOl/SMkl+rklEFgIX5k5THwTYgIdwzcP2jhM/o19KsOeoArnBS6suaqo2gQnXCJWSwXNwXB4gBMFekNBeTwSGUmiMK4yNktDhsleNaAZRrUvYWmasuQHJOSDdpdKyriEIvo9maexWC70gAIF/bKTvzzFUH4HgbJZ3HdFSw9vC6lfKHpq7X8X07AOOblK2HhLQBindC2g/9Rx+gePcj/cnqHIDoUFm1c9gjwNAy/d0kyXIAMLSYrQ8kqScAhhbH3iLJBwIwtBByTJKkBWBoIeSMJHMOwNBCyG+SdEYAQ4tTvyLJMQUwtBAyJEn8BTC0EHIHQhQSApOlzGTBqaty6jzVAhhaCOlhYahuYYitE02EHGNzURchLZItX4ChhZB9HFBpUjmgwhGuHv0feI0gBw1T3j7CgHT5jzYC5XQRsjUdSsrhjADGl7ka0EylBgRb+ySkMy9rww7A8Waududf2MH9Qh9k3CbXLsGVNh/mqrvojuEeQHI+Qmq4Fq1ndIyeruaDxAEuCWk+ncmB0z3gepubtQenMUHyGTWELJl8xk6B15CeqVAyLtPXtUICsyJnVivWs+J0dAAwbzLOkQRTk2YuKsapTQFkXqPjlDILEinnRcZ1fpXdkGo866xqnH9FNyTjz0JIQZXcuPQCAE5rqo6oMEFBl7RknBRfTg8lj5Yl48JdGT0ueIWiYIvIuHFfPg9l85LJcF42b+JTUFjysZnyVlhy2qfA0asovTo9+0JxYnWC8t0KBQXuFYrdkIy3mBj3LbeNQrejZTuqOlbcl8znGTqcfjXoM3pboqgaPhEPxda1qgcVYsRt5TanDkgISWzcV1N1hCS3jdu4dNxUDMIhlBzXysHGGspkcBtsW2pPh3fGLrZ2ya5cXHFp0qxJ6si3E68EQCpy344vQRZxO5jfye+2d/oqgHsV02Z3lvcl9QTnA+EkLZw5h9MZcY4pTvxldXj/W0+esc+25H/5HQGYon+Q5f+MwFz+8QAAAABJRU5ErkJggg==" alt="PNG circle" ondragstart="event.dataTransfer.effectAllowed = 'copy'"/></p>
+<p>Drag circle above to the box below. It should be copied to the box once you drop it there.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/images/012.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/images/012.xhtml
new file mode 100644
index 00000000000..d323d0a02ee
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/images/012.xhtml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop of dataURL image between frames</title>
+</head>
+<frameset rows="50%, 50%">
+<frame src="012-1.xhtml"/>
+<frame src="helper-drop-image-here.xhtml"/>
+</frameset>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/images/013-1.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/images/013-1.xhtml
new file mode 100644
index 00000000000..7a78528c846
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/images/013-1.xhtml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Image drag and drop: helper file</title>
+</head>
+<body>
+<p><img src="../resources/circle.png" alt="PNG circle" ondragstart="event.dataTransfer.effectAllowed = 'copy'"/></p>
+<p>Drag circle above to the box below. It should be copied to the box once you drop it there.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/images/013.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/images/013.xhtml
new file mode 100644
index 00000000000..ffa7f3b74b5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/images/013.xhtml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop of image between frames</title>
+</head>
+<frameset rows="50%, 50%">
+<frame src="013-1.xhtml"/>
+<frame src="helper-drop-image-here.xhtml"/>
+</frameset>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/images/014-1.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/images/014-1.xhtml
new file mode 100644
index 00000000000..a433bde987f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/images/014-1.xhtml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Image drag and drop: helper file</title>
+<style type="text/css">
+div[ondragenter]
+ {width:105px;
+ min-height:105px;
+ text-align:center;
+ margin-top:20px;
+ padding:10px;
+ background-color:silver;}
+p:first-child
+ {padding-left:12px;}
+</style>
+<script type="application/ecmascript">
+function addImage(event)
+ {var c = document.createElement('img');
+ c.setAttribute('src',event.dataTransfer.getData('text/uri-list').replace(/\r\n$/,''));
+ document.querySelector('div').appendChild(c);}
+</script>
+</head>
+<body>
+<p><img src="../resources/circle.png" alt="PNG circle" ondragstart="event.dataTransfer.effectAllowed = 'copy'"/></p>
+<p>Drag circle from one frame to the silver box in <strong>another</strong> frame. It should be copied to the box once you drop it there.</p>
+<div
+ ondragenter="event.preventDefault()"
+ ondragover="return false"
+ ondrop="addImage(event)"
+/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/images/014.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/images/014.xhtml
new file mode 100644
index 00000000000..1acb985a8d5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/images/014.xhtml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop of image between two instances of document</title>
+</head>
+<frameset rows="50%, 50%">
+<frame src="014-1.xhtml"/>
+<frame src="014-1.xhtml"/>
+</frameset>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/images/015.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/images/015.xhtml
new file mode 100644
index 00000000000..656f059530e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/images/015.xhtml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Dropping image on horizontal scrollbar of a scrollable block element</title>
+<style type="text/css">
+div[ondragenter]
+ {width:3em;
+ height:3em;
+ margin-top:1em;
+ font-size:1.5em;
+ white-space:nowrap;
+ overflow-x:scroll;}
+p:first-child
+ {padding-left:1em;}
+img
+ {width:5px;
+ height:5px;}
+</style>
+<script type="application/ecmascript">
+function checkImage(event)
+ {document.querySelector('div').firstChild.nodeValue = (document.querySelector('img').getAttribute('src') == event.dataTransfer.getData('text/uri-list').replace(/\r\n$/,''))?'PASS':'FAIL';}
+</script>
+</head>
+<body>
+<p><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAEElEQVR42mNgaGD4D8YwBgAw9AX9Y9zBwwAAAABJRU5ErkJggg==" alt="PNG green pixel" ondragstart="event.dataTransfer.effectAllowed = 'copy'"/></p>
+<p>Drag little square above and drop it on scrollbar below. You should see word PASS when you drop it on scrollbar.</p>
+<div ondragenter="event.preventDefault()" ondragover="return false" ondrop="checkImage(event)">↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓</div>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/images/016.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/images/016.xhtml
new file mode 100644
index 00000000000..3479c8f5013
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/images/016.xhtml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Dropping image on vertical scrollbar of a scrollable block element</title>
+<style type="text/css">
+div[ondragenter]
+ {width:2em;
+ height:5em;
+ margin-top:1em;
+ font-size:1.5em;
+ overflow-y:scroll;}
+p:first-child
+ {padding-left:1em;}
+img
+ {width:5px;
+ height:5px;}
+</style>
+<script type="application/ecmascript">
+function checkImage(event)
+ {document.querySelector('div').firstChild.nodeValue = (document.querySelector('img').getAttribute('src') == event.dataTransfer.getData('text/uri-list').replace(/\r\n$/,''))?'P A S S':'F A I L';}
+</script>
+</head>
+<body>
+<p><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAEElEQVR42mNgaGD4D8YwBgAw9AX9Y9zBwwAAAABJRU5ErkJggg==" alt="PNG green pixel" ondragstart="event.dataTransfer.effectAllowed = 'copy'"/></p>
+<p>Drag little square above and drop it on scrollbar below. You should see word PASS when you drop it on scrollbar.</p>
+<div ondragenter="event.preventDefault()" ondragover="return false" ondrop="checkImage(event)">→ → → → → → → → → → → → → → → → → → → →</div>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/images/017.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/images/017.xhtml
new file mode 100644
index 00000000000..0231c719e28
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/images/017.xhtml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Dropping image on horizontal page scrollbar</title>
+<style type="text/css">
+p:first-child
+ {padding-left:1em;}
+div
+ {position:fixed;
+ bottom:0;
+ left:0;}
+img
+ {width:5px;
+ height:5px;}
+body
+ {width:3000px;}
+</style>
+<script type="application/ecmascript">
+function dragImage()
+ {event.dataTransfer.effectAllowed = 'copy';}
+function dropImage(event)
+ {document.querySelector('div').firstChild.nodeValue = 'PASS';}
+</script>
+</head>
+<body ondragenter="event.preventDefault()" ondragover="return false">
+<p><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAEElEQVR42mNgaGD4D8YwBgAw9AX9Y9zBwwAAAABJRU5ErkJggg==" alt="PNG green pixel" ondragstart="dragImage()" ondragend="dropImage(event)"/></p>
+<p>Drag little square above and drop it on vertical scrollbar. Word PASS should appear near scrollbar once you drop it.</p>
+<div>↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓</div>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/images/018.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/images/018.xhtml
new file mode 100644
index 00000000000..a4b6cca356e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/images/018.xhtml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Dropping image on vertical page scrollbar</title>
+<style type="text/css">
+p:first-child
+ {padding-left:1em;}
+div
+ {width:1ex;
+ margin-left:auto;}
+img
+ {width:5px;
+ height:5px;}
+body
+ {height:3000px;}
+</style>
+<script type="application/ecmascript">
+function dragImage()
+ {event.dataTransfer.effectAllowed = 'copy';}
+function dropImage(event)
+ {document.querySelector('div').firstChild.nodeValue = 'P A S S';}
+</script>
+</head>
+<body ondragenter="event.preventDefault()" ondragover="return false">
+<p><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAEElEQVR42mNgaGD4D8YwBgAw9AX9Y9zBwwAAAABJRU5ErkJggg==" alt="PNG green pixel" ondragstart="dragImage()" ondragend="dropImage(event)"/></p>
+<p>Drag little square above and drop it on vertical scrollbar. Word PASS should appear near scrollbar once you drop it.</p>
+<div>→ → → → → → → → → → → → → → → → → → → → → → → → → → → → → → → → → → → →</div>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/images/021.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/images/021.xhtml
new file mode 100644
index 00000000000..33acd920350
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/images/021.xhtml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Dropping image on horizontal iframe scrollbar</title>
+<style type="text/css">
+p:first-child
+ {padding-left:1em;}
+iframe
+ {height:3em;
+ width:4em;}
+img
+ {width:5px;
+ height:5px;}
+</style>
+<script type="application/ecmascript">
+function dragImage()
+ {event.dataTransfer.effectAllowed = 'copy';}
+function dropImage(event)
+ {document.querySelector('p + p').firstChild.nodeValue = 'PASS';}
+</script>
+</head>
+<body ondragenter="event.preventDefault()" ondragover="return false">
+<p><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAEElEQVR42mNgaGD4D8YwBgAw9AX9Y9zBwwAAAABJRU5ErkJggg==" alt="PNG green pixel" ondragstart="dragImage()" ondragend="dropImage(event)"/></p>
+<p>Drag little square above and drop it on horizontal scrollbar. Word PASS should appear once you drop it.</p>
+<iframe src="helper-drop-horizontal-scrollbar.xhtml">XHTML document</iframe>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/images/022.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/images/022.xhtml
new file mode 100644
index 00000000000..41edef04af4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/images/022.xhtml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Dropping image on vertical iframe scrollbar</title>
+<style type="text/css">
+p:first-child
+ {padding-left:1em;}
+iframe
+ {height:6em;
+ width:3em;}
+img
+ {width:5px;
+ height:5px;}
+</style>
+<script type="application/ecmascript">
+function dragImage()
+ {event.dataTransfer.effectAllowed = 'copy';}
+function dropImage(event)
+ {document.querySelector('p + p').firstChild.nodeValue = 'PASS';}
+</script>
+</head>
+<body ondragenter="event.preventDefault()" ondragover="return false">
+<p><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAEElEQVR42mNgaGD4D8YwBgAw9AX9Y9zBwwAAAABJRU5ErkJggg==" alt="PNG green pixel" ondragstart="dragImage()" ondragend="dropImage(event)"/></p>
+<p>Drag little square above and drop it on vertical scrollbar. Word PASS should appear once you drop it.</p>
+<iframe src="helper-drop-vertical-scrollbar.xhtml">XHTML document</iframe>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/images/023.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/images/023.xhtml
new file mode 100644
index 00000000000..a282570d0e5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/images/023.xhtml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Dropping image on horizontal object scrollbar</title>
+<style type="text/css">
+p:first-child
+ {padding-left:1em;}
+object
+ {height:3em;
+ width:4em;}
+img
+ {width:5px;
+ height:5px;}
+</style>
+<script type="application/ecmascript">
+function dragImage()
+ {event.dataTransfer.effectAllowed = 'copy';}
+function dropImage(event)
+ {document.querySelector('p + p').firstChild.nodeValue = 'PASS';}
+</script>
+</head>
+<body ondragenter="event.preventDefault()" ondragover="return false">
+<p><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAEElEQVR42mNgaGD4D8YwBgAw9AX9Y9zBwwAAAABJRU5ErkJggg==" alt="PNG green pixel" ondragstart="dragImage()" ondragend="dropImage(event)"/></p>
+<p>Drag little square above and drop it on horizontal scrollbar. Word PASS should appear once you drop it.</p>
+<object type="application/xhtml+xml" data="helper-drop-horizontal-scrollbar.xhtml">XHTML document</object>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/images/024.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/images/024.xhtml
new file mode 100644
index 00000000000..789f8ea8b2a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/images/024.xhtml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Dropping image on vertical object scrollbar</title>
+<style type="text/css">
+p:first-child
+ {padding-left:1em;}
+object
+ {height:6em;
+ width:3em;}
+img
+ {width:5px;
+ height:5px;}
+</style>
+<script type="application/ecmascript">
+function dragImage()
+ {event.dataTransfer.effectAllowed = 'copy';}
+function dropImage(event)
+ {document.querySelector('p + p').firstChild.nodeValue = 'PASS';}
+</script>
+</head>
+<body ondragenter="event.preventDefault()" ondragover="return false">
+<p><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAEElEQVR42mNgaGD4D8YwBgAw9AX9Y9zBwwAAAABJRU5ErkJggg==" alt="PNG green pixel" ondragstart="dragImage()" ondragend="dropImage(event)"/></p>
+<p>Drag little square above and drop it on vertical scrollbar. Word PASS should appear once you drop it.</p>
+<object type="application/xhtml+xml" data="helper-drop-vertical-scrollbar.xhtml">XHTML document</object>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/images/025.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/images/025.xhtml
new file mode 100644
index 00000000000..d0b44383001
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/images/025.xhtml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop of image to scrollable container with horizontal scrollbar</title>
+<style type="text/css">
+p + div
+ {height:150px;
+ width:150px;
+ overflow-x:scroll;}
+div[ondragenter]
+ {margin-left:200px;
+ width:105px;
+ min-height:105px;
+ text-align:center;
+ padding:10px;
+ background-color:silver;}
+p:first-child
+ {padding-left:12px;}
+</style>
+<script type="application/ecmascript">
+function addImage(event)
+ {var c = document.createElement('img');
+ c.setAttribute('src',event.dataTransfer.getData('text/uri-list').replace(/\r\n$/,''));
+ document.querySelector('div > div').appendChild(c);}
+</script>
+</head>
+<body>
+<p><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAEq0lEQVR42u1dvU4bQRAeR0RCCilSp0peIoKGB4DSXYRDlcZlFClKBI4bB/kV/AymIDwCTahiicaioEOxhCsjWVTJziyKMfYZn+9ud3bvG2mEZB13u9+nndmf2Rki7fKFXtEBbVKD9o22jB4bPaND6hm9Mjo0enevw/vfevKMfbYl/8vv4HdBUkvFALhltG2A7dN3+pur8jv53fwN/hZkjjRo3eiuAatjdJA7CcnkDOSb/G1uQ6mFzUeDagaQrvl764yEJOU22LbUymXaGrRhOt40OvJOQvLIGUkbP9GLeIn4SM9NJ+tOTVI+Jq0ubY9sVFRNxy6DIWKWmEvpQ/ByQNumI+fBEjHrZ86lT8HJV3ptGn8aDRGzxJxKHwMZFe9Mg6+jJWNCyrX0VbUc0nuj4+jJmPiWsfRZodN+ZvSoNETMjpYjwUCFfKaXpjEnpSVjQsqJYOF5ZLw1elF6MiakXAgmnpw378DegIgZUm4EGw8jA2QsIuUbvXHpM2CmljFfhfsUO5uCA0/j6AudfZV5arv6WuVHcYs+ALwqKTkvHnmLoEwr8CJW9Llts9iNwvj3plzsfeWyIRnzrq37kfIzq6naBpA5a6bzlJgOl/SMkl+rklEFgIX5k5THwTYgIdwzcP2jhM/o19KsOeoArnBS6suaqo2gQnXCJWSwXNwXB4gBMFekNBeTwSGUmiMK4yNktDhsleNaAZRrUvYWmasuQHJOSDdpdKyriEIvo9maexWC70gAIF/bKTvzzFUH4HgbJZ3HdFSw9vC6lfKHpq7X8X07AOOblK2HhLQBindC2g/9Rx+gePcj/cnqHIDoUFm1c9gjwNAy/d0kyXIAMLSYrQ8kqScAhhbH3iLJBwIwtBByTJKkBWBoIeSMJHMOwNBCyG+SdEYAQ4tTvyLJMQUwtBAyJEn8BTC0EHIHQhQSApOlzGTBqaty6jzVAhhaCOlhYahuYYitE02EHGNzURchLZItX4ChhZB9HFBpUjmgwhGuHv0feI0gBw1T3j7CgHT5jzYC5XQRsjUdSsrhjADGl7ka0EylBgRb+ySkMy9rww7A8Waududf2MH9Qh9k3CbXLsGVNh/mqrvojuEeQHI+Qmq4Fq1ndIyeruaDxAEuCWk+ncmB0z3gepubtQenMUHyGTWELJl8xk6B15CeqVAyLtPXtUICsyJnVivWs+J0dAAwbzLOkQRTk2YuKsapTQFkXqPjlDILEinnRcZ1fpXdkGo866xqnH9FNyTjz0JIQZXcuPQCAE5rqo6oMEFBl7RknBRfTg8lj5Yl48JdGT0ueIWiYIvIuHFfPg9l85LJcF42b+JTUFjysZnyVlhy2qfA0asovTo9+0JxYnWC8t0KBQXuFYrdkIy3mBj3LbeNQrejZTuqOlbcl8znGTqcfjXoM3pboqgaPhEPxda1qgcVYsRt5TanDkgISWzcV1N1hCS3jdu4dNxUDMIhlBzXysHGGspkcBtsW2pPh3fGLrZ2ya5cXHFp0qxJ6si3E68EQCpy344vQRZxO5jfye+2d/oqgHsV02Z3lvcl9QTnA+EkLZw5h9MZcY4pTvxldXj/W0+esc+25H/5HQGYon+Q5f+MwFz+8QAAAABJRU5ErkJggg==" alt="PNG circle" ondragstart="event.dataTransfer.effectAllowed = 'copy'"/></p>
+<p>Drag circle above to the silver box inside scrollable container below (dragging towards edge of container triggers scrolling).</p>
+<p>It should be copied to the silver box once you drop it there.</p>
+<div>
+ <div
+ ondragenter="event.preventDefault()"
+ ondragover="return false"
+ ondrop="addImage(event)"
+ />
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/images/026.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/images/026.xhtml
new file mode 100644
index 00000000000..68ad4eb953b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/images/026.xhtml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop of image to scrollable container with vertical scrollbar</title>
+<style type="text/css">
+p + div
+ {height:150px;
+ width:150px;
+ overflow-y:scroll;}
+div[ondragenter]
+ {margin-top:200px;
+ width:105px;
+ min-height:105px;
+ text-align:center;
+ padding:10px;
+ background-color:silver;}
+p:first-child
+ {padding-left:12px;}
+</style>
+<script type="application/ecmascript">
+function addImage(event)
+ {var c = document.createElement('img');
+ c.setAttribute('src',event.dataTransfer.getData('text/uri-list').replace(/\r\n$/,''));
+ document.querySelector('div > div').appendChild(c);}
+</script>
+</head>
+<body>
+<p><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAEq0lEQVR42u1dvU4bQRAeR0RCCilSp0peIoKGB4DSXYRDlcZlFClKBI4bB/kV/AymIDwCTahiicaioEOxhCsjWVTJziyKMfYZn+9ud3bvG2mEZB13u9+nndmf2Rki7fKFXtEBbVKD9o22jB4bPaND6hm9Mjo0enevw/vfevKMfbYl/8vv4HdBUkvFALhltG2A7dN3+pur8jv53fwN/hZkjjRo3eiuAatjdJA7CcnkDOSb/G1uQ6mFzUeDagaQrvl764yEJOU22LbUymXaGrRhOt40OvJOQvLIGUkbP9GLeIn4SM9NJ+tOTVI+Jq0ubY9sVFRNxy6DIWKWmEvpQ/ByQNumI+fBEjHrZ86lT8HJV3ptGn8aDRGzxJxKHwMZFe9Mg6+jJWNCyrX0VbUc0nuj4+jJmPiWsfRZodN+ZvSoNETMjpYjwUCFfKaXpjEnpSVjQsqJYOF5ZLw1elF6MiakXAgmnpw378DegIgZUm4EGw8jA2QsIuUbvXHpM2CmljFfhfsUO5uCA0/j6AudfZV5arv6WuVHcYs+ALwqKTkvHnmLoEwr8CJW9Llts9iNwvj3plzsfeWyIRnzrq37kfIzq6naBpA5a6bzlJgOl/SMkl+rklEFgIX5k5THwTYgIdwzcP2jhM/o19KsOeoArnBS6suaqo2gQnXCJWSwXNwXB4gBMFekNBeTwSGUmiMK4yNktDhsleNaAZRrUvYWmasuQHJOSDdpdKyriEIvo9maexWC70gAIF/bKTvzzFUH4HgbJZ3HdFSw9vC6lfKHpq7X8X07AOOblK2HhLQBindC2g/9Rx+gePcj/cnqHIDoUFm1c9gjwNAy/d0kyXIAMLSYrQ8kqScAhhbH3iLJBwIwtBByTJKkBWBoIeSMJHMOwNBCyG+SdEYAQ4tTvyLJMQUwtBAyJEn8BTC0EHIHQhQSApOlzGTBqaty6jzVAhhaCOlhYahuYYitE02EHGNzURchLZItX4ChhZB9HFBpUjmgwhGuHv0feI0gBw1T3j7CgHT5jzYC5XQRsjUdSsrhjADGl7ka0EylBgRb+ySkMy9rww7A8Waududf2MH9Qh9k3CbXLsGVNh/mqrvojuEeQHI+Qmq4Fq1ndIyeruaDxAEuCWk+ncmB0z3gepubtQenMUHyGTWELJl8xk6B15CeqVAyLtPXtUICsyJnVivWs+J0dAAwbzLOkQRTk2YuKsapTQFkXqPjlDILEinnRcZ1fpXdkGo866xqnH9FNyTjz0JIQZXcuPQCAE5rqo6oMEFBl7RknBRfTg8lj5Yl48JdGT0ueIWiYIvIuHFfPg9l85LJcF42b+JTUFjysZnyVlhy2qfA0asovTo9+0JxYnWC8t0KBQXuFYrdkIy3mBj3LbeNQrejZTuqOlbcl8znGTqcfjXoM3pboqgaPhEPxda1qgcVYsRt5TanDkgISWzcV1N1hCS3jdu4dNxUDMIhlBzXysHGGspkcBtsW2pPh3fGLrZ2ya5cXHFp0qxJ6si3E68EQCpy344vQRZxO5jfye+2d/oqgHsV02Z3lvcl9QTnA+EkLZw5h9MZcY4pTvxldXj/W0+esc+25H/5HQGYon+Q5f+MwFz+8QAAAABJRU5ErkJggg==" alt="PNG circle" ondragstart="event.dataTransfer.effectAllowed = 'copy'"/></p>
+<p>Drag circle above to the silver box inside scrollable container below (dragging towards edge of container triggers scrolling).</p>
+<p>It should be copied to the silver box once you drop it there.</p>
+<div>
+↓↓↓↓↓↓↓↓↓
+ <div
+ ondragenter="event.preventDefault()"
+ ondragover="return false"
+ ondrop="addImage(event)"
+ />
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/images/027.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/images/027.xhtml
new file mode 100644
index 00000000000..51428a1ac3f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/images/027.xhtml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop of image to scrollable container</title>
+<style type="text/css">
+p + div
+ {height:150px;
+ width:150px;
+ overflow:scroll;}
+div[ondragenter]
+ {margin:200px 0 0 200px;
+ width:105px;
+ min-height:105px;
+ text-align:center;
+ padding:10px;
+ background-color:silver;}
+p:first-child
+ {padding-left:12px;}
+</style>
+<script type="application/ecmascript">
+function addImage(event)
+ {var c = document.createElement('img');
+ c.setAttribute('src',event.dataTransfer.getData('text/uri-list').replace(/\r\n$/,''));
+ document.querySelector('div > div').appendChild(c);}
+</script>
+</head>
+<body>
+<p><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAEq0lEQVR42u1dvU4bQRAeR0RCCilSp0peIoKGB4DSXYRDlcZlFClKBI4bB/kV/AymIDwCTahiicaioEOxhCsjWVTJziyKMfYZn+9ud3bvG2mEZB13u9+nndmf2Rki7fKFXtEBbVKD9o22jB4bPaND6hm9Mjo0enevw/vfevKMfbYl/8vv4HdBUkvFALhltG2A7dN3+pur8jv53fwN/hZkjjRo3eiuAatjdJA7CcnkDOSb/G1uQ6mFzUeDagaQrvl764yEJOU22LbUymXaGrRhOt40OvJOQvLIGUkbP9GLeIn4SM9NJ+tOTVI+Jq0ubY9sVFRNxy6DIWKWmEvpQ/ByQNumI+fBEjHrZ86lT8HJV3ptGn8aDRGzxJxKHwMZFe9Mg6+jJWNCyrX0VbUc0nuj4+jJmPiWsfRZodN+ZvSoNETMjpYjwUCFfKaXpjEnpSVjQsqJYOF5ZLw1elF6MiakXAgmnpw378DegIgZUm4EGw8jA2QsIuUbvXHpM2CmljFfhfsUO5uCA0/j6AudfZV5arv6WuVHcYs+ALwqKTkvHnmLoEwr8CJW9Llts9iNwvj3plzsfeWyIRnzrq37kfIzq6naBpA5a6bzlJgOl/SMkl+rklEFgIX5k5THwTYgIdwzcP2jhM/o19KsOeoArnBS6suaqo2gQnXCJWSwXNwXB4gBMFekNBeTwSGUmiMK4yNktDhsleNaAZRrUvYWmasuQHJOSDdpdKyriEIvo9maexWC70gAIF/bKTvzzFUH4HgbJZ3HdFSw9vC6lfKHpq7X8X07AOOblK2HhLQBindC2g/9Rx+gePcj/cnqHIDoUFm1c9gjwNAy/d0kyXIAMLSYrQ8kqScAhhbH3iLJBwIwtBByTJKkBWBoIeSMJHMOwNBCyG+SdEYAQ4tTvyLJMQUwtBAyJEn8BTC0EHIHQhQSApOlzGTBqaty6jzVAhhaCOlhYahuYYitE02EHGNzURchLZItX4ChhZB9HFBpUjmgwhGuHv0feI0gBw1T3j7CgHT5jzYC5XQRsjUdSsrhjADGl7ka0EylBgRb+ySkMy9rww7A8Waududf2MH9Qh9k3CbXLsGVNh/mqrvojuEeQHI+Qmq4Fq1ndIyeruaDxAEuCWk+ncmB0z3gepubtQenMUHyGTWELJl8xk6B15CeqVAyLtPXtUICsyJnVivWs+J0dAAwbzLOkQRTk2YuKsapTQFkXqPjlDILEinnRcZ1fpXdkGo866xqnH9FNyTjz0JIQZXcuPQCAE5rqo6oMEFBl7RknBRfTg8lj5Yl48JdGT0ueIWiYIvIuHFfPg9l85LJcF42b+JTUFjysZnyVlhy2qfA0asovTo9+0JxYnWC8t0KBQXuFYrdkIy3mBj3LbeNQrejZTuqOlbcl8znGTqcfjXoM3pboqgaPhEPxda1qgcVYsRt5TanDkgISWzcV1N1hCS3jdu4dNxUDMIhlBzXysHGGspkcBtsW2pPh3fGLrZ2ya5cXHFp0qxJ6si3E68EQCpy344vQRZxO5jfye+2d/oqgHsV02Z3lvcl9QTnA+EkLZw5h9MZcY4pTvxldXj/W0+esc+25H/5HQGYon+Q5f+MwFz+8QAAAABJRU5ErkJggg==" alt="PNG circle" ondragstart="event.dataTransfer.effectAllowed = 'copy'"/></p>
+<p>Drag circle above to the silver box inside scrollable container below (dragging towards edge of container triggers scrolling).</p>
+<p>It should be copied to the silver box once you drop it there.</p>
+<div>
+↘
+ <div
+ ondragenter="event.preventDefault()"
+ ondragover="return false"
+ ondrop="addImage(event)"
+ />
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/images/028.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/images/028.xhtml
new file mode 100644
index 00000000000..1bb7a5e9370
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/images/028.xhtml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Image drag and drop and url alias</title>
+<style type="text/css">
+div[ondragenter]
+ {width:105px;
+ min-height:105px;
+ text-align:center;
+ margin-top:20px;
+ padding:10px;
+ border:solid thin navy;}
+p:first-child
+ {padding-left:12px;}
+</style>
+<script type="application/ecmascript">
+function addImage(event)
+ {var c = document.createElement('img');
+ c.setAttribute('src',event.dataTransfer.getData('url'));
+ document.querySelector('div').appendChild(c);}
+</script>
+</head>
+<body>
+<p><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAEq0lEQVR42u1dvU4bQRAeR0RCCilSp0peIoKGB4DSXYRDlcZlFClKBI4bB/kV/AymIDwCTahiicaioEOxhCsjWVTJziyKMfYZn+9ud3bvG2mEZB13u9+nndmf2Rki7fKFXtEBbVKD9o22jB4bPaND6hm9Mjo0enevw/vfevKMfbYl/8vv4HdBUkvFALhltG2A7dN3+pur8jv53fwN/hZkjjRo3eiuAatjdJA7CcnkDOSb/G1uQ6mFzUeDagaQrvl764yEJOU22LbUymXaGrRhOt40OvJOQvLIGUkbP9GLeIn4SM9NJ+tOTVI+Jq0ubY9sVFRNxy6DIWKWmEvpQ/ByQNumI+fBEjHrZ86lT8HJV3ptGn8aDRGzxJxKHwMZFe9Mg6+jJWNCyrX0VbUc0nuj4+jJmPiWsfRZodN+ZvSoNETMjpYjwUCFfKaXpjEnpSVjQsqJYOF5ZLw1elF6MiakXAgmnpw378DegIgZUm4EGw8jA2QsIuUbvXHpM2CmljFfhfsUO5uCA0/j6AudfZV5arv6WuVHcYs+ALwqKTkvHnmLoEwr8CJW9Llts9iNwvj3plzsfeWyIRnzrq37kfIzq6naBpA5a6bzlJgOl/SMkl+rklEFgIX5k5THwTYgIdwzcP2jhM/o19KsOeoArnBS6suaqo2gQnXCJWSwXNwXB4gBMFekNBeTwSGUmiMK4yNktDhsleNaAZRrUvYWmasuQHJOSDdpdKyriEIvo9maexWC70gAIF/bKTvzzFUH4HgbJZ3HdFSw9vC6lfKHpq7X8X07AOOblK2HhLQBindC2g/9Rx+gePcj/cnqHIDoUFm1c9gjwNAy/d0kyXIAMLSYrQ8kqScAhhbH3iLJBwIwtBByTJKkBWBoIeSMJHMOwNBCyG+SdEYAQ4tTvyLJMQUwtBAyJEn8BTC0EHIHQhQSApOlzGTBqaty6jzVAhhaCOlhYahuYYitE02EHGNzURchLZItX4ChhZB9HFBpUjmgwhGuHv0feI0gBw1T3j7CgHT5jzYC5XQRsjUdSsrhjADGl7ka0EylBgRb+ySkMy9rww7A8Waududf2MH9Qh9k3CbXLsGVNh/mqrvojuEeQHI+Qmq4Fq1ndIyeruaDxAEuCWk+ncmB0z3gepubtQenMUHyGTWELJl8xk6B15CeqVAyLtPXtUICsyJnVivWs+J0dAAwbzLOkQRTk2YuKsapTQFkXqPjlDILEinnRcZ1fpXdkGo866xqnH9FNyTjz0JIQZXcuPQCAE5rqo6oMEFBl7RknBRfTg8lj5Yl48JdGT0ueIWiYIvIuHFfPg9l85LJcF42b+JTUFjysZnyVlhy2qfA0asovTo9+0JxYnWC8t0KBQXuFYrdkIy3mBj3LbeNQrejZTuqOlbcl8znGTqcfjXoM3pboqgaPhEPxda1qgcVYsRt5TanDkgISWzcV1N1hCS3jdu4dNxUDMIhlBzXysHGGspkcBtsW2pPh3fGLrZ2ya5cXHFp0qxJ6si3E68EQCpy344vQRZxO5jfye+2d/oqgHsV02Z3lvcl9QTnA+EkLZw5h9MZcY4pTvxldXj/W0+esc+25H/5HQGYon+Q5f+MwFz+8QAAAABJRU5ErkJggg==" alt="PNG circle" ondragstart="event.dataTransfer.effectAllowed = 'copy'"/></p>
+<p>Drag circle above outside the window and then back inside and drop in the box below. It should be copied to the box once you drop it there.</p>
+<div
+ ondragenter="event.preventDefault()"
+ ondragover="return false"
+ ondrop="addImage(event)"
+/>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/images/cross-domain/001.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/images/cross-domain/001.xhtml
new file mode 100644
index 00000000000..9eb5c7be32a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/images/cross-domain/001.xhtml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Cross-domain image data must not populate the dataTransfer</title>
+<script src="../../resources/crossorigin.js"></script>
+<style type="text/css">
+div {
+ width:105px;
+ min-height:105px;
+ text-align:center;
+ margin-top:20px;
+ padding:10px;
+ border:solid thin navy;
+}
+</style>
+</head>
+<body>
+<p><img id="image" draggable="true" alt="" width="100" height="100" /></p>
+<p>Drag the navy square above to the box below.</p>
+<div></div>
+<script><![CDATA[
+
+document.getElementsByTagName("img")[0].src = crossOriginUrl("www", "../../resources/100x100-navy.png");
+
+window.onload = function() {
+ var image = document.getElementsByTagName('img')[0], div = document.getElementsByTagName('div')[0], failed = [];
+ div.ondragover = div.ondragenter = function(e) {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'copy';
+ };
+ div.ondrop = image.ondragstart = function(e) {
+ if( e.type == 'dragstart' ) {
+ e.dataTransfer.setData('Text', 'dummy text');
+ e.dataTransfer.dropEffect = 'copy';
+ }
+ for( var i = 0; i < e.dataTransfer.types.length; i++ ) {
+ if( e.dataTransfer.types[i].match(/image\//) ) {
+ failed[failed.length] = e.dataTransfer.types[i];
+ }
+ }
+ if( e.type == 'drop' ) {
+ e.preventDefault();
+ document.getElementsByTagName('p')[1].innerHTML = failed.length ? ( 'FAIL (found ' + failed.join() + ')' ) : 'PASS';
+ }
+ };
+};
+]]></script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/images/helper-circle.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/images/helper-circle.xhtml
new file mode 100644
index 00000000000..1df3ee3fa68
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/images/helper-circle.xhtml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Image drag and drop: helper file</title>
+</head>
+<body>
+<p><img src="../resources/circle.png" alt="PNG circle" ondragstart="event.dataTransfer.effectAllowed = 'copy'"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/images/helper-drag-me-data-url-image.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/images/helper-drag-me-data-url-image.xhtml
new file mode 100644
index 00000000000..640b42b4dfb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/images/helper-drag-me-data-url-image.xhtml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Image drag and drop: helper file</title>
+</head>
+<body>
+<p><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAEq0lEQVR42u1dvU4bQRAeR0RCCilSp0peIoKGB4DSXYRDlcZlFClKBI4bB/kV/AymIDwCTahiicaioEOxhCsjWVTJziyKMfYZn+9ud3bvG2mEZB13u9+nndmf2Rki7fKFXtEBbVKD9o22jB4bPaND6hm9Mjo0enevw/vfevKMfbYl/8vv4HdBUkvFALhltG2A7dN3+pur8jv53fwN/hZkjjRo3eiuAatjdJA7CcnkDOSb/G1uQ6mFzUeDagaQrvl764yEJOU22LbUymXaGrRhOt40OvJOQvLIGUkbP9GLeIn4SM9NJ+tOTVI+Jq0ubY9sVFRNxy6DIWKWmEvpQ/ByQNumI+fBEjHrZ86lT8HJV3ptGn8aDRGzxJxKHwMZFe9Mg6+jJWNCyrX0VbUc0nuj4+jJmPiWsfRZodN+ZvSoNETMjpYjwUCFfKaXpjEnpSVjQsqJYOF5ZLw1elF6MiakXAgmnpw378DegIgZUm4EGw8jA2QsIuUbvXHpM2CmljFfhfsUO5uCA0/j6AudfZV5arv6WuVHcYs+ALwqKTkvHnmLoEwr8CJW9Llts9iNwvj3plzsfeWyIRnzrq37kfIzq6naBpA5a6bzlJgOl/SMkl+rklEFgIX5k5THwTYgIdwzcP2jhM/o19KsOeoArnBS6suaqo2gQnXCJWSwXNwXB4gBMFekNBeTwSGUmiMK4yNktDhsleNaAZRrUvYWmasuQHJOSDdpdKyriEIvo9maexWC70gAIF/bKTvzzFUH4HgbJZ3HdFSw9vC6lfKHpq7X8X07AOOblK2HhLQBindC2g/9Rx+gePcj/cnqHIDoUFm1c9gjwNAy/d0kyXIAMLSYrQ8kqScAhhbH3iLJBwIwtBByTJKkBWBoIeSMJHMOwNBCyG+SdEYAQ4tTvyLJMQUwtBAyJEn8BTC0EHIHQhQSApOlzGTBqaty6jzVAhhaCOlhYahuYYitE02EHGNzURchLZItX4ChhZB9HFBpUjmgwhGuHv0feI0gBw1T3j7CgHT5jzYC5XQRsjUdSsrhjADGl7ka0EylBgRb+ySkMy9rww7A8Waududf2MH9Qh9k3CbXLsGVNh/mqrvojuEeQHI+Qmq4Fq1ndIyeruaDxAEuCWk+ncmB0z3gepubtQenMUHyGTWELJl8xk6B15CeqVAyLtPXtUICsyJnVivWs+J0dAAwbzLOkQRTk2YuKsapTQFkXqPjlDILEinnRcZ1fpXdkGo866xqnH9FNyTjz0JIQZXcuPQCAE5rqo6oMEFBl7RknBRfTg8lj5Yl48JdGT0ueIWiYIvIuHFfPg9l85LJcF42b+JTUFjysZnyVlhy2qfA0asovTo9+0JxYnWC8t0KBQXuFYrdkIy3mBj3LbeNQrejZTuqOlbcl8znGTqcfjXoM3pboqgaPhEPxda1qgcVYsRt5TanDkgISWzcV1N1hCS3jdu4dNxUDMIhlBzXysHGGspkcBtsW2pPh3fGLrZ2ya5cXHFp0qxJ6si3E68EQCpy344vQRZxO5jfye+2d/oqgHsV02Z3lvcl9QTnA+EkLZw5h9MZcY4pTvxldXj/W0+esc+25H/5HQGYon+Q5f+MwFz+8QAAAABJRU5ErkJggg==" alt="PNG circle" ondragstart="event.dataTransfer.effectAllowed = 'copy'"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/images/helper-drop-horizontal-scrollbar.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/images/helper-drop-horizontal-scrollbar.xhtml
new file mode 100644
index 00000000000..ca1a677cc8c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/images/helper-drop-horizontal-scrollbar.xhtml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Image drag and drop: helper file</title>
+</head>
+<body ondragenter="event.preventDefault()" ondragover="return false">
+<div>↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓</div>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/images/helper-drop-image-here.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/images/helper-drop-image-here.xhtml
new file mode 100644
index 00000000000..00fb97a63bc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/images/helper-drop-image-here.xhtml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Image drag and drop: helper file</title>
+<style type="text/css">
+div[ondragenter]
+ {width:105px;
+ min-height:105px;
+ text-align:center;
+ margin-top:20px;
+ padding:10px;
+ border:solid thin navy;}
+</style>
+<script type="application/ecmascript">
+function addImage(event)
+ {var c = document.createElement('img');
+ c.setAttribute('src',event.dataTransfer.getData('text/uri-list').replace(/\r\n$/,''));
+ document.querySelector('div').appendChild(c);}
+</script>
+</head>
+<body>
+<div
+ ondragenter="event.preventDefault()"
+ ondragover="return false"
+ ondrop="addImage(event)"
+/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/images/helper-drop-vertical-scrollbar.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/images/helper-drop-vertical-scrollbar.xhtml
new file mode 100644
index 00000000000..619723882ce
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/images/helper-drop-vertical-scrollbar.xhtml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Image drag and drop: helper file</title>
+<style type="text/css">
+div
+ {width:1ex;}
+</style>
+</head>
+<body ondragenter="event.preventDefault()" ondragover="return false">
+<div>→ → → → → → → → → → → → → → → → → → → →</div>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/interactive/frames-1.html b/tests/wpt/web-platform-tests/html/editing/dnd/interactive/frames-1.html
new file mode 100644
index 00000000000..7df4fab4ef8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/interactive/frames-1.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<html>
+ <head>
+ <title>drag and drop should allow dragging of iframes and object iframes</title>
+ <style type="text/css">
+html { background: black; color: white; }
+ </style>
+ </head>
+ <body>
+
+ <script type="text/javascript">
+if( self == top ) {
+ document.write('<p>This is a helper file, not a testcase.<\/p>');
+}
+ </script>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/interactive/frames.html b/tests/wpt/web-platform-tests/html/editing/dnd/interactive/frames.html
new file mode 100644
index 00000000000..0414c524981
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/interactive/frames.html
@@ -0,0 +1,22 @@
+<!doctype html>
+<html>
+ <head>
+ <title>drag and drop should allow dragging of iframes and object iframes</title>
+ <style type="text/css">
+iframe, object {
+ border: 10px solid orange;
+ background: blue;
+ padding: 10px;
+ height: 100px;
+ width: 100px;
+}
+ </style>
+ </head>
+ <body>
+
+ <p>It should be possible to drag the following two blocks by both their orange and blue borders.</p>
+ <p><iframe draggable="true" src="frames-1.html"></iframe></p>
+ <p><object draggable="true" data="frames-1.html"></object></p>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/interactive/object-retention.html b/tests/wpt/web-platform-tests/html/editing/dnd/interactive/object-retention.html
new file mode 100644
index 00000000000..92a71d526b7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/interactive/object-retention.html
@@ -0,0 +1,144 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - variable retention within event handlers</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ }
+ body > div + div {
+ margin-top: 10px;
+ height: 200px;
+ width: 200px;
+ background-color: blue;
+ }
+</style>
+
+<script>
+window.onload = function() {
+ var orange = document.getElementsByTagName('div')[0], blue = document.getElementsByTagName('div')[1], fails = [], evs = {};
+ orange.ondragstart = function(e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ var foo = {};
+ e.dataTransfer.setData('text', foo);
+ if( e.dataTransfer.getData('text') === foo ) {
+ fails[fails.length] = 'object was not cast to string';
+ }
+ evs[e.type] = {};
+ evs[e.type].dataTransfer = e.dataTransfer;
+ evs[e.type].items = e.dataTransfer.items;
+ evs[e.type].types = e.dataTransfer.types;
+ evs[e.type].files = e.dataTransfer.files;
+ //"The same object must be returned each time."
+ if( evs[e.type].dataTransfer !== e.dataTransfer ) {
+ fails[fails.length] = '.dataTransfer is not returning the same object during '+e.type;
+ }
+ if( !e.dataTransfer.items ) {
+ fails[fails.length] = '.items is not returning anything during '+e.type;
+ } else if( evs[e.type].items !== e.dataTransfer.items ) {
+ fails[fails.length] = '.items is not returning the same object during '+e.type;
+ }
+ if( !e.dataTransfer.types ) {
+ fails[fails.length] = '.types is not returning anything during '+e.type;
+ } else if( evs[e.type].types !== e.dataTransfer.types ) {
+ fails[fails.length] = '.types is not returning the same object during '+e.type;
+ }
+ if( !e.dataTransfer.files ) {
+ fails[fails.length] = '.files is not returning anything during '+e.type;
+ } else if( evs[e.type].files !== e.dataTransfer.files ) {
+ fails[fails.length] = '.files is not returning the same object during '+e.type;
+ }
+ };
+ blue.ondragover = blue.ondragenter = function(e) {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'copy';
+ if( !evs[e.type] ) { evs[e.type] = {}; }
+ evs[e.type].dataTransfer = e.dataTransfer;
+ evs[e.type].items = e.dataTransfer.items;
+ evs[e.type].types = e.dataTransfer.types;
+ evs[e.type].files = e.dataTransfer.files;
+ if( evs[e.type].dataTransfer != e.dataTransfer ) {
+ fails[fails.length] = '.dataTransfer is not returning the same object during '+e.type;
+ }
+ if( !e.dataTransfer.items ) {
+ fails[fails.length] = '.items is not returning anything during '+e.type;
+ } else if( evs[e.type].items !== e.dataTransfer.items ) {
+ fails[fails.length] = '.items is not returning the same object during '+e.type;
+ }
+ if( !e.dataTransfer.types ) {
+ fails[fails.length] = '.types is not returning anything during '+e.type;
+ } else if( evs[e.type].types !== e.dataTransfer.types ) {
+ fails[fails.length] = '.types is not returning the same object during '+e.type;
+ }
+ if( !e.dataTransfer.files ) {
+ fails[fails.length] = '.files is not returning anything during '+e.type;
+ } else if( evs[e.type].files !== e.dataTransfer.files ) {
+ fails[fails.length] = '.files is not returning the same object during '+e.type;
+ }
+ //http://dev.w3.org/html5/spec/dnd.html#datatransfer
+ //"The * attribute must return a * object associated with the DataTransfer object."
+ //Note that it is associated with the DataTransfer object, *not* the data store
+ //http://dev.w3.org/html5/spec/dnd.html#dragevent
+ //"when a user agent is required to fire a DND event named e at an element, using a particular drag data store...
+ //Let dataTransfer be a newly created DataTransfer object associated with the given drag data store."
+ //A new DataTransfer object therefore means a new set of properties, not the same ones as last event
+ if( evs.dragstart.dataTransfer === e.dataTransfer ) {
+ fails[fails.length] = '.dataTransfer is returning the same object during '+e.type+' as it did during dragstart';
+ }
+ if( e.dataTransfer.items && evs.dragstart.items === e.dataTransfer.items ) {
+ fails[fails.length] = '.items is returning the same object during '+e.type+' as it did during dragstart';
+ }
+ if( e.dataTransfer.types && evs.dragstart.types === e.dataTransfer.types ) {
+ fails[fails.length] = '.types is returning the same object during '+e.type+' as it did during dragstart';
+ }
+ if( e.dataTransfer.files && evs.dragstart.files === e.dataTransfer.files ) {
+ fails[fails.length] = '.files is returning the same object during '+e.type+' as it did during dragstart';
+ }
+ };
+ blue.ondrop = function(e) {
+ e.preventDefault();
+ evs[e.type] = {};
+ evs[e.type].dataTransfer = e.dataTransfer;
+ evs[e.type].items = e.dataTransfer.items;
+ evs[e.type].types = e.dataTransfer.types;
+ evs[e.type].files = e.dataTransfer.files;
+ if( evs[e.type].dataTransfer !== e.dataTransfer ) {
+ fails[fails.length] = '.dataTransfer is not returning the same object during '+e.type;
+ }
+ if( !e.dataTransfer.items ) {
+ fails[fails.length] = '.items is not returning anything during '+e.type;
+ } else if( evs[e.type].items !== e.dataTransfer.items ) {
+ fails[fails.length] = '.items is not returning the same object during '+e.type;
+ }
+ if( !e.dataTransfer.types ) {
+ fails[fails.length] = '.types is not returning anything during '+e.type;
+ } else if( evs[e.type].types !== e.dataTransfer.types ) {
+ fails[fails.length] = '.types is not returning the same object during '+e.type;
+ }
+ if( !e.dataTransfer.files ) {
+ fails[fails.length] = '.files is not returning anything during '+e.type;
+ } else if( evs[e.type].files !== e.dataTransfer.files ) {
+ fails[fails.length] = '.files is not returning the same object during '+e.type;
+ }
+ if( evs.dragstart.dataTransfer === e.dataTransfer ) {
+ fails[fails.length] = '.dataTransfer is returning the same object during '+e.type+' as it did during dragstart';
+ }
+ if( e.dataTransfer.items && evs.dragstart.items === e.dataTransfer.items ) {
+ fails[fails.length] = '.items is returning the same object during '+e.type+' as it did during dragstart';
+ }
+ if( e.dataTransfer.types && evs.dragstart.types === e.dataTransfer.types ) {
+ fails[fails.length] = '.types is returning the same object during '+e.type+' as it did during dragstart';
+ }
+ if( e.dataTransfer.files && evs.dragstart.files === e.dataTransfer.files ) {
+ fails[fails.length] = '.files is returning the same object during '+e.type+' as it did during dragstart';
+ }
+ document.getElementsByTagName('p')[0].innerHTML = fails.length ? ( 'FAIL:<br>' + fails.join('<br>') ) : 'PASS';
+ };
+};
+</script>
+
+<p>Drag the orange square onto the blue square. Fail if this text does not change.</p>
+<div draggable="true"></div>
+<div></div>
+
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/interactive/plugins.html b/tests/wpt/web-platform-tests/html/editing/dnd/interactive/plugins.html
new file mode 100644
index 00000000000..7be5ec9397a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/interactive/plugins.html
@@ -0,0 +1,28 @@
+<!doctype html>
+<html>
+ <head>
+ <title>drag and drop should not remove styling of plugin object elements</title>
+ <style type="text/css">
+div {
+ border: 10px solid orange;
+ background: yellow;
+ padding: 10px;
+ height: 140px;
+ width: 140px;
+}
+object {
+ border: 10px solid gray;
+ background: fuchsia;
+ padding: 10px;
+ height: 100px;
+ width: 100px;
+}
+ </style>
+ </head>
+ <body>
+
+ <p>Drag the following block by the orange border. The drag placeholder should contain all inner borders, but may optionally show white or pink instead of the navy square.</p>
+ <div draggable="true" ondragstart="event.dataTransfer.setData('Text','dummy text');"><object data="../resources/boxnavy.swf"></object></div>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/001.html b/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/001.html
new file mode 100644
index 00000000000..33c6518e083
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/001.html
@@ -0,0 +1,29 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Select input inside draggable element</title>
+ <style type="text/css">
+select { border: 1px solid orange; border-top-width: 20px; }
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ document.getElementsByTagName('div')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('Text', 'dummy text');
+ };
+};
+ </script>
+ </head>
+ <body>
+
+ <p>Press your mouse button down on the orange block and drag downwards. It should open and select items in the dropdown, and should <strong>not</strong> drag the block or text.</p>
+ <div draggable="true">
+ <select>
+ <option>Option 1</option>
+ <option>Option 2</option>
+ <option>Option 3</option>
+ </select>
+ </div>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/002.html b/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/002.html
new file mode 100644
index 00000000000..8734a3e3aca
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/002.html
@@ -0,0 +1,29 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Select multiple input inside draggable element</title>
+ <style type="text/css">
+select { border: 1px solid orange; border-top-width: 20px; }
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ document.getElementsByTagName('div')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('Text', 'dummy text');
+ };
+};
+ </script>
+ </head>
+ <body>
+
+ <p>Press your mouse button down on the orange block and drag downwards. It should open and select items in the dropdown, and should <strong>not</strong> drag the block or text.</p>
+ <div draggable="true">
+ <select multiple size="3">
+ <option>Option 1</option>
+ <option>Option 2</option>
+ <option>Option 3</option>
+ </select>
+ </div>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/003.html b/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/003.html
new file mode 100644
index 00000000000..3399c2f0262
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/003.html
@@ -0,0 +1,29 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Draggable select</title>
+ <style type="text/css">
+select { border: 1px solid orange; border-top-width: 20px; }
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ document.getElementsByTagName('select')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('Text', 'dummy text');
+ };
+};
+ </script>
+ </head>
+ <body>
+
+ <p>Press your mouse button down on the orange block and drag downwards. It should open and select items in the dropdown, and should <strong>not</strong> drag the block or text.</p>
+ <div>
+ <select draggable="true">
+ <option>Option 1</option>
+ <option>Option 2</option>
+ <option>Option 3</option>
+ </select>
+ </div>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/004.html b/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/004.html
new file mode 100644
index 00000000000..5f58b207ae1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/004.html
@@ -0,0 +1,29 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Draggable select multiple</title>
+ <style type="text/css">
+select { border: 1px solid orange; border-top-width: 20px; }
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ document.getElementsByTagName('select')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('Text', 'dummy text');
+ };
+};
+ </script>
+ </head>
+ <body>
+
+ <p>Press your mouse button down on the orange block and drag downwards. It should open and select items in the dropdown, and should <strong>not</strong> drag the block or text.</p>
+ <div>
+ <select multiple size="3" draggable="true">
+ <option>Option 1</option>
+ <option>Option 2</option>
+ <option>Option 3</option>
+ </select>
+ </div>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/005.html b/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/005.html
new file mode 100644
index 00000000000..6647375c676
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/005.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Text input inside draggable element</title>
+ <style type="text/css">
+input { border: 1px solid orange; border-top-width: 20px; }
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ document.getElementsByTagName('div')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('Text', 'dummy text');
+ };
+};
+ </script>
+ </head>
+ <body>
+
+ <p>Press your mouse button down on the orange block and drag downwards. It should focus the dummy text. Use your mouse to select part of the dummy text. It should <strong>not</strong> drag the block or text in either case.</p>
+ <div draggable="true">
+ <input value="Dummy text">
+ </div>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/006.html b/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/006.html
new file mode 100644
index 00000000000..0ca35321220
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/006.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Draggable text input</title>
+ <style type="text/css">
+input { border: 1px solid orange; border-top-width: 20px; }
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ document.getElementsByTagName('input')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('Text', 'dummy text');
+ };
+};
+ </script>
+ </head>
+ <body>
+
+ <p>Press your mouse button down on the orange block and drag downwards. It should focus the dummy text. Use your mouse to select part of the dummy text. It should <strong>not</strong> drag the block or text in either case.</p>
+ <div>
+ <input value="Dummy text" draggable="true">
+ </div>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/007.html b/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/007.html
new file mode 100644
index 00000000000..6bcdc80e940
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/007.html
@@ -0,0 +1,36 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Textarea inside draggable element</title>
+ <style type="text/css">
+textarea { border: 1px solid orange; border-top-width: 20px; }
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ document.getElementsByTagName('div')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('Text', 'dummy text');
+ };
+};
+ </script>
+ </head>
+ <body>
+
+ <p>Press your mouse button down on the orange block and drag downwards. It may optionally focus the dummy text. Use your mouse to select part of the dummy text, moving the mouse vertically and horizontally. It should select the text. Try to drag the input's scrollbar thumb. It should <strong>not</strong> drag the block or text in any case.</p>
+ <div draggable="true">
+<textarea rows="5" cols="50" wrap="off">Dummy text
+Dummy text
+Dummy text
+Dummy text
+Dummy text
+Dummy text
+Dummy text
+Dummy text
+Dummy text
+Dummy text
+Dummy text
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</textarea>
+ </div>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/008.html b/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/008.html
new file mode 100644
index 00000000000..7cb97518fee
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/008.html
@@ -0,0 +1,36 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Draggable textarea</title>
+ <style type="text/css">
+textarea { border: 1px solid orange; border-top-width: 20px; }
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ document.getElementsByTagName('textarea')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('Text', 'dummy text');
+ };
+};
+ </script>
+ </head>
+ <body>
+
+ <p>Press your mouse button down on the orange block and drag downwards. It may optionally focus the dummy text. Use your mouse to select part of the dummy text, moving the mouse vertically and horizontally. It should select the text. Try to drag the input's scrollbar thumb. It should <strong>not</strong> drag the block or text in any case.</p>
+ <div>
+<textarea rows="5" cols="50" wrap="off">Dummy text
+Dummy text
+Dummy text
+Dummy text
+Dummy text
+Dummy text
+Dummy text
+Dummy text
+Dummy text
+Dummy text
+Dummy text
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</textarea>
+ </div>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/009.html b/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/009.html
new file mode 100644
index 00000000000..6c240c06fae
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/009.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Input button inside draggable element</title>
+ <style type="text/css">
+input { border: 1px solid orange; border-top-width: 20px; }
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ document.getElementsByTagName('div')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('Text', 'dummy text');
+ };
+};
+ </script>
+ </head>
+ <body>
+
+ <p>Press your mouse button down on the orange block and drag downwards. It should <strong>not</strong> drag the block or text.</p>
+ <div draggable="true">
+ <input type="button" value="Dummy text">
+ </div>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/010.html b/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/010.html
new file mode 100644
index 00000000000..2253e8bae2e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/010.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Draggable input button</title>
+ <style type="text/css">
+input { border: 1px solid orange; border-top-width: 20px; }
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ document.getElementsByTagName('input')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('Text', 'dummy text');
+ };
+};
+ </script>
+ </head>
+ <body>
+
+ <p>Press your mouse button down on the orange block and drag downwards. It should <strong>not</strong> drag the block or text.</p>
+ <div>
+ <input type="button" value="Dummy text" draggable="true">
+ </div>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/011.html b/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/011.html
new file mode 100644
index 00000000000..e90cfc3496a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/011.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Button inside draggable element</title>
+ <style type="text/css">
+button { border: 1px solid orange; border-top-width: 20px; }
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ document.getElementsByTagName('div')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('Text', 'dummy text');
+ };
+};
+ </script>
+ </head>
+ <body>
+
+ <p>Press your mouse button down on the orange block and drag downwards. It should <strong>not</strong> drag the block or text.</p>
+ <div draggable="true">
+ <button>Dummy text</button>
+ </div>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/012.html b/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/012.html
new file mode 100644
index 00000000000..15659cdc9d0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/012.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Draggable button</title>
+ <style type="text/css">
+button { border: 1px solid orange; border-top-width: 20px; }
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ document.getElementsByTagName('button')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('Text', 'dummy text');
+ };
+};
+ </script>
+ </head>
+ <body>
+
+ <p>Press your mouse button down on the orange block and drag downwards. It should <strong>not</strong> drag the block or text.</p>
+ <div>
+ <button draggable="true">Dummy text</button>
+ </div>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/015.html b/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/015.html
new file mode 100644
index 00000000000..a2c66a145e8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/015.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Contenteditable inside draggable element</title>
+ <style type="text/css">
+div div { border: 1px solid orange; border-top-width: 20px; }
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ document.getElementsByTagName('div')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('Text', 'dummy text');
+ };
+};
+ </script>
+ </head>
+ <body>
+
+ <p>Press your mouse button down on the orange block and drag downwards. It should <strong>not</strong> drag the text or the orange block. Use your mouse to select the dummy text. It should <strong>not</strong> drag the text or the orange block.</p>
+ <div draggable="true">
+ <div contenteditable="true">Dummy text</div>
+ </div>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/016.html b/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/016.html
new file mode 100644
index 00000000000..b9bc169e459
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/016.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Draggable contenteditable element</title>
+ <style type="text/css">
+div div { border: 1px solid orange; border-top-width: 20px; }
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ document.getElementsByTagName('div')[1].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('Text', 'dummy text');
+ };
+};
+ </script>
+ </head>
+ <body>
+
+ <p>Press your mouse button down on the orange block and drag downwards. It should <strong>not</strong> drag the text or the orange block. Use your mouse to select the dummy text. It should <strong>not</strong> drag the text or the orange block.</p>
+ <div>
+ <div draggable="true" contenteditable="true">Dummy text</div>
+ </div>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/017.html b/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/017.html
new file mode 100644
index 00000000000..8de64c08bff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/017.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Scrollable element inside draggable element</title>
+ <style type="text/css">
+div div { width: 300px; height: 100px; overflow: auto; border: 1px solid orange; }
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ document.getElementsByTagName('div')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('Text', 'dummy text');
+ };
+};
+ </script>
+ </head>
+ <body>
+
+ <p>It should be possible to drag the scrollbar thumbs of the box below without dragging the whole box.</p>
+ <div draggable="true">
+ <div>Dummy text<br>Dummy text<br>Dummy text<br>Dummy text<br>Dummy text<br>Dummy text<br>Dummy text<br>Dummy text<br>Dummy text<br>Dummy text<br>Dummy text<br>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</div>
+ </div>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/018.html b/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/018.html
new file mode 100644
index 00000000000..67d8ad0f85f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/018.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Draggable scrollable element</title>
+ <style type="text/css">
+div div { width: 300px; height: 100px; overflow: auto; border: 1px solid orange; }
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ document.getElementsByTagName('div')[1].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('Text', 'dummy text');
+ };
+};
+ </script>
+ </head>
+ <body>
+
+ <p>It should be possible to drag the scrollbar thumbs of the box below without dragging the whole box.</p>
+ <div>
+ <div draggable="true">Dummy text<br>Dummy text<br>Dummy text<br>Dummy text<br>Dummy text<br>Dummy text<br>Dummy text<br>Dummy text<br>Dummy text<br>Dummy text<br>Dummy text<br>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</div>
+ </div>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/019.html b/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/019.html
new file mode 100644
index 00000000000..77e6e813ccb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/019.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Disabled text input with inside draggable element</title>
+ <style type="text/css">
+input { border: 1px solid orange; border-top-width: 20px; }
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ document.getElementsByTagName('div')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('Text', 'dummy text');
+ };
+};
+ </script>
+ </head>
+ <body>
+
+ <p>Press your mouse button down on the orange block and drag downwards. Use your mouse to attempt to select part of the dummy text. It should <strong>not</strong> drag the block or text in either case.</p>
+ <div draggable="true">
+ <input value="Dummy text" disabled>
+ </div>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/020.html b/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/020.html
new file mode 100644
index 00000000000..2bad553120a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/020.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Disabled draggable text input</title>
+ <style type="text/css">
+input { border: 1px solid orange; border-top-width: 20px; }
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ document.getElementsByTagName('input')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('Text', 'dummy text');
+ };
+};
+ </script>
+ </head>
+ <body>
+
+ <p>Press your mouse button down on the orange block and drag downwards. Use your mouse to attempt to select part of the dummy text. It should <strong>not</strong> drag the block or text in either case.</p>
+ <div>
+ <input value="Dummy text" draggable="true" disabled>
+ </div>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/021.html b/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/021.html
new file mode 100644
index 00000000000..954c59509f4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/021.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Readonly text input with inside draggable element</title>
+ <style type="text/css">
+input { border: 1px solid orange; border-top-width: 20px; }
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ document.getElementsByTagName('div')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('Text', 'dummy text');
+ };
+};
+ </script>
+ </head>
+ <body>
+
+ <p>Press your mouse button down on the orange block and drag downwards. Use your mouse to attempt to select part of the dummy text. It should <strong>not</strong> drag the block or text in either case.</p>
+ <div draggable="true">
+ <input value="Dummy text" readonly>
+ </div>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/022.html b/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/022.html
new file mode 100644
index 00000000000..fb1d796bacf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/interactiveelements/022.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Readonly draggable text input</title>
+ <style type="text/css">
+input { border: 1px solid orange; border-top-width: 20px; }
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ document.getElementsByTagName('input')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('Text', 'dummy text');
+ };
+};
+ </script>
+ </head>
+ <body>
+
+ <p>Press your mouse button down on the orange block and drag downwards. Use your mouse to attempt to select part of the dummy text. It should <strong>not</strong> drag the block or text in either case.</p>
+ <div>
+ <input value="Dummy text" draggable="true" readonly>
+ </div>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/media/001.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/media/001.xhtml
new file mode 100644
index 00000000000..2f90f5c3ec6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/media/001.xhtml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Video drag and drop</title>
+<style type="text/css">
+canvas
+ {background-color:silver;}
+</style>
+<script type="application/ecmascript">
+var draggedFrame = 'data:text/plain,FAIL';
+function dropIt(event)
+ {document.querySelector('p + p').firstChild.nodeValue = (draggedFrame == event.dataTransfer.getData('text/uri-list'))?'PASS':'FAIL';}
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ var canvas = document.querySelector('canvas'),
+ c = canvas.getContext('2d');
+ c.drawImage(document.querySelector('video'),0,0,640,360);
+ draggedFrame = canvas.toDataURL('image/png');
+ event.dataTransfer.setData('text/uri-list',draggedFrame);}
+</script>
+<script src="/common/media.js"></script>
+</head>
+<body dropzone="copy string:text/uri-list" ondrop="dropIt(event)">
+<p>
+ <video draggable="true" ondragstart="start(event)" controls="true"/>
+ <script>
+ var video = document.querySelector('video');
+ video.src = getVideoURI('/media/movie_5');
+ </script>
+</p>
+<p>Drag video and drop it somewhere on the page. Dragged frame should be copied to the canvas below and you should see word PASS once you drop video.</p>
+<p>
+ <canvas width="640" height="360">Canvas</canvas>
+</p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/microdata/000.html b/tests/wpt/web-platform-tests/html/editing/dnd/microdata/000.html
new file mode 100644
index 00000000000..6ec402e7d6a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/microdata/000.html
@@ -0,0 +1,93 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - no microdata for no itemscope</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ position: absolute;
+ top: 8px;
+ left: 8px;
+ }
+ body > div * {
+ display: none;
+ }
+ body > div + div {
+ background-color: navy;
+ left: 250px;
+ }
+ body > div + div + div {
+ background-color: fuchsia;
+ left: 500px;
+ }
+ p:first-of-type {
+ margin-top: 220px;
+ }
+</style>
+
+<script>
+
+function makeEl(eltype,props,contents) {
+ var elem = document.createElement(eltype);
+ for( var i in props ) {
+ if( props.hasOwnProperty(i) ) {
+ elem.setAttribute(i,props[i]);
+ }
+ }
+ if( contents ) {
+ elem.innerHTML = contents;
+ }
+ return elem;
+}
+
+var orange, fails = [], doneonce = false;
+window.onload = function() {
+ orange = document.getElementsByTagName('div')[0];
+ orange.ondragstart = function(e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('Text', 'dummy text');
+ var err;
+ if( err = checkprops(e.dataTransfer.getData('application/microdata+json')) ) {
+ fails[fails.length] = e.type + ' ' + err;
+ }
+ };
+ orange.nextSibling.ondragenter = orange.nextSibling.ondragleave = orange.nextSibling.ondragover =
+ orange.ondrag = orange.ondragend = function(e) {
+ if( e.type == 'dragover' || e.type == 'dragenter' ) {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'copy';
+ }
+ if( e.dataTransfer.getData('application/microdata+json') ) {
+ fails[fails.length] = e.type + ' unexpectedly had microdata (security restriction)';
+ }
+ };
+ orange.nextSibling.ondrop = function(e) {
+ var err;
+ if( err = checkprops(e.dataTransfer.getData('application/microdata+json')) ) {
+ fails[fails.length] = e.type + ' ' + err;
+ }
+ if( e.type != 'drop' ) { return; }
+ if( doneonce ) { return; }
+ doneonce = true;
+ setTimeout(function () {
+ document.getElementsByTagName('p')[0].innerHTML = fails.length ? ( 'FAIL: ' + fails.join('<br>') ) : 'PASS';
+ fails = [];
+ }, 200 );
+ };
+
+};
+function checkprops(md) {
+ var i;
+ if( !md ) { return 'no microdata'; }
+ md = JSON.parse(md);
+ if( !md.items ) { return 'no items collection'; }
+ if( md.items.length != 0 ) { return 'unexpected items found'; }
+ return '';
+}
+
+</script>
+
+<div draggable='true'></div><div></div><div></div>
+
+<p>Use your pointing device to drag the orange box to the pink box, then back to the blue box, and release it.</p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/microdata/001.html b/tests/wpt/web-platform-tests/html/editing/dnd/microdata/001.html
new file mode 100644
index 00000000000..eda592fc684
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/microdata/001.html
@@ -0,0 +1,128 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - microdata for non looping simple drop</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ position: absolute;
+ top: 8px;
+ left: 8px;
+ }
+ body > div * {
+ display: none;
+ }
+ body > div + div {
+ background-color: navy;
+ left: 250px;
+ }
+ body > div + div + div {
+ background-color: fuchsia;
+ left: 500px;
+ }
+ p:first-of-type {
+ margin-top: 220px;
+ }
+</style>
+
+<script>
+
+function makeEl(eltype,props,contents) {
+ var elem = document.createElement(eltype);
+ for( var i in props ) {
+ if( props.hasOwnProperty(i) ) {
+ elem.setAttribute(i,props[i]);
+ }
+ }
+ if( contents ) {
+ elem.innerHTML = contents;
+ }
+ return elem;
+}
+
+var orange, fails = [], doneonce = false;
+window.onload = function() {
+ orange = document.getElementsByTagName('div')[0];
+
+ orange.appendChild( makeEl('meta',{itemprop:'foo',content:'test'}) );
+ orange.appendChild( makeEl('audio',{itemprop:'bar',src:'test'},'fail') );
+ orange.appendChild( makeEl('embed',{itemprop:'foo',src:'test'}) );
+ orange.appendChild( makeEl('iframe',{itemprop:'bar',src:'test'},'fail') );
+ orange.appendChild( makeEl('img',{itemprop:'foo',src:'test'}) );
+ orange.appendChild( makeEl('source',{itemprop:'bar',src:'test'}) );
+ orange.appendChild( makeEl('track',{itemprop:'foo',src:'test'}) );
+ orange.appendChild( makeEl('video',{itemprop:'bar',src:'test'},'fail') );
+ orange.appendChild( makeEl('a',{itemprop:'foo',href:'test'},'fail') );
+ orange.appendChild( makeEl('area',{itemprop:'bar',href:'test'}) );
+ orange.appendChild( makeEl('link',{itemprop:'foo',href:'test'}) );
+ orange.appendChild( makeEl('object',{itemprop:'bar',data:'test'},'fail') );
+ orange.appendChild( makeEl('time',{itemprop:'foo'},'fail') );
+ orange.appendChild( makeEl('time',{itemprop:'baz',datetime:'test'},'fail') );
+ orange.appendChild( makeEl('div',{itemprop:'baz'},'test') );
+ orange.appendChild( makeEl('madeuponthespot',{itemprop:'foo'},'test') );
+ orange.appendChild( makeEl('madeuponthespot',{itemprop:'foo',content:'test',src:'test',href:'test',data:'test',datetime:'test',value:'test'},'test') );
+ orange.appendChild( makeEl('input',{itemprop:'foo',value:'test'},'test') );
+
+ orange.ondragstart = function(e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('Text', 'dummy text');
+ var err;
+ if( err = checkprops(e.dataTransfer.getData('application/microdata+json')) ) {
+ fails[fails.length] = e.type + ' ' + err;
+ }
+ };
+ orange.nextSibling.ondragenter = orange.nextSibling.ondragleave = orange.nextSibling.ondragover =
+ orange.ondrag = orange.ondragend = function(e) {
+ if( e.type == 'dragover' || e.type == 'dragenter' ) {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'copy';
+ }
+ if( e.dataTransfer.getData('application/microdata+json') ) {
+ fails[fails.length] = e.type + ' unexpectedly had microdata (security restriction)';
+ }
+ };
+ orange.nextSibling.ondrop = function(e) {
+ var err;
+ if( err = checkprops(e.dataTransfer.getData('application/microdata+json')) ) {
+ fails[fails.length] = e.type + ' ' + err;
+ }
+ if( e.type != 'drop' ) { return; }
+ if( doneonce ) { return; }
+ doneonce = true;
+ setTimeout(function () {
+ document.getElementsByTagName('p')[0].innerHTML = fails.length ? ( 'FAIL: ' + fails.join('<br>') ) : 'PASS';
+ fails = [];
+ }, 200 );
+ };
+
+};
+function checkprops(md) {
+ var i;
+ if( !md ) { return 'no microdata'; }
+ md = JSON.parse(md);
+ if( !md.items || md.items.length != 1 ) { return 'no items'; }
+ if( !md.items[0].properties ) { return 'no properties'; }
+ if( !md.items[0].properties.foo ) { return 'no properties.foo'; }
+ if( !md.items[0].properties.bar ) { return 'no properties.bar'; }
+ if( !md.items[0].properties.baz ) { return 'no properties.baz'; }
+ if( md.items[0].properties.foo.length != 10 ) { return 'properties.foo length '+md.items[0].properties.foo.length+' instead of 10'; }
+ if( md.items[0].properties.bar.length != 6 ) { return 'properties.bar length '+md.items[0].properties.bar.length+' instead of 6'; }
+ if( md.items[0].properties.baz.length != 2 ) { return 'properties.baz length '+md.items[0].properties.baz.length+' instead of 2'; }
+ for( i = 0; i < 10; i++ ) {
+ if( md.items[0].properties.foo[i] != orange.properties.namedItem('foo').getValues()[i] ) { return 'properties.foo['+i+'] <i>'+md.items[0].properties.foo[i]+'</i> instead of <i>'+orange.properties.namedItem('foo').getValues()[i]+'</i>'; }
+ }
+ for( i = 0; i < 6; i++ ) {
+ if( md.items[0].properties.bar[i] != orange.properties.namedItem('bar').getValues()[i] ) { return 'properties.bar['+i+'] <i>'+md.items[0].properties.bar[i]+'</i> instead of <i>'+orange.properties.namedItem('bar').getValues()[i]+'</i>'; }
+ }
+ for( i = 0; i < 2; i++ ) {
+ if( md.items[0].properties.baz[i] != orange.properties.namedItem('baz').getValues()[i] ) { return 'properties.baz['+i+'] <i>'+md.items[0].properties.baz[i]+'</i> instead of <i>'+orange.properties.namedItem('baz').getValues()[i]+'</i>'; }
+ }
+ return '';
+}
+
+</script>
+
+<div draggable='true' itemscope></div><div></div><div></div>
+
+<p>Use your pointing device to drag the orange box to the pink box, then back to the blue box, and release it.</p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/microdata/002.html b/tests/wpt/web-platform-tests/html/editing/dnd/microdata/002.html
new file mode 100644
index 00000000000..bf75986bbfe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/microdata/002.html
@@ -0,0 +1,106 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - microdata with itemref</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ position: absolute;
+ top: 8px;
+ left: 8px;
+ }
+ body > div *, span {
+ display: none;
+ }
+ body > div + div {
+ background-color: navy;
+ left: 250px;
+ }
+ body > div + div + div {
+ background-color: fuchsia;
+ left: 500px;
+ }
+ p:first-of-type {
+ margin-top: 220px;
+ }
+</style>
+
+<script>
+
+function makeEl(eltype,props,contents) {
+ var elem = document.createElement(eltype);
+ for( var i in props ) {
+ if( props.hasOwnProperty(i) ) {
+ elem.setAttribute(i,props[i]);
+ }
+ }
+ if( contents ) {
+ elem.innerHTML = contents;
+ }
+ return elem;
+}
+
+var orange, fails = [], doneonce = false;
+window.onload = function() {
+ orange = document.getElementsByTagName('div')[0];
+
+ orange.parentNode.insertBefore( makeEl('span',{itemprop:'foo',id:'id1'},'dummytext1 '), orange );
+ orange.parentNode.appendChild( makeEl('span',{itemprop:'bar',id:'id2'},'dummytext2 ') );
+ orange.parentNode.appendChild( makeEl('span',{itemprop:'foo',id:'id3'},'dummytext3 ') );
+
+ orange.ondragstart = function(e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('Text', 'dummy text');
+ var err;
+ if( err = checkprops(e.dataTransfer.getData('application/microdata+json')) ) {
+ fails[fails.length] = e.type + ' ' + err;
+ }
+ };
+ orange.nextSibling.ondragenter = orange.nextSibling.ondragleave = orange.nextSibling.ondragover =
+ orange.ondrag = orange.ondragend = function(e) {
+ if( e.type == 'dragover' || e.type == 'dragenter' ) {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'copy';
+ }
+ if( e.dataTransfer.getData('application/microdata+json') ) {
+ fails[fails.length] = e.type + ' unexpectedly had microdata (security restriction)';
+ }
+ };
+ orange.nextSibling.ondrop = function(e) {
+ var err;
+ if( err = checkprops(e.dataTransfer.getData('application/microdata+json')) ) {
+ fails[fails.length] = e.type + ' ' + err;
+ }
+ if( e.type != 'drop' ) { return; }
+ if( doneonce ) { return; }
+ doneonce = true;
+ setTimeout(function () {
+ document.getElementsByTagName('p')[0].innerHTML = fails.length ? ( 'FAIL: ' + fails.join('<br>') ) : 'PASS';
+ fails = [];
+ }, 200 );
+ };
+
+};
+function checkprops(md) {
+ var i;
+ if( !md ) { return 'no microdata'; }
+ md = JSON.parse(md);
+ if( !md.items || md.items.length != 1 ) { return 'no items'; }
+ if( !md.items[0].properties ) { return 'no properties'; }
+ if( !md.items[0].properties.foo ) { return 'no properties.foo'; }
+ if( !md.items[0].properties.bar ) { return 'no properties.bar'; }
+ if( md.items[0].properties.foo.length != 2 ) { return 'properties.foo length '+md.items[0].properties.foo.length+' instead of 2'; }
+ if( md.items[0].properties.bar.length != 1 ) { return 'properties.bar length '+md.items[0].properties.bar.length+' instead of 1'; }
+ for( i = 0; i < 2; i++ ) {
+ if( md.items[0].properties.foo[i] != orange.properties.namedItem('foo').getValues()[i] ) { return 'properties.foo['+i+'] <i>'+md.items[0].properties.foo[i]+'</i> instead of <i>'+orange.properties.namedItem('foo').getValues()[i]+'</i>'; }
+ }
+ if( md.items[0].properties.bar[0] != orange.properties.namedItem('bar').getValues()[0] ) { return 'properties.bar[0] <i>'+md.items[0].properties.bar[i]+'</i> instead of <i>'+orange.properties.namedItem('bar').getValues()[0]+'</i>'; }
+ return '';
+}
+
+</script>
+
+<div draggable='true' itemscope itemref='id3 id2 id1'></div><div></div><div></div>
+
+<p>Use your pointing device to drag the orange box to the pink box, then back to the blue box, and release it.</p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/microdata/003.html b/tests/wpt/web-platform-tests/html/editing/dnd/microdata/003.html
new file mode 100644
index 00000000000..0b9cca7f339
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/microdata/003.html
@@ -0,0 +1,132 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - microdata changes after dragstart</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ position: absolute;
+ top: 8px;
+ left: 8px;
+ }
+ body > div * {
+ display: none;
+ }
+ body > div + div {
+ background-color: navy;
+ left: 250px;
+ }
+ body > div + div + div {
+ background-color: fuchsia;
+ left: 500px;
+ }
+ p:first-of-type {
+ margin-top: 220px;
+ }
+</style>
+
+<script>
+
+function makeEl(eltype,props,contents) {
+ var elem = document.createElement(eltype);
+ for( var i in props ) {
+ if( props.hasOwnProperty(i) ) {
+ elem.setAttribute(i,props[i]);
+ }
+ }
+ if( contents ) {
+ elem.innerHTML = contents;
+ }
+ return elem;
+}
+
+var orange, fails = [], doneonce = false;
+window.onload = function() {
+ orange = document.getElementsByTagName('div')[0];
+
+ orange.appendChild( makeEl('meta',{itemprop:'foo',content:'test'}) );
+ orange.appendChild( makeEl('audio',{itemprop:'bar',src:'test'},'fail') );
+ orange.appendChild( makeEl('embed',{itemprop:'foo',src:'test'}) );
+ orange.appendChild( makeEl('iframe',{itemprop:'bar',src:'test'},'fail') );
+ orange.appendChild( makeEl('img',{itemprop:'foo',src:'test'}) );
+ orange.appendChild( makeEl('source',{itemprop:'bar',src:'test'}) );
+ orange.appendChild( makeEl('track',{itemprop:'foo',src:'test'}) );
+ orange.appendChild( makeEl('video',{itemprop:'bar',src:'test'},'fail') );
+ orange.appendChild( makeEl('a',{itemprop:'foo',href:'test'},'fail') );
+ orange.appendChild( makeEl('area',{itemprop:'bar',href:'test'}) );
+ orange.appendChild( makeEl('link',{itemprop:'foo',href:'test'}) );
+ orange.appendChild( makeEl('object',{itemprop:'bar',data:'test'},'fail') );
+ orange.appendChild( makeEl('time',{itemprop:'foo'},'fail') );
+ orange.appendChild( makeEl('time',{itemprop:'baz',datetime:'test'},'fail') );
+ orange.appendChild( makeEl('div',{itemprop:'baz'},'test') );
+ orange.appendChild( makeEl('madeuponthespot',{itemprop:'foo'},'test') );
+ orange.appendChild( makeEl('madeuponthespot',{itemprop:'foo',content:'test',src:'test',href:'test',data:'test',datetime:'test',value:'test'},'test') );
+ orange.appendChild( makeEl('input',{itemprop:'foo',value:'test'},'test') );
+
+ orange.ondragstart = function(e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('Text', 'dummy text');
+ var err;
+ if( err = checkprops(e.dataTransfer.getData('application/microdata+json')) ) {
+ fails[fails.length] = e.type + ' ' + err;
+ }
+ //microdata should be stored and reused after the dragstart event
+ //removing the item should not cause the microdata tohave disappeared when the drop event fires
+ this.itemScope = false;
+ };
+ orange.nextSibling.ondragenter = orange.nextSibling.ondragleave = orange.nextSibling.ondragover =
+ orange.ondrag = orange.ondragend = function(e) {
+ if( e.type == 'dragover' || e.type == 'dragenter' ) {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'copy';
+ }
+ if( e.dataTransfer.getData('application/microdata+json') ) {
+ fails[fails.length] = e.type + ' unexpectedly had microdata (security restriction)';
+ }
+ };
+ orange.nextSibling.ondrop = function(e) {
+ var err, md = e.dataTransfer.getData('application/microdata+json');
+ orange.itemScope = true;
+ if( err = checkprops(md) ) {
+ fails[fails.length] = e.type + ' ' + err;
+ }
+ if( e.type != 'drop' ) { return; }
+ if( doneonce ) { return; }
+ doneonce = true;
+ setTimeout(function () {
+ document.getElementsByTagName('p')[0].innerHTML = fails.length ? ( 'FAIL: ' + fails.join('<br>') ) : 'PASS';
+ fails = [];
+ }, 200 );
+ };
+
+};
+function checkprops(md) {
+ var i;
+ if( !md ) { return 'no microdata'; }
+ md = JSON.parse(md);
+ if( !md.items || md.items.length != 1 ) { return 'no items'; }
+ if( !md.items[0].properties ) { return 'no properties'; }
+ if( !md.items[0].properties.foo ) { return 'no properties.foo'; }
+ if( !md.items[0].properties.bar ) { return 'no properties.bar'; }
+ if( !md.items[0].properties.baz ) { return 'no properties.baz'; }
+ if( md.items[0].properties.foo.length != 10 ) { return 'properties.foo length '+md.items[0].properties.foo.length+' instead of 10'; }
+ if( md.items[0].properties.bar.length != 6 ) { return 'properties.bar length '+md.items[0].properties.bar.length+' instead of 6'; }
+ if( md.items[0].properties.baz.length != 2 ) { return 'properties.baz length '+md.items[0].properties.baz.length+' instead of 2'; }
+ for( i = 0; i < 10; i++ ) {
+ if( md.items[0].properties.foo[i] != orange.properties.namedItem('foo').getValues()[i] ) { return 'properties.foo['+i+'] <i>'+md.items[0].properties.foo[i]+'</i> instead of <i>'+orange.properties.namedItem('foo').getValues()[i]+'</i>'; }
+ }
+ for( i = 0; i < 6; i++ ) {
+ if( md.items[0].properties.bar[i] != orange.properties.namedItem('bar').getValues()[i] ) { return 'properties.bar['+i+'] <i>'+md.items[0].properties.bar[i]+'</i> instead of <i>'+orange.properties.namedItem('bar').getValues()[i]+'</i>'; }
+ }
+ for( i = 0; i < 2; i++ ) {
+ if( md.items[0].properties.baz[i] != orange.properties.namedItem('baz').getValues()[i] ) { return 'properties.baz['+i+'] <i>'+md.items[0].properties.baz[i]+'</i> instead of <i>'+orange.properties.namedItem('baz').getValues()[i]+'</i>'; }
+ }
+ return '';
+}
+
+</script>
+
+<div draggable='true' itemscope></div><div></div><div></div>
+
+<p>Use your pointing device to drag the orange box to the pink box, then back to the blue box, and release it.</p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/microdata/004.html b/tests/wpt/web-platform-tests/html/editing/dnd/microdata/004.html
new file mode 100644
index 00000000000..33553326403
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/microdata/004.html
@@ -0,0 +1,116 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - microdata with nested item as property</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ position: absolute;
+ top: 8px;
+ left: 8px;
+ }
+ body > div * {
+ display: none;
+ }
+ body > div + div {
+ background-color: navy;
+ left: 250px;
+ }
+ body > div + div + div {
+ background-color: fuchsia;
+ left: 500px;
+ }
+ p:first-of-type {
+ margin-top: 220px;
+ }
+</style>
+
+<script>
+
+function makeEl(eltype,props,contents) {
+ var elem = document.createElement(eltype);
+ for( var i in props ) {
+ if( props.hasOwnProperty(i) ) {
+ elem.setAttribute(i,props[i]);
+ }
+ }
+ if( contents ) {
+ elem.innerHTML = contents;
+ }
+ return elem;
+}
+
+var orange, fails = [], doneonce = false;
+window.onload = function() {
+ orange = document.getElementsByTagName('div')[0];
+
+ orange.appendChild( makeEl('div',{itemprop:'foo',itemscope:'itemscope'},'') );
+ orange.appendChild( makeEl('div',{itemprop:'foo',itemscope:'itemscope'},'') );
+ orange.lastChild.appendChild( makeEl('div',{itemprop:'bar'},'test') );
+ orange.appendChild( makeEl('div',{itemprop:'bar',itemscope:'itemscope'},'') );
+
+ orange.ondragstart = function(e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('Text', 'dummy text');
+ var err;
+ if( err = checkprops(e.dataTransfer.getData('application/microdata+json')) ) {
+ fails[fails.length] = e.type + ' ' + err;
+ }
+ };
+ orange.nextSibling.ondragenter = orange.nextSibling.ondragleave = orange.nextSibling.ondragover =
+ orange.ondrag = orange.ondragend = function(e) {
+ if( e.type == 'dragover' || e.type == 'dragenter' ) {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'copy';
+ }
+ if( e.dataTransfer.getData('application/microdata+json') ) {
+ fails[fails.length] = e.type + ' unexpectedly had microdata (security restriction)';
+ }
+ };
+ orange.nextSibling.ondrop = function(e) {
+ var err;
+ if( err = checkprops(e.dataTransfer.getData('application/microdata+json')) ) {
+ fails[fails.length] = e.type + ' ' + err;
+ }
+ if( e.type != 'drop' ) { return; }
+ if( doneonce ) { return; }
+ doneonce = true;
+ setTimeout(function () {
+ document.getElementsByTagName('p')[0].innerHTML = fails.length ? ( 'FAIL: ' + fails.join('<br>') ) : 'PASS';
+ fails = [];
+ }, 200 );
+ };
+
+};
+function checkprops(md) {
+ var i;
+ if( !md ) { return 'no microdata'; }
+ md = JSON.parse(md);
+ if( !md.items ) { return 'no items'; }
+ if( md.items.length != 1 ) { return md.items.length+' items instead of 1'; }
+ if( !md.items[0].properties ) { return 'no properties'; }
+ if( !md.items[0].properties.foo ) { return 'no properties.foo'; }
+ if( !md.items[0].properties.bar ) { return 'no properties.bar'; }
+ if( md.items[0].properties.foo.length != 2 ) { return 'properties.foo length '+md.items[0].properties.foo.length+' instead of 2'; }
+ if( md.items[0].properties.bar.length != 1 ) { return 'properties.bar length '+md.items[0].properties.bar.length+' instead of 1'; }
+
+ if( !md.items[0].properties.foo[0] ) { return 'properties.foo[0] <i>'+md.items[0].properties.foo[0]+'</i> instead of <i>{properties:{}}</i>'; }
+ if( !md.items[0].properties.foo[0].properties ) { return 'properties.foo[0].properties <i>'+md.items[0].properties.foo[0].properties+'</i> instead of <i>{}</i>'; }
+
+ if( !md.items[0].properties.foo[1] ) { return 'properties.foo[1] <i>'+md.items[0].properties.foo[1]+'</i> instead of <i>{properties:{bar:[test]}}</i>'; }
+ if( !md.items[0].properties.foo[1].properties ) { return 'properties.foo[1].properties <i>'+md.items[0].properties.foo[1].properties+'</i> instead of <i>{bar:[test]}</i>'; }
+ if( !md.items[0].properties.foo[1].properties.bar ) { return 'properties.foo[1].properties.bar <i>'+md.items[0].properties.foo[1].properties.bar+'</i> instead of <i>[test]</i>'; }
+ if( !md.items[0].properties.foo[1].properties.bar.length ) { return 'properties.foo[1].properties.bar.length <i>'+md.items[0].properties.foo[1].properties.bar.length+'</i> instead of 1'; }
+ if( md.items[0].properties.foo[1].properties.bar[0] != 'test') { return 'properties.foo[1].properties.bar[0] <i>'+md.items[0].properties.foo[1].properties.bar[0]+'</i> instead of <i>test</i>'; }
+
+ if( !md.items[0].properties.bar[0] ) { return 'properties.bar[0] <i>'+md.items[0].properties.bar[0]+'</i> instead of <i>{properties:{}}</i>'; }
+ if( !md.items[0].properties.bar[0].properties ) { return 'properties.bar[0].properties <i>'+md.items[0].properties.bar[0].properties+'</i> instead of <i>{}</i>'; }
+ return '';
+}
+
+</script>
+
+<div draggable='true' itemscope></div><div></div><div></div>
+
+<p>Use your pointing device to drag the orange box to the pink box, then back to the blue box, and release it.</p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/microdata/005.html b/tests/wpt/web-platform-tests/html/editing/dnd/microdata/005.html
new file mode 100644
index 00000000000..3a10d90a12e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/microdata/005.html
@@ -0,0 +1,115 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - microdata with nested item as non-property</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ position: absolute;
+ top: 8px;
+ left: 8px;
+ }
+ body > div * {
+ display: none;
+ }
+ body > div + div {
+ background-color: navy;
+ left: 250px;
+ }
+ body > div + div + div {
+ background-color: fuchsia;
+ left: 500px;
+ }
+ p:first-of-type {
+ margin-top: 220px;
+ }
+</style>
+
+<script>
+
+function makeEl(eltype,props,contents) {
+ var elem = document.createElement(eltype);
+ for( var i in props ) {
+ if( props.hasOwnProperty(i) ) {
+ elem.setAttribute(i,props[i]);
+ }
+ }
+ if( contents ) {
+ elem.innerHTML = contents;
+ }
+ return elem;
+}
+
+var orange, fails = [], doneonce = false;
+window.onload = function() {
+ orange = document.getElementsByTagName('div')[0];
+
+ orange.appendChild( makeEl('div',{itemprop:'foo',itemscope:'itemscope'},'') );
+ orange.appendChild( makeEl('div',{itemscope:'itemscope'},'') );
+ orange.lastChild.appendChild( makeEl('div',{itemprop:'bar'},'test') );
+ orange.appendChild( makeEl('div',{itemprop:'bar',itemscope:'itemscope'},'') );
+
+ orange.ondragstart = function(e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('Text', 'dummy text');
+ var err;
+ if( err = checkprops(e.dataTransfer.getData('application/microdata+json')) ) {
+ fails[fails.length] = e.type + ' ' + err;
+ }
+ };
+ orange.nextSibling.ondragenter = orange.nextSibling.ondragleave = orange.nextSibling.ondragover =
+ orange.ondrag = orange.ondragend = function(e) {
+ if( e.type == 'dragover' || e.type == 'dragenter' ) {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'copy';
+ }
+ if( e.dataTransfer.getData('application/microdata+json') ) {
+ fails[fails.length] = e.type + ' unexpectedly had microdata (security restriction)';
+ }
+ };
+ orange.nextSibling.ondrop = function(e) {
+ var err;
+ if( err = checkprops(e.dataTransfer.getData('application/microdata+json')) ) {
+ fails[fails.length] = e.type + ' ' + err;
+ }
+ if( e.type != 'drop' ) { return; }
+ if( doneonce ) { return; }
+ doneonce = true;
+ setTimeout(function () {
+ document.getElementsByTagName('p')[0].innerHTML = fails.length ? ( 'FAIL: ' + fails.join('<br>') ) : 'PASS';
+ fails = [];
+ }, 200 );
+ };
+
+};
+function checkprops(md) {
+ // http://dev.w3.org/html5/md/#drag-and-drop
+ //"The user agent must take the list of dragged nodes and extract the microdata from those nodes into a JSON form"
+ // http://dev.w3.org/html5/spec/dnd.html#drag-and-drop-processing-model
+ //"the list of dragged nodes contains only the source node, if any."
+ //nested items should only be in the items list if they are in a dragged *selection*
+ var i;
+ if( !md ) { return 'no microdata'; }
+ md = JSON.parse(md);
+ if( !md.items ) { return 'no items'; }
+ if( md.items.length != 1 ) { return md.items.length+' items instead of 1'; }
+ if( !md.items[0].properties ) { return 'no properties'; }
+ if( !md.items[0].properties.foo ) { return 'no properties.foo'; }
+ if( !md.items[0].properties.bar ) { return 'no properties.bar'; }
+ if( md.items[0].properties.foo.length != 1 ) { return 'properties.foo length '+md.items[0].properties.foo.length+' instead of 1'; }
+ if( md.items[0].properties.bar.length != 1 ) { return 'properties.bar length '+md.items[0].properties.bar.length+' instead of 1'; }
+
+ if( !md.items[0].properties.foo[0] ) { return 'properties.foo[0] <i>'+md.items[0].properties.foo[0]+'</i> instead of <i>{properties:{}}</i>'; }
+ if( !md.items[0].properties.foo[0].properties ) { return 'properties.foo[0].properties <i>'+md.items[0].properties.foo[0].properties+'</i> instead of <i>{}</i>'; }
+
+ if( !md.items[0].properties.bar[0] ) { return 'properties.bar[0] <i>'+md.items[0].properties.bar[0]+'</i> instead of <i>{properties:{}}</i>'; }
+ if( !md.items[0].properties.bar[0].properties ) { return 'properties.bar[0].properties <i>'+md.items[0].properties.bar[0].properties+'</i> instead of <i>{}</i>'; }
+ return '';
+}
+
+</script>
+
+<div draggable='true' itemscope></div><div></div><div></div>
+
+<p>Use your pointing device to drag the orange box to the pink box, then back to the blue box, and release it.</p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/microdata/006.html b/tests/wpt/web-platform-tests/html/editing/dnd/microdata/006.html
new file mode 100644
index 00000000000..ce45f47ed37
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/microdata/006.html
@@ -0,0 +1,105 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - microdata with type and id</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ position: absolute;
+ top: 8px;
+ left: 8px;
+ }
+ body > div * {
+ display: none;
+ }
+ body > div + div {
+ background-color: navy;
+ left: 250px;
+ }
+ body > div + div + div {
+ background-color: fuchsia;
+ left: 500px;
+ }
+ p:first-of-type {
+ margin-top: 220px;
+ }
+</style>
+
+<script>
+
+function makeEl(eltype,props,contents) {
+ var elem = document.createElement(eltype);
+ for( var i in props ) {
+ if( props.hasOwnProperty(i) ) {
+ elem.setAttribute(i,props[i]);
+ }
+ }
+ if( contents ) {
+ elem.innerHTML = contents;
+ }
+ return elem;
+}
+
+var orange, fails = [], doneonce = false;
+window.onload = function() {
+ orange = document.getElementsByTagName('div')[0];
+
+ orange.appendChild( makeEl('div',{itemprop:'foo',itemscope:'itemscope',itemtype:'http://example.com/',id:'id2',itemid:'http://example.com/bar'},'') );
+
+ orange.ondragstart = function(e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('Text', 'dummy text');
+ var err;
+ if( err = checkprops(e.dataTransfer.getData('application/microdata+json')) ) {
+ fails[fails.length] = e.type + ' ' + err;
+ }
+ };
+ orange.nextSibling.ondragenter = orange.nextSibling.ondragleave = orange.nextSibling.ondragover =
+ orange.ondrag = orange.ondragend = function(e) {
+ if( e.type == 'dragover' || e.type == 'dragenter' ) {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'copy';
+ }
+ if( e.dataTransfer.getData('application/microdata+json') ) {
+ fails[fails.length] = e.type + ' unexpectedly had microdata (security restriction)';
+ }
+ };
+ orange.nextSibling.ondrop = function(e) {
+ var err;
+ if( err = checkprops(e.dataTransfer.getData('application/microdata+json')) ) {
+ fails[fails.length] = e.type + ' ' + err;
+ }
+ if( e.type != 'drop' ) { return; }
+ if( doneonce ) { return; }
+ doneonce = true;
+ setTimeout(function () {
+ document.getElementsByTagName('p')[0].innerHTML = fails.length ? ( 'FAIL: ' + fails.join('<br>') ) : 'PASS';
+ fails = [];
+ }, 200 );
+ };
+
+};
+function checkprops(md) {
+ var i;
+ if( !md ) { return 'no microdata'; }
+ md = JSON.parse(md);
+ if( !md.items ) { return 'no items'; }
+ if( md.items.length != 1 ) { return md.items.length+' items instead of 1'; }
+ if( md.items[0].type != orange.getAttribute('itemtype') ) { return 'items[0].type <i>'+md.items[0].type+'</i> instead of <i>'+orange.getAttribute('itemtype')+'</i>'; }
+ if( md.items[0].id != orange.getAttribute('itemid') ) { return 'items[0].id <i>'+md.items[0].id+'</i> instead of <i>'+orange.getAttribute('itemid')+'</i>'; }
+ if( !md.items[0].properties ) { return 'no properties'; }
+ if( !md.items[0].properties.foo ) { return 'no properties.foo'; }
+ if( md.items[0].properties.foo.length != 1 ) { return 'properties.foo length '+md.items[0].properties.foo.length+' instead of 1'; }
+ if( !md.items[0].properties.foo[0] ) { return 'properties.foo[0] <i>'+md.items[0].properties.foo[0]+'</i> instead of <i>{...}</i>'; }
+ if( md.items[0].properties.foo[0].type != orange.firstChild.getAttribute('itemtype') ) { return 'items[0].properties.foo[0].type <i>'+md.items[0].properties.foo[0].type+'</i> instead of <i>'+orange.firstChild.getAttribute('itemtype')+'</i>'; }
+ if( md.items[0].properties.foo[0].id != orange.firstChild.getAttribute('itemid') ) { return 'items[0].properties.foo[0].id <i>'+md.items[0].properties.foo[0].id+'</i> instead of <i>'+orange.firstChild.getAttribute('itemid')+'</i>'; }
+ if( !md.items[0].properties.foo[0].properties ) { return 'properties.foo[0].properties <i>'+md.items[0].properties.foo[0].properties+'</i> instead of <i>{}</i>'; }
+ return '';
+}
+
+</script>
+
+<div draggable='true' itemscope id='id1' itemtype='http://example.org/' itemid='http://example.org/foo'></div><div></div><div></div>
+
+<p>Use your pointing device to drag the orange box to the pink box, then back to the blue box, and release it.</p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/microdata/007.html b/tests/wpt/web-platform-tests/html/editing/dnd/microdata/007.html
new file mode 100644
index 00000000000..e890d803546
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/microdata/007.html
@@ -0,0 +1,116 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - microdata with multiply named item as property</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ position: absolute;
+ top: 8px;
+ left: 8px;
+ }
+ body > div * {
+ display: none;
+ }
+ body > div + div {
+ background-color: navy;
+ left: 250px;
+ }
+ body > div + div + div {
+ background-color: fuchsia;
+ left: 500px;
+ }
+ p:first-of-type {
+ margin-top: 220px;
+ }
+</style>
+
+<script>
+
+function makeEl(eltype,props,contents) {
+ var elem = document.createElement(eltype);
+ for( var i in props ) {
+ if( props.hasOwnProperty(i) ) {
+ elem.setAttribute(i,props[i]);
+ }
+ }
+ if( contents ) {
+ elem.innerHTML = contents;
+ }
+ return elem;
+}
+
+var orange, fails = [], doneonce = false;
+window.onload = function() {
+ orange = document.getElementsByTagName('div')[0];
+
+ orange.appendChild( makeEl('div',{itemprop:'foo bar',itemscope:'itemscope'},'') );
+ orange.lastChild.appendChild( makeEl('div',{itemprop:'baz'},'test') );
+
+ orange.ondragstart = function(e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('Text', 'dummy text');
+ var err;
+ if( err = checkprops(e.dataTransfer.getData('application/microdata+json')) ) {
+ fails[fails.length] = e.type + ' ' + err;
+ }
+ };
+ orange.nextSibling.ondragenter = orange.nextSibling.ondragleave = orange.nextSibling.ondragover =
+ orange.ondrag = orange.ondragend = function(e) {
+ if( e.type == 'dragover' || e.type == 'dragenter' ) {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'copy';
+ }
+ if( e.dataTransfer.getData('application/microdata+json') ) {
+ fails[fails.length] = e.type + ' unexpectedly had microdata (security restriction)';
+ }
+ };
+ orange.nextSibling.ondrop = function(e) {
+ var err;
+ if( err = checkprops(e.dataTransfer.getData('application/microdata+json')) ) {
+ fails[fails.length] = e.type + ' ' + err;
+ }
+ if( e.type != 'drop' ) { return; }
+ if( doneonce ) { return; }
+ doneonce = true;
+ setTimeout(function () {
+ document.getElementsByTagName('p')[0].innerHTML = fails.length ? ( 'FAIL: ' + fails.join('<br>') ) : 'PASS';
+ fails = [];
+ }, 200 );
+ };
+
+};
+function checkprops(md) {
+ var i;
+ if( !md ) { return 'no microdata'; }
+ md = JSON.parse(md);
+ if( !md.items ) { return 'no items'; }
+ if( md.items.length != 1 ) { return md.items.length+' items instead of 1'; }
+ if( !md.items[0].properties ) { return 'no properties'; }
+ if( !md.items[0].properties.foo ) { return 'no properties.foo'; }
+ if( !md.items[0].properties.bar ) { return 'no properties.bar'; }
+ if( md.items[0].properties.baz ) { return 'properties.baz should not exist'; }
+ if( md.items[0].properties.foo.length != 1 ) { return 'properties.foo length '+md.items[0].properties.foo.length+' instead of 1'; }
+ if( md.items[0].properties.bar.length != 1 ) { return 'properties.bar length '+md.items[0].properties.bar.length+' instead of 1'; }
+
+ if( !md.items[0].properties.foo[0] ) { return 'properties.foo[1] <i>'+md.items[0].properties.foo[0]+'</i> instead of <i>{properties:{baz:[test]}}</i>'; }
+ if( !md.items[0].properties.foo[0].properties ) { return 'properties.foo[0].properties <i>'+md.items[0].properties.foo[0].properties+'</i> instead of <i>{baz:[test]}</i>'; }
+ if( !md.items[0].properties.foo[0].properties.baz ) { return 'properties.foo[0].properties.baz <i>'+md.items[0].properties.foo[0].properties.baz+'</i> instead of <i>[test]</i>'; }
+ if( !md.items[0].properties.foo[0].properties.baz.length ) { return 'properties.foo[0].properties.baz.length <i>'+md.items[0].properties.foo[0].properties.baz.length+'</i> instead of 1'; }
+ if( md.items[0].properties.foo[0].properties.baz[0] != 'test') { return 'properties.foo[0].properties.baz[0] <i>'+md.items[0].properties.foo[0].properties.baz[0]+'</i> instead of <i>test</i>'; }
+
+ if( !md.items[0].properties.bar[0] ) { return 'properties.bar[1] <i>'+md.items[0].properties.bar[0]+'</i> instead of <i>{properties:{baz:[test]}}</i>'; }
+ if( !md.items[0].properties.bar[0].properties ) { return 'properties.bar[0].properties <i>'+md.items[0].properties.bar[0].properties+'</i> instead of <i>{baz:[test]}</i>'; }
+ if( !md.items[0].properties.bar[0].properties.baz ) { return 'properties.bar[0].properties.baz <i>'+md.items[0].properties.bar[0].properties.baz+'</i> instead of <i>[test]</i>'; }
+ if( !md.items[0].properties.bar[0].properties.baz.length ) { return 'properties.bar[0].properties.baz.length <i>'+md.items[0].properties.bar[0].properties.baz.length+'</i> instead of 1'; }
+ if( md.items[0].properties.bar[0].properties.baz[0] != 'test') { return 'properties.bar[0].properties.baz[0] <i>'+md.items[0].properties.bar[0].properties.baz[0]+'</i> instead of <i>test</i>'; }
+
+ return '';
+}
+
+</script>
+
+<div draggable='true' itemscope></div><div></div><div></div>
+
+<p>Use your pointing device to drag the orange box to the pink box, then back to the blue box, and release it.</p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/microdata/008.html b/tests/wpt/web-platform-tests/html/editing/dnd/microdata/008.html
new file mode 100644
index 00000000000..00ca61e05d1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/microdata/008.html
@@ -0,0 +1,94 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - no microdata for selection with no items</title>
+<style>
+ body > div {
+ height: 100px;
+ width: 200px;
+ background-color: fuchsia;
+ position: absolute;
+ top: 8px;
+ left: 8px;
+ }
+ span span {
+ display: none;
+ }
+ body > div + div {
+ background-color: navy;
+ top: 116px;
+ }
+ body > div + div + div {
+ background-color: orange;
+ top: 224px;
+ }
+ p:first-of-type {
+ margin-top: 350px;
+ }
+</style>
+
+<script>
+
+function makeEl(eltype,props,contents) {
+ var elem = document.createElement(eltype);
+ for( var i in props ) {
+ if( props.hasOwnProperty(i) ) {
+ elem.setAttribute(i,props[i]);
+ }
+ }
+ if( contents ) {
+ elem.innerHTML = contents;
+ }
+ return elem;
+}
+
+var orange, fails = [], doneonce = false;
+window.onload = function() {
+ orange = document.getElementsByTagName('div')[2];
+ orange.ondragstart = function(e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('Text', 'dummy text');
+ var err;
+ if( err = checkprops(e.dataTransfer.getData('application/microdata+json')) ) {
+ fails[fails.length] = e.type + ' ' + err;
+ }
+ };
+ orange.previousSibling.ondragenter = orange.previousSibling.ondragleave = orange.previousSibling.ondragover =
+ orange.ondrag = orange.ondragend = function(e) {
+ if( e.type == 'dragover' || e.type == 'dragenter' ) {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'copy';
+ }
+ if( e.dataTransfer.getData('application/microdata+json') ) {
+ fails[fails.length] = e.type + ' unexpectedly had microdata (security restriction)';
+ }
+ };
+ orange.previousSibling.ondrop = function(e) {
+ var err;
+ if( err = checkprops(e.dataTransfer.getData('application/microdata+json')) ) {
+ fails[fails.length] = e.type + ' ' + err;
+ }
+ if( e.type != 'drop' ) { return; }
+ if( doneonce ) { return; }
+ doneonce = true;
+ setTimeout(function () {
+ document.getElementsByTagName('p')[0].innerHTML = fails.length ? ( 'FAIL: ' + fails.join('<br>') ) : 'PASS';
+ fails = [];
+ }, 200 );
+ };
+
+};
+function checkprops(md) {
+ var i;
+ if( !md ) { return 'no microdata'; }
+ md = JSON.parse(md);
+ if( !md.items ) { return 'no items collection'; }
+ if( md.items.length != 0 ) { return 'unexpected items found'; }
+ return '';
+}
+
+</script>
+
+<div></div><div></div><div>01<span>23</span>45<span>67</span>89</div>
+
+<p>Use your pointing device to select the text substring "12345678" above, drag the selection upwards to the pink box,
+then back to the blue box, and release it.</p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/microdata/009.html b/tests/wpt/web-platform-tests/html/editing/dnd/microdata/009.html
new file mode 100644
index 00000000000..7ac0a6576e5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/microdata/009.html
@@ -0,0 +1,98 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - microdata for selection surrounding one item</title>
+<style>
+ body > div {
+ height: 100px;
+ width: 200px;
+ background-color: fuchsia;
+ position: absolute;
+ top: 8px;
+ left: 8px;
+ }
+ span * {
+ display: none;
+ }
+ body > div + div {
+ background-color: navy;
+ top: 116px;
+ }
+ body > div + div + div {
+ background-color: orange;
+ top: 224px;
+ }
+ p:first-of-type {
+ margin-top: 350px;
+ }
+</style>
+
+<script>
+
+function makeEl(eltype,props,contents) {
+ var elem = document.createElement(eltype);
+ for( var i in props ) {
+ if( props.hasOwnProperty(i) ) {
+ elem.setAttribute(i,props[i]);
+ }
+ }
+ if( contents ) {
+ elem.innerHTML = contents;
+ }
+ return elem;
+}
+
+var orange, fails = [], doneonce = false;
+window.onload = function() {
+ orange = document.getElementsByTagName('div')[2];
+ orange.childNodes[1].appendChild( makeEl('span',{itemprop:'foo'},'test') );
+ orange.ondragstart = function(e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('Text', 'dummy text');
+ var err;
+ if( err = checkprops(e.dataTransfer.getData('application/microdata+json')) ) {
+ fails[fails.length] = e.type + ' ' + err;
+ }
+ };
+ orange.previousSibling.ondragenter = orange.previousSibling.ondragleave = orange.previousSibling.ondragover =
+ orange.ondrag = orange.ondragend = function(e) {
+ if( e.type == 'dragover' || e.type == 'dragenter' ) {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'copy';
+ }
+ if( e.dataTransfer.getData('application/microdata+json') ) {
+ fails[fails.length] = e.type + ' unexpectedly had microdata (security restriction)';
+ }
+ };
+ orange.previousSibling.ondrop = function(e) {
+ var err;
+ if( err = checkprops(e.dataTransfer.getData('application/microdata+json')) ) {
+ fails[fails.length] = e.type + ' ' + err;
+ }
+ if( e.type != 'drop' ) { return; }
+ if( doneonce ) { return; }
+ doneonce = true;
+ setTimeout(function () {
+ document.getElementsByTagName('p')[0].innerHTML = fails.length ? ( 'FAIL: ' + fails.join('<br>') ) : 'PASS';
+ fails = [];
+ }, 200 );
+ };
+
+};
+function checkprops(md) {
+ var i;
+ if( !md ) { return 'no microdata'; }
+ md = JSON.parse(md);
+ if( !md.items || md.items.length != 1 ) { return 'no items'; }
+ if( !md.items[0].properties ) { return 'no properties'; }
+ if( !md.items[0].properties.foo ) { return 'no properties.foo'; }
+ if( md.items[0].properties.foo.length != 1 ) { return 'properties.foo length '+md.items[0].properties.foo.length+' instead of 1'; }
+ if( md.items[0].properties.foo[0] != orange.childNodes[1].properties.namedItem('foo').getValues()[0] ) { return 'properties.foo[0] <i>'+md.items[0].properties.foo[0]+'</i> instead of <i>'+orange.childNodes[1].properties.namedItem('foo').getValues()[0]+'</i>'; }
+ return '';
+}
+
+</script>
+
+<div></div><div></div><div>01<span itemscope>23</span>45<span>67</span>89</div>
+
+<p>Use your pointing device to select the text substring "12345678" above, drag the selection upwards to the pink box,
+then back to the blue box, and release it.</p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/microdata/010.html b/tests/wpt/web-platform-tests/html/editing/dnd/microdata/010.html
new file mode 100644
index 00000000000..bada1b706a5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/microdata/010.html
@@ -0,0 +1,104 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - microdata for selection surrounding multiple items</title>
+<style>
+ body > div {
+ height: 100px;
+ width: 200px;
+ background-color: fuchsia;
+ position: absolute;
+ top: 8px;
+ left: 8px;
+ }
+ span * {
+ display: none;
+ }
+ body > div + div {
+ background-color: navy;
+ top: 116px;
+ }
+ body > div + div + div {
+ background-color: orange;
+ top: 224px;
+ }
+ p:first-of-type {
+ margin-top: 350px;
+ }
+</style>
+
+<script>
+
+function makeEl(eltype,props,contents) {
+ var elem = document.createElement(eltype);
+ for( var i in props ) {
+ if( props.hasOwnProperty(i) ) {
+ elem.setAttribute(i,props[i]);
+ }
+ }
+ if( contents ) {
+ elem.innerHTML = contents;
+ }
+ return elem;
+}
+
+var orange, fails = [], doneonce = false;
+window.onload = function() {
+ orange = document.getElementsByTagName('div')[2];
+ orange.childNodes[1].appendChild( makeEl('span',{itemprop:'foo'},'test') );
+ orange.childNodes[3].appendChild( makeEl('span',{itemprop:'bar'},'test') );
+ orange.ondragstart = function(e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('Text', 'dummy text');
+ var err;
+ if( err = checkprops(e.dataTransfer.getData('application/microdata+json')) ) {
+ fails[fails.length] = e.type + ' ' + err;
+ }
+ };
+ orange.previousSibling.ondragenter = orange.previousSibling.ondragleave = orange.previousSibling.ondragover =
+ orange.ondrag = orange.ondragend = function(e) {
+ if( e.type == 'dragover' || e.type == 'dragenter' ) {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'copy';
+ }
+ if( e.dataTransfer.getData('application/microdata+json') ) {
+ fails[fails.length] = e.type + ' unexpectedly had microdata (security restriction)';
+ }
+ };
+ orange.previousSibling.ondrop = function(e) {
+ var err;
+ if( err = checkprops(e.dataTransfer.getData('application/microdata+json')) ) {
+ fails[fails.length] = e.type + ' ' + err;
+ }
+ if( e.type != 'drop' ) { return; }
+ if( doneonce ) { return; }
+ doneonce = true;
+ setTimeout(function () {
+ document.getElementsByTagName('p')[0].innerHTML = fails.length ? ( 'FAIL: ' + fails.join('<br>') ) : 'PASS';
+ fails = [];
+ }, 200 );
+ };
+
+};
+function checkprops(md) {
+ var i;
+ if( !md ) { return 'no microdata'; }
+ md = JSON.parse(md);
+ if( !md.items ) { return 'no items'; }
+ if( md.items.length != 2 ) { return md.items.length+' items instead of 2'; }
+ if( !md.items[0].properties ) { return 'no items[0].properties'; }
+ if( !md.items[0].properties.foo ) { return 'no items[0].properties.foo'; }
+ if( md.items[0].properties.foo.length != 1 ) { return 'items[0].properties.foo length '+md.items[0].properties.foo.length+' instead of 1'; }
+ if( md.items[0].properties.foo[0] != orange.childNodes[1].properties.namedItem('foo').getValues()[0] ) { return 'items[0].properties.foo[0] <i>'+md.items[0].properties.foo[0]+'</i> instead of <i>'+orange.childNodes[1].properties.namedItem('foo').getValues()[0]+'</i>'; }
+ if( !md.items[1].properties ) { return 'no items[1].properties'; }
+ if( !md.items[1].properties.bar ) { return 'no items[1].properties.bar'; }
+ if( md.items[1].properties.bar.length != 1 ) { return 'items[1].properties.bar length '+md.items[1].properties.bar.length+' instead of 1'; }
+ if( md.items[1].properties.bar[0] != orange.childNodes[1].properties.namedItem('foo').getValues()[0] ) { return 'items[1].properties.bar[0] <i>'+md.items[1].properties.bar[0]+'</i> instead of <i>'+orange.childNodes[1].properties.namedItem('foo').getValues()[0]+'</i>'; }
+ return '';
+}
+
+</script>
+
+<div></div><div></div><div>01<span itemscope>23</span>45<span itemscope>67</span>89</div>
+
+<p>Use your pointing device to select the text substring "12345678" above, drag the selection upwards to the pink box,
+then back to the blue box, and release it.</p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/microdata/011.html b/tests/wpt/web-platform-tests/html/editing/dnd/microdata/011.html
new file mode 100644
index 00000000000..04b49992b61
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/microdata/011.html
@@ -0,0 +1,107 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - microdata for selection partially intersecting multiple items</title>
+<style>
+ body > div {
+ height: 100px;
+ width: 200px;
+ background-color: fuchsia;
+ position: absolute;
+ top: 8px;
+ left: 8px;
+ }
+ span * {
+ display: none;
+ }
+ body > div + div {
+ background-color: navy;
+ top: 116px;
+ }
+ body > div + div + div {
+ background-color: orange;
+ top: 224px;
+ }
+ p:first-of-type {
+ margin-top: 350px;
+ }
+</style>
+
+<script>
+
+function makeEl(eltype,props,contents) {
+ var elem = document.createElement(eltype);
+ for( var i in props ) {
+ if( props.hasOwnProperty(i) ) {
+ elem.setAttribute(i,props[i]);
+ }
+ }
+ if( contents ) {
+ elem.innerHTML = contents;
+ }
+ return elem;
+}
+
+var orange, fails = [], doneonce = false;
+window.onload = function() {
+ orange = document.getElementsByTagName('div')[2];
+ orange.childNodes[1].appendChild( makeEl('span',{itemprop:'foo'},'test') );
+ orange.childNodes[3].appendChild( makeEl('span',{itemprop:'bar'},'test') );
+ orange.ondragstart = function(e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('Text', 'dummy text');
+ var err;
+ if( err = checkprops(e.dataTransfer.getData('application/microdata+json')) ) {
+ fails[fails.length] = e.type + ' ' + err;
+ }
+ };
+ orange.previousSibling.ondragenter = orange.previousSibling.ondragleave = orange.previousSibling.ondragover =
+ orange.ondrag = orange.ondragend = function(e) {
+ if( e.type == 'dragover' || e.type == 'dragenter' ) {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'copy';
+ }
+ if( e.dataTransfer.getData('application/microdata+json') ) {
+ fails[fails.length] = e.type + ' unexpectedly had microdata (security restriction)';
+ }
+ };
+ orange.previousSibling.ondrop = function(e) {
+ var err;
+ if( err = checkprops(e.dataTransfer.getData('application/microdata+json')) ) {
+ fails[fails.length] = e.type + ' ' + err;
+ }
+ if( e.type != 'drop' ) { return; }
+ if( doneonce ) { return; }
+ doneonce = true;
+ setTimeout(function () {
+ document.getElementsByTagName('p')[0].innerHTML = fails.length ? ( 'FAIL: ' + fails.join('<br>') ) : 'PASS';
+ fails = [];
+ }, 200 );
+ };
+
+};
+function checkprops(md) {
+ // http://dev.w3.org/html5/spec/dnd.html#list-of-dragged-nodes
+ //"If it is a selection that is being dragged, then the list of dragged nodes contains, in tree order, every node that is partially or completely included in the selection (including all their ancestors)."
+ //given this "ancestors" situation, what is to stop every item in the body from being included? oversight perhaps? tests 18-20 cover this more extensively
+ var i;
+ if( !md ) { return 'no microdata'; }
+ md = JSON.parse(md);
+ if( !md.items ) { return 'no items'; }
+ if( md.items.length != 2 ) { return md.items.length+' items instead of 2'; }
+ if( !md.items[0].properties ) { return 'no items[0].properties'; }
+ if( !md.items[0].properties.foo ) { return 'no items[0].properties.foo'; }
+ if( md.items[0].properties.foo.length != 1 ) { return 'items[0].properties.foo length '+md.items[0].properties.foo.length+' instead of 1'; }
+ if( md.items[0].properties.foo[0] != orange.childNodes[1].properties.namedItem('foo').getValues()[0] ) { return 'items[0].properties.foo[0] <i>'+md.items[0].properties.foo[0]+'</i> instead of <i>'+orange.childNodes[1].properties.namedItem('foo').getValues()[0]+'</i>'; }
+ if( !md.items[1].properties ) { return 'no items[1].properties'; }
+ if( !md.items[1].properties.bar ) { return 'no items[1].properties.bar'; }
+ if( md.items[1].properties.bar.length != 1 ) { return 'items[1].properties.bar length '+md.items[1].properties.bar.length+' instead of 1'; }
+ if( md.items[1].properties.bar[0] != orange.childNodes[1].properties.namedItem('foo').getValues()[0] ) { return 'items[1].properties.bar[0] <i>'+md.items[1].properties.bar[0]+'</i> instead of <i>'+orange.childNodes[1].properties.namedItem('foo').getValues()[0]+'</i>'; }
+ return '';
+}
+
+</script>
+
+<div></div><div></div><div>01<span itemscope>23</span>45<span itemscope>67</span>89</div>
+
+<p>Use your pointing device to select the text substring "3456" above, drag the selection upwards to the pink box,
+then back to the blue box, and release it.</p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/microdata/012.html b/tests/wpt/web-platform-tests/html/editing/dnd/microdata/012.html
new file mode 100644
index 00000000000..c09453faa42
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/microdata/012.html
@@ -0,0 +1,104 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - microdata for selection surrounding nested property items</title>
+<style>
+ body > div {
+ height: 100px;
+ width: 200px;
+ background-color: fuchsia;
+ position: absolute;
+ top: 8px;
+ left: 8px;
+ }
+ span * {
+ display: none;
+ }
+ body > div + div {
+ background-color: navy;
+ top: 116px;
+ }
+ body > div + div + div {
+ background-color: orange;
+ top: 224px;
+ }
+ p:first-of-type {
+ margin-top: 350px;
+ }
+</style>
+
+<script>
+
+function makeEl(eltype,props,contents) {
+ var elem = document.createElement(eltype);
+ for( var i in props ) {
+ if( props.hasOwnProperty(i) ) {
+ elem.setAttribute(i,props[i]);
+ }
+ }
+ if( contents ) {
+ elem.innerHTML = contents;
+ }
+ return elem;
+}
+
+var orange, fails = [], doneonce = false;
+window.onload = function() {
+ orange = document.getElementsByTagName('div')[2];
+ orange.childNodes[1].appendChild( makeEl('span',{itemscope:'itemscope',itemprop:'foo'},'test') );
+ orange.childNodes[1].lastChild.appendChild( makeEl('span',{itemprop:'bar'},'test') );
+ orange.ondragstart = function(e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('Text', 'dummy text');
+ var err;
+ if( err = checkprops(e.dataTransfer.getData('application/microdata+json')) ) {
+ fails[fails.length] = e.type + ' ' + err;
+ }
+ };
+ orange.previousSibling.ondragenter = orange.previousSibling.ondragleave = orange.previousSibling.ondragover =
+ orange.ondrag = orange.ondragend = function(e) {
+ if( e.type == 'dragover' || e.type == 'dragenter' ) {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'copy';
+ }
+ if( e.dataTransfer.getData('application/microdata+json') ) {
+ fails[fails.length] = e.type + ' unexpectedly had microdata (security restriction)';
+ }
+ };
+ orange.previousSibling.ondrop = function(e) {
+ var err;
+ if( err = checkprops(e.dataTransfer.getData('application/microdata+json')) ) {
+ fails[fails.length] = e.type + ' ' + err;
+ }
+ if( e.type != 'drop' ) { return; }
+ if( doneonce ) { return; }
+ doneonce = true;
+ setTimeout(function () {
+ document.getElementsByTagName('p')[0].innerHTML = fails.length ? ( 'FAIL: ' + fails.join('<br>') ) : 'PASS';
+ fails = [];
+ }, 200 );
+ };
+
+};
+function checkprops(md) {
+ //items should be represented at the top level only if they do not have the itemprop attribute
+ var i;
+ if( !md ) { return 'no microdata'; }
+ md = JSON.parse(md);
+ if( !md.items ) { return 'no items'; }
+ if( md.items.length != 1 ) { return md.items.length+' items instead of 1'; }
+ if( !md.items[0].properties ) { return 'no items[0].properties'; }
+ if( !md.items[0].properties.foo ) { return 'no items[0].properties.foo'; }
+ if( md.items[0].properties.foo.length != 1 ) { return 'items[0].properties.foo length '+md.items[0].properties.foo.length+' instead of 1'; }
+ if( !md.items[0].properties.foo[0].properties ) { return 'items[1].properties.foo[0].properties <i>'+md.items[0].properties.foo[0].properties+'</i> instead of <i>{bar:[test]}</i>'; }
+ if( !md.items[0].properties.foo[0].properties.bar ) { return 'items[1].properties.foo[0].properties.bar <i>'+md.items[0].properties.foo[0].properties.bar+'</i> instead of <i>[test]</i>'; }
+ if( md.items[0].properties.foo[0].properties.bar.length != 1 ) { return 'items[1].properties.foo[0].properties.bar.length <i>'+md.items[0].properties.foo[0].properties.bar.length+'</i> instead of 1'; }
+ if( md.items[0].properties.foo[0].properties.bar[0] != 'test') { return 'items[1].properties.foo[0].properties.bar[0] <i>'+md.items[0].properties.foo[0].properties.bar[0]+'</i> instead of <i>test</i>'; }
+ return '';
+}
+
+</script>
+
+<div></div><div></div><div>01<span itemscope>23</span>45<span itemscope itemprop="baz">67</span>89</div>
+
+<p>Use your pointing device to select the text substring "12345678" above, drag the selection upwards to the pink box,
+then back to the blue box, and release it.</p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/microdata/013.html b/tests/wpt/web-platform-tests/html/editing/dnd/microdata/013.html
new file mode 100644
index 00000000000..67f3b31f225
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/microdata/013.html
@@ -0,0 +1,104 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - microdata for selection surrounding nested non-property items</title>
+<style>
+ body > div {
+ height: 100px;
+ width: 200px;
+ background-color: fuchsia;
+ position: absolute;
+ top: 8px;
+ left: 8px;
+ }
+ span * {
+ display: none;
+ }
+ body > div + div {
+ background-color: navy;
+ top: 116px;
+ }
+ body > div + div + div {
+ background-color: orange;
+ top: 224px;
+ }
+ p:first-of-type {
+ margin-top: 350px;
+ }
+</style>
+
+<script>
+
+function makeEl(eltype,props,contents) {
+ var elem = document.createElement(eltype);
+ for( var i in props ) {
+ if( props.hasOwnProperty(i) ) {
+ elem.setAttribute(i,props[i]);
+ }
+ }
+ if( contents ) {
+ elem.innerHTML = contents;
+ }
+ return elem;
+}
+
+var orange, fails = [], doneonce = false;
+window.onload = function() {
+ orange = document.getElementsByTagName('div')[2];
+ orange.childNodes[1].appendChild( makeEl('span',{itemscope:'itemscope'},'test') );
+ orange.childNodes[1].lastChild.appendChild( makeEl('span',{itemprop:'bar'},'test') );
+ orange.ondragstart = function(e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('Text', 'dummy text');
+ var err;
+ if( err = checkprops(e.dataTransfer.getData('application/microdata+json')) ) {
+ fails[fails.length] = e.type + ' ' + err;
+ }
+ };
+ orange.previousSibling.ondragenter = orange.previousSibling.ondragleave = orange.previousSibling.ondragover =
+ orange.ondrag = orange.ondragend = function(e) {
+ if( e.type == 'dragover' || e.type == 'dragenter' ) {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'copy';
+ }
+ if( e.dataTransfer.getData('application/microdata+json') ) {
+ fails[fails.length] = e.type + ' unexpectedly had microdata (security restriction)';
+ }
+ };
+ orange.previousSibling.ondrop = function(e) {
+ var err;
+ if( err = checkprops(e.dataTransfer.getData('application/microdata+json')) ) {
+ fails[fails.length] = e.type + ' ' + err;
+ }
+ if( e.type != 'drop' ) { return; }
+ if( doneonce ) { return; }
+ doneonce = true;
+ setTimeout(function () {
+ document.getElementsByTagName('p')[0].innerHTML = fails.length ? ( 'FAIL: ' + fails.join('<br>') ) : 'PASS';
+ fails = [];
+ }, 200 );
+ };
+
+};
+function checkprops(md) {
+ //*all* items should be represented at the top level, even if they are nested
+ var i;
+ if( !md ) { return 'no microdata'; }
+ md = JSON.parse(md);
+ if( !md.items ) { return 'no items'; }
+ if( md.items.length != 2 ) { return md.items.length+' items instead of 2'; }
+ if( !md.items[0].properties ) { return 'no items[0].properties'; }
+ if( md.items[0].properties.bar ) { return 'unexpected items[0].properties.bar'; }
+
+ if( !md.items[1].properties ) { return 'no items[1].properties'; }
+ if( !md.items[1].properties.bar ) { return 'no items[1].properties.bar'; }
+ if( md.items[1].properties.bar.length != 1 ) { return 'items[1].properties.bar length '+md.items[1].properties.bar.length+' instead of 1'; }
+ if( md.items[1].properties.bar[0] != 'test' ) { return 'items[1].properties.bar[0] <i>'+md.items[1].properties.bar[0]+'</i> instead of <i>test</i>'; }
+ return '';
+}
+
+</script>
+
+<div></div><div></div><div>01<span itemscope>23</span>45<span>67</span>89</div>
+
+<p>Use your pointing device to select the text substring "12345678" above, drag the selection upwards to the pink box,
+then back to the blue box, and release it.</p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/microdata/014.html b/tests/wpt/web-platform-tests/html/editing/dnd/microdata/014.html
new file mode 100644
index 00000000000..bd0b84c2fd7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/microdata/014.html
@@ -0,0 +1,97 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - microdata with sibling itemref loop</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ position: absolute;
+ top: 8px;
+ left: 8px;
+ }
+ body > div *, span {
+ display: none;
+ }
+ body > div + div {
+ background-color: navy;
+ left: 250px;
+ }
+ body > div + div + div {
+ background-color: fuchsia;
+ left: 500px;
+ }
+ p:first-of-type {
+ margin-top: 220px;
+ }
+</style>
+
+<script>
+
+function makeEl(eltype,props,contents) {
+ var elem = document.createElement(eltype);
+ for( var i in props ) {
+ if( props.hasOwnProperty(i) ) {
+ elem.setAttribute(i,props[i]);
+ }
+ }
+ if( contents ) {
+ elem.innerHTML = contents;
+ }
+ return elem;
+}
+
+var orange, fails = [], doneonce = false;
+window.onload = function() {
+ orange = document.getElementsByTagName('div')[0];
+
+ orange.ondragstart = function(e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('Text', 'dummy text');
+ var err;
+ if( err = checkprops(e.dataTransfer.getData('application/microdata+json')) ) {
+ fails[fails.length] = e.type + ' ' + err;
+ }
+ };
+ orange.nextSibling.ondragenter = orange.nextSibling.ondragleave = orange.nextSibling.ondragover =
+ orange.ondrag = orange.ondragend = function(e) {
+ if( e.type == 'dragover' || e.type == 'dragenter' ) {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'copy';
+ }
+ if( e.dataTransfer.getData('application/microdata+json') ) {
+ fails[fails.length] = e.type + ' unexpectedly had microdata (security restriction)';
+ }
+ };
+ orange.nextSibling.ondrop = function(e) {
+ var err;
+ if( err = checkprops(e.dataTransfer.getData('application/microdata+json')) ) {
+ fails[fails.length] = e.type + ' ' + err;
+ }
+ if( e.type != 'drop' ) { return; }
+ if( doneonce ) { return; }
+ doneonce = true;
+ setTimeout(function () {
+ document.getElementsByTagName('p')[0].innerHTML = fails.length ? ( 'FAIL: ' + fails.join('<br>') ) : 'PASS';
+ fails = [];
+ }, 200 );
+ };
+
+};
+function checkprops(md) {
+ // http://dev.w3.org/html5/md/#extracting-json
+ //"check if the element is a top-level microdata item, and if it is"
+ //as it has itemprop, it is not a top-level item, and should be ignored
+ var i;
+ if( !md ) { return 'no microdata'; }
+ md = JSON.parse(md);
+ if( !md.items ) { return 'no items'; }
+ if( md.items.length != 0 ) { return md.items.length+' items instead of 0'; }
+ return '';
+}
+
+</script>
+
+<div draggable='true' itemscope itemprop='foo' id='id1' itemref='id2'></div><div id='id2' itemprop='bar' itemscope itemref='id1'></div><div></div>
+
+<p>Use your pointing device to drag the orange box to the pink box, then back to the blue box, and release it.</p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/microdata/015.html b/tests/wpt/web-platform-tests/html/editing/dnd/microdata/015.html
new file mode 100644
index 00000000000..597a9e405ef
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/microdata/015.html
@@ -0,0 +1,99 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - microdata with parent itemref loop</title>
+<style>
+ blockquote > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ position: absolute;
+ top: 8px;
+ left: 8px;
+ }
+ blockquote > div *, span {
+ display: none;
+ }
+ blockquote > div + div {
+ background-color: navy;
+ left: 250px;
+ }
+ blockquote > div + div + div {
+ background-color: fuchsia;
+ left: 500px;
+ }
+ p:first-of-type {
+ margin-top: 220px;
+ }
+</style>
+
+<script>
+
+function makeEl(eltype,props,contents) {
+ var elem = document.createElement(eltype);
+ for( var i in props ) {
+ if( props.hasOwnProperty(i) ) {
+ elem.setAttribute(i,props[i]);
+ }
+ }
+ if( contents ) {
+ elem.innerHTML = contents;
+ }
+ return elem;
+}
+
+var orange, fails = [], doneonce = false;
+window.onload = function() {
+ orange = document.getElementsByTagName('div')[0];
+
+ orange.ondragstart = function(e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('Text', 'dummy text');
+ var err;
+ if( err = checkprops(e.dataTransfer.getData('application/microdata+json')) ) {
+ fails[fails.length] = e.type + ' ' + err;
+ }
+ };
+ orange.nextSibling.ondragenter = orange.nextSibling.ondragleave = orange.nextSibling.ondragover =
+ orange.ondrag = orange.ondragend = function(e) {
+ if( e.type == 'dragover' || e.type == 'dragenter' ) {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'copy';
+ }
+ if( e.dataTransfer.getData('application/microdata+json') ) {
+ fails[fails.length] = e.type + ' unexpectedly had microdata (security restriction)';
+ }
+ };
+ orange.nextSibling.ondrop = function(e) {
+ var err;
+ if( err = checkprops(e.dataTransfer.getData('application/microdata+json')) ) {
+ fails[fails.length] = e.type + ' ' + err;
+ }
+ if( e.type != 'drop' ) { return; }
+ if( doneonce ) { return; }
+ doneonce = true;
+ setTimeout(function () {
+ document.getElementsByTagName('p')[0].innerHTML = fails.length ? ( 'FAIL: ' + fails.join('<br>') ) : 'PASS';
+ fails = [];
+ }, 200 );
+ };
+
+};
+function checkprops(md) {
+ // http://dev.w3.org/html5/md/#extracting-json
+ //"check if the element is a top-level microdata item, and if it is"
+ //as it has itemprop, it is not a top-level item, and should be ignored
+ var i;
+ if( !md ) { return 'no microdata'; }
+ md = JSON.parse(md);
+ if( !md.items ) { return 'no items'; }
+ if( md.items.length != 0 ) { return md.items.length+' items instead of 0'; }
+ return '';
+}
+
+</script>
+
+<blockquote id='id1' itemprop='bar' itemscope>
+<div draggable='true' itemscope itemprop='foo' itemref='id1'></div><div></div><div></div>
+</blockquote>
+
+<p>Use your pointing device to drag the orange box to the pink box, then back to the blue box, and release it.</p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/microdata/016.html b/tests/wpt/web-platform-tests/html/editing/dnd/microdata/016.html
new file mode 100644
index 00000000000..4d37d65a2b7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/microdata/016.html
@@ -0,0 +1,160 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - microdata with nested sibling itemref loop</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ position: absolute;
+ top: 8px;
+ left: 8px;
+ }
+ body > div *, span {
+ display: none;
+ }
+ body > div + div {
+ background-color: navy;
+ left: 250px;
+ }
+ body > div + div + div {
+ background-color: fuchsia;
+ left: 500px;
+ }
+ p:first-of-type {
+ margin-top: 220px;
+ }
+</style>
+
+<script>
+
+function makeEl(eltype,props,contents) {
+ var elem = document.createElement(eltype);
+ for( var i in props ) {
+ if( props.hasOwnProperty(i) ) {
+ elem.setAttribute(i,props[i]);
+ }
+ }
+ if( contents ) {
+ elem.innerHTML = contents;
+ }
+ return elem;
+}
+
+var orange, fails = [], doneonce = false;
+window.onload = function() {
+ orange = document.getElementsByTagName('div')[0];
+
+ orange.ondragstart = function(e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('Text', 'dummy text');
+ var err;
+ if( err = checkprops(e.dataTransfer.getData('application/microdata+json')) ) {
+ fails[fails.length] = e.type + ' ' + err;
+ }
+ };
+ orange.nextSibling.ondragenter = orange.nextSibling.ondragleave = orange.nextSibling.ondragover =
+ orange.ondrag = orange.ondragend = function(e) {
+ if( e.type == 'dragover' || e.type == 'dragenter' ) {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'copy';
+ }
+ if( e.dataTransfer.getData('application/microdata+json') ) {
+ fails[fails.length] = e.type + ' unexpectedly had microdata (security restriction)';
+ }
+ };
+ orange.nextSibling.ondrop = function(e) {
+ var err;
+ if( err = checkprops(e.dataTransfer.getData('application/microdata+json')) ) {
+ fails[fails.length] = e.type + ' ' + err;
+ }
+ if( e.type != 'drop' ) { return; }
+ if( doneonce ) { return; }
+ doneonce = true;
+ setTimeout(function () {
+ document.getElementsByTagName('p')[0].innerHTML = fails.length ? ( 'FAIL: ' + fails.join('<br>') ) : 'PASS';
+ fails = [];
+ }, 200 );
+ };
+
+};
+function checkprops(md) {
+ // http://dev.w3.org/html5/md/#extracting-json
+ //"If value is an item, then: If value is in memory, then let value be the string "ERROR"."
+ /*
+Loop detection happens only after the loop has been created, at which point it returns a property value
+of "ERROR" instead of the value which has already been encountered on the stringifying stack.
+Should create the following construct:
+{
+ items:[
+ {
+ properties:{
+ foo:[
+ {
+ properties:{
+ bar:[
+ {
+ properties:{
+ foo:[
+ "ERROR"
+ ]
+ }
+ }
+ ]
+ }
+ }
+ ],
+ bar:[
+ {
+ properties:{
+ foo:[
+ {
+ properties:{
+ bar:[
+ "ERROR"
+ ]
+ }
+ }
+ ]
+ }
+ }
+ ]
+ }
+ }
+ ]
+}
+ */
+
+ var i;
+ if( !md ) { return 'no microdata'; }
+ md = JSON.parse(md);
+ if( !md.items ) { return 'no items'; }
+ if( md.items.length != 1 ) { return md.items.length+' items instead of 1'; }
+ if( !md.items[0].properties ) { return 'no items[0].properties'; }
+ if( !md.items[0].properties.foo ) { return 'no items[0].properties.foo'; }
+ if( md.items[0].properties.foo.length != 1 ) { return 'items[0].properties.foo length '+md.items[0].properties.foo.length+' instead of 1'; }
+ if( !md.items[0].properties.foo[0].properties ) { return 'items[1].properties.foo[0].properties <i>'+md.items[0].properties.foo[0].properties+'</i> instead of object'; }
+ if( !md.items[0].properties.foo[0].properties.bar ) { return 'items[1].properties.foo[0].properties.bar <i>'+md.items[0].properties.foo[0].properties.bar+'</i> instead of array'; }
+ if( md.items[0].properties.foo[0].properties.bar.length != 1 ) { return 'items[1].properties.foo[0].properties.bar.length <i>'+md.items[0].properties.foo[0].properties.bar.length+'</i> instead of 1'; }
+ if( !md.items[0].properties.foo[0].properties.bar[0].properties ) { return 'items[1].properties.foo[0].properties.bar[0].properties <i>'+md.properties.foo[0].properties.bar[0].properties+'</i> instead of object'; }
+ if( !md.items[0].properties.foo[0].properties.bar[0].properties.foo ) { return 'items[1].properties.foo[0].properties.bar[0].properties.foo <i>'+md.items[0].properties.foo[0].properties.bar[0].properties.foo+'</i> instead of array'; }
+ if( md.items[0].properties.foo[0].properties.bar[0].properties.foo.length != 1 ) { return 'items[1].properties.foo[0].properties.bar[0].properties.foo.length <i>'+md.items[0].properties.foo[0].properties.bar[0].properties.foo.length+'</i> instead of 1'; }
+ if( md.items[0].properties.foo[0].properties.bar[0].properties.foo[0] != 'ERROR' ) { return 'items[1].properties.foo[0].properties.bar[0].properties.foo.length <i>'+md.items[0].properties.foo[0].properties.bar[0].properties.foo[0]+'</i> instead of <i>ERROR</a>'; }
+
+ if( !md.items[0].properties.bar ) { return 'no items[0].properties.bar'; }
+ if( md.items[0].properties.bar.length != 1 ) { return 'items[0].properties.bar length '+md.items[0].properties.bar.length+' instead of 1'; }
+ if( !md.items[0].properties.bar[0].properties ) { return 'items[1].properties.bar[0].properties <i>'+md.items[0].properties.bar[0].properties+'</i> instead of object'; }
+ if( !md.items[0].properties.bar[0].properties.foo ) { return 'items[1].properties.bar[0].properties.foo <i>'+md.items[0].properties.bar[0].properties.foo+'</i> instead of array'; }
+ if( md.items[0].properties.bar[0].properties.foo.length != 1 ) { return 'items[1].properties.bar[0].properties.foo.length <i>'+md.items[0].properties.bar[0].properties.foo.length+'</i> instead of 1'; }
+ if( !md.items[0].properties.bar[0].properties.foo[0].properties ) { return 'items[1].properties.bar[0].properties.foo[0].properties <i>'+md.properties.bar[0].properties.foo[0].properties+'</i> instead of object'; }
+ if( !md.items[0].properties.bar[0].properties.foo[0].properties.bar ) { return 'items[1].properties.bar[0].properties.foo[0].properties.bar <i>'+md.items[0].properties.bar[0].properties.foo[0].properties.bar+'</i> instead of array'; }
+ if( md.items[0].properties.bar[0].properties.foo[0].properties.bar.length != 1 ) { return 'items[1].properties.bar[0].properties.foo[0].properties.bar.length <i>'+md.items[0].properties.bar[0].properties.foo[0].properties.bar.length+'</i> instead of 1'; }
+ if( md.items[0].properties.bar[0].properties.foo[0].properties.bar[0] != 'ERROR' ) { return 'items[1].properties.bar[0].properties.foo[0].properties.bar.length <i>'+md.items[0].properties.bar[0].properties.foo[0].properties.bar[0]+'</i> instead of <i>ERROR</a>'; }
+ return '';
+}
+
+</script>
+
+<div draggable='true' itemscope><div itemscope itemprop='foo' id='id1' itemref='id2'></div><div itemscope itemprop='bar' id='id2' itemref='id1'></div></div><div></div><div></div>
+
+<p>Use your pointing device to drag the orange box to the pink box, then back to the blue box, and release it.</p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/microdata/017.html b/tests/wpt/web-platform-tests/html/editing/dnd/microdata/017.html
new file mode 100644
index 00000000000..378c7c97952
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/microdata/017.html
@@ -0,0 +1,137 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - microdata with nested parent itemref loop</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ position: absolute;
+ top: 8px;
+ left: 8px;
+ }
+ body > div *, span {
+ display: none;
+ }
+ body > div + div {
+ background-color: navy;
+ left: 250px;
+ }
+ body > div + div + div {
+ background-color: fuchsia;
+ left: 500px;
+ }
+ p:first-of-type {
+ margin-top: 220px;
+ }
+</style>
+
+<script>
+
+function makeEl(eltype,props,contents) {
+ var elem = document.createElement(eltype);
+ for( var i in props ) {
+ if( props.hasOwnProperty(i) ) {
+ elem.setAttribute(i,props[i]);
+ }
+ }
+ if( contents ) {
+ elem.innerHTML = contents;
+ }
+ return elem;
+}
+
+var orange, fails = [], doneonce = false;
+window.onload = function() {
+ orange = document.getElementsByTagName('div')[0];
+
+ orange.ondragstart = function(e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('Text', 'dummy text');
+ var err;
+ if( err = checkprops(e.dataTransfer.getData('application/microdata+json')) ) {
+ fails[fails.length] = e.type + ' ' + err;
+ }
+ };
+ orange.nextSibling.ondragenter = orange.nextSibling.ondragleave = orange.nextSibling.ondragover =
+ orange.ondrag = orange.ondragend = function(e) {
+ if( e.type == 'dragover' || e.type == 'dragenter' ) {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'copy';
+ }
+ if( e.dataTransfer.getData('application/microdata+json') ) {
+ fails[fails.length] = e.type + ' unexpectedly had microdata (security restriction)';
+ }
+ };
+ orange.nextSibling.ondrop = function(e) {
+ var err;
+ if( err = checkprops(e.dataTransfer.getData('application/microdata+json')) ) {
+ fails[fails.length] = e.type + ' ' + err;
+ }
+ if( e.type != 'drop' ) { return; }
+ if( doneonce ) { return; }
+ doneonce = true;
+ setTimeout(function () {
+ document.getElementsByTagName('p')[0].innerHTML = fails.length ? ( 'FAIL: ' + fails.join('<br>') ) : 'PASS';
+ fails = [];
+ }, 200 );
+ };
+
+};
+function checkprops(md) {
+ // http://dev.w3.org/html5/md/#extracting-json
+ //"If value is an item, then: If value is in memory, then let value be the string "ERROR"."
+ /*
+Loop detection happens only after the loop has been created, at which point it returns a property value
+of "ERROR" instead of the value which has already been encountered on the stringifying stack.
+Should create the following construct:
+{
+ items:[
+ {
+ properties:{
+ foo:[
+ {
+ properties:{
+ bar:[
+ {
+ properties:{
+ foo:[
+ "ERROR"
+ ]
+ }
+ }
+ ]
+ }
+ }
+ ]
+ }
+ }
+ ]
+}
+ */
+
+ var i;
+ if( !md ) { return 'no microdata'; }
+ md = JSON.parse(md);
+ if( !md.items ) { return 'no items'; }
+ if( md.items.length != 1 ) { return md.items.length+' items instead of 1'; }
+ if( !md.items[0].properties ) { return 'no items[0].properties'; }
+ if( !md.items[0].properties.foo ) { return 'no items[0].properties.foo'; }
+ if( md.items[0].properties.foo.length != 1 ) { return 'items[0].properties.foo length '+md.items[0].properties.foo.length+' instead of 1'; }
+ if( !md.items[0].properties.foo[0].properties ) { return 'items[1].properties.foo[0].properties <i>'+md.items[0].properties.foo[0].properties+'</i> instead of object'; }
+ if( !md.items[0].properties.foo[0].properties.bar ) { return 'items[1].properties.foo[0].properties.bar <i>'+md.items[0].properties.foo[0].properties.bar+'</i> instead of array'; }
+ if( md.items[0].properties.foo[0].properties.bar.length != 1 ) { return 'items[1].properties.foo[0].properties.bar.length <i>'+md.items[0].properties.foo[0].properties.bar.length+'</i> instead of 1'; }
+ if( !md.items[0].properties.foo[0].properties.bar[0].properties ) { return 'items[1].properties.foo[0].properties.bar[0].properties <i>'+md.properties.foo[0].properties.bar[0].properties+'</i> instead of object'; }
+ if( !md.items[0].properties.foo[0].properties.bar[0].properties.foo ) { return 'items[1].properties.foo[0].properties.bar[0].properties.foo <i>'+md.items[0].properties.foo[0].properties.bar[0].properties.foo+'</i> instead of array'; }
+ if( md.items[0].properties.foo[0].properties.bar[0].properties.foo.length != 1 ) { return 'items[1].properties.foo[0].properties.bar[0].properties.foo.length <i>'+md.items[0].properties.foo[0].properties.bar[0].properties.foo.length+'</i> instead of 1'; }
+ if( md.items[0].properties.foo[0].properties.bar[0].properties.foo[0] != 'ERROR' ) { return 'items[1].properties.foo[0].properties.bar[0].properties.foo.length <i>'+md.items[0].properties.foo[0].properties.bar[0].properties.foo[0]+'</i> instead of <i>ERROR</a>'; }
+ return '';
+}
+
+</script>
+
+<div draggable='true' itemscope>
+ <span id='id1' itemprop='foo' itemscope><span itemscope itemprop='bar' itemref='id1'></span></span>
+</div><div></div><div></div>
+
+<p>Use your pointing device to drag the orange box to the pink box, then back to the blue box, and release it.</p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/microdata/018.html b/tests/wpt/web-platform-tests/html/editing/dnd/microdata/018.html
new file mode 100644
index 00000000000..2dcaeaa75b4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/microdata/018.html
@@ -0,0 +1,95 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - microdata for selection partially intersecting a single item</title>
+<style>
+ body > div {
+ height: 100px;
+ width: 200px;
+ background-color: fuchsia;
+ position: absolute;
+ top: 8px;
+ left: 8px;
+ }
+ body > div + div {
+ background-color: navy;
+ top: 116px;
+ }
+ body > div + div + div {
+ background-color: orange;
+ top: 224px;
+ }
+ p:first-of-type {
+ margin-top: 350px;
+ }
+</style>
+
+<script>
+
+function makeEl(eltype,props,contents) {
+ var elem = document.createElement(eltype);
+ for( var i in props ) {
+ if( props.hasOwnProperty(i) ) {
+ elem.setAttribute(i,props[i]);
+ }
+ }
+ if( contents ) {
+ elem.innerHTML = contents;
+ }
+ return elem;
+}
+
+var orange, fails = [], doneonce = false;
+window.onload = function() {
+ orange = document.getElementsByTagName('div')[2];
+ orange.ondragstart = function(e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('Text', 'dummy text');
+ var err;
+ if( err = checkprops(e.dataTransfer.getData('application/microdata+json')) ) {
+ fails[fails.length] = e.type + ' ' + err;
+ }
+ };
+ orange.previousSibling.ondragenter = orange.previousSibling.ondragleave = orange.previousSibling.ondragover =
+ orange.ondrag = orange.ondragend = function(e) {
+ if( e.type == 'dragover' || e.type == 'dragenter' ) {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'copy';
+ }
+ if( e.dataTransfer.getData('application/microdata+json') ) {
+ fails[fails.length] = e.type + ' unexpectedly had microdata (security restriction)';
+ }
+ };
+ orange.previousSibling.ondrop = function(e) {
+ var err;
+ if( err = checkprops(e.dataTransfer.getData('application/microdata+json')) ) {
+ fails[fails.length] = e.type + ' ' + err;
+ }
+ if( e.type != 'drop' ) { return; }
+ if( doneonce ) { return; }
+ doneonce = true;
+ setTimeout(function () {
+ document.getElementsByTagName('p')[0].innerHTML = fails.length ? ( 'FAIL: ' + fails.join('<br>') ) : 'PASS';
+ fails = [];
+ }, 200 );
+ };
+
+};
+function checkprops(md) {
+ // http://dev.w3.org/html5/spec/dnd.html#list-of-dragged-nodes
+ //"If it is a selection that is being dragged, then the list of dragged nodes contains, in tree order, every node that is partially or completely included in the selection (including all their ancestors)."
+ //this test checks that the parent of the text node is included
+ var i;
+ if( !md ) { return 'no microdata'; }
+ md = JSON.parse(md);
+ if( !md.items ) { return 'no items'; }
+ if( md.items.length != 1 ) { return md.items.length+' items instead of 1'; }
+ if( md.items[0].id != 'http://example.com/item1' ) { return 'items[0].id incorrect'; }
+ return '';
+}
+
+</script>
+
+<div></div><div></div><div itemscope itemid="http://example.com/item1">abc</div>
+
+<p>Use your pointing device to select the text substring "b" above, drag the selection upwards to the pink box,
+then back to the blue box, and release it.</p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/microdata/019.html b/tests/wpt/web-platform-tests/html/editing/dnd/microdata/019.html
new file mode 100644
index 00000000000..95224174cb0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/microdata/019.html
@@ -0,0 +1,96 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - microdata for selection partially intersecting nested items</title>
+<style>
+ body > div {
+ height: 100px;
+ width: 200px;
+ background-color: fuchsia;
+ position: absolute;
+ top: 8px;
+ left: 8px;
+ }
+ body > div + div {
+ background-color: navy;
+ top: 116px;
+ }
+ body > div + div + div {
+ background-color: orange;
+ top: 224px;
+ }
+ p:first-of-type {
+ margin-top: 350px;
+ }
+</style>
+
+<script>
+
+function makeEl(eltype,props,contents) {
+ var elem = document.createElement(eltype);
+ for( var i in props ) {
+ if( props.hasOwnProperty(i) ) {
+ elem.setAttribute(i,props[i]);
+ }
+ }
+ if( contents ) {
+ elem.innerHTML = contents;
+ }
+ return elem;
+}
+
+var orange, fails = [], doneonce = false;
+window.onload = function() {
+ orange = document.getElementsByTagName('div')[2];
+ orange.ondragstart = function(e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('Text', 'dummy text');
+ var err;
+ if( err = checkprops(e.dataTransfer.getData('application/microdata+json')) ) {
+ fails[fails.length] = e.type + ' ' + err;
+ }
+ };
+ orange.previousSibling.ondragenter = orange.previousSibling.ondragleave = orange.previousSibling.ondragover =
+ orange.ondrag = orange.ondragend = function(e) {
+ if( e.type == 'dragover' || e.type == 'dragenter' ) {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'copy';
+ }
+ if( e.dataTransfer.getData('application/microdata+json') ) {
+ fails[fails.length] = e.type + ' unexpectedly had microdata (security restriction)';
+ }
+ };
+ orange.previousSibling.ondrop = function(e) {
+ var err;
+ if( err = checkprops(e.dataTransfer.getData('application/microdata+json')) ) {
+ fails[fails.length] = e.type + ' ' + err;
+ }
+ if( e.type != 'drop' ) { return; }
+ if( doneonce ) { return; }
+ doneonce = true;
+ setTimeout(function () {
+ document.getElementsByTagName('p')[0].innerHTML = fails.length ? ( 'FAIL: ' + fails.join('<br>') ) : 'PASS';
+ fails = [];
+ }, 200 );
+ };
+
+};
+function checkprops(md) {
+ // http://dev.w3.org/html5/spec/dnd.html#list-of-dragged-nodes
+ //"If it is a selection that is being dragged, then the list of dragged nodes contains, in tree order, every node that is partially or completely included in the selection (including all their ancestors)."
+ //this test checks that all ancestors of the text node are included
+ var i;
+ if( !md ) { return 'no microdata'; }
+ md = JSON.parse(md);
+ if( !md.items ) { return 'no items'; }
+ if( md.items.length != 2 ) { return md.items.length+' items instead of 2'; }
+ if( md.items[0].id != 'http://example.com/item1' ) { return 'items[0].id incorrect'; }
+ if( md.items[1].id != 'http://example.com/item2' ) { return 'items[1].id incorrect'; }
+ return '';
+}
+
+</script>
+
+<div></div><div></div><div itemscope itemid="http://example.com/item1">a<span itemscope itemid="http://example.com/item2">bcd</span>e</div>
+
+<p>Use your pointing device to select the text substring "d" above, drag the selection upwards to the pink box,
+then back to the blue box, and release it.</p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/microdata/020.html b/tests/wpt/web-platform-tests/html/editing/dnd/microdata/020.html
new file mode 100644
index 00000000000..007aecc3ab8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/microdata/020.html
@@ -0,0 +1,99 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - microdata for selection partially intersecting multiple items but not siblings</title>
+<style>
+ body > div {
+ height: 100px;
+ width: 400px;
+ background-color: fuchsia;
+ position: absolute;
+ top: 8px;
+ left: 8px;
+ }
+ body > div + div {
+ background-color: navy;
+ top: 116px;
+ }
+ body > div + div + div {
+ background-color: orange;
+ top: 224px;
+ }
+ p:first-of-type {
+ margin-top: 350px;
+ }
+</style>
+
+<script>
+
+function makeEl(eltype,props,contents) {
+ var elem = document.createElement(eltype);
+ for( var i in props ) {
+ if( props.hasOwnProperty(i) ) {
+ elem.setAttribute(i,props[i]);
+ }
+ }
+ if( contents ) {
+ elem.innerHTML = contents;
+ }
+ return elem;
+}
+
+var orange, fails = [], doneonce = false;
+window.onload = function() {
+ orange = document.getElementsByTagName('div')[2];
+ orange.ondragstart = function(e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('Text', 'dummy text');
+ var err;
+ if( err = checkprops(e.dataTransfer.getData('application/microdata+json')) ) {
+ fails[fails.length] = e.type + ' ' + err;
+ }
+ };
+ orange.previousSibling.ondragenter = orange.previousSibling.ondragleave = orange.previousSibling.ondragover =
+ orange.ondrag = orange.ondragend = function(e) {
+ if( e.type == 'dragover' || e.type == 'dragenter' ) {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'copy';
+ }
+ if( e.dataTransfer.getData('application/microdata+json') ) {
+ fails[fails.length] = e.type + ' unexpectedly had microdata (security restriction)';
+ }
+ };
+ orange.previousSibling.ondrop = function(e) {
+ var err;
+ if( err = checkprops(e.dataTransfer.getData('application/microdata+json')) ) {
+ fails[fails.length] = e.type + ' ' + err;
+ }
+ if( e.type != 'drop' ) { return; }
+ if( doneonce ) { return; }
+ doneonce = true;
+ setTimeout(function () {
+ document.getElementsByTagName('p')[0].innerHTML = fails.length ? ( 'FAIL: ' + fails.join('<br>') ) : 'PASS';
+ fails = [];
+ }, 200 );
+ };
+
+};
+function checkprops(md) {
+ // http://dev.w3.org/html5/spec/dnd.html#list-of-dragged-nodes
+ //"If it is a selection that is being dragged, then the list of dragged nodes contains, in tree order, every node that is partially or completely included in the selection (including all their ancestors)."
+ //this test checks that all ancestors of the selection's end points are included, and all elements enclosed by the selection are included, but no non-selected siblings of ancestors are included
+ var i;
+ if( !md ) { return 'no microdata'; }
+ md = JSON.parse(md);
+ if( !md.items ) { return 'no items'; }
+ if( md.items.length != 5 ) { return md.items.length+' items instead of 5'; }
+ if( md.items[0].id != 'http://example.com/item1' ) { return 'items[0].id incorrect'; }
+ if( md.items[1].id != 'http://example.com/item4' ) { return 'items[1].id incorrect'; }
+ if( md.items[2].id != 'http://example.com/item5' ) { return 'items[2].id incorrect'; }
+ if( md.items[3].id != 'http://example.com/item6' ) { return 'items[3].id incorrect'; }
+ if( md.items[4].id != 'http://example.com/item7' ) { return 'items[4].id incorrect'; }
+ return '';
+}
+
+</script>
+
+<div></div><div></div><div itemscope itemid="http://example.com/item1"><span itemscope itemid="http://example.com/item2">ab<span itemscope itemid="http://example.com/item3">cd</span>ef</span><span itemscope itemid="http://example.com/item4">gh<span itemscope itemid="http://example.com/item5">ij</span>kl</span><span itemscope itemid="http://example.com/item6">mn<span itemscope itemid="http://example.com/item7">op</span>qr</span><span itemscope itemid="http://example.com/item8">st<span itemscope itemid="http://example.com/item9">uv</span>wx</span></div>
+
+<p>Use your pointing device to select the text substring "hijklmnopq" above, drag the selection upwards to the pink box,
+then back to the blue box, and release it.</p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/microdata/021.html b/tests/wpt/web-platform-tests/html/editing/dnd/microdata/021.html
new file mode 100644
index 00000000000..792e3e2ce4a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/microdata/021.html
@@ -0,0 +1,104 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - microdata when addElement is used</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ position: absolute;
+ top: 8px;
+ left: 8px;
+ }
+ body > div * {
+ display: none;
+ }
+ body > div + div {
+ background-color: navy;
+ left: 250px;
+ }
+ body > div + div + div {
+ background-color: fuchsia;
+ left: 500px;
+ }
+ p:first-of-type {
+ margin-top: 220px;
+ }
+</style>
+
+<script>
+
+function makeEl(eltype,props,contents) {
+ var elem = document.createElement(eltype);
+ for( var i in props ) {
+ if( props.hasOwnProperty(i) ) {
+ elem.setAttribute(i,props[i]);
+ }
+ }
+ if( contents ) {
+ elem.innerHTML = contents;
+ }
+ return elem;
+}
+
+var orange, fails = [], doneonce = false;
+window.onload = function() {
+ orange = document.getElementsByTagName('div')[0];
+
+ orange.appendChild( makeEl('div',{itemprop:'foo'},'test') );
+
+ orange.ondragstart = function(e) {
+ e.dataTransfer.addElement(document.getElementById('side1'));
+ e.dataTransfer.addElement(document.getElementById('side2'));
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('Text', 'dummy text');
+ var err;
+ if( err = checkprops(e.dataTransfer.getData('application/microdata+json')) ) {
+ fails[fails.length] = e.type + ' ' + err;
+ }
+ };
+ orange.nextSibling.ondragenter = orange.nextSibling.ondragleave = orange.nextSibling.ondragover =
+ orange.ondrag = orange.ondragend = function(e) {
+ if( e.type == 'dragover' || e.type == 'dragenter' ) {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'copy';
+ }
+ if( e.dataTransfer.getData('application/microdata+json') ) {
+ fails[fails.length] = e.type + ' unexpectedly had microdata (security restriction)';
+ }
+ };
+ orange.nextSibling.ondrop = function(e) {
+ var err;
+ if( err = checkprops(e.dataTransfer.getData('application/microdata+json')) ) {
+ fails[fails.length] = e.type + ' ' + err;
+ }
+ if( e.type != 'drop' ) { return; }
+ if( doneonce ) { return; }
+ doneonce = true;
+ setTimeout(function () {
+ document.getElementsByTagName('p')[0].innerHTML = fails.length ? ( 'FAIL: ' + fails.join('<br>') ) : 'PASS';
+ fails = [];
+ }, 200 );
+ };
+
+};
+function checkprops(md) {
+ var i;
+ if( !md ) { return 'no microdata'; }
+ md = JSON.parse(md);
+ if( !md.items ) { return 'no items'; }
+ if( md.items.length != 1 ) { return 'items.length '+md.items.length+' instead of 1'; }
+ if( !md.items[0].properties ) { return 'no properties'; }
+ if( !md.items[0].properties.foo ) { return 'no properties.foo'; }
+ if( md.items[0].properties.bar ) { return 'unexpected properties.bar'; }
+ if( md.items[0].properties.foo.length != 1 ) { return 'properties.foo length '+md.items[0].properties.foo.length+' instead of 1'; }
+ if( md.items[0].properties.foo[0] != orange.properties.namedItem('foo').getValues()[0] ) { return 'properties.foo[0] <i>'+md.items[0].properties.foo[0]+'</i> instead of <i>'+orange.properties.namedItem('foo').getValues()[0]+'</i>'; }
+ return '';
+}
+
+</script>
+
+<div draggable='true' itemscope></div><div></div><div></div>
+<h4 itemscope id="side1">xxx</h4><h4 itemprop="bar" id="side2">yyy</h4>
+
+<p>Use your pointing device to drag the orange box to the pink box, then back to the blue box, and release it.</p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/microdata/test b/tests/wpt/web-platform-tests/html/editing/dnd/microdata/test
new file mode 100644
index 00000000000..42d41d980e7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/microdata/test
@@ -0,0 +1,2 @@
+<!doctype html>
+<!-- The tests in this folder point to this file in e.g. <img src> -->
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/navigation/001-1.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/001-1.xhtml
new file mode 100644
index 00000000000..63175342152
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/001-1.xhtml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Cross page drag and drop: helper file</title>
+<style type="text/css">
+html, body
+ {height:100%;}
+</style>
+<script type="application/ecmascript">
+function addImage(event)
+ {var c = document.createElement('img');
+ c.setAttribute('src',event.dataTransfer.getData('text/uri-list').replace(/\r\n$/,''));
+ document.querySelector('body').appendChild(c);}
+</script>
+</head>
+<body ondragenter="event.preventDefault()" ondragover="return false" ondrop="addImage(event)">
+<p>Drop canvas now, it should be copied to this page once you drop it here.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/navigation/001.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/001.xhtml
new file mode 100644
index 00000000000..8c297c2030b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/001.xhtml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Canvas cross page drag and drop</title>
+<script type="application/ecmascript">
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ event.dataTransfer.setData('text/uri-list', document.querySelector('canvas').toDataURL('image/png'));
+ window.location = '001-1.xhtml';}
+</script>
+</head>
+<body>
+<p>
+ <canvas width="100" height="100" draggable="true" ondragstart="start(event)">Canvas</canvas>
+</p>
+<p>Drag canvas pattern. You should be redirected to the new page and be able to drop it there.</p>
+<script type="application/ecmascript">
+var canvas = document.querySelector('canvas'),
+c = canvas.getContext('2d');
+for(var x = 0; x != 50; x++)
+ {c.fillStyle = (x%2 == 0)?'navy':'white';
+ c.beginPath();
+ c.moveTo(x,x);
+ c.lineTo(100-x,x);
+ c.lineTo(100-x,100-x);
+ c.lineTo(x,100-x);
+ c.closePath();
+ c.fill();}
+</script>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/navigation/002.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/002.xhtml
new file mode 100644
index 00000000000..252bf33ba50
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/002.xhtml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>PNG image cross page drag and drop</title>
+<style type="text/css">
+img
+ {margin:0 2px;}
+</style>
+</head>
+<body>
+<p><img ondragstart="event.dataTransfer.effectAllowed = 'copy';window.location = 'helper-drop-image-now.xhtml'" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAEq0lEQVR42u1dvU4bQRAeR0RCCilSp0peIoKGB4DSXYRDlcZlFClKBI4bB/kV/AymIDwCTahiicaioEOxhCsjWVTJziyKMfYZn+9ud3bvG2mEZB13u9+nndmf2Rki7fKFXtEBbVKD9o22jB4bPaND6hm9Mjo0enevw/vfevKMfbYl/8vv4HdBUkvFALhltG2A7dN3+pur8jv53fwN/hZkjjRo3eiuAatjdJA7CcnkDOSb/G1uQ6mFzUeDagaQrvl764yEJOU22LbUymXaGrRhOt40OvJOQvLIGUkbP9GLeIn4SM9NJ+tOTVI+Jq0ubY9sVFRNxy6DIWKWmEvpQ/ByQNumI+fBEjHrZ86lT8HJV3ptGn8aDRGzxJxKHwMZFe9Mg6+jJWNCyrX0VbUc0nuj4+jJmPiWsfRZodN+ZvSoNETMjpYjwUCFfKaXpjEnpSVjQsqJYOF5ZLw1elF6MiakXAgmnpw378DegIgZUm4EGw8jA2QsIuUbvXHpM2CmljFfhfsUO5uCA0/j6AudfZV5arv6WuVHcYs+ALwqKTkvHnmLoEwr8CJW9Llts9iNwvj3plzsfeWyIRnzrq37kfIzq6naBpA5a6bzlJgOl/SMkl+rklEFgIX5k5THwTYgIdwzcP2jhM/o19KsOeoArnBS6suaqo2gQnXCJWSwXNwXB4gBMFekNBeTwSGUmiMK4yNktDhsleNaAZRrUvYWmasuQHJOSDdpdKyriEIvo9maexWC70gAIF/bKTvzzFUH4HgbJZ3HdFSw9vC6lfKHpq7X8X07AOOblK2HhLQBindC2g/9Rx+gePcj/cnqHIDoUFm1c9gjwNAy/d0kyXIAMLSYrQ8kqScAhhbH3iLJBwIwtBByTJKkBWBoIeSMJHMOwNBCyG+SdEYAQ4tTvyLJMQUwtBAyJEn8BTC0EHIHQhQSApOlzGTBqaty6jzVAhhaCOlhYahuYYitE02EHGNzURchLZItX4ChhZB9HFBpUjmgwhGuHv0feI0gBw1T3j7CgHT5jzYC5XQRsjUdSsrhjADGl7ka0EylBgRb+ySkMy9rww7A8Waududf2MH9Qh9k3CbXLsGVNh/mqrvojuEeQHI+Qmq4Fq1ndIyeruaDxAEuCWk+ncmB0z3gepubtQenMUHyGTWELJl8xk6B15CeqVAyLtPXtUICsyJnVivWs+J0dAAwbzLOkQRTk2YuKsapTQFkXqPjlDILEinnRcZ1fpXdkGo866xqnH9FNyTjz0JIQZXcuPQCAE5rqo6oMEFBl7RknBRfTg8lj5Yl48JdGT0ueIWiYIvIuHFfPg9l85LJcF42b+JTUFjysZnyVlhy2qfA0asovTo9+0JxYnWC8t0KBQXuFYrdkIy3mBj3LbeNQrejZTuqOlbcl8znGTqcfjXoM3pboqgaPhEPxda1qgcVYsRt5TanDkgISWzcV1N1hCS3jdu4dNxUDMIhlBzXysHGGspkcBtsW2pPh3fGLrZ2ya5cXHFp0qxJ6si3E68EQCpy344vQRZxO5jfye+2d/oqgHsV02Z3lvcl9QTnA+EkLZw5h9MZcY4pTvxldXj/W0+esc+25H/5HQGYon+Q5f+MwFz+8QAAAABJRU5ErkJggg==" alt="PNG circle"/></p>
+<p>Drag circle above. You should be redirected to the new page and be able to drop it there.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/navigation/003.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/003.xhtml
new file mode 100644
index 00000000000..89c53d38125
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/003.xhtml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>SVG image cross page drag and drop</title>
+</head>
+<body>
+<p><img ondragstart="event.dataTransfer.effectAllowed = 'copy';window.location = 'helper-drop-image-now.xhtml'" src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20version%3D%221.1%22%20width%3D%22100px%22%20height%3D%22100px%22%20viewBox%3D%220%200%20100%20100%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22green%22/%3E%3C/svg%3E" alt="PNG circle"/></p>
+<p>Drag circle above. You should be redirected to the new page and be able to drop it there.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/navigation/004.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/004.xhtml
new file mode 100644
index 00000000000..9cd885de341
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/004.xhtml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Text input selection cross page drag and drop</title>
+</head>
+<body onload="document.querySelector('input').select()">
+<p><input value="Drag me" ondragstart="event.dataTransfer.effectAllowed = 'copy';window.location = 'helper-drop-now.xhtml'"/></p>
+<p>Drag selected text. You should be redirected to the new page and be able to drop it there.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/navigation/005.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/005.xhtml
new file mode 100644
index 00000000000..887ae393182
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/005.xhtml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection cross page drag and drop</title>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('p'))">
+<p ondragstart="event.dataTransfer.effectAllowed = 'copy';window.location = 'helper-drop-now.xhtml'">Drag me</p>
+<p>Drag selected text. You should be redirected to the new page and be able to drop it there.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/navigation/006.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/006.xhtml
new file mode 100644
index 00000000000..4cb8d3e1c77
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/006.xhtml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Link cross page drag and drop</title>
+</head>
+<body>
+<p><a href="data:text/plain,1" ondragstart="event.dataTransfer.effectAllowed = 'copy';window.location = 'helper-drop-link-now.xhtml'">Drag me</a></p>
+<p>Drag link above. You should be redirected to the new page and be able to drop it there.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/navigation/007-1.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/007-1.xhtml
new file mode 100644
index 00000000000..a1c982e72b8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/007-1.xhtml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Cross page drag and drop: helper file</title>
+<style type="text/css">
+html, body
+ {height:100%;}
+</style>
+</head>
+<body ondragenter="event.preventDefault()" ondragover="return false" ondrop="event.preventDefault();document.querySelector('p').firstChild.nodeValue = event.dataTransfer.getData('text/plain')">
+<p>Drop box now, you should see word PASS once you drop it.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/navigation/007.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/007.xhtml
new file mode 100644
index 00000000000..5cabbbd3ebb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/007.xhtml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Cross page drag and drop with text/plain data</title>
+<style type="text/css">
+div[ondragstart]
+ {width:40px;
+ min-height:40px;
+ margin-top:20px;
+ padding:40px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body>
+<div draggable="true" ondragstart="event.dataTransfer.effectAllowed = 'copy';event.dataTransfer.setData('text/plain','PASS');window.location = '007-1.xhtml'"/>
+<p>Drag blue box. You should be redirected to the new page and be able to drop it there.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/navigation/008-1.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/008-1.xhtml
new file mode 100644
index 00000000000..218b5873f3c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/008-1.xhtml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Cross page drag and drop: helper file</title>
+<style type="text/css">
+html, body
+ {height:100%;}
+</style>
+</head>
+<body ondragenter="event.preventDefault()" ondragover="return false" ondrop="event.preventDefault();document.querySelector('p').firstChild.nodeValue = event.dataTransfer.getData('text/uri-list').substr(16,4)">
+<p>Drop box now, you should see word PASS once you drop it.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/navigation/008.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/008.xhtml
new file mode 100644
index 00000000000..11b29a8f462
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/008.xhtml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Cross page drag and drop with text/uri-list data</title>
+<style type="text/css">
+div[ondragstart]
+ {width:40px;
+ min-height:40px;
+ margin-top:20px;
+ padding:40px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body>
+<div draggable="true" ondragstart="event.dataTransfer.effectAllowed = 'copy';event.dataTransfer.setData('text/uri-list','data:text/plain,PASS');window.location = '008-1.xhtml'"/>
+<p>Drag blue box. You should be redirected to the new page and be able to drop it there.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/navigation/009-1.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/009-1.xhtml
new file mode 100644
index 00000000000..8604fd534b3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/009-1.xhtml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Cross page drag and drop: helper file</title>
+<style type="text/css">
+html, body
+ {height:100%;}
+</style>
+</head>
+<body ondragenter="event.preventDefault()" ondragover="window.location = 'helper-drop-link-now.xhtml'">
+<p>Don't drop link yet, you should be redirected to another page.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/navigation/009.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/009.xhtml
new file mode 100644
index 00000000000..b93cdff31da
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/009.xhtml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Link drag and drop through three pages</title>
+</head>
+<body>
+<p><a href="data:text/plain,1" ondragstart="event.dataTransfer.effectAllowed = 'copy';window.location = '009-1.xhtml'">Drag me</a></p>
+<p>Drag link above. You should be redirected to the new page.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/navigation/010-1.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/010-1.xhtml
new file mode 100644
index 00000000000..620f1af871b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/010-1.xhtml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Cross page drag and drop: helper file</title>
+<style type="text/css">
+div[ondragenter]
+ {margin:200px 0 0 200px;
+ width:200px;
+ height:100px;
+ color:white;
+ background-color:navy;}
+div[ondragenter]:before
+ {display:block;
+ content:"";
+ border-style:solid;
+ position:relative;
+ top:-50px;
+ left:-200px;
+ border-width:100px;
+ border-color:transparent navy transparent transparent;}
+</style>
+</head>
+<body>
+<p>Drag link to the blue arrow but don't drop it yet. You should be returned back to start page.</p>
+<div ondragenter="event.preventDefault()" ondragover="history.go(-1)"/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/navigation/010.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/010.xhtml
new file mode 100644
index 00000000000..0af5b258fcc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/010.xhtml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Link drag and drop and history navigation roundtrip</title>
+<script type="application/ecmascript">
+function checkLink(event)
+ {document.querySelector('a').firstChild.nodeValue = (event.dataTransfer.getData('text/uri-list').replace(/\r\n$/,'') == 'data:text/plain,1')?'PASS':'FAIL'}
+</script>
+</head>
+<body>
+<p><a href="data:text/plain,1" ondragstart="event.dataTransfer.effectAllowed = 'copy';window.location = '010-1.xhtml'" ondragenter="event.preventDefault()" ondrop="checkLink(event)" ondragover="return false">Drag me around and drop here once you return back</a></p>
+<p>Drag link around. You will be redirected to new page. When you return back drop link on itself. You should see word PASS once you drop it.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/navigation/011-1.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/011-1.xhtml
new file mode 100644
index 00000000000..85f016441ca
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/011-1.xhtml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Cross page drag and drop: helper file</title>
+<style type="text/css">
+div[ondragenter]
+ {margin:200px 0 0 200px;
+ width:200px;
+ height:100px;
+ color:white;
+ background-color:navy;}
+div[ondragenter]:before
+ {display:block;
+ content:"";
+ border-style:solid;
+ position:relative;
+ top:-50px;
+ left:-200px;
+ border-width:100px;
+ border-color:transparent navy transparent transparent;}
+</style>
+</head>
+<body>
+<p>Drag canvas to the blue arrow but don't drop it yet. You should be returned back to start page.</p>
+<div ondragenter="event.preventDefault()" ondragover="history.go(-1)"/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/navigation/011.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/011.xhtml
new file mode 100644
index 00000000000..a4d86a1d28d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/011.xhtml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Canvas drag and drop and history navigation roundtrip</title>
+<style type="text/css">
+img
+ {margin:0 2px;}
+</style>
+<script type="application/ecmascript">
+function addImage(event)
+ {var c = document.createElement('img');
+ c.setAttribute('src',event.dataTransfer.getData('text/uri-list').replace(/\r\n$/,''));
+ document.querySelector('p').appendChild(c);}
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ event.dataTransfer.setData('text/uri-list', document.querySelector('canvas').toDataURL('image/png'));
+ window.location = '011-1.xhtml'}
+</script>
+</head>
+<body>
+<p>
+ <canvas width="100" height="100" draggable="true" ondragstart="start(event)" ondragenter="event.preventDefault()" ondragover="return false" ondrop="addImage(event)">Canvas</canvas>
+</p>
+<p>Drag canvas around. You will be redirected to new page. When you return back drop canvas on itself. It should be duplicated once you drop it.</p>
+<script type="application/ecmascript">
+var canvas = document.querySelector('canvas'),
+c = canvas.getContext('2d');
+for(var x = 0; x != 50; x++)
+ {c.fillStyle = (x%2 == 0)?'navy':'white';
+ c.beginPath();
+ c.moveTo(x,x);
+ c.lineTo(100-x,x);
+ c.lineTo(100-x,100-x);
+ c.lineTo(x,100-x);
+ c.closePath();
+ c.fill();}
+</script>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/navigation/012.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/012.xhtml
new file mode 100644
index 00000000000..842b75fa60a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/012.xhtml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>PNG image drag and drop and history navigation roundtrip</title>
+<style type="text/css">
+img
+ {margin:0 2px;}
+</style>
+<script type="application/ecmascript">
+function addImage(event)
+ {var c = document.createElement('img');
+ c.setAttribute('src',event.dataTransfer.getData('text/uri-list').replace(/\r\n$/,''));
+ document.querySelector('p').appendChild(c);}
+</script>
+</head>
+<body>
+<p><img ondragstart="event.dataTransfer.effectAllowed = 'copy';window.location = 'helper-drag-image-dont-drop.xhtml'" ondragenter="event.preventDefault()" ondrop="addImage(event)" ondragover="return false" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAEq0lEQVR42u1dvU4bQRAeR0RCCilSp0peIoKGB4DSXYRDlcZlFClKBI4bB/kV/AymIDwCTahiicaioEOxhCsjWVTJziyKMfYZn+9ud3bvG2mEZB13u9+nndmf2Rki7fKFXtEBbVKD9o22jB4bPaND6hm9Mjo0enevw/vfevKMfbYl/8vv4HdBUkvFALhltG2A7dN3+pur8jv53fwN/hZkjjRo3eiuAatjdJA7CcnkDOSb/G1uQ6mFzUeDagaQrvl764yEJOU22LbUymXaGrRhOt40OvJOQvLIGUkbP9GLeIn4SM9NJ+tOTVI+Jq0ubY9sVFRNxy6DIWKWmEvpQ/ByQNumI+fBEjHrZ86lT8HJV3ptGn8aDRGzxJxKHwMZFe9Mg6+jJWNCyrX0VbUc0nuj4+jJmPiWsfRZodN+ZvSoNETMjpYjwUCFfKaXpjEnpSVjQsqJYOF5ZLw1elF6MiakXAgmnpw378DegIgZUm4EGw8jA2QsIuUbvXHpM2CmljFfhfsUO5uCA0/j6AudfZV5arv6WuVHcYs+ALwqKTkvHnmLoEwr8CJW9Llts9iNwvj3plzsfeWyIRnzrq37kfIzq6naBpA5a6bzlJgOl/SMkl+rklEFgIX5k5THwTYgIdwzcP2jhM/o19KsOeoArnBS6suaqo2gQnXCJWSwXNwXB4gBMFekNBeTwSGUmiMK4yNktDhsleNaAZRrUvYWmasuQHJOSDdpdKyriEIvo9maexWC70gAIF/bKTvzzFUH4HgbJZ3HdFSw9vC6lfKHpq7X8X07AOOblK2HhLQBindC2g/9Rx+gePcj/cnqHIDoUFm1c9gjwNAy/d0kyXIAMLSYrQ8kqScAhhbH3iLJBwIwtBByTJKkBWBoIeSMJHMOwNBCyG+SdEYAQ4tTvyLJMQUwtBAyJEn8BTC0EHIHQhQSApOlzGTBqaty6jzVAhhaCOlhYahuYYitE02EHGNzURchLZItX4ChhZB9HFBpUjmgwhGuHv0feI0gBw1T3j7CgHT5jzYC5XQRsjUdSsrhjADGl7ka0EylBgRb+ySkMy9rww7A8Waududf2MH9Qh9k3CbXLsGVNh/mqrvojuEeQHI+Qmq4Fq1ndIyeruaDxAEuCWk+ncmB0z3gepubtQenMUHyGTWELJl8xk6B15CeqVAyLtPXtUICsyJnVivWs+J0dAAwbzLOkQRTk2YuKsapTQFkXqPjlDILEinnRcZ1fpXdkGo866xqnH9FNyTjz0JIQZXcuPQCAE5rqo6oMEFBl7RknBRfTg8lj5Yl48JdGT0ueIWiYIvIuHFfPg9l85LJcF42b+JTUFjysZnyVlhy2qfA0asovTo9+0JxYnWC8t0KBQXuFYrdkIy3mBj3LbeNQrejZTuqOlbcl8znGTqcfjXoM3pboqgaPhEPxda1qgcVYsRt5TanDkgISWzcV1N1hCS3jdu4dNxUDMIhlBzXysHGGspkcBtsW2pPh3fGLrZ2ya5cXHFp0qxJ6si3E68EQCpy344vQRZxO5jfye+2d/oqgHsV02Z3lvcl9QTnA+EkLZw5h9MZcY4pTvxldXj/W0+esc+25H/5HQGYon+Q5f+MwFz+8QAAAABJRU5ErkJggg==" alt="PNG circle"/></p>
+<p>Drag circle around. You will be redirected to new page. When you return back drop circle on itself. It should be duplicated once you drop it.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/navigation/013.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/013.xhtml
new file mode 100644
index 00000000000..59d48a04183
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/013.xhtml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>SVG image drag and drop and history navigation roundtrip</title>
+<style type="text/css">
+img
+ {margin:0 2px;}
+</style>
+<script type="application/ecmascript">
+function addImage(event)
+ {var c = document.createElement('img');
+ c.setAttribute('src',event.dataTransfer.getData('text/uri-list').replace(/\r\n$/,''));
+ document.querySelector('p').appendChild(c);}
+</script>
+</head>
+<body>
+<p><img ondragstart="event.dataTransfer.effectAllowed = 'copy';window.location = 'helper-drag-image-dont-drop.xhtml'" ondragenter="event.preventDefault()" ondrop="addImage(event)" ondragover="return false" src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20version%3D%221.1%22%20width%3D%22100px%22%20height%3D%22100px%22%20viewBox%3D%220%200%20100%20100%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22green%22/%3E%3C/svg%3E" alt="SVG circle"/></p>
+<p>Drag circle around. You will be redirected to new page. When you return back drop circle on itself. It should be duplicated once you drop it.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/navigation/014.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/014.xhtml
new file mode 100644
index 00000000000..5896797754d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/014.xhtml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Text input selection drag and drop and history navigation roundtrip</title>
+</head>
+<body onload="document.querySelector('input').select()">
+<p><input value="Drag me" ondragstart="window.location = 'helper-drag-selection-dont-drop.xhtml'" ondragenter="event.preventDefault()" ondragover="return false" ondrop="event.preventDefault();this.value = (event.dataTransfer.getData('text/plain') == 'Drag me')?'PASS':'FAIL'"/></p>
+<p>Drag selected text around. You will be redirected to new page. When you return back drop selection on itself. You should see word PASS once you drop it.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/navigation/015.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/015.xhtml
new file mode 100644
index 00000000000..cb194a52c0f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/015.xhtml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop and history navigation roundtrip</title>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('span'))">
+<p><span ondragstart="window.location = 'helper-drag-selection-dont-drop.xhtml'" ondragenter="event.preventDefault()" ondragover="return false" ondrop="document.querySelector('span').firstChild.nodeValue = (event.dataTransfer.getData('text/plain') == 'Drag me')?'PASS':'FAIL'">Drag me</span></p>
+<p>Drag selected text around. You will be redirected to new page. When you return back drop selection on itself. You should see word PASS once you drop it.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/navigation/016-1.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/016-1.xhtml
new file mode 100644
index 00000000000..5e25edaad02
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/016-1.xhtml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Cross page drag and drop: helper file</title>
+<style type="text/css">
+p
+ {border:solid medium navy;
+ height:200px;
+ padding:1em;
+ margin:0;}
+div
+ {margin:100px;
+ padding:50px;}
+img
+ {display:block;
+ margin:1em;}
+</style>
+<script type="application/ecmascript">
+function addImage(event)
+ {var c = document.createElement('img');
+ c.setAttribute('src',event.dataTransfer.getData('text/uri-list').replace(/\r\n$/,''));
+ document.querySelector('p').appendChild(c);}
+</script>
+</head>
+<body>
+<div ondragenter="window.location.reload()">
+<p ondragenter="event.stopPropagation()" dropzone="copy string:text/uri-list" ondrop="addImage(event)">Drop canvas here, it should be copied to this page once you drop it here.</p>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/navigation/016.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/016.xhtml
new file mode 100644
index 00000000000..1ac642fe136
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/016.xhtml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Reload during canvas cross page drag and drop</title>
+<script type="application/ecmascript">
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ event.dataTransfer.setData('text/uri-list', document.querySelector('canvas').toDataURL('image/png'));
+ window.location = '016-1.xhtml';}
+</script>
+</head>
+<body>
+<p>
+ <canvas width="100" height="100" draggable="true" ondragstart="start(event)">Canvas</canvas>
+</p>
+<p>Drag canvas pattern. You should be redirected to the new page and be able to drop it there.</p>
+<script type="application/ecmascript">
+var canvas = document.querySelector('canvas'),
+c = canvas.getContext('2d');
+for(var x = 0; x != 50; x++)
+ {c.fillStyle = (x%2 == 0)?'navy':'white';
+ c.beginPath();
+ c.moveTo(x,x);
+ c.lineTo(100-x,x);
+ c.lineTo(100-x,100-x);
+ c.lineTo(x,100-x);
+ c.closePath();
+ c.fill();}
+</script>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/navigation/017.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/017.xhtml
new file mode 100644
index 00000000000..36b8987a270
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/017.xhtml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Reload during PNG image cross page drag and drop</title>
+<style type="text/css">
+img
+ {margin:0 2px;}
+</style>
+</head>
+<body>
+<p><img ondragstart="event.dataTransfer.effectAllowed = 'copy';window.location = 'helper-drop-here-reload.xhtml'" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAEq0lEQVR42u1dvU4bQRAeR0RCCilSp0peIoKGB4DSXYRDlcZlFClKBI4bB/kV/AymIDwCTahiicaioEOxhCsjWVTJziyKMfYZn+9ud3bvG2mEZB13u9+nndmf2Rki7fKFXtEBbVKD9o22jB4bPaND6hm9Mjo0enevw/vfevKMfbYl/8vv4HdBUkvFALhltG2A7dN3+pur8jv53fwN/hZkjjRo3eiuAatjdJA7CcnkDOSb/G1uQ6mFzUeDagaQrvl764yEJOU22LbUymXaGrRhOt40OvJOQvLIGUkbP9GLeIn4SM9NJ+tOTVI+Jq0ubY9sVFRNxy6DIWKWmEvpQ/ByQNumI+fBEjHrZ86lT8HJV3ptGn8aDRGzxJxKHwMZFe9Mg6+jJWNCyrX0VbUc0nuj4+jJmPiWsfRZodN+ZvSoNETMjpYjwUCFfKaXpjEnpSVjQsqJYOF5ZLw1elF6MiakXAgmnpw378DegIgZUm4EGw8jA2QsIuUbvXHpM2CmljFfhfsUO5uCA0/j6AudfZV5arv6WuVHcYs+ALwqKTkvHnmLoEwr8CJW9Llts9iNwvj3plzsfeWyIRnzrq37kfIzq6naBpA5a6bzlJgOl/SMkl+rklEFgIX5k5THwTYgIdwzcP2jhM/o19KsOeoArnBS6suaqo2gQnXCJWSwXNwXB4gBMFekNBeTwSGUmiMK4yNktDhsleNaAZRrUvYWmasuQHJOSDdpdKyriEIvo9maexWC70gAIF/bKTvzzFUH4HgbJZ3HdFSw9vC6lfKHpq7X8X07AOOblK2HhLQBindC2g/9Rx+gePcj/cnqHIDoUFm1c9gjwNAy/d0kyXIAMLSYrQ8kqScAhhbH3iLJBwIwtBByTJKkBWBoIeSMJHMOwNBCyG+SdEYAQ4tTvyLJMQUwtBAyJEn8BTC0EHIHQhQSApOlzGTBqaty6jzVAhhaCOlhYahuYYitE02EHGNzURchLZItX4ChhZB9HFBpUjmgwhGuHv0feI0gBw1T3j7CgHT5jzYC5XQRsjUdSsrhjADGl7ka0EylBgRb+ySkMy9rww7A8Waududf2MH9Qh9k3CbXLsGVNh/mqrvojuEeQHI+Qmq4Fq1ndIyeruaDxAEuCWk+ncmB0z3gepubtQenMUHyGTWELJl8xk6B15CeqVAyLtPXtUICsyJnVivWs+J0dAAwbzLOkQRTk2YuKsapTQFkXqPjlDILEinnRcZ1fpXdkGo866xqnH9FNyTjz0JIQZXcuPQCAE5rqo6oMEFBl7RknBRfTg8lj5Yl48JdGT0ueIWiYIvIuHFfPg9l85LJcF42b+JTUFjysZnyVlhy2qfA0asovTo9+0JxYnWC8t0KBQXuFYrdkIy3mBj3LbeNQrejZTuqOlbcl8znGTqcfjXoM3pboqgaPhEPxda1qgcVYsRt5TanDkgISWzcV1N1hCS3jdu4dNxUDMIhlBzXysHGGspkcBtsW2pPh3fGLrZ2ya5cXHFp0qxJ6si3E68EQCpy344vQRZxO5jfye+2d/oqgHsV02Z3lvcl9QTnA+EkLZw5h9MZcY4pTvxldXj/W0+esc+25H/5HQGYon+Q5f+MwFz+8QAAAABJRU5ErkJggg==" alt="PNG circle"/></p>
+<p>Drag circle above. You should be redirected to the new page and be able to drop it there.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/navigation/018.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/018.xhtml
new file mode 100644
index 00000000000..b8849c4a35e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/018.xhtml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Reload during SVG image cross page drag and drop</title>
+</head>
+<body>
+<p><img ondragstart="event.dataTransfer.effectAllowed = 'copy';window.location = 'helper-drop-here-reload.xhtml'" src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20version%3D%221.1%22%20width%3D%22100px%22%20height%3D%22100px%22%20viewBox%3D%220%200%20100%20100%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22green%22/%3E%3C/svg%3E" alt="PNG circle"/></p>
+<p>Drag circle above. You should be redirected to the new page and be able to drop it there.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/navigation/019.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/019.xhtml
new file mode 100644
index 00000000000..f09041604f1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/019.xhtml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Reload during text input selection cross page drag and drop</title>
+</head>
+<body onload="document.querySelector('input').select()">
+<p><input value="Drag me" ondragstart="event.dataTransfer.effectAllowed = 'copy';window.location = 'helper-drop-selection-here.xhtml'"/></p>
+<p>Drag selected text. You should be redirected to the new page and be able to drop it there.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/navigation/020.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/020.xhtml
new file mode 100644
index 00000000000..cf653bcad8a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/020.xhtml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Reload during selection cross page drag and drop</title>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('p'))">
+<p ondragstart="event.dataTransfer.effectAllowed = 'copy';window.location = 'helper-drop-selection-here.xhtml'">Drag me</p>
+<p>Drag selected text. You should be redirected to the new page and be able to drop it there.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/navigation/021-1.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/021-1.xhtml
new file mode 100644
index 00000000000..e38204ca422
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/021-1.xhtml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Cross page drag and drop: helper file</title>
+<style type="text/css">
+p
+ {border:solid medium navy;
+ height:200px;
+ padding:1em;
+ margin:0;}
+div
+ {margin:100px;
+ padding:50px;}
+</style>
+<script type="application/ecmascript">
+function checkLink(event)
+ {document.querySelector('p').firstChild.nodeValue = (event.dataTransfer.getData('text/uri-list').replace(/\r\n$/,'') == 'data:text/plain,1')?'PASS':'FAIL'}
+</script>
+</head>
+<body>
+<div ondragenter="window.location.reload()">
+<p ondragenter="event.stopPropagation()" dropzone="copy string:text/uri-list" ondrop="checkLink(event)">Drop link here, you should see word PASS once you drop it.</p>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/navigation/021.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/021.xhtml
new file mode 100644
index 00000000000..5c7fad0ca43
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/021.xhtml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Reload during link cross page drag and drop</title>
+</head>
+<body>
+<p><a href="data:text/plain,1" ondragstart="event.dataTransfer.effectAllowed = 'copy';window.location = '021-1.xhtml'">Drag me</a></p>
+<p>Drag link above. You should be redirected to the new page and be able to drop it there.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/navigation/022-1.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/022-1.xhtml
new file mode 100644
index 00000000000..ff96e273b6d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/022-1.xhtml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Cross page drag and drop: helper file</title>
+<style type="text/css">
+p
+ {border:solid medium navy;
+ height:200px;
+ padding:1em;
+ margin:0;}
+div
+ {margin:100px;
+ padding:50px;}
+</style>
+</head>
+<body>
+<div ondragenter="window.location.reload()">
+<p ondragenter="event.stopPropagation()" dropzone="copy string:text/plain" ondrop="event.preventDefault();document.querySelector('p').firstChild.nodeValue = event.dataTransfer.getData('text/plain')">Drop box here, you should see word PASS once you drop it.</p>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/navigation/022.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/022.xhtml
new file mode 100644
index 00000000000..70aa3d93bcf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/022.xhtml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Reload during cross page drag and drop with text/plain data</title>
+<style type="text/css">
+div[ondragstart]
+ {width:40px;
+ min-height:40px;
+ margin-top:20px;
+ padding:40px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body>
+<div draggable="true" ondragstart="event.dataTransfer.effectAllowed = 'copy';event.dataTransfer.setData('text/plain','PASS');window.location = '022-1.xhtml'"/>
+<p>Drag blue box. You should be redirected to the new page and be able to drop it there.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/navigation/023-1.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/023-1.xhtml
new file mode 100644
index 00000000000..29f51732f29
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/023-1.xhtml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Cross page drag and drop: helper file</title>
+<style type="text/css">
+p
+ {border:solid medium navy;
+ height:200px;
+ padding:1em;
+ margin:0;}
+div
+ {margin:100px;
+ padding:50px;}
+</style>
+</head>
+<body>
+<div ondragenter="window.location.reload()">
+<p ondragenter="event.stopPropagation()" dropzone="copy string:text/uri-list" ondrop="event.preventDefault();document.querySelector('p').firstChild.nodeValue = event.dataTransfer.getData('text/uri-list').substr(16,4)">Drop box here, you should see word PASS once you drop it.</p>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/navigation/023.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/023.xhtml
new file mode 100644
index 00000000000..eb286ace89c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/023.xhtml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Reload during cross page drag and drop with text/uri-list data</title>
+<style type="text/css">
+div[ondragstart]
+ {width:40px;
+ min-height:40px;
+ margin-top:20px;
+ padding:40px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body>
+<div draggable="true" ondragstart="event.dataTransfer.effectAllowed = 'copy';event.dataTransfer.setData('text/uri-list','data:text/plain,PASS');window.location = '023-1.xhtml'"/>
+<p>Drag blue box. You should be redirected to the new page and be able to drop it there.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/navigation/helper-drag-image-dont-drop.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/helper-drag-image-dont-drop.xhtml
new file mode 100644
index 00000000000..883649e43e1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/helper-drag-image-dont-drop.xhtml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Cross page drag and drop: helper file</title>
+<style type="text/css">
+div[ondragenter]
+ {margin:200px 0 0 200px;
+ width:200px;
+ height:100px;
+ color:white;
+ background-color:navy;}
+div[ondragenter]:before
+ {display:block;
+ content:"";
+ border-style:solid;
+ position:relative;
+ top:-50px;
+ left:-200px;
+ border-width:100px;
+ border-color:transparent navy transparent transparent;}
+</style>
+</head>
+<body>
+<p>Drag image to the blue arrow but don't drop it yet. You should be returned back to start page.</p>
+<div ondragenter="event.preventDefault()" ondragover="history.go(-1)"/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/navigation/helper-drag-selection-dont-drop.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/helper-drag-selection-dont-drop.xhtml
new file mode 100644
index 00000000000..76712a6db39
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/helper-drag-selection-dont-drop.xhtml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Cross page drag and drop: helper file</title>
+<style type="text/css">
+div[ondragenter]
+ {margin:200px 0 0 200px;
+ width:200px;
+ height:100px;
+ color:white;
+ background-color:navy;}
+div[ondragenter]:before
+ {display:block;
+ content:"";
+ border-style:solid;
+ position:relative;
+ top:-50px;
+ left:-200px;
+ border-width:100px;
+ border-color:transparent navy transparent transparent;}
+</style>
+</head>
+<body>
+<p>Drag selection to the blue arrow but don't drop it yet. You should be returned back to start page.</p>
+<div ondragenter="event.preventDefault()" ondragover="history.go(-1)"/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/navigation/helper-drop-here-reload.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/helper-drop-here-reload.xhtml
new file mode 100644
index 00000000000..481692f79a2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/helper-drop-here-reload.xhtml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Cross page drag and drop: helper file</title>
+<style type="text/css">
+p
+ {border:solid medium navy;
+ height:200px;
+ padding:1em;
+ margin:0;}
+div
+ {margin:100px;
+ padding:50px;}
+img
+ {display:block;
+ margin:1em;}
+</style>
+<script type="application/ecmascript">
+function addImage(event)
+ {var c = document.createElement('img');
+ c.setAttribute('src',event.dataTransfer.getData('text/uri-list').replace(/\r\n$/,''));
+ document.querySelector('p').appendChild(c);}
+</script>
+</head>
+<body>
+<div ondragenter="window.location.reload()">
+<p ondragenter="event.stopPropagation()" dropzone="copy string:text/uri-list" ondrop="addImage(event)">Drop image here, it should be copied to this page once you drop it here.</p>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/navigation/helper-drop-image-now.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/helper-drop-image-now.xhtml
new file mode 100644
index 00000000000..a2c5ce4dbe9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/helper-drop-image-now.xhtml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Cross page drag and drop: helper file</title>
+<style type="text/css">
+html, body
+ {height:100%;}
+</style>
+<script type="application/ecmascript">
+function addImage(event)
+ {var c = document.createElement('img');
+ c.setAttribute('src',event.dataTransfer.getData('text/uri-list').replace(/\r\n$/,''));
+ document.querySelector('body').appendChild(c);}
+</script>
+</head>
+<body ondragenter="event.preventDefault()" ondragover="return false" ondrop="addImage(event)">
+<p>Drop image now, it should be copied to this page once you drop it here.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/navigation/helper-drop-link-now.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/helper-drop-link-now.xhtml
new file mode 100644
index 00000000000..f6a3c6c30f6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/helper-drop-link-now.xhtml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Cross page drag and drop: helper file</title>
+<style type="text/css">
+html, body
+ {height:100%;}
+</style>
+<script type="application/ecmascript">
+function checkLink(event)
+ {document.querySelector('p').firstChild.nodeValue = (event.dataTransfer.getData('text/uri-list').replace(/\r\n$/,'') == 'data:text/plain,1')?'PASS':'FAIL'}
+</script>
+</head>
+<body ondragenter="event.preventDefault()" ondrop="checkLink(event)" ondragover="return false">
+<p>Drop link now, you should see word PASS once you drop it.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/navigation/helper-drop-now.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/helper-drop-now.xhtml
new file mode 100644
index 00000000000..e391b342a12
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/helper-drop-now.xhtml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Cross page drag and drop: helper file</title>
+<style type="text/css">
+html, body
+ {height:100%;}
+</style>
+</head>
+<body ondragenter="event.preventDefault()" ondragover="return false" ondrop="event.preventDefault();document.querySelector('p').firstChild.nodeValue = (event.dataTransfer.getData('text/plain') == 'Drag me')?'PASS':'FAIL'">
+<p>Drop selection now, you should see word PASS once you drop it.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/navigation/helper-drop-selection-here.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/helper-drop-selection-here.xhtml
new file mode 100644
index 00000000000..a88d34eb83c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/navigation/helper-drop-selection-here.xhtml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Cross page drag and drop: helper file</title>
+<style type="text/css">
+p
+ {border:solid medium navy;
+ height:200px;
+ padding:1em;
+ margin:0;}
+div
+ {margin:100px;
+ padding:50px;}
+</style>
+</head>
+<body>
+<div ondragenter="window.location.reload()">
+<p ondragenter="event.stopPropagation()" dropzone="copy string:text/plain" ondrop="document.querySelector('p').firstChild.nodeValue = (event.dataTransfer.getData('text/plain') == 'Drag me')?'PASS':'FAIL'">Drop selection here, you should see word PASS once you drop it.</p>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/001.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/001.xhtml
new file mode 100644
index 00000000000..58e2811c333
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/001.xhtml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag feedback overlay size</title>
+<style type="text/css">
+img
+ {height:100px;
+ width:100px;}
+</style>
+</head>
+<body>
+<p><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAEElEQVR42mNgaGD4D8YwBgAw9AX9Y9zBwwAAAABJRU5ErkJggg==" alt="PNG green pixel" ondragstart="event.dataTransfer.effectAllowed = 'copy'"/></p>
+<p>Try to drag green box above. Size of feedback overlay should match size of green box.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/002.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/002.xhtml
new file mode 100644
index 00000000000..4e30fa79026
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/002.xhtml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Setting drag image during drag and drop</title>
+<style type="text/css">
+span
+ {color:green;
+ background-color:yellow;}
+</style>
+<script type="application/ecmascript">
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ event.dataTransfer.setDragImage(document.querySelector('span'), 1, 1);}
+</script>
+</head>
+<body>
+<p><a href="data:text/plain,1" ondragstart="start(event)">Drag me</a></p>
+<p>Try to drag link above. You should see word <span>PASS</span> in feedback overlay.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/003.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/003.xhtml
new file mode 100644
index 00000000000..2683013ae75
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/003.xhtml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Adding element to datastore</title>
+<style type="text/css">
+span
+ {color:green;
+ background-color:yellow;}
+</style>
+<script type="application/ecmascript">
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ event.dataTransfer.addElement(document.querySelector('span'));}
+</script>
+</head>
+<body>
+<p><a href="data:text/plain,1" ondragstart="start(event)">Drag me</a></p>
+<p>Try to drag link above. You should see word <span>PASS</span> in feedback overlay.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/004.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/004.xhtml
new file mode 100644
index 00000000000..1bb85f771e9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/004.xhtml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Resetting drag image on dragenter</title>
+<style type="text/css">
+span, strong
+ {color:green;
+ background-color:yellow;}
+strong
+ {color:red;}
+div
+ {width:100px;
+ height:100px;
+ background-color:silver;
+ margin-top:20px;}
+</style>
+<script type="application/ecmascript">
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ event.dataTransfer.setDragImage(document.querySelector('span'), 1, 1);}
+function resetImage(event)
+ {event.preventDefault();
+ event.dataTransfer.setDragImage(document.querySelector('strong'), 1, 1);}
+</script>
+</head>
+<body>
+<p><a href="data:text/plain,1" ondragstart="start(event)">Drag me</a></p>
+<p>Try to drag link above to the silver box. You should see word <span>PASS</span> not <strong>FAIL</strong> in feedback overlay all the time.</p>
+<div ondragenter="resetImage(event)" ondragover="return false"/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/005.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/005.xhtml
new file mode 100644
index 00000000000..4b9fd33d3a1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/005.xhtml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Adding element to datastore on dragenter</title>
+<style type="text/css">
+span, strong
+ {color:green;
+ background-color:yellow;}
+strong
+ {color:red;}
+div
+ {width:100px;
+ height:100px;
+ background-color:silver;
+ margin-top:20px;}
+</style>
+<script type="application/ecmascript">
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ event.dataTransfer.addElement(document.querySelector('span'));}
+function resetImage(event)
+ {event.preventDefault();
+ event.dataTransfer.addElement(document.querySelector('strong'));}
+</script>
+</head>
+<body>
+<p><a href="data:text/plain,1" ondragstart="start(event)">Drag me</a></p>
+<p>Try to drag link above to the silver box. You should see word <span>PASS</span> not <strong>FAIL</strong> in feedback overlay all the time.</p>
+<div ondragenter="resetImage(event)" ondragover="return false"/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/006.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/006.xhtml
new file mode 100644
index 00000000000..1681adb064c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/006.xhtml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Resetting drag image on dragover</title>
+<style type="text/css">
+span, strong
+ {color:green;
+ background-color:yellow;}
+strong
+ {color:red;}
+div
+ {width:100px;
+ height:100px;
+ background-color:silver;
+ margin-top:20px;}
+</style>
+<script type="application/ecmascript">
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ event.dataTransfer.setDragImage(document.querySelector('span'), 1, 1);}
+function resetImage(event)
+ {event.preventDefault();
+ event.dataTransfer.setDragImage(document.querySelector('strong'), 1, 1);}
+</script>
+</head>
+<body>
+<p><a href="data:text/plain,1" ondragstart="start(event)">Drag me</a></p>
+<p>Try to drag link above to the silver box. You should see word <span>PASS</span> not <strong>FAIL</strong> in feedback overlay all the time.</p>
+<div ondragenter="event.preventDefault()" ondragover="resetImage(event)"/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/007.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/007.xhtml
new file mode 100644
index 00000000000..c8461ea3ca8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/007.xhtml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Adding element to datastore on dragover</title>
+<style type="text/css">
+span, strong
+ {color:green;
+ background-color:yellow;}
+strong
+ {color:red;}
+div
+ {width:100px;
+ height:100px;
+ background-color:silver;
+ margin-top:20px;}
+</style>
+<script type="application/ecmascript">
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ event.dataTransfer.addElement(document.querySelector('span'));}
+function resetImage(event)
+ {event.preventDefault()
+ event.dataTransfer.addElement(document.querySelector('strong'));}
+</script>
+</head>
+<body>
+<p><a href="data:text/plain,1" ondragstart="start(event)">Drag me</a></p>
+<p>Try to drag link above to the silver box. You should see word <span>PASS</span> not <strong>FAIL</strong> in feedback overlay all the time.</p>
+<div ondragenter="event.preventDefault()" ondragover="resetImage(event)"/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/008.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/008.xhtml
new file mode 100644
index 00000000000..9c94229fac8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/008.xhtml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Resetting drag image on drag</title>
+<style type="text/css">
+span, strong
+ {color:green;
+ background-color:yellow;}
+strong
+ {color:red;}
+</style>
+<script type="application/ecmascript">
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ event.dataTransfer.setDragImage(document.querySelector('span'), 1, 1);}
+function resetImage(event)
+ {event.dataTransfer.setDragImage(document.querySelector('strong'), 1, 1);}
+</script>
+</head>
+<body>
+<p><a href="data:text/plain,1" ondragstart="start(event)" ondrag="resetImage(event)">Drag me</a></p>
+<p>Try to drag link above. You should see word <span>PASS</span> not <strong>FAIL</strong> in feedback overlay all the time.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/009.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/009.xhtml
new file mode 100644
index 00000000000..d9ffbcfcfa4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/009.xhtml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Adding element to datastore on drag</title>
+<style type="text/css">
+span, strong
+ {color:green;
+ background-color:yellow;}
+strong
+ {color:red;}
+</style>
+<script type="application/ecmascript">
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ event.dataTransfer.addElement(document.querySelector('span'));}
+function resetImage(event)
+ {event.dataTransfer.addElement(document.querySelector('strong'));}
+</script>
+</head>
+<body>
+<p><a href="data:text/plain,1" ondragstart="start(event)" ondrag="resetImage(event)">Drag me</a></p>
+<p>Try to drag link above. You should see word <span>PASS</span> not <strong>FAIL</strong> in feedback overlay all the time.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/010.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/010.xhtml
new file mode 100644
index 00000000000..1401823ec6c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/010.xhtml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Resetting drag image on new drag</title>
+<style type="text/css">
+span
+ {color:green;
+ background-color:yellow;}
+</style>
+<script type="application/ecmascript">
+var i = 0;
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ event.dataTransfer.setDragImage(document.querySelectorAll('span')[i++%2], 1, 1);}
+</script>
+</head>
+<body>
+<p><a href="data:text/plain,1" ondragstart="start(event)">Drag me</a></p>
+<p>Drag link above around the page drop it and try to drag again.</p>
+<p>First time you drag it you should see word <span>Odd</span> in feedback overlay, second time overlay should change to <span>Even</span>.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/011.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/011.xhtml
new file mode 100644
index 00000000000..d62be17f6db
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/011.xhtml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Feedback image for circle</title>
+<style type="text/css">
+body
+ {background-color:silver;
+ margin:0;}
+div
+ {background-color:white;}
+</style>
+</head>
+<body>
+<div><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAEq0lEQVR42u1dvU4bQRAeR0RCCilSp0peIoKGB4DSXYRDlcZlFClKBI4bB/kV/AymIDwCTahiicaioEOxhCsjWVTJziyKMfYZn+9ud3bvG2mEZB13u9+nndmf2Rki7fKFXtEBbVKD9o22jB4bPaND6hm9Mjo0enevw/vfevKMfbYl/8vv4HdBUkvFALhltG2A7dN3+pur8jv53fwN/hZkjjRo3eiuAatjdJA7CcnkDOSb/G1uQ6mFzUeDagaQrvl764yEJOU22LbUymXaGrRhOt40OvJOQvLIGUkbP9GLeIn4SM9NJ+tOTVI+Jq0ubY9sVFRNxy6DIWKWmEvpQ/ByQNumI+fBEjHrZ86lT8HJV3ptGn8aDRGzxJxKHwMZFe9Mg6+jJWNCyrX0VbUc0nuj4+jJmPiWsfRZodN+ZvSoNETMjpYjwUCFfKaXpjEnpSVjQsqJYOF5ZLw1elF6MiakXAgmnpw378DegIgZUm4EGw8jA2QsIuUbvXHpM2CmljFfhfsUO5uCA0/j6AudfZV5arv6WuVHcYs+ALwqKTkvHnmLoEwr8CJW9Llts9iNwvj3plzsfeWyIRnzrq37kfIzq6naBpA5a6bzlJgOl/SMkl+rklEFgIX5k5THwTYgIdwzcP2jhM/o19KsOeoArnBS6suaqo2gQnXCJWSwXNwXB4gBMFekNBeTwSGUmiMK4yNktDhsleNaAZRrUvYWmasuQHJOSDdpdKyriEIvo9maexWC70gAIF/bKTvzzFUH4HgbJZ3HdFSw9vC6lfKHpq7X8X07AOOblK2HhLQBindC2g/9Rx+gePcj/cnqHIDoUFm1c9gjwNAy/d0kyXIAMLSYrQ8kqScAhhbH3iLJBwIwtBByTJKkBWBoIeSMJHMOwNBCyG+SdEYAQ4tTvyLJMQUwtBAyJEn8BTC0EHIHQhQSApOlzGTBqaty6jzVAhhaCOlhYahuYYitE02EHGNzURchLZItX4ChhZB9HFBpUjmgwhGuHv0feI0gBw1T3j7CgHT5jzYC5XQRsjUdSsrhjADGl7ka0EylBgRb+ySkMy9rww7A8Waududf2MH9Qh9k3CbXLsGVNh/mqrvojuEeQHI+Qmq4Fq1ndIyeruaDxAEuCWk+ncmB0z3gepubtQenMUHyGTWELJl8xk6B15CeqVAyLtPXtUICsyJnVivWs+J0dAAwbzLOkQRTk2YuKsapTQFkXqPjlDILEinnRcZ1fpXdkGo866xqnH9FNyTjz0JIQZXcuPQCAE5rqo6oMEFBl7RknBRfTg8lj5Yl48JdGT0ueIWiYIvIuHFfPg9l85LJcF42b+JTUFjysZnyVlhy2qfA0asovTo9+0JxYnWC8t0KBQXuFYrdkIy3mBj3LbeNQrejZTuqOlbcl8znGTqcfjXoM3pboqgaPhEPxda1qgcVYsRt5TanDkgISWzcV1N1hCS3jdu4dNxUDMIhlBzXysHGGspkcBtsW2pPh3fGLrZ2ya5cXHFp0qxJ6si3E68EQCpy344vQRZxO5jfye+2d/oqgHsV02Z3lvcl9QTnA+EkLZw5h9MZcY4pTvxldXj/W0+esc+25H/5HQGYon+Q5f+MwFz+8QAAAABJRU5ErkJggg==" alt="PNG green pixel" ondragstart="event.dataTransfer.effectAllowed = 'copy'"/></div>
+<p>Try to drag green circle above. Feedback overlay should be a circle.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/012.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/012.xhtml
new file mode 100644
index 00000000000..5b069b99dd7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/012.xhtml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Feedback image and border-radius</title>
+<style type="text/css">
+body
+ {background-color:silver;
+ margin:0;}
+div
+ {background-color:white;}
+div > div
+ {display:block;
+ width:100px;
+ height:100px;
+ border:solid thin green;
+ border-radius:50px;}
+</style>
+</head>
+<body>
+<div>
+ <div draggable="true" ondragstart="event.dataTransfer.effectAllowed = 'copy'"/>
+</div>
+<p>Try to drag green circle above. Feedback overlay should be a circle.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/013.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/013.xhtml
new file mode 100644
index 00000000000..17ba67d1927
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/013.xhtml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Feedback image and CSS transforms</title>
+<style type="text/css">
+body
+ {background-color:silver;
+ margin:0;}
+div
+ {background-color:white;}
+div > div
+ {display:block;
+ width:100px;
+ height:87px;
+ transform-origin:bottom right;
+ transform:skew(-30deg);
+ -o-transform-origin:bottom right;
+ -o-transform:skew(-30deg);
+ background-color:green;}
+</style>
+</head>
+<body>
+<div>
+ <div draggable="true" ondragstart="event.dataTransfer.effectAllowed = 'copy'"/>
+</div>
+<p>Try to drag green rhomb above. Feedback overlay should not be rectangular.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/014.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/014.xhtml
new file mode 100644
index 00000000000..c853fa9cb13
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/014.xhtml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Setting drag image during drag and drop of selection</title>
+<style type="text/css">
+span
+ {color:green;
+ background-color:yellow;}
+</style>
+<script type="application/ecmascript">
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ event.dataTransfer.setDragImage(document.querySelector('span'), 1, 1);}
+</script>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('p'))">
+<p ondragstart="start(event)">Drag me</p>
+<p>Try to drag selection above. You should see word <span>PASS</span> in feedback overlay.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/015.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/015.xhtml
new file mode 100644
index 00000000000..63eb0f07e06
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/015.xhtml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Adding element to datastore during drag and drop of selection</title>
+<style type="text/css">
+span
+ {color:green;
+ background-color:yellow;}
+</style>
+<script type="application/ecmascript">
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ event.dataTransfer.addElement(document.querySelector('span'));}
+</script>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('p'))">
+<p ondragstart="start(event)">Drag me</p>
+<p>Try to drag selection above. You should see word <span>PASS</span> in feedback overlay.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/016.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/016.xhtml
new file mode 100644
index 00000000000..d60351b7421
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/016.xhtml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Setting drag image during drag and drop of PNG image</title>
+<style type="text/css">
+span
+ {color:green;
+ background-color:yellow;}
+img
+ {height:100px;
+ width:100px;}
+</style>
+<script type="application/ecmascript">
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ event.dataTransfer.setDragImage(document.querySelector('span'), 1, 1);}
+</script>
+</head>
+<body>
+<p ondragstart="start(event)">
+ <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAEElEQVR42mNgaGD4D8YwBgAw9AX9Y9zBwwAAAABJRU5ErkJggg==" alt="PNG green pixel"/>
+</p>
+<p>Try to drag green box above. You should see word <span>PASS</span> in feedback overlay.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/017.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/017.xhtml
new file mode 100644
index 00000000000..6bae357d614
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/017.xhtml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Adding element to datastore during drag and drop of PNG image</title>
+<style type="text/css">
+span
+ {color:green;
+ background-color:yellow;}
+img
+ {height:100px;
+ width:100px;}
+</style>
+<script type="application/ecmascript">
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ event.dataTransfer.addElement(document.querySelector('span'));}
+</script>
+</head>
+<body>
+<p ondragstart="start(event)">
+ <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAEElEQVR42mNgaGD4D8YwBgAw9AX9Y9zBwwAAAABJRU5ErkJggg==" alt="PNG green pixel"/>
+</p>
+<p>Try to drag green box above. You should see word <span>PASS</span> in feedback overlay.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/018.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/018.xhtml
new file mode 100644
index 00000000000..bfde05660ba
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/018.xhtml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Setting drag image during drag and drop of SVG image</title>
+<style type="text/css">
+span
+ {color:green;
+ background-color:yellow;}
+</style>
+<script type="application/ecmascript">
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ event.dataTransfer.setDragImage(document.querySelector('span'), 1, 1);}
+</script>
+</head>
+<body>
+<p><img src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20version%3D%221.1%22%20width%3D%22100px%22%20height%3D%22100px%22%20viewBox%3D%220%200%20100%20100%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22green%22/%3E%3C/svg%3E" alt="SVG circle" ondragstart="start(event)"/></p>
+<p>Try to drag green circle above. You should see word <span>PASS</span> in feedback overlay.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/019.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/019.xhtml
new file mode 100644
index 00000000000..130e716d6f4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/019.xhtml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Adding element to datastore during drag and drop of SVG image</title>
+<style type="text/css">
+span
+ {color:green;
+ background-color:yellow;}
+</style>
+<script type="application/ecmascript">
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ event.dataTransfer.addElement(document.querySelector('span'));}
+</script>
+</head>
+<body>
+<p><img src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20version%3D%221.1%22%20width%3D%22100px%22%20height%3D%22100px%22%20viewBox%3D%220%200%20100%20100%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22green%22/%3E%3C/svg%3E" alt="SVG circle" ondragstart="start(event)"/></p>
+<p>Try to drag green circle above. You should see word <span>PASS</span> in feedback overlay.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/020.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/020.xhtml
new file mode 100644
index 00000000000..80257d1d73d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/020.xhtml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Setting drag image during drag and drop of block element</title>
+<style type="text/css">
+div
+ {width:100px;
+ height:100px;
+ background-color:navy;}
+span
+ {color:green;
+ background-color:yellow;}
+</style>
+<script type="application/ecmascript">
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ event.dataTransfer.setDragImage(document.querySelector('span'), 1, 1);}
+</script>
+</head>
+<body>
+<div draggable="true" ondragstart="start(event)"/>
+<p>Try to drag blue box above. You should see word <span>PASS</span> in feedback overlay.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/021.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/021.xhtml
new file mode 100644
index 00000000000..d9400c71176
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/021.xhtml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Adding element to datastore during drag and drop of block element</title>
+<style type="text/css">
+div
+ {width:100px;
+ height:100px;
+ background-color:navy;}
+span
+ {color:green;
+ background-color:yellow;}
+</style>
+<script type="application/ecmascript">
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ event.dataTransfer.addElement(document.querySelector('span'));}
+</script>
+</head>
+<body>
+<div draggable="true" ondragstart="start(event)"/>
+<p>Try to drag blue box above. You should see word <span>PASS</span> in feedback overlay.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/022.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/022.xhtml
new file mode 100644
index 00000000000..8b8a0925a53
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/022.xhtml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Block element drag and drop: changing draggable attribute</title>
+<style type="text/css">
+div
+ {width:100px;
+ height:100px;
+ background-color:navy;}
+</style>
+</head>
+<body onload="document.querySelector('div').setAttribute('draggable','false')">
+<div draggable="true" ondragstart="document.querySelector('p').firstChild.nodeValue = 'FAIL'"/>
+<p>You should not be able to drag blue box.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/023.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/023.xhtml
new file mode 100644
index 00000000000..c3f7ddf51bb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/023.xhtml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Link drag and drop: changing draggable attribute</title>
+</head>
+<body onload="document.querySelector('a').setAttribute('draggable','false')">
+<p><a href="data:text/plain,1" ondragstart="document.querySelector('p').firstChild.nodeValue = 'FAIL'">Try to drag me</a></p>
+<p>You should not be able to drag link above.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/024.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/024.xhtml
new file mode 100644
index 00000000000..f514b208c7a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/024.xhtml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>PNG image drag and drop: changing draggable attribute</title>
+<style type="text/css">
+img
+ {width:100px;
+ height:100px;}
+</style>
+</head>
+<body onload="document.querySelector('img').setAttribute('draggable','false')">
+<p><img ondragstart="document.querySelector('p').firstChild.nodeValue = 'FAIL'" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAEElEQVR42mNgaGD4D8YwBgAw9AX9Y9zBwwAAAABJRU5ErkJggg==" alt="PNG green pixel"/></p>
+<p>You should not be able to drag green box.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/025.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/025.xhtml
new file mode 100644
index 00000000000..7bb8debd622
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/025.xhtml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>SVG image drag and drop: changing draggable attribute</title>
+<style type="text/css">
+img
+ {width:100px;
+ height:100px;}
+</style>
+</head>
+<body onload="document.querySelector('img').setAttribute('draggable','false')">
+<p><img ondragstart="document.querySelector('p').firstChild.nodeValue = 'FAIL'" src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20version%3D%221.1%22%20width%3D%22100px%22%20height%3D%22100px%22%20viewBox%3D%220%200%20100%20100%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22green%22/%3E%3C/svg%3E" alt="SVG circle"/></p>
+<p>You should not be able to drag green circle.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/026.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/026.xhtml
new file mode 100644
index 00000000000..0793daaee52
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/026.xhtml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop of overlapping links: zero height</title>
+<style type="text/css">
+span, strong
+ {color:green;
+ background-color:yellow;}
+strong
+ {color:red;}
+div
+ {width:4em;
+ padding:1em;
+ line-height:0;}
+a
+ {background-color:white;
+ padding:1ex;}
+</style>
+<script type="application/ecmascript">
+function start(event,feedback)
+ {event.dataTransfer.effectAllowed = 'copy';
+ event.dataTransfer.addElement(document.querySelector(feedback));}
+</script>
+</head>
+<body>
+<div>
+ <a href="data:text/plain,1" ondragstart="start(event,'strong')">    </a>
+ <a href="data:text/plain,2" ondragstart="start(event,'span')">Link</a>
+</div>
+<p>Try to drag link above. You should see word <span>PASS</span> not <strong>FAIL</strong> in feedback overlay all the time.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/027.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/027.xhtml
new file mode 100644
index 00000000000..7b2945ed90c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/027.xhtml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop of overlapping links: negative margin</title>
+<style type="text/css">
+span, strong
+ {color:green;
+ background-color:yellow;}
+strong
+ {color:red;}
+div
+ {height:2em;}
+div + div
+ {margin-top:-2em;}
+</style>
+<script type="application/ecmascript">
+function start(event,feedback)
+ {event.dataTransfer.effectAllowed = 'copy';
+ event.dataTransfer.addElement(document.querySelector(feedback));}
+</script>
+</head>
+<body>
+<div>
+ <a href="data:text/plain,1" ondragstart="start(event,'strong')">   </a>
+</div>
+<div>
+ <a href="data:text/plain,2" ondragstart="start(event,'span')">Link</a>
+</div>
+<p>Try to drag link above. You should see word <span>PASS</span> not <strong>FAIL</strong> in feedback overlay all the time.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/028.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/028.xhtml
new file mode 100644
index 00000000000..cba934b6d02
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/028.xhtml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop of overlapping links: relative position</title>
+<style type="text/css">
+span, strong
+ {color:green;
+ background-color:yellow;}
+strong
+ {color:red;}
+div
+ {height:2em;}
+div + div
+ {position:relative;
+ top:-2em;}
+</style>
+<script type="application/ecmascript">
+function start(event,feedback)
+ {event.dataTransfer.effectAllowed = 'copy';
+ event.dataTransfer.addElement(document.querySelector(feedback));}
+</script>
+</head>
+<body>
+<div>
+ <a href="data:text/plain,1" ondragstart="start(event,'strong')">   </a>
+</div>
+<div>
+ <a href="data:text/plain,2" ondragstart="start(event,'span')">Link</a>
+</div>
+<p>Try to drag link above. You should see word <span>PASS</span> not <strong>FAIL</strong> in feedback overlay all the time.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/029.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/029.xhtml
new file mode 100644
index 00000000000..dd02b1cdaf9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/029.xhtml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop of overlapping links: absolute position</title>
+<style type="text/css">
+span, strong
+ {color:green;
+ background-color:yellow;}
+strong
+ {color:red;}
+div
+ {height:2em;
+ position:absolute;
+ top:10px;
+ left:10px;}
+div + div
+ {z-index:2;}
+p
+ {margin-top:3em;}
+</style>
+<script type="application/ecmascript">
+function start(event,feedback)
+ {event.dataTransfer.effectAllowed = 'copy';
+ event.dataTransfer.addElement(document.querySelector(feedback));}
+</script>
+</head>
+<body>
+<div>
+ <a href="data:text/plain,1" ondragstart="start(event,'strong')">   </a>
+</div>
+<div>
+ <a href="data:text/plain,2" ondragstart="start(event,'span')">Link</a>
+</div>
+<p>Try to drag link above. You should see word <span>PASS</span> not <strong>FAIL</strong> in feedback overlay all the time.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/030.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/030.xhtml
new file mode 100644
index 00000000000..d86072dc852
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/030.xhtml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop of overlapping links: fixed position</title>
+<style type="text/css">
+span, strong
+ {color:green;
+ background-color:yellow;}
+strong
+ {color:red;}
+div
+ {height:2em;
+ position:fixed;
+ top:10px;
+ left:10px;}
+div + div
+ {z-index:2;}
+p
+ {margin-top:3em;}
+</style>
+<script type="application/ecmascript">
+function start(event,feedback)
+ {event.dataTransfer.effectAllowed = 'copy';
+ event.dataTransfer.addElement(document.querySelector(feedback));}
+</script>
+</head>
+<body>
+<div>
+ <a href="data:text/plain,1" ondragstart="start(event,'strong')">   </a>
+</div>
+<div>
+ <a href="data:text/plain,2" ondragstart="start(event,'span')">Link</a>
+</div>
+<p>Try to drag link above. You should see word <span>PASS</span> not <strong>FAIL</strong> in feedback overlay all the time.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/031.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/031.xhtml
new file mode 100644
index 00000000000..72ed959725a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/031.xhtml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop of overlapping images: negative margin</title>
+<style type="text/css">
+span, strong
+ {color:green;
+ background-color:yellow;}
+strong
+ {color:red;}
+img
+ {display:block;
+ width:100px;
+ height:100px;}
+img + img
+ {margin-top:-100px;}
+</style>
+<script type="application/ecmascript">
+function start(event,feedback)
+ {event.dataTransfer.effectAllowed = 'copy';
+ event.dataTransfer.addElement(document.querySelector(feedback));}
+</script>
+</head>
+<body>
+<div>
+ <img ondragstart="start(event,'strong')" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP4z8DwHwAFAAH/VscvDQAAAABJRU5ErkJggg=="/>
+ <img ondragstart="start(event,'span')" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNgaGD4DwAChAGAJVtEDQAAAABJRU5ErkJggg=="/>
+</div>
+<p>Try to drag box above. You should see word <span>PASS</span> not <strong>FAIL</strong> in feedback overlay all the time.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/032.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/032.xhtml
new file mode 100644
index 00000000000..22ae40193af
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/032.xhtml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop of overlapping images: absolute position</title>
+<style type="text/css">
+span, strong
+ {color:green;
+ background-color:yellow;}
+strong
+ {color:red;}
+div
+ {height:100px;
+ position:relative;}
+img
+ {display:block;
+ position:absolute;
+ top:0;
+ bottom:0;
+ width:100px;
+ height:100px;}
+</style>
+<script type="application/ecmascript">
+function start(event,feedback)
+ {event.dataTransfer.effectAllowed = 'copy';
+ event.dataTransfer.addElement(document.querySelector(feedback));}
+</script>
+</head>
+<body>
+<div>
+ <img ondragstart="start(event,'strong')" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP4z8DwHwAFAAH/VscvDQAAAABJRU5ErkJggg=="/>
+ <img ondragstart="start(event,'span')" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNgaGD4DwAChAGAJVtEDQAAAABJRU5ErkJggg=="/>
+</div>
+<p>Try to drag box above. You should see word <span>PASS</span> not <strong>FAIL</strong> in feedback overlay all the time.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/033.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/033.xhtml
new file mode 100644
index 00000000000..ba597bdcd60
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/033.xhtml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop of overlapping images: fixed position</title>
+<style type="text/css">
+span, strong
+ {color:green;
+ background-color:yellow;}
+strong
+ {color:red;}
+div
+ {height:100px;
+ position:relative;}
+img
+ {display:block;
+ position:fixed;
+ top:0;
+ bottom:0;
+ width:100px;
+ height:100px;}
+</style>
+<script type="application/ecmascript">
+function start(event,feedback)
+ {event.dataTransfer.effectAllowed = 'copy';
+ event.dataTransfer.addElement(document.querySelector(feedback));}
+</script>
+</head>
+<body>
+<div>
+ <img ondragstart="start(event,'strong')" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP4z8DwHwAFAAH/VscvDQAAAABJRU5ErkJggg=="/>
+ <img ondragstart="start(event,'span')" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNgaGD4DwAChAGAJVtEDQAAAABJRU5ErkJggg=="/>
+</div>
+<p>Try to drag box above. You should see word <span>PASS</span> not <strong>FAIL</strong> in feedback overlay all the time.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/034.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/034.xhtml
new file mode 100644
index 00000000000..d6b64da7540
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/034.xhtml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop of overlapping elements: negative margins</title>
+<style type="text/css">
+div
+ {height:100px;
+ width:100px;
+ margin-top:-50px;
+ background-color:navy;}
+div:nth-child(odd)
+ {background-color:maroon;
+ margin-left:50px;}
+div[draggable]
+ {background-color:teal;}
+</style>
+</head>
+<body>
+<div/>
+<div/>
+<div draggable="true"/>
+<div/>
+<div/>
+<div draggable="true"/>
+<div/>
+<div/>
+<p>Only green areas should be draggable.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/035.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/035.xhtml
new file mode 100644
index 00000000000..e0d26ce7d0d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/035.xhtml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop of floated overlapping elements: negative margins</title>
+<style type="text/css">
+div
+ {height:100px;
+ width:100px;
+ float:left;
+ margin-left:-50px;
+ background-color:navy;}
+div:nth-child(odd)
+ {background-color:maroon;
+ margin-top:50px;}
+div[draggable]
+ {background-color:teal;}
+</style>
+</head>
+<body>
+<p>Only green areas should be draggable.</p>
+<div/>
+<div/>
+<div draggable="true"/>
+<div/>
+<div/>
+<div draggable="true"/>
+<div/>
+<div/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/036.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/036.xhtml
new file mode 100644
index 00000000000..6ccb58fc217
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/036.xhtml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag feedback when multiple elements are added to dragstore</title>
+<style type="text/css">
+div > div
+ {height:100px;
+ width:100px;
+ float:left;
+ background-color:navy;}
+div + div
+ {margin-left:-60px;
+ background-color:maroon;}
+div[draggable]
+ {background-color:teal;
+ margin-top:50px;}
+</style>
+<script type="application/ecmascript">
+function start(event)
+ {var div = document.querySelectorAll('div > div:nth-child(odd)');
+ event.dataTransfer.effectAllowed = 'copy';
+ for(var i = 0; i != div.length; i++)
+ {event.dataTransfer.addElement(div[i]);}
+ }
+</script>
+</head>
+<body>
+<p>Try to drag green box below. Feedback overlay should include all three boxes when you drag green one.</p>
+<div ondragstart="start(event)">
+ <div/>
+ <div draggable="true"/>
+ <div/>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/038.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/038.xhtml
new file mode 100644
index 00000000000..db3f747ade5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/038.xhtml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Resetting drag image after element was added to dragstore</title>
+<style type="text/css">
+span, strong
+ {color:green;
+ background-color:yellow;}
+strong
+ {color:red;}
+</style>
+<script type="application/ecmascript">
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ event.dataTransfer.addElement(document.querySelector('strong'));
+ event.dataTransfer.setDragImage(document.querySelector('span'), 1, 1);}
+</script>
+</head>
+<body>
+<p><a href="data:text/plain,1" ondragstart="start(event)">Drag me</a></p>
+<p>Try to drag link above. You should see word <span>PASS</span> not <strong>FAIL</strong> in feedback overlay.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/039.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/039.xhtml
new file mode 100644
index 00000000000..500f5dabe71
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/039.xhtml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Resetting drag image during drag and drop of link</title>
+<style type="text/css">
+span, strong
+ {color:green;
+ background-color:yellow;}
+strong
+ {color:red;}
+</style>
+<script type="application/ecmascript">
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ event.dataTransfer.setDragImage(document.querySelector('strong'), 1, 1);
+ event.dataTransfer.setDragImage(document.querySelector('span'), 1, 1);}
+</script>
+</head>
+<body>
+<p><a href="data:text/plain,1" ondragstart="start(event)">Drag me</a></p>
+<p>Try to drag link above. You should see word <span>PASS</span> not <strong>FAIL</strong> in feedback overlay.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/040.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/040.xhtml
new file mode 100644
index 00000000000..73ab31aacd1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/040.xhtml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Cursor position and drag image</title>
+<script type="application/ecmascript">
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ event.dataTransfer.setDragImage(document.querySelector('canvas'), 50, 50);}
+</script>
+</head>
+<body>
+<p><a href="data:text/plain,1" ondragstart="start(event)">Drag me</a></p>
+<p>Try to drag link above. Feedback overlay should be based on canvas below and mouse pointer should be anchored in its center.</p>
+<p>
+ <canvas width="100" height="100">Canvas</canvas>
+</p>
+<script type="application/ecmascript">
+var canvas = document.querySelector('canvas'),
+c = canvas.getContext('2d');
+for(var x = 0; x != 50; x++)
+ {c.fillStyle = (x%2 == 0)?'navy':'white';
+ c.beginPath();
+ c.moveTo(x,x);
+ c.lineTo(100-x,x);
+ c.lineTo(100-x,100-x);
+ c.lineTo(x,100-x);
+ c.closePath();
+ c.fill();}
+</script>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/041.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/041.xhtml
new file mode 100644
index 00000000000..2b1bc06369b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/041.xhtml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Cursor position and drag image after new element is added to dragstore</title>
+<script type="application/ecmascript">
+function start(event,element)
+ {event.dataTransfer.effectAllowed = 'copy';
+ event.dataTransfer.addElement(document.querySelectorAll('canvas')[element]);}
+</script>
+</head>
+<body>
+<p>
+ <canvas width="100" height="100" draggable="true" ondragstart="start(event,1)">Canvas</canvas>
+ <canvas width="100" height="100" draggable="true" ondragstart="start(event,0)">Canvas</canvas>
+</p>
+<p>Try to drag canvas above. Feedback overlay should include both canvases and mouse pointer should be anchored in dragged ones center.</p>
+<script type="application/ecmascript">
+var canvases = document.querySelectorAll('canvas');
+paintCanvas(canvases[0],'navy');
+paintCanvas(canvases[1],'green');
+function paintCanvas(canvas,color)
+ {var c = canvas.getContext('2d');
+ for(var x = 0; x != 50; x++)
+ {c.fillStyle = (x%2 == 0)?color:'white';
+ c.beginPath();
+ c.moveTo(x,x);
+ c.lineTo(100-x,x);
+ c.lineTo(100-x,100-x);
+ c.lineTo(x,100-x);
+ c.closePath();
+ c.fill();}
+ }
+</script>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/042.html b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/042.html
new file mode 100644
index 00000000000..8a7db0e5dbc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/042.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - dragging elements that overlay each other</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: navy;
+ position: absolute;
+ top: 8px;
+ left: 8px;
+ }
+ body > div + div {
+ height: 100px;
+ width: 100px;
+ background-color: orange;
+ left: 58px;
+ top: 58px;
+ }
+ body > div + div + div {
+ background-color: fuchsia;
+ left: 258px;
+ }
+ p:first-of-type {
+ margin-top: 220px;
+ }
+</style>
+
+<script>
+
+window.onload = function() {
+ var passed = true, orange = document.getElementsByTagName('div')[1], blue = document.getElementsByTagName('div')[0], fuchsia = document.getElementsByTagName('div')[2];
+
+ orange.ondragstart = function(e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text/plain', 'PASS');
+ };
+ blue.ondragstart = function(e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text/plain', 'FAIL');
+ };
+ fuchsia.ondragenter = fuchsia.ondragover = function(e) {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'copy';
+ };
+ fuchsia.ondrop = function(e) {
+ //it's possible this could get called twice if the browser drags both items, so it uses the "passed" variable to make sure
+ //that if blue gets dropped first, it remains false when orange then gets dropped
+ passed = passed && ( e.dataTransfer.getData('text/plain') == 'PASS' );
+ document.getElementsByTagName('p')[0].innerHTML = passed ? 'PASS' : 'FAIL';
+ };
+
+};
+
+</script>
+
+<div draggable='true'></div><div draggable='true'></div><div></div>
+
+<p>Use your pointing device to drag the orange box to the pink box, then release it. While dragging, the drag placeholder should show that only the orange box is being dragged.</p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/043.html b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/043.html
new file mode 100644
index 00000000000..3b8093244d8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/043.html
@@ -0,0 +1,68 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - dragging nested draggable elements</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: navy;
+ position: absolute;
+ top: 8px;
+ left: 8px;
+ }
+ body > div div {
+ height: 100px;
+ width: 100px;
+ background-color: orange;
+ position: absolute;
+ left: 50px;
+ top: 50px;
+ }
+ body > div + div {
+ background-color: fuchsia;
+ height: 100px;
+ width: 100px;
+ left: 258px;
+ top: 58px;
+ }
+ p:first-of-type {
+ margin-top: 220px;
+ }
+</style>
+
+<script>
+
+window.onload = function() {
+ var passed = true, orange = document.getElementsByTagName('div')[1], blue = document.getElementsByTagName('div')[0], fuchsia = document.getElementsByTagName('div')[2];
+
+ orange.ondragstart = function(e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text/plain', 'child targeted');
+ };
+ blue.ondragstart = function(e) {
+ if( e.target == this ) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text/plain', 'parent targeted');
+ } else {
+ e.dataTransfer.setData('extra/data', 'parent bubble');
+ }
+ };
+ fuchsia.ondragenter = fuchsia.ondragover = function(e) {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'copy';
+ };
+ fuchsia.ondrop = function(e) {
+ e.preventDefault();
+ //it's possible this could get called twice if the browser drags both items, so it uses the "passed" variable to make sure
+ //that if blue gets dropped first, it remains false when orange then gets dropped
+ passed = passed && ( e.dataTransfer.getData('text/plain') == 'child targeted' ) && ( e.dataTransfer.getData('extra/data') == 'parent bubble' );
+ document.getElementsByTagName('p')[0].innerHTML = passed ? 'PASS' : 'FAIL';
+ };
+
+};
+
+</script>
+
+<div draggable='true'><div draggable='true'></div></div><div></div>
+
+<p>Use your pointing device to drag the orange box to the pink box, then release it. While dragging, the drag placeholder should show that only the orange box is being dragged.</p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/044.html b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/044.html
new file mode 100644
index 00000000000..a24ca2b7b38
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/044.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - dragging selections inside draggable elements</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ position: absolute;
+ top: 8px;
+ left: 8px;
+ }
+ body > div + div {
+ background-color: fuchsia;
+ left: 250px;
+ }
+ p:first-of-type {
+ margin-top: 220px;
+ }
+</style>
+
+<script>
+
+window.onload = function() {
+ var orange = document.getElementsByTagName('div')[0], fuchsia = document.getElementsByTagName('div')[1];
+
+ orange.ondragstart = function(e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('extra/data', 'parent bubble');
+ };
+ fuchsia.ondragenter = fuchsia.ondragover = function(e) {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'copy';
+ };
+ fuchsia.ondrop = function(e) {
+ e.preventDefault();
+ var passed = ( e.dataTransfer.getData('text/plain') == 'text dummy' ) && ( e.dataTransfer.getData('extra/data') == 'parent bubble' );
+ document.getElementsByTagName('p')[0].innerHTML = passed ? 'PASS' : 'FAIL';
+ };
+ var range = document.createRange();
+ range.selectNodeContents(orange);
+ range.setStart(orange.firstChild,6);
+ range.setEnd(orange.firstChild,16);
+ window.getSelection().addRange(range);
+
+};
+
+</script>
+
+<div draggable='true'>Dummy text dummy text</div><div></div>
+
+<p>Use your pointing device to <strong>drag the selected text</strong> to the pink box, then release it. While dragging, the drag placeholder should show that only the selected text is being dragged.</p>
+<p>(If no text is selected, you will need to use your browser's functionality to select &quot;text dummy&quot; in the orange box.)</p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/045.html b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/045.html
new file mode 100644
index 00000000000..80cd27c2835
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/045.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - dragging iframes overlaying draggable elements</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: blue;
+ position: absolute;
+ top: 8px;
+ left: 8px;
+ }
+ body > div + div {
+ background-color: fuchsia;
+ left: 258px;
+ }
+ iframe {
+ border: 5px solid yellow;
+ height: 130px;
+ width: 130px;
+ position: absolute;
+ top: 38px;
+ left: 38px;
+ }
+ p:first-of-type {
+ margin-top: 220px;
+ }
+</style>
+
+<script>
+
+window.onload = function() {
+ var orange = document.getElementsByTagName('div')[0], fuchsia = document.getElementsByTagName('div')[1];
+
+ orange.ondragstart = function(e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text/plain', 'FAIL');
+ };
+ fuchsia.ondragenter = fuchsia.ondragover = function(e) {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'copy';
+ };
+ fuchsia.ondrop = function(e) {
+ e.preventDefault();
+ document.getElementsByTagName('p')[0].innerHTML = 'FAIL';
+ };
+
+};
+
+</script>
+
+<div draggable='true'></div><div></div>
+
+<p>Use your pointing device to begin dragging inside the yellow border (not on any scrollbars that may appear), over to the pink box, then release it. Pass if nothing is dragged, and if this text does not change.
+<iframe src="about:blank"></iframe></p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/046.html b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/046.html
new file mode 100644
index 00000000000..89d67cd7bf0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/046.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - dragging iframes inside draggable elements</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: blue;
+ position: absolute;
+ top: 8px;
+ left: 8px;
+ }
+ body > div + div {
+ background-color: fuchsia;
+ left: 258px;
+ }
+ iframe {
+ border: 5px solid yellow;
+ height: 130px;
+ width: 130px;
+ position: absolute;
+ top: 30px;
+ left: 30px;
+ }
+ p:first-of-type {
+ margin-top: 220px;
+ }
+</style>
+
+<script>
+
+window.onload = function() {
+ var orange = document.getElementsByTagName('div')[0], fuchsia = document.getElementsByTagName('div')[1];
+
+ orange.ondragstart = function(e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text/plain', 'FAIL');
+ };
+ fuchsia.ondragenter = fuchsia.ondragover = function(e) {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'copy';
+ };
+ fuchsia.ondrop = function(e) {
+ e.preventDefault();
+ document.getElementsByTagName('p')[0].innerHTML = 'FAIL';
+ };
+
+};
+
+</script>
+
+<div draggable='true'><iframe src="about:blank"></iframe></div><div></div>
+
+<p>Use your pointing device to begin dragging inside the yellow border (not on any scrollbars that may appear), over to the pink box, then release it. Pass if nothing is dragged, and if this text does not change.</p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/047.html b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/047.html
new file mode 100644
index 00000000000..10f167a871c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/047.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - dragging objects overlaying draggable elements</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: blue;
+ position: absolute;
+ top: 8px;
+ left: 8px;
+ }
+ body > div + div {
+ background-color: fuchsia;
+ left: 258px;
+ }
+ object {
+ border: 5px solid yellow;
+ height: 130px;
+ width: 130px;
+ position: absolute;
+ top: 38px;
+ left: 38px;
+ }
+ p:first-of-type {
+ margin-top: 220px;
+ }
+</style>
+
+<script>
+
+window.onload = function() {
+ var orange = document.getElementsByTagName('div')[0], fuchsia = document.getElementsByTagName('div')[1];
+
+ orange.ondragstart = function(e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text/plain', 'FAIL');
+ };
+ fuchsia.ondragenter = fuchsia.ondragover = function(e) {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'copy';
+ };
+ fuchsia.ondrop = function(e) {
+ e.preventDefault();
+ document.getElementsByTagName('p')[0].innerHTML = 'FAIL';
+ };
+
+};
+
+</script>
+
+<div draggable='true'></div><div></div>
+
+<p>Use your pointing device to begin dragging inside the yellow border (not on any scrollbars that may appear), over to the pink box, then release it. Pass if nothing is dragged, and if this text does not change.
+<object data="about:blank"></object></p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/048.html b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/048.html
new file mode 100644
index 00000000000..d319fa27239
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/048.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - dragging objects inside draggable elements</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: blue;
+ position: absolute;
+ top: 8px;
+ left: 8px;
+ }
+ body > div + div {
+ background-color: fuchsia;
+ left: 258px;
+ }
+ object {
+ border: 5px solid yellow;
+ height: 130px;
+ width: 130px;
+ position: absolute;
+ top: 30px;
+ left: 30px;
+ }
+ p:first-of-type {
+ margin-top: 220px;
+ }
+</style>
+
+<script>
+
+window.onload = function() {
+ var orange = document.getElementsByTagName('div')[0], fuchsia = document.getElementsByTagName('div')[1];
+
+ orange.ondragstart = function(e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text/plain', 'FAIL');
+ };
+ fuchsia.ondragenter = fuchsia.ondragover = function(e) {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'copy';
+ };
+ fuchsia.ondrop = function(e) {
+ e.preventDefault();
+ document.getElementsByTagName('p')[0].innerHTML = 'FAIL';
+ };
+
+};
+
+</script>
+
+<div draggable='true'><object data="about:blank"></object></div><div></div>
+
+<p>Use your pointing device to begin dragging inside the yellow border (not on any scrollbars that may appear), over to the pink box, then release it. Pass if nothing is dragged, and if this text does not change.</p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/049.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/049.xhtml
new file mode 100644
index 00000000000..4f63d6ebaa9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/049.xhtml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag feedback for partly visible image: negative margins</title>
+<style type="text/css">
+p:first-child
+ {margin:-50px 0 0 -50px;}
+img
+ {height:100px;
+ width:100px;}
+</style>
+</head>
+<body>
+<p><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAEElEQVR42mNgaGD4D8YwBgAw9AX9Y9zBwwAAAABJRU5ErkJggg==" alt="PNG green pixel" ondragstart="event.dataTransfer.effectAllowed = 'copy'"/></p>
+<p>Try to drag green box above. Feedback overlay should be green square.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/050.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/050.xhtml
new file mode 100644
index 00000000000..112fbd0a78c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/050.xhtml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag feedback for partly visible image: relative position</title>
+<style type="text/css">
+p:first-child
+ {margin:0;
+ position:relative;
+ top:-50px;
+ left:-50px;}
+img
+ {display:block;
+ height:100px;
+ width:100px;}
+</style>
+</head>
+<body>
+<p><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAEElEQVR42mNgaGD4D8YwBgAw9AX9Y9zBwwAAAABJRU5ErkJggg==" alt="PNG green pixel" ondragstart="event.dataTransfer.effectAllowed = 'copy'"/></p>
+<p>Try to drag green box above. Feedback overlay should be green square.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/051.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/051.xhtml
new file mode 100644
index 00000000000..befd0779098
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/051.xhtml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag feedback for partly visible image: absolute position</title>
+<style type="text/css">
+img
+ {position:absolute;
+ top:-50px;
+ left:-50px;}
+p + p
+ {margin-top:100px;}
+img
+ {height:100px;
+ width:100px;}
+</style>
+</head>
+<body>
+<p><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAEElEQVR42mNgaGD4D8YwBgAw9AX9Y9zBwwAAAABJRU5ErkJggg==" alt="PNG green pixel" ondragstart="event.dataTransfer.effectAllowed = 'copy'"/></p>
+<p>Try to drag green box above. Feedback overlay should be green square.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/052.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/052.xhtml
new file mode 100644
index 00000000000..36e9e704c8f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/052.xhtml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag feedback for partly visible image: fixed position</title>
+<style type="text/css">
+img
+ {position:fixed;
+ top:-50px;
+ left:-50px;}
+p + p
+ {margin-top:100px;}
+img
+ {height:100px;
+ width:100px;}
+</style>
+</head>
+<body>
+<p><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAEElEQVR42mNgaGD4D8YwBgAw9AX9Y9zBwwAAAABJRU5ErkJggg==" alt="PNG green pixel" ondragstart="event.dataTransfer.effectAllowed = 'copy'"/></p>
+<p>Try to drag green box above. Feedback overlay should be green square.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/053.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/053.xhtml
new file mode 100644
index 00000000000..b66a6e6f6ed
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/053.xhtml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag feedback for partly visible element: negative margins</title>
+<style type="text/css">
+div
+ {margin:-160px 0 0 -160px;
+ height:200px;
+ width:200px;
+ background-color:navy;}
+</style>
+</head>
+<body>
+<div draggable="true" ondragstart="event.dataTransfer.effectAllowed = 'copy'"/>
+<p>Try to drag blue box above. Feedback overlay should be square.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/054.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/054.xhtml
new file mode 100644
index 00000000000..2b34d647e15
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/054.xhtml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag feedback for partly visible element: relative position</title>
+<style type="text/css">
+div
+ {position:relative;
+ top:-150px;
+ left:-150px;
+ height:200px;
+ width:200px;
+ background-color:navy;}
+</style>
+</head>
+<body>
+<div draggable="true" ondragstart="event.dataTransfer.effectAllowed = 'copy'"/>
+<p>Try to drag blue box above. Feedback overlay should be square.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/055.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/055.xhtml
new file mode 100644
index 00000000000..93df7ebc36e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/055.xhtml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag feedback for partly visible element: absolute position</title>
+<style type="text/css">
+div
+ {position:absolute;
+ top:-150px;
+ left:-150px;
+ height:200px;
+ width:200px;
+ background-color:navy;}
+p
+ {margin-top:100px;}
+</style>
+</head>
+<body>
+<div draggable="true" ondragstart="event.dataTransfer.effectAllowed = 'copy'"/>
+<p>Try to drag blue box above. Feedback overlay should be square.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/056.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/056.xhtml
new file mode 100644
index 00000000000..838d4389178
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/056.xhtml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag feedback for partly visible element: fixed position</title>
+<style type="text/css">
+div
+ {position:fixed;
+ top:-150px;
+ left:-150px;
+ height:200px;
+ width:200px;
+ background-color:navy;}
+p
+ {margin-top:100px;}
+</style>
+</head>
+<body>
+<div draggable="true" ondragstart="event.dataTransfer.effectAllowed = 'copy'"/>
+<p>Try to drag blue box above. Feedback overlay should be square.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/057.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/057.xhtml
new file mode 100644
index 00000000000..5f5805b2eb7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/057.xhtml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag feedback for partly visible float: negative margins</title>
+<style type="text/css">
+p
+ {margin-top:0;}
+div
+ {float:left;
+ margin:-150px 0 0 -150px;
+ height:200px;
+ width:200px;
+ background-color:navy;}
+</style>
+</head>
+<body>
+<div draggable="true" ondragstart="event.dataTransfer.effectAllowed = 'copy'"/>
+<p>Try to drag blue box above. Feedback overlay should be square.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/058.html b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/058.html
new file mode 100644
index 00000000000..560c6fdfefc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/058.html
@@ -0,0 +1,29 @@
+<!doctype html>
+<title>drag &amp; drop - dragging elements by children that extend out of them</title>
+<style type="text/css">
+div {
+ height: 200px;
+ width: 200px;
+ background: blue;
+ white-space: nowrap;
+}
+span {
+ display: inline-block;
+ width: 210px;
+ height: 100px;
+}
+span + span {
+ background: orange;
+ width: 100px;
+}
+</style>
+<script type="text/javascript">
+window.onload = function () {
+ document.getElementsByTagName('div')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text','dummy text');
+ };
+};
+</script>
+<div draggable="true"><span></span><span></span></div>
+<p>Drag the orange square sideways. Pass if the drag placeholder shows that both the blue and orange squares are being dragged.</p> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/059.html b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/059.html
new file mode 100644
index 00000000000..db6572033c6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/059.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<title>drag &amp; drop - dragging elements by text that extends out of them</title>
+<style type="text/css">
+div {
+ height: 200px;
+ width: 200px;
+ background: blue;
+ white-space: nowrap;
+}
+</style>
+<script type="text/javascript">
+window.onload = function () {
+ document.getElementsByTagName('div')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text','dummy text');
+ };
+};
+</script>
+<div draggable="true">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Drag me</div>
+<p>Drag the above text sideways. Pass if the drag placeholder shows that both the text and blue square are being dragged.</p> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/060.html b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/060.html
new file mode 100644
index 00000000000..b8d169f0e64
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/060.html
@@ -0,0 +1,30 @@
+<!doctype html>
+<title>drag &amp; drop - dragging elements by children that are positioned outside them</title>
+<style type="text/css">
+div {
+ height: 200px;
+ width: 200px;
+ background: blue;
+ white-space: nowrap;
+ position: relative;
+}
+span {
+ display: block;
+ top: 0;
+ left: 210px;
+ position: absolute;
+ width: 100px;
+ height: 100px;
+ background: orange;
+}
+</style>
+<script type="text/javascript">
+window.onload = function () {
+ document.getElementsByTagName('div')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text','dummy text');
+ };
+};
+</script>
+<div draggable="true"><span></span></div>
+<p>Drag the orange square sideways. Pass if the drag placeholder shows that both the blue and orange squares are being dragged.</p> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/061.html b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/061.html
new file mode 100644
index 00000000000..b1665171f08
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/061.html
@@ -0,0 +1,30 @@
+<!doctype html>
+<title>drag &amp; drop - dragging elements by overflowing children that are positioned outside them</title>
+<style type="text/css">
+div {
+ height: 200px;
+ width: 200px;
+ background: blue;
+ white-space: nowrap;
+ position: relative;
+}
+span {
+ display: block;
+ top: 0;
+ left: 210px;
+ position: absolute;
+ width: 100px;
+ height: 100px;
+ background: yellow;
+}
+</style>
+<script type="text/javascript">
+window.onload = function () {
+ document.getElementsByTagName('div')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text','dummy text');
+ };
+};
+</script>
+<div draggable="true"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Drag me</span></div>
+<p>Drag the above text sideways. Pass if the drag placeholder shows that the text and both the yellow and blue squares are being dragged.</p> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/062.html b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/062.html
new file mode 100644
index 00000000000..43fc8342d0b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/062.html
@@ -0,0 +1,22 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Selection spanning hidden elements</title>
+ <script type="text/javascript">
+window.onload = function () {
+ var range = document.createRange(), p = document.getElementsByTagName('p')[0];
+ range.selectNodeContents(p);
+ range.setStart(p.firstChild.firstChild,4);
+ range.setEnd(p.lastChild.firstChild,5);
+ window.getSelection().addRange(range);
+};
+ </script>
+ </head>
+ <body>
+
+ <p><span style="display:none">FAILPASS_</span>drag<span style="display:none">_THIS_</span>text<span style="display:none">_PASSFAIL</span></p>
+ <p><textarea rows="3" cols="50"></textarea></p>
+ <p>Drag the selected text into the input box. The drag placeholder should match the visible text that is being dragged. When dropped, either &quot;dragtext&quot; or &quot;PASS_drag_THIS_text_PASS&quot; should appear in the input.</p>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/heavy-styling-001.html b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/heavy-styling-001.html
new file mode 100644
index 00000000000..05f69fa61cd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/heavy-styling-001.html
@@ -0,0 +1,16 @@
+<!DOCTYPe html>
+<meta charset='utf-8'>
+<title>drag and drop – feedback overlay for heavily styled elements – 001</title>
+<style>
+a {
+ display: block;
+ height: 200px;
+ width: 200px;
+ background-color: blue;
+ box-shadow: 10px 10px 10px gray;
+}
+</style>
+
+<p>Drag the blue box below downwards. The drag placeholder should resemble the blue box. It may optionally also include the box's shadow.</p>
+
+<a href='#' draggable="true" ondragstart="event.dataTransfer.effectAllowed ='copy'"></a>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/heavy-styling-002.html b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/heavy-styling-002.html
new file mode 100644
index 00000000000..de3b2e296e6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/heavy-styling-002.html
@@ -0,0 +1,16 @@
+<!DOCTYPe html>
+<meta charset='utf-8'>
+<title>drag and drop – feedback overlay for heavily styled elements – 002</title>
+<style>
+a {
+ display: block;
+ height: 200px;
+ width: 200px;
+ background-color: blue;
+ border: 10px solid orange;
+}
+</style>
+
+<p>Drag the blue box below downwards. The drag placeholder should resemble the blue box, including the orange border.</p>
+
+<a href='#' draggable="true" ondragstart="event.dataTransfer.effectAllowed ='copy'"></a>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/heavy-styling-003.html b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/heavy-styling-003.html
new file mode 100644
index 00000000000..adb0a3581c2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/heavy-styling-003.html
@@ -0,0 +1,16 @@
+<!DOCTYPe html>
+<meta charset='utf-8'>
+<title>drag and drop – feedback overlay for heavily styled elements – 002</title>
+<style>
+a {
+ display: block;
+ height: 200px;
+ width: 200px;
+ background-color: blue;
+ outline: 10px solid orange;
+}
+</style>
+
+<p>Drag the blue box below downwards. The drag placeholder should resemble the blue box. It may optionally also include include the orange border.</p>
+
+<a href='#' draggable="true" ondragstart="event.dataTransfer.effectAllowed ='copy'"></a>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/heavy-styling-004.html b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/heavy-styling-004.html
new file mode 100644
index 00000000000..d6a5da41c01
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/heavy-styling-004.html
@@ -0,0 +1,19 @@
+<!DOCTYPe html>
+<meta charset='utf-8'>
+<title>drag and drop – feedback overlay for heavily styled elements – 004</title>
+<style>
+a {
+ display: block;
+ height: 200px;
+ width: 200px;
+ background-color: blue;
+ box-shadow: 10px 10px 10px gray;
+}
+div {
+ background-color: orange;
+}
+</style>
+
+<p>Drag the blue box below downwards. The drag placeholder should resemble the blue box. It may optionally also include the box's shadow, but must not include the orange rectangle.</p>
+
+<div><a href='#' draggable="true" ondragstart="event.dataTransfer.effectAllowed ='copy'"></a></div>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/heavy-styling-005.html b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/heavy-styling-005.html
new file mode 100644
index 00000000000..2bbdb3cf73b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/heavy-styling-005.html
@@ -0,0 +1,15 @@
+<!DOCTYPe html>
+<meta charset='utf-8'>
+<title>drag and drop – feedback overlay for heavily styled elements – 005</title>
+<style>
+a {
+ display: block;
+ height: 200px;
+ width: 200px;
+ background-color: rgba(0,0,255,0.5);
+}
+</style>
+
+<p>Drag the blue box below downwards. The drag placeholder should resemble the blue box, including the text within it.</p>
+
+<a draggable="true" ondragstart="event.dataTransfer.effectAllowed ='copy'">TEST</a>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/heavy-styling-006.html b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/heavy-styling-006.html
new file mode 100644
index 00000000000..c067878f22e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/heavy-styling-006.html
@@ -0,0 +1,16 @@
+<!DOCTYPe html>
+<meta charset='utf-8'>
+<title>drag and drop – feedback overlay for heavily styled elements – 006</title>
+<style>
+a {
+ display: block;
+ height: 200px;
+ width: 200px;
+ background-color: blue;
+ opacity: 0.5;
+}
+</style>
+
+<p>Drag the blue box below downwards. The drag placeholder should resemble the blue box, including the text within it.</p>
+
+<a draggable="true" ondragstart="event.dataTransfer.effectAllowed ='copy'">TEST</a>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/heavy-styling-007.html b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/heavy-styling-007.html
new file mode 100644
index 00000000000..56ba9594f2e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/heavy-styling-007.html
@@ -0,0 +1,20 @@
+<!DOCTYPe html>
+<meta charset='utf-8'>
+<title>drag and drop – feedback overlay for heavily styled elements – 007</title>
+<style>
+a {
+ display: block;
+ height: 200px;
+ width: 200px;
+ background-color: blue;
+ margin-left: 100px;
+ -moz-transform: rotate(-45deg) skew(15deg, 15deg);
+ -o-transform: rotate(-45deg) skew(15deg, 15deg);
+ -webkit-transform: rotate(-45deg) skew(15deg, 15deg);
+ transform: rotate(-45deg) skew(15deg, 15deg);
+}
+</style>
+
+<p>Drag the blue box below downwards. The drag placeholder should resemble the blue box, including the text within it, and with the same rotation.</p>
+
+<a draggable="true" ondragstart="event.dataTransfer.effectAllowed ='copy'">TEST</a>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/heavy-styling-008.html b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/heavy-styling-008.html
new file mode 100644
index 00000000000..7a78f814e1b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/heavy-styling-008.html
@@ -0,0 +1,31 @@
+<!DOCTYPe html>
+<meta charset='utf-8'>
+<title>drag and drop – feedback overlay for heavily styled elements – 008</title>
+<style>
+a {
+ display: block;
+ height: 200px;
+ width: 200px;
+ background-color: green;
+ position: absolute;
+ top: 100px;
+ left: 10px;
+ z-index: 1;
+}
+
+a + a {
+ background-color: red;
+ position: absolute;
+ top: 150px;
+ left: 20px;
+ z-index: 2;
+}
+
+
+</style>
+
+<p>Drag the green box below downwards. The drag placeholder should resemble the green box, including the text within it. It may optionally be a complete square, or the same shape as the visible part of the green box. There should be no red in the drag placeholder.</p>
+
+<a draggable="true" ondragstart="event.dataTransfer.effectAllowed ='copy'">TEST</a>
+
+<a href='#'>TEST</a>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/heavy-styling-009.html b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/heavy-styling-009.html
new file mode 100644
index 00000000000..0f36fe08345
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/heavy-styling-009.html
@@ -0,0 +1,16 @@
+<!DOCTYPe html>
+<meta charset='utf-8'>
+<title>drag and drop – feedback overlay for heavily styled elements – 009</title>
+<style>
+a {
+ display: block;
+ height: 200px;
+ width: 200px;
+ background-color: blue;
+ border-radius: 50px;
+}
+</style>
+
+<p>Drag the blue box below downwards. The drag placeholder should resemble the blue box, including the rounded corners.</p>
+
+<a draggable="true" ondragstart="event.dataTransfer.effectAllowed ='copy'"></a>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/outside-viewport-001.html b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/outside-viewport-001.html
new file mode 100644
index 00000000000..ecc7ebbf3b2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/outside-viewport-001.html
@@ -0,0 +1,22 @@
+<!DOCTYPe html>
+<meta charset='utf-8'>
+<title>drag and drop – feedback overlay of elements partly outside the viewport – 001</title>
+<style>
+a {
+ display: block;
+ height: 200px;
+ width: 200px;
+ background-color: blue;
+ position: absolute;
+ top: 10px;
+ right: -100px;
+}
+
+p {
+ margin-right: 200px;
+}
+</style>
+
+<a href='#'></a>
+
+<p>Drag the blue box on the right downwards. The drag placeholder should ideally be a blue square. It may optionally be a rectangle the same shape as the visible part of the blue box. No part of the UI should be dragged with the box.</p>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/outside-viewport-002.html b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/outside-viewport-002.html
new file mode 100644
index 00000000000..3878c31d0ab
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/outside-viewport-002.html
@@ -0,0 +1,22 @@
+<!DOCTYPe html>
+<meta charset='utf-8'>
+<title>drag and drop – feedback overlay of elements partly outside the viewport – 002</title>
+<style>
+img {
+ height: 200px;
+ width: 200px;
+ position: absolute;
+ top: 10px;
+ right: -100px;
+}
+
+p {
+ margin-right: 200px;
+}
+</style>
+
+
+<img alt=''
+src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAACRJREFUOE9jZGBoYCARADWQhEhTDXIOScaPaiAyuEaDlXBAAQBiw3iCaRp9LAAAAABJRU5ErkJggg%3D%3D'>
+
+<p>Drag the blue box on the right. The drag placeholder should ideally be a blue square. It may optionally be a rectangle the same shape as the visible part of the blue box. No part of the UI should be dragged with the box.</p>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/outside-viewport-003.html b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/outside-viewport-003.html
new file mode 100644
index 00000000000..895a008f981
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/outside-viewport-003.html
@@ -0,0 +1,22 @@
+<!DOCTYPe html>
+<meta charset='utf-8'>
+<title>drag and drop – feedback overlay of elements partly outside the viewport – 003</title>
+<style>
+a {
+ display: block;
+ height: 200px;
+ width: 200px;
+ background-color: blue;
+ position: absolute;
+ top: -100px;
+ right: -100px;
+}
+
+p {
+ margin-right: 200px;
+}
+</style>
+
+<a href='#'></a>
+
+<p>Drag the blue box on the right downwards. The drag placeholder should ideally be a blue square twice as high and wide as the visible part of the blue box. It may optionally be a square the same size as the visible part of the blue box. No part of the UI should be dragged with the box.</p>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/outside-viewport-004.html b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/outside-viewport-004.html
new file mode 100644
index 00000000000..61bc22eefe9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/outside-viewport-004.html
@@ -0,0 +1,21 @@
+<!DOCTYPe html>
+<meta charset='utf-8'>
+<title>drag and drop – feedback overlay of elements partly outside the viewport – 004</title>
+<style>
+img {
+ height: 200px;
+ width: 200px;
+ position: absolute;
+ top: -100px;
+ right: -100px;
+}
+
+p {
+ margin-right: 200px;
+}
+</style>
+
+<img alt=''
+src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAACRJREFUOE9jZGBoYCARADWQhEhTDXIOScaPaiAyuEaDlXBAAQBiw3iCaRp9LAAAAABJRU5ErkJggg%3D%3D'>
+
+<p>Drag the blue box on the right. The drag placeholder should ideally be a blue square twice as high and wide as the visible part of the blue box. It may optionally be a square the same size as the visible part of the blue box. No part of the UI should be dragged with the box.</p>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/outside-viewport-005.html b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/outside-viewport-005.html
new file mode 100644
index 00000000000..26e4bff2eb4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/outside-viewport-005.html
@@ -0,0 +1,22 @@
+<!DOCTYPe html>
+<meta charset='utf-8'>
+<title>drag and drop – feedback overlay of elements partly outside the viewport – 005</title>
+<style>
+div {
+ display: block;
+ height: 200px;
+ width: 200px;
+ background-color: blue;
+ position: absolute;
+ top: 10px;
+ right: -100px;
+}
+
+p {
+ margin-right: 200px;
+}
+</style>
+
+<div draggable="true" ondragstart="event.dataTransfer.effectAllowed ='copy'"></div>
+
+<p>Drag the blue box on the right. The drag placeholder should ideally be a blue square. It may optionally be a rectangle the same shape as the visible part of the blue box. No part of the UI should be dragged with the box.</p>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/outside-viewport-006.html b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/outside-viewport-006.html
new file mode 100644
index 00000000000..d10f06dfddb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/outside-viewport-006.html
@@ -0,0 +1,22 @@
+<!DOCTYPe html>
+<meta charset='utf-8'>
+<title>drag and drop – feedback overlay of elements partly outside the viewport – 006</title>
+<style>
+div {
+ display: block;
+ height: 200px;
+ width: 200px;
+ background-color: blue;
+ position: absolute;
+ top: -100px;
+ right: -100px;
+}
+
+p {
+ margin-right: 200px;
+}
+</style>
+
+<div draggable="true" ondragstart="event.dataTransfer.effectAllowed ='copy'"></div>
+
+<p>Drag the blue box on the right. The drag placeholder should ideally be a blue square twice as high and wide as the visible part of the blue box. It may optionally be a square the same size as the visible part of the blue box. No part of the UI should be dragged with the box.</p>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/overlay/oversized-001.html b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/oversized-001.html
new file mode 100644
index 00000000000..e13f6b190bc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/overlay/oversized-001.html
@@ -0,0 +1,18 @@
+<!DOCTYPe html>
+<meta charset='utf-8'>
+<title>drag and drop – feedback overlay of oversized element</title>
+<style>
+html, body, p + p { height: 100%; width: 100%; }
+a {
+ display: block;
+ height: 100%;
+ width: 100%;
+ background-color: blue;
+ border: 50px solid orange; /* makes it higher and wider than the viewport */
+}
+
+</style>
+
+<p>Drag the blue box below downwards. The drag placeholder should ideally be a blue rectangle with an orange border on all sides. It may optionally match the visible part of the blue-and-orange box. It may optionally be a rectangle with the same pattern and size as the visible part of the blue-and-orange box. It may optionally be shrunk to a manageable size. No part of the UI should be dragged with the box.</p>
+
+<p><a href='#'></a></p>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/alttab.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/alttab.html
new file mode 100644
index 00000000000..c3375d3d840
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/alttab.html
@@ -0,0 +1,12 @@
+<!doctype html>
+<html>
+ <head>
+ <title>drag and drop - alt+tab while dragging</title>
+ </head>
+ <body>
+
+ <p>This test is only relevant on platforms where alt+tab (or some equivalent) switches applications.</p>
+ <p>Ensure that at least one other application is open. Select this text. Drag the selection downwards a little, then alt+tab (or your system's equivalent) to the other application. Pass if the drag placeholder continues to follow the mouse/pointing device. Release the drag. Pass if the drag placeholder disappears.</p>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/cancel-middle-click.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/cancel-middle-click.html
new file mode 100644
index 00000000000..4136e2be711
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/cancel-middle-click.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Drag and drop with middle click</title>
+ <style type="text/css">
+div {
+ width: 100px;
+ height: 100px;
+ background: orange;
+ float: left;
+}
+div + div {
+ background: blue;
+}
+div + div + div {
+ background: fuchsia;
+}
+ol {
+ clear: left;
+}
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ document.getElementsByTagName('div')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text','dummy text');
+ };
+};
+ </script>
+ </head>
+ <body>
+ <div draggable="true"></div>
+ <div></div>
+ <div></div>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <ol>
+ <li>Drag the orange square over the blue square.</li>
+ <li>Without releasing the drag, click the middle mouse button.</li>
+ <li>If the platform's normal behaviour is to cancel a drag (eg. Windows and Unix+KDE), then the drag should be cancelled;<ul>
+ <li>The drag placeholder should disappear, and the cursor should return to the normal mouse cursor.</li>
+ <li>Move the mouse over the pink square and release the drag. The mouse cursor should remain the normal mouse cursor.</li>
+ </ul></li>
+ <li>If the platform's normal behaviour is not to cancel a drag (eg. Mac and Unix+Gnome), then the drag should not be cancelled;<ul>
+ <li>The drag placeholder should not disappear, and the cursor should be the no-drop cursor.</li>
+ <li>Move the mouse over the pink square and release the drag. The drag placeholder should disappear, and the cursor should return to the normal mouse cursor.</li>
+ </ul></li>
+ <li>Fail in either case if an inappropriate middle click function begins (eg. paste-and-go).</li>
+ </ol>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/cancel-right-click.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/cancel-right-click.html
new file mode 100644
index 00000000000..85416da52fc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/cancel-right-click.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Drag and drop with right click</title>
+ <style type="text/css">
+div {
+ width: 100px;
+ height: 100px;
+ background: orange;
+ float: left;
+}
+div + div {
+ background: blue;
+}
+div + div + div {
+ background: fuchsia;
+}
+ol {
+ clear: left;
+}
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ document.getElementsByTagName('div')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text','dummy text');
+ };
+};
+ </script>
+ </head>
+ <body>
+ <div draggable="true"></div>
+ <div></div>
+ <div></div>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <ol>
+ <li>Drag the orange square over the blue square.</li>
+ <li>Without releasing the drag, click the right mouse button.</li>
+ <li>If the platform's normal behaviour is to cancel a drag (eg. Windows and Unix+KDE), then the drag should be cancelled;<ul>
+ <li>The drag placeholder should disappear, and the cursor should return to the normal mouse cursor.</li>
+ <li>Move the mouse over the pink square and release the drag. The mouse cursor should remain the normal mouse cursor.</li>
+ </ul></li>
+ <li>If the platform's normal behaviour is not to cancel a drag (eg. Mac and Unix+Gnome), then the drag should not be cancelled;<ul>
+ <li>The drag placeholder should not disappear, and the cursor should be the no-drop cursor.</li>
+ <li>Move the mouse over the pink square and release the drag. The drag placeholder should disappear, and the cursor should return to the normal mouse cursor.</li>
+ </ul></li>
+ <li>Fail in either case if an inappropriate right click function begins (eg. context menu opens).</li>
+ </ol>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/close-drag-001.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/close-drag-001.html
new file mode 100644
index 00000000000..ed275943c45
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/close-drag-001.html
@@ -0,0 +1,24 @@
+<!doctype html>
+<title>drag &amp; drop - closing a popup while a drag is in operation</title>
+<style type="text/css">
+p.gone, ul { display: none; }
+p.gone + ul { display: block; }
+</style>
+<script type="text/javascript">
+window.onload = function() {
+ if( location.href.match(/#popup$/) ) { document.getElementsByTagName('p')[0].className = 'gone'; }
+ document.getElementsByTagName('ul')[0].ondragstart = function(e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('Text', 'dummy text');
+ setTimeout(function () { window.close(); },100);
+ };
+};
+</script>
+<p><a href="javascript:alert('Click the link normally');" onclick="window.open('close-drag-001.html#popup','_blank');return false;">Open this page in a popup</a>.</p>
+<ul draggable='true'>
+ <li>Drag this text downwards, and do not release the drag.</li>
+ <li>The browser may optionally cancel the drag. The browser may optionally close the popup. Fail if the drag placeholder gets stuck. Fail if the browser crashes. Fail if anything horrible happens. Fail if your pet kitten gets sick.</li>
+ <li>Release the drag.</li>
+ <li>Fail if the drag placeholder gets stuck. Fail if the browser crashes.</li>
+</ul>
+<noscript><p>Enable JavaScript and reload</p></noscript> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/close-drag-002.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/close-drag-002.html
new file mode 100644
index 00000000000..3ca09e8b54f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/close-drag-002.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<title>drag &amp; drop - closing the only window while a drag is in operation</title>
+<style type="text/css">
+p.gone, ul { display: none; }
+p.gone + ul { display: block; }
+</style>
+<script type="text/javascript">
+window.onload = function() {
+ if( location.href.match(/#popup$/) ) { document.getElementsByTagName('p')[0].className = 'gone'; }
+ document.getElementsByTagName('ul')[0].ondragstart = function(e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('Text', 'dummy text');
+ setTimeout(function () { window.close(); },100);
+ };
+};
+</script>
+<p><a href="javascript:alert('Click the link normally');" onclick="window.open('close-drag-002.html#popup','_blank');return false;">Open this page in a popup</a>.</p>
+<ul draggable='true'>
+ <li>Close all pages/browser windows except the popup.</li>
+ <li>Drag this text downwards, and do not release the drag.</li>
+ <li>The browser may optionally cancel the drag. The browser may optionally close the popup/window. Fail if the drag placeholder gets stuck. Fail if the browser crashes. Fail if anything horrible happens. Fail if zombie Michael Jackson resurects.</li>
+ <li>Release the drag.</li>
+ <li>Fail if the drag placeholder gets stuck. Fail if the browser crashes.</li>
+</ul>
+<noscript><p>Enable JavaScript and reload</p></noscript> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/close-drag-003.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/close-drag-003.html
new file mode 100644
index 00000000000..6d67ac1feb1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/close-drag-003.html
@@ -0,0 +1,28 @@
+<!doctype html>
+<title>drag &amp; drop - closing a popup while a drag is in operation out of the window</title>
+<style type="text/css">
+p.gone, ul { display: none; }
+p.gone + ul { display: block; }
+</style>
+<script type="text/javascript">
+window.onload = function() {
+ if( location.href.match(/#popup$/) ) { document.getElementsByTagName('p')[0].className = 'gone'; }
+ document.getElementsByTagName('ul')[0].ondragstart = function(e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('Text', 'dummy text');
+ setTimeout(function () { window.close(); },2000);
+ };
+};
+</script>
+<p><a href="javascript:alert('Click the link normally');" onclick="window.open('close-drag-003.html#popup','_blank');return false;">Open this page in a popup</a>.</p>
+<ul draggable='true'>
+ <li>Close all pages/browser windows except the popup.</li>
+ <li>Ensure that the browser window is not maximised.</li>
+ <li>Quickly drag this text out of the browser window (not over the taskbar), and do not release the drag.</li>
+ <li>The browser may optionally cancel the drag. The browser may optionally close the popup/window. Fail if the drag placeholder gets stuck. Fail if the browser crashes. Fail if anything horrible happens. Fail if your grandmother does not invite you over for Christmas.</li>
+ <li>After 2 seconds, fail if the address field shows that the page has closed, but it is still visibly rendered.</li>
+ <li>Continue dragging back into the browser window (if it is still open).</li>
+ <li>Release the drag.</li>
+ <li>Fail if the drag placeholder gets stuck. Fail if the browser crashes or hangs.</li>
+</ul>
+<noscript><p>Enable JavaScript and reload</p></noscript> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/close-drag-004.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/close-drag-004.html
new file mode 100644
index 00000000000..49337e2b853
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/close-drag-004.html
@@ -0,0 +1,22 @@
+<!doctype html>
+<title>drag &amp; drop - manually closing a tab while a drag is in operation</title>
+<style type="text/css">
+p.gone, ul { display: none; }
+p.gone + ul { display: block; }
+</style>
+<script type="text/javascript">
+window.onload = function() {
+ if( location.href.match(/#popup$/) ) { document.getElementsByTagName('p')[0].className = 'gone'; }
+ document.getElementsByTagName('ul')[0].ondragstart = function(e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('Text', 'dummy text');
+ };
+};
+</script>
+<p><a href="#popup" target="_blank">Open this page in a new tab</a>.</p>
+<ul draggable='true'>
+ <li>Drag this text downwards, and do not release the drag.</li>
+ <li>Use a keyboard shortcut (eg. Ctrl+W on Windows) to close the tab.</li>
+ <li>The browser may optionally cancel the drag. The browser may optionally close the tab. Fail if the drag placeholder gets stuck. Fail if the browser crashes.</li>
+</ul>
+<noscript><p>Enable JavaScript and reload</p></noscript> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/close-drag-005.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/close-drag-005.html
new file mode 100644
index 00000000000..3f6b479af07
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/close-drag-005.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<title>drag &amp; drop - manually closing a window while a drag is in operation</title>
+<script type="text/javascript">
+window.onload = function() {
+ document.getElementsByTagName('ul')[0].ondragstart = function(e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('Text', 'dummy text');
+ };
+};
+</script>
+<ul draggable='true'>
+ <li>Drag this text downwards, and do not release the drag.</li>
+ <li>Use a keyboard shortcut (eg. Alt+F4 on Windows) to close the window.</li>
+ <li>The browser may optionally cancel the drag. The browser may optionally close the window. Fail if the drag placeholder gets stuck. Fail if the browser crashes.</li>
+</ul>
+<noscript><p>Enable JavaScript and reload</p></noscript> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/close-drag-006.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/close-drag-006.html
new file mode 100644
index 00000000000..4e00a847242
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/close-drag-006.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<title>drag &amp; drop - dropping on window decoration after source tab is closed</title>
+<style type="text/css">
+p.gone, ul { display: none; }
+p.gone + ul { display: block; }
+</style>
+<script type="text/javascript">
+window.onload = function() {
+ if( location.href.match(/#popup$/) ) { document.getElementsByTagName('p')[0].className = 'gone'; }
+ document.getElementsByTagName('ul')[0].ondragstart = function(e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('Text', 'dummy text');
+ setTimeout(function () { window.close(); },2000);
+ };
+};
+</script>
+<p><a href="javascript:alert('Click the link normally');" onclick="window.open('close-drag-006.html#popup','_blank');return false;">Open this page in a popup</a>.</p>
+<ul draggable='true'>
+ <li>Ensure the browser window is not maximised.</li>
+ <li>Quickly drag this text upwards out of the browser window, and do not release the drag.</li>
+ <li>This tab should close after a couple of seconds.</li>
+ <li>Dragging downwards over the browser window's title bar, then release the drag.</li>
+ <li>Fail if the drag placeholder gets stuck. Fail if the browser crashes.</li>
+</ul>
+<noscript><p>Enable JavaScript and reload</p></noscript> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/cursors/001.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/cursors/001.html
new file mode 100644
index 00000000000..953927f917d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/cursors/001.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - no special cursor for draggable item</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ position: absolute;
+ top: 8px;
+ left: 8px;
+ }
+ body > div + div {
+ background-color: navy;
+ left: 250px;
+ }
+ p:first-of-type {
+ margin-top: 220px;
+ }
+</style>
+
+<div draggable='true'></div><div></div>
+
+<!-- In theory a "move" cursor would be better, but browsers have decided to allow the author to choose that
+- this test checks for browser compatibility. -->
+<p>Move your mouse over the orange box and blue box. It should show the same default mouse cursor in both cases.</p>
+<p>This test only applies to platforms with a mouse cursor that can change to indicate drop status.</p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/cursors/002.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/cursors/002.html
new file mode 100644
index 00000000000..9cca00077f5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/cursors/002.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - CSS cursor must be settable on draggable item</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ position: absolute;
+ top: 8px;
+ left: 8px;
+ cursor: pointer;
+ }
+ body > div + div {
+ background-color: navy;
+ left: 250px;
+ }
+ p:first-of-type {
+ margin-top: 220px;
+ }
+</style>
+
+<div draggable='true'></div><div></div>
+
+<p>Move your mouse over the orange box and blue box. It should show the same &quot;pointer&quot; mouse cursor in both cases (the one normally used for links).</p>
+<p>This test only applies to platforms with a mouse cursor that can change to indicate drop status.</p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/cursors/003.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/cursors/003.html
new file mode 100644
index 00000000000..a1a5c491871
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/cursors/003.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - should show no-drop for non-dropzones</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ position: absolute;
+ top: 8px;
+ left: 8px;
+ }
+ body > div + div {
+ background-color: navy;
+ left: 250px;
+ }
+ p:first-of-type {
+ margin-top: 220px;
+ }
+</style>
+
+<script type="text/javascript">
+
+window.onload = function() {
+ var orange = document.getElementsByTagName('div')[0];
+ orange.ondragstart = function(e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('Text', 'dummy text');
+ };
+};
+
+</script>
+
+<div draggable='true'></div><div></div>
+
+<p>Use your mouse to drag the orange box over the blue box. While dragging, the mouse cursor should appear as a &quot;no-drop&quot; cursor.<br>
+Release the drag. The cursor should revert to the default mouse cursor.</p>
+<p>This test only applies to platforms with a mouse cursor that can change to indicate drop status.</p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/cursors/004.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/cursors/004.html
new file mode 100644
index 00000000000..640ad37caa4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/cursors/004.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - no-drop should override CSS cursor when dragging</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ position: absolute;
+ top: 8px;
+ left: 8px;
+ }
+ body > div:first-child {
+ cursor: pointer;
+ }
+ body > div + div {
+ background-color: navy;
+ left: 250px;
+ }
+ p:first-of-type {
+ margin-top: 220px;
+ }
+</style>
+
+<script type="text/javascript">
+
+window.onload = function() {
+ var orange = document.getElementsByTagName('div')[0];
+ orange.ondragstart = function(e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('Text', 'dummy text');
+ };
+};
+
+</script>
+
+<div draggable='true'></div><div></div>
+
+<p>Move your mouse over the orange box. It should show the &quot;pointer&quot; cursor (normally used for links).<br>
+Use your mouse to drag the orange box over the blue box. While dragging, the mouse cursor should appear as a &quot;no-drop&quot; cursor.<br>
+Release the drag. The cursor should revert to the default mouse cursor.</p>
+<p>This test only applies to platforms with a mouse cursor that can change to indicate drop status.</p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/cursors/005.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/cursors/005.html
new file mode 100644
index 00000000000..9aa78f25a33
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/cursors/005.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - should show no-drop for refused-dropzones</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ position: absolute;
+ top: 8px;
+ left: 8px;
+ }
+ body > div + div {
+ background-color: navy;
+ left: 250px;
+ }
+ p:first-of-type {
+ margin-top: 220px;
+ }
+</style>
+
+<script type="text/javascript">
+
+window.onload = function() {
+ var orange = document.getElementsByTagName('div')[0], blue = document.getElementsByTagName('div')[1];
+ orange.ondragstart = function(e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('Text', 'dummy text');
+ };
+ blue.ondragenter = blue.ondragover = function(e) {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'none';
+ };
+ blue.ondrop = function(e) {
+ e.preventDefault();
+ };
+};
+
+</script>
+
+<div draggable='true'></div><div></div>
+
+<p>Use your mouse to drag the orange box over the blue box. While dragging, the mouse cursor should appear as a &quot;no-drop&quot; cursor.<br>
+Release the drag. The cursor should revert to the default mouse cursor.</p>
+<p>This test only applies to platforms with a mouse cursor that can change to indicate drop status.</p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/cursors/006.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/cursors/006.html
new file mode 100644
index 00000000000..61eb8ec30fb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/cursors/006.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - should show drop-allowed for dropzones</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ position: absolute;
+ top: 8px;
+ left: 8px;
+ }
+ body > div + div {
+ background-color: navy;
+ left: 250px;
+ }
+ p:first-of-type {
+ margin-top: 220px;
+ }
+</style>
+
+<script type="text/javascript">
+
+window.onload = function() {
+ var orange = document.getElementsByTagName('div')[0], blue = document.getElementsByTagName('div')[1];
+ orange.ondragstart = function(e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('Text', 'dummy text');
+ };
+ blue.ondragenter = blue.ondragover = function(e) {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'copy';
+ };
+ blue.ondrop = function(e) {
+ e.preventDefault();
+ };
+};
+
+</script>
+
+<div draggable='true'></div><div></div>
+
+<p>Use your mouse to drag the orange box over the blue box. While dragging over the blue box, the mouse cursor should appear as a &quot;drop-allowed&quot; or &quot;drop-clopy-allowed&quot; cursor.<br>
+Release the drag. The cursor should revert to the default mouse cursor.</p>
+<p>This test only applies to platforms with a mouse cursor that can change to indicate drop status.</p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/cursors/007.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/cursors/007.html
new file mode 100644
index 00000000000..c2abfaa310b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/cursors/007.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - should show drop-allowed for move dropzones</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ position: absolute;
+ top: 8px;
+ left: 8px;
+ }
+ body > div + div {
+ background-color: navy;
+ left: 250px;
+ }
+ p:first-of-type {
+ margin-top: 220px;
+ }
+</style>
+
+<script type="text/javascript">
+
+window.onload = function() {
+ var orange = document.getElementsByTagName('div')[0], blue = document.getElementsByTagName('div')[1];
+ orange.ondragstart = function(e) {
+ e.dataTransfer.effectAllowed = 'move';
+ e.dataTransfer.setData('Text', 'dummy text');
+ };
+ blue.ondragenter = blue.ondragover = function(e) {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'move';
+ };
+ blue.ondrop = function(e) {
+ e.preventDefault();
+ };
+};
+
+</script>
+
+<div draggable='true'></div><div></div>
+
+<p>Use your mouse to drag the orange box over the blue box. While dragging over the blue box, the mouse cursor should appear as a &quot;drop-allowed&quot; or &quot;drop-move-allowed&quot; cursor.<br>
+Release the drag. The cursor should revert to the default mouse cursor.</p>
+<p>This test only applies to platforms with a mouse cursor that can change to indicate drop status.</p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/cursors/008.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/cursors/008.html
new file mode 100644
index 00000000000..53b84346774
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/cursors/008.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - cursor should show drop-allowed for file drops</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ position: absolute;
+ top: 8px;
+ left: 8px;
+ }
+ body > div + div {
+ background-color: navy;
+ left: 250px;
+ }
+ body > div + div + div {
+ background-color: fuchsia;
+ left: 500px;
+ }
+ p:first-of-type {
+ margin-top: 220px;
+ }
+</style>
+
+<script type="text/javascript">
+
+window.onload = function() {
+ var blue = document.getElementsByTagName('div')[1], fuchsia = document.getElementsByTagName('div')[2];
+ blue.ondragenter = blue.ondragover = function(e) {
+ //this test assumes the browser will default to opening the file if the page does not want it
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'none';
+ };
+ fuchsia.ondragenter = fuchsia.ondragover = function(e) {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'copy';
+ };
+ fuchsia.ondrop = function(e) {
+ e.preventDefault();
+ };
+};
+
+</script>
+
+<div></div><div></div><div></div>
+
+<p>Use your mouse to drag a *.html file from your computer's desktop over the three coloured squares on this page. The mouse cursor should appear as a &quot;drop-allowed&quot; cursor over all three squares.<br>
+Release the drag over the pink square. If a prompt appears, accept it. The cursor should revert to the default mouse cursor.</p>
+<p>This test only applies to platforms with a mouse cursor that can change to indicate drop status.</p>
+<p>This test assumes the browser will open dropped files natively if they are not handled by a script.</p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/cursors/009.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/cursors/009.html
new file mode 100644
index 00000000000..4f09539322c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/cursors/009.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - should show drop-allowed for link dropzones</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ position: absolute;
+ top: 8px;
+ left: 8px;
+ }
+ body > div + div {
+ background-color: navy;
+ left: 250px;
+ }
+ p:first-of-type {
+ margin-top: 220px;
+ }
+</style>
+
+<script type="text/javascript">
+
+window.onload = function() {
+ var orange = document.getElementsByTagName('div')[0], blue = document.getElementsByTagName('div')[1];
+ orange.ondragstart = function(e) {
+ e.dataTransfer.effectAllowed = 'link';
+ e.dataTransfer.setData('Text', 'dummy text');
+ };
+ blue.ondragenter = blue.ondragover = function(e) {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'link';
+ };
+ blue.ondrop = function(e) {
+ e.preventDefault();
+ };
+};
+
+</script>
+
+<div draggable='true'></div><div></div>
+
+<p>Use your mouse to drag the orange box over the blue box. While dragging over the blue box, the mouse cursor should appear as a &quot;drop-allowed&quot; or &quot;drop-link-allowed&quot; cursor.<br>
+Release the drag. The cursor should revert to the default mouse cursor.</p>
+<p>This test only applies to platforms with a mouse cursor that can change to indicate drop status.</p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/cursors/010.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/cursors/010.html
new file mode 100644
index 00000000000..bcc408e8039
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/cursors/010.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - drag ending over draggable element</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background: orange url(../../resources/100x100-navy.png) repeat-y scroll right top;
+ }
+</style>
+
+<script type="text/javascript">
+
+window.onload = function() {
+ var orange = document.getElementsByTagName('div')[0];
+ orange.ondragstart = function(e) {
+ e.dataTransfer.effectAllowed = 'link';
+ e.dataTransfer.setData('Text', 'dummy text');
+ };
+};
+
+</script>
+
+<div draggable='true'></div>
+
+<p>Use your mouse to drag the orange box over the blue box, and release. While dragging over the blue box, the mouse cursor should appear as a &quot;no-drop&quot; cursor.<br>
+Release the drag. The cursor should revert to the default mouse cursor.</p>
+<p>This test only applies to platforms with a mouse cursor that can change to indicate drop status.</p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/cursors/011.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/cursors/011.html
new file mode 100644
index 00000000000..15f78849f91
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/cursors/011.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - cursors after dragging outside window</title>
+<style>
+ body > div {
+ height: 100px;
+ width: 100px;
+ display: inline-block;
+ background: orange;
+ }
+ body > div + div {
+ background: blue;
+ color: black;
+ }
+</style>
+
+<script type="text/javascript">
+
+window.onload = function() {
+ var orange = document.getElementsByTagName('div')[0];
+ orange.ondragstart = function(e) {
+ e.dataTransfer.effectAllowed = 'all';
+ e.dataTransfer.setData('Text', 'dummy text');
+ };
+ var copydiv = document.getElementsByTagName('div')[1];
+ copydiv.ondragenter = copydiv.ondragover = function(e) {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'copy';
+ };
+ var movediv = document.getElementsByTagName('div')[2];
+ movediv.ondragenter = movediv.ondragover = function(e) {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'move';
+ };
+ var linkdiv = document.getElementsByTagName('div')[3];
+ linkdiv.ondragenter = linkdiv.ondragover = function(e) {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'link';
+ };
+ var nodrop = document.getElementsByTagName('div')[4];
+ nodrop.ondragenter = nodrop.ondragover = function(e) {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'none';
+ };
+};
+
+</script>
+
+<div draggable='true'>&nbsp;</div>
+<div>Copy</div>
+<div>Move</div>
+<div>Link</div>
+<div>No-drop</div>
+
+<p>Use your mouse to drag the orange box out of the browser window (not over the system taskbar), then back into the browser window, and over each of the blue squares in turn.
+While dragging over the squares, the mouse cursor should be the one given by the text in the relevant square.</p>
+<p>This test only applies to platforms with a mouse cursor that can change to indicate drop status.</p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/drag-keypress.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/drag-keypress.html
new file mode 100644
index 00000000000..adb543ad424
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/drag-keypress.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - pressing tab while dragging</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ }
+ body {
+ height: 5000px;
+ }
+ p {
+ margin-top: 1000px;
+ }
+</style>
+
+<script>
+window.onload = function() {
+ window.scrollBy(0,1000);
+ document.getElementsByTagName('div')[0].ondragstart = function(e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text', 'dummy text');
+ };
+};
+</script>
+<noscript>Enable JavaScript and reload</noscript>
+<p>Drag the orange square. While still dragging, press the Tab key on your keyboard. Fail if the page scrolls.</p>
+<div draggable="true"></div> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/drag-link.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/drag-link.html
new file mode 100644
index 00000000000..c308d504f25
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/drag-link.html
@@ -0,0 +1,12 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Dragging vs selecting links</title>
+ </head>
+ <body>
+
+ <p><a href="">Test link, test link, test link, test link, test link, test link, test link, test link, test link</a></p>
+ <p>Drag the test link above. When dragging vertically, it should drag the link. When dragging horizontally, it should select the text within the link.</p>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/drag-to-title.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/drag-to-title.html
new file mode 100644
index 00000000000..b7fe31c131d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/drag-to-title.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<title>Dropping onto the title bar and UI</title>
+<script type="text/javascript">
+window.onload = function () {
+ document.getElementsByTagName('ul')[0].ondragstart = function () {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text','c');
+ };
+};
+</script>
+<ul draggable="true">
+ <li>Drag this text upwards to the browser window's title bar.</li>
+ <li>Release the drag. Fail if the drag placeholder does not disappear.</li>
+ <li>Start dragging again over a blank part of the page (below the text). Fail if the placeholder starts following the mouse again.</li>
+ <li>Release the drag over the browser's UI (e.g. the address bar). Fail if the browser crashes.</li>
+</ul> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/file-drop-position.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/file-drop-position.html
new file mode 100644
index 00000000000..62115c7cf36
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/file-drop-position.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - mouse coordinates during drop</title>
+<style>
+ body > div {
+ height: 5px;
+ width: 5px;
+ background-color: orange;
+ }
+</style>
+
+<script>
+window.onload = function() {
+ var orange = document.getElementsByTagName('div')[0];
+ orange.ondragover = orange.ondragenter = orange.ondrop = function(e) {
+ e.preventDefault();
+ };
+};
+</script>
+
+<div></div>
+
+<p>Save <a href="../resources/fail.png">this image</a> to your desktop. Minimise your browser. Use your pointing device to drag the saved file from your desktop <strong>via your browser's button on your operating system's taskbar</strong> (so that it maximises your browser), onto the small orange box above this text, and release it. If a confirmation dialog appears, accept it. Fail if the browser simply displays the image.</p>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/file-os-to-os.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/file-os-to-os.html
new file mode 100644
index 00000000000..b3db18077b5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/file-os-to-os.html
@@ -0,0 +1,13 @@
+<!doctype html>
+<html>
+ <head>
+ <title>drag and drop - dragging items from the OS to the OS, via the browser window</title>
+ </head>
+ <body>
+
+ <p>This test is only relevant on platforms where it is possible to switch applications in mid-drag (eg. alt+tab, dragging over taskbar buttons, dragging between restored windows).</p>
+ <p>This testcase requires an external application that accepts dragging and dropping of files - eg. your system's file manager. Ensure that two application windows are open for the external application, showing different folders.</p>
+ <p>Select a file in the first external application window. Drag the file over the browser window, then over the other external application window and release it. Pass if the file is copied/moved to the second window, as expected by the system.</p>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/file-to-system.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/file-to-system.html
new file mode 100644
index 00000000000..af9840e8c44
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/file-to-system.html
@@ -0,0 +1,50 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Dragging a file to the system</title>
+ <style type="text/css">
+span { display: inline-block; height: 100px; width: 100px; background: orange; }
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ var drag = document.getElementsByTagName('span')[0];
+ drag.ondragstart = function (e) {
+ e.dataTransfer.setData('text','PASS');
+ e.dataTransfer.effectAllowed = 'copy';
+ var filein = document.getElementsByTagName('input')[0];
+ if( !filein.files ) {
+ document.getElementsByTagName('p')[0].innerHTML = 'FAIL - file API is not supported.';
+ return;
+ }
+ if( !filein.files[0] ) {
+ document.getElementsByTagName('p')[0].innerHTML = 'FAIL - no file was found in the file input.';
+ return;
+ }
+ var thefile = filein.files[0];
+ try {
+ e.dataTransfer.items.add(thefile);
+ } catch(err) {
+ document.getElementsByTagName('p')[0].innerHTML = 'FAIL - error when adding file';
+ e.preventDefault();
+ return;
+ }
+ if( e.dataTransfer.files.length != 1 ) {
+ document.getElementsByTagName('p')[0].innerHTML = 'FAIL - file was not attached to data store';
+ e.preventDefault();
+ }
+ };
+};
+ </script>
+ </head>
+ <body>
+ <div>This test only applies to platforms where dropping a file onto a folder in the system's file manager copies/moves the file to that folder.</div>
+ <ol>
+ <li>Open an empty folder in your system's file manager.</li>
+ <li>Select a non-empty file on your computer using the following input: <input type="file"></li>
+ <li>Drag the orange square onto the folder in your system's file manager, and release it:<br><span draggable="true"></span></li>
+ <li>Pass if the file is copied to the folder.</li>
+ </ol>
+ <p></p>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/html-to-os-HELPER-FILE.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/html-to-os-HELPER-FILE.html
new file mode 100644
index 00000000000..608026f208b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/html-to-os-HELPER-FILE.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<html>
+ <head>
+ <title>drag and drop - dragging HTML onto the OS - helper file</title>
+ </head>
+ <body>
+
+ <p>This is the helper file. Drop the paragraph here --&gt;</p>
+ <script type="text/javascript">
+document.body.contentEditable = true;
+ </script>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/html-to-os.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/html-to-os.html
new file mode 100644
index 00000000000..6283c24cef8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/html-to-os.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<html>
+ <head>
+ <title>drag and drop - dragging HTML onto the OS</title>
+ </head>
+ <body>
+
+ <p>This test is only relevant on platforms where it is possible to switch applications in mid-drag (eg. alt+tab, dragging over taskbar buttons, dragging between restored windows).</p>
+ <p>This testcase requires an external application that accepts dropping of HTML from other applications - eg. Google Chrome and Internet Explorer (not Firefox). Load <a href="html-to-os-HELPER-FILE.html">the helper file</a> in the external application.</p>
+ <p draggable="true">Drag this paragraph to the other application and release it. De-select the text in that application if it is selected. Pass if &quot;Pass if this text is on a green background&quot; appears in the other application, and if it has a green background, and if the drag placeholder disappears when the drag is released.</p>
+ <script type="text/javascript">
+document.getElementsByTagName('p')[2].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text/html', '<span style="background:lime;color:black;">Pass if this text is on a green background</span>');
+};
+ </script>
+ <p>Disable JavaScript in this browser and repeat the test. Pass if the entire dragged paragraph appears in the other application. Vendors may optionally choose to ignore this requirement.</p>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/html-unicode-to-os.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/html-unicode-to-os.html
new file mode 100644
index 00000000000..b915865d458
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/html-unicode-to-os.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<html>
+ <head>
+ <title>drag and drop - dragging HTML onto the OS</title>
+ </head>
+ <body>
+
+ <p>This test is only relevant on platforms where it is possible to switch applications in mid-drag (eg. alt+tab, dragging over taskbar buttons, dragging between restored windows).</p>
+ <p>This testcase requires an external application that accepts dropping of unicode HTML from other applications - eg. Google Chrome (not Firefox or Internet Explorer). Load <a href="html-to-os-HELPER-FILE.html">the helper file</a> in the external application.</p>
+ <p draggable="true">Drag this paragraph to the other application and release it. De-select the text in that application if it is selected. Pass if &quot;Pass if this text is on a green background 中文אידישрусский&quot; appears in the other application, and if it has a green background, and if the drag placeholder disappears when the drag is released.</p>
+ <script type="text/javascript">
+document.getElementsByTagName('p')[2].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text/html', '<span style="background:lime;color:black;">Pass if this text is on a green background 中文אידישрусский</span>');
+};
+ </script>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/inputs-no-js.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/inputs-no-js.html
new file mode 100644
index 00000000000..876f0b58aaa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/inputs-no-js.html
@@ -0,0 +1,15 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Dropping selections with JS disabled</title>
+ </head>
+ <body>
+
+ <ol>
+ <li>Disable JavaScript</li>
+ <li>Select some text in <input type="text" value="this input"> and drag it into the following input: <input type="text" value=""> - the text you dragged should appear in there.</li>
+ <li>Select some text in this sentence and drag it into the following input: <input type="text" value=""> - the text you dragged should appear in there.</li>
+ </ol>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/001.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/001.html
new file mode 100644
index 00000000000..0a527b4992a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/001.html
@@ -0,0 +1,47 @@
+<!doctype html>
+<title>Interrupted drag with second drag attempt</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ display: inline-block;
+ }
+ body > div + div {
+ background-color: navy;
+ }
+ body > div + div + div {
+ background-color: fuchsia;
+ }
+</style>
+<script type="text/javascript">
+window.onload = function () {
+ var orange = document.getElementsByTagName('div')[0], blue = document.getElementsByTagName('div')[1], fuchsia = document.getElementsByTagName('div')[2];
+ orange.ondragstart = function (e) {
+ e.dataTransfer.setData('text','PASS');
+ e.dataTransfer.effectAllowed = 'all';
+ };
+ blue.ondragenter = function (e) {
+ alert('JS alert');
+ };
+ fuchsia.ondragenter = fuchsia.ondragover = function (e) {
+ e.preventDefault();
+ };
+ fuchsia.ondrop = function (e) {
+ document.getElementsByTagName('ol')[0].textContent = e.dataTransfer.getData('text');
+ e.preventDefault();
+ };
+};
+</script>
+<div draggable="true"></div>
+<div></div>
+<div></div>
+
+<ol>
+ <li>Drag the orange square over the blue square.</li>
+ <li>An alert may appear. Do not dismiss it. If an alert does not appear, PASS, and ignore any further steps.</li>
+ <li>Drag a file that your browser cannot open natively from your computer onto a blank part of the page. If a download dialog appears at any point after this, cancel it, and return to this page.</li>
+ <li>Dismiss the alert without using the left mouse button (eg. use keyboard, or mouse gestures such as gesture-down,gesture-right).</li>
+ <li>Do a short drag and drop within the pink square. If nothing happens, PASS, and ignore any further steps.</li>
+ <li>The word &quot;PASS&quot; should appear in place of this text.</li>
+</ol> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/002.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/002.html
new file mode 100644
index 00000000000..4b1806ac023
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/002.html
@@ -0,0 +1,49 @@
+<!doctype html>
+<title>Interrupted drag with second drag attempt and tab change</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ display: inline-block;
+ }
+ body > div + div {
+ background-color: navy;
+ }
+ body > div + div + div {
+ background-color: fuchsia;
+ }
+</style>
+<script type="text/javascript">
+window.onload = function () {
+ var orange = document.getElementsByTagName('div')[0], blue = document.getElementsByTagName('div')[1], fuchsia = document.getElementsByTagName('div')[2];
+ orange.ondragstart = function (e) {
+ e.dataTransfer.setData('text','PASS');
+ e.dataTransfer.effectAllowed = 'all';
+ };
+ blue.ondragenter = function (e) {
+ alert('JS alert');
+ };
+ fuchsia.ondragenter = fuchsia.ondragover = function (e) {
+ e.preventDefault();
+ };
+ fuchsia.ondrop = function (e) {
+ document.getElementsByTagName('ol')[0].textContent = e.dataTransfer.getData('text');
+ e.preventDefault();
+ };
+};
+</script>
+<div draggable="true"></div>
+<div></div>
+<div></div>
+
+<ol>
+ <li>Make sure at least one other tab is open.</li>
+ <li>Drag the orange square over the blue square.</li>
+ <li>An alert may appear. Do not dismiss it. If an alert does not appear, PASS, and ignore any further steps.</li>
+ <li>Click the other tab to focus it (or focus it in whatever way works). If you cannot change tabs, PASS, and ignore any further steps.</li>
+ <li>Drag a file that your browser cannot open natively from your computer and drop onto that page, then click the tab for this page to return here. If a download dialog appears at any point after this, cancel it, and return to this page.</li>
+ <li>Dismiss the alert without using the left mouse button (eg. use keyboard, or mouse gestures such as gesture-down,gesture-right).</li>
+ <li>Do a short drag and drop within the pink square. If nothing happens, PASS, and ignore any further steps.</li>
+ <li>The word &quot;PASS&quot; should appear in place of this text.</li>
+</ol> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/003.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/003.html
new file mode 100644
index 00000000000..85f20badf9c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/003.html
@@ -0,0 +1,59 @@
+<!doctype html>
+<title>Interrupted drag with second in-document drag attempt</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ display: inline-block;
+ }
+ body > div + div {
+ background-color: navy;
+ }
+ body > div + div + div {
+ background-color: yellow;
+ }
+ body > div + div + div + div {
+ background-color: fuchsia;
+ }
+</style>
+<script type="text/javascript">
+window.onload = function () {
+ var orange = document.getElementsByTagName('div')[0], blue = document.getElementsByTagName('div')[1], yellow = document.getElementsByTagName('div')[2], fuchsia = document.getElementsByTagName('div')[3];
+ orange.ondragstart = function (e) {
+ e.dataTransfer.setData('text','PASS');
+ e.dataTransfer.effectAllowed = 'all';
+ };
+ yellow.ondragstart = function (e) {
+ e.dataTransfer.setData('text','FAIL');
+ e.dataTransfer.effectAllowed = 'all';
+ };
+ blue.ondragenter = function (e) {
+ alert('JS alert');
+ };
+ fuchsia.ondragenter = fuchsia.ondragover = function (e) {
+ e.preventDefault();
+ };
+ fuchsia.ondrop = function (e) {
+ document.getElementsByTagName('ol')[0].textContent = e.dataTransfer.getData('text');
+ e.preventDefault();
+ };
+};
+</script>
+<div draggable="true"></div>
+<div></div>
+<div draggable="true"></div>
+<div></div>
+
+<ol>
+ <li>Open this page in two separate tabs, and start on tab #1.</li>
+ <li>Drag the orange square over the blue square.</li>
+ <li>An alert may appear. Do not dismiss it. If an alert does not appear, PASS, and ignore any further steps.</li>
+ <li>Click the other tab to focus it (or focus it in whatever way works). If you cannot change tabs, PASS, and ignore any further steps.</li>
+ <li>On tab #2, drag the yellow square over the blue square. If you cannot drag the yellow square, PASS, and ignore any further steps.</li>
+ <li>An alert may appear. Do not dismiss it.</li>
+ <li>Return to tab #1.</li>
+ <li>Dismiss the alert without using the left mouse button (eg. use keyboard, or mouse gestures such as gesture-down,gesture-right).</li>
+ <li>Do a short drag and drop within the pink square. If nothing happens, PASS, and ignore any further steps.</li>
+ <li>The word &quot;PASS&quot; should appear in place of this text.</li>
+</ol> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/004.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/004.html
new file mode 100644
index 00000000000..c66c4681a52
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/004.html
@@ -0,0 +1,31 @@
+<!doctype html>
+<title>File drag during prompt for upload</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ display: inline-block;
+ }
+</style>
+<script type="text/javascript">
+window.onload = function () {
+ var orange = document.getElementsByTagName('div')[0];
+ orange.ondragenter = orange.ondragover = function (e) {
+ e.preventDefault();
+ };
+ orange.ondrop = function (e) {
+ e.preventDefault();
+ document.getElementsByTagName('ol')[0].innerHTML = ( e.dataTransfer.files[0] && e.dataTransfer.files[0].name == 'pass.txt' ) ? 'PASS' : 'FAIL';
+ };
+};
+</script>
+<div draggable="true"></div>
+
+<ol>
+ <li>Save <a href="pass.txt">pass.txt</a> and <a href="fail.txt">fail.txt</a> onto your computer.</li>
+ <li>Drag pass.txt from your computer onto the orange square.</li>
+ <li>A prompt should appear. Do not dismiss it. If a prompt does not appear, ignore any further steps, and check the tests in ../../file/</li>
+ <li>Drag fail.txt from your computer onto a blank part of this page. Fail if this page is replaced.</li>
+ <li>Accept the prompt. Fail if nothing happens.</li>
+</ol> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/005.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/005.html
new file mode 100644
index 00000000000..efb5a5b794c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/005.html
@@ -0,0 +1,35 @@
+<!doctype html>
+<title>File drag and tab change during prompt for upload</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ display: inline-block;
+ }
+</style>
+<script type="text/javascript">
+window.onload = function () {
+ var orange = document.getElementsByTagName('div')[0];
+ orange.ondragenter = orange.ondragover = function (e) {
+ e.preventDefault();
+ };
+ orange.ondrop = function (e) {
+ e.preventDefault();
+ document.getElementsByTagName('ol')[0].innerHTML = ( e.dataTransfer.files[0] && e.dataTransfer.files[0].name );
+ };
+};
+</script>
+<div draggable="true"></div>
+
+<ol>
+ <li>Save <a href="file1.txt">file1.txt</a> and <a href="file2.txt">file2.txt</a> onto your computer.</li>
+ <li>Open this page in two separate tabs, and start on tab #1.</li>
+ <li>Drag file1.txt from your computer onto the orange square.</li>
+ <li>A prompt should appear. Do not dismiss it. If a prompt does not appear, ignore any further steps, and check the tests in ../../file/</li>
+ <li>Click the other tab to focus it (or focus it in whatever way works). If you cannot change tabs, PASS, and ignore any further steps.</li>
+ <li>Drag file2.txt from your computer onto the orange square. Fail if this text (but not the orange square) is replaced without any prompt.</li>
+ <li>If a prompt appears, do not dismiss it.</li>
+ <li>Return to tab #1.</li>
+ <li>Accept the prompt. Fail if it cannot be accepted. Pass if this text (but not the orange square) is replaced with the text: file1.txt</li>
+</ol> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/006.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/006.html
new file mode 100644
index 00000000000..83e6fa7f4cb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/006.html
@@ -0,0 +1,32 @@
+<!doctype html>
+<title>Alert during dragstart</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ display: inline-block;
+ }
+</style>
+<script type="text/javascript">
+window.onload = function () {
+ var orange = document.getElementsByTagName('div')[0], blue = document.getElementsByTagName('div')[1], hasfired = false;
+ orange.ondragstart = function (e) {
+ e.dataTransfer.setData('text','PASS');
+ e.dataTransfer.effectAllowed = 'all';
+ if( hasfired ) { return; }
+ hasfired = true;
+ alert('JS alert');
+ };
+};
+</script>
+<div draggable="true"></div>
+
+<ol>
+ <li>Drag the orange square downwards until the drag placeholder appears.</li>
+ <li>An alert may appear - release the mouse over the page, not the dialog. Dismiss it (you may need to use keyboard or mouse gestures such as gesture-down,gesture-right). If it does not appear, release the drag.</li>
+ <li>The mouse cursor may continue to show that a drag is in operation. If so, attempt to select some of this text with the mouse before continuing to the text step.</li>
+ <li>Fail if the mouse continues to show that a drag is in operation.</li>
+ <li>Try to select some text in this sentence. Fail if it is not possible.</li>
+ <li>Try to drag the orange square downwards again. Fail if that is not possible.</li>
+</ol> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/007.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/007.html
new file mode 100644
index 00000000000..1d79b85ef94
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/007.html
@@ -0,0 +1,34 @@
+<!doctype html>
+<title>Alert during drag</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ display: inline-block;
+ }
+</style>
+<script type="text/javascript">
+window.onload = function () {
+ var orange = document.getElementsByTagName('div')[0], blue = document.getElementsByTagName('div')[1], hasfired = false;
+ orange.ondragstart = function (e) {
+ e.dataTransfer.setData('text','PASS');
+ e.dataTransfer.effectAllowed = 'all';
+ };
+ orange.ondrag = function (e) {
+ if( hasfired ) { return; }
+ hasfired = true;
+ alert('JS alert');
+ };
+};
+</script>
+<div draggable="true"></div>
+
+<ol>
+ <li>Drag the orange square downwards until the drag placeholder appears.</li>
+ <li>An alert may appear - release the mouse over the page, not the dialog. Dismiss it (you may need to use keyboard or mouse gestures such as gesture-down,gesture-right). If it does not appear, release the drag.</li>
+ <li>The mouse cursor may continue to show that a drag is in operation. If so, attempt to select some of this text with the mouse before continuing to the text step.</li>
+ <li>Fail if the mouse continues to show that a drag is in operation.</li>
+ <li>Try to select some text in this sentence. Fail if it is not possible.</li>
+ <li>Try to drag the orange square downwards again. Fail if that is not possible.</li>
+</ol> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/008.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/008.html
new file mode 100644
index 00000000000..b2de74169ff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/008.html
@@ -0,0 +1,40 @@
+<!doctype html>
+<title>Alert during dragenter</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ display: inline-block;
+ }
+ body > div + div {
+ background-color: navy;
+ }
+</style>
+<script type="text/javascript">
+window.onload = function () {
+ var orange = document.getElementsByTagName('div')[0], blue = document.getElementsByTagName('div')[1];
+ orange.ondragstart = function (e) {
+ e.dataTransfer.setData('text','PASS');
+ e.dataTransfer.effectAllowed = 'all';
+ };
+ blue.ondragenter = function (e) {
+ e.preventDefault();
+ alert('JS alert');
+ };
+ blue.ondragover = function (e) {
+ e.preventDefault();
+ };
+};
+</script>
+<div draggable="true"></div>
+<div></div>
+
+<ol>
+ <li>Drag the orange square over the blue square.</li>
+ <li>An alert may appear - release the mouse over the page, not the dialog. Dismiss it (you may need to use keyboard or mouse gestures such as gesture-down,gesture-right). If it does not appear, release the drag.</li>
+ <li>The mouse cursor may continue to show that a drag is in operation. If so, attempt to select some of this text with the mouse before continuing to the text step.</li>
+ <li>Fail if the mouse continues to show that a drag is in operation.</li>
+ <li>Try to select some text in this sentence. Fail if it is not possible.</li>
+ <li>Try to drag the orange square downwards. Fail if it is not possible.</li>
+</ol> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/009.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/009.html
new file mode 100644
index 00000000000..ce1fec80865
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/009.html
@@ -0,0 +1,42 @@
+<!doctype html>
+<title>Alert during dragover</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ display: inline-block;
+ }
+ body > div + div {
+ background-color: navy;
+ }
+</style>
+<script type="text/javascript">
+window.onload = function () {
+ var orange = document.getElementsByTagName('div')[0], blue = document.getElementsByTagName('div')[1], hasfired = false;
+ orange.ondragstart = function (e) {
+ e.dataTransfer.setData('text','PASS');
+ e.dataTransfer.effectAllowed = 'all';
+ };
+ blue.ondragenter = function (e) {
+ e.preventDefault();
+ };
+ blue.ondragover = function (e) {
+ e.preventDefault();
+ if( hasfired ) { return; }
+ hasfired = true;
+ alert('JS alert');
+ };
+};
+</script>
+<div draggable="true"></div>
+<div></div>
+
+<ol>
+ <li>Drag the orange square over the blue square.</li>
+ <li>An alert may appear - release the mouse over the page, not the dialog. Dismiss it (you may need to use keyboard or mouse gestures such as gesture-down,gesture-right). If it does not appear, release the drag.</li>
+ <li>The mouse cursor may continue to show that a drag is in operation. If so, attempt to select some of this text with the mouse before continuing to the text step.</li>
+ <li>Fail if the mouse continues to show that a drag is in operation.</li>
+ <li>Try to select some text in this sentence. Fail if it is not possible.</li>
+ <li>Try to drag the orange square downwards. Fail if it is not possible.</li>
+</ol> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/010.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/010.html
new file mode 100644
index 00000000000..c5ec6648874
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/010.html
@@ -0,0 +1,39 @@
+<!doctype html>
+<title>Alert during dragleave</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ display: inline-block;
+ }
+ body > div + div {
+ background-color: navy;
+ }
+</style>
+<script type="text/javascript">
+window.onload = function () {
+ var orange = document.getElementsByTagName('div')[0], blue = document.getElementsByTagName('div')[1];
+ orange.ondragstart = function (e) {
+ e.dataTransfer.setData('text','PASS');
+ e.dataTransfer.effectAllowed = 'all';
+ };
+ blue.ondragenter = blue.ondragover = function (e) {
+ e.preventDefault();
+ };
+ blue.ondragleave = function (e) {
+ alert('JS alert');
+ };
+};
+</script>
+<div draggable="true"></div>
+<div></div>
+
+<ol>
+ <li>Drag the orange square over the blue square, then back over the orange square.</li>
+ <li>An alert may appear - release the mouse over the page, not the dialog. Dismiss it (you may need to use keyboard or mouse gestures such as gesture-down,gesture-right). If it does not appear, release the drag.</li>
+ <li>The mouse cursor may continue to show that a drag is in operation. If so, attempt to select some of this text with the mouse before continuing to the text step.</li>
+ <li>Fail if the mouse continues to show that a drag is in operation.</li>
+ <li>Try to select some text in this sentence. Fail if it is not possible.</li>
+ <li>Try to drag the orange square downwards. Fail if it is not possible.</li>
+</ol> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/011.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/011.html
new file mode 100644
index 00000000000..61b73ba8402
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/011.html
@@ -0,0 +1,40 @@
+<!doctype html>
+<title>Alert during drop</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ display: inline-block;
+ }
+ body > div + div {
+ background-color: navy;
+ }
+</style>
+<script type="text/javascript">
+window.onload = function () {
+ var orange = document.getElementsByTagName('div')[0], blue = document.getElementsByTagName('div')[1];
+ orange.ondragstart = function (e) {
+ e.dataTransfer.setData('text','PASS');
+ e.dataTransfer.effectAllowed = 'all';
+ };
+ blue.ondragenter = blue.ondragover = function (e) {
+ e.preventDefault();
+ };
+ blue.ondrop = function (e) {
+ e.preventDefault();
+ alert('JS alert');
+ };
+};
+</script>
+<div draggable="true"></div>
+<div></div>
+
+<ol>
+ <li>Drag the orange square over the blue square, then release it.</li>
+ <li>An alert may appear - release the mouse over the page, not the dialog. Dismiss it (you may need to use keyboard or mouse gestures such as gesture-down,gesture-right).</li>
+ <li>The mouse cursor may continue to show that a drag is in operation. If so, attempt to select some of this text with the mouse before continuing to the text step.</li>
+ <li>Fail if the mouse continues to show that a drag is in operation.</li>
+ <li>Try to select some text in this sentence. Fail if it is not possible.</li>
+ <li>Try to drag the orange square downwards. Fail if it is not possible.</li>
+</ol> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/012.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/012.html
new file mode 100644
index 00000000000..bcf65ce9e70
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/012.html
@@ -0,0 +1,44 @@
+<!doctype html>
+<title>Alert during dragend</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ display: inline-block;
+ }
+ body > div + div {
+ background-color: navy;
+ }
+</style>
+<script type="text/javascript">
+window.onload = function () {
+ var orange = document.getElementsByTagName('div')[0], blue = document.getElementsByTagName('div')[1], hasfired = false;
+ orange.ondragstart = function (e) {
+ e.dataTransfer.setData('text','PASS');
+ e.dataTransfer.effectAllowed = 'all';
+ };
+ blue.ondragenter = blue.ondragover = function (e) {
+ e.preventDefault();
+ };
+ blue.ondrop = function (e) {
+ e.preventDefault();
+ };
+ orange.ondragend = function (e) {
+ if( hasfired ) { return; }
+ hasfired = true;
+ alert('JS alert');
+ };
+};
+</script>
+<div draggable="true"></div>
+<div></div>
+
+<ol>
+ <li>Drag the orange square over the blue square, then release it.</li>
+ <li>An alert may appear - release the mouse over the page, not the dialog. Dismiss it (you may need to use keyboard or mouse gestures such as gesture-down,gesture-right).</li>
+ <li>The mouse cursor may continue to show that a drag is in operation. If so, attempt to select some of this text with the mouse before continuing to the text step.</li>
+ <li>Fail if the mouse continues to show that a drag is in operation.</li>
+ <li>Try to select some text in this sentence. Fail if it is not possible.</li>
+ <li>Try to drag the orange square downwards. Fail if it is not possible.</li>
+</ol> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/013.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/013.html
new file mode 100644
index 00000000000..31dd82e5113
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/013.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - drag interrupted by alert must not break mouse interaction with UI</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ }
+ body > div + div {
+ margin-top: 10px;
+ height: 200px;
+ width: 200px;
+ background-color: blue;
+ }
+</style>
+
+<script>
+window.onload = function() {
+ var orange = document.getElementsByTagName('div')[0], blue = document.getElementsByTagName('div')[1];
+ orange.ondragstart = function(e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text', 'dummy text');
+ };
+ blue.ondragover = function(e) {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'copy';
+ if( !window.doneonce ) {
+ alert('2. It should also ideally be possible to dismiss this dialog with your mouse/pointing device (do not use mouse gestures).');
+ }
+ window.doneonce = true;
+ };
+ blue.ondragenter = function(e) {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'copy';
+ alert('1. It should ideally be possible to dismiss this dialog with your mouse/pointing device (do not use mouse gestures).');
+ };
+ blue.ondrop = function(e) {
+ e.preventDefault();
+ };
+};
+</script>
+
+<p>Drag the orange square onto the blue square.</p>
+<div draggable="true"></div>
+<div></div>
+
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/014.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/014.html
new file mode 100644
index 00000000000..94258e44a6f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/014.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - drop interrupted by alert must not break mouse interaction with UI</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ }
+ body > div + div {
+ margin-top: 10px;
+ height: 200px;
+ width: 200px;
+ background-color: blue;
+ }
+</style>
+
+<script>
+window.onload = function() {
+ var orange = document.getElementsByTagName('div')[0], blue = document.getElementsByTagName('div')[1];
+ orange.ondragstart = function(e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text', 'dummy text');
+ };
+ blue.ondragover = blue.ondragenter = function(e) {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'copy';
+ };
+ blue.ondrop = function(e) {
+ e.preventDefault();
+ alert('It should ideally be possible to dismiss this dialog with your mouse/pointing device (do not use mouse gestures).');
+ };
+};
+</script>
+
+<p>Drag the orange square onto the blue square.</p>
+<div draggable="true"></div>
+<div></div>
+
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/015.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/015.html
new file mode 100644
index 00000000000..1fc6ef84dcf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/015.html
@@ -0,0 +1,32 @@
+<!doctype html>
+<title>Alert during dragstart with release over dialog</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ display: inline-block;
+ }
+</style>
+<script type="text/javascript">
+window.onload = function () {
+ var orange = document.getElementsByTagName('div')[0], blue = document.getElementsByTagName('div')[1], hasfired = false;
+ orange.ondragstart = function (e) {
+ e.dataTransfer.setData('text','PASS');
+ e.dataTransfer.effectAllowed = 'all';
+ if( hasfired ) { return; }
+ hasfired = true;
+ alert('Release the mouse over this dialog');
+ };
+};
+</script>
+<div draggable="true"></div>
+
+<ol>
+ <li>Drag the orange square downwards until the drag placeholder appears.</li>
+ <li>An alert may appear - release the mouse over the dialog. Dismiss it (you may need to use keyboard or mouse gestures such as gesture-down,gesture-right). If it does not appear, release the drag.</li>
+ <li>The mouse cursor may continue to show that a drag is in operation. If so, attempt to select some of this text with the mouse before continuing to the text step.</li>
+ <li>Fail if the mouse continues to show that a drag is in operation.</li>
+ <li>Try to select some text in this sentence. Fail if it is not possible.</li>
+ <li>Try to drag the orange square downwards again. Fail if that is not possible.</li>
+</ol> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/016.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/016.html
new file mode 100644
index 00000000000..f28191d46e5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/016.html
@@ -0,0 +1,34 @@
+<!doctype html>
+<title>Alert during drag with release over dialog</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ display: inline-block;
+ }
+</style>
+<script type="text/javascript">
+window.onload = function () {
+ var orange = document.getElementsByTagName('div')[0], blue = document.getElementsByTagName('div')[1], hasfired = false;
+ orange.ondragstart = function (e) {
+ e.dataTransfer.setData('text','PASS');
+ e.dataTransfer.effectAllowed = 'all';
+ };
+ orange.ondrag = function (e) {
+ if( hasfired ) { return; }
+ hasfired = true;
+ alert('Release the mouse over this dialog');
+ };
+};
+</script>
+<div draggable="true"></div>
+
+<ol>
+ <li>Drag the orange square downwards until the drag placeholder appears.</li>
+ <li>An alert may appear - release the mouse over the dialog. Dismiss it (you may need to use keyboard or mouse gestures such as gesture-down,gesture-right). If it does not appear, release the drag.</li>
+ <li>The mouse cursor may continue to show that a drag is in operation. If so, attempt to select some of this text with the mouse before continuing to the text step.</li>
+ <li>Fail if the mouse continues to show that a drag is in operation.</li>
+ <li>Try to select some text in this sentence. Fail if it is not possible.</li>
+ <li>Try to drag the orange square downwards again. Fail if that is not possible.</li>
+</ol> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/017.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/017.html
new file mode 100644
index 00000000000..6e3926c9d59
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/017.html
@@ -0,0 +1,40 @@
+<!doctype html>
+<title>Alert during dragenter with release over dialog</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ display: inline-block;
+ }
+ body > div + div {
+ background-color: navy;
+ }
+</style>
+<script type="text/javascript">
+window.onload = function () {
+ var orange = document.getElementsByTagName('div')[0], blue = document.getElementsByTagName('div')[1];
+ orange.ondragstart = function (e) {
+ e.dataTransfer.setData('text','PASS');
+ e.dataTransfer.effectAllowed = 'all';
+ };
+ blue.ondragenter = function (e) {
+ e.preventDefault();
+ alert('Release the mouse over this dialog');
+ };
+ blue.ondragover = function (e) {
+ e.preventDefault();
+ };
+};
+</script>
+<div draggable="true"></div>
+<div></div>
+
+<ol>
+ <li>Drag the orange square over the blue square.</li>
+ <li>An alert may appear - release the mouse over the dialog. Dismiss it (you may need to use keyboard or mouse gestures such as gesture-down,gesture-right). If it does not appear, release the drag.</li>
+ <li>The mouse cursor may continue to show that a drag is in operation. If so, attempt to select some of this text with the mouse before continuing to the text step.</li>
+ <li>Fail if the mouse continues to show that a drag is in operation.</li>
+ <li>Try to select some text in this sentence. Fail if it is not possible.</li>
+ <li>Try to drag the orange square downwards. Fail if it is not possible.</li>
+</ol> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/018.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/018.html
new file mode 100644
index 00000000000..6fdb79aa952
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/018.html
@@ -0,0 +1,42 @@
+<!doctype html>
+<title>Alert during dragover with release over dialog</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ display: inline-block;
+ }
+ body > div + div {
+ background-color: navy;
+ }
+</style>
+<script type="text/javascript">
+window.onload = function () {
+ var orange = document.getElementsByTagName('div')[0], blue = document.getElementsByTagName('div')[1], hasfired = false;
+ orange.ondragstart = function (e) {
+ e.dataTransfer.setData('text','PASS');
+ e.dataTransfer.effectAllowed = 'all';
+ };
+ blue.ondragenter = function (e) {
+ e.preventDefault();
+ };
+ blue.ondragover = function (e) {
+ e.preventDefault();
+ if( hasfired ) { return; }
+ hasfired = true;
+ alert('Release the mouse over this dialog');
+ };
+};
+</script>
+<div draggable="true"></div>
+<div></div>
+
+<ol>
+ <li>Drag the orange square over the blue square.</li>
+ <li>An alert may appear - release the mouse over the dialog. Dismiss it (you may need to use keyboard or mouse gestures such as gesture-down,gesture-right). If it does not appear, release the drag.</li>
+ <li>The mouse cursor may continue to show that a drag is in operation. If so, attempt to select some of this text with the mouse before continuing to the text step.</li>
+ <li>Fail if the mouse continues to show that a drag is in operation.</li>
+ <li>Try to select some text in this sentence. Fail if it is not possible.</li>
+ <li>Try to drag the orange square downwards. Fail if it is not possible.</li>
+</ol> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/019.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/019.html
new file mode 100644
index 00000000000..d9af799a58c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/019.html
@@ -0,0 +1,39 @@
+<!doctype html>
+<title>Alert during dragleave with release over dialog</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ display: inline-block;
+ }
+ body > div + div {
+ background-color: navy;
+ }
+</style>
+<script type="text/javascript">
+window.onload = function () {
+ var orange = document.getElementsByTagName('div')[0], blue = document.getElementsByTagName('div')[1];
+ orange.ondragstart = function (e) {
+ e.dataTransfer.setData('text','PASS');
+ e.dataTransfer.effectAllowed = 'all';
+ };
+ blue.ondragenter = blue.ondragover = function (e) {
+ e.preventDefault();
+ };
+ blue.ondragleave = function (e) {
+ alert('Release the mouse over this dialog');
+ };
+};
+</script>
+<div draggable="true"></div>
+<div></div>
+
+<ol>
+ <li>Drag the orange square over the blue square, then back over the orange square.</li>
+ <li>An alert may appear - release the mouse over the dialog. Dismiss it (you may need to use keyboard or mouse gestures such as gesture-down,gesture-right). If it does not appear, release the drag.</li>
+ <li>The mouse cursor may continue to show that a drag is in operation. If so, attempt to select some of this text with the mouse before continuing to the text step.</li>
+ <li>Fail if the mouse continues to show that a drag is in operation.</li>
+ <li>Try to select some text in this sentence. Fail if it is not possible.</li>
+ <li>Try to drag the orange square downwards. Fail if it is not possible.</li>
+</ol> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/020.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/020.html
new file mode 100644
index 00000000000..c57b25dcb0a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/020.html
@@ -0,0 +1,33 @@
+<!doctype html>
+<title>Alert during dragenter for file drag</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ display: inline-block;
+ }
+</style>
+<script type="text/javascript">
+window.onload = function () {
+ var orange = document.getElementsByTagName('div')[0];
+ orange.ondragenter = function (e) {
+ e.preventDefault();
+ alert('JS alert');
+ };
+ orange.ondragover = orange.ondrop = function (e) {
+ e.preventDefault();
+ };
+};
+</script>
+<div draggable="true"></div>
+
+<ol>
+ <li>Drag a file (one that your browser cannot open natively, such as an executable file) from your system file manager over the orange square.</li>
+ <li>An alert may appear - release the mouse over a blank part of the page, not the dialog. Dismiss it (you may need to use keyboard or mouse gestures such as gesture-down,gesture-right). If it does not appear, release the drag and accept any prompt to upload the file.</li>
+ <li>If a file download dialog appears, cancel it and return to this page.</li>
+ <li>Fail if the alert reappears.</li>
+ <li>The mouse cursor may continue to show that a drag is in operation. If so, attempt to select some of this text with the mouse before continuing to the text step.</li>
+ <li>Fail if the mouse continues to show that a drag is in operation.</li>
+ <li>Try to select some text in this sentence. Fail if it is not possible.</li>
+</ol> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/021.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/021.html
new file mode 100644
index 00000000000..e30416b4fbc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/021.html
@@ -0,0 +1,33 @@
+<!doctype html>
+<title>Alert during dragenter for file drag with release over dialog</title>
+<style>
+ body > div {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ display: inline-block;
+ }
+</style>
+<script type="text/javascript">
+window.onload = function () {
+ var orange = document.getElementsByTagName('div')[0];
+ orange.ondragenter = function (e) {
+ e.preventDefault();
+ alert('JS alert');
+ };
+ orange.ondragover = orange.ondrop = function (e) {
+ e.preventDefault();
+ };
+};
+</script>
+<div draggable="true"></div>
+
+<ol>
+ <li>Drag a file (one that your browser cannot open natively, such as an executable file) from your system file manager over the orange square.</li>
+ <li>An alert may appear - release the mouse over the dialog. Dismiss it (you may need to use keyboard or mouse gestures such as gesture-down,gesture-right). If it does not appear, release the drag and accept any prompt to upload the file.</li>
+ <li>If a file download dialog appears, cancel it and return to this page.</li>
+ <li>Fail if the alert reappears.</li>
+ <li>The mouse cursor may continue to show that a drag is in operation. If so, attempt to select some of this text with the mouse before continuing to the text step.</li>
+ <li>Fail if the mouse continues to show that a drag is in operation.</li>
+ <li>Try to select some text in this sentence. Fail if it is not possible.</li>
+</ol> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/fail.txt b/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/fail.txt
new file mode 100644
index 00000000000..fc26162516b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/fail.txt
@@ -0,0 +1 @@
+FAIL \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/file1.txt b/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/file1.txt
new file mode 100644
index 00000000000..6c8db5df2b3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/file1.txt
@@ -0,0 +1 @@
+file 1 \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/file2.txt b/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/file2.txt
new file mode 100644
index 00000000000..dd4128ed9e5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/file2.txt
@@ -0,0 +1 @@
+file 2 \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/pass.txt b/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/pass.txt
new file mode 100644
index 00000000000..fc26162516b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/interrupt/pass.txt
@@ -0,0 +1 @@
+FAIL \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/keyboardshortcuts.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/keyboardshortcuts.html
new file mode 100644
index 00000000000..13340f44234
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/keyboardshortcuts.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Keyboard shortcuts during drag/drop</title>
+ </head>
+ <body>
+
+ <ol>
+ <li>Select some text in this sentence and begin dragging it.</li>
+ <li>While dragging, use your keyboard shortcut to reload the page. It should work without cancelling the drag.</li>
+ <li>While dragging, use your keyboard shortcut to select all text on the page. It should work without cancelling the drag.</li>
+ <li>While dragging, use your keyboard shortcut to open a new tab. It should work without cancelling the drag.</li>
+ <li>While dragging, use your keyboard shortcut to switch to another tab. It should work without cancelling the drag.</li>
+ <li>While dragging, use your keyboard shortcuts to go back and forward in history (<a href="#next">use this link first to add a history entry if needed</a>). It should work without cancelling the drag.</li>
+ </ol>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/modifiers/all.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/modifiers/all.html
new file mode 100644
index 00000000000..3f91fb5fec9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/modifiers/all.html
@@ -0,0 +1,175 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Modifier keys selecting dropEffect with 'all'</title>
+ <style type="text/css">
+div:first-child {
+ height: 100px;
+ width: 100px;
+ background: orange;
+ display: inline-block;
+}
+div:first-child + div {
+ height: 100px;
+ width: 100px;
+ background: blue;
+ display: inline-block;
+}
+div:first-child + div + div {
+ height: 100px;
+ width: 100px;
+ background: fuchsia;
+ display: inline-block;
+}
+table {
+ display: inline-table;
+ margin-right: 1em;
+ border-collapse: collapse;
+}
+table, th, td {
+ border: 1px solid black;
+}
+thead th {
+ background: silver;
+ color: black;
+}
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ var countedDrops = 0, bde, bdo, bdo2, fde, fdo, fdr;
+ var orange = document.getElementsByTagName('div')[0];
+ orange.ondragstart = function (e) {
+ e.dataTransfer.setData('text','http://example.com/');
+ e.dataTransfer.effectAllowed = 'all';
+ bde = bdo = bdo2 = fde = fdo = fdr = '';
+ };
+ var blue = document.getElementsByTagName('div')[1];
+ blue.ondragenter = function (e) {
+ e.preventDefault();
+ if( !bde ) { bde = e.dataTransfer.dropEffect; }
+ };
+ blue.ondragover = function (e) {
+ e.preventDefault();
+ if( !bdo ) {
+ bdo = e.dataTransfer.dropEffect;
+ }
+ //bdo2 always collects dropEffect, since it can change multiple times in rapid succession when pressing multiple modifiers
+ //test cares about the last dropEffect that was seen before leaving the blue square, and that will be stored in bdo2
+ bdo2 = e.dataTransfer.dropEffect;
+ };
+ var fuchsia = document.getElementsByTagName('div')[2];
+ fuchsia.ondragenter = function (e) {
+ e.preventDefault();
+ if( !fde ) { fde = e.dataTransfer.dropEffect; }
+ };
+ fuchsia.ondragover = function (e) {
+ e.preventDefault();
+ if( !fdo ) { fdo = e.dataTransfer.dropEffect; }
+ };
+ fuchsia.ondrop = function (e) {
+ e.preventDefault();
+ fdr = e.dataTransfer.dropEffect;
+ };
+ orange.ondragend = function (e) {
+ var ode = e.dataTransfer.dropEffect, temparray;
+ if( bde == bdo && bdo2 == fdr && fde == fdr && fdo == fdr && ode == fdr ) {
+ if( bde == fdr ) {
+ tmparray = [fdr];
+ } else {
+ tmparray = [bde,fdr];
+ }
+ } else if( bde == bdo && bdo2 == fdo && fde == fdo && !fdr ) {
+ tmparray = [bde,fdo,ode];
+ } else {
+ tmparray = [bde,bdo,bdo2,fde,fdo,fdr,ode];
+ }
+ tmparray[ tmparray.length - 1 ] = '<strong>' + tmparray[ tmparray.length - 1 ] + '<\/strong>';
+ document.getElementsByTagName('div')[3].innerHTML = (++countedDrops) + '. ' + tmparray.join('=&gt;');
+ };
+};
+ </script>
+ </head>
+ <body>
+
+ <div draggable="true"></div>
+ <div></div>
+ <div></div>
+ <div><strong>&nbsp;</strong></div>
+ <ol>
+ <li>Drag the orange square over the blue square</li>
+ <li>Press the relevant modifier keys for your platform</li>
+ <li>Continue dragging over the pink square</li>
+ <li>Release the drag, then the keys</li>
+ <li>Check that the correct drop effect is produced in each case. If the mouse cursor can change to indicate the final type of drop effect that will take place, it should change to the relevant type (the one in bold) once the modifier keys are pressed.</li>
+ </ol>
+ <!-- Windows Explorer uses Ctrl for copy, Shift for move, Alt or Ctrl+Shift for link. -->
+ <!-- Anything else invalidates the modifiers, and reverts to default. -->
+ <table>
+ <caption>Windows</caption>
+ <thead>
+ <tr><th>Modifier</th><th>Drop effect</th></tr>
+ </thead>
+ <tbody>
+ <tr><td>None</td><td><strong>copy</strong></td></tr>
+ <tr><td>Ctrl</td><td><strong>copy</strong></td></tr>
+ <tr><td>Shift</td><td>copy=&gt;<strong>move</strong></td></tr>
+ <tr><td>Alt</td><td>copy=&gt;<strong>link</strong></td></tr>
+ <tr><td>Ctrl+Shift</td><td>copy=&gt;<strong>link</strong></td></tr>
+ <tr><td>Ctrl+Alt</td><td><strong>copy</strong></td></tr>
+ <tr><td>Alt+Shift</td><td><strong>copy</strong></td></tr>
+ <tr><td>Ctrl+Alt+Shift</td><td><strong>copy</strong></td></tr>
+ </tbody>
+ </table>
+ <!-- KDE Konqueror uses Ctrl for copy, Shift for move, Ctrl+Shift for link. -->
+ <!-- Anything else is ignored completely, and has no effect on the modifier sequence. -->
+ <!-- Gnome Nautilus uses Ctrl for copy, Shift for move, Ctrl+Shift for link (and Alt to open a context menu). -->
+ <!-- Anything else (including Alt when combined with other modifiers) is ignored completely, and has no effect on the modifier sequence. -->
+ <table>
+ <caption>Unix/Linux</caption>
+ <thead>
+ <tr><th>Modifier</th><th>Drop effect</th></tr>
+ </thead>
+ <tbody>
+ <tr><td>None</td><td><strong>copy</strong></td></tr>
+ <tr><td>Ctrl</td><td><strong>copy</strong></td></tr>
+ <tr><td>Shift</td><td>copy=&gt;<strong>move</strong></td></tr>
+ <tr><td>Alt</td><td><strong>copy</strong></td></tr>
+ <tr><td>Ctrl+Shift</td><td>copy=&gt;<strong>link</strong></td></tr>
+ <tr><td>Ctrl+Alt</td><td><strong>copy</strong></td></tr>
+ <tr><td>Alt+Shift</td><td>copy=&gt;<strong>move</strong></td></tr>
+ <tr><td>Ctrl+Alt+Shift</td><td>copy=&gt;<strong>link</strong></td></tr>
+ </tbody>
+ </table>
+ <!-- Mac Finder uses Option for copy, Command for move, Command+Option for link. -->
+ <!-- Anything else is ignored completely, and has no effect on the modifier sequence. -->
+ <table>
+ <caption>Mac</caption>
+ <thead>
+ <tr><th>Modifier</th><th>Drop effect</th></tr>
+ </thead>
+ <tbody>
+ <tr><td>None</td><td><strong>copy</strong></td></tr>
+ <tr><td>Ctrl</td><td><strong>copy</strong></td></tr>
+ <tr><td>Shift</td><td><strong>copy</strong></td></tr>
+ <tr><td>Option/alt</td><td><strong>copy</strong></td></tr>
+ <tr><td>Command</td><td>copy=&gt;<strong>move</strong></td></tr>
+
+ <tr><td>Ctrl+Shift</td><td><strong>copy</strong></td></tr>
+ <tr><td>Ctrl+Option</td><td><strong>copy</strong></td></tr>
+ <tr><td>Ctrl+Command</td><td>copy=&gt;<strong>move</strong></td></tr>
+ <tr><td>Shift+Option</td><td><strong>copy</strong></td></tr>
+ <tr><td>Shift+Command</td><td>copy=&gt;<strong>move</strong></td></tr>
+ <tr><td>Command+Option</td><td>copy=&gt;<strong>link</strong></td></tr>
+
+ <tr><td>Ctrl+Shift+Option</td><td><strong>copy</strong></td></tr>
+ <tr><td>Ctrl+Shift+Command</td><td>copy=&gt;<strong>move</strong></td></tr>
+ <tr><td>Ctrl+Command+Option</td><td>copy=&gt;<strong>link</strong></td></tr>
+ <tr><td>Shift+Command+Option</td><td>copy=&gt;<strong>link</strong></td></tr>
+
+ <tr><td>Ctrl+Shift+Command+Option</td><td>copy=&gt;<strong>link</strong></td></tr>
+ </tbody>
+ </table>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/modifiers/copy.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/modifiers/copy.html
new file mode 100644
index 00000000000..6366dd4dcd7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/modifiers/copy.html
@@ -0,0 +1,175 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Modifier keys selecting dropEffect with 'copy'</title>
+ <style type="text/css">
+div:first-child {
+ height: 100px;
+ width: 100px;
+ background: orange;
+ display: inline-block;
+}
+div:first-child + div {
+ height: 100px;
+ width: 100px;
+ background: blue;
+ display: inline-block;
+}
+div:first-child + div + div {
+ height: 100px;
+ width: 100px;
+ background: fuchsia;
+ display: inline-block;
+}
+table {
+ display: inline-table;
+ margin-right: 1em;
+ border-collapse: collapse;
+}
+table, th, td {
+ border: 1px solid black;
+}
+thead th {
+ background: silver;
+ color: black;
+}
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ var countedDrops = 0, bde, bdo, bdo2, fde, fdo, fdr;
+ var orange = document.getElementsByTagName('div')[0];
+ orange.ondragstart = function (e) {
+ e.dataTransfer.setData('text','http://example.com/');
+ e.dataTransfer.effectAllowed = 'copy';
+ bde = bdo = bdo2 = fde = fdo = fdr = '';
+ };
+ var blue = document.getElementsByTagName('div')[1];
+ blue.ondragenter = function (e) {
+ e.preventDefault();
+ if( !bde ) { bde = e.dataTransfer.dropEffect; }
+ };
+ blue.ondragover = function (e) {
+ e.preventDefault();
+ if( !bdo ) {
+ bdo = e.dataTransfer.dropEffect;
+ }
+ //bdo2 always collects dropEffect, since it can change multiple times in rapid succession when pressing multiple modifiers
+ //test cares about the last dropEffect that was seen before leaving the blue square, and that will be stored in bdo2
+ bdo2 = e.dataTransfer.dropEffect;
+ };
+ var fuchsia = document.getElementsByTagName('div')[2];
+ fuchsia.ondragenter = function (e) {
+ e.preventDefault();
+ if( !fde ) { fde = e.dataTransfer.dropEffect; }
+ };
+ fuchsia.ondragover = function (e) {
+ e.preventDefault();
+ if( !fdo ) { fdo = e.dataTransfer.dropEffect; }
+ };
+ fuchsia.ondrop = function (e) {
+ e.preventDefault();
+ fdr = e.dataTransfer.dropEffect;
+ };
+ orange.ondragend = function (e) {
+ var ode = e.dataTransfer.dropEffect, temparray;
+ if( bde == bdo && bdo2 == fdr && fde == fdr && fdo == fdr && ode == fdr ) {
+ if( bde == fdr ) {
+ tmparray = [fdr];
+ } else {
+ tmparray = [bde,fdr];
+ }
+ } else if( bde == bdo && bdo2 == fdo && fde == fdo && !fdr ) {
+ tmparray = [bde,fdo,ode];
+ } else {
+ tmparray = [bde,bdo,bdo2,fde,fdo,fdr,ode];
+ }
+ tmparray[ tmparray.length - 1 ] = '<strong>' + tmparray[ tmparray.length - 1 ] + '<\/strong>';
+ document.getElementsByTagName('div')[3].innerHTML = (++countedDrops) + '. ' + tmparray.join('=&gt;');
+ };
+};
+ </script>
+ </head>
+ <body>
+
+ <div draggable="true"></div>
+ <div></div>
+ <div></div>
+ <div><strong>&nbsp;</strong></div>
+ <ol>
+ <li>Drag the orange square over the blue square</li>
+ <li>Press the relevant modifier keys for your platform</li>
+ <li>Continue dragging over the pink square</li>
+ <li>Release the drag, then the keys</li>
+ <li>Check that the correct drop effect is produced in each case. If the mouse cursor can change to indicate the final type of drop effect that will take place, it should change to the relevant type (the one in bold) once the modifier keys are pressed.</li>
+ </ol>
+ <!-- Windows Explorer uses Ctrl for copy, Shift for move, Alt or Ctrl+Shift for link. -->
+ <!-- Anything else invalidates the modifiers, and reverts to default. -->
+ <table>
+ <caption>Windows</caption>
+ <thead>
+ <tr><th>Modifier</th><th>Drop effect</th></tr>
+ </thead>
+ <tbody>
+ <tr><td>None</td><td><strong>copy</strong></td></tr>
+ <tr><td>Ctrl</td><td><strong>copy</strong></td></tr>
+ <tr><td>Shift</td><td>copy=&gt;move=&gt;<strong>none</strong></td></tr>
+ <tr><td>Alt</td><td>copy=&gt;link=&gt;<strong>none</strong></td></tr>
+ <tr><td>Ctrl+Shift</td><td>copy=&gt;link=&gt;<strong>none</strong></td></tr>
+ <tr><td>Ctrl+Alt</td><td><strong>copy</strong></td></tr>
+ <tr><td>Alt+Shift</td><td><strong>copy</strong></td></tr>
+ <tr><td>Ctrl+Alt+Shift</td><td><strong>copy</strong></td></tr>
+ </tbody>
+ </table>
+ <!-- KDE Konqueror uses Ctrl for copy, Shift for move, Ctrl+Shift for link. -->
+ <!-- Anything else is ignored completely, and has no effect on the modifier sequence. -->
+ <!-- Gnome Nautilus uses Ctrl for copy, Shift for move, Ctrl+Shift for link (and Alt to open a context menu). -->
+ <!-- Anything else (including Alt when combined with other modifiers) is ignored completely, and has no effect on the modifier sequence. -->
+ <table>
+ <caption>Unix/Linux</caption>
+ <thead>
+ <tr><th>Modifier</th><th>Drop effect</th></tr>
+ </thead>
+ <tbody>
+ <tr><td><strong>none</td><td><strong>copy</strong></td></tr>
+ <tr><td>Ctrl</td><td><strong>copy</strong></td></tr>
+ <tr><td>Shift</td><td>copy=&gt;move=&gt;<strong>none</strong></td></tr>
+ <tr><td>Alt</td><td><strong>copy</strong></td></tr>
+ <tr><td>Ctrl+Shift</td><td>copy=&gt;link=&gt;<strong>none</strong></td></tr>
+ <tr><td>Ctrl+Alt</td><td><strong>copy</strong></td></tr>
+ <tr><td>Alt+Shift</td><td>copy=&gt;move=&gt;<strong>none</strong></td></tr>
+ <tr><td>Ctrl+Alt+Shift</td><td>copy=&gt;link=&gt;<strong>none</strong></td></tr>
+ </tbody>
+ </table>
+ <!-- Mac Finder uses Option for copy, Command for move, Command+Option for link. -->
+ <!-- Anything else is ignored completely, and has no effect on the modifier sequence. -->
+ <table>
+ <caption>Mac</caption>
+ <thead>
+ <tr><th>Modifier</th><th>Drop effect</th></tr>
+ </thead>
+ <tbody>
+ <tr><td><strong>none</td><td><strong>copy</strong></td></tr>
+ <tr><td>Ctrl</td><td><strong>copy</strong></td></tr>
+ <tr><td>Shift</td><td><strong>copy</strong></td></tr>
+ <tr><td>Option/alt</td><td><strong>copy</strong></td></tr>
+ <tr><td>Command</td><td>copy=&gt;move=&gt;<strong>none</strong></td></tr>
+
+ <tr><td>Ctrl+Shift</td><td><strong>copy</strong></td></tr>
+ <tr><td>Ctrl+Option</td><td><strong>copy</strong></td></tr>
+ <tr><td>Ctrl+Command</td><td>copy=&gt;move=&gt;<strong>none</strong></td></tr>
+ <tr><td>Shift+Option</td><td><strong>copy</strong></td></tr>
+ <tr><td>Shift+Command</td><td>copy=&gt;move=&gt;<strong>none</strong></td></tr>
+ <tr><td>Command+Option</td><td>copy=&gt;link=&gt;<strong>none</strong></td></tr>
+
+ <tr><td>Ctrl+Shift+Option</td><td><strong>copy</strong></td></tr>
+ <tr><td>Ctrl+Shift+Command</td><td>copy=&gt;move=&gt;<strong>none</strong></td></tr>
+ <tr><td>Ctrl+Command+Option</td><td>copy=&gt;link=&gt;<strong>none</strong></td></tr>
+ <tr><td>Shift+Command+Option</td><td>copy=&gt;link=&gt;<strong>none</strong></td></tr>
+
+ <tr><td>Ctrl+Shift+Command+Option</td><td>copy=&gt;link=&gt;<strong>none</strong></td></tr>
+ </tbody>
+ </table>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/modifiers/copylink.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/modifiers/copylink.html
new file mode 100644
index 00000000000..27d9126a959
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/modifiers/copylink.html
@@ -0,0 +1,175 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Modifier keys selecting dropEffect with 'copyLink'</title>
+ <style type="text/css">
+div:first-child {
+ height: 100px;
+ width: 100px;
+ background: orange;
+ display: inline-block;
+}
+div:first-child + div {
+ height: 100px;
+ width: 100px;
+ background: blue;
+ display: inline-block;
+}
+div:first-child + div + div {
+ height: 100px;
+ width: 100px;
+ background: fuchsia;
+ display: inline-block;
+}
+table {
+ display: inline-table;
+ margin-right: 1em;
+ border-collapse: collapse;
+}
+table, th, td {
+ border: 1px solid black;
+}
+thead th {
+ background: silver;
+ color: black;
+}
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ var countedDrops = 0, bde, bdo, bdo2, fde, fdo, fdr;
+ var orange = document.getElementsByTagName('div')[0];
+ orange.ondragstart = function (e) {
+ e.dataTransfer.setData('text','http://example.com/');
+ e.dataTransfer.effectAllowed = 'copyLink';
+ bde = bdo = bdo2 = fde = fdo = fdr = '';
+ };
+ var blue = document.getElementsByTagName('div')[1];
+ blue.ondragenter = function (e) {
+ e.preventDefault();
+ if( !bde ) { bde = e.dataTransfer.dropEffect; }
+ };
+ blue.ondragover = function (e) {
+ e.preventDefault();
+ if( !bdo ) {
+ bdo = e.dataTransfer.dropEffect;
+ }
+ //bdo2 always collects dropEffect, since it can change multiple times in rapid succession when pressing multiple modifiers
+ //test cares about the last dropEffect that was seen before leaving the blue square, and that will be stored in bdo2
+ bdo2 = e.dataTransfer.dropEffect;
+ };
+ var fuchsia = document.getElementsByTagName('div')[2];
+ fuchsia.ondragenter = function (e) {
+ e.preventDefault();
+ if( !fde ) { fde = e.dataTransfer.dropEffect; }
+ };
+ fuchsia.ondragover = function (e) {
+ e.preventDefault();
+ if( !fdo ) { fdo = e.dataTransfer.dropEffect; }
+ };
+ fuchsia.ondrop = function (e) {
+ e.preventDefault();
+ fdr = e.dataTransfer.dropEffect;
+ };
+ orange.ondragend = function (e) {
+ var ode = e.dataTransfer.dropEffect, temparray;
+ if( bde == bdo && bdo2 == fdr && fde == fdr && fdo == fdr && ode == fdr ) {
+ if( bde == fdr ) {
+ tmparray = [fdr];
+ } else {
+ tmparray = [bde,fdr];
+ }
+ } else if( bde == bdo && bdo2 == fdo && fde == fdo && !fdr ) {
+ tmparray = [bde,fdo,ode];
+ } else {
+ tmparray = [bde,bdo,bdo2,fde,fdo,fdr,ode];
+ }
+ tmparray[ tmparray.length - 1 ] = '<strong>' + tmparray[ tmparray.length - 1 ] + '<\/strong>';
+ document.getElementsByTagName('div')[3].innerHTML = (++countedDrops) + '. ' + tmparray.join('=&gt;');
+ };
+};
+ </script>
+ </head>
+ <body>
+
+ <div draggable="true"></div>
+ <div></div>
+ <div></div>
+ <div><strong>&nbsp;</strong></div>
+ <ol>
+ <li>Drag the orange square over the blue square</li>
+ <li>Press the relevant modifier keys for your platform</li>
+ <li>Continue dragging over the pink square</li>
+ <li>Release the drag, then the keys</li>
+ <li>Check that the correct drop effect is produced in each case. If the mouse cursor can change to indicate the final type of drop effect that will take place, it should change to the relevant type (the one in bold) once the modifier keys are pressed.</li>
+ </ol>
+ <!-- Windows Explorer uses Ctrl for copy, Shift for move, Alt or Ctrl+Shift for link. -->
+ <!-- Anything else invalidates the modifiers, and reverts to default. -->
+ <table>
+ <caption>Windows</caption>
+ <thead>
+ <tr><th>Modifier</th><th>Drop effect</th></tr>
+ </thead>
+ <tbody>
+ <tr><td>None</td><td><strong>copy</strong></td></tr>
+ <tr><td>Ctrl</td><td><strong>copy</strong></td></tr>
+ <tr><td>Shift</td><td>copy=&gt;move=&gt;<strong>none</strong></td></tr>
+ <tr><td>Alt</td><td>copy=&gt;<strong>link</strong></td></tr>
+ <tr><td>Ctrl+Shift</td><td>copy=&gt;<strong>link</strong></td></tr>
+ <tr><td>Ctrl+Alt</td><td><strong>copy</strong></td></tr>
+ <tr><td>Alt+Shift</td><td><strong>copy</strong></td></tr>
+ <tr><td>Ctrl+Alt+Shift</td><td><strong>copy</strong></td></tr>
+ </tbody>
+ </table>
+ <!-- KDE Konqueror uses Ctrl for copy, Shift for move, Ctrl+Shift for link. -->
+ <!-- Anything else is ignored completely, and has no effect on the modifier sequence. -->
+ <!-- Gnome Nautilus uses Ctrl for copy, Shift for move, Ctrl+Shift for link (and Alt to open a context menu). -->
+ <!-- Anything else (including Alt when combined with other modifiers) is ignored completely, and has no effect on the modifier sequence. -->
+ <table>
+ <caption>Unix/Linux</caption>
+ <thead>
+ <tr><th>Modifier</th><th>Drop effect</th></tr>
+ </thead>
+ <tbody>
+ <tr><td><strong>none</td><td><strong>copy</strong></td></tr>
+ <tr><td>Ctrl</td><td><strong>copy</strong></td></tr>
+ <tr><td>Shift</td><td>copy=&gt;move=&gt;<strong>none</strong></td></tr>
+ <tr><td>Alt</td><td><strong>copy</strong></td></tr>
+ <tr><td>Ctrl+Shift</td><td>copy=&gt;<strong>link</strong></td></tr>
+ <tr><td>Ctrl+Alt</td><td><strong>copy</strong></td></tr>
+ <tr><td>Alt+Shift</td><td>copy=&gt;move=&gt;<strong>none</strong></td></tr>
+ <tr><td>Ctrl+Alt+Shift</td><td>copy=&gt;<strong>link</strong></td></tr>
+ </tbody>
+ </table>
+ <!-- Mac Finder uses Option for copy, Command for move, Command+Option for link. -->
+ <!-- Anything else is ignored completely, and has no effect on the modifier sequence. -->
+ <table>
+ <caption>Mac</caption>
+ <thead>
+ <tr><th>Modifier</th><th>Drop effect</th></tr>
+ </thead>
+ <tbody>
+ <tr><td><strong>none</td><td><strong>copy</strong></td></tr>
+ <tr><td>Ctrl</td><td><strong>copy</strong></td></tr>
+ <tr><td>Shift</td><td><strong>copy</strong></td></tr>
+ <tr><td>Option/alt</td><td><strong>copy</strong></td></tr>
+ <tr><td>Command</td><td>copy=&gt;move=&gt;<strong>none</strong></td></tr>
+
+ <tr><td>Ctrl+Shift</td><td><strong>copy</strong></td></tr>
+ <tr><td>Ctrl+Option</td><td><strong>copy</strong></td></tr>
+ <tr><td>Ctrl+Command</td><td>copy=&gt;move=&gt;<strong>none</strong></td></tr>
+ <tr><td>Shift+Option</td><td><strong>copy</strong></td></tr>
+ <tr><td>Shift+Command</td><td>copy=&gt;move=&gt;<strong>none</strong></td></tr>
+ <tr><td>Command+Option</td><td>copy=&gt;<strong>link</strong></td></tr>
+
+ <tr><td>Ctrl+Shift+Option</td><td><strong>copy</strong></td></tr>
+ <tr><td>Ctrl+Shift+Command</td><td>copy=&gt;move=&gt;<strong>none</strong></td></tr>
+ <tr><td>Ctrl+Command+Option</td><td>copy=&gt;<strong>link</strong></td></tr>
+ <tr><td>Shift+Command+Option</td><td>copy=&gt;<strong>link</strong></td></tr>
+
+ <tr><td>Ctrl+Shift+Command+Option</td><td>copy=&gt;<strong>link</strong></td></tr>
+ </tbody>
+ </table>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/modifiers/copymove.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/modifiers/copymove.html
new file mode 100644
index 00000000000..352e831dc6a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/modifiers/copymove.html
@@ -0,0 +1,175 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Modifier keys selecting dropEffect with 'copyMove'</title>
+ <style type="text/css">
+div:first-child {
+ height: 100px;
+ width: 100px;
+ background: orange;
+ display: inline-block;
+}
+div:first-child + div {
+ height: 100px;
+ width: 100px;
+ background: blue;
+ display: inline-block;
+}
+div:first-child + div + div {
+ height: 100px;
+ width: 100px;
+ background: fuchsia;
+ display: inline-block;
+}
+table {
+ display: inline-table;
+ margin-right: 1em;
+ border-collapse: collapse;
+}
+table, th, td {
+ border: 1px solid black;
+}
+thead th {
+ background: silver;
+ color: black;
+}
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ var countedDrops = 0, bde, bdo, bdo2, fde, fdo, fdr;
+ var orange = document.getElementsByTagName('div')[0];
+ orange.ondragstart = function (e) {
+ e.dataTransfer.setData('text','http://example.com/');
+ e.dataTransfer.effectAllowed = 'copyMove';
+ bde = bdo = bdo2 = fde = fdo = fdr = '';
+ };
+ var blue = document.getElementsByTagName('div')[1];
+ blue.ondragenter = function (e) {
+ e.preventDefault();
+ if( !bde ) { bde = e.dataTransfer.dropEffect; }
+ };
+ blue.ondragover = function (e) {
+ e.preventDefault();
+ if( !bdo ) {
+ bdo = e.dataTransfer.dropEffect;
+ }
+ //bdo2 always collects dropEffect, since it can change multiple times in rapid succession when pressing multiple modifiers
+ //test cares about the last dropEffect that was seen before leaving the blue square, and that will be stored in bdo2
+ bdo2 = e.dataTransfer.dropEffect;
+ };
+ var fuchsia = document.getElementsByTagName('div')[2];
+ fuchsia.ondragenter = function (e) {
+ e.preventDefault();
+ if( !fde ) { fde = e.dataTransfer.dropEffect; }
+ };
+ fuchsia.ondragover = function (e) {
+ e.preventDefault();
+ if( !fdo ) { fdo = e.dataTransfer.dropEffect; }
+ };
+ fuchsia.ondrop = function (e) {
+ e.preventDefault();
+ fdr = e.dataTransfer.dropEffect;
+ };
+ orange.ondragend = function (e) {
+ var ode = e.dataTransfer.dropEffect, temparray;
+ if( bde == bdo && bdo2 == fdr && fde == fdr && fdo == fdr && ode == fdr ) {
+ if( bde == fdr ) {
+ tmparray = [fdr];
+ } else {
+ tmparray = [bde,fdr];
+ }
+ } else if( bde == bdo && bdo2 == fdo && fde == fdo && !fdr ) {
+ tmparray = [bde,fdo,ode];
+ } else {
+ tmparray = [bde,bdo,bdo2,fde,fdo,fdr,ode];
+ }
+ tmparray[ tmparray.length - 1 ] = '<strong>' + tmparray[ tmparray.length - 1 ] + '<\/strong>';
+ document.getElementsByTagName('div')[3].innerHTML = (++countedDrops) + '. ' + tmparray.join('=&gt;');
+ };
+};
+ </script>
+ </head>
+ <body>
+
+ <div draggable="true"></div>
+ <div></div>
+ <div></div>
+ <div><strong>&nbsp;</strong></div>
+ <ol>
+ <li>Drag the orange square over the blue square</li>
+ <li>Press the relevant modifier keys for your platform</li>
+ <li>Continue dragging over the pink square</li>
+ <li>Release the drag, then the keys</li>
+ <li>Check that the correct drop effect is produced in each case. If the mouse cursor can change to indicate the final type of drop effect that will take place, it should change to the relevant type (the one in bold) once the modifier keys are pressed.</li>
+ </ol>
+ <!-- Windows Explorer uses Ctrl for copy, Shift for move, Alt or Ctrl+Shift for link. -->
+ <!-- Anything else invalidates the modifiers, and reverts to default. -->
+ <table>
+ <caption>Windows</caption>
+ <thead>
+ <tr><th>Modifier</th><th>Drop effect</th></tr>
+ </thead>
+ <tbody>
+ <tr><td>None</td><td><strong>copy</strong></td></tr>
+ <tr><td>Ctrl</td><td><strong>copy</strong></td></tr>
+ <tr><td>Shift</td><td>copy=&gt;<strong>move</strong></td></tr>
+ <tr><td>Alt</td><td>copy=&gt;link=&gt;<strong>none</strong></td></tr>
+ <tr><td>Ctrl+Shift</td><td>copy=&gt;link=&gt;<strong>none</strong></td></tr>
+ <tr><td>Ctrl+Alt</td><td><strong>copy</strong></td></tr>
+ <tr><td>Alt+Shift</td><td><strong>copy</strong></td></tr>
+ <tr><td>Ctrl+Alt+Shift</td><td><strong>copy</strong></td></tr>
+ </tbody>
+ </table>
+ <!-- KDE Konqueror uses Ctrl for copy, Shift for move, Ctrl+Shift for link. -->
+ <!-- Anything else is ignored completely, and has no effect on the modifier sequence. -->
+ <!-- Gnome Nautilus uses Ctrl for copy, Shift for move, Ctrl+Shift for link (and Alt to open a context menu). -->
+ <!-- Anything else (including Alt when combined with other modifiers) is ignored completely, and has no effect on the modifier sequence. -->
+ <table>
+ <caption>Unix/Linux</caption>
+ <thead>
+ <tr><th>Modifier</th><th>Drop effect</th></tr>
+ </thead>
+ <tbody>
+ <tr><td><strong>none</td><td><strong>copy</strong></td></tr>
+ <tr><td>Ctrl</td><td><strong>copy</strong></td></tr>
+ <tr><td>Shift</td><td>copy=&gt;<strong>move</strong></td></tr>
+ <tr><td>Alt</td><td><strong>copy</strong></td></tr>
+ <tr><td>Ctrl+Shift</td><td>copy=&gt;link=&gt;<strong>none</strong></td></tr>
+ <tr><td>Ctrl+Alt</td><td><strong>copy</strong></td></tr>
+ <tr><td>Alt+Shift</td><td>copy=&gt;<strong>move</strong></td></tr>
+ <tr><td>Ctrl+Alt+Shift</td><td>copy=&gt;link=&gt;<strong>none</strong></td></tr>
+ </tbody>
+ </table>
+ <!-- Mac Finder uses Option for copy, Command for move, Command+Option for link. -->
+ <!-- Anything else is ignored completely, and has no effect on the modifier sequence. -->
+ <table>
+ <caption>Mac</caption>
+ <thead>
+ <tr><th>Modifier</th><th>Drop effect</th></tr>
+ </thead>
+ <tbody>
+ <tr><td><strong>none</td><td><strong>copy</strong></td></tr>
+ <tr><td>Ctrl</td><td><strong>copy</strong></td></tr>
+ <tr><td>Shift</td><td><strong>copy</strong></td></tr>
+ <tr><td>Option/alt</td><td><strong>copy</strong></td></tr>
+ <tr><td>Command</td><td>copy=&gt;<strong>move</strong></td></tr>
+
+ <tr><td>Ctrl+Shift</td><td><strong>copy</strong></td></tr>
+ <tr><td>Ctrl+Option</td><td><strong>copy</strong></td></tr>
+ <tr><td>Ctrl+Command</td><td>copy=&gt;<strong>move</strong></td></tr>
+ <tr><td>Shift+Option</td><td><strong>copy</strong></td></tr>
+ <tr><td>Shift+Command</td><td>copy=&gt;<strong>move</strong></td></tr>
+ <tr><td>Command+Option</td><td>copy=&gt;link=&gt;<strong>none</strong></td></tr>
+
+ <tr><td>Ctrl+Shift+Option</td><td><strong>copy</strong></td></tr>
+ <tr><td>Ctrl+Shift+Command</td><td>copy=&gt;<strong>move</strong></td></tr>
+ <tr><td>Ctrl+Command+Option</td><td>copy=&gt;link=&gt;<strong>none</strong></td></tr>
+ <tr><td>Shift+Command+Option</td><td>copy=&gt;link=&gt;<strong>none</strong></td></tr>
+
+ <tr><td>Ctrl+Shift+Command+Option</td><td>copy=&gt;link=&gt;<strong>none</strong></td></tr>
+ </tbody>
+ </table>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/modifiers/link.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/modifiers/link.html
new file mode 100644
index 00000000000..d5281a4b465
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/modifiers/link.html
@@ -0,0 +1,175 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Modifier keys selecting dropEffect with 'link'</title>
+ <style type="text/css">
+div:first-child {
+ height: 100px;
+ width: 100px;
+ background: orange;
+ display: inline-block;
+}
+div:first-child + div {
+ height: 100px;
+ width: 100px;
+ background: blue;
+ display: inline-block;
+}
+div:first-child + div + div {
+ height: 100px;
+ width: 100px;
+ background: fuchsia;
+ display: inline-block;
+}
+table {
+ display: inline-table;
+ margin-right: 1em;
+ border-collapse: collapse;
+}
+table, th, td {
+ border: 1px solid black;
+}
+thead th {
+ background: silver;
+ color: black;
+}
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ var countedDrops = 0, bde, bdo, bdo2, fde, fdo, fdr;
+ var orange = document.getElementsByTagName('div')[0];
+ orange.ondragstart = function (e) {
+ e.dataTransfer.setData('text','http://example.com/');
+ e.dataTransfer.effectAllowed = 'link';
+ bde = bdo = bdo2 = fde = fdo = fdr = '';
+ };
+ var blue = document.getElementsByTagName('div')[1];
+ blue.ondragenter = function (e) {
+ e.preventDefault();
+ if( !bde ) { bde = e.dataTransfer.dropEffect; }
+ };
+ blue.ondragover = function (e) {
+ e.preventDefault();
+ if( !bdo ) {
+ bdo = e.dataTransfer.dropEffect;
+ }
+ //bdo2 always collects dropEffect, since it can change multiple times in rapid succession when pressing multiple modifiers
+ //test cares about the last dropEffect that was seen before leaving the blue square, and that will be stored in bdo2
+ bdo2 = e.dataTransfer.dropEffect;
+ };
+ var fuchsia = document.getElementsByTagName('div')[2];
+ fuchsia.ondragenter = function (e) {
+ e.preventDefault();
+ if( !fde ) { fde = e.dataTransfer.dropEffect; }
+ };
+ fuchsia.ondragover = function (e) {
+ e.preventDefault();
+ if( !fdo ) { fdo = e.dataTransfer.dropEffect; }
+ };
+ fuchsia.ondrop = function (e) {
+ e.preventDefault();
+ fdr = e.dataTransfer.dropEffect;
+ };
+ orange.ondragend = function (e) {
+ var ode = e.dataTransfer.dropEffect, temparray;
+ if( bde == bdo && bdo2 == fdr && fde == fdr && fdo == fdr && ode == fdr ) {
+ if( bde == fdr ) {
+ tmparray = [fdr];
+ } else {
+ tmparray = [bde,fdr];
+ }
+ } else if( bde == bdo && bdo2 == fdo && fde == fdo && !fdr ) {
+ tmparray = [bde,fdo,ode];
+ } else {
+ tmparray = [bde,bdo,bdo2,fde,fdo,fdr,ode];
+ }
+ tmparray[ tmparray.length - 1 ] = '<strong>' + tmparray[ tmparray.length - 1 ] + '<\/strong>';
+ document.getElementsByTagName('div')[3].innerHTML = (++countedDrops) + '. ' + tmparray.join('=&gt;');
+ };
+};
+ </script>
+ </head>
+ <body>
+
+ <div draggable="true"></div>
+ <div></div>
+ <div></div>
+ <div><strong>&nbsp;</strong></div>
+ <ol>
+ <li>Drag the orange square over the blue square</li>
+ <li>Press the relevant modifier keys for your platform</li>
+ <li>Continue dragging over the pink square</li>
+ <li>Release the drag, then the keys</li>
+ <li>Check that the correct drop effect is produced in each case. If the mouse cursor can change to indicate the final type of drop effect that will take place, it should change to the relevant type (the one in bold) once the modifier keys are pressed.</li>
+ </ol>
+ <!-- Windows Explorer uses Ctrl for copy, Shift for move, Alt or Ctrl+Shift for link. -->
+ <!-- Anything else invalidates the modifiers, and reverts to default. -->
+ <table>
+ <caption>Windows</caption>
+ <thead>
+ <tr><th>Modifier</th><th>Drop effect</th></tr>
+ </thead>
+ <tbody>
+ <tr><td>None</td><td><strong>link</strong></td></tr>
+ <tr><td>Ctrl</td><td>link=&gt;copy=&gt;<strong>none</strong></td></tr>
+ <tr><td>Shift</td><td>link=&gt;move=&gt;<strong>none</strong></td></tr>
+ <tr><td>Alt</td><td><strong>link</strong></td></tr>
+ <tr><td>Ctrl+Shift</td><td><strong>link</strong></td></tr>
+ <tr><td>Ctrl+Alt</td><td><strong>link</strong></td></tr>
+ <tr><td>Alt+Shift</td><td><strong>link</strong></td></tr>
+ <tr><td>Ctrl+Alt+Shift</td><td><strong>link</strong></td></tr>
+ </tbody>
+ </table>
+ <!-- KDE Konqueror uses Ctrl for copy, Shift for move, Ctrl+Shift for link. -->
+ <!-- Anything else is ignored completely, and has no effect on the modifier sequence. -->
+ <!-- Gnome Nautilus uses Ctrl for copy, Shift for move, Ctrl+Shift for link (and Alt to open a context menu). -->
+ <!-- Anything else (including Alt when combined with other modifiers) is ignored completely, and has no effect on the modifier sequence. -->
+ <table>
+ <caption>Unix/Linux</caption>
+ <thead>
+ <tr><th>Modifier</th><th>Drop effect</th></tr>
+ </thead>
+ <tbody>
+ <tr><td><strong>none</td><td><strong>link</strong></td></tr>
+ <tr><td>Ctrl</td><td>link=&gt;copy=&gt;<strong>none</strong></td></tr>
+ <tr><td>Shift</td><td>link=&gt;move=&gt;<strong>none</strong></td></tr>
+ <tr><td>Alt</td><td><strong>link</strong></td></tr>
+ <tr><td>Ctrl+Shift</td><td><strong>link</strong></td></tr>
+ <tr><td>Ctrl+Alt</td><td>link=&gt;copy=&gt;<strong>none</strong></td></tr>
+ <tr><td>Alt+Shift</td><td>link=&gt;move=&gt;<strong>none</strong></td></tr>
+ <tr><td>Ctrl+Alt+Shift</td><td><strong>link</strong></td></tr>
+ </tbody>
+ </table>
+ <!-- Mac Finder uses Option for copy, Command for move, Command+Option for link. -->
+ <!-- Anything else is ignored completely, and has no effect on the modifier sequence. -->
+ <table>
+ <caption>Mac</caption>
+ <thead>
+ <tr><th>Modifier</th><th>Drop effect</th></tr>
+ </thead>
+ <tbody>
+ <tr><td><strong>none</td><td><strong>link</strong></td></tr>
+ <tr><td>Ctrl</td><td><strong>link</strong></td></tr>
+ <tr><td>Shift</td><td><strong>link</strong></td></tr>
+ <tr><td>Option/alt</td><td>link=&gt;copy=&gt;<strong>none</strong></td></tr>
+ <tr><td>Command</td><td>link=&gt;move=&gt;<strong>none</strong></td></tr>
+
+ <tr><td>Ctrl+Shift</td><td><strong>link</strong></td></tr>
+ <tr><td>Ctrl+Option</td><td>link=&gt;copy=&gt;<strong>none</strong></td></tr>
+ <tr><td>Ctrl+Command</td><td>link=&gt;move=&gt;<strong>none</strong></td></tr>
+ <tr><td>Shift+Option</td><td>link=&gt;copy=&gt;<strong>none</strong></td></tr>
+ <tr><td>Shift+Command</td><td>link=&gt;move=&gt;<strong>none</strong></td></tr>
+ <tr><td>Command+Option</td><td><strong>link</strong></td></tr>
+
+ <tr><td>Ctrl+Shift+Option</td><td>link=&gt;copy=&gt;<strong>none</strong></td></tr>
+ <tr><td>Ctrl+Shift+Command</td><td>link=&gt;move=&gt;<strong>none</strong></td></tr>
+ <tr><td>Ctrl+Command+Option</td><td><strong>link</strong></td></tr>
+ <tr><td>Shift+Command+Option</td><td><strong>link</strong></td></tr>
+
+ <tr><td>Ctrl+Shift+Command+Option</td><td><strong>link</strong></td></tr>
+ </tbody>
+ </table>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/modifiers/linkmove.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/modifiers/linkmove.html
new file mode 100644
index 00000000000..3e19f10de20
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/modifiers/linkmove.html
@@ -0,0 +1,175 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Modifier keys selecting dropEffect with 'linkMove'</title>
+ <style type="text/css">
+div:first-child {
+ height: 100px;
+ width: 100px;
+ background: orange;
+ display: inline-block;
+}
+div:first-child + div {
+ height: 100px;
+ width: 100px;
+ background: blue;
+ display: inline-block;
+}
+div:first-child + div + div {
+ height: 100px;
+ width: 100px;
+ background: fuchsia;
+ display: inline-block;
+}
+table {
+ display: inline-table;
+ margin-right: 1em;
+ border-collapse: collapse;
+}
+table, th, td {
+ border: 1px solid black;
+}
+thead th {
+ background: silver;
+ color: black;
+}
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ var countedDrops = 0, bde, bdo, bdo2, fde, fdo, fdr;
+ var orange = document.getElementsByTagName('div')[0];
+ orange.ondragstart = function (e) {
+ e.dataTransfer.setData('text','http://example.com/');
+ e.dataTransfer.effectAllowed = 'linkMove';
+ bde = bdo = bdo2 = fde = fdo = fdr = '';
+ };
+ var blue = document.getElementsByTagName('div')[1];
+ blue.ondragenter = function (e) {
+ e.preventDefault();
+ if( !bde ) { bde = e.dataTransfer.dropEffect; }
+ };
+ blue.ondragover = function (e) {
+ e.preventDefault();
+ if( !bdo ) {
+ bdo = e.dataTransfer.dropEffect;
+ }
+ //bdo2 always collects dropEffect, since it can change multiple times in rapid succession when pressing multiple modifiers
+ //test cares about the last dropEffect that was seen before leaving the blue square, and that will be stored in bdo2
+ bdo2 = e.dataTransfer.dropEffect;
+ };
+ var fuchsia = document.getElementsByTagName('div')[2];
+ fuchsia.ondragenter = function (e) {
+ e.preventDefault();
+ if( !fde ) { fde = e.dataTransfer.dropEffect; }
+ };
+ fuchsia.ondragover = function (e) {
+ e.preventDefault();
+ if( !fdo ) { fdo = e.dataTransfer.dropEffect; }
+ };
+ fuchsia.ondrop = function (e) {
+ e.preventDefault();
+ fdr = e.dataTransfer.dropEffect;
+ };
+ orange.ondragend = function (e) {
+ var ode = e.dataTransfer.dropEffect, temparray;
+ if( bde == bdo && bdo2 == fdr && fde == fdr && fdo == fdr && ode == fdr ) {
+ if( bde == fdr ) {
+ tmparray = [fdr];
+ } else {
+ tmparray = [bde,fdr];
+ }
+ } else if( bde == bdo && bdo2 == fdo && fde == fdo && !fdr ) {
+ tmparray = [bde,fdo,ode];
+ } else {
+ tmparray = [bde,bdo,bdo2,fde,fdo,fdr,ode];
+ }
+ tmparray[ tmparray.length - 1 ] = '<strong>' + tmparray[ tmparray.length - 1 ] + '<\/strong>';
+ document.getElementsByTagName('div')[3].innerHTML = (++countedDrops) + '. ' + tmparray.join('=&gt;');
+ };
+};
+ </script>
+ </head>
+ <body>
+
+ <div draggable="true"></div>
+ <div></div>
+ <div></div>
+ <div><strong>&nbsp;</strong></div>
+ <ol>
+ <li>Drag the orange square over the blue square</li>
+ <li>Press the relevant modifier keys for your platform</li>
+ <li>Continue dragging over the pink square</li>
+ <li>Release the drag, then the keys</li>
+ <li>Check that the correct drop effect is produced in each case. If the mouse cursor can change to indicate the final type of drop effect that will take place, it should change to the relevant type (the one in bold) once the modifier keys are pressed.</li>
+ </ol>
+ <!-- Windows Explorer uses Ctrl for copy, Shift for move, Alt or Ctrl+Shift for link. -->
+ <!-- Anything else invalidates the modifiers, and reverts to default. -->
+ <table>
+ <caption>Windows</caption>
+ <thead>
+ <tr><th>Modifier</th><th>Drop effect</th></tr>
+ </thead>
+ <tbody>
+ <tr><td>None</td><td><strong>link</strong></td></tr>
+ <tr><td>Ctrl</td><td>link=&gt;copy=&gt;<strong>none</strong></td></tr>
+ <tr><td>Shift</td><td>link=&gt;<strong>move</strong></td></tr>
+ <tr><td>Alt</td><td><strong>link</strong></td></tr>
+ <tr><td>Ctrl+Shift</td><td><strong>link</strong></td></tr>
+ <tr><td>Ctrl+Alt</td><td><strong>link</strong></td></tr>
+ <tr><td>Alt+Shift</td><td><strong>link</strong></td></tr>
+ <tr><td>Ctrl+Alt+Shift</td><td><strong>link</strong></td></tr>
+ </tbody>
+ </table>
+ <!-- KDE Konqueror uses Ctrl for copy, Shift for move, Ctrl+Shift for link. -->
+ <!-- Anything else is ignored completely, and has no effect on the modifier sequence. -->
+ <!-- Gnome Nautilus uses Ctrl for copy, Shift for move, Ctrl+Shift for link (and Alt to open a context menu). -->
+ <!-- Anything else (including Alt when combined with other modifiers) is ignored completely, and has no effect on the modifier sequence. -->
+ <table>
+ <caption>Unix/Linux</caption>
+ <thead>
+ <tr><th>Modifier</th><th>Drop effect</th></tr>
+ </thead>
+ <tbody>
+ <tr><td><strong>none</td><td><strong>link</strong></td></tr>
+ <tr><td>Ctrl</td><td>link=&gt;copy=&gt;<strong>none</strong></td></tr>
+ <tr><td>Shift</td><td>link=&gt;<strong>move</strong></td></tr>
+ <tr><td>Alt</td><td><strong>link</strong></td></tr>
+ <tr><td>Ctrl+Shift</td><td><strong>link</strong></td></tr>
+ <tr><td>Ctrl+Alt</td><td>link=&gt;copy=&gt;<strong>none</strong></td></tr>
+ <tr><td>Alt+Shift</td><td>link=&gt;<strong>move</strong></td></tr>
+ <tr><td>Ctrl+Alt+Shift</td><td><strong>link</strong></td></tr>
+ </tbody>
+ </table>
+ <!-- Mac Finder uses Option for copy, Command for move, Command+Option for link. -->
+ <!-- Anything else is ignored completely, and has no effect on the modifier sequence. -->
+ <table>
+ <caption>Mac</caption>
+ <thead>
+ <tr><th>Modifier</th><th>Drop effect</th></tr>
+ </thead>
+ <tbody>
+ <tr><td><strong>none</td><td><strong>link</strong></td></tr>
+ <tr><td>Ctrl</td><td><strong>link</strong></td></tr>
+ <tr><td>Shift</td><td><strong>link</strong></td></tr>
+ <tr><td>Option/alt</td><td>link=&gt;copy=&gt;<strong>none</strong></td></tr>
+ <tr><td>Command</td><td>link=&gt;<strong>move</strong></td></tr>
+
+ <tr><td>Ctrl+Shift</td><td><strong>link</strong></td></tr>
+ <tr><td>Ctrl+Option</td><td>link=&gt;copy=&gt;<strong>none</strong></td></tr>
+ <tr><td>Ctrl+Command</td><td>link=&gt;<strong>move</strong></td></tr>
+ <tr><td>Shift+Option</td><td>link=&gt;copy=&gt;<strong>none</strong></td></tr>
+ <tr><td>Shift+Command</td><td>link=&gt;<strong>move</strong></td></tr>
+ <tr><td>Command+Option</td><td><strong>link</strong></td></tr>
+
+ <tr><td>Ctrl+Shift+Option</td><td>link=&gt;copy=&gt;<strong>none</strong></td></tr>
+ <tr><td>Ctrl+Shift+Command</td><td>link=&gt;<strong>move</strong></td></tr>
+ <tr><td>Ctrl+Command+Option</td><td><strong>link</strong></td></tr>
+ <tr><td>Shift+Command+Option</td><td><strong>link</strong></td></tr>
+
+ <tr><td>Ctrl+Shift+Command+Option</td><td><strong>link</strong></td></tr>
+ </tbody>
+ </table>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/modifiers/move.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/modifiers/move.html
new file mode 100644
index 00000000000..ca3e83c24a2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/modifiers/move.html
@@ -0,0 +1,175 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Modifier keys selecting dropEffect with 'move'</title>
+ <style type="text/css">
+div:first-child {
+ height: 100px;
+ width: 100px;
+ background: orange;
+ display: inline-block;
+}
+div:first-child + div {
+ height: 100px;
+ width: 100px;
+ background: blue;
+ display: inline-block;
+}
+div:first-child + div + div {
+ height: 100px;
+ width: 100px;
+ background: fuchsia;
+ display: inline-block;
+}
+table {
+ display: inline-table;
+ margin-right: 1em;
+ border-collapse: collapse;
+}
+table, th, td {
+ border: 1px solid black;
+}
+thead th {
+ background: silver;
+ color: black;
+}
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ var countedDrops = 0, bde, bdo, bdo2, fde, fdo, fdr;
+ var orange = document.getElementsByTagName('div')[0];
+ orange.ondragstart = function (e) {
+ e.dataTransfer.setData('text','http://example.com/');
+ e.dataTransfer.effectAllowed = 'move';
+ bde = bdo = bdo2 = fde = fdo = fdr = '';
+ };
+ var blue = document.getElementsByTagName('div')[1];
+ blue.ondragenter = function (e) {
+ e.preventDefault();
+ if( !bde ) { bde = e.dataTransfer.dropEffect; }
+ };
+ blue.ondragover = function (e) {
+ e.preventDefault();
+ if( !bdo ) {
+ bdo = e.dataTransfer.dropEffect;
+ }
+ //bdo2 always collects dropEffect, since it can change multiple times in rapid succession when pressing multiple modifiers
+ //test cares about the last dropEffect that was seen before leaving the blue square, and that will be stored in bdo2
+ bdo2 = e.dataTransfer.dropEffect;
+ };
+ var fuchsia = document.getElementsByTagName('div')[2];
+ fuchsia.ondragenter = function (e) {
+ e.preventDefault();
+ if( !fde ) { fde = e.dataTransfer.dropEffect; }
+ };
+ fuchsia.ondragover = function (e) {
+ e.preventDefault();
+ if( !fdo ) { fdo = e.dataTransfer.dropEffect; }
+ };
+ fuchsia.ondrop = function (e) {
+ e.preventDefault();
+ fdr = e.dataTransfer.dropEffect;
+ };
+ orange.ondragend = function (e) {
+ var ode = e.dataTransfer.dropEffect, temparray;
+ if( bde == bdo && bdo2 == fdr && fde == fdr && fdo == fdr && ode == fdr ) {
+ if( bde == fdr ) {
+ tmparray = [fdr];
+ } else {
+ tmparray = [bde,fdr];
+ }
+ } else if( bde == bdo && bdo2 == fdo && fde == fdo && !fdr ) {
+ tmparray = [bde,fdo,ode];
+ } else {
+ tmparray = [bde,bdo,bdo2,fde,fdo,fdr,ode];
+ }
+ tmparray[ tmparray.length - 1 ] = '<strong>' + tmparray[ tmparray.length - 1 ] + '<\/strong>';
+ document.getElementsByTagName('div')[3].innerHTML = (++countedDrops) + '. ' + tmparray.join('=&gt;');
+ };
+};
+ </script>
+ </head>
+ <body>
+
+ <div draggable="true"></div>
+ <div></div>
+ <div></div>
+ <div><strong>&nbsp;</strong></div>
+ <ol>
+ <li>Drag the orange square over the blue square</li>
+ <li>Press the relevant modifier keys for your platform</li>
+ <li>Continue dragging over the pink square</li>
+ <li>Release the drag, then the keys</li>
+ <li>Check that the correct drop effect is produced in each case. If the mouse cursor can change to indicate the final type of drop effect that will take place, it should change to the relevant type (the one in bold) once the modifier keys are pressed.</li>
+ </ol>
+ <!-- Windows Explorer uses Ctrl for copy, Shift for move, Alt or Ctrl+Shift for link. -->
+ <!-- Anything else invalidates the modifiers, and reverts to default. -->
+ <table>
+ <caption>Windows</caption>
+ <thead>
+ <tr><th>Modifier</th><th>Drop effect</th></tr>
+ </thead>
+ <tbody>
+ <tr><td>None</td><td><strong>move</strong></td></tr>
+ <tr><td>Ctrl</td><td>move=&gt;copy=&gt;<strong>none</strong></td></tr>
+ <tr><td>Shift</td><td><strong>move</strong></td></tr>
+ <tr><td>Alt</td><td>move=&gt;link=&gt;<strong>none</strong></td></tr>
+ <tr><td>Ctrl+Shift</td><td>move=&gt;link=&gt;<strong>none</strong></td></tr>
+ <tr><td>Ctrl+Alt</td><td><strong>move</strong></td></tr>
+ <tr><td>Alt+Shift</td><td><strong>move</strong></td></tr>
+ <tr><td>Ctrl+Alt+Shift</td><td><strong>move</strong></td></tr>
+ </tbody>
+ </table>
+ <!-- KDE Konqueror uses Ctrl for copy, Shift for move, Ctrl+Shift for link. -->
+ <!-- Anything else is ignored completely, and has no effect on the modifier sequence. -->
+ <!-- Gnome Nautilus uses Ctrl for copy, Shift for move, Ctrl+Shift for link (and Alt to open a context menu). -->
+ <!-- Anything else (including Alt when combined with other modifiers) is ignored completely, and has no effect on the modifier sequence. -->
+ <table>
+ <caption>Unix/Linux</caption>
+ <thead>
+ <tr><th>Modifier</th><th>Drop effect</th></tr>
+ </thead>
+ <tbody>
+ <tr><td><strong>none</td><td><strong>move</strong></td></tr>
+ <tr><td>Ctrl</td><td>move=&gt;copy=&gt;<strong>none</strong></td></tr>
+ <tr><td>Shift</td><td><strong>move</strong></td></tr>
+ <tr><td>Alt</td><td><strong>move</strong></td></tr>
+ <tr><td>Ctrl+Shift</td><td>move=&gt;link=&gt;<strong>none</strong></td></tr>
+ <tr><td>Ctrl+Alt</td><td>move=&gt;copy=&gt;<strong>none</strong></td></tr>
+ <tr><td>Alt+Shift</td><td><strong>move</strong></td></tr>
+ <tr><td>Ctrl+Alt+Shift</td><td>move=&gt;link=&gt;<strong>none</strong></td></tr>
+ </tbody>
+ </table>
+ <!-- Mac Finder uses Option for copy, Command for move, Command+Option for link. -->
+ <!-- Anything else is ignored completely, and has no effect on the modifier sequence. -->
+ <table>
+ <caption>Mac</caption>
+ <thead>
+ <tr><th>Modifier</th><th>Drop effect</th></tr>
+ </thead>
+ <tbody>
+ <tr><td><strong>none</td><td><strong>move</strong></td></tr>
+ <tr><td>Ctrl</td><td><strong>move</strong></td></tr>
+ <tr><td>Shift</td><td><strong>move</strong></td></tr>
+ <tr><td>Option/alt</td><td>move=&gt;copy=&gt;<strong>none</strong></td></tr>
+ <tr><td>Command</td><td><strong>move</strong></td></tr>
+
+ <tr><td>Ctrl+Shift</td><td><strong>move</strong></td></tr>
+ <tr><td>Ctrl+Option</td><td>move=&gt;copy=&gt;<strong>none</strong></td></tr>
+ <tr><td>Ctrl+Command</td><td><strong>move</strong></td></tr>
+ <tr><td>Shift+Option</td><td>move=&gt;copy=&gt;<strong>none</strong></td></tr>
+ <tr><td>Shift+Command</td><td><strong>move</strong></td></tr>
+ <tr><td>Command+Option</td><td>move=&gt;link=&gt;<strong>none</strong></td></tr>
+
+ <tr><td>Ctrl+Shift+Option</td><td>move=&gt;copy=&gt;<strong>none</strong></td></tr>
+ <tr><td>Ctrl+Shift+Command</td><td><strong>move</strong></td></tr>
+ <tr><td>Ctrl+Command+Option</td><td>move=&gt;link=&gt;<strong>none</strong></td></tr>
+ <tr><td>Shift+Command+Option</td><td>move=&gt;link=&gt;<strong>none</strong></td></tr>
+
+ <tr><td>Ctrl+Shift+Command+Option</td><td>move=&gt;link=&gt;<strong>none</strong></td></tr>
+ </tbody>
+ </table>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/modifiers/onlydropzone.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/modifiers/onlydropzone.html
new file mode 100644
index 00000000000..f5c7bab061d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/modifiers/onlydropzone.html
@@ -0,0 +1,70 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Modifier keys being used with a dropzone attribute</title>
+ <style type="text/css">
+div:first-child {
+ height: 100px;
+ width: 100px;
+ background: orange;
+ display: inline-block;
+}
+div:first-child + div {
+ height: 100px;
+ width: 100px;
+ background: blue;
+ display: inline-block;
+}
+div:first-child + div + div {
+ height: 100px;
+ width: 100px;
+ background: fuchsia;
+ display: inline-block;
+}
+table {
+ display: inline-table;
+ margin-right: 1em;
+ border-collapse: collapse;
+}
+table, th, td {
+ border: 1px solid black;
+}
+thead th {
+ background: silver;
+ color: black;
+}
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ var orange = document.getElementsByTagName('div')[0];
+ orange.ondragstart = function (e) {
+ e.dataTransfer.setData('text/plain','http://example.com/');
+ e.dataTransfer.effectAllowed = 'copy';
+ };
+ var fuchsia = document.getElementsByTagName('div')[2];
+ fuchsia.ondrop = function (e) {
+ //dropzone overrides the modifier, always, and ignores effectAllowed
+ e.preventDefault();
+ document.getElementsByTagName('div')[3].innerHTML = ( e.dataTransfer.dropEffect == 'link' ) ? 'PASS' : 'FAIL';
+ };
+};
+ </script>
+ </head>
+ <body>
+
+ <div draggable="true"></div>
+ <div></div>
+ <div dropzone="link string:text/plain"></div>
+ <div>&nbsp;</div>
+ <ol>
+ <li>Drag the orange square over the blue square</li>
+ <li>Press the relevant modifier keys for your platform to request a &quot;move&quot; drop effect (eg. Shift on Windows/Unix/Linux, Command on Mac)</li>
+ <li>Continue dragging over the pink square</li>
+ <li>If supported by the platform, the mouse cursor should show that a &quot;link&quot; drop effect will be used</li>
+ <li>Release the drag, then the keys</li>
+ <li>Fail if no new text appears above this list</li>
+ </ol>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/modifiers/onlydropzoneevents.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/modifiers/onlydropzoneevents.html
new file mode 100644
index 00000000000..a8033603267
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/modifiers/onlydropzoneevents.html
@@ -0,0 +1,82 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Modifier keys being used with a dropzone attribute and dragenter/dragover events</title>
+ <style type="text/css">
+div:first-child {
+ height: 100px;
+ width: 100px;
+ background: orange;
+ display: inline-block;
+}
+div:first-child + div {
+ height: 100px;
+ width: 100px;
+ background: blue;
+ display: inline-block;
+}
+div:first-child + div + div {
+ height: 100px;
+ width: 100px;
+ background: fuchsia;
+ display: inline-block;
+}
+table {
+ display: inline-table;
+ margin-right: 1em;
+ border-collapse: collapse;
+}
+table, th, td {
+ border: 1px solid black;
+}
+thead th {
+ background: silver;
+ color: black;
+}
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ var orange = document.getElementsByTagName('div')[0];
+ orange.ondragstart = function (e) {
+ e.dataTransfer.setData('text/plain','http://example.com/');
+ e.dataTransfer.effectAllowed = 'copy';
+ };
+ var fuchsia = document.getElementsByTagName('div')[2], fde, fdo;
+ fuchsia.ondragenter = function (e) {
+ fde = e.dataTransfer.dropEffect;
+ };
+ fuchsia.ondragover = function (e) {
+ fdo = e.dataTransfer.dropEffect;
+ };
+ fuchsia.ondrop = function (e) {
+ //dropzone overrides the modifier, always, and ignores effectAllowed
+ e.preventDefault();
+ var sequence = ([fde,fdo,e.dataTransfer.dropEffect]).join('=&gt;')
+ var desiredsequence = (['move','move','link']).join('=&gt;')
+ if( sequence == desiredsequence ) {
+ document.getElementsByTagName('div')[3].innerHTML = 'PASS';
+ } else {
+ document.getElementsByTagName('div')[3].innerHTML = 'FAIL, got:<br>'+sequence+'<br>instead of:<br>'+desiredsequence;
+ }
+ };
+};
+ </script>
+ </head>
+ <body>
+
+ <div draggable="true"></div>
+ <div></div>
+ <div dropzone="link string:text/plain"></div>
+ <div>&nbsp;</div>
+ <ol>
+ <li>Drag the orange square over the blue square</li>
+ <li>Press the relevant modifier keys for your platform to request a &quot;move&quot; drop effect (eg. Shift on Windows/Unix/Linux, Command on Mac)</li>
+ <li>Continue dragging over the pink square</li>
+ <li>If supported by the platform, the mouse cursor should show that a &quot;link&quot; drop effect will be used</li>
+ <li>Release the drag, then the keys</li>
+ <li>Fail if no new text appears above this list</li>
+ </ol>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/modifiers/releasemodifiersdrag.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/modifiers/releasemodifiersdrag.html
new file mode 100644
index 00000000000..3468d0a53fd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/modifiers/releasemodifiersdrag.html
@@ -0,0 +1,125 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Modifier keys being released before end of drag</title>
+ <style type="text/css">
+div:first-child {
+ height: 100px;
+ width: 100px;
+ background: orange;
+ display: inline-block;
+}
+div:first-child + div {
+ height: 100px;
+ width: 100px;
+ background: blue;
+ display: inline-block;
+}
+div:first-child + div + div {
+ height: 100px;
+ width: 100px;
+ background: fuchsia;
+ display: inline-block;
+}
+div:first-child + div + div + div {
+ height: 100px;
+ width: 100px;
+ background: yellow;
+ display: inline-block;
+}
+div {
+ font-family: monospace;
+}
+table {
+ display: inline-table;
+ margin-right: 1em;
+ border-collapse: collapse;
+}
+table, th, td {
+ border: 1px solid black;
+}
+thead th {
+ background: silver;
+ color: black;
+}
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ var bde, bdo, bdo2, fde, fdo, fdo2, yde, ydo, ydr;
+ var orange = document.getElementsByTagName('div')[0];
+ orange.ondragstart = function (e) {
+ e.dataTransfer.setData('text','http://example.com/');
+ e.dataTransfer.effectAllowed = 'linkMove';
+ bde = bdo = bdo2 = fde = fdo = fdo2 = yde = ydo = ydr = '';
+ };
+ var blue = document.getElementsByTagName('div')[1];
+ blue.ondragenter = function (e) {
+ e.preventDefault();
+ bde = e.dataTransfer.dropEffect;
+ };
+ blue.ondragover = function (e) {
+ e.preventDefault();
+ if( !bdo ) {
+ bdo = e.dataTransfer.dropEffect;
+ }
+ //bdo2 always collects dropEffect, since it can change multiple times in rapid succession when pressing multiple modifiers
+ //test cares about the last dropEffect that was seen before leaving the blue square, and that will be stored in bdo2
+ bdo2 = e.dataTransfer.dropEffect;
+ };
+ var fuchsia = document.getElementsByTagName('div')[2];
+ fuchsia.ondragenter = function (e) {
+ e.preventDefault();
+ fde = e.dataTransfer.dropEffect;
+ };
+ fuchsia.ondragover = function (e) {
+ e.preventDefault();
+ if( !fdo ) { fdo = e.dataTransfer.dropEffect; }
+ fdo2 = e.dataTransfer.dropEffect;
+ };
+ var yellow = document.getElementsByTagName('div')[3];
+ yellow.ondragenter = function (e) {
+ e.preventDefault();
+ yde = e.dataTransfer.dropEffect;
+ };
+ yellow.ondragover = function (e) {
+ e.preventDefault();
+ if( !ydo ) { ydo = e.dataTransfer.dropEffect; }
+ };
+ yellow.ondrop = function (e) {
+ e.preventDefault();
+ ydr = e.dataTransfer.dropEffect;
+ };
+ orange.ondragend = function (e) {
+ var sequence = ([bde,bdo,bdo2,fde,fdo,fdo2,yde,ydo,ydr,e.dataTransfer.dropEffect]).join('=&gt;')
+ var desiredsequence = (['link','link','move','move','move','link','link','link','link','link']).join('=&gt;')
+ if( sequence == desiredsequence ) {
+ document.getElementsByTagName('div')[4].innerHTML = 'PASS';
+ } else {
+ document.getElementsByTagName('div')[4].innerHTML = 'FAIL, got:<br>'+sequence+'<br>instead of:<br>'+desiredsequence;
+ }
+ };
+};
+ </script>
+ </head>
+ <body>
+
+ <div draggable="true"></div>
+ <div></div>
+ <div></div>
+ <div></div>
+ <div><strong>&nbsp;</strong></div>
+ <ol>
+ <li>Drag the orange square over the blue square</li>
+ <li>Press the relevant modifier keys for your platform to request a &quot;move&quot; drop effect (eg. Shift on Windows/Unix/Linux, Command on Mac)</li>
+ <li>If supported by the platform, the mouse cursor should show that a &quot;move&quot; drop effect will be used</li>
+ <li>Continue dragging over the pink square</li>
+ <li>Release the modifier keys</li>
+ <li>If supported by the platform, the mouse cursor should show that a &quot;link&quot; drop effect will be used</li>
+ <li>Continue dragging over the yellow square</li>
+ <li>Release the drag</li>
+ <li>Fail if no new text appears above this list</li>
+ </ol>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/modifiers/releasemodifiersdrop.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/modifiers/releasemodifiersdrop.html
new file mode 100644
index 00000000000..678a2139a6b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/modifiers/releasemodifiersdrop.html
@@ -0,0 +1,108 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Modifier keys being released before drop</title>
+ <style type="text/css">
+div:first-child {
+ height: 100px;
+ width: 100px;
+ background: orange;
+ display: inline-block;
+}
+div:first-child + div {
+ height: 100px;
+ width: 100px;
+ background: blue;
+ display: inline-block;
+}
+div:first-child + div + div {
+ height: 100px;
+ width: 100px;
+ background: fuchsia;
+ display: inline-block;
+}
+div {
+ font-family: monospace;
+}
+table {
+ display: inline-table;
+ margin-right: 1em;
+ border-collapse: collapse;
+}
+table, th, td {
+ border: 1px solid black;
+}
+thead th {
+ background: silver;
+ color: black;
+}
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ var bde, bdo, bdo2, fde, fdo, fdo2, fdr;
+ var orange = document.getElementsByTagName('div')[0];
+ orange.ondragstart = function (e) {
+ e.dataTransfer.setData('text','http://example.com/');
+ e.dataTransfer.effectAllowed = 'linkMove';
+ bde = bdo = bdo2 = fde = fdo = fdo2 = fdr = '';
+ };
+ var blue = document.getElementsByTagName('div')[1];
+ blue.ondragenter = function (e) {
+ e.preventDefault();
+ bde = e.dataTransfer.dropEffect;
+ };
+ blue.ondragover = function (e) {
+ e.preventDefault();
+ if( !bdo ) {
+ bdo = e.dataTransfer.dropEffect;
+ }
+ //bdo2 always collects dropEffect, since it can change multiple times in rapid succession when pressing multiple modifiers
+ //test cares about the last dropEffect that was seen before leaving the blue square, and that will be stored in bdo2
+ bdo2 = e.dataTransfer.dropEffect;
+ };
+ var fuchsia = document.getElementsByTagName('div')[2];
+ fuchsia.ondragenter = function (e) {
+ e.preventDefault();
+ fde = e.dataTransfer.dropEffect;
+ };
+ fuchsia.ondragover = function (e) {
+ e.preventDefault();
+ if( !fdo ) { fdo = e.dataTransfer.dropEffect; }
+ fdo2 = e.dataTransfer.dropEffect;
+ };
+ fuchsia.ondrop = function (e) {
+ e.preventDefault();
+ fdr = e.dataTransfer.dropEffect;
+ };
+ orange.ondragend = function (e) {
+ var sequence = ([bde,bdo,bdo2,fde,fdo,fdo2,fdr,e.dataTransfer.dropEffect]).join('=&gt;')
+ var desiredsequence = (['link','link','move','move','move','link','link','link']).join('=&gt;')
+ if( sequence == desiredsequence ) {
+ document.getElementsByTagName('div')[3].innerHTML = 'PASS';
+ } else {
+ document.getElementsByTagName('div')[3].innerHTML = 'FAIL, got:<br>'+sequence+'<br>instead of:<br>'+desiredsequence;
+ }
+ };
+};
+ </script>
+ </head>
+ <body>
+
+ <div draggable="true"></div>
+ <div></div>
+ <div></div>
+ <div><strong>&nbsp;</strong></div>
+ <ol>
+ <li>Drag the orange square over the blue square</li>
+ <li>Press the relevant modifier keys for your platform to request a &quot;move&quot; drop effect (eg. Shift on Windows/Unix/Linux, Command on Mac)</li>
+ <li>If supported by the platform, the mouse cursor should show that a &quot;move&quot; drop effect will be used</li>
+ <li>Continue dragging over the pink square</li>
+ <li>Release the modifier keys, and wait for at least half a second</li>
+ <li>If supported by the platform, the mouse cursor should show that a &quot;link&quot; drop effect will be used</li>
+ <li>Release the drag, then the keys</li>
+ <li>Fail if no new text appears above this list</li>
+ </ol>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/modifiers/scriptmodified.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/modifiers/scriptmodified.html
new file mode 100644
index 00000000000..7053fc9aa2b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/modifiers/scriptmodified.html
@@ -0,0 +1,99 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Modifier keys selecting dropEffect with script overriding it</title>
+ <style type="text/css">
+div:first-child {
+ height: 100px;
+ width: 100px;
+ background: orange;
+ display: inline-block;
+}
+div:first-child + div {
+ height: 100px;
+ width: 100px;
+ background: blue;
+ display: inline-block;
+}
+div:first-child + div + div {
+ height: 100px;
+ width: 100px;
+ background: fuchsia;
+ display: inline-block;
+}
+table {
+ display: inline-table;
+ margin-right: 1em;
+ border-collapse: collapse;
+}
+table, th, td {
+ border: 1px solid black;
+}
+thead th {
+ background: silver;
+ color: black;
+}
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ var dragenterbefore = '', dragenterafter = '', dragoverbefore = '', dragoverafter = '';
+ var orange = document.getElementsByTagName('div')[0];
+ orange.ondragstart = function (e) {
+ e.dataTransfer.setData('text','http://example.com/');
+ e.dataTransfer.effectAllowed = 'all';
+ };
+ var fuchsia = document.getElementsByTagName('div')[2];
+ fuchsia.ondragenter = function (e) {
+ e.preventDefault();
+ if( e.dataTransfer.dropEffect != 'link' ) {
+ dragenterbefore = e.dataTransfer.dropEffect;
+ }
+ try {
+ e.dataTransfer.dropEffect = 'move';
+ } catch(e) {}
+ if( e.dataTransfer.dropEffect != 'move' ) {
+ dragenterafter = e.dataTransfer.dropEffect;
+ }
+ };
+ fuchsia.ondragover = function (e) {
+ e.preventDefault();
+ if( e.dataTransfer.dropEffect != 'link' ) {
+ dragoverbefore = e.dataTransfer.dropEffect;
+ }
+ try {
+ e.dataTransfer.dropEffect = 'move';
+ } catch(e) {}
+ if( e.dataTransfer.dropEffect != 'move' ) {
+ dragoverafter = e.dataTransfer.dropEffect;
+ }
+ };
+ fuchsia.ondrop = function (e) {
+ e.preventDefault();
+ document.getElementsByTagName('div')[3].innerHTML = ( dragenterbefore || dragenterafter || dragoverbefore || dragoverafter || e.dataTransfer.dropEffect != 'move' ) ? ( 'FAIL' +
+ ( dragenterbefore ? ( '<br>dragenter.dropEffect was '+dragenterbefore+' instead of link' ) : '' ) +
+ ( dragenterafter ? ( '<br>dragenter.dropEffect after writing was '+dragenterafter+' instead of move' ) : '' ) +
+ ( dragoverbefore ? ( '<br>dragover.dropEffect was '+dragoverbefore+' instead of link' ) : '' ) +
+ ( dragoverafter ? ( '<br>dragover.dropEffect after writing was '+dragoverafter+' instead of move' ) : '' ) +
+ ( ( e.dataTransfer.dropEffect != 'move' ) ? ( '<br>drop.dropEffect was '+e.dataTransfer.dropEffect+' instead of move' ) : '' )
+ ) : 'PASS';
+ };
+};
+ </script>
+ </head>
+ <body>
+
+ <div draggable="true"></div>
+ <div></div>
+ <div></div>
+ <div>&nbsp;</div>
+ <ol>
+ <li>Drag the orange square over the blue square</li>
+ <li>Press the relevant modifier keys for your platform to request a &quot;link&quot; drop effect (eg. Alt on Windows, Ctrl+Shift on Unix/Linux, Command+Option on Mac)</li>
+ <li>Continue dragging over the pink square</li>
+ <li>If supported by the platform, the mouse cursor should show that a &quot;move&quot; drop effect will be used</li>
+ <li>Release the drag, then the keys</li>
+ <li>Fail if no new text appears above this list</li>
+ </ol>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/moving-window.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/moving-window.html
new file mode 100644
index 00000000000..810ade95fff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/moving-window.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>drag &amp; drop - moving windows must not start a drag</title>
+<script type="text/javascript">
+
+window.onload = function() {
+ var li1 = document.getElementsByTagName('li')[3], li2 = document.getElementsByTagName('li')[4];
+ li1.ondragstart = li2.ondragstart = function(e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('Text', 'dummy text');
+ this.innerHTML = 'FAIL';
+ };
+ li1.onmousedown = function () { window.moveBy(0,10); };
+ li2.onmousedown = function () { setTimeout(function () {
+ window.moveBy(0,10);
+ },10); };
+};
+
+</script>
+<p></p>
+<ol>
+ <li onclick="window.open(location.href,'_blank','width=500,height=300');">Click here to open this page in a popup window.</li>
+ <li>Ensure that this popup window is not maximised (or tab, in the case of tabs being rendered as an MDI).</li>
+ <li>Ensure that your browser settings allow browser windows to be moved by scripts.</li>
+ <li draggable='true'>Press your mouse down on this text but do not move it afterwards. Fail if a drag operation has started (eg. if the mouse cursor shows that you are dragging something, or if some drag placeholder text appears, or if this text changes).</li>
+ <li draggable='true'>Press your mouse down on this text but do not move it afterwards. Fail if a drag operation has started (eg. if the mouse cursor shows that you are dragging something, or if some drag placeholder text appears, or if this text changes).</li>
+</ol>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/overlappingwindows.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/overlappingwindows.html
new file mode 100644
index 00000000000..cac76acf405
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/overlappingwindows.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<title>Dropping on always-on-top application windows that overlay the browser</title>
+<style>
+ html, body, ol {
+ margin: 0;
+ padding: 0;
+ height: 100%;
+ width: 100%;
+ background: blue;
+ color: black;
+ list-style-position: inside;
+ }
+ div {
+ height: 100px;
+ width: 100px;
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ margin-top: -50px;
+ margin-left: -50px;
+ background: orange;
+ }
+</style>
+
+<script type="text/javascript">
+
+window.onload = function() {
+ var orange = document.getElementsByTagName('div')[0];
+ orange.ondragstart = function(e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('Text', 'dummy text');
+ };
+ var blue = document.getElementsByTagName('ol')[0];
+ blue.ondragenter = blue.ondragover = function(e) {
+ e.preventDefault();
+ };
+ blue.ondrop = function(e) {
+ e.preventDefault();
+ this.innerHTML = 'FAIL';
+ };
+};
+
+</script>
+
+<ol>
+ <li>Position the browser window so that the blue part of this page extends behind the system taskbar.</li>
+ <li>Use your mouse to drag the orange box over a part of the taskbar that overlays the blue part of this page.</li>
+ <li>If supported by the platform, the mouse cursor should <em>not</em> show the browser's custom &quot;copy&quot; cursor, and should instead show the system's expected cursor for dropping on that part of the taskbar.</li>
+ <li>Release the drag. Fail if the text on this page changes.</li>
+ <li>Reload and repeat this test for:<ul>
+ <li>Where the blue part of this page extends under an always-on-top window (eg. the Windows Task Manager).</li>
+ <li>Where the blue part of this page extends under an always-on-top notification (eg. a system tray info balloon).</li>
+ </ul></li>
+</ol>
+<div draggable='true'></div>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/placeholderposition1.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/placeholderposition1.html
new file mode 100644
index 00000000000..ff61224a34c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/placeholderposition1.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<html>
+ <head>
+ <title>drag and drop - position of the placeholder for a dragged element</title>
+ <style type="text/css">
+div { background: orange; color: black; width: 200px; padding: 10px; border: 10px solid orange; margin: 10px; }
+ </style>
+ </head>
+ <body>
+
+ <div draggable="true">Drag the orange block around the page (and only over the page), using the pixel in its top-left corner. When dragging, the top-left corner of the dragged placeholder should exactly match the position of the mouse cursor.</div>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/placeholderposition2.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/placeholderposition2.html
new file mode 100644
index 00000000000..5899f726639
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/placeholderposition2.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<html>
+ <head>
+ <title>drag and drop - position of the placeholder for a dragged selection</title>
+ <style type="text/css">
+p { cursor: default; }
+ </style>
+ </head>
+ <body>
+
+ <p>Select the first word in this sentence. Drag the selection downwards, using the pixel in the top-left corner of the selection highlight. When dragging, the top-left corner of the dragged placeholder should exactly match the position of the mouse cursor.</p>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/click-to-activate.js b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/click-to-activate.js
new file mode 100644
index 00000000000..2ea2f19c2c9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/click-to-activate.js
@@ -0,0 +1 @@
+document.write(plugincode); \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/dragndrop.swf b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/dragndrop.swf
new file mode 100644
index 00000000000..6b49d46c5f2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/dragndrop.swf
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/dragndropleavedeactivate.swf b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/dragndropleavedeactivate.swf
new file mode 100644
index 00000000000..be486248d13
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/dragndropleavedeactivate.swf
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-001.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-001.html
new file mode 100644
index 00000000000..62dc5847ad2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-001.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Drag and drop in Flash</title>
+ <style type="text/css">
+object {
+ width: 400px;
+ height: 400px;
+ border: 5px solid black;
+}
+ </style>
+ </head>
+ <body>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <p>Drag the orange square onto the blue square and release it. The orange square should disappear, and the blue square should turn yellow.</p>
+ <script type="text/javascript">
+var plugincode = '<object data="dragndrop.swf" type="application/x-shockwave-flash">Flash plugin is required for this test.</object>';
+ </script>
+ <script type="text/javascript" src="click-to-activate.js"></script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-002.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-002.html
new file mode 100644
index 00000000000..caa5f1a9d3e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-002.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Drag and drop alternating between Flash and page</title>
+ <style type="text/css">
+div {
+ width: 100px;
+ height: 100px;
+ background: fuchsia;
+}
+object {
+ width: 400px;
+ height: 400px;
+ border: 5px solid black;
+}
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ document.getElementsByTagName('div')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text','dummy text');
+ };
+};
+ </script>
+ </head>
+ <body>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <ol>
+ <li>Drag the pink square onto the blue square and release it. The drag placeholder should disappear (either when releasing, or when passing the black square), and the mouse cursor should return to normal.</li>
+ <li>Without moving your mouse outside the black square, drag the orange square onto the blue square and release it. The orange square should disappear, and the blue square should turn yellow. Fail if the orange square does not immediately respond to the drag attempt.</li>
+ <li>Drag the pink square onto the yellow square and release it. The drag placeholder should disappear, and the mouse cursor should return to normal. Fail if the pink square does not immediately respond to the drag attempt.</li>
+ </ol>
+ <div draggable="true"></div>
+ <script type="text/javascript">
+var plugincode = '<object data="dragndrop.swf" type="application/x-shockwave-flash">Flash plugin is required for this test.</object>';
+ </script>
+ <script type="text/javascript" src="click-to-activate.js"></script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-003.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-003.html
new file mode 100644
index 00000000000..15c672e622b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-003.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Incomplete drag and drop in Flash</title>
+ <style type="text/css">
+object {
+ width: 400px;
+ height: 400px;
+ border: 5px solid black;
+}
+ </style>
+ </head>
+ <body>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <!-- Test is based on expected behaviour where the mouseup is sent to the plugin because a drag was in operation. -->
+ <p>Drag the orange square until the mouse is outside the black square, then release it. Move the mouse over the blue square. Fail if the orange square continues to follow the mouse.</p>
+ <script type="text/javascript">
+var plugincode = '<object data="dragndrop.swf" type="application/x-shockwave-flash">Flash plugin is required for this test.</object>';
+ </script>
+ <script type="text/javascript" src="click-to-activate.js"></script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-004.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-004.html
new file mode 100644
index 00000000000..430eae42b68
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-004.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Drag and drop alternating between incompleted Flash drag and page</title>
+ <style type="text/css">
+div {
+ width: 100px;
+ height: 100px;
+ background: fuchsia;
+}
+object {
+ width: 400px;
+ height: 400px;
+ border: 5px solid black;
+}
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ document.getElementsByTagName('div')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text','dummy text');
+ };
+};
+ </script>
+ </head>
+ <body>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <ol>
+ <li>Drag the orange square until the mouse is outside the right side of the black square but the edge of the orange square can still be seen, then release it.</li>
+ <li>Without passing over the black square again, move the mouse to the pink square.</li>
+ <li>Drag the pink square onto the blue square and release it. The drag placeholder should disappear (either when releasing, or when passing the black square), and the mouse cursor should return to normal. Fail if the pink square does not immediately respond to the drag attempt.</li>
+ <li>Without passing over the black square again, move the mouse to the orange square. Fail if the orange square moves.</li>
+ <li>Drag the orange square onto the blue square and release it. The orange square should disappear, and the blue square should turn yellow. Fail if the orange square does not immediately respond to the drag attempt.</li>
+ </ol>
+ <div draggable="true"></div>
+ <script type="text/javascript">
+var plugincode = '<object data="dragndrop.swf" type="application/x-shockwave-flash">Flash plugin is required for this test.</object>';
+ </script>
+ <script type="text/javascript" src="click-to-activate.js"></script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-005.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-005.html
new file mode 100644
index 00000000000..cf5343f2aa4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-005.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Drag and drop in Flash with Alt+Tab</title>
+ <style type="text/css">
+object {
+ width: 400px;
+ height: 400px;
+ border: 5px solid black;
+}
+ </style>
+ </head>
+ <body>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <ol>
+ <li>Ensure at least one other program is running, with its window maximised.</li>
+ <li>Drag the orange square over the blue square.</li>
+ <li>Without releasing the mouse button, use Alt+Tab (or your system's equivalent) to switch to the other program, then back to this one.</li>
+ <li>Move the mouse around inside the black square. The orange square should continue to follow the mouse.</li>
+ </ol>
+ <script type="text/javascript">
+var plugincode = '<object data="dragndrop.swf" type="application/x-shockwave-flash">Flash plugin is required for this test.</object>';
+ </script>
+ <script type="text/javascript" src="click-to-activate.js"></script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-006.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-006.html
new file mode 100644
index 00000000000..b77539fa2be
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-006.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Drag and drop in Flash with Alt+Tab over page</title>
+ <style type="text/css">
+object {
+ width: 400px;
+ height: 400px;
+ border: 5px solid black;
+}
+ </style>
+ </head>
+ <body>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <ol>
+ <li>Ensure at least one other program is running, with its window maximised.</li>
+ <li>Drag the orange square around until the mouse is outside the black square.</li>
+ <li>Without releasing the mouse button, use Alt+Tab (or your system's equivalent) to switch to the other program, then back to this one.</li>
+ <li>Move the mouse inside the black square. The orange square should continue to follow the mouse.</li>
+ </ol>
+ <script type="text/javascript">
+var plugincode = '<object data="dragndrop.swf" type="application/x-shockwave-flash">Flash plugin is required for this test.</object>';
+ </script>
+ <script type="text/javascript" src="click-to-activate.js"></script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-007.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-007.html
new file mode 100644
index 00000000000..44a69a4ce2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-007.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Drag and drop with Alt+Tab over Flash</title>
+ <style type="text/css">
+div {
+ width: 100px;
+ height: 100px;
+ background: fuchsia;
+}
+object {
+ width: 400px;
+ height: 400px;
+ border: 5px solid black;
+}
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ document.getElementsByTagName('div')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text','dummy text');
+ };
+};
+ </script>
+ </head>
+ <body>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <ol>
+ <li>Ensure at least one other program is running, with its window maximised.</li>
+ <li>Drag the pink square over the blue square. The mouse cursor should be the no-drop cursor, or the platform's drop-allowed cursor.</li>
+ <li>Without releasing the mouse button, use Alt+Tab (or your system's equivalent) to switch to the other program, then back to this one.</li>
+ <li>The mouse cursor should be the same cursor as in step 2.</li>
+ <li>Move the mouse outside the black square. The drag placeholder should follow the mouse (reappearing if it disappeared in step 2).</li>
+ <li>Release the drag. The drag placeholder should disappear, and the cursor should revert to the default mouse cursor.</li>
+ </ol>
+ <div draggable="true"></div>
+ <script type="text/javascript">
+var plugincode = '<object data="dragndrop.swf" type="application/x-shockwave-flash">Flash plugin is required for this test.</object>';
+ </script>
+ <script type="text/javascript" src="click-to-activate.js"></script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-008.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-008.html
new file mode 100644
index 00000000000..31d3b8d5168
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-008.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Drag and drop with right click over Flash</title>
+ <style type="text/css">
+div {
+ width: 100px;
+ height: 100px;
+ background: fuchsia;
+}
+object {
+ width: 400px;
+ height: 400px;
+ border: 5px solid black;
+}
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ document.getElementsByTagName('div')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text','dummy text');
+ };
+};
+ </script>
+ </head>
+ <body>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <ol>
+ <li>Drag the pink square over the blue square.</li>
+ <li>Without releasing the drag, click the right mouse button.</li>
+ <li>If the platform's normal behaviour is to cancel a drag (eg. Windows and Unix+KDE), then the drag should be cancelled; moving the mouse outside the black square should not cause the drag placeholder to continue following the mouse, and the mouse cursor should revert to default.</li>
+ <li>If the platform's normal behaviour is not to cancel a drag (eg. Mac and Unix+Gnome), then the drag should not be cancelled; moving the mouse outside the black square should cause the drag placeholder to continue following the mouse, and the mouse cursor should show as no-drop or drop-allowed.</li>
+ <li>Fail in either case if the drag placeholder gets stuck temporarily or permanently over the blue square. Fail if an inappropriate right click function begins (eg. context menu opens).</li>
+ </ol>
+ <div draggable="true"></div>
+ <script type="text/javascript">
+var plugincode = '<object data="dragndrop.swf" type="application/x-shockwave-flash">Flash plugin is required for this test.</object>';
+ </script>
+ <script type="text/javascript" src="click-to-activate.js"></script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-009.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-009.html
new file mode 100644
index 00000000000..4c9cb2cab02
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-009.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Drag and drop with right click and release over Flash</title>
+ <style type="text/css">
+div {
+ width: 100px;
+ height: 100px;
+ background: fuchsia;
+}
+object {
+ width: 400px;
+ height: 400px;
+ border: 5px solid black;
+}
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ document.getElementsByTagName('div')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text','dummy text');
+ };
+};
+ </script>
+ </head>
+ <body>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <ol>
+ <li>Drag the pink square over the blue square.</li>
+ <li>Without releasing the drag, click the right mouse button, then release the drag.</li>
+ <li>Fail if the drag placeholder gets stuck over the blue square.</li>
+ <li>Move the mouse outside the black square. The mouse cursor should be the default mouse cursor.</li>
+ </ol>
+ <div draggable="true"></div>
+ <script type="text/javascript">
+var plugincode = '<object data="dragndrop.swf" type="application/x-shockwave-flash">Flash plugin is required for this test.</object>';
+ </script>
+ <script type="text/javascript" src="click-to-activate.js"></script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-010.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-010.html
new file mode 100644
index 00000000000..f1f8933933d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-010.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Drag and drop with middle click over Flash</title>
+ <style type="text/css">
+div {
+ width: 100px;
+ height: 100px;
+ background: fuchsia;
+}
+object {
+ width: 400px;
+ height: 400px;
+ border: 5px solid black;
+}
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ document.getElementsByTagName('div')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text','dummy text');
+ };
+};
+ </script>
+ </head>
+ <body>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <ol>
+ <li>Drag the pink square over the blue square.</li>
+ <li>Without releasing the drag, click the middle mouse button.</li>
+ <li>If the platform's normal behaviour is to cancel a drag (eg. Windows and Unix+KDE), then the drag should be cancelled; moving the mouse outside the black square should not cause the drag placeholder to continue following the mouse, and the mouse cursor should revert to default.</li>
+ <li>If the platform's normal behaviour is not to cancel a drag (eg. Mac and Unix+Gnome), then the drag should not be cancelled; moving the mouse outside the black square should cause the drag placeholder to continue following the mouse, and the mouse cursor should show as no-drop or drop-allowed.</li>
+ <li>Fail in either case if the drag placeholder gets stuck temporarily or permanently over the blue square. Fail if an inappropriate middle click function begins (eg. paste-and-go).</li>
+ </ol>
+ <div draggable="true"></div>
+ <script type="text/javascript">
+var plugincode = '<object data="dragndrop.swf" type="application/x-shockwave-flash">Flash plugin is required for this test.</object>';
+ </script>
+ <script type="text/javascript" src="click-to-activate.js"></script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-011.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-011.html
new file mode 100644
index 00000000000..8a5753b0cb9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-011.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Drag and drop with middle click and release over Flash</title>
+ <style type="text/css">
+div {
+ width: 100px;
+ height: 100px;
+ background: fuchsia;
+}
+object {
+ width: 400px;
+ height: 400px;
+ border: 5px solid black;
+}
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ document.getElementsByTagName('div')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text','dummy text');
+ };
+};
+ </script>
+ </head>
+ <body>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <ol>
+ <li>Drag the pink square over the blue square.</li>
+ <li>Without releasing the drag, click the middle mouse button, then release the drag.</li>
+ <li>Fail if the drag placeholder gets stuck over the blue square.</li>
+ <li>Move the mouse outside the black square. The mouse cursor should be the default mouse cursor.</li>
+ </ol>
+ <div draggable="true"></div>
+ <script type="text/javascript">
+var plugincode = '<object data="dragndrop.swf" type="application/x-shockwave-flash">Flash plugin is required for this test.</object>';
+ </script>
+ <script type="text/javascript" src="click-to-activate.js"></script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-101.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-101.html
new file mode 100644
index 00000000000..58d03fde851
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-101.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Drag and drop in windowless Flash</title>
+ <style type="text/css">
+object {
+ width: 400px;
+ height: 400px;
+ border: 5px solid black;
+}
+ </style>
+ </head>
+ <body>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <p>Drag the orange square onto the blue square and release it. The orange square should disappear, and the blue square should turn yellow.</p>
+ <script type="text/javascript">
+var plugincode = '<object data="dragndrop.swf" type="application/x-shockwave-flash"><param name="wmode" value="opaque">Flash plugin is required for this test.</object>';
+ </script>
+ <script type="text/javascript" src="click-to-activate.js"></script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-102.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-102.html
new file mode 100644
index 00000000000..428c191fb22
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-102.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Drag and drop alternating between windowless Flash and page</title>
+ <style type="text/css">
+div {
+ width: 100px;
+ height: 100px;
+ background: fuchsia;
+}
+object {
+ width: 400px;
+ height: 400px;
+ border: 5px solid black;
+}
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ document.getElementsByTagName('div')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text','dummy text');
+ };
+};
+ </script>
+ </head>
+ <body>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <ol>
+ <li>Drag the pink square onto the blue square and release it. The drag placeholder should disappear (either when releasing, or when passing the black square), and the mouse cursor should return to normal.</li>
+ <li>Without moving your mouse outside the black square, drag the orange square onto the blue square and release it. The orange square should disappear, and the blue square should turn yellow. Fail if the orange square does not immediately respond to the drag attempt.</li>
+ <li>Drag the pink square onto the yellow square and release it. The drag placeholder should disappear, and the mouse cursor should return to normal. Fail if the pink square does not immediately respond to the drag attempt.</li>
+ </ol>
+ <div draggable="true"></div>
+ <script type="text/javascript">
+var plugincode = '<object data="dragndrop.swf" type="application/x-shockwave-flash"><param name="wmode" value="opaque">Flash plugin is required for this test.</object>';
+ </script>
+ <script type="text/javascript" src="click-to-activate.js"></script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-103.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-103.html
new file mode 100644
index 00000000000..2ac8f1df635
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-103.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Incomplete drag and drop in windowless Flash</title>
+ <style type="text/css">
+object {
+ width: 400px;
+ height: 400px;
+ border: 5px solid black;
+}
+ </style>
+ </head>
+ <body>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <!-- Test is based on expected behaviour of windowless plugin where the mouseup is not sent to the plugin even though a drag was in operation. -->
+ <p>Drag the orange square until the mouse is outside the black square, then release it. Move the mouse over the blue square. Pass if the orange square follows the mouse.</p>
+ <script type="text/javascript">
+var plugincode = '<object data="dragndrop.swf" type="application/x-shockwave-flash"><param name="wmode" value="opaque">Flash plugin is required for this test.</object>';
+ </script>
+ <script type="text/javascript" src="click-to-activate.js"></script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-104.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-104.html
new file mode 100644
index 00000000000..9f4a3ec1c01
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-104.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Drag and drop alternating between incompleted windowless Flash drag and page</title>
+ <style type="text/css">
+div {
+ width: 100px;
+ height: 100px;
+ background: fuchsia;
+}
+object {
+ width: 400px;
+ height: 400px;
+ border: 5px solid black;
+}
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ document.getElementsByTagName('div')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text','dummy text');
+ };
+};
+ </script>
+ </head>
+ <body>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <ol>
+ <li>Drag the orange square until the mouse is outside the right side of the black square but the edge of the orange square can still be seen, then release it.</li>
+ <li>Without passing over the black square again, move the mouse to the pink square.</li>
+ <li>Drag the pink square onto the white area inside the black square and release it. The drag placeholder should disappear (either when releasing, or when passing the black square), and the mouse cursor should return to normal. The orange square should jump to the mouse position. Fail if the pink square does not immediately respond to the drag attempt.</li>
+ <li>The orange square may optionally continue to follow the mouse.</li>
+ <!-- There are no rules here. Browsers may mask the mouseup event from the plugin (since a dnd operation was in progress), or they may pass the mouseup to the plugin (since the dnd operation has completed). -->
+ </ol>
+ <div draggable="true"></div>
+ <script type="text/javascript">
+var plugincode = '<object data="dragndrop.swf" type="application/x-shockwave-flash"><param name="wmode" value="opaque">Flash plugin is required for this test.</object>';
+ </script>
+ <script type="text/javascript" src="click-to-activate.js"></script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-105.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-105.html
new file mode 100644
index 00000000000..3b072a4237e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-105.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Drag and drop in windowless Flash with Alt+Tab</title>
+ <style type="text/css">
+object {
+ width: 400px;
+ height: 400px;
+ border: 5px solid black;
+}
+ </style>
+ </head>
+ <body>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <ol>
+ <li>Ensure at least one other program is running, with its window maximised.</li>
+ <li>Drag the orange square over the blue square.</li>
+ <li>Without releasing the mouse button, use Alt+Tab (or your system's equivalent) to switch to the other program, then back to this one.</li>
+ <li>Move the mouse around inside the black square. The orange square should continue to follow the mouse.</li>
+ </ol>
+ <script type="text/javascript">
+var plugincode = '<object data="dragndrop.swf" type="application/x-shockwave-flash"><param name="wmode" value="opaque">Flash plugin is required for this test.</object>';
+ </script>
+ <script type="text/javascript" src="click-to-activate.js"></script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-106.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-106.html
new file mode 100644
index 00000000000..f38fd302f78
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-106.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Drag and drop in windowless Flash with Alt+Tab over page</title>
+ <style type="text/css">
+object {
+ width: 400px;
+ height: 400px;
+ border: 5px solid black;
+}
+ </style>
+ </head>
+ <body>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <ol>
+ <li>Ensure at least one other program is running, with its window maximised.</li>
+ <li>Drag the orange square around until the mouse is outside the black square.</li>
+ <li>Without releasing the mouse button, use Alt+Tab (or your system's equivalent) to switch to the other program, then back to this one.</li>
+ <li>Move the mouse inside the black square. The orange square should continue to follow the mouse.</li>
+ </ol>
+ <script type="text/javascript">
+var plugincode = '<object data="dragndrop.swf" type="application/x-shockwave-flash"><param name="wmode" value="opaque">Flash plugin is required for this test.</object>';
+ </script>
+ <script type="text/javascript" src="click-to-activate.js"></script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-107.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-107.html
new file mode 100644
index 00000000000..972df68847b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-107.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Drag and drop with Alt+Tab over windowless Flash</title>
+ <style type="text/css">
+div {
+ width: 100px;
+ height: 100px;
+ background: fuchsia;
+}
+object {
+ width: 400px;
+ height: 400px;
+ border: 5px solid black;
+}
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ document.getElementsByTagName('div')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text','dummy text');
+ };
+};
+ </script>
+ </head>
+ <body>
+ <p><strong>Note:</strong> Mac has no no-drop cursor.</p>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <ol>
+ <li>Ensure at least one other program is running, with its window maximised.</li>
+ <li>Drag the pink square over the blue square. The mouse cursor should be the no-drop cursor, or the platform's drop-allowed cursor.</li>
+ <li>Without releasing the mouse button, use Alt+Tab (or your system's equivalent) to switch to the other program, then back to this one.</li>
+ <li>The mouse cursor should be the same cursor as in step 2.</li>
+ <li>Move the mouse outside the black square. The drag placeholder should follow the mouse (reappearing if it disappeared in step 2).</li>
+ <li>Release the drag. The drag placeholder should disappear, and the cursor should revert to the default mouse cursor.</li>
+ </ol>
+ <div draggable="true"></div>
+ <script type="text/javascript">
+var plugincode = '<object data="dragndrop.swf" type="application/x-shockwave-flash"><param name="wmode" value="opaque">Flash plugin is required for this test.</object>';
+ </script>
+ <script type="text/javascript" src="click-to-activate.js"></script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-108.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-108.html
new file mode 100644
index 00000000000..7a145d06004
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-108.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Drag and drop with right click over windowless Flash</title>
+ <style type="text/css">
+div {
+ width: 100px;
+ height: 100px;
+ background: fuchsia;
+}
+object {
+ width: 400px;
+ height: 400px;
+ border: 5px solid black;
+}
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ document.getElementsByTagName('div')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text','dummy text');
+ };
+};
+ </script>
+ </head>
+ <body>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <ol>
+ <li>Drag the pink square over the blue square.</li>
+ <li>Without releasing the drag, click the right mouse button.</li>
+ <li>If the platform's normal behaviour is to cancel a drag (eg. Windows and Unix+KDE), then the drag should be cancelled; moving the mouse outside the black square should not cause the drag placeholder to continue following the mouse, and the mouse cursor should revert to default.</li>
+ <li>If the platform's normal behaviour is not to cancel a drag (eg. Mac and Unix+Gnome), then the drag should not be cancelled; moving the mouse outside the black square should cause the drag placeholder to continue following the mouse, and the mouse cursor should show as no-drop or drop-allowed.</li>
+ <li>Fail in either case if the drag placeholder gets stuck temporarily or permanently over the blue square. Fail if an inappropriate right click function begins (eg. context menu opens).</li>
+ </ol>
+ <div draggable="true"></div>
+ <script type="text/javascript">
+var plugincode = '<object data="dragndrop.swf" type="application/x-shockwave-flash"><param name="wmode" value="opaque">Flash plugin is required for this test.</object>';
+ </script>
+ <script type="text/javascript" src="click-to-activate.js"></script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-109.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-109.html
new file mode 100644
index 00000000000..e28e166d5fd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-109.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Drag and drop with right click and release over windowless Flash</title>
+ <style type="text/css">
+div {
+ width: 100px;
+ height: 100px;
+ background: fuchsia;
+}
+object {
+ width: 400px;
+ height: 400px;
+ border: 5px solid black;
+}
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ document.getElementsByTagName('div')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text','dummy text');
+ };
+};
+ </script>
+ </head>
+ <body>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <ol>
+ <li>Drag the pink square over the blue square.</li>
+ <li>Without releasing the drag, click the right mouse button, then release the drag.</li>
+ <li>Fail if the drag placeholder gets stuck over the blue square.</li>
+ <li>Move the mouse outside the black square. The mouse cursor should be the default mouse cursor.</li>
+ </ol>
+ <div draggable="true"></div>
+ <script type="text/javascript">
+var plugincode = '<object data="dragndrop.swf" type="application/x-shockwave-flash"><param name="wmode" value="opaque">Flash plugin is required for this test.</object>';
+ </script>
+ <script type="text/javascript" src="click-to-activate.js"></script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-110.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-110.html
new file mode 100644
index 00000000000..07e6241cfd1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-110.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Drag and drop with middle click over windowless Flash</title>
+ <style type="text/css">
+div {
+ width: 100px;
+ height: 100px;
+ background: fuchsia;
+}
+object {
+ width: 400px;
+ height: 400px;
+ border: 5px solid black;
+}
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ document.getElementsByTagName('div')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text','dummy text');
+ };
+};
+ </script>
+ </head>
+ <body>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <ol>
+ <li>Drag the pink square over the blue square.</li>
+ <li>Without releasing the drag, click the middle mouse button.</li>
+ <li>If the platform's normal behaviour is to cancel a drag (eg. Windows and Unix+KDE), then the drag should be cancelled; moving the mouse outside the black square should not cause the drag placeholder to continue following the mouse, and the mouse cursor should revert to default.</li>
+ <li>If the platform's normal behaviour is not to cancel a drag (eg. Mac and Unix+Gnome), then the drag should not be cancelled; moving the mouse outside the black square should cause the drag placeholder to continue following the mouse, and the mouse cursor should show as no-drop or drop-allowed.</li>
+ <li>Fail in either case if the drag placeholder gets stuck temporarily or permanently over the blue square. Fail if an inappropriate middle click function begins (eg. paste-and-go).</li>
+ </ol>
+ <div draggable="true"></div>
+ <script type="text/javascript">
+var plugincode = '<object data="dragndrop.swf" type="application/x-shockwave-flash"><param name="wmode" value="opaque">Flash plugin is required for this test.</object>';
+ </script>
+ <script type="text/javascript" src="click-to-activate.js"></script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-111.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-111.html
new file mode 100644
index 00000000000..587c70f24c4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-111.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Drag and drop with middle click and release over windowless Flash</title>
+ <style type="text/css">
+div {
+ width: 100px;
+ height: 100px;
+ background: fuchsia;
+}
+object {
+ width: 400px;
+ height: 400px;
+ border: 5px solid black;
+}
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ document.getElementsByTagName('div')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text','dummy text');
+ };
+};
+ </script>
+ </head>
+ <body>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <ol>
+ <li>Drag the pink square over the blue square.</li>
+ <li>Without releasing the drag, click the middle mouse button, then release the drag.</li>
+ <li>Fail if the drag placeholder gets stuck over the blue square.</li>
+ <li>Move the mouse outside the black square. The mouse cursor should be the default mouse cursor.</li>
+ </ol>
+ <div draggable="true"></div>
+ <script type="text/javascript">
+var plugincode = '<object data="dragndrop.swf" type="application/x-shockwave-flash"><param name="wmode" value="opaque">Flash plugin is required for this test.</object>';
+ </script>
+ <script type="text/javascript" src="click-to-activate.js"></script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-203.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-203.html
new file mode 100644
index 00000000000..a4d08ecd44e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-203.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Incomplete drag and drop with deactivate in Flash</title>
+ <style type="text/css">
+object {
+ width: 400px;
+ height: 400px;
+ border: 5px solid black;
+}
+ </style>
+ </head>
+ <body>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <!-- Test is based on expected behaviour where the mouseup is sent to the plugin because a drag was in operation. -->
+ <p>Drag the orange square until the mouse is outside the black square, then release it. Move the mouse over the blue square. Fail if the orange square continues to follow the mouse.</p>
+ <script type="text/javascript">
+var plugincode = '<object data="dragndropleavedeactivate.swf" type="application/x-shockwave-flash">Flash plugin is required for this test.</object>';
+ </script>
+ <script type="text/javascript" src="click-to-activate.js"></script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-204.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-204.html
new file mode 100644
index 00000000000..4ba76e65294
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-204.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Drag and drop with deactivate alternating between incompleted Flash drag and page</title>
+ <style type="text/css">
+div {
+ width: 100px;
+ height: 100px;
+ background: fuchsia;
+}
+object {
+ width: 400px;
+ height: 400px;
+ border: 5px solid black;
+}
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ document.getElementsByTagName('div')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text','dummy text');
+ };
+};
+ </script>
+ </head>
+ <body>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <ol>
+ <li>Drag the orange square until the mouse is outside the right side of the black square but the edge of the orange square can still be seen, then release it.</li>
+ <li>Without passing over the black square again, move the mouse to the pink square.</li>
+ <li>Drag the pink square onto the blue square and release it. The drag placeholder should disappear (either when releasing, or when passing the black square), and the mouse cursor should return to normal. Fail if the pink square does not immediately respond to the drag attempt.</li>
+ <li>Without passing over the black square again, move the mouse to the orange square. Fail if the orange square moves.</li>
+ <li>Drag the orange square onto the blue square and release it. The orange square should disappear, and the blue square should turn yellow. Fail if the orange square does not immediately respond to the drag attempt.</li>
+ </ol>
+ <div draggable="true"></div>
+ <script type="text/javascript">
+var plugincode = '<object data="dragndropleavedeactivate.swf" type="application/x-shockwave-flash">Flash plugin is required for this test.</object>';
+ </script>
+ <script type="text/javascript" src="click-to-activate.js"></script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-205.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-205.html
new file mode 100644
index 00000000000..e49add30468
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-205.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Drag and drop with deactivate in Flash with Alt+Tab</title>
+ <style type="text/css">
+object {
+ width: 400px;
+ height: 400px;
+ border: 5px solid black;
+}
+ </style>
+ </head>
+ <body>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <ol>
+ <li>Ensure at least one other program is running, with its window maximised.</li>
+ <li>Drag the orange square over the blue square.</li>
+ <li>Without releasing the mouse button, use Alt+Tab (or your system's equivalent) to switch to the other program, then back to this one.</li>
+ <li>Move the mouse around inside the black square. The orange square should not follow the mouse.</li>
+ <li>Release the mouse button over the white area inside the black square. The orange square should disappear, and the blue square should turn yellow.</li>
+ </ol>
+ <script type="text/javascript">
+var plugincode = '<object data="dragndropleavedeactivate.swf" type="application/x-shockwave-flash">Flash plugin is required for this test.</object>';
+ </script>
+ <script type="text/javascript" src="click-to-activate.js"></script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-206.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-206.html
new file mode 100644
index 00000000000..b3bae6e48f9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-206.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Drag and drop with deactivate in Flash with Alt+Tab over page</title>
+ <style type="text/css">
+object {
+ width: 400px;
+ height: 400px;
+ border: 5px solid black;
+}
+ </style>
+ </head>
+ <body>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <ol>
+ <li>Ensure at least one other program is running, with its window maximised.</li>
+ <li>Drag the orange square around until the mouse is outside the black square.</li>
+ <li>Without releasing the mouse button, use Alt+Tab (or your system's equivalent) to switch to the other program, then back to this one.</li>
+ <li>Move the mouse over the blue square. The orange square should not continue to follow the mouse.</li>
+ </ol>
+ <script type="text/javascript">
+var plugincode = '<object data="dragndropleavedeactivate.swf" type="application/x-shockwave-flash">Flash plugin is required for this test.</object>';
+ </script>
+ <script type="text/javascript" src="click-to-activate.js"></script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-207.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-207.html
new file mode 100644
index 00000000000..bfb4c4d1062
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-207.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Drag and drop with deactivate with Alt+Tab over Flash</title>
+ <style type="text/css">
+div {
+ width: 100px;
+ height: 100px;
+ background: fuchsia;
+}
+object {
+ width: 400px;
+ height: 400px;
+ border: 5px solid black;
+}
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ document.getElementsByTagName('div')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text','dummy text');
+ };
+};
+ </script>
+ </head>
+ <body>
+ <p><strong>Note:</strong> Mac has no no-drop cursor.</p>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <ol>
+ <li>Ensure at least one other program is running, with its window maximised.</li>
+ <li>Drag the pink square over the blue square. The mouse cursor should be the no-drop cursor, or the platform's drop-allowed cursor.</li>
+ <li>Without releasing the mouse button, use Alt+Tab (or your system's equivalent) to switch to the other program, then back to this one.</li>
+ <li>The mouse cursor should be the same cursor as in step 2.</li>
+ <li>Move the mouse outside the black square. The drag placeholder should follow the mouse (reappearing if it disappeared in step 2).</li>
+ <li>Release the drag. The drag placeholder should disappear, and the cursor should revert to the default mouse cursor.</li>
+ </ol>
+ <div draggable="true"></div>
+ <script type="text/javascript">
+var plugincode = '<object data="dragndropleavedeactivate.swf" type="application/x-shockwave-flash">Flash plugin is required for this test.</object>';
+ </script>
+ <script type="text/javascript" src="click-to-activate.js"></script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-303.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-303.html
new file mode 100644
index 00000000000..275e207df33
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-303.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Incomplete drag and drop with deactivate in windowless Flash</title>
+ <style type="text/css">
+object {
+ width: 400px;
+ height: 400px;
+ border: 5px solid black;
+}
+ </style>
+ </head>
+ <body>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <!-- Test is based on expected behaviour of windowless plugin where the mouseup is not sent to the plugin even though a drag was in operation. -->
+ <p>Drag the orange square until the mouse is outside the black square, then release it. Move the mouse over the blue square. Pass if the orange square follows the mouse.</p>
+ <script type="text/javascript">
+var plugincode = '<object data="dragndropleavedeactivate.swf" type="application/x-shockwave-flash"><param name="wmode" value="opaque">Flash plugin is required for this test.</object>';
+ </script>
+ <script type="text/javascript" src="click-to-activate.js"></script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-304.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-304.html
new file mode 100644
index 00000000000..a68a8c3fad0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-304.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Drag and drop with deactivate alternating between incompleted windowless Flash drag and page</title>
+ <style type="text/css">
+div {
+ width: 100px;
+ height: 100px;
+ background: fuchsia;
+}
+object {
+ width: 400px;
+ height: 400px;
+ border: 5px solid black;
+}
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ document.getElementsByTagName('div')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text','dummy text');
+ };
+};
+ </script>
+ </head>
+ <body>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <ol>
+ <li>Drag the orange square until the mouse is outside the right side of the black square but the edge of the orange square can still be seen, then release it.</li>
+ <li>Without passing over the black square again, move the mouse to the pink square.</li>
+ <li>Drag the pink square onto the white area inside the black square and release it. The drag placeholder should disappear (either when releasing, or when passing the black square), and the mouse cursor should return to normal. The orange square should jump to the mouse position. Fail if the pink square does not immediately respond to the drag attempt.</li>
+ <li>The orange square may optionally continue to follow the mouse.</li>
+ <!-- There are no rules here. Browsers may mask the mouseup event from the plugin (since a dnd operation was in progress), or they may pass the mouseup to the plugin (since the dnd operation has completed). -->
+ </ol>
+ <div draggable="true"></div>
+ <script type="text/javascript">
+var plugincode = '<object data="dragndropleavedeactivate.swf" type="application/x-shockwave-flash"><param name="wmode" value="opaque">Flash plugin is required for this test.</object>';
+ </script>
+ <script type="text/javascript" src="click-to-activate.js"></script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-305.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-305.html
new file mode 100644
index 00000000000..3a702789aed
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-305.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Drag and drop with deactivate in windowless Flash with Alt+Tab</title>
+ <style type="text/css">
+object {
+ width: 400px;
+ height: 400px;
+ border: 5px solid black;
+}
+ </style>
+ </head>
+ <body>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <ol>
+ <li>Ensure at least one other program is running, with its window maximised.</li>
+ <li>Drag the orange square over the blue square.</li>
+ <li>Without releasing the mouse button, use Alt+Tab (or your system's equivalent) to switch to the other program, then back to this one.</li>
+ <li>Move the mouse around inside the black square. The orange square should continue to follow the mouse.</li>
+ </ol>
+ <script type="text/javascript">
+var plugincode = '<object data="dragndropleavedeactivate.swf" type="application/x-shockwave-flash"><param name="wmode" value="opaque">Flash plugin is required for this test.</object>';
+ </script>
+ <script type="text/javascript" src="click-to-activate.js"></script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-306.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-306.html
new file mode 100644
index 00000000000..a8248bd696d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-306.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Drag and drop with deactivate in windowless Flash with Alt+Tab over page</title>
+ <style type="text/css">
+object {
+ width: 400px;
+ height: 400px;
+ border: 5px solid black;
+}
+ </style>
+ </head>
+ <body>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <ol>
+ <li>Ensure at least one other program is running, with its window maximised.</li>
+ <li>Drag the orange square around until the mouse is outside the black square.</li>
+ <li>Without releasing the mouse button, use Alt+Tab (or your system's equivalent) to switch to the other program, then back to this one.</li>
+ <li>Move the mouse inside the black square. The orange square should continue to follow the mouse.</li>
+ </ol>
+ <script type="text/javascript">
+var plugincode = '<object data="dragndropleavedeactivate.swf" type="application/x-shockwave-flash"><param name="wmode" value="opaque">Flash plugin is required for this test.</object>';
+ </script>
+ <script type="text/javascript" src="click-to-activate.js"></script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-307.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-307.html
new file mode 100644
index 00000000000..1def298cc16
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/plugin-dnd-307.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Drag and drop with deactivate with Alt+Tab over windowless Flash</title>
+ <style type="text/css">
+div {
+ width: 100px;
+ height: 100px;
+ background: fuchsia;
+}
+object {
+ width: 400px;
+ height: 400px;
+ border: 5px solid black;
+}
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ document.getElementsByTagName('div')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text','dummy text');
+ };
+};
+ </script>
+ </head>
+ <body>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <ol>
+ <li>Ensure at least one other program is running, with its window maximised.</li>
+ <li>Drag the pink square over the blue square. The mouse cursor should be the no-drop cursor, or the platform's drop-allowed cursor.</li>
+ <li>Without releasing the mouse button, use Alt+Tab (or your system's equivalent) to switch to the other program, then back to this one.</li>
+ <li>The mouse cursor should be the same cursor as in step 2.</li>
+ <li>Move the mouse outside the black square. The drag placeholder should follow the mouse (reappearing if it disappeared in step 2).</li>
+ <li>Release the drag. The drag placeholder should disappear, and the cursor should revert to the default mouse cursor.</li>
+ </ol>
+ <div draggable="true"></div>
+ <script type="text/javascript">
+var plugincode = '<object data="dragndropleavedeactivate.swf" type="application/x-shockwave-flash"><param name="wmode" value="opaque">Flash plugin is required for this test.</object>';
+ </script>
+ <script type="text/javascript" src="click-to-activate.js"></script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/swfsources/dragndrop.hx b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/swfsources/dragndrop.hx
new file mode 100644
index 00000000000..25fc51ef0d2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/swfsources/dragndrop.hx
@@ -0,0 +1,133 @@
+import Std;
+import flash.Lib;
+import flash.events.MouseEvent;
+
+class DragNDrop
+{
+ static var s_box_draggable:Box;
+ static var s_box_target:Box;
+ static var s_dragging:Bool = false;
+
+ private static function main()
+ {
+ /* Blue box (target). */
+ s_box_target = new Box(0x0000ff, 100, 100, 150, 150);
+ /* Orange box (draggable). */
+ s_box_draggable = new Box(0xffa500, 25, 25, 50, 50);
+
+ flash.Lib.current.stage.addEventListener(MouseEvent.MOUSE_DOWN, OnMouseDown);
+ flash.Lib.current.stage.addEventListener(MouseEvent.MOUSE_MOVE, OnMouseMove);
+ flash.Lib.current.stage.addEventListener(MouseEvent.MOUSE_UP, OnMouseUp);
+ }
+
+ static function OnMouseDown(event:MouseEvent):Void
+ {
+ if (s_box_draggable.IsHit(event.stageX, event.stageY))
+ s_dragging = true;
+ }
+
+ static function OnMouseUp(event:MouseEvent):Void
+ {
+ s_dragging = false;
+
+ /* Check if passed. */
+ if (s_box_draggable.IsWithin(s_box_target))
+ {
+ s_box_draggable.Hide();
+ s_box_target.SetColor(0xffee00);
+ }
+ }
+
+ static function OnMouseMove(event:MouseEvent):Void
+ {
+ if (s_dragging)
+ {
+ ClearCanvas();
+ s_box_target.Redraw();
+ s_box_draggable.Move(event.stageX, event.stageY);
+ }
+ }
+
+ static function ClearCanvas():Void
+ {
+ var mc:flash.display.MovieClip = flash.Lib.current;
+ mc.graphics.beginFill(0xffffff);
+ mc.graphics.drawRect(0, 0, flash.Lib.current.stage.width, flash.Lib.current.stage.height);
+ mc.graphics.endFill();
+ }
+}
+
+class Box
+{
+ var m_mc:flash.display.MovieClip;
+ var m_color:Int;
+ var m_rel_x:Float;
+ var m_rel_y:Float;
+ var m_x:Float;
+ var m_y:Float;
+ var m_width:Int;
+ var m_height:Int;
+
+ public function new(color:Int, x:Int, y:Int, width:Int, height:Int)
+ {
+ m_mc = flash.Lib.current;
+ m_color = color;
+ m_x = x;
+ m_y = y;
+ m_width = width;
+ m_height = height;
+
+ Redraw();
+ }
+
+ public function IsHit(x:Float, y:Float):Bool
+ {
+ if ((x >= m_x && x <= m_x + m_width) && (y >= m_y && y <= m_y + m_height))
+ {
+ m_rel_x = x - m_x;
+ m_rel_y = y - m_y;
+ return true;
+ }
+
+ return false;
+ }
+
+ public function IsWithin(other:Box):Bool
+ {
+ return m_x >= other.m_x && m_x + m_width <= other.m_x + other.m_width
+ && m_y >= other.m_y && m_y + m_height <= other.m_y + other.m_height;
+ }
+
+ public function Hide():Void
+ {
+ m_width = 0;
+ m_height = 0;
+ }
+
+ public function SetColor(color:Int):Void
+ {
+ m_color = color;
+ Redraw();
+ }
+
+ public function Move(x:Float, y:Float):Void
+ {
+ /* Accounting for click offset. */
+ m_x = x - m_rel_x;
+ m_y = y - m_rel_y;
+ Draw(Std.int(m_x), Std.int(m_y), m_width, m_height);
+ }
+
+ public function Redraw():Void
+ {
+ Draw(Std.int(m_x), Std.int(m_y), m_width, m_height);
+ }
+
+ private function Draw(x:Int, y:Int, width:Int, height:Int)
+ {
+ /* Draw moved rect. */
+ m_mc.graphics.beginFill(m_color);
+ m_mc.graphics.drawRect(x, y, width, height);
+ m_mc.graphics.endFill();
+ }
+}
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/swfsources/dragndrop.hxml b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/swfsources/dragndrop.hxml
new file mode 100644
index 00000000000..71f2eb5b9c9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/swfsources/dragndrop.hxml
@@ -0,0 +1 @@
+-swf dragndrop.swf -swf-version 10 -main DragNDrop -swf-header 300:300:25:FFFFFF \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/swfsources/mouseup.hx b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/swfsources/mouseup.hx
new file mode 100644
index 00000000000..13a8757bd79
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/swfsources/mouseup.hx
@@ -0,0 +1,34 @@
+import flash.Lib;
+import flash.display.Sprite;
+import flash.events.MouseEvent;
+
+class MouseUp extends Sprite
+{
+ var s:Sprite;
+
+ static function main()
+ {
+ new MouseUp();
+ }
+
+ public function new()
+ {
+ super();
+ flash.Lib.current.addChild(this);
+
+ s = new Sprite();
+ s.graphics.beginFill(0xffa500);
+ s.graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
+ s.graphics.endFill();
+ stage.addChild(s);
+
+ stage.addEventListener(MouseEvent.MOUSE_UP, OnMouseUp);
+ }
+
+ function OnMouseUp(event:MouseEvent):Void
+ {
+ s.graphics.beginFill(0xffee00);
+ s.graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
+ s.graphics.endFill();
+ }
+}
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/swfsources/mouseup.hxml b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/swfsources/mouseup.hxml
new file mode 100644
index 00000000000..d588590347f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugin/swfsources/mouseup.hxml
@@ -0,0 +1 @@
+-swf mouseup.swf -swf-version 10 -main MouseUp -swf-header 300:300:25:FFFFFF \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugindrop.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugindrop.html
new file mode 100644
index 00000000000..548e4da8c1e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/plugindrop.html
@@ -0,0 +1,24 @@
+<!doctype html>
+<html>
+ <head>
+ <title>drag and drop sequence should end when dropping over a plugin</title>
+ <style type="text/css">
+div {
+ background: orange;
+ height: 100px;
+ width: 100px;
+}
+object {
+ height: 100px;
+ width: 100px;
+}
+ </style>
+ </head>
+ <body>
+
+ <p>Use your pointing device to drag the orange square onto the blue square, and release it. The drag placeholder should disappear after releasing (or as the pointer moves over the blue square). Try dragging the orange square again. Fail if it does not respond when trying to drag it.</p>
+ <div draggable="true" ondragstart="event.dataTransfer.setData('Text','dummy text');"></div>
+ <p><object data="../resources/boxnavy.swf"></object></p>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/selection-between-ui.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/selection-between-ui.html
new file mode 100644
index 00000000000..a0e94f65b7c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/selection-between-ui.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Dragging text from UI widgets to each other</title>
+ </head>
+ <body>
+
+ <ol>
+ <li>Select some text in the address bar.</li>
+ <li>Drag the selection to another text input in the UI, and release it.</li>
+ <li>Pass if:<ol>
+ <li>A visible representation of the selected text appears to be dragged.</li>
+ <li>The mouse cursor shows that the drop will be allowed over the input.</li>
+ <li>The selected text appears in the input.</li>
+ </ol></li>
+ <li>Repeat the test with other UI text inputs as drag source/destination.</li>
+ </ol>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/selection-from-os.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/selection-from-os.html
new file mode 100644
index 00000000000..14f3db335d3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/selection-from-os.html
@@ -0,0 +1,17 @@
+<!doctype html>
+<html>
+ <head>
+ <title>drag and drop - dragging a selection from the OS</title>
+ </head>
+ <body>
+
+ <p>This test is only relevant on platforms where it is possible to switch applications in mid-drag (eg. alt+tab, dragging over taskbar buttons, dragging between restored windows).</p>
+ <p>This testcase requires an external application that allows dragging of selections into other applications - eg. Wordpad (write.exe) on Windows. Ensure that the external application is open.</p>
+ <p>Move the browser window so it sits about 200 pixels down from the top of the screen.</p>
+ <p>Subtest 1. Write some text into the external application (if needed), containing both unicode and Latin characters. Select the text in the external application, and drag the selection into the following input:<br><textarea rows="3" cols="50"></textarea><br>Pass if the text you selected appears in the input.</p>
+ <p>Subtest 2. Select the text in the external application, and drag the selection into the following block:
+ <span style="background:orange;display:block;min-height:100px;width:300px;" ondragenter="return false;" ondragover="return false;" ondrop="this.innerHTML = arguments[0].dataTransfer.getData('text/plain');return false;"></span>
+ Pass if the text you selected appears in the block.</p>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/selection-from-ui.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/selection-from-ui.html
new file mode 100644
index 00000000000..1fc552ec6d5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/selection-from-ui.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Dragging text from UI widgets</title>
+ </head>
+ <body>
+
+ <ol>
+ <li>Select some text in the address bar.</li>
+ <li>Drag the selection to the following textarea, and release it: <br><textarea rows="3" cols="50"></textarea></li>
+ <li>Pass if:<ol>
+ <li>A visible representation of the selected text appears to be dragged.</li>
+ <li>The mouse cursor shows that the drop will be allowed over the textarea.</li>
+ <li>The selected text appears in the textarea.</li>
+ </ol></li>
+ <li>Repeat the test with other UI text inputs, including ones that allow linebreaks (if any).</li>
+ </ol>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/selection-to-os.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/selection-to-os.html
new file mode 100644
index 00000000000..c4c72954714
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/selection-to-os.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<html>
+ <head>
+ <title>drag and drop - dragging a selection onto the OS</title>
+ </head>
+ <body>
+
+ <p>This test is only relevant on platforms where it is possible to switch applications in mid-drag (eg. alt+tab, dragging over taskbar buttons, dragging between restored windows).</p>
+ <p>This testcase requires an external application that accepts dropping of text from other applications - eg. Wordpad (write.exe) on Windows. Ensure that the external application is open.</p>
+ <p>Select this text. Drag the selection to the other application and release it. Pass if the text you selected appears in the other application, and the drag placeholder disappears when the drag is released.</p>
+ <p>Disable JavaScript and repeat the test. It should still pass.</p>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/selection-to-ui-via.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/selection-to-ui-via.html
new file mode 100644
index 00000000000..f4f1cf15993
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/selection-to-ui-via.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Dragging text to UI widgets via window decoration</title>
+ </head>
+ <body>
+
+ <p>This test assumes that the address bar is positioned below the window's title bar, and above the page. If your browser uses an alternative layout, adjust your testing accordingly to ensure that the testing interacts with the edges of the window decoration.</p>
+ <ol>
+ <li>Select some text on this page.</li>
+ <li>Drag the selection to your browser's title bar.</li>
+ <li>Drag the selection back to your browser's address field. Fail if the mouse cursor shows that the text cannot be dropped.</li>
+ <li>Fail if the cursor and/or input focus caret respond in the wrong position (ie. if the drag operation seems to think the address field is offset from its actual location).</li>
+ <li>Release it. Pass if the selected text appears in the address field.</li>
+ <li>Repeat the test with other UI text inputs.</li>
+ </ol>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/selection-to-ui.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/selection-to-ui.html
new file mode 100644
index 00000000000..9c3a60387fc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/selection-to-ui.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Dragging text to UI widgets</title>
+ </head>
+ <body>
+
+ <ol>
+ <li>Select some text on this page.</li>
+ <li>Drag the selection to your browser's address field. Fail if the mouse cursor shows that the text cannot be dropped.</li>
+ <li>Release it. Pass if the selected text appears in the address field.</li>
+ <li>Repeat the test with other UI text inputs.</li>
+ </ol>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/selection-ui-to-self.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/selection-ui-to-self.html
new file mode 100644
index 00000000000..363416de840
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/selection-ui-to-self.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Dragging text from UI widgets to themselves</title>
+ </head>
+ <body>
+
+ <ol>
+ <li>Select all text in the address bar.</li>
+ <li>Drag the selection around a little, and release it over the address bar again.</li>
+ <li>Try to select the text in this sentence.</li>
+ <li>Pass if:<ol>
+ <li>A visible representation of the selected text appears to be dragged.</li>
+ <li>The mouse cursor shows that the drop will be allowed over the address bar.</li>
+ <li>The text on this page can be selected afterwards.</li>
+ </ol></li>
+ <li>Repeat the test with other UI text inputs as drag source/destination.</li>
+ </ol>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/selection-unicode-to-os.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/selection-unicode-to-os.html
new file mode 100644
index 00000000000..ed093f6fa74
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/selection-unicode-to-os.html
@@ -0,0 +1,13 @@
+<!doctype html>
+<html>
+ <head>
+ <title>drag and drop - dragging a selection containing unicode onto the OS</title>
+ </head>
+ <body>
+
+ <p>This test is only relevant on platforms where it is possible to switch applications in mid-drag (eg. alt+tab, dragging over taskbar buttons, dragging between restored windows).</p>
+ <p>This testcase requires an external application that accepts dropping of text from other applications, and supports unicode - eg. Wordpad (write.exe) on Windows. Ensure that the external application is open.</p>
+ <p>Select the following non-English text --> 中文אידישрусский &lt;-- Drag the selection to the other application and release it. Pass if the text you selected appears in the other application, and the drag placeholder disappears when the drag is released.</p>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/taskbardrop.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/taskbardrop.html
new file mode 100644
index 00000000000..4b4e6c468ef
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/taskbardrop.html
@@ -0,0 +1,23 @@
+<!doctype html>
+<html>
+ <head>
+ <title>drag and drop - dropping on the taskbar</title>
+ </head>
+ <body>
+
+ <p>This test is only relevant on platforms where dragging over taskbar buttons will switch between applications.</p>
+ <p>Ensure that at least one other application is open and visible on the taskbar. Maximise this browser window. Select this text. Drag the selection downwards, over a blank part of the system taskbar, and release the drag. Drag the selection again, over the taskbar button for the other application (without passing over any other buttons on the taskbar). Fail if the drag placeholder does not appear when dragging the selection. Pass if the other application becomes focused.</p>
+ <p>Repeat this test while dropping on other parts of the taskbar, such as:</p>
+ <ul>
+ <li>The Start menu button (or your system's equivalent)</li>
+ <li>The Quick Launch bar (or your system's equivalent)</li>
+ <li>The System Tray (or your system's equivalent)</li>
+ <li>The expander button for the System Tray (or your system's equivalent)</li>
+ <li>The button for another application</li>
+ <li>The label for a folder toolbar - drop a folder onto the Windows taskbar to create one (or your system's equivalent)</li>
+ <li>The menu button for a folder toolbar (or your system's equivalent)</li>
+ </ul>
+ <p><strong>WARNING: different operating system versions handle this differently - Windows XP Taskbar in particular can cause several more problems than the Windows 7 Taskbar</strong></p>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/taskbarminimise.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/taskbarminimise.html
new file mode 100644
index 00000000000..8531ad93503
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/taskbarminimise.html
@@ -0,0 +1,12 @@
+<!doctype html>
+<html>
+ <head>
+ <title>drag and drop - minimising using the taskbar</title>
+ </head>
+ <body>
+
+ <p>This test is only relevant on platforms where dragging over the taskbar (or a specific button on it) will minimise all applications.</p>
+ <p>Select this text. Drag the selection downwards, over a blank part of the system taskbar (or a minimise-all button if provided by the system). Hold the drag until all applications have minimised, then drag upwards over the desktop. Pass if the drag placeholder is still visible.</p>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/text-os-to-os.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/text-os-to-os.html
new file mode 100644
index 00000000000..030972b70ad
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/text-os-to-os.html
@@ -0,0 +1,13 @@
+<!doctype html>
+<html>
+ <head>
+ <title>drag and drop - dragging items from the OS to the OS, via the browser window</title>
+ </head>
+ <body>
+
+ <p>This test is only relevant on platforms where it is possible to switch applications in mid-drag (eg. alt+tab, dragging over taskbar buttons, dragging between restored windows).</p>
+ <p>This testcase requires an external application that accepts dropping of text from other applications - eg. Wordpad (write.exe) on Windows. Ensure that the external application is open.</p>
+ <p>Select some text in the external application. Drag the selection over the browser window, then back to the other application and release it. Pass if the text you selected appears in the other application.</p>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/platform/text-to-os.html b/tests/wpt/web-platform-tests/html/editing/dnd/platform/text-to-os.html
new file mode 100644
index 00000000000..ce57c43eb87
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/platform/text-to-os.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<html>
+ <head>
+ <title>drag and drop - dragging plain text onto the OS</title>
+ </head>
+ <body>
+
+ <p>This test is only relevant on platforms where it is possible to switch applications in mid-drag (eg. alt+tab, dragging over taskbar buttons, dragging between restored windows).</p>
+ <p>This testcase requires an external application that accepts dropping of text from other applications - eg. Wordpad (write.exe) on Windows. Ensure that the external application is open.</p>
+ <p draggable="true">Drag this paragraph to the other application and release it. Pass if &quot;PASS&quot; appears in the other application, and the drag placeholder disappears when the drag is released.</p>
+ <script type="text/javascript">
+document.getElementsByTagName('p')[2].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('Text', 'PASS');
+};
+ </script>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/reload/001.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/reload/001.xhtml
new file mode 100644
index 00000000000..87b97d4153b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/reload/001.xhtml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Reload during canvas drag and drop roundtrip</title>
+<style type="text/css">
+img
+ {margin:0 2px;}
+</style>
+<script type="application/ecmascript">
+function addImage(event)
+ {var c = document.createElement('img');
+ c.setAttribute('src',event.dataTransfer.getData('text/uri-list').replace(/\r\n$/,''));
+ document.querySelector('p').appendChild(c);}
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ event.dataTransfer.setData('text/uri-list', document.querySelector('canvas').toDataURL('image/png'));
+ window.location.reload();}
+</script>
+</head>
+<body>
+<p>
+ <canvas width="100" height="100" draggable="true" ondragstart="start(event)" ondragenter="event.preventDefault()" ondragover="return false" ondrop="addImage(event)">Canvas</canvas>
+</p>
+<p>Drag canvas pattern around page and then drag it back and drop on itself. It should be duplicated once you drop it.</p>
+<script type="application/ecmascript">
+var canvas = document.querySelector('canvas'),
+c = canvas.getContext('2d');
+for(var x = 0; x != 50; x++)
+ {c.fillStyle = (x%2 == 0)?'navy':'white';
+ c.beginPath();
+ c.moveTo(x,x);
+ c.lineTo(100-x,x);
+ c.lineTo(100-x,100-x);
+ c.lineTo(x,100-x);
+ c.closePath();
+ c.fill();}
+</script>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/reload/002.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/reload/002.xhtml
new file mode 100644
index 00000000000..47d14528ae2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/reload/002.xhtml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Reload during PNG image drag and drop roundtrip</title>
+<style type="text/css">
+img
+ {margin:0 2px;}
+</style>
+<script type="application/ecmascript">
+function addImage(event)
+ {var c = document.createElement('img');
+ c.setAttribute('src',event.dataTransfer.getData('text/uri-list').replace(/\r\n$/,''));
+ document.querySelector('p').appendChild(c);}
+</script>
+</head>
+<body>
+<p><img ondragstart="event.dataTransfer.effectAllowed = 'copy';window.location.reload()" ondragenter="event.preventDefault()" ondrop="addImage(event)" ondragover="return false" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAEq0lEQVR42u1dvU4bQRAeR0RCCilSp0peIoKGB4DSXYRDlcZlFClKBI4bB/kV/AymIDwCTahiicaioEOxhCsjWVTJziyKMfYZn+9ud3bvG2mEZB13u9+nndmf2Rki7fKFXtEBbVKD9o22jB4bPaND6hm9Mjo0enevw/vfevKMfbYl/8vv4HdBUkvFALhltG2A7dN3+pur8jv53fwN/hZkjjRo3eiuAatjdJA7CcnkDOSb/G1uQ6mFzUeDagaQrvl764yEJOU22LbUymXaGrRhOt40OvJOQvLIGUkbP9GLeIn4SM9NJ+tOTVI+Jq0ubY9sVFRNxy6DIWKWmEvpQ/ByQNumI+fBEjHrZ86lT8HJV3ptGn8aDRGzxJxKHwMZFe9Mg6+jJWNCyrX0VbUc0nuj4+jJmPiWsfRZodN+ZvSoNETMjpYjwUCFfKaXpjEnpSVjQsqJYOF5ZLw1elF6MiakXAgmnpw378DegIgZUm4EGw8jA2QsIuUbvXHpM2CmljFfhfsUO5uCA0/j6AudfZV5arv6WuVHcYs+ALwqKTkvHnmLoEwr8CJW9Llts9iNwvj3plzsfeWyIRnzrq37kfIzq6naBpA5a6bzlJgOl/SMkl+rklEFgIX5k5THwTYgIdwzcP2jhM/o19KsOeoArnBS6suaqo2gQnXCJWSwXNwXB4gBMFekNBeTwSGUmiMK4yNktDhsleNaAZRrUvYWmasuQHJOSDdpdKyriEIvo9maexWC70gAIF/bKTvzzFUH4HgbJZ3HdFSw9vC6lfKHpq7X8X07AOOblK2HhLQBindC2g/9Rx+gePcj/cnqHIDoUFm1c9gjwNAy/d0kyXIAMLSYrQ8kqScAhhbH3iLJBwIwtBByTJKkBWBoIeSMJHMOwNBCyG+SdEYAQ4tTvyLJMQUwtBAyJEn8BTC0EHIHQhQSApOlzGTBqaty6jzVAhhaCOlhYahuYYitE02EHGNzURchLZItX4ChhZB9HFBpUjmgwhGuHv0feI0gBw1T3j7CgHT5jzYC5XQRsjUdSsrhjADGl7ka0EylBgRb+ySkMy9rww7A8Waududf2MH9Qh9k3CbXLsGVNh/mqrvojuEeQHI+Qmq4Fq1ndIyeruaDxAEuCWk+ncmB0z3gepubtQenMUHyGTWELJl8xk6B15CeqVAyLtPXtUICsyJnVivWs+J0dAAwbzLOkQRTk2YuKsapTQFkXqPjlDILEinnRcZ1fpXdkGo866xqnH9FNyTjz0JIQZXcuPQCAE5rqo6oMEFBl7RknBRfTg8lj5Yl48JdGT0ueIWiYIvIuHFfPg9l85LJcF42b+JTUFjysZnyVlhy2qfA0asovTo9+0JxYnWC8t0KBQXuFYrdkIy3mBj3LbeNQrejZTuqOlbcl8znGTqcfjXoM3pboqgaPhEPxda1qgcVYsRt5TanDkgISWzcV1N1hCS3jdu4dNxUDMIhlBzXysHGGspkcBtsW2pPh3fGLrZ2ya5cXHFp0qxJ6si3E68EQCpy344vQRZxO5jfye+2d/oqgHsV02Z3lvcl9QTnA+EkLZw5h9MZcY4pTvxldXj/W0+esc+25H/5HQGYon+Q5f+MwFz+8QAAAABJRU5ErkJggg==" alt="PNG circle"/></p>
+<p>Drag circle around page and then drag it back and drop on itself. It should be duplicated once you drop it.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/reload/003.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/reload/003.xhtml
new file mode 100644
index 00000000000..9fadf392656
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/reload/003.xhtml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Reload during SVG image drag and drop roundtrip</title>
+<style type="text/css">
+img
+ {margin:0 2px;}
+</style>
+<script type="application/ecmascript">
+function addImage(event)
+ {var c = document.createElement('img');
+ c.setAttribute('src',event.dataTransfer.getData('text/uri-list').replace(/\r\n$/,''));
+ document.querySelector('p').appendChild(c);}
+</script>
+</head>
+<body>
+<p><img ondragstart="event.dataTransfer.effectAllowed = 'copy';window.location.reload()" ondragenter="event.preventDefault()" ondrop="addImage(event)" ondragover="return false" src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20version%3D%221.1%22%20width%3D%22100px%22%20height%3D%22100px%22%20viewBox%3D%220%200%20100%20100%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22green%22/%3E%3C/svg%3E" alt="SVG circle"/></p>
+<p>Drag circle around page and then drag it back and drop on itself. It should be duplicated once you drop it.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/reload/004.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/reload/004.xhtml
new file mode 100644
index 00000000000..26489b5626c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/reload/004.xhtml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Reload during text input selection drag and drop roundtrip</title>
+</head>
+<body onload="document.querySelector('input').select()">
+<p><input value="Drag me" ondragstart="window.location.reload()" ondragenter="event.preventDefault();" ondragover="return false" ondrop="event.preventDefault();this.value = (event.dataTransfer.getData('text/plain') == 'Drag me')?'PASS':'FAIL'"/></p>
+<p>Drag selected text around page and then drag it back and drop on itself. You should see word PASS once you drop it.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/reload/005.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/reload/005.xhtml
new file mode 100644
index 00000000000..1e0e1bb828f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/reload/005.xhtml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Reload during selection drag and drop roundtrip</title>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('span'))">
+<p><span ondragstart="window.location.reload()" ondragenter="event.preventDefault()" ondragover="return false" ondrop="document.querySelector('span').firstChild.nodeValue = (event.dataTransfer.getData('text/plain') == 'Drag me')?'PASS':'FAIL'">Drag me</span></p>
+<p>Drag selected text around page and then drag it back and drop on itself. You should see word PASS once you drop it.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/reload/006.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/reload/006.xhtml
new file mode 100644
index 00000000000..953dc47adf0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/reload/006.xhtml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Reload during link drag and drop roundtrip</title>
+<script type="application/ecmascript">
+function checkLink(event)
+ {document.querySelector('a').firstChild.nodeValue = (event.dataTransfer.getData('text/uri-list').replace(/\r\n$/,'') == 'data:text/plain,1')?'PASS':'FAIL'}
+</script>
+</head>
+<body>
+<p><a href="data:text/plain,1" ondragstart="event.dataTransfer.effectAllowed = 'copy';window.location.reload()" ondragenter="event.preventDefault()" ondrop="checkLink(event)" ondragover="return false">Drag me</a></p>
+<p>Drag link around page and then drag it back and drop on itself. You should see word PASS once you drop it.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/reload/007.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/reload/007.xhtml
new file mode 100644
index 00000000000..0a4160e9a5e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/reload/007.xhtml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Reload during drag and drop roundtrip with text/plain data</title>
+<style type="text/css">
+div[ondragenter]
+ {width:40px;
+ min-height:40px;
+ margin-top:20px;
+ padding:40px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body>
+<div
+ draggable="true"
+ ondragstart="event.dataTransfer.effectAllowed = 'copy';event.dataTransfer.setData('text/plain',' PASS ');window.location.reload();"
+ ondragenter="event.preventDefault()"
+ ondragover="return false"
+ ondrop="document.querySelector('div').appendChild(document.createTextNode(event.dataTransfer.getData('text/plain')))"
+/>
+<p>Drag blue box around page and then drag it back and drop on itself. You should see word PASS once you drop it.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/reload/008.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/reload/008.xhtml
new file mode 100644
index 00000000000..a0c49e6eae1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/reload/008.xhtml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Reload during drag and drop roundtrip with text/uri-list data</title>
+<style type="text/css">
+div[ondragenter]
+ {width:40px;
+ min-height:40px;
+ margin-top:20px;
+ padding:40px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body>
+<div
+ draggable="true"
+ ondragstart="event.dataTransfer.effectAllowed = 'copy';event.dataTransfer.setData('text/uri-list','data:text/plain,PASS');window.location.reload()"
+ ondragenter="event.preventDefault()"
+ ondragover="return false"
+ ondrop="document.querySelector('div').appendChild(document.createTextNode(event.dataTransfer.getData('text/uri-list').substr(16,4) + ' '))"
+/>
+<p>Drag blue box around page and then drag it back and drop on itself. You should see word PASS once you drop it.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/reload/009-1.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/reload/009-1.xhtml
new file mode 100644
index 00000000000..9e98b932049
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/reload/009-1.xhtml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Reload during drag and drop: helper file</title>
+</head>
+<body ondragleave="window.location.reload()">
+<p><a href="data:text/plain,1" ondragstart="event.dataTransfer.effectAllowed = 'copy'">Drag me</a></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/reload/009.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/reload/009.xhtml
new file mode 100644
index 00000000000..5cb61fb8d72
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/reload/009.xhtml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Reload during link drag and drop from object</title>
+<style type="text/css">
+object
+ {height:100px;
+ width:300px;
+ border:solid medium navy;}
+</style>
+</head>
+<body dropzone="copy string:text/uri-list" ondrop="document.querySelector('p').firstChild.nodeValue = (event.dataTransfer.getData('text/uri-list').replace(/\r\n$/,'') == 'data:text/plain,1')?'PASS':'FAIL'">
+<object type="application/xhtml+xml" data="009-1.xhtml">XHTML document</object>
+<p>Drag link above out of frame and drop it somewhere on the page. You should see word PASS once you drop it.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/reload/010-1.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/reload/010-1.xhtml
new file mode 100644
index 00000000000..51d2012f79b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/reload/010-1.xhtml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Reload during drag and drop: helper file</title>
+</head>
+<body onload="document.querySelector('input').select()" ondragleave="window.location.reload()">
+<p><input value="Drag me"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/reload/010.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/reload/010.xhtml
new file mode 100644
index 00000000000..86663f722ac
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/reload/010.xhtml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Reload during text input selection drag and drop from object</title>
+<style type="text/css">
+object
+ {height:100px;
+ width:300px;
+ border:solid medium navy;}
+</style>
+</head>
+<body dropzone="copy string:text/plain" ondrop="document.querySelector('p').firstChild.nodeValue = (event.dataTransfer.getData('text/plain') == 'Drag me')?'PASS':'FAIL'">
+<object type="application/xhtml+xml" data="010-1.xhtml">XHTML document</object>
+<p>Drag selection above out of frame and drop it somewhere on the page. You should see word PASS once you drop it.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/reload/011-1.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/reload/011-1.xhtml
new file mode 100644
index 00000000000..61c46c57ffc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/reload/011-1.xhtml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Reload during drag and drop: helper file</title>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('p'))" ondragleave="window.location.reload()">
+<p>Drag me</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/reload/011.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/reload/011.xhtml
new file mode 100644
index 00000000000..837b0853626
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/reload/011.xhtml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Reload during selection drag and drop from object</title>
+<style type="text/css">
+object
+ {height:100px;
+ width:300px;
+ border:solid medium navy;}
+</style>
+</head>
+<body dropzone="copy string:text/plain" ondrop="document.querySelector('p').firstChild.nodeValue = (event.dataTransfer.getData('text/plain') == 'Drag me')?'PASS':'FAIL'">
+<object type="application/xhtml+xml" data="011-1.xhtml">XHTML document</object>
+<p>Drag selection above out of frame and drop it somewhere on the page. You should see word PASS once you drop it.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/reload/012-1.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/reload/012-1.xhtml
new file mode 100644
index 00000000000..b7f0ab11a14
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/reload/012-1.xhtml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Reload during drag and drop: helper file</title>
+</head>
+<body ondragleave="window.location.reload()">
+<p><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAEq0lEQVR42u1dvU4bQRAeR0RCCilSp0peIoKGB4DSXYRDlcZlFClKBI4bB/kV/AymIDwCTahiicaioEOxhCsjWVTJziyKMfYZn+9ud3bvG2mEZB13u9+nndmf2Rki7fKFXtEBbVKD9o22jB4bPaND6hm9Mjo0enevw/vfevKMfbYl/8vv4HdBUkvFALhltG2A7dN3+pur8jv53fwN/hZkjjRo3eiuAatjdJA7CcnkDOSb/G1uQ6mFzUeDagaQrvl764yEJOU22LbUymXaGrRhOt40OvJOQvLIGUkbP9GLeIn4SM9NJ+tOTVI+Jq0ubY9sVFRNxy6DIWKWmEvpQ/ByQNumI+fBEjHrZ86lT8HJV3ptGn8aDRGzxJxKHwMZFe9Mg6+jJWNCyrX0VbUc0nuj4+jJmPiWsfRZodN+ZvSoNETMjpYjwUCFfKaXpjEnpSVjQsqJYOF5ZLw1elF6MiakXAgmnpw378DegIgZUm4EGw8jA2QsIuUbvXHpM2CmljFfhfsUO5uCA0/j6AudfZV5arv6WuVHcYs+ALwqKTkvHnmLoEwr8CJW9Llts9iNwvj3plzsfeWyIRnzrq37kfIzq6naBpA5a6bzlJgOl/SMkl+rklEFgIX5k5THwTYgIdwzcP2jhM/o19KsOeoArnBS6suaqo2gQnXCJWSwXNwXB4gBMFekNBeTwSGUmiMK4yNktDhsleNaAZRrUvYWmasuQHJOSDdpdKyriEIvo9maexWC70gAIF/bKTvzzFUH4HgbJZ3HdFSw9vC6lfKHpq7X8X07AOOblK2HhLQBindC2g/9Rx+gePcj/cnqHIDoUFm1c9gjwNAy/d0kyXIAMLSYrQ8kqScAhhbH3iLJBwIwtBByTJKkBWBoIeSMJHMOwNBCyG+SdEYAQ4tTvyLJMQUwtBAyJEn8BTC0EHIHQhQSApOlzGTBqaty6jzVAhhaCOlhYahuYYitE02EHGNzURchLZItX4ChhZB9HFBpUjmgwhGuHv0feI0gBw1T3j7CgHT5jzYC5XQRsjUdSsrhjADGl7ka0EylBgRb+ySkMy9rww7A8Waududf2MH9Qh9k3CbXLsGVNh/mqrvojuEeQHI+Qmq4Fq1ndIyeruaDxAEuCWk+ncmB0z3gepubtQenMUHyGTWELJl8xk6B15CeqVAyLtPXtUICsyJnVivWs+J0dAAwbzLOkQRTk2YuKsapTQFkXqPjlDILEinnRcZ1fpXdkGo866xqnH9FNyTjz0JIQZXcuPQCAE5rqo6oMEFBl7RknBRfTg8lj5Yl48JdGT0ueIWiYIvIuHFfPg9l85LJcF42b+JTUFjysZnyVlhy2qfA0asovTo9+0JxYnWC8t0KBQXuFYrdkIy3mBj3LbeNQrejZTuqOlbcl8znGTqcfjXoM3pboqgaPhEPxda1qgcVYsRt5TanDkgISWzcV1N1hCS3jdu4dNxUDMIhlBzXysHGGspkcBtsW2pPh3fGLrZ2ya5cXHFp0qxJ6si3E68EQCpy344vQRZxO5jfye+2d/oqgHsV02Z3lvcl9QTnA+EkLZw5h9MZcY4pTvxldXj/W0+esc+25H/5HQGYon+Q5f+MwFz+8QAAAABJRU5ErkJggg==" alt="PNG circle" ondragstart="event.dataTransfer.effectAllowed = 'copy'"/></p>
+<p>Drag circle above to the box below. It should be copied to the box once you drop it there.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/reload/012-2.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/reload/012-2.xhtml
new file mode 100644
index 00000000000..ae8560b14c2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/reload/012-2.xhtml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Reload during drag and drop: helper file</title>
+<style type="text/css">
+div[ondragenter]
+ {width:105px;
+ min-height:105px;
+ text-align:center;
+ margin-top:20px;
+ padding:10px;
+ border:solid thin navy;}
+</style>
+<script type="application/ecmascript">
+function addImage(event)
+ {var c = document.createElement('img');
+ c.setAttribute('src',event.dataTransfer.getData('text/uri-list').replace(/\r\n$/,''));
+ document.querySelector('div').appendChild(c);}
+</script>
+</head>
+<body>
+<div
+ ondragenter="event.preventDefault()"
+ ondragover="return false"
+ ondrop="addImage(event)"
+/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/reload/012.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/reload/012.xhtml
new file mode 100644
index 00000000000..d4028cc7204
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/reload/012.xhtml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Reload during drag and drop of image between frames</title>
+</head>
+<frameset rows="50%, 50%">
+<frame src="012-1.xhtml"/>
+<frame src="012-2.xhtml"/>
+</frameset>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/remove/001.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/remove/001.xhtml
new file mode 100644
index 00000000000..1ab5013cc88
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/remove/001.xhtml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Removing canvas element during drag and drop</title>
+<style type="text/css">
+div
+ {height:100px;
+ width:100px;
+ padding:20px;
+ background-color:silver;}
+</style>
+<script type="application/ecmascript">
+function addImage(event)
+ {var c = document.createElement('img');
+ c.setAttribute('src',event.dataTransfer.getData('text/uri-list').replace(/\r\n$/,''));
+ document.querySelector('div').appendChild(c);}
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ event.dataTransfer.setData('text/uri-list', document.querySelector('canvas').toDataURL('image/png'));
+ document.querySelector('p').removeChild(canvas);}
+</script>
+</head>
+<body>
+<p>
+ <canvas width="100" height="100" draggable="true" ondragstart="start(event)">Canvas</canvas>
+</p>
+<p>Drag canvas pattern to the silver box below and drop it. It should be copied to the box once you drop it there.</p>
+<div ondragover="return false" ondrop="addImage(event)"/>
+<script type="application/ecmascript">
+var canvas = document.querySelector('canvas'),
+c = canvas.getContext('2d');
+for(var x = 0; x != 50; x++)
+ {c.fillStyle = (x%2 == 0)?'navy':'white';
+ c.beginPath();
+ c.moveTo(x,x);
+ c.lineTo(100-x,x);
+ c.lineTo(100-x,100-x);
+ c.lineTo(x,100-x);
+ c.closePath();
+ c.fill();}
+</script>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/remove/002.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/remove/002.xhtml
new file mode 100644
index 00000000000..02a9dc7484c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/remove/002.xhtml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Removing image element during drag and drop of PNG image</title>
+<style type="text/css">
+div
+ {height:100px;
+ width:100px;
+ padding:20px;
+ background-color:silver;}
+</style>
+<script type="application/ecmascript">
+function addImage(event)
+ {var c = document.createElement('img');
+ c.setAttribute('src',event.dataTransfer.getData('text/uri-list').replace(/\r\n$/,''));
+ document.querySelector('div').appendChild(c);}
+</script>
+</head>
+<body>
+<p><img ondragstart="event.dataTransfer.effectAllowed = 'copy';document.querySelector('p').removeChild(document.querySelector('img'))" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAEq0lEQVR42u1dvU4bQRAeR0RCCilSp0peIoKGB4DSXYRDlcZlFClKBI4bB/kV/AymIDwCTahiicaioEOxhCsjWVTJziyKMfYZn+9ud3bvG2mEZB13u9+nndmf2Rki7fKFXtEBbVKD9o22jB4bPaND6hm9Mjo0enevw/vfevKMfbYl/8vv4HdBUkvFALhltG2A7dN3+pur8jv53fwN/hZkjjRo3eiuAatjdJA7CcnkDOSb/G1uQ6mFzUeDagaQrvl764yEJOU22LbUymXaGrRhOt40OvJOQvLIGUkbP9GLeIn4SM9NJ+tOTVI+Jq0ubY9sVFRNxy6DIWKWmEvpQ/ByQNumI+fBEjHrZ86lT8HJV3ptGn8aDRGzxJxKHwMZFe9Mg6+jJWNCyrX0VbUc0nuj4+jJmPiWsfRZodN+ZvSoNETMjpYjwUCFfKaXpjEnpSVjQsqJYOF5ZLw1elF6MiakXAgmnpw378DegIgZUm4EGw8jA2QsIuUbvXHpM2CmljFfhfsUO5uCA0/j6AudfZV5arv6WuVHcYs+ALwqKTkvHnmLoEwr8CJW9Llts9iNwvj3plzsfeWyIRnzrq37kfIzq6naBpA5a6bzlJgOl/SMkl+rklEFgIX5k5THwTYgIdwzcP2jhM/o19KsOeoArnBS6suaqo2gQnXCJWSwXNwXB4gBMFekNBeTwSGUmiMK4yNktDhsleNaAZRrUvYWmasuQHJOSDdpdKyriEIvo9maexWC70gAIF/bKTvzzFUH4HgbJZ3HdFSw9vC6lfKHpq7X8X07AOOblK2HhLQBindC2g/9Rx+gePcj/cnqHIDoUFm1c9gjwNAy/d0kyXIAMLSYrQ8kqScAhhbH3iLJBwIwtBByTJKkBWBoIeSMJHMOwNBCyG+SdEYAQ4tTvyLJMQUwtBAyJEn8BTC0EHIHQhQSApOlzGTBqaty6jzVAhhaCOlhYahuYYitE02EHGNzURchLZItX4ChhZB9HFBpUjmgwhGuHv0feI0gBw1T3j7CgHT5jzYC5XQRsjUdSsrhjADGl7ka0EylBgRb+ySkMy9rww7A8Waududf2MH9Qh9k3CbXLsGVNh/mqrvojuEeQHI+Qmq4Fq1ndIyeruaDxAEuCWk+ncmB0z3gepubtQenMUHyGTWELJl8xk6B15CeqVAyLtPXtUICsyJnVivWs+J0dAAwbzLOkQRTk2YuKsapTQFkXqPjlDILEinnRcZ1fpXdkGo866xqnH9FNyTjz0JIQZXcuPQCAE5rqo6oMEFBl7RknBRfTg8lj5Yl48JdGT0ueIWiYIvIuHFfPg9l85LJcF42b+JTUFjysZnyVlhy2qfA0asovTo9+0JxYnWC8t0KBQXuFYrdkIy3mBj3LbeNQrejZTuqOlbcl8znGTqcfjXoM3pboqgaPhEPxda1qgcVYsRt5TanDkgISWzcV1N1hCS3jdu4dNxUDMIhlBzXysHGGspkcBtsW2pPh3fGLrZ2ya5cXHFp0qxJ6si3E68EQCpy344vQRZxO5jfye+2d/oqgHsV02Z3lvcl9QTnA+EkLZw5h9MZcY4pTvxldXj/W0+esc+25H/5HQGYon+Q5f+MwFz+8QAAAABJRU5ErkJggg==" alt="PNG circle"/></p>
+<p>Drag green circle to the silver box below and drop it. It should be copied to the box once you drop it there.</p>
+<div ondragover="return false" ondrop="addImage(event)"/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/remove/003.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/remove/003.xhtml
new file mode 100644
index 00000000000..33eeb6a5793
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/remove/003.xhtml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Removing image element during drag and drop of SVG image</title>
+<style type="text/css">
+div
+ {height:100px;
+ width:100px;
+ padding:20px;
+ background-color:silver;}
+</style>
+<script type="application/ecmascript">
+function addImage(event)
+ {var c = document.createElement('img');
+ c.setAttribute('src',event.dataTransfer.getData('text/uri-list').replace(/\r\n$/,''));
+ document.querySelector('div').appendChild(c);}
+</script>
+</head>
+<body>
+<p><img ondragstart="event.dataTransfer.effectAllowed = 'copy';document.querySelector('p').removeChild(document.querySelector('img'))" src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20version%3D%221.1%22%20width%3D%22100px%22%20height%3D%22100px%22%20viewBox%3D%220%200%20100%20100%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22green%22/%3E%3C/svg%3E" alt="SVG circle"/></p>
+<p>Drag green circle to the silver box below and drop it. It should be copied to the box once you drop it there.</p>
+<div ondragover="return false" ondrop="addImage(event)"/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/remove/004.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/remove/004.xhtml
new file mode 100644
index 00000000000..44db0193349
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/remove/004.xhtml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Removing input element during drag and drop of selection</title>
+<style type="text/css">
+div
+ {min-height:100px;
+ width:100px;
+ padding:20px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body onload="document.querySelector('input').select()">
+<p><input value="Drag me" ondragstart="document.querySelector('p').removeChild(document.querySelector('input'))"/></p>
+<p>Drag selection above to the navy box below and drop it. You should see word PASS once you drop it in the box.</p>
+<div ondragover="return false" ondrop="document.querySelector('div').appendChild(document.createTextNode((event.dataTransfer.getData('text/plain') == 'Drag me')?'PASS':'FAIL'))"/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/remove/005.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/remove/005.xhtml
new file mode 100644
index 00000000000..23faac7cd49
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/remove/005.xhtml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Removing span element during drag and drop of selection</title>
+<style type="text/css">
+div
+ {min-height:100px;
+ width:100px;
+ padding:20px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('span'))">
+<p><span ondragstart="document.querySelector('p').removeChild(document.querySelector('span'))">Drag me</span></p>
+<p>Drag selection above to the navy box below and drop it. You should see word PASS once you drop it in the box.</p>
+<div ondragover="return false" ondrop="document.querySelector('div').appendChild(document.createTextNode((event.dataTransfer.getData('text/plain') == 'Drag me')?'PASS':'FAIL'))"/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/remove/006.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/remove/006.xhtml
new file mode 100644
index 00000000000..0b3b92c6033
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/remove/006.xhtml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Removing a element during drag and drop of link</title>
+<style type="text/css">
+div
+ {min-height:100px;
+ width:100px;
+ padding:20px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body>
+<p><a href="data:text/plain,1" ondragstart="event.dataTransfer.effectAllowed = 'copy';document.querySelector('p').removeChild(document.querySelector('a'))">Drag me</a></p>
+<p>Drag link above to the navy box below and drop it. You should see word PASS once you drop it in the box.</p>
+<div ondragover="return false" ondrop="document.querySelector('div').appendChild(document.createTextNode((event.dataTransfer.getData('text/uri-list').replace(/\r\n$/,'') == 'data:text/plain,1')?'PASS':'FAIL'))"/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/remove/007.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/remove/007.xhtml
new file mode 100644
index 00000000000..fbda1862325
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/remove/007.xhtml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Removing div element during drag and drop with text/plain data</title>
+<style type="text/css">
+div
+ {width:40px;
+ height:40px;
+ margin-top:20px;
+ padding:40px;
+ color:white;
+ background-color:gray;}
+p + div
+ {background-color:navy;}
+</style>
+</head>
+<body>
+<div
+ draggable="true"
+ ondragstart="event.dataTransfer.effectAllowed = 'copy';event.dataTransfer.setData('text/plain','PASS');document.querySelector('body').removeChild(document.querySelector('div'))"
+/>
+<p>Drag gray box above to the navy box below and drop it. You should see word PASS once you drop it.</p>
+<div
+ ondragover="return false"
+ ondrop="document.querySelector('div').appendChild(document.createTextNode(event.dataTransfer.getData('text/plain')))"
+/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/remove/008.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/remove/008.xhtml
new file mode 100644
index 00000000000..24aff7ea910
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/remove/008.xhtml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Removing div element during drag and drop with text/uri-list data</title>
+<style type="text/css">
+div
+ {width:40px;
+ height:40px;
+ margin-top:20px;
+ padding:40px;
+ color:white;
+ background-color:gray;}
+p + div
+ {background-color:navy;}
+</style>
+</head>
+<body>
+<div
+ draggable="true"
+ ondragstart="event.dataTransfer.effectAllowed = 'copy';event.dataTransfer.setData('text/uri-list','data:text/plain,PASS');document.querySelector('body').removeChild(document.querySelector('div'))"
+/>
+<p>Drag gray box above to the navy box below and drop it. You should see word PASS once you drop it.</p>
+<div
+ ondragover="return false"
+ ondrop="document.querySelector('div').appendChild(document.createTextNode(event.dataTransfer.getData('text/uri-list').substr(16,4)))"
+/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/remove/009.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/remove/009.xhtml
new file mode 100644
index 00000000000..5d1aa6989d4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/remove/009.xhtml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Changing iframe content during drag and drop of link</title>
+<style type="text/css">
+iframe
+ {height:100px;
+ width:300px;
+ border:solid medium navy;}
+</style>
+</head>
+<body ondragenter="event.preventDefault();document.querySelector('iframe').src = 'data:text/plain,Drop%20link%20outside%20this%20frame'" ondragover="return false" ondrop="document.querySelector('p').firstChild.nodeValue = (event.dataTransfer.getData('text/uri-list').replace(/\r\n$/,'') == 'data:text/plain,1')?'PASS':'FAIL'">
+<iframe src="helper-drag-me-link.xhtml">XHTML document</iframe>
+<p>Drag link above out of frame and drop it somewhere on the page. You should see word PASS once you drop it.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/remove/010.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/remove/010.xhtml
new file mode 100644
index 00000000000..f0e60927704
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/remove/010.xhtml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Changing object content during drag and drop of link</title>
+<style type="text/css">
+object
+ {height:100px;
+ width:300px;
+ border:solid medium navy;}
+</style>
+</head>
+<body ondragenter="event.preventDefault();document.querySelector('object').setAttribute('data','data:text/plain,Drop%20link%20outside%20this%20frame')" ondragover="return false" ondrop="document.querySelector('p').firstChild.nodeValue = (event.dataTransfer.getData('text/uri-list').replace(/\r\n$/,'') == 'data:text/plain,1')?'PASS':'FAIL'">
+<object type="application/xhtml+xml" data="helper-drag-me-link.xhtml">XHTML document</object>
+<p>Drag link above out of frame and drop it somewhere on the page. You should see word PASS once you drop it.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/remove/011.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/remove/011.xhtml
new file mode 100644
index 00000000000..3fc9f0a07aa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/remove/011.xhtml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Changing iframe content during drag and drop of text input selection</title>
+<style type="text/css">
+iframe
+ {height:100px;
+ width:300px;
+ border:solid medium navy;}
+</style>
+</head>
+<body ondragenter="event.preventDefault();document.querySelector('iframe').src = 'data:text/plain,Drop%20selection%20outside%20this%20frame'" ondragover="return false" ondrop="document.querySelector('p').firstChild.nodeValue = (event.dataTransfer.getData('text/plain') == 'Drag me')?'PASS':'FAIL'">
+<iframe src="helper-drag-me-input.xhtml">XHTML document</iframe>
+<p>Drag selection above out of frame and drop it somewhere on the page. You should see word PASS once you drop it.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/remove/012.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/remove/012.xhtml
new file mode 100644
index 00000000000..ab6e2db37e5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/remove/012.xhtml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Changing object content during drag and drop of text input selection</title>
+<style type="text/css">
+object
+ {height:100px;
+ width:300px;
+ border:solid medium navy;}
+</style>
+</head>
+<body ondragenter="event.preventDefault();document.querySelector('object').setAttribute('data','data:text/plain,Drop%20selection%20outside%20this%20frame')" ondragover="return false" ondrop="document.querySelector('p').firstChild.nodeValue = (event.dataTransfer.getData('text/plain') == 'Drag me')?'PASS':'FAIL'">
+<object type="application/xhtml+xml" data="helper-drag-me-input.xhtml">XHTML document</object>
+<p>Drag selection above out of frame and drop it somewhere on the page. You should see word PASS once you drop it.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/remove/013.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/remove/013.xhtml
new file mode 100644
index 00000000000..0bacf9e5676
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/remove/013.xhtml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Changing iframe content during drag and drop of selection</title>
+<style type="text/css">
+iframe
+ {height:100px;
+ width:300px;
+ border:solid medium navy;}
+</style>
+</head>
+<body ondragenter="event.preventDefault();document.querySelector('iframe').src = 'data:text/plain,Drop%20selection%20outside%20this%20frame'" ondragover="return false" ondrop="document.querySelector('p').firstChild.nodeValue = (event.dataTransfer.getData('text/plain') == 'Drag me')?'PASS':'FAIL'">
+<iframe src="helper-drag-me-p.xhtml">XHTML document</iframe>
+<p>Drag selection above out of frame and drop it somewhere on the page. You should see word PASS once you drop it.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/remove/014.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/remove/014.xhtml
new file mode 100644
index 00000000000..93fae6f31a1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/remove/014.xhtml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Changing object content during drag and drop of selection</title>
+<style type="text/css">
+object
+ {height:100px;
+ width:300px;
+ border:solid medium navy;}
+</style>
+</head>
+<body ondragenter="event.preventDefault();document.querySelector('object').setAttribute('data','data:text/plain,Drop%20selection%20outside%20this%20frame')" ondragover="return false" ondrop="document.querySelector('p').firstChild.nodeValue = (event.dataTransfer.getData('text/plain') == 'Drag me')?'PASS':'FAIL'">
+<object type="application/xhtml+xml" data="helper-drag-me-p.xhtml">XHTML document</object>
+<p>Drag selection above out of frame and drop it somewhere on the page. You should see word PASS once you drop it.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/remove/015.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/remove/015.xhtml
new file mode 100644
index 00000000000..dcba8d49025
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/remove/015.xhtml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Removing iframe during drag and drop of link</title>
+<style type="text/css">
+iframe
+ {height:100px;
+ width:300px;
+ border:solid medium navy;}
+</style>
+</head>
+<body ondragenter="event.preventDefault();document.querySelector('body').removeChild(document.querySelector('iframe'))" ondragover="return false" ondrop="document.querySelector('p').firstChild.nodeValue = (event.dataTransfer.getData('text/uri-list').replace(/\r\n$/,'') == 'data:text/plain,1')?'PASS':'FAIL'">
+<iframe src="helper-drag-me-link.xhtml">XHTML document</iframe>
+<p>Drag link above out of frame and drop it somewhere on the page. You should see word PASS once you drop it.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/remove/016.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/remove/016.xhtml
new file mode 100644
index 00000000000..3e2881eb0b6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/remove/016.xhtml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Removing object during drag and drop of link</title>
+<style type="text/css">
+object
+ {height:100px;
+ width:300px;
+ border:solid medium navy;}
+</style>
+</head>
+<body ondragenter="event.preventDefault();document.querySelector('body').removeChild(document.querySelector('object'))" ondragover="return false" ondrop="document.querySelector('p').firstChild.nodeValue = (event.dataTransfer.getData('text/uri-list').replace(/\r\n$/,'') == 'data:text/plain,1')?'PASS':'FAIL'">
+<object type="application/xhtml+xml" data="helper-drag-me-link.xhtml">XHTML document</object>
+<p>Drag link above out of frame and drop it somewhere on the page. You should see word PASS once you drop it.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/remove/017.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/remove/017.xhtml
new file mode 100644
index 00000000000..d7c33101743
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/remove/017.xhtml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Removing iframe during drag and drop of text input selection</title>
+<style type="text/css">
+iframe
+ {height:100px;
+ width:300px;
+ border:solid medium navy;}
+</style>
+</head>
+<body ondragenter="event.preventDefault();document.querySelector('body').removeChild(document.querySelector('iframe'))" ondragover="return false" ondrop="document.querySelector('p').firstChild.nodeValue = (event.dataTransfer.getData('text/plain') == 'Drag me')?'PASS':'FAIL'">
+<iframe src="helper-drag-me-input.xhtml">XHTML document</iframe>
+<p>Drag selection above out of frame and drop it somewhere on the page. You should see word PASS once you drop it.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/remove/018.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/remove/018.xhtml
new file mode 100644
index 00000000000..2dda93fe938
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/remove/018.xhtml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Removing object during drag and drop of text input selection</title>
+<style type="text/css">
+object
+ {height:100px;
+ width:300px;
+ border:solid medium navy;}
+</style>
+</head>
+<body ondragenter="event.preventDefault();document.querySelector('body').removeChild(document.querySelector('object'))" ondragover="return false" ondrop="document.querySelector('p').firstChild.nodeValue = (event.dataTransfer.getData('text/plain') == 'Drag me')?'PASS':'FAIL'">
+<object type="application/xhtml+xml" data="helper-drag-me-input.xhtml">XHTML document</object>
+<p>Drag selection above out of frame and drop it somewhere on the page. You should see word PASS once you drop it.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/remove/019.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/remove/019.xhtml
new file mode 100644
index 00000000000..86969550f59
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/remove/019.xhtml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Removing iframe during drag and drop of selection</title>
+<style type="text/css">
+iframe
+ {height:100px;
+ width:300px;
+ border:solid medium navy;}
+</style>
+</head>
+<body ondragenter="event.preventDefault();document.querySelector('body').removeChild(document.querySelector('iframe'))" ondragover="return false" ondrop="document.querySelector('p').firstChild.nodeValue = (event.dataTransfer.getData('text/plain') == 'Drag me')?'PASS':'FAIL'">
+<iframe src="helper-drag-me-p.xhtml">XHTML document</iframe>
+<p>Drag selection above out of frame and drop it somewhere on the page. You should see word PASS once you drop it.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/remove/020.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/remove/020.xhtml
new file mode 100644
index 00000000000..f5bc7d464f9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/remove/020.xhtml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Removing object during drag and drop of selection</title>
+<style type="text/css">
+object
+ {height:100px;
+ width:300px;
+ border:solid medium navy;}
+</style>
+</head>
+<body ondragenter="event.preventDefault();document.querySelector('body').removeChild(document.querySelector('object'))" ondragover="return false" ondrop="document.querySelector('p').firstChild.nodeValue = (event.dataTransfer.getData('text/plain') == 'Drag me')?'PASS':'FAIL'">
+<object type="application/xhtml+xml" data="helper-drag-me-p.xhtml">XHTML document</object>
+<p>Drag selection above out of frame and drop it somewhere on the page. You should see word PASS once you drop it.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/remove/021.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/remove/021.xhtml
new file mode 100644
index 00000000000..fe67ded93c0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/remove/021.xhtml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Removing a element during drag and drop of url</title>
+<style type="text/css">
+div
+ {min-height:100px;
+ width:100px;
+ padding:20px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body>
+<p><a href="data:text/plain,1" ondragstart="event.dataTransfer.effectAllowed = 'copy';document.querySelector('p').removeChild(document.querySelector('a'))">Drag me</a></p>
+<p>Drag selection above to the navy box below and drop it. You should see word PASS once you drop it in the box.</p>
+<div ondragenter="event.preventDefault()" ondragover="return false" ondrop="document.querySelector('div').appendChild(document.createTextNode((event.dataTransfer.getData('url') == 'data:text/plain,1')?'PASS':'FAIL'))"/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/remove/022-1.html b/tests/wpt/web-platform-tests/html/editing/dnd/remove/022-1.html
new file mode 100644
index 00000000000..fe65c604536
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/remove/022-1.html
@@ -0,0 +1,26 @@
+<!doctype html>
+<title>Removing drop targetted document before the queue is processed</title>
+<style>
+ html, body, div {
+ height: 100%;
+ width: 100%;
+ margin: 0;
+ padding: 0;
+ background-color: blue;
+ }
+</style>
+<script type="text/javascript">
+window.onload = function () {
+ var blue = document.getElementsByTagName('div')[0];
+ blue.ondragenter = blue.ondragover = blue.ondrop = function (e) {
+ e.preventDefault();
+ };
+ window.addEventListener('message',function (){
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET','/common/blank.html?pipe=trickle(d5)',false);
+ xhr.send(null); //should not end within the lifetime of this document
+ },false);
+};
+</script>
+<div></div>
+<noscript><p>Enable JavaScript and reload</p></noscript>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/remove/022.html b/tests/wpt/web-platform-tests/html/editing/dnd/remove/022.html
new file mode 100644
index 00000000000..6bb8e6adefb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/remove/022.html
@@ -0,0 +1,28 @@
+<!doctype html>
+<title>Removing drop targetted document before the queue is processed</title>
+<style>
+ span, iframe {
+ height: 200px;
+ width: 200px;
+ background-color: orange;
+ display: inline-block;
+ border: none;
+ }
+</style>
+<script type="text/javascript">
+window.onload = function () {
+ var orange = document.getElementsByTagName('span')[0];
+ orange.ondragstart = function (e) {
+ e.dataTransfer.setData('text','dummy text');
+ e.dataTransfer.effectAllowed = 'all';
+ document.getElementsByTagName('iframe')[0].contentWindow.postMessage('dummy message','*');
+ setTimeout(function () {
+ document.getElementsByTagName('p')[0].removeChild(document.getElementsByTagName('iframe')[0]);
+ },4000);
+ };
+};
+</script>
+<p><span draggable="true"></span> <iframe height="200" width="200" src="022-1.html"></iframe></p>
+
+<p>Drag the orange square over the blue square, then release it. Wait 5 seconds for the blue square to disappear. Pass if you can select this text.</li>
+<noscript><p>Enable JavaScript and reload</p></noscript> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/remove/helper-drag-me-input.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/remove/helper-drag-me-input.xhtml
new file mode 100644
index 00000000000..ca87466cd2e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/remove/helper-drag-me-input.xhtml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop: helper file</title>
+</head>
+<body onload="document.querySelector('input').select()">
+<p><input value="Drag me"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/remove/helper-drag-me-link.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/remove/helper-drag-me-link.xhtml
new file mode 100644
index 00000000000..9062014b455
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/remove/helper-drag-me-link.xhtml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Link drag and drop: helper file</title>
+</head>
+<body>
+<p><a href="data:text/plain,1" ondragstart="event.dataTransfer.effectAllowed = 'copy'">Drag me</a></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/remove/helper-drag-me-p.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/remove/helper-drag-me-p.xhtml
new file mode 100644
index 00000000000..5e11544c4e3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/remove/helper-drag-me-p.xhtml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop: helper file</title>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('p'))">
+<p>Drag me</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/resources/100x100-navy.png b/tests/wpt/web-platform-tests/html/editing/dnd/resources/100x100-navy.png
new file mode 100644
index 00000000000..ee8f953c001
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/resources/100x100-navy.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/resources/1x1-transparent.gif b/tests/wpt/web-platform-tests/html/editing/dnd/resources/1x1-transparent.gif
new file mode 100644
index 00000000000..e565824aafa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/resources/1x1-transparent.gif
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/resources/boxnavy.swf b/tests/wpt/web-platform-tests/html/editing/dnd/resources/boxnavy.swf
new file mode 100644
index 00000000000..c4ef5889a33
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/resources/boxnavy.swf
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/resources/circle.png b/tests/wpt/web-platform-tests/html/editing/dnd/resources/circle.png
new file mode 100644
index 00000000000..8bb141cb8c7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/resources/circle.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/resources/crossorigin.sub.js b/tests/wpt/web-platform-tests/html/editing/dnd/resources/crossorigin.sub.js
new file mode 100644
index 00000000000..d6aaa18ad76
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/resources/crossorigin.sub.js
@@ -0,0 +1,13 @@
+var httpHostMain = '{{domains[]}}'; //name of the server that this page must accessed over port 80
+var httpHostAlias = '{{domains[www]}}'; //another hostname (must be a subdomain so document.domain can be set to a higher domain) that accesses the same content, over HTTP
+var httpsHostAlias = httpHostAlias; //another hostname (can be same as httpHostAlias) that accesses the same content, over HTTPS port
+var httpPortAlias = {{ports[http][0]}}; //another port that accesses the same content on the current hostname, over HTTP
+//XXX HTTPS
+//var httpsPortAlias = ports[https][0]; //another port that accesses the same content on the httpsHostAlias, over HTTPS
+var httpsPortAlias = 8443;
+
+function crossOriginUrl(subdomain, relative_url) {
+ var a = document.createElement("a");
+ a.href = relative_url;
+ return a.href.replace(location.href.replace("://", "://" + subdomain + "."));
+}
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/resources/fail.png b/tests/wpt/web-platform-tests/html/editing/dnd/resources/fail.png
new file mode 100644
index 00000000000..b5933803338
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/resources/fail.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/resources/filler.html b/tests/wpt/web-platform-tests/html/editing/dnd/resources/filler.html
new file mode 100644
index 00000000000..6ca9868ac2e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/resources/filler.html
@@ -0,0 +1,109 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+ <title>Filler text</title>
+</head>
+<body>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text</p>
+ <p>Filler text (end)</p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/resources/pass.png b/tests/wpt/web-platform-tests/html/editing/dnd/resources/pass.png
new file mode 100644
index 00000000000..2fa1e0ac066
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/resources/pass.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/roundtrip/001.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/roundtrip/001.xhtml
new file mode 100644
index 00000000000..671f143f5e2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/roundtrip/001.xhtml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Canvas drag and drop roundtrip</title>
+<style type="text/css">
+img
+ {margin:0 2px;}
+</style>
+<script type="application/ecmascript">
+function addImage(event)
+ {var c = document.createElement('img');
+ c.setAttribute('src',event.dataTransfer.getData('text/uri-list').replace(/\r\n$/,''));
+ document.querySelector('p').appendChild(c);}
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ event.dataTransfer.setData('text/uri-list', document.querySelector('canvas').toDataURL('image/png'));}
+</script>
+</head>
+<body>
+<p>
+ <canvas width="100" height="100" draggable="true" ondragstart="start(event)" ondragenter="event.preventDefault()" ondragover="return false" ondrop="addImage(event)">Canvas</canvas>
+</p>
+<p>Drag canvas pattern outside browser window and then drag it back and drop on itself. It should be duplicated once you drop it.</p>
+<script type="application/ecmascript">
+var canvas = document.querySelector('canvas'),
+c = canvas.getContext('2d');
+for(var x = 0; x != 50; x++)
+ {c.fillStyle = (x%2 == 0)?'navy':'white';
+ c.beginPath();
+ c.moveTo(x,x);
+ c.lineTo(100-x,x);
+ c.lineTo(100-x,100-x);
+ c.lineTo(x,100-x);
+ c.closePath();
+ c.fill();}
+</script>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/roundtrip/002.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/roundtrip/002.xhtml
new file mode 100644
index 00000000000..c7106fdd973
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/roundtrip/002.xhtml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>PNG image drag and drop roundtrip</title>
+<style type="text/css">
+img
+ {margin:0 2px;}
+</style>
+<script type="application/ecmascript">
+function addImage(event)
+ {var c = document.createElement('img');
+ c.setAttribute('src',event.dataTransfer.getData('text/uri-list').replace(/\r\n$/,''));
+ document.querySelector('p').appendChild(c);}
+</script>
+</head>
+<body>
+<p><img ondragstart="event.dataTransfer.effectAllowed = 'copy'" ondragenter="event.preventDefault()" ondrop="addImage(event)" ondragover="return false" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAEq0lEQVR42u1dvU4bQRAeR0RCCilSp0peIoKGB4DSXYRDlcZlFClKBI4bB/kV/AymIDwCTahiicaioEOxhCsjWVTJziyKMfYZn+9ud3bvG2mEZB13u9+nndmf2Rki7fKFXtEBbVKD9o22jB4bPaND6hm9Mjo0enevw/vfevKMfbYl/8vv4HdBUkvFALhltG2A7dN3+pur8jv53fwN/hZkjjRo3eiuAatjdJA7CcnkDOSb/G1uQ6mFzUeDagaQrvl764yEJOU22LbUymXaGrRhOt40OvJOQvLIGUkbP9GLeIn4SM9NJ+tOTVI+Jq0ubY9sVFRNxy6DIWKWmEvpQ/ByQNumI+fBEjHrZ86lT8HJV3ptGn8aDRGzxJxKHwMZFe9Mg6+jJWNCyrX0VbUc0nuj4+jJmPiWsfRZodN+ZvSoNETMjpYjwUCFfKaXpjEnpSVjQsqJYOF5ZLw1elF6MiakXAgmnpw378DegIgZUm4EGw8jA2QsIuUbvXHpM2CmljFfhfsUO5uCA0/j6AudfZV5arv6WuVHcYs+ALwqKTkvHnmLoEwr8CJW9Llts9iNwvj3plzsfeWyIRnzrq37kfIzq6naBpA5a6bzlJgOl/SMkl+rklEFgIX5k5THwTYgIdwzcP2jhM/o19KsOeoArnBS6suaqo2gQnXCJWSwXNwXB4gBMFekNBeTwSGUmiMK4yNktDhsleNaAZRrUvYWmasuQHJOSDdpdKyriEIvo9maexWC70gAIF/bKTvzzFUH4HgbJZ3HdFSw9vC6lfKHpq7X8X07AOOblK2HhLQBindC2g/9Rx+gePcj/cnqHIDoUFm1c9gjwNAy/d0kyXIAMLSYrQ8kqScAhhbH3iLJBwIwtBByTJKkBWBoIeSMJHMOwNBCyG+SdEYAQ4tTvyLJMQUwtBAyJEn8BTC0EHIHQhQSApOlzGTBqaty6jzVAhhaCOlhYahuYYitE02EHGNzURchLZItX4ChhZB9HFBpUjmgwhGuHv0feI0gBw1T3j7CgHT5jzYC5XQRsjUdSsrhjADGl7ka0EylBgRb+ySkMy9rww7A8Waududf2MH9Qh9k3CbXLsGVNh/mqrvojuEeQHI+Qmq4Fq1ndIyeruaDxAEuCWk+ncmB0z3gepubtQenMUHyGTWELJl8xk6B15CeqVAyLtPXtUICsyJnVivWs+J0dAAwbzLOkQRTk2YuKsapTQFkXqPjlDILEinnRcZ1fpXdkGo866xqnH9FNyTjz0JIQZXcuPQCAE5rqo6oMEFBl7RknBRfTg8lj5Yl48JdGT0ueIWiYIvIuHFfPg9l85LJcF42b+JTUFjysZnyVlhy2qfA0asovTo9+0JxYnWC8t0KBQXuFYrdkIy3mBj3LbeNQrejZTuqOlbcl8znGTqcfjXoM3pboqgaPhEPxda1qgcVYsRt5TanDkgISWzcV1N1hCS3jdu4dNxUDMIhlBzXysHGGspkcBtsW2pPh3fGLrZ2ya5cXHFp0qxJ6si3E68EQCpy344vQRZxO5jfye+2d/oqgHsV02Z3lvcl9QTnA+EkLZw5h9MZcY4pTvxldXj/W0+esc+25H/5HQGYon+Q5f+MwFz+8QAAAABJRU5ErkJggg==" alt="PNG circle"/></p>
+<p>Drag circle outside browser window and then drag it back and drop on itself. It should be duplicated once you drop it.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/roundtrip/003.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/roundtrip/003.xhtml
new file mode 100644
index 00000000000..0f89a367c5a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/roundtrip/003.xhtml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>SVG image drag and drop roundtrip</title>
+<style type="text/css">
+img
+ {margin:0 2px;}
+</style>
+<script type="application/ecmascript">
+function addImage(event)
+ {var c = document.createElement('img');
+ c.setAttribute('src',event.dataTransfer.getData('text/uri-list').replace(/\r\n$/,''));
+ document.querySelector('p').appendChild(c);}
+</script>
+</head>
+<body>
+<p><img ondragstart="event.dataTransfer.effectAllowed = 'copy'" ondragenter="event.preventDefault()" ondrop="addImage(event)" ondragover="return false" src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20version%3D%221.1%22%20width%3D%22100px%22%20height%3D%22100px%22%20viewBox%3D%220%200%20100%20100%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22green%22/%3E%3C/svg%3E" alt="SVG circle"/></p>
+<p>Drag circle outside browser window and then drag it back and drop on itself. It should be duplicated once you drop it.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/roundtrip/004.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/roundtrip/004.xhtml
new file mode 100644
index 00000000000..0b31a5989b8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/roundtrip/004.xhtml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Text input selection drag and drop roundtrip</title>
+</head>
+<body onload="document.querySelector('input').select()">
+<p><input value="Drag me" ondragenter="event.preventDefault()" ondragover="return false" ondrop="event.preventDefault();this.value = (event.dataTransfer.getData('text/plain') == 'Drag me')?'PASS':'FAIL'"/></p>
+<p>Drag selected text outside browser window and then drag it back and drop on itself. You should see word PASS once you drop it.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/roundtrip/005.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/roundtrip/005.xhtml
new file mode 100644
index 00000000000..e482fb2a0fa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/roundtrip/005.xhtml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop roundtrip</title>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('span'))">
+<p><span ondragenter="event.preventDefault()" ondragover="return false" ondrop="document.querySelector('span').firstChild.nodeValue = (event.dataTransfer.getData('text/plain') == 'Drag me')?'PASS':'FAIL'">Drag me</span></p>
+<p>Drag selected text outside browser window and then drag it back and drop on itself. You should see word PASS once you drop it.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/roundtrip/006.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/roundtrip/006.xhtml
new file mode 100644
index 00000000000..d609a72b85c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/roundtrip/006.xhtml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Link drag and drop roundtrip</title>
+<script type="application/ecmascript">
+function checkLink(event)
+ {document.querySelector('a').firstChild.nodeValue = (event.dataTransfer.getData('text/uri-list').replace(/\r\n$/,'') == 'data:text/plain,1')?'PASS':'FAIL'}
+</script>
+</head>
+<body>
+<p><a href="data:text/plain,1" ondragstart="event.dataTransfer.effectAllowed = 'copy'" ondragenter="event.preventDefault()" ondrop="checkLink(event)" ondragover="return false">Drag me</a></p>
+<p>Drag link outside browser window and then drag it back and drop on itself. You should see word PASS once you drop it.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/roundtrip/007.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/roundtrip/007.xhtml
new file mode 100644
index 00000000000..cfe4cb26f50
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/roundtrip/007.xhtml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop roundtrip with text/plain data</title>
+<style type="text/css">
+div[ondragenter]
+ {width:40px;
+ min-height:40px;
+ margin-top:20px;
+ padding:40px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body>
+<div
+ draggable="true"
+ ondragstart="event.dataTransfer.effectAllowed = 'copy';event.dataTransfer.setData('text/plain',' PASS ')"
+ ondragenter="event.preventDefault()"
+ ondragover="return false"
+ ondrop="document.querySelector('div').appendChild(document.createTextNode(event.dataTransfer.getData('text/plain')))"
+/>
+<p>Drag blue box outside browser window and then drag it back and drop on itself. You should see word PASS once you drop it.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/roundtrip/008.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/roundtrip/008.xhtml
new file mode 100644
index 00000000000..21adfb50a6b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/roundtrip/008.xhtml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop roundtrip with text/uri-list data</title>
+<style type="text/css">
+div[ondragenter]
+ {width:40px;
+ min-height:40px;
+ margin-top:20px;
+ padding:40px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body>
+<div
+ draggable="true"
+ ondragstart="event.dataTransfer.effectAllowed = 'copy';event.dataTransfer.setData('text/uri-list','data:text/plain,PASS')"
+ ondragenter="event.preventDefault()"
+ ondragover="return false"
+ ondrop="document.querySelector('div').appendChild(document.createTextNode(event.dataTransfer.getData('text/uri-list').substr(16,4) + ' '))"
+/>
+<p>Drag blue box outside browser window and then drag it back and drop on itself. You should see word PASS once you drop it.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/001.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/001.xhtml
new file mode 100644
index 00000000000..e1806f8e232
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/001.xhtml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from text input to block element</title>
+<style type="text/css">
+div[ondragenter]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected text to the blue box. Copy of selection should end up in the blue box once you drop it there.</p>
+<p><input value="Drag me"/></p>
+<div
+ ondragenter="event.preventDefault()"
+ ondragover="return false"
+ ondrop="document.querySelector('div').appendChild(document.createTextNode(event.dataTransfer.getData('text/plain')))"
+/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/002.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/002.xhtml
new file mode 100644
index 00000000000..55c457e5384
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/002.xhtml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from search input to block element</title>
+<style type="text/css">
+div[ondragenter]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected text to the blue box. Copy of selection should end up in the blue box once you drop it there.</p>
+<p><input type="search" value="Selection"/></p>
+<div
+ ondragenter="event.preventDefault()"
+ ondragover="return false"
+ ondrop="document.querySelector('div').appendChild(document.createTextNode(event.dataTransfer.getData('text/plain')))"
+/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/003.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/003.xhtml
new file mode 100644
index 00000000000..6430d603d58
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/003.xhtml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from tel input to block element</title>
+<style type="text/css">
+div[ondragenter]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected number to the blue box. Copy of selection should end up in the blue box once you drop it there.</p>
+<p><input type="tel" value="123456789"/></p>
+<div
+ ondragenter="event.preventDefault()"
+ ondragover="return false"
+ ondrop="document.querySelector('div').appendChild(document.createTextNode(event.dataTransfer.getData('text/plain')))"
+/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/004.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/004.xhtml
new file mode 100644
index 00000000000..1c6904853db
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/004.xhtml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from url input to block element</title>
+<style type="text/css">
+div[ondragenter]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected url to the blue box. Copy of selection should end up in the blue box once you drop it there.</p>
+<p><input type="url" value="http://example.org"/></p>
+<div
+ ondragenter="event.preventDefault()"
+ ondragover="return false"
+ ondrop="document.querySelector('div').appendChild(document.createTextNode(event.dataTransfer.getData('text/plain')))"
+/>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/005.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/005.xhtml
new file mode 100644
index 00000000000..a8d7056e451
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/005.xhtml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from email input to block element</title>
+<style type="text/css">
+div[ondragenter]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected email to the blue box. Copy of selection should end up in the blue box once you drop it there.</p>
+<p><input type="email" value="mail@example.org"/></p>
+<div
+ ondragenter="event.preventDefault()"
+ ondragover="return false"
+ ondrop="document.querySelector('div').appendChild(document.createTextNode(event.dataTransfer.getData('text/plain')))"
+/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/006.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/006.xhtml
new file mode 100644
index 00000000000..9a2b41e82b2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/006.xhtml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from number input to block element</title>
+<style type="text/css">
+div[ondragenter]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected number to the blue box. Copy of selection should end up in the blue box once you drop it there.</p>
+<p><input type="number" value="123456789"/></p>
+<div
+ ondragenter="event.preventDefault()"
+ ondragover="return false"
+ ondrop="document.querySelector('div').appendChild(document.createTextNode(event.dataTransfer.getData('text/plain')))"
+/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/007.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/007.xhtml
new file mode 100644
index 00000000000..2b5d05a50a3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/007.xhtml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from short text input to block element</title>
+<style type="text/css">
+div[ondragenter]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected date to the blue box. Copy of selection should end up in the blue box once you drop it there.</p>
+<p><input size="5" value="Drag me"/></p>
+<div
+ ondragenter="event.preventDefault()"
+ ondragover="return false"
+ ondrop="document.querySelector('div').appendChild(document.createTextNode(event.dataTransfer.getData('text/plain')))"
+/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/008.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/008.xhtml
new file mode 100644
index 00000000000..6abfe2c318c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/008.xhtml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from password input to block element</title>
+<style type="text/css">
+div[ondragenter]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>You should not be able to drag and drop selection from password field to the blue box.</p>
+<p><input type="password" value="FAIL"/></p>
+<div
+ ondragenter="event.preventDefault()"
+ ondragover="return false"
+ ondrop="document.querySelector('div').appendChild(document.createTextNode(event.dataTransfer.getData('text/plain')))"
+/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/009.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/009.xhtml
new file mode 100644
index 00000000000..07509f6bcf6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/009.xhtml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from readonly text input to block element</title>
+<style type="text/css">
+div[ondragenter]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected text to the blue box. Copy of selection should end up in the blue box once you drop it there.</p>
+<p><input readonly="readonly" value="Drag me"/></p>
+<div
+ ondragenter="event.preventDefault()"
+ ondragover="return false"
+ ondrop="document.querySelector('div').appendChild(document.createTextNode(event.dataTransfer.getData('text/plain')))"
+/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/010.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/010.xhtml
new file mode 100644
index 00000000000..d26770ee647
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/010.xhtml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from texarea to block element</title>
+<style type="text/css">
+div[ondragenter]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+textarea
+ {height:1.5em;
+ width:7em;}
+</style>
+</head>
+<body onload="var t = document.querySelector('textarea');t.select();t.setSelectionRange(0,7)">
+<p>Drag selected text to the blue box. Copy of selection should end up in the blue box once you drop it there.</p>
+<p><textarea>Drag me</textarea></p>
+<div
+ ondragenter="event.preventDefault()"
+ ondragover="return false"
+ ondrop="document.querySelector('div').appendChild(document.createTextNode(event.dataTransfer.getData('text/plain')))"
+/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/011.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/011.xhtml
new file mode 100644
index 00000000000..1ea8cd592f8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/011.xhtml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from text input to textarea</title>
+<style type="text/css">
+textarea
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;}
+</style>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected text to the textarea. Selected text should be moved to the textarea once you drop it there.</p>
+<p><input value="Drag me"/></p>
+<p><textarea placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/012.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/012.xhtml
new file mode 100644
index 00000000000..8013e28c391
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/012.xhtml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from search input to textarea</title>
+<style type="text/css">
+textarea
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;}
+</style>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected text to the textarea. Selected text should be moved to the textarea once you drop it there.</p>
+<p><input type="search" value="Selection"/></p>
+<p><textarea placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/013.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/013.xhtml
new file mode 100644
index 00000000000..0f1defc8962
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/013.xhtml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from tel input to textarea</title>
+<style type="text/css">
+textarea
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;}
+</style>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected number to the textarea. Selected text should be moved to the textarea once you drop it there.</p>
+<p><input type="tel" value="123456789"/></p>
+<p><textarea placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/014.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/014.xhtml
new file mode 100644
index 00000000000..6ed64a608f1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/014.xhtml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from url input to textarea</title>
+<style type="text/css">
+textarea
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;}
+</style>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected url to the textarea. Selected text should be moved to the textarea once you drop it there.</p>
+<p><input type="url" value="http://opera.com"/></p>
+<p><textarea placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/015.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/015.xhtml
new file mode 100644
index 00000000000..ecd3f88702b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/015.xhtml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from email input to textarea</title>
+<style type="text/css">
+textarea
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;}
+</style>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected email to the textarea. Selected text should be moved to the textarea once you drop it there.</p>
+<p><input type="email" value="mail@example.org"/></p>
+<p><textarea placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/016.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/016.xhtml
new file mode 100644
index 00000000000..64784d71f15
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/016.xhtml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from number input to textarea</title>
+<style type="text/css">
+textarea
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;}
+</style>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected number to the textarea. Copy of selection should end up in the textarea once you drop it there.</p>
+<p><input type="number" value="123456789"/></p>
+<p><textarea placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/017.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/017.xhtml
new file mode 100644
index 00000000000..b8b64d1c5b5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/017.xhtml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from short text input to textarea</title>
+<style type="text/css">
+textarea
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;}
+</style>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected date to the textarea. Selected text should be moved to the textarea once you drop it there.</p>
+<p><input size="5" value="Drag me"/></p>
+<p><textarea placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/018.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/018.xhtml
new file mode 100644
index 00000000000..338bdd73ac9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/018.xhtml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from password input to textarea</title>
+<style type="text/css">
+textarea
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;}
+</style>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>You should not be able to drag and drop selection from password field to the textarea.</p>
+<p><input type="password" value="FAIL"/></p>
+<p><textarea placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/019.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/019.xhtml
new file mode 100644
index 00000000000..d8f7d304dd2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/019.xhtml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from readonly input to textarea</title>
+<style type="text/css">
+textarea
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;}
+</style>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected text to the textarea. Selected text should be moved to the textarea once you drop it there.</p>
+<p><input readonly="readonly" value="Drag me"/></p>
+<p><textarea placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/020.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/020.xhtml
new file mode 100644
index 00000000000..f6b860140dd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/020.xhtml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop between textareas</title>
+<style type="text/css">
+p:last-child > textarea
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;}
+p:first-child + p > textarea
+ {height:1.5em;
+ width:7em;}
+</style>
+</head>
+<body onload="var t = document.querySelector('textarea');t.select();t.setSelectionRange(0,7)">
+<p>Drag selected text to the textarea. Selected text should be moved to the textarea once you drop it there.</p>
+<p><textarea>Drag me</textarea></p>
+<p><textarea placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/021.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/021.xhtml
new file mode 100644
index 00000000000..4526c1aaaa4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/021.xhtml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from text input to contenteditable element</title>
+<style type="text/css">
+div[contenteditable]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected text to the blue box. Selected text should be moved to the blue box once you drop it there.</p>
+<p><input value="Drag me"/></p>
+<div contenteditable="true"/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/022.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/022.xhtml
new file mode 100644
index 00000000000..e69d2419a4c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/022.xhtml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from search input to contenteditable element</title>
+<style type="text/css">
+div[contenteditable]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected text to the blue box. Selected text should be moved to the blue box once you drop it there.</p>
+<p><input type="search" value="Selection"/></p>
+<div contenteditable="true"/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/023.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/023.xhtml
new file mode 100644
index 00000000000..0d1183d8c95
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/023.xhtml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from tel input to contenteditable element</title>
+<style type="text/css">
+div[contenteditable]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected number to the blue box. Selected text should be moved to the blue box once you drop it there.</p>
+<p><input type="tel" value="123456789"/></p>
+<div contenteditable="true"/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/024.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/024.xhtml
new file mode 100644
index 00000000000..dc275e36645
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/024.xhtml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from url input to contenteditable element</title>
+<style type="text/css">
+div[contenteditable]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected url to the blue box. Selected text should be moved to the blue box once you drop it there.</p>
+<p><input type="url" value="http://example.org"/></p>
+<div contenteditable="true"/>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/025.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/025.xhtml
new file mode 100644
index 00000000000..25f123b147a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/025.xhtml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from email input to contenteditable element</title>
+<style type="text/css">
+div[contenteditable]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected email to the blue box. Selected text should be moved to the blue box once you drop it there.</p>
+<p><input type="email" value="mail@example.org"/></p>
+<div contenteditable="true"/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/026.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/026.xhtml
new file mode 100644
index 00000000000..a4ee2a18fe0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/026.xhtml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from number input to contenteditable element</title>
+<style type="text/css">
+div[contenteditable]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected number to the blue box. Copy of selection should end up in the blue box once you drop it there.</p>
+<p><input type="number" value="123456789"/></p>
+<div contenteditable="true"/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/027.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/027.xhtml
new file mode 100644
index 00000000000..593f62dc088
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/027.xhtml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from short input to contenteditable element</title>
+<style type="text/css">
+div[contenteditable]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected date to the blue box. Selected text should be moved to the blue box once you drop it there.</p>
+<p><input size="5" value="Drag me"/></p>
+<div contenteditable="true"/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/028.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/028.xhtml
new file mode 100644
index 00000000000..6444e3c9205
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/028.xhtml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from password input to contenteditable element</title>
+<style type="text/css">
+div[contenteditable]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>You should not be able to drag and drop selection from password field to the blue box.</p>
+<p><input type="password" value="FAIL"/></p>
+<div contenteditable="true"/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/029.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/029.xhtml
new file mode 100644
index 00000000000..3ffecf0ec23
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/029.xhtml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from readonly input to contenteditable element</title>
+<style type="text/css">
+div[contenteditable]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected text to the blue box. Selected text should be moved to the blue box once you drop it there.</p>
+<p><input readonly="readonly" value="Drag me"/></p>
+<div contenteditable="true"/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/030.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/030.xhtml
new file mode 100644
index 00000000000..25536ec273b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/030.xhtml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from textarea to contenteditable element</title>
+<style type="text/css">
+div[contenteditable]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+textarea
+ {height:1.5em;
+ width:7em;}
+</style>
+</head>
+<body onload="var t = document.querySelector('textarea');t.select();t.setSelectionRange(0,7)">
+<p>Drag selected text to the blue box. Selected text should be moved to the blue box once you drop it there.</p>
+<p><textarea>Drag me</textarea></p>
+<div contenteditable="true"/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/031.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/031.xhtml
new file mode 100644
index 00000000000..ecdd466f723
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/031.xhtml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Dragging two lines of text selection from textarea to block element</title>
+<style type="text/css">
+div[ondragenter]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+textarea
+ {width:300px;
+ height:100px;}
+</style>
+</head>
+<body onload="var t = document.querySelector('textarea');t.select();t.setSelectionRange(25,56)">
+<p>
+<textarea>
+Here is textarea
+with selection that
+spans two lines.
+Drag selected text to the blue box.
+Selected text should be moved to the blue box once you drop it there.
+</textarea>
+</p>
+<div
+ ondragenter="event.preventDefault()"
+ ondragover="return false"
+ ondrop="document.querySelector('div').appendChild(document.createTextNode(event.dataTransfer.getData('text/plain')))"
+/>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/032.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/032.xhtml
new file mode 100644
index 00000000000..59070062e10
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/032.xhtml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Dragging multiline text selection from textarea to block element</title>
+<style type="text/css">
+div[ondragenter]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+textarea
+ {width:300px;
+ height:100px;}
+</style>
+</head>
+<body onload="var t = document.querySelector('textarea');t.select();t.setSelectionRange(24,58)">
+<p>
+<textarea>
+Here is textarea with selection
+that spans
+three lines. Drag selected text to the blue box.
+Copy of selection should end up in the blue box once you drop it there.
+</textarea>
+</p>
+<div
+ ondragenter="event.preventDefault()"
+ ondragover="return false"
+ ondrop="document.querySelector('div').appendChild(document.createTextNode(event.dataTransfer.getData('text/plain')))"
+/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/033.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/033.xhtml
new file mode 100644
index 00000000000..edd53277661
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/033.xhtml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Dragging two lines of text selection between textareas</title>
+<style type="text/css">
+textarea
+ {width:300px;
+ height:100px;}
+</style>
+</head>
+<body onload="var t = document.querySelector('textarea');t.select();t.setSelectionRange(25,56)">
+<p>
+<textarea>
+Here is textarea
+with selection that
+spans two lines.
+Drag selected text to the textarea below.
+Selected text should be moved to second textarea once you drop it there.
+</textarea>
+</p>
+<p><textarea placeholder="Drop selection here"/></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/034.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/034.xhtml
new file mode 100644
index 00000000000..4643156feab
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/034.xhtml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Dragging multiline text selection between textareas</title>
+<style type="text/css">
+textarea
+ {width:300px;
+ height:100px;}
+</style>
+</head>
+<body onload="var t = document.querySelector('textarea');t.select();t.setSelectionRange(24,58)">
+<p>
+<textarea>
+Here is textarea with selection
+that spans
+three lines. Drag selected text to the textarea below.
+Selected text should be moved to second textarea once you drop it there.
+</textarea>
+</p>
+<p><textarea placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/035.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/035.xhtml
new file mode 100644
index 00000000000..1bc133431ef
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/035.xhtml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Dragging two lines of text selection from textarea to contenteditable element</title>
+<style type="text/css">
+div[contenteditable]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+textarea
+ {width:300px;
+ height:100px;}
+</style>
+</head>
+<body onload="var t = document.querySelector('textarea');t.select();t.setSelectionRange(25,56)">
+<p>
+<textarea>
+Here is textarea
+with selection that
+spans two lines.
+Drag selected text to the blue box.
+Selected text should be moved to the blue box once you drop it there.
+</textarea>
+</p>
+<div contenteditable="true"/>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/036.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/036.xhtml
new file mode 100644
index 00000000000..e819719840b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/036.xhtml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Dragging multiline text selection from textarea to contenteditable element</title>
+<style type="text/css">
+div[contenteditable]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+textarea
+ {width:300px;
+ height:100px;}
+</style>
+</head>
+<body onload="var t = document.querySelector('textarea');t.select();t.setSelectionRange(24,58)">
+<p>
+<textarea>
+Here is textarea with selection
+that spans
+three lines. Drag selected text to the blue box.
+Selected text should be moved to the blue box once you drop it there.
+</textarea>
+</p>
+<div contenteditable="true"/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/037.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/037.xhtml
new file mode 100644
index 00000000000..fc06f3a069b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/037.xhtml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Cross frame selection drag and drop from text input to block element</title>
+</head>
+<frameset rows="50%, 50%">
+<frame src="helper-drag-me-input.xhtml"/>
+<frame src="helper-drop-here-blue-box.xhtml"/>
+</frameset>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/038.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/038.xhtml
new file mode 100644
index 00000000000..5843f5830c1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/038.xhtml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Cross frame selection drag and drop from textarea input to block element</title>
+</head>
+<frameset rows="50%, 50%">
+<frame src="helper-drag-me-textarea-to-other-blue-box.xhtml"/>
+<frame src="helper-drop-here-blue-box.xhtml"/>
+</frameset>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/039.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/039.xhtml
new file mode 100644
index 00000000000..f5f823b9563
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/039.xhtml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Cross frame selection drag and drop from text input to textarea</title>
+</head>
+<frameset rows="50%, 50%">
+<frame src="helper-drag-me-input-to-other-textarea.xhtml"/>
+<frame src="helper-drop-here-textarea.xhtml"/>
+</frameset>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/040.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/040.xhtml
new file mode 100644
index 00000000000..91605aff794
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/040.xhtml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Cross frame selection drag and drop between textareas</title>
+</head>
+<frameset rows="50%, 50%">
+<frame src="helper-drag-me-textarea-to-other-textarea.xhtml"/>
+<frame src="helper-drop-here-textarea.xhtml"/>
+</frameset>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/041.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/041.xhtml
new file mode 100644
index 00000000000..73a88347222
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/041.xhtml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Cross frame selection drag and drop from text input to contenteditable element</title>
+</head>
+<frameset rows="50%, 50%">
+<frame src="helper-drag-me-input.xhtml"/>
+<frame src="helper-drop-here-blue-box-contenteditable.xhtml"/>
+</frameset>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/042.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/042.xhtml
new file mode 100644
index 00000000000..686accb246e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/042.xhtml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Cross frame selection drag and drop from textarea to contenteditable element</title>
+</head>
+<frameset rows="50%, 50%">
+<frame src="helper-drag-me-textarea-to-other-blue-box.xhtml"/>
+<frame src="helper-drop-here-blue-box-contenteditable.xhtml"/>
+</frameset>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/043.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/043.xhtml
new file mode 100644
index 00000000000..bc296d5bc52
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/043.xhtml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Cross frame selection drag and drop between text inputs</title>
+</head>
+<frameset rows="50%, 50%">
+<frame src="helper-drag-me-input-to-other-input.xhtml"/>
+<frame src="helper-drop-here-input.xhtml"/>
+</frameset>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/044.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/044.xhtml
new file mode 100644
index 00000000000..0dd958edc8a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/044.xhtml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Cross frame selection drag and drop from textarea to text input</title>
+</head>
+<frameset rows="50%, 50%">
+<frame src="helper-drag-me-textarea-to-other-input.xhtml"/>
+<frame src="helper-drop-here-input.xhtml"/>
+</frameset>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/045.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/045.xhtml
new file mode 100644
index 00000000000..1b44ad3e307
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/045.xhtml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from text input to iframe</title>
+<style type="text/css">
+iframe
+ {width:350px;
+ height:150px;
+ border-style:none;}
+</style>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected text to the blue box. Copy of selection should end up in the blue box once you drop it there.</p>
+<p><input value="Drag me"/></p>
+<p><iframe src="helper-drop-here-blue-box.xhtml">XHTML document</iframe></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/046.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/046.xhtml
new file mode 100644
index 00000000000..b5a8f9510d9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/046.xhtml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from textarea to iframe</title>
+<style type="text/css">
+iframe
+ {width:350px;
+ height:150px;
+ border-style:none;}
+</style>
+</head>
+<body onload="var t = document.querySelector('textarea');t.select();t.setSelectionRange(0,7)">
+<p>Drag selected text to the blue box. Copy of selection should end up in the blue box once you drop it there.</p>
+<p><textarea>Drag me</textarea></p>
+<p><iframe src="helper-drop-here-blue-box.xhtml">XHTML document</iframe></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/047.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/047.xhtml
new file mode 100644
index 00000000000..61d4afca418
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/047.xhtml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from text input to textarea in iframe</title>
+<style type="text/css">
+iframe
+ {width:500px;
+ height:400px;
+ border-style:none;}
+</style>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected text to the textarea. Copy of selection should end up in the textarea once you drop it there.</p>
+<p><input value="Drag me"/></p>
+<p><iframe src="helper-drop-here-textarea.xhtml">XHTML document</iframe></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/048.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/048.xhtml
new file mode 100644
index 00000000000..73483036c80
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/048.xhtml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from textarea to another textarea in iframe</title>
+<style type="text/css">
+iframe
+ {width:500px;
+ height:400px;
+ border-style:none;}
+</style>
+</head>
+<body onload="var t = document.querySelector('textarea');t.select();t.setSelectionRange(0,7)">
+<p>Drag selected text to the textarea. Copy of selection should end up in the textarea once you drop it there.</p>
+<p><textarea>Drag me</textarea></p>
+<p><iframe src="helper-drop-here-textarea.xhtml">XHTML document</iframe></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/049.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/049.xhtml
new file mode 100644
index 00000000000..5bed43563bd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/049.xhtml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from text input to contenteditable element in iframe</title>
+<style type="text/css">
+iframe
+ {width:350px;
+ height:150px;
+ border-style:none;}
+</style>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected text to the blue box. Copy of selection should end up in the blue box once you drop it there.</p>
+<p><input value="Drag me"/></p>
+<p><iframe src="helper-drop-here-blue-box-contenteditable.xhtml">XHTML document</iframe></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/050.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/050.xhtml
new file mode 100644
index 00000000000..7a1545ec5bf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/050.xhtml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from textarea to contenteditable element in iframe</title>
+<style type="text/css">
+iframe
+ {width:350px;
+ height:150px;
+ border-style:none;}
+</style>
+</head>
+<body onload="var t = document.querySelector('textarea');t.select();t.setSelectionRange(0,7)">
+<p>Drag selected text to the blue box. Copy of selection should end up in the blue box once you drop it there.</p>
+<p><textarea>Drag me</textarea></p>
+<p><iframe src="helper-drop-here-blue-box-contenteditable.xhtml">XHTML document</iframe></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/051.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/051.xhtml
new file mode 100644
index 00000000000..41a94dd8c41
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/051.xhtml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from text input in iframe to block element</title>
+<style type="text/css">
+iframe
+ {width:500px;
+ height:200px;
+ border-style:none;}
+div[ondragenter]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body>
+<p><iframe src="helper-drag-me-input.xhtml">XHTML document</iframe></p>
+<div
+ ondragenter="event.preventDefault()"
+ ondragover="return false"
+ ondrop="document.querySelector('div').appendChild(document.createTextNode(event.dataTransfer.getData('text/plain')))"
+/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/052.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/052.xhtml
new file mode 100644
index 00000000000..32d713ff5a4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/052.xhtml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from textarea in iframe to block element</title>
+<style type="text/css">
+iframe
+ {width:500px;
+ height:200px;
+ border-style:none;}
+div[ondragenter]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body>
+<p><iframe src="helper-drag-me-textarea-to-other-blue-box.xhtml">XHTML document</iframe></p>
+<div
+ ondragenter="event.preventDefault()"
+ ondragover="return false"
+ ondrop="document.querySelector('div').appendChild(document.createTextNode(event.dataTransfer.getData('text/plain')))"
+/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/053.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/053.xhtml
new file mode 100644
index 00000000000..52a3c148bab
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/053.xhtml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from text input in iframe to textarea</title>
+<style type="text/css">
+iframe
+ {width:500px;
+ height:200px;
+ border-style:none;}
+textarea
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;}
+</style>
+</head>
+<body>
+<p><iframe src="helper-drag-me-input-to-other-textarea.xhtml">XHTML document</iframe></p>
+<p><textarea placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/054.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/054.xhtml
new file mode 100644
index 00000000000..22be4107158
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/054.xhtml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from textarea in iframe to another textarea</title>
+<style type="text/css">
+iframe
+ {width:500px;
+ height:200px;
+ border-style:none;}
+textarea
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;}
+</style>
+</head>
+<body>
+<p><iframe src="helper-drag-me-textarea-to-other-textarea.xhtml">XHTML document</iframe></p>
+<p><textarea placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/055.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/055.xhtml
new file mode 100644
index 00000000000..9465b1beb80
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/055.xhtml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from text input in iframe to contenteditable element</title>
+<style type="text/css">
+iframe
+ {width:500px;
+ height:200px;
+ border-style:none;}
+div[contenteditable]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body>
+<p><iframe src="helper-drag-me-input.xhtml">XHTML document</iframe></p>
+<div contenteditable="true"/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/056.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/056.xhtml
new file mode 100644
index 00000000000..94a99a7917f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/056.xhtml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from textarea in iframe to contenteditable element</title>
+<style type="text/css">
+iframe
+ {width:500px;
+ height:200px;
+ border-style:none;}
+div[contenteditable]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body>
+<p><iframe src="helper-drag-me-textarea-to-other-blue-box.xhtml">XHTML document</iframe></p>
+<div contenteditable="true"/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/057.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/057.xhtml
new file mode 100644
index 00000000000..4fca493a7c0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/057.xhtml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from text input in iframe to another input element</title>
+<style type="text/css">
+iframe
+ {width:500px;
+ height:200px;
+ border-style:none;}
+textarea
+ {width:300px;
+ height:100px;
+ margin-top:20px;}
+</style>
+</head>
+<body>
+<p><iframe src="helper-drag-me-input-to-other-input.xhtml">XHTML document</iframe></p>
+<p><input placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/058.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/058.xhtml
new file mode 100644
index 00000000000..7f3c51a9705
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/058.xhtml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from textarea in iframe to input element</title>
+<style type="text/css">
+iframe
+ {width:500px;
+ height:200px;
+ border-style:none;}
+textarea
+ {width:300px;
+ height:100px;
+ margin-top:20px;}
+</style>
+</head>
+<body>
+<p><iframe src="helper-drag-me-textarea-to-other-input.xhtml">XHTML document</iframe></p>
+<p><input placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/059.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/059.xhtml
new file mode 100644
index 00000000000..89a778b3ef4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/059.xhtml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Cross iframe selection drag and drop from text input to block element</title>
+<style type="text/css">
+iframe
+ {width:100%;
+ height:200px;
+ border-style:none;}
+</style>
+</head>
+<body>
+<p><iframe src="helper-drag-me-input.xhtml">XHTML document</iframe></p>
+<p><iframe src="helper-drop-here-blue-box.xhtml">XHTML document</iframe></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/060.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/060.xhtml
new file mode 100644
index 00000000000..73d49810aef
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/060.xhtml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Cross iframe selection drag and drop from textarea to block element</title>
+<style type="text/css">
+iframe
+ {width:100%;
+ height:200px;
+ border-style:none;}
+</style>
+</head>
+<body>
+<p><iframe src="helper-drag-me-textarea-to-other-blue-box.xhtml">XHTML document</iframe></p>
+<p><iframe src="helper-drop-here-blue-box.xhtml">XHTML document</iframe></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/061.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/061.xhtml
new file mode 100644
index 00000000000..c30c031e22d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/061.xhtml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Cross iframe selection drag and drop from text input to textarea</title>
+<style type="text/css">
+iframe
+ {width:100%;
+ height:200px;
+ border-style:none;}
+</style>
+</head>
+<body>
+<p><iframe src="helper-drag-me-input-to-other-textarea.xhtml">XHTML document</iframe></p>
+<p><iframe src="helper-drop-here-textarea.xhtml">XHTML document</iframe></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/062.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/062.xhtml
new file mode 100644
index 00000000000..df64cfd8e64
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/062.xhtml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Cross iframe selection drag and drop between textareas</title>
+<style type="text/css">
+iframe
+ {width:100%;
+ height:200px;
+ border-style:none;}
+</style>
+</head>
+<body>
+<p><iframe src="helper-drag-me-textarea-to-other-textarea.xhtml">XHTML document</iframe></p>
+<p><iframe src="helper-drop-here-textarea.xhtml">XHTML document</iframe></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/063.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/063.xhtml
new file mode 100644
index 00000000000..c07ab932a68
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/063.xhtml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Cross iframe selection drag and drop from text input to contenteditable element</title>
+<style type="text/css">
+iframe
+ {width:100%;
+ height:200px;
+ border-style:none;}
+</style>
+</head>
+<body>
+<p><iframe src="helper-drag-me-input.xhtml">XHTML document</iframe></p>
+<p><iframe src="helper-drop-here-blue-box-contenteditable.xhtml">XHTML document</iframe></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/064-1.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/064-1.xhtml
new file mode 100644
index 00000000000..8f164a60121
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/064-1.xhtml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop: helper file</title>
+<style type="text/css">
+textarea
+ {height:1.5em;
+ width:7em;}
+</style>
+</head>
+<body onload="var t = document.querySelector('textarea');t.select();t.setSelectionRange(0,7)">
+<p>Drag selected text to the blue box. Selection should be moved to the blue box once you drop it there.</p>
+<p><textarea>Drag me</textarea></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/064.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/064.xhtml
new file mode 100644
index 00000000000..cf585c6d53d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/064.xhtml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Cross iframe selection drag and drop from textarea to contenteditable element</title>
+<style type="text/css">
+iframe
+ {width:100%;
+ height:200px;
+ border-style:none;}
+</style>
+</head>
+<body>
+<p><iframe src="064-1.xhtml">XHTML document</iframe></p>
+<p><iframe src="helper-drop-here-blue-box-contenteditable.xhtml">XHTML document</iframe></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/065.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/065.xhtml
new file mode 100644
index 00000000000..d4bd8f3251b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/065.xhtml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Cross iframe selection drag and drop between text inputs</title>
+<style type="text/css">
+iframe
+ {width:100%;
+ height:200px;
+ border-style:none;}
+</style>
+</head>
+<body>
+<p><iframe src="helper-drag-me-input-to-other-input.xhtml">XHTML document</iframe></p>
+<p><iframe src="helper-drop-here-input.xhtml">XHTML document</iframe></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/066.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/066.xhtml
new file mode 100644
index 00000000000..8f65061a16e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/066.xhtml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Cross iframe selection drag and drop from textarea to text input</title>
+<style type="text/css">
+iframe
+ {width:100%;
+ height:200px;
+ border-style:none;}
+</style>
+</head>
+<body>
+<p><iframe src="helper-drag-me-textarea-to-other-input.xhtml">XHTML document</iframe></p>
+<p><iframe src="helper-drop-here-input.xhtml">XHTML document</iframe></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/067-1.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/067-1.xhtml
new file mode 100644
index 00000000000..206c5967562
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/067-1.xhtml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop: helper file</title>
+<style type="text/css">
+iframe
+ {width:100%;
+ height:200px;
+ border-style:none;}
+</style>
+</head>
+<body>
+<p><iframe src="helper-drag-me-input.xhtml">XHTML document</iframe></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/067-2.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/067-2.xhtml
new file mode 100644
index 00000000000..3362fba6c45
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/067-2.xhtml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop: helper file</title>
+<style type="text/css">
+iframe
+ {width:100%;
+ height:200px;
+ border-style:none;}
+</style>
+</head>
+<body>
+<p><iframe src="helper-drop-here-blue-box.xhtml">XHTML document</iframe></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/067.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/067.xhtml
new file mode 100644
index 00000000000..2d33465fd4b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/067.xhtml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Nested cross frame selection drag and drop from text input to block element</title>
+</head>
+<frameset rows="50%, 50%">
+<frame src="067-1.xhtml"/>
+<frame src="067-2.xhtml"/>
+</frameset>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/068-1.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/068-1.xhtml
new file mode 100644
index 00000000000..c9fc41b478f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/068-1.xhtml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop: helper file</title>
+</head>
+<frameset rows="100%, 0%">
+<frame src="helper-drag-me-textarea-to-other-textarea.xhtml"/>
+<frame src="data:text/plain,1"/>
+</frameset>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/068-2.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/068-2.xhtml
new file mode 100644
index 00000000000..b639b16fc1c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/068-2.xhtml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop: helper file</title>
+</head>
+<frameset rows="100%, 0%">
+<frame src="helper-drop-here-textarea.xhtml"/>
+<frame src="data:text/plain,2"/>
+</frameset>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/068.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/068.xhtml
new file mode 100644
index 00000000000..5f051697cd5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/068.xhtml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Nested cross frame selection drag and drop between textareas</title>
+</head>
+<frameset rows="50%, 50%">
+<frame src="068-1.xhtml"/>
+<frame src="068-2.xhtml"/>
+</frameset>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/069.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/069.xhtml
new file mode 100644
index 00000000000..02c12bd72e7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/069.xhtml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop to textarea in iframe</title>
+<style type="text/css">
+iframe
+ {width:500px;
+ height:400px;
+ border-style:none;}
+</style>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('p'))">
+<p>Drag me</p>
+<p>Drag selected text to the textarea. Copy of selection should end up in the textarea once you drop it there.</p>
+<p><iframe src="helper-drop-here-textarea.xhtml">XHTML document</iframe></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/070.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/070.xhtml
new file mode 100644
index 00000000000..73511debdf3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/070.xhtml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop to contenteditable element in iframe</title>
+<style type="text/css">
+iframe
+ {width:500px;
+ height:400px;
+ border-style:none;}
+</style>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('p'))">
+<p>Drag me</p>
+<p>Drag selected text to the blue box. Copy of selection should end up in the blue box once you drop it there.</p>
+<p><iframe src="helper-drop-here-blue-box-contenteditable.xhtml">XHTML document</iframe></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/071.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/071.xhtml
new file mode 100644
index 00000000000..e3dcd57defb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/071.xhtml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop between text inputs of different size</title>
+<style type="text/css">
+input[placeholder]
+ {width:300px;
+ height:100px;
+ margin-top:20px;}
+</style>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected text to the input below. Selected text should be moved to the input once you drop it there.</p>
+<p><input value="Drag me"/></p>
+<p><input placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/072.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/072.xhtml
new file mode 100644
index 00000000000..c44e2bd8db5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/072.xhtml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from search to text input</title>
+<style type="text/css">
+input[placeholder]
+ {width:300px;
+ height:100px;
+ margin-top:20px;}
+</style>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected text to the input below. Selected text should be moved to the input once you drop it there.</p>
+<p><input type="search" value="Selection"/></p>
+<p><input placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/073.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/073.xhtml
new file mode 100644
index 00000000000..ade164797b9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/073.xhtml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from tel to text input</title>
+<style type="text/css">
+input[placeholder]
+ {width:300px;
+ height:100px;
+ margin-top:20px;}
+</style>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected number to the input below. Selected text should be moved to the input once you drop it there.</p>
+<p><input type="tel" value="123456789"/></p>
+<p><input placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/074.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/074.xhtml
new file mode 100644
index 00000000000..f441ad101ac
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/074.xhtml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from url to text input</title>
+<style type="text/css">
+input[placeholder]
+ {width:300px;
+ height:100px;
+ margin-top:20px;}
+</style>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected url to the input below. Selected text should be moved to the input once you drop it there.</p>
+<p><input type="url" value="http://example.org"/></p>
+<p><input placeholder="Drop selection here"/></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/075.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/075.xhtml
new file mode 100644
index 00000000000..8b5304f0e69
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/075.xhtml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from email to text input</title>
+<style type="text/css">
+input[placeholder]
+ {width:300px;
+ height:100px;
+ margin-top:20px;}
+</style>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected email to the input below. Selected text should be moved to the input once you drop it there.</p>
+<p><input type="email" value="mail@example.org"/></p>
+<p><input placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/076.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/076.xhtml
new file mode 100644
index 00000000000..bb5db839a41
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/076.xhtml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from number to text input</title>
+<style type="text/css">
+input[placeholder]
+ {width:300px;
+ height:100px;
+ margin-top:20px;}
+</style>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected number to the input below. Copy of selection should end up in the input once you drop it there.</p>
+<p><input type="number" value="123456789"/></p>
+<p><input placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/077.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/077.xhtml
new file mode 100644
index 00000000000..42cee3e22d8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/077.xhtml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from short text input to another text input</title>
+<style type="text/css">
+input[placeholder]
+ {width:300px;
+ height:100px;
+ margin-top:20px;}
+</style>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected date to the input below. Selected text should be moved to the input once you drop it there.</p>
+<p><input size="5" value="Drag me"/></p>
+<p><input placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/078.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/078.xhtml
new file mode 100644
index 00000000000..1261a6a1350
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/078.xhtml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from password to text input</title>
+<style type="text/css">
+input[placeholder]
+ {width:300px;
+ height:100px;
+ margin-top:20px;}
+</style>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>You should not be able to drag and drop selection from password field to the input below.</p>
+<p><input type="password" value="FAIL"/></p>
+<p><input placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/079.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/079.xhtml
new file mode 100644
index 00000000000..d114cc68d45
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/079.xhtml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from readonly text input to another text input</title>
+<style type="text/css">
+input[placeholder]
+ {width:300px;
+ height:100px;
+ margin-top:20px;}
+</style>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected text to the input below. Selected text should be moved to the input once you drop it there.</p>
+<p><input readonly="readonly" value="Drag me"/></p>
+<p><input placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/080.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/080.xhtml
new file mode 100644
index 00000000000..35fac3928a1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/080.xhtml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from textarea to text input</title>
+<style type="text/css">
+input
+ {width:300px;
+ height:100px;
+ margin-top:20px;}
+textarea
+ {height:1.5em;
+ width:7em;}
+</style>
+</head>
+<body onload="var t = document.querySelector('textarea');t.select();t.setSelectionRange(0,7)">
+<p>Drag selected text to the input below. Selected text should be moved to the input once you drop it there.</p>
+<p><textarea>Drag me</textarea></p>
+<p><input placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/081.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/081.xhtml
new file mode 100644
index 00000000000..eb8c4124fb4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/081.xhtml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Events during selection drag and drop to text input</title>
+<style type="text/css">
+input[placeholder]
+ {width:300px;
+ height:50px;
+ margin-top:20px;}
+.hidden
+ {visibility:hidden;}
+</style>
+<script type="application/ecmascript">
+function evtChange()
+ {document.querySelectorAll('tt')[0].firstChild.nodeValue = 'PASS'}
+function evtInput()
+ {document.querySelectorAll('tt')[1].firstChild.nodeValue = 'PASS'}
+function evtDrop()
+ {document.querySelectorAll('tt')[2].firstChild.nodeValue = (event.dataTransfer.getData('text/plain') == 'Drag me')?'PASS':'FAIL (selection is not properly added to data store)'}
+function evtKeypress()
+ {document.querySelectorAll('tt')[3].firstChild.nodeValue = 'FAIL (even is not supposed to fire)'}
+</script>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('p'))">
+<p>Drag me</p>
+<p>Drag selected text to the input below. Follow check results link once you drop selection in the input.</p>
+<p><input placeholder="Drop selection here" onchange="evtChange()" oninput="evtInput()" onkeypress="evtKeypress()" ondrop="evtDrop()"/></p>
+<p><a href="javascript:document.querySelector('ul').removeAttribute('class')">Check results</a></p>
+<ul class="hidden">
+<li>Change event: <tt>FAIL (even did not fire)</tt></li>
+<li>Input event: <tt>FAIL (even did not fire)</tt></li>
+<li>Drop event: <tt>FAIL (even did not fire)</tt></li>
+<li>Keypress event: <tt>PASS</tt></li>
+</ul>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/082.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/082.xhtml
new file mode 100644
index 00000000000..449ce932a46
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/082.xhtml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Events during selection drag and drop to search input</title>
+<style type="text/css">
+input[placeholder]
+ {width:300px;
+ height:50px;
+ margin-top:20px;}
+.hidden
+ {visibility:hidden;}
+</style>
+<script type="application/ecmascript">
+function evtChange()
+ {document.querySelectorAll('tt')[0].firstChild.nodeValue = 'PASS'}
+function evtInput()
+ {document.querySelectorAll('tt')[1].firstChild.nodeValue = 'PASS'}
+function evtDrop()
+ {document.querySelectorAll('tt')[2].firstChild.nodeValue = (event.dataTransfer.getData('text/plain') == 'Drag me')?'PASS':'FAIL (selection is not properly added to data store)'}
+function evtKeypress()
+ {document.querySelectorAll('tt')[3].firstChild.nodeValue = 'FAIL (even is not supposed to fire)'}
+</script>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('p'))">
+<p>Drag me</p>
+<p>Drag selected text to the input below. Follow check results link once you drop selection in the input.</p>
+<p><input type="search" placeholder="Drop selection here" onchange="evtChange()" oninput="evtInput()" onkeypress="evtKeypress()" ondrop="evtDrop()"/></p>
+<p><a href="javascript:document.querySelector('ul').removeAttribute('class')">Check results</a></p>
+<ul class="hidden">
+<li>Change event: <tt>FAIL (even did not fire)</tt></li>
+<li>Input event: <tt>FAIL (even did not fire)</tt></li>
+<li>Drop event: <tt>FAIL (even did not fire)</tt></li>
+<li>Keypress event: <tt>PASS</tt></li>
+</ul>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/083.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/083.xhtml
new file mode 100644
index 00000000000..9ca21e9e35a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/083.xhtml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Events during selection drag and drop to tel input</title>
+<style type="text/css">
+input[placeholder]
+ {width:300px;
+ height:50px;
+ margin-top:20px;}
+.hidden
+ {visibility:hidden;}
+</style>
+<script type="application/ecmascript">
+function evtChange()
+ {document.querySelectorAll('tt')[0].firstChild.nodeValue = 'PASS'}
+function evtInput()
+ {document.querySelectorAll('tt')[1].firstChild.nodeValue = 'PASS'}
+function evtDrop()
+ {document.querySelectorAll('tt')[2].firstChild.nodeValue = (event.dataTransfer.getData('text/plain') == '123456789')?'PASS':'FAIL (selection is not properly added to data store)'}
+function evtKeypress()
+ {document.querySelectorAll('tt')[3].firstChild.nodeValue = 'FAIL (even is not supposed to fire)'}
+</script>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('p'))">
+<p>123456789</p>
+<p>Drag selected number to the input below. Follow check results link once you drop selection in the input.</p>
+<p><input type="tel" placeholder="Drop selection here" onchange="evtChange()" oninput="evtInput()" onkeypress="evtKeypress()" ondrop="evtDrop()"/></p>
+<p><a href="javascript:document.querySelector('ul').removeAttribute('class')">Check results</a></p>
+<ul class="hidden">
+<li>Change event: <tt>FAIL (even did not fire)</tt></li>
+<li>Input event: <tt>FAIL (even did not fire)</tt></li>
+<li>Drop event: <tt>FAIL (even did not fire)</tt></li>
+<li>Keypress event: <tt>PASS</tt></li>
+</ul>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/084.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/084.xhtml
new file mode 100644
index 00000000000..baaae70d29c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/084.xhtml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Events during selection drag and drop to url input</title>
+<style type="text/css">
+input[placeholder]
+ {width:300px;
+ height:50px;
+ margin-top:20px;}
+.hidden
+ {visibility:hidden;}
+</style>
+<script type="application/ecmascript">
+function evtChange()
+ {document.querySelectorAll('tt')[0].firstChild.nodeValue = 'PASS'}
+function evtInput()
+ {document.querySelectorAll('tt')[1].firstChild.nodeValue = 'PASS'}
+function evtDrop()
+ {document.querySelectorAll('tt')[2].firstChild.nodeValue = (event.dataTransfer.getData('text/plain') == 'http://example.org')?'PASS':'FAIL (selection is not properly added to data store)'}
+function evtKeypress()
+ {document.querySelectorAll('tt')[3].firstChild.nodeValue = 'FAIL (even is not supposed to fire)'}
+</script>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('p'))">
+<p>http://example.org</p>
+<p>Drag selected url to the input below. Follow check results link once you drop selection in the input.</p>
+<p><input type="url" placeholder="Drop selection here" onchange="evtChange()" oninput="evtInput()" onkeypress="evtKeypress()" ondrop="evtDrop()"/></p>
+<p><a href="javascript:document.querySelector('ul').removeAttribute('class')">Check results</a></p>
+<ul class="hidden">
+<li>Change event: <tt>FAIL (even did not fire)</tt></li>
+<li>Input event: <tt>FAIL (even did not fire)</tt></li>
+<li>Drop event: <tt>FAIL (even did not fire)</tt></li>
+<li>Keypress event: <tt>PASS</tt></li>
+</ul>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/085.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/085.xhtml
new file mode 100644
index 00000000000..23f49f72033
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/085.xhtml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Events during selection drag and drop to email input</title>
+<style type="text/css">
+input[placeholder]
+ {width:300px;
+ height:50px;
+ margin-top:20px;}
+.hidden
+ {visibility:hidden;}
+</style>
+<script type="application/ecmascript">
+function evtChange()
+ {document.querySelectorAll('tt')[0].firstChild.nodeValue = 'PASS'}
+function evtInput()
+ {document.querySelectorAll('tt')[1].firstChild.nodeValue = 'PASS'}
+function evtDrop()
+ {document.querySelectorAll('tt')[2].firstChild.nodeValue = (event.dataTransfer.getData('text/plain') == 'mail@example.org')?'PASS':'FAIL (selection is not properly added to data store)'}
+function evtKeypress()
+ {document.querySelectorAll('tt')[3].firstChild.nodeValue = 'FAIL (even is not supposed to fire)'}
+</script>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('p'))">
+<p>mail@example.org</p>
+<p>Drag selected address to the input below. Follow check results link once you drop selection in the input.</p>
+<p><input type="email" placeholder="Drop selection here" onchange="evtChange()" oninput="evtInput()" onkeypress="evtKeypress()" ondrop="evtDrop()"/></p>
+<p><a href="javascript:document.querySelector('ul').removeAttribute('class')">Check results</a></p>
+<ul class="hidden">
+<li>Change event: <tt>FAIL (even did not fire)</tt></li>
+<li>Input event: <tt>FAIL (even did not fire)</tt></li>
+<li>Drop event: <tt>FAIL (even did not fire)</tt></li>
+<li>Keypress event: <tt>PASS</tt></li>
+</ul>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/086.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/086.xhtml
new file mode 100644
index 00000000000..adb2fc7686d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/086.xhtml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Events during selection drag and drop to number input</title>
+<style type="text/css">
+input[placeholder]
+ {width:300px;
+ height:50px;
+ margin-top:20px;}
+.hidden
+ {visibility:hidden;}
+</style>
+<script type="application/ecmascript">
+function evtChange()
+ {document.querySelectorAll('tt')[0].firstChild.nodeValue = 'PASS'}
+function evtInput()
+ {document.querySelectorAll('tt')[1].firstChild.nodeValue = 'PASS'}
+function evtDrop()
+ {document.querySelectorAll('tt')[2].firstChild.nodeValue = (event.dataTransfer.getData('text/plain') == '123456789')?'PASS':'FAIL (selection is not properly added to data store)'}
+function evtKeypress()
+ {document.querySelectorAll('tt')[3].firstChild.nodeValue = 'FAIL (even is not supposed to fire)'}
+</script>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('p'))">
+<p>123456789</p>
+<p>Drag selected address to the input below. Follow check results link once you drop selection in the input.</p>
+<p><input type="number" placeholder="Drop selection here" onchange="evtChange()" oninput="evtInput()" onkeypress="evtKeypress()" ondrop="evtDrop()"/></p>
+<p><a href="javascript:document.querySelector('ul').removeAttribute('class')">Check results</a></p>
+<ul class="hidden">
+<li>Change event: <tt>FAIL (even did not fire)</tt></li>
+<li>Input event: <tt>FAIL (even did not fire)</tt></li>
+<li>Drop event: <tt>FAIL (even did not fire)</tt></li>
+<li>Keypress event: <tt>PASS</tt></li>
+</ul>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/087.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/087.xhtml
new file mode 100644
index 00000000000..6cb5b0f107d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/087.xhtml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Scrolling during selection drag and drop to text input</title>
+<style type="text/css">
+input[placeholder]
+ {width:300px;
+ height:50px;
+ margin-top:200px;}
+div
+ {height:150px;
+ width:500px;
+ overflow-y:scroll;}
+</style>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('p'))">
+<p>Drag me</p>
+<div>
+<p>You should be able to drag selected text to the input at the bottom of scrollable container (dragging towards the bottom edge triggers scrolling).</p>
+<input placeholder="Drop selection here"/>
+<p>Copy of selection should end up in the input once you drop it there.</p>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/088.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/088.xhtml
new file mode 100644
index 00000000000..54d0ca088f5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/088.xhtml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Vertical scrolling during selection drag and drop to text input</title>
+<style type="text/css">
+input[placeholder]
+ {width:300px;
+ height:50px;}
+div > p:first-child
+ {margin-bottom:200px;}
+body > div
+ {height:150px;
+ width:500px;
+ overflow-y:scroll;}
+div > div
+ {height:400px;}
+</style>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('p'))">
+<p>Drag me</p>
+<div>
+ <div>
+ <p>You should be able to drag selected text to the input at the bottom of scrollable container (dragging towards the bottom edge triggers scrolling).</p>
+ <input placeholder="Drop selection here"/>
+ <p>Copy of selection should end up in the input once you drop it there.</p>
+ </div>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/089.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/089.xhtml
new file mode 100644
index 00000000000..da0f5e2f17d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/089.xhtml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Scrolling during selection drag and drop to iframe</title>
+<style type="text/css">
+iframe
+ {width:350px;
+ height:150px;}
+</style>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('p'))">
+<p>Drag me</p>
+<p><iframe src="helper-scroll-then-drop-input.xhtml">XHTML document</iframe></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/090.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/090.xhtml
new file mode 100644
index 00000000000..5759be186de
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/090.xhtml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Scrolling during selection drag and drop to object</title>
+<style type="text/css">
+object
+ {width:350px;
+ height:150px;}
+</style>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('p'))">
+<p>Drag me</p>
+<p><object type="application/xhtml+xml" data="helper-scroll-then-drop-input.xhtml">XHTML document</object></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/091-1.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/091-1.xhtml
new file mode 100644
index 00000000000..5e11544c4e3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/091-1.xhtml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop: helper file</title>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('p'))">
+<p>Drag me</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/091-2.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/091-2.xhtml
new file mode 100644
index 00000000000..205eff77152
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/091-2.xhtml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop: helper file</title>
+<style type="text/css">
+input[placeholder]
+ {width:300px;
+ height:50px;}
+p:first-child
+ {margin-bottom:1000px;}
+</style>
+</head>
+<body>
+<p>You should be able to drag selected text to the input at the bottom of scrollable container (dragging towards the bottom edge triggers scrolling).</p>
+<input placeholder="Drop selection here"/>
+<p>Copy of selection should end up in the input once you drop it there.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/091.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/091.xhtml
new file mode 100644
index 00000000000..bc85f2231b1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/091.xhtml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Scrolling during selection drag and drop to frame</title>
+</head>
+<frameset rows="50%, 50%">
+<frame src="091-1.xhtml"/>
+<frame src="091-2.xhtml"/>
+</frameset>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/092.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/092.xhtml
new file mode 100644
index 00000000000..dfd454a10d1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/092.xhtml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from text input to element in object</title>
+<style type="text/css">
+object
+ {width:350px;
+ height:150px;}
+</style>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected text to the blue box. Copy of selection should end up in the blue box once you drop it there.</p>
+<p><input value="Drag me"/></p>
+<p><object type="application/xhtml+xml" data="helper-drop-here-blue-box.xhtml">XHTML document</object></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/093.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/093.xhtml
new file mode 100644
index 00000000000..88e8ecd8198
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/093.xhtml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from textarea to element in object</title>
+<style type="text/css">
+object
+ {width:350px;
+ height:150px;}
+</style>
+</head>
+<body onload="var t = document.querySelector('textarea');t.select();t.setSelectionRange(0,7)">
+<p>Drag selected text to the blue box. Copy of selection should end up in the blue box once you drop it there.</p>
+<p><textarea>Drag me</textarea></p>
+<p><object type="application/xhtml+xml" data="helper-drop-here-blue-box.xhtml">XHTML document</object></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/094.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/094.xhtml
new file mode 100644
index 00000000000..114fa0fee6f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/094.xhtml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from text input to textarea in object</title>
+<style type="text/css">
+object
+ {width:500px;
+ height:400px;}
+</style>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected text to the textarea. Copy of selection should end up in the textarea once you drop it there.</p>
+<p><input value="Drag me"/></p>
+<p><object type="application/xhtml+xml" data="helper-drop-here-textarea.xhtml">XHTML document</object></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/095.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/095.xhtml
new file mode 100644
index 00000000000..9f2c761d619
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/095.xhtml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from textarea to another textarea in object</title>
+<style type="text/css">
+object
+ {width:500px;
+ height:400px;}
+</style>
+</head>
+<body onload="var t = document.querySelector('textarea');t.select();t.setSelectionRange(0,7)">
+<p>Drag selected text to the textarea. Copy of selection should end up in the textarea once you drop it there.</p>
+<p><textarea>Drag me</textarea></p>
+<p><object type="application/xhtml+xml" data="helper-drop-here-textarea.xhtml">XHTML document</object></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/096.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/096.xhtml
new file mode 100644
index 00000000000..0589ede6c7c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/096.xhtml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from text input to contenteditable element in object</title>
+<style type="text/css">
+object
+ {width:350px;
+ height:150px;}
+</style>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected text to the blue box. Copy of selection should end up in the blue box once you drop it there.</p>
+<p><input value="Drag me"/></p>
+<p><object type="application/xhtml+xml" data="helper-drop-here-blue-box-contenteditable.xhtml">XHTML document</object></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/097.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/097.xhtml
new file mode 100644
index 00000000000..7ee94f86a9b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/097.xhtml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from textarea to contenteditable element in object</title>
+<style type="text/css">
+object
+ {width:350px;
+ height:150px;}
+</style>
+</head>
+<body onload="var t = document.querySelector('textarea');t.select();t.setSelectionRange(0,7)">
+<p>Drag selected text to the blue box. Copy of selection should end up in the blue box once you drop it there.</p>
+<p><textarea>Drag me</textarea></p>
+<p><object type="application/xhtml+xml" data="helper-drop-here-blue-box-contenteditable.xhtml">XHTML document</object></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/098.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/098.xhtml
new file mode 100644
index 00000000000..c1595d9bbfc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/098.xhtml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from text input in object to block element</title>
+<style type="text/css">
+object
+ {width:500px;
+ height:200px;}
+div[ondragenter]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body>
+<p><object type="application/xhtml+xml" data="helper-drag-me-input.xhtml">XHTML document</object></p>
+<div
+ ondragenter="event.preventDefault()"
+ ondragover="return false"
+ ondrop="document.querySelector('div').appendChild(document.createTextNode(event.dataTransfer.getData('text/plain')))"
+/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/099.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/099.xhtml
new file mode 100644
index 00000000000..8eaa0562ae6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/099.xhtml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from textarea in object to block element</title>
+<style type="text/css">
+object
+ {width:500px;
+ height:200px;}
+div[ondragenter]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body>
+<p><object type="application/xhtml+xml" data="helper-drag-me-textarea-to-other-blue-box.xhtml">XHTML document</object></p>
+<div
+ ondragenter="event.preventDefault()"
+ ondragover="return false"
+ ondrop="document.querySelector('div').appendChild(document.createTextNode(event.dataTransfer.getData('text/plain')))"
+/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/100.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/100.xhtml
new file mode 100644
index 00000000000..c6d5b52c78e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/100.xhtml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from text input in object to textarea</title>
+<style type="text/css">
+object
+ {width:500px;
+ height:200px;}
+textarea
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;}
+</style>
+</head>
+<body>
+<p><object type="application/xhtml+xml" data="helper-drag-me-input-to-other-textarea.xhtml">XHTML document</object></p>
+<p><textarea placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/101.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/101.xhtml
new file mode 100644
index 00000000000..d1316c1af09
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/101.xhtml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from textarea in object to another textarea</title>
+<style type="text/css">
+object
+ {width:500px;
+ height:200px;}
+textarea
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;}
+</style>
+</head>
+<body>
+<p><object type="application/xhtml+xml" data="helper-drag-me-textarea-to-other-textarea.xhtml">XHTML document</object></p>
+<p><textarea placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/102.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/102.xhtml
new file mode 100644
index 00000000000..ca924483029
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/102.xhtml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from text input in object to contenteditable element</title>
+<style type="text/css">
+object
+ {width:500px;
+ height:200px;}
+div[contenteditable]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body>
+<p><object type="application/xhtml+xml" data="helper-drag-me-input.xhtml">XHTML document</object></p>
+<div contenteditable="true"/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/103.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/103.xhtml
new file mode 100644
index 00000000000..4f91db6990b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/103.xhtml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from textarea in object to contenteditable element</title>
+<style type="text/css">
+object
+ {width:500px;
+ height:200px;}
+div[contenteditable]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body>
+<p><object type="application/xhtml+xml" data="helper-drag-me-textarea-to-other-blue-box.xhtml">XHTML document</object></p>
+<div contenteditable="true"/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/104.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/104.xhtml
new file mode 100644
index 00000000000..9b23cc9eff8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/104.xhtml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from text input in object to another text input</title>
+<style type="text/css">
+object
+ {width:500px;
+ height:200px;}
+textarea
+ {width:300px;
+ height:100px;
+ margin-top:20px;}
+</style>
+</head>
+<body>
+<p><object type="application/xhtml+xml" data="helper-drag-me-input-to-other-input.xhtml">XHTML document</object></p>
+<p><input placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/105.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/105.xhtml
new file mode 100644
index 00000000000..432664793e1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/105.xhtml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from textarea in object to text input</title>
+<style type="text/css">
+object
+ {width:500px;
+ height:200px;}
+textarea
+ {width:300px;
+ height:100px;
+ margin-top:20px;}
+</style>
+</head>
+<body>
+<p><object type="application/xhtml+xml" data="helper-drag-me-textarea-to-other-input.xhtml">XHTML document</object></p>
+<p><input placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/106.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/106.xhtml
new file mode 100644
index 00000000000..9accdc0758c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/106.xhtml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from textarea input in dataURL frame to block element</title>
+</head>
+<frameset rows="50%, 50%">
+<frame src="data:application/xhtml+xml,%3Chtml%20xmlns%3D%22http%3A//www.w3.org/1999/xhtml%22%3E%3Chead%3E%3Ctitle%3EDragging%20selection%3C/title%3E%3C/head%3E%3Cbody%20onload%3D%22document.querySelector%28%27input%27%29.select%28%29%22%3E%3Cp%3EDrag%20selected%20text%20to%20the%20blue%20box.%20Copy%20of%20selection%20should%20end%20up%20in%20the%20blue%20box%20once%20you%20drop%20it%20there.%3C/p%3E%3Cp%3E%3Cinput%20value%3D%22Drag%20me%22/%3E%3C/p%3E%3C/body%3E%3C/html%3E"/>
+<frame src="helper-drop-here-blue-box.xhtml"/>
+</frameset>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/107-1.html b/tests/wpt/web-platform-tests/html/editing/dnd/selection/107-1.html
new file mode 100644
index 00000000000..5dc99143f95
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/107-1.html
@@ -0,0 +1,8 @@
+<!doctype html>
+<title>Dragging selection breaks layout</title>
+<p>Select all text in the input below, drag it downwards a little, and release it. Pass if you can still edit the contents of the input.</p>
+<p><input value="SelectAndDrag"/></p>
+<script type="text/javascript">
+document.getElementsByTagName('input')[0].select();
+</script>
+<noscript><p>Enable JavaScript and reload</p></noscript> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/107.html b/tests/wpt/web-platform-tests/html/editing/dnd/selection/107.html
new file mode 100644
index 00000000000..0d7f75f3206
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/107.html
@@ -0,0 +1,5 @@
+<!doctype html>
+<title>Dragging selection breaks layout</title>
+<frameset rows="100%">
+ <frame src="107-1.html">
+</frameset> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/108-1.html b/tests/wpt/web-platform-tests/html/editing/dnd/selection/108-1.html
new file mode 100644
index 00000000000..9359fed4300
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/108-1.html
@@ -0,0 +1,3 @@
+<!doctype html>
+<title>Dragging custom selection breaks layout</title>
+<p>Select this sentence, drag it downwards a little, and release it. Pass if you can now select this sentence instead.</p> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/108.html b/tests/wpt/web-platform-tests/html/editing/dnd/selection/108.html
new file mode 100644
index 00000000000..967e99e0f4a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/108.html
@@ -0,0 +1,5 @@
+<!doctype html>
+<title>Dragging custom selection breaks layout</title>
+<frameset rows="100%">
+ <frame src="108-1.html">
+</frameset> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/109.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/109.xhtml
new file mode 100644
index 00000000000..7e4dc25c60c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/109.xhtml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>RTL text selection drag and drop from text input to RTL textarea</title>
+<style type="text/css">
+textarea
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;}
+</style>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected text to the textarea. Selected text should be moved to the textarea once you drop it there. Text direction should be preserved during drag and drop.</p>
+<p><input dir="rtl" value="&#x202E;FAIL|SSAP&#x202C;"/></p>
+<p><textarea dir="rtl" placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/110.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/110.xhtml
new file mode 100644
index 00000000000..fce336fb7d1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/110.xhtml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>RTL text selection drag and drop from text input to textarea</title>
+<style type="text/css">
+textarea
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;}
+</style>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected text to the textarea. Selected text should be moved to the textarea once you drop it there. Text direction should be preserved during drag and drop.</p>
+<div dir="rtl">
+<p><input value="&#x202E;FAIL|SSAP&#x202C;"/></p>
+<p><textarea placeholder="Drop selection here"/></p>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/111.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/111.xhtml
new file mode 100644
index 00000000000..4c3aa4094af
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/111.xhtml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>RTL text selection drag and drop from RTL element to textarea</title>
+<style type="text/css">
+textarea
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;}
+</style>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('p'))">
+<p dir="rtl">&#x202E;FAIL|SSAP&#x202C;</p>
+<p>Drag selected text to the textarea. Copy of selection should end up in the textarea once you drop it there. Text direction should be preserved during drag and drop.</p>
+<p dir="rtl"><textarea placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/112.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/112.xhtml
new file mode 100644
index 00000000000..693d0301d57
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/112.xhtml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>RTL text selection drag and drop to textarea</title>
+<style type="text/css">
+textarea
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;}
+</style>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('p'))">
+<p>&#x202E;FAIL|SSAP&#x202C;</p>
+<p>Drag selected text to the textarea. Copy of selection should end up in the textarea once you drop it there. Text direction should be preserved during drag and drop.</p>
+<p dir="rtl"><textarea placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/113.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/113.xhtml
new file mode 100644
index 00000000000..d8c92cb70d4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/113.xhtml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>RTL text selection drag and drop between textareas</title>
+<style type="text/css">
+textarea
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;}
+</style>
+</head>
+<body onload="var t = document.querySelector('textarea');t.select();t.setSelectionRange(0,11)">
+<p>Drag selected text to the textarea. Selected text should be moved to the textarea once you drop it there. Text direction should be preserved during drag and drop.</p>
+<p><textarea>&#x202E;FAIL|SSAP&#x202C;</textarea></p>
+<p><textarea dir="rtl" placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/114.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/114.xhtml
new file mode 100644
index 00000000000..4884ff2fef1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/114.xhtml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>RTL text selection drag and drop between RTL textareas</title>
+<style type="text/css">
+textarea
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;}
+</style>
+</head>
+<body onload="var t = document.querySelector('textarea');t.select();t.setSelectionRange(0,11)">
+<p>Drag selected text to the textarea. Selected text should be moved to the textarea once you drop it there. Text direction should be preserved during drag and drop.</p>
+<div dir="rtl">
+<p><textarea>&#x202E;FAIL|SSAP&#x202C;</textarea></p>
+<p><textarea placeholder="Drop selection here"/></p>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/115.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/115.xhtml
new file mode 100644
index 00000000000..a99d14f750c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/115.xhtml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>RTL text selection drag and drop between RTL inputs</title>
+<style type="text/css">
+input[placeholder]
+ {width:300px;
+ height:100px;
+ margin-top:20px;}
+</style>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected text to the input below. Selected text should be moved to the input once you drop it there. Text direction should be preserved during drag and drop.</p>
+<p><input dir="rtl" value="&#x202E;FAIL|SSAP&#x202C;"/></p>
+<p><input dir="rtl" placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/116.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/116.xhtml
new file mode 100644
index 00000000000..c4ea9930db8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/116.xhtml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>RTL text selection drag and drop between text inputs</title>
+<style type="text/css">
+input[placeholder]
+ {width:300px;
+ height:100px;
+ margin-top:20px;}
+</style>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected text to the input below. Selected text should be moved to the input once you drop it there. Text direction should be preserved during drag and drop.</p>
+<div dir="rtl">
+<p><input value="&#x202E;FAIL|SSAP&#x202C;"/></p>
+<p><input placeholder="Drop selection here"/></p>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/117.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/117.xhtml
new file mode 100644
index 00000000000..daa30ca42ca
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/117.xhtml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>RTL text selection drag and drop from RTL element to text input</title>
+<style type="text/css">
+input[placeholder]
+ {width:300px;
+ height:100px;
+ margin-top:20px;}
+</style>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('p'))">
+<p dir="rtl">&#x202E;FAIL|SSAP&#x202C;</p>
+<p>Drag selected text to the input below. Copy of selection should end up in the input once you drop it there. Text direction should be preserved during drag and drop.</p>
+<p dir="rtl"><input placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/118.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/118.xhtml
new file mode 100644
index 00000000000..0ea40e29993
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/118.xhtml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>RTL text selection drag and drop to text input</title>
+<style type="text/css">
+input[placeholder]
+ {width:300px;
+ height:100px;
+ margin-top:20px;}
+</style>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('p'))">
+<p>&#x202E;FAIL|SSAP&#x202C;</p>
+<p>Drag selected text to the input below. Copy of selection should end up in the input once you drop it there. Text direction should be preserved during drag and drop.</p>
+<p dir="rtl"><input placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/119.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/119.xhtml
new file mode 100644
index 00000000000..344679fada3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/119.xhtml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>RTL text selection drag and drop from textarea to RTL text input</title>
+<style type="text/css">
+input[placeholder]
+ {width:300px;
+ height:100px;
+ margin-top:20px;}
+</style>
+</head>
+<body onload="var t = document.querySelector('textarea');t.select();t.setSelectionRange(0,11)">
+<p>Drag selected text to the input below. Selected text should be moved to the input once you drop it there. Text direction should be preserved during drag and drop.</p>
+<p><textarea>&#x202E;FAIL|SSAP&#x202C;</textarea></p>
+<p><input dir="rtl" placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/120.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/120.xhtml
new file mode 100644
index 00000000000..eb7b7472d5c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/120.xhtml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>RTL text selection drag and drop from textarea to text input</title>
+<style type="text/css">
+input[placeholder]
+ {width:300px;
+ height:100px;
+ margin-top:20px;}
+</style>
+</head>
+<body onload="var t = document.querySelector('textarea');t.select();t.setSelectionRange(0,11)">
+<p>Drag selected text to the input below. Selected text should be moved to the input once you drop it there. Text direction should be preserved during drag and drop.</p>
+<div dir="rtl">
+<p><textarea>&#x202E;FAIL|SSAP&#x202C;</textarea></p>
+<p><input placeholder="Drop selection here"/></p>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/121.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/121.xhtml
new file mode 100644
index 00000000000..58de2b2d008
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/121.xhtml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>RTL text selection drag and drop from RTL text input to contenteditable element</title>
+<style type="text/css">
+div[contenteditable]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected text to the blue box. Selected text should be moved to the box once you drop it there. Text direction should be preserved during drag and drop.</p>
+<p><input dir="rtl" value="&#x202E;FAIL|SSAP&#x202C;"/></p>
+<p><div dir="rtl" contenteditable="true"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/122.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/122.xhtml
new file mode 100644
index 00000000000..cb2ade8a853
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/122.xhtml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>RTL text selection drag and drop from text input to contenteditable element</title>
+<style type="text/css">
+div[contenteditable]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected text to the blue box. Selected text should be moved to the box once you drop it there. Text direction should be preserved during drag and drop.</p>
+<div dir="rtl">
+<p><input value="&#x202E;FAIL|SSAP&#x202C;"/></p>
+<p><div contenteditable="true"/></p>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/123.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/123.xhtml
new file mode 100644
index 00000000000..597667a0eaf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/123.xhtml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>RTL text selection drag and drop from RTL element to contenteditable element</title>
+<style type="text/css">
+div[contenteditable]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('p'))">
+<p dir="rtl">&#x202E;FAIL|SSAP&#x202C;</p>
+<p>Drag selected text to the blue box. Copy of selection should end up in the box once you drop it there. Text direction should be preserved during drag and drop.</p>
+<p dir="rtl"><div contenteditable="true"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/124.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/124.xhtml
new file mode 100644
index 00000000000..b60da71a6e0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/124.xhtml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>RTL text selection drag and drop to contenteditable element</title>
+<style type="text/css">
+div[contenteditable]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('p'))">
+<p>&#x202E;FAIL|SSAP&#x202C;</p>
+<p>Drag selected text to the blue box. Copy of selection should end up in the box once you drop it there. Text direction should be preserved during drag and drop.</p>
+<p dir="rtl"><div contenteditable="true"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/125.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/125.xhtml
new file mode 100644
index 00000000000..65c074ca1c2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/125.xhtml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>RTL text selection drag and drop from textarea to RTL contenteditable element</title>
+<style type="text/css">
+div[contenteditable]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body onload="var t = document.querySelector('textarea');t.select();t.setSelectionRange(0,11)">
+<p>Drag selected text to the blue box. Selected text should be moved to the blue box once you drop it there.</p>
+<p><textarea>&#x202E;FAIL|SSAP&#x202C;</textarea></p>
+<p><div dir="rtl" contenteditable="true"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/126.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/126.xhtml
new file mode 100644
index 00000000000..03d92ae7b7a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/126.xhtml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>RTL text selection drag and drop from textarea to contenteditable element</title>
+<style type="text/css">
+div[contenteditable]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body onload="var t = document.querySelector('textarea');t.select();t.setSelectionRange(0,11)">
+<p>Drag selected text to the blue box. Selected text should be moved to the blue box once you drop it there.</p>
+<div dir="rtl">
+<p><textarea>&#x202E;FAIL|SSAP&#x202C;</textarea></p>
+<p><div contenteditable="true"/></p>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/127.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/127.xhtml
new file mode 100644
index 00000000000..161ab64db06
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/127.xhtml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>RTL text selection drag and drop from text input to RTL element</title>
+<style type="text/css">
+div[ondragenter]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected text to the blue box. Copy of selection should end up in the box once you drop it there. Text direction should be preserved during drag and drop.</p>
+<p><input dir="rtl" value="&#x202E;FAIL|SSAP&#x202C;"/></p>
+<div
+ dir="rtl"
+ ondragenter="event.preventDefault()"
+ ondragover="return false"
+ ondrop="document.querySelector('div').appendChild(document.createTextNode(event.dataTransfer.getData('text/plain')))"
+/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/128.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/128.xhtml
new file mode 100644
index 00000000000..504250686f4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/128.xhtml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>RTL text selection drag and drop from text input to block element</title>
+<style type="text/css">
+div[ondragenter]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected text to the blue box. Copy of selection should end up in the box once you drop it there. Text direction should be preserved during drag and drop.</p>
+<div dir="rtl">
+<p><input value="&#x202E;FAIL|SSAP&#x202C;"/></p>
+<div
+ ondragenter="event.preventDefault()"
+ ondragover="return false"
+ ondrop="document.querySelector('div > div').appendChild(document.createTextNode(event.dataTransfer.getData('text/plain')))"
+/>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/129.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/129.xhtml
new file mode 100644
index 00000000000..e9aea186607
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/129.xhtml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>RTL text selection drag and drop from RTL element to another RTL element</title>
+<style type="text/css">
+div[ondragenter]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('p'))">
+<p dir="rtl">&#x202E;FAIL|SSAP&#x202C;</p>
+<p>Drag selected text to the blue box. Copy of selection should end up in the box once you drop it there. Text direction should be preserved during drag and drop.</p>
+<div
+ dir="rtl"
+ ondragenter="event.preventDefault()"
+ ondragover="return false"
+ ondrop="document.querySelector('div').appendChild(document.createTextNode(event.dataTransfer.getData('text/plain')))"
+/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/130.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/130.xhtml
new file mode 100644
index 00000000000..07343252684
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/130.xhtml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>RTL text selection drag and drop to block element</title>
+<style type="text/css">
+div[ondragenter]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('p'))">
+<p>&#x202E;FAIL|SSAP&#x202C;</p>
+<p>Drag selected text to the blue box. Copy of selection should end up in the box once you drop it there. Text direction should be preserved during drag and drop.</p>
+<div
+ dir="rtl"
+ ondragenter="event.preventDefault()"
+ ondragover="return false"
+ ondrop="document.querySelector('div').appendChild(document.createTextNode(event.dataTransfer.getData('text/plain')))"
+/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/131.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/131.xhtml
new file mode 100644
index 00000000000..04e61773103
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/131.xhtml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>RTL text selection drag and drop from textarea to block element</title>
+<style type="text/css">
+div[ondragenter]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body onload="var t = document.querySelector('textarea');t.select();t.setSelectionRange(0,11)">
+<p>Drag selected text to the blue box. Copy of selection should end up in the blue box once you drop it there.</p>
+<p><textarea>&#x202E;FAIL|SSAP&#x202C;</textarea></p>
+<div
+ dir="rtl"
+ ondragenter="event.preventDefault()"
+ ondragover="return false"
+ ondrop="document.querySelector('div').appendChild(document.createTextNode(event.dataTransfer.getData('text/plain')))"
+/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/132.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/132.xhtml
new file mode 100644
index 00000000000..d662b206fd3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/132.xhtml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>RTL text selection drag and drop from RTL textarea to block element</title>
+<style type="text/css">
+div[ondragenter]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body onload="var t = document.querySelector('textarea');t.select();t.setSelectionRange(0,11)">
+<p>Drag selected text to the blue box. Copy of selection should end up in the blue box once you drop it there.</p>
+<p><textarea dir="rtl">&#x202E;FAIL|SSAP&#x202C;</textarea></p>
+<div
+ ondragenter="event.preventDefault()"
+ ondragover="return false"
+ ondrop="document.querySelector('div').appendChild(document.createTextNode(event.dataTransfer.getData('text/plain')))"
+/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/133.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/133.xhtml
new file mode 100644
index 00000000000..bf03eee9164
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/133.xhtml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Multielement selection drag and drop</title>
+<style type="text/css">
+textarea
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;}
+</style>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('div'))">
+<div>
+ <p>Drag selected text to the textarea.</p>
+ <p>Copy of selection should end up in the textarea once you drop it there.</p>
+</div>
+<p><textarea placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/134.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/134.xhtml
new file mode 100644
index 00000000000..0b61026da28
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/134.xhtml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop after selecting whole page content</title>
+<style type="text/css">
+textarea
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;}
+</style>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('body'))">
+<p>Drag selected text to the textarea. Copy of selection should end up in the textarea once you drop it there.</p>
+<p><textarea placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/135.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/135.xhtml
new file mode 100644
index 00000000000..34d63e720b8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/135.xhtml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop after manually selecting whole page content</title>
+<style type="text/css">
+textarea
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;}
+</style>
+</head>
+<body>
+<p>Select whole page (Ctrl+A) and try to drag selection to the textarea. Copy of selection should end up in the textarea once you drop it there.</p>
+<p><textarea placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/136.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/136.xhtml
new file mode 100644
index 00000000000..c4ffc7d002a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/136.xhtml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>BiDi text selection drag and drop to textarea</title>
+<style type="text/css">
+textarea
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;}
+</style>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('p'))">
+<p>PASS|LIAF &#x202E;FAIL|SSAP&#x202C; PASS|LIAF</p>
+<p>Drag selected text to the textarea. Copy of selection should end up in the textarea once you drop it there. Text direction should be preserved during drag and drop.</p>
+<p><textarea placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/137.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/137.xhtml
new file mode 100644
index 00000000000..a1841b367f4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/137.xhtml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Multielement BiDi text selection drag and drop to textarea</title>
+<style type="text/css">
+textarea
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;}
+</style>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('p'))">
+<p>PASS|LIAF <span dir="rtl">&#x202E;FAIL|SSAP&#x202C;</span> PASS|LIAF</p>
+<p>Drag selected text to the textarea. Copy of selection should end up in the textarea once you drop it there. Text direction should be preserved during drag and drop.</p>
+<p><textarea placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/138.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/138.xhtml
new file mode 100644
index 00000000000..4a9080a827f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/138.xhtml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>BiDi text selection drag and drop from text input to textarea</title>
+<style type="text/css">
+textarea
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;}
+</style>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected text to the textarea. Selected text should be moved to the textarea once you drop it there. Text direction should be preserved during drag and drop.</p>
+<p><input value="PASS|LIAF &#x202E;FAIL|SSAP&#x202C; PASS|LIAF"/></p>
+<p><textarea dir="rtl" placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/139.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/139.xhtml
new file mode 100644
index 00000000000..f9b1f61b608
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/139.xhtml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>BiDi text selection drag and drop between textareas</title>
+<style type="text/css">
+textarea
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;}
+</style>
+</head>
+<body onload="var t = document.querySelector('textarea');t.select();t.setSelectionRange(0,32)">
+<p>Drag selected text to the textarea. Selected text should be moved to the textarea once you drop it there. Text direction should be preserved during drag and drop.</p>
+<p><textarea>PASS|LIAF &#x202E;FAIL|SSAP&#x202C; PASS|LIAF</textarea></p>
+<p><textarea placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/140.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/140.xhtml
new file mode 100644
index 00000000000..c97468bfe2f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/140.xhtml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>BiDi text selection drag and drop between text inputs</title>
+<style type="text/css">
+input[placeholder]
+ {width:300px;
+ height:100px;
+ margin-top:20px;}
+</style>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected text to the input below. Selected text should be moved to the input once you drop it there. Text direction should be preserved during drag and drop.</p>
+<p><input value="PASS|LIAF &#x202E;FAIL|SSAP&#x202C; PASS|LIAF"/></p>
+<p><input placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/141.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/141.xhtml
new file mode 100644
index 00000000000..820556cb9fd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/141.xhtml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>BiDi text selection drag and drop to contenteditable element</title>
+<style type="text/css">
+div[contenteditable]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('p'))">
+<p>PASS|LIAF &#x202E;FAIL|SSAP&#x202C; PASS|LIAF</p>
+<p>Drag selected text to the blue box. Copy of selection should end up in the box once you drop it there. Text direction should be preserved during drag and drop.</p>
+<p><div contenteditable="true"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/142.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/142.xhtml
new file mode 100644
index 00000000000..428ce10c89e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/142.xhtml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>BiDi text selection drag and drop to block element</title>
+<style type="text/css">
+div[ondragenter]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('p'))">
+<p>PASS|LIAF &#x202E;FAIL|SSAP&#x202C; PASS|LIAF</p>
+<p>Drag selected text to the blue box. Copy of selection should end up in the box once you drop it there. Text direction should be preserved during drag and drop.</p>
+<div
+ ondragenter="event.preventDefault()"
+ ondragover="return false"
+ ondrop="document.querySelector('div').appendChild(document.createTextNode(event.dataTransfer.getData('text/plain')))"
+/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/143.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/143.xhtml
new file mode 100644
index 00000000000..39e73d41b30
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/143.xhtml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Large text selection drag and drop</title>
+<style type="text/css">
+textarea
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;}
+</style>
+<script type="application/ecmascript">
+function start(event)
+ {var p = document.querySelector('p:last-child'), s = p.firstChild.nodeValue;
+ for(var i = 0; i != 12; i++)
+ {s = s + ' ' + s;}
+ p.firstChild.nodeValue = 'Start of selection. ' + s + ' End of selection';
+ window.getSelection().selectAllChildren(p);}
+</script>
+</head>
+<body onload="start()">
+<p>Try to drag selection below to the textarea. Copy of selection should end up in the textarea once you drop it there.</p>
+<p><textarea placeholder="Drop selection here"/></p>
+<p>Large selection.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/144.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/144.xhtml
new file mode 100644
index 00000000000..6dd04bd4b2c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/144.xhtml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from text input and text/plain aliases</title>
+<style type="text/css">
+div
+ {min-height:40px;
+ width:40px;
+ padding:40px;
+ text-align:center;
+ color:white;
+ background-color:navy;}
+</style>
+<script type="application/ecmascript">
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ event.dataTransfer.setData('text/plain','PASS');}
+function checkText(event)
+ {var a = event.dataTransfer.getData('text/plain'),
+ b = event.dataTransfer.getData('text'),
+ c = event.dataTransfer.getData('TEXT'),
+ d = event.dataTransfer.getData('TexT');
+ document.querySelector('div').appendChild(document.createTextNode((a == b &amp;&amp; b == c &amp;&amp; c == d &amp;&amp; d == 'PASS')?' PASS ':' FAIL '))}
+</script>
+</head>
+<body onload="document.querySelector('input').select()">
+<p><input value="Drag me" ondragstart="start(event)"/></p>
+<p>Drag selection above to the navy box below and drop it. You should see word PASS once you drop it.</p>
+<div ondragenter="event.preventDefault()" ondragover="return false" ondrop="checkText(event)"/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/145.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/145.xhtml
new file mode 100644
index 00000000000..9ab73d43e1e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/145.xhtml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from inline element and text/plain aliases</title>
+<style type="text/css">
+div
+ {min-height:40px;
+ width:40px;
+ padding:40px;
+ text-align:center;
+ color:white;
+ background-color:navy;}
+</style>
+<script type="application/ecmascript">
+function start(event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ event.dataTransfer.setData('Text','PASS');}
+function checkText(event)
+ {var a = event.dataTransfer.getData('text/plain'),
+ b = event.dataTransfer.getData('text'),
+ c = event.dataTransfer.getData('TEXT'),
+ d = event.dataTransfer.getData('TexT');
+ document.querySelector('div').appendChild(document.createTextNode((a == b &amp;&amp; b == c &amp;&amp; c == d &amp;&amp; d == 'PASS')?'PASS':'FAIL'))}
+</script>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('span'))">
+<p><span ondragstart="start(event)">Drag me</span></p>
+<p>Drag selection above to the navy box below and drop it. You should see word PASS once you drop it.</p>
+<div ondragenter="event.preventDefault()" ondragover="return false" ondrop="checkText(event)"/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/146.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/146.xhtml
new file mode 100644
index 00000000000..574345cd1d5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/146.xhtml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop and text/plain aliases</title>
+<style type="text/css">
+div
+ {min-height:40px;
+ width:40px;
+ padding:40px;
+ text-align:center;
+ color:white;
+ background-color:navy;}
+</style>
+<script type="application/ecmascript">
+function checkText(event)
+ {var a = event.dataTransfer.getData('text/plain'),
+ b = event.dataTransfer.getData('text'),
+ c = event.dataTransfer.getData('TEXT'),
+ d = event.dataTransfer.getData('TexT');
+ document.querySelector('div').appendChild(document.createTextNode((a == b &amp;&amp; b == c &amp;&amp; c == d &amp;&amp; d == 'Drag me')?'PASS':'FAIL'))}
+</script>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('p'))">
+<p>Drag me</p>
+<p>Drag selection above to the navy box below and drop it. You should see word PASS once you drop it.</p>
+<div ondragenter="event.preventDefault()" ondragover="return false" ondrop="checkText(event)"/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/147.html b/tests/wpt/web-platform-tests/html/editing/dnd/selection/147.html
new file mode 100644
index 00000000000..da64ecd7398
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/147.html
@@ -0,0 +1,15 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Selection should not be cleared on failed drop</title>
+ </head>
+ <body>
+
+ <ol>
+ <li>Select some text in this sentence and begin dragging it.</li>
+ <li>Drop it on this text.</li>
+ <li>Pass if the text in step 1 is still selected.</li>
+ </ol>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/148.html b/tests/wpt/web-platform-tests/html/editing/dnd/selection/148.html
new file mode 100644
index 00000000000..93219c59447
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/148.html
@@ -0,0 +1,15 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Selection in input should not be cleared on failed drop</title>
+ </head>
+ <body>
+
+ <ol>
+ <li><textarea rows="3" cols="60">Select some text in this sentence and begin dragging it.</textarea></li>
+ <li>Drop it on this text.</li>
+ <li>Pass if the text in step 1 is still selected.</li>
+ </ol>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/149.html b/tests/wpt/web-platform-tests/html/editing/dnd/selection/149.html
new file mode 100644
index 00000000000..66475937df6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/149.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Dragging selections from multiline inputs should show editing caret</title>
+ </head>
+ <body>
+
+ <p>Select one word in the first input. Drag the selection around over the same input, and over the other inputs. It should show the input editing caret at the relevant insertion point within the target input's text.</p>
+ <p><textarea rows="3" cols="60">Dummy text, dummy text, dummy text, dummy text, dummy text,
+dummy text, dummy text, dummy text, dummy text, dummy text</textarea></p>
+ <p><textarea rows="3" cols="60">Dummy text, dummy text, dummy text, dummy text, dummy text,
+dummy text, dummy text, dummy text, dummy text, dummy text</textarea></p>
+ <p><input value="Dummy text, dummy text"></p>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/150.html b/tests/wpt/web-platform-tests/html/editing/dnd/selection/150.html
new file mode 100644
index 00000000000..ceecd35cde4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/150.html
@@ -0,0 +1,15 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Dragging selections from single-line inputs should show editing caret</title>
+ </head>
+ <body>
+
+ <p>Select one word in the first input. Drag the selection around over the same input, and over the other inputs. It should show the input editing caret at the relevant insertion point within the target input's text.</p>
+ <p><input value="Dummy text, dummy text"></p>
+ <p><textarea rows="3" cols="60">Dummy text, dummy text, dummy text, dummy text, dummy text,
+dummy text, dummy text, dummy text, dummy text, dummy text</textarea></p>
+ <p><input value="Dummy text, dummy text"></p>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/151.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/151.xhtml
new file mode 100644
index 00000000000..c9b2bf9f33b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/151.xhtml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Dropping selection in readonly text input</title>
+<style type="text/css">
+input
+ {padding:1em;
+ width:300px;}
+</style>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('p'))">
+<p>Drag me</p>
+<p>Try to drag selected text into the input below. You should not be able to drop it here.</p>
+<p><input readonly="readonly" placeholder="Try to drop selected text here" onchange="document.querySelector('p+p').firstChild.nodeValue = 'FAIL'"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/152.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/152.xhtml
new file mode 100644
index 00000000000..a9e24f3058b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/152.xhtml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Dropping selection in readonly textarea</title>
+<style type="text/css">
+textarea
+ {padding:1em;
+ width:300px;
+ height:100px;}
+</style>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('p'))">
+<p>Drag me</p>
+<p>Try to drag selected text into the input below. You should not be able to drop it here.</p>
+<p><textarea readonly="readonly" placeholder="Try to drop selected text here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/153.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/153.xhtml
new file mode 100644
index 00000000000..cb122364b5d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/153.xhtml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Dropping selection from text input into readonly text input</title>
+<style type="text/css">
+input
+ {padding:1em;
+ width:300px;}
+</style>
+</head>
+<body onload="document.querySelector('input').select()">
+<p><input value="Drag me"/></p>
+<p>Try to drag selected text into the input below. You should not be able to drop it here.</p>
+<p><input readonly="readonly" placeholder="Try to drop selected text here" onchange="document.querySelector('p+p').firstChild.nodeValue = 'FAIL'"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/154.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/154.xhtml
new file mode 100644
index 00000000000..96937b641b2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/154.xhtml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Dropping selection from text input into readonly textarea</title>
+<style type="text/css">
+textarea
+ {padding:1em;
+ width:300px;
+ height:100px;}
+</style>
+</head>
+<body onload="document.querySelector('input').select()">
+<p><input value="Drag me"/></p>
+<p>Try to drag selected text into the input below. You should not be able to drop it here.</p>
+<p><textarea readonly="readonly" placeholder="Try to drop selected text here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/155.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/155.xhtml
new file mode 100644
index 00000000000..f58562b00ea
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/155.xhtml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop from readonly textarea to block element</title>
+<style type="text/css">
+div[ondragenter]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body onload="var t = document.querySelector('textarea');t.select();t.setSelectionRange(0,7)">
+<p>Drag selected text to the blue box. Copy of selection should end up in the blue box once you drop it there.</p>
+<p><textarea readonly="readonly">Drag me</textarea></p>
+<div
+ ondragenter="event.preventDefault()"
+ ondragover="return false"
+ ondrop="document.querySelector('div').appendChild(document.createTextNode(event.dataTransfer.getData('text/plain')))"
+/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/156.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/156.xhtml
new file mode 100644
index 00000000000..cbdcdd826c1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/156.xhtml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop between text inputs</title>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected text to the blue box. Selected text should be moved to the blue box once you drop it there.</p>
+<p><input value="Drag me"/></p>
+<p><input placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/157.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/157.xhtml
new file mode 100644
index 00000000000..e754b67d4e1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/157.xhtml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop between search inputs</title>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected number to the second input box. Copy of selection should end up in the second input once you drop it there.</p>
+<p><input type="search" value="Selection"/></p>
+<p><input type="search" placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/158.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/158.xhtml
new file mode 100644
index 00000000000..a17ac4cf19b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/158.xhtml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop between tel inputs</title>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected number to the second input box. Copy of selection should end up in the second input once you drop it there.</p>
+<p><input type="tel" value="123456789"/></p>
+<p><input type="tel" placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/159.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/159.xhtml
new file mode 100644
index 00000000000..b8987acc564
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/159.xhtml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop between url inputs</title>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected number to the second input box. Copy of selection should end up in the second input once you drop it there.</p>
+<p><input type="url" value="http://example.org"/></p>
+<p><input type="url" placeholder="Drop selection here"/></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/160.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/160.xhtml
new file mode 100644
index 00000000000..8bb0297e47c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/160.xhtml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop between email inputs</title>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected number to the second input box. Copy of selection should end up in the second input once you drop it there.</p>
+<p><input type="email" value="mail@example.org"/></p>
+<p><input type="email" placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/161.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/161.xhtml
new file mode 100644
index 00000000000..f292bff1dd2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/161.xhtml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop between number inputs</title>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected number to the second input box. Copy of selection should end up in the second input once you drop it there.</p>
+<p><input type="number" value="123456789"/></p>
+<p><input type="number" placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/162.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/162.xhtml
new file mode 100644
index 00000000000..49d4ba9164e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/162.xhtml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop between contenteditable elements</title>
+<style type="text/css">
+div + div[contenteditable]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('div'))">
+<p>Drag selected text to the blue box. Copy of selection should end up in the blue box once you drop it there.</p>
+<div contenteditable="true">Drag me</div>
+<div contenteditable="true"/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/163.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/163.xhtml
new file mode 100644
index 00000000000..f94049a2503
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/163.xhtml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Moving text between text inputs</title>
+<script type="application/ecmascript">
+function check()
+ {var input = document.querySelectorAll('input');
+ document.querySelector('p').firstChild.nodeValue = (input[0].value == '' &amp;&amp; input[1].value == 'Drag me')?'PASS':'FAIL';}
+</script>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected text to the blue box. You should see word PASS once you drop it there.</p>
+<p><input value="Drag me"/></p>
+<p><input ondragenter="event.preventDefault()" ondragover="event.preventDefault();event.dataTransfer.effectAllowed = 'move'" ondrop="window.setTimeout('check()',100)" placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/164.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/164.xhtml
new file mode 100644
index 00000000000..28d4d4864f3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/164.xhtml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Moving text between search inputs</title>
+<script type="application/ecmascript">
+function check()
+ {var input = document.querySelectorAll('input');
+ document.querySelector('p').firstChild.nodeValue = (input[0].value == '' &amp;&amp; input[1].value == 'Selection')?'PASS':'FAIL';}
+</script>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected text to the blue box. Copy of selection should end up in the blue box once you drop it there.</p>
+<p><input type="search" value="Selection"/></p>
+<p><input ondragenter="event.preventDefault()" ondragover="event.preventDefault();event.dataTransfer.effectAllowed = 'move'" ondrop="window.setTimeout('check()',100)" type="search" placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/165.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/165.xhtml
new file mode 100644
index 00000000000..81ee12366d9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/165.xhtml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Moving text between tel inputs</title>
+<script type="application/ecmascript">
+function check()
+ {var input = document.querySelectorAll('input');
+ document.querySelector('p').firstChild.nodeValue = (input[0].value == '' &amp;&amp; input[1].value == '123456789')?'PASS':'FAIL';}
+</script>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected number to the blue box. Copy of selection should end up in the blue box once you drop it there.</p>
+<p><input type="tel" value="123456789"/></p>
+<p><input ondragenter="event.preventDefault()" ondragover="event.preventDefault();event.dataTransfer.effectAllowed = 'move'" ondrop="window.setTimeout('check()',100)" type="tel" placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/166.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/166.xhtml
new file mode 100644
index 00000000000..de23321ddb0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/166.xhtml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Moving text between url inputs</title>
+<script type="application/ecmascript">
+function check()
+ {var input = document.querySelectorAll('input');
+ document.querySelector('p').firstChild.nodeValue = (input[0].value == '' &amp;&amp; input[1].value == 'http://example.org')?'PASS':'FAIL';}
+</script>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected url to the blue box. Copy of selection should end up in the blue box once you drop it there.</p>
+<p><input type="url" value="http://example.org"/></p>
+<p><input ondragenter="event.preventDefault()" ondragover="event.preventDefault();event.dataTransfer.effectAllowed = 'move'" ondrop="window.setTimeout('check()',100)" type="url" placeholder="Drop selection here"/></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/167.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/167.xhtml
new file mode 100644
index 00000000000..cc0a58008bd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/167.xhtml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Moving text between email inputs</title>
+<script type="application/ecmascript">
+function check()
+ {var input = document.querySelectorAll('input');
+ document.querySelector('p').firstChild.nodeValue = (input[0].value == '' &amp;&amp; input[1].value == 'mail@example.org')?'PASS':'FAIL';}
+</script>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected email to the blue box. Copy of selection should end up in the blue box once you drop it there.</p>
+<p><input type="email" value="mail@example.org"/></p>
+<p><input ondragenter="event.preventDefault()" ondragover="event.preventDefault();event.dataTransfer.effectAllowed = 'move'" ondrop="window.setTimeout('check()',100)" type="email" placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/168.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/168.xhtml
new file mode 100644
index 00000000000..5b89314a8a2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/168.xhtml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Moving text between contenteditable elements</title>
+<style type="text/css">
+div + div[contenteditable]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+</style>
+<script type="application/ecmascript">
+function check()
+ {var div = document.querySelectorAll('div');
+ document.querySelector('p').firstChild.nodeValue = (!div[0].firstChild.nodeValue &amp;&amp; div[1].firstChild.nodeValue == 'Drag me')?'PASS':('FAIL(' + div[0].firstChild.nodeValue + ')');}
+</script>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('div'))">
+<p>Drag selected text to the blue box. Copy of selection should end up in the blue box once you drop it there.</p>
+<div contenteditable="true" ondragstart="event.dataTransfer.effectAllowed = 'move'">Drag me</div>
+<div ondragenter="event.preventDefault()" ondragover="event.preventDefault();" ondrop="window.setTimeout('check()',100)" contenteditable="true"/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/169.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/169.xhtml
new file mode 100644
index 00000000000..d1f56734fe4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/169.xhtml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Moving text from text input to contenteditable element</title>
+<style type="text/css">
+div[contenteditable]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+</style>
+<script type="application/ecmascript">
+function check()
+ {document.querySelector('p').firstChild.nodeValue = (document.querySelector('input').value == '' &amp;&amp; document.querySelector('div').firstChild.nodeValue == 'Drag me')?'PASS':('FAIL(' + div[0].firstChild.nodeValue + ')');}
+</script>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected text to the blue box. Copy of selection should end up in the blue box once you drop it there.</p>
+<p><input value="Drag me"/></p>
+<div ondragenter="event.preventDefault()" ondragover="event.preventDefault();event.dataTransfer.effectAllowed = 'move'" ondrop="window.setTimeout('check()',100)" contenteditable="true"/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/170.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/170.xhtml
new file mode 100644
index 00000000000..ccc8e8bdb3b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/170.xhtml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Dragging multiline text selection from scrolled textarea to block element</title>
+<style type="text/css">
+div[ondragenter]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+textarea
+ {width:300px;
+ height:100px;}
+</style>
+</head>
+<body onload="var t = document.querySelector('textarea');t.select();t.setSelectionRange(163,185)">
+<p>
+<textarea>
+Here is textarea with selection at the end of it.
+Drag selected text to the blue box.
+Copy of selection should end up in the blue box once you drop it there.
+Try to drag this text.
+</textarea>
+</p>
+<div
+ ondragenter="event.preventDefault()"
+ ondragover="return false"
+ ondrop="document.querySelector('div').appendChild(document.createTextNode(event.dataTransfer.getData('text/plain')))"
+/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/171.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/171.xhtml
new file mode 100644
index 00000000000..ce00dd71b4e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/171.xhtml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Dragging text selection from scrollable container to block element</title>
+<style type="text/css">
+div
+ {width:300px;
+ height:100px;}
+div:first-child
+ {overflow-y:scroll;}
+div[ondragenter]
+ {margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+textarea
+ {width:300px;
+ height:100px;}
+p+p
+ {margin-top:200px;
+ padding-bottom:50px;}
+</style>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('p + p'))">
+<div>
+<p>
+Here is scrollable container with text selection at the end of it.
+Drag selected text to the blue box.
+Copy of selection should end up in the blue box once you drop it there.
+</p>
+<p>Try to drag this text.</p>
+</div>
+<div
+ ondragenter="event.preventDefault()"
+ ondragover="return false"
+ ondrop="document.querySelector('div + div').appendChild(document.createTextNode(event.dataTransfer.getData('text/plain')))"
+/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/172.html b/tests/wpt/web-platform-tests/html/editing/dnd/selection/172.html
new file mode 100644
index 00000000000..a9273370176
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/172.html
@@ -0,0 +1,45 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Selection dragging should drag minimal HTML context</title>
+ <style type="text/css">
+p + div {
+ background: orange;
+ width: 4em;
+}
+div + div {
+ border: 1px solid black;
+ min-height: 5em;
+}
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ var output = document.getElementsByTagName('div')[1];
+ output.ondragenter = output.ondragover = function (e) { e.preventDefault(); };
+ output.ondrop = function (e) {
+ e.preventDefault();
+ var drophtml = e.dataTransfer.getData('text/html').toUpperCase().replace(/\sSTYLE="[^"]*"/g,'').replace(/[\r\n]+/g,'\\n');
+ var droptext = e.dataTransfer.getData('text/plain').replace(/[\r\n]+/g,'\\n');
+ var expectedhtml = '<P><SPAN>C</SPAN>D</P><P>E<SPAN>F</SPAN></P>';
+ var expectedtext = 'CD\\nEF';
+ if( drophtml != expectedhtml ) {
+ output.innerHTML = 'FAIL - normalised dropped HTML was:<br>'+drophtml.replace(/</g,'&lt;');
+ } else if( droptext != expectedtext ) {
+ output.innerHTML = 'FAIL - normalised dropped text was:<br>'+droptext.replace(/</g,'&lt;');
+ } else {
+ output.innerHTML = 'PASS';
+ }
+ };
+};
+ </script>
+ </head>
+ <body>
+
+ <p>Select the text from &quot;C&quot; to &quot;F&quot; (including both of those characters) in the text below.</p>
+ <div>
+ <p><span>A</span><span>BC</span>D</p><p>E<span>FG</span><span>H</span></p>
+ </div>
+ <div>Drag the selection and drop it here.</div>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/173.html b/tests/wpt/web-platform-tests/html/editing/dnd/selection/173.html
new file mode 100644
index 00000000000..5ff15a219b6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/173.html
@@ -0,0 +1,45 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Selection dragging should drag no HTML when inside a single element</title>
+ <style type="text/css">
+p + div {
+ background: orange;
+ width: 4em;
+}
+div + div {
+ border: 1px solid black;
+ min-height: 5em;
+}
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ var output = document.getElementsByTagName('div')[1];
+ output.ondragenter = output.ondragover = function (e) { e.preventDefault(); };
+ output.ondrop = function (e) {
+ e.preventDefault();
+ var drophtml = e.dataTransfer.getData('text/html').toUpperCase().replace(/\sSTYLE="[^"]*"/g,'').replace(/[\r\n]+/g,'\\n');
+ var droptext = e.dataTransfer.getData('text/plain').replace(/[\r\n]+/g,'\\n');
+ var expectedhtml = 'B';
+ var expectedtext = 'B';
+ if( drophtml != expectedhtml ) {
+ output.innerHTML = 'FAIL - normalised dropped HTML was:<br>'+drophtml.replace(/</g,'&lt;');
+ } else if( droptext != expectedtext ) {
+ output.innerHTML = 'FAIL - normalised dropped text was:<br>'+droptext.replace(/</g,'&lt;');
+ } else {
+ output.innerHTML = 'PASS';
+ }
+ };
+};
+ </script>
+ </head>
+ <body>
+
+ <p>Select &quot;B&quot; in the text below.</p>
+ <div>
+ <p>ABC</p>
+ </div>
+ <div>Drag the selection and drop it here.</div>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/helper-drag-me-input-to-other-input.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/helper-drag-me-input-to-other-input.xhtml
new file mode 100644
index 00000000000..f005092f6e7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/helper-drag-me-input-to-other-input.xhtml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop: helper file</title>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected text to the input field below. Copy of selection should end up in the input once you drop it there.</p>
+<p><input value="Drag me"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/helper-drag-me-input-to-other-textarea.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/helper-drag-me-input-to-other-textarea.xhtml
new file mode 100644
index 00000000000..767e5a43e24
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/helper-drag-me-input-to-other-textarea.xhtml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop: helper file</title>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected text to the textarea. Copy of selection should end up in the textarea once you drop it there.</p>
+<p><input value="Drag me"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/helper-drag-me-input.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/helper-drag-me-input.xhtml
new file mode 100644
index 00000000000..9d12a89dd7b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/helper-drag-me-input.xhtml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop: helper file</title>
+</head>
+<body onload="document.querySelector('input').select()">
+<p>Drag selected text to the blue box. Copy of selection should end up in the blue box once you drop it there.</p>
+<p><input value="Drag me"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/helper-drag-me-textarea-to-other-blue-box.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/helper-drag-me-textarea-to-other-blue-box.xhtml
new file mode 100644
index 00000000000..6c76fbdbb34
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/helper-drag-me-textarea-to-other-blue-box.xhtml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop: helper file</title>
+<style type="text/css">
+textarea
+ {height:1.5em;
+ width:7em;}
+</style>
+</head>
+<body onload="var t = document.querySelector('textarea');t.select();t.setSelectionRange(0,7)">
+<p>Drag selected text to the blue box. Copy of selection should end up in the blue box once you drop it there.</p>
+<p><textarea>Drag me</textarea></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/helper-drag-me-textarea-to-other-input.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/helper-drag-me-textarea-to-other-input.xhtml
new file mode 100644
index 00000000000..287e3bb5ebd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/helper-drag-me-textarea-to-other-input.xhtml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop: helper file</title>
+<style type="text/css">
+textarea
+ {height:1.5em;
+ width:7em;}
+</style>
+</head>
+<body onload="var t = document.querySelector('textarea');t.select();t.setSelectionRange(0,7)">
+<p>Drag selected text to the input field below. Copy of selection should end up in the input once you drop it there.</p>
+<p><textarea>Drag me</textarea></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/helper-drag-me-textarea-to-other-textarea.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/helper-drag-me-textarea-to-other-textarea.xhtml
new file mode 100644
index 00000000000..c7eb544784b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/helper-drag-me-textarea-to-other-textarea.xhtml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop: helper file</title>
+<style type="text/css">
+textarea
+ {height:1.5em;
+ width:7em;}
+</style>
+</head>
+<body onload="var t = document.querySelector('textarea');t.select();t.setSelectionRange(0,7)">
+<p>Drag selected text to the textarea. Copy of selection should end up in the textarea once you drop it there.</p>
+<p><textarea>Drag me</textarea></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/helper-drop-here-blue-box-contenteditable.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/helper-drop-here-blue-box-contenteditable.xhtml
new file mode 100644
index 00000000000..20f3820a14e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/helper-drop-here-blue-box-contenteditable.xhtml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop: helper file</title>
+<style type="text/css">
+div[contenteditable]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body>
+<div contenteditable="true"/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/helper-drop-here-blue-box.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/helper-drop-here-blue-box.xhtml
new file mode 100644
index 00000000000..ccd32c227b9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/helper-drop-here-blue-box.xhtml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop: helper file</title>
+<style type="text/css">
+div[ondragenter]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body>
+<div
+ ondragenter="event.preventDefault()"
+ ondragover="return false"
+ ondrop="document.querySelector('div').appendChild(document.createTextNode(event.dataTransfer.getData('text/plain')))"
+/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/helper-drop-here-input.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/helper-drop-here-input.xhtml
new file mode 100644
index 00000000000..8be631888d0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/helper-drop-here-input.xhtml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop: helper file</title>
+<style type="text/css">
+textarea
+ {width:300px;
+ height:100px;
+ margin-top:20px;}
+</style>
+</head>
+<body>
+<p><input placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/helper-drop-here-textarea.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/helper-drop-here-textarea.xhtml
new file mode 100644
index 00000000000..cbe268374c3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/helper-drop-here-textarea.xhtml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop: helper file</title>
+<style type="text/css">
+textarea
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;}
+</style>
+</head>
+<body>
+<p><textarea placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/selection/helper-scroll-then-drop-input.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/selection/helper-scroll-then-drop-input.xhtml
new file mode 100644
index 00000000000..14c01ccac71
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/selection/helper-scroll-then-drop-input.xhtml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selection drag and drop: helper file</title>
+<style type="text/css">
+input[placeholder]
+ {width:300px;
+ height:50px;}
+p:first-child
+ {margin-bottom:200px;}
+</style>
+</head>
+<body>
+<p>You should be able to drag selected text to the input at the bottom of scrollable container (dragging towards the bottom edge triggers scrolling).</p>
+<input placeholder="Drop selection here"/>
+<p>Copy of selection should end up in the input once you drop it there.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/001.svg b/tests/wpt/web-platform-tests/html/editing/dnd/svg/001.svg
new file mode 100644
index 00000000000..055a7b278b7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/001.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" version="1.2" width="500px" height="500px" viewBox="0 0 500 500">
+<title>Drag and drop of SVG text selection from text element to textArea</title>
+<text x="10" y="30" font-size="20">Select part of this text and drag selection to</text>
+<text x="10" y="60" font-size="20">the box below. Content of selection should be</text>
+<text x="10" y="90" font-size="20">copies once it's dropped in the box.</text>
+<textArea x="10" y="110" width="480" height="380" font-size="20" editable="simple" pointer-events="boundingBox">Drop selection here</textArea>
+<rect x="10" y="110" width="480" height="380" stroke="black" stroke-width="1" fill="none"/>
+</svg> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/002.svg b/tests/wpt/web-platform-tests/html/editing/dnd/svg/002.svg
new file mode 100644
index 00000000000..45ab566e661
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/002.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" version="1.2" width="500px" height="500px" viewBox="0 0 500 500">
+<title>Drag and drop of SVG text selection from editable text element to textArea</title>
+<text x="10" y="30" editable="simple" font-size="20">Select part of this text and drag selection to</text>
+<text x="10" y="60" font-size="20">the box below. Content of selection should be</text>
+<text x="10" y="90" font-size="20">copies once it's dropped in the box.</text>
+<textArea x="10" y="110" width="480" height="380" font-size="20" editable="simple" pointer-events="boundingBox">Drop selection here</textArea>
+<rect x="10" y="110" width="480" height="380" stroke="black" stroke-width="1" fill="none"/>
+</svg> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/003.svg b/tests/wpt/web-platform-tests/html/editing/dnd/svg/003.svg
new file mode 100644
index 00000000000..c1f30cfbc42
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/003.svg
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" version="1.2" width="500px" height="500px" viewBox="0 0 500 500">
+<title>Drag and drop of SVG text selection from tspan elements to textArea</title>
+<text x="10" y="30" font-size="20">
+ <tspan>Select part</tspan>
+ <tspan>of this text</tspan>
+ <tspan>and drag selection to</tspan>
+</text>
+<text x="10" y="60" font-size="20">the box below. Content of selection should be</text>
+<text x="10" y="90" font-size="20">copies once it's dropped in the box.</text>
+<textArea x="10" y="110" width="480" height="380" font-size="20" editable="simple" pointer-events="boundingBox">Drop selection here</textArea>
+<rect x="10" y="110" width="480" height="380" stroke="black" stroke-width="1" fill="none"/>
+</svg> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/004.svg b/tests/wpt/web-platform-tests/html/editing/dnd/svg/004.svg
new file mode 100644
index 00000000000..e3c4828a8ca
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/004.svg
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.2" width="500px" height="500px" viewBox="0 0 500 500">
+<title>Drag and drop of SVG text selection from tref element to textArea</title>
+<defs>
+ <text id="text">Select me</text>
+ </defs>
+<text x="10" y="30" font-size="20" fill="navy"><tref xlink:href="#text"/></text>
+<text x="10" y="60" font-size="20">Select text above and drag selection to</text>
+<text x="10" y="90" font-size="20">the box below. Content of selection should be</text>
+<text x="10" y="120" font-size="20">copies once it's dropped in the box.</text>
+<textArea x="10" y="130" width="480" height="360" font-size="20" editable="simple" pointer-events="boundingBox">Drop selection here</textArea>
+<rect x="10" y="130" width="480" height="360" stroke="black" stroke-width="1" fill="none"/>
+</svg> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/005.svg b/tests/wpt/web-platform-tests/html/editing/dnd/svg/005.svg
new file mode 100644
index 00000000000..9bb3bd68bb4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/005.svg
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" version="1.2" width="500px" height="500px" viewBox="0 0 500 500">
+<title>Drag and drop of SVG text selection from textArea to textArea</title>
+<textArea x="10" y="10" width="480" height="90" font-size="20">Select part of this text and drag selection to the box below.
+Content of selection should be copied once it's dropped in the box.</textArea>
+<textArea x="10" y="110" width="480" height="380" font-size="20" editable="simple" pointer-events="boundingBox">Drop selection here</textArea>
+<rect x="10" y="110" width="480" height="380" stroke="black" stroke-width="1" fill="none"/>
+</svg> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/006.svg b/tests/wpt/web-platform-tests/html/editing/dnd/svg/006.svg
new file mode 100644
index 00000000000..5edeba69718
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/006.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" version="1.2" width="500px" height="500px" viewBox="0 0 500 500">
+<title>Drag and drop of SVG text selection from text element to editable text element</title>
+<text x="10" y="30" font-size="20">Select part of this text and drag selection to</text>
+<text x="10" y="60" font-size="20">the box below. Content of selection should be</text>
+<text x="10" y="90" font-size="20">copies once it's dropped in the box.</text>
+<text x="10" y="200" font-size="50" editable="simple">                             </text>
+<rect x="10" y="160" width="480" height="50" stroke="black" stroke-width="1" fill="none"/>
+</svg> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/007.svg b/tests/wpt/web-platform-tests/html/editing/dnd/svg/007.svg
new file mode 100644
index 00000000000..7d8bcf8d4d6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/007.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" version="1.2" width="500px" height="500px" viewBox="0 0 500 500">
+<title>Drag and drop of SVG text selection between editable text elements</title>
+<text x="10" y="30" font-size="20" editable="simple">Select part of this text and drag selection to</text>
+<text x="10" y="60" font-size="20">the box below. Content of selection should be</text>
+<text x="10" y="90" font-size="20">copies once it's dropped in the box.</text>
+<text x="10" y="200" font-size="50" editable="simple">                             </text>
+<rect x="10" y="160" width="480" height="50" stroke="black" stroke-width="1" fill="none"/>
+</svg> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/008.svg b/tests/wpt/web-platform-tests/html/editing/dnd/svg/008.svg
new file mode 100644
index 00000000000..167f73febe7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/008.svg
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" version="1.2" width="500px" height="500px" viewBox="0 0 500 500">
+<title>Drag and drop of SVG text selection from tspan element to editable text element</title>
+<text x="10" y="30" font-size="20">
+ <tspan>Select part</tspan>
+ <tspan>of this text</tspan>
+ <tspan>and drag selection to</tspan>
+</text>
+<text x="10" y="60" font-size="20">the box below. Content of selection should be</text>
+<text x="10" y="90" font-size="20">copies once it's dropped in the box.</text>
+<text x="10" y="200" font-size="50" editable="simple">                             </text>
+<rect x="10" y="160" width="480" height="50" stroke="black" stroke-width="1" fill="none"/>
+</svg> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/009.svg b/tests/wpt/web-platform-tests/html/editing/dnd/svg/009.svg
new file mode 100644
index 00000000000..e7bd622a0f8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/009.svg
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.2" width="500px" height="500px" viewBox="0 0 500 500">
+<title>Drag and drop of SVG text selection from tref element to editable text element</title>
+<defs>
+ <text id="text">Select me</text>
+ </defs>
+<text x="10" y="30" font-size="20" fill="navy"><tref xlink:href="#text"/></text>
+<text x="10" y="60" font-size="20">Select text above and drag selection to</text>
+<text x="10" y="90" font-size="20">the box below. Content of selection should be</text>
+<text x="10" y="120" font-size="20">copies once it's dropped in the box.</text>
+<text x="10" y="200" font-size="50" editable="simple">                             </text>
+<rect x="10" y="160" width="480" height="50" stroke="black" stroke-width="1" fill="none"/>
+</svg> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/010.svg b/tests/wpt/web-platform-tests/html/editing/dnd/svg/010.svg
new file mode 100644
index 00000000000..c5cce18678c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/010.svg
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" version="1.2" width="500px" height="500px" viewBox="0 0 500 500">
+<title>Drag and drop of SVG text selection from textArea to editable text element</title>
+<textArea x="10" y="10" width="480" height="90" font-size="20">Select part of this text and drag selection to the box below.
+Content of selection should be copied once it's dropped in the box.</textArea>
+<text x="10" y="200" font-size="50" editable="simple">                             </text>
+<rect x="10" y="160" width="480" height="50" stroke="black" stroke-width="1" fill="none"/>
+</svg> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/011.svg b/tests/wpt/web-platform-tests/html/editing/dnd/svg/011.svg
new file mode 100644
index 00000000000..8f07c3c82ae
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/011.svg
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.2" width="500px" height="500px" viewBox="0 0 500 500">
+<title>Drag and drop of SVG text selection from textpath to textArea</title>
+<defs>
+ <path id="path" d="M 10 40 C 10 20 480 20 480 40"/>
+</defs>
+<text fill="navy">
+ <textPath xlink:href="#path">Some selectable text rendered along curved text path</textPath>
+</text>
+<text x="10" y="60" font-size="20">Select part of text above and drag selection to</text>
+<text x="10" y="90" font-size="20">the box below. Content of selection should be</text>
+<text x="10" y="120" font-size="20">copies once it's dropped in the box.</text>
+<textArea x="10" y="130" width="480" height="360" font-size="20" editable="simple" pointer-events="boundingBox">Drop selection here</textArea>
+<rect x="10" y="130" width="480" height="360" stroke="black" stroke-width="1" fill="none"/>
+</svg> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/012.svg b/tests/wpt/web-platform-tests/html/editing/dnd/svg/012.svg
new file mode 100644
index 00000000000..18c027655a9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/012.svg
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.2" width="500px" height="500px" viewBox="0 0 500 500">
+<title>Drag and drop of SVG text selection from editable textpath to textArea</title>
+<defs>
+ <path id="path" d="M 10 40 C 10 20 480 20 480 40"/>
+</defs>
+<text fill="navy" editable="simple">
+ <textPath xlink:href="#path">Some selectable text rendered along curved text path</textPath>
+</text>
+<text x="10" y="60" font-size="20">Select part of text above and drag selection to</text>
+<text x="10" y="90" font-size="20">the box below. Content of selection should be</text>
+<text x="10" y="120" font-size="20">copies once it's dropped in the box.</text>
+<textArea x="10" y="130" width="480" height="360" font-size="20" editable="simple" pointer-events="boundingBox">Drop selection here</textArea>
+<rect x="10" y="130" width="480" height="360" stroke="black" stroke-width="1" fill="none"/>
+</svg> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/013-1.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/svg/013-1.xhtml
new file mode 100644
index 00000000000..a97dce1f2b9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/013-1.xhtml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop from SVG: helper file</title>
+<style type="text/css">
+textarea
+ {width:400px;
+ height:300px;
+ padding:10px;}
+</style>
+</head>
+<body>
+<p><textarea placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/013.svg b/tests/wpt/web-platform-tests/html/editing/dnd/svg/013.svg
new file mode 100644
index 00000000000..d312135be01
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/013.svg
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.2" width="500px" height="500px" viewBox="0 0 500 500">
+<title>Drag and drop of SVG text selection from text element to XHTML textarea in foreignObject</title>
+<text x="10" y="30" font-size="20">Select part of this text and drag selection to</text>
+<text x="10" y="60" font-size="20">the box below. Content of selection should be</text>
+<text x="10" y="90" font-size="20">copies once it's dropped in the box.</text>
+<switch>
+ <foreignObject x="10" y="120" width="480" height="380" requiredExtensions="http://www.w3.org/1999/xhtml" xlink:href="013-1.xhtml"/>
+ <text x="10" y="150" font-size="20">Skip the test (foreignObject is not supported).</text>
+</switch>
+</svg> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/014-1.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/svg/014-1.xhtml
new file mode 100644
index 00000000000..674870d05c6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/014-1.xhtml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop from SVG: helper file</title>
+<style type="text/css">
+div[contenteditable]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body>
+<div contenteditable="true"/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/014.svg b/tests/wpt/web-platform-tests/html/editing/dnd/svg/014.svg
new file mode 100644
index 00000000000..772a9fdefba
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/014.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.2" width="500px" height="500px" viewBox="0 0 500 500">
+<title>Drag and drop of SVG text selection from textArea to contenteditable element in foreignObject</title>
+<textArea x="10" y="10" width="480" height="90" font-size="20">Select part of this text and drag selection to the box below.
+Content of selection should be copied once it's dropped in the box.</textArea>
+<switch>
+ <foreignObject x="10" y="120" width="480" height="380" requiredExtensions="http://www.w3.org/1999/xhtml" xlink:href="014-1.xhtml"/>
+ <text x="10" y="150" font-size="20">Skip the test (foreignObject is not supported).</text>
+</switch>
+</svg> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/015-1.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/svg/015-1.xhtml
new file mode 100644
index 00000000000..f5217a91e9d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/015-1.xhtml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop from SVG: helper file</title>
+</head>
+<body>
+<input placeholder="Drop selection here"/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/015.svg b/tests/wpt/web-platform-tests/html/editing/dnd/svg/015.svg
new file mode 100644
index 00000000000..3f97727c5ca
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/015.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.2" width="500px" height="500px" viewBox="0 0 500 500">
+<title>Drag and drop of SVG text selection from textArea to XHTML input in foreignObject</title>
+<textArea x="10" y="10" width="480" height="90" font-size="20">Select part of this text and drag selection to the box below.
+Content of selection should be copied once it's dropped in the box.</textArea>
+<switch>
+ <foreignObject x="10" y="120" width="480" height="380" requiredExtensions="http://www.w3.org/1999/xhtml" xlink:href="015-1.xhtml"/>
+ <text x="10" y="150" font-size="20">Skip the test (foreignObject is not supported).</text>
+</switch>
+</svg> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/016-1.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/svg/016-1.xhtml
new file mode 100644
index 00000000000..484d4b4eb7e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/016-1.xhtml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop from SVG: helper file</title>
+<style type="text/css">
+div[ondragenter]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body>
+<div
+ ondragenter="event.preventDefault();event.dataTransfer.effectAllowed = 'copy'"
+ ondragover="return false"
+ ondrop="document.querySelector('div').appendChild(document.createTextNode(event.dataTransfer.getData('text/plain')))"
+/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/016.svg b/tests/wpt/web-platform-tests/html/editing/dnd/svg/016.svg
new file mode 100644
index 00000000000..60d9e40c70b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/016.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.2" width="500px" height="500px" viewBox="0 0 500 500">
+<title>Drag and drop of SVG text selection from textArea to foreignObject</title>
+<textArea x="10" y="10" width="480" height="90" font-size="20">Select part of this text and drag selection to the box below.
+Content of selection should be copied once it's dropped in the box.</textArea>
+<switch>
+ <foreignObject x="10" y="120" width="480" height="380" requiredExtensions="http://www.w3.org/1999/xhtml" xlink:href="016-1.xhtml"/>
+ <text x="10" y="150" font-size="20">Skip the test (foreignObject is not supported).</text>
+</switch>
+</svg> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/017.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/svg/017.xhtml
new file mode 100644
index 00000000000..598a2c6f3d3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/017.xhtml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Dragging selection to SVG textArea</title>
+</head>
+<body onload="window.getSelection().selectAllChildren(document.querySelector('p'))">
+<p>Drag me</p>
+<p>Drag selection above to the box below. Copy of selection should end up in the box once you drop it there.</p>
+<svg xmlns="http://www.w3.org/2000/svg" version="1.2" width="500px" height="300px" viewBox="0 0 500 300">
+<textArea x="10" y="10" width="480" height="280" font-size="20" editable="simple" pointer-events="boundingBox">Drop selection here</textArea>
+<rect x="10" y="10" width="480" height="280" stroke="black" stroke-width="1" fill="none"/>
+</svg>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/018.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/svg/018.xhtml
new file mode 100644
index 00000000000..03ac442a36e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/018.xhtml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Dragging selection from XHTML text input to SVG textArea</title>
+</head>
+<body onload="document.querySelector('input').select()">
+<p><input value="Drag me"/></p>
+<p>Drag selection above to the blue box. Copy of selection should end up in the blue box once you drop it there.</p>
+<svg xmlns="http://www.w3.org/2000/svg" version="1.2" width="500px" height="300px" viewBox="0 0 500 300">
+<textArea x="10" y="10" width="480" height="280" font-size="20" editable="simple" pointer-events="boundingBox">Drop selection here</textArea>
+<rect x="10" y="10" width="480" height="280" stroke="black" stroke-width="1" fill="none"/>
+</svg>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/019.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/svg/019.xhtml
new file mode 100644
index 00000000000..6c16875a14d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/019.xhtml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Dragging selection from XHTML textarea to SVG textArea</title>
+<style type="text/css">
+textarea
+ {height:1.5em;
+ width:7em;}
+</style>
+</head>
+<body onload="var t = document.querySelector('textarea');t.select();t.setSelectionRange(0,7)">
+<p><textarea>Drag me</textarea></p>
+<p>Drag selection above to the blue box. Copy of selection should end up in the blue box once you drop it there.</p>
+<svg xmlns="http://www.w3.org/2000/svg" version="1.2" width="500px" height="300px" viewBox="0 0 500 300">
+<textArea x="10" y="10" width="480" height="280" font-size="20" editable="simple" pointer-events="boundingBox">Drop selection here</textArea>
+<rect x="10" y="10" width="480" height="280" stroke="black" stroke-width="1" fill="none"/>
+</svg>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/020.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/svg/020.xhtml
new file mode 100644
index 00000000000..c3c50fd9ece
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/020.xhtml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Dragging multiline selection from XHTML textarea to SVG textArea</title>
+<style type="text/css">
+textarea
+ {width:300px;
+ height:100px;}
+</style>
+</head>
+<body onload="var t = document.querySelector('textarea');t.select();t.setSelectionRange(25,56)">
+<p>
+<textarea>
+Here is textarea
+with selection that
+spans two lines.
+Drag selected text to the blue box.
+Copy of selection should end up in the blue box once you drop it there.
+</textarea>
+</p>
+<p>Drag selection above to the textarea below. Copy of selection should end up in the textarea once you drop it there.</p>
+<svg xmlns="http://www.w3.org/2000/svg" version="1.2" width="500px" height="300px" viewBox="0 0 500 300">
+<textArea x="10" y="10" width="480" height="280" font-size="20" editable="simple" pointer-events="boundingBox">Drop selection here</textArea>
+<rect x="10" y="10" width="480" height="280" stroke="black" stroke-width="1" fill="none"/>
+</svg>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/021.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/svg/021.xhtml
new file mode 100644
index 00000000000..3cc07af2885
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/021.xhtml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Dragging selection from SVG text element to XHTML element</title>
+<style type="text/css">
+div[ondragenter]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body>
+<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="200px" height="50px" viewBox="0 0 200 50">
+<text x="10" y="45" font-size="30" fill="navy">Select me</text>
+</svg>
+<p>Select the text above and drag selection to the blue box. Copy of selection should end up in the blue box once you drop it there.</p>
+<div
+ ondragenter="event.preventDefault()"
+ ondragover="return false"
+ ondrop="document.querySelector('div').appendChild(document.createTextNode(event.dataTransfer.getData('text/plain')))"
+/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/022.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/svg/022.xhtml
new file mode 100644
index 00000000000..bd619ca0054
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/022.xhtml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Dragging selection from SVG editable text element to XHTML element</title>
+<style type="text/css">
+div[ondragenter]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body>
+<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="200px" height="50px" viewBox="0 0 200 50">
+<text x="10" y="45" font-size="30" fill="navy" editable="simple">Select me</text>
+</svg>
+<p>Select the text above and drag selection to the blue box. Copy of selection should end up in the blue box once you drop it there.</p>
+<div
+ ondragenter="event.preventDefault()"
+ ondragover="return false"
+ ondrop="document.querySelector('div').appendChild(document.createTextNode(event.dataTransfer.getData('text/plain')))"
+/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/023.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/svg/023.xhtml
new file mode 100644
index 00000000000..3ada55cef67
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/023.xhtml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Dragging selection from SVG textArea to XHTML element</title>
+<style type="text/css">
+div[ondragenter]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body>
+<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="500px" height="100px" viewBox="0 0 500 100">
+<textArea x="10" y="10" width="480" height="90" font-size="20">Select part of this text and drag selection to the box below.
+Content of selection should be copied once it's dropped in the box.</textArea>
+</svg>
+<div
+ ondragenter="event.preventDefault()"
+ ondragover="return false"
+ ondrop="document.querySelector('div').appendChild(document.createTextNode(event.dataTransfer.getData('text/plain')))"
+/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/024.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/svg/024.xhtml
new file mode 100644
index 00000000000..58349cdcf6a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/024.xhtml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Dragging selection from SVG text element to contenteditable element</title>
+<style type="text/css">
+div[contenteditable]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body>
+<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="200px" height="50px" viewBox="0 0 200 50">
+<text x="10" y="45" font-size="30" fill="navy">Select me</text>
+</svg>
+<p>Select the text above and drag selection to the blue box. Copy of selection should end up in the blue box once you drop it there.</p>
+<div contenteditable="true"/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/025.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/svg/025.xhtml
new file mode 100644
index 00000000000..236e1655e6b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/025.xhtml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Dragging selection from SVG editable text element to contenteditable element</title>
+<style type="text/css">
+div[contenteditable]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body>
+<svg xmlns="http://www.w3.org/2000/svg" version="1.2" width="200px" height="50px" viewBox="0 0 200 50">
+<text x="10" y="45" font-size="30" fill="navy" editable="simple">Select me</text>
+</svg>
+<p>Select the text above and drag selection to the blue box. Copy of selection should end up in the blue box once you drop it there.</p>
+<div contenteditable="true"/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/026.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/svg/026.xhtml
new file mode 100644
index 00000000000..b387f0a00fe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/026.xhtml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Dragging selection from SVG textArea to contenteditable element</title>
+<style type="text/css">
+div[contenteditable]
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body>
+<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="500px" height="100px" viewBox="0 0 500 100">
+<textArea x="10" y="10" width="480" height="90" font-size="20">Select part of this text and drag selection to the box below.
+Content of selection should be copied once it's dropped in the box.</textArea>
+</svg>
+<div contenteditable="true"/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/027.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/svg/027.xhtml
new file mode 100644
index 00000000000..d122bae1994
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/027.xhtml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Dragging selection from SVG text element to XHTML textarea</title>
+<style type="text/css">
+textarea
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;}
+</style>
+</head>
+<body>
+<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="200px" height="50px" viewBox="0 0 200 50">
+<text x="10" y="45" font-size="30" fill="navy">Select me</text>
+</svg>
+<p>Select the text above and drag selection to the textarea. Copy of selection should end up in the textarea once you drop it there.</p>
+<p><textarea placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/028.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/svg/028.xhtml
new file mode 100644
index 00000000000..1d5437117c5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/028.xhtml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Dragging selection from SVG editable text element to XHTML textarea</title>
+<style type="text/css">
+textarea
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;}
+</style>
+</head>
+<body>
+<svg xmlns="http://www.w3.org/2000/svg" version="1.2" width="200px" height="50px" viewBox="0 0 200 50">
+<text x="10" y="45" font-size="30" fill="navy" editable="simple">Select me</text>
+</svg>
+<p>Select the text above and drag selection to the textarea. Copy of selection should end up in the textarea once you drop it there.</p>
+<p><textarea placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/029.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/svg/029.xhtml
new file mode 100644
index 00000000000..02e258e8519
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/029.xhtml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Dragging selection from SVG textArea to XHTML textarea</title>
+<style type="text/css">
+textarea
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;}
+</style>
+</head>
+<body>
+<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="500px" height="100px" viewBox="0 0 500 100">
+<textArea x="10" y="10" width="480" height="90" font-size="20">Select part of this text and drag selection to the box below.
+Content of selection should be copied once it's dropped in the box.</textArea>
+</svg>
+<p>Select the text above and drag selection to the textarea. Copy of selection should end up in the textarea once you drop it there.</p>
+<p><textarea placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/030-1.svg b/tests/wpt/web-platform-tests/html/editing/dnd/svg/030-1.svg
new file mode 100644
index 00000000000..62798a7e11d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/030-1.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="100px" viewBox="0 0 100 100">
+<circle cx="50" cy="50" r="50" fill="green"/>
+</svg>
+
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/030.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/svg/030.xhtml
new file mode 100644
index 00000000000..dd6f7fa22d5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/030.xhtml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>SVG image drag and drop</title>
+<style type="text/css">
+div[ondragenter]
+ {width:105px;
+ min-height:105px;
+ text-align:center;
+ margin-top:20px;
+ padding:10px;
+ border:solid thin navy;}
+p:first-child
+ {padding-left:12px;}
+</style>
+<script type="application/ecmascript">
+function addImage(event)
+ {var c = document.createElement('img');
+ c.setAttribute('src',event.dataTransfer.getData('text/uri-list'));
+ document.querySelector('div').appendChild(c);}
+</script>
+</head>
+<body>
+<p><img src="030-1.svg" alt="SVG circle" ondragstart="event.dataTransfer.effectAllowed = 'copy'"/></p>
+<p>Drag circle above to the box below. It should be copied to the box once you drop it there.</p>
+<div
+ ondragenter="event.preventDefault()"
+ ondragover="return false"
+ ondrop="addImage(event)"
+/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/031.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/svg/031.xhtml
new file mode 100644
index 00000000000..a21fdc0f638
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/031.xhtml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>SVG dataURL image drag and drop</title>
+<style type="text/css">
+div[ondragenter]
+ {width:105px;
+ min-height:105px;
+ text-align:center;
+ margin-top:20px;
+ padding:10px;
+ border:solid thin navy;}
+p:first-child
+ {padding-left:12px;}
+</style>
+<script type="application/ecmascript">
+function addImage(event)
+ {var c = document.createElement('img');
+ c.setAttribute('src',event.dataTransfer.getData('text/uri-list'));
+ document.querySelector('div').appendChild(c);}
+</script>
+</head>
+<body>
+<p><img src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20version%3D%221.1%22%20width%3D%22100px%22%20height%3D%22100px%22%20viewBox%3D%220%200%20100%20100%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22green%22/%3E%3C/svg%3E" alt="SVG circle" ondragstart="event.dataTransfer.effectAllowed = 'copy'"/></p>
+<p>Drag circle above to the box below. It should be copied to the box once you drop it there.</p>
+<div
+ ondragenter="event.preventDefault()"
+ ondragover="return false"
+ ondrop="addImage(event)"
+/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/032.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/svg/032.xhtml
new file mode 100644
index 00000000000..bdc6c990478
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/032.xhtml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Cross fragment drag and drop of SVG text selection from text element to textArea</title>
+<style type="text/css">
+textarea
+ {width:300px;
+ height:100px;}
+</style>
+</head>
+<body>
+<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="200px" height="50px" viewBox="0 0 200 50">
+<text x="10" y="45" font-size="30" fill="navy">Select me</text>
+</svg>
+<p>Drag selection above to the textarea below. Copy of selection should end up in the textarea once you drop it there.</p>
+<svg xmlns="http://www.w3.org/2000/svg" version="1.2" width="500px" height="300px" viewBox="0 0 500 300">
+<textArea x="10" y="10" width="480" height="280" font-size="20" editable="simple" pointer-events="boundingBox">Drop selection here</textArea>
+<rect x="10" y="10" width="480" height="280" stroke="black" stroke-width="1" fill="none"/>
+</svg>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/033.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/svg/033.xhtml
new file mode 100644
index 00000000000..1888875ab02
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/033.xhtml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Cross fragment drag and drop of SVG text selection from editable text element to textArea</title>
+<style type="text/css">
+textarea
+ {width:300px;
+ height:100px;}
+</style>
+</head>
+<body>
+<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="200px" height="50px" viewBox="0 0 200 50">
+<text x="10" y="45" font-size="30" fill="navy" editable="simple">Select me</text>
+</svg>
+<p>Drag selection above to the textarea below. Copy of selection should end up in the textarea once you drop it there.</p>
+<svg xmlns="http://www.w3.org/2000/svg" version="1.2" width="500px" height="300px" viewBox="0 0 500 300">
+<textArea x="10" y="10" width="480" height="280" font-size="20" editable="simple" pointer-events="boundingBox">Drop selection here</textArea>
+<rect x="10" y="10" width="480" height="280" stroke="black" stroke-width="1" fill="none"/>
+</svg>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/034.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/svg/034.xhtml
new file mode 100644
index 00000000000..0e9e4ea4440
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/034.xhtml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Cross fragment drag and drop of SVG text selection from textArea to editable text element</title>
+<style type="text/css">
+textarea
+ {width:300px;
+ height:100px;}
+</style>
+</head>
+<body>
+<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="500px" height="100px" viewBox="0 0 500 100">
+<textArea x="10" y="10" width="480" height="90" font-size="20">Select me.</textArea>
+</svg>
+<p>Drag selection above to the textarea below. Copy of selection should end up in the textarea once you drop it there.</p>
+<svg xmlns="http://www.w3.org/2000/svg" version="1.2" width="500px" height="300px" viewBox="0 0 500 300">
+<textArea x="10" y="10" width="480" height="280" font-size="20" editable="simple" pointer-events="boundingBox">Drop selection here</textArea>
+<rect x="10" y="10" width="480" height="280" stroke="black" stroke-width="1" fill="none"/>
+</svg>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/035.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/svg/035.xhtml
new file mode 100644
index 00000000000..a0dd437bd70
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/035.xhtml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Cross fragment drag and drop between SVG textAreas</title>
+<style type="text/css">
+textarea
+ {width:300px;
+ height:100px;}
+</style>
+</head>
+<body>
+<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="500px" height="100px" viewBox="0 0 500 100">
+<textArea x="10" y="10" width="480" height="90" font-size="20">Select me.</textArea>
+</svg>
+<p>Drag selection above to the textarea below. Copy of selection should end up in the textarea once you drop it there.</p>
+<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="400px" height="50px" viewBox="0 0 400 50">
+<text x="10" y="40" font-size="50" editable="simple">                        </text>
+<rect x="10" y="0" width="380" height="50" stroke="black" stroke-width="1" fill="none"/>
+</svg>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/036-1.svg b/tests/wpt/web-platform-tests/html/editing/dnd/svg/036-1.svg
new file mode 100644
index 00000000000..d16862da640
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/036-1.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="200px" height="50px" viewBox="0 0 200 50">
+<text x="10" y="45" font-size="30" fill="navy">Select me</text>
+</svg>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/036.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/svg/036.xhtml
new file mode 100644
index 00000000000..cb774b3ebcb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/036.xhtml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Dragging text selection between different SVG images</title>
+</head>
+<body>
+<p><object type="image/svg+xml" data="036-1.svg">SVG Image</object></p>
+<p>Drag selection above to the box below. Copy of selection should end up in the box once you drop it there.</p>
+<p><object type="image/svg+xml" data="helper-drop-selection-here-textArea.svg">SVG Image</object></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/037.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/svg/037.xhtml
new file mode 100644
index 00000000000..b97f99cc46e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/037.xhtml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Dragging text selection from dataURL image to another SVG image</title>
+</head>
+<body>
+<object type="image/svg+xml" data="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20version%3D%221.1%22%20width%3D%22200px%22%20height%3D%2250px%22%20viewBox%3D%220%200%20200%2050%22%3E%3Ctext%20x%3D%2210%22%20y%3D%2245%22%20font-size%3D%2230%22%20fill%3D%22navy%22%3ESelect%20me%3C/text%3E%3C/svg%3E">SVG Image</object>
+<p>Drag selection above to the box below. Copy of selection should end up in the box once you drop it there.</p>
+<p><object type="image/svg+xml" data="helper-drop-selection-here-textArea.svg">SVG Image</object></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/038.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/svg/038.xhtml
new file mode 100644
index 00000000000..c74b1db9ccb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/038.xhtml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Dragging text selection between different SVG dataURL images</title>
+</head>
+<body>
+<p><object type="image/svg+xml" data="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20version%3D%221.1%22%20width%3D%22200px%22%20height%3D%2250px%22%20viewBox%3D%220%200%20200%2050%22%3E%3Ctext%20x%3D%2210%22%20y%3D%2245%22%20font-size%3D%2230%22%20fill%3D%22navy%22%3ESelect%20me%3C/text%3E%3C/svg%3E">SVG Image</object></p>
+<p>Drag selection above to the box below. Copy of selection should end up in the box once you drop it there.</p>
+<p><object type="image/svg+xml" data="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20version%3D%221.2%22%20width%3D%22500px%22%20height%3D%22300px%22%20viewBox%3D%220%200%20500%20300%22%3E%3CtextArea%20x%3D%2210%22%20y%3D%2210%22%20width%3D%22480%22%20height%3D%22280%22%20font-size%3D%2220%22%20editable%3D%22simple%22%20pointer-events%3D%22boundingBox%22%3EDrop%20selection%20here%3C/textArea%3E%3Crect%20x%3D%2210%22%20y%3D%2210%22%20width%3D%22480%22%20height%3D%22280%22%20stroke%3D%22black%22%20stroke-width%3D%221%22%20fill%3D%22none%22/%3E%3C/svg%3E">SVG Image</object></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/039-1.svg b/tests/wpt/web-platform-tests/html/editing/dnd/svg/039-1.svg
new file mode 100644
index 00000000000..7023ddd9389
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/039-1.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="250px" height="50px" viewBox="0 0 250 50">
+<textArea x="10" y="10" width="200" height="50" font-size="20">Select me.</textArea>
+</svg> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/039.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/svg/039.xhtml
new file mode 100644
index 00000000000..77bc7e9c9dd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/039.xhtml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Dragging textArea selection between different SVG images</title>
+</head>
+<body>
+<p><object type="image/svg+xml" data="039-1.svg">SVG Image</object></p>
+<p>Drag selection above to the box below. Copy of selection should end up in the box once you drop it there.</p>
+<p><object type="image/svg+xml" data="helper-drop-selection-here-textArea.svg">SVG Image</object></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/040.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/svg/040.xhtml
new file mode 100644
index 00000000000..6069563a915
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/040.xhtml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Dragging textArea selection from dataURL image to another SVG image</title>
+</head>
+<body>
+<p><object type="image/svg+xml" data="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20version%3D%221.1%22%20width%3D%22250px%22%20height%3D%2250px%22%20viewBox%3D%220%200%20250%2050%22%3E%3CtextArea%20x%3D%2210%22%20y%3D%2210%22%20width%3D%22200%22%20height%3D%2250%22%20font-size%3D%2220%22%3ESelect%20me.%3C/textArea%3E%3C/svg%3E">SVG Image</object></p>
+<p>Drag selection above to the box below. Copy of selection should end up in the box once you drop it there.</p>
+<p><object type="image/svg+xml" data="helper-drop-selection-here-textArea.svg">SVG Image</object></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/041.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/svg/041.xhtml
new file mode 100644
index 00000000000..326bafe6395
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/041.xhtml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Dragging textArea selection between different SVG dataURL images</title>
+</head>
+<body>
+<p><object type="image/svg+xml" data="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20version%3D%221.1%22%20width%3D%22250px%22%20height%3D%2250px%22%20viewBox%3D%220%200%20250%2050%22%3E%3CtextArea%20x%3D%2210%22%20y%3D%2210%22%20width%3D%22200%22%20height%3D%2250%22%20font-size%3D%2220%22%3ESelect%20me.%3C/textArea%3E%3C/svg%3E">SVG Image</object></p>
+<p>Drag selection above to the box below. Copy of selection should end up in the box once you drop it there.</p>
+<p><object type="image/svg+xml" data="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20version%3D%221.2%22%20width%3D%22500px%22%20height%3D%22300px%22%20viewBox%3D%220%200%20500%20300%22%3E%3CtextArea%20x%3D%2210%22%20y%3D%2210%22%20width%3D%22480%22%20height%3D%22280%22%20font-size%3D%2220%22%20editable%3D%22simple%22%20pointer-events%3D%22boundingBox%22%3EDrop%20selection%20here%3C/textArea%3E%3Crect%20x%3D%2210%22%20y%3D%2210%22%20width%3D%22480%22%20height%3D%22280%22%20stroke%3D%22black%22%20stroke-width%3D%221%22%20fill%3D%22none%22/%3E%3C/svg%3E">SVG Image</object></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/042.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/svg/042.xhtml
new file mode 100644
index 00000000000..25d360fcb37
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/042.xhtml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop from downsized SVG image</title>
+<style type="text/css">
+object
+ {width:100px;
+ height:30px;}
+textarea
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;}
+</style>
+</head>
+<body>
+<p><object type="image/svg+xml" data="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20version%3D%221.1%22%20width%3D%22200px%22%20height%3D%2250px%22%20viewBox%3D%220%200%20200%2050%22%3E%3Ctext%20x%3D%2210%22%20y%3D%2245%22%20font-size%3D%2230%22%20fill%3D%22navy%22%3ESelect%20me%3C/text%3E%3C/svg%3E">SVG Image</object></p>
+<p>Select the text above and drag selection to the textarea. Copy of selection should end up in the textarea once you drop it there.</p>
+<p><textarea placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/043.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/svg/043.xhtml
new file mode 100644
index 00000000000..7144e0f7efe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/043.xhtml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop from enlarged SVG image</title>
+<style type="text/css">
+object
+ {width:300px;
+ height:75px;}
+textarea
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;}
+</style>
+</head>
+<body>
+<p><object type="image/svg+xml" data="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20version%3D%221.1%22%20width%3D%22200px%22%20height%3D%2250px%22%20viewBox%3D%220%200%20200%2050%22%3E%3Ctext%20x%3D%2210%22%20y%3D%2245%22%20font-size%3D%2230%22%20fill%3D%22navy%22%3ESelect%20me%3C/text%3E%3C/svg%3E">SVG Image</object></p>
+<p>Select the text above and drag selection to the textarea. Copy of selection should end up in the textarea once you drop it there.</p>
+<p><textarea placeholder="Drop selection here"/></p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/044.svg b/tests/wpt/web-platform-tests/html/editing/dnd/svg/044.svg
new file mode 100644
index 00000000000..6dfcb4d6639
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/044.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.2" width="500px" height="500px" viewBox="0 0 500 500">
+<title>Drag and drop of RTL SVG text selection from text element to textArea</title>
+<text x="10" y="30" font-size="20" fill="navy">&#x202E;FAIL|SSAP&#x202C;</text>
+<text x="10" y="60" font-size="20">Select text above and drag selection to</text>
+<text x="10" y="90" font-size="20">the box below. Content of selection should be</text>
+<text x="10" y="120" font-size="20">copies once it's dropped in the box.</text>
+<textArea x="10" y="130" width="480" height="360" font-size="20" editable="simple" pointer-events="boundingBox">Drop selection here</textArea>
+<rect x="10" y="130" width="480" height="360" stroke="black" stroke-width="1" fill="none"/>
+</svg> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/045.svg b/tests/wpt/web-platform-tests/html/editing/dnd/svg/045.svg
new file mode 100644
index 00000000000..00dee4564ce
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/045.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.2" width="500px" height="500px" viewBox="0 0 500 500">
+<title>Drag and drop of BiDi SVG text selection from text element to textArea</title>
+<text x="10" y="30" font-size="20" fill="navy">PASS|LIAF &#x202E;FAIL|SSAP&#x202C; PASS|LIAF</text>
+<text x="10" y="60" font-size="20">Select text above and drag selection to</text>
+<text x="10" y="90" font-size="20">the box below. Content of selection should be</text>
+<text x="10" y="120" font-size="20">copies once it's dropped in the box.</text>
+<textArea x="10" y="130" width="480" height="360" font-size="20" editable="simple" pointer-events="boundingBox">Drop selection here</textArea>
+<rect x="10" y="130" width="480" height="360" stroke="black" stroke-width="1" fill="none"/>
+</svg> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/046.svg b/tests/wpt/web-platform-tests/html/editing/dnd/svg/046.svg
new file mode 100644
index 00000000000..da9b03718e5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/046.svg
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.2" width="500px" height="500px" viewBox="0 0 500 500">
+<title>Drag and drop of BiDi SVG text selection from tspan elements to textArea</title>
+<text x="10" y="30" font-size="20" fill="navy">
+ <tspan>PASS|LIAF</tspan>
+ <tspan>&#x202E;FAIL|SSAP&#x202C;</tspan>
+ <tspan>PASS|LIAF</tspan>
+</text>
+<text x="10" y="60" font-size="20">Select text above and drag selection to</text>
+<text x="10" y="90" font-size="20">the box below. Content of selection should be</text>
+<text x="10" y="120" font-size="20">copies once it's dropped in the box.</text>
+<textArea x="10" y="130" width="480" height="360" font-size="20" editable="simple" pointer-events="boundingBox">Drop selection here</textArea>
+<rect x="10" y="130" width="480" height="360" stroke="black" stroke-width="1" fill="none"/>
+</svg> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/047.svg b/tests/wpt/web-platform-tests/html/editing/dnd/svg/047.svg
new file mode 100644
index 00000000000..f8f737c6d50
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/047.svg
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.2" width="500px" height="500px" viewBox="0 0 500 500">
+<title>Drag and drop of RTL SVG text selection from tref element to textArea</title>
+<defs>
+ <text id="text">&#x202E;FAIL|SSAP&#x202C;</text>
+ </defs>
+<text x="10" y="30" font-size="20" fill="navy"><tref xlink:href="#text"/></text>
+<text x="10" y="60" font-size="20">Select text above and drag selection to</text>
+<text x="10" y="90" font-size="20">the box below. Content of selection should be</text>
+<text x="10" y="120" font-size="20">copies once it's dropped in the box.</text>
+<textArea x="10" y="130" width="480" height="360" font-size="20" editable="simple" pointer-events="boundingBox">Drop selection here</textArea>
+<rect x="10" y="130" width="480" height="360" stroke="black" stroke-width="1" fill="none"/>
+</svg> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/048.svg b/tests/wpt/web-platform-tests/html/editing/dnd/svg/048.svg
new file mode 100644
index 00000000000..fb41bc991cb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/048.svg
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.2" width="500px" height="500px" viewBox="0 0 500 500">
+<title>Drag and drop of BiDi SVG text selection from tref element to textArea</title>
+<defs>
+ <text id="text">PASS|LIAF &#x202E;FAIL|SSAP&#x202C; PASS|LIAF</text>
+ </defs>
+<text x="10" y="30" font-size="20" fill="navy"><tref xlink:href="#text"/></text>
+<text x="10" y="60" font-size="20">Select text above and drag selection to</text>
+<text x="10" y="90" font-size="20">the box below. Content of selection should be</text>
+<text x="10" y="120" font-size="20">copies once it's dropped in the box.</text>
+<textArea x="10" y="130" width="480" height="360" font-size="20" editable="simple" pointer-events="boundingBox">Drop selection here</textArea>
+<rect x="10" y="130" width="480" height="360" stroke="black" stroke-width="1" fill="none"/>
+</svg> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/049.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/svg/049.xhtml
new file mode 100644
index 00000000000..155f75533b0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/049.xhtml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selecting text in SVG text element inside draggable container</title>
+</head>
+<body>
+<div draggable="true">
+ <svg xmlns="http://www.w3.org/2000/svg" version="1.2" width="200px" height="50px" viewBox="0 0 200 50">
+ <text x="10" y="45" font-size="30" fill="navy" editable="simple">Select me</text>
+ </svg>
+</div>
+<p>You should be able to select text above</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/050.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/svg/050.xhtml
new file mode 100644
index 00000000000..56fef670f48
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/050.xhtml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Selecting text in SVG textArea element inside draggable container</title>
+</head>
+<body>
+<div draggable="true">
+ <svg xmlns="http://www.w3.org/2000/svg" version="1.2" width="500px" height="100px" viewBox="0 0 500 100">
+ <textArea x="10" y="10" width="480" height="90" font-size="20" editable="simple">You should be able to select this text</textArea>
+ </svg>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/051.xhtml b/tests/wpt/web-platform-tests/html/editing/dnd/svg/051.xhtml
new file mode 100644
index 00000000000..2cb65636172
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/051.xhtml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Drag and drop of link from SVG fragment to XHTML</title>
+<style type="text/css">
+div
+ {width:300px;
+ height:100px;
+ margin-top:20px;
+ padding:10px;
+ color:white;
+ background-color:navy;}
+</style>
+</head>
+<body>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="200px" height="50px" viewBox="0 0 200 50">
+ <a xlink:href="data:text/plain,PASS">
+ <text x="10" y="45" font-size="30" fill="navy">Drag me</text>
+ </a>
+</svg>
+<p>Drag link to the blue box. You should see word PASS once you drop it there.</p>
+<div dropzone="copy string:text/uri-list" ondrop="document.querySelector('div').appendChild(document.createTextNode(event.dataTransfer.getData('text/uri-list').substring(16)))"/>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/052.svg b/tests/wpt/web-platform-tests/html/editing/dnd/svg/052.svg
new file mode 100644
index 00000000000..f559b234a39
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/052.svg
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="500px" height="500px" viewBox="0 0 500 500">
+<title>Drag and drop of text link inside SVG</title>
+<a xlink:href="data:text/plain,PASS">
+ <text x="10" y="50" font-size="30" fill="navy">Drag me</text>
+</a>
+<textArea x="10" y="70" width="480" height="170" font-size="30">Drag link above and drop it in the gray box below. You should see word PASS once you drop it.</textArea>
+<rect x="10" y="300" width="480" height="190" fill="gray"/>
+<script type="application/ecmascript">
+var a = document.querySelector('a'), rect = document.querySelector('rect'), text = document.querySelector('textArea');
+a.addEventListener('dragstart',
+function (event)
+ {event.dataTransfer.effectAllowed = 'copy'}
+,false);
+rect.addEventListener('dragenter',
+function (event)
+ {event.preventDefault()}
+,false);
+rect.addEventListener('dragover',
+function (event)
+ {event.preventDefault()}
+,false);
+rect.addEventListener('drop',
+function (event)
+ {text.firstChild.nodeValue = event.dataTransfer.getData('text/uri-list').substring(16,20)}
+,false);
+</script>
+</svg>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/053.svg b/tests/wpt/web-platform-tests/html/editing/dnd/svg/053.svg
new file mode 100644
index 00000000000..a116f63a188
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/053.svg
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="500px" height="500px" viewBox="0 0 500 500">
+<title>Drag and drop of circle link inside SVG</title>
+<a xlink:href="data:text/plain,PASS">
+ <circle cx="50" cy="50" r="50" fill="green"/>
+</a>
+<textArea x="10" y="100" width="480" height="200" font-size="30">Drag green circle above and drop it in the gray box below. Gray box should turn green once you drop it.</textArea>
+<rect x="10" y="300" width="480" height="190" fill="gray"/>
+<script type="application/ecmascript">
+var a = document.querySelector('a'), rect = document.querySelector('rect');
+a.addEventListener('dragstart',
+function (event)
+ {event.dataTransfer.effectAllowed = 'copy'}
+,false);
+rect.addEventListener('dragenter',
+function (event)
+ {event.preventDefault()}
+,false);
+rect.addEventListener('dragover',
+function (event)
+ {event.preventDefault()}
+,false);
+rect.addEventListener('drop',
+function (event)
+ {if(event.dataTransfer.getData('text/uri-list').replace(/\r\n$/,'') == 'data:text/plain,PASS')
+ {rect.setAttribute('fill','green');}
+ }
+,false);
+</script>
+</svg>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/054.svg b/tests/wpt/web-platform-tests/html/editing/dnd/svg/054.svg
new file mode 100644
index 00000000000..8029734cd83
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/054.svg
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="500px" height="500px" viewBox="0 0 500 500">
+<title>Drag and drop of animated circle link inside SVG</title>
+<a xlink:href="data:text/plain,PASS">
+ <circle cx="50" cy="50" r="10" fill="green">
+ <animate attributeName="r" to="50" dur="10s" begin="0s" fill="freeze"/>
+ </circle>
+</a>
+<textArea x="10" y="100" width="480" height="200" font-size="30">
+Drag green circle above and drop it in the gray box below.
+Size of feedback image should match size of circle
+and gray box should turn green.</textArea>
+<rect x="10" y="300" width="480" height="190" fill="gray"/>
+<script type="application/ecmascript">
+var a = document.querySelector('a'), rect = document.querySelector('rect');
+a.addEventListener('dragstart',
+function (event)
+ {event.dataTransfer.effectAllowed = 'copy'}
+,false);
+rect.addEventListener('dragenter',
+function (event)
+ {event.preventDefault()}
+,false);
+rect.addEventListener('dragover',
+function (event)
+ {event.preventDefault()}
+,false);
+rect.addEventListener('drop',
+function (event)
+ {if(event.dataTransfer.getData('text/uri-list').replace(/\r\n$/,'') == 'data:text/plain,PASS')
+ {rect.setAttribute('fill','green');}
+ }
+,false);
+</script>
+</svg>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/055.svg b/tests/wpt/web-platform-tests/html/editing/dnd/svg/055.svg
new file mode 100644
index 00000000000..d23ca5f90c2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/055.svg
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="500px" height="500px" viewBox="0 0 500 500">
+<title>Selection and drag and drop of link inside SVG</title>
+<a xlink:href="data:text/plain,PASS">
+ <rect x="10" y="10" width="80" height="80" fill="green"/>
+</a>
+<textArea x="10" y="100" width="480" height="200" font-size="30">Select part of this text. Once text is selected drag green square above and drop it in the gray box below. Gray box should turn green.</textArea>
+<rect x="10" y="300" width="480" height="190" fill="gray"/>
+<script type="application/ecmascript">
+var a = document.querySelector('a'), rect = document.querySelector('svg > rect');
+a.addEventListener('dragstart',
+function (event)
+ {event.dataTransfer.effectAllowed = 'copy'}
+,false);
+rect.addEventListener('dragenter',
+function (event)
+ {event.preventDefault()}
+,false);
+rect.addEventListener('dragover',
+function (event)
+ {event.preventDefault()}
+,false);
+rect.addEventListener('drop',
+function (event)
+ {if(event.dataTransfer.getData('text/uri-list').replace(/\r\n$/,'') == 'data:text/plain,PASS')
+ {rect.setAttribute('fill','green');}
+ }
+,false);
+</script>
+</svg>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/056.svg b/tests/wpt/web-platform-tests/html/editing/dnd/svg/056.svg
new file mode 100644
index 00000000000..ff2bab82d7f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/056.svg
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="500px" height="500px" viewBox="0 0 500 500">
+<title>dataTransfer.setData/getData during SVG link drag and drop</title>
+<a xlink:href="data:text/plain,PASS">
+ <polygon points="0,0 100,0 0,100" fill="green"/>
+</a>
+<textArea x="10" y="100" width="480" height="200" font-size="15">Drag green triangle above and drop it in the gray box below. Gray box should turn green.</textArea>
+<rect x="10" y="300" width="480" height="190" fill="gray"/>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text/uri-list', 'text/plain', 'application/xml', 'application/xhtml+xml', 'application/mathml+xml', 'image/svg+xml', 'text/html', 'text/x-example'],
+data = ['data:text/plain,PASS', 'PASS', '<result>PASS</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>PASS</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">PASS</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>PASS</p></body></html>', 'PASS'],
+a = document.querySelector('a'), rect = document.querySelector('rect'), text = document.querySelector('textArea'), result = true;
+a.addEventListener('dragstart',
+ function (event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], data[i]);}
+ if(event.dataTransfer.items.length < dataTypes.length)
+ {say('items.length (dragstart) : FAIL');}
+ },false);
+a.addEventListener('drag',
+ function (event)
+ {for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during drag)')}
+ }
+ if(event.dataTransfer.items.length < dataTypes.length)
+ {say('items.length (dragover) : FAIL')}
+ },false);
+rect.addEventListener('dragenter',
+ function (event)
+ {event.preventDefault();
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during dragenter)')}
+ }
+ if(event.dataTransfer.items.length < dataTypes.length)
+ {say('items.length (dragenter) : FAIL')}
+ },false);
+rect.addEventListener('dragover',
+ function (event)
+ {event.preventDefault();
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], 'FAIL');
+ if(event.dataTransfer.getData(dataTypes[i]))
+ {say('getData(' + dataTypes[i] + ') : FAIL (data store should not be readable during dragover)')}
+ }
+ if(event.dataTransfer.items.length < dataTypes.length)
+ {say('items.length (dragover) : FAIL');}
+ },false);
+rect.addEventListener('drop',
+ function (event)
+ {if(event.dataTransfer.items.length < dataTypes.length)
+ {say('items.length (drop) : FAIL');}
+ for(var i = 0; i != dataTypes.length; i++)
+ {if(event.dataTransfer.getData(dataTypes[i]) != data[i])
+ {say('getData(' + dataTypes[i] + ') : FAIL');}
+ }
+ rect.setAttribute('fill',result?'green':'red');
+ },false);
+function say(it)
+ {text.appendChild(document.createTextNode(it + '.'));
+ result = false;}
+]]>
+</script>
+</svg>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/057.svg b/tests/wpt/web-platform-tests/html/editing/dnd/svg/057.svg
new file mode 100644
index 00000000000..709521beac4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/057.svg
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="500px" height="500px" viewBox="0 0 500 500">
+<title>dataTransfer.items during SVG link drag and drop</title>
+<a xlink:href="data:text/plain,PASS">
+ <polygon points="0,0 100,0 100,100" fill="green"/>
+</a>
+<textArea x="10" y="100" width="480" height="200" font-size="15">Drag green triangle above and drop it in the gray box below. Gray box should turn green.</textArea>
+<rect x="10" y="300" width="480" height="190" fill="gray"/>
+<script type="application/ecmascript">
+<![CDATA[
+var dataTypes = ['text/uri-list', 'text/plain', 'application/xml', 'application/xhtml+xml', 'application/mathml+xml', 'image/svg+xml', 'text/html', 'text/x-example'],
+data = ['data:text/plain,PASS', 'PASS', '<result>PASS</result>', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Data store item</title></head><body><p>PASS</p></body></html>', '<math xmlns="http://www.w3.org/1998/Math/MathML"><mn>1</mn></math>', '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="50px" viewBox="0 0 100 50"><text x="0" y="40" font-size="40" fill="green">PASS</text></svg>', '<!DOCTYPE html><html><head><title>Data store item</title></head><body><p>PASS</p></body></html>', 'PASS'],
+a = document.querySelector('a'), rect = document.querySelector('rect'), text = document.querySelector('textArea'), e = 0, result = true;
+a.addEventListener('dragstart',
+ function (event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ for(var i = 0; i != dataTypes.length; i++)
+ {event.dataTransfer.setData(dataTypes[i], data[i]);}
+ for(var i = event.dataTransfer.items.length; i != 0; i--)
+ {if(dataTypes.indexOf(event.dataTransfer.items[i-1].type) == -1)
+ {delete event.dataTransfer.items[i-1]}
+ }
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragstart) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragstart): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragstart): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0] != data[e++])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should pass' + data[e] + ')')}
+ }
+ );
+ }
+ },false);
+a.addEventListener('drag',
+ function (event)
+ {event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondrag) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondrag): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondrag): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to drag event handler)')}
+ }
+ );
+ }
+ },false);
+rect.addEventListener('dragenter',
+ function (event)
+ {event.preventDefault();
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragenter) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {delete event.dataTransfer.items[i];
+ if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragenter): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragenter): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to drag event handler)')}
+ }
+ );
+ }
+ },false);
+rect.addEventListener('dragover',
+ function (event)
+ {event.preventDefault();
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondragover) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondragover): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondragover): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should not reveal data to dragover event handler)')}
+ }
+ );
+ }
+ },false);
+rect.addEventListener('drop',
+ function (event)
+ {e = 0;
+ event.dataTransfer.items.clear();
+ if(event.dataTransfer.items.length != dataTypes.length)
+ {say('items.length (ondrop) : FAIL (items.length should be' + dataTypes.length + ')')}
+ for(var i = 0; i != event.dataTransfer.items.length; i++)
+ {delete event.dataTransfer.items[i];
+ if(event.dataTransfer.items[i].kind != 'string')
+ {say('Item kind (ondrop): FAIL (items[' + i + '].kind should be string)')}
+ if(event.dataTransfer.items[i].type != dataTypes[i])
+ {say('Item type (ondrop): FAIL (items[' + i + '].type should be' + dataTypes[i] + ')')}
+ event.dataTransfer.items[i].getAsString(
+ function ()
+ {if(arguments[0] != data[e++])
+ {say('getAsString : FAIL (items[' + i + '].getAsString should pass' + data[e] + ')')}
+ }
+ );
+ }
+ rect.setAttribute('fill',result?'green':'red');
+ },false);
+function say(it)
+ {text.appendChild(document.createTextNode(it + '.'));
+ result = false;}
+]]>
+</script>
+</svg>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/058.svg b/tests/wpt/web-platform-tests/html/editing/dnd/svg/058.svg
new file mode 100644
index 00000000000..f27626f66cf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/058.svg
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="500px" height="500px" viewBox="0 0 500 500">
+<title>SVG link drag and drop: allowed effects 'copy','move','link' and 'none'</title>
+<a xlink:href="data:text/plain,1">
+ <circle cx="50" cy="50" r="40" fill="green"/>
+</a>
+<textArea x="10" y="100" width="480" height="200" font-size="30">You should be able to drag green circle and drop it onto any of the boxes below. Choosen box should turn green once circle is dropped on it.</textArea>
+<rect x="10" y="300" width="100" height="100" fill="silver"/>
+<rect x="120" y="300" width="100" height="100" fill="gray"/>
+<rect x="230" y="300" width="100" height="100" fill="gray"/>
+<rect x="340" y="300" width="100" height="100" fill="black"/>
+<script type="application/ecmascript">
+var a = document.querySelector('a'), rect = document.querySelectorAll('rect'),
+effects = ['copy','move','link','all'], e = 0;
+a.addEventListener('dragstart',
+function (event)
+ {event.dataTransfer.effectAllowed = effects[e]}
+,false);
+for(var i = 0; i != rect.length; i++)
+ {rect[i].addEventListener('dragenter',
+ function (event)
+ {event.preventDefault();
+ event.dataTransfer.effectAllowed = effects[e];}
+ ,false);
+ rect[i].addEventListener('dragover',
+ function (event)
+ {event.preventDefault()}
+ ,false);
+ rect[i].addEventListener('drop',
+ function (event)
+ {if(event.dataTransfer.dropEffect == effects[e] &amp;&amp; event.dataTransfer.effectAllowed == effects[e] &amp;&amp; i != 3)
+ {event.target.setAttribute('fill','green');}
+ e = (e+1)%3;}
+ ,false);}
+</script>
+</svg>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/059-1.svg b/tests/wpt/web-platform-tests/html/editing/dnd/svg/059-1.svg
new file mode 100644
index 00000000000..634620a2fe0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/059-1.svg
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="500px" height="500px" viewBox="0 0 500 500">
+<title>SVG link drag and drop: helper file</title>
+<textArea x="10" y="10" width="480" height="200" font-size="30">Drop circle onto gray box below. Box should turn green once circle is dropped.</textArea>
+<rect x="10" y="220" width="480" height="270" fill="gray"/>
+<script type="application/ecmascript">
+var rect = document.querySelector('rect');
+rect.addEventListener('dragenter',
+function (event)
+ {event.preventDefault();}
+,false);
+rect.addEventListener('dragover',
+function (event)
+ {event.preventDefault();}
+,false);
+rect.addEventListener('drop',
+function (event)
+ {rect.setAttribute('fill',(event.dataTransfer.getData('text/uri-list').replace(/\r\n$/,'') == 'data:text/plain,1')?'green':'red');}
+,false);
+</script>
+</svg>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/059.svg b/tests/wpt/web-platform-tests/html/editing/dnd/svg/059.svg
new file mode 100644
index 00000000000..a289804e63d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/059.svg
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="500px" height="500px" viewBox="0 0 500 500">
+<title>SVG link cross page drag and drop</title>
+<a xlink:href="data:text/plain,1">
+ <circle cx="50" cy="50" r="40" fill="green"/>
+</a>
+<textArea x="10" y="100" width="480" height="200" font-size="30">Drag circle above. You should be redirected to the new page and be able to drop it there.</textArea>
+<script type="application/ecmascript">
+document.querySelector('a').addEventListener('dragstart',
+function (event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ window.location = '059-1.svg'}
+,false);
+</script>
+</svg>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/060-1.svg b/tests/wpt/web-platform-tests/html/editing/dnd/svg/060-1.svg
new file mode 100644
index 00000000000..b78e04b2112
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/060-1.svg
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="500px" height="500px" viewBox="0 0 500 500">
+<title>SVG link drag and drop: helper file</title>
+<textArea x="10" y="10" width="480" height="200" font-size="30">Drag circle over arrow below but don't drop it yet. You should be returned back to start page.</textArea>
+<polygon points="10,400 100,300 100,350 480,350 480,450 100,450 100,500 10,400" fill="navy"/>
+<script type="application/ecmascript">
+document.querySelector('polygon').addEventListener('dragenter',
+function (event)
+ {window.location = '060.svg'}
+,false);
+</script>
+</svg>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/060.svg b/tests/wpt/web-platform-tests/html/editing/dnd/svg/060.svg
new file mode 100644
index 00000000000..da3efcc4954
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/060.svg
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="500px" height="500px" viewBox="0 0 500 500">
+<title>SVG link drag and drop and history navigation roundtrip</title>
+<a xlink:href="data:text/plain,1">
+ <circle cx="50" cy="50" r="40" fill="green"/>
+</a>
+<textArea x="10" y="100" width="480" height="200" font-size="30">Drag circle above. You will be redirected to new page. When you return back drop circle on itself. You should see word PASS once you drop it.</textArea>
+<script type="application/ecmascript">
+var a = document.querySelector('a');
+a.addEventListener('dragstart',
+function (event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ window.location = '060-1.svg'}
+,false);
+a.addEventListener('dragenter',
+function (event)
+ {event.preventDefault();}
+,false);
+a.addEventListener('dragover',
+function (event)
+ {event.preventDefault();}
+,false);
+a.addEventListener('drop',
+function (event)
+ {document.querySelector('textArea').firstChild.nodeValue = (event.dataTransfer.getData('text/uri-list').replace(/\r\n$/,'') == 'data:text/plain,1')?'PASS':'FAIL';}
+,false);
+</script>
+</svg>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/061.svg b/tests/wpt/web-platform-tests/html/editing/dnd/svg/061.svg
new file mode 100644
index 00000000000..17f8734358d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/061.svg
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="500px" height="500px" viewBox="0 0 500 500">
+<title>SVG link drag and drop roundtrip</title>
+<a xlink:href="data:text/plain,1">
+ <circle cx="50" cy="50" r="40" fill="green"/>
+</a>
+<textArea x="10" y="100" width="480" height="200" font-size="30">Drag circle outside browser window and then drag it back and drop on itself. You should see word PASS once you drop it.</textArea>
+<script type="application/ecmascript">
+var a = document.querySelector('a');
+a.addEventListener('dragstart',
+function (event)
+ {event.dataTransfer.effectAllowed = 'copy';}
+,false);
+a.addEventListener('dragenter',
+function (event)
+ {event.preventDefault();}
+,false);
+a.addEventListener('dragover',
+function (event)
+ {event.preventDefault();}
+,false);
+a.addEventListener('drop',
+function (event)
+ {document.querySelector('textArea').firstChild.nodeValue = (event.dataTransfer.getData('text/uri-list').replace(/\r\n$/,'') == 'data:text/plain,1')?'PASS':'FAIL';}
+,false);
+</script>
+</svg>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/062.svg b/tests/wpt/web-platform-tests/html/editing/dnd/svg/062.svg
new file mode 100644
index 00000000000..0bc8477e5a6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/062.svg
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="500px" height="500px" viewBox="0 0 500 500">
+<title>Setting drag image during drag and drop of SVG link</title>
+<a xlink:href="data:text/plain,1">
+ <circle cx="60" cy="60" r="50" fill="gray"/>
+</a>
+<textArea x="10" y="200" width="480" height="200" font-size="30">Try to drag circle. Drag feedback should look like green rectangle.</textArea>
+<rect x="300" y="10" width="100" height="100" fill="green"/>
+<script type="application/ecmascript">
+var a = document.querySelector('a'), rect = document.querySelector('rect');
+a.addEventListener('dragstart',
+function (event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ event.dataTransfer.setDragImage(document.querySelector('rect'), 50, 50);}
+,false);
+</script>
+</svg> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/063.svg b/tests/wpt/web-platform-tests/html/editing/dnd/svg/063.svg
new file mode 100644
index 00000000000..eda15495f41
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/063.svg
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="500px" height="500px" viewBox="0 0 500 500">
+<title>Adding element to datastore while dragging SVG links</title>
+<a xlink:href="data:text/plain,1">
+ <rect x="10" y="10" width="100" height="100" fill="green"/>
+</a>
+<a xlink:href="data:text/plain,2">
+ <rect x="300" y="10" width="100" height="100" fill="teal"/>
+</a>
+<textArea x="10" y="200" width="480" height="200" font-size="30">Try to drag one of boxes above. Drag feedback should include both boxes.</textArea>
+<script type="application/ecmascript">
+var a = document.querySelectorAll('a');
+a[0].addEventListener('dragstart',
+function (event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ event.dataTransfer.addElement(document.querySelectorAll('rect')[1]);}
+,false);
+a[1].addEventListener('dragstart',
+function (event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ event.dataTransfer.addElement(document.querySelectorAll('rect')[0]);}
+,false);
+</script>
+</svg> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/064.svg b/tests/wpt/web-platform-tests/html/editing/dnd/svg/064.svg
new file mode 100644
index 00000000000..913732360c8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/064.svg
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="500px" height="500px" viewBox="0 0 500 500">
+<title>Drag and drop of overlapping SVG links</title>
+<a xlink:href="data:text/plain,1">
+ <rect x="10" y="10" width="100" height="100" fill="silver"/>
+</a>
+<a xlink:href="data:text/plain,2">
+ <rect x="10" y="10" width="100" height="100" fill="gray"/>
+</a>
+ <rect x="160" y="10" width="100" height="100" fill="green"/>
+ <rect x="310" y="10" width="100" height="100" fill="maroon"/>
+<textArea x="10" y="200" width="480" height="200" font-size="30">Try to drag gray boxe above. Drag feedback should be green, not red.</textArea>
+<script type="application/ecmascript">
+var a = document.querySelectorAll('a');
+a[0].addEventListener('dragstart',
+function (event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ event.dataTransfer.setDragImage(document.querySelectorAll('rect')[3], 50, 50);}
+,false);
+a[1].addEventListener('dragstart',
+function (event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ event.dataTransfer.setDragImage(document.querySelectorAll('rect')[2], 50, 50);}
+,false);
+</script>
+</svg> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/065.svg b/tests/wpt/web-platform-tests/html/editing/dnd/svg/065.svg
new file mode 100644
index 00000000000..38cb9560ddf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/065.svg
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="500px" height="500px" viewBox="0 0 500 500">
+<title>Reload during SVG link drag and drop roundtrip</title>
+<a xlink:href="data:text/plain,1">
+ <circle cx="50" cy="50" r="40" fill="green"/>
+</a>
+<textArea x="10" y="100" width="480" height="200" font-size="30">Drag circle around page and then drag it back and drop on itself. You should see word PASS once you drop it.</textArea>
+<script type="application/ecmascript">
+var a = document.querySelector('a');
+a.addEventListener('dragstart',
+function (event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ window.location.reload()}
+,false);
+a.addEventListener('dragenter',
+function (event)
+ {event.preventDefault();}
+,false);
+a.addEventListener('dragover',
+function (event)
+ {event.preventDefault();}
+,false);
+a.addEventListener('drop',
+function (event)
+ {document.querySelector('textArea').firstChild.nodeValue = (event.dataTransfer.getData('text/uri-list').replace(/\r\n$/,'') == 'data:text/plain,1')?'PASS':'FAIL';}
+,false);
+</script>
+</svg>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/066.svg b/tests/wpt/web-platform-tests/html/editing/dnd/svg/066.svg
new file mode 100644
index 00000000000..1020ec82c80
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/066.svg
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="500px" height="500px" viewBox="0 0 500 500">
+<title>Removing dragged element during drag and drop of SVG link</title>
+<a xlink:href="data:text/plain,1">
+ <circle cx="50" cy="50" r="50" fill="green"/>
+</a>
+<textArea x="10" y="100" width="480" height="200" font-size="30">Drag green circle above and drop it in the gray box below. Gray box should turn green once you drop it.</textArea>
+<rect x="10" y="300" width="480" height="190" fill="gray"/>
+<script type="application/ecmascript">
+var a = document.querySelector('a'), rect = document.querySelector('rect');
+a.addEventListener('dragstart',
+function (event)
+ {event.dataTransfer.effectAllowed = 'copy';
+ document.documentElement.removeChild(a);}
+,false);
+rect.addEventListener('dragenter',
+function (event)
+ {event.preventDefault()}
+,false);
+rect.addEventListener('dragover',
+function (event)
+ {event.preventDefault()}
+,false);
+rect.addEventListener('drop',
+function (event)
+ {if(event.dataTransfer.getData('text/uri-list').replace(/\r\n$/,'') == 'data:text/plain,1')
+ {rect.setAttribute('fill','green');}
+ }
+,false);
+</script>
+</svg>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/067.svg b/tests/wpt/web-platform-tests/html/editing/dnd/svg/067.svg
new file mode 100644
index 00000000000..ba1e5011f2f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/067.svg
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="500px" height="500px" viewBox="0 0 500 500">
+<title>Drag and drop of SVG links</title>
+<a xlink:href="data:text/plain,olive">
+ <circle cx="50" cy="50" r="50" fill="olive"/>
+</a>
+<a xlink:href="data:text/plain,green">
+ <circle cx="200" cy="50" r="50" fill="green"/>
+</a>
+<a xlink:href="data:text/plain,teal">
+ <circle cx="350" cy="50" r="50" fill="teal"/>
+</a>
+<textArea x="10" y="120" width="480" height="200" font-size="30">Drag one of green circles above and drop it in the gray box below. Gray box should turn green.</textArea>
+<rect x="10" y="300" width="480" height="190" fill="gray"/>
+<script type="application/ecmascript">
+var a = document.querySelectorAll('a'), rect = document.querySelector('rect');
+for(var i = 0; i != a.length; i++)
+ {a[i].addEventListener('dragstart',
+ function (event)
+ {event.dataTransfer.effectAllowed = 'copy';}
+ ,false);}
+rect.addEventListener('dragenter',
+function (event)
+ {event.preventDefault()}
+,false);
+rect.addEventListener('dragover',
+function (event)
+ {event.preventDefault()}
+,false);
+rect.addEventListener('drop',
+function (event)
+ {rect.setAttribute('fill',event.dataTransfer.getData('text/uri-list').substr(16).replace(/\r\n$/,''));}
+,false);
+</script>
+</svg>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/svg/helper-drop-selection-here-textArea.svg b/tests/wpt/web-platform-tests/html/editing/dnd/svg/helper-drop-selection-here-textArea.svg
new file mode 100644
index 00000000000..783c164eb22
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/svg/helper-drop-selection-here-textArea.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" version="1.2" width="500px" height="300px" viewBox="0 0 500 300">
+<textArea x="10" y="10" width="480" height="280" font-size="20" editable="simple" pointer-events="boundingBox">Drop selection here</textArea>
+<rect x="10" y="10" width="480" height="280" stroke="black" stroke-width="1" fill="none"/>
+</svg> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/synthetic/001.html b/tests/wpt/web-platform-tests/html/editing/dnd/synthetic/001.html
new file mode 100644
index 00000000000..bcc38e0e72c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/synthetic/001.html
@@ -0,0 +1,120 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Synthetic drag events</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script type="text/javascript">
+test(function() {
+ assert_own_property(window,'DragEvent');
+}, 'window.DragEvent should be exposed' );
+test(function() {
+ assert_throws('NOT_SUPPORTED_ERR', function() {
+ var evt = document.createEvent('DragEvent');
+ });
+}, 'createEvent should not be able to create a DragEvent' );
+test(function() {
+ var evt = new DragEvent('dragstart');
+ assert_false( !!evt.initDragEvent, 'initDragEvent' );
+ assert_true( !!evt.initMouseEvent, 'initMouseEvent' );
+ assert_true( !!evt.initUIEvent, 'initUIEvent' );
+ assert_true( !!evt.initEvent, 'initEvent' );
+}, 'DragEvent should have all of the inherited init*Event methods' );
+
+//cannot test non-synthetic dataTransfer objects as the param here because that needs a real DragEvent to create a proper one with global storage
+//will be tested in another file
+test(function() {
+ var evt = new DragEvent('dragstart');
+ evt.initMouseEvent('dragstart', true, true, window, 1, 0, 0, 0, 0, false, false, false, false, 1, document.body);
+}, 'initMouseEvent should not throw' );
+test(function() {
+ var evt = new DragEvent('dragstart');
+ evt.initUIEvent('dragstart', true, true, window, 1);
+}, 'initUIEvent should not throw' );
+test(function() {
+ var evt = new DragEvent('dragstart');
+ evt.initEvent('dragstart', true, true);
+}, 'initEvent should not throw' );
+
+test(function() {
+ var evt = new DragEvent('dragstart', {dataTransfer:null}), div = document.createElement('div'), ranlistener = false;
+ div.ondragstart = function () { ranlistener = true; };
+ div.dispatchEvent(evt);
+ assert_true(ranlistener);
+}, 'DragEvent constructor with null as the dataTransfer parameter should be able to fire the event' );
+test(function() {
+ var evt = new DragEvent('dragstart', {dataTransfer:undefined}), div = document.createElement('div'), ranlistener = false;
+ div.ondragstart = function () { ranlistener = true; };
+ div.dispatchEvent(evt);
+ assert_true(ranlistener);
+}, 'DragEvent constructor with undefined as the dataTransfer parameter should be able to fire the event' );
+test(function() {
+ assert_throws(new TypeError(), function() {
+ var evt = new DragEvent('dragstart', {dataTransfer:{}});
+ });
+}, 'DragEvent constructor with custom object as the dataTransfer parameter should throw TypeError' );
+test(function() {
+ var evt = new DragEvent('dragstart'), div = document.createElement('div'), ranlistener = false;
+ div.ondragstart = function () { ranlistener = true; };
+ evt.initMouseEvent('dragstart', true, true, window, 1, 0, 0, 0, 0, false, false, false, false, 1, document.body);
+ div.dispatchEvent(evt);
+ assert_true(ranlistener);
+}, 'initMouseEvent should be able to fire the event' );
+test(function() {
+ var evt = new DragEvent('dragstart'), div = document.createElement('div'), ranlistener = false;
+ div.ondragstart = function () { ranlistener = true; };
+ evt.initUIEvent('dragstart', true, true, window, 1);
+ div.dispatchEvent(evt);
+ assert_true(ranlistener);
+}, 'initUIEvent should be able to fire the event' );
+test(function() {
+ var evt = new DragEvent('dragstart'), div = document.createElement('div'), ranlistener = false;
+ div.ondragstart = function () { ranlistener = true; };
+ evt.initEvent('dragstart', true, true);
+ div.dispatchEvent(evt);
+ assert_true(ranlistener);
+}, 'initEvent should be able to fire the event' );
+
+test(function() {
+ var evt = new DragEvent('dragstart', {dataTransfer:null}), div = document.createElement('div'), dTrans = 'fail';
+ div.ondragstart = function (e) { dTrans = e.dataTransfer };
+ div.dispatchEvent(evt);
+ assert_equals(dTrans,null);
+}, 'DragEvent constructor with null as the dataTransfer parameter should give null as the dataTransfer' );
+test(function() {
+ var evt = new DragEvent('dragstart', {dataTransfer:undefined}), div = document.createElement('div'), dTrans = 'fail';
+ div.ondragstart = function (e) { dTrans = e.dataTransfer };
+ div.dispatchEvent(evt);
+ assert_equals(dTrans,null);
+}, 'DragEvent constructor with undefined as the dataTransfer parameter should give null as the dataTransfer' );
+test(function() {
+ var evt = new DragEvent('dragstart'), div = document.createElement('div'), dTrans = 'fail';
+ div.ondragstart = function (e) { dTrans = e.dataTransfer };
+ evt.initMouseEvent('dragstart', true, true, window, 1, 0, 0, 0, 0, false, false, false, false, 1, document.body);
+ div.dispatchEvent(evt);
+ assert_equals(dTrans,null);
+}, 'initMouseEvent should give null as the dataTransfer' );
+test(function() {
+ var evt = new DragEvent('dragstart'), div = document.createElement('div'), dTrans = 'fail';
+ div.ondragstart = function (e) { dTrans = e.dataTransfer };
+ evt.initUIEvent('dragstart', true, true, window, 1);
+ div.dispatchEvent(evt);
+ assert_equals(dTrans,null);
+}, 'initUIEvent should give null as the dataTransfer' );
+test(function() {
+ var evt = new DragEvent('dragstart'), div = document.createElement('div'), dTrans = 'fail';
+ div.ondragstart = function (e) { dTrans = e.dataTransfer };
+ evt.initEvent('dragstart', true, true);
+ div.dispatchEvent(evt);
+ assert_equals(dTrans,null);
+}, 'initEvent should give null as the dataTransfer' );
+
+//cannot test that synthetic event does not use the same data store as non-synthetic event because that needs a real DragEvent to create a proper one with global storage
+//will be tested in another file
+ </script>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/synthetic/005-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/synthetic/005-manual.html
new file mode 100644
index 00000000000..0089b784b95
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/synthetic/005-manual.html
@@ -0,0 +1,339 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Synthetic events with real data store must inherit protection status from real events</title>
+ <style type="text/css">
+blockquote { height: 100px; width: 100px; background: orange; margin: 0; padding: 0; float: left; }
+blockquote + blockquote { background: blue; }
+blockquote + blockquote + blockquote { background: fuchsia; }
+blockquote + div { clear: left; }
+ </style>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript">
+setup(function () {},{explicit_done:true,explicit_timeout:true});
+window.onload = function () {
+
+ var orange = document.getElementsByTagName('blockquote')[0],
+ blue = document.getElementsByTagName('blockquote')[1],
+ fuchsia = document.getElementsByTagName('blockquote')[2],
+ evtdone = {};
+
+ orange.ondragstart = function (e) {
+ evtdone[e.type] = true;
+ e.dataTransfer.effectAllowed = 'copy';
+
+ var t = async_test(e.type+' should share its data with the synthetic event');
+ blue.ondragstart = function (e) {
+ t.step(function() {
+ assert_equals( e.dataTransfer.getData('text'), 'dragstart real data', 'step 1' );
+ e.dataTransfer.setData('text','dragstart-dragstart synthetic data');
+ assert_equals( e.dataTransfer.getData('text'), 'dragstart-dragstart synthetic data', 'step 2' );
+ });
+ };
+ t.step(function() {
+ var evt = new DragEvent('dragstart', {dataTransfer:e.dataTransfer});
+ e.dataTransfer.setData('text','dragstart real data'); //changing in between steps, just to make sure it uses the underlying data store, not a temporary clone
+ blue.dispatchEvent(evt);
+ });
+ t.done();
+
+ test(function() {
+ assert_equals( e.dataTransfer.getData('text'), 'dragstart-dragstart synthetic data' );
+ }, e.type+' should see the data from the synthetic event' );
+
+ var t2 = async_test(e.type+' should share its protection status with the synthetic event');
+ blue.ondrag = function (e) {
+ t2.step(function() {
+ e.dataTransfer.setData('text','dragstart-drag synthetic data');
+ assert_equals( e.dataTransfer.getData('text'), 'dragstart-drag synthetic data' );
+ });
+ };
+ t2.step(function() {
+ var evt = new DragEvent('drag', {dataTransfer:e.dataTransfer});
+ blue.dispatchEvent(evt);
+ });
+ t2.done();
+
+ var t3 = async_test(e.type+' should share its protection status with the nested synthetic event');
+ blue.ondrag = function (e) {
+ blue.ondragend = function (e) {
+ t3.step(function() {
+ assert_equals( e.dataTransfer.getData('text'), 'dragstart-drag synthetic data', 'step1' );
+ e.dataTransfer.setData('text','dragstart-drag-dragend synthetic data');
+ assert_equals( e.dataTransfer.getData('text'), 'dragstart-drag-dragend synthetic data', 'step2' );
+ });
+ };
+ t3.step(function() {
+ var evt = new DragEvent('dragend', {dataTransfer:e.dataTransfer});
+ blue.dispatchEvent(evt);
+ });
+ };
+ t3.step(function() {
+ var evt = new DragEvent('drag', {dataTransfer:e.dataTransfer});
+ blue.dispatchEvent(evt);
+ });
+ t3.done();
+
+ test(function() {
+ assert_equals( e.dataTransfer.getData('text'), 'dragstart-drag-dragend synthetic data' );
+ }, e.type+' should see the data from the nested synthetic event' );
+ };
+
+ blue.ondragenter = blue.ondragover = function (e) {
+ e.preventDefault();
+ };
+ orange.ondrag = blue.ondragleave = function (e) {
+ if( evtdone[e.type] ) { return; }
+ evtdone[e.type] = true;
+ var evtype = e.type;
+
+ var t = async_test(e.type+' should share its data with the synthetic event');
+ blue.ondragstart = function (e) {
+ t.step(function() {
+ assert_true( e.dataTransfer.items.length > 0, 'items.length' );
+ });
+ };
+ t.step(function() {
+ var evt = new DragEvent('dragstart', {dataTransfer:e.dataTransfer});
+ blue.dispatchEvent(evt);
+ });
+ t.done();
+
+ var t2 = async_test(e.type+' should share its protection status with the synthetic event');
+ blue.ondragstart = function (e) {
+ t2.step(function() {
+ assert_equals( e.dataTransfer.getData('text'), '', 'step 1' );
+ e.dataTransfer.setData('text',evtype+'-dragstart synthetic data');
+ assert_equals( e.dataTransfer.getData('text'), '', 'step 2' );
+ });
+ };
+ t2.step(function() {
+ var evt = new DragEvent('dragstart', {dataTransfer:e.dataTransfer});
+ blue.dispatchEvent(evt);
+ });
+ t2.done();
+
+ test(function() {
+ assert_equals( e.dataTransfer.getData('text'), '' );
+ }, e.type+' protection status should not be modified by the synthetic event' );
+
+ var t3 = async_test(e.type+' should share its protection status with the nested synthetic event');
+ blue.ondragstart = function (e) {
+ var div = document.createElement('div');
+ div.ondragstart = function (e) {
+ t3.step(function() {
+ assert_equals( e.dataTransfer.getData('text'), '', 'step1' );
+ e.dataTransfer.setData('text',evtype+'dragstart-dragstart synthetic data');
+ assert_equals( e.dataTransfer.getData('text'), '', 'step2' );
+ });
+ };
+ t3.step(function() {
+ var evt = new DragEvent('dragend', {dataTransfer:e.dataTransfer});
+ div.dispatchEvent(evt);
+ });
+ };
+ t3.step(function() {
+ var evt = new DragEvent('drag', {dataTransfer:e.dataTransfer});
+ blue.dispatchEvent(evt);
+ });
+ t3.done();
+ };
+
+ fuchsia.ondragenter = fuchsia.ondragover = function (e) {
+ e.preventDefault();
+ if( evtdone[e.type] ) { return; }
+ evtdone[e.type] = true;
+ var evtype = e.type;
+
+ var t = async_test(e.type+' should share its data with the synthetic event');
+ blue.ondragstart = function (e) {
+ t.step(function() {
+ assert_true( e.dataTransfer.items.length > 0, 'items.length' );
+ });
+ };
+ t.step(function() {
+ var evt = new DragEvent('dragstart', {dataTransfer:e.dataTransfer});
+ blue.dispatchEvent(evt);
+ });
+ t.done();
+
+ var t2 = async_test(e.type+' should share its protection status with the synthetic event');
+ blue.ondragstart = function (e) {
+ t2.step(function() {
+ assert_equals( e.dataTransfer.getData('text'), '', 'step 1' );
+ e.dataTransfer.setData('text',evtype+'-dragstart synthetic data');
+ assert_equals( e.dataTransfer.getData('text'), '', 'step 2' );
+ });
+ };
+ t2.step(function() {
+ var evt = new DragEvent('dragstart', {dataTransfer:e.dataTransfer});
+ blue.dispatchEvent(evt);
+ });
+ t2.done();
+
+ test(function() {
+ assert_equals( e.dataTransfer.getData('text'), '' );
+ }, e.type+' protection status should not be modified by the synthetic event' );
+
+ var t3 = async_test(e.type+' should share its protection status with the nested synthetic event');
+ blue.ondragstart = function (e) {
+ var div = document.createElement('div');
+ div.ondragstart = function (e) {
+ t3.step(function() {
+ assert_equals( e.dataTransfer.getData('text'), '', 'step1' );
+ e.dataTransfer.setData('text',evtype+'dragstart-dragstart synthetic data');
+ assert_equals( e.dataTransfer.getData('text'), '', 'step2' );
+ });
+ };
+ t3.step(function() {
+ var evt = new DragEvent('dragend', {dataTransfer:e.dataTransfer});
+ div.dispatchEvent(evt);
+ });
+ };
+ t3.step(function() {
+ var evt = new DragEvent('drag', {dataTransfer:e.dataTransfer});
+ blue.dispatchEvent(evt);
+ });
+ t3.done();
+ };
+
+ fuchsia.ondrop = function (e) {
+ e.preventDefault();
+ if( evtdone[e.type] ) { return; }
+ evtdone[e.type] = true;
+ var evtype = e.type;
+
+ var t = async_test(e.type+' should share its data with the synthetic event');
+ blue.ondragstart = function (e) {
+ t.step(function() {
+ assert_equals( e.dataTransfer.getData('text'), 'dragstart-drag-dragend synthetic data' );
+ });
+ };
+ t.step(function() {
+ var evt = new DragEvent('dragstart', {dataTransfer:e.dataTransfer});
+ blue.dispatchEvent(evt);
+ });
+ t.done();
+
+ var t2 = async_test(e.type+' should share its protection status with the synthetic event');
+ blue.ondragstart = function (e) {
+ t2.step(function() {
+ assert_equals( e.dataTransfer.getData('text'), 'dragstart-drag-dragend synthetic data', 'step 1' );
+ e.dataTransfer.setData('text',evtype+'-dragstart synthetic data');
+ assert_equals( e.dataTransfer.getData('text'), 'dragstart-drag-dragend synthetic data', 'step 2' );
+ });
+ };
+ t2.step(function() {
+ var evt = new DragEvent('dragstart', {dataTransfer:e.dataTransfer});
+ blue.dispatchEvent(evt);
+ });
+ t2.done();
+
+ test(function() {
+ e.dataTransfer.setData('text','drop synthetic data');
+ assert_equals( e.dataTransfer.getData('text'), 'dragstart-drag-dragend synthetic data' );
+ }, e.type+' protection status should not be modified by the synthetic event' );
+
+ var t3 = async_test(e.type+' should share its protection status with the nested synthetic event');
+ blue.ondragstart = function (e) {
+ var div = document.createElement('div');
+ div.ondragstart = function (e) {
+ t3.step(function() {
+ assert_equals( e.dataTransfer.getData('text'), 'dragstart-drag-dragend synthetic data', 'step 1' );
+ e.dataTransfer.setData('text',evtype+'dragstart-dragstart synthetic data');
+ assert_equals( e.dataTransfer.getData('text'), 'dragstart-drag-dragend synthetic data', 'step 2' );
+ });
+ };
+ t3.step(function() {
+ var evt = new DragEvent('dragend', {dataTransfer:e.dataTransfer});
+ div.dispatchEvent(evt);
+ });
+ };
+ t3.step(function() {
+ var evt = new DragEvent('drag', {dataTransfer:e.dataTransfer});
+ blue.dispatchEvent(evt);
+ });
+ t3.done();
+ };
+
+ orange.ondragend = function (e) {
+ if( evtdone[e.type] ) { return; }
+ evtdone[e.type] = true;
+ var evtype = e.type;
+
+ var t = async_test(e.type+' should share its data with the synthetic event');
+ blue.ondragstart = function (e) {
+ t.step(function() {
+ assert_true( e.dataTransfer.items.length > 0, 'items.length' );
+ });
+ };
+ t.step(function() {
+ var evt = new DragEvent('dragstart', {dataTransfer:e.dataTransfer});
+ blue.dispatchEvent(evt);
+ });
+ t.done();
+
+ var t2 = async_test(e.type+' should share its protection status with the synthetic event');
+ blue.ondragstart = function (e) {
+ t2.step(function() {
+ assert_equals( e.dataTransfer.getData('text'), '', 'step 1' );
+ e.dataTransfer.setData('text',evtype+'-dragstart synthetic data');
+ assert_equals( e.dataTransfer.getData('text'), '', 'step 2' );
+ });
+ };
+ t2.step(function() {
+ var evt = new DragEvent('dragstart', {dataTransfer:e.dataTransfer});
+ blue.dispatchEvent(evt);
+ });
+ t2.done();
+
+ test(function() {
+ assert_equals( e.dataTransfer.getData('text'), '' );
+ }, e.type+' protection status should not be modified by the synthetic event' );
+
+ var t3 = async_test(e.type+' should share its protection status with the nested synthetic event');
+ blue.ondragstart = function (e) {
+ var div = document.createElement('div');
+ div.ondragstart = function (e) {
+ t3.step(function() {
+ assert_equals( e.dataTransfer.getData('text'), '', 'step1' );
+ e.dataTransfer.setData('text',evtype+'dragstart-dragstart synthetic data');
+ assert_equals( e.dataTransfer.getData('text'), '', 'step2' );
+ });
+ };
+ t3.step(function() {
+ var evt = new DragEvent('dragend', {dataTransfer:e.dataTransfer});
+ div.dispatchEvent(evt);
+ });
+ };
+ t3.step(function() {
+ var evt = new DragEvent('drag', {dataTransfer:e.dataTransfer});
+ blue.dispatchEvent(evt);
+ });
+ t3.done();
+
+ test(function() {
+ var failtxt = '- Reload and try again';
+ assert_true( evtdone.dragstart, 'dragstart event was not tested'+failtxt );
+ assert_true( evtdone.drag, 'drag event was not tested'+failtxt );
+ assert_true( evtdone.dragenter, 'dragenter event was not tested'+failtxt );
+ assert_true( evtdone.dragleave, 'dragleave event was not tested'+failtxt );
+ assert_true( evtdone.dragover, 'dragover event was not tested'+failtxt );
+ assert_true( evtdone.drop, 'drop event was not tested'+failtxt );
+ assert_true( evtdone.dragend, 'dragend event was not tested'+failtxt );
+ }, 'all event types must now have been tested' );
+ done();
+ };
+
+};
+ </script>
+ </head>
+ <body>
+ <p>Drag the orange square over the blue square then the fuchsia square, then release it.</p>
+ <blockquote draggable="true"></blockquote>
+ <blockquote></blockquote>
+ <blockquote></blockquote>
+ <div id="log"></div>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/synthetic/006-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/synthetic/006-manual.html
new file mode 100644
index 00000000000..b03ec431b43
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/synthetic/006-manual.html
@@ -0,0 +1,78 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Synthetic events using real dataTransfer in new thread</title>
+ <style type="text/css">
+blockquote { height: 100px; width: 100px; background: orange; margin: 0; padding: 0; float: left; }
+blockquote + blockquote { background: blue; }
+blockquote + blockquote + blockquote { background: fuchsia; }
+blockquote + div { clear: left; }
+ </style>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript">
+setup(function () {},{explicit_done:true,explicit_timeout:true});
+window.onload = function () {
+
+ var orange = document.getElementsByTagName('blockquote')[0],
+ blue = document.getElementsByTagName('blockquote')[1],
+ fuchsia = document.getElementsByTagName('blockquote')[2],
+ evtdone = {};
+
+ orange.ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text','dragstart real data');
+ var dataTransfer = e.dataTransfer;
+ setTimeout(function () {
+ var t = async_test('new thread should see data store in protected mode after dragstart');
+ blue.ondragstart = function (e) {
+ t.step(function() {
+ assert_equals( e.dataTransfer.getData('text'), '', 'step 1' );
+ e.dataTransfer.setData('text','new thread after dragstart');
+ assert_equals( e.dataTransfer.getData('text'), '', 'step 2' );
+ });
+ };
+ t.step(function() {
+ var evt = new DragEvent('dragstart', {dataTransfer:dataTransfer});
+ blue.dispatchEvent(evt);
+ });
+ t.done();
+ },0);
+ };
+
+ fuchsia.ondragenter = fuchsia.ondragover = function (e) {
+ e.preventDefault();
+ };
+
+ fuchsia.ondrop = function (e) {
+ e.preventDefault();
+ var dataTransfer = e.dataTransfer;
+ setTimeout(function () {
+ var t = async_test('new thread should see data store in protected mode after drop');
+ blue.ondragstart = function (e) {
+ t.step(function() {
+ assert_equals( e.dataTransfer.getData('text'), '', 'step 1' );
+ e.dataTransfer.setData('text','new thread after dragstart');
+ assert_equals( e.dataTransfer.getData('text'), '', 'step 2' );
+ });
+ };
+ t.step(function() {
+ var evt = new DragEvent('dragstart', {dataTransfer:dataTransfer});
+ blue.dispatchEvent(evt);
+ });
+ t.done();
+ done();
+ },0);
+ };
+
+};
+ </script>
+ </head>
+ <body>
+ <p>Drag the orange square over the blue square then the fuchsia square, then release it.</p>
+ <blockquote draggable="true"></blockquote>
+ <blockquote></blockquote>
+ <blockquote></blockquote>
+ <div id="log"></div>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/001-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/001-manual.html
new file mode 100644
index 00000000000..f64e1c4e030
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/001-manual.html
@@ -0,0 +1,110 @@
+<!doctype html>
+<html>
+ <head>
+ <title>allowTargetOrigin syntax</title>
+ <style type="text/css">
+blockquote { height: 100px; width: 100px; background: orange; margin: 0; padding: 0; }
+ </style>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript">
+setup(function () {},{explicit_done:true});
+window.onload = function () {
+ document.getElementsByTagName('blockquote')[0].ondragstart = function (e) {
+ test(function() {
+ assert_true( !!e.dataTransfer.allowTargetOrigin );
+ }, 'allowTargetOrigin should be supported' );
+ test(function() {
+ assert_throws( new TypeError(), function () { e.dataTransfer.allowTargetOrigin(); } );
+ }, 'no parameter should throw TypeError' );
+ test(function() {
+ assert_throws( 'SYNTAX_ERR', function () { e.dataTransfer.allowTargetOrigin(''); } );
+ }, 'empty string should be an invalid URL' );
+ test(function() {
+ e.dataTransfer.allowTargetOrigin('*');
+ }, '* should be a valid URL' );
+ test(function() {
+ e.dataTransfer.allowTargetOrigin('/');
+ }, '/ should be a valid URL' );
+ test(function() {
+ assert_throws( 'SYNTAX_ERR', function () { e.dataTransfer.allowTargetOrigin('/foo'); } );
+ }, '/foo should be an invalid URL' );
+ test(function() {
+ assert_throws( 'SYNTAX_ERR', function () { e.dataTransfer.allowTargetOrigin('foo'); } );
+ }, 'foo should be an invalid URL' );
+ test(function() {
+ assert_throws( 'SYNTAX_ERR', function () { e.dataTransfer.allowTargetOrigin('//foo'); } );
+ }, '//foo should be an invalid URL' );
+ test(function() {
+ assert_throws( 'SYNTAX_ERR', function () { e.dataTransfer.allowTargetOrigin('http://'); } );
+ }, 'http:// should be an invalid URL' );
+ test(function() {
+ assert_throws( 'SYNTAX_ERR', function () { e.dataTransfer.allowTargetOrigin('http://*'); } );
+ }, 'http://* should be an invalid URL' );
+ test(function() {
+ assert_throws( 'SYNTAX_ERR', function () { e.dataTransfer.allowTargetOrigin('http://foo*'); } );
+ }, 'http://foo* should be an invalid URL' );
+ test(function() {
+ assert_throws( 'SYNTAX_ERR', function () { e.dataTransfer.allowTargetOrigin('http://foo.*'); } );
+ }, 'http://foo.* should be an invalid URL' );
+ test(function() {
+ assert_throws( 'SYNTAX_ERR', function () { e.dataTransfer.allowTargetOrigin('http://*.foo'); } );
+ }, 'http://*.foo should be an invalid URL' );
+ test(function() {
+ assert_throws( 'SYNTAX_ERR', function () { e.dataTransfer.allowTargetOrigin('http://foo:bar'); } );
+ }, 'http://foo:bar should be an invalid URL' );
+ test(function() {
+ assert_throws( 'SYNTAX_ERR', function () { e.dataTransfer.allowTargetOrigin('http://foo:bar@'); } );
+ }, 'http://foo:bar@ should be an invalid URL' );
+ test(function() {
+ assert_throws( 'SYNTAX_ERR', function () { e.dataTransfer.allowTargetOrigin('file:'); } );
+ }, 'file: should be an invalid URL' );
+ test(function() {
+ assert_throws( 'SYNTAX_ERR', function () { e.dataTransfer.allowTargetOrigin('file://'); } );
+ }, 'file:// should be an invalid URL' );
+ test(function() {
+ assert_throws( 'SYNTAX_ERR', function () { e.dataTransfer.allowTargetOrigin('data:'); } );
+ }, 'data: should be an invalid URL' );
+ test(function() {
+ assert_throws( 'SYNTAX_ERR', function () { e.dataTransfer.allowTargetOrigin('data:text/html'); } );
+ }, 'data:text/html should be an invalid URL' );
+ test(function() {
+ assert_throws( 'SYNTAX_ERR', function () { e.dataTransfer.allowTargetOrigin('file://localhost/'); } );
+ }, 'file://localhost/ should be an invalid URL' );
+ test(function() {
+ assert_throws( 'SYNTAX_ERR', function () { e.dataTransfer.allowTargetOrigin('file:///'); } );
+ }, 'file:/// should be an invalid URL' );
+ test(function() {
+ assert_throws( 'SYNTAX_ERR', function () { e.dataTransfer.allowTargetOrigin('data:text/html,'); } );
+ }, 'data:text/html, should be an invalid URL' );
+ test(function() {
+ assert_throws( 'SYNTAX_ERR', function () { e.dataTransfer.allowTargetOrigin('javascript:'); } );
+ }, 'javascript: should be an invalid URL' );
+ test(function() {
+ e.dataTransfer.allowTargetOrigin('http://foo');
+ }, 'http://foo should be a valid URL' );
+ test(function() {
+ e.dataTransfer.allowTargetOrigin('http://foo.bar');
+ }, 'http://foo.bar should be a valid URL' );
+ test(function() {
+ e.dataTransfer.allowTargetOrigin('http://foo/bar');
+ }, 'http://foo/bar should be a valid URL' );
+ test(function() {
+ e.dataTransfer.allowTargetOrigin('http://foo:123');
+ }, 'http://foo:123 should be a valid URL' );
+ test(function() {
+ e.dataTransfer.allowTargetOrigin('http://foo:bar@baz');
+ }, 'http://foo:bar@baz should be a valid URL' );
+ test(function() {
+ e.dataTransfer.allowTargetOrigin('http://foo:bar@baz:123/qux');
+ }, 'http://foo:bar@baz:123/qux should be a valid URL' );
+ done();
+ };
+};
+ </script>
+ </head>
+ <body>
+ <blockquote draggable="true"></blockquote>
+ <div id="log">Drag the orange square above until the drag placeholder appears, then release it.</div>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/002-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/002-manual.html
new file mode 100644
index 00000000000..db46c6797bb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/002-manual.html
@@ -0,0 +1,86 @@
+<!doctype html>
+<html>
+ <head>
+ <title>allowTargetOrigin events</title>
+ <style type="text/css">
+blockquote { height: 100px; width: 100px; background: orange; margin: 0; padding: 0; float: left; }
+blockquote + blockquote { background: blue; }
+blockquote + blockquote + blockquote { background: fuchsia; }
+blockquote + div { clear: left; }
+ </style>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript">
+setup(function () {},{explicit_done:true});
+window.onload = function () {
+ var orange = document.getElementsByTagName('blockquote')[0],
+ blue = document.getElementsByTagName('blockquote')[1],
+ fuchsia = document.getElementsByTagName('blockquote')[2],
+ evtdone = {};
+ orange.ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text','dummy text');
+ if( evtdone[e.type] ) { return; }
+ evtdone[e.type] = true;
+ test(function() {
+ assert_true( !!e.dataTransfer.allowTargetOrigin );
+ }, 'allowTargetOrigin should exist in '+e.type );
+ test(function() {
+ e.dataTransfer.allowTargetOrigin('*');
+ }, 'allowTargetOrigin should work in '+e.type );
+ };
+ blue.ondragenter = blue.ondragover = function (e) {
+ e.preventDefault();
+ };
+ orange.ondrag = blue.ondragleave = function (e) {
+ if( evtdone[e.type] ) { return; }
+ evtdone[e.type] = true;
+ test(function() {
+ assert_true( !!e.dataTransfer.allowTargetOrigin );
+ }, 'allowTargetOrigin should exist in '+e.type );
+ test(function() {
+ assert_throws( 'SECURITY_ERR', function () { e.dataTransfer.allowTargetOrigin('*'); } );
+ }, 'allowTargetOrigin should throw a SECURITY_ERR in '+e.type );
+ };
+ fuchsia.ondragenter = fuchsia.ondragover = fuchsia.ondrop = function (e) {
+ e.preventDefault();
+ if( evtdone[e.type] ) { return; }
+ evtdone[e.type] = true;
+ test(function() {
+ assert_true( !!e.dataTransfer.allowTargetOrigin );
+ }, 'allowTargetOrigin should exist in '+e.type );
+ test(function() {
+ assert_throws( 'SECURITY_ERR', function () { e.dataTransfer.allowTargetOrigin('*'); } );
+ }, 'allowTargetOrigin should throw a SECURITY_ERR in '+e.type );
+ };
+ orange.ondragend = function (e) {
+ if( evtdone[e.type] ) { return; }
+ evtdone[e.type] = true;
+ test(function() {
+ assert_true( !!e.dataTransfer.allowTargetOrigin );
+ }, 'allowTargetOrigin should exist in '+e.type );
+ test(function() {
+ assert_throws( 'SECURITY_ERR', function () { e.dataTransfer.allowTargetOrigin('*'); } );
+ }, 'allowTargetOrigin should throw a SECURITY_ERR in '+e.type );
+ test(function() {
+ var failtxt = '- Reload and try again';
+ assert_true( evtdone.dragstart, 'dragstart event was not tested'+failtxt );
+ assert_true( evtdone.drag, 'drag event was not tested'+failtxt );
+ assert_true( evtdone.dragenter, 'dragenter event was not tested'+failtxt );
+ assert_true( evtdone.dragleave, 'dragleave event was not tested'+failtxt );
+ assert_true( evtdone.dragover, 'dragover event was not tested'+failtxt );
+ assert_true( evtdone.drop, 'drop event was not tested'+failtxt );
+ assert_true( evtdone.dragend, 'dragend event was not tested'+failtxt );
+ }, 'all event types must now have been tested' );
+ done();
+ };
+};
+ </script>
+ </head>
+ <body>
+ <blockquote draggable="true"></blockquote>
+ <blockquote></blockquote>
+ <blockquote></blockquote>
+ <div id="log">Drag the orange square over the blue square then the fuchsia square, then release it.</div>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/003-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/003-manual.html
new file mode 100644
index 00000000000..5e0adbdd87b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/003-manual.html
@@ -0,0 +1,95 @@
+<!doctype html>
+<html>
+ <head>
+ <title>allowTargetOrigin valid syntax</title>
+ <style type="text/css">
+div { float: left; height: 100px; width: 100px; margin-right: 10px; background: orange; }
+iframe { height: 100px; width: 100px; border: none; }
+.note { float: right; color: silver; }
+ </style>
+ <script type="text/javascript" src="../resources/crossorigin.sub.js"></script>
+ <script type="text/javascript">
+function addNote(el,str) {
+ var par = document.createElement(el);
+ par.textContent = str;
+ document.body.appendChild(par);
+}
+function testFrame(text,frameorigin,framepath) {
+ var persist = arguments;
+ addNote('p',(done++)+'. '+text);
+ var div = document.createElement('div');
+ var frame = document.createElement('iframe');
+ frame.src = frameorigin+framepath;
+ div.draggable = true;
+ div.ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text','dummy text');
+ for( var i = 3; i < persist.length; i++ ) {
+ e.dataTransfer.allowTargetOrigin(persist[i]);
+ }
+ };
+ var par = document.createElement('p');
+ par.className = 'note';
+ par.appendChild(document.createTextNode('Target: '+frameorigin));
+ par.appendChild(document.createElement('br'));
+ par.appendChild(document.createTextNode('Allowing: '+([]).slice.call(persist,3).join(' and ')));
+ if( framepath.match(/\?domain\b/) ) {
+ par.appendChild(document.createElement('br'));
+ par.appendChild(document.createTextNode('document.domain set to parent domain'));
+ }
+ document.body.appendChild(par);
+ document.body.appendChild(div);
+ document.body.appendChild(frame);
+}
+var done = 1;
+window.onload = function () {
+ var allowText = 'Drag the orange box below over the blue box the right, and release it. Fail if nothing happens in the blue box.';
+ var blockText = 'Drag the orange box below over the pink box the right, and release it. Pass if nothing happens in the pink box.';
+ var allowHelper = location.pathname.replace(/[^\/]*$/,'HELPER-mustallow.html');
+ var blockHelper = location.pathname.replace(/[^\/]*$/,'HELPER-mustblock.html');
+ if( location.hostname != httpHostMain || location.host != httpHostMain ) {
+ addNote('p','This test must be loaded over http:\/\/'+httpHostMain+'\/');
+ } else {
+ /* 01 */ testFrame(allowText,'http://'+httpHostMain,allowHelper);
+ /* 02 */ testFrame(allowText,'http://'+httpHostAlias,allowHelper);
+ /* 03 */ testFrame(allowText,'http://'+httpHostMain,allowHelper,'*');
+ /* 04 */ testFrame(allowText,'http://'+httpHostAlias,allowHelper,'*');
+ /* 05 */ testFrame(allowText,'http://'+httpHostMain,allowHelper,'/');
+ /* 06 */ testFrame(blockText,'http://'+httpHostAlias,blockHelper,'/');
+ /* 07 */ testFrame(allowText,'http://'+httpHostMain,allowHelper,'http://'+httpHostMain);
+ /* 08 */ testFrame(blockText,'http://'+httpHostMain+':'+httpPortAlias,blockHelper,'http://'+httpHostMain);
+ /* 09 */ testFrame(blockText,'http://'+httpHostAlias,blockHelper,'http://'+httpHostMain);
+ /* 10 */ testFrame(blockText,'http://'+httpHostAlias,blockHelper,'http://'+httpHostMain);
+ /* 11 */ testFrame(allowText,'http://'+httpHostMain,allowHelper,'http://'+httpHostMain+':80');
+ /* 12 */ testFrame(blockText,'http://'+httpHostMain+':'+httpPortAlias,blockHelper,'http://'+httpHostMain+':80');
+ /* 13 */ testFrame(allowText,'http://'+httpHostMain+':'+httpPortAlias,allowHelper,'http://'+httpHostMain+':'+httpPortAlias);
+ /* 14 */ testFrame(blockText,'http://'+httpHostMain,blockHelper,'http://'+httpHostMain+':'+httpPortAlias);
+ /* 15 */ testFrame(blockText,'https://'+httpsHostAlias,blockHelper,'http://'+httpsHostAlias);
+ /* 16 */ testFrame(allowText,'https://'+httpsHostAlias,allowHelper,'https://'+httpsHostAlias);
+ /* 17 */ testFrame(allowText,'http://'+httpHostMain,allowHelper,'http://foo:bar@'+httpHostMain+'/baz');
+ /* 18 */ testFrame(allowText,'http://foo:bar@'+httpHostMain,allowHelper,'http://'+httpHostMain);
+ /* 19 */ testFrame(allowText,'http://'+httpHostMain,allowHelper,'http://'+httpHostAlias,'/');
+ /* 20 */ testFrame(allowText,'http://'+httpHostMain,allowHelper,'/','http://'+httpHostAlias);
+ /* 21 */ testFrame(allowText,'http://'+httpHostMain,allowHelper,'http://'+httpHostAlias,'*');
+ /* 22 */ testFrame(allowText,'http://'+httpHostMain,allowHelper,'http://'+httpHostAlias,'http://'+httpHostMain);
+ /* 23 */ testFrame(allowText,'http://'+httpHostAlias,allowHelper,'http://'+httpHostAlias,'http://'+httpHostMain);
+ /* 24 */ testFrame(blockText,'http://'+httpHostAlias,blockHelper,'http://dummy','http://'+httpHostMain);
+ /* 25 */ testFrame(blockText,'https://'+httpsHostAlias,blockHelper,'https://'+httpsHostAlias+':'+httpsPortAlias);
+ /* 26 */ testFrame(blockText,'https://'+httpsHostAlias+':'+httpsPortAlias,blockHelper,'https://'+httpsHostAlias);
+ /* 27 */ testFrame(allowText,'https://'+httpsHostAlias+':'+httpsPortAlias,allowHelper,'https://'+httpsHostAlias+':'+httpsPortAlias);
+ window.xhr = new XMLHttpRequest();
+ xhr.open('GET',allowHelper,false);
+ xhr.send(null);
+ /* 28 */ testFrame(allowText,'data:text/html,',escape(xhr.responseText),'http://'+httpHostMain);
+ /* 29 */ testFrame(allowText,'javascript:','parent.xhr.responseText','http://'+httpHostMain);
+ /* 30 */ testFrame(blockText,'http://'+httpHostAlias,blockHelper,'http://'+httpHostAlias.replace(/^[^.]+\./,''));
+ /* 31 */ testFrame(allowText,'http://'+httpHostAlias,allowHelper+'?domain','http://'+httpHostAlias);
+ /* 32 */ testFrame(blockText,'http://'+httpHostAlias,blockHelper+'?domain','http://'+httpHostAlias.replace(/^[^.]+\./,''));
+ }
+};
+ </script>
+ </head>
+ <body>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/004-1.html b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/004-1.html
new file mode 100644
index 00000000000..f8a4e8e5562
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/004-1.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Data URI does not match absolute HTTP URL</title>
+ <style type="text/css">
+html, body { margin: 0; padding: 0; }
+div { height: 100px; width: 100px; background: orange; }
+ </style>
+ <script type="text/javascript" src="../resources/crossorigin.sub.js"></script>
+ <script type="text/javascript">
+window.onload = function () {
+ document.getElementsByTagName('div')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text','dummy text');
+ e.dataTransfer.allowTargetOrigin('http://'+httpHostMain);
+ };
+};
+ </script>
+ </head>
+ <body>
+
+ <div draggable="true"></div>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/004-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/004-manual.html
new file mode 100644
index 00000000000..2a3d3bbe4b2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/004-manual.html
@@ -0,0 +1,36 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Data URI does not match absolute HTTP URL</title>
+ </head>
+ <body>
+ <p>Load the following URL in a new tab (copy &amp; paste it into the address bar):</p>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+
+ <script type="text/javascript">
+document.write('data:text/html,'+escape(
+'<!doctype html>\
+<html>\
+ <head>\
+ <title>Data URI does not match absolute HTTP URL<\/title>\
+ <style type="text/css">\
+iframe { border: none; height: 150px; width: 150px; }\
+ <\/style>\
+ <script type="text/javascript">\
+window.onload = function () {\
+ document.body.ondragenter = document.body.ondragleave = document.body.ondragover = document.body.ondrop = function (e) {\
+ e.preventDefault();\
+ document.body.innerHTML = "FAIL";\
+ };\
+};\
+ <\/script>\
+ <\/head>\
+ <body>\
+ <p>Drag the orange square below over this text, and release it. Pass if this text does not change.<\/p>\
+ <p><iframe src="'+location.href.replace(/\.html$/,'-1.html')+'"><\/iframe><\/p>\
+ <\/body>\
+<\/html>'));
+
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/005-1.html b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/005-1.html
new file mode 100644
index 00000000000..15f6a8c23cb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/005-1.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<html>
+ <head>
+ <title>JavaScript URI does not match absolute HTTP URL</title>
+ <style type="text/css">
+html, body { margin: 0; padding: 0; }
+div { height: 100px; width: 100px; background: orange; }
+ </style>
+ <script type="text/javascript" src="../resources/crossorigin.sub.js"></script>
+ <script type="text/javascript">
+window.onload = function () {
+ document.getElementsByTagName('div')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text','dummy text');
+ e.dataTransfer.allowTargetOrigin('http://'+httpHostMain);
+ };
+};
+ </script>
+ </head>
+ <body>
+
+ <div draggable="true"></div>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/005-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/005-manual.html
new file mode 100644
index 00000000000..90a002cf0b4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/005-manual.html
@@ -0,0 +1,36 @@
+<!doctype html>
+<html>
+ <head>
+ <title>JavaScript URI does not match absolute HTTP URL</title>
+ </head>
+ <body>
+ <p>Load the following URL in a new tab (copy &amp; paste it into the address bar):</p>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+
+ <script type="text/javascript">
+document.write('javascript:unescape("'+escape(
+'<!doctype html>\
+<html>\
+ <head>\
+ <title>JavaScript does not match absolute HTTP URL<\/title>\
+ <style type=\'text/css\'>\
+iframe { border: none; height: 150px; width: 150px; }\
+ <\/style>\
+ <script type=\'text/javascript\'>\
+window.onload = function () {\
+ document.body.ondragenter = document.body.ondragleave = document.body.ondragover = document.body.ondrop = function (e) {\
+ e.preventDefault();\
+ document.body.innerHTML = \'FAIL\';\
+ };\
+};\
+ <\/script>\
+ <\/head>\
+ <body>\
+ <p>Drag the orange square below over this text, and release it. Pass if this text does not change.<\/p>\
+ <p><iframe src=\''+location.href.replace(/\.html$/,'-1.html')+'\'><\/iframe><\/p>\
+ <\/body>\
+<\/html>')+'")');
+
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/006-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/006-manual.html
new file mode 100644
index 00000000000..e1674390c0d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/006-manual.html
@@ -0,0 +1,52 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Data URI does not match /</title>
+ </head>
+ <body>
+ <!--
+/ sets an absolute URL pointing to the document's unique identifier - used as the script origin.
+The script origin will in fact be inherited from the parent page, which is actually the same data URI.
+That part works.
+However, when it comes to matching against it, it will not match, as the global identifier does not
+match because the origin does not match the scheme/host/port tuple required.
+ -->
+ <p>Load the following URL in a new tab (copy &amp; paste it into the address bar):</p>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+
+ <script type="text/javascript">
+document.write('data:text/html,'+escape(
+'<!doctype html>\
+<html>\
+ <head>\
+ <title>Data URI does not match /<\/title>\
+ <style type="text/css">\
+html, body { margin: 0; padding: 0; }\
+div { height: 100px; width: 100px; background: orange; }\
+iframe { border: none; height: 150px; width: 150px; }\
+ <\/style>\
+ <\/head>\
+ <body>\
+ <script type="text/javascript">\
+if( self == top ) {\
+ document.body.ondragenter = document.body.ondragleave = document.body.ondragover = document.body.ondrop = function (e) {\
+ e.preventDefault();\
+ document.body.innerHTML = "FAIL";\
+ };\
+ document.write("<p>Drag the orange square below over this text, and release it. Pass if this text does not change.<\\\/p>");\
+ document.write("<p><iframe src=\\""+location.href+"\\"><\\\/iframe><\\\/p>");\
+} else {\
+ document.write("<div draggable=\\"true\\"><\\\/div>");\
+ document.getElementsByTagName("div")[0].ondragstart = function (e) {\
+ e.dataTransfer.effectAllowed = "copy";\
+ e.dataTransfer.setData("text","dummy text");\
+ e.dataTransfer.allowTargetOrigin("/");\
+ };\
+}\
+ <\/script>\
+ <\/body>\
+<\/html>'));
+
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/007-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/007-manual.html
new file mode 100644
index 00000000000..4f35ed17e31
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/007-manual.html
@@ -0,0 +1,52 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Data URI does not match its own URL</title>
+ </head>
+ <body>
+ <!--
+Sets an absolute URL pointing to the data URI.
+The script origin will in fact be inherited from the parent page, which is actually the same data URI.
+That part works.
+However, when it comes to matching against it, it will not match, as the global identifier used as the
+script origin does not match because the origin does not match the scheme/host/port tuple required.
+ -->
+ <p>Load the following URL in a new tab (copy &amp; paste it into the address bar):</p>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+
+ <script type="text/javascript">
+document.write('data:text/html,'+escape(
+'<!doctype html>\
+<html>\
+ <head>\
+ <title>Data URI does not match its own URL<\/title>\
+ <style type="text/css">\
+html, body { margin: 0; padding: 0; }\
+div { height: 100px; width: 100px; background: orange; }\
+iframe { border: none; height: 150px; width: 150px; }\
+ <\/style>\
+ <\/head>\
+ <body>\
+ <script type="text/javascript">\
+if( self == top ) {\
+ document.body.ondragenter = document.body.ondragleave = document.body.ondragover = document.body.ondrop = function (e) {\
+ e.preventDefault();\
+ document.body.innerHTML = "FAIL";\
+ };\
+ document.write("<p>Drag the orange square below over this text, and release it. Pass if this text does not change.<\\\/p>");\
+ document.write("<p><iframe src=\\""+location.href+"\\"><\\\/iframe><\\\/p>");\
+} else {\
+ document.write("<div draggable=\\"true\\"><\\\/div>");\
+ document.getElementsByTagName("div")[0].ondragstart = function (e) {\
+ e.dataTransfer.effectAllowed = "copy";\
+ e.dataTransfer.setData("text","dummy text");\
+ e.dataTransfer.allowTargetOrigin(location.href);\
+ };\
+}\
+ <\/script>\
+ <\/body>\
+<\/html>'));
+
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/008-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/008-manual.html
new file mode 100644
index 00000000000..71e915c9cde
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/008-manual.html
@@ -0,0 +1,53 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Data URI does match *</title>
+ </head>
+ <body>
+ <!--
+* allows any URL at all, so it should work
+ -->
+ <p>Load the following URL in a new tab (copy &amp; paste it into the address bar):</p>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+
+ <script type="text/javascript">
+document.write('data:text/html,'+escape(
+'<!doctype html>\
+<html>\
+ <head>\
+ <title>Data URI does match *<\/title>\
+ <style type="text/css">\
+html, body { margin: 0; padding: 0; }\
+div { height: 100px; width: 100px; background: orange; }\
+iframe { border: none; height: 150px; width: 150px; }\
+ <\/style>\
+ <\/head>\
+ <body>\
+ <script type="text/javascript">\
+var seentypes = {};\
+if( self == top ) {\
+ document.body.ondragenter = document.body.ondragover = document.body.ondrop = function (e) {\
+ e.preventDefault();\
+ if( e.type == "drop" ) {\
+ document.body.innerHTML = ( seentypes.dragenter && seentypes.dragover ) ? "PASS" : "FAIL";\
+ } else {\
+ seentypes[e.type] = true;\
+ }\
+ };\
+ document.write("<p>Drag the orange square below over this text, and release it. Fail if this text does not change.<\\\/p>");\
+ document.write("<p><iframe src=\\""+location.href+"\\"><\\\/iframe><\\\/p>");\
+} else {\
+ document.write("<div draggable=\\"true\\"><\\\/div>");\
+ document.getElementsByTagName("div")[0].ondragstart = function (e) {\
+ e.dataTransfer.effectAllowed = "copy";\
+ e.dataTransfer.setData("text","dummy text");\
+ e.dataTransfer.allowTargetOrigin("*");\
+ };\
+}\
+ <\/script>\
+ <\/body>\
+<\/html>'));
+
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/009-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/009-manual.html
new file mode 100644
index 00000000000..2fc7ef43ed2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/009-manual.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<html>
+ <head>
+ <title>* should not prevent dropping on external applications</title>
+ <style type="text/css">
+div { height: 100px; width: 100px; background: orange; }
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ document.getElementsByTagName("div")[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = "copy";
+ e.dataTransfer.setData("text","PASS");
+ e.dataTransfer.allowTargetOrigin("*");
+ };
+};
+ </script>
+ </head>
+ <body>
+ <p>This test is only relevant on platforms where it is possible to switch applications in mid-drag (eg. alt+tab, dragging over taskbar buttons, dragging between restored windows).</p>
+ <p>This testcase requires an external application that accepts dropping of text from other applications - eg. Wordpad (write.exe) on Windows. Ensure that the external application is open.</p>
+ <p>Drag the orange block to the other application and release it. Pass if the word &quot;PASS&quot; appears in the other application.</p>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <div draggable="true"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/010-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/010-manual.html
new file mode 100644
index 00000000000..74a20d7e0e9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/010-manual.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<html>
+ <head>
+ <title>A URL should prevent dropping on external applications</title>
+ <style type="text/css">
+div { height: 100px; width: 100px; background: orange; }
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ document.getElementsByTagName("div")[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = "copy";
+ e.dataTransfer.setData("text","FAIL");
+ e.dataTransfer.allowTargetOrigin("http://foo");
+ };
+};
+ </script>
+ </head>
+ <body>
+ <p>This test is only relevant on platforms where it is possible to switch applications in mid-drag (eg. alt+tab, dragging over taskbar buttons, dragging between restored windows).</p>
+ <p>This testcase requires an external application that accepts dropping of text from other applications - eg. Wordpad (write.exe) on Windows. Ensure that the external application is open.</p>
+ <p>Drag the orange block to the other application and release it. Fail if the word &quot;FAIL&quot; appears in the other application.</p>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <div draggable="true"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/011-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/011-manual.html
new file mode 100644
index 00000000000..e0302712e52
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/011-manual.html
@@ -0,0 +1,63 @@
+<!doctype html>
+<html>
+ <head>
+ <title>allowTargetOrigin should only block dragenter, dragover, dragleave and drop events</title>
+ <style type="text/css">
+div { height: 100px; width: 100px; background: orange; margin: 0; padding: 0; float: left; }
+div + div { background: blue; }
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ var orange = document.getElementsByTagName('div')[0], evtdone = {}, fails = [];
+ orange.ondragstart = function (e) {
+ evtdone[e.type] = true;
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text','dummy text');
+ try {
+ e.dataTransfer.allowTargetOrigin('http://example.com');
+ } catch(e) {
+ fails[fails.length] = 'allowTargetOrigin threw an error: '+e;
+ }
+ };
+ orange.ondragenter = orange.ondragover = orange.ondrop = function (e) {
+ e.preventDefault();
+ evtdone[e.type] = true;
+ };
+ orange.ondrag = orange.ondragleave = function (e) {
+ evtdone[e.type] = true;
+ };
+ orange.ondragend = function (e) {
+ evtdone[e.type] = true;
+ if( !evtdone.dragstart ) {
+ fails[fails.length] = 'dragstart did not fire - how did that happen?';
+ }
+ if( !evtdone.drag ) {
+ fails[fails.length] = 'drag did not fire';
+ }
+ if( !evtdone.dragend ) {
+ fails[fails.length] = 'dragend did not fire - OK, who broke the testcase?';
+ }
+ if( evtdone.dragenter ) {
+ fails[fails.length] = 'dragenter fired';
+ }
+ if( evtdone.dragover ) {
+ fails[fails.length] = 'dragover fired';
+ }
+ if( evtdone.dragleave ) {
+ fails[fails.length] = 'dragleave fired';
+ }
+ if( evtdone.drop ) {
+ fails[fails.length] = 'drop fired';
+ }
+ document.getElementsByTagName('p')[0].innerHTML = fails.length ? ( 'FAIL:<br>' + fails.join('<br>') ) : 'PASS';
+ };
+};
+ </script>
+ </head>
+ <body>
+ <p>Drag the orange square over the blue square then back to the orange square, then release it. Fail if this text does not change.</p>
+ <div draggable="true"></div>
+ <div></div>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/012-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/012-manual.html
new file mode 100644
index 00000000000..164e613edb9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/012-manual.html
@@ -0,0 +1,62 @@
+<!doctype html>
+<html>
+ <head>
+ <title>allowTargetOrigin after leaving browser window</title>
+ <style type="text/css">
+div { float: left; height: 100px; width: 100px; margin-right: 10px; background: orange; }
+iframe { height: 100px; width: 100px; border: none; }
+.note { float: right; color: silver; }
+ </style>
+ <script type="text/javascript" src="../resources/crossorigin.sub.js"></script>
+ <script type="text/javascript">
+function addNote(el,str) {
+ var par = document.createElement(el);
+ par.textContent = str;
+ document.body.appendChild(par);
+}
+function testFrame(text,frameorigin,framepath) {
+ var persist = arguments;
+ addNote('p',(done++)+'. '+text);
+ var div = document.createElement('div');
+ var frame = document.createElement('iframe');
+ frame.src = frameorigin+framepath;
+ div.draggable = true;
+ div.ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text','dummy text');
+ for( var i = 3; i < persist.length; i++ ) {
+ e.dataTransfer.allowTargetOrigin(persist[i]);
+ }
+ };
+ var par = document.createElement('p');
+ par.className = 'note';
+ par.appendChild(document.createTextNode('Target: '+frameorigin));
+ par.appendChild(document.createElement('br'));
+ par.appendChild(document.createTextNode('Allowing: '+([]).slice.call(persist,3).join(' and ')));
+ if( framepath.match(/\?domain\b/) ) {
+ par.appendChild(document.createElement('br'));
+ par.appendChild(document.createTextNode('document.domain set to parent domain'));
+ }
+ document.body.appendChild(par);
+ document.body.appendChild(div);
+ document.body.appendChild(frame);
+}
+var done = 1;
+window.onload = function () {
+ var allowText = 'Drag the orange box below outside the browser window (not onto the system taskbar) then back over the blue box the right, and release it. Fail if nothing happens in the blue box.';
+ var blockText = 'Drag the orange box below outside the browser window (not onto the system taskbar) then back over the pink box the right, and release it. Pass if nothing happens in the pink box.';
+ var allowHelper = location.pathname.replace(/[^\/]*$/,'HELPER-mustallow.html');
+ var blockHelper = location.pathname.replace(/[^\/]*$/,'HELPER-mustblock.html');
+ if( location.hostname != httpHostMain || location.host != httpHostMain ) {
+ addNote('p','This test must be loaded over http:\/\/'+httpHostMain+'\/');
+ } else {
+ /* 07 */ testFrame(allowText,'http://'+httpHostMain,allowHelper,'http://'+httpHostMain);
+ /* 09 */ testFrame(blockText,'http://'+httpHostAlias,blockHelper,'http://'+httpHostMain);
+ }
+};
+ </script>
+ </head>
+ <body>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/013-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/013-manual.html
new file mode 100644
index 00000000000..39ee70cf579
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/013-manual.html
@@ -0,0 +1,24 @@
+<!doctype html>
+<html>
+ <head>
+ <title>A URL should prevent dropping on UI</title>
+ <style type="text/css">
+div { height: 100px; width: 100px; background: orange; }
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ document.getElementsByTagName("div")[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = "copy";
+ e.dataTransfer.setData("text","FAIL");
+ e.dataTransfer.allowTargetOrigin("http://foo");
+ };
+};
+ </script>
+ </head>
+ <body>
+ <p>This test is only relevant on platforms where it is possible to drop data onto the browser UI (eg. the address field).</p>
+ <p>Drag the orange block to the address field and release it. Fail if the word &quot;FAIL&quot; appears in the address field. Repeat for other UI fields.</p>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <div draggable="true"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/101-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/101-manual.html
new file mode 100644
index 00000000000..24ef0395744
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/101-manual.html
@@ -0,0 +1,123 @@
+<!doctype html>
+<html>
+ <head>
+ <title>.origin for all events</title>
+ <style type="text/css">
+blockquote { height: 100px; width: 100px; background: orange; margin: 0; padding: 0; float: left; }
+blockquote + blockquote { background: blue; }
+blockquote + blockquote + blockquote { background: fuchsia; }
+blockquote + div { clear: left; }
+ </style>
+ <script type="text/javascript" src="../resources/crossorigin.sub.js"></script>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript">
+setup(function () {},{explicit_done:true});
+window.onload = function () {
+ var origin = 'http://'+httpHostMain;
+ if( location.href.indexOf(origin+'/') ) {
+ done();
+ document.body.innerHTML = 'This must be tested on '+origin+'/';
+ return;
+ }
+ var orange = document.getElementsByTagName('blockquote')[0],
+ blue = document.getElementsByTagName('blockquote')[1],
+ fuchsia = document.getElementsByTagName('blockquote')[2],
+ evtdone = {};
+ orange.ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text','dummy text');
+ if( evtdone[e.type] ) { return; }
+ evtdone[e.type] = true;
+ test(function() {
+ assert_equals( e.dataTransfer.origin, origin );
+ }, '.origin should exist in '+e.type );
+ test(function () {
+ //WebIDL and ECMAScript 5 - a readonly property has a getter but not a setter
+ //ES5 makes [[Put]] fail but not throw
+ var failed = false, oldorigin = e.dataTransfer.origin;
+ try {
+ e.dataTransfer.origin = 'http://example.com';
+ } catch(e) {
+ failed = e;
+ }
+ assert_equals(e.dataTransfer.origin,oldorigin);
+ assert_false(failed,'an error was thrown');
+ }, '.origin must be read-only in '+e.type);
+ };
+ blue.ondragenter = blue.ondragover = function (e) {
+ e.preventDefault();
+ };
+ orange.ondrag = blue.ondragleave = function (e) {
+ if( evtdone[e.type] ) { return; }
+ evtdone[e.type] = true;
+ test(function() {
+ assert_equals( e.dataTransfer.origin, origin );
+ }, '.origin should exist in '+e.type );
+ test(function () {
+ var failed = false, oldorigin = e.dataTransfer.origin;
+ try {
+ e.dataTransfer.origin = 'http://example.com';
+ } catch(e) {
+ failed = e;
+ }
+ assert_equals(e.dataTransfer.origin,oldorigin);
+ assert_false(failed,'an error was thrown');
+ }, '.origin must be read-only in '+e.type);
+ };
+ fuchsia.ondragenter = fuchsia.ondragover = fuchsia.ondrop = function (e) {
+ e.preventDefault();
+ if( evtdone[e.type] ) { return; }
+ evtdone[e.type] = true;
+ test(function() {
+ assert_equals( e.dataTransfer.origin, origin );
+ }, '.origin should exist in '+e.type );
+ test(function () {
+ var failed = false, oldorigin = e.dataTransfer.origin;
+ try {
+ e.dataTransfer.origin = 'http://example.com';
+ } catch(e) {
+ failed = e;
+ }
+ assert_equals(e.dataTransfer.origin,oldorigin);
+ assert_false(failed,'an error was thrown');
+ }, '.origin must be read-only in '+e.type);
+ };
+ orange.ondragend = function (e) {
+ if( evtdone[e.type] ) { return; }
+ evtdone[e.type] = true;
+ test(function() {
+ assert_equals( e.dataTransfer.origin, origin );
+ }, '.origin should exist in '+e.type );
+ test(function () {
+ var failed = false, oldorigin = e.dataTransfer.origin;
+ try {
+ e.dataTransfer.origin = 'http://example.com';
+ } catch(e) {
+ failed = e;
+ }
+ assert_equals(e.dataTransfer.origin,oldorigin);
+ assert_false(failed,'an error was thrown');
+ }, '.origin must be read-only in '+e.type);
+ test(function() {
+ var failtxt = '- Reload and try again';
+ assert_true( evtdone.dragstart, 'dragstart event was not tested'+failtxt );
+ assert_true( evtdone.drag, 'drag event was not tested'+failtxt );
+ assert_true( evtdone.dragenter, 'dragenter event was not tested'+failtxt );
+ assert_true( evtdone.dragleave, 'dragleave event was not tested'+failtxt );
+ assert_true( evtdone.dragover, 'dragover event was not tested'+failtxt );
+ assert_true( evtdone.drop, 'drop event was not tested'+failtxt );
+ assert_true( evtdone.dragend, 'dragend event was not tested'+failtxt );
+ }, 'all event types must now have been tested' );
+ done();
+ };
+};
+ </script>
+ </head>
+ <body>
+ <blockquote draggable="true"></blockquote>
+ <blockquote></blockquote>
+ <blockquote></blockquote>
+ <div id="log">Drag the orange square over the blue square then the fuchsia square, then release it.</div>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/102-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/102-manual.html
new file mode 100644
index 00000000000..ebb3090ba33
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/102-manual.html
@@ -0,0 +1,36 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Origin for http site to itself</title>
+ <style type="text/css">
+div { height: 100px; width: 100px; background: orange; }
+iframe { width: 500px; height: 120px; border: none; }
+ </style>
+ <script type="text/javascript" src="../resources/crossorigin.sub.js"></script>
+ <script type="text/javascript">
+window.onload = function () {
+ var origin = 'http://'+httpHostMain;
+ if( location.href.indexOf(origin+'/') ) {
+ document.body.innerHTML = 'This must be tested on '+origin+'/';
+ return;
+ }
+ document.getElementsByTagName('div')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text','dummy text');
+ };
+ document.getElementsByTagName('span')[0].textContent = origin;
+ var iframe = document.createElement('iframe');
+ iframe.src = origin+location.pathname.replace(/[^\/]*$/,'HELPER-showorigin.html');
+ document.body.insertBefore(iframe,document.getElementsByTagName('div')[0]);
+};
+ </script>
+ </head>
+ <body>
+
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <p>Drag the orange square onto the blue square and release it. The blue square should be replaced with the text:<br>
+ <span></span></p>
+ <div draggable="true"></div>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/103-1.html b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/103-1.html
new file mode 100644
index 00000000000..9904ceaa061
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/103-1.html
@@ -0,0 +1,32 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Origin for http site with user/pass/port to itself</title>
+ <style type="text/css">
+div { height: 100px; width: 100px; background: orange; }
+iframe { width: 500px; height: 120px; border: none; }
+ </style>
+ <script type="text/javascript" src="../resources/crossorigin.sub.js"></script>
+ <script type="text/javascript">
+window.onload = function () {
+ var origin = 'http://'+httpHostMain;
+ document.getElementsByTagName('div')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text','dummy text');
+ };
+ document.getElementsByTagName('span')[0].textContent = origin;
+ var iframe = document.createElement('iframe');
+ iframe.src = origin+location.pathname.replace(/[^\/]*$/,'HELPER-showorigin.html');
+ document.body.insertBefore(iframe,document.getElementsByTagName('div')[0]);
+};
+ </script>
+ </head>
+ <body>
+
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <p>Drag the orange square onto the blue square and release it. The blue square should be replaced with the text:<br>
+ <span></span></p>
+ <div draggable="true"></div>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/103-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/103-manual.html
new file mode 100644
index 00000000000..7bedf0958a3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/103-manual.html
@@ -0,0 +1,27 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Origin for http site with user/pass/port to itself</title>
+ <style type="text/css">
+html, body, iframe { display: block; width: 100%; height: 100%; border: none; margin: 0; padding: 0; }
+ </style>
+ <script type="text/javascript" src="../resources/crossorigin.sub.js"></script>
+ <script type="text/javascript">
+window.onload = function () {
+ var origin = 'http://'+httpHostMain;
+ if( location.href.indexOf(origin+'/') ) {
+ document.body.innerHTML = 'This must be tested on '+origin+'/';
+ return;
+ }
+ var iframe = document.createElement('iframe');
+ iframe.src = 'http://foo:bar@'+httpHostMain+':80'+location.pathname.replace(/.html$/,'-1.html');
+ document.body.appendChild(iframe);
+};
+ </script>
+ </head>
+ <body>
+
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/104-1.html b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/104-1.html
new file mode 100644
index 00000000000..ada4a6f995c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/104-1.html
@@ -0,0 +1,32 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Origin for http site with non-default port to itself</title>
+ <style type="text/css">
+div { height: 100px; width: 100px; background: orange; }
+iframe { width: 500px; height: 120px; border: none; }
+ </style>
+ <script type="text/javascript" src="../resources/crossorigin.sub.js"></script>
+ <script type="text/javascript">
+window.onload = function () {
+ var origin = 'http://'+httpHostMain+':'+httpPortAlias;
+ document.getElementsByTagName('div')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text','dummy text');
+ };
+ document.getElementsByTagName('span')[0].textContent = origin;
+ var iframe = document.createElement('iframe');
+ iframe.src = origin+location.pathname.replace(/[^\/]*$/,'HELPER-showorigin.html');
+ document.body.insertBefore(iframe,document.getElementsByTagName('div')[0]);
+};
+ </script>
+ </head>
+ <body>
+
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <p>Drag the orange square onto the blue square and release it. The blue square should be replaced with the text:<br>
+ <span></span></p>
+ <div draggable="true"></div>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/104-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/104-manual.html
new file mode 100644
index 00000000000..1262424624f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/104-manual.html
@@ -0,0 +1,27 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Origin for http site with non-default port to itself</title>
+ <style type="text/css">
+html, body, iframe { display: block; width: 100%; height: 100%; border: none; margin: 0; padding: 0; }
+ </style>
+ <script type="text/javascript" src="../resources/crossorigin.sub.js"></script>
+ <script type="text/javascript">
+window.onload = function () {
+ var origin = 'http://'+httpHostMain;
+ if( location.href.indexOf(origin+'/') ) {
+ document.body.innerHTML = 'This must be tested on '+origin+'/';
+ return;
+ }
+ var iframe = document.createElement('iframe');
+ iframe.src = 'http://'+httpHostMain+':'+httpPortAlias+location.pathname.replace(/.html$/,'-1.html');
+ document.body.appendChild(iframe);
+};
+ </script>
+ </head>
+ <body>
+
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/105-1.html b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/105-1.html
new file mode 100644
index 00000000000..ccfe4f4c476
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/105-1.html
@@ -0,0 +1,32 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Origin for http site to site with non-default port</title>
+ <style type="text/css">
+div { height: 100px; width: 100px; background: orange; }
+iframe { width: 500px; height: 120px; border: none; }
+ </style>
+ <script type="text/javascript" src="../resources/crossorigin.sub.js"></script>
+ <script type="text/javascript">
+window.onload = function () {
+ var origin = 'http://'+httpHostMain;
+ document.getElementsByTagName('div')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text','dummy text');
+ };
+ document.getElementsByTagName('span')[0].textContent = origin;
+ var iframe = document.createElement('iframe');
+ iframe.src = origin+':'+httpPortAlias+location.pathname.replace(/[^\/]*$/,'HELPER-showorigin.html');
+ document.body.insertBefore(iframe,document.getElementsByTagName('div')[0]);
+};
+ </script>
+ </head>
+ <body>
+
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <p>Drag the orange square onto the blue square and release it. The blue square should be replaced with the text:<br>
+ <span></span></p>
+ <div draggable="true"></div>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/105-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/105-manual.html
new file mode 100644
index 00000000000..4695888a6d3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/105-manual.html
@@ -0,0 +1,27 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Origin for http site to site with non-default port</title>
+ <style type="text/css">
+html, body, iframe { display: block; width: 100%; height: 100%; border: none; margin: 0; padding: 0; }
+ </style>
+ <script type="text/javascript" src="../resources/crossorigin.sub.js"></script>
+ <script type="text/javascript">
+window.onload = function () {
+ var origin = 'http://'+httpHostMain;
+ if( location.href.indexOf(origin+'/') ) {
+ document.body.innerHTML = 'This must be tested on '+origin+'/';
+ return;
+ }
+ var iframe = document.createElement('iframe');
+ iframe.src = 'http://'+httpHostMain+location.pathname.replace(/.html$/,'-1.html');
+ document.body.appendChild(iframe);
+};
+ </script>
+ </head>
+ <body>
+
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/106-1.html b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/106-1.html
new file mode 100644
index 00000000000..d8ff88efc4f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/106-1.html
@@ -0,0 +1,32 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Origin for http site with non-default port to site</title>
+ <style type="text/css">
+div { height: 100px; width: 100px; background: orange; }
+iframe { width: 500px; height: 120px; border: none; }
+ </style>
+ <script type="text/javascript" src="../resources/crossorigin.sub.js"></script>
+ <script type="text/javascript">
+window.onload = function () {
+ var origin = 'http://'+httpHostMain+':'+httpPortAlias;
+ document.getElementsByTagName('div')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text','dummy text');
+ };
+ document.getElementsByTagName('span')[0].textContent = origin;
+ var iframe = document.createElement('iframe');
+ iframe.src = 'http://'+httpHostMain+location.pathname.replace(/[^\/]*$/,'HELPER-showorigin.html');
+ document.body.insertBefore(iframe,document.getElementsByTagName('div')[0]);
+};
+ </script>
+ </head>
+ <body>
+
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <p>Drag the orange square onto the blue square and release it. The blue square should be replaced with the text:<br>
+ <span></span></p>
+ <div draggable="true"></div>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/106-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/106-manual.html
new file mode 100644
index 00000000000..18017511beb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/106-manual.html
@@ -0,0 +1,27 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Origin for http site with non-default port to site</title>
+ <style type="text/css">
+html, body, iframe { display: block; width: 100%; height: 100%; border: none; margin: 0; padding: 0; }
+ </style>
+ <script type="text/javascript" src="../resources/crossorigin.sub.js"></script>
+ <script type="text/javascript">
+window.onload = function () {
+ var origin = 'http://'+httpHostMain;
+ if( location.href.indexOf(origin+'/') ) {
+ document.body.innerHTML = 'This must be tested on '+origin+'/';
+ return;
+ }
+ var iframe = document.createElement('iframe');
+ iframe.src = 'http://'+httpHostMain+':'+httpPortAlias+location.pathname.replace(/.html$/,'-1.html');
+ document.body.appendChild(iframe);
+};
+ </script>
+ </head>
+ <body>
+
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/107-1.html b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/107-1.html
new file mode 100644
index 00000000000..2392b19eaa6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/107-1.html
@@ -0,0 +1,32 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Origin for https site to itself</title>
+ <style type="text/css">
+div { height: 100px; width: 100px; background: orange; }
+iframe { width: 500px; height: 120px; border: none; }
+ </style>
+ <script type="text/javascript" src="../resources/crossorigin.sub.js"></script>
+ <script type="text/javascript">
+window.onload = function () {
+ var origin = 'https://'+httpsHostAlias;
+ document.getElementsByTagName('div')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text','dummy text');
+ };
+ document.getElementsByTagName('span')[0].textContent = origin;
+ var iframe = document.createElement('iframe');
+ iframe.src = origin+location.pathname.replace(/[^\/]*$/,'HELPER-showorigin.html');
+ document.body.insertBefore(iframe,document.getElementsByTagName('div')[0]);
+};
+ </script>
+ </head>
+ <body>
+
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <p>Drag the orange square onto the blue square and release it. The blue square should be replaced with the text:<br>
+ <span></span></p>
+ <div draggable="true"></div>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/107-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/107-manual.html
new file mode 100644
index 00000000000..ecd9e9b7b7d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/107-manual.html
@@ -0,0 +1,27 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Origin for https site to itself</title>
+ <style type="text/css">
+html, body, iframe { display: block; width: 100%; height: 100%; border: none; margin: 0; padding: 0; }
+ </style>
+ <script type="text/javascript" src="../resources/crossorigin.sub.js"></script>
+ <script type="text/javascript">
+window.onload = function () {
+ var origin = 'http://'+httpHostMain;
+ if( location.href.indexOf(origin+'/') ) {
+ document.body.innerHTML = 'This must be tested on '+origin+'/';
+ return;
+ }
+ var iframe = document.createElement('iframe');
+ iframe.src = 'https://'+httpsHostAlias+location.pathname.replace(/.html$/,'-1.html');
+ document.body.appendChild(iframe);
+};
+ </script>
+ </head>
+ <body>
+
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/108-1.html b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/108-1.html
new file mode 100644
index 00000000000..b3027dbe248
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/108-1.html
@@ -0,0 +1,32 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Origin for https site with non-default port to itself</title>
+ <style type="text/css">
+div { height: 100px; width: 100px; background: orange; }
+iframe { width: 500px; height: 120px; border: none; }
+ </style>
+ <script type="text/javascript" src="../resources/crossorigin.sub.js"></script>
+ <script type="text/javascript">
+window.onload = function () {
+ var origin = 'https://'+httpsHostAlias+':'+httpsPortAlias;
+ document.getElementsByTagName('div')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text','dummy text');
+ };
+ document.getElementsByTagName('span')[0].textContent = origin;
+ var iframe = document.createElement('iframe');
+ iframe.src = origin+location.pathname.replace(/[^\/]*$/,'HELPER-showorigin.html');
+ document.body.insertBefore(iframe,document.getElementsByTagName('div')[0]);
+};
+ </script>
+ </head>
+ <body>
+
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <p>Drag the orange square onto the blue square and release it. The blue square should be replaced with the text:<br>
+ <span></span></p>
+ <div draggable="true"></div>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/108-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/108-manual.html
new file mode 100644
index 00000000000..eb77db366a1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/108-manual.html
@@ -0,0 +1,27 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Origin for https site with non-default port to itself</title>
+ <style type="text/css">
+html, body, iframe { display: block; width: 100%; height: 100%; border: none; margin: 0; padding: 0; }
+ </style>
+ <script type="text/javascript" src="../resources/crossorigin.sub.js"></script>
+ <script type="text/javascript">
+window.onload = function () {
+ var origin = 'http://'+httpHostMain;
+ if( location.href.indexOf(origin+'/') ) {
+ document.body.innerHTML = 'This must be tested on '+origin+'/';
+ return;
+ }
+ var iframe = document.createElement('iframe');
+ iframe.src = 'https://'+httpsHostAlias+':'+httpsPortAlias+location.pathname.replace(/.html$/,'-1.html');
+ document.body.appendChild(iframe);
+};
+ </script>
+ </head>
+ <body>
+
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/109-1.html b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/109-1.html
new file mode 100644
index 00000000000..6b4e1d80cf6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/109-1.html
@@ -0,0 +1,32 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Origin for https site to site with non-default port</title>
+ <style type="text/css">
+div { height: 100px; width: 100px; background: orange; }
+iframe { width: 500px; height: 120px; border: none; }
+ </style>
+ <script type="text/javascript" src="../resources/crossorigin.sub.js"></script>
+ <script type="text/javascript">
+window.onload = function () {
+ var origin = 'https://'+httpsHostAlias;
+ document.getElementsByTagName('div')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text','dummy text');
+ };
+ document.getElementsByTagName('span')[0].textContent = origin;
+ var iframe = document.createElement('iframe');
+ iframe.src = origin+':'+httpsPortAlias+location.pathname.replace(/[^\/]*$/,'HELPER-showorigin.html');
+ document.body.insertBefore(iframe,document.getElementsByTagName('div')[0]);
+};
+ </script>
+ </head>
+ <body>
+
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <p>Drag the orange square onto the blue square and release it. The blue square should be replaced with the text:<br>
+ <span></span></p>
+ <div draggable="true"></div>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/109-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/109-manual.html
new file mode 100644
index 00000000000..7817a85509c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/109-manual.html
@@ -0,0 +1,27 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Origin for https site to site with non-default port</title>
+ <style type="text/css">
+html, body, iframe { display: block; width: 100%; height: 100%; border: none; margin: 0; padding: 0; }
+ </style>
+ <script type="text/javascript" src="../resources/crossorigin.sub.js"></script>
+ <script type="text/javascript">
+window.onload = function () {
+ var origin = 'http://'+httpHostMain;
+ if( location.href.indexOf(origin+'/') ) {
+ document.body.innerHTML = 'This must be tested on '+origin+'/';
+ return;
+ }
+ var iframe = document.createElement('iframe');
+ iframe.src = 'https://'+httpsHostAlias+location.pathname.replace(/.html$/,'-1.html');
+ document.body.appendChild(iframe);
+};
+ </script>
+ </head>
+ <body>
+
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/110-1.html b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/110-1.html
new file mode 100644
index 00000000000..ee584003a85
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/110-1.html
@@ -0,0 +1,32 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Origin for https site with non-default port to site</title>
+ <style type="text/css">
+div { height: 100px; width: 100px; background: orange; }
+iframe { width: 500px; height: 120px; border: none; }
+ </style>
+ <script type="text/javascript" src="../resources/crossorigin.sub.js"></script>
+ <script type="text/javascript">
+window.onload = function () {
+ var origin = 'https://'+httpsHostAlias+':'+httpsPortAlias;
+ document.getElementsByTagName('div')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text','dummy text');
+ };
+ document.getElementsByTagName('span')[0].textContent = origin;
+ var iframe = document.createElement('iframe');
+ iframe.src = 'https://'+httpsHostAlias+location.pathname.replace(/[^\/]*$/,'HELPER-showorigin.html');
+ document.body.insertBefore(iframe,document.getElementsByTagName('div')[0]);
+};
+ </script>
+ </head>
+ <body>
+
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <p>Drag the orange square onto the blue square and release it. The blue square should be replaced with the text:<br>
+ <span></span></p>
+ <div draggable="true"></div>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/110-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/110-manual.html
new file mode 100644
index 00000000000..663e162bd46
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/110-manual.html
@@ -0,0 +1,27 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Origin for https site with non-default port to site</title>
+ <style type="text/css">
+html, body, iframe { display: block; width: 100%; height: 100%; border: none; margin: 0; padding: 0; }
+ </style>
+ <script type="text/javascript" src="../resources/crossorigin.sub.js"></script>
+ <script type="text/javascript">
+window.onload = function () {
+ var origin = 'http://'+httpHostMain;
+ if( location.href.indexOf(origin+'/') ) {
+ document.body.innerHTML = 'This must be tested on '+origin+'/';
+ return;
+ }
+ var iframe = document.createElement('iframe');
+ iframe.src = 'https://'+httpsHostAlias+':'+httpsPortAlias+location.pathname.replace(/.html$/,'-1.html');
+ document.body.appendChild(iframe);
+};
+ </script>
+ </head>
+ <body>
+
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/111-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/111-manual.html
new file mode 100644
index 00000000000..c81efa01d06
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/111-manual.html
@@ -0,0 +1,52 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Origin for file: to http:</title>
+ <script type="text/javascript" src="../resources/crossorigin.sub.js"></script>
+ <script type="text/javascript">
+window.onload = function () {
+ var origin = 'http://'+httpHostMain;
+ if( location.href.indexOf(origin+'/') ) {
+ document.body.innerHTML = 'This must be tested on '+origin+'/';
+ return;
+ }
+ var datastr =
+'<!doctype html>\
+<html>\
+ <head>\
+ <title>Origin for file: to http:<\/title>\
+ <style type="text/css">\
+div { height: 100px; width: 100px; background: orange; }\
+iframe { width: 500px; height: 120px; border: none; }\
+ <\/style>\
+ <script type="text/javascript">\
+window.onload = function () {\
+ var origin = "null (string)";\
+ document.getElementsByTagName("div")[0].ondragstart = function (e) {\
+ e.dataTransfer.effectAllowed = "copy";\
+ e.dataTransfer.setData("text","dummy text");\
+ };\
+ document.getElementsByTagName("span")[0].textContent = origin;\
+ var iframe = document.createElement("iframe");\
+ iframe.src = "'+location.href.replace(/[^\/]*$/,'HELPER-showorigin.html')+'";\
+ document.body.insertBefore(iframe,document.getElementsByTagName("div")[0]);\
+};\
+ <\/script>\
+ <\/head>\
+ <body>\
+ <p>Drag the orange square onto the blue square and release it. The blue square should be replaced with the text:<br>\
+ <span><\/span><\/p>\
+ <div draggable="true"></div>\
+ <\/body>\
+<\/html>';
+ document.getElementsByTagName('a')[0].href = 'data:text/html,'+escape(datastr);
+};
+ </script>
+ </head>
+ <body>
+
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <p><a href="">Download the linked file to your disk</a>, and open it locally. Follow further instructions in that file.</p>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/112-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/112-manual.html
new file mode 100644
index 00000000000..858e51d9c1c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/112-manual.html
@@ -0,0 +1,56 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Origin for data: with inherited http origin to http:</title>
+ <style type="text/css">
+html, body, iframe { display: block; width: 100%; height: 100%; border: none; margin: 0; padding: 0; }
+ </style>
+ <script type="text/javascript" src="../resources/crossorigin.sub.js"></script>
+ <script type="text/javascript">
+window.onload = function () {
+ var origin = 'http://'+httpHostMain;
+ if( location.href.indexOf(origin+'/') ) {
+ document.body.innerHTML = 'This must be tested on '+origin+'/';
+ return;
+ }
+ var datastr =
+'<!doctype html>\
+<html>\
+ <head>\
+ <title>Origin for data: with inherited http origin to http:<\/title>\
+ <style type="text/css">\
+div { height: 100px; width: 100px; background: orange; }\
+iframe { width: 500px; height: 120px; border: none; }\
+ <\/style>\
+ <script type="text/javascript">\
+window.onload = function () {\
+ var origin = "http://'+httpHostMain+'";\
+ document.getElementsByTagName("div")[0].ondragstart = function (e) {\
+ e.dataTransfer.effectAllowed = "copy";\
+ e.dataTransfer.setData("text","dummy text");\
+ };\
+ document.getElementsByTagName("span")[0].textContent = origin;\
+ var iframe = document.createElement("iframe");\
+ iframe.src = "'+location.href.replace(/[^\/]*$/,'HELPER-showorigin.html')+'";\
+ document.body.insertBefore(iframe,document.getElementsByTagName("div")[0]);\
+};\
+ <\/script>\
+ <\/head>\
+ <body>\
+ <p>Drag the orange square onto the blue square and release it. The blue square should be replaced with the text:<br>\
+ <span><\/span><\/p>\
+ <div draggable="true"></div>\
+ <\/body>\
+<\/html>';
+ var iframe = document.createElement('iframe');
+ iframe.src = 'data:text/html,'+escape(datastr);
+ document.body.appendChild(iframe);
+};
+ </script>
+ </head>
+ <body>
+
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/113-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/113-manual.html
new file mode 100644
index 00000000000..d3f889a9de3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/113-manual.html
@@ -0,0 +1,50 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Origin for data: with no inherited origin to http:</title>
+ <script type="text/javascript" src="../resources/crossorigin.sub.js"></script>
+ </head>
+ <body>
+
+ <p>Load the following URL in a new tab (copy &amp; paste it into the address bar):</p>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+
+ <script type="text/javascript">
+var origin = 'http://'+httpHostMain;
+if( location.href.indexOf(origin+'/') ) {
+ document.write('This must be tested on '+origin+'/');
+} else {
+ document.write("data:text/html,"+escape(
+'<!doctype html>\
+<html>\
+ <head>\
+ <title>Origin for data: with no inherited origin to http:<\/title>\
+ <style type="text/css">\
+div { height: 100px; width: 100px; background: orange; }\
+iframe { width: 500px; height: 120px; border: none; }\
+ <\/style>\
+ <script type="text/javascript">\
+window.onload = function () {\
+ var origin = "null (string)";\
+ document.getElementsByTagName("div")[0].ondragstart = function (e) {\
+ e.dataTransfer.effectAllowed = "copy";\
+ e.dataTransfer.setData("text","dummy text");\
+ };\
+ document.getElementsByTagName("span")[0].textContent = origin;\
+ var iframe = document.createElement("iframe");\
+ iframe.src = "'+location.href.replace(/[^\/]*$/,'HELPER-showorigin.html')+'";\
+ document.body.insertBefore(iframe,document.getElementsByTagName("div")[0]);\
+};\
+ <\/script>\
+ <\/head>\
+ <body>\
+ <p>Drag the orange square onto the blue square and release it. The blue square should be replaced with the text:<br>\
+ <span><\/span><\/p>\
+ <div draggable="true"></div>\
+ <\/body>\
+<\/html>'));
+}
+ </script>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/114-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/114-manual.html
new file mode 100644
index 00000000000..b2532178a8a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/114-manual.html
@@ -0,0 +1,56 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Origin for javascript: with inherited http origin to http:</title>
+ <style type="text/css">
+html, body, iframe { display: block; width: 100%; height: 100%; border: none; margin: 0; padding: 0; }
+ </style>
+ <script type="text/javascript" src="../resources/crossorigin.sub.js"></script>
+ <script type="text/javascript">
+window.onload = function () {
+ var origin = 'http://'+httpHostMain;
+ if( location.href.indexOf(origin+'/') ) {
+ document.body.innerHTML = 'This must be tested on '+origin+'/';
+ return;
+ }
+ var datastr =
+'<!doctype html>\
+<html>\
+ <head>\
+ <title>Origin for javascript: with inherited http origin to http:<\/title>\
+ <style type="text/css">\
+div { height: 100px; width: 100px; background: orange; }\
+iframe { width: 500px; height: 120px; border: none; }\
+ <\/style>\
+ <script type="text/javascript">\
+window.onload = function () {\
+ var origin = "http://'+httpHostMain+'";\
+ document.getElementsByTagName("div")[0].ondragstart = function (e) {\
+ e.dataTransfer.effectAllowed = "copy";\
+ e.dataTransfer.setData("text","dummy text");\
+ };\
+ document.getElementsByTagName("span")[0].textContent = origin;\
+ var iframe = document.createElement("iframe");\
+ iframe.src = "'+location.href.replace(/[^\/]*$/,'HELPER-showorigin.html')+'";\
+ document.body.insertBefore(iframe,document.getElementsByTagName("div")[0]);\
+};\
+ <\/script>\
+ <\/head>\
+ <body>\
+ <p>Drag the orange square onto the blue square and release it. The blue square should be replaced with the text:<br>\
+ <span><\/span><\/p>\
+ <div draggable="true"></div>\
+ <\/body>\
+<\/html>';
+ var iframe = document.createElement('iframe');
+ iframe.src = "javascript:'"+escape(datastr)+"'";
+ document.body.appendChild(iframe);
+};
+ </script>
+ </head>
+ <body>
+
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/115-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/115-manual.html
new file mode 100644
index 00000000000..751757e1461
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/115-manual.html
@@ -0,0 +1,50 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Origin for javascript: with no inherited origin to http:</title>
+ <script type="text/javascript" src="../resources/crossorigin.sub.js"></script>
+ </head>
+ <body>
+
+ <p>Load the following URL in a new tab (copy &amp; paste it into the address bar):</p>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+
+ <script type="text/javascript">
+var origin = 'http://'+httpHostMain;
+if( location.href.indexOf(origin+'/') ) {
+ document.write('This must be tested on '+origin+'/');
+} else {
+ document.write("javascript:'"+escape(
+'<!doctype html>\
+<html>\
+ <head>\
+ <title>Origin for javascript: with no inherited origin to http:<\/title>\
+ <style type="text/css">\
+div { height: 100px; width: 100px; background: orange; }\
+iframe { width: 500px; height: 120px; border: none; }\
+ <\/style>\
+ <script type="text/javascript">\
+window.onload = function () {\
+ var origin = "null (string)";\
+ document.getElementsByTagName("div")[0].ondragstart = function (e) {\
+ e.dataTransfer.effectAllowed = "copy";\
+ e.dataTransfer.setData("text","dummy text");\
+ };\
+ document.getElementsByTagName("span")[0].textContent = origin;\
+ var iframe = document.createElement("iframe");\
+ iframe.src = "'+location.href.replace(/[^\/]*$/,'HELPER-showorigin.html')+'";\
+ document.body.insertBefore(iframe,document.getElementsByTagName("div")[0]);\
+};\
+ <\/script>\
+ <\/head>\
+ <body>\
+ <p>Drag the orange square onto the blue square and release it. The blue square should be replaced with the text:<br>\
+ <span><\/span><\/p>\
+ <div draggable="true"></div>\
+ <\/body>\
+<\/html>')+"'");
+}
+ </script>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/116-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/116-manual.html
new file mode 100644
index 00000000000..fdeeeb3734e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/116-manual.html
@@ -0,0 +1,31 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Origin for dropped files</title>
+ <style type="text/css">
+div { height: 100px; width: 100px; background: orange; }
+iframe { width: 500px; height: 120px; border: none; }
+ </style>
+ <script type="text/javascript" src="../resources/crossorigin.sub.js"></script>
+ <script type="text/javascript">
+window.onload = function () {
+ var origin = 'http://'+httpHostMain;
+ if( location.href.indexOf(origin+'/') ) {
+ document.body.innerHTML = 'This must be tested on '+origin+'/';
+ return;
+ }
+ document.getElementsByTagName('span')[0].textContent = 'null (string)';
+ var iframe = document.createElement('iframe');
+ iframe.src = origin+location.pathname.replace(/[^\/]*$/,'HELPER-showorigin.html');
+ document.body.insertBefore(iframe,document.getElementsByTagName('div')[0]);
+};
+ </script>
+ </head>
+ <body>
+
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <p>Drag a small file from your computer onto the blue square and release it. If a prompt appears, accept it. The blue square should be replaced with the text:<br>
+ <span></span></p>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/117-1.html b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/117-1.html
new file mode 100644
index 00000000000..c49b18ac9cc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/117-1.html
@@ -0,0 +1,33 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Origin for site with document.domain set to a parent domain</title>
+ <style type="text/css">
+div { height: 100px; width: 100px; background: orange; }
+iframe { width: 500px; height: 120px; border: none; }
+ </style>
+ <script type="text/javascript" src="../resources/crossorigin.sub.js"></script>
+ <script type="text/javascript">
+window.onload = function () {
+ var origin = 'http://'+httpHostAlias;
+ document.getElementsByTagName('div')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text','dummy text');
+ };
+ document.getElementsByTagName('span')[0].textContent = origin;
+ document.domain = httpsHostAlias.replace(/^[^.]+\./,'');
+ var iframe = document.createElement('iframe');
+ iframe.src = origin+location.pathname.replace(/[^\/]*$/,'HELPER-showorigin.html');
+ document.body.insertBefore(iframe,document.getElementsByTagName('div')[0]);
+};
+ </script>
+ </head>
+ <body>
+
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <p>Drag the orange square onto the blue square and release it. The blue square should be replaced with the text:<br>
+ <span></span></p>
+ <div draggable="true"></div>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/117-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/117-manual.html
new file mode 100644
index 00000000000..d126fdaac66
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/117-manual.html
@@ -0,0 +1,27 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Origin for site with document.domain set to a parent domain</title>
+ <style type="text/css">
+html, body, iframe { display: block; width: 100%; height: 100%; border: none; margin: 0; padding: 0; }
+ </style>
+ <script type="text/javascript" src="../resources/crossorigin.sub.js"></script>
+ <script type="text/javascript">
+window.onload = function () {
+ var origin = 'http://'+httpHostMain;
+ if( location.href.indexOf(origin+'/') ) {
+ document.body.innerHTML = 'This must be tested on '+origin+'/';
+ return;
+ }
+ var iframe = document.createElement('iframe');
+ iframe.src = 'http://'+httpHostAlias+location.pathname.replace(/.html$/,'-1.html');
+ document.body.appendChild(iframe);
+};
+ </script>
+ </head>
+ <body>
+
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/118-1.html b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/118-1.html
new file mode 100644
index 00000000000..d0212bd2a4c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/118-1.html
@@ -0,0 +1,32 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Origin after leaving browser window</title>
+ <style type="text/css">
+div { height: 100px; width: 100px; background: orange; }
+iframe { width: 500px; height: 120px; border: none; }
+ </style>
+ <script type="text/javascript" src="../resources/crossorigin.sub.js"></script>
+ <script type="text/javascript">
+window.onload = function () {
+ var origin = 'http://'+httpHostMain+':'+httpPortAlias;
+ document.getElementsByTagName('div')[0].ondragstart = function (e) {
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text','dummy text');
+ };
+ document.getElementsByTagName('span')[0].textContent = origin;
+ var iframe = document.createElement('iframe');
+ iframe.src = 'http://'+httpHostMain+location.pathname.replace(/[^\/]*$/,'HELPER-showorigin.html');
+ document.body.insertBefore(iframe,document.getElementsByTagName('div')[0]);
+};
+ </script>
+ </head>
+ <body>
+
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <p>Drag the orange square out of the browser window (not onto the system taskbar) then back onto the blue square and release it. The blue square should be replaced with the text:<br>
+ <span></span></p>
+ <div draggable="true"></div>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/118-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/118-manual.html
new file mode 100644
index 00000000000..6b931692d31
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/118-manual.html
@@ -0,0 +1,27 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Origin after leaving browser window</title>
+ <style type="text/css">
+html, body, iframe { display: block; width: 100%; height: 100%; border: none; margin: 0; padding: 0; }
+ </style>
+ <script type="text/javascript" src="../resources/crossorigin.sub.js"></script>
+ <script type="text/javascript">
+window.onload = function () {
+ var origin = 'http://'+httpHostMain;
+ if( location.href.indexOf(origin+'/') ) {
+ document.body.innerHTML = 'This must be tested on '+origin+'/';
+ return;
+ }
+ var iframe = document.createElement('iframe');
+ iframe.src = 'http://'+httpHostMain+':'+httpPortAlias+location.pathname.replace(/.html$/,'-1.html');
+ document.body.appendChild(iframe);
+};
+ </script>
+ </head>
+ <body>
+
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/201-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/201-manual.html
new file mode 100644
index 00000000000..a687147c765
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/201-manual.html
@@ -0,0 +1,83 @@
+<!doctype html>
+<html>
+ <head>
+ <title>allowTargetOrigin with real dataTransfer should block dragenter, dragover, dragleave and drop synthetic events</title>
+ <style type="text/css">
+p + div { height: 100px; width: 100px; background: orange; }
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ var orange = document.getElementsByTagName('div')[0], targ = document.getElementsByTagName('div')[1], evtdone = {}, fails = [];
+ orange.ondragstart = function (e) {
+ var evt;
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text','dummy text');
+ try {
+ e.dataTransfer.allowTargetOrigin('http://example.com');
+ } catch(e) {
+ fails[fails.length] = 'allowTargetOrigin threw an error: '+e;
+ }
+ try {
+ evt = new DragEvent('dragstart', {dataTransfer:e.dataTransfer});
+ targ.dispatchEvent(evt);
+ evt = new DragEvent('drag', {dataTransfer:e.dataTransfer});
+ targ.dispatchEvent(evt);
+ evt = new DragEvent('dragenter', {dataTransfer:e.dataTransfer});
+ targ.dispatchEvent(evt);
+ evt = new DragEvent('dragover', {dataTransfer:e.dataTransfer});
+ targ.dispatchEvent(evt);
+ evt = new DragEvent('dragleave', {dataTransfer:e.dataTransfer});
+ targ.dispatchEvent(evt);
+ evt = new DragEvent('drop', {dataTransfer:e.dataTransfer});
+ targ.dispatchEvent(evt);
+ evt = new DragEvent('dragend', {dataTransfer:e.dataTransfer});
+ targ.dispatchEvent(evt);
+ } catch(e) {
+ fails[fails.length] = 'Synthetic event threw an error: '+e;
+ }
+ if( !evtdone.dragstart ) {
+ fails[fails.length] = 'dragstart did not fire';
+ }
+ if( !evtdone.drag ) {
+ fails[fails.length] = 'drag did not fire';
+ }
+ if( !evtdone.dragend ) {
+ fails[fails.length] = 'dragend did not fire';
+ }
+ if( evtdone.dragenter ) {
+ fails[fails.length] = 'dragenter fired';
+ }
+ if( evtdone.dragover ) {
+ fails[fails.length] = 'dragover fired';
+ }
+ if( evtdone.dragleave ) {
+ fails[fails.length] = 'dragleave fired';
+ }
+ if( evtdone.drop ) {
+ fails[fails.length] = 'drop fired';
+ }
+ document.getElementsByTagName('p')[0].innerHTML = fails.length ? ( 'FAIL:<br>' + fails.join('<br>') ) : 'PASS';
+ };
+ targ.ondragstart = function (e) {
+ evtdone[e.type] = true;
+ };
+ targ.ondragenter = targ.ondragover = targ.ondrop = function (e) {
+ e.preventDefault();
+ evtdone[e.type] = true;
+ };
+ targ.ondrag = targ.ondragleave = function (e) {
+ evtdone[e.type] = true;
+ };
+ targ.ondragend = function (e) {
+ evtdone[e.type] = true;
+ };
+};
+ </script>
+ </head>
+ <body>
+ <p>Drag the orange square to the right until the drag placeholder appears, then release it. Fail if this text does not change.</p>
+ <div draggable="true"></div>
+ <div></div>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/202.html b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/202.html
new file mode 100644
index 00000000000..0e6b43c060e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/202.html
@@ -0,0 +1,64 @@
+<!doctype html>
+<html>
+ <head>
+ <title>allowTargetOrigin with fake dataTransfer should block dragenter, dragover, dragleave and drop synthetic events</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div draggable="true"></div>
+ <div></div>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <div id="log"></div>
+
+ <script type="text/javascript">
+test(function () {
+ var dragsource = document.getElementsByTagName('div')[0], targ = document.getElementsByTagName('div')[1], evtdone = {};
+ dragsource.ondragstart = function (e) {
+ var evt;
+ evtdone.initial = true;
+ e.dataTransfer.effectAllowed = 'copy';
+ e.dataTransfer.setData('text','dummy text');
+ e.dataTransfer.allowTargetOrigin('http://example.com');
+ evt = new DragEvent('dragstart', {dataTransfer:e.dataTransfer});
+ targ.dispatchEvent(evt);
+ evt = new DragEvent('drag', {dataTransfer:e.dataTransfer});
+ targ.dispatchEvent(evt);
+ evt = new DragEvent('dragenter', {dataTransfer:e.dataTransfer});
+ targ.dispatchEvent(evt);
+ evt = new DragEvent('dragover', {dataTransfer:e.dataTransfer});
+ targ.dispatchEvent(evt);
+ evt = new DragEvent('dragleave', {dataTransfer:e.dataTransfer});
+ targ.dispatchEvent(evt);
+ evt = new DragEvent('drop', {dataTransfer:e.dataTransfer});
+ targ.dispatchEvent(evt);
+ evt = new DragEvent('dragend', {dataTransfer:e.dataTransfer});
+ targ.dispatchEvent(evt);
+ };
+ targ.ondragstart = function (e) {
+ evtdone[e.type] = true;
+ };
+ targ.ondragenter = targ.ondragover = targ.ondrop = function (e) {
+ e.preventDefault();
+ evtdone[e.type] = true;
+ };
+ targ.ondrag = targ.ondragleave = function (e) {
+ evtdone[e.type] = true;
+ };
+ targ.ondragend = function (e) {
+ evtdone[e.type] = true;
+ };
+ var creatorevent = document.createEvent('DragEvent');
+ creatorevent.initDragEvent('dragstart', true, true, window, 1, 0, 0, 0, 0, false, false, false, false, 1, document.body, {});
+ dragsource.dispatchEvent(creatorevent);
+ assert_true(evtdone.dragstart, 'dragstart must fire');
+ assert_true(evtdone.drag, 'drag must fire');
+ assert_true(evtdone.dragend, 'dragend must fire');
+ assert_false(evtdone.dragenter, 'dragenter must not fire');
+ assert_false(evtdone.dragover, 'dragover must not fire');
+ assert_false(evtdone.dragleave, 'dragleave must not fire');
+ assert_false(evtdone.drop, 'drop must not fire');
+}, "allowTargetOrigin with fake dataTransfer should block events");
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/HELPER-mustallow.html b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/HELPER-mustallow.html
new file mode 100644
index 00000000000..0a68b74483f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/HELPER-mustallow.html
@@ -0,0 +1,26 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Must be allowed</title>
+ <style type="text/css">
+html { background: blue; }
+html, body { margin: 0; padding: 0; height: 100%; width: 100%; }
+ </style>
+ </head>
+ <body>
+ <script type="text/javascript">
+if( location.search && location.search.indexOf('domain') != -1 ) {
+ document.domain = location.hostname.replace(/^[^.]+\./,'');
+}
+var seentypes = {};
+document.body.ondragenter = document.body.ondragover = document.body.ondrop = function (e) {
+ e.preventDefault();
+ if( e.type == 'drop' ) {
+ document.body.innerHTML = ( seentypes.dragenter && seentypes.dragover && e.dataTransfer.getData('text') == 'dummy text' ) ? 'PASS' : 'FAIL';
+ } else {
+ seentypes[e.type] = true;
+ }
+}
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/HELPER-mustblock.html b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/HELPER-mustblock.html
new file mode 100644
index 00000000000..dd467f55f08
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/HELPER-mustblock.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Must be blocked</title>
+ <style type="text/css">
+html { background: fuchsia; }
+html, body { margin: 0; padding: 0; height: 100%; width: 100%; }
+ </style>
+ </head>
+ <body>
+ <script type="text/javascript">
+if( location.search && location.search.indexOf('domain') != -1 ) {
+ document.domain = location.hostname.replace(/^[^.]+\./,'');
+}
+document.body.ondragenter = document.body.ondragleave = document.body.ondragover = document.body.ondrop = function (e) {
+ e.preventDefault();
+ document.body.innerHTML = 'FAIL';
+}
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/HELPER-showorigin.html b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/HELPER-showorigin.html
new file mode 100644
index 00000000000..ea071e81124
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/target-origin/HELPER-showorigin.html
@@ -0,0 +1,31 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Readout of .origin</title>
+ <style type="text/css">
+html, body { margin: 0; padding: 0; }
+div { height: 100px; width: 100px; background: blue; }
+ </style>
+ <script type="text/javascript">
+window.onload = function () {
+ var blue = document.getElementsByTagName('div')[0];
+ blue.ondragenter = blue.ondragover = function (e) {
+ e.preventDefault();
+ };
+ blue.ondrop = function (e) {
+ e.preventDefault();
+ if( e.dataTransfer.origin === 'null' ) {
+ document.body.innerHTML = 'null (string)';
+ } else {
+ document.body.innerHTML = e.dataTransfer.origin;
+ }
+ };
+};
+ </script>
+ </head>
+ <body>
+
+ <div></div>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/the-dragevent-interface/dragevent-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/the-dragevent-interface/dragevent-manual.html
new file mode 100644
index 00000000000..aafe83205fd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/the-dragevent-interface/dragevent-manual.html
@@ -0,0 +1,99 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset='utf-8'>
+ <title>HTML Test: DragEvent</title>
+ <link rel='author' title='Intel' href='http://www.intel.com'>
+ <link rel='help' href='https://html.spec.whatwg.org/multipage/#dndevents'>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+ <style>
+ #drop {
+ border: 2px solid black;
+ width: 100px;
+ height: 100px;
+ padding: 20px;
+ }
+ #drag {
+ color: blue;
+ margin: 20px auto;
+ }
+ </style>
+ </head>
+
+ <body>
+ <div>Select and drag the blue text to rectangular box.</div>
+ <div id='drag' draggable>blue text</div>
+ <div id='drop' dropzone='copy string:text/plain'></div>
+ <div id='log'> </div>
+
+ <script>
+ var drag, element;
+ var Events = ['ondragstart', 'ondrag', 'ondragover', 'ondragenter', 'ondragexit', 'ondragleave', 'ondrop', 'ondragend'];
+
+ setup(function() {
+ drag = document.querySelector('#drag');
+ element = document.createElement('div');
+ }, {explicit_done: true, explicit_timeout: true});
+
+ for(var i=0; i< Events.length; i++) {
+ test(function() {
+ assert_true(Events[i] in document, 'Check ' + Events[i] + ' in document');
+ }, 'Check ' + Events[i] + ' in document');
+ }
+
+ test(function() {
+ assert_inherits(element, 'ondragstart', 'Check if have ondragstart attribute');
+ }, 'Check if have ondragstart attribute');
+
+ test(function() {
+ assert_inherits(element, 'ondrag', 'Check if have ondrag attribute');
+ }, 'Check if have ondrag attribute');
+
+ test(function() {
+ assert_inherits(element, 'ondragenter', 'Check if have ondragenter attribute');
+ }, 'Check if have ondragenter attribute');
+
+ test(function() {
+ assert_inherits(element, 'ondragexit', 'Check if have ondragexit attribute');
+ }, 'Check if have ondragexit attribute');
+
+ test(function() {
+ assert_inherits(element, 'ondragleave', 'Check if have dragleave attribute');
+ }, 'Check if have dragleave attribute');
+
+ test(function() {
+ assert_inherits(element, 'ondragover', 'Check if have dragover attribute');
+ }, 'Check if have dragover attribute');
+
+ test(function() {
+ assert_inherits(element, 'ondrop', 'Check if have ondrop attribute');
+ }, 'Check if have ondrop attribute');
+
+ test(function() {
+ assert_inherits(element, 'ondragend', 'Check if have ondragend attribute');
+ }, 'Check if have ondragend attribute');
+
+ on_event(drag, 'dragstart', function(event) {
+ test(function() {
+ assert_equals(event.type, 'dragstart', 'Check if the dragstart event captured');
+ }, 'Check if the dragstart event captured');
+ });
+
+ on_event(drag, 'dragenter', function(event) {
+ test(function() {
+ assert_equals(event.type, 'dragenter', 'Check if the dragenter event captured');
+ }, 'Check if the dragenter event captured');
+ });
+
+ on_event(drag, 'dragend', function(event) {
+ test(function() {
+ assert_equals(event.type, 'dragend', 'Check if the dragend event captured');
+ }, 'Check if the dragend event captured');
+ done();
+ });
+
+
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/the-draggable-attribute/draggable_attribute.html b/tests/wpt/web-platform-tests/html/editing/dnd/the-draggable-attribute/draggable_attribute.html
new file mode 100644
index 00000000000..cd9073e1055
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/the-draggable-attribute/draggable_attribute.html
@@ -0,0 +1,123 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset='utf-8'>
+ <title>HTML Test: draggable_attribute</title>
+ <link rel='author' title='Intel' href='http://www.intel.com'>
+ <link rel='help' href='https://html.spec.whatwg.org/multipage/#the-draggable-attribute'>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+ <script src='/html/semantics/interfaces.js'></script>
+ </head>
+
+ <body>
+ <div id='log'> </div>
+
+ <script>
+ elements.forEach(function(a) {
+ test(function() {
+ var eElement = document.createElement(a[0]);
+ assert_inherits(eElement, 'draggable', 'Element ' + a[0] +' should have draggable property');
+ }, 'Element ' + a[0] +' should have draggable property');
+ });
+
+ function run_test(element, element_name, exp) {
+ if (exp) {
+ assert_true(element.draggable, 'Element ' + element_name +' should be draggable');
+ } else {
+ assert_false(element.draggable, 'Element ' + element_name +' should not be draggable');
+ }
+ }
+
+ function run_idl_test(element, element_name, exp) {
+ if (exp) {
+ assert_equals(element.getAttribute('draggable'), 'true', 'Element ' + element_name +' should be draggable');
+ } else {
+ assert_equals(element.getAttribute('draggable'), 'false', 'Element ' + element_name +' should not be draggable');
+ }
+ }
+
+ elements.forEach(function(a) {
+
+ test(function() {
+ //Default values for elements
+ //If the element is an img element, or, if the element is an a element with an href content attribute,
+ //the draggable IDL attribute must return true.
+ var eElement = document.createElement(a[0]);
+ switch (a[0]) {
+ case 'a':
+ eElement.setAttribute('href', 'http://w3.org');
+ run_test(eElement, 'a', true);
+ break;
+ case 'img':
+ run_test(eElement, 'img', true);
+ break;
+ default:
+ run_test(eElement, a[0], false);
+ }
+
+ //If an element's draggable content attribute has the state true,
+ //the draggable IDL attribute must return true.
+ eElement.setAttribute('draggable', 'true');
+ run_test(eElement, a[0] + ' draggable=\'true\'', true);
+
+ //If an element's draggable content attribute has the state false,
+ //the draggable IDL attribute must return false.
+ eElement.setAttribute('draggable', 'false');
+ run_test(eElement, a[0] + ' draggable=\'false\'', false);
+
+ //auto values for elements
+ //The element's draggable content attribute has the state auto.
+ //If the element is an img element, or, if the element is an a element with an href content attribute,
+ //the draggable IDL attribute must return true.
+ switch (a[0]) {
+ case 'a':
+ eElement.setAttribute('href', 'http://w3.org');
+ eElement.setAttribute('draggable', 'auto');
+ run_test(eElement, 'Element ' + 'a' + ' draggable=\'auto\'', true);
+ break;
+ case 'img':
+ eElement.setAttribute('draggable', 'auto');
+ run_test(eElement, 'Element ' + 'img' + ' draggable=\'auto\'', true);
+ break;
+ default:
+ run_test(eElement, 'Element ' + a[0] + ' draggable=\'auto\'', false);
+ }
+
+ //Foo values for elements
+ //The element's draggable content attribute value is not enumerated (true, false, auto) but unexpected.
+ //Fallback to defaults
+ switch (a[0]) {
+ case 'a':
+ eElement.setAttribute('href', 'http://w3.org');
+ eElement.setAttribute('draggable', 'foo');
+ run_test(eElement, 'Element ' + 'a' + ' draggable=\'foo\'', true);
+ break;
+ case 'img':
+ eElement.setAttribute('draggable', 'foo');
+ run_test(eElement, 'Element ' + 'img' + ' draggable=\'foo\'', true);
+ break;
+ default:
+ run_test(eElement, 'Element ' + a[0] + ' draggable=\'foo\'', false);
+ }
+
+ //An element with a draggable attribute should also have a title attribute
+ //that names the element for the purpose of non-visual interactions.
+ eElement.setAttribute('title', 'foo as title value');
+ assert_equals(typeof eElement.title, 'string', '<' + a[0] + '> draggable block has title attribute');
+
+ //If the draggable IDL attribute is set to the value false,
+ //the draggable content attribute must be set to the literal value false.
+ eElement.draggable = false;
+ run_idl_test(eElement, a[0] + '.getAttribute(\'draggable\') is \'false\'', false);
+
+ //If the draggable IDL attribute is set to the value true,
+ //the draggable content attribute must be set to the literal value true.
+ eElement.draggable = true;
+ run_idl_test(eElement, a[0] + '.getAttribute(\'draggable\') is \'true\'', true);
+ }, 'Element ' + a[0] +' draggable attribute test');
+
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute.html b/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute.html
new file mode 100644
index 00000000000..feb73eccfe7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset='utf-8'>
+ <title>HTML Test: dropzone_attribute</title>
+ <link rel='author' title='Intel' href='http://www.intel.com'>
+ <link rel='help' href='https://html.spec.whatwg.org/multipage/#the-dropzone-attribute'>
+ <meta name="flags" content="may">
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+ </head>
+
+ <body>
+ <div id='log'> </div>
+
+ <script>
+ var drop_element;
+
+ setup(function() { drop_element = document.createElement('div'); });
+
+ test(function() {
+ //Empty values for elements
+ drop_element.dropzone = '';
+ assert_not_equals(drop_element.dropzone, undefined, 'div.dropzone should not be undefined if it\'s been set');
+ }, 'div.dropzone should not be undefined if it\'s been set');
+
+ test(function() {
+ drop_element.dropzone = null;
+ assert_not_equals(drop_element.dropzone, null, 'div.dropzone should not be null');
+ }, 'div.dropzone should not be null');
+
+ test(function() {
+ //The dropzone IDL attribute must reflect the content attribute of the same name.
+ drop_element.setAttribute('dropzone', 'copy file:image/png file:image/gif file:image/jpeg');
+ assert_equals(drop_element.dropzone, 'copy file:image/png file:image/gif file:image/jpeg', 'div dropzone idl attribute must reflect the content attribute of the same name');
+ }, 'div dropzone idl attribute must reflect the content attribute of the same name');
+
+ test(function() {
+ //The dropzone content attribute is set to the literal value when the idl attribute value is set.
+ drop_element.dropzone = 'copy file:image/png file:image/gif file:image/jpeg';
+ assert_equals(drop_element.getAttribute('dropzone'), 'copy file:image/png file:image/gif file:image/jpeg', 'div dropzone content attribute is set to the literal value');
+ }, 'div dropzone content attribute is set to the literal value');
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_data_item_file_type-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_data_item_file_type-manual.html
new file mode 100644
index 00000000000..9027559dc2c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_data_item_file_type-manual.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset='utf-8'>
+ <title>HTML Test: dropzone_attribute_data_item_file_type</title>
+ <link rel='author' title='Intel' href='http://www.intel.com'>
+ <link rel='help' href='https://html.spec.whatwg.org/multipage/#the-dropzone-attribute'>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+ <style>
+ #drop {
+ border: 2px solid black;
+ width: 160px;
+ height: 160px;
+ padding: 20px;
+ color: white;
+ }
+ img {
+ margin: 20px auto;
+ }
+ </style>
+ </head>
+
+ <body>
+ <img src='/images/blue.png' alt='blue image' />
+ <div>Save the blue image (image/png) above to your desktop, drag the image from desktop to the blue text to rectangular box in browser.</div>
+ <div id='drop' dropzone='copy file:image/png'></div>
+ <div id='log'> </div>
+
+ <script>
+ var drop;
+ setup(function() {
+ drop = document.querySelector('#drop');
+ }, {explicit_done: true, explicit_timeout: true});
+
+ on_event(drop, 'drop', function(event) {
+ var item = event.dataTransfer.items[0];
+ test(function() {
+ assert_equals(item.type, 'image/png', 'data item type is "image/png"');
+ }, 'data item type is "image/png"');
+ done();
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_data_item_kind_file-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_data_item_kind_file-manual.html
new file mode 100644
index 00000000000..7a77c12414f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_data_item_kind_file-manual.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset='utf-8'>
+ <title>HTML Test: dropzone_attribute_data_item_kind_file</title>
+ <link rel='author' title='Intel' href='http://www.intel.com'>
+ <link rel='help' href='https://html.spec.whatwg.org/multipage/#the-dropzone-attribute'>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+ <style>
+ #drop {
+ border: 2px solid black;
+ width: 160px;
+ height: 160px;
+ padding: 20px;
+ color: white;
+ }
+ img {
+ margin: 20px auto;
+ }
+ </style>
+ </head>
+
+ <body>
+ <img src='/images/blue.png' alt='blue image' />
+ <div>Save the blue image (image/png) above to your desktop, drag the image from desktop to the blue text to rectangular box in browser.</div>
+ <div id='drop' dropzone='copy file:image/png'></div>
+ <div id='log'> </div>
+
+ <script>
+ var drop;
+ setup(function() {
+ drop = document.querySelector('#drop');
+ }, {explicit_done: true, explicit_timeout: true});
+
+ on_event(drop, 'drop', function(event) {
+ var item = event.dataTransfer.items[0];
+ test(function() {
+ assert_equals(item.kind, 'file', 'data item kind is file');
+ }, 'data item kind is file');
+ done();
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_data_item_kind_string-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_data_item_kind_string-manual.html
new file mode 100644
index 00000000000..b8a22e613bb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_data_item_kind_string-manual.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset='utf-8'>
+ <title>HTML Test: dropzone_attribute_data_item_kind_string</title>
+ <link rel='author' title='Intel' href='http://www.intel.com'>
+ <link rel='help' href='https://html.spec.whatwg.org/multipage/#the-dropzone-attribute'>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+ <style>
+ #drop {
+ border: 2px solid black;
+ width: 100px;
+ height: 100px;
+ padding: 20px;
+ }
+ #select {
+ color: blue;
+ margin: 20px auto;
+ }
+ </style>
+ </head>
+
+ <body>
+ <div>Select and drag the blue text to rectangular box.</div>
+ <div id='select' draggable>blue text</div>
+ <div id='drop' dropzone='copy string:text/plain'></div>
+ <div id='log'> </div>
+
+ <script>
+ var drop;
+ setup(function() {
+ drop = document.querySelector('#drop');
+ }, {explicit_done: true, explicit_timeout: true});
+
+ on_event(drop, 'drop', function(event) {
+ var item = event.dataTransfer.items[0];
+ test(function() {
+ assert_equals(item.kind, 'string', 'data item kind is string');
+ }, 'data item kind is string');
+ done();
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_data_item_string_type-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_data_item_string_type-manual.html
new file mode 100644
index 00000000000..7a5dccf4e2b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_data_item_string_type-manual.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset='utf-8'>
+ <title>HTML Test: dropzone_attribute_data_item_string_type</title>
+ <link rel='author' title='Intel' href='http://www.intel.com'>
+ <link rel='help' href='https://html.spec.whatwg.org/multipage/#the-dropzone-attribute'>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+ <style>
+ #drop {
+ border: 2px solid black;
+ width: 100px;
+ height: 100px;
+ padding: 20px;
+ }
+ #select {
+ color: blue;
+ margin: 20px auto;
+ }
+ </style>
+ </head>
+
+ <body>
+ <div>Select and drag the blue text to rectangular box.</div>
+ <div id='select' draggable>blue text</div>
+ <div id='drop' dropzone='copy string:text/plain'></div>
+ <div id='log'> </div>
+
+ <script>
+ var drop;
+ setup(function() {
+ drop = document.querySelector('#drop');
+ }, {explicit_done: true, explicit_timeout: true});
+
+ on_event(drop, 'drop', function(event) {
+ var item = event.dataTransfer.items[0];
+ test(function() {
+ assert_equals(item.type, 'text/plain', 'data item type is "text/plain"');
+ }, 'data item type is "text/plain"');
+ done();
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_inputbox_element-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_inputbox_element-manual.html
new file mode 100644
index 00000000000..f80604afa29
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_inputbox_element-manual.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset='utf-8'>
+ <title>HTML Test: dropzone_attribute_inputbox_element</title>
+ <link rel='author' title='Intel' href='http://www.intel.com'>
+ <link rel='help' href='https://html.spec.whatwg.org/multipage/#the-dropzone-attribute'>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+ <style>
+ #drop {
+ border: 2px solid black;
+ width: 100px;
+ height: 100px;
+ padding: 20px;
+ }
+ input {
+ color: blue;
+ margin: 20px auto;
+ }
+ </style>
+ </head>
+
+ <body>
+ <div>Select all the inputbox text then drag to rectangular box.</div>
+ <input draggable='true' type='text' value='hello world'></input>
+ <div id='drop' dropzone='move string:text/plain'></div>
+ <div id='log'> </div>
+
+ <script>
+ var drop;
+ setup(function() {
+ drop = document.querySelector('#drop');
+ }, {explicit_done: true, explicit_timeout: true});
+
+ on_event(drop, 'drop', function(event) {
+
+ test(function() {
+ assert_equals(event.dataTransfer.dropEffect, 'move', 'dropzone content attribute value is "move"');
+ }, 'dropzone content attribute value is "move"');
+
+ test(function() {
+ var item = event.dataTransfer.items[0];
+ assert_equals(event.dataTransfer.getData(item.type), 'hello world', 'The dropped string value is the inputbox text you selected.');
+ }, 'The dropped string value is the inputbox text you selected.');
+
+ done();
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_inputbox_element_dbcs-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_inputbox_element_dbcs-manual.html
new file mode 100644
index 00000000000..a7f8ad1aa71
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_inputbox_element_dbcs-manual.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset='utf-8'>
+ <title>HTML Test: dropzone_attribute_inputbox_element_dbcs</title>
+ <link rel='author' title='Intel' href='http://www.intel.com'>
+ <link rel='help' href='https://html.spec.whatwg.org/multipage/#the-dropzone-attribute'>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+ <style>
+ #drop {
+ border: 2px solid black;
+ width: 100px;
+ height: 100px;
+ padding: 20px;
+ }
+ input {
+ color: blue;
+ margin: 20px auto;
+ }
+ </style>
+ </head>
+
+ <body>
+ <div>Select all the inputbox DBCS (Double Byte Character Set) text then drag to rectangular box.</div>
+ <input draggable='true' type='text' value='您好,互联网。'></input>
+ <div id='drop' dropzone='move string:text/plain'></div>
+ <div id='log'> </div>
+
+ <script>
+ var drop;
+ setup(function() {
+ drop = document.querySelector('#drop');
+ }, {explicit_done: true, explicit_timeout: true});
+
+ on_event(drop, 'drop', function(event) {
+ test(function() {
+ var item = item = event.dataTransfer.items[0];
+ assert_equals(event.dataTransfer.getData(item.type), '您好,互联网。', 'The dropped string value is the inputbox text you selected.');
+ }, 'The dropped string value is the inputbox text you selected.');
+
+ done();
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_link_element-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_link_element-manual.html
new file mode 100644
index 00000000000..c6e5756ad68
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_link_element-manual.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset='utf-8'>
+ <title>HTML Test: dropzone_attribute_element_link</title>
+ <link rel='author' title='Intel' href='http://www.intel.com'>
+ <link rel='help' href='https://html.spec.whatwg.org/multipage/#the-dropzone-attribute'>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+ <style>
+ #drop {
+ border: 2px solid black;
+ width: 100px;
+ height: 100px;
+ padding: 20px;
+ }
+ div { margin: 20px 0px;}
+ </style>
+ </head>
+
+ <body>
+ <div>Select and drag the all the text of link below to rectangular box.</div>
+ <a href="http://w3.org" title="World Wide Web Consortium">w3.org</a>
+ <div id='drop' dropzone='link string:text/plain'></div>
+ <div id='log'> </div>
+
+ <script>
+ var drop;
+ setup(function() {
+ drop = document.querySelector('#drop');
+ }, {explicit_done: true, explicit_timeout: true});
+
+ on_event(drop, 'drop', function(event) {
+
+ test(function() {
+ assert_equals(event.dataTransfer.dropEffect, 'link', 'dropzone content attribute value is "link"');
+ }, 'dropzone content attribute value is "link"');
+
+ test(function() {
+ var item = item = event.dataTransfer.items[0];
+ assert_equals(event.dataTransfer.getData(item.type), 'w3.org', 'The dropped link value is "w3.org"');
+ }, 'The dropped link value is "w3.org"');
+
+ done();
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_value_case_insensitive_COpy-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_value_case_insensitive_COpy-manual.html
new file mode 100644
index 00000000000..17ec7a36a3e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_value_case_insensitive_COpy-manual.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset='utf-8'>
+ <title>HTML Test: dropzone_attribute_value_case_insensitive_COpy</title>
+ <link rel='author' title='Intel' href='http://www.intel.com'>
+ <link rel='help' href='https://html.spec.whatwg.org/multipage/#the-dropzone-attribute'>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+ <style>
+ #drop {
+ border: 2px solid black;
+ width: 100px;
+ height: 100px;
+ padding: 20px;
+ }
+ #select {
+ color: blue;
+ margin: 20px auto;
+ }
+ </style>
+ </head>
+
+ <body>
+ <div>Select and drag the blue text to rectangular box.</div>
+ <div id='select' draggable>blue text</div>
+ <div id='drop' dropzone='COpy string:text/plain'></div>
+ <div id='log'> </div>
+
+ <script>
+ var drop;
+ setup(function() {
+ drop = document.querySelector('#drop');
+ }, {explicit_done: true, explicit_timeout: true});
+
+ on_event(drop, 'drop', function(event) {
+ test(function() {
+ assert_equals(event.dataTransfer.dropEffect, 'copy', 'dropzone content attribute value is case insensitive_COpy');
+ }, 'dropzone content attribute value is case insensitive_COpy');
+
+ done();
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_value_case_insensitive_STRING-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_value_case_insensitive_STRING-manual.html
new file mode 100644
index 00000000000..f118ba00bcf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_value_case_insensitive_STRING-manual.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset='utf-8'>
+ <title>HTML Test: dropzone_attribute_value_case_insensitive_STRING</title>
+ <link rel='author' title='Intel' href='http://www.intel.com'>
+ <link rel='help' href='https://html.spec.whatwg.org/multipage/#the-dropzone-attribute'>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+ <style>
+ #drop {
+ border: 2px solid black;
+ width: 100px;
+ height: 100px;
+ padding: 20px;
+ }
+ #select {
+ color: blue;
+ margin: 20px auto;
+ }
+ </style>
+ </head>
+
+ <body>
+ <div>Select and drag the blue text to rectangular box.</div>
+ <div id='select' draggable>blue text</div>
+ <div id='drop' dropzone='copy STRING:text/plain'></div>
+ <div id='log'> </div>
+
+ <script>
+ var drop;
+ setup(function() {
+ drop = document.querySelector('#drop');
+ }, {explicit_done: true, explicit_timeout: true});
+
+ on_event(drop, 'drop', function(event) {
+ test(function() {
+ assert_equals(event.dataTransfer.dropEffect, 'copy', 'dropzone content attribute value is case insensitive_STRING');
+ }, 'dropzone content attribute value is case insensitive_STRING');
+
+ done();
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_value_case_insensitive_String_-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_value_case_insensitive_String_-manual.html
new file mode 100644
index 00000000000..9b84803806b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_value_case_insensitive_String_-manual.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset='utf-8'>
+ <title>HTML Test: dropzone_attribute_value_case_insensitive_String</title>
+ <link rel='author' title='Intel' href='http://www.intel.com'>
+ <link rel='help' href='https://html.spec.whatwg.org/multipage/#the-dropzone-attribute'>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+ <style>
+ #drop {
+ border: 2px solid black;
+ width: 100px;
+ height: 100px;
+ padding: 20px;
+ }
+ #select {
+ color: blue;
+ margin: 20px auto;
+ }
+ </style>
+ </head>
+
+ <body>
+ <div>Select and drag the blue text to rectangular box.</div>
+ <div id='select' draggable>blue text</div>
+ <div id='drop' dropzone='link String:text/plain'></div>
+ <div id='log'> </div>
+
+ <script>
+ var drop;
+ setup(function() {
+ drop = document.querySelector('#drop');
+ }, {explicit_done: true, explicit_timeout: true});
+
+ on_event(drop, 'drop', function(event) {
+ test(function() {
+ assert_equals(event.dataTransfer.dropEffect, 'link', 'dropzone content attribute value is case insensitive_String');
+ }, 'dropzone content attribute value is case insensitive_String');
+
+ done();
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_value_case_insensitive_linK-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_value_case_insensitive_linK-manual.html
new file mode 100644
index 00000000000..e4364db7351
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_value_case_insensitive_linK-manual.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset='utf-8'>
+ <title>HTML Test: dropzone_attribute_value_case_insensitive_linK</title>
+ <link rel='author' title='Intel' href='http://www.intel.com'>
+ <link rel='help' href='https://html.spec.whatwg.org/multipage/#the-dropzone-attribute'>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+ <style>
+ #drop {
+ border: 2px solid black;
+ width: 100px;
+ height: 100px;
+ padding: 20px;
+ }
+ #select {
+ color: blue;
+ margin: 20px auto;
+ }
+ </style>
+ </head>
+
+ <body>
+ <div>Select and drag the blue text to rectangular box.</div>
+ <div id='select' draggable>blue text</div>
+ <div id='drop' dropzone='liNK string:text/plain'></div>
+ <div id='log'> </div>
+
+ <script>
+ var drop;
+ setup(function() {
+ drop = document.querySelector('#drop');
+ }, {explicit_done: true, explicit_timeout: true});
+
+ on_event(drop, 'drop', function(event) {
+ test(function() {
+ assert_equals(event.dataTransfer.dropEffect, 'link', 'dropzone content attribute value is case insensitive_linK');
+ }, 'dropzone content attribute value is case insensitive_linK');
+
+ done();
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_value_copy-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_value_copy-manual.html
new file mode 100644
index 00000000000..dcc7c97acd8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_value_copy-manual.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset='utf-8'>
+ <title>HTML Test: dropzone_attribute_value_copy</title>
+ <link rel='author' title='Intel' href='http://www.intel.com'>
+ <link rel='help' href='https://html.spec.whatwg.org/multipage/#the-dropzone-attribute'>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+ <style>
+ #drop {
+ border: 2px solid black;
+ width: 100px;
+ height: 100px;
+ padding: 20px;
+ }
+ #select {
+ color: blue;
+ margin: 20px auto;
+ }
+ </style>
+ </head>
+
+ <body>
+ <div>Select and drag the blue text to rectangular box.</div>
+ <div id='select' draggable>blue text</div>
+ <div id='drop' dropzone='copy string:text/plain'></div>
+ <div id='log'> </div>
+
+ <script>
+ var drop;
+ setup(function() {
+ drop = document.querySelector('#drop');
+ }, {explicit_done: true, explicit_timeout: true});
+
+ on_event(drop, 'drop', function(event) {
+ test(function() {
+ assert_equals(event.dataTransfer.dropEffect, 'copy', 'dropzone content attribute value is "copy"');
+ }, 'dropzone content attribute value is "copy"');
+
+ done();
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_value_foo-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_value_foo-manual.html
new file mode 100644
index 00000000000..f9606f1b9f6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_value_foo-manual.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset='utf-8'>
+ <title>HTML Test: dropzone_attribute_value_foo</title>
+ <link rel='author' title='Intel' href='http://www.intel.com'>
+ <link rel='help' href='https://html.spec.whatwg.org/multipage/#the-dropzone-attribute'>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+ <style>
+ #drop {
+ border: 2px solid black;
+ width: 100px;
+ height: 100px;
+ padding: 20px;
+ }
+ #select {
+ color: blue;
+ margin: 20px auto;
+ }
+ </style>
+ </head>
+
+ <body>
+ <div>Select and drag the blue text to rectangular box.</div>
+ <div id='select' draggable>blue text</div>
+ <div id='drop' dropzone='foo string:text/plain'></div>
+ <div id='log'> </div>
+
+ <script>
+ var drop;
+ setup(function() {
+ drop = document.querySelector('#drop');
+ }, {explicit_done: true, explicit_timeout: true});
+
+ on_event(drop, 'drop', function(event) {
+ test(function() {
+ assert_equals(event.dataTransfer.dropEffect, 'copy', 'dropzone content attribute value is "copy" if it\'s not one of three feedback values (copy, move, and link) specified');
+ }, 'dropzone content attribute value is "copy" if it\'s not one of three feedback values (copy, move, and link) specified');
+
+ done();
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_value_link-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_value_link-manual.html
new file mode 100644
index 00000000000..a4ba8196560
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_value_link-manual.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset='utf-8'>
+ <title>HTML Test: dropzone_attribute_value_link</title>
+ <link rel='author' title='Intel' href='http://www.intel.com'>
+ <link rel='help' href='https://html.spec.whatwg.org/multipage/#the-dropzone-attribute'>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+ <style>
+ #drop {
+ border: 2px solid black;
+ width: 100px;
+ height: 100px;
+ padding: 20px;
+ }
+ #select {
+ color: blue;
+ margin: 20px auto;
+ }
+ </style>
+ </head>
+
+ <body>
+ <div>Select and drag the blue text to rectangular box.</div>
+ <div id='select' draggable>blue text</div>
+ <div id='drop' dropzone='link string:text/plain'></div>
+ <div id='log'> </div>
+
+ <script>
+ var drop;
+ setup(function() {
+ drop = document.querySelector('#drop');
+ }, {explicit_done: true, explicit_timeout: true});
+
+ on_event(drop, 'drop', function(event) {
+ test(function() {
+ assert_equals(event.dataTransfer.dropEffect, 'link', 'dropzone content attribute value is "link"');
+ }, 'dropzone content attribute value is "link"');
+
+ done();
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_value_move-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_value_move-manual.html
new file mode 100644
index 00000000000..dfad88ba615
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_value_move-manual.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset='utf-8'>
+ <title>HTML Test: dropzone_attribute_value_move</title>
+ <link rel='author' title='Intel' href='http://www.intel.com'>
+ <link rel='help' href='https://html.spec.whatwg.org/multipage/#the-dropzone-attribute'>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+ <style>
+ #drop {
+ border: 2px solid black;
+ width: 100px;
+ height: 100px;
+ padding: 20px;
+ }
+ #select {
+ color: blue;
+ margin: 20px auto;
+ }
+ </style>
+ </head>
+
+ <body>
+ <div>Select and drag the blue text to rectangular box.</div>
+ <div id='select' draggable>blue text</div>
+ <div id='drop' dropzone='move string:text/plain'></div>
+ <div id='log'> </div>
+
+ <script>
+ var drop;
+ setup(function() {
+ drop = document.querySelector('#drop');
+ }, {explicit_done: true, explicit_timeout: true});
+
+ on_event(drop, 'drop', function(event) {
+ test(function() {
+ assert_equals(event.dataTransfer.dropEffect, 'move', 'dropzone content attribute value is "move"');
+ }, 'dropzone content attribute value is "move"');
+
+ done();
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_value_multiple_values_foo_bar_move-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_value_multiple_values_foo_bar_move-manual.html
new file mode 100644
index 00000000000..3243774c935
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_value_multiple_values_foo_bar_move-manual.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset='utf-8'>
+ <title>HTML Test: dropzone_attribute_value_multiple_values_foo_bar_move</title>
+ <link rel='author' title='Intel' href='http://www.intel.com'>
+ <link rel='help' href='https://html.spec.whatwg.org/multipage/#the-dropzone-attribute'>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+ <style>
+ #drop {
+ border: 2px solid black;
+ width: 100px;
+ height: 100px;
+ padding: 20px;
+ }
+ #select {
+ color: blue;
+ margin: 20px auto;
+ }
+ </style>
+ </head>
+
+ <body>
+ <div>Select and drag the blue text to rectangular box.</div>
+ <div id='select' draggable>blue text</div>
+ <div id='drop' dropzone='foo bar move string:text/plain'></div>
+ <div id='log'> </div>
+
+ <script>
+ var drop;
+ setup(function() {
+ drop = document.querySelector('#drop');
+ }, {explicit_done: true, explicit_timeout: true});
+
+ on_event(drop, 'drop', function(event) {
+ test(function() {
+ assert_equals(event.dataTransfer.dropEffect, 'move', 'dropzone content attribute value is the first matched value of "foo bar move"');
+ }, 'dropzone content attribute value is the first matched value of "foo bar move"');
+
+ done();
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_value_multiple_values_foo_link-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_value_multiple_values_foo_link-manual.html
new file mode 100644
index 00000000000..fd9e23d03a9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_value_multiple_values_foo_link-manual.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset='utf-8'>
+ <title>HTML Test: dropzone_attribute_value_multiple_values_foo_link</title>
+ <link rel='author' title='Intel' href='http://www.intel.com'>
+ <link rel='help' href='https://html.spec.whatwg.org/multipage/#the-dropzone-attribute'>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+ <style>
+ #drop {
+ border: 2px solid black;
+ width: 100px;
+ height: 100px;
+ padding: 20px;
+ }
+ #select {
+ color: blue;
+ margin: 20px auto;
+ }
+ </style>
+ </head>
+
+ <body>
+ <div>Select and drag the blue text to rectangular box.</div>
+ <div id='select' draggable>blue text</div>
+ <div id='drop' dropzone='foo link string:text/plain'></div>
+ <div id='log'> </div>
+
+ <script>
+ var drop;
+ setup(function() {
+ drop = document.querySelector('#drop');
+ }, {explicit_done: true, explicit_timeout: true});
+
+ on_event(drop, 'drop', function(event) {
+ test(function() {
+ assert_equals(event.dataTransfer.dropEffect, 'link', 'dropzone content attribute value is the first matched value of "foo link"');
+ }, 'dropzone content attribute value is the first matched value of "foo link"');
+
+ done();
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_value_multiple_values_move_copy-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_value_multiple_values_move_copy-manual.html
new file mode 100644
index 00000000000..50ea9369f2f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_value_multiple_values_move_copy-manual.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset='utf-8'>
+ <title>HTML Test: dropzone_attribute_value_multiple_values_move_copy</title>
+ <link rel='author' title='Intel' href='http://www.intel.com'>
+ <link rel='help' href='https://html.spec.whatwg.org/multipage/#the-dropzone-attribute'>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+ <style>
+ #drop {
+ border: 2px solid black;
+ width: 100px;
+ height: 100px;
+ padding: 20px;
+ }
+ #select {
+ color: blue;
+ margin: 20px auto;
+ }
+ </style>
+ </head>
+
+ <body>
+ <div>Select and drag the blue text to rectangular box.</div>
+ <div id='select' draggable>blue text</div>
+ <div id='drop' dropzone='move copy string:text/plain'></div>
+ <div id='log'> </div>
+
+ <script>
+ var drop;
+ setup(function() {
+ drop = document.querySelector('#drop');
+ }, {explicit_done: true, explicit_timeout: true});
+
+ on_event(drop, 'drop', function(event) {
+ test(function() {
+ assert_equals(event.dataTransfer.dropEffect, 'move', 'dropzone content attribute value is the first matched value of "move copy"');
+ }, 'dropzone content attribute value is the first matched value of "move copy"');
+
+ done();
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_value_not_specified-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_value_not_specified-manual.html
new file mode 100644
index 00000000000..152c30022b0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_value_not_specified-manual.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset='utf-8'>
+ <title>HTML Test: dropzone_attribute_value_not_specified</title>
+ <link rel='author' title='Intel' href='http://www.intel.com'>
+ <link rel='help' href='https://html.spec.whatwg.org/multipage/#the-dropzone-attribute'>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+ <style>
+ #drop {
+ border: 2px solid black;
+ width: 100px;
+ height: 100px;
+ padding: 20px;
+ }
+ #select {
+ color: blue;
+ margin: 20px auto;
+ }
+ </style>
+ </head>
+
+ <body>
+ <div>Select and drag the blue text to rectangular box.</div>
+ <div id='select' draggable>blue text</div>
+ <div id='drop' dropzone='string:text/plain'></div>
+ <div id='log'> </div>
+
+ <script>
+ var drop;
+ setup(function() {
+ drop = document.querySelector('#drop');
+ }, {explicit_done: true, explicit_timeout: true});
+
+ on_event(drop, 'drop', function(event) {
+ test(function() {
+ assert_equals(event.dataTransfer.dropEffect, 'copy', 'dropzone content attribute value is "copy" if it\'s not specified');
+ }, 'dropzone content attribute value is "copy" if it\'s not specified');
+
+ done();
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_value_unordered_unique_space_separated-manual.html b/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_value_unordered_unique_space_separated-manual.html
new file mode 100644
index 00000000000..24c5b032ab9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/dnd/the-dropzone-attribute/dropzone_attribute_value_unordered_unique_space_separated-manual.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset='utf-8'>
+ <title>HTML Test: dropzone_attribute_value_unordered_unique_space_separated</title>
+ <link rel='author' title='Intel' href='http://www.intel.com'>
+ <link rel='help' href='https://html.spec.whatwg.org/multipage/#the-dropzone-attribute'>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+ <style>
+ #drop {
+ border: 2px solid black;
+ width: 100px;
+ height: 100px;
+ padding: 20px;
+ }
+ #select {
+ color: blue;
+ margin: 20px auto;
+ }
+ </style>
+ </head>
+
+ <body>
+ <div>Select and drag the blue text to rectangular box.</div>
+ <div id='select' draggable>blue text</div>
+ <div id='drop' dropzone='string:text/plain copy'></div>
+ <div id='log'> </div>
+
+ <script>
+ var drop;
+ setup(function() {
+ drop = document.querySelector('#drop');
+ }, {explicit_done: true, explicit_timeout: true});
+
+ on_event(drop, 'drop', function(event) {
+
+ test(function() {
+ assert_equals(event.dataTransfer.dropEffect, 'copy', 'unordered_unique_space_separated "string:text/plain copy", drop effect is copy');
+ }, 'dropzone content attribute value is unordered_unique_space_separated "string:text/plain copy", drop effect is copy');
+ test(function() {
+ item = event.dataTransfer.items[0];
+ assert_equals(item.kind, 'string', 'unordered_unique_space_separated "string:text/plain copy", data item kind is string');
+ }, 'dropzone content attribute value is unordered_unique_space_separated "string:text/plain copy", data item kind is string');
+ test(function() {
+ item = event.dataTransfer.items[0];
+ assert_equals(item.type, 'text/plain', 'dropzone content attribute value is unordered_unique_space_separated "string:text/plain copy", data item type is "text/plain"');
+ }, 'dropzone content attribute value is unordered_unique_space_separated "string:text/plain copy", data item type is "text/plain"');
+ done();
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/editing-0/.gitkeep b/tests/wpt/web-platform-tests/html/editing/editing-0/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/editing-0/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/editing/editing-0/best-practices-for-in-page-editors/.gitkeep b/tests/wpt/web-platform-tests/html/editing/editing-0/best-practices-for-in-page-editors/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/editing-0/best-practices-for-in-page-editors/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/editing/editing-0/contenteditable/.gitkeep b/tests/wpt/web-platform-tests/html/editing/editing-0/contenteditable/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/editing-0/contenteditable/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/editing/editing-0/contenteditable/contentEditable-invalidvalue.html b/tests/wpt/web-platform-tests/html/editing/editing-0/contenteditable/contentEditable-invalidvalue.html
new file mode 100644
index 00000000000..85b71043e16
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/editing-0/contenteditable/contentEditable-invalidvalue.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>contentEditable setter: invalid value</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#contenteditable">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+ var el = document.createElement("div");
+ test(function(){
+ assert_throws("SyntaxError", function() {
+ el.contentEditable = "foobar";
+ });
+ }, "setting contentEditable to an invalid value throws a SyntaxError Exception");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/editing/editing-0/contenteditable/user-interaction-editing-contenteditable.html b/tests/wpt/web-platform-tests/html/editing/editing-0/contenteditable/user-interaction-editing-contenteditable.html
new file mode 100644
index 00000000000..9ef867b2d3f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/editing-0/contenteditable/user-interaction-editing-contenteditable.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Editing: contentEditable attribute test</title>
+ <link rel="author" title="Baidu" href="mailto: guopengcheng@baidu.com"/>
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#contenteditable"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <div id="log"></div>
+ </head>
+ <body>
+ <script type="text/javascript">
+ var testElement = document.createElement("testElement");
+ test(function() {
+ assert_equals(testElement.contentEditable,"inherit", "check for testElement.contentEditable value");
+ }, "no contentEditable attribute");
+ testElement.setAttribute("contentEditable", "");
+ test(function() {
+ assert_true(testElement.isContentEditable, "check for testElement.isContentEditable value");
+ assert_equals(testElement.contentEditable,"true", "check for testElement.contentEditable value");
+ }, "empty contentEditable attribute");
+ testElement.contentEditable="true";
+ test(function() {
+ assert_true(testElement.isContentEditable, "check for testElement.isContentEditable value");
+ assert_equals(testElement.contentEditable,"true", "check for testElement.contentEditable value");
+ }, "set contentEditable = \"true\"");
+ testElement.contentEditable="false";
+ test(function() {
+ assert_false(testElement.isContentEditable, "check for testElement.isContentEditable value");
+ assert_equals(testElement.contentEditable,"false", "check for testElement.contentEditable value");
+ }, "set contentEditable = \"false\"");
+ testElement.contentEditable="inherit";
+ test(function() {
+ assert_equals(testElement.contentEditable,"inherit", "check for testElement.contentEditable value");
+ }, "set contentEditable = \"inherit\"");
+ var childElement = document.createElement("childElement");
+ testElement.appendChild(childElement);
+ testElement.contentEditable="true";
+ test(function() {
+ assert_true(testElement.isContentEditable, "check for testElement.isContentEditable value");
+ assert_equals(testElement.contentEditable,"true", "check for testElement.contentEditable value");
+ assert_true(childElement.isContentEditable, "check for childElement.isContentEditable value");
+ assert_equals(childElement.contentEditable,"inherit", "check for childElement.contentEditable value");
+ }, "set parent element contentEditable = \"true\"");
+ testElement.contentEditable="false";
+ test(function() {
+ assert_false(testElement.isContentEditable, "check for testElement.isContentEditable value");
+ assert_equals(testElement.contentEditable,"false", "check for testElement.contentEditable value");
+ assert_false(childElement.isContentEditable, "check for childElement.isContentEditable value");
+ assert_equals(childElement.contentEditable,"inherit", "check for childElement.contentEditable value");
+ }, "set parent element contentEditable = \"false\"");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/editing-0/editing-apis/.gitkeep b/tests/wpt/web-platform-tests/html/editing/editing-0/editing-apis/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/editing-0/editing-apis/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/editing/editing-0/making-entire-documents-editable-the-designmode-idl-attribute/.gitkeep b/tests/wpt/web-platform-tests/html/editing/editing-0/making-entire-documents-editable-the-designmode-idl-attribute/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/editing-0/making-entire-documents-editable-the-designmode-idl-attribute/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/editing/editing-0/making-entire-documents-editable-the-designmode-idl-attribute/original-id.json b/tests/wpt/web-platform-tests/html/editing/editing-0/making-entire-documents-editable-the-designmode-idl-attribute/original-id.json
new file mode 100644
index 00000000000..8b7c4b838c2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/editing-0/making-entire-documents-editable-the-designmode-idl-attribute/original-id.json
@@ -0,0 +1 @@
+{"original_id":"making-entire-documents-editable:-the-designmode-idl-attribute"} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/editing/editing-0/making-entire-documents-editable-the-designmode-idl-attribute/user-interaction-editing-designMode.html b/tests/wpt/web-platform-tests/html/editing/editing-0/making-entire-documents-editable-the-designmode-idl-attribute/user-interaction-editing-designMode.html
new file mode 100644
index 00000000000..f73ea73260e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/editing-0/making-entire-documents-editable-the-designmode-idl-attribute/user-interaction-editing-designMode.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Editing: designMode attribute test</title>
+ <link rel="author" title="Baidu" href="mailto: guopengcheng@baidu.com"/>
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#making-entire-documents-editable:-the-designmode-idl-attribute"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <div id="log"></div>
+ </head>
+ <body>
+ <script type="text/javascript">
+ test(function() {
+ assert_equals(document.designMode, "off", "check for designMode value");
+ }, "initial designMode attribute");
+ document.designMode="on";
+ test(function() {
+ assert_equals(document.designMode, "on", "check for designMode value");
+ }, "set designMode = \"on\"");
+ document.designMode="off";
+ test(function() {
+ assert_equals(document.designMode,"off", "check for designMode value");
+ }, "set designMode = \"off\"");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/editing-0/spelling-and-grammar-checking/.gitkeep b/tests/wpt/web-platform-tests/html/editing/editing-0/spelling-and-grammar-checking/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/editing-0/spelling-and-grammar-checking/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/editing/editing-0/spelling-and-grammar-checking/user-interaction-editing-spellcheck.html b/tests/wpt/web-platform-tests/html/editing/editing-0/spelling-and-grammar-checking/user-interaction-editing-spellcheck.html
new file mode 100644
index 00000000000..c8bdaafdb89
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/editing-0/spelling-and-grammar-checking/user-interaction-editing-spellcheck.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Editing: spellcheck attribute test</title>
+ <link rel="author" title="Baidu" href="mailto: guopengcheng@baidu.com"/>
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#spelling-and-grammar-checking"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <textarea id="testText1" spellcheck="true">Test textarea with spellcheck is true</textarea>
+ <textarea id="testText2" spellcheck="false">Test textarea with spellcheck is false</textarea>
+ <script type="text/javascript">
+ test(function() {
+ assert_true(document.getElementById("testText1").spellcheck, "check for testText1 spellcheck value");
+ assert_false(document.getElementById("testText2").spellcheck, "check for testText2 spellcheck value");
+ }, "Getting spellcheck IDL attribute");
+ test(function() {
+ var testElement = document.createElement("testElement");
+ testElement.contentEditable = true;
+ testElement.spellcheck = true;
+ assert_true(testElement.spellcheck, "check for testElement.spellcheck value");
+ assert_equals(testElement.getAttribute("spellcheck"), "true");
+ }, "Setting spellcheck IDL attribute to true");
+ test(function() {
+ var testElement = document.createElement("testElement");
+ testElement.contentEditable = true;
+ testElement.spellcheck = false;
+ assert_false(testElement.spellcheck, "check for testText2 spellcheck value");
+ assert_equals(testElement.getAttribute("spellcheck"), "false");
+ }, "Setting spellcheck IDL attribute to false");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/editing/focus/.gitkeep b/tests/wpt/web-platform-tests/html/editing/focus/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/focus/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/editing/focus/document-level-focus-apis/.gitkeep b/tests/wpt/web-platform-tests/html/editing/focus/document-level-focus-apis/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/focus/document-level-focus-apis/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/editing/focus/document-level-focus-apis/document-level-apis.html b/tests/wpt/web-platform-tests/html/editing/focus/document-level-focus-apis/document-level-apis.html
new file mode 100644
index 00000000000..2d8c49c7f61
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/focus/document-level-focus-apis/document-level-apis.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: focus - document-level APIs</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#document-level-focus-apis">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<input id="test">
+<script>
+
+test(function () {
+ assert_equals(document.activeElement, document.body, "The active element should be the body element.");
+}, "The body element must be the active element if no element is focused");
+
+test(function () {
+ document.getElementById("test").focus();
+ assert_equals(document.activeElement, document.getElementById("test"), "The active element should be the input element.");
+}, "The element must be the active element if it is focused");
+
+function frame_load () {
+ test(function () {
+ document.getElementById("fr").contentDocument.getElementById("ipt").focus();
+ assert_equals(document.activeElement, document.getElementById("fr"), "The active element should be the iframe element.");
+ }, "When a child browsing context is focused, its browsing context container is also focused");
+}
+
+test(function () {
+ var doc = document.implementation.createHTMLDocument("test");
+ assert_false(doc.hasFocus(), "The hasFocus() method should return false.");
+}, "The hasFocus() method must return false if the Document has no browsing context");
+
+</script>
+<iframe id="fr" src="test.html" onload="frame_load()"></iframe>
diff --git a/tests/wpt/web-platform-tests/html/editing/focus/document-level-focus-apis/test.html b/tests/wpt/web-platform-tests/html/editing/focus/document-level-focus-apis/test.html
new file mode 100644
index 00000000000..90d63e51e93
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/focus/document-level-focus-apis/test.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: focus - document-level APIs</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<input id="ipt">
diff --git a/tests/wpt/web-platform-tests/html/editing/focus/element-level-focus-apis/.gitkeep b/tests/wpt/web-platform-tests/html/editing/focus/element-level-focus-apis/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/focus/element-level-focus-apis/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/editing/focus/focus-01-manual.html b/tests/wpt/web-platform-tests/html/editing/focus/focus-01-manual.html
new file mode 100644
index 00000000000..16e0b0f6c1e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/focus/focus-01-manual.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: focus - key events</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#focus">
+<meta assert="flag" content="interact">
+<meta assert="assert" content="Check if the key events received by document are targeted at the element when it is focused">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<h2>Steps:</h2>
+<ol>
+ <li>Input any character into the textbox by keyboard in 10 seconds.</li>
+</ol>
+<h2>Expect results:</h2>
+<p>PASS</p>
+<div id="log"></div>
+<input id="test">
+<script>
+
+//These tests can be automated once we have an uniform way to use webdriver.
+var t1 = async_test("The keydown event must be targeted at the input element"),
+ t2 = async_test("The keypress event must be targeted at the input element"),
+ t3 = async_test("The keyup event must be targeted at the input element"),
+ testEle;
+
+setup(function () {
+ testEle = document.getElementById("test");
+ testEle.focus();
+}, {timeout: 10000});
+
+document.onkeydown = t1.step_func_done(function(evt){
+ assert_equals(evt.target, testEle, "The keydown events must be targeted at the input element.");
+});
+
+document.onkeypress = t2.step_func_done(function(evt){
+ assert_equals(evt.target, testEle, "The keypress events must be targeted at the input element.");
+});
+
+document.onkeyup = t3.step_func_done(function(evt){
+ assert_equals(evt.target, testEle, "The keyup events must be targeted at the input element.");
+});
+
+</script>
diff --git a/tests/wpt/web-platform-tests/html/editing/focus/focus-02-manual.html b/tests/wpt/web-platform-tests/html/editing/focus/focus-02-manual.html
new file mode 100644
index 00000000000..16dcfcf2a15
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/focus/focus-02-manual.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: focus - key events</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#focus">
+<meta assert="flag" content="interact">
+<meta assert="assert" content="Check if the key events received by document are targeted at the element when no element is focused">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<h2>Steps:</h2>
+<ol>
+ <li>Press any key in [0-9a-zA-Z].</li>
+</ol>
+<h2>Expect results:</h2>
+<p>PASS</p>
+<div id="log"></div>
+<script>
+
+//These tests can be automated once we have an uniform way to use webdriver.
+var t1 = async_test("The keydown event must be targeted at the body element"),
+ t2 = async_test("The keypress event must be targeted at the body element"),
+ t3 = async_test("The keyup event must be targeted at the body element");
+
+setup({timeout: 10000});
+
+document.onkeydown = t1.step_func_done(function(evt){
+ assert_equals(evt.target, document.body, "The keydown events must be targeted at the document's body.");
+});
+
+document.onkeypress = t2.step_func_done(function(evt){
+ assert_equals(evt.target, document.body, "The keypress events must be targeted at the document's body.");
+});
+
+document.onkeyup = t3.step_func_done(function(evt){
+ assert_equals(evt.target, document.body, "The keyup events must be targeted at the document's body.");
+});
+
+</script>
diff --git a/tests/wpt/web-platform-tests/html/editing/focus/focus-management/.gitkeep b/tests/wpt/web-platform-tests/html/editing/focus/focus-management/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/focus/focus-management/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/editing/focus/focus-management/focus-events.html b/tests/wpt/web-platform-tests/html/editing/focus/focus-management/focus-events.html
new file mode 100644
index 00000000000..d63362aaa18
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/focus/focus-management/focus-events.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Focus management</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#focus-management">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<input type=text id=i1>
+<input type=text id=i2>
+<script>
+ var i1 = document.getElementById('i1'),
+ i2 = document.getElementById('i2'),
+ t1 = async_test("focusing on a focusable element fires a focus event at the element"),
+ t2 = async_test("focusing on a focusable element fires a blur event at the previous focussed element");
+
+ i2.onfocus = t1.step_func_done(function(e){
+ assert_true(e.isTrusted, "focus event is trusted");
+ assert_false(e.bubbles, "focus event doesn't bubble");
+ assert_false(e.cancelable, "focus event is not cancelable");
+ assert_equals(document.activeElement, i2);
+ });
+
+ i1.onblur = t2.step_func_done(function(e){
+ assert_true(e.isTrusted, "blur event is trusted");
+ assert_false(e.bubbles, "blur event doesn't bubble");
+ assert_false(e.cancelable, "blur event is not cancelable");
+ });
+
+ i1.focus();
+ i2.focus();
+</script>
diff --git a/tests/wpt/web-platform-tests/html/editing/focus/sequential-focus-navigation-and-the-tabindex-attribute/.gitkeep b/tests/wpt/web-platform-tests/html/editing/focus/sequential-focus-navigation-and-the-tabindex-attribute/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/focus/sequential-focus-navigation-and-the-tabindex-attribute/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/editing/focus/sequential-focus-navigation-and-the-tabindex-attribute/focus-tabindex-default-value.html b/tests/wpt/web-platform-tests/html/editing/focus/sequential-focus-navigation-and-the-tabindex-attribute/focus-tabindex-default-value.html
new file mode 100644
index 00000000000..25e359c2a25
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/focus/sequential-focus-navigation-and-the-tabindex-attribute/focus-tabindex-default-value.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: focus - default value of tabindex</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#sequential-focus-navigation-and-the-tabindex-attribute">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<button id="test1">TEST1</button>
+<div id="test2">TEST2</div>
+<script>
+
+test(function() {
+ assert_equals(document.getElementById("test1").tabIndex, 0, "The value of tabIndex attribute should be 0.");
+}, "The default value of tabIndex attribute must be 0 for elements that are focusable");
+
+test(function() {
+ assert_equals(document.getElementById("test2").tabIndex, -1, "The value of tabIndex attribute should be -1.");
+}, "The default value of tabIndex attribute must be -1 for elements that are not focusable");
+
+</script>
diff --git a/tests/wpt/web-platform-tests/html/editing/focus/sequential-focus-navigation-and-the-tabindex-attribute/focus-tabindex-negative-manual.html b/tests/wpt/web-platform-tests/html/editing/focus/sequential-focus-navigation-and-the-tabindex-attribute/focus-tabindex-negative-manual.html
new file mode 100644
index 00000000000..506435074e3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/focus/sequential-focus-navigation-and-the-tabindex-attribute/focus-tabindex-negative-manual.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: focus - negative tabindex</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#sequential-focus-navigation-and-the-tabindex-attribute">
+<meta assert="flag" content="interact">
+<meta assert="assert" content="Check if the tabindex attribute controls whether an element is supposed to be focusable">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<h2>Steps:</h2>
+<ol>
+ <li>Press 'Tab' key in 10 seconds.</li>
+</ol>
+<h2>Expect results:</h2>
+<p>PASS</p>
+<div id="log"></div>
+<form id="fm">
+ <input id="test1" tabindex="-1">
+ <input id="test2" tabindex="0">
+</form>
+<script>
+
+//This test can be automated once we have an uniform way to use webdriver.
+var t = async_test("The element with a negative tabindex must not be focused by press 'Tab' key");
+
+setup({timeout: 10000});
+
+document.forms.fm.addEventListener("focus", function (evt) {
+ t.step(function () {
+ var testEle = document.getElementById("test1");
+ assert_equals(testEle.tabIndex, -1, "The tabIndex attribute of the first input element should be -1.");
+ assert_not_equals(evt.target, testEle, "The second input element must be focused.");
+ assert_equals(document.activeElement, document.getElementById("test2"), "The second input element must be activated.");
+ });
+ t.done();
+}, true);
+
+document.addEventListener("keydown", function (evt) {
+ t.step(function () {
+ assert_equals(evt.keyCode, 9, "Please press 'Tab' key.");
+ });
+}, true);
+
+</script>
diff --git a/tests/wpt/web-platform-tests/html/editing/focus/sequential-focus-navigation-and-the-tabindex-attribute/focus-tabindex-order-manual.html b/tests/wpt/web-platform-tests/html/editing/focus/sequential-focus-navigation-and-the-tabindex-attribute/focus-tabindex-order-manual.html
new file mode 100644
index 00000000000..c837626293c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/focus/sequential-focus-navigation-and-the-tabindex-attribute/focus-tabindex-order-manual.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: focus - the sequential focus navigation order</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#sequential-focus-navigation-and-the-tabindex-attribute">
+<meta assert="flag" content="interact">
+<meta assert="assert" content="Check the sequential focus navigation order">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<h2>Steps:</h2>
+<ol>
+ <li>Press 'Tab' key at least 10 times in 20 seconds.(Long press the 'Tab' key will be better.)</li>
+</ol>
+<h2>Expect results:</h2>
+<p>PASS</p>
+<div id="log"></div>
+<form id="fm">
+ <button id="btn0">tabindex(omitted)</button>
+ <button id="btn1" tabindex="">tabindex(empty)</button>
+ <button id="btn2" tabindex="a">tabindex(a)</button>
+ <button id="btn3" tabindex="-1">tabindex(-1)</button>
+ <button id="btn4" tabindex="0">tabindex(0)</button>
+ <button id="btn5" tabindex="3">tabindex(3)</button>
+ <button id="btn6" tabindex="2">tabindex(2)</button>
+ <button id="btn7" tabindex="2">tabindex(2)</button>
+ <button id="btn8" tabindex="2">tabindex(2)</button>
+ <button id="btn9" tabindex="1">tabindex(1)</button>
+</form>
+<script>
+
+//This test can be automated once we have an uniform way to use webdriver.
+var i = 0,
+ expectation = ["btn9", "btn6", "btn7", "btn8", "btn5", "btn0", "btn1", "btn2", "btn4"],
+ results = [],
+ t = async_test("The element with a zero tabindex must be focused by press 'Tab' key");
+
+setup(function () {
+ document.body.focus();
+}, {timeout: 20000});
+
+document.forms.fm.addEventListener("focus", function (evt) {
+ results.push(evt.target.id);
+ if (i >= 9) {
+ t.step(function () {
+ assert_array_equals(results, expectation);
+ });
+ }
+}, true);
+
+document.addEventListener("keydown", function (evt) {
+ if (evt.keyCode === 9) {
+ i += 1;
+ if (i === 10) {
+ t.done();
+ }
+ }
+}, true);
+
+</script>
diff --git a/tests/wpt/web-platform-tests/html/editing/focus/sequential-focus-navigation-and-the-tabindex-attribute/focus-tabindex-positive-manual.html b/tests/wpt/web-platform-tests/html/editing/focus/sequential-focus-navigation-and-the-tabindex-attribute/focus-tabindex-positive-manual.html
new file mode 100644
index 00000000000..012a3e7ee29
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/focus/sequential-focus-navigation-and-the-tabindex-attribute/focus-tabindex-positive-manual.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: focus - positive tabindex</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#sequential-focus-navigation-and-the-tabindex-attribute">
+<meta assert="flag" content="interact">
+<meta assert="assert" content="Check if the tabindex attribute controls whether an element is supposed to be focusable">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<h2>Steps:</h2>
+<ol>
+ <li>Press 'Tab' key in 10 seconds.</li>
+</ol>
+<h2>Expect results:</h2>
+<p>PASS</p>
+<div id="log"></div>
+<form id="fm">
+ <input id="test" tabindex="1">
+</form>
+<script>
+
+//This test can be automated once we have an uniform way to use webdriver.
+var t = async_test("The element with a positive tabindex must be focused by press 'Tab' key");
+
+setup({timeout: 10000});
+
+document.forms.fm.addEventListener("focus", function (evt) {
+ t.step(function () {
+ var testEle = document.getElementById("test");
+ assert_equals(testEle.tabIndex, 1, "The tabIndex attribute of the input element should be 1.");
+ assert_equals(evt.target, testEle, "The input element must be focused.");
+ assert_equals(document.activeElement, testEle, "The input element must be activated.");
+ });
+ t.done();
+}, true);
+
+document.addEventListener("keydown", function (evt) {
+ t.step(function () {
+ assert_equals(evt.keyCode, 9, "Please press 'Tab' key.");
+ });
+}, true);
+
+</script>
diff --git a/tests/wpt/web-platform-tests/html/editing/focus/sequential-focus-navigation-and-the-tabindex-attribute/focus-tabindex-zero-manual.html b/tests/wpt/web-platform-tests/html/editing/focus/sequential-focus-navigation-and-the-tabindex-attribute/focus-tabindex-zero-manual.html
new file mode 100644
index 00000000000..108b818b1d1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/focus/sequential-focus-navigation-and-the-tabindex-attribute/focus-tabindex-zero-manual.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<head>
+<meta charset="utf-8">
+<title>HTML Test: focus - zero tabindex</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#sequential-focus-navigation-and-the-tabindex-attribute">
+<meta assert="flag" content="interact">
+<meta assert="assert" content="Check if the tabindex attribute controls whether an element is supposed to be focusable">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<h2>Steps:</h2>
+<ol>
+ <li>Press 'Tab' key in 10 seconds.</li>
+</ol>
+<h2>Expect results:</h2>
+<p>PASS</p>
+<div id="log"></div>
+<form id="fm">
+ <input id="test" tabindex="0">
+</form>
+<script>
+
+//This test can be automated once we have an uniform way to use webdriver.
+var t = async_test("The element with a zero tabindex must be focused by press 'Tab' key");
+
+setup({timeout: 10000});
+
+document.forms.fm.addEventListener("focus", function (evt) {
+ t.step(function () {
+ var testEle = document.getElementById("test");
+ assert_equals(testEle.tabIndex, 0, "The tabIndex attribute of the input element should be 0.");
+ assert_equals(evt.target, testEle, "The input element must be focused.");
+ assert_equals(document.activeElement, testEle, "The input element must be activated.");
+ });
+ t.done();
+}, true);
+
+document.addEventListener("keydown", function (evt) {
+ t.step(function () {
+ assert_equals(evt.keyCode, 9, "Please press 'Tab' key.");
+ });
+}, true);
+
+</script>
diff --git a/tests/wpt/web-platform-tests/html/editing/inert-subtrees/.gitkeep b/tests/wpt/web-platform-tests/html/editing/inert-subtrees/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/inert-subtrees/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/editing/inert-subtrees/the-inert-attribute/.gitkeep b/tests/wpt/web-platform-tests/html/editing/inert-subtrees/the-inert-attribute/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/inert-subtrees/the-inert-attribute/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/editing/the-hidden-attribute/.gitkeep b/tests/wpt/web-platform-tests/html/editing/the-hidden-attribute/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/the-hidden-attribute/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/editing/the-hidden-attribute/hidden-1-ref.html b/tests/wpt/web-platform-tests/html/editing/the-hidden-attribute/hidden-1-ref.html
new file mode 100644
index 00000000000..7346ce919d2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/the-hidden-attribute/hidden-1-ref.html
@@ -0,0 +1,4 @@
+<!doctype html>
+<title>The hidden attribute</title>
+<link rel=author title=Ms2ger href=mailto:Ms2ger@gmail.com>
+<p>This line should be visible.
diff --git a/tests/wpt/web-platform-tests/html/editing/the-hidden-attribute/hidden-1a.html b/tests/wpt/web-platform-tests/html/editing/the-hidden-attribute/hidden-1a.html
new file mode 100644
index 00000000000..27a71a764b1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/the-hidden-attribute/hidden-1a.html
@@ -0,0 +1,7 @@
+<!doctype html>
+<title>The hidden attribute</title>
+<link rel=author title=Ms2ger href=mailto:Ms2ger@gmail.com>
+<link rel=help href=https://html.spec.whatwg.org/multipage/#the-hidden-attribute>
+<link rel=help href=https://html.spec.whatwg.org/multipage/#hidden-elements>
+<p>This line should be visible.
+<p hidden>This line should not be visible.
diff --git a/tests/wpt/web-platform-tests/html/editing/the-hidden-attribute/hidden-1b.html b/tests/wpt/web-platform-tests/html/editing/the-hidden-attribute/hidden-1b.html
new file mode 100644
index 00000000000..8f4524550dc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/the-hidden-attribute/hidden-1b.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>The hidden attribute</title>
+<link rel=author title=Ms2ger href=mailto:Ms2ger@gmail.com>
+<link rel=help href=https://html.spec.whatwg.org/multipage/#the-hidden-attribute>
+<link rel=help href=https://html.spec.whatwg.org/multipage/#hidden-elements>
+<style>
+p { display: none; }
+[hidden] { display: block; }
+</style>
+<p hidden>This line should be visible.
diff --git a/tests/wpt/web-platform-tests/html/editing/the-hidden-attribute/hidden-1c.html b/tests/wpt/web-platform-tests/html/editing/the-hidden-attribute/hidden-1c.html
new file mode 100644
index 00000000000..8612e41a0b0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/the-hidden-attribute/hidden-1c.html
@@ -0,0 +1,11 @@
+<!doctype html>
+<title>The hidden attribute</title>
+<link rel=author title=Ms2ger href=mailto:Ms2ger@gmail.com>
+<link rel=help href=https://html.spec.whatwg.org/multipage/#the-hidden-attribute>
+<link rel=help href=https://html.spec.whatwg.org/multipage/#hidden-elements>
+<p hidden>This line should be visible.
+<p>This line should not be visible.
+<script>
+document.getElementsByTagName("p")[0].hidden = false;
+document.getElementsByTagName("p")[1].hidden = true;
+</script>
diff --git a/tests/wpt/web-platform-tests/html/editing/the-hidden-attribute/hidden-1d.html b/tests/wpt/web-platform-tests/html/editing/the-hidden-attribute/hidden-1d.html
new file mode 100644
index 00000000000..b5c8ba93321
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/the-hidden-attribute/hidden-1d.html
@@ -0,0 +1,11 @@
+<!doctype html>
+<title>The hidden attribute</title>
+<link rel=author title=Ms2ger href=mailto:Ms2ger@gmail.com>
+<link rel=help href=https://html.spec.whatwg.org/multipage/#the-hidden-attribute>
+<link rel=help href=https://html.spec.whatwg.org/multipage/#hidden-elements>
+<p hidden>This line should be visible.
+<p>This line should not be visible.
+<script>
+document.getElementsByTagName("p")[0].removeAttribute("hidden");
+document.getElementsByTagName("p")[1].setAttribute("hidden", "");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/editing/the-hidden-attribute/hidden-1e.html b/tests/wpt/web-platform-tests/html/editing/the-hidden-attribute/hidden-1e.html
new file mode 100644
index 00000000000..8f518916198
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/the-hidden-attribute/hidden-1e.html
@@ -0,0 +1,9 @@
+<!doctype html>
+<title>The hidden attribute</title>
+<link rel=author title=Ms2ger href=mailto:Ms2ger@gmail.com>
+<link rel=help href=https://html.spec.whatwg.org/multipage/#the-hidden-attribute>
+<link rel=help href=https://html.spec.whatwg.org/multipage/#hidden-elements>
+<style>
+p { display: block; }
+</style>
+<p hidden>This line should be visible.
diff --git a/tests/wpt/web-platform-tests/html/editing/the-hidden-attribute/hidden-1f.html b/tests/wpt/web-platform-tests/html/editing/the-hidden-attribute/hidden-1f.html
new file mode 100644
index 00000000000..7b37b3ba966
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/the-hidden-attribute/hidden-1f.html
@@ -0,0 +1,9 @@
+<!doctype html>
+<title>The hidden attribute</title>
+<link rel=author title=Ms2ger href=mailto:Ms2ger@gmail.com>
+<link rel=help href=https://html.spec.whatwg.org/multipage/#the-hidden-attribute>
+<link rel=help href=https://html.spec.whatwg.org/multipage/#hidden-elements>
+<style>
+p { display: block !important; }
+</style>
+<p hidden>This line should be visible.
diff --git a/tests/wpt/web-platform-tests/html/editing/the-hidden-attribute/hidden-1g.html b/tests/wpt/web-platform-tests/html/editing/the-hidden-attribute/hidden-1g.html
new file mode 100644
index 00000000000..873b408ebe0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/the-hidden-attribute/hidden-1g.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>The hidden attribute</title>
+<link rel=author title=Ms2ger href=mailto:Ms2ger@gmail.com>
+<link rel=help href=https://html.spec.whatwg.org/multipage/#the-hidden-attribute>
+<link rel=help href=https://html.spec.whatwg.org/multipage/#hidden-elements>
+<p>This line should be visible.
+<p hidden=hidden>This line should not be visible.
+<p hidden=blue>This line should not be visible.
+<p hidden=true>This line should not be visible.
+<p hidden=false>This line should not be visible.
diff --git a/tests/wpt/web-platform-tests/html/editing/the-hidden-attribute/hidden-2-ref.svg b/tests/wpt/web-platform-tests/html/editing/the-hidden-attribute/hidden-2-ref.svg
new file mode 100644
index 00000000000..10931bfcab7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/the-hidden-attribute/hidden-2-ref.svg
@@ -0,0 +1,7 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="20" width="20">
+<metadata>
+ <link xmlns="http://www.w3.org/1999/xhtml" rel="author" title="Ms2ger"
+ href="mailto:Ms2ger@gmail.com"/>
+</metadata>
+<rect height="20" width="20"/>
+</svg>
diff --git a/tests/wpt/web-platform-tests/html/editing/the-hidden-attribute/hidden-2.svg b/tests/wpt/web-platform-tests/html/editing/the-hidden-attribute/hidden-2.svg
new file mode 100644
index 00000000000..a5f08f6b273
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/editing/the-hidden-attribute/hidden-2.svg
@@ -0,0 +1,12 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="20" width="20">
+<metadata>
+ <link xmlns="http://www.w3.org/1999/xhtml" rel="match" href="hidden-2-ref.svg" />
+ <link xmlns="http://www.w3.org/1999/xhtml" rel="author" title="Ms2ger"
+ href="mailto:Ms2ger@gmail.com"/>
+ <link xmlns="http://www.w3.org/1999/xhtml" rel="help"
+ href="https://html.spec.whatwg.org/multipage/#the-hidden-attribute"/>
+ <link xmlns="http://www.w3.org/1999/xhtml" rel="help"
+ href="https://html.spec.whatwg.org/multipage/#hidden-elements"/>
+</metadata>
+<rect hidden="" height="20" width="20"/>
+</svg>
diff --git a/tests/wpt/web-platform-tests/html/iana/.gitkeep b/tests/wpt/web-platform-tests/html/iana/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/iana/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/iana/application-x-www-form-urlencoded/.gitkeep b/tests/wpt/web-platform-tests/html/iana/application-x-www-form-urlencoded/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/iana/application-x-www-form-urlencoded/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/iana/application-x-www-form-urlencoded/original-id.json b/tests/wpt/web-platform-tests/html/iana/application-x-www-form-urlencoded/original-id.json
new file mode 100644
index 00000000000..6a52a7a5ffa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/iana/application-x-www-form-urlencoded/original-id.json
@@ -0,0 +1 @@
+{"original_id":"application/x-www-form-urlencoded"} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/iana/application-xhtml-xml/.gitkeep b/tests/wpt/web-platform-tests/html/iana/application-xhtml-xml/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/iana/application-xhtml-xml/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/iana/application-xhtml-xml/original-id.json b/tests/wpt/web-platform-tests/html/iana/application-xhtml-xml/original-id.json
new file mode 100644
index 00000000000..b376ccb40fd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/iana/application-xhtml-xml/original-id.json
@@ -0,0 +1 @@
+{"original_id":"application/xhtml+xml"} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/iana/multipart-x-mixed-replace/.gitkeep b/tests/wpt/web-platform-tests/html/iana/multipart-x-mixed-replace/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/iana/multipart-x-mixed-replace/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/iana/multipart-x-mixed-replace/original-id.json b/tests/wpt/web-platform-tests/html/iana/multipart-x-mixed-replace/original-id.json
new file mode 100644
index 00000000000..2cf8d777041
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/iana/multipart-x-mixed-replace/original-id.json
@@ -0,0 +1 @@
+{"original_id":"multipart/x-mixed-replace"} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/iana/ping-to/.gitkeep b/tests/wpt/web-platform-tests/html/iana/ping-to/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/iana/ping-to/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/iana/text-cache-manifest/.gitkeep b/tests/wpt/web-platform-tests/html/iana/text-cache-manifest/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/iana/text-cache-manifest/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/iana/text-cache-manifest/original-id.json b/tests/wpt/web-platform-tests/html/iana/text-cache-manifest/original-id.json
new file mode 100644
index 00000000000..b9055c2cde0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/iana/text-cache-manifest/original-id.json
@@ -0,0 +1 @@
+{"original_id":"text/cache-manifest"} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/iana/text-html/.gitkeep b/tests/wpt/web-platform-tests/html/iana/text-html/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/iana/text-html/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/iana/text-html/original-id.json b/tests/wpt/web-platform-tests/html/iana/text-html/original-id.json
new file mode 100644
index 00000000000..ff0ed4fbe61
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/iana/text-html/original-id.json
@@ -0,0 +1 @@
+{"original_id":"text/html"} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/iana/web-scheme-prefix/.gitkeep b/tests/wpt/web-platform-tests/html/iana/web-scheme-prefix/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/iana/web-scheme-prefix/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/iana/web-scheme-prefix/original-id.json b/tests/wpt/web-platform-tests/html/iana/web-scheme-prefix/original-id.json
new file mode 100644
index 00000000000..9db9bc7bf50
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/iana/web-scheme-prefix/original-id.json
@@ -0,0 +1 @@
+{"original_id":"web+-scheme-prefix"} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/.gitkeep b/tests/wpt/web-platform-tests/html/infrastructure/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/case-sensitivity-and-string-comparison/.gitkeep b/tests/wpt/web-platform-tests/html/infrastructure/case-sensitivity-and-string-comparison/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/case-sensitivity-and-string-comparison/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/.gitkeep b/tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/collections/.gitkeep b/tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/collections/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/collections/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/collections/contains.json b/tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/collections/contains.json
new file mode 100644
index 00000000000..b30f1d0d533
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/collections/contains.json
@@ -0,0 +1,14 @@
+[
+ {
+ "id": "htmlallcollection",
+ "original_id": "htmlallcollection"
+ },
+ {
+ "id": "htmlformcontrolscollection",
+ "original_id": "htmlformcontrolscollection"
+ },
+ {
+ "id": "htmloptionscollection",
+ "original_id": "htmloptionscollection"
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/collections/htmlallcollection.html b/tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/collections/htmlallcollection.html
new file mode 100644
index 00000000000..bf2911954e5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/collections/htmlallcollection.html
@@ -0,0 +1,33 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>HTMLAllCollection Tests</title>
+<link rel="author" title="Dan Druta" href="mailto:dan.druta@att.com"/>
+<link rel="help" href="2.7.2.1 - Common Infrastructure/Common DOM Interfaces/Collections/HTMLAllCollection"/>
+<meta name="flags" content="TOKENS" />
+<meta name="assert" content="TEST ASSERTION"/>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<img src="../../../../images/green.png" name="picture">
+<script>
+test(function(){ assert_equals(document.all.length,12)}, "Test for HTMLAllCollection size");
+
+test(function(){ assert_equals(document.all.item(0).tagName,"HTML")}, "Test lookup by index using ()");
+
+test(function(){ assert_equals(document.all[0].tagName,"HTML")}, "Test lookup by index using []");
+
+test(function(){ assert_equals(document.all.tags("script").length,3)}, "Test for multiple occurence 3 <script> found");
+
+test(function(){ assert_equals(document.all.item("picture").nodeName,"IMG")}, "Test lookup IMG by name");
+
+test(function(){ assert_equals(document.all.namedItem("picture").nodeName,"IMG")}, "Test lookup IMG by namedItem ");
+
+test(function(){ assert_equals(document.all("picture").nodeName,"IMG")}, "Test lookup IMG in collection using ()");
+
+test(function(){ assert_equals(document.all["picture"].nodeName,"IMG")}, "Test lookup IMG in collection using []");
+</script>
+<div id="log"></div>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/collections/htmlformcontrolscollection.html b/tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/collections/htmlformcontrolscollection.html
new file mode 100644
index 00000000000..a867ab826ab
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/collections/htmlformcontrolscollection.html
@@ -0,0 +1,112 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: the HTMLFormControlsCollection interface</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/multipage/common-dom-interfaces.html#htmlformcontrolscollection">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<form id="f1">
+ <input type="radio" id="r1">
+ <keygen id="kg" name="key"></keygen>
+</form>
+<form id="f2">
+ <table>
+ <tr>
+ <td>
+ <input type="checkbox" id="cb">
+ <input type="checkbox" name="cb">
+ </td>
+ </tr>
+ <button id="btn"></button>
+ <button name="btn"></button>
+ </table>
+</form>
+
+<script>
+
+var coll1, coll2, rdo;
+
+setup(function () {
+ rdo = document.getElementById("r1");
+ coll1 = document.forms[0].elements;
+ coll2 = document.forms[1].elements;
+});
+
+//length
+test(function () {
+ assert_equals(coll1.length, 2, "The length attribute is incorrect.");
+ assert_equals(coll2.length, 4, "The length attribute is incorrect.");
+}, "The length attribute must return the number of elements in the form");
+
+//getter - index
+test(function () {
+ assert_equals(coll1.item(0), rdo, "HTMLFormControlsCollection.item(index) should return the 'input' element in radio status.");
+}, "HTMLFormControlsCollection.item(index) must return the indexed item");
+
+test(function () {
+ assert_equals(coll1[0], rdo, "HTMLFormControlsCollection[index] should return the 'input' element in radio status.");
+}, "HTMLFormControlsCollection[index] must return the indexed item");
+
+//getter - name
+test(function () {
+ assert_equals(coll1("r1"), rdo, "HTMLFormControlsCollection(name) should return the 'input' element in radio status.");
+}, "HTMLFormControlsCollection(name) must return the named item");
+
+test(function () {
+ assert_equals(coll1["r1"], rdo, "HTMLFormControlsCollection[name] should return the 'input' element in radio status.");
+}, "HTMLFormControlsCollection[name] must return the named item");
+
+//getter - namedItem
+test(function () {
+ assert_equals(coll1.namedItem("r1"), rdo, "HTMLFormControlsCollection.namedItem(name) should return the 'input' element in radio status.");
+}, "HTMLFormControlsCollection.namedItem(name) must return the named item");
+
+test(function () {
+ assert_true(coll1.namedItem("r1") instanceof Element, "Can not return 'Element' object.");
+}, "The namedItem(name) must return an Element");
+
+test(function () {
+ assert_true(coll2.namedItem("cb") instanceof RadioNodeList, "Can not return 'RadioNodeList' object.");
+}, "The namedItem(name) must return RadioNodeList");
+
+test(function () {
+ assert_equals(coll1.namedItem(""), null, "The return value of namedItem() should be null.");
+}, "The namedItem(name) must return null if the name is empty");
+
+test(function () {
+ assert_equals(coll1.namedItem("test"), null, "The return value of namedItem() should be null.");
+}, "The namedItem(name) must return null if there is no matched element");
+
+test(function () {
+ assert_equals(coll1.namedItem("kg"), document.getElementById("kg"), "Controls can be named by 'id' attribute.");
+ assert_equals(coll1.namedItem("key"), document.getElementById("kg"), "Controls can be named by 'name' attribute.");
+}, "Controls can be indexed by id or name attribute");
+
+test(function () {
+ assert_equals(coll2.namedItem("btn").length, 2, "The length attribute should be 2.");
+}, "The namedItem(name) must return the items with id or name attribute");
+
+//various controls in fieldset and form
+var containers = ["form", "fieldset"],
+ controls = ["button", "fieldset", "input", "keygen", "object", "output", "select", "textarea"];
+for (var m = 0; m < containers.length; m++) {
+ test(function () {
+ var container = document.createElement(containers[m]);
+ var len = controls.length;
+ for (var n = 0; n < len; n++)
+ container.appendChild(document.createElement(controls[n]));
+ document.body.appendChild(container);
+ assert_equals(container.elements.length, len, "The length should be " + len + ".");
+ }, "The HTMLFormControlsCollection interface is used for collections of listed elements in " + containers[m] + " element");
+}
+
+//Check the controls' order
+test(function () {
+ var opt = document.forms[1].insertBefore(document.createElement("output"), document.forms[1].firstChild);
+ assert_array_equals(document.forms[1].elements,
+ [opt, document.getElementsByTagName("input")[1], document.getElementsByTagName("input")[2],
+ document.getElementsByTagName("button")[0], document.getElementsByTagName("button")[1]]);
+}, "The controls in the form element must be sorted in tree order");
+
+</script>
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/collections/htmloptionscollection.html b/tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/collections/htmloptionscollection.html
new file mode 100644
index 00000000000..d4f004d73dc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/collections/htmloptionscollection.html
@@ -0,0 +1,184 @@
+<!doctype html>
+<title>HTMLOptionsCollection</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#htmloptionscollection-0">
+<select id=a>
+ <option>1</option>
+ <option>2</option>
+ <option>3</option>
+<!--Note whitespace is important-->
+ <option>4</option>
+ <option>5</option>
+</select>
+
+<select id=b>
+ <option id=b1>1</option>
+ <option name=b2>2</option>
+ <option id=b3>3</option>
+ <option id=b3>4</option>
+ <option name=b4>5</option>
+ <option name=b4>6</option>
+ <option id=b5>7</option>
+ <option name=b5>8</option>
+ <option id=b6 name=b7>9</option>
+ <option id=b6 name=b6>10</option>
+ <option id=b8 name=b9>11</option>
+</select>
+
+<script>
+var a;
+var a_opts;
+var a_original_innerHTML;
+var b;
+var b_opts;
+
+setup(function() {
+ a = document.getElementById("a");
+ a_opts = a.options;
+ a_original_innerHTML = a.innerHTML;
+ a.innerHTML = a_original_innerHTML;
+ b = document.getElementById("b");
+ b_opts = b.options;
+ b_original_innerHTML = b.innerHTML;
+ b.innerHTML = b_original_innerHTML;
+})
+
+function assert_values_equals(coll, expected_values, message) {
+ actual = [];
+ for (var i=0; i<coll.length; i++) {
+ actual.push(coll[i].value);
+ }
+ assert_array_equals(actual, expected_values, message);
+}
+
+test(function() {
+ assert_equals(5, a_opts.length);
+}, "Original length");
+
+test(function() {
+ a.innerHTML = a_original_innerHTML;
+ a_opts.value = "3";
+ a_opts.length = 5;
+ assert_equals(a_opts.length, 5);
+ assert_equals(a_opts.value, "3");
+}, "Setting length to original value has no effect");
+
+test(function() {
+ a.innerHTML = a_original_innerHTML;
+ a.value = 3;
+ a_opts.length = 3;
+ assert_equals(3, a_opts.length, "Correct length");
+ assert_values_equals(a_opts, ["1","2","3"], "Correct elements remain")
+ assert_equals(a_opts.value, "3", "Correct value set");
+ assert_equals(a.childNodes.length, 11, "Correct number of child nodes")
+}, "Setting length to shorter value");
+
+test(function() {
+ a.innerHTML = a_original_innerHTML;
+ a.value = 3;
+ a_opts.length = 7;
+ assert_equals(a_opts.length, 7, "Correct length");
+ assert_values_equals(a_opts, ["1","2","3","4","5","",""], "Correct elements inserted")
+ assert_equals(a.value, "3", "Correct value set");
+ assert_equals(a.childNodes.length, 15, "Correct number of child nodes")
+}, "Setting length to longer value");
+
+test(function() {
+ a.innerHTML = a_original_innerHTML;
+ var newChild = document.createElement("p");
+ var newOption = document.createElement("option");
+ newOption.textContent = "6";
+ newChild.appendChild(newOption);
+ a.appendChild(newChild);
+ a.value = 3;
+ assert_equals(a_opts.length, 5, "Correct length");
+ assert_values_equals(a_opts, ["1","2","3","4","5"], "Correct elements inserted")
+ assert_equals(a.value, "3", "Correct value set");
+}, "Insert <p><option>6</option></p> into <select>");
+
+test(function() {
+ a.innerHTML = a_original_innerHTML;
+ var newChild = document.createElement("select");
+ var newOption = document.createElement("option");
+ newOption.textContent = "6";
+ newChild.appendChild(newOption);
+ a.appendChild(newChild);
+ a.value = 3;
+ assert_equals(a_opts.length, 5, "Correct length");
+ assert_values_equals(a_opts, ["1","2","3","4","5"], "Correct elements inserted")
+ assert_equals(a.value, "3", "Correct value set");
+}, "Insert <select><option>6</option></select> into <select>");
+
+test(function() {
+ //This tests the spec but it is probably wrong here; see bug 12665
+ a.innerHTML = a_original_innerHTML;
+ var newChild = document.createElement("optgroup");
+ var newOption = document.createElement("option");
+ newOption.textContent = "6";
+ newChild.appendChild(newOption);
+ a.appendChild(newChild);
+ a.value = 3;
+ assert_equals(a_opts.length, 6, "Correct length");
+ assert_values_equals(a_opts, ["1","2","3","4","5", "6"], "Correct elements inserted")
+ assert_equals(a.value, "3", "Correct value set");
+}, "Insert <optgroup><option>6</option></optgroup> into <select>");
+
+test(function() {
+ a.innerHTML = a_original_innerHTML;
+ var newChild = document.createElement("optgroup");
+ var newChild1 = document.createElement("optgroup");
+ var newOption = document.createElement("option");
+ newOption.textContent = "6";
+ newChild.appendChild(newChild1);
+ newChild1.appendChild(newOption);
+ a.appendChild(newChild);
+ a.value = 3;
+ assert_equals(a_opts.length, 5, "Correct length");
+ assert_values_equals(a_opts, ["1","2","3","4","5"], "Correct elements inserted")
+ assert_equals(a.value, "3", "Correct value set");
+}, "Insert <optgroup><optgroup><option>6</option></optgroup></optgroup> into <select>");
+
+test(function() {
+ assert_equals(b_opts.namedItem("b1").value, "1");
+}, "namedItem id attribute");
+
+test(function() {
+ assert_equals(b_opts.namedItem("b2").value, "2");
+}, "namedItem name attribute");
+
+test(function() {
+ assert_equals(b_opts.namedItem("c"), null);
+}, "namedItem doesn't match anything");
+
+test(function() {
+ assert_equals(b_opts.namedItem("b3").value, "3");
+}, "namedItem multiple IDs");
+
+test(function() {
+ assert_equals(b_opts.namedItem("b4").value, "5");
+}, "namedItem multiple names");
+
+test(function() {
+ assert_equals(b_opts.namedItem("b5").value, "7");
+}, "namedItem multiple name and ID");
+
+test(function() {
+ assert_equals(b_opts.namedItem("b6").value, "9");
+}, "namedItem multiple name and ID with multiple attributes");
+
+test(function() {
+ assert_equals(b_opts.namedItem("b8").value, "11");
+}, "namedItem id attribute multiple attributes one element");
+
+test(function() {
+ assert_equals(b_opts.namedItem("b9").value, "11");
+}, "namedItem name attribute multiple attributes one element");
+
+test(function() {
+ var add = document.createElement("p");
+ assert_throws(new TypeError(), function() {b_opts.add(add);});
+}, "Add non-option to collection");
+
+</script>
+<div id=log></div>
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/collections/radionodelist.html b/tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/collections/radionodelist.html
new file mode 100644
index 00000000000..fc70d7172c3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/collections/radionodelist.html
@@ -0,0 +1,78 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: the RadioNodeList interface</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/multipage/common-dom-interfaces.html#radionodelist">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<form >
+ <input type="checkbox" name="rdo" value="0" id="r0" checked>
+ <input type="radio" name="rdo" id="r1">
+ <input type="radio" name="rdo" id="r2" value="2">
+</form>
+<script>
+
+var rdoList;
+
+setup(function () {
+ rdoList = document.forms[0].elements.namedItem("rdo");
+});
+
+//on getting
+test(function () {
+ assert_equals(rdoList.value, "", "The value attribute should be empty.");
+}, "The value attribute should be empty if no element is checked");
+
+test(function () {
+ document.getElementById("r2").checked = true;
+ assert_equals(rdoList.value, "2", "The value attribute should be 2.");
+}, "The RadioNodeList.value must be the first checked radio button's value");
+
+test(function () {
+ document.getElementById("r1").checked = true;
+ assert_equals(rdoList.value, "on", "The value attribute should be on.");
+
+ document.getElementById("r1").value = 1;
+ assert_equals(rdoList.value, "1", "The value attribute should be 1.");
+}, "Check the RadioNodeList.value on getting");
+
+//on setting
+test(function () {
+ assert_equals(rdoList.value, document.getElementById("r1").value,
+ "The value attribute should be equal to the first checked radio input element's value.");
+ assert_false(document.getElementById("r2").checked,
+ "The second radio input element should not be checked.");
+
+ rdoList.value = "2";
+ assert_equals(rdoList.value, document.getElementById("r2").value,
+ "The value attribute should be equal to the second radio input element's value.");
+ assert_true(document.getElementById("r2").checked,
+ "The second radio input element should be checked.");
+
+ //Do nothing if no element's value is equal to new value.
+ rdoList.value = "3";
+ assert_equals(rdoList.value, document.getElementById("r2").value,
+ "The value attribute should be the second radio input element's value.");
+ assert_true(document.getElementById("r2").checked,
+ "The second radio input element should be checked.");
+}, "Check the RadioNodeList.value on setting");
+
+//setting to on, specific case
+test(function () {
+ rdoList.value = "on";
+ assert_equals(rdoList.value, document.getElementById("r2").value,
+ "The value attribute should be the second radio input element's value.");
+ assert_true(document.getElementById("r2").checked,
+ "The second radio input element should be checked.");
+
+ document.getElementById("r1").removeAttribute("value");
+ rdoList.value = "on";
+ assert_equals(rdoList.value, document.getElementById("r1").value,
+ "The value attribute should be the first radio input element's value.");
+ assert_true(document.getElementById("r1").checked,
+ "The first radio input element should be checked.");
+}, "Check the RadioNodeList.value on setting to 'on'");
+
+
+</script>
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/domstringmap/.gitkeep b/tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/domstringmap/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/domstringmap/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/garbage-collection/.gitkeep b/tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/garbage-collection/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/garbage-collection/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/reflecting-content-attributes-in-idl-attributes/.gitkeep b/tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/reflecting-content-attributes-in-idl-attributes/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/reflecting-content-attributes-in-idl-attributes/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/safe-passing-of-structured-data/.gitkeep b/tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/safe-passing-of-structured-data/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/safe-passing-of-structured-data/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/transferable-objects/.gitkeep b/tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/transferable-objects/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/common-dom-interfaces/transferable-objects/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/common-microsyntaxes/.gitkeep b/tests/wpt/web-platform-tests/html/infrastructure/common-microsyntaxes/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/common-microsyntaxes/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/common-microsyntaxes/boolean-attributes/.gitkeep b/tests/wpt/web-platform-tests/html/infrastructure/common-microsyntaxes/boolean-attributes/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/common-microsyntaxes/boolean-attributes/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/common-microsyntaxes/colors/.gitkeep b/tests/wpt/web-platform-tests/html/infrastructure/common-microsyntaxes/colors/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/common-microsyntaxes/colors/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/common-microsyntaxes/comma-separated-tokens/.gitkeep b/tests/wpt/web-platform-tests/html/infrastructure/common-microsyntaxes/comma-separated-tokens/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/common-microsyntaxes/comma-separated-tokens/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/common-microsyntaxes/common-parser-idioms/.gitkeep b/tests/wpt/web-platform-tests/html/infrastructure/common-microsyntaxes/common-parser-idioms/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/common-microsyntaxes/common-parser-idioms/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/common-microsyntaxes/dates-and-times/.gitkeep b/tests/wpt/web-platform-tests/html/infrastructure/common-microsyntaxes/dates-and-times/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/common-microsyntaxes/dates-and-times/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/common-microsyntaxes/dates-and-times/contains.json b/tests/wpt/web-platform-tests/html/infrastructure/common-microsyntaxes/dates-and-times/contains.json
new file mode 100644
index 00000000000..5be31eb48f1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/common-microsyntaxes/dates-and-times/contains.json
@@ -0,0 +1,42 @@
+[
+ {
+ "id": "months",
+ "original_id": "months"
+ },
+ {
+ "id": "dates",
+ "original_id": "dates"
+ },
+ {
+ "id": "yearless-dates",
+ "original_id": "yearless-dates"
+ },
+ {
+ "id": "times",
+ "original_id": "times"
+ },
+ {
+ "id": "local-dates-and-times",
+ "original_id": "local-dates-and-times"
+ },
+ {
+ "id": "time-zones",
+ "original_id": "time-zones"
+ },
+ {
+ "id": "global-dates-and-times",
+ "original_id": "global-dates-and-times"
+ },
+ {
+ "id": "weeks",
+ "original_id": "weeks"
+ },
+ {
+ "id": "durations",
+ "original_id": "durations"
+ },
+ {
+ "id": "vaguer-moments-in-time",
+ "original_id": "vaguer-moments-in-time"
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/common-microsyntaxes/keywords-and-enumerated-attributes/.gitkeep b/tests/wpt/web-platform-tests/html/infrastructure/common-microsyntaxes/keywords-and-enumerated-attributes/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/common-microsyntaxes/keywords-and-enumerated-attributes/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/common-microsyntaxes/mq/.gitkeep b/tests/wpt/web-platform-tests/html/infrastructure/common-microsyntaxes/mq/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/common-microsyntaxes/mq/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/common-microsyntaxes/numbers/.gitkeep b/tests/wpt/web-platform-tests/html/infrastructure/common-microsyntaxes/numbers/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/common-microsyntaxes/numbers/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/common-microsyntaxes/numbers/contains.json b/tests/wpt/web-platform-tests/html/infrastructure/common-microsyntaxes/numbers/contains.json
new file mode 100644
index 00000000000..39a6ea00588
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/common-microsyntaxes/numbers/contains.json
@@ -0,0 +1,26 @@
+[
+ {
+ "id": "signed-integers",
+ "original_id": "signed-integers"
+ },
+ {
+ "id": "non-negative-integers",
+ "original_id": "non-negative-integers"
+ },
+ {
+ "id": "floating-point-numbers",
+ "original_id": "floating-point-numbers"
+ },
+ {
+ "id": "percentages-and-dimensions",
+ "original_id": "percentages-and-dimensions"
+ },
+ {
+ "id": "lists-of-integers",
+ "original_id": "lists-of-integers"
+ },
+ {
+ "id": "lists-of-dimensions",
+ "original_id": "lists-of-dimensions"
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/common-microsyntaxes/space-separated-tokens/.gitkeep b/tests/wpt/web-platform-tests/html/infrastructure/common-microsyntaxes/space-separated-tokens/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/common-microsyntaxes/space-separated-tokens/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/common-microsyntaxes/syntax-references/.gitkeep b/tests/wpt/web-platform-tests/html/infrastructure/common-microsyntaxes/syntax-references/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/common-microsyntaxes/syntax-references/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/conformance-requirements/.gitkeep b/tests/wpt/web-platform-tests/html/infrastructure/conformance-requirements/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/conformance-requirements/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/conformance-requirements/conformance-classes/.gitkeep b/tests/wpt/web-platform-tests/html/infrastructure/conformance-requirements/conformance-classes/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/conformance-requirements/conformance-classes/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/conformance-requirements/dependencies/.gitkeep b/tests/wpt/web-platform-tests/html/infrastructure/conformance-requirements/dependencies/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/conformance-requirements/dependencies/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/conformance-requirements/extensibility/.gitkeep b/tests/wpt/web-platform-tests/html/infrastructure/conformance-requirements/extensibility/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/conformance-requirements/extensibility/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/conformance-requirements/extensibility/foreign.html b/tests/wpt/web-platform-tests/html/infrastructure/conformance-requirements/extensibility/foreign.html
new file mode 100644
index 00000000000..eaa133badee
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/conformance-requirements/extensibility/foreign.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html lang="en" foo='bar'>
+ <head foo='bar'>
+ <meta charset="utf-8" foo='bar'>
+ <title id='title' foo='bar'>Foreign content</title>
+ <link rel="author" title="Philippe Le Hegaret" href="mailto:plh@w3.org" foo='bar'>
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#extensibility" foo='bar'>
+ <script src="/resources/testharness.js" foo='bar'></script>
+ <script src="/resources/testharnessreport.js" foo='bar'></script>
+ </head>
+
+ <body foo='bar'>
+
+ <p class='assert' foo='bar'>User agents must treat elements and attributes that they do not understand as semantically neutral; leaving them in the DOM (for DOM processors), and styling them according to CSS (for CSS processors), but not inferring any meaning from them.</p>
+
+ <foo foo='bar' echo>Foobar</foo>
+
+ <div id="log">Running test...</div>
+
+ <script>
+ var t = async_test("foreign content");
+
+ on_event(window, "load",
+ t.step_func(function() {
+ var nodes = document.getElementsByTagName("*");
+ var cont = true;
+ var last = null;
+ for(var i=0;i<nodes.length && cont; i++) {
+ var as = nodes.item(i).getAttribute("foo");
+ if (!(as === "bar") && (nodes.item(i).getAttribute("id") === "log")) {
+ cont = false;
+ } else {
+ last = nodes.item(i);
+ assert_equals(as, "bar");
+ }
+ }
+
+ assert_equals(last.nodeName, "FOO");
+ assert_equals(last.getAttribute("echo"), "");
+ assert_equals(last.getAttribute("charly"), null);
+ t.done();
+ }));
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/fetching-resources/.gitkeep b/tests/wpt/web-platform-tests/html/infrastructure/fetching-resources/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/fetching-resources/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/fetching-resources/content-type-sniffing/.gitkeep b/tests/wpt/web-platform-tests/html/infrastructure/fetching-resources/content-type-sniffing/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/fetching-resources/content-type-sniffing/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/fetching-resources/cors-enabled-fetch/.gitkeep b/tests/wpt/web-platform-tests/html/infrastructure/fetching-resources/cors-enabled-fetch/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/fetching-resources/cors-enabled-fetch/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/fetching-resources/cors-settings-attributes/.gitkeep b/tests/wpt/web-platform-tests/html/infrastructure/fetching-resources/cors-settings-attributes/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/fetching-resources/cors-settings-attributes/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/fetching-resources/encrypted-http-and-related-security-concerns/.gitkeep b/tests/wpt/web-platform-tests/html/infrastructure/fetching-resources/encrypted-http-and-related-security-concerns/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/fetching-resources/encrypted-http-and-related-security-concerns/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/fetching-resources/extracting-character-encodings-from-meta-elements/.gitkeep b/tests/wpt/web-platform-tests/html/infrastructure/fetching-resources/extracting-character-encodings-from-meta-elements/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/fetching-resources/extracting-character-encodings-from-meta-elements/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/fetching-resources/processing-model/.gitkeep b/tests/wpt/web-platform-tests/html/infrastructure/fetching-resources/processing-model/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/fetching-resources/processing-model/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/fetching-resources/terminology-1/.gitkeep b/tests/wpt/web-platform-tests/html/infrastructure/fetching-resources/terminology-1/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/fetching-resources/terminology-1/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/namespaces/.gitkeep b/tests/wpt/web-platform-tests/html/infrastructure/namespaces/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/namespaces/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/terminology/.gitkeep b/tests/wpt/web-platform-tests/html/infrastructure/terminology/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/terminology/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/terminology/character-encodings/.gitkeep b/tests/wpt/web-platform-tests/html/infrastructure/terminology/character-encodings/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/terminology/character-encodings/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/terminology/dom-trees/.gitkeep b/tests/wpt/web-platform-tests/html/infrastructure/terminology/dom-trees/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/terminology/dom-trees/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/terminology/plugins/.gitkeep b/tests/wpt/web-platform-tests/html/infrastructure/terminology/plugins/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/terminology/plugins/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/terminology/plugins/sample.txt b/tests/wpt/web-platform-tests/html/infrastructure/terminology/plugins/sample.txt
new file mode 100644
index 00000000000..cedecd6d884
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/terminology/plugins/sample.txt
@@ -0,0 +1,3 @@
+This is a sample text/plain document.
+
+This is not an HTML document.
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/terminology/plugins/text-plain.html b/tests/wpt/web-platform-tests/html/infrastructure/terminology/plugins/text-plain.html
new file mode 100644
index 00000000000..0ed0ce23b8a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/terminology/plugins/text-plain.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <title id='title'>Media Types</title>
+ <link rel="author" title="Philippe Le Hegaret" href="mailto:plh@w3.org"/>
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#plugins"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+
+ <body>
+ <script>
+ var t = async_test("A user agent must not consider the type text/plain as having a registered plugin.");
+
+ window.onload =
+ t.step_func(function() {
+ assert_equals(document.getElementById("frameContext").contentDocument.body.firstChild.nodeName, "PRE");
+ t.done();
+ });
+ </script>
+
+ <h1>Test of plugin support</h1>
+ <p class='assert'>A user agent must not consider the types text/plain and application/octet-stream as having a registered plugin.</p>
+
+ <iframe id="frameContext" src="sample.txt"></iframe>
+
+
+ <div id="log">Running test...</div>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/terminology/resources/.gitkeep b/tests/wpt/web-platform-tests/html/infrastructure/terminology/resources/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/terminology/resources/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/terminology/scripting-0/.gitkeep b/tests/wpt/web-platform-tests/html/infrastructure/terminology/scripting-0/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/terminology/scripting-0/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/terminology/xml/.gitkeep b/tests/wpt/web-platform-tests/html/infrastructure/terminology/xml/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/terminology/xml/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/urls/.gitkeep b/tests/wpt/web-platform-tests/html/infrastructure/urls/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/urls/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/urls/base-urls/.gitkeep b/tests/wpt/web-platform-tests/html/infrastructure/urls/base-urls/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/urls/base-urls/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/urls/dynamic-changes-to-base-urls/.gitkeep b/tests/wpt/web-platform-tests/html/infrastructure/urls/dynamic-changes-to-base-urls/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/urls/dynamic-changes-to-base-urls/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/urls/dynamic-changes-to-base-urls/dynamic-urls.sub.xhtml b/tests/wpt/web-platform-tests/html/infrastructure/urls/dynamic-changes-to-base-urls/dynamic-urls.sub.xhtml
new file mode 100644
index 00000000000..7302ed6e239
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/urls/dynamic-changes-to-base-urls/dynamic-urls.sub.xhtml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html>
+<html id="h" xmlns="http://www.w3.org/1999/xhtml" xml:base="">
+ <head>
+ <title>HTML Test: Dynamic changes to base URLs</title>
+ <link rel="author" title="Intel" href="http://www.intel.com/"/>
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#dynamic-changes-to-base-urls" />
+ <script src="/resources/testharness.js" id="s1"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <div id="div" style="display:none" xml:base=""></div>
+ <script>
+ <![CDATA[
+ var div = document.getElementById("div"),
+ html = document.getElementById("h"),
+ url = document.location.href;
+
+ var testData = [
+ {elements: ["a", "link", "area"], set: "href", get: "href"},
+ {elements: ["q", "blockquote", "ins", "del"], set: "cite", get: "cite"},
+ {elements: ["img", "embed", "video", "iframe", "script", "source", "track"], set: "src", get: "src"},
+ {elements: ["form"], set: "action", get: "action"},
+ {elements: ["object"], set: "data", get: "data"},
+ {elements: ["button"], set: "formaction", get: "formAction"}
+ ];
+
+ for (var i in testData) {
+ var item = testData[i];
+ for (var j in item.elements) {
+ test(function () {
+ var ele = document.createElement(item.elements[j]);
+
+ ele.setAttribute(item.set, "test.txt");
+ div.appendChild(ele);
+
+ html.setAttribute("xml:base", "");
+ assert_equals(ele[item.get], url.substr(0, url.lastIndexOf("/")) +"/test.txt", "The '" + item.get + "' attribute is incorrect.");
+ html.setAttribute("xml:base", "http://{{domains[www]}}:{{ports[http][0]}}");
+ assert_equals(ele[item.get], "http://{{domains[www]}}:{{ports[http][0]}}/test.txt", "The '" + item.get + "' attribute is incorrect.");
+ }, "The '" + item.set + "' attribute of the '" + item.elements[j] + "' element");
+ }
+ }
+
+ test(function () {
+ var s1 = document.getElementById("s1");
+ var val1 = s1.src;
+ var val2 = div.firstChild.href;
+
+ div.setAttribute("xml:base", "http://{{domains[www2]}}:{{ports[http][0]}}");
+ assert_equals(s1.src, val1, "The outer element must not be effected.");
+ assert_not_equals(div.firstChild.href, val2, "The inner element must be effected.");
+ assert_equals(div.firstChild.href, "http://{{domains[www2]}}:{{ports[http][0]}}/test.txt");
+ }, "Change the base URL must effect the descendant elements only");
+ ]]>
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/urls/interfaces-for-url-manipulation/.gitkeep b/tests/wpt/web-platform-tests/html/infrastructure/urls/interfaces-for-url-manipulation/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/urls/interfaces-for-url-manipulation/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/urls/parsing-urls/.gitkeep b/tests/wpt/web-platform-tests/html/infrastructure/urls/parsing-urls/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/urls/parsing-urls/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/urls/resolving-urls/.gitkeep b/tests/wpt/web-platform-tests/html/infrastructure/urls/resolving-urls/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/urls/resolving-urls/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/urls/resolving-urls/query-encoding/resources/blank.py b/tests/wpt/web-platform-tests/html/infrastructure/urls/resolving-urls/query-encoding/resources/blank.py
new file mode 100644
index 00000000000..6274a4e3cbf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/urls/resolving-urls/query-encoding/resources/blank.py
@@ -0,0 +1,2 @@
+def main(request, response):
+ return [("Content-Type", "text/html; charset=%s" % (request.GET['encoding']))], ""
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/urls/resolving-urls/query-encoding/resources/css-tmpl.py b/tests/wpt/web-platform-tests/html/infrastructure/urls/resolving-urls/query-encoding/resources/css-tmpl.py
new file mode 100644
index 00000000000..d7c9bce2786
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/urls/resolving-urls/query-encoding/resources/css-tmpl.py
@@ -0,0 +1,5 @@
+def main(request, response):
+ encoding = request.GET['encoding']
+ tmpl = request.GET['tmpl']
+ sheet = tmpl % u'\\0000E5'
+ return [("Content-Type", "text/css; charset=%s" % encoding)], sheet.encode(encoding)
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/urls/resolving-urls/query-encoding/resources/manifest.py b/tests/wpt/web-platform-tests/html/infrastructure/urls/resolving-urls/query-encoding/resources/manifest.py
new file mode 100644
index 00000000000..05b47f8163f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/urls/resolving-urls/query-encoding/resources/manifest.py
@@ -0,0 +1,12 @@
+def main(request, response):
+ id = request.GET['id']
+ mode = request.GET['mode']
+ fallback_url = ""
+ if mode == "FALLBACK":
+ fallback_url = "fallback-namespace/"
+ manifest = u"""CACHE MANIFEST
+
+%s:
+%s stash.py?q=\u00E5&id=%s&action=put
+""" % (mode, fallback_url, id)
+ return [("Content-Type", "text/cache-manifest; charset=%s" % request.GET['encoding'])], manifest.encode('utf-8') # charset should be ignored for cache manifests
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/urls/resolving-urls/query-encoding/resources/page-using-manifest.py b/tests/wpt/web-platform-tests/html/infrastructure/urls/resolving-urls/query-encoding/resources/page-using-manifest.py
new file mode 100644
index 00000000000..401d741a4bc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/urls/resolving-urls/query-encoding/resources/page-using-manifest.py
@@ -0,0 +1,12 @@
+def main(request, response):
+ id = request.GET['id']
+ encoding = request.GET['encoding']
+ mode = request.GET['mode']
+ iframe = ""
+ if mode == 'NETWORK':
+ iframe = "<iframe src='stash.py?q=%%C3%%A5&id=%s&action=put'></iframe>" % id
+ doc = """<!doctype html>
+<html manifest="manifest.py?id=%s&encoding=%s&mode=%s">
+%s
+""" % (id, encoding, mode, iframe)
+ return [("Content-Type", "text/html; charset=%s" % encoding)], doc.encode(encoding)
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/urls/resolving-urls/query-encoding/resources/resolve-url.js b/tests/wpt/web-platform-tests/html/infrastructure/urls/resolving-urls/query-encoding/resources/resolve-url.js
new file mode 100644
index 00000000000..b5d00ee57e3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/urls/resolving-urls/query-encoding/resources/resolve-url.js
@@ -0,0 +1,952 @@
+setup({explicit_done:true});
+onload = function() {
+ var encoding = '{{GET[encoding]}}';
+ var input_url = 'resources/resource.py?q=\u00E5&encoding=' + encoding + '&type=';
+ ('html css js worker sharedworker worker_importScripts sharedworker_importScripts worker_worker worker_sharedworker sharedworker_worker '+
+ 'sharedworker_sharedworker eventstream png svg xmlstylesheet_css video webvtt').split(' ').forEach(function(str) {
+ window['input_url_'+str] = input_url + str;
+ });
+ var blank = 'resources/blank.py?encoding=' + encoding;
+ var stash_put = 'resources/stash.py?q=\u00E5&action=put&id=';
+ var stash_take = 'resources/stash.py?action=take&id=';
+ var expected_obj = {
+ 'utf-8':'%C3%A5',
+ 'utf-16be':'%C3%A5',
+ 'utf-16le':'%C3%A5',
+ 'windows-1252':'%E5',
+ 'windows-1251':'%3F'
+ };
+ var expected_current = expected_obj[encoding];
+ var expected_utf8 = expected_obj['utf-8'];
+
+ function msg(expected, got) {
+ return 'expected substring '+expected+' got '+got;
+ }
+
+ function poll_for_stash(test_obj, uuid, expected) {
+ var start = new Date();
+ var poll = test_obj.step_func(function () {
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', stash_take + uuid);
+ xhr.onload = test_obj.step_func(function(e) {
+ if (xhr.response == "") {
+ if (new Date() - start > 10000) {
+ // If we set the status to TIMEOUT here we avoid a race between the
+ // page and the test timing out
+ test_obj.force_timeout();
+ }
+ setTimeout(poll, 200);
+ } else {
+ assert_equals(xhr.response, expected);
+ test_obj.done();
+ }
+ });
+ xhr.send();
+ })
+ setTimeout(poll, 200);
+ }
+
+ // background attribute, check with getComputedStyle
+ function test_background(tag) {
+ var spec_url = 'https://html.spec.whatwg.org/multipage/multipage/rendering.html';
+ spec_url += tag == 'body' ? '#the-page' : '#tables';
+ test(function() {
+ var elm = document.createElement(tag);
+ document.body.appendChild(elm);
+ this.add_cleanup(function() {
+ document.body.removeChild(elm);
+ });
+ elm.setAttribute('background', input_url_png);
+ var got = getComputedStyle(elm).backgroundImage;
+ assert_true(got.indexOf(expected_current) > -1, msg(expected_current, got));
+ }, 'getComputedStyle <'+tag+' background>',
+ {help:spec_url});
+ }
+
+ 'body, table, thead, tbody, tfoot, tr, td, th'.split(', ').forEach(function(str) {
+ test_background(str);
+ });
+
+ // get a reflecting IDL attributes whose content attribute takes a URL or a list of space-separated URLs
+ function test_reflecting(tag, attr, idlAttr, multiple) {
+ idlAttr = idlAttr || attr;
+ var input = input_url_html;
+ if (multiple) {
+ input += ' ' + input;
+ }
+ test(function() {
+ var elm = document.createElement(tag);
+ assert_true(idlAttr in elm, idlAttr + ' is not supported');
+ elm.setAttribute(attr, input);
+ var got = elm[idlAttr];
+ assert_true(got.indexOf(expected_current) > -1, msg(expected_current, got));
+ }, 'Getting <'+tag+'>.'+idlAttr + (multiple ? ' (multiple URLs)' : ''),
+ {help:'https://html.spec.whatwg.org/multipage/multipage/common-dom-interfaces.html#reflecting-content-attributes-in-idl-attributes'});
+ }
+
+ ('iframe src, a href, base href, link href, img src, embed src, object data, track src, video src, audio src, input src, form action, ' +
+ 'input formaction formAction, button formaction formAction, menuitem icon, script src, div itemid').split(', ').forEach(function(str) {
+ var arr = str.split(' ');
+ test_reflecting(arr[0], arr[1], arr[2]);
+ });
+
+ 'a ping'.split(', ').forEach(function(str) {
+ var arr = str.split(' ');
+ test_reflecting(arr[0], arr[1], arr[2], true);
+ });
+
+ function setup_navigation(elm, iframe, id, test_obj) {
+ iframe.name = id;
+ elm.target = id;
+ elm.setAttribute('href', input_url_html);
+ document.body.appendChild(iframe);
+ document.body.appendChild(elm);
+ test_obj.add_cleanup(function() {
+ document.body.removeChild(iframe);
+ document.body.removeChild(elm);
+ });
+ }
+
+ // follow hyperlink
+ function test_follow_link(tag) {
+ async_test(function() {
+ var elm = document.createElement(tag);
+ var iframe = document.createElement('iframe');
+ setup_navigation(elm, iframe, 'test_follow_link_'+tag, this);
+ iframe.onload = this.step_func_done(function() { // when the page navigated to has loaded
+ assert_equals(iframe.contentDocument.body.textContent, expected_current);
+ });
+ // follow the hyperlink
+ elm.click();
+ // check that navigation succeeded by ...??? XXX
+ }, 'follow hyperlink <'+tag+' href>',
+ {help:'https://html.spec.whatwg.org/multipage/multipage/links.html#following-hyperlinks'});
+ }
+
+ 'a, area, link'.split(', ').forEach(function(str) {
+ test_follow_link(str);
+ });
+
+ // follow hyperlink with ping attribute
+ function test_follow_link_ping(tag) {
+ async_test(function() {
+ var uuid = token();
+ var elm = document.createElement(tag);
+ // check if ping is supported
+ assert_true('ping' in elm, 'ping not supported');
+ elm.setAttribute('ping', stash_put + uuid);
+ var iframe = document.createElement('iframe');
+ setup_navigation(elm, iframe, 'test_follow_link_ping_'+tag, this);
+ // follow the hyperlink
+ elm.click();
+ // check that navigation succeeded by ...??? XXX
+ // check that the right URL was requested for the ping
+ poll_for_stash(this, uuid, expected_current);
+ }, 'hyperlink auditing <'+tag+' ping>',
+ {help:'https://html.spec.whatwg.org/multipage/multipage/links.html#hyperlink-auditing'});
+ }
+
+ 'a, area'.split(', ').forEach(function(str) {
+ test_follow_link_ping(str);
+ });
+
+ // navigating with meta refresh
+ async_test(function() {
+ var iframe = document.createElement('iframe');
+ iframe.src = blank;
+ document.body.appendChild(iframe);
+ this.add_cleanup(function() {
+ document.body.removeChild(iframe);
+ });
+ iframe.onload = this.step_func_done(function() {
+ var doc = iframe.contentDocument;
+ var got = doc.body.textContent;
+ if (got == '') {
+ doc.write('<meta http-equiv=refresh content="0; URL='+input_url_html+'">REFRESH');
+ doc.close();
+ return;
+ }
+ assert_equals(got, expected_current);
+ });
+ }, 'meta refresh',
+ {help:'https://html.spec.whatwg.org/multipage/multipage/semantics.html#attr-meta-http-equiv-refresh'});
+
+ // loading html (or actually svg to support <embed>)
+ function test_load_nested_browsing_context(tag, attr, spec_url) {
+ async_test(function() {
+ var id = 'test_load_nested_browsing_context_'+tag;
+ var elm = document.createElement(tag);
+ elm.setAttribute(attr, input_url_svg);
+ elm.name = id;
+ document.body.appendChild(elm);
+ this.add_cleanup(function() {
+ document.body.removeChild(elm);
+ });
+ elm.onload = this.step_func_done(function() {
+ assert_equals(window[id].document.documentElement.textContent, expected_current);
+ });
+
+ }, 'load nested browsing context <'+tag+' '+attr+'>',
+ {help:spec_url});
+ }
+
+ spec_url_load_nested_browsing_context = {
+ frame:'https://html.spec.whatwg.org/multipage/multipage/obsolete.html#process-the-frame-attributes',
+ iframe:'https://html.spec.whatwg.org/multipage/multipage/the-iframe-element.html#process-the-iframe-attributes',
+ object:'https://html.spec.whatwg.org/multipage/multipage/the-iframe-element.html#the-object-element',
+ embed:'https://html.spec.whatwg.org/multipage/multipage/the-iframe-element.html#the-embed-element-setup-steps'
+ };
+
+ 'frame src, iframe src, object data, embed src'.split(', ').forEach(function(str) {
+ var arr = str.split(' ');
+ test_load_nested_browsing_context(arr[0], arr[1], spec_url_load_nested_browsing_context[arr[0]]);
+ });
+
+ // loading css with <link>
+ async_test(function() {
+ var elm = document.createElement('link');
+ elm.href = input_url_css;
+ elm.rel = 'stylesheet';
+ document.head.appendChild(elm);
+ this.add_cleanup(function() {
+ document.head.removeChild(elm);
+ });
+ elm.onload = this.step_func_done(function() {
+ var got = elm.sheet.href;
+ assert_true(elm.sheet.href.indexOf(expected_current) > -1, 'sheet.href ' + msg(expected_current, got));
+ assert_equals(elm.sheet.cssRules[0].style.content, '"'+expected_current+'"', 'sheet.cssRules[0].style.content');
+ });
+ }, 'loading css <link>',
+ {help:['https://html.spec.whatwg.org/multipage/multipage/semantics.html#the-link-element',
+ 'https://html.spec.whatwg.org/multipage/multipage/semantics.html#styling']});
+
+ // loading js
+ async_test(function() {
+ var elm = document.createElement('script');
+ elm.src = input_url_js + '&var=test_load_js_got';
+ document.head.appendChild(elm); // no cleanup
+ elm.onload = this.step_func_done(function() {
+ assert_equals(window.test_load_js_got, expected_current);
+ });
+ }, 'loading js <script>',
+ {help:'https://html.spec.whatwg.org/multipage/multipage/scripting-1.html#prepare-a-script'});
+
+ // loading image
+ function test_load_image(tag, attr, spec_url) {
+ async_test(function() {
+ var elm = document.createElement(tag);
+ if (tag == 'input') {
+ elm.type = 'image';
+ }
+ elm.setAttribute(attr, input_url_png);
+ document.body.appendChild(elm);
+ this.add_cleanup(function() {
+ document.body.removeChild(elm);
+ });
+ elm.onload = this.step_func_done(function() {
+ var got = elm.offsetWidth;
+ assert_equals(got, query_to_image_width[expected_current], msg(expected_current, image_width_to_query[got]));
+ });
+ // <video poster> doesn't notify when the image is loaded so we need to poll :-(
+ var interval;
+ var check_video_width = function() {
+ var width = elm.offsetWidth;
+ if (width != 300 && width != 0) {
+ clearInterval(interval);
+ elm.onload();
+ }
+ }
+ if (tag == 'video') {
+ interval = setInterval(check_video_width, 10);
+ }
+ }, 'loading image <'+tag+' '+attr+'>',
+ {help:spec_url});
+ }
+
+ var query_to_image_width = {
+ '%E5':1,
+ '%C3%A5':2,
+ '%3F':16,
+ 'unknown query':256,
+ 'default intrinsic width':300
+ };
+
+ var image_width_to_query = {};
+ (function() {
+ for (var x in query_to_image_width) {
+ image_width_to_query[query_to_image_width[x]] = x;
+ }
+ })();
+
+ var spec_url_load_image = {
+ img:'https://html.spec.whatwg.org/multipage/multipage/embedded-content-1.html#update-the-image-data',
+ embed:'https://html.spec.whatwg.org/multipage/multipage/the-iframe-element.html#the-embed-element-setup-steps',
+ object:'https://html.spec.whatwg.org/multipage/multipage/the-iframe-element.html#the-object-element',
+ input:'https://html.spec.whatwg.org/multipage/multipage/states-of-the-type-attribute.html#image-button-state-(type=image)',
+ video:'https://html.spec.whatwg.org/multipage/multipage/the-video-element.html#poster-frame'
+ };
+
+ 'img src, embed src, object data, input src, video poster'.split(', ').forEach(function(str) {
+ var arr = str.split(' ');
+ test_load_image(arr[0], arr[1], spec_url_load_image[arr[0]]);
+ });
+
+ // XXX test <img srcset> or its successor
+ // <menuitem icon> could also be tested but the spec doesn't require it to be loaded...
+
+ // loading video
+ function test_load_video(tag, use_source_element) {
+ async_test(function() {
+ var elm = document.createElement(tag);
+ var video_ext = '';
+ if (elm.canPlayType('video/ogg; codecs="theora,vorbis"')) {
+ video_ext = 'ogv';
+ } else if (elm.canPlayType('video/mp4; codecs="avc1.42E01E,mp4a.40.2"')) {
+ video_ext = 'mp4';
+ }
+ assert_not_equals(video_ext, '', 'no supported video format');
+ var source;
+ if (use_source_element) {
+ source = document.createElement('source');
+ elm.appendChild(source);
+ } else {
+ source = elm;
+ }
+ source.src = input_url_video + '&ext=' + video_ext;
+ elm.preload = 'auto';
+ elm.load();
+ this.add_cleanup(function() {
+ elm.removeAttribute('src');
+ if (elm.firstChild) {
+ elm.removeChild(elm.firstChild);
+ }
+ elm.load();
+ });
+ elm.onloadedmetadata = this.step_func_done(function() {
+ var got = Math.round(elm.duration);
+ assert_equals(got, query_to_video_duration[expected_current], msg(expected_current, video_duration_to_query[got]));
+ });
+ }, 'loading video <'+tag+'>' + (use_source_element ? '<source>' : ''),
+ {help:'https://html.spec.whatwg.org/multipage/multipage/the-video-element.html#concept-media-load-algorithm'});
+ }
+
+ var query_to_video_duration = {
+ '%E5':3,
+ '%C3%A5':5,
+ '%3F':30,
+ 'unknown query':300,
+ 'Infinity':Infinity,
+ 'NaN':NaN
+ };
+
+ var video_duration_to_query = {};
+ (function() {
+ for (var x in query_to_video_duration) {
+ video_duration_to_query[query_to_video_duration[x]] = x;
+ }
+ })();
+
+ 'video, audio'.split(', ').forEach(function(str) {
+ test_load_video(str);
+ test_load_video(str, true);
+ });
+
+ // loading webvtt
+ async_test(function() {
+ var video = document.createElement('video');
+ var track = document.createElement('track');
+ video.appendChild(track);
+ track.src = input_url_webvtt;
+ track.track.mode = 'showing';
+ track.onload = this.step_func_done(function() {
+ var got = track.track.cues[0].text;
+ assert_equals(got, expected_current);
+ });
+ }, 'loading webvtt <track>',
+ {help:'https://html.spec.whatwg.org/multipage/multipage/the-video-element.html#track-url'});
+
+ // XXX downloading seems hard to automate
+ // <a href download>
+ // <area href download>
+
+ // submit forms
+ function test_submit_form(tag, attr) {
+ async_test(function(){
+ var elm = document.createElement(tag);
+ elm.setAttribute(attr, input_url_html);
+ var form;
+ var button;
+ if (tag == 'form') {
+ form = elm;
+ button = document.createElement('button');
+ } else {
+ form = document.createElement('form');
+ button = elm;
+ }
+ form.method = 'post';
+ form.appendChild(button);
+ var iframe = document.createElement('iframe');
+ var id = 'test_submit_form_' + tag;
+ iframe.name = id;
+ form.target = id;
+ button.type = 'submit';
+ document.body.appendChild(form);
+ document.body.appendChild(iframe);
+ this.add_cleanup(function() {
+ document.body.removeChild(form);
+ document.body.removeChild(iframe);
+ });
+ button.click();
+ iframe.onload = this.step_func_done(function() {
+ var got = iframe.contentDocument.body.textContent;
+ if (got == '') {
+ return;
+ }
+ assert_equals(got, expected_current);
+ });
+ }, 'submit form <'+tag+' '+attr+'>',
+ {help:'https://html.spec.whatwg.org/multipage/multipage/association-of-controls-and-forms.html#concept-form-submit'});
+ }
+
+ 'form action, input formaction, button formaction'.split(', ').forEach(function(str) {
+ var arr = str.split(' ');
+ test_submit_form(arr[0], arr[1]);
+ });
+
+ // <base href>
+ async_test(function() {
+ var iframe = document.createElement('iframe');
+ iframe.src = blank;
+ document.body.appendChild(iframe);
+ this.add_cleanup(function() {
+ document.body.removeChild(iframe);
+ });
+ iframe.onload = this.step_func_done(function() {
+ var doc = iframe.contentDocument;
+ doc.write('<!doctype html><base href="'+input_url+'"><a href></a>');
+ doc.close();
+ var got_baseURI = doc.baseURI;
+ assert_true(got_baseURI.indexOf(expected_current) > -1, msg(expected_current, got_baseURI), 'doc.baseURI');
+ var got_a_href = doc.links[0].href;
+ assert_true(got_a_href.indexOf(expected_current) > -1, msg(expected_current, got_a_href), 'a.href');
+ });
+ }, '<base href>',
+ {help:['https://html.spec.whatwg.org/multipage/multipage/semantics.html#set-the-frozen-base-url',
+ 'https://dom.spec.whatwg.org/#dom-node-baseuri',
+ 'https://html.spec.whatwg.org/multipage/multipage/text-level-semantics.html#the-a-element']});
+
+ // XXX itemid is exposed in JSON drag-and-drop but seems hard to automate
+
+ // microdata values
+ function test_microdata_values(tag, attr) {
+ test(function() {
+ var elm = document.createElement(tag);
+ elm.setAttribute('itemprop', '');
+ elm.setAttribute(attr, input_url_html);
+ var got = elm.itemValue;
+ assert_not_equals(got, undefined, 'itemValue not supported');
+ assert_true(got.indexOf(expected_current) > -1, msg(expected_current, got));
+ }, 'microdata values <'+tag+' '+attr+'>',
+ {help:'https://html.spec.whatwg.org/multipage/multipage/microdata.html#concept-property-value'});
+ }
+
+ 'audio src, embed src, iframe src, img src, source src, track src, video src, a href, area href, link href, object data'.split(', ').forEach(function(str) {
+ var arr = str.split(' ');
+ test_microdata_values(arr[0], arr[1]);
+ });
+
+ // XXX drag and drop (<a href> or <img src>) seems hard to automate
+
+ // Worker()
+ async_test(function() {
+ var worker = new Worker(input_url_worker);
+ worker.onmessage = this.step_func_done(function(e) {
+ assert_equals(e.data, expected_current);
+ });
+ }, 'Worker constructor',
+ {help:'https://html.spec.whatwg.org/multipage/multipage/workers.html#dom-worker'});
+
+ // SharedWorker()
+ async_test(function() {
+ var worker = new SharedWorker(input_url_sharedworker);
+ worker.port.onmessage = this.step_func_done(function(e) {
+ assert_equals(e.data, expected_current);
+ });
+ }, 'SharedWorker constructor',
+ {help:'https://html.spec.whatwg.org/multipage/multipage/workers.html#dom-sharedworker'});
+
+ // EventSource()
+ async_test(function() {
+ var source = new EventSource(input_url_eventstream);
+ this.add_cleanup(function() {
+ source.close();
+ });
+ source.onmessage = this.step_func_done(function(e) {
+ assert_equals(e.data, expected_current);
+ });
+ }, 'EventSource constructor',
+ {help:'https://html.spec.whatwg.org/multipage/multipage/comms.html#dom-eventsource'});
+
+ // EventSource#url
+ test(function() {
+ var source = new EventSource(input_url_eventstream);
+ source.close();
+ var got = source.url;
+ assert_true(source.url.indexOf(expected_current) > -1, msg(expected_current, got));
+ }, 'EventSource#url',
+ {help:'https://html.spec.whatwg.org/multipage/multipage/comms.html#dom-eventsource'});
+
+ // XMLDocument#load()
+ async_test(function() {
+ var doc = document.implementation.createDocument(null, "x");
+ doc.load(input_url_svg);
+ doc.onload = this.step_func_done(function() {
+ assert_equals(doc.documentElement.textContent, expected_current);
+ });
+ }, 'XMLDocument#load()',
+ {help:'https://html.spec.whatwg.org/multipage/multipage/dom.html#dom-xmldocument-load'});
+
+ // window.open
+ async_test(function() {
+ var id = 'test_window_open';
+ var iframe = document.createElement('iframe');
+ iframe.name = id;
+ document.body.appendChild(iframe);
+ this.add_cleanup(function() {
+ document.body.removeChild(iframe);
+ });
+ window.open(input_url_html, id);
+ iframe.onload = this.step_func(function() {
+ var got = iframe.contentDocument.body.textContent;
+ if (got != "") {
+ assert_equals(got, expected_current);
+ this.done();
+ }
+ });
+ }, 'window.open()',
+ {help:'https://html.spec.whatwg.org/multipage/multipage/browsers.html#dom-open'});
+
+ // location
+ function test_location(func, desc) {
+ async_test(function() {
+ var iframe = document.createElement('iframe');
+ document.body.appendChild(iframe);
+ this.add_cleanup(function() {
+ document.body.removeChild(iframe);
+ });
+ func(iframe.contentWindow, input_url_html);
+ iframe.onload = this.step_func(function() {
+ var got = iframe.contentDocument.body.textContent;
+ if (got != '') {
+ assert_equals(got, expected_current);
+ this.done();
+ }
+ });
+ }, desc,
+ {help:'https://html.spec.whatwg.org/multipage/multipage/history.html#the-location-interface'});
+ }
+ [[function(win, input) { win.location = input; }, "location [PutForwards]"],
+ [function(win, input) { win.location.assign(input); }, "location.assign()"],
+ [function(win, input) { win.location.replace(input); }, "location.replace()"],
+ [function(win, input) { win.location.href = input; }, "location.href"]].forEach(function(arr) {
+ test_location(arr[0], arr[1]);
+ });
+
+ // location.search
+ async_test(function() {
+ var iframe = document.createElement('iframe');
+ iframe.src = input_url_html;
+ document.body.appendChild(iframe);
+ this.add_cleanup(function() {
+ document.body.removeChild(iframe);
+ });
+ var i = 0;
+ iframe.onload = this.step_func(function() {
+ i++;
+ if (i == 1) {
+ iframe.contentWindow.location.search = '?' + input_url_html.split('?')[1] + '&other=foobar';
+ } else {
+ var got = iframe.contentDocument.body.textContent;
+ assert_equals(got, expected_current);
+ this.done();
+ }
+ });
+ }, 'location.search',
+ {help:['https://html.spec.whatwg.org/multipage/multipage/history.html#the-location-interface',
+ 'http://url.spec.whatwg.org/#dom-url-search']});
+
+ // a.search, area.search
+ function test_hyperlink_search(tag) {
+ test(function() {
+ var elm = document.createElement(tag);
+ var input_arr = input_url_html.split('?');
+ elm.href = input_arr[0];
+ elm.search = '?' + input_arr[1];
+ var got_href = elm.getAttribute('href');
+ assert_true(got_href.indexOf(expected_current) > -1, 'href content attribute ' + msg(expected_current, got_href));
+ var got_search = elm.search;
+ assert_true(got_search.indexOf(expected_current) > -1, 'getting .search '+msg(expected_current, got_search));
+ }, '<'+tag+'>.search',
+ {help:['https://html.spec.whatwg.org/multipage/multipage/text-level-semantics.html#the-'+tag+'-element',
+ 'http://url.spec.whatwg.org/#dom-url-search']});
+ }
+ 'a, area'.split(', ').forEach(function(str) {
+ test_hyperlink_search(str);
+ });
+
+ // history.pushState
+ // history.replaceState
+ function test_history(prop) {
+ async_test(function() {
+ var iframe = document.createElement('iframe');
+ iframe.src = blank;
+ document.body.appendChild(iframe);
+ this.add_cleanup(function() {
+ document.body.removeChild(iframe);
+ });
+ iframe.onload = this.step_func_done(function() {
+ iframe.contentWindow.history[prop](null, null, input_url_html); // this should resolve against the test's URL, not the iframe's URL
+ var got = iframe.contentWindow.location.href;
+ assert_true(got.indexOf(expected_current) > -1, msg(expected_current, got));
+ assert_equals(got.indexOf('/resources/resources/'), -1, 'url was resolved against the iframe\'s URL instead of the settings object\'s API base URL');
+ });
+ }, 'history.'+prop,
+ {help:'https://html.spec.whatwg.org/multipage/multipage/history.html#dom-history-'+prop.toLowerCase()});
+ }
+
+ 'pushState, replaceState'.split(', ').forEach(function(str) {
+ test_history(str);
+ });
+
+ // SVG
+ var ns = {svg:'http://www.w3.org/2000/svg', xlink:'http://www.w3.org/1999/xlink'};
+ // a
+ async_test(function() {
+ SVGAElement; // check support
+ var iframe = document.createElement('iframe');
+ var id = 'test_svg_a';
+ iframe.name = id;
+ var svg = document.createElementNS(ns.svg, 'svg');
+ var a = document.createElementNS(ns.svg, 'a');
+ a.setAttributeNS(ns.xlink, 'xlink:href', input_url_html);
+ a.setAttribute('target', id);
+ var span = document.createElement('span');
+ a.appendChild(span);
+ svg.appendChild(a);
+ document.body.appendChild(iframe);
+ document.body.appendChild(svg);
+ this.add_cleanup(function() {
+ document.body.removeChild(iframe);
+ document.body.removeChild(svg);
+ });
+ span.click();
+ iframe.onload = this.step_func_done(function() {
+ var got = iframe.contentDocument.body.textContent;
+ if (got != '') {
+ assert_equals(got, expected_current);
+ }
+ });
+ }, 'SVG <a>');
+
+ // feImage, image, use
+ function test_svg(func, tag) {
+ async_test(function() {
+ var uuid = token();
+ var id = 'test_svg_'+tag;
+ var svg = document.createElementNS(ns.svg, 'svg');
+ var parent = func(svg, id);
+ var elm = document.createElementNS(ns.svg, tag);
+ elm.setAttributeNS(ns.xlink, 'xlink:href', stash_put + uuid + '#foo');
+ parent.appendChild(elm);
+ document.body.appendChild(svg);
+ this.add_cleanup(function() {
+ document.body.removeChild(svg);
+ });
+ poll_for_stash(this, uuid, expected_current);
+ }, 'SVG <' + tag + '>',
+ {help:'https://www.w3.org/Bugs/Public/show_bug.cgi?id=24148'});
+ }
+
+ [[function(svg, id) {
+ SVGFEImageElement; // check support
+ var filter = document.createElementNS(ns.svg, 'filter');
+ filter.setAttribute('id', id);
+ svg.appendChild(filter);
+ var rect = document.createElementNS(ns.svg, 'rect');
+ rect.setAttribute('filter', 'url(#'+id+')');
+ svg.appendChild(rect);
+ return filter;
+ }, 'feImage'],
+ [function(svg, id) { SVGImageElement; return svg; }, 'image'],
+ [function(svg, id) { SVGUseElement; return svg; }, 'use']].forEach(function(arr) {
+ test_svg(arr[0], arr[1]);
+ });
+
+ // UTF-8:
+ // XHR
+ async_test(function() {
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', input_url_html);
+ xhr.onload = this.step_func_done(function() {
+ assert_equals(xhr.response, expected_utf8);
+ });
+ xhr.send();
+ }, 'XMLHttpRequest#open()',
+ {help:'https://xhr.spec.whatwg.org/#the-open()-method'});
+
+ // in a worker
+ async_test(function() {
+ var worker = new Worker(input_url_worker_importScripts);
+ worker.onmessage = this.step_func_done(function(e) {
+ assert_equals(e.data, expected_utf8);
+ });
+ }, 'importScripts() in a dedicated worker',
+ {help:['https://html.spec.whatwg.org/multipage/multipage/workers.html#set-up-a-worker-script-settings-object',
+ 'https://html.spec.whatwg.org/multipage/multipage/workers.html#dom-workerglobalscope-importscripts']});
+
+ async_test(function() {
+ var worker = new Worker(input_url_worker_worker);
+ worker.onmessage = this.step_func_done(function(e) {
+ assert_equals(e.data, expected_utf8);
+ });
+ }, 'Worker() in a dedicated worker',
+ {help:['https://html.spec.whatwg.org/multipage/multipage/workers.html#set-up-a-worker-script-settings-object',
+ 'https://html.spec.whatwg.org/multipage/multipage/workers.html#dom-worker']});
+
+ async_test(function() {
+ var worker = new Worker(input_url_worker_sharedworker);
+ worker.onmessage = this.step_func_done(function(e) {
+ assert_equals(e.data, expected_utf8);
+ });
+ }, 'SharedWorker() in a dedicated worker',
+ {help:['https://html.spec.whatwg.org/multipage/multipage/workers.html#set-up-a-worker-script-settings-object',
+ 'https://html.spec.whatwg.org/multipage/multipage/workers.html#dom-sharedworker']});
+
+ async_test(function() {
+ var worker = new SharedWorker(input_url_sharedworker_importScripts);
+ worker.port.onmessage = this.step_func_done(function(e) {
+ assert_equals(e.data, expected_utf8);
+ });
+ }, 'importScripts() in a shared worker',
+ {help:['https://html.spec.whatwg.org/multipage/multipage/workers.html#set-up-a-worker-script-settings-object',
+ 'https://html.spec.whatwg.org/multipage/multipage/workers.html#dom-workerglobalscope-importscripts']});
+
+ async_test(function() {
+ var worker = new SharedWorker(input_url_sharedworker_worker);
+ worker.port.onmessage = this.step_func_done(function(e) {
+ assert_equals(e.data, expected_utf8);
+ });
+ }, 'Worker() in a shared worker',
+ {help:['https://html.spec.whatwg.org/multipage/multipage/workers.html#set-up-a-worker-script-settings-object',
+ 'https://html.spec.whatwg.org/multipage/multipage/workers.html#dom-worker']});
+
+ async_test(function() {
+ var worker = new SharedWorker(input_url_sharedworker_sharedworker);
+ worker.port.onmessage = this.step_func_done(function(e) {
+ assert_equals(e.data, expected_utf8);
+ });
+ }, 'SharedWorker() in a shared worker',
+ {help:['https://html.spec.whatwg.org/multipage/multipage/workers.html#set-up-a-worker-script-settings-object',
+ 'https://html.spec.whatwg.org/multipage/multipage/workers.html#dom-sharedworker']});
+
+ // WebSocket()
+ async_test(function(){
+ var ws = new WebSocket('ws://{{host}}:{{ports[ws][0]}}/echo-query?\u00E5');
+ this.add_cleanup(function() {
+ ws.close();
+ });
+ ws.onmessage = this.step_func_done(function(e) {
+ assert_equals(e.data, expected_utf8);
+ });
+ }, 'WebSocket constructor',
+ {help:'https://html.spec.whatwg.org/multipage/multipage/network.html#parse-a-websocket-url\'s-components'});
+
+ // WebSocket#url
+ test(function(){
+ var ws = new WebSocket('ws://{{host}}:{{ports[ws][0]}}/echo-query?\u00E5');
+ ws.close();
+ var got = ws.url;
+ assert_true(ws.url.indexOf(expected_utf8) > -1, msg(expected_utf8, got));
+ }, 'WebSocket#url',
+ {help:'https://html.spec.whatwg.org/multipage/multipage/network.html#dom-websocket-url'});
+
+ // Parsing cache manifest
+ function test_cache_manifest(mode) {
+ async_test(function() {
+ var iframe = document.createElement('iframe');
+ var uuid = token();
+ iframe.src = 'resources/page-using-manifest.py?id='+uuid+'&encoding='+encoding+'&mode='+mode;
+ document.body.appendChild(iframe);
+ this.add_cleanup(function() {
+ document.body.removeChild(iframe);
+ });
+ poll_for_stash(this, uuid, expected_utf8);
+ }, 'Parsing cache manifest (' + mode + ')',
+ {help:'https://html.spec.whatwg.org/multipage/multipage/offline.html#parse-a-manifest'});
+ }
+
+ 'CACHE, FALLBACK, NETWORK'.split(', ').forEach(function(str) {
+ test_cache_manifest(str);
+ });
+
+ // CSS
+ function test_css(tmpl, expected_cssom, encoding, use_style_element) {
+ var desc = ['CSS', (use_style_element ? '<style>' : '<link> (' + encoding + ')'), tmpl].join(' ');
+ async_test(function(){
+ css_is_supported(tmpl, expected_cssom, this);
+ var uuid = token();
+ var id = 'test_css_' + uuid;
+ var url = 'url(stash.py?q=%s&action=put&id=' + uuid + ')';
+ tmpl = tmpl.replace(/<id>/g, id).replace(/<url>/g, url);
+ var link;
+ if (use_style_element) {
+ link = document.createElement('style');
+ link.textContent = tmpl.replace(/%s/g, '\u00E5').replace(/stash\.py/g, 'resources/stash.py');
+ } else {
+ link = document.createElement('link');
+ link.rel = 'stylesheet';
+ link.href = 'resources/css-tmpl.py?encoding='+encoding+'&tmpl='+encodeURIComponent(tmpl);
+ }
+ var div = document.createElement('div');
+ div.id = id;
+ div.textContent='x';
+ document.head.appendChild(link);
+ document.body.appendChild(div);
+ this.add_cleanup(function() {
+ document.head.removeChild(link);
+ document.body.removeChild(div);
+ });
+ poll_for_stash(this, uuid, expected_utf8);
+ }, desc,
+ {help:'https://www.w3.org/Bugs/Public/show_bug.cgi?id=23968'});
+ }
+
+ // fail fast if the input doesn't parse into the expected cssom
+ function css_is_supported(tmpl, expected_cssom, test_obj) {
+ if (expected_cssom === null) {
+ return;
+ }
+ var style = document.createElement('style');
+ style.textContent = tmpl.replace(/<id>/g, 'x').replace(/<url>/g, 'url(data:,)');
+ document.head.appendChild(style);
+ test_obj.add_cleanup(function() {
+ document.head.removeChild(style);
+ });
+ assert_equals(style.sheet.cssRules.length, expected_cssom.length, 'number of style rules');
+ for (var i = 0; i < expected_cssom.length; ++i) {
+ if (expected_cssom[i] === null) {
+ continue;
+ }
+ assert_equals(style.sheet.cssRules[i].style.length, expected_cssom[i], 'number of declarations in style rule #'+i);
+ }
+ }
+
+ [['#<id> { background-image:<url> }', [1] ],
+ ['#<id> { border-image-source:<url> }', [1] ],
+ ['#<id>::before { content:<url> }', [1] ],
+ ['@font-face { font-family:<id>; src:<url> } #<id> { font-family:<id> }', [null, 1] ],
+ ['#<id> { display:list-item; list-style-image:<url> }', [2] ],
+ ['@import <url>;', null ],
+ // XXX maybe cursor isn't suitable for automation here if browsers delay fetching it
+ ['#<id> { cursor:<url>, pointer }', [1] ]].forEach(function(arr) {
+ var input = arr[0];
+ var expected_cssom = arr[1];
+ var other_encoding = encoding == 'utf-8' ? 'windows-1252' : 'utf-8';
+ test_css(input, expected_cssom, encoding);
+ test_css(input, expected_cssom, other_encoding);
+ test_css(input, expected_cssom, null, true);
+ });
+
+ // XXX maybe test if they become relevant:
+ // binding (obsolete?)
+ // aural: cue-after, cue-before, play-during (not implemented?)
+ // hyphenate-resource (not implemented?)
+ // image() (not implemented?)
+
+ // <?xml-stylesheet?>
+ async_test(function() {
+ var iframe = document.createElement('iframe');
+ iframe.src = input_url_xmlstylesheet_css;
+ document.body.appendChild(iframe);
+ this.add_cleanup(function() {
+ document.body.removeChild(iframe);
+ });
+ iframe.onload = this.step_func_done(function() {
+ assert_equals(iframe.contentDocument.firstChild.sheet.cssRules[0].style.content, '"' + expected_utf8 + '"');
+ });
+ }, '<?xml-stylesheet?> (CSS)',
+ {help:'http://dev.w3.org/csswg/cssom/#requirements-on-user-agents-implementing-the-xml-stylesheet-processing-instruction'});
+
+ // new URL()
+ test(function() {
+ var url = new URL('http://example.org/'+input_url);
+ var expected = expected_utf8;
+ assert_true(url.href.indexOf(expected) > -1, 'url.href '+msg(expected, url.href));
+ assert_true(url.search.indexOf(expected) > -1, 'url.search '+msg(expected, url.search));
+ }, 'URL constructor, url',
+ {help:'http://url.spec.whatwg.org/#dom-url'});
+
+ test(function() {
+ var url = new URL('', 'http://example.org/'+input_url);
+ var expected = expected_utf8;
+ assert_true(url.href.indexOf(expected) > -1, 'url.href '+msg(expected, url.href));
+ assert_true(url.search.indexOf(expected) > -1, 'url.search '+msg(expected, url.search));
+ }, 'URL constructor, base',
+ {help:'http://url.spec.whatwg.org/#dom-url'});
+
+ // Test different schemes
+ function test_scheme(url, utf8) {
+ test(function() {
+ var a = document.createElement('a');
+ a.setAttribute('href', url);
+ var got = a.href;
+ var expected = utf8 ? expected_utf8 : expected_current;
+ assert_true(got.indexOf(expected) != -1, msg(expected, got));
+ }, 'Scheme ' + url.split(':')[0] + ' (getting <a>.href)');
+ }
+
+ var test_scheme_urls = ['ftp://example.invalid/?x=\u00E5',
+ 'file:///?x=\u00E5',
+ 'gopher://example.invalid/?x=\u00E5',
+ 'http://example.invalid/?x=\u00E5',
+ 'https://example.invalid/?x=\u00E5',
+ ];
+
+ var test_scheme_urls_utf8 = ['ws://example.invalid/?x=\u00E5',
+ 'wss://example.invalid/?x=\u00E5',
+ 'mailto:example@invalid?x=\u00E5',
+ 'data:text/plain;charset='+encoding+',?x=\u00E5',
+ 'javascript:"?x=\u00E5"',
+ 'ftps://example.invalid/?x=\u00E5',
+ 'httpbogus://example.invalid/?x=\u00E5',
+ 'bitcoin:foo?x=\u00E5',
+ 'geo:foo?x=\u00E5',
+ 'im:foo?x=\u00E5',
+ 'irc:foo?x=\u00E5',
+ 'ircs:foo?x=\u00E5',
+ 'magnet:foo?x=\u00E5',
+ 'mms:foo?x=\u00E5',
+ 'news:foo?x=\u00E5',
+ 'nntp:foo?x=\u00E5',
+ 'sip:foo?x=\u00E5',
+ 'sms:foo?x=\u00E5',
+ 'smsto:foo?x=\u00E5',
+ 'ssh:foo?x=\u00E5',
+ 'tel:foo?x=\u00E5',
+ 'urn:foo?x=\u00E5',
+ 'webcal:foo?x=\u00E5',
+ 'wtai:foo?x=\u00E5',
+ 'xmpp:foo?x=\u00E5',
+ 'web+http:foo?x=\u00E5',
+ ];
+
+ test_scheme_urls.forEach(function(url) {
+ test_scheme(url);
+ });
+
+ test_scheme_urls_utf8.forEach(function(url) {
+ test_scheme(url, true);
+ });
+
+ done();
+};
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/urls/resolving-urls/query-encoding/resources/resource.py b/tests/wpt/web-platform-tests/html/infrastructure/urls/resolving-urls/query-encoding/resources/resource.py
new file mode 100644
index 00000000000..20d4bde02fc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/urls/resolving-urls/query-encoding/resources/resource.py
@@ -0,0 +1,131 @@
+import os
+import re
+
+def main(request, response):
+ type = request.GET['type']
+ encoding = request.GET['encoding']
+ # We want the raw input for 'q'
+ q = re.search(r'q=([^&]+)', request.url_parts.query).groups()[0]
+ if type == 'html':
+ return [("Content-Type", "text/html; charset=utf-8")], q
+ elif type == 'css':
+ return [("Content-Type", "text/css; charset=utf-8")], "#test::before { content:'%s' }" % q
+ elif type == 'js':
+ return [("Content-Type", "text/javascript; charset=utf-8")], "%s = '%s';" % (request.GET['var'], q)
+ elif type == 'worker':
+ return [("Content-Type", "text/javascript")], "postMessage('%s'); close();" % q
+ elif type == 'sharedworker':
+ return [("Content-Type", "text/javascript")], "onconnect = function(e) { e.source.postMessage('%s'); close(); };" % q
+ elif type == 'worker_importScripts':
+ return ([("Content-Type", "text/javascript; charset=%s" % encoding)], # charset should be ignored for workers
+ """try {
+ var x = 'importScripts failed to run';
+ importScripts('?q=\\u00E5&type=js&var=x&encoding=%s');
+ postMessage(x);
+ close();
+ } catch(ex) {
+ postMessage(String(ex));
+ }""" % encoding)
+ elif type == 'worker_worker':
+ return ([("Content-Type", "text/javascript; charset=%s" % encoding)], # charset should be ignored for workers
+ """try {
+ var worker = new Worker('?q=\\u00E5&type=worker&encoding=%s');
+ worker.onmessage = function(e) {
+ postMessage(e.data);
+ close();
+ };
+ } catch(ex) {
+ postMessage(String(ex));
+ }""" % encoding)
+ elif type =='worker_sharedworker':
+ return ([("Content-Type", "text/javascript; charset=%s" % encoding)], # charset should be ignored for workers
+ """try {
+ var worker = new SharedWorker('?q=\\u00E5&type=sharedworker&encoding=%s');
+ worker.port.onmessage = function(e) {
+ postMessage(e.data);
+ close();
+ };
+ } catch(ex) {
+ postMessage(String(ex));
+ }""" % encoding)
+ elif type == 'sharedworker_importScripts':
+ return ([("Content-Type", "text/javascript; charset=%s" % request.GET['encoding'])], # charset should be ignored for workers
+ """onconnect = function(e) {
+ var connect_port = e.source;
+ try {
+ var x = 'importScripts failed to run';
+ importScripts('?q=\\u00E5&type=js&var=x&encoding=%s');
+ connect_port.postMessage(x);
+ close();
+ } catch(ex) {
+ connect_port.postMessage(String(ex));
+ }
+ };""" % encoding)
+ elif type == 'sharedworker_worker':
+ return ([("Content-Type", "text/javascript; charset=%s" % encoding)], # charset should be ignored for workers
+ """onconnect = function(e) {
+ var connect_port = e.source;
+ try {
+ var worker = new Worker('?q=\\u00E5&type=worker&encoding=%s');
+ worker.onmessage = function(e) {
+ connect_port.postMessage(e.data);
+ close();
+ };
+ } catch(ex) {
+ connect_port.postMessage(String(ex));
+ }
+ };""" % encoding)
+ elif type == 'sharedworker_sharedworker':
+ return ([("Content-Type", "text/javascript; charset=%s" % encoding)], # charset should be ignored for workers
+ """onconnect = function(e) {
+ var connect_port = e.source;
+ try {
+ onerror = function(msg) {
+ connect_port.postMessage(msg);
+ close();
+ return false;
+ };
+ var worker = new SharedWorker('?q=\\u00E5&type=sharedworker&encoding=%s');
+ worker.port.onmessage = function(e) {
+ connect_port.postMessage(e.data);
+ close();
+ };
+ } catch(ex) {
+ connect_port.postMessage(String(ex));
+ }
+ };""" % encoding)
+ elif type == 'eventstream':
+ return [("Content-Type", "text/event-stream")], "data: %s\n\n" % q
+ elif type == 'svg':
+ return [("Content-Type", "image/svg+xml")], "<svg xmlns='http://www.w3.org/2000/svg'>%s</svg>" % q
+ elif type == 'xmlstylesheet_css':
+ return ([("Content-Type", "application/xhtml+xml; charset=%s" % encoding)],
+ (u"""<?xml-stylesheet href="?q=&#x00E5;&amp;type=css&amp;encoding=%s"?><html xmlns="http://www.w3.org/1999/xhtml"/>""" % encoding)
+ .encode(encoding))
+ elif type == 'png':
+ if q == '%E5':
+ image = 'green-1x1.png'
+ elif q == '%C3%A5':
+ image = 'green-2x2.png'
+ elif q == '%3F':
+ image = 'green-16x16.png'
+ else:
+ image = 'green-256x256.png'
+ rv = open(os.path.join(request.doc_root, "images", image)).read()
+ return [("Content-Type", "image/png")], rv
+ elif type == 'video':
+ ext = request.GET['ext']
+ if q == '%E5':
+ video = 'A4' # duration: 3
+ elif q == '%C3%A5':
+ video = 'movie_5' # duration: 5
+ elif q == '%3F':
+ video = 'green-at-15' # duration: 30
+ else:
+ video = 'movie_300' # duration: 300
+ rv = open(os.path.join(request.doc_root, "media", "%s.%s" % (video, ext))).read()
+ if ext == 'ogv':
+ ext = 'ogg'
+ return [("Content-Type", "video/%s" % ext)], rv
+ elif type == 'webvtt':
+ return [("Content-Type", "text/vtt")], "WEBVTT\n\n00:00:00.000 --> 00:00:01.000\n%s" % q
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/urls/resolving-urls/query-encoding/resources/stash.py b/tests/wpt/web-platform-tests/html/infrastructure/urls/resolving-urls/query-encoding/resources/stash.py
new file mode 100644
index 00000000000..d6e3dd5ea50
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/urls/resolving-urls/query-encoding/resources/stash.py
@@ -0,0 +1,16 @@
+import time
+import re
+
+def main(request, response):
+ key = request.GET['id']
+ action = request.GET['action']
+ if action == 'put':
+ # We want the raw input for 'q'
+ q = re.search(r'q=([^&]+)', request.url_parts.query).groups()[0]
+ request.server.stash.put(key, q)
+ return [("Content-Type", "text/html")], 'Put %s' % q
+ else:
+ q = request.server.stash.take(key)
+ if q != None:
+ return [("Content-Type", "text/html")], q
+ return [], ""
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/urls/resolving-urls/query-encoding/utf-16be.html b/tests/wpt/web-platform-tests/html/infrastructure/urls/resolving-urls/query-encoding/utf-16be.html
new file mode 100644
index 00000000000..80a3970fc1a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/urls/resolving-urls/query-encoding/utf-16be.html
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/urls/resolving-urls/query-encoding/utf-16le.html b/tests/wpt/web-platform-tests/html/infrastructure/urls/resolving-urls/query-encoding/utf-16le.html
new file mode 100644
index 00000000000..8d91dcbd8e0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/urls/resolving-urls/query-encoding/utf-16le.html
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/urls/resolving-urls/query-encoding/utf-8.html b/tests/wpt/web-platform-tests/html/infrastructure/urls/resolving-urls/query-encoding/utf-8.html
new file mode 100644
index 00000000000..fcf43e0a988
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/urls/resolving-urls/query-encoding/utf-8.html
@@ -0,0 +1,9 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Resolving URLs, URL character encoding, utf-8</title>
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/utils.js"></script>
+<div id=log></div>
+<script src="resources/resolve-url.js?encoding=utf-8&pipe=sub"></script>
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/urls/resolving-urls/query-encoding/windows-1251.html b/tests/wpt/web-platform-tests/html/infrastructure/urls/resolving-urls/query-encoding/windows-1251.html
new file mode 100644
index 00000000000..23d33f9f733
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/urls/resolving-urls/query-encoding/windows-1251.html
@@ -0,0 +1,9 @@
+<!doctype html>
+<meta charset=windows-1251>
+<title>Resolving URLs, URL character encoding, windows-1251</title>
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/utils.js"></script>
+<div id=log></div>
+<script src="resources/resolve-url.js?encoding=windows-1251&pipe=sub"></script>
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/urls/resolving-urls/query-encoding/windows-1252.html b/tests/wpt/web-platform-tests/html/infrastructure/urls/resolving-urls/query-encoding/windows-1252.html
new file mode 100644
index 00000000000..642c82ab4f0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/urls/resolving-urls/query-encoding/windows-1252.html
@@ -0,0 +1,9 @@
+<!doctype html>
+<meta charset=windows-1252>
+<title>Resolving URLs, URL character encoding, windows-1252</title>
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/utils.js"></script>
+<div id=log></div>
+<script src="resources/resolve-url.js?encoding=windows-1252&pipe=sub"></script>
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/urls/terminology-0/.gitkeep b/tests/wpt/web-platform-tests/html/infrastructure/urls/terminology-0/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/urls/terminology-0/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/urls/terminology-0/document-base-url.html b/tests/wpt/web-platform-tests/html/infrastructure/urls/terminology-0/document-base-url.html
new file mode 100644
index 00000000000..8f37873caea
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/urls/terminology-0/document-base-url.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: document base URL</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+ iframe { display: none }
+</style>
+<body onload="on_load()">
+ <div id="log"></div>
+ <script>
+ var t1 = async_test("The document base URL of a document containing one or more base elements with href attributes is the frozen base URL of the first base element in the document that has an href attribute, in tree order.");
+
+ function on_load() {
+ t1.step(function () {
+ var base = document.createElement("base");
+ base.setAttribute("href", "/foo/bar");
+ document.head.appendChild(base);
+ assert_equals(document.baseURI, base.href, "The document base URL should be URL of the first base element that has an href attribute.");
+ });
+ t1.done();
+ }
+
+ async_test(function() {
+ var iframe = document.createElement("iframe");
+ iframe.onload = this.step_func_done(function () {
+ assert_equals(iframe.contentDocument.baseURI, iframe.contentDocument.location.href, "The document base URL should be the document's address.");
+ });
+ iframe.setAttribute("src", "/common/blank.html");
+ document.body.appendChild(iframe);
+ }, "The fallback base URL of a document containing no base element is the document's address.");
+
+ async_test(function () {
+ var iframe = document.createElement("iframe");
+ iframe.onload = this.step_func_done(function () {
+ assert_equals(iframe.contentDocument.baseURI, document.baseURI, "The document base URL should be the creator document's base URL.");
+ });
+ iframe.setAttribute("src", "about:blank");
+ document.body.appendChild(iframe);
+ }, "The fallback base URL of a document whose address is about:blank is the document base URL of the creator document.");
+
+ async_test(function () {
+ var iframe = document.createElement("iframe");
+ iframe.onload = this.step_func_done(function () {
+ assert_equals(iframe.contentDocument.baseURI, document.baseURI, "The document base URL should be the containing document's base URL.");
+ });
+ iframe.setAttribute("srcdoc", "<p>foobar</p>");
+ document.body.appendChild(iframe);
+ }, "The fallback base URL of an iframe srcdoc document is the document base URL of the document's browsing context's browsing context container's document.");
+ </script>
+</body>
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/urls/terminology-0/multiple-base.sub.html b/tests/wpt/web-platform-tests/html/infrastructure/urls/terminology-0/multiple-base.sub.html
new file mode 100644
index 00000000000..49c428c5bea
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/urls/terminology-0/multiple-base.sub.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>document base URL: multiple base elements</title>
+<base target="_blank" >
+<base href="http://{{domains[www]}}:{{ports[http][0]}}/">
+<base href="http://{{domains[www1]}}:{{ports[http][0]}}/">
+<base href="http://{{domains[www2]}}:{{ports[http][0]}}/">
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+ test(function(){
+ var base = document.querySelectorAll("base");
+ assert_equals(document.baseURI, document.querySelectorAll("base[href]")[0].href);
+ }, "If there are multiple <base> elements, the document base URL is the frozen base URL of the first one that has an href attribute");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/urls/url-manipulation-and-creation/.gitkeep b/tests/wpt/web-platform-tests/html/infrastructure/urls/url-manipulation-and-creation/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/urls/url-manipulation-and-creation/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/infrastructure/utf-8/.gitkeep b/tests/wpt/web-platform-tests/html/infrastructure/utf-8/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/infrastructure/utf-8/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/introduction/.gitkeep b/tests/wpt/web-platform-tests/html/introduction/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/introduction/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/introduction/a-quick-introduction-to-html/.gitkeep b/tests/wpt/web-platform-tests/html/introduction/a-quick-introduction-to-html/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/introduction/a-quick-introduction-to-html/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/introduction/a-quick-introduction-to-html/common-pitfalls-to-avoid-when-using-the-scripting-apis/.gitkeep b/tests/wpt/web-platform-tests/html/introduction/a-quick-introduction-to-html/common-pitfalls-to-avoid-when-using-the-scripting-apis/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/introduction/a-quick-introduction-to-html/common-pitfalls-to-avoid-when-using-the-scripting-apis/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/introduction/a-quick-introduction-to-html/writing-secure-applications-with-html/.gitkeep b/tests/wpt/web-platform-tests/html/introduction/a-quick-introduction-to-html/writing-secure-applications-with-html/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/introduction/a-quick-introduction-to-html/writing-secure-applications-with-html/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/introduction/audience/.gitkeep b/tests/wpt/web-platform-tests/html/introduction/audience/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/introduction/audience/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/introduction/background/.gitkeep b/tests/wpt/web-platform-tests/html/introduction/background/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/introduction/background/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/introduction/conformance-requirements-for-authors/.gitkeep b/tests/wpt/web-platform-tests/html/introduction/conformance-requirements-for-authors/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/introduction/conformance-requirements-for-authors/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/introduction/conformance-requirements-for-authors/presentational-markup/.gitkeep b/tests/wpt/web-platform-tests/html/introduction/conformance-requirements-for-authors/presentational-markup/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/introduction/conformance-requirements-for-authors/presentational-markup/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/introduction/conformance-requirements-for-authors/restrictions-on-content-models-and-on-attribute-values/.gitkeep b/tests/wpt/web-platform-tests/html/introduction/conformance-requirements-for-authors/restrictions-on-content-models-and-on-attribute-values/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/introduction/conformance-requirements-for-authors/restrictions-on-content-models-and-on-attribute-values/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/introduction/conformance-requirements-for-authors/syntax-errors/.gitkeep b/tests/wpt/web-platform-tests/html/introduction/conformance-requirements-for-authors/syntax-errors/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/introduction/conformance-requirements-for-authors/syntax-errors/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/introduction/design-notes/.gitkeep b/tests/wpt/web-platform-tests/html/introduction/design-notes/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/introduction/design-notes/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/introduction/design-notes/compliance-with-other-specifications/.gitkeep b/tests/wpt/web-platform-tests/html/introduction/design-notes/compliance-with-other-specifications/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/introduction/design-notes/compliance-with-other-specifications/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/introduction/design-notes/serializability-of-script-execution/.gitkeep b/tests/wpt/web-platform-tests/html/introduction/design-notes/serializability-of-script-execution/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/introduction/design-notes/serializability-of-script-execution/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/introduction/fingerprint/.gitkeep b/tests/wpt/web-platform-tests/html/introduction/fingerprint/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/introduction/fingerprint/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/introduction/history-0/.gitkeep b/tests/wpt/web-platform-tests/html/introduction/history-0/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/introduction/history-0/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/introduction/html-vs-xhtml/.gitkeep b/tests/wpt/web-platform-tests/html/introduction/html-vs-xhtml/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/introduction/html-vs-xhtml/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/introduction/scope/.gitkeep b/tests/wpt/web-platform-tests/html/introduction/scope/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/introduction/scope/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/introduction/structure-of-this-specification/.gitkeep b/tests/wpt/web-platform-tests/html/introduction/structure-of-this-specification/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/introduction/structure-of-this-specification/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/introduction/structure-of-this-specification/how-to-read-this-specification/.gitkeep b/tests/wpt/web-platform-tests/html/introduction/structure-of-this-specification/how-to-read-this-specification/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/introduction/structure-of-this-specification/how-to-read-this-specification/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/introduction/structure-of-this-specification/typographic-conventions/.gitkeep b/tests/wpt/web-platform-tests/html/introduction/structure-of-this-specification/typographic-conventions/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/introduction/structure-of-this-specification/typographic-conventions/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/introduction/suggested-reading/.gitkeep b/tests/wpt/web-platform-tests/html/introduction/suggested-reading/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/introduction/suggested-reading/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/obsolete/.gitkeep b/tests/wpt/web-platform-tests/html/obsolete/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/obsolete/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/obsolete/non-conforming-features/.gitkeep b/tests/wpt/web-platform-tests/html/obsolete/non-conforming-features/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/obsolete/non-conforming-features/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/obsolete/obsolete-but-conforming-features/.gitkeep b/tests/wpt/web-platform-tests/html/obsolete/obsolete-but-conforming-features/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/obsolete/obsolete-but-conforming-features/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/obsolete/obsolete-but-conforming-features/warnings-for-obsolete-but-conforming-features/.gitkeep b/tests/wpt/web-platform-tests/html/obsolete/obsolete-but-conforming-features/warnings-for-obsolete-but-conforming-features/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/obsolete/obsolete-but-conforming-features/warnings-for-obsolete-but-conforming-features/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/.gitkeep b/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/frames/.gitkeep b/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/frames/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/frames/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/other-elements-attributes-and-apis/.gitkeep b/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/other-elements-attributes-and-apis/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/other-elements-attributes-and-apis/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/other-elements-attributes-and-apis/document-color-01.html b/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/other-elements-attributes-and-apis/document-color-01.html
new file mode 100644
index 00000000000..8e2fbe7b002
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/other-elements-attributes-and-apis/document-color-01.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<title>document: fg/bg/link/vlink/alink-color</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-document-fgcolor">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-body-text">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ document.documentElement.removeChild(document.body);
+ assert_equals(document.fgColor, "");
+ assert_equals(document.bgColor, "");
+ assert_equals(document.linkColor, "");
+ assert_equals(document.vlinkColor, "");
+ assert_equals(document.alinkColor, "");
+})
+</script>
diff --git a/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/other-elements-attributes-and-apis/document-color-02.html b/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/other-elements-attributes-and-apis/document-color-02.html
new file mode 100644
index 00000000000..daf74e1344e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/other-elements-attributes-and-apis/document-color-02.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<title>document: fg/bg/link/vlink/alink-color</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-document-fgcolor">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-body-text">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ assert_equals(document.fgColor, document.body.text);
+ assert_equals(document.bgColor, document.body.bgColor);
+ assert_equals(document.linkColor, document.body.link);
+ assert_equals(document.vlinkColor, document.body.vLink);
+ assert_equals(document.alinkColor, document.body.aLink);
+})
+test(function() {
+ document.fgColor = "blue";
+ assert_equals(document.fgColor, "blue");
+ assert_equals(document.body.text, "blue");
+ assert_equals(document.body.getAttribute("text"), "blue");
+})
+test(function() {
+ document.bgColor = "green";
+ assert_equals(document.bgColor, "green");
+ assert_equals(document.body.bgColor, "green");
+ assert_equals(document.body.getAttribute("bgcolor"), "green");
+})
+test(function() {
+ document.linkColor = "red";
+ assert_equals(document.linkColor, "red");
+ assert_equals(document.body.link, "red");
+ assert_equals(document.body.getAttribute("link"), "red");
+})
+test(function() {
+ document.vlinkColor = "yellow";
+ assert_equals(document.vlinkColor, "yellow");
+ assert_equals(document.body.vLink, "yellow");
+ assert_equals(document.body.getAttribute("vlink"), "yellow");
+})
+test(function() {
+ document.alinkColor = "silver";
+ assert_equals(document.alinkColor, "silver");
+ assert_equals(document.body.aLink, "silver");
+ assert_equals(document.body.getAttribute("alink"), "silver");
+})
+</script>
diff --git a/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/other-elements-attributes-and-apis/document-color-03.html b/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/other-elements-attributes-and-apis/document-color-03.html
new file mode 100644
index 00000000000..e020a3853da
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/other-elements-attributes-and-apis/document-color-03.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<title>document: fg/bg/link/vlink/alink-color</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-document-fgcolor">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-body-text">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ assert_equals(document.fgColor, document.body.text);
+ assert_equals(document.bgColor, document.body.bgColor);
+ assert_equals(document.linkColor, document.body.link);
+ assert_equals(document.vlinkColor, document.body.vLink);
+ assert_equals(document.alinkColor, document.body.aLink);
+})
+test(function() {
+ document.body.text = "blue";
+ assert_equals(document.fgColor, "blue");
+ assert_equals(document.body.text, "blue");
+ assert_equals(document.body.getAttribute("text"), "blue");
+})
+test(function() {
+ document.body.bgColor = "green";
+ assert_equals(document.bgColor, "green");
+ assert_equals(document.body.bgColor, "green");
+ assert_equals(document.body.getAttribute("bgcolor"), "green");
+})
+test(function() {
+ document.body.link = "red";
+ assert_equals(document.linkColor, "red");
+ assert_equals(document.body.link, "red");
+ assert_equals(document.body.getAttribute("link"), "red");
+})
+test(function() {
+ document.body.vLink = "yellow";
+ assert_equals(document.vlinkColor, "yellow");
+ assert_equals(document.body.vLink, "yellow");
+ assert_equals(document.body.getAttribute("vlink"), "yellow");
+})
+test(function() {
+ document.body.aLink = "silver";
+ assert_equals(document.alinkColor, "silver");
+ assert_equals(document.body.aLink, "silver");
+ assert_equals(document.body.getAttribute("alink"), "silver");
+})
+</script>
diff --git a/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/other-elements-attributes-and-apis/document-color-04.html b/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/other-elements-attributes-and-apis/document-color-04.html
new file mode 100644
index 00000000000..ca9fc21d853
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/other-elements-attributes-and-apis/document-color-04.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<title>document: fg/bg/link/vlink/alink-color</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-document-fgcolor">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-body-text">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ assert_equals(document.fgColor, document.body.text);
+ assert_equals(document.bgColor, document.body.bgColor);
+ assert_equals(document.linkColor, document.body.link);
+ assert_equals(document.vlinkColor, document.body.vLink);
+ assert_equals(document.alinkColor, document.body.aLink);
+})
+test(function() {
+ document.body.setAttribute("text", "blue");
+ assert_equals(document.fgColor, "blue");
+ assert_equals(document.body.text, "blue");
+ assert_equals(document.body.getAttribute("text"), "blue");
+})
+test(function() {
+ document.body.setAttribute("bgcolor", "green");
+ assert_equals(document.bgColor, "green");
+ assert_equals(document.body.bgColor, "green");
+ assert_equals(document.body.getAttribute("bgcolor"), "green");
+})
+test(function() {
+ document.body.setAttribute("link", "red");
+ assert_equals(document.linkColor, "red");
+ assert_equals(document.body.link, "red");
+ assert_equals(document.body.getAttribute("link"), "red");
+})
+test(function() {
+ document.body.setAttribute("vlink", "yellow");
+ assert_equals(document.vlinkColor, "yellow");
+ assert_equals(document.body.vLink, "yellow");
+ assert_equals(document.body.getAttribute("vlink"), "yellow");
+})
+test(function() {
+ document.body.setAttribute("alink", "silver");
+ assert_equals(document.alinkColor, "silver");
+ assert_equals(document.body.aLink, "silver");
+ assert_equals(document.body.getAttribute("alink"), "silver");
+})
+</script>
diff --git a/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/other-elements-attributes-and-apis/heading-obsolete-attributes-01.html b/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/other-elements-attributes-and-apis/heading-obsolete-attributes-01.html
new file mode 100644
index 00000000000..84c66b4c565
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/other-elements-attributes-and-apis/heading-obsolete-attributes-01.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<title>HTMLHeadingElement: obsolete attribute reflecting</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-hx-align">
+<link rel="help" href="https://heycam.github.io/webidl/#es-DOMString">
+<link rel="help" href="http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf#page=57">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ var el = document.createElement("h7");
+ el.align = "left";
+ assert_equals(el.align, "left");
+ assert_false(el.hasAttribute("align"));
+ assert_equals(el.getAttribute("align"), null);
+}, "IDL attributes for HTMLHeadingElement should not apply to h7.")
+</script>
diff --git a/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/other-elements-attributes-and-apis/nothing.html b/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/other-elements-attributes-and-apis/nothing.html
new file mode 100644
index 00000000000..039495d78d6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/other-elements-attributes-and-apis/nothing.html
@@ -0,0 +1,27 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Methods that must do nothing: clear(), captureEvents(), and releaseEvents()</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function() {
+ assert_equals(document.clear(), undefined);
+}, "document.clear");
+
+test(function() {
+ assert_equals(document.captureEvents(), undefined);
+}, "document.captureEvents");
+
+test(function() {
+ assert_equals(document.releaseEvents(), undefined);
+}, "document.releaseEvents");
+
+test(function() {
+ assert_equals(window.captureEvents(), undefined);
+}, "window.captureEvents");
+
+test(function() {
+ assert_equals(window.releaseEvents(), undefined);
+}, "window.releaseEvents");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/other-elements-attributes-and-apis/original-id.json b/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/other-elements-attributes-and-apis/original-id.json
new file mode 100644
index 00000000000..601a7c08d19
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/other-elements-attributes-and-apis/original-id.json
@@ -0,0 +1 @@
+{"original_id":"other-elements,-attributes-and-apis"} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/other-elements-attributes-and-apis/script-IDL-event-htmlfor.html b/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/other-elements-attributes-and-apis/script-IDL-event-htmlfor.html
new file mode 100644
index 00000000000..0c5913944c5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/other-elements-attributes-and-apis/script-IDL-event-htmlfor.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<title>event and htmlFor IDL attributes of HTMLScriptElement</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-script-event">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-script-htmlfor">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ var script = document.createElement("script");
+ assert_equals(script.event, "");
+ assert_equals(script.htmlFor, "");
+})
+test(function() {
+ var script = document.createElement("script");
+ script.setAttribute("event", "blah");
+ script.setAttribute("for", "blah");
+ assert_equals(script.event, "");
+ assert_equals(script.htmlFor, "");
+ assert_equals(script.getAttribute("event"), "blah");
+ assert_equals(script.getAttribute("for"), "blah");
+})
+test(function() {
+ var script = document.createElement("script");
+ script.setAttribute("event", "blah");
+ script.setAttribute("for", "blah");
+ script.event = "foo";
+ script.htmlFor = "foo";
+ assert_equals(script.event, "");
+ assert_equals(script.htmlFor, "");
+ assert_equals(script.getAttribute("event"), "blah");
+ assert_equals(script.getAttribute("for"), "blah");
+})
+test(function() {
+ var script = document.createElement("script");
+ script.setAttribute("event", "blah");
+ script.setAttribute("for", "blah");
+ script.event = null;
+ script.htmlFor = null;
+ assert_equals(script.event, "");
+ assert_equals(script.htmlFor, "");
+ assert_equals(script.getAttribute("event"), "blah");
+ assert_equals(script.getAttribute("for"), "blah");
+})
+test(function() {
+ var script = document.createElement("script");
+ script.setAttribute("event", "blah");
+ script.setAttribute("for", "blah");
+ script.event = undefined;
+ script.htmlFor = undefined;
+ assert_equals(script.event, "");
+ assert_equals(script.htmlFor, "");
+ assert_equals(script.getAttribute("event"), "blah");
+ assert_equals(script.getAttribute("for"), "blah");
+})
+</script>
diff --git a/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/the-applet-element/.gitkeep b/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/the-applet-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/the-applet-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/the-marquee-element-0/.gitkeep b/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/the-marquee-element-0/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/the-marquee-element-0/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/the-marquee-element-0/marquee-direction-down-manual.html b/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/the-marquee-element-0/marquee-direction-down-manual.html
new file mode 100644
index 00000000000..a9d4a7f6be8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/the-marquee-element-0/marquee-direction-down-manual.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: marquee-direction-down</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/multipage/obsolete.html#the-marquee-element">
+<meta name="assert" content="Check if the marquee direction is from top to bottom">
+<p>Test passes if the text "Test Marquee" moves from top to bottom.</p>
+<marquee direction="down">Test Marquee</marquee>
diff --git a/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/the-marquee-element-0/marquee-direction-left-manual.html b/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/the-marquee-element-0/marquee-direction-left-manual.html
new file mode 100644
index 00000000000..cf08cca4b76
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/the-marquee-element-0/marquee-direction-left-manual.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: marquee-direction-left</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/multipage/obsolete.html#the-marquee-element">
+<meta name="assert" content="Check if the marquee direction is from right to left">
+<p>Test passes if the text "Test Marquee" moves from right to left.</p>
+<marquee direction="left">Test Marquee</marquee>
diff --git a/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/the-marquee-element-0/marquee-direction-right-manual.html b/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/the-marquee-element-0/marquee-direction-right-manual.html
new file mode 100644
index 00000000000..b42c9454fb1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/the-marquee-element-0/marquee-direction-right-manual.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: marquee-direction-right</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/multipage/obsolete.html#the-marquee-element">
+<meta name="assert" content="Check if the marquee direction is from left to right">
+<p>Test passes if the text "Test Marquee" moves from left to right.</p>
+<marquee direction="right">Test Marquee</marquee>
diff --git a/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/the-marquee-element-0/marquee-direction-up-manual.html b/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/the-marquee-element-0/marquee-direction-up-manual.html
new file mode 100644
index 00000000000..040609fb690
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/the-marquee-element-0/marquee-direction-up-manual.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: marquee-direction-up</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/multipage/obsolete.html#the-marquee-element">
+<meta name="assert" content="Check if the marquee direction is from bottom to top">
+<p>Test passes if the text "Test Marquee" moves from bottom to top.</p>
+<marquee direction="up">Test Marquee</marquee>
diff --git a/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/the-marquee-element-0/marquee-events.html b/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/the-marquee-element-0/marquee-events.html
new file mode 100644
index 00000000000..0d20c5102f1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/the-marquee-element-0/marquee-events.html
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: marquee-events</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/multipage/obsolete.html#the-marquee-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<marquee id="test1" loop="2" width="1" behavior="alternate">&nbsp;</marquee>
+<marquee id="test2" loop="2" width="1">&nbsp;</marquee>
+<script>
+ var mq;
+ var t_start = async_test("marquee_events_start");
+ var t_finish = async_test("marquee_events_finish");
+ var t_bounce = async_test("marquee_events_bounce");
+ var t_bounce2 = async_test("marquee_events_bounce2");
+ var timeStamp = [];
+ var bounced = false;
+
+ setup(function() {
+ mq = document.getElementById("test1");
+ mq2 = document.getElementById("test2");
+ });
+
+ mq.addEventListener("start", function(evt) {
+ t_start.step(function() {
+ timeStamp.push(evt.timeStamp);
+ assert_true(evt.isTrusted, "The onstart event is created by UA, it must be trusted.");
+ assert_equals(timeStamp.length, 1, "The onstart event should be fired firstly.");
+ assert_false(evt.bubbles, "The bubbles property of onstart event should be false.");
+ assert_false(evt.cancelable, "The cancelable property of onstart event should be false.");
+ assert_true(evt instanceof Event, "The onstart event must be the instance of Event interface.");
+ });
+ t_start.done();
+ });
+
+ mq.addEventListener("finish", function(evt) {
+ t_finish.step(function() {
+ timeStamp.push(evt.timeStamp);
+ assert_true(evt.isTrusted, "The onfinish event is created by UA, it must be trusted.");
+ assert_equals(timeStamp.length, 3, "The onfinish event should be fired lastly.");
+ assert_false(evt.bubbles, "The bubbles property of onfinish event should be false.");
+ assert_false(evt.cancelable, "The cancelable property of onfinish event should be false.");
+ assert_true(evt instanceof Event, "The onfinish event must be the instance of Event interface.");
+ });
+ t_finish.done();
+ });
+
+ mq.addEventListener("bounce", function(evt) {
+ t_bounce.step(function() {
+ timeStamp.push(evt.timeStamp);
+ assert_true(evt.isTrusted, "The onbounce event is created by UA, it must be trusted.");
+ assert_equals(timeStamp.length, 2, "The onbounce event should be fired secondly.");
+ assert_false(evt.bubbles, "The bubbles property of onbounce event should be false.");
+ assert_false(evt.cancelable, "The cancelable property of onbounce event should be false.");
+ assert_true(evt instanceof Event, "The onbounce event must be the instance of Event interface.");
+ });
+ t_bounce.done();
+ });
+
+ mq2.addEventListener("bounce", function(evt) {
+ bounced = true;
+ });
+
+ mq2.addEventListener("finish", function(evt) {
+ t_bounce2.step(function () {
+ assert_false(bounced, "The onbounce event should not be fired.");
+ });
+ t_bounce2.done();
+ });
+</script>
diff --git a/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/the-marquee-element-0/marquee-loop.html b/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/the-marquee-element-0/marquee-loop.html
new file mode 100644
index 00000000000..d150a5473b6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/the-marquee-element-0/marquee-loop.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: marquee-loop</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/multipage/obsolete.html#the-marquee-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<marquee id="test1" loop="a">Test1</marquee>
+<marquee id="test2" loop="-2">Test2</marquee>
+<marquee id="test3" loop="2">Test3</marquee>
+<script>
+ test(function() {
+ var mq = document.getElementById("test1");
+ assert_equals(mq.loop, -1, "The value of loop should be -1.");
+ }, "marquee_loop_string");
+
+ test(function() {
+ var mq = document.getElementById("test2");
+ assert_equals(mq.loop, -1, "The value of loop should be -1.");
+ }, "marquee_loop_less_than_1");
+
+ test(function() {
+ var mq = document.getElementById("test3");
+ assert_equals(mq.loop, 2, "The value of loop should be 2.");
+ }, "marquee_loop_normal");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/the-marquee-element-0/marquee-scrollamount-effect.html b/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/the-marquee-element-0/marquee-scrollamount-effect.html
new file mode 100644
index 00000000000..ad7ff0f3b16
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/the-marquee-element-0/marquee-scrollamount-effect.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: marquee-scrollamount-effect</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/multipage/obsolete.html#the-marquee-element">
+<meta name="assert" content="Check the effect of scrollamount attribute">
+<p>Test passes if the text "Test2" moves faster than the text "Test1".</p>
+<marquee id="test1">Test1</marquee>
+<marquee scrollamount="10" id="test2">Test2</marquee>
diff --git a/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/the-marquee-element-0/marquee-scrollamount.html b/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/the-marquee-element-0/marquee-scrollamount.html
new file mode 100644
index 00000000000..808361a99f3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/the-marquee-element-0/marquee-scrollamount.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: marquee-scrollamount</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/multipage/obsolete.html#the-marquee-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<marquee id="test1" scrollamount="aa">Test1</marquee>
+<marquee id="test2" scrollamount="-1">Test2</marquee>
+<marquee id="test3" scrollamount="10">Test3</marquee>
+<script>
+ test(function() {
+ var mq = document.getElementById("test1");
+ assert_equals(mq.scrollAmount, 6, "The value of scrollamount should be 6.");
+ }, "The scrollamount is a string");
+
+ test(function() {
+ var mq = document.getElementById("test2");
+ assert_equals(mq.scrollAmount, 6, "The value of scrollamount should be 6.");
+ }, "The scrollamount is a negative");
+
+ test(function() {
+ var mq = document.getElementById("test3");
+ assert_equals(mq.scrollAmount, 10, "The value of scrollamount should be 10.");
+ }, "The scrollamount is a normal value");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/the-marquee-element-0/marquee-scrolldelay.html b/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/the-marquee-element-0/marquee-scrolldelay.html
new file mode 100644
index 00000000000..9bc769fec36
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/the-marquee-element-0/marquee-scrolldelay.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: marquee-scrolldelay</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/multipage/obsolete.html#the-marquee-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<marquee id="test1" scrolldelay="aa">Test1</marquee>
+<marquee id="test2" scrolldelay="-1">Test2</marquee>
+<marquee id="test3" scrolldelay="1">Test3</marquee>
+<marquee id="test4" scrolldelay="100">Test4</marquee>
+<script>
+ test(function() {
+ var mq = document.getElementById("test1");
+ assert_equals(mq.scrollDelay, 85, "The delay time should be 85ms.");
+ }, "The scrolldelay attribute is a string");
+
+ test(function() {
+ var mq = document.getElementById("test2");
+ assert_equals(mq.scrollDelay, 85, "The delay time should be 85ms.");
+ }, "The scrolldelay attribute is a negative");
+
+ test(function() {
+ var mq = document.getElementById("test3");
+ assert_equals(mq.scrollDelay, 60, "The delay time should be 60ms.");
+ }, "The scrolldelay attribute is less than 60");
+
+ test(function() {
+ var mq = document.getElementById("test4");
+ assert_equals(mq.scrollDelay, 100, "The delay time should be 100ms.");
+ }, "The scrolldelay attribute is greater than 60");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/the-marquee-element-0/marquee-start.html b/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/the-marquee-element-0/marquee-start.html
new file mode 100644
index 00000000000..51b4289b247
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/the-marquee-element-0/marquee-start.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: marquee-start</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/multipage/obsolete.html#the-marquee-element">
+<meta name="flags" content="interact">
+<meta name="assert" content="Check the start operation of HTMLMarqueeElement interface">
+<h2>Steps:</h2>
+<ol>
+ <li>Click the 'Start' button to start the marquee element.</li>
+</ol>
+<h2>Expected result:</h2>
+<ul>
+ <li>The text "Test Marquee" start to move when the 'Start' button is clicked.</li>
+</ul>
+<input type="button" id="start" value="Start" />
+<marquee id="test">Test Marquee</marquee>
+<script>
+ document.getElementById("test").stop();
+ document.getElementById("start").addEventListener("click", function(evt) {
+ document.getElementById("test").start();
+ }, false);
+</script>
diff --git a/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/the-marquee-element-0/marquee-stop.html b/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/the-marquee-element-0/marquee-stop.html
new file mode 100644
index 00000000000..57a4e73e4c6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/obsolete/requirements-for-implementations/the-marquee-element-0/marquee-stop.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: marquee-stop</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/multipage/obsolete.html#the-marquee-element">
+<meta name="flags" content="interact">
+<meta name="assert" content="Check the stop operation of HTMLMarqueeElement interface">
+<h2>Steps:</h2>
+<ol>
+ <li>Click the 'Start' button to start the marquee element.</li>
+</ol>
+<h2>Expected result:</h2>
+<ul>
+ <li>The text "Test Marquee" stop moving when the 'Stop' button is clicked.</li>
+</ul>
+<input type="button" id="stop" value="Stop" />
+<marquee id="test">Test Marquee</marquee>
+<script>
+ document.getElementById("stop").addEventListener("click", function(evt) {
+ document.getElementById("test").stop();
+ }, false);
+</script>
diff --git a/tests/wpt/web-platform-tests/html/rendering/.gitkeep b/tests/wpt/web-platform-tests/html/rendering/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/rendering/bindings/.gitkeep b/tests/wpt/web-platform-tests/html/rendering/bindings/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/bindings/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/rendering/bindings/introduction-9/.gitkeep b/tests/wpt/web-platform-tests/html/rendering/bindings/introduction-9/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/bindings/introduction-9/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/rendering/bindings/the-button-element-0/.gitkeep b/tests/wpt/web-platform-tests/html/rendering/bindings/the-button-element-0/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/bindings/the-button-element-0/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/rendering/bindings/the-details-element-0/.gitkeep b/tests/wpt/web-platform-tests/html/rendering/bindings/the-details-element-0/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/bindings/the-details-element-0/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/rendering/bindings/the-input-element-as-a-button/.gitkeep b/tests/wpt/web-platform-tests/html/rendering/bindings/the-input-element-as-a-button/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/bindings/the-input-element-as-a-button/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/rendering/bindings/the-input-element-as-a-checkbox-and-radio-button-widgets/.gitkeep b/tests/wpt/web-platform-tests/html/rendering/bindings/the-input-element-as-a-checkbox-and-radio-button-widgets/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/bindings/the-input-element-as-a-checkbox-and-radio-button-widgets/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/rendering/bindings/the-input-element-as-a-color-well/.gitkeep b/tests/wpt/web-platform-tests/html/rendering/bindings/the-input-element-as-a-color-well/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/bindings/the-input-element-as-a-color-well/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/rendering/bindings/the-input-element-as-a-file-upload-control/.gitkeep b/tests/wpt/web-platform-tests/html/rendering/bindings/the-input-element-as-a-file-upload-control/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/bindings/the-input-element-as-a-file-upload-control/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/rendering/bindings/the-input-element-as-a-range-control/.gitkeep b/tests/wpt/web-platform-tests/html/rendering/bindings/the-input-element-as-a-range-control/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/bindings/the-input-element-as-a-range-control/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/rendering/bindings/the-input-element-as-a-text-entry-widget/.gitkeep b/tests/wpt/web-platform-tests/html/rendering/bindings/the-input-element-as-a-text-entry-widget/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/bindings/the-input-element-as-a-text-entry-widget/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/rendering/bindings/the-input-element-as-domain-specific-widgets/.gitkeep b/tests/wpt/web-platform-tests/html/rendering/bindings/the-input-element-as-domain-specific-widgets/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/bindings/the-input-element-as-domain-specific-widgets/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/rendering/bindings/the-keygen-element-0/.gitkeep b/tests/wpt/web-platform-tests/html/rendering/bindings/the-keygen-element-0/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/bindings/the-keygen-element-0/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/rendering/bindings/the-marquee-element/.gitkeep b/tests/wpt/web-platform-tests/html/rendering/bindings/the-marquee-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/bindings/the-marquee-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/rendering/bindings/the-meter-element-0/.gitkeep b/tests/wpt/web-platform-tests/html/rendering/bindings/the-meter-element-0/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/bindings/the-meter-element-0/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/rendering/bindings/the-progress-element-0/.gitkeep b/tests/wpt/web-platform-tests/html/rendering/bindings/the-progress-element-0/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/bindings/the-progress-element-0/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/rendering/bindings/the-select-element-0/.gitkeep b/tests/wpt/web-platform-tests/html/rendering/bindings/the-select-element-0/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/bindings/the-select-element-0/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/rendering/bindings/the-select-element-0/option-label-ref.html b/tests/wpt/web-platform-tests/html/rendering/bindings/the-select-element-0/option-label-ref.html
new file mode 100644
index 00000000000..e3f73cb3eda
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/bindings/the-select-element-0/option-label-ref.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<title>Option labels</title>
+<select size=12>
+ <option><!-- No children, no label-->
+ <option><!-- No children, empty label-->
+ <option>label<!-- No children, label-->
+ <option><!-- No children, namespaced label-->
+
+ <option>child<!-- Single child, no label-->
+ <option>child<!-- Single child, empty label-->
+ <option>label<!-- Single child, label-->
+ <option>child<!-- Single child, namespaced label-->
+
+ <option>child node<!-- Two children, no label-->
+ <option>child node<!-- Two children, empty label-->
+ <option>label<!-- Two children, label-->
+ <option>child node<!-- Two children, namespaced label-->
+</select>
+
diff --git a/tests/wpt/web-platform-tests/html/rendering/bindings/the-select-element-0/option-label.html b/tests/wpt/web-platform-tests/html/rendering/bindings/the-select-element-0/option-label.html
new file mode 100644
index 00000000000..f98595ed013
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/bindings/the-select-element-0/option-label.html
@@ -0,0 +1,66 @@
+<!doctype html>
+<title>Option labels</title>
+<link rel="match" href="option-label-ref.html">
+<select size=12></select>
+<script>
+var select = document.getElementsByTagName("select")[0], option;
+
+option = document.createElement("option");
+select.appendChild(option);
+
+option = document.createElement("option");
+option.setAttribute("label", "")
+select.appendChild(option);
+
+option = document.createElement("option");
+option.setAttribute("label", "label")
+select.appendChild(option);
+
+option = document.createElement("option");
+option.setAttributeNS("http://www.example.com/", "label", "label")
+select.appendChild(option);
+
+option = document.createElement("option");
+option.appendChild(document.createTextNode(" child "));
+select.appendChild(option);
+
+option = document.createElement("option");
+option.appendChild(document.createTextNode(" child "));
+option.setAttribute("label", "")
+select.appendChild(option);
+
+option = document.createElement("option");
+option.appendChild(document.createTextNode(" child "));
+option.setAttribute("label", "label")
+select.appendChild(option);
+
+option = document.createElement("option");
+option.appendChild(document.createTextNode(" child "));
+option.setAttributeNS("http://www.example.com/", "label", "label")
+select.appendChild(option);
+
+
+option = document.createElement("option");
+option.appendChild(document.createTextNode(" child "));
+option.appendChild(document.createTextNode(" node "));
+select.appendChild(option);
+
+option = document.createElement("option");
+option.appendChild(document.createTextNode(" child "));
+option.appendChild(document.createTextNode(" node "));
+option.setAttribute("label", "")
+select.appendChild(option);
+
+
+option = document.createElement("option");
+option.appendChild(document.createTextNode(" child "));
+option.appendChild(document.createTextNode(" node "));
+option.setAttribute("label", "label")
+select.appendChild(option);
+
+option = document.createElement("option");
+option.appendChild(document.createTextNode(" child "));
+option.appendChild(document.createTextNode(" node "));
+option.setAttributeNS("http://www.example.com/", "label", "label")
+select.appendChild(option);
+</script>
diff --git a/tests/wpt/web-platform-tests/html/rendering/bindings/the-textarea-element-0/.gitkeep b/tests/wpt/web-platform-tests/html/rendering/bindings/the-textarea-element-0/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/bindings/the-textarea-element-0/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/rendering/frames-and-framesets/.gitkeep b/tests/wpt/web-platform-tests/html/rendering/frames-and-framesets/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/frames-and-framesets/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/rendering/interactive-media/.gitkeep b/tests/wpt/web-platform-tests/html/rendering/interactive-media/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/interactive-media/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/rendering/interactive-media/editing-hosts/.gitkeep b/tests/wpt/web-platform-tests/html/rendering/interactive-media/editing-hosts/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/interactive-media/editing-hosts/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/rendering/interactive-media/links-forms-and-navigation/.gitkeep b/tests/wpt/web-platform-tests/html/rendering/interactive-media/links-forms-and-navigation/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/interactive-media/links-forms-and-navigation/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/rendering/interactive-media/links-forms-and-navigation/original-id.json b/tests/wpt/web-platform-tests/html/rendering/interactive-media/links-forms-and-navigation/original-id.json
new file mode 100644
index 00000000000..07a108785e8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/interactive-media/links-forms-and-navigation/original-id.json
@@ -0,0 +1 @@
+{"original_id":"links,-forms,-and-navigation"} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/rendering/interactive-media/text-rendered-in-native-user-interfaces/.gitkeep b/tests/wpt/web-platform-tests/html/rendering/interactive-media/text-rendered-in-native-user-interfaces/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/interactive-media/text-rendered-in-native-user-interfaces/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/rendering/interactive-media/the-title-attribute-0/.gitkeep b/tests/wpt/web-platform-tests/html/rendering/interactive-media/the-title-attribute-0/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/interactive-media/the-title-attribute-0/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/rendering/introduction-8/.gitkeep b/tests/wpt/web-platform-tests/html/rendering/introduction-8/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/introduction-8/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/.gitkeep b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/bidirectional-text/.gitkeep b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/bidirectional-text/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/bidirectional-text/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/flow-content-0/.gitkeep b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/flow-content-0/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/flow-content-0/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/flow-content-0/figure-ref.html b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/flow-content-0/figure-ref.html
new file mode 100644
index 00000000000..a87141be110
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/flow-content-0/figure-ref.html
@@ -0,0 +1,11 @@
+<!doctype html>
+<title>The figure element</title>
+<link rel=author title=Ms2ger href=ms2ger@gmail.com>
+<link rel=help href=https://html.spec.whatwg.org/multipage/#the-figure-element>
+<style>
+body > div { margin: 1em 40px; }
+</style>
+<div>
+<div>Caption</div>
+Figure
+</div>
diff --git a/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/flow-content-0/figure.html b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/flow-content-0/figure.html
new file mode 100644
index 00000000000..943f38c3e03
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/flow-content-0/figure.html
@@ -0,0 +1,9 @@
+<!doctype html>
+<title>The figure element</title>
+<link rel="match" href="figure-ref.html">
+<link rel=author title=Ms2ger href=ms2ger@gmail.com>
+<link rel=help href=https://html.spec.whatwg.org/multipage/#the-figure-element>
+<figure>
+<figcaption>Caption</figcaption>
+Figure
+</figure>
diff --git a/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/form-controls/.gitkeep b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/form-controls/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/form-controls/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/hidden-elements/.gitkeep b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/hidden-elements/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/hidden-elements/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/lists/.gitkeep b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/lists/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/lists/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/lists/TODO-lists.html b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/lists/TODO-lists.html
new file mode 100644
index 00000000000..6d79efc3846
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/lists/TODO-lists.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<ol><div><li>A</div></ol>
+<ol><div><li>A</div> <li>B</ol>
+<ol><div><li>A</div><div><li>B</div></ol>
+<ol reversed><div><li>A</div> <li>B</ol>
+<ol><div style=display:list-item>A</div><li>B</ol>
+<ol reversed><div style=display:list-item>A</div><li>B</ol>
+<ol reversed>
+ <div><li>Two</li></div>
+ <li>One</li>
+ <li>Zero</li>
+</ol>
+<ol reversed>
+ <li>Three</li>
+ <li style="display: none"></li>
+ <li>Two</li>
+</ol>
diff --git a/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/phrasing-content-0/.gitkeep b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/phrasing-content-0/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/phrasing-content-0/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/quotes/.gitkeep b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/quotes/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/quotes/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/sections-and-headings/.gitkeep b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/sections-and-headings/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/sections-and-headings/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/tables/.gitkeep b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/tables/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/tables/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/tables/table-border-1-ref.html b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/tables/table-border-1-ref.html
new file mode 100644
index 00000000000..ceac88e9a3c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/tables/table-border-1-ref.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Table borders</title>
+<style>
+table {
+ border-width: 1px;
+ border-style: outset;
+}
+td {
+ border-width: 1px;
+ border-style: inset;
+}
+</style>
+<table>
+<tr><td>Test
+</table>
+<table>
+<tr><td>Test
+</table>
+<table>
+<tr><td>Test
+</table>
+<table>
+<tr><td>Test
+</table>
+<table>
+<tr><td>Test
+</table>
+<table>
+<tr><td>Test
+</table>
+<table>
+<tr><td>Test
+</table>
+<table>
+<tr><td>Test
+</table>
+<table>
+<tr><td>Test
+</table>
+<table>
+<tr><td>Test
+</table>
+<table>
+<tr><td>Test
+</table>
diff --git a/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/tables/table-border-1.html b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/tables/table-border-1.html
new file mode 100644
index 00000000000..33388139955
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/tables/table-border-1.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<link rel="match" href="table-border-1-ref.html">
+<title>Table borders</title>
+<table border>
+<tr><td>Test
+</table>
+<table border="">
+<tr><td>Test
+</table>
+<table border=null>
+<tr><td>Test
+</table>
+<table border=undefined>
+<tr><td>Test
+</table>
+<table border=foo>
+<tr><td>Test
+</table>
+<table border=1>
+<tr><td>Test
+</table>
+<table border=1foo>
+<tr><td>Test
+</table>
+<table border=1%>
+<tr><td>Test
+</table>
+<table border=-1>
+<tr><td>Test
+</table>
+<table border=-1foo>
+<tr><td>Test
+</table>
+<table border=-1%>
+<tr><td>Test
+</table>
diff --git a/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/tables/table-border-2-notref.html b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/tables/table-border-2-notref.html
new file mode 100644
index 00000000000..7558e5271a3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/tables/table-border-2-notref.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Table borders</title>
+<style>
+table {
+ border-width: 1px;
+ border-style: outset;
+}
+td {
+ border-width: 1px;
+ border-style: inset;
+}
+</style>
+<table>
+<tr><td>Test
+</table>
+<table>
+<tr><td>Test
+</table>
+<table>
+<tr><td>Test
+</table>
+<table>
+<tr><td>Test
+</table>
+<table>
+<tr><td>Test
+</table>
+<table>
+<tr><td>Test
+</table>
+<table>
+<tr><td>Test
+</table>
+<table>
+<tr><td>Test
+</table>
+<table>
+<tr><td>Test
+</table>
diff --git a/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/tables/table-border-2-ref.html b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/tables/table-border-2-ref.html
new file mode 100644
index 00000000000..36d1e451062
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/tables/table-border-2-ref.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Table borders</title>
+<table>
+<tr><td>Test
+</table>
+<table>
+<tr><td>Test
+</table>
+<table>
+<tr><td>Test
+</table>
+<table>
+<tr><td>Test
+</table>
+<table>
+<tr><td>Test
+</table>
+<table>
+<tr><td>Test
+</table>
+<table>
+<tr><td>Test
+</table>
+<table>
+<tr><td>Test
+</table>
+<table>
+<tr><td>Test
+</table>
diff --git a/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/tables/table-border-2.html b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/tables/table-border-2.html
new file mode 100644
index 00000000000..6f4f39b113b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/tables/table-border-2.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<link rel="match" href="table-border-2-ref.html">
+<title>Table borders</title>
+<table border=0>
+<tr><td>Test
+</table>
+<table border=0foo>
+<tr><td>Test
+</table>
+<table border=0%>
+<tr><td>Test
+</table>
+<table border=+0>
+<tr><td>Test
+</table>
+<table border=+0foo>
+<tr><td>Test
+</table>
+<table border=+0%>
+<tr><td>Test
+</table>
+<table border=-0>
+<tr><td>Test
+</table>
+<table border=-0foo>
+<tr><td>Test
+</table>
+<table border=-0%>
+<tr><td>Test
+</table>
diff --git a/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/tables/table-layout-notref.html b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/tables/table-layout-notref.html
new file mode 100644
index 00000000000..ef1378185ae
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/tables/table-layout-notref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Table layout attribute</title>
+<table border width=100% style=table-layout:fixed>
+<tr><td>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa<td>aaa
+</table>
+<table border width=100% style=table-layout:fixed>
+<tr><td>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa<td>aaa
+</table>
diff --git a/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/tables/table-layout-ref.html b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/tables/table-layout-ref.html
new file mode 100644
index 00000000000..d76a48c4ab1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/tables/table-layout-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Table layout attribute</title>
+<table border width=100%>
+<tr><td>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa<td>aaa
+</table>
+<table border width=100%>
+<tr><td>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa<td>aaa
+</table>
diff --git a/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/tables/table-layout.html b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/tables/table-layout.html
new file mode 100644
index 00000000000..7dfacf22791
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/tables/table-layout.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Table layout attribute</title>
+<link rel="match" href="table-layout-ref.html">
+<meta name="assert"
+ content="The layout attribute on table elements should have no effect.">
+<table border width=100% layout=fixed>
+<tr><td>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa<td>aaa
+</table>
+<table border width=100% layout=auto>
+<tr><td>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa<td>aaa
+</table>
diff --git a/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/tables/table-width-150percent-ref.html b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/tables/table-width-150percent-ref.html
new file mode 100644
index 00000000000..820c360e391
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/tables/table-width-150percent-ref.html
@@ -0,0 +1,12 @@
+<!doctype html>
+<title>Test for capping percentages</title>
+<style>
+div { width:300px; background:yellow; height:50px; }
+table { width:150%; }
+td { background:blue; }
+</style>
+<div>
+ <table cellspacing="0" cellpadding="0" border="0">
+ <tr><td>parent div float=left</td></tr>
+ </table>
+</div>
diff --git a/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/tables/table-width-150percent.html b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/tables/table-width-150percent.html
new file mode 100644
index 00000000000..9a5e108505e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/tables/table-width-150percent.html
@@ -0,0 +1,12 @@
+<!doctype html>
+<title>Test for capping percentages</title>
+<link rel="match" href="table-width-150percent-ref.html">
+<style>
+div { width:300px; background:yellow; height:50px; }
+td { background:blue; }
+</style>
+<div>
+ <table width="150%" cellspacing="0" cellpadding="0" border="0">
+ <tr><td>parent div float=left</td></tr>
+ </table>
+</div>
diff --git a/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/the-fieldset-element-0/.gitkeep b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/the-fieldset-element-0/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/the-fieldset-element-0/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/the-hr-element-0/.gitkeep b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/the-hr-element-0/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/the-hr-element-0/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/the-page/.gitkeep b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/the-page/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/the-page/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/the-page/body_link.xhtml b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/the-page/body_link.xhtml
new file mode 100644
index 00000000000..b93435de8a5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/the-page/body_link.xhtml
@@ -0,0 +1,16 @@
+<html xmlns='http://www.w3.org/1999/xhtml'>
+<head>
+<title>body - LINK=yellow</title>
+</head>
+<body link="yellow">
+<p> Test for <b> link="yellow" </b> on body </p>
+
+This <a href="test-body.xhtml">LINK</a> should be displayed in <b>yellow</b><i> if it has not been clicked before </i><br/>
+<p>Once clicked, the link will take default color of visited link.<br /></p>
+<p>To run this test again in browsers, delete your browsing history and navigate to this page.<br /></p>
+
+<p>
+<i>Note - This test checks for User Agent requirement as per HTML5 spec NOT the author requirement</i>
+</p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/the-page/body_text_00ffff-ref.html b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/the-page/body_text_00ffff-ref.html
new file mode 100644
index 00000000000..c907a119f8b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/the-page/body_text_00ffff-ref.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>[body - TEXT=00ffff] Reference file</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<style>
+ body {
+ color: blue;
+ }
+</style>
+<body>
+ <p>This document should have text color 'Blue' using the RGB Hexadecimal color value of "0000ff". </p>
+ <p>This test passes if the color of text above matches the image below.</p>
+ <p><img src="/images/blue.png"/></p>
+</body>
diff --git a/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/the-page/body_text_00ffff.xhtml b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/the-page/body_text_00ffff.xhtml
new file mode 100644
index 00000000000..42b8aa3b6ba
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/the-page/body_text_00ffff.xhtml
@@ -0,0 +1,12 @@
+<html xmlns='http://www.w3.org/1999/xhtml'>
+<head>
+<title>body - TEXT=00ffff</title>
+<link rel="match" href="body_text_00ffff-ref.html"/>
+<meta name="assert" content="Test checks that User Agent requirement as per HTML5 spec NOT the author requirement."/>
+</head>
+<body text="0000ff">
+<p>This document should have text color 'Blue' using the RGB Hexadecimal color value of "0000ff". </p>
+<p>This test passes if the color of text above matches the image below.</p>
+<p><img src="/images/blue.png" /></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/the-page/test-body.xhtml b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/the-page/test-body.xhtml
new file mode 100644
index 00000000000..cd733b17ba4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/non-replaced-elements/the-page/test-body.xhtml
@@ -0,0 +1,8 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title> This is a test page</title>
+</head>
+<body>
+<p> To rerun this test, delete history and go <a href="body_link.xhtml">back </a> to previous test.</p>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/rendering/print-media/.gitkeep b/tests/wpt/web-platform-tests/html/rendering/print-media/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/print-media/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/rendering/replaced-elements/.gitkeep b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/.gitkeep b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img_border-ref.xhtml b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img_border-ref.xhtml
new file mode 100644
index 00000000000..0050c542cde
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img_border-ref.xhtml
@@ -0,0 +1,9 @@
+<html xmlns='http://www.w3.org/1999/xhtml'>
+<head>
+<title>IMG - Border in CSS</title>
+</head>
+<body>
+<p><img src="../../../../../images/blue.png"/></p>
+<p><img src="../../../../../images/blue.png" style="border-width:50px; border-style:solid;"/></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img_border_percent.xhtml b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img_border_percent.xhtml
new file mode 100644
index 00000000000..da74fb32b9e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img_border_percent.xhtml
@@ -0,0 +1,10 @@
+<html xmlns='http://www.w3.org/1999/xhtml'>
+<head>
+<title>IMG - Border= value in percent</title>
+<link rel="match" href="img_border-ref.xhtml"/>
+</head>
+<body>
+<p><img src="../../../../../images/blue.png" border="0%"/></p>
+<p><img src="../../../../../images/blue.png" border="50%"/></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/object_border-ref.xhtml b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/object_border-ref.xhtml
new file mode 100644
index 00000000000..6eaaa0ba141
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/object_border-ref.xhtml
@@ -0,0 +1,8 @@
+<html xmlns='http://www.w3.org/1999/xhtml'>
+<head>
+<title>OBJECT - border in CSS</title>
+</head>
+<body>
+<p><object data="../../../../images/blue.png" type="image/png" style="border-width:50px; border-style:solid;"></object></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/object_border_perc.xhtml b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/object_border_perc.xhtml
new file mode 100644
index 00000000000..3663e9ce61d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/object_border_perc.xhtml
@@ -0,0 +1,9 @@
+<html xmlns='http://www.w3.org/1999/xhtml'>
+<head>
+<title>OBJECT - border=value in %</title>
+<link rel="match" href="object_border-ref.xhtml"/>
+</head>
+<body>
+<p><object data="../../../../images/blue.png" type="image/png" border="50%"></object></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/object_border_pixel.xhtml b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/object_border_pixel.xhtml
new file mode 100644
index 00000000000..55f7f0a3bfe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/object_border_pixel.xhtml
@@ -0,0 +1,9 @@
+<html xmlns='http://www.w3.org/1999/xhtml'>
+<head>
+<title>OBJECT - border=pixel</title>
+<link rel="match" href="object_border-ref.xhtml"/>
+</head>
+<body>
+<p><object data="../../../../images/blue.png" type="image/png" border="50"></object></p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/rendering/replaced-elements/embedded-content-rendering-rules/.gitkeep b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/embedded-content-rendering-rules/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/embedded-content-rendering-rules/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/rendering/replaced-elements/image-maps-0/.gitkeep b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/image-maps-0/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/image-maps-0/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/rendering/replaced-elements/images/.gitkeep b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/images/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/images/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/rendering/replaced-elements/images/space-ref.html b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/images/space-ref.html
new file mode 100644
index 00000000000..0cf272e1621
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/images/space-ref.html
@@ -0,0 +1,13 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>img hspace/vspace - reference</title>
+<style>
+span { background: blue; }
+</style>
+<div style=width:400px;>
+<p><span><img src=/images/green.png></span>
+<p><span><img src=/images/green.png style="margin: 0 10px"></span>
+<p><span><img src=/images/green.png style="margin: 10px 0"></span>
+<p><span><img src=/images/green.png style="margin: 0 10%"></span>
+<p><span><img src=/images/green.png style="margin: 10% 0"></span>
+</div>
diff --git a/tests/wpt/web-platform-tests/html/rendering/replaced-elements/images/space.html b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/images/space.html
new file mode 100644
index 00000000000..fee115dfce6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/images/space.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>img hspace/vspace</title>
+<link rel=match href=space-ref.html>
+<style>
+span { background: blue; }
+</style>
+<div style=width:400px;>
+<p><span><img src=/images/green.png></span>
+<p><span><img src=/images/green.png hspace=10></span>
+<p><span><img src=/images/green.png vspace=10></span>
+<p><span><img src=/images/green.png hspace=10%></span>
+<p><span><img src=/images/green.png vspace=10%></span>
+</div>
diff --git a/tests/wpt/web-platform-tests/html/rendering/replaced-elements/resources/svg-sizing.js b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/resources/svg-sizing.js
new file mode 100644
index 00000000000..f54541e9ea2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/resources/svg-sizing.js
@@ -0,0 +1,418 @@
+// Simple implementation of SVG sizing
+
+setup({explicit_done: true});
+
+var SVGSizing = (function() {
+ function parseLength(l) {
+ var match = /^([-+]?[0-9]+|[-+]?[0-9]*\.[0-9]+)(px|%)?$/.exec(l);
+ if (!match)
+ return null;
+ return new Length(Number(match[1]), match[2] ? match[2] : "px");
+ }
+
+ function parseViewBox(input) {
+ if (!input)
+ return null;
+
+ var arr = input.split(' ');
+ return arr.map(function(a) { return parseInt(a); });
+ }
+
+ // Only px and % are used
+ function convertToPx(input, percentRef) {
+ if (input == null)
+ return null;
+ var length = parseLength(input);
+ if (length.amount == 0)
+ return 0;
+ if (!length.unit)
+ length.unit = "px";
+ if (length.unit == "%" && percentRef === undefined)
+ return null;
+ return length.amount * { px: 1,
+ "%": percentRef/100}[length.unit];
+ }
+
+ function Length(amount, unit) {
+ this.amount = amount;
+ this.unit = unit;
+ }
+
+ function describe(data) {
+ function dumpObject(obj) {
+ var r = "";
+ for (var property in obj) {
+ if (obj.hasOwnProperty(property)) {
+ var value = obj[property];
+ if (typeof value == 'string')
+ value = "'" + value + "'";
+ else if (value == null)
+ value = "null";
+ else if (typeof value == 'object')
+ {
+ if (value instanceof Array)
+ value = "[" + value + "]";
+ else
+ value = "{" + dumpObject(value) + "}";
+ }
+
+ if (value != "null")
+ r += property + ": " + value + ", ";
+ }
+ }
+ return r;
+ }
+ var result = dumpObject(data);
+ if (result == "")
+ return "(initial values)";
+ return result;
+ }
+
+ function mapPresentationalHintLength(testData, cssProperty, attr) {
+ if (attr) {
+ var l = parseLength(attr);
+ if (l)
+ testData.style[cssProperty] = l.amount + l.unit;
+ }
+ }
+
+ function computedWidthIsAuto(testData) {
+ return !testData.style["width"] || testData.style["width"] == 'auto';
+ }
+
+ function computedHeightIsAuto(testData) {
+ return !testData.style["height"] || testData.style["height"] == 'auto' ||
+ (parseLength(testData.style["height"]).unit == '%' &&
+ containerComputedHeightIsAuto(testData));
+ }
+
+ function containerComputedWidthIsAuto(testData) {
+ return !testData.config.containerWidthStyle ||
+ testData.config.containerWidthStyle == 'auto';
+ }
+
+ function containerComputedHeightIsAuto(testData) {
+ return !testData.config.containerHeightStyle ||
+ testData.config.containerHeightStyle == 'auto';
+ }
+
+ function intrinsicInformation(testData) {
+ if (testData.config.placeholder == 'iframe')
+ return {};
+
+ var w = convertToPx(testData.config.svgWidthAttr) || 0;
+ var h = convertToPx(testData.config.svgHeightAttr) || 0;
+ var r = 0;
+ if (w && h) {
+ r = w / h;
+ } else {
+ var vb = parseViewBox(testData.config.svgViewBoxAttr);
+ if (vb) {
+ r = vb[2] / vb[3];
+ }
+ if (r) {
+ if (!w && h)
+ w = h * r;
+ else if (!h && w)
+ h = w / r;
+ }
+ }
+ return { width: w, height: h, ratio: r };
+ };
+
+ function contentAttributeForPlaceholder(testData) {
+ if (testData.config.placeholder == 'object')
+ return "data";
+ else
+ return "src";
+ }
+
+ function TestData(config) {
+ this.config = config;
+ this.name = describe(config);
+ this.style = {};
+ if (config.placeholder) {
+ mapPresentationalHintLength(this, "width", config.placeholderWidthAttr);
+ mapPresentationalHintLength(this, "height", config.placeholderHeightAttr);
+ } else {
+ if (config.svgWidthStyle)
+ this.style["width"] = config.svgWidthStyle;
+ else
+ mapPresentationalHintLength(this, "width", config.svgWidthAttr);
+
+ if (config.svgHeightStyle)
+ this.style["height"] = config.svgHeightStyle;
+ else
+ mapPresentationalHintLength(this, "height", config.svgHeightAttr);
+ }
+ }
+
+ TestData.prototype.computeInlineReplacedSize = function(outerWidth, outerHeight) {
+ var intrinsic = intrinsicInformation(this);
+ var self = this;
+
+ // http://www.w3.org/TR/CSS2/visudet.html#inline-replaced-height
+ function calculateUsedHeight() {
+ if (computedHeightIsAuto(self)) {
+ if (computedWidthIsAuto(self) && intrinsic.height)
+ return intrinsic.height;
+ if (intrinsic.ratio)
+ return calculateUsedWidth() / intrinsic.ratio;
+ if (intrinsic.height)
+ return intrinsic.height;
+ return 150;
+ }
+
+ return convertToPx(self.style["height"],
+ convertToPx(self.config.containerHeightStyle,
+ outerHeight));
+ }
+
+ // http://www.w3.org/TR/CSS2/visudet.html#inline-replaced-width
+ function calculateUsedWidth() {
+ if (computedWidthIsAuto(self)) {
+ if (computedHeightIsAuto(self) && intrinsic.width)
+ return intrinsic.width;
+ if (!computedHeightIsAuto(self) && intrinsic.ratio)
+ return calculateUsedHeight() * intrinsic.ratio;
+ if (computedHeightIsAuto(self) && intrinsic.ratio) {
+ if (containerComputedWidthIsAuto(self)) {
+ // Note: While this is actually undefined in CSS
+ // 2.1, use the suggested value by examining the
+ // ancestor widths.
+ return outerWidth;
+ } else {
+ return convertToPx(self.config.containerWidthStyle,
+ outerWidth);
+ }
+ }
+ if (intrinsic.width)
+ return intrinsic.width;
+ return 300;
+ }
+
+ if (containerComputedWidthIsAuto(self))
+ return convertToPx(self.style["width"], outerWidth);
+ else
+ return convertToPx(self.style["width"],
+ convertToPx(self.config.containerWidthStyle,
+ outerWidth));
+ }
+ return { width: calculateUsedWidth(),
+ height: calculateUsedHeight() };
+ };
+
+ TestData.prototype.buildContainer = function (placeholder, options) {
+ options = options || {};
+
+ var container = document.createElement("div");
+
+ container.id = "container";
+ if (this.config.containerWidthStyle)
+ container.style.width = this.config.containerWidthStyle;
+
+ if (this.config.containerHeightStyle)
+ container.style.height = this.config.containerHeightStyle;
+
+ if (options.pretty)
+ container.appendChild(document.createTextNode("\n\t\t"));
+ container.appendChild(placeholder);
+ if (options.pretty)
+ container.appendChild(document.createTextNode("\n\t"));
+
+ return container;
+ };
+
+ TestData.prototype.buildSVGOrPlaceholder = function (options) {
+ options = options || {};
+ var self = this;
+
+ if (this.config.placeholder) {
+ var generateSVGURI = function(testData, encoder) {
+ var res = '<svg xmlns="http://www.w3.org/2000/svg"';
+ function addAttr(attr, prop) {
+ if (testData.config[prop])
+ res += ' ' + attr + '="' + testData.config[prop] + '"';
+ }
+ addAttr("width", "svgWidthAttr");
+ addAttr("height", "svgHeightAttr");
+ addAttr("viewBox", "svgViewBoxAttr");
+ res += '></svg>';
+ return 'data:image/svg+xml' + encoder(res);
+ };
+ var placeholder = document.createElement(this.config.placeholder);
+ if (options.pretty) {
+ placeholder.appendChild(document.createTextNode("\n\t\t\t"));
+ placeholder.appendChild(
+ document.createComment(
+ generateSVGURI(this, function(x) { return "," + x; })));
+ placeholder.appendChild(document.createTextNode("\n\t\t"));
+ }
+ placeholder.setAttribute("id", "test");
+ if (this.config.placeholderWidthAttr)
+ placeholder.setAttribute("width", this.config.placeholderWidthAttr);
+ if (this.config.placeholderHeightAttr)
+ placeholder.setAttribute("height", this.config.placeholderHeightAttr);
+ placeholder.setAttribute(contentAttributeForPlaceholder(this),
+ generateSVGURI(this, function(x) {
+ return ";base64," + btoa(x);
+ }));
+ return placeholder;
+ } else {
+ var svgElement = document.createElementNS("http://www.w3.org/2000/svg", "svg");
+ svgElement.setAttribute("id", "test");
+ if (self.config.svgWidthStyle)
+ svgElement.style.width = self.config.svgWidthStyle;
+ if (self.config.svgHeightStyle)
+ svgElement.style.height = self.config.svgHeightStyle;
+ if (self.config.svgWidthAttr)
+ svgElement.setAttribute("width", self.config.svgWidthAttr);
+ if (self.config.svgHeightAttr)
+ svgElement.setAttribute("height", self.config.svgHeightAttr);
+ if (self.config.svgViewBoxAttr)
+ svgElement.setAttribute("viewBox", self.config.svgViewBoxAttr);
+ return svgElement;
+ }
+ };
+
+ TestData.prototype.buildDemo = function (expectedRect, id) {
+ // Non-essential debugging tool
+ var self = this;
+
+ function buildDemoSerialization() {
+ var outerWidth = 800;
+ var outerHeight = 600;
+
+ var options = { pretty: true };
+ var container =
+ self.buildContainer(self.buildSVGOrPlaceholder(options), options);
+
+ var root = document.createElement("html");
+ var style = document.createElement("style");
+
+ style.textContent = "\n" +
+ "\tbody { margin: 0; font-family: sans-serif }\n" +
+ "\tiframe { border: none }\n" +
+ "\t#expected {\n" +
+ "\t\twidth: " + (expectedRect.width) + "px; height: "
+ + (expectedRect.height) + "px;\n" +
+ "\t\tborder: 10px solid lime; position: absolute;\n" +
+ "\t\tbackground-color: red }\n" +
+ "\t#testContainer { position: absolute;\n" +
+ "\t\ttop: 10px; left: 10px; width: " + outerWidth + "px;\n" +
+ "\t\theight: " + outerHeight + "px }\n" +
+ "\t#test { background-color: green }\n" +
+ "\t.result { position: absolute; top: 0; right: 0;\n" +
+ "\t\tbackground-color: hsla(0,0%, 0%, 0.85); border-radius: 0.5em;\n" +
+ "\t\tpadding: 0.5em; border: 0.25em solid black }\n" +
+ "\t.pass { color: lime }\n" +
+ "\t.fail { color: red }\n";
+
+ root.appendChild(document.createTextNode("\n"));
+ root.appendChild(style);
+ root.appendChild(document.createTextNode("\n"));
+
+ var script = document.createElement("script");
+ script.textContent = "\n" +
+ "onload = function() {\n" +
+ "\tvar svgRect =\n" +
+ "\t\tdocument.querySelector('#test').getBoundingClientRect();\n" +
+ "\tpassed = (svgRect.width == " + expectedRect.width + " && " +
+ "svgRect.height == " + expectedRect.height + ");\n" +
+ "\tdocument.body.insertAdjacentHTML('beforeEnd',\n" +
+ "\t\t'<span class=\"result '+ (passed ? 'pass' : 'fail') " +
+ "+ '\">' + (passed ? 'Pass' : 'Fail') + '</span>');\n" +
+ "};\n";
+
+ root.appendChild(script);
+ root.appendChild(document.createTextNode("\n"));
+
+ var expectedElement = document.createElement("div");
+ expectedElement.id = "expected";
+ root.appendChild(expectedElement);
+ root.appendChild(document.createTextNode("\n"));
+
+ var testContainer = document.createElement("div");
+ testContainer.id = "testContainer";
+ testContainer.appendChild(document.createTextNode("\n\t"));
+ testContainer.appendChild(container);
+ testContainer.appendChild(document.createTextNode("\n"));
+ root.appendChild(testContainer);
+ root.appendChild(document.createTextNode("\n"));
+
+ return "<!DOCTYPE html>\n" + root.outerHTML;
+ }
+
+ function pad(n, width, z) {
+ z = z || '0';
+ n = n + '';
+ return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n;
+ }
+
+ function heightToDescription(height) {
+ if (!height || height == "auto")
+ return "auto";
+ if (parseLength(height).unit == '%')
+ return "percentage";
+ return "fixed";
+ }
+
+ var demoRoot = document.querySelector('#demo');
+ if (demoRoot) {
+ var demo = buildDemoSerialization();
+ var iframe = document.createElement('iframe');
+ iframe.style.width = (Math.max(900, expectedRect.width)) + "px";
+ iframe.style.height = (Math.max(400, expectedRect.height)) + "px";
+ iframe.src = "data:text/html;charset=utf-8," + encodeURIComponent(demo);
+ demoRoot.appendChild(iframe);
+ demoRoot.insertAdjacentHTML(
+ 'beforeEnd',
+ '<p><a href="data:application/octet-stream;charset=utf-8;base64,' +
+ btoa(demo) + '" download="svg-in-' + this.config.placeholder + "-" +
+ heightToDescription(this.config.placeholderHeightAttr) + "-" + pad(id, 3) +
+ '.html">Download</a></p>');
+ }
+ };
+
+ return {
+ TestData: TestData,
+ doCombinationTest: function(values, func, testSingleId) {
+ function computeConfig(id) {
+ id--;
+ var multiplier = 1;
+ var config = {};
+ for (var i=0; i<values.length; i++) {
+ // Compute offset into current array
+ var ii = (Math.floor(id / multiplier)) % values[i][1].length;
+ // Set corresponding value
+ config[values[i][0]] = values[i][1][ii];
+ // Compute new multiplier
+ multiplier *= values[i][1].length;
+ }
+ if (id >= multiplier)
+ return null;
+ return config;
+ }
+
+ function cont(id) {
+ var config = computeConfig(id);
+ if (config && (!testSingleId || testSingleId == id)) {
+ var next = function() {func(config, id, cont)};
+ // Make sure we don't blow the stack, without too much slowness
+ if (id % 20 === 0) {
+ setTimeout(next, 0);
+ } else {
+ next();
+ }
+ } else {
+ done();
+ }
+ };
+
+ if (testSingleId)
+ cont(testSingleId);
+ else
+ cont(1);
+ }
+ };
+})();
diff --git a/tests/wpt/web-platform-tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-embedded-sizing.js b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-embedded-sizing.js
new file mode 100644
index 00000000000..5dc5131c58c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-embedded-sizing.js
@@ -0,0 +1,96 @@
+// global async_test, assert_equals
+//
+// This test generates a couple of scenarios (each a
+// SVGSizing.TestData) for sizing inline <svg> and uses a simple
+// JavaScript sizing implementation for comparison.
+//
+// The tests loops through different combinations of:
+//
+// * width and height on <object>, <iframe> (input dependent)
+//
+// * width and height on <svg>
+//
+// * viewBox on <svg> (gives intrinsic ratio)
+//
+// * width and height on containing block of <object>
+//
+// All these contribute to the final size of the SVG in some way.
+//
+// The test focuses on the size of the CSS box generated by the SVG.
+// The SVG is always empty by itself so no actual SVG are tested.
+// Little focus is put on variations within an attribute that doesn't
+// affect the sizing behavior.
+//
+// To debug a specific test, append ?<test-id> to the URL. An <iframe>
+// is generated with equivalent test and the source code of the test
+// can be downloaded.
+
+var debugHint = function(id) { return "(append ?"+id+" to debug) "; };
+var testSingleId;
+if (window.location.search) {
+ testSingleId = parseInt(window.location.search.substring(1));
+ debugHint = function(id) { return ""; };
+}
+
+function testPlaceholderWithHeight(placeholder,
+ placeholderHeightAttr) {
+ var testContainer = document.querySelector('#testContainer');
+ var outerWidth = testContainer.getBoundingClientRect().width;
+ var outerHeight = testContainer.getBoundingClientRect().height;
+
+ SVGSizing.doCombinationTest(
+ [["placeholder", [ placeholder ]],
+ ["containerWidthStyle", [null, "400px"]],
+ ["containerHeightStyle", [null, "400px"]],
+ ["placeholderWidthAttr", [null, "100", "50%"]],
+ ["placeholderHeightAttr", [placeholderHeightAttr]],
+ ["svgViewBoxAttr", [ null, "0 0 100 200" ]],
+ ["svgWidthAttr", [ null, "200", "25%" ]],
+ ["svgHeightAttr", [ null, "200", "25%" ]]],
+ function (config, id, cont) {
+ var testData = new SVGSizing.TestData(config);
+ var t = async_test(testData.name);
+ var expectedRect =
+ testData.computeInlineReplacedSize(outerWidth, outerHeight);
+ var placeholder = testData.buildSVGOrPlaceholder();
+ var container =
+ testData.buildContainer(placeholder);
+
+ var checkSize = function() {
+ var placeholderRect =
+ placeholder.getBoundingClientRect();
+
+ try {
+ assert_equals(placeholderRect.width,
+ expectedRect.width,
+ debugHint(id) + "Wrong width");
+ assert_equals(placeholderRect.height,
+ expectedRect.height,
+ debugHint(id) + "Wrong height");
+ } finally {
+ testContainer.removeChild(container);
+ if (testSingleId)
+ document.body.removeChild(testContainer);
+ cont(id+1);
+ }
+ t.done();
+ };
+
+ if (!config.placeholder) {
+ testContainer.appendChild(container);
+ test(checkSize, testData.name);
+ } else {
+ t.step(function() {
+ placeholder.addEventListener('load', function() {
+ // setTimeout is a work-around to let engines
+ // finish layout of child browsing contexts even
+ // after the load event
+ setTimeout(t.step_func(checkSize), 0);
+ });
+ testContainer.appendChild(container);
+ });
+ }
+ if (testSingleId == id)
+ testData.buildDemo(expectedRect, id);
+ }, testSingleId);
+}
diff --git a/tests/wpt/web-platform-tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-iframe-auto.html b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-iframe-auto.html
new file mode 100644
index 00000000000..4c3fefe88f3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-iframe-auto.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- This file is generated by gen-svgsizing-tests.py -->
+<html>
+ <head>
+ <title>SVG sizing: &lt;iframe></title>
+ <meta name=timeout content=long>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="../resources/svg-sizing.js"></script>
+ <style>
+ #testContainer {
+ position: absolute;
+ left: 0;
+ top: 0;
+ width: 800px;
+ height: 600px
+ }
+ iframe { border: 0 }
+ </style>
+ <link rel="help" href="http://www.w3.org/TR/CSS2/visudet.html#inline-replaced-width">
+ <link rel="help" href="http://www.w3.org/TR/CSS2/visudet.html#inline-replaced-height">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#replaced-elements">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#attr-dim-width">
+ <link rel="help" href="http://www.w3.org/TR/SVG/coords.html#ViewportSpace">
+ </head>
+ <body>
+ <div id="log"></div>
+ <div id="testContainer"></div>
+ <div id="demo"></div>
+ <script src="svg-embedded-sizing.js"></script>
+ <script>testPlaceholderWithHeight("iframe", null)</script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-iframe-fixed.html b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-iframe-fixed.html
new file mode 100644
index 00000000000..ae3328c6a88
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-iframe-fixed.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- This file is generated by gen-svgsizing-tests.py -->
+<html>
+ <head>
+ <title>SVG sizing: &lt;iframe></title>
+ <meta name=timeout content=long>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="../resources/svg-sizing.js"></script>
+ <style>
+ #testContainer {
+ position: absolute;
+ left: 0;
+ top: 0;
+ width: 800px;
+ height: 600px
+ }
+ iframe { border: 0 }
+ </style>
+ <link rel="help" href="http://www.w3.org/TR/CSS2/visudet.html#inline-replaced-width">
+ <link rel="help" href="http://www.w3.org/TR/CSS2/visudet.html#inline-replaced-height">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#replaced-elements">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#attr-dim-width">
+ <link rel="help" href="http://www.w3.org/TR/SVG/coords.html#ViewportSpace">
+ </head>
+ <body>
+ <div id="log"></div>
+ <div id="testContainer"></div>
+ <div id="demo"></div>
+ <script src="svg-embedded-sizing.js"></script>
+ <script>testPlaceholderWithHeight("iframe", '100px')</script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-iframe-percentage.html b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-iframe-percentage.html
new file mode 100644
index 00000000000..da00c0680bb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-iframe-percentage.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- This file is generated by gen-svgsizing-tests.py -->
+<html>
+ <head>
+ <title>SVG sizing: &lt;iframe></title>
+ <meta name=timeout content=long>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="../resources/svg-sizing.js"></script>
+ <style>
+ #testContainer {
+ position: absolute;
+ left: 0;
+ top: 0;
+ width: 800px;
+ height: 600px
+ }
+ iframe { border: 0 }
+ </style>
+ <link rel="help" href="http://www.w3.org/TR/CSS2/visudet.html#inline-replaced-width">
+ <link rel="help" href="http://www.w3.org/TR/CSS2/visudet.html#inline-replaced-height">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#replaced-elements">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#attr-dim-width">
+ <link rel="help" href="http://www.w3.org/TR/SVG/coords.html#ViewportSpace">
+ </head>
+ <body>
+ <div id="log"></div>
+ <div id="testContainer"></div>
+ <div id="demo"></div>
+ <script src="svg-embedded-sizing.js"></script>
+ <script>testPlaceholderWithHeight("iframe", '100%')</script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-img-auto.html b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-img-auto.html
new file mode 100644
index 00000000000..cef35306761
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-img-auto.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- This file is generated by gen-svgsizing-tests.py -->
+<html>
+ <head>
+ <title>SVG sizing: &lt;img></title>
+ <meta name=timeout content=long>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="../resources/svg-sizing.js"></script>
+ <style>
+ #testContainer {
+ position: absolute;
+ left: 0;
+ top: 0;
+ width: 800px;
+ height: 600px
+ }
+ iframe { border: 0 }
+ </style>
+ <link rel="help" href="http://www.w3.org/TR/CSS2/visudet.html#inline-replaced-width">
+ <link rel="help" href="http://www.w3.org/TR/CSS2/visudet.html#inline-replaced-height">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#replaced-elements">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#attr-dim-width">
+ <link rel="help" href="http://www.w3.org/TR/SVG/coords.html#ViewportSpace">
+ </head>
+ <body>
+ <div id="log"></div>
+ <div id="testContainer"></div>
+ <div id="demo"></div>
+ <script src="svg-embedded-sizing.js"></script>
+ <script>testPlaceholderWithHeight("img", null)</script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-img-fixed.html b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-img-fixed.html
new file mode 100644
index 00000000000..e8ad0dc935d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-img-fixed.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- This file is generated by gen-svgsizing-tests.py -->
+<html>
+ <head>
+ <title>SVG sizing: &lt;img></title>
+ <meta name=timeout content=long>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="../resources/svg-sizing.js"></script>
+ <style>
+ #testContainer {
+ position: absolute;
+ left: 0;
+ top: 0;
+ width: 800px;
+ height: 600px
+ }
+ iframe { border: 0 }
+ </style>
+ <link rel="help" href="http://www.w3.org/TR/CSS2/visudet.html#inline-replaced-width">
+ <link rel="help" href="http://www.w3.org/TR/CSS2/visudet.html#inline-replaced-height">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#replaced-elements">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#attr-dim-width">
+ <link rel="help" href="http://www.w3.org/TR/SVG/coords.html#ViewportSpace">
+ </head>
+ <body>
+ <div id="log"></div>
+ <div id="testContainer"></div>
+ <div id="demo"></div>
+ <script src="svg-embedded-sizing.js"></script>
+ <script>testPlaceholderWithHeight("img", '100px')</script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-img-percentage.html b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-img-percentage.html
new file mode 100644
index 00000000000..7bd5d90317f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-img-percentage.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- This file is generated by gen-svgsizing-tests.py -->
+<html>
+ <head>
+ <title>SVG sizing: &lt;img></title>
+ <meta name=timeout content=long>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="../resources/svg-sizing.js"></script>
+ <style>
+ #testContainer {
+ position: absolute;
+ left: 0;
+ top: 0;
+ width: 800px;
+ height: 600px
+ }
+ iframe { border: 0 }
+ </style>
+ <link rel="help" href="http://www.w3.org/TR/CSS2/visudet.html#inline-replaced-width">
+ <link rel="help" href="http://www.w3.org/TR/CSS2/visudet.html#inline-replaced-height">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#replaced-elements">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#attr-dim-width">
+ <link rel="help" href="http://www.w3.org/TR/SVG/coords.html#ViewportSpace">
+ </head>
+ <body>
+ <div id="log"></div>
+ <div id="testContainer"></div>
+ <div id="demo"></div>
+ <script src="svg-embedded-sizing.js"></script>
+ <script>testPlaceholderWithHeight("img", '100%')</script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-object-auto.html b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-object-auto.html
new file mode 100644
index 00000000000..7d79d2a4280
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-object-auto.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- This file is generated by gen-svgsizing-tests.py -->
+<html>
+ <head>
+ <title>SVG sizing: &lt;object></title>
+ <meta name=timeout content=long>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="../resources/svg-sizing.js"></script>
+ <style>
+ #testContainer {
+ position: absolute;
+ left: 0;
+ top: 0;
+ width: 800px;
+ height: 600px
+ }
+ iframe { border: 0 }
+ </style>
+ <link rel="help" href="http://www.w3.org/TR/CSS2/visudet.html#inline-replaced-width">
+ <link rel="help" href="http://www.w3.org/TR/CSS2/visudet.html#inline-replaced-height">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#replaced-elements">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#attr-dim-width">
+ <link rel="help" href="http://www.w3.org/TR/SVG/coords.html#ViewportSpace">
+ </head>
+ <body>
+ <div id="log"></div>
+ <div id="testContainer"></div>
+ <div id="demo"></div>
+ <script src="svg-embedded-sizing.js"></script>
+ <script>testPlaceholderWithHeight("object", null)</script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-object-fixed.html b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-object-fixed.html
new file mode 100644
index 00000000000..75f76362587
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-object-fixed.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- This file is generated by gen-svgsizing-tests.py -->
+<html>
+ <head>
+ <title>SVG sizing: &lt;object></title>
+ <meta name=timeout content=long>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="../resources/svg-sizing.js"></script>
+ <style>
+ #testContainer {
+ position: absolute;
+ left: 0;
+ top: 0;
+ width: 800px;
+ height: 600px
+ }
+ iframe { border: 0 }
+ </style>
+ <link rel="help" href="http://www.w3.org/TR/CSS2/visudet.html#inline-replaced-width">
+ <link rel="help" href="http://www.w3.org/TR/CSS2/visudet.html#inline-replaced-height">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#replaced-elements">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#attr-dim-width">
+ <link rel="help" href="http://www.w3.org/TR/SVG/coords.html#ViewportSpace">
+ </head>
+ <body>
+ <div id="log"></div>
+ <div id="testContainer"></div>
+ <div id="demo"></div>
+ <script src="svg-embedded-sizing.js"></script>
+ <script>testPlaceholderWithHeight("object", '100px')</script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-object-percentage.html b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-object-percentage.html
new file mode 100644
index 00000000000..8f82836e1b8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-object-percentage.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- This file is generated by gen-svgsizing-tests.py -->
+<html>
+ <head>
+ <title>SVG sizing: &lt;object></title>
+ <meta name=timeout content=long>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="../resources/svg-sizing.js"></script>
+ <style>
+ #testContainer {
+ position: absolute;
+ left: 0;
+ top: 0;
+ width: 800px;
+ height: 600px
+ }
+ iframe { border: 0 }
+ </style>
+ <link rel="help" href="http://www.w3.org/TR/CSS2/visudet.html#inline-replaced-width">
+ <link rel="help" href="http://www.w3.org/TR/CSS2/visudet.html#inline-replaced-height">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#replaced-elements">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#attr-dim-width">
+ <link rel="help" href="http://www.w3.org/TR/SVG/coords.html#ViewportSpace">
+ </head>
+ <body>
+ <div id="log"></div>
+ <div id="testContainer"></div>
+ <div id="demo"></div>
+ <script src="svg-embedded-sizing.js"></script>
+ <script>testPlaceholderWithHeight("object", '100%')</script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/rendering/replaced-elements/svg-inline-sizing/svg-inline.html b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/svg-inline-sizing/svg-inline.html
new file mode 100644
index 00000000000..2b3cf653666
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/svg-inline-sizing/svg-inline.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>SVG sizing: inline</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="../resources/svg-sizing.js"></script>
+ <style>
+ #testContainer {
+ position: absolute;
+ left: 0;
+ top: 0;
+ width: 800px;
+ height: 600px;
+ }
+ </style>
+ <link rel="help" href="http://www.w3.org/TR/CSS2/visudet.html#inline-replaced-width">
+ <link rel="help" href="http://www.w3.org/TR/CSS2/visudet.html#inline-replaced-height">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#replaced-elements">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#attr-dim-width">
+ <link rel="help" href="http://www.w3.org/TR/SVG/coords.html#ViewportSpace">
+ </head>
+ <body>
+ <div id="log"></div>
+ <div id="testContainer"></div>
+ <div id="demo"></div>
+ <script src="svg-inline.js"></script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/rendering/replaced-elements/svg-inline-sizing/svg-inline.js b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/svg-inline-sizing/svg-inline.js
new file mode 100644
index 00000000000..07c44f00ea6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/svg-inline-sizing/svg-inline.js
@@ -0,0 +1,78 @@
+// global async_test, assert_equals
+//
+// This test generates a couple of scenarios (each a
+// SVGSizing.TestData) for sizing inline <svg> and uses a simple
+// JavaScript sizing implementation for comparison.
+//
+// The tests loops through different combinations of:
+//
+// * width and height attributes and style on <svg>
+//
+// * viewBox on <svg> (gives intrinsic ratio)
+//
+// * width and height on containing block of <svg>
+//
+// All these may contribute to the final size of the SVG. The test
+// focuses on the size of the CSS box generated by the SVG. Little
+// focus is put on variations within an attribute that doesn't affect
+// the final size.
+//
+// To debug a specific test append ?<test-id> to the URL. An <iframe>
+// is generated with equivalent test and the source of the test is
+// added to a <pre> element.
+
+var debugHint = function(id) { return "(append ?"+id+" to debug) "; };
+var testSingleId;
+if (window.location.search) {
+ testSingleId = window.location.search.substring(1);
+ debugHint = function(id) { return ""; };
+}
+
+var testContainer = document.querySelector('#testContainer');
+var outerWidth = testContainer.getBoundingClientRect().width;
+var outerHeight = testContainer.getBoundingClientRect().height;
+
+SVGSizing.doCombinationTest(
+ [["placeholder", [ null ]],
+ ["containerWidthStyle", [null, "400px"]],
+ ["containerHeightStyle", [null, "400px"]],
+ ["svgViewBoxAttr", [ null, "0 0 100 200" ]],
+ ["svgWidthStyle", [ null, "100px", "50%" ]],
+ ["svgHeightStyle", [ null, "100px", "50%" ]],
+ ["svgWidthAttr", [ null, "200", "25%" ]],
+ ["svgHeightAttr", [ null, "200", "25%" ]]],
+ function(config, id, cont) {
+ var testData = new SVGSizing.TestData(config);
+
+ var expectedRect =
+ testData.computeInlineReplacedSize(outerWidth, outerHeight);
+ var svgElement = testData.buildSVGOrPlaceholder();
+ var container =
+ testData.buildContainer(svgElement);
+
+ var checkSize = function() {
+ var svgRect =
+ svgElement.getBoundingClientRect();
+
+ try {
+ assert_equals(svgRect.width,
+ expectedRect.width,
+ debugHint(id) + "Wrong width");
+ assert_equals(svgRect.height,
+ expectedRect.height,
+ debugHint(id) + "Wrong height");
+ } finally {
+ testContainer.removeChild(container);
+ if (testSingleId)
+ document.body.removeChild(testContainer);
+ cont(id+1);
+ }
+ };
+
+ testContainer.appendChild(container);
+ test(checkSize, testData.name);
+
+ if (testSingleId == id) {
+ testData.buildDemo(expectedRect, id);
+ }
+ }, testSingleId);
diff --git a/tests/wpt/web-platform-tests/html/rendering/replaced-elements/toolbars-0/.gitkeep b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/toolbars-0/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/toolbars-0/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/rendering/replaced-elements/tools/gen-svgsizing-tests.py b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/tools/gen-svgsizing-tests.py
new file mode 100644
index 00000000000..5ba69f8ab5b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/replaced-elements/tools/gen-svgsizing-tests.py
@@ -0,0 +1,55 @@
+from string import Template
+import os
+import sys
+
+template = Template("""<!DOCTYPE html>
+<!-- This file is generated by $generator -->
+<html>
+ <head>
+ <title>SVG sizing: &lt;$placeholder></title>
+ <meta name=timeout content=long>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="../resources/svg-sizing.js"></script>
+ <style>
+ #testContainer {
+ position: absolute;
+ left: 0;
+ top: 0;
+ width: 800px;
+ height: 600px
+ }
+ iframe { border: 0 }
+ </style>
+ <link rel="help" href="http://www.w3.org/TR/CSS2/visudet.html#inline-replaced-width">
+ <link rel="help" href="http://www.w3.org/TR/CSS2/visudet.html#inline-replaced-height">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#replaced-elements">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#attr-dim-width">
+ <link rel="help" href="http://www.w3.org/TR/SVG/coords.html#ViewportSpace">
+ </head>
+ <body>
+ <div id="log"></div>
+ <div id="testContainer"></div>
+ <div id="demo"></div>
+ <script src="svg-embedded-sizing.js"></script>
+ <script>testPlaceholderWithHeight("$placeholder", $placeholderHeightAttr)</script>
+ </body>
+</html>
+""")
+
+placeholders = [ "object", "iframe", "img" ]
+placeholderHeightAttrs = [ "null", "'100px'", "'100%'" ]
+placeholderHeightAttrsDescriptions = [ "auto", "fixed", "percentage" ]
+
+try:
+ os.makedirs("../svg-embedded-sizing")
+except OSError:
+ pass
+
+for placeholder in placeholders:
+ for i, placeholderHeightAttr in enumerate(placeholderHeightAttrs):
+ testContent = template.substitute(placeholder=placeholder, placeholderHeightAttr=placeholderHeightAttr, generator=sys.argv[0])
+ filename = "../svg-embedded-sizing/svg-in-%s-%s.html" % (placeholder, placeholderHeightAttrsDescriptions[i])
+ f = open(filename, "w")
+ f.write(testContent)
+ f.close()
diff --git a/tests/wpt/web-platform-tests/html/rendering/the-css-user-agent-style-sheet-and-presentational-hints/.gitkeep b/tests/wpt/web-platform-tests/html/rendering/the-css-user-agent-style-sheet-and-presentational-hints/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/the-css-user-agent-style-sheet-and-presentational-hints/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/rendering/unstyled-xml-documents/.gitkeep b/tests/wpt/web-platform-tests/html/rendering/unstyled-xml-documents/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/rendering/unstyled-xml-documents/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/common-idioms/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/common-idioms/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/common-idioms/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/common-idioms/conversations/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/common-idioms/conversations/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/common-idioms/conversations/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/common-idioms/footnotes/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/common-idioms/footnotes/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/common-idioms/footnotes/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/common-idioms/rel-up/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/common-idioms/rel-up/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/common-idioms/rel-up/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/common-idioms/tag-clouds/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/common-idioms/tag-clouds/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/common-idioms/tag-clouds/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/common-idioms/the-main-part-of-the-content/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/common-idioms/the-main-part-of-the-content/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/common-idioms/the-main-part-of-the-content/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/disabled-elements/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/disabled-elements/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/disabled-elements/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/disabled-elements/disabledElement.html b/tests/wpt/web-platform-tests/html/semantics/disabled-elements/disabledElement.html
new file mode 100644
index 00000000000..03f57424d22
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/disabled-elements/disabledElement.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Disabled elements</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#disabled-elements">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<button disabled>button</button>
+<input disabled>
+<select disabled>
+ <optgroup label="options" disabled>
+ <option value="option1" disabled>option1
+ <option value="option2">option2
+</select>
+<textarea disabled>textarea</textarea>
+<fieldset disabled>
+ <input type=radio name=c value=0 checked>
+ <input type=radio name=c value=1>
+</fieldset>
+<a href="http://www.w3.org/" disabled>w3</a>
+<span tabindex=0 disabled>foobar</span>
+
+<script>
+ test(function(){
+ assert_equals(document.activeElement, document.body);
+ }, "The body element must be the active element if no element is focused");
+
+ ["button", "input", "select", "optgroup", "option", "textarea", "input[type=radio]"].forEach(function(el) {
+ test(function() {
+ var element = document.querySelector(el);
+ element.focus();
+ assert_equals(document.activeElement, document.body, "activeElement after focus on a disabled <" + el + "> remains unchanged");
+ }, "A disabled <" + el + "> should not be focusable");
+ });
+
+ ["a", "span"].forEach(function(el) {
+ test(function() {
+ var element = document.querySelector(el);
+ element.focus();
+ assert_equals(document.activeElement, element, "focus on a <" + el + "> with a disabled attribute should make it the activeElement");
+ }, "A disabled <" + el + "> should be focusable");
+ });
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/document-metadata/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/document-metadata/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/document-metadata/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/document-metadata/styling/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/document-metadata/styling/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/document-metadata/styling/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/document-metadata/styling/LinkStyle.html b/tests/wpt/web-platform-tests/html/semantics/document-metadata/styling/LinkStyle.html
new file mode 100644
index 00000000000..09278d2028b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/document-metadata/styling/LinkStyle.html
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>HTML Test: Styling</title>
+ <link rel="author" title="Intel" href="http://www.intel.com/">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#styling">
+ <link id="style1" rel="text" title="Intel" href="./support/unmatch.css">
+ <link id="style2" rel="alternate stylesheet" type="text/css" title="" href="./support/emptytitle.css">
+ <link id="style3" rel="alternate stylesheet" type="text/css" href="./support/notitle.css">
+ <link id="style5" rel="stylesheet" type="text/css" href="./support/normal.css">
+ <link id="style6" rel="alternate stylesheet" type="text/css" href="./support/normal.css" title="./support/alternate.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <style id="style4" type="text/html">
+ #test {
+ height: 100px;
+ width: 100px;
+ }
+ </style>
+ <style id="style7" type="text/css" media="all" title="./support/alternate.css">
+ #test {
+ background-color: green;
+ }
+ </style>
+ </head>
+ <body>
+ <div id="log"></div>
+ <div id="test" style="display:none">STYLING TEST</div>
+
+ <script>
+ test(function() {
+ var style = null,
+ i;
+ for (i = 1; i < 5; i++) {
+ style = document.getElementById("style" + i);
+ assert_equals(style.sheet, null, "The sheet attribute of style" + i + " should be null.");
+ assert_false(style.disabled, "The disabled attribute of style" + i + " should be false.");
+ }
+ }, "The LinkStyle interface's sheet attribute must return null; the disabled attribute must be false");
+
+ test(function() {
+ var style = document.createElement("style"),
+ link = document.createElement("link");
+ assert_equals(style.sheet, null, "The sheet attribute of the style element not in a document should be null.");
+ assert_equals(link.sheet, null, "The sheet attribute of the link element not in a document should be null.");
+ }, "The LinkStyle interface's sheet attribute must return null if the corresponding element is not in a Document");
+
+ test(function() {
+ var style = null,
+ i;
+ for (i = 5; i < 8; i++) {
+ style = document.getElementById("style" + i);
+ assert_true(style.sheet instanceof StyleSheet, "The sheet attribute of style" + i + " should be a StyleSheet object.");
+ assert_equals(style.disabled, style.sheet.disabled, "The disabled attribute of style" + i + " should equal to the same attribute of StyleSheet.");
+ }
+ }, "The LinkStyle interface's sheet attribute must return StyleSheet object; the disabled attribute must be same as the StyleSheet's disabled attribute");
+
+ test(function() {
+ assert_equals(document.getElementById("style2").title, "", "The title attribute of style2 is incorrect.");
+ assert_equals(document.getElementById("style5").title, "", "The title attribute of style5 is incorrect.");
+ assert_equals(document.getElementById("style6").title, "./support/alternate.css", "The title attribute of style6 is incorrect.");
+ assert_equals(document.getElementById("style7").title, "./support/alternate.css", "The title attribute of style7 is incorrect.");
+ }, "The title must be the same as the value of the element's title content attribute");
+
+ test(function() {
+ assert_equals(document.getElementById("style5").media, "", "The media attribute of style5 is incorrect.");
+ assert_equals(document.getElementById("style7").media, "all", "The media attribute of style7 is incorrect.");
+ }, "The media must be the same as the value of the element's media content attribute, or the empty string if it is omitted");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/document-metadata/styling/support/alternate.css b/tests/wpt/web-platform-tests/html/semantics/document-metadata/styling/support/alternate.css
new file mode 100644
index 00000000000..b8deb07b0ac
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/document-metadata/styling/support/alternate.css
@@ -0,0 +1,7 @@
+#test {
+ color: yellow;
+ background-color: blue;
+ width: 100px;
+ height: 50px;
+ font-size: .5em;
+}
diff --git a/tests/wpt/web-platform-tests/html/semantics/document-metadata/styling/support/emptytitle.css b/tests/wpt/web-platform-tests/html/semantics/document-metadata/styling/support/emptytitle.css
new file mode 100644
index 00000000000..e62fe701b38
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/document-metadata/styling/support/emptytitle.css
@@ -0,0 +1,4 @@
+#test {
+ width: 100px;
+ height: 100px;
+}
diff --git a/tests/wpt/web-platform-tests/html/semantics/document-metadata/styling/support/normal.css b/tests/wpt/web-platform-tests/html/semantics/document-metadata/styling/support/normal.css
new file mode 100644
index 00000000000..a803c221124
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/document-metadata/styling/support/normal.css
@@ -0,0 +1,5 @@
+#test {
+ width: 100px;
+ height: 50px;
+ font-size: 10px;
+}
diff --git a/tests/wpt/web-platform-tests/html/semantics/document-metadata/styling/support/notitle.css b/tests/wpt/web-platform-tests/html/semantics/document-metadata/styling/support/notitle.css
new file mode 100644
index 00000000000..e62fe701b38
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/document-metadata/styling/support/notitle.css
@@ -0,0 +1,4 @@
+#test {
+ width: 100px;
+ height: 100px;
+}
diff --git a/tests/wpt/web-platform-tests/html/semantics/document-metadata/styling/support/unmatch.css b/tests/wpt/web-platform-tests/html/semantics/document-metadata/styling/support/unmatch.css
new file mode 100644
index 00000000000..e62fe701b38
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/document-metadata/styling/support/unmatch.css
@@ -0,0 +1,4 @@
+#test {
+ width: 100px;
+ height: 100px;
+}
diff --git a/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-base-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-base-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-base-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-base-element/base_href_empty.html b/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-base-element/base_href_empty.html
new file mode 100644
index 00000000000..7737556a1a8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-base-element/base_href_empty.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: base_href_empty</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-base-element">
+<base id="base" href="" target="_blank">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<img id="test" src="/images/blue-100x100.png" style="display:none">
+
+<script>
+ var testElement,
+ baseElement;
+
+ setup(function() {
+ testElement = document.getElementById("test");
+ baseElement = document.getElementById("base");
+ });
+
+ test(function() {
+ assert_equals(baseElement.href, document.location.href, "The href of base element is incorrect.");
+ }, "The value of the href attribute must be the document's address if it is empty");
+
+ test(function() {
+ var exp = testElement.src.substring(0, testElement.src.lastIndexOf("/images/blue-100x100.png") + 1);
+ assert_true(baseElement.href.indexOf(exp) != -1, "The src of img element is incorrect.");
+ }, "The src attribute of the img element must relative to document's address");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-base-element/base_href_specified.sub.html b/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-base-element/base_href_specified.sub.html
new file mode 100644
index 00000000000..e66a9caae46
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-base-element/base_href_specified.sub.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: base_href_specified</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-base-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<base id="base" href="http://{{domains[www]}}:{{ports[http][0]}}">
+<div id="log"></div>
+<img id="test" src="test.ico" style="display:none">
+
+<script>
+ var testElement;
+ var baseElement;
+
+ setup(function() {
+ testElement = document.getElementById("test");
+ baseElement = document.getElementById("base");
+ });
+
+ test(function() {
+ assert_equals(baseElement.href, "http://{{domains[www]}}:{{ports[http][0]}}/", "The href attribute of the base element is incorrect.");
+ }, "The href attribute of the base element is specified");
+
+ test(function() {
+ assert_equals(testElement.src, "http://{{domains[www]}}:{{ports[http][0]}}/test.ico", "The src attribute of the img element is incorrect.");
+ }, "The src attribute of the img element must relative to the href attribute of the base element");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-base-element/base_href_unspecified.html b/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-base-element/base_href_unspecified.html
new file mode 100644
index 00000000000..cf883f72395
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-base-element/base_href_unspecified.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: base_href_unspecified</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-base-element">
+<base id="base" target="_blank">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<div id="log"></div>
+<img id="test" src="/images/blue-100x100.png" style="display:none">
+
+<script>
+ var testElement,
+ baseElement;
+
+ setup(function () {
+ testElement = document.getElementById("test");
+ baseElement = document.getElementById("base");
+ });
+
+ test(function() {
+ assert_equals(baseElement.href, document.location.href, "Return the document base URL if the base element has no href content attribute.");
+ }, "The value of the href attribute must be the document's address if it is unspecified");
+
+ test(function() {
+ var exp = testElement.src.substring(0, testElement.src.lastIndexOf("/images/blue-100x100.png") + 1);
+ assert_true(baseElement.href.indexOf(exp) != -1, "The src attribute of the img element is incorrect.");
+ }, "The src attribute of the img element must relative to document's address");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-base-element/base_multiple.html b/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-base-element/base_multiple.html
new file mode 100644
index 00000000000..f56fd443bf0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-base-element/base_multiple.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: base_multiple</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-base-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body onload="on_load()">
+ <div id="log"></div>
+ <iframe id="test1" src="example.html" style="width:0;height:0" frameborder="0"></iframe>
+ <iframe id="test2" src="example.html" name="targetWin" style="width:0;height:0" frameborder="0"></iframe>
+ <script>
+ var t = async_test("The attributes of the a element must be affected by the first base element"),
+ doc1,
+ fr2,
+ a1;
+
+ function on_load() {
+ setup(function (){
+ doc1 = document.getElementById("test1").contentDocument;
+ fr2 = document.getElementById("test2");
+ a1 = doc1.getElementById("a1");
+ });
+
+ fr2.addEventListener("load", function () {
+ t.step(function () {
+ var doc2 = fr2.contentDocument;
+ assert_not_equals(doc2.location.href.indexOf("example2.html"), -1, "The target attribute does not impact the a element.");
+ assert_equals(doc2.getElementById("d1").innerHTML, "PASS", "The opend page should be the example2.html.");
+ });
+ t.done();
+ }, true);
+
+ a1.click();
+ }
+ </script>
+</body>
diff --git a/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-base-element/example.html b/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-base-element/example.html
new file mode 100644
index 00000000000..49dc772f916
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-base-element/example.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Example</title>
+<base target="targetWin" href="">
+<base target="_self" href="http://www.example.com/">
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<a id="a1" href="example2.html" target="">click me</a>
diff --git a/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-base-element/example2.html b/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-base-element/example2.html
new file mode 100644
index 00000000000..0e57cb9c5c1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-base-element/example2.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Example</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<div id="d1">PASS</div>
diff --git a/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-head-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-head-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-head-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-link-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-link-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-link-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-link-element/link-rellist.html b/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-link-element/link-rellist.html
new file mode 100644
index 00000000000..8d11f1e5ccc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-link-element/link-rellist.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<title>link.relList: non-string contains</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-link-element">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#domtokenlist">
+<link rel="help" href="https://heycam.github.io/webidl/#ecmascript-binding">
+<link rel="help" href="http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf#page=57">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link id="link" rel="undefined null 0 NaN Infinity">
+<div id="log"></div>
+<script>
+test(function() {
+ var list = document.getElementById("link").relList;
+ assert_equals(list.contains(undefined), true); //"undefined"
+ assert_equals(list.contains(null), true); //"null"
+ assert_equals(list.contains(-0), true); //"0"
+ assert_equals(list.contains(+0), true); //"0"
+ assert_equals(list.contains(NaN), true); //"NaN"
+ assert_equals(list.contains(+Infinity), true); //"Infinity"
+ assert_equals(list.contains(-Infinity), false); //"-Infinity"
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-link-element/link-style-error-01.html b/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-link-element/link-style-error-01.html
new file mode 100644
index 00000000000..ce35e03d93f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-link-element/link-style-error-01.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<title>link: error events</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-link-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<div id="test">
+<script>
+//var t404 = async_test("Should get an error event for a 404 error.")
+//t404.step(function() {
+// var elt = document.createElement("link");
+// elt.onerror = t404.step_func(function() {
+// assert_true(true, "Got error event for 404 error.")
+// t404.done()
+// })
+// elt.rel = "stylesheet";
+// elt.href = 404 error;
+// document.getElementsByTagName("head")[0].appendChild(elt);
+//})
+var tText = async_test("Should get an error event for a text/plain response.")
+tText.step(function() {
+ var elt = document.createElement("link");
+ elt.onerror = tText.step_func(function() {
+ assert_true(true, "Got error event for 404 error.")
+ tText.done()
+ })
+ elt.rel = "stylesheet";
+ elt.href = "../../../../../common/css-red.txt";
+ document.getElementsByTagName("head")[0].appendChild(elt);
+})
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-meta-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-meta-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-meta-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-meta-element/contains.json b/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-meta-element/contains.json
new file mode 100644
index 00000000000..70a4546914b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-meta-element/contains.json
@@ -0,0 +1,22 @@
+[
+ {
+ "id": "standard-metadata-names",
+ "original_id": "standard-metadata-names"
+ },
+ {
+ "id": "other-metadata-names",
+ "original_id": "other-metadata-names"
+ },
+ {
+ "id": "pragma-directives",
+ "original_id": "pragma-directives"
+ },
+ {
+ "id": "other-pragma-directives",
+ "original_id": "other-pragma-directives"
+ },
+ {
+ "id": "charset",
+ "original_id": "charset"
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-meta-element/the-lang-attribute-012.html b/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-meta-element/the-lang-attribute-012.html
new file mode 100644
index 00000000000..36ff2a2c24d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-meta-element/the-lang-attribute-012.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html >
+<head>
+<meta charset="utf-8"/>
+ <meta http-equiv="Content-Language" content="ko,zh,ja" >
+<title>Multiple languages in Content-Language meta element</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='https://html.spec.whatwg.org/multipage/#pragma-directives'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<meta name='flags' content='dom'>
+<style type='text/css'>
+ #colonlangcontroltest { color: red; font-weight: bold; width: 400px; }
+ #colonlangcontroltest:lang(xx) { display:none; }
+.test div { width: 50px; }
+
+#box:lang(ko) { width: 100px; }
+#box:lang(zh) { width: 100px; }
+#box:lang(ja) { width: 100px; }
+
+ /* styling for debugging related notes */
+ .notes span:lang(ko) { background-color: #0000FF; color: white; padding: 0 5px; }
+ .notes span:lang(zh) { background-color: #0000FF; color: white; padding: 0 5px; }
+ .notes span:lang(ja) { background-color: #0000FF; color: white; padding: 0 5px; }
+
+</style>
+</head>
+<body>
+
+
+
+<div class="test"><div id="box">&#xA0;</div></div>
+<p lang='xx' id='colonlangcontroltest'>This test failed because it relies on :lang for results, but :lang is not supported by this browser.</p>
+
+
+<!--Notes:
+
+This test uses :lang to detect whether the language has been set. If :lang is not supported, a message will appear and the test will fail.
+
+-->
+<script>
+test(function() {
+assert_equals(document.getElementById('colonlangcontroltest').offsetWidth, 0)
+assert_equals(document.getElementById('box').offsetWidth, 50);
+}, "The UA will not recognize a language declaration in the Content-Language meta element when more than one language is declared.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-style-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-style-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-style-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-style-element/html_style_in_comment-ref.html b/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-style-element/html_style_in_comment-ref.html
new file mode 100644
index 00000000000..999383c7696
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-style-element/html_style_in_comment-ref.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>[style] Reference file</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<style>
+ h4 {
+ color: green;
+ }
+</style>
+<body>
+ <p>
+ This page tests that Style written inside HTML comment is not applied
+ </p>
+ This test passes if the text below is <b>Green. NOT Red.</b>
+ <h4>
+ This is some text.
+ </h4>
+</body>
diff --git a/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-style-element/html_style_in_comment.xhtml b/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-style-element/html_style_in_comment.xhtml
new file mode 100644
index 00000000000..839548f01cf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-style-element/html_style_in_comment.xhtml
@@ -0,0 +1,18 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<link rel="match" href="html_style_in_comment-ref.html"/>
+<style type="text/css">
+h4 {color: green}
+<!--
+h4 {color: red}
+-->
+</style>
+</head>
+<body>
+<p> This page tests that Style written inside HTML comment is not applied</p>
+This test passes if the text below is <b>Green. NOT Red.</b>
+<h4>
+This is some text.
+</h4>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-style-element/style-error-01.html b/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-style-element/style-error-01.html
new file mode 100644
index 00000000000..87cb9fafd84
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-style-element/style-error-01.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<title>style: error events</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-style-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<div id="test">
+<script>
+//var t404 = async_test("Should get an error event for a 404 error.")
+//t404.step(function() {
+// var elt = document.createElement("style");
+// elt.onerror = t404.step_func(function() {
+// assert_true(true, "Got error event for 404 error.")
+// t404.done()
+// })
+// elt.appendChild(
+// document.createTextNode('@import 404 error;'));
+// document.getElementsByTagName("head")[0].appendChild(elt);
+//})
+var tText = async_test("Should get an error event for a text/plain response.")
+tText.step(function() {
+ var elt = document.createElement("style");
+ elt.onerror = tText.step_func(function() {
+ assert_true(true, "Got error event for 404 error.")
+ tText.done()
+ })
+ elt.appendChild(
+ document.createTextNode('@import "../../../../common/css-red.txt";'));
+ document.getElementsByTagName("head")[0].appendChild(elt);
+})
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-style-element/style_disabled.html b/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-style-element/style_disabled.html
new file mode 100644
index 00000000000..d26746a9c83
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-style-element/style_disabled.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>HTML Test: The style should not be applied if it is disabled</title>
+ <link rel="author" title="Intel" href="http://www.intel.com/">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-style-element">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <style>
+ #test {
+ width: 100px;
+ }
+ </style>
+ <style id="style">
+ #test {
+ width: 50px;
+ }
+ </style>
+ </head>
+ <body>
+ <div id="log"></div>
+ <div id="test"></div>
+ <script>
+ test(function() {
+ var testElement = document.getElementById("test");
+ var style = document.getElementById("style");
+ var width1, width2;
+
+ width1 = window.getComputedStyle(testElement, false)["width"];
+ assert_equals(width1, "50px", "The style should be applied.");
+
+ style.disabled = true;
+ width2 = window.getComputedStyle(testElement, false)["width"];
+ assert_equals(width2, "100px", "The style should not be applied.");
+ }, "The style is not applied when it is disabled");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-style-element/style_events.html b/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-style-element/style_events.html
new file mode 100644
index 00000000000..5e07e508829
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-style-element/style_events.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>HTML Test: The style events</title>
+ <link rel="author" title="Intel" href="http://www.intel.com/">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-style-element">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ var tLoad = async_test("If the style is loaded successfully, the 'load' event must be fired");
+ var tError = async_test("If the style is loaded unsuccessfully, the 'error' event must be fired");
+
+ function onstyleload(e) {
+ tLoad.done();
+ }
+
+ function onstyleerror(e) {
+ tError.done();
+ }
+ </script>
+ <style onload="onstyleload()">
+ #test {
+ height: 100px;
+ width: 100px;
+ }
+ </style>
+ <style onerror="onstyleerror()">
+ @import url(nonexistent.css);
+ </style>
+ </head>
+ <body>
+ <div id="log"></div>
+ <div id="test"></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-style-element/style_media.html b/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-style-element/style_media.html
new file mode 100644
index 00000000000..5bd189a2635
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-style-element/style_media.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>HTML Test: The style information must be applied to the environment specified by the media attribute</title>
+ <link rel="author" title="Intel" href="http://www.intel.com/">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#attr-style-media">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-style-element">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <style>
+ #test {
+ width: 100px;
+ }
+ </style>
+ <style id="style">
+ #test {
+ width: 50px;
+ }
+ </style>
+ </head>
+ <body>
+ <div id="log"></div>
+ <div id="test"></div>
+ <script>
+ test(function() {
+ var testElement = document.getElementById("test");
+ var style = document.getElementById("style");
+ var width1, width2;
+
+ width1 = window.getComputedStyle(testElement, false)["width"];
+ assert_equals(width1, "50px", "The style should be applied.");
+
+ style.media = "print";
+ width2 = window.getComputedStyle(testElement, false)["width"];
+ assert_equals(width2, "100px", "The style should not be applied.");
+ }, "The style information must be applied to the environment specified by the media attribute");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-style-element/style_scoped.html b/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-style-element/style_scoped.html
new file mode 100644
index 00000000000..d18e925ff4b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-style-element/style_scoped.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>HTML Test: The scoped attribute must apply the style information only to its parent element</title>
+ <link rel="author" title="Intel" href="http://www.intel.com/">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#attr-style-scoped">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-style-element">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <style>
+ #test {
+ width: 50px;
+ }
+ </style>
+ </head>
+ <body>
+ <div id="log"></div>
+ <div id="test"></div>
+ <div>
+ <style id="style">
+ #test {
+ width: 100px;
+ }
+ </style>
+ <div>
+ <script>
+ test(function() {
+ var testElement = document.getElementById("test");
+ var style = document.getElementById("style");
+ var width1, width2;
+
+ width1 = window.getComputedStyle(testElement, false)["width"];
+ assert_equals(width1, "100px", "The style 'width' should be applied.");
+
+ style.scoped = true;
+ width2 = window.getComputedStyle(testElement, false)["width"];
+ assert_equals(width2, "50px", "The width should not be applied.");
+ }, "The scoped attribute is present, the style information must be applied only to its parent element");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-title-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-title-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-title-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-title-element/title.text-01.html b/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-title-element/title.text-01.html
new file mode 100644
index 00000000000..7f25400ea89
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-title-element/title.text-01.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<title>title.text with comment and element children.</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-title-text">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+try {
+ var title = document.getElementsByTagName("title")[0];
+ while (title.childNodes.length)
+ title.removeChild(title.childNodes[0]);
+ title.appendChild(document.createComment("COMMENT"));
+ title.appendChild(document.createTextNode("TEXT"));
+ title.appendChild(document.createElement("a"))
+ .appendChild(document.createTextNode("ELEMENT"))
+} catch (e) {
+}
+</script>
+<script>
+test(function() {
+ assert_equals(title.text, "TEXT");
+ assert_equals(title.textContent, "TEXTELEMENT");
+})
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-title-element/title.text-02.xhtml b/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-title-element/title.text-02.xhtml
new file mode 100644
index 00000000000..068b105046d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-title-element/title.text-02.xhtml
@@ -0,0 +1,30 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>title.text with comment and element children.</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com"/>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-title-text"/>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id="log"></div>
+<script>
+try {
+ var title = document.getElementsByTagName("title")[0];
+ while (title.childNodes.length)
+ title.removeChild(title.childNodes[0]);
+ title.appendChild(document.createComment("COMMENT"));
+ title.appendChild(document.createTextNode("TEXT"));
+ title.appendChild(document.createElement("a"))
+ .appendChild(document.createTextNode("ELEMENT"))
+} catch (e) {
+}
+</script>
+<script>
+test(function() {
+ assert_equals(title.text, "TEXT");
+ assert_equals(title.textContent, "TEXTELEMENT");
+})
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-title-element/title.text-03.html b/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-title-element/title.text-03.html
new file mode 100644
index 00000000000..1c119a825cf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-title-element/title.text-03.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<title> title.text and space normalization </title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-title-text">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ assert_equals(document.getElementsByTagName("title")[0].text,
+ " title.text and space normalization ");
+ assert_equals(document.getElementsByTagName("title")[0].textContent,
+ " title.text and space normalization ");
+ assert_equals(document.getElementsByTagName("title")[0].firstChild.nodeValue,
+ " title.text and space normalization ");
+}, "title.text and space normalization (markup)");
+[
+ "one space", "two spaces",
+ "one\ttab", "two\t\ttabs",
+ "one\nnewline", "two\n\nnewlines",
+ "one\fform feed", "two\f\fform feeds",
+ "one\rcarriage return", "two\r\rcarriage returns"
+].forEach(function(str) {
+ test(function() {
+ document.title = str;
+ var title = document.getElementsByTagName("title")[0];
+ assert_equals(title.text, str);
+ assert_equals(title.textContent, str);
+ assert_equals(title.firstChild.nodeValue, str);
+ }, "title.text and space normalization: " + format_value(str))
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-title-element/title.text-04.xhtml b/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-title-element/title.text-04.xhtml
new file mode 100644
index 00000000000..de382ab4d52
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/document-metadata/the-title-element/title.text-04.xhtml
@@ -0,0 +1,37 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title> title.text and space normalization </title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com"/>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-title-text"/>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ assert_equals(document.getElementsByTagName("title")[0].text,
+ " title.text and space normalization ");
+ assert_equals(document.getElementsByTagName("title")[0].textContent,
+ " title.text and space normalization ");
+ assert_equals(document.getElementsByTagName("title")[0].firstChild.nodeValue,
+ " title.text and space normalization ");
+}, "title.text and space normalization (markup)");
+[
+ "one space", "two spaces",
+ "one\ttab", "two\t\ttabs",
+ "one\nnewline", "two\n\nnewlines",
+ "one\fform feed", "two\f\fform feeds",
+ "one\rcarriage return", "two\r\rcarriage returns"
+].forEach(function(str) {
+ test(function() {
+ document.title = str;
+ var title = document.getElementsByTagName("title")[0];
+ assert_equals(title.text, str);
+ assert_equals(title.textContent, str);
+ assert_equals(title.firstChild.nodeValue, str);
+ }, "title.text and space normalization: " + format_value(str))
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/edits/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/edits/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/edits/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/edits/attributes-common-to-ins-and-del-elements/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/edits/attributes-common-to-ins-and-del-elements/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/edits/attributes-common-to-ins-and-del-elements/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/edits/edits-and-lists/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/edits/edits-and-lists/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/edits/edits-and-lists/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/edits/edits-and-paragraphs/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/edits/edits-and-paragraphs/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/edits/edits-and-paragraphs/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/edits/edits-and-tables/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/edits/edits-and-tables/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/edits/edits-and-tables/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/edits/the-del-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/edits/the-del-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/edits/the-del-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/edits/the-del-element/del_effect.html b/tests/wpt/web-platform-tests/html/semantics/edits/the-del-element/del_effect.html
new file mode 100644
index 00000000000..14297e5293e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/edits/the-del-element/del_effect.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<meta charset=UTF-8>
+<title>HTML Test: Text in the del element should be 'line-through'</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-del-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<p><del>crossed-off text</del></p>
+<div id="log"></div>
+
+<script>
+ test(function() {
+ var element = document.getElementsByTagName('del')[0],
+ textDecoration = getComputedStyle(element).textDecorationLine ||
+ getComputedStyle(element).textDecoration;
+ assert_equals(textDecoration, 'line-through');
+ });
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/edits/the-ins-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/edits/the-ins-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/edits/the-ins-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/edits/the-ins-element/ins_effect.html b/tests/wpt/web-platform-tests/html/semantics/edits/the-ins-element/ins_effect.html
new file mode 100644
index 00000000000..6e1b3445969
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/edits/the-ins-element/ins_effect.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<meta charset=UTF-8>
+<title>HTML Test: Text in the ins element should be 'underline'</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-ins-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<p><ins>underlined text</ins></p>
+<div id="log"></div>
+
+<script>
+ test(function() {
+ var element = document.getElementsByTagName('ins')[0],
+ textDecoration = getComputedStyle(element).textDecorationLine ||
+ getComputedStyle(element).textDecoration;
+ assert_equals(textDecoration, 'underline');
+ });
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/embedded-content/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/dimension-attributes/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/embedded-content/dimension-attributes/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/dimension-attributes/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/image-maps/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/embedded-content/image-maps/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/image-maps/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/image-maps/contains.json b/tests/wpt/web-platform-tests/html/semantics/embedded-content/image-maps/contains.json
new file mode 100644
index 00000000000..77e0d34fa40
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/image-maps/contains.json
@@ -0,0 +1,10 @@
+[
+ {
+ "id": "authoring",
+ "original_id": "authoring"
+ },
+ {
+ "id": "processing-model-0",
+ "original_id": "processing-model-0"
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/mathml/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/embedded-content/mathml/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/mathml/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/audio_controls_present-manual.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/audio_controls_present-manual.html
new file mode 100644
index 00000000000..38faa4d00ad
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/audio_controls_present-manual.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Audio Test: audio_controls_present.html</title>
+ <link rel="author" title="Intel" href="http://www.intel.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-media-controls" />
+ <meta name="flags" content="" />
+ <meta name="assert" content="Check if the controls attribute is present in the audio element that expecting the user agent exposes a controller user interface" />
+ </head>
+ <body>
+ <p>Test passes if a controller user interface appears below and the text 'The user agent doesn't support media element.' does not appear anywhere on this page</p>
+ <audio id="m" controls>The user agent doesn't support media element.</audio>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/audio_loop_base.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/audio_loop_base.html
new file mode 100644
index 00000000000..4917d9c3955
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/audio_loop_base.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Audio Test: audio_loop_base</title>
+ <link rel="author" title="Intel" href="http://www.intel.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-media-loop" />
+ <meta name="flags" content="" />
+ <meta name="assert" content="Check if audio.loop is set to true that expecting the seeking event is fired more than once" />
+ <meta name=timeout content=long>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <audio id="m" controls>The user agent doesn't support media element.</audio>
+ <script type="text/javascript">
+ var media = document.getElementById("m");
+ var name = document.getElementsByName("assert")[0].content;
+ var t = async_test(name);
+
+ var looped = false;
+
+ function startTest() {
+ if (looped) {
+ t.step(function() {
+ assert_true(true, "looped");
+ });
+ t.done();
+ media.pause();
+ }
+
+ looped = true;
+ }
+
+ media.addEventListener("seeking", startTest, false);
+ media.loop = true;
+ media.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+ media.play();
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/audio_loop_current_media_controller-manual.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/audio_loop_current_media_controller-manual.html
new file mode 100644
index 00000000000..c76377022fc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/audio_loop_current_media_controller-manual.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Audio Test: audio_loop_current_media_controller</title>
+ <link rel="author" title="Intel" href="http://www.intel.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-media-loop" />
+ <meta name="flags" content="" />
+ <meta name="assert" content="Check if the audio element has a current media controller that expecting the loop attribute has no effect" />
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p>Test passes if the audio doesn't repeatly play and the text 'The user agent doesn't support media element.' does not appear anywhere on this page</p>
+ <audio id="m" controls loop mediagroup="movie">The user agent doesn't support media element.</audio>
+ <script type="text/javascript">
+ var media = document.getElementById("m");
+ var controller = new MediaController();
+
+ media.controller = controller;
+ media.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+ media.play();
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/audio_muted_overriding_volume-manual.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/audio_muted_overriding_volume-manual.html
new file mode 100644
index 00000000000..cc1892ce89e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/audio_muted_overriding_volume-manual.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Audio Test: audio_muted_overriding_volume</title>
+ <link rel="author" title="Intel" href="http://www.intel.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-media-muted" />
+ <meta name="flags" content="" />
+ <meta name="assert" content="Check if the muted attribute is present in the audio element with volume is set to loudest that expecting the user hears no sound" />
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p>Test passes if the audio is playing without sound output and the text 'The user agent doesn't support media element.' does not appear anywhere on this page</p>
+ <audio id="m" controls muted>The user agent doesn't support media element.</audio>
+ <script type="text/javascript">
+ var media = document.getElementById("m");
+ media.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+ media.volume = 1.0;
+ media.play();
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/audio_muted_present-manual.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/audio_muted_present-manual.html
new file mode 100644
index 00000000000..16d6f07eed2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/audio_muted_present-manual.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Audio Test: audio_muted_present</title>
+ <link rel="author" title="Intel" href="http://www.intel.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-media-muted" />
+ <meta name="flags" content="" />
+ <meta name="assert" content="Check if the muted attribute is present in the audio element that expecting the user hears no sound" />
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p>Test passes if the audio is playing without sound output and the text 'The user agent doesn't support media element.' does not appear anywhere on this page</p>
+ <audio id="m" controls muted>The user agent doesn't support media element.</audio>
+ <script type="text/javascript">
+ var media = document.getElementById("m");
+ media.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+ media.play();
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/audio_volume_check.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/audio_volume_check.html
new file mode 100644
index 00000000000..b467c702a7c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/audio_volume_check.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Audio Test: audio_volume_check</title>
+ <link rel="author" title="Intel" href="http://www.intel.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-media-volume" />
+ <meta name="flags" content="" />
+ <meta name="assert" content="Check that audio.volume returns the value of the muted content attribute" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <audio id="m">The user agent doesn't support media element.</audio>
+ <script type="text/javascript">
+ var media = document.getElementById("m");
+ var VOLUME = {
+ 'SILENT' : 0.0,
+ 'NORMAL' : 0.5,
+ 'LOUDEST' : 1.0,
+ 'LOWER' : -1.1,
+ 'UPPER' : 1.1,
+ };
+
+ test(function() {
+ assert_false(media.volume < VOLUME.SILENT || media.volume > VOLUME.LOUDEST, "media.volume outside the range 0.0 to 1.0 inclusive");
+ }, "Check if the intial value of the audio.volume is in the range 0.0 to 1.0 inclusive");
+
+ function volume_setting(vol, name)
+ {
+ if (vol < VOLUME.SILENT || vol > VOLUME.LOUDEST) {
+ try {
+ media.volume = vol;
+ test(function() {
+ assert_true(false, "media.volume setting exception");
+ }, name);
+ } catch(e) {
+ test(function() {
+ // 1 should be e.IndexSizeError or e.INDEX_SIZE_ERR in previous spec
+ assert_equals(e.code, 1, "media.volume setting exception");
+ }, name);
+ }
+ } else {
+ media.volume = vol;
+ test(function() {
+ assert_equals(media.volume, vol, "media.volume new value");
+ }, name);
+ }
+ }
+
+ volume_setting(VOLUME.NORMAL, "Check if audio.volume is able to set to new value in the range 0.0 to 1.0");
+ volume_setting(VOLUME.SILENT, "Check if media.volume is able to set to new value 0.0 as silent");
+ volume_setting(VOLUME.LOUDEST, "Check if media.volume is able to set to new value 1.0 as loudest");
+ volume_setting(VOLUME.LOWER, "Check if media.volume is set to new value less than 0.0 that expecting an IndexSizeError exception is to be thrown");
+ volume_setting(VOLUME.UPPER, "Check if audio.volume is set to new value greater than 1.0 that expecting an IndexSizeError exception is to be thrown");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/audio_volume_loudest-manual.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/audio_volume_loudest-manual.html
new file mode 100644
index 00000000000..a623e8f5c2e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/audio_volume_loudest-manual.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Audio Test: audio_volume_loudest</title>
+ <link rel="author" title="Intel" href="http://www.intel.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-media-volume" />
+ <meta name="flags" content="" />
+ <meta name="assert" content="Check if the volume attribute is set to 1.0 as loudest in the audio element that expecting the user hears sound loudly" />
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p>Test passes if the audio is playing with sound heard and the text 'The user agent doesn't support media element.' does not appear anywhere on this page</p>
+ <audio id="m" controls>The user agent doesn't support media element.</audio>
+ <script type="text/javascript">
+ var media = document.getElementById("m");
+ media.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+ media.volume = 1.0;
+ media.play();
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/audio_volume_silent-manual.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/audio_volume_silent-manual.html
new file mode 100644
index 00000000000..257bd46289d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/audio_volume_silent-manual.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Audio Test: audio_volume_silent</title>
+ <link rel="author" title="Intel" href="http://www.intel.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-media-volume" />
+ <meta name="flags" content="" />
+ <meta name="assert" content="Check if the volume attribute is set to 0.0 as silent in the audio element that expecting the user hears no sound" />
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p>Test passes if the audio is playing without sound heard and the text 'The user agent doesn't support media element.' does not appear anywhere on this page</p>
+ <audio id="m" controls volume=0.0>The user agent doesn't support media element.</audio>
+ <script type="text/javascript">
+ var media = document.getElementById("m");
+ media.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+ media.volume = 0.0;
+ media.play();
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/contains.json b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/contains.json
new file mode 100644
index 00000000000..9cf23296cee
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/contains.json
@@ -0,0 +1,132 @@
+[
+ {
+ "id": "error-codes",
+ "original_id": "error-codes"
+ },
+ {
+ "id": "location-of-the-media-resource",
+ "original_id": "location-of-the-media-resource"
+ },
+ {
+ "id": "mime-types",
+ "original_id": "mime-types"
+ },
+ {
+ "id": "network-states",
+ "original_id": "network-states"
+ },
+ {
+ "id": "loading-the-media-resource",
+ "original_id": "loading-the-media-resource"
+ },
+ {
+ "id": "offsets-into-the-media-resource",
+ "original_id": "offsets-into-the-media-resource"
+ },
+ {
+ "id": "ready-states",
+ "original_id": "ready-states"
+ },
+ {
+ "id": "playing-the-media-resource",
+ "original_id": "playing-the-media-resource"
+ },
+ {
+ "id": "seeking",
+ "original_id": "seeking"
+ },
+ {
+ "id": "media-resources-with-multiple-media-tracks",
+ "original_id": "media-resources-with-multiple-media-tracks",
+ "children": [
+ {
+ "id": "audiotracklist-and-videotracklist-objects",
+ "original_id": "audiotracklist-and-videotracklist-objects"
+ },
+ {
+ "id": "selecting-specific-audio-and-video-tracks-declaratively",
+ "original_id": "selecting-specific-audio-and-video-tracks-declaratively"
+ }
+ ]
+ },
+ {
+ "id": "synchronising-multiple-media-elements",
+ "original_id": "synchronising-multiple-media-elements",
+ "children": [
+ {
+ "id": "introduction-0",
+ "original_id": "introduction-0"
+ },
+ {
+ "id": "media-controllers",
+ "original_id": "media-controllers"
+ },
+ {
+ "id": "assigning-a-media-controller-declaratively",
+ "original_id": "assigning-a-media-controller-declaratively"
+ }
+ ]
+ },
+ {
+ "id": "timed-text-tracks",
+ "original_id": "timed-text-tracks",
+ "children": [
+ {
+ "id": "text-track-model",
+ "original_id": "text-track-model"
+ },
+ {
+ "id": "sourcing-in-band-text-tracks",
+ "original_id": "sourcing-in-band-text-tracks"
+ },
+ {
+ "id": "sourcing-out-of-band-text-tracks",
+ "original_id": "sourcing-out-of-band-text-tracks"
+ },
+ {
+ "id": "guidelines-for-exposing-cues-in-various-formats-as-text-track-cues",
+ "original_id": "guidelines-for-exposing-cues-in-various-formats-as-text-track-cues"
+ },
+ {
+ "id": "text-track-api",
+ "original_id": "text-track-api"
+ },
+ {
+ "id": "text-tracks-describing-chapters",
+ "original_id": "text-tracks-describing-chapters"
+ },
+ {
+ "id": "cue-events",
+ "original_id": "cue-events"
+ }
+ ]
+ },
+ {
+ "id": "user-interface",
+ "original_id": "user-interface"
+ },
+ {
+ "id": "time-ranges",
+ "original_id": "time-ranges"
+ },
+ {
+ "id": "event-definitions",
+ "original_id": "event-definitions"
+ },
+ {
+ "id": "mediaevents",
+ "original_id": "mediaevents"
+ },
+ {
+ "id": "security-and-privacy-considerations",
+ "original_id": "security-and-privacy-considerations"
+ },
+ {
+ "id": "best-practices-for-authors-using-media-elements",
+ "original_id": "best-practices-for-authors-using-media-elements"
+ },
+ {
+ "id": "best-practices-for-implementors-of-media-elements",
+ "original_id": "best-practices-for-implementors-of-media-elements"
+ }
+]
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/error-codes/error.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/error-codes/error.html
new file mode 100644
index 00000000000..c9757604167
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/error-codes/error.html
@@ -0,0 +1,38 @@
+<!doctype html>
+<title>error</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/media.js"></script>
+<div id="log"></div>
+<script>
+function error_test(tagName, src) {
+ test(function() {
+ assert_equals(document.createElement(tagName).error, null);
+ }, tagName + '.error initial value');
+
+ async_test(function(t) {
+ var e = document.createElement(tagName);
+ e.src = src;
+ e.onloadeddata = t.step_func(function() {
+ assert_equals(e.error, null);
+ t.done();
+ });
+ }, tagName + '.error after successful load');
+
+ // TODO: MEDIA_ERR_ABORTED, MEDIA_ERR_NETWORK, MEDIA_ERR_DECODE
+
+ async_test(function(t) {
+ var e = document.createElement(tagName);
+ e.src = '';
+ e.onerror = t.step_func(function() {
+ assert_true(e.error instanceof MediaError);
+ assert_equals(e.error.code, 4);
+ assert_equals(e.error.code, e.error.MEDIA_ERR_SRC_NOT_SUPPORTED);
+ t.done();
+ });
+ }, tagName + '.error after setting src to the empty string');
+}
+
+error_test('audio', getAudioURI('/media/sound_5'));
+error_test('video', getVideoURI('/media/movie_5'));
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_canplay.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_canplay.html
new file mode 100644
index 00000000000..8e1b32dcb30
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_canplay.html
@@ -0,0 +1,38 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - canplay</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" autoplay controls>
+ </audio>
+ <video id="v" autoplay controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var t = async_test("setting src attribute on autoplay audio should trigger canplay event", {timeout:5000});
+ var a = document.getElementById("a");
+ a.addEventListener("canplay", function() {
+ t.done();
+ a.pause();
+ }, false);
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+}, "audio events - canplay");
+
+test(function() {
+ var t = async_test("setting src attribute on autoplay video should trigger canplay event", {timeout:5000});
+ var v = document.getElementById("v");
+ v.addEventListener("canplay", function() {
+ t.done();
+ v.pause();
+ }, false);
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+}, "video events - canplay");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_canplay_noautoplay.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_canplay_noautoplay.html
new file mode 100644
index 00000000000..8f3372501d2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_canplay_noautoplay.html
@@ -0,0 +1,36 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - canplay</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" controls>
+ </audio>
+ <video id="v" controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function () {
+ var t = async_test("setting src attribute on non-autoplay audio should trigger canplay event", {timeout:5000});
+ var a = document.getElementById("a");
+ a.addEventListener("canplay", function() {
+ t.done();
+ }, false);
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+}, "audio events - canplay");
+
+test(function () {
+ var t = async_test("setting src attribute on non-autoplay video should trigger canplay event", {timeout:5000});
+ var v = document.getElementById("v");
+ v.addEventListener("canplay", function() {
+ t.done();
+ }, false);
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+}, "video events - canplay");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_canplaythrough.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_canplaythrough.html
new file mode 100644
index 00000000000..827e796072f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_canplaythrough.html
@@ -0,0 +1,38 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - canplaythrough</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" autoplay controls>
+ </audio>
+ <video id="v" autoplay controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var t = async_test("setting src attribute on autoplay audio should trigger canplaythrough event", {timeout:5000});
+ var a = document.getElementById("a");
+ a.addEventListener("canplaythrough", function() {
+ t.done();
+ a.pause();
+ }, false);
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+}, "audio events - canplaythrough");
+
+test(function() {
+ var t = async_test("setting src attribute on autoplay video should trigger canplaythrough event", {timeout:5000});
+ var v = document.getElementById("v");
+ v.addEventListener("canplaythrough", function() {
+ t.done();
+ v.pause();
+ }, false);
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+}, "video events - canplaythrough");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_canplaythrough_noautoplay.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_canplaythrough_noautoplay.html
new file mode 100644
index 00000000000..75a70985ab3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_canplaythrough_noautoplay.html
@@ -0,0 +1,36 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - canplaythrough</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" controls>
+ </audio>
+ <video id="v" controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var t = async_test("setting src attribute on non-autoplay audio should trigger canplaythrough event", {timeout:5000});
+ var a = document.getElementById("a");
+ a.addEventListener("canplaythrough", function() {
+ t.done();
+ }, false);
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+}, "audio events - canplaythrough");
+
+test(function() {
+ var t = async_test("setting src attribute on non-autoplay video should trigger canplaythrough event", {timeout:5000});
+ var v = document.getElementById("v");
+ v.addEventListener("canplaythrough", function() {
+ t.done();
+ }, false);
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+}, "video events - canplaythrough");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_loadeddata.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_loadeddata.html
new file mode 100644
index 00000000000..f0e89c3c160
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_loadeddata.html
@@ -0,0 +1,38 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - loadeddata</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" autoplay controls>
+ </audio>
+ <video id="v" autoplay controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var t = async_test("setting src attribute on autoplay audio should trigger loadeddata event", {timeout:5000});
+ var a = document.getElementById("a");
+ a.addEventListener("loadeddata", function() {
+ t.done();
+ a.pause();
+ }, false);
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+}, "audio events - loadeddata");
+
+test(function() {
+ var t = async_test("setting src attribute on autoplay video should trigger loadeddata event", {timeout:5000});
+ var a = document.getElementById("v");
+ v.addEventListener("loadeddata", function() {
+ t.done();
+ v.pause();
+ }, false);
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+}, "video events - loadeddata");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_loadeddata_noautoplay.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_loadeddata_noautoplay.html
new file mode 100644
index 00000000000..0c81f335bb5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_loadeddata_noautoplay.html
@@ -0,0 +1,36 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - loadeddata</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" controls>
+ </audio>
+ <video id="v" controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var t = async_test("setting src attribute on non-autoplay audio should trigger loadeddata event", {timeout:5000});
+ var a = document.getElementById("a");
+ a.addEventListener("loadeddata", function() {
+ t.done();
+ }, false);
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+}, "audio events - loadeddata");
+
+test(function() {
+ var t = async_test("setting src attribute on non-autoplay video should trigger loadeddata event", {timeout:5000});
+ var v = document.getElementById("v");
+ v.addEventListener("loadeddata", function() {
+ t.done();
+ }, false);
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+}, "video events - loadeddata");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_loadedmetadata.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_loadedmetadata.html
new file mode 100644
index 00000000000..234121e58b5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_loadedmetadata.html
@@ -0,0 +1,38 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - loadedmetadata</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" autoplay controls>
+ </audio>
+ <video id="v" autoplay controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var t = async_test("setting src attribute on autoplay audio should trigger loadedmetadata event", {timeout:5000});
+ var a = document.getElementById("a");
+ a.addEventListener("loadedmetadata", function() {
+ t.done();
+ a.pause();
+ });
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+}, "audio events - loadedmetadata");
+
+test(function() {
+ var t = async_test("setting src attribute on autoplay video should trigger loadedmetadata event", {timeout:5000});
+ var v = document.getElementById("v");
+ v.addEventListener("loadedmetadata", function() {
+ t.done();
+ v.pause();
+ });
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+}, "video events - loadedmetadata");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_loadedmetadata_noautoplay.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_loadedmetadata_noautoplay.html
new file mode 100644
index 00000000000..382f3f6fb26
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_loadedmetadata_noautoplay.html
@@ -0,0 +1,36 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - loadedmetadata</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" controls>
+ </audio>
+ <video id="v" controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var t = async_test("setting src attribute on non-autoplay audio should trigger loadedmetadata event", {timeout:5000});
+ var a = document.getElementById("a");
+ a.addEventListener("loadedmetadata", function() {
+ t.done();
+ }, false);
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+}, "audio events - loadedmetadata");
+
+test(function() {
+ var t = async_test("setting src attribute on non-autoplay video should trigger loadedmetadata event", {timeout:5000});
+ var v = document.getElementById("v");
+ v.addEventListener("loadedmetadata", function() {
+ t.done();
+ }, false);
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+}, "video events, loadedmetadata");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_loadstart.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_loadstart.html
new file mode 100644
index 00000000000..de45682125c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_loadstart.html
@@ -0,0 +1,38 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - loadstart</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" autoplay controls>
+ </audio>
+ <video id="v" autoplay controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var t = async_test("setting src attribute on autoplay audio should trigger loadstart event", {timeout:5000});
+ var a = document.getElementById("a");
+ a.addEventListener("loadstart", function() {
+ t.done();
+ a.pause();
+ }, false);
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+}, "audio events - loadstart");
+
+test(function() {
+ var t = async_test("setting src attribute on autoplay video should trigger loadstart event", {timeout:5000});
+ var v = document.getElementById("v");
+ v.addEventListener("loadstart", function() {
+ t.done();
+ v.pause();
+ }, false);
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+}, "video events - loadstart");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_loadstart_noautoplay.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_loadstart_noautoplay.html
new file mode 100644
index 00000000000..b575e7ac87c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_loadstart_noautoplay.html
@@ -0,0 +1,36 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - loadstart</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" controls>
+ </audio>
+ <video id="v" controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var t = async_test("setting src attribute on non-autoplay audio should trigger loadstart event", {timeout:5000});
+ var a = document.getElementById("a");
+ a.addEventListener("loadstart", function() {
+ t.done();
+ }, false);
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+}, "audio events - loadstart");
+
+test(function() {
+ var t = async_test("setting src attribute on non-autoplay video should trigger loadstart event", {timeout:5000});
+ var v = document.getElementById("v");
+ v.addEventListener("loadstart", function() {
+ t.done();
+ }, false);
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+}, "video events - loadstart");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_order_canplay_canplaythrough.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_order_canplay_canplaythrough.html
new file mode 100644
index 00000000000..a1e7e4155ac
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_order_canplay_canplaythrough.html
@@ -0,0 +1,52 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - canplay, then canplaythrough</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" autoplay controls>
+ </audio>
+ <video id="v" autoplay controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var t = async_test("setting src attribute on autoplay audio should trigger canplay then canplaythrough event", {timeout:5000});
+ var a = document.getElementById("a");
+ var found_canplay = false;
+ a.addEventListener("canplay", function() {
+ found_canplay = true;
+ });
+ a.addEventListener("canplaythrough", function() {
+ t.step(function() {
+ assert_true(found_canplay);
+ });
+ t.done();
+ a.pause();
+ }, false);
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+}, "audio events - canplay, then canplaythrough");
+
+test(function() {
+ var t = async_test("setting src attribute on autoplay video should trigger canplay then canplaythrough event", {timeout:5000});
+ var v = document.getElementById("v");
+ var found_canplay = false;
+ v.addEventListener("canplay", function() {
+ found_canplay = true;
+ });
+ v.addEventListener("canplaythrough", function() {
+ t.step(function() {
+ assert_true(found_canplay);
+ });
+ t.done();
+ v.pause();
+ }, false);
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+}, "video events - canplay, then canplaythrough");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_order_canplay_playing.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_order_canplay_playing.html
new file mode 100644
index 00000000000..a5a67ddb2df
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_order_canplay_playing.html
@@ -0,0 +1,52 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - canplay, then playing</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" autoplay controls>
+ </audio>
+ <video id="v" autoplay controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var t = async_test("setting src attribute on autoplay audio should trigger canplay then playing event", {timeout:5000});
+ var a = document.getElementById("a");
+ var found_canplay = false;
+ a.addEventListener("canplay", function() {
+ found_canplay = true;
+ });
+ a.addEventListener("playing", function() {
+ t.step(function() {
+ assert_true(found_canplay);
+ });
+ t.done();
+ a.pause();
+ }, false);
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+}, "audio events - canplay, then playing");
+
+test(function() {
+ var t = async_test("setting src attribute on autoplay video should trigger canplay then playing event", {timeout:5000});
+ var v = document.getElementById("v");
+ var found_canplay = false;
+ v.addEventListener("canplay", function() {
+ found_canplay = true;
+ });
+ v.addEventListener("playing", function() {
+ t.step(function() {
+ assert_true(found_canplay);
+ });
+ t.done();
+ v.pause();
+ }, false);
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+}, "video events - canplay, then playing");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_order_loadedmetadata_loadeddata.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_order_loadedmetadata_loadeddata.html
new file mode 100644
index 00000000000..3aba3684f19
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_order_loadedmetadata_loadeddata.html
@@ -0,0 +1,52 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - loadedmetadata, then loadeddata</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" autoplay controls>
+ </audio>
+ <video id="v" autoplay controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var t = async_test("setting src attribute on autoplay audio should trigger loadedmetadata then loadeddata event", {timeout:5000});
+ var a = document.getElementById("a");
+ var found_loadedmetadata = false;
+ a.addEventListener("loadedmetadata", function() {
+ found_loadedmetadata = true;
+ });
+ a.addEventListener("loadeddata", function() {
+ t.step(function() {
+ assert_true(found_loadedmetadata);
+ });
+ t.done();
+ a.pause();
+ }, false);
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+}, "audio events - loadedmetadata, then loadeddata");
+
+test(function() {
+ var t = async_test("setting src attribute on autoplay video should trigger loadedmetadata then loadeddata event", {timeout:5000});
+ var v = document.getElementById("v");
+ var found_loadedmetadata = false;
+ v.addEventListener("loadedmetadata", function() {
+ found_loadedmetadata = true;
+ });
+ v.addEventListener("loadeddata", function() {
+ t.step(function() {
+ assert_true(found_loadedmetadata);
+ });
+ t.done();
+ v.pause();
+ }, false);
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+}, "video events - loadedmetadata, then loadeddata");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_order_loadstart_progress.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_order_loadstart_progress.html
new file mode 100644
index 00000000000..75e3ba772c2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_order_loadstart_progress.html
@@ -0,0 +1,52 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - loadstart, then progress</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" autoplay controls>
+ </audio>
+ <video id="v" autoplay controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var t = async_test("setting src attribute on autoplay audio should trigger loadstart then progress event", {timeout:5000});
+ var a = document.getElementById("a");
+ var found_loadstart = false;
+ a.addEventListener("loadstart", function() {
+ found_loadstart = true;
+ });
+ a.addEventListener("progress", function() {
+ t.step(function() {
+ assert_true(found_loadstart);
+ });
+ t.done();
+ a.pause();
+ }, false);
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+}, "audio events - loadstart, then progress");
+
+test(function() {
+ var t = async_test("setting src attribute on autoplay video should trigger loadstart then progress event", {timeout:5000});
+ var v = document.getElementById("v");
+ var found_loadstart = false;
+ v.addEventListener("loadstart", function() {
+ found_loadstart = true;
+ });
+ v.addEventListener("progress", function() {
+ t.step(function() {
+ assert_true(found_loadstart);
+ });
+ t.done();
+ v.pause();
+ }, false);
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+}, "video events - loadstart, then progress");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_pause.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_pause.html
new file mode 100644
index 00000000000..1f7904c3b74
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_pause.html
@@ -0,0 +1,48 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - pause</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" autoplay controls>
+ </audio>
+ <video id="v" autoplay controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var t = async_test("calling pause() on autoplay audio should trigger pause event", {timeout:5000});
+ var a = document.getElementById("a");
+ a.addEventListener("pause", function() {
+ t.step(function() {
+ assert_true(true);
+ });
+ t.done();
+ }, false);
+ a.addEventListener("play", function() {
+ a.pause(); // pause right after play
+ });
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+}, "audio events - pause");
+
+test(function() {
+ var t = async_test("calling pause() on autoplay video should trigger pause event", {timeout:5000});
+ var v = document.getElementById("v");
+ v.addEventListener("pause", function() {
+ t.step(function() {
+ assert_true(true);
+ });
+ t.done();
+ }, false);
+ v.addEventListener("play", function() {
+ v.pause(); // pause right after play
+ });
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+}, "video events - pause");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_pause_noautoplay.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_pause_noautoplay.html
new file mode 100644
index 00000000000..55482348387
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_pause_noautoplay.html
@@ -0,0 +1,40 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - pause</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" controls>
+ </audio>
+ <video id="v" controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var t = async_test("calling play() then pause() on non-autoplay audio should trigger pause event", {timeout:5000});
+ var a = document.getElementById("a");
+ a.addEventListener("pause", function() {
+ t.done();
+ }, false);
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+ a.play();
+ a.pause();
+}, "audio events - pause");
+
+test(function() {
+ var t = async_test("calling play() then pause() on non-autoplay video should trigger pause event", {timeout:5000});
+ var v = document.getElementById("v");
+ v.addEventListener("pause", function() {
+ t.done();
+ }, false);
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+ v.play();
+ v.pause();
+}, "video events - pause");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_play.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_play.html
new file mode 100644
index 00000000000..82b2ca40734
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_play.html
@@ -0,0 +1,38 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - play</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" autoplay controls>
+ </audio>
+ <video id="v" autoplay controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var t = async_test("setting src attribute on autoplay audio should trigger play event", {timeout:5000});
+ var a = document.getElementById("a");
+ a.addEventListener("play", function() {
+ t.done();
+ a.pause();
+ }, false);
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+}, "audio events - play");
+
+test(function() {
+ var t = async_test("setting src attribute on autoplay video should trigger play event", {timeout:5000});
+ var v = document.getElementById("v");
+ v.addEventListener("play", function() {
+ t.done();
+ v.pause();
+ }, false);
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+}, "video events - play");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_play_noautoplay.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_play_noautoplay.html
new file mode 100644
index 00000000000..67285a95abd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_play_noautoplay.html
@@ -0,0 +1,40 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - play</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" controls>
+ </audio>
+ <video id="v" controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var t = async_test("calling play() on audio should trigger play event", {timeout:5000});
+ var a = document.getElementById("a");
+ a.addEventListener("play", function() {
+ t.done();
+ a.pause();
+ }, false);
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+ a.play();
+}, "audio events - play");
+
+test(function() {
+ var t = async_test("calling play() on video should trigger play event", {timeout:5000});
+ var v = document.getElementById("v");
+ v.addEventListener("play", function() {
+ t.done();
+ v.pause();
+ }, false);
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+ v.play();
+}, "video events - play");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_playing.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_playing.html
new file mode 100644
index 00000000000..3741a1c9838
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_playing.html
@@ -0,0 +1,38 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - playing</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" autoplay controls>
+ </audio>
+ <video id="v" autoplay controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var t = async_test("setting src attribute on autoplay audio should trigger playing event", {timeout:5000});
+ var a = document.getElementById("a");
+ a.addEventListener("playing", function() {
+ t.done();
+ a.pause();
+ }, false);
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+}, "audio events - playing");
+
+test(function() {
+ var t = async_test("setting src attribute on autoplay video should trigger playing event", {timeout:5000});
+ var v = document.getElementById("v");
+ v.addEventListener("playing", function() {
+ t.done();
+ v.pause();
+ }, false);
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+}, "video events - playing");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_playing_noautoplay.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_playing_noautoplay.html
new file mode 100644
index 00000000000..f750085ed2b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_playing_noautoplay.html
@@ -0,0 +1,40 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - playing</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" controls>
+ </audio>
+ <video id="v" controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var t = async_test("calling play() on audio should trigger playing event", {timeout:5000});
+ var a = document.getElementById("a");
+ a.addEventListener("playing", function() {
+ t.done();
+ a.pause();
+ });
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+ a.play();
+}, "audio events - playing");
+
+test(function() {
+ var t = async_test("calling play() on video should trigger playing event", {timeout:5000});
+ var v = document.getElementById("v");
+ v.addEventListener("playing", function() {
+ t.done();
+ v.pause();
+ });
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+ v.play();
+}, "video events - playing");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_progress.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_progress.html
new file mode 100644
index 00000000000..269f824f745
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_progress.html
@@ -0,0 +1,38 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - progress</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" autoplay controls>
+ </audio>
+ <video id="v" autoplay controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var t = async_test("setting src attribute on autoplay audio should trigger progress event", {timeout:5000});
+ var a = document.getElementById("a");
+ a.addEventListener("progress", function() {
+ t.done();
+ a.pause();
+ }, false);
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+}, "audio events - progress");
+
+test(function() {
+ var t = async_test("setting src attribute on autoplay video should trigger progress event", {timeout:5000});
+ var v = document.getElementById("v");
+ v.addEventListener("progress", function() {
+ t.done();
+ v.pause();
+ }, false);
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+}, "video events - progress");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_progress_noautoplay.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_progress_noautoplay.html
new file mode 100644
index 00000000000..c594f3036dc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_progress_noautoplay.html
@@ -0,0 +1,36 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - progress</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" controls>
+ </audio>
+ <video id="v" controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var t = async_test("setting src attribute on non-autoplay audio should trigger progress event", {timeout:5000});
+ var a = document.getElementById("a");
+ a.addEventListener("progress", function() {
+ t.done();
+ }, false);
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+}, "audio events - progress");
+
+test(function() {
+ var t = async_test("setting src attribute on non-autoplay video should trigger progress event", {timeout:5000});
+ var v = document.getElementById("v");
+ v.addEventListener("progress", function() {
+ t.done();
+ }, false);
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+}, "video events - progress");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_timeupdate.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_timeupdate.html
new file mode 100644
index 00000000000..cc0a17fe2e5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_timeupdate.html
@@ -0,0 +1,34 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - timeupdate</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" autoplay controls>
+ </audio>
+ <video id="v" autoplay controls>
+ </video>
+ <div id="log"></div>
+ <script>
+var ta = async_test("setting src attribute on a sufficiently long autoplay audio should trigger timeupdate event", {timeout:5000});
+var a = document.getElementById("a");
+a.addEventListener("timeupdate", function() {
+ ta.done();
+ a.pause();
+}, false);
+a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+
+var tv = async_test("setting src attribute on a sufficiently long autoplay video should trigger timeupdate event", {timeout:5000});
+var v = document.getElementById("v");
+v.addEventListener("timeupdate", function() {
+ tv.done();
+ v.pause();
+}, false);
+v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_timeupdate_noautoplay.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_timeupdate_noautoplay.html
new file mode 100644
index 00000000000..feb4b856883
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_timeupdate_noautoplay.html
@@ -0,0 +1,40 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - timeupdate</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" controls>
+ </audio>
+ <video id="v" controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var t = async_test("calling play() on a sufficiently long audio should trigger timeupdate event", {timeout:5000});
+ var a = document.getElementById("a");
+ a.addEventListener("timeupdate", function() {
+ t.done();
+ a.pause();
+ }, false);
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+ a.play();
+}, "audio events - timeupdate");
+
+test(function() {
+ var t = async_test("calling play() on a sufficiently long video should trigger timeupdate event", {timeout:5000});
+ var v = document.getElementById("v");
+ v.addEventListener("timeupdate", function() {
+ t.done();
+ v.pause();
+ }, false);
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+ v.play();
+}, "video events - timeupdate");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_volumechange.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_volumechange.html
new file mode 100644
index 00000000000..3481947e87b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/event_volumechange.html
@@ -0,0 +1,72 @@
+<!doctype html>
+<title>volumechange event</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+function volumechange_test(tagName) {
+ async_test(function(t) {
+ var e = document.createElement(tagName);
+ assert_equals(e.volume, 1);
+ e.volume = 0.5;
+ assert_equals(e.volume, 0.5);
+ e.onvolumechange = t.step_func(function() {
+ assert_equals(e.volume, 0.5);
+ e.volume = 1;
+ assert_equals(e.volume, 1);
+ e.onvolumechange = t.step_func(function() {
+ assert_equals(e.volume, 1);
+ t.done();
+ });
+ });
+ }, "setting " + tagName + ".volume fires volumechange");
+
+ async_test(function(t) {
+ var e = document.createElement(tagName);
+ assert_false(e.muted);
+ e.muted = true;
+ assert_true(e.muted);
+ e.onvolumechange = t.step_func(function() {
+ assert_true(e.muted);
+ e.muted = false;
+ assert_false(e.muted);
+ e.onvolumechange = t.step_func(function() {
+ assert_false(e.muted);
+ t.done();
+ });
+ });
+ }, "setting " + tagName + ".muted fires volumechange");
+
+ async_test(function(t) {
+ var e = document.createElement(tagName);
+ e.volume = e.volume;
+ e.muted = e.muted;
+ e.onvolumechange = t.step_func(function() {
+ assert_unreached();
+ });
+ var e2 = document.createElement(tagName);
+ e2.muted = !e2.muted;
+ e2.onvolumechange = t.step_func(function() {
+ t.done();
+ });
+ }, "setting " + tagName + ".volume/muted to the same value does not fire volumechange");
+
+ async_test(function(t) {
+ var e = document.createElement(tagName);
+ e.muted = !e.muted;
+ e.volume = 1 - e.volume;
+ e.muted = !e.muted;
+ e.volume = 1 - e.volume;
+ var volumechange_count = 0;
+ e.onvolumechange = t.step_func(function() {
+ volumechange_count++;
+ if (volumechange_count == 4) {
+ t.done();
+ }
+ });
+ }, "setting " + tagName + ".volume/muted repeatedly fires volumechange repeatedly");
+}
+
+volumechange_test("audio");
+volumechange_test("video");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/historical.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/historical.html
new file mode 100644
index 00000000000..408bb21b7a9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/historical.html
@@ -0,0 +1,46 @@
+<!doctype html>
+<title>Historical media element features should not be supported</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+function t(property, tagName) {
+ var tagNames = tagName ? [tagName] : ['audio', 'video'];
+ tagNames.forEach(function(tagName) {
+ test(function() {
+ assert_false(property in document.createElement(tagName));
+ }, tagName + '.' + property + ' should not be supported');
+ });
+}
+
+t('bufferingRate'); // added in r678, removed in r2872.
+t('start'); // added in r692, removed in r2401.
+t('end'); // added in r692, removed in r2401.
+t('loopStart'); // added in r692, removed in r2401.
+t('loopEnd'); // added in r692, removed in r2401.
+t('loopCount'); // added in r692, replaced with playCount in r1105.
+t('currentLoop'); // added in r692, removed in r2401.
+t('addCuePoint'); // added in r721, replaced with addCueRange in r1106.
+t('removeCuePoint'); // added in r721, replaced with removeCueRanges in r1106.
+t('media', 'source'); // added in r724, removed in r8472.
+t('playCount'); // added in r1105, removed in r2401.
+t('addCueRange'); // added in r1106, removed in r5070.
+t('removeCueRanges'); // added in r1106, removed in r5070.
+t('pixelratio', 'source'); // added in r1629, removed in r2493.
+t('bufferedBytes'); // added in r1630, removed in r2405.
+t('totalBytes'); // added in r1630, removed in r2405.
+t('bufferingThrottled'); // added in r1632, removed in r2872.
+t('autobuffer'); // added in r2855, replaced with preload in r4811.
+t('startTime'); // added in r3035, replaced with initialTime in r5310.
+t('startOffsetTime'); // added in r5310, replaced with startDate in r7045.
+t('initialTime'); // added in r5310, removed in r7046.
+t('audio', 'video'); // added in r5636, replaced with muted in r5991.
+t('startDate'); // added in r7045, replaced with getStartDate() in r8113.
+
+// TextTrackCue constructor: added in r5723, removed in r7742.
+test(function() {
+ assert_throws(new TypeError(), function() {
+ new TextTrackCue(0, 0, '');
+ });
+}, 'TextTrackCue constructor should not be supported');
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLMediaElement/addTextTrack.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLMediaElement/addTextTrack.html
new file mode 100644
index 00000000000..2a76b0a66ba
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLMediaElement/addTextTrack.html
@@ -0,0 +1,116 @@
+<!doctype html>
+<title>HTMLMediaElement.addTextTrack</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+var video = document.createElement('video');
+test(function(){
+ assert_throws(new TypeError(), function(){
+ video.addTextTrack('foo');
+ });
+ assert_throws(new TypeError(), function(){
+ video.addTextTrack(undefined);
+ });
+ assert_throws(new TypeError(), function(){
+ video.addTextTrack(null);
+ });
+}, document.title + ' bogus first arg');
+
+test(function(){
+ assert_throws(new TypeError(), function(){
+ video.addTextTrack('SUBTITLES');
+ });
+}, document.title + ' uppercase first arg');
+
+test(function(){
+ var t = video.addTextTrack('subtitles');
+ assert_equals(t.kind, 'subtitles');
+ assert_equals(t.label, '');
+ assert_equals(t.language, '');
+ assert_equals(t.mode, 'hidden');
+ assert_true(t.cues instanceof TextTrackCueList);
+ assert_equals(t.cues.length, 0);
+}, document.title + ' subtitles first arg');
+
+test(function(){
+ var t = video.addTextTrack('captions');
+ assert_equals(t.kind, 'captions');
+ assert_equals(t.label, '');
+ assert_equals(t.language, '');
+ assert_equals(t.mode, 'hidden');
+ assert_true(t.cues instanceof TextTrackCueList);
+ assert_equals(t.cues.length, 0);
+}, document.title + ' captions first arg');
+
+test(function(){
+ var t = video.addTextTrack('descriptions');
+ assert_equals(t.kind, 'descriptions');
+ assert_equals(t.label, '');
+ assert_equals(t.language, '');
+ assert_equals(t.mode, 'hidden');
+ assert_true(t.cues instanceof TextTrackCueList);
+ assert_equals(t.cues.length, 0);
+}, document.title + ' descriptions first arg');
+
+test(function(){
+ var t = video.addTextTrack('chapters');
+ assert_equals(t.kind, 'chapters');
+ assert_equals(t.label, '');
+ assert_equals(t.language, '');
+ assert_equals(t.mode, 'hidden');
+ assert_true(t.cues instanceof TextTrackCueList);
+ assert_equals(t.cues.length, 0);
+}, document.title + ' chapters first arg');
+
+test(function(){
+ var t = video.addTextTrack('metadata');
+ assert_equals(t.kind, 'metadata');
+ assert_equals(t.label, '');
+ assert_equals(t.language, '');
+ assert_equals(t.mode, 'hidden');
+ assert_true(t.cues instanceof TextTrackCueList);
+ assert_equals(t.cues.length, 0);
+}, document.title + ' metadata first arg');
+
+test(function(){
+ var t = video.addTextTrack('subtitles', undefined, undefined);
+ assert_equals(t.kind, 'subtitles');
+ assert_equals(t.label, '');
+ assert_equals(t.language, '');
+ assert_equals(t.mode, 'hidden');
+ assert_true(t.cues instanceof TextTrackCueList);
+ assert_equals(t.cues.length, 0);
+}, document.title + ' undefined second and third arg');
+
+test(function(){
+ var t = video.addTextTrack('subtitles', null, null);
+ assert_equals(t.kind, 'subtitles');
+ assert_equals(t.label, 'null');
+ assert_equals(t.language, 'null');
+ assert_equals(t.mode, 'hidden');
+ assert_true(t.cues instanceof TextTrackCueList);
+ assert_equals(t.cues.length, 0);
+}, document.title + ' null second and third arg');
+
+test(function(){
+ var t = video.addTextTrack('subtitles', 'foo', 'bar');
+ assert_equals(t.kind, 'subtitles');
+ assert_equals(t.label, 'foo');
+ assert_equals(t.language, 'bar');
+ assert_equals(t.mode, 'hidden');
+ assert_true(t.cues instanceof TextTrackCueList);
+ assert_equals(t.cues.length, 0);
+}, document.title + ' foo and bar second and third arg');
+
+test(function(){
+ var t = video.addTextTrack('subtitles', 'foo');
+ assert_equals(t.kind, 'subtitles');
+ assert_equals(t.label, 'foo');
+ assert_equals(t.language, '');
+ assert_equals(t.mode, 'hidden');
+ assert_true(t.cues instanceof TextTrackCueList);
+ assert_equals(t.cues.length, 0);
+}, document.title + ' foo second arg, third arg omitted');
+
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLMediaElement/textTracks.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLMediaElement/textTracks.html
new file mode 100644
index 00000000000..0f183b7e151
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLMediaElement/textTracks.html
@@ -0,0 +1,13 @@
+<!doctype html>
+<title>HTMLMediaElement.textTracks</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+var video = document.createElement('video');
+test(function(){
+ assert_equals(video.textTracks, video.textTracks);
+ assert_equals(video.textTracks.length, 0);
+});
+
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/default.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/default.html
new file mode 100644
index 00000000000..05fd0f7f7dc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/default.html
@@ -0,0 +1,55 @@
+<!doctype html>
+<title>HTMLTrackElement.default</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function(){
+ var track = document.createElement('track');
+ assert_equals(track['default'], false);
+ assert_equals(track.getAttribute('default'), null);
+}, document.title + ' missing value');
+
+test(function(){
+ var track = document.createElement('track');
+ track.setAttribute('default', '');
+ assert_equals(track['default'], true);
+ assert_equals(track.getAttribute('default'), '');
+}, document.title + ' empty string content attribute');
+
+test(function(){
+ var track = document.createElement('track');
+ track['default'] = '';
+ assert_equals(track['default'], false);
+ assert_equals(track.getAttribute('default'), null);
+}, document.title + ' empty string IDL attribute');
+
+test(function(){
+ var track = document.createElement('track');
+ track.setAttribute('default', 'foo');
+ assert_equals(track['default'], true);
+ assert_equals(track.getAttribute('default'), 'foo');
+}, document.title + ' foo in content attribute');
+
+test(function(){
+ var track = document.createElement('track');
+ track['default'] = 'foo';
+ assert_equals(track['default'], true);
+ assert_equals(track.getAttribute('default'), '');
+}, document.title + ' foo in IDL attribute');
+
+test(function(){
+ var track = document.createElement('track');
+ track['default'] = true;
+ assert_equals(track['default'], true);
+ assert_equals(track.getAttribute('default'), '');
+}, document.title + ' true in IDL attribute');
+
+test(function(){
+ var track = document.createElement('track');
+ track.setAttribute('default', '');
+ track['default'] = false;
+ assert_equals(track['default'], false);
+ assert_equals(track.getAttribute('default'), null);
+}, document.title + ' false in IDL attribute');
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/kind.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/kind.html
new file mode 100644
index 00000000000..4f1ba31e160
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/kind.html
@@ -0,0 +1,146 @@
+<!doctype html>
+<title>HTMLTrackElement.kind</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function(){
+ var track = document.createElement('track');
+ assert_equals(track.kind, 'subtitles');
+ assert_equals(track.getAttribute('kind'), null);
+}, document.title + ' missing value');
+
+test(function(){
+ var track = document.createElement('track');
+ track.setAttribute('kind', 'invalid');
+ assert_equals(track.kind, 'subtitles');
+ assert_equals(track.getAttribute('kind'), 'invalid');
+}, document.title + ' invalid value in content attribute');
+
+test(function(){
+ var track = document.createElement('track');
+ track.setAttribute('kind', 'CAPTIONS');
+ assert_equals(track.kind, 'captions');
+ assert_equals(track.getAttribute('kind'), 'CAPTIONS');
+}, document.title + ' content attribute uppercase');
+
+test(function(){
+ var track = document.createElement('track');
+ track.setAttribute('kind', 'CAPT\u0130ONS');
+ assert_equals(track.kind, 'subtitles');
+ assert_equals(track.getAttribute('kind'), 'CAPT\u0130ONS');
+}, document.title + ' content attribute with uppercase turkish I (with dot)');
+
+test(function(){
+ var track = document.createElement('track');
+ track.setAttribute('kind', 'capt\u0131ons');
+ assert_equals(track.kind, 'subtitles');
+ assert_equals(track.getAttribute('kind'), 'capt\u0131ons');
+}, document.title + ' content attribute with lowercase turkish i (dotless)');
+
+test(function(){
+ var track = document.createElement('track');
+ track.setAttribute('kind', 'subtitles');
+ assert_equals(track.kind, 'subtitles');
+ assert_equals(track.getAttribute('kind'), 'subtitles');
+}, document.title + ' content attribute "subtitles"');
+
+test(function(){
+ var track = document.createElement('track');
+ track.setAttribute('kind', 'captions');
+ assert_equals(track.kind, 'captions');
+ assert_equals(track.getAttribute('kind'), 'captions');
+}, document.title + ' content attribute "captions"');
+
+test(function(){
+ var track = document.createElement('track');
+ track.setAttribute('kind', 'descriptions');
+ assert_equals(track.kind, 'descriptions');
+ assert_equals(track.getAttribute('kind'), 'descriptions');
+}, document.title + ' content attribute "descriptions"');
+
+test(function(){
+ var track = document.createElement('track');
+ track.setAttribute('kind', 'chapters');
+ assert_equals(track.kind, 'chapters');
+ assert_equals(track.getAttribute('kind'), 'chapters');
+}, document.title + ' content attribute "chapters"');
+
+test(function(){
+ var track = document.createElement('track');
+ track.setAttribute('kind', 'metadata');
+ assert_equals(track.kind, 'metadata');
+ assert_equals(track.getAttribute('kind'), 'metadata');
+}, document.title + ' content attribute "metadata"');
+
+test(function(){
+ var track = document.createElement('track');
+ track.setAttribute('kind', 'captions\u0000');
+ assert_equals(track.kind, 'subtitles');
+ assert_equals(track.getAttribute('kind'), 'captions\u0000');
+}, document.title + ' content attribute "captions\\u0000"');
+
+test(function(){
+ var track = document.createElement('track');
+ track.kind = 'subtitles';
+ assert_equals(track.getAttribute('kind'), 'subtitles');
+ assert_equals(track.kind, 'subtitles');
+}, document.title + ' setting IDL attribute to "subtitles"');
+
+test(function(){
+ var track = document.createElement('track');
+ track.kind = 'captions';
+ assert_equals(track.getAttribute('kind'), 'captions');
+ assert_equals(track.kind, 'captions');
+}, document.title + ' setting IDL attribute to "captions"');
+
+test(function(){
+ var track = document.createElement('track');
+ track.kind = 'descriptions';
+ assert_equals(track.getAttribute('kind'), 'descriptions');
+ assert_equals(track.kind, 'descriptions');
+}, document.title + ' setting IDL attribute to "descriptions"');
+
+test(function(){
+ var track = document.createElement('track');
+ track.kind = 'chapters';
+ assert_equals(track.getAttribute('kind'), 'chapters');
+ assert_equals(track.kind, 'chapters');
+}, document.title + ' setting IDL attribute to "chapters"');
+
+test(function(){
+ var track = document.createElement('track');
+ track.kind = 'metadata';
+ assert_equals(track.getAttribute('kind'), 'metadata');
+ assert_equals(track.kind, 'metadata');
+}, document.title + ' setting IDL attribute to "metadata"');
+
+test(function(){
+ var track = document.createElement('track');
+ track.kind = 'CAPTIONS';
+ assert_equals(track.getAttribute('kind'), 'CAPTIONS');
+ assert_equals(track.kind, 'captions');
+}, document.title + ' setting IDL attribute to "CAPTIONS"');
+
+test(function(){
+ var track = document.createElement('track');
+ track.kind = 'CAPT\u0130ONS';
+ assert_equals(track.getAttribute('kind'), 'CAPT\u0130ONS');
+ assert_equals(track.kind, 'subtitles');
+}, document.title + ' setting IDL attribute with uppercase turkish I (with dot)');
+
+test(function(){
+ var track = document.createElement('track');
+ track.kind = 'capt\u0131ons';
+ assert_equals(track.getAttribute('kind'), 'capt\u0131ons');
+ assert_equals(track.kind, 'subtitles');
+}, document.title + ' setting IDL attribute with lowercase turkish I (dotless)');
+
+test(function(){
+ var track = document.createElement('track');
+ track.kind = 'captions\u0000';
+ assert_equals(track.getAttribute('kind'), 'captions\u0000');
+ assert_equals(track.kind, 'subtitles');
+}, document.title + ' setting IDL attribute with \\u0000');
+
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/label.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/label.html
new file mode 100644
index 00000000000..b2360315cfd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/label.html
@@ -0,0 +1,83 @@
+<!doctype html>
+<title>HTMLTrackElement.label</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function(){
+ var track = document.createElement('track');
+ assert_equals(track.label, '');
+ assert_equals(track.getAttribute('label'), null);
+}, document.title + ' missing value');
+
+test(function(){
+ var track = document.createElement('track');
+ track.setAttribute('label', '');
+ assert_equals(track.label, '');
+ assert_equals(track.getAttribute('label'), '');
+}, document.title + ' empty string content attribute');
+
+test(function(){
+ var track = document.createElement('track');
+ track.label = '';
+ assert_equals(track.label, '');
+ assert_equals(track.getAttribute('label'), '');
+}, document.title + ' empty string IDL attribute');
+
+test(function(){
+ var track = document.createElement('track');
+ track.setAttribute('label', 'foo');
+ assert_equals(track.label, 'foo');
+ assert_equals(track.getAttribute('label'), 'foo');
+}, document.title + ' lowercase content attribute');
+
+test(function(){
+ var track = document.createElement('track');
+ track.setAttribute('label', 'FOO');
+ assert_equals(track.label, 'FOO');
+ assert_equals(track.getAttribute('label'), 'FOO');
+}, document.title + ' uppercase content attribute');
+
+test(function(){
+ var track = document.createElement('track');
+ track.setAttribute('label', '\u0000');
+ assert_equals(track.label, '\u0000');
+ assert_equals(track.getAttribute('label'), '\u0000');
+}, document.title + '\\u0000 in content attribute');
+
+test(function(){
+ var track = document.createElement('track');
+ track.label = 'foo';
+ assert_equals(track.label, 'foo');
+ assert_equals(track.getAttribute('label'), 'foo');
+}, document.title + ' lowercase IDL attribute');
+
+test(function(){
+ var track = document.createElement('track');
+ track.label = 'FOO';
+ assert_equals(track.label, 'FOO');
+ assert_equals(track.getAttribute('label'), 'FOO');
+}, document.title + ' uppercase IDL attribute');
+
+test(function(){
+ var track = document.createElement('track');
+ track.setAttribute('label', ' foo \n');
+ assert_equals(track.label, ' foo \n');
+ assert_equals(track.getAttribute('label'), ' foo \n');
+}, document.title + ' whitespace in content attribute');
+
+test(function(){
+ var track = document.createElement('track');
+ track.label = ' foo \n';
+ assert_equals(track.label, ' foo \n');
+ assert_equals(track.getAttribute('label'), ' foo \n');
+}, document.title + ' whitespace in IDL attribute');
+
+test(function(){
+ var track = document.createElement('track');
+ track.label = '\u0000';
+ assert_equals(track.label, '\u0000');
+ assert_equals(track.getAttribute('label'), '\u0000');
+}, document.title + ' \\u0000 in IDL attribute');
+
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/readyState.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/readyState.html
new file mode 100644
index 00000000000..e18f21934de
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/readyState.html
@@ -0,0 +1,11 @@
+<!doctype html>
+<title>HTMLTrackElement.readyState</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function(){
+ var track = document.createElement('track');
+ assert_equals(track.readyState, 0);
+}, document.title + ' default value');
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/src.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/src.html
new file mode 100644
index 00000000000..cc703861a41
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/src.html
@@ -0,0 +1,77 @@
+<!doctype html>
+<title>HTMLTrackElement.src</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function(){
+ var track = document.createElement('track');
+ assert_equals(track.src, '');
+ assert_equals(track.getAttribute('src'), null);
+}, document.title + ' missing value');
+
+test(function(){
+ var track = document.createElement('track');
+ track.setAttribute('src', '');
+ assert_equals(track.src, '');
+ assert_equals(track.getAttribute('src'), '');
+}, document.title + ' empty string in content attribute');
+
+test(function(){
+ var track = document.createElement('track');
+ track.src = '';
+ assert_equals(track.src, '');
+ assert_equals(track.getAttribute('src'), '');
+}, document.title + ' empty string in IDL attribute');
+
+test(function(){
+ var track = document.createElement('track');
+ track.setAttribute('src', 'http://foo bar');
+ assert_equals(track.src, 'http://foo bar');
+ assert_equals(track.getAttribute('src'), 'http://foo bar');
+}, document.title + ' unresolvable value in content attribute');
+
+test(function(){
+ var track = document.createElement('track');
+ track.setAttribute('src', 'test');
+ var link = document.createElement('a');
+ link.setAttribute('href', 'test');
+ assert_equals(track.src, link.href);
+ assert_equals(track.getAttribute('src'), 'test');
+}, document.title + ' resolvable value in content attribute');
+
+test(function(){
+ var track = document.createElement('track');
+ track.setAttribute('src', '\u0000');
+ var link = document.createElement('a');
+ link.setAttribute('href', '%00');
+ assert_equals(track.src, link.href);
+ assert_equals(track.getAttribute('src'), '\u0000');
+}, document.title + ' \\u0000 in content attribute');
+
+test(function(){
+ var track = document.createElement('track');
+ track.src = 'http://foo bar';
+ assert_equals(track.src, 'http://foo bar');
+ assert_equals(track.getAttribute('src'), 'http://foo bar');
+}, document.title + ' assigning unresolvable value to IDL attribute');
+
+test(function(){
+ var track = document.createElement('track');
+ track.src = 'test';
+ var link = document.createElement('a');
+ link.setAttribute('href', 'test');
+ assert_equals(track.src, link.href);
+ assert_equals(track.getAttribute('src'), 'test');
+}, document.title + ' assigning resolvable value to IDL attribute');
+
+test(function(){
+ var track = document.createElement('track');
+ track.src = '\u0000';
+ var link = document.createElement('a');
+ link.setAttribute('href', '%00');
+ assert_equals(track.src, link.href);
+ assert_equals(track.getAttribute('src'), '\u0000');
+}, document.title + ' assigning \\u0000 to IDL attribute');
+
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/srclang.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/srclang.html
new file mode 100644
index 00000000000..b5071e0c36c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/srclang.html
@@ -0,0 +1,82 @@
+<!doctype html>
+<title>HTMLTrackElement.srclang</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function(){
+ var track = document.createElement('track');
+ assert_equals(track.srclang, '');
+ assert_equals(track.getAttribute('srclang'), null);
+}, document.title + ' missing value');
+
+test(function(){
+ var track = document.createElement('track');
+ track.setAttribute('srclang', '');
+ assert_equals(track.srclang, '');
+ assert_equals(track.getAttribute('srclang'), '');
+}, document.title + ' empty string content attribute');
+
+test(function(){
+ var track = document.createElement('track');
+ track.srclang = '';
+ assert_equals(track.srclang, '');
+ assert_equals(track.getAttribute('srclang'), '');
+}, document.title + ' empty string IDL attribute');
+
+test(function(){
+ var track = document.createElement('track');
+ track.setAttribute('srclang', 'foo');
+ assert_equals(track.srclang, 'foo');
+ assert_equals(track.getAttribute('srclang'), 'foo');
+}, document.title + ' lowercase content attribute');
+
+test(function(){
+ var track = document.createElement('track');
+ track.setAttribute('srclang', 'FOO');
+ assert_equals(track.srclang, 'FOO');
+ assert_equals(track.getAttribute('srclang'), 'FOO');
+}, document.title + ' uppercase content attribute');
+
+test(function(){
+ var track = document.createElement('track');
+ track.setAttribute('srclang', '\u0000');
+ assert_equals(track.srclang, '\u0000');
+ assert_equals(track.getAttribute('srclang'), '\u0000');
+}, document.title + ' \\u0000 content attribute');
+
+test(function(){
+ var track = document.createElement('track');
+ track.srclang = 'foo';
+ assert_equals(track.srclang, 'foo');
+ assert_equals(track.getAttribute('srclang'), 'foo');
+}, document.title + ' lowercase IDL attribute');
+
+test(function(){
+ var track = document.createElement('track');
+ track.srclang = 'FOO';
+ assert_equals(track.srclang, 'FOO');
+ assert_equals(track.getAttribute('srclang'), 'FOO');
+}, document.title + ' uppercase IDL attribute');
+
+test(function(){
+ var track = document.createElement('track');
+ track.setAttribute('srclang', ' foo \n');
+ assert_equals(track.srclang, ' foo \n');
+ assert_equals(track.getAttribute('srclang'), ' foo \n');
+}, document.title + ' whitespace in content attribute');
+
+test(function(){
+ var track = document.createElement('track');
+ track.srclang = ' foo \n';
+ assert_equals(track.srclang, ' foo \n');
+ assert_equals(track.getAttribute('srclang'), ' foo \n');
+}, document.title + ' whitespace in IDL attribute');
+
+test(function(){
+ var track = document.createElement('track');
+ track.srclang = '\u0000';
+ assert_equals(track.srclang, '\u0000');
+ assert_equals(track.getAttribute('srclang'), '\u0000');
+}, document.title + ' \\u0000 in IDL attribute');
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/track.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/track.html
new file mode 100644
index 00000000000..1de0a880467
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/track.html
@@ -0,0 +1,12 @@
+<!doctype html>
+<title>HTMLTrackElement.track</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function(){
+ var track = document.createElement('track');
+ assert_equals(track.track, track.track, 'same object should be returned');
+ assert_true(track.track instanceof TextTrack, 'returned object should be a TextTrack');
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/activeCues.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/activeCues.html
new file mode 100644
index 00000000000..689ec12be0c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/activeCues.html
@@ -0,0 +1,104 @@
+<!doctype html>
+<title>TextTrack.activeCues</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=/common/media.js></script>
+<div id=log></div>
+<script>
+setup(function(){
+ window.video = document.createElement('video');
+ window.t1 = video.addTextTrack('subtitles');
+ window.track = document.createElement('track');
+ track['default'] = true;
+ video.appendChild(track);
+ window.t2 = track.track;
+ t2.mode = 'showing';
+ window.t1_cues = t1.activeCues;
+ window.t2_cues = t2.activeCues;
+ document.body.appendChild(video);
+ if (!t1)
+ throw new Error('t1 was undefined')
+}, {timeout:25000});
+function smoke_test() {
+ assert_true('HTMLTrackElement' in window, 'track not supported');
+}
+
+test(function(){
+ smoke_test();
+ assert_equals(t1.activeCues, t1_cues, 't1.activeCues should return same object');
+ assert_equals(t2.activeCues, t2_cues, 't2.activeCues should return same object');
+ assert_not_equals(t1.activeCues, t2.activeCues, 't1.activeCues and t2.activeCues should be different objects');
+ assert_not_equals(t1.activeCues, null, 't1.activeCues should not be null');
+ assert_not_equals(t2.activeCues, null, 't2.activeCues should not be null');
+ assert_equals(t1.activeCues.length, 0, 't1.activeCues should have length 0');
+ assert_equals(t2.activeCues.length, 0, 't2.activeCues should have length 0');
+}, document.title+', empty list');
+test(function(){
+ smoke_test();
+ var c = new VTTCue(0, 1, "text");
+ t1.addCue(c);
+ assert_equals(t1.activeCues, t1_cues, "t1.activeCues should return same object");
+ assert_equals(t1.activeCues.length, 0, "t1.activeCues.length");
+ var c2 = new VTTCue(1, 2, "text2");
+ t1.addCue(c2);
+ assert_equals(t1.activeCues, t1_cues, "t1.activeCues should return the same object after adding a second cue");
+ assert_equals(t1.activeCues.length, 0, "t1.activeCues.length after adding a second cue");
+}, document.title+', after addCue()');
+test(function(){
+ smoke_test();
+ t1.mode = 'showing';
+ assert_equals(t1.activeCues, t1_cues, "t1.activeCues should return the same object after setting mode to showing");
+ t1.mode = 'hidden';
+ assert_equals(t1.activeCues, t1_cues, "t1.activeCues should return the same object after setting mode to hidden");
+ t1.mode = 'disabled';
+ assert_equals(t1.activeCues, null, "t1.activeCues should be null when mode is disabled");
+ assert_equals(t1_cues.length, 0, "t1_cues should still be intact after setting mode to disabled");
+}, document.title+', different modes');
+
+// ok now let's load in a video
+var test1 = async_test(document.title+', video loading', {timeout:20000});
+var test2 = async_test(document.title+', video playing', {timeout:20000});
+var test3 = async_test(document.title+', adding cue during playback', {timeout:20000});
+test1.step(smoke_test);
+test2.step(smoke_test);
+test3.step(smoke_test);
+test1.step(function(){
+ t1.mode = 'showing';
+ video.onloadeddata = test1.step_func(function(e) {
+ video.onplaying = test2.step_func(function(e) {
+ try {
+ assert_equals(t1.activeCues, t1_cues, "t1.activeCues should return the same object after playing a video");
+ assert_equals(t1.activeCues.length, 1, "t1.activeCues.length after the video has started playing");
+ } catch(ex) {
+ test2.step(function() { throw ex; });
+ test3.step(function() { assert_unreached(); });
+ return;
+ }
+ test3.step(function(){
+ var c3 = new VTTCue(0, 2, "text3");
+ t1.addCue(c3);
+ assert_equals(t1.activeCues.length, 1, "t1.activeCues.length after adding a cue in the same script");
+ setTimeout(test3.step_func(function(){
+ assert_equals(t1.activeCues.length, 2, "t1.activeCues.length after the event loop has spun");
+ test3.done();
+ }, 0));
+ });
+ test2.done();
+ });
+ try {
+ assert_equals(t1.activeCues, t1_cues, "t1.activeCues should return the same object after loading a video");
+ assert_equals(t2.activeCues, t2_cues, "t2.activeCues should return the same object after loading a video");
+ assert_equals(t1.activeCues.length, 0, "t1.activeCues.length before the video has started playing");
+ assert_equals(t2.activeCues.length, 0, "t1.activeCues.length before the video has started playing");
+ } catch(ex) {
+ test1.step(function() { throw ex; });
+ test2.step(function() { assert_unreached(); });
+ test3.step(function() { assert_unreached(); });
+ return;
+ }
+ video.play();
+ test1.done();
+ });
+ video.src = getVideoURI("/media/movie_5");
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/addCue.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/addCue.html
new file mode 100644
index 00000000000..2679413348c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/addCue.html
@@ -0,0 +1,68 @@
+<!doctype html>
+<title>TextTrack.addCue()</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+setup(function(){
+ window.video = document.createElement('video');
+ document.body.appendChild(video);
+}, {timeout:5000});
+test(function() {
+ var t1 = video.addTextTrack('subtitles');
+ var t2 = video.addTextTrack('subtitles');
+ var c1 = new VTTCue(0, 1, 'text1');
+ t1.addCue(c1);
+ t2.addCue(c1);
+ assert_equals(c1.track, t2);
+}, document.title+', adding a cue to two different tracks');
+test(function() {
+ var t1 = video.addTextTrack('subtitles');
+ var c1 = new VTTCue(0, 1, 'text1');
+ t1.addCue(c1);
+ assert_equals(c1.track, t1);
+ t1.addCue(c1);
+ assert_equals(c1.track, t1);
+}, document.title+', adding a cue to a track twice');
+test(function() {
+ var t1 = video.addTextTrack('subtitles');
+ var t2 = video.addTextTrack('subtitles');
+ var c1 = new VTTCue(0, 1, 'text1');
+ t1.addCue(c1);
+ assert_equals(c1.track, t1);
+ t1.removeCue(c1);
+ assert_equals(c1.track, null);
+ t2.addCue(c1);
+ assert_equals(c1.track, t2);
+}, document.title+', adding a removed cue to a different track');
+test(function() {
+ var t1 = video.addTextTrack('subtitles');
+ var c1 = new VTTCue(0, 1, 'text1');
+ t1.addCue(c1);
+ assert_equals(t1.cues.length, 1, 't1.cues.length after first addition');
+ t1.removeCue(c1);
+ assert_equals(t1.cues.length, 0, 't1.cues.length after removal');
+ t1.addCue(c1);
+ assert_equals(t1.cues.length, 1, 't1.cues.length after second addition');
+}, document.title+', adding an associated but removed cue to the same track');
+
+var t = async_test(document.title+', adding a cue associated with a track element to other track');
+t.step(function(){
+ var t1 = video.addTextTrack('subtitles');
+ var track = document.createElement('track');
+ track.onload = t.step_func(function(){
+ var cue = track.track.cues[0];
+ track.track.removeCue(cue);
+ t1.addCue(cue);
+ assert_equals(cue.track, t1);
+ t.done();
+ });
+ track.onerror = t.step_func(function() {
+ assert_unreached('got error event');
+ });
+ track.src= 'data:text/vtt,'+encodeURIComponent('WEBVTT\n\n00:00:00.000 --> 00:00:01.000\ntest\n');
+ track.kind = 'subtitles';
+ track.track.mode = 'hidden';
+ video.appendChild(track);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/constants.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/constants.html
new file mode 100644
index 00000000000..3c8046cdc48
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/constants.html
@@ -0,0 +1,23 @@
+<!doctype html>
+<title>TextTrack constants</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+setup(function(){
+ window.video = document.createElement('video');
+ window.t1 = video.addTextTrack('subtitles');
+});
+test(function(){
+ assert_equals(t1.DISABLED, undefined, "t1.DISABLED");
+ assert_equals(t1.HIDDEN, undefined, "t1.HIDDEN");
+ assert_equals(t1.SHOWING, undefined, "t1.SHOWING");
+ assert_equals(TextTrack.prototype.DISABLED, undefined, "TextTrack.prototype.DISABLED");
+ assert_equals(TextTrack.prototype.HIDDEN, undefined, "TextTrack.prototype.HIDDEN");
+ assert_equals(TextTrack.prototype.SHOWING, undefined, "TextTrack.prototype.SHOWING");
+ assert_equals(TextTrack.DISABLED, undefined, "TextTrack.DISABLED");
+ assert_equals(TextTrack.HIDDEN, undefined, "TextTrack.HIDDEN");
+ assert_equals(TextTrack.SHOWING, undefined, "TextTrack.SHOWING");
+});
+
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/cues.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/cues.html
new file mode 100644
index 00000000000..11d33b77116
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/cues.html
@@ -0,0 +1,100 @@
+<!doctype html>
+<title>TextTrack.cues</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function(){
+ var video = document.createElement('video');
+ var t1 = video.addTextTrack('subtitles');
+ assert_equals(t1.cues, t1.cues, 't1.cues should return same object');
+ assert_not_equals(t1.cues, null, 't1.cues should not be null');
+ assert_true(t1.cues instanceof TextTrackCueList, 't1.cues instanceof TextTrackCueList');
+ assert_equals(t1.cues.length, 0, 't1.cues.length');
+}, document.title+', empty list');
+
+function addCue(texttrack, start, end, text, id) {
+ var c = new VTTCue(start, end, text);
+ c.id = id;
+ texttrack.addCue(c);
+ return c;
+}
+
+test(function(){
+ var video = document.createElement('video');
+ var t1 = video.addTextTrack('subtitles');
+ var t1_cues = t1.cues;
+ var c = addCue(t1, 0, 1, 'text', 'id');
+ assert_equals(t1.cues, t1_cues, "t1.cues should return same object");
+ assert_equals(t1.cues.length, 1, "t1.cues.length");
+ var c2 = addCue(t1, 1, 2, 'text2', 'id2');
+ assert_equals(t1.cues, t1_cues, "t1.cues should return the same object after adding a second cue");
+ assert_equals(t1.cues.length, 2, "t1.cues.length after adding a second cue");
+ assert_equals(t1.cues[0].id, "id");
+ assert_equals(t1.cues[1].id, "id2");
+}, document.title+', after addCue()');
+
+test(function(){
+ var video = document.createElement('video');
+ var t1 = video.addTextTrack('subtitles');
+ var t1_cues = t1.cues;
+ var c = addCue(t1, 0, 1, 'text', 'id');
+ var c2 = addCue(t1, 1, 2, 'text2', 'id2');
+ t1.mode = 'showing';
+ assert_equals(t1.cues, t1_cues, "t1.cues should return the same object after setting mode to 'showing'");
+ t1.mode = 'hidden';
+ assert_equals(t1.cues, t1_cues, "t1.cues should return the same object after setting mode to 'hidden'");
+ t1.mode = 'disabled';
+ assert_equals(t1.cues, null, "t1.cues should be null when mode is 'disabled'");
+ assert_equals(t1_cues.length, 2, "t1_cues should still be intact after setting mode to 'disabled'");
+ assert_equals(t1_cues[0].id, "id", "t1_cues first cue should still be intact after setting mode to 'disabled'");
+ assert_equals(t1_cues[1].id, "id2", "t1_cues second cue should still be intact after setting mode to 'disabled'");
+ t1.mode = 'hidden';
+ assert_equals(t1.cues, t1_cues, "t1.cues should return the same object after setting mode to 'disabled' and then 'hidden'");
+ t1.mode = 'disabled';
+ assert_equals(t1.cues, null, "t1.cues should be null when mode is set to 'disabled' again");
+ assert_equals(t1_cues.length, 2, "t1_cues should still be intact after setting mode to 'disabled' again");
+ assert_equals(t1_cues[0].id, "id", "t1_cues first cue should still be intact after setting mode to 'disabled' again");
+ assert_equals(t1_cues[1].id, "id2", "t1_cues second cue should still be intact after setting mode to 'disabled' again");
+ t1.mode = 'showing';
+ assert_equals(t1.cues, t1_cues, "t1.cues should return the same object after setting mode to 'disabled' and then 'showing'");
+}, document.title+', different modes');
+
+test(function(){
+ var video = document.createElement('video');
+ var t1 = video.addTextTrack('subtitles');
+ var t1_cues = t1.cues;
+ var c = addCue(t1, 0, 1, 'text', 'id');
+ var c2 = addCue(t1, 1, 2, 'text2', 'id2');
+ t1.mode = 'showing';
+ t1.cues[1].startTime = 0; // this should change the text track cue order
+ assert_equals(t1.cues[0].id, 'id2');
+ assert_equals(t1.cues[1].id, 'id');
+ t1.cues[0].startTime = 0.5; // this should change it back
+ assert_equals(t1.cues[0].id, 'id');
+ assert_equals(t1.cues[1].id, 'id2');
+}, document.title+', changing order');
+
+async_test(function(){
+ var video = document.createElement('video');
+ var t1 = video.addTextTrack('subtitles');
+ var t1_cues = t1.cues;
+ t1.mode = 'showing';
+ var track = document.createElement('track');
+ track['default'] = true;
+ video.appendChild(track); // queues a task to "honor user preferences...", media element event task source
+ var t2 = track.track;
+ assert_equals(t2.cues, null, 't2.cues should be null');
+ // We need to wait until the "honor user preferences..." steps have run so we invoke play()
+ // which queues an event with the same task source.
+ video.onplay = this.step_func(function(){
+ assert_equals(t2.cues, t2.cues, 't2.cues should return same object');
+ assert_not_equals(t1.cues, t2.cues, 't1.cues and t2.cues should be different objects');
+ assert_not_equals(t2.cues, null, 't2.cues should not be null');
+ assert_true(t2.cues instanceof TextTrackCueList, 't2.cues instanceof TextTrackCueList');
+ assert_equals(t2.cues.length, 0, 't2.cues should have length 0');
+ this.done();
+ });
+ video.play(); // queues a task to fire 'play', media element event task source
+}, document.title+', default attribute');
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/kind.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/kind.html
new file mode 100644
index 00000000000..d91373d860b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/kind.html
@@ -0,0 +1,31 @@
+<!doctype html>
+<title>TextTrack.kind</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function(){
+ var video = document.createElement('video');
+ var t1 = video.addTextTrack('subtitles');
+ var t2 = video.addTextTrack('captions');
+ var t3 = video.addTextTrack('descriptions');
+ var t4 = video.addTextTrack('chapters');
+ var t5 = video.addTextTrack('metadata');
+ assert_equals(t1.kind, 'subtitles');
+ assert_equals(t2.kind, 'captions');
+ assert_equals(t3.kind, 'descriptions');
+ assert_equals(t4.kind, 'chapters');
+ assert_equals(t5.kind, 'metadata');
+}, document.title+', addTextTrack');
+test(function(){
+ var track = document.createElement('track');
+ track.setAttribute('kind', 'CAPTIONS');
+ var t = track.track;
+ assert_equals(t.kind, 'captions');
+}, document.title+', track element');
+test(function(){
+ var track = document.createElement('track');
+ track.kind = 'captions\u0000';
+ assert_equals(track.track.kind, 'subtitles');
+}, document.title+', \\u0000');
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/label.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/label.html
new file mode 100644
index 00000000000..c60e85c21ac
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/label.html
@@ -0,0 +1,29 @@
+<!doctype html>
+<title>TextTrack.label</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+setup(function(){
+ window.video = document.createElement('video');
+ window.t1 = video.addTextTrack('subtitles', 'foo');
+ window.track = document.createElement('track');
+ track.setAttribute('label', 'bar');
+ video.appendChild(track);
+ window.t2 = track.track;
+});
+test(function(){
+ assert_equals(t1.label, 'foo');
+ assert_equals(t2.label, 'bar');
+ track.label = 'baz';
+ assert_equals(t2.label, 'baz');
+ track.removeAttribute('label');
+ assert_equals(t2.label, '');
+});
+test(function(){
+ track.label = '\u0000a';
+ assert_equals(t2.label, '\u0000a');
+ track.setAttribute('label', '\u0000b', 'IDL attribute');
+ assert_equals(t2.label, '\u0000b', 'content attribute');
+}, document.title+', \\u0000');
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/language.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/language.html
new file mode 100644
index 00000000000..eda3653de04
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/language.html
@@ -0,0 +1,29 @@
+<!doctype html>
+<title>TextTrack.language</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+setup(function(){
+ window.video = document.createElement('video');
+ window.t1 = video.addTextTrack('subtitles', 'foo', 'foo');
+ window.track = document.createElement('track');
+ track.setAttribute('srclang', 'bar');
+ video.appendChild(track);
+ window.t2 = track.track;
+});
+test(function(){
+ assert_equals(t1.language, 'foo');
+ assert_equals(t2.language, 'bar');
+ track.srclang = 'baz';
+ assert_equals(t2.language, 'baz');
+ track.removeAttribute('srclang');
+ assert_equals(t2.language, '');
+});
+test(function(){
+ track.srclang = '\u0000a';
+ assert_equals(t2.language, '\u0000a', 'IDL attribute');
+ track.setAttribute('srclang', '\u0000b');
+ assert_equals(t2.language, '\u0000b', 'content attribute');
+}, document.title+', \\u0000');
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/mode.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/mode.html
new file mode 100644
index 00000000000..9f941567067
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/mode.html
@@ -0,0 +1,55 @@
+<!doctype html>
+<title>TextTrack.mode</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function(){
+ var track = document.createElement('track');
+ assert_equals(track.track.mode, 'disabled', 'initial');
+ track.track.mode = 1;
+ assert_equals(track.track.mode, 'disabled', '1');
+ track.track.mode = '';
+ assert_equals(track.track.mode, 'disabled', '""');
+ track.track.mode = null;
+ assert_equals(track.track.mode, 'disabled', 'null');
+ track.track.mode = undefined;
+ assert_equals(track.track.mode, 'disabled', 'undefined');
+ track.track.mode = 'showing';
+ assert_equals(track.track.mode, 'showing', 'showing (correct value)');
+ track.track.mode = 'DISABLED';
+ assert_equals(track.track.mode, 'showing', '"DISABLED"');
+ track.track.mode = 'd\u0130sabled'; // dotted uppercase i
+ assert_equals(track.track.mode, 'showing', '"d\u0130sabled" (dotted uppercase i)');
+ track.track.mode = 'd\u0131sabled'; // dotless lowercase i
+ assert_equals(track.track.mode, 'showing', '"d\u0131sabled" (dotless lowercase i)');
+ track.track.mode = 'disabled ';
+ assert_equals(track.track.mode, 'showing', '"disabled "');
+ track.track.mode = ' disabled';
+ assert_equals(track.track.mode, 'showing', '" disabled"');
+ track.track.mode = {};
+ assert_equals(track.track.mode, 'showing', '{}');
+ track.track.mode = 'HIDDEN';
+ assert_equals(track.track.mode, 'showing', '"HIDDEN"');
+ track.track.mode = 'h\u0130dden'; // dotted uppercase i
+ assert_equals(track.track.mode, 'showing', '"h\u0130dden" (dotted uppercase i)');
+ track.track.mode = 'h\u0131dden'; // dotless lowercase i
+ assert_equals(track.track.mode, 'showing', '"h\u0131dden" (dotless lowercase i)');
+}, document.title+', wrong value');
+test(function() {
+ var track = document.createElement('track');
+ assert_equals(track.track.mode, 'disabled', 'initial');
+ track.track.mode = 'disabled'; // no-op
+ assert_equals(track.track.mode, 'disabled', 'disabled (1)');
+ track.track.mode = 'hidden';
+ assert_equals(track.track.mode, 'hidden', 'hidden (1)');
+ track.track.mode = 'hidden'; // no-op
+ assert_equals(track.track.mode, 'hidden', 'hidden (2)');
+ track.track.mode = 'showing';
+ assert_equals(track.track.mode, 'showing', 'showing (1)');
+ track.track.mode = 'showing'; // no-op
+ assert_equals(track.track.mode, 'showing', 'showing (2)');
+ track.track.mode = {toString:function() { return 'disabled'; }};
+ assert_equals(track.track.mode, 'disabled', '{toString:...}');
+}, document.title+', correct value');
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/oncuechange.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/oncuechange.html
new file mode 100644
index 00000000000..16c76f9484a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/oncuechange.html
@@ -0,0 +1,33 @@
+<!doctype html>
+<title>TextTrack.oncuechange</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+setup(function(){
+ window.video = document.createElement('video');
+ window.t1 = video.addTextTrack('subtitles');
+ window.ev = new Event('cuechange');
+ window.ran = false;
+ window.cb = function() { ran = true; };
+});
+test(function(){
+ assert_equals(t1.oncuechange, null);
+ t1.oncuechange = cb;
+ t1.dispatchEvent(ev);
+ assert_true(ran);
+ t1.oncuechange = null;
+ ran = false;
+ t1.dispatchEvent(ev);
+ assert_false(ran);
+});
+test(function(){
+ t1.addEventListener('cuechange', cb, false);
+ t1.dispatchEvent(ev);
+ assert_true(ran);
+ t1.removeEventListener('cuechange', cb, false);
+ ran = false;
+ t1.dispatchEvent(ev);
+ assert_false(ran);
+}, 'TextTrack.addEventListener/removeEventListener');
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/removeCue.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/removeCue.html
new file mode 100644
index 00000000000..3623f44bbc0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/removeCue.html
@@ -0,0 +1,50 @@
+<!doctype html>
+<title>TextTrack.removeCue()</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+setup(function(){
+ window.video = document.createElement('video');
+ document.body.appendChild(video);
+}, {timeout:5000});
+test(function() {
+ var t1 = video.addTextTrack('subtitles');
+ var t2 = video.addTextTrack('subtitles');
+ var c1 = new VTTCue(0, 1, 'text1');
+ assert_throws("NOT_FOUND_ERR", function() {
+ t1.removeCue(c1);
+ }, 'standalone');
+ t1.addCue(c1);
+ assert_throws("NOT_FOUND_ERR", function() {
+ t2.removeCue(c1);
+ }, 'listed in t1, remove from t2');
+ t1.removeCue(c1);
+ assert_throws("NOT_FOUND_ERR", function() {
+ t1.removeCue(c1);
+ }, 'standalone, remove from t1');
+ assert_throws("NOT_FOUND_ERR", function() {
+ t2.removeCue(c1);
+ }, 'standalone, remove from t2');
+}, document.title+', two elementless tracks');
+var t = async_test(document.title+', cue from track element');
+t.step(function(){
+ var t1 = video.addTextTrack('subtitles');
+ var track = document.createElement('track');
+ track.onload = t.step_func(function(){
+ var cue = track.track.cues[0];
+ assert_throws('NOT_FOUND_ERR', function() { t1.removeCue(cue); }, 'listed in track.track, remove from t1');
+ track.track.removeCue(cue);
+ assert_throws('NOT_FOUND_ERR', function() { track.track.removeCue(cue); }, 'standalone, remove from track.track');
+ assert_throws('NOT_FOUND_ERR', function() { t1.removeCue(cue); }, 'standalone, remove from t1');
+ t.done();
+ });
+ track.onerror = t.step_func(function() {
+ assert_unreached('got error event');
+ });
+ track.src= 'data:text/vtt,'+encodeURIComponent('WEBVTT\n\n00:00:00.000 --> 00:00:01.000\ntest\n');
+ track.kind = 'subtitles';
+ track.track.mode = 'hidden';
+ video.appendChild(track);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/endTime.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/endTime.html
new file mode 100644
index 00000000000..b99a12e05aa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/endTime.html
@@ -0,0 +1,39 @@
+<!doctype html>
+<title>TextTrackCue.endTime</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+setup(function(){
+ window.video = document.createElement('video');
+ window.t1 = video.addTextTrack('subtitles');
+ document.body.appendChild(video);
+});
+test(function(){
+ var c1 = new VTTCue(-2, -1, 'text1');
+ assert_equals(c1.endTime, -1);
+ c1.endTime = c1.endTime;
+ assert_equals(c1.endTime, -1);
+ assert_throws(new TypeError(), function(){ c1.endTime = NaN; });
+ assert_throws(new TypeError(), function(){ c1.endTime = +Infinity; });
+ assert_throws(new TypeError(), function(){ c1.endTime = -Infinity; });
+}, document.title+', script-created cue');
+
+var t_parsed = async_test(document.title+', parsed cue');
+t_parsed.step(function(){
+ var t = document.createElement('track');
+ t.onload = this.step_func(function(){
+ var c = t.track.cues;
+ assert_equals(c[0].endTime, 0.001);
+ assert_equals(c[1].endTime, 3600.001);
+ this.done();
+ });
+ t.onerror = this.step_func(function() {
+ assert_unreached('got error event');
+ });
+ t.src = 'data:text/vtt,'+encodeURIComponent('WEBVTT\n\n00:00:00.000 --> 00:00:00.001\ntest'+
+ '\n\nfoobar\n01:00:00.000 --> 01:00:00.001\ntest');
+ t.track.mode = 'showing';
+ video.appendChild(t);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/id.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/id.html
new file mode 100644
index 00000000000..a88f94766f7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/id.html
@@ -0,0 +1,39 @@
+<!doctype html>
+<title>TextTrackCue.id</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+setup(function(){
+ window.video = document.createElement('video');
+ window.t1 = video.addTextTrack('subtitles');
+ document.body.appendChild(video);
+});
+test(function(){
+ var c1 = new VTTCue(0, 1, 'text1');
+ c1.id = 'id1\r\n\u0000';
+ assert_equals(c1.id, 'id1\r\n\u0000');
+ c1.id = c1.id;
+ assert_equals(c1.id, 'id1\r\n\u0000');
+ c1.id = null;
+ assert_equals(c1.id, 'null');
+}, document.title+', script-created cue');
+
+var t_parsed = async_test(document.title+', parsed cue');
+t_parsed.step(function(){
+ var t = document.createElement('track');
+ t.onload = this.step_func(function(){
+ var c = t.track.cues;
+ assert_equals(c[0].id, '');
+ assert_equals(c[1].id, 'foobar');
+ this.done();
+ });
+ t.onerror = this.step_func(function() {
+ assert_unreached('got error event');
+ });
+ t.src = 'data:text/vtt,'+encodeURIComponent('WEBVTT\n\n00:00:00.000 --> 00:00:00.001\ntest'+
+ '\n\nfoobar\n00:00:00.000 --> 00:00:00.001\ntest');
+ t.track.mode = 'showing';
+ video.appendChild(t);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/onenter.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/onenter.html
new file mode 100644
index 00000000000..17deed05305
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/onenter.html
@@ -0,0 +1,36 @@
+<!doctype html>
+<title>TextTrackCue.onenter</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+setup(function(){
+ window.c1 = new VTTCue(0, 1, 'text1');
+ window.ev = new Event('enter');
+ window.ran = false;
+ window.cb = function() { ran = true; };
+});
+test(function(){
+ assert_equals(c1.onenter, null, 'initial value');
+ c1.onenter = undefined;
+ assert_equals(c1.onenter, null, 'assigning undefined');
+ c1.onenter = cb;
+ assert_equals(c1.onenter, cb, 'assigning onenter');
+ c1.dispatchEvent(ev);
+ assert_true(ran, 'dispatching event');
+ c1.onenter = null;
+ assert_equals(c1.onenter, null, 'assigning null');
+ ran = false;
+ c1.dispatchEvent(ev);
+ assert_false(ran, 'dispatching event after nulling onenter');
+});
+test(function(){
+ c1.addEventListener('enter', cb, false);
+ c1.dispatchEvent(ev);
+ assert_true(ran);
+ c1.removeEventListener('enter', cb, false);
+ ran = false;
+ c1.dispatchEvent(ev);
+ assert_false(ran);
+}, 'TextTrackCue.addEventListener/removeEventListener');
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/onexit.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/onexit.html
new file mode 100644
index 00000000000..815377e4d1a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/onexit.html
@@ -0,0 +1,36 @@
+<!doctype html>
+<title>TextTrackCue.onexit</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+setup(function(){
+ window.c1 = new VTTCue(0, 1, 'text1');
+ window.ev = new Event('exit');
+ window.ran = false;
+ window.cb = function() { ran = true; };
+});
+test(function(){
+ assert_equals(c1.onexit, null, 'initial value');
+ c1.onexit = undefined;
+ assert_equals(c1.onexit, null, 'assigning undefined');
+ c1.onexit = cb;
+ assert_equals(c1.onexit, cb, 'assigning onexit');
+ c1.dispatchEvent(ev);
+ assert_true(ran, 'dispatching event');
+ c1.onexit = null;
+ assert_equals(c1.onexit, null, 'assigning null');
+ ran = false;
+ c1.dispatchEvent(ev);
+ assert_false(ran, 'dispatching event after nulling onexit');
+});
+test(function(){
+ c1.addEventListener('exit', cb, false);
+ c1.dispatchEvent(ev);
+ assert_true(ran);
+ c1.removeEventListener('exit', cb, false);
+ ran = false;
+ c1.dispatchEvent(ev);
+ assert_false(ran);
+}, 'TextTrackCue.addEventListener/removeEventListener');
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/pauseOnExit.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/pauseOnExit.html
new file mode 100644
index 00000000000..31ea4c63b7a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/pauseOnExit.html
@@ -0,0 +1,40 @@
+<!doctype html>
+<title>TextTrackCue.pauseOnExit</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+setup(function(){
+ window.video = document.createElement('video');
+ window.t1 = video.addTextTrack('subtitles');
+ document.body.appendChild(video);
+});
+test(function(){
+ var c1 = new VTTCue(0, 1, 'text1');
+ assert_equals(c1.pauseOnExit, false);
+ c1.pauseOnExit = null;
+ assert_equals(c1.pauseOnExit, false);
+ c1.pauseOnExit = 'foo';
+ assert_equals(c1.pauseOnExit, true);
+}, document.title+', script-created cue');
+
+var t_parsed = async_test(document.title+', parsed cue');
+t_parsed.step(function(){
+ var t = document.createElement('track');
+ t.onload = this.step_func(function(){
+ var c1 = t.track.cues[0];
+ assert_equals(c1.pauseOnExit, false);
+ c1.pauseOnExit = null;
+ assert_equals(c1.pauseOnExit, false);
+ c1.pauseOnExit = 'foo';
+ assert_equals(c1.pauseOnExit, true);
+ this.done();
+ });
+ t.onerror = this.step_func(function() {
+ assert_unreached('got error event');
+ });
+ t.src = 'data:text/vtt,'+encodeURIComponent('WEBVTT\n\n00:00:00.000 --> 00:00:00.001\ntest');
+ t.track.mode = 'showing';
+ video.appendChild(t);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/startTime.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/startTime.html
new file mode 100644
index 00000000000..232a7f23b3e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/startTime.html
@@ -0,0 +1,39 @@
+<!doctype html>
+<title>TextTrackCue.startTime</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+setup(function(){
+ window.video = document.createElement('video');
+ window.t1 = video.addTextTrack('subtitles');
+ document.body.appendChild(video);
+});
+test(function(){
+ var c1 = new VTTCue(-1, 1, 'text1');
+ assert_equals(c1.startTime, -1);
+ c1.startTime = c1.startTime;
+ assert_equals(c1.startTime, -1);
+ assert_throws(new TypeError(), function(){ c1.startTime = NaN; });
+ assert_throws(new TypeError(), function(){ c1.startTime = +Infinity; });
+ assert_throws(new TypeError(), function(){ c1.startTime = -Infinity; });
+}, document.title+', script-created cue');
+
+var t_parsed = async_test(document.title+', parsed cue');
+t_parsed.step(function(){
+ var t = document.createElement('track');
+ t.onload = this.step_func(function(){
+ var c = t.track.cues;
+ assert_equals(c[0].startTime, 0);
+ assert_equals(c[1].startTime, 3600);
+ this.done();
+ });
+ t.onerror = this.step_func(function() {
+ assert_unreached('got error event');
+ });
+ t.src = 'data:text/vtt,'+encodeURIComponent('WEBVTT\n\n00:00:00.000 --> 00:00:00.001\ntest'+
+ '\n\nfoobar\n01:00:00.000 --> 01:00:00.001\ntest');
+ t.track.mode = 'showing';
+ video.appendChild(t);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/track.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/track.html
new file mode 100644
index 00000000000..219e3e703ba
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCue/track.html
@@ -0,0 +1,38 @@
+<!doctype html>
+<title>TextTrackCue.track</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+setup(function(){
+ window.video = document.createElement('video');
+ window.t1 = video.addTextTrack('subtitles');
+ document.body.appendChild(video);
+});
+test(function(){
+ var c1 = new VTTCue(0, 1, 'text1');
+ assert_equals(c1.track, null);
+ t1.addCue(c1);
+ assert_equals(c1.track, t1);
+ t1.removeCue(c1);
+ assert_equals(c1.track, null);
+}, document.title+', script-created cue');
+
+var t_parsed = async_test(document.title+', parsed cue');
+t_parsed.step(function(){
+ var t = document.createElement('track');
+ t.onload = this.step_func(function(){
+ var c = t.track.cues[0];
+ assert_equals(c.track, t.track);
+ t.track.removeCue(c);
+ assert_equals(c.track, null);
+ this.done();
+ });
+ t.onerror = this.step_func(function() {
+ assert_unreached('got error event');
+ });
+ t.src = 'data:text/vtt,'+encodeURIComponent('WEBVTT\n\n00:00:00.000 --> 00:00:00.001\ntest');
+ t.track.mode = 'showing';
+ video.appendChild(t);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCueList/getCueById.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCueList/getCueById.html
new file mode 100644
index 00000000000..8184189b05a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCueList/getCueById.html
@@ -0,0 +1,53 @@
+<!doctype html>
+<title>TextTrackCueList.getCueById</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function(){
+ var video = document.createElement('video');
+ var t = video.addTextTrack('subtitles');
+ document.body.appendChild(video);
+ var cues = t.cues;
+ var c = new VTTCue(0, 1, 'text1');
+ t.addCue(c);
+ assert_equals(cues.getCueById(""), null, '""');
+ assert_equals(cues.getCueById(null), null, 'null');
+ assert_equals(cues.getCueById(undefined), null, 'undefined');
+}, document.title+ ', no id');
+test(function(){
+ var video = document.createElement('video');
+ var t = video.addTextTrack('subtitles');
+ document.body.appendChild(video);
+ var cues = t.cues;
+ var c = new VTTCue(0, 1, 'text1');
+ c.id = 'foo';
+ t.addCue(c);
+ assert_equals(cues.getCueById(""), null, '""');
+ assert_equals(cues.getCueById("foo"), c, '"foo"');
+ assert_equals(cues.getCueById({toString:function(){return "foo"}}), c, 'object');
+}, document.title+ ', id foo');
+test(function(){
+ var video = document.createElement('video');
+ var t = video.addTextTrack('subtitles');
+ document.body.appendChild(video);
+ var cues = t.cues;
+ var c = new VTTCue(0, 1, 'text1');
+ c.id = '1';
+ t.addCue(c);
+ assert_equals(cues.getCueById(""), null, '""');
+ assert_equals(cues.getCueById("1"), c, '"1"');
+ assert_equals(cues.getCueById(1), c, '1');
+}, document.title+ ', no 1');
+test(function(){
+ var video = document.createElement('video');
+ var t = video.addTextTrack('subtitles');
+ document.body.appendChild(video);
+ var cues = t.cues;
+ var c = new VTTCue(0, 1, 'text1');
+ c.id = 'a\u0000b';
+ t.addCue(c);
+ assert_equals(cues.getCueById("a\u0000b"), c, '"a\\u0000b"');
+ assert_equals(cues.getCueById("a"), null, '"a"');
+}, document.title+ ', id a\\u0000b');
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCueList/getter.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCueList/getter.html
new file mode 100644
index 00000000000..d9cd871720e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCueList/getter.html
@@ -0,0 +1,49 @@
+<!doctype html>
+<title>TextTrackCueList getter</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+setup(function(){
+ window.video = document.createElement('video');
+ window.t1 = video.addTextTrack('subtitles');
+ document.body.appendChild(video);
+});
+test(function(){
+ var cues = t1.cues;
+ assert_equals(cues[0], undefined, 'cues[0] before');
+ var c1 = new VTTCue(0, 1, 'text1');
+ t1.addCue(c1);
+ assert_equals(cues[0], c1, 'cues[0]');
+ assert_equals(cues[1], undefined, 'cues[1]');
+ assert_equals(cues[-1], undefined, 'cues[-1]');
+ t1.removeCue(c1);
+ assert_equals(cues[0], undefined, 'cues[0] after');
+});
+test(function(){
+ var cues = t1.cues;
+ assert_equals(cues[0], undefined);
+ cues[0] = 'foo';
+ assert_equals(cues[0], undefined);
+ var c1 = new VTTCue(0, 1, 'text1');
+ t1.addCue(c1);
+ assert_equals(cues[0], c1);
+ cues[0] = 'foo';
+ assert_equals(cues[0], c1);
+ t1.removeCue(c1);
+}, document.title+', no indexed set/create');
+test(function(){
+ 'use strict';
+ var cues = t1.cues;
+ assert_equals(cues[0], undefined);
+ assert_throws(new TypeError(), function() { cues[0] = 'foo'; });
+ assert_equals(cues[0], undefined);
+ var c1 = new VTTCue(0, 1, 'text1');
+ t1.addCue(c1);
+ assert_equals(cues[0], c1);
+ assert_throws(new TypeError(), function() { cues[0] = 'foo'; });
+ assert_equals(cues[0], c1);
+ t1.removeCue(c1);
+}, document.title+', no indexed set/create (strict)');
+
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCueList/length.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCueList/length.html
new file mode 100644
index 00000000000..91e6e7ff999
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackCueList/length.html
@@ -0,0 +1,22 @@
+<!doctype html>
+<title>TextTrackCueList.length</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+setup(function(){
+ window.video = document.createElement('video');
+ window.t1 = video.addTextTrack('subtitles');
+ document.body.appendChild(video);
+});
+test(function(){
+ var cues = t1.cues;
+ assert_equals(cues.length, 0);
+ var c1 = new VTTCue(0, 1, 'text1');
+ t1.addCue(c1);
+ assert_equals(cues.length, 1);
+ t1.removeCue(c1);
+ assert_equals(cues.length, 0);
+});
+
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackList/getTrackById.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackList/getTrackById.html
new file mode 100644
index 00000000000..b701dd5e73d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackList/getTrackById.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<title>TextTrackList.getTrackById</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function(){
+ var video = document.createElement('video');
+ var track1 = video.addTextTrack('subtitles');
+ var track2 = video.addTextTrack('subtitles');
+ assert_equals(track1.id, '');
+ assert_equals(track2.id, '');
+ assert_equals(video.textTracks.getTrackById(''), track1);
+ assert_equals(video.textTracks.getTrackById('fake-id'), null);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackList/getter.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackList/getter.html
new file mode 100644
index 00000000000..8c5fb375940
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackList/getter.html
@@ -0,0 +1,32 @@
+<!doctype html>
+<title>TextTrackList getter</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+setup(function(){
+ window.video = document.createElement('video');
+ video.addTextTrack('subtitles', 'b');
+ window.track = document.createElement('track');
+ track.label = 'a';
+ video.appendChild(track);
+ video.addTextTrack('subtitles', 'c');
+});
+test(function(){
+ assert_equals(video.textTracks[0].label, 'a');
+ assert_equals(video.textTracks[1].label, 'b');
+ assert_equals(video.textTracks[2].label, 'c');
+});
+test(function(){
+ var track_before = video.textTracks[0];
+ video.textTracks[0] = 'foo';
+ assert_equals(video.textTracks[0], track_before);
+}, document.title+', no indexed set/create');
+test(function(){
+ 'use strict';
+ var track_before = video.textTracks[0];
+ assert_throws(new TypeError(), function(){ video.textTracks[0] = 'foo'; });
+ assert_equals(video.textTracks[0], track_before);
+}, document.title+', no indexed set/create (strict)');
+
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackList/length.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackList/length.html
new file mode 100644
index 00000000000..7a24130d10b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackList/length.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<title>TextTrackList.length</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+setup(function(){
+ window.video = document.createElement('video');
+ video.addTextTrack('subtitles');
+ window.track = document.createElement('track');
+ video.appendChild(track);
+ video.addTextTrack('subtitles');
+});
+test(function(){
+ assert_equals(video.textTracks.length, 3);
+});
+
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackList/onaddtrack.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackList/onaddtrack.html
new file mode 100644
index 00000000000..114ca890467
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackList/onaddtrack.html
@@ -0,0 +1,33 @@
+<!doctype html>
+<title>TextTrackList.onaddtrack</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+setup(function(){
+ window.tracks = document.createElement('video').textTracks;
+ window.ev = new Event('addtrack');
+ window.ran = false;
+ window.cb = function() { ran = true; };
+});
+test(function(){
+ assert_equals(tracks.onaddtrack, null);
+ tracks.onaddtrack = cb;
+ assert_equals(tracks.onaddtrack, cb);
+ tracks.dispatchEvent(ev);
+ assert_true(ran);
+ tracks.onaddtrack = null;
+ ran = false;
+ tracks.dispatchEvent(ev);
+ assert_false(ran);
+});
+test(function(){
+ tracks.addEventListener('addtrack', cb, false);
+ tracks.dispatchEvent(ev);
+ assert_true(ran);
+ tracks.removeEventListener('addtrack', cb, false);
+ ran = false;
+ tracks.dispatchEvent(ev);
+ assert_false(ran);
+}, 'TextTrackList.addEventListener/removeEventListener');
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackList/onremovetrack.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackList/onremovetrack.html
new file mode 100644
index 00000000000..b8da16ce2ee
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrackList/onremovetrack.html
@@ -0,0 +1,33 @@
+<!doctype html>
+<title>TextTrackList.onremovetrack</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+setup(function(){
+ window.tracks = document.createElement('video').textTracks;
+ window.ev = new Event('removetrack');
+ window.ran = false;
+ window.cb = function() { ran = true; };
+});
+test(function(){
+ assert_equals(tracks.onremovetrack, null);
+ tracks.onremovetrack = cb;
+ assert_equals(tracks.onremovetrack, cb);
+ tracks.dispatchEvent(ev);
+ assert_true(ran);
+ tracks.onremovetrack = null;
+ ran = false;
+ tracks.dispatchEvent(ev);
+ assert_false(ran);
+});
+test(function(){
+ tracks.addEventListener('removetrack', cb, false);
+ tracks.dispatchEvent(ev);
+ assert_true(ran);
+ tracks.removeEventListener('removetrack', cb, false);
+ ran = false;
+ tracks.dispatchEvent(ev);
+ assert_false(ran);
+}, 'TextTrackList.addEventListener/removeEventListener');
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TrackEvent/constructor.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TrackEvent/constructor.html
new file mode 100644
index 00000000000..54567d14a68
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TrackEvent/constructor.html
@@ -0,0 +1,24 @@
+<!doctype html>
+<title>TrackEvent constructor</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function(){
+ var ev = new TrackEvent('foo');
+ assert_true(ev instanceof TrackEvent, 'ev instanceof TrackEvent');
+ assert_true(ev instanceof Event, 'ev instanceof Event');
+ assert_equals(ev.track, null, 'ev.track');
+ ev.track = {};
+ assert_equals(ev.track, null, 'ev.track after assignment');
+}, document.title+', one arg');
+test(function(){
+ var obj = {};
+ var ev = new TrackEvent('foo', {track:obj});
+ assert_true(ev instanceof TrackEvent, 'ev instanceof TrackEvent');
+ assert_true(ev instanceof Event, 'ev instanceof Event');
+ assert_equals(ev.track, obj, 'ev.track');
+ ev.track = {};
+ assert_equals(ev.track, obj, 'ev.track after assignment');
+}, document.title+', two args');
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TrackEvent/createEvent.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TrackEvent/createEvent.html
new file mode 100644
index 00000000000..9bf763f1fab
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TrackEvent/createEvent.html
@@ -0,0 +1,15 @@
+<!doctype html>
+<title>TrackEvent created with createEvent</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function(){
+ // https://www.w3.org/Bugs/Public/show_bug.cgi?id=17268
+ assert_throws('NOT_SUPPORTED_ERR', function() {
+ var ev = document.createEvent('TrackEvent');
+ });
+ var ev = new TrackEvent('foo');
+ assert_false('initTrackEvent' in ev, 'initTrackEvent');
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/autoplay-overrides-preload.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/autoplay-overrides-preload.html
new file mode 100644
index 00000000000..91103c58677
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/autoplay-overrides-preload.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML>
+<title>autoplay overrides preload</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/media.js"></script>
+<div id=log></div>
+<script>
+['none', 'metadata'].forEach(function(preload) {
+ ['first', 'last'].forEach(function(order) {
+ async_test(function(t) {
+ var a = document.createElement('audio');
+ a.src = getAudioURI('/media/sound_5');
+ if (order == 'first') {
+ a.autoplay = true;
+ a.preload = preload;
+ } else {
+ a.preload = preload;
+ a.autoplay = true;
+ }
+ a.addEventListener('playing', t.step_func(function() {
+ assert_equals(a.readyState, a.HAVE_ENOUGH_DATA);
+ assert_false(a.paused);
+ t.done();
+ }));
+ }, 'autoplay (set ' + order + ') overrides preload "' + preload + '"');
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/load-events-networkState.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/load-events-networkState.html
new file mode 100644
index 00000000000..8c12011ef02
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/load-events-networkState.html
@@ -0,0 +1,67 @@
+<!doctype html>
+<title>load() fires abort/emptied events when networkState is not NETWORK_EMPTY</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/media.js"></script>
+<div id=log></div>
+<script>
+function load_test(t, v) {
+ assert_not_equals(v.networkState, v.NETWORK_EMPTY);
+
+ var expected_events = [];
+ if (v.networkState == v.NETWORK_LOADING || v.networkState == v.NETWORK_IDLE) {
+ expected_events.push('abort');
+ }
+ if (v.networkState != v.NETWORK_EMPTY) {
+ expected_events.push('emptied');
+ }
+
+ var actual_events = [];
+ v.onabort = v.onemptied = t.step_func(function(e) {
+ actual_events.push(e.type);
+ });
+
+ v.onloadstart = t.step_func(function() {
+ assert_array_equals(actual_events, expected_events);
+ t.done();
+ });
+
+ v.load();
+
+ assert_array_equals(actual_events, [], 'events should be fired in queued tasks');
+}
+
+async_test(function(t) {
+ var v = document.createElement('video');
+ // suspend is fired optionally "if the user agent intends to not attempt to
+ // fetch the resource" or "once the entire media resource has been fetched"
+ v.preload = 'none';
+ v.src = getAudioURI('/media/sound_5');
+ v.onsuspend = t.step_func(function() {
+ v.onsuspend = null;
+ assert_equals(v.networkState, v.NETWORK_IDLE);
+ load_test(t, v);
+ });
+}, 'NETWORK_IDLE');
+
+async_test(function(t) {
+ var v = document.createElement('video');
+ v.src = 'resources/delayed-broken-video.py';
+ v.onloadstart = t.step_func(function() {
+ v.onloadstart = null;
+ assert_equals(v.networkState, v.NETWORK_LOADING);
+ load_test(t, v);
+ });
+}, 'NETWORK_LOADING');
+
+async_test(function(t) {
+ var v = document.createElement('video');
+ v.src = 'data:,';
+ v.onerror = t.step_func(function() {
+ v.onerror = null;
+ assert_equals(v.networkState, v.NETWORK_NO_SOURCE);
+ load_test(t, v);
+ });
+ assert_equals(v.networkState, v.NETWORK_NO_SOURCE);
+}, 'NETWORK_NO_SOURCE');
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/load-removes-queued-error-event.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/load-removes-queued-error-event.html
new file mode 100644
index 00000000000..54d5c28dad5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/load-removes-queued-error-event.html
@@ -0,0 +1,44 @@
+<!doctype html>
+<title>load() removes queued error event</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+// The loadstart and error event firing tasks are queued in the synchronous
+// section of the resource selection algorithm, so no tasks can come between
+// them. Calling load() in the loadstart event handler removes the queued error
+// event task at very latest opportunity, failing any implementation that fires
+// the events in the same task.
+
+async_test(function(t) {
+ var v = document.createElement('video');
+ var events = [];
+ v.onloadstart = v.onerror = t.step_func(function(e) {
+ events.push(e.type);
+ if (events.length == 1) {
+ v.load();
+ } else if (events.length == 3) {
+ assert_array_equals(events, ['loadstart', 'loadstart', 'error']);
+ t.done();
+ }
+ });
+ v.src = '';
+}, 'video error event');
+
+async_test(function(t) {
+ var v = document.createElement('video');
+ var s = document.createElement('source');
+ var events = [];
+ v.onloadstart = s.onerror = t.step_func(function(e) {
+ events.push(e.type);
+ if (events.length == 1) {
+ v.load();
+ } else if (events.length == 3) {
+ assert_array_equals(events, ['loadstart', 'loadstart', 'error']);
+ t.done();
+ }
+ });
+ v.onerror = t.step_func(function() { assert_unreached(); });
+ v.appendChild(s);
+}, 'source error event');
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-candidate-insert-before.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-candidate-insert-before.html
new file mode 100644
index 00000000000..39c98875052
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-candidate-insert-before.html
@@ -0,0 +1,29 @@
+<!doctype html>
+<title>inserting another source before the candidate</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var v;
+function createSource(src) {
+ var source = document.createElement('source');
+ source.src = src;
+ return source;
+}
+var t = async_test(function(t) {
+ v = document.createElement('video');
+ v.addEventListener('loadstart', t.step_func(function() {
+ assert_equals(v.currentSrc.substr(v.currentSrc.lastIndexOf('#')), '#a');
+ t.done();
+ }), false);
+ v.appendChild(createSource('#a')); // invokes resource selection
+});
+</script>
+<!-- now resource selection algorithm will continue its sync section (the </script> tag below provides a stable state) -->
+<!-- #a is candidate -->
+<!-- pointer is between #a and the end of the list -->
+<script>
+t.step(function() {
+ v.insertBefore(createSource('#b'), v.firstChild); // pointer is unchanged, #a is still candidate
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-candidate-moved.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-candidate-moved.html
new file mode 100644
index 00000000000..f59452e0d85
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-candidate-moved.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<title>moving the candidate source</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var s;
+var t = async_test(function(t) {
+ var v = document.createElement('video');
+ s = document.createElement('source');
+ s.src = 'resources/delayed-broken-video.py';
+ s.onerror = t.step_func(function() { t.done(); });
+ v.appendChild(s); // invokes resource selection
+ onload = t.step_func(function() { assert_unreached(); });
+});
+</script>
+<script>
+t.step(function() {
+ document.body.appendChild(s);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-candidate-remove-addEventListener.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-candidate-remove-addEventListener.html
new file mode 100644
index 00000000000..0c1e6f0ad8f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-candidate-remove-addEventListener.html
@@ -0,0 +1,26 @@
+<!doctype html>
+<title>removing the candidate source, addEventListener</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var v;
+function createSource(src) {
+ var source = document.createElement('source');
+ source.src = src;
+ return source;
+}
+var t = async_test(function(t) {
+ v = document.createElement('video');
+ v.appendChild(createSource('resources/delayed-broken-video.py')); // invokes resource selection
+ v.firstChild.addEventListener('error', t.step_func(function() { t.done(); }), false);
+});
+</script>
+<!-- now resource selection algorithm will continue its sync section (the </script> tag below provides a stable state) -->
+<!-- the <source> is candidate -->
+<!-- pointer is between the <source> and the end of the list -->
+<script>
+t.step(function() {
+ v.removeChild(v.firstChild); // tests that we fire 'error' on it despite being removed
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-candidate-remove-no-listener.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-candidate-remove-no-listener.html
new file mode 100644
index 00000000000..f384eb31215
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-candidate-remove-no-listener.html
@@ -0,0 +1,26 @@
+<!doctype html>
+<title>removing the candidate source, no listener</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var v;
+function createSource(src) {
+ var source = document.createElement('source');
+ source.src = src;
+ return source;
+}
+var t = async_test(function(t) {
+ v = document.createElement('video');
+ v.appendChild(createSource('resources/delayed-broken-video.py')); // invokes resource selection
+});
+</script>
+<!-- now resource selection algorithm will continue its sync section (the </script> tag below provides a stable state) -->
+<!-- the <source> is candidate -->
+<!-- pointer is between the <source> and the end of the list -->
+<script>
+t.step(function() {
+ v.removeChild(v.firstChild); // just tests that we don't crash
+ onload = t.step_func(function() { t.done(); });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-candidate-remove-onerror.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-candidate-remove-onerror.html
new file mode 100644
index 00000000000..c295c85bfcd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-candidate-remove-onerror.html
@@ -0,0 +1,26 @@
+<!doctype html>
+<title>removing the candidate source, onerror</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var v;
+function createSource(src) {
+ var source = document.createElement('source');
+ source.src = src;
+ return source;
+}
+var t = async_test(function(t) {
+ v = document.createElement('video');
+ v.appendChild(createSource('resources/delayed-broken-video.py')); // invokes resource selection
+ v.firstChild.onerror = t.step_func(function() { t.done(); });
+});
+</script>
+<!-- now resource selection algorithm will continue its sync section (the </script> tag below provides a stable state) -->
+<!-- the <source> is candidate -->
+<!-- pointer is between the <source> and the end of the list -->
+<script>
+t.step(function() {
+ v.removeChild(v.firstChild); // tests that we fire 'error' on it despite being removed
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-audio-constructor-no-src.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-audio-constructor-no-src.html
new file mode 100644
index 00000000000..cb2a5795979
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-audio-constructor-no-src.html
@@ -0,0 +1,13 @@
+<!doctype html>
+<title>NOT invoking resource selection with new Audio() sans src</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var a = new Audio();
+ assert_equals(a.networkState, a.NETWORK_EMPTY);
+ a.onloadstart = t.step_func(function() { assert_unreached(); });
+ window.onload = t.step_func(function() { t.done(); });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-audio-constructor.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-audio-constructor.html
new file mode 100644
index 00000000000..662129756f5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-audio-constructor.html
@@ -0,0 +1,12 @@
+<!doctype html>
+<title>invoking resource selection with new Audio(src)</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var a = new Audio('');
+ a.onloadstart = t.step_func(function() { t.done(); });
+ window.onload = t.step_func(function() { assert_unreached(); });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-in-sync-event.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-in-sync-event.html
new file mode 100644
index 00000000000..55fc7c20d3a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-in-sync-event.html
@@ -0,0 +1,32 @@
+<!doctype html>
+<title>await a stable state and sync event handlers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<video></video>
+<script>
+var v;
+var t = async_test(function(t) {
+ v = document.querySelector('video');
+ var a = document.createElement('a');
+ a.onclick = t.step_func(function() {
+ v.setAttribute('src', '#'); // invokes media load which invokes resource selection
+ assert_equals(v.networkState, v.NETWORK_NO_SOURCE, 'networkState in onclick handler');
+ });
+ a.click(); // sync fires click, so sets src
+ // now we should still await a stable state because the script hasn't
+ // finished, the event handler has just returned
+ assert_equals(v.networkState, v.NETWORK_NO_SOURCE, 'networkState after click()');
+ v.removeAttribute('src');
+});
+</script>
+<script>
+t.step(function() {
+ // now the sync section of resource selection should have run and should
+ // have found no src="" or <source> thus networkState being set to NETWORK_EMPTY.
+ // if the sync section was run when onclick returned, then networkState
+ // would be either NETWORK_LOADING or NETWORK_NO_SOURCE.
+ assert_equals(v.networkState, v.NETWORK_EMPTY, 'networkState in separate script');
+ t.done();
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-fragment-into-document.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-fragment-into-document.html
new file mode 100644
index 00000000000..5d4c32f670e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-fragment-into-document.html
@@ -0,0 +1,22 @@
+<!doctype html>
+<title>NOT invoking resource selection by inserting document fragment into a document</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var v;
+var t = async_test(function(t) {
+ v = document.createElement('video');
+ var fragment = document.createDocumentFragment();
+ fragment.appendChild(v);
+ assert_equals(v.networkState, v.NETWORK_EMPTY, 'networkState after fragment.appendChild(v)');
+ document.body.appendChild(fragment);
+ assert_equals(v.networkState, v.NETWORK_EMPTY, 'networkState after document.body.appendChild(fragment)');
+});
+</script>
+<script>
+t.step(function() {
+ assert_equals(v.networkState, v.NETWORK_EMPTY, 'networkState in separate script');
+ t.done();
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-into-document.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-into-document.html
new file mode 100644
index 00000000000..2f9ec978a55
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-into-document.html
@@ -0,0 +1,12 @@
+<!doctype html>
+<title>NOT invoking resource selection by inserting into a document</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+test(function(t) {
+ var v = document.createElement('video');
+ document.body.appendChild(v);
+ assert_equals(v.networkState, v.NETWORK_EMPTY);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-into-iframe.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-into-iframe.html
new file mode 100644
index 00000000000..45d133d8788
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-into-iframe.html
@@ -0,0 +1,23 @@
+<!doctype html>
+<title>NOT invoking resource selection by inserting into other document with src set</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<iframe hidden></iframe>
+<script>
+async_test(function(t) {
+ var v = document.createElement('video');
+ v.src = 'data:,';
+ v.onerror = t.step_func(function() {
+ assert_equals(v.readyState, v.HAVE_NOTHING);
+ assert_equals(v.networkState, v.NETWORK_NO_SOURCE);
+ var iframe = document.querySelector('iframe');
+ iframe.contentDocument.body.appendChild(v);
+ v.onloadstart = t.step_func(function() { assert_unreached(); });
+ // wait for an event after the above
+ var v2 = document.createElement('video');
+ v2.src = 'data:,';
+ v2.onloadstart = t.step_func(function() { t.done(); });
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-parent-into-document.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-parent-into-document.html
new file mode 100644
index 00000000000..6da34344fd1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-parent-into-document.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<title>NOT invoking resource selection by inserting parent into a document</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var v = document.createElement('video');
+ var div = document.createElement('div');
+ div.appendChild(v);
+ assert_equals(v.networkState, v.NETWORK_EMPTY, 'networkState after div.appendChild(v)');
+ document.body.appendChild(div);
+ assert_equals(v.networkState, v.NETWORK_EMPTY, 'networkState after document.body.appendChild(div)');
+ window.onload = t.step_func(function() {
+ assert_equals(v.networkState, v.NETWORK_EMPTY, 'networkState in window.onload');
+ t.done();
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source-in-div.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source-in-div.html
new file mode 100644
index 00000000000..b79bea52f1a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source-in-div.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<title>NOT invoking resource selection by inserting &lt;source> in &lt;div> in &lt;video></title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<video><div></div></video>
+<script>
+async_test(function(t) {
+ var v = document.querySelector('video');
+ v.onloadstart = t.step_func(function() { assert_unreached(); });
+ v.firstChild.appendChild(document.createElement('source'));
+ window.onload = t.step_func(function() { t.done(); });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source-in-namespace.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source-in-namespace.html
new file mode 100644
index 00000000000..b73f229ecc6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source-in-namespace.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<title>NOT invoking resource selection by inserting &lt;source> in the wrong namespace</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<video></video>
+<script>
+async_test(function(t) {
+ var v = document.querySelector('video');
+ v.onloadstart = t.step_func(function() { assert_unreached(); });
+ v.appendChild(document.createElementNS('bogus','source'));
+ window.onload = t.step_func(function() { t.done(); });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source-networkState.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source-networkState.html
new file mode 100644
index 00000000000..5ef6e4cb3ba
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source-networkState.html
@@ -0,0 +1,38 @@
+<!doctype html>
+<title>NOT invoking resource selection by inserting &lt;source> when networkState is not NETWORK_EMPTY</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var loadstartCount = 0;
+var s1ErrorCount = 0;
+var s2ErrorCount = 0;
+var v;
+var t = async_test(function(t) {
+ v = document.createElement('video');
+ v.onloadstart = function() { loadstartCount++; };
+ var s1 = document.createElement('source');
+ s1.src = 'resources/delayed-broken-video.py';
+ s1.onerror = function() { s1ErrorCount++; };
+ v.appendChild(s1); // invokes resource selection
+ assert_equals(v.networkState, v.NETWORK_NO_SOURCE, 'networkState in first script');
+});
+</script>
+<script>
+t.step(function() {
+ assert_equals(v.networkState, v.NETWORK_LOADING, 'networkState in second script');
+ assert_equals(s1ErrorCount, 0, 's1ErrorCount in second script');
+ var s2 = document.createElement('source');
+ s2.onerror = t.step_func(function() {
+ s2ErrorCount++;
+ assert_equals(s1ErrorCount, 1, 's1ErrorCount in s2.onerror');
+ });
+ v.appendChild(s2);
+ onload = t.step_func(function() {
+ assert_equals(s2ErrorCount, 1, 's2ErrorCount in window.onload');
+ assert_equals(loadstartCount, 1, 'loadstartCount in window.onload'); // reliable if https://www.w3.org/Bugs/Public/show_bug.cgi?id=24353 is fixed
+ assert_equals(v.networkState, v.NETWORK_NO_SOURCE, 'networkState in window.onload'); // See Waiting step
+ t.done();
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source-not-in-document.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source-not-in-document.html
new file mode 100644
index 00000000000..2007b2e8b3c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source-not-in-document.html
@@ -0,0 +1,13 @@
+<!doctype html>
+<title>invoking resource selection by inserting &lt;source> in video not in a document</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var v = document.createElement('video');
+ v.onloadstart = t.step_func(function() { t.done(); });
+ v.appendChild(document.createElement('source'));
+ window.onload = t.step_func(function() { assert_unreached(); });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source.html
new file mode 100644
index 00000000000..969daad6231
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-source.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<title>invoking resource selection by inserting &lt;source></title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<video></video>
+<script>
+async_test(function(t) {
+ var v = document.querySelector('video');
+ v.onloadstart = t.step_func(function() { t.done(); });
+ v.appendChild(document.createElement('source'));
+ window.onload = t.step_func(function() { assert_unreached(); });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-load.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-load.html
new file mode 100644
index 00000000000..909c72cd150
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-load.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<title>invoking resource selection with load()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var v;
+var t = async_test(function(t) {
+ v = document.createElement('video');
+ assert_equals(v.networkState, v.NETWORK_EMPTY, 'networkState after creating v');
+ v.load();
+ assert_equals(v.networkState, v.NETWORK_NO_SOURCE, 'networkState after v.load()');
+});
+</script>
+<script>
+t.step(function() {
+ assert_equals(v.networkState, v.NETWORK_EMPTY, 'networkState in separate script');
+ t.done();
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-pause-networkState.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-pause-networkState.html
new file mode 100644
index 00000000000..18561a2649a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-pause-networkState.html
@@ -0,0 +1,28 @@
+<!doctype html>
+<title>NOT invoking resource selection with pause() when networkState is not NETWORK_EMPTY</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<video></video>
+<script>
+var v;
+var t = async_test(function(t) {
+ v = document.querySelector('video');
+ v.src = 'data:,';
+ assert_equals(v.networkState, v.NETWORK_NO_SOURCE, 'networkState after setting src');
+ var errorCount = 0;
+ v.onerror = t.step_func(function() {
+ errorCount++;
+ if (errorCount == 1) {
+ assert_equals(v.networkState, v.NETWORK_NO_SOURCE, 'networkState in onerror');
+ v.pause(); // should not invoke RSA. if it does, error will be fired again.
+ } else {
+ assert_unreached();
+ }
+ });
+ onload = t.step_func(function() {
+ assert_equals(errorCount, 1, 'errorCount');
+ t.done();
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-pause.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-pause.html
new file mode 100644
index 00000000000..4f1bca74dd1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-pause.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<title>invoking resource selection with pause()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var v;
+var t = async_test(function(t) {
+ v = document.createElement('video');
+ assert_equals(v.networkState, v.NETWORK_EMPTY, 'networkState after creating v');
+ v.pause();
+ assert_equals(v.networkState, v.NETWORK_NO_SOURCE, 'networkState after v.pause()');
+});
+</script>
+<script>
+t.step(function() {
+ assert_equals(v.networkState, v.NETWORK_EMPTY, 'networkState in separate script');
+ t.done();
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-play.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-play.html
new file mode 100644
index 00000000000..64a440080c2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-play.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<title>invoking resource selection with play()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var v;
+var t = async_test(function(t) {
+ v = document.createElement('video');
+ assert_equals(v.networkState, v.NETWORK_EMPTY, 'networkState after creating v');
+ v.play();
+ assert_equals(v.networkState, v.NETWORK_NO_SOURCE, 'networkState after v.play()');
+});
+</script>
+<script>
+t.step(function() {
+ assert_equals(v.networkState, v.NETWORK_EMPTY, 'networkState in separate script');
+ t.done();
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-remove-from-document-networkState.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-remove-from-document-networkState.html
new file mode 100644
index 00000000000..1eed276b20f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-remove-from-document-networkState.html
@@ -0,0 +1,29 @@
+<!doctype html>
+<title>NOT invoking resource selection with implicit pause() when networkState is not NETWORK_EMPTY</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<video></video>
+<script>
+var v;
+var t = async_test(function(t) {
+ v = document.querySelector('video');
+ v.src = 'data:,';
+ document.body.appendChild(v);
+ assert_equals(v.networkState, v.NETWORK_NO_SOURCE, 'networkState after setting src');
+ var errorCount = 0;
+ v.onerror = t.step_func(function() {
+ errorCount++;
+ if (errorCount == 1) {
+ assert_equals(v.networkState, v.NETWORK_NO_SOURCE, 'networkState in onerror');
+ document.body.removeChild(v); // invokes pause() which should not invoke RSA. if it does, error will be fired again.
+ } else {
+ assert_unreached();
+ }
+ });
+ onload = t.step_func(function() {
+ assert_equals(errorCount, 1, 'errorCount');
+ t.done();
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-remove-from-document.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-remove-from-document.html
new file mode 100644
index 00000000000..23e7104cab8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-remove-from-document.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<title>NOT invoking resource selection by removing from document with NETWORK_EMPTY</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var v;
+var t = async_test(function(t) {
+ v = document.createElement('video');
+ document.body.appendChild(v);
+ assert_equals(v.networkState, v.NETWORK_EMPTY, 'networkState after appending v to document');
+ v.parentNode.removeChild(v); // search for "When a media element is removed from a Document,"
+ assert_equals(v.networkState, v.NETWORK_EMPTY, 'networkState after removing v');
+});
+</script>
+<script>
+t.step(function() {
+ assert_equals(v.networkState, v.NETWORK_EMPTY, 'networkState in separate script');
+ t.done();
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-remove-src.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-remove-src.html
new file mode 100644
index 00000000000..6302ffeacf2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-remove-src.html
@@ -0,0 +1,22 @@
+<!doctype html>
+<title>NOT invoking media load or resource selection when removing the src attribute</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var v;
+var t = async_test(function(t) {
+ v = document.createElement('video');
+ v.setAttribute('src', ''); // invokes media load
+ assert_equals(v.networkState, v.NETWORK_NO_SOURCE, 'networkState after setting src');
+ var s = document.createElement('source');
+ s.onerror = this.step_func(function() { assert_unreached(); });
+ v.appendChild(s); // src is present so nothing happens here
+ onload = this.step_func(function() { t.done(); });
+});
+</script>
+<script>
+t.step(function() {
+ v.removeAttribute('src'); // nothing should happen
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-set-src-in-namespace.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-set-src-in-namespace.html
new file mode 100644
index 00000000000..438db124d23
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-set-src-in-namespace.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<title>NOT invoking load by setting src in the wrong namespace</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<video></video>
+<script>
+async_test(function(t) {
+ var v = document.querySelector('video');
+ v.onloadstart = t.step_func(function() { assert_unreached(); });
+ v.setAttributeNS('bogus','src', '');
+ window.onload = t.step_func(function() { t.done(); });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-set-src-networkState.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-set-src-networkState.html
new file mode 100644
index 00000000000..e195dedb044
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-set-src-networkState.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<title>invoking load by setting src when networkState is not NETWORK_EMPTY</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+test(function(t) {
+ var v = document.createElement('video');
+ v.play(); // invokes resource selection and sets .paused to false
+ assert_equals(v.networkState, v.NETWORK_NO_SOURCE, 'networkState');
+ assert_false(v.paused, 'paused');
+ v.setAttribute('src', ''); // invokes media load which sets .paused to true
+ assert_equals(v.networkState, v.NETWORK_NO_SOURCE, 'networkState after setting src');
+ assert_true(v.paused, 'paused after setting src');
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-set-src-not-in-document.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-set-src-not-in-document.html
new file mode 100644
index 00000000000..f6c4f2406a3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-set-src-not-in-document.html
@@ -0,0 +1,13 @@
+<!doctype html>
+<title>invoking load by setting src on video not in a document</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var v = document.createElement('video');
+ v.onloadstart = t.step_func(function() { t.done(); });
+ v.setAttribute('src','');
+ window.onload = t.step_func(function() { assert_unreached(); });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-set-src.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-set-src.html
new file mode 100644
index 00000000000..e04b1b0580f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-set-src.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<title>invoking load by setting src</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<video></video>
+<script>
+async_test(function(t) {
+ var v = document.querySelector('video');
+ v.onloadstart = t.step_func(function() { t.done(); });
+ v.setAttribute('src', '');
+ window.onload = t.step_func(function() { assert_unreached(); });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-control.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-control.html
new file mode 100644
index 00000000000..dad5e5fd008
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-control.html
@@ -0,0 +1,26 @@
+<!doctype html>
+<title>pointer updates (control test)</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var a = 0;
+var b = 0;
+var c = 0;
+</script>
+<video
+ ><source onerror=a++
+ ><source onerror=b++ src='resources/delayed-broken-video.py'
+ ><source onerror=c++
+ ></video
+>
+<script>
+async_test(function(t) {
+ window.onload = t.step_func(function() {
+ assert_equals(a, 1, 'error events on a');
+ assert_equals(b, 1, 'error events on b');
+ assert_equals(c, 1, 'error events on c');
+ t.done();
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-insert-br.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-insert-br.html
new file mode 100644
index 00000000000..3ee141e3069
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-insert-br.html
@@ -0,0 +1,33 @@
+<!doctype html>
+<title>pointer updates (adding br elements)</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var a = 0;
+var b = 0;
+var c = 0;
+</script>
+<video
+ ><source onerror=a++
+ ><source onerror=b++ src='resources/delayed-broken-video.py'
+ ><source onerror=c++
+ ></video
+>
+<script>
+async_test(function(t) {
+ var video = document.querySelector('video');
+ // add br elements
+ var br = document.createElement('br');
+ video.insertBefore(br, video.querySelector('[onerror="a++"]'));
+ video.insertBefore(br.cloneNode(false), video.querySelector('[onerror="b++"]'));
+ video.insertBefore(br.cloneNode(false), video.querySelector('[onerror="c++"]'));
+ video.appendChild(br.cloneNode(false));
+ window.onload = t.step_func(function() {
+ assert_equals(a, 1, 'error events on a');
+ assert_equals(b, 1, 'error events on b');
+ assert_equals(c, 1, 'error events on c');
+ t.done();
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-insert-source.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-insert-source.html
new file mode 100644
index 00000000000..2d32e6fca05
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-insert-source.html
@@ -0,0 +1,44 @@
+<!doctype html>
+<title>pointer updates (adding source elements)</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var a = 0;
+var b = 0;
+var c = 0;
+var x1 = 0;
+var x2 = 0;
+var x3 = 0;
+var x4 = 0;
+</script>
+<video
+ ><source onerror=a++
+ ><source onerror=b++ src='resources/delayed-broken-video.py'
+ ><source onerror=c++
+ ></video
+>
+<script>
+async_test(function(t) {
+ var video = document.querySelector('video');
+ // add source elements
+ var source1 = document.createElement('source'); source1.onerror = function() { x1++; };
+ var source2 = document.createElement('source'); source2.onerror = function() { x2++; };
+ var source3 = document.createElement('source'); source3.onerror = function() { x3++; };
+ var source4 = document.createElement('source'); source4.onerror = function() { x4++; };
+ video.insertBefore(source1, video.querySelector('[onerror="a++"]'));
+ video.insertBefore(source2, video.querySelector('[onerror="b++"]'));
+ video.insertBefore(source3, video.querySelector('[onerror="c++"]'));
+ video.appendChild(source4);
+ window.onload = t.step_func(function() {
+ assert_equals(a, 1, 'error events on a');
+ assert_equals(b, 1, 'error events on b');
+ assert_equals(c, 1, 'error events on c');
+ assert_equals(x1, 0, 'error events on x1');
+ assert_equals(x2, 0, 'error events on x2');
+ assert_equals(x3, 1, 'error events on x3');
+ assert_equals(x4, 1, 'error events on x4');
+ t.done();
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-insert-text.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-insert-text.html
new file mode 100644
index 00000000000..15a4e4be064
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-insert-text.html
@@ -0,0 +1,33 @@
+<!doctype html>
+<title>pointer updates (adding text nodes)</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var a = 0;
+var b = 0;
+var c = 0;
+</script>
+<video
+ ><source onerror=a++
+ ><source onerror=b++ src='resources/delayed-broken-video.py'
+ ><source onerror=c++
+ ></video
+>
+<script>
+async_test(function(t) {
+ var video = document.querySelector('video');
+ // add text nodes
+ var text = document.createTextNode('x');
+ video.insertBefore(text, video.querySelector('[onerror="a++"]'));
+ video.insertBefore(text.cloneNode(false), video.querySelector('[onerror="b++"]'));
+ video.insertBefore(text.cloneNode(false), video.querySelector('[onerror="c++"]'));
+ video.appendChild(text.cloneNode(false));
+ window.onload = t.step_func(function() {
+ assert_equals(a, 1, 'error events on a');
+ assert_equals(b, 1, 'error events on b');
+ assert_equals(c, 1, 'error events on c');
+ t.done();
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-remove-source-after.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-remove-source-after.html
new file mode 100644
index 00000000000..0d1c940375c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-remove-source-after.html
@@ -0,0 +1,56 @@
+<!doctype html>
+<title>pointer updates (removing source element after pointer)</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var a = 0;
+var b = 0;
+var c = 0;
+var x1 = 0;
+var x2 = 0;
+var x3 = 0;
+var x4 = 0;
+</script>
+<video
+ ><source onerror=a++
+ ><source onerror=b++ src='resources/delayed-broken-video.py'
+ ><source onerror=x1++
+ ><source onerror=x2++
+ ><source onerror=x3++
+ ><source onerror=x4++
+ ><source onerror=c++
+ ></video
+>
+<script>
+var v;
+var t = async_test(function(t) {
+ v = document.querySelector('video');
+ v.removeChild(document.querySelector('[onerror="x1++"]'));
+ window.onload = t.step_func(function() {
+ assert_equals(a, 1, 'error events on a');
+ assert_equals(b, 1, 'error events on b');
+ assert_equals(c, 1, 'error events on c');
+ assert_equals(x1, 0, 'error events on x1');
+ assert_equals(x2, 0, 'error events on x2');
+ assert_equals(x3, 0, 'error events on x3');
+ assert_equals(x4, 0, 'error events on x4');
+ t.done();
+ });
+});
+</script>
+<script>
+t.step(function() {
+ v.removeChild(document.querySelector('[onerror="x2++"]'));
+});
+</script>
+<script>
+t.step(function() {
+ v.removeChild(document.querySelector('[onerror="x3++"]'));
+});
+</script>
+<script>
+t.step(function() {
+ v.removeChild(document.querySelector('[onerror="x4++"]'));
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-remove-source.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-remove-source.html
new file mode 100644
index 00000000000..191f9b5e21f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-remove-source.html
@@ -0,0 +1,43 @@
+<!doctype html>
+<title>pointer updates (removing source elements)</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var a = 0;
+var b = 0;
+var c = 0;
+var x1 = 0;
+var x2 = 0;
+var x3 = 0;
+var x4 = 0;
+</script>
+<video
+ ><source onerror=x1++
+ ><source onerror=a++
+ ><source onerror=x2++
+ ><source onerror=b++ src='resources/delayed-broken-video.py'
+ ><source onerror=x3++
+ ><source onerror=c++
+ ><source onerror=x4++
+ ></video
+>
+<script>
+async_test(function(t) {
+ var video = document.querySelector('video');
+ // remove the xn elements
+ [].forEach.call(document.querySelectorAll('[onerror^="x"]'), function(elm) {
+ video.removeChild(elm);
+ });
+ window.onload = t.step_func(function() {
+ assert_equals(a, 1, 'error events on a');
+ assert_equals(b, 1, 'error events on b');
+ assert_equals(c, 1, 'error events on c');
+ assert_equals(x1, 1, 'error events on x1');
+ assert_equals(x2, 1, 'error events on x2');
+ assert_equals(x3, 0, 'error events on x3');
+ assert_equals(x4, 0, 'error events on x4');
+ t.done();
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-remove-text.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-remove-text.html
new file mode 100644
index 00000000000..f0fe5da909c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-pointer-remove-text.html
@@ -0,0 +1,33 @@
+<!doctype html>
+<title>pointer updates (removing text nodes)</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var a = 0;
+var b = 0;
+var c = 0;
+</script>
+<video
+ >x<source onerror=a++
+ >x<source onerror=b++ src='resources/delayed-broken-video.py'
+ >x<source onerror=c++
+ >x</video
+>
+<script>
+async_test(function(t) {
+ var video = document.querySelector('video');
+ // remove the text nodes
+ [].forEach.call(video.childNodes, function(node) {
+ if (node.nodeType == node.TEXT_NODE) {
+ video.removeChild(node);
+ }
+ });
+ window.onload = t.step_func(function() {
+ assert_equals(a, 1, 'error events on a');
+ assert_equals(b, 1, 'error events on b');
+ assert_equals(c, 1, 'error events on c');
+ t.done();
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-remove-source.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-remove-source.html
new file mode 100644
index 00000000000..fbeead01915
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-remove-source.html
@@ -0,0 +1,24 @@
+<!doctype html>
+<title>Changes to networkState when inserting and removing a &lt;source></title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var v;
+var t = async_test(function(t) {
+ v = document.createElement('video');
+ assert_equals(v.networkState, v.NETWORK_EMPTY, 'networkState when creating the element');
+ v.appendChild(document.createElement('source')); // runs resource selection algorithm
+ assert_equals(v.networkState, v.NETWORK_NO_SOURCE, 'networkState when inserting a source element');
+ v.removeChild(v.firstChild);
+ assert_equals(v.networkState, v.NETWORK_NO_SOURCE, 'networkState after removing the source element');
+});
+</script>
+<!-- now resource selection will continue its sync section (the </script> tag below provides a stable state) -->
+<!-- will find neither src nor source, so sets networkState to NETWORK_EMPTY -->
+<script>
+t.step(function() {
+ assert_equals(v.networkState, v.NETWORK_EMPTY, 'networkState after letting the sync section of resource selection run');
+ t.done();
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-remove-src.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-remove-src.html
new file mode 100644
index 00000000000..4d788718237
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-remove-src.html
@@ -0,0 +1,22 @@
+<!doctype html>
+<title>invoking resource selection by setting src; await stable state</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var v;
+var t = async_test(function(t) {
+ v = document.createElement('video');
+ v.onloadstart = t.step_func(function() { assert_unreached(); });
+ v.setAttribute('src', ''); // runs resource selection algorithm, but it will wait running the sync section until this script has finished
+ assert_equals(v.networkState, v.NETWORK_NO_SOURCE);
+ v.removeAttribute('src'); // will make resource selection algorithm revert to NETWORK_EMPTY and abort (in the sync section)
+ assert_equals(v.networkState, v.NETWORK_NO_SOURCE);
+ window.onload = t.step_func(function() { t.done(); });
+});
+</script>
+<script>
+t.step(function() {
+ assert_equals(v.networkState, v.NETWORK_EMPTY);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-source-media.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-source-media.html
new file mode 100644
index 00000000000..6332f0890db
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-source-media.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<title>the &lt;source> media attribute has no effect</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<video><source src="resources/delayed-broken-video.py" media="none"></video>
+<script>
+test(function() {
+ var v = document.querySelector('video');
+ var s = document.querySelector('source');
+ assert_equals(v.networkState, v.NETWORK_LOADING);
+ assert_equals(v.currentSrc, s.src);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resources/delayed-broken-video.py b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resources/delayed-broken-video.py
new file mode 100644
index 00000000000..88e5027947c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/resources/delayed-broken-video.py
@@ -0,0 +1,5 @@
+import time
+
+def main(request, response):
+ time.sleep(0.1)
+ return [("Content-Type", "text/plain")], "FAIL"
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/stable-state-beforeunload-manual.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/stable-state-beforeunload-manual.html
new file mode 100644
index 00000000000..61ed225fa10
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/stable-state-beforeunload-manual.html
@@ -0,0 +1,30 @@
+<!doctype html>
+<title>stable state in beforeunload</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<button>click this button and cancel navigation</button>
+<a href="data:text/plain,FAIL: did not cancel navigation"></a>
+<script>
+async_test(function(t) {
+ window.onbeforeunload = t.step_func(function(event) {
+ var message = "foo bar";
+ event.returnValue = message;
+ return message;
+ });
+ var button = document.querySelector('button');
+ var link = document.querySelector('a');
+ button.onclick = t.step_func(function() {
+ v = document.createElement('video');
+ v.src = 'data:,';
+ assert_equals(v.networkState, v.NETWORK_NO_SOURCE, 'networkState before dialog');
+ assert_equals(v.currentSrc, '', 'currentSrc before dialog');
+ link.click();
+ assert_equals(v.networkState, v.NETWORK_NO_SOURCE, 'networkState after dialog');
+ assert_equals(v.currentSrc, '', 'currentSrc after dialog');
+ t.done();
+ window.onbeforeonload = null;
+ button.remove();
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/stable-state-dialogs-manual.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/stable-state-dialogs-manual.html
new file mode 100644
index 00000000000..267dde913c5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/stable-state-dialogs-manual.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<title>stable state in dialogs</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+['alert', 'confirm', 'prompt'].forEach(function(dialog) {
+ test(function() {
+ v = document.createElement('video');
+ v.src = 'data:,';
+ assert_equals(v.networkState, v.NETWORK_NO_SOURCE, 'networkState before dialog');
+ assert_equals(v.currentSrc, '', 'currentSrc before dialog');
+ window[dialog]('dismiss this dialog');
+ assert_equals(v.networkState, v.NETWORK_NO_SOURCE, 'networkState after dialog');
+ assert_equals(v.currentSrc, '', 'currentSrc after dialog');
+ }, 'stable state in ' + dialog + '()');
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/stable-state-print-manual.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/stable-state-print-manual.html
new file mode 100644
index 00000000000..1261a00793e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/loading-the-media-resource/stable-state-print-manual.html
@@ -0,0 +1,22 @@
+<!doctype html>
+<title>stable state in print()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<button>click this button and dismiss the print dialog</button>
+<script>
+async_test(function(t) {
+ var button = document.querySelector('button');
+ button.onclick = t.step_func(function() {
+ v = document.createElement('video');
+ v.src = 'data:,';
+ assert_equals(v.networkState, v.NETWORK_NO_SOURCE, 'networkState before dialog');
+ assert_equals(v.currentSrc, '', 'currentSrc before dialog');
+ print();
+ assert_equals(v.networkState, v.NETWORK_NO_SOURCE, 'networkState after dialog');
+ assert_equals(v.currentSrc, '', 'currentSrc after dialog');
+ t.done();
+ button.remove();
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/location-of-the-media-resource/currentSrc.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/location-of-the-media-resource/currentSrc.html
new file mode 100644
index 00000000000..2ca0a5180cd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/location-of-the-media-resource/currentSrc.html
@@ -0,0 +1,44 @@
+<!doctype html>
+<title>currentSrc</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+['audio', 'video'].forEach(function(tagName) {
+ test(function() {
+ assert_equals(document.createElement(tagName).currentSrc, '');
+ }, tagName + '.currentSrc initial value');
+
+ ['', '.', ' ', 'data:,'].forEach(function(src) {
+ async_test(function(t) {
+ var e = document.createElement(tagName);
+ e.src = src;
+ assert_equals(e.currentSrc, '');
+ setTimeout(t.step_func(function() {
+ if (src == '') {
+ assert_equals(e.currentSrc, '');
+ } else {
+ assert_equals(e.currentSrc, e.src);
+ }
+ t.done();
+ }), 0);
+ }, tagName + '.currentSrc after setting src attribute "' + src + '"');
+
+ async_test(function(t) {
+ var e = document.createElement(tagName);
+ var s = document.createElement('source');
+ s.src = src;
+ e.appendChild(s);
+ assert_equals(e.currentSrc, '');
+ setTimeout(t.step_func(function() {
+ if (src == '') {
+ assert_equals(e.currentSrc, '');
+ } else {
+ assert_equals(e.currentSrc, s.src);
+ }
+ t.done();
+ }), 0);
+ }, tagName + '.currentSrc after adding source element with src attribute "' + src + '"');
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/mime-types/canPlayType.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/mime-types/canPlayType.html
new file mode 100644
index 00000000000..c5d37e75206
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/mime-types/canPlayType.html
@@ -0,0 +1,110 @@
+<!doctype html>
+<title>canPlayType</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+function t(type, expected) {
+ assert_equals(canPlayType(type), expected, type);
+}
+
+function mime(type, codecs) {
+ if (codecs.length) {
+ return type + '; codecs="' + codecs.join(', ') + '"';
+ }
+ return type;
+}
+
+test(function() {
+ assert_equals(mime('video/webm', []), 'video/webm');
+ assert_equals(mime('video/webm', ['vp8']), 'video/webm; codecs="vp8"');
+ assert_equals(mime('video/webm', ['vp8', 'vorbis']), 'video/webm; codecs="vp8, vorbis"');
+}, 'utility code');
+
+function canPlayType(type) {
+ var canPlay = document.createElement('audio').canPlayType(type);
+ assert_equals(canPlay, document.createElement('video').canPlayType(type),
+ 'audio.canPlayType() and video.canPlayType() agree');
+ assert_in_array(canPlay, ['', 'maybe', 'probably'],
+ 'return value is one of "", "maybe" and "probably"');
+ return canPlay;
+}
+
+test(function() {
+ t('application/octet-stream', '');
+ t('application/octet-stream; codecs="vorbis"', '');
+ t('application/octet-stream; codecs="vp8, vorbis"', '');
+ t('application/octet-stream; codecs="mp4a.40.2"', '');
+ t('application/octet-stream; codecs="theora, vorbis"', '');
+ t('application/octet-stream; codecs="avc1.42E01E, mp4a.40.2"', '');
+}, 'application/octet-stream');
+
+test(function() {
+ t('video/x-new-fictional-format', '');
+ t('video/x-new-fictional-format;codecs="kittens,bunnies"', '');
+}, 'video/x-new-fictional-format');
+
+function type_codecs_test(type, audioCodecs, videoCodecs) {
+ var typeSupported = false;
+ var codecSupported = false;
+
+ test(function() {
+ // Spec: Generally, a user agent should never return "probably" for a type
+ // that allows the codecs parameter if that parameter is not present.
+ t(type, 'maybe');
+ typeSupported = true;
+ }, type + ' (optional)');
+
+ function test_codec(codec) {
+ var typeWithCodec = mime(type, [codec]);
+ test(function() {
+ t(typeWithCodec, 'probably');
+ codecSupported = true;
+ }, typeWithCodec + ' (optional)');
+ }
+
+ audioCodecs.forEach(test_codec);
+ videoCodecs.forEach(test_codec);
+
+ if (audioCodecs.length > 0 && videoCodecs.length > 0) {
+ test(function() {
+ audioCodecs.forEach(function(ac) {
+ videoCodecs.forEach(function(vc) {
+ var canPlayBoth = canPlayType(mime(type, [ac, vc]));
+ if (canPlayBoth) {
+ t(mime(type, [ac]), canPlayBoth);
+ t(mime(type, [vc]), canPlayBoth);
+ }
+ });
+ });
+ }, type + ' codecs subset');
+
+ test(function() {
+ audioCodecs.forEach(function(ac) {
+ videoCodecs.forEach(function(vc) {
+ assert_equals(canPlayType(mime(type, [ac, vc])),
+ canPlayType(mime(type, [vc, ac])));
+ });
+ });
+ }, type + ' codecs order');
+ }
+
+ test(function() {
+ t(mime(type, ['bogus']), '');
+ }, type + ' with bogus codec');
+
+ test(function() {
+ // At least one known codec must be supported if the container format is.
+ assert_equals(typeSupported, codecSupported);
+ }, type + ' with and without codecs');
+}
+
+type_codecs_test('audio/mp4', ['mp4a.40.2'], []);
+type_codecs_test('audio/ogg', ['opus', 'vorbis'], []);
+type_codecs_test('audio/wav', ['1'], []);
+type_codecs_test('audio/webm', ['opus', 'vorbis'], []);
+type_codecs_test('video/3gpp', ['samr'], ['mp4v.20.8']);
+type_codecs_test('video/mp4', ['mp4a.40.2'], ['avc1.42E01E', 'avc1.4D401E', 'avc1.58A01E', 'avc1.64001E', 'mp4v.20.8', 'mp4v.20.240']);
+type_codecs_test('video/ogg', ['opus', 'vorbis'], ['theora']);
+type_codecs_test('video/webm', ['opus', 'vorbis'], ['vp8', 'vp8.0', 'vp9', 'vp9.0']);
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/networkState_during_loadstart.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/networkState_during_loadstart.html
new file mode 100644
index 00000000000..8f0fffc612a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/networkState_during_loadstart.html
@@ -0,0 +1,42 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video}.networkState - NETWORK_LOADING</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#dom-media-networkstate">spec reference</a></p>
+ <audio id="a" autoplay controls>
+ </audio>
+ <video id="v" autoplay controls>
+ </video>
+ <div id="log"></div>
+ <script>
+var ta = async_test("audioElement.networkState should be NETWORK_LOADING during loadstart event", {timeout:5000});
+var a = document.getElementById("a");
+a.addEventListener("loadstart", function() {
+ ta.step(function() {
+ assert_equals(a.networkState,
+ a.NETWORK_LOADING);
+ });
+ ta.done();
+ a.pause();
+}, false);
+a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+
+var tv = async_test("videoElement.networkState should be NETWORK_LOADING during loadstart event", {timeout:5000});
+var v = document.getElementById("v");
+v.addEventListener("loadstart", function() {
+ tv.step(function() {
+ assert_equals(a.networkState,
+ v.NETWORK_LOADING);
+ });
+ tv.done();
+ v.pause();
+}, false);
+v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/networkState_during_progress.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/networkState_during_progress.html
new file mode 100644
index 00000000000..cf23e822cab
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/networkState_during_progress.html
@@ -0,0 +1,42 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video}.networkState - NETWORK_LOADING</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#dom-media-networkstate">spec reference</a></p>
+ <audio id="a" autoplay controls>
+ </audio>
+ <video id="v" autoplay controls>
+ </video>
+ <div id="log"></div>
+ <script>
+var ta = async_test("audioElement.networkState should be NETWORK_LOADING during progress event", {timeout:5000});
+var a = document.getElementById("a");
+a.addEventListener("progress", function() {
+ ta.step(function() {
+ assert_equals(a.networkState,
+ a.NETWORK_LOADING);
+ });
+ ta.done();
+ a.pause();
+}, false);
+a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+
+var tv = async_test("videoElement.networkState should be NETWORK_LOADING during progress event", {timeout:5000});
+var v = document.getElementById("v");
+v.addEventListener("progress", function() {
+ tv.step(function() {
+ assert_equals(v.networkState,
+ v.NETWORK_LOADING);
+ });
+ tv.done();
+ v.pause();
+}, false);
+v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/networkState_initial.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/networkState_initial.html
new file mode 100644
index 00000000000..0a203e65427
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/networkState_initial.html
@@ -0,0 +1,33 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video}.networkState - default state</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#dom-media-networkstate">spec reference</a></p>
+ <audio id="a">
+ </audio>
+ <video id="v">
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var a = document.getElementById("a");
+ assert_equals(
+ a.networkState,
+ a.NETWORK_EMPTY,
+ "audioElement.networkState should be NETWORK_EMPTY to begin with");
+}, "audio.networkState - default state");
+
+test(function() {
+ var v = document.getElementById("v");
+ assert_equals(
+ v.networkState,
+ v.NETWORK_EMPTY,
+ "videoElement.networkState should be NETWORK_EMPTY to begin with");
+}, "video.networkState - default state");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/offsets-into-the-media-resource/currentTime.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/offsets-into-the-media-resource/currentTime.html
new file mode 100644
index 00000000000..0dce7c5569a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/offsets-into-the-media-resource/currentTime.html
@@ -0,0 +1,40 @@
+<!doctype html>
+<title>currentTime</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/media.js"></script>
+<div id=log></div>
+<script>
+test(function() {
+ var v = document.createElement('video');
+ assert_equals(v.currentTime, 0);
+}, 'currentTime initial value');
+
+test(function() {
+ var v = document.createElement('video');
+ v.controller = new MediaController();
+ assert_true(v.controller instanceof MediaController);
+ assert_throws('InvalidStateError', function() { v.currentTime = 1; });
+ assert_false(v.seeking);
+}, 'setting currentTime with a media controller present');
+
+test(function() {
+ var v = document.createElement('video');
+ assert_equals(v.readyState, v.HAVE_NOTHING);
+ v.currentTime = Number.MAX_VALUE;
+ assert_equals(v.currentTime, Number.MAX_VALUE);
+ assert_false(v.seeking);
+}, 'setting currentTime when readyState is HAVE_NOTHING');
+
+async_test(function(t) {
+ var v = document.createElement('video');
+ v.src = getVideoURI('/media/movie_5');
+ v.onloadedmetadata = t.step_func(function() {
+ assert_greater_than(v.readyState, v.HAVE_NOTHING);
+ assert_false(v.seeking);
+ v.currentTime = 1;
+ assert_true(v.seeking);
+ t.done();
+ });
+}, 'setting currentTime when readyState is greater than HAVE_NOTHING');
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/offsets-into-the-media-resource/duration.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/offsets-into-the-media-resource/duration.html
new file mode 100644
index 00000000000..0ac26eddb93
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/offsets-into-the-media-resource/duration.html
@@ -0,0 +1,11 @@
+<!doctype html>
+<title>duration</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+test(function() {
+ var v = document.createElement('video');
+ assert_true(isNaN(v.duration));
+}, 'duration initial value');
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/paused_false_during_play.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/paused_false_during_play.html
new file mode 100644
index 00000000000..28c563333fa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/paused_false_during_play.html
@@ -0,0 +1,44 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - paused property</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" autoplay controls>
+ </audio>
+ <video id="v" autoplay controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var t = async_test("audio.paused should be false during play event", {timeout:5000});
+ var a = document.getElementById("a");
+ a.addEventListener("play", function() {
+ t.step(function() {
+ assert_false(a.paused);
+ });
+ t.done();
+ a.pause();
+ }, false);
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+}, "audio events - paused property");
+
+test(function() {
+ var t = async_test("video.paused should be false during play event", {timeout:5000});
+ var v = document.getElementById("v");
+ v.addEventListener("play", function() {
+ t.step(function() {
+ assert_false(v.paused);
+ });
+ t.done();
+ v.pause();
+ }, false);
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+}, "video events - paused property");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/paused_true_during_pause.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/paused_true_during_pause.html
new file mode 100644
index 00000000000..6c4eb7c0c09
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/paused_true_during_pause.html
@@ -0,0 +1,46 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - paused property</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" controls>
+ </audio>
+ <video id="v" controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var t = async_test("audio.paused should be true during pause event", {timeout:5000});
+ var a = document.getElementById("a");
+ a.addEventListener("pause", function() {
+ t.step(function() {
+ assert_true(a.paused);
+ });
+ t.done();
+ }, false);
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+ a.play();
+ a.pause();
+}, "audio events - paused property");
+
+test(function() {
+ var t = async_test("video.paused should be true during pause event", {timeout:5000});
+ var v = document.getElementById("v");
+ v.addEventListener("pause", function() {
+ t.step(function() {
+ assert_true(v.paused);
+ });
+ t.done();
+ }, false);
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+ v.play();
+ v.pause();
+}, "video events - paused property");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/pause-move-to-other-document.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/pause-move-to-other-document.html
new file mode 100644
index 00000000000..342771dbd5b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/pause-move-to-other-document.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<title>paused state when moving to other document</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/media.js"></script>
+<div id="log"></div>
+<video hidden></video>
+<iframe hidden></iframe>
+<script>
+async_test(function(t) {
+ var v = document.querySelector('video');
+ v.src = getVideoURI('/media/movie_300');
+ v.play();
+ v.onplaying = t.step_func(function() {
+ assert_false(v.paused, 'paused after playing');
+ document.querySelector('iframe').contentDocument.body.appendChild(v);
+ assert_false(v.paused, 'paused after moving');
+ setTimeout(t.step_func(function() {
+ assert_false(v.paused, 'paused after stable state')
+ t.done();
+ }), 0);
+ });
+ v.onpause = t.step_func(function() { assert_unreached(); });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/pause-move-within-document.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/pause-move-within-document.html
new file mode 100644
index 00000000000..a28322d4d5b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/pause-move-within-document.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<title>paused state when moving within a document</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/media.js"></script>
+<div id="log"></div>
+<video hidden></video>
+<div id="elsewhere"></div>
+<script>
+async_test(function(t) {
+ var v = document.querySelector('video');
+ v.src = getVideoURI('/media/movie_300');
+ v.play();
+ v.onplaying = t.step_func(function() {
+ assert_false(v.paused, 'paused after playing');
+ document.getElementById('elsewhere').appendChild(v);
+ assert_false(v.paused, 'paused after moving');
+ setTimeout(t.step_func(function() {
+ assert_false(v.paused, 'paused after stable state')
+ t.done();
+ }), 0);
+ });
+ v.onpause = t.step_func(function() { assert_unreached(); });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/pause-remove-from-document-networkState.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/pause-remove-from-document-networkState.html
new file mode 100644
index 00000000000..3b5849a351d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/pause-remove-from-document-networkState.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<title>paused state when removing from a document when networkState is NETWORK_EMPTY</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<video hidden></video>
+<script>
+// Negative test for the specified behavior prior to HTML r8447.
+async_test(function(t) {
+ var v = document.querySelector('video');
+ v.play();
+ setTimeout(t.step_func(function() {
+ assert_equals(v.networkState, v.NETWORK_EMPTY,
+ 'networkState after stable state');
+ assert_false(v.paused, 'paused after stable state');
+ v.parentNode.removeChild(v);
+ assert_false(v.paused, 'paused after removing');
+ v.onpause = t.step_func(function() { t.done(); });
+ }), 0);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/pause-remove-from-document.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/pause-remove-from-document.html
new file mode 100644
index 00000000000..7a4b0bc0d22
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/pause-remove-from-document.html
@@ -0,0 +1,37 @@
+<!doctype html>
+<title>paused state when removing from a document</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/media.js"></script>
+<div id="log"></div>
+<video hidden></video>
+<script>
+function afterStableState(func) {
+ var a = new Audio();
+ a.volume = 0;
+ a.addEventListener('volumechange', func);
+}
+
+async_test(function(t) {
+ var v = document.querySelector('video');
+ v.src = getVideoURI('/media/movie_300');
+ v.play();
+ v.onplaying = t.step_func(function() {
+ assert_false(v.paused, 'paused after playing');
+ v.parentNode.removeChild(v);
+ assert_false(v.paused, 'paused after removing');
+ afterStableState(t.step_func(function() {
+ assert_true(v.paused, 'paused after stable state');
+ v.onpause = t.step_func(function() {
+ assert_true(v.paused, 'paused in pause event');
+ // re-insert and verify that it stays paused
+ document.body.appendChild(v);
+ setTimeout(t.step_func(function() {
+ assert_true(v.paused, 'paused after re-inserting');
+ t.done();
+ }), 0);
+ });
+ }));
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/play-in-detached-document.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/play-in-detached-document.html
new file mode 100644
index 00000000000..9c6fd5fabc3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/play-in-detached-document.html
@@ -0,0 +1,23 @@
+<!doctype html>
+<title>play() in detached document</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/media.js"></script>
+<div id="log"></div>
+<script>
+// Negative test for failure to play in a detached document.
+async_test(function(t)
+{
+ var doc = document.implementation.createHTMLDocument("");
+ var v = doc.createElement("video");
+ doc.body.appendChild(v);
+ v.src = getVideoURI("/media/movie_5");
+ v.play();
+ v.addEventListener("timeupdate", t.step_func(function() {
+ assert_false(v.paused);
+ if (v.currentTime > 0) {
+ t.done();
+ }
+ }));
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/playbackRate.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/playbackRate.html
new file mode 100644
index 00000000000..fa11d9944a6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/playing-the-media-resource/playbackRate.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<title>playbackRate</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+test(function() {
+ var v = document.createElement('video');
+ assert_equals(v.playbackRate, 1);
+}, 'playbackRate initial value');
+
+async_test(function(t) {
+ var v = document.createElement('video');
+ v.playbackRate = 2;
+ v.addEventListener('ratechange', t.step_func(function() {
+ t.done();
+ }));
+}, 'setting playbackRate');
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/preload_reflects_none_autoplay.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/preload_reflects_none_autoplay.html
new file mode 100644
index 00000000000..2670b0dd813
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/preload_reflects_none_autoplay.html
@@ -0,0 +1,31 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video}.preload - reflection test</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#dom-media-preload">spec reference</a></p>
+ <audio id="audio" autoplay preload="none">
+ </audio>
+ <video id="video" autoplay preload="none">
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ assert_equals(
+ document.getElementById("audio").preload,
+ "none",
+ "audioElement.preload reflects 'none' value even if autoplay attribute is present");
+}, "audio.preload - reflection test");
+
+test(function() {
+ assert_equals(
+ document.getElementById("video").preload,
+ "none",
+ "videoElement.preload reflects 'none' value even if autoplay attribute is present");
+}, "video.preload - reflection test");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/ready-states/autoplay.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/ready-states/autoplay.html
new file mode 100644
index 00000000000..76aef1dbcc9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/ready-states/autoplay.html
@@ -0,0 +1,73 @@
+<!doctype html>
+<title>autoplay</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/media.js"></script>
+<div id="log"></div>
+<script>
+function autoplay_test(tagName, src) {
+ function expect_events(t, e, expected_events) {
+ var actual_events = [];
+ var callback = t.step_func(function(ev) {
+ actual_events.push(ev.type);
+ assert_array_equals(actual_events,
+ expected_events.slice(0, actual_events.length));
+ if (expected_events.length == actual_events.length) {
+ t.done();
+ }
+ });
+ ['canplay', 'canplaythrough',
+ 'pause', 'play', 'playing'].forEach(function(type) {
+ e.addEventListener(type, callback);
+ });
+ }
+
+ async_test(function(t) {
+ var e = document.createElement(tagName);
+ e.src = src;
+ e.autoplay = true;
+ expect_events(t, e, ['canplay', 'play', 'playing', 'canplaythrough']);
+ }, tagName + '.autoplay');
+
+ async_test(function(t) {
+ var e = document.createElement(tagName);
+ e.src = src;
+ e.autoplay = true;
+ e.pause(); // sets the autoplaying flag to false
+ e.load(); // sets the autoplaying flag to true
+ expect_events(t, e, ['canplay', 'play', 'playing', 'canplaythrough']);
+ }, tagName + '.autoplay and load()');
+
+ async_test(function(t) {
+ var e = document.createElement(tagName);
+ e.src = src;
+ e.autoplay = true;
+ e.play(); // sets the autoplaying flag to false
+ // play() also sets the paused attribute to false; there is no way for the
+ // autoplaying flag to be true when the paused attribute is false.
+ assert_equals(e.paused, false);
+ expect_events(t, e, ['play', 'canplay', 'playing', 'canplaythrough']);
+ }, tagName + '.autoplay and play()');
+
+ async_test(function(t) {
+ var e = document.createElement(tagName);
+ e.src = src;
+ e.autoplay = true;
+ e.pause(); // sets the autoplaying flag to false
+ expect_events(t, e, ['canplay', 'canplaythrough']);
+ }, tagName + '.autoplay and pause()');
+
+ async_test(function(t) {
+ var e = document.createElement(tagName);
+ e.src = src;
+ e.autoplay = true;
+ document.body.appendChild(e);
+ document.body.removeChild(e);
+ // in stable state, internal pause steps sets the autoplaying flag to false
+ expect_events(t, e, ['canplay', 'canplaythrough']);
+ }, tagName + '.autoplay and internal pause steps');
+}
+
+autoplay_test('audio', getAudioURI('/media/sound_5'));
+autoplay_test('video', getVideoURI('/media/movie_5'));
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/readyState_during_canplay.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/readyState_during_canplay.html
new file mode 100644
index 00000000000..09ad89f8bfd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/readyState_during_canplay.html
@@ -0,0 +1,44 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - readyState property during canplay</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" autoplay controls>
+ </audio>
+ <video id="v" autoplay controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var t = async_test("audio.readyState should be >= HAVE_FUTURE_DATA during canplay event", {timeout:5000});
+ var a = document.getElementById("a");
+ a.addEventListener("canplay", function() {
+ t.step(function() {
+ assert_greater_than_equal(a.readyState, a.HAVE_FUTURE_DATA);
+ });
+ t.done();
+ a.pause();
+ }, false);
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+}, "audio events - readyState property during canplay");
+
+test(function() {
+ var t = async_test("video.readyState should be >= HAVE_FUTURE_DATA during canplay event", {timeout:5000});
+ var v = document.getElementById("v");
+ v.addEventListener("canplay", function() {
+ t.step(function() {
+ assert_greater_than_equal(v.readyState, v.HAVE_FUTURE_DATA);
+ });
+ t.done();
+ v.pause();
+ }, false);
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+}, "video events - readyState property during canplay");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/readyState_during_canplaythrough.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/readyState_during_canplaythrough.html
new file mode 100644
index 00000000000..7ef7b5f74fa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/readyState_during_canplaythrough.html
@@ -0,0 +1,46 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - readyState property during canplaythrough</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" autoplay controls>
+ </audio>
+ <video id="v" autoplay controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var t = async_test("audio.readyState should be HAVE_ENOUGH_DATA during canplaythrough event", {timeout:5000});
+ var a = document.getElementById("a");
+ a.addEventListener("canplaythrough", function() {
+ t.step(function() {
+ assert_equals(a.readyState,
+ a.HAVE_ENOUGH_DATA);
+ });
+ t.done();
+ a.pause();
+ }, false);
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+}, "audio events - readyState property during canplaythrough");
+
+test(function() {
+ var t = async_test("video.readyState should be HAVE_ENOUGH_DATA during canplaythrough event", {timeout:5000});
+ var v = document.getElementById("v");
+ v.addEventListener("canplaythrough", function() {
+ t.step(function() {
+ assert_equals(v.readyState,
+ v.HAVE_ENOUGH_DATA);
+ });
+ t.done();
+ v.pause();
+ }, false);
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+}, "video events - readyState property during canplaythrough");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/readyState_during_loadeddata.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/readyState_during_loadeddata.html
new file mode 100644
index 00000000000..1de85eb86ad
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/readyState_during_loadeddata.html
@@ -0,0 +1,44 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - readyState property during loadeddata</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" autoplay controls>
+ </audio>
+ <video id="v" autoplay controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var t = async_test("audio.readyState should be >= HAVE_CURRENT_DATA during loadeddata event", {timeout:5000});
+ var a = document.getElementById("a");
+ a.addEventListener("loadeddata", function() {
+ t.step(function() {
+ assert_greater_than_equal(a.readyState, a.HAVE_CURRENT_DATA);
+ });
+ t.done();
+ a.pause();
+ }, false);
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+}, "audio events - readyState property during loadeddata");
+
+test(function() {
+ var t = async_test("video.readyState should be >= HAVE_CURRENT_DATA during loadeddata event", {timeout:5000});
+ var v = document.getElementById("v");
+ v.addEventListener("loadeddata", function() {
+ t.step(function() {
+ assert_greater_than_equal(v.readyState, v.HAVE_CURRENT_DATA);
+ });
+ t.done();
+ v.pause();
+ }, false);
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+}, "video events - readyState property during loadeddata");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/readyState_during_loadedmetadata.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/readyState_during_loadedmetadata.html
new file mode 100644
index 00000000000..85db8afb7b4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/readyState_during_loadedmetadata.html
@@ -0,0 +1,44 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - readyState property during loadedmetadata</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" autoplay controls>
+ </audio>
+ <video id="v" autoplay controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var t = async_test("audio.readyState should be >= HAVE_METADATA during loadedmetadata event", {timeout:5000});
+ var a = document.getElementById("a");
+ a.addEventListener("loadedmetadata", function() {
+ t.step(function() {
+ assert_greater_than_equal(a.readyState, a.HAVE_METADATA);
+ });
+ t.done();
+ a.pause();
+ }, false);
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+}, "audio events - readyState property during loadedmetadata");
+
+test(function() {
+ var t = async_test("video.readyState should be >= HAVE_METADATA during loadedmetadata event", {timeout:5000});
+ var v = document.getElementById("v");
+ v.addEventListener("loadedmetadata", function() {
+ t.step(function() {
+ assert_greater_than_equal(v.readyState, v.HAVE_METADATA);
+ });
+ t.done();
+ v.pause();
+ }, false);
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+}, "video events - readyState property during loadedmetadata");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/readyState_during_playing.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/readyState_during_playing.html
new file mode 100644
index 00000000000..92a1b7f50a6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/readyState_during_playing.html
@@ -0,0 +1,44 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video} events - readyState property during playing</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#mediaevents">spec reference</a></p>
+ <audio id="a" autoplay controls>
+ </audio>
+ <video id="v" autoplay controls>
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var t = async_test("audio.readyState should be >= HAVE_FUTURE_DATA during playing event", {timeout:5000});
+ var a = document.getElementById("a");
+ a.addEventListener("playing", function() {
+ t.step(function() {
+ assert_greater_than_equal(a.readyState, a.HAVE_FUTURE_DATA);
+ });
+ t.done();
+ a.pause();
+ }, false);
+ a.src = getAudioURI("/media/sound_5") + "?" + new Date() + Math.random();
+}, "audio events - readyState property during playing");
+
+test(function() {
+ var t = async_test("video.readyState should be >= HAVE_FUTURE_DATA during playing event", {timeout:5000});
+ var v = document.getElementById("v");
+ v.addEventListener("playing", function() {
+ t.step(function() {
+ assert_greater_than_equal(v.readyState, v.HAVE_FUTURE_DATA);
+ });
+ t.done();
+ v.pause();
+ }, false);
+ v.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+}, "video events - readyState property during playing");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/readyState_initial.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/readyState_initial.html
new file mode 100644
index 00000000000..e9c112bd247
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/readyState_initial.html
@@ -0,0 +1,33 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video}.readyState - default state</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#dom-media-networkstate">spec reference</a></p>
+ <audio id="a">
+ </audio>
+ <video id="v">
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ var a = document.getElementById("a");
+ assert_equals(
+ a.readyState,
+ a.HAVE_NOTHING,
+ "audioElement.readyState should be HAVE_NOTHING to begin with");
+}, "audio.readyState - default state");
+
+test(function() {
+ var v = document.getElementById("v");
+ assert_equals(
+ v.readyState,
+ v.HAVE_NOTHING,
+ "videoElement.readyState should be HAVE_NOTHING to begin with");
+}, "video.readyState - default state");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/seeking/seek-to-currentTime.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/seeking/seek-to-currentTime.html
new file mode 100644
index 00000000000..3d577dac97f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/seeking/seek-to-currentTime.html
@@ -0,0 +1,33 @@
+<!doctype html>
+<title>seek to currentTime</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/media.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var v = document.createElement('video');
+ v.src = getVideoURI('/media/movie_5');
+ v.onloadedmetadata = t.step_func(function() {
+ assert_greater_than(v.readyState, v.HAVE_NOTHING, 'readyState');
+ assert_greater_than(v.seekable.length, 0, 'seekable ranges');
+ assert_false(v.seeking, 'seeking before setting currentTime');
+ v.currentTime = v.currentTime;
+ assert_true(v.seeking, 'seeking after setting currentTime');
+ var events = [];
+ v.onseeking = v.ontimeupdate = v.onseeked = t.step_func(function(e) {
+ events.push(e.type);
+ // v.seeking can be true or false in the seeking event, see
+ // https://www.w3.org/Bugs/Public/show_bug.cgi?id=24774
+ if (e.type != 'seeking') {
+ assert_equals(v.seeking, false, 'seeking in ' + e.type + ' event');
+ }
+ if (e.type == 'seeked') {
+ assert_array_equals(events, ['seeking', 'timeupdate', 'seeked'],
+ 'fired events');
+ t.done();
+ }
+ });
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/seeking/seek-to-max-value.htm b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/seeking/seek-to-max-value.htm
new file mode 100644
index 00000000000..a31f6c07ab0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/seeking/seek-to-max-value.htm
@@ -0,0 +1,23 @@
+<!doctype html>
+<title>seek to Number.MAX_VALUE</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/media.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var v = document.createElement('video');
+ v.src = getVideoURI('/media/movie_5');
+ v.onloadedmetadata = t.step_func(function() {
+ assert_equals(v.seekable.length, 1);
+ v.currentTime = Number.MAX_VALUE;
+ assert_true(v.seeking, 'seeking after setting');
+ assert_equals(v.currentTime, v.seekable.end(0), 'currentTime after setting');
+ v.onseeked = t.step_func(function(e) {
+ assert_false(v.seeking, 'seeking in seeked event');
+ assert_equals(v.currentTime, v.seekable.end(0), 'currentTime in seeked event');
+ t.done();
+ });
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/seeking/seek-to-negative-time.htm b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/seeking/seek-to-negative-time.htm
new file mode 100644
index 00000000000..56a99028deb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/seeking/seek-to-negative-time.htm
@@ -0,0 +1,23 @@
+<!doctype html>
+<title>seek to negative time</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/media.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var v = document.createElement('video');
+ v.src = getVideoURI('/media/movie_5');
+ v.onloadedmetadata = t.step_func(function() {
+ assert_equals(v.seekable.start(0), 0, 'earliest seekable time');
+ v.currentTime = -1;
+ assert_true(v.seeking, 'seeking after setting');
+ assert_equals(v.currentTime, 0, 'currentTime after setting');
+ v.onseeked = t.step_func(function(e) {
+ assert_false(v.seeking, 'seeking in seeked event');
+ assert_equals(v.currentTime, 0, 'currentTime in seeked event');
+ t.done();
+ });
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/src_reflects_attribute_not_source_elements.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/src_reflects_attribute_not_source_elements.html
new file mode 100644
index 00000000000..3dd43cc3f55
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/src_reflects_attribute_not_source_elements.html
@@ -0,0 +1,33 @@
+<!doctype html>
+<html>
+ <head>
+ <title>{audio,video}.src - reflection test</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <p><a href="https://html.spec.whatwg.org/multipage/#dom-media-src">spec reference</a></p>
+ <audio id="audio" src="foo">
+ <source src="barbaz" />
+ </audio>
+ <video id="video" src="foo">
+ <source src="barbaz" />
+ </video>
+ <div id="log"></div>
+ <script>
+test(function() {
+ assert_equals(
+ document.getElementById("audio").src.indexOf("barbaz"),
+ -1,
+ "audioElement.src should reflect src attribute, not source child elements");
+}, "audio.src - reflection test");
+
+test(function() {
+ assert_equals(
+ document.getElementById("video").src.indexOf("barbaz"),
+ -1,
+ "videoElement.src should reflect src attribute, not source child elements");
+}, "video.src - reflection test");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/synchronising-multiple-media-elements/media-controllers/task-source.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/synchronising-multiple-media-elements/media-controllers/task-source.html
new file mode 100644
index 00000000000..798890da6e6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/synchronising-multiple-media-elements/media-controllers/task-source.html
@@ -0,0 +1,27 @@
+<!doctype html>
+<title>MediaController events task source</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function(t) {
+ // Both MediaControllers should use the DOM manipulation task source, so the
+ // events should fire in the same order as the attributes are modified.
+ var mc1 = new MediaController();
+ var mc2 = new MediaController();
+ mc1.volume = 0;
+ mc2.volume = 0;
+ mc1.volume = 1;
+ mc2.volume = 1;
+ var targets = [];
+ var callback = t.step_func(function(event) {
+ targets.push(event.target);
+ if (targets.length == 4) {
+ assert_array_equals(targets, [mc1, mc2, mc1, mc2]);
+ t.done();
+ }
+ });
+ mc1.addEventListener('volumechange', callback);
+ mc2.addEventListener('volumechange', callback);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cloneNode.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cloneNode.html
new file mode 100644
index 00000000000..1159a52ff1f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cloneNode.html
@@ -0,0 +1,86 @@
+<!doctype html>
+<title>track element cloneNode</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+test(function() {
+ var elm = document.createElement('track');
+ assert_equals(elm.readyState, elm.NONE, 'elm.readyState after element creation');
+ var clone = elm.cloneNode(true);
+ assert_equals(clone.readyState, clone.NONE, 'clone.readyState after element creation');
+ assert_not_equals(clone.track, elm.track, 'clone.track and elm.track');
+}, document.title+', not loaded');
+
+async_test(function(t) {
+ var elm = document.createElement('track');
+ var video = document.createElement('video');
+ video.appendChild(elm);
+ elm.track.mode = 'showing';
+ assert_equals(elm.readyState, elm.NONE, 'elm.readyState after appening to video setting mode');
+ elm.src = 'resources/track.vtt?pipe=trickle(d1)';
+ assert_equals(elm.readyState, elm.NONE, 'elm.readyState after setting src');
+ setTimeout(t.step_func_done(function() {
+ assert_equals(elm.readyState, elm.LOADING, 'elm.readyState in setTimeout');
+ var clone = elm.cloneNode(true);
+ assert_equals(clone.readyState, clone.NONE, 'clone.readyState after element creation');
+ video.appendChild(clone);
+ clone.track.mode = 'showing';
+ assert_equals(clone.readyState, clone.NONE, 'clone.readyState after appending to video and setting mode');
+ assert_not_equals(clone.track, elm.track, 'clone.track and elm.track');
+ }), 0);
+}, document.title+', loading');
+
+async_test(function(t) {
+ var elm = document.createElement('track');
+ var video = document.createElement('video');
+ video.appendChild(elm);
+ elm.track.mode = 'showing';
+ elm.src = 'data:text/vtt,'+encodeURIComponent('WEBVTT\n\n00:00:00.000 --> 00:00:01.000\nfoo');
+ assert_equals(elm.readyState, elm.NONE, 'elm.readyState after setting src');
+ elm.onload = this.step_func(function() {
+ assert_equals(elm.readyState, elm.LOADED, 'elm.readyState');
+ assert_equals(elm.track.cues.length, 1, 'elm.track.cues.length');
+ assert_equals(elm.track.cues[0].startTime, 0, 'elm.track.cues[0].startTime');
+ assert_equals(elm.track.cues[0].endTime, 1, 'elm.track.cues[0].endTime');
+ assert_equals(elm.track.cues[0].text, 'foo', 'elm.track.cues[0].text');
+ var clone = elm.cloneNode(true);
+ assert_equals(clone.readyState, clone.NONE, 'clone.readyState after element creation');
+ video.appendChild(clone);
+ clone.track.mode = 'showing';
+ assert_equals(clone.readyState, clone.NONE, 'clone.readyState after appending to video and setting mode');
+ assert_not_equals(clone.track, elm.track, 'clone.track and elm.track');
+ clone.onload = this.step_func(function(){
+ assert_equals(clone.readyState, clone.LOADED, 'clone.readyState');
+ assert_not_equals(clone.track, elm.track, 'clone.track and elm.track');
+ assert_not_equals(clone.track.cues, elm.track.cues, 'clone.track.cues and elm.track.cues');
+ assert_equals(clone.track.cues.length, 1, 'clone.track.cues.length');
+ assert_not_equals(clone.track.cues[0], elm.track.cues[0], 'cues[0]');
+ assert_equals(clone.track.cues[0].startTime, 0, 'clone.track.cues[0].startTime');
+ assert_equals(clone.track.cues[0].endTime, 1, 'clone.track.cues[0].endTime');
+ assert_equals(clone.track.cues[0].text, 'foo', 'clone.track.cues[0].text');
+ this.done();
+ });
+ clone.onerror = this.step_func(function() { assert_unreached('clone got error'); });
+ });
+ elm.onerror = this.step_func(function() { assert_unreached('elm got error'); });
+}, document.title+', loaded');
+
+async_test(function(t) {
+ var elm = document.createElement('track');
+ var video = document.createElement('video');
+ video.appendChild(elm);
+ elm.track.mode = 'showing';
+ elm.onerror = t.step_func(function() {
+ assert_equals(elm.readyState, elm.ERROR, 'elm.readyState in onerror');
+ var clone = elm.cloneNode(true);
+ assert_equals(clone.readyState, clone.NONE, 'clone.readyState after element creation');
+ video.appendChild(clone);
+ clone.track.mode = 'showing';
+ assert_equals(clone.readyState, clone.NONE, 'clone.readyState after appending to video and setting mode');
+ assert_not_equals(clone.track, elm.track, 'clone.track and elm.track');
+ clone.onerror = t.step_func_done();
+ });
+ elm.src = 'javascript:"network error"';
+}, document.title+', failed to load');
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/003.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/003.html
new file mode 100644
index 00000000000..4236df29b91
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/003.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: No CORS, same-origin, no headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'load', requests:[{cors:'no', cookie:'yes'}]};
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/004.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/004.html
new file mode 100644
index 00000000000..4f86d011a30
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/004.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: No CORS, same-origin, with headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'load', requests:[{cors:'no', cookie:'yes'}]};
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/005.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/005.html
new file mode 100644
index 00000000000..e6a693400c1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/005.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Anonymous, same-origin, no headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'load', requests:[{cors:'no', cookie:'yes'}]};
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/006.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/006.html
new file mode 100644
index 00000000000..351b97d6775
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/006.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Anonymous, same-origin, with headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'load', requests:[{cors:'no', cookie:'yes'}]};
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/007.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/007.html
new file mode 100644
index 00000000000..4ccc6b66ac9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/007.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Use Credentials, same-origin, no headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'load', requests:[{cors:'no', cookie:'yes'}]};
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/008.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/008.html
new file mode 100644
index 00000000000..0444a83085f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/008.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Use Credentials, same-origin, with headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'load', requests:[{cors:'no', cookie:'yes'}]};
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/009.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/009.html
new file mode 100644
index 00000000000..dd622327554
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/009.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: No CORS, not same-origin, no headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'error', requests:[]};
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/010.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/010.html
new file mode 100644
index 00000000000..d75d6f4d6da
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/010.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Anonymous, not same-origin, no headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'error', requests:[{cors:origin, cookie:'no'}]};
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/011.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/011.html
new file mode 100644
index 00000000000..6d0fae6de73
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/011.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Anonymous, not same-origin, with headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'load', requests:[{cors:origin, cookie:'no'}]};
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/012.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/012.html
new file mode 100644
index 00000000000..110497b494b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/012.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Use Credentials, not same-origin, no headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'error', requests:[{cors:origin, cookie:'yes'}]};
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/013.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/013.html
new file mode 100644
index 00000000000..d2a9ddb193f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/013.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Use Credentials, not same-origin, with headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'load', requests:[{cors:origin, cookie:'yes'}]};
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/014.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/014.html
new file mode 100644
index 00000000000..a1d6a8b2957
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/014.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: No CORS, same-origin, no headers, redirects to same-origin, no headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'load', requests:[{cors:'no', cookie:'yes'}, {cors:'no', cookie:'yes'}]};
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/015.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/015.html
new file mode 100644
index 00000000000..2850a24e17e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/015.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: No CORS, same-origin, with headers, redirects to same-origin, with headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'load', requests:[{cors:'no', cookie:'yes'}, {cors:'no', cookie:'yes'}]};
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/016.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/016.html
new file mode 100644
index 00000000000..5cd5a85d431
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/016.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Anonymous, same-origin, no headers, redirects to same-origin, no headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'load', requests:[{cors:'no', cookie:'yes'}, {cors:'no', cookie:'yes'}]};
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/017.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/017.html
new file mode 100644
index 00000000000..0ec5bc32910
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/017.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Anonymous, same-origin, no headers, redirects to same-origin, with headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'load', requests:[{cors:'no', cookie:'yes'}, {cors:'no', cookie:'yes'}]};
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/018.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/018.html
new file mode 100644
index 00000000000..f639d043a31
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/018.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Use Credentials, same-origin, no headers, redirects to same-origin, no headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'load', requests:[{cors:'no', cookie:'yes'}, {cors:'no', cookie:'yes'}]};
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/019.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/019.html
new file mode 100644
index 00000000000..45e1291c923
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/019.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Use Credentials, same-origin, with headers, redirects to same-origin, no headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'load', requests:[{cors:'no', cookie:'yes'}, {cors:'no', cookie:'yes'}]};
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/020.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/020.html
new file mode 100644
index 00000000000..e1153b6813e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/020.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Anonymous, not same-origin, no headers, redirects to same-origin, no headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'error', requests:[{cors:origin, cookie:'no'}]}; // redirect not followed
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/021.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/021.html
new file mode 100644
index 00000000000..ec2e9d8bb41
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/021.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Anonymous, not same-origin, with headers, redirects to same-origin, no headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'error', requests:[{cors:origin, cookie:'no'}, {cors:'null', cookie:'no'}]};
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/022.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/022.html
new file mode 100644
index 00000000000..e8fb0c3d438
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/022.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Anonymous, not same-origin, with headers, redirects to same-origin, with headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'load', requests:[{cors:origin, cookie:'no'}, {cors:'null', cookie:'no'}]};
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/023.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/023.html
new file mode 100644
index 00000000000..ac9bb354655
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/023.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Use Credentials, not same-origin, no headers, redirects to same-origin, no headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'error', requests:[{cors:origin, cookie:'yes'}]}; // redirect not followed
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/024.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/024.html
new file mode 100644
index 00000000000..302340022d3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/024.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Use Credentials, not same-origin, with headers, redirects to same-origin, no headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'error', requests:[{cors:origin, cookie:'yes'}, {cors:'null', cookie:'yes'}]};
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/025.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/025.html
new file mode 100644
index 00000000000..5cbe8528e26
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/025.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Use Credentials, not same-origin, with headers, redirects to same-origin, with headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'load', requests:[{cors:origin, cookie:'yes'}, {cors:'null', cookie:'yes'}]};
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/026.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/026.html
new file mode 100644
index 00000000000..c8386ffff3e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/026.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: No CORS, same-origin, with headers, redirects to not same-origin, with headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'error', requests:[{cors:'no', cookie:'yes'}]}; // redirect not followed
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/027.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/027.html
new file mode 100644
index 00000000000..5fe4760e66c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/027.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Anonymous, same-origin, no headers, redirects to not same-origin, no headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'error', requests:[{cors:'no', cookie:'yes'}, {cors:origin, cookie:'no'}]};
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/028.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/028.html
new file mode 100644
index 00000000000..6019d37b63d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/028.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Anonymous, same-origin, with headers, redirects to not same-origin, with headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'load', requests:[{cors:'no', cookie:'yes'}, {cors:origin, cookie:'no'}]};
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/029.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/029.html
new file mode 100644
index 00000000000..7fa85456de5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/029.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Use Credentials, same-origin, no headers, redirects to not same-origin, no headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'error', requests:[{cors:'no', cookie:'yes'}, {cors:origin, cookie:'yes'}]};
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/030.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/030.html
new file mode 100644
index 00000000000..f7abf3b1ed4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/030.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Use Credentials, same-origin, with headers, redirects to not same-origin, with headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'load', requests:[{cors:'no', cookie:'yes'}, {cors:origin, cookie:'yes'}]};
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/031.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/031.html
new file mode 100644
index 00000000000..d709d0bc426
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/031.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Anonymous, not same-origin, no headers, redirects to not same-origin, with headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'error', requests:[{cors:origin, cookie:'no'}]}; // redirect not followed
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/032.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/032.html
new file mode 100644
index 00000000000..62b1008a417
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/032.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Anonymous, not same-origin, with headers, redirects to not same-origin, no headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'error', requests:[{cors:origin, cookie:'no'}, {cors:origin, cookie:'no'}]};
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/033.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/033.html
new file mode 100644
index 00000000000..215cae24193
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/033.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Anonymous, not same-origin, with headers, redirects to not same-origin, with headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'load', requests:[{cors:origin, cookie:'no'}, {cors:origin, cookie:'no'}]};
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/034.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/034.html
new file mode 100644
index 00000000000..bebb43ba8c1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/034.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Use Credentials, not same-origin, no headers, redirects to not same-origin, with headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'error', requests:[{cors:origin, cookie:'yes'}]}; // redirect not followed
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/035.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/035.html
new file mode 100644
index 00000000000..a17fb7dfc1e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/035.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Use Credentials, not same-origin, with headers, redirects to not same-origin, no headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'error', requests:[{cors:origin, cookie:'yes'}, {cors:origin, cookie:'yes'}]};
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/036.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/036.html
new file mode 100644
index 00000000000..52411177ea5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/036.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Use Credentials, not same-origin, with headers, redirects to not same-origin, with headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'load', requests:[{cors:origin, cookie:'yes'}, {cors:origin, cookie:'yes'}]};
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/037.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/037.html
new file mode 100644
index 00000000000..675b913a135
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/037.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Anonymous, same-origin, no headers, redirects to not same-origin, no headers, redirects to same-origin, no headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'error', requests:[{cors:'no', cookie:'yes'}, {cors:origin, cookie:'no'}]}; // second redirect not followed
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/038.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/038.html
new file mode 100644
index 00000000000..a29b2bdeade
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/038.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Anonymous, same-origin, with headers, redirects to not same-origin, with headers, redirects to same-origin, with headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'load', requests:[{cors:'no', cookie:'yes'}, {cors:origin, cookie:'no'}, {cors:'null', cookie:'no'}]};
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/039.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/039.html
new file mode 100644
index 00000000000..fcd4871ddb4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/039.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Anonymous, same-origin, no headers, redirects to not same-origin, with headers, redirects to same-origin, no headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'error', requests:[{cors:'no', cookie:'yes'}, {cors:origin, cookie:'no'}, {cors:'null', cookie:'no'}]};
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/040.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/040.html
new file mode 100644
index 00000000000..3c819684c43
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/040.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Use Credentials, same-origin, no headers, redirects to not same-origin, no headers, redirects to same-origin, no headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'error', requests:[{cors:'no', cookie:'yes'}, {cors:origin, cookie:'yes'}]}; // second redirect not followed
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/041.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/041.html
new file mode 100644
index 00000000000..f0f81953fca
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/041.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Use Credentials, same-origin, with headers, redirects to not same-origin, with headers, redirects to same-origin, with headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'load', requests:[{cors:'no', cookie:'yes'}, {cors:origin, cookie:'yes'}, {cors:'null', cookie:'yes'}]};
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/042.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/042.html
new file mode 100644
index 00000000000..c1ffa5f1ea8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/042.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Use Credentials, same-origin, no headers, redirects to not same-origin, with headers, redirects to same-origin, no headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'error', requests:[{cors:'no', cookie:'yes'}, {cors:origin, cookie:'yes'}, {cors:'null', cookie:'yes'}]};
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/043.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/043.html
new file mode 100644
index 00000000000..09072a9895d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/043.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Anonymous, same-origin, no headers, redirects to same-origin, no headers, redirects to not same-origin, no headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'error', requests:[{cors:'no', cookie:'yes'}, {cors:'no', cookie:'yes'}, {cors:origin, cookie:'no'}]};
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/044.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/044.html
new file mode 100644
index 00000000000..0d4a9fefbd3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/044.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Anonymous, same-origin, no headers, redirects to same-origin, no headers, redirects to not same-origin, with headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'load', requests:[{cors:'no', cookie:'yes'}, {cors:'no', cookie:'yes'}, {cors:origin, cookie:'no'}]};
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/045.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/045.html
new file mode 100644
index 00000000000..7151364f9c8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/045.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Use Credentials, same-origin, no headers, redirects to same-origin, no headers, redirects to not same-origin, no headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'error', requests:[{cors:'no', cookie:'yes'}, {cors:'no', cookie:'yes'}, {cors:origin, cookie:'yes'}]};
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/046.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/046.html
new file mode 100644
index 00000000000..e2864628144
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/046.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>track CORS: Use Credentials, same-origin, no headers, redirects to same-origin, no headers, redirects to not same-origin, with headers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script src=/common/utils.js></script>
+<script src=support/common.js?pipe=sub></script>
+<script>
+var expected = {event:'load', requests:[{cors:'no', cookie:'yes'}, {cors:'no', cookie:'yes'}, {cors:origin, cookie:'yes'}]};
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/support/common.js b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/support/common.js
new file mode 100644
index 00000000000..9d48abde09d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/support/common.js
@@ -0,0 +1,144 @@
+setup(function(){
+ window.id = token();
+ var p = document.createElement('p');
+ p.innerHTML = 'Test id: <samp>'+id+'</samp>';
+ document.body.appendChild(p);
+ window.actual = {event:null, requests:[]};
+ window.errors = [];
+ window.origin = location.protocol+'//'+location.host;
+ window.escapedOrigin = encodeURIComponent(origin);
+ window.sameOriginURL = "http://{{domains[]}}:{{ports[http][0]}}" + location.pathname.replace(/\/[^\/]+$/, '/');
+ window.otherOriginURL = "http://{{domains[www1]}}:{{ports[http][0]}}" + location.pathname.replace(/\/[^\/]+$/, '/');
+}, {timeout:10000, explicit_done:true});
+
+onload = function() {
+ (async_test(document.title, {timeout:10000})).step(function() {
+ // fail early if track isn't supported
+ assert_true('HTMLTrackElement' in window, 'track not supported');
+ window.corsMode = document.title.match(/^track CORS: (No CORS|Anonymous|Use Credentials)/)[1];
+ var requests_tmp = document.title.substr(('track CORS: '+corsMode+', ').length).split(/, redirects to /g);
+ window.requests = [];
+ requests_tmp.forEach(function(r) {
+ var parts = r.split(', ');
+ requests.push({sameOrigin:parts[0] == 'same-origin', withHeaders:parts[1] == 'with headers'});
+ });
+ if (document.title.indexOf('not same-origin') > -1) {
+ window.hasCrossDomainCookie = true;
+ this.step(setCrossDomainCookie);
+ } else {
+ window.hasCrossDomainCookie = false;
+ this.step(loadTrack);
+ }
+ });
+ done();
+};
+
+function setCrossDomainCookie() {
+ var iframe = document.createElement('iframe');
+ iframe.onload = this.step_func(loadTrack);
+ iframe.src = otherOriginURL + 'support/set-cookie.html#'+id;
+ document.body.appendChild(iframe);
+}
+
+function loadTrack() {
+ var video = document.createElement('video');
+ window.track = document.createElement('track');
+ if (corsMode == 'Anonymous')
+ video.setAttribute('crossorigin', 'anonymous');
+ else if (corsMode == 'Use Credentials')
+ video.setAttribute('crossorigin', 'use-credentials');
+ // else No CORS, omit the crossorigin attribute
+ video.appendChild(track);
+ document.body.appendChild(video);
+ track.track.mode = 'showing';
+ document.cookie = id+'=yes;path=/;max-age=10';
+ var url = '';
+ var r;
+ while (r = requests.pop()) {
+ url = (r.sameOrigin ? sameOriginURL : otherOriginURL) +
+ 'support/cors-tester.py?id=' + id +
+ (r.withHeaders ? '&origin=' + escapedOrigin : '') +
+ (url === '' ? '' : '&redirect=' + encodeURIComponent(url));
+ }
+ track.src = url;
+ track.onerror = track.onload = this.step_func(function(e) {
+ actual.event = e.type;
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', 'support/cors-tester.py?read=true&id=' + id, true);
+ xhr.onload = this.step_func(function() {
+ if (xhr.status == 200) {
+ var lines = xhr.responseText.split('\n');
+ lines.forEach(function(line) {
+ var chunks = line.split(' | ');
+ var current = {};
+ actual.requests.push(current);
+ chunks.forEach(function(chunk) {
+ var nameval = chunk.split(' = ');
+ var name = nameval[0];
+ var value = nameval[1];
+ current[name] = value;
+ });
+ });
+ } else if (xhr.status == 404) {
+ //No stash was found
+ } else {
+ errors.push('got unexpected xhr status: '+xhr.status);
+ }
+ this.step(removeCookies);
+ });
+ xhr.onerror = this.step_func(function() {
+ errors.push('got xhr error');
+ this.step(removeCookies);
+ });
+ xhr.send();
+ });
+}
+
+function removeCookies() {
+ document.cookie = id+'=;path=/;max-age=0';
+ var nextStep = checkData;
+ if (hasCrossDomainCookie) {
+ var iframe = document.createElement('iframe');
+ iframe.onload = this.step_func(nextStep);
+ iframe.src = otherOriginURL + 'support/cors-tester.py?delete-cookie&id=' + id;
+ document.body.appendChild(iframe);
+ } else {
+ this.step(nextStep);
+ }
+}
+
+function removeLog() {
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', 'support/cors-tester.py?cleanup&id='+id, true);
+ xhr.onload = this.step_func(function() {
+ assert_equals(xhr.responseText, 'OK', 'failed to clean up log: '+id);
+ this.step(checkData);
+ });
+ xhr.onerror = this.step_func(function() {
+ assert_unreached('failed to clean up log: '+id);
+ });
+ xhr.send();
+}
+
+function checkData() {
+ assert_equals(errors.length, 0, errors);
+ try {
+ if (actual.event == 'load' && expected.event == 'error')
+ assert_unreached('Security problem: got load event but expected error event');
+ assert_object_equals(actual, expected);
+ } catch(ex) {
+ var style = document.createElement('style');
+ style.textContent = '.json-diffs td { vertical-align:top } .json-diffs pre { margin:0 }';
+ document.head.appendChild(style);
+ var table = document.createElement('table');
+ table.border = "";
+ table.className = 'json-diffs';
+ table.innerHTML = '<tr><th>Actual<th>Expected<tr><td><pre></pre><td><pre></pre>';
+ table.getElementsByTagName('pre')[0].textContent = JSON.stringify(actual, null, 2);
+ table.getElementsByTagName('pre')[1].textContent = JSON.stringify(expected, null, 2);
+ document.body.insertBefore(table, document.getElementById('log'));
+ throw ex;
+ }
+ assert_equals(track.track.cues.length, expected.event == 'load' ? 1 : 0, 'track.track.cues.length');
+ this.done();
+}
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/support/cors-tester.py b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/support/cors-tester.py
new file mode 100644
index 00000000000..1c27a0d14bd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/support/cors-tester.py
@@ -0,0 +1,51 @@
+from wptserve.handlers import HTTPException
+import urllib
+
+def main(request, response):
+ if request.method != "GET":
+ raise HTTPException(400, message="Method was not GET")
+
+ if not "id" in request.GET:
+ raise HTTPException(400, message="No id")
+
+ id = request.GET['id']
+
+ if "read" in request.GET:
+ data = request.server.stash.take(id)
+ if data is None:
+ response.set_error(404, "Tried to read data not yet set")
+ return
+ return [("Content-Type", "text/plain")], data
+
+ elif "cleanup" in request.GET:
+ request.server.stash.take(id)
+ return "OK"
+
+ elif "delete-cookie" in request.GET:
+ response.delete_cookie(id)
+ return [("Content-Type", "text/plain")], "OK"
+
+ if "origin" in request.GET:
+ response.headers.set('Access-Control-Allow-Origin', request.GET['origin'])
+ response.headers.set('Access-Control-Allow-Credentials', 'true')
+
+ cors = request.headers.get("origin", "no")
+
+ cookie = request.cookies.first(id, "no")
+
+ line = 'cors = ' + cors + ' | cookie = ' + cookie.value;
+
+ data = request.server.stash.take(id)
+ if data is not None:
+ line = data + "\n" + line
+
+ request.server.stash.put(id, line)
+
+ if "redirect" in request.GET:
+ response.status = 302
+ response.headers.set('Location', request.GET['redirect'])
+ else:
+ return """WEBVTT
+
+00:00:00.000 --> 00:00:10.000
+Test"""
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/support/remove-cookie.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/support/remove-cookie.html
new file mode 100644
index 00000000000..00430e3f0e3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/support/remove-cookie.html
@@ -0,0 +1,6 @@
+<!doctype html>
+<title>Remove cookie from location.hash</title>
+<script>
+if (location.hash)
+ document.cookie = decodeURIComponent(location.hash.substr(1))+'=yes;path=/;max-age=0';
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/support/set-cookie.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/support/set-cookie.html
new file mode 100644
index 00000000000..cc1c9263860
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/cors/support/set-cookie.html
@@ -0,0 +1,6 @@
+<!doctype html>
+<title>Set cookie from location.hash</title>
+<script>
+if (location.hash)
+ document.cookie = decodeURIComponent(location.hash.substr(1))+'=yes;path=/;max-age=15';
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/track.de.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/track.de.vtt
new file mode 100644
index 00000000000..9eaf3d31e41
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/track.de.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:01.000
+German
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/track.en.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/track.en.vtt
new file mode 100644
index 00000000000..4241f35b569
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/track.en.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:01.000
+English
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/track.fr.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/track.fr.vtt
new file mode 100644
index 00000000000..5523224e0d6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/track.fr.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:01.000
+french
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/track.vtt b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/track.vtt
new file mode 100644
index 00000000000..c916c0983b2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/resources/track.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:01.000
+test
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/src-clear-cues.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/src-clear-cues.html
new file mode 100644
index 00000000000..3ba8c9db88a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/src-clear-cues.html
@@ -0,0 +1,52 @@
+<!doctype html>
+<title>track element changing "track URL" and clearing cues</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+(async_test(document.title+', set mode, add cue, set src')).step(function(){
+ var track = document.createElement('track');
+ var c = new VTTCue(0, 1, 'foo');
+ c.id = 'id';
+ track.track.addCue(c);
+ assert_equals(track.track.cues, null, 'cues before setting src or mode');
+ track.track.mode = 'showing';
+ assert_equals(track.track.cues.length, 1, 'cues after setting mode');
+ var cues = track.track.cues;
+ track.src = 'data:,a';
+ assert_equals(track.track.cues.length, 0, 'cues.length after setting src');
+ assert_equals(track.track.cues, cues, 'track.track.cues sameness after setting src');
+ assert_equals(c.id, 'id', 'liveness of removed cue');
+ this.done();
+});
+
+(async_test(document.title+', set mode, set src, add cue, change src')).step(function(){
+ var track = document.createElement('track');
+ track.track.mode = 'showing';
+ track.src = 'data:,a';
+ var c = new VTTCue(0, 1, 'foo');
+ c.id = 'id';
+ track.track.addCue(c);
+ assert_equals(track.track.cues.length, 1, 'cues.length before changing src');
+ var cues = track.track.cues;
+ track.src = 'data:,b';
+ assert_equals(track.track.cues.length, 0, 'cues.length after changing src');
+ assert_equals(track.track.cues, cues, 'track.track.cues sameness after changing src');
+ assert_equals(c.id, 'id', 'liveness of removed cue');
+ this.done();
+});
+
+(async_test(document.title+', set mode, add cue, change mode to disabled, set src')).step(function(){
+ var track = document.createElement('track');
+ track.track.mode = 'showing';
+ var c = new VTTCue(0, 1, 'foo');
+ c.id = 'id';
+ track.track.addCue(c);
+ var cues = track.track.cues;
+ track.track.mode = 'disabled';
+ track.src = 'data:,a';
+ assert_equals(cues.length, 0, 'cues.length after changing src');
+ assert_equals(c.id, 'id', 'liveness of removed cue');
+ this.done();
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-api-texttracks.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-api-texttracks.html
new file mode 100644
index 00000000000..b2840d235a9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-api-texttracks.html
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>Track element - text tracks API test</title>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#text-track-api">
+<link rel="author" title="Hyunjin Cho">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<h1>Track element and API Test</h1>
+<div style="display:none;">
+ <video id="tracktest" src="/media/movie_300.mp4">
+ <track kind="subtitles" src="resources/track.en.vtt" srclang="en" label="English">
+ <track kind="captions" src="resources/track.en.vtt" srclang="en" label="English with Captions">
+ <track id="french" kind="subtitles" src="resources/track.fr.vtt" srclang="fr" label="Francais">
+ <track kind="subtitles" src="resources/track.de.vtt" srclang="de" label="Deutsch">
+ </video>
+</div>
+<div id="log"></div>
+<script>
+test(function() {
+ var t1 = document.getElementById('tracktest').textTracks;
+ assert_not_equals(t1, undefined, "textTracks member should not be undefined");
+}, "Check the track elements");
+test(function() {
+ var t2 = document.getElementById('tracktest').textTracks.getTrackById("french");
+ assert_not_equals(t2, undefined, "textTracks member should not be undefined");
+}, "Check getTrackById method");
+test(function() {
+ var t3 = document.getElementById('tracktest').textTracks.length;
+ assert_equals(t3, 4, "textTracks List should be 4");
+}, "Count track list");
+</script>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/user-interface/muted.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/user-interface/muted.html
new file mode 100644
index 00000000000..906350d88c8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/user-interface/muted.html
@@ -0,0 +1,152 @@
+<!doctype html>
+<title>muted</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/media.js"></script>
+<style>video { display: none; }</style>
+<div id=log></div>
+
+<script>
+function test_setting(e, muted, hasAttribute) {
+ assert_equals(e.muted, muted);
+ assert_equals(e.hasAttribute('muted'), hasAttribute);
+
+ e.muted = !e.muted;
+ assert_equals(e.muted, !muted);
+ assert_equals(e.hasAttribute('muted'), hasAttribute);
+
+ e.muted = !e.muted;
+ assert_equals(e.muted, muted);
+ assert_equals(e.hasAttribute('muted'), hasAttribute);
+}
+</script>
+
+<!-- These tests are inside <audio>/<video> so that the steps for updating the
+ muted IDL attribute cannot be delayed until the end tag is parsed. -->
+
+<audio id=a1>
+<script>
+var a1 = document.getElementById('a1');
+
+test(function() {
+ assert_false(a1.muted);
+}, 'getting audio.muted (parser-created)');
+
+test(function() {
+ test_setting(a1, false, false);
+}, 'setting audio.muted (parser-created)');
+</script>
+</audio>
+
+<audio id=a2 muted>
+<script>
+var a2 = document.getElementById('a2');
+
+test(function() {
+ assert_true(a2.muted);
+}, 'getting audio.muted with muted="" (parser-created)');
+
+test(function() {
+ test_setting(a2, true, true);
+}, 'setting audio.muted with muted="" (parser-created)');
+</script>
+</audio>
+
+<video id=v1>
+<script>
+var v1 = document.getElementById('v1');
+
+test(function() {
+ assert_false(v1.muted);
+}, 'getting video.muted (parser-created)');
+
+test(function() {
+ test_setting(v1, false, false);
+}, 'setting video.muted (parser-created)');
+</script>
+</video>
+
+<video id=v2 muted>
+<script>
+var v2 = document.getElementById('v2');
+
+test(function() {
+ assert_true(v2.muted);
+}, 'getting video.muted with muted="" (parser-created)');
+
+test(function() {
+ test_setting(v2, true, true);
+}, 'setting video.muted with muted="" (parser-created)');
+</script>
+</video>
+
+<!-- Negative test to ensure that the load algorithm does not update the
+ muted IDL attribute to match the content attribute. -->
+
+<video id=v3 muted></video>
+<script>
+async_test(function(t) {
+ var v = document.getElementById('v3');
+ assert_true(v.muted);
+ v.muted = false;
+ v.src = 'data:,'; // invokes load()
+ v.addEventListener('error', t.step_func(function() {
+ assert_false(v.muted);
+ t.done();
+ }));
+}, 'getting video.muted with muted="" after load (parser-created)');
+</script>
+
+<script>
+['audio', 'video'].forEach(function(tagName) {
+ test(function() {
+ var m = document.createElement(tagName);
+ assert_false(m.muted);
+ }, 'getting ' + tagName + '.muted (script-created)');
+
+ test(function() {
+ var m = document.createElement(tagName);
+ test_setting(m, false, false);
+ }, 'setting ' + tagName + '.muted (script-created)');
+
+ test(function() {
+ var m = document.createElement(tagName);
+ m.setAttribute('muted', '');
+ assert_false(m.muted);
+ }, 'getting ' + tagName + '.muted with muted="" (script-created)');
+
+ test(function() {
+ var m = document.createElement(tagName);
+ m.setAttribute('muted', '');
+ test_setting(m, false, true);
+ }, 'setting ' + tagName + '.muted with muted="" (script-created)');
+
+ // Spec bug: https://www.w3.org/Bugs/Public/show_bug.cgi?id=25153
+ /*
+ test(function() {
+ var m = document.createElement(tagName);
+ m.setAttribute('muted', '');
+ m = m.cloneNode(false);
+ assert_true(m.hasAttribute('muted'));
+ assert_false(m.muted);
+ }, 'getting ' + tagName + '.muted with muted="" (cloneNode-created)');
+ */
+
+ test(function() {
+ var div = document.createElement('div');
+ div.innerHTML = '<' + tagName + ' muted>';
+ m = div.firstChild;
+ assert_true(m.hasAttribute('muted'));
+ assert_true(m.muted);
+ }, 'getting ' + tagName + '.muted with muted="" (innerHTML-created)');
+
+ test(function() {
+ var id = tagName;
+ assert_equals(document.getElementById(id), null);
+ document.write('<' + tagName + ' id=' + id + ' muted>');
+ m = document.getElementById(id);
+ assert_true(m.hasAttribute('muted'));
+ assert_true(m.muted);
+ }, 'getting ' + tagName + '.muted with muted="" (document.write-created)');
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/video_controls_present-manual.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/video_controls_present-manual.html
new file mode 100644
index 00000000000..8e44951d7ae
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/video_controls_present-manual.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Video Test: video_controls_present.html</title>
+ <link rel="author" title="Intel" href="http://www.intel.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-media-controls" />
+ <meta name="flags" content="" />
+ <meta name="assert" content="Check if the controls attribute is present in the video element that expecting the user agent exposes a controller user interface" />
+ </head>
+ <body>
+ <p>Test passes if a controller user interface appears below and the text 'The user agent doesn't support media element.' does not appear anywhere on this page</p>
+ <video id="m" controls>The user agent doesn't support media element.</video>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/video_loop_base.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/video_loop_base.html
new file mode 100644
index 00000000000..348f1cdae2f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/video_loop_base.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Video Test: video_loop_base</title>
+ <link rel="author" title="Intel" href="http://www.intel.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-media-loop" />
+ <meta name="flags" content="" />
+ <meta name="assert" content="Check if video.loop is set to true that expecting the seeking event is fired more than once" />
+ <meta name=timeout content=long>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <video id="m" controls>The user agent doesn't support media element.</video>
+ <script type="text/javascript">
+ var media = document.getElementById("m");
+ var name = document.getElementsByName("assert")[0].content;
+ var t = async_test(name);
+ var looped = false;
+
+ function startTest() {
+ if (looped) {
+ t.step(function() {
+ assert_true(true, "looped");
+ });
+ t.done();
+ media.pause();
+ }
+
+ looped = true;
+ }
+
+ media.addEventListener("seeking", startTest, false);
+ media.loop = true;
+ media.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+ media.play();
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/video_loop_current_media_controller-manual.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/video_loop_current_media_controller-manual.html
new file mode 100644
index 00000000000..590ab93089c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/video_loop_current_media_controller-manual.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Video Test: video_loop_current_media_controller</title>
+ <link rel="author" title="Intel" href="http://www.intel.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-media-loop" />
+ <meta name="flags" content="" />
+ <meta name="assert" content="Check if the video element has a current media controller that expecting the loop attribute has no effect" />
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p>Test passes if the video doesn't repeatly play and the text 'The user agent doesn't support media element.' does not appear anywhere on this page</p>
+ <video id="m" controls loop mediagroup="movie">The user agent doesn't support media element.</video>
+ <script type="text/javascript">
+ var media = document.getElementById("m");
+ var controller = new MediaController();
+
+ media.controller = controller;
+ media.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+ media.play();
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/video_muted_overriding_volume-manual.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/video_muted_overriding_volume-manual.html
new file mode 100644
index 00000000000..6d770666cc4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/video_muted_overriding_volume-manual.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Video Test: video_muted_overriding_volume</title>
+ <link rel="author" title="Intel" href="http://www.intel.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-media-muted" />
+ <meta name="flags" content="" />
+ <meta name="assert" content="Check if the muted attribute is present in the video element with volume is set to loudest that expecting the user hears no sound" />
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p>Test passes if the video is playing without sound output and the text 'The user agent doesn't support media element.' does not appear anywhere on this page</p>
+ <video id="m" controls muted>The user agent doesn't support media element.</video>
+ <script type="text/javascript">
+ var media = document.getElementById("m");
+ media.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+ media.volume = 1.0;
+ media.play();
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/video_muted_present-manual.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/video_muted_present-manual.html
new file mode 100644
index 00000000000..bc808277758
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/video_muted_present-manual.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Video Test: video_muted_present</title>
+ <link rel="author" title="Intel" href="http://www.intel.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-media-muted" />
+ <meta name="flags" content="" />
+ <meta name="assert" content="Check if the muted attribute is present in the video element that expecting the user hears no sound" />
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p>Test passes if the video is playing without sound output and the text 'The user agent doesn't support media element.' does not appear anywhere on this page</p>
+ <video id="m" controls muted>The user agent doesn't support media element.</video>
+ <script type="text/javascript">
+ var media = document.getElementById("m");
+ media.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+ media.play();
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/video_volume_check.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/video_volume_check.html
new file mode 100644
index 00000000000..1a45358a76f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/video_volume_check.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Video Test: video_volume_check</title>
+ <link rel="author" title="Intel" href="http://www.intel.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-media-volume" />
+ <meta name="flags" content="" />
+ <meta name="assert" content="Check that video.volume returns the value of the muted content attribute" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <video id="m">The user agent doesn't support media element.</video>
+ <script type="text/javascript">
+ var media = document.getElementById("m");
+ var VOLUME = {
+ 'SILENT' : 0.0,
+ 'NORMAL' : 0.5,
+ 'LOUDEST' : 1.0,
+ 'LOWER' : -1.1,
+ 'UPPER' : 1.1,
+ };
+
+ test(function() {
+ assert_false(media.volume < VOLUME.SILENT || media.volume > VOLUME.LOUDEST, "media.volume outside the range 0.0 to 1.0 inclusive");
+ }, "Check if the intial value of the video.volume is in the range 0.0 to 1.0 inclusive");
+
+ function volume_setting(vol, name)
+ {
+ if (vol < VOLUME.SILENT || vol > VOLUME.LOUDEST) {
+ try {
+ media.volume = vol;
+ test(function() {
+ assert_true(false, "media.volume setting exception");
+ }, name);
+ } catch(e) {
+ test(function() {
+ // 1 should be e.IndexSizeError or e.INDEX_SIZE_ERR in previous spec
+ assert_equals(e.code, 1, "media.volume setting exception");
+ }, name);
+ }
+ } else {
+ media.volume = vol;
+ test(function() {
+ assert_equals(media.volume, vol, "media.volume new value");
+ }, name);
+ }
+ }
+
+ volume_setting(VOLUME.NORMAL, "Check if video.volume is able to set to new value in the range 0.0 to 1.0");
+ volume_setting(VOLUME.SILENT, "Check if media.volume is able to set to new value 0.0 as silent");
+ volume_setting(VOLUME.LOUDEST, "Check if media.volume is able to set to new value 1.0 as loudest");
+ volume_setting(VOLUME.LOWER, "Check if media.volume is set to new value less than 0.0 that expecting an IndexSizeError exception is to be thrown");
+ volume_setting(VOLUME.UPPER, "Check if video.volume is set to new value greater than 1.0 that expecting an IndexSizeError exception is to be thrown");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/video_volume_loudest-manual.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/video_volume_loudest-manual.html
new file mode 100644
index 00000000000..74757812015
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/video_volume_loudest-manual.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Video Test: video_volume_loudest</title>
+ <link rel="author" title="Intel" href="http://www.intel.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-media-volume" />
+ <meta name="flags" content="" />
+ <meta name="assert" content="Check if the volume attribute is set to 1.0 as loudest in the video element that expecting the user hears sound loudly" />
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p>Test passes if the video is playing with sound heard and the text 'The user agent doesn't support media element.' does not appear anywhere on this page</p>
+ <video id="m" controls>The user agent doesn't support media element.</video>
+ <script type="text/javascript">
+ var media = document.getElementById("m");
+ media.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+ media.volume = 1.0;
+ media.play();
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/video_volume_silent-manual.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/video_volume_silent-manual.html
new file mode 100644
index 00000000000..1768dd4d4c7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/video_volume_silent-manual.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Video Test: video_volume_silent</title>
+ <link rel="author" title="Intel" href="http://www.intel.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-media-volume" />
+ <meta name="flags" content="" />
+ <meta name="assert" content="Check if the volume attribute is set to 0.0 as silent in the video element that expecting the user hears no sound" />
+ <script src="/common/media.js"></script>
+ </head>
+ <body>
+ <p>Test passes if the video is playing without sound heard and the text 'The user agent doesn't support media element.' does not appear anywhere on this page</p>
+ <video id="m" controls volume=0.0>The user agent doesn't support media element.</video>
+ <script type="text/javascript">
+ var media = document.getElementById("m");
+ media.src = getVideoURI("/media/movie_5") + "?" + new Date() + Math.random();
+ media.volume = 0.0;
+ media.play();
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/volume_nonfinite.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/volume_nonfinite.html
new file mode 100644
index 00000000000..6e90a2ebcdb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/media-elements/volume_nonfinite.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>Setting HTMLMediaElement.volume to non-finite numbers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+["audio", "video"].forEach(function(aElement) {
+ [NaN, Infinity, -Infinity].forEach(function(aValue) {
+ test(function() {
+ var el = document.createElement(aElement);
+ assert_throws(new TypeError(), function() {
+ el.volume = aValue;
+ });
+ }, "Setting " + aElement + ".volume to " + String(aValue) + " should throw a TypeError");
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/svg/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/embedded-content/svg/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/svg/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-area-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-area-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-area-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-area-element/area-stringifier.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-area-element/area-stringifier.html
new file mode 100644
index 00000000000..d06429630db
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-area-element/area-stringifier.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<title>HTMLAreaElement stringifier</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://heycam.github.io/webidl/#es-stringifier">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=/common/stringifiers.js></script>
+<div id=log></div>
+<script>
+test(function() {
+ test_stringifier_attribute(document.createElement("area"), "href", false);
+ var area = document.createElement("area");
+ area.setAttribute("href", "foo");
+ test_stringifier_attribute(area, "href", false);
+})
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-area-element/area_nohref.xhtml b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-area-element/area_nohref.xhtml
new file mode 100644
index 00000000000..4af616e0d23
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-area-element/area_nohref.xhtml
@@ -0,0 +1,18 @@
+<html xmlns='http://www.w3.org/1999/xhtml'>
+<head>
+<title>AREA - NOREF</title>
+</head>
+<body>
+<p>Test for <b>nohref</b> attribute on <b>area</b> </p>
+<p>Hover over the Blue Square below. The square is not clickable but the area around it should be.</p>
+<p>The test passes if clicking on the square doesn't do anything. Clicking on the area around the square should take you to another page.</p>
+<img src="../../../../images/blue-area.png" height="180" width="228" usemap="#square" border="0"/>
+<map name="square">
+<area alt="Blue Square" coords="43,29,176,135" nohref=""/>
+<area shape="rect" alt="White Space" coords="0,0,227,179" href="test-area.xhtml"/>
+</map>
+<p>
+<i>Note - This test checks for User Agent requirement as per HTML5 spec NOT the author requirement</i>
+</p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-area-element/test-area.xhtml b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-area-element/test-area.xhtml
new file mode 100644
index 00000000000..baa36c50a6f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-area-element/test-area.xhtml
@@ -0,0 +1,9 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title> This is a test page</title>
+</head>
+<body>
+This is a simple xhtml page
+<p><a href="area_nohref.xhtml">Click here</a> to go back to the previous page</p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-audio-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-audio-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-audio-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-audio-element/audio_001.htm b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-audio-element/audio_001.htm
new file mode 100644
index 00000000000..f455c682417
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-audio-element/audio_001.htm
@@ -0,0 +1,18 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>HTML5 Media Elements: Content inside the 'audio' element is not shown to the user (image).</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#audio" />
+ <link rel="match" href="audio_content-ref.htm" />
+ <meta name="assert" content="Content inside the 'audio' element is not shown to the user (image)." />
+</head>
+<body>
+<p>Test passes if there is no red.</p>
+<div id='testcontent'>
+<audio><img src="../../../../images/fail.gif" /></audio>
+
+</div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-audio-element/audio_002.htm b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-audio-element/audio_002.htm
new file mode 100644
index 00000000000..23b3ea188a8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-audio-element/audio_002.htm
@@ -0,0 +1,18 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>HTML5 Media Elements: Content inside the 'audio' element is not shown to the user.</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#audio" />
+ <link rel="match" href="audio_content-ref.htm" />
+ <meta name="assert" content="Content inside the 'audio' element is not shown to the user." />
+</head>
+<body>
+<p>Test passes if there is no red.</p>
+<div id='testcontent'>
+<audio><span style="color: red;">FAIL</span></audio>
+
+</div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-audio-element/audio_constructor.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-audio-element/audio_constructor.html
new file mode 100644
index 00000000000..995ea0ba056
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-audio-element/audio_constructor.html
@@ -0,0 +1,51 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Audio constructor</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+test(function() {
+ var throwingObject = {
+ toString: function() { throw Error() },
+ valueOf: function() { throw Error() }
+ };
+ var tests = [
+ [function() { return Audio() }, null, "No arguments, without new"],
+ [function() { return new Audio() }, null, "No arguments, with new"],
+ [function() { return Audio("") }, "", "Empty string argument, without new"],
+ [function() { return new Audio("") }, "", "Empty string argument, with new"],
+ [function() { return Audio("src") }, "src", "Non-empty string argument, without new"],
+ [function() { return new Audio("src") }, "src", "Non-empty string argument, with new"],
+ [function() { return Audio(null) }, "null", "Null argument, without new"],
+ [function() { return new Audio(null) }, "null", "Null argument, with new"],
+ [function() { return Audio(undefined) }, null, "Undefined argument, without new"],
+ [function() { return new Audio(undefined) }, null, "Undefined argument, with new"],
+ [function() { return Audio("", throwingObject) }, "", "Extra argument, without new"],
+ [function() { return new Audio("", throwingObject) }, "", "Extra argument, with new"],
+ ];
+ tests.forEach(function(t) {
+ var fn = t[0], expectedSrc = t[1], description = t[2];
+ test(function() {
+ var element = fn();
+ assert_equals(element.localName, "audio");
+ assert_equals(element.tagName, "AUDIO");
+ assert_equals(element.namespaceURI, "http://www.w3.org/1999/xhtml");
+ assert_equals(element.nodeType, Node.ELEMENT_NODE);
+ assert_equals(element.getAttribute("preload"), "auto");
+ assert_equals(element.getAttribute("src"), expectedSrc);
+ assert_equals(element.ownerDocument, document);
+ }, description);
+ });
+});
+test(function() {
+ assert_throws(new TypeError(), function() {
+ HTMLAudioElement();
+ });
+}, "Calling HTMLAudioElement should throw");
+test(function() {
+ assert_throws(new TypeError(), function() {
+ new HTMLAudioElement();
+ });
+}, "Constructing HTMLAudioElement should throw");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-audio-element/audio_content-ref.htm b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-audio-element/audio_content-ref.htm
new file mode 100644
index 00000000000..ef5964496dd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-audio-element/audio_content-ref.htm
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>HTML5 Media Elements: Content inside the 'audio' element is not shown to the user.</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+</head>
+<body>
+<p>Test passes if there is no red.</p>
+<div id='testcontent'>
+</div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/2d.canvas.readonly.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/2d.canvas.readonly.html
new file mode 100644
index 00000000000..5e1c22d2da7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/2d.canvas.readonly.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.canvas.readonly</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.canvas.readonly</h1>
+<p class="desc">CanvasRenderingContext2D.canvas is readonly</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("CanvasRenderingContext2D.canvas is readonly");
+_addTest(function(canvas, ctx) {
+
+var c = document.createElement('canvas');
+var d = ctx.canvas;
+_assertDifferent(c, d, "c", "d");
+ctx.canvas = c;
+_assertSame(ctx.canvas, d, "ctx.canvas", "d");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/2d.canvas.reference.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/2d.canvas.reference.html
new file mode 100644
index 00000000000..5bdb233f63d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/2d.canvas.reference.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.canvas.reference</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.canvas.reference</h1>
+<p class="desc">CanvasRenderingContext2D.canvas refers back to its canvas</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("CanvasRenderingContext2D.canvas refers back to its canvas");
+_addTest(function(canvas, ctx) {
+
+_assertSame(ctx.canvas, canvas, "ctx.canvas", "canvas");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/2d.getcontext.exists.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/2d.getcontext.exists.html
new file mode 100644
index 00000000000..f8b768ad880
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/2d.getcontext.exists.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.getcontext.exists</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.getcontext.exists</h1>
+<p class="desc">The 2D context is implemented</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("The 2D context is implemented");
+_addTest(function(canvas, ctx) {
+
+_assertDifferent(canvas.getContext('2d'), null, "canvas.getContext('2d')", "null");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/2d.getcontext.extraargs.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/2d.getcontext.extraargs.html
new file mode 100644
index 00000000000..f58911d0401
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/2d.getcontext.extraargs.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.getcontext.extraargs</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.getcontext.extraargs</h1>
+<p class="desc">The 2D context ignores extra getContext arguments</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("The 2D context ignores extra getContext arguments");
+_addTest(function(canvas, ctx) {
+
+_assertDifferent(canvas.getContext('2d', false, {}, [], 1, "2"), null, "canvas.getContext('2d', false, {}, [], 1, \"2\")", "null");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/2d.getcontext.shared.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/2d.getcontext.shared.html
new file mode 100644
index 00000000000..a678a135fda
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/2d.getcontext.shared.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.getcontext.shared</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.getcontext.shared</h1>
+<p class="desc">getContext('2d') returns objects which share canvas state</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("getContext('2d') returns objects which share canvas state");
+_addTest(function(canvas, ctx) {
+
+var ctx2 = canvas.getContext('2d');
+ctx.fillStyle = '#f00';
+ctx2.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/2d.getcontext.unique.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/2d.getcontext.unique.html
new file mode 100644
index 00000000000..d4d4a0d17ca
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/2d.getcontext.unique.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.getcontext.unique</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.getcontext.unique</h1>
+<p class="desc">getContext('2d') returns the same object</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("getContext('2d') returns the same object");
+_addTest(function(canvas, ctx) {
+
+_assertSame(canvas.getContext('2d'), canvas.getContext('2d'), "canvas.getContext('2d')", "canvas.getContext('2d')");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/2d.scaled-manual.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/2d.scaled-manual.html
new file mode 100644
index 00000000000..6ea8ba4b9b7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/2d.scaled-manual.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.scaled</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.scaled</h1>
+<p class="desc">CSS-scaled canvases get drawn correctly</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="50" height="25" style="width: 100px; height: 50px"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="2d.scaled.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("CSS-scaled canvases get drawn correctly");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#00f';
+ctx.fillRect(0, 0, 50, 25);
+ctx.fillStyle = '#0ff';
+ctx.fillRect(0, 0, 25, 10);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/2d.scaled-manual.png b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/2d.scaled-manual.png
new file mode 100644
index 00000000000..875407769ff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/2d.scaled-manual.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/2d.type.exists.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/2d.type.exists.html
new file mode 100644
index 00000000000..f29f1392623
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/2d.type.exists.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.type.exists</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.type.exists</h1>
+<p class="desc">The 2D context interface is a property of 'window'</p>
+
+<p class="notes">Defined in "Web IDL" (draft)
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("The 2D context interface is a property of 'window'");
+_addTest(function(canvas, ctx) {
+
+_assert(window.CanvasRenderingContext2D, "window.CanvasRenderingContext2D");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/2d.type.extend.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/2d.type.extend.html
new file mode 100644
index 00000000000..f4dfea879ee
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/2d.type.extend.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.type.extend</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.type.extend</h1>
+<p class="desc">Interface methods can be added</p>
+
+<p class="notes">Defined in "Web IDL" (draft)
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Interface methods can be added");
+_addTest(function(canvas, ctx) {
+
+window.CanvasRenderingContext2D.prototype.fillRectGreen = function (x, y, w, h)
+{
+ this.fillStyle = '#0f0';
+ this.fillRect(x, y, w, h);
+};
+ctx.fillStyle = '#f00';
+ctx.fillRectGreen(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/2d.type.prototype.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/2d.type.prototype.html
new file mode 100644
index 00000000000..9888d7b6ab6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/2d.type.prototype.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.type.prototype</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.type.prototype</h1>
+<p class="desc">window.CanvasRenderingContext2D.prototype are not [[Writable]] and not [[Configurable]], and its methods are [[Configurable]].</p>
+
+<p class="notes">Defined in "Web IDL" (draft)
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("window.CanvasRenderingContext2D.prototype are not [[Writable]] and not [[Configurable]], and its methods are [[Configurable]].");
+_addTest(function(canvas, ctx) {
+
+_assert(window.CanvasRenderingContext2D.prototype, "window.CanvasRenderingContext2D.prototype");
+_assert(window.CanvasRenderingContext2D.prototype.fill, "window.CanvasRenderingContext2D.prototype.fill");
+window.CanvasRenderingContext2D.prototype = null;
+_assert(window.CanvasRenderingContext2D.prototype, "window.CanvasRenderingContext2D.prototype");
+delete window.CanvasRenderingContext2D.prototype;
+_assert(window.CanvasRenderingContext2D.prototype, "window.CanvasRenderingContext2D.prototype");
+window.CanvasRenderingContext2D.prototype.fill = 1;
+_assertSame(window.CanvasRenderingContext2D.prototype.fill, 1, "window.CanvasRenderingContext2D.prototype.fill", "1");
+delete window.CanvasRenderingContext2D.prototype.fill;
+_assertSame(window.CanvasRenderingContext2D.prototype.fill, undefined, "window.CanvasRenderingContext2D.prototype.fill", "undefined");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/2d.type.replace.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/2d.type.replace.html
new file mode 100644
index 00000000000..1e3337732e4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/2d.type.replace.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: 2d.type.replace</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>2d.type.replace</h1>
+<p class="desc">Interface methods can be overridden</p>
+
+<p class="notes">Defined in "Web IDL" (draft)
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Interface methods can be overridden");
+_addTest(function(canvas, ctx) {
+
+var fillRect = window.CanvasRenderingContext2D.prototype.fillRect;
+window.CanvasRenderingContext2D.prototype.fillRect = function (x, y, w, h)
+{
+ this.fillStyle = '#0f0';
+ fillRect.call(this, x, y, w, h);
+};
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/contains.json b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/contains.json
new file mode 100644
index 00000000000..3f56f4fd8b3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/contains.json
@@ -0,0 +1,10 @@
+[
+ {
+ "id": "color-spaces-and-color-correction",
+ "original_id": "color-spaces-and-color-correction"
+ },
+ {
+ "id": "security-with-canvas-elements",
+ "original_id": "security-with-canvas-elements"
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/context.arguments.missing.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/context.arguments.missing.html
new file mode 100644
index 00000000000..37ae4e80021
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/context.arguments.missing.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: context.arguments.missing</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>context.arguments.missing</h1>
+<p class="desc"></p>
+
+<p class="notes">Defined in "Web IDL" (draft)
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("");
+_addTest(function(canvas, ctx) {
+
+assert_throws(new TypeError(), function() { canvas.getContext(); });
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/context.casesensitive.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/context.casesensitive.html
new file mode 100644
index 00000000000..5c64f7a04f1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/context.casesensitive.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: context.casesensitive</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>context.casesensitive</h1>
+<p class="desc">Context name "2D" is unrecognised; matching is case sensitive</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Context name \"2D\" is unrecognised; matching is case sensitive");
+_addTest(function(canvas, ctx) {
+
+_assertSame(canvas.getContext('2D'), null, "canvas.getContext('2D')", "null");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/context.emptystring.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/context.emptystring.html
new file mode 100644
index 00000000000..8f8b44a23e9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/context.emptystring.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: context.emptystring</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>context.emptystring</h1>
+<p class="desc">getContext with empty string returns null</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("getContext with empty string returns null");
+_addTest(function(canvas, ctx) {
+
+_assertSame(canvas.getContext(""), null, "canvas.getContext(\"\")", "null");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/context.unrecognised.badname.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/context.unrecognised.badname.html
new file mode 100644
index 00000000000..75f44277450
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/context.unrecognised.badname.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: context.unrecognised.badname</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>context.unrecognised.badname</h1>
+<p class="desc">getContext with unrecognised context name returns null</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("getContext with unrecognised context name returns null");
+_addTest(function(canvas, ctx) {
+
+_assertSame(canvas.getContext('This is not an implemented context in any real browser'), null, "canvas.getContext('This is not an implemented context in any real browser')", "null");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/context.unrecognised.badsuffix.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/context.unrecognised.badsuffix.html
new file mode 100644
index 00000000000..2f65ae3c8ac
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/context.unrecognised.badsuffix.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: context.unrecognised.badsuffix</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>context.unrecognised.badsuffix</h1>
+<p class="desc">Context name "2d" plus a suffix is unrecognised</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Context name \"2d\" plus a suffix is unrecognised");
+_addTest(function(canvas, ctx) {
+
+_assertSame(canvas.getContext("2d#"), null, "canvas.getContext(\"2d#\")", "null");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/context.unrecognised.nullsuffix.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/context.unrecognised.nullsuffix.html
new file mode 100644
index 00000000000..1607fec86cf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/context.unrecognised.nullsuffix.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: context.unrecognised.nullsuffix</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>context.unrecognised.nullsuffix</h1>
+<p class="desc">Context name "2d" plus a "\0" suffix is unrecognised</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Context name \"2d\" plus a \"\\0\" suffix is unrecognised");
+_addTest(function(canvas, ctx) {
+
+_assertSame(canvas.getContext("2d\0"), null, "canvas.getContext(\"2d\\0\")", "null");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/context.unrecognised.unicode.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/context.unrecognised.unicode.html
new file mode 100644
index 00000000000..c4eb943c242
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/context.unrecognised.unicode.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: context.unrecognised.unicode</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>context.unrecognised.unicode</h1>
+<p class="desc">Context name which kind of looks like "2d" is unrecognised</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Context name which kind of looks like \"2d\" is unrecognised");
+_addTest(function(canvas, ctx) {
+
+_assertSame(canvas.getContext("2\uFF44"), null, "canvas.getContext(\"2\\uFF44\")", "null"); // Fullwidth Latin Small Letter D
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/fallback.basic.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/fallback.basic.html
new file mode 100644
index 00000000000..0bae976e824
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/fallback.basic.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: fallback.basic</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>fallback.basic</h1>
+<p class="desc">Fallback content is inserted into the DOM</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Fallback content is inserted into the DOM");
+_addTest(function(canvas, ctx) {
+
+_assertSame(canvas.childNodes.length, 1, "canvas.childNodes.length", "1");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/fallback.multiple.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/fallback.multiple.html
new file mode 100644
index 00000000000..5c89be51975
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/fallback.multiple.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: fallback.multiple</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>fallback.multiple</h1>
+<p class="desc">Fallback content with multiple elements</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL</p><p class="fallback">FAIL</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Fallback content with multiple elements");
+_addTest(function(canvas, ctx) {
+
+_assertSame(canvas.childNodes.length, 2, "canvas.childNodes.length", "2");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/fallback.nested.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/fallback.nested.html
new file mode 100644
index 00000000000..e84739c85e4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/fallback.nested.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: fallback.nested</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>fallback.nested</h1>
+<p class="desc">Fallback content containing another canvas (mostly testing parsers)</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><canvas><p class="fallback">FAIL (fallback content)</p></canvas><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Fallback content containing another canvas (mostly testing parsers)");
+_addTest(function(canvas, ctx) {
+
+_assertSame(canvas.childNodes.length, 2, "canvas.childNodes.length", "2");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/initial.colour.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/initial.colour.html
new file mode 100644
index 00000000000..f680d504c21
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/initial.colour.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: initial.colour</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>initial.colour</h1>
+<p class="desc">Initial state is transparent black</p>
+
+<p class="notes">Output should be transparent black (not transparent anything-else), but manual
+verification can only confirm that it's transparent - it's not possible to make
+the actual blackness visible.
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="initial.colour.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Initial state is transparent black");
+_addTest(function(canvas, ctx) {
+
+_assertPixel(canvas, 20,20, 0,0,0,0, "20,20", "0,0,0,0");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/initial.colour.png b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/initial.colour.png
new file mode 100644
index 00000000000..eeedd0ff058
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/initial.colour.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/initial.reset.2dstate.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/initial.reset.2dstate.html
new file mode 100644
index 00000000000..b51253a6eea
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/initial.reset.2dstate.html
@@ -0,0 +1,103 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: initial.reset.2dstate</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>initial.reset.2dstate</h1>
+<p class="desc">Resetting the canvas state resets 2D state variables</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Resetting the canvas state resets 2D state variables");
+_addTest(function(canvas, ctx) {
+
+canvas.width = 100;
+var default_val;
+
+default_val = ctx.strokeStyle;
+ctx.strokeStyle = "#ff0000";
+canvas.width = 100;
+_assertSame(ctx.strokeStyle, default_val, "ctx.strokeStyle", "default_val");
+
+default_val = ctx.fillStyle;
+ctx.fillStyle = "#ff0000";
+canvas.width = 100;
+_assertSame(ctx.fillStyle, default_val, "ctx.fillStyle", "default_val");
+
+default_val = ctx.globalAlpha;
+ctx.globalAlpha = 0.5;
+canvas.width = 100;
+_assertSame(ctx.globalAlpha, default_val, "ctx.globalAlpha", "default_val");
+
+default_val = ctx.lineWidth;
+ctx.lineWidth = 0.5;
+canvas.width = 100;
+_assertSame(ctx.lineWidth, default_val, "ctx.lineWidth", "default_val");
+
+default_val = ctx.lineCap;
+ctx.lineCap = "round";
+canvas.width = 100;
+_assertSame(ctx.lineCap, default_val, "ctx.lineCap", "default_val");
+
+default_val = ctx.lineJoin;
+ctx.lineJoin = "round";
+canvas.width = 100;
+_assertSame(ctx.lineJoin, default_val, "ctx.lineJoin", "default_val");
+
+default_val = ctx.miterLimit;
+ctx.miterLimit = 0.5;
+canvas.width = 100;
+_assertSame(ctx.miterLimit, default_val, "ctx.miterLimit", "default_val");
+
+default_val = ctx.shadowOffsetX;
+ctx.shadowOffsetX = 5;
+canvas.width = 100;
+_assertSame(ctx.shadowOffsetX, default_val, "ctx.shadowOffsetX", "default_val");
+
+default_val = ctx.shadowOffsetY;
+ctx.shadowOffsetY = 5;
+canvas.width = 100;
+_assertSame(ctx.shadowOffsetY, default_val, "ctx.shadowOffsetY", "default_val");
+
+default_val = ctx.shadowBlur;
+ctx.shadowBlur = 5;
+canvas.width = 100;
+_assertSame(ctx.shadowBlur, default_val, "ctx.shadowBlur", "default_val");
+
+default_val = ctx.shadowColor;
+ctx.shadowColor = "#ff0000";
+canvas.width = 100;
+_assertSame(ctx.shadowColor, default_val, "ctx.shadowColor", "default_val");
+
+default_val = ctx.globalCompositeOperation;
+ctx.globalCompositeOperation = "copy";
+canvas.width = 100;
+_assertSame(ctx.globalCompositeOperation, default_val, "ctx.globalCompositeOperation", "default_val");
+
+default_val = ctx.font;
+ctx.font = "25px serif";
+canvas.width = 100;
+_assertSame(ctx.font, default_val, "ctx.font", "default_val");
+
+default_val = ctx.textAlign;
+ctx.textAlign = "center";
+canvas.width = 100;
+_assertSame(ctx.textAlign, default_val, "ctx.textAlign", "default_val");
+
+default_val = ctx.textBaseline;
+ctx.textBaseline = "bottom";
+canvas.width = 100;
+_assertSame(ctx.textBaseline, default_val, "ctx.textBaseline", "default_val");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/initial.reset.clip.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/initial.reset.clip.html
new file mode 100644
index 00000000000..044ccc58388
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/initial.reset.clip.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: initial.reset.clip</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>initial.reset.clip</h1>
+<p class="desc">Resetting the canvas state resets the current clip region</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Resetting the canvas state resets the current clip region");
+_addTest(function(canvas, ctx) {
+
+canvas.width = 100;
+ctx.rect(0, 0, 1, 1);
+ctx.clip();
+canvas.width = 100;
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 20,20, 0,255,0,255, "20,20", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/initial.reset.different.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/initial.reset.different.html
new file mode 100644
index 00000000000..0d02f40d6f4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/initial.reset.different.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: initial.reset.different</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>initial.reset.different</h1>
+<p class="desc">Changing size resets canvas to transparent black</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="initial.reset.different.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Changing size resets canvas to transparent black");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 50, 50);
+_assertPixel(canvas, 20,20, 255,0,0,255, "20,20", "255,0,0,255");
+canvas.width = 50;
+_assertPixel(canvas, 20,20, 0,0,0,0, "20,20", "0,0,0,0");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/initial.reset.different.png b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/initial.reset.different.png
new file mode 100644
index 00000000000..d83fdd55b15
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/initial.reset.different.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/initial.reset.gradient.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/initial.reset.gradient.html
new file mode 100644
index 00000000000..a1a8516d3e7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/initial.reset.gradient.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: initial.reset.gradient</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>initial.reset.gradient</h1>
+<p class="desc">Resetting the canvas state does not invalidate any existing gradients</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Resetting the canvas state does not invalidate any existing gradients");
+_addTest(function(canvas, ctx) {
+
+canvas.width = 50;
+var g = ctx.createLinearGradient(0, 0, 100, 0);
+g.addColorStop(0, '#0f0');
+g.addColorStop(1, '#0f0');
+canvas.width = 100;
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.fillStyle = g;
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/initial.reset.path.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/initial.reset.path.html
new file mode 100644
index 00000000000..ab59ce9a119
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/initial.reset.path.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: initial.reset.path</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>initial.reset.path</h1>
+<p class="desc">Resetting the canvas state resets the current path</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="initial.reset.path.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Resetting the canvas state resets the current path");
+_addTest(function(canvas, ctx) {
+
+canvas.width = 100;
+ctx.rect(0, 0, 100, 50);
+canvas.width = 100;
+ctx.fillStyle = '#f00';
+ctx.fill();
+_assertPixel(canvas, 20,20, 0,0,0,0, "20,20", "0,0,0,0");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/initial.reset.path.png b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/initial.reset.path.png
new file mode 100644
index 00000000000..eeedd0ff058
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/initial.reset.path.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/initial.reset.pattern.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/initial.reset.pattern.html
new file mode 100644
index 00000000000..f569d21f249
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/initial.reset.pattern.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: initial.reset.pattern</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>initial.reset.pattern</h1>
+<p class="desc">Resetting the canvas state does not invalidate any existing patterns</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Resetting the canvas state does not invalidate any existing patterns");
+_addTest(function(canvas, ctx) {
+
+canvas.width = 30;
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 30, 50);
+var p = ctx.createPattern(canvas, 'repeat-x');
+canvas.width = 100;
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+ctx.fillStyle = p;
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/initial.reset.same.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/initial.reset.same.html
new file mode 100644
index 00000000000..b0bf73f8f2c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/initial.reset.same.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: initial.reset.same</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>initial.reset.same</h1>
+<p class="desc">Setting size (not changing the value) resets canvas to transparent black</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="initial.reset.same.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Setting size (not changing the value) resets canvas to transparent black");
+_addTest(function(canvas, ctx) {
+
+canvas.width = 100;
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 50, 50);
+_assertPixel(canvas, 20,20, 255,0,0,255, "20,20", "255,0,0,255");
+canvas.width = 100;
+_assertPixel(canvas, 20,20, 0,0,0,0, "20,20", "0,0,0,0");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/initial.reset.same.png b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/initial.reset.same.png
new file mode 100644
index 00000000000..eeedd0ff058
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/initial.reset.same.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/initial.reset.transform.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/initial.reset.transform.html
new file mode 100644
index 00000000000..c5a92ca0f00
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/initial.reset.transform.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: initial.reset.transform</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>initial.reset.transform</h1>
+<p class="desc">Resetting the canvas state resets the current transformation matrix</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Resetting the canvas state resets the current transformation matrix");
+_addTest(function(canvas, ctx) {
+
+canvas.width = 100;
+ctx.scale(0.1, 0.1);
+canvas.width = 100;
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+_assertPixel(canvas, 20,20, 0,255,0,255, "20,20", "0,255,0,255");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/security.dataURI.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/security.dataURI.html
new file mode 100644
index 00000000000..d130579150d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/security.dataURI.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: security.dataURI</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>security.dataURI</h1>
+<p class="desc">data: URIs do not count as different-origin, and do not taint the canvas</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="/images/green-100x50.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("data: URIs do not count as different-origin, and do not taint the canvas");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#0f0';
+ctx.fillRect(0, 0, 100, 50);
+var data = canvas.toDataURL();
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+var img = new Image();
+deferTest();
+img.onload = t.step_func_done(function ()
+{
+ ctx.drawImage(img, 0, 0);
+ canvas.toDataURL(); // should be permitted
+ _assertPixel(canvas, 50,25, 0,255,0,255, "50,25", "0,255,0,255");
+});
+img.src = data;
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/security.drawImage.canvas.sub.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/security.drawImage.canvas.sub.html
new file mode 100644
index 00000000000..301e93ba8b3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/security.drawImage.canvas.sub.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: security.drawImage.canvas.sub</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>security.drawImage.canvas.sub</h1>
+<p class="desc">drawImage of unclean canvas makes the canvas origin-unclean</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("drawImage of unclean canvas makes the canvas origin-unclean");
+_addTest(function(canvas, ctx) {
+
+var canvas2 = document.createElement('canvas');
+canvas2.width = 100;
+canvas2.height = 50;
+var ctx2 = canvas2.getContext('2d');
+ctx2.drawImage(document.getElementById('yellow.png'), 0, 0);
+ctx.drawImage(canvas2, 0, 0);
+assert_throws("SECURITY_ERR", function() { canvas.toDataURL(); });
+assert_throws("SECURITY_ERR", function() { ctx.getImageData(0, 0, 1, 1); });
+
+
+});
+</script>
+<img src="http://{{domains[www2]}}:{{ports[http][0]}}/images/yellow.png" id="yellow.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/security.drawImage.image.sub.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/security.drawImage.image.sub.html
new file mode 100644
index 00000000000..e15eaa4e2ce
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/security.drawImage.image.sub.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: security.drawImage.image.sub</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>security.drawImage.image.sub</h1>
+<p class="desc">drawImage of different-origin image makes the canvas origin-unclean</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("drawImage of different-origin image makes the canvas origin-unclean");
+_addTest(function(canvas, ctx) {
+
+ctx.drawImage(document.getElementById('yellow.png'), 0, 0);
+assert_throws("SECURITY_ERR", function() { canvas.toDataURL(); });
+assert_throws("SECURITY_ERR", function() { ctx.getImageData(0, 0, 1, 1); });
+
+
+});
+</script>
+<img src="http://{{domains[www2]}}:{{ports[http][0]}}/images/yellow.png" id="yellow.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/security.pattern.canvas.fillStyle.sub.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/security.pattern.canvas.fillStyle.sub.html
new file mode 100644
index 00000000000..0a48d9694c7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/security.pattern.canvas.fillStyle.sub.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: security.pattern.canvas.fillStyle.sub</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>security.pattern.canvas.fillStyle.sub</h1>
+<p class="desc">Setting fillStyle to a pattern of an unclean canvas makes the canvas origin-unclean</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Setting fillStyle to a pattern of an unclean canvas makes the canvas origin-unclean");
+_addTest(function(canvas, ctx) {
+
+var canvas2 = document.createElement('canvas');
+canvas2.width = 100;
+canvas2.height = 50;
+var ctx2 = canvas2.getContext('2d');
+ctx2.drawImage(document.getElementById('yellow.png'), 0, 0);
+var p = ctx.createPattern(canvas2, 'repeat');
+ctx.fillStyle = p;
+ctx.fillStyle = 'red';
+assert_throws("SECURITY_ERR", function() { canvas.toDataURL(); });
+assert_throws("SECURITY_ERR", function() { ctx.getImageData(0, 0, 1, 1); });
+
+
+});
+</script>
+<img src="http://{{domains[www2]}}:{{ports[http][0]}}/images/yellow.png" id="yellow.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/security.pattern.canvas.strokeStyle.sub.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/security.pattern.canvas.strokeStyle.sub.html
new file mode 100644
index 00000000000..a65e0621a49
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/security.pattern.canvas.strokeStyle.sub.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: security.pattern.canvas.strokeStyle.sub</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>security.pattern.canvas.strokeStyle.sub</h1>
+<p class="desc">Setting strokeStyle to a pattern of an unclean canvas makes the canvas origin-unclean</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Setting strokeStyle to a pattern of an unclean canvas makes the canvas origin-unclean");
+_addTest(function(canvas, ctx) {
+
+var canvas2 = document.createElement('canvas');
+canvas2.width = 100;
+canvas2.height = 50;
+var ctx2 = canvas2.getContext('2d');
+ctx2.drawImage(document.getElementById('yellow.png'), 0, 0);
+var p = ctx.createPattern(canvas2, 'repeat');
+ctx.strokeStyle = p;
+ctx.strokeStyle = 'red';
+assert_throws("SECURITY_ERR", function() { canvas.toDataURL(); });
+assert_throws("SECURITY_ERR", function() { ctx.getImageData(0, 0, 1, 1); });
+
+
+});
+</script>
+<img src="http://{{domains[www2]}}:{{ports[http][0]}}/images/yellow.png" id="yellow.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/security.pattern.canvas.timing.sub.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/security.pattern.canvas.timing.sub.html
new file mode 100644
index 00000000000..5f20edc857f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/security.pattern.canvas.timing.sub.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: security.pattern.canvas.timing.sub</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>security.pattern.canvas.timing.sub</h1>
+<p class="desc">Pattern safety depends on whether the source was origin-clean, not on whether it still is clean</p>
+
+<p class="notes">Disagrees with spec on "is" vs "was"
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Pattern safety depends on whether the source was origin-clean, not on whether it still is clean");
+_addTest(function(canvas, ctx) {
+
+var canvas2 = document.createElement('canvas');
+canvas2.width = 100;
+canvas2.height = 50;
+var ctx2 = canvas2.getContext('2d');
+ctx2.fillStyle = '#0f0';
+ctx2.fillRect(0, 0, 100, 50);
+var p = ctx.createPattern(canvas2, 'repeat');
+ctx2.drawImage(document.getElementById('yellow.png'), 0, 0); // make canvas2 origin-unclean
+ctx.fillStyle = p;
+ctx.fillRect(0, 0, 100, 50);
+canvas.toDataURL();
+ctx.getImageData(0, 0, 1, 1);
+_assert(true, "true"); // okay if there was no exception
+
+
+});
+</script>
+<img src="http://{{domains[www2]}}:{{ports[http][0]}}/images/yellow.png" id="yellow.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/security.pattern.create.sub.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/security.pattern.create.sub.html
new file mode 100644
index 00000000000..41ed250eb5b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/security.pattern.create.sub.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: security.pattern.create.sub</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>security.pattern.create.sub</h1>
+<p class="desc">Creating an unclean pattern does not make the canvas origin-unclean</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Creating an unclean pattern does not make the canvas origin-unclean");
+_addTest(function(canvas, ctx) {
+
+var p = ctx.createPattern(document.getElementById('yellow.png'), 'repeat');
+canvas.toDataURL();
+ctx.getImageData(0, 0, 1, 1);
+_assert(true, "true"); // okay if there was no exception
+
+
+});
+</script>
+<img src="http://{{domains[www]}}:{{ports[http][0]}}/images/yellow.png" id="yellow.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/security.pattern.cross.sub.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/security.pattern.cross.sub.html
new file mode 100644
index 00000000000..83ac1c71b6b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/security.pattern.cross.sub.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: security.pattern.cross.sub</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>security.pattern.cross.sub</h1>
+<p class="desc">Using an unclean pattern makes the target canvas origin-unclean, not the pattern canvas</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Using an unclean pattern makes the target canvas origin-unclean, not the pattern canvas");
+_addTest(function(canvas, ctx) {
+
+var canvas2 = document.createElement('canvas');
+canvas2.width = 100;
+canvas2.height = 50;
+var ctx2 = canvas2.getContext('2d');
+var p = ctx2.createPattern(document.getElementById('yellow.png'), 'repeat');
+ctx.fillStyle = p;
+ctx.fillRect(0, 0, 100, 50);
+assert_throws("SECURITY_ERR", function() { canvas.toDataURL(); });
+assert_throws("SECURITY_ERR", function() { ctx.getImageData(0, 0, 1, 1); });
+canvas2.toDataURL();
+ctx2.getImageData(0, 0, 1, 1);
+
+
+});
+</script>
+<img src="http://{{domains[www2]}}:{{ports[http][0]}}/images/yellow.png" id="yellow.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/security.pattern.image.fillStyle.sub.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/security.pattern.image.fillStyle.sub.html
new file mode 100644
index 00000000000..ba0904ec1d4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/security.pattern.image.fillStyle.sub.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: security.pattern.image.fillStyle.sub</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>security.pattern.image.fillStyle.sub</h1>
+<p class="desc">Setting fillStyle to a pattern of a different-origin image makes the canvas origin-unclean</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Setting fillStyle to a pattern of a different-origin image makes the canvas origin-unclean");
+_addTest(function(canvas, ctx) {
+
+var p = ctx.createPattern(document.getElementById('yellow.png'), 'repeat');
+ctx.fillStyle = p;
+ctx.fillStyle = 'red';
+assert_throws("SECURITY_ERR", function() { canvas.toDataURL(); });
+assert_throws("SECURITY_ERR", function() { ctx.getImageData(0, 0, 1, 1); });
+
+
+});
+</script>
+<img src="http://{{domains[www2]}}:{{ports[http][0]}}/images/yellow.png" id="yellow.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/security.pattern.image.strokeStyle.sub.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/security.pattern.image.strokeStyle.sub.html
new file mode 100644
index 00000000000..d7f32a9484b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/security.pattern.image.strokeStyle.sub.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: security.pattern.image.strokeStyle.sub</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>security.pattern.image.strokeStyle.sub</h1>
+<p class="desc">Setting strokeStyle to a pattern of a different-origin image makes the canvas origin-unclean</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Setting strokeStyle to a pattern of a different-origin image makes the canvas origin-unclean");
+_addTest(function(canvas, ctx) {
+
+var p = ctx.createPattern(document.getElementById('yellow.png'), 'repeat');
+ctx.strokeStyle = p;
+ctx.strokeStyle = 'red';
+assert_throws("SECURITY_ERR", function() { canvas.toDataURL(); });
+assert_throws("SECURITY_ERR", function() { ctx.getImageData(0, 0, 1, 1); });
+
+
+});
+</script>
+<img src="http://{{domains[www2]}}:{{ports[http][0]}}/images/yellow.png" id="yellow.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/security.reset.sub.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/security.reset.sub.html
new file mode 100644
index 00000000000..28693490ad3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/security.reset.sub.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: security.reset.sub</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>security.reset.sub</h1>
+<p class="desc">Resetting the canvas state does not reset the origin-clean flag</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Resetting the canvas state does not reset the origin-clean flag");
+_addTest(function(canvas, ctx) {
+
+canvas.width = 50;
+ctx.drawImage(document.getElementById('yellow.png'), 0, 0);
+assert_throws("SECURITY_ERR", function() { canvas.toDataURL(); });
+canvas.width = 100;
+assert_throws("SECURITY_ERR", function() { canvas.toDataURL(); });
+
+
+});
+</script>
+<img src="http://{{domains[www2]}}:{{ports[http][0]}}/images/yellow.png" id="yellow.png" class="resource">
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.default.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.default.html
new file mode 100644
index 00000000000..004636d841f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.default.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: size.attributes.default</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>size.attributes.default</h1>
+<p class="desc">Default width/height when attributes are missing</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" ><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="size.attributes.default.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Default width/height when attributes are missing");
+_addTest(function(canvas, ctx) {
+
+_assertSame(canvas.width, 300, "canvas.width", "300");
+_assertSame(canvas.height, 150, "canvas.height", "150");
+_assert(!canvas.hasAttribute('width'), "!canvas.hasAttribute('width')");
+_assert(!canvas.hasAttribute('height'), "!canvas.hasAttribute('height')");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.default.png b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.default.png
new file mode 100644
index 00000000000..a72d047556a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.default.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.get.png b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.get.png
new file mode 100644
index 00000000000..47830c83ea9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.get.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.idl.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.idl.html
new file mode 100644
index 00000000000..cd6796e0724
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.idl.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: size.attributes.idl</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>size.attributes.idl</h1>
+<p class="desc">Getting/setting width/height IDL attributes</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Getting/setting width/height IDL attributes");
+_addTest(function(canvas, ctx) {
+
+canvas.width = "100";
+canvas.height = "100";
+_assertSame(canvas.width, 100, "canvas.width", "100");
+_assertSame(canvas.height, 100, "canvas.height", "100");
+
+canvas.width = "+1.5e2";
+canvas.height = "0x96";
+_assertSame(canvas.width, 150, "canvas.width", "150");
+_assertSame(canvas.height, 150, "canvas.height", "150");
+
+canvas.width = 200 - Math.pow(2, 32);
+canvas.height = 200 - Math.pow(2, 32);
+_assertSame(canvas.width, 200, "canvas.width", "200");
+_assertSame(canvas.height, 200, "canvas.height", "200");
+
+canvas.width = 301.999;
+canvas.height = 301.001;
+_assertSame(canvas.width, 301, "canvas.width", "301");
+_assertSame(canvas.height, 301, "canvas.height", "301");
+
+canvas.width = "400x";
+canvas.height = "foo";
+_assertSame(canvas.width, 0, "canvas.width", "0");
+_assertSame(canvas.height, 0, "canvas.height", "0");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.idl.set.zero.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.idl.set.zero.html
new file mode 100644
index 00000000000..a10ac5443c4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.idl.set.zero.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: size.attributes.idl.set.zero</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>size.attributes.idl.set.zero</h1>
+<p class="desc">Setting width/height IDL attributes to 0</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Setting width/height IDL attributes to 0");
+_addTest(function(canvas, ctx) {
+
+canvas.width = 0;
+canvas.height = 0;
+_assertSame(canvas.width, 0, "canvas.width", "0");
+_assertSame(canvas.height, 0, "canvas.height", "0");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.decimal.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.decimal.html
new file mode 100644
index 00000000000..ccf579e05b7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.decimal.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: size.attributes.parse.decimal</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>size.attributes.parse.decimal</h1>
+<p class="desc">Parsing of non-negative integers</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100.999" height="100.999"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="size.attributes.parse.decimal.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Parsing of non-negative integers");
+_addTest(function(canvas, ctx) {
+
+_assertSame(canvas.width, 100, "canvas.width", "100");
+_assertSame(canvas.height, 100, "canvas.height", "100");
+_assertSame(window.getComputedStyle(canvas, null).getPropertyValue("width"), "100px", "window.getComputedStyle(canvas, null).getPropertyValue(\"width\")", "\"100px\"");
+_assertSame(canvas.getAttribute('width'), '100.999', "canvas.getAttribute('width')", "'100.999'");
+_assertSame(canvas.getAttribute('height'), '100.999', "canvas.getAttribute('height')", "'100.999'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.decimal.png b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.decimal.png
new file mode 100644
index 00000000000..f8426733306
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.decimal.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.em.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.em.html
new file mode 100644
index 00000000000..84614691a6b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.em.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: size.attributes.parse.em</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>size.attributes.parse.em</h1>
+<p class="desc">Parsing of non-negative integers</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100em" height="100em"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="size.attributes.parse.em.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Parsing of non-negative integers");
+_addTest(function(canvas, ctx) {
+
+_assertSame(canvas.width, 100, "canvas.width", "100");
+_assertSame(canvas.height, 100, "canvas.height", "100");
+_assertSame(window.getComputedStyle(canvas, null).getPropertyValue("width"), "100px", "window.getComputedStyle(canvas, null).getPropertyValue(\"width\")", "\"100px\"");
+_assertSame(canvas.getAttribute('width'), '100em', "canvas.getAttribute('width')", "'100em'");
+_assertSame(canvas.getAttribute('height'), '100em', "canvas.getAttribute('height')", "'100em'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.em.png b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.em.png
new file mode 100644
index 00000000000..f8426733306
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.em.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.empty.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.empty.html
new file mode 100644
index 00000000000..04a19b44aea
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.empty.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: size.attributes.parse.empty</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>size.attributes.parse.empty</h1>
+<p class="desc">Parsing of non-negative integers</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="" height=""><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="size.attributes.parse.empty.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Parsing of non-negative integers");
+_addTest(function(canvas, ctx) {
+
+_assertSame(canvas.width, 300, "canvas.width", "300");
+_assertSame(canvas.height, 150, "canvas.height", "150");
+_assertSame(canvas.getAttribute('width'), '', "canvas.getAttribute('width')", "''");
+_assertSame(canvas.getAttribute('height'), '', "canvas.getAttribute('height')", "''");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.empty.png b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.empty.png
new file mode 100644
index 00000000000..a72d047556a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.empty.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.exp.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.exp.html
new file mode 100644
index 00000000000..7a7c72692c6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.exp.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: size.attributes.parse.exp</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>size.attributes.parse.exp</h1>
+<p class="desc">Parsing of non-negative integers</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100e1" height="100e1"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="size.attributes.parse.exp.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Parsing of non-negative integers");
+_addTest(function(canvas, ctx) {
+
+_assertSame(canvas.width, 100, "canvas.width", "100");
+_assertSame(canvas.height, 100, "canvas.height", "100");
+_assertSame(window.getComputedStyle(canvas, null).getPropertyValue("width"), "100px", "window.getComputedStyle(canvas, null).getPropertyValue(\"width\")", "\"100px\"");
+_assertSame(canvas.getAttribute('width'), '100e1', "canvas.getAttribute('width')", "'100e1'");
+_assertSame(canvas.getAttribute('height'), '100e1', "canvas.getAttribute('height')", "'100e1'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.exp.png b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.exp.png
new file mode 100644
index 00000000000..f8426733306
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.exp.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.hex.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.hex.html
new file mode 100644
index 00000000000..7532d775357
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.hex.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: size.attributes.parse.hex</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>size.attributes.parse.hex</h1>
+<p class="desc">Parsing of non-negative integers</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="0x100" height="0x100"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Parsing of non-negative integers");
+_addTest(function(canvas, ctx) {
+
+_assertSame(canvas.width, 0, "canvas.width", "0");
+_assertSame(canvas.height, 0, "canvas.height", "0");
+_assertSame(window.getComputedStyle(canvas, null).getPropertyValue("width"), "0px", "window.getComputedStyle(canvas, null).getPropertyValue(\"width\")", "\"0px\"");
+_assertSame(canvas.getAttribute('width'), '0x100', "canvas.getAttribute('width')", "'0x100'");
+_assertSame(canvas.getAttribute('height'), '0x100', "canvas.getAttribute('height')", "'0x100'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.junk.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.junk.html
new file mode 100644
index 00000000000..8dca5ef3c6b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.junk.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: size.attributes.parse.junk</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>size.attributes.parse.junk</h1>
+<p class="desc">Parsing of non-negative integers</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="#!?" height="#!?"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="size.attributes.parse.junk.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Parsing of non-negative integers");
+_addTest(function(canvas, ctx) {
+
+_assertSame(canvas.width, 300, "canvas.width", "300");
+_assertSame(canvas.height, 150, "canvas.height", "150");
+_assertSame(canvas.getAttribute('width'), '#!?', "canvas.getAttribute('width')", "'#!?'");
+_assertSame(canvas.getAttribute('height'), '#!?', "canvas.getAttribute('height')", "'#!?'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.junk.png b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.junk.png
new file mode 100644
index 00000000000..a72d047556a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.junk.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.minus.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.minus.html
new file mode 100644
index 00000000000..c901dffc508
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.minus.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: size.attributes.parse.minus</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>size.attributes.parse.minus</h1>
+<p class="desc">Parsing of non-negative integers</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="-100" height="-100"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="size.attributes.parse.minus.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Parsing of non-negative integers");
+_addTest(function(canvas, ctx) {
+
+_assertSame(canvas.width, 300, "canvas.width", "300");
+_assertSame(canvas.height, 150, "canvas.height", "150");
+_assertSame(canvas.getAttribute('width'), '-100', "canvas.getAttribute('width')", "'-100'");
+_assertSame(canvas.getAttribute('height'), '-100', "canvas.getAttribute('height')", "'-100'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.minus.png b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.minus.png
new file mode 100644
index 00000000000..a72d047556a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.minus.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.octal.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.octal.html
new file mode 100644
index 00000000000..efdcfeb3afe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.octal.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: size.attributes.parse.octal</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>size.attributes.parse.octal</h1>
+<p class="desc">Parsing of non-negative integers</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="0100" height="0100"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="size.attributes.parse.octal.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Parsing of non-negative integers");
+_addTest(function(canvas, ctx) {
+
+_assertSame(canvas.width, 100, "canvas.width", "100");
+_assertSame(canvas.height, 100, "canvas.height", "100");
+_assertSame(window.getComputedStyle(canvas, null).getPropertyValue("width"), "100px", "window.getComputedStyle(canvas, null).getPropertyValue(\"width\")", "\"100px\"");
+_assertSame(canvas.getAttribute('width'), '0100', "canvas.getAttribute('width')", "'0100'");
+_assertSame(canvas.getAttribute('height'), '0100', "canvas.getAttribute('height')", "'0100'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.octal.png b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.octal.png
new file mode 100644
index 00000000000..f8426733306
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.octal.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.onlyspace.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.onlyspace.html
new file mode 100644
index 00000000000..11948581ec0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.onlyspace.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: size.attributes.parse.onlyspace</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>size.attributes.parse.onlyspace</h1>
+<p class="desc">Parsing of non-negative integers</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width=" " height=" "><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="size.attributes.parse.onlyspace.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Parsing of non-negative integers");
+_addTest(function(canvas, ctx) {
+
+_assertSame(canvas.width, 300, "canvas.width", "300");
+_assertSame(canvas.height, 150, "canvas.height", "150");
+_assertSame(canvas.getAttribute('width'), ' ', "canvas.getAttribute('width')", "' '");
+_assertSame(canvas.getAttribute('height'), ' ', "canvas.getAttribute('height')", "' '");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.onlyspace.png b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.onlyspace.png
new file mode 100644
index 00000000000..a72d047556a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.onlyspace.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.percent.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.percent.html
new file mode 100644
index 00000000000..9073424e282
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.percent.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: size.attributes.parse.percent</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>size.attributes.parse.percent</h1>
+<p class="desc">Parsing of non-negative integers</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100%" height="100%"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="size.attributes.parse.percent.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Parsing of non-negative integers");
+_addTest(function(canvas, ctx) {
+
+_assertSame(canvas.width, 100, "canvas.width", "100");
+_assertSame(canvas.height, 100, "canvas.height", "100");
+_assertSame(window.getComputedStyle(canvas, null).getPropertyValue("width"), "100px", "window.getComputedStyle(canvas, null).getPropertyValue(\"width\")", "\"100px\"");
+_assertSame(canvas.getAttribute('width'), '100%', "canvas.getAttribute('width')", "'100%'");
+_assertSame(canvas.getAttribute('height'), '100%', "canvas.getAttribute('height')", "'100%'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.percent.png b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.percent.png
new file mode 100644
index 00000000000..f8426733306
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.percent.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.plus.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.plus.html
new file mode 100644
index 00000000000..816f381d409
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.plus.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: size.attributes.parse.plus</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>size.attributes.parse.plus</h1>
+<p class="desc">Parsing of non-negative integers</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="+100" height="+100"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="size.attributes.parse.plus.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Parsing of non-negative integers");
+_addTest(function(canvas, ctx) {
+
+_assertSame(canvas.width, 100, "canvas.width", "100");
+_assertSame(canvas.height, 100, "canvas.height", "100");
+_assertSame(window.getComputedStyle(canvas, null).getPropertyValue("width"), "100px", "window.getComputedStyle(canvas, null).getPropertyValue(\"width\")", "\"100px\"");
+_assertSame(canvas.getAttribute('width'), '+100', "canvas.getAttribute('width')", "'+100'");
+_assertSame(canvas.getAttribute('height'), '+100', "canvas.getAttribute('height')", "'+100'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.plus.png b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.plus.png
new file mode 100644
index 00000000000..f8426733306
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.plus.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.space.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.space.html
new file mode 100644
index 00000000000..417674d186e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.space.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: size.attributes.parse.space</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>size.attributes.parse.space</h1>
+<p class="desc">Parsing of non-negative integers</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width=" 100" height=" 100"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="size.attributes.parse.space.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Parsing of non-negative integers");
+_addTest(function(canvas, ctx) {
+
+_assertSame(canvas.width, 100, "canvas.width", "100");
+_assertSame(canvas.height, 100, "canvas.height", "100");
+_assertSame(window.getComputedStyle(canvas, null).getPropertyValue("width"), "100px", "window.getComputedStyle(canvas, null).getPropertyValue(\"width\")", "\"100px\"");
+_assertSame(canvas.getAttribute('width'), ' 100', "canvas.getAttribute('width')", "' 100'");
+_assertSame(canvas.getAttribute('height'), ' 100', "canvas.getAttribute('height')", "' 100'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.space.png b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.space.png
new file mode 100644
index 00000000000..f8426733306
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.space.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.trailingjunk.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.trailingjunk.html
new file mode 100644
index 00000000000..76c6db05f6f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.trailingjunk.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: size.attributes.parse.trailingjunk</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>size.attributes.parse.trailingjunk</h1>
+<p class="desc">Parsing of non-negative integers</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100#!?" height="100#!?"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="size.attributes.parse.trailingjunk.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Parsing of non-negative integers");
+_addTest(function(canvas, ctx) {
+
+_assertSame(canvas.width, 100, "canvas.width", "100");
+_assertSame(canvas.height, 100, "canvas.height", "100");
+_assertSame(window.getComputedStyle(canvas, null).getPropertyValue("width"), "100px", "window.getComputedStyle(canvas, null).getPropertyValue(\"width\")", "\"100px\"");
+_assertSame(canvas.getAttribute('width'), '100#!?', "canvas.getAttribute('width')", "'100#!?'");
+_assertSame(canvas.getAttribute('height'), '100#!?', "canvas.getAttribute('height')", "'100#!?'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.trailingjunk.png b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.trailingjunk.png
new file mode 100644
index 00000000000..f8426733306
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.trailingjunk.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.whitespace.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.whitespace.html
new file mode 100644
index 00000000000..dc8eab52bc4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.whitespace.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: size.attributes.parse.whitespace</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>size.attributes.parse.whitespace</h1>
+<p class="desc">Parsing of non-negative integers</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="
+ 100" height="
+ 100"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="size.attributes.parse.whitespace.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Parsing of non-negative integers");
+_addTest(function(canvas, ctx) {
+
+_assertSame(canvas.width, 100, "canvas.width", "100");
+_assertSame(canvas.height, 100, "canvas.height", "100");
+_assertSame(window.getComputedStyle(canvas, null).getPropertyValue("width"), "100px", "window.getComputedStyle(canvas, null).getPropertyValue(\"width\")", "\"100px\"");
+_assertSame(canvas.getAttribute('width'), '\n\t\x0c100', "canvas.getAttribute('width')", "'\\n\\t\\x0c100'");
+_assertSame(canvas.getAttribute('height'), '\n\t\x0c100', "canvas.getAttribute('height')", "'\\n\\t\\x0c100'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.whitespace.png b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.whitespace.png
new file mode 100644
index 00000000000..f8426733306
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.whitespace.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.zero.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.zero.html
new file mode 100644
index 00000000000..e42ebeb2424
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.parse.zero.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: size.attributes.parse.zero</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>size.attributes.parse.zero</h1>
+<p class="desc">Parsing of non-negative integers</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="0" height="0"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Parsing of non-negative integers");
+_addTest(function(canvas, ctx) {
+
+_assertSame(canvas.width, 0, "canvas.width", "0");
+_assertSame(canvas.height, 0, "canvas.height", "0");
+_assertSame(window.getComputedStyle(canvas, null).getPropertyValue("width"), "0px", "window.getComputedStyle(canvas, null).getPropertyValue(\"width\")", "\"0px\"");
+_assertSame(canvas.getAttribute('width'), '0', "canvas.getAttribute('width')", "'0'");
+_assertSame(canvas.getAttribute('height'), '0', "canvas.getAttribute('height')", "'0'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.reflect.setcontent.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.reflect.setcontent.html
new file mode 100644
index 00000000000..e77ca8ee0a8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.reflect.setcontent.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: size.attributes.reflect.setcontent</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>size.attributes.reflect.setcontent</h1>
+<p class="desc">Setting content attributes updates IDL and content attributes</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="size.attributes.reflect.setcontent.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Setting content attributes updates IDL and content attributes");
+_addTest(function(canvas, ctx) {
+
+canvas.setAttribute('width', '120');
+canvas.setAttribute('height', '60');
+_assertSame(canvas.getAttribute('width'), '120', "canvas.getAttribute('width')", "'120'");
+_assertSame(canvas.getAttribute('height'), '60', "canvas.getAttribute('height')", "'60'");
+_assertSame(canvas.width, 120, "canvas.width", "120");
+_assertSame(canvas.height, 60, "canvas.height", "60");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.reflect.setcontent.png b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.reflect.setcontent.png
new file mode 100644
index 00000000000..47830c83ea9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.reflect.setcontent.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.reflect.setidl.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.reflect.setidl.html
new file mode 100644
index 00000000000..15228829145
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.reflect.setidl.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: size.attributes.reflect.setidl</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>size.attributes.reflect.setidl</h1>
+<p class="desc">Setting IDL attributes updates IDL and content attributes</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="size.attributes.reflect.setidl.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Setting IDL attributes updates IDL and content attributes");
+_addTest(function(canvas, ctx) {
+
+canvas.width = 120;
+canvas.height = 60;
+_assertSame(canvas.getAttribute('width'), '120', "canvas.getAttribute('width')", "'120'");
+_assertSame(canvas.getAttribute('height'), '60', "canvas.getAttribute('height')", "'60'");
+_assertSame(canvas.width, 120, "canvas.width", "120");
+_assertSame(canvas.height, 60, "canvas.height", "60");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.reflect.setidl.png b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.reflect.setidl.png
new file mode 100644
index 00000000000..47830c83ea9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.reflect.setidl.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.reflect.setidlzero.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.reflect.setidlzero.html
new file mode 100644
index 00000000000..2bace5a3331
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.reflect.setidlzero.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: size.attributes.reflect.setidlzero</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>size.attributes.reflect.setidlzero</h1>
+<p class="desc">Setting IDL attributes to 0 updates IDL and content attributes</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Setting IDL attributes to 0 updates IDL and content attributes");
+_addTest(function(canvas, ctx) {
+
+canvas.width = 0;
+canvas.height = 0;
+_assertSame(canvas.getAttribute('width'), '0', "canvas.getAttribute('width')", "'0'");
+_assertSame(canvas.getAttribute('height'), '0', "canvas.getAttribute('height')", "'0'");
+_assertSame(canvas.width, 0, "canvas.width", "0");
+_assertSame(canvas.height, 0, "canvas.height", "0");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.removed.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.removed.html
new file mode 100644
index 00000000000..58fb899e02a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.removed.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: size.attributes.removed</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>size.attributes.removed</h1>
+<p class="desc">Removing content attributes reverts to default size</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="120" height="60"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="size.attributes.removed.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Removing content attributes reverts to default size");
+_addTest(function(canvas, ctx) {
+
+_assertSame(canvas.width, 120, "canvas.width", "120");
+canvas.removeAttribute('width');
+_assertSame(canvas.width, 300, "canvas.width", "300");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.removed.png b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.removed.png
new file mode 100644
index 00000000000..1ebf30d8aaa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.removed.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.set.png b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.set.png
new file mode 100644
index 00000000000..47830c83ea9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.set.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.decimal.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.decimal.html
new file mode 100644
index 00000000000..0f4fb69fa6f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.decimal.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: size.attributes.setAttribute.decimal</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>size.attributes.setAttribute.decimal</h1>
+<p class="desc">Parsing of non-negative integers in setAttribute</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="50" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="size.attributes.setAttribute.decimal.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Parsing of non-negative integers in setAttribute");
+_addTest(function(canvas, ctx) {
+
+canvas.setAttribute('width', '100.999');
+canvas.setAttribute('height', '100.999');
+_assertSame(canvas.width, 100, "canvas.width", "100");
+_assertSame(canvas.height, 100, "canvas.height", "100");
+_assertSame(window.getComputedStyle(canvas, null).getPropertyValue("width"), "100px", "window.getComputedStyle(canvas, null).getPropertyValue(\"width\")", "\"100px\"");
+_assertSame(canvas.getAttribute('width'), '100.999', "canvas.getAttribute('width')", "'100.999'");
+_assertSame(canvas.getAttribute('height'), '100.999', "canvas.getAttribute('height')", "'100.999'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.decimal.png b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.decimal.png
new file mode 100644
index 00000000000..f8426733306
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.decimal.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.em.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.em.html
new file mode 100644
index 00000000000..5768d1727bd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.em.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: size.attributes.setAttribute.em</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>size.attributes.setAttribute.em</h1>
+<p class="desc">Parsing of non-negative integers in setAttribute</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="50" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="size.attributes.setAttribute.em.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Parsing of non-negative integers in setAttribute");
+_addTest(function(canvas, ctx) {
+
+canvas.setAttribute('width', '100em');
+canvas.setAttribute('height', '100em');
+_assertSame(canvas.width, 100, "canvas.width", "100");
+_assertSame(canvas.height, 100, "canvas.height", "100");
+_assertSame(window.getComputedStyle(canvas, null).getPropertyValue("width"), "100px", "window.getComputedStyle(canvas, null).getPropertyValue(\"width\")", "\"100px\"");
+_assertSame(canvas.getAttribute('width'), '100em', "canvas.getAttribute('width')", "'100em'");
+_assertSame(canvas.getAttribute('height'), '100em', "canvas.getAttribute('height')", "'100em'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.em.png b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.em.png
new file mode 100644
index 00000000000..f8426733306
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.em.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.empty.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.empty.html
new file mode 100644
index 00000000000..65a5bc0d916
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.empty.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: size.attributes.setAttribute.empty</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>size.attributes.setAttribute.empty</h1>
+<p class="desc">Parsing of non-negative integers in setAttribute</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="50" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="size.attributes.setAttribute.empty.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Parsing of non-negative integers in setAttribute");
+_addTest(function(canvas, ctx) {
+
+canvas.setAttribute('width', '');
+canvas.setAttribute('height', '');
+_assertSame(canvas.width, 300, "canvas.width", "300");
+_assertSame(canvas.height, 150, "canvas.height", "150");
+_assertSame(canvas.getAttribute('width'), '', "canvas.getAttribute('width')", "''");
+_assertSame(canvas.getAttribute('height'), '', "canvas.getAttribute('height')", "''");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.empty.png b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.empty.png
new file mode 100644
index 00000000000..a72d047556a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.empty.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.exp.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.exp.html
new file mode 100644
index 00000000000..673edad56b8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.exp.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: size.attributes.setAttribute.exp</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>size.attributes.setAttribute.exp</h1>
+<p class="desc">Parsing of non-negative integers in setAttribute</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="50" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="size.attributes.setAttribute.exp.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Parsing of non-negative integers in setAttribute");
+_addTest(function(canvas, ctx) {
+
+canvas.setAttribute('width', '100e1');
+canvas.setAttribute('height', '100e1');
+_assertSame(canvas.width, 100, "canvas.width", "100");
+_assertSame(canvas.height, 100, "canvas.height", "100");
+_assertSame(window.getComputedStyle(canvas, null).getPropertyValue("width"), "100px", "window.getComputedStyle(canvas, null).getPropertyValue(\"width\")", "\"100px\"");
+_assertSame(canvas.getAttribute('width'), '100e1', "canvas.getAttribute('width')", "'100e1'");
+_assertSame(canvas.getAttribute('height'), '100e1', "canvas.getAttribute('height')", "'100e1'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.exp.png b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.exp.png
new file mode 100644
index 00000000000..f8426733306
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.exp.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.hex.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.hex.html
new file mode 100644
index 00000000000..e6fde5329a8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.hex.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: size.attributes.setAttribute.hex</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>size.attributes.setAttribute.hex</h1>
+<p class="desc">Parsing of non-negative integers in setAttribute</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="50" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Parsing of non-negative integers in setAttribute");
+_addTest(function(canvas, ctx) {
+
+canvas.setAttribute('width', '0x100');
+canvas.setAttribute('height', '0x100');
+_assertSame(canvas.width, 0, "canvas.width", "0");
+_assertSame(canvas.height, 0, "canvas.height", "0");
+_assertSame(window.getComputedStyle(canvas, null).getPropertyValue("width"), "0px", "window.getComputedStyle(canvas, null).getPropertyValue(\"width\")", "\"0px\"");
+_assertSame(canvas.getAttribute('width'), '0x100', "canvas.getAttribute('width')", "'0x100'");
+_assertSame(canvas.getAttribute('height'), '0x100', "canvas.getAttribute('height')", "'0x100'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.junk.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.junk.html
new file mode 100644
index 00000000000..77b50fd1101
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.junk.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: size.attributes.setAttribute.junk</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>size.attributes.setAttribute.junk</h1>
+<p class="desc">Parsing of non-negative integers in setAttribute</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="50" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="size.attributes.setAttribute.junk.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Parsing of non-negative integers in setAttribute");
+_addTest(function(canvas, ctx) {
+
+canvas.setAttribute('width', '#!?');
+canvas.setAttribute('height', '#!?');
+_assertSame(canvas.width, 300, "canvas.width", "300");
+_assertSame(canvas.height, 150, "canvas.height", "150");
+_assertSame(canvas.getAttribute('width'), '#!?', "canvas.getAttribute('width')", "'#!?'");
+_assertSame(canvas.getAttribute('height'), '#!?', "canvas.getAttribute('height')", "'#!?'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.junk.png b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.junk.png
new file mode 100644
index 00000000000..a72d047556a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.junk.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.minus.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.minus.html
new file mode 100644
index 00000000000..2bb09bbf29a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.minus.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: size.attributes.setAttribute.minus</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>size.attributes.setAttribute.minus</h1>
+<p class="desc">Parsing of non-negative integers in setAttribute</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="50" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="size.attributes.setAttribute.minus.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Parsing of non-negative integers in setAttribute");
+_addTest(function(canvas, ctx) {
+
+canvas.setAttribute('width', '-100');
+canvas.setAttribute('height', '-100');
+_assertSame(canvas.width, 300, "canvas.width", "300");
+_assertSame(canvas.height, 150, "canvas.height", "150");
+_assertSame(canvas.getAttribute('width'), '-100', "canvas.getAttribute('width')", "'-100'");
+_assertSame(canvas.getAttribute('height'), '-100', "canvas.getAttribute('height')", "'-100'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.minus.png b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.minus.png
new file mode 100644
index 00000000000..a72d047556a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.minus.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.octal.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.octal.html
new file mode 100644
index 00000000000..a6cb6d37fb7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.octal.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: size.attributes.setAttribute.octal</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>size.attributes.setAttribute.octal</h1>
+<p class="desc">Parsing of non-negative integers in setAttribute</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="50" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="size.attributes.setAttribute.octal.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Parsing of non-negative integers in setAttribute");
+_addTest(function(canvas, ctx) {
+
+canvas.setAttribute('width', '0100');
+canvas.setAttribute('height', '0100');
+_assertSame(canvas.width, 100, "canvas.width", "100");
+_assertSame(canvas.height, 100, "canvas.height", "100");
+_assertSame(window.getComputedStyle(canvas, null).getPropertyValue("width"), "100px", "window.getComputedStyle(canvas, null).getPropertyValue(\"width\")", "\"100px\"");
+_assertSame(canvas.getAttribute('width'), '0100', "canvas.getAttribute('width')", "'0100'");
+_assertSame(canvas.getAttribute('height'), '0100', "canvas.getAttribute('height')", "'0100'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.octal.png b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.octal.png
new file mode 100644
index 00000000000..f8426733306
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.octal.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.onlyspace.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.onlyspace.html
new file mode 100644
index 00000000000..5e2dd0c6cc1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.onlyspace.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: size.attributes.setAttribute.onlyspace</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>size.attributes.setAttribute.onlyspace</h1>
+<p class="desc">Parsing of non-negative integers in setAttribute</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="50" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="size.attributes.setAttribute.onlyspace.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Parsing of non-negative integers in setAttribute");
+_addTest(function(canvas, ctx) {
+
+canvas.setAttribute('width', ' ');
+canvas.setAttribute('height', ' ');
+_assertSame(canvas.width, 300, "canvas.width", "300");
+_assertSame(canvas.height, 150, "canvas.height", "150");
+_assertSame(canvas.getAttribute('width'), ' ', "canvas.getAttribute('width')", "' '");
+_assertSame(canvas.getAttribute('height'), ' ', "canvas.getAttribute('height')", "' '");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.onlyspace.png b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.onlyspace.png
new file mode 100644
index 00000000000..a72d047556a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.onlyspace.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.percent.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.percent.html
new file mode 100644
index 00000000000..2a41c667e82
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.percent.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: size.attributes.setAttribute.percent</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>size.attributes.setAttribute.percent</h1>
+<p class="desc">Parsing of non-negative integers in setAttribute</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="50" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="size.attributes.setAttribute.percent.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Parsing of non-negative integers in setAttribute");
+_addTest(function(canvas, ctx) {
+
+canvas.setAttribute('width', '100%');
+canvas.setAttribute('height', '100%');
+_assertSame(canvas.width, 100, "canvas.width", "100");
+_assertSame(canvas.height, 100, "canvas.height", "100");
+_assertSame(window.getComputedStyle(canvas, null).getPropertyValue("width"), "100px", "window.getComputedStyle(canvas, null).getPropertyValue(\"width\")", "\"100px\"");
+_assertSame(canvas.getAttribute('width'), '100%', "canvas.getAttribute('width')", "'100%'");
+_assertSame(canvas.getAttribute('height'), '100%', "canvas.getAttribute('height')", "'100%'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.percent.png b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.percent.png
new file mode 100644
index 00000000000..f8426733306
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.percent.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.plus.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.plus.html
new file mode 100644
index 00000000000..f384d82d30a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.plus.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: size.attributes.setAttribute.plus</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>size.attributes.setAttribute.plus</h1>
+<p class="desc">Parsing of non-negative integers in setAttribute</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="50" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="size.attributes.setAttribute.plus.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Parsing of non-negative integers in setAttribute");
+_addTest(function(canvas, ctx) {
+
+canvas.setAttribute('width', '+100');
+canvas.setAttribute('height', '+100');
+_assertSame(canvas.width, 100, "canvas.width", "100");
+_assertSame(canvas.height, 100, "canvas.height", "100");
+_assertSame(window.getComputedStyle(canvas, null).getPropertyValue("width"), "100px", "window.getComputedStyle(canvas, null).getPropertyValue(\"width\")", "\"100px\"");
+_assertSame(canvas.getAttribute('width'), '+100', "canvas.getAttribute('width')", "'+100'");
+_assertSame(canvas.getAttribute('height'), '+100', "canvas.getAttribute('height')", "'+100'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.plus.png b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.plus.png
new file mode 100644
index 00000000000..f8426733306
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.plus.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.space.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.space.html
new file mode 100644
index 00000000000..8f858527939
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.space.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: size.attributes.setAttribute.space</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>size.attributes.setAttribute.space</h1>
+<p class="desc">Parsing of non-negative integers in setAttribute</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="50" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="size.attributes.setAttribute.space.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Parsing of non-negative integers in setAttribute");
+_addTest(function(canvas, ctx) {
+
+canvas.setAttribute('width', ' 100');
+canvas.setAttribute('height', ' 100');
+_assertSame(canvas.width, 100, "canvas.width", "100");
+_assertSame(canvas.height, 100, "canvas.height", "100");
+_assertSame(window.getComputedStyle(canvas, null).getPropertyValue("width"), "100px", "window.getComputedStyle(canvas, null).getPropertyValue(\"width\")", "\"100px\"");
+_assertSame(canvas.getAttribute('width'), ' 100', "canvas.getAttribute('width')", "' 100'");
+_assertSame(canvas.getAttribute('height'), ' 100', "canvas.getAttribute('height')", "' 100'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.space.png b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.space.png
new file mode 100644
index 00000000000..f8426733306
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.space.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.trailingjunk.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.trailingjunk.html
new file mode 100644
index 00000000000..f6d06bab012
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.trailingjunk.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: size.attributes.setAttribute.trailingjunk</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>size.attributes.setAttribute.trailingjunk</h1>
+<p class="desc">Parsing of non-negative integers in setAttribute</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="50" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="size.attributes.setAttribute.trailingjunk.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Parsing of non-negative integers in setAttribute");
+_addTest(function(canvas, ctx) {
+
+canvas.setAttribute('width', '100#!?');
+canvas.setAttribute('height', '100#!?');
+_assertSame(canvas.width, 100, "canvas.width", "100");
+_assertSame(canvas.height, 100, "canvas.height", "100");
+_assertSame(window.getComputedStyle(canvas, null).getPropertyValue("width"), "100px", "window.getComputedStyle(canvas, null).getPropertyValue(\"width\")", "\"100px\"");
+_assertSame(canvas.getAttribute('width'), '100#!?', "canvas.getAttribute('width')", "'100#!?'");
+_assertSame(canvas.getAttribute('height'), '100#!?', "canvas.getAttribute('height')", "'100#!?'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.trailingjunk.png b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.trailingjunk.png
new file mode 100644
index 00000000000..f8426733306
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.trailingjunk.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.whitespace.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.whitespace.html
new file mode 100644
index 00000000000..8a01f57ea5d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.whitespace.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: size.attributes.setAttribute.whitespace</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>size.attributes.setAttribute.whitespace</h1>
+<p class="desc">Parsing of non-negative integers in setAttribute</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="50" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="size.attributes.setAttribute.whitespace.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Parsing of non-negative integers in setAttribute");
+_addTest(function(canvas, ctx) {
+
+canvas.setAttribute('width', '\r\n\t\x0c100');
+canvas.setAttribute('height', '\r\n\t\x0c100');
+_assertSame(canvas.width, 100, "canvas.width", "100");
+_assertSame(canvas.height, 100, "canvas.height", "100");
+_assertSame(window.getComputedStyle(canvas, null).getPropertyValue("width"), "100px", "window.getComputedStyle(canvas, null).getPropertyValue(\"width\")", "\"100px\"");
+_assertSame(canvas.getAttribute('width'), '\r\n\t\x0c100', "canvas.getAttribute('width')", "'\\r\\n\\t\\x0c100'");
+_assertSame(canvas.getAttribute('height'), '\r\n\t\x0c100', "canvas.getAttribute('height')", "'\\r\\n\\t\\x0c100'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.whitespace.png b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.whitespace.png
new file mode 100644
index 00000000000..f8426733306
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.whitespace.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.zero.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.zero.html
new file mode 100644
index 00000000000..d1b05ad2096
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.setAttribute.zero.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: size.attributes.setAttribute.zero</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>size.attributes.setAttribute.zero</h1>
+<p class="desc">Parsing of non-negative integers in setAttribute</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="50" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("Parsing of non-negative integers in setAttribute");
+_addTest(function(canvas, ctx) {
+
+canvas.setAttribute('width', '0');
+canvas.setAttribute('height', '0');
+_assertSame(canvas.width, 0, "canvas.width", "0");
+_assertSame(canvas.height, 0, "canvas.height", "0");
+_assertSame(window.getComputedStyle(canvas, null).getPropertyValue("width"), "0px", "window.getComputedStyle(canvas, null).getPropertyValue(\"width\")", "\"0px\"");
+_assertSame(canvas.getAttribute('width'), '0', "canvas.getAttribute('width')", "'0'");
+_assertSame(canvas.getAttribute('height'), '0', "canvas.getAttribute('height')", "'0'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.style.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.style.html
new file mode 100644
index 00000000000..3bab3e79d10
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.style.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: size.attributes.style</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>size.attributes.style</h1>
+<p class="desc">Canvas size is independent of CSS resizing</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="50" height="30" style="width: 100px; height: 50px"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="size.attributes.style.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("Canvas size is independent of CSS resizing");
+_addTest(function(canvas, ctx) {
+
+_assertSame(canvas.width, 50, "canvas.width", "50");
+_assertSame(canvas.height, 30, "canvas.height", "30");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.style.png b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.style.png
new file mode 100644
index 00000000000..eeedd0ff058
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/size.attributes.style.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.arguments.1.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.arguments.1.html
new file mode 100644
index 00000000000..969d4f53839
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.arguments.1.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: toDataURL.arguments.1</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>toDataURL.arguments.1</h1>
+<p class="desc">toDataURL ignores extra arguments</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("toDataURL ignores extra arguments");
+_addTest(function(canvas, ctx) {
+
+var data = canvas.toDataURL('image/png', 'another argument that should not raise an exception');
+assert_regexp_match(data, /^data:image\/png[;,]/);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.arguments.2.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.arguments.2.html
new file mode 100644
index 00000000000..37894660893
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.arguments.2.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: toDataURL.arguments.2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>toDataURL.arguments.2</h1>
+<p class="desc">toDataURL ignores extra arguments</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("toDataURL ignores extra arguments");
+_addTest(function(canvas, ctx) {
+
+var data = canvas.toDataURL('image/png', 'another argument that should not raise an exception', 'and another');
+assert_regexp_match(data, /^data:image\/png[;,]/);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.arguments.3.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.arguments.3.html
new file mode 100644
index 00000000000..236aba5ff8a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.arguments.3.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: toDataURL.arguments.3</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>toDataURL.arguments.3</h1>
+<p class="desc">toDataURL ignores extra arguments</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("toDataURL ignores extra arguments");
+_addTest(function(canvas, ctx) {
+
+// More arguments that should not raise exceptions
+var data = canvas.toDataURL('image/png', null, null, null);
+assert_regexp_match(data, /^data:image\/png[;,]/);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.bogustype.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.bogustype.html
new file mode 100644
index 00000000000..ade95f0ac41
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.bogustype.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: toDataURL.bogustype</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>toDataURL.bogustype</h1>
+<p class="desc">toDataURL with a syntactically invalid type returns a PNG</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("toDataURL with a syntactically invalid type returns a PNG");
+_addTest(function(canvas, ctx) {
+
+var data = canvas.toDataURL('bogus');
+assert_regexp_match(data, /^data:image\/png[;,]/);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.default.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.default.html
new file mode 100644
index 00000000000..84f4c9ed4c6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.default.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: toDataURL.default</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>toDataURL.default</h1>
+<p class="desc">toDataURL with no arguments returns a PNG</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("toDataURL with no arguments returns a PNG");
+_addTest(function(canvas, ctx) {
+
+var data = canvas.toDataURL();
+assert_regexp_match(data, /^data:image\/png[;,]/);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.jpeg.alpha.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.jpeg.alpha.html
new file mode 100644
index 00000000000..80a2fca427d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.jpeg.alpha.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: toDataURL.jpeg.alpha</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>toDataURL.jpeg.alpha</h1>
+<p class="desc">toDataURL with JPEG composites onto black</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="toDataURL.jpeg.alpha.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("toDataURL with JPEG composites onto black");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = 'rgba(128, 255, 128, 0.5)';
+ctx.fillRect(0, 0, 100, 50);
+ctx.globalCompositeOperation = 'destination-over'; // should be ignored by toDataURL
+var data = canvas.toDataURL('image/jpeg');
+ctx.globalCompositeOperation = 'source-over';
+if (!data.match(/^data:image\/jpeg[;,]/)) {
+ _assert(true, "true");
+} else {
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ var img = new Image();
+ deferTest();
+ img.onload = t.step_func_done(function ()
+ {
+ ctx.drawImage(img, 0, 0);
+ _assertPixelApprox(canvas, 50,25, 63,127,63,255, "50,25", "63,127,63,255", 8);
+ });
+ img.src = data;
+}
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.jpeg.alpha.png b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.jpeg.alpha.png
new file mode 100644
index 00000000000..551871295c8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.jpeg.alpha.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.jpeg.primarycolours.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.jpeg.primarycolours.html
new file mode 100644
index 00000000000..a896cbb5cc8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.jpeg.primarycolours.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: toDataURL.jpeg.primarycolours</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>toDataURL.jpeg.primarycolours</h1>
+<p class="desc">toDataURL with JPEG handles simple colours correctly</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="toDataURL.jpeg.primarycolours.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("toDataURL with JPEG handles simple colours correctly");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#ff0';
+ctx.fillRect(0, 0, 25, 40);
+ctx.fillStyle = '#0ff';
+ctx.fillRect(25, 0, 50, 40);
+ctx.fillStyle = '#00f';
+ctx.fillRect(75, 0, 25, 40);
+ctx.fillStyle = '#fff';
+ctx.fillRect(0, 40, 100, 10);
+var data = canvas.toDataURL('image/jpeg'); // it is okay if this returns a PNG instead
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+var img = new Image();
+deferTest();
+img.onload = t.step_func_done(function ()
+{
+ ctx.drawImage(img, 0, 0);
+ _assertPixelApprox(canvas, 12,20, 255,255,0,255, "12,20", "255,255,0,255", 8);
+ _assertPixelApprox(canvas, 50,20, 0,255,255,255, "50,20", "0,255,255,255", 8);
+ _assertPixelApprox(canvas, 87,20, 0,0,255,255, "87,20", "0,0,255,255", 8);
+ _assertPixelApprox(canvas, 50,45, 255,255,255,255, "50,45", "255,255,255,255", 8);
+});
+img.src = data;
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.jpeg.primarycolours.png b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.jpeg.primarycolours.png
new file mode 100644
index 00000000000..cfd13690077
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.jpeg.primarycolours.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.jpeg.quality.basic.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.jpeg.quality.basic.html
new file mode 100644
index 00000000000..aad56cdd5c7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.jpeg.quality.basic.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: toDataURL.jpeg.quality.basic</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>toDataURL.jpeg.quality.basic</h1>
+<p class="desc">toDataURL with JPEG uses the quality parameter</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="toDataURL.jpeg.quality.basic.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("toDataURL with JPEG uses the quality parameter");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#00f';
+ctx.fillRect(0, 0, 100, 50);
+ctx.fillStyle = '#0ff';
+ctx.fillRect(0, 3, 100, 1);
+// Check for JPEG support first
+var data = canvas.toDataURL('image/jpeg');
+if (!data.match(/^data:image\/jpeg[;,]/)) {
+ _assert(true, "true");
+} else {
+ var data_hi = canvas.toDataURL('image/jpeg', 0.99);
+ var data_lo = canvas.toDataURL('image/jpeg', 0.01);
+ ctx.fillStyle = '#f00';
+ ctx.fillRect(0, 0, 100, 50);
+ deferTest();
+ var img_hi = new Image();
+ img_hi.onload = function ()
+ {
+ var img_lo = new Image();
+ img_lo.onload = t.step_func_done(function ()
+ {
+ ctx.drawImage(img_hi, 0, 0, 50, 50, 0, 0, 50, 50);
+ ctx.drawImage(img_lo, 0, 0, 50, 50, 50, 0, 50, 50);
+ _assert(data_hi.length > data_lo.length, "data_hi.length > data_lo.length");
+ _assertPixelApprox(canvas, 25,25, 0,0,255,255, "25,25", "0,0,255,255", 8);
+ _assertPixelApprox(canvas, 75,25, 0,0,255,255, "75,25", "0,0,255,255", 32);
+ });
+ img_lo.src = data_lo;
+ };
+ img_hi.src = data_hi;
+}
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.jpeg.quality.basic.png b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.jpeg.quality.basic.png
new file mode 100644
index 00000000000..2f8a0bc7903
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.jpeg.quality.basic.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.jpeg.quality.notnumber.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.jpeg.quality.notnumber.html
new file mode 100644
index 00000000000..3167e3c095d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.jpeg.quality.notnumber.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: toDataURL.jpeg.quality.notnumber</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>toDataURL.jpeg.quality.notnumber</h1>
+<p class="desc">toDataURL with JPEG handles non-numeric quality parameters</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("toDataURL with JPEG handles non-numeric quality parameters");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#00f';
+ctx.fillRect(0, 0, 100, 50);
+ctx.fillStyle = '#0ff';
+ctx.fillRect(0, 3, 100, 1);
+// Check for JPEG support first
+var data = canvas.toDataURL('image/jpeg');
+if (!data.match(/^data:image\/jpeg[;,]/)) {
+ _assert(true, "true");
+} else {
+ _assertSame(canvas.toDataURL('image/jpeg', 'bogus'), data, "canvas.toDataURL('image/jpeg', 'bogus')", "data");
+ _assertSame(canvas.toDataURL('image/jpeg', {}), data, "canvas.toDataURL('image/jpeg', {})", "data");
+ _assertSame(canvas.toDataURL('image/jpeg', null), data, "canvas.toDataURL('image/jpeg', null)", "data");
+ _assertSame(canvas.toDataURL('image/jpeg', undefined), data, "canvas.toDataURL('image/jpeg', undefined)", "data");
+ _assertSame(canvas.toDataURL('image/jpeg', true), data, "canvas.toDataURL('image/jpeg', true)", "data");
+ _assertSame(canvas.toDataURL('image/jpeg', '0.01'), data, "canvas.toDataURL('image/jpeg', '0.01')", "data");
+}
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.jpeg.quality.outsiderange.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.jpeg.quality.outsiderange.html
new file mode 100644
index 00000000000..885dc99b825
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.jpeg.quality.outsiderange.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: toDataURL.jpeg.quality.outsiderange</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>toDataURL.jpeg.quality.outsiderange</h1>
+<p class="desc">toDataURL with JPEG handles out-of-range quality parameters</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("toDataURL with JPEG handles out-of-range quality parameters");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#00f';
+ctx.fillRect(0, 0, 100, 50);
+ctx.fillStyle = '#0ff';
+ctx.fillRect(0, 3, 100, 1);
+// Check for JPEG support first
+var data = canvas.toDataURL('image/jpeg');
+if (!data.match(/^data:image\/jpeg[;,]/)) {
+ _assert(true, "true");
+} else {
+ _assertSame(canvas.toDataURL('image/jpeg', 10), data, "canvas.toDataURL('image/jpeg', 10)", "data");
+ _assertSame(canvas.toDataURL('image/jpeg', -10), data, "canvas.toDataURL('image/jpeg', -10)", "data");
+ _assertSame(canvas.toDataURL('image/jpeg', 1.01), data, "canvas.toDataURL('image/jpeg', 1.01)", "data");
+ _assertSame(canvas.toDataURL('image/jpeg', -0.01), data, "canvas.toDataURL('image/jpeg', -0.01)", "data");
+
+ _assert(canvas.toDataURL('image/jpeg', 1).length >= canvas.toDataURL('image/jpeg', 0.9).length, "canvas.toDataURL('image/jpeg', 1).length >= canvas.toDataURL('image/jpeg', 0.9).length");
+ _assert(canvas.toDataURL('image/jpeg', 0).length <= canvas.toDataURL('image/jpeg', 0.1).length, "canvas.toDataURL('image/jpeg', 0).length <= canvas.toDataURL('image/jpeg', 0.1).length");
+}
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.lowercase.ascii.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.lowercase.ascii.html
new file mode 100644
index 00000000000..b95c8285b73
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.lowercase.ascii.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: toDataURL.lowercase.ascii</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>toDataURL.lowercase.ascii</h1>
+<p class="desc">toDataURL type is case-insensitive</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("toDataURL type is case-insensitive");
+_addTest(function(canvas, ctx) {
+
+var data = canvas.toDataURL('ImAgE/PnG');
+assert_regexp_match(data, /^data:image\/png[;,]/);
+
+// If JPEG is supported at all, it must be supported case-insensitively
+data = canvas.toDataURL('image/jpeg');
+if (data.match(/^data:image\/jpeg[;,]/)) {
+ data = canvas.toDataURL('ImAgE/JpEg');
+ assert_regexp_match(data, /^data:image\/jpeg[;,]/);
+}
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.lowercase.unicode.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.lowercase.unicode.html
new file mode 100644
index 00000000000..ab06d59ec7c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.lowercase.unicode.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: toDataURL.lowercase.unicode</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>toDataURL.lowercase.unicode</h1>
+<p class="desc">toDataURL type is ASCII-case-insensitive</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("toDataURL type is ASCII-case-insensitive");
+_addTest(function(canvas, ctx) {
+
+// Use LATIN CAPITAL LETTER I WITH DOT ABOVE (Unicode lowercase is "i")
+var data = canvas.toDataURL('\u0130mage/png');
+assert_regexp_match(data, /^data:image\/png[;,]/);
+
+var data = canvas.toDataURL('\u0130mage/jpeg');
+assert_regexp_match(data, /^data:image\/png[;,]/);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.nocontext.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.nocontext.html
new file mode 100644
index 00000000000..f1138ee7275
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.nocontext.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: toDataURL.nocontext</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>toDataURL.nocontext</h1>
+<p class="desc">toDataURL works before any context has been got</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("toDataURL works before any context has been got");
+_addTest(function(canvas, ctx) {
+
+var canvas2 = document.createElement('canvas');
+var data = canvas2.toDataURL();
+assert_regexp_match(data, /^data:image\/png[;,]/);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.png.complexcolours.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.png.complexcolours.html
new file mode 100644
index 00000000000..cc067b737a6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.png.complexcolours.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: toDataURL.png.complexcolours</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>toDataURL.png.complexcolours</h1>
+<p class="desc">toDataURL with PNG handles non-primary and non-solid colours correctly</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="toDataURL.png.complexcolours.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("toDataURL with PNG handles non-primary and non-solid colours correctly");
+_addTest(function(canvas, ctx) {
+
+// (These values are chosen to survive relatively alright through being premultiplied)
+ctx.fillStyle = 'rgba(1, 3, 254, 1)';
+ctx.fillRect(0, 0, 25, 25);
+ctx.fillStyle = 'rgba(8, 252, 248, 0.75)';
+ctx.fillRect(25, 0, 25, 25);
+ctx.fillStyle = 'rgba(6, 10, 250, 0.502)';
+ctx.fillRect(50, 0, 25, 25);
+ctx.fillStyle = 'rgba(12, 16, 244, 0.25)';
+ctx.fillRect(75, 0, 25, 25);
+var img = new Image();
+deferTest();
+img.onload = t.step_func_done(function ()
+{
+ ctx.drawImage(img, 0, 25);
+ // (The alpha values do not really survive float->int conversion, so just
+ // do approximate comparisons)
+ _assertPixel(canvas, 12,40, 1,3,254,255, "12,40", "1,3,254,255");
+ _assertPixelApprox(canvas, 37,40, 8,252,248,191, "37,40", "8,252,248,191", 2);
+ _assertPixelApprox(canvas, 62,40, 6,10,250,127, "62,40", "6,10,250,127", 4);
+ _assertPixelApprox(canvas, 87,40, 12,16,244,63, "87,40", "12,16,244,63", 8);
+});
+img.src = canvas.toDataURL();
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.png.complexcolours.png b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.png.complexcolours.png
new file mode 100644
index 00000000000..9bc81465842
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.png.complexcolours.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.png.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.png.html
new file mode 100644
index 00000000000..39917eb234f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.png.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: toDataURL.png</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>toDataURL.png</h1>
+<p class="desc">toDataURL with image/png returns a PNG</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("toDataURL with image/png returns a PNG");
+_addTest(function(canvas, ctx) {
+
+var data = canvas.toDataURL('image/png');
+assert_regexp_match(data, /^data:image\/png[;,]/);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.png.primarycolours.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.png.primarycolours.html
new file mode 100644
index 00000000000..b962821d771
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.png.primarycolours.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: toDataURL.png.primarycolours</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>toDataURL.png.primarycolours</h1>
+<p class="desc">toDataURL with PNG handles simple colours correctly</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+<p class="output expectedtext">Expected output:<p><img src="toDataURL.png.primarycolours.png" class="output expected" id="expected" alt="">
+<ul id="d"></ul>
+<script>
+var t = async_test("toDataURL with PNG handles simple colours correctly");
+_addTest(function(canvas, ctx) {
+
+ctx.fillStyle = '#ff0';
+ctx.fillRect(0, 0, 25, 40);
+ctx.fillStyle = '#0ff';
+ctx.fillRect(25, 0, 50, 40);
+ctx.fillStyle = '#00f';
+ctx.fillRect(75, 0, 25, 40);
+ctx.fillStyle = '#fff';
+ctx.fillRect(0, 40, 100, 10);
+var data = canvas.toDataURL();
+ctx.fillStyle = '#f00';
+ctx.fillRect(0, 0, 100, 50);
+var img = new Image();
+deferTest();
+img.onload = t.step_func_done(function ()
+{
+ ctx.drawImage(img, 0, 0);
+ _assertPixel(canvas, 12,20, 255,255,0,255, "12,20", "255,255,0,255");
+ _assertPixel(canvas, 50,20, 0,255,255,255, "50,20", "0,255,255,255");
+ _assertPixel(canvas, 87,20, 0,0,255,255, "87,20", "0,0,255,255");
+ _assertPixel(canvas, 50,45, 255,255,255,255, "50,45", "255,255,255,255");
+});
+img.src = data;
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.png.primarycolours.png b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.png.primarycolours.png
new file mode 100644
index 00000000000..cfd13690077
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.png.primarycolours.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.unrecognised.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.unrecognised.html
new file mode 100644
index 00000000000..3526cc3a2b3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.unrecognised.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: toDataURL.unrecognised</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>toDataURL.unrecognised</h1>
+<p class="desc">toDataURL with an unhandled type returns a PNG</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("toDataURL with an unhandled type returns a PNG");
+_addTest(function(canvas, ctx) {
+
+var data = canvas.toDataURL('image/example');
+assert_regexp_match(data, /^data:image\/png[;,]/);
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.zeroheight.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.zeroheight.html
new file mode 100644
index 00000000000..04c11321645
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.zeroheight.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: toDataURL.zeroheight</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>toDataURL.zeroheight</h1>
+<p class="desc">toDataURL on zero-size canvas returns 'data:,'</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" height="0"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("toDataURL on zero-size canvas returns 'data:,'");
+_addTest(function(canvas, ctx) {
+
+var data = canvas.toDataURL();
+_assertSame(data, 'data:,', "data", "'data:,'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.zerosize.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.zerosize.html
new file mode 100644
index 00000000000..7d2913d020e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.zerosize.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: toDataURL.zerosize</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>toDataURL.zerosize</h1>
+<p class="desc">toDataURL on zero-size canvas returns 'data:,'</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="0" height="0"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("toDataURL on zero-size canvas returns 'data:,'");
+_addTest(function(canvas, ctx) {
+
+var data = canvas.toDataURL();
+_assertSame(data, 'data:,', "data", "'data:,'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.zerowidth.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.zerowidth.html
new file mode 100644
index 00000000000..d4020aa51a5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/toDataURL.zerowidth.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: toDataURL.zerowidth</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>toDataURL.zerowidth</h1>
+<p class="desc">toDataURL on zero-size canvas returns 'data:,'</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="0"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("toDataURL on zero-size canvas returns 'data:,'");
+_addTest(function(canvas, ctx) {
+
+var data = canvas.toDataURL();
+_assertSame(data, 'data:,', "data", "'data:,'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/type.delete.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/type.delete.html
new file mode 100644
index 00000000000..98b67b909bb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/type.delete.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: type.delete</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>type.delete</h1>
+<p class="desc">window.HTMLCanvasElement interface object is [[Configurable]]</p>
+
+<p class="notes">Defined in "Web IDL" (draft)
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("window.HTMLCanvasElement interface object is [[Configurable]]");
+_addTest(function(canvas, ctx) {
+
+_assertSame(delete window.HTMLCanvasElement, true, "delete window.HTMLCanvasElement", "true");
+_assertSame(window.HTMLCanvasElement, undefined, "window.HTMLCanvasElement", "undefined");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/type.exists.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/type.exists.html
new file mode 100644
index 00000000000..04aa975707a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/type.exists.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: type.exists</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>type.exists</h1>
+<p class="desc">HTMLCanvasElement is a property of window</p>
+
+<p class="notes">Defined in "Web IDL" (draft)
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("HTMLCanvasElement is a property of window");
+_addTest(function(canvas, ctx) {
+
+_assert(window.HTMLCanvasElement, "window.HTMLCanvasElement");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/type.extend.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/type.extend.html
new file mode 100644
index 00000000000..572273083dc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/type.extend.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: type.extend</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>type.extend</h1>
+<p class="desc">HTMLCanvasElement methods can be added, and the new methods used by canvases</p>
+
+<p class="notes">Defined in "Web IDL" (draft)
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("HTMLCanvasElement methods can be added, and the new methods used by canvases");
+_addTest(function(canvas, ctx) {
+
+window.HTMLCanvasElement.prototype.getZero = function () { return 0; };
+_assertSame(canvas.getZero(), 0, "canvas.getZero()", "0");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/type.name.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/type.name.html
new file mode 100644
index 00000000000..a514effaa9c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/type.name.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: type.name</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>type.name</h1>
+<p class="desc">HTMLCanvasElement type and toString</p>
+
+
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("HTMLCanvasElement type and toString");
+_addTest(function(canvas, ctx) {
+
+_assertSame(Object.prototype.toString.call(canvas), '[object HTMLCanvasElement]', "Object.prototype.toString.call(canvas)", "'[object HTMLCanvasElement]'");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/type.prototype.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/type.prototype.html
new file mode 100644
index 00000000000..029a9fbbd69
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/type.prototype.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: type.prototype</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>type.prototype</h1>
+<p class="desc">window.HTMLCanvasElement has prototype, which is { ReadOnly, DontDelete }. prototype has getContext, which is not</p>
+
+<p class="notes">Defined in "Web IDL" (draft)
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("window.HTMLCanvasElement has prototype, which is { ReadOnly, DontDelete }. prototype has getContext, which is not");
+_addTest(function(canvas, ctx) {
+
+_assert(window.HTMLCanvasElement.prototype, "window.HTMLCanvasElement.prototype");
+_assert(window.HTMLCanvasElement.prototype.getContext, "window.HTMLCanvasElement.prototype.getContext");
+window.HTMLCanvasElement.prototype = null;
+_assert(window.HTMLCanvasElement.prototype, "window.HTMLCanvasElement.prototype");
+delete window.HTMLCanvasElement.prototype;
+_assert(window.HTMLCanvasElement.prototype, "window.HTMLCanvasElement.prototype");
+window.HTMLCanvasElement.prototype.getContext = 1;
+_assertSame(window.HTMLCanvasElement.prototype.getContext, 1, "window.HTMLCanvasElement.prototype.getContext", "1");
+delete window.HTMLCanvasElement.prototype.getContext;
+_assertSame(window.HTMLCanvasElement.prototype.getContext, undefined, "window.HTMLCanvasElement.prototype.getContext", "undefined");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/type.replace.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/type.replace.html
new file mode 100644
index 00000000000..70a08066e3e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-canvas-element/type.replace.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by tools/gentest.py. -->
+<title>Canvas test: type.replace</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/canvas-tests.js"></script>
+<link rel="stylesheet" href="/common/canvas-tests.css">
+<body class="show_output">
+
+<h1>type.replace</h1>
+<p class="desc">HTMLCanvasElement methods can be replaced, and the replacement methods used by canvases</p>
+
+<p class="notes">Defined in "Web IDL" (draft)
+<p class="output">Actual output:</p>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<ul id="d"></ul>
+<script>
+var t = async_test("HTMLCanvasElement methods can be replaced, and the replacement methods used by canvases");
+_addTest(function(canvas, ctx) {
+
+window.HTMLCanvasElement.prototype.getContext = function (name) { return 0; };
+_assertSame(canvas.getContext('2d'), 0, "canvas.getContext('2d')", "0");
+
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-embed-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-embed-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-embed-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-embed-element/embed-dimension.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-embed-element/embed-dimension.html
new file mode 100644
index 00000000000..608ed331c9e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-embed-element/embed-dimension.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: dimension</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-embed-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<embed src="/images/blue.png" height="100" width="100" id="test">
+<script>
+ test(function () {
+ var height = getComputedStyle(document.getElementById("test"), false)["height"];
+ assert_equals(height, "100px", "The height of the embed element should be 100px.");
+ }, "Check the actual length of the embed element's height");
+
+ test(function () {
+ var width = getComputedStyle(document.getElementById("test"), false)["width"];
+ assert_equals(width, "100px", "The width of the embed element should be 100px.");
+ }, "Check the actual length of the embed element's width");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-embed-element/embed-represent-nothing-01.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-embed-element/embed-represent-nothing-01.html
new file mode 100644
index 00000000000..e66bd4a9069
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-embed-element/embed-represent-nothing-01.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: The embed element without src and type attributes represents nothing</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-embed-element">
+<link rel="match" href="embed-represent-nothing-ref.html">
+<meta name="assert" content="Check if the embed element without src and type attributes represents nothing">
+<style>
+ embed {
+ background-color: red;
+ height: 100px;
+ width: 100px;
+ }
+</style>
+<body>
+ <p>Test passes if there is <strong>no red</strong>.</p>
+ <embed>
+</body>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-embed-element/embed-represent-nothing-02.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-embed-element/embed-represent-nothing-02.html
new file mode 100644
index 00000000000..65cd672387f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-embed-element/embed-represent-nothing-02.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: The embed element represents nothing when its type and src attributs are removed</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-embed-element">
+<link rel="match" href="embed-represent-nothing-ref.html">
+<meta name="assert" content="Check if the embed element represents nothing when its src and type attributes are removed">
+<style>
+ embed {
+ background-color: red;
+ height: 100px;
+ width: 100px;
+ }
+</style>
+<body>
+ <p>Test passes if there is <strong>no red</strong>.</p>
+ <embed id="embed" src="/images/red-16x16.png" type="image/png">
+ <script>
+ document.getElementById("embed").removeAttribute("src");
+ document.getElementById("embed").removeAttribute("type");
+ </script>
+</body>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-embed-element/embed-represent-nothing-03.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-embed-element/embed-represent-nothing-03.html
new file mode 100644
index 00000000000..a16f3794aef
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-embed-element/embed-represent-nothing-03.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: The embed element represents nothing when it has a media ancestor</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-embed-element">
+<link rel="match" href="embed-represent-nothing-ref.html">
+<meta name="assert" content="Check if the embed element represents nothing when it has a media ancestor">
+<style>
+ embed {
+ background-color: red;
+ height: 100px;
+ width: 100px;
+ }
+</style>
+<body>
+ <p>Test passes if there is <strong>no red</strong>.</p>
+ <video>
+ <embed src="/images/red-16x16.png">
+ </video>
+</body>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-embed-element/embed-represent-nothing-04.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-embed-element/embed-represent-nothing-04.html
new file mode 100644
index 00000000000..7cc1b668a6b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-embed-element/embed-represent-nothing-04.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: The embed element represents nothing when it has an object ancestor</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-embed-element">
+<link rel="match" href="embed-represent-nothing-ref.html">
+<meta name="assert" content="Check if the embed element represents nothing when it has a object ancestor that is not showing its fallback content">
+<style>
+ embed {
+ background-color: red;
+ height: 100px;
+ width: 100px;
+ }
+</style>
+<body>
+ <p>Test passes if there is <strong>no red</strong>.</p>
+ <object type="application/x-shockwave-flash">
+ <embed src="/images/red-16x16.png">
+ </object>
+</body>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-embed-element/embed-represent-nothing-ref.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-embed-element/embed-represent-nothing-ref.html
new file mode 100644
index 00000000000..91d680debf1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-embed-element/embed-represent-nothing-ref.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Embed Reftest Reference</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<body>
+ <p>Test passes if there is <strong>no red</strong>.</p>
+</body>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-iframe-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-iframe-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-iframe-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-iframe-element/iframe_javascript_url_01.htm b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-iframe-element/iframe_javascript_url_01.htm
new file mode 100644
index 00000000000..fbdb7f75551
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-iframe-element/iframe_javascript_url_01.htm
@@ -0,0 +1,55 @@
+<!DOCTYPE html><html><head><title>javascript: URL creating a document in an about:blank iframe</title>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/embedded-content.html#the-iframe-element">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/embedded-content.html#process-the-iframe-attributes">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-iframe-element">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#process-the-iframe-attributes">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id="log">FAILED (test did not run)</div>
+
+<iframe src="about:blank" name="ifr1"></iframe>
+<iframe src="" name="ifr2"></iframe>
+<iframe src="./" name="ifr3"></iframe>
+
+<script>
+var test = async_test();
+var results = {};
+var expected = {
+ ifr1:{url:"about:blank", sameDom: true},
+ ifr2:{url:"about:blank", sameDom: true},
+ ifr3:{url: location.href.replace(/\/[^\/]*$/, '/'), sameDom: true },
+ ifr4:{url:"about:blank", sameDom: true}
+}
+
+var js_url = 'javascript:"<html><script>var sameDom = false; try{var cn = top.document.body.className;sameDom = true;}catch(e){}; parent.postMessage( {url: document.URL, name: name, sameDom: sameDom}, \'*\')<\/script><body><p>JS-generated document</p></body></<html>";'
+window.addEventListener('message', function(e){
+ var ifr = e.data.name;
+ results[ifr] = e.data;
+ test.step(function(){
+ assert_equals(results[ifr].url, expected[ifr].url);
+ assert_equals(results[ifr].sameDom, expected[ifr].sameDom);
+ }, 'Testing URL and details of IFRAME ' + ifr);
+ if(Object.keys(results).length === Object.keys(expected).length){
+ test.done();
+ }
+}, false);
+
+var ifr = document.createElement('iframe');
+ifr.name = 'ifr4';
+document.body.appendChild(ifr);
+
+window.onload = function () {
+ for (var i = 0, frame, frames = document.getElementsByTagName('iframe'); frame = frames[i]; i++) {
+ try{
+ frame.src = js_url;
+ }catch(e){
+ results[frame.name] = 'Exception on setting!';
+ }
+ };
+}
+
+</script>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_allow_script.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_allow_script.html
new file mode 100644
index 00000000000..5e015ce98d2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_allow_script.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<meta charset="uft-8">
+<title>HTML Test: iframe_sandbox_allow_scripts</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#attr-iframe-sandbox">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-iframe-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<iframe id="testIframe" src="support/sandbox_allow_script.html" sandbox="allow-same-origin" style="display:none"></iframe>
+<div id="log"></div>
+<script>
+ var step1 = false;
+ var t = async_test("iframe_sandbox_allow_scripts");
+
+ setup({timeout:1000});
+ window.addEventListener("message", callback1, false);
+
+ function run() {
+ window.removeEventListener("message", callback1, false);
+ document.getElementById("testIframe").sandbox = "allow-scripts";
+ document.getElementById("testIframe").contentWindow.location.reload();
+ window.addEventListener("message", callback2, false);
+ }
+
+ function callback1(e) {
+ step1= !step1;
+ }
+
+ function callback2(e) {
+ t.step(function () {
+ assert_false(step1, "[allow-scripts] is not set.");
+ assert_equals(e.data, "Script executed", "[allow-scripts] is set.");
+ });
+ t.done();
+ }
+
+ setTimeout(run, 500);
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-iframe-element/move_iframe_in_dom_01.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-iframe-element/move_iframe_in_dom_01.html
new file mode 100644
index 00000000000..efd563f51ac
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-iframe-element/move_iframe_in_dom_01.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<title>moving modified IFRAME in document (original page about:blank, DOM modification)</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="help" href="https://html.spec.whatwg.org/#iframe-load-event-steps">
+<iframe src="about:blank"></iframe>
+<div id="target"></div>
+<script>
+onload = function() {
+ var ifr = document.getElementsByTagName('iframe')[0];
+ ifr.contentDocument.body.appendChild(ifr.contentDocument.createElement('p')).textContent = 'Modified document';
+ setTimeout(function() {
+ ifr.onload = function() {
+ assert_equals(ifr.contentDocument.body.textContent.indexOf('Modified'), -1);
+ done();
+ };
+ document.getElementById('target').appendChild(ifr);
+ }, 100);
+}
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-iframe-element/move_iframe_in_dom_02.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-iframe-element/move_iframe_in_dom_02.html
new file mode 100644
index 00000000000..dbe266b2930
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-iframe-element/move_iframe_in_dom_02.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<title>moving modified IFRAME in document (original page about:blank, document.write modification)</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="help" href="https://html.spec.whatwg.org/#iframe-load-event-steps">
+<iframe src="about:blank"></iframe>
+<div id="target"></div>
+<script>
+onload = function() {
+ var ifr = document.getElementsByTagName('iframe')[0];
+ ifr.contentDocument.open();
+ ifr.contentDocument.write('Modified document');
+ ifr.contentDocument.close();
+ setTimeout(function() {
+ ifr.onload = function() {
+ assert_equals(ifr.contentDocument.body.textContent.indexOf('Modified'), -1);
+ done();
+ };
+ document.getElementById('target').appendChild(ifr);
+ }, 100);
+}
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-iframe-element/move_iframe_in_dom_03.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-iframe-element/move_iframe_in_dom_03.html
new file mode 100644
index 00000000000..c07dd42dc81
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-iframe-element/move_iframe_in_dom_03.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<title>moving modified IFRAME in document (original page from server, DOM modification)</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="help" href="https://html.spec.whatwg.org/#iframe-load-event-steps">
+<iframe src="support/blank.htm"></iframe>
+<div id="target"></div>
+<script>
+onload = function() {
+ var ifr = document.getElementsByTagName('iframe')[0];
+ ifr.contentDocument.body.appendChild(ifr.contentDocument.createElement('p')).textContent = 'Modified document';
+ setTimeout(function() {
+ ifr.onload = function() {
+ assert_equals(ifr.contentDocument.body.textContent.indexOf('Modified'), -1);
+ done();
+ };
+ document.getElementById('target').appendChild(ifr);
+ }, 100);
+}
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-iframe-element/move_iframe_in_dom_04.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-iframe-element/move_iframe_in_dom_04.html
new file mode 100644
index 00000000000..755cd45d34b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-iframe-element/move_iframe_in_dom_04.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<title>moving modified IFRAME in document (original page from server, document.write modification)</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="help" href="https://html.spec.whatwg.org/#iframe-load-event-steps">
+<iframe src="support/blank.htm"></iframe>
+<div id="target"></div>
+<script>
+onload = function(){
+ var ifr = document.getElementsByTagName('iframe')[0];
+ ifr.contentDocument.open();
+ ifr.contentDocument.write('Modified document');
+ ifr.contentDocument.close();
+ setTimeout(function() {
+ ifr.onload = function () {
+ assert_equals(ifr.contentDocument.body.textContent.indexOf('Modified'), -1);
+ done();
+ };
+ document.getElementById('target').appendChild(ifr);
+ }, 100);
+}
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-iframe-element/support/blank.htm b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-iframe-element/support/blank.htm
new file mode 100644
index 00000000000..6c70bcfe4d4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-iframe-element/support/blank.htm
@@ -0,0 +1 @@
+<html></html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-iframe-element/support/sandbox_allow_script.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-iframe-element/support/sandbox_allow_script.html
new file mode 100644
index 00000000000..95c30dec1de
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-iframe-element/support/sandbox_allow_script.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<meta charset="uft-8">
+<title>HTML Test: sandbox_allow_scripts</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<div id="test">Before change</div>
+<script>
+ parent.window.postMessage("Script executed", "*");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/3.jpg b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/3.jpg
new file mode 100644
index 00000000000..d30ac2ac36c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/3.jpg
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/brokenimg.jpg b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/brokenimg.jpg
new file mode 100644
index 00000000000..ccff177ae9b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/brokenimg.jpg
@@ -0,0 +1,4 @@
+<!DOCTYPE HTML>
+<html>
+
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/contains.json b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/contains.json
new file mode 100644
index 00000000000..9ac6d3d4224
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/contains.json
@@ -0,0 +1,60 @@
+[
+ {
+ "id": "alt",
+ "original_id": "alt",
+ "children": [
+ {
+ "id": "general-guidelines",
+ "original_id": "general-guidelines"
+ },
+ {
+ "id": "a-link-or-button-containing-nothing-but-the-image",
+ "original_id": "a-link-or-button-containing-nothing-but-the-image"
+ },
+ {
+ "id": "a-phrase-or-paragraph-with-an-alternative-graphical-representation-charts-diagrams-graphs-maps-illustrations",
+ "original_id": "a-phrase-or-paragraph-with-an-alternative-graphical-representation:-charts,-diagrams,-graphs,-maps,-illustrations"
+ },
+ {
+ "id": "a-short-phrase-or-label-with-an-alternative-graphical-representation-icons-logos",
+ "original_id": "a-short-phrase-or-label-with-an-alternative-graphical-representation:-icons,-logos"
+ },
+ {
+ "id": "text-that-has-been-rendered-to-a-graphic-for-typographical-effect",
+ "original_id": "text-that-has-been-rendered-to-a-graphic-for-typographical-effect"
+ },
+ {
+ "id": "a-graphical-representation-of-some-of-the-surrounding-text",
+ "original_id": "a-graphical-representation-of-some-of-the-surrounding-text"
+ },
+ {
+ "id": "a-purely-decorative-image-that-doesn-t-add-any-information",
+ "original_id": "a-purely-decorative-image-that-doesn't-add-any-information"
+ },
+ {
+ "id": "a-group-of-images-that-form-a-single-larger-picture-with-no-links",
+ "original_id": "a-group-of-images-that-form-a-single-larger-picture-with-no-links"
+ },
+ {
+ "id": "a-group-of-images-that-form-a-single-larger-picture-with-links",
+ "original_id": "a-group-of-images-that-form-a-single-larger-picture-with-links"
+ },
+ {
+ "id": "a-key-part-of-the-content",
+ "original_id": "a-key-part-of-the-content"
+ },
+ {
+ "id": "an-image-not-intended-for-the-user",
+ "original_id": "an-image-not-intended-for-the-user"
+ },
+ {
+ "id": "guidance-for-markup-generators",
+ "original_id": "guidance-for-markup-generators"
+ },
+ {
+ "id": "guidance-for-conformance-checkers",
+ "original_id": "guidance-for-conformance-checkers"
+ }
+ ]
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/current-pixel-density/basic.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/current-pixel-density/basic.html
new file mode 100644
index 00000000000..a7904bf0fe0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/current-pixel-density/basic.html
@@ -0,0 +1,33 @@
+<!doctype html>
+<title>img current pixel density basic</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<img src="/images/green-256x256.png" data-expect="256">
+<img srcset="/images/green-256x256.png 1x" data-expect="256">
+<img srcset="/images/green-256x256.png 1.6x" data-expect="160">
+<img srcset="/images/green-256x256.png 2x" data-expect="128">
+<img srcset="/images/green-256x256.png 10000x" data-expect="0">
+<img srcset="/images/green-256x256.png 9e99999999999999999999999x" data-expect="0">
+<img srcset="/images/green-256x256.png 256w" sizes="256px" data-expect="256">
+<img srcset="/images/green-256x256.png 512w" sizes="256px" data-expect="128">
+<img srcset="/images/green-256x256.png 256w" sizes="512px" data-expect="512">
+<img srcset="/images/green-256x256.png 256w" sizes="1px" data-expect="1">
+<img srcset="/images/green-256x256.png 256w" sizes="0px" data-expect="0">
+<script>
+setup({explicit_done:true});
+onload = function() {
+ [].forEach.call(document.images, function(img) {
+ test(function() {
+ var expected = parseFloat(img.dataset.expect);
+ assert_equals(img.width, expected, 'width');
+ assert_equals(img.height, expected, 'height');
+ assert_equals(img.clientWidth, expected, 'clientWidth');
+ assert_equals(img.clientHeight, expected, 'clientHeight');
+ assert_equals(img.naturalWidth, 256, 'naturalWidth');
+ assert_equals(img.naturalHeight, 256, 'naturalHeight');
+ }, img.outerHTML);
+ });
+ done();
+};
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/current-pixel-density/error.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/current-pixel-density/error.html
new file mode 100644
index 00000000000..00649795f55
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/current-pixel-density/error.html
@@ -0,0 +1,30 @@
+<!doctype html>
+<title>img current pixel density error</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<img id=ref src="404" alt="testing">
+<img srcset="404" alt="testing">
+<img srcset="404 0.5x" alt="testing">
+<img srcset="404 2x" alt="testing">
+<img srcset="404 100w" alt="testing">
+<img srcset="404 100w" sizes="500px" alt="testing">
+<picture><img src="404 100w" sizes="500px" alt="testing"></picture>
+<script>
+setup({explicit_done:true});
+onload = function() {
+ var expected_width = ref.width;
+ var expected_height = ref.height;
+ [].forEach.call(document.images, function(img) {
+ test(function() {
+ assert_not_equals(expected_width, 0, 'expected_width');
+ assert_not_equals(expected_height, 0, 'expected_height');
+ assert_equals(img.width, expected_width, 'width');
+ assert_equals(img.height, expected_height, 'height');
+ assert_equals(img.naturalWidth, 0, 'naturalWidth');
+ assert_equals(img.naturalHeight, 0, 'naturalHeight');
+ }, img.outerHTML);
+ });
+ done();
+};
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/environment-changes/iframed.sub.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/environment-changes/iframed.sub.html
new file mode 100644
index 00000000000..0f7ab9ae272
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/environment-changes/iframed.sub.html
@@ -0,0 +1,78 @@
+<!doctype html>
+
+<img
+data-desc="img (no src)"
+data-narrow=""
+data-wide=""
+data-no-change>
+
+<img src=""
+data-desc="img (empty src)"
+data-narrow=""
+data-wide=""
+data-no-change>
+
+<img src="/images/broken.png?30-{{GET[id]}}"
+data-desc="img (src only) broken image"
+data-narrow="/images/broken.png?30-{{GET[id]}}"
+data-wide="/images/broken.png?30-{{GET[id]}}"
+data-no-change>
+
+<img src="/images/green-1x1.png?40-{{GET[id]}}"
+data-desc="img (src only) valid image"
+data-narrow="/images/green-1x1.png?40-{{GET[id]}}"
+data-wide="/images/green-1x1.png?40-{{GET[id]}}"
+data-no-change>
+
+<img srcset="/images/broken.png?50-{{GET[id]}}"
+data-desc="img (srcset 1 cand) broken image"
+data-narrow="/images/broken.png?50-{{GET[id]}}"
+data-wide="/images/broken.png?50-{{GET[id]}}"
+data-no-change>
+
+<img srcset="/images/green-1x1.png?60-{{GET[id]}}"
+data-desc="img (srcset 1 cand) valid image"
+data-narrow="/images/green-1x1.png?60-{{GET[id]}}"
+data-wide="/images/green-1x1.png?60-{{GET[id]}}"
+data-no-change>
+
+<picture>
+<source media="(max-width:500px)" srcset="/images/broken.png?70-{{GET[id]}}">
+<img src="/images/broken.png?71-{{GET[id]}}"
+data-desc="picture: source (max-width:500px) broken image, img broken image"
+data-narrow="/images/broken.png?70-{{GET[id]}}"
+data-wide="/images/broken.png?71-{{GET[id]}}">
+</picture>
+
+<picture>
+<source media="(max-width:500px)" srcset="/images/broken.png?80-{{GET[id]}}">
+<img src="/images/green-2x2.png?81-{{GET[id]}}"
+data-desc="picture: source (max-width:500px) broken image, img valid image"
+data-narrow="/images/broken.png?80-{{GET[id]}}"
+data-wide="/images/green-2x2.png?81-{{GET[id]}}">
+</picture>
+
+<picture>
+<source media="(max-width:500px)" srcset="/images/green-1x1.png?90-{{GET[id]}}">
+<img src="/images/broken.png?91-{{GET[id]}}"
+data-desc="picture: source (max-width:500px) valid image, img broken image"
+data-narrow="/images/green-1x1.png?90-{{GET[id]}}"
+data-wide="/images/broken.png?91-{{GET[id]}}">
+</picture>
+
+<picture>
+<source media="(max-width:500px)" srcset="/images/green-1x1.png?100-{{GET[id]}}">
+<img src="/images/green-2x2.png?101-{{GET[id]}}"
+data-desc="picture: source (max-width:500px) valid image, img valid image"
+data-narrow="/images/green-1x1.png?100-{{GET[id]}}"
+data-wide="/images/green-2x2.png?101-{{GET[id]}}">
+</picture>
+
+<picture>
+<source media="(max-width:500px)" srcset="/images/green-1x1.png?110-{{GET[id]}}">
+<img src="/images/green-1x1.png?110-{{GET[id]}}"
+data-desc="picture: same URL in source (max-width:500px) and img"
+data-narrow="/images/green-1x1.png?110-{{GET[id]}}"
+data-wide="/images/green-1x1.png?110-{{GET[id]}}"
+data-no-change>
+</picture>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/environment-changes/viewport-change.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/environment-changes/viewport-change.html
new file mode 100644
index 00000000000..21624712cf9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/environment-changes/viewport-change.html
@@ -0,0 +1,65 @@
+<!doctype html>
+<title>img viewport change</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/utils.js"></script>
+<style>
+.narrow { width:50px }
+.wide { width:1000px }
+</style>
+<div id=log></div>
+<script>
+setup({explicit_done:true});
+
+function resolve(url) {
+ if (url === "") {
+ return url;
+ }
+ var a = document.createElement('a');
+ a.href = url;
+ return a.href;
+}
+
+function insertIframe(className) {
+ var iframe = document.createElement('iframe');
+ iframe.className = className;
+ iframe.src = 'iframed.sub.html?id=' + token();
+ document.body.appendChild(iframe);
+}
+insertIframe('narrow');
+insertIframe('wide');
+
+var start_date = new Date();
+
+onload = function() {
+ var load_time = new Date() - start_date;
+ var iframes = document.getElementsByTagName('iframe');
+ [].forEach.call(iframes, function(iframe) {
+ [].forEach.call(iframe.contentDocument.images, function(img) {
+ var expected = {wide:resolve(img.dataset.wide), narrow:resolve(img.dataset.narrow)};
+ var current = iframe.className;
+ var next = current === 'wide' ? 'narrow' : 'wide';
+ var expect_change = expected[next].indexOf('broken.png') !== 0 && !('noChange' in img.dataset);
+
+ test(function() {
+ assert_equals(img.currentSrc, expected[current]);
+ }, img.dataset.desc + ', onload, ' + current);
+
+ async_test(function() {
+ img.onload = this.unreached_func('Got unexpected load event');
+ img.onerror = this.unreached_func('Got unexpected error event');
+ if (expect_change) {
+ img.onload = this.step_func_done(function() {
+ assert_equals(img.currentSrc, expected[next]);
+ });
+ } else {
+ setTimeout(this.step_func_done(), 500 + load_time);
+ }
+ }, img.dataset.desc + ', resize to ' + next);
+ });
+ iframe.classList.toggle('wide');
+ iframe.classList.toggle('narrow');
+ });
+ done();
+}
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/image-1.jpg b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/image-1.jpg
new file mode 100644
index 00000000000..2fb0255609a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/image-1.jpg
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/img.complete.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/img.complete.html
new file mode 100644
index 00000000000..a34010aadde
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/img.complete.html
@@ -0,0 +1,82 @@
+<!DOCTYPE HTML>
+<title>DOM img complete Test</title>
+<meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
+<link rel="author" title="Anselm Hannemann" href="http://anselm-hannemann.com/" />
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-img-complete" />
+<meta name="assert" content="Tests the complete status of the img-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<img id="imgTestTag">
+<img src="" id="imgTestTag2">
+<img id="imgTestTag3" style="width: 80px; height:auto;">
+<img id="imgTestTag4">
+
+<script>
+ var imageInstance = document.createElement('img');
+ imageInstance.style.display = 'none';
+
+ document.body.appendChild(imageInstance);
+</script>
+
+<div id="log"></div>
+<script>
+ test(function() {
+ assert_true(document.getElementById("imgTestTag").complete);
+ }, "img src omitted");
+
+ test(function() {
+ assert_true(document.getElementById("imgTestTag2").complete);
+ }, "img src empty");
+
+ // test if set to true after img is completely available
+ var t = async_test("async src complete test");
+
+ t.step(function(){
+ document.getElementById("imgTestTag3").src = '3.jpg?nocache=' + Math.random();
+
+ //test if img.complete is set to false if src is changed
+ assert_false(document.getElementById("imgTestTag3").complete, "src changed, should be set to false")
+ });
+
+ document.getElementById("imgTestTag3").onload = t.step_func(function(){
+ assert_true(document.getElementById("imgTestTag3").complete);
+ t.done();
+ });
+
+ // https://html.spec.whatwg.org/multipage/multipage/embedded-content-1.html#update-the-image-data
+ // says to "await a stable state" before fetching so we use a separate <script>
+ imageInstance.src = 'image-1.jpg?pipe=trickle(d1)&nocache=' + Math.random(); // make sure the image isn't in cache
+</script>
+<script>
+ // test: The final task that is queued by the networking task source once the resource has been fetched has been queued, but has not yet been run, and the img element is not in the broken state
+ async_test(function(t) {
+ assert_false(imageInstance.complete, "imageInstance.complete should be false");
+ var startTime = Date.now();
+ while (true) {
+ if (Date.now() - startTime > 2000)
+ assert_unreached('.complete didn\'t change to true');
+ if (imageInstance.complete === true) break;
+ }
+ t.done();
+ },
+ 'IDL attribute complete returns true when image resource has been fetched but not run yet & image is not in broken state');
+
+ // test if broken img does not pass
+ var t2 = async_test("async src broken test");
+ var img4 = document.getElementById("imgTestTag4");
+
+ t2.step(
+ function(){
+ img4.src = 'brokenimg.jpg';
+
+ //test if img.complete is set to false if src is changed
+ assert_false(img4.complete, "src changed to broken img, should be set to false");
+ });
+
+ img4.onload = img4.onerror = t2.step_func(function(event){
+ assert_equals(event.type, "error");
+ assert_true(img4.complete);
+ t2.done();
+ });
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/relevant-mutations.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/relevant-mutations.html
new file mode 100644
index 00000000000..535bada1f23
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/relevant-mutations.html
@@ -0,0 +1,386 @@
+<!doctype html>
+<title>img relevant mutations</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+
+<!-- should invoke update the image data -->
+
+<img data-desc="src set">
+<img src="/images/green-2x2.png" data-desc="src changed">
+<img src="/images/green-2x2.png" data-desc="src removed">
+
+<img data-desc="srcset set">
+<img srcset="/images/green-2x2.png" data-desc="srcset changed">
+<img srcset="/images/green-2x2.png" data-desc="srcset removed">
+
+<img data-desc="sizes set">
+<img sizes="" data-desc="sizes changed">
+<img sizes="" data-desc="sizes removed">
+
+<img src="/images/green-2x2.png" data-desc="src set to same value">
+
+<img data-desc="crossorigin absent to empty">
+<img data-desc="crossorigin absent to anonymous">
+<img data-desc="crossorigin absent to use-credentials">
+<img crossorigin data-desc="crossorigin empty to absent">
+<img crossorigin data-desc="crossorigin empty to use-credentials">
+<img crossorigin=anonymous data-desc="crossorigin anonymous to absent">
+<img crossorigin=anonymous data-desc="crossorigin anonymous to use-credentials">
+<img crossorigin=use-credentials data-desc="crossorigin use-credentials to absent">
+<img crossorigin=use-credentials data-desc="crossorigin use-credentials to empty">
+<img crossorigin=use-credentials data-desc="crossorigin use-credentials to anonymous">
+
+<img src="/images/green-2x2.png" data-desc="inserted into picture"><picture></picture>
+
+<picture><img src="/images/green-2x2.png" data-desc="removed from picture"></picture>
+
+<picture><img src="/images/green-2x2.png" data-desc="parent is picture, previous source inserted"></picture>
+
+<picture><source><img src="/images/green-2x2.png" data-desc="parent is picture, previous source removed"></picture>
+
+<picture><source><img src="/images/green-2x2.png" data-desc="parent is picture, previous source has srcset set"></picture>
+<picture><source srcset=""><img src="/images/green-2x2.png" data-desc="parent is picture, previous source has srcset changed"></picture>
+<picture><source srcset=""><img src="/images/green-2x2.png" data-desc="parent is picture, previous source has srcset removed"></picture>
+
+<picture><source><img src="/images/green-2x2.png" data-desc="parent is picture, previous source has sizes set"></picture>
+<picture><source sizes=""><img src="/images/green-2x2.png" data-desc="parent is picture, previous source has sizes changed"></picture>
+<picture><source sizes=""><img src="/images/green-2x2.png" data-desc="parent is picture, previous source has sizes removed"></picture>
+
+<picture><source><img src="/images/green-2x2.png" data-desc="parent is picture, previous source has media set"></picture>
+<picture><source media=""><img src="/images/green-2x2.png" data-desc="parent is picture, previous source has media changed"></picture>
+<picture><source media=""><img src="/images/green-2x2.png" data-desc="parent is picture, previous source has media removed"></picture>
+
+<picture><source><img src="/images/green-2x2.png" data-desc="parent is picture, previous source has type set"></picture>
+<picture><source type=""><img src="/images/green-2x2.png" data-desc="parent is picture, previous source has type changed"></picture>
+<picture><source type=""><img src="/images/green-2x2.png" data-desc="parent is picture, previous source has type removed"></picture>
+
+<!-- should not invoke update the image data -->
+
+<img srcset="/images/green-2x2.png" data-desc="srcset is set to same value">
+<img srcset="/images/green-2x2.png" sizes data-desc="sizes is set to same value">
+
+<img src="/images/green-2x2.png" data-desc="crossorigin state not changed: absent, removeAttribute">
+<img src="/images/green-2x2.png" crossorigin data-desc="crossorigin state not changed: empty to anonymous">
+<img src="/images/green-2x2.png" crossorigin=anonymous data-desc="crossorigin state not changed: anonymous to foobar">
+<img src="/images/green-2x2.png" crossorigin=use-credentials data-desc="crossorigin state not changed: use-credentials to USE-CREDENTIALS">
+
+<img src="/images/green-2x2.png" data-desc="inserted into picture ancestor"><picture><span></span></picture>
+<picture><span><img src="/images/green-2x2.png" data-desc="removed from picture ancestor"></span></picture>
+
+<picture><span><img src="/images/green-2x2.png" data-desc="ancestor picture has a source inserted"></span></picture>
+<picture><source><span><img src="/images/green-2x2.png" data-desc="ancestor picture has a source removed"></span></picture>
+
+<picture><span><img src="/images/green-2x2.png" data-desc="ancestor picture; previous sibling source inserted"></span></picture>
+<picture><span><source><img src="/images/green-2x2.png" data-desc="ancestor picture; previous sibling source removed"></span></picture>
+
+<picture><img src="/images/green-2x2.png" data-desc="parent is picture, following sibling source inserted"></picture>
+<picture><img src="/images/green-2x2.png" data-desc="parent is picture, following sibling source removed"><source></picture>
+
+<picture><img src="/images/green-2x2.png" data-desc="parent is picture, following sibling source has srcset set"><source></picture>
+
+<img src="/images/green-2x2.png" data-desc="media on img set">
+<img src="/images/green-2x2.png" data-desc="type on img set">
+<img src="/images/green-2x2.png" data-desc="class on img set">
+<img src="/images/green-2x2.png" data-desc="alt on img set">
+
+<picture><source><img src="/images/green-2x2.png" data-desc="src on previous sibling source set"></picture>
+<picture><source><img src="/images/green-2x2.png" data-desc="class on previous sibling source set"></picture>
+
+<img src="/images/green-2x2.png" data-desc="inserted/removed children of img">
+
+<picture><img src="/images/green-2x2.png" data-desc="picture is inserted"></picture><span></span>
+<picture><img src="/images/green-2x2.png" data-desc="picture is removed"></picture>
+
+<picture><img src="/images/green-2x2.png" data-desc="parent is picture, following img inserted"></picture>
+<picture><img src="/images/green-2x2.png" data-desc="parent is picture, following img removed"><img></picture>
+<picture><img src="/images/green-2x2.png" data-desc="parent is picture, following img has src set"><img></picture>
+<picture><img src="/images/green-2x2.png" data-desc="parent is picture, following img has srcset set"><img></picture>
+<picture><img src="/images/green-2x2.png" data-desc="parent is picture, following img has sizes set"><img></picture>
+
+
+<script>
+setup({explicit_done:true});
+
+function t(desc, func, expect) {
+ async_test(function() {
+ var img = document.querySelector('[data-desc="' + desc + '"]');
+ img.onload = img.onerror = this.unreached_func('update the image data was run');
+ if (expect == 'timeout') {
+ setTimeout(this.step_func_done(), 250);
+ } else {
+ img['on' + expect] = this.step_func_done(function() {});
+ setTimeout(this.unreached_func('update the image data was not run'), 250)
+ }
+ func.call(this, img);
+ }, desc);
+}
+
+onload = function() {
+
+ t('src set', function(img) {
+ img.src = '/images/green-2x2.png';
+ }, 'load');
+
+ t('src changed', function(img) {
+ img.src = '/images/green-2x2.png ';
+ }, 'load');
+
+ t('src removed', function(img) {
+ img.removeAttribute('src');
+ }, 'error');
+
+ t('srcset set', function(img) {
+ img.srcset = '/images/green-2x2.png';
+ }, 'load');
+
+ t('srcset changed', function(img) {
+ img.srcset = '/images/green-2x2.png ';
+ }, 'load');
+
+ t('srcset removed', function(img) {
+ img.removeAttribute('srcset');
+ }, 'error');
+
+ t('sizes set', function(img) {
+ img.sizes = '';
+ }, 'error');
+
+ t('sizes changed', function(img) {
+ img.sizes = ' ';
+ }, 'error');
+
+ t('sizes removed', function(img) {
+ img.removeAttribute('sizes');
+ }, 'error');
+
+ t('src set to same value', function(img) {
+ img.src = '/images/green-2x2.png';
+ }, 'load');
+
+ t('crossorigin absent to empty', function(img) {
+ img.crossOrigin = '';
+ }, 'error');
+
+ t('crossorigin absent to anonymous', function(img) {
+ img.crossOrigin = 'anonymous';
+ }, 'error');
+
+ t('crossorigin absent to use-credentials', function(img) {
+ img.crossOrigin = 'use-credentials';
+ }, 'error');
+
+ t('crossorigin empty to absent', function(img) {
+ img.removeAttribute('crossorigin');
+ }, 'error');
+
+ t('crossorigin empty to use-credentials', function(img) {
+ img.crossOrigin = 'use-credentials';
+ }, 'error');
+
+ t('crossorigin anonymous to absent', function(img) {
+ img.removeAttribute('crossorigin');
+ }, 'error');
+
+ t('crossorigin anonymous to use-credentials', function(img) {
+ img.crossOrigin = 'use-credentials';
+ }, 'error');
+
+ t('crossorigin use-credentials to absent', function(img) {
+ img.removeAttribute('crossorigin');
+ }, 'error');
+
+ t('crossorigin use-credentials to empty', function(img) {
+ img.crossOrigin = '';
+ });
+
+ t('crossorigin use-credentials to anonymous', function(img) {
+ img.crossOrigin = 'anonymous';
+ });
+
+ t('inserted into picture', function(img) {
+ img.nextSibling.appendChild(img);
+ }, 'load');
+
+ t('removed from picture', function(img) {
+ img.parentNode.removeChild(img);
+ }, 'load');
+
+ t('parent is picture, previous source inserted', function(img) {
+ img.parentNode.insertBefore(document.createElement('source'), img);
+ }, 'load');
+
+ t('parent is picture, previous source removed', function(img) {
+ img.parentNode.removeChild(img.previousSibling);
+ }, 'load');
+
+ t('parent is picture, previous source has srcset set', function(img) {
+ img.previousSibling.srcset = '';
+ }, 'load');
+
+ t('parent is picture, previous source has srcset changed', function(img) {
+ img.previousSibling.srcset = ' ';
+ }, 'load');
+
+ t('parent is picture, previous source has srcset removed', function(img) {
+ img.previousSibling.removeAttribute('srcset');
+ }, 'load');
+
+ t('parent is picture, previous source has sizes set', function(img) {
+ img.previousSibling.sizes = '';
+ }, 'load');
+
+ t('parent is picture, previous source has sizes changed', function(img) {
+ img.previousSibling.sizes = ' ';
+ }, 'load');
+
+ t('parent is picture, previous source has sizes removed', function(img) {
+ img.previousSibling.removeAttribute('sizes');
+ }, 'load');
+
+ t('parent is picture, previous source has media set', function(img) {
+ img.previousSibling.media = '';
+ }, 'load');
+
+ t('parent is picture, previous source has media changed', function(img) {
+ img.previousSibling.media = ' ';
+ }, 'load');
+
+ t('parent is picture, previous source has media removed', function(img) {
+ img.previousSibling.removeAttribute('media');
+ }, 'load');
+
+ t('parent is picture, previous source has type set', function(img) {
+ img.previousSibling.type = '';
+ }, 'load');
+
+ t('parent is picture, previous source has type changed', function(img) {
+ img.previousSibling.type = ' ';
+ }, 'load');
+
+ t('parent is picture, previous source has type removed', function(img) {
+ img.previousSibling.removeAttribute('type');
+ }, 'load');
+
+ t('srcset is set to same value', function(img) {
+ img.srcset = "/images/green-2x2.png";
+ }, 'timeout');
+
+ t('sizes is set to same value', function(img) {
+ img.sizes = '';
+ }, 'timeout');
+
+ t('crossorigin state not changed: absent, removeAttribute', function(img) {
+ img.removeAttribute('crossorigin');
+ }, 'timeout');
+
+ t('crossorigin state not changed: empty to anonymous', function(img) {
+ img.crossOrigin = 'anonymous';
+ }, 'timeout');
+
+ t('crossorigin state not changed: anonymous to foobar', function(img) {
+ img.crossOrigin = 'foobar';
+ }, 'timeout');
+
+ t('crossorigin state not changed: use-credentials to USE-CREDENTIALS', function(img) {
+ img.crossOrigin = 'USE-CREDENTIALS';
+ }, 'timeout');
+
+ t('inserted into picture ancestor', function(img) {
+ img.nextSibling.firstChild.appendChild(img);
+ }, 'timeout');
+
+ t('removed from picture ancestor', function(img) {
+ img.parentNode.removeChild(img);
+ }, 'timeout');
+
+ t('ancestor picture has a source inserted', function(img) {
+ img.parentNode.parentNode.insertBefore(document.createElement('source'), img.parentNode);
+ }, 'timeout');
+
+ t('ancestor picture has a source removed', function(img) {
+ img.parentNode.parentNode.removeChild(img.parentNode.previousSibling);
+ }, 'timeout');
+
+ t('ancestor picture; previous sibling source inserted', function(img) {
+ img.parentNode.insertBefore(document.createElement('source'), img);
+ }, 'timeout');
+
+ t('ancestor picture; previous sibling source removed', function(img) {
+ img.parentNode.removeChild(img.previousSibling);
+ }, 'timeout');
+
+ t('parent is picture, following sibling source inserted', function(img) {
+ img.parentNode.appendChild(document.createElement('source'));
+ }, 'timeout');
+
+ t('parent is picture, following sibling source removed', function(img) {
+ img.parentNode.removeChild(img.nextSibling);
+ }, 'timeout');
+
+ t('parent is picture, following sibling source has srcset set', function(img) {
+ img.nextSibling.srcset = '';
+ }, 'timeout');
+
+ t('media on img set', function(img) {
+ img.setAttribute('media', '');
+ }, 'timeout');
+
+ t('type on img set', function(img) {
+ img.setAttribute('type', '');
+ }, 'timeout');
+
+ t('class on img set', function(img) {
+ img.className = '';
+ }, 'timeout');
+
+ t('alt on img set', function(img) {
+ img.alt = '';
+ }, 'timeout');
+
+ t('src on previous sibling source set', function(img) {
+ img.previousSibling.setAttribute('src', '');
+ }, 'timeout');
+
+ t('class on previous sibling source set', function(img) {
+ img.previousSibling.className = '';
+ }, 'timeout');
+
+ t('inserted/removed children of img', function(img) {
+ img.appendChild(document.createElement('source'));
+ setTimeout(this.step_func(function() {
+ img.removeChild(img.firstChild);
+ }), 0);
+ }, 'timeout');
+
+ t('picture is inserted', function(img) {
+ img.parentNode.nextSibling.appendChild(img.parentNode);
+ }, 'timeout');
+
+ t('picture is removed', function(img) {
+ img.parentNode.parentNode.removeChild(img.parentNode);
+ }, 'timeout');
+
+ t('parent is picture, following img inserted', function(img) {
+ img.parentNode.appendChild(document.createElement('img'));
+ }, 'timeout');
+
+ t('parent is picture, following img removed', function(img) {
+ img.parentNode.removeChild(img.nextSibling);
+ }, 'timeout');
+
+ t('parent is picture, following img has src set', function(img) {
+ img.nextSibling.src = '';
+ }, 'timeout');
+
+ t('parent is picture, following img has srcset set', function(img) {
+ img.nextSibling.srcset = '';
+ }, 'timeout');
+
+ t('parent is picture, following img has sizes set', function(img) {
+ img.nextSibling.sizes = '';
+ }, 'timeout');
+
+ done();
+};
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/sizes/parse-a-sizes-attribute.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/sizes/parse-a-sizes-attribute.html
new file mode 100644
index 00000000000..bd204542081
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/sizes/parse-a-sizes-attribute.html
@@ -0,0 +1,42 @@
+<!doctype html>
+<title>img parse a sizes attribute</title>
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<iframe data-desc="standards mode" style="width:1000px; height:1000px" src="sizes-iframed.sub.html?doctype=doctype%20html&style="></iframe>
+<iframe data-desc="quirks mode" style="width:1000px; height:1000px" src="sizes-iframed.sub.html?doctype=----&style="></iframe>
+<iframe data-desc="display:none" style="width:1000px; height:1000px" src="sizes-iframed.sub.html?doctype=doctype%20html&style=display:none"></iframe>
+<iframe data-desc="width:1000px" style="width:1000px; height:1000px" src="sizes-iframed.sub.html?doctype=doctype%20html&style=width:1000px%3B%20height:16px"></iframe>
+<script>
+setup({explicit_done:true});
+
+function check(p, iframe) {
+ var current = p.firstElementChild;
+ var ref_sizes = current.getAttribute('sizes');
+ var expect = p.firstElementChild.currentSrc;
+ if (expect) {
+ expect = expect.split('?')[0];
+ }
+ while (current = current.nextElementSibling) {
+ test(function() {
+ if (expect === '' || expect === null || expect === undefined) {
+ assert_unreached('ref currentSrc was ' + format_value(expect));
+ }
+ var got = current.currentSrc;
+ assert_greater_than(got.indexOf('?'), -1, 'expected a "?" in currentSrc');
+ got = got.split('?')[0];
+ assert_equals(got, expect);
+ }, current.outerHTML + ' ref sizes=' + format_value(ref_sizes) + ' (' + iframe.getAttribute('data-desc') + ')');
+ }
+}
+
+onload = function() {
+ [].forEach.call(document.querySelectorAll('iframe'), function(iframe) {
+ [].forEach.call(iframe.contentDocument.querySelectorAll('p'), function(p) {
+ check(p, iframe);
+ });
+ });
+ done();
+}
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/sizes/sizes-iframed.sub.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/sizes/sizes-iframed.sub.html
new file mode 100644
index 00000000000..c0f3c43f97c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/sizes/sizes-iframed.sub.html
@@ -0,0 +1,170 @@
+<!{{GET[doctype]}}>
+<style> img { {{GET[style]}} } </style>
+<!-- First <img> in a <p> is the reference. The following <img>s should be equivalent -->
+<!-- default is 100vw, not 300px -->
+<p>
+<img srcset='/images/green-1x1.png?a1 300w, /images/green-16x16.png?a1 301w' sizes='100vw'>
+<img srcset='/images/green-1x1.png?a2 300w, /images/green-16x16.png?a2 301w'>
+<p>
+<img srcset='/images/green-1x1.png?b1 450w, /images/green-16x16.png?b1 451w' sizes='100vw'>
+<img srcset='/images/green-1x1.png?b2 450w, /images/green-16x16.png?b2 451w'>
+<p>
+<img srcset='/images/green-1x1.png?c1 600w, /images/green-16x16.png?c1 601w' sizes='100vw'>
+<img srcset='/images/green-1x1.png?c2 600w, /images/green-16x16.png?c2 601w'>
+<p>
+<img srcset='/images/green-1x1.png?d1 900w, /images/green-16x16.png?d1 901w' sizes='100vw'>
+<img srcset='/images/green-1x1.png?d2 900w, /images/green-16x16.png?d2 901w'>
+
+<p>
+<img srcset='/images/green-1x1.png?e1 50w, /images/green-16x16.png?e1 51w' sizes='1px'>
+<img srcset='/images/green-1x1.png?e2 50w, /images/green-16x16.png?e2 51w' sizes='0'>
+<img srcset='/images/green-1x1.png?e3 50w, /images/green-16x16.png?e3 51w' sizes='-0'>
+<img srcset='/images/green-1x1.png?e4 50w, /images/green-16x16.png?e4 51w' sizes='+0'>
+<img srcset='/images/green-1x1.png?e5 50w, /images/green-16x16.png?e5 51w' sizes='+1px'>
+<img srcset='/images/green-1x1.png?e6 50w, /images/green-16x16.png?e6 51w' sizes='.1px'>
+<img srcset='/images/green-1x1.png?e7 50w, /images/green-16x16.png?e7 51w' sizes='0.1em'>
+<img srcset='/images/green-1x1.png?e8 50w, /images/green-16x16.png?e8 51w' sizes='0.1ex'>
+<img srcset='/images/green-1x1.png?e9 50w, /images/green-16x16.png?e9 51w' sizes='0.1ch'>
+<img srcset='/images/green-1x1.png?e10 50w, /images/green-16x16.png?e10 51w' sizes='0.1rem'>
+<img srcset='/images/green-1x1.png?e11 50w, /images/green-16x16.png?e11 51w' sizes='0.1vw'>
+<img srcset='/images/green-1x1.png?e12 50w, /images/green-16x16.png?e12 51w' sizes='0.1vh'>
+<img srcset='/images/green-1x1.png?e13 50w, /images/green-16x16.png?e13 51w' sizes='0.1vmin'>
+<img srcset='/images/green-1x1.png?e14 50w, /images/green-16x16.png?e14 51w' sizes='0.1vmax'>
+<img srcset='/images/green-1x1.png?e15 50w, /images/green-16x16.png?e15 51w' sizes='0.1cm'>
+<img srcset='/images/green-1x1.png?e16 50w, /images/green-16x16.png?e16 51w' sizes='1mm'>
+<img srcset='/images/green-1x1.png?e17 50w, /images/green-16x16.png?e17 51w' sizes='1q'>
+<img srcset='/images/green-1x1.png?e18 50w, /images/green-16x16.png?e18 51w' sizes='0.01in'>
+<img srcset='/images/green-1x1.png?e19 50w, /images/green-16x16.png?e19 51w' sizes='0.1pc'>
+<img srcset='/images/green-1x1.png?e20 50w, /images/green-16x16.png?e20 51w' sizes='0.1pt'>
+<img srcset='/images/green-1x1.png?e21 50w, /images/green-16x16.png?e21 51w' sizes='/* */1px/* */'>
+<img srcset='/images/green-1x1.png?e22 50w, /images/green-16x16.png?e22 51w' sizes=' /**/ /**/ 1px /**/ /**/ '>
+<img srcset='/images/green-1x1.png?e23 50w, /images/green-16x16.png?e23 51w' sizes='(),1px'>
+<img srcset='/images/green-1x1.png?e24 50w, /images/green-16x16.png?e24 51w' sizes='x(),1px'>
+<img srcset='/images/green-1x1.png?e25 50w, /images/green-16x16.png?e25 51w' sizes='{},1px'>
+<img srcset='/images/green-1x1.png?e26 50w, /images/green-16x16.png?e26 51w' sizes='[],1px'>
+<img srcset='/images/green-1x1.png?e27 50w, /images/green-16x16.png?e27 51w' sizes='1px,('>
+<img srcset='/images/green-1x1.png?e28 50w, /images/green-16x16.png?e28 51w' sizes='1px,x('>
+<img srcset='/images/green-1x1.png?e29 50w, /images/green-16x16.png?e29 51w' sizes='1px,{'>
+<img srcset='/images/green-1x1.png?e30 50w, /images/green-16x16.png?e30 51w' sizes='1px,['>
+<img srcset='/images/green-1x1.png?e31 50w, /images/green-16x16.png?e31 51w' sizes='\(,1px'>
+<img srcset='/images/green-1x1.png?e32 50w, /images/green-16x16.png?e32 51w' sizes='x\(,1px'>
+<img srcset='/images/green-1x1.png?e33 50w, /images/green-16x16.png?e33 51w' sizes='\{,1px'>
+<img srcset='/images/green-1x1.png?e34 50w, /images/green-16x16.png?e34 51w' sizes='\[,1px'>
+<img srcset='/images/green-1x1.png?e35 50w, /images/green-16x16.png?e35 51w' sizes='1\p\x'>
+<img srcset='/images/green-1x1.png?e36 50w, /images/green-16x16.png?e36 51w' sizes='calc(1px)'>
+<img srcset='/images/green-1x1.png?e37 50w, /images/green-16x16.png?e37 51w' sizes='(min-width:0) calc(1px)'>
+<img srcset='/images/green-1x1.png?e38 50w, /images/green-16x16.png?e38 51w' sizes='(min-width:calc(0)) 1px'>
+<img srcset='/images/green-1x1.png?e39 50w, /images/green-16x16.png?e39 51w' sizes='(min-width:0) 1px, 100vw'>
+<img srcset='/images/green-1x1.png?e40 50w, /images/green-16x16.png?e40 51w' sizes='(min-width:0) 1px, (min-width:0) 100vw, 100vw'>
+<img srcset='/images/green-1x1.png?e41 50w, /images/green-16x16.png?e41 51w' sizes='(min-width:0) 1px'>
+<img srcset='/images/green-1x1.png?e42 50w, /images/green-16x16.png?e42 51w' sizes='not (min-width:0) 100vw, 1px'>
+<img srcset='/images/green-1x1.png?e43 50w, /images/green-16x16.png?e43 51w' sizes='(min-width:unknown-mf-value) 100vw, 1px'>
+<img srcset='/images/green-1x1.png?e44 50w, /images/green-16x16.png?e44 51w' sizes='not (min-width:unknown-mf-value) 1px'>
+<img srcset='/images/green-1x1.png?e45 50w, /images/green-16x16.png?e45 51w' sizes='(min-width:-1px) 100vw, 1px'>
+<img srcset='/images/green-1x1.png?e46 50w, /images/green-16x16.png?e46 51w' sizes='not (min-width:-1px) 1px'>
+<img srcset='/images/green-1x1.png?e47 50w, /images/green-16x16.png?e47 51w' sizes='(unknown-mf-name) 100vw, 1px'>
+<img srcset='/images/green-1x1.png?e48 50w, /images/green-16x16.png?e48 51w' sizes='not (unknown-mf-name) 1px'>
+<img srcset='/images/green-1x1.png?e49 50w, /images/green-16x16.png?e49 51w' sizes='("unknown-general-enclosed") 100vw, 1px'>
+<img srcset='/images/green-1x1.png?e50 50w, /images/green-16x16.png?e50 51w' sizes='not ("unknown-general-enclosed") 1px'>
+<img srcset='/images/green-1x1.png?e51 50w, /images/green-16x16.png?e51 51w' sizes='unknown-general-enclosed(foo) 100vw, 1px'>
+<img srcset='/images/green-1x1.png?e52 50w, /images/green-16x16.png?e52 51w' sizes='not unknown-general-enclosed(foo) 1px'>
+<img srcset='/images/green-1x1.png?e53 50w, /images/green-16x16.png?e53 51w' sizes='print 100vw, 1px'>
+<img srcset='/images/green-1x1.png?e54 50w, /images/green-16x16.png?e54 51w' sizes='not print 100vw, 1px'>
+<img srcset='/images/green-1x1.png?e55 50w, /images/green-16x16.png?e55 51w' sizes='unknown-media-type 100vw, 1px'>
+<img srcset='/images/green-1x1.png?e56 50w, /images/green-16x16.png?e56 51w' sizes='not unknown-media-type 100vw, 1px'>
+<img srcset='/images/green-1x1.png?e57 50w, /images/green-16x16.png?e57 51w' sizes='(min-width:0) or (min-width:0) 1px'>
+<img srcset='/images/green-1x1.png?e58 50w, /images/green-16x16.png?e58 51w' sizes='(min-width:0) or (unknown-mf-name) 1px'>
+<img srcset='/images/green-1x1.png?e59 50w, /images/green-16x16.png?e59 51w' sizes='(min-width:0) or (min-width:unknown-mf-value) 1px'>
+<img srcset='/images/green-1x1.png?e60 50w, /images/green-16x16.png?e60 51w' sizes='(min-width:0) or (min-width:-1px) 1px'>
+<img srcset='/images/green-1x1.png?e61 50w, /images/green-16x16.png?e61 51w' sizes='(min-width:0) or ("unknown-general-enclosed") 1px'>
+<img srcset='/images/green-1x1.png?e62 50w, /images/green-16x16.png?e62 51w' sizes='(min-width:0) or unknown-general-enclosed(foo) 1px'>
+<img srcset='/images/green-1x1.png?e63 50w, /images/green-16x16.png?e63 51w' sizes='(min-width:0) or (!) 100vw, 1px'>
+<img srcset='/images/green-1x1.png?e64 50w, /images/green-16x16.png?e64 51w' sizes='(min-width:0) or unknown-media-type 100vw, 1px'>
+<img srcset='/images/green-1x1.png?e65 50w, /images/green-16x16.png?e65 51w' sizes='(123) 100vw, 1px'>
+<img srcset='/images/green-1x1.png?e66 50w, /images/green-16x16.png?e66 51w' sizes='not (123) 1px'>
+<img srcset='/images/green-1x1.png?e67 50w, /images/green-16x16.png?e67 51w' sizes='(!) 100vw, 1px'>
+<img srcset='/images/green-1x1.png?e68 50w, /images/green-16x16.png?e68 51w' sizes='not (!) 100vw, 1px'>
+<img srcset='/images/green-1x1.png?e69 50w, /images/green-16x16.png?e69 51w' sizes='! 100vw, 1px'>
+<img srcset='/images/green-1x1.png?e70 50w, /images/green-16x16.png?e70 51w' sizes='not ! 100vw, 1px'>
+<img srcset='/images/green-1x1.png?e71 50w, /images/green-16x16.png?e71 51w' sizes='(]) 100vw, 1px'>
+<img srcset='/images/green-1x1.png?e72 50w, /images/green-16x16.png?e72 51w' sizes='not (]) 100vw, 1px'>
+<img srcset='/images/green-1x1.png?e73 50w, /images/green-16x16.png?e73 51w' sizes='] 100vw, 1px'>
+<img srcset='/images/green-1x1.png?e74 50w, /images/green-16x16.png?e74 51w' sizes='not ] 100vw, 1px'>
+<img srcset='/images/green-1x1.png?e75 50w, /images/green-16x16.png?e75 51w' sizes='(}) 100vw, 1px'>
+<img srcset='/images/green-1x1.png?e76 50w, /images/green-16x16.png?e76 51w' sizes='not (}) 100vw, 1px'>
+<img srcset='/images/green-1x1.png?e77 50w, /images/green-16x16.png?e77 51w' sizes='} 100vw, 1px'>
+<img srcset='/images/green-1x1.png?e78 50w, /images/green-16x16.png?e78 51w' sizes='not } 100vw, 1px'>
+<img srcset='/images/green-1x1.png?e79 50w, /images/green-16x16.png?e79 51w' sizes=') 100vw, 1px'>
+<img srcset='/images/green-1x1.png?e80 50w, /images/green-16x16.png?e80 51w' sizes='not ) 100vw, 1px'>
+<img srcset='/images/green-1x1.png?e81 50w, /images/green-16x16.png?e81 51w' sizes='(;) 100vw, 1px'>
+<img srcset='/images/green-1x1.png?e82 50w, /images/green-16x16.png?e82 51w' sizes='not (;) 100vw, 1px'>
+<img srcset='/images/green-1x1.png?e83 50w, /images/green-16x16.png?e83 51w' sizes='(.) 100vw, 1px'>
+<img srcset='/images/green-1x1.png?e84 50w, /images/green-16x16.png?e84 51w' sizes='not (.) 1px'>
+<img srcset='/images/green-1x1.png?e85 50w, /images/green-16x16.png?e85 51w' sizes='; 100vw, 1px'>
+<img srcset='/images/green-1x1.png?e86 50w, /images/green-16x16.png?e86 51w' sizes='not ; 100vw, 1px'>
+<img srcset='/images/green-1x1.png?e87 50w, /images/green-16x16.png?e87 51w' sizes=', 1px'>
+<img srcset='/images/green-1x1.png?e88 50w, /images/green-16x16.png?e88 51w' sizes='1px,'>
+<img srcset='/images/green-1x1.png?e89 50w, /images/green-16x16.png?e89 51w' sizes='(min-width:0) 1px,'>
+<img srcset='/images/green-1x1.png?e90 50w, /images/green-16x16.png?e90 51w' sizes='-0e-0px'>
+<img srcset='/images/green-1x1.png?e91 50w, /images/green-16x16.png?e91 51w' sizes='+0.11e+01px'>
+<img srcset='/images/green-1x1.png?e92 50w, /images/green-16x16.png?e92 51w' sizes='0.2e1px'>
+<img srcset='/images/green-1x1.png?e93 50w, /images/green-16x16.png?e93 51w' sizes='0.3E1px'>
+<img srcset='/images/green-1x1.png?e94 50w, /images/green-16x16.png?e94 51w' sizes='.4E1px'>
+<img srcset='/images/green-1x1.png?e95 50w, /images/green-16x16.png?e95 51w' sizes='all 100vw, 1px'>
+<img srcset='/images/green-1x1.png?e96 50w, /images/green-16x16.png?e96 51w' sizes='all and (min-width:0) 100vw, 1px'>
+<img srcset='/images/green-1x1.png?e97 50w, /images/green-16x16.png?e97 51w' sizes='min-width:0 100vw, 1px'>
+<img srcset='/images/green-1x1.png?e98 50w, /images/green-16x16.png?e98 51w' sizes='1px, 100vw'>
+<img srcset='/images/green-1x1.png?e99 50w, /images/green-16x16.png?e99 51w' sizes='1px, (min-width:0) 100vw'>
+<img srcset='/images/green-1x1.png?e100 50w, /images/green-16x16.png?e100 51w' sizes='1px, foo bar'>
+<img srcset='/images/green-1x1.png?e101 50w, /images/green-16x16.png?e101 51w' sizes='(min-width:0) 1px, foo bar'>
+
+<p>
+<img srcset='/images/green-1x1.png?f1 50w, /images/green-16x16.png?f1 51w' sizes='100vw'>
+<img srcset='/images/green-1x1.png?f2 50w, /images/green-16x16.png?f2 51w' sizes=''>
+<img srcset='/images/green-1x1.png?f3 50w, /images/green-16x16.png?f3 51w' sizes=','>
+<img srcset='/images/green-1x1.png?f4 50w, /images/green-16x16.png?f4 51w' sizes='-1px'>
+<img srcset='/images/green-1x1.png?f5 50w, /images/green-16x16.png?f5 51w' sizes='1'>
+<img srcset='/images/green-1x1.png?f6 50w, /images/green-16x16.png?f6 51w' sizes='0.1%'>
+<img srcset='/images/green-1x1.png?f7 50w, /images/green-16x16.png?f7 51w' sizes='0.1deg'>
+<img srcset='/images/green-1x1.png?f8 50w, /images/green-16x16.png?f8 51w' sizes='0.1grad'>
+<img srcset='/images/green-1x1.png?f9 50w, /images/green-16x16.png?f9 51w' sizes='0.1rad'>
+<img srcset='/images/green-1x1.png?f10 50w, /images/green-16x16.png?f10 51w' sizes='0.1turn'>
+<img srcset='/images/green-1x1.png?f11 50w, /images/green-16x16.png?f11 51w' sizes='0.1s'>
+<img srcset='/images/green-1x1.png?f12 50w, /images/green-16x16.png?f12 51w' sizes='0.1ms'>
+<img srcset='/images/green-1x1.png?f13 50w, /images/green-16x16.png?f13 51w' sizes='0.1Hz'>
+<img srcset='/images/green-1x1.png?f14 50w, /images/green-16x16.png?f14 51w' sizes='0.1kHz'>
+<img srcset='/images/green-1x1.png?f15 50w, /images/green-16x16.png?f15 51w' sizes='0.1dpi'>
+<img srcset='/images/green-1x1.png?f16 50w, /images/green-16x16.png?f16 51w' sizes='0.1dpcm'>
+<img srcset='/images/green-1x1.png?f17 50w, /images/green-16x16.png?f17 51w' sizes='0.1dppx'>
+<img srcset='/images/green-1x1.png?f18 50w, /images/green-16x16.png?f18 51w' data-foo='1px' sizes='attr(data-foo, length, 1px)'>
+<img srcset='/images/green-1x1.png?f19 50w, /images/green-16x16.png?f19 51w' data-foo='1' sizes='attr(data-foo, px, 1px)'>
+<img srcset='/images/green-1x1.png?f20 50w, /images/green-16x16.png?f20 51w' sizes='toggle(1px)'>
+<img srcset='/images/green-1x1.png?f21 50w, /images/green-16x16.png?f21 51w' sizes='inherit'>
+<img srcset='/images/green-1x1.png?f22 50w, /images/green-16x16.png?f22 51w' sizes='auto'>
+<img srcset='/images/green-1x1.png?f23 50w, /images/green-16x16.png?f23 51w' sizes='initial'>
+<img srcset='/images/green-1x1.png?f24 50w, /images/green-16x16.png?f24 51w' sizes='unset'>
+<img srcset='/images/green-1x1.png?f25 50w, /images/green-16x16.png?f25 51w' sizes='default'>
+<img srcset='/images/green-1x1.png?f26 50w, /images/green-16x16.png?f26 51w' sizes='1/* */px'>
+<img srcset='/images/green-1x1.png?f27 50w, /images/green-16x16.png?f27 51w' sizes='1p/* */x'>
+<img srcset='/images/green-1x1.png?f28 50w, /images/green-16x16.png?f28 51w' sizes='-/**/0'>
+<img srcset='/images/green-1x1.png?f29 50w, /images/green-16x16.png?f29 51w' sizes='((),1px'>
+<img srcset='/images/green-1x1.png?f30 50w, /images/green-16x16.png?f30 51w' sizes='x(x(),1px'>
+<img srcset='/images/green-1x1.png?f31 50w, /images/green-16x16.png?f31 51w' sizes='{{},1px'>
+<img srcset='/images/green-1x1.png?f32 50w, /images/green-16x16.png?f32 51w' sizes='[[],1px'>
+<img srcset='/images/green-1x1.png?f33 50w, /images/green-16x16.png?f33 51w' sizes='1px !important'>
+<img srcset='/images/green-1x1.png?f34 50w, /images/green-16x16.png?f34 51w' sizes='\1px'>
+<img srcset='/images/green-1x1.png?f35 50w, /images/green-16x16.png?f35 51w' sizes='all 1px'>
+<img srcset='/images/green-1x1.png?f36 50w, /images/green-16x16.png?f36 51w' sizes='all and (min-width:0) 1px'>
+<img srcset='/images/green-1x1.png?f37 50w, /images/green-16x16.png?f37 51w' sizes='min-width:0 1px'>
+<img srcset='/images/green-1x1.png?f38 50w, /images/green-16x16.png?f38 51w' sizes='100vw, 1px'>
+<img srcset='/images/green-1x1.png?f39 50w, /images/green-16x16.png?f39 51w' sizes='100vw, (min-width:0) 1px'>
+<img srcset='/images/green-1x1.png?f40 50w, /images/green-16x16.png?f40 51w' sizes='foo bar'>
+<img srcset='/images/green-1x1.png?f41 50w, /images/green-16x16.png?f41 51w' sizes='foo-bar'>
+<img srcset='/images/green-1x1.png?f42 50w, /images/green-16x16.png?f42 51w' sizes='(min-width:0) 1px foo bar'>
+<img srcset='/images/green-1x1.png?f43 50w, /images/green-16x16.png?f43 51w' sizes='(min-width:0) 0.1%'>
+<img srcset='/images/green-1x1.png?f44 50w, /images/green-16x16.png?f44 51w' sizes='(min-width:0) 1'>
+<img srcset='/images/green-1x1.png?f45 50w, /images/green-16x16.png?f45 51w' sizes='-1e0px'>
+<img srcset='/images/green-1x1.png?f46 50w, /images/green-16x16.png?f46 51w' sizes='1e1.5px'>
+<img srcset='/images/green-1x1.png?f47 50w, /images/green-16x16.png?f47 51w' style='--foo: 1px' sizes='var(--foo)'>
+<img srcset='/images/green-1x1.png?f48 50w, /images/green-16x16.png?f48 51w' sizes='calc(1px'>
+<img srcset='/images/green-1x1.png?f49 50w, /images/green-16x16.png?f49 51w' sizes='(min-width:0) calc(1px'>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/srcset/common.js b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/srcset/common.js
new file mode 100644
index 00000000000..d4d2c7534c7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/srcset/common.js
@@ -0,0 +1,25 @@
+setup({explicit_done:true});
+
+function check(img) {
+ var name = format_value(img.getAttribute('srcset'));
+ if (img.hasAttribute('sizes')) {
+ name += ' sizes=' + format_value(img.getAttribute('sizes'));
+ }
+ if (img.hasAttribute('data-desc')) {
+ name += ' (' + img.getAttribute('data-desc') + ')';
+ }
+ test(function() {
+ var expect = img.dataset.expect;
+ if ('resolve' in img.dataset) {
+ var a = document.createElement('a');
+ a.href = expect;
+ expect = a.href;
+ }
+ assert_equals(img.currentSrc, expect);
+ }, name);
+}
+
+onload = function() {
+ [].forEach.call(document.images, check);
+ done();
+};
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/srcset/parse-a-srcset-attribute.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/srcset/parse-a-srcset-attribute.html
new file mode 100644
index 00000000000..2ff9886e036
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/srcset/parse-a-srcset-attribute.html
@@ -0,0 +1,244 @@
+<!doctype html>
+<title>img parse a srcset attribute</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src=common.js></script>
+<div id=log></div>
+<!-- splitting loop -->
+<img srcset='' data-expect=''>
+<img srcset=',' data-expect=''>
+<img srcset=',,,' data-expect=''>
+<img srcset=' data:,a 1x ' data-expect='data:,a'>
+<img srcset='&#x9;&#x9;data:,a&#x9;&#x9;1x&#x9;&#x9;' data-expect='data:,a'>
+<img srcset='&#xA;&#xA;data:,a&#xA;&#xA;1x&#xA;&#xA;' data-expect='data:,a'>
+<img srcset='&#xB;&#xB;data:,a&#xB;&#xB;1x&#xB;&#xB;' data-expect='&#xB;&#xB;data:,a&#xB;&#xB;1x&#xB;&#xB;' data-resolve>
+<img srcset='&#xC;&#xC;data:,a&#xC;&#xC;1x&#xC;&#xC;' data-expect='data:,a'>
+<img srcset='&#xD;&#xD;data:,a&#xD;&#xD;1x&#xD;&#xD;' data-expect='data:,a'>
+<img srcset='&#xE;&#xE;data:,a&#xE;&#xE;1x&#xE;&#xE;' data-expect='&#xE;&#xE;data:,a&#xE;&#xE;1x&#xE;&#xE;' data-resolve>
+<img srcset='&#xF;&#xF;data:,a&#xF;&#xF;1x&#xF;&#xF;' data-expect='&#xF;&#xF;data:,a&#xF;&#xF;1x&#xF;&#xF;' data-resolve>
+<img srcset='&#x10;&#x10;data:,a&#x10;&#x10;1x&#x10;&#x10;' data-expect='&#x10;&#x10;data:,a&#x10;&#x10;1x&#x10;&#x10;' data-resolve>
+<img srcset='data:,a' data-expect='data:,a'>
+<img srcset='data:,a ' data-expect='data:,a'>
+<img srcset='data:,a ,' data-expect='data:,a'>
+<img srcset='data:,a,' data-expect='data:,a'>
+<img srcset='data:,a, ' data-expect='data:,a'>
+<img srcset='data:,a,,,' data-expect='data:,a'>
+<img srcset='data:,a,, , ' data-expect='data:,a'>
+<img srcset=' data:,a' data-expect='data:,a'>
+<img srcset=',,,data:,a' data-expect='data:,a'>
+<img srcset=' , ,,data:,a' data-expect='data:,a'>
+<img srcset='&nbsp;data:,a' data-expect='&nbsp;data:,a' data-resolve>
+<img srcset='data:,a&nbsp;' data-expect='data:,a&nbsp;' data-resolve>
+<!-- descriptor tokenizer -->
+<img srcset='data:,a 1x' data-expect='data:,a'>
+<img srcset='data:,a 1x ' data-expect='data:,a'>
+<img srcset='data:,a 1x,' data-expect='data:,a'>
+<img srcset='data:,a ( , data:,b 1x, ), data:,c' data-expect='data:,c'>
+<img srcset='data:,a ((( , data:,b 1x, ), data:,c' data-expect='data:,c'>
+<img srcset='data:,a [ , data:,b 1x, ], data:,c' data-expect='data:,b'>
+<img srcset='data:,a { , data:,b 1x, }, data:,c' data-expect='data:,b'>
+<img srcset='data:,a " , data:,b 1x, ", data:,c' data-expect='data:,b'>
+<img srcset='data:,a \,data:;\,b, data:,c' data-expect='data:;\,b'>
+<img srcset='data:,a, data:,b (' data-expect='data:,a'>
+<img srcset='data:,a, data:,b ( ' data-expect='data:,a'>
+<img srcset='data:,a, data:,b (,' data-expect='data:,a'>
+<img srcset='data:,a, data:,b (x' data-expect='data:,a'>
+<img srcset='data:,a, data:,b ()' data-expect='data:,a'>
+<img srcset='data:,a (, data:,b' data-expect=''>
+<img srcset='data:,a /*, data:,b, data:,c */' data-expect='data:,b'>
+<img srcset='data:,a //, data:,b' data-expect='data:,b'>
+<!-- descriptor parser -->
+<img srcset='data:,a foo' data-expect=''>
+<img srcset='data:,a foo foo' data-expect=''>
+<img srcset='data:,a foo 1x' data-expect=''>
+<img srcset='data:,a foo 1x foo' data-expect=''>
+<img srcset='data:,a foo 1w' data-expect=''>
+<img srcset='data:,a foo 1w foo' data-expect=''>
+<img srcset='data:,a 1x 1x' data-expect=''>
+<img srcset='data:,a 1w 1w' data-expect=''>
+<img srcset='data:,a 1w 1x' data-expect=''>
+<img srcset='data:,a 1x 1w' data-expect=''>
+<img srcset='data:,a 1w 1h' data-expect='data:,a'>
+<img srcset='data:,a 1h 1w' data-expect='data:,a'>
+<img srcset='data:,a 1h 1h' data-expect=''>
+<img srcset='data:,a 1h 1x' data-expect=''>
+<img srcset='data:,a 1h 1w 1x' data-expect=''>
+<img srcset='data:,a 1x 1w 1h' data-expect=''>
+<img srcset='data:,a 1h' data-expect=''>
+<img srcset='data:,a 1h foo' data-expect=''>
+<img srcset='data:,a foo 1h' data-expect=''>
+<img srcset='data:,a 0w' data-expect=''>
+<img srcset='data:,a -1w' data-expect=''>
+<img srcset='data:,a 1w -1w' data-expect=''>
+<img srcset='data:,a 1.0w' data-expect=''>
+<img srcset='data:,a 1w 1.0w' data-expect=''>
+<img srcset='data:,a 1e0w' data-expect=''>
+<img srcset='data:,a 1w 1e0w' data-expect=''>
+<img srcset='data:,a 1www' data-expect=''>
+<img srcset='data:,a 1w 1www' data-expect=''>
+<img srcset='data:,a +1w' data-expect=''>
+<img srcset='data:,a 1w +1w' data-expect=''>
+<img srcset='data:,a 1W' data-expect=''>
+<img srcset='data:,a 1w 1W' data-expect=''>
+<img srcset='data:,a Infinityw' data-expect=''>
+<img srcset='data:,a 1w Infinityw' data-expect=''>
+<img srcset='data:,a NaNw' data-expect=''>
+<img srcset='data:,a 1w NaNw' data-expect=''>
+<img srcset='data:,a 0x1w' data-expect=''>
+<img srcset='data:,a 0X1w' data-expect=''>
+<img srcset='data:,a 1&#x1;w' data-expect='' data-desc='trailing U+0001'>
+<img srcset='data:,a 1&nbsp;w' data-expect='' data-desc='trailing U+00A0'>
+<img srcset='data:,a 1&#x1680;w' data-expect='' data-desc='trailing U+1680'>
+<img srcset='data:,a 1&#x2000;w' data-expect='' data-desc='trailing U+2000'>
+<img srcset='data:,a 1&#x2001;w' data-expect='' data-desc='trailing U+2001'>
+<img srcset='data:,a 1&#x2002;w' data-expect='' data-desc='trailing U+2002'>
+<img srcset='data:,a 1&#x2003;w' data-expect='' data-desc='trailing U+2003'>
+<img srcset='data:,a 1&#x2004;w' data-expect='' data-desc='trailing U+2004'>
+<img srcset='data:,a 1&#x2005;w' data-expect='' data-desc='trailing U+2005'>
+<img srcset='data:,a 1&#x2006;w' data-expect='' data-desc='trailing U+2006'>
+<img srcset='data:,a 1&#x2007;w' data-expect='' data-desc='trailing U+2007'>
+<img srcset='data:,a 1&#x2008;w' data-expect='' data-desc='trailing U+2008'>
+<img srcset='data:,a 1&#x2009;w' data-expect='' data-desc='trailing U+2009'>
+<img srcset='data:,a 1&#x200A;w' data-expect='' data-desc='trailing U+200A'>
+<img srcset='data:,a 1&#x200C;w' data-expect='' data-desc='trailing U+200C'>
+<img srcset='data:,a 1&#x200D;w' data-expect='' data-desc='trailing U+200D'>
+<img srcset='data:,a 1&#x202F;w' data-expect='' data-desc='trailing U+202F'>
+<img srcset='data:,a 1&#x205F;w' data-expect='' data-desc='trailing U+205F'>
+<img srcset='data:,a 1&#x3000;w' data-expect='' data-desc='trailing U+3000'>
+<img srcset='data:,a 1&#xFEFF;w' data-expect='' data-desc='trailing U+FEFF'>
+<img srcset='data:,a &#x1;1w' data-expect='' data-desc='leading U+0001'>
+<img srcset='data:,a &nbsp;1w' data-expect='' data-desc='leading U+00A0'>
+<img srcset='data:,a &#x1680;1w' data-expect='' data-desc='leading U+1680'>
+<img srcset='data:,a &#x2000;1w' data-expect='' data-desc='leading U+2000'>
+<img srcset='data:,a &#x2001;1w' data-expect='' data-desc='leading U+2001'>
+<img srcset='data:,a &#x2002;1w' data-expect='' data-desc='leading U+2002'>
+<img srcset='data:,a &#x2003;1w' data-expect='' data-desc='leading U+2003'>
+<img srcset='data:,a &#x2004;1w' data-expect='' data-desc='leading U+2004'>
+<img srcset='data:,a &#x2005;1w' data-expect='' data-desc='leading U+2005'>
+<img srcset='data:,a &#x2006;1w' data-expect='' data-desc='leading U+2006'>
+<img srcset='data:,a &#x2007;1w' data-expect='' data-desc='leading U+2007'>
+<img srcset='data:,a &#x2008;1w' data-expect='' data-desc='leading U+2008'>
+<img srcset='data:,a &#x2009;1w' data-expect='' data-desc='leading U+2009'>
+<img srcset='data:,a &#x200A;1w' data-expect='' data-desc='leading U+200A'>
+<img srcset='data:,a &#x200C;1w' data-expect='' data-desc='leading U+200C'>
+<img srcset='data:,a &#x200D;1w' data-expect='' data-desc='leading U+200D'>
+<img srcset='data:,a &#x202F;1w' data-expect='' data-desc='leading U+202F'>
+<img srcset='data:,a &#x205F;1w' data-expect='' data-desc='leading U+205F'>
+<img srcset='data:,a &#x3000;1w' data-expect='' data-desc='leading U+3000'>
+<img srcset='data:,a &#xFEFF;1w' data-expect='' data-desc='leading U+FEFF'>
+<img srcset='data:,a 0x' data-expect='data:,a'>
+<img srcset='data:,a -0x' data-expect='data:,a'>
+<img srcset='data:,a 1x -0x' data-expect=''>
+<img srcset='data:,a -1x' data-expect=''>
+<img srcset='data:,a 1x -1x' data-expect=''>
+<img srcset='data:,a 1e0x' data-expect='data:,a'>
+<img srcset='data:,a 1E0x' data-expect='data:,a'>
+<img srcset='data:,a 1e-1x' data-expect='data:,a'>
+<img srcset='data:,a 1.5e1x' data-expect='data:,a'>
+<img srcset='data:,a -x' data-expect=''>
+<img srcset='data:,a .x' data-expect=''>
+<img srcset='data:,a -.x' data-expect=''>
+<img srcset='data:,a 1.x' data-expect=''>
+<img srcset='data:,a .5x' data-expect='data:,a'>
+<img srcset='data:,a .5e1x' data-expect='data:,a'>
+<img srcset='data:,a 1x 1.5e1x' data-expect=''>
+<img srcset='data:,a 1x 1e1.5x' data-expect=''>
+<img srcset='data:,a 1.0x' data-expect='data:,a'>
+<img srcset='data:,a 1x 1.0x' data-expect=''>
+<img srcset='data:,a +1x' data-expect=''>
+<img srcset='data:,a 1X' data-expect=''>
+<img srcset='data:,a Infinityx' data-expect=''>
+<img srcset='data:,a NaNx' data-expect=''>
+<img srcset='data:,a 0x1x' data-expect=''>
+<img srcset='data:,a 0X1x' data-expect=''>
+<img srcset='data:,a 1&#x1;x' data-expect='' data-desc='trailing U+0001'>
+<img srcset='data:,a 1&nbsp;x' data-expect='' data-desc='trailing U+00A0'>
+<img srcset='data:,a 1&#x1680;x' data-expect='' data-desc='trailing U+1680'>
+<img srcset='data:,a 1&#x2000;x' data-expect='' data-desc='trailing U+2000'>
+<img srcset='data:,a 1&#x2001;x' data-expect='' data-desc='trailing U+2001'>
+<img srcset='data:,a 1&#x2002;x' data-expect='' data-desc='trailing U+2002'>
+<img srcset='data:,a 1&#x2003;x' data-expect='' data-desc='trailing U+2003'>
+<img srcset='data:,a 1&#x2004;x' data-expect='' data-desc='trailing U+2004'>
+<img srcset='data:,a 1&#x2005;x' data-expect='' data-desc='trailing U+2005'>
+<img srcset='data:,a 1&#x2006;x' data-expect='' data-desc='trailing U+2006'>
+<img srcset='data:,a 1&#x2007;x' data-expect='' data-desc='trailing U+2007'>
+<img srcset='data:,a 1&#x2008;x' data-expect='' data-desc='trailing U+2008'>
+<img srcset='data:,a 1&#x2009;x' data-expect='' data-desc='trailing U+2009'>
+<img srcset='data:,a 1&#x200A;x' data-expect='' data-desc='trailing U+200A'>
+<img srcset='data:,a 1&#x200C;x' data-expect='' data-desc='trailing U+200C'>
+<img srcset='data:,a 1&#x200D;x' data-expect='' data-desc='trailing U+200D'>
+<img srcset='data:,a 1&#x202F;x' data-expect='' data-desc='trailing U+202F'>
+<img srcset='data:,a 1&#x205F;x' data-expect='' data-desc='trailing U+205F'>
+<img srcset='data:,a 1&#x3000;x' data-expect='' data-desc='trailing U+3000'>
+<img srcset='data:,a 1&#xFEFF;x' data-expect='' data-desc='trailing U+FEFF'>
+<img srcset='data:,a &#x1;1x' data-expect='' data-desc='leading U+0001'>
+<img srcset='data:,a &nbsp;1x' data-expect='' data-desc='leading U+00A0'>
+<img srcset='data:,a &#x1680;1x' data-expect='' data-desc='leading U+1680'>
+<img srcset='data:,a &#x2000;1x' data-expect='' data-desc='leading U+2000'>
+<img srcset='data:,a &#x2001;1x' data-expect='' data-desc='leading U+2001'>
+<img srcset='data:,a &#x2002;1x' data-expect='' data-desc='leading U+2002'>
+<img srcset='data:,a &#x2003;1x' data-expect='' data-desc='leading U+2003'>
+<img srcset='data:,a &#x2004;1x' data-expect='' data-desc='leading U+2004'>
+<img srcset='data:,a &#x2005;1x' data-expect='' data-desc='leading U+2005'>
+<img srcset='data:,a &#x2006;1x' data-expect='' data-desc='leading U+2006'>
+<img srcset='data:,a &#x2007;1x' data-expect='' data-desc='leading U+2007'>
+<img srcset='data:,a &#x2008;1x' data-expect='' data-desc='leading U+2008'>
+<img srcset='data:,a &#x2009;1x' data-expect='' data-desc='leading U+2009'>
+<img srcset='data:,a &#x200A;1x' data-expect='' data-desc='leading U+200A'>
+<img srcset='data:,a &#x200C;1x' data-expect='' data-desc='leading U+200C'>
+<img srcset='data:,a &#x200D;1x' data-expect='' data-desc='leading U+200D'>
+<img srcset='data:,a &#x202F;1x' data-expect='' data-desc='leading U+202F'>
+<img srcset='data:,a &#x205F;1x' data-expect='' data-desc='leading U+205F'>
+<img srcset='data:,a &#x3000;1x' data-expect='' data-desc='leading U+3000'>
+<img srcset='data:,a &#xFEFF;1x' data-expect='' data-desc='leading U+FEFF'>
+<img srcset='data:,a 1w 0h' data-expect=''>
+<img srcset='data:,a 1w -1h' data-expect=''>
+<img srcset='data:,a 1w 1.0h' data-expect=''>
+<img srcset='data:,a 1w 1e0h' data-expect=''>
+<img srcset='data:,a 1w 1hhh' data-expect=''>
+<img srcset='data:,a 1w +1h' data-expect=''>
+<img srcset='data:,a 1w 1H' data-expect=''>
+<img srcset='data:,a 1w Infinityh' data-expect=''>
+<img srcset='data:,a 1w NaNh' data-expect=''>
+<img srcset='data:,a 0x1h' data-expect=''>
+<img srcset='data:,a 0X1h' data-expect=''>
+<img srcset='data:,a 1w 1&#x1;h' data-expect='' data-desc='trailing U+0001'>
+<img srcset='data:,a 1w 1&nbsp;h' data-expect='' data-desc='trailing U+00A0'>
+<img srcset='data:,a 1w 1&#x1680;h' data-expect='' data-desc='trailing U+1680'>
+<img srcset='data:,a 1w 1&#x2000;h' data-expect='' data-desc='trailing U+2000'>
+<img srcset='data:,a 1w 1&#x2001;h' data-expect='' data-desc='trailing U+2001'>
+<img srcset='data:,a 1w 1&#x2002;h' data-expect='' data-desc='trailing U+2002'>
+<img srcset='data:,a 1w 1&#x2003;h' data-expect='' data-desc='trailing U+2003'>
+<img srcset='data:,a 1w 1&#x2004;h' data-expect='' data-desc='trailing U+2004'>
+<img srcset='data:,a 1w 1&#x2005;h' data-expect='' data-desc='trailing U+2005'>
+<img srcset='data:,a 1w 1&#x2006;h' data-expect='' data-desc='trailing U+2006'>
+<img srcset='data:,a 1w 1&#x2007;h' data-expect='' data-desc='trailing U+2007'>
+<img srcset='data:,a 1w 1&#x2008;h' data-expect='' data-desc='trailing U+2008'>
+<img srcset='data:,a 1w 1&#x2009;h' data-expect='' data-desc='trailing U+2009'>
+<img srcset='data:,a 1w 1&#x200A;h' data-expect='' data-desc='trailing U+200A'>
+<img srcset='data:,a 1w 1&#x200C;h' data-expect='' data-desc='trailing U+200C'>
+<img srcset='data:,a 1w 1&#x200D;h' data-expect='' data-desc='trailing U+200D'>
+<img srcset='data:,a 1w 1&#x202F;h' data-expect='' data-desc='trailing U+202F'>
+<img srcset='data:,a 1w 1&#x205F;h' data-expect='' data-desc='trailing U+205F'>
+<img srcset='data:,a 1w 1&#x3000;h' data-expect='' data-desc='trailing U+3000'>
+<img srcset='data:,a 1w 1&#xFEFF;h' data-expect='' data-desc='trailing U+FEFF'>
+<img srcset='data:,a 1w &#x1;1h' data-expect='' data-desc='leading U+0001'>
+<img srcset='data:,a 1w &nbsp;1h' data-expect='' data-desc='leading U+00A0'>
+<img srcset='data:,a 1w &#x1680;1h' data-expect='' data-desc='leading U+1680'>
+<img srcset='data:,a 1w &#x2000;1h' data-expect='' data-desc='leading U+2000'>
+<img srcset='data:,a 1w &#x2001;1h' data-expect='' data-desc='leading U+2001'>
+<img srcset='data:,a 1w &#x2002;1h' data-expect='' data-desc='leading U+2002'>
+<img srcset='data:,a 1w &#x2003;1h' data-expect='' data-desc='leading U+2003'>
+<img srcset='data:,a 1w &#x2004;1h' data-expect='' data-desc='leading U+2004'>
+<img srcset='data:,a 1w &#x2005;1h' data-expect='' data-desc='leading U+2005'>
+<img srcset='data:,a 1w &#x2006;1h' data-expect='' data-desc='leading U+2006'>
+<img srcset='data:,a 1w &#x2007;1h' data-expect='' data-desc='leading U+2007'>
+<img srcset='data:,a 1w &#x2008;1h' data-expect='' data-desc='leading U+2008'>
+<img srcset='data:,a 1w &#x2009;1h' data-expect='' data-desc='leading U+2009'>
+<img srcset='data:,a 1w &#x200A;1h' data-expect='' data-desc='leading U+200A'>
+<img srcset='data:,a 1w &#x200C;1h' data-expect='' data-desc='leading U+200C'>
+<img srcset='data:,a 1w &#x200D;1h' data-expect='' data-desc='leading U+200D'>
+<img srcset='data:,a 1w &#x202F;1h' data-expect='' data-desc='leading U+202F'>
+<img srcset='data:,a 1w &#x205F;1h' data-expect='' data-desc='leading U+205F'>
+<img srcset='data:,a 1w &#x3000;1h' data-expect='' data-desc='leading U+3000'>
+<img srcset='data:,a 1w &#xFEFF;1h' data-expect='' data-desc='leading U+FEFF'>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/srcset/select-an-image-source.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/srcset/select-an-image-source.html
new file mode 100644
index 00000000000..292395d3aef
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/srcset/select-an-image-source.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<title>img select an image source</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src=common.js></script>
+<div id=log></div>
+<!-- dup entries -->
+<img srcset='data:,a 1x, data:,b 1x' data-expect='data:,a'>
+<img srcset='data:,a , data:,b 1x' data-expect='data:,a'>
+<img srcset='data:,a 1x, data:,b' data-expect='data:,a'>
+<img srcset='data:,a 1w, data:,b 1w' data-expect='data:,a'>
+<img srcset='data:,a 1w 1h, data:,b 1w' data-expect='data:,a'>
+<img srcset='data:,a 1w, data:,b 1w 1h' data-expect='data:,a'>
+<img srcset='data:,a 1w 1h, data:,b 1w 2h' data-expect='data:,a'>
+<img srcset='data:,a 1w 2h, data:,b 1w 1h' data-expect='data:,a'>
+<img srcset='data:,a , data:,b' data-expect='data:,a'>
+<img srcset='data:,a 1w, data:,b 1x' sizes='1px' data-expect='data:,a'>
+<img srcset='data:,a 1x, data:,b 1w' sizes='1px' data-expect='data:,a'>
+<img srcset='data:,a 1w, data:,b 2x' sizes='0.5px' data-expect='data:,a'>
+<img srcset='data:,a 2x, data:,b 1w' sizes='0.5px' data-expect='data:,a'>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/update-the-source-set.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/update-the-source-set.html
new file mode 100644
index 00000000000..063667baa9e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/update-the-source-set.html
@@ -0,0 +1,140 @@
+<!doctype html>
+<title>img update the source set</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+setup({explicit_done:true});
+
+function check(p) {
+ var img = p.querySelector('[data-expect]');
+ test(function() {
+ var expect = img.dataset.expect;
+ if ('resolve' in img.dataset) {
+ var a = document.createElement('a');
+ a.href = expect;
+ expect = a.href;
+ }
+ assert_equals(img.currentSrc, expect);
+ }, p.innerHTML);
+}
+
+onload = function() {
+ [].forEach.call(document.querySelectorAll('div:not([id])'), check);
+ done();
+};
+
+</script>
+<div id=log></div>
+<div><img data-expect=''></div>
+<div><img src data-expect=''></div>
+<div><img src='data:,a' data-expect='data:,a'></div>
+<div><img srcset src='data:,a' data-expect='data:,a'></div>
+<div><img srcset='data:,b' src='data:,a' data-expect='data:,b'></div>
+<div><img src='data:,a' srcset='data:,b' data-expect='data:,b'><!-- srcset after src --></div>
+<div><img src='data:,a' srcset='data:,b 1x' data-expect='data:,b'></div>
+<div><img src='data:,a' srcset='data:,b 1.0x' data-expect='data:,b'></div>
+<div><img src='data:,a' srcset='data:,b 1e0x' data-expect='data:,b'></div>
+<div><img src='data:,a' srcset='data:,b 10000w' sizes='1px' data-expect='data:,b'></div>
+<div><img src='data:,a' srcset='data:,b 10000w, data:,c 10000x' sizes='1px' data-expect='data:,b'></div>
+<div><img src='data:,a' srcset='data:,b 10000x, data:,c 10000w' sizes='1px' data-expect='data:,b'></div>
+<div><img src='data:,a' srcset='data:,b 1w' sizes='10000px' data-expect='data:,b'></div>
+<div><img src='data:,a' srcset='data:,b 1w, data:,c 0.0001x' sizes='10000px' data-expect='data:,b'></div>
+<div><img src='data:,a' srcset='data:,b 0.0001x, data:,c 1w' sizes='10000px' data-expect='data:,b'></div>
+<div><img srcset='data:,a' data-expect='data:,a'></div>
+
+<!-- child is not a <source> -->
+
+<div><picture>foo<img src='data:,a' data-expect='data:,a'></picture></div>
+<div><picture><!--foo--><img src='data:,a' data-expect='data:,a'></picture></div>
+<div><picture><br><img src='data:,a' data-expect='data:,a'></picture></div>
+<div><picture><p></p><img src='data:,a' data-expect='data:,a'></picture></div>
+<div><picture><video><source srcset='data:,b'></video><img src='data:,a' data-expect='data:,a'></picture></div>
+<div><picture><span><source srcset='data:,b'></span><img src='data:,a' data-expect='data:,a'></picture></div>
+<div><picture><svg><source srcset='data:,b'/></svg><img src='data:,a' data-expect='data:,a'></picture></div>
+<div><picture><svg/><source srcset='data:,b'/><img src='data:,a' data-expect='data:,b'></picture></div>
+<div><picture><svg><font/><source srcset='data:,b'/></svg><img src='data:,a' data-expect='data:,a'></picture></div>
+<div><picture><svg><!--<font face> tag breaks out of svg--><font face></font><source srcset='data:,b'/></svg><img src='data:,a' data-expect='data:,b'></picture></div>
+<div><picture><img src='data:,a'><img src='data:,b' data-expect='data:,b'></picture></div>
+
+<!-- <source> has no srcset -->
+
+<div><picture><source><img src='data:,a' data-expect='data:,a'></picture></div>
+<div><picture><source src='data:,b'><img src='data:,a' data-expect='data:,a'></picture></div>
+
+<!-- <source srcset> has zero candidates -->
+
+<div><picture><source srcset><img src='data:,a' data-expect='data:,a'></picture></div>
+<div><picture><source srcset=', ,'><img src='data:,a' data-expect='data:,a'></picture></div>
+<div><picture><source srcset='data:,b 1x 1x'><img src='data:,a' data-expect='data:,a'></picture></div>
+
+<!-- <source media> -->
+
+<div><picture><source srcset='data:,b' media><img src='data:,a' data-expect='data:,b'></picture></div>
+<div><picture><source srcset='data:,b' media='all'><img src='data:,a' data-expect='data:,b'></picture></div>
+<div><picture><source srcset='data:,b' media='all and (min-width:0)'><img src='data:,a' data-expect='data:,b'></picture></div>
+<div><picture><source srcset='data:,b' media='all and !'><img src='data:,a' data-expect='data:,a'></picture></div>
+<div><picture><source srcset='data:,b' media='all and (!)'><img src='data:,a' data-expect='data:,a'></picture></div>
+<div><picture><source srcset='data:,b' media='not all'><img src='data:,a' data-expect='data:,a'></picture></div>
+<div><picture><source srcset='data:,b' media='not all and (min-width:0)'><img src='data:,a' data-expect='data:,a'></picture></div>
+<div><picture><source srcset='data:,b' media='not all and (max-width:0)'><img src='data:,a' data-expect='data:,b'></picture></div>
+<div><picture><source srcset='data:,b' media='not all and !'><img src='data:,a' data-expect='data:,a'></picture></div>
+<div><picture><source srcset='data:,b' media='not all and (!)'><img src='data:,a' data-expect='data:,a'></picture></div>
+<div><picture><source srcset='data:,b' media='all, !'><img src='data:,a' data-expect='data:,b'></picture></div>
+<div><picture><source srcset='data:,b' media=','><img src='data:,a' data-expect='data:,a'></picture></div>
+<div><picture><source srcset='data:,b' media=', all'><img src='data:,a' data-expect='data:,b'></picture></div>
+
+<!-- <source type> assume support for gif, png, jpg, svg, ico -->
+
+<div><picture><source srcset='data:,b' type><img src='data:,a' data-expect='data:,b'></picture></div>
+<div><picture><source srcset='data:,b' type=' '><img src='data:,a' data-expect='data:,b'></picture></div>
+<div><picture><source srcset='data:,b' type='image/gif'><img src='data:,a' data-expect='data:,b'></picture></div>
+<div><picture><source srcset='data:,b' type=' image/gif'><img src='data:,a' data-expect='data:,b'></picture></div>
+<div><picture><source srcset='data:,b' type='image/gif '><img src='data:,a' data-expect='data:,b'></picture></div>
+<div><picture><source srcset='data:,b' type='image/gif;'><img src='data:,a' data-expect='data:,b'></picture></div>
+<div><picture><source srcset='data:,b' type='image/gif;encodings'><img src='data:,a' data-expect='data:,b'></picture></div>
+<div><picture><source srcset='data:,b' type='image/gif;encodings='><img src='data:,a' data-expect='data:,b'></picture></div>
+<div><picture><source srcset='data:,b' type='image/gif;encodings=foobar'><img src='data:,a' data-expect='data:,b'></picture></div>
+<div><picture><source srcset='data:,b' type='image/png'><img src='data:,a' data-expect='data:,b'></picture></div>
+<div><picture><source srcset='data:,b' type='image/jpeg'><img src='data:,a' data-expect='data:,b'></picture></div>
+<div><picture><source srcset='data:,b' type='image/svg+xml'><img src='data:,a' data-expect='data:,b'></picture></div>
+<div><picture><source srcset='data:,b' type='image/x-icon'><img src='data:,a' data-expect='data:,b'></picture></div>
+<div><picture><source srcset='data:,b' type='text/xml'><img src='data:,a' data-expect='data:,a'></picture></div>
+<div><picture><source srcset='data:,b' type='text/html'><img src='data:,a' data-expect='data:,a'></picture></div>
+<div><picture><source srcset='data:,b' type='text/plain'><img src='data:,a' data-expect='data:,a'></picture></div>
+<div><picture><source srcset='data:,b' type='text/css'><img src='data:,a' data-expect='data:,a'></picture></div>
+<div><picture><source srcset='data:,b' type='video/mp4'><img src='data:,a' data-expect='data:,a'></picture></div>
+<div><picture><source srcset='data:,b' type='video/ogg'><img src='data:,a' data-expect='data:,a'></picture></div>
+<div><picture><source srcset='data:,b' type='video/webm'><img src='data:,a' data-expect='data:,a'></picture></div>
+<div><picture><source srcset='data:,b' type='unknown/unknown'><img src='data:,a' data-expect='data:,a'></picture></div>
+<div><picture><source srcset='data:,b' type='application/octet-stream'><img src='data:,a' data-expect='data:,a'></picture></div>
+<div><picture><source srcset='data:,b' type='application/x-shockwave-flash'><img src='data:,a' data-expect='data:,a'></picture></div>
+<div><picture><source srcset='data:,b' type='image\gif'><img src='data:,a' data-expect='data:,a'></picture></div>
+<div><picture><source srcset='data:,b' type='gif'><img src='data:,a' data-expect='data:,a'></picture></div>
+<div><picture><source srcset='data:,b' type='.gif'><img src='data:,a' data-expect='data:,a'></picture></div>
+<div><picture><source srcset='data:,b' type='*'><img src='data:,a' data-expect='data:,a'></picture></div>
+<div><picture><source srcset='data:,b' type='*/*'><img src='data:,a' data-expect='data:,a'></picture></div>
+<div><picture><source srcset='data:,b' type='image/*'><img src='data:,a' data-expect='data:,a'></picture></div>
+<div><picture><source srcset='data:,b' type=','><img src='data:,a' data-expect='data:,a'></picture></div>
+<div><picture><source srcset='data:,b' type='image/gif, image/png'><img src='data:,a' data-expect='data:,a'></picture></div>
+<div><picture><source srcset='data:,b' type='image/gif image/png'><img src='data:,a' data-expect='data:,a'></picture></div>
+<div><picture><source srcset='data:,b' type='image/foobarbaz'><img src='data:,a' data-expect='data:,a'></picture></div>
+
+<!-- trailing garbage -->
+
+<div><picture><img src='data:,a' data-expect='data:,a'>foo</picture></div>
+<div><picture><img src='data:,a' data-expect='data:,a'><br></picture></div>
+<div><picture><img src='data:,a' data-expect='data:,a'><!--foo--></picture></div>
+<div><picture><img src='data:,a' data-expect='data:,a'><img src='data:,b'></picture></div>
+<div><picture><img data-expect=''><img src='data:,b'></picture></div>
+<div><picture><img src='data:,a' data-expect='data:,a'><source srcset='data:,b'></picture></div>
+<div><picture><img data-expect=''><source srcset='data:,b'></picture></div>
+
+<!-- parent not picture -->
+
+<div><picture><span><source srcset='data:,b'><img data-expect=''></span></picture></div>
+<div><picture><span><source srcset='data:,b'><img src='data:,a' data-expect='data:,a'></span></picture></div>
+<div><picture><source srcset='data:,b'><span><img src='data:,a' data-expect='data:,a'></span></picture></div>
+
+<!-- no src -->
+
+<div><picture><source srcset='data:,b'><img data-expect='data:,b'></picture></div>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-map-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-map-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-map-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-object-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-object-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-object-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-object-element/object-attributes.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-object-element/object-attributes.html
new file mode 100644
index 00000000000..30fdcf520b8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-object-element/object-attributes.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: object - attributes</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body onload="on_load()">
+<div id="log"></div>
+<form>
+ <object id="obj1" data="blue.html" name="o" height="50" width="100"></object>
+ <object id="obj2" name="p" type="image/png"></object>
+</form>
+<script>
+ var obj1;
+ var obj2;
+ var t1 = async_test("object.contentWindow");
+ var t3 = async_test("object.width");
+ var t4 = async_test("object.height");
+
+ setup(function() {
+ obj1 = document.getElementById("obj1");
+ obj2 = document.getElementById("obj2");
+ });
+
+ function on_load () {
+ t1.step(function() {
+ assert_equals(obj1.contentWindow.name, "o", "The contentWindow's name of the object element should be 'o'.");
+ assert_equals(obj2.contentWindow, null, "The contentWindow of the object element should be null when it type attribute starts with 'image/'.");
+ obj1.setAttribute("name", "o1");
+ assert_equals(obj1.name, "o1", "The name of the object element should be 'o1'.");
+ assert_equals(obj1.contentWindow.name, "o1", "The contentWindow's name of the object element should be 'o1'.");
+ obj1.removeAttribute("name");
+ assert_equals(obj1.name, "", "The name of the object element should be empty string.");
+ assert_equals(obj1.contentWindow.name, "", "The contentWindow's name of the object element should be empty string.");
+ });
+ t1.done()
+
+ t3.step(function() {
+ assert_equals(getComputedStyle(obj1, null)["width"], "100px", "The width should be 100px.");
+ });
+ t3.done();
+
+ t4.step(function() {
+ assert_equals(getComputedStyle(obj1, null)["height"], "50px", "The height should be 50px.");
+ });
+ t4.done();
+ }
+</script>
+
+</body>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-object-element/object-events.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-object-element/object-events.html
new file mode 100644
index 00000000000..9cce02796b5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-object-element/object-events.html
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: object-events</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+
+async_test(function(t) {
+ var obj = document.createElement("object");
+ obj.onerror = t.step_func_done(function(e){
+ assert_equals(Object.getPrototypeOf(e).constructor, Event, "The error event should use the Event interface.");
+ assert_true(e.isTrusted, "The error event should be a trusted event.");
+ assert_false(e.cancelable, "The error event should not be a cancelable event.");
+ assert_false(e.bubbles, "The error event should not be a bubble event.");
+ assert_equals(e.target, obj, "The error event target should be the corresponding object element.");
+ });
+
+ obj.onload = t.step_func_done(function(e){
+ assert_unreached("The load event should not be fired.");
+ });
+
+ obj.data = "file:\\http://nonexistent.html";
+ document.body.appendChild(obj);
+}, "error event");
+
+async_test(function(t) {
+ var obj = document.createElement("object");
+ obj.onload = t.step_func_done(function(e){
+ assert_equals(Object.getPrototypeOf(e).constructor, Event, "The load event should use the Event interface.");
+ assert_true(e.isTrusted, "The load event should be a trusted event.");
+ assert_false(e.cancelable, "The load event should not be a cancelable event.");
+ assert_false(e.bubbles, "The load event should not be a bubble event.");
+ assert_equals(e.target, obj, "The load event target should be the corresponding object element.");
+ });
+
+ obj.onerror = t.step_func_done(function(e){
+ assert_unreached("The error event should not be fired.");
+ });
+
+ obj.data = "/images/blue.png";
+ document.body.appendChild(obj);
+}, "load event");
+
+async_test(function(t) {
+ var obj = document.createElement("object");
+ obj.onload = t.step_func_done(function(e){
+ assert_true(obj.contentWindow instanceof Window, "The object element should represent a nested browsing context.")
+ assert_equals(Object.getPrototypeOf(e).constructor, Event, "The load event should use the Event interface.");
+ assert_true(e.isTrusted, "The load event should be a trusted event.");
+ assert_false(e.cancelable, "The load event should not be a cancelable event.");
+ assert_false(e.bubbles, "The load event should not be a bubble event.");
+ assert_equals(e.target, obj, "The load event target should be the corresponding object element.");
+ });
+
+ obj.onerror = t.step_func_done(function(e){
+ assert_unreached("The error event should not be fired.");
+ });
+
+ obj.data = "about:blank";
+ document.body.appendChild(obj);
+}, "load event of about:blank");
+
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-object-element/object-fallback.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-object-element/object-fallback.html
new file mode 100644
index 00000000000..d5469a3edc1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-object-element/object-fallback.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: display fallback content</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+
+var t1 = async_test("the typemustmatch attribute is specified");
+var t2 = async_test("the typemustmatch attribute is not specified");
+
+</script>
+<body onload="t1.done(); t2.done()">
+<object id="obj"></object>
+<div id="log"></div>
+<script>
+
+t1.step(function() {
+ var obj1 = document.createElement("object");
+ obj1.setAttribute("data", "/images/blue.png");
+ obj1.setAttribute("type", "text/plain");
+ obj1.setAttribute("typemustmatch", "");
+ obj1.onload = t1.step_func(function () {
+ assert_true("typeMustMatch" in obj1, "typeMustMatch is not supported.");
+ assert_unreached("The image of the first object should not be loaded.");
+ });
+ document.getElementById("obj").appendChild(obj1);
+});
+
+t2.step(function () {
+ var obj2 = document.createElement("object");
+ obj2.setAttribute("data", "test2.html");
+ obj2.setAttribute("type", "text/plain");
+ obj2.onload = t2.step_func( function () {
+ assert_not_equals(obj2.contentDocument, null, "The test2.html should be loaded.");
+ });
+ document.getElementById("obj").appendChild(obj2);
+});
+
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-object-element/object-handler.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-object-element/object-handler.html
new file mode 100644
index 00000000000..a24554e0cc3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-object-element/object-handler.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: object - handler</title>
+<link rel="author" title="Intel" href="http://www.intel.com" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<object id="test" name="obj" data="test0.html" type="text/html"></object>
+<script>
+
+var t1 = async_test("The nested browsing context must be navigated to the resource specified by the data attribute.");
+var t2 = async_test("The object.data must not be updated if the browsing context gets further navigated.");
+
+function callback(data) {
+ if (data == "test0") {
+ t1.step(function() {
+ var testEle = document.getElementById("test");
+ assert_true(testEle.contentDocument.location.href.indexOf("test0.html") != -1, "The nested browsing context should be navigated to test0.html.");
+ window["obj"].history.replaceState({state:"ok"}, "mytitle ", "object-fallback.html");
+ assert_not_equals(testEle.contentDocument.location.href.indexOf("object-fallback.html"), -1, "The nested browsing context should be replacement enabled.");
+ });
+ t1.done();
+ } else if (data == "test1") {
+ t2.step(function() {
+ var testEle = document.getElementById("test");
+ assert_true(testEle.contentDocument.location.href.indexOf("test1.html") != -1, "The browsing context should be navigated to test1.html.");
+ assert_true(testEle.data.indexOf("test0.html") != -1, "The value of attribute data should not be updated.");
+ });
+ t2.done();
+ }
+}
+
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-object-element/test0.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-object-element/test0.html
new file mode 100644
index 00000000000..17df71daa24
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-object-element/test0.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<script>
+
+parent.callback("test0");
+document.location.href = "test1.html";
+
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-object-element/test1.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-object-element/test1.html
new file mode 100644
index 00000000000..cf2423275ea
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-object-element/test1.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<script>
+
+parent.callback("test1");
+
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-object-element/test2.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-object-element/test2.html
new file mode 100644
index 00000000000..e5061eaea0d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-object-element/test2.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: object - fallback</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-param-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-param-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-param-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-source-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-source-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-source-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-track-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-track-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-track-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-video-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-video-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-video-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-video-element/video-tabindex.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-video-element/video-tabindex.html
new file mode 100644
index 00000000000..30448747892
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-video-element/video-tabindex.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<title>tabindex on video elements</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#video">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<div id="test">
+<video></video>
+</div>
+<script>
+var t = async_test("Attributes shouldn't magically appear");
+on_event(window, "load", t.step_func(function() {
+ var el = document.getElementById("test").getElementsByTagName("video")[0];
+ assert_equals(el.hasAttribute("tabindex"), false);
+ t.done()
+}))
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-video-element/video_content-ref.htm b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-video-element/video_content-ref.htm
new file mode 100644
index 00000000000..c02abb1236d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-video-element/video_content-ref.htm
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>HTML5 Media Elements: Content inside the 'video' element is not shown to the user.</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ </head>
+ <body>
+ <div id='testcontent'>
+ </div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-video-element/video_content_image.htm b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-video-element/video_content_image.htm
new file mode 100644
index 00000000000..0808d894aa7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-video-element/video_content_image.htm
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>HTML5 Media Elements: Content inside the 'video' element is not shown to the user.</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#video" />
+ <link rel="match" href="video_content-ref.htm" />
+ <meta name="assert" content="Content inside the 'video' element is not shown to the user (image)." />
+ </head>
+ <body>
+ <div id='testcontent'>
+ <video><img src="../../../../images/fail.gif" /></video>
+ </div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-video-element/video_content_text.htm b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-video-element/video_content_text.htm
new file mode 100644
index 00000000000..639fb73f8ff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-video-element/video_content_text.htm
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>HTML5 Media Elements: Content inside the 'video' element is not shown to the user.</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#video" />
+ <link rel="match" href="video_content-ref.htm" />
+ <meta name="assert" content="Content inside the 'video' element is not shown to the user." />
+ </head>
+ <body>
+ <div id='testcontent'>
+ <video><p style="color: red;">FAIL</p></video>
+ </div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-video-element/video_dynamic_poster-ref.htm b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-video-element/video_dynamic_poster-ref.htm
new file mode 100644
index 00000000000..78c03626e11
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-video-element/video_dynamic_poster-ref.htm
@@ -0,0 +1,5 @@
+<!DOCTYPE HTML>
+<meta charset=UTF-8>
+<title>Reference for poster tests</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com/">
+<img src="/media/poster.png">
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-video-element/video_dynamic_poster_absolute.htm b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-video-element/video_dynamic_poster_absolute.htm
new file mode 100644
index 00000000000..bec2b0fba72
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-video-element/video_dynamic_poster_absolute.htm
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML>
+<meta charset=UTF-8>
+<title>The 'HTMLVideoElement' interface supports setting 'poster' to an absolute URL</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-video-poster">
+<link rel="match" href="video_dynamic_poster-ref.htm">
+<meta name="assert" content="The 'HTMLVideoElement' interface supports setting 'poster' to an absolute URL">
+<video id="video0">Your browser does not support video.</video>
+<script>
+var testElem = document.getElementById("video0");
+testElem.poster = "/media/poster.png";
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-video-element/video_dynamic_poster_relative.htm b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-video-element/video_dynamic_poster_relative.htm
new file mode 100644
index 00000000000..4faca61c40a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-video-element/video_dynamic_poster_relative.htm
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML>
+<meta charset=UTF-8>
+<title>The 'HTMLVideoElement' interface supports setting 'poster' to a relative URL</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-video-poster">
+<link rel="match" href="video_dynamic_poster-ref.htm">
+<meta name="assert" content="The 'HTMLVideoElement' interface supports setting 'poster' to a relative URL">
+<video id="video0">Your browser does not support video.</video>
+<script>
+var testElem = document.getElementById("video0");
+testElem.poster = "../../../../media/poster.png";
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-video-element/video_initially_paused-ref.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-video-element/video_initially_paused-ref.html
new file mode 100644
index 00000000000..8556aabf23f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-video-element/video_initially_paused-ref.html
@@ -0,0 +1,8 @@
+<!DOCTYPE HTML>
+<meta charset=UTF-8>
+<title>Video elements should initially be paused</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-media-paused">
+<script src="/common/media.js"></script>
+<p>The following video element should be paused. (All clocks at zero).</p>
+<img src='/images/movie_300_frame_0.png'>
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-video-element/video_initially_paused.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-video-element/video_initially_paused.html
new file mode 100644
index 00000000000..b2725b04aa1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-video-element/video_initially_paused.html
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML>
+<meta charset=UTF-8>
+<title>Video elements should initially be paused</title>
+<link rel="match" href="video_initially_paused-ref.html">
+<link rel="author" title="Microsoft" href="http://www.microsoft.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-media-paused">
+<script src="/common/media.js"></script>
+<style>
+div#video {
+ padding: 6px 3px;
+}
+</style>
+<p>The following video element should be paused. (All clocks at zero).</p>
+<div id=video>
+<script>
+document.write(
+ "<video src='"+ getVideoURI('/media/movie_300') + "' >" +
+ "Your browser does not support the video element." +
+ "<\/video>");
+</script>
+</div>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/forms/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/attributes-common-to-form-controls/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/forms/attributes-common-to-form-controls/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/attributes-common-to-form-controls/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/attributes-common-to-form-controls/contains.json b/tests/wpt/web-platform-tests/html/semantics/forms/attributes-common-to-form-controls/contains.json
new file mode 100644
index 00000000000..357a1e6a7b8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/attributes-common-to-form-controls/contains.json
@@ -0,0 +1,34 @@
+[
+ {
+ "id": "naming-form-controls-the-name-attribute",
+ "original_id": "naming-form-controls:-the-name-attribute"
+ },
+ {
+ "id": "submitting-element-directionality-the-dirname-attribute",
+ "original_id": "submitting-element-directionality:-the-dirname-attribute"
+ },
+ {
+ "id": "limiting-user-input-length-the-maxlength-attribute",
+ "original_id": "limiting-user-input-length:-the-maxlength-attribute"
+ },
+ {
+ "id": "enabling-and-disabling-form-controls-the-disabled-attribute",
+ "original_id": "enabling-and-disabling-form-controls:-the-disabled-attribute"
+ },
+ {
+ "id": "form-submission",
+ "original_id": "form-submission"
+ },
+ {
+ "id": "autofocusing-a-form-control-the-autofocus-attribute",
+ "original_id": "autofocusing-a-form-control:-the-autofocus-attribute"
+ },
+ {
+ "id": "input-modalities-the-inputmode-attribute",
+ "original_id": "input-modalities:-the-inputmode-attribute"
+ },
+ {
+ "id": "autofilling-form-controls-the-autocomplete-attribute",
+ "original_id": "autofilling-form-controls:-the-autocomplete-attribute"
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/attributes-common-to-form-controls/dirname-ltr-iframe.html b/tests/wpt/web-platform-tests/html/semantics/forms/attributes-common-to-form-controls/dirname-ltr-iframe.html
new file mode 100644
index 00000000000..b5ed7e3d9a7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/attributes-common-to-form-controls/dirname-ltr-iframe.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Submitting element directionality: the dirname attribute support</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/attributes-common-to-form-controls/dirname-ltr.html b/tests/wpt/web-platform-tests/html/semantics/forms/attributes-common-to-form-controls/dirname-ltr.html
new file mode 100644
index 00000000000..28d1c150b37
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/attributes-common-to-form-controls/dirname-ltr.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Submitting element directionality: the dirname attribute</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#submitting-element-directionality:-the-dirname-attribute">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<form action="dirname-ltr-iframe.html" method=get target="iframe">
+ <p><label>Comment: <input type=text name="comment" dirname="comment.dir" required></label></p>
+ <p><button type=submit>Post Comment</button></p>
+</form>
+<iframe name="iframe"></iframe>
+<script>
+ function getParameterByName(name) {
+ name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
+ var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
+ results = regex.exec(document.querySelector("iframe").contentWindow.location.search);
+ return results == null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
+ }
+
+ var t = async_test("submit element directionality");
+ document.querySelector("input").value="foobar";
+ document.querySelector("button").click();
+
+ document.querySelector("iframe").onload = t.step_func_done(function() {
+ assert_equals(getParameterByName("comment.dir"), "ltr");
+ });
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/attributes-common-to-form-controls/dirname-rtl-manual.html b/tests/wpt/web-platform-tests/html/semantics/forms/attributes-common-to-form-controls/dirname-rtl-manual.html
new file mode 100644
index 00000000000..cb00f6972df
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/attributes-common-to-form-controls/dirname-rtl-manual.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Submitting element directionality: the dirname attribute (rtl)</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#submitting-element-directionality:-the-dirname-attribute">
+<form action="dirname-rtl-manual.html" method=get>
+ <p><label>Comment: <input type=text name="comment" dirname="comment.dir" required></label></p>
+ <p><button type=submit>Post Comment</button></p>
+</form>
+<p>Switch to a right-to-left writing direction, enter a text in the input and submit the form.</p>
+<p>Test passes if the word "PASS" appears below</p>
+<script>
+ function getParameterByName(name) {
+ name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
+ var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
+ results = regex.exec(location.search);
+ return results == null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
+ }
+
+ var commentDir = getParameterByName("comment.dir");
+ if (commentDir) {
+ var p = document.createElement("p");
+ p.textContent = (commentDir == "rtl") ? "PASS" : "FAIL";
+ document.body.appendChild(p);
+ }
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/attributes-common-to-form-controls/disabled-elements-01.html b/tests/wpt/web-platform-tests/html/semantics/forms/attributes-common-to-form-controls/disabled-elements-01.html
new file mode 100644
index 00000000000..14443e40997
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/attributes-common-to-form-controls/disabled-elements-01.html
@@ -0,0 +1,84 @@
+<!DOCTYPE html>
+<title>HTMLFormElement: the disabled attribute</title>
+<link rel="author" title="Eric Casler" href="mailto:ericorange@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#enabling-and-disabling-form-controls:-the-disabled-attribute">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id="log"></div>
+<div id="root"></div>
+<script>
+// Elements tested for in this file
+var types = ["button", "input", "select", "textarea"];
+// no tests for: optgroup, option, fieldset
+
+var root = document.getElementById("root");
+for (var element_type = 0; element_type < types.length; element_type++) {
+ test(function() {
+ root.innerHTML = "<"+types[element_type]+" + id='elem'></"+types[element_type]+">";
+
+ var elem = document.getElementById("elem");
+ assert_false(elem.disabled);
+ },
+ "Test ["+types[element_type]+"]: default behaviour is NOT disabled");
+
+ test(function() {
+ var formats = ["disabled",
+ "disabled=disabled", "disabled='disabled'",
+ "disabled='true'", "disabled=true",
+ "disabled='false'", "disabled=false"];
+
+ for (var f = 0; f < formats.length; f++) {
+ root.innerHTML = "<"+types[element_type]+" id='elem' " + formats[f] + "></"+types[element_type]+">";
+
+ var elem = document.getElementById("elem");
+ assert_true(elem.disabled);
+ }
+ },
+ "Test ["+types[element_type]+"]: verify disabled acts as boolean attribute");
+
+ test(function() {
+ root.innerHTML = "<"+types[element_type]+" id='elem'></"+types[element_type]+"><input id='other' value='no event dispatched'></input>";
+ var elem = document.getElementById("elem"),
+ other = document.getElementById("other");
+
+ assert_equals(other.value, "no event dispatched");
+
+ elem.disabled = true;
+ assert_true(elem.disabled);
+
+ elem.onclick = function () {
+ // change value of other element, to avoid *.value returning "" for disabled elements
+ document.getElementById("other").value = "event dispatched";
+ };
+
+ // Check if dispatched event executes
+ var evObj = document.createEvent('Events');
+ evObj.initEvent("click", true, false);
+ elem.dispatchEvent(evObj);
+ assert_equals(other.value, "event dispatched");
+ },
+ "Test ["+types[element_type]+"]: synthetic click events should be dispatched");
+
+ test(function() {
+ root.innerHTML = "<"+types[element_type]+" id='elem'></"+types[element_type]+"><input id='other' value='no event dispatched'></input>";
+ var elem = document.getElementById("elem"),
+ other = document.getElementById("other");
+
+ assert_equals(other.value, "no event dispatched");
+
+ elem.disabled = true;
+ assert_true(elem.disabled);
+
+ elem.onclick = function () {
+ // change value of other element, to avoid *.value returning "" for disabled elements
+ document.getElementById("other").value = "event dispatched";
+ };
+
+ // Check that click() on a disabled element doesn't dispatch a click event.
+ elem.click();
+ assert_equals(other.value, "no event dispatched");
+ },
+ "Test ["+types[element_type]+"]: click() should not dispatch a click event");
+}
+root.innerHTML = "";
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/attributes-common-to-form-controls/formAction_document_address.html b/tests/wpt/web-platform-tests/html/semantics/forms/attributes-common-to-form-controls/formAction_document_address.html
new file mode 100644
index 00000000000..d14cad53298
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/attributes-common-to-form-controls/formAction_document_address.html
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>HTML Test: formAction_document_address</title>
+ <link rel="author" title="Intel" href="http://www.intel.com/">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-fs-formaction">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-document's-address">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-button-element">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-input-element">
+ <meta name="assert" content="On getting the formAction IDL attribute, when the content attribute is missing or its value is the empty string, the document's address must be returned instead.">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+
+ <div id="missing" style="display:none">
+ <button type="submit">Submit</button>
+ <input type="submit">
+ </div>
+
+ <div id="empty_string" style="display:none">
+ <button type="submit" formaction="">Submit</button>
+ <input type="submit" formaction="">
+ </div>
+
+ <div id="no_assigned_value" style="display:none">
+ <button type="submit" formaction>Submit</button>
+ <input type="submit" formaction>
+ </div>
+
+ <script>
+ // formaction content attribute is missing
+ test(function() {
+ var formAction = document.querySelector('#missing button').formAction;
+ var address = document.location.href;
+ assert_equals(formAction, address);
+ }, "Check if button.formAction is the document's address when formaction content attribute is missing");
+
+ test(function() {
+ var formAction = document.querySelector('#missing input').formAction;
+ var address = document.location.href;
+ assert_equals(formAction, address);
+ }, "Check if input.formAction is the document's address when formaction content attribute is missing");
+
+ // formaction content attribute value is empty string
+ test(function() {
+ var formAction = document.querySelector('#empty_string button').formAction;
+ var address = document.location.href;
+ assert_equals(formAction, address);
+ }, "Check if button.formAction is the document's address when formaction content attribute value is empty string");
+
+ test(function() {
+ var formAction = document.querySelector('#empty_string input').formAction;
+ var address = document.location.href;
+ assert_equals(formAction, address);
+ }, "Check if input.formAction is the document's address when formaction content attribute value is empty string");
+
+ // formaction content attribute value is not assigned, just for comparison with empty string above
+ test(function() {
+ var formAction = document.querySelector('#no_assigned_value button').formAction;
+ var address = document.location.href;
+ assert_equals(formAction, address);
+ }, "Check if button.formAction is the document's address when formaction content attribute value is not assigned");
+
+ test(function() {
+ var formAction = document.querySelector('#no_assigned_value input').formAction;
+ var address = document.location.href;
+ assert_equals(formAction, address);
+ }, "Check if input.formAction is the document's address when formaction content attribute value is not assigned");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/attributes-common-to-form-controls/formaction.html b/tests/wpt/web-platform-tests/html/semantics/forms/attributes-common-to-form-controls/formaction.html
new file mode 100644
index 00000000000..82798eaa84f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/attributes-common-to-form-controls/formaction.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html><head>
+ <title>formaction on button element</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="content-type">
+ <meta content="formaction on button element" name="description">
+ <link href="https://html.spec.whatwg.org/multipage/#dom-fs-formaction" rel="help">
+</head>
+ <body>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ <div id="log"></div>
+ <button formaction="http://www.example.com/" style="display: none" type="submit">Submit</button>
+ <input formaction="http://www.example.com/" style="display: none" type="submit" value="submit">
+ <input style="display: none" type="submit" value="submit">
+ <input formaction="" style="display: none" type="submit" value="submit">
+
+ <script type="text/javascript">
+ function relativeToAbsolute(relativeURL) {
+ var a = document.createElement('a');
+ a.href = relativeURL;
+ return a.href;
+ }
+ test(function() {assert_equals(document.getElementsByTagName("button")[0].formAction, "http://www.example.com/")}, "formAction on button support");
+ test(function() {assert_equals(document.getElementsByTagName("input")[0].formAction, "http://www.example.com/")}, "formAction on input support");
+
+ var testElem = document.getElementsByTagName("input")[0];
+ testElem.formAction = "http://www.example.com/page2.html";
+
+ test(function() {assert_equals(document.getElementsByTagName("input")[0].formAction, "http://www.example.com/page2.html")}, "formaction absolute URL value on input reflects correct value after being updated by the DOM");
+ test(function() {assert_equals(document.getElementsByTagName("input")[0].getAttribute("formaction"), "http://www.example.com/page2.html")}, "formAction absolute URL value is correct using getAttribute");
+
+ var testElem = document.getElementsByTagName("input")[0];
+ testElem.formAction = "../page3.html";
+
+ test(function() {assert_equals(document.getElementsByTagName("input")[0].formAction, relativeToAbsolute('../page3.html'))}, "formAction relative URL value on input reflects correct value after being updated by the DOM");
+ test(function() {assert_equals(document.getElementsByTagName("input")[0].getAttribute("formaction"), "../page3.html")}, "formAction relative URL value is correct using getAttribute");
+
+ test(function() {assert_equals(document.getElementsByTagName("input")[1].formAction, document.URL)}, "On getting, when formaction is missing, the document's address must be returned");
+ test(function() {assert_equals(document.getElementsByTagName("input")[2].formAction, document.URL)}, "On getting, when formaction value is the empty string, the document's address must be returned");
+ </script>
+</body></html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/categories/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/forms/categories/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/categories/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/constraints/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/forms/constraints/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/constraints/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/constraints/contains.json b/tests/wpt/web-platform-tests/html/semantics/forms/constraints/contains.json
new file mode 100644
index 00000000000..67e4c3b12e0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/constraints/contains.json
@@ -0,0 +1,18 @@
+[
+ {
+ "id": "definitions",
+ "original_id": "definitions"
+ },
+ {
+ "id": "constraint-validation",
+ "original_id": "constraint-validation"
+ },
+ {
+ "id": "the-constraint-validation-api",
+ "original_id": "the-constraint-validation-api"
+ },
+ {
+ "id": "security-forms",
+ "original_id": "security-forms"
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-checkValidity.html b/tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-checkValidity.html
new file mode 100644
index 00000000000..9ef5ddd819a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-checkValidity.html
@@ -0,0 +1,145 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>The constraint validation API Test: element.checkValidity()</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-cva-checkvalidity">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-constraint-validation-api">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/validator.js"></script>
+<div id="log"></div>
+<script>
+ var testElements = [
+ {
+ tag: "input",
+ types: ["text", "search", "tel", "password"],
+ testData: [
+ {conditions: {}, expected: true, name: "[target] no constraint"},
+ {conditions: {maxLength: "4", value: "abcdef"}, expected: false, name: "[target] suffering from being too long", dirty: true},
+ {conditions: {pattern: "[A-Z]", value: "abc"}, expected: false, name: "[target] suffering from a pattern mismatch"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] suffering from being missing"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["url"],
+ testData: [
+ {conditions: {}, expected: true, name: "[target] no constraint"},
+ {conditions: {maxLength: "20", value: "http://www.example.com"}, expected: false, name: "[target] suffering from being too long", dirty: true},
+ {conditions: {pattern: "http://www.example.com", value: "http://www.example.net"}, expected: false, name: "[target] suffering from a pattern mismatch"},
+ {conditions: {value: "abc"}, expected: false, name: "[target] suffering from a type mismatch"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] suffering from being missing"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["email"],
+ testData: [
+ {conditions: {}, expected: true, name: "[target] no constraint"},
+ {conditions: {maxLength: "10", value: "test@example.com"}, expected: false, name: "[target] suffering from being too long", dirty: true},
+ {conditions: {pattern: "test@example.com", value: "test@example.net"}, expected: false, name: "[target] suffering from a pattern mismatch"},
+ {conditions: {value: "abc"}, expected: false, name: "[target] suffering from a type mismatch"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] suffering from being missing"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["datetime"],
+ testData: [
+ {conditions: {}, expected: true, name: "[target] no constraint"},
+ {conditions: {max: "2000-01-01T12:00:00Z", value: "2001-01-01T12:00:00Z"}, expected: false, name: "[target] suffering from an overflow"},
+ {conditions: {min: "2001-01-01T12:00:00Z", value: "2000-01-01T12:00:00Z"}, expected: false, name: "[target] suffering from an underflow"},
+ {conditions: {step: 2 * 60 * 1000, value: "2001-01-01T12:03:00Z"}, expected: false, name: "[target] suffering from a step mismatch"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] suffering from being missing"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["date"],
+ testData: [
+ {conditions: {}, expected: true, name: "[target] no constraint"},
+ {conditions: {max: "2000-01-01", value: "2001-01-01"}, expected: false, name: "[target] suffering from an overflow"},
+ {conditions: {min: "2001-01-01", value: "2000-01-01"}, expected: false, name: "[target] suffering from an underflow"},
+ {conditions: {step: 2 * 1 * 86400000, value: "2001-01-03"}, expected: false, name: "[target] suffering from a step mismatch"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] suffering from being missing"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["month"],
+ testData: [
+ {conditions: {}, expected: true, name: "[target] no constraint"},
+ {conditions: {max: "2000-01", value: "2001-01"}, expected: false, name: "[target] suffering from an overflow"},
+ {conditions: {min: "2001-01", value: "2000-01"}, expected: false, name: "[target] suffering from an underflow"},
+ {conditions: {step: 2 * 1 * 1, value: "2001-03"}, expected: false, name: "[target] suffering from a step mismatch"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] suffering from being missing"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["week"],
+ testData: [
+ {conditions: {}, expected: true, name: "[target] no constraint"},
+ {conditions: {max: "2000-W01", value: "2001-W01"}, expected: false, name: "[target] suffering from an overflow"},
+ {conditions: {min: "2001-W01", value: "2000-W01"}, expected: false, name: "[target] suffering from an underflow"},
+ {conditions: {step: 2 * 1 * 604800000, value: "2001-W03"}, expected: false, name: "[target] suffering from a step mismatch"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] suffering from being missing"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["time"],
+ testData: [
+ {conditions: {}, expected: true, name: "[target] no constraint"},
+ {conditions: {max: "12:00:00", value: "13:00:00"}, expected: false, name: "[target] suffering from an overflow"},
+ {conditions: {min: "12:00:00", value: "11:00:00"}, expected: false, name: "[target] suffering from an underflow"},
+ {conditions: {step: 2 * 60 * 1000, value: "12:03:00"}, expected: false, name: "[target] suffering from a step mismatch"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] suffering from being missing"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["number"],
+ testData: [
+ {conditions: {max: "5", value: "6"}, expected: false, name: "[target] suffering from an overflow"},
+ {conditions: {min: "5", value: "4"}, expected: false, name: "[target] suffering from an underflow"},
+ {conditions: {step: 2 * 1 * 1, value: "3"}, expected: false, name: "[target] suffering from a step mismatch"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] suffering from being missing"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["checkbox", "radio"],
+ testData: [
+ {conditions: {}, expected: true, name: "[target] no constraint"},
+ {conditions: {required: true, checked: false, name: "test1"}, expected: false, name: "[target] suffering from being missing"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["file"],
+ testData: [
+ {conditions: {}, expected: true, name: "[target] no constraint"},
+ {conditions: {required: true, files: null}, expected: false, name: "[target] suffering from being missing"}
+ ]
+ },
+ {
+ tag: "select",
+ types: [],
+ testData: [
+ {conditions: {}, expected: true, name: "[target] no constraint"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] suffering from being missing"}
+ ]
+ },
+ {
+ tag: "textarea",
+ types: [],
+ testData: [
+ {conditions: {}, expected: true, name: "[target] no constraint"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] suffering from being missing"}
+ ]
+ }
+ ];
+
+ validator.run_test(testElements, "checkValidity");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-reportValidity.html b/tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-reportValidity.html
new file mode 100644
index 00000000000..f69c1255510
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-reportValidity.html
@@ -0,0 +1,145 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>The constraint validation API Test: element.reportValidity()</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-cva-reportvalidity">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-constraint-validation-api">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/validator.js"></script>
+<div id="log"></div>
+<script>
+ var testElements = [
+ {
+ tag: "input",
+ types: ["text", "search", "tel", "password"],
+ testData: [
+ {conditions: {}, expected: true, name: "[target] no constraint"},
+ {conditions: {maxLength: "4", value: "abcdef"}, expected: false, name: "[target] suffering from being too long", dirty: true},
+ {conditions: {pattern: "[A-Z]", value: "abc"}, expected: false, name: "[target] suffering from a pattern mismatch"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] suffering from being missing"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["url"],
+ testData: [
+ {conditions: {}, expected: true, name: "[target] no constraint"},
+ {conditions: {maxLength: "20", value: "http://www.example.com"}, expected: false, name: "[target] suffering from being too long", dirty: true},
+ {conditions: {pattern: "http://www.example.com", value: "http://www.example.net"}, expected: false, name: "[target] suffering from a pattern mismatch"},
+ {conditions: {value: "abc"}, expected: false, name: "[target] suffering from a type mismatch"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] suffering from being missing"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["email"],
+ testData: [
+ {conditions: {}, expected: true, name: "[target] no constraint"},
+ {conditions: {maxLength: "10", value: "test@example.com"}, expected: false, name: "[target] suffering from being too long", dirty: true},
+ {conditions: {pattern: "test@example.com", value: "test@example.net"}, expected: false, name: "[target] suffering from a pattern mismatch"},
+ {conditions: {value: "abc"}, expected: false, name: "[target] suffering from a type mismatch"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] suffering from being missing"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["datetime"],
+ testData: [
+ {conditions: {}, expected: true, name: "[target] no constraint"},
+ {conditions: {max: "2000-01-01T12:00:00Z", value: "2001-01-01T12:00:00Z"}, expected: false, name: "[target] suffering from an overflow"},
+ {conditions: {min: "2001-01-01T12:00:00Z", value: "2000-01-01T12:00:00Z"}, expected: false, name: "[target] suffering from an underflow"},
+ {conditions: {step: 2 * 60 * 1000, value: "2001-01-01T12:03:00Z"}, expected: false, name: "[target] suffering from a step mismatch"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] suffering from being missing"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["date"],
+ testData: [
+ {conditions: {}, expected: true, name: "[target] no constraint"},
+ {conditions: {max: "2000-01-01", value: "2001-01-01"}, expected: false, name: "[target] suffering from an overflow"},
+ {conditions: {min: "2001-01-01", value: "2000-01-01"}, expected: false, name: "[target] suffering from an underflow"},
+ {conditions: {step: 2 * 1 * 86400000, value: "2001-01-03"}, expected: false, name: "[target] suffering from a step mismatch"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] suffering from being missing"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["month"],
+ testData: [
+ {conditions: {}, expected: true, name: "[target] no constraint"},
+ {conditions: {max: "2000-01", value: "2001-01"}, expected: false, name: "[target] suffering from an overflow"},
+ {conditions: {min: "2001-01", value: "2000-01"}, expected: false, name: "[target] suffering from an underflow"},
+ {conditions: {step: 2 * 1 * 1, value: "2001-03"}, expected: false, name: "[target] suffering from a step mismatch"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] suffering from being missing"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["week"],
+ testData: [
+ {conditions: {}, expected: true, name: "[target] no constraint"},
+ {conditions: {max: "2000-W01", value: "2001-W01"}, expected: false, name: "[target] suffering from an overflow"},
+ {conditions: {min: "2001-W01", value: "2000-W01"}, expected: false, name: "[target] suffering from an underflow"},
+ {conditions: {step: 2 * 1 * 604800000, value: "2001-W03"}, expected: false, name: "[target] suffering from a step mismatch"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] suffering from being missing"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["time"],
+ testData: [
+ {conditions: {}, expected: true, name: "[target] no constraint"},
+ {conditions: {max: "12:00:00", value: "13:00:00"}, expected: false, name: "[target] suffering from an overflow"},
+ {conditions: {min: "12:00:00", value: "11:00:00"}, expected: false, name: "[target] suffering from an underflow"},
+ {conditions: {step: 2 * 60 * 1000, value: "12:03:00"}, expected: false, name: "[target] suffering from a step mismatch"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] suffering from being missing"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["number"],
+ testData: [
+ {conditions: {max: "5", value: "6"}, expected: false, name: "[target] suffering from an overflow"},
+ {conditions: {min: "5", value: "4"}, expected: false, name: "[target] suffering from an underflow"},
+ {conditions: {step: 2 * 1 * 1, value: "3"}, expected: false, name: "[target] suffering from a step mismatch"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] suffering from being missing"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["checkbox", "radio"],
+ testData: [
+ {conditions: {}, expected: true, name: "[target] no constraint"},
+ {conditions: {required: true, checked: false, name: "test1"}, expected: false, name: "[target] suffering from being missing"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["file"],
+ testData: [
+ {conditions: {}, expected: true, name: "[target] no constraint"},
+ {conditions: {required: true, files: null}, expected: false, name: "[target] suffering from being missing"}
+ ]
+ },
+ {
+ tag: "select",
+ types: [],
+ testData: [
+ {conditions: {}, expected: true, name: "[target] no constraint"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] suffering from being missing"}
+ ]
+ },
+ {
+ tag: "textarea",
+ types: [],
+ testData: [
+ {conditions: {}, expected: true, name: "[target] no constraint"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] suffering from being missing"}
+ ]
+ }
+ ];
+
+ validator.run_test(testElements, "reportValidity");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-validate.html b/tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-validate.html
new file mode 100644
index 00000000000..1fde9b3e2cc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-validate.html
@@ -0,0 +1,122 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Constraint validation</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#constraint-validation">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<form id="fm1" style="display:none">
+ <fieldset id="test0">
+ <input type="text" required value="" id="test1">
+ </fieldset>
+ <input type="email" value="abc" id="test2">
+ <button id="test3">TEST</button>
+ <select id="test4"></select>
+ <textarea id="test5"></textarea>
+ <output id="test6"></output>
+</form>
+<form id="fm2" style="display:none">
+ <fieldset>
+ <input type="text" required value="abc">
+ </fieldset>
+ <input type="email" value="test@example.com">
+ <button>TEST</button>
+ <select></select>
+ <textarea></textarea>
+ <output></output>
+</form>
+<form id="fm3" style="display:none">
+ <fieldset id="fs">
+ <legend><input type="text" id="inp1"></legend>
+ <input type="text" required value="" id="inp2">
+ </fieldset>
+</form>
+
+<script>
+ var cancelable = true,
+ times1 = 0,
+ times2 = 0,
+ invalidList1 = [],
+ invalidList2 = [],
+ test1,
+ test2,
+ fm1,
+ fm2,
+ fm3;
+
+ setup(function () {
+ fm1 = document.getElementById("fm1");
+ fm2 = document.getElementById("fm2");
+ fm3 = document.getElementById("fm3");
+ test1 = document.getElementById("test1");
+ test2 = document.getElementById("test2");
+ for (var index = 0; index < fm1.elements.length; index++) {
+ var ele = fm1.elements.item(index);
+ ele.addEventListener("invalid", function (e) {
+ times1++;
+ invalidList1.push(e.target);
+ if (!e.cancelable)
+ cancelable = e.cancelable;
+ }, false);
+ }
+
+ for (var index = 0; index < fm1.elements.length; index++) {
+ var ele = fm2.elements.item(index);
+ ele.addEventListener("invalid", function (e) {
+ times2++;
+ invalidList2.push(ele);
+ }, false);
+ }
+ });
+
+ test(function(){
+ assert_false(fm1.checkValidity(), "The checkValidity method should be false.");
+ }, "If there is any invalid submittable element whose form owner is the form, the form.checkValidity must be false");
+
+ test(function(){
+ assert_true("reportValidity" in fm1, "The reportValidity method is not supported");
+ assert_false(fm1.reportValidity(), "The reportValidity method should be false.");
+ }, "If there is any invalid submittable element whose form owner is the form, the form.reportValidity must be false");
+
+ test(function(){
+ assert_true(fm2.checkValidity(), "The checkValidity method should be true.");
+ }, "If all of the submittable elements whose form owner is the form are valid, the form.checkValidity must be true");
+
+ test(function(){
+ assert_true("reportValidity" in fm2, "The reportValidity method is not supported.");
+ assert_true(fm2.reportValidity(), "The reportValidity method should be true.");
+ }, "If all of the submittable elements whose form owner is the form are valid, the form.reportValidity must be true");
+
+ test(function(){
+ assert_false(fm3.checkValidity(), "The checkValidity method should be false.");
+ document.getElementById("fs").disabled = true;
+ assert_true(fm3.checkValidity(), "The checkValidity method should be true.");
+
+ document.getElementById("inp1").value = "aaa";
+ document.getElementById("inp1").type = "url";
+ assert_false(fm3.checkValidity(), "The checkValidity method should be false.");
+ }, "Check the checkValidity method of the form element when it has a fieldset child");
+
+ test(function(){
+ assert_true("reportValidity" in fm3, "The reportValidity method is not supported.");
+ assert_false(fm3.reportValidity(), "The reportValidity method should be false.");
+ document.getElementById("fs").disabled = true;
+ assert_true(fm3.reportValidity(), "The reportValidity method should be true.");
+
+ document.getElementById("inp1").value = "aaa";
+ document.getElementById("inp1").type = "url";
+ assert_false(fm3.reportValidity(), "The reportValidity method should be false.");
+ }, "Check the reportValidity method of the form element when it has a fieldset child");
+
+ test(function () {
+ assert_equals(times1, 4, "The invalid event will be fired if the checkValidity or reportValidity method are called.");
+ assert_array_equals(invalidList1, [test1, test2, test1, test2], "The invalid event must be fired at the invalid control");
+ assert_true(cancelable, "The invalid event is cancelable.");
+ }, "The invalid event must be fired at the invalid controls");
+
+ test(function () {
+ assert_equals(times2, 0, "The invalid event should not be fired, times should be 0.");
+ assert_array_equals(invalidList2, [], "The invalid event should not be fired, invalid list should be empty");
+ }, "The invalid event must not be fired at the invalid controls");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-validity-badInput.html b/tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-validity-badInput.html
new file mode 100644
index 00000000000..8c4958a4000
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-validity-badInput.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>The constraint validation API Test: element.validity.badInput</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/multipage/association-of-controls-and-forms.html#suffering-from-bad-input">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/multipage/the-button-element.html#the-constraint-validation-api">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/validator.js"></script>
+<div id="log"></div>
+<script>
+var testElements = [
+ {
+ tag: "input",
+ types: ["email"],
+ testData: [
+ {conditions: {multiple: false, value: ""}, expected: false, name: "[target] The multiple attribute is false and the value attribute is empty"},
+ {conditions: {multiple: false, value: "test1@example.com"}, expected: false, name: "[target] The multiple attribute is false and the value attribute is a valid e-mail address"},
+ {conditions: {multiple: true, value: "test1@example.com,test2@eample.com"}, expected: false, name: "[target] The multiple attribute is true and the value contains valid e-mail addresses"},
+ {conditions: {multiple: true, value: "test,1@example.com"}, expected: false, name: "[target] The multiple attribute is true and the value attribute contains a ','"}
+ //TODO, the value contains characters that cannot be converted to punycode.
+ //Can not find a character that cannot be converted to punycode.
+ ]
+ },
+ {
+ tag: "input",
+ types: ["datetime"],
+ testData: [
+ {conditions: {value: ""}, expected: false, name: "[target] The value attribute is empty"},
+ {conditions: {value: "2000-01-01T12:00:00Z"}, expected: false, name: "[target] The value attribute is a valid date and time string"},
+ {conditions: {value: "abc"}, expected: true, name: "[target] The value attribute cannot convert to a valid normalized forced-UTC global date and time string"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["color"],
+ testData: [
+ {conditions: {value: ""}, expected: true, name: "[target] The value attribute is empty"},
+ {conditions: {value: "#000000"}, expected: false, name: "[target] The value attribute is a valid sample color"},
+ {conditions: {value: "#FFFFFF"}, expected: false, name: "[target] The value attribute is not a valid lowercase sample color"},
+ {conditions: {value: "abc"}, expected: true, name: "[target] The value attribute cannot convert to a valid sample color"}
+ ]
+ },
+ ];
+ validator.run_test (testElements, "badInput");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-validity-customError.html b/tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-validity-customError.html
new file mode 100644
index 00000000000..16e64214761
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-validity-customError.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>The constraint validation API Test: element.validity.customError</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-validitystate-customerror">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-constraint-validation-api">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/validator.js"></script>
+<div id="log"></div>
+<script>
+var testElements = [
+ {
+ tag: "input",
+ types: [],
+ testData: [
+ {conditions: {message: "My custom error"}, expected: true, name: "[target] The validity.customError must be true if the custom validity error message is not empty"},
+ {conditions: {message: ""}, expected: false, name: "[target] The validity.customError must be false if the custom validity error message is empty"}
+ ]
+ },
+ {
+ tag: "button",
+ types: [],
+ testData: [
+ {conditions: {message: "My custom error"}, expected: true, name: "[target] The validity.customError must be true if the custom validity error message is not empty"},
+ {conditions: {message: ""}, expected: false, name: "[target] The validity.customError must be false if the custom validity error message is empty"}
+ ]
+ },
+ {
+ tag: "select",
+ types: [],
+ testData: [
+ {conditions: {message: "My custom error"}, expected: true, name: "[target] The validity.customError must be true if the custom validity error message is not empty"},
+ {conditions: {message: ""}, expected: false, name: "[target] The validity.customError must be false i the custom validity error message is empty"}
+ ]
+ },
+ {
+ tag: "textarea",
+ types: [],
+ testData: [
+ {conditions: {message: "My custom error"}, expected: true, name: "[target] The validity.customError must be true if the custom validity error message is not empty"},
+ {conditions: {message: ""}, expected: false, name: "[target] The validity.customError must be false if the custom validity error message is empty"}
+ ]
+ }
+ ]
+
+ validator.run_test(testElements, "customError");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-validity-patternMismatch.html b/tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-validity-patternMismatch.html
new file mode 100644
index 00000000000..5a0012b0eb3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-validity-patternMismatch.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>The constraint validation API Test: element.validity.patternMismatch</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-validitystate-patternmismatch">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-constraint-validation-api">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/validator.js"></script>
+<div id="log"></div>
+<script>
+ var testElements = [
+ {
+ tag: "input",
+ types: ["text", "search", "tel", "url", "email", "password"],
+ testData: [
+ {conditions: {pattern: null, value: "abc"}, expected: false, name: "[target] The pattern attribute is not set"},
+ {conditions: {pattern: "[A-Z]+", value: ""}, expected: false, name: "[target] The value attibute is empty string"},
+ {conditions: {pattern: "[A-Z]{1}", value: "A"}, expected: false, name: "[target] The value attribute matches the pattern attribute"},
+ {conditions: {pattern: "[A-Z]+", value: "\u0041\u0042\u0043"}, expected: false, name: "[target] The value(ABC) in unicode attribute matches the pattern attribute"},
+ {conditions: {pattern: "[a-z]{3,}", value: "ABCD"}, expected: true, name: "[target] The value attribute mismatches the pattern attribute"}
+ ]
+ }
+ ];
+
+ validator.run_test (testElements, "patternMismatch");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-validity-rangeOverflow.html b/tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-validity-rangeOverflow.html
new file mode 100644
index 00000000000..2fe214265ae
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-validity-rangeOverflow.html
@@ -0,0 +1,116 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>The constraint validation API Test: element.validity.rangeOverflow</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-validitystate-rangeoverflow">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-constraint-validation-api">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/validator.js"></script>
+<div id="log"></div>
+<script>
+ var testElements = [
+ {
+ tag: "input",
+ types: ["datetime"],
+ testData: [
+ {conditions: {max: "", value: "2000-01-01T12:00:00Z"}, expected: false, name: "[target] The max attribute is not set"},
+ {conditions: {max: "2000-01-01T12:00:00Z", value: ""}, expected: false, name: "[target] Value is empty string"},
+ {conditions: {max: "2000-01-01 12:00:00Z", value: "2001-01-01T12:00:00Z"}, expected: false, name: "[target] The max attribute is an invalid global date time string"},
+ {conditions: {max: "2000-01-01T12:00:00Z", value: "2000-01-01T11:00:00Z"}, expected: false, name: "[target] The max attribute is greater than the value attribute"},
+ {conditions: {max: "2000-01-01T23:59:59Z", value: "2001-01-01T24:00:00Z"}, expected: false, name: "[target] The value is an invalid datetime string(hour is greater than 23)"},
+ {conditions: {max: "1970-01-01T12:00Z", value: "80-01-01T12:00Z"}, expected: false, name: "[target] The value if an invalid date time string(year is two digits)"},
+ {conditions: {max: "2000-01-01T12:00:00Z", value: "2001-01-01T13:00:00Z"}, expected: true, name: "[target] The value is greater than max"},
+ {conditions: {max: "2000-01-01T12:00:00.1Z", value: "2000-01-01T12:00:00.2Z"}, expected: true, name: "[target] The value is greater than max(with millisecond in 1 digit)"},
+ {conditions: {max: "2000-01-01T12:00:00.01Z", value: "2000-01-01T12:00:00.02Z"}, expected: true, name: "[target] The value is greater than max(with millisecond in 2 digits)"},
+ {conditions: {max: "2000-01-01T12:00:00.001Z", value: "2000-01-01T12:00:00.002Z"}, expected: true, name: "[target] The value is greater than max(with millisecond in 3 digits)"},
+ {conditions: {max: "2000-01-01T12:00:00", value: "10000-01-01T12:00:00"}, expected: true, name: "[target] The value is greater than max(Year is 10000 should be valid)"},
+ {conditions: {max: "8592-01-01T02:09+02:09", value: "8593-01-01T02:09+02:09"}, expected: true, name: "[target] The value is greater than max(with timezone)"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["date"],
+ testData: [
+ {conditions: {max: "", value: "2000-01-01"}, expected: false, name: "[target] The max attribute is not set"},
+ {conditions: {max: "2000-01-01", value: ""}, expected: false, name: "[target] Value is empty string"},
+ {conditions: {max: "2000/01/01", value: "2002-01-01"}, expected: false, name: "[target] The max attribute is an invalid date"},
+ {conditions: {max: "2000-01-01", value: "2000-2-2"}, expected: false, name: "[target] The value attribute is an invalid date"},
+ {conditions: {max: "987-01-01", value: "988-01-01"}, expected: false, name: "[target] The value is an invalid date(year is three digits)"},
+ {conditions: {max: "2000-01-01", value: "2000-13-01"}, expected: false, name: "[target] The value is an invalid date(month is greater than 12)"},
+ {conditions: {max: "2000-01-01", value: "2000-02-30"}, expected: false, name: "[target] The value is an invalid date(date is greater than 29 for Feb)"},
+ {conditions: {max: "2000-12-01", value: "2000-01-01"}, expected: false, name: "[target] The max attribute is greater than value attribute"},
+ {conditions: {max: "2000-12-01", value: "2001-01-01"}, expected: true, name: "[target] The value attribute is greater than max attribute"},
+ {conditions: {max: "9999-01-01", value: "10000-01-01"}, expected: true, name: "[target] The value attribute is greater than max attribute(Year is 10000 should be valid)"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["month"],
+ testData: [
+ {conditions: {max: "", value: "2000-01"}, expected: false, name: "[target] The max attribute is not set"},
+ {conditions: {max: "2000-01", value: ""}, expected: false, name: "[target] Value is empty string"},
+ {conditions: {max: "2000/01", value: "2001-02"}, expected: false, name: "[target] The max attribute is an invalid month string"},
+ {conditions: {max: "2000-01", value: "2000-1"}, expected: false, name: "[target] The value attribute is an invalid month string"},
+ {conditions: {max: "987-01", value: "988-01"}, expected: false, name: "[target] The value is an invalid month string(year is three digits)"},
+ {conditions: {max: "2000-01", value: "2000-13"}, expected: false, name: "[target] The value is an invalid month string(month is greater than 12)"},
+ {conditions: {max: "2000-12", value: "2000-01"}, expected: false, name: "[target] The max attribute is greater than value attribute"},
+ {conditions: {max: "2000-01", value: "2000-12"}, expected: true, name: "[target] The value attribute is greater than max attribute"},
+ {conditions: {max: "9999-01", value: "10000-01"}, expected: true, name: "[target] The value attribute is greater than max attribute(Year is 10000 should be valid)"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["week"],
+ testData: [
+ {conditions: {max: "", value: "2000-W01"}, expected: false, name: "[target] The max attribute is not set"},
+ {conditions: {max: "2000-W01", value: ""}, expected: false, name: "[target] Value is empty string"},
+ {conditions: {max: "2000/W01", value: "2001-W02"}, expected: false, name: "[target] The max attribute is an invalid week string"},
+ {conditions: {max: "2000-W01", value: "2000-W2"}, expected: false, name: "[target] The value attribute is an invalid week string"},
+ {conditions: {max: "2000-W01", value: "2000-w02"}, expected: false, name: "[target] The value attribute is an invalid week string(w is in lowercase)"},
+ {conditions: {max: "987-W01", value: "988-W01"}, expected: false, name: "[target] The value is an invalid week string(year is three digits)"},
+ {conditions: {max: "2000-W01", value: "2000-W57"}, expected: false, name: "[target] The value is an invalid week string(week is too greater)"},
+ {conditions: {max: "2000-W12", value: "2000-W01"}, expected: false, name: "[target] The max attribute is greater than value attribute"},
+ {conditions: {max: "2000-W01", value: "2000-W12"}, expected: true, name: "[target] The value attribute is greater than max attribute"},
+ {conditions: {max: "9999-W01", value: "10000-W01"}, expected: true, name: "[target] The value attribute is greater than max attribute(Year is 10000 should be valid)"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["time"],
+ testData: [
+ {conditions: {max: "", value: "12:00:00"}, expected: false, name: "[target] The max attribute is not set"},
+ {conditions: {max: "12:00:00", value: ""}, expected: false, name: "[target] Value is empty string"},
+ {conditions: {max: "12.00.00", value: "12:00:01"}, expected: false, name: "[target] The max attribute is an invalid time string"},
+ {conditions: {max: "12:00:00", value: "12.00.01"}, expected: false, name: "[target] The value attribute is an invalid time string"},
+ {conditions: {max: "23:59:59", value: "24:00:00"}, expected: false, name: "[target] The value attribute is an invalid time string(hour is greater than 23)"},
+ {conditions: {max: "23:59:59", value: "23:60:00"}, expected: false, name: "[target] The value attribute is an invalid time string(minute is greater than 59)"},
+ {conditions: {max: "23:59:59", value: "23:59:60"}, expected: false, name: "[target] The value attribute is an invalid time string(second is greater than 59)"},
+ {conditions: {max: "13:00:00", value: "12:00:00"}, expected: false, name: "[target] The max attribute is greater than value attribute"},
+ {conditions: {max: "12:00:00", value: "13"}, expected: false, name: "[target] The time missing second and minute parts is invalid"},
+ {conditions: {max: "12:00:00", value: "12:00:02"}, expected: true, name: "[target] The value attribute is greater than max attribute"},
+ {conditions: {max: "12:00:00.1", value: "12:00:00.2"}, expected: true, name: "[target] The value is greater than max(with millisecond in 1 digit)"},
+ {conditions: {max: "12:00:00.01", value: "12:00:00.02"}, expected: true, name: "[target] The value is greater than max(with millisecond in 2 digit)"},
+ {conditions: {max: "12:00:00.001", value: "12:00:00.002"}, expected: true, name: "[target] The value is greater than max(with millisecond in 3 digit)"},
+ {conditions: {max: "12:00:00", value: "12:01"}, expected: true, name: "[target] The time missing second part is valid"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["number"],
+ testData: [
+ {conditions: {max: "", value: "10"}, expected: false, name: "[target] The max attribute is not set"},
+ {conditions: {max: "5", value: ""}, expected: false, name: "[target] Value is empty string"},
+ {conditions: {max: "5", value: "4"}, expected: false, name: "[target] The max is greater than value(integer)"},
+ {conditions: {max: "-5.5", value: "-5.6"}, expected: false, name: "[target] The max is greater than value(floating number)"},
+ {conditions: {max: "-0", value: "0"}, expected: false, name: "[target] The max equals to value"},
+ {conditions: {max: "5", value: "1abc"}, expected: false, name: "[target] The value is not a number"},
+ {conditions: {max: "5", value: "6"}, expected: true, name: "[target] The value is greater than max(integer)"},
+ {conditions: {max: "-5.5", value: "-5.4"}, expected: true, name: "[target] The value is greater than max(floating number)"},
+ {conditions: {max: "-5e-1", value: "5e+2"}, expected: true, name: "[target] The value is greater than max(scientific notation)"}
+ ]
+ }
+ ];
+
+ validator.run_test(testElements, "rangeOverflow");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-validity-rangeUnderflow.html b/tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-validity-rangeUnderflow.html
new file mode 100644
index 00000000000..567345c3e28
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-validity-rangeUnderflow.html
@@ -0,0 +1,113 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>The constraint validation API Test: element.validity.rangeUnderflow</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-validitystate-rangeunderflow">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-constraint-validation-api">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/validator.js"></script>
+<div id="log"></div>
+<script>
+ var testElements = [
+ {
+ tag: "input",
+ types: ["datetime"],
+ testData: [
+ {conditions: {min: "", value: "2000-01-01T12:00:00Z"}, expected: false, name: "[target] The min attribute is not set"},
+ {conditions: {min: "2000-01-01T12:00:00Z", value: ""}, expected: false, name: "[target] Value is empty string"},
+ {conditions: {min: "2001-01-01 12:00:00Z", value: "2000-01-01T12:00:00Z"}, expected: false, name: "[target] The min attribute is an invalid global date time string"},
+ {conditions: {min: "2000-01-01T11:00:00Z", value: "2000-01-01T12:00:00Z"}, expected: false, name: "[target] The min attribute is less than the value attribute"},
+ {conditions: {min: "2001-01-01T23:59:59Z", value: "2000-01-01T24:00:00Z"}, expected: false, name: "[target] The value is an invalid datetime string(hour is greater than 23)"},
+ {conditions: {min: "1980-01-01T12:00Z", value: "79-01-01T12:00Z"}, expected: false, name: "[target] The value is an invalid date time string(year is two digits)"},
+ {conditions: {min: "2000-01-01T13:00:00Z", value: "2000-01-01T12:00:00Z"}, expected: true, name: "[target] The value is less than min"},
+ {conditions: {min: "2000-01-01T12:00:00.2Z", value: "2000-01-01T12:00:00.1Z"}, expected: true, name: "[target] The value is less than min(with millisecond in 1 digit)"},
+ {conditions: {min: "2000-01-01T12:00:00.02Z", value: "2000-01-01T12:00:00.01Z"}, expected: true, name: "[target] The value is less than min(with millisecond in 2 digits)"},
+ {conditions: {min: "2000-01-01T12:00:00.002Z", value: "2000-01-01T12:00:00.001Z"}, expected: true, name: "[target] The value is less than min(with millisecond in 3 digits)"},
+ {conditions: {min: "10000-01-01T12:00:00Z", value: "2000-01-01T12:00:00Z"}, expected: true, name: "[target] The value is less than min(Year is 10000 should be valid)"},
+ {conditions: {min: "8593-01-01T02:09+02:09", value: "8592-01-01T02:09+02:09"}, expected: true, name: "[target] The value is greater than max(with timezone)"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["date"],
+ testData: [
+ {conditions: {min: "", value: "2000-01-01"}, expected: false, name: "[target] The min attribute is not set"},
+ {conditions: {min: "2000-01-01", value: ""}, expected: false, name: "[target] Value is empty string"},
+ {conditions: {min: "2001/01/01", value: "2000-01-01"}, expected: false, name: "[target] The min attribute is an invalid date"},
+ {conditions: {min: "2000-02-02", value: "2000-1-1"}, expected: false, name: "[target] The value attribute is an invalid date"},
+ {conditions: {min: "988-01-01", value: "987-01-01"}, expected: false, name: "[target] The value is an invalid date(year is three digits)"},
+ {conditions: {min: "2001-01-01", value: "2000-13-01"}, expected: false, name: "[target] The value is an invalid date(month is less than 12)"},
+ {conditions: {min: "2001-01-01", value: "2000-02-30"}, expected: false, name: "[target] The value is an invalid date(date is less than 29 for Feb)"},
+ {conditions: {min: "2000-01-01", value: "2000-12-01"}, expected: false, name: "[target] The min attribute is less than value attribute"},
+ {conditions: {min: "2000-12-01", value: "2000-01-01"}, expected: true, name: "[target] The value attribute is less than min attribute"},
+ {conditions: {min: "10000-01-01", value: "9999-01-01"}, expected: true, name: "[target] The value attribute is less than min attribute(Year is 10000 should be valid)"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["month"],
+ testData: [
+ {conditions: {min: "", value: "2000-01"}, expected: false, name: "[target] The min attribute is not set"},
+ {conditions: {min: "2000-01", value: ""}, expected: false, name: "[target] Value is empty string"},
+ {conditions: {min: "2001/01", value: "2000-02"}, expected: false, name: "[target] The min attribute is an invalid month string"},
+ {conditions: {min: "2000-02", value: "2000-1"}, expected: false, name: "[target] The value attribute is an invalid month string"},
+ {conditions: {min: "988-01", value: "987-01"}, expected: false, name: "[target] The value is an invalid month string(year is three digits)"},
+ {conditions: {min: "2001-01", value: "2000-13"}, expected: false, name: "[target] The value is an invalid month string(month is less than 12)"},
+ {conditions: {min: "2000-01", value: "2000-12"}, expected: false, name: "[target] The min attribute is less than value attribute"},
+ {conditions: {min: "2001-01", value: "2000-12"}, expected: true, name: "[target] The value attribute is less than min attribute"},
+ {conditions: {min: "10000-01", value: "2000-01"}, expected: true, name: "[target] The value attribute is less than min attribute(Year is 10000 should be valid)"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["week"],
+ testData: [
+ {conditions: {min: "", value: "2000-W01"}, expected: false, name: "[target] The min attribute is not set"},
+ {conditions: {min: "2000-W01", value: ""}, expected: false, name: "[target] Value is empty string"},
+ {conditions: {min: "2001/W02", value: "2000-W01"}, expected: false, name: "[target] The min attribute is an invalid week string"},
+ {conditions: {min: "2001-W02", value: "2000-W1"}, expected: false, name: "[target] The value attribute is an invalid week string"},
+ {conditions: {min: "2001-W02", value: "2000-w01"}, expected: false, name: "[target] The value attribute is an invalid week string(w is in lowercase)"},
+ {conditions: {min: "988-W01", value: "987-W01"}, expected: false, name: "[target] The value is an invalid week string(year is three digits)"},
+ {conditions: {min: "2001-W01", value: "2000-W57"}, expected: false, name: "[target] The value is an invalid week string(week is too greater)"},
+ {conditions: {min: "2000-W01", value: "2000-W12"}, expected: false, name: "[target] The min attribute is less than value attribute"},
+ {conditions: {min: "2000-W12", value: "2000-W01"}, expected: true, name: "[target] The value attribute is less than min attribute"},
+ {conditions: {min: "10000-W01", value: "2000-W01"}, expected: true, name: "[target] The value attribute is less than min attribute(Year is 10000 should be valid)"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["time"],
+ testData: [
+ {conditions: {min: "", value: "12:00:00"}, expected: false, name: "[target] The min attribute is not set"},
+ {conditions: {min: "12:00:00", value: ""}, expected: false, name: "[target] Value is empty string"},
+ {conditions: {min: "12.00.01", value: "12:00:00"}, expected: false, name: "[target] The min attribute is an invalid time string"},
+ {conditions: {min: "12:00:01", value: "12.00.00"}, expected: false, name: "[target] The value attribute is an invalid time string"},
+ {conditions: {min: "12:00:00", value: "13:00:00"}, expected: false, name: "[target] The min attribute is less than value attribute"},
+ {conditions: {min: "13:00:00", value: "12"}, expected: false, name: "[target] The time missing second and minute parts is invalid"},
+ {conditions: {min: "12:00:02", value: "12:00:00"}, expected: true, name: "[target] The value attribute is less than min attribute"},
+ {conditions: {min: "12:00:00.2", value: "12:00:00.1"}, expected: true, name: "[target] The value is less than min(with millisecond in 1 digit)"},
+ {conditions: {min: "12:00:00.02", value: "12:00:00.01"}, expected: true, name: "[target] The value is less than min(with millisecond in 2 digit)"},
+ {conditions: {min: "12:00:00.002", value: "12:00:00.001"}, expected: true, name: "[target] The value is less than min(with millisecond in 3 digit)"},
+ {conditions: {min: "12:00:00", value: "11:59"}, expected: true, name: "[target] The time missing second part is valid"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["number"],
+ testData: [
+ {conditions: {min: "", value: "10"}, expected: false, name: "[target] The min attribute is not set"},
+ {conditions: {min: "5", value: ""}, expected: false, name: "[target] Value is empty string"},
+ {conditions: {min: "4", value: "5"}, expected: false, name: "[target] The min is less than value(integer)"},
+ {conditions: {min: "-5.6", value: "-5.5"}, expected: false, name: "[target] The min is less than value(floating number)"},
+ {conditions: {min: "0", value: "-0"}, expected: false, name: "[target] The min equals to value"},
+ {conditions: {min: "5", value: "6abc"}, expected: false, name: "[target] The value is not a number"},
+ {conditions: {min: "6", value: "5"}, expected: true, name: "[target] The value is less than min(integer)"},
+ {conditions: {min: "-5.4", value: "-5.5"}, expected: true, name: "[target] The value is less than min(floating number)"},
+ {conditions: {min: "5e+2", value: "-5e-1"}, expected: true, name: "[target] The value is less than min(scientific notation)"}
+ ]
+ }
+ ];
+
+ validator.run_test(testElements, "rangeUnderflow");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-validity-stepMismatch.html b/tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-validity-stepMismatch.html
new file mode 100644
index 00000000000..bb0e9239ac8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-validity-stepMismatch.html
@@ -0,0 +1,87 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>The constraint validation API Test: element.validity.patternMismatch</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-validitystate-stepmismatch">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-constraint-validation-api">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/validator.js"></script>
+<div id="log"></div>
+<script>
+ //set step = 2 * default step * factor
+ var testElements = [
+ {
+ tag: "input",
+ types: ["datetime"],
+ testData: [
+ {conditions: {step: "", value: "2000-01-01T12:00:00Z"}, expected: false, name: "[target] The step attribute is not set"},
+ {conditions: {step: 2 * 60 * 1000, value: ""}, expected: false, name: "[target] The value attibute is empty string"},
+ {conditions: {step: 2 * 60 * 1000, value: "2000-01-01T12:58Z"}, expected: false, name: "[target] The value must match the step"},
+ {conditions: {step: 2 * 60 * 1000, value: "2000-01-01T12:59Z"}, expected: true, name: "[target] The value must mismatch the step"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["date"],
+ testData: [
+ {conditions: {step: "", value: "2000-01-01"}, expected: false, name: "[target] The step attribute is not set"},
+ {conditions: {step: 2 * 1 * 86400000, value: ""}, expected: false, name: "[target] The value attibute is empty string"},
+ {conditions: {step: 2 * 1 * 86400000, value: "1970-01-02"}, expected: false, name: "[target] The value must match the step"},
+ {conditions: {step: 2 * 1 * 86400000, value: "1970-01-03"}, expected: true, name: "[target] The value must mismatch the step"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["month"],
+ testData: [
+ {conditions: {step: "", value: "2000-01"}, expected: false, name: "[target] The step attribute is not set"},
+ {conditions: {step: 2 * 1 * 1, value: ""}, expected: false, name: "[target] The value attibute is empty string"},
+ {conditions: {step: 2 * 1 * 1, value: "1970-03"}, expected: false, name: "[target] The value must match the step"},
+ {conditions: {step: 2 * 1 * 1, value: "1970-04"}, expected: true, name: "[target] The value must mismatch the step"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["week"],
+ testData: [
+ {conditions: {step: "", value: "1970-W01"}, expected: false, name: "[target] The step attribute is not set"},
+ {conditions: {step: 2 * 1 * 604800000, value: ""}, expected: false, name: "[target] The value attibute is empty string"},
+ {conditions: {step: 2 * 1 * 604800000, value: "1970-W03"}, expected: false, name: "[target] The value must match the step"},
+ {conditions: {step: 2 * 1 * 604800000, value: "1970-W04"}, expected: true, name: "[target] The value must mismatch the step"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["time"],
+ testData: [
+ {conditions: {step: "", value: "12:00:00"}, expected: false, name: "[target] The step attribute is not set"},
+ {conditions: {step: 2 * 60 * 1000, value: ""}, expected: false, name: "[target] The value attibute is empty string"},
+ {conditions: {step: 2 * 60 * 1000, value: "12:02:00"}, expected: false, name: "[target] The value must match the step"},
+ {conditions: {step: 2 * 60 * 1000, value: "12:03:00"}, expected: true, name: "[target] The value must mismatch the step"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["datetime-local"],
+ testData: [
+ {conditions: {step: "", value: "2000-01-01T12:00:00"}, expected: false, name: "[target] The step attribute is not set"},
+ {conditions: {step: 2 * 60 * 1000, value: ""}, expected: false, name: "[target] The value attibute is empty string"},
+ {conditions: {step: 2 * 60 * 1000, value: "1970-01-01T12:02:00"}, expected: false, name: "[target] The value must match the step"},
+ {conditions: {step: 2 * 60 * 1000, value: "1970-01-01T12:03:00"}, expected: true, name: "[target] The value must mismatch the step"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["number"],
+ testData: [
+ {conditions: {step: "", value: "1"}, expected: false, name: "[target] The step attribute is not set"},
+ {conditions: {step: 2 * 1 * 1, value: ""}, expected: false, name: "[target] The value attibute is empty string"},
+ {conditions: {step: 2 * 1 * 1, value: "2"}, expected: false, name: "[target] The value must match the step"},
+ {conditions: {step: 2 * 1 * 1, value: "3"}, expected: true, name: "[target] The value must mismatch the step"}
+ ]
+ }
+ ];
+
+ validator.run_test(testElements, "stepMismatch");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-validity-tooLong.html b/tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-validity-tooLong.html
new file mode 100644
index 00000000000..79d0cbe17c0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-validity-tooLong.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>The constraint validation API Test: element.validity.tooLong</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-validitystate-toolong">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-constraint-validation-api">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/validator.js"></script>
+<div id="log"></div>
+<script>
+ var testElements = [
+ {
+ tag: "input",
+ types: ["text", "search", "tel", "url", "email", "password"],
+ testData: [ // Non-dirty value
+ {conditions: {maxLength: "", value: "abc"}, expected: false, name: "[target] Non-dirty value - maxlength is not set"},
+ {conditions: {maxLength: "4", value: ""}, expected: false, name: "[target] Non-dirty value - value is empty string"},
+ {conditions: {maxLength: "4", value: "abc"}, expected: false, name: "[target] Non-dirty value - length of value is less than maxlength"},
+ {conditions: {maxLength: "4", value: "abcd"}, expected: false, name: "[target] Non-dirty value - length of value equals to maxlength"},
+ {conditions: {maxLength: "4", value: "abcde"}, expected: false, name: "[target] Non-dirty value - length of value is greater than maxlength"},
+ //Dirty value
+ {conditions: {maxLength: "4", value: "abc"}, expected: false, name: "[target] Dirty value - value is less than maxlength", dirty: true},
+ {conditions: {maxLength: "4", value: "\u0041\u0041\u0041"}, expected: false, name: "[target] Dirty value - length of value(AAA) in unicode is less than maxlength", dirty: true},
+ {conditions: {maxLength: "4", value: "abcd"}, expected: false, name: "[target] Dirty value - value equals to maxlength", dirty: true},
+ {conditions: {maxLength: "4", value: "abcde"}, expected: true, name: "[target] Dirty value - length of value is greater than maxlength", dirty: true}
+ ]
+ },
+ {
+ tag: "textarea",
+ types: [],
+ testData: [
+ {conditions: {maxLength: "", value: "abc"}, expected: false, name: "[target] Non-dirty value - maxlength is not set"},
+ {conditions: {maxLength: "4", value: ""}, expected: false, name: "[target] Non-dirty value - value is empty string"},
+ {conditions: {maxLength: "4", value: "abc"}, expected: false, name: "[target] Non-dirty value - length of value is less than maxlength"},
+ {conditions: {maxLength: "4", value: "abcd"}, expected: false, name: "[target] Non-dirty value - length of value equals to maxlength"},
+ {conditions: {maxLength: "4", value: "abcde"}, expected: false, name: "[target] Non-dirty value - length of value is greater than maxlength"},
+ //Dirty value
+ {conditions: {maxLength: "4", value: "abc"}, expected: false, name: "[target] Dirty value - value is less than maxlength", dirty: true},
+ {conditions: {maxLength: "4", value: "\u000D\u000A"}, expected: false, name: "[target] Dirty value - length of value(LF, CRLF) in unicode is less than maxlength", dirty: true},
+ {conditions: {maxLength: "4", value: "abcd"}, expected: false, name: "[target] Dirty value - length of value equals to maxlength", dirty: true},
+ {conditions: {maxLength: "4", value: "abcde"}, expected: true, name: "[target] Dirty value - length of value is greater than maxlength", dirty: true}
+ ]
+ }
+ ];
+
+ validator.run_test (testElements, "tooLong");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-validity-tooShort.html b/tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-validity-tooShort.html
new file mode 100644
index 00000000000..dfc44746239
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-validity-tooShort.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>The constraint validation API Test: element.validity.tooShort</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#suffering-from-being-too-short">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-constraint-validation-api">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/validator.js"></script>
+<div id="log"></div>
+<script>
+ var testElements = [
+ {
+ tag: "input",
+ types: ["text", "search", "tel", "url", "email", "password"],
+ testData: [
+ // Non-dirty value
+ {conditions: {minLength: "", value: "abc"}, expected: false, name: "[target] Non-dirty value - minLength is not set"},
+ {conditions: {minLength: "4", value: ""}, expected: false, name: "[target] Non-dirty value - value is empty string"},
+ {conditions: {minLength: "4", value: "abcde"}, expected: false, name: "[target] Non-dirty value - length of value is greater than minLength"},
+ {conditions: {minLength: "4", value: "abcd"}, expected: false, name: "[target] Non-dirty value - length of value equals to minLength"},
+ {conditions: {minLength: "4", value: "abc"}, expected: false, name: "[target] Non-dirty value - length of value is less than minLength"},
+ //Dirty value
+ {conditions: {minLength: "4", value: "abcde"}, expected: false, name: "[target] Dirty value - value is greater than minLength", dirty: true},
+ {conditions: {minLength: "4", value: "\u0041\u0041\u0041\u0041\u0041"}, expected: false, name: "[target] Dirty value - length of value(AAAAA) in unicode is greater than minLength", dirty: true},
+ {conditions: {minLength: "4", value: "abcd"}, expected: false, name: "[target] Dirty value - value equals to minLength", dirty: true},
+ {conditions: {minLength: "4", value: "abc"}, expected: true, name: "[target] Dirty value - length of value is less than minLength", dirty: true}
+ ]
+ },
+ {
+ tag: "textarea",
+ types: [],
+ testData: [
+ // Non-dirty value
+ {conditions: {minLength: "", value: "abc"}, expected: false, name: "[target] Non-dirty value - minLength is no set"},
+ {conditions: {minLength: "4", value: ""}, expected: false, name: "[target] Non-dirty value - value is empty string"},
+ {conditions: {minLength: "4", value: "abcde"}, expected: false, name: "[target] Non-dirty value - length of value is greater than minLength"},
+ {conditions: {minLength: "4", value: "abcd"}, expected: false, name: "[target] Non-dirty value - length of value equals to minLength"},
+ {conditions: {minLength: "4", value: "abc"}, expected: false, name: "[target] Non-dirty value - length of length of value is greater than minLength"},
+ //Dirty value
+ {conditions: {minLength: "4", value: "abcde"}, expected: false, name: "[target] Dirty value - value is less than minLength", dirty: true},
+ {conditions: {minLength: "4", value: "\u000D\u000A\u000D\u000A\u000D\u000A"}, expected: false, name: "[target] Dirty value - length of value(LF, CRLF) in unicode is less than minLength", dirty: true},
+ {conditions: {minLength: "4", value: "abcd"}, expected: false, name: "[target] Dirty value - length of value equals to minLength", dirty: true},
+ {conditions: {minLength: "4", value: "abc"}, expected: true, name: "[target] Dirty value - length of value is greater than minLength", dirty: true}
+ ]
+ }
+ ];
+
+ validator.run_test (testElements, "tooShort");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-validity-typeMismatch.html b/tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-validity-typeMismatch.html
new file mode 100644
index 00000000000..40444277cda
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-validity-typeMismatch.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>The constraint validation API Test: element.validity.typeMismatch</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-validitystate-typemismatch">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-constraint-validation-api">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/validator.js"></script>
+<div id="log"></div>
+<script>
+ var testElements = [
+ {
+ tag: "input",
+ types: ["email"],
+ testData: [
+ // multiple is false
+ {conditions: {multiple: false, value: ""}, expected: false, name: "[target] The value is empty"},
+ {conditions: {multiple: false, value: "test@example.com"}, expected: false, name: "[target] The value is a valid email address"},
+ {conditions: {multiple: false, value: "\u000A\u000D\u0020\u0009 test@example.com \u000A\u000D\u0020\u0009"}, expected: false, name: "[target] The value is a valid email address with some white spaces."},
+ {conditions: {multiple: false, value: "abc"}, expected: true, name: "[target] The value is not an email address"},
+ {conditions: {multiple: false, value: "test1@example.com,test2@example.com"}, expected: true, name: "[target] The value contains multiple email addresses"},
+ //multiple is true
+ {conditions: {multiple: true, value: "test1@example.com,test2@example.com"}, expected: false, name: "[target] The value is valid email addresses"},
+ {conditions: {multiple: true, value: "test1@example.com;test2@example.com"}, expected: true, name: "[target] The value contains invalid separator"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["url"],
+ testData: [
+ {conditions: {multiple: false, value: ""}, expected: false, name: "[target] The value is empty"},
+ {conditions: {multiple: false, value: "http://www.example.com"}, expected: false, name: "[target] The value is a valid url"},
+ {conditions: {multiple: false, value: "\u000A\u000D\u0020\u0009 http://www.example.com \u000A\u000D\u0020\u0009 "}, expected: false, name: "[target] The value is a valid url with some white spaces."},
+ {conditions: {multiple: false, value: "abc"}, expected: true, name: "[target] The value is not an url"}
+ ]
+ }
+ ];
+
+ validator.run_test(testElements, "typeMismatch");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-validity-valid.html b/tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-validity-valid.html
new file mode 100644
index 00000000000..3f66646083d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-validity-valid.html
@@ -0,0 +1,133 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>The constraint validation API Test: element.validity.valid</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-validitystate-valid">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-constraint-validation-api">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/validator.js"></script>
+<div id="log"></div>
+<script>
+ var testElements = [
+ {
+ tag: "input",
+ types: ["text", "search", "tel", "password"],
+ testData: [
+ {conditions: {maxLength: "4", value: "abcdef"}, expected: false, name: "[target] validity.valid must be false if validity.tooLong is true", dirty: true},
+ {conditions: {pattern: "[A-Z]", value: "abc"}, expected: false, name: "[target] validity.valid must be false if validity.patternMismatch is true"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] validity.valid must be false if validity.valueMissing is true"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["url"],
+ testData: [
+ {conditions: {maxLength: "20", value: "http://www.example.com"}, expected: false, name: "[target] validity.valid must be false if validity.tooLong is true", dirty: true},
+ {conditions: {pattern: "http://www.example.com", value: "http://www.example.net"}, expected: false, name: "[target] validity.valid must be false if validity.patternMismatch is true"},
+ {conditions: {value: "abc"}, expected: false, name: "[target] validity.valid must be false if validity.typeMismatch is true"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] validity.valid must be false if validity.valueMissing is true"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["email"],
+ testData: [
+ {conditions: {maxLength: "10", value: "test@example.com"}, expected: false, name: "[target] validity.valid must be false if validity.tooLong is true", dirty: true},
+ {conditions: {pattern: "test@example.com", value: "test@example.net"}, expected: false, name: "[target] validity.valid must be false if validity.patternMismatch is true"},
+ {conditions: {value: "abc"}, expected: false, name: "[target] validity.valid must be false if validity.typeMismatch is true"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] validity.valid must be false if validity.valueMissing is true"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["datetime"],
+ testData: [
+ {conditions: {max: "2000-01-01T12:00:00Z", value: "2001-01-01T12:00:00Z"}, expected: false, name: "[target] validity.valid must be false if validity.rangeOverflow is true"},
+ {conditions: {min: "2001-01-01T12:00:00Z", value: "2000-01-01T12:00:00Z"}, expected: false, name: "[target] validity.valid must be false if validity.rangeUnderflow is true"},
+ {conditions: {step: 2 * 60 * 1000, value: "2001-01-01T12:03:00Z"}, expected: false, name: "[target] validity.valid must be false if validity.stepMismatch is true"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] validity.valid must be false if validity.valueMissing is true"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["date"],
+ testData: [
+ {conditions: {max: "2000-01-01", value: "2001-01-01"}, expected: false, name: "[target] validity.valid must be false if validity.rangeOverflow is true"},
+ {conditions: {min: "2001-01-01", value: "2000-01-01"}, expected: false, name: "[target] validity.valid must be false if validity.rangeUnderflow is true"},
+ {conditions: {step: 2 * 1 * 86400000, value: "2000-01-03"}, expected: false, name: "[target] validity.valid must be false if validity.stepMismatch is true"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] validity.valid must be false if validity.valueMissing is true"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["month"],
+ testData: [
+ {conditions: {max: "2000-01", value: "2001-01"}, expected: false, name: "[target] validity.valid must be false if validity.rangeOverflow is true"},
+ {conditions: {min: "2001-01", value: "2000-01"}, expected: false, name: "[target] validity.valid must be false if validity.rangeUnderflow is true"},
+ {conditions: {step: 2 * 1 * 1, value: "2001-03"}, expected: false, name: "[target] validity.valid must be false if validity.stepMismatch is true"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] validity.valid must be false if validity.valueMissing is true"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["week"],
+ testData: [
+ {conditions: {max: "2000-W01", value: "2001-W01"}, expected: false, name: "[target] validity.valid must be false if validity.rangeOverflow is true"},
+ {conditions: {min: "2001-W01", value: "2000-W01"}, expected: false, name: "[target] validity.valid must be false if validity.rangeUnderflow is true"},
+ {conditions: {step: 2 * 1 * 604800000, value: "2001-W03"}, expected: false, name: "[target] validity.valid must be false if validity.stepMismatch is true"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] validity.valid must be false if validity.valueMissing is true"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["time"],
+ testData: [
+ {conditions: {max: "12:00:00", value: "13:00:00"}, expected: false, name: "[target] validity.valid must be false if validity.rangeOverflow is true"},
+ {conditions: {min: "12:00:00", value: "11:00:00"}, expected: false, name: "[target] validity.valid must be false if validity.rangeUnderflow is true"},
+ {conditions: {step: 2 * 60 * 1000, value: "12:03:00"}, expected: false, name: "[target] validity.valid must be false if validity.stepMismatch is true"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] validity.valid must be false if validity.valueMissing is true"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["number"],
+ testData: [
+ {conditions: {max: "5", value: "6"}, expected: false, name: "[target] validity.valid must be false if validity.rangeOverflow is true"},
+ {conditions: {min: "5", value: "4"}, expected: false, name: "[target] validity.valid must be false if validity.rangeUnderflow is true"},
+ {conditions: {step: 2 * 1 * 1, value: "3"}, expected: false, name: "[target] validity.valid must be false if validity.stepMismatch is true"},
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] validity.valid must be false if validity.valueMissing is true"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["checkbox", "radio"],
+ testData: [
+ {conditions: {required: true, checked: false, name: "test1"}, expected: false, name: "[target] validity.valid must be false if validity.valueMissing is true"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["file"],
+ testData: [
+ {conditions: {required: true, files: null}, expected: false, name: "[target] validity.valid must be false if validity.valueMissing is true"}
+ ]
+ },
+ {
+ tag: "select",
+ types: [],
+ testData: [
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] validity.valid must be false if validity.valueMissing is true"}
+ ]
+ },
+ {
+ tag: "textarea",
+ types: [],
+ testData: [
+ {conditions: {required: true, value: ""}, expected: false, name: "[target] validity.valid must be false if validity.valueMissing is true"}
+ ]
+ }
+ ];
+
+ validator.run_test(testElements, "isValid");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-validity-valueMissing.html b/tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-validity-valueMissing.html
new file mode 100644
index 00000000000..4554c95a3b4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-validity-valueMissing.html
@@ -0,0 +1,160 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>The constraint validation API Test: element.validity.valueMissing</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-validitystate-valuemissing">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-constraint-validation-api">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/validator.js"></script>
+<div id="log"></div>
+<script>
+ var testElements = [
+ {
+ tag: "input",
+ types: ["text", "search", "tel", "url", "email", "password"],
+ testData: [
+ {conditions: {required: false, value: ""}, expected: false, name: "[target] The required attribute is not set"},
+ {conditions: {required: true, value: "abc"}, expected: false, name: "[target] The value is not empty and required is true"},
+ {conditions: {required: true, value: ""}, expected: true, name: "[target] The value is empty and required is true"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["datetime"],
+ testData: [
+ {conditions: {required: false, value: ""}, expected: false, name: "[target] The required attribute is not set"},
+ {conditions: {required: true, value: "2000-12-10T12:00:00Z"}, expected: false, name: "[target] Valid global date and time string(2000-12-10T12:00:00Z)"},
+ {conditions: {required: true, value: "2000-12-10 12:00Z"}, expected: false, name: "[target] Valid global date and time string(2000-12-10 12:00Z)"},
+ {conditions: {required: true, value: "1979-10-14T12:00:00.001-04:00"}, expected: false, name: "[target] Valid global date and time string(1979-10-14T12:00:00.001-04:00)"},
+ {conditions: {required: true, value: "8592-01-01T02:09+02:09"}, expected: false, name: "[target] Valid global date and time string(8592-01-01T02:09+02:09)"},
+ {conditions: {required: true, value: 1234567}, expected: true, name: "[target] The value attribute is a number(1234567)"},
+ {conditions: {required: true, value: new Date()}, expected: true, name: "[target] The value attribute is a Date object"},
+ {conditions: {required: true, value: "1979-10-99 99:99Z"}, expected: true, name: "[target] Invalid global date and time string(1979-10-99 99:99Z)"},
+ {conditions: {required: true, value: "1979-10-14 12:00:00"}, expected: true, name: "[target] Invalid global date and time string(1979-10-14 12:00:00)"},
+ {conditions: {required: true, value: "2001-12-21 12:00Z"}, expected: true, name: "[target] Invalid global date and time string(2001-12-21 12:00Z)-two white space"},
+ {conditions: {required: true, value: "abc"}, expected: true, name: "[target] the value attribute is a string(abc)"},
+ {conditions: {required: true, value: ""}, expected: true, name: "[target] The value attribute is empty string"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["date"],
+ testData: [
+ {conditions: {required: false, value: ""}, expected: false, name: "[target] The required attribute is not set"},
+ {conditions: {required: true, value: "2000-12-10"}, expected: false, name: "[target] Valid date string(2000-12-10)"},
+ {conditions: {required: true, value: "9999-01-01"}, expected: false, name: "[target] Valid date string(9999-01-01)"},
+ {conditions: {required: true, value: 1234567}, expected: true, name: "[target] The value attribute is a number(1234567)"},
+ {conditions: {required: true, value: new Date()}, expected: true, name: "[target] The value attribute is a Date object"},
+ {conditions: {required: true, value: "9999-99-99"}, expected: true, name: "[target] Invalid date string(9999-99-99)"},
+ {conditions: {required: true, value: "37/01/01"}, expected: true, name: "[target] Invalid date string(37-01-01)"},
+ {conditions: {required: true, value: "2000/01/01"}, expected: true, name: "[target] Invalid date string(2000/01/01)"},
+ {conditions: {required: true, value: ""}, expected: true, name: "[target] The value attribute is empty string"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["month"],
+ testData: [
+ {conditions: {required: false, value: ""}, expected: false, name: "[target] The required attribute is not set"},
+ {conditions: {required: true, value: "2000-12"}, expected: false, name: "[target] Valid month string(2000-12)"},
+ {conditions: {required: true, value: "9999-01"}, expected: false, name: "[target] Valid month string(9999-01)"},
+ {conditions: {required: true, value: 1234567}, expected: true, name: "[target] The value attribute is a number(1234567)"},
+ {conditions: {required: true, value: new Date()}, expected: true, name: "[target] The value attribute is a Date object"},
+ {conditions: {required: true, value: "2000-99"}, expected: true, name: "[target] Invalid month string(2000-99)"},
+ {conditions: {required: true, value: "37-01"}, expected: true, name: "[target] Invalid month string(37-01)"},
+ {conditions: {required: true, value: "2000/01"}, expected: true, name: "[target] Invalid month string(2000/01)"},
+ {conditions: {required: true, value: ""}, expected: true, name: "[target] The value attribute is empty string"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["week"],
+ testData: [
+ {conditions: {required: false, value: ""}, expected: false, name: "[target] The required attribute is not set"},
+ {conditions: {required: true, value: "2000-W12"}, expected: false, name: "[target] Valid week string(2000-W12)"},
+ {conditions: {required: true, value: "9999-W01"}, expected: false, name: "[target] Valid week string(9999-W01)"},
+ {conditions: {required: true, value: 1234567}, expected: true, name: "[target] The value attribute is a number(1234567)"},
+ {conditions: {required: true, value: new Date()}, expected: true, name: "[target] The value attribute is a Date object"},
+ {conditions: {required: true, value: "2000-W99"}, expected: true, name: "[target] Invalid week string(2000-W99)"},
+ {conditions: {required: true, value: "2000-W00"}, expected: true, name: "[target] invalid week string(2000-W00)"},
+ {conditions: {required: true, value: "2000-w01"}, expected: true, name: "[target] invalid week string(2000-w01)"},
+ {conditions: {required: true, value: ""}, expected: true, name: "[target] The value attribute is empty string"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["time"],
+ testData: [
+ {conditions: {required: false, value: ""}, expected: false, name: "[target] The required attribute is not set"},
+ {conditions: {required: true, value: "12:00:00"}, expected: false, name: "[target] Validtime string(12:00:00)"},
+ {conditions: {required: true, value: "12:00"}, expected: false, name: "[target] Validtime string(12:00)"},
+ {conditions: {required: true, value: "12:00:00.001"}, expected: false, name: "[target] Valid time string(12:00:60.001)"},
+ {conditions: {required: true, value: "12:00:00.01"}, expected: false, name: "[target] Valid time string(12:00:60.01)"},
+ {conditions: {required: true, value: "12:00:00.1"}, expected: false, name: "[target] Valid time string(12:00:60.1)"},
+ {conditions: {required: true, value: 1234567}, expected: true, name: "[target] The value attribute is a number(1234567)"},
+ {conditions: {required: true, value: new Date()}, expected: true, name: "[target] The value attribute is a time object"},
+ {conditions: {required: true, value: "25:00:00"}, expected: true, name: "[target] Invalid time string(25:00:00)"},
+ {conditions: {required: true, value: "12:60:00"}, expected: true, name: "[target] Invalid time string(12:60:00)"},
+ {conditions: {required: true, value: "12:00:60"}, expected: true, name: "[target] Invalid time string(12:00:60)"},
+ {conditions: {required: true, value: "12:00:00:001"}, expected: true, name: "[target] Invalid time string(12:00:00:001)"},
+ {conditions: {required: true, value: ""}, expected: true, name: "[target] The value attribute is empty string"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["number"],
+ testData: [
+ {conditions: {required: false, value: ""}, expected: false, name: "[target] The required attribute is not set"},
+ {conditions: {required: true, value: "123"}, expected: false, name: "[target] Value is an integer with a leading symbol '+'"},
+ {conditions: {required: true, value: "-123.45"}, expected: false, name: "[target] Value is a number with a '-' symbol"},
+ {conditions: {required: true, value: "123.01e-10"}, expected: false, name: "[target] Value is a number in scientific notation form(e is in lowercase)"},
+ {conditions: {required: true, value: "123.01E+10"}, expected: false, name: "[target] Value is a number in scientific notation form(E is in uppercase)"},
+ {conditions: {required: true, value: "-0"}, expected: false, name: "[target] Value is -0"},
+ {conditions: {required: true, value: " 123 "}, expected: true, name: "[target] Value is a number with some white spaces"},
+ {conditions: {required: true, value: Math.pow(2, 1024)}, expected: true, name: "[target] Value is Math.pow(2, 1024)"},
+ {conditions: {required: true, value: Math.pow(-2, 1024)}, expected: true, name: "[target] Value is Math.pow(-2, 1024)"},
+ {conditions: {required: true, value: "abc"}, expected: true, name: "[target] Value is a string that can not be coverted to a number"},
+ {conditions: {required: true, value: ""}, expected: true, name: "[target] The value attribute is empty string"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["checkbox", "radio"],
+ testData: [
+ {conditions: {required: false, checked: false, name: "test1"}, expected: false, name: "[target] The required attribute is not set"},
+ {conditions: {required: true, checked: true, name: "test1"}, expected: false, name: "[target] The checked attribute is true"},
+ {conditions: {required: true, checked: false, name: "test1"}, expected: true, name: "[target] The checked attribute is false"}
+ ]
+ },
+ {
+ tag: "input",
+ types: ["file"],
+ testData: [
+ {conditions: {required: false, files: null}, expected: false, name: "[target] The required attribute is not set"},
+ {conditions: {required: true, files: null}, expected: true, name: "[target] The Files attribute is null"}
+ //ToDo: Add a case to test the files is not null
+ ]
+ },
+ {
+ tag: "select",
+ types: [],
+ testData: [
+ {conditions: {required: false, value: ""}, expected: false, name: "[target] The required attribute is not set"},
+ {conditions: {required: true, value: 1}, expected: false, name: "[target] Selected the option with value equals to 1"},
+ {conditions: {required: true, value: ""}, expected: true, name: "[target] Selected the option with value equals to empty"}
+ ]
+ },
+ {
+ tag: "textarea",
+ types: [],
+ testData: [
+ {conditions: {required: false, value: ""}, expected: false, name: "[target] The required attribute is not set"},
+ {conditions: {required: true, value: "abc"}, expected: false, name: "[target] The value is not empty"},
+ {conditions: {required: true, value: ""}, expected: true , name: "[target] The value is empty"}
+ ]
+ }
+ ];
+
+ validator.run_test(testElements, "valueMissing");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-willValidate.html b/tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-willValidate.html
new file mode 100644
index 00000000000..671d269ef58
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/constraints/form-validation-willValidate.html
@@ -0,0 +1,90 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>The constraint validation API Test: element.willValidate</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-cva-willvalidate">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-constraint-validation-api">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/validator.js"></script>
+<div id="log"></div>
+<script>
+ var testElements = [
+ //input in hidden, button and reset status must be barred from the constraint validation
+ {
+ tag: "input",
+ types: ["hidden", "button", "reset"],
+ testData: [{conditions: {}, expected: false, name: "[target] Must be barred from the constraint validation"}]
+ },
+ //button in button and reset status must be barred from the constraint validation
+ {
+ tag: "button",
+ types: ["button", "reset"],
+ testData: [{conditions: {}, expected: false, name: "[target] Must be barred from the constraint validation"}]
+ },
+ //FIELDSET, OUTPUT elements should not be barred from the constraint validation
+ {
+ tag: "fieldset",
+ types: [],
+ testData: [{conditions: {}, expected: true, name: "[target] Must not be barred from the constraint validation"}]
+ },
+ {
+ tag: "output",
+ types: [],
+ testData: [{conditions: {}, expected: true, name: "[target] Must not be barred from the constraint validation"}]
+ },
+ //OBJECT, KEYGEN, elements must be barred from the constraint validation
+ {
+ tag: "object",
+ types: [],
+ testData: [{conditions: {}, expected: false, name: "[target] Must be barred from the constraint validation"}]
+ },
+ {
+ tag: "keygen",
+ types: [],
+ testData: [{conditions: {}, expected: false, name: "[target] Must be barred from the constraint validation"}]
+ },
+ //If an element is disabled, it is barred from constraint validation.
+ //The willValidate attribute must be true if an element is mutable
+ //If the readonly attribute is specified on an INPUT element, the element is barred from constraint validation.
+ {
+ tag: "input",
+ types: ["text", "search", "tel", "url", "email", "password", "datetime", "date", "month", "week", "time", "color", "file", "submit"],
+ testData: [
+ {conditions: {disabled: true}, expected: false, name: "[target] Must be barred from the constraint validation if it is disabled"},
+ {conditions: {disabled: false, readOnly: false}, expected: true, name: "[target] The willValidate attribute must be true if an elment is mutable"},
+ {conditions: {readOnly: true}, expected: false, name: "[target] Must be barred from the constraint validation if it is readonly"},
+ {conditions: {disabled: false, readOnly: false}, expected: false, name: "[target] The willValidate attribute must be false if it has a datalist ancestor", ancestor: "datalist"},
+ ]
+ },
+ {
+ tag: "button",
+ types: ["submit"],
+ testData: [
+ {conditions: {disabled: true}, expected: false, name: "[target] Must be barred from the constraint validation"},
+ {conditions: {disabled: false}, expected: true, name: "[target] The willValidate attribute must be true if an elment is mutable"},
+ {conditions: {disabled: false}, expected: false, name: "[target] The willValidate attribute must be false if it has a datalist ancestor", ancestor: "datalist"}
+ ]
+ },
+ {
+ tag: "select",
+ types: [],
+ testData: [
+ {conditions: {disabled: true}, expected: false, name: "[target] Must be barred from the constraint validation"},
+ {conditions: {disabled: false}, expected: true, name: "[target] The willValidate attribute must be true if an elment is mutable"},
+ {conditions: {disabled: false}, expected: false, name: "[target] The willValidate attribute must be false if it has a datalist ancestor", ancestor: "datalist"}
+ ]
+ },
+ {
+ tag: "textarea",
+ types: [],
+ testData: [,
+ {conditions: {disabled: true}, expected: false, name: "[target] Must be barred from the constraint validation"},
+ {conditions: {disabled: false}, expected: true, name: "[target] The willValidate attribute must be true if an elment is mutable"},
+ {conditions: {disabled: false}, expected: false, name: "[target] The willValidate attribute must be false if it has a datalist ancestor", ancestor: "datalist"}
+ ]
+ }
+ ];
+
+ validator.run_test(testElements, "willValidate");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/constraints/inputwillvalidate.html b/tests/wpt/web-platform-tests/html/semantics/forms/constraints/inputwillvalidate.html
new file mode 100644
index 00000000000..909fd889bbb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/constraints/inputwillvalidate.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html><head>
+ <title>willValidate property on the input element</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="content-type">
+ <meta content="willValidate property on the input element" name="description">
+ <link href="https://html.spec.whatwg.org/multipage/#dom-cva-willvalidate" rel="help">
+ </head>
+ <body>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ <div id="log"></div>
+
+ <form action="http://www.example.com/" style="display : none">
+ <input required="" type="text">
+ <input disabled="" type="text">
+ </form>
+
+ <script type="text/javascript">
+
+ test(function() {assert_true(document.getElementsByTagName("input")[0].willValidate)}, "willValidate property returns true when required attribute exists");
+ test(function() {assert_false(document.getElementsByTagName("input")[1].willValidate)}, "willValidate property returns false when disabled attribute exists");
+
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/constraints/support/validator.js b/tests/wpt/web-platform-tests/html/semantics/forms/constraints/support/validator.js
new file mode 100644
index 00000000000..12a88c1fc6e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/constraints/support/validator.js
@@ -0,0 +1,369 @@
+var validator = {
+ test_tooLong: function(ctl, data) {
+ var self = this;
+ test(function () {
+ self.pre_check(ctl, "tooLong");
+ self.set_conditions(ctl, data.conditions);
+ if (data.dirty)
+ self.set_dirty(ctl);
+
+ if (data.expected)
+ assert_true(ctl.validity.tooLong, "The validity.tooLong should be true.");
+ else
+ assert_false(ctl.validity.tooLong, "The validity.tooLong should be false.");
+ }, data.name);
+ },
+
+ test_tooShort: function(ctl, data) {
+ var self = this;
+ test(function () {
+ self.pre_check(ctl, "tooShort");
+ self.set_conditions(ctl, data.conditions);
+ if (data.dirty)
+ self.set_dirty(ctl);
+
+ if (data.expected)
+ assert_true(ctl.validity.tooShort, "The validity.tooShort should be true.");
+ else
+ assert_false(ctl.validity.tooShort, "The validity.tooShort should be false.");
+ }, data.name);
+ },
+
+ test_patternMismatch: function(ctl, data) {
+ var self = this;
+ test(function () {
+ self.pre_check(ctl, "patternMismatch");
+ self.set_conditions(ctl, data.conditions);
+
+ if (data.expected)
+ assert_true(ctl.validity.patternMismatch, "The validity.patternMismatch should be true.");
+ else
+ assert_false(ctl.validity.patternMismatch, "The validity.patternMismatch should be false.");
+ }, data.name);
+ },
+
+ test_valueMissing: function(ctl, data) {
+ var self = this;
+ test(function () {
+ self.pre_check(ctl, "valueMissing");
+ self.set_conditions(ctl, data.conditions);
+ if (data.expected)
+ assert_true(ctl.validity.valueMissing, "The validity.valueMissing should be true.");
+ else
+ assert_false(ctl.validity.valueMissing, "The validity.valueMissing should be false.");
+ }, data.name);
+ },
+
+ test_typeMismatch: function(ctl, data) {
+ var self = this;
+ test(function () {
+ self.pre_check(ctl, "typeMismatch");
+ self.set_conditions(ctl, data.conditions);
+
+ if (data.expected)
+ assert_true(ctl.validity.typeMismatch, "The validity.typeMismatch should be true.");
+ else
+ assert_false(ctl.validity.typeMismatch, "The validity.typeMismatch should be false.");
+ }, data.name);
+ },
+
+ test_rangeOverflow: function(ctl, data) {
+ var self = this;
+ test(function () {
+ self.pre_check(ctl, "rangeOverflow");
+ self.set_conditions(ctl, data.conditions);
+
+ if (data.expected)
+ assert_true(ctl.validity.rangeOverflow, "The validity.rangeOverflow should be true.");
+ else
+ assert_false(ctl.validity.rangeOverflow, "The validity.rangeOverflow should be false.");
+ }, data.name);
+ },
+
+ test_rangeUnderflow: function(ctl, data) {
+ var self = this;
+ test(function () {
+ self.pre_check(ctl, "rangeUnderflow");
+ self.set_conditions(ctl, data.conditions);
+ if (data.expected)
+ assert_true(ctl.validity.rangeUnderflow, "The validity.rangeUnderflow should be true.");
+ else
+ assert_false(ctl.validity.rangeUnderflow, "The validity.rangeUnderflow should be false.");
+ }, data.name);
+ },
+
+ test_stepMismatch: function(ctl, data) {
+ var self = this;
+ test(function () {
+ self.pre_check(ctl, "stepMismatch");
+ self.set_conditions(ctl, data.conditions);
+
+ if (data.expected)
+ assert_true(ctl.validity.stepMismatch, "The validity.stepMismatch should be true.");
+ else
+ assert_false(ctl.validity.stepMismatch, "The validity.stepMismatch should be false.");
+ }, data.name);
+ },
+
+ test_badInput: function(ctl, data) {
+ var self = this;
+ test(function () {
+ self.pre_check(ctl, "badInput");
+ self.set_conditions(ctl, data.conditions);
+
+ if (data.expected)
+ assert_true(ctl.validity.badInput, "The validity.badInput should be true.");
+ else
+ assert_false(ctl.validity.badInput, "The validity.badInput should be false.");
+ }, data.name);
+ },
+
+ test_customError: function(ctl, data) {
+ var self = this;
+ test(function () {
+ self.pre_check(ctl, "customError");
+ ctl.setCustomValidity(data.conditions.message);
+
+ if (data.expected) {
+ assert_true(ctl.validity.customError, "The validity.customError attribute should be true.");
+ assert_equals(ctl.validationMessage, data.conditions.message,
+ "The validationMessage attribute should be '" + data.conditions.message + "'.");
+ } else {
+ assert_false(ctl.validity.customError, "The validity.customError attribute should be false.");
+ assert_equals(ctl.validationMessage, "", "The validationMessage attribute must be empty.");
+ }
+ }, data.name);
+ },
+
+ test_isValid: function (ctl, data) {
+ var self = this;
+ test(function () {
+ self.set_conditions(ctl, data.conditions);
+ if (data.dirty)
+ self.set_dirty(ctl);
+
+ if (data.expected)
+ assert_true(ctl.validity.valid, "The validity.valid should be true.");
+ else
+ assert_false(ctl.validity.valid, "The validity.valid should be false.");
+ }, data.name);
+ },
+
+ test_willValidate: function(ctl, data) {
+ var self = this;
+ test(function () {
+ self.pre_check(ctl, "willValidate");
+ self.set_conditions(ctl, data.conditions);
+ if (data.ancestor) {
+ var dl = document.createElement("datalist");
+ dl.appendChild(ctl);
+ }
+
+ if (data.expected)
+ assert_true(ctl.willValidate, "The willValidate attribute should be true.");
+ else
+ assert_false(ctl.willValidate, "The willValidate attribute should be false.");
+ }, data.name);
+ },
+
+ test_checkValidity: function (ctl, data) {
+ var self = this;
+ test(function () {
+ var eventFired = false;
+ self.pre_check(ctl, "checkValidity");
+ self.set_conditions(ctl, data.conditions);
+ if (data.dirty)
+ self.set_dirty(ctl);
+
+ on_event(ctl, "invalid", function(e){
+ assert_equals(e.type, "invalid", "The invalid event should be fired.");
+ eventFired = true;
+ });
+
+ if (data.expected) {
+ assert_true(ctl.checkValidity(), "The checkValidity method should be true.");
+ assert_false(eventFired, "The invalid event should not be fired.");
+ } else {
+ assert_false(ctl.checkValidity(), "The checkValidity method should be false.");
+ assert_true(eventFired, "The invalid event should be fired.");
+ }
+ }, data.name);
+
+ test(function () {
+ var fm = document.createElement("form");
+ var ctl2 = ctl.cloneNode(true);
+
+ self.pre_check(ctl, "checkValidity");
+ self.set_conditions(ctl2, data.conditions);
+ fm.appendChild(ctl2);
+ document.body.appendChild(fm);
+ if (data.dirty)
+ self.set_dirty(ctl2);
+
+ var result = fm.checkValidity();
+ document.body.removeChild(fm);
+
+ if (data.expected)
+ assert_true(result, "The checkValidity method of the element's form owner should return true.");
+ else
+ assert_false(result, "The checkValidity method of the element's form owner should return false.");
+ }, data.name + " (in a form)");
+ },
+
+ test_reportValidity: function (ctl, data) {
+ var self = this;
+ test(function () {
+ var eventFired = false;
+
+ self.pre_check(ctl, "reportValidity");
+ self.set_conditions(ctl, data.conditions);
+ if (data.dirty)
+ self.set_dirty(ctl);
+
+ on_event(ctl, "invalid", function(e){
+ assert_equals(e.type, "invalid", "The invalid event should be fired.");
+ eventFired = true;
+ });
+
+ if (data.expected) {
+ assert_true(ctl.reportValidity(), "The reportValidity method should be true.");
+ assert_false(eventFired, "The invalid event should not be fired.");
+ } else {
+ assert_true(eventFired, "The invalid event should be fired.");
+ assert_false(ctl.reportValidity(), "The reportValidity method should be false.");
+ }
+ }, data.name);
+
+ test(function () {
+ var fm = document.createElement("form");
+ var ctl2 = ctl.cloneNode(true);
+
+ self.pre_check(ctl, "reportValidity");
+ self.set_conditions(ctl2, data.conditions);
+ fm.appendChild(ctl2);
+ document.body.appendChild(fm);
+ if (data.dirty)
+ self.set_dirty(ctl2);
+
+ var result = fm.reportValidity();
+ document.body.removeChild(fm);
+
+ if (data.expected)
+ assert_true(result, "The reportValidity method of the element's form owner should return true.");
+ else
+ assert_false(result, "The reportValidity method of the element's form owner should return false.");
+ }, data.name + " (in a form)");
+ },
+
+ test_support_type: function (ctl, typ, testName) {
+ test(function () {
+ assert_equals(ctl.type, typ, "The " + typ + " type should be supported.");
+ }, testName);
+ },
+
+ set_conditions: function (ctl, obj) {
+ ["required", "pattern", "step", "max", "min", "maxlength",
+ "value", "multiple", "checked", "selected"].forEach(function(item) {
+ ctl.removeAttribute(item);
+ });
+ for (var attr in obj) {
+ if (obj[attr] || obj[attr] === "")
+ ctl[attr] = obj[attr];
+ }
+ },
+
+ set_dirty: function(ctl) {
+ document.disgnMode = "on";
+ ctl.focus();
+ var old_value = ctl.value;
+ ctl.value = "a";
+ ctl.value = old_value;
+ ctl.setSelectionRange(ctl.value.length, ctl.value.length);
+ document.execCommand("Delete");
+ document.disgnMode = "off";
+ },
+
+ pre_check: function(ctl, item) {
+ switch (item) {
+ case "willValidate":
+ assert_true(item in ctl, "The " + item + " attribute doesn't exist.");
+ break;
+ case "checkValidity":
+ case "reportValidity":
+ assert_true(item in ctl, "The " + item + " method doesn't exist.");
+ break;
+ case "tooLong":
+ case "tooShort":
+ case "patternMismatch":
+ case "typeMismatch":
+ case "stepMismatch":
+ case "rangeOverflow":
+ case "rangeUnderflow":
+ case "valueMissing":
+ case "badInput":
+ case "valid":
+ assert_true("validity" in ctl, "The validity attribute doesn't exist.");
+ assert_true(item in ctl.validity, "The " + item + " attribute doesn't exist.");
+ break;
+ case "customError":
+ assert_true("validity" in ctl, "The validity attribute doesn't exist.");
+ assert_true("setCustomValidity" in ctl, "The validity attribute doesn't exist.");
+ assert_true("validationMessage" in ctl, "The validity attribute doesn't exist.");
+ assert_true(item in ctl.validity, "The " + item + " attribute doesn't exist.");
+ break;
+ }
+ },
+
+ run_test: function (testee, method) {
+ var testMethod = "test_" + method;
+ if (typeof this[testMethod] !== "function") {
+ return false;
+ }
+
+ var ele = null,
+ prefix = "";
+
+ for (var i = 0; i < testee.length; i++) {
+ if (testee[i].types.length > 0) {
+ for (var typ in testee[i].types) {
+ ele = document.createElement(testee[i].tag);
+ document.body.appendChild(ele);
+ try {
+ ele.type = testee[i].types[typ];
+ } catch (e) {
+ //Do nothing, avoid the runtime error breaking the test
+ }
+
+ prefix = "[" + testee[i].tag.toUpperCase() + " in " + testee[i].types[typ].toUpperCase() + " status] ";
+ if (ele.type != testee[i].types[typ]) {
+ this.test_support_type(
+ ele,
+ testee[i].types[typ],
+ prefix + "The " + testee[i].types[typ] + " type must be supported."
+ );
+ continue;
+ }
+
+ for (var j = 0; j < testee[i].testData.length; j++) {
+ testee[i].testData[j].name = testee[i].testData[j].name.replace(/\[.*\]\s/g, prefix);
+ this[testMethod](ele, testee[i].testData[j]);
+ }
+ }
+ } else {
+ ele = document.createElement(testee[i].tag);
+ document.body.appendChild(ele);
+ prefix = "[" + testee[i].tag + "] ";
+
+ if (testElements[i].tag === "select") {
+ ele.add(new Option("test1", ""));
+ ele.add(new Option("test2", 1));
+ }
+
+ for (var item in testee[i].testData) {
+ testee[i].testData[item].name = testee[i].testData[item].name.replace("[target]", prefix);
+ this[testMethod](ele, testee[i].testData[item]);
+ }
+ }
+ }
+ }
+}
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/form-control-infrastructure/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/forms/form-control-infrastructure/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/form-control-infrastructure/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/form-control-infrastructure/contains.json b/tests/wpt/web-platform-tests/html/semantics/forms/form-control-infrastructure/contains.json
new file mode 100644
index 00000000000..754a6901d23
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/form-control-infrastructure/contains.json
@@ -0,0 +1,14 @@
+[
+ {
+ "id": "a-form-control-s-value",
+ "original_id": "a-form-control's-value"
+ },
+ {
+ "id": "mutability",
+ "original_id": "mutability"
+ },
+ {
+ "id": "association-of-controls-and-forms",
+ "original_id": "association-of-controls-and-forms"
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/form-control-infrastructure/form.html b/tests/wpt/web-platform-tests/html/semantics/forms/form-control-infrastructure/form.html
new file mode 100644
index 00000000000..6563c27458a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/form-control-infrastructure/form.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTMLInputElement#form</title>
+<link rel="author" title="Ms2ger" href="mailto:Ms2ger@gmail.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<form id="form">
+<p><button id="button">button</button>
+<p><fieldset id="fieldset">fieldset</fieldset>
+<p><input id="input">
+<p><keygen id="keygen">
+<p><label id="label">label</label>
+<p><object id="object">object</object>
+<p><output id="output">output</output>
+<p><select id="select"><option>select</option></select>
+<p><textarea id="textarea">textarea</textarea>
+</form>
+<script>
+var form;
+setup(function() {
+ form = document.getElementById("form");
+ if (!form) {
+ throw new TypeError("Didn't find form");
+ }
+});
+
+var reassociateableElements = [
+ "button",
+ "fieldset",
+ "input",
+ "keygen",
+ "label",
+ "object",
+ "output",
+ "select",
+ "textarea",
+];
+
+reassociateableElements.forEach(function(localName) {
+ test(function() {
+ var button = document.getElementById(localName);
+ assert_equals(button.form, form);
+ }, localName + ".form");
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/form-submission-0/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/forms/form-submission-0/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/form-submission-0/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/form-submission-0/contains.json b/tests/wpt/web-platform-tests/html/semantics/forms/form-submission-0/contains.json
new file mode 100644
index 00000000000..f9d0d63bf68
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/form-submission-0/contains.json
@@ -0,0 +1,30 @@
+[
+ {
+ "id": "introduction-2",
+ "original_id": "introduction-2"
+ },
+ {
+ "id": "implicit-submission",
+ "original_id": "implicit-submission"
+ },
+ {
+ "id": "form-submission-algorithm",
+ "original_id": "form-submission-algorithm"
+ },
+ {
+ "id": "constructing-form-data-set",
+ "original_id": "constructing-form-data-set"
+ },
+ {
+ "id": "url-encoded-form-data",
+ "original_id": "url-encoded-form-data"
+ },
+ {
+ "id": "multipart-form-data",
+ "original_id": "multipart-form-data"
+ },
+ {
+ "id": "plain-text-form-data",
+ "original_id": "plain-text-form-data"
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/introduction-1/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/forms/introduction-1/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/introduction-1/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/introduction-1/contains.json b/tests/wpt/web-platform-tests/html/semantics/forms/introduction-1/contains.json
new file mode 100644
index 00000000000..12a86681384
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/introduction-1/contains.json
@@ -0,0 +1,34 @@
+[
+ {
+ "id": "writing-a-form-s-user-interface",
+ "original_id": "writing-a-form's-user-interface"
+ },
+ {
+ "id": "implementing-the-server-side-processing-for-a-form",
+ "original_id": "implementing-the-server-side-processing-for-a-form"
+ },
+ {
+ "id": "configuring-a-form-to-communicate-with-a-server",
+ "original_id": "configuring-a-form-to-communicate-with-a-server"
+ },
+ {
+ "id": "client-side-form-validation",
+ "original_id": "client-side-form-validation"
+ },
+ {
+ "id": "enabling-client-side-automatic-filling-of-form-controls",
+ "original_id": "enabling-client-side-automatic-filling-of-form-controls"
+ },
+ {
+ "id": "improving-the-user-experience-on-mobile-devices",
+ "original_id": "improving-the-user-experience-on-mobile-devices"
+ },
+ {
+ "id": "the-difference-between-the-field-type-the-autofill-field-name-and-the-input-modality",
+ "original_id": "the-difference-between-the-field-type,-the-autofill-field-name,-and-the-input-modality"
+ },
+ {
+ "id": "input-author-notes",
+ "original_id": "input-author-notes"
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/resetting-a-form/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/forms/resetting-a-form/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/resetting-a-form/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/resetting-a-form/reset-form.html b/tests/wpt/web-platform-tests/html/semantics/forms/resetting-a-form/reset-form.html
new file mode 100644
index 00000000000..b74b52c46e4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/resetting-a-form/reset-form.html
@@ -0,0 +1,105 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: Resetting a form</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#concept-form-reset">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#category-reset">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<form name="fm1" style="display:none">
+ <input value="abc" id="ipt1" />
+ <input id="ipt2" />
+ <input type="radio" id="rd1" checked="checked" />
+ <input type="radio" id="rd2"/>
+ <input type="checkbox" id="cb1" checked="checked" />
+ <input type="checkbox" id="cb2" />
+ <textarea id="ta">abc</textarea>
+ <!--<keygen id="kg"></keygen>-->
+ <output id="opt">5</output>
+ <select id="slt1">
+ <option value="1">ITEM1</option>
+ <option value="2">ITEM2</option>
+ </select>
+ <select id="slt2">
+ <option value="1">ITEM1</option>
+ <option value="2" selected>ITEM2</option>
+ </select>
+ <select id="slt3" multiple>
+ <option value="1">ITEM1</option>
+ <option value="2" selected>ITEM2</option>
+ <option value="3" selected>ITEM3</option>
+ </select>
+ <button id="rst1" type="reset">Reset1</button>
+ <input id="rst2" type="reset" value="Reset2" />
+</form>
+<script>
+
+runTest(function() {
+ document.forms.fm1.reset();
+}, "by calling the reset() method");
+
+runTest(function() {
+ document.getElementById("rst1").click();
+}, "by clicking the button in reset status");
+
+runTest(function() {
+ document.getElementById("rst2").click();
+}, "by clicking the input in reset status");
+
+function setPreconditions (arg) {
+ document.getElementById("ipt1").value = "123";
+ document.getElementById("ipt2").value = "123";
+ document.getElementById("rd1").checked = false;
+ document.getElementById("rd2").checked = true;
+ document.getElementById("cb1").checked = false;
+ document.getElementById("cb2").checked = true;
+ document.getElementById("ta").value = "123";
+ document.getElementById("opt").textContent = "abc";
+ document.getElementById("slt1").value = "2";
+ document.getElementById("slt2").value = "1";
+ document.getElementById("slt3").options[0].selected = true;
+ document.getElementById("slt3").options[1].selected = false;
+ document.getElementById("slt3").options[2].selected = false;
+
+ assert_equals(document.getElementById("ipt1").value, "123", "Precondition 1");
+ assert_equals(document.getElementById("ipt2").value, "123", "Precondition 2");
+ assert_false(document.getElementById("rd1").checked, "Precondition 3");
+ assert_true(document.getElementById("rd2").checked, "Precondition 4");
+ assert_false(document.getElementById("cb1").checked, "Precondition 5");
+ assert_true(document.getElementById("cb2").checked, "Precondition 6");
+ assert_equals(document.getElementById("ta").value, "123", "Precondition 17");
+ assert_equals(document.getElementById("opt").textContent, "abc", "Precondition 8");
+ assert_true(document.getElementById("slt1").options[1].selected, "Precondition 9");
+ assert_true(document.getElementById("slt2").options[0].selected, "Precondition 10");
+ assert_true(document.getElementById("slt3").options[0].selected, "Precondition 11");
+ assert_false(document.getElementById("slt3").options[1].selected, "Precondition 12");
+ assert_false(document.getElementById("slt3").options[2].selected, "Precondition 13");
+}
+
+function runTest(reset, description) {
+ test(function() {
+ setPreconditions("Setting preconditions for resetting " + description);
+ reset();
+ assert_equals(document.getElementById("ipt1").value, "abc", "The value of the input element in text status should be 'abc'.");
+ assert_equals(document.getElementById("ipt2").value, "", "The value of the input element in text status should be empty string.");
+ assert_true(document.getElementById("rd1").checked, "The checked attribute of the input element in radio should be true.");
+ assert_false(document.getElementById("rd2").checked, "The checked attribute of the input element in radio should be false.");
+ assert_true(document.getElementById("cb1").checked, "The checked attribute of the input element in checkbox should be true.");
+ assert_false(document.getElementById("cb2").checked, "The checked attribute of the input element in checkbox should be false.");
+ assert_equals(document.getElementById("ta").value, document.getElementById("ta").textContent, "The value attribute of the textarea element should be reset.");
+ assert_equals(document.getElementById("ta").value, "abc", "The value attribute of the textarea element should be 'abc'.");
+ assert_equals(document.getElementById("opt").textContent, document.getElementById("opt").defaultValue, "The textContent of the output element should be reset.");
+ assert_equals(document.getElementById("opt").textContent, "abc", "The textContent of the output element should be 'abc'.");
+ assert_true(document.getElementById("slt1").options[0].selected, "The first option in the select element should be selected.");
+ assert_false(document.getElementById("slt1").options[1].selected, "The second option in the select element should not be selected.");
+ assert_false(document.getElementById("slt2").options[0].selected, "The first option in the select element should not be selected.");
+ assert_true(document.getElementById("slt2").options[1].selected, "The second option in the select element should be selected.");
+ assert_false(document.getElementById("slt3").options[0].selected, "The first option in the select element with multiple attribute should not be selected.");
+ assert_true(document.getElementById("slt3").options[1].selected, "The second option in the select element with multiple attribute should be selected.");
+ assert_true(document.getElementById("slt3").options[2].selected, "The third option in the select element with multiple attribute should be selected.");
+ //TODO: The keygen reset algorithm
+ }, "Resetting the form " + description);
+}
+
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/original-id.json b/tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/original-id.json
new file mode 100644
index 00000000000..d9fe4358563
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/original-id.json
@@ -0,0 +1 @@
+{"original_id":"textFieldSelection"} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/select-event.html b/tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/select-event.html
new file mode 100644
index 00000000000..92a12d12eb3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/select-event.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>text field selection: select()</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#textFieldSelection">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<textarea>foobar</textarea>
+<script>
+ var input_types = ["text", "search", "tel", "url", "password"],
+ t1 = async_test("select() on textarea queues select event"),
+ q1 = false;
+
+ input_types.forEach(function(type) {
+ var input = document.createElement("input"),
+ t = async_test("select() on input type " + type + " queues select event"),
+ q = false;
+ t.step(function() {
+ input.type = type;
+ input.value = "foobar";
+ document.body.appendChild(input);
+ input.onselect = t.step_func_done(function(e) {
+ assert_true(q, "event should be queued");
+ assert_true(e.isTrusted, "event is trusted");
+ assert_true(e.bubbles, "event bubbles");
+ assert_false(e.cancelable, "event is not cancelable");
+ });
+ input.select();
+ q=true;
+ });
+ });
+
+ document.querySelector("textarea").onselect = t1.step_func_done(function(e) {
+ assert_true(q1, "event should be queued");
+ assert_true(e.isTrusted, "event is trusted");
+ assert_true(e.bubbles, "event bubbles");
+ assert_false(e.cancelable, "event is not cancelable");
+ });
+
+ t1.step(function() {
+ document.querySelector("textarea").select();
+ q1=true;
+ });
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/selection-not-application-textarea.html b/tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/selection-not-application-textarea.html
new file mode 100644
index 00000000000..c17ad32325e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/selection-not-application-textarea.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>text field selection (textarea)</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#textFieldSelection">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+ test(function() {
+ var el = document.createElement("textarea");
+ assert_equals(el.selectionStart, 0);
+ assert_equals(el.selectionEnd, 0);
+ el.selectionStart = 1;
+ el.selectionEnd = 1;
+ el.selectionDirection = "forward";
+ el.setRangeText("foobar");
+ el.setSelectionRange(0, 1);
+ }, "text field selection for the input textarea");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/selection-not-application.html b/tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/selection-not-application.html
new file mode 100644
index 00000000000..4ecaa4acbb6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/selection-not-application.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>text field selection</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#textFieldSelection">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+ var types = ["hidden", "email", "datetime", "date", "month", "week", "time", "number", "range", "color", "checkbox", "radio", "file", "submit", "image", "reset", "button"]; //types for which the API doesn't apply
+ var types2 = ["text", "search", "tel", "url", "password"]; //types for which the API applies
+
+ types.forEach(function(type){
+ test(function(){
+ var el = document.createElement("input");
+ el.type = type;
+ assert_throws("InvalidStateError", function(){
+ el.selectionStart;
+ });
+ assert_throws("InvalidStateError", function(){
+ el.selectionEnd;
+ });
+ assert_throws("InvalidStateError", function(){
+ el.selectionDirection;
+ });
+ assert_throws("InvalidStateError", function(){
+ el.setRangeText("foobar");
+ });
+ assert_throws("InvalidStateError", function(){
+ el.setSelectionRange(0, 1);
+ });
+ }, "text field selection for the input " + type);
+ });
+
+ types2.forEach(function(type) {
+ test(function() {
+ var el = document.createElement("input");
+ el.type = type;
+ assert_equals(el.selectionStart, 0);
+ assert_equals(el.selectionEnd, 0);
+ el.selectionStart = 1;
+ el.selectionEnd = 1;
+ el.selectionDirection = "forward";
+ el.setRangeText("foobar");
+ el.setSelectionRange(0, 1);
+ }, "text field selection for the input " + type);
+ });
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/selection.html b/tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/selection.html
new file mode 100644
index 00000000000..d89ca04c466
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/selection.html
@@ -0,0 +1,144 @@
+<!DOCTYPE HTML>
+<title>test if select() API returns correct attributes</title>
+<meta charset="UTF-8">
+<link rel="author" title="Koji Tashiro" href="mailto:koji.tashiro@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/multipage/association-of-controls-and-forms.html#textFieldSelection">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<div id="log"></div>
+
+<script>
+ var body = document.getElementsByTagName("body").item(0);
+ var dirs = ['forward', 'backward', 'none'];
+ var sampleText = "0123456789";
+
+ var createInputElement = function(value) {
+ var el = document.createElement("input");
+ el.type = "text";
+ el.value = value;
+ body.appendChild(el);
+ return el;
+ };
+
+ var createTextareaElement = function(value) {
+ var el = document.createElement("textarea");
+ el.value = value;
+ body.appendChild(el);
+ return el;
+ };
+
+
+ test(function() {
+ var text = 'a';
+ for (var i=0; i<255; i++) {
+ var el = createInputElement(text);
+ el.select();
+ var selectionText = el.value.substring(el.selectionStart, el.selectionEnd);
+ assert_equals(selectionText, text, "Selection text mismatched");
+ el.parentNode.removeChild(el);
+ text += 'a';
+ }
+ }, "test if selection text is correct for input");
+
+
+ test(function() {
+ var text = 'a';
+ for (var i=0; i<255; i++) {
+ var el = createTextareaElement(text);
+ el.select();
+ var selectionText = el.value.substring(el.selectionStart, el.selectionEnd);
+ assert_equals(selectionText, text, "Selection text mismatched");
+ el.parentNode.removeChild(el);
+ text += 'a';
+ }
+ }, "test if selection text is correct for textarea");
+
+
+ test(function() {
+ var text = 'あ';
+ for (var i=0; i<255; i++) {
+ var el = createInputElement(text);
+ el.select();
+ var selectionText = el.value.substring(el.selectionStart, el.selectionEnd);
+ assert_equals(selectionText, text, "Selection text mismatched");
+ el.parentNode.removeChild(el);
+ text += 'あ';
+ }
+ }, "test if non-ascii selection text is correct for input");
+
+
+ test(function() {
+ var text = 'あ';
+ for (var i=0; i<255; i++) {
+ var el = createTextareaElement(text);
+ el.select();
+ var selectionText = el.value.substring(el.selectionStart, el.selectionEnd);
+ assert_equals(selectionText, text, "Selection text mismatched");
+ el.parentNode.removeChild(el);
+ text += 'あ';
+ }
+ }, "test if non-ascii selection text is correct for textarea");
+
+
+ test(function() {
+ var el = createInputElement(sampleText);
+ // If there is no selection, then it must return the offset(in logical order)
+ // to the character that immediately follows the text entry cursor.
+ assert_equals(el.selectionStart, el.value.length, "SelectionStart offset without selection");
+ el.select();
+ assert_equals(el.selectionStart, 0, "SelectionStart offset");
+ el.parentNode.removeChild(el);
+ }, "test SelectionStart offset for input");
+
+
+ test(function() {
+ var el = createTextareaElement(sampleText);
+ // If there is no selection, then it must return the offset(in logical order)
+ // to the character that immediately follows the text entry cursor.
+ assert_equals(el.selectionStart, el.value.length, "SelectionStart offset without selection");
+ el.select();
+ assert_equals(el.selectionStart, 0, "SelectionStart offset");
+ el.parentNode.removeChild(el);
+ }, "test SelectionStart offset for textarea");
+
+
+ test(function() {
+ var el = createInputElement(sampleText);
+ // If there is no selection, then it must return the offset(in logical order)
+ // to the character that immediately follows the text entry cursor.
+ assert_equals(el.selectionEnd, el.value.length, "SelectionEnd offset without selection");
+ el.select();
+ assert_equals(el.selectionEnd, el.value.length, "SelectionEnd offset");
+ el.parentNode.removeChild(el);
+ }, "test SelectionEnd offset for input");
+
+
+ test(function() {
+ var el = createTextareaElement(sampleText);
+ // If there is no selection, then it must return the offset(in logical order)
+ // to the character that immediately follows the text entry cursor.
+ assert_equals(el.selectionEnd, el.value.length, "SelectionEnd offset without selection");
+ el.select();
+ assert_equals(el.selectionEnd, el.value.length, "SelectionEnd offset");
+ el.parentNode.removeChild(el);
+ }, "test SelectionEnd offset for textarea");
+
+
+ test(function() {
+ var el = createInputElement(sampleText);
+ assert_in_array(el.selectionDirection, dirs, "SelectionDirection");
+ el.select();
+ assert_in_array(el.selectionDirection, dirs, "SelectionDirection");
+ el.parentNode.removeChild(el);
+ }, "test SelectionDirection for input");
+
+
+ test(function() {
+ var el = createInputElement(sampleText);
+ assert_in_array(el.selectionDirection, dirs, "SelectionDirection");
+ el.select();
+ assert_in_array(el.selectionDirection, dirs, "SelectionDirection");
+ el.parentNode.removeChild(el);
+ }, "test SelectionDirection for textarea");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/textfieldselection-setRangeText.html b/tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/textfieldselection-setRangeText.html
new file mode 100644
index 00000000000..126aad9cf4e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/textfieldselection-setRangeText.html
@@ -0,0 +1,120 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>text field selection: setRangeText</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#textFieldSelection">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+ #display_none {display:none;}
+</style>
+<div id="log"></div>
+<input type=text id=text value="foobar">
+<input type=search id=search value="foobar">
+<input type=tel id=tel value="foobar">
+<input type=url id=url value="foobar">
+<input type=password id=password value="foobar">
+<input id=display_none value="foobar">
+<textarea id=textarea>foobar</textarea>
+<script>
+ var input = document.createElement("input");
+ input.id = "input_not_in_doc";
+ input.value = "foobar";
+
+ var elements = [
+ document.getElementById("text"),
+ document.getElementById("search"),
+ document.getElementById("tel"),
+ document.getElementById("url"),
+ document.getElementById("password"),
+ document.getElementById("display_none"),
+ document.getElementById("textarea"),
+ input,
+ ]
+
+ elements.forEach(function(element) {
+ var t = async_test(element.id + " setRangeText fires a select event"),
+ q = false;
+
+ test(function() {
+ element.value = "foobar";
+ element.selectionStart = 0;
+ element.selectionEnd = 3;
+ assert_equals(element.selectionStart, 0);
+ assert_equals(element.selectionEnd, 3);
+ element.setRangeText("foobar2");
+ assert_equals(element.value, "foobar2bar");
+ assert_equals(element.selectionStart, 0);
+ assert_equals(element.selectionEnd, 7);
+ element.setRangeText("foobar3", 7, 10);
+ assert_equals(element.value, "foobar2foobar3");
+ }, element.id + " setRangeText with only one argument replaces the value between selectionStart and selectionEnd, otherwise replaces the value between 2nd and 3rd arguments");
+
+ test(function(){
+ element.value = "foobar";
+ element.selectionStart = 0;
+ element.selectionEnd = 0;
+
+ element.setRangeText("foobar2", 0, 3); // no 4th arg, default "preserve"
+ assert_equals(element.value, "foobar2bar");
+ assert_equals(element.selectionStart, 0);
+ assert_equals(element.selectionEnd, 0);
+ }, element.id + " selectionMode missing");
+
+ test(function(){
+ element.value = "foobar"
+ element.setRangeText("foo", 3, 6, "select");
+ assert_equals(element.value, "foofoo");
+ assert_equals(element.selectionStart, 3);
+ assert_equals(element.selectionEnd, 6);
+ }, element.id + " selectionMode 'select'");
+
+ test(function(){
+ element.value = "foobar"
+ element.setRangeText("foo", 3, 6, "start");
+ assert_equals(element.value, "foofoo");
+ assert_equals(element.selectionStart, 3);
+ assert_equals(element.selectionEnd, 3);
+ }, element.id + " selectionMode 'start'");
+
+ test(function(){
+ element.value = "foobar"
+ element.setRangeText("foobar", 3, 6, "end");
+ assert_equals(element.value, "foofoobar");
+ assert_equals(element.selectionStart, 9);
+ assert_equals(element.selectionEnd, 9);
+ }, element.id + " selectionMode 'end'");
+
+ test(function(){
+ element.value = "foobar"
+ element.selectionStart = 0;
+ element.selectionEnd = 5;
+ assert_equals(element.selectionStart, 0);
+ element.setRangeText("", 3, 6, "preserve");
+ assert_equals(element.value, "foo");
+ assert_equals(element.selectionStart, 0);
+ assert_equals(element.selectionEnd, 3);
+ }, element.id + " selectionMode 'preserve'");
+
+ test(function(){
+ assert_throws("INDEX_SIZE_ERR", function() {
+ element.setRangeText("barfoo", 2, 1);
+ });
+ }, element.id + " setRangeText with 3rd argument greater than 2nd argument throws an IndexSizeError exception");
+
+ test(function(){
+ assert_throws(new TypeError(), function() {
+ element.setRangeText();
+ });
+ }, element.id + " setRangeText without argument throws a type error");
+
+ element.onselect = t.step_func_done(function(e) {
+ assert_true(q, "event should be queued");
+ assert_true(e.isTrusted, "event is trusted");
+ assert_false(e.bubbles, "event bubbles");
+ assert_false(e.cancelable, "event is not cancelable");
+ });
+ element.setRangeText("foobar2", 0, 6);
+ q=true;
+ })
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/textfieldselection-setSelectionRange.html b/tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/textfieldselection-setSelectionRange.html
new file mode 100644
index 00000000000..ec4cf1b5d5b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/textfieldselection/textfieldselection-setSelectionRange.html
@@ -0,0 +1,224 @@
+<!DOCTYPE HTML>
+<title>Test of text field setSelectionRange</title>
+<link rel="author" title="Takeharu.Oshida" href="mailto:georgeosddev@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-textarea/input-setselectionrange">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<div id="hide" style="display: block">
+ <input id="a" type="text" value="abcde">
+ <textarea id="b">abcde</textarea>
+</div>
+<script>
+test(function() {
+ var input = document.getElementById("a");
+ test(function() {
+ assert_equals(typeof(input.setSelectionRange), "function", "element must have 'setSelectionRange' function");
+ },"input typeof(input.setSelectionRange)'");
+
+ test(function() {
+ assert_equals(input.setSelectionRange(0,1,"forward"),undefined,"setSelectionRange is void functuon");
+ },"input setSelectionRange return void");
+
+ test(function() {
+ input.setSelectionRange(0,1)
+ assert_equals(input.selectionStart, 0, "element.selectionStart should be 0");
+ assert_equals(input.selectionEnd, 1, "element.selectionEnd should be 1");
+ },'input setSelectionRange(0,1)');
+
+ test(function() {
+ input.setSelectionRange(0,input.value.length+1)
+ assert_equals(input.selectionEnd, input.value.length, "Arguments greater than the length of the value of the text field must be treated as pointing at the end of the text field");
+ },'input setSelectionRange(0,input.value.length+1)');
+
+ test(function() {
+ input.setSelectionRange(2,2)
+ assert_equals(input.selectionStart, 2, "If end is less than or equal to start then the start of the selection and the end of the selection must both be placed immediately before the character with offset end");
+ assert_equals(input.selectionEnd, 2, "If end is less than or equal to start then the start of the selection and the end of the selection must both be placed immediately before the character with offset end");
+ },'input setSelectionRange(2,2)');
+
+ test(function() {
+ input.setSelectionRange(2,1)
+ assert_equals(input.selectionStart, 1, "If end is less than or equal to start then the start of the selection and the end of the selection must both be placed immediately before the character with offset end");
+ assert_equals(input.selectionEnd, 1, "If end is less than or equal to start then the start of the selection and the end of the selection must both be placed immediately before the character with offset end");
+ },'input setSelectionRange(2,1)');
+
+ test(function() {
+ input.setSelectionRange(0,1,"backward")
+ assert_equals(input.selectionDirection, "backward", 'The direction of the selection must be set to backward if direction is a case-sensitive match for the string "backward"');
+ },'input direction of setSelectionRange(0,1,"backward")');
+
+ test(function() {
+ input.setSelectionRange(0,1,"forward")
+ assert_equals(input.selectionDirection, "forward", 'The direction of the selection must be set to forward if direction is a case-sensitive match for the string "forward"');
+ },'input direction of setSelectionRange(0,1,"forward")');
+
+ test(function() {
+ input.setSelectionRange(0,1,"none")
+ assert_equals(input.selectionDirection, "none", 'The direction of the selection must be set to forward if direction is a case-sensitive match for the string "none"');
+ },'input direction of setSelectionRange(0,1,"none")');
+
+ test(function() {
+ input.setSelectionRange(0,1,"hoge")
+ assert_equals(input.selectionDirection, "none", "otherwise");
+ },'input direction of setSelectionRange(0,1,"hoge")');
+
+ test(function() {
+ input.setSelectionRange(0,1,"BACKWARD")
+ assert_equals(input.selectionDirection, "none", "selectionDirection should be 'none'");
+ },'input direction of setSelectionRange(0,1,"BACKWARD")');
+
+ test(function() {
+ input.setSelectionRange(0,1)
+ assert_equals(input.selectionDirection, "none", "if the argument is omitted");
+ },'input direction of setSelectionRange(0,1)');
+
+ test(function() {
+ input.setSelectionRange("string",1);
+ assert_equals(input.selectionStart, 0, "element.selectionStart should be 0");
+ assert_equals(input.selectionEnd, 1, "element.selectionEnd should be 1");
+ },'input setSelectionRange("string",1)');
+
+ test(function() {
+ input.setSelectionRange(true,1);
+ assert_equals(input.selectionStart, 1, "element.selectionStart should be 1");
+ assert_equals(input.selectionEnd, 1, "element.selectionEnd should be 1");
+ },'input setSelectionRange(true,1)');
+
+ test(function() {
+ input.setSelectionRange([],1);
+ assert_equals(input.selectionStart, 0, "element.selectionStart should be 0");
+ assert_equals(input.selectionEnd, 1, "element.selectionEnd should be 1");
+ },'input setSelectionRange([],1)');
+
+ test(function() {
+ input.setSelectionRange({},1);
+ assert_equals(input.selectionStart, 0, "element.selectionStart should be 0");
+ assert_equals(input.selectionEnd, 1, "element.selectionEnd should be 1");
+ },'input setSelectionRange({},1)');
+
+ test(function() {
+ input.setSelectionRange(NaN,1);
+ assert_equals(input.selectionStart, 0, "element.selectionStart should be 0");
+ assert_equals(input.selectionEnd, 1, "element.selectionEnd should be 1");
+ },'input setSelectionRange(NaN,1)');
+
+ test(function() {
+ input.setSelectionRange(null,1);
+ assert_equals(input.selectionStart, 0, "element.selectionStart should be 0");
+ assert_equals(input.selectionEnd, 1, "element.selectionEnd should be 1");
+ },'input setSelectionRange(null,1)');
+
+ test(function() {
+ input.setSelectionRange(undefined,1);
+ assert_equals(input.selectionStart, 0, "element.selectionStart should be 0");
+ assert_equals(input.selectionEnd, 1, "element.selectionEnd should be 1");
+ },'input setSelectionRange(undefined,1)');
+},"test of input.setSelectionRange");
+
+test(function() {
+ var textarea = document.getElementById("b");
+ test(function() {
+ assert_equals(typeof(textarea.setSelectionRange), "function", "element must have 'setSelectionRange' function");
+ },"textarea typeof(input.setSelectionRange)'");
+
+ test(function() {
+ assert_equals(textarea.setSelectionRange(0,1,"forward"),undefined,"setSelectionRange is void functuon");
+ },"textarea setSelectionRange return void");
+
+ test(function() {
+ textarea.setSelectionRange(0,1)
+ assert_equals(textarea.selectionStart, 0, "element.selectionStart should be 0");
+ assert_equals(textarea.selectionEnd, 1, "element.selectionEnd should be 1");
+ },'textarea setSelectionRange(0,1)');
+
+ test(function() {
+ textarea.setSelectionRange(0,textarea.value.length+1)
+ assert_equals(textarea.selectionEnd, textarea.value.length, "Arguments greater than the length of the value of the text field must be treated as pointing at the end of the text field");
+ },'textarea setSelectionRange(0,textarea.value.length+1)');
+
+ test(function() {
+ textarea.setSelectionRange(2,2)
+ assert_equals(textarea.selectionStart, 2, "If end is less than or equal to start then the start of the selection and the end of the selection must both be placed immediately before the character with offset end");
+ assert_equals(textarea.selectionEnd, 2, "If end is less than or equal to start then the start of the selection and the end of the selection must both be placed immediately before the character with offset end");
+ },'textarea setSelectionRange(2,2)');
+
+ test(function() {
+ textarea.setSelectionRange(2,1)
+ assert_equals(textarea.selectionStart, 1, "If end is less than or equal to start then the start of the selection and the end of the selection must both be placed immediately before the character with offset end");
+ assert_equals(textarea.selectionEnd, 1, "If end is less than or equal to start then the start of the selection and the end of the selection must both be placed immediately before the character with offset end");
+ },'textarea setSelectionRange(2,1)');
+
+ test(function() {
+ textarea.setSelectionRange(0,1,"backward")
+ assert_equals(textarea.selectionDirection, "backward", 'The direction of the selection must be set to backward if direction is a case-sensitive match for the string "backward"');
+ },'textarea direction of setSelectionRange(0,1,"backward")');
+
+ test(function() {
+ textarea.setSelectionRange(0,1,"forward")
+ assert_equals(textarea.selectionDirection, "forward", 'The direction of the selection must be set to forward if direction is a case-sensitive match for the string "forward"');
+ },'textarea direction of setSelectionRange(0,1,"forward")');
+
+ test(function() {
+ textarea.setSelectionRange(0,1,"none")
+ assert_equals(textarea.selectionDirection, "none", 'The direction of the selection must be set to forward if direction is a case-sensitive match for the string "none"');
+ },'textarea direction of setSelectionRange(0,1,"none")');
+
+ test(function() {
+ textarea.setSelectionRange(0,1,"hoge")
+ assert_equals(textarea.selectionDirection, "none", "otherwise");
+ },'textarea direction of setSelectionRange(0,1,"hoge")');
+
+ test(function() {
+ textarea.setSelectionRange(0,1,"BACKWARD")
+ assert_equals(textarea.selectionDirection, "none", "selectionDirection should be 'none'");
+ },'textarea direction of setSelectionRange(0,1,"BACKWARD")');
+
+ test(function() {
+ textarea.setSelectionRange(0,1)
+ assert_equals(textarea.selectionDirection, "none", "if the argument is omitted");
+ },'textarea direction of setSelectionRange(0,1)');
+
+ test(function() {
+ textarea.setSelectionRange("string",1);
+ assert_equals(textarea.selectionStart, 1, "element.selectionStart should be 0");
+ assert_equals(textarea.selectionEnd, 1, "element.selectionStart should be 1");
+ },'textarea setSelectionRange("string",1)');
+
+ test(function() {
+ textarea.setSelectionRange(true,1);
+ assert_equals(textarea.selectionStart, 1, "element.selectionStart should be 1");
+ assert_equals(textarea.selectionEnd, 1, "element.selectionStart should be 1");
+ },'textarea setSelectionRange(true,1)');
+
+ test(function() {
+ textarea.setSelectionRange([],1);
+ assert_equals(textarea.selectionStart, 1, "element.selectionStart should be 0");
+ assert_equals(textarea.selectionEnd, 1, "element.selectionStart should be 1");
+ },'textarea setSelectionRange([],1)');
+
+ test(function() {
+ textarea.setSelectionRange({},1);
+ assert_equals(textarea.selectionStart, 1, "element.selectionStart should be 0");
+ assert_equals(textarea.selectionEnd, 1, "element.selectionStart should be 1");
+ },'textarea setSelectionRange({},1)');
+
+ test(function() {
+ textarea.setSelectionRange(NaN,1);
+ assert_equals(textarea.selectionStart, 1, "element.selectionStart should be 0");
+ assert_equals(textarea.selectionEnd, 1, "element.selectionStart should be 1");
+ },'textarea setSelectionRange(NaN,1)');
+
+ test(function() {
+ textarea.setSelectionRange(null,1);
+ assert_equals(textarea.selectionStart, 1, "element.selectionStart should be 0");
+ assert_equals(textarea.selectionEnd, 1, "element.selectionStart should be 1");
+ },'textarea setSelectionRange(null,1)');
+
+ test(function() {
+ textarea.setSelectionRange(undefined,1);
+ assert_equals(textarea.selectionStart, 1, "element.selectionStart should be 0");
+ assert_equals(textarea.selectionEnd, 1, "element.selectionStart should be 1");
+ },'textarea setSelectionRange(undefined,1)');
+},"test of textarea.setSelectionRange");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-button-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/forms/the-button-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-button-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-button-element/button-events.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-button-element/button-events.html
new file mode 100644
index 00000000000..74b48e92100
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-button-element/button-events.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: Button - events</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-button-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<form name="fm1" style="display:none">
+ <button id="btn">BUTTON</button>
+ <button id="menu_btn" type="menu" menu="menu">MENU BUTTON</button>
+ <menu id="menu" label="MENU">
+ <li>Menu item</li>
+ </menu>
+</form>
+<script>
+
+var btn = document.getElementById("btn"),
+ menu_btn = document.getElementById("menu_btn"),
+ t1 = async_test("The submit event must be fired when click a button in submit status"),
+ t2 = async_test("The reset event must be fired when click a button in reset status"),
+ t3 = async_test("The show event must be fired when click a button in menu status");
+
+document.forms.fm1.onsubmit = t1.step_func(function (evt) {
+ evt.preventDefault();
+ assert_true(evt.isTrusted, "The isTrusted attribute of the submit event shoud be true.");
+ assert_true(evt.bubbles, "The bubbles attribute of the submit event shoud be true.");
+ assert_true(evt.cancelable, "The cancelable attribute of the submit event shoud be true.");
+ assert_true(evt instanceof Event, "The submit event is an instance of Event interface.");
+ t1.done();
+});
+
+document.forms.fm1.onreset = t2.step_func(function (evt) {
+ assert_true(evt.isTrusted, "The isTrusted attribute of the reset event shoud be true.");
+ assert_true(evt.bubbles, "The bubbles attribute of the reset event shoud be true.");
+ assert_true(evt.cancelable, "The cancelable attribute of the reset event shoud be true.");
+ assert_true(evt instanceof Event, "The reset event is an instance of Event interface.");
+ t2.done();
+});
+
+document.getElementById("menu").onshow = t3.step_func(function (evt) {
+ assert_true(evt.isTrusted, "The isTrusted attribute of the show event shoud be true.");
+ assert_equals(evt.relatedTarget, menu_btn, "The relatedTarget attribute should be initialized to the related button element.");
+ assert_true(evt.cancelable, "The cancelable attribute of the show event shoud be true.");
+ assert_true(evt instanceof RelatedEvent, "The show event is an instance of RelatedEvent interface.");
+ t3.done();
+});
+
+t1.step(function () {
+ btn.type = "submit";
+ assert_equals(btn.type, "submit", "The button type should be 'submit'.");
+ btn.click();
+});
+
+t2.step(function () {
+ btn.type = "reset";
+ assert_equals(btn.type, "reset", "The button type should be 'reset'.");
+ btn.click();
+});
+
+t3.step(function () {
+ assert_equals(menu_btn.type, "menu", "The button type should be 'menu'.");
+ menu_btn.click();
+});
+
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-button-element/button-validation.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-button-element/button-validation.html
new file mode 100644
index 00000000000..a153907d77a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-button-element/button-validation.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>button element validation</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-button-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<button id=btn1>button</button>
+<button id=btn2 type=submit>button</button>
+<button id=btn3 type=reset>button</button>
+<button id=btn4 type=button>button</button>
+<button id=btn5 type=menu>button</button>
+<button id=btn6 type=foobar>button</button>
+<script>
+ function willValid(element, expectedType, willValidate, desc) {
+ test(function(){
+ assert_equals(element.type, expectedType);
+ assert_equals(element.willValidate, willValidate);
+ }, desc);
+ }
+
+ willValid(document.getElementById('btn1'), "submit", true, "missing type attribute");
+ willValid(document.getElementById('btn2'), "submit", true, "submit type attribute");
+ willValid(document.getElementById('btn3'), "reset", false, "reset type attribute");
+ willValid(document.getElementById('btn4'), "button", false, "button type attribute");
+ willValid(document.getElementById('btn5'), "menu", false, "menu type attribute");
+ willValid(document.getElementById('btn6'), "submit", true, "invalid type attribute");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-datalist-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/forms/the-datalist-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-datalist-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-datalist-element/datalistoptions.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-datalist-element/datalistoptions.html
new file mode 100644
index 00000000000..245d43cec4a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-datalist-element/datalistoptions.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Datalist element options</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#the-datalist-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<label>
+ Number:
+ <input list=numbers>
+</label>
+<datalist id=numbers>
+ <label> Select number:
+ <select id=num>
+ <option label="zero" value="0">
+ <option label="one" value="1">
+ <option label="two">2
+ <option label="three" disabled>3
+ <option>
+ </select>
+ </label>
+</datalist>
+<script>
+ test(function(){
+ var datalist = document.getElementById('numbers'),
+ labels = [],
+ values = [];
+ assert_equals(datalist.options.length, 5);
+
+ for (var i = 0, len = datalist.options.length; i < len; i++) {
+ assert_equals(datalist.options[i], datalist.options.item(i));
+ labels.push(datalist.options[i].label);
+ values.push(datalist.options[i].value);
+ }
+ assert_array_equals(labels, ["zero", "one", "two", "three", ""]);
+ assert_array_equals(values, ["0", "1", "2", "3", ""]);
+ }, "options label/value");
+
+ test(function(){
+ assert_false(document.getElementById('num').willValidate);
+ }, "If an element has a datalist element ancestor, it is barred from constraint validation");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-fieldset-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/forms/the-fieldset-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-fieldset-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-fieldset-element/HTMLFieldSetElement.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-fieldset-element/HTMLFieldSetElement.html
new file mode 100644
index 00000000000..0c394cbedd7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-fieldset-element/HTMLFieldSetElement.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: HTMLFieldSetElement interface</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-fieldset-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<form name="fm1" style="display:none">
+ <fieldset id="fs_outer">
+ <legend><input type="checkbox" name="cb"></legend>
+ <input type=text name="txt" id="ctl1">
+ <button id="ctl2" name="btn">BUTTON</button>
+ <fieldset id="fs_inner">
+ <input type="text" name="txt_inner">
+ <progress name="pg" value="0.5"></progress>
+ </fieldset>
+ </fieldset>
+</form>
+<script>
+
+var fm1,
+ fs_outer,
+ children_outer;
+
+setup(function () {
+ fm1 = document.forms.fm1;
+ fs_outer = document.getElementById("fs_outer");
+ children_outer = fs_outer.elements;
+});
+
+test(function () {
+ assert_equals(fs_outer.type, "fieldset", "The value of type attribute is incorrect.");
+}, "The type attribute must return 'fieldset'");
+
+test(function () {
+ assert_equals(fs_outer.form, fm1, "The fieldset should have a form owner.");
+}, "The form attribute must return the fieldset's form owner");
+
+test(function () {
+ assert_true(children_outer instanceof HTMLFormControlsCollection,
+ "The elements attribute should be an HTMLFormControlsCollection object");
+}, "The elements must return an HTMLFormControlsCollection object");
+
+test(function () {
+ var fs_inner = document.getElementById("fs_inner");
+ var children_inner = fs_inner.elements;
+ assert_array_equals(children_inner, [fm1.txt_inner],
+ "The items in the collection must be children of the inner fieldset element.");
+ assert_array_equals(children_outer, [fm1.cb, fm1.txt, fm1.btn, fm1.fs_inner, fm1.txt_inner],
+ "The items in the collection must be children of the outer fieldset element.");
+}, "The controls must root at the fieldset element");
+
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-fieldset-element/disabled.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-fieldset-element/disabled.html
new file mode 100644
index 00000000000..cbbda4ab042
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-fieldset-element/disabled.html
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Fieldset disabled</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-fieldset-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<form>
+ <fieldset id=fs disabled>
+ <legend>
+ <input type=checkbox id=clubc_l1>
+ <input type=radio id=clubr_l1>
+ <input type=text id=clubt_l1>
+ </legend>
+ <legend><input type=checkbox id=club_l2></legend>
+ <p><label>Name on card: <input id=clubname required></label></p>
+ <p><label>Card number: <input id=clubnum required pattern="[-0-9]+"></label></p>
+ </fieldset>
+ <fieldset id=fs2 disabled>
+ <p><legend><input type=checkbox id=club2></legend></p>
+ <p><label>Name on card: <input id=clubname2 required></label></p>
+ <p><label>Card number: <input id=clubnum2 required pattern="[-0-9]+"></label></p>
+ </fieldset>
+ <fieldset id=fs3 disabled>
+ <fieldset>
+ <legend><input type=checkbox id=club3></legend>
+ </fieldset>
+ <p><label>Name on card: <input id=clubname3 required></label></p>
+ <p><label>Card number: <input id=clubnum3 required pattern="[-0-9]+"></label></p>
+ </fieldset>
+ <fieldset id=fs4 disabled>
+ <legend>
+ <fieldset><input type=checkbox id=club4></fieldset>
+ </legend>
+ <p><label>Name on card: <input id=clubname4 required></label></p>
+ <p><label>Card number: <input id=clubnum4 required pattern="[-0-9]+"></label></p>
+ </fieldset>
+</form>
+<script>
+ test(function () {
+ assert_true(document.getElementById('fs').disabled, "The fieldset is disabled");
+ assert_false(document.getElementById('clubname').willValidate, "fieldset is disabled so is input 'clubname'");
+ assert_false(document.getElementById('clubnum').willValidate, "fieldset is disabled so is input 'clubnum'");
+ assert_true(document.getElementById('clubc_l1').willValidate, "input 'clubc_l1' is descendant of the first legend child of the fieldset. It should not be disabled");
+ assert_true(document.getElementById('clubr_l1').willValidate, "input 'clubr_l1' is descendant of the first legend child of the fieldset. It should not be disabled");
+ assert_true(document.getElementById('clubt_l1').willValidate, "input 'clubt_l1' is descendant of the first legend child of the fieldset. It should not be disabled");
+ assert_false(document.getElementById('club_l2').willValidate, "input 'club_l2' is a descendant of the second legend child of the fieldset. It should be disabled");
+ }, "The disabled attribute, when specified, causes all the form control descendants of the fieldset element, excluding those that are descendants of the fieldset element's first legend element child, if any, to be disabled.");
+
+ test(function () {
+ assert_true(document.getElementById('fs2').disabled, "The fieldset is disabled");
+ assert_false(document.getElementById('clubname2').willValidate, "fieldset is disabled so is input 'clubname2'");
+ assert_false(document.getElementById('clubnum2').willValidate, "fieldset is disabled so is input 'clubnum2'");
+ assert_false(document.getElementById('club2').willValidate, "the first legend is not a child of the disbled fieldset: input 'club2' is disabled");
+ }, "The first 'legend' element is not a child of the disabled fieldset: Its descendants should be disabled.");
+
+ test(function () {
+ assert_true(document.getElementById('fs3').disabled, "The fieldset is disabled");
+ assert_false(document.getElementById('clubname3').willValidate, "fieldset is disabled so is input 'clubname3'");
+ assert_false(document.getElementById('clubnum3').willValidate, "fieldset is disabled so is input 'clubnum3'");
+ assert_false(document.getElementById('club3').willValidate, "the first legend is not a child of the disbled fieldset: input 'club3' is disabled");
+ }, "The <legend> element is not a child of the disabled fieldset: Its descendants should be disabled.");
+
+ test(function () {
+ assert_true(document.getElementById('fs4').disabled, "The fieldset is disabled");
+ assert_false(document.getElementById('clubname4').willValidate, "fieldset is disabled so is input 'clubname4'");
+ assert_false(document.getElementById('clubnum4').willValidate, "fieldset is disabled so is input 'clubnum4'");
+ assert_true(document.getElementById('club4').willValidate, "the first legend a child of the disbled fieldset: input 'club4' is disabled");
+ }, "The <legend> element is child of the disabled fieldset: Its descendants should be disabled.");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-form-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/forms/the-form-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-form-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-form-element/form-autocomplete.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-form-element/form-autocomplete.html
new file mode 100644
index 00000000000..af497b40959
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-form-element/form-autocomplete.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>form autocomplete attribute</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#the-form-element">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#attr-fe-autocomplete">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<form name="missing_attribute">
+ <input>
+ <input autocomplete="on">
+ <input autocomplete="off">
+ <input autocomplete="foobar">
+</form>
+<form name="autocomplete_on" autocomplete="on">
+ <input>
+ <input autocomplete="on">
+ <input autocomplete="off">
+ <input autocomplete="foobar">
+</form>
+<form name="autocomplete_off" autocomplete="off">
+ <input>
+ <input autocomplete="on">
+ <input autocomplete="off">
+ <input autocomplete="foobar">
+</form>
+<form name="autocomplete_invalid" autocomplete="foobar">
+ <input>
+ <input autocomplete="on">
+ <input autocomplete="off">
+ <input autocomplete="foobar">
+</form>
+<script>
+ function autocompletetest(form, expectedValues, desc) {
+ test(function(){
+ assert_equals(form.autocomplete, expectedValues[0]);
+ assert_equals(form.elements[0].autocomplete, expectedValues[1]);
+ assert_equals(form.elements[1].autocomplete, expectedValues[2]);
+ assert_equals(form.elements[2].autocomplete, expectedValues[3]);
+ assert_equals(form.elements[3].autocomplete, expectedValues[4]);
+ }, desc);
+ }
+
+ autocompletetest(document.forms.missing_attribute, ["on", "on", "on", "off", ""], "form autocomplete attribute missing");
+ autocompletetest(document.forms.autocomplete_on, ["on", "on", "on", "off", ""], "form autocomplete attribute on");
+ autocompletetest(document.forms.autocomplete_off, ["off", "off", "on", "off", ""], "form autocomplete attribute off");
+ autocompletetest(document.forms.autocomplete_invalid, ["on", "on", "on", "off", ""], "form autocomplete attribute invalid");
+
+ var keywords = [ "name", "honorific-prefix", "given-name", "additional-name", "family-name", "honorific-suffix", "nickname", "organization-title", "organization", "street-address", "address-line1", "address-line2", "address-line3", "locality", "region", "country", "country-name", "postal-code", "cc-name", "cc-given-name", "cc-additional-name", "cc-family-name", "cc-number", "cc-exp", "cc-exp-month", "cc-exp-year", "cc-csc", "cc-type", "language", "bday", "bday-day", "bday-month", "bday-year", "sex", "url", "photo", "tel", "tel-country-code", "tel-national", "tel-area-code", "tel-local", "tel-local-prefix", "tel-local-suffix", "tel-extension", "email", "impp" ];
+ keywords.forEach(function(keyword) {
+ test(function(){
+ var input = document.createElement("input");
+ input.setAttribute("autocomplete", keyword);
+ assert_equals(input.autocomplete, keyword);
+ }, keyword + " is an allowed autocomplete field name");
+ });
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-form-element/form-elements-interfaces-01.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-form-element/form-elements-interfaces-01.html
new file mode 100644
index 00000000000..c8b4a6c71ed
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-form-element/form-elements-interfaces-01.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<title>form.elements: interfaces</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-form-elements">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#htmlformcontrolscollection">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ var form = document.createElement("form");
+ ["HTMLFormControlsCollection", "HTMLCollection"].forEach(function(i) {
+ test(function() {
+ assert_true(i in window, "Interface should exist")
+ assert_true(form.elements instanceof window[i],
+ "elements should implement the interface")
+ }, "Testing interface " + i)
+ })
+})
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-form-element/form-elements-matches.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-form-element/form-elements-matches.html
new file mode 100644
index 00000000000..79216272651
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-form-element/form-elements-matches.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<title>form.elements: matches</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-form-elements">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<div id="test">
+<form id="form">
+<input type="image">
+</form>
+</div>
+<script>
+test(function() {
+ assert_equals(document.getElementById("form").elements.length, 0);
+}, "input type=image should not be present in the form.elements collection")
+test(function() {
+ var form = document.getElementById("form");
+ var i = document.createElement("input");
+ i.name = "2";
+ form.appendChild(i);
+ var j = document.createElement("input");
+ j.name = "03";
+ form.appendChild(j);
+ assert_equals(form.elements[-1], undefined, '[-1]');
+ assert_equals(form.elements["-1"], undefined, '["-1"]');
+ assert_equals(form.elements[0], i, '[0]');
+ assert_equals(form.elements["0"], i, '["0"]');
+ assert_equals(form.elements[1], j, '[1]');
+ assert_equals(form.elements["1"], j, '["1"]');
+ assert_equals(form.elements[2], undefined, '[2]');
+ assert_equals(form.elements["2"], undefined, '["2"]');
+ assert_equals(form.elements[03], undefined, '[03]');
+ assert_equals(form.elements["03"], j, '["03"]');
+ assert_equals(form.elements.item(-1), null, 'item(-1)');
+ assert_equals(form.elements.item(0), i, 'item(0)');
+ assert_equals(form.elements.item(1), j, 'item(1)');
+ assert_equals(form.elements.item(2), null, 'item(2)');
+ assert_equals(form.elements.namedItem("2"), i, 'namedItem("2")');
+ assert_equals(form.elements.namedItem("03"), j, 'namedItem("03")');
+ assert_equals(form.elements.namedItem("3"), null, 'namedItem("3")');
+ assert_array_equals(form.elements, [i, j]);
+ form.removeChild(i);
+ form.removeChild(j);
+}, "form.elements should include elements whose name starts with a number");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-form-element/form-elements-nameditem-01.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-form-element/form-elements-nameditem-01.html
new file mode 100644
index 00000000000..0b5aeb8ef5c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-form-element/form-elements-nameditem-01.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<title>form.elements: namedItem</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-form-elements">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<div id="test">
+<form id=form>
+<input name=b id=i1>
+<input name=b id=i2>
+</form>
+</div>
+<script>
+test(function() {
+ assert_true("RadioNodeList" in window, "RadioNodeList should exist");
+}, "RadioNodeList should exist")
+test(function() {
+ var nl = document.forms.form.elements["b"];
+ assert_true(nl instanceof NodeList, "Should get a NodeList");
+ if ("RadioNodeList" in window) {
+ assert_true(nl instanceof RadioNodeList, "Should get a RadioNodeList");
+ }
+ assert_array_equals(nl,
+ [document.getElementById("i1"),
+ document.getElementById("i2")]);
+
+ var el = nl[0];
+ el.parentNode.removeChild(el);
+ assert_true(nl instanceof NodeList, "Should get a NodeList");
+ if ("RadioNodeList" in window) {
+ assert_true(nl instanceof RadioNodeList, "Should get a RadioNodeList");
+ }
+ assert_array_equals(nl, [document.getElementById("i2")]);
+ assert_equals(document.forms.form.elements["b"], document.getElementById("i2"));
+}, "elements collection should return elements or RadioNodeLists")
+test(function() {
+ var fs = document.forms.form.appendChild(document.createElement("fieldset"));
+ fs.name = "fs";
+ assert_equals(document.forms.form.elements.fs, fs);
+ fs.parentNode.removeChild(fs);
+}, "elements collection should include fieldsets")
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-form-element/form-elements-nameditem-02.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-form-element/form-elements-nameditem-02.html
new file mode 100644
index 00000000000..c25e554de11
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-form-element/form-elements-nameditem-02.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<title>form.elements: parsing</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-form-elements">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#parsing-main-intr">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<div id="test">
+<form id=form>
+<table>
+<tr>
+<td><input type="radio" name="radio1" id="r1" value=1></td>
+<td><input type="radio" name="radio2" id="r2" value=2></td>
+<input type="radio" name="radio0" id="r0" value=0>
+</tr>
+</table>
+</form>
+</div>
+<script>
+test(function() {
+ var form = document.getElementById("form");
+ assert_array_equals(form.elements,
+ [document.getElementById("r0"),
+ document.getElementById("r1"),
+ document.getElementById("r2")]);
+}, "form.elements should work correctly in the face of table syntax errors")
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-form-element/form-nameditem.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-form-element/form-nameditem.html
new file mode 100644
index 00000000000..f372742a721
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-form-element/form-nameditem.html
@@ -0,0 +1,239 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Form named getter</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<!-- XXX Nothing tests id attributes yet. -->
+<!-- XXX Keygen. -->
+<!-- XXX We also need tests for moving inputs and forms in the DOM. -->
+<form>
+<input type=button name=button>
+<input type=radio name=radio value=x>
+<input type=radio name=radio value=y>
+<input type=radio name=radio value=z>
+</form>
+
+<form>
+<button name=l1></button>
+<fieldset name=l2></fieldset>
+<input type=hidden name=l3>
+<input type=text name=l4>
+<input type=search name=l5>
+<input type=tel name=l6>
+<input type=url name=l7>
+<input type=email name=l8>
+<input type=password name=l9>
+<input type=datetime name=l10>
+<input type=date name=l11>
+<input type=month name=l12>
+<input type=week name=l13>
+<input type=time name=l14>
+<input type=datetime-local name=l15>
+<input type=number name=l16>
+<input type=range name=l17>
+<input type=color name=l18>
+<input type=checkbox name=l19>
+<input type=radio name=l20>
+<input type=file name=l21>
+<input type=submit name=l22>
+<input type=image name=l23>
+<input type=reset name=l24>
+<input type=button name=l25>
+<input type=foo name=l26>
+<input name=l27>
+<object name=l28></object>
+<output name=l29></output>
+<select name=l30></select>
+<textarea name=l31></textarea>
+</form>
+
+<form>
+<!-- EventTarget -->
+<input type=radio name=addEventListener>
+<input type=radio name=removeEventListener>
+<input type=radio name=dispatchEvent>
+
+<!-- Node -->
+<input type=radio name=nodeType>
+<input type=radio name=nodeName>
+<input type=radio name=ownerDocument>
+
+<!-- Element -->
+<input type=radio name=namespaceURI>
+<input type=radio name=prefix>
+<input type=radio name=localName>
+
+<!-- HTMLElement -->
+<input type=radio name=title>
+<input type=radio name=lang>
+<input type=radio name=dir>
+
+<!-- HTMLFormElement -->
+<input type=radio name=acceptCharset>
+<input type=radio name=action>
+<input type=radio name=autocomplete>
+<input type=radio name=enctype>
+<input type=radio name=encoding>
+<input type=radio name=method>
+<input type=radio name=name>
+<input type=radio name=noValidate>
+<input type=radio name=target>
+<input type=radio name=elements>
+<input type=radio name=length>
+<input type=radio name=submit>
+<input type=radio name=reset>
+<input type=radio name=checkValidity>
+</form>
+
+<img name=x>
+<form></form><!-- no child nodes -->
+<img name=y>
+<form><!-- a child node --></form>
+<img name=z>
+
+<input form=a name=b>
+<form id=a></form>
+<input form=c name=d>
+<input form=c name=d>
+<form id=c></form>
+<script>
+test(function() {
+ var form = document.getElementsByTagName("form")[0]
+ assert_equals(form.item, undefined)
+ assert_false("item" in form)
+}, "Forms should not have an item method")
+
+test(function() {
+ var form = document.getElementsByTagName("form")[0]
+ assert_equals(form.namedItem, undefined)
+ assert_false("namedItem" in form)
+}, "Forms should not have a namedItem method")
+
+test(function() {
+ var form = document.getElementsByTagName("form")[0]
+ var button = document.getElementsByTagName("input")[0]
+ assert_equals(button.type, "button")
+ assert_equals(form.button, button)
+ assert_equals(form.button.length, undefined)
+}, "Name for a single element should work")
+
+test(function() {
+ var form = document.getElementsByTagName("form")[0]
+ assert_equals(form.radio.item(-1), null)
+ assert_array_equals([0, 1, 2].map(function(i) {
+ return form.radio.item(i).value
+ }), ["x", "y", "z"])
+ assert_equals(form.radio.item(3), null)
+}, "Calling item() on the NodeList returned from the named getter should work")
+
+test(function() {
+ var form = document.getElementsByTagName("form")[0]
+ assert_equals(form.radio.length, 3)
+ assert_equals(form.radio[-1], undefined)
+ assert_array_equals([0, 1, 2].map(function(i) {
+ return form.radio[i].value
+ }), ["x", "y", "z"])
+ assert_equals(form.radio[3], undefined)
+}, "Indexed getter on the NodeList returned from the named getter should work")
+
+test(function() {
+ var form = document.getElementsByTagName("form")[0]
+ var indices = [-1, 0, 1, 2, 3]
+ indices.forEach(function(i) {
+ assert_throws(new TypeError(), function() {
+ form.radio(i)
+ })
+ })
+}, "Invoking a legacycaller on the NodeList returned from the named getter " +
+ "should not work")
+
+test(function() {
+ var form = document.getElementsByTagName("form")[1]
+ for (var i = 1; i <= 31; ++i) {
+ if (i == 23) {
+ // input type=image
+ assert_equals(form["l" + i], undefined)
+ } else {
+ assert_equals(form["l" + i], form.children[i - 1])
+ }
+ }
+}, "All listed elements except input type=image should be present in the form")
+
+test(function() {
+ var names = [
+ // EventTarget
+ "addEventListener", "removeEventListener", "dispatchEvent",
+ // Node
+ "nodeType", "nodeName", "ownerDocument",
+ // Element
+ "namespaceURI", "prefix", "localName",
+ // HTMLElement
+ "title", "lang", "dir",
+ // HTMLFormElement
+ "acceptCharset", "action", "autocomplete", "enctype", "encoding", "method",
+ "name", "noValidate", "target", "elements", "length", "submit", "reset",
+ "checkValidity"
+ ]
+ var form = document.getElementsByTagName("form")[2]
+ names.forEach(function(name, i) {
+ assert_equals(form[name], form.children[i])
+ })
+}, "Named elements should override builtins")
+
+test(function() {
+ var form = document.getElementsByTagName("form")[3]
+ assert_equals(form.x, undefined, "x should not be associated with the form")
+ assert_equals(form.y, undefined, "y should not be associated with the form")
+ assert_equals(form.z, undefined, "z should not be associated with the form")
+ assert_equals(form[0], undefined, "The form should not have supported property indices")
+ assert_equals(form.length, 0)
+}, "Named items outside the form should not be returned (no children)")
+
+test(function() {
+ var form = document.getElementsByTagName("form")[4]
+ assert_equals(form.x, undefined, "x should not be associated with the form")
+ assert_equals(form.y, undefined, "y should not be associated with the form")
+ assert_equals(form.z, undefined, "z should not be associated with the form")
+ assert_equals(form[0], undefined, "The form should not have supported property indices")
+ assert_equals(form.length, 0)
+}, "Named items outside the form should not be returned (one child)")
+
+test(function() {
+ var form = document.getElementsByTagName("form")[5]
+ assert_equals(form.id, "a")
+
+ var input = document.getElementsByName("b")[0]
+ assert_equals(input.localName, "input")
+ assert_equals(input.getAttribute("form"), "a")
+
+ assert_equals(form.b, input);
+}, "The form attribute should be taken into account for named getters (single element)")
+
+test(function() {
+ var form = document.getElementsByTagName("form")[6]
+ assert_equals(form.id, "c")
+
+ var input1 = document.getElementsByName("d")[0]
+ assert_equals(input1.localName, "input")
+ assert_equals(input1.getAttribute("form"), "c")
+
+ var input2 = document.getElementsByName("d")[1]
+ assert_equals(input2.localName, "input")
+ assert_equals(input2.getAttribute("form"), "c")
+
+ assert_true(form.d instanceof NodeList, "form.d should be a NodeList")
+ assert_array_equals(form.d, [input1, input2])
+}, "The form attribute should be taken into account for named getters (multiple elements)")
+
+test(function() {
+ var f = document.body.appendChild(document.createElement("form"))
+ f.id = "f"
+ var g = f.appendChild(document.createElement("form"))
+ g.id = "g"
+ var input = g.appendChild(document.createElement("input"))
+ input.name = "x"
+ assert_equals(f.x, undefined)
+ assert_equals(g.x, input)
+}, "Input should only be a named property on the innermost form that contains it")
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/button.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/button.html
new file mode 100644
index 00000000000..3c826a9754f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/button.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>input type button</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#button-state-(type=button)">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<form id=f1>
+ <input type=button id=b1 name=b1>
+</form>
+<form>
+ <input id=i1 value="foo">
+ <input type=button id=b2 name=b2>
+</form>
+<form>
+ <input type=radio id=i2 checked name=b3>
+ <input type=button id=b3 name=b3>
+</form>
+<form>
+ <input type=checkbox id=i3>
+ <input type=button id=b4 name=b4>
+</form>
+
+<script>
+ var t = async_test("clicking on button should not submit a form"),
+ b1 = document.getElementById('b1'),
+ b2 = document.getElementById('b2'),
+ b3 = document.getElementById('b3'),
+ b4 = document.getElementById('b4'),
+ i1 = document.getElementById('i1'),
+ i2 = document.getElementById('i2'),
+ i3 = document.getElementById('i3');
+
+ test(function(){
+ assert_false(b1.willValidate);
+ }, "the element is barred from constraint validation");
+
+ document.getElementById('f1').onsubmit = t.step_func(function(e) {
+ e.preventDefault();
+ assert_unreached("form has been submitted");
+ });
+
+ t.step(function() {
+ b1.click();
+ });
+ t.done();
+
+ test(function(){
+ i1.value = "bar";
+ b2.click();
+ assert_equals(i1.value, "bar");
+ }, "clicking on button should not reset other form fields");
+
+ test(function(){
+ assert_true(i2.checked);
+ b3.click();
+ assert_true(i2.checked);
+ }, "clicking on button should not unchecked radio buttons");
+
+ test(function(){
+ assert_false(i3.indeterminate);
+ b4.click();
+ assert_false(i3.indeterminate);
+ }, "clicking on button should not change its indeterminate IDL attribute");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/checkbox.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/checkbox.html
new file mode 100644
index 00000000000..1b75d74300a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/checkbox.html
@@ -0,0 +1,110 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>input type checkbox</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#checkbox-state-(type=checkbox)">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<input type=checkbox id=checkbox1>
+<input type=checkbox id=checkbox2 disabled>
+<input type=checkbox id=checkbox3>
+<input type=checkbox id=checkbox4 checked>
+<input type=checkbox id=checkbox5>
+<input type=checkbox id=checkbox6>
+<script>
+ var checkbox1 = document.getElementById('checkbox1'),
+ checkbox2 = document.getElementById('checkbox2'),
+ checkbox3 = document.getElementById('checkbox3'),
+ checkbox4 = document.getElementById('checkbox4'),
+ checkbox5 = document.getElementById('checkbox5'),
+ checkbox6 = document.getElementById('checkbox6'),
+ c1_input_fired = false, c1_change_fired = false,
+ t1 = async_test("click on mutable checkbox fires the input and change events"),
+ t2 = async_test("click on non-mutable checkbox doesn't fire the input or change event"),
+ t3 = async_test("pre-activation steps on unchecked checkbox"),
+ t4 = async_test("pre-activation steps on checked checkbox"),
+ t5 = async_test("canceled activation steps on unchecked checkbox"),
+ t6 = async_test("canceled activation steps on unchecked checkbox (indeterminate=true in onclick)");
+
+ checkbox1.oninput= t1.step_func(function(e) {
+ c1_input_fired = true;
+ assert_true(e.bubbles, "event should bubble");
+ assert_true(e.isTrusted, "event should be trusted");
+ assert_false(e.cancelable, "event shoud not be cancelable");
+ assert_true(checkbox1.checked, "checkbox is checked");
+ assert_false(checkbox1.indeterminate, "checkbox is not indeterminate");
+ });
+
+ checkbox1.onchange = t1.step_func(function(e) {
+ c1_change_fired = true;
+ assert_true(e.bubbles, "event should bubble")
+ assert_true(e.isTrusted, "event should be trusted");
+ assert_false(e.cancelable, "event shoud not be cancelable");
+ assert_true(checkbox1.checked, "checkbox is checked");
+ assert_false(checkbox1.indeterminate, "checkbox is not indeterminate");
+ });
+
+ checkbox2.oninput= t2.step_func(function(e) {
+ assert_unreached("event input fired");
+ });
+
+ checkbox2.onchange = t2.step_func(function(e) {
+ assert_unreached("event change fired");
+ });
+
+ t1.step(function() {
+ checkbox1.click();
+ assert_true(c1_input_fired);
+ assert_true(c1_change_fired);
+ t1.done();
+ });
+
+ t2.step(function() {
+ checkbox2.click();
+ t2.done();
+ });
+
+ t3.step(function() {
+ checkbox3.indeterminate = true;
+ checkbox3.click();
+ assert_true(checkbox3.checked);
+ assert_false(checkbox3.indeterminate);
+ t3.done();
+ });
+
+ t4.step(function() {
+ checkbox4.indeterminate = true;
+ checkbox4.click();
+ assert_false(checkbox4.checked);
+ assert_false(checkbox4.indeterminate);
+ t4.done();
+ });
+
+ checkbox5.onclick = t5.step_func(function(e) {
+ e.preventDefault();
+ assert_false(checkbox5.checked);
+ assert_false(checkbox5.indeterminate);
+ t5.done();
+ });
+
+ t5.step(function(){
+ assert_false(checkbox5.checked);
+ assert_false(checkbox5.indeterminate);
+ checkbox5.click();
+ });
+
+ checkbox6.onclick = t6.step_func(function(e) {
+ checkbox6.indeterminate = true;
+ e.preventDefault();
+ assert_false(checkbox6.checked);
+ assert_false(checkbox6.indeterminate);
+ t6.done();
+ });
+
+ t6.step(function(){
+ assert_false(checkbox6.checked);
+ assert_false(checkbox6.indeterminate);
+ checkbox6.click();
+ });
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/checked.xhtml b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/checked.xhtml
new file mode 100644
index 00000000000..70aeb510979
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/checked.xhtml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>input@checked is immediately reflected to 'checked' IDL attribute</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id="log"></div>
+<input style="display: none" type="checkbox" checked="">
+<script>
+test(function(){
+assert_true(document.querySelector('input').checked, 'Examining "checked" IDL attribute value:')
+});
+</script>
+</input>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/color.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/color.html
new file mode 100644
index 00000000000..6164815f66e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/color.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Form input type=color</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel=help href="https://html.spec.whatwg.org/multipage/multipage/common-microsyntaxes.html#colors">
+<link rel=help href="https://html.spec.whatwg.org/multipage/multipage/states-of-the-type-attribute.html#color-state-(type=color)">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+ var colors = [
+ {value: "", expected: "#000000", testname: "Empty value should return #000000"},
+ {expected: "#000000", testname: "Missing value should return #000000"},
+ {value: "#ffffff", expected: "#ffffff", testname: "Valid simple color: should return #ffffff"},
+ {value: "#FFFFFF", expected: "#ffffff", testname: "Valid simple color (containing LATIN CAPITAL LETTERS): should return #ffffff (converted to ASCII lowercase)"},
+ {value: "#0F0F0F", expected: "#0f0f0f", testname: "Zero-padding"},
+ {value: "#fff", expected: "#000000", testname: "Invalid simple color: not 7 characters long"},
+ {value: "fffffff", expected: "#000000", testname: "Invalid simple color: no starting # sign"},
+ {value: "#gggggg", expected: "#000000", testname: "Invalid simple color: non ASCII hex digits"},
+ {value: "foobar", expected: "#000000", testname: "Invalid simple color: foobar"},
+ {value: "#ffffff\u0000", expected: "#000000", testname: "Invalid color: trailing Null (U+0000)"},
+ {value: "#ffffff;", expected: "#000000", testname: "Invalid color: trailing ;"},
+ {value: " #ffffff", expected: "#000000", testname: "Invalid color: leading space"},
+ {value: "#ffffff ", expected: "#000000", testname: "Invalid color: trailing space"},
+ {value: " #ffffff ", expected: "#000000", testname: "Invalid color: leading+trailing spaces"},
+ {value: "crimson", expected: "#000000", testname: "Invalid color: keyword crimson"},
+ {value: "bisque", expected: "#000000", testname: "Invalid color: keyword bisque"},
+ {value: "currentColor", expected: "#000000", testname: "Invalid color: keyword currentColor"},
+ {value: "transparent", expected: "#000000", testname: "Invalid color: keyword transparent"},
+ {value: "ActiveBorder", expected: "#000000", testname: "Invalid color: keyword ActiveBorder"},
+ {value: "inherit", expected: "#000000", testname: "Invalid color: keyword inherit"},
+ {value: "rgb(1,1,1)", expected: "#000000", testname: "Invalid color: rgb(1,1,1)"},
+ {value: "rgb(1,1,1,1)", expected: "#000000", testname: "Invalid color: rgb(1,1,1,1)"},
+ {value: "#FFFFF\u1F4A9", expected: "#000000", testname: "Invalid color: PILE OF POO (U+1F4A9)"}
+ ];
+ for (var i = 0; i < colors.length; i++) {
+ var w = colors[i];
+ test(function() {
+ var input = document.createElement("input");
+ input.type = "color";
+ input.value = w.value;
+ assert_equals(input.value, w.expected);
+ }, w.testname);
+ }
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/contains.json b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/contains.json
new file mode 100644
index 00000000000..c2b780f0b8d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/contains.json
@@ -0,0 +1,154 @@
+[
+ {
+ "id": "states-of-the-type-attribute",
+ "original_id": "states-of-the-type-attribute",
+ "children": [
+ {
+ "id": "hidden-state-type-hidden",
+ "original_id": "hidden-state-(type=hidden)"
+ },
+ {
+ "id": "text-type-text-state-and-search-state-type-search",
+ "original_id": "text-(type=text)-state-and-search-state-(type=search)"
+ },
+ {
+ "id": "telephone-state-type-tel",
+ "original_id": "telephone-state-(type=tel)"
+ },
+ {
+ "id": "url-state-type-url",
+ "original_id": "url-state-(type=url)"
+ },
+ {
+ "id": "e-mail-state-type-email",
+ "original_id": "e-mail-state-(type=email)"
+ },
+ {
+ "id": "password-state-type-password",
+ "original_id": "password-state-(type=password)"
+ },
+ {
+ "id": "date-and-time-state-type-datetime",
+ "original_id": "date-and-time-state-(type=datetime)"
+ },
+ {
+ "id": "date-state-type-date",
+ "original_id": "date-state-(type=date)"
+ },
+ {
+ "id": "month-state-type-month",
+ "original_id": "month-state-(type=month)"
+ },
+ {
+ "id": "week-state-type-week",
+ "original_id": "week-state-(type=week)"
+ },
+ {
+ "id": "time-state-type-time",
+ "original_id": "time-state-(type=time)"
+ },
+ {
+ "id": "local-date-and-time-state-type-datetime-local",
+ "original_id": "local-date-and-time-state-(type=datetime-local)"
+ },
+ {
+ "id": "number-state-type-number",
+ "original_id": "number-state-(type=number)"
+ },
+ {
+ "id": "range-state-type-range",
+ "original_id": "range-state-(type=range)"
+ },
+ {
+ "id": "color-state-type-color",
+ "original_id": "color-state-(type=color)"
+ },
+ {
+ "id": "checkbox-state-type-checkbox",
+ "original_id": "checkbox-state-(type=checkbox)"
+ },
+ {
+ "id": "radio-button-state-type-radio",
+ "original_id": "radio-button-state-(type=radio)"
+ },
+ {
+ "id": "file-upload-state-type-file",
+ "original_id": "file-upload-state-(type=file)"
+ },
+ {
+ "id": "submit-button-state-type-submit",
+ "original_id": "submit-button-state-(type=submit)"
+ },
+ {
+ "id": "image-button-state-type-image",
+ "original_id": "image-button-state-(type=image)"
+ },
+ {
+ "id": "reset-button-state-type-reset",
+ "original_id": "reset-button-state-(type=reset)"
+ },
+ {
+ "id": "button-state-type-button",
+ "original_id": "button-state-(type=button)"
+ }
+ ]
+ },
+ {
+ "id": "input-impl-notes",
+ "original_id": "input-impl-notes"
+ },
+ {
+ "id": "common-input-element-attributes",
+ "original_id": "common-input-element-attributes",
+ "children": [
+ {
+ "id": "the-maxlength-attribute",
+ "original_id": "the-maxlength-attribute"
+ },
+ {
+ "id": "the-size-attribute",
+ "original_id": "the-size-attribute"
+ },
+ {
+ "id": "the-readonly-attribute",
+ "original_id": "the-readonly-attribute"
+ },
+ {
+ "id": "the-required-attribute",
+ "original_id": "the-required-attribute"
+ },
+ {
+ "id": "the-multiple-attribute",
+ "original_id": "the-multiple-attribute"
+ },
+ {
+ "id": "the-pattern-attribute",
+ "original_id": "the-pattern-attribute"
+ },
+ {
+ "id": "the-min-and-max-attributes",
+ "original_id": "the-min-and-max-attributes"
+ },
+ {
+ "id": "the-step-attribute",
+ "original_id": "the-step-attribute"
+ },
+ {
+ "id": "the-list-attribute",
+ "original_id": "the-list-attribute"
+ },
+ {
+ "id": "the-placeholder-attribute",
+ "original_id": "the-placeholder-attribute"
+ }
+ ]
+ },
+ {
+ "id": "common-input-element-apis",
+ "original_id": "common-input-element-apis"
+ },
+ {
+ "id": "common-event-behaviors",
+ "original_id": "common-event-behaviors"
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/date.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/date.html
new file mode 100644
index 00000000000..70885ed05a8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/date.html
@@ -0,0 +1,90 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Inputs Date</title>
+ <link rel="author" title="Morishita Hiromitsu" href="mailto:hero@asterisk-works.jp">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#date-state-(type=date)">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#dates-and-times">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <h1>Inputs Date</h1>
+ <div style="display: none">
+ <input id="valid" type="date" value="2011-11-01" min="2011-01-01" max="2011-12-31" />
+ <input id="too_small_value" type="date" value="1999-01-31" min="2011-01-01" max="2011-12-31"/>
+ <input id="too_large_value" type="date" value="2099-01-31" min="2011-01-01" max="2011-12-31"/>
+ <input id="invalid_min" type="date" value="2011-01-01" min="1999-1" max="2011-12-31"/>
+ <input id="invalid_max" type="date" value="2011-01-01" min="2011-01-01" max="2011-13-162-777"/>
+ <input id="min_larger_than_max" type="date" value="2011-01-01" min="2099-01" max="2011-12-31"/>
+ <input id="invalid_value" type="date" value="invalid-date" min="2011-01-01" max="2011-12-31"/>
+ </div>
+
+ <div id="log"></div>
+
+ <script type="text/javascript">
+ test(function() {
+ assert_equals(document.getElementById("valid").type, "date")
+ }, "date type support on input element");
+
+ test(function() {
+ assert_equals(document.getElementById("valid").value, "2011-11-01");
+ assert_equals(document.getElementById("too_small_value").value, "2011-01-01");
+ assert_equals(document.getElementById("too_large_value").value, "2011-12-31");
+ }, "The value attribute, if specified and not empty, must have a value that is a valid date string.");
+
+ test(function() {
+ assert_equals(document.getElementById("valid").min, "2011-01-01"),
+ assert_equals(document.getElementById("invalid_min").min, "")
+ }, "The min attribute, if specified, must have a value that is a valid date string.");
+
+ test(function() {
+ assert_equals(document.getElementById("valid").max, "2011-12-31"),
+ assert_equals(document.getElementById("min_larger_than_max").max, "2099-01"),
+ assert_equals(document.getElementById("invalid_max").max, "")
+ },"The max attribute, if specified, must have a value that is a valid date string.");
+
+ test(function() {
+ assert_equals(document.getElementById("invalid_value").value, "");
+ }, "User agents must not allow the user to set the value to a non-empty string that is not a valid date string.");
+ test(function() {
+ var numDays = [
+ // the number of days in month month of year year is: 31 if month is 1, 3, 5, 7, 8, 10, or 12;
+ {value: "2014-01-31", expected: "2014-01-31", testname: "January has 31 days"},
+ {value: "2014-01-32", expected: "", testname: "January has 31 days"},
+ {value: "2014-03-31", expected: "2014-03-31", testname: "March has 31 days"},
+ {value: "2014-03-32", expected: "", testname: "March has 31 days"},
+ {value: "2014-05-31", expected: "2014-05-31", testname: "May has 31 days"},
+ {value: "2014-05-32", expected: "", testname: "May has 31 days"},
+ {value: "2014-07-31", expected: "2014-07-31", testname: "July has 31 days"},
+ {value: "2014-07-32", expected: "", testname: "July has 31 days"},
+ {value: "2014-08-31", expected: "2014-08-31", testname: "August has 31 days"},
+ {value: "2014-08-32", expected: "", testname: "August has 31 days"},
+ {value: "2014-10-31", expected: "2014-10-31", testname: "October has 31 days"},
+ {value: "2014-10-32", expected: "", testname: "October has 31 days"},
+ {value: "2014-12-31", expected: "2014-12-31", testname: "December has 31 days"},
+ {value: "2014-12-32", expected: "", testname: "December has 31 days"},
+ // the number of days in month month of year year is: 30 if month is 4, 6, 9, or 11;
+ {value: "2014-04-30", expected: "2014-04-30", testname: "April has 30 days"},
+ {value: "2014-04-31", expected: "", testname: "April has 30 days"},
+ {value: "2014-06-30", expected: "2014-06-30", testname: "June has 30 days"},
+ {value: "2014-06-31", expected: "", testname: "June has 30 days"},
+ {value: "2014-09-30", expected: "2014-09-30", testname: "September has 30 days"},
+ {value: "2014-09-31", expected: "", testname: "September has 30 days"},
+ {value: "2014-11-30", expected: "2014-11-30", testname: "November has 30 days"},
+ {value: "2014-11-31", expected: "", testname: "November has 30 days"},
+ // leap years
+ {value: "2014-02-28", expected: "2014-02-28", testname: "2014 is not a leap year: February has 28 days"},
+ {value: "2014-02-29", expected: "", testname: "2014 is not a leap year: February has 28 days: value should be empty"},
+ {value: "2016-02-29", expected: "2016-02-29", testname: "2016 is a leap year: February has 29 days"}
+ ];
+ for (var i = 0; i < numDays.length; i++) {
+ var input = document.createElement("input");
+ input.type = "date";
+ input.value = numDays[i].value;
+ assert_equals(input.value, numDays[i].expected, numDays[i].testname);
+ }
+ }, "Number of days");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/datetime-2.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/datetime-2.html
new file mode 100644
index 00000000000..121dce8d25b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/datetime-2.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Form input type=datetime</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel=help href="https://html.spec.whatwg.org/multipage/multipage/common-microsyntaxes.html#global-dates-and-times">
+<link rel=help href="https://html.spec.whatwg.org/multipage/multipage/states-of-the-type-attribute.html#local-date-and-time-state-(type=datetime)">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+ var datetime = [
+ // valid values
+ {value: "", expected: "", testname: "empty value"},
+ {value: "2014-01-01T11:11Z", expected: "2014-01-01T11:11Z", testname: "datetime input value set to 2014-01-01T11:11Z without min/max"},
+ {value: "2014-01-01 11:11Z", expected: "2014-01-01T11:11Z", testname: "datetime input value set to 2014-01-01 11:11Z without min/max"},
+ {value: "2014-01-01 11:11-04:00", expected: "2014-01-01T15:11Z", testname: "datetime input value set to 2014-01-01 11:11-04:00 without min/max"},
+ {value: "2014-01-01 11:11-0400", expected: "2014-01-01T15:11Z", testname: "datetime input value set to 2014-01-01 11:11-0400 without min/max"},
+ {value: "2014-01-01 11:11:00.000-04:00", expected: "2014-01-01T15:11Z", testname: "datetime input value set to 2014-01-01 11:11:00.000-04:00 without min/max"},
+ // invalid values
+ {value: "2014-01-01 11:11:00.000Z", expected: "", testname: "datetime input value set to 2014-01-01 11:11:00.000Z without min/max"},
+ {value: "2014-01-01 11:11:00.000", expected: "", testname: "datetime input value set to 2014-01-01 11:11:00.000 without min/max"},
+ {value: "2014-01-01 11:11:00.000+", expected: "", testname: "datetime input value set to 2014-01-01 11:11:00.000+ without min/max"},
+ {value: "2014-01-01 11:11:00.000+24", expected: "", testname: "datetime input value set to 2014-01-01 11:11:00.000+24 without min/max"},
+ {value: "2014-01-01 11:11:00.000+2360", expected: "", testname: "datetime input value set to 2014-01-01 11:11:00.000+2360 without min/max"},
+ {value: "2014-01-0 11:11:00.000+0400", expected: "", testname: "datetime input value set to 2014-01-0 11:11:00.000+0400 without min/max"},
+ {value: "2014-01-01 11:1:00.000+0400", expected: "", testname: "datetime input value set to 2014-01-01 11:1:00.000+0400 without min/max"},
+ // min/max
+ {value: "2014-01-01 11:11Z", attributes: { min: "2014-01-01T11:10Z" }, expected: "2014-01-01T11:11Z", testname: "Value >= min attribute"},
+ {value: "2014-01-01 11:10Z", attributes: { min: "2014-01-01T11:11Z" }, expected: "2014-01-01T11:11Z", testname: "Value < min attribute"},
+ {value: "2014-01-01 11:10Z", attributes: { max: "2014-01-01T11:11Z" }, expected: "2014-01-01T11:11Z", testname: "Value <= max attribute"},
+ {value: "2014-01-01 11:11Z", attributes: { max: "2014-01-01T11:10Z" }, expected: "2014-01-01T11:10Z", testname: "Value > max attribute"}
+ ];
+ for (var i = 0; i < datetime.length; i++) {
+ var w = datetime[i];
+ test(function() {
+ var input = document.createElement("input");
+ input.type = "datetime";
+ input.value = w.value;
+ for(var attr in w.attributes) {
+ input[attr] = w.attributes[attr];
+ }
+ assert_equals(input.value, w.expected);
+ }, w.testname);
+ }
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/datetime-local.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/datetime-local.html
new file mode 100644
index 00000000000..b4548b77aac
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/datetime-local.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Form input type=datetime-local</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel=help href="https://html.spec.whatwg.org/multipage/multipage/common-microsyntaxes.html#local-dates-and-times">
+<link rel=help href="https://html.spec.whatwg.org/multipage/multipage/states-of-the-type-attribute.html#local-date-and-time-state-(type=datetime-local)">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+ var datetimeLocal = [
+ {value: "", expected: "", testname: "empty value"},
+ {value: "2014-01-01T11:11:11.111", expected: "2014-01-01T11:11:11.111", testname: "datetime-local input value set to 2014-01-01T11:11:11.111 without min/max"},
+ {value: "2014-01-01 11:11:11.111", expected: "2014-01-01T11:11:11.111", testname: "datetime-local input value set to 2014-01-01 11:11:11.111 without min/max"},
+ {value: "2014-01-01 11:11", expected: "2014-01-01T11:11", testname: "datetime-local input value set to 2014-01-01 11:11 without min/max"},
+ {value: "2014-01-01 00:00:00.000", expected: "2014-01-01T00:00", testname: "datetime-local input value set to 2014-01-01 00:00:00.000 without min/max"},
+ {value: "2014-01-0 11:11", expected: "", testname: "datetime-local input value set to 2014-01-0 11:11 without min/max"},
+ {value: "2014-01-01 11:1", expected: "", testname: "datetime-local input value set to 2014-01-01 11:1 without min/max"},
+ {value: "2014-01-01 11:12", attributes: { min: "2014-01-01 11:11" }, expected: "2014-01-01T11:12", testname: "Value >= min attribute"},
+ {value: "2014-01-01 11:10", attributes: { min: "2014-01-01 11:11" }, expected: "2014-01-01T11:11", testname: "Value < min attribute"},
+ {value: "2014-01-01 11:10", attributes: { max: "2014-01-01 11:11" }, expected: "2014-01-01T11:10", testname: "Value <= max attribute"},
+ {value: "2014-01-01 11:12", attributes: { max: "2014-01-01 11:11" }, expected: "2014-01-01T11:11", testname: "Value > max attribute"}
+ ];
+ for (var i = 0; i < datetimeLocal.length; i++) {
+ var w = datetimeLocal[i];
+ test(function() {
+ var input = document.createElement("input");
+ input.type = "datetime-local";
+ input.value = w.value;
+ for(var attr in w.attributes) {
+ input[attr] = w.attributes[attr];
+ }
+ assert_equals(input.value, w.expected);
+ }, w.testname);
+ }
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/datetime.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/datetime.html
new file mode 100644
index 00000000000..2e909da2d0c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/datetime.html
@@ -0,0 +1,106 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Date & Time Inputs</title>
+ <meta name=viewport content="width=device-width, maximum-scale=1.0, user-scalable=no" />
+ <link rel="author" title="Fabrice Clari" href="mailto:f.clari@inno-group.com">
+ <link rel="author" title="Dimitri Bocquet" href="mailto:Dimitri.Bocquet@mosquito-fp7.eu">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-input-element">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+
+ <h1>Date & Time Inputs</h1>
+ <div style="display: none">
+ <input type="date" value="2011-12-01" min="2011-12-01" max="2011-12-31" step="5" />
+ <input type="time" value= "12:00" min="11:30" max="14:00" step="600" />
+ <input type="datetime" value="2011-12-01T12:00Z" min="2011-12-01T12:00Z" max="2011-12-31T22:00Z" step="7200" />
+ <input type="month" value="2011-01" min="2011-01" max="2011-12" step="2" />
+ <input type="week" value="2011-W40" min="2011-W20" max="2011-W50" step="2" />
+ </div>
+
+ <div id="log">
+ </div>
+
+ <script type="text/javascript">
+ test(function() {assert_equals(document.getElementsByTagName("input")[0].type, "date")}, "date type support on input element", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-type" });
+ test(function() {assert_equals(document.getElementsByTagName("input")[0].value, "2011-12-01")}, "[date] The value must be a valid global date and time string", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-value" });
+ test(function() {assert_equals(document.getElementsByTagName("input")[0].min, "2011-12-01")}, "[date] The min attribute must have a value that is a valid global date and time string", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-min" });
+ test(function() {assert_equals(document.getElementsByTagName("input")[0].max, "2011-12-31")}, "[date] The max attribute must have a value that is a valid global date and time string", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-max" });
+ test(function() {assert_equals(document.getElementsByTagName("input")[0].step, "5")}, "[date] The step attribute must be expressed in seconds", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-step" });
+ test(function() {assert_true(typeof(document.getElementsByTagName("input")[0].stepUp) == "function")}, "[date] stepUp method support on input 'date' element", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-stepup" });
+ test(function() {assert_true(typeof(document.getElementsByTagName("input")[0].stepDown) == "function")}, "[date] stepDown method support on input 'date' element", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-stepdown" });
+
+ test(function() {assert_equals(document.getElementsByTagName("input")[1].type, "time")}, "[time] time type support on input element", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-type" });
+ test(function() {assert_equals(document.getElementsByTagName("input")[1].value, "12:00")}, "[time] The value must be a valid global date and time string", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-value" });
+ test(function() {assert_equals(document.getElementsByTagName("input")[1].min, "11:30")}, "[time] The min attribute must have a value that is a valid global date and time string", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-min" });
+ test(function() {assert_equals(document.getElementsByTagName("input")[1].max, "14:00")}, "[time] The max attribute must have a value that is a valid global date and time string", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-max" });
+ test(function() {assert_equals(document.getElementsByTagName("input")[1].step, "600")}, "[time] The step attribute must be expressed in seconds", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-step" });
+ test(function() {assert_true(typeof(document.getElementsByTagName("input")[1].stepUp) == "function")}, "[time] stepUp method support on input 'time' element", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-stepup" });
+ test(function() {assert_true(typeof(document.getElementsByTagName("input")[1].stepDown) == "function")}, "[time] stepDown method support on input 'time' element", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-stepdown" });
+
+ test(function() {assert_equals(document.getElementsByTagName("input")[2].type, "datetime")}, "datetime type support on input element", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-type" });
+ test(function() {assert_equals(document.getElementsByTagName("input")[2].value, "2011-12-01T12:00Z")}, "[datetime] The must be a valid global date and time string", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-value" });
+ test(function() {assert_equals(document.getElementsByTagName("input")[2].min, "2011-12-01T12:00Z")}, "[datetime] The min attribute must have a value that is a valid global date and time string", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-min" });
+ test(function() {assert_equals(document.getElementsByTagName("input")[2].max, "2011-12-31T22:00Z")}, "[datetime] The max attribute must have a value that is a valid global date and time string", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-max" });
+ test(function() {assert_equals(document.getElementsByTagName("input")[2].step, "7200")}, "[datetime] The step attribute must be expressed in seconds", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-step" });
+ test(function() {assert_true(typeof(document.getElementsByTagName("input")[2].stepUp) == "function")}, "[datetime] stepUp method support on input 'datetime' element", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-stepup" });
+ test(function() {assert_true(typeof(document.getElementsByTagName("input")[2].stepDown) == "function")}, "[datetime] stepDown method support on input 'datetime' element", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-stepdown" });
+
+ test(function() {assert_equals(document.getElementsByTagName("input")[3].type, "month")}, "month type support on input element", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-type" });
+ test(function() {assert_equals(document.getElementsByTagName("input")[3].value, "2011-01")}, "[month] The value must be a value that is a valid global date and time string", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-value" });
+ test(function() {assert_equals(document.getElementsByTagName("input")[3].min, "2011-01")}, "[month] The min attribute must have a value that is a valid global date and time string", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-min" });
+ test(function() {assert_equals(document.getElementsByTagName("input")[3].max, "2011-12")}, "[month] The max attribute must have a value that is a valid global date and time string", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-max" });
+ test(function() {assert_equals(document.getElementsByTagName("input")[3].step, "2")}, "[month] The step attribute must be expressed in seconds", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-step" });
+ test(function() {assert_true(typeof(document.getElementsByTagName("input")[3].stepUp) == "function")}, "[month] stepUp method support on input 'month' element", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-stepup" });
+ test(function() {assert_true(typeof(document.getElementsByTagName("input")[3].stepDown) == "function")}, "[month] stepDown method support on input 'month' element", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-stepdown" });
+
+ test(function() {assert_equals(document.getElementsByTagName("input")[4].type, "week")}, "week type support on input element", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-type" });
+ test(function() {assert_equals(document.getElementsByTagName("input")[4].value, "2011-W40")}, "[week] The value must be a value that is a valid global date and time string", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-value" });
+ test(function() {assert_equals(document.getElementsByTagName("input")[4].min, "2011-W20")}, "[week] The min attribute must have a value that is a valid global date and time string", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-min" });
+ test(function() {assert_equals(document.getElementsByTagName("input")[4].max, "2011-W50")}, "[week] The max attribute must have a value that is a valid global date and time string", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-max" });
+ test(function() {assert_equals(document.getElementsByTagName("input")[4].step, "2")}, "[week] The step attribute must be expressed in seconds", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-step" });
+ test(function() {assert_true(typeof(document.getElementsByTagName("input")[4].stepUp) == "function")}, "[week] stepUp method support on input 'week' element", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-stepup" });
+ test(function() {assert_true(typeof(document.getElementsByTagName("input")[4].stepDown) == "function")}, "[week] stepDown method support on input 'week' element", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-stepdown" });
+
+ </script>
+
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/email.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/email.html
new file mode 100644
index 00000000000..b154ab93c78
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/email.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<title>Input Email</title>
+<link rel="author" title="Kazuki Kanamori" href="mailto:yogurito@gmail.com">
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#e-mail-state-(type=email)">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<input type="email" id="single_email" value="user@example.com"/>
+<input type="email" id="multiple_email" value="user1@example.com, user2@test.com" multiple/>
+<div id="log"></div>
+
+<script type="text/javascript">
+ var single = document.getElementById('single_email'),
+ mult = document.getElementById('multiple_email'),
+
+ test(function(){
+ assert_false(single.multiple);
+ }, "single_email doesn't have the multiple attribute");
+
+ test(function(){
+ single.value = 'user2@example.com\u000A';
+ assert_equals(single.value, 'user2@example.com');
+ single.value = 'user3@example.com\u000D';
+ assert_equals(single.value, 'user3@example.com');
+ }, 'value should be sanitized: strip line breaks');
+
+ test(function(){
+ single.value = 'user4@example.com';
+ assert_true(single.validity.valid);
+ single.value = 'example.com';
+ assert_false(single.validity.valid);
+ }, 'Email address validity');
+
+ test(function(){
+ single.setAttribute('multiple', true);
+ single.value = ' user@example.com , user2@example.com ';
+ assert_equals(single.value, 'user@example.com,user2@example.com');
+ single.removeAttribute('multiple');
+ assert_equals(single.value, 'user@example.com,user2@example.com');
+ }, 'When the multiple attribute is removed, the user agent must run the value sanitization algorithm');
+
+ test(function(){
+ assert_true(mult.multiple);
+ }, "multiple_email has the multiple attribute");
+
+ test(function(){
+ mult.value = ' user1@example.com , user2@test.com, user3@test.com ';
+ assert_equals(mult.value, 'user1@example.com,user2@test.com,user3@test.com');
+ }, "run the value sanitization algorithm after setting a new value");
+
+ test(function(){
+ mult.value = 'user1@example.com,user2@test.com,user3@test.com';
+ assert_true(mult.validity.valid);
+
+ mult.value = 'u,ser1@example.com,user2@test.com,user3@test.com';
+ assert_false(mult.validity.valid);
+ }, "valid value is a set of valid email addresses separated by a single ','");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/file-manual.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/file-manual.html
new file mode 100644
index 00000000000..3340239881b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/file-manual.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>input type file</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#file-upload-state-(type=file)">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<p>Manual test: clicking on the input should open a prompt allowing you to select a file.</p>
+<input type=file id=file>
+<script>
+ setup({explicit_timeout:true});
+
+ var input = document.getElementById('file'),
+ t1 = async_test("selecting files should fire the input event at the input element"),
+ t2 = async_test("selecting files should fire the change event at the input element");
+
+ document.getElementById('file').oninput = t1.step_func_done(function(e) {
+ assert_true(e.bubbles, "input event bubbles");
+ assert_true(e.isTrusted, "input event should be trusted");
+ assert_false(e.cancelable, "input event shoud not be cancelable");
+ })
+ document.getElementById('file').onchange = t2.step_func_done(function(e) {
+ assert_true(e.bubbles, "change event bubbles");
+ assert_true(e.isTrusted, "change event should be trusted");
+ assert_false(e.cancelable, "change event shoud not be cancelable");
+ assert_true(input.files instanceof FileList);
+ assert_equals(input.value, "C:\\fakepath\\" + input.files[0].name);
+ })
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/files.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/files.html
new file mode 100644
index 00000000000..f2fac99bbf5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/files.html
@@ -0,0 +1,49 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>HTMLInputElement#files</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var types = [
+ "hidden",
+ "text",
+ "search",
+ "tel",
+ "url",
+ "email",
+ "password",
+ "datetime",
+ "date",
+ "month",
+ "week",
+ "time",
+ "datetime-local",
+ "number",
+ "range",
+ "color",
+ "checkbox",
+ "radio",
+ "submit",
+ "image",
+ "reset",
+ "button",
+];
+
+types.forEach(function(type) {
+ test(function() {
+ var input = document.createElement("input");
+ input.type = type;
+ assert_equals(input.files, null, "files should be null");
+ }, "files for input type=" + type);
+});
+
+test(function() {
+ var input = document.createElement("input");
+ input.type = "file";
+ assert_not_equals(input.files, null);
+ assert_true(input.files instanceof FileList, "files should be a FileList");
+ var files = input.files;
+ assert_equals(input.files, files, "files should return the same object");
+}, "files for input type=file");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/hidden.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/hidden.html
new file mode 100644
index 00000000000..4aca00d8c6b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/hidden.html
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Hidden input element</title>
+ <link rel="author" title="Kinuko Yasuda" href="mailto:kinuko@chromium.org">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#hidden-state-(type=hidden)">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+
+ <body>
+ <h1>Hidden input element</h1>
+ <div style="display: none">
+
+ <input id="hidden" type="hidden" />
+ <input id="hidden_with_value" type="hidden" value="foo" />
+
+ </div>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ test(
+ function() {
+ assert_equals(document.getElementById("hidden").value, "");
+ assert_equals(document.getElementById("hidden_with_value").value, "foo");
+ }, "Value returns the current value for hidden");
+
+ test(
+ function() {
+ document.getElementById("hidden").value = "A";
+ assert_equals(document.getElementById("hidden").value, "A");
+ document.getElementById("hidden").value = "B";
+ assert_equals(document.getElementById("hidden").value, "B");
+ }, "Setting value changes the current value for hidden");
+
+ test(
+ function() {
+ assert_equals(document.getElementById("hidden").files, null);
+ }, "files attribute must return null for hidden");
+
+ test(
+ function() {
+ assert_equals(document.getElementById("hidden").valueAsDate, null);
+ }, "valueAsDate attribute must return null for hidden");
+
+ test(
+ function() {
+ assert_equals(document.getElementById("hidden").valueAsNumber, NaN);
+ }, "valueAsNumber attribute must return NaN for hidden");
+
+ test(
+ function() {
+ assert_equals(document.getElementById("hidden").list, null);
+ }, "list attribute must return null for hidden");
+
+ test(
+ function() {
+ var el = document.getElementById("hidden");
+ assert_throws("InvalidStateError", function() { el.stepDown(); }, "");
+ }, "stepDown does not apply for hidden");
+
+ test(
+ function() {
+ var el = document.getElementById("hidden");
+ assert_throws("InvalidStateError", function() { el.stepUp(); }, "");
+ }, "stepUp does not apply for hidden");
+
+ test(function(){
+ var el = document.getElementById("hidden");
+ assert_false(el.willValidate);
+ }, "input type=hidden is barred from constraint validation");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/image01-ref.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/image01-ref.html
new file mode 100644
index 00000000000..62c141d960d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/image01-ref.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>input type image reference file</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<img src="/media/poster.png"/>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/image01.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/image01.html
new file mode 100644
index 00000000000..e9028dceec7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/image01.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>input type image</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#image-button-state-(type=image)">
+<link rel="match" href="image01-ref.html">
+<input type=image id=image src="/media/poster.png">
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/input-textselection-01.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/input-textselection-01.html
new file mode 100644
index 00000000000..df7c52567e8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/input-textselection-01.html
@@ -0,0 +1,42 @@
+<!DOCTYPE HTML>
+<title>The selection interface members</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#textFieldSelection">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ var valid = ["text", "search", "url", "tel", "email", "password"];
+ var invalid = ["hidden", "datetime", "date", "month", "week", "datetime-local",
+ "number", "range", "color", "checkbox", "radio", "button",
+ "file", "submit", "image", "reset"];
+ valid.forEach(function(aType) {
+ test(function() {
+ var input = document.createElement("input");
+ input.type = aType;
+ assert_equals(input.type, aType, "Input type unsupported")
+ input.select();
+ var a = input.selectionStart;
+ input.selectionStart = 0;
+ a = input.selectionEnd;
+ input.selectionEnd = 0;
+ input.setSelectionRange(0, 0);
+ }, "Selection attributes should apply to type " + aType)
+ })
+
+ invalid.forEach(function(aType) {
+ test(function() {
+ var input = document.createElement("input");
+ input.type = aType;
+ assert_equals(input.type, aType, "Input type unsupported")
+ assert_throws("INVALID_STATE_ERR", function() { input.select(); }, "Should throw with type " + aType);
+ assert_throws("INVALID_STATE_ERR", function() { var a = input.selectionStart; });
+ assert_throws("INVALID_STATE_ERR", function() { input.selectionStart = 0; });
+ assert_throws("INVALID_STATE_ERR", function() { var a = input.selectionEnd; });
+ assert_throws("INVALID_STATE_ERR", function() { input.selectionEnd = 0; });
+ assert_throws("INVALID_STATE_ERR", function() { input.setSelectionRange(0, 0); });
+ }, "Selection attributes should not apply to type " + aType)
+ })
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/input-type-button.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/input-type-button.html
new file mode 100644
index 00000000000..0f269355a51
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/input-type-button.html
@@ -0,0 +1,51 @@
+<!DOCTYPE HTML>
+<head>
+<title>input type button</title>
+<link rel="author" title="Takeharu.Oshida" href="mailto:georgeosddev@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#button-state-(type=button)">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id="log"></div>
+<div id="hide" style="display">
+ <input type="button"/>
+ <input type="button" value="BUTTON"/>
+ <form action="/" method="get" onsubmit="isSubmitted = true;return false;">
+ <input type="button" value="mutable"/>
+ </form>
+ <form action="/" method="get" onsubmit="isSubmitted = true;return false;">
+ <input type="button" value="immutable" disabled/>
+ </form>
+</div>
+<script>
+var isSubmitted = false;
+var buttons = document.getElementsByTagName("input");
+
+test(function() {
+ assert_equals(buttons[0].click(), undefined, "The input element represents a button with no default behavior");
+},"default behavior");
+
+test(function() {
+ assert_equals(buttons[0].value, "", "It must be the empty string");
+},"empty value attribute");
+
+test(function() {
+ document.getElementById("hide").style.display = "block";
+ assert_not_equals(buttons[0].offsetWidth, buttons[1].offsetWidth, "If the element has a value attribute, the button's label must be the value of that attribute");
+ document.getElementById("hide").style.display = "none";
+},"label value");
+
+test(function() {
+ isSubmitted = false;
+ buttons[2].click();
+ assert_equals(isSubmitted, false, "If the element is mutable, the element's activation behavior is to do nothing.");
+},"mutable element's activation behavior is to do nothing.");
+
+test(function() {
+ isSubmitted = false;
+ buttons[3].click()
+ assert_equals(isSubmitted, false, "If the element is immutable, the element has no activation behavior.");
+},"immutable element has no activation behavior.");
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/input-type-checkbox.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/input-type-checkbox.html
new file mode 100644
index 00000000000..7dd2f26b12c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/input-type-checkbox.html
@@ -0,0 +1,60 @@
+<!DOCTYPE HTML>
+<head>
+<title>input type checkbox</title>
+<link rel="author" title="Gary Gao" href="mailto:angrytoast@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#checkbox-state-(type=checkbox)">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div style="display:none;">
+ <input id="checkbox_default" type="checkbox" width="20" />
+
+ <input id="checkbox_checked" type="checkbox" checked />
+
+ <input id="checkbox_indeterminate" type="checkbox" />
+
+ <input id="checkbox_default_value" type="checkbox" />
+</div>
+
+<div id="log"></div>
+
+<script>
+ var checkbox_default = document.getElementById('checkbox_default'),
+ checkbox_checked = document.getElementById('checkbox_checked'),
+ checkbox_indeterminate = document.getElementById('checkbox_indeterminate'),
+ checkbox_default_value = document.getElementById('checkbox_default_value');
+
+ test(function() {
+ assert_false(checkbox_default.checked);
+ }, "default checkbox has no checkedness state");
+
+ test(function() {
+ assert_true(checkbox_checked.checked);
+ }, "checkbox with initial state set to checked has checkedness state");
+
+ test(function() {
+ checkbox_default.checked = 'chicken'
+ assert_true(checkbox_default.checked);
+ }, "changing the checked attribute to a string sets the checkedness state");
+
+ test(function() {
+ assert_false(checkbox_indeterminate.indeterminate);
+ }, "a checkbox has an indeterminate state set to false onload");
+
+ test(function() {
+ checkbox_indeterminate.indeterminate = true,
+ assert_true(checkbox_indeterminate.indeterminate);
+ }, "on setting, a checkbox's indeterminate state must be set to the new value and returns the last value it was set to");
+
+ test(function() {
+ assert_equals(checkbox_default_value.value, 'on');
+ }, "default/on: on getting, if the element has a value attribute, it must return that attribute's value; otherwise, it must return the string 'on'");
+
+ test(function() {
+ checkbox_default_value.value = 'chicken'
+ assert_equals(checkbox_default_value.value, 'chicken');
+ }, "on getting, if the element has a value attribute, it must return that attribute's value");
+</script>
+
+</body>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/month.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/month.html
new file mode 100644
index 00000000000..198fb9f3a82
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/month.html
@@ -0,0 +1,93 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Inputs Month</title>
+ <link rel="author" title="Morishita Hiromitsu" href="mailto:hero@asterisk-works.jp">
+ <link rel="author" title="kaseijin" href="mailto:pcmkas@gmail.com">
+ <link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#months">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#month-state-(type=month)">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <h1>Inputs Month</h1>
+ <div style="display: none">
+ <input id="valid" type="month" value="2011-11" min="2011-01" max="2011-12" />
+ <input id="too_small_value" type="month" value="1999-01" min="2011-01" max="2011-12"/>
+ <input id="too_large_value" type="month" value="2099-01" min="2011-01" max="2011-12"/>
+ <input id="invalid_value" type="month" value="invalid-month" min="2011-01" max="2011-12"/>
+ <input id="invalid_min" type="month" value="2011-01" min="invalid_min" max="2011-12"/>
+ <input id="invalid_max" type="month" value="2011-01" min="2011-01" max="invalid_max"/>
+ <input id="min_larger_than_max" type="month" value="2011-01" min="2099-01" max="2011-12"/>
+ <input id="value_can_be_empty_string" type="month" value="2013-06" />
+ <input id="invalid_value_with_two_digits_year" type="month" value="13-06" />
+ <input id="invalid_value_is_set" type="month" />
+ <input id="invalid_value_is_set_to_valid_value" type="month" value="2013-05" />
+ <input id="step_attribute_is_invalid_value" type="month" value="2013-06" step="invalid_step_value" />
+ <input id="invalid_month_too_high" type="month" value="2013-13" />
+ <input id="invalid_month_too_low" type="month" value="2013-00" />
+ </div>
+
+ <div id="log"></div>
+
+ <script>
+ test(function() {
+ assert_equals(document.getElementById("valid").type, "month")
+ }, "month type support on input element");
+
+ test(function() {
+ assert_equals(document.getElementById("valid").value, "2011-11"),
+ assert_equals(document.getElementById("too_small_value").value, "2011-01"),
+ assert_equals(document.getElementById("too_large_value").value, "2011-12")
+ }, "The value attribute, if specified and not empty, must have a value that is a valid month string");
+
+ test(function() {
+ assert_equals(document.getElementById("valid").min, "2011-01"),
+ assert_equals(document.getElementById("invalid_min").min, "")
+ }, "The min attribute, if specified, must have a value that is a valid month string.");
+
+ test(function() {
+ assert_equals(document.getElementById("valid").max, "2011-12"),
+ assert_equals(document.getElementById("min_larger_than_max").max, "2099-01"),
+ assert_equals(document.getElementById("invalid_max").max, "")
+ }, "The max attribute, if specified, must have a value that is a valid month string");
+
+ test(function() {
+ assert_equals(document.getElementById("invalid_value").value, "")
+ }, "User agents must not allow the user to set the value to a non-empty string that is not a valid month string.");
+
+ test(function() {
+ document.getElementById("value_can_be_empty_string").value = "";
+ assert_equals(document.getElementById("value_can_be_empty_string").value, "")
+ }, "Month value can be empty string.");
+
+ test(function() {
+ assert_equals(document.getElementById("invalid_value_with_two_digits_year").value, "")
+ }, "When value attribute has two digits year value, the value,which is invalid, must return empty string.");
+
+ test(function() {
+ document.getElementById("invalid_value_is_set").value = "invalid value";
+ assert_equals(document.getElementById("invalid_value_is_set").value, "")
+ }, "When value is set with invalid value, the value must return empty string.");
+
+ test(function() {
+ document.getElementById("invalid_value_is_set_to_valid_value").value = "invalid value";
+ assert_equals(document.getElementById("invalid_value_is_set_to_valid_value").value, "2013-05")
+ }, "When value is given invalid value to non-empty valid string, the value must be same as before.");
+
+ test(function() {
+ document.getElementById("step_attribute_is_invalid_value").stepUp();
+ assert_equals(document.getElementById("step_attribute_is_invalid_value").value, "2013-07")
+ }, "When step attribute is given invalid value, it must ignore the invalid value and use defaul value instead.");
+
+ test(function() {
+ assert_equals(document.getElementById("invalid_month_too_high").value, "");
+ }, "Month should be <= 13: If the value of the element is not a valid month string, then set it to the empty string instead.");
+
+ test(function() {
+ assert_equals(document.getElementById("invalid_month_too_low").value, "");
+ }, "Month should be > 0: If the value of the element is not a valid month string, then set it to the empty string instead.>");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/number.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/number.html
new file mode 100644
index 00000000000..5067d0e2fdd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/number.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Form input type=number</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#password-state-(type=number)">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+ var numbers = [
+ {value: "", expected: "", testname: "empty value"},
+ {value: "11", expected: "11", testname: "value = 11"},
+ {value: "11.12", expected: "11.12", testname: "value = 11.12"},
+ {value: "-11111", expected: "-11111", testname: "value = -11111"},
+ {value: "-11111.123", expected: "-11111.123", testname: "value = -11111.123"},
+ {value: "1e2", expected: "1e2", testname: "value = 1e2"},
+ {value: "1E2", expected: "1E2", testname: "value = 1E2"},
+ {value: "1e+2", expected: "1e+2", testname: "value = 1e+2"},
+ {value: "1e-2", expected: "1e-2", testname: "value = 1e-2"},
+ {value: "1d+2", expected: "", testname: "value is not a valid floating-point number: 1d+2"},
+ {value: "foobar", expected: "", testname: "value not a valid floating-point number: random string"},
+ {value: "11", attributes: { min: "10" }, expected: "11", testname: "Value >= min attribute"},
+ {value: "9", attributes: { min: "10" }, expected: "9", testname: "Value < min attribute"},
+ {value: "19", attributes: { max: "20" }, expected: "19", testname: "Value <= max attribute"},
+ {value: "21", attributes: { max: "20" }, expected: "21", testname: "Value > max attribute"},
+ {value: ".1", expected: ".1", testname: "value with a leading '.'"},
+ {value: "1.", expected: "", testname: "value ending with '.'"},
+ {value: "-0", expected: "-0", testname: "value = -0"},
+ {value: "Infinity", expected: "", testname: " value = Infinity"},
+ {value: "-Infinity", expected: "", testname: "value = -Infinity"},
+ {value: "NaN", expected: "", testname: "value = NaN"},
+ {value: "9007199254740993", expected: "9007199254740992", testname: "value = 2^53+1"},
+ {value: "2e308", expected: "", testname: "value >= Number.MAX_VALUE"},
+ {value: "1e", expected: "", testname: "value = 1e"},
+ {value: "+1", expected: "1", testname: "value = +1"},
+ {value: "+", expected: "", testname: "value = '+'"},
+ {value: "-", expected: "", testname: "value = '-'"},
+ {value: " 1", expected: "1", testname: "value with a leading whitespace"},
+ {value: "1trailing junk", expected: "1", testname: "value = 1trailing junk"}
+ ];
+ for (var i = 0; i < numbers.length; i++) {
+ var w = numbers[i];
+ test(function() {
+ var input = document.createElement("input");
+ input.type = "number";
+ input.value = w.value;
+ for(var attr in w.attributes) {
+ input[attr] = w.attributes[attr];
+ }
+ assert_equals(input.value, w.expected);
+ }, w.testname);
+ }
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/password.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/password.html
new file mode 100644
index 00000000000..aac54aa1c72
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/password.html
@@ -0,0 +1,79 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Password input element</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#password-state-%28type=password%29">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<div style="display: none">
+<input id="password" type="password" />
+<input id=password2 type=password value="password">
+<input id="password_with_value" type="password" value="foobar" />
+</div>
+<script type="text/javascript">
+ setup(function() {
+ window.password = document.getElementById("password");
+ });
+
+ test(function() {
+ assert_equals(password.value, "");
+ assert_equals(document.getElementById("password_with_value").value, "foobar");
+ }, "Value returns the current value for password");
+
+ test(function() {
+ password.value = "A";
+ assert_equals(password.value, "A");
+ assert_equals(password.getAttribute("value"), null);
+ password.value = "B";
+ assert_equals(password.value, "B");
+ assert_equals(password.getAttribute("value"), null);
+ }, "Setting value changes the current value for password, but not the value content attribute");
+
+ test(function() {
+ // Any LF (\n) must be stripped.
+ password.value = "\nAB";
+ assert_equals(password.value, "AB");
+ password.value = "A\nB";
+ assert_equals(password.value, "AB");
+ password.value = "AB\n";
+ assert_equals(password.value, "AB");
+
+ // Any CR (\r) must be stripped.
+ password.value = "\rAB";
+ assert_equals(password.value, "AB");
+ password.value = "A\rB";
+ assert_equals(password.value, "AB");
+ password.value = "AB\r";
+ assert_equals(password.value, "AB");
+
+ // Any combinations of LF CR must be stripped.
+ password.value = "\r\nAB";
+ assert_equals(password.value, "AB");
+ password.value = "A\r\nB";
+ assert_equals(password.value, "AB");
+ password.value = "AB\r\n";
+ assert_equals(password.value, "AB");
+ password.value = "\r\nA\n\rB\r\n";
+ assert_equals(password.value, "AB");
+ }, "Value sanitization algorithm should strip line breaks for password");
+
+ var pass = document.getElementById('password2');
+
+ test(function(){
+ assert_equals(pass.value, "password");
+ pass.value = " pass word ";
+ assert_equals(pass.value, " pass word ");
+ }, "sanitization algorithm doesn't strip leading and trailing whitespaces");
+
+ test(function(){
+ pass.value = "pass\u000Aword";
+ assert_equals(pass.value, "password");
+ pass.value = "\u000Apassword\u000A";
+ assert_equals(pass.value, "password");
+ pass.value = "pass\u000Dword";
+ assert_equals(pass.value, "password");
+ pass.value = "\u000Dpassword\u000D";
+ assert_equals(pass.value, "password");
+ }, "sanitization algorithm strips line breaks");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/pattern_attribute.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/pattern_attribute.html
new file mode 100644
index 00000000000..01e19a808f8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/pattern_attribute.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+
+ <head>
+ <title>Pattern Attribute</title>
+ <meta name=viewport content="width=device-width, maximum-scale=1.0, user-scalable=no" />
+ <link rel="author" title="Fabrice Clari" href="mailto:f.clari@inno-group.com">
+ <link rel="author" title="Dimitri Bocquet" href="mailto:Dimitri.Bocquet@mosquito-fp7.eu">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#attr-input-pattern">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+
+ <body>
+
+
+ <h1>Pattern Attribute</h1>
+ <div style="display: none">
+ <input pattern="[a-z]{3}" value="abcd" title="three letters max"/>
+ </div>
+
+ <div id="log">
+ </div>
+
+ <script type="text/javascript">
+
+
+ test(function() {assert_equals(document.getElementsByTagName("input")[0].getAttribute("pattern"), "[a-z]{3}")}, "pattern attribute support on input element");
+
+ </script>
+
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/radio-groupname-case.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/radio-groupname-case.html
new file mode 100644
index 00000000000..05192fc7df4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/radio-groupname-case.html
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>radio group name compatibility caseless</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel="help" href="http://people.mozilla.org/~jdaggett/tests/radiobuttonnamecase.html">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<input id=r1 type="radio" name="sImPlE">
+<input id=r2 type="radio" name="simple">
+<input id=r3 type="radio" name="SIMPLE">
+
+<input id=r4 type="radio" name="paSSfield-killroyß">
+<input id=r5 type="radio" name="passfield-killroyß">
+<input id=r6 type="radio" name="PASSFIELD-KILLROYß">
+<input id=r7 type="radio" name="paſſfield-killroyß">
+<input id=r8 type="radio" name="passfield-&#x212a;illroyß">
+<input id=r9 type="radio" name="paßfield-killroyß">
+<input id=r10 type="radio" name="paẞfield-killroyß">
+<input id=r11 type="radio" name="passfield-killroyẞ">
+<input id=r12 type="radio" name="passfield-killroyß">
+<input id=r13 type="radio" name="passfıeld-killroyß">
+<input id=r14 type="radio" name="passfİeld-killroyß">
+
+<input id=r15 type="radio" name="глупый">
+<input id=r16 type="radio" name="глупы&#x438;&#x306;">
+<input id=r17 type="radio" name="ГЛУПЫЙ">
+<input id=r18 type="radio" name="ГЛУПЫ&#x418;&#x306;">
+
+<input id=r19 type="radio" name="åωk">
+<input id=r20 type="radio" name="ÅΩK">
+<input id=r21 type="radio" name="&#x212b;ωk">
+<input id=r22 type="radio" name="å&#x2126;k">
+<input id=r23 type="radio" name="åω&#x212a;">
+
+<input id=r24 type="radio" name="blah1">
+<input id=r25 type="radio" name="blah&#x2460;">
+<input id=r26 type="radio" name="bl&#x24b6;h1">
+<input id=r27 type="radio" name="bl&#x24d0;h1">
+
+<input id=r28 type="radio" name="t&Eacute;dz5アパートFi">
+<input id=r29 type="radio" name="T&Eacute;DZ5アパートFi">
+<input id=r30 type="radio" name="T&eacute;&#x01F1;&#x2075;アパートFi">
+<input id=r31 type="radio" name="t&Eacute;dz5&#x3300;Fi">
+<input id=r32 type="radio" name="t&Eacute;dz5&#x30A2;&#x30CF;&#x309A;&#x30FC;&#x30C8;Fi">
+<input id=r33 type="radio" name="t&Eacute;dz5&#x30A2;&#x30D1;&#x30FC;&#x30C8;Fi">
+<input id=r34 type="radio" name="T&Eacute;DZ⁵アパートFi">
+<input id=r35 type="radio" name="T&Eacute;DZ5アパートfi">
+
+<input id=r36 type="radio" name="ΣΣ">
+<input id=r37 type="radio" name="σς">
+<script>
+ var groups = [["r1" ,"r2", "r3"],
+ ["r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13", "r14"],
+ ["r15", "r16", "r17", "r18"],
+ ["r19", "r20", "r21", "r22", "r23"],
+ ["r24", "r25", "r26", "r27"],
+ ["r28", "r29", "r30", "r31", "r32", "r33", "r34", "r35"],
+ ["r36", "r37"]],
+ groupName = ["sImPlE", "paSSfield-killroyß", "глупый", "åωk", "blah1", "tÉdz5アパートFi", "ΣΣ"];
+ groups.forEach(function(group, index) {
+ test(function(){
+ group.forEach(function(radioId) {
+ assert_false(document.getElementById(radioId).checked);
+ });
+ for (var i = 0; i < group.length; i++) {
+ document.getElementById(group[i]).checked = true;
+ assert_true(document.getElementById(group[i]).checked);
+ for (var j = 0; j < group.length; j++) {
+ if (j != i) assert_false(document.getElementById(group[j]).checked);
+ }
+ }
+ }, "radio button group name = " + groupName[index]);
+ });
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/radio.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/radio.html
new file mode 100644
index 00000000000..3c4fea2a617
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/radio.html
@@ -0,0 +1,137 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>input type radio</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#radio-button-state-(type=radio)">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<input type=radio name=group1 id=radio1>
+<input type=radio name=group1 id=radio2>
+
+<input type=radio name=groüp2 id=radio3>
+<input type=radio name=groÜp2 id=radio4>
+
+<input type=radio id=radio5>
+<input type=radio id=radio6 disabled>
+
+<input type=radio id=radio71 checked>
+<input type=radio id=radio72>
+
+<input type=radio name=group3 id=radio8 checked>
+<input type=radio name=group3 id=radio9>
+<input type=radio name=group4 id=radio10>
+<input type=radio name=group4 id=radio11 checked>
+
+
+<script>
+ var radio1 = document.getElementById('radio1'),
+ radio2 = document.getElementById('radio2'),
+ radio3 = document.getElementById('radio3'),
+ radio4 = document.getElementById('radio4'),
+ radio5 = document.getElementById('radio5'),
+ radio6 = document.getElementById('radio6'),
+ radio71 = document.getElementById('radio71'),
+ radio72 = document.getElementById('radio72'),
+ radio8 = document.getElementById('radio8'),
+ radio9 = document.getElementById('radio9'),
+ radio10 = document.getElementById('radio10'),
+ radio11 = document.getElementById('radio11'),
+ t1 = async_test("click on mutable radio fires the input event"),
+ t2 = async_test("click on mutable radio fires the change event"),
+ t3 = async_test("click on non-mutable radio doesn't fire the input event"),
+ t4 = async_test("click on non-mutable radio doesn't fire the change event"),
+ t5 = async_test("canceled activation steps on unchecked radio"),
+ input_fired = false,
+ change_fired = false;
+
+ test(function(){
+ assert_false(radio1.checked);
+ assert_false(radio2.checked);
+ radio1.checked = true;
+ assert_true(radio1.checked);
+ assert_false(radio2.checked);
+ radio2.checked = true;
+ assert_false(radio1.checked);
+ assert_true(radio2.checked);
+ }, "only one control of a radio button group can have its checkedness set to true");
+
+ test(function(){
+ assert_false(radio3.checked);
+ assert_false(radio4.checked);
+ radio3.checked = true;
+ assert_true(radio3.checked);
+ assert_false(radio4.checked);
+ radio4.checked = true;
+ assert_false(radio3.checked);
+ assert_true(radio4.checked);
+ }, "radio inputs with name attributes groüp2 and groÜp2 belong to the same radio button group");
+
+ test(function(){
+ assert_true(radio8.checked);
+ assert_false(radio9.checked);
+ assert_false(radio10.checked);
+ assert_true(radio11.checked);
+ radio9.name="group4";
+ radio9.checked = true;
+ assert_true(radio8.checked);
+ assert_true(radio9.checked);
+ assert_false(radio10.checked);
+ assert_false(radio11.checked);
+ }, "changing the name of a radio input element and setting its checkedness to true makes all the other elements' checkedness in the same radio button group be set to false");
+
+ radio5.oninput= t1.step_func(function(e) {
+ input_fired = true;
+ assert_true(e.bubbles, "event should bubble")
+ assert_true(e.isTrusted, "event should be trusted");
+ assert_false(e.cancelable, "event shoud not be cancelable");
+ });
+
+ radio5.onchange = t2.step_func(function(e) {
+ change_fired = true;
+ assert_true(e.bubbles, "event should bubble")
+ assert_true(e.isTrusted, "event should be trusted");
+ assert_false(e.cancelable, "event shoud not be cancelable");
+ });
+
+ radio6.oninput= t3.step_func_done(function(e) {
+ assert_unreached("event input fired");
+ });
+
+ radio6.onchange = t4.step_func_done(function(e) {
+ assert_unreached("event change fired");
+ });
+
+ t1.step(function() {
+ radio5.click();
+ assert_true(input_fired);
+ t1.done();
+ });
+
+ t2.step(function() {
+ assert_true(change_fired);
+ t2.done();
+ })
+
+ t3.step(function(){
+ radio6.click();
+ t3.done();
+ t4.done();
+ });
+
+ radio72.onclick = t5.step_func_done(function(e){
+ assert_false(radio71.checked);
+ assert_true(radio72.checked);
+ e.preventDefault();
+ assert_false(radio71.checked);
+ assert_true(radio72.checked);
+ });
+
+ t5.step(function(){
+ assert_true(radio71.checked);
+ assert_false(radio72.checked);
+ radio72.click();
+ assert_true(radio71.checked);
+ assert_false(radio72.checked);
+ });
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/range-2.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/range-2.html
new file mode 100644
index 00000000000..3277dfc07fd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/range-2.html
@@ -0,0 +1,43 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>range input Tests</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<input type="range" id="r00" min="0" max="100" step="20" value="40" style="display:none">
+<input type="range" id="r01" min="0" max="1" step=".1" value=".2" style="display:none">
+<input type="range" id="r02" style="display:none">
+<input type="range" id="r03" style="display:none">
+<input type="range" id="r04" style="display:none">
+
+<script>
+test(function rangeElementTest0() {
+ document.getElementById('r00').value = "";
+ assert_equals(document.getElementById('r00').type, "range");
+ assert_equals(document.getElementById('r00').value, "60");
+}, "range input value set to ''");
+
+test(function rangeElementTest1() {
+ document.getElementById('r01').value = .6;
+ assert_equals(document.getElementById('r01').type, "range");
+ assert_equals(document.getElementById('r01').value, "0.6");
+}, "range input value set to an integer");
+
+test(function rangeElementTest2() {
+ assert_equals(document.getElementById('r02').type, "range");
+ assert_equals(document.getElementById('r02').value, "50");
+}, "range input value equals 50");
+
+test(function rangeElementTest3() {
+ document.getElementById('r03').value = 200;
+ assert_equals(document.getElementById('r03').type, "range");
+ assert_equals(document.getElementById('r03').value, "100");
+}, "range input value equals 100");
+
+test(function rangeElementTest4() {
+ document.getElementById('r04').value = 2.1;
+ assert_equals(document.getElementById('r04').type, "range");
+ assert_equals(document.getElementById('r04').value, "2");
+}, "range input value equals 2");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/range.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/range.html
new file mode 100644
index 00000000000..2e7a85ea956
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/range.html
@@ -0,0 +1,276 @@
+<!DOCTYPE html>
+<html>
+
+ <head>
+ <title>Input Range</title>
+ <meta name=viewport content="width=device-width, maximum-scale=1.0, user-scalable=no" />
+ <link rel="author" title="Fabrice Clari" href="mailto:f.clari@inno-group.com">
+ <link rel="author" title="Dimitri Bocquet" href="mailto:Dimitri.Bocquet@mosquito-fp7.eu">
+ <link rel="author" title="Tomoyuki SHIMIZU" href="mailto:tomoyuki.labs@gmail.com">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-input-element">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+
+ <body>
+
+
+ <h1>Input Range</h1>
+ <div style="display:none">
+ <input type="range" id="range_basic" min=0 max=5 />
+ <input type="range" id="value_smaller_than_min" min=0 max=5 value=-10 />
+ <input type="range" id="value_larger_than_max" min=0 max=5 value=7 />
+ <input type="range" id="empty_attributes" />
+ <input type="range" id="value_not_specified" min=2 max=6 />
+ <input type="range" id="control_step_mismatch" min=0 max=7 step=2 />
+ <input type="range" id="max_smaller_than_min" min=2 max=-3 />
+ <input type="range" id="default_step_scale_factor_1" min=5 max=12.6 value=6.7 />
+ <input type="range" id="default_step_scale_factor_2" min=5.3 max=12 value=6.7 />
+ <input type="range" id="default_step_scale_factor_3"min=5 max=12.6 step=0.5 value=6.7 />
+ <input type="range" id="float_step_scale_factor" min=5.3 max=12 step=0.5 value=6.7 />
+ <input type="range" id="stepup" min=3 max=14 value=6 step=3 />
+ <input type="range" id="stepdown" min=3 max=11 value=9 step=3 />
+ <input type="range" id="stepup_beyond_max" min=3 max=14 value=9 step=3 />
+ <input type="range" id="stepdown_beyond_min" min=3 max=11 value=6 step=3 />
+ <input type="range" id="illegal_min_and_max" min="ab" max="f" />
+ <input type="range" id="illegal_value_and_step" min=0 max=5 value="ppp" step="xyz" />
+ </div>
+
+ <div id="log">
+ </div>
+
+ <script type="text/javascript">
+
+ test(
+ function() {
+ assert_equals(document.getElementById('range_basic').type, "range");
+ },
+ "range type support on input element",
+ {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-type"
+ }
+ );
+
+ test(
+ function() {
+ assert_equals(document.getElementById('range_basic').min, "0")
+ },
+ "min attribute support on input element",
+ {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-min"
+ }
+ );
+
+ test(
+ function() {
+ assert_equals(document.getElementById('range_basic').max, "5")
+ },
+ "max attribute support on input element",
+ {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-max"
+ }
+ );
+
+ // HTML5 spec says the default vaules of min and max attributes are 0 and 100 respectively,
+ // however, Chrome, Opera and Firefox would not give any default value at all...
+ test(
+ function() {
+ assert_equals(document.getElementById('illegal_min_and_max').min, "0")
+ },
+ "Illegal value of min attribute",
+ {
+ "help" : "https://html.spec.whatwg.org/multipage/#range-state-(type=range)"
+ }
+ );
+
+ test(
+ function() {
+ assert_equals(document.getElementById('illegal_min_and_max').max, "100")
+ },
+ "Illegal value of max attribute",
+ { "help" : "https://html.spec.whatwg.org/multipage/#range-state-(type=range)" }
+ );
+
+ test(
+ function() {
+ assert_equals(document.getElementById('illegal_value_and_step').value, "3")
+ },
+ "Converting an illegal string to the default value",
+ {
+ "help" : "https://html.spec.whatwg.org/multipage/#range-state-(type=range)"
+ }
+ );
+
+ test(
+ function() {
+ assert_equals(document.getElementById('illegal_value_and_step').step, "1")
+ },
+ "Converting an illegal string to the default step",
+ { "help" : "https://html.spec.whatwg.org/multipage/#range-state-(type=range)" }
+ );
+
+ test(
+ function() {
+ assert_equals(document.getElementById('value_smaller_than_min').value, "0")
+ },
+ "the value is set to min when a smaller value than min attribute is given",
+ {
+ "help" : "https://html.spec.whatwg.org/multipage/#range-state-(type=range)"
+ }
+ );
+
+ test(
+ function() {
+ assert_equals(document.getElementById('value_larger_than_max').value, "5")
+ },
+ "the value is set to max when a larger value than max attribute is given",
+ {
+ "help" : "https://html.spec.whatwg.org/multipage/#range-state-(type=range)"
+ }
+ );
+
+ test(
+ function() {
+ assert_equals(document.getElementById('empty_attributes').min, "0")
+ },
+ "default value of min attribute in input type=range",
+ { "help" : "https://html.spec.whatwg.org/multipage/#dom-input-min" }
+ );
+
+ test(
+ function() {
+ assert_equals(document.getElementById('empty_attributes').max, "100")
+ },
+ "default value of max attribute in input type=range",
+ {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-max"
+ }
+ );
+
+ test(
+ function() {
+ assert_equals(document.getElementById('value_not_specified').value, "4")
+ },
+ "default value when min and max attributes are given (= min plus half the difference between min and max)",
+ {
+ "help" : "https://html.spec.whatwg.org/multipage/#range-state-(type=range)"
+ }
+ );
+
+ test(
+ function() {
+ assert_equals(document.getElementById('control_step_mismatch').value, "4")
+ },
+ "default value with step control when both min and max attributes are given",
+ {
+ "help" : "https://html.spec.whatwg.org/multipage/#range-state-(type=range)"
+ }
+ );
+
+ // Chrome would result in different value out of the range between min and max. Why?
+ test(
+ function() {
+ assert_equals(document.getElementById('max_smaller_than_min').value, "2")
+ },
+ "default value when both min and max attributes are given, while min > max",
+ {
+ "help" : "https://html.spec.whatwg.org/multipage/#range-state-(type=range)"
+ }
+ );
+
+ test(
+ function() {
+ assert_equals(document.getElementById('default_step_scale_factor_1').value, "7")
+ },
+ "The default step scale factor is 1, unless min attribute has non-integer value",
+ {
+ "help" : "https://html.spec.whatwg.org/multipage/#range-state-(type=range)"
+ }
+ );
+
+ test(
+ function() {
+ assert_equals(document.getElementById('default_step_scale_factor_2').value, "6.3")
+ },
+ "Step scale factor behavior when min attribute has integer value but max attribute is non-integer ",
+ {
+ "help" : "https://html.spec.whatwg.org/multipage/#range-state-(type=range)" }
+ );
+
+ test(
+ function() {
+ assert_equals(document.getElementById('default_step_scale_factor_3').step, "1")
+ },
+ "The default scale factor is 1 even if step attribute is explicitly set to non-integer value, unless min attribute has non-integer value",
+ {
+ "help" : "https://html.spec.whatwg.org/multipage/#range-state-(type=range)"
+ }
+ );
+
+ test(
+ function() {
+ assert_equals(document.getElementById('float_step_scale_factor').value, "6.8")
+ },
+ "Solving the step mismatch",
+ {
+ "help" : "https://html.spec.whatwg.org/multipage/#range-state-(type=range)"
+ }
+ );
+
+ // Firefox Nightly (24.0a1) would result in the possible maximum value in this range... (i.e. 12)
+ test(
+ function() {
+ var e = document.getElementById('stepup');
+ e.stepUp();
+ assert_equals(e.value, "9")
+ },
+ "Performing stepUp()",
+ {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-stepup"
+ }
+ );
+
+ // Firefox Nightly (24.0a1) would result in the possible minimum value in this range... (i.e. 3)
+ test(
+ function() {
+ var e = document.getElementById('stepdown');
+ e.stepDown();
+ assert_equals(e.value, "6")
+ },
+ "Performing stepDown()",
+ {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-stepdown"
+ }
+ );
+
+ // Chrome and Opera would throw DOM Exception 11 (InvalidStateError)
+ // Firefox Nightly gives the correct result
+ test(
+ function() {
+ var e = document.getElementById('stepup_beyond_max');
+ e.stepUp(2);
+ assert_equals(e.value, "12")
+ },
+ "Performing stepUp() beyond the value of the max attribute",
+ {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-stepup"
+ }
+ );
+
+ // Chrome and Opera would throw DOM Exception 11 (InvalidStateError)
+ // Firefox Nightly gives the correct result
+ test(
+ function() {
+ var e = document.getElementById('stepdown_beyond_min');
+ e.stepDown(2);
+ assert_equals(e.value, "3")
+ }, "Performing stepDown() beyond the value of the min attribute", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-stepdown"
+ }
+ );
+
+ </script>
+
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/required_attribute.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/required_attribute.html
new file mode 100644
index 00000000000..6674fca2e37
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/required_attribute.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+
+ <head>
+ <title>Required Attribute</title>
+ <meta name=viewport content="width=device-width, maximum-scale=1.0, user-scalable=no" />
+ <link rel="author" title="Fabrice Clari" href="mailto:f.clari@inno-group.com">
+ <link rel="author" title="Dimitri Bocquet" href="mailto:Dimitri.Bocquet@mosquito-fp7.eu">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#attr-input-required">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+
+ <body>
+
+
+ <h1>Required Attribute</h1>
+ <div style="display: none">
+ <input type="text" required="required" />
+ </div>
+
+ <div id="log">
+ </div>
+
+ <script type="text/javascript">
+
+
+ test(function() {assert_equals(document.getElementsByTagName("input")[0].getAttribute("required"), "required")}, "required attribute support on input element");
+
+ </script>
+
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/reset.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/reset.html
new file mode 100644
index 00000000000..9a979954265
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/reset.html
@@ -0,0 +1,113 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>input type reset</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#reset-button-state-(type=reset)">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<form>
+ <input type=text id=input1 value="foobar">
+ <input type=text id=input2>
+ <input type=reset id=r1>
+</form>
+
+<input type=text id=input3 value="barfoo">
+
+<table>
+ <form>
+ <tr>
+ <td>
+ <input type=text id=input4 value="foobar">
+ <input type=reset id=r2>
+ </td>
+ </tr>
+ </form>
+</table>
+
+<div>
+ <form>
+ <input type=text id=input5 value="foobar">
+ </div>
+ <input type=reset id=r3>
+</form>
+
+<div>
+ <form>
+ <input type=reset id=r4>
+ </div>
+ <input type=text id=input6 value="foobar">
+</form>
+
+<form id=form5>
+ <input type=reset id=r5>
+</form>
+<input form=form5 type=text id=input7 value="foobar">
+
+<form id=form6>
+ <input type=text id=input8 value="foobar">
+</form>
+<input type=reset form=form6 id=r6>
+
+<script>
+ var input1 = document.getElementById('input1'),
+ input2 = document.getElementById('input2'),
+ input3 = document.getElementById('input3'),
+ input7 = document.getElementById('input7'),
+ input8 = document.getElementById('input8'),
+ r1 = document.getElementById('r1');
+
+ test(function(){
+ assert_equals(input1.value, "foobar");
+ assert_equals(input2.value, "");
+ assert_equals(input3.value, "barfoo");
+ input1.value = "foobar1";
+ input2.value = "notempty";
+ input3.value = "barfoo1";
+ assert_equals(input1.value, "foobar1");
+ assert_equals(input2.value, "notempty");
+ assert_equals(input3.value, "barfoo1");
+ r1.click();
+ assert_equals(input1.value, "foobar");
+ assert_equals(input2.value, "");
+ assert_equals(input3.value, "barfoo1");
+ }, "reset button only resets the form owner");
+
+ test(function(){
+ assert_false(r1.willValidate);
+ }, "the element is barred from constraint validation");
+
+ test(function(){
+ assert_equals(input1.value, "foobar");
+ assert_equals(input2.value, "");
+ assert_equals(input3.value, "barfoo1");
+ r1.disabled = true;
+ r1.click();
+ assert_equals(input1.value, "foobar");
+ assert_equals(input2.value, "");
+ assert_equals(input3.value, "barfoo1");
+ }, "clicking on a disabled reset does nothing");
+
+ function testReset(inputId, buttonId) {
+ var inp = document.getElementById(inputId);
+ assert_equals(inp.value, "foobar");
+ inp.value = "barfoo";
+ assert_equals(inp.value, "barfoo");
+ document.getElementById(buttonId).click();
+ assert_equals(inp.value, "foobar");
+ }
+
+ test(function(){
+ testReset("input4", "r2");
+ testReset("input5", "r3");
+ testReset("input6", "r4");
+ }, "reset button resets controls associated with their form using the form element pointer");
+
+ test(function(){
+ testReset("input7", "r5");
+ }, "reset button resets controls associated with a form using the form attribute");
+
+ test(function(){
+ testReset("input8", "r6");
+ }, "reset button associated with a form using the form attribute resets all the form's controls");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/search_input.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/search_input.html
new file mode 100644
index 00000000000..f3c346a2396
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/search_input.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+
+ <head>
+ <title>Search Input</title>
+ <meta name=viewport content="width=device-width, maximum-scale=1.0, user-scalable=no" />
+ <link rel="author" title="Fabrice Clari" href="mailto:f.clari@inno-group.com">
+ <link rel="author" title="Dimitri Bocquet" href="mailto:Dimitri.Bocquet@mosquito-fp7.eu">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-input-element">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+
+ <body>
+
+
+ <h1>Search Input</h1>
+ <input type="search" style="display:none" placeholder="Search..." />
+
+ <div id="log">
+ </div>
+
+ <script type="text/javascript">
+
+
+ test(function() {assert_equals(document.getElementsByTagName("input")[0].type, "search")}, "search type support on input element", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-type" });
+ test(function() {assert_equals(document.getElementsByTagName("input")[0].placeholder, "Search...")}, "placeholder attribute support on input element", {
+ "help" : "https://html.spec.whatwg.org/multipage/#dom-input-placeholder" });
+
+ </script>
+
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/telephone.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/telephone.html
new file mode 100644
index 00000000000..4d9aaf09970
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/telephone.html
@@ -0,0 +1,84 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Input tel</title>
+ <link rel="author" title="Kazuki Kanamori" href="mailto:yogurito@gmail.com">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#telephone-state-(type=tel)">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <h1>Input tel</h1>
+ <input type="tel" id="novalue" />
+ <input type="tel" id="value_with_LF" value="0&#x000A;1" />
+ <input type="tel" id="value_with_CR" value="0&#x000D;1" />
+ <input type="tel" id="value_with_CRLF" value="0&#x000A;&#x000D;1" />
+ <div id="log">
+ </div>
+
+ <script type="text/javascript">
+ var element = document.getElementById('novalue');
+ test(function(){
+ assert_equals(element.type, 'tel');
+ }, 'tel type supported on input element');
+ test(function(){
+ element.value = '0\u000A1';
+ assert_equals(element.value, '01');
+ }, 'User agents must not allow users to insert "LF" (U+000A)');
+ test(function(){
+ element.value = '0\u000D1';
+ assert_equals(element.value, '01');
+ }, 'User agents must not allow users to insert "CR" (U+000D)');
+
+ element = document.getElementById('value_with_LF');
+ test(function(){
+ assert_equals(element.value, '01');
+ }, 'The value attribute, if specified, must have a value that contains no "LF" (U+000A)');
+
+ element = document.getElementById('value_with_CR');
+ test(function(){
+ assert_equals(element.value, '01');
+ }, 'The value attribute, if specified, must have a value that contains no "CR" (U+000D)');
+
+ test(function(){
+ element = document.getElementById('novalue');
+ element.value = '0\u000D\u000A1';
+ assert_equals(element.value, '01');
+
+ element = document.getElementById('value_with_CRLF');
+ assert_equals(element.value, '01');
+ }, 'The value sanitization algorithm is as follows: Strip line breaks from the value');
+
+ element = document.getElementById('novalue');
+ test(function(){
+ element.value = '+811234';
+ assert_equals(element.value, '+811234');
+ }, 'Element can accept the phone number with plus sign(country code)');
+ test(function(){
+ element.value = '1234#5678';
+ assert_equals(element.value, '1234#5678');
+ }, 'Element can accept the phone number with hash mark(extension number)');
+ test(function(){
+ element.value = '123-456-789';
+ assert_equals(element.value, '123-456-789');
+ }, 'Element can accept the phone number with hyphen');
+ test(function(){
+ element.value = '123.456.789';
+ assert_equals(element.value, '123.456.789');
+ }, 'Element can accept the phone number with dots');
+ test(function(){
+ element.value = '1 23 4';
+ assert_equals(element.value, '1 23 4');
+ }, 'Element can accept the phone number with whitespace');
+ test(function(){
+ element.value = ' 1234 ';
+ assert_equals(element.value, ' 1234 ');
+ }, 'Element can accept the phone number with leading & following whitespaces');
+ test(function(){
+ element.value = '(03)12345678';
+ assert_equals(element.value, '(03)12345678');
+ }, 'Element can accept the phone number with parentheses(area code)');
+ </script>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/text.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/text.html
new file mode 100644
index 00000000000..b6d4ceabf4f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/text.html
@@ -0,0 +1,104 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Text input element</title>
+ <link rel="author" title="Kinuko Yasuda" href="mailto:kinuko@chromium.org">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#text-(type=text)-state-and-search-state-(type=search)">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+
+ <body>
+ <h1>Text input element</h1>
+ <div style="display: none">
+
+ <input id="text" type="text" />
+ <input id="text_with_value" type="text" value="foo" />
+
+ <input id="search" type="search" />
+ <input id="search_with_value" type="search" value="foo" />
+
+ </div>
+ <div id="log"></div>
+ <script type="text/javascript">
+ var types = [ 'text', 'search' ];
+
+ for (var i = 0; i < types.length; ++i) {
+ test(
+ function() {
+ assert_equals(document.getElementById(types[i]).value, "");
+ assert_equals(document.getElementById(types[i] + "_with_value").value, "foo");
+ }, "Value returns the current value for " + types[i]);
+
+ test(
+ function() {
+ document.getElementById(types[i]).value = "A";
+ assert_equals(document.getElementById(types[i]).value, "A");
+ document.getElementById(types[i]).value = "B";
+ }, "Setting value changes the current value for " + types[i]);
+
+ test(
+ function() {
+ // Any LF (\n) must be stripped.
+ document.getElementById(types[i]).value = "\nAB";
+ assert_equals(document.getElementById(types[i]).value, "AB");
+ document.getElementById(types[i]).value = "A\nB";
+ assert_equals(document.getElementById(types[i]).value, "AB");
+ document.getElementById(types[i]).value = "AB\n";
+ assert_equals(document.getElementById(types[i]).value, "AB");
+
+ // Any CR (\r) must be stripped.
+ document.getElementById(types[i]).value = "\rAB";
+ assert_equals(document.getElementById(types[i]).value, "AB");
+ document.getElementById(types[i]).value = "A\rB";
+ assert_equals(document.getElementById(types[i]).value, "AB");
+ document.getElementById(types[i]).value = "AB\r";
+ assert_equals(document.getElementById(types[i]).value, "AB");
+
+ // Any combinations of LF CR must be stripped.
+ document.getElementById(types[i]).value = "\r\nAB";
+ assert_equals(document.getElementById(types[i]).value, "AB");
+ document.getElementById(types[i]).value = "A\r\nB";
+ assert_equals(document.getElementById(types[i]).value, "AB");
+ document.getElementById(types[i]).value = "AB\r\n";
+ assert_equals(document.getElementById(types[i]).value, "AB");
+ document.getElementById(types[i]).value = "\r\nA\n\rB\r\n";
+ assert_equals(document.getElementById(types[i]).value, "AB");
+ }, "Value sanitization algorithm should strip line breaks for " + types[i]);
+
+ test(
+ function() {
+ assert_equals(document.getElementById(types[i]).files, null);
+ }, "files attribute must return null for " + types[i]);
+
+ test(
+ function() {
+ assert_equals(document.getElementById(types[i]).valueAsDate, null);
+ }, "valueAsDate attribute must return null for " + types[i]);
+
+ test(
+ function() {
+ assert_equals(document.getElementById(types[i]).valueAsNumber, NaN);
+ }, "valueAsNumber attribute must return NaN for " + types[i]);
+
+ test(
+ function() {
+ assert_equals(document.getElementById("text").list, null);
+ }, "list attribute must return null for " + types[i]);
+
+ test(
+ function() {
+ var el = document.getElementById(types[i]);
+ assert_throws("InvalidStateError", function() { el.stepDown(); }, "");
+ }, "stepDown does not apply for " + types[i]);
+
+ test(
+ function() {
+ var el = document.getElementById(types[i]);
+ assert_throws("InvalidStateError", function() { el.stepUp(); }, "");
+ }, "stepUp does not apply for " + types[i]);
+ }
+
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/time-2.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/time-2.html
new file mode 100644
index 00000000000..cf0d4cbbeab
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/time-2.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Form input type=time</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel=help href="https://html.spec.whatwg.org/multipage/multipage/common-microsyntaxes.html#times">
+<link rel=help href="https://html.spec.whatwg.org/multipage/multipage/states-of-the-type-attribute.html#time-state-(type=time)">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+ var times = [
+ {value: "", expected: "", testname: "empty value"},
+ {value: "00:00", expected: "00:00", testname: "Valid value: value should be 00:00"},
+ {value: "00:00:00", expected: "00:00:00", testname: "Valid value: value should be 00:00:00"},
+ {value: "00:00:00.0", expected: "00:00:00.0", testname: "Valid value: value should be 00:00:00.0"},
+ {value: "00:00:00.00", expected: "00:00:00.00", testname: "Valid value: value should be 00:00:00.00"},
+ {value: "00:00:00.000", expected: "00:00:00.000", testname: "Valid value: value should be 00:00:00.000"},
+ {value: "00:00:00.0000", expected: "", testname: "Invalid value: fraction should have one, two or three ASCII digits. Value should be empty"},
+ {value: "0:00:00.000", expected: "", testname: "Invalid value: hour should have two ASCII digits. Value should be empty"},
+ {value: "00:0:00.000", expected: "", testname: "Invalid value: minutes should have two ASCII digits. Value should be empty"},
+ {value: "00:00:0.000", expected: "", testname: "Invalid value: seconds should have two ASCII digits. Value should be empty"},
+ {value: "24:00:00.000", expected: "", testname: "Invalid value: hour > 23. Value should be empty"},
+ {value: "00:60:00.000", expected: "", testname: "Invalid value: minute > 59. Value should be empty"},
+ {value: "00:00:60.000", expected: "", testname: "Invalid value: second > 59. Value should be empty"},
+ {value: "12:00:00.001", attributes: { min: "12:00:00.000" }, expected: "12:00:00.001", testname: "Value >= min attribute"},
+ {value: "12:00:00.000", attributes: { min: "12:00:00.001" }, expected: "12:00:00.001", testname: "Value < min attribute"},
+ {value: "12:00:00.000", attributes: { max: "12:00:00.001" }, expected: "12:00:00.000", testname: "Value <= max attribute"},
+ {value: "12:00:00.001", attributes: { max: "12:00:00.000" }, expected: "12:00:00.000", testname: "Value > max attribute"}
+ ];
+ for (var i = 0; i < times.length; i++) {
+ var w = times[i];
+ test(function() {
+ var input = document.createElement("input");
+ input.type = "time";
+ input.value = w.value;
+ for(var attr in w.attributes) {
+ input[attr] = w.attributes[attr];
+ }
+ assert_equals(input.value, w.expected);
+ }, w.testname);
+ }
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/time.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/time.html
new file mode 100644
index 00000000000..b202d28c79c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/time.html
@@ -0,0 +1,207 @@
+<!DOCTYPE html>
+<html>
+
+ <head>
+ <title>Input Time</title>
+ <meta name=viewport content="width=device-width, maximum-scale=1.0, user-scalable=no" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-input-element">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+
+ <body>
+ <h1>Input Time</h1>
+ <div style="display:none;">
+ <input type="time "id="chkDefaultValue" />
+ <input type="time" id="chkStep" />
+ <input type="time" id="chkSetValueTest" />
+ <input type="time" id="chkSupportAttribute" min="01:01:01.001" max="12:12:12.012" step="600" />
+ </div>
+ <div id="log">
+ </div>
+
+ <script type="text/javascript">
+
+/* check default value */
+test(function(){ assert_equals(document.getElementById("chkDefaultValue").value, "");
+}, "time element of default time value");
+test(function(){assert_equals(document.getElementById('chkStep').step, "");
+} , "step attribute on default value check");
+test(function(){assert_equals(document.getElementById('chkDefaultValue').max, "");
+} , "max attribute on default value check")
+test(function(){assert_equals(document.getElementById('chkDefaultValue').max, "");
+} , "min attribute on default value check")
+
+/* simple attribute test*/
+test(function(){assert_equals(document.getElementById("chkSupportAttribute").type,"time");}
+ , "type attribute support on input element");
+test(function(){assert_equals(document.getElementById('chkSupportAttribute').min, "01:01:01.001")}
+ , "max attribute support on input element");
+test(function(){assert_equals(document.getElementById('chkSupportAttribute').max, "12:12:12.012")}
+ , "min attribute support on input element");
+test(function(){assert_equals(document.getElementById("chkSupportAttribute").step, "600")}
+ , "step attribute support on input element");
+
+/* check step up and down */
+var _StepTest = document.getElementById("chkStep");
+test(function(){ assert_true(typeof(_StepTest.stepUp) ==="function" ) } , "stepUp function support on input Element");
+test(function(){ assert_true(typeof(_StepTest.stepDown) ==="function" ) } , "stepDown function support on input Element");
+
+test(function(){
+ _StepTest.value = "12:00";
+ _StepTest.step = "";
+ _StepTest.stepUp();
+ assert_equals(_StepTest.value,"12:01");
+} , "stepUp step value empty on default step value ");
+
+test(function(){
+ _StepTest.value = "12:00";
+ _StepTest.step = "";
+ _StepTest.stepDown();
+ assert_equals(_StepTest.value,"11:59");
+}, "stepDown step value empty default step value");
+
+test(function(){
+ _StepTest.value = "12:00";
+ _StepTest.step = "-600";
+ _StepTest.stepUp();
+ assert_equals(_StepTest.value, "12:01");
+},"stepUp on step value minus");
+test(function(){
+ _StepTest.value = "12:00";
+ _StepTest.step = "-600";
+ _StepTest.stepDown();
+ assert_equals(_StepTest.value, "11:59");
+},"stepDown on step value minus");
+
+test(function(){
+ _StepTest.value = "12:00";
+ _StepTest.step = "0";
+ _StepTest.stepUp();
+ assert_equals(_StepTest.value, "12:01");
+} , "stepUp on step value zero ");
+test(function(){
+ _StepTest.value = "12:00";
+ _StepTest.step = "0";
+ _StepTest.stepDown();
+ assert_equals(_StepTest.value, "11:59");
+} , "stepDown on step value zero ");
+
+test(function(){
+ _StepTest.value = "00:00";
+ _StepTest.step = "86399";
+ _StepTest.stepUp();
+ assert_equals(_StepTest.value, "23:59:59");
+} , "stepUp on step value 24 hour");
+test(function(){
+ _StepTest.value = "23:59:59";
+ _StepTest.step = "86399";
+ _StepTest.stepDown();
+ assert_equals(_StepTest.value, "00:00:00");
+} , "stepDown on step value 24 hour ");
+
+test(function(){
+ _StepTest.value = "12:00";
+ _StepTest.step = "3600";
+ _StepTest.stepUp();
+ assert_equals(_StepTest.value, "13:00");
+} , "stepUp on step value hour ");
+test(function(){
+ _StepTest.value = "12:00";
+ _StepTest.step = "3600";
+ _StepTest.stepDown();
+ assert_equals(_StepTest.value, "11:00");
+} , "stepDown on step value hour ");
+
+test(function(){
+ _StepTest.value = "12:00";
+ _StepTest.step = "1";
+ _StepTest.stepUp();
+ assert_equals(_StepTest.value, "12:00:01");
+} , "stepUp on step value second ");
+test(function(){
+ _StepTest.value = "12:00";
+ _StepTest.step = "1";
+ _StepTest.stepDown();
+ assert_equals(_StepTest.value, "11:59:59");
+} , "stepDown on step value second ");
+
+test(function(){
+ _StepTest.value = "12:00";
+ _StepTest.step = "0.001";
+ _StepTest.stepUp();
+ assert_equals(_StepTest.value, "12:00:00.001");
+} , "stepUp on step value miri second ");
+test(function(){
+ _StepTest.value = "12:00";
+ _StepTest.step = "0.001";
+ _StepTest.stepDown();
+ assert_equals(_StepTest.value, "11:59:59.999");
+} , "stepDown on step value miri second ");
+
+test(function(){
+ _StepTest.value = "13:00:00";
+ _StepTest.step = "1";
+ _StepTest.stepUp(2);
+ assert_equals(_StepTest.value, "13:00:02");
+}, "stepUp argment 2 times");
+test(function(){
+ _StepTest.value = "13:00:00";
+ _StepTest.step = "1";
+ _StepTest.stepDown(2);
+ assert_equals(_StepTest.value, "12:59:58");
+}, "stepDown argment 2 times");
+
+test(function(){
+ _StepTest.max = "15:00";
+ _StepTest.value = "15:00";
+ _StepTest.stepUp();
+ assert_equals(_StepTest.value, "15:00");
+ _StepTest.max = "";
+} , "stepUp stop because it exceeds the maximum value");
+test(function(){
+ _StepTest.min = "13:00";
+ _StepTest.value = "13:00";
+ _StepTest.stepDown();
+ assert_equals(_StepTest.value, "13:00");
+ _StepTest.min="";
+} , "stepDown Stop so lower than the minimum value");
+
+test(function(){
+ _StepTest.max = "15:01";
+ _StepTest.value = "15:00";
+ _StepTest.step = "120";
+ _StepTest.stepUp();
+ assert_equals(_StepTest.value, "15:01");
+ _StepTest.max = "";
+} , "stop at border on stepUp");
+test(function(){
+ _StepTest.min = "12:59";
+ _StepTest.value = "13:00";
+ _StepTest.step = "120";
+ _StepTest.stepDown();
+ assert_equals(_StepTest.value, "12:59");
+ _StepTest.min="";
+} , "stop at border on stepDown");
+
+test(function(){
+ _StepTest.value = "";
+ _StepTest.step = "60";
+ _StepTest.stepUp();
+ assert_equals(_StepTest.value, "00:01");
+} , " empty value of stepUp");
+
+
+/* set value test */
+test(function(){
+ var _time = document.getElementById("chkSetValueTest");
+ _time.value = "12:00:00.000";
+ assert_equals(_time.value, "12:00:00.000");
+ _time.value = "hh:mi:ss.sss";
+ assert_equals(_time.value, "");
+}, "set value on not time format value");
+
+
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/type-change-state.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/type-change-state.html
new file mode 100644
index 00000000000..87f734b90fd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/type-change-state.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Input element's type attribute changes state</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#the-input-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+ var types = [
+ { type: "hidden" },
+ { type: "text", sanitizedValue: " foobar " },
+ { type: "search", sanitizedValue: " foobar " },
+ { type: "tel", sanitizedValue: " foobar " },
+ { type: "url", sanitizedValue: "foobar" },
+ { type: "email", sanitizedValue: "foobar" },
+ { type: "password", sanitizedValue: " foobar " },
+ { type: "datetime", sanitizedValue: "" },
+ { type: "date", sanitizedValue: "" },
+ { type: "month", sanitizedValue: "" },
+ { type: "week", sanitizedValue: "" },
+ { type: "time", sanitizedValue: "" },
+ { type: "number", sanitizedValue: "" },
+ { type: "range", sanitizedValue: "50" },
+ { type: "color", sanitizedValue: "#000000" },
+ { type: "checkbox" },
+ { type: "radio" },
+ { type: "file" },
+ { type: "submit" },
+ { type: "image" },
+ { type: "reset" },
+ { type: "button" }
+ ];
+ for (var i = 0; i < types.length; i++) {
+ for (var j = 0; j < types.length; j++) {
+ if (types[i] != types[j]) {
+ test(function() {
+ var input = document.createElement("input");
+ input.type = types[i].type;
+ if (types[i].type === "file") {
+ assert_throws("INVALID_STATE_ERR", function() {
+ input.value = " foo\rbar ";
+ });
+ assert_equals(input.value, "");
+ } else {
+ input.value = " foo\rbar ";
+ input.type = types[j].type; // change state
+ if (types[j].sanitizedValue || types[j].sanitizedValue === "") {
+ assert_equals(input.value, types[j].sanitizedValue, "input.value should be " + types[j].sanitizedValue + " after change of state");
+ } else {
+ assert_equals(input.value, " foo\rbar ", "input.value should be ' foo\\rbar ' after change of state");
+ }
+ }
+ }, "change state from " + types[i].type + " to " + types[j].type);
+ }
+ }
+ }
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/url.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/url.html
new file mode 100644
index 00000000000..c368e746612
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/url.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Input url</title>
+ <link rel="author" title="Hyeonseok Shin" href="mailto:hyeonseok@gmail.com">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#url-state-%28type=url%29">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <h1>Input url</h1>
+ <div style="display: none">
+ <input type="url" id="type_support" />
+ <input type="url" id="set_value_LF" />
+ <input type="url" id="set_value_CR" />
+ <input type="url" id="set_value_CRLF" />
+ <input type="url" id="value_with_CRLF" value="a&#x000D;&#x000A;a" />
+ <input type="url" id="value_with_leading_trailing_white_space" value=" aa " />
+ <input type="url" id="value_with_leading_trailing_inner_white_space" value=" a a " />
+ </div>
+ <div id="log">
+ </div>
+
+ <script type="text/javascript">
+ test(function(){
+ var element = document.getElementById('type_support');
+ assert_equals(element.type, 'url');
+ }, 'url type supported on input element');
+
+ test(function(){
+ var element = document.getElementById('set_value_LF');
+ element.value = 'a\u000Aa';
+ assert_equals(element.value, 'aa');
+
+ element = document.getElementById('set_value_CR');
+ element.value = 'a\u000Da';
+ assert_equals(element.value, 'aa');
+
+ element = document.getElementById('set_value_CRLF');
+ element.value = 'a\u000D\u000Aa';
+ assert_equals(element.value, 'aa');
+ }, 'The value must not be set with "LF" (U+000A) or "CR" (U+000D)');
+
+ test(function(){
+ var element = document.getElementById('value_with_CRLF');
+ assert_equals(element.value, 'aa');
+ }, 'The value sanitization algorithm is as follows: Strip line breaks from the value');
+
+ test(function(){
+ var element = document.getElementById('value_with_leading_trailing_white_space');
+ assert_equals(element.value, 'aa');
+
+ element = document.getElementById('value_with_leading_trailing_inner_white_space');
+ assert_equals(element.value, 'a a');
+ }, 'The value sanitization algorithm is as follows: Strip leading and trailing whitespace from the value.');
+ </script>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/valueMode.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/valueMode.html
new file mode 100644
index 00000000000..04b09650955
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/valueMode.html
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Input element value mode</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+ var types = [
+ { type: "hidden", mode: "default" },
+ { type: "text", mode: "value", sanitizedValue: "foo" },
+ { type: "search", mode: "value", sanitizedValue: "foo" },
+ { type: "tel", mode: "value", sanitizedValue: "foo" },
+ { type: "url", mode: "value", sanitizedValue: "foo" },
+ { type: "email", mode: "value", sanitizedValue: "foo" },
+ { type: "password", mode: "value", sanitizedValue: "foo" },
+ { type: "datetime", mode: "value", sanitizedValue: "" },
+ { type: "date", mode: "value", sanitizedValue: "" },
+ { type: "month", mode: "value", sanitizedValue: "" },
+ { type: "week", mode: "value", sanitizedValue: "" },
+ { type: "time", mode: "value", sanitizedValue: "" },
+ { type: "number", mode: "value", sanitizedValue: "" },
+ { type: "range", mode: "value", sanitizedValue: "50" },
+ { type: "color", mode: "value", sanitizedValue: "#000000" },
+ { type: "checkbox", mode: "default/on" },
+ { type: "radio", mode: "default/on" },
+ { type: "submit", mode: "default" },
+ { type: "image", mode: "default" },
+ { type: "reset", mode: "default" },
+ { type: "button", mode: "default" }
+ ];
+ for (var i = 0; i < types.length; i++) {
+ test(function() {
+ var input = document.createElement("input"),
+ expected;
+ input.type = types[i].type;
+ input.value = "foo";
+ switch(types[i].mode) {
+ case "default":
+ expected = "";
+ break;
+ case "default/on":
+ expected = "on";
+ break;
+ case "value":
+ expected = types[i].sanitizedValue;
+ break;
+ }
+ assert_equals(input.value, expected);
+ }, "value IDL attribute of input type " + types[i].type + " without value attribute");
+
+ test(function() {
+ var input = document.createElement("input"),
+ expected;
+ input.type = types[i].type;
+ input.setAttribute("value", "bar");
+ input.value = "foo";
+ switch(types[i].mode) {
+ case "default":
+ expected = "bar";
+ break;
+ case "default/on":
+ expected = "bar";
+ break;
+ case "value":
+ expected = types[i].sanitizedValue;
+ break;
+ }
+ assert_equals(input.value, expected);
+ }, "value IDL attribute of input type " + types[i].type + " with value attribute");
+ }
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/week.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/week.html
new file mode 100644
index 00000000000..e06b67889e0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/week.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Form input type=week</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#weeks">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#week-state-(type=week)">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+ var weeks = [
+ {value: "", expected: "", testname: "empty value"},
+ {value: "2014-W52", expected: "2014-W52", testname: "Valid value: Value should be 2014-W52"},
+ {value: "2014-W53", expected: "", testname: "2014 has 52 weeks: Value should be empty"},
+ {value: "2015-W53", expected: "2015-W53", testname: "2015 has 53 weeks: Value should be 2015-W53"},
+ {value: "2014", expected: "", testname: "Invalid value: year only"},
+ {value: "2014W", expected: "", testname: "Invalid value: no week number"},
+ {value: "2014W52", expected: "", testname: "Invalid value: no '-' (U+002D)"},
+ {value: "-W52", expected: "", testname: "Invalid value: yearless week"},
+ {value: "W52", expected: "", testname: "Invalid value: yearless week and no '-' (U+002D)"},
+ {value: "2014-W03", attributes: { min: "2014-W02" }, expected: "2014-W03", testname: "Value >= min attribute"},
+ {value: "2014-W01", attributes: { min: "2014-W02" }, expected: "2014-W02", testname: "Value < min attribute"},
+ {value: "2014-W10", attributes: { max: "2014-W11" }, expected: "2014-W10", testname: "Value <= max attribute"},
+ {value: "2014-W12", attributes: { max: "2014-W11" }, expected: "2014-W11", testname: "Value > max attribute"}
+ ];
+ for (var i = 0; i < weeks.length; i++) {
+ var w = weeks[i];
+ test(function() {
+ var input = document.createElement("input");
+ input.type = "week";
+ input.value = w.value;
+ for(var attr in w.attributes) {
+ input[attr] = w.attributes[attr];
+ }
+ assert_equals(input.value, w.expected);
+ }, w.testname);
+ }
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-keygen-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/forms/the-keygen-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-keygen-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-label-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/forms/the-label-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-label-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-label-element/label-attributes.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-label-element/label-attributes.html
new file mode 100644
index 00000000000..324f72ba468
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-label-element/label-attributes.html
@@ -0,0 +1,124 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: The label element</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<form id="fm" style="display:none">
+ <label id="lbl0" for="test0"></label>
+ <b id="test0"></b>
+
+ <input id="test1"></input>
+
+ <label id="lbl1">
+ <a id="test2"></a>
+ <div><input id="test3"></div>
+ <input id="test4">
+ </label>
+
+ <label id="lbl2" for="testx">
+ <input id="test5">
+ </label>
+
+ <label id="lbl3" for="test6">
+ <b id="test6"></b>
+ <input id="test6" class="class1">
+ </label>
+
+ <label id="lbl4" for="">
+ <input id="" class="class2">
+ </label>
+
+ <label id="lbl5" for="test7"></label>
+ <input id="test7">
+</form>
+
+<label id="lbl6" for="test7"></label>
+
+<script>
+
+ //control attribute
+ test(function () {
+ assert_not_equals(document.getElementById("lbl0").control, document.getElementById("test0"),
+ "An element that's not a labelable element can't be a label element's labeled control.");
+ assert_equals(document.getElementById("lbl0").control, null,
+ "A label element whose 'for' attribute doesn't reference any labelable element shouldn't have any labeled control.");
+ }, "A label element with a 'for' attribute should only be associated with a labelable element.");
+
+ test(function () {
+ var label = document.createElement("label");
+ label.htmlFor = "test1";
+ assert_not_equals(label.control, document.getElementById("test1"),
+ "A label element not in a document should not label an element in a document.");
+ document.body.appendChild(label);
+ assert_equals(label.control, document.getElementById("test1"));
+ }, "A label element not in a document can not label any element in the document.");
+
+ test(function () {
+ assert_equals(document.getElementById("lbl1").control, document.getElementById("test3"),
+ "The first labelable descendant of a label element should be its labeled control.");
+
+ var input = document.createElement("input");
+ document.getElementById("lbl1").insertBefore(input, document.getElementById("test2"));
+ assert_equals(document.getElementById("lbl1").control, input,
+ "The first labelable descendant of a label element in tree order should be its labeled control.");
+ }, "The labeled control for a label element that has no 'for' attribute is the first labelable element which is a descendant of that label element.");
+
+ test(function () {
+ assert_equals(document.getElementById("lbl2").control, null,
+ "The label's 'control' property should return null if its 'for' attribute points to an inexistent element.");
+ }, "The 'for' attribute points to an inexistent id.");
+
+ test(function () {
+ assert_equals(document.getElementById("lbl3").control, null, "The label should have no control associated.");
+ assert_equals(document.querySelector(".class1").labels.length, 0);
+ }, "A non-control follows by a control with same ID.");
+
+ test(function () {
+ assert_equals(document.getElementById("lbl4").control, null,
+ "A label element with an empty 'for' attribute should not associate with anything.");
+ }, "The 'for' attribute is an empty string.");
+
+ //labels attribute
+ test(function () {
+ var labels = document.getElementById("test7").labels;
+ assert_true(labels instanceof NodeList,
+ "A form control's 'labels' property should be an instance of a NodeList.");
+ assert_equals(labels.length, 2,
+ "The number of labels associated with a form control should be the number of label elements for which it is a labeled control.");
+ assert_array_equals(labels, [document.getElementById("lbl5"), document.getElementById("lbl6")],
+ "The labels for a form control should be returned in tree order.");
+
+ var newLabel = document.createElement("label");
+ newLabel.htmlFor = "test7";
+ document.getElementById("fm").insertBefore(newLabel, document.getElementById("lbl0"));
+ assert_array_equals(document.getElementById("test7").labels, [newLabel, document.getElementById("lbl5"), document.getElementById("lbl6")],
+ "The labels for a form control should be returned in tree order.");
+ }, "A form control has multiple labels.");
+
+ test(function () {
+ var labels = document.getElementById("test4").labels;
+ assert_true(labels instanceof NodeList, "A form control's 'labels' property should be an instance of a NodeList.");
+ assert_equals(labels.length, 0, "The number of labels should be 0 if the associated form control isn't referenced by any <label>.");
+ }, "A form control has no label 1.");
+
+ test(function () {
+ assert_equals(document.getElementById("test5").labels.length, 0,
+ "The number of labels should be 0 if the form control has an ancestor label elment that the for attribute points to another control.");
+ assert_equals(document.getElementById("lbl2").control, null,
+ "The labeled cotrol should be associated with the control whose ID is equal to the value of the 'for' attribute.");
+ }, "A form control has no label 2.");
+
+ // form attribute
+ test(function () {
+ assert_equals(document.getElementById("lbl0").form, document.getElementById("fm"),
+ "The 'form' property for a label with a form owner should return the form owner.");
+ }, "A label's form attribute should return its form owner.");
+
+ test(function () {
+ assert_equals(document.getElementById("lbl6").form, null,
+ "The 'form' property for a label without a form owner should return null.");
+ }, "Check that the labels property of a form control with no label returns a zero-length NodeList.");
+
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-label-element/labelable-elements.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-label-element/labelable-elements.html
new file mode 100644
index 00000000000..38706cb8c75
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-label-element/labelable-elements.html
@@ -0,0 +1,96 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: labelable elements</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<form style="display:none">
+ <output id="testoutput"></output>
+ <label id="lbl0" for="testoutput"></label>
+ <progress id="testprogress"></progress>
+ <label id="lbl1" for="testprogress"></label>
+ <select id="testselect"></select>
+ <label id="lbl2" for="testselect"></label>
+ <textarea id="testarea"></textarea>
+ <label id="lbl3" for="testarea"></label>
+ <button id="testButton"></button>
+ <label id="lbl4" for="testButton"></label>
+ <input type="hidden" id="testHidden">
+ <label id="lbl5" for="testHidden"></label>
+ <input type="radio" id="testRadio">
+ <label id="lbl6" for="testRadio"></label>
+ <keygen id="testkeygen">
+ <label id="lbl7" for="testkeygen"></label>
+ <meter id="testmeter"></meter>
+ <label id="lbl8" for="testmeter"></label>
+
+ <fieldset id="testfieldset"></fieldset>
+ <label id="lbl9" for="testfieldset"></label>
+ <label id="testlabel"></label>
+ <label id="lbl10" for="testlabel"></label>
+ <object id="testobject"></object>
+ <label id="lbl11" for="testobject"></label>
+ <img id="testimg">
+ <label id="lbl12" for="testimg"></label>
+</form>
+
+<script>
+
+test(function() {
+ assert_equals(document.getElementById("lbl0").control.id, "testoutput", "An output element should be labelable.");
+}, "Check if the output element is a labelable element");
+
+test(function() {
+ assert_equals(document.getElementById("lbl1").control.id, "testprogress", "A progress element should be labelable.");
+}, "Check if the progress element is a labelable element");
+
+test(function() {
+ assert_equals(document.getElementById("lbl2").control.id, "testselect", "A select element should be labelable.");
+}, "Check if the select element is a labelable element");
+
+test(function() {
+ assert_equals(document.getElementById("lbl3").control.id, "testarea", "A textarea element should be labelable.");
+}, "Check if the textarea element is a labelable form-element");
+
+test(function() {
+ assert_equals(document.getElementById("lbl4").control.id, "testButton", "A button element should be labelable.");
+}, "Check if the button element is a labelable element");
+
+test(function() {
+ assert_equals(document.getElementById("lbl5").control, null, "An input element in hidden state should not be labelable.");
+}, "Check if the hidden input element is not a labelable element.");
+
+test(function() {
+ assert_equals(document.getElementById("lbl6").control.id, "testRadio", "An input element in radio state should be labelable.");
+}, "Check if the input element in radio state is a labelable element");
+
+test(function() {
+ assert_equals(document.getElementById("lbl7").control.id, "testkeygen", "A keygen element should be labelable.");
+}, "Check if the keygen element is a labelable element");
+
+test(function() {
+ assert_equals(document.getElementById("lbl8").control.id, "testmeter", "A meter element should be labelable.");
+}, "Check if the meter element is a labelable element");
+
+test(function() {
+ assert_not_equals(document.getElementById("lbl9").control, document.getElementById("testfieldset"));
+ assert_equals(document.getElementById("lbl9").control, null, "A fieldset element should not be labelable.");
+}, "Check if the fieldset element is not a labelable element");
+
+test(function() {
+ assert_not_equals(document.getElementById("lbl9").control, document.getElementById("testlabel"));
+ assert_equals(document.getElementById("lbl10").control, null, "A label element should not be labelable.");
+}, "Check if the label element is not a labelable element");
+
+test(function() {
+ assert_not_equals(document.getElementById("lbl9").control, document.getElementById("testobject"));
+ assert_equals(document.getElementById("lbl11").control, null, "An object element should not be labelable.");
+}, "Check if the object element is not a labelable element");
+
+test(function() {
+ assert_not_equals(document.getElementById("lbl9").control, document.getElementById("testimg"));
+ assert_equals(document.getElementById("lbl12").control, null, "An img element should not be labelable.");
+}, "Check if the img element is not a labelable element");
+
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-legend-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/forms/the-legend-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-legend-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-meter-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/forms/the-meter-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-meter-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-meter-element/meter.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-meter-element/meter.html
new file mode 100644
index 00000000000..7a77513d31e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-meter-element/meter.html
@@ -0,0 +1,242 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>The meter element</title>
+ <link rel="author" title="Tomoyuki SHIMIZU" href="mailto:tomoyuki.labs@gmail.com">
+ <link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-meter-element">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <h1>Meter Element</h1>
+ <div id="log"></div>
+ <div style="display: none;">
+ <meter id="meter_illegal_value" value="abc"></meter>
+ <meter id="meter_without_min" value="-10"></meter>
+ <meter id="meter_without_max" value="10"></meter>
+ <meter id="meter_min_without_max_1" value="10" min="-3.1"></meter>
+ <meter id="meter_min_without_max_2" value="210" min="12.1"></meter>
+ <meter id="meter_max_without_min_1" value="-10" max="-5342.55"></meter>
+ <meter id="meter_max_without_min_2" value="210" max="-9.9"></meter>
+ <meter id="meter_illegal_min" value="-2" min="hugfe"></meter>
+ <meter id="meter_illegal_max" value="2.4" max="min"></meter>
+ <meter id="meter_illegal_low_with_min" value="-20" min="-10.3" low="ahuge"></meter>
+ <meter id="meter_illegal_high_with_max" value="2.4" high="old" max="1.5"></meter>
+ <meter id="meter_smaller_than_min" value="-10" min="4.5"></meter>
+ <meter id="meter_larger_than_max" value="2345.53" max="52.02"></meter>
+ <meter id="meter_default_low_and_high_1" value="40" min="-12.3" max="3.4"></meter>
+ <meter id="meter_default_low_and_high_2" value="23"></meter>
+ <meter id="meter_low_smaller_than_min" value="-4" min="12.3" low="34"></meter>
+ <meter id="meter_low_larger_than_max" value="-1" min="-50" low="-5" max="-34.5"></meter>
+ <meter id="meter_high_smaller_than_min" value="-4" min="12.3" high="34"></meter>
+ <meter id="meter_high_larger_than_max" value="-1" min="-50" high="-5" max="-34.5"></meter>
+ <meter id="meter_high_smaller_than_low" value="-9" min="-20" low="-10.3" high="-15.2" max="-2"></meter>
+ <meter id="meter_low_without_min" value="-1" low="-5"></meter>
+ <meter id="meter_high_without_max" value="50000" high="4"></meter>
+ <meter id="meter_optimum_smaller_than_min" value="-8" optimum="-4"></meter>
+ <meter id="meter_optimum_larger_than_max" value="324" optimum="4.6"></meter>
+ <meter id="meter_default_optimum" value="10" min="-132.35" max="33.423"></meter>
+ </div>
+ <script>
+ var meters = [
+ {value: 0, expectedValue: 0, expectedMin: 0, expectedMax: 1.0, expectedLow: 0, expectedHigh: 1.0, expectedOptimum: 0.5, testname: "Default values"},
+ {value: 3, expectedValue: 3, min: -10.1, expectedMin: -10.1, max: 10.1, expectedMax: 10.1, low: -9.1, expectedLow: -9.1, high: 9.1, expectedHigh: 9.1, optimum: 3, expectedOptimum: 3, testname: "Setting values to min, max, low, high and optimum"},
+ {value: "foobar", expectedValue: 0, min: "foobar", expectedMin: 0, max: "foobar", expectedMax: 1.0, low: "foobar", expectedLow: 0, high: "foobar", expectedHigh: 1.0, optimum: "foobar", expectedOptimum: 0.5, testname: "Invalid floating-point number values"},
+ {value: 0, expectedValue: 0, min: 0, expectedMin: 0, max: -1.0, expectedMax: 0, expectedLow: 0, expectedHigh: 0, expectedOptimum: 0, testname: "max < min"},
+ {value: 0, expectedValue: 10, min: 10, expectedMin: 10, max: 20, expectedMax: 20, expectedLow: 10, expectedHigh: 20, expectedOptimum: 15, testname: "value < min"},
+ {value: 30, expectedValue: 20, min: 10, expectedMin: 10, max: 20, expectedMax: 20, expectedLow: 10, expectedHigh: 20, expectedOptimum: 15, testname: "value > max"},
+ {value: 15, expectedValue: 15, min: 10, expectedMin: 10, max: 20, expectedMax: 20, low: 5, expectedLow: 10, expectedHigh: 20, expectedOptimum: 15, testname: "low < min"},
+ {value: 15, expectedValue: 15, min: 10, expectedMin: 10, max: 20, expectedMax: 20, low: 25, expectedLow: 20, expectedHigh: 20, expectedOptimum: 15, testname: "low > max"},
+ {value: 15, expectedValue: 15, min: 10, expectedMin: 10, max: 20, expectedMax: 20, low: 12, expectedLow: 12, high: 10, expectedHigh: 12, expectedOptimum: 15, testname: "high < low"},
+ {value: 15, expectedValue: 15, min: 10, expectedMin: 10, max: 20, expectedMax: 20, low: 10, expectedLow: 10, high: 22, expectedHigh: 20, expectedOptimum: 15, testname: "high > max"},
+ {value: 15, expectedValue: 15, min: 10, expectedMin: 10, max: 20, expectedMax: 20, expectedLow: 10, expectedHigh: 20, optimum: 9, expectedOptimum: 10, testname: "optimum < min"},
+ {value: 15, expectedValue: 15, min: 10, expectedMin: 10, max: 20, expectedMax: 20, expectedLow: 10, expectedHigh: 20, optimum: 21, expectedOptimum: 20, testname: "optimum > max"}
+ ];
+ for (var i = 0; i < meters.length; i++) {
+ var m = meters[i];
+ test(function() {
+ var meter = document.createElement("meter");
+ meter.value = m.value;
+ if (m.min) meter.min= m.min;
+ if (m.max) meter.max = m.max;
+ if (m.low) meter.low = m.low;
+ if (m.high) meter.high = m.high;
+ if (m.optimum) meter.optimum = m.optimum;
+ assert_equals(meter.value, m.expectedValue, "meter value");
+ assert_equals(meter.min, m.expectedMin, "min value");
+ assert_equals(meter.max, m.expectedMax, "max value");
+ assert_equals(meter.low, m.expectedLow, "low value");
+ assert_equals(meter.high, m.expectedHigh, "high value");
+ assert_equals(meter.optimum, m.expectedOptimum, "optimum value");
+ }, m.testname);
+ }
+
+ </script>
+ <script type="text/javascript">
+ test(function() {
+ assert_equals(document.getElementById('meter_illegal_value').value, 0);
+ }, "value must be 0 when a string is given");
+
+ test(function() {
+ assert_equals(document.getElementById('meter_without_min').min, 0);
+ }, "default value of min is 0");
+
+ test(function() {
+ assert_equals(document.getElementById('meter_without_min').value, 0);
+ }, "If min is not specified and value is smaller than the default value of min (i.e. 0), the actual value must be 0");
+
+ test(function() {
+ assert_equals(document.getElementById('meter_without_max').max, 1.0);
+ }, "default value of max is 1.0");
+
+ test(function() {
+ assert_equals(document.getElementById('meter_without_max').value, 1.0);
+ }, "If max is not specified and value is larger than the default value of max (i.e. 1.0), the actual value must be 1.0");
+
+ test(function() {
+ assert_equals(document.getElementById('meter_min_without_max_1').max, 1.0);
+ }, "If a value smaller than 1.0 is given to min and max is not specified, max must be the same value as its default value (i.e. 1.0)");
+
+ test(function() {
+ assert_equals(document.getElementById('meter_min_without_max_1').value, 1.0);
+ }, "If a value smaller than 1.0 is given to min, max is not specified, and value is larger than the default value of max (i.e. 1.0), the actual value must be 1.0");
+
+ test(function() {
+ assert_equals(document.getElementById('meter_min_without_max_2').max, 12.1);
+ }, "If a value larger than or equal to 1.0 is given to min and max is not specified, max must be the same value as min");
+
+ test(function() {
+ assert_equals(document.getElementById('meter_min_without_max_2').value, 12.1);
+ }, "If a value larger than or equal to 1.0 is given to min and max is not specified, the actual value must be the same value as min");
+
+ test(function() {
+ assert_equals(document.getElementById('meter_max_without_min_1').min, 0);
+ }, "If a value smaller than 0 is given to max and min is not specified, min must be be the same value as its default value (i.e. 0)");
+
+ test(function() {
+ assert_equals(document.getElementById('meter_max_without_min_1').max, 0);
+ }, "If a value smaller than 0 is given to max and min is not specified, max must be be the same value as the default value of min (i.e. 0)");
+
+ test(function() {
+ assert_equals(document.getElementById('meter_max_without_min_1').value, 0);
+ }, "If a value smaller than 0 is given to max and min is not specified, the actual value must be be the same value as the default value of min (i.e. 0)");
+
+ test(function() {
+ assert_equals(document.getElementById('meter_max_without_min_2').max, 0);
+ }, "If a value larger than or equal to 0 is given to max and min is not specified, max must be the same value as the default value of min (i.e. 0)");
+
+ test(function() {
+ assert_equals(document.getElementById('meter_max_without_min_2').min, 0);
+ }, "If a value larger than or equal to 0 is given to max and min is not specified, min must be the same value as its default value (i.e. 0)");
+
+ test(function() {
+ assert_equals(document.getElementById('meter_max_without_min_2').value, 0);
+ }, "If a value larger than or equal to 0 is given to max and min is not specified, the actual value must be the same value as the default value of min (i.e. 0)");
+
+ test(function() {
+ assert_equals(document.getElementById('meter_illegal_min').min, 0);
+ }, "min must be 0 when a string is given");
+
+ test(function() {
+ assert_equals(document.getElementById('meter_illegal_min').value, 0);
+ }, "If a string is given to min and value is smaller than the default value of min (i.e. 0), the actual value must be 0");
+
+ test(function() {
+ assert_equals(document.getElementById('meter_illegal_max').max, 1.0);
+ }, "max must be 1.0 when a string is given");
+
+ test(function() {
+ assert_equals(document.getElementById('meter_illegal_max').value, 1.0);
+ }, "If a string is given to max and value is larger than the default value of min (i.e. 1.0), the actual value must be 1.0");
+
+ test(function() {
+ assert_equals(document.getElementById('meter_illegal_low_with_min').low, -10.3);
+ }, "giving a string to low must not affect the actual value");
+
+ test(function() {
+ assert_equals(document.getElementById('meter_illegal_high_with_max').high, 1.5);
+ }, "high must equal max when a string is given to high");
+
+ test(function() {
+ assert_equals(document.getElementById('meter_illegal_high_with_max').value, 1.5);
+ }, "giving a string to high must not affect the actual value");
+
+ test(function() {
+ assert_equals(document.getElementById('meter_smaller_than_min').value, 4.5);
+ }, "value must not be smaller than min");
+
+ test(function() {
+ assert_equals(document.getElementById('meter_larger_than_max').value, 52.02);
+ }, "value must not be larger than max");
+
+ test(function() {
+ var e = document.getElementById('meter_default_low_and_high_1');
+ assert_array_equals([e.low,e.high], [-12.3,3.4]);
+ }, "default low and high values equal min and max, respectively");
+
+ test(function() {
+ var e = document.getElementById('meter_default_low_and_high_2');
+ assert_array_equals([e.low,e.high], [0,1.0]);
+ }, "default low and high values equal 0 and 1.0 respectively, if both low and high are not specified");
+
+ test(function() {
+ var e = document.getElementById('meter_low_smaller_than_min');
+ assert_array_equals([e.low,e.min,e.value], [12.3,12.3,12.3]);
+ }, "low must not be smaller than min");
+
+ test(function() {
+ var e = document.getElementById('meter_low_larger_than_max');
+ assert_array_equals([e.low,e.max,e.value], [-34.5,-34.5,-34.5]);
+ }, "low must not be larger than max");
+
+ test(function() {
+ var e = document.getElementById('meter_high_smaller_than_min');
+ assert_array_equals([e.high,e.min,e.value], [12.3,12.3,12.3]);
+ }, "high must not be smaller than min");
+
+ test(function() {
+ var e = document.getElementById('meter_high_larger_than_max');
+ assert_array_equals([e.high,e.max,e.value], [-34.5,-34.5,-34.5]);
+ }, "high must not be larger than max");
+
+ test(function() {
+ var e = document.getElementById('meter_low_without_min');
+ assert_array_equals([e.low,e.min,e.value], [0,0,0]);
+ }, "If min is not specified, low must not be smaller than default value of min (i.e. 0)");
+
+ test(function() {
+ var e = document.getElementById('meter_high_smaller_than_low');
+ assert_array_equals([e.low,e.high,e.value], [-10.3,-10.3,-9]);
+ }, "If a value smaller than low is given to high, it must be set to the same value as low");
+
+ test(function() {
+ var e = document.getElementById('meter_high_without_max');
+ assert_array_equals([e.high,e.value], [1.0,1.0]);
+ }, "If max is not specified, high must not be larger than default value of max (i.e. 1.0)");
+
+ test(function() {
+ assert_equals(document.getElementById('meter_optimum_smaller_than_min').optimum, 0);
+ }, "optimum smaller than min");
+
+ test(function() {
+ var e = document.getElementById('meter_optimum_smaller_than_min');
+ assert_array_equals([e.min,e.value], [0,0]);
+ }, "optimum (smaller than min) must not affect min and the actual value");
+
+ test(function() {
+ assert_equals(document.getElementById('meter_optimum_larger_than_max').optimum, 1.0);
+ }, "optimum smaller than max");
+
+ test(function() {
+ var e = document.getElementById('meter_optimum_larger_than_max');
+ assert_array_equals([e.max,e.value], [1.0,1.0]);
+ }, "optimum (larger than max) must not affect max and the actual value");
+
+ test(function() {
+ var e = document.getElementById('meter_default_optimum');
+ assert_equals(e.optimum, (e.max + e.min) / 2);
+ }, "default optimum value is the midpoint between min and max");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-optgroup-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/forms/the-optgroup-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-optgroup-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-option-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/forms/the-option-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-option-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-option-element/option-label-value.js b/tests/wpt/web-platform-tests/html/semantics/forms/the-option-element/option-label-value.js
new file mode 100644
index 00000000000..5c453f1733e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-option-element/option-label-value.js
@@ -0,0 +1,82 @@
+function test_option(member) {
+ test(function() {
+ var option = document.createElement("option");
+ assert_equals(option[member], "");
+ }, "No children, no " + member);
+
+ test(function() {
+ var option = document.createElement("option");
+ option.setAttribute(member, "")
+ assert_equals(option[member], "");
+ }, "No children, empty " + member);
+
+ test(function() {
+ var option = document.createElement("option");
+ option.setAttribute(member, member)
+ assert_equals(option[member], member);
+ }, "No children, " + member);
+
+ test(function() {
+ var option = document.createElement("option");
+ option.setAttributeNS("http://www.example.com/", member, member)
+ assert_equals(option[member], "");
+ }, "No children, namespaced " + member);
+
+ test(function() {
+ var option = document.createElement("option");
+ option.appendChild(document.createTextNode(" child "));
+ assert_equals(option[member], "child");
+ }, "Single child, no " + member);
+
+ test(function() {
+ var option = document.createElement("option");
+ option.appendChild(document.createTextNode(" child "));
+ option.setAttribute(member, "")
+ assert_equals(option[member], "");
+ }, "Single child, empty " + member);
+
+ test(function() {
+ var option = document.createElement("option");
+ option.appendChild(document.createTextNode(" child "));
+ option.setAttribute(member, member)
+ assert_equals(option[member], member);
+ }, "Single child, " + member);
+
+ test(function() {
+ var option = document.createElement("option");
+ option.appendChild(document.createTextNode(" child "));
+ option.setAttributeNS("http://www.example.com/", member, member)
+ assert_equals(option[member], "child");
+ }, "Single child, namespaced " + member);
+
+ test(function() {
+ var option = document.createElement("option");
+ option.appendChild(document.createTextNode(" child "));
+ option.appendChild(document.createTextNode(" node "));
+ assert_equals(option[member], "child node");
+ }, "Two children, no " + member);
+
+ test(function() {
+ var option = document.createElement("option");
+ option.appendChild(document.createTextNode(" child "));
+ option.appendChild(document.createTextNode(" node "));
+ option.setAttribute(member, "")
+ assert_equals(option[member], "");
+ }, "Two children, empty " + member);
+
+ test(function() {
+ var option = document.createElement("option");
+ option.appendChild(document.createTextNode(" child "));
+ option.appendChild(document.createTextNode(" node "));
+ option.setAttribute(member, member)
+ assert_equals(option[member], member);
+ }, "Two children, " + member);
+
+ test(function() {
+ var option = document.createElement("option");
+ option.appendChild(document.createTextNode(" child "));
+ option.appendChild(document.createTextNode(" node "));
+ option.setAttributeNS("http://www.example.com/", member, member)
+ assert_equals(option[member], "child node");
+ }, "Two children, namespaced " + member);
+}
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-option-element/option-label.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-option-element/option-label.html
new file mode 100644
index 00000000000..f931b962207
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-option-element/option-label.html
@@ -0,0 +1,12 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>HTMLOptionElement.label</title>
+<link rel=author title=Ms2ger href="mailto:Ms2ger@gmail.com">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#dom-option-label">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src=option-label-value.js></script>
+<div id=log></div>
+<script>
+test_option("label")
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-option-element/option-text-backslash.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-option-element/option-text-backslash.html
new file mode 100644
index 00000000000..34bd0d368bf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-option-element/option-text-backslash.html
@@ -0,0 +1,15 @@
+<!doctype html>
+<meta charset=EUC-JP>
+<title>Test for the backslash sign in option.text</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<select id=test><option>\</option></select>
+<script>
+test(function() {
+ var select = document.getElementById("test");
+ var option = select.firstChild;
+ assert_equals(option.text, "\\");
+ assert_equals(option.textContent, "\\");
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-option-element/option-text-label.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-option-element/option-text-label.html
new file mode 100644
index 00000000000..9259aecf303
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-option-element/option-text-label.html
@@ -0,0 +1,23 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>HTMLOptionElement.text</title>
+<link rel=author title=Ms2ger href="mailto:Ms2ger@gmail.com">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#dom-option-text">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+test(function() {
+ var option = document.createElement("option");
+ option.setAttribute("label", "label");
+ option.textContent = "text";
+ assert_equals(option.text, "text");
+}, "Option with non-empty label.");
+
+test(function() {
+ var option = document.createElement("option");
+ option.setAttribute("label", "");
+ option.textContent = "text";
+ assert_equals(option.text, "text");
+}, "Option with empty label.");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-option-element/option-text-recurse.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-option-element/option-text-recurse.html
new file mode 100644
index 00000000000..46baa8e1ce5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-option-element/option-text-recurse.html
@@ -0,0 +1,77 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>HTMLOptionElement.text</title>
+<link rel=author title=Ms2ger href="mailto:Ms2ger@gmail.com">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#dom-option-text">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+test(function() {
+ var option = document.createElement("option");
+ option.appendChild(document.createElement("font"))
+ .appendChild(document.createTextNode(" font "));
+ assert_equals(option.text, "font");
+}, "option.text should recurse");
+
+test(function() {
+ var option = document.createElement("option");
+ option.appendChild(document.createTextNode(" before "));
+ option.appendChild(document.createElement("script"))
+ .appendChild(document.createTextNode(" script "));
+ option.appendChild(document.createTextNode(" after "));
+ assert_equals(option.text, "before after");
+}, "option.text should not recurse into HTML script elements");
+test(function() {
+ var option = document.createElement("option");
+ option.appendChild(document.createTextNode(" before "));
+ option.appendChild(document.createElementNS("http://www.w3.org/2000/svg", "script"))
+ .appendChild(document.createTextNode(" script "));
+ option.appendChild(document.createTextNode(" after "));
+ assert_equals(option.text, "before after");
+}, "option.text should not recurse into SVG script elements");
+test(function() {
+ var option = document.createElement("option");
+ option.appendChild(document.createTextNode(" before "));
+ option.appendChild(document.createElementNS("http://www.w3.org/1998/Math/MathML", "script"))
+ .appendChild(document.createTextNode(" script "));
+ option.appendChild(document.createTextNode(" after "));
+ assert_equals(option.text, "before script after");
+}, "option.text should recurse into MathML script elements");
+test(function() {
+ var option = document.createElement("option");
+ option.appendChild(document.createTextNode(" before "));
+ option.appendChild(document.createElementNS(null, "script"))
+ .appendChild(document.createTextNode(" script "));
+ option.appendChild(document.createTextNode(" after "));
+ assert_equals(option.text, "before script after");
+}, "option.text should recurse into null script elements");
+test(function() {
+ var option = document.createElement("option");
+ var span = option.appendChild(document.createElement("span"));
+ span.appendChild(document.createTextNode(" Some "));
+ span.appendChild(document.createElement("script"))
+ .appendChild(document.createTextNode(" script "));
+ option.appendChild(document.createTextNode(" Text "));
+ assert_equals(option.text, "Some Text");
+}, "option.text should work if a child of the option ends with a script");
+
+test(function() {
+ var script = document.createElement("script");
+ var option = script.appendChild(document.createElement("option"));
+ option.appendChild(document.createTextNode("text"));
+ assert_equals(option.text, "text");
+}, "option.text should work if the option is in an HTML script element");
+test(function() {
+ var script = document.createElementNS("http://www.w3.org/2000/svg", "script");
+ var option = script.appendChild(document.createElement("option"));
+ option.appendChild(document.createTextNode("text"));
+ assert_equals(option.text, "text");
+}, "option.text should work if the option is in an SVG script element");
+test(function() {
+ var script = document.createElementNS("http://www.w3.org/1998/Math/MathML", "script");
+ var option = script.appendChild(document.createElement("option"));
+ option.appendChild(document.createTextNode("text"));
+ assert_equals(option.text, "text");
+}, "option.text should work if the option is in a MathML script element");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-option-element/option-text-spaces.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-option-element/option-text-spaces.html
new file mode 100644
index 00000000000..2c712655a9b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-option-element/option-text-spaces.html
@@ -0,0 +1,75 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>HTMLOptionElement.text</title>
+<link rel=author title=Ms2ger href="mailto:Ms2ger@gmail.com">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#dom-option-text">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+test(function() {
+ var spaces = ["\u0020", "\u0009", "\u000A", "\u000C", "\u000D"];
+ spaces.forEach(function(space) {
+ test(function() {
+ var option = document.createElement("option");
+ option.textContent = space + "text";
+ assert_equals(option.text, "text");
+ }, "option.text should strip leading space characters (" +
+ format_value(space) + ")");
+ });
+ spaces.forEach(function(space) {
+ test(function() {
+ var option = document.createElement("option");
+ option.textContent = "text" + space;
+ assert_equals(option.text, "text");
+ }, "option.text should strip trailing space characters (" +
+ format_value(space) + ")");
+ });
+ spaces.forEach(function(space) {
+ test(function() {
+ var option = document.createElement("option");
+ option.textContent = space + "text" + space;
+ assert_equals(option.text, "text");
+ }, "option.text should strip leading and trailing space characters (" +
+ format_value(space) + ")");
+ });
+ spaces.forEach(function(space) {
+ test(function() {
+ var option = document.createElement("option");
+ option.textContent = "before" + space + "after";
+ assert_equals(option.text, "before after");
+ }, "option.text should replace single internal space characters (" +
+ format_value(space) + ")");
+ });
+ spaces.forEach(function(space1) {
+ spaces.forEach(function(space2) {
+ test(function() {
+ var option = document.createElement("option");
+ option.textContent = "before" + space1 + space2 + "after";
+ assert_equals(option.text, "before after");
+ }, "option.text should replace multiple internal space characters (" +
+ format_value(space1) + ", " + format_value(space2) + ")");
+ });
+ });
+ test(function() {
+ var option = document.createElement("option");
+ option.textContent = "\u00a0text";
+ assert_equals(option.text, "\u00a0text");
+ }, "option.text should leave leading NBSP alone.");
+ test(function() {
+ var option = document.createElement("option");
+ option.textContent = "text\u00a0";
+ assert_equals(option.text, "text\u00a0");
+ }, "option.text should leave trailing NBSP alone.");
+ test(function() {
+ var option = document.createElement("option");
+ option.textContent = "before\u00a0after";
+ assert_equals(option.text, "before\u00a0after");
+ }, "option.text should leave a single internal NBSP alone.");
+ test(function() {
+ var option = document.createElement("option");
+ option.textContent = "before\u00a0\u00a0after";
+ assert_equals(option.text, "before\u00a0\u00a0after");
+ }, "option.text should leave two internal NBSPs alone.");
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-option-element/option-value.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-option-element/option-value.html
new file mode 100644
index 00000000000..cccdc37487e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-option-element/option-value.html
@@ -0,0 +1,12 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>HTMLOptionElement.value</title>
+<link rel=author title=Ms2ger href="mailto:Ms2ger@gmail.com">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#dom-option-label">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src=option-label-value.js></script>
+<div id=log></div>
+<script>
+test_option("value")
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-output-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/forms/the-output-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-output-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-output-element/output.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-output-element/output.html
new file mode 100644
index 00000000000..7682703fa8c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-output-element/output.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>The output element</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#the-output-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<output id=output></output>
+<script>
+ var output = document.getElementById("output");
+
+ test(function(){
+ assert_equals(output.type, "output", "type must return the string 'output'");
+ assert_equals(output.textContent, "", "textContent is empty");
+ assert_equals(output.value, "", "value should be empty");
+ assert_equals(output.defaultValue, "", "defaultValue should be empty");
+
+ output.textContent="5";
+ assert_equals(output.value, "5", "textContent is set to 5: value is updated");
+ assert_equals(output.textContent, "5", "textContent is set to 5");
+ assert_equals(output.defaultValue, "5", "textContent is set to 5: defaultValue is updated");
+
+ output.defaultValue="10"; // value mode flag is in "default" mode. Setting defaultValue should set textContent as well
+ assert_equals(output.value, "10", "defaultValue is set to 10: value is updated");
+ assert_equals(output.textContent, "10", "defaultValue is set to 10: textContent is updated");
+ assert_equals(output.defaultValue, "10", "defaultValue is set to 10");
+
+ output.value="20"; // set the value mode flag to "value": default value remains unchanged
+ assert_equals(output.value, "20", "value is set to 20");
+ assert_equals(output.textContent, "20", "value is set to 20: textContent is updated");
+ assert_equals(output.defaultValue, "10", "value is set to 20: defaultValue remains unchanged");
+
+ output.defaultValue="15"; // value mode flag is in "value" mode. textContent remains unchanged when setting defaultValue
+ assert_equals(output.value, "20", "defaultValue is set to 15: value remains unchanged");
+ assert_equals(output.textContent, "20", "defaultValue is set to 15: textContent remains unchanged");
+ assert_equals(output.defaultValue, "15", "defaultValue is set to 15");
+ }, "output value and defaultValue");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-progress-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/forms/the-progress-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-progress-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-progress-element/progress-2.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-progress-element/progress-2.html
new file mode 100644
index 00000000000..ebc47506278
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-progress-element/progress-2.html
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Progress Element Tests</title>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-progress-element" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <progress id="p00" style="display: none"></progress>
+ <progress id="p01" max="5.5" value=".5" style="display: none"></progress>
+ <script>
+ test(function () {
+ assert_equals(document.getElementById('p00').position, -1);
+ }, "progress position equals -1");
+
+ test(function () {
+ assert_equals(document.getElementById('p00').value, 0);
+ }, "progress value equals 0");
+
+ test(function () {
+ assert_equals(document.getElementById('p01').value, .5);
+ }, "progress value equals .5");
+
+ test(function () {
+ document.getElementById('p00').value = document.getElementById('p00').value;
+ assert_equals(document.getElementById('p00').position, 0);
+ }, "progress position equals 0");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-progress-element/progress.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-progress-element/progress.html
new file mode 100644
index 00000000000..0c176d8ea6e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-progress-element/progress.html
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>The progress element</title>
+
+ <link rel="author" title="dan smith" href="mailto:XX1011@gmail.com">
+ <link rel="author" title="Tomoyuki SHIMIZU" href="mailto:tomoyuki.labs@gmail.com">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-progress-element">
+
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+
+ <progress id="indeterminate"></progress>
+ <progress id="removevalue" value="0.5"></progress>
+ <progress id="quarter" value="1" max="4"></progress>
+ <progress id="largerthanmax" value="2"></progress>
+ <progress id="invalidmax" value="1" max="a"></progress>
+ <progress id="negativemax" value="1" max="-1"></progress>
+ <progress id="invalidvalue" value="a"></progress>
+ <progress id="negativevalue" value="-1"></progress>
+
+ <script>
+
+ test(function() {
+ assert_equals(indeterminate.position, -1);
+ }, "Indeterminate progress bar should have position -1");
+
+ test(function() {
+ removevalue.removeAttribute('value');
+ assert_equals(removevalue.position, -1);
+ }, "Revoming the value attribute makes an intermediate progress bar, which should have position -1");
+
+ test(function() {
+ assert_equals(quarter.position, quarter.value / quarter.max);
+ }, "Determinate progress bar should have fractional position");
+
+ test(function() {
+ assert_equals(indeterminate.value, 0);
+ }, "Indeterminate progress bar should have value 0");
+
+ test(function() {
+ assert_array_equals(largerthanmax.value, 1);
+ }, "Value must equal max if the parsed value is larger than max");
+
+ test(function() {
+ assert_equals(indeterminate.max, 1);
+ }, "Max must be 1 by default");
+
+ test(function() {
+ assert_array_equals(largerthanmax.max, 1);
+ }, "Max must be 1 by default, even if value is specified");
+
+ test(function() {
+ assert_equals(invalidmax.max, 1);
+ }, "Max must be 1 if max value is invalid");
+
+ test(function() {
+ assert_equals(negativemax.max, 1);
+ }, "Max must be 1 if the parsed max value is less than or equal to zero");
+
+ test(function() {
+ assert_equals(invalidvalue.value, 0);
+ }, "Value must be 0 if value is invalid");
+
+ test(function() {
+ assert_equals(negativevalue.value, 0);
+ }, "Value must be 0 if the parsed value is less than or equal to zero");
+
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-select-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/forms/the-select-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-select-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-select-element/common-HTMLOptionsCollection-namedItem.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-select-element/common-HTMLOptionsCollection-namedItem.html
new file mode 100644
index 00000000000..429c642a685
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-select-element/common-HTMLOptionsCollection-namedItem.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title id='title'>HTMLOptionsCollection</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<select id="selly">
+ <option id="id1" name="name1">1</option>
+ <option id="id2" name="name2">2</option>
+ <option id="id3" name="name3">3</option>
+ <option id="id4" name="name4">4</option>
+ <option name="nameonly">nameonly</option>
+ <option id="id3">duplicate ID</option>
+ <option name="name4">duplicate name</option>
+ <option id="mixed1">mixed ID</option>
+ <option name="mixed1">mixed name</option>
+</select>
+
+<script>
+var selly;
+setup(function() {
+ selly = document.getElementById('selly');
+});
+
+test(function () {
+ assert_equals(selly.namedItem('nameonly')["value"], "nameonly");
+}, "if only one item has a *name* or id value matching the parameter, return that object and stop");
+
+test(function () {
+ assert_equals(selly.namedItem('id2')["value"], "2");
+}, "if only one item has a name or *id* value matching the parameter, return that object and stop");
+
+test(function () {
+ assert_equals(selly.namedItem('thisdoesnotexist'), null);
+}, "if no item has a name or id value matching the parameter, return null and stop");
+
+test(function () {
+ var testarr = [];
+ for (var i = 0; i < selly.namedItem('id3').length; i++) {
+ testarr.push(selly.namedItem('id3')[i].text);
+ }
+ assert_array_equals(testarr, ['3','duplicate ID']);
+}, "return an HTMLOptionsCollection in correct order for repeated 'id' value");
+
+test(function () {
+ var testarr = [];
+ for (var i = 0; i < selly.namedItem('name4').length; i++) {
+ testarr.push(selly.namedItem('name4')[i].text);
+ }
+ assert_array_equals(testarr, ['4', 'duplicate name']);
+}, "return an HTMLOptionsCollection in correct order for repeated 'name' value");
+
+test(function () {
+ var testarr = [];
+ for (var i = 0; i < selly.namedItem('mixed1').length; i++) {
+ testarr.push(selly.namedItem('mixed1')[i].text);
+ }
+ assert_array_equals(testarr, ['mixed ID', 'mixed name']);
+}, "return an HTMLOptionsCollection in correct order for repeated mixed value");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-select-element/common-HTMLOptionsCollection.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-select-element/common-HTMLOptionsCollection.html
new file mode 100644
index 00000000000..6bae66ccf78
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-select-element/common-HTMLOptionsCollection.html
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title id='title'>HTMLOptionsCollection</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<select id="selly">
+ <option>1</option>
+ <option>2</option>
+ <option>3</option>
+ <option>4</option>
+</select>
+
+<script>
+var selly;
+setup(function() {
+ selly = document.getElementById('selly');
+});
+
+test(function () {
+ assert_equals(selly.length, 4);
+}, "On getting, the length attribute must return the number of nodes represented by the collection.");
+
+test(function () {
+ selly.length = 7;
+ assert_equals(selly.length, 7,
+ "Number of nodes in collection should have changed");
+ assert_equals(selly.children.length, 7,
+ "Number of children should have changed");
+ for (var i = 4; i < 7; ++i) {
+ var child = selly.children[i];
+ assert_equals(child.localName, "option",
+ "new child should be an option");
+ assert_equals(child.namespaceURI, "http://www.w3.org/1999/xhtml",
+ "new child should be an HTML element");
+ assert_equals(child.attributes.length, 0,
+ "new child should not have attributes");
+ assert_equals(child.childNodes.length, 0,
+ "new child should not have child nodes");
+ }
+}, "Changing the length adds new nodes; The number of new nodes = new length minus old length");
+
+test(function () {
+ var elarray = [];
+ for (var i = 0; i < selly.length; i++) {
+ elarray.push(selly[i].value);
+ }
+ assert_array_equals(elarray, ["1", "2", "3", "4", "", "", ""]);
+}, "New nodes have no value");
+
+test(function () {
+ selly.length = 7;
+ assert_equals(selly.length, 7,
+ "Number of nodes in collection should not have changed");
+ assert_equals(selly.children.length, 7,
+ "Number of children should not have changed");
+}, "Setting a length equal to existing length changes nothing");
+
+test(function () {
+ selly.length = 4;
+ assert_equals(selly[6], undefined,
+ "previously set node is now undefined");
+ assert_equals(selly.length, 4,
+ "Number of nodes in collection is correctly changed");
+ assert_equals(selly.children.length, 4,
+ "Number of children should have changed");
+}, "Setting a length lower than the old length trims nodes from the end");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-select-element/select-named-getter.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-select-element/select-named-getter.html
new file mode 100644
index 00000000000..da43da9d920
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-select-element/select-named-getter.html
@@ -0,0 +1,46 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Absence of a named getter on HTMLSelectElement</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<select id=select>
+ <option id=op1>A</option>
+ <option name=op2>B</option>
+ <option id=op3 name=op4>C</option>
+ <option id=>D</option>
+ <option name=>D</option>
+</select>
+<script>
+test(function() {
+ var select = document.getElementById("select");
+ assert_equals(select.op1, undefined);
+ assert_false("op1" in select);
+ assert_equals(select.namedItem("op1"), select.children[0]);
+}, "Option with id")
+
+test(function() {
+ var select = document.getElementById("select");
+ assert_equals(select.op2, undefined);
+ assert_false("op2" in select);
+ assert_equals(select.namedItem("op2"), select.children[1]);
+}, "Option with name")
+
+test(function() {
+ var select = document.getElementById("select");
+ assert_equals(select.op3, undefined);
+ assert_false("op3" in select);
+ assert_equals(select.namedItem("op3"), select.children[2]);
+
+ assert_equals(select.op4, undefined);
+ assert_false("op4" in select);
+ assert_equals(select.namedItem("op4"), select.children[2]);
+}, "Option with name and id")
+
+test(function() {
+ var select = document.getElementById("select");
+ assert_equals(select[""], undefined);
+ assert_false("" in select);
+ assert_equals(select.namedItem(""), null);
+}, "Empty string name");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-select-element/select-remove.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-select-element/select-remove.html
new file mode 100644
index 00000000000..cf2128bd158
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-select-element/select-remove.html
@@ -0,0 +1,64 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>HTMLSelectElement.remove</title>
+<link rel="author" title="Ms2ger" href="Ms2ger@gmail.com">
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-childnode-remove">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-select-remove">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-htmloptionscollection-remove">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+function testRemove(getter, desc) {
+ test(function() {
+ var div = document.createElement("div");
+ var select = document.createElement("select");
+ div.appendChild(select);
+ assert_equals(select.parentNode, div);
+
+ var options = [];
+ for (var i = 0; i < 3; ++i) {
+ var option = document.createElement("option");
+ option.textContent = String(i);
+ select.appendChild(option);
+ options.push(option);
+ }
+
+ getter(select).remove(-1);
+ assert_array_equals(select.options, options, "After remove(-1)");
+ assert_equals(select.parentNode, div);
+
+ getter(select).remove(3);
+ assert_array_equals(select.options, options, "After remove(3)");
+ assert_equals(select.parentNode, div);
+
+ getter(select).remove(0);
+ assert_array_equals(select.options, [options[1], options[2]], "After remove(0)");
+ assert_equals(select.parentNode, div);
+ }, desc)
+}
+testRemove(function(select) { return select; }, "select.remove(n) should work");
+testRemove(function(select) { return select.options; }, "select.options.remove(n) should work");
+test(function() {
+ var div = document.createElement("div");
+ var select = document.createElement("select");
+ div.appendChild(select);
+ assert_equals(select.parentNode, div);
+ assert_equals(div.firstChild, select);
+
+ select.remove();
+ assert_equals(select.parentNode, null);
+ assert_equals(div.firstChild, null);
+}, "remove() should work on select elements.")
+test(function() {
+ var div = document.createElement("div");
+ var select = document.createElement("select");
+ div.appendChild(select);
+ assert_equals(select.parentNode, div);
+ assert_equals(div.firstChild, select);
+
+ Element.prototype.remove.call(select);
+ assert_equals(select.parentNode, null);
+ assert_equals(div.firstChild, null);
+}, "Element#remove() should work on select elements.")
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-textarea-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/forms/the-textarea-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-textarea-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-textarea-element/textarea-newline-bidi-ref.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-textarea-element/textarea-newline-bidi-ref.html
new file mode 100644
index 00000000000..d69195b4f4a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-textarea-element/textarea-newline-bidi-ref.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>HTML Test reference: newline in &lt;textarea&gt; separates bidi paragraphs</title>
+ <link rel="author" title="Amir E. Aharoni" href="mailto:amir.aharoni@mail.huji.ac.il"/>
+ <link rel="author" title="Eyal Sela" href="mailto:eyal@post.isoc.org.il"/>
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com"/>
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-textarea-element"/>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the rightmost character in the first line below is a full stop and to the left of it is a Hebrew letter.</p></div>
+ <div class="test">
+ <textarea cols="70" rows="3">
+A Hebrew letter and a full stop: &#x05d0;.&lrm;
+&#x05d0; this line begins with a Hebrew letter.
+ </textarea>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-textarea-element/textarea-newline-bidi.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-textarea-element/textarea-newline-bidi.html
new file mode 100644
index 00000000000..ce1ff944c29
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-textarea-element/textarea-newline-bidi.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8"/>
+ <title>HTML Test: newline in &lt;textarea&gt; separates bidi paragraphs</title>
+ <link rel="match" href="textarea-newline-bidi-ref.html" />
+ <link rel="author" title="Amir E. Aharoni" href="mailto:amir.aharoni@mail.huji.ac.il"/>
+ <link rel="author" title="Eyal Sela" href="mailto:eyal@post.isoc.org.il"/>
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com"/>
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-textarea-element"/>
+ <meta name="assert"
+ content="A newline in a textarea element, and in its raw value, should separate paragraphs for the purposes of the Unicode bidirectional algorithm."/>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the rightmost character in the first line below is a full stop and to the left of it is a Hebrew letter.</p></div>
+ <div class="test">
+ <textarea cols="70" rows="3">
+A Hebrew letter and a full stop: &#x05d0;.
+&#x05d0; this line begins with a Hebrew letter.
+ </textarea>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-textarea-element/textarea-type.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-textarea-element/textarea-type.html
new file mode 100644
index 00000000000..ac80f936567
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-textarea-element/textarea-type.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML>
+<title>The type IDL attribute</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-textarea-type">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="test">
+<textarea></textarea>
+</div>
+<script>
+test(function() {
+ assert_equals(document.getElementById("test")
+ .getElementsByTagName("textarea")[0].type,
+ "textarea");
+}, "Textarea's type attribute should return 'textarea'");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-textarea-element/wrap-reflect-1-ref.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-textarea-element/wrap-reflect-1-ref.html
new file mode 100644
index 00000000000..98a7f8a3af6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-textarea-element/wrap-reflect-1-ref.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<title>Dynamic manipulation of textarea.wrap</title>
+<link rel=help href=https://html.spec.whatwg.org/multipage/#dom-textarea-wrap>
+<link rel=author title=Ms2ger href=mailto:ms2ger@gmail.com>
+<textarea wrap=soft cols=20>01234567890 01234567890 01234567890</textarea>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-textarea-element/wrap-reflect-1a.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-textarea-element/wrap-reflect-1a.html
new file mode 100644
index 00000000000..4a965f5d48e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-textarea-element/wrap-reflect-1a.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<title>Dynamic manipulation of textarea.wrap</title>
+<link rel=help href=https://html.spec.whatwg.org/multipage/#dom-textarea-wrap>
+<link rel=author title=Ms2ger href=mailto:ms2ger@gmail.com>
+<textarea wrap=off cols=20>01234567890 01234567890 01234567890</textarea>
+<script>
+document.getElementsByTagName("textarea")[0].wrap = "soft";
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-textarea-element/wrap-reflect-1b.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-textarea-element/wrap-reflect-1b.html
new file mode 100644
index 00000000000..8c20dc9f120
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-textarea-element/wrap-reflect-1b.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<title>Dynamic manipulation of textarea.wrap</title>
+<link rel=help href=https://html.spec.whatwg.org/multipage/#dom-textarea-wrap>
+<link rel=author title=Ms2ger href=mailto:ms2ger@gmail.com>
+<textarea wrap=off cols=20>01234567890 01234567890 01234567890</textarea>
+<script>
+document.getElementsByTagName("textarea")[0].setAttribute("wrap", "soft");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/grouping-content/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/grouping-content/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/grouping-content/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-blockquote-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-blockquote-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-blockquote-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-dd-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-dd-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-dd-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-dd-element/grouping-dd.html b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-dd-element/grouping-dd.html
new file mode 100644
index 00000000000..022e555bd24
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-dd-element/grouping-dd.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>the dd element</title>
+ <link rel="author" title="dzenana" href="mailto:dzenana.trenutak@gmail.com">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dd-element">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ "use strict";
+
+ // check that prototype matches spec's DOM interface
+ test(function () {
+ var testElement = document.createElement("dd");
+ assert_equals(Object.getPrototypeOf(testElement), HTMLElement.prototype, "HTMLElement.prototype should be used for dd");
+ }, "The prototype for dd is HTMLElement.prototype");
+
+ </script>
+</head>
+<body>
+ <h1>Description</h1>
+ <p>This test validates the dd element.</p>
+
+ <div id="log"></div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-div-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-div-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-div-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-div-element/grouping-div.html b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-div-element/grouping-div.html
new file mode 100644
index 00000000000..ffde6eb53f8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-div-element/grouping-div.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>The div element</title>
+ <link rel="author" title="dzenana" href="mailto:dzenana.trenutak@gmail.com">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-div-element">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ "use strict";
+
+ // check that prototype matches spec's DOM interface
+ test(function () {
+ var testElement = document.createElement("div");
+ assert_equals(Object.getPrototypeOf(testElement), HTMLDivElement.prototype, "HTMLDivElement.prototype should be used for div");
+ }, "The prototype for div is HTMLDivElement.prototype");
+
+ </script>
+</head>
+<body>
+ <h1>Description</h1>
+ <p>This test validates the div element.</p>
+
+ <div id="log"></div>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-dl-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-dl-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-dl-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-dl-element/grouping-dl.html b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-dl-element/grouping-dl.html
new file mode 100644
index 00000000000..2394d6a9298
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-dl-element/grouping-dl.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>the dl element</title>
+ <link rel="author" title="dzenana" href="mailto:dzenana.trenutak@gmail.com">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dl-element">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ "use strict";
+
+ // check that prototype matches spec's DOM interface
+ test(function () {
+ var testElement = document.createElement("dl");
+ assert_equals(Object.getPrototypeOf(testElement), HTMLDListElement.prototype, "HTMLDListElement.prototype should be used for dl");
+ }, "The prototype for dl is HTMLDListElement.prototype");
+
+ // Not checking: effects of markup on defining groups and the name-pair values within those groups
+
+ </script>
+</head>
+<body>
+ <h1>Description</h1>
+ <p>This test validates the dl element.</p>
+
+ <div id="log"></div>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-dt-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-dt-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-dt-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-dt-element/grouping-dt.html b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-dt-element/grouping-dt.html
new file mode 100644
index 00000000000..1dbb4384dd2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-dt-element/grouping-dt.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>the dl element</title>
+ <link rel="author" title="dzenana" href="mailto:dzenana.trenutak@gmail.com">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-dt-element">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ "use strict";
+
+ // check that prototype matches spec's DOM interface
+ test(function () {
+ var testElement = document.createElement("dt");
+ assert_equals(Object.getPrototypeOf(testElement), HTMLElement.prototype, "HTMLElement.prototype should be used for dt");
+ }, "The prototype for dt is HTMLElement.prototype");
+
+ </script>
+</head>
+<body>
+ <h1>Description</h1>
+ <p>This test validates the dt element.</p>
+
+ <div id="log"></div>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-figcaption-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-figcaption-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-figcaption-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-figcaption-element/grouping-figcaption.html b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-figcaption-element/grouping-figcaption.html
new file mode 100644
index 00000000000..68e7a516b41
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-figcaption-element/grouping-figcaption.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>the figcaption element</title>
+ <link rel="author" title="dzenana" href="mailto:dzenana.trenutak@gmail.com">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-figcaption-element">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ "use strict";
+
+ // check that prototype matches spec's DOM interface
+ test(function () {
+ var testElement = document.createElement("figcaption");
+ assert_equals(Object.getPrototypeOf(testElement), HTMLElement.prototype, "HTMLElement.prototype should be used for figcaption");
+ }, "The prototype for figcaption is HTMLElement.prototype");
+
+ </script>
+</head>
+<body>
+ <h1>Description</h1>
+ <p>This test validates the figcaption element.</p>
+
+ <div id="log"></div>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-figure-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-figure-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-figure-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-figure-element/grouping-figure.html b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-figure-element/grouping-figure.html
new file mode 100644
index 00000000000..31c156ce380
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-figure-element/grouping-figure.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>the figure element</title>
+ <link rel="author" title="dzenana" href="mailto:dzenana.trenutak@gmail.com">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-figure-element">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ "use strict";
+
+ // check that prototype matches spec's DOM interface
+ test(function () {
+ var testElement = document.createElement("figure");
+ assert_equals(Object.getPrototypeOf(testElement), HTMLElement.prototype, "HTMLElement.prototype should be used for figure");
+ }, "The prototype for figure is HTMLElement.prototype");
+
+ // Not checking: Sectioning root
+
+ </script>
+</head>
+<body>
+ <h1>Description</h1>
+ <p>This test validates the figure element.</p>
+
+ <div id="log"></div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-hr-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-hr-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-hr-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-hr-element/grouping-hr.html b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-hr-element/grouping-hr.html
new file mode 100644
index 00000000000..eeadd97d446
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-hr-element/grouping-hr.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>the hr element</title>
+ <link rel="author" title="dzenana" href="mailto:dzenana.trenutak@gmail.com">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-hr-element">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ "use strict";
+
+ // check that prototype matches spec's DOM interface
+ test(function () {
+ var testElement = document.createElement("hr");
+ assert_equals(Object.getPrototypeOf(testElement), HTMLHRElement.prototype, "HTMLHRElement.prototype should be used for hr");
+ }, "The prototype for hr is HTMLHRElement.prototype");
+
+ // Not checking: "The hr element does not affect the document's outline."
+
+ </script>
+</head>
+<body>
+ <h1>Description</h1>
+ <p>This test validates the hr element.</p>
+
+ <div id="log"></div>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-li-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-li-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-li-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-li-element/grouping-li-novalue-manual.html b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-li-element/grouping-li-novalue-manual.html
new file mode 100644
index 00000000000..346ed566296
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-li-element/grouping-li-novalue-manual.html
@@ -0,0 +1,148 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Body Element</title>
+ <link rel="author" title="dzenana" href="mailto:dzenana.trenutak@gmail.com">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-body-element">
+ <meta name="flags" content="interact" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <h1>Validation of li characteristic requiring manual testing</h1>
+
+ <p>The spec states: "If the parent element is an ol element, then the li element has an ordinal value."</p>
+ <p>This manual test is needed to verify that NON-ol element parents do NOT result in an ordinal value.</p>
+ <p>It needs to be manual because the ordinal value assigned to each list element by the user agent is NOT available programmatically. Values which are set either via markup or IDL are available programmatically, but not the calculated values for all the other list items.</p>
+ <p>And, as we cannot be sure how a mistakenly assigned value would be rendered, this test cannot be a reftest.</p>
+ <p>So, please use the buttons to answer the following questions:</p>
+
+ <table>
+ <thead>
+ <tr>
+ <th>HTML Markup</th>
+ <th>Do you see any sort of sequencing information?</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>
+ <menu>
+ <li>Menu Item</li>
+ <li>Menu Item</li>
+ </menu>
+ </td>
+ <td>
+ <input type="button" id="btnMenuYes" value="Yes" />
+ <input type="button" id="btnMenuNo" value="No" />
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <menu type="toolbar">
+ <li>
+ <menu label="ToolbarLabel">
+ <li><a>Toolbar Menu Item</a></li>
+ <li><a>Toolbar Menu Item</a></li>
+ </menu>
+ </li>
+ <li>
+ <menu label="ToolbarLabel">
+ <li><a>Toolbar Menu Item</a></li>
+ <li><a>Toolbar Menu Item</a></li>
+ </menu>
+ </li>
+ </menu>
+ </td>
+ <td>
+ <input type="button" id="btnToolbarYes" value="Yes" />
+ <input type="button" id="btnToolbarNo" value="No" />
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <ul>
+ <li>list item</li>
+ <li>list item</li>
+ <li>list item</li>
+ </ul>
+ </td>
+ <td>
+ <input type="button" id="btnULYes" value="Yes" />
+ <input type="button" id="btnULNo" value="No" />
+ </td>
+ </tr>
+ </tbody>
+ </table>
+
+ <div id="log"></div>
+
+ <script>
+ "use strict";
+
+ var testMenu = {}, testToolbar = {}, testUL = {};
+
+ // need to be able to wait for user to push button
+ setup(function () {
+ btnMenuYes.disabled = false;
+ btnMenuNo.disabled = false;
+ btnToolbarYes.disabled = false;
+ btnToolbarNo.disabled = false;
+ btnULYes.disabled = false;
+ btnULNo.disabled = false;
+ },
+ { explicit_timeout: true }
+ );
+
+ // register async tests
+ testMenu = async_test("Check that menu element does not result in values for list items.");
+ testToolbar = async_test("Check that toolbar type menu element does not result in values for list items.");
+ testUL = async_test("Check that unordered list element does not result in values for list items.");
+
+ // run async tests after buttons are clicked - MENU test
+ document.getElementById("btnMenuNo").onclick = testMenu.step_func(function (event) {
+ assert_true(true, "No sequencing applied to list elements inside menu.");
+ testMenu.done();
+ btnMenuYes.disabled = true;
+ btnMenuNo.disabled = true;
+ });
+ document.getElementById("btnMenuYes").onclick = testMenu.step_func(function (event) {
+ assert_true(false, "No sequencing applied to list elements inside menu.");
+ testMenu.done();
+ btnMenuYes.disabled = true;
+ btnMenuNo.disabled = true;
+ });
+
+ // run async tests after buttons are clicked -TOOLBAR test
+ document.getElementById("btnToolbarNo").onclick = testToolbar.step_func(function (event) {
+ assert_true(true, "No sequencing applied to list elements inside toolbar menu.");
+ testToolbar.done();
+ btnToolbarYes.disabled = true;
+ btnToolbarNo.disabled = true;
+ });
+ document.getElementById("btnToolbarYes").onclick = testToolbar.step_func(function (event) {
+ assert_true(false, "No sequencing applied to list elements inside toolbar menu.");
+ testToolbar.done();
+ btnToolbarYes.disabled = true;
+ btnToolbarNo.disabled = true;
+ });
+
+ // run async tests after buttons are clicked - UL test
+ document.getElementById("btnULNo").onclick = testUL.step_func(function (event) {
+ assert_true(true, "No sequencing applied to list elements inside UL.");
+ testUL.done();
+ btnULYes.disabled = true;
+ btnULNo.disabled = true;
+ });
+ document.getElementById("btnULYes").onclick = testUL.step_func(function (event) {
+ assert_true(false, "No sequencing applied to list elements inside UL.");
+ testUL.done();
+ btnULYes.disabled = true;
+ btnULNo.disabled = true;
+ });
+
+
+ </script>
+
+</body>
diff --git a/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-li-element/grouping-li-reftest-001-ref.html b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-li-element/grouping-li-reftest-001-ref.html
new file mode 100644
index 00000000000..e92a3a9ba73
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-li-element/grouping-li-reftest-001-ref.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>li element</title>
+ <link rel="author" title="dzenana" href="mailto:dzenana.trenutak@gmail.com">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-li-element">
+ <link rel="match" href="grouping-li-reftest-001.html" />
+ <meta name="assert" content="The value attribute has no effect when applied to a li element whose parent is a non-ol element." />
+</head>
+<body>
+ <h1>Description</h1>
+ <p>This test continues to validate the li element.</p>
+
+ <p>The spec states:</p>
+ <blockquote>"If the parent element is an ol element, then the li element has an ordinal value. The value attribute is processed relative to the element's parent ol element (q.v.), if there is one. If there is not, the attribute has no effect."</blockquote>
+ <p>This reftest verifies that the value attribute has no effect when applied to a list item NOT having an ol parent.</p>
+ <p>A reftest is necessary because the values of li elements as calculated by the user agent are NOT available programatically. Only explicitly-set values are then available programatically.</p>
+ <p>This reftest passes if you see NO sequencing information on any of the items below.</p>
+
+ <p>Unordered List</p>
+ <ul>
+ <li>list item</li>
+ <li>list item</li>
+ <li>list item</li>
+ </ul>
+
+ <menu>
+ <li>Menu Item</li>
+ <li>Menu Item</li>
+ </menu>
+
+ <menu type="toolbar">
+ <li>
+ <menu label="ToolbarLabel">
+ <li><a>Toolbar Menu Item</a></li>
+ <li><a>Toolbar Menu Item</a></li>
+ </menu>
+ </li>
+ <li>
+ <menu label="ToolbarLabel">
+ <li><a>Toolbar Menu Item</a></li>
+ <li><a>Toolbar Menu Item</a></li>
+ </menu>
+ </li>
+ </menu>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-li-element/grouping-li-reftest-001.html b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-li-element/grouping-li-reftest-001.html
new file mode 100644
index 00000000000..71b72c2ce9e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-li-element/grouping-li-reftest-001.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>li element</title>
+ <link rel="author" title="dzenana" href="mailto:dzenana.trenutak@gmail.com">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-li-element">
+ <link rel="match" href="grouping-li-reftest-001-ref.html" />
+ <meta name="assert" content="The value attribute has no effect when applied to a li element whose parent is a non-ol element." />
+</head>
+<body>
+ <h1>Description</h1>
+ <p>This test continues to validate the li element.</p>
+
+ <p>The spec states:</p>
+ <blockquote>"If the parent element is an ol element, then the li element has an ordinal value. The value attribute is processed relative to the element's parent ol element (q.v.), if there is one. If there is not, the attribute has no effect."</blockquote>
+ <p>This reftest verifies that the value attribute has no effect when applied to a list item NOT having an ol parent.</p>
+ <p>A reftest is necessary because the values of li elements as calculated by the user agent are NOT available programatically. Only explicitly-set values are then available programatically.</p>
+ <p>This reftest passes if you see NO sequencing information on any of the items below.</p>
+
+ <p>Unordered List</p>
+ <ul>
+ <li value="2">list item</li>
+ <li>list item</li>
+ <li>list item</li>
+ </ul>
+
+ <menu>
+ <li>Menu Item</li>
+ <li value="3">Menu Item</li>
+ </menu>
+
+ <menu type="toolbar">
+ <li value="4">
+ <menu label="ToolbarLabel">
+ <li value="5"><a>Toolbar Menu Item</a></li>
+ <li><a>Toolbar Menu Item</a></li>
+ </menu>
+ </li>
+ <li value="6">
+ <menu label="ToolbarLabel">
+ <li value="10"><a>Toolbar Menu Item</a></li>
+ <li><a>Toolbar Menu Item</a></li>
+ </menu>
+ </li>
+ </menu>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-li-element/grouping-li-reftest-002-ref.html b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-li-element/grouping-li-reftest-002-ref.html
new file mode 100644
index 00000000000..00a95d1ca78
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-li-element/grouping-li-reftest-002-ref.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>li element</title>
+ <link rel="author" title="dzenana" href="mailto:dzenana.trenutak@gmail.com">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-li-element">
+ <link rel="match" href="grouping-li-reftest-002-ref.html" />
+ <meta name="assert" content="li elements with ol parents have ordinal values." />
+ <style type="text/css">
+ span p {display:list-item; margin-left: 0; margin-top: 0; margin-bottom: 0; padding-left: 0; padding-top: 0; padding-bottom: 0;}
+ span span p {margin-left: 0; margin-top: 0; margin-bottom: 0; padding-left: 5em; padding-top: 0; padding-bottom: 0; font-family: monospace;}
+ </style>
+</head>
+<body>
+ <h1>Description</h1>
+ <p>This test continues to validate the li element.</p>
+
+ <p>The spec states:</p>
+ <blockquote>"If the parent element is an ol element, then the li element has an ordinal value. The value attribute is processed relative to the element's parent ol element (q.v.), if there is one. If there is not, the attribute has no effect."</blockquote>
+ <p>This reftest verifies that the value attribute has an effect when applied to a list item with an ol parent.</p>
+ <p>A reftest is necessary because the values of li elements as calculated by the user agent are NOT available programatically. Only explicitly-set values are then available programatically.</p>
+ <p>This reftest passes if you see the numbers 1. 2. 3. below the words "Ordered List"</p>
+
+ <span>
+ <p>Ordered List</p>
+ <span>
+ <p>1.</p>
+ <p>2.</p>
+ <p>3.</p>
+ </span>
+ </span>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-li-element/grouping-li-reftest-002.html b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-li-element/grouping-li-reftest-002.html
new file mode 100644
index 00000000000..ae4eebee196
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-li-element/grouping-li-reftest-002.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>li element</title>
+ <link rel="author" title="dzenana" href="mailto:dzenana.trenutak@gmail.com">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-li-element">
+ <link rel="match" href="grouping-li-reftest-002-ref.html" />
+ <meta name="assert" content="li elements with ol parents have ordinal values." />
+ <style type="text/css">
+ span p {display:list-item; margin-left: 0; margin-top: 0; margin-bottom: 0; padding-left: 0; padding-top: 0; padding-bottom: 0;}
+ span li {margin-left: 0; margin-top: 0; margin-bottom: 0; padding-left: 0; padding-top: 0; padding-bottom: 0; font-family: monospace;}
+ span ol {margin-left: 0; margin-top: 0; margin-bottom: 0; padding-left: 5em; padding-top: 0; padding-bottom: 0; font-family: monospace;
+ list-style-position: inside; list-style-type: decimal; }
+ </style>
+</head>
+<body>
+ <h1>Description</h1>
+ <p>This test continues to validate the li element.</p>
+
+ <p>The spec states:</p>
+ <blockquote>"If the parent element is an ol element, then the li element has an ordinal value. The value attribute is processed relative to the element's parent ol element (q.v.), if there is one. If there is not, the attribute has no effect."</blockquote>
+ <p>This reftest verifies that the value attribute has an effect when applied to a list item with an ol parent.</p>
+ <p>A reftest is necessary because the values of li elements as calculated by the user agent are NOT available programatically. Only explicitly-set values are then available programatically.</p>
+ <p>This reftest passes if you see the numbers 1. 2. 3. below the words "Ordered List"</p>
+
+ <span>
+ <p>Ordered List</p>
+ <ol>
+ <li></li>
+ <li></li>
+ <li></li>
+ </ol>
+ </span>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-li-element/grouping-li.html b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-li-element/grouping-li.html
new file mode 100644
index 00000000000..9deb9b59139
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-li-element/grouping-li.html
@@ -0,0 +1,205 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>li element</title>
+ <link rel="author" title="dzenana" href="mailto:dzenana.trenutak@gmail.com">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-li-element">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <h1>Description</h1>
+ <p>This test validates the li element.</p>
+
+ <div id="log"></div>
+
+ <span>
+ <menu id="listmenu">
+ <li>Command</li>
+ <li value="3">Command</li>
+ </menu>
+
+ <menu type="toolbar" id="toolbarmenu">
+ <li>
+ <menu label="File">
+ <button type="button">New...</button>
+ <button type="button">Open...</button>
+ </menu>
+ </li>
+ <li value="10">
+ <menu label="Help">
+ <li value = "2"><a href="help.html">Help Me</a></li>
+ <li><a href="about.html">About</a></li>
+ </menu>
+ </li>
+ </menu>
+
+ <p>Unordered List</p>
+ <ul id="unordered">
+ <li id="test_li">list item</li>
+ <li>list item</li>
+ <li>list item</li>
+ </ul>
+ </span>
+
+ <p>Ordered List</p>
+ <ol id="basic">
+ <li>list item</li>
+ <li>list item</li>
+ <li>list item</li>
+ </ol>
+
+ <p>Ordered List</p>
+ <ol id="start2">
+ <li value="2">list item</li>
+ <li>list item</li>
+ <li>list item</li>
+ </ol>
+
+ <p>Ordered List</p>
+ <ol id="negative">
+ <li value="-10">list item</li>
+ <li>list item</li>
+ <li>list item</li>
+ </ol>
+
+ <p>Ordered List</p>
+ <ol id="posFloatDown">
+ <li value="4.03">list item</li>
+ <li>list item</li>
+ <li>list item</li>
+ </ol>
+
+ <p>Ordered List</p>
+ <ol id="negFloatDown">
+ <li value="-4.03">list item</li>
+ <li>list item</li>
+ <li>list item</li>
+ </ol>
+
+ <p>Ordered List</p>
+ <ol id="posFloatUp">
+ <li value="4.9">list item</li>
+ <li>list item</li>
+ <li>list item</li>
+ </ol>
+
+ <p>Ordered List</p>
+ <ol id="negFloatUp">
+ <li value="-4.9">list item</li>
+ <li>list item</li>
+ <li>list item</li>
+ </ol>
+
+ <p>Ordered List</p>
+ <ol id="exponent">
+ <li value="7e2">list item</li>
+ <li>list item</li>
+ <li>list item</li>
+ </ol>
+
+ <p>Ordered List</p>
+ <ol id="decimal">
+ <li value=".5">list item</li>
+ <li>list item</li>
+ <li>list item</li>
+ </ol>
+
+ <p>Ordered List</p>
+ <ol id="letter">
+ <li value="A">list item</li>
+ <li>list item</li>
+ <li>list item</li>
+ </ol>
+
+ <script>
+ "use strict";
+
+ var testLI = document.getElementById("test_li"), testList = [], i = 0;
+
+ // check that prototype matches spec's DOM interface
+ test(function() {
+ assert_equals(Object.getPrototypeOf(testLI), HTMLLIElement.prototype, "HTMLLIElement.prototype should be used for li");
+ }, "The prototype for li is HTMLLIElement.prototype");
+
+ // check that "own" property "value" is present
+ test(function() {
+ assert_own_property(testLI,"value", "li should have a 'value' attribute");
+ }, "li should have a 'value' attribute");
+
+ // "The [value] attribute has no default value" so, per https://html.spec.whatwg.org/multipage/#reflect,
+ // the default when unspecified is 0
+ testList = document.querySelectorAll("#unordered li, #basic li");
+ test(function() {
+ for(i = 0; i < testList.length; i++) {
+ assert_equals(testList[i].value, 0, "Default (unspecified) value of value is 0.");
+ }
+ }, "Default (unspecified) value of value is 0.");
+
+ // "If the value attribute is present, user agents must parse it as an integer, in order to determine the attribute's value.
+ // If the attribute's value cannot be converted to a number, the attribute must be treated as if it was absent."
+ // Per https://html.spec.whatwg.org/multipage/#collect-a-sequence-of-characters,
+ // an integer is parsed by collecting as many digits as possible and then aborting at the first
+ // non-digit character after the first digit (otherwise, with no beginning digit, it's just an error)
+ // and: "The value IDL attribute must reflect the value of the value content attribute."
+
+ // start2's first element has value of 2
+ test(function() {
+ testLI = document.getElementById("start2").children[0];
+ assert_equals(testLI.value, 2, "value of 2 -> value of 2");
+ }, ".value property reflects content attribute - and both parse value of '2' correctly.");
+
+ // negative's first element has value of -10
+ test(function() {
+ testLI = document.getElementById("negative").children[0];
+ assert_equals(testLI.value, -10, "value of -10 -> value of -10");
+ }, "IDL and content attribute parse value of '-10' correctly.");
+
+ // posFloatDown's first element has value of 4.03 which should return 4
+ test(function() {
+ testLI = document.getElementById("posFloatDown").children[0];
+ assert_equals(testLI.value, 4, "value of 4.03 -> 4");
+ }, "IDL and content attribute parse value of '4.03' correctly.");
+
+ // negFloatDown's first element has value of -4.03 which should return -4
+ test(function() {
+ testLI = document.getElementById("negFloatDown").children[0];
+ assert_equals(testLI.value, -4, "value of -4.03 -> -4");
+ }, "IDL and content attribute parse value of '-4.03' correctly.");
+
+ // posFloatUp's first element has value of 4.9 which should return 4
+ test(function() {
+ testLI = document.getElementById("posFloatUp").children[0];
+ assert_equals(testLI.value, 4, "value of 4.9 -> 4");
+ }, "IDL and content attribute parse value of '4.9' correctly.");
+
+ // negFloatUp's first element has value of -4.9 which should return -4
+ test(function() {
+ testLI = document.getElementById("negFloatUp").children[0];
+ assert_equals(testLI.value, -4, "value of -4.9 -> -4");
+ }, "IDL and content attribute parse value of '-4.9' correctly.");
+
+ // exponent's first element has value of 7e2 which should return 7
+ test(function() {
+ testLI = document.getElementById("exponent").children[0];
+ assert_equals(testLI.value, 7, "value of 7e2 -> 7");
+ }, "IDL and content attribute parse value of '7e2' correctly.");
+
+ // decimal's first element has value of .5 which should return 0
+ test(function() {
+ testLI = document.getElementById("decimal").children[0];
+ assert_equals(testLI.value, 0, "value of .5 -> 0 (default)");
+ }, "IDL and content attribute parse value of '.5' correctly.");
+
+ // letter's first element has value of A which should return 0
+ test(function() {
+ testLI = document.getElementById("letter").children[0];
+ assert_equals(testLI.value, 0, "value of A -> 0 (default)");
+ }, "IDL and content attribute parse value of 'A' correctly.");
+
+ // SHOULD I TEST MORE NON-ASCII-DIGIT ENTRIES?
+
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/grouping-ol-rev-reftest-001-ref.html b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/grouping-ol-rev-reftest-001-ref.html
new file mode 100644
index 00000000000..5bb9758e91f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/grouping-ol-rev-reftest-001-ref.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>ol element</title>
+ <link rel="author" title="dzenana" href="mailto:dzenana.trenutak@gmail.com">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-ol-element">
+ <link rel="match" href="grouping-ol-rev-reftest-001.html" />
+ <meta name="assert" content="OL's reversed attribute creates a descending list." />
+ <style type="text/css">
+ span p {display:list-item; margin-left: 0; margin-top: 0; margin-bottom: 0; padding-left: 0; padding-top: 0; padding-bottom: 0;}
+ span span p {margin-left: 0; margin-top: 0; margin-bottom: 0; padding-left: 5em; padding-top: 0; padding-bottom: 0; font-family: monospace;}
+ </style>
+</head>
+<body>
+ <h1>Description</h1>
+ <p>This test continues to validate the ol element.</p>
+
+ <p>These reftests are necessary because the values of the ol's li children as calculated by the user agent are NOT available programatically. Only explicitly-set values are available programatically. Therefore, we need to check actual rendering against expected rendering.</p>
+
+ <p>The spec states:</p>
+ <blockquote>"The reversed attribute is a boolean attribute. If present, it indicates that the list is a descending list (..., 3, 2, 1). If the attribute is omitted, the list is an ascending list (1, 2, 3, ...)."</blockquote>
+
+ <p><strong>This reftest passes if you see an ascending list followed by two descending lists.</strong></p>
+ <p>(Note: each list item has no content; only the sequencing should appear.)</p>
+
+ <span>
+
+ <p>Ordered List</p>
+ <span>
+ <p>1.</p>
+ <p>2.</p>
+ <p>3.</p>
+ </span>
+
+ <p>Ordered List - reversed via content attribute</p>
+ <span>
+ <p>3.</p>
+ <p>2.</p>
+ <p>1.</p>
+ </span>
+
+ <p>Ordered List - reversed via IDL</p>
+ <span>
+ <p>3.</p>
+ <p>2.</p>
+ <p>1.</p>
+ </span>
+
+ </span>
+
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/grouping-ol-rev-reftest-001.html b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/grouping-ol-rev-reftest-001.html
new file mode 100644
index 00000000000..32d4f2c86f9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/grouping-ol-rev-reftest-001.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>ol element</title>
+ <link rel="author" title="dzenana" href="mailto:dzenana.trenutak@gmail.com">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-ol-element">
+ <link rel="match" href="grouping-ol-rev-reftest-001-ref.html" />
+ <meta name="assert" content="OL's reversed attribute creates a descending list." />
+ <style type="text/css">
+ span p {display:list-item; margin-left: 0; margin-top: 0; margin-bottom: 0; padding-left: 0; padding-top: 0; padding-bottom: 0;}
+ span li {margin-left: 0; margin-top: 0; margin-bottom: 0; padding-left: 0; padding-top: 0; padding-bottom: 0; font-family: monospace;}
+ span ol {margin-left: 0; margin-top: 0; margin-bottom: 0; padding-left: 5em; padding-top: 0; padding-bottom: 0; font-family: monospace;
+ list-style-position: inside; list-style-type: decimal; }
+ </style>
+</head>
+<body>
+ <h1>Description</h1>
+ <p>This test continues to validate the ol element.</p>
+
+ <p>These reftests are necessary because the values of the ol's li children as calculated by the user agent are NOT available programatically. Only explicitly-set values are available programatically. Therefore, we need to check actual rendering against expected rendering.</p>
+
+ <p>The spec states:</p>
+ <blockquote>"The reversed attribute is a boolean attribute. If present, it indicates that the list is a descending list (..., 3, 2, 1). If the attribute is omitted, the list is an ascending list (1, 2, 3, ...)."</blockquote>
+
+ <p><strong>This reftest passes if you see an ascending list followed by two descending lists.</strong></p>
+ <p>(Note: each list item has no content; only the sequencing should appear.)</p>
+
+ <span>
+
+ <p>Ordered List</p>
+ <ol>
+ <li></li>
+ <li></li>
+ <li></li>
+ </ol>
+
+ <p>Ordered List - reversed via content attribute</p>
+ <ol reversed="reversed">
+ <li></li>
+ <li></li>
+ <li></li>
+ </ol>
+
+ <p>Ordered List - reversed via IDL</p>
+ <ol id="reverse_me">
+ <li></li>
+ <li></li>
+ <li></li>
+ </ol>
+
+ </span>
+
+ <script>
+ document.getElementById("reverse_me").reversed = true;
+ </script>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/grouping-ol-start-reftest-001-ref.html b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/grouping-ol-start-reftest-001-ref.html
new file mode 100644
index 00000000000..5180e03d18c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/grouping-ol-start-reftest-001-ref.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>ol element</title>
+ <link rel="author" title="dzenana" href="mailto:dzenana.trenutak@gmail.com">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-ol-element">
+ <link rel="match" href="grouping-ol-start-reftest-001.html" />
+ <meta name="assert" content="Sequences produced by calculated values for LI elements within OL match spec's expectations. (part one)" />
+ <style type="text/css">
+ span p {display:list-item; margin-left: 0; margin-top: 0; margin-bottom: 0; padding-left: 0; padding-top: 0; padding-bottom: 0;}
+ span span p {margin-left: 0; margin-top: 0; margin-bottom: 0; padding-left: 5em; padding-top: 0; padding-bottom: 0; font-family: monospace;}
+ </style>
+</head>
+<body>
+ <p>This test continues to validate the ol element. This reftest is necessary because the values of the ol's li children as calculated and displayed by the user agent are NOT systematically available programatically. Only explicitly-set values are available programatically. Therefore, we need to check actual rendering against expected rendering.</p>
+
+ <p>The spec states:</p>
+ <blockquote><p>The first item in the list has the ordinal value given by the ol element's start attribute, unless that li element has a value attribute with a value that can be successfully parsed, in which case it has the ordinal value given by that value attribute.</p>
+ <p>Each subsequent item in the list has the ordinal value given by its value attribute, if it has one, or, if it doesn't, the ordinal value of the previous item, plus one if the reversed is absent, or minus one if it is present.</p></blockquote>
+
+ <p><strong>This reftest passes if each list's items are numbered identically to the horizontal sequence immediately above those list items.</strong></p>
+ <p>(Note: each list item has no content; only the sequencing should appear.)</p>
+
+ <span>
+
+ <p>2, 3, 4 (ol has start attribute of 2)</p>
+ <span>
+ <p>2.</p>
+ <p>3.</p>
+ <p>4.</p>
+ </span>
+
+ <p>-9, -8, -7 (ol has start attribute of -9)</p>
+ <span>
+ <p>-9.</p>
+ <p>-8.</p>
+ <p>-7.</p>
+ </span>
+
+ <p>1000, 1001, 1002 (list's start attribute of 1000 provided by JavaScript)</p>
+ <span>
+ <p>1000.</p>
+ <p>1001.</p>
+ <p>1002.</p>
+ </span>
+
+ <p>2, 1, 9 (each list item has a specified value attribute, list has a start attribute of 1000)</p>
+ <span>
+ <p>2.</p>
+ <p>1.</p>
+ <p>9.</p>
+ </span>
+
+ </span>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/grouping-ol-start-reftest-001.html b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/grouping-ol-start-reftest-001.html
new file mode 100644
index 00000000000..dc373f91019
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/grouping-ol-start-reftest-001.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>ol element</title>
+ <link rel="author" title="dzenana" href="mailto:dzenana.trenutak@gmail.com">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-ol-element">
+ <link rel="match" href="grouping-ol-start-reftest-001-ref.html" />
+ <meta name="assert" content="Sequences produced by calculated values for LI elements within OL match spec's expectations (part one)." />
+ <style type="text/css">
+ span p {display:list-item; margin-left: 0; margin-top: 0; margin-bottom: 0; padding-left: 0; padding-top: 0; padding-bottom: 0;}
+ span li {margin-left: 0; margin-top: 0; margin-bottom: 0; padding-left: 0; padding-top: 0; padding-bottom: 0; font-family: monospace;}
+ span ol {margin-left: 0; margin-top: 0; margin-bottom: 0; padding-left: 5em; padding-top: 0; padding-bottom: 0; font-family: monospace;
+ list-style-position: inside; list-style-type: decimal; }
+ </style>
+</head>
+<body>
+ <p>This test continues to validate the ol element. This reftest is necessary because the values of the ol's li children as calculated and displayed by the user agent are NOT systematically available programatically. Only explicitly-set values are available programatically. Therefore, we need to check actual rendering against expected rendering.</p>
+
+ <p>The spec states:</p>
+ <blockquote><p>The first item in the list has the ordinal value given by the ol element's start attribute, unless that li element has a value attribute with a value that can be successfully parsed, in which case it has the ordinal value given by that value attribute.</p>
+ <p>Each subsequent item in the list has the ordinal value given by its value attribute, if it has one, or, if it doesn't, the ordinal value of the previous item, plus one if the reversed is absent, or minus one if it is present.</p></blockquote>
+
+ <p><strong>This reftest passes if each list's items are numbered identically to the horizontal sequence immediately above those list items.</strong></p>
+ <p>(Note: each list item has no content; only the sequencing should appear.)</p>
+
+ <span>
+
+ <p>2, 3, 4 (ol has start attribute of 2)</p>
+ <ol start="2">
+ <li></li>
+ <li></li>
+ <li></li>
+ </ol>
+
+ <p>-9, -8, -7 (ol has start attribute of -9)</p>
+ <ol start="-9">
+ <li></li>
+ <li></li>
+ <li></li>
+ </ol>
+
+ <p>1000, 1001, 1002 (list's start attribute of 1000 provided by JavaScript)</p>
+ <ol id="start_me">
+ <li></li>
+ <li></li>
+ <li></li>
+ </ol>
+
+ <p>2, 1, 9 (each list item has a specified value attribute, list has a start attribute of 1000)</p>
+ <ol istart="1000">
+ <li value="2"></li>
+ <li value="1"></li>
+ <li value="9"></li>
+ </ol>
+
+ </span>
+
+ <script>
+ document.getElementById("start_me").start = 1000;
+ </script>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/grouping-ol-start-reftest-002-ref.html b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/grouping-ol-start-reftest-002-ref.html
new file mode 100644
index 00000000000..e40c12c3a2f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/grouping-ol-start-reftest-002-ref.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>ol element</title>
+ <link rel="author" title="dzenana" href="mailto:dzenana.trenutak@gmail.com">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-ol-element">
+ <link rel="match" href="grouping-ol-start-reftest-002.html" />
+ <meta name="assert" content="Sequences produced by calculated values for LI elements within OL match spec's expectations. (part two)" />
+ <style type="text/css">
+ span p {display:list-item; margin-left: 0; margin-top: 0; margin-bottom: 0; padding-left: 0; padding-top: 0; padding-bottom: 0;}
+ span span p {margin-left: 0; margin-top: 0; margin-bottom: 0; padding-left: 5em; padding-top: 0; padding-bottom: 0; font-family: monospace;}
+ </style>
+</head>
+<body>
+ <p>This test continues to validate the ol element. This reftest is necessary because the values of the ol's li children as calculated and displayed by the user agent are NOT systematically available programatically. Only explicitly-set values are available programatically. Therefore, we need to check actual rendering against expected rendering.</p>
+
+ <p>The spec states:</p>
+ <blockquote><p>The first item in the list has the ordinal value given by the ol element's start attribute, unless that li element has a value attribute with a value that can be successfully parsed, in which case it has the ordinal value given by that value attribute.</p>
+ <p>Each subsequent item in the list has the ordinal value given by its value attribute, if it has one, or, if it doesn't, the ordinal value of the previous item, plus one if the reversed is absent, or minus one if it is present.</p></blockquote>
+
+ <p><strong>This reftest passes if each list's items are numbered identically to the horizontal sequence immediately above those list items.</strong></p>
+ <p>(Note: each list item has no content; only the sequencing should appear.)</p>
+
+ <span>
+
+ <p>4, 5, 6 (ol has start attribute of 2 which is overridden by first list item's value attribute of 4)</p>
+ <span>
+ <p>4.</p>
+ <p>5.</p>
+ <p>6.</p>
+ </span>
+
+ <p>4, 5, 6 (ol has start attribute of -10 which is overridden by first list item's value attribute of 4)</p>
+ <span>
+ <p>4.</p>
+ <p>5.</p>
+ <p>6.</p>
+ </span>
+
+ <p>1, 5, 6 (2nd list item has value attribute of 5)</p>
+ <span>
+ <p>1.</p>
+ <p>5.</p>
+ <p>6.</p>
+ </span>
+
+ <p>-1, -5, -4 (list has a start attribute of -1, and 2nd list item has value attribute of -5)</p>
+ <span>
+ <p>-1.</p>
+ <p>-5.</p>
+ <p>-4.</p>
+ </span>
+
+ </span>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/grouping-ol-start-reftest-002.html b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/grouping-ol-start-reftest-002.html
new file mode 100644
index 00000000000..559e3c21967
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/grouping-ol-start-reftest-002.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>ol element</title>
+ <link rel="author" title="dzenana" href="mailto:dzenana.trenutak@gmail.com">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-ol-element">
+ <link rel="match" href="grouping-ol-start-reftest-002-ref.html" />
+ <meta name="assert" content="Sequences produced by calculated values for LI elements within OL match spec's expectations. (part two)" />
+ <style type="text/css">
+ span p {display:list-item; margin-left: 0; margin-top: 0; margin-bottom: 0; padding-left: 0; padding-top: 0; padding-bottom: 0;}
+ span li {margin-left: 0; margin-top: 0; margin-bottom: 0; padding-left: 0; padding-top: 0; padding-bottom: 0; font-family: monospace;}
+ span ol {margin-left: 0; margin-top: 0; margin-bottom: 0; padding-left: 5em; padding-top: 0; padding-bottom: 0; font-family: monospace;
+ list-style-position: inside; list-style-type: decimal; }
+ </style>
+</head>
+<body>
+ <p>This test continues to validate the ol element. This reftest is necessary because the values of the ol's li children as calculated and displayed by the user agent are NOT systematically available programatically. Only explicitly-set values are available programatically. Therefore, we need to check actual rendering against expected rendering.</p>
+
+ <p>The spec states:</p>
+ <blockquote><p>The first item in the list has the ordinal value given by the ol element's start attribute, unless that li element has a value attribute with a value that can be successfully parsed, in which case it has the ordinal value given by that value attribute.</p>
+ <p>Each subsequent item in the list has the ordinal value given by its value attribute, if it has one, or, if it doesn't, the ordinal value of the previous item, plus one if the reversed is absent, or minus one if it is present.</p></blockquote>
+
+ <p><strong>This reftest passes if each list's items are numbered identically to the horizontal sequence immediately above those list items.</strong></p>
+ <p>(Note: each list item has no content; only the sequencing should appear.)</p>
+
+ <span>
+
+ <p>4, 5, 6 (ol has start attribute of 2 which is overridden by first list item's value attribute of 4)</p>
+ <ol start="2">
+ <li value="4"></li>
+ <li></li>
+ <li></li>
+ </ol>
+
+ <p>4, 5, 6 (ol has start attribute of -10 which is overridden by first list item's value attribute of 4)</p>
+ <ol start="-10">
+ <li value="4"></li>
+ <li></li>
+ <li></li>
+ </ol>
+
+ <p>1, 5, 6 (2nd list item has value attribute of 5)</p>
+ <ol>
+ <li></li>
+ <li value="5"></li>
+ <li></li>
+ </ol>
+
+ <p>-1, -5, -4 (list has a start attribute of -1, and 2nd list item has value attribute of -5)</p>
+ <ol start="-1">
+ <li></li>
+ <li value="-5"></li>
+ <li></li>
+ </ol>
+
+ </span>
+
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/grouping-ol-type-reftest-001-ref.html b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/grouping-ol-type-reftest-001-ref.html
new file mode 100644
index 00000000000..d46f5951a74
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/grouping-ol-type-reftest-001-ref.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>ol element</title>
+ <link rel="author" title="dzenana" href="mailto:dzenana.trenutak@gmail.com">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-ol-element">
+ <link rel="match" href="grouping-ol-type-reftest-001.html" />
+ <meta name="assert" content="OL's type attribute defaults to decimal state." />
+ <style type="text/css">
+ span p {display:list-item; margin-left: 0; margin-top: 0; margin-bottom: 0; padding-left: 0; padding-top: 0; padding-bottom: 0;}
+ span span p {margin-left: 0; margin-top: 0; margin-bottom: 0; padding-left: 5em; padding-top: 0; padding-bottom: 0; font-family: monospace;}
+ </style>
+</head>
+<body>
+ <p>This test continues to validate the ol element. This reftest is necessary because the values of the ol's li children as calculated and displayed by the user agent are NOT systematically available programatically. Only explicitly-set values are available programatically. Therefore, we need to check actual rendering against expected rendering.</p>
+
+ <p>The spec states:</p>
+ <blockquote><p>The type attribute represents the state given in the cell in the second column of the row whose first cell matches the attribute's value; if none of the cells match, or if the attribute is omitted, then the attribute represents the decimal state.</p></blockquote>
+
+ <p><strong>This reftest passes if each list's items are labelled identically to the horizontal sequence immediately above those list items:</strong></p>
+ <p>(Note: each list item has no content; only the sequencing should appear.)</p>
+
+ <span>
+ <p>1, 2, 3 (default value for unspecified type attribute is 'decimal')</p>
+ <span>
+ <p>1.</p>
+ <p>2.</p>
+ <p>3.</p>
+ </span>
+
+ <p>1, 2, 3 (default value for type attribute not listed in spec table is 'decimal' (type = "!"))</p>
+ <span>
+ <p>1.</p>
+ <p>2.</p>
+ <p>3.</p>
+ </span>
+
+ <p>1, 2, 3 (default value for type attribute not listed in spec table is 'decimal' (type = "2"))</p>
+ <span>
+ <p>1.</p>
+ <p>2.</p>
+ <p>3.</p>
+ </span>
+
+ <p>1, 2, 3 (default value for type attribute not listed in spec table is 'decimal' (type = "b"))</p>
+ <span>
+ <p>1.</p>
+ <p>2.</p>
+ <p>3.</p>
+ </span>
+
+ </span>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/grouping-ol-type-reftest-001.html b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/grouping-ol-type-reftest-001.html
new file mode 100644
index 00000000000..32b0e200ba5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/grouping-ol-type-reftest-001.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>ol element</title>
+ <link rel="author" title="dzenana" href="mailto:dzenana.trenutak@gmail.com">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-ol-element">
+ <link rel="match" href="grouping-ol-type-reftest-001-ref.html" />
+ <meta name="assert" content="OL's type attribute defaults to decimal state." />
+ <style type="text/css">
+ span p {display:list-item; margin-left: 0; margin-top: 0; margin-bottom: 0; padding-left: 0; padding-top: 0; padding-bottom: 0;}
+ span li {margin-left: 0; margin-top: 0; margin-bottom: 0; padding-left: 0; padding-top: 0; padding-bottom: 0; font-family: monospace;}
+ span ol {margin-left: 0; margin-top: 0; margin-bottom: 0; padding-left: 5em; padding-top: 0; padding-bottom: 0; font-family: monospace; list-style-position: inside; }
+ </style>
+</head>
+<body>
+ <p>This test continues to validate the ol element. This reftest is necessary because the values of the ol's li children as calculated and displayed by the user agent are NOT systematically available programatically. Only explicitly-set values are available programatically. Therefore, we need to check actual rendering against expected rendering.</p>
+
+ <p>The spec states:</p>
+ <blockquote><p>The type attribute represents the state given in the cell in the second column of the row whose first cell matches the attribute's value; if none of the cells match, or if the attribute is omitted, then the attribute represents the decimal state.</p></blockquote>
+
+ <p><strong>This reftest passes if each list's items are labelled identically to the horizontal sequence immediately above those list items:</strong></p>
+ <p>(Note: each list item has no content; only the sequencing should appear.)</p>
+
+ <span>
+
+ <p>1, 2, 3 (default value for unspecified type attribute is 'decimal')</p>
+ <ol>
+ <li></li>
+ <li></li>
+ <li></li>
+ </ol>
+
+ <p>1, 2, 3 (default value for type attribute not listed in spec table is 'decimal' (type = "!"))</p>
+ <ol type="!">
+ <li></li>
+ <li></li>
+ <li></li>
+ </ol>
+
+ <p>1, 2, 3 (default value for type attribute not listed in spec table is 'decimal' (type = "2"))</p>
+ <ol type="2">
+ <li></li>
+ <li></li>
+ <li></li>
+ </ol>
+
+ <p>1, 2, 3 (default value for type attribute not listed in spec table is 'decimal' (type = "b"))</p>
+ <ol type="b">
+ <li></li>
+ <li></li>
+ <li></li>
+ </ol>
+
+ </span>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/grouping-ol-type-reftest-002-ref.html b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/grouping-ol-type-reftest-002-ref.html
new file mode 100644
index 00000000000..b2c05468c62
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/grouping-ol-type-reftest-002-ref.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>ol element</title>
+ <link rel="author" title="dzenana" href="mailto:dzenana.trenutak@gmail.com">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-ol-element">
+ <link rel="match" href="grouping-ol-type-reftest-002.html" />
+ <meta name="assert" content="List items are rendered consistently with the state of the type attribute." />
+ <style type="text/css">
+ span p {display:list-item; margin-left: 0; margin-top: 0; margin-bottom: 0; padding-left: 0; padding-top: 0; padding-bottom: 0;}
+ span span p {margin-left: 0; margin-top: 0; margin-bottom: 0; padding-left: 5em; padding-top: 0; padding-bottom: 0; font-family: monospace;}
+ </style>
+</head>
+<body>
+ <p>This test continues to validate the ol element. This reftest is necessary because the values of the ol's li children as calculated and displayed by the user agent are NOT systematically available programatically. Only explicitly-set values are available programatically. Therefore, we need to check actual rendering against expected rendering.</p>
+
+ <p>The spec states:</p>
+ <blockquote>User agents should render the items of the list in a manner consistent with the state of the type attribute of the ol element.</blockquote>
+
+ <p><strong>This reftest passes if each list's items are labelled identically to the horizontal sequence immediately above those list items:</strong></p>
+ <p>(Note: each list item has no content; only the sequencing should appear.)</p>
+
+ <span>
+ <p>1, 2, 3 (type attribute of "1" results in decimal type)</p>
+ <span>
+ <p>1.</p>
+ <p>2.</p>
+ <p>3.</p>
+ </span>
+
+ <p>aa, ab, ac (type attribute of "a" results in lower case latin alphabet, start = 27)</p>
+ <span>
+ <p>aa.</p>
+ <p>ab.</p>
+ <p>ac.</p>
+ </span>
+
+ <p>AA, AB, AC (type attribute of "A" results in upper case latin alphabet, start = 27)</p>
+ <span>
+ <p>AA.</p>
+ <p>AB.</p>
+ <p>AC.</p>
+ </span>
+
+ <p>i, v, c (type attribute of "i" results in lower case roman alphabet, list values = 1, 5, 100)</p>
+ <span>
+ <p>i.</p>
+ <p>v.</p>
+ <p>c.</p>
+ </span>
+
+ <p>I, V, C (type attribute of "I" results in upper case roman alphabet, list values = 1, 5, 100)</p>
+ <span>
+ <p>I.</p>
+ <p>V.</p>
+ <p>C.</p>
+ </span>
+
+ </span>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/grouping-ol-type-reftest-002.html b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/grouping-ol-type-reftest-002.html
new file mode 100644
index 00000000000..7daea54c027
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/grouping-ol-type-reftest-002.html
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>ol element</title>
+ <link rel="author" title="dzenana" href="mailto:dzenana.trenutak@gmail.com">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-ol-element">
+ <link rel="match" href="grouping-ol-type-reftest-002-ref.html" />
+ <meta name="assert" content="List items are rendered consistently with the state of the type attribute." />
+ <style type="text/css">
+ span p {display:list-item; margin-left: 0; margin-top: 0; margin-bottom: 0; padding-left: 0; padding-top: 0; padding-bottom: 0;}
+ span li {margin-left: 0; margin-top: 0; margin-bottom: 0; padding-left: 0; padding-top: 0; padding-bottom: 0; font-family: monospace;}
+ span ol {margin-left: 0; margin-top: 0; margin-bottom: 0; padding-left: 5em; padding-top: 0; padding-bottom: 0; font-family: monospace; list-style-position: inside;}
+ </style>
+</head>
+<body>
+ <p>This test continues to validate the ol element. This reftest is necessary because the values of the ol's li children as calculated and displayed by the user agent are NOT systematically available programatically. Only explicitly-set values are available programatically. Therefore, we need to check actual rendering against expected rendering.</p>
+
+ <p>The spec states:</p>
+ <blockquote>User agents should render the items of the list in a manner consistent with the state of the type attribute of the ol element.</blockquote>
+
+ <p><strong>This reftest passes if each list's items are labelled identically to the horizontal sequence immediately above those list items:</strong></p>
+ <p>(Note: each list item has no content; only the sequencing should appear.)</p>
+
+ <span>
+
+ <p>1, 2, 3 (type attribute of "1" results in decimal type)</p>
+ <ol type="1">
+ <li></li>
+ <li></li>
+ <li></li>
+ </ol>
+
+ <p>aa, ab, ac (type attribute of "a" results in lower case latin alphabet, start = 27)</p>
+ <ol type="a" start="27">
+ <li></li>
+ <li></li>
+ <li></li>
+ </ol>
+
+ <p>AA, AB, AC (type attribute of "A" results in upper case latin alphabet, start = 27)</p>
+ <ol type="A" start="27">
+ <li></li>
+ <li></li>
+ <li></li>
+ </ol>
+
+ <p>i, v, c (type attribute of "i" results in lower case roman alphabet, list values = 1, 5, 100)</p>
+ <ol type="i">
+ <li value="1"></li>
+ <li value="5"></li>
+ <li value="100"></li>
+ </ol>
+
+ <p>I, V, C (type attribute of "I" results in upper case roman alphabet, list values = 1, 5, 100)</p>
+ <ol type="I">
+ <li value="1"></li>
+ <li value="5"></li>
+ <li value="100"></li>
+ </ol>
+
+ </span>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/grouping-ol-type-reftest-003-ref.html b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/grouping-ol-type-reftest-003-ref.html
new file mode 100644
index 00000000000..f6afd302fe1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/grouping-ol-type-reftest-003-ref.html
@@ -0,0 +1,79 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>ol element</title>
+ <link rel="author" title="dzenana" href="mailto:dzenana.trenutak@gmail.com">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-ol-element">
+ <link rel="match" href="grouping-ol-type-reftest-003.html" />
+ <meta name="assert" content="OL's type attribute defaults to decimal state." />
+ <style type="text/css">
+ span p {display:list-item; margin-left: 0; margin-top: 0; margin-bottom: 0; padding-left: 0; padding-top: 0; padding-bottom: 0;}
+ span span p {margin-left: 0; margin-top: 0; margin-bottom: 0; padding-left: 5em; padding-top: 0; padding-bottom: 0; font-family: monospace;}
+ </style>
+</head>
+<body>
+ <p>This test continues to validate the ol element. This reftest is necessary because the values of the ol's li children as calculated and displayed by the user agent are NOT systematically available programatically. Only explicitly-set values are available programatically. Therefore, we need to check actual rendering against expected rendering.</p>
+
+ <p>The spec states: Numbers less than or equal to zero should always use the decimal system regardless of the type attribute.</p>
+
+ <p><strong>This reftest passes if each list's items are labelled identically to the horizontal sequence immediately above those list items:</strong></p>
+ <p>(Note: each list item has no content; only the sequencing should appear.)</p>
+
+ <span>
+ <p>-3, -2, -1 (type is "a", start is -3)</p>
+ <span>
+ <p>-3.</p>
+ <p>-2.</p>
+ <p>-1.</p>
+ </span>
+
+ <p>0, a (type is "a", start is 0)</p>
+ <span>
+ <p>0.</p>
+ <p>a.</p>
+ </span>
+
+ <p>-3, -2, -1 (type is "A", start is -3)</p>
+ <span>
+ <p>-3.</p>
+ <p>-2.</p>
+ <p>-1.</p>
+ </span>
+
+ <p>0, A (type is "A", start is 0)</p>
+ <span>
+ <p>0.</p>
+ <p>A.</p>
+ </span>
+
+ <p>-3, -2, -1 (type is "i", start is -3)</p>
+ <span>
+ <p>-3.</p>
+ <p>-2.</p>
+ <p>-1.</p>
+ </span>
+
+ <p>0, i (type is "i", start is 0)</p>
+ <span>
+ <p>0.</p>
+ <p>i.</p>
+ </span>
+
+ <p>-3, -2, -1 (type is "I", start is -3)</p>
+ <span>
+ <p>-3.</p>
+ <p>-2.</p>
+ <p>-1.</p>
+ </span>
+
+ <p>0, I (type is "I", start is 0)</p>
+ <span>
+ <p>0.</p>
+ <p>I.</p>
+ </span>
+
+ </span>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/grouping-ol-type-reftest-003.html b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/grouping-ol-type-reftest-003.html
new file mode 100644
index 00000000000..5e4b5a58885
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/grouping-ol-type-reftest-003.html
@@ -0,0 +1,81 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>ol element</title>
+ <link rel="author" title="dzenana" href="mailto:dzenana.trenutak@gmail.com">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-ol-element">
+ <link rel="match" href="grouping-ol-type-reftest-003-ref.html" />
+ <meta name="assert" content="OL's type attribute defaults to decimal state." />
+ <style type="text/css">
+ span p {display:list-item; margin-left: 0; margin-top: 0; margin-bottom: 0; padding-left: 0; padding-top: 0; padding-bottom: 0;}
+ span li {margin-left: 0; margin-top: 0; margin-bottom: 0; padding-left: 0; padding-top: 0; padding-bottom: 0; font-family: monospace;}
+ span ol {margin-left: 0; margin-top: 0; margin-bottom: 0; padding-left: 5em; padding-top: 0; padding-bottom: 0; font-family: monospace; list-style-position: inside;}
+ </style>
+</head>
+<body>
+ <p>This test continues to validate the ol element. This reftest is necessary because the values of the ol's li children as calculated and displayed by the user agent are NOT systematically available programatically. Only explicitly-set values are available programatically. Therefore, we need to check actual rendering against expected rendering.</p>
+
+ <p>The spec states: Numbers less than or equal to zero should always use the decimal system regardless of the type attribute.</p>
+
+ <p><strong>This reftest passes if each list's items are labelled identically to the horizontal sequence immediately above those list items:</strong></p>
+ <p>(Note: each list item has no content; only the sequencing should appear.)</p>
+
+ <span>
+
+ <p>-3, -2, -1 (type is "a", start is -3)</p>
+ <ol type="a" start="-3">
+ <li></li>
+ <li></li>
+ <li></li>
+ </ol>
+
+ <p>0, a (type is "a", start is 0)</p>
+ <ol type="a" start="0">
+ <li></li>
+ <li></li>
+ </ol>
+
+ <p>-3, -2, -1 (type is "A", start is -3)</p>
+ <ol type="A" start="-3">
+ <li></li>
+ <li></li>
+ <li></li>
+ </ol>
+
+ <p>0, A (type is "A", start is 0)</p>
+ <ol type="A" start="0">
+ <li></li>
+ <li></li>
+ </ol>
+
+ <p>-3, -2, -1 (type is "i", start is -3)</p>
+ <ol type="i" start="-3">
+ <li></li>
+ <li></li>
+ <li></li>
+ </ol>
+
+ <p>0, i (type is "i", start is 0)</p>
+ <ol type="i" start="0">
+ <li></li>
+ <li></li>
+ </ol>
+
+ <p>-3, -2, -1 (type is "I", start is -3)</p>
+ <ol type="I" start="-3">
+ <li></li>
+ <li></li>
+ <li></li>
+ </ol>
+
+ <p>0, I (type is "I", start is 0)</p>
+ <ol type="I" start="0">
+ <li></li>
+ <li></li>
+ </ol>
+
+ </span>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/grouping-ol.html b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/grouping-ol.html
new file mode 100644
index 00000000000..6dfd26eecb0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/grouping-ol.html
@@ -0,0 +1,314 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>the ol element</title>
+ <link rel="author" title="dzenana" href="mailto:dzenana.trenutak@gmail.com">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-ol-element">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <h1>Description</h1>
+ <p>This test validates the ol element.</p>
+
+ <div id="log"></div>
+
+ <p>Ordered List</p>
+ <ol id="basic">
+ <li>list item</li>
+ <li>list item</li>
+ <li>list item</li>
+ </ol>
+
+ <p>Ordered List</p>
+ <ol id="allAtts" reversed start="3" type="A">
+ <li>list item</li>
+ <li>list item</li>
+ <li>list item</li>
+ </ol>
+
+ <p>Ordered List</p>
+ <ol id="justRev" reversed>
+ <li>list item</li>
+ <li>list item</li>
+ <li>list item</li>
+ </ol>
+
+ <p>Ordered List</p>
+ <ol id="basicRevGoodName" reversed="reversed">
+ <li>list item</li>
+ <li>list item</li>
+ <li>list item</li>
+ </ol>
+
+ <p>Ordered List</p>
+ <ol id="basicRevNameWithSpace" reversed=" reversed ">
+ <li>list item</li>
+ <li>list item</li>
+ <li>list item</li>
+ </ol>
+
+ <p>Ordered List</p>
+ <ol id="basicRevEmpty" reversed="" start="A">
+ <li>list item</li>
+ <li>list item</li>
+ <li>list item</li>
+ </ol>
+
+ <p>Ordered List</p>
+ <ol id="basicRevTrue" reversed="true">
+ <li>list item</li>
+ <li>list item</li>
+ <li>list item</li>
+ </ol>
+
+ <p>Ordered List</p>
+ <ol id="basicRevFalse" reversed="false">
+ <li>list item</li>
+ <li>list item</li>
+ <li>list item</li>
+ </ol>
+
+ <p>Ordered List</p>
+ <ol id="start2" start="2">
+ <li>list item</li>
+ <li>list item</li>
+ <li>list item</li>
+ </ol>
+
+ <p>Ordered List</p>
+ <ol id="negative" start="-10">
+ <li>list item</li>
+ <li>list item</li>
+ <li>list item</li>
+ </ol>
+
+ <p>Ordered List</p>
+ <ol id="posFloatDown" start="4.03">
+ <li>list item</li>
+ <li>list item</li>
+ <li>list item</li>
+ </ol>
+
+ <p>Ordered List</p>
+ <ol id="negFloatDown" start="-4.03">
+ <li>list item</li>
+ <li>list item</li>
+ <li>list item</li>
+ </ol>
+
+ <p>Ordered List</p>
+ <ol id="posFloatUp" start="4.9">
+ <li>list item</li>
+ <li>list item</li>
+ <li>list item</li>
+ </ol>
+
+ <p>Ordered List</p>
+ <ol id="negFloatUp" start="-4.9">
+ <li>list item</li>
+ <li>list item</li>
+ <li>list item</li>
+ </ol>
+
+ <p>Ordered List</p>
+ <ol id="exponent" start="7e2">
+ <li>list item</li>
+ <li>list item</li>
+ <li>list item</li>
+ </ol>
+
+ <p>Ordered List</p>
+ <ol id="decimal" start=".5">
+ <li>list item</li>
+ <li>list item</li>
+ <li>list item</li>
+ </ol>
+
+ <p>Ordered List</p>
+ <ol id="letter" start="A">
+ <li>list item</li>
+ <li>list item</li>
+ <li>list item</li>
+ </ol>
+
+ <p>Ordered List</p>
+ <ol id="middle50">
+ <li>list item</li>
+ <li value="50">list item</li>
+ <li>list item</li>
+ </ol>
+
+ <p>Ordered List</p>
+ <ol id="middleneg50">
+ <li>list item</li>
+ <li value="-50">list item</li>
+ <li>list item</li>
+ </ol>
+
+ <p>Ordered List</p>
+ <ol id="lots" reversed="reversed">
+ <li value="10">list item</li>
+ <li value="20">list item</li>
+<a></a><abbr></abbr><address></address><area></area><article></article><aside></aside><audio></audio><b></b><base></base><bdi></bdi><bdo></bdo><blockquote></blockquote><body></body><br></br><button></button><canvas></canvas><caption></caption><cite></cite><code></code><col></col><colgroup></colgroup><command></command><datalist></datalist><dd></dd><del></del><details></details><dfn></dfn><dialog></dialog><div></div><dl></dl><dt></dt><em></em><embed></embed><fieldset></fieldset><figcaption></figcaption><figure></figure><footer></footer><form></form><h1></h1><h2></h2><h3></h3><h4></h4><h5></h5><h6></h6><head></head><header></header><hgroup></hgroup><hr></hr><html></html><i></i><iframe></iframe><img></img><input></input><ins></ins><kbd></kbd><keygen></keygen><label></label><legend></legend><link></link><map></map><mark></mark><menu></menu><meta></meta><meter></meter><nav></nav><noscript></noscript><object></object><ol><li></li><li></li></ol><optgroup></optgroup><option></option><output></output><p></p><param></param><pre></pre><progress></progress><q></q><rp></rp><rt></rt><ruby></ruby><s></s><samp></samp><script></script><section></section><select></select><small></small><source></source><span></span><strong></strong><style></style><sub></sub><summary></summary><sup></sup><table></table><tbody></tbody><td></td><textarea></textarea><tfoot></tfoot><th></th><thead></thead><time></time><title></title><tr></tr><track></track><u></u><ul><li></li><li></li></ul><var></var><video></video><wbr></wbr>
+ <li value="-99">list item</li>
+ </ol>
+
+ <script>
+ "use strict";
+
+ var testList;
+
+ // check that prototype matches spec's DOM interface
+ test(function () {
+ testList = document.getElementById("basic");
+ assert_equals(Object.getPrototypeOf(testList), HTMLOListElement.prototype, "HTMLOListElement.prototype should be used for OL");
+ }, "The prototype for OL is HTMLOListElement.prototype");
+
+ // check that "own" properties reversed, start, and type are present
+ test(function () {
+ testList = document.getElementById("basic");
+ assert_own_property(testList, "reversed");
+ }, "'reversed' property should be defined on OL.");
+
+ test(function () {
+ testList = document.getElementById("basic");
+ assert_own_property(testList, "start");
+ }, "'start' property should be defined on OL.");
+
+ test(function () {
+ testList = document.getElementById("basic");
+ assert_own_property(testList, "type");
+ }, "'type' property should be defined on OL.");
+
+ // "The reversed, start, and type IDL attributes must reflect the respective content attributes of the same name."
+ test(function () {
+ testList = document.getElementById("allAtts");
+ assert_true(testList.reversed);
+ }, "OL's 'reversed' IDL property reflects content attribute.");
+
+ test(function () {
+ testList = document.getElementById("allAtts");
+ assert_equals(testList.start, 3);
+ }, "OL's 'start' IDL property reflects content attribute.");
+
+ test(function () {
+ testList = document.getElementById("allAtts");
+ assert_equals(testList.type, "A");
+ }, "OL's 'type' IDL property reflects content attribute.");
+
+
+ // "The reversed attribute is a boolean attribute."
+
+ // check lists for which reversed value should be false
+ test(function() {
+ assert_false(document.getElementById("basic").reversed, "IDL 'reversed' attribute value false when content attribute absent");
+ }, "IDL 'reversed' attribute value false when content attribute absent");
+
+ // check lists for which reversed value should be true
+ test(function() {
+ assert_true(document.getElementById("justRev").reversed);
+ assert_true(document.getElementById("basicRevGoodName").reversed);
+ assert_true(document.getElementById("basicRevNameWithSpace").reversed);
+ assert_true(document.getElementById("basicRevEmpty").reversed);
+ assert_true(document.getElementById("basicRevTrue").reversed);
+ assert_true(document.getElementById("basicRevFalse").reversed);
+ }, "IDL 'reversed' attribute value true when content attribute exists");
+
+ // check that IDL property works to change reversed value
+ test(function() {
+ document.getElementById("justRev").reversed = false;
+ assert_false(document.getElementById("justRev").reversed, "Changing IDL 'reversed' property changes list's reversed property.");
+ }, "Changing IDL 'reversed' property changes list's reversed property.");
+
+
+ // If the start attribute is present, user agents must parse it as an integer, in order to determine the attribute's value.
+ // The default value, used if the attribute is missing or
+ // if the value cannot be converted to a number according to the referenced algorithm,
+ // is 1 if the element has no reversed attribute, and
+ // is the number of child li elements otherwise."
+ // "The start IDL attribute has the same default as its content attribute."
+
+ // basic - default should be 1
+ test(function() {
+ assert_equals(document.getElementById("basic").start, 1, "no start attribute provided -> 1");
+ }, "Default start value for non-reversed list should be 1");
+
+ // decimal's first element has value of .5 which should return 1
+ test(function() {
+ assert_equals(document.getElementById("decimal").start, 1, "start of .5 -> 1 (default)");
+ }, "IDL and content attribute parse start of '.5' correctly.");
+
+ // letter's first element has value of A which should return 1
+ test(function() {
+ assert_equals(document.getElementById("letter").start, 1, "start of A -> 1 (default)");
+ }, "IDL and content attribute parse start of 'A' correctly.");
+
+ // basicRevGoodName - default should be 3
+ test(function() {
+ assert_equals(document.getElementById("basicRevGoodName").start, 3, "no start attribute provided -> 3");
+ }, "Default start value (if none provided) for reversed list = child li elements.");
+
+ // basicRevEmpty - default should be 3
+ test(function() {
+ assert_equals(document.getElementById("basicRevEmpty").start, 3, "start of A -> 3 (default)");
+ }, "Default start value (if failed to parse) for reversed list = child li elements.");
+
+ // lots - default should be 3
+ test(function() {
+ assert_equals(document.getElementById("lots").start, 3, "no start attribute -> 3 (default)");
+ }, "Default start value for reversed list = child li elements (even with tons of other child elements).");
+
+ // adding child element changes default start value for reversed list
+ test(function() {
+ var myList = document.getElementById("basicRevGoodName"), myLI = document.createElement("li");
+ myList.appendChild(myLI);
+ assert_equals(document.getElementById("basicRevGoodName").start, 4, "Adding child element to reversed list adds 1 to start value");
+ }, "Adding child element to reversed list adds 1 to start value");
+
+ // removing child element changes default start value for reversed list
+ test(function() {
+ var myList = document.getElementById("basicRevTrue");
+ myList.removeChild(myList.children[0]);
+ assert_equals(document.getElementById("basicRevTrue").start, 2, "Deleting child element from reversed list reduces start value by 1");
+ }, "Deleting child element from reversed list reduces start value by 1");
+
+ // start2's first element has value of 2
+ test(function() {
+ assert_equals(document.getElementById("start2").start, 2, "start of 2 -> 2");
+ }, "IDL and content attribute parse start of '2' correctly.");
+
+ // negative's first element has value of -10
+ test(function() {
+ assert_equals(document.getElementById("negative").start, -10, "start of -10 -> -10");
+ }, "IDL and content attribute parse start of '-10' correctly.");
+
+ // posFloatDown's first element has value of 4.03 which should return 4
+ test(function() {
+ assert_equals(document.getElementById("posFloatDown").start, 4, "start of 4.03 -> 4");
+ }, "IDL and content attribute parse start of '4.03' correctly.");
+
+ // negFloatDown's first element has value of -4.03 which should return -4
+ test(function() {
+ assert_equals(document.getElementById("negFloatDown").start, -4, "start of -4.03 -> -4");
+ }, "IDL and content attribute parse start of '-4.03' correctly.");
+
+ // posFloatUp's first element has value of 4.9 which should return 4
+ test(function() {
+ assert_equals(document.getElementById("posFloatUp").start, 4, "start of 4.9 -> 4");
+ }, "IDL and content attribute parse start of '4.9' correctly.");
+
+ // negFloatUp's first element has value of -4.9 which should return -4
+ test(function() {
+ assert_equals(document.getElementById("negFloatUp").start, -4, "start of -4.9 -> -4");
+ }, "IDL and content attribute parse start of '-4.9' correctly.");
+
+ // exponent's first element has value of 7e2 which should return 7
+ test(function() {
+ assert_equals(document.getElementById("exponent").start, 7, "start of 7e2 -> 7");
+ }, "IDL and content attribute parse start of '7e2' correctly.");
+
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/ol.start-reflection-1.html b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/ol.start-reflection-1.html
new file mode 100644
index 00000000000..957cb7fd78d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/ol.start-reflection-1.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ol.start - reflection test</title>
+ <link rel="author" title="Shiki Okasaka" href="http://shiki.esrille.com/">
+ <link rel="author" title="Esrille Inc." href="http://www.esrille.com/">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-ol-element">
+ <meta name="assert" content="This test checks that the start IDL attribute reflects the respective content attribute of the same name.">
+ <link rel="stylesheet" href="/resources/testharness.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <ol id="ol">
+ <li>One</li>
+ <li>Two</li>
+ <li>Three</li>
+ </ol>
+ <div id="log"></div>
+ <script>
+test(function() {
+ assert_equals(document.getElementById('ol').start, 1);
+})
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/ol.start-reflection-2.html b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/ol.start-reflection-2.html
new file mode 100644
index 00000000000..97416e65e1f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/ol.start-reflection-2.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>ol.start - reflection test</title>
+ <link rel="author" title="Shiki Okasaka" href="http://shiki.esrille.com/">
+ <link rel="author" title="Esrille Inc." href="http://www.esrille.com/">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-ol-element">
+ <meta name="assert" content="This test checks that the start IDL attribute reflects the respective content attribute of the same name.">
+ <link rel="stylesheet" href="/resources/testharness.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <ol id='ol' reversed>
+ <li>Three</li>
+ <li>Two</li>
+ <li>One</li>
+ </ol>
+ <div id='log'></div>
+ <script>
+test(function() {
+ assert_equals(document.getElementById('ol').start, 3);
+})
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/reversed-1-ref.html b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/reversed-1-ref.html
new file mode 100644
index 00000000000..f8cac3c702b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/reversed-1-ref.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<ol>
+ <li value="3">Three</li>
+ <li value="2">Two</li>
+ <li value="1">One</li>
+</ol>
diff --git a/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/reversed-1a.html b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/reversed-1a.html
new file mode 100644
index 00000000000..35e967c05e6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/reversed-1a.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<ol reversed>
+ <li>Three</li>
+ <li>Two</li>
+ <li>One</li>
+</ol>
diff --git a/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/reversed-1b.html b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/reversed-1b.html
new file mode 100644
index 00000000000..d9810560eb7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/reversed-1b.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<ol id="x">
+ <li>Three</li>
+ <li>Two</li>
+ <li>One</li>
+</ol>
+<script>
+ var l = document.getElementById("x");
+ var w = l.offsetWidth;
+ l.setAttribute("reversed", "");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/reversed-1c.html b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/reversed-1c.html
new file mode 100644
index 00000000000..82ae844335e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/reversed-1c.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<ol id="x" reversed>
+ <li>Three</li>
+ <li>Two</li>
+</ol>
+<script>
+ var l = document.getElementById("x");
+ var w = l.offsetWidth;
+ var li = document.createElement("li");
+ li.textContent = "One"
+ l.appendChild(li);
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/reversed-2-ref.html b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/reversed-2-ref.html
new file mode 100644
index 00000000000..4f3ece2be48
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/reversed-2-ref.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<ol>
+ <li value="5">Five</li>
+ <li value="4">Four</li>
+ <li value="3">Three</li>
+</ol>
diff --git a/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/reversed-2.html b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/reversed-2.html
new file mode 100644
index 00000000000..0d4948153c1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ol-element/reversed-2.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<link rel="match" href="reversed-2-ref.html">
+<ol reversed start="5">
+ <li>Five</li>
+ <li>Four</li>
+ <li>Three</li>
+</ol>
diff --git a/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-p-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-p-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-p-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-p-element/grouping-p.html b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-p-element/grouping-p.html
new file mode 100644
index 00000000000..5f15aca31f7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-p-element/grouping-p.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>the p element</title>
+ <link rel="author" title="dzenana" href="mailto:dzenana.trenutak@gmail.com">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-p-element">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ "use strict";
+
+ // check that prototype matches spec's DOM interface
+ test(function () {
+ var testElement = document.createElement("p");
+ assert_equals(Object.getPrototypeOf(testElement), HTMLParagraphElement.prototype, "HTMLParagraphElement.prototype should be used for p");
+ }, "The prototype for p is HTMLParagraphElement.prototype");
+
+ </script>
+</head>
+<body>
+ <h1>Description</h1>
+ <p>This test validates the p element.</p>
+
+ <div id="log"></div>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-pre-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-pre-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-pre-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-pre-element/grouping-pre-reftest-001-ref.html b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-pre-element/grouping-pre-reftest-001-ref.html
new file mode 100644
index 00000000000..a84f703ee81
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-pre-element/grouping-pre-reftest-001-ref.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>pre element</title>
+ <link rel="author" title="dzenana" href="mailto:dzenana.trenutak@gmail.com">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-pre-element">
+ <link rel="match" href="grouping-pre-reftest-001.html" />
+ <meta name="assert" content="Newlines within pre elements separate paragraphs for the purposes of BIDI." />
+</head>
+<body>
+ <h1>Description</h1>
+ <p>This test continues to validate the pre element.</p>
+
+ <p>The spec states:</p>
+ <blockquote>"A newline in a pre element should separate paragraphs for the purposes of the Unicode bidirectional algorithm. This requirement may be implemented indirectly through the style layer. For example, an HTML+CSS user agent could implement these requirements by implementing the CSS 'unicode-bidi' property."</blockquote>
+
+ <p>This reftest passes if below you see "ABC ABC" repeated on two separate lines below (4 ABCs total):</p>
+
+ <pre>ABC ABC
+ABC ABC</pre>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-pre-element/grouping-pre-reftest-001.html b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-pre-element/grouping-pre-reftest-001.html
new file mode 100644
index 00000000000..29e582edd56
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-pre-element/grouping-pre-reftest-001.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>pre element</title>
+ <link rel="author" title="dzenana" href="mailto:dzenana.trenutak@gmail.com">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-pre-element">
+ <link rel="match" href="grouping-pre-reftest-001-ref.html" />
+ <meta name="assert" content="Newlines within pre elements separate paragraphs for the purposes of BIDI." />
+</head>
+<body>
+ <h1>Description</h1>
+ <p>This test continues to validate the pre element.</p>
+
+ <p>The spec states:</p>
+ <blockquote>"A newline in a pre element should separate paragraphs for the purposes of the Unicode bidirectional algorithm. This requirement may be implemented indirectly through the style layer. For example, an HTML+CSS user agent could implement these requirements by implementing the CSS 'unicode-bidi' property."</blockquote>
+
+ <p>This reftest passes if below you see "ABC ABC" repeated on two separate lines below (4 ABCs total):</p>
+
+ <pre>&#x202E CBA CBA
+ABC ABC</pre>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-pre-element/grouping-pre.html b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-pre-element/grouping-pre.html
new file mode 100644
index 00000000000..07fc631b91c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-pre-element/grouping-pre.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>the pre element</title>
+ <link rel="author" title="dzenana" href="mailto:dzenana.trenutak@gmail.com">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-pre-element">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <h1>Description</h1>
+ <p>This test validates the pre element.</p>
+
+ <div id="log"></div>
+
+ <script>
+ "use strict";
+
+ // check that prototype matches spec's DOM interface
+ test(function () {
+ var testElement = document.createElement("pre");
+ assert_equals(Object.getPrototypeOf(testElement), HTMLPreElement.prototype, "HTMLPreElement.prototype should be used for pre");
+ }, "The prototype for pre is HTMLPreElement.prototype");
+
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-pre-element/pre-newline-bidi-ref.html b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-pre-element/pre-newline-bidi-ref.html
new file mode 100644
index 00000000000..0f302b5d4bf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-pre-element/pre-newline-bidi-ref.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>HTML Test reference: newline in &lt;pre&gt; separates bidi paragraphs</title>
+ <link rel="author" title="Amir E. Aharoni" href="mailto:amir.aharoni@mail.huji.ac.il"/>
+ <link rel="author" title="Eyal Sela" href="mailto:eyal@post.isoc.org.il"/>
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com"/>
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-pre-element"/>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the rightmost character in the first line below is a full stop and to the left of it is a Hebrew letter.</p></div>
+ <div class="test">
+ <pre>
+A Hebrew letter and a full stop: &#x05d0;.&lrm;
+&#x05d0; this line begins with a Hebrew letter.
+ </pre>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-pre-element/pre-newline-bidi.html b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-pre-element/pre-newline-bidi.html
new file mode 100644
index 00000000000..23d442f52ca
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-pre-element/pre-newline-bidi.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8"/>
+ <title>HTML Test: newline in pre separates bidi paragraphs</title>
+ <link rel="match" href="pre-newline-bidi-ref.html" />
+ <link rel="author" title="Amir E. Aharoni" href="mailto:amir.aharoni@mail.huji.ac.il"/>
+ <link rel="author" title="Eyal Sela" href="mailto:eyal@post.isoc.org.il"/>
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com"/>
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-pre-element"/>
+ <meta name="assert"
+ content="A newline in a pre element should separate paragraphs for the purposes of the Unicode bidirectional algorithm."/>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the rightmost character in the first line below is a full stop and to the left of it is a Hebrew letter.</p></div>
+ <div class="test">
+ <pre>
+A Hebrew letter and a full stop: &#x05d0;.
+&#x05d0; this line begins with a Hebrew letter.
+ </pre>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ul-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ul-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ul-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ul-element/grouping-ul.html b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ul-element/grouping-ul.html
new file mode 100644
index 00000000000..6e62343f6b8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/grouping-content/the-ul-element/grouping-ul.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>the ul element</title>
+ <link rel="author" title="dzenana" href="mailto:dzenana.trenutak@gmail.com">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-ul-element">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ "use strict";
+
+ // check that prototype matches spec's DOM interface
+ test(function () {
+ var testElement = document.createElement("ul");
+ assert_equals(Object.getPrototypeOf(testElement), HTMLUListElement.prototype, "HTMLUListElement.prototype should be used for ul");
+ }, "The prototype for ul is HTMLUListElement.prototype");
+
+ </script>
+</head>
+<body>
+ <h1>Description</h1>
+ <p>This test validates the ul element.</p>
+
+ <div id="log"></div>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/interactive-elements/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/interactive-elements/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/interactive-elements/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/interactive-elements/commands/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/interactive-elements/commands/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/interactive-elements/commands/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/interactive-elements/commands/contains.json b/tests/wpt/web-platform-tests/html/semantics/interactive-elements/commands/contains.json
new file mode 100644
index 00000000000..b2ca2e771bd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/interactive-elements/commands/contains.json
@@ -0,0 +1,38 @@
+[
+ {
+ "id": "using-the-a-element-to-define-a-command",
+ "original_id": "using-the-a-element-to-define-a-command"
+ },
+ {
+ "id": "using-the-button-element-to-define-a-command",
+ "original_id": "using-the-button-element-to-define-a-command"
+ },
+ {
+ "id": "using-the-input-element-to-define-a-command",
+ "original_id": "using-the-input-element-to-define-a-command"
+ },
+ {
+ "id": "using-the-option-element-to-define-a-command",
+ "original_id": "using-the-option-element-to-define-a-command"
+ },
+ {
+ "id": "using-the-command-element-to-define-a-command",
+ "original_id": "using-the-command-element-to-define-a-command"
+ },
+ {
+ "id": "using-the-command-attribute-on-command-elements-to-define-a-command-indirectly",
+ "original_id": "using-the-command-attribute-on-command-elements-to-define-a-command-indirectly"
+ },
+ {
+ "id": "using-the-accesskey-attribute-on-a-label-element-to-define-a-command",
+ "original_id": "using-the-accesskey-attribute-on-a-label-element-to-define-a-command"
+ },
+ {
+ "id": "using-the-accesskey-attribute-on-a-legend-element-to-define-a-command",
+ "original_id": "using-the-accesskey-attribute-on-a-legend-element-to-define-a-command"
+ },
+ {
+ "id": "using-the-accesskey-attribute-to-define-a-command-on-other-elements",
+ "original_id": "using-the-accesskey-attribute-to-define-a-command-on-other-elements"
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/interactive-elements/the-command-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/interactive-elements/the-command-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/interactive-elements/the-command-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/interactive-elements/the-details-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/interactive-elements/the-details-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/interactive-elements/the-details-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/interactive-elements/the-details-element/details.html b/tests/wpt/web-platform-tests/html/semantics/interactive-elements/the-details-element/details.html
new file mode 100644
index 00000000000..5ed14c53afc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/interactive-elements/the-details-element/details.html
@@ -0,0 +1,47 @@
+<!doctype html>
+<html>
+ <head>
+ <title>HTML details element API</title>
+ <style>#one, #two { visibility: hidden; }</style>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+
+ <!-- Used in parsing tests -->
+ <div id='one'><details></details><details></details></div>
+ <div id='two'><p><details></details></div>
+
+ <script type="text/javascript">
+
+function makeDetails () {
+ return document.createElement('details');
+}
+
+
+// <details>
+test(function () {
+ var times = document.getElementById('one').getElementsByTagName('details');
+ assert_equals( times.length, 2 );
+}, 'HTML parsing should locate 2 details elements in this document');
+
+test(function () {
+ assert_equals( document.getElementById('two').getElementsByTagName('p')[0].innerHTML, '' );
+}, 'HTML parsing should close an unclosed <p> before <details>');
+
+test(function () {
+ assert_true( !!window.HTMLDetailsElement );
+}, 'HTMLDetailsElement should be exposed for prototyping');
+
+test(function () {
+ assert_true( makeDetails() instanceof window.HTMLDetailsElement);
+}, 'a dynamically created details element should be instanceof HTMLDetailsElement');
+
+test(function () {
+ assert_true( document.getElementById('one').getElementsByTagName('details')[0] instanceof window.HTMLDetailsElement);
+}, 'a details element from the parser should be instanceof HTMLDetailsElement');
+ </script>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/interactive-elements/the-details-element/toggleEvent.html b/tests/wpt/web-platform-tests/html/semantics/interactive-elements/the-details-element/toggleEvent.html
new file mode 100644
index 00000000000..08d49c9bb9a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/interactive-elements/the-details-element/toggleEvent.html
@@ -0,0 +1,93 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>The details element</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#the-details-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<details id=details1>
+ <summary>Lorem ipsum</summary>
+ <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
+</details>
+<details id=details2 open>
+ <summary>Lorem ipsum</summary>
+ <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
+</details>
+<details id=details3 style="display:none;">
+ <summary>Lorem ipsum</summary>
+ <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
+</details>
+<details id=details4>
+</details>
+<details id=details6>
+ <summary>Lorem ipsum</summary>
+ <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
+</details>
+<script>
+ var t1 = async_test("Adding open to 'details' should fire a toggle event at the 'details' element"),
+ t2 = async_test("Removing open from 'details' should fire a toggle event at the 'details' element"),
+ t3 = async_test("Adding open to 'details' (display:none) should fire a toggle event at the 'details' element"),
+ t4 = async_test("Adding open from 'details' (no children) should fire a toggle event at the 'details' element"),
+ t6 = async_test("Calling open twice on 'details' fires only one toggle event"),
+ details1 = document.getElementById('details1'),
+ details2 = document.getElementById('details2'),
+ details3 = document.getElementById('details3'),
+ details4 = document.getElementById('details4'),
+ details6 = document.getElementById('details6'),
+ loop=false;
+
+ function testEvent(evt) {
+ assert_true(evt.isTrusted, "event is trusted");
+ assert_false(evt.bubbles, "event doesn't bubble");
+ assert_false(evt.cancelable, "event is not cancelable");
+ assert_equals(Object.getPrototypeOf(evt), Event.prototype, "Prototype of toggle event is Event.prototype");
+ }
+
+ details1.ontoggle = t1.step_func_done(function(evt) {
+ assert_true(details1.open);
+ testEvent(evt)
+ });
+ details1.open = true; // opens details1
+
+ details2.ontoggle = t2.step_func_done(function(evt) {
+ assert_false(details2.open);
+ testEvent(evt);
+ });
+ details2.open = false; // closes details2
+
+ details3.ontoggle = t3.step_func_done(function(evt) {
+ assert_true(details3.open);
+ testEvent(evt);
+ });
+ details3.open = true; // opens details3
+
+ details4.ontoggle = t4.step_func_done(function(evt) {
+ assert_true(details4.open);
+ testEvent(evt);
+ });
+ details4.open = true; // opens details4
+
+ async_test(function(t) {
+ var details5 = document.createElement("details");
+ details5.ontoggle = t.step_func_done(function(evt) {
+ assert_true(details5.open);
+ testEvent(evt);
+ })
+ details5.open = true;
+ }, "Adding open to 'details' (not in the document) should fire a toggle event at the 'details' element");
+
+ details6.open = true;
+ details6.open = false;
+ details6.ontoggle = t6.step_func(function() {
+ if (loop) {
+ assert_unreached("toggle event fired twice");
+ } else {
+ loop = true;
+ }
+ });
+ setTimeout(t6.step_func(function() {
+ assert_true(loop);
+ t6.done();
+ }), 0);
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/interactive-elements/the-dialog-element/contains.json b/tests/wpt/web-platform-tests/html/semantics/interactive-elements/the-dialog-element/contains.json
new file mode 100644
index 00000000000..c865c858857
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/interactive-elements/the-dialog-element/contains.json
@@ -0,0 +1,6 @@
+[
+ {
+ "id": "anchor-points",
+ "original_id": "anchor-points"
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/interactive-elements/the-dialog-element/dialog-close.html b/tests/wpt/web-platform-tests/html/semantics/interactive-elements/the-dialog-element/dialog-close.html
new file mode 100644
index 00000000000..a3d07f053dc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/interactive-elements/the-dialog-element/dialog-close.html
@@ -0,0 +1,78 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>dialog element: close()</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#the-dialog-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<dialog id="d1">
+ <p>foobar</p>
+ <button>OK</button>
+</dialog>
+<dialog id="d2" open>
+ <p>foobar</p>
+ <button>OK</button>
+</dialog>
+<dialog id="d3" open>
+ <p>foobar</p>
+ <button>OK</button>
+</dialog>
+<dialog id="d4" open>
+ <p>foobar</p>
+ <button>OK</button>
+</dialog>
+<dialog id="d5" open>
+ <p>foobar</p>
+ <button>OK</button>
+</dialog>
+<script>
+ var d1 = document.getElementById('d1'),
+ d2 = document.getElementById('d2'),
+ d3 = document.getElementById('d3'),
+ d4 = document.getElementById('d4'),
+ d5 = document.getElementById('d5'),
+ t = async_test("close() fires a close event"),
+ was_queued = false;
+
+ test(function(){
+ assert_throws("INVALID_STATE_ERR", function() {
+ d1.close();
+ });
+ }, "close() on a <dialog> that doesn't have an open attribute throws an InvalidStateError exception");
+
+ test(function(){
+ assert_true(d2.open);
+ assert_equals(d2.returnValue, "");
+ d2.close("closedialog");
+ assert_false(d2.hasAttribute("open"));
+ assert_equals(d2.returnValue, "closedialog");
+ }, "close() removes the open attribute and set the returnValue to the first argument");
+
+ test(function(){
+ assert_true(d3.open);
+ assert_equals(d3.returnValue, "");
+ d3.returnValue = "foobar";
+ d3.close();
+ assert_false(d3.hasAttribute("open"));
+ assert_equals(d3.returnValue, "foobar");
+ }, "close() without argument removes the open attribute and there's no returnValue");
+
+ d4.onclose = t.step_func_done(function(e) {
+ assert_true(was_queued, "close event should be queued");
+ assert_true(e.isTrusted, "close event is trusted");
+ assert_false(e.bubbles, "close event doesn't bubble");
+ assert_false(e.cancelable, "close event is not cancelable");
+ });
+
+ t.step(function() {
+ d4.close();
+ was_queued = true;
+ })
+
+ test(function(){
+ Object.defineProperty(HTMLDialogElement.prototype, 'returnValue', { set: function(v) { assert_unreached('JS-defined setter returnValue on the prototype was invoked'); }, configurable:true });
+ Object.defineProperty(d5, 'returnValue', { set: function(v) { assert_unreached('JS-defined setter returnValue on the instance was invoked'); }, configurable:true });
+ d5.close('foo');
+ }, "close() should set the returnValue IDL attribute but not the JS property");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/interactive-elements/the-dialog-element/dialog-showModal.html b/tests/wpt/web-platform-tests/html/semantics/interactive-elements/the-dialog-element/dialog-showModal.html
new file mode 100644
index 00000000000..6ca9189c08a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/interactive-elements/the-dialog-element/dialog-showModal.html
@@ -0,0 +1,125 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>dialog element: showModal()</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#the-dialog-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<button id="b0">OK</button>
+<dialog id="d1">
+ <p>foobar</p>
+ <button id="b1">OK</button>
+</dialog>
+<dialog id="d2" open>
+ <p>foobar</p>
+ <button>OK</button>
+</dialog>
+<dialog id="d3">
+ <p>foobar</p>
+ <button id="b3">OK</button>
+</dialog>
+<dialog id="d4">
+ <p>foobar</p>
+ <button id="b4">OK</button>
+</dialog>
+<dialog id="d5">
+ <p>foobar</p>
+ <button id="b5">OK</button>
+</dialog>
+<dialog id="d6"></dialog>
+<dialog id="d7">
+ <input id="i71" value="foobar">
+ <input id="i72" value="foobar">
+ <button id="b7">OK</button>
+</dialog>
+<dialog id="d8">
+ <input id="i81" value="foobar">
+ <input id="i82" value="foobar" autofocus>
+ <button id="b8">OK</button>
+</dialog>
+<script>
+ var d1 = document.getElementById('d1'),
+ d2 = document.getElementById('d2'),
+ d3 = document.getElementById('d3'),
+ d4 = document.getElementById('d4'),
+ d5 = document.getElementById('d5'),
+ d6 = document.getElementById('d6'),
+ d7 = document.getElementById('d7'),
+ d8 = document.getElementById('d8'),
+ b0 = document.getElementById('b0'),
+ b1 = document.getElementById('b1'),
+ b3 = document.getElementById('b3'),
+ b4 = document.getElementById('b4'),
+ b5 = document.getElementById('b5');
+
+ test(function(){
+ assert_false(d1.open);
+ assert_false(b0.commandDisabled);
+ d1.showModal();
+ this.add_cleanup(function() { d1.close(); });
+ assert_true(d1.open);
+ assert_true(b0.commandDisabled);
+ assert_equals(document.activeElement, b1);
+ });
+
+ test(function(){
+ assert_throws("INVALID_STATE_ERR", function() {
+ d2.showModal();
+ this.add_cleanup(function() { d2.close(); });
+ });
+ }, "showModal() on a <dialog> that already has an open attribute throws an InvalidStateError exception");
+
+ test(function(){
+ var d = document.createElement("dialog");
+ assert_throws("INVALID_STATE_ERR", function() {
+ d.showModal();
+ this.add_cleanup(function() { d.close(); });
+ });
+ }, "showModal() on a <dialog> not in a Document throws an InvalidStateError exception");
+
+ test(function(){
+ assert_false(d3.open);
+ assert_false(b3.commandDisabled);
+ assert_false(d4.open);
+ assert_false(b4.commandDisabled);
+ assert_false(d5.open);
+ assert_false(b5.commandDisabled);
+ d3.showModal();
+ this.add_cleanup(function() { d3.close(); });
+ d4.showModal();
+ this.add_cleanup(function() { d4.close(); });
+ d5.showModal();
+ this.add_cleanup(function() { d5.close(); });
+ assert_true(d3.open);
+ assert_true(b3.commandDisabled);
+ assert_true(d4.open);
+ assert_true(b4.commandDisabled);
+ assert_true(d5.open);
+ assert_false(b5.commandDisabled);
+ }, "when opening multiple dialogs, only the newest one is non-inert");
+
+ test(function(){
+ assert_false(d6.open);
+ d6.showModal();
+ this.add_cleanup(function() { d6.close(); });
+ assert_true(d6.open);
+ assert_equals(document.activeElement, d6);
+ }, "opening dialog without focusable children");
+
+ test(function(){
+ assert_false(d7.open);
+ d7.showModal();
+ this.add_cleanup(function() { d7.close(); });
+ assert_true(d7.open);
+ assert_equals(document.activeElement, document.getElementById("i71"));
+ }, "opening dialog with multiple focusable children");
+
+ test(function(){
+ assert_false(d8.open);
+ d8.showModal();
+ this.add_cleanup(function() { d8.close(); });
+ assert_true(d8.open);
+ assert_equals(document.activeElement, document.getElementById("i82"));
+ }, "opening dialog with multiple focusable children, one having the autofocus attribute");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/interactive-elements/the-menu-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/interactive-elements/the-menu-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/interactive-elements/the-menu-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/interactive-elements/the-menu-element/contains.json b/tests/wpt/web-platform-tests/html/semantics/interactive-elements/the-menu-element/contains.json
new file mode 100644
index 00000000000..20f2439f66c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/interactive-elements/the-menu-element/contains.json
@@ -0,0 +1,18 @@
+[
+ {
+ "id": "menus-intro",
+ "original_id": "menus-intro"
+ },
+ {
+ "id": "building-menus-and-toolbars",
+ "original_id": "building-menus-and-toolbars"
+ },
+ {
+ "id": "context-menus",
+ "original_id": "context-menus"
+ },
+ {
+ "id": "toolbars",
+ "original_id": "toolbars"
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/interactive-elements/the-summary-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/interactive-elements/the-summary-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/interactive-elements/the-summary-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/interfaces.html b/tests/wpt/web-platform-tests/html/semantics/interfaces.html
new file mode 100644
index 00000000000..d3b2a23e27c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/interfaces.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<title>Test of interfaces</title>
+<link rel="author" title="Ms2ger" href="mailto:Ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/">
+<link rel="help" href="https://heycam.github.io/webidl/#host-objects">
+<link rel="help" href="http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf#page=96">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src=interfaces.js></script>
+<div id="log"></div>
+<script>
+test(function() {
+ elements.forEach(function(a) {
+ test(function() {
+ var e = document.createElement(a[0]), i = "HTML" + a[1] + "Element";
+ assert_class_string(e, i,
+ "Element " + a[0] + " should have " + i +
+ " as its primary interface.");
+ assert_true(e instanceof window[i],
+ "Element " + a[0] + " should implement " + i + ".");
+ assert_true(e instanceof HTMLElement,
+ "Element " + a[0] + " should implement HTMLElement.");
+ assert_true(e instanceof Element,
+ "Element " + a[0] + " should implement Element.");
+ assert_true(e instanceof Node,
+ "Element " + a[0] + " should implement Node.");
+ }, "Interfaces for " + a[0])
+ })
+})
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/interfaces.js b/tests/wpt/web-platform-tests/html/semantics/interfaces.js
new file mode 100644
index 00000000000..5f5d2d908fa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/interfaces.js
@@ -0,0 +1,138 @@
+var elements = [
+ ["abbr", ""],
+ ["acronym", ""],
+ ["address", ""],
+ ["applet", "Applet"],
+ ["audio", "Audio"],
+ ["b", ""],
+ ["base", "Base"],
+ ["basefont", "Unknown"],
+ ["bdo", ""],
+ ["bgsound", "Unknown"],
+ ["big", ""],
+ ["blink", "Unknown"],
+ ["blockquote", "Quote"],
+ ["body", "Body"],
+ ["br", "BR"],
+ ["button", "Button"],
+ ["canvas", "Canvas"],
+ ["caption", "TableCaption"],
+ ["center", ""],
+ ["cite", ""],
+ ["code", ""],
+ ["col", "TableCol"],
+ ["colgroup", "TableCol"],
+ ["dd", ""],
+ ["del", "Mod"],
+ ["dfn", ""],
+ ["dir", "Directory"],
+ ["div", "Div"],
+ ["dl", "DList"],
+ ["dt", ""],
+ ["em", ""],
+ ["embed", "Embed"],
+ ["fieldset", "FieldSet"],
+ ["font", "Font"],
+ ["form", "Form"],
+ ["frame", "Frame"],
+ ["frameset", "FrameSet"],
+ ["h1", "Heading"],
+ ["h2", "Heading"],
+ ["h3", "Heading"],
+ ["h4", "Heading"],
+ ["h5", "Heading"],
+ ["h6", "Heading"],
+ ["head", "Head"],
+ ["hr", "HR"],
+ ["html", "Html"],
+ ["i", ""],
+ ["iframe", "IFrame"],
+ ["image", "Unknown"],
+ ["img", "Image"],
+ ["input", "Input"],
+ ["ins", "Mod"],
+ ["isindex", "Unknown"],
+ ["kbd", ""],
+ ["keygen", "Keygen"],
+ ["label", "Label"],
+ ["legend", "Legend"],
+ ["li", "LI"],
+ ["link", "Link"],
+ ["listing", ""],
+ ["map", "Map"],
+ ["marquee", "Marquee"],
+ ["menu", "Menu"],
+ ["meta", "Meta"],
+ ["multicol", "Unknown"],
+ ["nobr", ""],
+ ["noembed", ""],
+ ["noframes", ""],
+ ["noscript", ""],
+ ["object", "Object"],
+ ["ol", "OList"],
+ ["optgroup", "OptGroup"],
+ ["option", "Option"],
+ ["p", "Paragraph"],
+ ["param", "Param"],
+ ["plaintext", ""],
+ ["pre", "Pre"],
+ ["q", "Quote"],
+ ["s", ""],
+ ["samp", ""],
+ ["script", "Script"],
+ ["select", "Select"],
+ ["small", ""],
+ ["source", "Source"],
+ ["spacer", "Unknown"],
+ ["span", "Span"],
+ ["strike", ""],
+ ["strong", ""],
+ ["style", "Style"],
+ ["sub", ""],
+ ["sup", ""],
+ ["table", "Table"],
+ ["tbody", "TableSection"],
+ ["td", "TableDataCell"],
+ ["textarea", "TextArea"],
+ ["tfoot", "TableSection"],
+ ["th", "TableHeaderCell"],
+ ["thead", "TableSection"],
+ ["title", "Title"],
+ ["tr", "TableRow"],
+ ["tt", ""],
+ ["u", ""],
+ ["ul", "UList"],
+ ["var", ""],
+ ["video", "Video"],
+ ["wbr", ""],
+ ["xmp", ""],
+ ["section", ""],
+ ["nav", ""],
+ ["article", ""],
+ ["aside", ""],
+ ["hgroup", ""],
+ ["header", ""],
+ ["footer", ""],
+ ["time", "Time"],
+ ["mark", ""],
+ ["progress", "Progress"],
+ ["meter", "Meter"],
+ ["ruby", ""],
+ ["rt", ""],
+ ["rp", ""],
+ ["figure", ""],
+ ["datalist", "DataList"],
+ ["output", "Output"],
+ ["details", "Details"],
+ ["command", "Command"],
+ ["nextid", "Unknown"],
+ ["rb", "Unknown"],
+ ["bdi", ""],
+ ["data", "Data"],
+ ["a", "Anchor"],
+ ["area", "Area"],
+ ["dialog", "Dialog"],
+ ["figcaption", ""],
+ ["summary", ""],
+ ["track", "Track"]
+];
diff --git a/tests/wpt/web-platform-tests/html/semantics/links/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/links/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/links/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/links/downloading-resources/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/links/downloading-resources/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/links/downloading-resources/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/links/downloading-resources/contains.json b/tests/wpt/web-platform-tests/html/semantics/links/downloading-resources/contains.json
new file mode 100644
index 00000000000..b67f855cfb8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/links/downloading-resources/contains.json
@@ -0,0 +1,6 @@
+[
+ {
+ "id": "hyperlink-auditing",
+ "original_id": "hyperlink-auditing"
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/links/following-hyperlinks/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/links/following-hyperlinks/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/links/following-hyperlinks/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/links/introduction-3/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/links/introduction-3/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/links/introduction-3/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/links/links-created-by-a-and-area-elements/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/links/links-created-by-a-and-area-elements/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/links/links-created-by-a-and-area-elements/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/links/linktypes/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/links/linktypes/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/links/linktypes/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/links/linktypes/contains.json b/tests/wpt/web-platform-tests/html/semantics/links/linktypes/contains.json
new file mode 100644
index 00000000000..55aa4f6774a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/links/linktypes/contains.json
@@ -0,0 +1,68 @@
+[
+ {
+ "id": "rel-alternate",
+ "original_id": "rel-alternate"
+ },
+ {
+ "id": "link-type-author",
+ "original_id": "link-type-author"
+ },
+ {
+ "id": "link-type-bookmark",
+ "original_id": "link-type-bookmark"
+ },
+ {
+ "id": "link-type-help",
+ "original_id": "link-type-help"
+ },
+ {
+ "id": "rel-icon",
+ "original_id": "rel-icon"
+ },
+ {
+ "id": "link-type-license",
+ "original_id": "link-type-license"
+ },
+ {
+ "id": "link-type-nofollow",
+ "original_id": "link-type-nofollow"
+ },
+ {
+ "id": "link-type-noreferrer",
+ "original_id": "link-type-noreferrer"
+ },
+ {
+ "id": "link-type-prefetch",
+ "original_id": "link-type-prefetch"
+ },
+ {
+ "id": "link-type-search",
+ "original_id": "link-type-search"
+ },
+ {
+ "id": "link-type-stylesheet",
+ "original_id": "link-type-stylesheet"
+ },
+ {
+ "id": "link-type-tag",
+ "original_id": "link-type-tag"
+ },
+ {
+ "id": "sequential-link-types",
+ "original_id": "sequential-link-types",
+ "children": [
+ {
+ "id": "link-type-next",
+ "original_id": "link-type-next"
+ },
+ {
+ "id": "link-type-prev",
+ "original_id": "link-type-prev"
+ }
+ ]
+ },
+ {
+ "id": "other-link-types",
+ "original_id": "other-link-types"
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/links/linktypes/original-id.json b/tests/wpt/web-platform-tests/html/semantics/links/linktypes/original-id.json
new file mode 100644
index 00000000000..1e5f7b5ed36
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/links/linktypes/original-id.json
@@ -0,0 +1 @@
+{"original_id":"linkTypes"} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/scripting-1/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-noscript-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-noscript-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-noscript-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/async_001.htm b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/async_001.htm
new file mode 100644
index 00000000000..370152683b9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/async_001.htm
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Async property on a dynamically-created script is true by default</title>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
+ <meta description="This test checks the Async property on a dynamically-created script element. By default it should be true." />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-script-async"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id=log></div>
+ <script type="text/javascript">
+ test(function() {assert_true(document.createElement("script").async)}, "Async property on a dynamically-created script is true by default");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/async_002.htm b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/async_002.htm
new file mode 100644
index 00000000000..e1850ff6e16
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/async_002.htm
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Changes to the 'async' attribute are reflected in the async property</title>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
+ <meta description="This test ensures changes to the 'async' attribute are reflected in the async property." />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-script-async"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id=log></div>
+ <script type="text/javascript">
+ test(function() {
+ var s = document.createElement("script");
+ s.async = false;
+ s.setAttribute('async', ''); /*Should change s.async to true*/
+ assert_true(s.async)
+ }, "Test 'async' attribute are reflected in the async property with setAttribute");
+
+ test(function() {
+ var s = document.createElement("script");
+ s.async = false;
+ s.setAttribute('async', ''); /*Should change s.async to true*/
+ s.removeAttribute('async'); /*Should change s.async to false*/
+ assert_false(s.async)
+ }, "Test 'async' attribute are reflected in the async property with removeAttribute");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/async_003.htm b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/async_003.htm
new file mode 100644
index 00000000000..b9a854c6bbf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/async_003.htm
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>An async script does not block the parser while downloading</title>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
+ <meta description="This test ensures an async script does not block the parser while downloading." />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#attr-script-async"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id=log></div>
+ <script type="text/javascript">
+ var t = async_test("An async script does not block the parser while downloading");
+
+ function timeout()
+ {
+ t.step(function(){ assert_equals(document.getElementById("testresult").innerHTML, "21")});
+ t.done();
+ }
+
+ var timer = setTimeout(timeout, 4000);
+
+ function log(text)
+ {
+ var textNode = document.createTextNode(text);
+ document.getElementById("testresult").appendChild(textNode);
+ }
+ </script>
+
+ <span id="testresult"></span>
+
+ <script src="log.py?sec=3&id=1" async></script>
+ <script>
+ log('2');
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/async_004.htm b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/async_004.htm
new file mode 100644
index 00000000000..7908b757a3d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/async_004.htm
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>An async script executes as soon as possible after a download is complete</title>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
+ <meta description="This test ensures an async script executes as soon as possible after a download is complete." />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#attr-script-async"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id=log></div>
+ <script type="text/javascript">
+ var t = async_test("async script executes as soon as possible after a download is complete");
+
+ function timeout()
+ {
+ t.step(function(){ assert_equals(document.getElementById("testresult").innerHTML, "21")});
+ t.done();
+ }
+
+ var timer = setTimeout(timeout, 4000);
+
+ function log(text)
+ {
+ var textNode = document.createTextNode(text);
+ document.getElementById("testresult").appendChild(textNode);
+ }
+ </script>
+
+ <span id="testresult"></span>
+
+ <script src="log.py?sec=3&id=1" async></script>
+ <script src="log.py?sec=1&id=2" async></script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/async_005.htm b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/async_005.htm
new file mode 100644
index 00000000000..4519d72346e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/async_005.htm
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>A script element with both async and defer set should execute asynchronously</title>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
+ <meta description="This test ensures a script element with both async and defer set should execute asynchronously." />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#attr-script-async"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id=log></div>
+ <script type="text/javascript">
+ var t = async_test("A script element with both async and defer set should execute asynchronously");
+
+ function timeout()
+ {
+ t.step(function(){ assert_equals(document.getElementById("testresult").innerHTML, "2134")});
+ t.done();
+ }
+
+ var timer = setTimeout(timeout, 5000);
+
+ function log(text)
+ {
+ var textNode = document.createTextNode(text);
+ document.getElementById("testresult").appendChild(textNode);
+ }
+ </script>
+
+ <span id="testresult"></span>
+
+ <script type="text/javascript" src="log.py?sec=1&id=1" defer async></script>
+ <script type="text/javascript">log('2');</script>
+ <script type="text/javascript" src="log.py?sec=3&id=3"></script>
+ <script type="text/javascript">log('4');</script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/async_006.htm b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/async_006.htm
new file mode 100644
index 00000000000..86eb99897ab
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/async_006.htm
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>A dynamically created external script executes asynchronously</title>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
+ <meta description="This test ensures a dynamically created external script executes asynchronously." />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#force-async"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id=log></div>
+ <script type="text/javascript">
+ var t = async_test("dynamically created external script executes asynchronously");
+
+ function timeout()
+ {
+ t.step(function(){ assert_equals(document.getElementById("testresult").innerHTML, "321")});
+ t.done();
+ }
+
+ var timer = setTimeout(timeout, 4000);
+
+ function log(text)
+ {
+ var textNode = document.createTextNode(text);
+ document.getElementById("testresult").appendChild(textNode);
+ }
+ </script>
+
+ <span id="testresult"></span>
+ <script type="text/javascript">
+ var one = document.createElement("script");
+ one.src="log.py?sec=3&id=1";
+ document.head.appendChild(one);
+
+ var two = document.createElement("script");
+ two.src="log.py?sec=1&id=2";
+ document.head.appendChild(two);
+
+ log('3');
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/async_007.htm b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/async_007.htm
new file mode 100644
index 00000000000..8df0fba37d0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/async_007.htm
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Ordered async script execution when script.async == false</title>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
+ <meta description="This test ensures Ordered async script execution when script.async == false" />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#script-processing-src-sync"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id=log></div>
+ <script type="text/javascript">
+ var t = async_test("Ordered async script execution when script.async == false");
+
+ function timeout()
+ {
+ t.step(function(){ assert_equals(document.getElementById("testresult").innerHTML, "312")});
+ t.done();
+ }
+
+ var timer = setTimeout(timeout, 8000);
+
+ function log(text)
+ {
+ var textNode = document.createTextNode(text);
+ document.getElementById("testresult").appendChild(textNode);
+ }
+ </script>
+
+ <span id="testresult"></span>
+ <script type="text/javascript">
+ var one = document.createElement("script");
+ one.src="log.py?sec=3&id=1";
+ one.async = false;
+ document.head.appendChild(one);
+
+ var two = document.createElement("script");
+ two.src="log.py?sec=1&id=2";
+ two.async = false;
+ document.head.appendChild(two);
+ </script>
+ <script type="text/javascript">
+ log('3');
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/async_008.htm b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/async_008.htm
new file mode 100644
index 00000000000..73529cc3182
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/async_008.htm
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Async script element execution delays the window's load event</title>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
+ <meta description="This test ensures an async script element's execution delays the window's load event." />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#delay-the-load-event"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id=log></div>
+ <script type="text/javascript">
+ var t = async_test("Async script element execution delays the window's load event");
+
+ function timeout()
+ {
+ t.step(function(){ assert_equals(document.getElementById("testresult").innerHTML, "213")});
+ t.done();
+ }
+
+ var timer = setTimeout(timeout, 8000);
+
+ function log(text)
+ {
+ var textNode = document.createTextNode(text);
+ document.getElementById("testresult").appendChild(textNode);
+ }
+ </script>
+
+ <span id="testresult"></span>
+ <script type="text/javascript">
+ window.addEventListener("load", function() {
+ log("3");
+ timeout();
+ }, false);
+
+ var s1 = document.createElement("script");
+ s1.src = "log.py?sec=2&id=1";
+ document.head.appendChild(s1);
+ </script>
+ <script type="text/javascript">
+ log('2');
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/async_009.htm b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/async_009.htm
new file mode 100644
index 00000000000..501edda065a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/async_009.htm
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Document.write() silently fails from an Async script</title>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
+ <meta description="This test ensures Document.write() silently fails from an Async script." />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript">
+ var t = async_test("Document.write() silently fails from an Async script");
+
+ var log = t.step_func(function() {
+ document.write("<span id='writtenText'/>");
+ assert_equals(null, document.getElementById('writtenText'));
+ t.done();
+ });
+ </script>
+ </head>
+ <body>
+ <div id=log></div>
+ <script type="text/javascript" src="log.py?sec=1&id=1" async></script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/async_010.htm b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/async_010.htm
new file mode 100644
index 00000000000..959a8aa274d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/async_010.htm
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Removing an async script before execution</title>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
+ <meta description="This test ensures that an async script still executes if it is removed from a markup before the download is complete. The other two scripts that come after it in insertion order should execute as well." />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript">
+ var t = async_test("Removing an async script before execution");
+
+ function timeout()
+ {
+ t.step(function(){ assert_equals(document.getElementById("testresult").innerHTML, "4123")});
+ t.done();
+ }
+
+ var timer = setTimeout(timeout, 8000);
+
+ function log(text)
+ {
+ var textNode = document.createTextNode(text);
+ document.getElementById("testresult").appendChild(textNode);
+ }
+ </script>
+ </head>
+ <body>
+ <div id=log></div>
+ <span id="testresult"></span>
+ <script type="text/javascript">
+ var s1 = document.createElement("script");
+ s1.src="log.py?sec=2&id=1";
+ s1.async = false;
+ document.body.appendChild(s1);
+
+ var s2 = document.createElement("script");
+ s2.src="log.py?sec=1&id=2";
+ s2.async = false;
+ document.body.appendChild(s2);
+
+ var s3 = document.createElement("script");
+ s3.id = "s3";
+ s3.src="log.py?sec=0&id=3";
+ s3.async = false;
+ document.body.appendChild(s3);
+
+ //Remove s1 (Should still execute)
+ document.body.removeChild(s1);
+ </script>
+ <script type="text/javascript">log('4');</script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/async_011.htm b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/async_011.htm
new file mode 100644
index 00000000000..d80e463cee5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/async_011.htm
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>An empty parser-inserted script element should return async=true</title>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
+ <meta description="An empty parser-inserted script element should return async=true." />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#prepare-a-script"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id=log></div>
+ <script></script>
+ <script type="text/javascript">
+ test(function() { assert_true(document.getElementsByTagName("script")[2].async)}, "An empty parser-inserted script element should return async=true");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/contains.json b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/contains.json
new file mode 100644
index 00000000000..e31ce400312
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/contains.json
@@ -0,0 +1,18 @@
+[
+ {
+ "id": "scriptinglanguages",
+ "original_id": "scriptingLanguages"
+ },
+ {
+ "id": "restrictions-for-contents-of-script-elements",
+ "original_id": "restrictions-for-contents-of-script-elements"
+ },
+ {
+ "id": "inline-documentation-for-external-scripts",
+ "original_id": "inline-documentation-for-external-scripts"
+ },
+ {
+ "id": "scripttagxslt",
+ "original_id": "scriptTagXSLT"
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/log.py b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/log.py
new file mode 100644
index 00000000000..6803bb3e405
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/log.py
@@ -0,0 +1,13 @@
+import time
+
+def main(request, response):
+ response.headers.append("Content-Type", "text/javascript")
+ try:
+ script_id = int(request.GET.first("id"))
+ delay = int(request.GET.first("sec"))
+ except:
+ response.set_error(400, "Invalid parameter")
+
+ time.sleep(int(delay))
+
+ return "log('%s')" % script_id
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/script-before-after-events.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/script-before-after-events.html
new file mode 100644
index 00000000000..4cd77250ed6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/script-before-after-events.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>script beforescriptexecute/afterscriptexecute events</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#the-script-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+ var t1 = async_test("'beforescriptexecute'/'afterscriptexecute' events have been fired"),
+ t2 = async_test("default prevented 'beforescriptexecute' event aborts script execution"),
+ a = false,
+ b = false;
+
+ var before = function(e) {
+ b = true;
+ test(function(){
+ assert_true(e.isTrusted);
+ assert_true(e.bubbles);
+ assert_true(e.cancelable);
+ }, "'beforescriptexecute' event is trusted, bubbles and is cancelable");
+ };
+
+ var after = function(e) {
+ a = true;
+ test(function(){
+ assert_true(e.isTrusted);
+ assert_true(e.bubbles);
+ assert_false(e.cancelable);
+ }, "'afterscriptexecute' event is trusted, bubbles and isn't cancelable");
+ };
+
+ var prevent_default = function(e) {
+ t2.step(function() {
+ e.preventDefault();
+ assert_true(e.defaultPrevented);
+ });
+ };
+
+ document.body.onload = function() {
+ t1.step(function() {
+ assert_true(a && b);
+ });
+ t1.done();
+ t2.done();
+ };
+</script>
+<script onbeforescriptexecute=before(event) onafterscriptexecute=after(event)>
+ document.querySelector("script");
+</script>
+<script onbeforescriptexecute=prevent_default(event)>
+ t2.step(function() {
+ assert_unreached("script execution not aborted by default prevented 'beforescriptexecute' event");
+ });
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/script-for-event.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/script-for-event.html
new file mode 100644
index 00000000000..552ea7041a3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/script-for-event.html
@@ -0,0 +1,93 @@
+<!DOCTYPE html>
+<title>Scripts with for and event attributes</title>
+<link rel="author" title="Matheus Kerschbaum" href="mailto:matjk7@gmail.com">
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#prepare-a-script">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var expected = [
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ false,
+ true,
+ true,
+ false,
+ true,
+ true,
+];
+var run = expected.map(function() { return false });
+</script>
+<script for="w&#x130;ndow" event="onload">
+run[0] = true;
+</script>
+<script for="window" event="onload x">
+run[1] = true;
+</script>
+<script for="window" event="onload(x">
+run[2] = true;
+</script>
+<script for="window" event="onload(x)">
+run[3] = true;
+</script>
+<script for="window" event="onclick">
+run[4] = true;
+</script>
+<script for="" event="onload">
+run[5] = true;
+</script>
+<script for="window" event="">
+run[6] = true;
+</script>
+<script for="" event="">
+run[7] = true;
+</script>
+<script for="&#xa0;window" event="onload">
+run[8] = true;
+</script>
+<script for="window&#xa0;" event="onload">
+run[9] = true;
+</script>
+<script for="window" event="&#xa0;onload">
+run[10] = true;
+</script>
+<script for="window" event="onload&#xa0;">
+run[11] = true;
+</script>
+<script for=" window " event=" onload ">
+run[12] = true;
+</script>
+<script for=" window " event=" onload() ">
+run[13] = true;
+</script>
+<script for="object" event="handler">
+run[14] = true;
+</script>
+<script event="handler">
+run[15] = true;
+</script>
+<script for="object">
+run[16] = true;
+</script>
+<script>
+test(function() {
+ for (var i = 0; i < run.length; ++i) {
+ test(function() {
+ var script = document.querySelectorAll("script[for], script[event]")[i];
+ assert_equals(run[i], expected[i],
+ "script for=" + format_value(script.getAttribute("for")) +
+ " event=" + format_value(script.getAttribute("event")));
+ }, "Script " + i);
+ }
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/script-for-event.xhtml b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/script-for-event.xhtml
new file mode 100644
index 00000000000..69c4ef1f810
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/script-for-event.xhtml
@@ -0,0 +1,22 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>Scripts with for and event attributes</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script>
+ var run = false;
+ </script>
+ <script for="window" event="bar">
+ // This script should not run, but should not cause a parse error either.
+ run = true;
+ </script>
+ <script>
+ test(function() {
+ assert_false(run, "Script was unexpectedly run.")
+ }, "Scripts with for and event attributes should not run.")
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/script-language-type.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/script-language-type.html
new file mode 100644
index 00000000000..b94834c83dd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/script-language-type.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<title>Script: combinations of @type and @language</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#prepare-a-script">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var run = false;
+</script>
+<script type="" language="foo">
+run = true;
+</script>
+<script>
+test(function() {
+ assert_equals(run, true);
+}, "A script with empty type should run");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/script-languages-01.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/script-languages-01.html
new file mode 100644
index 00000000000..f2f2724df5a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/script-languages-01.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<title>Script @type: unknown parameters</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#scriptingLanguages">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<div id="test">
+<script type="text/javascript;charset=UTF-8">
+test(function() {
+ assert_unreached("'charset' should have prevented this script from executing.");
+})
+</script>
+<script type="text/javascript;x-test=abc">
+test(function() {
+ assert_unreached("'x-test' should have prevented this script from executing.");
+})
+</script>
+</div>
+<script>
+test(function() {
+ assert_true(true)
+})
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/script-languages-02.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/script-languages-02.html
new file mode 100644
index 00000000000..69613e5104f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/script-languages-02.html
@@ -0,0 +1,98 @@
+<!DOCTYPE html>
+<title>Script @type: JavaScript types</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#scriptingLanguages">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+function testAttribute(attr, val, shouldRun) {
+ test(function() {
+ assert_false(ran, "ran variable not reset");
+ var script = document.createElement("script");
+ script.setAttribute(attr, val);
+ script.textContent = "ran = true;"
+ document.body.appendChild(script);
+ assert_equals(ran, shouldRun);
+ }, "Script should" + (shouldRun ? "" : "n't") + " run with " + attr + "=" + format_value(val));
+ ran = false
+}
+function testType(type) {
+ testAttribute("type", type, true);
+}
+function testLanguage(lang) {
+ testAttribute("language", lang, true);
+}
+function testTypeIgnored(type) {
+ testAttribute("type", type, false);
+}
+function testLanguageIgnored(lang) {
+ testAttribute("language", lang, false);
+}
+var application = [
+ "ecmascript",
+ "javascript",
+ "x-ecmascript",
+ "x-javascript"
+];
+var text = [
+ "ecmascript",
+ "javascript",
+ "javascript1.0",
+ "javascript1.1",
+ "javascript1.2",
+ "javascript1.3",
+ "javascript1.4",
+ "javascript1.5",
+ "jscript",
+ "livescript",
+ "x-ecmascript",
+ "x-javascript"
+];
+var spaces = [" ", "\t", "\n", "\r", "\f"];
+
+var ran = false;
+
+// Type attribute
+
+testType("");
+testTypeIgnored(" ");
+
+application.map(function(t) { return "application/" + t; }).forEach(testType);
+application.map(function(t) { return ("application/" + t).toUpperCase(); }).forEach(testType);
+
+spaces.forEach(function(s) {
+ application.map(function(t) { return "application/" + t + s; }).forEach(testType);
+ application.map(function(t) { return s + "application/" + t; }).forEach(testType);
+})
+
+application.map(function(t) { return "application/" + t + "\0"; }).forEach(testTypeIgnored);
+application.map(function(t) { return "application/" + t + "\0foo"; }).forEach(testTypeIgnored);
+
+text.map(function(t) { return "text/" + t; }).forEach(testType);
+text.map(function(t) { return ("text/" + t).toUpperCase(); }).forEach(testType);
+
+spaces.forEach(function(s) {
+ text.map(function(t) { return "text/" + t + s; }).forEach(testType);
+ text.map(function(t) { return s + "text/" + t; }).forEach(testType);
+})
+
+text.map(function(t) { return "text/" + t + "\0"; }).forEach(testTypeIgnored);
+text.map(function(t) { return "text/" + t + "\0foo"; }).forEach(testTypeIgnored);
+
+// Language attribute
+
+testLanguage("");
+testLanguageIgnored(" ");
+
+text.forEach(testLanguage);
+text.map(function(t) { return t.toUpperCase(); }).forEach(testLanguage);
+
+text.map(function(t) { return t + " "; }).forEach(testLanguageIgnored);
+text.map(function(t) { return " " + t; }).forEach(testLanguageIgnored);
+text.map(function(t) { return t + "xyz"; }).forEach(testLanguageIgnored);
+text.map(function(t) { return "xyz" + t; }).forEach(testLanguageIgnored);
+
+text.map(function(t) { return t + "\0"; }).forEach(testLanguageIgnored);
+text.map(function(t) { return t + "\0foo"; }).forEach(testLanguageIgnored);
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/script-noembed-noframes-iframe.xhtml b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/script-noembed-noframes-iframe.xhtml
new file mode 100644
index 00000000000..8dd9ceb9a62
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/script-noembed-noframes-iframe.xhtml
@@ -0,0 +1,36 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Script inside noembed, noframes and iframe</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com"/>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id="log"></div>
+<script>
+var run = [];
+</script>
+<div id="test">
+<noembed>
+<script>
+run.push("noembed");
+</script>
+</noembed>
+<noframes>
+<script>
+run.push("noframes");
+</script>
+</noframes>
+<iframe>
+<script>
+run.push("iframe");
+</script>
+</iframe>
+</div>
+<script>
+test(function() {
+ assert_array_equals(run, ["noembed", "noframes", "iframe"], "Haven't run.");
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/script-onload-string.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/script-onload-string.html
new file mode 100644
index 00000000000..85f2d4dcfaf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/script-onload-string.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<title>Script: setting onload to a string</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+test(function() {
+ var s = document.createElement("script");
+ assert_equals(s.onload, null);
+ var dummy = function() {};
+ s.onload = dummy;
+ assert_equals(s.onload, dummy);
+ s.onload = "w('load DOM appended')";
+ assert_equals(s.onload, null);
+}, "Setting onload to a string should convert to null.");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/script-text.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/script-text.html
new file mode 100644
index 00000000000..e32f8402427
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/script-text.html
@@ -0,0 +1,53 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>HTMLScriptElement.text</title>
+<link rel=help href="https://html.spec.whatwg.org/multipage/#dom-script-text">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var script;
+setup(function() {
+ script = document.createElement("script")
+ script.appendChild(document.createComment("COMMENT"))
+ script.appendChild(document.createTextNode(" TEXT "))
+ script.appendChild(document.createProcessingInstruction("P", "I"))
+ script.appendChild(document.createElement("a"))
+ .appendChild(document.createTextNode("ELEMENT"))
+})
+test(function() {
+ assert_equals(script.text, " TEXT ")
+ assert_equals(script.textContent, " TEXT ELEMENT")
+}, "Getter")
+test(function() {
+ script.text = " text "
+ assert_equals(script.text, " text ")
+ assert_equals(script.textContent, " text ")
+ assert_equals(script.firstChild.nodeType, Node.TEXT_NODE)
+ assert_equals(script.firstChild.data, " text ")
+ assert_equals(script.firstChild, script.lastChild)
+ assert_array_equals(script.childNodes, [script.firstChild])
+}, "Setter (non-empty string)")
+test(function() {
+ script.text = ""
+ assert_equals(script.text, "")
+ assert_equals(script.textContent, "")
+ assert_equals(script.firstChild, null)
+}, "Setter (empty string)")
+test(function() {
+ script.text = null
+ assert_equals(script.text, "null")
+ assert_equals(script.textContent, "null")
+ assert_equals(script.firstChild.nodeType, Node.TEXT_NODE)
+ assert_equals(script.firstChild.data, "null")
+ assert_equals(script.firstChild, script.lastChild)
+}, "Setter (null)")
+test(function() {
+ script.text = undefined
+ assert_equals(script.text, "undefined")
+ assert_equals(script.textContent, "undefined")
+ assert_equals(script.firstChild.nodeType, Node.TEXT_NODE)
+ assert_equals(script.firstChild.data, "undefined")
+ assert_equals(script.firstChild, script.lastChild)
+}, "Setter (undefined)")
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/script-text.xhtml b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/script-text.xhtml
new file mode 100644
index 00000000000..33a4635db37
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-script-element/script-text.xhtml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>HTMLScriptElement.text</title>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-script-text"/>
+<script src="/resources/testharness.js"/>
+<script src="/resources/testharnessreport.js"/>
+</head>
+<body>
+<div id="log"></div>
+<script>
+<x>7;</x>
+<![CDATA[
+ var x = "y";
+]]>
+</script>
+<script>
+var script;
+setup(function() {
+ script = document.body.getElementsByTagName("script")[0];
+})
+test(function() {
+ assert_equals(script.text, '\n\n\n var x = "y";\n\n')
+ assert_equals(script.textContent, '\n7;\n\n var x = "y";\n\n')
+}, "Getter with CDATA section")
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/additions-to-parsing-xhtml-documents/node-document.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/additions-to-parsing-xhtml-documents/node-document.html
new file mode 100644
index 00000000000..d3903738e27
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/additions-to-parsing-xhtml-documents/node-document.html
@@ -0,0 +1,148 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>HTML Templates: Parsing XHTML: Node's node document</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<meta name="assert" content="Parsing XHTML: Node's node document must be set to that of the element to which it will be appended">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#parsing-xhtml-documents">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src='../testcommon.js'></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script type="text/javascript">
+
+
+
+test(function() {
+ var doc = newXHTMLDocument();
+ doc.body = doc.createElement('body');
+ doc.body.innerHTML = '<template id="tmpl"></template>';
+
+ var template = doc.querySelector('#tmpl');
+
+ assert_not_equals(template, null, 'Template element should not be null');
+ assert_not_equals(template.content, undefined,
+ 'Content attribute of template element should not be undefined');
+ assert_not_equals(template.content, null,
+ 'Content attribute of template element should not be null');
+
+ assert_equals(template.ownerDocument, doc.body.ownerDocument,
+ 'Wrong template node owner document');
+ assert_equals(template.content.ownerDocument, doc,
+ 'Wrong template content owner document');
+
+}, 'Parsing XHTML: Node\'s node document must be set to that of the element '
+ + 'to which it will be appended. Test empty template');
+
+
+
+test(function() {
+ var doc = newXHTMLDocument();
+
+ doc.body = doc.createElement('body');
+ doc.body.innerHTML = '<template id="tmpl"><div>Div content</div></template>';
+
+ var template = doc.querySelector('#tmpl');
+
+ assert_equals(template.ownerDocument, doc.body.ownerDocument,
+ 'Wrong template node owner document');
+
+ assert_not_equals(template, null, 'Template element should not be null');
+ assert_not_equals(template.content, undefined,
+ 'Content attribute of template element should not be undefined');
+ assert_not_equals(template.content, null,
+ 'Content attribute of template element should not be null');
+
+ var div = template.content.querySelector('div');
+ assert_equals(template.content.ownerDocument, div.ownerDocument,
+ 'Wrong DIV node owner document');
+
+}, 'Parsing XHTML: Node\'s node document must be set to that of the element '
+ + 'to which it will be appended. Test not empty template');
+
+
+
+test(function() {
+ var doc = newXHTMLDocument();
+ doc.body = doc.createElement('body');
+ doc.body.innerHTML = ''
+ + '<template id="tmpl"><div>Div content</div> And some more text'
+ + '<template id="tmpl2"><div>Template content</div></template>'
+ + '</template>';
+
+ var template = doc.querySelector('#tmpl');
+ assert_not_equals(template, null, 'Template element should not be null');
+ assert_equals(template.ownerDocument, doc, 'Wrong template node owner document');
+ assert_not_equals(template.content, undefined,
+ 'Content attribute of template element should not be undefined');
+ assert_not_equals(template.content, null,
+ 'Content attribute of template element should not be null');
+
+ var nestedTemplate = template.content.querySelector('#tmpl2');
+ assert_not_equals(nestedTemplate, null, 'Nested template element should not be null');
+ assert_not_equals(nestedTemplate.content, undefined,
+ 'Content attribute of nested template element should not be undefined');
+ assert_not_equals(nestedTemplate.content, null,
+ 'Content attribute of nested template element should not be null');
+
+ assert_equals(nestedTemplate.ownerDocument, template.content.ownerDocument,
+ 'Wrong nested template node owner document');
+
+
+ var div = nestedTemplate.content.querySelector('div');
+ assert_equals(nestedTemplate.content.ownerDocument, div.ownerDocument,
+ 'Wrong DIV node owner document');
+
+}, 'Parsing XHTML: Node\'s node document must be set to that of the element '
+ + 'to which it will be appended. Test nested templates');
+
+
+
+testInIFrame('../resources/template-child-nodes-div.xhtml', function(context) {
+ var doc = context.iframes[0].contentDocument;
+
+ var template = doc.querySelector('template');
+
+ assert_equals(template.ownerDocument, doc, 'Wrong template node owner document');
+
+ assert_not_equals(template.content, undefined,
+ 'Content attribute of template element should not be undefined');
+ assert_not_equals(template.content, null,
+ 'Content attribute of template element should not be null');
+
+ var div = template.content.querySelector('div');
+ assert_equals(template.content.ownerDocument, div.ownerDocument,
+ 'Wrong DIV node owner document');
+
+}, 'Parsing XHTML: Node\'s node document must be set to that of the element '
+ + 'to which it will be appended. Test loading XHTML document from a file');
+
+
+
+testInIFrame('../resources/template-child-nodes-nested.xhtml', function(context) {
+ var doc = context.iframes[0].contentDocument;
+
+ var template = doc.querySelector('template');
+
+ assert_equals(template.ownerDocument, doc, 'Wrong template node owner document');
+
+ var nestedTemplate = template.content.querySelector('template');
+
+ assert_equals(nestedTemplate.ownerDocument, template.content.ownerDocument,
+ 'Wrong template node owner document');
+
+ var div = nestedTemplate.content.querySelector('div');
+ assert_equals(nestedTemplate.content.ownerDocument, div.ownerDocument,
+ 'Wrong DIV node owner document');
+
+}, 'Parsing XHTML: Node\'s node document must be set to that of the element '
+ + 'to which it will be appended. Test loading of XHTML document '
+ + 'with nested templates from a file');
+
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/additions-to-parsing-xhtml-documents/template-child-nodes.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/additions-to-parsing-xhtml-documents/template-child-nodes.html
new file mode 100644
index 00000000000..a5a644af3ad
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/additions-to-parsing-xhtml-documents/template-child-nodes.html
@@ -0,0 +1,103 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>HTML Templates: Child nodes of template element in XHTML documents</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="author" title="Aleksei Yu. Semenov" href="a.semenov@unipro.ru">
+<meta name="assert" content="Child nodes of template element in XHTML documents are always appended to the template content (instead of template itself)">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#parsing-xhtml-documents">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src='../testcommon.js'></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script type="text/javascript">
+
+
+test(function() {
+ var doc = newXHTMLDocument();
+
+ doc.body = doc.createElement('body');
+ doc.body.innerHTML = '<template id="tmpl1">'
+ + '<div id="div1">This is div inside template</div>'
+ + '<div id="div2">This is another div inside template</div>'
+ + '</template>';
+
+ var template = doc.querySelector('#tmpl1');
+
+ assert_equals(template.childNodes.length, 0,
+ 'Wrong number of template child nodes');
+ assert_equals(template.content.childNodes.length, 2,
+ 'Wrong number of template content child nodes');
+
+}, 'Child nodes of template element in XHTML documents must be appended to template content');
+
+
+
+test(function() {
+ var doc = newXHTMLDocument();
+ doc.body = doc.createElement('body');
+ doc.body.innerHTML = '<template id="tmpl1">'
+ + '<div id="div1">This is div inside template</div>'
+ + '<div id="div2">This is another div inside template</div>'
+ + '<template id="tmpl2">'
+ + '<div id="div3">This is div inside nested template</div>'
+ + '<div id="div4">This is another div inside nested template</div>'
+ + '</template>' + '</template>';
+
+ var template = doc.querySelector('#tmpl1');
+
+ assert_equals(template.childNodes.length, 0,
+ 'Wrong number of template child nodes');
+ assert_equals(template.content.childNodes.length, 3,
+ 'Wrong number of template content child nodes');
+
+ var nestedTemplate = template.content.querySelector('#tmpl2');
+
+ assert_equals(nestedTemplate.childNodes.length, 0,
+ 'Wrong number of template child nodes');
+ assert_equals(nestedTemplate.content.childNodes.length, 2,
+ 'Wrong number of nested template content child nodes');
+
+}, 'Child nodes of nested template element in XHTML documents must be appended to template content');
+
+
+
+testInIFrame('../resources/template-child-nodes-div.xhtml', function(context) {
+ var doc = context.iframes[0].contentDocument;
+
+ var template = doc.querySelector('template');
+
+ assert_equals(template.childNodes.length, 0,
+ 'Wrong number of template child nodes');
+ assert_equals(template.content.querySelectorAll('div').length, 2,
+ 'Wrong number of template content child nodes');
+
+}, 'Child nodes of template element in XHTML documents must be appended to template content. '
+ + 'Test loading XHTML document from a file');
+
+
+testInIFrame('../resources/template-child-nodes-nested.xhtml', function(context) {
+ var doc = context.iframes[0].contentDocument;
+
+ var template = doc.querySelector('template');
+
+ assert_equals(template.childNodes.length, 0,
+ 'Wrong number of template child nodes');
+
+ var nestedTemplate = template.content.querySelector('template');
+
+ assert_equals(nestedTemplate.childNodes.length, 0,
+ 'Wrong number of template child nodes');
+
+ assert_equals(nestedTemplate.content.querySelectorAll('div').length, 2,
+ 'Wrong number of template content child nodes');
+
+}, 'Child nodes of nested template element in XHTML documents must be appended to template content. '
+ + 'Test loading XHTML document from a file');
+
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/additions-to-serializing-xhtml-documents/outerhtml.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/additions-to-serializing-xhtml-documents/outerhtml.html
new file mode 100644
index 00000000000..931c0fc9b40
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/additions-to-serializing-xhtml-documents/outerhtml.html
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>HTML Templates: serialize template contents instead of template element</title>
+<meta name="author" title="Aleksei Yu. Semenov" href="a.semenov@unipro.ru">
+<meta name="assert" content="Template contents should be serialized instead of template element if serializing template element in XHTML document">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#serializing-xhtml-documents">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src='../testcommon.js'></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script type="text/javascript">
+
+test(function () {
+ var doc = newXHTMLDocument();
+ var template = doc.createElement('template');
+
+ var div = doc.createElement('div');
+ div.setAttribute('id', 'div1');
+ div.innerHTML = 'some text';
+ template.content.appendChild(div);
+
+ assert_equals(template.outerHTML, '<template xmlns="http://www.w3.org/1999/xhtml"><div id="div1">some text</div></template>',
+ 'template element is serialized incorrectly');
+
+}, 'Template contents should be serialized instead of template element if serializing template element');
+
+
+
+test(function () {
+ var doc = newXHTMLDocument();
+ var template = doc.createElement('template');
+ var nestedTemplate = doc.createElement('template');
+
+ template.content.appendChild(nestedTemplate);
+
+ var div = doc.createElement('div');
+ div.setAttribute('id', 'div1');
+ div.innerHTML = 'some text';
+ nestedTemplate.content.appendChild(div);
+
+ assert_equals(template.outerHTML, '<template xmlns="http://www.w3.org/1999/xhtml"><template><div id="div1">some text</div></template></template>',
+ 'template element is serialized incorrectly');
+
+
+}, 'Template contents should be serialized instead of template element if serializing template element. '
+ + 'Test nested template');
+
+
+test(function () {
+ var doc = newXHTMLDocument();
+ var template = doc.createElement('template');
+
+ var div = doc.createElement('div');
+ div.setAttribute('id', 'div1');
+ div.innerHTML = 'some text';
+ template.content.appendChild(div);
+ doc.body = doc.createElement('body');
+ doc.body.appendChild(template);
+
+ assert_equals(doc.documentElement.outerHTML, '<html xmlns="http://www.w3.org/1999/xhtml"><body><template><div id="div1">some text</div></template></body></html>',
+ 'template element is serialized incorrectly');
+
+}, 'Template contents should be serialized instead of template element if serializing template element. '
+ + 'Test serializing whole document');
+
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/additions-to-the-css-user-agent-style-sheet/css-user-agent-style-sheet-test-001-ref.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/additions-to-the-css-user-agent-style-sheet/css-user-agent-style-sheet-test-001-ref.html
new file mode 100644
index 00000000000..55c8b2e30c9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/additions-to-the-css-user-agent-style-sheet/css-user-agent-style-sheet-test-001-ref.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<title>Template Reftest Reference</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru"/>
+<body>
+ <p>Test passes if there's no anything below this line.</p>
+</body>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/additions-to-the-css-user-agent-style-sheet/css-user-agent-style-sheet-test-001.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/additions-to-the-css-user-agent-style-sheet/css-user-agent-style-sheet-test-001.html
new file mode 100644
index 00000000000..fc310f47c89
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/additions-to-the-css-user-agent-style-sheet/css-user-agent-style-sheet-test-001.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+ <title>Template Test: check that template content is invisible by default</title>
+ <link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+ <link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#css-additions">
+ <meta name="assert" content="Test checks that the template contents are hidden implicitly">
+ <link rel="match" href="css-user-agent-style-sheet-test-001-ref.html">
+<body>
+ <p>Test passes if there's no anything below this line.</p>
+ <template>
+ <span style="color:red">Test fails if you can see this text</span>
+ </template>
+</body>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/additions-to-the-css-user-agent-style-sheet/css-user-agent-style-sheet-test-002.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/additions-to-the-css-user-agent-style-sheet/css-user-agent-style-sheet-test-002.html
new file mode 100644
index 00000000000..92f3d81eaca
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/additions-to-the-css-user-agent-style-sheet/css-user-agent-style-sheet-test-002.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+ <title>Template Test: check that template content is invisible by default</title>
+ <link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+ <link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#css-additions">
+ <meta name="assert" content="The template element itself must be hidden by default">
+ <link rel="match" href="css-user-agent-style-sheet-test-001-ref.html">
+<body>
+ <p>Test passes if there's no anything below this line.</p>
+ <template style="border: 1px solid; width: 100px; height: 100px">
+ <span style="color:red">Test fails if you can see this text or border around it</span>
+ </template>
+</body>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/additions-to-the-css-user-agent-style-sheet/css-user-agent-style-sheet-test-003.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/additions-to-the-css-user-agent-style-sheet/css-user-agent-style-sheet-test-003.html
new file mode 100644
index 00000000000..4c477fde79b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/additions-to-the-css-user-agent-style-sheet/css-user-agent-style-sheet-test-003.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+ <title>HTML Templates: template content is invisible by default</title>
+ <link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+ <link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#css-additions">
+ <meta name="assert" content="The template element itself must be hidden by default">
+ <link rel="match" href="css-user-agent-style-sheet-test-001-ref.html">
+ <style>
+ template {
+ border: 1px solid;
+ width: 100px;
+ height: 100px;
+ }
+ </style>
+<body>
+ <p>Test passes if there's no anything below this line.</p>
+ <template>
+ <span style="color:red">Test fails if you can see this text or border around it</span>
+ </template>
+</body>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/additions-to-the-steps-to-clone-a-node/template-clone-children.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/additions-to-the-steps-to-clone-a-node/template-clone-children.html
new file mode 100644
index 00000000000..75725573412
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/additions-to-the-steps-to-clone-a-node/template-clone-children.html
@@ -0,0 +1,83 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>HTML Templates: Clone template node: All the children of template content are copied if 'copy children flag' set to true</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="assert" content="Clone template node: all the children of template content are copied if 'copy children flag' set to true">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#node-clone-additions">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src='../testcommon.js'></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script type="text/javascript">
+
+test(function () {
+ var doc = newHTMLDocument();
+ doc.body.innerHTML = '<template id="tmpl1">' +
+ '<div id="div1">This is div inside template</div>' +
+ '<div id="div2">This is another div inside template</div>' +
+ '</template>';
+
+ var template = doc.querySelector('#tmpl1');
+ var copy = template.cloneNode(true);
+
+ assert_not_equals(copy.content, undefined, 'Template clone content attribute should not be undefined');
+ assert_not_equals(copy.content, null, 'Template clone content attribute should not be null');
+
+ assert_equals(copy.content.childNodes.length, 2,
+ 'Wrong number of template content\'s copy child nodes');
+ assert_not_equals(copy.content.querySelector('#div1'), null,
+ 'Template child node should be copied');
+ assert_not_equals(copy.content.querySelector('#div2'), null,
+ 'Template child node should be copied');
+
+}, 'Clone template node. Test call to cloneNode(true)');
+
+
+
+test(function () {
+ var doc = newHTMLDocument();
+ doc.body.innerHTML = '<template id="tmpl1">' +
+ '<div id="div1">This is div inside template</div>' +
+ '<div id="div2">This is another div inside template</div>' +
+ '</template>';
+
+ var template = doc.querySelector('#tmpl1');
+ var copy = template.cloneNode();
+
+ assert_not_equals(copy.content, undefined, 'Template clone content attribute should not be undefined');
+ assert_not_equals(copy.content, null, 'Template clone content attribute should not be null');
+
+ assert_equals(copy.content.childNodes.length, 0,
+ 'Wrong number of template content\'s copy child nodes');
+
+}, 'Clone template node. Test call to cloneNode() with the default parameter '
+ + '(false by default)');
+
+
+
+test(function () {
+ var doc = newHTMLDocument();
+ doc.body.innerHTML = '<template id="tmpl1">' +
+ '<div id="div1">This is div inside template</div>' +
+ '<div id="div2">This is another div inside template</div>' +
+ '</template>';
+
+ var template = doc.querySelector('#tmpl1');
+ var copy = template.cloneNode(false);
+
+ assert_not_equals(copy.content, undefined, 'Template clone content attribute is undefined');
+ assert_not_equals(copy.content, null, 'Template clone content attribute is null');
+
+ assert_equals(copy.content.childNodes.length, 0,
+ 'Wrong number of template content\'s copy child nodes');
+
+}, 'Clone template node. Test call to cloneNode(false)');
+
+
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/additions-to-the-steps-to-clone-a-node/templates-copy-document-owner.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/additions-to-the-steps-to-clone-a-node/templates-copy-document-owner.html
new file mode 100644
index 00000000000..9d60e29be6a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/additions-to-the-steps-to-clone-a-node/templates-copy-document-owner.html
@@ -0,0 +1,127 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>HTML Templates: ownerDocument of cloned template content is set to template content owner</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="author" title="Aleksei Yu. Semenov" href="a.semenov@unipro.ru">
+<meta name="assert" content="ownerDocument of cloned template content is set to template content owner">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#node-clone-additions">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src='../testcommon.js'></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script type="text/javascript">
+
+function checkOwnerDocument(node, doc) {
+ if ((node !== null) && (node !== undefined)) {
+ assert_equals(node.ownerDocument, doc,
+ 'Wrong ownerDocument of the template copy\'s node ' + node.nodeName);
+ for (var i = 0; i < node.childNodes.length; i++) {
+ if (node.childNodes[i].nodeType === Node.ELEMENT_NODE) {
+ checkOwnerDocument(node.childNodes[i], doc);
+ if (node.childNodes[i].nodeName === 'TEMPLATE') {
+ checkOwnerDocument(node.childNodes[i].content, doc);
+ }
+ }
+ }
+ }
+}
+
+
+test(function () {
+ var doc = newHTMLDocument();
+ doc.body.innerHTML = '<template id="tmpl1">' +
+ '<div id="div1">This is div inside template</div>' +
+ '<div id="div2">This is another div inside template</div>' +
+ '</template>';
+
+ var template = doc.querySelector('#tmpl1');
+ var copy = template.cloneNode(true);
+
+ assert_equals(copy.content.childNodes.length, 2,
+ 'Wrong number of template content\'s copy child nodes');
+ checkOwnerDocument(copy.content, template.content.ownerDocument);
+
+}, 'ownerDocument of cloned template content is set to template content owner. '
+ + 'Test cloning with children');
+
+
+
+test(function () {
+ var doc = newHTMLDocument();
+ doc.body.innerHTML = '<template id="tmpl1">' +
+ '<div id="div1">This is div inside template</div>' +
+ '<div id="div2">This is another div inside template</div>' +
+ '</template>';
+
+ var template = doc.querySelector('#tmpl1');
+ var copy = template.cloneNode(false);
+
+ assert_equals(copy.content.childNodes.length, 0,
+ 'Wrong number of template content\'s copy child nodes');
+ checkOwnerDocument(copy.content, template.content.ownerDocument);
+
+}, 'ownerDocument of cloned template content is set to template content owner. '
+ + 'Test cloning without children');
+
+
+
+test(function () {
+ var doc = newHTMLDocument();
+ doc.body.innerHTML = '<template id="tmpl1">' +
+ '<div id="div1">This is div inside template</div>' +
+ '<div id="div2">This is another div inside template</div>' +
+ '</template>';
+
+ var template = doc.querySelector('#tmpl1');
+ var copy = template.cloneNode();
+
+ assert_equals(copy.content.childNodes.length, 0,
+ 'Wrong number of template content\'s copy child nodes');
+ checkOwnerDocument(copy.content, template.content.ownerDocument);
+
+}, 'ownerDocument of cloned template content is set to template content owner. '
+ + 'Test cloneNode() with no arguments (false by default)');
+
+
+
+test(function () {
+ var doc = newHTMLDocument();
+ doc.body.innerHTML = '<template id="tmpl1">' +
+ '<div id="div1">This is div inside template</div>' +
+ '<div id="div2">This is another div inside template</div>' +
+ '<template id="tmpl2">' +
+ '<div id="div3">This is div inside nested template</div>' +
+ '<div id="div4">This is another div inside nested template</div>' +
+ '</template>' +
+ '</template>';
+
+ var template = doc.querySelector('#tmpl1');
+ var copy = template.cloneNode(true);
+
+ assert_equals(copy.content.childNodes.length, 3,
+ 'Wrong number of template content\'s copy child nodes');
+ checkOwnerDocument(copy.content, template.content.ownerDocument);
+
+}, 'ownerDocument of cloned template content is set to template content owner. '
+ + 'Test cloning nested template');
+
+
+
+testInIFrame('../resources/template-contents.html', function(context) {
+ var doc = context.iframes[0].contentDocument;
+
+ var template = doc.body.querySelector('template');
+ var copy = template.cloneNode(true);
+
+ checkOwnerDocument(copy.content, template.content.ownerDocument);
+
+}, 'ownerDocument of cloned template content is set to template content owner. '
+ + 'Test loading HTML document from file');
+
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/definitions/template-contents-owner-document-type.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/definitions/template-contents-owner-document-type.html
new file mode 100644
index 00000000000..5f401892139
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/definitions/template-contents-owner-document-type.html
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>HTML Templates: The template contents owner document type is HTML document</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="assert" content="The template contents owner document type is HTML document, if template is declared in HTML document">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#definitions">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src='../testcommon.js'></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script type="text/javascript">
+
+testInIFrame('../resources/template-contents.html', function(context) {
+ var doc = context.iframes[0].contentDocument;
+ var template = doc.querySelector('template');
+
+ assert_class_string(template.content.ownerDocument, 'HTMLDocument',
+ 'Template content owner should be a HTML document');
+
+}, 'The template contents owner document type is HTML document ' +
+ '(case when document has browsing context and the template ' +
+ 'is created by HTML parser)');
+
+
+testInIFrame('../resources/template-contents.html', function(context) {
+ var doc = context.iframes[0].contentDocument;
+ var template = doc.createElement('template');
+ var div = doc.createElement('div');
+ template.appendChild(div);
+
+ doc.body.appendChild(template);
+
+ assert_class_string(template.content.ownerDocument, 'HTMLDocument',
+ 'Template content owner should be a HTML document');
+
+}, 'The template contents owner document type is HTML document ' +
+ '(case when document has browsing context and the template ' +
+ 'is created by createElement())');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var template = doc.createElement('template');
+ var div = doc.createElement('div');
+ template.appendChild(div);
+
+ doc.body.appendChild(template);
+
+ assert_class_string(template.content.ownerDocument, 'HTMLDocument',
+ 'Template content owner should be a HTML document');
+
+}, 'The template contents owner document type is HTML document ' +
+ '(case when document has no browsing context and the template is created ' +
+ 'by createElement())');
+
+test(function() {
+ var doc = newHTMLDocument();
+ doc.body.innerHTML = '<template><div>Hello!</div></template>';
+ var template = doc.querySelector('template');
+
+ assert_class_string(template.content.ownerDocument, 'HTMLDocument',
+ 'Template content owner should be a HTML document');
+
+}, 'The template contents owner document type is HTML document ' +
+ '(case when document has no browsing context and the template is created via innerHTML)');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/definitions/template-contents-owner-test-001.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/definitions/template-contents-owner-test-001.html
new file mode 100644
index 00000000000..2c8329f31bb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/definitions/template-contents-owner-test-001.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>HTML Templates: The template contents owner document (no browsing context)</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="assert" content="Even if template's enclosing document has no browsing context, it gets its own template contents owner">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#definitions">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src='../testcommon.js'></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script type="text/javascript">
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var template = doc.createElement('template');
+
+ doc.body.appendChild(template);
+
+ assert_not_equals(template.content.ownerDocument, doc, 'Wrong template content owner');
+
+}, 'Test the template contents owner document when enclosing document has '
+ + 'no browsing content. Template element is created by createElement()');
+
+
+
+test(function() {
+ var doc = newHTMLDocument();
+
+ doc.body.innerHTML = '<template><div>some text</div></template>';
+
+ var template = doc.querySelector('template');
+
+ assert_not_equals(template.content.ownerDocument, doc, 'Wrong template content owner');
+
+}, 'Test the template contents owner document when enclosing document has '
+ + 'no browsing content. Template element is created by innerHTML');
+
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/definitions/template-contents-owner-test-002.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/definitions/template-contents-owner-test-002.html
new file mode 100644
index 00000000000..49cfc8d0673
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/definitions/template-contents-owner-test-002.html
@@ -0,0 +1,69 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>HTML Templates: The template contents owner document (there's browsing context)</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="assert" content="If template's enclosing document has browsing context, then templates content owner must be a new Document node without browsing context">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#definitions">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src='../testcommon.js'></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script type="text/javascript">
+
+
+testInIFrame(null, function(context) {
+ var doc = context.iframes[0].contentDocument;
+ var template = doc.createElement('template');
+
+ var div = doc.createElement('div');
+ div.setAttribute('id', 'div1');
+ div.innerText = 'Some text';
+
+ template.appendChild(div);
+
+ doc.body.appendChild(template);
+
+ // doc has browsing context. There should be another document as a template
+ // content owner
+ assert_not_equals(template.content.ownerDocument, doc, 'Wrong template owner document');
+
+}, 'The template contents owner document must be different from template owner document,' +
+ ' which has browsing context. Template element is created by createElement()');
+
+
+
+testInIFrame(null, function(context) {
+ var doc = context.iframes[0].contentDocument;
+
+ doc.body.innerHTML = '<template><div>some text</div></template>';
+
+ var template = doc.querySelector('template');
+
+ // doc has browsing context. There should be another document as a template
+ // content owner
+ assert_not_equals(template.content.ownerDocument, doc, 'Wrong template owner document');
+
+}, 'The template contents owner document must be different from template owner document,' +
+ ' which has browsing context. Template element is created via innerHTML');
+
+
+
+testInIFrame('../resources/template-contents.html', function(context) {
+ var doc = context.iframes[0].contentDocument;
+
+ var template = doc.querySelector('template');
+
+ // doc has browsing context. There should be another document as a template
+ // content owner
+ assert_not_equals(template.content.ownerDocument, doc, 'Wrong template owner document');
+
+}, 'The template contents owner document must be different from template owner document,' +
+ ' which has browsing context. Template element is created by HTML parser');
+
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/definitions/template-contents.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/definitions/template-contents.html
new file mode 100644
index 00000000000..a69c9c52dc2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/definitions/template-contents.html
@@ -0,0 +1,173 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>HTML Templates: The template contents is a DocumentFragment</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="assert" content="The template contents must be a DocumentFragment">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#definitions">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src='../testcommon.js'></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script type="text/javascript">
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var template = doc.createElement('template');
+
+ doc.body.appendChild(template);
+
+ assert_equals(template.content.nodeType, Node.DOCUMENT_FRAGMENT_NODE,
+ 'Template content should be a DocumentFragment');
+
+ assert_class_string(template.content, 'DocumentFragment',
+ 'Template content class should be a DocumentFragment');
+
+}, 'The template contents must be a DocumentFragment (empty template)');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var template = doc.createElement('template');
+
+ template.innerHTML = '<div>This is a div</div><span>This is a span</span>';
+
+ doc.body.appendChild(template);
+
+ assert_equals(template.content.nodeType, Node.DOCUMENT_FRAGMENT_NODE,
+ 'Template content should be a DocumentFragment');
+
+ assert_class_string(template.content, 'DocumentFragment',
+ 'Template content class should be a DocumentFragment');
+
+}, 'The template contents must be a DocumentFragment (non empty template)');
+
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var template = doc.createElement('template');
+
+ template.innerHTML = '<div>This is a div</div>';
+
+ doc.body.appendChild(template);
+
+ assert_equals(template.content.nodeType, Node.DOCUMENT_FRAGMENT_NODE,
+ 'Template content should be a documentFragment');
+
+}, 'The template contents must be a DocumentFragment (non empty template '
+ + 'containing div which is an Element instance)');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var template = doc.createElement('template');
+
+ template.innerHTML = 'Some text';
+
+ doc.body.appendChild(template);
+
+ assert_equals(template.content.nodeType, Node.DOCUMENT_FRAGMENT_NODE,
+ 'Template content should be a documentFragment');
+
+ assert_class_string(template.content, 'DocumentFragment',
+ 'Template content class should be a DocumentFragment');
+
+}, 'The template contents must be a DocumentFragment (not empty template '
+ + 'containing text node)');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var template = doc.createElement('template');
+
+ template.innerHTML = '<template id="t2">Some text</template>';
+
+ doc.body.appendChild(template);
+
+ assert_equals(template.content.nodeType, Node.DOCUMENT_FRAGMENT_NODE,
+ 'Template content should be a documentFragment');
+ assert_class_string(template.content, 'DocumentFragment',
+ 'Template content class should be a DocumentFragment');
+
+ var nestedTemplate = template.content.querySelector("#t2");
+ assert_equals(nestedTemplate.content.nodeType, Node.DOCUMENT_FRAGMENT_NODE,
+ 'Nested template content should be a documentFragment');
+
+ assert_class_string(nestedTemplate.content, 'DocumentFragment',
+ 'Nested template content class should be a DocumentFragment');
+
+
+}, 'The template contents must be a DocumentFragment (nested template '
+ + 'containing a text node)');
+
+
+testInIFrame('../resources/template-contents-empty.html', function(context) {
+ var doc = context.iframes[0].contentDocument;
+
+ var template = doc.querySelector('template');
+
+ assert_equals(template.content.nodeType, Node.DOCUMENT_FRAGMENT_NODE,
+ 'Template content should be a documentFragment');
+ assert_class_string(template.content, 'DocumentFragment',
+ 'Template content class should be a DocumentFragment');
+
+
+}, 'The template contents must be a DocumentFragment (the empty template tag '
+ + 'inside HTML file loaded in iframe)');
+
+
+testInIFrame('../resources/template-contents.html', function(context) {
+ var doc = context.iframes[0].contentDocument;
+
+ var template = doc.querySelector('template');
+
+ assert_equals(template.content.nodeType, Node.DOCUMENT_FRAGMENT_NODE,
+ 'Template content should be a documentFragment');
+ assert_class_string(template.content, 'DocumentFragment',
+ 'Template content class should be a DocumentFragment');
+
+}, 'The template contents must be a DocumentFragment (non empty template '
+ + 'tag inside HTML file loaded in iframe)');
+
+
+testInIFrame('../resources/template-contents-text.html', function(context) {
+ var doc = context.iframes[0].contentDocument;
+
+ var template = doc.querySelector('template');
+
+ assert_equals(template.content.nodeType, Node.DOCUMENT_FRAGMENT_NODE,
+ 'Template content should be a documentFragment');
+ assert_class_string(template.content, 'DocumentFragment',
+ 'Template content class should be a DocumentFragment');
+
+}, 'The template contents must be a DocumentFragment (the template tag '
+ + 'with some text inside HTML file loaded in iframe)');
+
+
+testInIFrame('../resources/template-contents-nested.html', function(context) {
+ var doc = context.iframes[0].contentDocument;
+
+ var template = doc.querySelector('template');
+
+ assert_equals(template.content.nodeType, Node.DOCUMENT_FRAGMENT_NODE,
+ 'Template content should be a documentFragment');
+ assert_class_string(template.content, 'DocumentFragment',
+ 'Template content class should be a DocumentFragment');
+
+ var nestedTemplate = template.content.querySelector("template");
+
+ assert_equals(nestedTemplate.content.nodeType, Node.DOCUMENT_FRAGMENT_NODE,
+ 'Nested template content should be a documentFragment');
+ assert_class_string(nestedTemplate.content, 'DocumentFragment',
+ 'Nested template content class should be a DocumentFragment');
+
+}, 'The template contents must be a DocumentFragment (the template tag '
+ + 'with nested template tag inside HTML file loaded in iframe)');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/innerhtml-on-templates/innerhtml.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/innerhtml-on-templates/innerhtml.html
new file mode 100644
index 00000000000..7ae9c132591
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/innerhtml-on-templates/innerhtml.html
@@ -0,0 +1,87 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>HTML Templates: innerHTML of template element replaces all referenced by the content attribute</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="author" title="Aleksei Yu. Semenov" href="a.semenov@unipro.ru">
+<meta name="assert" content="innerHTML of template element replaces all referenced by the content attribute">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#innerhtml-on-templates">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src='../testcommon.js'></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script type="text/javascript">
+
+test(function () {
+ var doc = newHTMLDocument();
+ var template = doc.createElement('template');
+
+ var div1 = doc.createElement('div');
+ div1.setAttribute('id', 'div1');
+ template.content.appendChild(div1);
+
+ assert_not_equals(template.content.querySelector('#div1'), null,
+ 'Element should present in template content');
+
+ template.innerHTML = '<div id="div2"></div>';
+
+ assert_equals(template.content.querySelector('#div1'), null,
+ 'Template content should be replaced by innerHTML');
+ assert_not_equals(template.content.querySelector('#div2'), null,
+ 'Element should present in template content');
+
+}, 'innerHTML of template element replaces all referenced by the content attribute');
+
+
+
+test(function () {
+ var doc = newHTMLDocument();
+ var template = doc.createElement('template');
+ var nestedTemplate = doc.createElement('template');
+
+ template.content.appendChild(nestedTemplate);
+
+ var div1 = doc.createElement('div');
+ div1.setAttribute('id', 'div1');
+ nestedTemplate.content.appendChild(div1);
+
+ assert_not_equals(nestedTemplate.content.querySelector('#div1'), null,
+ 'Element should present in template content');
+
+ nestedTemplate.innerHTML = '<div id="div2"></div>';
+
+ assert_equals(nestedTemplate.content.querySelector('#div1'), null,
+ 'Template content should be replaced by innerHTML');
+ assert_not_equals(nestedTemplate.content.querySelector('#div2'), null,
+ 'Element should present in template content');
+
+}, 'innerHTML of template element replaces all referenced by the content attribute. '
+ + 'Test nested template');
+
+
+testInIFrame('../resources/template-contents.html', function(context) {
+ var doc = context.iframes[0].contentDocument;
+
+ var template = doc.querySelector('template');
+ assert_not_equals(template.content.querySelector('div'), null,
+ 'Div element should present in template content');
+
+ template.innerHTML = '<span>span internals</span>';
+
+ assert_equals(template.content.querySelector('div'), null,
+ 'div element should be replaced by span in template content');
+
+ assert_not_equals(template.content.querySelector('span'), null,
+ 'span element should present in template content');
+
+
+}, 'innerHTML of template element replaces all referenced by the content attribute. '
+ + 'Test loading of HTML document from a file');
+
+
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/end-template-tag-in-body.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/end-template-tag-in-body.html
new file mode 100644
index 00000000000..2cb149853ff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/end-template-tag-in-body.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>The file contains several &lt;/template&gt; tag in HTML body without start one</title>
+ <link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+</head>
+<body>
+ </template>
+ <div>The file contains several &lt;/template&gt; tag in HTML body without start one</div>
+ </template></template>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/end-template-tag-in-head.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/end-template-tag-in-head.html
new file mode 100644
index 00000000000..02d0c7be65a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/end-template-tag-in-head.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+ </template>
+ <title>The file contains several &lt;/template&gt; tag in HTML head without start one</title>
+ </template></template>
+ <link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+ </template>
+</head>
+<body>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/frameset-end-tag.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/frameset-end-tag.html
new file mode 100644
index 00000000000..b84d55595f7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/frameset-end-tag.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>The file contains frameset with the template and frameset end tag in it</title>
+ <link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+</head>
+<frameset>
+ <template></frameset></template>
+</frameset>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/head-template-contents-div-no-end-tag.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/head-template-contents-div-no-end-tag.html
new file mode 100644
index 00000000000..e4e45bcea5a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/head-template-contents-div-no-end-tag.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>The file contains template element with open div tag, but without end div tag, in the head</title>
+ <link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+ <template>
+ <div>Hello, template
+ </template>
+</head>
+<body>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/head-template-contents-table-no-end-tag.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/head-template-contents-table-no-end-tag.html
new file mode 100644
index 00000000000..9db2b4af062
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/head-template-contents-table-no-end-tag.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>The file contains template element with open table, tr, td tags, but without end td, tr, table tags, in the head</title>
+ <link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+ <template>
+ <table>
+ <tr>
+ <td>Hello, cell one!
+ </template>
+</head>
+<body>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/html-start-tag.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/html-start-tag.html
new file mode 100644
index 00000000000..0de652cf364
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/html-start-tag.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html tabindex="5">
+<head>
+ <title>The file contains html root element with attributes and some in the body</title>
+ <link rel="author" title="Sergey G. Grekhovv" href="mailto:sgrekhov@unipro.ru">
+</head>
+<body>
+<template id="tmpl"><html class="htmlClass"></html></template><html id="htmlId" tabindex="5">
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-child-nodes-div.xhtml b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-child-nodes-div.xhtml
new file mode 100644
index 00000000000..327119f142a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-child-nodes-div.xhtml
@@ -0,0 +1,14 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>Template tag with children div tags inside</title>
+ <link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru"/>
+</head>
+<body>
+ <p>Template tag with div tags inside</p>
+ <template>
+ <div>This is div inside template</div>
+ <div>This is another div inside template</div>
+ </template>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-child-nodes-nested.xhtml b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-child-nodes-nested.xhtml
new file mode 100644
index 00000000000..acf220faf5a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-child-nodes-nested.xhtml
@@ -0,0 +1,16 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>Template tag with children div tags inside another template tag</title>
+ <link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru"/>
+</head>
+<body>
+ <p>Template tag with children div tags inside another template tag</p>
+ <template>
+ <template>
+ <div>This is div inside template</div>
+ <div>This is another div inside template</div>
+ </template>
+ </template>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-contents-attribute.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-contents-attribute.html
new file mode 100644
index 00000000000..b9dd5f47a8b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-contents-attribute.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Empty template tag with attribute content</title>
+ <link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<head>
+<body>
+ <template content='some text'></template>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-contents-body.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-contents-body.html
new file mode 100644
index 00000000000..a1f246fd639
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-contents-body.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>BODY tag inside template</title>
+ <link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<head>
+<body>
+ <template><body></body></template>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-contents-div-no-end-tag.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-contents-div-no-end-tag.html
new file mode 100644
index 00000000000..304acf30256
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-contents-div-no-end-tag.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Div tag inside template tag</title>
+ <link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+</head>
+<body>
+ <template>
+ <div>Hello, template
+ </template>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-contents-empty.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-contents-empty.html
new file mode 100644
index 00000000000..f1a539cc08e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-contents-empty.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Empty template tag</title>
+ <link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<head>
+<body>
+ <template>
+ </template>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-contents-frameset.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-contents-frameset.html
new file mode 100644
index 00000000000..4331367df3f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-contents-frameset.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>FRAMESET tag inside template</title>
+ <link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<head>
+<body>
+ <template><frameset></frameset></template>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-contents-head.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-contents-head.html
new file mode 100644
index 00000000000..1e3a337e8d9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-contents-head.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>HEAD tag inside template</title>
+ <link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<head>
+<body>
+ <template><head></head></template>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-contents-html.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-contents-html.html
new file mode 100644
index 00000000000..5dd3a28e6a6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-contents-html.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>HTML tag inside template</title>
+ <link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<head>
+<body>
+ <template><html></html></template>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-contents-nested.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-contents-nested.html
new file mode 100644
index 00000000000..dc2dc6f15f7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-contents-nested.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+ <title>Contains second template tag inside template tag</title>
+ <link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<body>
+ <template>
+ <template>
+ <div>Inside nested template</div>
+ </template>
+ </template>
+</body>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-contents-table-no-end-tag.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-contents-table-no-end-tag.html
new file mode 100644
index 00000000000..4639b4dc8e4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-contents-table-no-end-tag.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>The file contains template element with open table, tr, td tags, without end td, tr, table tags</title>
+ <link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+</head>
+<body>
+ <template>
+ <table>
+ <tr>
+ <td>Hello, cell one!
+ </template>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-contents-text.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-contents-text.html
new file mode 100644
index 00000000000..a401848efcc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-contents-text.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Some text inside template tag</title>
+ <link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+</head>
+<body>
+ <template>Some text</template>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-contents.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-contents.html
new file mode 100644
index 00000000000..07256c06a31
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-contents.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Div tag inside template tag</title>
+ <link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+</head>
+<body>
+ <template>
+ <div>Hello, template</div>
+ </template>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-descendant-body.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-descendant-body.html
new file mode 100644
index 00000000000..d64848c8db8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-descendant-body.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Div tag inside template tag</title>
+ <link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+</head>
+<body>
+ <template>
+ <div>Hello, template</div>
+ </template>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-descendant-frameset.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-descendant-frameset.html
new file mode 100644
index 00000000000..4801178454e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-descendant-frameset.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Template tag inside frameset</title>
+ <link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+</head>
+<frameset>
+ <template>
+ <div>Hello, template</div>
+ </template>
+</frameset>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-descendant-head.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-descendant-head.html
new file mode 100644
index 00000000000..6bab00ea99e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/template-descendant-head.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Template tag inside head</title>
+ <link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+ <template>
+ <div>Hello, template</div>
+ </template>
+</head>
+<body>
+ Nothing interesting here
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/two-templates.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/two-templates.html
new file mode 100644
index 00000000000..f6e9ab58e80
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/resources/two-templates.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>The file contains two template elements</title>
+ <link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+</head>
+<body>
+ <template id="template1">
+ <div>Hello, template</div>
+ </template>
+
+ <template id="template2">
+ <div>Hello, from second template</div>
+ </template>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/serializing-html-templates/outerhtml.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/serializing-html-templates/outerhtml.html
new file mode 100644
index 00000000000..992152a7d0f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/serializing-html-templates/outerhtml.html
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>HTML Templates: serialize template contents instead of template element</title>
+<meta name="author" title="Aleksei Yu. Semenov" href="a.semenov@unipro.ru">
+<meta name="assert" content="template contents should be serialized instead of template element if serializing template element">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#serializing-html-templates">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src='../testcommon.js'></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script type="text/javascript">
+
+test(function () {
+ var doc = newHTMLDocument();
+ var template = doc.createElement('template');
+
+ var div = doc.createElement('div');
+ div.setAttribute('id', 'div1');
+ div.innerHTML = 'some text';
+ template.content.appendChild(div);
+
+ assert_equals(template.outerHTML, '<template><div id="div1">some text</div></template>',
+ 'template element is serialized incorrectly');
+
+}, 'Template contents should be serialized instead of template element if serializing template element');
+
+
+
+test(function () {
+ var doc = newHTMLDocument();
+ var template = doc.createElement('template');
+ var nestedTemplate = doc.createElement('template');
+
+ template.content.appendChild(nestedTemplate);
+
+ var div = doc.createElement('div');
+ div.setAttribute('id', 'div1');
+ div.innerHTML = 'some text';
+ nestedTemplate.content.appendChild(div);
+
+ assert_equals(template.outerHTML, '<template><template><div id="div1">some text</div></template></template>',
+ 'template element is serialized incorrectly');
+
+
+}, 'Template contents should be serialized instead of template element if serializing template element. '
+ + 'Test nested template');
+
+
+test(function () {
+ var doc = newHTMLDocument();
+ var template = doc.createElement('template');
+
+ var div = doc.createElement('div');
+ div.setAttribute('id', 'div1');
+ div.innerHTML = 'some text';
+ template.content.appendChild(div);
+ doc.body.appendChild(template);
+
+ assert_equals(doc.documentElement.outerHTML, '<html><head><title>Test Document</title></head><body><template><div id="div1">some text</div></template></body></html>',
+ 'template element is serialized incorrectly');
+
+}, 'Template contents should be serialized instead of template element if serializing template element. '
+ + 'Test serializing whole document');
+
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/template-element/content-attribute.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/template-element/content-attribute.html
new file mode 100644
index 00000000000..3541b385b96
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/template-element/content-attribute.html
@@ -0,0 +1,115 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>HTML Templates: Content attribute of template element is read-only</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<meta name="assert" content="Content attribute of template element is read-only">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#template-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src='../testcommon.js'></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script type="text/javascript">
+
+test(function() {
+ var doc = newHTMLDocument();
+ var template = doc.createElement('template');
+
+ assert_readonly(template, 'content',
+ 'Content attribute of template element should be read-only');
+
+}, 'Content attribute of template element is read-only. ' +
+ 'Test empty template');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var template = doc.createElement('template');
+ var el1 = doc.createElement('div');
+ var el2 = doc.createElement('span');
+ el1.appendChild(el2);
+
+ template.content.appendChild(el1);
+
+ assert_readonly(template, 'content',
+ 'Content attribute of template element should be read-only');
+
+}, 'Content attribute of template element is read-only. ' +
+ 'Test not empty template populated by appendchild()');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ doc.body.innerHTML = '<template>Text<div>DIV</div></template>';
+
+ var template = doc.querySelector('template');
+
+ assert_readonly(template, 'content',
+ 'Content attribute of template element should be read-only');
+
+}, 'Content attribute of template element is read-only. ' +
+ 'Test not empty template populated by innerHTML');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ doc.body.innerHTML = '<template id="template1" content="Some text as a content"></template>';
+
+ var template = doc.querySelector('#template1');
+
+ assert_readonly(template, 'content',
+ 'Content attribute of template element should be read-only');
+
+}, 'Content attribute of template element is read-only. ' +
+ 'Test that custom content attribute named \'content\' doesn\'t ' +
+ 'make content IDL attribute writable');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ doc.body.innerHTML = '<template id="template1" content="<div id=div1>Div content</div>"></template>';
+
+ var template = doc.querySelector('#template1');
+
+ assert_readonly(template, 'content',
+ 'Content attribute of template element should be read-only');
+
+ assert_equals(template.content.childNodes.length, 0,
+ 'Content attribute of template element should be read-only');
+
+}, 'Content attribute of template element is read-only. ' +
+ 'Test that custom content attribute named \'content\' doesn\'t ' +
+ 'affect content IDL attribute');
+
+
+testInIFrame('../resources/template-contents-attribute.html', function(context) {
+ var doc = context.iframes[0].contentDocument;
+
+ var template = doc.body.querySelector('template');
+
+ assert_readonly(template, 'content',
+ 'Content attribute of template element should be read-only');
+
+}, 'Content attribute of template element is read-only. '
+ + 'Text value of content attribute of template tag should be ignored, '
+ + 'when loading document from a file');
+
+
+testInIFrame('../resources/template-contents.html', function(context) {
+ var doc = context.iframes[0].contentDocument;
+
+ var template = doc.body.querySelector('template');
+
+ assert_readonly(template, 'content',
+ 'Content attribute of template element should be read-only');
+
+}, 'Content attribute of template element is read-only. '
+ + 'Test content attribute of a document loaded from a file');
+
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/template-element/node-document-changes.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/template-element/node-document-changes.html
new file mode 100644
index 00000000000..b44f4e611b1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/template-element/node-document-changes.html
@@ -0,0 +1,200 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>HTML Templates: When node's document changes its owner document should be changed</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<meta name="assert" content="When a template element's node document changes, the template element's content DocumentFragment must be adopted into the new node document's template contents owner document">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#template-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src='../testcommon.js'></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script type="text/javascript">
+
+
+test(function() {
+ var doc1 = newHTMLDocument();
+ var template = doc1.createElement('template');
+
+ assert_equals(template.ownerDocument, doc1, 'Wrong template node owner document');
+ assert_not_equals(template.content.ownerDocument, doc1,
+ 'Wrong template content owner document');
+
+ var doc2 = newHTMLDocument();
+ var template2 = doc2.createElement('template');
+ doc2.body.appendChild(template);
+
+ assert_equals(template.ownerDocument, template2.ownerDocument,
+ 'Template node owner document should be changed');
+ assert_equals(template.content.ownerDocument, template2.content.ownerDocument,
+ 'Template content owner document should be changed');
+
+}, 'Changing of template element\'s node document. ' +
+ 'Test that ownerDocument of an empty template and its content changes');
+
+
+test(function() {
+ var doc1 = newHTMLDocument();
+ doc1.body.innerHTML = '<template id="tmpl"><div>Div content</div> And some more text</template>';
+
+ var template = doc1.querySelector('#tmpl');
+
+ assert_equals(template.ownerDocument, doc1,
+ 'Wrong template node owner document');
+ assert_not_equals(template.content.ownerDocument, doc1,
+ 'Wrong template content owner document');
+
+ var doc2 = newHTMLDocument();
+ var template2 = doc2.createElement('template');
+ doc2.body.appendChild(template);
+
+ assert_equals(template.ownerDocument, template2.ownerDocument,
+ 'Template node owner document should be changed');
+ assert_equals(template.content.ownerDocument, template2.content.ownerDocument,
+ 'Template content owner document should be changed');
+
+ assert_equals(template.content.querySelector('div').ownerDocument,
+ template2.content.ownerDocument,
+ 'Template content descendants owner document should be changed');
+
+}, 'Changing of template element\'s node document. ' +
+ 'Test that ownerDocument of a not empty template and its content changes');
+
+
+test(function() {
+ var doc1 = newHTMLDocument();
+ doc1.body.innerHTML = ''
+ + '<template id="tmpl"><div>Div content</div> And some more text'
+ + '<template id="tmpl2"><div>Template content</div></template>'
+ + '</template>';
+
+ var template = doc1.querySelector('#tmpl');
+
+ assert_equals(template.ownerDocument, doc1, 'Wrong template node owner document');
+ assert_not_equals(template.content.ownerDocument, doc1,
+ 'Wrong template content owner document');
+
+ var nestedTemplate = template.content.querySelector('#tmpl2');
+
+ assert_equals(nestedTemplate.ownerDocument, template.content.ownerDocument,
+ 'Wrong nested template node owner document');
+ assert_equals(nestedTemplate.content.ownerDocument, template.content.ownerDocument,
+ 'Wrong nested template content owner document');
+
+ var doc2 = newHTMLDocument();
+ var template2 = doc2.createElement('template');
+ doc2.body.appendChild(template);
+
+ assert_equals(template.ownerDocument, template2.ownerDocument,
+ 'Template node owner document should be changed');
+ assert_equals(template.content.ownerDocument, template2.content.ownerDocument,
+ 'Template content owner document should be changed');
+ assert_equals(template.content.querySelector('div').ownerDocument,
+ template2.content.ownerDocument,
+ 'Template content descendants owner document should be changed');
+
+ assert_equals(nestedTemplate.ownerDocument,
+ template2.content.ownerDocument,
+ 'Nested template node owner document should be changed');
+ assert_equals(nestedTemplate.content.ownerDocument,
+ template2.content.ownerDocument,
+ 'Nested template content owner document should be changed');
+ assert_equals(nestedTemplate.content.querySelector('div').ownerDocument,
+ template2.content.ownerDocument,
+ 'Owner document of the nested template content descendants should be changed');
+
+}, 'Changing of template element\'s node document. ' +
+ 'Test that ownerDocument of nested template and its content changes');
+
+
+testInIFrame('../resources/template-contents.html', function(context) {
+ var doc1 = context.iframes[0].contentDocument;
+
+ var template = doc1.body.querySelector('template');
+
+ var doc2 = newHTMLDocument();
+ var template2 = doc2.createElement('template');
+ doc2.body.appendChild(template);
+
+ assert_equals(template.ownerDocument, template2.ownerDocument,
+ 'Template node owner document should be changed');
+ assert_equals(template.content.ownerDocument,
+ template2.content.ownerDocument,
+ 'Template content owner document should be changed');
+ assert_equals(template.content.querySelector('div').ownerDocument,
+ template2.content.ownerDocument,
+ 'Template content descendants owner document should be changed');
+
+}, 'Changing of template element\'s node document. ' +
+ 'Test document loaded from a file');
+
+
+testInIFrame('../resources/template-contents.html', function(context) {
+ var doc1 = context.iframes[0].contentDocument;
+
+ var doc2 = newHTMLDocument();
+ var template = doc2.createElement('template');
+ var div = doc2.createElement('div');
+ template.content.appendChild(div);
+
+ doc1.body.appendChild(template);
+
+ assert_not_equals(template.ownerDocument, doc2,
+ 'Template node owner document should be changed');
+ assert_not_equals(template.content.ownerDocument, doc2,
+ 'Template content owner document should be changed');
+ assert_not_equals(div.ownerDocument, doc2,
+ 'Template content descendants owner document should be changed');
+
+ assert_equals(template.ownerDocument, doc1,
+ 'Template node owner document should be changed');
+ // doc1 has browsing context so it cannot be template.content.ownerDocument
+ assert_not_equals(template.content.ownerDocument, doc1,
+ 'Template content owner document should be a new document');
+ assert_equals(div.ownerDocument, template.content.ownerDocument,
+ 'Template content descendants owner document should be ' +
+ 'template content document owner');
+
+}, 'Changing of template element\'s node document. ' +
+ 'Adobt template element into a document that has a browsing context');
+
+
+testInIFrame('../resources/template-contents.html', function(context) {
+ var doc1 = context.iframes[0].contentDocument;
+
+ var template = doc1.querySelector('template');
+ var div = template.content.querySelector('div');
+ var templateContentOwner = template.content.ownerDocument;
+
+ var doc2 = document;
+
+ doc2.body.appendChild(template);
+
+
+ assert_not_equals(template.ownerDocument, doc1,
+ 'Template node owner document should be changed');
+ assert_not_equals(template.content.ownerDocument, templateContentOwner,
+ 'Template content owner document should be changed');
+ assert_not_equals(div.ownerDocument, templateContentOwner,
+ 'Template content descendants owner document should be changed');
+
+ assert_equals(template.ownerDocument, doc2,
+ 'Template node owner document should be changed');
+ // doc2 has browsing context, so it cannot be template.content.ownerDocument
+ assert_not_equals(template.content.ownerDocument, doc2,
+ 'Template content owner document should be a new document');
+ assert_equals(div.ownerDocument, template.content.ownerDocument,
+ 'Template content descendants owner document should be ' +
+ 'template content document owner');
+
+}, 'Changing of template element\'s node document. ' +
+ 'Test the case when both old and new owner documents of template element ' +
+ 'have browsing context');
+
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/template-element/template-as-a-descendant.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/template-element/template-as-a-descendant.html
new file mode 100644
index 00000000000..42ba33e6a07
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/template-element/template-as-a-descendant.html
@@ -0,0 +1,115 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>HTML Templates: Template element as a descendant of the body element.</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<meta name="assert" content="Template element can be a descendant of the body element">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#template-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src='../testcommon.js'></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script type="text/javascript">
+
+function templateIsAChild(element) {
+ element.innerHTML = '<template>some text</template>';
+
+ assert_not_equals(element.querySelector('template'), null,
+ 'Template element should be a descendant of the ' + element.tagName + ' element');
+}
+
+function templateIsAnIndirectChild(element) {
+ element.innerHTML = '<div><template>some text</template></div>';
+
+ assert_not_equals(element.querySelector('template'), null,
+ 'Template element should be a descendant of the ' + element.tagName + ' element');
+}
+
+function templateIsAnAppendedChild(doc, element) {
+ var template = doc.createElement('template');
+
+ element.appendChild(template);
+
+ assert_not_equals(element.querySelector('template'), null,
+ 'Template element should be a descendant of the ' + element.tagName + ' element');
+}
+
+function templateIsAnAppendedIndirectChild(doc, element) {
+ var template = doc.createElement('template');
+ var div = doc.createElement('div');
+ div.appendChild(template);
+
+ element.appendChild(div);
+
+ assert_not_equals(element.querySelector('template'), null,
+ 'Template element should be a descendant of the ' + element.tagName + ' element');
+}
+
+var doc = newHTMLDocument();
+var frameset = doc.createElement('frameset');
+
+var parameters = [['Template element as a descendant of the BODY element. ' +
+ 'Template element is created by innerHTML',
+ doc.body],
+ ['Template element as a descendant of the HEAD element. ' +
+ 'Template element is created by innerHTML',
+ doc.head],
+ ['Template element as a descendant of the FRAMESET element. ' +
+ 'Template element is created by innerHTML',
+ frameset]
+ ];
+generate_tests(templateIsAChild, parameters,
+ 'Template element as a descendant of the HEAD, BODY and FRAMESET elements');
+
+
+
+parameters = [['Template element as an indirect descendant of the BODY element. ' +
+ 'Template element is created by innerHTML',
+ doc.body],
+ ['Template element as an indirect descendant of the HEAD element. ' +
+ 'Template element is created by innerHTML',
+ doc.head],
+ ['Template element as an indirect descendant of the FRAMESET element. ' +
+ 'Template element is created by innerHTML',
+ frameset]
+ ];
+generate_tests(templateIsAnIndirectChild, parameters,
+ 'Template element as an indirect descendant of the HEAD, BODY and FRAMESET elements');
+
+
+
+parameters = [['Template element as a descendant of the BODY element. ' +
+ 'Template element is appended by appendChild()',
+ doc, doc.body],
+ ['Template element as a descendant of the HEAD element. ' +
+ 'Template element is appended by appendChild()',
+ doc, doc.head],
+ ['Template element as a descendant of the FRAMESET element. ' +
+ 'Template element is appended by appendChild()',
+ doc, frameset]
+ ];
+generate_tests(templateIsAnAppendedChild, parameters,
+ 'Template element as a descendant of the HEAD, BODY and FRAMESET elements');
+
+
+
+parameters = [['Template element as an indirect descendant of the BODY element. ' +
+ 'Template element is appended by appendChild()',
+ doc, doc.body],
+ ['Template element as an indirect descendant of the HEAD element. ' +
+ 'Template element is appended by appendChild()',
+ doc, doc.head],
+ ['Template element as an indirect descendant of the FRAMESET element. ' +
+ 'Template element is appended by appendChild()',
+ doc, frameset]
+ ];
+generate_tests(templateIsAnAppendedIndirectChild, parameters,
+ 'Template element as a descendant of the HEAD, BODY and FRAMESET elements');
+
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/template-element/template-content-node-document.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/template-element/template-content-node-document.html
new file mode 100644
index 00000000000..9aa69ce1b1f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/template-element/template-content-node-document.html
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>HTML Templates: Node document of the template content attribute must be template contents owner</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<meta name="assert" content="Node document of the template content attribute must be template contents owner">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#template-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src='../testcommon.js'></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script type="text/javascript">
+
+test(function() {
+ var doc = newHTMLDocument();
+ var template = doc.createElement('template');
+ var nestedTemplate = doc.createElement('template');
+ template.appendChild(nestedTemplate);
+
+ assert_equals(nestedTemplate.content.ownerDocument, template.content.ownerDocument,
+ 'Wrong node document of the template content attribute');
+
+}, 'Node document of the template content attribute must be template contents owner. ' +
+ 'Nested template element created by createElement');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ doc.body.innerHTML = '<template><template></template></template>';
+ var template = doc.querySelector('template');
+ var nestedTemplate = template.content.querySelector('template');
+
+ assert_equals(nestedTemplate.content.ownerDocument, template.content.ownerDocument,
+ 'Wrong node document of the template content attribute');
+
+}, 'Node document of the template content attribute must be template contents owner. ' +
+ 'Nested template element created by innerHTML');
+
+testInIFrame('../resources/two-templates.html', function(context) {
+ var doc = context.iframes[0].contentDocument;
+
+ var template1 = doc.querySelector('#template1');
+ var template2 = doc.querySelector('#template2');
+
+ // when there is a browsing context, template contents owner is only accessible via template.content.ownerDocument
+ // because template contents owner is bounded to document
+ // verify that multiple templates share the same instance of template contents owner
+
+ assert_equals(template1.content.ownerDocument, template2.content.ownerDocument,
+ 'Wrong node document of the template content attribute');
+}, 'Node document of the template content attribute must be template contents owner. ' +
+ 'Load HTML file with multiple template elements');
+
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/template-element/template-content.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/template-element/template-content.html
new file mode 100644
index 00000000000..fca52730bb8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/template-element/template-content.html
@@ -0,0 +1,78 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>HTML Templates: HTML elements in template content</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="author" title="Aleksei Yu. Semenov" href="a.semenov@unipro.ru">
+<meta name="assert" content="Template may contain any element, except the html element, the head element, the body element, or the frameset element">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#template-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src='../testcommon.js'></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script type="text/javascript">
+
+var parameters = [];
+
+HTML5_ELEMENTS.forEach(function(value) {
+ if (value !== 'body' && value !== 'html' && value !== 'head' && value !== 'frameset') {
+
+ var doc = newHTMLDocument();
+ var template = doc.createElement('template');
+ var element = doc.createElement(value);
+ template.content.appendChild(element);
+ var valueToTest = template.content.querySelector(value);
+
+ doc.body.appendChild(template);
+
+ parameters.push([
+ 'Template may contain ' + value + ' element',
+ valueToTest,
+ null
+ ]);
+ }
+});
+
+generate_tests(assert_not_equals, parameters,
+ 'Template may contain any element, except the html element, '
+ + 'the head element, the body element, or the frameset element');
+
+
+
+
+var parameters = [];
+
+HTML5_ELEMENTS.forEach(function(value) {
+ if (value !== 'body' && value !== 'html' && value !== 'head' && value !== 'frameset') {
+
+ var doc = newHTMLDocument();
+
+ if (isVoidElement(value)) {
+ doc.body.innerHTML = '<template><' + value + '/></template>';
+ } else {
+ doc.body.innerHTML = '<template><' + value + '></' + value + '></template>';
+ }
+
+ var template = doc.querySelector('template');
+ var element = template.content.querySelector(value);
+
+ parameters.push([
+ 'Template may contain ' + value + ' element. '
+ +'The template element and contents are added via body.innerHTML',
+ element,
+ null
+ ]);
+ }
+});
+
+generate_tests(assert_not_equals, parameters,
+ 'Template may contain any element, except the html element, '
+ + 'the head element, the body element, or the frameset element. '
+ +'The template element and contents are added via body.innerHTML');
+
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/template-element/template-descendant-body.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/template-element/template-descendant-body.html
new file mode 100644
index 00000000000..c45931cdae3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/template-element/template-descendant-body.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>HTML Templates: Template element as a descendant of the body element.</title>
+<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<meta name="assert" content="Template element can be a descendant of the body element">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#template-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src='../testcommon.js'></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script type="text/javascript">
+
+testInIFrame('../resources/template-contents.html', function(ctx) {
+ var doc = ctx.iframes[0].contentDocument;
+
+ assert_not_equals(doc.body.querySelector('template'), null,
+ 'Template element should be a descendant of the body element');
+
+}, 'Template element as a descendant of the body element. Test loading from a file');
+
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/template-element/template-descendant-frameset.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/template-element/template-descendant-frameset.html
new file mode 100644
index 00000000000..f3dbd7ebf67
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/template-element/template-descendant-frameset.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>HTML Templates: Template element as a descendant of the frameset element.</title>
+<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<meta name="assert" content="Template element can be a descendant of the frameset element">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#template-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src='../testcommon.js'></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script type="text/javascript">
+
+testInIFrame('../resources/template-descendant-frameset.html', function(context) {
+ var doc = context.iframes[0].contentDocument;
+
+ var frameset = doc.querySelector('frameset');
+
+ assert_not_equals(frameset.querySelector('template'), null,
+ 'Template element should be a descendant of the frameset element');
+
+}, 'Template element as a descendant of the frameset element. Test loading from a file');
+
+
+testInIFrame('../resources/template-descendant-frameset.html', function(context) {
+ var doc = context.iframes[0].contentDocument;
+
+ var frameset = doc.querySelector('frameset');
+
+ frameset.innerHTML = '';
+ assert_equals(doc.querySelector('template'), null,
+ 'Initial conditions are not satisfied');
+
+ frameset.innerHTML = '<template>some text</template>';
+
+ assert_not_equals(frameset.querySelector('template'), null,
+ 'Template element should be a descendant of the frameset element');
+
+}, 'Template element as a descendant of the frameset element. '
+ + 'Test template element is assigned to frameset\'s innerHTML)');
+
+
+testInIFrame('../resources/template-descendant-frameset.html', function(context) {
+ var doc = context.iframes[0].contentDocument;
+
+ var frameset = doc.querySelector('frameset');
+
+ var template = doc.createElement('template');
+ frameset.appendChild(template);
+
+ assert_equals(frameset.querySelectorAll('template').length, 2,
+ 'Template element should be a descendant of the frameset element');
+
+}, 'Template element as a descendant of the frameset element. '
+ + 'Test template element appended to frameset by appendChild()');
+
+
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/template-element/template-descendant-head.html b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/template-element/template-descendant-head.html
new file mode 100644
index 00000000000..6b025e9abd8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/template-element/template-descendant-head.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>HTML Templates: Template element as a descendant of the head element.</title>
+<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<meta name="assert" content="Template element can be a descendant of the head element">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#template-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src='../testcommon.js'></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script type="text/javascript">
+
+testInIFrame('../resources/template-descendant-head.html', function(context) {
+ var doc = context.iframes[0].contentDocument;
+
+ assert_not_equals(doc.head.querySelector('template'), null,
+ 'Template element should be a descendant of the head element');
+
+}, 'Template element as a descendant of the head element. Test loading from a file');
+
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/testcommon.js b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/testcommon.js
new file mode 100644
index 00000000000..0f2bfb1e21a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/scripting-1/the-template-element/testcommon.js
@@ -0,0 +1,191 @@
+/*
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+ */
+
+"use strict";
+
+var HTML5_ELEMENTS = [ 'a', 'abbr', 'address', 'area', 'article', 'aside',
+ 'audio', 'b', 'base', 'bdi', 'bdo', 'blockquote', 'body', 'br',
+ 'button', 'canvas', 'caption', 'cite', 'code', 'col', 'colgroup',
+ 'command', 'datalist', 'dd', 'del', 'details', 'dfn', 'dialog', 'div',
+ 'dl', 'dt', 'em', 'embed', 'fieldset', 'figcaption', 'figure',
+ 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header',
+ 'hgroup', 'hr', 'html', 'i', 'iframe', 'img', 'input', 'ins', 'kbd',
+ 'keygen', 'label', 'legend', 'li', 'link', 'map', 'mark', 'menu',
+ 'meta', 'meter', 'nav', 'noscript', 'object', 'ol', 'optgroup',
+ 'option', 'output', 'p', 'param', 'pre', 'progress', 'q', 'rp', 'rt',
+ 'ruby', 's', 'samp', 'script', 'section', 'select', 'small', 'source',
+ 'span', 'strong', 'style', 'sub', 'table', 'tbody', 'td', 'textarea',
+ 'tfoot', 'th', 'thead', 'time', 'title', 'tr', 'track', 'u', 'ul',
+ 'var', 'video', 'wbr' ];
+
+// only void (without end tag) HTML5 elements
+var HTML5_VOID_ELEMENTS = [ 'area', 'base', 'br', 'col', 'command', 'embed',
+ 'hr', 'img', 'input', 'keygen', 'link', 'meta', 'param', 'source',
+ 'track', 'wbr' ];
+
+// https://html.spec.whatwg.org/multipage/multipage/forms.html#form-associated-element
+var HTML5_FORM_ASSOCIATED_ELEMENTS = [ 'button', 'fieldset', 'input', 'keygen',
+ 'label', 'object', 'output', 'select', 'textarea' ];
+
+function newDocument() {
+ var d = document.implementation.createDocument();
+ return d;
+}
+
+function newHTMLDocument() {
+ var d = document.implementation.createHTMLDocument('Test Document');
+ return d;
+}
+
+function newXHTMLDocument() {
+ var doctype = document.implementation.createDocumentType('html',
+ '-//W3C//DTD XHTML 1.0 Transitional//EN',
+ 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd');
+
+ var d = document.implementation.createDocument(
+ 'http://www.w3.org/1999/xhtml', 'html', doctype);
+ return d;
+}
+
+function newIFrame(context, src) {
+ if (typeof (context) === 'undefined'
+ || typeof (context.iframes) !== 'object') {
+ assert_unreached('Illegal context object in newIFrame');
+ }
+
+ var iframe = document.createElement('iframe');
+ iframe.style.display = 'none';
+
+ if (typeof (src) != 'undefined') {
+ iframe.src = src;
+ }
+ document.body.appendChild(iframe);
+ context.iframes.push(iframe);
+
+ assert_true(typeof (iframe.contentWindow) != 'undefined'
+ && typeof (iframe.contentWindow.document) != 'undefined'
+ && iframe.contentWindow.document != document,
+ 'Failed to create new rendered document');
+ return iframe;
+}
+
+function newRenderedHTMLDocument(context) {
+ var frame = newIFrame(context);
+ var d = frame.contentWindow.document;
+ return d;
+}
+
+function newContext() {
+ return {
+ iframes : []
+ };
+}
+
+function cleanContext(context) {
+ context.iframes.forEach(function(e) {
+ e.parentNode.removeChild(e);
+ });
+}
+
+// run given test function in context
+// the context is cleaned up after test completes.
+function inContext(f) {
+ return function() {
+ var context = newContext();
+ try {
+ f(context);
+ } finally {
+ cleanContext(context);
+ }
+ };
+}
+
+// new context and iframe are created and url (if supplied) is asigned to
+// iframe.src
+// function f is bound to the iframe onload event or executed directly after
+// iframe creation
+// the context is passed to function as argument
+function testInIFrame(url, f, testName, testProps) {
+ if (url) {
+ var t = async_test(testName, testProps);
+ t.step(function() {
+ var context = newContext();
+ var iframe = newIFrame(context, url);
+ iframe.onload = t.step_func(function() {
+ try {
+ f(context);
+ t.done();
+ } finally {
+ cleanContext(context);
+ }
+ });
+ });
+ } else {
+ test(inContext(function(context) {
+ newRenderedHTMLDocument(context);
+ f(context);
+ }), testName, testProps);
+ }
+}
+
+function assert_nodelist_contents_equal_noorder(actual, expected, message) {
+ assert_equals(actual.length, expected.length, message);
+ var used = [];
+ for ( var i = 0; i < expected.length; i++) {
+ used.push(false);
+ }
+ for (i = 0; i < expected.length; i++) {
+ var found = false;
+ for ( var j = 0; j < actual.length; j++) {
+ if (used[j] == false && expected[i] == actual[j]) {
+ used[j] = true;
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ assert_unreached(message + ". Fail reason: element not found: "
+ + expected[i]);
+ }
+ }
+}
+
+function isVisible(el) {
+ return el.offsetTop != 0;
+}
+
+function isVoidElement(elementName) {
+ return HTML5_VOID_ELEMENTS.indexOf(elementName) >= 0;
+}
+
+function checkTemplateContent(d, obj, html, id, nodeName) {
+
+ obj.innerHTML = '<template id="tmpl">' + html + '</template>';
+
+ var t = d.querySelector('#tmpl');
+
+ if (id != null) {
+ assert_equals(t.content.childNodes.length, 1, 'Element ' + nodeName
+ + ' should present among template nodes');
+ assert_equals(t.content.firstChild.id, id, 'Wrong element ID');
+ }
+ if (nodeName != null) {
+ assert_equals(t.content.firstChild.nodeName, nodeName.toUpperCase(),
+ 'Wrong node name');
+ }
+}
+
+function checkBodyTemplateContent(d, html, id, nodeName) {
+ checkTemplateContent(d, d.body, html, id, nodeName);
+}
+
+function checkHeadTemplateContent(d, html, id, nodeName) {
+ checkTemplateContent(d, d.head, html, id, nodeName);
+}
diff --git a/tests/wpt/web-platform-tests/html/semantics/sections/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/sections/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/sections/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/sections/headings-and-sections/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/sections/headings-and-sections/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/sections/headings-and-sections/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/sections/headings-and-sections/contains.json b/tests/wpt/web-platform-tests/html/semantics/sections/headings-and-sections/contains.json
new file mode 100644
index 00000000000..a9fecf65b9d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/sections/headings-and-sections/contains.json
@@ -0,0 +1,6 @@
+[
+ {
+ "id": "outlines",
+ "original_id": "outlines"
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/sections/the-address-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/sections/the-address-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/sections/the-address-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/sections/the-article-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/sections/the-article-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/sections/the-article-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/sections/the-aside-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/sections/the-aside-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/sections/the-aside-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/sections/the-body-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/sections/the-body-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/sections/the-body-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/sections/the-footer-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/sections/the-footer-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/sections/the-footer-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/sections/the-h1-h2-h3-h4-h5-and-h6-elements/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/sections/the-h1-h2-h3-h4-h5-and-h6-elements/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/sections/the-h1-h2-h3-h4-h5-and-h6-elements/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/sections/the-h1-h2-h3-h4-h5-and-h6-elements/original-id.json b/tests/wpt/web-platform-tests/html/semantics/sections/the-h1-h2-h3-h4-h5-and-h6-elements/original-id.json
new file mode 100644
index 00000000000..748a548ca98
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/sections/the-h1-h2-h3-h4-h5-and-h6-elements/original-id.json
@@ -0,0 +1 @@
+{"original_id":"the-h1,-h2,-h3,-h4,-h5,-and-h6-elements"} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/sections/the-header-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/sections/the-header-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/sections/the-header-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/sections/the-hgroup-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/sections/the-hgroup-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/sections/the-hgroup-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/sections/the-nav-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/sections/the-nav-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/sections/the-nav-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/sections/the-section-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/sections/the-section-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/sections/the-section-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/sections/usage-summary-0/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/sections/usage-summary-0/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/sections/usage-summary-0/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/selectors/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/selectors/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/selectors/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/selectors/case-sensitivity/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/selectors/case-sensitivity/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/selectors/case-sensitivity/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/checked.html b/tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/checked.html
new file mode 100644
index 00000000000..ada4ee4dd6b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/checked.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Selector: pseudo-classes (:checked)</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org" id=link1>
+<link rel=help href="https://html.spec.whatwg.org/multipage/#pseudo-classes" id=link2>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="utils.js"></script>
+<div id="log"></div>
+<select id=select1>
+ <optgroup label="options" id=optgroup1>
+ <option value="option1" id=option1 selected>option1
+ <option value="option2" id=option2>option2
+ <option value="option2" id=option3 checked>option3
+</select>
+<input type=checkbox id=checkbox1 checked>
+<input type=checkbox id=checkbox2>
+<input type=checkbox id=checkbox3 selected>
+<input type=radio id=radio1 checked>
+<input type=radio id=radio2>
+<form>
+ <p><input type=submit contextmenu=formmenu id="submitbutton"></p>
+ <menu type=popup id=formmenu>
+ <menuitem type=checkbox checked default id=menuitem1>
+ <menuitem type=checkbox default id=menuitem2>
+ <menuitem type=checkbox id=menuitem3>
+ <menuitem type=radio checked id=menuitem4>
+ <menuitem type=radio id=menuitem5>
+ </menu>
+</form>
+
+<script>
+ testSelector(":checked", ["option1", "checkbox1", "radio1", "menuitem1", "menuitem4"], "':checked' matches checked <input>/<menuitem> in checkbox and radio button states, selected <option>s");
+
+ document.getElementById("checkbox1").removeAttribute("type"); // change type of input
+ document.getElementById("radio1").removeAttribute("type"); // change type of input
+ testSelector(":checked", ["option1", "menuitem1", "menuitem4"], "':checked' should no longer match <input>s whose type checkbox/radio has been removed");
+
+ document.getElementById("option2").selected = "selected"; // select option2
+ document.getElementById("checkbox2").click(); // check chekbox2
+ document.getElementById("radio2").click(); // check radio2
+ testSelector(":checked", ["option2", "checkbox2", "radio2", "menuitem1", "menuitem4"], "':checked' matches clicked checkbox and radio buttons");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/default.html b/tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/default.html
new file mode 100644
index 00000000000..a6564f03de2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/default.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Selector: pseudo-classes (:default)</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org" id=link1>
+<link rel=help href="https://html.spec.whatwg.org/multipage/#pseudo-classes" id=link2>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="utils.js"></script>
+<div id="log"></div>
+<form>
+ <button id=button1 type=button>button1</button>
+ <button id=button2 type=submit>button2</button>
+</form>
+<form>
+ <button id=button3 type=reset>button3</button>
+ <button id=button4>button4</button>
+</form>
+<button id=button5 type=submit>button5</button>
+<form id=form1>
+ <input type=text id=input1>
+</form>
+<input type=text id=input2 form=form1>
+<form>
+ <input type=submit id=input3>
+ <input type=submit id=input4>
+</form>
+<form>
+ <input type=image id=input5>
+ <input type=image id=input6>
+</form>
+<form>
+ <input type=submit id=input7>
+</form>
+<input type=checkbox id=checkbox1 checked>
+<input type=checkbox id=checkbox2>
+<input type=checkbox id=checkbox3 default>
+<select id=select1>
+ <optgroup label="options" id=optgroup1>
+ <option value="option1" id=option1 selected>option1
+ <option value="option1" id=option1>option1
+</select>
+<dialog id="dialog">
+ <input type=submit id=input8>
+</dialog>
+<form>
+ <button id=button6 type='invalid'>button6</button>
+ <button id=button7>button7</button>
+</form>
+<form>
+ <button id=button8>button8</button>
+ <button id=button9>button9</button>
+</form>
+
+
+<script>
+ testSelector(":default", ["button2", "button4", "input3", "input5", "input7", "checkbox1", "option1", "button6", "button8"], "':default' matches <button>s that are their form's default button, <input>s of type submit/image that are their form's default button, checked <input>s and selected <option>s");
+
+ document.getElementById("button1").type = "submit"; // change the form's default button
+ testSelector(":default", ["button1", "button4", "input3", "input5", "input7", "checkbox1", "option1", "button6", "button8"], "':default' matches dynamically changed form's default buttons");
+
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/dir.html b/tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/dir.html
new file mode 100644
index 00000000000..0ac1892a67c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/dir.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<meta charset=utf-8 id=meta>
+<title id=title>Selector: pseudo-classes (:dir(ltr), :dir(rtl))</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org" id=link1>
+<link rel=help href="https://html.spec.whatwg.org/multipage/#pseudo-classes" id=link2>
+<script src="/resources/testharness.js" id=script1></script>
+<script src="/resources/testharnessreport.js" id=script2></script>
+<script src="utils.js" id=script3></script>
+<style id=style>
+ #span1 {direction: rtl;}
+ #span5, #span6 {display: none;}
+</style>
+<div id="log"></div>
+<bdo dir="rtl" id=bdo1>WERBEH</bdo>
+<bdo dir="ltr" id=bdo2>HEBREW</bdo>
+<bdi id=bdi1>HEBREW</bdi>
+<bdi dir="rtl" id=bdi2>WERBEH</bdi>
+<bdi dir="ltr" id=bdi3>HEBREW</bdi>
+<span id=span1>WERBEH</span>
+<span dir="rtl" id=span2>WERBEH</span>
+<span dir="ltr" id=span3>HEBREW</span>
+&#x202E;<span id=span4>WERBEH</span>&#x202C;
+<span dir="rtl" id=span5>WERBEH</span>
+<span dir="ltr" id=span6>HEBREW</span>
+<bdo dir="auto" id=bdo3>HEBREW</bdo>
+<bdo dir="auto" id=bdo4>إيان</bdo>
+<bdo dir="ltr" id=bdo5>עברית</bdo>
+
+<script>
+ testSelector(":dir(rtl)", ["bdo1", "bdi2", "span1", "span2", "span4", "span5", "bdo4"], "':dir(rtl)' matches all elements whose directionality is 'rtl'.");
+ testSelector(":dir(ltr)", ["html", "head", "body", "meta", "title", "link1", "link2", "script1", "script2", "script3", "stlyle", "log", "bdo2", "bdi3", "span3", "span6", "bdo3", "bdo5"], "':dir(ltr)' matches all elements whose directionality is 'ltr'.");
+
+ var bdo = document.createElement("bdo");
+ bdo.setAttribute("dir", "ltr");
+ testSelector(":dir(ltr)", ["meta", "title", "link1", "link2", "script1", "script2", "script3", "stlyle", "log", "bdo2", "bdi3", "span3", "span6", "bdo3"], "':dir(ltr)' doesn't match elements not in the document.");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/dir01.html b/tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/dir01.html
new file mode 100644
index 00000000000..6f9dedb0ae5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/dir01.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<meta charset=iso-8859-8 id=meta>
+<title id=title>Selector: pseudo-classes (:dir(ltr), :dir(rtl)) in iso-8859-8 documents</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org" id=link1>
+<link rel=help href="https://html.spec.whatwg.org/multipage/#pseudo-classes" id=link2>
+<script src="/resources/testharness.js" id=script1></script>
+<script src="/resources/testharnessreport.js" id=script2></script>
+<script src="utils.js" id=script3></script>
+<div id="log"></div>
+<div>This text is left to right<div id=div1 style="direction:rtl">this is right to left</div></div>
+<div>This text is left to right<span id=div2 style="direction:rtl">this is left to right</span></div>
+
+<script>
+ var ltr = new Array(),
+ all = document.querySelectorAll('*');
+ for(var i = all.length; i--; ltr.unshift(all[i]));
+ testSelector(":dir(ltr)", ltr, "direction doesn't affect :dir()");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/disabled.html b/tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/disabled.html
new file mode 100644
index 00000000000..5417371a17c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/disabled.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Selector: pseudo-classes (:disabled)</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org" id=link1>
+<link rel=help href="https://html.spec.whatwg.org/multipage/#pseudo-classes" id=link2>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="utils.js"></script>
+<style>
+ #input4 {display:none;}
+</style>
+<div id="log"></div>
+<button id=button1 type=submit>button1</button>
+<button id=button2 disabled>button2</button>
+<input id=input1>
+<input id=input2 disabled>
+<input id=input3 readonly>
+<input id=input4>
+<select id=select1>
+ <optgroup label="options" id=optgroup1>
+ <option value="option1" id=option1 selected>option1
+</select>
+<select disabled id=select2>
+ <optgroup label="options" disabled id=optgroup2>
+ <option value="option2" disabled id=option2>option2
+</select>
+<textarea id=textarea1>textarea1</textarea>
+<textarea disabled id=textarea2>textarea2</textarea>
+<fieldset id=fieldset1></fieldset>
+<fieldset disabled id=fieldset2>
+ <legend><input type=checkbox id=club></legend>
+ <p><label>Name on card: <input id=clubname required></label></p>
+ <p><label>Card number: <input id=clubnum required pattern="[-0-9]+"></label></p>
+</fieldset>
+<label disabled></label>
+<object disabled></object>
+<output disabled></output>
+<img disabled/>
+<meter disabled></meter>
+<progress disabled></progress>
+
+<script>
+ testSelector(":disabled", ["button2", "input2", "select2", "optgroup2", "option2", "textarea2", "fieldset2", "clubname", "clubnum"], "':disabled' should match only disabled elements");
+
+ document.getElementById("button2").removeAttribute("disabled");
+ testSelector(":disabled", ["input2", "select2", "optgroup2", "option2", "textarea2", "fieldset2", "clubname", "clubnum"], "':disabled' should not match elements whose disabled attribute has been removed");
+
+ document.getElementById("button1").setAttribute("disabled", "disabled");
+ testSelector(":disabled", ["button1", "input2", "select2", "optgroup2", "option2", "textarea2", "fieldset2", "clubname", "clubnum"], "':disabled' should also match elements whose disabled attribute has been set");
+
+ document.getElementById("input2").setAttribute("type", "submit"); // change input type to submit
+ testSelector(":disabled", ["button1", "input2", "select2", "optgroup2", "option2", "textarea2", "fieldset2", "clubname", "clubnum"], "':disabled' should also match disabled elements whose type has changed");
+
+ var input = document.createElement("input");
+ input.setAttribute("disabled", "disabled");
+ testSelector(":disabled", ["button1", "input2", "select2", "optgroup2", "option2", "textarea2", "fieldset2", "clubname", "clubnum"], "':disabled' should not match elements not in the document");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/enabled.html b/tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/enabled.html
new file mode 100644
index 00000000000..66d48d5517c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/enabled.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Selector: pseudo-classes (:enabled)</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org" id=link1>
+<link rel=help href="https://html.spec.whatwg.org/multipage/#pseudo-classes" id=link2>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="utils.js"></script>
+<div id="log"></div>
+<a id=link3></a>
+<area id=link4></area>
+<link id=link5></link>
+<a href="http://www.w3.org" id=link6></a>
+<area href="http://www.w3.org" id=link7></area>
+<link href="http://www.w3.org" id=link8></link>
+<button id=button1>button1</button>
+<button id=button2 disabled>button2</button>
+<input id=input1>
+<input id=input2 disabled>
+<select id=select1>
+ <optgroup label="options" id=optgroup1>
+ <option value="option1" id=option1 selected>option1
+</select>
+<select disabled id=select2>
+ <optgroup label="options" disabled id=optgroup2>
+ <option value="option2" disabled id=option2>option2
+</select>
+<textarea id=textarea1>textarea1</textarea>
+<textarea disabled id=textarea2>textarea2</textarea>
+<form>
+ <p><input type=submit contextmenu=formmenu id=submitbutton></p>
+ <menu type=popup id=formmenu>
+ <menuitem command="submitbutton" default id=menuitem1>
+ <menuitem command="resetbutton" disabled id=menuitem2>
+ </menu>
+</form>
+<fieldset id=fieldset1></fieldset>
+<fieldset disabled id=fieldset2></fieldset>
+
+<script>
+ testSelector(":enabled", ["button1", "input1", "select1", "optgroup1", "option1", "textarea1", "submitbutton", "menuitem1", "fieldset1"], "':enabled' elements that are not disabled");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/focus-iframe.html b/tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/focus-iframe.html
new file mode 100644
index 00000000000..a269f1c6717
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/focus-iframe.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Selector: pseudo-classes (:focus)</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<input id="inputiframe" type=text value="foobar" />
diff --git a/tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/focus.html b/tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/focus.html
new file mode 100644
index 00000000000..69f8b2afcf7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/focus.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Selector: pseudo-classes (:focus)</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org" id=link1>
+<link rel=help href="https://html.spec.whatwg.org/multipage/#pseudo-classes" id=link2>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="utils.js"></script>
+<body id=body tabindex=0>
+ <div id="log"></div>
+ <button id=button1 type=submit>button1</button>
+ <input id=input1>
+ <input id=input2 disabled>
+ <input id=input3 autofocus>
+ <textarea id=textarea1>textarea1</textarea>
+ <input type=checkbox id=checkbox1 checked>
+ <input type=radio id=radio1 checked>
+ <div tabindex=0 id=div1>hello</div>
+ <div contenteditable id=div2>content</div>
+ <iframe src="focus-iframe.html" id=iframe onload="load()"></iframe>
+
+ <script>
+ testSelector(":focus", ["input3"], "input3 has the attribute autofocus");
+
+ document.getElementById("input1").focus(); // set the focus on input1
+ testSelector(":focus", ["input1"], "input1 has the focus");
+
+ document.getElementById("div1").focus();
+ testSelector(":focus", ["div1"], "tabindex attribute makes the element focusable");
+
+ document.getElementById("div2").focus();
+ testSelector(":focus", ["div2"], "editable elements are focusable");
+
+ function load() {
+ document.getElementById("iframe").contentDocument.getElementById("inputiframe").focus();
+ testSelector(":focus", [], "':focus' doesn't match focused elements in iframe");
+ }
+
+ document.body.focus();
+ testSelector(":focus", ["body"], "':focus' matches focussed body with tabindex");
+ </script>
+</body>
diff --git a/tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/indeterminate.html b/tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/indeterminate.html
new file mode 100644
index 00000000000..62a40641b46
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/indeterminate.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Selector: pseudo-classes (:indeterminate)</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org" id=link1>
+<link rel=help href="https://html.spec.whatwg.org/multipage/#pseudo-classes" id=link2>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="utils.js"></script>
+<div id="log"></div>
+<input type=checkbox id=checkbox1>
+<input type=checkbox id=checkbox2>
+<input type=radio id=radio1 checked>
+<input type=radio name=radiogroup id=radio2>
+<input type=radio name=radiogroup id=radio3>
+<input type=radio name=group2 id=radio4>
+<input type=radio name=group2 id=radio5>
+<progress id="progress1"></progress>
+<progress id="progress2" value=10></progress>
+
+<script>
+ testSelector(":indeterminate", ["radio2", "radio3", "radio4", "radio5", "progress1"], "':progress' matches <input>s radio buttons whose radio button group contains no checked input and <progress> elements without value attribute");
+
+ document.getElementById("radio2").setAttribute("checked", "checked");
+ testSelector(":indeterminate", ["radio4", "radio5", "progress1"], "dynamically check a radio input in a radio button group");
+
+ document.getElementById("radio4").click();
+ testSelector(":indeterminate", ["checkbox1", "progress2"], "click on radio4 which is in the indeterminate state");
+
+ document.getElementById("progress1").setAttribute("value", "20");
+ testSelector(":indeterminate", [], "adding a value to progress1 should put it in a determinate state");
+
+ document.getElementById("progress2").removeAttribute("value");
+ testSelector(":indeterminate", ["progress2"], "removing progress2's value should put it in an indeterminate state");
+
+ document.getElementById("checkbox1").indeterminate = true; // set checkbox1 in the indeterminate state
+ testSelector(":indeterminate", ["checkbox1", "progress2"], "':progress' also matches <input> checkbox whose indeterminate IDL is set to true");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/inrange-outofrange.html b/tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/inrange-outofrange.html
new file mode 100644
index 00000000000..92b16837631
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/inrange-outofrange.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Selector: pseudo-classes (:in-range, :out-of-range)</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org" id=link1>
+<link rel=help href="https://html.spec.whatwg.org/multipage/#pseudo-classes" id=link2>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="utils.js"></script>
+<div id="log"></div>
+<input type=number value=0 min=0 max=10 id=number1>
+<input type=number value=0 min=0 max=10 id=number2 disabled>
+<input type=number value=0 min=1 max=10 id=number3>
+<input type=number value=11 min=0 max=10 id=number4>
+
+<script>
+ testSelector(":in-range", ["number1"], "':in-range' matches all elements that are candidates for constraint validation, have range limitations, and that are neither suffering from an underflow nor suffering from an overflow");
+
+ testSelector(":out-of-range", ["number3", "number4"], "':out-of-range' matches all elements that are candidates for constraint validation, have range limitations, and that are either suffering from an underflow or suffering from an overflow");
+
+ document.getElementById("number1").value = -10;
+ testSelector(":in-range", [], "':in-range' update number1's value < min");
+ testSelector(":out-of-range", ["number1", "number3", "number4"], "':out-of-range' update number1's value < min");
+
+ document.getElementById("number3").min = 0;
+ testSelector(":in-range", ["number3"], "':in-range' update number3's min < value");
+ testSelector(":out-of-range", ["number1", "number4"], "':out-of-range' update number3's min < value");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/link.html b/tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/link.html
new file mode 100644
index 00000000000..3e6e4a57898
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/link.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Selector: pseudo-classes (:link)</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org" id=link1>
+<link rel=help href="https://html.spec.whatwg.org/multipage/#pseudo-classes" id=link2>
+<link rel=stylesheet href="/resources/testharness.css" id=link3>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="utils.js"></script>
+<div id="log"></div>
+<a id=link4></a>
+<area id=link5></area>
+<link id=link6></link>
+<a href="http://www.w3.org" id=link7></a>
+<area href="http://www.w3.org" id=link8></area>
+<link href="http://www.w3.org" id=link9></link>
+<a href="http://[" id=link10></a>
+
+<script>
+ testSelector(":link", ["link1", "link2", "link3", "link7", "link8", "link9", "link10"], "Only <a>s, <area>s and <link>s that have a href attribute match ':link'");
+
+ document.getElementById("link9").removeAttribute("href");
+ testSelector(":link", ["link1", "link2", "link3", "link7", "link8", "link10"], "':link' doesn't match elements whos href attribute has been removed");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/readwrite-readonly.html b/tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/readwrite-readonly.html
new file mode 100644
index 00000000000..a23dc8e1b6e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/readwrite-readonly.html
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Selector: pseudo-classes (:read-write, :read-only)</title>
+<link rel=help href="https://html.spec.whatwg.org/multipage/#pseudo-classes" id=link2>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="utils.js"></script>
+<div id="log"></div>
+
+<div id=set1>
+<input id=input1>
+<input id=input2 readonly>
+<input id=input3 disabled>
+<input id=input4 type=checkbox>
+<input id=input5 type=checkbox readonly>
+</div>
+
+<div id=set2>
+<textarea id=textarea1>textarea1</textarea>
+<textarea readonly id=textarea2>textarea2</textarea>
+</div>
+
+<div id=set3>
+<textarea id=textarea3>textarea3</textarea>
+<textarea disabled id=textarea4>textarea4</textarea>
+</div>
+
+<div id=set4>
+<p id=p1>paragraph1.</p>
+<p id=p2 contenteditable>paragraph2.</p>
+</div>
+
+<script>
+ testSelector("#set1 :read-write", ["input1"], "The :read-write pseudo-class must match input elements to which the readonly attribute applies, and that are mutable");
+
+ testSelector("#set1 :read-only", ["input2"], "The :read-only pseudo-class must not match input elements to which the readonly attribute applies, and that are mutable");
+
+ document.getElementById("input1").setAttribute("readonly", "readonly");
+ testSelector("#set1 :read-write", [], "The :read-write pseudo-class must not match input elements after the readonly attribute has been added");
+
+ testSelector("#set1 :read-only", ["input1", "input2"], "The :read-only pseudo-class must match input elements after the readonly attribute has been added");
+
+ document.getElementById("input1").removeAttribute("readonly");
+ testSelector("#set1 :read-write", ["input1"], "The :read-write pseudo-class must not match input elements after the readonly attribute has been removed");
+
+ testSelector("#set1 :read-only", ["input2"], "The :read-only pseudo-class must match input elements after the readonly attribute has been removed");
+
+ testSelector("#set2 :read-write", ["textarea1"], "The :read-write pseudo-class must match textarea elements that do not have a readonly attribute, and that are not disabled");
+
+ testSelector("#set2 :read-only", ["textarea2"], "The :read-only pseudo-class must match textarea elements that have a readonly attribute, or that are disabled");
+
+ document.getElementById("textarea1").setAttribute("readonly", "readonly");
+ testSelector("#set2 :read-write", [], "The :read-write pseudo-class must match textarea elements after the readonly attribute has been added");
+
+ testSelector("#set2 :read-only", ["textarea1", "textarea2"], "The :read-only pseudo-class must match textarea elements after the readonly attribute has been added");
+
+ testSelector("#set3 :read-write", ["textarea3"], "The :read-write pseudo-class must not match textarea elements that are disabled");
+
+ testSelector("#set3 :read-only", ["textarea4"], "The :read-only pseudo-class must match textarea elements that are disabled");
+
+ testSelector("#set4 :read-write", ["p2"], "The :read-write pseudo-class must match elements that are editable");
+
+ testSelector("#set4 :read-only", ["p1"], "The :read-only pseudo-class must not match elements that are editable");
+
+ document.designMode = "on";
+
+ testSelector("#set4 :read-write", ["p1", "p2"], "The :read-write pseudo-class must match elements that are editing hosts");
+
+ testSelector("#set4 :read-only", [], "The :read-only pseudo-class must not match elements that are editing hosts");
+
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/required-optional.html b/tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/required-optional.html
new file mode 100644
index 00000000000..5c6df2ebcd0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/required-optional.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Selector: pseudo-classes (:required, :optional)</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org" id=link1>
+<link rel=help href="https://html.spec.whatwg.org/multipage/#pseudo-classes" id=link2>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="utils.js"></script>
+<div id="log"></div>
+<input type=text id=text1 value="foobar" required>
+<input type=text id=text2 required>
+<input type=text id=text3>
+<select id=select1 required>
+ <optgroup label="options" id=optgroup1>
+ <option value="option1" id=option1>option1
+</select>
+<select id=select2>
+ <optgroup label="options" id=optgroup2>
+ <option value="option2" id=option2>option2
+</select>
+<textarea required id=textarea1>textarea1</textarea>
+<textarea id=textarea2>textarea2</textarea>
+
+<script>
+ testSelector(":required", ["text1", "text2", "select1", "textarea1"], "':required' matches required <input>s, <select>s and <textarea>s");
+ testSelector(":optional", ["text3", "select2", "textarea2"], "':optional' matches elements <input>s, <select>s and <textarea>s that are not required");
+
+ document.getElementById("text1").removeAttribute("required");
+ testSelector(":required", ["text2", "select1", "textarea1"], "':required' doesn't match elements whose required attribute has been removed");
+ testSelector(":optional", ["text1", "text3", "select2", "textarea2"], "':optional' matches elements whose required attribute has been removed");
+
+ document.getElementById("select2").setAttribute("required", "required");
+ testSelector(":required", ["text2", "select1", "select2", "textarea1"], "':required' matches elements whose required attribute has been added");
+ testSelector(":optional", ["text1", "text3", "textarea2"], "':optional' doesn't match elements whose required attribute has been added");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/utils.js b/tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/utils.js
new file mode 100644
index 00000000000..8f5497ec57e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/utils.js
@@ -0,0 +1,14 @@
+function getElementsByIds(ids) {
+ var result = [];
+ ids.forEach(function(id) {
+ result.push(document.getElementById(id));
+ });
+ return result;
+}
+
+function testSelector(selector, expected, testName) {
+ test(function(){
+ var elements = document.querySelectorAll(selector);
+ assert_array_equals(elements, getElementsByIds(expected));
+ }, testName);
+}
diff --git a/tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/valid-invalid.html b/tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/valid-invalid.html
new file mode 100644
index 00000000000..746f7e96c33
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/selectors/pseudo-classes/valid-invalid.html
@@ -0,0 +1,68 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Selector: pseudo-classes (:valid, :invalid)</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org" id=link1>
+<link rel=help href="https://html.spec.whatwg.org/multipage/#pseudo-classes" id=link2>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="utils.js"></script>
+<div id="log"></div>
+<div id='simpleConstraints'>
+ <input type=text id=text1 value="foobar" required>
+ <input type=text id=text2 required>
+</div>
+<div id='FormSelection'>
+ <form id=form1>
+ <input type=text id=text3 value="foobar" required>
+ </form>
+ <form id=form2>
+ <input type=text id=text4 required>
+ </form>
+</div>
+<div id='FieldSetSelection'>
+ <fieldset id=fieldset1>
+ <input type=text id=text5 value="foobar" required>
+ </fieldset>
+ <fieldset id=fieldset2>
+ <input type=text id=text6 required>
+ </fieldset>
+</div>
+<div id='patternConstraints'>
+ <input type=text id=text7 value="AAA" pattern="[0-9][A-Z]{3}">
+ <input type=text id=text8 value="0AAA" pattern="[0-9][A-Z]{3}">
+</div>
+<div id='numberConstraints'>
+ <input type=number id=number1 value=0 min=1>
+ <input type=number id=number2 value=1 min=1>
+</div>
+
+<script>
+ testSelector("#simpleConstraints :valid", ["text1"], "':valid' matches elements that satisfy their constraints");
+
+ testSelector("#FormSelection :valid", ["form1", "text3"], "':valid' matches form elements that are not the form owner of any elements that themselves are candidates for constraint validation but do not satisfy their constraints");
+
+ testSelector("#FieldSetSelection :valid", ["fieldset1", "text5"], "':valid' matches fieldset elements that have no descendant elements that themselves are candidates for constraint validation but do not satisfy their constraints");
+
+ testSelector("#patternConstraints :valid", [ "text8" ], "':valid' matches elements that satisfy their pattern constraints");
+
+ testSelector("#numberConstraints :valid", [ "number2" ], "':valid' matches elements that satisfy their number constraints");
+
+
+ testSelector("#simpleConstraints :invalid", ["text2"], "':invalid' matches elements that do not satisfy their simple text constraints");
+
+ testSelector("#FormSelection :invalid", ["form2", "text4"], "':invalid' matches form elements that are the form owner of one or more elements that themselves are candidates for constraint validation but do not satisfy their constraints");
+
+ testSelector("#FieldSetSelection :invalid", ["fieldset2", "text6"], "':invalid' matches fieldset elements that have of one or more descendant elements that themselves are candidates for constraint validation but do not satisfy their constraints");
+
+ testSelector("#patternConstraints :invalid", ["text7"], "':invalid' matches elements that do not satisfy their pattern constraints");
+
+ testSelector("#numberConstraints :invalid", ["number1"], "':invalid' matches elements that do not satisfy their number constraints");
+
+ document.getElementById("text7").value="0BBB";
+ testSelector("#patternConstraints :valid", [ "text7", "text8" ], "':valid' matches new elements that satisfy their constraints");
+ testSelector("#patternConstraints :invalid", [], "':invalid' doesn't match new elements that satisfy their constraints");
+
+ document.getElementById("text8").value="BBB";
+ testSelector("#patternConstraints :valid", ["text7"], "':valid' doesn't match new elements that do not satisfy their constraints");
+ testSelector("#patternConstraints :invalid", ["text8"], "':invalid' matches new elements that do not satisfy their constraints");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/tabular-data/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/tabular-data/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/tabular-data/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/tabular-data/attributes-common-to-td-and-th-elements/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/tabular-data/attributes-common-to-td-and-th-elements/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/tabular-data/attributes-common-to-td-and-th-elements/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/tabular-data/attributes-common-to-td-and-th-elements/cellIndex.html b/tests/wpt/web-platform-tests/html/semantics/tabular-data/attributes-common-to-td-and-th-elements/cellIndex.html
new file mode 100644
index 00000000000..b9e523334f3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/tabular-data/attributes-common-to-td-and-th-elements/cellIndex.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>HTMLTableCellElement.cellIndex</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ var th = document.createElement("th");
+ assert_true("cellIndex" in th, '"cellIndex" in th');
+ var td = document.createElement("td");
+ assert_true("cellIndex" in td, '"cellIndex" in td');
+}, "cellIndex should exist.")
+test(function() {
+ var th = document.createElement("th");
+ assert_equals(th.cellIndex, -1);
+ var td = document.createElement("td");
+ assert_equals(td.cellIndex, -1);
+}, "For cells without a parent, cellIndex should be -1.")
+test(function() {
+ var table = document.createElement("table");
+ var th = table.appendChild(document.createElement("th"));
+ assert_equals(th.cellIndex, -1);
+ var td = table.appendChild(document.createElement("td"));
+ assert_equals(td.cellIndex, -1);
+}, "For cells whose parent is not a tr, cellIndex should be -1.")
+test(function() {
+ var tr = document.createElementNS("", "tr");
+ var th = tr.appendChild(document.createElement("th"));
+ assert_equals(th.cellIndex, -1);
+ var td = tr.appendChild(document.createElement("td"));
+ assert_equals(td.cellIndex, -1);
+}, "For cells whose parent is not a HTML tr, cellIndex should be -1.")
+test(function() {
+ var tr = document.createElement("tr");
+ var th = tr.appendChild(document.createElement("th"));
+ assert_equals(th.cellIndex, 0);
+ var td = tr.appendChild(document.createElement("td"));
+ assert_equals(td.cellIndex, 1);
+}, "For cells whose parent is a tr, cellIndex should be the index.")
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/tabular-data/examples/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/tabular-data/examples/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/tabular-data/examples/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/tabular-data/processing-model-1/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/tabular-data/processing-model-1/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/tabular-data/processing-model-1/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/tabular-data/processing-model-1/contains.json b/tests/wpt/web-platform-tests/html/semantics/tabular-data/processing-model-1/contains.json
new file mode 100644
index 00000000000..be5a8fdfdd4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/tabular-data/processing-model-1/contains.json
@@ -0,0 +1,10 @@
+[
+ {
+ "id": "forming-a-table",
+ "original_id": "forming-a-table"
+ },
+ {
+ "id": "header-and-data-cell-semantics",
+ "original_id": "header-and-data-cell-semantics"
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-caption-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-caption-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-caption-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-caption-element/caption_001.html b/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-caption-element/caption_001.html
new file mode 100644
index 00000000000..5393d1ed5c5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-caption-element/caption_001.html
@@ -0,0 +1,69 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>HTML5 Table API Tests</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-caption-element" />
+ </head>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <body>
+ <div id="log"></div>
+ <table id="table1" style="display:none">
+ <tr><td></td></tr>
+ <caption>first caption</caption>
+ <caption>second caption</caption>
+ </table>
+ <table id="table2" style="display:none">
+ <tr><td></td></tr>
+ </table>
+ <table id="table3" style="display:none">
+ <tr><td></td></tr>
+ </table>
+ <table id="table4" style="display:none">
+ <tr><td></td></tr>
+ <caption>first caption</caption>
+ </table>
+ <script>
+ test(function () {
+ assert_equals(document.getElementById('table1').caption.innerHTML, "first caption");
+ }, "first caption element child of the first table element");
+
+ test(function () {
+ var caption = document.createElement("caption");
+ caption.innerHTML = "new caption";
+ var table = document.getElementById('table1');
+ table.caption = caption;
+
+ assert_equals(caption.parentNode, table);
+ assert_equals(table.caption.innerHTML, "new caption");
+
+ captions = table.getElementsByTagName('caption');
+ assert_equals(captions.length, 2);
+ assert_equals(captions[0].innerHTML, "new caption");
+ assert_equals(captions[1].innerHTML, "second caption");
+ }, "setting caption on a table");
+
+ test(function () {
+ assert_equals(document.getElementById('table2').caption, null);
+ }, "caption IDL attribute is null");
+
+ test(function () {
+ var table = document.getElementById('table3');
+ var caption = document.createElement("caption")
+ table.rows[0].appendChild(caption);
+ assert_equals(table.caption, null);
+ }, "caption of the third table element should be null");
+
+ test(function () {
+ assert_not_equals(document.getElementById('table4').caption, null);
+
+ var parent = document.getElementById('table4').caption.parentNode;
+ parent.removeChild(document.getElementById('table4').caption);
+
+ assert_equals(document.getElementById('table4').caption, null);
+ }, "dynamically removing caption on a table");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-col-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-col-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-col-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-colgroup-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-colgroup-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-colgroup-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-table-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-table-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-table-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-table-element/caption-methods.html b/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-table-element/caption-methods.html
new file mode 100644
index 00000000000..5e609097e7c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-table-element/caption-methods.html
@@ -0,0 +1,56 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Creating and deleting captions</title>
+ <link rel="author" title="Erika Navara" href="mailto:edoyle@microsoft.com">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-table-element" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-table-createcaption" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-table-deletecaption" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <table id="table1" style="display:none">
+ <caption id="caption1">caption</caption>
+ <tr>
+ <td>cell</td>
+ <td>cell</td>
+ </tr>
+ </table>
+ <table id="table2" style="display:none">
+ <tr>
+ <td>cell</td>
+ <td>cell</td>
+ </tr>
+ </table>
+ <table id="table3" style="display:none">
+ <caption id="caption3">caption 3</caption>
+ <tr>
+ <td>cell</td>
+ <td>cell</td>
+ </tr>
+ </table>
+ <script>
+ test(function () {
+ var table1 = document.getElementById('table1');
+ var testCaption = table1.createCaption();
+ var table1FirstCaption = table1.caption;
+ assert_equals(testCaption, table1FirstCaption);
+ }, "createCaption method returns the first caption element child of the table")
+ test(function () {
+ var table2 = document.getElementById('table2');
+ var test2Caption = table2.createCaption();
+ var table2FirstNode = table2.firstChild;
+ assert_true(test2Caption instanceof HTMLTableCaptionElement);
+ assert_equals(table2FirstNode, test2Caption);
+ }, "createCaption method creates a new caption and inserts it as the first node of the table element")
+ test(function () {
+ var table3 = document.getElementById('table3');
+ assert_equals(table3.caption.textContent, "caption 3");
+ table3.deleteCaption();
+ assert_equals(table3.caption, null);
+ }, "deleteCaption method removes the first caption element child of the table element")
+ </script>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-table-element/contains.json b/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-table-element/contains.json
new file mode 100644
index 00000000000..ee89be21dc6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-table-element/contains.json
@@ -0,0 +1,10 @@
+[
+ {
+ "id": "table-descriptions-techniques",
+ "original_id": "table-descriptions-techniques"
+ },
+ {
+ "id": "table-layout-techniques",
+ "original_id": "table-layout-techniques"
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-table-element/createTBody.html b/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-table-element/createTBody.html
new file mode 100644
index 00000000000..7927e43cae6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-table-element/createTBody.html
@@ -0,0 +1,165 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>HTMLTableElement.createTBody</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+function assert_tbody(tbody) {
+ assert_equals(tbody.localName, "tbody");
+ assert_equals(tbody.namespaceURI, htmlNS);
+ assert_equals(tbody.prefix, null);
+}
+var htmlNS = "http://www.w3.org/1999/xhtml";
+test(function() {
+ var table = document.createElement("table");
+ var tbody = table.createTBody();
+ assert_equals(table.firstChild, tbody);
+ assert_tbody(tbody);
+}, "No child nodes");
+
+test(function() {
+ var table = document.createElement("table");
+ var before = table.appendChild(document.createElement("tbody"));
+ assert_array_equals(table.childNodes, [before]);
+
+ var tbody = table.createTBody();
+ assert_array_equals(table.childNodes, [before, tbody]);
+ assert_tbody(tbody);
+}, "One tbody child node");
+
+test(function() {
+ var table = document.createElement("table");
+ var before1 = table.appendChild(document.createElement("tbody"));
+ var before2 = table.appendChild(document.createElement("tbody"));
+ assert_array_equals(table.childNodes, [before1, before2]);
+
+ var tbody = table.createTBody();
+ assert_array_equals(table.childNodes, [before1, before2, tbody]);
+ assert_tbody(tbody);
+}, "Two tbody child nodes");
+
+test(function() {
+ var table = document.createElement("table");
+ var before1 = table.appendChild(document.createElement("thead"));
+ var before2 = table.appendChild(document.createElement("tbody"));
+ assert_array_equals(table.childNodes, [before1, before2]);
+
+ var tbody = table.createTBody();
+ assert_array_equals(table.childNodes, [before1, before2, tbody]);
+ assert_tbody(tbody);
+}, "A thead and a tbody child node");
+
+test(function() {
+ var table = document.createElement("table");
+ var before1 = table.appendChild(document.createElement("tfoot"));
+ var before2 = table.appendChild(document.createElement("tbody"));
+ assert_array_equals(table.childNodes, [before1, before2]);
+
+ var tbody = table.createTBody();
+ assert_array_equals(table.childNodes, [before1, before2, tbody]);
+ assert_tbody(tbody);
+}, "A tfoot and a tbody child node");
+
+test(function() {
+ var table = document.createElement("table");
+ var before = table.appendChild(document.createElement("tbody"));
+ var after = table.appendChild(document.createElement("thead"));
+ assert_array_equals(table.childNodes, [before, after]);
+
+ var tbody = table.createTBody();
+ assert_array_equals(table.childNodes, [before, tbody, after]);
+ assert_tbody(tbody);
+}, "A tbody and a thead child node");
+
+test(function() {
+ var table = document.createElement("table");
+ var before = table.appendChild(document.createElement("tbody"));
+ var after = table.appendChild(document.createElement("tfoot"));
+ assert_array_equals(table.childNodes, [before, after]);
+
+ var tbody = table.createTBody();
+ assert_array_equals(table.childNodes, [before, tbody, after]);
+ assert_tbody(tbody);
+}, "A tbody and a tfoot child node");
+
+test(function() {
+ var table = document.createElement("table");
+ var before1 = table.appendChild(document.createElement("tbody"));
+ var before2 = table.appendChild(document.createElement("tbody"));
+ var after = table.appendChild(document.createElement("div"));
+ assert_array_equals(table.childNodes, [before1, before2, after]);
+
+ var tbody = table.createTBody();
+ assert_array_equals(table.childNodes, [before1, before2, tbody, after]);
+ assert_tbody(tbody);
+}, "Two tbody child nodes and a div");
+
+test(function() {
+ var table = document.createElement("table");
+ var before = table.appendChild(document.createElement("tbody"));
+ var after = table.appendChild(document.createElementNS("x", "tbody"));
+ assert_array_equals(table.childNodes, [before, after]);
+
+ var tbody = table.createTBody();
+ assert_array_equals(table.childNodes, [before, tbody, after]);
+ assert_tbody(tbody);
+}, "One HTML and one namespaced tbody child node");
+
+test(function() {
+ var table = document.createElement("table");
+ var before1 = table.appendChild(document.createElement("tbody"));
+ var before2 = before1.appendChild(document.createElement("tbody"));
+ assert_array_equals(table.childNodes, [before1]);
+
+ var tbody = table.createTBody();
+ assert_array_equals(table.childNodes, [before1, tbody]);
+ assert_tbody(tbody);
+}, "Two nested tbody child nodes");
+
+test(function() {
+ var table = document.createElement("table");
+ var before1 = table.appendChild(document.createElement("thead"));
+ var before2 = before1.appendChild(document.createElement("tbody"));
+ assert_array_equals(table.childNodes, [before1]);
+
+ var tbody = table.createTBody();
+ assert_array_equals(table.childNodes, [before1, tbody]);
+ assert_tbody(tbody);
+}, "A tbody node inside a thead child node");
+
+test(function() {
+ var table = document.createElement("table");
+ var before1 = table.appendChild(document.createElement("tfoot"));
+ var before2 = before1.appendChild(document.createElement("tbody"));
+ assert_array_equals(table.childNodes, [before1]);
+
+ var tbody = table.createTBody();
+ assert_array_equals(table.childNodes, [before1, tbody]);
+ assert_tbody(tbody);
+}, "A tbody node inside a tfoot child node");
+
+test(function() {
+ var table = document.createElement("table");
+ var before = table.appendChild(document.createElement("tbody"));
+ var after1 = table.appendChild(document.createElement("thead"));
+ var after2 = after1.appendChild(document.createElement("tbody"));
+ assert_array_equals(table.childNodes, [before, after1]);
+
+ var tbody = table.createTBody();
+ assert_array_equals(table.childNodes, [before, tbody, after1]);
+ assert_tbody(tbody);
+}, "A tbody node inside a thead child node after a tbody child node");
+
+test(function() {
+ var table = document.createElement("table");
+ var before = table.appendChild(document.createElement("tbody"));
+ var after1 = table.appendChild(document.createElement("tfoot"));
+ var after2 = after1.appendChild(document.createElement("tbody"));
+ assert_array_equals(table.childNodes, [before, after1]);
+
+ var tbody = table.createTBody();
+ assert_array_equals(table.childNodes, [before, tbody, after1]);
+ assert_tbody(tbody);
+}, "A tbody node inside a tfoot child node after a tbody child node");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-table-element/insertRow-method-01.html b/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-table-element/insertRow-method-01.html
new file mode 100644
index 00000000000..4e379a1ccc3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-table-element/insertRow-method-01.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<title>insertRow(): INDEX_SIZE_ERR</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-table-insertrow">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<div id="test">
+<table>
+<tr>
+<td>
+</table>
+</div>
+<script>
+test(function() {
+ var table = document.getElementById("test").getElementsByTagName("table")[0];
+ assert_throws("INDEX_SIZE_ERR", function() {
+ table.insertRow(-2);
+ })
+ assert_throws("INDEX_SIZE_ERR", function() {
+ table.insertRow(2);
+ })
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-table-element/insertRow-method-02.html b/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-table-element/insertRow-method-02.html
new file mode 100644
index 00000000000..410425fb1e7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-table-element/insertRow-method-02.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<title>insertRow(): Empty table</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-table-insertrow">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<div id="test">
+<table></table>
+</div>
+<script>
+var HTML = "http://www.w3.org/1999/xhtml";
+test(function() {
+ var table = document.getElementById("test").getElementsByTagName("table")[0];
+ test(function() {
+ assert_equals(table.childNodes.length, 0);
+ assert_equals(table.rows.length, 0);
+ }, "table should start out empty")
+
+ var tr;
+ test(function() {
+ tr = table.insertRow(0);
+ assert_equals(tr.localName, "tr");
+ assert_equals(tr.namespaceURI, HTML);
+ }, "insertRow should insert a tr element")
+
+ var tbody = tr.parentNode;
+ test(function() {
+ assert_equals(tbody.localName, "tbody");
+ assert_equals(tbody.namespaceURI, HTML);
+ assert_equals(tbody.parentNode, table);
+ }, "insertRow should insert a tbody element")
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-table-element/tBodies.html b/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-table-element/tBodies.html
new file mode 100644
index 00000000000..128dbc9f7d9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-table-element/tBodies.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<title>HTMLTableElement.tBodies</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ var text =
+ '<html xmlns="http://www.w3.org/1999/xhtml">' +
+ ' <head>' +
+ ' <title>Virtual Library</title>' +
+ ' </head>' +
+ ' <body>' +
+ ' <table id="mytable" border="1">' +
+ ' <tbody>' +
+ ' <tr><td>Cell 1</td><td>Cell 2</td></tr>' +
+ ' <tr><td>Cell 3</td><td>Cell 4</td></tr>' +
+ ' </tbody>' +
+ ' </table>' +
+ ' </body>' +
+ '</html>';
+
+ var parser = new DOMParser();
+ var doc = parser.parseFromString(text, "text/xml");
+
+ // import <table>
+ var table = doc.documentElement.getElementsByTagName('table')[0];
+ var mytable = document.body.appendChild(document.importNode(table, true));
+
+ assert_equals(mytable.tBodies.length, 1);
+ var tbody = document.createElement('tbody');
+ mytable.appendChild(tbody);
+ var tr = tbody.insertRow(-1);
+ tr.insertCell(-1).appendChild(document.createTextNode('Cell 5'));
+ tr.insertCell(-1).appendChild(document.createTextNode('Cell 6'));
+ assert_equals(mytable.tBodies.length, 2);
+ assert_equals(mytable.rows.length, 3);
+ assert_equals(tr.rowIndex, 2);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-table-element/table-insertRow.html b/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-table-element/table-insertRow.html
new file mode 100644
index 00000000000..8a9574ecdd4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-table-element/table-insertRow.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>HTMLTableElement.insertRow</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ var HTMLNS = "http://www.w3.org/1999/xhtml"
+ var parentEl = document.createElementNS(HTMLNS, "html:table")
+ assert_equals(parentEl.namespaceURI, HTMLNS, "Parent should be in the HTML namespace")
+ assert_equals(parentEl.prefix, "html", "Parent prefix should be html")
+ assert_equals(parentEl.localName, "table", "Parent local name should be table")
+ assert_equals(parentEl.tagName, "HTML:TABLE", "Parent tag name should be HTML:TABLE")
+
+ var row = parentEl.insertRow(-1)
+ assert_equals(row.namespaceURI, HTMLNS, "Row should be in the HTML namespace")
+ assert_equals(row.prefix, null, "Row prefix should be null")
+ assert_equals(row.localName, "tr", "Row local name should be tr")
+ assert_equals(row.tagName, "TR", "Row tag name should be TR")
+
+ var body = row.parentNode
+ assert_equals(body.namespaceURI, HTMLNS, "Body should be in the HTML namespace")
+ assert_equals(body.prefix, null, "Body prefix should be null")
+ assert_equals(body.localName, "tbody", "Body local name should be tr")
+ assert_equals(body.tagName, "TBODY", "Body tag name should be TR")
+
+ assert_array_equals(parentEl.childNodes, [body])
+ assert_array_equals(body.childNodes, [row])
+ assert_array_equals(parentEl.rows, [row])
+}, "insertRow should not copy prefixes")
+test(function() {
+ var table = document.createElement("table")
+ var head = table.appendChild(document.createElement("thead"))
+ assert_array_equals(table.rows, [])
+
+ var row = table.insertRow(-1)
+ var body = row.parentNode
+ assert_array_equals(table.childNodes, [head, body])
+ assert_array_equals(head.childNodes, [])
+ assert_array_equals(body.childNodes, [row])
+ assert_array_equals(table.rows, [row])
+}, "insertRow should insert into a tbody, not into a thead, if table.rows is empty")
+test(function() {
+ var table = document.createElement("table")
+ var foot = table.appendChild(document.createElement("tfoot"))
+ assert_array_equals(table.rows, [])
+
+ var row = table.insertRow(-1)
+ var body = row.parentNode
+ assert_array_equals(table.childNodes, [foot, body])
+ assert_array_equals(foot.childNodes, [])
+ assert_array_equals(body.childNodes, [row])
+ assert_array_equals(table.rows, [row])
+}, "insertRow should insert into a tbody, not into a tfoot, if table.rows is empty")
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-table-element/table-rows.html b/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-table-element/table-rows.html
new file mode 100644
index 00000000000..c813e0866e6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-table-element/table-rows.html
@@ -0,0 +1,186 @@
+<!DOCTYPE html>
+<title>HTMLTableElement.rows</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+function assert_nodelist_equals(actual, expected) {
+ assert_equals(actual.length, expected.length);
+
+ for (var i = 0; i < actual.length; ++i) {
+ assert_true(i in actual);
+ assert_true(actual.hasOwnProperty(i),
+ "property " + i + " expected to be present on the object");
+ assert_equals(actual.item(i), expected[i]);
+ assert_equals(actual[i], expected[i]);
+ }
+}
+
+function test_table_simple(group, table) {
+ var foo1 = group.appendChild(document.createElement("tr"));
+ foo1.id = "foo";
+ var bar1 = group.appendChild(document.createElement("tr"));
+ bar1.id = "bar";
+ var foo2 = group.appendChild(document.createElement("tr"));
+ foo2.id = "foo";
+ var bar2 = group.appendChild(document.createElement("tr"));
+ bar2.id = "bar";
+
+ assert_true(table.rows instanceof HTMLCollection, "table.rows should be a HTMLCollection.");
+ assert_nodelist_equals(table.rows, [foo1, bar1, foo2, bar2]);
+ assert_equals(table.rows.foo, foo1);
+ assert_equals(table.rows["foo"], foo1);
+ assert_equals(table.rows.namedItem("foo"), foo1);
+ assert_equals(table.rows.bar, bar1);
+ assert_equals(table.rows["bar"], bar1);
+ assert_equals(table.rows.namedItem("bar"), bar1);
+}
+test(function() {
+ var table = document.createElement("table");
+ test_table_simple(table, table);
+}, "Children of table");
+test(function() {
+ var table = document.createElement("table");
+ var group = table.appendChild(document.createElement("thead"));
+ test_table_simple(group, table);
+}, "Children of thead");
+test(function() {
+ var table = document.createElement("table");
+ var group = table.appendChild(document.createElement("tbody"));
+ test_table_simple(group, table);
+}, "Children of tbody");
+test(function() {
+ var table = document.createElement("table");
+ var group = table.appendChild(document.createElement("tfoot"));
+ test_table_simple(group, table);
+}, "Children of tfoot");
+test(function() {
+ var table = document.createElement("table");
+ var orphan1 = table.appendChild(document.createElement("tr"));
+ orphan1.id = "orphan1";
+ var foot1 = table.appendChild(document.createElement("tfoot"));
+ var orphan2 = table.appendChild(document.createElement("tr"));
+ orphan2.id = "orphan2";
+ var foot2 = table.appendChild(document.createElement("tfoot"));
+ var orphan3 = table.appendChild(document.createElement("tr"));
+ orphan3.id = "orphan3";
+ var body1 = table.appendChild(document.createElement("tbody"));
+ var orphan4 = table.appendChild(document.createElement("tr"));
+ orphan4.id = "orphan4";
+ var body2 = table.appendChild(document.createElement("tbody"));
+ var orphan5 = table.appendChild(document.createElement("tr"));
+ orphan5.id = "orphan5";
+ var head1 = table.appendChild(document.createElement("thead"));
+ var orphan6 = table.appendChild(document.createElement("tr"));
+ orphan6.id = "orphan6";
+ var head2 = table.appendChild(document.createElement("thead"));
+ var orphan7 = table.appendChild(document.createElement("tr"));
+ orphan7.id = "orphan7";
+
+ var foot1row1 = foot1.appendChild(document.createElement("tr"));
+ foot1row1.id = "foot1row1";
+ var foot1row2 = foot1.appendChild(document.createElement("tr"));
+ foot1row2.id = "foot1row2";
+ var foot2row1 = foot2.appendChild(document.createElement("tr"));
+ foot2row1.id = "foot2row1";
+ var foot2row2 = foot2.appendChild(document.createElement("tr"));
+ foot2row2.id = "foot2row2";
+
+ var body1row1 = body1.appendChild(document.createElement("tr"));
+ body1row1.id = "body1row1";
+ var body1row2 = body1.appendChild(document.createElement("tr"));
+ body1row2.id = "body1row2";
+ var body2row1 = body2.appendChild(document.createElement("tr"));
+ body2row1.id = "body2row1";
+ var body2row2 = body2.appendChild(document.createElement("tr"));
+ body2row2.id = "body2row2";
+
+ var head1row1 = head1.appendChild(document.createElement("tr"));
+ head1row1.id = "head1row1";
+ var head1row2 = head1.appendChild(document.createElement("tr"));
+ head1row2.id = "head1row2";
+ var head2row1 = head2.appendChild(document.createElement("tr"));
+ head2row1.id = "head2row1";
+ var head2row2 = head2.appendChild(document.createElement("tr"));
+ head2row2.id = "head2row2";
+
+ // These elements should not end up in any collection.
+ table.appendChild(document.createElement("div"))
+ .appendChild(document.createElement("tr"));
+ foot1.appendChild(document.createElement("div"))
+ .appendChild(document.createElement("tr"));
+ body1.appendChild(document.createElement("div"))
+ .appendChild(document.createElement("tr"));
+ head1.appendChild(document.createElement("div"))
+ .appendChild(document.createElement("tr"));
+ table.appendChild(document.createElementNS("http://example.com/test", "tr"));
+ foot1.appendChild(document.createElementNS("http://example.com/test", "tr"));
+ body1.appendChild(document.createElementNS("http://example.com/test", "tr"));
+ head1.appendChild(document.createElementNS("http://example.com/test", "tr"));
+
+ assert_true(table.rows instanceof HTMLCollection, "table.rows should be a HTMLCollection.");
+ assert_nodelist_equals(table.rows, [
+ // thead
+ head1row1,
+ head1row2,
+ head2row1,
+ head2row2,
+
+ // tbody + table
+ orphan1,
+ orphan2,
+ orphan3,
+ body1row1,
+ body1row2,
+ orphan4,
+ body2row1,
+ body2row2,
+ orphan5,
+ orphan6,
+ orphan7,
+
+ // tfoot
+ foot1row1,
+ foot1row2,
+ foot2row1,
+ foot2row2
+ ]);
+
+ var ids = [
+ "orphan1",
+ "orphan2",
+ "orphan3",
+ "orphan4",
+ "orphan5",
+ "orphan6",
+ "orphan7",
+ "foot1row1",
+ "foot1row2",
+ "foot2row1",
+ "foot2row2",
+ "body1row1",
+ "body1row2",
+ "body2row1",
+ "body2row2",
+ "head1row1",
+ "head1row2",
+ "head2row1",
+ "head2row2"
+ ];
+ ids.forEach(function(id) {
+ assert_equals(table.rows.namedItem(id).id, id);
+ assert_true(id in table.rows);
+ assert_equals(table.rows[id].id, id);
+ assert_true(id in table.rows);
+ });
+ while (table.firstChild) {
+ table.removeChild(table.firstChild);
+ }
+ ids.forEach(function(id) {
+ assert_equals(table.rows.namedItem(id), null);
+ assert_false(id in table.rows);
+ assert_equals(table.rows[id], undefined);
+ assert_false(id in table.rows);
+ });
+}, "Complicated case");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-tbody-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-tbody-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-tbody-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-td-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-td-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-td-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-tfoot-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-tfoot-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-tfoot-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-th-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-th-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-th-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-thead-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-thead-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-thead-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-tr-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-tr-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-tr-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-tr-element/rowIndex.html b/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-tr-element/rowIndex.html
new file mode 100644
index 00000000000..117712563d5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-tr-element/rowIndex.html
@@ -0,0 +1,77 @@
+<!DOCTYPE html>
+<title>HTMLTableRowElement.rowIndex</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ var row = document.createElement("table")
+ .appendChild(document.createElement("div"))
+ .appendChild(document.createElement("tr"));
+ assert_equals(row.rowIndex, -1);
+});
+test(function() {
+ var row = document.createElement("table")
+ .appendChild(document.createElement("thead"))
+ .appendChild(document.createElement("tr"));
+ assert_equals(row.rowIndex, 0);
+});
+test(function() {
+ var row = document.createElement("table")
+ .appendChild(document.createElement("tbody"))
+ .appendChild(document.createElement("tr"));
+ assert_equals(row.rowIndex, 0);
+});
+test(function() {
+ var row = document.createElement("table")
+ .appendChild(document.createElement("tfoot"))
+ .appendChild(document.createElement("tr"));
+ assert_equals(row.rowIndex, 0);
+});
+test(function() {
+ var row = document.createElement("table")
+ .appendChild(document.createElement("tr"));
+ assert_equals(row.rowIndex, 0);
+});
+test(function() {
+ var row = document.createElementNS("", "table")
+ .appendChild(document.createElement("thead"))
+ .appendChild(document.createElement("tr"));
+ assert_equals(row.rowIndex, -1);
+});
+test(function() {
+ var row = document.createElementNS("", "table")
+ .appendChild(document.createElement("tbody"))
+ .appendChild(document.createElement("tr"));
+ assert_equals(row.rowIndex, -1);
+});
+test(function() {
+ var row = document.createElementNS("", "table")
+ .appendChild(document.createElement("tfoot"))
+ .appendChild(document.createElement("tr"));
+ assert_equals(row.rowIndex, -1);
+});
+test(function() {
+ var row = document.createElementNS("", "table")
+ .appendChild(document.createElement("tr"));
+ assert_equals(row.rowIndex, -1);
+});
+test(function() {
+ var row = document.createElement("table")
+ .appendChild(document.createElementNS("", "thead"))
+ .appendChild(document.createElement("tr"));
+ assert_equals(row.rowIndex, -1);
+});
+test(function() {
+ var row = document.createElement("table")
+ .appendChild(document.createElementNS("", "tbody"))
+ .appendChild(document.createElement("tr"));
+ assert_equals(row.rowIndex, -1);
+});
+test(function() {
+ var row = document.createElement("table")
+ .appendChild(document.createElementNS("", "tfoot"))
+ .appendChild(document.createElement("tr"));
+ assert_equals(row.rowIndex, -1);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-tr-element/sectionRowIndex.html b/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-tr-element/sectionRowIndex.html
new file mode 100644
index 00000000000..ef5366739e9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/tabular-data/the-tr-element/sectionRowIndex.html
@@ -0,0 +1,130 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>HTMLTableRowElement.sectionRowIndex</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<table>
+ <thead>
+ <tr id="ht1"></tr>
+ </thead>
+ <tr id="t1"></tr>
+ <tr id="t2">
+ <td>
+ <table>
+ <thead>
+ <tr id="nht1"></tr>
+ </thead>
+ <tr></tr>
+ <tr id="nt1"></tr>
+ <tbody>
+ <tr id="nbt1"></tr>
+ </tbody>
+ </table>
+ </td>
+ </tr>
+ <tbody>
+ <tr></tr>
+ <tr id="bt1"></tr>
+ </tbody>
+ <tfoot>
+ <tr></tr>
+ <tr></tr>
+ <tr id="ft1"></tr>
+ </tfoot>
+</table>
+
+<script>
+test(function() {
+ var tHeadRow = document.getElementById('ht1');
+ assert_equals(tHeadRow.sectionRowIndex, 0);
+}, "Row in thead in HTML");
+
+test(function() {
+ var tRow1 = document.getElementById('t1');
+ assert_equals(tRow1.sectionRowIndex, 0);
+}, "Row in implicit tbody in HTML");
+
+test(function() {
+ var tRow2 = document.getElementById('t2');
+ assert_equals(tRow2.sectionRowIndex, 1);
+}, "Other row in implicit tbody in HTML");
+
+test(function() {
+ var tBodyRow = document.getElementById('bt1');
+ assert_equals(tBodyRow.sectionRowIndex, 1);
+}, "Row in explicit tbody in HTML");
+
+test(function() {
+ var tFootRow = document.getElementById('ft1');
+ assert_equals(tFootRow.sectionRowIndex, 2);
+}, "Row in tfoot in HTML");
+
+test(function() {
+ var childHeadRow = document.getElementById('nht1');
+ assert_equals(childHeadRow.sectionRowIndex, 0);
+}, "Row in thead in nested table in HTML");
+
+test(function() {
+ var childRow = document.getElementById('nt1');
+ assert_equals(childRow.sectionRowIndex, 1);
+}, "Row in implicit tbody in nested table in HTML");
+
+test(function() {
+ var childBodyRow = document.getElementById('nbt1');
+ assert_equals(childBodyRow.sectionRowIndex, 0);
+}, "Row in explicit tbody in nested table in HTML");
+
+/* script create element test */
+var mkTrElm = function (elst) {
+ var elm = document.createElement("table");
+ elst.forEach(function(item) {
+ elm = elm.appendChild(document.createElement(item));
+ });
+ return elm.appendChild(document.createElement("tr"));
+};
+
+test(function() {
+ assert_equals(mkTrElm([]).sectionRowIndex, 0);
+}, "Row in script-created table");
+
+test(function() {
+ assert_equals(mkTrElm(["div"]).sectionRowIndex, -1);
+}, "Row in script-created div in table");
+
+test(function() {
+ assert_equals(mkTrElm(["thead"]).sectionRowIndex, 0);
+}, "Row in script-created thead in table");
+
+test(function() {
+ assert_equals(mkTrElm(["tbody"]).sectionRowIndex, 0);
+}, "Row in script-created tbody in table");
+
+test(function() {
+ assert_equals(mkTrElm(["tfoot"]).sectionRowIndex, 0);
+}, "Row in script-created tfoot in table");
+
+test(function() {
+ assert_equals(mkTrElm(["tbody", "tr"]).sectionRowIndex, -1);
+}, "Row in script-created tr in tbody in table");
+
+test(function() {
+ assert_equals(mkTrElm(["tbody", "tr", "td"]).sectionRowIndex, -1);
+}, "Row in script-created td in tr in tbody in table");
+
+test(function() {
+ assert_equals(mkTrElm(["tbody", "tr", "td", "table"]).sectionRowIndex, 0);
+}, "Row in script-created nested table");
+
+test(function() {
+ assert_equals(mkTrElm(["tbody", "tr", "td", "table", "thead"]).sectionRowIndex, 0);
+}, "Row in script-created thead in nested table");
+
+test(function() {
+ assert_equals(mkTrElm(["tbody", "tr", "td", "table", "tbody"]).sectionRowIndex, 0);
+}, "Row in script-created tbody in nested table");
+
+test(function() {
+ assert_equals(mkTrElm(["tbody", "tr", "td", "table", "tfoot"]).sectionRowIndex, 0);
+}, "Row in script-created tfoot in nested table");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-a-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-a-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-a-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-a-element/a-stringifier.html b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-a-element/a-stringifier.html
new file mode 100644
index 00000000000..fb0780dee81
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-a-element/a-stringifier.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<title>HTMLAnchorElement stringifier</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://heycam.github.io/webidl/#es-stringifier">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=/common/stringifiers.js></script>
+<div id=log></div>
+<script>
+test(function() {
+ test_stringifier_attribute(document.createElement("a"), "href", false);
+ var a = document.createElement("a");
+ a.setAttribute("href", "foo");
+ test_stringifier_attribute(a, "href", false);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-a-element/a.text-getter-01.html b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-a-element/a.text-getter-01.html
new file mode 100644
index 00000000000..e0bb73be0ff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-a-element/a.text-getter-01.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<title>HTMLAnchorElement.text getting</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-a-text">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>var b</script>
+<div id="test">
+<a href="a">a b c </a>
+<a href="b">a <!--b-->b c </a>
+<a href="c">a <b>b</b> c </a>
+<a href="d">a <script>b</script> c </a>
+<script>
+var e = document.getElementById("test")
+ .appendChild(document.createElement("a"));
+e.href = "d";
+e.appendChild(document.createTextNode("a "));
+e.appendChild(document.createTextNode("b "));
+e.appendChild(document.createTextNode("c "));
+</script>
+</div>
+<script>
+test(function() {
+ var list = document.getElementById("test")
+ .getElementsByTagName("a");
+ for (var i = 0, il = list.length; i < il; ++i) {
+ test(function() {
+ assert_equals(list[i].text, list[i].textContent);
+ assert_equals(list[i].text, "a b c ");
+ }, "Test for anchor " + i);
+ }
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-a-element/a.text-setter-01.html b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-a-element/a.text-setter-01.html
new file mode 100644
index 00000000000..879a9e3d08b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-a-element/a.text-setter-01.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<title>HTMLAnchorElement.text setting</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-a-text">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<div id="test">
+<a href="a">a b c</a>
+<a href="b">a <!--b--> c</a>
+<a href="c">a <b>b</b> c</a>
+<script>
+var d = document.getElementById("test")
+ .appendChild(document.createElement("a"));
+d.href = "d";
+d.appendChild(document.createTextNode("a "));
+d.appendChild(document.createTextNode("b "));
+d.appendChild(document.createTextNode("c "));
+</script>
+</div>
+<script>
+test(function() {
+ var list = document.getElementById("test")
+ .getElementsByTagName("a");
+ for (var i = 0, il = list.length; i < il; ++i) {
+ test(function() {
+ list[i].text = "x";
+ assert_equals(list[i].text, "x");
+ assert_equals(list[i].textContent, "x");
+ assert_equals(list[i].firstChild.data, "x");
+ assert_equals(list[i].childNodes.length, 1);
+
+ list[i].textContent = "y";
+ assert_equals(list[i].text, "y");
+ assert_equals(list[i].textContent, "y");
+ assert_equals(list[i].firstChild.data, "y");
+ assert_equals(list[i].childNodes.length, 1);
+ }, "Test for anchor " + i);
+ }
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-abbr-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-abbr-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-abbr-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-b-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-b-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-b-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-auto-dir-default-ref.html b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-auto-dir-default-ref.html
new file mode 100644
index 00000000000..eff61bb4196
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-auto-dir-default-ref.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com">
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com">
+ <style>
+ body{
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 500px;
+ margin: 20px;
+ }
+ .comments { display: none; }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; ... &#x05D5; - The first six Hebrew letters (strongly RTL).
+ &#x202D; - The LRO (left-to-right override) formatting character.
+ &#x202C; - The PDF (pop directional formatting) formatting character; closes LRO.
+ </div>
+ <div class="test">
+ <div dir="ltr">&#x202D;[:)], [+- a &#x05D1;], [d &#x05D2; 1]...&#x202C;</div>
+ <div dir="rtl">&#x202D;...[d &#x05D2; 1] ,[+- a &#x05D1;] ,[:)]&#x202C;</div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">&#x202D;[:)], [+- a &#x05D1;], [d &#x05D2; 1]...&#x202C;</div>
+ <div dir="rtl">&#x202D;...[d &#x05D2; 1] ,[+- a &#x05D1;] ,[:)]&#x202C;</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-auto-dir-default.html b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-auto-dir-default.html
new file mode 100644
index 00000000000..e658500a4eb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-auto-dir-default.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8"/>
+ <title>HTML Test: BDI: has dir=auto by default</title>
+ <link rel="match" href="bdi-auto-dir-default-ref.html"/>
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com"/>
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com"/>
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-bdi-element"/>
+ <meta name="assert" content="
+ 'The dir global attribute defaults to auto on this element (it never inherits from the parent
+ element like with other elements).'"/>
+ <style>
+ body{
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 500px;
+ margin: 20px;
+ }
+ .comments { display: none; }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; ... &#x05D5; - The first six Hebrew letters (strongly RTL).
+ &#x202D; - The LRO (left-to-right override) formatting character.
+ &#x202C; - The PDF (pop directional formatting) formatting character; closes LRO.
+ In each DIV of the test:
+ - the first BDI, having no characters with strong direction, should be LTR by default;
+ - the second BDI, having an LTR character first, should be LTR by default;
+ - the third BDI, having an RTL character first, should be RTL by default.
+ </div>
+ <div class="test">
+ <div dir="ltr"><bdi>[:)]</bdi>, <bdi>[+- a &#x05D1;]</bdi>, <bdi>[1 &#x05D2; d]</bdi>...</div>
+ <div dir="rtl"><bdi>[:)]</bdi>, <bdi>[+- a &#x05D1;]</bdi>, <bdi>[1 &#x05D2; d]</bdi>...</div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">&#x202D;[:)], [+- a &#x05D1;], [d &#x05D2; 1]...&#x202C;</div>
+ <div dir="rtl">&#x202D;...[d &#x05D2; 1] ,[+- a &#x05D1;] ,[:)]&#x202C;</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-missing-pdf-ref.html b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-missing-pdf-ref.html
new file mode 100644
index 00000000000..b4d44c51011
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-missing-pdf-ref.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com">
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com">
+ <style>
+ body{
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments { display: none; }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; ... &#x05D5; - The first six Hebrew letters (strongly RTL).
+ &#x202D; - The LRO (left-to-right override) formatting character.
+ &#x202C; - The PDF (pop directional formatting) formatting character; closes LRO.
+ </div>
+ <div class="test">
+ <div dir="ltr">&#x202D;cb&#x05D0;de...&#x202C;</div>
+ <div dir="ltr">&#x202D;cb&#x05D0;de...&#x202C;</div>
+ <div dir="ltr">&#x202D;cb&#x05D0;de...&#x202C;</div>
+ <div dir="rtl">&#x202D;...&#x05D4;&#x05D3;a&#x05D1;&#x05D2;&#x202C;</div>
+ <div dir="rtl">&#x202D;...&#x05D4;&#x05D3;a&#x05D1;&#x05D2;&#x202C;</div>
+ <div dir="rtl">&#x202D;...&#x05D4;&#x05D3;a&#x05D1;&#x05D2;&#x202C;</div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">&#x202D;cb&#x05D0;de...&#x202C;</div>
+ <div dir="ltr">&#x202D;cb&#x05D0;de...&#x202C;</div>
+ <div dir="ltr">&#x202D;cb&#x05D0;de...&#x202C;</div>
+ <div dir="rtl">&#x202D;...&#x05D4;&#x05D3;a&#x05D1;&#x05D2;&#x202C;</div>
+ <div dir="rtl">&#x202D;...&#x05D4;&#x05D3;a&#x05D1;&#x05D2;&#x202C;</div>
+ <div dir="rtl">&#x202D;...&#x05D4;&#x05D3;a&#x05D1;&#x05D2;&#x202C;</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-missing-pdf.html b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-missing-pdf.html
new file mode 100644
index 00000000000..1ce9da6b769
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-missing-pdf.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8"/>
+ <title>HTML Test: BDI: neutral when contains LRO or RLO without PDF</title>
+ <link rel="match" href="bdi-neutral-missing-pdf-ref.html"/>
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com"/>
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com"/>
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-bdi-element"/>
+ <meta name="assert" content="
+ 'For the purposes of applying the bidirectional algorithm to the paragraph-level
+ container that a bdi element finds itself within, the bdi element must be treated
+ like a U+FFFC OBJECT REPLACEMENT CHARACTER.'
+ Thus, if a BDI contains LRO or RLO characters lacking a matching PDF, these must not affect
+ the visual ordering of the content outside the BDI."/>
+ <style>
+ body{
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments { display: none; }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; ... &#x05D5; - The first six Hebrew letters (strongly RTL).
+ &#x202D; - The LRO (left-to-right override) formatting character.
+ &#x202E; - the RLO (right-to-left-override) formatting character.
+ &#x202C; - The PDF (pop directional formatting) formatting character; closes LRO and RLO.
+ If the BDI in the test's first DIV were a SPAN, the RLO it contains, not being closed by a
+ PDF, would visually reorder the de into ed.
+ </div>
+ <div class="test">
+ <div dir="ltr"><bdi>&#x05D0;&#x202E;bc</bdi>de...</div>
+ <div dir="ltr"><bdi dir="ltr">&#x05D0;&#x202E;bc</bdi>de...</div>
+ <div dir="ltr"><bdi dir="rtl">&#x05D0;&#x202E;bc</bdi>de...</div>
+ <div dir="rtl"><bdi>a&#x202D;&#x05D1;&#x05D2;</bdi>&#x05D3;&#x05D4;...</div>
+ <div dir="rtl"><bdi dir="ltr">a&#x202D;&#x05D1;&#x05D2;</bdi>&#x05D3;&#x05D4;...</div>
+ <div dir="rtl"><bdi dir="rtl">a&#x202D;&#x05D1;&#x05D2;</bdi>&#x05D3;&#x05D4;...</div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">&#x202D;cb&#x05D0;de...&#x202C;</div>
+ <div dir="ltr">&#x202D;cb&#x05D0;de...&#x202C;</div>
+ <div dir="ltr">&#x202D;cb&#x05D0;de...&#x202C;</div>
+ <div dir="rtl">&#x202D;...&#x05D4;&#x05D3;a&#x05D1;&#x05D2;&#x202C;</div>
+ <div dir="rtl">&#x202D;...&#x05D4;&#x05D3;a&#x05D1;&#x05D2;&#x202C;</div>
+ <div dir="rtl">&#x202D;...&#x05D4;&#x05D3;a&#x05D1;&#x05D2;&#x202C;</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-nested-ref.html b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-nested-ref.html
new file mode 100644
index 00000000000..d5d7674a45e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-nested-ref.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com">
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com">
+ <style>
+ body{
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 500px;
+ margin: 20px;
+ }
+ .comments { display: none; }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; ... &#x05D5; - The first six Hebrew letters (strongly RTL).
+ &#x202D; - The LRO (left-to-right override) formatting character.
+ &#x202C; - The PDF (pop directional formatting) formatting character; closes LRO.
+ </div>
+ <div class="test">
+ <div dir="ltr">&#x202D;1 + [a + [3 + [b + 4] + &#x05D1;] + 2] + &#x05D0;&#x202C;</div>
+ <div dir="ltr">&#x202D;1 + [a + [3 + [b + 4] + &#x05D1;] + 2] + &#x05D0;&#x202C;</div>
+ <div dir="ltr">&#x202D;1 + [a + [3 + [b + 4] + &#x05D1;] + 2] + &#x05D0;&#x202C;</div>
+ <div dir="rtl">&#x202D;a + [1 + [b + [3 + &#x05D1;] + 2] + &#x05D0;] + 0&#x202C;</div>
+ <div dir="rtl">&#x202D;a + [1 + [b + [3 + &#x05D1;] + 2] + &#x05D0;] + 0&#x202C;</div>
+ <div dir="rtl">&#x202D;a + [1 + [b + [3 + &#x05D1;] + 2] + &#x05D0;] + 0&#x202C;</div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">&#x202D;1 + [a + [3 + [b + 4] + &#x05D1;] + 2] + &#x05D0;&#x202C;</div>
+ <div dir="ltr">&#x202D;1 + [a + [3 + [b + 4] + &#x05D1;] + 2] + &#x05D0;&#x202C;</div>
+ <div dir="ltr">&#x202D;1 + [a + [3 + [b + 4] + &#x05D1;] + 2] + &#x05D0;&#x202C;</div>
+ <div dir="rtl">&#x202D;a + [1 + [b + [3 + &#x05D1;] + 2] + &#x05D0;] + 0&#x202C;</div>
+ <div dir="rtl">&#x202D;a + [1 + [b + [3 + &#x05D1;] + 2] + &#x05D0;] + 0&#x202C;</div>
+ <div dir="rtl">&#x202D;a + [1 + [b + [3 + &#x05D1;] + 2] + &#x05D0;] + 0&#x202C;</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-nested.html b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-nested.html
new file mode 100644
index 00000000000..158576885c8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-nested.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8"/>
+ <title>HTML Test: BDI: neutral when nested</title>
+ <link rel="match" href="bdi-neutral-nested-ref.html"/>
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com"/>
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com"/>
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-bdi-element"/>
+ <meta name="assert" content="
+ 'For the purposes of applying the bidirectional algorithm to the paragraph-level
+ container that a bdi element finds itself within, the bdi element must be treated
+ like a U+FFFC OBJECT REPLACEMENT CHARACTER.'
+ This must apply when a BDI is nested within a BDI."/>
+ <style>
+ body{
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 500px;
+ margin: 20px;
+ }
+ .comments { display: none; }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; ... &#x05D5; - The first six Hebrew letters (strongly RTL).
+ &#x202D; - The LRO (left-to-right override) formatting character.
+ &#x202C; - The PDF (pop directional formatting) formatting character; closes LRO.
+ </div>
+ <div class="test">
+ <div dir="ltr">&#x05D0; + <bdi>[a + <bdi>[&#x05D1; + <bdi>[b + 4]</bdi> + 3]</bdi> + 2]</bdi> + 1</div>
+ <div dir="ltr">&#x05D0; + <bdi dir="rtl">[a + <bdi dir="ltr">[&#x05D1; + <bdi dir="rtl">[b + 4]</bdi> + 3]</bdi> + 2]</bdi> + 1</div>
+ <div dir="ltr">&#x05D0; + <bdi dir="ltr">[a + <bdi dir="rtl">[&#x05D1; + <bdi dir="ltr">[b + 4]</bdi> + 3]</bdi> + 2]</bdi> + 1</div>
+ <div dir="rtl">a + <bdi>[&#x05D0; + <bdi>[b + <bdi>[&#x05D1; + 3]</bdi> + 2]</bdi> + 1]</bdi> + 0</div>
+ <div dir="rtl">a + <bdi dir="ltr">[&#x05D0; + <bdi dir="rtl">[b + <bdi dir="ltr">[&#x05D1; + 3]</bdi> + 2]</bdi> + 1]</bdi> + 0</div>
+ <div dir="rtl">a + <bdi dir="rtl">[&#x05D0; + <bdi dir="ltr">[b + <bdi dir="rtl">[&#x05D1; + 3]</bdi> + 2]</bdi> + 1]</bdi> + 0</div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">&#x202D;1 + [a + [3 + [b + 4] + &#x05D1;] + 2] + &#x05D0;&#x202C;</div>
+ <div dir="ltr">&#x202D;1 + [a + [3 + [b + 4] + &#x05D1;] + 2] + &#x05D0;&#x202C;</div>
+ <div dir="ltr">&#x202D;1 + [a + [3 + [b + 4] + &#x05D1;] + 2] + &#x05D0;&#x202C;</div>
+ <div dir="rtl">&#x202D;a + [1 + [b + [3 + &#x05D1;] + 2] + &#x05D0;] + 0&#x202C;</div>
+ <div dir="rtl">&#x202D;a + [1 + [b + [3 + &#x05D1;] + 2] + &#x05D0;] + 0&#x202C;</div>
+ <div dir="rtl">&#x202D;a + [1 + [b + [3 + &#x05D1;] + 2] + &#x05D0;] + 0&#x202C;</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-number-ref.html b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-number-ref.html
new file mode 100644
index 00000000000..df7af7778af
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-number-ref.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com">
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com">
+ <style>
+ body{
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments { display: none; }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; ... &#x05D5; - The first six Hebrew letters (strongly RTL).
+ &#x202D; - The LRO (left-to-right override) formatting character.
+ &#x202C; - The PDF (pop directional formatting) formatting character; closes LRO.
+ </div>
+ <div class="test">
+ <div dir="ltr">&#x202D;&#x05D0; - [1]...&#x202C;</div>
+ <div dir="ltr">&#x202D;&#x05D0; - [1]...&#x202C;</div>
+ <div dir="ltr">&#x202D;&#x05D0; - [1]...&#x202C;</div>
+ <div dir="rtl">&#x202D;...[1] - a&#x202C;</div>
+ <div dir="rtl">&#x202D;...[1] - a&#x202C;</div>
+ <div dir="rtl">&#x202D;...[1] - a&#x202C;</div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">&#x202D;&#x05D0; - [1]...&#x202C;</div>
+ <div dir="ltr">&#x202D;&#x05D0; - [1]...&#x202C;</div>
+ <div dir="ltr">&#x202D;&#x05D0; - [1]...&#x202C;</div>
+ <div dir="rtl">&#x202D;...[1] - a&#x202C;</div>
+ <div dir="rtl">&#x202D;...[1] - a&#x202C;</div>
+ <div dir="rtl">&#x202D;...[1] - a&#x202C;</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-number.html b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-number.html
new file mode 100644
index 00000000000..37e467c173c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-number.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8"/>
+ <title>HTML Test: BDI: neutral when number</title>
+ <link rel="match" href="bdi-neutral-number-ref.html"/>
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com"/>
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com"/>
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-bdi-element"/>
+ <meta name="assert" content="
+ 'For the purposes of applying the bidirectional algorithm to the paragraph-level
+ container that a bdi element finds itself within, the bdi element must be treated
+ like a U+FFFC OBJECT REPLACEMENT CHARACTER.'"/>
+ <style>
+ body{
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments { display: none; }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; ... &#x05D5; - The first six Hebrew letters (strongly RTL).
+ &#x202D; - The LRO (left-to-right override) formatting character.
+ &#x202C; - The PDF (pop directional formatting) formatting character; closes LRO.
+ If the BDI in the test's first DIV were a SPAN, the 1 inside it would be visually ordered
+ to the left of the &#x05D0;.
+ </div>
+ <div class="test">
+ <div dir="ltr">&#x05D0; - <bdi>[1]</bdi>...</div>
+ <div dir="ltr">&#x05D0; - <bdi dir="ltr">[1]</bdi>...</div>
+ <div dir="ltr">&#x05D0; - <bdi dir="rtl">[1]</bdi>...</div>
+ <div dir="rtl">a - <bdi>[1]</bdi>...</div>
+ <div dir="rtl">a - <bdi dir="ltr">[1]</bdi>...</div>
+ <div dir="rtl">a - <bdi dir="rtl">[1]</bdi>...</div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">&#x202D;&#x05D0; - [1]...&#x202C;</div>
+ <div dir="ltr">&#x202D;&#x05D0; - [1]...&#x202C;</div>
+ <div dir="ltr">&#x202D;&#x05D0; - [1]...&#x202C;</div>
+ <div dir="rtl">&#x202D;...[1] - a&#x202C;</div>
+ <div dir="rtl">&#x202D;...[1] - a&#x202C;</div>
+ <div dir="rtl">&#x202D;...[1] - a&#x202C;</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-separate-ref.html b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-separate-ref.html
new file mode 100644
index 00000000000..ec8e34627d8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-separate-ref.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com">
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com">
+ <style>
+ body{
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 500px;
+ margin: 20px;
+ }
+ .comments { display: none; }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; ... &#x05D5; - The first six Hebrew letters (strongly RTL).
+ &#x202D; - The LRO (left-to-right override) formatting character.
+ &#x202C; - The PDF (pop directional formatting) formatting character; closes LRO.
+ </div>
+ <div class="test">
+ <div dir="ltr">&#x202D;&#x05D0; [1 b] c [d &#x05D4;] &#x05D5;...&#x202C;</div>
+ <div dir="rtl">&#x202D;...f [e &#x05D3;] &#x05D2; [&#x05D1; 1] a&#x202C;</div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">&#x202D;&#x05D0; [1 b] c [d &#x05D4;] &#x05D5;...&#x202C;</div>
+ <div dir="rtl">&#x202D;...f [e &#x05D3;] &#x05D2; [&#x05D1; 1] a&#x202C;</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-separate.html b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-separate.html
new file mode 100644
index 00000000000..7bb8a20811a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-separate.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8"/>
+ <title>HTML Test: BDI: paragraph-level container</title>
+ <link rel="match" href="bdi-neutral-separate-ref.html"/>
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com"/>
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com"/>
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-bdi-element"/>
+ <meta name="assert" content="
+ 'For the purposes of applying the bidirectional algorithm to the paragraph-level
+ container that a bdi element finds itself within, the bdi element must be treated
+ like a U+FFFC OBJECT REPLACEMENT CHARACTER.'
+ Thus, under no circumstances should any part of the content outside a BDI be visually
+ reordered inside the BDI's content."/>
+ <style>
+ body{
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 500px;
+ margin: 20px;
+ }
+ .comments { display: none; }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; ... &#x05D5; - The first six Hebrew letters (strongly RTL).
+ &#x202D; - The LRO (left-to-right override) formatting character.
+ &#x202C; - The PDF (pop directional formatting) formatting character; closes LRO.
+ If the BDIs in the test's first DIV were just SPANs, the &#x05D0; would appear between the 1
+ and the b, and the &#x05D5; between the d and the &#x05D4;.
+ </div>
+ <div class="test">
+ <div dir="ltr">&#x05D0; <bdi>[1 b]</bdi> c <bdi>[d &#x05D4;]</bdi> &#x05D5;...</div>
+ <div dir="rtl">a <bdi>[1 &#x05D1;]</bdi> &#x05D2; <bdi>[&#x05D3; e]</bdi> f...</div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">&#x202D;&#x05D0; [1 b] c [d &#x05D4;] &#x05D5;...&#x202C;</div>
+ <div dir="rtl">&#x202D;...f [e &#x05D3;] &#x05D2; [&#x05D1; 1] a&#x202C;</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-another-bdi-1-ref.html b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-another-bdi-1-ref.html
new file mode 100644
index 00000000000..c0f323ea2c8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-another-bdi-1-ref.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com" />
+ <link rel="author" title="Shai Berger" href="mailto:shai@platonix.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <style>
+ body{
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions">Test passes if the two boxes below look exactly the same.</div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; ... &#x05D5; - The first six Hebrew letters (strongly RTL).
+ &#x202D; - The LRO (left-to-right override) formatting character.
+ &#x202C; - The PDF (pop directional formatting) formatting character; closes LRO.
+ </div>
+ <div class="test">
+ <div dir="ltr">&#x202D;[&#x05D0;] &gt; [&#x05D1;]...&#x202C;</div>
+ <div dir="ltr">&#x202D;[&#x05D0;] &gt; [&#x05D1;]...&#x202C;</div>
+ <div dir="ltr">&#x202D;[&#x05D0;] &gt; [&#x05D1;]...&#x202C;</div>
+ <div dir="rtl">&#x202D;...[b] &lt; [a]&#x202C;</div>
+ <div dir="rtl">&#x202D;...[b] &lt; [a]&#x202C;</div>
+ <div dir="rtl">&#x202D;...[b] &lt; [a]&#x202C;</div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">&#x202D;[&#x05D0;] &gt; [&#x05D1;]...&#x202C;</div>
+ <div dir="ltr">&#x202D;[&#x05D0;] &gt; [&#x05D1;]...&#x202C;</div>
+ <div dir="ltr">&#x202D;[&#x05D0;] &gt; [&#x05D1;]...&#x202C;</div>
+ <div dir="rtl">&#x202D;...[b] &lt; [a]&#x202C;</div>
+ <div dir="rtl">&#x202D;...[b] &lt; [a]&#x202C;</div>
+ <div dir="rtl">&#x202D;...[b] &lt; [a]&#x202C;</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-another-bdi-1.html b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-another-bdi-1.html
new file mode 100644
index 00000000000..822120721fe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-another-bdi-1.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: BDI: neutral to another BDI</title>
+ <link rel="match" href="bdi-neutral-to-another-bdi-1-ref.html" />
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com" />
+ <link rel="author" title="Shai Berger" href="mailto:shai@platonix.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-bdi-element" />
+ <meta name="assert" content="
+ 'For the purposes of applying the bidirectional algorithm to the paragraph-level
+ container that a bdi element finds itself within, the bdi element must be treated
+ like a U+FFFC OBJECT REPLACEMENT CHARACTER.'
+ Thus, when a BDI contains text of the same strong direction as another BDI following it, the
+ two must not form a directional run as would be the case if the BDIs were just SPANs." />
+ <style>
+ body{
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions">Test passes if the two boxes below look exactly the same.</div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; ... &#x05D5; - The first six Hebrew letters (strongly RTL).
+ &#x202D; - The LRO (left-to-right override) formatting character.
+ &#x202C; - The PDF (pop directional formatting) formatting character; closes LRO.
+ If the BDIs in the test's first DIV were SPANs, the &#x05D1; would be rendered to the left
+ of the &#x05D0;.
+ </div>
+ <div class="test">
+ <div dir="ltr"><bdi>[&#x05D0;]</bdi> &gt; <bdi>[&#x05D1;]</bdi>...</div>
+ <div dir="ltr"><bdi dir="rtl">[&#x05D0;]</bdi> &gt; <bdi dir="rtl">[&#x05D1;]</bdi>...</div>
+ <div dir="ltr"><bdi dir="ltr">[&#x05D0;]</bdi> &gt; <bdi dir="ltr">[&#x05D1;]</bdi>...</div>
+ <div dir="rtl"><bdi>[a]</bdi> &gt; <bdi>[b]</bdi>...</div>
+ <div dir="rtl"><bdi dir="ltr">[a]</bdi> &gt; <bdi dir="ltr">[b]</bdi>...</div>
+ <div dir="rtl"><bdi dir="rtl">[a]</bdi> &gt; <bdi dir="rtl">[b]</bdi>...</div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">&#x202D;[&#x05D0;] &gt; [&#x05D1;]...&#x202C;</div>
+ <div dir="ltr">&#x202D;[&#x05D0;] &gt; [&#x05D1;]...&#x202C;</div>
+ <div dir="ltr">&#x202D;[&#x05D0;] &gt; [&#x05D1;]...&#x202C;</div>
+ <div dir="rtl">&#x202D;...[b] &lt; [a]&#x202C;</div>
+ <div dir="rtl">&#x202D;...[b] &lt; [a]&#x202C;</div>
+ <div dir="rtl">&#x202D;...[b] &lt; [a]&#x202C;</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-another-bdi-2-ref.html b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-another-bdi-2-ref.html
new file mode 100644
index 00000000000..9aef97c0ea1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-another-bdi-2-ref.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com" />
+ <link rel="author" title="Shai Berger" href="mailto:shai@platonix.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <style>
+ body{
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions">Test passes if the two boxes below look exactly the same.</div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; ... &#x05D5; - The first six Hebrew letters (strongly RTL).
+ &#x202D; - The LRO (left-to-right override) formatting character.
+ &#x202C; - The PDF (pop directional formatting) formatting character; closes LRO.
+ </div>
+ <div class="test">
+ <div dir="ltr">&#x202D;&#x05D0;&#x05D1;...&#x202C;</div>
+ <div dir="ltr">&#x202D;&#x05D0;&#x05D1;...&#x202C;</div>
+ <div dir="ltr">&#x202D;&#x05D0;&#x05D1;...&#x202C;</div>
+ <div dir="rtl">&#x202D;...ba&#x202C;</div>
+ <div dir="rtl">&#x202D;...ba&#x202C;</div>
+ <div dir="rtl">&#x202D;...ba&#x202C;</div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">&#x202D;&#x05D0;&#x05D1;...&#x202C;</div>
+ <div dir="ltr">&#x202D;&#x05D0;&#x05D1;...&#x202C;</div>
+ <div dir="ltr">&#x202D;&#x05D0;&#x05D1;...&#x202C;</div>
+ <div dir="rtl">&#x202D;...ba&#x202C;</div>
+ <div dir="rtl">&#x202D;...ba&#x202C;</div>
+ <div dir="rtl">&#x202D;...ba&#x202C;</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-another-bdi-2.html b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-another-bdi-2.html
new file mode 100644
index 00000000000..85aec466862
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-another-bdi-2.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: BDI: neutral to another immediately following BDI</title>
+ <link rel="match" href="bdi-neutral-to-another-bdi-2-ref.html">
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com" />
+ <link rel="author" title="Shai Berger" href="mailto:shai@platonix.com" />
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-bdi-element" />
+ <meta name="assert" content="
+ 'For the purposes of applying the bidirectional algorithm to the paragraph-level
+ container that a bdi element finds itself within, the bdi element must be treated
+ like a U+FFFC OBJECT REPLACEMENT CHARACTER.'
+ Thus, when a BDI contains text of the same strong direction as another BDI following it, the
+ two must not form a directional run as would be the case if the BDIs were just SPANs, even if
+ the two BDIs are not separated by anything at all." />
+ <style>
+ body{
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments {
+ display: none;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="instructions">Test passes if the two boxes below look exactly the same.</div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; ... &#x05D5; - The first six Hebrew letters (strongly RTL).
+ &#x202D; - The LRO (left-to-right override) formatting character.
+ &#x202C; - The PDF (pop directional formatting) formatting character; closes LRO.
+ If the BDIs in the test's first DIV were SPANs, the &#x05D1; would be rendered to the left of
+ the &#x05D0;.
+ </div>
+ <div class="test">
+ <div dir="ltr"><bdi>&#x05D0;</bdi><bdi>&#x05D1;</bdi>...</div>
+ <div dir="ltr"><bdi dir="rtl">&#x05D0;</bdi><bdi dir="rtl">&#x05D1;</bdi>...</div>
+ <div dir="ltr"><bdi dir="ltr">&#x05D0;</bdi><bdi dir="ltr">&#x05D1;</bdi>...</div>
+ <div dir="rtl"><bdi>a</bdi><bdi>b</bdi>...</div>
+ <div dir="rtl"><bdi dir="ltr">a</bdi><bdi dir="ltr">b</bdi>...</div>
+ <div dir="rtl"><bdi dir="rtl">a</bdi><bdi dir="rtl">b</bdi>...</div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">&#x202D;&#x05D0;&#x05D1;...&#x202C;</div>
+ <div dir="ltr">&#x202D;&#x05D0;&#x05D1;...&#x202C;</div>
+ <div dir="ltr">&#x202D;&#x05D0;&#x05D1;...&#x202C;</div>
+ <div dir="rtl">&#x202D;...ba&#x202C;</div>
+ <div dir="rtl">&#x202D;...ba&#x202C;</div>
+ <div dir="rtl">&#x202D;...ba&#x202C;</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-letter-following-1-ref.html b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-letter-following-1-ref.html
new file mode 100644
index 00000000000..a34d09bd24a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-letter-following-1-ref.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com">
+ <link rel="author" title="Shai Berger" href="mailto:shai@platonix.com">
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com">
+ <style>
+ body{
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments { display: none; }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; ... &#x05D5; - The first six Hebrew letters (strongly RTL).
+ &#x202D; - The LRO (left-to-right override) formatting character.
+ &#x202C; - The PDF (pop directional formatting) formatting character; closes LRO.
+ </div>
+ <div class="test">
+ <div dir="ltr">&#x202D;[&#x05D0;] &gt; &#x05D1;...&#x202C;</div>
+ <div dir="ltr">&#x202D;[&#x05D0;] &gt; &#x05D1;...&#x202C;</div>
+ <div dir="ltr">&#x202D;[&#x05D0;] &gt; &#x05D1;...&#x202C;</div>
+ <div dir="rtl">&#x202D;...b &lt; [a]&#x202C;</div>
+ <div dir="rtl">&#x202D;...b &lt; [a]&#x202C;</div>
+ <div dir="rtl">&#x202D;...b &lt; [a]&#x202C;</div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">&#x202D;[&#x05D0;] &gt; &#x05D1;...&#x202C;</div>
+ <div dir="ltr">&#x202D;[&#x05D0;] &gt; &#x05D1;...&#x202C;</div>
+ <div dir="ltr">&#x202D;[&#x05D0;] &gt; &#x05D1;...&#x202C;</div>
+ <div dir="rtl">&#x202D;...b &lt; [a]&#x202C;</div>
+ <div dir="rtl">&#x202D;...b &lt; [a]&#x202C;</div>
+ <div dir="rtl">&#x202D;...b &lt; [a]&#x202C;</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-letter-following-1.html b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-letter-following-1.html
new file mode 100644
index 00000000000..76da57c2b93
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-letter-following-1.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8"/>
+ <title>HTML Test: BDI: neutral to following letter</title>
+ <link rel="match" href="bdi-neutral-to-letter-following-1-ref.html"/>
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com"/>
+ <link rel="author" title="Shai Berger" href="mailto:shai@platonix.com"/>
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com"/>
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-bdi-element"/>
+ <meta name="assert" content="
+ 'For the purposes of applying the bidirectional algorithm to the paragraph-level
+ container that a bdi element finds itself within, the bdi element must be treated
+ like a U+FFFC OBJECT REPLACEMENT CHARACTER.'"/>
+ <style>
+ body{
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments { display: none; }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; ... &#x05D5; - The first six Hebrew letters (strongly RTL).
+ &#x202D; - The LRO (left-to-right override) formatting character.
+ &#x202C; - The PDF (pop directional formatting) formatting character; closes LRO.
+ If the BDI in the test's first DIV were a SPAN, the &#x05D1; would be rendered to the left
+ of the &#x05D0;
+ </div>
+ <div class="test">
+ <div dir="ltr"><bdi>[&#x05D0;]</bdi> &gt; &#x05D1;...</div>
+ <div dir="ltr"><bdi dir="rtl">[&#x05D0;]</bdi> &gt; &#x05D1;...</div>
+ <div dir="ltr"><bdi dir="ltr">[&#x05D0;]</bdi> &gt; &#x05D1;...</div>
+ <div dir="rtl"><bdi>[a]</bdi> &gt; b...</div>
+ <div dir="rtl"><bdi dir="ltr">[a]</bdi> &gt; b...</div>
+ <div dir="rtl"><bdi dir="rtl">[a]</bdi> &gt; b...</div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">&#x202D;[&#x05D0;] &gt; &#x05D1;...&#x202C;</div>
+ <div dir="ltr">&#x202D;[&#x05D0;] &gt; &#x05D1;...&#x202C;</div>
+ <div dir="ltr">&#x202D;[&#x05D0;] &gt; &#x05D1;...&#x202C;</div>
+ <div dir="rtl">&#x202D;...b &lt; [a]&#x202C;</div>
+ <div dir="rtl">&#x202D;...b &lt; [a]&#x202C;</div>
+ <div dir="rtl">&#x202D;...b &lt; [a]&#x202C;</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-letter-following-2-ref.html b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-letter-following-2-ref.html
new file mode 100644
index 00000000000..80f36183b03
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-letter-following-2-ref.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com">
+ <link rel="author" title="Shai Berger" href="mailto:shai@platonix.com">
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com">
+ <style>
+ body{
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments { display: none; }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; ... &#x05D5; - The first six Hebrew letters (strongly RTL).
+ &#x202D; - The LRO (left-to-right override) formatting character.
+ &#x202C; - The PDF (pop directional formatting) formatting character; closes LRO.
+ </div>
+ <div class="test">
+ <div dir="ltr">&#x202D;&#x05D0;&#x05D1;...&#x202C;</div>
+ <div dir="ltr">&#x202D;&#x05D0;&#x05D1;...&#x202C;</div>
+ <div dir="ltr">&#x202D;&#x05D0;&#x05D1;...&#x202C;</div>
+ <div dir="rtl">&#x202D;...ba&#x202C;</div>
+ <div dir="rtl">&#x202D;...ba&#x202C;</div>
+ <div dir="rtl">&#x202D;...ba&#x202C;</div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">&#x202D;&#x05D0;&#x05D1;...&#x202C;</div>
+ <div dir="ltr">&#x202D;&#x05D0;&#x05D1;...&#x202C;</div>
+ <div dir="ltr">&#x202D;&#x05D0;&#x05D1;...&#x202C;</div>
+ <div dir="rtl">&#x202D;...ba&#x202C;</div>
+ <div dir="rtl">&#x202D;...ba&#x202C;</div>
+ <div dir="rtl">&#x202D;...ba&#x202C;</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-letter-following-2.html b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-letter-following-2.html
new file mode 100644
index 00000000000..ce41983f00c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-letter-following-2.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8"/>
+ <title>HTML Test: BDI: neutral to immediately following letter</title>
+ <link rel="match" href="bdi-neutral-to-letter-following-2-ref.html">
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com"/>
+ <link rel="author" title="Shai Berger" href="mailto:shai@platonix.com"/>
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com"/>
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-bdi-element"/>
+ <meta name="assert" content="
+ 'For the purposes of applying the bidirectional algorithm to the paragraph-level
+ container that a bdi element finds itself within, the bdi element must be treated
+ like a U+FFFC OBJECT REPLACEMENT CHARACTER.'"/>
+ <style>
+ body{
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments { display: none; }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; ... &#x05D5; - The first six Hebrew letters (strongly RTL).
+ &#x202D; - The LRO (left-to-right override) formatting character.
+ &#x202C; - The PDF (pop directional formatting) formatting character; closes LRO.
+ If the BDI in the following DIV were a SPAN, the &#x05D1; would be rendered to the left
+ of the &#x05D0;
+ </div>
+ <div class="test">
+ <div dir="ltr"><bdi>&#x05D0;</bdi>&#x05D1;...</div>
+ <div dir="ltr"><bdi dir="rtl">&#x05D0;</bdi>&#x05D1;...</div>
+ <div dir="ltr"><bdi dir="ltr">&#x05D0;</bdi>&#x05D1;...</div>
+ <div dir="rtl"><bdi>a</bdi>b...</div>
+ <div dir="rtl"><bdi dir="ltr">a</bdi>b...</div>
+ <div dir="rtl"><bdi dir="rtl">a</bdi>b...</div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">&#x202D;&#x05D0;&#x05D1;...&#x202C;</div>
+ <div dir="ltr">&#x202D;&#x05D0;&#x05D1;...&#x202C;</div>
+ <div dir="ltr">&#x202D;&#x05D0;&#x05D1;...&#x202C;</div>
+ <div dir="rtl">&#x202D;...ba&#x202C;</div>
+ <div dir="rtl">&#x202D;...ba&#x202C;</div>
+ <div dir="rtl">&#x202D;...ba&#x202C;</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-letter-preceding-1-ref.html b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-letter-preceding-1-ref.html
new file mode 100644
index 00000000000..5e39eabd289
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-letter-preceding-1-ref.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com">
+ <link rel="author" title="Shai Berger" href="mailto:shai@platonix.com">
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com">
+ <style>
+ body{
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments { display: none; }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; ... &#x05D5; - The first six Hebrew letters (strongly RTL).
+ &#x202D; - The LRO (left-to-right override) formatting character.
+ &#x202C; - The PDF (pop directional formatting) formatting character; closes LRO.
+ </div>
+ <div class="test">
+ <div dir="ltr">&#x202D;&#x05D0; &gt; [&#x05D1;]...&#x202C;</div>
+ <div dir="ltr">&#x202D;&#x05D0; &gt; [&#x05D1;]...&#x202C;</div>
+ <div dir="ltr">&#x202D;&#x05D0; &gt; [&#x05D1;]...&#x202C;</div>
+ <div dir="rtl">&#x202D;...[b] &lt; a&#x202C;</div>
+ <div dir="rtl">&#x202D;...[b] &lt; a&#x202C;</div>
+ <div dir="rtl">&#x202D;...[b] &lt; a&#x202C;</div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">&#x202D;&#x05D0; &gt; [&#x05D1;]...&#x202C;</div>
+ <div dir="ltr">&#x202D;&#x05D0; &gt; [&#x05D1;]...&#x202C;</div>
+ <div dir="ltr">&#x202D;&#x05D0; &gt; [&#x05D1;]...&#x202C;</div>
+ <div dir="rtl">&#x202D;...[b] &lt; a&#x202C;</div>
+ <div dir="rtl">&#x202D;...[b] &lt; a&#x202C;</div>
+ <div dir="rtl">&#x202D;...[b] &lt; a&#x202C;</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-letter-preceding-1.html b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-letter-preceding-1.html
new file mode 100644
index 00000000000..46772de642b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-letter-preceding-1.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8"/>
+ <title>HTML Test: BDI: neutral to preceding letter</title>
+ <link rel="match" href="bdi-neutral-to-letter-preceding-1-ref.html">
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com"/>
+ <link rel="author" title="Shai Berger" href="mailto:shai@platonix.com"/>
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com"/>
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-bdi-element"/>
+ <meta name="assert" content="
+ 'For the purposes of applying the bidirectional algorithm to the paragraph-level
+ container that a bdi element finds itself within, the bdi element must be treated
+ like a U+FFFC OBJECT REPLACEMENT CHARACTER.'"/>
+ <style>
+ body{
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments { display: none; }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; ... &#x05D5; - The first six Hebrew letters (strongly RTL).
+ &#x202D; - The LRO (left-to-right override) formatting character.
+ &#x202C; - The PDF (pop directional formatting) formatting character; closes LRO.
+ If the BDI in the test's first DIV were a SPAN, the &#x05D1; would be rendered to the left
+ of the &#x05D0;
+ </div>
+ <div class="test">
+ <div dir="ltr">&#x05D0; &gt; <bdi>[&#x05D1;]</bdi>...</div>
+ <div dir="ltr">&#x05D0; &gt; <bdi dir="rtl">[&#x05D1;]</bdi>...</div>
+ <div dir="ltr">&#x05D0; &gt; <bdi dir="ltr">[&#x05D1;]</bdi>...</div>
+ <div dir="rtl">a &gt; <bdi>[b]</bdi>...</div>
+ <div dir="rtl">a &gt; <bdi dir="ltr">[b]</bdi>...</div>
+ <div dir="rtl">a &gt; <bdi dir="rtl">[b]</bdi>...</div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">&#x202D;&#x05D0; &gt; [&#x05D1;]...&#x202C;</div>
+ <div dir="ltr">&#x202D;&#x05D0; &gt; [&#x05D1;]...&#x202C;</div>
+ <div dir="ltr">&#x202D;&#x05D0; &gt; [&#x05D1;]...&#x202C;</div>
+ <div dir="rtl">&#x202D;...[b] &lt; a&#x202C;</div>
+ <div dir="rtl">&#x202D;...[b] &lt; a&#x202C;</div>
+ <div dir="rtl">&#x202D;...[b] &lt; a&#x202C;</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-letter-preceding-2-ref.html b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-letter-preceding-2-ref.html
new file mode 100644
index 00000000000..80f36183b03
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-letter-preceding-2-ref.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com">
+ <link rel="author" title="Shai Berger" href="mailto:shai@platonix.com">
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com">
+ <style>
+ body{
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments { display: none; }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; ... &#x05D5; - The first six Hebrew letters (strongly RTL).
+ &#x202D; - The LRO (left-to-right override) formatting character.
+ &#x202C; - The PDF (pop directional formatting) formatting character; closes LRO.
+ </div>
+ <div class="test">
+ <div dir="ltr">&#x202D;&#x05D0;&#x05D1;...&#x202C;</div>
+ <div dir="ltr">&#x202D;&#x05D0;&#x05D1;...&#x202C;</div>
+ <div dir="ltr">&#x202D;&#x05D0;&#x05D1;...&#x202C;</div>
+ <div dir="rtl">&#x202D;...ba&#x202C;</div>
+ <div dir="rtl">&#x202D;...ba&#x202C;</div>
+ <div dir="rtl">&#x202D;...ba&#x202C;</div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">&#x202D;&#x05D0;&#x05D1;...&#x202C;</div>
+ <div dir="ltr">&#x202D;&#x05D0;&#x05D1;...&#x202C;</div>
+ <div dir="ltr">&#x202D;&#x05D0;&#x05D1;...&#x202C;</div>
+ <div dir="rtl">&#x202D;...ba&#x202C;</div>
+ <div dir="rtl">&#x202D;...ba&#x202C;</div>
+ <div dir="rtl">&#x202D;...ba&#x202C;</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-letter-preceding-2.html b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-letter-preceding-2.html
new file mode 100644
index 00000000000..192115775c7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-letter-preceding-2.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8"/>
+ <title>HTML Test: BDI: neutral to immediately preceding letter</title>
+ <link rel="match" href="bdi-neutral-to-letter-preceding-2-ref.html"/>
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com"/>
+ <link rel="author" title="Shai Berger" href="mailto:shai@platonix.com"/>
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com"/>
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-bdi-element"/>
+ <meta name="assert" content="
+ 'For the purposes of applying the bidirectional algorithm to the paragraph-level
+ container that a bdi element finds itself within, the bdi element must be treated
+ like a U+FFFC OBJECT REPLACEMENT CHARACTER.'"/>
+ <style>
+ body{
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments { display: none; }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; ... &#x05D5; - The first six Hebrew letters (strongly RTL).
+ &#x202D; - The LRO (left-to-right override) formatting character.
+ &#x202C; - The PDF (pop directional formatting) formatting character; closes LRO.
+ If the BDI in the test's first DIV were a SPAN, the &#x05D1; would be rendered to the left
+ of the &#x05D0;
+ </div>
+ <div class="test">
+ <div dir="ltr">&#x05D0;<bdi>&#x05D1;</bdi>...</div>
+ <div dir="ltr">&#x05D0;<bdi dir="rtl">&#x05D1;</bdi>...</div>
+ <div dir="ltr">&#x05D0;<bdi dir="ltr">&#x05D1;</bdi>...</div>
+ <div dir="rtl">a<bdi>b</bdi>...</div>
+ <div dir="rtl">a<bdi dir="ltr">b</bdi>...</div>
+ <div dir="rtl">a<bdi dir="rtl">b</bdi>...</div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">&#x202D;&#x05D0;&#x05D1;...&#x202C;</div>
+ <div dir="ltr">&#x202D;&#x05D0;&#x05D1;...&#x202C;</div>
+ <div dir="ltr">&#x202D;&#x05D0;&#x05D1;...&#x202C;</div>
+ <div dir="rtl">&#x202D;...ba&#x202C;</div>
+ <div dir="rtl">&#x202D;...ba&#x202C;</div>
+ <div dir="rtl">&#x202D;...ba&#x202C;</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-number-following-1-ref.html b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-number-following-1-ref.html
new file mode 100644
index 00000000000..ad15d468b88
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-number-following-1-ref.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com">
+ <link rel="author" title="Shai Berger" href="mailto:shai@platonix.com">
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com">
+ <style>
+ body{
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments { display: none; }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; ... &#x05D5; - The first six Hebrew letters (strongly RTL).
+ &#x202D; - The LRO (left-to-right override) formatting character.
+ &#x202C; - The PDF (pop directional formatting) formatting character; closes LRO.
+ </div>
+ <div class="test">
+ <div dir="ltr">&#x202D;[&#x05D0;] (3 reviews)...&#x202C;</div>
+ <div dir="ltr">&#x202D;[&#x05D0;] (3 reviews)...&#x202C;</div>
+ <div dir="ltr">&#x202D;[&#x05D0;] (3 reviews)...&#x202C;</div>
+ <div dir="rtl">&#x202D;...(3) [a]&#x202C;</div>
+ <div dir="rtl">&#x202D;...(3) [a]&#x202C;</div>
+ <div dir="rtl">&#x202D;...(3) [a]&#x202C;</div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">&#x202D;[&#x05D0;] (3 reviews)...&#x202C;</div>
+ <div dir="ltr">&#x202D;[&#x05D0;] (3 reviews)...&#x202C;</div>
+ <div dir="ltr">&#x202D;[&#x05D0;] (3 reviews)...&#x202C;</div>
+ <div dir="rtl">&#x202D;...(3) [a]&#x202C;</div>
+ <div dir="rtl">&#x202D;...(3) [a]&#x202C;</div>
+ <div dir="rtl">&#x202D;...(3) [a]&#x202C;</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-number-following-1.html b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-number-following-1.html
new file mode 100644
index 00000000000..ff566737f2f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-number-following-1.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8"/>
+ <title>HTML Test: BDI: neutral to following number</title>
+ <link rel="match" href="bdi-neutral-to-number-following-1-ref.html"/>
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com"/>
+ <link rel="author" title="Shai Berger" href="mailto:shai@platonix.com"/>
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com"/>
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-bdi-element"/>
+ <meta name="assert" content="
+ 'For the purposes of applying the bidirectional algorithm to the paragraph-level
+ container that a bdi element finds itself within, the bdi element must be treated
+ like a U+FFFC OBJECT REPLACEMENT CHARACTER.'"/>
+ <style>
+ body{
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments { display: none; }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; ... &#x05D5; - The first six Hebrew letters (strongly RTL).
+ &#x202D; - The LRO (left-to-right override) formatting character.
+ &#x202C; - The PDF (pop directional formatting) formatting character; closes LRO.
+ If the BDI in the test's first DIV were a SPAN, the 3 would be rendered to the left
+ of the &#x05D0;
+ </div>
+ <div class="test">
+ <div dir="ltr"><bdi>[&#x05D0;]</bdi> (3 reviews)...</div>
+ <div dir="ltr"><bdi dir="rtl">[&#x05D0;]</bdi> (3 reviews)...</div>
+ <div dir="ltr"><bdi dir="ltr">[&#x05D0;]</bdi> (3 reviews)...</div>
+ <div dir="rtl"><bdi>[a]</bdi> (3)...</div>
+ <div dir="rtl"><bdi dir="ltr">[a]</bdi> (3)...</div>
+ <div dir="rtl"><bdi dir="rtl">[a]</bdi> (3)...</div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">&#x202D;[&#x05D0;] (3 reviews)...&#x202C;</div>
+ <div dir="ltr">&#x202D;[&#x05D0;] (3 reviews)...&#x202C;</div>
+ <div dir="ltr">&#x202D;[&#x05D0;] (3 reviews)...&#x202C;</div>
+ <div dir="rtl">&#x202D;...(3) [a]&#x202C;</div>
+ <div dir="rtl">&#x202D;...(3) [a]&#x202C;</div>
+ <div dir="rtl">&#x202D;...(3) [a]&#x202C;</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-number-following-2-ref.html b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-number-following-2-ref.html
new file mode 100644
index 00000000000..d0f1097adeb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-number-following-2-ref.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com">
+ <link rel="author" title="Shai Berger" href="mailto:shai@platonix.com">
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com">
+ <style>
+ body{
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments { display: none; }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; ... &#x05D5; - The first six Hebrew letters (strongly RTL).
+ &#x202D; - The LRO (left-to-right override) formatting character.
+ &#x202C; - The PDF (pop directional formatting) formatting character; closes LRO.
+ </div>
+ <div class="test">
+ <div dir="ltr">&#x202D;&#x05D0;1...&#x202C;</div>
+ <div dir="ltr">&#x202D;&#x05D0;1...&#x202C;</div>
+ <div dir="ltr">&#x202D;&#x05D0;1...&#x202C;</div>
+ <div dir="rtl">&#x202D;...1a&#x202C;</div>
+ <div dir="rtl">&#x202D;...1a&#x202C;</div>
+ <div dir="rtl">&#x202D;...1a&#x202C;</div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">&#x202D;&#x05D0;1...&#x202C;</div>
+ <div dir="ltr">&#x202D;&#x05D0;1...&#x202C;</div>
+ <div dir="ltr">&#x202D;&#x05D0;1...&#x202C;</div>
+ <div dir="rtl">&#x202D;...1a&#x202C;</div>
+ <div dir="rtl">&#x202D;...1a&#x202C;</div>
+ <div dir="rtl">&#x202D;...1a&#x202C;</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-number-following-2.html b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-number-following-2.html
new file mode 100644
index 00000000000..62a3b50ffeb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-number-following-2.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8"/>
+ <title>HTML Test: BDI: neutral to immediately following number</title>
+ <link rel="match" href="bdi-neutral-to-number-following-2-ref.html"/>
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com"/>
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com"/>
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-bdi-element"/>
+ <meta name="assert" content="
+ 'For the purposes of applying the bidirectional algorithm to the paragraph-level
+ container that a bdi element finds itself within, the bdi element must be treated
+ like a U+FFFC OBJECT REPLACEMENT CHARACTER.'"/>
+ <style>
+ body{
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments { display: none; }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; ... &#x05D5; - The first six Hebrew letters (strongly RTL).
+ &#x202D; - The LRO (left-to-right override) formatting character.
+ &#x202C; - The PDF (pop directional formatting) formatting character; closes LRO.
+ If the BDI in the test's first DIV were a SPAN, the 1 would be rendered to the left
+ of the &#x05D0;
+ </div>
+ <div class="test">
+ <div dir="ltr"><bdi>&#x05D0;</bdi>1...</div>
+ <div dir="ltr"><bdi dir="rtl">&#x05D0;</bdi>1...</div>
+ <div dir="ltr"><bdi dir="ltr">&#x05D0;</bdi>1...</div>
+ <div dir="rtl"><bdi>a</bdi>1...</div>
+ <div dir="rtl"><bdi dir="ltr">a</bdi>1...</div>
+ <div dir="rtl"><bdi dir="rtl">a</bdi>1...</div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">&#x202D;&#x05D0;1...&#x202C;</div>
+ <div dir="ltr">&#x202D;&#x05D0;1...&#x202C;</div>
+ <div dir="ltr">&#x202D;&#x05D0;1...&#x202C;</div>
+ <div dir="rtl">&#x202D;...1a&#x202C;</div>
+ <div dir="rtl">&#x202D;...1a&#x202C;</div>
+ <div dir="rtl">&#x202D;...1a&#x202C;</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-surrounding-run-ref.html b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-surrounding-run-ref.html
new file mode 100644
index 00000000000..d7967c77fc5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-surrounding-run-ref.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com">
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com">
+ <style>
+ body{
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments { display: none; }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; ... &#x05D5; - The first six Hebrew letters (strongly RTL).
+ &#x202D; - The LRO (left-to-right override) formatting character.
+ &#x202C; - The PDF (pop directional formatting) formatting character; closes LRO.
+ </div>
+ <div class="test">
+ <div dir="ltr">&#x202D;&#x05D2; &lt; [b] &lt; &#x05D0;...&#x202C;</div>
+ <div dir="ltr">&#x202D;&#x05D2; &lt; [b] &lt; &#x05D0;...&#x202C;</div>
+ <div dir="ltr">&#x202D;&#x05D2; &lt; [b] &lt; &#x05D0;...&#x202C;</div>
+ <div dir="rtl">&#x202D;...a &gt; [&#x05D1;] &gt; c&#x202C;</div>
+ <div dir="rtl">&#x202D;...a &gt; [&#x05D1;] &gt; c&#x202C;</div>
+ <div dir="rtl">&#x202D;...a &gt; [&#x05D1;] &gt; c&#x202C;</div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">&#x202D;&#x05D2; &lt; [b] &lt; &#x05D0;...&#x202C;</div>
+ <div dir="ltr">&#x202D;&#x05D2; &lt; [b] &lt; &#x05D0;...&#x202C;</div>
+ <div dir="ltr">&#x202D;&#x05D2; &lt; [b] &lt; &#x05D0;...&#x202C;</div>
+ <div dir="rtl">&#x202D;...a &gt; [&#x05D1;] &gt; c&#x202C;</div>
+ <div dir="rtl">&#x202D;...a &gt; [&#x05D1;] &gt; c&#x202C;</div>
+ <div dir="rtl">&#x202D;...a &gt; [&#x05D1;] &gt; c&#x202C;</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-surrounding-run.html b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-surrounding-run.html
new file mode 100644
index 00000000000..bff339ec345
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-to-surrounding-run.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8"/>
+ <title>HTML Test: BDI: neutral to surrounding letters</title>
+ <link rel="match" href="bdi-neutral-to-surrounding-run-ref.html">
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com"/>
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com"/>
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-bdi-element"/>
+ <meta name="assert" content="
+ 'For the purposes of applying the bidirectional algorithm to the paragraph-level
+ container that a bdi element finds itself within, the bdi element must be treated
+ like a U+FFFC OBJECT REPLACEMENT CHARACTER.'
+ Thus, regardless of its content and its dir attribute (if any), a BDI will not prevent
+ a strongly RTL (or LTR) character preceding it from forming a single directional run with
+ another strongly RTL (LTR) character following it."/>
+ <style>
+ body{
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments { display: none; }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; ... &#x05D5; - The first six Hebrew letters (strongly RTL).
+ &#x202D; - The LRO (left-to-right override) formatting character.
+ &#x202C; - The PDF (pop directional formatting) formatting character; closes LRO.
+ If the BDI in the test's first DIV were a SPAN, its b would prevent the &#x05D0; and the &#x05D1;
+ from forming a single RTL run and thus keep the &gt;s between from being mirrored into &lt;s.
+ </div>
+ <div class="test">
+ <div dir="ltr">&#x05D0; &gt; <bdi>[b]</bdi> &gt; &#x05D2;...</div>
+ <div dir="ltr">&#x05D0; &gt; <bdi dir="ltr">[b]</bdi> &gt; &#x05D2;...</div>
+ <div dir="ltr">&#x05D0; &gt; <bdi dir="rtl">[b]</bdi> &gt; &#x05D2;...</div>
+ <div dir="rtl">a &gt; <bdi>[&#x05D1;]</bdi> &gt; c...</div>
+ <div dir="rtl">a &gt; <bdi dir="ltr">[&#x05D1;]</bdi> &gt; c...</div>
+ <div dir="rtl">a &gt; <bdi dir="rtl">[&#x05D1;]</bdi> &gt; c...</div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">&#x202D;&#x05D2; &lt; [b] &lt; &#x05D0;...&#x202C;</div>
+ <div dir="ltr">&#x202D;&#x05D2; &lt; [b] &lt; &#x05D0;...&#x202C;</div>
+ <div dir="ltr">&#x202D;&#x05D2; &lt; [b] &lt; &#x05D0;...&#x202C;</div>
+ <div dir="rtl">&#x202D;...a &gt; [&#x05D1;] &gt; c&#x202C;</div>
+ <div dir="rtl">&#x202D;...a &gt; [&#x05D1;] &gt; c&#x202C;</div>
+ <div dir="rtl">&#x202D;...a &gt; [&#x05D1;] &gt; c&#x202C;</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-wrapped-ref.html b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-wrapped-ref.html
new file mode 100644
index 00000000000..9859de47474
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-wrapped-ref.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com">
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com">
+ <style>
+ body{
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments { display: none; }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; ... &#x05D5; - The first six Hebrew letters (strongly RTL).
+ &#x202D; - The LRO (left-to-right override) formatting character.
+ &#x202C; - The PDF (pop directional formatting) formatting character; closes LRO.
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ &#x202D;b &lt; &#x05D0;&#x202C;<br/>
+ &#x202D;&gt;&gt;&gt;&#x202C;<br/>
+ &#x202D;&#x05D3; &lt; c...&#x202C;
+ </div>
+ <div dir="rtl">
+ &#x202D;a &gt; &#x05D1;&#x202C;<br/>
+ &#x202D;&lt;&lt;&lt;&#x202C;<br/>
+ &#x202D;...&#x05D2; &gt; d&#x202C;
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ &#x202D;b &lt; &#x05D0;&#x202C;<br/>
+ &#x202D;&gt;&gt;&gt;&#x202C;<br/>
+ &#x202D;&#x05D3; &lt; c...&#x202C;
+ </div>
+ <div dir="rtl">
+ &#x202D;a &gt; &#x05D1;&#x202C;<br/>
+ &#x202D;&lt;&lt;&lt;&#x202C;<br/>
+ &#x202D;...&#x05D2; &gt; d&#x202C;
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-wrapped.html b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-wrapped.html
new file mode 100644
index 00000000000..3e21fcb0fd4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-neutral-wrapped.html
@@ -0,0 +1,73 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8"/>
+ <title>HTML Test: BDI: neutral when wrapped</title>
+ <link rel="match" href="bdi-neutral-wrapped-ref.html">
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com"/>
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com"/>
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-bdi-element"/>
+ <meta name="assert" content="
+ 'For the purposes of applying the bidirectional algorithm to the paragraph-level
+ container that a bdi element finds itself within, the bdi element must be treated
+ like a U+FFFC OBJECT REPLACEMENT CHARACTER.'
+ This should hold even if the BDI's content is wrapped over more than one line."/>
+ <style>
+ body{
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments { display: none; }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#xA0; - Non-breaking space.
+ &#x05D0; ... &#x05D5; - The first six Hebrew letters (strongly RTL).
+ &#x202D; - The LRO (left-to-right override) formatting character.
+ &#x202C; - The PDF (pop directional formatting) formatting character; closes LRO.
+ In the test below, the non-breaking spaces in the BDI's middle "word" make it so long that it
+ must be displayed on a line of its own, with the BDI wrapped before and after it. At the same
+ time, the content surrounding the BDI is supposed to form a single directional run, despite
+ the containing element and the BDI both having the opposite direction, because the BDI must be
+ treated as a neutral. Thus, on the line containing the first part of the BDI, the BDI's
+ content must appear after the content preceding it, and on the line containing the last part
+ of the BDI, the BDI content must appear before the content following it, where both 'before'
+ and 'after' are defined relative to the surrounding directional run.
+ </div>
+ <div class="test">
+ <div dir="ltr">
+ &#x05D0; &gt;
+ <bdi>b
+&gt;&gt;&gt;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;
+ c</bdi>
+ &gt; &#x05D3;...
+ </div>
+ <div dir="rtl">
+ a &gt;
+ <bdi>&#x05D1;
+&gt;&gt;&gt;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;
+ &#x05D2;</bdi>
+ &gt; d...
+ </div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">
+ &#x202D;b &lt; &#x05D0;&#x202C;<br/>
+ &#x202D;&gt;&gt;&gt;&#x202C;<br/>
+ &#x202D;&#x05D3; &lt; c...&#x202C;
+ </div>
+ <div dir="rtl">
+ &#x202D;a &gt; &#x05D1;&#x202C;<br/>
+ &#x202D;&lt;&lt;&lt;&#x202C;<br/>
+ &#x202D;...&#x05D2; &gt; d&#x202C;
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-paragraph-level-container-ref.html b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-paragraph-level-container-ref.html
new file mode 100644
index 00000000000..0c74ecf68ac
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-paragraph-level-container-ref.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com">
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com">
+ <style>
+ body{
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 500px;
+ margin: 20px;
+ }
+ .comments { display: none; }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; ... &#x05D5; - The first six Hebrew letters (strongly RTL).
+ &#x202D; - The LRO (left-to-right override) formatting character.
+ &#x202C; - The PDF (pop directional formatting) formatting character; closes LRO.
+ </div>
+ <div class="test">
+ <div dir="ltr">&#x202D;&#x05D0; [1 2 3 b] c [d &#x05D4;?!] &#x05D5;...&#x202C;</div>
+ <div dir="rtl">&#x202D;...f [!?e &#x05D3;] &#x05D2; [&#x05D1; 3 2 1] a&#x202C;</div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">&#x202D;&#x05D0; [1 2 3 b] c [d &#x05D4;?!] &#x05D5;...&#x202C;</div>
+ <div dir="rtl">&#x202D;...f [!?e &#x05D3;] &#x05D2; [&#x05D1; 3 2 1] a&#x202C;</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-paragraph-level-container.html b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-paragraph-level-container.html
new file mode 100644
index 00000000000..f133a95772d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdi-element/bdi-paragraph-level-container.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8"/>
+ <title>HTML Test: BDI: paragraph-level container</title>
+ <link rel="match" href="bdi-paragraph-level-container-ref.html"/>
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com"/>
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com"/>
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-bdi-element"/>
+ <meta name="assert" content="
+ 'For the purposes of applying the bidirectional algorithm to the contents of a bdi element,
+ user agents must treat the element as a paragraph-level container.'
+ Thus, under no circumstances should the content outside a BDI affect the visual
+ ordering of the BDI's content."/>
+ <style>
+ body{
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 500px;
+ margin: 20px;
+ }
+ .comments { display: none; }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; ... &#x05D5; - The first six Hebrew letters (strongly RTL).
+ &#x202D; - The LRO (left-to-right override) formatting character.
+ &#x202C; - The PDF (pop directional formatting) formatting character; closes LRO.
+ If the BDIs in the test's first DIV were just SPANs, the &#x05D0; would order the 1 2 3 as
+ 3 2 1, and the &#x05D5; would (with the &#x05D4;) order the ?! as !?.
+ </div>
+ <div class="test">
+ <div dir="ltr">&#x05D0; <bdi>[1 2 3 b]</bdi> c <bdi>[d &#x05D4;?!]</bdi> &#x05D5;...</div>
+ <div dir="rtl">a <bdi>[1 2 3 &#x05D1;]</bdi> &#x05D2; <bdi>[&#x05D3; e?!]</bdi> f...</div>
+ </div>
+ <div class="ref">
+ <div dir="ltr">&#x202D;&#x05D0; [1 2 3 b] c [d &#x05D4;?!] &#x05D5;...&#x202C;</div>
+ <div dir="rtl">&#x202D;...f [!?e &#x05D3;] &#x05D2; [&#x05D1; 3 2 1] a&#x202C;</div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdo-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdo-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdo-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdo-element/bdo-child.html b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdo-element/bdo-child.html
new file mode 100644
index 00000000000..feadc26d7bd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdo-element/bdo-child.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>HTML Test: bdo - text directionality formatting control for its children</title>
+ <link rel="author" title="Intel" href="http://www.intel.com/">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-bdo-element">
+ <link rel="match" href="bidi-001-ref.html">
+ <meta name="assert" content="Check if the bdo element represents explicit text directionality formatting control for its children.">
+ </head>
+ <body>
+ <p>Test passes if there is text 'WERBEH'.</p>
+ <bdo dir="rtl">
+ <span>HEBREW</span>
+ </bdo>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdo-element/bdo-ltr.html b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdo-element/bdo-ltr.html
new file mode 100644
index 00000000000..8a7861086af
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdo-element/bdo-ltr.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>HTML Test: The value 'ltr' of dir attribute specifies a left-to-right override</title>
+ <link rel="author" title="Intel" href="http://www.intel.com/">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-bdo-element">
+ <link rel="match" href="bidi-001-ref.html">
+ <meta name="assert" content="Check if the value ltr of dir attribute specifies a left-to-right override">
+ </head>
+ <body>
+ <p>Test passes if there is text 'WERBEH'.</p>
+ <bdo dir="ltr">WERBEH</bdo>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdo-element/bdo-override.html b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdo-element/bdo-override.html
new file mode 100644
index 00000000000..75a45e198ff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdo-element/bdo-override.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>HTML Test: bdo - override the Unicode bidirectional algorithm</title>
+ <link rel="author" title="Intel" href="http://www.intel.com/">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-bdo-element">
+ <link rel="match" href="bidi-001-ref.html">
+ <meta name="assert" content="Check if authors could override the Unicode bidirectional algorithm
+ by explicitly specifying a direction override of bdo element">
+ </head>
+ <body>
+ <p>Test passes if there is text 'WERBEH'.</p>
+ <p>
+ &#x202E;<bdo dir="ltr">WERBEH</bdo>&#x202C;
+ </p>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdo-element/bidi-001-ref.html b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdo-element/bidi-001-ref.html
new file mode 100644
index 00000000000..83d2dc4a16d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdo-element/bidi-001-ref.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="UTF-8">
+<title>directional type reference</title>
+</head>
+<body>
+<p>Test passes if there is text 'WERBEH'.</p>
+<div>WERBEH</div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdo-element/bidi-001.html b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdo-element/bidi-001.html
new file mode 100644
index 00000000000..772dcf43b37
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-bdo-element/bidi-001.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="UTF-8">
+<title>directional type</title>
+<meta content="W3C" name="author">
+<link rel="match" href="bidi-001-ref.html">
+<meta name="assert" content="Test text bidirectionality using the bdo element">
+</head>
+<body dir='ltr'>
+<p>Test passes if there is text 'WERBEH'.</p>
+<bdo dir="rtl">HEBREW</bdo>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-br-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-br-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-br-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-br-element/br-bidi-in-inline-ancestors-ref.html b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-br-element/br-bidi-in-inline-ancestors-ref.html
new file mode 100644
index 00000000000..c2dd4daa7a5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-br-element/br-bidi-in-inline-ancestors-ref.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com"/>
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <style>
+ body{
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments { display: none; }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; ... &#x05D8; - The first nine Hebrew letters (strongly RTL).
+ &#x202D; - The LRO (left-to-right override) formatting character.
+ &#x202C; - The PDF (pop directional formatting) formatting character; closes LRO.
+ </div>
+ <div class="test">
+ &#x202D;&#x05D0;&#x05D1; &#x05D2;&#x05D3; 1. I like &#x05D4;. fg hi&#x202C;
+ <br/>
+ &#x202D;ab cd 2. &#x05D4; is great! &#x05D5;&#x05D6; &#x05D7;&#x05D8;&#x202C;
+ </div>
+ <div class="ref">
+ &#x202D;&#x05D0;&#x05D1; &#x05D2;&#x05D3; 1. I like &#x05D4;. fg hi&#x202C;
+ <br/>
+ &#x202D;ab cd 2. &#x05D4; is great! &#x05D5;&#x05D6; &#x05D7;&#x05D8;&#x202C;
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-br-element/br-bidi-in-inline-ancestors.html b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-br-element/br-bidi-in-inline-ancestors.html
new file mode 100644
index 00000000000..89e7f2f1aab
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-br-element/br-bidi-in-inline-ancestors.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>HTML Test: BR in inline ancestors</title>
+ <link rel="match" href="br-bidi-in-inline-ancestors-ref.html">
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com"/>
+ <link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-br-element"/>
+ <link rel="help" href="http://www.w3.org/TR/css3-writing-modes/#unicode-bidi" />
+ <meta name="assert" content="
+ 'A br element should separate paragraphs for the purposes of the Unicode bidirectional
+ algorithm.'
+ 'If an inline element is broken around a bidi paragraph boundary (e.g. if split by a block or
+ forced paragraph break), then the bidi control codes corresponding to the end of the element
+ are added before the interruption and the codes corresponding to the start of the element are
+ added after it. (In other words, any embedding levels or overrides started by the element are
+ closed at the paragraph break and reopened on the other side of it.)'" />
+ <style>
+ body{
+ font-size:2em;
+ }
+ .test, .ref {
+ border: medium solid gray;
+ width: 400px;
+ margin: 20px;
+ }
+ .comments { display: none; }
+ </style>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the two boxes below look exactly the same.</p></div>
+ <div class="comments">
+ Key to entities used below:
+ &#x05D0; ... &#x05D8; - The first nine Hebrew letters (strongly RTL).
+ &#x200E; - The LRM (left-to-right mark) formatting character (invisible, stronly LTR).
+ &#x200F; - The RLM (right-to-left mark) formatting character (invisible, stronly RTL).
+ &#x202D; - The LRO (left-to-right override) formatting character.
+ &#x202C; - The PDF (pop directional formatting) formatting character; closes LRO.
+ </div>
+ <div class="test">
+ &#x05D1;&#x05D0;&#x200E;
+ <bdo dir="rtl">ih
+ <bdo dir="ltr">&#x05D2;&#x05D3;
+ <span dir="rtl">fg&#x200F;
+ <span dir="ltr">1. I like &#x05D4;.<br/>
+ 2. &#x05D4; is great!</span>
+ &#x200F;cd</span>
+ &#x05D5;&#x05D6;</bdo>
+ ba</bdo>
+ &#x200E;&#x05D8;&#x05D7;
+ </div>
+ <div class="ref">
+ &#x202D;&#x05D0;&#x05D1; &#x05D2;&#x05D3; 1. I like &#x05D4;. fg hi&#x202C;
+ <br/>
+ &#x202D;ab cd 2. &#x05D4; is great! &#x05D5;&#x05D6; &#x05D7;&#x05D8;&#x202C;
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-br-element/br-bidi-ref.html b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-br-element/br-bidi-ref.html
new file mode 100644
index 00000000000..f07c077917f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-br-element/br-bidi-ref.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>HTML Test reference: BR separates bidi paragraph</title>
+ <link rel="author" title="Amir E. Aharoni" href="mailto:amir.aharoni@mail.huji.ac.il"/>
+ <link rel="author" title="Eyal Sela" href="mailto:eyal@post.isoc.org.il"/>
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com"/>
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-br-element"/>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the rightmost character in the first line below is a full stop and to the left of it is a Hebrew letter.</p></div>
+ <div class="test">
+ A Hebrew letter and a full stop: &#x05d0;.&lrm;
+ <br />
+ &#x05d0; this line begins with a Hebrew letter.
+ </div>
+</p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-br-element/br-bidi.html b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-br-element/br-bidi.html
new file mode 100644
index 00000000000..1dfa6836f39
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-br-element/br-bidi.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8"/>
+ <title>HTML Test: BR separates bidi paragraph</title>
+ <link rel="match" href="br-bidi-ref.html">
+ <link rel="author" title="Amir E. Aharoni" href="mailto:amir.aharoni@mail.huji.ac.il"/>
+ <link rel="author" title="Eyal Sela" href="mailto:eyal@post.isoc.org.il"/>
+ <link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com"/>
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-br-element"/>
+ <meta name="assert"
+ content="A br element should separate paragraphs for the purposes of the Unicode bidirectional algorithm."/>
+ </head>
+ <body>
+ <div class="instructions"><p>Test passes if the rightmost character in the first line below is a full stop and to the left of it is a Hebrew letter.</p></div>
+ <div class="test">
+ A Hebrew letter and a full stop: &#x05d0;.
+ <br />
+ &#x05d0; this line begins with a Hebrew letter.
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-cite-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-cite-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-cite-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-code-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-code-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-code-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-dfn-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-dfn-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-dfn-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-em-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-em-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-em-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-i-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-i-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-i-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-kbd-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-kbd-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-kbd-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-mark-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-mark-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-mark-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-q-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-q-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-q-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-rp-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-rp-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-rp-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-rt-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-rt-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-rt-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-ruby-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-ruby-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-ruby-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-s-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-s-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-s-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-samp-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-samp-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-samp-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-small-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-small-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-small-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-span-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-span-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-span-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-strong-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-strong-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-strong-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-sub-and-sup-elements/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-sub-and-sup-elements/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-sub-and-sup-elements/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-time-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-time-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-time-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-time-element/001.html b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-time-element/001.html
new file mode 100644
index 00000000000..49b8dbc9db9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-time-element/001.html
@@ -0,0 +1,68 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>HTML time element API</title>
+ <style>
+#time { visibility: hidden; }
+ </style>
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#the-time-element">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <!-- intentionally nested to test parsing rules -->
+ <p id="time"><time pubdate datetime="2000-02-01T03:04:05Z">Dummy text <time>2001-06-07T<time>08:09<time></time></time>Z</time></time></p>
+ <script type="text/javascript">
+function makeTime(dateTime,contents,dateTimeProp) {
+ var timeEl = document.createElement('time');
+ if( dateTime ) {
+ timeEl.setAttribute('datetime',dateTime);
+ }
+ if( contents ) {
+ timeEl.innerHTML = contents;
+ }
+ if( dateTimeProp ) {
+ timeEl.dateTime = dateTimeProp;
+ }
+ return timeEl;
+}
+
+var timep = document.getElementById('time');
+var times = timep.getElementsByTagName('time');
+
+//TIME elements
+test(function () {
+ assert_equals( times.length, 4 );
+}, 'HTML parsing should locate 4 time elements in this document');
+test(function () {
+ assert_true( !!window.HTMLTimeElement );
+}, 'HTMLTimeElement should be exposed for prototyping');
+test(function () {
+ assert_true( makeTime() instanceof window.HTMLTimeElement, 'createElement variant' );
+ assert_true( times[0] instanceof window.HTMLTimeElement, 'HTML parsing variant' );
+}, 'the time elements should be instanceof HTMLTimeElement');
+
+//dateTime
+test(function () {
+ assert_equals( makeTime('2000-02-01T03:04:05Z','2001-02-01T03:04:05Z').dateTime, '2000-02-01T03:04:05Z' );
+}, 'the datetime attribute should be reflected by the .dateTime property');
+test(function () {
+ assert_equals( typeof makeTime().dateTime, 'string', 'typeof test' );
+ assert_equals( makeTime().dateTime, '', 'value test' );
+}, 'the dateTime IDL property should default to an empty string');
+test(function () {
+ assert_equals( makeTime(false,false,'2000-02-01T03:04:05Z').dateTime, '2000-02-01T03:04:05Z' );
+}, 'the dateTime property should be read/write');
+test(function () {
+ assert_equals( makeTime('go fish').dateTime, 'go fish' );
+}, 'the datetime attribute should be reflected by the .dateTime property even if it is invalid');
+test(function () {
+ assert_equals( makeTime(false,'2000-02-01T03:04:05Z').dateTime, '' );
+}, 'the datetime attribute should not reflect the textContent');
+
+ </script>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-u-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-u-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-u-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-var-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-var-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-var-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-wbr-element/wbr-element-ref.html b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-wbr-element/wbr-element-ref.html
new file mode 100644
index 00000000000..f1a14f421ed
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-wbr-element/wbr-element-ref.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>The wbr element</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel="mismatch" href="wbr-element-notref.html" />
+<meta name="flags" content="ahem">
+<style>
+ p {font-family: Ahem;}
+</style>
+<p>Loremipsumdolorsit<br>amet,consectetur<br>adipisicingelit,sed<br>doeiusmodtempor<br>incididuntutlaboreet<br>doloremagnaaliqua.Ut<br>enimadminimveniam,<br>quisnostrud<br>exercitationullamco<br>laborisnisiutaliquip<br>exeacommodo<br>consequat.Duisaute<br>iruredolorin<br>reprehenderitin<br>voluptatevelitesse<br>cillumdoloreeufugiat<br>nullapariatur.<br>Excepteursint<br>occaecatcupidatatnon<br>proident,suntinculpa<br>quiofficiadeserunt<br>mollitanimidest<br>laborum.</p>
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-wbr-element/wbr-element.html b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-wbr-element/wbr-element.html
new file mode 100644
index 00000000000..ccd0f3cbc00
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/the-wbr-element/wbr-element.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>The wbr element</title>
+<link rel="author" title="Denis Ah-Kang" href="mailto:denis@w3.org">
+<link rel=help href="https://html.spec.whatwg.org/multipage/#rendering">
+<link rel="match" href="wbr-element-ref.html">
+<meta name="flags" content="ahem">
+<style>
+ p {max-width: 300px; font-family: Ahem;}
+</style>
+<p>AHEM_<wbr>ipsum<wbr>dolor<wbr>sit<wbr>amet,<wbr>consectetur<wbr>adipisicing<wbr>elit,<wbr>sed<wbr>do<wbr>eiusmod<wbr>tempor<wbr>incididunt<wbr>ut<wbr>labore<wbr>et<wbr>dolore<wbr>magna<wbr>aliqua.<wbr>Ut<wbr>enim<wbr>ad<wbr>minim<wbr>veniam,<wbr>quis<wbr>nostrud<wbr>exercitation<wbr>ullamco<wbr>laboris<wbr>nisi<wbr>ut<wbr>aliquip<wbr>ex<wbr>ea<wbr>commodo<wbr>consequat.<wbr>Duis<wbr>aute<wbr>irure<wbr>dolor<wbr>in<wbr>reprehenderit<wbr>in<wbr>voluptate<wbr>velit<wbr>esse<wbr>cillum<wbr>dolore<wbr>eu<wbr>fugiat<wbr>nulla<wbr>pariatur.<wbr>Excepteur<wbr>sint<wbr>occaecat<wbr>cupidatat<wbr>non<wbr>proident,<wbr>sunt<wbr>in<wbr>culpa<wbr>qui<wbr>officia<wbr>deserunt<wbr>mollit<wbr>anim<wbr>id<wbr>est<wbr>laborum.</p>
diff --git a/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/usage-summary/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/usage-summary/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/text-level-semantics/usage-summary/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/the-root-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/the-root-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/the-root-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/semantics/the-root-element/the-html-element/.gitkeep b/tests/wpt/web-platform-tests/html/semantics/the-root-element/the-html-element/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/the-root-element/the-html-element/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/syntax/.gitkeep b/tests/wpt/web-platform-tests/html/syntax/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/.gitkeep b/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/support/encodingtests-1.css b/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/support/encodingtests-1.css
new file mode 100644
index 00000000000..a64973ca7ab
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/support/encodingtests-1.css
@@ -0,0 +1,4 @@
+@charset "utf-8";
+.test div.ýäè {
+ width: 100px;
+ }
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/support/encodingtests-15-inverse.css b/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/support/encodingtests-15-inverse.css
new file mode 100644
index 00000000000..112a453b7fc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/support/encodingtests-15-inverse.css
@@ -0,0 +1,4 @@
+@charset "utf-8";
+.test div#box.ÜÀÚ {
+ width: 100px;
+ }
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/support/encodingtests-15.css b/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/support/encodingtests-15.css
new file mode 100644
index 00000000000..b9af2c72930
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/support/encodingtests-15.css
@@ -0,0 +1,4 @@
+@charset "utf-8";
+.test div.ÜÀÚ {
+ width: 100px;
+ }
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/support/encodingtests-utf8.css b/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/support/encodingtests-utf8.css
new file mode 100644
index 00000000000..dc0006ef628
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/support/encodingtests-utf8.css
@@ -0,0 +1,4 @@
+@charset "utf-8";
+.test div.ýäè {
+ width: 100px;
+ }
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-001.html b/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-001.html
new file mode 100644
index 00000000000..a85682adf93
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-001.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+ <title>HTTP charset</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='https://html.spec.whatwg.org/multipage/#the-input-byte-stream'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<meta name='flags' content='http'>
+<style type='text/css'>
+.test div { width: 50px; }</style>
+<link rel="stylesheet" type="text/css" href="support/encodingtests-15.css">
+</head>
+<body>
+
+
+
+<div class='test'><div id='box' class='ýäè'>&#xA0;</div></div>
+
+
+<!--Notes:
+
+The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector <code>.test div.&#x00C3;&#x0153;&#x00C3;&#x20AC;&#x00C3;&#x0161;</code>. This matches the sequence of bytes above when they are interpreted as ISO 8859-15. If the class name matches the selector then the test will pass.
+
+The only character encoding declaration for this HTML file is in the HTTP header, which sets the encoding to ISO 8859-15.
+
+-->
+<script>
+test(function() {
+assert_equals(document.getElementById('box').offsetWidth, 100);
+}, "The character encoding of a page can be set using the HTTP header charset declaration.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-001.html.headers b/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-001.html.headers
new file mode 100644
index 00000000000..3d9718c07bc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-001.html.headers
@@ -0,0 +1 @@
+Content-Type: text/html; charset=iso-8859-15
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-003.html b/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-003.html
new file mode 100644
index 00000000000..5b3863b4c31
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-003.html
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-004.html b/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-004.html
new file mode 100644
index 00000000000..2041daff071
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-004.html
Binary files differ
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-007.html b/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-007.html
new file mode 100644
index 00000000000..03dd532b38d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-007.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+ <meta http-equiv="content-type" content="text/html; charset=iso-8859-15"> <title>meta content attribute</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='https://html.spec.whatwg.org/multipage/#the-input-byte-stream'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<meta name='flags' content='http'>
+<style type='text/css'>
+.test div { width: 50px; }</style>
+<link rel="stylesheet" type="text/css" href="support/encodingtests-15.css">
+</head>
+<body>
+
+
+
+<div class='test'><div id='box' class='ýäè'>&#xA0;</div></div>
+
+
+<!--Notes:
+
+The only character encoding declaration for this HTML file is in the content attribute of the meta element, which declares the encoding to be ISO 8859-15.
+
+The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector <code>.test div.&#x00C3;&#x0153;&#x00C3;&#x20AC;&#x00C3;&#x0161;</code>. This matches the sequence of bytes above when they are interpreted as ISO 8859-15. If the class name matches the selector then the test will pass.
+
+-->
+<script>
+test(function() {
+assert_equals(document.getElementById('box').offsetWidth, 100);
+}, "The character encoding of the page can be set by a meta element with http-equiv and content attributes.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-007.html.headers b/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-007.html.headers
new file mode 100644
index 00000000000..156209f9c81
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-007.html.headers
@@ -0,0 +1 @@
+Content-Type: text/html
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-009.html b/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-009.html
new file mode 100644
index 00000000000..13832928320
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-009.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+ <meta charset="iso-8859-15"> <title>meta charset attribute</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='https://html.spec.whatwg.org/multipage/#the-input-byte-stream'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<meta name='flags' content='http'>
+<style type='text/css'>
+.test div { width: 50px; }</style>
+<link rel="stylesheet" type="text/css" href="support/encodingtests-15.css">
+</head>
+<body>
+
+
+
+<div class='test'><div id='box' class='ýäè'>&#xA0;</div></div>
+
+
+<!--Notes:
+
+The only character encoding declaration for this HTML file is in the charset attribute of the meta element, which declares the encoding to be ISO 8859-15.
+
+The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector <code>.test div.&#x00C3;&#x0153;&#x00C3;&#x20AC;&#x00C3;&#x0161;</code>. This matches the sequence of bytes above when they are interpreted as ISO 8859-15. If the class name matches the selector then the test will pass.
+
+-->
+<script>
+test(function() {
+assert_equals(document.getElementById('box').offsetWidth, 100);
+}, "The character encoding of the page can be set by a meta element with charset attribute.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-009.html.headers b/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-009.html.headers
new file mode 100644
index 00000000000..156209f9c81
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-009.html.headers
@@ -0,0 +1 @@
+Content-Type: text/html
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-015.html b/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-015.html
new file mode 100644
index 00000000000..383c93b5e57
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-015.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+ <title>No encoding declaration</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='https://html.spec.whatwg.org/multipage/#the-input-byte-stream'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<meta name='flags' content='http'>
+<style type='text/css'>
+.test div { width: 50px; }</style>
+<link rel="stylesheet" type="text/css" href="support/encodingtests-utf8.css">
+</head>
+<body>
+
+
+
+<div class='test'><div id='box' class='ýäè'>&#xA0;</div></div>
+
+
+<!--Notes:
+
+The test on this page contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector <code>.test div.&#x00FD;&#x00E4;&#x00E8;</code>. This matches the sequence of bytes above when they are interpreted as UTF-8. If the class name matches the selector then the test will pass.
+
+-->
+<script>
+test(function() {
+assert_equals(document.getElementById('box').offsetWidth, 100);
+}, "A page with no encoding information in HTTP, BOM, XML declaration or meta element will be treated as UTF-8.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-015.html.headers b/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-015.html.headers
new file mode 100644
index 00000000000..156209f9c81
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-015.html.headers
@@ -0,0 +1 @@
+Content-Type: text/html
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-016.html b/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-016.html
new file mode 100644
index 00000000000..141ca3e56f3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-016.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+ <meta http-equiv="content-type" content="text/html;charset=iso-8859-1" > <title>HTTP vs meta content</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='https://html.spec.whatwg.org/multipage/#the-input-byte-stream'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<meta name='flags' content='http'>
+<style type='text/css'>
+.test div { width: 50px; }.test div { width: 90px; }
+</style>
+<link rel="stylesheet" type="text/css" href="support/encodingtests-15.css">
+</head>
+<body>
+
+
+
+<div class='test'><div id='box' class='ýäè'>&#xA0;</div></div>
+
+
+<!--Notes:
+
+The HTTP header attempts to set the character encoding to ISO 8859-15. The page contains an encoding declaration in a meta content attribute that attempts to set the character encoding to ISO 8859-1.
+
+The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector <code>.test div.&#x00C3;&#x0153;&#x00C3;&#x20AC;&#x00C3;&#x0161;</code>. This matches the sequence of bytes above when they are interpreted as ISO 8859-15. If the class name matches the selector then the test will pass.
+
+-->
+<script>
+test(function() {
+assert_equals(document.getElementById('box').offsetWidth, 100);
+}, "The HTTP header has a higher precedence than an encoding declaration in a meta content attribute.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-016.html.headers b/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-016.html.headers
new file mode 100644
index 00000000000..3d9718c07bc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-016.html.headers
@@ -0,0 +1 @@
+Content-Type: text/html; charset=iso-8859-15
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-018.html b/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-018.html
new file mode 100644
index 00000000000..9ee7510e5a0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-018.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+ <meta charset="iso-8859-1" > <title>HTTP vs meta charset</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='https://html.spec.whatwg.org/multipage/#the-input-byte-stream'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<meta name='flags' content='http'>
+<style type='text/css'>
+.test div { width: 50px; }.test div { width: 90px; }
+</style>
+<link rel="stylesheet" type="text/css" href="support/encodingtests-15.css">
+</head>
+<body>
+
+
+
+<div class='test'><div id='box' class='ýäè'>&#xA0;</div></div>
+
+
+<!--Notes:
+
+The HTTP header attempts to set the character encoding to ISO 8859-15. The page contains an encoding declaration in a meta charset attribute that attempts to set the character encoding to ISO 8859-1.
+
+The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector <code>.test div.&#x00C3;&#x0153;&#x00C3;&#x20AC;&#x00C3;&#x0161;</code>. This matches the sequence of bytes above when they are interpreted as ISO 8859-15. If the class name matches the selector then the test will pass.
+
+-->
+<script>
+test(function() {
+assert_equals(document.getElementById('box').offsetWidth, 100);
+}, "The HTTP header has a higher precedence than an encoding declaration in a meta charset attribute.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-018.html.headers b/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-018.html.headers
new file mode 100644
index 00000000000..3d9718c07bc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-018.html.headers
@@ -0,0 +1 @@
+Content-Type: text/html; charset=iso-8859-15
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-030.html b/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-030.html
new file mode 100644
index 00000000000..5f85199928a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-030.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+ <meta charset="iso-8859-15" ><meta http-equiv="content-type" content="text/html;charset=iso-8859-1" > <title>meta charset, then meta content</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='https://html.spec.whatwg.org/multipage/#the-input-byte-stream'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<meta name='flags' content='http'>
+<style type='text/css'>
+.test div { width: 50px; }.test div { width: 90px; }
+</style>
+<link rel="stylesheet" type="text/css" href="support/encodingtests-15.css">
+</head>
+<body>
+
+
+
+<div class='test'><div id='box' class='ýäè'>&#xA0;</div></div>
+
+
+<!--Notes:
+
+The page contains an encoding declaration in a meta charset attribute that attempts to set the character encoding to ISO 8859-15, followed by a meta content attribute that tries to set the encoding to ISO 8859-1.
+
+The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector <code>.test div.&#x00C3;&#x0153;&#x00C3;&#x20AC;&#x00C3;&#x0161;</code>. This matches the sequence of bytes above when they are interpreted as ISO 8859-15. If the class name matches the selector then the test will pass.
+
+-->
+<script>
+test(function() {
+assert_equals(document.getElementById('box').offsetWidth, 100);
+}, "An encoding declaration in a meta charset attribute has a higher precedence than a following encoding declaration in a meta charset attribute.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-030.html.headers b/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-030.html.headers
new file mode 100644
index 00000000000..156209f9c81
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-030.html.headers
@@ -0,0 +1 @@
+Content-Type: text/html
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-034.html b/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-034.html
new file mode 100644
index 00000000000..f0b699792eb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-034.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+ <title>HTTP vs UTF-8 BOM</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='https://html.spec.whatwg.org/multipage/#the-input-byte-stream'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<meta name='flags' content='http'>
+<style type='text/css'>
+.test div { width: 50px; }</style>
+<link rel="stylesheet" type="text/css" href="support/encodingtests-utf8.css">
+</head>
+<body>
+
+
+
+<div class='test'><div id='box' class='ýäè'>&#xA0;</div></div>
+
+
+<!--Notes:
+
+The HTTP header attempts to set the character encoding to ISO 8859-15. The page starts with a UTF-8 signature.
+
+The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector <code>.test div.&#x00FD;&#x00E4;&#x00E8;</code>. This matches the sequence of bytes above when they are interpreted as UTF-8. If the class name matches the selector then the test will pass.
+
+If the test is unsuccessful, the characters &#x00EF;&#x00BB;&#x00BF; should appear at the top of the page. These represent the bytes that make up the UTF-8 signature when encountered in the ISO 8859-15 encoding.
+
+-->
+<script>
+test(function() {
+assert_equals(document.getElementById('box').offsetWidth, 100);
+}, "A character encoding set in the HTTP header has lower precedence than the UTF-8 signature.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-034.html.headers b/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-034.html.headers
new file mode 100644
index 00000000000..3d9718c07bc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-034.html.headers
@@ -0,0 +1 @@
+Content-Type: text/html; charset=iso-8859-15
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-037.html b/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-037.html
new file mode 100644
index 00000000000..1fcf157b237
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-037.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+ <meta http-equiv="content-type" content="text/html; charset=iso-8859-15"> <title>UTF-8 BOM vs meta content</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='https://html.spec.whatwg.org/multipage/#the-input-byte-stream'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<meta name='flags' content='http'>
+<style type='text/css'>
+.test div { width: 50px; }</style>
+<link rel="stylesheet" type="text/css" href="support/encodingtests-utf8.css">
+</head>
+<body>
+
+
+
+<div class='test'><div id='box' class='ýäè'>&#xA0;</div></div>
+
+
+<!--Notes:
+
+The page contains an encoding declaration in a meta content attribute that attempts to set the character encoding to ISO 8859-15, but the file starts with a UTF-8 signature.
+
+The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector <code>.test div.&#x00FD;&#x00E4;&#x00E8;</code>. This matches the sequence of bytes above when they are interpreted as UTF-8. If the class name matches the selector then the test will pass.
+
+-->
+<script>
+test(function() {
+assert_equals(document.getElementById('box').offsetWidth, 100);
+}, "A page with a UTF-8 BOM will be recognized as UTF-8 even if the meta content attribute declares a different encoding.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-037.html.headers b/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-037.html.headers
new file mode 100644
index 00000000000..156209f9c81
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-037.html.headers
@@ -0,0 +1 @@
+Content-Type: text/html
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-038.html b/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-038.html
new file mode 100644
index 00000000000..9432113a25f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-038.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html lang="en" >
+<head>
+ <meta charset="iso-8859-15"> <title>UTF-8 BOM vs meta charset</title>
+<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
+<link rel='help' href='https://html.spec.whatwg.org/multipage/#the-input-byte-stream'>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<meta name='flags' content='http'>
+<style type='text/css'>
+.test div { width: 50px; }.test div { width: 90px; }
+</style>
+<link rel="stylesheet" type="text/css" href="support/encodingtests-utf8.css">
+</head>
+<body>
+
+
+
+<div class='test'><div id='box' class='ýäè'>&#xA0;</div></div>
+
+
+<!--Notes:
+
+The page contains an encoding declaration in a meta charset attribute that attempts to set the character encoding to ISO 8859-15, but the file starts with a UTF-8 signature.
+
+The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector <code>.test div.&#x00FD;&#x00E4;&#x00E8;</code>. This matches the sequence of bytes above when they are interpreted as UTF-8. If the class name matches the selector then the test will pass.
+
+-->
+<script>
+test(function() {
+assert_equals(document.getElementById('box').offsetWidth, 100);
+}, "A page with a UTF-8 BOM will be recognized as UTF-8 even if the meta charset attribute declares a different encoding.");
+</script>
+
+<div id='log'></div>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-038.html.headers b/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-038.html.headers
new file mode 100644
index 00000000000..156209f9c81
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing-html-fragments/the-input-byte-stream-038.html.headers
@@ -0,0 +1 @@
+Content-Type: text/html
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/.gitkeep b/tests/wpt/web-platform-tests/html/syntax/parsing/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/Document.getElementsByTagName-foreign-01.html b/tests/wpt/web-platform-tests/html/syntax/parsing/Document.getElementsByTagName-foreign-01.html
new file mode 100644
index 00000000000..2bdc83145e3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/Document.getElementsByTagName-foreign-01.html
@@ -0,0 +1,143 @@
+<!DOCTYPE html>
+<title>document.getElementsByTagName and foreign parser-inserted
+elements</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-document-getelementsbytagname">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#parsing">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<div id="test">
+<svg>
+<altglyph/>
+ <altglyphdef/>
+ <altglyphitem/>
+ <animatecolor/>
+ <animatemotion/>
+ <animatetransform/>
+ <clippath/>
+ <feblend/>
+ <fecolormatrix/>
+ <fecomponenttransfer/>
+ <fecomposite/>
+ <feconvolvematrix/>
+ <fediffuselighting/>
+ <fedisplacementmap/>
+ <fedistantlight/>
+ <feflood/>
+ <fefunca/>
+ <fefuncb/>
+ <fefuncg/>
+ <fefuncr/>
+ <fegaussianblur/>
+ <feimage/>
+ <femerge/>
+ <femergenode/>
+ <femorphology/>
+ <feoffset/>
+ <fepointlight/>
+ <fespecularlighting/>
+ <fespotlight/>
+ <fetile/>
+ <feturbulence/>
+ <foreignobject/>
+ <glyphref/>
+ <lineargradient/>
+ <radialgradient/>
+ <textpath/>
+ <ALTGLYPH/>
+ <ALTGLYPHDEF/>
+ <ALTGLYPHITEM/>
+ <ANIMATECOLOR/>
+ <ANIMATEMOTION/>
+ <ANIMATETRANSFORM/>
+ <CLIPPATH/>
+ <FEBLEND/>
+ <FECOLORMATRIX/>
+ <FECOMPONENTTRANSFER/>
+ <FECOMPOSITE/>
+ <FECONVOLVEMATRIX/>
+ <FEDIFFUSELIGHTING/>
+ <FEDISPLACEMENTMAP/>
+ <FEDISTANTLIGHT/>
+ <FEFLOOD/>
+ <FEFUNCA/>
+ <FEFUNCB/>
+ <FEFUNCG/>
+ <FEFUNCR/>
+ <FEGAUSSIANBLUR/>
+ <FEIMAGE/>
+ <FEMERGE/>
+ <FEMERGENODE/>
+ <FEMORPHOLOGY/>
+ <FEOFFSET/>
+ <FEPOINTLIGHT/>
+ <FESPECULARLIGHTING/>
+ <FESPOTLIGHT/>
+ <FETILE/>
+ <FETURBULENCE/>
+ <FOREIGNOBJECT/>
+ <GLYPHREF/>
+ <LINEARGRADIENT/>
+ <RADIALGRADIENT/>
+ <TEXTPATH/>
+</svg>
+<script>
+var elements = [
+ "altGlyph",
+ "altGlyphDef",
+ "altGlyphItem",
+ "animateColor",
+ "animateMotion",
+ "animateTransform",
+ "clipPath",
+ "feBlend",
+ "feColorMatrix",
+ "feComponentTransfer",
+ "feComposite",
+ "feConvolveMatrix",
+ "feDiffuseLighting",
+ "feDisplacementMap",
+ "feDistantLight",
+ "feFlood",
+ "feFuncA",
+ "feFuncB",
+ "feFuncG",
+ "feFuncR",
+ "feGaussianBlur",
+ "feImage",
+ "feMerge",
+ "feMergeNode",
+ "feMorphology",
+ "feOffset",
+ "fePointLight",
+ "feSpecularLighting",
+ "feSpotLight",
+ "feTile",
+ "feTurbulence",
+ "foreignObject",
+ "glyphRef",
+ "linearGradient",
+ "radialGradient",
+ "textPath"];
+</script>
+</div>
+<script>
+var SVG = "http://www.w3.org/2000/svg";
+function t(el) {
+ assert_equals(document.getElementsByTagName(el).length, 2);
+ assert_equals(document.getElementsByTagName(el.toUpperCase()).length, 0);
+ assert_equals(document.getElementsByTagName(el.toLowerCase()).length, 0);
+ assert_equals(document.getElementsByTagNameNS(SVG, el).length, 2);
+ assert_equals(document.getElementsByTagNameNS(SVG, el.toUpperCase()).length, 0);
+ assert_equals(document.getElementsByTagNameNS(SVG, el.toLowerCase()).length, 0);
+}
+test(function() {
+ var tests = [];
+ assert_equals(document.getElementsByTagName('svg').length, 1);
+ for (var i = 0, il = elements.length; i < il; ++i) {
+ tests.push(["Testing " + elements[i], elements[i]]);
+ }
+ generate_tests(t, tests);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/Document.getElementsByTagName-foreign-02.html b/tests/wpt/web-platform-tests/html/syntax/parsing/Document.getElementsByTagName-foreign-02.html
new file mode 100644
index 00000000000..1109a24cfee
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/Document.getElementsByTagName-foreign-02.html
@@ -0,0 +1,24 @@
+<!doctype html>
+<title>getElementsByTagName and font</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-document-getelementsbytagname">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#parsing">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<div id="test">
+<font></font>
+<svg><font/></svg>
+</div>
+<script>
+var HTML = "http://www.w3.org/1999/xhtml", SVG = "http://www.w3.org/2000/svg";
+test(function() {
+ assert_equals(document.getElementsByTagName("FONT").length, 1);
+ assert_equals(document.getElementsByTagName("FONT")[0].namespaceURI, HTML);
+}, "Upper-case font")
+test(function() {
+ assert_equals(document.getElementsByTagName("font").length, 2);
+ assert_equals(document.getElementsByTagName("font")[0].namespaceURI, HTML);
+ assert_equals(document.getElementsByTagName("font")[1].namespaceURI, SVG);
+}, "Lower-case font")
+</script>
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/Element.getElementsByTagName-foreign-01.html b/tests/wpt/web-platform-tests/html/syntax/parsing/Element.getElementsByTagName-foreign-01.html
new file mode 100644
index 00000000000..cbad9f6d195
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/Element.getElementsByTagName-foreign-01.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<title>getElementsByTagName and font</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-element-getelementsbytagname">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#parsing">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<div id="test">
+<font></font>
+<svg><font/></svg>
+</div>
+<script>
+var HTML = "http://www.w3.org/1999/xhtml", SVG = "http://www.w3.org/2000/svg";
+var wrapper = document.getElementById("test");
+test(function() {
+ assert_equals(wrapper.getElementsByTagName("FONT").length, 1);
+ assert_equals(wrapper.getElementsByTagName("FONT")[0].namespaceURI, HTML);
+}, "Upper-case font")
+test(function() {
+ assert_equals(wrapper.getElementsByTagName("font").length, 2);
+ assert_equals(wrapper.getElementsByTagName("font")[0].namespaceURI, HTML);
+ assert_equals(wrapper.getElementsByTagName("font")[1].namespaceURI, SVG);
+}, "Lower-case font")
+</script>
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/Element.getElementsByTagName-foreign-02.html b/tests/wpt/web-platform-tests/html/syntax/parsing/Element.getElementsByTagName-foreign-02.html
new file mode 100644
index 00000000000..aabb169b1b5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/Element.getElementsByTagName-foreign-02.html
@@ -0,0 +1,29 @@
+<!doctype html>
+<title>getElementsByTagName and font</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://dom.spec.whatwg.org/#dom-element-getelementsbytagname">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#parsing">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<div id="test">
+<svg id="outer">
+<foreignObject>
+<font></font>
+<svg><font/></svg>
+</foreignObject>
+</svg>
+</div>
+<script>
+var HTML = "http://www.w3.org/1999/xhtml", SVG = "http://www.w3.org/2000/svg";
+var wrapper = document.getElementById("outer");
+test(function() {
+ assert_equals(wrapper.getElementsByTagName("FONT").length, 1);
+ assert_equals(wrapper.getElementsByTagName("FONT")[0].namespaceURI, HTML);
+}, "Upper-case font")
+test(function() {
+ assert_equals(wrapper.getElementsByTagName("font").length, 2);
+ assert_equals(wrapper.getElementsByTagName("font")[0].namespaceURI, HTML);
+ assert_equals(wrapper.getElementsByTagName("font")[1].namespaceURI, SVG);
+}, "Lower-case font")
+</script>
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/README b/tests/wpt/web-platform-tests/html/syntax/parsing/README
new file mode 100644
index 00000000000..8e4ae0808b6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/README
@@ -0,0 +1,4 @@
+Note: the html5lib_* files in this directory are autogenerated.
+
+To update them use the script /tools/scripts/update_html5lib_tests.py.
+Further instructions are provided in that file. \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/common.js b/tests/wpt/web-platform-tests/html/syntax/parsing/common.js
new file mode 100644
index 00000000000..9c85650c3f4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/common.js
@@ -0,0 +1,24 @@
+function mark_diffs(expected, actual) {
+ var expected_lines = expected.split("\n");
+ var actual_lines = actual.split("\n");
+
+ var max_length = Math.max(expected_lines.length, actual_lines.length);
+
+ var expected_diff = ["code", {}];
+ var actual_diff = ["code", {}];
+
+ for (var i=0; i<max_length; i++) {
+ if (expected_lines[i] === actual_lines[i]) {
+ expected_diff.push(expected_lines[i] + "\n");
+ actual_diff.push(actual_lines[i] + "\n");
+ } else {
+ if (expected_lines[i]) {
+ expected_diff.push(["span", {style:"color:red"}, expected_lines[i] + "\n"]);
+ }
+ if (actual_lines[i]) {
+ actual_diff.push(["span", {style:"color:red"}, actual_lines[i] + "\n"]);
+ }
+ }
+ }
+ return [expected_diff, actual_diff];
+} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/contains.json b/tests/wpt/web-platform-tests/html/syntax/parsing/contains.json
new file mode 100644
index 00000000000..249c9fe014a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/contains.json
@@ -0,0 +1,490 @@
+[
+ {
+ "id": "overview-of-the-parsing-model",
+ "original_id": "overview-of-the-parsing-model"
+ },
+ {
+ "id": "the-input-byte-stream",
+ "original_id": "the-input-byte-stream",
+ "children": [
+ {
+ "id": "determining-the-character-encoding",
+ "original_id": "determining-the-character-encoding"
+ },
+ {
+ "id": "character-encodings-0",
+ "original_id": "character-encodings-0"
+ },
+ {
+ "id": "changing-the-encoding-while-parsing",
+ "original_id": "changing-the-encoding-while-parsing"
+ },
+ {
+ "id": "preprocessing-the-input-stream",
+ "original_id": "preprocessing-the-input-stream"
+ }
+ ]
+ },
+ {
+ "id": "parse-state",
+ "original_id": "parse-state",
+ "children": [
+ {
+ "id": "the-insertion-mode",
+ "original_id": "the-insertion-mode"
+ },
+ {
+ "id": "the-stack-of-open-elements",
+ "original_id": "the-stack-of-open-elements"
+ },
+ {
+ "id": "the-list-of-active-formatting-elements",
+ "original_id": "the-list-of-active-formatting-elements"
+ },
+ {
+ "id": "the-element-pointers",
+ "original_id": "the-element-pointers"
+ },
+ {
+ "id": "other-parsing-state-flags",
+ "original_id": "other-parsing-state-flags"
+ }
+ ]
+ },
+ {
+ "id": "tokenization",
+ "original_id": "tokenization",
+ "children": [
+ {
+ "id": "data-state",
+ "original_id": "data-state"
+ },
+ {
+ "id": "character-reference-in-data-state",
+ "original_id": "character-reference-in-data-state"
+ },
+ {
+ "id": "rcdata-state",
+ "original_id": "rcdata-state"
+ },
+ {
+ "id": "character-reference-in-rcdata-state",
+ "original_id": "character-reference-in-rcdata-state"
+ },
+ {
+ "id": "rawtext-state",
+ "original_id": "rawtext-state"
+ },
+ {
+ "id": "script-data-state",
+ "original_id": "script-data-state"
+ },
+ {
+ "id": "plaintext-state",
+ "original_id": "plaintext-state"
+ },
+ {
+ "id": "tag-open-state",
+ "original_id": "tag-open-state"
+ },
+ {
+ "id": "end-tag-open-state",
+ "original_id": "end-tag-open-state"
+ },
+ {
+ "id": "tag-name-state",
+ "original_id": "tag-name-state"
+ },
+ {
+ "id": "rcdata-less-than-sign-state",
+ "original_id": "rcdata-less-than-sign-state"
+ },
+ {
+ "id": "rcdata-end-tag-open-state",
+ "original_id": "rcdata-end-tag-open-state"
+ },
+ {
+ "id": "rcdata-end-tag-name-state",
+ "original_id": "rcdata-end-tag-name-state"
+ },
+ {
+ "id": "rawtext-less-than-sign-state",
+ "original_id": "rawtext-less-than-sign-state"
+ },
+ {
+ "id": "rawtext-end-tag-open-state",
+ "original_id": "rawtext-end-tag-open-state"
+ },
+ {
+ "id": "rawtext-end-tag-name-state",
+ "original_id": "rawtext-end-tag-name-state"
+ },
+ {
+ "id": "script-data-less-than-sign-state",
+ "original_id": "script-data-less-than-sign-state"
+ },
+ {
+ "id": "script-data-end-tag-open-state",
+ "original_id": "script-data-end-tag-open-state"
+ },
+ {
+ "id": "script-data-end-tag-name-state",
+ "original_id": "script-data-end-tag-name-state"
+ },
+ {
+ "id": "script-data-escape-start-state",
+ "original_id": "script-data-escape-start-state"
+ },
+ {
+ "id": "script-data-escape-start-dash-state",
+ "original_id": "script-data-escape-start-dash-state"
+ },
+ {
+ "id": "script-data-escaped-state",
+ "original_id": "script-data-escaped-state"
+ },
+ {
+ "id": "script-data-escaped-dash-state",
+ "original_id": "script-data-escaped-dash-state"
+ },
+ {
+ "id": "script-data-escaped-dash-dash-state",
+ "original_id": "script-data-escaped-dash-dash-state"
+ },
+ {
+ "id": "script-data-escaped-less-than-sign-state",
+ "original_id": "script-data-escaped-less-than-sign-state"
+ },
+ {
+ "id": "script-data-escaped-end-tag-open-state",
+ "original_id": "script-data-escaped-end-tag-open-state"
+ },
+ {
+ "id": "script-data-escaped-end-tag-name-state",
+ "original_id": "script-data-escaped-end-tag-name-state"
+ },
+ {
+ "id": "script-data-double-escape-start-state",
+ "original_id": "script-data-double-escape-start-state"
+ },
+ {
+ "id": "script-data-double-escaped-state",
+ "original_id": "script-data-double-escaped-state"
+ },
+ {
+ "id": "script-data-double-escaped-dash-state",
+ "original_id": "script-data-double-escaped-dash-state"
+ },
+ {
+ "id": "script-data-double-escaped-dash-dash-state",
+ "original_id": "script-data-double-escaped-dash-dash-state"
+ },
+ {
+ "id": "script-data-double-escaped-less-than-sign-state",
+ "original_id": "script-data-double-escaped-less-than-sign-state"
+ },
+ {
+ "id": "script-data-double-escape-end-state",
+ "original_id": "script-data-double-escape-end-state"
+ },
+ {
+ "id": "before-attribute-name-state",
+ "original_id": "before-attribute-name-state"
+ },
+ {
+ "id": "attribute-name-state",
+ "original_id": "attribute-name-state"
+ },
+ {
+ "id": "after-attribute-name-state",
+ "original_id": "after-attribute-name-state"
+ },
+ {
+ "id": "before-attribute-value-state",
+ "original_id": "before-attribute-value-state"
+ },
+ {
+ "id": "attribute-value-double-quoted-state",
+ "original_id": "attribute-value-(double-quoted)-state"
+ },
+ {
+ "id": "attribute-value-single-quoted-state",
+ "original_id": "attribute-value-(single-quoted)-state"
+ },
+ {
+ "id": "attribute-value-unquoted-state",
+ "original_id": "attribute-value-(unquoted)-state"
+ },
+ {
+ "id": "character-reference-in-attribute-value-state",
+ "original_id": "character-reference-in-attribute-value-state"
+ },
+ {
+ "id": "after-attribute-value-quoted-state",
+ "original_id": "after-attribute-value-(quoted)-state"
+ },
+ {
+ "id": "self-closing-start-tag-state",
+ "original_id": "self-closing-start-tag-state"
+ },
+ {
+ "id": "bogus-comment-state",
+ "original_id": "bogus-comment-state"
+ },
+ {
+ "id": "markup-declaration-open-state",
+ "original_id": "markup-declaration-open-state"
+ },
+ {
+ "id": "comment-start-state",
+ "original_id": "comment-start-state"
+ },
+ {
+ "id": "comment-start-dash-state",
+ "original_id": "comment-start-dash-state"
+ },
+ {
+ "id": "comment-state",
+ "original_id": "comment-state"
+ },
+ {
+ "id": "comment-end-dash-state",
+ "original_id": "comment-end-dash-state"
+ },
+ {
+ "id": "comment-end-state",
+ "original_id": "comment-end-state"
+ },
+ {
+ "id": "comment-end-bang-state",
+ "original_id": "comment-end-bang-state"
+ },
+ {
+ "id": "doctype-state",
+ "original_id": "doctype-state"
+ },
+ {
+ "id": "before-doctype-name-state",
+ "original_id": "before-doctype-name-state"
+ },
+ {
+ "id": "doctype-name-state",
+ "original_id": "doctype-name-state"
+ },
+ {
+ "id": "after-doctype-name-state",
+ "original_id": "after-doctype-name-state"
+ },
+ {
+ "id": "after-doctype-public-keyword-state",
+ "original_id": "after-doctype-public-keyword-state"
+ },
+ {
+ "id": "before-doctype-public-identifier-state",
+ "original_id": "before-doctype-public-identifier-state"
+ },
+ {
+ "id": "doctype-public-identifier-double-quoted-state",
+ "original_id": "doctype-public-identifier-(double-quoted)-state"
+ },
+ {
+ "id": "doctype-public-identifier-single-quoted-state",
+ "original_id": "doctype-public-identifier-(single-quoted)-state"
+ },
+ {
+ "id": "after-doctype-public-identifier-state",
+ "original_id": "after-doctype-public-identifier-state"
+ },
+ {
+ "id": "between-doctype-public-and-system-identifiers-state",
+ "original_id": "between-doctype-public-and-system-identifiers-state"
+ },
+ {
+ "id": "after-doctype-system-keyword-state",
+ "original_id": "after-doctype-system-keyword-state"
+ },
+ {
+ "id": "before-doctype-system-identifier-state",
+ "original_id": "before-doctype-system-identifier-state"
+ },
+ {
+ "id": "doctype-system-identifier-double-quoted-state",
+ "original_id": "doctype-system-identifier-(double-quoted)-state"
+ },
+ {
+ "id": "doctype-system-identifier-single-quoted-state",
+ "original_id": "doctype-system-identifier-(single-quoted)-state"
+ },
+ {
+ "id": "after-doctype-system-identifier-state",
+ "original_id": "after-doctype-system-identifier-state"
+ },
+ {
+ "id": "bogus-doctype-state",
+ "original_id": "bogus-doctype-state"
+ },
+ {
+ "id": "cdata-section-state",
+ "original_id": "cdata-section-state"
+ },
+ {
+ "id": "tokenizing-character-references",
+ "original_id": "tokenizing-character-references"
+ }
+ ]
+ },
+ {
+ "id": "tree-construction",
+ "original_id": "tree-construction",
+ "children": [
+ {
+ "id": "creating-and-inserting-elements",
+ "original_id": "creating-and-inserting-elements"
+ },
+ {
+ "id": "closing-elements-that-have-implied-end-tags",
+ "original_id": "closing-elements-that-have-implied-end-tags"
+ },
+ {
+ "id": "foster-parenting",
+ "original_id": "foster-parenting"
+ },
+ {
+ "id": "parsing-main-inhtml",
+ "original_id": "parsing-main-inhtml",
+ "children": [
+ {
+ "id": "the-initial-insertion-mode",
+ "original_id": "the-initial-insertion-mode"
+ },
+ {
+ "id": "the-before-html-insertion-mode",
+ "original_id": "the-before-html-insertion-mode"
+ },
+ {
+ "id": "the-before-head-insertion-mode",
+ "original_id": "the-before-head-insertion-mode"
+ },
+ {
+ "id": "parsing-main-inhead",
+ "original_id": "parsing-main-inhead"
+ },
+ {
+ "id": "parsing-main-inheadnoscript",
+ "original_id": "parsing-main-inheadnoscript"
+ },
+ {
+ "id": "the-after-head-insertion-mode",
+ "original_id": "the-after-head-insertion-mode"
+ },
+ {
+ "id": "parsing-main-inbody",
+ "original_id": "parsing-main-inbody"
+ },
+ {
+ "id": "parsing-main-incdata",
+ "original_id": "parsing-main-incdata"
+ },
+ {
+ "id": "parsing-main-intable",
+ "original_id": "parsing-main-intable"
+ },
+ {
+ "id": "parsing-main-intabletext",
+ "original_id": "parsing-main-intabletext"
+ },
+ {
+ "id": "parsing-main-incaption",
+ "original_id": "parsing-main-incaption"
+ },
+ {
+ "id": "parsing-main-incolgroup",
+ "original_id": "parsing-main-incolgroup"
+ },
+ {
+ "id": "parsing-main-intbody",
+ "original_id": "parsing-main-intbody"
+ },
+ {
+ "id": "parsing-main-intr",
+ "original_id": "parsing-main-intr"
+ },
+ {
+ "id": "parsing-main-intd",
+ "original_id": "parsing-main-intd"
+ },
+ {
+ "id": "parsing-main-inselect",
+ "original_id": "parsing-main-inselect"
+ },
+ {
+ "id": "parsing-main-inselectintable",
+ "original_id": "parsing-main-inselectintable"
+ },
+ {
+ "id": "parsing-main-afterbody",
+ "original_id": "parsing-main-afterbody"
+ },
+ {
+ "id": "parsing-main-inframeset",
+ "original_id": "parsing-main-inframeset"
+ },
+ {
+ "id": "parsing-main-afterframeset",
+ "original_id": "parsing-main-afterframeset"
+ },
+ {
+ "id": "the-after-after-body-insertion-mode",
+ "original_id": "the-after-after-body-insertion-mode"
+ },
+ {
+ "id": "the-after-after-frameset-insertion-mode",
+ "original_id": "the-after-after-frameset-insertion-mode"
+ }
+ ]
+ },
+ {
+ "id": "parsing-main-inforeign",
+ "original_id": "parsing-main-inforeign"
+ }
+ ]
+ },
+ {
+ "id": "the-end",
+ "original_id": "the-end"
+ },
+ {
+ "id": "coercing-an-html-dom-into-an-infoset",
+ "original_id": "coercing-an-html-dom-into-an-infoset"
+ },
+ {
+ "id": "an-introduction-to-error-handling-and-strange-cases-in-the-parser",
+ "original_id": "an-introduction-to-error-handling-and-strange-cases-in-the-parser",
+ "children": [
+ {
+ "id": "misnested-tags-b-i-b-i",
+ "original_id": "misnested-tags:-b-i-/b-/i"
+ },
+ {
+ "id": "misnested-tags-b-p-b-p",
+ "original_id": "misnested-tags:-b-p-/b-/p"
+ },
+ {
+ "id": "unexpected-markup-in-tables",
+ "original_id": "unexpected-markup-in-tables"
+ },
+ {
+ "id": "scripts-that-modify-the-page-as-it-is-being-parsed",
+ "original_id": "scripts-that-modify-the-page-as-it-is-being-parsed"
+ },
+ {
+ "id": "the-execution-of-scripts-that-are-moving-across-multiple-documents",
+ "original_id": "the-execution-of-scripts-that-are-moving-across-multiple-documents"
+ },
+ {
+ "id": "unclosed-formatting-elements",
+ "original_id": "unclosed-formatting-elements"
+ }
+ ]
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/foreign_content_001.html b/tests/wpt/web-platform-tests/html/syntax/parsing/foreign_content_001.html
new file mode 100644
index 00000000000..10ebaa8434f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/foreign_content_001.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>HTML 5 Foreign Content SVG in HTML </title>
+ <meta description="Test to verify SVG inside HTML OBJECT element parses correctly" />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+
+ <script type="text/javascript">
+ function RunTest()
+ {
+ try
+ {
+ var svgNS = "http://www.w3.org/2000/svg";
+ if(document.getElementsByTagName("object")[0].childNodes[1].localName=="svg" && document.getElementsByTagName("rect")[0].namespaceURI==svgNS)
+ {
+ document.getElementsByTagName("rect")[0].setAttribute("fill","green");
+ }
+ else
+ {
+ document.getElementsByTagName("rect")[0].setAttribute("fill","red");
+ }
+ }
+ catch(ex)
+ {
+ document.getElementsByTagName("rect")[0].setAttribute("fill","red")
+ }
+ }
+ </script>
+ </head>
+
+ <body onLoad="RunTest()">
+ <div class="testdata">
+ <p id="instructions"> Test passes if a green rectangle is visible on the page below this line. </p>
+ </div>
+
+ <object>
+ <svg width="100px" height="100px" >
+ <rect width="100px" height="100px" fill="none"/>
+ </svg>
+ </object>
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/foreign_content_003.html b/tests/wpt/web-platform-tests/html/syntax/parsing/foreign_content_003.html
new file mode 100644
index 00000000000..320a9440924
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/foreign_content_003.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>HTML 5 Foreign Content SVG in HTML </title>
+ <meta description="Test to verify SVG inside HTML BUTTON element parses correctly" />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+
+ <script type="text/javascript">
+ function RunTest()
+ {
+ try
+ {
+ var svgNS = "http://www.w3.org/2000/svg";
+ if(document.getElementsByTagName("button")[0].childNodes[1].localName=="svg" && document.getElementsByTagName("rect")[0].namespaceURI==svgNS)
+ {
+ document.getElementsByTagName("rect")[0].setAttribute("fill","green");
+ }
+ else
+ {
+ document.getElementsByTagName("rect")[0].setAttribute("fill","red");
+ }
+ }
+ catch(ex)
+ {
+ document.getElementsByTagName("rect")[0].setAttribute("fill","red")
+ }
+ }
+ </script>
+ </head>
+
+ <body onLoad="RunTest()">
+
+ <div class="testdata">
+ <p id="instructions">Test passes if the button has a green rectangle while 'FillerText1' and 'FillerText3' are on either side of the button.</p>
+ </div>
+ <div>
+ FillerText1
+ <button>
+ <svg width="100px" height="100px">
+ <rect width="100px" height="100px" fill="none" />
+ </svg>
+
+ </button>
+ FillerText3
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/foreign_content_004.html b/tests/wpt/web-platform-tests/html/syntax/parsing/foreign_content_004.html
new file mode 100644
index 00000000000..eec49a81d18
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/foreign_content_004.html
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>HTML 5 Foreign Content SVG in HTML </title>
+ <meta description="Test to verify SVG inside HTML CAPTION element parses correctly" />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+
+ <script type="text/javascript">
+ function RunTest()
+ {
+ try
+ {
+ var svgNS = "http://www.w3.org/2000/svg";
+ if(document.getElementsByTagName("caption")[0].childNodes[1].localName=="svg" && document.getElementsByTagName("rect")[0].namespaceURI==svgNS)
+ {
+ document.getElementsByTagName("rect")[0].setAttribute("fill","green");
+ }
+ else
+ {
+ document.getElementsByTagName("rect")[0].setAttribute("fill","red");
+ }
+ }
+ catch(ex)
+ {
+ document.getElementsByTagName("rect")[0].setAttribute("fill","red")
+ }
+ }
+ </script>
+ </head>
+
+ <body onLoad="RunTest()">
+ <div class="testdata">
+ <p id="instructions">Test passes if a green square appears above and centered relative to the table.</p>
+ </div>
+ <div>
+ <table border="1">
+ <caption>
+ <svg width="100px" height="100px">
+ <rect width="100px" height="100px" fill="none" />
+ </svg>
+ </caption>
+ <thead>
+ <th>FillerText</th>
+ <th>FillerText</th>
+ <th>FillerText</th>
+ </thead>
+ <tr>
+ <td>FillerText</td>
+ <td>FillerText</td>
+ <td>FillerText</td>
+ </tr>
+ <tr>
+ <td>FillerText</td>
+ <td>FillerText</td>
+ <td>FillerText</td>
+ </tr>
+ <tr>
+ <td>FillerText</td>
+ <td>FillerText</td>
+ <td>FillerText</td>
+ </tr>
+ </table>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/foreign_content_005.html b/tests/wpt/web-platform-tests/html/syntax/parsing/foreign_content_005.html
new file mode 100644
index 00000000000..b8629dc7c6d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/foreign_content_005.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>HTML 5 Foreign Content SVG in HTML </title>
+ <meta description="Test to verify SVG inside HTML FORM element parses correctly" />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+
+ <script type="text/javascript">
+ function RunTest()
+ {
+ try
+ {
+ var svgNS = "http://www.w3.org/2000/svg";
+ if(document.getElementsByTagName("form")[0].childNodes[1].localName=="svg" && document.getElementsByTagName("rect")[0].namespaceURI==svgNS)
+ {
+ document.getElementsByTagName("rect")[0].setAttribute("fill","green");
+ }
+ else
+ {
+ document.getElementsByTagName("rect")[0].setAttribute("fill","red");
+ }
+ }
+ catch(ex)
+ {
+ document.getElementsByTagName("rect")[0].setAttribute("fill","red")
+ }
+ }
+ </script>
+ </head>
+
+ <body onLoad="RunTest()">
+ <div class="testdata">
+ <p id="instructions">Test passes if green rectangle is visible below 'FillerText1'.</p>
+ </div>
+ <div>
+ FillerText1
+ <form>
+ <svg width="100px" height="100px">
+ <rect width="100px" height="100px" fill="none" />
+ </svg>
+ </form>
+
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/foreign_content_006.html b/tests/wpt/web-platform-tests/html/syntax/parsing/foreign_content_006.html
new file mode 100644
index 00000000000..36acda8fc39
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/foreign_content_006.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+ <svg width="100px" height="100px">
+ <rect width="100px" height="100px" fill="none" />
+ </svg>
+
+ <head>
+ <title>HTML 5 Foreign Content SVG in HTML </title>
+ <meta description="Test to verify SVG inside HTML 'HTML' element parses correctly" />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <script type="text/javascript">
+ function RunTest()
+ {
+ try
+ {
+ if(document.body.childNodes[0].localName=="svg")
+ {
+ document.getElementsByTagName("rect")[0].setAttribute("fill","green");
+ }
+ else
+ {
+ document.getElementsByTagName("rect")[0].setAttribute("fill","red");
+ }
+ }
+ catch(ex)
+ {
+ document.getElementsByTagName("rect")[0].setAttribute("fill","red")
+ }
+ }
+ </script>
+ </head>
+
+ <body onLoad="RunTest()">
+ <div class="testdata">
+ <p id="instructions">Test passes if a green rectangle is visible on the page above this line.</p>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/foreign_content_008.html b/tests/wpt/web-platform-tests/html/syntax/parsing/foreign_content_008.html
new file mode 100644
index 00000000000..348ff0b7137
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/foreign_content_008.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>HTML 5 Foreign Content SVG in HTML </title>
+ <meta description="Test to verify SVG inside HTML 'BODY' element parses correctly" />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+
+ <script type="text/javascript">
+ function RunTest()
+ {
+ try
+ {
+ if(document.body.childNodes[3].localName=="svg")
+ {
+ document.getElementsByTagName("rect")[0].setAttribute("fill","green");
+ }
+ else
+ {
+ document.getElementsByTagName("rect")[0].setAttribute("fill","red");
+ }
+ }
+ catch(ex)
+ {
+ document.getElementsByTagName("rect")[0].setAttribute("fill","red")
+ }
+ }
+ </script>
+ </head>
+
+ <body onLoad="RunTest()">
+ <div class="testdata">
+ <p id="instructions"> Test passes if a green rectangle is visible on the page below this line. </p>
+ </div>
+ <svg width="100px" height="100px" >
+ <rect x="0" y="0" width="100px" height="100px" />
+ </svg>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/foreign_content_009.html b/tests/wpt/web-platform-tests/html/syntax/parsing/foreign_content_009.html
new file mode 100644
index 00000000000..364dd857811
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/foreign_content_009.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>HTML 5 Foreign Content SVG in HTML </title>
+ <meta description="Test to verify SVG Self Closing tags parses properly" />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+
+ <script type="text/javascript">
+ function RunTest()
+ {
+ try
+ {
+ var parentNode = document.getElementById("rect1");
+ if(parentNode.childNodes[1].localName=="circle")
+ {
+ document.getElementById("testresult").innerHTML = "PASS";
+ }
+ else
+ {
+ document.getElementById("testresult").innerHTML = "FAIL"
+ }
+ }
+ catch(ex)
+ {
+ document.getElementById("testresult").innerHTML = "FAIL";
+ }
+ }
+ </script>
+ </head>
+
+ <body onload="RunTest()">
+ <div class="testdata">
+ <p id="instructions"> Test passes if the word "PASS" appears below </p>
+ <p> Test Result : </p>
+ <p id="testresult"> RUNNING </div>
+ </div>
+
+ <svg width="100px" height="100px">
+ <rect id="rect1" >
+ <circle> </circle>
+ </rect>
+ </svg>
+
+ </body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/foreign_content_010.html b/tests/wpt/web-platform-tests/html/syntax/parsing/foreign_content_010.html
new file mode 100644
index 00000000000..11e1bf10066
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/foreign_content_010.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>HTML 5 Foreign Content SVG in HTML </title>
+ <meta description="Test to verify SVG Self Closing tags parses properly" />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+
+ <script type="text/javascript">
+ function RunTest()
+ {
+ try
+ {
+ var parentNode = document.getElementById("svg1");
+ if(parentNode.childNodes[1].localName=="rect" && parentNode.childNodes[3].localName=="circle")
+ {
+ document.getElementById("testresult").innerHTML = "PASS";
+ }
+ else
+ {
+ document.getElementById("testresult").innerHTML = "FAIL"
+ }
+ }
+ catch(ex)
+ {
+ document.getElementById("testresult").innerHTML = "FAIL";
+ }
+ }
+ </script>
+ </head>
+
+ <body onload="RunTest()">
+
+ <div class="testdata">
+ <p id="instructions"> Test passes if the word "PASS" appears below </p>
+ <p> Test Result : </p>
+ <p id="testresult"> RUNNING </div>
+ </div>
+ <svg id="svg1" width="100px" height="100px">
+ <rect id="rect1" />
+ <circle id="circle1" />
+ </svg>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/foreign_content_011.html b/tests/wpt/web-platform-tests/html/syntax/parsing/foreign_content_011.html
new file mode 100644
index 00000000000..a8a9d7a1b61
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/foreign_content_011.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>HTML 5 Foreign Content SVG in HTML </title>
+ <meta description="Test to verify SVG elements are styled using ID Selector" />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+
+ <style>
+ #d1
+ {
+ fill: green;
+ }
+ </style>
+ </head>
+
+ <body>
+ <div class="testdata">
+ <p id="instructions">Test passes if a green square is visible below this line.</p>
+ </div>
+ <div id="d1">
+ <svg width="100px" height="100px">
+ <rect width="100px" height="100px" />
+ </svg>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/foreign_content_013.html b/tests/wpt/web-platform-tests/html/syntax/parsing/foreign_content_013.html
new file mode 100644
index 00000000000..e88aae9e4db
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/foreign_content_013.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>HTML 5 Foreign Content SVG in HTML </title>
+ <meta description="Test to verify SVG elements are styled using CLASS Selector" />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+
+ <style>
+ .svg1
+ {
+ fill: green ;
+ }
+ </style>
+ </head>
+
+ <body>
+ <div class="testdata">
+ <p id="instructions">Test passes if a green square is visible below this line. </p>
+ </div>
+ <div id="d1">
+ <svg class="svg1" width="100px" height="100px">
+ <rect width="100px" height="100px"/>
+ </svg>
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_adoption01.html b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_adoption01.html
new file mode 100644
index 00000000000..87664da7785
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_adoption01.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf8">
+ <title>HTML 5 Parser tests html5lib_adoption01.html</title>
+ <meta name="timeout" content="long">
+ <meta name="variant" content="?run_type=uri">
+ <meta name="variant" content="?run_type=write">
+ <meta name="variant" content="?run_type=write_single">
+ </head>
+ <body>
+ <h1>html5lib Parser Test</h1>
+ <div id="log"></div>
+ <script src="common.js"></script>
+ <script src="test.js"></script>
+ <script src="template.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ var num_iframes = 8;
+ var order = ['dab5eca760a630bc57719d678d789dd1ca74f492','a3a46907dc73b7be1e1171f797a9f696b7fb185b','b720cd1d95283d6288e7ca17142540b10ef8f847','83b2bd6f0849b2c7283448f15095806a17c7f0c0','1d56fa2d9d756f9053638a3db25fcd84e57e41ec','c129fce97933067558d7833632ad7ef2d149616e','39a3ec04f54cda2bf1e06c54caf0b302da4fd252','d0bdfe6be48309b2d01b497667b350a8e6ec8ffb','63401082c6afd4b3c3201e348a1a61722f167b21','883cfd89f63da854dffbfbc938da1f31887a55e5','4dc0665051dac0d72c71aba5c95c5b86437dea2c','4f376c0a798e71a91065e215dc0175d3107d5208','52b62611a847a3f5fc3dc607a6b0174f1697247c','88d0d3403d2a7b4058fcfb4e62835acb1c207e0f','d7338f457789f65d47b240e203b9e40a3925f2ca','bf8088acd8bd48d8487bae49a613c248c488c041','39edaa2e298c60ad4a1b0b9fdb4481d4aea98f36',];
+ var tests = {
+ "dab5eca760a630bc57719d678d789dd1ca74f492":[async_test('html5lib_adoption01.html dab5eca760a630bc57719d678d789dd1ca74f492'), "%3Ca%3E%3Cp%3E%3C/a%3E%3C/p%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Ca%3E"],"a3a46907dc73b7be1e1171f797a9f696b7fb185b":[async_test('html5lib_adoption01.html a3a46907dc73b7be1e1171f797a9f696b7fb185b'), "%3Ca%3E1%3Cp%3E2%3C/a%3E3%3C/p%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%221%22%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%222%22%0A%7C%20%20%20%20%20%20%20%223%22"],"b720cd1d95283d6288e7ca17142540b10ef8f847":[async_test('html5lib_adoption01.html b720cd1d95283d6288e7ca17142540b10ef8f847'), "%3Ca%3E1%3Cbutton%3E2%3C/a%3E3%3C/button%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%221%22%0A%7C%20%20%20%20%20%3Cbutton%3E%0A%7C%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%222%22%0A%7C%20%20%20%20%20%20%20%223%22"],"83b2bd6f0849b2c7283448f15095806a17c7f0c0":[async_test('html5lib_adoption01.html 83b2bd6f0849b2c7283448f15095806a17c7f0c0'), "%3Ca%3E1%3Cb%3E2%3C/a%3E3%3C/b%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%221%22%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%222%22%0A%7C%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%223%22"],"1d56fa2d9d756f9053638a3db25fcd84e57e41ec":[async_test('html5lib_adoption01.html 1d56fa2d9d756f9053638a3db25fcd84e57e41ec'), "%3Ca%3E1%3Cdiv%3E2%3Cdiv%3E3%3C/a%3E4%3C/div%3E5%3C/div%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%221%22%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%222%22%0A%7C%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%223%22%0A%7C%20%20%20%20%20%20%20%20%20%224%22%0A%7C%20%20%20%20%20%20%20%225%22"],"c129fce97933067558d7833632ad7ef2d149616e":[async_test('html5lib_adoption01.html c129fce97933067558d7833632ad7ef2d149616e'), "%3Ctable%3E%3Ca%3E1%3Cp%3E2%3C/a%3E3%3C/p%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%221%22%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%222%22%0A%7C%20%20%20%20%20%20%20%223%22%0A%7C%20%20%20%20%20%3Ctable%3E"],"39a3ec04f54cda2bf1e06c54caf0b302da4fd252":[async_test('html5lib_adoption01.html 39a3ec04f54cda2bf1e06c54caf0b302da4fd252'), "%3Cb%3E%3Cb%3E%3Ca%3E%3Cp%3E%3C/a%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ca%3E"],"d0bdfe6be48309b2d01b497667b350a8e6ec8ffb":[async_test('html5lib_adoption01.html d0bdfe6be48309b2d01b497667b350a8e6ec8ffb'), "%3Cb%3E%3Ca%3E%3Cb%3E%3Cp%3E%3C/a%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ca%3E"],"63401082c6afd4b3c3201e348a1a61722f167b21":[async_test('html5lib_adoption01.html 63401082c6afd4b3c3201e348a1a61722f167b21'), "%3Ca%3E%3Cb%3E%3Cb%3E%3Cp%3E%3C/a%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ca%3E"],"883cfd89f63da854dffbfbc938da1f31887a55e5":[async_test('html5lib_adoption01.html 883cfd89f63da854dffbfbc938da1f31887a55e5'), "%3Cp%3E1%3Cs%20id%3D%22A%22%3E2%3Cb%20id%3D%22B%22%3E3%3C/p%3E4%3C/s%3E5%3C/b%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%221%22%0A%7C%20%20%20%20%20%20%20%3Cs%3E%0A%7C%20%20%20%20%20%20%20%20%20id%3D%22A%22%0A%7C%20%20%20%20%20%20%20%20%20%222%22%0A%7C%20%20%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20id%3D%22B%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%223%22%0A%7C%20%20%20%20%20%3Cs%3E%0A%7C%20%20%20%20%20%20%20id%3D%22A%22%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20id%3D%22B%22%0A%7C%20%20%20%20%20%20%20%20%20%224%22%0A%7C%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20id%3D%22B%22%0A%7C%20%20%20%20%20%20%20%225%22"],"4dc0665051dac0d72c71aba5c95c5b86437dea2c":[async_test('html5lib_adoption01.html 4dc0665051dac0d72c71aba5c95c5b86437dea2c'), "%3Ctable%3E%3Ca%3E1%3Ctd%3E2%3C/td%3E3%3C/table%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%221%22%0A%7C%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%223%22%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%222%22"],"4f376c0a798e71a91065e215dc0175d3107d5208":[async_test('html5lib_adoption01.html 4f376c0a798e71a91065e215dc0175d3107d5208'), "%3Ctable%3EA%3Ctd%3EB%3C/td%3EC%3C/table%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22AC%22%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%22B%22"],"52b62611a847a3f5fc3dc607a6b0174f1697247c":[async_test('html5lib_adoption01.html 52b62611a847a3f5fc3dc607a6b0174f1697247c'), "%3Ca%3E%3Csvg%3E%3Ctr%3E%3Cinput%3E%3C/a%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Csvg%20tr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Csvg%20input%3E"],"88d0d3403d2a7b4058fcfb4e62835acb1c207e0f":[async_test('html5lib_adoption01.html 88d0d3403d2a7b4058fcfb4e62835acb1c207e0f'), "%3Cdiv%3E%3Ca%3E%3Cb%3E%3Cdiv%3E%3Cdiv%3E%3Cdiv%3E%3Cdiv%3E%3Cdiv%3E%3Cdiv%3E%3Cdiv%3E%3Cdiv%3E%3Cdiv%3E%3Cdiv%3E%3C/a%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%3E"],"d7338f457789f65d47b240e203b9e40a3925f2ca":[async_test('html5lib_adoption01.html d7338f457789f65d47b240e203b9e40a3925f2ca'), "%3Cdiv%3E%3Ca%3E%3Cb%3E%3Cu%3E%3Ci%3E%3Ccode%3E%3Cdiv%3E%3C/a%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cu%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ccode%3E%0A%7C%20%20%20%20%20%20%20%3Cu%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ccode%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ca%3E"],"bf8088acd8bd48d8487bae49a613c248c488c041":[async_test('html5lib_adoption01.html bf8088acd8bd48d8487bae49a613c248c488c041'), "%3Cb%3E%3Cb%3E%3Cb%3E%3Cb%3Ex%3C/b%3E%3C/b%3E%3C/b%3E%3C/b%3Ey", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%22x%22%0A%7C%20%20%20%20%20%22y%22"],"39edaa2e298c60ad4a1b0b9fdb4481d4aea98f36":[async_test('html5lib_adoption01.html 39edaa2e298c60ad4a1b0b9fdb4481d4aea98f36'), "%3Cp%3E%3Cb%3E%3Cb%3E%3Cb%3E%3Cb%3E%3Cp%3Ex", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%22x%22"],
+ }
+ init_tests(get_type());
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_adoption02.html b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_adoption02.html
new file mode 100644
index 00000000000..81bb8d35f20
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_adoption02.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf8">
+ <title>HTML 5 Parser tests html5lib_adoption02.html</title>
+ <meta name="timeout" content="long">
+ <meta name="variant" content="?run_type=uri">
+ <meta name="variant" content="?run_type=write">
+ <meta name="variant" content="?run_type=write_single">
+ </head>
+ <body>
+ <h1>html5lib Parser Test</h1>
+ <div id="log"></div>
+ <script src="common.js"></script>
+ <script src="test.js"></script>
+ <script src="template.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ var num_iframes = 8;
+ var order = ['cefc9890d621707fedf5eb634f3a86d753659d9b','2a8f569e9d55b3cb7e54b026f758dea8593f4cb4',];
+ var tests = {
+ "cefc9890d621707fedf5eb634f3a86d753659d9b":[async_test('html5lib_adoption02.html cefc9890d621707fedf5eb634f3a86d753659d9b'), "%3Cb%3E1%3Ci%3E2%3Cp%3E3%3C/b%3E4", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%221%22%0A%7C%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%222%22%0A%7C%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%223%22%0A%7C%20%20%20%20%20%20%20%20%20%224%22"],"2a8f569e9d55b3cb7e54b026f758dea8593f4cb4":[async_test('html5lib_adoption02.html 2a8f569e9d55b3cb7e54b026f758dea8593f4cb4'), "%3Ca%3E%3Cdiv%3E%3Cstyle%3E%3C/style%3E%3Caddress%3E%3Ca%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cstyle%3E%0A%7C%20%20%20%20%20%20%20%3Caddress%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ca%3E"],
+ }
+ init_tests(get_type());
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_comments01.html b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_comments01.html
new file mode 100644
index 00000000000..3464bc5e44f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_comments01.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf8">
+ <title>HTML 5 Parser tests html5lib_comments01.html</title>
+ <meta name="timeout" content="long">
+ <meta name="variant" content="?run_type=uri">
+ <meta name="variant" content="?run_type=write">
+ <meta name="variant" content="?run_type=write_single">
+ </head>
+ <body>
+ <h1>html5lib Parser Test</h1>
+ <div id="log"></div>
+ <script src="common.js"></script>
+ <script src="test.js"></script>
+ <script src="template.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ var num_iframes = 8;
+ var order = ['3dbda8330033c3fbf3185a55e963075328099578','7476098e9823b3deee1857739daf719ff18e37b4','a6c42885c32fa988374894c0871b5a289786912a','d59b196ec9f6f19ded28d5e1fb48cbec2b1a4187','97486c43262a9a5c3fec1a3b028b99b7ca8c0e3e','06145ae05b1d92b71aed067ed6f1aab1afea50ae','5064d84d3adaf6262cf3573e9e112f40e3abc147','8b36d140a4a223b083a8d41af7c98a1c20377856','1894e23c5ee89d6f4b5f1dbe9b681b42863b4d1f','2cefeae994b6b0be0accbfff4757fef40ed914eb','ac9fd94008255e73cba953dbd374cb41703f5446','617815b6a683613fcb6b9cd5841b2ea7428d838d','bb8faf75d2e28aee13ec4a0d8eab00b4d7475763','89c4ae1ae34df9dff0e516afdef87cd169c3e6a5',];
+ var tests = {
+ "3dbda8330033c3fbf3185a55e963075328099578":[async_test('html5lib_comments01.html 3dbda8330033c3fbf3185a55e963075328099578'), "FOO%3C%21--%20BAR%20--%3EBAZ", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%22%0A%7C%20%20%20%20%20%3C%21--%20%20BAR%20%20--%3E%0A%7C%20%20%20%20%20%22BAZ%22"],"7476098e9823b3deee1857739daf719ff18e37b4":[async_test('html5lib_comments01.html 7476098e9823b3deee1857739daf719ff18e37b4'), "FOO%3C%21--%20BAR%20--%21%3EBAZ", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%22%0A%7C%20%20%20%20%20%3C%21--%20%20BAR%20%20--%3E%0A%7C%20%20%20%20%20%22BAZ%22"],"a6c42885c32fa988374894c0871b5a289786912a":[async_test('html5lib_comments01.html a6c42885c32fa988374894c0871b5a289786912a'), "FOO%3C%21--%20BAR%20--%20%20%20%3EBAZ", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%22%0A%7C%20%20%20%20%20%3C%21--%20%20BAR%20--%20%20%20%3EBAZ%20--%3E"],"d59b196ec9f6f19ded28d5e1fb48cbec2b1a4187":[async_test('html5lib_comments01.html d59b196ec9f6f19ded28d5e1fb48cbec2b1a4187'), "FOO%3C%21--%20BAR%20--%20%3CQUX%3E%20--%20MUX%20--%3EBAZ", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%22%0A%7C%20%20%20%20%20%3C%21--%20%20BAR%20--%20%3CQUX%3E%20--%20MUX%20%20--%3E%0A%7C%20%20%20%20%20%22BAZ%22"],"97486c43262a9a5c3fec1a3b028b99b7ca8c0e3e":[async_test('html5lib_comments01.html 97486c43262a9a5c3fec1a3b028b99b7ca8c0e3e'), "FOO%3C%21--%20BAR%20--%20%3CQUX%3E%20--%20MUX%20--%21%3EBAZ", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%22%0A%7C%20%20%20%20%20%3C%21--%20%20BAR%20--%20%3CQUX%3E%20--%20MUX%20%20--%3E%0A%7C%20%20%20%20%20%22BAZ%22"],"06145ae05b1d92b71aed067ed6f1aab1afea50ae":[async_test('html5lib_comments01.html 06145ae05b1d92b71aed067ed6f1aab1afea50ae'), "FOO%3C%21--%20BAR%20--%20%3CQUX%3E%20--%20MUX%20--%20%3EBAZ", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%22%0A%7C%20%20%20%20%20%3C%21--%20%20BAR%20--%20%3CQUX%3E%20--%20MUX%20--%20%3EBAZ%20--%3E"],"5064d84d3adaf6262cf3573e9e112f40e3abc147":[async_test('html5lib_comments01.html 5064d84d3adaf6262cf3573e9e112f40e3abc147'), "FOO%3C%21----%3EBAZ", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%22%0A%7C%20%20%20%20%20%3C%21--%20%20--%3E%0A%7C%20%20%20%20%20%22BAZ%22"],"8b36d140a4a223b083a8d41af7c98a1c20377856":[async_test('html5lib_comments01.html 8b36d140a4a223b083a8d41af7c98a1c20377856'), "FOO%3C%21---%3EBAZ", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%22%0A%7C%20%20%20%20%20%3C%21--%20%20--%3E%0A%7C%20%20%20%20%20%22BAZ%22"],"1894e23c5ee89d6f4b5f1dbe9b681b42863b4d1f":[async_test('html5lib_comments01.html 1894e23c5ee89d6f4b5f1dbe9b681b42863b4d1f'), "FOO%3C%21--%3EBAZ", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%22%0A%7C%20%20%20%20%20%3C%21--%20%20--%3E%0A%7C%20%20%20%20%20%22BAZ%22"],"2cefeae994b6b0be0accbfff4757fef40ed914eb":[async_test('html5lib_comments01.html 2cefeae994b6b0be0accbfff4757fef40ed914eb'), "%3C%3Fxml%20version%3D%221.0%22%3EHi", "%23document%0A%7C%20%3C%21--%20%3Fxml%20version%3D%221.0%22%20--%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22Hi%22"],"ac9fd94008255e73cba953dbd374cb41703f5446":[async_test('html5lib_comments01.html ac9fd94008255e73cba953dbd374cb41703f5446'), "%3C%3Fxml%20version%3D%221.0%22%3E", "%23document%0A%7C%20%3C%21--%20%3Fxml%20version%3D%221.0%22%20--%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"617815b6a683613fcb6b9cd5841b2ea7428d838d":[async_test('html5lib_comments01.html 617815b6a683613fcb6b9cd5841b2ea7428d838d'), "%3C%3Fxml%20version", "%23document%0A%7C%20%3C%21--%20%3Fxml%20version%20--%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"bb8faf75d2e28aee13ec4a0d8eab00b4d7475763":[async_test('html5lib_comments01.html bb8faf75d2e28aee13ec4a0d8eab00b4d7475763'), "FOO%3C%21-----%3EBAZ", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%22%0A%7C%20%20%20%20%20%3C%21--%20-%20--%3E%0A%7C%20%20%20%20%20%22BAZ%22"],"89c4ae1ae34df9dff0e516afdef87cd169c3e6a5":[async_test('html5lib_comments01.html 89c4ae1ae34df9dff0e516afdef87cd169c3e6a5'), "%3Chtml%3E%3C%21--%20comment%20--%3E%3Ctitle%3EComment%20before%20head%3C/title%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3C%21--%20%20comment%20%20--%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Ctitle%3E%0A%7C%20%20%20%20%20%20%20%22Comment%20before%20head%22%0A%7C%20%20%20%3Cbody%3E"],
+ }
+ init_tests(get_type());
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_doctype01.html b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_doctype01.html
new file mode 100644
index 00000000000..fcf616e1a5e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_doctype01.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf8">
+ <title>HTML 5 Parser tests html5lib_doctype01.html</title>
+ <meta name="timeout" content="long">
+ <meta name="variant" content="?run_type=uri">
+ <meta name="variant" content="?run_type=write">
+ <meta name="variant" content="?run_type=write_single">
+ </head>
+ <body>
+ <h1>html5lib Parser Test</h1>
+ <div id="log"></div>
+ <script src="common.js"></script>
+ <script src="test.js"></script>
+ <script src="template.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ var num_iframes = 8;
+ var order = ['8c660236fa29672c9b1ed0b64be59835a2a2f8cf','6a757c8c420fe3273632e84a4d999f17164f1214','a8ba29d82bb59f5ca03cfc193a1af770b889d4df','7a5044da1f470565fc4c6697b05132ff803d33e5','6514baf0155d3d10c1449752666c9da1c3db7141','ab7af413296ccb0e5705d978b98751821eb60ee3','3f3585cd61875a7f824422eda85a568952c1b08d','32bf847dcfae86480610633948efb2eca296abdd','692ab73d917820f55f789498c003ff184694becd','69af8e298e3560620c7598a9d2a6be0c50fe6881','93737d931105f8441c51a61ce6c9c625708aa690','be48ad2b635136c6ae4d99ff06bc930711e26ab7','6b90a61449551f1d7ac3aaa54669e81b1adbeb48','dc641c8a55963188374a5ab0f9be4c00897a113d','a157f7a60a42840003e9a798ca4c3981c17eb08b','826518fc2114e88a3dd7caecef77fa9ed0967f9e','0d86430bce85790c6eb1ead82133ee74077c6ac9','79ef363724b7881ee356c0a105e6add81941d57e','d8d1295947c1944ba51f7be60165e2d5d7592225','8214eb8bef5c817fd5fee4befdc15dbcc49ff6e0','51dd468ef51c8c0ea3e4b5a81517831c6a9168cb','dab4dcff81a1d051394a34771eb9627d07700377','6c679921462b1833e5203e6cd48f761b479d8924','a45fad90fa4d150fdb82f61bf49e0f92a0aaaf94','18cc825780e6be5a1ab60475c07be505759b25ad','37960ee5e9a9252988a63d9653336d30c1645834','095187e72e2336527d8c39293d68d456dfb1a10e','46383e4754c42b37ebba10ad4e3644dcff1eec18','702c2be9dc6bf31da96af43947e0e16d040bd395','7ffeed0800cff7c5117ba7de33f5e70d037129c3','2d57d9c9c46d222676eeb8e8531f3a77ca7aa4c0','544240cd747ec56acbc607b6b8ad9f99de4c4085','af212d55a1c59b5e3658fb39a2f86daab3686f94','10d43f89829998731c313c85eb31e981961b1981','99d16cdde20971b45a3b81ca7a2b9d9858525b22','44ac65856abd110419aafffde69f0dc127f98ec3','a69ffa9525892dbb38be6ee78f4fe1216ef6ea5d',];
+ var tests = {
+ "8c660236fa29672c9b1ed0b64be59835a2a2f8cf":[async_test('html5lib_doctype01.html 8c660236fa29672c9b1ed0b64be59835a2a2f8cf'), "%3C%21DOCTYPE%20html%3EHello", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22Hello%22"],"6a757c8c420fe3273632e84a4d999f17164f1214":[async_test('html5lib_doctype01.html 6a757c8c420fe3273632e84a4d999f17164f1214'), "%3C%21dOctYpE%20HtMl%3EHello", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22Hello%22"],"a8ba29d82bb59f5ca03cfc193a1af770b889d4df":[async_test('html5lib_doctype01.html a8ba29d82bb59f5ca03cfc193a1af770b889d4df'), "%3C%21DOCTYPEhtml%3EHello", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22Hello%22"],"7a5044da1f470565fc4c6697b05132ff803d33e5":[async_test('html5lib_doctype01.html 7a5044da1f470565fc4c6697b05132ff803d33e5'), "%3C%21DOCTYPE%3EHello", "%23document%0A%7C%20%3C%21DOCTYPE%20%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22Hello%22"],"6514baf0155d3d10c1449752666c9da1c3db7141":[async_test('html5lib_doctype01.html 6514baf0155d3d10c1449752666c9da1c3db7141'), "%3C%21DOCTYPE%20%3EHello", "%23document%0A%7C%20%3C%21DOCTYPE%20%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22Hello%22"],"ab7af413296ccb0e5705d978b98751821eb60ee3":[async_test('html5lib_doctype01.html ab7af413296ccb0e5705d978b98751821eb60ee3'), "%3C%21DOCTYPE%20potato%3EHello", "%23document%0A%7C%20%3C%21DOCTYPE%20potato%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22Hello%22"],"3f3585cd61875a7f824422eda85a568952c1b08d":[async_test('html5lib_doctype01.html 3f3585cd61875a7f824422eda85a568952c1b08d'), "%3C%21DOCTYPE%20potato%20%3EHello", "%23document%0A%7C%20%3C%21DOCTYPE%20potato%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22Hello%22"],"32bf847dcfae86480610633948efb2eca296abdd":[async_test('html5lib_doctype01.html 32bf847dcfae86480610633948efb2eca296abdd'), "%3C%21DOCTYPE%20potato%20taco%3EHello", "%23document%0A%7C%20%3C%21DOCTYPE%20potato%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22Hello%22"],"692ab73d917820f55f789498c003ff184694becd":[async_test('html5lib_doctype01.html 692ab73d917820f55f789498c003ff184694becd'), "%3C%21DOCTYPE%20potato%20taco%20%22ddd%3EHello", "%23document%0A%7C%20%3C%21DOCTYPE%20potato%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22Hello%22"],"69af8e298e3560620c7598a9d2a6be0c50fe6881":[async_test('html5lib_doctype01.html 69af8e298e3560620c7598a9d2a6be0c50fe6881'), "%3C%21DOCTYPE%20potato%20sYstEM%3EHello", "%23document%0A%7C%20%3C%21DOCTYPE%20potato%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22Hello%22"],"93737d931105f8441c51a61ce6c9c625708aa690":[async_test('html5lib_doctype01.html 93737d931105f8441c51a61ce6c9c625708aa690'), "%3C%21DOCTYPE%20potato%20sYstEM%20%20%20%20%3EHello", "%23document%0A%7C%20%3C%21DOCTYPE%20potato%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22Hello%22"],"be48ad2b635136c6ae4d99ff06bc930711e26ab7":[async_test('html5lib_doctype01.html be48ad2b635136c6ae4d99ff06bc930711e26ab7'), "%3C%21DOCTYPE%20%20%20potato%20%20%20%20%20%20%20sYstEM%20%20ggg%3EHello", "%23document%0A%7C%20%3C%21DOCTYPE%20potato%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22Hello%22"],"6b90a61449551f1d7ac3aaa54669e81b1adbeb48":[async_test('html5lib_doctype01.html 6b90a61449551f1d7ac3aaa54669e81b1adbeb48'), "%3C%21DOCTYPE%20potato%20SYSTEM%20taco%20%20%3EHello", "%23document%0A%7C%20%3C%21DOCTYPE%20potato%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22Hello%22"],"dc641c8a55963188374a5ab0f9be4c00897a113d":[async_test('html5lib_doctype01.html dc641c8a55963188374a5ab0f9be4c00897a113d'), "%3C%21DOCTYPE%20potato%20SYSTEM%20%27taco%22%27%3EHello", "%23document%0A%7C%20%3C%21DOCTYPE%20potato%20%22%22%20%22taco%22%22%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22Hello%22"],"a157f7a60a42840003e9a798ca4c3981c17eb08b":[async_test('html5lib_doctype01.html a157f7a60a42840003e9a798ca4c3981c17eb08b'), "%3C%21DOCTYPE%20potato%20SYSTEM%20%22taco%22%3EHello", "%23document%0A%7C%20%3C%21DOCTYPE%20potato%20%22%22%20%22taco%22%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22Hello%22"],"826518fc2114e88a3dd7caecef77fa9ed0967f9e":[async_test('html5lib_doctype01.html 826518fc2114e88a3dd7caecef77fa9ed0967f9e'), "%3C%21DOCTYPE%20potato%20SYSTEM%20%22tai%27co%22%3EHello", "%23document%0A%7C%20%3C%21DOCTYPE%20potato%20%22%22%20%22tai%27co%22%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22Hello%22"],"0d86430bce85790c6eb1ead82133ee74077c6ac9":[async_test('html5lib_doctype01.html 0d86430bce85790c6eb1ead82133ee74077c6ac9'), "%3C%21DOCTYPE%20potato%20SYSTEMtaco%20%22ddd%22%3EHello", "%23document%0A%7C%20%3C%21DOCTYPE%20potato%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22Hello%22"],"79ef363724b7881ee356c0a105e6add81941d57e":[async_test('html5lib_doctype01.html 79ef363724b7881ee356c0a105e6add81941d57e'), "%3C%21DOCTYPE%20potato%20grass%20SYSTEM%20taco%3EHello", "%23document%0A%7C%20%3C%21DOCTYPE%20potato%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22Hello%22"],"d8d1295947c1944ba51f7be60165e2d5d7592225":[async_test('html5lib_doctype01.html d8d1295947c1944ba51f7be60165e2d5d7592225'), "%3C%21DOCTYPE%20potato%20pUbLIc%3EHello", "%23document%0A%7C%20%3C%21DOCTYPE%20potato%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22Hello%22"],"8214eb8bef5c817fd5fee4befdc15dbcc49ff6e0":[async_test('html5lib_doctype01.html 8214eb8bef5c817fd5fee4befdc15dbcc49ff6e0'), "%3C%21DOCTYPE%20potato%20pUbLIc%20%3EHello", "%23document%0A%7C%20%3C%21DOCTYPE%20potato%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22Hello%22"],"51dd468ef51c8c0ea3e4b5a81517831c6a9168cb":[async_test('html5lib_doctype01.html 51dd468ef51c8c0ea3e4b5a81517831c6a9168cb'), "%3C%21DOCTYPE%20potato%20pUbLIcgoof%3EHello", "%23document%0A%7C%20%3C%21DOCTYPE%20potato%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22Hello%22"],"dab4dcff81a1d051394a34771eb9627d07700377":[async_test('html5lib_doctype01.html dab4dcff81a1d051394a34771eb9627d07700377'), "%3C%21DOCTYPE%20potato%20PUBLIC%20goof%3EHello", "%23document%0A%7C%20%3C%21DOCTYPE%20potato%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22Hello%22"],"6c679921462b1833e5203e6cd48f761b479d8924":[async_test('html5lib_doctype01.html 6c679921462b1833e5203e6cd48f761b479d8924'), "%3C%21DOCTYPE%20potato%20PUBLIC%20%22go%27of%22%3EHello", "%23document%0A%7C%20%3C%21DOCTYPE%20potato%20%22go%27of%22%20%22%22%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22Hello%22"],"a45fad90fa4d150fdb82f61bf49e0f92a0aaaf94":[async_test('html5lib_doctype01.html a45fad90fa4d150fdb82f61bf49e0f92a0aaaf94'), "%3C%21DOCTYPE%20potato%20PUBLIC%20%27go%27of%27%3EHello", "%23document%0A%7C%20%3C%21DOCTYPE%20potato%20%22go%22%20%22%22%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22Hello%22"],"18cc825780e6be5a1ab60475c07be505759b25ad":[async_test('html5lib_doctype01.html 18cc825780e6be5a1ab60475c07be505759b25ad'), "%3C%21DOCTYPE%20potato%20PUBLIC%20%27go%3Ahh%20%20%20of%27%20%3EHello", "%23document%0A%7C%20%3C%21DOCTYPE%20potato%20%22go%3Ahh%20%20%20of%22%20%22%22%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22Hello%22"],"37960ee5e9a9252988a63d9653336d30c1645834":[async_test('html5lib_doctype01.html 37960ee5e9a9252988a63d9653336d30c1645834'), "%3C%21DOCTYPE%20potato%20PUBLIC%20%22W3C-//dfdf%22%20SYSTEM%20ggg%3EHello", "%23document%0A%7C%20%3C%21DOCTYPE%20potato%20%22W3C-//dfdf%22%20%22%22%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22Hello%22"],"095187e72e2336527d8c39293d68d456dfb1a10e":[async_test('html5lib_doctype01.html 095187e72e2336527d8c39293d68d456dfb1a10e'), "%3C%21DOCTYPE%20HTML%20PUBLIC%20%22-//W3C//DTD%20HTML%204.01//EN%22%0A%20%20%20%22http%3A//www.w3.org/TR/html4/strict.dtd%22%3EHello", "%23document%0A%7C%20%3C%21DOCTYPE%20html%20%22-//W3C//DTD%20HTML%204.01//EN%22%20%22http%3A//www.w3.org/TR/html4/strict.dtd%22%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22Hello%22"],"46383e4754c42b37ebba10ad4e3644dcff1eec18":[async_test('html5lib_doctype01.html 46383e4754c42b37ebba10ad4e3644dcff1eec18'), "%3C%21DOCTYPE%20...%3EHello", "%23document%0A%7C%20%3C%21DOCTYPE%20...%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22Hello%22"],"702c2be9dc6bf31da96af43947e0e16d040bd395":[async_test('html5lib_doctype01.html 702c2be9dc6bf31da96af43947e0e16d040bd395'), "%3C%21DOCTYPE%20html%20PUBLIC%20%22-//W3C//DTD%20XHTML%201.0%20Transitional//EN%22%0A%22http%3A//www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd%22%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%20%22-//W3C//DTD%20XHTML%201.0%20Transitional//EN%22%20%22http%3A//www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd%22%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"7ffeed0800cff7c5117ba7de33f5e70d037129c3":[async_test('html5lib_doctype01.html 7ffeed0800cff7c5117ba7de33f5e70d037129c3'), "%3C%21DOCTYPE%20html%20PUBLIC%20%22-//W3C//DTD%20XHTML%201.0%20Frameset//EN%22%0A%22http%3A//www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd%22%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%20%22-//W3C//DTD%20XHTML%201.0%20Frameset//EN%22%20%22http%3A//www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd%22%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"2d57d9c9c46d222676eeb8e8531f3a77ca7aa4c0":[async_test('html5lib_doctype01.html 2d57d9c9c46d222676eeb8e8531f3a77ca7aa4c0'), "%3C%21DOCTYPE%20root-element%20%5BSYSTEM%20OR%20PUBLIC%20FPI%5D%20%22uri%22%20%5B%20%0A%3C%21--%20internal%20declarations%20--%3E%0A%5D%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20root-element%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22%5D%3E%22"],"544240cd747ec56acbc607b6b8ad9f99de4c4085":[async_test('html5lib_doctype01.html 544240cd747ec56acbc607b6b8ad9f99de4c4085'), "%3C%21DOCTYPE%20html%20PUBLIC%0A%20%20%22-//WAPFORUM//DTD%20XHTML%20Mobile%201.0//EN%22%0A%20%20%20%20%22http%3A//www.wapforum.org/DTD/xhtml-mobile10.dtd%22%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%20%22-//WAPFORUM//DTD%20XHTML%20Mobile%201.0//EN%22%20%22http%3A//www.wapforum.org/DTD/xhtml-mobile10.dtd%22%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"af212d55a1c59b5e3658fb39a2f86daab3686f94":[async_test('html5lib_doctype01.html af212d55a1c59b5e3658fb39a2f86daab3686f94'), "%3C%21DOCTYPE%20HTML%20SYSTEM%20%22http%3A//www.w3.org/DTD/HTML4-strict.dtd%22%3E%3Cbody%3E%3Cb%3EMine%21%3C/b%3E%3C/body%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%20%22%22%20%22http%3A//www.w3.org/DTD/HTML4-strict.dtd%22%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%22Mine%21%22"],"10d43f89829998731c313c85eb31e981961b1981":[async_test('html5lib_doctype01.html 10d43f89829998731c313c85eb31e981961b1981'), "%3C%21DOCTYPE%20HTML%20PUBLIC%20%22-//W3C//DTD%20HTML%204.01//EN%22%22http%3A//www.w3.org/TR/html4/strict.dtd%22%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%20%22-//W3C//DTD%20HTML%204.01//EN%22%20%22http%3A//www.w3.org/TR/html4/strict.dtd%22%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"99d16cdde20971b45a3b81ca7a2b9d9858525b22":[async_test('html5lib_doctype01.html 99d16cdde20971b45a3b81ca7a2b9d9858525b22'), "%3C%21DOCTYPE%20HTML%20PUBLIC%20%22-//W3C//DTD%20HTML%204.01//EN%22%27http%3A//www.w3.org/TR/html4/strict.dtd%27%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%20%22-//W3C//DTD%20HTML%204.01//EN%22%20%22http%3A//www.w3.org/TR/html4/strict.dtd%22%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"44ac65856abd110419aafffde69f0dc127f98ec3":[async_test('html5lib_doctype01.html 44ac65856abd110419aafffde69f0dc127f98ec3'), "%3C%21DOCTYPE%20HTML%20PUBLIC%22-//W3C//DTD%20HTML%204.01//EN%22%27http%3A//www.w3.org/TR/html4/strict.dtd%27%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%20%22-//W3C//DTD%20HTML%204.01//EN%22%20%22http%3A//www.w3.org/TR/html4/strict.dtd%22%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"a69ffa9525892dbb38be6ee78f4fe1216ef6ea5d":[async_test('html5lib_doctype01.html a69ffa9525892dbb38be6ee78f4fe1216ef6ea5d'), "%3C%21DOCTYPE%20HTML%20PUBLIC%27-//W3C//DTD%20HTML%204.01//EN%27%27http%3A//www.w3.org/TR/html4/strict.dtd%27%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%20%22-//W3C//DTD%20HTML%204.01//EN%22%20%22http%3A//www.w3.org/TR/html4/strict.dtd%22%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],
+ }
+ init_tests(get_type());
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_domjs-unsafe.html b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_domjs-unsafe.html
new file mode 100644
index 00000000000..6a8c9d5064c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_domjs-unsafe.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf8">
+ <title>HTML 5 Parser tests html5lib_domjs-unsafe.html</title>
+ <meta name="timeout" content="long">
+ <meta name="variant" content="?run_type=uri">
+ <meta name="variant" content="?run_type=write">
+ <meta name="variant" content="?run_type=write_single">
+ </head>
+ <body>
+ <h1>html5lib Parser Test</h1>
+ <div id="log"></div>
+ <script src="common.js"></script>
+ <script src="test.js"></script>
+ <script src="template.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ var num_iframes = 8;
+ var order = ['b76df4b192c11a5ef7a3e895a7dd2aaea2dcc5c7','da5cf60e732fcf20d288e772e51a7a9ccd3471e4','c32f77685b52841e1685110a8a6fac17b3ae127a','4fd39e063b0ad1fa82274d6de3122859f76934a8','7208fbe8702c37cf180b1c736c984f5340517408','7b5dd0bcb2a92ebf1974a0ec6017a798e774ca5b','54c3b7008093eea8c5b45f729585097df53641a8','b8de3bd0272a8362093670968eb21ad0bfa3cd40','40033d4270de7ad3595607426efc221988100175','4ffebb41a5c7f9239ba71301793a1e1cfd65dece','4fa68424ed093da8a6c954d64bb154ef4269ea83','41ddb90fa2e7785945dd18c32736dc83c1440fa4','89466f9770c893ffb117d18eac80993bd69564ad','72186fc6836326792e7e46ce4b5432191a5ac192','9863747db1e2676bad75c9929d895db2bb02306c','01818845dd1283fc54707a140be17e689a91f013','3255082e063beec09c3b0e605f0e3bfae177a113','54cd599d050ee568b0ed0060d1926479d3e528c3','bf081558b113ea712baeeb3294f3b53845510996','25e3471f40f3b6b0b448f7f7be41f0ee06403faa','006df46be5600e3d99caaf7dfc6a8af1636fd43a','b9bea556d1a155ef04e3f583328d51cf95995945','9eff404da18d0c20765a19613c718a9f49b874ac','1d246a13e96719a3fb48f1a81d1218671ee3a472','92bb86082f237803c7ace5fcd41a36861b364551','3a89dee49af0d2b537ad0c50fb74bb68d4dfe651','89bd023b6e2cbc5c7a37d85b45eadc88143bd670','9574dbbf3302c84fc4ddb965bf1f43ae7106e68c','341226c7328f8d3d6ab1d373368cc14aad712f20','15b3a23030aed47b3795d9c1ef11cd241b6902cb','4b318ddd18e0e360e70df9da138eabb002e34666','5a107feb60f518e1bed5fbd44de19f10dfde1d1e','92d4f652bcf5160b9815ea29546bde415cb83b04','42ebb8a722e7940826975575b2cb422c0a112c68','1a761bd94b707be3a5bd87fbcce0e0873c0b60ab','2fc6eb9f9eb3e005eb3c4765f638203ce0c34f5f','57672cdb7506becfcf63d59cc06f88d7e240808c','59ad4ed1b502b7adb49cf799c107bf405ddc0cca','4f00716246c38ec50813c6dd1e17b1e87a399252','767cec7804216f7b7bf6565a735c683fb2282059','c3258281fe46017ff5ea19cb08c711a6c281d673','755e6ed1b6f991af24c720c51546b5e0f6ef9ca5','3fb041d606429c494f972b82556759cf1a22171f','2f2ff31150ecec96cae1417fab3c4bda7e626948','6253f7f734608919f9966365fbbdd42163af7af2','db7da9a182140259b590eedd078f64b4831df749','9db35cf980c7170803f09243fb2f631ea0558adc','a96cbc244801cd9c8e201fa5a35e29dbb2a6cf08','920ab711970123a6123c8aa41190b63862399a5b',];
+ var tests = {
+ "b76df4b192c11a5ef7a3e895a7dd2aaea2dcc5c7":[async_test('html5lib_domjs-unsafe.html b76df4b192c11a5ef7a3e895a7dd2aaea2dcc5c7'), "%3Csvg%3E%3C%21%5BCDATA%5Bfoo%0Abar%5D%5D%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%22foo%0Abar%22"],"da5cf60e732fcf20d288e772e51a7a9ccd3471e4":[async_test('html5lib_domjs-unsafe.html da5cf60e732fcf20d288e772e51a7a9ccd3471e4'), "%3Csvg%3E%3C%21%5BCDATA%5Bfoo%0Dbar%5D%5D%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%22foo%0Abar%22"],"c32f77685b52841e1685110a8a6fac17b3ae127a":[async_test('html5lib_domjs-unsafe.html c32f77685b52841e1685110a8a6fac17b3ae127a'), "%3Csvg%3E%3C%21%5BCDATA%5Bfoo%0D%0Abar%5D%5D%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%22foo%0Abar%22"],"4fd39e063b0ad1fa82274d6de3122859f76934a8":[async_test('html5lib_domjs-unsafe.html 4fd39e063b0ad1fa82274d6de3122859f76934a8'), "%3Cscript%3Ea%3D%27%00%27%3C/script%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22a%3D%27%EF%BF%BD%27%22%0A%7C%20%20%20%3Cbody%3E"],"7208fbe8702c37cf180b1c736c984f5340517408":[async_test('html5lib_domjs-unsafe.html 7208fbe8702c37cf180b1c736c984f5340517408'), "%3Cscript%20type%3D%22data%22%3E%3C%21--%00%3C/script%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20type%3D%22data%22%0A%7C%20%20%20%20%20%20%20%22%3C%21--%EF%BF%BD%22%0A%7C%20%20%20%3Cbody%3E"],"7b5dd0bcb2a92ebf1974a0ec6017a798e774ca5b":[async_test('html5lib_domjs-unsafe.html 7b5dd0bcb2a92ebf1974a0ec6017a798e774ca5b'), "%3Cscript%20type%3D%22data%22%3E%3C%21--foo%00%3C/script%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20type%3D%22data%22%0A%7C%20%20%20%20%20%20%20%22%3C%21--foo%EF%BF%BD%22%0A%7C%20%20%20%3Cbody%3E"],"54c3b7008093eea8c5b45f729585097df53641a8":[async_test('html5lib_domjs-unsafe.html 54c3b7008093eea8c5b45f729585097df53641a8'), "%3Cscript%20type%3D%22data%22%3E%3C%21--%20foo-%00%3C/script%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20type%3D%22data%22%0A%7C%20%20%20%20%20%20%20%22%3C%21--%20foo-%EF%BF%BD%22%0A%7C%20%20%20%3Cbody%3E"],"b8de3bd0272a8362093670968eb21ad0bfa3cd40":[async_test('html5lib_domjs-unsafe.html b8de3bd0272a8362093670968eb21ad0bfa3cd40'), "%3Cscript%20type%3D%22data%22%3E%3C%21--%20foo--%00%3C/script%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20type%3D%22data%22%0A%7C%20%20%20%20%20%20%20%22%3C%21--%20foo--%EF%BF%BD%22%0A%7C%20%20%20%3Cbody%3E"],"40033d4270de7ad3595607426efc221988100175":[async_test('html5lib_domjs-unsafe.html 40033d4270de7ad3595607426efc221988100175'), "%3Cscript%20type%3D%22data%22%3E%3C%21--%20foo-", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20type%3D%22data%22%0A%7C%20%20%20%20%20%20%20%22%3C%21--%20foo-%22%0A%7C%20%20%20%3Cbody%3E"],"4ffebb41a5c7f9239ba71301793a1e1cfd65dece":[async_test('html5lib_domjs-unsafe.html 4ffebb41a5c7f9239ba71301793a1e1cfd65dece'), "%3Cscript%20type%3D%22data%22%3E%3C%21--%20foo-%3C%3C/script%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20type%3D%22data%22%0A%7C%20%20%20%20%20%20%20%22%3C%21--%20foo-%3C%22%0A%7C%20%20%20%3Cbody%3E"],"4fa68424ed093da8a6c954d64bb154ef4269ea83":[async_test('html5lib_domjs-unsafe.html 4fa68424ed093da8a6c954d64bb154ef4269ea83'), "%3Cscript%20type%3D%22data%22%3E%3C%21--%20foo-%3CS", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20type%3D%22data%22%0A%7C%20%20%20%20%20%20%20%22%3C%21--%20foo-%3CS%22%0A%7C%20%20%20%3Cbody%3E"],"41ddb90fa2e7785945dd18c32736dc83c1440fa4":[async_test('html5lib_domjs-unsafe.html 41ddb90fa2e7785945dd18c32736dc83c1440fa4'), "%3Cscript%20type%3D%22data%22%3E%3C%21--%20foo-%3C/SCRIPT%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20type%3D%22data%22%0A%7C%20%20%20%20%20%20%20%22%3C%21--%20foo-%22%0A%7C%20%20%20%3Cbody%3E"],"89466f9770c893ffb117d18eac80993bd69564ad":[async_test('html5lib_domjs-unsafe.html 89466f9770c893ffb117d18eac80993bd69564ad'), "%3Cscript%20type%3D%22data%22%3E%3C%21--%3Cp%3E%3C/script%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20type%3D%22data%22%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cp%3E%22%0A%7C%20%20%20%3Cbody%3E"],"72186fc6836326792e7e46ce4b5432191a5ac192":[async_test('html5lib_domjs-unsafe.html 72186fc6836326792e7e46ce4b5432191a5ac192'), "%3Cscript%20type%3D%22data%22%3E%3C%21--%3Cscript%3E%3C/script%3E%3C/script%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20type%3D%22data%22%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%3E%3C/script%3E%22%0A%7C%20%20%20%3Cbody%3E"],"9863747db1e2676bad75c9929d895db2bb02306c":[async_test('html5lib_domjs-unsafe.html 9863747db1e2676bad75c9929d895db2bb02306c'), "%3Cscript%20type%3D%22data%22%3E%3C%21--%3Cscript%3E%00%3C/script%3E%3C/script%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20type%3D%22data%22%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%3E%EF%BF%BD%3C/script%3E%22%0A%7C%20%20%20%3Cbody%3E"],"01818845dd1283fc54707a140be17e689a91f013":[async_test('html5lib_domjs-unsafe.html 01818845dd1283fc54707a140be17e689a91f013'), "%3Cscript%20type%3D%22data%22%3E%3C%21--%3Cscript%3E-%00%3C/script%3E%3C/script%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20type%3D%22data%22%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%3E-%EF%BF%BD%3C/script%3E%22%0A%7C%20%20%20%3Cbody%3E"],"3255082e063beec09c3b0e605f0e3bfae177a113":[async_test('html5lib_domjs-unsafe.html 3255082e063beec09c3b0e605f0e3bfae177a113'), "%3Cscript%20type%3D%22data%22%3E%3C%21--%3Cscript%3E--%00%3C/script%3E%3C/script%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20type%3D%22data%22%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%3E--%EF%BF%BD%3C/script%3E%22%0A%7C%20%20%20%3Cbody%3E"],"54cd599d050ee568b0ed0060d1926479d3e528c3":[async_test('html5lib_domjs-unsafe.html 54cd599d050ee568b0ed0060d1926479d3e528c3'), "%3Cscript%20type%3D%22data%22%3E%3C%21--%3Cscript%3E---%3C/script%3E%3C/script%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20type%3D%22data%22%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%3E---%3C/script%3E%22%0A%7C%20%20%20%3Cbody%3E"],"bf081558b113ea712baeeb3294f3b53845510996":[async_test('html5lib_domjs-unsafe.html bf081558b113ea712baeeb3294f3b53845510996'), "%3Cscript%20type%3D%22data%22%3E%3C%21--%3Cscript%3E%3C/scrip%3E%3C/SCRIPT%3E%3C/script%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20type%3D%22data%22%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%3E%3C/scrip%3E%3C/SCRIPT%3E%22%0A%7C%20%20%20%3Cbody%3E"],"25e3471f40f3b6b0b448f7f7be41f0ee06403faa":[async_test('html5lib_domjs-unsafe.html 25e3471f40f3b6b0b448f7f7be41f0ee06403faa'), "%3Cscript%20type%3D%22data%22%3E%3C%21--%3Cscript%3E%3C/scrip%20%3C/SCRIPT%3E%3C/script%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20type%3D%22data%22%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%3E%3C/scrip%20%3C/SCRIPT%3E%22%0A%7C%20%20%20%3Cbody%3E"],"006df46be5600e3d99caaf7dfc6a8af1636fd43a":[async_test('html5lib_domjs-unsafe.html 006df46be5600e3d99caaf7dfc6a8af1636fd43a'), "%3Cscript%20type%3D%22data%22%3E%3C%21--%3Cscript%3E%3C/scrip/%3C/SCRIPT%3E%3C/script%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20type%3D%22data%22%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%3E%3C/scrip/%3C/SCRIPT%3E%22%0A%7C%20%20%20%3Cbody%3E"],"b9bea556d1a155ef04e3f583328d51cf95995945":[async_test('html5lib_domjs-unsafe.html b9bea556d1a155ef04e3f583328d51cf95995945'), "%3Cscript%20type%3D%22data%22%3E%3C/scrip/%3E%3C/script%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20type%3D%22data%22%0A%7C%20%20%20%20%20%20%20%22%3C/scrip/%3E%22%0A%7C%20%20%20%3Cbody%3E"],"9eff404da18d0c20765a19613c718a9f49b874ac":[async_test('html5lib_domjs-unsafe.html 9eff404da18d0c20765a19613c718a9f49b874ac'), "%3Cscript%20type%3D%22data%22%3E%3C/scrip%20%3E%3C/script%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20type%3D%22data%22%0A%7C%20%20%20%20%20%20%20%22%3C/scrip%20%3E%22%0A%7C%20%20%20%3Cbody%3E"],"1d246a13e96719a3fb48f1a81d1218671ee3a472":[async_test('html5lib_domjs-unsafe.html 1d246a13e96719a3fb48f1a81d1218671ee3a472'), "%3Cscript%20type%3D%22data%22%3E%3C%21--%3C/scrip%3E%3C/script%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20type%3D%22data%22%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3C/scrip%3E%22%0A%7C%20%20%20%3Cbody%3E"],"92bb86082f237803c7ace5fcd41a36861b364551":[async_test('html5lib_domjs-unsafe.html 92bb86082f237803c7ace5fcd41a36861b364551'), "%3Cscript%20type%3D%22data%22%3E%3C%21--%3C/scrip%20%3C/script%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20type%3D%22data%22%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3C/scrip%20%22%0A%7C%20%20%20%3Cbody%3E"],"3a89dee49af0d2b537ad0c50fb74bb68d4dfe651":[async_test('html5lib_domjs-unsafe.html 3a89dee49af0d2b537ad0c50fb74bb68d4dfe651'), "%3Cscript%20type%3D%22data%22%3E%3C%21--%3C/scrip/%3C/script%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20type%3D%22data%22%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3C/scrip/%22%0A%7C%20%20%20%3Cbody%3E"],"89bd023b6e2cbc5c7a37d85b45eadc88143bd670":[async_test('html5lib_domjs-unsafe.html 89bd023b6e2cbc5c7a37d85b45eadc88143bd670'), "%3C%21DOCTYPE%20html%3E%3C%21DOCTYPE%20html%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"9574dbbf3302c84fc4ddb965bf1f43ae7106e68c":[async_test('html5lib_domjs-unsafe.html 9574dbbf3302c84fc4ddb965bf1f43ae7106e68c'), "%3Chtml%3E%3C%21DOCTYPE%20html%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"341226c7328f8d3d6ab1d373368cc14aad712f20":[async_test('html5lib_domjs-unsafe.html 341226c7328f8d3d6ab1d373368cc14aad712f20'), "%3Chtml%3E%3Chead%3E%3C%21DOCTYPE%20html%3E%3C/head%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"15b3a23030aed47b3795d9c1ef11cd241b6902cb":[async_test('html5lib_domjs-unsafe.html 15b3a23030aed47b3795d9c1ef11cd241b6902cb'), "%3Chtml%3E%3Chead%3E%3C/head%3E%3C%21DOCTYPE%20html%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"4b318ddd18e0e360e70df9da138eabb002e34666":[async_test('html5lib_domjs-unsafe.html 4b318ddd18e0e360e70df9da138eabb002e34666'), "%3Cbody%3E%3C/body%3E%3C%21DOCTYPE%20html%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"5a107feb60f518e1bed5fbd44de19f10dfde1d1e":[async_test('html5lib_domjs-unsafe.html 5a107feb60f518e1bed5fbd44de19f10dfde1d1e'), "%3Ctable%3E%3C%21DOCTYPE%20html%3E%3C/table%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E"],"92d4f652bcf5160b9815ea29546bde415cb83b04":[async_test('html5lib_domjs-unsafe.html 92d4f652bcf5160b9815ea29546bde415cb83b04'), "%3Cselect%3E%3C%21DOCTYPE%20html%3E%3C/select%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cselect%3E"],"42ebb8a722e7940826975575b2cb422c0a112c68":[async_test('html5lib_domjs-unsafe.html 42ebb8a722e7940826975575b2cb422c0a112c68'), "%3Ctable%3E%3Ccolgroup%3E%3C%21DOCTYPE%20html%3E%3C/colgroup%3E%3C/table%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ccolgroup%3E"],"1a761bd94b707be3a5bd87fbcce0e0873c0b60ab":[async_test('html5lib_domjs-unsafe.html 1a761bd94b707be3a5bd87fbcce0e0873c0b60ab'), "%3Ctable%3E%3Ccolgroup%3E%3C%21--test--%3E%3C/colgroup%3E%3C/table%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ccolgroup%3E%0A%7C%20%20%20%20%20%20%20%20%20%3C%21--%20test%20--%3E"],"2fc6eb9f9eb3e005eb3c4765f638203ce0c34f5f":[async_test('html5lib_domjs-unsafe.html 2fc6eb9f9eb3e005eb3c4765f638203ce0c34f5f'), "%3Ctable%3E%3Ccolgroup%3E%3Chtml%3E%3C/colgroup%3E%3C/table%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ccolgroup%3E"],"57672cdb7506becfcf63d59cc06f88d7e240808c":[async_test('html5lib_domjs-unsafe.html 57672cdb7506becfcf63d59cc06f88d7e240808c'), "%3Ctable%3E%3Ccolgroup%3E%20foo%3C/colgroup%3E%3C/table%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22foo%22%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ccolgroup%3E%0A%7C%20%20%20%20%20%20%20%20%20%22%20%22"],"59ad4ed1b502b7adb49cf799c107bf405ddc0cca":[async_test('html5lib_domjs-unsafe.html 59ad4ed1b502b7adb49cf799c107bf405ddc0cca'), "%3Cselect%3E%3C%21--test--%3E%3C/select%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cselect%3E%0A%7C%20%20%20%20%20%20%20%3C%21--%20test%20--%3E"],"4f00716246c38ec50813c6dd1e17b1e87a399252":[async_test('html5lib_domjs-unsafe.html 4f00716246c38ec50813c6dd1e17b1e87a399252'), "%3Cselect%3E%3Chtml%3E%3C/select%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cselect%3E"],"767cec7804216f7b7bf6565a735c683fb2282059":[async_test('html5lib_domjs-unsafe.html 767cec7804216f7b7bf6565a735c683fb2282059'), "%3Cframeset%3E%3Chtml%3E%3C/frameset%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E"],"c3258281fe46017ff5ea19cb08c711a6c281d673":[async_test('html5lib_domjs-unsafe.html c3258281fe46017ff5ea19cb08c711a6c281d673'), "%3Cframeset%3E%3C/frameset%3E%3Chtml%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E"],"755e6ed1b6f991af24c720c51546b5e0f6ef9ca5":[async_test('html5lib_domjs-unsafe.html 755e6ed1b6f991af24c720c51546b5e0f6ef9ca5'), "%3Cframeset%3E%3C/frameset%3E%3C%21DOCTYPE%20html%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E"],"3fb041d606429c494f972b82556759cf1a22171f":[async_test('html5lib_domjs-unsafe.html 3fb041d606429c494f972b82556759cf1a22171f'), "%3Chtml%3E%3Cbody%3E%3C/body%3E%3C/html%3E%3C%21DOCTYPE%20html%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"2f2ff31150ecec96cae1417fab3c4bda7e626948":[async_test('html5lib_domjs-unsafe.html 2f2ff31150ecec96cae1417fab3c4bda7e626948'), "%3Csvg%3E%3C%21DOCTYPE%20html%3E%3C/svg%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E"],"6253f7f734608919f9966365fbbdd42163af7af2":[async_test('html5lib_domjs-unsafe.html 6253f7f734608919f9966365fbbdd42163af7af2'), "%3Csvg%3E%3Cfont%3E%3C/font%3E%3C/svg%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20font%3E"],"db7da9a182140259b590eedd078f64b4831df749":[async_test('html5lib_domjs-unsafe.html db7da9a182140259b590eedd078f64b4831df749'), "%3Csvg%3E%3Cfont%20id%3Dfoo%3E%3C/font%3E%3C/svg%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20font%3E%0A%7C%20%20%20%20%20%20%20%20%20id%3D%22foo%22"],"9db35cf980c7170803f09243fb2f631ea0558adc":[async_test('html5lib_domjs-unsafe.html 9db35cf980c7170803f09243fb2f631ea0558adc'), "%3Csvg%3E%3Cfont%20size%3D4%3E%3C/font%3E%3C/svg%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20size%3D%224%22"],"a96cbc244801cd9c8e201fa5a35e29dbb2a6cf08":[async_test('html5lib_domjs-unsafe.html a96cbc244801cd9c8e201fa5a35e29dbb2a6cf08'), "%3Csvg%3E%3Cfont%20color%3Dred%3E%3C/font%3E%3C/svg%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20color%3D%22red%22"],"920ab711970123a6123c8aa41190b63862399a5b":[async_test('html5lib_domjs-unsafe.html 920ab711970123a6123c8aa41190b63862399a5b'), "%3Csvg%3E%3Cfont%20font%3Dsans%3E%3C/font%3E%3C/svg%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20font%3E%0A%7C%20%20%20%20%20%20%20%20%20font%3D%22sans%22"],
+ }
+ init_tests(get_type());
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_entities01.html b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_entities01.html
new file mode 100644
index 00000000000..c3af61b7904
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_entities01.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf8">
+ <title>HTML 5 Parser tests html5lib_entities01.html</title>
+ <meta name="timeout" content="long">
+ <meta name="variant" content="?run_type=uri">
+ <meta name="variant" content="?run_type=write">
+ <meta name="variant" content="?run_type=write_single">
+ </head>
+ <body>
+ <h1>html5lib Parser Test</h1>
+ <div id="log"></div>
+ <script src="common.js"></script>
+ <script src="test.js"></script>
+ <script src="template.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ var num_iframes = 8;
+ var order = ['16c694bcf0b3ff3723fa070eea7e1e82ef12a337','05e04b39ef06e2367a33326f5dd566913aa6628f','fbf7d9fec595585869c5c595d5588b34fd175278','e59b0a76d7bcfb429b27e00e469f35e08a9bdd1a','5ea854d6ecd4d6dd459cb36d4faf3ed36e11c073','119cd15b852615cd0fce759769b4a3788595e3bb','9c00a1833e8cf4af28c8bd94902412ad7052b4b0','b5bcdcbc6e88b380be0e48ca2620fbbb8e92e497','bf6c90305b2856c2d9c9a146dfff867fe7a5e0f3','6b9c8d175a3d7b6cf04ffd72e44a7dc88686460f','76c184d9ce64b8a52c2e67eafeb8d332c096f2be','4c30f8f931eb44c2f208e837555c0cc444dd4612','1db77ef761092d65ce847c0bcd6e7cb892db754d','284c18aa40a73e4052525a9ffb30b23182f237ea','6b336a43e394d3ab7ceb2ab54c63409e8a27aded','436c30dd76bf9b5c2b29a181d9a9412ec0ab4bdf','1373a52ddcb71f20f29d92abb6714eaabeba7424','d60f4f324a1ad9c09c4d3590c8c537af2852eeb4','d21511e2df56c306c78e1449c960c66e565e016e','39107d16f24d4c7bcd40ad1239b5f4f677877ee8','a44b740e8b2349e75c9eb0376f665eab13ff821d','a0e38b1c19eba037b34c68864634cff032f0b892','390d9571a24be0961c8fcd78c69eea16a6414246','ceba8404405dd3b3b423c45411bde15bf72a846d','f8dd2fccc21d3a08790a7877186840a692adf111','d526830d439d3c4e966b22fbedf819d465d3107b','240af7bacbfecce6e2a973de9c89fad817fb8d42','d657585ca1df5b86693fca8a0a2eae76bd9b1c2b','b508fcffb2d9f2424c7837270e51824321fb4570','897ab551df27df14418a46ff1c3acef8338c53f3','493a472ccf903088c813ff6874d54482a161df8f','67d19edb1f6ecbbb6ccb90df2345e52e5c58efc3','dded422b7406c966c944555f220d7d3dfcf2a143','60a76c9e10e4ac53f836f9e45eb0518dd0b7b73b','b47fcc6a614247319908b00935f10ec134399917','3b5c7d0331ae900e1179eaf3545c78d147434fbf','a0f119508046dbb4f8059232f6e99f66c1e8e7a6','daab384be8471edeb755353c5dccaad0c415dac5','8485e4d103a517615f39c0d0b71fe5065c5437db','4c28749faddb096d1f04792b7daf039268c43181','c84c576954c4c493528eaa34233c926653152be5','b2797e18c499df32296545225c259dbf4bea2908','5b2dfe6f187413faecd91336bd353c05768ea722','34af7be5bcff18ec869a306b19daea70f61f7088','8f2e74688427858fc1a895fc472d074a0528a7ae','530d6251a43d688e69959237e519812585de8266','bced9b8c339d0d2838ea0fffe9a64027b4f3a877','9c9e8079df25999c606bc84f46b348544a23b9b4','ec61d22b3bc6f93e54bbff964311bba9a3a06b21','391f0136aebdd0e874c8eb85651ffda7e9f86f24','e2974e7029b008539aacc1ee885705764f8c53f4','23e105ca5329cc0338a96fe7e088ba9b319c46d1','87af28752724c400edef3970e52440639be5b1a8','f50d9e39e2bda3d8c0b1c69d1f1e4e86c4b39ac3','12827fadb8d36b829e9c2c7315e0848d2d7ef278','f603997321070e6ccada6fefe4240a9e6c7e870a','a88e381bf36e74aaa8ac5b0877153b7158bae579','11019fa64a25748a5bfb864fc200ec2710b54aa3','3d238b9146102bd11e898ff4913f86e8ded65be4','a1375bfde7be56e514471700e030b1c7e7090e2f','7936b73efa385d183e93453bea24fd0c4dff4742','41cdf6978b0c48e7044d5e4534fc8bb08de4cdf2','5138f572a4db2e2edc2d723e1bb87af72ab501f4','f30757617b6df330deba1cb607e8d47f71bda13f','a6fd8cdca1fa8cf07519d9a0c5b779eafa438b70','ada342466887e85d89c3b815b127bfced036ac76','74bd99a9263f0b8e8a5fac4d2684fe37d5a1a9cc',];
+ var tests = {
+ "16c694bcf0b3ff3723fa070eea7e1e82ef12a337":[async_test('html5lib_entities01.html 16c694bcf0b3ff3723fa070eea7e1e82ef12a337'), "FOO%26gt%3BBAR", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%3EBAR%22"],"05e04b39ef06e2367a33326f5dd566913aa6628f":[async_test('html5lib_entities01.html 05e04b39ef06e2367a33326f5dd566913aa6628f'), "FOO%26gtBAR", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%3EBAR%22"],"fbf7d9fec595585869c5c595d5588b34fd175278":[async_test('html5lib_entities01.html fbf7d9fec595585869c5c595d5588b34fd175278'), "FOO%26gt%20BAR", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%3E%20BAR%22"],"e59b0a76d7bcfb429b27e00e469f35e08a9bdd1a":[async_test('html5lib_entities01.html e59b0a76d7bcfb429b27e00e469f35e08a9bdd1a'), "FOO%26gt%3B%3B%3BBAR", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%3E%3B%3BBAR%22"],"5ea854d6ecd4d6dd459cb36d4faf3ed36e11c073":[async_test('html5lib_entities01.html 5ea854d6ecd4d6dd459cb36d4faf3ed36e11c073'), "I%27m%20%26notit%3B%20I%20tell%20you", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22I%27m%20%C2%ACit%3B%20I%20tell%20you%22"],"119cd15b852615cd0fce759769b4a3788595e3bb":[async_test('html5lib_entities01.html 119cd15b852615cd0fce759769b4a3788595e3bb'), "I%27m%20%26notin%3B%20I%20tell%20you", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22I%27m%20%E2%88%89%20I%20tell%20you%22"],"9c00a1833e8cf4af28c8bd94902412ad7052b4b0":[async_test('html5lib_entities01.html 9c00a1833e8cf4af28c8bd94902412ad7052b4b0'), "FOO%26%20BAR", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%26%20BAR%22"],"b5bcdcbc6e88b380be0e48ca2620fbbb8e92e497":[async_test('html5lib_entities01.html b5bcdcbc6e88b380be0e48ca2620fbbb8e92e497'), "FOO%26%3CBAR%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%26%22%0A%7C%20%20%20%20%20%3Cbar%3E"],"bf6c90305b2856c2d9c9a146dfff867fe7a5e0f3":[async_test('html5lib_entities01.html bf6c90305b2856c2d9c9a146dfff867fe7a5e0f3'), "FOO%26%26%26%26gt%3BBAR", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%26%26%26%3EBAR%22"],"6b9c8d175a3d7b6cf04ffd72e44a7dc88686460f":[async_test('html5lib_entities01.html 6b9c8d175a3d7b6cf04ffd72e44a7dc88686460f'), "FOO%26%2341%3BBAR", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%29BAR%22"],"76c184d9ce64b8a52c2e67eafeb8d332c096f2be":[async_test('html5lib_entities01.html 76c184d9ce64b8a52c2e67eafeb8d332c096f2be'), "FOO%26%23x41%3BBAR", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOOABAR%22"],"4c30f8f931eb44c2f208e837555c0cc444dd4612":[async_test('html5lib_entities01.html 4c30f8f931eb44c2f208e837555c0cc444dd4612'), "FOO%26%23X41%3BBAR", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOOABAR%22"],"1db77ef761092d65ce847c0bcd6e7cb892db754d":[async_test('html5lib_entities01.html 1db77ef761092d65ce847c0bcd6e7cb892db754d'), "FOO%26%23BAR", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%26%23BAR%22"],"284c18aa40a73e4052525a9ffb30b23182f237ea":[async_test('html5lib_entities01.html 284c18aa40a73e4052525a9ffb30b23182f237ea'), "FOO%26%23ZOO", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%26%23ZOO%22"],"6b336a43e394d3ab7ceb2ab54c63409e8a27aded":[async_test('html5lib_entities01.html 6b336a43e394d3ab7ceb2ab54c63409e8a27aded'), "FOO%26%23xBAR", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%C2%BAR%22"],"436c30dd76bf9b5c2b29a181d9a9412ec0ab4bdf":[async_test('html5lib_entities01.html 436c30dd76bf9b5c2b29a181d9a9412ec0ab4bdf'), "FOO%26%23xZOO", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%26%23xZOO%22"],"1373a52ddcb71f20f29d92abb6714eaabeba7424":[async_test('html5lib_entities01.html 1373a52ddcb71f20f29d92abb6714eaabeba7424'), "FOO%26%23XZOO", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%26%23XZOO%22"],"d60f4f324a1ad9c09c4d3590c8c537af2852eeb4":[async_test('html5lib_entities01.html d60f4f324a1ad9c09c4d3590c8c537af2852eeb4'), "FOO%26%2341BAR", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%29BAR%22"],"d21511e2df56c306c78e1449c960c66e565e016e":[async_test('html5lib_entities01.html d21511e2df56c306c78e1449c960c66e565e016e'), "FOO%26%23x41BAR", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%E4%86%BAR%22"],"39107d16f24d4c7bcd40ad1239b5f4f677877ee8":[async_test('html5lib_entities01.html 39107d16f24d4c7bcd40ad1239b5f4f677877ee8'), "FOO%26%23x41ZOO", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOOAZOO%22"],"a44b740e8b2349e75c9eb0376f665eab13ff821d":[async_test('html5lib_entities01.html a44b740e8b2349e75c9eb0376f665eab13ff821d'), "FOO%26%23x0000%3BZOO", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%EF%BF%BDZOO%22"],"a0e38b1c19eba037b34c68864634cff032f0b892":[async_test('html5lib_entities01.html a0e38b1c19eba037b34c68864634cff032f0b892'), "FOO%26%23x0078%3BZOO", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOOxZOO%22"],"390d9571a24be0961c8fcd78c69eea16a6414246":[async_test('html5lib_entities01.html 390d9571a24be0961c8fcd78c69eea16a6414246'), "FOO%26%23x0079%3BZOO", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOOyZOO%22"],"ceba8404405dd3b3b423c45411bde15bf72a846d":[async_test('html5lib_entities01.html ceba8404405dd3b3b423c45411bde15bf72a846d'), "FOO%26%23x0080%3BZOO", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%E2%82%ACZOO%22"],"f8dd2fccc21d3a08790a7877186840a692adf111":[async_test('html5lib_entities01.html f8dd2fccc21d3a08790a7877186840a692adf111'), "FOO%26%23x0081%3BZOO", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%C2%81ZOO%22"],"d526830d439d3c4e966b22fbedf819d465d3107b":[async_test('html5lib_entities01.html d526830d439d3c4e966b22fbedf819d465d3107b'), "FOO%26%23x0082%3BZOO", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%E2%80%9AZOO%22"],"240af7bacbfecce6e2a973de9c89fad817fb8d42":[async_test('html5lib_entities01.html 240af7bacbfecce6e2a973de9c89fad817fb8d42'), "FOO%26%23x0083%3BZOO", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%C6%92ZOO%22"],"d657585ca1df5b86693fca8a0a2eae76bd9b1c2b":[async_test('html5lib_entities01.html d657585ca1df5b86693fca8a0a2eae76bd9b1c2b'), "FOO%26%23x0084%3BZOO", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%E2%80%9EZOO%22"],"b508fcffb2d9f2424c7837270e51824321fb4570":[async_test('html5lib_entities01.html b508fcffb2d9f2424c7837270e51824321fb4570'), "FOO%26%23x0085%3BZOO", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%E2%80%A6ZOO%22"],"897ab551df27df14418a46ff1c3acef8338c53f3":[async_test('html5lib_entities01.html 897ab551df27df14418a46ff1c3acef8338c53f3'), "FOO%26%23x0086%3BZOO", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%E2%80%A0ZOO%22"],"493a472ccf903088c813ff6874d54482a161df8f":[async_test('html5lib_entities01.html 493a472ccf903088c813ff6874d54482a161df8f'), "FOO%26%23x0087%3BZOO", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%E2%80%A1ZOO%22"],"67d19edb1f6ecbbb6ccb90df2345e52e5c58efc3":[async_test('html5lib_entities01.html 67d19edb1f6ecbbb6ccb90df2345e52e5c58efc3'), "FOO%26%23x0088%3BZOO", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%CB%86ZOO%22"],"dded422b7406c966c944555f220d7d3dfcf2a143":[async_test('html5lib_entities01.html dded422b7406c966c944555f220d7d3dfcf2a143'), "FOO%26%23x0089%3BZOO", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%E2%80%B0ZOO%22"],"60a76c9e10e4ac53f836f9e45eb0518dd0b7b73b":[async_test('html5lib_entities01.html 60a76c9e10e4ac53f836f9e45eb0518dd0b7b73b'), "FOO%26%23x008A%3BZOO", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%C5%A0ZOO%22"],"b47fcc6a614247319908b00935f10ec134399917":[async_test('html5lib_entities01.html b47fcc6a614247319908b00935f10ec134399917'), "FOO%26%23x008B%3BZOO", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%E2%80%B9ZOO%22"],"3b5c7d0331ae900e1179eaf3545c78d147434fbf":[async_test('html5lib_entities01.html 3b5c7d0331ae900e1179eaf3545c78d147434fbf'), "FOO%26%23x008C%3BZOO", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%C5%92ZOO%22"],"a0f119508046dbb4f8059232f6e99f66c1e8e7a6":[async_test('html5lib_entities01.html a0f119508046dbb4f8059232f6e99f66c1e8e7a6'), "FOO%26%23x008D%3BZOO", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%C2%8DZOO%22"],"daab384be8471edeb755353c5dccaad0c415dac5":[async_test('html5lib_entities01.html daab384be8471edeb755353c5dccaad0c415dac5'), "FOO%26%23x008E%3BZOO", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%C5%BDZOO%22"],"8485e4d103a517615f39c0d0b71fe5065c5437db":[async_test('html5lib_entities01.html 8485e4d103a517615f39c0d0b71fe5065c5437db'), "FOO%26%23x008F%3BZOO", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%C2%8FZOO%22"],"4c28749faddb096d1f04792b7daf039268c43181":[async_test('html5lib_entities01.html 4c28749faddb096d1f04792b7daf039268c43181'), "FOO%26%23x0090%3BZOO", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%C2%90ZOO%22"],"c84c576954c4c493528eaa34233c926653152be5":[async_test('html5lib_entities01.html c84c576954c4c493528eaa34233c926653152be5'), "FOO%26%23x0091%3BZOO", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%E2%80%98ZOO%22"],"b2797e18c499df32296545225c259dbf4bea2908":[async_test('html5lib_entities01.html b2797e18c499df32296545225c259dbf4bea2908'), "FOO%26%23x0092%3BZOO", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%E2%80%99ZOO%22"],"5b2dfe6f187413faecd91336bd353c05768ea722":[async_test('html5lib_entities01.html 5b2dfe6f187413faecd91336bd353c05768ea722'), "FOO%26%23x0093%3BZOO", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%E2%80%9CZOO%22"],"34af7be5bcff18ec869a306b19daea70f61f7088":[async_test('html5lib_entities01.html 34af7be5bcff18ec869a306b19daea70f61f7088'), "FOO%26%23x0094%3BZOO", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%E2%80%9DZOO%22"],"8f2e74688427858fc1a895fc472d074a0528a7ae":[async_test('html5lib_entities01.html 8f2e74688427858fc1a895fc472d074a0528a7ae'), "FOO%26%23x0095%3BZOO", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%E2%80%A2ZOO%22"],"530d6251a43d688e69959237e519812585de8266":[async_test('html5lib_entities01.html 530d6251a43d688e69959237e519812585de8266'), "FOO%26%23x0096%3BZOO", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%E2%80%93ZOO%22"],"bced9b8c339d0d2838ea0fffe9a64027b4f3a877":[async_test('html5lib_entities01.html bced9b8c339d0d2838ea0fffe9a64027b4f3a877'), "FOO%26%23x0097%3BZOO", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%E2%80%94ZOO%22"],"9c9e8079df25999c606bc84f46b348544a23b9b4":[async_test('html5lib_entities01.html 9c9e8079df25999c606bc84f46b348544a23b9b4'), "FOO%26%23x0098%3BZOO", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%CB%9CZOO%22"],"ec61d22b3bc6f93e54bbff964311bba9a3a06b21":[async_test('html5lib_entities01.html ec61d22b3bc6f93e54bbff964311bba9a3a06b21'), "FOO%26%23x0099%3BZOO", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%E2%84%A2ZOO%22"],"391f0136aebdd0e874c8eb85651ffda7e9f86f24":[async_test('html5lib_entities01.html 391f0136aebdd0e874c8eb85651ffda7e9f86f24'), "FOO%26%23x009A%3BZOO", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%C5%A1ZOO%22"],"e2974e7029b008539aacc1ee885705764f8c53f4":[async_test('html5lib_entities01.html e2974e7029b008539aacc1ee885705764f8c53f4'), "FOO%26%23x009B%3BZOO", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%E2%80%BAZOO%22"],"23e105ca5329cc0338a96fe7e088ba9b319c46d1":[async_test('html5lib_entities01.html 23e105ca5329cc0338a96fe7e088ba9b319c46d1'), "FOO%26%23x009C%3BZOO", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%C5%93ZOO%22"],"87af28752724c400edef3970e52440639be5b1a8":[async_test('html5lib_entities01.html 87af28752724c400edef3970e52440639be5b1a8'), "FOO%26%23x009D%3BZOO", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%C2%9DZOO%22"],"f50d9e39e2bda3d8c0b1c69d1f1e4e86c4b39ac3":[async_test('html5lib_entities01.html f50d9e39e2bda3d8c0b1c69d1f1e4e86c4b39ac3'), "FOO%26%23x009E%3BZOO", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%C5%BEZOO%22"],"12827fadb8d36b829e9c2c7315e0848d2d7ef278":[async_test('html5lib_entities01.html 12827fadb8d36b829e9c2c7315e0848d2d7ef278'), "FOO%26%23x009F%3BZOO", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%C5%B8ZOO%22"],"f603997321070e6ccada6fefe4240a9e6c7e870a":[async_test('html5lib_entities01.html f603997321070e6ccada6fefe4240a9e6c7e870a'), "FOO%26%23x00A0%3BZOO", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%C2%A0ZOO%22"],"a88e381bf36e74aaa8ac5b0877153b7158bae579":[async_test('html5lib_entities01.html a88e381bf36e74aaa8ac5b0877153b7158bae579'), "FOO%26%23xD7FF%3BZOO", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%ED%9F%BFZOO%22"],"11019fa64a25748a5bfb864fc200ec2710b54aa3":[async_test('html5lib_entities01.html 11019fa64a25748a5bfb864fc200ec2710b54aa3'), "FOO%26%23xD800%3BZOO", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%EF%BF%BDZOO%22"],"3d238b9146102bd11e898ff4913f86e8ded65be4":[async_test('html5lib_entities01.html 3d238b9146102bd11e898ff4913f86e8ded65be4'), "FOO%26%23xD801%3BZOO", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%EF%BF%BDZOO%22"],"a1375bfde7be56e514471700e030b1c7e7090e2f":[async_test('html5lib_entities01.html a1375bfde7be56e514471700e030b1c7e7090e2f'), "FOO%26%23xDFFE%3BZOO", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%EF%BF%BDZOO%22"],"7936b73efa385d183e93453bea24fd0c4dff4742":[async_test('html5lib_entities01.html 7936b73efa385d183e93453bea24fd0c4dff4742'), "FOO%26%23xDFFF%3BZOO", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%EF%BF%BDZOO%22"],"41cdf6978b0c48e7044d5e4534fc8bb08de4cdf2":[async_test('html5lib_entities01.html 41cdf6978b0c48e7044d5e4534fc8bb08de4cdf2'), "FOO%26%23xE000%3BZOO", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%EE%80%80ZOO%22"],"5138f572a4db2e2edc2d723e1bb87af72ab501f4":[async_test('html5lib_entities01.html 5138f572a4db2e2edc2d723e1bb87af72ab501f4'), "FOO%26%23x10FFFE%3BZOO", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%F4%8F%BF%BEZOO%22"],"f30757617b6df330deba1cb607e8d47f71bda13f":[async_test('html5lib_entities01.html f30757617b6df330deba1cb607e8d47f71bda13f'), "FOO%26%23x1087D4%3BZOO", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%F4%88%9F%94ZOO%22"],"a6fd8cdca1fa8cf07519d9a0c5b779eafa438b70":[async_test('html5lib_entities01.html a6fd8cdca1fa8cf07519d9a0c5b779eafa438b70'), "FOO%26%23x10FFFF%3BZOO", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%F4%8F%BF%BFZOO%22"],"ada342466887e85d89c3b815b127bfced036ac76":[async_test('html5lib_entities01.html ada342466887e85d89c3b815b127bfced036ac76'), "FOO%26%23x110000%3BZOO", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%EF%BF%BDZOO%22"],"74bd99a9263f0b8e8a5fac4d2684fe37d5a1a9cc":[async_test('html5lib_entities01.html 74bd99a9263f0b8e8a5fac4d2684fe37d5a1a9cc'), "FOO%26%23xFFFFFF%3BZOO", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%EF%BF%BDZOO%22"],
+ }
+ init_tests(get_type());
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_entities02.html b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_entities02.html
new file mode 100644
index 00000000000..fdfddded2aa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_entities02.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf8">
+ <title>HTML 5 Parser tests html5lib_entities02.html</title>
+ <meta name="timeout" content="long">
+ <meta name="variant" content="?run_type=uri">
+ <meta name="variant" content="?run_type=write">
+ <meta name="variant" content="?run_type=write_single">
+ </head>
+ <body>
+ <h1>html5lib Parser Test</h1>
+ <div id="log"></div>
+ <script src="common.js"></script>
+ <script src="test.js"></script>
+ <script src="template.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ var num_iframes = 8;
+ var order = ['ea66863900b0b42deee5a77c58a432c2215c32ac','bc2a229b7c801ad045da76f411faf1d4c89886d0','e30755b30108f65919767f57a2200097b638f2b4','17c5acad9075755a413541d57d0d135338450834','ec40a7216b4ac918c5e16cae66bfb8b69bcfabce','54d2e9d13436e6850a5257e8028122581cf7088d','99c8496d0ea75429a5836de44dd18708974f6de8','7e4e70e57f63968ebba82682a2629158bd053a65','dca2db4f61b5fd60121e3da3e15065654f8d8a0c','fe22904d5f3936bedc1fa110e6bde48895b399a0','6553483a30141fcff05787287c2c212df9f468e8','88d7c74afcb27bbee3e3255d9116dce9c3dc6d73','db5d22d3350e0a51d675dc17c641c73251a4739d','ea08276faa7ba526e612fc1e80047d705cd29885','c59d1cfe1b36e75e0f57664e45bef7023a73c9e9','f9d3950620f8adcbe5f9a0542c7967de4be65963','8e35dacd7c296f054e58f1ce83719401c8aff8a0','48edddaa93bbebc5cd1615cc67422ca6508e47a2','9c69a29b53eebd93db20f12d405335274098e662','565c5f6744a27602bb466d6df77803a80f064752','742984a32ecd86cb9cdedffbba47eb212e19c80f','f908b529ac9ca5366e1160856db2c3d17e3898c9','1294ffc6bee2ee41f65a60ac48ba445b99504286','ba7d8cdd4b40020f7af6bdde75a3574b5771fac9','ce23051409f58749cbce6836bc4c7c21e9c548cf',];
+ var tests = {
+ "ea66863900b0b42deee5a77c58a432c2215c32ac":[async_test('html5lib_entities02.html ea66863900b0b42deee5a77c58a432c2215c32ac'), "%3Cdiv%20bar%3D%22ZZ%26gt%3BYY%22%3E%3C/div%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20bar%3D%22ZZ%3EYY%22"],"bc2a229b7c801ad045da76f411faf1d4c89886d0":[async_test('html5lib_entities02.html bc2a229b7c801ad045da76f411faf1d4c89886d0'), "%3Cdiv%20bar%3D%22ZZ%26%22%3E%3C/div%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20bar%3D%22ZZ%26%22"],"e30755b30108f65919767f57a2200097b638f2b4":[async_test('html5lib_entities02.html e30755b30108f65919767f57a2200097b638f2b4'), "%3Cdiv%20bar%3D%27ZZ%26%27%3E%3C/div%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20bar%3D%22ZZ%26%22"],"17c5acad9075755a413541d57d0d135338450834":[async_test('html5lib_entities02.html 17c5acad9075755a413541d57d0d135338450834'), "%3Cdiv%20bar%3DZZ%26%3E%3C/div%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20bar%3D%22ZZ%26%22"],"ec40a7216b4ac918c5e16cae66bfb8b69bcfabce":[async_test('html5lib_entities02.html ec40a7216b4ac918c5e16cae66bfb8b69bcfabce'), "%3Cdiv%20bar%3D%22ZZ%26gt%3DYY%22%3E%3C/div%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20bar%3D%22ZZ%26gt%3DYY%22"],"54d2e9d13436e6850a5257e8028122581cf7088d":[async_test('html5lib_entities02.html 54d2e9d13436e6850a5257e8028122581cf7088d'), "%3Cdiv%20bar%3D%22ZZ%26gt0YY%22%3E%3C/div%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20bar%3D%22ZZ%26gt0YY%22"],"99c8496d0ea75429a5836de44dd18708974f6de8":[async_test('html5lib_entities02.html 99c8496d0ea75429a5836de44dd18708974f6de8'), "%3Cdiv%20bar%3D%22ZZ%26gt9YY%22%3E%3C/div%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20bar%3D%22ZZ%26gt9YY%22"],"7e4e70e57f63968ebba82682a2629158bd053a65":[async_test('html5lib_entities02.html 7e4e70e57f63968ebba82682a2629158bd053a65'), "%3Cdiv%20bar%3D%22ZZ%26gtaYY%22%3E%3C/div%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20bar%3D%22ZZ%26gtaYY%22"],"dca2db4f61b5fd60121e3da3e15065654f8d8a0c":[async_test('html5lib_entities02.html dca2db4f61b5fd60121e3da3e15065654f8d8a0c'), "%3Cdiv%20bar%3D%22ZZ%26gtZYY%22%3E%3C/div%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20bar%3D%22ZZ%26gtZYY%22"],"fe22904d5f3936bedc1fa110e6bde48895b399a0":[async_test('html5lib_entities02.html fe22904d5f3936bedc1fa110e6bde48895b399a0'), "%3Cdiv%20bar%3D%22ZZ%26gt%20YY%22%3E%3C/div%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20bar%3D%22ZZ%3E%20YY%22"],"6553483a30141fcff05787287c2c212df9f468e8":[async_test('html5lib_entities02.html 6553483a30141fcff05787287c2c212df9f468e8'), "%3Cdiv%20bar%3D%22ZZ%26gt%22%3E%3C/div%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20bar%3D%22ZZ%3E%22"],"88d7c74afcb27bbee3e3255d9116dce9c3dc6d73":[async_test('html5lib_entities02.html 88d7c74afcb27bbee3e3255d9116dce9c3dc6d73'), "%3Cdiv%20bar%3D%27ZZ%26gt%27%3E%3C/div%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20bar%3D%22ZZ%3E%22"],"db5d22d3350e0a51d675dc17c641c73251a4739d":[async_test('html5lib_entities02.html db5d22d3350e0a51d675dc17c641c73251a4739d'), "%3Cdiv%20bar%3DZZ%26gt%3E%3C/div%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20bar%3D%22ZZ%3E%22"],"ea08276faa7ba526e612fc1e80047d705cd29885":[async_test('html5lib_entities02.html ea08276faa7ba526e612fc1e80047d705cd29885'), "%3Cdiv%20bar%3D%22ZZ%26pound_id%3D23%22%3E%3C/div%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20bar%3D%22ZZ%C2%A3_id%3D23%22"],"c59d1cfe1b36e75e0f57664e45bef7023a73c9e9":[async_test('html5lib_entities02.html c59d1cfe1b36e75e0f57664e45bef7023a73c9e9'), "%3Cdiv%20bar%3D%22ZZ%26prod_id%3D23%22%3E%3C/div%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20bar%3D%22ZZ%26prod_id%3D23%22"],"f9d3950620f8adcbe5f9a0542c7967de4be65963":[async_test('html5lib_entities02.html f9d3950620f8adcbe5f9a0542c7967de4be65963'), "%3Cdiv%20bar%3D%22ZZ%26pound%3B_id%3D23%22%3E%3C/div%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20bar%3D%22ZZ%C2%A3_id%3D23%22"],"8e35dacd7c296f054e58f1ce83719401c8aff8a0":[async_test('html5lib_entities02.html 8e35dacd7c296f054e58f1ce83719401c8aff8a0'), "%3Cdiv%20bar%3D%22ZZ%26prod%3B_id%3D23%22%3E%3C/div%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20bar%3D%22ZZ%E2%88%8F_id%3D23%22"],"48edddaa93bbebc5cd1615cc67422ca6508e47a2":[async_test('html5lib_entities02.html 48edddaa93bbebc5cd1615cc67422ca6508e47a2'), "%3Cdiv%20bar%3D%22ZZ%26pound%3D23%22%3E%3C/div%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20bar%3D%22ZZ%26pound%3D23%22"],"9c69a29b53eebd93db20f12d405335274098e662":[async_test('html5lib_entities02.html 9c69a29b53eebd93db20f12d405335274098e662'), "%3Cdiv%20bar%3D%22ZZ%26prod%3D23%22%3E%3C/div%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20bar%3D%22ZZ%26prod%3D23%22"],"565c5f6744a27602bb466d6df77803a80f064752":[async_test('html5lib_entities02.html 565c5f6744a27602bb466d6df77803a80f064752'), "%3Cdiv%3EZZ%26pound_id%3D23%3C/div%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%22ZZ%C2%A3_id%3D23%22"],"742984a32ecd86cb9cdedffbba47eb212e19c80f":[async_test('html5lib_entities02.html 742984a32ecd86cb9cdedffbba47eb212e19c80f'), "%3Cdiv%3EZZ%26prod_id%3D23%3C/div%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%22ZZ%26prod_id%3D23%22"],"f908b529ac9ca5366e1160856db2c3d17e3898c9":[async_test('html5lib_entities02.html f908b529ac9ca5366e1160856db2c3d17e3898c9'), "%3Cdiv%3EZZ%26pound%3B_id%3D23%3C/div%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%22ZZ%C2%A3_id%3D23%22"],"1294ffc6bee2ee41f65a60ac48ba445b99504286":[async_test('html5lib_entities02.html 1294ffc6bee2ee41f65a60ac48ba445b99504286'), "%3Cdiv%3EZZ%26prod%3B_id%3D23%3C/div%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%22ZZ%E2%88%8F_id%3D23%22"],"ba7d8cdd4b40020f7af6bdde75a3574b5771fac9":[async_test('html5lib_entities02.html ba7d8cdd4b40020f7af6bdde75a3574b5771fac9'), "%3Cdiv%3EZZ%26pound%3D23%3C/div%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%22ZZ%C2%A3%3D23%22"],"ce23051409f58749cbce6836bc4c7c21e9c548cf":[async_test('html5lib_entities02.html ce23051409f58749cbce6836bc4c7c21e9c548cf'), "%3Cdiv%3EZZ%26prod%3D23%3C/div%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%22ZZ%26prod%3D23%22"],
+ }
+ init_tests(get_type());
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_html5test-com.html b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_html5test-com.html
new file mode 100644
index 00000000000..b74b7f99934
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_html5test-com.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf8">
+ <title>HTML 5 Parser tests html5lib_html5test-com.html</title>
+ <meta name="timeout" content="long">
+ <meta name="variant" content="?run_type=uri">
+ <meta name="variant" content="?run_type=write">
+ <meta name="variant" content="?run_type=write_single">
+ </head>
+ <body>
+ <h1>html5lib Parser Test</h1>
+ <div id="log"></div>
+ <script src="common.js"></script>
+ <script src="test.js"></script>
+ <script src="template.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ var num_iframes = 8;
+ var order = ['71bd5e6b9e907e65295b6d670627e0da4a8a65ed','32cd504d36a6db3584b716b3681ab4b0741423b3','f0bf0506a2d3e5ca4aa5f14a1f260e405882827e','666a215d91c4e83d99f4be4caebb67fd65569480','fd2cd459bdc79db754b24bc537758990d392b1fc','86be28614bf72e24c162d865c04d687447098867','be72b058e5be0f6aef2c442d83c92c0d251fcb7f','ab6e31cf52c8d57d6dfdcaf7165f1abf7bd5e73d','11240d9b03b14eb515d6a1d1595c5a409830ea38','809c1bebcded8f43981af902442ff8a2db5d2578','bcbeb84f40e56a642b794d514e97e3ec303d4a79','1cbb987dd0a35af3a5b2e4fc11eba36a60eba03d','5b5e75eca2f5c80e1c4d5676254b9891090e288e','93e966e2edad3297ecb159f3983bdd2dc84f829e','7a02a2d7ab875dbeedc9a34c6c27b6119bd6d1f0','46615acdb9dd6231e2a65fed5bcce7e19f086d03','381de12234a699cbfb775b3ca7c679f357e7403e','72736fc894b2077928559cc4284a102635cac898','290d5e7fa9684038411e78c4b0e0ade83150eeea','a5fb9cf46ed215a61d073ae4b7e7477ba49fa5d8','88dea19243733a9bda26c6f5290d2c4f5bbac157','9906bb30ae08654f4c67bf6d97040abbca91082d','c6cd25ce02329e4a42b9be9ba35453532fec7599','81af3f9d6ccc2a1a1a58ace18dd530c544675610',];
+ var tests = {
+ "71bd5e6b9e907e65295b6d670627e0da4a8a65ed":[async_test('html5lib_html5test-com.html 71bd5e6b9e907e65295b6d670627e0da4a8a65ed'), "%3Cdiv%3Cdiv%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3Cdiv%3E"],"32cd504d36a6db3584b716b3681ab4b0741423b3":[async_test('html5lib_html5test-com.html 32cd504d36a6db3584b716b3681ab4b0741423b3'), "%3Cdiv%20foo%3Cbar%3D%27%27%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20foo%3Cbar%3D%22%22"],"f0bf0506a2d3e5ca4aa5f14a1f260e405882827e":[async_test('html5lib_html5test-com.html f0bf0506a2d3e5ca4aa5f14a1f260e405882827e'), "%3Cdiv%20foo%3D%60bar%60%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20foo%3D%22%60bar%60%22"],"666a215d91c4e83d99f4be4caebb67fd65569480":[async_test('html5lib_html5test-com.html 666a215d91c4e83d99f4be4caebb67fd65569480'), "%3Cdiv%20%5C%22foo%3D%27%27%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%5C%22foo%3D%22%22"],"fd2cd459bdc79db754b24bc537758990d392b1fc":[async_test('html5lib_html5test-com.html fd2cd459bdc79db754b24bc537758990d392b1fc'), "%3Ca%20href%3D%27%5Cnbar%27%3E%3C/a%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20href%3D%22%5Cnbar%22"],"86be28614bf72e24c162d865c04d687447098867":[async_test('html5lib_html5test-com.html 86be28614bf72e24c162d865c04d687447098867'), "%3C%21DOCTYPE%20html%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"be72b058e5be0f6aef2c442d83c92c0d251fcb7f":[async_test('html5lib_html5test-com.html be72b058e5be0f6aef2c442d83c92c0d251fcb7f'), "%26lang%3B%26rang%3B", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22%E2%9F%A8%E2%9F%A9%22"],"ab6e31cf52c8d57d6dfdcaf7165f1abf7bd5e73d":[async_test('html5lib_html5test-com.html ab6e31cf52c8d57d6dfdcaf7165f1abf7bd5e73d'), "%26apos%3B", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22%27%22"],"11240d9b03b14eb515d6a1d1595c5a409830ea38":[async_test('html5lib_html5test-com.html 11240d9b03b14eb515d6a1d1595c5a409830ea38'), "%26ImaginaryI%3B", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22%E2%85%88%22"],"809c1bebcded8f43981af902442ff8a2db5d2578":[async_test('html5lib_html5test-com.html 809c1bebcded8f43981af902442ff8a2db5d2578'), "%26Kopf%3B", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22%F0%9D%95%82%22"],"bcbeb84f40e56a642b794d514e97e3ec303d4a79":[async_test('html5lib_html5test-com.html bcbeb84f40e56a642b794d514e97e3ec303d4a79'), "%26notinva%3B", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22%E2%88%89%22"],"1cbb987dd0a35af3a5b2e4fc11eba36a60eba03d":[async_test('html5lib_html5test-com.html 1cbb987dd0a35af3a5b2e4fc11eba36a60eba03d'), "%3C%3Fimport%20namespace%3D%22foo%22%20implementation%3D%22%23bar%22%3E", "%23document%0A%7C%20%3C%21--%20%3Fimport%20namespace%3D%22foo%22%20implementation%3D%22%23bar%22%20--%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"5b5e75eca2f5c80e1c4d5676254b9891090e288e":[async_test('html5lib_html5test-com.html 5b5e75eca2f5c80e1c4d5676254b9891090e288e'), "%3C%21--foo--bar--%3E", "%23document%0A%7C%20%3C%21--%20foo--bar%20--%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"93e966e2edad3297ecb159f3983bdd2dc84f829e":[async_test('html5lib_html5test-com.html 93e966e2edad3297ecb159f3983bdd2dc84f829e'), "%3C%21%5BCDATA%5Bx%5D%5D%3E", "%23document%0A%7C%20%3C%21--%20%5BCDATA%5Bx%5D%5D%20--%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"7a02a2d7ab875dbeedc9a34c6c27b6119bd6d1f0":[async_test('html5lib_html5test-com.html 7a02a2d7ab875dbeedc9a34c6c27b6119bd6d1f0'), "%3Ctextarea%3E%3C%21--%3C/textarea%3E--%3E%3C/textarea%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctextarea%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%22%0A%7C%20%20%20%20%20%22--%3E%22"],"46615acdb9dd6231e2a65fed5bcce7e19f086d03":[async_test('html5lib_html5test-com.html 46615acdb9dd6231e2a65fed5bcce7e19f086d03'), "%3Ctextarea%3E%3C%21--%3C/textarea%3E--%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctextarea%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%22%0A%7C%20%20%20%20%20%22--%3E%22"],"381de12234a699cbfb775b3ca7c679f357e7403e":[async_test('html5lib_html5test-com.html 381de12234a699cbfb775b3ca7c679f357e7403e'), "%3Cstyle%3E%3C%21--%3C/style%3E--%3E%3C/style%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cstyle%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%22%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22--%3E%22"],"72736fc894b2077928559cc4284a102635cac898":[async_test('html5lib_html5test-com.html 72736fc894b2077928559cc4284a102635cac898'), "%3Cstyle%3E%3C%21--%3C/style%3E--%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cstyle%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%22%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22--%3E%22"],"290d5e7fa9684038411e78c4b0e0ade83150eeea":[async_test('html5lib_html5test-com.html 290d5e7fa9684038411e78c4b0e0ade83150eeea'), "%3Cul%3E%3Cli%3EA%20%3C/li%3E%20%3Cli%3EB%3C/li%3E%3C/ul%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cul%3E%0A%7C%20%20%20%20%20%20%20%3Cli%3E%0A%7C%20%20%20%20%20%20%20%20%20%22A%20%22%0A%7C%20%20%20%20%20%20%20%22%20%22%0A%7C%20%20%20%20%20%20%20%3Cli%3E%0A%7C%20%20%20%20%20%20%20%20%20%22B%22"],"a5fb9cf46ed215a61d073ae4b7e7477ba49fa5d8":[async_test('html5lib_html5test-com.html a5fb9cf46ed215a61d073ae4b7e7477ba49fa5d8'), "%3Ctable%3E%3Cform%3E%3Cinput%20type%3Dhidden%3E%3Cinput%3E%3C/form%3E%3Cdiv%3E%3C/div%3E%3C/table%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cinput%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Cform%3E%0A%7C%20%20%20%20%20%20%20%3Cinput%3E%0A%7C%20%20%20%20%20%20%20%20%20type%3D%22hidden%22"],"88dea19243733a9bda26c6f5290d2c4f5bbac157":[async_test('html5lib_html5test-com.html 88dea19243733a9bda26c6f5290d2c4f5bbac157'), "%3Ci%3EA%3Cb%3EB%3Cp%3E%3C/i%3EC%3C/b%3ED", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%22A%22%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%22B%22%0A%7C%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%22C%22%0A%7C%20%20%20%20%20%20%20%22D%22"],"9906bb30ae08654f4c67bf6d97040abbca91082d":[async_test('html5lib_html5test-com.html 9906bb30ae08654f4c67bf6d97040abbca91082d'), "%3Cdiv%3E%3C/div%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E"],"c6cd25ce02329e4a42b9be9ba35453532fec7599":[async_test('html5lib_html5test-com.html c6cd25ce02329e4a42b9be9ba35453532fec7599'), "%3Csvg%3E%3C/svg%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E"],"81af3f9d6ccc2a1a1a58ace18dd530c544675610":[async_test('html5lib_html5test-com.html 81af3f9d6ccc2a1a1a58ace18dd530c544675610'), "%3Cmath%3E%3C/math%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cmath%20math%3E"],
+ }
+ init_tests(get_type());
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_inbody01.html b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_inbody01.html
new file mode 100644
index 00000000000..43064d43f1d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_inbody01.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf8">
+ <title>HTML 5 Parser tests html5lib_inbody01.html</title>
+ <meta name="timeout" content="long">
+ <meta name="variant" content="?run_type=uri">
+ <meta name="variant" content="?run_type=write">
+ <meta name="variant" content="?run_type=write_single">
+ </head>
+ <body>
+ <h1>html5lib Parser Test</h1>
+ <div id="log"></div>
+ <script src="common.js"></script>
+ <script src="test.js"></script>
+ <script src="template.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ var num_iframes = 8;
+ var order = ['3e20aae3cbc7f10b28cbfc1e20b2949708872a3c','ec6b9d9dccaa3494a317afac0edfcc485b959663','cc4923612d10b2115cd03e269080ddf5463d95ae','a5ebf8808e479239966038951d5383ed65ff4eb6',];
+ var tests = {
+ "3e20aae3cbc7f10b28cbfc1e20b2949708872a3c":[async_test('html5lib_inbody01.html 3e20aae3cbc7f10b28cbfc1e20b2949708872a3c'), "%3Cbutton%3E1%3C/foo%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cbutton%3E%0A%7C%20%20%20%20%20%20%20%221%22"],"ec6b9d9dccaa3494a317afac0edfcc485b959663":[async_test('html5lib_inbody01.html ec6b9d9dccaa3494a317afac0edfcc485b959663'), "%3Cfoo%3E1%3Cp%3E2%3C/foo%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cfoo%3E%0A%7C%20%20%20%20%20%20%20%221%22%0A%7C%20%20%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%20%20%222%22"],"cc4923612d10b2115cd03e269080ddf5463d95ae":[async_test('html5lib_inbody01.html cc4923612d10b2115cd03e269080ddf5463d95ae'), "%3Cdd%3E1%3C/foo%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdd%3E%0A%7C%20%20%20%20%20%20%20%221%22"],"a5ebf8808e479239966038951d5383ed65ff4eb6":[async_test('html5lib_inbody01.html a5ebf8808e479239966038951d5383ed65ff4eb6'), "%3Cfoo%3E1%3Cdd%3E2%3C/foo%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cfoo%3E%0A%7C%20%20%20%20%20%20%20%221%22%0A%7C%20%20%20%20%20%20%20%3Cdd%3E%0A%7C%20%20%20%20%20%20%20%20%20%222%22"],
+ }
+ init_tests(get_type());
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_innerHTML_tests4.html b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_innerHTML_tests4.html
new file mode 100644
index 00000000000..9394df7f1f2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_innerHTML_tests4.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf8">
+ <title>HTML 5 Parser tests html5lib_innerHTML_tests4.html</title>
+ <meta name="timeout" content="long">
+ </head>
+ <body>
+ <h1>html5lib Parser Test</h1>
+ <div id="log"></div>
+ <script src="common.js"></script>
+ <script src="test.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ var num_iframes = 8;
+ var order = ['8c692a23f8c9b5860cf06fb334041d2e97e96f5c','95cb768746a1ca7ac02d39c0bb2b10d9e965e37c','06bd3583493359d112d19765f68fac3901267408','48d8375ef2d9d73bd133f2947858a3450a988d53','36fb2178fbdfa1b32701a9d9214c3fd115fd7184','d373bc3abdda01b17a6055af21b16c151dd1d697','4f91b1d4c6e2bbc0595c9effc490b7357e9cefc2',];
+ var tests = {
+ "8c692a23f8c9b5860cf06fb334041d2e97e96f5c":[async_test('html5lib_innerHTML_tests4.html 8c692a23f8c9b5860cf06fb334041d2e97e96f5c'), "direct%20div%20content", "%23document%0A%7C%20%22direct%20div%20content%22", 'div'],"95cb768746a1ca7ac02d39c0bb2b10d9e965e37c":[async_test('html5lib_innerHTML_tests4.html 95cb768746a1ca7ac02d39c0bb2b10d9e965e37c'), "direct%20textarea%20content", "%23document%0A%7C%20%22direct%20textarea%20content%22", 'textarea'],"06bd3583493359d112d19765f68fac3901267408":[async_test('html5lib_innerHTML_tests4.html 06bd3583493359d112d19765f68fac3901267408'), "textarea%20content%20with%20%3Cem%3Epseudo%3C/em%3E%20%3Cfoo%3Emarkup", "%23document%0A%7C%20%22textarea%20content%20with%20%3Cem%3Epseudo%3C/em%3E%20%3Cfoo%3Emarkup%22", 'textarea'],"48d8375ef2d9d73bd133f2947858a3450a988d53":[async_test('html5lib_innerHTML_tests4.html 48d8375ef2d9d73bd133f2947858a3450a988d53'), "this%20is%20%26%23x0043%3BDATA%20inside%20a%20%3Cstyle%3E%20element", "%23document%0A%7C%20%22this%20is%20%26%23x0043%3BDATA%20inside%20a%20%3Cstyle%3E%20element%22", 'style'],"36fb2178fbdfa1b32701a9d9214c3fd115fd7184":[async_test('html5lib_innerHTML_tests4.html 36fb2178fbdfa1b32701a9d9214c3fd115fd7184'), "%3C/plaintext%3E", "%23document%0A%7C%20%22%3C/plaintext%3E%22", 'plaintext'],"d373bc3abdda01b17a6055af21b16c151dd1d697":[async_test('html5lib_innerHTML_tests4.html d373bc3abdda01b17a6055af21b16c151dd1d697'), "setting%20html%27s%20innerHTML", "%23document%0A%7C%20%3Chead%3E%0A%7C%20%3Cbody%3E%0A%7C%20%20%20%22setting%20html%27s%20innerHTML%22", 'html'],"4f91b1d4c6e2bbc0595c9effc490b7357e9cefc2":[async_test('html5lib_innerHTML_tests4.html 4f91b1d4c6e2bbc0595c9effc490b7357e9cefc2'), "%3Ctitle%3Esetting%20head%27s%20innerHTML%3C/title%3E", "%23document%0A%7C%20%3Ctitle%3E%0A%7C%20%20%20%22setting%20head%27s%20innerHTML%22", 'head'],
+ }
+ init_tests("innerHTML");
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_innerHTML_tests6.html b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_innerHTML_tests6.html
new file mode 100644
index 00000000000..7b7669e2fa8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_innerHTML_tests6.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf8">
+ <title>HTML 5 Parser tests html5lib_innerHTML_tests6.html</title>
+ <meta name="timeout" content="long">
+ </head>
+ <body>
+ <h1>html5lib Parser Test</h1>
+ <div id="log"></div>
+ <script src="common.js"></script>
+ <script src="test.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ var num_iframes = 8;
+ var order = ['ccb245e2f1d9fe1580235854daa1a124525aca61','ed2b0f8fe477e3a6a0d9052b46bd94e628fb666a','ed4acc4544b7ee83072a3c2ae078e3cbaf8303fb','28f111cdfb84bfa4a70b57e3aeec1f0aa13337de','616bd17e481973f9fe286aa30727ee22850fc31e','1cfb3baf2ad29109ddd5581daa3a009029c71491','98ba377bacd2ec343919bdc589116eabf94402d5','7cf2db8c65b79da98e39b13772ed0440ff177fd7','cb78efe1d4f4279be6c0a363cce643b3591efdc5','82911b0551c00e9971dd1491f8f2d2782aa3ac63','a3ff1f1809e8018b725620f1d04b6ebb24fda9a4','e35e330f7eb5bb27df1fe702843747e104a193be','c1dc3add1fcb1f506ea395691a710eb8e727b123',];
+ var tests = {
+ "ccb245e2f1d9fe1580235854daa1a124525aca61":[async_test('html5lib_innerHTML_tests6.html ccb245e2f1d9fe1580235854daa1a124525aca61'), "%3Cbody%3E%0A%3Cdiv%3E", "%23document%0A%7C%20%22%0A%22%0A%7C%20%3Cdiv%3E", 'div'],"ed2b0f8fe477e3a6a0d9052b46bd94e628fb666a":[async_test('html5lib_innerHTML_tests6.html ed2b0f8fe477e3a6a0d9052b46bd94e628fb666a'), "%3C/caption%3E%3Cdiv%3E", "%23document%0A%7C%20%3Cdiv%3E", 'caption'],"ed4acc4544b7ee83072a3c2ae078e3cbaf8303fb":[async_test('html5lib_innerHTML_tests6.html ed4acc4544b7ee83072a3c2ae078e3cbaf8303fb'), "%3C/table%3E%3Cdiv%3E", "%23document%0A%7C%20%3Cdiv%3E", 'caption'],"28f111cdfb84bfa4a70b57e3aeec1f0aa13337de":[async_test('html5lib_innerHTML_tests6.html 28f111cdfb84bfa4a70b57e3aeec1f0aa13337de'), "%3C/table%3E%3C/tbody%3E%3C/tfoot%3E%3C/thead%3E%3C/tr%3E%3Cdiv%3E", "%23document%0A%7C%20%3Cdiv%3E", 'td'],"616bd17e481973f9fe286aa30727ee22850fc31e":[async_test('html5lib_innerHTML_tests6.html 616bd17e481973f9fe286aa30727ee22850fc31e'), "foo%3Ccol%3E", "%23document%0A%7C%20%3Ccol%3E", 'colgroup'],"1cfb3baf2ad29109ddd5581daa3a009029c71491":[async_test('html5lib_innerHTML_tests6.html 1cfb3baf2ad29109ddd5581daa3a009029c71491'), "%3C/frameset%3E%3Cframe%3E", "%23document%0A%7C%20%3Cframe%3E", 'frameset'],"98ba377bacd2ec343919bdc589116eabf94402d5":[async_test('html5lib_innerHTML_tests6.html 98ba377bacd2ec343919bdc589116eabf94402d5'), "%3C/body%3E%3Cdiv%3E", "%23document%0A%7C%20%3Cdiv%3E", 'body'],"7cf2db8c65b79da98e39b13772ed0440ff177fd7":[async_test('html5lib_innerHTML_tests6.html 7cf2db8c65b79da98e39b13772ed0440ff177fd7'), "%3C/tr%3E%3Ctd%3E", "%23document%0A%7C%20%3Ctd%3E", 'tr'],"cb78efe1d4f4279be6c0a363cce643b3591efdc5":[async_test('html5lib_innerHTML_tests6.html cb78efe1d4f4279be6c0a363cce643b3591efdc5'), "%3C/tbody%3E%3C/tfoot%3E%3C/thead%3E%3Ctd%3E", "%23document%0A%7C%20%3Ctd%3E", 'tr'],"82911b0551c00e9971dd1491f8f2d2782aa3ac63":[async_test('html5lib_innerHTML_tests6.html 82911b0551c00e9971dd1491f8f2d2782aa3ac63'), "%3Ccaption%3E%3Ccol%3E%3Ccolgroup%3E%3Ctbody%3E%3Ctfoot%3E%3Cthead%3E%3Ctr%3E", "%23document%0A%7C%20%3Ctr%3E", 'tbody'],"a3ff1f1809e8018b725620f1d04b6ebb24fda9a4":[async_test('html5lib_innerHTML_tests6.html a3ff1f1809e8018b725620f1d04b6ebb24fda9a4'), "%3C/table%3E%3Ctr%3E", "%23document%0A%7C%20%3Ctr%3E", 'tbody'],"e35e330f7eb5bb27df1fe702843747e104a193be":[async_test('html5lib_innerHTML_tests6.html e35e330f7eb5bb27df1fe702843747e104a193be'), "%3C/table%3E%3Ctr%3E", "%23document%0A%7C%20%3Ctbody%3E%0A%7C%20%20%20%3Ctr%3E", 'table'],"c1dc3add1fcb1f506ea395691a710eb8e727b123":[async_test('html5lib_innerHTML_tests6.html c1dc3add1fcb1f506ea395691a710eb8e727b123'), "%3Cbody%3E%3C/body%3E%3C/html%3E", "%23document%0A%7C%20%3Chead%3E%0A%7C%20%3Cbody%3E", 'html'],
+ }
+ init_tests("innerHTML");
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_innerHTML_tests7.html b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_innerHTML_tests7.html
new file mode 100644
index 00000000000..cc775229791
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_innerHTML_tests7.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf8">
+ <title>HTML 5 Parser tests html5lib_innerHTML_tests7.html</title>
+ <meta name="timeout" content="long">
+ </head>
+ <body>
+ <h1>html5lib Parser Test</h1>
+ <div id="log"></div>
+ <script src="common.js"></script>
+ <script src="test.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ var num_iframes = 8;
+ var order = ['7aabda442dc7b37110c3d03b1465fa893dc25625',];
+ var tests = {
+ "7aabda442dc7b37110c3d03b1465fa893dc25625":[async_test('html5lib_innerHTML_tests7.html 7aabda442dc7b37110c3d03b1465fa893dc25625'), "%3Cbody%3EX%3C/body%3E%3C/body%3E", "%23document%0A%7C%20%3Chead%3E%0A%7C%20%3Cbody%3E%0A%7C%20%20%20%22X%22", 'html'],
+ }
+ init_tests("innerHTML");
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_innerHTML_tests_innerHTML_1.html b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_innerHTML_tests_innerHTML_1.html
new file mode 100644
index 00000000000..29df3868a3f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_innerHTML_tests_innerHTML_1.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf8">
+ <title>HTML 5 Parser tests html5lib_innerHTML_tests_innerHTML_1.html</title>
+ <meta name="timeout" content="long">
+ </head>
+ <body>
+ <h1>html5lib Parser Test</h1>
+ <div id="log"></div>
+ <script src="common.js"></script>
+ <script src="test.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ var num_iframes = 8;
+ var order = ['7a9e287595dd570e0f19b7eec0ac424228908daf','6f766fa07c8697a5379c5542adbba2a42f913004','dbbe75ae41228f9264d56a018e620217ec87fd32','32e2fea7531c0c910ac73b35665b2f8bca47a049','7fc9ad33d4bc6af760883f0581cf869f96473f2e','8883d04b33c7e718b0d201a5f0bf5aa6d98754e6','347f73ada7ab974a081c65385444cca0b6a2d446','25a03753c27ab46891e2c59665215e4657ca7177','75e9c86aff595da8999673fce99bc12741552c4e','e35e330f7eb5bb27df1fe702843747e104a193be','b55e32e22980fe99bab895005a0a757a2fcb1a2b','ce6fc19319d2568fec9084d8d4d1cc10f20b8565','b600f8c7df58e42342feff051778923dbf7616af','6056619333f1a780052612e1dda18112147f67fa','d9300c4d8d36e950490bbe5800c1a3ba4e744e2a','411ebe3bea1d0508263ec17618492feaa9ca99d7','6c7c85721f823ab889bcb9e035341a1fb6d6eeee','973d06969d7968d200d5639ce06f7209655b1e26','dfb6ec1e412a6634b497151f222f4272721ae57e','4916096ab7dbdd051dc96de7952ec60674d617a3','58277507de4ce0df9b4eb03262e4cb04d2fcc7af','8e5727f170507ba6b86c1c3bdb3a5201d3480b33','61eb343f71030688ab1a26bb980b9e4409993e3d','3548939a56a148b59781c5f930036c1528db1545','0b88a12102fba0634b44ac9f157544faeca68df6','c300553f45f4ad6e5e1da9d884fafb95f36ab05a','00a7ed4082183eba76af197418305b2d196ec7e6','5dfd84382f85ff8343a62d6bb5028996111e5017','9b1a1cd33bb3f26ec3f969f3158edf5c2db47052','8ab89f758b96bf994a21d8283d27e8ae9804b924','25add8314f59cdc264d7779f36ae4dffd1f9ad29','7104e981f6018b18766fd95109bfbffeb878cc56','28fbaa710ce3f440a56fdf909c4b8bc223a1b965','3380b0143f3d1e2edb216d388acd72702e141165','a630fb272be6de118b728a28d6ce71b296a75694','5adf8b7bd3d63a77ea1dbe6deb6741c5b92de6cd','4e0312ac349a70d07f2bb1ae154740e46e8c9a6e','987061379d2542e88d8a72ce6f0169a211d3ac41','e0798aa003863ba2be750d3e6c2e6766fea11279','586ed8e0d1395198f43ee68843d654a49169f379','8896feedef576c1ed768a4eb67f57c3dc5242fed','89f4f0f289a23d1ebfbf499c2ecd24cd35fc10b4','2c07361470533b905a7ff9a685439cad2fe35549','a36f27cbe53991c647055c95bfa250a0ab734b0d','ac28c352ae8453434e3aefb24e798a9580c1b230','f8770f97671a805b37277db7e42536b40c0804cb','469a071b520d8436e6a0f6da6f9385f5ebd8e2f8','7cf2db8c65b79da98e39b13772ed0440ff177fd7','3940fdb54783cb3c42138670a17d28e77e29e900','3b5ab5fbb3585d7215a5766f1e2377b7929b5cc6','7c4a40203d5830d36432b0f30a09cebea6e9d2e4','e6d930d4239666fdc6c0722106bd2b115b4d3fd3','c8817b3b55a437bd153e978fc5f49fbe10bb56e2','2a302c14f1983aaad9fd7abe49336d9561ed82e9','28cfddd5b5875f7044b0859ba4ce88175fcbf07e','887596c50809eeb809ad24d86c239130a42f5a46','fa3797a2d2baeb8b8b2de81f1e7f33725e6b2aad','dc0e2582ff83e60c0eb549dc3387562d3482e364','4ea02fd705291eb2d14274ebeaa0117ba2b9b306','52cc77eac9488a8bb1a2c8c695f16f8919c52044','c53ab7d84ae27de9f0937521c74eec2fd6c1b1ec','d8747a49503f3486155d77dd366e0ee8ad9512a6','03e71832c254852f206f6f0ae6f4d161a276a699','92786cfafa890c23f200dccea089ca52233ef395','11d284c2b1e2f87d28dd06b938518361fe834855','bf6aebcd54d5dead9e6d56c77b41f01ea666d8b1','4d448a4239cb4c465a21c04997d656e51fdd388f','1e8faedc427045d59305218c1aba2f545c4eb4b7','6762997c1a93b1ec65722498f3fd00f0d8129369','a162461c18d9b09734f6fe5d362b84edb4eed31f','0befc335ffd6cace344d94a35de96af22b1313a5','a23b70f1f246ba08d13b570319391b4a5c3e9456','9d5e0c25bfe921df9ea2897c027f42bc88950e69','9210d577d6deecf5ab3505af86c501c5befa0b50','c34af491c0a339db6ba63fcc478108533347319b','2c4284e6b2bb480daa50bca43bcbe29cfcdeeab4','d75277b65d0118463afeb66b478509d4e27565ab','b354df69dbe9b3ef0c42177648e3aace114cf8ea','fd3be386292ea1f411cea8e86e29595deb177d28','1cfb3baf2ad29109ddd5581daa3a009029c71491','2555d238e04f3d2853cfbc5f6dd366f82cf0e868',];
+ var tests = {
+ "7a9e287595dd570e0f19b7eec0ac424228908daf":[async_test('html5lib_innerHTML_tests_innerHTML_1.html 7a9e287595dd570e0f19b7eec0ac424228908daf'), "%3Cbody%3E%3Cspan%3E", "%23document%0A%7C%20%3Cspan%3E", 'body'],"6f766fa07c8697a5379c5542adbba2a42f913004":[async_test('html5lib_innerHTML_tests_innerHTML_1.html 6f766fa07c8697a5379c5542adbba2a42f913004'), "%3Cspan%3E%3Cbody%3E", "%23document%0A%7C%20%3Cspan%3E", 'body'],"dbbe75ae41228f9264d56a018e620217ec87fd32":[async_test('html5lib_innerHTML_tests_innerHTML_1.html dbbe75ae41228f9264d56a018e620217ec87fd32'), "%3Cspan%3E%3Cbody%3E", "%23document%0A%7C%20%3Cspan%3E", 'div'],"32e2fea7531c0c910ac73b35665b2f8bca47a049":[async_test('html5lib_innerHTML_tests_innerHTML_1.html 32e2fea7531c0c910ac73b35665b2f8bca47a049'), "%3Cbody%3E%3Cspan%3E", "%23document%0A%7C%20%3Chead%3E%0A%7C%20%3Cbody%3E%0A%7C%20%20%20%3Cspan%3E", 'html'],"7fc9ad33d4bc6af760883f0581cf869f96473f2e":[async_test('html5lib_innerHTML_tests_innerHTML_1.html 7fc9ad33d4bc6af760883f0581cf869f96473f2e'), "%3Cframeset%3E%3Cspan%3E", "%23document%0A%7C%20%3Cspan%3E", 'body'],"8883d04b33c7e718b0d201a5f0bf5aa6d98754e6":[async_test('html5lib_innerHTML_tests_innerHTML_1.html 8883d04b33c7e718b0d201a5f0bf5aa6d98754e6'), "%3Cspan%3E%3Cframeset%3E", "%23document%0A%7C%20%3Cspan%3E", 'body'],"347f73ada7ab974a081c65385444cca0b6a2d446":[async_test('html5lib_innerHTML_tests_innerHTML_1.html 347f73ada7ab974a081c65385444cca0b6a2d446'), "%3Cspan%3E%3Cframeset%3E", "%23document%0A%7C%20%3Cspan%3E", 'div'],"25a03753c27ab46891e2c59665215e4657ca7177":[async_test('html5lib_innerHTML_tests_innerHTML_1.html 25a03753c27ab46891e2c59665215e4657ca7177'), "%3Cframeset%3E%3Cspan%3E", "%23document%0A%7C%20%3Chead%3E%0A%7C%20%3Cframeset%3E", 'html'],"75e9c86aff595da8999673fce99bc12741552c4e":[async_test('html5lib_innerHTML_tests_innerHTML_1.html 75e9c86aff595da8999673fce99bc12741552c4e'), "%3Ctable%3E%3Ctr%3E", "%23document%0A%7C%20%3Ctbody%3E%0A%7C%20%20%20%3Ctr%3E", 'table'],"e35e330f7eb5bb27df1fe702843747e104a193be":[async_test('html5lib_innerHTML_tests_innerHTML_1.html e35e330f7eb5bb27df1fe702843747e104a193be'), "%3C/table%3E%3Ctr%3E", "%23document%0A%7C%20%3Ctbody%3E%0A%7C%20%20%20%3Ctr%3E", 'table'],"b55e32e22980fe99bab895005a0a757a2fcb1a2b":[async_test('html5lib_innerHTML_tests_innerHTML_1.html b55e32e22980fe99bab895005a0a757a2fcb1a2b'), "%3Ca%3E", "%23document%0A%7C%20%3Ca%3E", 'table'],"ce6fc19319d2568fec9084d8d4d1cc10f20b8565":[async_test('html5lib_innerHTML_tests_innerHTML_1.html ce6fc19319d2568fec9084d8d4d1cc10f20b8565'), "%3Ca%3E%3Ccaption%3Ea", "%23document%0A%7C%20%3Ca%3E%0A%7C%20%3Ccaption%3E%0A%7C%20%20%20%22a%22", 'table'],"b600f8c7df58e42342feff051778923dbf7616af":[async_test('html5lib_innerHTML_tests_innerHTML_1.html b600f8c7df58e42342feff051778923dbf7616af'), "%3Ca%3E%3Ccolgroup%3E%3Ccol%3E", "%23document%0A%7C%20%3Ca%3E%0A%7C%20%3Ccolgroup%3E%0A%7C%20%20%20%3Ccol%3E", 'table'],"6056619333f1a780052612e1dda18112147f67fa":[async_test('html5lib_innerHTML_tests_innerHTML_1.html 6056619333f1a780052612e1dda18112147f67fa'), "%3Ca%3E%3Ctbody%3E%3Ctr%3E", "%23document%0A%7C%20%3Ca%3E%0A%7C%20%3Ctbody%3E%0A%7C%20%20%20%3Ctr%3E", 'table'],"d9300c4d8d36e950490bbe5800c1a3ba4e744e2a":[async_test('html5lib_innerHTML_tests_innerHTML_1.html d9300c4d8d36e950490bbe5800c1a3ba4e744e2a'), "%3Ca%3E%3Ctfoot%3E%3Ctr%3E", "%23document%0A%7C%20%3Ca%3E%0A%7C%20%3Ctfoot%3E%0A%7C%20%20%20%3Ctr%3E", 'table'],"411ebe3bea1d0508263ec17618492feaa9ca99d7":[async_test('html5lib_innerHTML_tests_innerHTML_1.html 411ebe3bea1d0508263ec17618492feaa9ca99d7'), "%3Ca%3E%3Cthead%3E%3Ctr%3E", "%23document%0A%7C%20%3Ca%3E%0A%7C%20%3Cthead%3E%0A%7C%20%20%20%3Ctr%3E", 'table'],"6c7c85721f823ab889bcb9e035341a1fb6d6eeee":[async_test('html5lib_innerHTML_tests_innerHTML_1.html 6c7c85721f823ab889bcb9e035341a1fb6d6eeee'), "%3Ca%3E%3Ctr%3E", "%23document%0A%7C%20%3Ca%3E%0A%7C%20%3Ctbody%3E%0A%7C%20%20%20%3Ctr%3E", 'table'],"973d06969d7968d200d5639ce06f7209655b1e26":[async_test('html5lib_innerHTML_tests_innerHTML_1.html 973d06969d7968d200d5639ce06f7209655b1e26'), "%3Ca%3E%3Cth%3E", "%23document%0A%7C%20%3Ca%3E%0A%7C%20%3Ctbody%3E%0A%7C%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%3Cth%3E", 'table'],"dfb6ec1e412a6634b497151f222f4272721ae57e":[async_test('html5lib_innerHTML_tests_innerHTML_1.html dfb6ec1e412a6634b497151f222f4272721ae57e'), "%3Ca%3E%3Ctd%3E", "%23document%0A%7C%20%3Ca%3E%0A%7C%20%3Ctbody%3E%0A%7C%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%3Ctd%3E", 'table'],"4916096ab7dbdd051dc96de7952ec60674d617a3":[async_test('html5lib_innerHTML_tests_innerHTML_1.html 4916096ab7dbdd051dc96de7952ec60674d617a3'), "%3Ctable%3E%3C/table%3E%3Ctbody%3E", "%23document%0A%7C%20%3Ctable%3E", 'caption'],"58277507de4ce0df9b4eb03262e4cb04d2fcc7af":[async_test('html5lib_innerHTML_tests_innerHTML_1.html 58277507de4ce0df9b4eb03262e4cb04d2fcc7af'), "%3C/table%3E%3Cspan%3E", "%23document%0A%7C%20%3Cspan%3E", 'caption'],"8e5727f170507ba6b86c1c3bdb3a5201d3480b33":[async_test('html5lib_innerHTML_tests_innerHTML_1.html 8e5727f170507ba6b86c1c3bdb3a5201d3480b33'), "%3Cspan%3E%3C/table%3E", "%23document%0A%7C%20%3Cspan%3E", 'caption'],"61eb343f71030688ab1a26bb980b9e4409993e3d":[async_test('html5lib_innerHTML_tests_innerHTML_1.html 61eb343f71030688ab1a26bb980b9e4409993e3d'), "%3C/caption%3E%3Cspan%3E", "%23document%0A%7C%20%3Cspan%3E", 'caption'],"3548939a56a148b59781c5f930036c1528db1545":[async_test('html5lib_innerHTML_tests_innerHTML_1.html 3548939a56a148b59781c5f930036c1528db1545'), "%3Cspan%3E%3C/caption%3E%3Cspan%3E", "%23document%0A%7C%20%3Cspan%3E%0A%7C%20%20%20%3Cspan%3E", 'caption'],"0b88a12102fba0634b44ac9f157544faeca68df6":[async_test('html5lib_innerHTML_tests_innerHTML_1.html 0b88a12102fba0634b44ac9f157544faeca68df6'), "%3Cspan%3E%3Ccaption%3E%3Cspan%3E", "%23document%0A%7C%20%3Cspan%3E%0A%7C%20%20%20%3Cspan%3E", 'caption'],"c300553f45f4ad6e5e1da9d884fafb95f36ab05a":[async_test('html5lib_innerHTML_tests_innerHTML_1.html c300553f45f4ad6e5e1da9d884fafb95f36ab05a'), "%3Cspan%3E%3Ccol%3E%3Cspan%3E", "%23document%0A%7C%20%3Cspan%3E%0A%7C%20%20%20%3Cspan%3E", 'caption'],"00a7ed4082183eba76af197418305b2d196ec7e6":[async_test('html5lib_innerHTML_tests_innerHTML_1.html 00a7ed4082183eba76af197418305b2d196ec7e6'), "%3Cspan%3E%3Ccolgroup%3E%3Cspan%3E", "%23document%0A%7C%20%3Cspan%3E%0A%7C%20%20%20%3Cspan%3E", 'caption'],"5dfd84382f85ff8343a62d6bb5028996111e5017":[async_test('html5lib_innerHTML_tests_innerHTML_1.html 5dfd84382f85ff8343a62d6bb5028996111e5017'), "%3Cspan%3E%3Chtml%3E%3Cspan%3E", "%23document%0A%7C%20%3Cspan%3E%0A%7C%20%20%20%3Cspan%3E", 'caption'],"9b1a1cd33bb3f26ec3f969f3158edf5c2db47052":[async_test('html5lib_innerHTML_tests_innerHTML_1.html 9b1a1cd33bb3f26ec3f969f3158edf5c2db47052'), "%3Cspan%3E%3Ctbody%3E%3Cspan%3E", "%23document%0A%7C%20%3Cspan%3E%0A%7C%20%20%20%3Cspan%3E", 'caption'],"8ab89f758b96bf994a21d8283d27e8ae9804b924":[async_test('html5lib_innerHTML_tests_innerHTML_1.html 8ab89f758b96bf994a21d8283d27e8ae9804b924'), "%3Cspan%3E%3Ctd%3E%3Cspan%3E", "%23document%0A%7C%20%3Cspan%3E%0A%7C%20%20%20%3Cspan%3E", 'caption'],"25add8314f59cdc264d7779f36ae4dffd1f9ad29":[async_test('html5lib_innerHTML_tests_innerHTML_1.html 25add8314f59cdc264d7779f36ae4dffd1f9ad29'), "%3Cspan%3E%3Ctfoot%3E%3Cspan%3E", "%23document%0A%7C%20%3Cspan%3E%0A%7C%20%20%20%3Cspan%3E", 'caption'],"7104e981f6018b18766fd95109bfbffeb878cc56":[async_test('html5lib_innerHTML_tests_innerHTML_1.html 7104e981f6018b18766fd95109bfbffeb878cc56'), "%3Cspan%3E%3Cthead%3E%3Cspan%3E", "%23document%0A%7C%20%3Cspan%3E%0A%7C%20%20%20%3Cspan%3E", 'caption'],"28fbaa710ce3f440a56fdf909c4b8bc223a1b965":[async_test('html5lib_innerHTML_tests_innerHTML_1.html 28fbaa710ce3f440a56fdf909c4b8bc223a1b965'), "%3Cspan%3E%3Cth%3E%3Cspan%3E", "%23document%0A%7C%20%3Cspan%3E%0A%7C%20%20%20%3Cspan%3E", 'caption'],"3380b0143f3d1e2edb216d388acd72702e141165":[async_test('html5lib_innerHTML_tests_innerHTML_1.html 3380b0143f3d1e2edb216d388acd72702e141165'), "%3Cspan%3E%3Ctr%3E%3Cspan%3E", "%23document%0A%7C%20%3Cspan%3E%0A%7C%20%20%20%3Cspan%3E", 'caption'],"a630fb272be6de118b728a28d6ce71b296a75694":[async_test('html5lib_innerHTML_tests_innerHTML_1.html a630fb272be6de118b728a28d6ce71b296a75694'), "%3Cspan%3E%3C/table%3E%3Cspan%3E", "%23document%0A%7C%20%3Cspan%3E%0A%7C%20%20%20%3Cspan%3E", 'caption'],"5adf8b7bd3d63a77ea1dbe6deb6741c5b92de6cd":[async_test('html5lib_innerHTML_tests_innerHTML_1.html 5adf8b7bd3d63a77ea1dbe6deb6741c5b92de6cd'), "%3C/colgroup%3E%3Ccol%3E", "%23document%0A%7C%20%3Ccol%3E", 'colgroup'],"4e0312ac349a70d07f2bb1ae154740e46e8c9a6e":[async_test('html5lib_innerHTML_tests_innerHTML_1.html 4e0312ac349a70d07f2bb1ae154740e46e8c9a6e'), "%3Ca%3E%3Ccol%3E", "%23document%0A%7C%20%3Ccol%3E", 'colgroup'],"987061379d2542e88d8a72ce6f0169a211d3ac41":[async_test('html5lib_innerHTML_tests_innerHTML_1.html 987061379d2542e88d8a72ce6f0169a211d3ac41'), "%3Ccaption%3E%3Ca%3E", "%23document%0A%7C%20%3Ca%3E", 'tbody'],"e0798aa003863ba2be750d3e6c2e6766fea11279":[async_test('html5lib_innerHTML_tests_innerHTML_1.html e0798aa003863ba2be750d3e6c2e6766fea11279'), "%3Ccol%3E%3Ca%3E", "%23document%0A%7C%20%3Ca%3E", 'tbody'],"586ed8e0d1395198f43ee68843d654a49169f379":[async_test('html5lib_innerHTML_tests_innerHTML_1.html 586ed8e0d1395198f43ee68843d654a49169f379'), "%3Ccolgroup%3E%3Ca%3E", "%23document%0A%7C%20%3Ca%3E", 'tbody'],"8896feedef576c1ed768a4eb67f57c3dc5242fed":[async_test('html5lib_innerHTML_tests_innerHTML_1.html 8896feedef576c1ed768a4eb67f57c3dc5242fed'), "%3Ctbody%3E%3Ca%3E", "%23document%0A%7C%20%3Ca%3E", 'tbody'],"89f4f0f289a23d1ebfbf499c2ecd24cd35fc10b4":[async_test('html5lib_innerHTML_tests_innerHTML_1.html 89f4f0f289a23d1ebfbf499c2ecd24cd35fc10b4'), "%3Ctfoot%3E%3Ca%3E", "%23document%0A%7C%20%3Ca%3E", 'tbody'],"2c07361470533b905a7ff9a685439cad2fe35549":[async_test('html5lib_innerHTML_tests_innerHTML_1.html 2c07361470533b905a7ff9a685439cad2fe35549'), "%3Cthead%3E%3Ca%3E", "%23document%0A%7C%20%3Ca%3E", 'tbody'],"a36f27cbe53991c647055c95bfa250a0ab734b0d":[async_test('html5lib_innerHTML_tests_innerHTML_1.html a36f27cbe53991c647055c95bfa250a0ab734b0d'), "%3C/table%3E%3Ca%3E", "%23document%0A%7C%20%3Ca%3E", 'tbody'],"ac28c352ae8453434e3aefb24e798a9580c1b230":[async_test('html5lib_innerHTML_tests_innerHTML_1.html ac28c352ae8453434e3aefb24e798a9580c1b230'), "%3Ca%3E%3Ctr%3E", "%23document%0A%7C%20%3Ca%3E%0A%7C%20%3Ctr%3E", 'tbody'],"f8770f97671a805b37277db7e42536b40c0804cb":[async_test('html5lib_innerHTML_tests_innerHTML_1.html f8770f97671a805b37277db7e42536b40c0804cb'), "%3Ca%3E%3Ctd%3E", "%23document%0A%7C%20%3Ca%3E%0A%7C%20%3Ctr%3E%0A%7C%20%20%20%3Ctd%3E", 'tbody'],"469a071b520d8436e6a0f6da6f9385f5ebd8e2f8":[async_test('html5lib_innerHTML_tests_innerHTML_1.html 469a071b520d8436e6a0f6da6f9385f5ebd8e2f8'), "%3Ctd%3E%3Ctable%3E%3Ctbody%3E%3Ca%3E%3Ctr%3E", "%23document%0A%7C%20%3Ctr%3E%0A%7C%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E", 'tbody'],"7cf2db8c65b79da98e39b13772ed0440ff177fd7":[async_test('html5lib_innerHTML_tests_innerHTML_1.html 7cf2db8c65b79da98e39b13772ed0440ff177fd7'), "%3C/tr%3E%3Ctd%3E", "%23document%0A%7C%20%3Ctd%3E", 'tr'],"3940fdb54783cb3c42138670a17d28e77e29e900":[async_test('html5lib_innerHTML_tests_innerHTML_1.html 3940fdb54783cb3c42138670a17d28e77e29e900'), "%3Ctd%3E%3Ctable%3E%3Ca%3E%3Ctr%3E%3C/tr%3E%3Ctr%3E", "%23document%0A%7C%20%3Ctd%3E%0A%7C%20%20%20%3Ca%3E%0A%7C%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%3Ctr%3E", 'tr'],"3b5ab5fbb3585d7215a5766f1e2377b7929b5cc6":[async_test('html5lib_innerHTML_tests_innerHTML_1.html 3b5ab5fbb3585d7215a5766f1e2377b7929b5cc6'), "%3Ccaption%3E%3Ctd%3E", "%23document%0A%7C%20%3Ctd%3E", 'tr'],"7c4a40203d5830d36432b0f30a09cebea6e9d2e4":[async_test('html5lib_innerHTML_tests_innerHTML_1.html 7c4a40203d5830d36432b0f30a09cebea6e9d2e4'), "%3Ccol%3E%3Ctd%3E", "%23document%0A%7C%20%3Ctd%3E", 'tr'],"e6d930d4239666fdc6c0722106bd2b115b4d3fd3":[async_test('html5lib_innerHTML_tests_innerHTML_1.html e6d930d4239666fdc6c0722106bd2b115b4d3fd3'), "%3Ccolgroup%3E%3Ctd%3E", "%23document%0A%7C%20%3Ctd%3E", 'tr'],"c8817b3b55a437bd153e978fc5f49fbe10bb56e2":[async_test('html5lib_innerHTML_tests_innerHTML_1.html c8817b3b55a437bd153e978fc5f49fbe10bb56e2'), "%3Ctbody%3E%3Ctd%3E", "%23document%0A%7C%20%3Ctd%3E", 'tr'],"2a302c14f1983aaad9fd7abe49336d9561ed82e9":[async_test('html5lib_innerHTML_tests_innerHTML_1.html 2a302c14f1983aaad9fd7abe49336d9561ed82e9'), "%3Ctfoot%3E%3Ctd%3E", "%23document%0A%7C%20%3Ctd%3E", 'tr'],"28cfddd5b5875f7044b0859ba4ce88175fcbf07e":[async_test('html5lib_innerHTML_tests_innerHTML_1.html 28cfddd5b5875f7044b0859ba4ce88175fcbf07e'), "%3Cthead%3E%3Ctd%3E", "%23document%0A%7C%20%3Ctd%3E", 'tr'],"887596c50809eeb809ad24d86c239130a42f5a46":[async_test('html5lib_innerHTML_tests_innerHTML_1.html 887596c50809eeb809ad24d86c239130a42f5a46'), "%3Ctr%3E%3Ctd%3E", "%23document%0A%7C%20%3Ctd%3E", 'tr'],"fa3797a2d2baeb8b8b2de81f1e7f33725e6b2aad":[async_test('html5lib_innerHTML_tests_innerHTML_1.html fa3797a2d2baeb8b8b2de81f1e7f33725e6b2aad'), "%3C/table%3E%3Ctd%3E", "%23document%0A%7C%20%3Ctd%3E", 'tr'],"dc0e2582ff83e60c0eb549dc3387562d3482e364":[async_test('html5lib_innerHTML_tests_innerHTML_1.html dc0e2582ff83e60c0eb549dc3387562d3482e364'), "%3Ctd%3E%3Ctable%3E%3C/table%3E%3Ctd%3E", "%23document%0A%7C%20%3Ctd%3E%0A%7C%20%20%20%3Ctable%3E%0A%7C%20%3Ctd%3E", 'tr'],"4ea02fd705291eb2d14274ebeaa0117ba2b9b306":[async_test('html5lib_innerHTML_tests_innerHTML_1.html 4ea02fd705291eb2d14274ebeaa0117ba2b9b306'), "%3Ccaption%3E%3Ca%3E", "%23document%0A%7C%20%3Ca%3E", 'td'],"52cc77eac9488a8bb1a2c8c695f16f8919c52044":[async_test('html5lib_innerHTML_tests_innerHTML_1.html 52cc77eac9488a8bb1a2c8c695f16f8919c52044'), "%3Ccol%3E%3Ca%3E", "%23document%0A%7C%20%3Ca%3E", 'td'],"c53ab7d84ae27de9f0937521c74eec2fd6c1b1ec":[async_test('html5lib_innerHTML_tests_innerHTML_1.html c53ab7d84ae27de9f0937521c74eec2fd6c1b1ec'), "%3Ccolgroup%3E%3Ca%3E", "%23document%0A%7C%20%3Ca%3E", 'td'],"d8747a49503f3486155d77dd366e0ee8ad9512a6":[async_test('html5lib_innerHTML_tests_innerHTML_1.html d8747a49503f3486155d77dd366e0ee8ad9512a6'), "%3Ctbody%3E%3Ca%3E", "%23document%0A%7C%20%3Ca%3E", 'td'],"03e71832c254852f206f6f0ae6f4d161a276a699":[async_test('html5lib_innerHTML_tests_innerHTML_1.html 03e71832c254852f206f6f0ae6f4d161a276a699'), "%3Ctfoot%3E%3Ca%3E", "%23document%0A%7C%20%3Ca%3E", 'td'],"92786cfafa890c23f200dccea089ca52233ef395":[async_test('html5lib_innerHTML_tests_innerHTML_1.html 92786cfafa890c23f200dccea089ca52233ef395'), "%3Cth%3E%3Ca%3E", "%23document%0A%7C%20%3Ca%3E", 'td'],"11d284c2b1e2f87d28dd06b938518361fe834855":[async_test('html5lib_innerHTML_tests_innerHTML_1.html 11d284c2b1e2f87d28dd06b938518361fe834855'), "%3Cthead%3E%3Ca%3E", "%23document%0A%7C%20%3Ca%3E", 'td'],"bf6aebcd54d5dead9e6d56c77b41f01ea666d8b1":[async_test('html5lib_innerHTML_tests_innerHTML_1.html bf6aebcd54d5dead9e6d56c77b41f01ea666d8b1'), "%3Ctr%3E%3Ca%3E", "%23document%0A%7C%20%3Ca%3E", 'td'],"4d448a4239cb4c465a21c04997d656e51fdd388f":[async_test('html5lib_innerHTML_tests_innerHTML_1.html 4d448a4239cb4c465a21c04997d656e51fdd388f'), "%3C/table%3E%3Ca%3E", "%23document%0A%7C%20%3Ca%3E", 'td'],"1e8faedc427045d59305218c1aba2f545c4eb4b7":[async_test('html5lib_innerHTML_tests_innerHTML_1.html 1e8faedc427045d59305218c1aba2f545c4eb4b7'), "%3C/tbody%3E%3Ca%3E", "%23document%0A%7C%20%3Ca%3E", 'td'],"6762997c1a93b1ec65722498f3fd00f0d8129369":[async_test('html5lib_innerHTML_tests_innerHTML_1.html 6762997c1a93b1ec65722498f3fd00f0d8129369'), "%3C/td%3E%3Ca%3E", "%23document%0A%7C%20%3Ca%3E", 'td'],"a162461c18d9b09734f6fe5d362b84edb4eed31f":[async_test('html5lib_innerHTML_tests_innerHTML_1.html a162461c18d9b09734f6fe5d362b84edb4eed31f'), "%3C/tfoot%3E%3Ca%3E", "%23document%0A%7C%20%3Ca%3E", 'td'],"0befc335ffd6cace344d94a35de96af22b1313a5":[async_test('html5lib_innerHTML_tests_innerHTML_1.html 0befc335ffd6cace344d94a35de96af22b1313a5'), "%3C/thead%3E%3Ca%3E", "%23document%0A%7C%20%3Ca%3E", 'td'],"a23b70f1f246ba08d13b570319391b4a5c3e9456":[async_test('html5lib_innerHTML_tests_innerHTML_1.html a23b70f1f246ba08d13b570319391b4a5c3e9456'), "%3C/th%3E%3Ca%3E", "%23document%0A%7C%20%3Ca%3E", 'td'],"9d5e0c25bfe921df9ea2897c027f42bc88950e69":[async_test('html5lib_innerHTML_tests_innerHTML_1.html 9d5e0c25bfe921df9ea2897c027f42bc88950e69'), "%3C/tr%3E%3Ca%3E", "%23document%0A%7C%20%3Ca%3E", 'td'],"9210d577d6deecf5ab3505af86c501c5befa0b50":[async_test('html5lib_innerHTML_tests_innerHTML_1.html 9210d577d6deecf5ab3505af86c501c5befa0b50'), "%3Ctable%3E%3Ctd%3E%3Ctd%3E", "%23document%0A%7C%20%3Ctable%3E%0A%7C%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%3Ctd%3E", 'td'],"c34af491c0a339db6ba63fcc478108533347319b":[async_test('html5lib_innerHTML_tests_innerHTML_1.html c34af491c0a339db6ba63fcc478108533347319b'), "%3C/select%3E%3Coption%3E", "%23document%0A%7C%20%3Coption%3E", 'select'],"2c4284e6b2bb480daa50bca43bcbe29cfcdeeab4":[async_test('html5lib_innerHTML_tests_innerHTML_1.html 2c4284e6b2bb480daa50bca43bcbe29cfcdeeab4'), "%3Cinput%3E%3Coption%3E", "%23document%0A%7C%20%3Coption%3E", 'select'],"d75277b65d0118463afeb66b478509d4e27565ab":[async_test('html5lib_innerHTML_tests_innerHTML_1.html d75277b65d0118463afeb66b478509d4e27565ab'), "%3Ckeygen%3E%3Coption%3E", "%23document%0A%7C%20%3Coption%3E", 'select'],"b354df69dbe9b3ef0c42177648e3aace114cf8ea":[async_test('html5lib_innerHTML_tests_innerHTML_1.html b354df69dbe9b3ef0c42177648e3aace114cf8ea'), "%3Ctextarea%3E%3Coption%3E", "%23document%0A%7C%20%3Coption%3E", 'select'],"fd3be386292ea1f411cea8e86e29595deb177d28":[async_test('html5lib_innerHTML_tests_innerHTML_1.html fd3be386292ea1f411cea8e86e29595deb177d28'), "%3C/html%3E%3C%21--abc--%3E", "%23document%0A%7C%20%3Chead%3E%0A%7C%20%3Cbody%3E%0A%7C%20%3C%21--%20abc%20--%3E", 'html'],"1cfb3baf2ad29109ddd5581daa3a009029c71491":[async_test('html5lib_innerHTML_tests_innerHTML_1.html 1cfb3baf2ad29109ddd5581daa3a009029c71491'), "%3C/frameset%3E%3Cframe%3E", "%23document%0A%7C%20%3Cframe%3E", 'frameset'],"2555d238e04f3d2853cfbc5f6dd366f82cf0e868":[async_test('html5lib_innerHTML_tests_innerHTML_1.html 2555d238e04f3d2853cfbc5f6dd366f82cf0e868'), "", "%23document%0A%7C%20%3Chead%3E%0A%7C%20%3Cbody%3E", 'html'],
+ }
+ init_tests("innerHTML");
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_isindex.html b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_isindex.html
new file mode 100644
index 00000000000..e73fb5a9469
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_isindex.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf8">
+ <title>HTML 5 Parser tests html5lib_isindex.html</title>
+ <meta name="timeout" content="long">
+ <meta name="variant" content="?run_type=uri">
+ <meta name="variant" content="?run_type=write">
+ <meta name="variant" content="?run_type=write_single">
+ </head>
+ <body>
+ <h1>html5lib Parser Test</h1>
+ <div id="log"></div>
+ <script src="common.js"></script>
+ <script src="test.js"></script>
+ <script src="template.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ var num_iframes = 8;
+ var order = ['579ca96e69c47b3d2ac83f1aa79a450b745d21f3','cb91f67071d81dd18d7ba9990de8f0f845c375f0','bd8ac64cc8f1422fac94bbe1c8828c0b51dca3f2',];
+ var tests = {
+ "579ca96e69c47b3d2ac83f1aa79a450b745d21f3":[async_test('html5lib_isindex.html 579ca96e69c47b3d2ac83f1aa79a450b745d21f3'), "%3Cisindex%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cform%3E%0A%7C%20%20%20%20%20%20%20%3Chr%3E%0A%7C%20%20%20%20%20%20%20%3Clabel%3E%0A%7C%20%20%20%20%20%20%20%20%20%22This%20is%20a%20searchable%20index.%20Enter%20search%20keywords%3A%20%22%0A%7C%20%20%20%20%20%20%20%20%20%3Cinput%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20name%3D%22isindex%22%0A%7C%20%20%20%20%20%20%20%3Chr%3E"],"cb91f67071d81dd18d7ba9990de8f0f845c375f0":[async_test('html5lib_isindex.html cb91f67071d81dd18d7ba9990de8f0f845c375f0'), "%3Cisindex%20name%3D%22A%22%20action%3D%22B%22%20prompt%3D%22C%22%20foo%3D%22D%22%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cform%3E%0A%7C%20%20%20%20%20%20%20action%3D%22B%22%0A%7C%20%20%20%20%20%20%20%3Chr%3E%0A%7C%20%20%20%20%20%20%20%3Clabel%3E%0A%7C%20%20%20%20%20%20%20%20%20%22C%22%0A%7C%20%20%20%20%20%20%20%20%20%3Cinput%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20foo%3D%22D%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20name%3D%22isindex%22%0A%7C%20%20%20%20%20%20%20%3Chr%3E"],"bd8ac64cc8f1422fac94bbe1c8828c0b51dca3f2":[async_test('html5lib_isindex.html bd8ac64cc8f1422fac94bbe1c8828c0b51dca3f2'), "%3Cform%3E%3Cisindex%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cform%3E"],
+ }
+ init_tests(get_type());
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_main-element.html b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_main-element.html
new file mode 100644
index 00000000000..8f01831505c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_main-element.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf8">
+ <title>HTML 5 Parser tests html5lib_main-element.html</title>
+ <meta name="timeout" content="long">
+ <meta name="variant" content="?run_type=uri">
+ <meta name="variant" content="?run_type=write">
+ <meta name="variant" content="?run_type=write_single">
+ </head>
+ <body>
+ <h1>html5lib Parser Test</h1>
+ <div id="log"></div>
+ <script src="common.js"></script>
+ <script src="test.js"></script>
+ <script src="template.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ var num_iframes = 8;
+ var order = ['336a047fbc84b86dfd4baea5881b50fe0cdb5ce8','fc887f078ddc2723261a7dfb25829efe2da284f2','ebd10973e73d3a339bdf22f8bbac2f028044e096',];
+ var tests = {
+ "336a047fbc84b86dfd4baea5881b50fe0cdb5ce8":[async_test('html5lib_main-element.html 336a047fbc84b86dfd4baea5881b50fe0cdb5ce8'), "%3C%21doctype%20html%3E%3Cp%3Efoo%3Cmain%3Ebar%3Cp%3Ebaz", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%22foo%22%0A%7C%20%20%20%20%20%3Cmain%3E%0A%7C%20%20%20%20%20%20%20%22bar%22%0A%7C%20%20%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%20%20%22baz%22"],"fc887f078ddc2723261a7dfb25829efe2da284f2":[async_test('html5lib_main-element.html fc887f078ddc2723261a7dfb25829efe2da284f2'), "%3C%21doctype%20html%3E%3Cmain%3E%3Cp%3Efoo%3C/main%3Ebar", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cmain%3E%0A%7C%20%20%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%20%20%22foo%22%0A%7C%20%20%20%20%20%22bar%22"],"ebd10973e73d3a339bdf22f8bbac2f028044e096":[async_test('html5lib_main-element.html ebd10973e73d3a339bdf22f8bbac2f028044e096'), "%3C%21DOCTYPE%20html%3Exxx%3Csvg%3E%3Cx%3E%3Cg%3E%3Ca%3E%3Cmain%3E%3Cb%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22xxx%22%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20x%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Csvg%20g%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Csvg%20a%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Csvg%20main%3E%0A%7C%20%20%20%20%20%3Cb%3E"],
+ }
+ init_tests(get_type());
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_pending-spec-changes-plain-text-unsafe.html b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_pending-spec-changes-plain-text-unsafe.html
new file mode 100644
index 00000000000..3943758423e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_pending-spec-changes-plain-text-unsafe.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf8">
+ <title>HTML 5 Parser tests html5lib_pending-spec-changes-plain-text-unsafe.html</title>
+ <meta name="timeout" content="long">
+ <meta name="variant" content="?run_type=uri">
+ <meta name="variant" content="?run_type=write">
+ <meta name="variant" content="?run_type=write_single">
+ </head>
+ <body>
+ <h1>html5lib Parser Test</h1>
+ <div id="log"></div>
+ <script src="common.js"></script>
+ <script src="test.js"></script>
+ <script src="template.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ var num_iframes = 8;
+ var order = ['8afa8d082dc447be5cab2eeb3e13efb07ec72aa6',];
+ var tests = {
+ "8afa8d082dc447be5cab2eeb3e13efb07ec72aa6":[async_test('html5lib_pending-spec-changes-plain-text-unsafe.html 8afa8d082dc447be5cab2eeb3e13efb07ec72aa6'), "%3Cbody%3E%3Ctable%3E%00filler%00text%00", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22fillertext%22%0A%7C%20%20%20%20%20%3Ctable%3E"],
+ }
+ init_tests(get_type());
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_pending-spec-changes.html b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_pending-spec-changes.html
new file mode 100644
index 00000000000..f7aa17e72ae
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_pending-spec-changes.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf8">
+ <title>HTML 5 Parser tests html5lib_pending-spec-changes.html</title>
+ <meta name="timeout" content="long">
+ <meta name="variant" content="?run_type=uri">
+ <meta name="variant" content="?run_type=write">
+ <meta name="variant" content="?run_type=write_single">
+ </head>
+ <body>
+ <h1>html5lib Parser Test</h1>
+ <div id="log"></div>
+ <script src="common.js"></script>
+ <script src="test.js"></script>
+ <script src="template.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ var num_iframes = 8;
+ var order = ['965e062f9d01c4334cb12637e84dcbf438d38faf','8772d25919914a17118b2105e126aaa5bc83f92c','9804e9659cd045f199d9f58ef85c2639724359aa',];
+ var tests = {
+ "965e062f9d01c4334cb12637e84dcbf438d38faf":[async_test('html5lib_pending-spec-changes.html 965e062f9d01c4334cb12637e84dcbf438d38faf'), "%3Cinput%20type%3D%22hidden%22%3E%3Cframeset%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E"],"8772d25919914a17118b2105e126aaa5bc83f92c":[async_test('html5lib_pending-spec-changes.html 8772d25919914a17118b2105e126aaa5bc83f92c'), "%3C%21DOCTYPE%20html%3E%3Ctable%3E%3Ccaption%3E%3Csvg%3Efoo%3C/table%3Ebar", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ccaption%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22foo%22%0A%7C%20%20%20%20%20%22bar%22"],"9804e9659cd045f199d9f58ef85c2639724359aa":[async_test('html5lib_pending-spec-changes.html 9804e9659cd045f199d9f58ef85c2639724359aa'), "%3Ctable%3E%3Ctr%3E%3Ctd%3E%3Csvg%3E%3Cdesc%3E%3Ctd%3E%3C/desc%3E%3Ccircle%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Csvg%20desc%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ccircle%3E"],
+ }
+ init_tests(get_type());
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_plain-text-unsafe.html b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_plain-text-unsafe.html
new file mode 100644
index 00000000000..d99328907fb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_plain-text-unsafe.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf8">
+ <title>HTML 5 Parser tests html5lib_plain-text-unsafe.html</title>
+ <meta name="timeout" content="long">
+ <meta name="variant" content="?run_type=uri">
+ <meta name="variant" content="?run_type=write">
+ <meta name="variant" content="?run_type=write_single">
+ </head>
+ <body>
+ <h1>html5lib Parser Test</h1>
+ <div id="log"></div>
+ <script src="common.js"></script>
+ <script src="test.js"></script>
+ <script src="template.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ var num_iframes = 8;
+ var order = ['7e4ca4cb5e73852744a876bf8652dd2c8998d94a','e552342bdd3ac62316bd91126556512683f3d4a9','9112cef60139e6988b66334e522777329051442a','5dfa36c8a466dd245e7977924936f4940df65e53','e057c57a5f32e5e341d70b0a6581bdad39b84ac5','dee24cacc42c7d0cdacab20abbcf128d8ac423bb','24ed904940ecdad39c61706e709ffed5ee804514','0829c314a34a62cd1caf52ddc4100050bf32aef3','024ba847361612e5e87bce271d0497eeee07f87f','ec721aae75752c688fa48ad4b251d3a5a394dc8f','1e262b6f330b0870e854458f11b2280c72c8bd16','29f42d8bf04aea6ab4c051bd77da7e79173cf159','1d65ea8967bdc24e89d6548320b7fb9e2ad2c915','f1c51609a504e4ab4f7ae4d61fb6175619974b0d','692122e8d2a27e37cb585c827fb33e22e31c018e','a4537cad9c2386108157889b3bf6ddd414f0366d','252ca95f75b077320bc167cb117a05edfcbd7d0e','dde4bba02ef4e37d010e552111bc668d9660a076','41b9352a4d99b4fd545551fe260754b3137ad148','4b9e317cba617324fea77a4e525602b3ad2717ef','a1e08cb99d89381a1c997fcd60bad23c029c4500','26d850208425cc885d4d0143909cf341f61fa1f1','68f0365c01dc386c706edd2b18672f9d85caaa2e','e415a2e7cf090e2c308af905d52c5f8163ae52ce','822702de65b80ec8e79da19335ab9d6a49f6ec6a','ee8b017ab043ff51b593787961626acb4c6488cd','304960c795639128844445166238350682ba0516','275bb0b518ec00b1e64a28cb9088989371fca9d9','068ac565b7c7bdad572f26dafb4580483cdbc6f7','f5ff59e9765a468913e14a6a9612edb2cd4f30f0','9ff76ac49f95ab0e22278fd07ed4dfee50519286','6a9486cce6ebcb83329c17ebcf3c9b6fe8bb8096','6f2f3f4f91f5484170a6dc8cc6165ce0ce498bff',];
+ var tests = {
+ "7e4ca4cb5e73852744a876bf8652dd2c8998d94a":[async_test('html5lib_plain-text-unsafe.html 7e4ca4cb5e73852744a876bf8652dd2c8998d94a'), "FOO%26%23x000D%3BZOO", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%0DZOO%22"],"e552342bdd3ac62316bd91126556512683f3d4a9":[async_test('html5lib_plain-text-unsafe.html e552342bdd3ac62316bd91126556512683f3d4a9'), "%3Chtml%3E%00%3Cframeset%3E%3C/frameset%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E"],"9112cef60139e6988b66334e522777329051442a":[async_test('html5lib_plain-text-unsafe.html 9112cef60139e6988b66334e522777329051442a'), "%3Chtml%3E%20%00%20%3Cframeset%3E%3C/frameset%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E"],"5dfa36c8a466dd245e7977924936f4940df65e53":[async_test('html5lib_plain-text-unsafe.html 5dfa36c8a466dd245e7977924936f4940df65e53'), "%3Chtml%3Ea%00a%3Cframeset%3E%3C/frameset%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22aa%22"],"e057c57a5f32e5e341d70b0a6581bdad39b84ac5":[async_test('html5lib_plain-text-unsafe.html e057c57a5f32e5e341d70b0a6581bdad39b84ac5'), "%3Chtml%3E%00%00%3Cframeset%3E%3C/frameset%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E"],"dee24cacc42c7d0cdacab20abbcf128d8ac423bb":[async_test('html5lib_plain-text-unsafe.html dee24cacc42c7d0cdacab20abbcf128d8ac423bb'), "%3Chtml%3E%00%0A%20%3Cframeset%3E%3C/frameset%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E"],"24ed904940ecdad39c61706e709ffed5ee804514":[async_test('html5lib_plain-text-unsafe.html 24ed904940ecdad39c61706e709ffed5ee804514'), "%3Chtml%3E%3Cselect%3E%00", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cselect%3E"],"0829c314a34a62cd1caf52ddc4100050bf32aef3":[async_test('html5lib_plain-text-unsafe.html 0829c314a34a62cd1caf52ddc4100050bf32aef3'), "%00", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"024ba847361612e5e87bce271d0497eeee07f87f":[async_test('html5lib_plain-text-unsafe.html 024ba847361612e5e87bce271d0497eeee07f87f'), "%3Cbody%3E%00", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"ec721aae75752c688fa48ad4b251d3a5a394dc8f":[async_test('html5lib_plain-text-unsafe.html ec721aae75752c688fa48ad4b251d3a5a394dc8f'), "%3Cplaintext%3E%00filler%00text%00", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cplaintext%3E%0A%7C%20%20%20%20%20%20%20%22%EF%BF%BDfiller%EF%BF%BDtext%EF%BF%BD%22"],"1e262b6f330b0870e854458f11b2280c72c8bd16":[async_test('html5lib_plain-text-unsafe.html 1e262b6f330b0870e854458f11b2280c72c8bd16'), "%3Csvg%3E%3C%21%5BCDATA%5B%00filler%00text%00%5D%5D%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%22%EF%BF%BDfiller%EF%BF%BDtext%EF%BF%BD%22"],"29f42d8bf04aea6ab4c051bd77da7e79173cf159":[async_test('html5lib_plain-text-unsafe.html 29f42d8bf04aea6ab4c051bd77da7e79173cf159'), "%3Cbody%3E%3C%21%00%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3C%21--%20%EF%BF%BD%20--%3E"],"1d65ea8967bdc24e89d6548320b7fb9e2ad2c915":[async_test('html5lib_plain-text-unsafe.html 1d65ea8967bdc24e89d6548320b7fb9e2ad2c915'), "%3Cbody%3E%3C%21%00filler%00text%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3C%21--%20%EF%BF%BDfiller%EF%BF%BDtext%20--%3E"],"f1c51609a504e4ab4f7ae4d61fb6175619974b0d":[async_test('html5lib_plain-text-unsafe.html f1c51609a504e4ab4f7ae4d61fb6175619974b0d'), "%3Cbody%3E%3Csvg%3E%3CforeignObject%3E%00filler%00text", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20foreignObject%3E%0A%7C%20%20%20%20%20%20%20%20%20%22fillertext%22"],"692122e8d2a27e37cb585c827fb33e22e31c018e":[async_test('html5lib_plain-text-unsafe.html 692122e8d2a27e37cb585c827fb33e22e31c018e'), "%3Csvg%3E%00filler%00text", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%22%EF%BF%BDfiller%EF%BF%BDtext%22"],"a4537cad9c2386108157889b3bf6ddd414f0366d":[async_test('html5lib_plain-text-unsafe.html a4537cad9c2386108157889b3bf6ddd414f0366d'), "%3Csvg%3E%00%3Cframeset%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%22%EF%BF%BD%22%0A%7C%20%20%20%20%20%20%20%3Csvg%20frameset%3E"],"252ca95f75b077320bc167cb117a05edfcbd7d0e":[async_test('html5lib_plain-text-unsafe.html 252ca95f75b077320bc167cb117a05edfcbd7d0e'), "%3Csvg%3E%00%20%3Cframeset%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%22%EF%BF%BD%20%22%0A%7C%20%20%20%20%20%20%20%3Csvg%20frameset%3E"],"dde4bba02ef4e37d010e552111bc668d9660a076":[async_test('html5lib_plain-text-unsafe.html dde4bba02ef4e37d010e552111bc668d9660a076'), "%3Csvg%3E%00a%3Cframeset%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%22%EF%BF%BDa%22%0A%7C%20%20%20%20%20%20%20%3Csvg%20frameset%3E"],"41b9352a4d99b4fd545551fe260754b3137ad148":[async_test('html5lib_plain-text-unsafe.html 41b9352a4d99b4fd545551fe260754b3137ad148'), "%3Csvg%3E%00%3C/svg%3E%3Cframeset%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E"],"4b9e317cba617324fea77a4e525602b3ad2717ef":[async_test('html5lib_plain-text-unsafe.html 4b9e317cba617324fea77a4e525602b3ad2717ef'), "%3Csvg%3E%00%20%3C/svg%3E%3Cframeset%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E"],"a1e08cb99d89381a1c997fcd60bad23c029c4500":[async_test('html5lib_plain-text-unsafe.html a1e08cb99d89381a1c997fcd60bad23c029c4500'), "%3Csvg%3E%00a%3C/svg%3E%3Cframeset%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%22%EF%BF%BDa%22"],"26d850208425cc885d4d0143909cf341f61fa1f1":[async_test('html5lib_plain-text-unsafe.html 26d850208425cc885d4d0143909cf341f61fa1f1'), "%3Csvg%3E%3Cpath%3E%3C/path%3E%3C/svg%3E%3Cframeset%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E"],"68f0365c01dc386c706edd2b18672f9d85caaa2e":[async_test('html5lib_plain-text-unsafe.html 68f0365c01dc386c706edd2b18672f9d85caaa2e'), "%3Csvg%3E%3Cp%3E%3Cframeset%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E"],"e415a2e7cf090e2c308af905d52c5f8163ae52ce":[async_test('html5lib_plain-text-unsafe.html e415a2e7cf090e2c308af905d52c5f8163ae52ce'), "%3C%21DOCTYPE%20html%3E%3Cpre%3E%0D%0A%0D%0AA%3C/pre%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cpre%3E%0A%7C%20%20%20%20%20%20%20%22%0AA%22"],"822702de65b80ec8e79da19335ab9d6a49f6ec6a":[async_test('html5lib_plain-text-unsafe.html 822702de65b80ec8e79da19335ab9d6a49f6ec6a'), "%3C%21DOCTYPE%20html%3E%3Cpre%3E%0D%0DA%3C/pre%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cpre%3E%0A%7C%20%20%20%20%20%20%20%22%0AA%22"],"ee8b017ab043ff51b593787961626acb4c6488cd":[async_test('html5lib_plain-text-unsafe.html ee8b017ab043ff51b593787961626acb4c6488cd'), "%3C%21DOCTYPE%20html%3E%3Cpre%3E%0DA%3C/pre%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cpre%3E%0A%7C%20%20%20%20%20%20%20%22A%22"],"304960c795639128844445166238350682ba0516":[async_test('html5lib_plain-text-unsafe.html 304960c795639128844445166238350682ba0516'), "%3C%21DOCTYPE%20html%3E%3Ctable%3E%3Ctr%3E%3Ctd%3E%3Cmath%3E%3Cmtext%3E%00a", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cmath%20mtext%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22a%22"],"275bb0b518ec00b1e64a28cb9088989371fca9d9":[async_test('html5lib_plain-text-unsafe.html 275bb0b518ec00b1e64a28cb9088989371fca9d9'), "%3C%21DOCTYPE%20html%3E%3Ctable%3E%3Ctr%3E%3Ctd%3E%3Csvg%3E%3CforeignObject%3E%00a", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Csvg%20foreignObject%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22a%22"],"068ac565b7c7bdad572f26dafb4580483cdbc6f7":[async_test('html5lib_plain-text-unsafe.html 068ac565b7c7bdad572f26dafb4580483cdbc6f7'), "%3C%21DOCTYPE%20html%3E%3Cmath%3E%3Cmi%3Ea%00b", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20mi%3E%0A%7C%20%20%20%20%20%20%20%20%20%22ab%22"],"f5ff59e9765a468913e14a6a9612edb2cd4f30f0":[async_test('html5lib_plain-text-unsafe.html f5ff59e9765a468913e14a6a9612edb2cd4f30f0'), "%3C%21DOCTYPE%20html%3E%3Cmath%3E%3Cmo%3Ea%00b", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20mo%3E%0A%7C%20%20%20%20%20%20%20%20%20%22ab%22"],"9ff76ac49f95ab0e22278fd07ed4dfee50519286":[async_test('html5lib_plain-text-unsafe.html 9ff76ac49f95ab0e22278fd07ed4dfee50519286'), "%3C%21DOCTYPE%20html%3E%3Cmath%3E%3Cmn%3Ea%00b", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20mn%3E%0A%7C%20%20%20%20%20%20%20%20%20%22ab%22"],"6a9486cce6ebcb83329c17ebcf3c9b6fe8bb8096":[async_test('html5lib_plain-text-unsafe.html 6a9486cce6ebcb83329c17ebcf3c9b6fe8bb8096'), "%3C%21DOCTYPE%20html%3E%3Cmath%3E%3Cms%3Ea%00b", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20ms%3E%0A%7C%20%20%20%20%20%20%20%20%20%22ab%22"],"6f2f3f4f91f5484170a6dc8cc6165ce0ce498bff":[async_test('html5lib_plain-text-unsafe.html 6f2f3f4f91f5484170a6dc8cc6165ce0ce498bff'), "%3C%21DOCTYPE%20html%3E%3Cmath%3E%3Cmtext%3Ea%00b", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20mtext%3E%0A%7C%20%20%20%20%20%20%20%20%20%22ab%22"],
+ }
+ init_tests(get_type());
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_scriptdata01.html b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_scriptdata01.html
new file mode 100644
index 00000000000..1233917145a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_scriptdata01.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf8">
+ <title>HTML 5 Parser tests html5lib_scriptdata01.html</title>
+ <meta name="timeout" content="long">
+ <meta name="variant" content="?run_type=uri">
+ <meta name="variant" content="?run_type=write">
+ <meta name="variant" content="?run_type=write_single">
+ </head>
+ <body>
+ <h1>html5lib Parser Test</h1>
+ <div id="log"></div>
+ <script src="common.js"></script>
+ <script src="test.js"></script>
+ <script src="template.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ var num_iframes = 8;
+ var order = ['3fc7e140adb65f9cfdf39219996f98e0749f398d','38ab7bda69dfd05e3ff01788cf5dac2d150a712a','09abe1da30643fd813db75facc7fde7b75762d43','193920d1c0fff50991d61655c529c62075a3da7f','66754fc904199af367a0a2b26cc89ea1834939cc','8c8a34698899e39e7b0879c07821aeb90f46cd83','a454052b572d9952465190ec354ad0ec2defca0b','6cc06752976c2cc9a4239f608b47cdb8df2b0b6b','4176aaaa17b9009e1ac8a293acbaa0d0cfd56975','e05f6594ea01489b55fca25aa79e5cffa43d9587','c7728688e5d12d5350c4228ac82c03a9886bef2f','c2a2bd66cbf430ee517678470fb560fa8862fa86','e04bd4c273176c0638e98dce1cbdcfc6438ec7eb','96a8546fd066084179852aa72bb599c1ee6f513f','1dae0f9ba7e933c1f6f9912d2289c290b2c8495a','44437869d870fea50416386a003d0b477a7d4f9d','3c72e7aa1fe7b65598a88a8cba1d7691824ec8a2','026ad2b8a6c85ab7a8804b1553b16560bc36fefd','d6b18cb44b4eda72b75fb64fe4287ee984562aaf','6ebea78eedeb25cbefd06e1ff55423db91f98c6d','fb5424c9ab36d5f8383268df1d64b17bab310e4d','3123b21e759d33987c407189584a5533c31a7482','f208b834bd4a2e13d79cebd59c02659f2f75ff04','0b72c0fef80895598cdf691a4913ff7aa5b1934b','bc7d3b5d37eaf53e338d81215f552e55cb555fc2','df2e36330e2e9609b1b9e1ff8a9440a66281dd46',];
+ var tests = {
+ "3fc7e140adb65f9cfdf39219996f98e0749f398d":[async_test('html5lib_scriptdata01.html 3fc7e140adb65f9cfdf39219996f98e0749f398d'), "FOO%3Cscript%3E%27Hello%27%3C/script%3EBAR", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%22%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%27Hello%27%22%0A%7C%20%20%20%20%20%22BAR%22"],"38ab7bda69dfd05e3ff01788cf5dac2d150a712a":[async_test('html5lib_scriptdata01.html 38ab7bda69dfd05e3ff01788cf5dac2d150a712a'), "FOO%3Cscript%3E%3C/script%3EBAR", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%22%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%22BAR%22"],"09abe1da30643fd813db75facc7fde7b75762d43":[async_test('html5lib_scriptdata01.html 09abe1da30643fd813db75facc7fde7b75762d43'), "FOO%3Cscript%3E%3C/script%20%3EBAR", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%22%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%22BAR%22"],"193920d1c0fff50991d61655c529c62075a3da7f":[async_test('html5lib_scriptdata01.html 193920d1c0fff50991d61655c529c62075a3da7f'), "FOO%3Cscript%3E%3C/script/%3EBAR", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%22%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%22BAR%22"],"66754fc904199af367a0a2b26cc89ea1834939cc":[async_test('html5lib_scriptdata01.html 66754fc904199af367a0a2b26cc89ea1834939cc'), "FOO%3Cscript%3E%3C/script/%20%3EBAR", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%22%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%22BAR%22"],"8c8a34698899e39e7b0879c07821aeb90f46cd83":[async_test('html5lib_scriptdata01.html 8c8a34698899e39e7b0879c07821aeb90f46cd83'), "FOO%3Cscript%20type%3D%22text/plain%22%3E%3C/scriptx%3EBAR", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%22%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20type%3D%22text/plain%22%0A%7C%20%20%20%20%20%20%20%22%3C/scriptx%3EBAR%22"],"a454052b572d9952465190ec354ad0ec2defca0b":[async_test('html5lib_scriptdata01.html a454052b572d9952465190ec354ad0ec2defca0b'), "FOO%3Cscript%3E%3C/script%20foo%3D%22%3E%22%20dd%3EBAR", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%22%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%22BAR%22"],"6cc06752976c2cc9a4239f608b47cdb8df2b0b6b":[async_test('html5lib_scriptdata01.html 6cc06752976c2cc9a4239f608b47cdb8df2b0b6b'), "FOO%3Cscript%3E%27%3C%27%3C/script%3EBAR", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%22%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%27%3C%27%22%0A%7C%20%20%20%20%20%22BAR%22"],"4176aaaa17b9009e1ac8a293acbaa0d0cfd56975":[async_test('html5lib_scriptdata01.html 4176aaaa17b9009e1ac8a293acbaa0d0cfd56975'), "FOO%3Cscript%3E%27%3C%21%27%3C/script%3EBAR", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%22%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%27%3C%21%27%22%0A%7C%20%20%20%20%20%22BAR%22"],"e05f6594ea01489b55fca25aa79e5cffa43d9587":[async_test('html5lib_scriptdata01.html e05f6594ea01489b55fca25aa79e5cffa43d9587'), "FOO%3Cscript%3E%27%3C%21-%27%3C/script%3EBAR", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%22%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%27%3C%21-%27%22%0A%7C%20%20%20%20%20%22BAR%22"],"c7728688e5d12d5350c4228ac82c03a9886bef2f":[async_test('html5lib_scriptdata01.html c7728688e5d12d5350c4228ac82c03a9886bef2f'), "FOO%3Cscript%3E%27%3C%21--%27%3C/script%3EBAR", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%22%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%27%3C%21--%27%22%0A%7C%20%20%20%20%20%22BAR%22"],"c2a2bd66cbf430ee517678470fb560fa8862fa86":[async_test('html5lib_scriptdata01.html c2a2bd66cbf430ee517678470fb560fa8862fa86'), "FOO%3Cscript%3E%27%3C%21---%27%3C/script%3EBAR", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%22%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%27%3C%21---%27%22%0A%7C%20%20%20%20%20%22BAR%22"],"e04bd4c273176c0638e98dce1cbdcfc6438ec7eb":[async_test('html5lib_scriptdata01.html e04bd4c273176c0638e98dce1cbdcfc6438ec7eb'), "FOO%3Cscript%3E%27%3C%21--%3E%27%3C/script%3EBAR", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%22%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%27%3C%21--%3E%27%22%0A%7C%20%20%20%20%20%22BAR%22"],"96a8546fd066084179852aa72bb599c1ee6f513f":[async_test('html5lib_scriptdata01.html 96a8546fd066084179852aa72bb599c1ee6f513f'), "FOO%3Cscript%3E%27%3C%21--%20potato%27%3C/script%3EBAR", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%22%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%27%3C%21--%20potato%27%22%0A%7C%20%20%20%20%20%22BAR%22"],"1dae0f9ba7e933c1f6f9912d2289c290b2c8495a":[async_test('html5lib_scriptdata01.html 1dae0f9ba7e933c1f6f9912d2289c290b2c8495a'), "FOO%3Cscript%3E%27%3C%21--%20%3CsCrIpt%27%3C/script%3EBAR", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%22%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%27%3C%21--%20%3CsCrIpt%27%22%0A%7C%20%20%20%20%20%22BAR%22"],"44437869d870fea50416386a003d0b477a7d4f9d":[async_test('html5lib_scriptdata01.html 44437869d870fea50416386a003d0b477a7d4f9d'), "FOO%3Cscript%20type%3D%22text/plain%22%3E%27%3C%21--%20%3CsCrIpt%3E%27%3C/script%3EBAR", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%22%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20type%3D%22text/plain%22%0A%7C%20%20%20%20%20%20%20%22%27%3C%21--%20%3CsCrIpt%3E%27%3C/script%3EBAR%22"],"3c72e7aa1fe7b65598a88a8cba1d7691824ec8a2":[async_test('html5lib_scriptdata01.html 3c72e7aa1fe7b65598a88a8cba1d7691824ec8a2'), "FOO%3Cscript%20type%3D%22text/plain%22%3E%27%3C%21--%20%3CsCrIpt%3E%20-%27%3C/script%3EBAR", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%22%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20type%3D%22text/plain%22%0A%7C%20%20%20%20%20%20%20%22%27%3C%21--%20%3CsCrIpt%3E%20-%27%3C/script%3EBAR%22"],"026ad2b8a6c85ab7a8804b1553b16560bc36fefd":[async_test('html5lib_scriptdata01.html 026ad2b8a6c85ab7a8804b1553b16560bc36fefd'), "FOO%3Cscript%20type%3D%22text/plain%22%3E%27%3C%21--%20%3CsCrIpt%3E%20--%27%3C/script%3EBAR", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%22%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20type%3D%22text/plain%22%0A%7C%20%20%20%20%20%20%20%22%27%3C%21--%20%3CsCrIpt%3E%20--%27%3C/script%3EBAR%22"],"d6b18cb44b4eda72b75fb64fe4287ee984562aaf":[async_test('html5lib_scriptdata01.html d6b18cb44b4eda72b75fb64fe4287ee984562aaf'), "FOO%3Cscript%3E%27%3C%21--%20%3CsCrIpt%3E%20--%3E%27%3C/script%3EBAR", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%22%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%27%3C%21--%20%3CsCrIpt%3E%20--%3E%27%22%0A%7C%20%20%20%20%20%22BAR%22"],"6ebea78eedeb25cbefd06e1ff55423db91f98c6d":[async_test('html5lib_scriptdata01.html 6ebea78eedeb25cbefd06e1ff55423db91f98c6d'), "FOO%3Cscript%20type%3D%22text/plain%22%3E%27%3C%21--%20%3CsCrIpt%3E%20--%21%3E%27%3C/script%3EBAR", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%22%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20type%3D%22text/plain%22%0A%7C%20%20%20%20%20%20%20%22%27%3C%21--%20%3CsCrIpt%3E%20--%21%3E%27%3C/script%3EBAR%22"],"fb5424c9ab36d5f8383268df1d64b17bab310e4d":[async_test('html5lib_scriptdata01.html fb5424c9ab36d5f8383268df1d64b17bab310e4d'), "FOO%3Cscript%20type%3D%22text/plain%22%3E%27%3C%21--%20%3CsCrIpt%3E%20--%20%3E%27%3C/script%3EBAR", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%22%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20type%3D%22text/plain%22%0A%7C%20%20%20%20%20%20%20%22%27%3C%21--%20%3CsCrIpt%3E%20--%20%3E%27%3C/script%3EBAR%22"],"3123b21e759d33987c407189584a5533c31a7482":[async_test('html5lib_scriptdata01.html 3123b21e759d33987c407189584a5533c31a7482'), "FOO%3Cscript%20type%3D%22text/plain%22%3E%27%3C%21--%20%3CsCrIpt%20%27%3C/script%3EBAR", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%22%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20type%3D%22text/plain%22%0A%7C%20%20%20%20%20%20%20%22%27%3C%21--%20%3CsCrIpt%20%27%3C/script%3EBAR%22"],"f208b834bd4a2e13d79cebd59c02659f2f75ff04":[async_test('html5lib_scriptdata01.html f208b834bd4a2e13d79cebd59c02659f2f75ff04'), "FOO%3Cscript%20type%3D%22text/plain%22%3E%27%3C%21--%20%3CsCrIpt/%27%3C/script%3EBAR", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%22%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20type%3D%22text/plain%22%0A%7C%20%20%20%20%20%20%20%22%27%3C%21--%20%3CsCrIpt/%27%3C/script%3EBAR%22"],"0b72c0fef80895598cdf691a4913ff7aa5b1934b":[async_test('html5lib_scriptdata01.html 0b72c0fef80895598cdf691a4913ff7aa5b1934b'), "FOO%3Cscript%20type%3D%22text/plain%22%3E%27%3C%21--%20%3CsCrIpt%5C%27%3C/script%3EBAR", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%22%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20type%3D%22text/plain%22%0A%7C%20%20%20%20%20%20%20%22%27%3C%21--%20%3CsCrIpt%5C%27%22%0A%7C%20%20%20%20%20%22BAR%22"],"bc7d3b5d37eaf53e338d81215f552e55cb555fc2":[async_test('html5lib_scriptdata01.html bc7d3b5d37eaf53e338d81215f552e55cb555fc2'), "FOO%3Cscript%20type%3D%22text/plain%22%3E%27%3C%21--%20%3CsCrIpt/%27%3C/script%3EBAR%3C/script%3EQUX", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%22%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20type%3D%22text/plain%22%0A%7C%20%20%20%20%20%20%20%22%27%3C%21--%20%3CsCrIpt/%27%3C/script%3EBAR%22%0A%7C%20%20%20%20%20%22QUX%22"],"df2e36330e2e9609b1b9e1ff8a9440a66281dd46":[async_test('html5lib_scriptdata01.html df2e36330e2e9609b1b9e1ff8a9440a66281dd46'), "FOO%3Cscript%3E%3C%21--%3Cscript%3E-%3E%3C/script%3E--%3E%3C/script%3EQUX", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22FOO%22%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%3E-%3E%3C/script%3E--%3E%22%0A%7C%20%20%20%20%20%22QUX%22"],
+ }
+ init_tests(get_type());
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_scripted_adoption01.html b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_scripted_adoption01.html
new file mode 100644
index 00000000000..479208aa912
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_scripted_adoption01.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf8">
+ <title>HTML 5 Parser tests html5lib_scripted_adoption01.html</title>
+ <meta name="timeout" content="long">
+ <meta name="variant" content="?run_type=uri">
+ <meta name="variant" content="?run_type=write">
+ <meta name="variant" content="?run_type=write_single">
+ </head>
+ <body>
+ <h1>html5lib Parser Test</h1>
+ <div id="log"></div>
+ <script src="common.js"></script>
+ <script src="test.js"></script>
+ <script src="template.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ var num_iframes = 8;
+ var order = ['8970fe21b551a270aa74648bb2e8b905edb54522',];
+ var tests = {
+ "8970fe21b551a270aa74648bb2e8b905edb54522":[async_test('html5lib_scripted_adoption01.html 8970fe21b551a270aa74648bb2e8b905edb54522'), "%3Cp%3E%3Cb%20id%3D%22A%22%3E%3Cscript%3Edocument.getElementById%28%22A%22%29.id%20%3D%20%22B%22%3C/script%3E%3C/p%3ETEXT%3C/b%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20id%3D%22B%22%0A%7C%20%20%20%20%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22document.getElementById%28%22A%22%29.id%20%3D%20%22B%22%22%0A%7C%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20id%3D%22A%22%0A%7C%20%20%20%20%20%20%20%22TEXT%22"],
+ }
+ init_tests(get_type());
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_scripted_ark.html b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_scripted_ark.html
new file mode 100644
index 00000000000..4542b7c7d0d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_scripted_ark.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf8">
+ <title>HTML 5 Parser tests html5lib_scripted_ark.html</title>
+ <meta name="timeout" content="long">
+ <meta name="variant" content="?run_type=uri">
+ <meta name="variant" content="?run_type=write">
+ <meta name="variant" content="?run_type=write_single">
+ </head>
+ <body>
+ <h1>html5lib Parser Test</h1>
+ <div id="log"></div>
+ <script src="common.js"></script>
+ <script src="test.js"></script>
+ <script src="template.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ var num_iframes = 8;
+ var order = ['b9a7cd0310cab4fd4eb77aed9149b966918e7ca2',];
+ var tests = {
+ "b9a7cd0310cab4fd4eb77aed9149b966918e7ca2":[async_test('html5lib_scripted_ark.html b9a7cd0310cab4fd4eb77aed9149b966918e7ca2'), "%3Cp%3E%3Cfont%20size%3D4%3E%3Cfont%20size%3D4%3E%3Cfont%20size%3D4%3E%3Cscript%3Edocument.getElementsByTagName%28%22font%22%29%5B2%5D.setAttribute%28%22size%22%2C%20%225%22%29%3B%3C/script%3E%3Cfont%20size%3D4%3E%3Cp%3EX", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%20%20size%3D%224%22%0A%7C%20%20%20%20%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20size%3D%224%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20size%3D%225%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22document.getElementsByTagName%28%22font%22%29%5B2%5D.setAttribute%28%22size%22%2C%20%225%22%29%3B%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20size%3D%224%22%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%20%20size%3D%224%22%0A%7C%20%20%20%20%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20size%3D%224%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20size%3D%224%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%22X%22"],
+ }
+ init_tests(get_type());
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_scripted_webkit01.html b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_scripted_webkit01.html
new file mode 100644
index 00000000000..ef4f16d9cac
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_scripted_webkit01.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf8">
+ <title>HTML 5 Parser tests html5lib_scripted_webkit01.html</title>
+ <meta name="timeout" content="long">
+ <meta name="variant" content="?run_type=uri">
+ <meta name="variant" content="?run_type=write">
+ <meta name="variant" content="?run_type=write_single">
+ </head>
+ <body>
+ <h1>html5lib Parser Test</h1>
+ <div id="log"></div>
+ <script src="common.js"></script>
+ <script src="test.js"></script>
+ <script src="template.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ var num_iframes = 8;
+ var order = ['3ff6ec1125852c7933bf6d89ecb375354e6e1b40','46ae362de712eb9c55916de93110299dbbcb5726',];
+ var tests = {
+ "3ff6ec1125852c7933bf6d89ecb375354e6e1b40":[async_test('html5lib_scripted_webkit01.html 3ff6ec1125852c7933bf6d89ecb375354e6e1b40'), "1%3Cscript%3Edocument.write%28%222%22%29%3C/script%3E3", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%221%22%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22document.write%28%222%22%29%22%0A%7C%20%20%20%20%20%2223%22"],"46ae362de712eb9c55916de93110299dbbcb5726":[async_test('html5lib_scripted_webkit01.html 46ae362de712eb9c55916de93110299dbbcb5726'), "1%3Cscript%3Edocument.write%28%22%3Cscript%3Edocument.write%28%272%27%29%3C/scr%22%2B%20%22ipt%3E%3Cscript%3Edocument.write%28%273%27%29%3C/scr%22%20%2B%20%22ipt%3E%22%29%3C/script%3E4", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%221%22%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22document.write%28%22%3Cscript%3Edocument.write%28%272%27%29%3C/scr%22%2B%20%22ipt%3E%3Cscript%3Edocument.write%28%273%27%29%3C/scr%22%20%2B%20%22ipt%3E%22%29%22%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22document.write%28%272%27%29%22%0A%7C%20%20%20%20%20%222%22%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22document.write%28%273%27%29%22%0A%7C%20%20%20%20%20%2234%22"],
+ }
+ init_tests(get_type());
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tables01.html b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tables01.html
new file mode 100644
index 00000000000..a22bfe0b2b2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tables01.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf8">
+ <title>HTML 5 Parser tests html5lib_tables01.html</title>
+ <meta name="timeout" content="long">
+ <meta name="variant" content="?run_type=uri">
+ <meta name="variant" content="?run_type=write">
+ <meta name="variant" content="?run_type=write_single">
+ </head>
+ <body>
+ <h1>html5lib Parser Test</h1>
+ <div id="log"></div>
+ <script src="common.js"></script>
+ <script src="test.js"></script>
+ <script src="template.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ var num_iframes = 8;
+ var order = ['86a267778d1960b41f887b7bd2cd3ebf691d2e42','b6c1142484570bb90c36e454ee193cca17bb618a','7c507b825650f9721ea9656b1e844752a2424271','d10316cac9d03820ecfbc85ab373632e12d70c75','331a8c15a2f1dd3a9a1c31f5c65b99d356a65f30','6cdb83f12cb37a56f5ebad018ec3b07c2ad5b89f','9d01d4a7d7519e410e10493c8b108298b6733c31','b4615709ab72b6aa6cbf836582bd40fd93c0deb5','24132334bffa9eea4c8e29c940a8201f4253baf5','103784c31b8e3280b19e30f3b26f467585fbc304','0787e31440ae020f6f6e6207c364e9a2daec1c6f','1c40461886d4fdfca6ac5ef1d766b6fbf360ff9c','aea3c063f853938a36184825893e0820b700e241','6595dc192b10c479a543dbe25e67e6e0b6923ea8','9fcd09d757401684bcc28eaec005ed82718e836f','4be18eaaf0aa53f224b4ff8aeaf47d44ba854260','8e743c4f0ab5783b8973533640f669c92acb3797',];
+ var tests = {
+ "86a267778d1960b41f887b7bd2cd3ebf691d2e42":[async_test('html5lib_tables01.html 86a267778d1960b41f887b7bd2cd3ebf691d2e42'), "%3Ctable%3E%3Cth%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cth%3E"],"b6c1142484570bb90c36e454ee193cca17bb618a":[async_test('html5lib_tables01.html b6c1142484570bb90c36e454ee193cca17bb618a'), "%3Ctable%3E%3Ctd%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E"],"7c507b825650f9721ea9656b1e844752a2424271":[async_test('html5lib_tables01.html 7c507b825650f9721ea9656b1e844752a2424271'), "%3Ctable%3E%3Ccol%20foo%3D%27bar%27%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ccolgroup%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ccol%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20foo%3D%22bar%22"],"d10316cac9d03820ecfbc85ab373632e12d70c75":[async_test('html5lib_tables01.html d10316cac9d03820ecfbc85ab373632e12d70c75'), "%3Ctable%3E%3Ccolgroup%3E%3C/html%3Efoo", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22foo%22%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ccolgroup%3E"],"331a8c15a2f1dd3a9a1c31f5c65b99d356a65f30":[async_test('html5lib_tables01.html 331a8c15a2f1dd3a9a1c31f5c65b99d356a65f30'), "%3Ctable%3E%3C/table%3E%3Cp%3Efoo", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%22foo%22"],"6cdb83f12cb37a56f5ebad018ec3b07c2ad5b89f":[async_test('html5lib_tables01.html 6cdb83f12cb37a56f5ebad018ec3b07c2ad5b89f'), "%3Ctable%3E%3C/body%3E%3C/caption%3E%3C/col%3E%3C/colgroup%3E%3C/html%3E%3C/tbody%3E%3C/td%3E%3C/tfoot%3E%3C/th%3E%3C/thead%3E%3C/tr%3E%3Ctd%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E"],"9d01d4a7d7519e410e10493c8b108298b6733c31":[async_test('html5lib_tables01.html 9d01d4a7d7519e410e10493c8b108298b6733c31'), "%3Ctable%3E%3Cselect%3E%3Coption%3E3%3C/select%3E%3C/table%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cselect%3E%0A%7C%20%20%20%20%20%20%20%3Coption%3E%0A%7C%20%20%20%20%20%20%20%20%20%223%22%0A%7C%20%20%20%20%20%3Ctable%3E"],"b4615709ab72b6aa6cbf836582bd40fd93c0deb5":[async_test('html5lib_tables01.html b4615709ab72b6aa6cbf836582bd40fd93c0deb5'), "%3Ctable%3E%3Cselect%3E%3Ctable%3E%3C/table%3E%3C/select%3E%3C/table%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cselect%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%3Ctable%3E"],"24132334bffa9eea4c8e29c940a8201f4253baf5":[async_test('html5lib_tables01.html 24132334bffa9eea4c8e29c940a8201f4253baf5'), "%3Ctable%3E%3Cselect%3E%3C/table%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cselect%3E%0A%7C%20%20%20%20%20%3Ctable%3E"],"103784c31b8e3280b19e30f3b26f467585fbc304":[async_test('html5lib_tables01.html 103784c31b8e3280b19e30f3b26f467585fbc304'), "%3Ctable%3E%3Cselect%3E%3Coption%3EA%3Ctr%3E%3Ctd%3EB%3C/td%3E%3C/tr%3E%3C/table%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cselect%3E%0A%7C%20%20%20%20%20%20%20%3Coption%3E%0A%7C%20%20%20%20%20%20%20%20%20%22A%22%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%22B%22"],"0787e31440ae020f6f6e6207c364e9a2daec1c6f":[async_test('html5lib_tables01.html 0787e31440ae020f6f6e6207c364e9a2daec1c6f'), "%3Ctable%3E%3Ctd%3E%3C/body%3E%3C/caption%3E%3C/col%3E%3C/colgroup%3E%3C/html%3Efoo", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%22foo%22"],"1c40461886d4fdfca6ac5ef1d766b6fbf360ff9c":[async_test('html5lib_tables01.html 1c40461886d4fdfca6ac5ef1d766b6fbf360ff9c'), "%3Ctable%3E%3Ctd%3EA%3C/table%3EB", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%22A%22%0A%7C%20%20%20%20%20%22B%22"],"aea3c063f853938a36184825893e0820b700e241":[async_test('html5lib_tables01.html aea3c063f853938a36184825893e0820b700e241'), "%3Ctable%3E%3Ctr%3E%3Ccaption%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%3Ccaption%3E"],"6595dc192b10c479a543dbe25e67e6e0b6923ea8":[async_test('html5lib_tables01.html 6595dc192b10c479a543dbe25e67e6e0b6923ea8'), "%3Ctable%3E%3Ctr%3E%3C/body%3E%3C/caption%3E%3C/col%3E%3C/colgroup%3E%3C/html%3E%3C/td%3E%3C/th%3E%3Ctd%3Efoo", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%22foo%22"],"9fcd09d757401684bcc28eaec005ed82718e836f":[async_test('html5lib_tables01.html 9fcd09d757401684bcc28eaec005ed82718e836f'), "%3Ctable%3E%3Ctd%3E%3Ctr%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E"],"4be18eaaf0aa53f224b4ff8aeaf47d44ba854260":[async_test('html5lib_tables01.html 4be18eaaf0aa53f224b4ff8aeaf47d44ba854260'), "%3Ctable%3E%3Ctd%3E%3Cbutton%3E%3Ctd%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cbutton%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E"],"8e743c4f0ab5783b8973533640f669c92acb3797":[async_test('html5lib_tables01.html 8e743c4f0ab5783b8973533640f669c92acb3797'), "%3Ctable%3E%3Ctr%3E%3Ctd%3E%3Csvg%3E%3Cdesc%3E%3Ctd%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Csvg%20desc%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E"],
+ }
+ init_tests(get_type());
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_template.html b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_template.html
new file mode 100644
index 00000000000..92500dd342f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_template.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf8">
+ <title>HTML 5 Parser tests html5lib_template.html</title>
+ <meta name="timeout" content="long">
+ <meta name="variant" content="?run_type=uri">
+ <meta name="variant" content="?run_type=write">
+ <meta name="variant" content="?run_type=write_single">
+ </head>
+ <body>
+ <h1>html5lib Parser Test</h1>
+ <div id="log"></div>
+ <script src="common.js"></script>
+ <script src="test.js"></script>
+ <script src="template.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ var num_iframes = 8;
+ var order = ['010950d55f4eccf16e9c4af1d263bb747294c646','a838bd54410cef059a42eea9606356488e16535b','27fb9111f6675a7e033b867480c0afddcda161a6','aee883a65775489399a003b2371d58248a6aff6f','89b17b54ab343191bf74ef5434f4d2cfac40ea97','c4433556c7414cfd71f27b420f1ffc4348774f5e','3dcce7d97108b3e9ea7fa96f240ac62bf280e74b','a1f587f7ea85ccfe294bd45bfb501e850cb979e0','cd26a7832f13bdc135697321ca6c2fecdca6ef5d','e30571d90b0e56864499961eb7be955994cf72e2','01cbe9f6a25f286b08d8dc4f7b65421e8eb3500c','96cbbcdffe02c86a8b929604c2fd5f3571a18dbe','d51676f55550e960dd0f5fa7fd0bdfa20bdde046','f9dfd9acfd494489c899604649a01d864741f50f','ea00361c265d3ffb47ce636d919c94ca10d58911','d8ebfcf7694c9d04457e796ac73049210313602e','b4d5e6fe9b92e2c8f54199d7cab3da383c42add0','07724ef8f7a4fa61c77ffcd5180d3101c4781502','e90f8aae8fc690540b42b3ffa3e741e7c1dfbf43','687bdf4adda88a316ec69fe20e84720acc5d1fe6','5b232642f472c2b4c0c7511fed464eebe686b427','dc1ac1830a881d1532a1e6fd6d0cfa56d6571da2','c58747a85e8b4f44d7ae63c04cdad783a903c25e','ca59bfdaec7451f704973176fab46e582bd691b2','cf807d6391a58c172b6c15c3b01d2a99ec0e6cf8','350b7ac850e46de79615308fc923649264406104','a31ff44edf7f377543dabdda8141cda9bb6de134','533c5c1b5f0d0cbb1ede2cc5ae927095c5b21f0b','61f79e083005007853c4f8e431559ac8d3845cfd','e802e85f36792b176b73c102c0e8761d9478621d','51d0797ff7653cd7be34458d689146e08a666c7f','d60e4079a18bd6266740cc61d1ca736e9d5098ce','308709292677b4d74c108a811ad7b7acd0bdfc9c','8965cdf9c4e9936262e25c90c7a7f8673840a445','7dccda789764beb489e09be10188af9347335d05','e15be51c77e1a6de35568a099ed339440ce9426d','503d3782e45940c19f096f360a092282b46ab1ea','b4ab56fd9e9cebf479d14adfa523c06d16483a5e','cd8bc9521f9683086a9e8529dd97314a6869daeb','f915e7b3407c24b28c3aad318e5693cc774020f4','3c5eb261787b3d15aff86fa61de773fd7e439b0e','2b57775750c198d4b98b23aed74ff80a866a01f5','dc3d016610f3ab532525a6c2871f03d6b62b0168','6a184d71d00580a26a8b6bd97aafe5503339f3f6','ce570a6c4bcee8b72a03e25508c6dd72e3cc6c35','e0c3d922f7b1f1654f02f716c3d9b31198ce3385','87e67242bf6debcf3b7dca852d10aa0f7b625b28','35ac4d4c972a01d368ed0cacb41370efef0a644d','5226c39dfc2d624ad4191b4eacb7e40c7ae528eb','aa90cd4db6b12e0a47341914a90cc536eec32d64','48af1faf5fcf48a0854af5a5c33656d9ccf6736b','ed3a029ba5e7f59969d65a4fc490a8f13b098cb9','6c8880d54475ad9574e203dcf2e55820b123cc64','275060925a844cb51b29bae660301de9780d68c8','9f82f6ec4c0a48c1d4dfbe6803b94abd553aea88','f094bf7e94a88b86c80a0643e70c8e5ff3354698','35a07ec3b4bf26ea407dc1ddf52f14195a714059','24faa53b271f994a4ff31d5796c8ff47d6f2c3e6','0f1c491b58c2dd3c402a62e37f833bc1f1db8d21','868d918a7b5d8b5c065c15229492bc2022bfbcba','0538efa44e857596c556033a3821d424378aea3f','e7d7bf3973c70d3cf9b0adad2ebed9f25be48d66','c69d0ac542d477b7312bb24981127b8aa8fdb1df','b496a8c13a7bd75b778bb0de489726aee952ae0c','5d6ee61de40274c9626ca78ee208d51276d5662d','9bd9687a65f258adc24450fc5cbd781fff6c038a','db1baeb846d718c773324746524fbd68f2e9436e','4b0ce46c611dbcc016db272ef007f302bee0c897','1a735e1c7f28f8701f3c7fd5e9404b8911916086','0686eedec06b2db1dc283fac92c1ef1a33114c71','d4dfb87ce626f12923056a6cd77448eaf4660ac2','1f295920f2937b2c8023b3761c43a0d4d9e5353c','3b91fa08fad923d387d924cff37fbf6b4c3a5712','45a1c1ad5d99ad67c573096a79253996a664e01b','0fe3a66773c6048c8f6f2c92f2611f65be972ec1','be40897ca411e1507197c31ab2a9f9752a05f769','dcfb1048ed5c40e406b4fbf0cde24c826713907f','78263aeea68ac97903598682013bae9c0c21d547','5aa177ef1a35bf4502dcb867d8e666288982ba99','5d303375907dc4d4380b477e0317c17b660613e9','d822f726927c34b92fe102b13e63920850878f6a','07acdcaeb4fa639296d46673cf28823ddf2a6ca7','58bd846ce1be0caf7560fba2ef19e2c2070ab123','8eeee377e5ab324731cc592f1fa8abe1045ad610','b30690019090149132fc228a7261c5cf2fd149fc','67a209d928804f90fdb66d070201b23f3d0c8a42','12104886b8f87daa937eac30b5ff0e1e074eaa6f','483cc9957a7225fe435112642be59abb4c459a1e','72d8ac431a154c40ab75d53a258d9d80d47689eb','1125967cbbcd404f4cb14d48270b8ec778970d77','32c963e164b9ec82c60e490bb141c1ccc70b992f','574a95fc9c9f2de3aeaa0c9ee1e6967fc3d4770d','332863a7f9e61bff32bd3427ede7a088b790d453','2121db07146781773df9e53b94fa921a805175ce','8675de267cd7e34f2febdee3feb665614d1562fe','c5d26ad923a2b1e988ddd378ca4fb26eb48353e1','eec1542e2fa0e9eafb7f8d4a51eae56b5a31b3c8','b79387a54c3b136db0f28ed96555ff683b3947fe','c477a29a4deb32d072a415fa809a84a4f2beee0c','26e4480c08e1f5f7b6ac8b8c1832ab0312e3b7c5','24b3b50fdd0bf8d5cf2ebaa6bf502d7bcfde1da4','d3704c68528357189eb5826ab66eea071d6137a5','d958f7d44faf772d1fb60f1a8f186f837ca735d9','3fc4d97fa68fc2658356bdbd4e051c867de8de53','94820107bbf3fab3f82de1f717e8413aead7d3a6','657c00ebdda37ae060cc69633ed98482ccc29e18',];
+ var tests = {
+ "010950d55f4eccf16e9c4af1d263bb747294c646":[async_test('html5lib_template.html 010950d55f4eccf16e9c4af1d263bb747294c646'), "%3Cbody%3E%3Ctemplate%3EHello%3C/template%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%22Hello%22"],"a838bd54410cef059a42eea9606356488e16535b":[async_test('html5lib_template.html a838bd54410cef059a42eea9606356488e16535b'), "%3Ctemplate%3EHello%3C/template%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%22Hello%22%0A%7C%20%20%20%3Cbody%3E"],"27fb9111f6675a7e033b867480c0afddcda161a6":[async_test('html5lib_template.html 27fb9111f6675a7e033b867480c0afddcda161a6'), "%3Ctemplate%3E%3C/template%3E%3Cdiv%3E%3C/div%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E"],"aee883a65775489399a003b2371d58248a6aff6f":[async_test('html5lib_template.html aee883a65775489399a003b2371d58248a6aff6f'), "%3Chtml%3E%3Ctemplate%3EHello%3C/template%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%22Hello%22%0A%7C%20%20%20%3Cbody%3E"],"89b17b54ab343191bf74ef5434f4d2cfac40ea97":[async_test('html5lib_template.html 89b17b54ab343191bf74ef5434f4d2cfac40ea97'), "%3Chead%3E%3Ctemplate%3E%3Cdiv%3E%3C/div%3E%3C/template%3E%3C/head%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%3Cbody%3E"],"c4433556c7414cfd71f27b420f1ffc4348774f5e":[async_test('html5lib_template.html c4433556c7414cfd71f27b420f1ffc4348774f5e'), "%3Cdiv%3E%3Ctemplate%3E%3Cdiv%3E%3Cspan%3E%3C/template%3E%3Cb%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cspan%3E%0A%7C%20%20%20%20%20%20%20%3Cb%3E"],"3dcce7d97108b3e9ea7fa96f240ac62bf280e74b":[async_test('html5lib_template.html 3dcce7d97108b3e9ea7fa96f240ac62bf280e74b'), "%3Cdiv%3E%3Ctemplate%3E%3C/div%3EHello", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22Hello%22"],"a1f587f7ea85ccfe294bd45bfb501e850cb979e0":[async_test('html5lib_template.html a1f587f7ea85ccfe294bd45bfb501e850cb979e0'), "%3Cdiv%3E%3C/template%3E%3C/div%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E"],"cd26a7832f13bdc135697321ca6c2fecdca6ef5d":[async_test('html5lib_template.html cd26a7832f13bdc135697321ca6c2fecdca6ef5d'), "%3Ctable%3E%3Ctemplate%3E%3C/template%3E%3C/table%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20content"],"e30571d90b0e56864499961eb7be955994cf72e2":[async_test('html5lib_template.html e30571d90b0e56864499961eb7be955994cf72e2'), "%3Ctable%3E%3Ctemplate%3E%3C/template%3E%3C/div%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20content"],"01cbe9f6a25f286b08d8dc4f7b65421e8eb3500c":[async_test('html5lib_template.html 01cbe9f6a25f286b08d8dc4f7b65421e8eb3500c'), "%3Ctable%3E%3Cdiv%3E%3Ctemplate%3E%3C/template%3E%3C/div%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%3Ctable%3E"],"96cbbcdffe02c86a8b929604c2fd5f3571a18dbe":[async_test('html5lib_template.html 96cbbcdffe02c86a8b929604c2fd5f3571a18dbe'), "%3Ctable%3E%3Ctemplate%3E%3C/template%3E%3Cdiv%3E%3C/div%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20content"],"d51676f55550e960dd0f5fa7fd0bdfa20bdde046":[async_test('html5lib_template.html d51676f55550e960dd0f5fa7fd0bdfa20bdde046'), "%3Ctable%3E%20%20%20%3Ctemplate%3E%3C/template%3E%3C/table%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%22%20%20%20%22%0A%7C%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20content"],"f9dfd9acfd494489c899604649a01d864741f50f":[async_test('html5lib_template.html f9dfd9acfd494489c899604649a01d864741f50f'), "%3Ctable%3E%3Ctbody%3E%3Ctemplate%3E%3C/template%3E%3C/tbody%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20content"],"ea00361c265d3ffb47ce636d919c94ca10d58911":[async_test('html5lib_template.html ea00361c265d3ffb47ce636d919c94ca10d58911'), "%3Ctable%3E%3Ctbody%3E%3Ctemplate%3E%3C/tbody%3E%3C/template%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20content"],"d8ebfcf7694c9d04457e796ac73049210313602e":[async_test('html5lib_template.html d8ebfcf7694c9d04457e796ac73049210313602e'), "%3Ctable%3E%3Ctbody%3E%3Ctemplate%3E%3C/template%3E%3C/tbody%3E%3C/table%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20content"],"b4d5e6fe9b92e2c8f54199d7cab3da383c42add0":[async_test('html5lib_template.html b4d5e6fe9b92e2c8f54199d7cab3da383c42add0'), "%3Ctable%3E%3Cthead%3E%3Ctemplate%3E%3C/template%3E%3C/thead%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Cthead%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20content"],"07724ef8f7a4fa61c77ffcd5180d3101c4781502":[async_test('html5lib_template.html 07724ef8f7a4fa61c77ffcd5180d3101c4781502'), "%3Ctable%3E%3Ctfoot%3E%3Ctemplate%3E%3C/template%3E%3C/tfoot%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctfoot%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20content"],"e90f8aae8fc690540b42b3ffa3e741e7c1dfbf43":[async_test('html5lib_template.html e90f8aae8fc690540b42b3ffa3e741e7c1dfbf43'), "%3Cselect%3E%3Ctemplate%3E%3C/template%3E%3C/select%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cselect%3E%0A%7C%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20content"],"687bdf4adda88a316ec69fe20e84720acc5d1fe6":[async_test('html5lib_template.html 687bdf4adda88a316ec69fe20e84720acc5d1fe6'), "%3Cselect%3E%3Ctemplate%3E%3Coption%3E%3C/option%3E%3C/template%3E%3C/select%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cselect%3E%0A%7C%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Coption%3E"],"5b232642f472c2b4c0c7511fed464eebe686b427":[async_test('html5lib_template.html 5b232642f472c2b4c0c7511fed464eebe686b427'), "%3Ctemplate%3E%3Coption%3E%3C/option%3E%3C/select%3E%3Coption%3E%3C/option%3E%3C/template%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Coption%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Coption%3E%0A%7C%20%20%20%3Cbody%3E"],"dc1ac1830a881d1532a1e6fd6d0cfa56d6571da2":[async_test('html5lib_template.html dc1ac1830a881d1532a1e6fd6d0cfa56d6571da2'), "%3Cselect%3E%3Ctemplate%3E%3C/template%3E%3Coption%3E%3C/select%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cselect%3E%0A%7C%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%3Coption%3E"],"c58747a85e8b4f44d7ae63c04cdad783a903c25e":[async_test('html5lib_template.html c58747a85e8b4f44d7ae63c04cdad783a903c25e'), "%3Cselect%3E%3Coption%3E%3Ctemplate%3E%3C/template%3E%3C/select%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cselect%3E%0A%7C%20%20%20%20%20%20%20%3Coption%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20content"],"ca59bfdaec7451f704973176fab46e582bd691b2":[async_test('html5lib_template.html ca59bfdaec7451f704973176fab46e582bd691b2'), "%3Cselect%3E%3Ctemplate%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cselect%3E%0A%7C%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20content"],"cf807d6391a58c172b6c15c3b01d2a99ec0e6cf8":[async_test('html5lib_template.html cf807d6391a58c172b6c15c3b01d2a99ec0e6cf8'), "%3Cselect%3E%3Coption%3E%3C/option%3E%3Ctemplate%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cselect%3E%0A%7C%20%20%20%20%20%20%20%3Coption%3E%0A%7C%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20content"],"350b7ac850e46de79615308fc923649264406104":[async_test('html5lib_template.html 350b7ac850e46de79615308fc923649264406104'), "%3Cselect%3E%3Coption%3E%3C/option%3E%3Ctemplate%3E%3Coption%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cselect%3E%0A%7C%20%20%20%20%20%20%20%3Coption%3E%0A%7C%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Coption%3E"],"a31ff44edf7f377543dabdda8141cda9bb6de134":[async_test('html5lib_template.html a31ff44edf7f377543dabdda8141cda9bb6de134'), "%3Ctable%3E%3Cthead%3E%3Ctemplate%3E%3Ctd%3E%3C/template%3E%3C/table%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Cthead%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E"],"533c5c1b5f0d0cbb1ede2cc5ae927095c5b21f0b":[async_test('html5lib_template.html 533c5c1b5f0d0cbb1ede2cc5ae927095c5b21f0b'), "%3Ctable%3E%3Ctemplate%3E%3Cthead%3E%3C/template%3E%3C/table%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cthead%3E"],"61f79e083005007853c4f8e431559ac8d3845cfd":[async_test('html5lib_template.html 61f79e083005007853c4f8e431559ac8d3845cfd'), "%3Cbody%3E%3Ctable%3E%3Ctemplate%3E%3Ctd%3E%3C/tr%3E%3Cdiv%3E%3C/template%3E%3C/table%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%3E"],"e802e85f36792b176b73c102c0e8761d9478621d":[async_test('html5lib_template.html e802e85f36792b176b73c102c0e8761d9478621d'), "%3Ctable%3E%3Ctemplate%3E%3Cthead%3E%3C/template%3E%3C/thead%3E%3C/table%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cthead%3E"],"51d0797ff7653cd7be34458d689146e08a666c7f":[async_test('html5lib_template.html 51d0797ff7653cd7be34458d689146e08a666c7f'), "%3Ctable%3E%3Cthead%3E%3Ctemplate%3E%3Ctr%3E%3C/template%3E%3C/table%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Cthead%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctr%3E"],"d60e4079a18bd6266740cc61d1ca736e9d5098ce":[async_test('html5lib_template.html d60e4079a18bd6266740cc61d1ca736e9d5098ce'), "%3Ctable%3E%3Ctemplate%3E%3Ctr%3E%3C/template%3E%3C/table%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctr%3E"],"308709292677b4d74c108a811ad7b7acd0bdfc9c":[async_test('html5lib_template.html 308709292677b4d74c108a811ad7b7acd0bdfc9c'), "%3Ctable%3E%3Ctr%3E%3Ctemplate%3E%3Ctd%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E"],"8965cdf9c4e9936262e25c90c7a7f8673840a445":[async_test('html5lib_template.html 8965cdf9c4e9936262e25c90c7a7f8673840a445'), "%3Ctable%3E%3Ctemplate%3E%3Ctr%3E%3Ctemplate%3E%3Ctd%3E%3C/template%3E%3C/tr%3E%3C/template%3E%3C/table%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E"],"7dccda789764beb489e09be10188af9347335d05":[async_test('html5lib_template.html 7dccda789764beb489e09be10188af9347335d05'), "%3Ctable%3E%3Ctemplate%3E%3Ctr%3E%3Ctemplate%3E%3Ctd%3E%3C/td%3E%3C/template%3E%3C/tr%3E%3C/template%3E%3C/table%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E"],"e15be51c77e1a6de35568a099ed339440ce9426d":[async_test('html5lib_template.html e15be51c77e1a6de35568a099ed339440ce9426d'), "%3Ctable%3E%3Ctemplate%3E%3Ctd%3E%3C/template%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E"],"503d3782e45940c19f096f360a092282b46ab1ea":[async_test('html5lib_template.html 503d3782e45940c19f096f360a092282b46ab1ea'), "%3Cbody%3E%3Ctemplate%3E%3Ctd%3E%3C/td%3E%3C/template%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Ctd%3E"],"b4ab56fd9e9cebf479d14adfa523c06d16483a5e":[async_test('html5lib_template.html b4ab56fd9e9cebf479d14adfa523c06d16483a5e'), "%3Cbody%3E%3Ctemplate%3E%3Ctemplate%3E%3Ctr%3E%3C/tr%3E%3C/template%3E%3Ctd%3E%3C/td%3E%3C/template%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctd%3E"],"cd8bc9521f9683086a9e8529dd97314a6869daeb":[async_test('html5lib_template.html cd8bc9521f9683086a9e8529dd97314a6869daeb'), "%3Ctable%3E%3Ccolgroup%3E%3Ctemplate%3E%3Ccol%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ccolgroup%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ccol%3E"],"f915e7b3407c24b28c3aad318e5693cc774020f4":[async_test('html5lib_template.html f915e7b3407c24b28c3aad318e5693cc774020f4'), "%3Cframeset%3E%3Ctemplate%3E%3Cframe%3E%3C/frame%3E%3C/template%3E%3C/frameset%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E%0A%7C%20%20%20%20%20%3Cframe%3E"],"3c5eb261787b3d15aff86fa61de773fd7e439b0e":[async_test('html5lib_template.html 3c5eb261787b3d15aff86fa61de773fd7e439b0e'), "%3Ctemplate%3E%3Cframe%3E%3C/frame%3E%3C/frameset%3E%3Cframe%3E%3C/frame%3E%3C/template%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%3Cbody%3E"],"2b57775750c198d4b98b23aed74ff80a866a01f5":[async_test('html5lib_template.html 2b57775750c198d4b98b23aed74ff80a866a01f5'), "%3Ctemplate%3E%3Cdiv%3E%3Cframeset%3E%3Cspan%3E%3C/span%3E%3C/div%3E%3Cspan%3E%3C/span%3E%3C/template%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cspan%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cspan%3E%0A%7C%20%20%20%3Cbody%3E"],"dc3d016610f3ab532525a6c2871f03d6b62b0168":[async_test('html5lib_template.html dc3d016610f3ab532525a6c2871f03d6b62b0168'), "%3Cbody%3E%3Ctemplate%3E%3Cdiv%3E%3Cframeset%3E%3Cspan%3E%3C/span%3E%3C/div%3E%3Cspan%3E%3C/span%3E%3C/template%3E%3C/body%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cspan%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cspan%3E"],"6a184d71d00580a26a8b6bd97aafe5503339f3f6":[async_test('html5lib_template.html 6a184d71d00580a26a8b6bd97aafe5503339f3f6'), "%3Cbody%3E%3Ctemplate%3E%3Cscript%3Evar%20i%20%3D%201%3B%3C/script%3E%3Ctd%3E%3C/td%3E%3C/template%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22var%20i%20%3D%201%3B%22%0A%7C%20%20%20%20%20%20%20%20%20%3Ctd%3E"],"ce570a6c4bcee8b72a03e25508c6dd72e3cc6c35":[async_test('html5lib_template.html ce570a6c4bcee8b72a03e25508c6dd72e3cc6c35'), "%3Cbody%3E%3Ctemplate%3E%3Ctr%3E%3Cdiv%3E%3C/div%3E%3C/tr%3E%3C/template%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cdiv%3E"],"e0c3d922f7b1f1654f02f716c3d9b31198ce3385":[async_test('html5lib_template.html e0c3d922f7b1f1654f02f716c3d9b31198ce3385'), "%3Cbody%3E%3Ctemplate%3E%3Ctr%3E%3C/tr%3E%3Ctd%3E%3C/td%3E%3C/template%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E"],"87e67242bf6debcf3b7dca852d10aa0f7b625b28":[async_test('html5lib_template.html 87e67242bf6debcf3b7dca852d10aa0f7b625b28'), "%3Cbody%3E%3Ctemplate%3E%3Ctd%3E%3C/td%3E%3C/tr%3E%3Ctd%3E%3C/td%3E%3C/template%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctd%3E"],"35ac4d4c972a01d368ed0cacb41370efef0a644d":[async_test('html5lib_template.html 35ac4d4c972a01d368ed0cacb41370efef0a644d'), "%3Cbody%3E%3Ctemplate%3E%3Ctd%3E%3C/td%3E%3Ctbody%3E%3Ctd%3E%3C/td%3E%3C/template%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctd%3E"],"5226c39dfc2d624ad4191b4eacb7e40c7ae528eb":[async_test('html5lib_template.html 5226c39dfc2d624ad4191b4eacb7e40c7ae528eb'), "%3Cbody%3E%3Ctemplate%3E%3Ctd%3E%3C/td%3E%3Ccaption%3E%3C/caption%3E%3Ctd%3E%3C/td%3E%3C/template%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctd%3E"],"aa90cd4db6b12e0a47341914a90cc536eec32d64":[async_test('html5lib_template.html aa90cd4db6b12e0a47341914a90cc536eec32d64'), "%3Cbody%3E%3Ctemplate%3E%3Ctd%3E%3C/td%3E%3Ccolgroup%3E%3C/caption%3E%3Ctd%3E%3C/td%3E%3C/template%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctd%3E"],"48af1faf5fcf48a0854af5a5c33656d9ccf6736b":[async_test('html5lib_template.html 48af1faf5fcf48a0854af5a5c33656d9ccf6736b'), "%3Cbody%3E%3Ctemplate%3E%3Ctd%3E%3C/td%3E%3C/table%3E%3Ctd%3E%3C/td%3E%3C/template%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctd%3E"],"ed3a029ba5e7f59969d65a4fc490a8f13b098cb9":[async_test('html5lib_template.html ed3a029ba5e7f59969d65a4fc490a8f13b098cb9'), "%3Cbody%3E%3Ctemplate%3E%3Ctr%3E%3C/tr%3E%3Ctbody%3E%3Ctr%3E%3C/tr%3E%3C/template%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E"],"6c8880d54475ad9574e203dcf2e55820b123cc64":[async_test('html5lib_template.html 6c8880d54475ad9574e203dcf2e55820b123cc64'), "%3Cbody%3E%3Ctemplate%3E%3Ctr%3E%3C/tr%3E%3Ccaption%3E%3Ctr%3E%3C/tr%3E%3C/template%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E"],"275060925a844cb51b29bae660301de9780d68c8":[async_test('html5lib_template.html 275060925a844cb51b29bae660301de9780d68c8'), "%3Cbody%3E%3Ctemplate%3E%3Ctr%3E%3C/tr%3E%3C/table%3E%3Ctr%3E%3C/tr%3E%3C/template%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E"],"9f82f6ec4c0a48c1d4dfbe6803b94abd553aea88":[async_test('html5lib_template.html 9f82f6ec4c0a48c1d4dfbe6803b94abd553aea88'), "%3Cbody%3E%3Ctemplate%3E%3Cthead%3E%3C/thead%3E%3Ccaption%3E%3C/caption%3E%3Ctbody%3E%3C/tbody%3E%3C/template%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Cthead%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ccaption%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctbody%3E"],"f094bf7e94a88b86c80a0643e70c8e5ff3354698":[async_test('html5lib_template.html f094bf7e94a88b86c80a0643e70c8e5ff3354698'), "%3Cbody%3E%3Ctemplate%3E%3Cthead%3E%3C/thead%3E%3C/table%3E%3Ctbody%3E%3C/tbody%3E%3C/template%3E%3C/body%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Cthead%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctbody%3E"],"35a07ec3b4bf26ea407dc1ddf52f14195a714059":[async_test('html5lib_template.html 35a07ec3b4bf26ea407dc1ddf52f14195a714059'), "%3Cbody%3E%3Ctemplate%3E%3Cdiv%3E%3Ctr%3E%3C/tr%3E%3C/div%3E%3C/template%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Cdiv%3E"],"24faa53b271f994a4ff31d5796c8ff47d6f2c3e6":[async_test('html5lib_template.html 24faa53b271f994a4ff31d5796c8ff47d6f2c3e6'), "%3Cbody%3E%3Ctemplate%3E%3Cem%3EHello%3C/em%3E%3C/template%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Cem%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22Hello%22"],"0f1c491b58c2dd3c402a62e37f833bc1f1db8d21":[async_test('html5lib_template.html 0f1c491b58c2dd3c402a62e37f833bc1f1db8d21'), "%3Cbody%3E%3Ctemplate%3E%3C%21--comment--%3E%3C/template%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3C%21--%20comment%20--%3E"],"868d918a7b5d8b5c065c15229492bc2022bfbcba":[async_test('html5lib_template.html 868d918a7b5d8b5c065c15229492bc2022bfbcba'), "%3Cbody%3E%3Ctemplate%3E%3Cstyle%3E%3C/style%3E%3Ctd%3E%3C/td%3E%3C/template%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Cstyle%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctd%3E"],"0538efa44e857596c556033a3821d424378aea3f":[async_test('html5lib_template.html 0538efa44e857596c556033a3821d424378aea3f'), "%3Cbody%3E%3Ctemplate%3E%3Cmeta%3E%3Ctd%3E%3C/td%3E%3C/template%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Cmeta%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctd%3E"],"e7d7bf3973c70d3cf9b0adad2ebed9f25be48d66":[async_test('html5lib_template.html e7d7bf3973c70d3cf9b0adad2ebed9f25be48d66'), "%3Cbody%3E%3Ctemplate%3E%3Clink%3E%3Ctd%3E%3C/td%3E%3C/template%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Clink%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctd%3E"],"c69d0ac542d477b7312bb24981127b8aa8fdb1df":[async_test('html5lib_template.html c69d0ac542d477b7312bb24981127b8aa8fdb1df'), "%3Cbody%3E%3Ctable%3E%3Ccolgroup%3E%3Ctemplate%3E%3Ccol%3E%3C/col%3E%3C/template%3E%3C/colgroup%3E%3C/table%3E%3C/body%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ccolgroup%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ccol%3E"],"b496a8c13a7bd75b778bb0de489726aee952ae0c":[async_test('html5lib_template.html b496a8c13a7bd75b778bb0de489726aee952ae0c'), "%3Cbody%20a%3Db%3E%3Ctemplate%3E%3Cdiv%3E%3C/div%3E%3Cbody%20c%3Dd%3E%3Cdiv%3E%3C/div%3E%3C/body%3E%3C/template%3E%3C/body%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20a%3D%22b%22%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cdiv%3E"],"5d6ee61de40274c9626ca78ee208d51276d5662d":[async_test('html5lib_template.html 5d6ee61de40274c9626ca78ee208d51276d5662d'), "%3Chtml%20a%3Db%3E%3Ctemplate%3E%3Cdiv%3E%3Chtml%20b%3Dc%3E%3Cspan%3E%3C/template%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20a%3D%22b%22%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cspan%3E%0A%7C%20%20%20%3Cbody%3E"],"9bd9687a65f258adc24450fc5cbd781fff6c038a":[async_test('html5lib_template.html 9bd9687a65f258adc24450fc5cbd781fff6c038a'), "%3Chtml%20a%3Db%3E%3Ctemplate%3E%3Ccol%3E%3C/col%3E%3Chtml%20b%3Dc%3E%3Ccol%3E%3C/col%3E%3C/template%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20a%3D%22b%22%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Ccol%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ccol%3E%0A%7C%20%20%20%3Cbody%3E"],"db1baeb846d718c773324746524fbd68f2e9436e":[async_test('html5lib_template.html db1baeb846d718c773324746524fbd68f2e9436e'), "%3Chtml%20a%3Db%3E%3Ctemplate%3E%3Cframe%3E%3C/frame%3E%3Chtml%20b%3Dc%3E%3Cframe%3E%3C/frame%3E%3C/template%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20a%3D%22b%22%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%3Cbody%3E"],"4b0ce46c611dbcc016db272ef007f302bee0c897":[async_test('html5lib_template.html 4b0ce46c611dbcc016db272ef007f302bee0c897'), "%3Cbody%3E%3Ctemplate%3E%3Ctr%3E%3C/tr%3E%3Ctemplate%3E%3C/template%3E%3Ctd%3E%3C/td%3E%3C/template%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E"],"1a735e1c7f28f8701f3c7fd5e9404b8911916086":[async_test('html5lib_template.html 1a735e1c7f28f8701f3c7fd5e9404b8911916086'), "%3Cbody%3E%3Ctemplate%3E%3Cthead%3E%3C/thead%3E%3Ctemplate%3E%3Ctr%3E%3C/tr%3E%3C/template%3E%3Ctr%3E%3C/tr%3E%3Ctfoot%3E%3C/tfoot%3E%3C/template%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Cthead%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctfoot%3E"],"0686eedec06b2db1dc283fac92c1ef1a33114c71":[async_test('html5lib_template.html 0686eedec06b2db1dc283fac92c1ef1a33114c71'), "%3Cbody%3E%3Ctemplate%3E%3Ctemplate%3E%3Cb%3E%3Ctemplate%3E%3C/template%3E%3C/template%3Etext%3C/template%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%22text%22"],"d4dfb87ce626f12923056a6cd77448eaf4660ac2":[async_test('html5lib_template.html d4dfb87ce626f12923056a6cd77448eaf4660ac2'), "%3Cbody%3E%3Ctemplate%3E%3Ccol%3E%3Ccolgroup%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Ccol%3E"],"1f295920f2937b2c8023b3761c43a0d4d9e5353c":[async_test('html5lib_template.html 1f295920f2937b2c8023b3761c43a0d4d9e5353c'), "%3Cbody%3E%3Ctemplate%3E%3Ccol%3E%3C/colgroup%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Ccol%3E"],"3b91fa08fad923d387d924cff37fbf6b4c3a5712":[async_test('html5lib_template.html 3b91fa08fad923d387d924cff37fbf6b4c3a5712'), "%3Cbody%3E%3Ctemplate%3E%3Ccol%3E%3Ccolgroup%3E%3C/template%3E%3C/body%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Ccol%3E"],"45a1c1ad5d99ad67c573096a79253996a664e01b":[async_test('html5lib_template.html 45a1c1ad5d99ad67c573096a79253996a664e01b'), "%3Cbody%3E%3Ctemplate%3E%3Ccol%3E%3Cdiv%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Ccol%3E"],"0fe3a66773c6048c8f6f2c92f2611f65be972ec1":[async_test('html5lib_template.html 0fe3a66773c6048c8f6f2c92f2611f65be972ec1'), "%3Cbody%3E%3Ctemplate%3E%3Ccol%3E%3C/div%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Ccol%3E"],"be40897ca411e1507197c31ab2a9f9752a05f769":[async_test('html5lib_template.html be40897ca411e1507197c31ab2a9f9752a05f769'), "%3Cbody%3E%3Ctemplate%3E%3Ccol%3EHello", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Ccol%3E"],"dcfb1048ed5c40e406b4fbf0cde24c826713907f":[async_test('html5lib_template.html dcfb1048ed5c40e406b4fbf0cde24c826713907f'), "%3Cbody%3E%3Ctemplate%3E%3Ci%3E%3Cmenu%3EFoo%3C/i%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cmenu%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%22Foo%22"],"78263aeea68ac97903598682013bae9c0c21d547":[async_test('html5lib_template.html 78263aeea68ac97903598682013bae9c0c21d547'), "%3Cbody%3E%3Ctemplate%3E%3C/div%3E%3Cdiv%3EFoo%3C/div%3E%3Ctemplate%3E%3C/template%3E%3Ctr%3E%3C/tr%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22Foo%22%0A%7C%20%20%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20content"],"5aa177ef1a35bf4502dcb867d8e666288982ba99":[async_test('html5lib_template.html 5aa177ef1a35bf4502dcb867d8e666288982ba99'), "%3Cbody%3E%3Cdiv%3E%3Ctemplate%3E%3C/div%3E%3Ctr%3E%3Ctd%3EFoo%3C/td%3E%3C/tr%3E%3C/template%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22Foo%22"],"5d303375907dc4d4380b477e0317c17b660613e9":[async_test('html5lib_template.html 5d303375907dc4d4380b477e0317c17b660613e9'), "%3Ctemplate%3E%3C/figcaption%3E%3Csub%3E%3Ctable%3E%3C/table%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Csub%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%3Cbody%3E"],"d822f726927c34b92fe102b13e63920850878f6a":[async_test('html5lib_template.html d822f726927c34b92fe102b13e63920850878f6a'), "%3Ctemplate%3E%3Ctemplate%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20content%0A%7C%20%20%20%3Cbody%3E"],"07acdcaeb4fa639296d46673cf28823ddf2a6ca7":[async_test('html5lib_template.html 07acdcaeb4fa639296d46673cf28823ddf2a6ca7'), "%3Ctemplate%3E%3Cdiv%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%3Cbody%3E"],"58bd846ce1be0caf7560fba2ef19e2c2070ab123":[async_test('html5lib_template.html 58bd846ce1be0caf7560fba2ef19e2c2070ab123'), "%3Ctemplate%3E%3Ctemplate%3E%3Cdiv%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%3Cbody%3E"],"8eeee377e5ab324731cc592f1fa8abe1045ad610":[async_test('html5lib_template.html 8eeee377e5ab324731cc592f1fa8abe1045ad610'), "%3Ctemplate%3E%3Ctemplate%3E%3Ctable%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%3Cbody%3E"],"b30690019090149132fc228a7261c5cf2fd149fc":[async_test('html5lib_template.html b30690019090149132fc228a7261c5cf2fd149fc'), "%3Ctemplate%3E%3Ctemplate%3E%3Ctbody%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%3Cbody%3E"],"67a209d928804f90fdb66d070201b23f3d0c8a42":[async_test('html5lib_template.html 67a209d928804f90fdb66d070201b23f3d0c8a42'), "%3Ctemplate%3E%3Ctemplate%3E%3Ctr%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%3Cbody%3E"],"12104886b8f87daa937eac30b5ff0e1e074eaa6f":[async_test('html5lib_template.html 12104886b8f87daa937eac30b5ff0e1e074eaa6f'), "%3Ctemplate%3E%3Ctemplate%3E%3Ctd%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%3Cbody%3E"],"483cc9957a7225fe435112642be59abb4c459a1e":[async_test('html5lib_template.html 483cc9957a7225fe435112642be59abb4c459a1e'), "%3Ctemplate%3E%3Ctemplate%3E%3Ccaption%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ccaption%3E%0A%7C%20%20%20%3Cbody%3E"],"72d8ac431a154c40ab75d53a258d9d80d47689eb":[async_test('html5lib_template.html 72d8ac431a154c40ab75d53a258d9d80d47689eb'), "%3Ctemplate%3E%3Ctemplate%3E%3Ccolgroup%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ccolgroup%3E%0A%7C%20%20%20%3Cbody%3E"],"1125967cbbcd404f4cb14d48270b8ec778970d77":[async_test('html5lib_template.html 1125967cbbcd404f4cb14d48270b8ec778970d77'), "%3Ctemplate%3E%3Ctemplate%3E%3Ccol%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ccol%3E%0A%7C%20%20%20%3Cbody%3E"],"32c963e164b9ec82c60e490bb141c1ccc70b992f":[async_test('html5lib_template.html 32c963e164b9ec82c60e490bb141c1ccc70b992f'), "%3Ctemplate%3E%3Ctemplate%3E%3Ctbody%3E%3Cselect%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cselect%3E%0A%7C%20%20%20%3Cbody%3E"],"574a95fc9c9f2de3aeaa0c9ee1e6967fc3d4770d":[async_test('html5lib_template.html 574a95fc9c9f2de3aeaa0c9ee1e6967fc3d4770d'), "%3Ctemplate%3E%3Ctemplate%3E%3Ctable%3EFoo", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%22Foo%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%3Cbody%3E"],"332863a7f9e61bff32bd3427ede7a088b790d453":[async_test('html5lib_template.html 332863a7f9e61bff32bd3427ede7a088b790d453'), "%3Ctemplate%3E%3Ctemplate%3E%3Cframe%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20content%0A%7C%20%20%20%3Cbody%3E"],"2121db07146781773df9e53b94fa921a805175ce":[async_test('html5lib_template.html 2121db07146781773df9e53b94fa921a805175ce'), "%3Ctemplate%3E%3Ctemplate%3E%3Cscript%3Evar%20i", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22var%20i%22%0A%7C%20%20%20%3Cbody%3E"],"8675de267cd7e34f2febdee3feb665614d1562fe":[async_test('html5lib_template.html 8675de267cd7e34f2febdee3feb665614d1562fe'), "%3Ctemplate%3E%3Ctemplate%3E%3Cstyle%3Evar%20i", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cstyle%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22var%20i%22%0A%7C%20%20%20%3Cbody%3E"],"c5d26ad923a2b1e988ddd378ca4fb26eb48353e1":[async_test('html5lib_template.html c5d26ad923a2b1e988ddd378ca4fb26eb48353e1'), "%3Ctemplate%3E%3Ctable%3E%3C/template%3E%3Cbody%3E%3Cspan%3EFoo", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cspan%3E%0A%7C%20%20%20%20%20%20%20%22Foo%22"],"eec1542e2fa0e9eafb7f8d4a51eae56b5a31b3c8":[async_test('html5lib_template.html eec1542e2fa0e9eafb7f8d4a51eae56b5a31b3c8'), "%3Ctemplate%3E%3Ctd%3E%3C/template%3E%3Cbody%3E%3Cspan%3EFoo", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cspan%3E%0A%7C%20%20%20%20%20%20%20%22Foo%22"],"b79387a54c3b136db0f28ed96555ff683b3947fe":[async_test('html5lib_template.html b79387a54c3b136db0f28ed96555ff683b3947fe'), "%3Ctemplate%3E%3Cobject%3E%3C/template%3E%3Cbody%3E%3Cspan%3EFoo", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Cobject%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cspan%3E%0A%7C%20%20%20%20%20%20%20%22Foo%22"],"c477a29a4deb32d072a415fa809a84a4f2beee0c":[async_test('html5lib_template.html c477a29a4deb32d072a415fa809a84a4f2beee0c'), "%3Ctemplate%3E%3Csvg%3E%3Ctemplate%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Csvg%20template%3E%0A%7C%20%20%20%3Cbody%3E"],"26e4480c08e1f5f7b6ac8b8c1832ab0312e3b7c5":[async_test('html5lib_template.html 26e4480c08e1f5f7b6ac8b8c1832ab0312e3b7c5'), "%3Ctemplate%3E%3Csvg%3E%3Cfoo%3E%3Ctemplate%3E%3CforeignObject%3E%3Cdiv%3E%3C/template%3E%3Cdiv%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Csvg%20foo%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Csvg%20template%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Csvg%20foreignObject%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E"],"24b3b50fdd0bf8d5cf2ebaa6bf502d7bcfde1da4":[async_test('html5lib_template.html 24b3b50fdd0bf8d5cf2ebaa6bf502d7bcfde1da4'), "%3Cdummy%3E%3Ctemplate%3E%3Cspan%3E%3C/dummy%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdummy%3E%0A%7C%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cspan%3E"],"d3704c68528357189eb5826ab66eea071d6137a5":[async_test('html5lib_template.html d3704c68528357189eb5826ab66eea071d6137a5'), "%3Cbody%3E%3Ctable%3E%3Ctr%3E%3Ctd%3E%3Cselect%3E%3Ctemplate%3EFoo%3C/template%3E%3Ccaption%3EA%3C/table%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cselect%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22Foo%22%0A%7C%20%20%20%20%20%20%20%3Ccaption%3E%0A%7C%20%20%20%20%20%20%20%20%20%22A%22"],"d958f7d44faf772d1fb60f1a8f186f837ca735d9":[async_test('html5lib_template.html d958f7d44faf772d1fb60f1a8f186f837ca735d9'), "%3Cbody%3E%3C/body%3E%3Ctemplate%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content"],"3fc4d97fa68fc2658356bdbd4e051c867de8de53":[async_test('html5lib_template.html 3fc4d97fa68fc2658356bdbd4e051c867de8de53'), "%3Chead%3E%3C/head%3E%3Ctemplate%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%3Cbody%3E"],"94820107bbf3fab3f82de1f717e8413aead7d3a6":[async_test('html5lib_template.html 94820107bbf3fab3f82de1f717e8413aead7d3a6'), "%3Chead%3E%3C/head%3E%3Ctemplate%3EFoo%3C/template%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%22Foo%22%0A%7C%20%20%20%3Cbody%3E"],"657c00ebdda37ae060cc69633ed98482ccc29e18":[async_test('html5lib_template.html 657c00ebdda37ae060cc69633ed98482ccc29e18'), "%3C%21DOCTYPE%20HTML%3E%3Cdummy%3E%3Ctable%3E%3Ctemplate%3E%3Ctable%3E%3Ctemplate%3E%3Ctable%3E%3Cscript%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdummy%3E%0A%7C%20%20%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctemplate%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20content%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cscript%3E"],
+ }
+ init_tests(get_type());
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests1.html b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests1.html
new file mode 100644
index 00000000000..fa658fc7682
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests1.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf8">
+ <title>HTML 5 Parser tests html5lib_tests1.html</title>
+ <meta name="timeout" content="long">
+ <meta name="variant" content="?run_type=uri">
+ <meta name="variant" content="?run_type=write">
+ <meta name="variant" content="?run_type=write_single">
+ </head>
+ <body>
+ <h1>html5lib Parser Test</h1>
+ <div id="log"></div>
+ <script src="common.js"></script>
+ <script src="test.js"></script>
+ <script src="template.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ var num_iframes = 8;
+ var order = ['4235382bf15f93f7dd1096832ae74cc71edef4d7','ad8515e9db0abd26469d0d2e46b42cebf606d4f3','2433aa5c088d78da9e7824e499f639177f56625d','c99d322c3502e38e9d18ac6c0180fa5462ce612e','d8473f7b5cec9d99526179f980ebf55a0beccbd3','ac7703fbb5c62cadb25024aed762c206c187a919','a00121213e2eb2c846a575f662e8c69389bfc44d','447f22e6a43ddbbc308afbc78b64b16452bc7bbb','cdac424e0f2fb979f21a64f50793d529375c01b3','63587d177231d2478a6ffd25f3c830fed7cc2efe','a3e13da13681f9f16c65334099136f3b5c235e6d','b7a06a5aa0c19d7914b853f5ed497743bb269e56','3d28b753b97f460868ca65ed8fc153021a815b8c','83cce5b1e1e49c92c618aabf1ed60926a8736456','b9e809bc4521004440bf558c7dc5d7dc1ae3dd40','60302916ab9a2128104dbf72629875ad19b5cb16','f4ad8e574fcac3bb08070eeb345855ea7081ea1d','d38fe13d87344a20bdf6e111988b5a09ed247913','e5f2e91cbff6a4bc56149b889f4f9396e455c5ad','18b58d1de184b6866963c902ff8451dd3522f540','88eb93691065e212a4323f55ec326585c7c44262','260db4c31fb80894beb825c4793e6142f178497d','59d9c5e2941952f7af99ed3e21d66e4fdb1df07c','1e788677da8eb26f560409392ff674744c6f8b64','240ee32b47e30bcf34483c7a7530cfeb99a6d1f1','e85dc012a49630206e6163cd1e0fd6c706865106','c440d1f0223d6b3ce85955d8246fdd47ecdfb034','9a2ce05a0b342b377ef054385131ad4d1b5ae84b','daa9d8440e2bc4d560536b52123b01e52aa81692','0b27e026dd03a356bbd78690fff7fb40cd63b606','a2d3321d1ea23b55d9117e5c2014e4ab0fa5e224','cc9c12dd44b43fa78ad340a91d20432e3f119c19','3d0cb9632b521a3fb334f567b3cdec985e85abd7','f158c8b44e4cdf872cc5bb4d148fad3ff27ea03f','1dfb5ce6c1a10d870a35b24314976d887c700c42','1fc4fad5eead893c51be2b6aa1d705cd58ebcfe9','f85417e345053cf627abf572911c0f7ffefe16c8','277ea1a5aade6c61a8386ff73086a91160caf5a2','32714c0ca1bae661ba9342ef275b2e6e5e025c34','619aa593419925064f51b0602000a2b9d13a8bc3','40fd9f6e4a08a69596f0dc0846d44ebd39e4913d','82120b3520ad73b9e11a413631e6f015ed0cf265','a9f265e67b901f8d41ece9bb631696795327ed50','6325e1d53c83784c1e5092861c8b0138fb4871ad','451c02faba02d2768e3497fdcc8ffb0dec41640d','fefda3429288aa79b4c9e8e9e3ba97897d0783c8','6328f70bb445e1dd692c36d6c92e2a2a7ed6ee0f','287320444eec6e3b4481d33738f971b696a2d6f0','65ea3a80efc973b5cd92c1db5a4520365bbb5478','d60de29dd2f3e8a080882986d6689d74fb981619','343048017f1928db8ba4c0b45a4f1dd3dadf3063','cf14f5563275bac3fe2c77f8973e882e51965b5b','2d8f9308951237fd0dcba3ff7709369cfd7563fd','87421a25ca75e2d6a165eb981921235f4de9210a','30d87693aead287d5a63310d2f819623455f4133','20d7a996a47fab66aead30ed7012d50b990dc65d','258c0966cc576ec8a563e41e783fa34f6b5c8baf','f7ee5b858e93b22e1594d6d8cd0bc0def665ac02','6d9127103f8733d168e69cf04b576a7b0bea3d5c','03db7399a2d674955930611fdbcaad9f4064243a','a0a1dcb330314ce12af02d136319a1be6a1ffa53','09b3483ef5f7a83aa9e3224d0335b6f9aa78ac73','34d56f09a1a9c0f51a8abc41be2f157faf0e8d15','dffa0785e6c80af52950a64d8612633de58bbb29','076e6ac3cb344d60f6ce9a5188cf103ff053830c','5f14cb9c8502f09105ad83e27842625c70f3857d','25172f395b855b6eeb61ff95a8162a34ca92195e','053beabf01d70d03a0ca61b809d5d986ddf2ea3d','bd385dbe93b192c2182e09e75d3664b96845ea0a','2ddaacb4f4e566ae79af5259f57f5b4dd166c19f','d430f2fc3bd20e658ed00b55e6c27f14204a7b6f','bbdb0a08b66b0789068ddac96a05ac39e104553d','37ed2a3a96026e7a78f6675154d11746aa9484e0','4177a74406cf1c048d2d6d6bcf774445f55ba517','fc188652d9f486174b21d1919f35ea8c13636ca1','c10f83cc69763e42964e08ddb976a1bd27b51e2f','64452c62ced87bd3cd8fd88df33a33d5531818d6','96dc04673021ad113df40397113df972f090c1f6','26b7eb0b18d9cd0a69d19c7f6ee9f12c2d0b2783','f8d500cd7089942814fa0751c75bd37e63790685','3b386c205ec767f842e63491d14ec90192f562dd','ca8ecc666a82d1f2f48a095d42d9f95700e015bd','6727ab7c4240bf05f0a5d9ca4b384ca8d61e2d4f','3ad08edf5b9690be261dc375da3b1d9ec82e499a','06ed0f32cfd261010c9d810ff8317ef96b47c04c','44ea84c7e4e401c9d3f96d7cc39709e4be81edc8','67af290f1b04c4b1a67131edba1ee832c690432c','2f1899f72fafcb062418e8ce892188040de4708c','ed2a4958c832ef6cec993cb52afc808132714d0a','c7943ccd9d880664b0894a2035e1f2a837f37c7a','bbc836b1f494223d4eb8982930d693489d135740','617fdf08035740698b2f0f4c3874dbb469fd1848','e901fe2093e51eccb4d9d23103214bc527af265c','63970995ab6b8aee63de9e7a7667178d4fc86820','d7607fdd41625431bcbee319a86db1b73fc49edd','ce31a583a3921e306aaa558b1ea798b34d2bb0dc','04ba864e740f7ef104570ddc6af834e6336031ed','ea6ab4a56efd19cc04b5656583ea6d5c9cfd2752','1bb5dfba014f63c0a18b12097ed9a28d64552e07','a2dd4d5a28a61ec99ce9dae35e9d4ffe92812e2f','e26f001557952154c308e3e6f6d1789cf711ef27','34c1f9c212198edd7baf56e658db21d98c59f74c','e1c47adbde197e3eaa9504f3582fd9deac1cbbff','0f5aba4c1ed57ac3c6a2774f3bf43ef598bd9915','d11ff75681c4df2ff24ad731ff244afc3e1c87af','fa392f5dd6f2f6a73635c06208c8989caa874588','5815b2afbb0a7f4756af7914407f71f469658f38','a100bb6a2a80bec65c418d672144b6f647fbd46b','f66797fd63c8b0254b4ef28e9c38c3d4e512c93c','f10a41faca4cf01e39ed92c4eefff0631d1195dc','5d14e20ae19e0b3e14dcb997e3ccad5f0e1956e1','1949f8c612e660985fb5eb28235b6f9386ed4ffc',];
+ var tests = {
+ "4235382bf15f93f7dd1096832ae74cc71edef4d7":[async_test('html5lib_tests1.html 4235382bf15f93f7dd1096832ae74cc71edef4d7'), "Test", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22Test%22"],"ad8515e9db0abd26469d0d2e46b42cebf606d4f3":[async_test('html5lib_tests1.html ad8515e9db0abd26469d0d2e46b42cebf606d4f3'), "%3Cp%3EOne%3Cp%3ETwo", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%22One%22%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%22Two%22"],"2433aa5c088d78da9e7824e499f639177f56625d":[async_test('html5lib_tests1.html 2433aa5c088d78da9e7824e499f639177f56625d'), "Line1%3Cbr%3ELine2%3Cbr%3ELine3%3Cbr%3ELine4", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22Line1%22%0A%7C%20%20%20%20%20%3Cbr%3E%0A%7C%20%20%20%20%20%22Line2%22%0A%7C%20%20%20%20%20%3Cbr%3E%0A%7C%20%20%20%20%20%22Line3%22%0A%7C%20%20%20%20%20%3Cbr%3E%0A%7C%20%20%20%20%20%22Line4%22"],"c99d322c3502e38e9d18ac6c0180fa5462ce612e":[async_test('html5lib_tests1.html c99d322c3502e38e9d18ac6c0180fa5462ce612e'), "%3Chtml%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"d8473f7b5cec9d99526179f980ebf55a0beccbd3":[async_test('html5lib_tests1.html d8473f7b5cec9d99526179f980ebf55a0beccbd3'), "%3Chead%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"ac7703fbb5c62cadb25024aed762c206c187a919":[async_test('html5lib_tests1.html ac7703fbb5c62cadb25024aed762c206c187a919'), "%3Cbody%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"a00121213e2eb2c846a575f662e8c69389bfc44d":[async_test('html5lib_tests1.html a00121213e2eb2c846a575f662e8c69389bfc44d'), "%3Chtml%3E%3Chead%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"447f22e6a43ddbbc308afbc78b64b16452bc7bbb":[async_test('html5lib_tests1.html 447f22e6a43ddbbc308afbc78b64b16452bc7bbb'), "%3Chtml%3E%3Chead%3E%3C/head%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"cdac424e0f2fb979f21a64f50793d529375c01b3":[async_test('html5lib_tests1.html cdac424e0f2fb979f21a64f50793d529375c01b3'), "%3Chtml%3E%3Chead%3E%3C/head%3E%3Cbody%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"63587d177231d2478a6ffd25f3c830fed7cc2efe":[async_test('html5lib_tests1.html 63587d177231d2478a6ffd25f3c830fed7cc2efe'), "%3Chtml%3E%3Chead%3E%3C/head%3E%3Cbody%3E%3C/body%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"a3e13da13681f9f16c65334099136f3b5c235e6d":[async_test('html5lib_tests1.html a3e13da13681f9f16c65334099136f3b5c235e6d'), "%3Chtml%3E%3Chead%3E%3Cbody%3E%3C/body%3E%3C/html%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"b7a06a5aa0c19d7914b853f5ed497743bb269e56":[async_test('html5lib_tests1.html b7a06a5aa0c19d7914b853f5ed497743bb269e56'), "%3Chtml%3E%3Chead%3E%3C/body%3E%3C/html%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"3d28b753b97f460868ca65ed8fc153021a815b8c":[async_test('html5lib_tests1.html 3d28b753b97f460868ca65ed8fc153021a815b8c'), "%3Chtml%3E%3Chead%3E%3Cbody%3E%3C/html%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"83cce5b1e1e49c92c618aabf1ed60926a8736456":[async_test('html5lib_tests1.html 83cce5b1e1e49c92c618aabf1ed60926a8736456'), "%3Chtml%3E%3Cbody%3E%3C/html%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"b9e809bc4521004440bf558c7dc5d7dc1ae3dd40":[async_test('html5lib_tests1.html b9e809bc4521004440bf558c7dc5d7dc1ae3dd40'), "%3Cbody%3E%3C/html%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"60302916ab9a2128104dbf72629875ad19b5cb16":[async_test('html5lib_tests1.html 60302916ab9a2128104dbf72629875ad19b5cb16'), "%3Chead%3E%3C/html%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"f4ad8e574fcac3bb08070eeb345855ea7081ea1d":[async_test('html5lib_tests1.html f4ad8e574fcac3bb08070eeb345855ea7081ea1d'), "%3C/head%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"d38fe13d87344a20bdf6e111988b5a09ed247913":[async_test('html5lib_tests1.html d38fe13d87344a20bdf6e111988b5a09ed247913'), "%3C/body%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"e5f2e91cbff6a4bc56149b889f4f9396e455c5ad":[async_test('html5lib_tests1.html e5f2e91cbff6a4bc56149b889f4f9396e455c5ad'), "%3C/html%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"18b58d1de184b6866963c902ff8451dd3522f540":[async_test('html5lib_tests1.html 18b58d1de184b6866963c902ff8451dd3522f540'), "%3Cb%3E%3Ctable%3E%3Ctd%3E%3Ci%3E%3C/table%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ci%3E"],"88eb93691065e212a4323f55ec326585c7c44262":[async_test('html5lib_tests1.html 88eb93691065e212a4323f55ec326585c7c44262'), "%3Cb%3E%3Ctable%3E%3Ctd%3E%3C/b%3E%3Ci%3E%3C/table%3EX", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%22X%22"],"260db4c31fb80894beb825c4793e6142f178497d":[async_test('html5lib_tests1.html 260db4c31fb80894beb825c4793e6142f178497d'), "%3Ch1%3EHello%3Ch2%3EWorld", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ch1%3E%0A%7C%20%20%20%20%20%20%20%22Hello%22%0A%7C%20%20%20%20%20%3Ch2%3E%0A%7C%20%20%20%20%20%20%20%22World%22"],"59d9c5e2941952f7af99ed3e21d66e4fdb1df07c":[async_test('html5lib_tests1.html 59d9c5e2941952f7af99ed3e21d66e4fdb1df07c'), "%3Ca%3E%3Cp%3EX%3Ca%3EY%3C/a%3EZ%3C/p%3E%3C/a%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%22X%22%0A%7C%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%22Y%22%0A%7C%20%20%20%20%20%20%20%22Z%22"],"1e788677da8eb26f560409392ff674744c6f8b64":[async_test('html5lib_tests1.html 1e788677da8eb26f560409392ff674744c6f8b64'), "%3Cb%3E%3Cbutton%3Efoo%3C/b%3Ebar", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%3Cbutton%3E%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%22foo%22%0A%7C%20%20%20%20%20%20%20%22bar%22"],"240ee32b47e30bcf34483c7a7530cfeb99a6d1f1":[async_test('html5lib_tests1.html 240ee32b47e30bcf34483c7a7530cfeb99a6d1f1'), "%3C%21DOCTYPE%20html%3E%3Cspan%3E%3Cbutton%3Efoo%3C/span%3Ebar", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cspan%3E%0A%7C%20%20%20%20%20%20%20%3Cbutton%3E%0A%7C%20%20%20%20%20%20%20%20%20%22foobar%22"],"e85dc012a49630206e6163cd1e0fd6c706865106":[async_test('html5lib_tests1.html e85dc012a49630206e6163cd1e0fd6c706865106'), "%3Cp%3E%3Cb%3E%3Cdiv%3E%3Cmarquee%3E%3C/p%3E%3C/b%3E%3C/div%3EX", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cmarquee%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22X%22"],"c440d1f0223d6b3ce85955d8246fdd47ecdfb034":[async_test('html5lib_tests1.html c440d1f0223d6b3ce85955d8246fdd47ecdfb034'), "%3Cscript%3E%3Cdiv%3E%3C/script%3E%3C/div%3E%3Ctitle%3E%3Cp%3E%3C/title%3E%3Cp%3E%3Cp%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3Cdiv%3E%22%0A%7C%20%20%20%20%20%3Ctitle%3E%0A%7C%20%20%20%20%20%20%20%22%3Cp%3E%22%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%3Cp%3E"],"9a2ce05a0b342b377ef054385131ad4d1b5ae84b":[async_test('html5lib_tests1.html 9a2ce05a0b342b377ef054385131ad4d1b5ae84b'), "%3C%21--%3E%3Cdiv%3E--%3C%21--%3E", "%23document%0A%7C%20%3C%21--%20%20--%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%22--%22%0A%7C%20%20%20%20%20%20%20%3C%21--%20%20--%3E"],"daa9d8440e2bc4d560536b52123b01e52aa81692":[async_test('html5lib_tests1.html daa9d8440e2bc4d560536b52123b01e52aa81692'), "%3Cp%3E%3Chr%3E%3C/p%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%3Chr%3E%0A%7C%20%20%20%20%20%3Cp%3E"],"0b27e026dd03a356bbd78690fff7fb40cd63b606":[async_test('html5lib_tests1.html 0b27e026dd03a356bbd78690fff7fb40cd63b606'), "%3Cselect%3E%3Cb%3E%3Coption%3E%3Cselect%3E%3Coption%3E%3C/b%3E%3C/select%3EX", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cselect%3E%0A%7C%20%20%20%20%20%20%20%3Coption%3E%0A%7C%20%20%20%20%20%3Coption%3E%0A%7C%20%20%20%20%20%20%20%22X%22"],"a2d3321d1ea23b55d9117e5c2014e4ab0fa5e224":[async_test('html5lib_tests1.html a2d3321d1ea23b55d9117e5c2014e4ab0fa5e224'), "%3Ca%3E%3Ctable%3E%3Ctd%3E%3Ca%3E%3Ctable%3E%3C/table%3E%3Ca%3E%3C/tr%3E%3Ca%3E%3C/table%3E%3Cb%3EX%3C/b%3EC%3Ca%3EY", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%22X%22%0A%7C%20%20%20%20%20%20%20%22C%22%0A%7C%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%22Y%22"],"cc9c12dd44b43fa78ad340a91d20432e3f119c19":[async_test('html5lib_tests1.html cc9c12dd44b43fa78ad340a91d20432e3f119c19'), "%3Ca%20X%3E0%3Cb%3E1%3Ca%20Y%3E2", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20x%3D%22%22%0A%7C%20%20%20%20%20%20%20%220%22%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%221%22%0A%7C%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20y%3D%22%22%0A%7C%20%20%20%20%20%20%20%20%20%222%22"],"3d0cb9632b521a3fb334f567b3cdec985e85abd7":[async_test('html5lib_tests1.html 3d0cb9632b521a3fb334f567b3cdec985e85abd7'), "%3C%21-----%3E%3Cfont%3E%3Cdiv%3Ehello%3Ctable%3Eexcite%21%3Cb%3Eme%21%3Cth%3E%3Ci%3Eplease%21%3C/tr%3E%3C%21--X--%3E", "%23document%0A%7C%20%3C%21--%20-%20--%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%22helloexcite%21%22%0A%7C%20%20%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22me%21%22%0A%7C%20%20%20%20%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cth%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22please%21%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%21--%20X%20--%3E"],"f158c8b44e4cdf872cc5bb4d148fad3ff27ea03f":[async_test('html5lib_tests1.html f158c8b44e4cdf872cc5bb4d148fad3ff27ea03f'), "%3C%21DOCTYPE%20html%3E%3Cli%3Ehello%3Cli%3Eworld%3Cul%3Ehow%3Cli%3Edo%3C/ul%3Eyou%3C/body%3E%3C%21--do--%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cli%3E%0A%7C%20%20%20%20%20%20%20%22hello%22%0A%7C%20%20%20%20%20%3Cli%3E%0A%7C%20%20%20%20%20%20%20%22world%22%0A%7C%20%20%20%20%20%20%20%3Cul%3E%0A%7C%20%20%20%20%20%20%20%20%20%22how%22%0A%7C%20%20%20%20%20%20%20%20%20%3Cli%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22do%22%0A%7C%20%20%20%20%20%20%20%22you%22%0A%7C%20%20%20%3C%21--%20do%20--%3E"],"1dfb5ce6c1a10d870a35b24314976d887c700c42":[async_test('html5lib_tests1.html 1dfb5ce6c1a10d870a35b24314976d887c700c42'), "%3C%21DOCTYPE%20html%3EA%3Coption%3EB%3Coptgroup%3EC%3Cselect%3ED%3C/option%3EE", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22A%22%0A%7C%20%20%20%20%20%3Coption%3E%0A%7C%20%20%20%20%20%20%20%22B%22%0A%7C%20%20%20%20%20%3Coptgroup%3E%0A%7C%20%20%20%20%20%20%20%22C%22%0A%7C%20%20%20%20%20%20%20%3Cselect%3E%0A%7C%20%20%20%20%20%20%20%20%20%22DE%22"],"1fc4fad5eead893c51be2b6aa1d705cd58ebcfe9":[async_test('html5lib_tests1.html 1fc4fad5eead893c51be2b6aa1d705cd58ebcfe9'), "%3C", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22%3C%22"],"f85417e345053cf627abf572911c0f7ffefe16c8":[async_test('html5lib_tests1.html f85417e345053cf627abf572911c0f7ffefe16c8'), "%3C%23", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22%3C%23%22"],"277ea1a5aade6c61a8386ff73086a91160caf5a2":[async_test('html5lib_tests1.html 277ea1a5aade6c61a8386ff73086a91160caf5a2'), "%3C/", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22%3C/%22"],"32714c0ca1bae661ba9342ef275b2e6e5e025c34":[async_test('html5lib_tests1.html 32714c0ca1bae661ba9342ef275b2e6e5e025c34'), "%3C/%23", "%23document%0A%7C%20%3C%21--%20%23%20--%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"619aa593419925064f51b0602000a2b9d13a8bc3":[async_test('html5lib_tests1.html 619aa593419925064f51b0602000a2b9d13a8bc3'), "%3C%3F", "%23document%0A%7C%20%3C%21--%20%3F%20--%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"40fd9f6e4a08a69596f0dc0846d44ebd39e4913d":[async_test('html5lib_tests1.html 40fd9f6e4a08a69596f0dc0846d44ebd39e4913d'), "%3C%3F%23", "%23document%0A%7C%20%3C%21--%20%3F%23%20--%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"82120b3520ad73b9e11a413631e6f015ed0cf265":[async_test('html5lib_tests1.html 82120b3520ad73b9e11a413631e6f015ed0cf265'), "%3C%21", "%23document%0A%7C%20%3C%21--%20%20--%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"a9f265e67b901f8d41ece9bb631696795327ed50":[async_test('html5lib_tests1.html a9f265e67b901f8d41ece9bb631696795327ed50'), "%3C%21%23", "%23document%0A%7C%20%3C%21--%20%23%20--%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"6325e1d53c83784c1e5092861c8b0138fb4871ad":[async_test('html5lib_tests1.html 6325e1d53c83784c1e5092861c8b0138fb4871ad'), "%3C%3FCOMMENT%3F%3E", "%23document%0A%7C%20%3C%21--%20%3FCOMMENT%3F%20--%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"451c02faba02d2768e3497fdcc8ffb0dec41640d":[async_test('html5lib_tests1.html 451c02faba02d2768e3497fdcc8ffb0dec41640d'), "%3C%21COMMENT%3E", "%23document%0A%7C%20%3C%21--%20COMMENT%20--%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"fefda3429288aa79b4c9e8e9e3ba97897d0783c8":[async_test('html5lib_tests1.html fefda3429288aa79b4c9e8e9e3ba97897d0783c8'), "%3C/%20COMMENT%20%3E", "%23document%0A%7C%20%3C%21--%20%20COMMENT%20%20--%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"6328f70bb445e1dd692c36d6c92e2a2a7ed6ee0f":[async_test('html5lib_tests1.html 6328f70bb445e1dd692c36d6c92e2a2a7ed6ee0f'), "%3C%3FCOM--MENT%3F%3E", "%23document%0A%7C%20%3C%21--%20%3FCOM--MENT%3F%20--%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"287320444eec6e3b4481d33738f971b696a2d6f0":[async_test('html5lib_tests1.html 287320444eec6e3b4481d33738f971b696a2d6f0'), "%3C%21COM--MENT%3E", "%23document%0A%7C%20%3C%21--%20COM--MENT%20--%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"65ea3a80efc973b5cd92c1db5a4520365bbb5478":[async_test('html5lib_tests1.html 65ea3a80efc973b5cd92c1db5a4520365bbb5478'), "%3C/%20COM--MENT%20%3E", "%23document%0A%7C%20%3C%21--%20%20COM--MENT%20%20--%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"d60de29dd2f3e8a080882986d6689d74fb981619":[async_test('html5lib_tests1.html d60de29dd2f3e8a080882986d6689d74fb981619'), "%3C%21DOCTYPE%20html%3E%3Cstyle%3E%20EOF", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cstyle%3E%0A%7C%20%20%20%20%20%20%20%22%20EOF%22%0A%7C%20%20%20%3Cbody%3E"],"343048017f1928db8ba4c0b45a4f1dd3dadf3063":[async_test('html5lib_tests1.html 343048017f1928db8ba4c0b45a4f1dd3dadf3063'), "%3C%21DOCTYPE%20html%3E%3Cscript%3E%20%3C%21--%20%3C/script%3E%20--%3E%20%3C/script%3E%20EOF", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%20%3C%21--%20%22%0A%7C%20%20%20%20%20%22%20%22%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22--%3E%20%20EOF%22"],"cf14f5563275bac3fe2c77f8973e882e51965b5b":[async_test('html5lib_tests1.html cf14f5563275bac3fe2c77f8973e882e51965b5b'), "%3Cb%3E%3Cp%3E%3C/b%3ETEST", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%22TEST%22"],"2d8f9308951237fd0dcba3ff7709369cfd7563fd":[async_test('html5lib_tests1.html 2d8f9308951237fd0dcba3ff7709369cfd7563fd'), "%3Cp%20id%3Da%3E%3Cb%3E%3Cp%20id%3Db%3E%3C/b%3ETEST", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20id%3D%22a%22%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20id%3D%22b%22%0A%7C%20%20%20%20%20%20%20%22TEST%22"],"87421a25ca75e2d6a165eb981921235f4de9210a":[async_test('html5lib_tests1.html 87421a25ca75e2d6a165eb981921235f4de9210a'), "%3Cb%20id%3Da%3E%3Cp%3E%3Cb%20id%3Db%3E%3C/p%3E%3C/b%3ETEST", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20id%3D%22a%22%0A%7C%20%20%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20id%3D%22b%22%0A%7C%20%20%20%20%20%20%20%22TEST%22"],"30d87693aead287d5a63310d2f819623455f4133":[async_test('html5lib_tests1.html 30d87693aead287d5a63310d2f819623455f4133'), "%3C%21DOCTYPE%20html%3E%3Ctitle%3EU-test%3C/title%3E%3Cbody%3E%3Cdiv%3E%3Cp%3ETest%3Cu%3E%3C/p%3E%3C/div%3E%3C/body%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Ctitle%3E%0A%7C%20%20%20%20%20%20%20%22U-test%22%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%20%20%22Test%22%0A%7C%20%20%20%20%20%20%20%20%20%3Cu%3E"],"20d7a996a47fab66aead30ed7012d50b990dc65d":[async_test('html5lib_tests1.html 20d7a996a47fab66aead30ed7012d50b990dc65d'), "%3C%21DOCTYPE%20html%3E%3Cfont%3E%3Ctable%3E%3C/font%3E%3C/table%3E%3C/font%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%3Ctable%3E"],"258c0966cc576ec8a563e41e783fa34f6b5c8baf":[async_test('html5lib_tests1.html 258c0966cc576ec8a563e41e783fa34f6b5c8baf'), "%3Cfont%3E%3Cp%3Ehello%3Cb%3Ecruel%3C/font%3Eworld", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%20%20%22hello%22%0A%7C%20%20%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22cruel%22%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%22world%22"],"f7ee5b858e93b22e1594d6d8cd0bc0def665ac02":[async_test('html5lib_tests1.html f7ee5b858e93b22e1594d6d8cd0bc0def665ac02'), "%3Cb%3ETest%3C/i%3ETest", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%22TestTest%22"],"6d9127103f8733d168e69cf04b576a7b0bea3d5c":[async_test('html5lib_tests1.html 6d9127103f8733d168e69cf04b576a7b0bea3d5c'), "%3Cb%3EA%3Ccite%3EB%3Cdiv%3EC", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%22A%22%0A%7C%20%20%20%20%20%20%20%3Ccite%3E%0A%7C%20%20%20%20%20%20%20%20%20%22B%22%0A%7C%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22C%22"],"03db7399a2d674955930611fdbcaad9f4064243a":[async_test('html5lib_tests1.html 03db7399a2d674955930611fdbcaad9f4064243a'), "%3Cb%3EA%3Ccite%3EB%3Cdiv%3EC%3C/cite%3ED", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%22A%22%0A%7C%20%20%20%20%20%20%20%3Ccite%3E%0A%7C%20%20%20%20%20%20%20%20%20%22B%22%0A%7C%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22CD%22"],"a0a1dcb330314ce12af02d136319a1be6a1ffa53":[async_test('html5lib_tests1.html a0a1dcb330314ce12af02d136319a1be6a1ffa53'), "%3Cb%3EA%3Ccite%3EB%3Cdiv%3EC%3C/b%3ED", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%22A%22%0A%7C%20%20%20%20%20%20%20%3Ccite%3E%0A%7C%20%20%20%20%20%20%20%20%20%22B%22%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%22C%22%0A%7C%20%20%20%20%20%20%20%22D%22"],"09b3483ef5f7a83aa9e3224d0335b6f9aa78ac73":[async_test('html5lib_tests1.html 09b3483ef5f7a83aa9e3224d0335b6f9aa78ac73'), "", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"34d56f09a1a9c0f51a8abc41be2f157faf0e8d15":[async_test('html5lib_tests1.html 34d56f09a1a9c0f51a8abc41be2f157faf0e8d15'), "%3CDIV%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E"],"dffa0785e6c80af52950a64d8612633de58bbb29":[async_test('html5lib_tests1.html dffa0785e6c80af52950a64d8612633de58bbb29'), "%3CDIV%3E%20abc", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%22%20abc%22"],"076e6ac3cb344d60f6ce9a5188cf103ff053830c":[async_test('html5lib_tests1.html 076e6ac3cb344d60f6ce9a5188cf103ff053830c'), "%3CDIV%3E%20abc%20%3CB%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%22%20abc%20%22%0A%7C%20%20%20%20%20%20%20%3Cb%3E"],"5f14cb9c8502f09105ad83e27842625c70f3857d":[async_test('html5lib_tests1.html 5f14cb9c8502f09105ad83e27842625c70f3857d'), "%3CDIV%3E%20abc%20%3CB%3E%20def", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%22%20abc%20%22%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%22%20def%22"],"25172f395b855b6eeb61ff95a8162a34ca92195e":[async_test('html5lib_tests1.html 25172f395b855b6eeb61ff95a8162a34ca92195e'), "%3CDIV%3E%20abc%20%3CB%3E%20def%20%3CI%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%22%20abc%20%22%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%22%20def%20%22%0A%7C%20%20%20%20%20%20%20%20%20%3Ci%3E"],"053beabf01d70d03a0ca61b809d5d986ddf2ea3d":[async_test('html5lib_tests1.html 053beabf01d70d03a0ca61b809d5d986ddf2ea3d'), "%3CDIV%3E%20abc%20%3CB%3E%20def%20%3CI%3E%20ghi", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%22%20abc%20%22%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%22%20def%20%22%0A%7C%20%20%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22%20ghi%22"],"bd385dbe93b192c2182e09e75d3664b96845ea0a":[async_test('html5lib_tests1.html bd385dbe93b192c2182e09e75d3664b96845ea0a'), "%3CDIV%3E%20abc%20%3CB%3E%20def%20%3CI%3E%20ghi%20%3CP%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%22%20abc%20%22%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%22%20def%20%22%0A%7C%20%20%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22%20ghi%20%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cp%3E"],"2ddaacb4f4e566ae79af5259f57f5b4dd166c19f":[async_test('html5lib_tests1.html 2ddaacb4f4e566ae79af5259f57f5b4dd166c19f'), "%3CDIV%3E%20abc%20%3CB%3E%20def%20%3CI%3E%20ghi%20%3CP%3E%20jkl", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%22%20abc%20%22%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%22%20def%20%22%0A%7C%20%20%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22%20ghi%20%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%22%20jkl%22"],"d430f2fc3bd20e658ed00b55e6c27f14204a7b6f":[async_test('html5lib_tests1.html d430f2fc3bd20e658ed00b55e6c27f14204a7b6f'), "%3CDIV%3E%20abc%20%3CB%3E%20def%20%3CI%3E%20ghi%20%3CP%3E%20jkl%20%3C/B%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%22%20abc%20%22%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%22%20def%20%22%0A%7C%20%20%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22%20ghi%20%22%0A%7C%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%22%20jkl%20%22"],"bbdb0a08b66b0789068ddac96a05ac39e104553d":[async_test('html5lib_tests1.html bbdb0a08b66b0789068ddac96a05ac39e104553d'), "%3CDIV%3E%20abc%20%3CB%3E%20def%20%3CI%3E%20ghi%20%3CP%3E%20jkl%20%3C/B%3E%20mno", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%22%20abc%20%22%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%22%20def%20%22%0A%7C%20%20%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22%20ghi%20%22%0A%7C%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%22%20jkl%20%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22%20mno%22"],"37ed2a3a96026e7a78f6675154d11746aa9484e0":[async_test('html5lib_tests1.html 37ed2a3a96026e7a78f6675154d11746aa9484e0'), "%3CDIV%3E%20abc%20%3CB%3E%20def%20%3CI%3E%20ghi%20%3CP%3E%20jkl%20%3C/B%3E%20mno%20%3C/I%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%22%20abc%20%22%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%22%20def%20%22%0A%7C%20%20%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22%20ghi%20%22%0A%7C%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%22%20jkl%20%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22%20mno%20%22"],"4177a74406cf1c048d2d6d6bcf774445f55ba517":[async_test('html5lib_tests1.html 4177a74406cf1c048d2d6d6bcf774445f55ba517'), "%3CDIV%3E%20abc%20%3CB%3E%20def%20%3CI%3E%20ghi%20%3CP%3E%20jkl%20%3C/B%3E%20mno%20%3C/I%3E%20pqr", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%22%20abc%20%22%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%22%20def%20%22%0A%7C%20%20%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22%20ghi%20%22%0A%7C%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%22%20jkl%20%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22%20mno%20%22%0A%7C%20%20%20%20%20%20%20%20%20%22%20pqr%22"],"fc188652d9f486174b21d1919f35ea8c13636ca1":[async_test('html5lib_tests1.html fc188652d9f486174b21d1919f35ea8c13636ca1'), "%3CDIV%3E%20abc%20%3CB%3E%20def%20%3CI%3E%20ghi%20%3CP%3E%20jkl%20%3C/B%3E%20mno%20%3C/I%3E%20pqr%20%3C/P%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%22%20abc%20%22%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%22%20def%20%22%0A%7C%20%20%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22%20ghi%20%22%0A%7C%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%22%20jkl%20%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22%20mno%20%22%0A%7C%20%20%20%20%20%20%20%20%20%22%20pqr%20%22"],"c10f83cc69763e42964e08ddb976a1bd27b51e2f":[async_test('html5lib_tests1.html c10f83cc69763e42964e08ddb976a1bd27b51e2f'), "%3CDIV%3E%20abc%20%3CB%3E%20def%20%3CI%3E%20ghi%20%3CP%3E%20jkl%20%3C/B%3E%20mno%20%3C/I%3E%20pqr%20%3C/P%3E%20stu", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%22%20abc%20%22%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%22%20def%20%22%0A%7C%20%20%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22%20ghi%20%22%0A%7C%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%22%20jkl%20%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22%20mno%20%22%0A%7C%20%20%20%20%20%20%20%20%20%22%20pqr%20%22%0A%7C%20%20%20%20%20%20%20%22%20stu%22"],"64452c62ced87bd3cd8fd88df33a33d5531818d6":[async_test('html5lib_tests1.html 64452c62ced87bd3cd8fd88df33a33d5531818d6'), "%3Ctest%20attribute----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctest%3E%0A%7C%20%20%20%20%20%20%20attribute----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------%3D%22%22"],"96dc04673021ad113df40397113df972f090c1f6":[async_test('html5lib_tests1.html 96dc04673021ad113df40397113df972f090c1f6'), "%3Ca%20href%3D%22blah%22%3Eaba%3Ctable%3E%3Ca%20href%3D%22foo%22%3Ebr%3Ctr%3E%3Ctd%3E%3C/td%3E%3C/tr%3Ex%3C/table%3Eaoe", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20href%3D%22blah%22%0A%7C%20%20%20%20%20%20%20%22aba%22%0A%7C%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20href%3D%22foo%22%0A%7C%20%20%20%20%20%20%20%20%20%22br%22%0A%7C%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20href%3D%22foo%22%0A%7C%20%20%20%20%20%20%20%20%20%22x%22%0A%7C%20%20%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20href%3D%22foo%22%0A%7C%20%20%20%20%20%20%20%22aoe%22"],"26b7eb0b18d9cd0a69d19c7f6ee9f12c2d0b2783":[async_test('html5lib_tests1.html 26b7eb0b18d9cd0a69d19c7f6ee9f12c2d0b2783'), "%3Ca%20href%3D%22blah%22%3Eaba%3Ctable%3E%3Ctr%3E%3Ctd%3E%3Ca%20href%3D%22foo%22%3Ebr%3C/td%3E%3C/tr%3Ex%3C/table%3Eaoe", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20href%3D%22blah%22%0A%7C%20%20%20%20%20%20%20%22abax%22%0A%7C%20%20%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20href%3D%22foo%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22br%22%0A%7C%20%20%20%20%20%20%20%22aoe%22"],"f8d500cd7089942814fa0751c75bd37e63790685":[async_test('html5lib_tests1.html f8d500cd7089942814fa0751c75bd37e63790685'), "%3Ctable%3E%3Ca%20href%3D%22blah%22%3Eaba%3Ctr%3E%3Ctd%3E%3Ca%20href%3D%22foo%22%3Ebr%3C/td%3E%3C/tr%3Ex%3C/table%3Eaoe", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20href%3D%22blah%22%0A%7C%20%20%20%20%20%20%20%22aba%22%0A%7C%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20href%3D%22blah%22%0A%7C%20%20%20%20%20%20%20%22x%22%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20href%3D%22foo%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22br%22%0A%7C%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20href%3D%22blah%22%0A%7C%20%20%20%20%20%20%20%22aoe%22"],"3b386c205ec767f842e63491d14ec90192f562dd":[async_test('html5lib_tests1.html 3b386c205ec767f842e63491d14ec90192f562dd'), "%3Ca%20href%3Da%3Eaa%3Cmarquee%3Eaa%3Ca%20href%3Db%3Ebb%3C/marquee%3Eaa", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20href%3D%22a%22%0A%7C%20%20%20%20%20%20%20%22aa%22%0A%7C%20%20%20%20%20%20%20%3Cmarquee%3E%0A%7C%20%20%20%20%20%20%20%20%20%22aa%22%0A%7C%20%20%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20href%3D%22b%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22bb%22%0A%7C%20%20%20%20%20%20%20%22aa%22"],"ca8ecc666a82d1f2f48a095d42d9f95700e015bd":[async_test('html5lib_tests1.html ca8ecc666a82d1f2f48a095d42d9f95700e015bd'), "%3Cwbr%3E%3Cstrike%3E%3Ccode%3E%3C/strike%3E%3Ccode%3E%3Cstrike%3E%3C/code%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cwbr%3E%0A%7C%20%20%20%20%20%3Cstrike%3E%0A%7C%20%20%20%20%20%20%20%3Ccode%3E%0A%7C%20%20%20%20%20%3Ccode%3E%0A%7C%20%20%20%20%20%20%20%3Ccode%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cstrike%3E"],"6727ab7c4240bf05f0a5d9ca4b384ca8d61e2d4f":[async_test('html5lib_tests1.html 6727ab7c4240bf05f0a5d9ca4b384ca8d61e2d4f'), "%3C%21DOCTYPE%20html%3E%3Cspacer%3Efoo", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cspacer%3E%0A%7C%20%20%20%20%20%20%20%22foo%22"],"3ad08edf5b9690be261dc375da3b1d9ec82e499a":[async_test('html5lib_tests1.html 3ad08edf5b9690be261dc375da3b1d9ec82e499a'), "%3Ctitle%3E%3Cmeta%3E%3C/title%3E%3Clink%3E%3Ctitle%3E%3Cmeta%3E%3C/title%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Ctitle%3E%0A%7C%20%20%20%20%20%20%20%22%3Cmeta%3E%22%0A%7C%20%20%20%20%20%3Clink%3E%0A%7C%20%20%20%20%20%3Ctitle%3E%0A%7C%20%20%20%20%20%20%20%22%3Cmeta%3E%22%0A%7C%20%20%20%3Cbody%3E"],"06ed0f32cfd261010c9d810ff8317ef96b47c04c":[async_test('html5lib_tests1.html 06ed0f32cfd261010c9d810ff8317ef96b47c04c'), "%3Cstyle%3E%3C%21--%3C/style%3E%3Cmeta%3E%3Cscript%3E--%3E%3Clink%3E%3C/script%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cstyle%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%22%0A%7C%20%20%20%20%20%3Cmeta%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22--%3E%3Clink%3E%22%0A%7C%20%20%20%3Cbody%3E"],"44ea84c7e4e401c9d3f96d7cc39709e4be81edc8":[async_test('html5lib_tests1.html 44ea84c7e4e401c9d3f96d7cc39709e4be81edc8'), "%3Chead%3E%3Cmeta%3E%3C/head%3E%3Clink%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cmeta%3E%0A%7C%20%20%20%20%20%3Clink%3E%0A%7C%20%20%20%3Cbody%3E"],"67af290f1b04c4b1a67131edba1ee832c690432c":[async_test('html5lib_tests1.html 67af290f1b04c4b1a67131edba1ee832c690432c'), "%3Ctable%3E%3Ctr%3E%3Ctr%3E%3Ctd%3E%3Ctd%3E%3Cspan%3E%3Cth%3E%3Cspan%3EX%3C/table%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cspan%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cth%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cspan%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22X%22"],"2f1899f72fafcb062418e8ce892188040de4708c":[async_test('html5lib_tests1.html 2f1899f72fafcb062418e8ce892188040de4708c'), "%3Cbody%3E%3Cbody%3E%3Cbase%3E%3Clink%3E%3Cmeta%3E%3Ctitle%3E%3Cp%3E%3C/title%3E%3Cbody%3E%3Cp%3E%3C/body%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cbase%3E%0A%7C%20%20%20%20%20%3Clink%3E%0A%7C%20%20%20%20%20%3Cmeta%3E%0A%7C%20%20%20%20%20%3Ctitle%3E%0A%7C%20%20%20%20%20%20%20%22%3Cp%3E%22%0A%7C%20%20%20%20%20%3Cp%3E"],"ed2a4958c832ef6cec993cb52afc808132714d0a":[async_test('html5lib_tests1.html ed2a4958c832ef6cec993cb52afc808132714d0a'), "%3Ctextarea%3E%3Cp%3E%3C/textarea%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctextarea%3E%0A%7C%20%20%20%20%20%20%20%22%3Cp%3E%22"],"c7943ccd9d880664b0894a2035e1f2a837f37c7a":[async_test('html5lib_tests1.html c7943ccd9d880664b0894a2035e1f2a837f37c7a'), "%3Cp%3E%3Cimage%3E%3C/p%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cimg%3E"],"bbc836b1f494223d4eb8982930d693489d135740":[async_test('html5lib_tests1.html bbc836b1f494223d4eb8982930d693489d135740'), "%3Ca%3E%3Ctable%3E%3Ca%3E%3C/table%3E%3Cp%3E%3Ca%3E%3Cdiv%3E%3Ca%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%3Ca%3E"],"617fdf08035740698b2f0f4c3874dbb469fd1848":[async_test('html5lib_tests1.html 617fdf08035740698b2f0f4c3874dbb469fd1848'), "%3Chead%3E%3C/p%3E%3Cmeta%3E%3Cp%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cmeta%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E"],"e901fe2093e51eccb4d9d23103214bc527af265c":[async_test('html5lib_tests1.html e901fe2093e51eccb4d9d23103214bc527af265c'), "%3Chead%3E%3C/html%3E%3Cmeta%3E%3Cp%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cmeta%3E%0A%7C%20%20%20%20%20%3Cp%3E"],"63970995ab6b8aee63de9e7a7667178d4fc86820":[async_test('html5lib_tests1.html 63970995ab6b8aee63de9e7a7667178d4fc86820'), "%3Cb%3E%3Ctable%3E%3Ctd%3E%3C/b%3E%3Ci%3E%3C/table%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ci%3E"],"d7607fdd41625431bcbee319a86db1b73fc49edd":[async_test('html5lib_tests1.html d7607fdd41625431bcbee319a86db1b73fc49edd'), "%3Ch1%3E%3Ch2%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ch1%3E%0A%7C%20%20%20%20%20%3Ch2%3E"],"ce31a583a3921e306aaa558b1ea798b34d2bb0dc":[async_test('html5lib_tests1.html ce31a583a3921e306aaa558b1ea798b34d2bb0dc'), "%3Ca%3E%3Cp%3E%3Ca%3E%3C/a%3E%3C/p%3E%3C/a%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%3Ca%3E"],"04ba864e740f7ef104570ddc6af834e6336031ed":[async_test('html5lib_tests1.html 04ba864e740f7ef104570ddc6af834e6336031ed'), "%3Cb%3E%3Cbutton%3E%3C/b%3E%3C/button%3E%3C/b%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%3Cbutton%3E%0A%7C%20%20%20%20%20%20%20%3Cb%3E"],"ea6ab4a56efd19cc04b5656583ea6d5c9cfd2752":[async_test('html5lib_tests1.html ea6ab4a56efd19cc04b5656583ea6d5c9cfd2752'), "%3Cp%3E%3Cb%3E%3Cdiv%3E%3Cmarquee%3E%3C/p%3E%3C/b%3E%3C/div%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cmarquee%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cp%3E"],"1bb5dfba014f63c0a18b12097ed9a28d64552e07":[async_test('html5lib_tests1.html 1bb5dfba014f63c0a18b12097ed9a28d64552e07'), "%3Cscript%3E%3C/script%3E%3C/div%3E%3Ctitle%3E%3C/title%3E%3Cp%3E%3Cp%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%3Ctitle%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%3Cp%3E"],"a2dd4d5a28a61ec99ce9dae35e9d4ffe92812e2f":[async_test('html5lib_tests1.html a2dd4d5a28a61ec99ce9dae35e9d4ffe92812e2f'), "%3Cselect%3E%3Cb%3E%3Coption%3E%3Cselect%3E%3Coption%3E%3C/b%3E%3C/select%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cselect%3E%0A%7C%20%20%20%20%20%20%20%3Coption%3E%0A%7C%20%20%20%20%20%3Coption%3E"],"e26f001557952154c308e3e6f6d1789cf711ef27":[async_test('html5lib_tests1.html e26f001557952154c308e3e6f6d1789cf711ef27'), "%3Chtml%3E%3Chead%3E%3Ctitle%3E%3C/title%3E%3Cbody%3E%3C/body%3E%3C/html%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Ctitle%3E%0A%7C%20%20%20%3Cbody%3E"],"34c1f9c212198edd7baf56e658db21d98c59f74c":[async_test('html5lib_tests1.html 34c1f9c212198edd7baf56e658db21d98c59f74c'), "%3Ca%3E%3Ctable%3E%3Ctd%3E%3Ca%3E%3Ctable%3E%3C/table%3E%3Ca%3E%3C/tr%3E%3Ca%3E%3C/table%3E%3Ca%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%3Ca%3E"],"e1c47adbde197e3eaa9504f3582fd9deac1cbbff":[async_test('html5lib_tests1.html e1c47adbde197e3eaa9504f3582fd9deac1cbbff'), "%3Cul%3E%3Cli%3E%3C/li%3E%3Cdiv%3E%3Cli%3E%3C/div%3E%3Cli%3E%3Cli%3E%3Cdiv%3E%3Cli%3E%3Caddress%3E%3Cli%3E%3Cb%3E%3Cem%3E%3C/b%3E%3Cli%3E%3C/ul%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cul%3E%0A%7C%20%20%20%20%20%20%20%3Cli%3E%0A%7C%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cli%3E%0A%7C%20%20%20%20%20%20%20%3Cli%3E%0A%7C%20%20%20%20%20%20%20%3Cli%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%3Cli%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Caddress%3E%0A%7C%20%20%20%20%20%20%20%3Cli%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cem%3E%0A%7C%20%20%20%20%20%20%20%3Cli%3E"],"0f5aba4c1ed57ac3c6a2774f3bf43ef598bd9915":[async_test('html5lib_tests1.html 0f5aba4c1ed57ac3c6a2774f3bf43ef598bd9915'), "%3Cul%3E%3Cli%3E%3Cul%3E%3C/li%3E%3Cli%3Ea%3C/li%3E%3C/ul%3E%3C/li%3E%3C/ul%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cul%3E%0A%7C%20%20%20%20%20%20%20%3Cli%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cul%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cli%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%22a%22"],"d11ff75681c4df2ff24ad731ff244afc3e1c87af":[async_test('html5lib_tests1.html d11ff75681c4df2ff24ad731ff244afc3e1c87af'), "%3Cframeset%3E%3Cframe%3E%3Cframeset%3E%3Cframe%3E%3C/frameset%3E%3Cnoframes%3E%3C/noframes%3E%3C/frameset%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E%0A%7C%20%20%20%20%20%3Cframe%3E%0A%7C%20%20%20%20%20%3Cframeset%3E%0A%7C%20%20%20%20%20%20%20%3Cframe%3E%0A%7C%20%20%20%20%20%3Cnoframes%3E"],"fa392f5dd6f2f6a73635c06208c8989caa874588":[async_test('html5lib_tests1.html fa392f5dd6f2f6a73635c06208c8989caa874588'), "%3Ch1%3E%3Ctable%3E%3Ctd%3E%3Ch3%3E%3C/table%3E%3Ch3%3E%3C/h1%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ch1%3E%0A%7C%20%20%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ch3%3E%0A%7C%20%20%20%20%20%3Ch3%3E"],"5815b2afbb0a7f4756af7914407f71f469658f38":[async_test('html5lib_tests1.html 5815b2afbb0a7f4756af7914407f71f469658f38'), "%3Ctable%3E%3Ccolgroup%3E%3Ccol%3E%3Ccolgroup%3E%3Ccol%3E%3Ccol%3E%3Ccol%3E%3Ccolgroup%3E%3Ccol%3E%3Ccol%3E%3Cthead%3E%3Ctr%3E%3Ctd%3E%3C/table%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ccolgroup%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ccol%3E%0A%7C%20%20%20%20%20%20%20%3Ccolgroup%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ccol%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ccol%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ccol%3E%0A%7C%20%20%20%20%20%20%20%3Ccolgroup%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ccol%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ccol%3E%0A%7C%20%20%20%20%20%20%20%3Cthead%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E"],"a100bb6a2a80bec65c418d672144b6f647fbd46b":[async_test('html5lib_tests1.html a100bb6a2a80bec65c418d672144b6f647fbd46b'), "%3Ctable%3E%3Ccol%3E%3Ctbody%3E%3Ccol%3E%3Ctr%3E%3Ccol%3E%3Ctd%3E%3Ccol%3E%3C/table%3E%3Ccol%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ccolgroup%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ccol%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%3Ccolgroup%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ccol%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%3Ccolgroup%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ccol%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%3Ccolgroup%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ccol%3E"],"f66797fd63c8b0254b4ef28e9c38c3d4e512c93c":[async_test('html5lib_tests1.html f66797fd63c8b0254b4ef28e9c38c3d4e512c93c'), "%3Ctable%3E%3Ccolgroup%3E%3Ctbody%3E%3Ccolgroup%3E%3Ctr%3E%3Ccolgroup%3E%3Ctd%3E%3Ccolgroup%3E%3C/table%3E%3Ccolgroup%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ccolgroup%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%3Ccolgroup%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%3Ccolgroup%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%3Ccolgroup%3E"],"f10a41faca4cf01e39ed92c4eefff0631d1195dc":[async_test('html5lib_tests1.html f10a41faca4cf01e39ed92c4eefff0631d1195dc'), "%3C/strong%3E%3C/b%3E%3C/em%3E%3C/i%3E%3C/u%3E%3C/strike%3E%3C/s%3E%3C/blink%3E%3C/tt%3E%3C/pre%3E%3C/big%3E%3C/small%3E%3C/font%3E%3C/select%3E%3C/h1%3E%3C/h2%3E%3C/h3%3E%3C/h4%3E%3C/h5%3E%3C/h6%3E%3C/body%3E%3C/br%3E%3C/a%3E%3C/img%3E%3C/title%3E%3C/span%3E%3C/style%3E%3C/script%3E%3C/table%3E%3C/th%3E%3C/td%3E%3C/tr%3E%3C/frame%3E%3C/area%3E%3C/link%3E%3C/param%3E%3C/hr%3E%3C/input%3E%3C/col%3E%3C/base%3E%3C/meta%3E%3C/basefont%3E%3C/bgsound%3E%3C/embed%3E%3C/spacer%3E%3C/p%3E%3C/dd%3E%3C/dt%3E%3C/caption%3E%3C/colgroup%3E%3C/tbody%3E%3C/tfoot%3E%3C/thead%3E%3C/address%3E%3C/blockquote%3E%3C/center%3E%3C/dir%3E%3C/div%3E%3C/dl%3E%3C/fieldset%3E%3C/listing%3E%3C/menu%3E%3C/ol%3E%3C/ul%3E%3C/li%3E%3C/nobr%3E%3C/wbr%3E%3C/form%3E%3C/button%3E%3C/marquee%3E%3C/object%3E%3C/html%3E%3C/frameset%3E%3C/head%3E%3C/iframe%3E%3C/image%3E%3C/isindex%3E%3C/noembed%3E%3C/noframes%3E%3C/noscript%3E%3C/optgroup%3E%3C/option%3E%3C/plaintext%3E%3C/textarea%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cbr%3E%0A%7C%20%20%20%20%20%3Cp%3E"],"5d14e20ae19e0b3e14dcb997e3ccad5f0e1956e1":[async_test('html5lib_tests1.html 5d14e20ae19e0b3e14dcb997e3ccad5f0e1956e1'), "%3Ctable%3E%3Ctr%3E%3C/strong%3E%3C/b%3E%3C/em%3E%3C/i%3E%3C/u%3E%3C/strike%3E%3C/s%3E%3C/blink%3E%3C/tt%3E%3C/pre%3E%3C/big%3E%3C/small%3E%3C/font%3E%3C/select%3E%3C/h1%3E%3C/h2%3E%3C/h3%3E%3C/h4%3E%3C/h5%3E%3C/h6%3E%3C/body%3E%3C/br%3E%3C/a%3E%3C/img%3E%3C/title%3E%3C/span%3E%3C/style%3E%3C/script%3E%3C/table%3E%3C/th%3E%3C/td%3E%3C/tr%3E%3C/frame%3E%3C/area%3E%3C/link%3E%3C/param%3E%3C/hr%3E%3C/input%3E%3C/col%3E%3C/base%3E%3C/meta%3E%3C/basefont%3E%3C/bgsound%3E%3C/embed%3E%3C/spacer%3E%3C/p%3E%3C/dd%3E%3C/dt%3E%3C/caption%3E%3C/colgroup%3E%3C/tbody%3E%3C/tfoot%3E%3C/thead%3E%3C/address%3E%3C/blockquote%3E%3C/center%3E%3C/dir%3E%3C/div%3E%3C/dl%3E%3C/fieldset%3E%3C/listing%3E%3C/menu%3E%3C/ol%3E%3C/ul%3E%3C/li%3E%3C/nobr%3E%3C/wbr%3E%3C/form%3E%3C/button%3E%3C/marquee%3E%3C/object%3E%3C/html%3E%3C/frameset%3E%3C/head%3E%3C/iframe%3E%3C/image%3E%3C/isindex%3E%3C/noembed%3E%3C/noframes%3E%3C/noscript%3E%3C/optgroup%3E%3C/option%3E%3C/plaintext%3E%3C/textarea%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cbr%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%3Cp%3E"],"1949f8c612e660985fb5eb28235b6f9386ed4ffc":[async_test('html5lib_tests1.html 1949f8c612e660985fb5eb28235b6f9386ed4ffc'), "%3Cframeset%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E"],
+ }
+ init_tests(get_type());
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests10.html b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests10.html
new file mode 100644
index 00000000000..26411582b1a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests10.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf8">
+ <title>HTML 5 Parser tests html5lib_tests10.html</title>
+ <meta name="timeout" content="long">
+ <meta name="variant" content="?run_type=uri">
+ <meta name="variant" content="?run_type=write">
+ <meta name="variant" content="?run_type=write_single">
+ </head>
+ <body>
+ <h1>html5lib Parser Test</h1>
+ <div id="log"></div>
+ <script src="common.js"></script>
+ <script src="test.js"></script>
+ <script src="template.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ var num_iframes = 8;
+ var order = ['33cab27b810c8329105a4447f7767307577cb52f','b833b22c2ce59749e320b26fbc4d277bc015f261','5159857bc8326870c92e525f000abe74b51f9104','fee2541ab7080ca5b363bb4b7b0c18ee1d3699ba','679fbaa80e9d15416f17eb041a8fe04c373f0e12','0fe5609efd1436590d64aa7f47643fcaf1decc9c','7900ad087a3da10cbd7eb3eae57181ca7e417f0e','52f78e3d4b60a998fe249f7c026078f13ef65fe3','01dd3726b85de9278486adaf23c7cd553ea701b0','c993a3cf01522d1b958e942f781c535bd63e7f43','3f8ac796f286506aa56f87a8b430c4d6d2802695','df1f29ea6a1d57e029cdb95216b85e9daac07ad0','ae19484ce5b8e2087e3df7f13183622d2cf059a7','7f9c4aeecce3bbf1483104213487a506cfdc6650','219f8f9866ad87d2e98f0cbbf35e0d7070848f81','a1e3a3515da712da9fa9bae0ab874a0a31207e6b','badaa2069df3f2bb2d2da79f8ae2598f66ab2d0f','64e72bd5af825a0b014a78c77d6d0be8c330892b','6b6728b11b3f67a6b67e0dec03222222783e2c40','c16f6e833fafc8e96c4d888aace5e7df190f8bb5','8b5cc06ce9513c4b0b2be26adad3357c79a10241','f396d620bf4e128981156d61f4768634c407c806','3c262f2c74c6cf5519cfad9440e118dd36fcc37f','4e788a289a02c283f0a7b71340f4947c30fd289e','b0a2a300705d9a5b6ceb8f7b9d4d240a9eb9f9e0','2e92f741697be25c07416f7885b7decc0684c874','3cffa6d987cfd48c6cd5f9e7d198ca0e79b6cdb8','f89f8c14aeaa1d3107b6aa6d87fbf10e8fd5f8c3','663691222288a8f734149fba4f1b7ff5bb201df0','dbe5123aed0264b7fe421fea4b9bc5bd304cc596','982e01ebddec435aeb2dc0f23fa77e4201a38b28','b613b907ffa87da6f3076a24ad775843e5c2a43a','4553fc5ae2782aef4100d8db614041e42c3612e9','6c10b9811a0d228cf26bc0b55ee12c7d99926270','ee2de7753d6594fbf05d321b24e2c8bb6f2323c6','225170b3f08201a11d43f153fa3c8a041173b55f','716a01ee7d076876318395625e08e555065fc3b0','3c5cc236386d2d4a16d14e5c65da7edd26697a43','6c3447a16060d2805f8c969ec0a7b5c551468f25','071f13f248eb7af8f7d512cf453b16c8ccc57483','0ef97c924e3e5e8ddf8a0bc74530868684685c38','25a94dd91d982fa75c89944ad8f066f7961c590b','575adfd2e679ad44140d8afd131fee2e5e819fc0','2eb6893275ff1de69569440710f5588b8558ca17','4f57b212888bfcc7ac6d8e29ef444cc7ae3ec495','c069a88f172919c862432dbef290a425e71414aa','f944f978d6a10ec9f194f03a5e232f9663d96ec1','d5ab79a14609f3ed214baa8e02bedb54ddcf33ec','4318bf46f0256426716a911e194f9bdf6185bd7c','aa5c4b093ee603618493cff853af125b5fb0d401','bfd98674d75ff3291d377f2a7cec3321844a0701','7fc99b729a6d57d28b2ad1edc33bb15167e051bb','8e87f0d5ca606ca162384d1bf3bb8de62bd6f398','6476f80f3d2a04e9c1323ffe78686188c579e9ac',];
+ var tests = {
+ "33cab27b810c8329105a4447f7767307577cb52f":[async_test('html5lib_tests10.html 33cab27b810c8329105a4447f7767307577cb52f'), "%3C%21DOCTYPE%20html%3E%3Csvg%3E%3C/svg%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E"],"b833b22c2ce59749e320b26fbc4d277bc015f261":[async_test('html5lib_tests10.html b833b22c2ce59749e320b26fbc4d277bc015f261'), "%3C%21DOCTYPE%20html%3E%3Csvg%3E%3C/svg%3E%3C%21%5BCDATA%5Ba%5D%5D%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%3C%21--%20%5BCDATA%5Ba%5D%5D%20--%3E"],"5159857bc8326870c92e525f000abe74b51f9104":[async_test('html5lib_tests10.html 5159857bc8326870c92e525f000abe74b51f9104'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Csvg%3E%3C/svg%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E"],"fee2541ab7080ca5b363bb4b7b0c18ee1d3699ba":[async_test('html5lib_tests10.html fee2541ab7080ca5b363bb4b7b0c18ee1d3699ba'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Cselect%3E%3Csvg%3E%3C/svg%3E%3C/select%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cselect%3E"],"679fbaa80e9d15416f17eb041a8fe04c373f0e12":[async_test('html5lib_tests10.html 679fbaa80e9d15416f17eb041a8fe04c373f0e12'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Cselect%3E%3Coption%3E%3Csvg%3E%3C/svg%3E%3C/option%3E%3C/select%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cselect%3E%0A%7C%20%20%20%20%20%20%20%3Coption%3E"],"0fe5609efd1436590d64aa7f47643fcaf1decc9c":[async_test('html5lib_tests10.html 0fe5609efd1436590d64aa7f47643fcaf1decc9c'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Ctable%3E%3Csvg%3E%3C/svg%3E%3C/table%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%3Ctable%3E"],"7900ad087a3da10cbd7eb3eae57181ca7e417f0e":[async_test('html5lib_tests10.html 7900ad087a3da10cbd7eb3eae57181ca7e417f0e'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Ctable%3E%3Csvg%3E%3Cg%3Efoo%3C/g%3E%3C/svg%3E%3C/table%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20g%3E%0A%7C%20%20%20%20%20%20%20%20%20%22foo%22%0A%7C%20%20%20%20%20%3Ctable%3E"],"52f78e3d4b60a998fe249f7c026078f13ef65fe3":[async_test('html5lib_tests10.html 52f78e3d4b60a998fe249f7c026078f13ef65fe3'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Ctable%3E%3Csvg%3E%3Cg%3Efoo%3C/g%3E%3Cg%3Ebar%3C/g%3E%3C/svg%3E%3C/table%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20g%3E%0A%7C%20%20%20%20%20%20%20%20%20%22foo%22%0A%7C%20%20%20%20%20%20%20%3Csvg%20g%3E%0A%7C%20%20%20%20%20%20%20%20%20%22bar%22%0A%7C%20%20%20%20%20%3Ctable%3E"],"01dd3726b85de9278486adaf23c7cd553ea701b0":[async_test('html5lib_tests10.html 01dd3726b85de9278486adaf23c7cd553ea701b0'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Ctable%3E%3Ctbody%3E%3Csvg%3E%3Cg%3Efoo%3C/g%3E%3Cg%3Ebar%3C/g%3E%3C/svg%3E%3C/tbody%3E%3C/table%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20g%3E%0A%7C%20%20%20%20%20%20%20%20%20%22foo%22%0A%7C%20%20%20%20%20%20%20%3Csvg%20g%3E%0A%7C%20%20%20%20%20%20%20%20%20%22bar%22%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E"],"c993a3cf01522d1b958e942f781c535bd63e7f43":[async_test('html5lib_tests10.html c993a3cf01522d1b958e942f781c535bd63e7f43'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Ctable%3E%3Ctbody%3E%3Ctr%3E%3Csvg%3E%3Cg%3Efoo%3C/g%3E%3Cg%3Ebar%3C/g%3E%3C/svg%3E%3C/tr%3E%3C/tbody%3E%3C/table%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20g%3E%0A%7C%20%20%20%20%20%20%20%20%20%22foo%22%0A%7C%20%20%20%20%20%20%20%3Csvg%20g%3E%0A%7C%20%20%20%20%20%20%20%20%20%22bar%22%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E"],"3f8ac796f286506aa56f87a8b430c4d6d2802695":[async_test('html5lib_tests10.html 3f8ac796f286506aa56f87a8b430c4d6d2802695'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Ctable%3E%3Ctbody%3E%3Ctr%3E%3Ctd%3E%3Csvg%3E%3Cg%3Efoo%3C/g%3E%3Cg%3Ebar%3C/g%3E%3C/svg%3E%3C/td%3E%3C/tr%3E%3C/tbody%3E%3C/table%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Csvg%20g%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22foo%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Csvg%20g%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22bar%22"],"df1f29ea6a1d57e029cdb95216b85e9daac07ad0":[async_test('html5lib_tests10.html df1f29ea6a1d57e029cdb95216b85e9daac07ad0'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Ctable%3E%3Ctbody%3E%3Ctr%3E%3Ctd%3E%3Csvg%3E%3Cg%3Efoo%3C/g%3E%3Cg%3Ebar%3C/g%3E%3C/svg%3E%3Cp%3Ebaz%3C/td%3E%3C/tr%3E%3C/tbody%3E%3C/table%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Csvg%20g%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22foo%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Csvg%20g%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22bar%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22baz%22"],"ae19484ce5b8e2087e3df7f13183622d2cf059a7":[async_test('html5lib_tests10.html ae19484ce5b8e2087e3df7f13183622d2cf059a7'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Ctable%3E%3Ccaption%3E%3Csvg%3E%3Cg%3Efoo%3C/g%3E%3Cg%3Ebar%3C/g%3E%3C/svg%3E%3Cp%3Ebaz%3C/caption%3E%3C/table%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ccaption%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Csvg%20g%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%22foo%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Csvg%20g%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%22bar%22%0A%7C%20%20%20%20%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22baz%22"],"7f9c4aeecce3bbf1483104213487a506cfdc6650":[async_test('html5lib_tests10.html 7f9c4aeecce3bbf1483104213487a506cfdc6650'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Ctable%3E%3Ccaption%3E%3Csvg%3E%3Cg%3Efoo%3C/g%3E%3Cg%3Ebar%3C/g%3E%3Cp%3Ebaz%3C/table%3E%3Cp%3Equux", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ccaption%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Csvg%20g%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%22foo%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Csvg%20g%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%22bar%22%0A%7C%20%20%20%20%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22baz%22%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%22quux%22"],"219f8f9866ad87d2e98f0cbbf35e0d7070848f81":[async_test('html5lib_tests10.html 219f8f9866ad87d2e98f0cbbf35e0d7070848f81'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Ctable%3E%3Ccaption%3E%3Csvg%3E%3Cg%3Efoo%3C/g%3E%3Cg%3Ebar%3C/g%3Ebaz%3C/table%3E%3Cp%3Equux", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ccaption%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Csvg%20g%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%22foo%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Csvg%20g%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%22bar%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22baz%22%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%22quux%22"],"a1e3a3515da712da9fa9bae0ab874a0a31207e6b":[async_test('html5lib_tests10.html a1e3a3515da712da9fa9bae0ab874a0a31207e6b'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Ctable%3E%3Ccolgroup%3E%3Csvg%3E%3Cg%3Efoo%3C/g%3E%3Cg%3Ebar%3C/g%3E%3Cp%3Ebaz%3C/table%3E%3Cp%3Equux", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20g%3E%0A%7C%20%20%20%20%20%20%20%20%20%22foo%22%0A%7C%20%20%20%20%20%20%20%3Csvg%20g%3E%0A%7C%20%20%20%20%20%20%20%20%20%22bar%22%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%22baz%22%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ccolgroup%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%22quux%22"],"badaa2069df3f2bb2d2da79f8ae2598f66ab2d0f":[async_test('html5lib_tests10.html badaa2069df3f2bb2d2da79f8ae2598f66ab2d0f'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Ctable%3E%3Ctr%3E%3Ctd%3E%3Cselect%3E%3Csvg%3E%3Cg%3Efoo%3C/g%3E%3Cg%3Ebar%3C/g%3E%3Cp%3Ebaz%3C/table%3E%3Cp%3Equux", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cselect%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22foobarbaz%22%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%22quux%22"],"64e72bd5af825a0b014a78c77d6d0be8c330892b":[async_test('html5lib_tests10.html 64e72bd5af825a0b014a78c77d6d0be8c330892b'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Ctable%3E%3Cselect%3E%3Csvg%3E%3Cg%3Efoo%3C/g%3E%3Cg%3Ebar%3C/g%3E%3Cp%3Ebaz%3C/table%3E%3Cp%3Equux", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cselect%3E%0A%7C%20%20%20%20%20%20%20%22foobarbaz%22%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%22quux%22"],"6b6728b11b3f67a6b67e0dec03222222783e2c40":[async_test('html5lib_tests10.html 6b6728b11b3f67a6b67e0dec03222222783e2c40'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3C/body%3E%3C/html%3E%3Csvg%3E%3Cg%3Efoo%3C/g%3E%3Cg%3Ebar%3C/g%3E%3Cp%3Ebaz", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20g%3E%0A%7C%20%20%20%20%20%20%20%20%20%22foo%22%0A%7C%20%20%20%20%20%20%20%3Csvg%20g%3E%0A%7C%20%20%20%20%20%20%20%20%20%22bar%22%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%22baz%22"],"c16f6e833fafc8e96c4d888aace5e7df190f8bb5":[async_test('html5lib_tests10.html c16f6e833fafc8e96c4d888aace5e7df190f8bb5'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3C/body%3E%3Csvg%3E%3Cg%3Efoo%3C/g%3E%3Cg%3Ebar%3C/g%3E%3Cp%3Ebaz", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20g%3E%0A%7C%20%20%20%20%20%20%20%20%20%22foo%22%0A%7C%20%20%20%20%20%20%20%3Csvg%20g%3E%0A%7C%20%20%20%20%20%20%20%20%20%22bar%22%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%22baz%22"],"8b5cc06ce9513c4b0b2be26adad3357c79a10241":[async_test('html5lib_tests10.html 8b5cc06ce9513c4b0b2be26adad3357c79a10241'), "%3C%21DOCTYPE%20html%3E%3Cframeset%3E%3Csvg%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cp%3E%3Cspan%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E"],"f396d620bf4e128981156d61f4768634c407c806":[async_test('html5lib_tests10.html f396d620bf4e128981156d61f4768634c407c806'), "%3C%21DOCTYPE%20html%3E%3Cframeset%3E%3C/frameset%3E%3Csvg%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cp%3E%3Cspan%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E"],"3c262f2c74c6cf5519cfad9440e118dd36fcc37f":[async_test('html5lib_tests10.html 3c262f2c74c6cf5519cfad9440e118dd36fcc37f'), "%3C%21DOCTYPE%20html%3E%3Cbody%20xlink%3Ahref%3Dfoo%3E%3Csvg%20xlink%3Ahref%3Dfoo%3E%3C/svg%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20xlink%3Ahref%3D%22foo%22%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20xlink%20href%3D%22foo%22"],"4e788a289a02c283f0a7b71340f4947c30fd289e":[async_test('html5lib_tests10.html 4e788a289a02c283f0a7b71340f4947c30fd289e'), "%3C%21DOCTYPE%20html%3E%3Cbody%20xlink%3Ahref%3Dfoo%20xml%3Alang%3Den%3E%3Csvg%3E%3Cg%20xml%3Alang%3Den%20xlink%3Ahref%3Dfoo%3E%3C/g%3E%3C/svg%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20xlink%3Ahref%3D%22foo%22%0A%7C%20%20%20%20%20xml%3Alang%3D%22en%22%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20g%3E%0A%7C%20%20%20%20%20%20%20%20%20xlink%20href%3D%22foo%22%0A%7C%20%20%20%20%20%20%20%20%20xml%20lang%3D%22en%22"],"b0a2a300705d9a5b6ceb8f7b9d4d240a9eb9f9e0":[async_test('html5lib_tests10.html b0a2a300705d9a5b6ceb8f7b9d4d240a9eb9f9e0'), "%3C%21DOCTYPE%20html%3E%3Cbody%20xlink%3Ahref%3Dfoo%20xml%3Alang%3Den%3E%3Csvg%3E%3Cg%20xml%3Alang%3Den%20xlink%3Ahref%3Dfoo%20/%3E%3C/svg%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20xlink%3Ahref%3D%22foo%22%0A%7C%20%20%20%20%20xml%3Alang%3D%22en%22%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20g%3E%0A%7C%20%20%20%20%20%20%20%20%20xlink%20href%3D%22foo%22%0A%7C%20%20%20%20%20%20%20%20%20xml%20lang%3D%22en%22"],"2e92f741697be25c07416f7885b7decc0684c874":[async_test('html5lib_tests10.html 2e92f741697be25c07416f7885b7decc0684c874'), "%3C%21DOCTYPE%20html%3E%3Cbody%20xlink%3Ahref%3Dfoo%20xml%3Alang%3Den%3E%3Csvg%3E%3Cg%20xml%3Alang%3Den%20xlink%3Ahref%3Dfoo%20/%3Ebar%3C/svg%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20xlink%3Ahref%3D%22foo%22%0A%7C%20%20%20%20%20xml%3Alang%3D%22en%22%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20g%3E%0A%7C%20%20%20%20%20%20%20%20%20xlink%20href%3D%22foo%22%0A%7C%20%20%20%20%20%20%20%20%20xml%20lang%3D%22en%22%0A%7C%20%20%20%20%20%20%20%22bar%22"],"3cffa6d987cfd48c6cd5f9e7d198ca0e79b6cdb8":[async_test('html5lib_tests10.html 3cffa6d987cfd48c6cd5f9e7d198ca0e79b6cdb8'), "%3Csvg%3E%3C/path%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E"],"f89f8c14aeaa1d3107b6aa6d87fbf10e8fd5f8c3":[async_test('html5lib_tests10.html f89f8c14aeaa1d3107b6aa6d87fbf10e8fd5f8c3'), "%3Cdiv%3E%3Csvg%3E%3C/div%3Ea", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%22a%22"],"663691222288a8f734149fba4f1b7ff5bb201df0":[async_test('html5lib_tests10.html 663691222288a8f734149fba4f1b7ff5bb201df0'), "%3Cdiv%3E%3Csvg%3E%3Cpath%3E%3C/div%3Ea", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Csvg%20path%3E%0A%7C%20%20%20%20%20%22a%22"],"dbe5123aed0264b7fe421fea4b9bc5bd304cc596":[async_test('html5lib_tests10.html dbe5123aed0264b7fe421fea4b9bc5bd304cc596'), "%3Cdiv%3E%3Csvg%3E%3Cpath%3E%3C/svg%3E%3Cpath%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Csvg%20path%3E%0A%7C%20%20%20%20%20%20%20%3Cpath%3E"],"982e01ebddec435aeb2dc0f23fa77e4201a38b28":[async_test('html5lib_tests10.html 982e01ebddec435aeb2dc0f23fa77e4201a38b28'), "%3Cdiv%3E%3Csvg%3E%3Cpath%3E%3CforeignObject%3E%3Cmath%3E%3C/div%3Ea", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Csvg%20path%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Csvg%20foreignObject%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22a%22"],"b613b907ffa87da6f3076a24ad775843e5c2a43a":[async_test('html5lib_tests10.html b613b907ffa87da6f3076a24ad775843e5c2a43a'), "%3Cdiv%3E%3Csvg%3E%3Cpath%3E%3CforeignObject%3E%3Cp%3E%3C/div%3Ea", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Csvg%20path%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Csvg%20foreignObject%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22a%22"],"4553fc5ae2782aef4100d8db614041e42c3612e9":[async_test('html5lib_tests10.html 4553fc5ae2782aef4100d8db614041e42c3612e9'), "%3C%21DOCTYPE%20html%3E%3Csvg%3E%3Cdesc%3E%3Cdiv%3E%3Csvg%3E%3Cul%3Ea", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20desc%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cul%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%22a%22"],"6c10b9811a0d228cf26bc0b55ee12c7d99926270":[async_test('html5lib_tests10.html 6c10b9811a0d228cf26bc0b55ee12c7d99926270'), "%3C%21DOCTYPE%20html%3E%3Csvg%3E%3Cdesc%3E%3Csvg%3E%3Cul%3Ea", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20desc%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cul%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22a%22"],"ee2de7753d6594fbf05d321b24e2c8bb6f2323c6":[async_test('html5lib_tests10.html ee2de7753d6594fbf05d321b24e2c8bb6f2323c6'), "%3C%21DOCTYPE%20html%3E%3Cp%3E%3Csvg%3E%3Cdesc%3E%3Cp%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Csvg%20desc%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cp%3E"],"225170b3f08201a11d43f153fa3c8a041173b55f":[async_test('html5lib_tests10.html 225170b3f08201a11d43f153fa3c8a041173b55f'), "%3C%21DOCTYPE%20html%3E%3Cp%3E%3Csvg%3E%3Ctitle%3E%3Cp%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Csvg%20title%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cp%3E"],"716a01ee7d076876318395625e08e555065fc3b0":[async_test('html5lib_tests10.html 716a01ee7d076876318395625e08e555065fc3b0'), "%3Cdiv%3E%3Csvg%3E%3Cpath%3E%3CforeignObject%3E%3Cp%3E%3C/foreignObject%3E%3Cp%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Csvg%20path%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Csvg%20foreignObject%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cp%3E"],"3c5cc236386d2d4a16d14e5c65da7edd26697a43":[async_test('html5lib_tests10.html 3c5cc236386d2d4a16d14e5c65da7edd26697a43'), "%3Cmath%3E%3Cmi%3E%3Cdiv%3E%3Cobject%3E%3Cdiv%3E%3Cspan%3E%3C/span%3E%3C/div%3E%3C/object%3E%3C/div%3E%3C/mi%3E%3Cmi%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20mi%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cobject%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cspan%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20mi%3E"],"6c3447a16060d2805f8c969ec0a7b5c551468f25":[async_test('html5lib_tests10.html 6c3447a16060d2805f8c969ec0a7b5c551468f25'), "%3Cmath%3E%3Cmi%3E%3Csvg%3E%3CforeignObject%3E%3Cdiv%3E%3Cdiv%3E%3C/div%3E%3C/div%3E%3C/foreignObject%3E%3C/svg%3E%3C/mi%3E%3Cmi%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20mi%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Csvg%20foreignObject%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20mi%3E"],"071f13f248eb7af8f7d512cf453b16c8ccc57483":[async_test('html5lib_tests10.html 071f13f248eb7af8f7d512cf453b16c8ccc57483'), "%3Csvg%3E%3Cscript%3E%3C/script%3E%3Cpath%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20script%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20path%3E"],"0ef97c924e3e5e8ddf8a0bc74530868684685c38":[async_test('html5lib_tests10.html 0ef97c924e3e5e8ddf8a0bc74530868684685c38'), "%3Ctable%3E%3Csvg%3E%3C/svg%3E%3Ctr%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E"],"25a94dd91d982fa75c89944ad8f066f7961c590b":[async_test('html5lib_tests10.html 25a94dd91d982fa75c89944ad8f066f7961c590b'), "%3Cmath%3E%3Cmi%3E%3Cmglyph%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20mi%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cmath%20mglyph%3E"],"575adfd2e679ad44140d8afd131fee2e5e819fc0":[async_test('html5lib_tests10.html 575adfd2e679ad44140d8afd131fee2e5e819fc0'), "%3Cmath%3E%3Cmi%3E%3Cmalignmark%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20mi%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cmath%20malignmark%3E"],"2eb6893275ff1de69569440710f5588b8558ca17":[async_test('html5lib_tests10.html 2eb6893275ff1de69569440710f5588b8558ca17'), "%3Cmath%3E%3Cmo%3E%3Cmglyph%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20mo%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cmath%20mglyph%3E"],"4f57b212888bfcc7ac6d8e29ef444cc7ae3ec495":[async_test('html5lib_tests10.html 4f57b212888bfcc7ac6d8e29ef444cc7ae3ec495'), "%3Cmath%3E%3Cmo%3E%3Cmalignmark%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20mo%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cmath%20malignmark%3E"],"c069a88f172919c862432dbef290a425e71414aa":[async_test('html5lib_tests10.html c069a88f172919c862432dbef290a425e71414aa'), "%3Cmath%3E%3Cmn%3E%3Cmglyph%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20mn%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cmath%20mglyph%3E"],"f944f978d6a10ec9f194f03a5e232f9663d96ec1":[async_test('html5lib_tests10.html f944f978d6a10ec9f194f03a5e232f9663d96ec1'), "%3Cmath%3E%3Cmn%3E%3Cmalignmark%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20mn%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cmath%20malignmark%3E"],"d5ab79a14609f3ed214baa8e02bedb54ddcf33ec":[async_test('html5lib_tests10.html d5ab79a14609f3ed214baa8e02bedb54ddcf33ec'), "%3Cmath%3E%3Cms%3E%3Cmglyph%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20ms%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cmath%20mglyph%3E"],"4318bf46f0256426716a911e194f9bdf6185bd7c":[async_test('html5lib_tests10.html 4318bf46f0256426716a911e194f9bdf6185bd7c'), "%3Cmath%3E%3Cms%3E%3Cmalignmark%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20ms%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cmath%20malignmark%3E"],"aa5c4b093ee603618493cff853af125b5fb0d401":[async_test('html5lib_tests10.html aa5c4b093ee603618493cff853af125b5fb0d401'), "%3Cmath%3E%3Cmtext%3E%3Cmglyph%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20mtext%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cmath%20mglyph%3E"],"bfd98674d75ff3291d377f2a7cec3321844a0701":[async_test('html5lib_tests10.html bfd98674d75ff3291d377f2a7cec3321844a0701'), "%3Cmath%3E%3Cmtext%3E%3Cmalignmark%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20mtext%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cmath%20malignmark%3E"],"7fc99b729a6d57d28b2ad1edc33bb15167e051bb":[async_test('html5lib_tests10.html 7fc99b729a6d57d28b2ad1edc33bb15167e051bb'), "%3Cmath%3E%3Cannotation-xml%3E%3Csvg%3E%3C/svg%3E%3C/annotation-xml%3E%3Cmi%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20annotation-xml%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20mi%3E"],"8e87f0d5ca606ca162384d1bf3bb8de62bd6f398":[async_test('html5lib_tests10.html 8e87f0d5ca606ca162384d1bf3bb8de62bd6f398'), "%3Cmath%3E%3Cannotation-xml%3E%3Csvg%3E%3CforeignObject%3E%3Cdiv%3E%3Cmath%3E%3Cmi%3E%3C/mi%3E%3C/math%3E%3Cspan%3E%3C/span%3E%3C/div%3E%3C/foreignObject%3E%3Cpath%3E%3C/path%3E%3C/svg%3E%3C/annotation-xml%3E%3Cmi%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20annotation-xml%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Csvg%20foreignObject%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cmath%20mi%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cspan%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Csvg%20path%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20mi%3E"],"6476f80f3d2a04e9c1323ffe78686188c579e9ac":[async_test('html5lib_tests10.html 6476f80f3d2a04e9c1323ffe78686188c579e9ac'), "%3Cmath%3E%3Cannotation-xml%3E%3Csvg%3E%3CforeignObject%3E%3Cmath%3E%3Cmi%3E%3Csvg%3E%3C/svg%3E%3C/mi%3E%3Cmo%3E%3C/mo%3E%3C/math%3E%3Cspan%3E%3C/span%3E%3C/foreignObject%3E%3Cpath%3E%3C/path%3E%3C/svg%3E%3C/annotation-xml%3E%3Cmi%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20annotation-xml%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Csvg%20foreignObject%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cmath%20mi%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cmath%20mo%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cspan%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Csvg%20path%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20mi%3E"],
+ }
+ init_tests(get_type());
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests11.html b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests11.html
new file mode 100644
index 00000000000..e21b0328a23
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests11.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf8">
+ <title>HTML 5 Parser tests html5lib_tests11.html</title>
+ <meta name="timeout" content="long">
+ <meta name="variant" content="?run_type=uri">
+ <meta name="variant" content="?run_type=write">
+ <meta name="variant" content="?run_type=write_single">
+ </head>
+ <body>
+ <h1>html5lib Parser Test</h1>
+ <div id="log"></div>
+ <script src="common.js"></script>
+ <script src="test.js"></script>
+ <script src="template.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ var num_iframes = 8;
+ var order = ['d3a8de194ffc676baf08142bcda59ba18dcde2ba','7ab36bc30d0d6bee4be899f13baed214e1ff0a74','45b6adfc38d306084d105aa7779a3b4fb83c031f','b6ce0d4b36700a2f000199109155d1869f3c8d2f','39c50f080b2b9ae9e7a1070679ab97d7b814f9ec','6d1fa1599f75625fe4d019abb04a064cf6ed39e8','791437ece7ba684e00162d1dd79dfe540e3621a7','af40d26164229c29b9be77ed6dd7dda780cba55c','16e68d18f8f0fb81013fe77a30b7d396c5081e5e',];
+ var tests = {
+ "d3a8de194ffc676baf08142bcda59ba18dcde2ba":[async_test('html5lib_tests11.html d3a8de194ffc676baf08142bcda59ba18dcde2ba'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Csvg%20attributeName%3D%27%27%20attributeType%3D%27%27%20baseFrequency%3D%27%27%20baseProfile%3D%27%27%20calcMode%3D%27%27%20clipPathUnits%3D%27%27%20contentScriptType%3D%27%27%20contentStyleType%3D%27%27%20diffuseConstant%3D%27%27%20edgeMode%3D%27%27%20externalResourcesRequired%3D%27%27%20filterRes%3D%27%27%20filterUnits%3D%27%27%20glyphRef%3D%27%27%20gradientTransform%3D%27%27%20gradientUnits%3D%27%27%20kernelMatrix%3D%27%27%20kernelUnitLength%3D%27%27%20keyPoints%3D%27%27%20keySplines%3D%27%27%20keyTimes%3D%27%27%20lengthAdjust%3D%27%27%20limitingConeAngle%3D%27%27%20markerHeight%3D%27%27%20markerUnits%3D%27%27%20markerWidth%3D%27%27%20maskContentUnits%3D%27%27%20maskUnits%3D%27%27%20numOctaves%3D%27%27%20pathLength%3D%27%27%20patternContentUnits%3D%27%27%20patternTransform%3D%27%27%20patternUnits%3D%27%27%20pointsAtX%3D%27%27%20pointsAtY%3D%27%27%20pointsAtZ%3D%27%27%20preserveAlpha%3D%27%27%20preserveAspectRatio%3D%27%27%20primitiveUnits%3D%27%27%20refX%3D%27%27%20refY%3D%27%27%20repeatCount%3D%27%27%20repeatDur%3D%27%27%20requiredExtensions%3D%27%27%20requiredFeatures%3D%27%27%20specularConstant%3D%27%27%20specularExponent%3D%27%27%20spreadMethod%3D%27%27%20startOffset%3D%27%27%20stdDeviation%3D%27%27%20stitchTiles%3D%27%27%20surfaceScale%3D%27%27%20systemLanguage%3D%27%27%20tableValues%3D%27%27%20targetX%3D%27%27%20targetY%3D%27%27%20textLength%3D%27%27%20viewBox%3D%27%27%20viewTarget%3D%27%27%20xChannelSelector%3D%27%27%20yChannelSelector%3D%27%27%20zoomAndPan%3D%27%27%3E%3C/svg%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20attributeName%3D%22%22%0A%7C%20%20%20%20%20%20%20attributeType%3D%22%22%0A%7C%20%20%20%20%20%20%20baseFrequency%3D%22%22%0A%7C%20%20%20%20%20%20%20baseProfile%3D%22%22%0A%7C%20%20%20%20%20%20%20calcMode%3D%22%22%0A%7C%20%20%20%20%20%20%20clipPathUnits%3D%22%22%0A%7C%20%20%20%20%20%20%20contentscripttype%3D%22%22%0A%7C%20%20%20%20%20%20%20contentstyletype%3D%22%22%0A%7C%20%20%20%20%20%20%20diffuseConstant%3D%22%22%0A%7C%20%20%20%20%20%20%20edgeMode%3D%22%22%0A%7C%20%20%20%20%20%20%20externalresourcesrequired%3D%22%22%0A%7C%20%20%20%20%20%20%20filterUnits%3D%22%22%0A%7C%20%20%20%20%20%20%20filterres%3D%22%22%0A%7C%20%20%20%20%20%20%20glyphRef%3D%22%22%0A%7C%20%20%20%20%20%20%20gradientTransform%3D%22%22%0A%7C%20%20%20%20%20%20%20gradientUnits%3D%22%22%0A%7C%20%20%20%20%20%20%20kernelMatrix%3D%22%22%0A%7C%20%20%20%20%20%20%20kernelUnitLength%3D%22%22%0A%7C%20%20%20%20%20%20%20keyPoints%3D%22%22%0A%7C%20%20%20%20%20%20%20keySplines%3D%22%22%0A%7C%20%20%20%20%20%20%20keyTimes%3D%22%22%0A%7C%20%20%20%20%20%20%20lengthAdjust%3D%22%22%0A%7C%20%20%20%20%20%20%20limitingConeAngle%3D%22%22%0A%7C%20%20%20%20%20%20%20markerHeight%3D%22%22%0A%7C%20%20%20%20%20%20%20markerUnits%3D%22%22%0A%7C%20%20%20%20%20%20%20markerWidth%3D%22%22%0A%7C%20%20%20%20%20%20%20maskContentUnits%3D%22%22%0A%7C%20%20%20%20%20%20%20maskUnits%3D%22%22%0A%7C%20%20%20%20%20%20%20numOctaves%3D%22%22%0A%7C%20%20%20%20%20%20%20pathLength%3D%22%22%0A%7C%20%20%20%20%20%20%20patternContentUnits%3D%22%22%0A%7C%20%20%20%20%20%20%20patternTransform%3D%22%22%0A%7C%20%20%20%20%20%20%20patternUnits%3D%22%22%0A%7C%20%20%20%20%20%20%20pointsAtX%3D%22%22%0A%7C%20%20%20%20%20%20%20pointsAtY%3D%22%22%0A%7C%20%20%20%20%20%20%20pointsAtZ%3D%22%22%0A%7C%20%20%20%20%20%20%20preserveAlpha%3D%22%22%0A%7C%20%20%20%20%20%20%20preserveAspectRatio%3D%22%22%0A%7C%20%20%20%20%20%20%20primitiveUnits%3D%22%22%0A%7C%20%20%20%20%20%20%20refX%3D%22%22%0A%7C%20%20%20%20%20%20%20refY%3D%22%22%0A%7C%20%20%20%20%20%20%20repeatCount%3D%22%22%0A%7C%20%20%20%20%20%20%20repeatDur%3D%22%22%0A%7C%20%20%20%20%20%20%20requiredExtensions%3D%22%22%0A%7C%20%20%20%20%20%20%20requiredFeatures%3D%22%22%0A%7C%20%20%20%20%20%20%20specularConstant%3D%22%22%0A%7C%20%20%20%20%20%20%20specularExponent%3D%22%22%0A%7C%20%20%20%20%20%20%20spreadMethod%3D%22%22%0A%7C%20%20%20%20%20%20%20startOffset%3D%22%22%0A%7C%20%20%20%20%20%20%20stdDeviation%3D%22%22%0A%7C%20%20%20%20%20%20%20stitchTiles%3D%22%22%0A%7C%20%20%20%20%20%20%20surfaceScale%3D%22%22%0A%7C%20%20%20%20%20%20%20systemLanguage%3D%22%22%0A%7C%20%20%20%20%20%20%20tableValues%3D%22%22%0A%7C%20%20%20%20%20%20%20targetX%3D%22%22%0A%7C%20%20%20%20%20%20%20targetY%3D%22%22%0A%7C%20%20%20%20%20%20%20textLength%3D%22%22%0A%7C%20%20%20%20%20%20%20viewBox%3D%22%22%0A%7C%20%20%20%20%20%20%20viewTarget%3D%22%22%0A%7C%20%20%20%20%20%20%20xChannelSelector%3D%22%22%0A%7C%20%20%20%20%20%20%20yChannelSelector%3D%22%22%0A%7C%20%20%20%20%20%20%20zoomAndPan%3D%22%22"],"7ab36bc30d0d6bee4be899f13baed214e1ff0a74":[async_test('html5lib_tests11.html 7ab36bc30d0d6bee4be899f13baed214e1ff0a74'), "%3C%21DOCTYPE%20html%3E%3CBODY%3E%3CSVG%20ATTRIBUTENAME%3D%27%27%20ATTRIBUTETYPE%3D%27%27%20BASEFREQUENCY%3D%27%27%20BASEPROFILE%3D%27%27%20CALCMODE%3D%27%27%20CLIPPATHUNITS%3D%27%27%20CONTENTSCRIPTTYPE%3D%27%27%20CONTENTSTYLETYPE%3D%27%27%20DIFFUSECONSTANT%3D%27%27%20EDGEMODE%3D%27%27%20EXTERNALRESOURCESREQUIRED%3D%27%27%20FILTERRES%3D%27%27%20FILTERUNITS%3D%27%27%20GLYPHREF%3D%27%27%20GRADIENTTRANSFORM%3D%27%27%20GRADIENTUNITS%3D%27%27%20KERNELMATRIX%3D%27%27%20KERNELUNITLENGTH%3D%27%27%20KEYPOINTS%3D%27%27%20KEYSPLINES%3D%27%27%20KEYTIMES%3D%27%27%20LENGTHADJUST%3D%27%27%20LIMITINGCONEANGLE%3D%27%27%20MARKERHEIGHT%3D%27%27%20MARKERUNITS%3D%27%27%20MARKERWIDTH%3D%27%27%20MASKCONTENTUNITS%3D%27%27%20MASKUNITS%3D%27%27%20NUMOCTAVES%3D%27%27%20PATHLENGTH%3D%27%27%20PATTERNCONTENTUNITS%3D%27%27%20PATTERNTRANSFORM%3D%27%27%20PATTERNUNITS%3D%27%27%20POINTSATX%3D%27%27%20POINTSATY%3D%27%27%20POINTSATZ%3D%27%27%20PRESERVEALPHA%3D%27%27%20PRESERVEASPECTRATIO%3D%27%27%20PRIMITIVEUNITS%3D%27%27%20REFX%3D%27%27%20REFY%3D%27%27%20REPEATCOUNT%3D%27%27%20REPEATDUR%3D%27%27%20REQUIREDEXTENSIONS%3D%27%27%20REQUIREDFEATURES%3D%27%27%20SPECULARCONSTANT%3D%27%27%20SPECULAREXPONENT%3D%27%27%20SPREADMETHOD%3D%27%27%20STARTOFFSET%3D%27%27%20STDDEVIATION%3D%27%27%20STITCHTILES%3D%27%27%20SURFACESCALE%3D%27%27%20SYSTEMLANGUAGE%3D%27%27%20TABLEVALUES%3D%27%27%20TARGETX%3D%27%27%20TARGETY%3D%27%27%20TEXTLENGTH%3D%27%27%20VIEWBOX%3D%27%27%20VIEWTARGET%3D%27%27%20XCHANNELSELECTOR%3D%27%27%20YCHANNELSELECTOR%3D%27%27%20ZOOMANDPAN%3D%27%27%3E%3C/SVG%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20attributeName%3D%22%22%0A%7C%20%20%20%20%20%20%20attributeType%3D%22%22%0A%7C%20%20%20%20%20%20%20baseFrequency%3D%22%22%0A%7C%20%20%20%20%20%20%20baseProfile%3D%22%22%0A%7C%20%20%20%20%20%20%20calcMode%3D%22%22%0A%7C%20%20%20%20%20%20%20clipPathUnits%3D%22%22%0A%7C%20%20%20%20%20%20%20contentscripttype%3D%22%22%0A%7C%20%20%20%20%20%20%20contentstyletype%3D%22%22%0A%7C%20%20%20%20%20%20%20diffuseConstant%3D%22%22%0A%7C%20%20%20%20%20%20%20edgeMode%3D%22%22%0A%7C%20%20%20%20%20%20%20externalresourcesrequired%3D%22%22%0A%7C%20%20%20%20%20%20%20filterUnits%3D%22%22%0A%7C%20%20%20%20%20%20%20filterres%3D%22%22%0A%7C%20%20%20%20%20%20%20glyphRef%3D%22%22%0A%7C%20%20%20%20%20%20%20gradientTransform%3D%22%22%0A%7C%20%20%20%20%20%20%20gradientUnits%3D%22%22%0A%7C%20%20%20%20%20%20%20kernelMatrix%3D%22%22%0A%7C%20%20%20%20%20%20%20kernelUnitLength%3D%22%22%0A%7C%20%20%20%20%20%20%20keyPoints%3D%22%22%0A%7C%20%20%20%20%20%20%20keySplines%3D%22%22%0A%7C%20%20%20%20%20%20%20keyTimes%3D%22%22%0A%7C%20%20%20%20%20%20%20lengthAdjust%3D%22%22%0A%7C%20%20%20%20%20%20%20limitingConeAngle%3D%22%22%0A%7C%20%20%20%20%20%20%20markerHeight%3D%22%22%0A%7C%20%20%20%20%20%20%20markerUnits%3D%22%22%0A%7C%20%20%20%20%20%20%20markerWidth%3D%22%22%0A%7C%20%20%20%20%20%20%20maskContentUnits%3D%22%22%0A%7C%20%20%20%20%20%20%20maskUnits%3D%22%22%0A%7C%20%20%20%20%20%20%20numOctaves%3D%22%22%0A%7C%20%20%20%20%20%20%20pathLength%3D%22%22%0A%7C%20%20%20%20%20%20%20patternContentUnits%3D%22%22%0A%7C%20%20%20%20%20%20%20patternTransform%3D%22%22%0A%7C%20%20%20%20%20%20%20patternUnits%3D%22%22%0A%7C%20%20%20%20%20%20%20pointsAtX%3D%22%22%0A%7C%20%20%20%20%20%20%20pointsAtY%3D%22%22%0A%7C%20%20%20%20%20%20%20pointsAtZ%3D%22%22%0A%7C%20%20%20%20%20%20%20preserveAlpha%3D%22%22%0A%7C%20%20%20%20%20%20%20preserveAspectRatio%3D%22%22%0A%7C%20%20%20%20%20%20%20primitiveUnits%3D%22%22%0A%7C%20%20%20%20%20%20%20refX%3D%22%22%0A%7C%20%20%20%20%20%20%20refY%3D%22%22%0A%7C%20%20%20%20%20%20%20repeatCount%3D%22%22%0A%7C%20%20%20%20%20%20%20repeatDur%3D%22%22%0A%7C%20%20%20%20%20%20%20requiredExtensions%3D%22%22%0A%7C%20%20%20%20%20%20%20requiredFeatures%3D%22%22%0A%7C%20%20%20%20%20%20%20specularConstant%3D%22%22%0A%7C%20%20%20%20%20%20%20specularExponent%3D%22%22%0A%7C%20%20%20%20%20%20%20spreadMethod%3D%22%22%0A%7C%20%20%20%20%20%20%20startOffset%3D%22%22%0A%7C%20%20%20%20%20%20%20stdDeviation%3D%22%22%0A%7C%20%20%20%20%20%20%20stitchTiles%3D%22%22%0A%7C%20%20%20%20%20%20%20surfaceScale%3D%22%22%0A%7C%20%20%20%20%20%20%20systemLanguage%3D%22%22%0A%7C%20%20%20%20%20%20%20tableValues%3D%22%22%0A%7C%20%20%20%20%20%20%20targetX%3D%22%22%0A%7C%20%20%20%20%20%20%20targetY%3D%22%22%0A%7C%20%20%20%20%20%20%20textLength%3D%22%22%0A%7C%20%20%20%20%20%20%20viewBox%3D%22%22%0A%7C%20%20%20%20%20%20%20viewTarget%3D%22%22%0A%7C%20%20%20%20%20%20%20xChannelSelector%3D%22%22%0A%7C%20%20%20%20%20%20%20yChannelSelector%3D%22%22%0A%7C%20%20%20%20%20%20%20zoomAndPan%3D%22%22"],"45b6adfc38d306084d105aa7779a3b4fb83c031f":[async_test('html5lib_tests11.html 45b6adfc38d306084d105aa7779a3b4fb83c031f'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Csvg%20attributename%3D%27%27%20attributetype%3D%27%27%20basefrequency%3D%27%27%20baseprofile%3D%27%27%20calcmode%3D%27%27%20clippathunits%3D%27%27%20contentscripttype%3D%27%27%20contentstyletype%3D%27%27%20diffuseconstant%3D%27%27%20edgemode%3D%27%27%20externalresourcesrequired%3D%27%27%20filterres%3D%27%27%20filterunits%3D%27%27%20glyphref%3D%27%27%20gradienttransform%3D%27%27%20gradientunits%3D%27%27%20kernelmatrix%3D%27%27%20kernelunitlength%3D%27%27%20keypoints%3D%27%27%20keysplines%3D%27%27%20keytimes%3D%27%27%20lengthadjust%3D%27%27%20limitingconeangle%3D%27%27%20markerheight%3D%27%27%20markerunits%3D%27%27%20markerwidth%3D%27%27%20maskcontentunits%3D%27%27%20maskunits%3D%27%27%20numoctaves%3D%27%27%20pathlength%3D%27%27%20patterncontentunits%3D%27%27%20patterntransform%3D%27%27%20patternunits%3D%27%27%20pointsatx%3D%27%27%20pointsaty%3D%27%27%20pointsatz%3D%27%27%20preservealpha%3D%27%27%20preserveaspectratio%3D%27%27%20primitiveunits%3D%27%27%20refx%3D%27%27%20refy%3D%27%27%20repeatcount%3D%27%27%20repeatdur%3D%27%27%20requiredextensions%3D%27%27%20requiredfeatures%3D%27%27%20specularconstant%3D%27%27%20specularexponent%3D%27%27%20spreadmethod%3D%27%27%20startoffset%3D%27%27%20stddeviation%3D%27%27%20stitchtiles%3D%27%27%20surfacescale%3D%27%27%20systemlanguage%3D%27%27%20tablevalues%3D%27%27%20targetx%3D%27%27%20targety%3D%27%27%20textlength%3D%27%27%20viewbox%3D%27%27%20viewtarget%3D%27%27%20xchannelselector%3D%27%27%20ychannelselector%3D%27%27%20zoomandpan%3D%27%27%3E%3C/svg%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20attributeName%3D%22%22%0A%7C%20%20%20%20%20%20%20attributeType%3D%22%22%0A%7C%20%20%20%20%20%20%20baseFrequency%3D%22%22%0A%7C%20%20%20%20%20%20%20baseProfile%3D%22%22%0A%7C%20%20%20%20%20%20%20calcMode%3D%22%22%0A%7C%20%20%20%20%20%20%20clipPathUnits%3D%22%22%0A%7C%20%20%20%20%20%20%20contentscripttype%3D%22%22%0A%7C%20%20%20%20%20%20%20contentstyletype%3D%22%22%0A%7C%20%20%20%20%20%20%20diffuseConstant%3D%22%22%0A%7C%20%20%20%20%20%20%20edgeMode%3D%22%22%0A%7C%20%20%20%20%20%20%20externalresourcesrequired%3D%22%22%0A%7C%20%20%20%20%20%20%20filterUnits%3D%22%22%0A%7C%20%20%20%20%20%20%20filterres%3D%22%22%0A%7C%20%20%20%20%20%20%20glyphRef%3D%22%22%0A%7C%20%20%20%20%20%20%20gradientTransform%3D%22%22%0A%7C%20%20%20%20%20%20%20gradientUnits%3D%22%22%0A%7C%20%20%20%20%20%20%20kernelMatrix%3D%22%22%0A%7C%20%20%20%20%20%20%20kernelUnitLength%3D%22%22%0A%7C%20%20%20%20%20%20%20keyPoints%3D%22%22%0A%7C%20%20%20%20%20%20%20keySplines%3D%22%22%0A%7C%20%20%20%20%20%20%20keyTimes%3D%22%22%0A%7C%20%20%20%20%20%20%20lengthAdjust%3D%22%22%0A%7C%20%20%20%20%20%20%20limitingConeAngle%3D%22%22%0A%7C%20%20%20%20%20%20%20markerHeight%3D%22%22%0A%7C%20%20%20%20%20%20%20markerUnits%3D%22%22%0A%7C%20%20%20%20%20%20%20markerWidth%3D%22%22%0A%7C%20%20%20%20%20%20%20maskContentUnits%3D%22%22%0A%7C%20%20%20%20%20%20%20maskUnits%3D%22%22%0A%7C%20%20%20%20%20%20%20numOctaves%3D%22%22%0A%7C%20%20%20%20%20%20%20pathLength%3D%22%22%0A%7C%20%20%20%20%20%20%20patternContentUnits%3D%22%22%0A%7C%20%20%20%20%20%20%20patternTransform%3D%22%22%0A%7C%20%20%20%20%20%20%20patternUnits%3D%22%22%0A%7C%20%20%20%20%20%20%20pointsAtX%3D%22%22%0A%7C%20%20%20%20%20%20%20pointsAtY%3D%22%22%0A%7C%20%20%20%20%20%20%20pointsAtZ%3D%22%22%0A%7C%20%20%20%20%20%20%20preserveAlpha%3D%22%22%0A%7C%20%20%20%20%20%20%20preserveAspectRatio%3D%22%22%0A%7C%20%20%20%20%20%20%20primitiveUnits%3D%22%22%0A%7C%20%20%20%20%20%20%20refX%3D%22%22%0A%7C%20%20%20%20%20%20%20refY%3D%22%22%0A%7C%20%20%20%20%20%20%20repeatCount%3D%22%22%0A%7C%20%20%20%20%20%20%20repeatDur%3D%22%22%0A%7C%20%20%20%20%20%20%20requiredExtensions%3D%22%22%0A%7C%20%20%20%20%20%20%20requiredFeatures%3D%22%22%0A%7C%20%20%20%20%20%20%20specularConstant%3D%22%22%0A%7C%20%20%20%20%20%20%20specularExponent%3D%22%22%0A%7C%20%20%20%20%20%20%20spreadMethod%3D%22%22%0A%7C%20%20%20%20%20%20%20startOffset%3D%22%22%0A%7C%20%20%20%20%20%20%20stdDeviation%3D%22%22%0A%7C%20%20%20%20%20%20%20stitchTiles%3D%22%22%0A%7C%20%20%20%20%20%20%20surfaceScale%3D%22%22%0A%7C%20%20%20%20%20%20%20systemLanguage%3D%22%22%0A%7C%20%20%20%20%20%20%20tableValues%3D%22%22%0A%7C%20%20%20%20%20%20%20targetX%3D%22%22%0A%7C%20%20%20%20%20%20%20targetY%3D%22%22%0A%7C%20%20%20%20%20%20%20textLength%3D%22%22%0A%7C%20%20%20%20%20%20%20viewBox%3D%22%22%0A%7C%20%20%20%20%20%20%20viewTarget%3D%22%22%0A%7C%20%20%20%20%20%20%20xChannelSelector%3D%22%22%0A%7C%20%20%20%20%20%20%20yChannelSelector%3D%22%22%0A%7C%20%20%20%20%20%20%20zoomAndPan%3D%22%22"],"b6ce0d4b36700a2f000199109155d1869f3c8d2f":[async_test('html5lib_tests11.html b6ce0d4b36700a2f000199109155d1869f3c8d2f'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Cmath%20attributeName%3D%27%27%20attributeType%3D%27%27%20baseFrequency%3D%27%27%20baseProfile%3D%27%27%20calcMode%3D%27%27%20clipPathUnits%3D%27%27%20contentScriptType%3D%27%27%20contentStyleType%3D%27%27%20diffuseConstant%3D%27%27%20edgeMode%3D%27%27%20externalResourcesRequired%3D%27%27%20filterRes%3D%27%27%20filterUnits%3D%27%27%20glyphRef%3D%27%27%20gradientTransform%3D%27%27%20gradientUnits%3D%27%27%20kernelMatrix%3D%27%27%20kernelUnitLength%3D%27%27%20keyPoints%3D%27%27%20keySplines%3D%27%27%20keyTimes%3D%27%27%20lengthAdjust%3D%27%27%20limitingConeAngle%3D%27%27%20markerHeight%3D%27%27%20markerUnits%3D%27%27%20markerWidth%3D%27%27%20maskContentUnits%3D%27%27%20maskUnits%3D%27%27%20numOctaves%3D%27%27%20pathLength%3D%27%27%20patternContentUnits%3D%27%27%20patternTransform%3D%27%27%20patternUnits%3D%27%27%20pointsAtX%3D%27%27%20pointsAtY%3D%27%27%20pointsAtZ%3D%27%27%20preserveAlpha%3D%27%27%20preserveAspectRatio%3D%27%27%20primitiveUnits%3D%27%27%20refX%3D%27%27%20refY%3D%27%27%20repeatCount%3D%27%27%20repeatDur%3D%27%27%20requiredExtensions%3D%27%27%20requiredFeatures%3D%27%27%20specularConstant%3D%27%27%20specularExponent%3D%27%27%20spreadMethod%3D%27%27%20startOffset%3D%27%27%20stdDeviation%3D%27%27%20stitchTiles%3D%27%27%20surfaceScale%3D%27%27%20systemLanguage%3D%27%27%20tableValues%3D%27%27%20targetX%3D%27%27%20targetY%3D%27%27%20textLength%3D%27%27%20viewBox%3D%27%27%20viewTarget%3D%27%27%20xChannelSelector%3D%27%27%20yChannelSelector%3D%27%27%20zoomAndPan%3D%27%27%3E%3C/math%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20attributename%3D%22%22%0A%7C%20%20%20%20%20%20%20attributetype%3D%22%22%0A%7C%20%20%20%20%20%20%20basefrequency%3D%22%22%0A%7C%20%20%20%20%20%20%20baseprofile%3D%22%22%0A%7C%20%20%20%20%20%20%20calcmode%3D%22%22%0A%7C%20%20%20%20%20%20%20clippathunits%3D%22%22%0A%7C%20%20%20%20%20%20%20contentscripttype%3D%22%22%0A%7C%20%20%20%20%20%20%20contentstyletype%3D%22%22%0A%7C%20%20%20%20%20%20%20diffuseconstant%3D%22%22%0A%7C%20%20%20%20%20%20%20edgemode%3D%22%22%0A%7C%20%20%20%20%20%20%20externalresourcesrequired%3D%22%22%0A%7C%20%20%20%20%20%20%20filterres%3D%22%22%0A%7C%20%20%20%20%20%20%20filterunits%3D%22%22%0A%7C%20%20%20%20%20%20%20glyphref%3D%22%22%0A%7C%20%20%20%20%20%20%20gradienttransform%3D%22%22%0A%7C%20%20%20%20%20%20%20gradientunits%3D%22%22%0A%7C%20%20%20%20%20%20%20kernelmatrix%3D%22%22%0A%7C%20%20%20%20%20%20%20kernelunitlength%3D%22%22%0A%7C%20%20%20%20%20%20%20keypoints%3D%22%22%0A%7C%20%20%20%20%20%20%20keysplines%3D%22%22%0A%7C%20%20%20%20%20%20%20keytimes%3D%22%22%0A%7C%20%20%20%20%20%20%20lengthadjust%3D%22%22%0A%7C%20%20%20%20%20%20%20limitingconeangle%3D%22%22%0A%7C%20%20%20%20%20%20%20markerheight%3D%22%22%0A%7C%20%20%20%20%20%20%20markerunits%3D%22%22%0A%7C%20%20%20%20%20%20%20markerwidth%3D%22%22%0A%7C%20%20%20%20%20%20%20maskcontentunits%3D%22%22%0A%7C%20%20%20%20%20%20%20maskunits%3D%22%22%0A%7C%20%20%20%20%20%20%20numoctaves%3D%22%22%0A%7C%20%20%20%20%20%20%20pathlength%3D%22%22%0A%7C%20%20%20%20%20%20%20patterncontentunits%3D%22%22%0A%7C%20%20%20%20%20%20%20patterntransform%3D%22%22%0A%7C%20%20%20%20%20%20%20patternunits%3D%22%22%0A%7C%20%20%20%20%20%20%20pointsatx%3D%22%22%0A%7C%20%20%20%20%20%20%20pointsaty%3D%22%22%0A%7C%20%20%20%20%20%20%20pointsatz%3D%22%22%0A%7C%20%20%20%20%20%20%20preservealpha%3D%22%22%0A%7C%20%20%20%20%20%20%20preserveaspectratio%3D%22%22%0A%7C%20%20%20%20%20%20%20primitiveunits%3D%22%22%0A%7C%20%20%20%20%20%20%20refx%3D%22%22%0A%7C%20%20%20%20%20%20%20refy%3D%22%22%0A%7C%20%20%20%20%20%20%20repeatcount%3D%22%22%0A%7C%20%20%20%20%20%20%20repeatdur%3D%22%22%0A%7C%20%20%20%20%20%20%20requiredextensions%3D%22%22%0A%7C%20%20%20%20%20%20%20requiredfeatures%3D%22%22%0A%7C%20%20%20%20%20%20%20specularconstant%3D%22%22%0A%7C%20%20%20%20%20%20%20specularexponent%3D%22%22%0A%7C%20%20%20%20%20%20%20spreadmethod%3D%22%22%0A%7C%20%20%20%20%20%20%20startoffset%3D%22%22%0A%7C%20%20%20%20%20%20%20stddeviation%3D%22%22%0A%7C%20%20%20%20%20%20%20stitchtiles%3D%22%22%0A%7C%20%20%20%20%20%20%20surfacescale%3D%22%22%0A%7C%20%20%20%20%20%20%20systemlanguage%3D%22%22%0A%7C%20%20%20%20%20%20%20tablevalues%3D%22%22%0A%7C%20%20%20%20%20%20%20targetx%3D%22%22%0A%7C%20%20%20%20%20%20%20targety%3D%22%22%0A%7C%20%20%20%20%20%20%20textlength%3D%22%22%0A%7C%20%20%20%20%20%20%20viewbox%3D%22%22%0A%7C%20%20%20%20%20%20%20viewtarget%3D%22%22%0A%7C%20%20%20%20%20%20%20xchannelselector%3D%22%22%0A%7C%20%20%20%20%20%20%20ychannelselector%3D%22%22%0A%7C%20%20%20%20%20%20%20zoomandpan%3D%22%22"],"39c50f080b2b9ae9e7a1070679ab97d7b814f9ec":[async_test('html5lib_tests11.html 39c50f080b2b9ae9e7a1070679ab97d7b814f9ec'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Csvg%3E%3CaltGlyph%20/%3E%3CaltGlyphDef%20/%3E%3CaltGlyphItem%20/%3E%3CanimateColor%20/%3E%3CanimateMotion%20/%3E%3CanimateTransform%20/%3E%3CclipPath%20/%3E%3CfeBlend%20/%3E%3CfeColorMatrix%20/%3E%3CfeComponentTransfer%20/%3E%3CfeComposite%20/%3E%3CfeConvolveMatrix%20/%3E%3CfeDiffuseLighting%20/%3E%3CfeDisplacementMap%20/%3E%3CfeDistantLight%20/%3E%3CfeFlood%20/%3E%3CfeFuncA%20/%3E%3CfeFuncB%20/%3E%3CfeFuncG%20/%3E%3CfeFuncR%20/%3E%3CfeGaussianBlur%20/%3E%3CfeImage%20/%3E%3CfeMerge%20/%3E%3CfeMergeNode%20/%3E%3CfeMorphology%20/%3E%3CfeOffset%20/%3E%3CfePointLight%20/%3E%3CfeSpecularLighting%20/%3E%3CfeSpotLight%20/%3E%3CfeTile%20/%3E%3CfeTurbulence%20/%3E%3CforeignObject%20/%3E%3CglyphRef%20/%3E%3ClinearGradient%20/%3E%3CradialGradient%20/%3E%3CtextPath%20/%3E%3C/svg%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20altGlyph%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20altGlyphDef%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20altGlyphItem%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20animateColor%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20animateMotion%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20animateTransform%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20clipPath%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feBlend%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feColorMatrix%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feComponentTransfer%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feComposite%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feConvolveMatrix%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feDiffuseLighting%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feDisplacementMap%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feDistantLight%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feFlood%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feFuncA%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feFuncB%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feFuncG%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feFuncR%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feGaussianBlur%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feImage%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feMerge%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feMergeNode%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feMorphology%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feOffset%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20fePointLight%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feSpecularLighting%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feSpotLight%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feTile%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feTurbulence%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20foreignObject%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20glyphRef%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20linearGradient%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20radialGradient%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20textPath%3E"],"6d1fa1599f75625fe4d019abb04a064cf6ed39e8":[async_test('html5lib_tests11.html 6d1fa1599f75625fe4d019abb04a064cf6ed39e8'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Csvg%3E%3Caltglyph%20/%3E%3Caltglyphdef%20/%3E%3Caltglyphitem%20/%3E%3Canimatecolor%20/%3E%3Canimatemotion%20/%3E%3Canimatetransform%20/%3E%3Cclippath%20/%3E%3Cfeblend%20/%3E%3Cfecolormatrix%20/%3E%3Cfecomponenttransfer%20/%3E%3Cfecomposite%20/%3E%3Cfeconvolvematrix%20/%3E%3Cfediffuselighting%20/%3E%3Cfedisplacementmap%20/%3E%3Cfedistantlight%20/%3E%3Cfeflood%20/%3E%3Cfefunca%20/%3E%3Cfefuncb%20/%3E%3Cfefuncg%20/%3E%3Cfefuncr%20/%3E%3Cfegaussianblur%20/%3E%3Cfeimage%20/%3E%3Cfemerge%20/%3E%3Cfemergenode%20/%3E%3Cfemorphology%20/%3E%3Cfeoffset%20/%3E%3Cfepointlight%20/%3E%3Cfespecularlighting%20/%3E%3Cfespotlight%20/%3E%3Cfetile%20/%3E%3Cfeturbulence%20/%3E%3Cforeignobject%20/%3E%3Cglyphref%20/%3E%3Clineargradient%20/%3E%3Cradialgradient%20/%3E%3Ctextpath%20/%3E%3C/svg%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20altGlyph%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20altGlyphDef%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20altGlyphItem%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20animateColor%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20animateMotion%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20animateTransform%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20clipPath%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feBlend%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feColorMatrix%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feComponentTransfer%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feComposite%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feConvolveMatrix%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feDiffuseLighting%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feDisplacementMap%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feDistantLight%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feFlood%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feFuncA%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feFuncB%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feFuncG%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feFuncR%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feGaussianBlur%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feImage%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feMerge%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feMergeNode%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feMorphology%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feOffset%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20fePointLight%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feSpecularLighting%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feSpotLight%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feTile%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feTurbulence%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20foreignObject%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20glyphRef%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20linearGradient%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20radialGradient%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20textPath%3E"],"791437ece7ba684e00162d1dd79dfe540e3621a7":[async_test('html5lib_tests11.html 791437ece7ba684e00162d1dd79dfe540e3621a7'), "%3C%21DOCTYPE%20html%3E%3CBODY%3E%3CSVG%3E%3CALTGLYPH%20/%3E%3CALTGLYPHDEF%20/%3E%3CALTGLYPHITEM%20/%3E%3CANIMATECOLOR%20/%3E%3CANIMATEMOTION%20/%3E%3CANIMATETRANSFORM%20/%3E%3CCLIPPATH%20/%3E%3CFEBLEND%20/%3E%3CFECOLORMATRIX%20/%3E%3CFECOMPONENTTRANSFER%20/%3E%3CFECOMPOSITE%20/%3E%3CFECONVOLVEMATRIX%20/%3E%3CFEDIFFUSELIGHTING%20/%3E%3CFEDISPLACEMENTMAP%20/%3E%3CFEDISTANTLIGHT%20/%3E%3CFEFLOOD%20/%3E%3CFEFUNCA%20/%3E%3CFEFUNCB%20/%3E%3CFEFUNCG%20/%3E%3CFEFUNCR%20/%3E%3CFEGAUSSIANBLUR%20/%3E%3CFEIMAGE%20/%3E%3CFEMERGE%20/%3E%3CFEMERGENODE%20/%3E%3CFEMORPHOLOGY%20/%3E%3CFEOFFSET%20/%3E%3CFEPOINTLIGHT%20/%3E%3CFESPECULARLIGHTING%20/%3E%3CFESPOTLIGHT%20/%3E%3CFETILE%20/%3E%3CFETURBULENCE%20/%3E%3CFOREIGNOBJECT%20/%3E%3CGLYPHREF%20/%3E%3CLINEARGRADIENT%20/%3E%3CRADIALGRADIENT%20/%3E%3CTEXTPATH%20/%3E%3C/SVG%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20altGlyph%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20altGlyphDef%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20altGlyphItem%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20animateColor%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20animateMotion%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20animateTransform%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20clipPath%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feBlend%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feColorMatrix%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feComponentTransfer%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feComposite%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feConvolveMatrix%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feDiffuseLighting%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feDisplacementMap%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feDistantLight%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feFlood%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feFuncA%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feFuncB%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feFuncG%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feFuncR%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feGaussianBlur%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feImage%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feMerge%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feMergeNode%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feMorphology%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feOffset%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20fePointLight%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feSpecularLighting%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feSpotLight%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feTile%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20feTurbulence%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20foreignObject%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20glyphRef%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20linearGradient%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20radialGradient%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20textPath%3E"],"af40d26164229c29b9be77ed6dd7dda780cba55c":[async_test('html5lib_tests11.html af40d26164229c29b9be77ed6dd7dda780cba55c'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Cmath%3E%3CaltGlyph%20/%3E%3CaltGlyphDef%20/%3E%3CaltGlyphItem%20/%3E%3CanimateColor%20/%3E%3CanimateMotion%20/%3E%3CanimateTransform%20/%3E%3CclipPath%20/%3E%3CfeBlend%20/%3E%3CfeColorMatrix%20/%3E%3CfeComponentTransfer%20/%3E%3CfeComposite%20/%3E%3CfeConvolveMatrix%20/%3E%3CfeDiffuseLighting%20/%3E%3CfeDisplacementMap%20/%3E%3CfeDistantLight%20/%3E%3CfeFlood%20/%3E%3CfeFuncA%20/%3E%3CfeFuncB%20/%3E%3CfeFuncG%20/%3E%3CfeFuncR%20/%3E%3CfeGaussianBlur%20/%3E%3CfeImage%20/%3E%3CfeMerge%20/%3E%3CfeMergeNode%20/%3E%3CfeMorphology%20/%3E%3CfeOffset%20/%3E%3CfePointLight%20/%3E%3CfeSpecularLighting%20/%3E%3CfeSpotLight%20/%3E%3CfeTile%20/%3E%3CfeTurbulence%20/%3E%3CforeignObject%20/%3E%3CglyphRef%20/%3E%3ClinearGradient%20/%3E%3CradialGradient%20/%3E%3CtextPath%20/%3E%3C/math%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20altglyph%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20altglyphdef%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20altglyphitem%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20animatecolor%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20animatemotion%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20animatetransform%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20clippath%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20feblend%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20fecolormatrix%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20fecomponenttransfer%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20fecomposite%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20feconvolvematrix%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20fediffuselighting%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20fedisplacementmap%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20fedistantlight%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20feflood%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20fefunca%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20fefuncb%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20fefuncg%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20fefuncr%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20fegaussianblur%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20feimage%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20femerge%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20femergenode%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20femorphology%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20feoffset%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20fepointlight%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20fespecularlighting%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20fespotlight%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20fetile%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20feturbulence%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20foreignobject%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20glyphref%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20lineargradient%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20radialgradient%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20textpath%3E"],"16e68d18f8f0fb81013fe77a30b7d396c5081e5e":[async_test('html5lib_tests11.html 16e68d18f8f0fb81013fe77a30b7d396c5081e5e'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Csvg%3E%3CsolidColor%20/%3E%3C/svg%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20solidcolor%3E"],
+ }
+ init_tests(get_type());
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests12.html b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests12.html
new file mode 100644
index 00000000000..4c1b388f04e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests12.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf8">
+ <title>HTML 5 Parser tests html5lib_tests12.html</title>
+ <meta name="timeout" content="long">
+ <meta name="variant" content="?run_type=uri">
+ <meta name="variant" content="?run_type=write">
+ <meta name="variant" content="?run_type=write_single">
+ </head>
+ <body>
+ <h1>html5lib Parser Test</h1>
+ <div id="log"></div>
+ <script src="common.js"></script>
+ <script src="test.js"></script>
+ <script src="template.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ var num_iframes = 8;
+ var order = ['95751b82f57d4feaaf06d208d57b7f6cc4d5fef5','411c792cef85cbb029d5c91f4a2142751a319bc2',];
+ var tests = {
+ "95751b82f57d4feaaf06d208d57b7f6cc4d5fef5":[async_test('html5lib_tests12.html 95751b82f57d4feaaf06d208d57b7f6cc4d5fef5'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Cp%3Efoo%3Cmath%3E%3Cmtext%3E%3Ci%3Ebaz%3C/i%3E%3C/mtext%3E%3Cannotation-xml%3E%3Csvg%3E%3Cdesc%3E%3Cb%3Eeggs%3C/b%3E%3C/desc%3E%3Cg%3E%3CforeignObject%3E%3CP%3Espam%3CTABLE%3E%3Ctr%3E%3Ctd%3E%3Cimg%3E%3C/td%3E%3C/table%3E%3C/foreignObject%3E%3C/g%3E%3Cg%3Equux%3C/g%3E%3C/svg%3E%3C/annotation-xml%3E%3C/math%3Ebar", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%22foo%22%0A%7C%20%20%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cmath%20mtext%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%22baz%22%0A%7C%20%20%20%20%20%20%20%20%20%3Cmath%20annotation-xml%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Csvg%20desc%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22eggs%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Csvg%20g%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Csvg%20foreignObject%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22spam%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cimg%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Csvg%20g%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22quux%22%0A%7C%20%20%20%20%20%20%20%22bar%22"],"411c792cef85cbb029d5c91f4a2142751a319bc2":[async_test('html5lib_tests12.html 411c792cef85cbb029d5c91f4a2142751a319bc2'), "%3C%21DOCTYPE%20html%3E%3Cbody%3Efoo%3Cmath%3E%3Cmtext%3E%3Ci%3Ebaz%3C/i%3E%3C/mtext%3E%3Cannotation-xml%3E%3Csvg%3E%3Cdesc%3E%3Cb%3Eeggs%3C/b%3E%3C/desc%3E%3Cg%3E%3CforeignObject%3E%3CP%3Espam%3CTABLE%3E%3Ctr%3E%3Ctd%3E%3Cimg%3E%3C/td%3E%3C/table%3E%3C/foreignObject%3E%3C/g%3E%3Cg%3Equux%3C/g%3E%3C/svg%3E%3C/annotation-xml%3E%3C/math%3Ebar", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22foo%22%0A%7C%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20mtext%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22baz%22%0A%7C%20%20%20%20%20%20%20%3Cmath%20annotation-xml%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Csvg%20desc%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22eggs%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Csvg%20g%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Csvg%20foreignObject%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22spam%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cimg%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Csvg%20g%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%22quux%22%0A%7C%20%20%20%20%20%22bar%22"],
+ }
+ init_tests(get_type());
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests14.html b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests14.html
new file mode 100644
index 00000000000..b1a4323c2d9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests14.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf8">
+ <title>HTML 5 Parser tests html5lib_tests14.html</title>
+ <meta name="timeout" content="long">
+ <meta name="variant" content="?run_type=uri">
+ <meta name="variant" content="?run_type=write">
+ <meta name="variant" content="?run_type=write_single">
+ </head>
+ <body>
+ <h1>html5lib Parser Test</h1>
+ <div id="log"></div>
+ <script src="common.js"></script>
+ <script src="test.js"></script>
+ <script src="template.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ var num_iframes = 8;
+ var order = ['d0faa36cd34bbc8e41bacd676e995aef68cb8ef7','9d97df65d72e97363840684da4e164b50c4bf1cb','c5de9372cd188bc22d40d4ad08eb6f787ab521ea','d16e1c0655b2086c1bd995cf6f1c5c7106e48ef0','383a71bb62eacf93dcb2399c7dd7419d92a91899','ee5e2e4a3346d225907f27c1f12b3cb2e77c32c4','cd557ae48cd48356c367e470927d0fc108724409',];
+ var tests = {
+ "d0faa36cd34bbc8e41bacd676e995aef68cb8ef7":[async_test('html5lib_tests14.html d0faa36cd34bbc8e41bacd676e995aef68cb8ef7'), "%3C%21DOCTYPE%20html%3E%3Chtml%3E%3Cbody%3E%3Cxyz%3Aabc%3E%3C/xyz%3Aabc%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cxyz%3Aabc%3E"],"9d97df65d72e97363840684da4e164b50c4bf1cb":[async_test('html5lib_tests14.html 9d97df65d72e97363840684da4e164b50c4bf1cb'), "%3C%21DOCTYPE%20html%3E%3Chtml%3E%3Cbody%3E%3Cxyz%3Aabc%3E%3C/xyz%3Aabc%3E%3Cspan%3E%3C/span%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cxyz%3Aabc%3E%0A%7C%20%20%20%20%20%3Cspan%3E"],"c5de9372cd188bc22d40d4ad08eb6f787ab521ea":[async_test('html5lib_tests14.html c5de9372cd188bc22d40d4ad08eb6f787ab521ea'), "%3C%21DOCTYPE%20html%3E%3Chtml%3E%3Chtml%20abc%3Adef%3Dgh%3E%3Cxyz%3Aabc%3E%3C/xyz%3Aabc%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20abc%3Adef%3D%22gh%22%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cxyz%3Aabc%3E"],"d16e1c0655b2086c1bd995cf6f1c5c7106e48ef0":[async_test('html5lib_tests14.html d16e1c0655b2086c1bd995cf6f1c5c7106e48ef0'), "%3C%21DOCTYPE%20html%3E%3Chtml%20xml%3Alang%3Dbar%3E%3Chtml%20xml%3Alang%3Dfoo%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20xml%3Alang%3D%22bar%22%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"383a71bb62eacf93dcb2399c7dd7419d92a91899":[async_test('html5lib_tests14.html 383a71bb62eacf93dcb2399c7dd7419d92a91899'), "%3C%21DOCTYPE%20html%3E%3Chtml%20123%3D456%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20123%3D%22456%22%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"ee5e2e4a3346d225907f27c1f12b3cb2e77c32c4":[async_test('html5lib_tests14.html ee5e2e4a3346d225907f27c1f12b3cb2e77c32c4'), "%3C%21DOCTYPE%20html%3E%3Chtml%20123%3D456%3E%3Chtml%20789%3D012%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20123%3D%22456%22%0A%7C%20%20%20789%3D%22012%22%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"cd557ae48cd48356c367e470927d0fc108724409":[async_test('html5lib_tests14.html cd557ae48cd48356c367e470927d0fc108724409'), "%3C%21DOCTYPE%20html%3E%3Chtml%3E%3Cbody%20789%3D012%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20789%3D%22012%22"],
+ }
+ init_tests(get_type());
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests15.html b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests15.html
new file mode 100644
index 00000000000..3e9ac0cbe80
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests15.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf8">
+ <title>HTML 5 Parser tests html5lib_tests15.html</title>
+ <meta name="timeout" content="long">
+ <meta name="variant" content="?run_type=uri">
+ <meta name="variant" content="?run_type=write">
+ <meta name="variant" content="?run_type=write_single">
+ </head>
+ <body>
+ <h1>html5lib Parser Test</h1>
+ <div id="log"></div>
+ <script src="common.js"></script>
+ <script src="test.js"></script>
+ <script src="template.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ var num_iframes = 8;
+ var order = ['6b53427ced5c2da3830c5053af874df81b59f4dc','e4719f96139431e67dc783631eb1b3b25e0e62e8','6c880904728529240130ab72c30a1f800502e1fc','59cae979c2d8110a1015fd401afb42d1015e2c05','fdac591df8c2ff9db7bdd63adee17e002a620ea1','72352f74535e62a2b0623446073f3edb7698bcf3','93c2841d64ce8d4745de6a0fbd28ddba273fd3d0','e83c7f01a04d3ff180019d1578cc666f67ea71eb','8ed7e05d49dfc6701ef8325a5d9504d596d8d083','938af694979b4eae59e7bd3ab71d76e5254192a0','e7bba1876ae72e36eb68142d21f64fee1043cff6','fc3373f9cb00e32fc98435157d1d74a6a27a7fb9','f4c1486ad877d96aeb9a31fde16d2a93ada53b35','c1176256398117ceca6c3878106893855c39aa5a',];
+ var tests = {
+ "6b53427ced5c2da3830c5053af874df81b59f4dc":[async_test('html5lib_tests15.html 6b53427ced5c2da3830c5053af874df81b59f4dc'), "%3C%21DOCTYPE%20html%3E%3Cp%3E%3Cb%3E%3Ci%3E%3Cu%3E%3C/p%3E%20%3Cp%3EX", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cu%3E%0A%7C%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cu%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22%20%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%22X%22"],"e4719f96139431e67dc783631eb1b3b25e0e62e8":[async_test('html5lib_tests15.html e4719f96139431e67dc783631eb1b3b25e0e62e8'), "%3Cp%3E%3Cb%3E%3Ci%3E%3Cu%3E%3C/p%3E%0A%3Cp%3EX", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cu%3E%0A%7C%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cu%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22%0A%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%22X%22"],"6c880904728529240130ab72c30a1f800502e1fc":[async_test('html5lib_tests15.html 6c880904728529240130ab72c30a1f800502e1fc'), "%3C%21doctype%20html%3E%3C/html%3E%20%3Chead%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22%20%22"],"59cae979c2d8110a1015fd401afb42d1015e2c05":[async_test('html5lib_tests15.html 59cae979c2d8110a1015fd401afb42d1015e2c05'), "%3C%21doctype%20html%3E%3C/body%3E%3Cmeta%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cmeta%3E"],"fdac591df8c2ff9db7bdd63adee17e002a620ea1":[async_test('html5lib_tests15.html fdac591df8c2ff9db7bdd63adee17e002a620ea1'), "%3Chtml%3E%3C/html%3E%3C%21--%20foo%20--%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%3C%21--%20%20foo%20%20--%3E"],"72352f74535e62a2b0623446073f3edb7698bcf3":[async_test('html5lib_tests15.html 72352f74535e62a2b0623446073f3edb7698bcf3'), "%3C%21doctype%20html%3E%3C/body%3E%3Ctitle%3EX%3C/title%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctitle%3E%0A%7C%20%20%20%20%20%20%20%22X%22"],"93c2841d64ce8d4745de6a0fbd28ddba273fd3d0":[async_test('html5lib_tests15.html 93c2841d64ce8d4745de6a0fbd28ddba273fd3d0'), "%3C%21doctype%20html%3E%3Ctable%3E%20X%3Cmeta%3E%3C/table%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22%20X%22%0A%7C%20%20%20%20%20%3Cmeta%3E%0A%7C%20%20%20%20%20%3Ctable%3E"],"e83c7f01a04d3ff180019d1578cc666f67ea71eb":[async_test('html5lib_tests15.html e83c7f01a04d3ff180019d1578cc666f67ea71eb'), "%3C%21doctype%20html%3E%3Ctable%3E%20x%3C/table%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22%20x%22%0A%7C%20%20%20%20%20%3Ctable%3E"],"8ed7e05d49dfc6701ef8325a5d9504d596d8d083":[async_test('html5lib_tests15.html 8ed7e05d49dfc6701ef8325a5d9504d596d8d083'), "%3C%21doctype%20html%3E%3Ctable%3E%20x%20%3C/table%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22%20x%20%22%0A%7C%20%20%20%20%20%3Ctable%3E"],"938af694979b4eae59e7bd3ab71d76e5254192a0":[async_test('html5lib_tests15.html 938af694979b4eae59e7bd3ab71d76e5254192a0'), "%3C%21doctype%20html%3E%3Ctable%3E%3Ctr%3E%20x%3C/table%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22%20x%22%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E"],"e7bba1876ae72e36eb68142d21f64fee1043cff6":[async_test('html5lib_tests15.html e7bba1876ae72e36eb68142d21f64fee1043cff6'), "%3C%21doctype%20html%3E%3Ctable%3EX%3Cstyle%3E%20%3Ctr%3Ex%20%3C/style%3E%20%3C/table%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22X%22%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Cstyle%3E%0A%7C%20%20%20%20%20%20%20%20%20%22%20%3Ctr%3Ex%20%22%0A%7C%20%20%20%20%20%20%20%22%20%22"],"fc3373f9cb00e32fc98435157d1d74a6a27a7fb9":[async_test('html5lib_tests15.html fc3373f9cb00e32fc98435157d1d74a6a27a7fb9'), "%3C%21doctype%20html%3E%3Cdiv%3E%3Ctable%3E%3Ca%3Efoo%3C/a%3E%20%3Ctr%3E%3Ctd%3Ebar%3C/td%3E%20%3C/tr%3E%3C/table%3E%3C/div%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%22foo%22%0A%7C%20%20%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%20%20%22%20%22%0A%7C%20%20%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22bar%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%22%20%22"],"f4c1486ad877d96aeb9a31fde16d2a93ada53b35":[async_test('html5lib_tests15.html f4c1486ad877d96aeb9a31fde16d2a93ada53b35'), "%3Cframe%3E%3C/frame%3E%3C/frame%3E%3Cframeset%3E%3Cframe%3E%3Cframeset%3E%3Cframe%3E%3C/frameset%3E%3Cnoframes%3E%3C/frameset%3E%3Cnoframes%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E%0A%7C%20%20%20%20%20%3Cframe%3E%0A%7C%20%20%20%20%20%3Cframeset%3E%0A%7C%20%20%20%20%20%20%20%3Cframe%3E%0A%7C%20%20%20%20%20%3Cnoframes%3E%0A%7C%20%20%20%20%20%20%20%22%3C/frameset%3E%3Cnoframes%3E%22"],"c1176256398117ceca6c3878106893855c39aa5a":[async_test('html5lib_tests15.html c1176256398117ceca6c3878106893855c39aa5a'), "%3C%21DOCTYPE%20html%3E%3Cobject%3E%3C/html%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cobject%3E"],
+ }
+ init_tests(get_type());
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests16.html b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests16.html
new file mode 100644
index 00000000000..f6c8a027ce5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests16.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf8">
+ <title>HTML 5 Parser tests html5lib_tests16.html</title>
+ <meta name="timeout" content="long">
+ <meta name="variant" content="?run_type=uri">
+ <meta name="variant" content="?run_type=write">
+ <meta name="variant" content="?run_type=write_single">
+ </head>
+ <body>
+ <h1>html5lib Parser Test</h1>
+ <div id="log"></div>
+ <script src="common.js"></script>
+ <script src="test.js"></script>
+ <script src="template.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ var num_iframes = 8;
+ var order = ['6d8b9d29f1890d59ef2453cff3f6d57b7e398c5c','5d4ac4961f9d52a42f309886d16fbe9c55c198bb','132c6e3cd2659e15b69904c67981a04e81fabe78','bf0b3062e7cbe684380581919947333beef23a8c','cd76a82b9a4bde442e4f8819b37e6308e3eef8f5','747087d5bf2fe9a8a6c0ecf822211d93a4e0cc2a','413482922b0185970bfdd6008e6a0e70ad1b554f','0e3cc8b1f36a34fb3048bb4f01e0e7fec678ceef','3d7a659a8880588e831c7198867b65ac2a974353','46914793d44763c3cd37c3aef0c3689d826602d1','bc8ed1aea5ac5d7eac284386a5defe779eeab3d7','48e7e206aade47bdd9ad3a7cce2c9c86fb4227f6','cc10f706cec3e9356f8c42f77b970f669f74be03','9a6506b01fabf7ba73bb5c90f11b3898c2f119fa','f840264cf775999580e621a83d34af302e139632','efe27c508629d48cf36861e680918f11f48aad15','c51f18f140335e61f0158fadd282fb0f0c75bee6','76d621ce4bd9e462bacaa40ebf43e1ccb569bd21','70e4352779315880955134dfe67c53acb76c4850','b05be3f93446c26026591cbfee84b9603cd6f151','3f08f2e2326b621f819b73336f502610dd94d54f','4932d705ce9c31d4141a630d305e16ae130982e7','accb817d72edbb0d9f72e2c44f47055fb1719d0a','b7b2e78af3f5846dc7f67246c92d95aacc2bd996','52e03d2903a9556823275541c58c173ac077a2a9','1daec6e34a3b4b4ea28f3e90595052090e67cbf7','539e26d76efe146f95bd7b6bfa88ae2d29afd35a','ab43ce067468a33bb658e0d6cc542b9dbcd0c80f','3f93565e7a692675cc519326cc4122b5ea44b533','e579c03d00de7a95bad40602af783b4d7775ab78','1541ebd513bc357af538635050f1b3ec854648e5','ae91f664e0c85f63d21dddaa03a9104d27a9d5ce','17b1bf0912a302c2bed5358791fae3ea6d3efa7d','beac9d7ec99b6317c8504e80118dd0f2d5fad573','d5ead5851ba4d1cdac136d97a449e6b48b0c2cb4','17fe63597371d22c41ccbc4abcd8f468373559d7','26a585731ba7caa063ad5c87a09748a223e56639','91dc36fa03b62334c115db6d4b4a420ef1081753','b0ee0820468ee622b802020e20be120d3c534af2','65907331b39d13cc2128eb57afb7185f0173a953','c284310f4becf9d64252eaec25fe46de8c6e4f2c','63bbe135b3dbb75f2262ce1cc5e9259634596a55','c83e5a48a9409482b62903960b0a04a932832668','193aa9aa570a39d74e340e8d6ddd015ee0a7477c','0ce3d12fa6ac40027b789b09fd987194426e09e6','fd613c2eb713e158fae7a54c45a3d952efa3d5a7','14220896fd483fbeae58f2d69975acc99682be0c','11ca3aa17a2c0b1b6cfc0fb842105247272fbc8d','b524c040a6ab671b006713c8f117d494b11e92ce','9032e7dd5c12caaaf2baf259cee186aaaa67e0e7','aea756cf197079dc506242b729a1d16231644e31','7446d6b66ccedb48db489df92102a0cf439004ce','935849b22e851061994b7da0a7abb626cfe27cab','075cdcf1f8b05fe1a1306ae9702fb7442a76754c','c7d08dec7a358d06f64235f1f6189c0c53e7e75e','c0c7b3e8f7109cf2fef447c2ac28e1566a246a74','d95e3c1ce7b2b79e43654cc23a4a1fc65c084d82','49e2f750500035dfc265752923b58a26d743bc60','c9a6e8a5f0da04035a690465b85c49e1c7259390','7e0c780436a6c11fcdc39dfa30c7e40542bb4745','10b54008a6e2f12bbfcaa0d9e19c0f98d67dfb53','6cdd162096c7fb581b808d491baff3c1234b02e1','243a2da6a25d3d7641fac624e712f4c96376d23c','86ff3afe4315b87db9a5d1d566b029c775e62b94','e20f08402b6afc6d237e8261e512f89ce5299881','c48c5eae7882c00df9026ba16f890266291635f2','d055df57faa87a91d463956c4816bb9c67384c73','33cc450505dd8b55c690589d441a793bb8985f11','40077f2a5b88cf53f3a53485194fc29e39feb39b','10bd03da7b29a7ebe5e18e2163849c2521ae4555','39e7696382843bda945f5717030388257f54dad0','6d0edc9ca958384e4c608386588400b63f8cbc1a','0ec48786ebc1bf532930e5f442c83fc05d5ab873','763803287fa8300b3fd5a0285ce1ab6520640245','f9b350e5c8304caf954b333f54060cd1ab377b47','c82aa963e4443053afe065da586dc6f5df062f9f','a97946be8e03c386e23023e6b6184d11517fc4f5','5b1e9bf7ee6e6222b78d38d99ffd3d0281b930a3','252c0a3870902b1fdf15224188ffd5abf56ced5f','10f2c0e9041fe19c9aea3c9f6a61842372242691','a68fa9f51d285e08b95b34a1ad7ae303d1180cda','1553cebdf01dc953ed7983d39a18752a4fbb24d7','802e7c9b307082d9f15835722eb9ef2dee60ea5f','c7f41e79f00db5b41872c0ef1443094e7ad5bc22','ae3967a139a3ecf61ecbc59c8c769a2731626fac','3586a5a4a1d1d69b139d139b0823af4753bc3e8d','0e99e2603bc91553c252713108e30495d71c3f37','f9858d096fa1e68cce0742d125c551878d2d7020','225e87bce5a4518c3e5cd248ef93ebc39dba14e0','bb08b00b361470ce18b435c97aff4449dc98cc51','cd74b727c1c8233f98e325293a2307e882e10f41','367bf426c092467300f78e5d7526b5a95b490871','96630ff73c222ae5aa31c5d8d32391c00e01d4ae','efd159c8bb96c72857a1b23247240fef25c4bc16','302c14341a82cd1ed9c77beb7ad60ce574f764ff','40369d98631eb17e8ae0cad61d9b7d6dbcddf424','4285eba81853a6d9ea3121ffa93f1b68bb33c157','824bd03d81ed9d5c1d3effe1ea45db39c27d520e','5593651c759624a4b7d91f3e07fc3e02c9bc6642','8862cf5a3972eec607fabbac4bd1dcf5eb50c3f2','bdaf31925507cd81bace2411601cb50be9ed3339','7df307e7cede64fda865c44c0897fc6191ce788c','8f275021b4d57f5235abc4efa2f53d0c633a22d6','b3b17f7b0a43afc62fcc24602488f7c1535eafb1','4383e943d6be1525114a923c5c5c7875d3506f43','c47db9cd301d75cc4ff1f4f66a70efaf04d88d34','c02e6a5ec0971e7e860b61f3638baecfe8d12edc','b3e566664033b9b6c550d44627807a9c17ac0fec','e1b7c9e452fbd47b9f62901e2802d4880c9798d5','20b70b5e4c22aae23ed2f06f957d611b60a16e69','80275b0c1f6bd16a37660822a9accc973b9ad6f6','0707f977884170b8e752fb7956e658e60b96a39c','3634374d8c7b8c049cfeb6cc9cab3284103d7745','1cef2f6f416ac760843e475fdc3aca248fde2a64','bcc75b33353806f86f5ecb7137309fe33fbc39cf','2b2b5615880e8fdd80ec772540344d3bf9f6cf98','87f5714929355b5a84c5bd86ade881e98135bbb8','bc926c61b947962e23f1424d178e8b6caec63984','0f8650ed2fd554c65428eed896e5a6d0276ffe43','e6c000aaa91a5cf04f15a4b6775e17d1bd9143b7','6783594161f7848e42e7c89a32da546163892d75','9c23cc23237032d8decf39d3d886a300c9304707','985c2415bc39a322004bbba6817df37dcdf3f10b','649e75657bd308f81f93189a02efa6b9a7702902','d42bb3557b0fbbe59cf5f606445ba973d4a3d720','d0178734ef1a063624bfd6a737dba933a54bf63d','f6ac88b3fe1743a446da7e0ad895b8f46ea31b23','fb513439a4a4683ec8fc60dc5f2d5588bd656910','4ed828c62d9dcc18ecf8608c9c38708b0b89b83d','51bbdaeed5d24b370a3456040561f8cad226b1a7','45b8f97a3a29d8b1d5e7b7f2586189ead21873b7','1ca26210654f4c95e3f5a337922cd5e8b0694789','a2cd3e4d9dfccfe71bbf5780b537396b5f76c0d6','bb1450fbedebc1605f79eaa4dc501f47d1d7feb6','a9d29f0909132226fd57de4a55282f95682778fd','1fdf0dda892b230252ce864b5c7073ee09aa9165','af1c863ec4e65c29006a0c98ef0872950618a05e','18763f4dd0f9681f043e0124ac26b76795f8afad','499e8bdd759619c5c2248e854e7cd9148ff5fe6d','b442057918b0f6954cf88be6da17b0c5ace03382','8a4c1d1a49ab635498f581f8341f0f037178d01d','c4d806ce1a7cb0abe0cb26e6950839b47134dc68','189378cd03b029adb6e679b6a349124155c697b7','6c9b32168850736c788f14208a39e70272ccc54e','2e9cd7a39540b3bd1df32320556cec71585fb2df','15fee76589fa386fa841a369bf84eb5c75ec131a','689bc409ce3f93662f1223f16271f8ca9883c647','47097173fe23e65b63647777b53b0bdde6ce0f18','fcaa6c59f13ef6a3d6cafeaffaad71b017c34c3c','dd0a2f0c0e6fdcf01c7a917ea662a7ef1e953f11','b29fb15f9b7a448bb70ca27a4b1aac48c1d4f51f','0d91bcb1f42c1a7214168ee61e875166bd75d547','d561d1634333a05fe3428e355f6ab3d67b69ed44','6a13a34b36f6ea738d10b2a2da4958045c243fb7','ee49c31a8c40676f366959341cd98aecdcf9c14f','c541aa24beb8107a3726bd8b9e655ca8f95d7b48','7ae06c19dd24dea99940ceaed8dffdd0e24cd5f9','6d2029f0e2404dcc7f836481cef6bf56f060b248','5c5a26c8bcb37a214c47f4b6d9843de20a8fb7e1','3ee633bf4e4eadc2b70c6eebfa14c600435604c9','ad5d10a0d7d8fc98040ff33f1db197735d6d3d52','2bde3ac14192be5f4e664c2b01b5aaa57c14e347','a87a03c8c3a06269e6ff8d11e142f6ebb05e9306','190325aed218711647eae5581a1f629c76da297c','e244d9f1edb6275b69c4a832620b9439d39bfb22','751f7c9538b9fd00f5c7dd0ed59df07f4d51fdac','762904de405fa26afdd39e024395a441bc6a0f8a','4df21df646897816e166b3dd829a8a3e21157f22','9c241f721c1f6677d736b37ecd86bb230df329df','96ebedcc684f27f984cc7be467c908bdab2470a9','419cfbd87ad35c1d43214b122630cfde1c3ccf1b','cf75ace0d7531b8daa271001dbf92b93b0b4490c','a058b4bb03a689ce8528ed412d62cdd5bb879571','d7c871c41c9db40312ffc5af996ede62ecdfc579','6c353ee8f48c1227eeab81279dc3eb3890c9c3bd','fea28aab54637701c5dfaef4f3fe64c72b272e1c','ecd79b7eb7af2bb4dadf710f70e0d78f62adc40e','43917824cc1d9b5a65601f46e13a0779c3dcff4e','5423bb28649f37e70a0559cba78c3b253a60c277','2c091a50dfd31e766a5a629c0b7c21973e33319d','920feb4f9d1032dcec2abc5c526e4996f642968b','31b9b446263cd5b7a844d43f2a235ed9b0c53efb','dbb5127246fee18718bcffc6cf0730674d12b98a','3872a4cfeba7651f0671de7e5f3922fd5053837b','2fbcb2db61b6416cdf46e0526e1929d146ab3da7','999da234e770bbf681a819423d04ea57415d9bbc','6fc6be53a87bbb2d2a51a5617009063002321d09','b0de72088fa3e543572329eda36fa4bd16e29fa3','2a6d8110b8148a9aa83db81dc38d544becea2fa9','6556aaaca3956eafbc1660bce50a2f3568f1bff6','8ba3d2c7712e9c0484a4cafc8b0ca6f35d8f11ed',];
+ var tests = {
+ "6d8b9d29f1890d59ef2453cff3f6d57b7e398c5c":[async_test('html5lib_tests16.html 6d8b9d29f1890d59ef2453cff3f6d57b7e398c5c'), "%3C%21doctype%20html%3E%3Cscript%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%3Cbody%3E"],"5d4ac4961f9d52a42f309886d16fbe9c55c198bb":[async_test('html5lib_tests16.html 5d4ac4961f9d52a42f309886d16fbe9c55c198bb'), "%3C%21doctype%20html%3E%3Cscript%3Ea", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22a%22%0A%7C%20%20%20%3Cbody%3E"],"132c6e3cd2659e15b69904c67981a04e81fabe78":[async_test('html5lib_tests16.html 132c6e3cd2659e15b69904c67981a04e81fabe78'), "%3C%21doctype%20html%3E%3Cscript%3E%3C", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%22%0A%7C%20%20%20%3Cbody%3E"],"bf0b3062e7cbe684380581919947333beef23a8c":[async_test('html5lib_tests16.html bf0b3062e7cbe684380581919947333beef23a8c'), "%3C%21doctype%20html%3E%3Cscript%3E%3C/", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C/%22%0A%7C%20%20%20%3Cbody%3E"],"cd76a82b9a4bde442e4f8819b37e6308e3eef8f5":[async_test('html5lib_tests16.html cd76a82b9a4bde442e4f8819b37e6308e3eef8f5'), "%3C%21doctype%20html%3E%3Cscript%3E%3C/S", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C/S%22%0A%7C%20%20%20%3Cbody%3E"],"747087d5bf2fe9a8a6c0ecf822211d93a4e0cc2a":[async_test('html5lib_tests16.html 747087d5bf2fe9a8a6c0ecf822211d93a4e0cc2a'), "%3C%21doctype%20html%3E%3Cscript%3E%3C/SC", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C/SC%22%0A%7C%20%20%20%3Cbody%3E"],"413482922b0185970bfdd6008e6a0e70ad1b554f":[async_test('html5lib_tests16.html 413482922b0185970bfdd6008e6a0e70ad1b554f'), "%3C%21doctype%20html%3E%3Cscript%3E%3C/SCR", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C/SCR%22%0A%7C%20%20%20%3Cbody%3E"],"0e3cc8b1f36a34fb3048bb4f01e0e7fec678ceef":[async_test('html5lib_tests16.html 0e3cc8b1f36a34fb3048bb4f01e0e7fec678ceef'), "%3C%21doctype%20html%3E%3Cscript%3E%3C/SCRI", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C/SCRI%22%0A%7C%20%20%20%3Cbody%3E"],"3d7a659a8880588e831c7198867b65ac2a974353":[async_test('html5lib_tests16.html 3d7a659a8880588e831c7198867b65ac2a974353'), "%3C%21doctype%20html%3E%3Cscript%3E%3C/SCRIP", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C/SCRIP%22%0A%7C%20%20%20%3Cbody%3E"],"46914793d44763c3cd37c3aef0c3689d826602d1":[async_test('html5lib_tests16.html 46914793d44763c3cd37c3aef0c3689d826602d1'), "%3C%21doctype%20html%3E%3Cscript%3E%3C/SCRIPT", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C/SCRIPT%22%0A%7C%20%20%20%3Cbody%3E"],"bc8ed1aea5ac5d7eac284386a5defe779eeab3d7":[async_test('html5lib_tests16.html bc8ed1aea5ac5d7eac284386a5defe779eeab3d7'), "%3C%21doctype%20html%3E%3Cscript%3E%3C/SCRIPT%20", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%3Cbody%3E"],"48e7e206aade47bdd9ad3a7cce2c9c86fb4227f6":[async_test('html5lib_tests16.html 48e7e206aade47bdd9ad3a7cce2c9c86fb4227f6'), "%3C%21doctype%20html%3E%3Cscript%3E%3C/s", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C/s%22%0A%7C%20%20%20%3Cbody%3E"],"cc10f706cec3e9356f8c42f77b970f669f74be03":[async_test('html5lib_tests16.html cc10f706cec3e9356f8c42f77b970f669f74be03'), "%3C%21doctype%20html%3E%3Cscript%3E%3C/sc", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C/sc%22%0A%7C%20%20%20%3Cbody%3E"],"9a6506b01fabf7ba73bb5c90f11b3898c2f119fa":[async_test('html5lib_tests16.html 9a6506b01fabf7ba73bb5c90f11b3898c2f119fa'), "%3C%21doctype%20html%3E%3Cscript%3E%3C/scr", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C/scr%22%0A%7C%20%20%20%3Cbody%3E"],"f840264cf775999580e621a83d34af302e139632":[async_test('html5lib_tests16.html f840264cf775999580e621a83d34af302e139632'), "%3C%21doctype%20html%3E%3Cscript%3E%3C/scri", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C/scri%22%0A%7C%20%20%20%3Cbody%3E"],"efe27c508629d48cf36861e680918f11f48aad15":[async_test('html5lib_tests16.html efe27c508629d48cf36861e680918f11f48aad15'), "%3C%21doctype%20html%3E%3Cscript%3E%3C/scrip", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C/scrip%22%0A%7C%20%20%20%3Cbody%3E"],"c51f18f140335e61f0158fadd282fb0f0c75bee6":[async_test('html5lib_tests16.html c51f18f140335e61f0158fadd282fb0f0c75bee6'), "%3C%21doctype%20html%3E%3Cscript%3E%3C/script", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C/script%22%0A%7C%20%20%20%3Cbody%3E"],"76d621ce4bd9e462bacaa40ebf43e1ccb569bd21":[async_test('html5lib_tests16.html 76d621ce4bd9e462bacaa40ebf43e1ccb569bd21'), "%3C%21doctype%20html%3E%3Cscript%3E%3C/script%20", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%3Cbody%3E"],"70e4352779315880955134dfe67c53acb76c4850":[async_test('html5lib_tests16.html 70e4352779315880955134dfe67c53acb76c4850'), "%3C%21doctype%20html%3E%3Cscript%3E%3C%21", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21%22%0A%7C%20%20%20%3Cbody%3E"],"b05be3f93446c26026591cbfee84b9603cd6f151":[async_test('html5lib_tests16.html b05be3f93446c26026591cbfee84b9603cd6f151'), "%3C%21doctype%20html%3E%3Cscript%3E%3C%21a", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21a%22%0A%7C%20%20%20%3Cbody%3E"],"3f08f2e2326b621f819b73336f502610dd94d54f":[async_test('html5lib_tests16.html 3f08f2e2326b621f819b73336f502610dd94d54f'), "%3C%21doctype%20html%3E%3Cscript%3E%3C%21-", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21-%22%0A%7C%20%20%20%3Cbody%3E"],"4932d705ce9c31d4141a630d305e16ae130982e7":[async_test('html5lib_tests16.html 4932d705ce9c31d4141a630d305e16ae130982e7'), "%3C%21doctype%20html%3E%3Cscript%3E%3C%21-a", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21-a%22%0A%7C%20%20%20%3Cbody%3E"],"accb817d72edbb0d9f72e2c44f47055fb1719d0a":[async_test('html5lib_tests16.html accb817d72edbb0d9f72e2c44f47055fb1719d0a'), "%3C%21doctype%20html%3E%3Cscript%3E%3C%21--", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%22%0A%7C%20%20%20%3Cbody%3E"],"b7b2e78af3f5846dc7f67246c92d95aacc2bd996":[async_test('html5lib_tests16.html b7b2e78af3f5846dc7f67246c92d95aacc2bd996'), "%3C%21doctype%20html%3E%3Cscript%3E%3C%21--a", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--a%22%0A%7C%20%20%20%3Cbody%3E"],"52e03d2903a9556823275541c58c173ac077a2a9":[async_test('html5lib_tests16.html 52e03d2903a9556823275541c58c173ac077a2a9'), "%3C%21doctype%20html%3E%3Cscript%3E%3C%21--%3C", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3C%22%0A%7C%20%20%20%3Cbody%3E"],"1daec6e34a3b4b4ea28f3e90595052090e67cbf7":[async_test('html5lib_tests16.html 1daec6e34a3b4b4ea28f3e90595052090e67cbf7'), "%3C%21doctype%20html%3E%3Cscript%3E%3C%21--%3Ca", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Ca%22%0A%7C%20%20%20%3Cbody%3E"],"539e26d76efe146f95bd7b6bfa88ae2d29afd35a":[async_test('html5lib_tests16.html 539e26d76efe146f95bd7b6bfa88ae2d29afd35a'), "%3C%21doctype%20html%3E%3Cscript%3E%3C%21--%3C/", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3C/%22%0A%7C%20%20%20%3Cbody%3E"],"ab43ce067468a33bb658e0d6cc542b9dbcd0c80f":[async_test('html5lib_tests16.html ab43ce067468a33bb658e0d6cc542b9dbcd0c80f'), "%3C%21doctype%20html%3E%3Cscript%3E%3C%21--%3C/script", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3C/script%22%0A%7C%20%20%20%3Cbody%3E"],"3f93565e7a692675cc519326cc4122b5ea44b533":[async_test('html5lib_tests16.html 3f93565e7a692675cc519326cc4122b5ea44b533'), "%3C%21doctype%20html%3E%3Cscript%3E%3C%21--%3C/script%20", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%22%0A%7C%20%20%20%3Cbody%3E"],"e579c03d00de7a95bad40602af783b4d7775ab78":[async_test('html5lib_tests16.html e579c03d00de7a95bad40602af783b4d7775ab78'), "%3C%21doctype%20html%3E%3Cscript%3E%3C%21--%3Cs", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cs%22%0A%7C%20%20%20%3Cbody%3E"],"1541ebd513bc357af538635050f1b3ec854648e5":[async_test('html5lib_tests16.html 1541ebd513bc357af538635050f1b3ec854648e5'), "%3C%21doctype%20html%3E%3Cscript%3E%3C%21--%3Cscript", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%22%0A%7C%20%20%20%3Cbody%3E"],"ae91f664e0c85f63d21dddaa03a9104d27a9d5ce":[async_test('html5lib_tests16.html ae91f664e0c85f63d21dddaa03a9104d27a9d5ce'), "%3C%21doctype%20html%3E%3Cscript%3E%3C%21--%3Cscript%20", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20%22%0A%7C%20%20%20%3Cbody%3E"],"17b1bf0912a302c2bed5358791fae3ea6d3efa7d":[async_test('html5lib_tests16.html 17b1bf0912a302c2bed5358791fae3ea6d3efa7d'), "%3C%21doctype%20html%3E%3Cscript%3E%3C%21--%3Cscript%20%3C", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20%3C%22%0A%7C%20%20%20%3Cbody%3E"],"beac9d7ec99b6317c8504e80118dd0f2d5fad573":[async_test('html5lib_tests16.html beac9d7ec99b6317c8504e80118dd0f2d5fad573'), "%3C%21doctype%20html%3E%3Cscript%3E%3C%21--%3Cscript%20%3Ca", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20%3Ca%22%0A%7C%20%20%20%3Cbody%3E"],"d5ead5851ba4d1cdac136d97a449e6b48b0c2cb4":[async_test('html5lib_tests16.html d5ead5851ba4d1cdac136d97a449e6b48b0c2cb4'), "%3C%21doctype%20html%3E%3Cscript%3E%3C%21--%3Cscript%20%3C/", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20%3C/%22%0A%7C%20%20%20%3Cbody%3E"],"17fe63597371d22c41ccbc4abcd8f468373559d7":[async_test('html5lib_tests16.html 17fe63597371d22c41ccbc4abcd8f468373559d7'), "%3C%21doctype%20html%3E%3Cscript%3E%3C%21--%3Cscript%20%3C/s", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20%3C/s%22%0A%7C%20%20%20%3Cbody%3E"],"26a585731ba7caa063ad5c87a09748a223e56639":[async_test('html5lib_tests16.html 26a585731ba7caa063ad5c87a09748a223e56639'), "%3C%21doctype%20html%3E%3Cscript%3E%3C%21--%3Cscript%20%3C/script", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20%3C/script%22%0A%7C%20%20%20%3Cbody%3E"],"91dc36fa03b62334c115db6d4b4a420ef1081753":[async_test('html5lib_tests16.html 91dc36fa03b62334c115db6d4b4a420ef1081753'), "%3C%21doctype%20html%3E%3Cscript%3E%3C%21--%3Cscript%20%3C/scripta", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20%3C/scripta%22%0A%7C%20%20%20%3Cbody%3E"],"b0ee0820468ee622b802020e20be120d3c534af2":[async_test('html5lib_tests16.html b0ee0820468ee622b802020e20be120d3c534af2'), "%3C%21doctype%20html%3E%3Cscript%3E%3C%21--%3Cscript%20%3C/script%20", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20%3C/script%20%22%0A%7C%20%20%20%3Cbody%3E"],"65907331b39d13cc2128eb57afb7185f0173a953":[async_test('html5lib_tests16.html 65907331b39d13cc2128eb57afb7185f0173a953'), "%3C%21doctype%20html%3E%3Cscript%3E%3C%21--%3Cscript%20%3C/script%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20%3C/script%3E%22%0A%7C%20%20%20%3Cbody%3E"],"c284310f4becf9d64252eaec25fe46de8c6e4f2c":[async_test('html5lib_tests16.html c284310f4becf9d64252eaec25fe46de8c6e4f2c'), "%3C%21doctype%20html%3E%3Cscript%3E%3C%21--%3Cscript%20%3C/script/", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20%3C/script/%22%0A%7C%20%20%20%3Cbody%3E"],"63bbe135b3dbb75f2262ce1cc5e9259634596a55":[async_test('html5lib_tests16.html 63bbe135b3dbb75f2262ce1cc5e9259634596a55'), "%3C%21doctype%20html%3E%3Cscript%3E%3C%21--%3Cscript%20%3C/script%20%3C", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20%3C/script%20%3C%22%0A%7C%20%20%20%3Cbody%3E"],"c83e5a48a9409482b62903960b0a04a932832668":[async_test('html5lib_tests16.html c83e5a48a9409482b62903960b0a04a932832668'), "%3C%21doctype%20html%3E%3Cscript%3E%3C%21--%3Cscript%20%3C/script%20%3Ca", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20%3C/script%20%3Ca%22%0A%7C%20%20%20%3Cbody%3E"],"193aa9aa570a39d74e340e8d6ddd015ee0a7477c":[async_test('html5lib_tests16.html 193aa9aa570a39d74e340e8d6ddd015ee0a7477c'), "%3C%21doctype%20html%3E%3Cscript%3E%3C%21--%3Cscript%20%3C/script%20%3C/", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20%3C/script%20%3C/%22%0A%7C%20%20%20%3Cbody%3E"],"0ce3d12fa6ac40027b789b09fd987194426e09e6":[async_test('html5lib_tests16.html 0ce3d12fa6ac40027b789b09fd987194426e09e6'), "%3C%21doctype%20html%3E%3Cscript%3E%3C%21--%3Cscript%20%3C/script%20%3C/script", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20%3C/script%20%3C/script%22%0A%7C%20%20%20%3Cbody%3E"],"fd613c2eb713e158fae7a54c45a3d952efa3d5a7":[async_test('html5lib_tests16.html fd613c2eb713e158fae7a54c45a3d952efa3d5a7'), "%3C%21doctype%20html%3E%3Cscript%3E%3C%21--%3Cscript%20%3C/script%20%3C/script%20", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20%3C/script%20%22%0A%7C%20%20%20%3Cbody%3E"],"14220896fd483fbeae58f2d69975acc99682be0c":[async_test('html5lib_tests16.html 14220896fd483fbeae58f2d69975acc99682be0c'), "%3C%21doctype%20html%3E%3Cscript%3E%3C%21--%3Cscript%20%3C/script%20%3C/script/", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20%3C/script%20%22%0A%7C%20%20%20%3Cbody%3E"],"11ca3aa17a2c0b1b6cfc0fb842105247272fbc8d":[async_test('html5lib_tests16.html 11ca3aa17a2c0b1b6cfc0fb842105247272fbc8d'), "%3C%21doctype%20html%3E%3Cscript%3E%3C%21--%3Cscript%20%3C/script%20%3C/script%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20%3C/script%20%22%0A%7C%20%20%20%3Cbody%3E"],"b524c040a6ab671b006713c8f117d494b11e92ce":[async_test('html5lib_tests16.html b524c040a6ab671b006713c8f117d494b11e92ce'), "%3C%21doctype%20html%3E%3Cscript%3E%3C%21--%3Cscript%20-", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20-%22%0A%7C%20%20%20%3Cbody%3E"],"9032e7dd5c12caaaf2baf259cee186aaaa67e0e7":[async_test('html5lib_tests16.html 9032e7dd5c12caaaf2baf259cee186aaaa67e0e7'), "%3C%21doctype%20html%3E%3Cscript%3E%3C%21--%3Cscript%20-a", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20-a%22%0A%7C%20%20%20%3Cbody%3E"],"aea756cf197079dc506242b729a1d16231644e31":[async_test('html5lib_tests16.html aea756cf197079dc506242b729a1d16231644e31'), "%3C%21doctype%20html%3E%3Cscript%3E%3C%21--%3Cscript%20-%3C", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20-%3C%22%0A%7C%20%20%20%3Cbody%3E"],"7446d6b66ccedb48db489df92102a0cf439004ce":[async_test('html5lib_tests16.html 7446d6b66ccedb48db489df92102a0cf439004ce'), "%3C%21doctype%20html%3E%3Cscript%3E%3C%21--%3Cscript%20--", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20--%22%0A%7C%20%20%20%3Cbody%3E"],"935849b22e851061994b7da0a7abb626cfe27cab":[async_test('html5lib_tests16.html 935849b22e851061994b7da0a7abb626cfe27cab'), "%3C%21doctype%20html%3E%3Cscript%3E%3C%21--%3Cscript%20--a", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20--a%22%0A%7C%20%20%20%3Cbody%3E"],"075cdcf1f8b05fe1a1306ae9702fb7442a76754c":[async_test('html5lib_tests16.html 075cdcf1f8b05fe1a1306ae9702fb7442a76754c'), "%3C%21doctype%20html%3E%3Cscript%3E%3C%21--%3Cscript%20--%3C", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20--%3C%22%0A%7C%20%20%20%3Cbody%3E"],"c7d08dec7a358d06f64235f1f6189c0c53e7e75e":[async_test('html5lib_tests16.html c7d08dec7a358d06f64235f1f6189c0c53e7e75e'), "%3C%21doctype%20html%3E%3Cscript%3E%3C%21--%3Cscript%20--%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20--%3E%22%0A%7C%20%20%20%3Cbody%3E"],"c0c7b3e8f7109cf2fef447c2ac28e1566a246a74":[async_test('html5lib_tests16.html c0c7b3e8f7109cf2fef447c2ac28e1566a246a74'), "%3C%21doctype%20html%3E%3Cscript%3E%3C%21--%3Cscript%20--%3E%3C", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20--%3E%3C%22%0A%7C%20%20%20%3Cbody%3E"],"d95e3c1ce7b2b79e43654cc23a4a1fc65c084d82":[async_test('html5lib_tests16.html d95e3c1ce7b2b79e43654cc23a4a1fc65c084d82'), "%3C%21doctype%20html%3E%3Cscript%3E%3C%21--%3Cscript%20--%3E%3C/", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20--%3E%3C/%22%0A%7C%20%20%20%3Cbody%3E"],"49e2f750500035dfc265752923b58a26d743bc60":[async_test('html5lib_tests16.html 49e2f750500035dfc265752923b58a26d743bc60'), "%3C%21doctype%20html%3E%3Cscript%3E%3C%21--%3Cscript%20--%3E%3C/script", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20--%3E%3C/script%22%0A%7C%20%20%20%3Cbody%3E"],"c9a6e8a5f0da04035a690465b85c49e1c7259390":[async_test('html5lib_tests16.html c9a6e8a5f0da04035a690465b85c49e1c7259390'), "%3C%21doctype%20html%3E%3Cscript%3E%3C%21--%3Cscript%20--%3E%3C/script%20", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20--%3E%22%0A%7C%20%20%20%3Cbody%3E"],"7e0c780436a6c11fcdc39dfa30c7e40542bb4745":[async_test('html5lib_tests16.html 7e0c780436a6c11fcdc39dfa30c7e40542bb4745'), "%3C%21doctype%20html%3E%3Cscript%3E%3C%21--%3Cscript%20--%3E%3C/script/", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20--%3E%22%0A%7C%20%20%20%3Cbody%3E"],"10b54008a6e2f12bbfcaa0d9e19c0f98d67dfb53":[async_test('html5lib_tests16.html 10b54008a6e2f12bbfcaa0d9e19c0f98d67dfb53'), "%3C%21doctype%20html%3E%3Cscript%3E%3C%21--%3Cscript%20--%3E%3C/script%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20--%3E%22%0A%7C%20%20%20%3Cbody%3E"],"6cdd162096c7fb581b808d491baff3c1234b02e1":[async_test('html5lib_tests16.html 6cdd162096c7fb581b808d491baff3c1234b02e1'), "%3C%21doctype%20html%3E%3Cscript%3E%3C%21--%3Cscript%3E%3C%5C/script%3E--%3E%3C/script%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%3E%3C%5C/script%3E--%3E%22%0A%7C%20%20%20%3Cbody%3E"],"243a2da6a25d3d7641fac624e712f4c96376d23c":[async_test('html5lib_tests16.html 243a2da6a25d3d7641fac624e712f4c96376d23c'), "%3C%21doctype%20html%3E%3Cscript%3E%3C%21--%3Cscript%3E%3C/scr%27%2B%27ipt%3E--%3E%3C/script%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%3E%3C/scr%27%2B%27ipt%3E--%3E%22%0A%7C%20%20%20%3Cbody%3E"],"86ff3afe4315b87db9a5d1d566b029c775e62b94":[async_test('html5lib_tests16.html 86ff3afe4315b87db9a5d1d566b029c775e62b94'), "%3C%21doctype%20html%3E%3Cscript%3E%3C%21--%3Cscript%3E%3C/script%3E%3Cscript%3E%3C/script%3E%3C/script%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%3E%3C/script%3E%3Cscript%3E%3C/script%3E%22%0A%7C%20%20%20%3Cbody%3E"],"e20f08402b6afc6d237e8261e512f89ce5299881":[async_test('html5lib_tests16.html e20f08402b6afc6d237e8261e512f89ce5299881'), "%3C%21doctype%20html%3E%3Cscript%3E%3C%21--%3Cscript%3E%3C/script%3E%3Cscript%3E%3C/script%3E--%3E%3C%21--%3C/script%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%3E%3C/script%3E%3Cscript%3E%3C/script%3E--%3E%3C%21--%22%0A%7C%20%20%20%3Cbody%3E"],"c48c5eae7882c00df9026ba16f890266291635f2":[async_test('html5lib_tests16.html c48c5eae7882c00df9026ba16f890266291635f2'), "%3C%21doctype%20html%3E%3Cscript%3E%3C%21--%3Cscript%3E%3C/script%3E%3Cscript%3E%3C/script%3E--%20%3E%3C/script%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%3E%3C/script%3E%3Cscript%3E%3C/script%3E--%20%3E%22%0A%7C%20%20%20%3Cbody%3E"],"d055df57faa87a91d463956c4816bb9c67384c73":[async_test('html5lib_tests16.html d055df57faa87a91d463956c4816bb9c67384c73'), "%3C%21doctype%20html%3E%3Cscript%3E%3C%21--%3Cscript%3E%3C/script%3E%3Cscript%3E%3C/script%3E-%20-%3E%3C/script%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%3E%3C/script%3E%3Cscript%3E%3C/script%3E-%20-%3E%22%0A%7C%20%20%20%3Cbody%3E"],"33cc450505dd8b55c690589d441a793bb8985f11":[async_test('html5lib_tests16.html 33cc450505dd8b55c690589d441a793bb8985f11'), "%3C%21doctype%20html%3E%3Cscript%3E%3C%21--%3Cscript%3E%3C/script%3E%3Cscript%3E%3C/script%3E-%20-%20%3E%3C/script%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%3E%3C/script%3E%3Cscript%3E%3C/script%3E-%20-%20%3E%22%0A%7C%20%20%20%3Cbody%3E"],"40077f2a5b88cf53f3a53485194fc29e39feb39b":[async_test('html5lib_tests16.html 40077f2a5b88cf53f3a53485194fc29e39feb39b'), "%3C%21doctype%20html%3E%3Cscript%3E%3C%21--%3Cscript%3E%3C/script%3E%3Cscript%3E%3C/script%3E-%3E%3C/script%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%3E%3C/script%3E%3Cscript%3E%3C/script%3E-%3E%22%0A%7C%20%20%20%3Cbody%3E"],"10bd03da7b29a7ebe5e18e2163849c2521ae4555":[async_test('html5lib_tests16.html 10bd03da7b29a7ebe5e18e2163849c2521ae4555'), "%3C%21doctype%20html%3E%3Cscript%3E%3C%21--%3Cscript%3E--%21%3E%3C/script%3EX", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%3E--%21%3E%3C/script%3EX%22%0A%7C%20%20%20%3Cbody%3E"],"39e7696382843bda945f5717030388257f54dad0":[async_test('html5lib_tests16.html 39e7696382843bda945f5717030388257f54dad0'), "%3C%21doctype%20html%3E%3Cscript%3E%3C%21--%3Cscr%27%2B%27ipt%3E%3C/script%3E--%3E%3C/script%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscr%27%2B%27ipt%3E%22%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22--%3E%22"],"6d0edc9ca958384e4c608386588400b63f8cbc1a":[async_test('html5lib_tests16.html 6d0edc9ca958384e4c608386588400b63f8cbc1a'), "%3C%21doctype%20html%3E%3Cscript%3E%3C%21--%3Cscript%3E%3C/scr%27%2B%27ipt%3E%3C/script%3EX", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%3E%3C/scr%27%2B%27ipt%3E%3C/script%3EX%22%0A%7C%20%20%20%3Cbody%3E"],"0ec48786ebc1bf532930e5f442c83fc05d5ab873":[async_test('html5lib_tests16.html 0ec48786ebc1bf532930e5f442c83fc05d5ab873'), "%3C%21doctype%20html%3E%3Cstyle%3E%3C%21--%3Cstyle%3E%3C/style%3E--%3E%3C/style%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cstyle%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cstyle%3E%22%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22--%3E%22"],"763803287fa8300b3fd5a0285ce1ab6520640245":[async_test('html5lib_tests16.html 763803287fa8300b3fd5a0285ce1ab6520640245'), "%3C%21doctype%20html%3E%3Cstyle%3E%3C%21--%3C/style%3EX", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cstyle%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%22%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22X%22"],"f9b350e5c8304caf954b333f54060cd1ab377b47":[async_test('html5lib_tests16.html f9b350e5c8304caf954b333f54060cd1ab377b47'), "%3C%21doctype%20html%3E%3Cstyle%3E%3C%21--...%3C/style%3E...--%3E%3C/style%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cstyle%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--...%22%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22...--%3E%22"],"c82aa963e4443053afe065da586dc6f5df062f9f":[async_test('html5lib_tests16.html c82aa963e4443053afe065da586dc6f5df062f9f'), "%3C%21doctype%20html%3E%3Cstyle%3E%3C%21--%3Cbr%3E%3Chtml%20xmlns%3Av%3D%22urn%3Aschemas-microsoft-com%3Avml%22%3E%3C%21--%5Bif%20%21mso%5D%3E%3Cstyle%3E%3C/style%3EX", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cstyle%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cbr%3E%3Chtml%20xmlns%3Av%3D%22urn%3Aschemas-microsoft-com%3Avml%22%3E%3C%21--%5Bif%20%21mso%5D%3E%3Cstyle%3E%22%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22X%22"],"a97946be8e03c386e23023e6b6184d11517fc4f5":[async_test('html5lib_tests16.html a97946be8e03c386e23023e6b6184d11517fc4f5'), "%3C%21doctype%20html%3E%3Cstyle%3E%3C%21--...%3Cstyle%3E%3C%21--...--%21%3E%3C/style%3E--%3E%3C/style%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cstyle%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--...%3Cstyle%3E%3C%21--...--%21%3E%22%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22--%3E%22"],"5b1e9bf7ee6e6222b78d38d99ffd3d0281b930a3":[async_test('html5lib_tests16.html 5b1e9bf7ee6e6222b78d38d99ffd3d0281b930a3'), "%3C%21doctype%20html%3E%3Cstyle%3E%3C%21--...%3C/style%3E%3C%21--%20--%3E%3Cstyle%3E%40import%20...%3C/style%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cstyle%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--...%22%0A%7C%20%20%20%20%20%3C%21--%20%20%20--%3E%0A%7C%20%20%20%20%20%3Cstyle%3E%0A%7C%20%20%20%20%20%20%20%22%40import%20...%22%0A%7C%20%20%20%3Cbody%3E"],"252c0a3870902b1fdf15224188ffd5abf56ced5f":[async_test('html5lib_tests16.html 252c0a3870902b1fdf15224188ffd5abf56ced5f'), "%3C%21doctype%20html%3E%3Cstyle%3E...%3Cstyle%3E%3C%21--...%3C/style%3E%3C%21--%20--%3E%3C/style%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cstyle%3E%0A%7C%20%20%20%20%20%20%20%22...%3Cstyle%3E%3C%21--...%22%0A%7C%20%20%20%20%20%3C%21--%20%20%20--%3E%0A%7C%20%20%20%3Cbody%3E"],"10f2c0e9041fe19c9aea3c9f6a61842372242691":[async_test('html5lib_tests16.html 10f2c0e9041fe19c9aea3c9f6a61842372242691'), "%3C%21doctype%20html%3E%3Cstyle%3E...%3C%21--%5Bif%20IE%5D%3E%3Cstyle%3E...%3C/style%3EX", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cstyle%3E%0A%7C%20%20%20%20%20%20%20%22...%3C%21--%5Bif%20IE%5D%3E%3Cstyle%3E...%22%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22X%22"],"a68fa9f51d285e08b95b34a1ad7ae303d1180cda":[async_test('html5lib_tests16.html a68fa9f51d285e08b95b34a1ad7ae303d1180cda'), "%3C%21doctype%20html%3E%3Ctitle%3E%3C%21--%3Ctitle%3E%3C/title%3E--%3E%3C/title%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Ctitle%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Ctitle%3E%22%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22--%3E%22"],"1553cebdf01dc953ed7983d39a18752a4fbb24d7":[async_test('html5lib_tests16.html 1553cebdf01dc953ed7983d39a18752a4fbb24d7'), "%3C%21doctype%20html%3E%3Ctitle%3E%26lt%3B/title%3E%3C/title%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Ctitle%3E%0A%7C%20%20%20%20%20%20%20%22%3C/title%3E%22%0A%7C%20%20%20%3Cbody%3E"],"802e7c9b307082d9f15835722eb9ef2dee60ea5f":[async_test('html5lib_tests16.html 802e7c9b307082d9f15835722eb9ef2dee60ea5f'), "%3C%21doctype%20html%3E%3Ctitle%3Efoo/title%3E%3Clink%3E%3C/head%3E%3Cbody%3EX", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Ctitle%3E%0A%7C%20%20%20%20%20%20%20%22foo/title%3E%3Clink%3E%3C/head%3E%3Cbody%3EX%22%0A%7C%20%20%20%3Cbody%3E"],"c7f41e79f00db5b41872c0ef1443094e7ad5bc22":[async_test('html5lib_tests16.html c7f41e79f00db5b41872c0ef1443094e7ad5bc22'), "%3C%21doctype%20html%3E%3Cnoscript%3E%3C%21--%3Cnoscript%3E%3C/noscript%3E--%3E%3C/noscript%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cnoscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cnoscript%3E%22%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22--%3E%22"],"ae3967a139a3ecf61ecbc59c8c769a2731626fac":[async_test('html5lib_tests16.html ae3967a139a3ecf61ecbc59c8c769a2731626fac'), "%3C%21doctype%20html%3E%3Cnoscript%3E%3C%21--%3C/noscript%3EX%3Cnoscript%3E--%3E%3C/noscript%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cnoscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%22%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22X%22%0A%7C%20%20%20%20%20%3Cnoscript%3E%0A%7C%20%20%20%20%20%20%20%22--%3E%22"],"3586a5a4a1d1d69b139d139b0823af4753bc3e8d":[async_test('html5lib_tests16.html 3586a5a4a1d1d69b139d139b0823af4753bc3e8d'), "%3C%21doctype%20html%3E%3Cnoscript%3E%3Ciframe%3E%3C/noscript%3EX", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cnoscript%3E%0A%7C%20%20%20%20%20%20%20%22%3Ciframe%3E%22%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22X%22"],"0e99e2603bc91553c252713108e30495d71c3f37":[async_test('html5lib_tests16.html 0e99e2603bc91553c252713108e30495d71c3f37'), "%3C%21doctype%20html%3E%3Cnoframes%3E%3C%21--%3Cnoframes%3E%3C/noframes%3E--%3E%3C/noframes%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cnoframes%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cnoframes%3E%22%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22--%3E%22"],"f9858d096fa1e68cce0742d125c551878d2d7020":[async_test('html5lib_tests16.html f9858d096fa1e68cce0742d125c551878d2d7020'), "%3C%21doctype%20html%3E%3Cnoframes%3E%3Cbody%3E%3Cscript%3E%3C%21--...%3C/script%3E%3C/body%3E%3C/noframes%3E%3C/html%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cnoframes%3E%0A%7C%20%20%20%20%20%20%20%22%3Cbody%3E%3Cscript%3E%3C%21--...%3C/script%3E%3C/body%3E%22%0A%7C%20%20%20%3Cbody%3E"],"225e87bce5a4518c3e5cd248ef93ebc39dba14e0":[async_test('html5lib_tests16.html 225e87bce5a4518c3e5cd248ef93ebc39dba14e0'), "%3C%21doctype%20html%3E%3Ctextarea%3E%3C%21--%3Ctextarea%3E%3C/textarea%3E--%3E%3C/textarea%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctextarea%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Ctextarea%3E%22%0A%7C%20%20%20%20%20%22--%3E%22"],"bb08b00b361470ce18b435c97aff4449dc98cc51":[async_test('html5lib_tests16.html bb08b00b361470ce18b435c97aff4449dc98cc51'), "%3C%21doctype%20html%3E%3Ctextarea%3E%26lt%3B/textarea%3E%3C/textarea%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctextarea%3E%0A%7C%20%20%20%20%20%20%20%22%3C/textarea%3E%22"],"cd74b727c1c8233f98e325293a2307e882e10f41":[async_test('html5lib_tests16.html cd74b727c1c8233f98e325293a2307e882e10f41'), "%3C%21doctype%20html%3E%3Ctextarea%3E%26lt%3B%3C/textarea%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctextarea%3E%0A%7C%20%20%20%20%20%20%20%22%3C%22"],"367bf426c092467300f78e5d7526b5a95b490871":[async_test('html5lib_tests16.html 367bf426c092467300f78e5d7526b5a95b490871'), "%3C%21doctype%20html%3E%3Ctextarea%3Ea%26lt%3Bb%3C/textarea%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctextarea%3E%0A%7C%20%20%20%20%20%20%20%22a%3Cb%22"],"96630ff73c222ae5aa31c5d8d32391c00e01d4ae":[async_test('html5lib_tests16.html 96630ff73c222ae5aa31c5d8d32391c00e01d4ae'), "%3C%21doctype%20html%3E%3Ciframe%3E%3C%21--%3Ciframe%3E%3C/iframe%3E--%3E%3C/iframe%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ciframe%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Ciframe%3E%22%0A%7C%20%20%20%20%20%22--%3E%22"],"efd159c8bb96c72857a1b23247240fef25c4bc16":[async_test('html5lib_tests16.html efd159c8bb96c72857a1b23247240fef25c4bc16'), "%3C%21doctype%20html%3E%3Ciframe%3E...%3C%21--X-%3E...%3C%21--/X-%3E...%3C/iframe%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ciframe%3E%0A%7C%20%20%20%20%20%20%20%22...%3C%21--X-%3E...%3C%21--/X-%3E...%22"],"302c14341a82cd1ed9c77beb7ad60ce574f764ff":[async_test('html5lib_tests16.html 302c14341a82cd1ed9c77beb7ad60ce574f764ff'), "%3C%21doctype%20html%3E%3Cxmp%3E%3C%21--%3Cxmp%3E%3C/xmp%3E--%3E%3C/xmp%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cxmp%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cxmp%3E%22%0A%7C%20%20%20%20%20%22--%3E%22"],"40369d98631eb17e8ae0cad61d9b7d6dbcddf424":[async_test('html5lib_tests16.html 40369d98631eb17e8ae0cad61d9b7d6dbcddf424'), "%3C%21doctype%20html%3E%3Cnoembed%3E%3C%21--%3Cnoembed%3E%3C/noembed%3E--%3E%3C/noembed%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cnoembed%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cnoembed%3E%22%0A%7C%20%20%20%20%20%22--%3E%22"],"4285eba81853a6d9ea3121ffa93f1b68bb33c157":[async_test('html5lib_tests16.html 4285eba81853a6d9ea3121ffa93f1b68bb33c157'), "%3Cscript%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%3Cbody%3E"],"824bd03d81ed9d5c1d3effe1ea45db39c27d520e":[async_test('html5lib_tests16.html 824bd03d81ed9d5c1d3effe1ea45db39c27d520e'), "%3Cscript%3Ea", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22a%22%0A%7C%20%20%20%3Cbody%3E"],"5593651c759624a4b7d91f3e07fc3e02c9bc6642":[async_test('html5lib_tests16.html 5593651c759624a4b7d91f3e07fc3e02c9bc6642'), "%3Cscript%3E%3C", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%22%0A%7C%20%20%20%3Cbody%3E"],"8862cf5a3972eec607fabbac4bd1dcf5eb50c3f2":[async_test('html5lib_tests16.html 8862cf5a3972eec607fabbac4bd1dcf5eb50c3f2'), "%3Cscript%3E%3C/", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C/%22%0A%7C%20%20%20%3Cbody%3E"],"bdaf31925507cd81bace2411601cb50be9ed3339":[async_test('html5lib_tests16.html bdaf31925507cd81bace2411601cb50be9ed3339'), "%3Cscript%3E%3C/S", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C/S%22%0A%7C%20%20%20%3Cbody%3E"],"7df307e7cede64fda865c44c0897fc6191ce788c":[async_test('html5lib_tests16.html 7df307e7cede64fda865c44c0897fc6191ce788c'), "%3Cscript%3E%3C/SC", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C/SC%22%0A%7C%20%20%20%3Cbody%3E"],"8f275021b4d57f5235abc4efa2f53d0c633a22d6":[async_test('html5lib_tests16.html 8f275021b4d57f5235abc4efa2f53d0c633a22d6'), "%3Cscript%3E%3C/SCR", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C/SCR%22%0A%7C%20%20%20%3Cbody%3E"],"b3b17f7b0a43afc62fcc24602488f7c1535eafb1":[async_test('html5lib_tests16.html b3b17f7b0a43afc62fcc24602488f7c1535eafb1'), "%3Cscript%3E%3C/SCRI", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C/SCRI%22%0A%7C%20%20%20%3Cbody%3E"],"4383e943d6be1525114a923c5c5c7875d3506f43":[async_test('html5lib_tests16.html 4383e943d6be1525114a923c5c5c7875d3506f43'), "%3Cscript%3E%3C/SCRIP", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C/SCRIP%22%0A%7C%20%20%20%3Cbody%3E"],"c47db9cd301d75cc4ff1f4f66a70efaf04d88d34":[async_test('html5lib_tests16.html c47db9cd301d75cc4ff1f4f66a70efaf04d88d34'), "%3Cscript%3E%3C/SCRIPT", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C/SCRIPT%22%0A%7C%20%20%20%3Cbody%3E"],"c02e6a5ec0971e7e860b61f3638baecfe8d12edc":[async_test('html5lib_tests16.html c02e6a5ec0971e7e860b61f3638baecfe8d12edc'), "%3Cscript%3E%3C/SCRIPT%20", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%3Cbody%3E"],"b3e566664033b9b6c550d44627807a9c17ac0fec":[async_test('html5lib_tests16.html b3e566664033b9b6c550d44627807a9c17ac0fec'), "%3Cscript%3E%3C/s", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C/s%22%0A%7C%20%20%20%3Cbody%3E"],"e1b7c9e452fbd47b9f62901e2802d4880c9798d5":[async_test('html5lib_tests16.html e1b7c9e452fbd47b9f62901e2802d4880c9798d5'), "%3Cscript%3E%3C/sc", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C/sc%22%0A%7C%20%20%20%3Cbody%3E"],"20b70b5e4c22aae23ed2f06f957d611b60a16e69":[async_test('html5lib_tests16.html 20b70b5e4c22aae23ed2f06f957d611b60a16e69'), "%3Cscript%3E%3C/scr", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C/scr%22%0A%7C%20%20%20%3Cbody%3E"],"80275b0c1f6bd16a37660822a9accc973b9ad6f6":[async_test('html5lib_tests16.html 80275b0c1f6bd16a37660822a9accc973b9ad6f6'), "%3Cscript%3E%3C/scri", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C/scri%22%0A%7C%20%20%20%3Cbody%3E"],"0707f977884170b8e752fb7956e658e60b96a39c":[async_test('html5lib_tests16.html 0707f977884170b8e752fb7956e658e60b96a39c'), "%3Cscript%3E%3C/scrip", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C/scrip%22%0A%7C%20%20%20%3Cbody%3E"],"3634374d8c7b8c049cfeb6cc9cab3284103d7745":[async_test('html5lib_tests16.html 3634374d8c7b8c049cfeb6cc9cab3284103d7745'), "%3Cscript%3E%3C/script", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C/script%22%0A%7C%20%20%20%3Cbody%3E"],"1cef2f6f416ac760843e475fdc3aca248fde2a64":[async_test('html5lib_tests16.html 1cef2f6f416ac760843e475fdc3aca248fde2a64'), "%3Cscript%3E%3C/script%20", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%3Cbody%3E"],"bcc75b33353806f86f5ecb7137309fe33fbc39cf":[async_test('html5lib_tests16.html bcc75b33353806f86f5ecb7137309fe33fbc39cf'), "%3Cscript%3E%3C%21", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21%22%0A%7C%20%20%20%3Cbody%3E"],"2b2b5615880e8fdd80ec772540344d3bf9f6cf98":[async_test('html5lib_tests16.html 2b2b5615880e8fdd80ec772540344d3bf9f6cf98'), "%3Cscript%3E%3C%21a", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21a%22%0A%7C%20%20%20%3Cbody%3E"],"87f5714929355b5a84c5bd86ade881e98135bbb8":[async_test('html5lib_tests16.html 87f5714929355b5a84c5bd86ade881e98135bbb8'), "%3Cscript%3E%3C%21-", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21-%22%0A%7C%20%20%20%3Cbody%3E"],"bc926c61b947962e23f1424d178e8b6caec63984":[async_test('html5lib_tests16.html bc926c61b947962e23f1424d178e8b6caec63984'), "%3Cscript%3E%3C%21-a", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21-a%22%0A%7C%20%20%20%3Cbody%3E"],"0f8650ed2fd554c65428eed896e5a6d0276ffe43":[async_test('html5lib_tests16.html 0f8650ed2fd554c65428eed896e5a6d0276ffe43'), "%3Cscript%3E%3C%21--", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%22%0A%7C%20%20%20%3Cbody%3E"],"e6c000aaa91a5cf04f15a4b6775e17d1bd9143b7":[async_test('html5lib_tests16.html e6c000aaa91a5cf04f15a4b6775e17d1bd9143b7'), "%3Cscript%3E%3C%21--a", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--a%22%0A%7C%20%20%20%3Cbody%3E"],"6783594161f7848e42e7c89a32da546163892d75":[async_test('html5lib_tests16.html 6783594161f7848e42e7c89a32da546163892d75'), "%3Cscript%3E%3C%21--%3C", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3C%22%0A%7C%20%20%20%3Cbody%3E"],"9c23cc23237032d8decf39d3d886a300c9304707":[async_test('html5lib_tests16.html 9c23cc23237032d8decf39d3d886a300c9304707'), "%3Cscript%3E%3C%21--%3Ca", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Ca%22%0A%7C%20%20%20%3Cbody%3E"],"985c2415bc39a322004bbba6817df37dcdf3f10b":[async_test('html5lib_tests16.html 985c2415bc39a322004bbba6817df37dcdf3f10b'), "%3Cscript%3E%3C%21--%3C/", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3C/%22%0A%7C%20%20%20%3Cbody%3E"],"649e75657bd308f81f93189a02efa6b9a7702902":[async_test('html5lib_tests16.html 649e75657bd308f81f93189a02efa6b9a7702902'), "%3Cscript%3E%3C%21--%3C/script", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3C/script%22%0A%7C%20%20%20%3Cbody%3E"],"d42bb3557b0fbbe59cf5f606445ba973d4a3d720":[async_test('html5lib_tests16.html d42bb3557b0fbbe59cf5f606445ba973d4a3d720'), "%3Cscript%3E%3C%21--%3C/script%20", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%22%0A%7C%20%20%20%3Cbody%3E"],"d0178734ef1a063624bfd6a737dba933a54bf63d":[async_test('html5lib_tests16.html d0178734ef1a063624bfd6a737dba933a54bf63d'), "%3Cscript%3E%3C%21--%3Cs", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cs%22%0A%7C%20%20%20%3Cbody%3E"],"f6ac88b3fe1743a446da7e0ad895b8f46ea31b23":[async_test('html5lib_tests16.html f6ac88b3fe1743a446da7e0ad895b8f46ea31b23'), "%3Cscript%3E%3C%21--%3Cscript", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%22%0A%7C%20%20%20%3Cbody%3E"],"fb513439a4a4683ec8fc60dc5f2d5588bd656910":[async_test('html5lib_tests16.html fb513439a4a4683ec8fc60dc5f2d5588bd656910'), "%3Cscript%3E%3C%21--%3Cscript%20", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20%22%0A%7C%20%20%20%3Cbody%3E"],"4ed828c62d9dcc18ecf8608c9c38708b0b89b83d":[async_test('html5lib_tests16.html 4ed828c62d9dcc18ecf8608c9c38708b0b89b83d'), "%3Cscript%3E%3C%21--%3Cscript%20%3C", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20%3C%22%0A%7C%20%20%20%3Cbody%3E"],"51bbdaeed5d24b370a3456040561f8cad226b1a7":[async_test('html5lib_tests16.html 51bbdaeed5d24b370a3456040561f8cad226b1a7'), "%3Cscript%3E%3C%21--%3Cscript%20%3Ca", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20%3Ca%22%0A%7C%20%20%20%3Cbody%3E"],"45b8f97a3a29d8b1d5e7b7f2586189ead21873b7":[async_test('html5lib_tests16.html 45b8f97a3a29d8b1d5e7b7f2586189ead21873b7'), "%3Cscript%3E%3C%21--%3Cscript%20%3C/", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20%3C/%22%0A%7C%20%20%20%3Cbody%3E"],"1ca26210654f4c95e3f5a337922cd5e8b0694789":[async_test('html5lib_tests16.html 1ca26210654f4c95e3f5a337922cd5e8b0694789'), "%3Cscript%3E%3C%21--%3Cscript%20%3C/s", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20%3C/s%22%0A%7C%20%20%20%3Cbody%3E"],"a2cd3e4d9dfccfe71bbf5780b537396b5f76c0d6":[async_test('html5lib_tests16.html a2cd3e4d9dfccfe71bbf5780b537396b5f76c0d6'), "%3Cscript%3E%3C%21--%3Cscript%20%3C/script", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20%3C/script%22%0A%7C%20%20%20%3Cbody%3E"],"bb1450fbedebc1605f79eaa4dc501f47d1d7feb6":[async_test('html5lib_tests16.html bb1450fbedebc1605f79eaa4dc501f47d1d7feb6'), "%3Cscript%3E%3C%21--%3Cscript%20%3C/scripta", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20%3C/scripta%22%0A%7C%20%20%20%3Cbody%3E"],"a9d29f0909132226fd57de4a55282f95682778fd":[async_test('html5lib_tests16.html a9d29f0909132226fd57de4a55282f95682778fd'), "%3Cscript%3E%3C%21--%3Cscript%20%3C/script%20", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20%3C/script%20%22%0A%7C%20%20%20%3Cbody%3E"],"1fdf0dda892b230252ce864b5c7073ee09aa9165":[async_test('html5lib_tests16.html 1fdf0dda892b230252ce864b5c7073ee09aa9165'), "%3Cscript%3E%3C%21--%3Cscript%20%3C/script%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20%3C/script%3E%22%0A%7C%20%20%20%3Cbody%3E"],"af1c863ec4e65c29006a0c98ef0872950618a05e":[async_test('html5lib_tests16.html af1c863ec4e65c29006a0c98ef0872950618a05e'), "%3Cscript%3E%3C%21--%3Cscript%20%3C/script/", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20%3C/script/%22%0A%7C%20%20%20%3Cbody%3E"],"18763f4dd0f9681f043e0124ac26b76795f8afad":[async_test('html5lib_tests16.html 18763f4dd0f9681f043e0124ac26b76795f8afad'), "%3Cscript%3E%3C%21--%3Cscript%20%3C/script%20%3C", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20%3C/script%20%3C%22%0A%7C%20%20%20%3Cbody%3E"],"499e8bdd759619c5c2248e854e7cd9148ff5fe6d":[async_test('html5lib_tests16.html 499e8bdd759619c5c2248e854e7cd9148ff5fe6d'), "%3Cscript%3E%3C%21--%3Cscript%20%3C/script%20%3Ca", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20%3C/script%20%3Ca%22%0A%7C%20%20%20%3Cbody%3E"],"b442057918b0f6954cf88be6da17b0c5ace03382":[async_test('html5lib_tests16.html b442057918b0f6954cf88be6da17b0c5ace03382'), "%3Cscript%3E%3C%21--%3Cscript%20%3C/script%20%3C/", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20%3C/script%20%3C/%22%0A%7C%20%20%20%3Cbody%3E"],"8a4c1d1a49ab635498f581f8341f0f037178d01d":[async_test('html5lib_tests16.html 8a4c1d1a49ab635498f581f8341f0f037178d01d'), "%3Cscript%3E%3C%21--%3Cscript%20%3C/script%20%3C/script", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20%3C/script%20%3C/script%22%0A%7C%20%20%20%3Cbody%3E"],"c4d806ce1a7cb0abe0cb26e6950839b47134dc68":[async_test('html5lib_tests16.html c4d806ce1a7cb0abe0cb26e6950839b47134dc68'), "%3Cscript%3E%3C%21--%3Cscript%20%3C/script%20%3C/script%20", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20%3C/script%20%22%0A%7C%20%20%20%3Cbody%3E"],"189378cd03b029adb6e679b6a349124155c697b7":[async_test('html5lib_tests16.html 189378cd03b029adb6e679b6a349124155c697b7'), "%3Cscript%3E%3C%21--%3Cscript%20%3C/script%20%3C/script/", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20%3C/script%20%22%0A%7C%20%20%20%3Cbody%3E"],"6c9b32168850736c788f14208a39e70272ccc54e":[async_test('html5lib_tests16.html 6c9b32168850736c788f14208a39e70272ccc54e'), "%3Cscript%3E%3C%21--%3Cscript%20%3C/script%20%3C/script%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20%3C/script%20%22%0A%7C%20%20%20%3Cbody%3E"],"2e9cd7a39540b3bd1df32320556cec71585fb2df":[async_test('html5lib_tests16.html 2e9cd7a39540b3bd1df32320556cec71585fb2df'), "%3Cscript%3E%3C%21--%3Cscript%20-", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20-%22%0A%7C%20%20%20%3Cbody%3E"],"15fee76589fa386fa841a369bf84eb5c75ec131a":[async_test('html5lib_tests16.html 15fee76589fa386fa841a369bf84eb5c75ec131a'), "%3Cscript%3E%3C%21--%3Cscript%20-a", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20-a%22%0A%7C%20%20%20%3Cbody%3E"],"689bc409ce3f93662f1223f16271f8ca9883c647":[async_test('html5lib_tests16.html 689bc409ce3f93662f1223f16271f8ca9883c647'), "%3Cscript%3E%3C%21--%3Cscript%20--", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20--%22%0A%7C%20%20%20%3Cbody%3E"],"47097173fe23e65b63647777b53b0bdde6ce0f18":[async_test('html5lib_tests16.html 47097173fe23e65b63647777b53b0bdde6ce0f18'), "%3Cscript%3E%3C%21--%3Cscript%20--a", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20--a%22%0A%7C%20%20%20%3Cbody%3E"],"fcaa6c59f13ef6a3d6cafeaffaad71b017c34c3c":[async_test('html5lib_tests16.html fcaa6c59f13ef6a3d6cafeaffaad71b017c34c3c'), "%3Cscript%3E%3C%21--%3Cscript%20--%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20--%3E%22%0A%7C%20%20%20%3Cbody%3E"],"dd0a2f0c0e6fdcf01c7a917ea662a7ef1e953f11":[async_test('html5lib_tests16.html dd0a2f0c0e6fdcf01c7a917ea662a7ef1e953f11'), "%3Cscript%3E%3C%21--%3Cscript%20--%3E%3C", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20--%3E%3C%22%0A%7C%20%20%20%3Cbody%3E"],"b29fb15f9b7a448bb70ca27a4b1aac48c1d4f51f":[async_test('html5lib_tests16.html b29fb15f9b7a448bb70ca27a4b1aac48c1d4f51f'), "%3Cscript%3E%3C%21--%3Cscript%20--%3E%3C/", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20--%3E%3C/%22%0A%7C%20%20%20%3Cbody%3E"],"0d91bcb1f42c1a7214168ee61e875166bd75d547":[async_test('html5lib_tests16.html 0d91bcb1f42c1a7214168ee61e875166bd75d547'), "%3Cscript%3E%3C%21--%3Cscript%20--%3E%3C/script", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20--%3E%3C/script%22%0A%7C%20%20%20%3Cbody%3E"],"d561d1634333a05fe3428e355f6ab3d67b69ed44":[async_test('html5lib_tests16.html d561d1634333a05fe3428e355f6ab3d67b69ed44'), "%3Cscript%3E%3C%21--%3Cscript%20--%3E%3C/script%20", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20--%3E%22%0A%7C%20%20%20%3Cbody%3E"],"6a13a34b36f6ea738d10b2a2da4958045c243fb7":[async_test('html5lib_tests16.html 6a13a34b36f6ea738d10b2a2da4958045c243fb7'), "%3Cscript%3E%3C%21--%3Cscript%20--%3E%3C/script/", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20--%3E%22%0A%7C%20%20%20%3Cbody%3E"],"ee49c31a8c40676f366959341cd98aecdcf9c14f":[async_test('html5lib_tests16.html ee49c31a8c40676f366959341cd98aecdcf9c14f'), "%3Cscript%3E%3C%21--%3Cscript%20--%3E%3C/script%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%20--%3E%22%0A%7C%20%20%20%3Cbody%3E"],"c541aa24beb8107a3726bd8b9e655ca8f95d7b48":[async_test('html5lib_tests16.html c541aa24beb8107a3726bd8b9e655ca8f95d7b48'), "%3Cscript%3E%3C%21--%3Cscript%3E%3C%5C/script%3E--%3E%3C/script%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%3E%3C%5C/script%3E--%3E%22%0A%7C%20%20%20%3Cbody%3E"],"7ae06c19dd24dea99940ceaed8dffdd0e24cd5f9":[async_test('html5lib_tests16.html 7ae06c19dd24dea99940ceaed8dffdd0e24cd5f9'), "%3Cscript%3E%3C%21--%3Cscript%3E%3C/scr%27%2B%27ipt%3E--%3E%3C/script%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%3E%3C/scr%27%2B%27ipt%3E--%3E%22%0A%7C%20%20%20%3Cbody%3E"],"6d2029f0e2404dcc7f836481cef6bf56f060b248":[async_test('html5lib_tests16.html 6d2029f0e2404dcc7f836481cef6bf56f060b248'), "%3Cscript%3E%3C%21--%3Cscript%3E%3C/script%3E%3Cscript%3E%3C/script%3E%3C/script%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%3E%3C/script%3E%3Cscript%3E%3C/script%3E%22%0A%7C%20%20%20%3Cbody%3E"],"5c5a26c8bcb37a214c47f4b6d9843de20a8fb7e1":[async_test('html5lib_tests16.html 5c5a26c8bcb37a214c47f4b6d9843de20a8fb7e1'), "%3Cscript%3E%3C%21--%3Cscript%3E%3C/script%3E%3Cscript%3E%3C/script%3E--%3E%3C%21--%3C/script%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%3E%3C/script%3E%3Cscript%3E%3C/script%3E--%3E%3C%21--%22%0A%7C%20%20%20%3Cbody%3E"],"3ee633bf4e4eadc2b70c6eebfa14c600435604c9":[async_test('html5lib_tests16.html 3ee633bf4e4eadc2b70c6eebfa14c600435604c9'), "%3Cscript%3E%3C%21--%3Cscript%3E%3C/script%3E%3Cscript%3E%3C/script%3E--%20%3E%3C/script%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%3E%3C/script%3E%3Cscript%3E%3C/script%3E--%20%3E%22%0A%7C%20%20%20%3Cbody%3E"],"ad5d10a0d7d8fc98040ff33f1db197735d6d3d52":[async_test('html5lib_tests16.html ad5d10a0d7d8fc98040ff33f1db197735d6d3d52'), "%3Cscript%3E%3C%21--%3Cscript%3E%3C/script%3E%3Cscript%3E%3C/script%3E-%20-%3E%3C/script%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%3E%3C/script%3E%3Cscript%3E%3C/script%3E-%20-%3E%22%0A%7C%20%20%20%3Cbody%3E"],"2bde3ac14192be5f4e664c2b01b5aaa57c14e347":[async_test('html5lib_tests16.html 2bde3ac14192be5f4e664c2b01b5aaa57c14e347'), "%3Cscript%3E%3C%21--%3Cscript%3E%3C/script%3E%3Cscript%3E%3C/script%3E-%20-%20%3E%3C/script%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%3E%3C/script%3E%3Cscript%3E%3C/script%3E-%20-%20%3E%22%0A%7C%20%20%20%3Cbody%3E"],"a87a03c8c3a06269e6ff8d11e142f6ebb05e9306":[async_test('html5lib_tests16.html a87a03c8c3a06269e6ff8d11e142f6ebb05e9306'), "%3Cscript%3E%3C%21--%3Cscript%3E%3C/script%3E%3Cscript%3E%3C/script%3E-%3E%3C/script%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%3E%3C/script%3E%3Cscript%3E%3C/script%3E-%3E%22%0A%7C%20%20%20%3Cbody%3E"],"190325aed218711647eae5581a1f629c76da297c":[async_test('html5lib_tests16.html 190325aed218711647eae5581a1f629c76da297c'), "%3Cscript%3E%3C%21--%3Cscript%3E--%21%3E%3C/script%3EX", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%3E--%21%3E%3C/script%3EX%22%0A%7C%20%20%20%3Cbody%3E"],"e244d9f1edb6275b69c4a832620b9439d39bfb22":[async_test('html5lib_tests16.html e244d9f1edb6275b69c4a832620b9439d39bfb22'), "%3Cscript%3E%3C%21--%3Cscr%27%2B%27ipt%3E%3C/script%3E--%3E%3C/script%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscr%27%2B%27ipt%3E%22%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22--%3E%22"],"751f7c9538b9fd00f5c7dd0ed59df07f4d51fdac":[async_test('html5lib_tests16.html 751f7c9538b9fd00f5c7dd0ed59df07f4d51fdac'), "%3Cscript%3E%3C%21--%3Cscript%3E%3C/scr%27%2B%27ipt%3E%3C/script%3EX", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cscript%3E%3C/scr%27%2B%27ipt%3E%3C/script%3EX%22%0A%7C%20%20%20%3Cbody%3E"],"762904de405fa26afdd39e024395a441bc6a0f8a":[async_test('html5lib_tests16.html 762904de405fa26afdd39e024395a441bc6a0f8a'), "%3Cstyle%3E%3C%21--%3Cstyle%3E%3C/style%3E--%3E%3C/style%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cstyle%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cstyle%3E%22%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22--%3E%22"],"4df21df646897816e166b3dd829a8a3e21157f22":[async_test('html5lib_tests16.html 4df21df646897816e166b3dd829a8a3e21157f22'), "%3Cstyle%3E%3C%21--%3C/style%3EX", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cstyle%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%22%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22X%22"],"9c241f721c1f6677d736b37ecd86bb230df329df":[async_test('html5lib_tests16.html 9c241f721c1f6677d736b37ecd86bb230df329df'), "%3Cstyle%3E%3C%21--...%3C/style%3E...--%3E%3C/style%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cstyle%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--...%22%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22...--%3E%22"],"96ebedcc684f27f984cc7be467c908bdab2470a9":[async_test('html5lib_tests16.html 96ebedcc684f27f984cc7be467c908bdab2470a9'), "%3Cstyle%3E%3C%21--%3Cbr%3E%3Chtml%20xmlns%3Av%3D%22urn%3Aschemas-microsoft-com%3Avml%22%3E%3C%21--%5Bif%20%21mso%5D%3E%3Cstyle%3E%3C/style%3EX", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cstyle%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cbr%3E%3Chtml%20xmlns%3Av%3D%22urn%3Aschemas-microsoft-com%3Avml%22%3E%3C%21--%5Bif%20%21mso%5D%3E%3Cstyle%3E%22%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22X%22"],"419cfbd87ad35c1d43214b122630cfde1c3ccf1b":[async_test('html5lib_tests16.html 419cfbd87ad35c1d43214b122630cfde1c3ccf1b'), "%3Cstyle%3E%3C%21--...%3Cstyle%3E%3C%21--...--%21%3E%3C/style%3E--%3E%3C/style%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cstyle%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--...%3Cstyle%3E%3C%21--...--%21%3E%22%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22--%3E%22"],"cf75ace0d7531b8daa271001dbf92b93b0b4490c":[async_test('html5lib_tests16.html cf75ace0d7531b8daa271001dbf92b93b0b4490c'), "%3Cstyle%3E%3C%21--...%3C/style%3E%3C%21--%20--%3E%3Cstyle%3E%40import%20...%3C/style%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cstyle%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--...%22%0A%7C%20%20%20%20%20%3C%21--%20%20%20--%3E%0A%7C%20%20%20%20%20%3Cstyle%3E%0A%7C%20%20%20%20%20%20%20%22%40import%20...%22%0A%7C%20%20%20%3Cbody%3E"],"a058b4bb03a689ce8528ed412d62cdd5bb879571":[async_test('html5lib_tests16.html a058b4bb03a689ce8528ed412d62cdd5bb879571'), "%3Cstyle%3E...%3Cstyle%3E%3C%21--...%3C/style%3E%3C%21--%20--%3E%3C/style%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cstyle%3E%0A%7C%20%20%20%20%20%20%20%22...%3Cstyle%3E%3C%21--...%22%0A%7C%20%20%20%20%20%3C%21--%20%20%20--%3E%0A%7C%20%20%20%3Cbody%3E"],"d7c871c41c9db40312ffc5af996ede62ecdfc579":[async_test('html5lib_tests16.html d7c871c41c9db40312ffc5af996ede62ecdfc579'), "%3Cstyle%3E...%3C%21--%5Bif%20IE%5D%3E%3Cstyle%3E...%3C/style%3EX", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cstyle%3E%0A%7C%20%20%20%20%20%20%20%22...%3C%21--%5Bif%20IE%5D%3E%3Cstyle%3E...%22%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22X%22"],"6c353ee8f48c1227eeab81279dc3eb3890c9c3bd":[async_test('html5lib_tests16.html 6c353ee8f48c1227eeab81279dc3eb3890c9c3bd'), "%3Ctitle%3E%3C%21--%3Ctitle%3E%3C/title%3E--%3E%3C/title%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Ctitle%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Ctitle%3E%22%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22--%3E%22"],"fea28aab54637701c5dfaef4f3fe64c72b272e1c":[async_test('html5lib_tests16.html fea28aab54637701c5dfaef4f3fe64c72b272e1c'), "%3Ctitle%3E%26lt%3B/title%3E%3C/title%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Ctitle%3E%0A%7C%20%20%20%20%20%20%20%22%3C/title%3E%22%0A%7C%20%20%20%3Cbody%3E"],"ecd79b7eb7af2bb4dadf710f70e0d78f62adc40e":[async_test('html5lib_tests16.html ecd79b7eb7af2bb4dadf710f70e0d78f62adc40e'), "%3Ctitle%3Efoo/title%3E%3Clink%3E%3C/head%3E%3Cbody%3EX", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Ctitle%3E%0A%7C%20%20%20%20%20%20%20%22foo/title%3E%3Clink%3E%3C/head%3E%3Cbody%3EX%22%0A%7C%20%20%20%3Cbody%3E"],"43917824cc1d9b5a65601f46e13a0779c3dcff4e":[async_test('html5lib_tests16.html 43917824cc1d9b5a65601f46e13a0779c3dcff4e'), "%3Cnoscript%3E%3C%21--%3Cnoscript%3E%3C/noscript%3E--%3E%3C/noscript%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cnoscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cnoscript%3E%22%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22--%3E%22"],"5423bb28649f37e70a0559cba78c3b253a60c277":[async_test('html5lib_tests16.html 5423bb28649f37e70a0559cba78c3b253a60c277'), "%3Cnoscript%3E%3C%21--%3C/noscript%3EX%3Cnoscript%3E--%3E%3C/noscript%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cnoscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%22%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22X%22%0A%7C%20%20%20%20%20%3Cnoscript%3E%0A%7C%20%20%20%20%20%20%20%22--%3E%22"],"2c091a50dfd31e766a5a629c0b7c21973e33319d":[async_test('html5lib_tests16.html 2c091a50dfd31e766a5a629c0b7c21973e33319d'), "%3Cnoscript%3E%3Ciframe%3E%3C/noscript%3EX", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cnoscript%3E%0A%7C%20%20%20%20%20%20%20%22%3Ciframe%3E%22%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22X%22"],"920feb4f9d1032dcec2abc5c526e4996f642968b":[async_test('html5lib_tests16.html 920feb4f9d1032dcec2abc5c526e4996f642968b'), "%3Cnoframes%3E%3C%21--%3Cnoframes%3E%3C/noframes%3E--%3E%3C/noframes%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cnoframes%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cnoframes%3E%22%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22--%3E%22"],"31b9b446263cd5b7a844d43f2a235ed9b0c53efb":[async_test('html5lib_tests16.html 31b9b446263cd5b7a844d43f2a235ed9b0c53efb'), "%3Cnoframes%3E%3Cbody%3E%3Cscript%3E%3C%21--...%3C/script%3E%3C/body%3E%3C/noframes%3E%3C/html%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cnoframes%3E%0A%7C%20%20%20%20%20%20%20%22%3Cbody%3E%3Cscript%3E%3C%21--...%3C/script%3E%3C/body%3E%22%0A%7C%20%20%20%3Cbody%3E"],"dbb5127246fee18718bcffc6cf0730674d12b98a":[async_test('html5lib_tests16.html dbb5127246fee18718bcffc6cf0730674d12b98a'), "%3Ctextarea%3E%3C%21--%3Ctextarea%3E%3C/textarea%3E--%3E%3C/textarea%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctextarea%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Ctextarea%3E%22%0A%7C%20%20%20%20%20%22--%3E%22"],"3872a4cfeba7651f0671de7e5f3922fd5053837b":[async_test('html5lib_tests16.html 3872a4cfeba7651f0671de7e5f3922fd5053837b'), "%3Ctextarea%3E%26lt%3B/textarea%3E%3C/textarea%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctextarea%3E%0A%7C%20%20%20%20%20%20%20%22%3C/textarea%3E%22"],"2fbcb2db61b6416cdf46e0526e1929d146ab3da7":[async_test('html5lib_tests16.html 2fbcb2db61b6416cdf46e0526e1929d146ab3da7'), "%3Ciframe%3E%3C%21--%3Ciframe%3E%3C/iframe%3E--%3E%3C/iframe%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ciframe%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Ciframe%3E%22%0A%7C%20%20%20%20%20%22--%3E%22"],"999da234e770bbf681a819423d04ea57415d9bbc":[async_test('html5lib_tests16.html 999da234e770bbf681a819423d04ea57415d9bbc'), "%3Ciframe%3E...%3C%21--X-%3E...%3C%21--/X-%3E...%3C/iframe%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ciframe%3E%0A%7C%20%20%20%20%20%20%20%22...%3C%21--X-%3E...%3C%21--/X-%3E...%22"],"6fc6be53a87bbb2d2a51a5617009063002321d09":[async_test('html5lib_tests16.html 6fc6be53a87bbb2d2a51a5617009063002321d09'), "%3Cxmp%3E%3C%21--%3Cxmp%3E%3C/xmp%3E--%3E%3C/xmp%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cxmp%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cxmp%3E%22%0A%7C%20%20%20%20%20%22--%3E%22"],"b0de72088fa3e543572329eda36fa4bd16e29fa3":[async_test('html5lib_tests16.html b0de72088fa3e543572329eda36fa4bd16e29fa3'), "%3Cnoembed%3E%3C%21--%3Cnoembed%3E%3C/noembed%3E--%3E%3C/noembed%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cnoembed%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%3Cnoembed%3E%22%0A%7C%20%20%20%20%20%22--%3E%22"],"2a6d8110b8148a9aa83db81dc38d544becea2fa9":[async_test('html5lib_tests16.html 2a6d8110b8148a9aa83db81dc38d544becea2fa9'), "%3C%21doctype%20html%3E%3Ctable%3E%0A", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%22%0A%22"],"6556aaaca3956eafbc1660bce50a2f3568f1bff6":[async_test('html5lib_tests16.html 6556aaaca3956eafbc1660bce50a2f3568f1bff6'), "%3C%21doctype%20html%3E%3Ctable%3E%3Ctd%3E%3Cspan%3E%3Cfont%3E%3C/span%3E%3Cspan%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cspan%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cspan%3E"],"8ba3d2c7712e9c0484a4cafc8b0ca6f35d8f11ed":[async_test('html5lib_tests16.html 8ba3d2c7712e9c0484a4cafc8b0ca6f35d8f11ed'), "%3C%21doctype%20html%3E%3Cform%3E%3Ctable%3E%3C/form%3E%3Cform%3E%3C/table%3E%3C/form%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cform%3E%0A%7C%20%20%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cform%3E"],
+ }
+ init_tests(get_type());
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests17.html b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests17.html
new file mode 100644
index 00000000000..6363ca72b2e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests17.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf8">
+ <title>HTML 5 Parser tests html5lib_tests17.html</title>
+ <meta name="timeout" content="long">
+ <meta name="variant" content="?run_type=uri">
+ <meta name="variant" content="?run_type=write">
+ <meta name="variant" content="?run_type=write_single">
+ </head>
+ <body>
+ <h1>html5lib Parser Test</h1>
+ <div id="log"></div>
+ <script src="common.js"></script>
+ <script src="test.js"></script>
+ <script src="template.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ var num_iframes = 8;
+ var order = ['bad1cc428ca144d278d40343f9da4d22d43b7b50','8a99dcd95c28dc294ec302998adac16111085aea','1d2be91c91dc2506354f01bb0058d0e10123668a','37ef4643c5f11b68f8991c4f1b34c3fe4d78c0af','0739d340b754e400864a668ac7f72259965b8bc7','16cb95e820b074bad119f13b1204cac90db8cf82','8b6c1a5706c668ccc47a4ff61527a30daa14848e','92ebd54a48d986a555e1a456565b3cbd06c78ffa','1fdd1835ee0cb01351d30fc567cd19b3ecda7966','55412bdbb0fe315b9ff46592e8f08ba47568f2e9','d5e1450f92115f6c5704b0b5f27699cd418816f9','a3ed0cf6e162498c7c5b87228c33bbcd960087a6','c1af331cb6400571f5e2b6ec81461223ab603d3d',];
+ var tests = {
+ "bad1cc428ca144d278d40343f9da4d22d43b7b50":[async_test('html5lib_tests17.html bad1cc428ca144d278d40343f9da4d22d43b7b50'), "%3C%21doctype%20html%3E%3Ctable%3E%3Ctbody%3E%3Cselect%3E%3Ctr%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cselect%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E"],"8a99dcd95c28dc294ec302998adac16111085aea":[async_test('html5lib_tests17.html 8a99dcd95c28dc294ec302998adac16111085aea'), "%3C%21doctype%20html%3E%3Ctable%3E%3Ctr%3E%3Cselect%3E%3Ctd%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cselect%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E"],"1d2be91c91dc2506354f01bb0058d0e10123668a":[async_test('html5lib_tests17.html 1d2be91c91dc2506354f01bb0058d0e10123668a'), "%3C%21doctype%20html%3E%3Ctable%3E%3Ctr%3E%3Ctd%3E%3Cselect%3E%3Ctd%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cselect%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E"],"37ef4643c5f11b68f8991c4f1b34c3fe4d78c0af":[async_test('html5lib_tests17.html 37ef4643c5f11b68f8991c4f1b34c3fe4d78c0af'), "%3C%21doctype%20html%3E%3Ctable%3E%3Ctr%3E%3Cth%3E%3Cselect%3E%3Ctd%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cth%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cselect%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E"],"0739d340b754e400864a668ac7f72259965b8bc7":[async_test('html5lib_tests17.html 0739d340b754e400864a668ac7f72259965b8bc7'), "%3C%21doctype%20html%3E%3Ctable%3E%3Ccaption%3E%3Cselect%3E%3Ctr%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ccaption%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cselect%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E"],"16cb95e820b074bad119f13b1204cac90db8cf82":[async_test('html5lib_tests17.html 16cb95e820b074bad119f13b1204cac90db8cf82'), "%3C%21doctype%20html%3E%3Cselect%3E%3Ctr%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cselect%3E"],"8b6c1a5706c668ccc47a4ff61527a30daa14848e":[async_test('html5lib_tests17.html 8b6c1a5706c668ccc47a4ff61527a30daa14848e'), "%3C%21doctype%20html%3E%3Cselect%3E%3Ctd%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cselect%3E"],"92ebd54a48d986a555e1a456565b3cbd06c78ffa":[async_test('html5lib_tests17.html 92ebd54a48d986a555e1a456565b3cbd06c78ffa'), "%3C%21doctype%20html%3E%3Cselect%3E%3Cth%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cselect%3E"],"1fdd1835ee0cb01351d30fc567cd19b3ecda7966":[async_test('html5lib_tests17.html 1fdd1835ee0cb01351d30fc567cd19b3ecda7966'), "%3C%21doctype%20html%3E%3Cselect%3E%3Ctbody%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cselect%3E"],"55412bdbb0fe315b9ff46592e8f08ba47568f2e9":[async_test('html5lib_tests17.html 55412bdbb0fe315b9ff46592e8f08ba47568f2e9'), "%3C%21doctype%20html%3E%3Cselect%3E%3Cthead%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cselect%3E"],"d5e1450f92115f6c5704b0b5f27699cd418816f9":[async_test('html5lib_tests17.html d5e1450f92115f6c5704b0b5f27699cd418816f9'), "%3C%21doctype%20html%3E%3Cselect%3E%3Ctfoot%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cselect%3E"],"a3ed0cf6e162498c7c5b87228c33bbcd960087a6":[async_test('html5lib_tests17.html a3ed0cf6e162498c7c5b87228c33bbcd960087a6'), "%3C%21doctype%20html%3E%3Cselect%3E%3Ccaption%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cselect%3E"],"c1af331cb6400571f5e2b6ec81461223ab603d3d":[async_test('html5lib_tests17.html c1af331cb6400571f5e2b6ec81461223ab603d3d'), "%3C%21doctype%20html%3E%3Ctable%3E%3Ctr%3E%3C/table%3Ea", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%22a%22"],
+ }
+ init_tests(get_type());
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests18.html b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests18.html
new file mode 100644
index 00000000000..5c23b22c58b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests18.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf8">
+ <title>HTML 5 Parser tests html5lib_tests18.html</title>
+ <meta name="timeout" content="long">
+ <meta name="variant" content="?run_type=uri">
+ <meta name="variant" content="?run_type=write">
+ <meta name="variant" content="?run_type=write_single">
+ </head>
+ <body>
+ <h1>html5lib Parser Test</h1>
+ <div id="log"></div>
+ <script src="common.js"></script>
+ <script src="test.js"></script>
+ <script src="template.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ var num_iframes = 8;
+ var order = ['0d0085749435e0d0ddb56c9db809bfcbbc995767','863c5dd5ef7e9279342de0f714383d3e47033e95','ddeaaff85a50ea415dee1c4ee6c43e98ea331953','61eb7572a2490ac82423953eefe8fcef8dbc78ee','df407b3f102bc2504539136b46afbb895763dc27','9ac591f40aae947707f7d5e83947712bbeca9574','4b6f10fa2d8b7cc70e3b3085aac46c64a0c42eaf','1e88e5946ba773f1202e8af27f2a17ef2658e3ee','17ec3aff2568b56687f00d6ee3aeb6625fdd8ecc','b22cb10082e7328708e1da334a12b015b90535a4','9bfd787aa3b30eb38ce7942696ccc01d991e8e52','41edb5b76ce7a4378daa093e59b1225af546864f','5c6c65bd01758ecb6eb539a979dfacf50ff93a78','76d96fecc3d88820bab5274089886d20bc164d74','28a8566daaae49c529298d0de8a26af1263ff625','13eb2279a1e58eb281541564ae945b87880ae7c2','3c7d4e068461b340966e07dff93d93503fcfa46c','d38ed6488066d3e0d4d74b29888c5d000c2f4808','43180045ad714b405e6fe110a27011f2644f16c2',];
+ var tests = {
+ "0d0085749435e0d0ddb56c9db809bfcbbc995767":[async_test('html5lib_tests18.html 0d0085749435e0d0ddb56c9db809bfcbbc995767'), "%3C%21doctype%20html%3E%3Cplaintext%3E%3C/plaintext%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cplaintext%3E%0A%7C%20%20%20%20%20%20%20%22%3C/plaintext%3E%22"],"863c5dd5ef7e9279342de0f714383d3e47033e95":[async_test('html5lib_tests18.html 863c5dd5ef7e9279342de0f714383d3e47033e95'), "%3C%21doctype%20html%3E%3Ctable%3E%3Cplaintext%3E%3C/plaintext%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cplaintext%3E%0A%7C%20%20%20%20%20%20%20%22%3C/plaintext%3E%22%0A%7C%20%20%20%20%20%3Ctable%3E"],"ddeaaff85a50ea415dee1c4ee6c43e98ea331953":[async_test('html5lib_tests18.html ddeaaff85a50ea415dee1c4ee6c43e98ea331953'), "%3C%21doctype%20html%3E%3Ctable%3E%3Ctbody%3E%3Cplaintext%3E%3C/plaintext%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cplaintext%3E%0A%7C%20%20%20%20%20%20%20%22%3C/plaintext%3E%22%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E"],"61eb7572a2490ac82423953eefe8fcef8dbc78ee":[async_test('html5lib_tests18.html 61eb7572a2490ac82423953eefe8fcef8dbc78ee'), "%3C%21doctype%20html%3E%3Ctable%3E%3Ctbody%3E%3Ctr%3E%3Cplaintext%3E%3C/plaintext%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cplaintext%3E%0A%7C%20%20%20%20%20%20%20%22%3C/plaintext%3E%22%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E"],"df407b3f102bc2504539136b46afbb895763dc27":[async_test('html5lib_tests18.html df407b3f102bc2504539136b46afbb895763dc27'), "%3C%21doctype%20html%3E%3Ctable%3E%3Ctd%3E%3Cplaintext%3E%3C/plaintext%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cplaintext%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22%3C/plaintext%3E%22"],"9ac591f40aae947707f7d5e83947712bbeca9574":[async_test('html5lib_tests18.html 9ac591f40aae947707f7d5e83947712bbeca9574'), "%3C%21doctype%20html%3E%3Ctable%3E%3Ccaption%3E%3Cplaintext%3E%3C/plaintext%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ccaption%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cplaintext%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22%3C/plaintext%3E%22"],"4b6f10fa2d8b7cc70e3b3085aac46c64a0c42eaf":[async_test('html5lib_tests18.html 4b6f10fa2d8b7cc70e3b3085aac46c64a0c42eaf'), "%3C%21doctype%20html%3E%3Ctable%3E%3Ctr%3E%3Cstyle%3E%3C/script%3E%3C/style%3Eabc", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22abc%22%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cstyle%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%22%3C/script%3E%22"],"1e88e5946ba773f1202e8af27f2a17ef2658e3ee":[async_test('html5lib_tests18.html 1e88e5946ba773f1202e8af27f2a17ef2658e3ee'), "%3C%21doctype%20html%3E%3Ctable%3E%3Ctr%3E%3Cscript%3E%3C/style%3E%3C/script%3Eabc", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22abc%22%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%22%3C/style%3E%22"],"17ec3aff2568b56687f00d6ee3aeb6625fdd8ecc":[async_test('html5lib_tests18.html 17ec3aff2568b56687f00d6ee3aeb6625fdd8ecc'), "%3C%21doctype%20html%3E%3Ctable%3E%3Ccaption%3E%3Cstyle%3E%3C/script%3E%3C/style%3Eabc", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ccaption%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cstyle%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22%3C/script%3E%22%0A%7C%20%20%20%20%20%20%20%20%20%22abc%22"],"b22cb10082e7328708e1da334a12b015b90535a4":[async_test('html5lib_tests18.html b22cb10082e7328708e1da334a12b015b90535a4'), "%3C%21doctype%20html%3E%3Ctable%3E%3Ctd%3E%3Cstyle%3E%3C/script%3E%3C/style%3Eabc", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cstyle%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22%3C/script%3E%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%22abc%22"],"9bfd787aa3b30eb38ce7942696ccc01d991e8e52":[async_test('html5lib_tests18.html 9bfd787aa3b30eb38ce7942696ccc01d991e8e52'), "%3C%21doctype%20html%3E%3Cselect%3E%3Cscript%3E%3C/style%3E%3C/script%3Eabc", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cselect%3E%0A%7C%20%20%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%20%20%22%3C/style%3E%22%0A%7C%20%20%20%20%20%20%20%22abc%22"],"41edb5b76ce7a4378daa093e59b1225af546864f":[async_test('html5lib_tests18.html 41edb5b76ce7a4378daa093e59b1225af546864f'), "%3C%21doctype%20html%3E%3Ctable%3E%3Cselect%3E%3Cscript%3E%3C/style%3E%3C/script%3Eabc", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cselect%3E%0A%7C%20%20%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%20%20%22%3C/style%3E%22%0A%7C%20%20%20%20%20%20%20%22abc%22%0A%7C%20%20%20%20%20%3Ctable%3E"],"5c6c65bd01758ecb6eb539a979dfacf50ff93a78":[async_test('html5lib_tests18.html 5c6c65bd01758ecb6eb539a979dfacf50ff93a78'), "%3C%21doctype%20html%3E%3Ctable%3E%3Ctr%3E%3Cselect%3E%3Cscript%3E%3C/style%3E%3C/script%3Eabc", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cselect%3E%0A%7C%20%20%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%20%20%22%3C/style%3E%22%0A%7C%20%20%20%20%20%20%20%22abc%22%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E"],"76d96fecc3d88820bab5274089886d20bc164d74":[async_test('html5lib_tests18.html 76d96fecc3d88820bab5274089886d20bc164d74'), "%3C%21doctype%20html%3E%3Cframeset%3E%3C/frameset%3E%3Cnoframes%3Eabc", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E%0A%7C%20%20%20%3Cnoframes%3E%0A%7C%20%20%20%20%20%22abc%22"],"28a8566daaae49c529298d0de8a26af1263ff625":[async_test('html5lib_tests18.html 28a8566daaae49c529298d0de8a26af1263ff625'), "%3C%21doctype%20html%3E%3Cframeset%3E%3C/frameset%3E%3Cnoframes%3Eabc%3C/noframes%3E%3C%21--abc--%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E%0A%7C%20%20%20%3Cnoframes%3E%0A%7C%20%20%20%20%20%22abc%22%0A%7C%20%20%20%3C%21--%20abc%20--%3E"],"13eb2279a1e58eb281541564ae945b87880ae7c2":[async_test('html5lib_tests18.html 13eb2279a1e58eb281541564ae945b87880ae7c2'), "%3C%21doctype%20html%3E%3Cframeset%3E%3C/frameset%3E%3C/html%3E%3Cnoframes%3Eabc", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E%0A%7C%20%20%20%3Cnoframes%3E%0A%7C%20%20%20%20%20%22abc%22"],"3c7d4e068461b340966e07dff93d93503fcfa46c":[async_test('html5lib_tests18.html 3c7d4e068461b340966e07dff93d93503fcfa46c'), "%3C%21doctype%20html%3E%3Cframeset%3E%3C/frameset%3E%3C/html%3E%3Cnoframes%3Eabc%3C/noframes%3E%3C%21--abc--%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E%0A%7C%20%20%20%3Cnoframes%3E%0A%7C%20%20%20%20%20%22abc%22%0A%7C%20%3C%21--%20abc%20--%3E"],"d38ed6488066d3e0d4d74b29888c5d000c2f4808":[async_test('html5lib_tests18.html d38ed6488066d3e0d4d74b29888c5d000c2f4808'), "%3C%21doctype%20html%3E%3Ctable%3E%3Ctr%3E%3C/tbody%3E%3Ctfoot%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%3Ctfoot%3E"],"43180045ad714b405e6fe110a27011f2644f16c2":[async_test('html5lib_tests18.html 43180045ad714b405e6fe110a27011f2644f16c2'), "%3C%21doctype%20html%3E%3Ctable%3E%3Ctd%3E%3Csvg%3E%3C/svg%3Eabc%3Ctd%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%22abc%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E"],
+ }
+ init_tests(get_type());
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests19.html b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests19.html
new file mode 100644
index 00000000000..151b121704a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests19.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf8">
+ <title>HTML 5 Parser tests html5lib_tests19.html</title>
+ <meta name="timeout" content="long">
+ <meta name="variant" content="?run_type=uri">
+ <meta name="variant" content="?run_type=write">
+ <meta name="variant" content="?run_type=write_single">
+ </head>
+ <body>
+ <h1>html5lib Parser Test</h1>
+ <div id="log"></div>
+ <script src="common.js"></script>
+ <script src="test.js"></script>
+ <script src="template.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ var num_iframes = 8;
+ var order = ['6135e0cbdbb22a97e8a13c2442c3e9a9e0a53298','6b46dba2f4d7d1a08359ab21fe5e011463dd8746','bd558a6d89fae63fed9c0801e6fd8e8737bc8dc1','a7955e9f06178980cbc13fc4d548f196fef42b13','2fda53e44aa91cb475f8b1aa57e938adcce60d4d','9f55c21807de5c769197a9a2f29f836f08af050b','197605d0b406dbb3de884de6949237dd33669997','73760ab95f224cf93922b45dbe5898005ada203c','1bba57ac3ccda8d4c7a79bde5342eede0bd10d8e','ce477c47f37eea25ad53c88915b75c801e41ee54','3b1730b917da1c33da80ee08d41573c44404c663','94d253ded5fe8c34906a57f0c16daf5f067cf386','ac6b608079815ad00c84b291ad6715eec523ccf4','a68acf7673e0c886fcf8cf609f3a39fb36362de5','266157f051148b068dad52e9786a0bda96e851db','2fd40bb6048be379000d73bc52a50405ca99b356','19652e3b1ec783f279f527ddfb07073684520ab8','e5676878cff9332b572ebfd327e426f87e32ab4d','03bbba49b30ec908e06e3c84e1fcede1ac7508ff','5f9f25a089e72b4a4e5d7ebbacb440349c53f52f','d26f2542fc6fcee4e737b578c8db716a96a22ade','0e8c4b181993b477f4f215d5724b99ad04f18b2d','e3f1de111562f25106efad76583a3b6c0e3516ba','84db6521d1350830f3e46b7d9676527e1b4ee9e2','033d9b356b2a646471de009fa8a75e40500d2dd2','0971186f913b3c7f915817d2b82c73ea6487e932','5257f17c3ecab5b65d74d7c27f0fd492f82ef9b9','b8c3379e60829428188fd57e974ea4d8a7e7ec45','f9ab61cdf08301bcf02208165cc94e6bdbad746c','c6aa9952dcccdde3fc6d4ba104647f049d038e66','3984cbe166b42d77ff6dadc8e1687075db7a8e65','2d78ba34eecedf8261e9a9e3f8858baf00a0d960','8d45a57b7093df38c88dccb1f3fba6a62c810445','871917ed049ff21b35e74e39de2ca1eef6863562','74ad5d3026f1b3eb6553086eb2811eed4418e334','0b1e97138c4d8e8d770f107202e46a18362fd587','02624fcb7ddb77b15e9bc553d8392fc8cd031f68','a2579d287fd8111306e6dcd7248971a6baa4488d','acd1c9218828ea4367920c7a499c54de7f9a618f','36a6346b03982942b4427d5089271a101ebf1605','e58ed5b56f81d057c23be31e068a10e694f52adf','d422166b880468765f34d89075d4db9c4fcbfee9','fc673f5874c0cf1477554dfb733d6292cc01558b','0d2192c16cc224e770abff9e9e89e860aff9da78','d5941f6b68ef817d062636d0d61c24c68d0d86a2','259a085138224e3dfe0dceded2a043e72a8b6d76','869fff76cfe00ff33987de007ce98dc949bf8cbf','c06518cdbf3816faf265644d28d93b7aee9258f7','2fb0cdb3a9f69ca6c3d564e01f89d7173cd51295','138623cd07ccff1ce13bb1aa5dbaaadc962c414f','52e4a8422d6ef591f33f8686842d974dbaa33302','5ba1d0e97f121810025c1d6447a426c669661637','709ec07924db4c9fd66d48eac08575dfdef01d8f','f72edb80bc3be091e4b448cd1de8fe851d623e05','cb7de0dc7e17c1454ceaa7eb49cb9f9476a1f510','511bf4bae15c8119042e5e80b5358b70e7da26c1','c51ee24ef9d92206318cc5bbba784630cd10e531','819d39ae49fd04f0dfce90ac8ed2f8e423bb9329','ef6bdf5b3ba9d41d6c1c08ede60c2e7fb21c6d71','6bf9c038255c31f20d8fbeaebdf3609eb3c9ed75','08983ab2a54f61b09a1df134cdaf51d321f3ef32','2ef94ed028fa71b70540cf41f0884ae0c1cf8077','5c9ed202789fb29566e0d146d155e0d672e8a037','7d766253cbf500df03506dfb7f2cbdd0f0f533c6','4d5629c61993ef0bb83fcbd80ccc6ead7cd776ee','6320d9fa3295984d3da7e4831ced75dfb97d4848','bdb97868e951b7a719fa8b1afc79650bf9aae7a5','81868cde252694a252b6b0c8d366850f8a54736c','20651db48147f8dda189c563f5fa60bfd0913ac0','d098e8a39897cd8453fc18399622e413872b054c','0beb7903dcc0dbee206d8b6e729963a0461eedb3','78e5cdb86bf2aecef4697d70d50499b50de5c25b','cfb1d482e5971a6915c90434f580721b772fc09b','99d8bff8bbcca1c7faa7b6e10b9ff305b9f99594','daaa43db05ffe9bdd8d734a4389fb3c459caddf1','b3d421e57a4135731309152d7f47e26a4866f3d6','aa5eac4b7a0bafdafcd52cb190a8e181ff74144c','91d56a57f4c8af2bce03e9974df0a80f62686fb4','9cbad5cad719a63d2eb7721de6737a346ad42da1','057c2e91a7e6053d39436efe2bc29049f6fa8e82','61e6517e5e82cdaed41ab3e1f6fa927731aa0c82','9274ab4f08baa52c5d7016f6062f186730cfbe6c','fc2fa41ebadc21653b38d70c1097bd4ac5979948','473303e65f26fafacbaf01c11b04d745ff293963','7854276e1637619f693cd87f64542c08c35d40bd','a2d262d392e8d10645ce559edf401df3f3872eb3','d5e50987bf495e285e279ff8670255d9b1314f5d','be54d7506e54a127a05b115a8659a5b52fa57f6c','af389f1a8ef93c457560fd2445df80a6789dab0d','601dfa9502942deb8bf46a91c64f10f649bc1875','4b01442faf29563d3b736d235515f77c20c81863','696a2b60681b0b6758f165a67e29a84b0f75a153','7a48b98cbae5cd7cbbb90f138c0d12da6c4448b3','d7693a0f2be68925250d3aa2cf295b1d1a60bf94','9e4d91f02184de1b1e5d927144bb06d3bc78bb09','9655591702381a52fe0eb3224e63e2d8bfd735e8','fe9aa1c8ec32796e26f3e58022f0e42dc365b5c7','4c9ec04359c3e94d4a56d6932d289f0c4246d1ef','3fcc2f15951b3c3375c3e359cf7888c71187994a','a94b35c317763de75150df6b436c7c153aeb8c51','173b990198dd8fd9534d7808817c19440b75d406','48ed5945491d4ad0c00acfd01c2060a459436d34','392b8d4d25351467da961e4ab011a1d4e970b97a','bd14373173ea3617610fc8154237f59f1a810733','db3c4ddb389a2b8f42ca6b3719007d4de2eccc41','c1741a62627b2e5bb1cfa2b2cd667f3f9f76157e','0d6cf626790e9f06e30ceb6baf3004663b0247e7',];
+ var tests = {
+ "6135e0cbdbb22a97e8a13c2442c3e9a9e0a53298":[async_test('html5lib_tests19.html 6135e0cbdbb22a97e8a13c2442c3e9a9e0a53298'), "%3C%21doctype%20html%3E%3Cmath%3E%3Cmn%20DefinitionUrl%3D%22foo%22%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20mn%3E%0A%7C%20%20%20%20%20%20%20%20%20definitionURL%3D%22foo%22"],"6b46dba2f4d7d1a08359ab21fe5e011463dd8746":[async_test('html5lib_tests19.html 6b46dba2f4d7d1a08359ab21fe5e011463dd8746'), "%3C%21doctype%20html%3E%3Chtml%3E%3C/p%3E%3C%21--foo--%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3C%21--%20foo%20--%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"bd558a6d89fae63fed9c0801e6fd8e8737bc8dc1":[async_test('html5lib_tests19.html bd558a6d89fae63fed9c0801e6fd8e8737bc8dc1'), "%3C%21doctype%20html%3E%3Chead%3E%3C/head%3E%3C/p%3E%3C%21--foo--%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3C%21--%20foo%20--%3E%0A%7C%20%20%20%3Cbody%3E"],"a7955e9f06178980cbc13fc4d548f196fef42b13":[async_test('html5lib_tests19.html a7955e9f06178980cbc13fc4d548f196fef42b13'), "%3C%21doctype%20html%3E%3Cbody%3E%3Cp%3E%3Cpre%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%3Cpre%3E"],"2fda53e44aa91cb475f8b1aa57e938adcce60d4d":[async_test('html5lib_tests19.html 2fda53e44aa91cb475f8b1aa57e938adcce60d4d'), "%3C%21doctype%20html%3E%3Cbody%3E%3Cp%3E%3Clisting%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%3Clisting%3E"],"9f55c21807de5c769197a9a2f29f836f08af050b":[async_test('html5lib_tests19.html 9f55c21807de5c769197a9a2f29f836f08af050b'), "%3C%21doctype%20html%3E%3Cp%3E%3Cplaintext%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%3Cplaintext%3E"],"197605d0b406dbb3de884de6949237dd33669997":[async_test('html5lib_tests19.html 197605d0b406dbb3de884de6949237dd33669997'), "%3C%21doctype%20html%3E%3Cp%3E%3Ch1%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%3Ch1%3E"],"73760ab95f224cf93922b45dbe5898005ada203c":[async_test('html5lib_tests19.html 73760ab95f224cf93922b45dbe5898005ada203c'), "%3C%21doctype%20html%3E%3Cform%3E%3Cisindex%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cform%3E"],"1bba57ac3ccda8d4c7a79bde5342eede0bd10d8e":[async_test('html5lib_tests19.html 1bba57ac3ccda8d4c7a79bde5342eede0bd10d8e'), "%3C%21doctype%20html%3E%3Cisindex%20action%3D%22POST%22%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cform%3E%0A%7C%20%20%20%20%20%20%20action%3D%22POST%22%0A%7C%20%20%20%20%20%20%20%3Chr%3E%0A%7C%20%20%20%20%20%20%20%3Clabel%3E%0A%7C%20%20%20%20%20%20%20%20%20%22This%20is%20a%20searchable%20index.%20Enter%20search%20keywords%3A%20%22%0A%7C%20%20%20%20%20%20%20%20%20%3Cinput%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20name%3D%22isindex%22%0A%7C%20%20%20%20%20%20%20%3Chr%3E"],"ce477c47f37eea25ad53c88915b75c801e41ee54":[async_test('html5lib_tests19.html ce477c47f37eea25ad53c88915b75c801e41ee54'), "%3C%21doctype%20html%3E%3Cisindex%20prompt%3D%22this%20is%20isindex%22%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cform%3E%0A%7C%20%20%20%20%20%20%20%3Chr%3E%0A%7C%20%20%20%20%20%20%20%3Clabel%3E%0A%7C%20%20%20%20%20%20%20%20%20%22this%20is%20isindex%22%0A%7C%20%20%20%20%20%20%20%20%20%3Cinput%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20name%3D%22isindex%22%0A%7C%20%20%20%20%20%20%20%3Chr%3E"],"3b1730b917da1c33da80ee08d41573c44404c663":[async_test('html5lib_tests19.html 3b1730b917da1c33da80ee08d41573c44404c663'), "%3C%21doctype%20html%3E%3Cisindex%20type%3D%22hidden%22%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cform%3E%0A%7C%20%20%20%20%20%20%20%3Chr%3E%0A%7C%20%20%20%20%20%20%20%3Clabel%3E%0A%7C%20%20%20%20%20%20%20%20%20%22This%20is%20a%20searchable%20index.%20Enter%20search%20keywords%3A%20%22%0A%7C%20%20%20%20%20%20%20%20%20%3Cinput%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20name%3D%22isindex%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20type%3D%22hidden%22%0A%7C%20%20%20%20%20%20%20%3Chr%3E"],"94d253ded5fe8c34906a57f0c16daf5f067cf386":[async_test('html5lib_tests19.html 94d253ded5fe8c34906a57f0c16daf5f067cf386'), "%3C%21doctype%20html%3E%3Cisindex%20name%3D%22foo%22%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cform%3E%0A%7C%20%20%20%20%20%20%20%3Chr%3E%0A%7C%20%20%20%20%20%20%20%3Clabel%3E%0A%7C%20%20%20%20%20%20%20%20%20%22This%20is%20a%20searchable%20index.%20Enter%20search%20keywords%3A%20%22%0A%7C%20%20%20%20%20%20%20%20%20%3Cinput%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20name%3D%22isindex%22%0A%7C%20%20%20%20%20%20%20%3Chr%3E"],"ac6b608079815ad00c84b291ad6715eec523ccf4":[async_test('html5lib_tests19.html ac6b608079815ad00c84b291ad6715eec523ccf4'), "%3C%21doctype%20html%3E%3Cruby%3E%3Cp%3E%3Crp%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cruby%3E%0A%7C%20%20%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Crp%3E"],"a68acf7673e0c886fcf8cf609f3a39fb36362de5":[async_test('html5lib_tests19.html a68acf7673e0c886fcf8cf609f3a39fb36362de5'), "%3C%21doctype%20html%3E%3Cruby%3E%3Cdiv%3E%3Cspan%3E%3Crp%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cruby%3E%0A%7C%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cspan%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Crp%3E"],"266157f051148b068dad52e9786a0bda96e851db":[async_test('html5lib_tests19.html 266157f051148b068dad52e9786a0bda96e851db'), "%3C%21doctype%20html%3E%3Cruby%3E%3Cdiv%3E%3Cp%3E%3Crp%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cruby%3E%0A%7C%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Crp%3E"],"2fd40bb6048be379000d73bc52a50405ca99b356":[async_test('html5lib_tests19.html 2fd40bb6048be379000d73bc52a50405ca99b356'), "%3C%21doctype%20html%3E%3Cruby%3E%3Cp%3E%3Crt%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cruby%3E%0A%7C%20%20%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Crt%3E"],"19652e3b1ec783f279f527ddfb07073684520ab8":[async_test('html5lib_tests19.html 19652e3b1ec783f279f527ddfb07073684520ab8'), "%3C%21doctype%20html%3E%3Cruby%3E%3Cdiv%3E%3Cspan%3E%3Crt%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cruby%3E%0A%7C%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cspan%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Crt%3E"],"e5676878cff9332b572ebfd327e426f87e32ab4d":[async_test('html5lib_tests19.html e5676878cff9332b572ebfd327e426f87e32ab4d'), "%3C%21doctype%20html%3E%3Cruby%3E%3Cdiv%3E%3Cp%3E%3Crt%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cruby%3E%0A%7C%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Crt%3E"],"03bbba49b30ec908e06e3c84e1fcede1ac7508ff":[async_test('html5lib_tests19.html 03bbba49b30ec908e06e3c84e1fcede1ac7508ff'), "%3Chtml%3E%3Cruby%3Ea%3Crb%3Eb%3Crt%3E%3C/ruby%3E%3C/html%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cruby%3E%0A%7C%20%20%20%20%20%20%20%22a%22%0A%7C%20%20%20%20%20%20%20%3Crb%3E%0A%7C%20%20%20%20%20%20%20%20%20%22b%22%0A%7C%20%20%20%20%20%20%20%3Crt%3E"],"5f9f25a089e72b4a4e5d7ebbacb440349c53f52f":[async_test('html5lib_tests19.html 5f9f25a089e72b4a4e5d7ebbacb440349c53f52f'), "%3Chtml%3E%3Cruby%3Ea%3Crp%3Eb%3Crt%3E%3C/ruby%3E%3C/html%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cruby%3E%0A%7C%20%20%20%20%20%20%20%22a%22%0A%7C%20%20%20%20%20%20%20%3Crp%3E%0A%7C%20%20%20%20%20%20%20%20%20%22b%22%0A%7C%20%20%20%20%20%20%20%3Crt%3E"],"d26f2542fc6fcee4e737b578c8db716a96a22ade":[async_test('html5lib_tests19.html d26f2542fc6fcee4e737b578c8db716a96a22ade'), "%3Chtml%3E%3Cruby%3Ea%3Crt%3Eb%3Crt%3E%3C/ruby%3E%3C/html%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cruby%3E%0A%7C%20%20%20%20%20%20%20%22a%22%0A%7C%20%20%20%20%20%20%20%3Crt%3E%0A%7C%20%20%20%20%20%20%20%20%20%22b%22%0A%7C%20%20%20%20%20%20%20%3Crt%3E"],"0e8c4b181993b477f4f215d5724b99ad04f18b2d":[async_test('html5lib_tests19.html 0e8c4b181993b477f4f215d5724b99ad04f18b2d'), "%3Chtml%3E%3Cruby%3Ea%3Crtc%3Eb%3Crt%3Ec%3Crb%3Ed%3C/ruby%3E%3C/html%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cruby%3E%0A%7C%20%20%20%20%20%20%20%22a%22%0A%7C%20%20%20%20%20%20%20%3Crtc%3E%0A%7C%20%20%20%20%20%20%20%20%20%22b%22%0A%7C%20%20%20%20%20%20%20%20%20%3Crt%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22c%22%0A%7C%20%20%20%20%20%20%20%3Crb%3E%0A%7C%20%20%20%20%20%20%20%20%20%22d%22"],"e3f1de111562f25106efad76583a3b6c0e3516ba":[async_test('html5lib_tests19.html e3f1de111562f25106efad76583a3b6c0e3516ba'), "%3C%21doctype%20html%3E%3Cmath/%3E%3Cfoo%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%3Cfoo%3E"],"84db6521d1350830f3e46b7d9676527e1b4ee9e2":[async_test('html5lib_tests19.html 84db6521d1350830f3e46b7d9676527e1b4ee9e2'), "%3C%21doctype%20html%3E%3Csvg/%3E%3Cfoo%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%3Cfoo%3E"],"033d9b356b2a646471de009fa8a75e40500d2dd2":[async_test('html5lib_tests19.html 033d9b356b2a646471de009fa8a75e40500d2dd2'), "%3C%21doctype%20html%3E%3Cdiv%3E%3C/body%3E%3C%21--foo--%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%3C%21--%20foo%20--%3E"],"0971186f913b3c7f915817d2b82c73ea6487e932":[async_test('html5lib_tests19.html 0971186f913b3c7f915817d2b82c73ea6487e932'), "%3C%21doctype%20html%3E%3Ch1%3E%3Cdiv%3E%3Ch3%3E%3Cspan%3E%3C/h1%3Efoo", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ch1%3E%0A%7C%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ch3%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cspan%3E%0A%7C%20%20%20%20%20%20%20%20%20%22foo%22"],"5257f17c3ecab5b65d74d7c27f0fd492f82ef9b9":[async_test('html5lib_tests19.html 5257f17c3ecab5b65d74d7c27f0fd492f82ef9b9'), "%3C%21doctype%20html%3E%3Cp%3E%3C/h3%3Efoo", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%22foo%22"],"b8c3379e60829428188fd57e974ea4d8a7e7ec45":[async_test('html5lib_tests19.html b8c3379e60829428188fd57e974ea4d8a7e7ec45'), "%3C%21doctype%20html%3E%3Ch3%3E%3Cli%3Eabc%3C/h2%3Efoo", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ch3%3E%0A%7C%20%20%20%20%20%20%20%3Cli%3E%0A%7C%20%20%20%20%20%20%20%20%20%22abc%22%0A%7C%20%20%20%20%20%22foo%22"],"f9ab61cdf08301bcf02208165cc94e6bdbad746c":[async_test('html5lib_tests19.html f9ab61cdf08301bcf02208165cc94e6bdbad746c'), "%3C%21doctype%20html%3E%3Ctable%3Eabc%3C%21--foo--%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22abc%22%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3C%21--%20foo%20--%3E"],"c6aa9952dcccdde3fc6d4ba104647f049d038e66":[async_test('html5lib_tests19.html c6aa9952dcccdde3fc6d4ba104647f049d038e66'), "%3C%21doctype%20html%3E%3Ctable%3E%20%20%3C%21--foo--%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%22%20%20%22%0A%7C%20%20%20%20%20%20%20%3C%21--%20foo%20--%3E"],"3984cbe166b42d77ff6dadc8e1687075db7a8e65":[async_test('html5lib_tests19.html 3984cbe166b42d77ff6dadc8e1687075db7a8e65'), "%3C%21doctype%20html%3E%3Ctable%3E%20b%20%3C%21--foo--%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22%20b%20%22%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3C%21--%20foo%20--%3E"],"2d78ba34eecedf8261e9a9e3f8858baf00a0d960":[async_test('html5lib_tests19.html 2d78ba34eecedf8261e9a9e3f8858baf00a0d960'), "%3C%21doctype%20html%3E%3Cselect%3E%3Coption%3E%3Coption%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cselect%3E%0A%7C%20%20%20%20%20%20%20%3Coption%3E%0A%7C%20%20%20%20%20%20%20%3Coption%3E"],"8d45a57b7093df38c88dccb1f3fba6a62c810445":[async_test('html5lib_tests19.html 8d45a57b7093df38c88dccb1f3fba6a62c810445'), "%3C%21doctype%20html%3E%3Cselect%3E%3Coption%3E%3C/optgroup%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cselect%3E%0A%7C%20%20%20%20%20%20%20%3Coption%3E"],"871917ed049ff21b35e74e39de2ca1eef6863562":[async_test('html5lib_tests19.html 871917ed049ff21b35e74e39de2ca1eef6863562'), "%3C%21doctype%20html%3E%3Cdd%3E%3Coptgroup%3E%3Cdd%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdd%3E%0A%7C%20%20%20%20%20%20%20%3Coptgroup%3E%0A%7C%20%20%20%20%20%3Cdd%3E"],"74ad5d3026f1b3eb6553086eb2811eed4418e334":[async_test('html5lib_tests19.html 74ad5d3026f1b3eb6553086eb2811eed4418e334'), "%3C%21doctype%20html%3E%3Cp%3E%3Cmath%3E%3Cmi%3E%3Cp%3E%3Ch1%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cmath%20mi%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ch1%3E"],"0b1e97138c4d8e8d770f107202e46a18362fd587":[async_test('html5lib_tests19.html 0b1e97138c4d8e8d770f107202e46a18362fd587'), "%3C%21doctype%20html%3E%3Cp%3E%3Cmath%3E%3Cmo%3E%3Cp%3E%3Ch1%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cmath%20mo%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ch1%3E"],"02624fcb7ddb77b15e9bc553d8392fc8cd031f68":[async_test('html5lib_tests19.html 02624fcb7ddb77b15e9bc553d8392fc8cd031f68'), "%3C%21doctype%20html%3E%3Cp%3E%3Cmath%3E%3Cmn%3E%3Cp%3E%3Ch1%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cmath%20mn%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ch1%3E"],"a2579d287fd8111306e6dcd7248971a6baa4488d":[async_test('html5lib_tests19.html a2579d287fd8111306e6dcd7248971a6baa4488d'), "%3C%21doctype%20html%3E%3Cp%3E%3Cmath%3E%3Cms%3E%3Cp%3E%3Ch1%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cmath%20ms%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ch1%3E"],"acd1c9218828ea4367920c7a499c54de7f9a618f":[async_test('html5lib_tests19.html acd1c9218828ea4367920c7a499c54de7f9a618f'), "%3C%21doctype%20html%3E%3Cp%3E%3Cmath%3E%3Cmtext%3E%3Cp%3E%3Ch1%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cmath%20mtext%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ch1%3E"],"36a6346b03982942b4427d5089271a101ebf1605":[async_test('html5lib_tests19.html 36a6346b03982942b4427d5089271a101ebf1605'), "%3C%21doctype%20html%3E%3Cframeset%3E%3C/noframes%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E"],"e58ed5b56f81d057c23be31e068a10e694f52adf":[async_test('html5lib_tests19.html e58ed5b56f81d057c23be31e068a10e694f52adf'), "%3C%21doctype%20html%3E%3Chtml%20c%3Dd%3E%3Cbody%3E%3C/html%3E%3Chtml%20a%3Db%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20a%3D%22b%22%0A%7C%20%20%20c%3D%22d%22%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"d422166b880468765f34d89075d4db9c4fcbfee9":[async_test('html5lib_tests19.html d422166b880468765f34d89075d4db9c4fcbfee9'), "%3C%21doctype%20html%3E%3Chtml%20c%3Dd%3E%3Cframeset%3E%3C/frameset%3E%3C/html%3E%3Chtml%20a%3Db%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20a%3D%22b%22%0A%7C%20%20%20c%3D%22d%22%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E"],"fc673f5874c0cf1477554dfb733d6292cc01558b":[async_test('html5lib_tests19.html fc673f5874c0cf1477554dfb733d6292cc01558b'), "%3C%21doctype%20html%3E%3Chtml%3E%3Cframeset%3E%3C/frameset%3E%3C/html%3E%3C%21--foo--%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E%0A%7C%20%3C%21--%20foo%20--%3E"],"0d2192c16cc224e770abff9e9e89e860aff9da78":[async_test('html5lib_tests19.html 0d2192c16cc224e770abff9e9e89e860aff9da78'), "%3C%21doctype%20html%3E%3Chtml%3E%3Cframeset%3E%3C/frameset%3E%3C/html%3E%20%20", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E%0A%7C%20%20%20%22%20%20%22"],"d5941f6b68ef817d062636d0d61c24c68d0d86a2":[async_test('html5lib_tests19.html d5941f6b68ef817d062636d0d61c24c68d0d86a2'), "%3C%21doctype%20html%3E%3Chtml%3E%3Cframeset%3E%3C/frameset%3E%3C/html%3Eabc", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E"],"259a085138224e3dfe0dceded2a043e72a8b6d76":[async_test('html5lib_tests19.html 259a085138224e3dfe0dceded2a043e72a8b6d76'), "%3C%21doctype%20html%3E%3Chtml%3E%3Cframeset%3E%3C/frameset%3E%3C/html%3E%3Cp%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E"],"869fff76cfe00ff33987de007ce98dc949bf8cbf":[async_test('html5lib_tests19.html 869fff76cfe00ff33987de007ce98dc949bf8cbf'), "%3C%21doctype%20html%3E%3Chtml%3E%3Cframeset%3E%3C/frameset%3E%3C/html%3E%3C/p%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E"],"c06518cdbf3816faf265644d28d93b7aee9258f7":[async_test('html5lib_tests19.html c06518cdbf3816faf265644d28d93b7aee9258f7'), "%3Chtml%3E%3Cframeset%3E%3C/frameset%3E%3C/html%3E%3C%21doctype%20html%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E"],"2fb0cdb3a9f69ca6c3d564e01f89d7173cd51295":[async_test('html5lib_tests19.html 2fb0cdb3a9f69ca6c3d564e01f89d7173cd51295'), "%3C%21doctype%20html%3E%3Cbody%3E%3Cframeset%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"138623cd07ccff1ce13bb1aa5dbaaadc962c414f":[async_test('html5lib_tests19.html 138623cd07ccff1ce13bb1aa5dbaaadc962c414f'), "%3C%21doctype%20html%3E%3Cp%3E%3Cframeset%3E%3Cframe%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E%0A%7C%20%20%20%20%20%3Cframe%3E"],"52e4a8422d6ef591f33f8686842d974dbaa33302":[async_test('html5lib_tests19.html 52e4a8422d6ef591f33f8686842d974dbaa33302'), "%3C%21doctype%20html%3E%3Cp%3Ea%3Cframeset%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%22a%22"],"5ba1d0e97f121810025c1d6447a426c669661637":[async_test('html5lib_tests19.html 5ba1d0e97f121810025c1d6447a426c669661637'), "%3C%21doctype%20html%3E%3Cp%3E%20%3Cframeset%3E%3Cframe%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E%0A%7C%20%20%20%20%20%3Cframe%3E"],"709ec07924db4c9fd66d48eac08575dfdef01d8f":[async_test('html5lib_tests19.html 709ec07924db4c9fd66d48eac08575dfdef01d8f'), "%3C%21doctype%20html%3E%3Cpre%3E%3Cframeset%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cpre%3E"],"f72edb80bc3be091e4b448cd1de8fe851d623e05":[async_test('html5lib_tests19.html f72edb80bc3be091e4b448cd1de8fe851d623e05'), "%3C%21doctype%20html%3E%3Clisting%3E%3Cframeset%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Clisting%3E"],"cb7de0dc7e17c1454ceaa7eb49cb9f9476a1f510":[async_test('html5lib_tests19.html cb7de0dc7e17c1454ceaa7eb49cb9f9476a1f510'), "%3C%21doctype%20html%3E%3Cli%3E%3Cframeset%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cli%3E"],"511bf4bae15c8119042e5e80b5358b70e7da26c1":[async_test('html5lib_tests19.html 511bf4bae15c8119042e5e80b5358b70e7da26c1'), "%3C%21doctype%20html%3E%3Cdd%3E%3Cframeset%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdd%3E"],"c51ee24ef9d92206318cc5bbba784630cd10e531":[async_test('html5lib_tests19.html c51ee24ef9d92206318cc5bbba784630cd10e531'), "%3C%21doctype%20html%3E%3Cdt%3E%3Cframeset%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdt%3E"],"819d39ae49fd04f0dfce90ac8ed2f8e423bb9329":[async_test('html5lib_tests19.html 819d39ae49fd04f0dfce90ac8ed2f8e423bb9329'), "%3C%21doctype%20html%3E%3Cbutton%3E%3Cframeset%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cbutton%3E"],"ef6bdf5b3ba9d41d6c1c08ede60c2e7fb21c6d71":[async_test('html5lib_tests19.html ef6bdf5b3ba9d41d6c1c08ede60c2e7fb21c6d71'), "%3C%21doctype%20html%3E%3Capplet%3E%3Cframeset%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Capplet%3E"],"6bf9c038255c31f20d8fbeaebdf3609eb3c9ed75":[async_test('html5lib_tests19.html 6bf9c038255c31f20d8fbeaebdf3609eb3c9ed75'), "%3C%21doctype%20html%3E%3Cmarquee%3E%3Cframeset%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cmarquee%3E"],"08983ab2a54f61b09a1df134cdaf51d321f3ef32":[async_test('html5lib_tests19.html 08983ab2a54f61b09a1df134cdaf51d321f3ef32'), "%3C%21doctype%20html%3E%3Cobject%3E%3Cframeset%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cobject%3E"],"2ef94ed028fa71b70540cf41f0884ae0c1cf8077":[async_test('html5lib_tests19.html 2ef94ed028fa71b70540cf41f0884ae0c1cf8077'), "%3C%21doctype%20html%3E%3Ctable%3E%3Cframeset%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E"],"5c9ed202789fb29566e0d146d155e0d672e8a037":[async_test('html5lib_tests19.html 5c9ed202789fb29566e0d146d155e0d672e8a037'), "%3C%21doctype%20html%3E%3Carea%3E%3Cframeset%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Carea%3E"],"7d766253cbf500df03506dfb7f2cbdd0f0f533c6":[async_test('html5lib_tests19.html 7d766253cbf500df03506dfb7f2cbdd0f0f533c6'), "%3C%21doctype%20html%3E%3Cbasefont%3E%3Cframeset%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cbasefont%3E%0A%7C%20%20%20%3Cframeset%3E"],"4d5629c61993ef0bb83fcbd80ccc6ead7cd776ee":[async_test('html5lib_tests19.html 4d5629c61993ef0bb83fcbd80ccc6ead7cd776ee'), "%3C%21doctype%20html%3E%3Cbgsound%3E%3Cframeset%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cbgsound%3E%0A%7C%20%20%20%3Cframeset%3E"],"6320d9fa3295984d3da7e4831ced75dfb97d4848":[async_test('html5lib_tests19.html 6320d9fa3295984d3da7e4831ced75dfb97d4848'), "%3C%21doctype%20html%3E%3Cbr%3E%3Cframeset%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cbr%3E"],"bdb97868e951b7a719fa8b1afc79650bf9aae7a5":[async_test('html5lib_tests19.html bdb97868e951b7a719fa8b1afc79650bf9aae7a5'), "%3C%21doctype%20html%3E%3Cembed%3E%3Cframeset%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cembed%3E"],"81868cde252694a252b6b0c8d366850f8a54736c":[async_test('html5lib_tests19.html 81868cde252694a252b6b0c8d366850f8a54736c'), "%3C%21doctype%20html%3E%3Cimg%3E%3Cframeset%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cimg%3E"],"20651db48147f8dda189c563f5fa60bfd0913ac0":[async_test('html5lib_tests19.html 20651db48147f8dda189c563f5fa60bfd0913ac0'), "%3C%21doctype%20html%3E%3Cinput%3E%3Cframeset%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cinput%3E"],"d098e8a39897cd8453fc18399622e413872b054c":[async_test('html5lib_tests19.html d098e8a39897cd8453fc18399622e413872b054c'), "%3C%21doctype%20html%3E%3Ckeygen%3E%3Cframeset%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ckeygen%3E"],"0beb7903dcc0dbee206d8b6e729963a0461eedb3":[async_test('html5lib_tests19.html 0beb7903dcc0dbee206d8b6e729963a0461eedb3'), "%3C%21doctype%20html%3E%3Cwbr%3E%3Cframeset%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cwbr%3E"],"78e5cdb86bf2aecef4697d70d50499b50de5c25b":[async_test('html5lib_tests19.html 78e5cdb86bf2aecef4697d70d50499b50de5c25b'), "%3C%21doctype%20html%3E%3Chr%3E%3Cframeset%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Chr%3E"],"cfb1d482e5971a6915c90434f580721b772fc09b":[async_test('html5lib_tests19.html cfb1d482e5971a6915c90434f580721b772fc09b'), "%3C%21doctype%20html%3E%3Ctextarea%3E%3C/textarea%3E%3Cframeset%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctextarea%3E"],"99d8bff8bbcca1c7faa7b6e10b9ff305b9f99594":[async_test('html5lib_tests19.html 99d8bff8bbcca1c7faa7b6e10b9ff305b9f99594'), "%3C%21doctype%20html%3E%3Cxmp%3E%3C/xmp%3E%3Cframeset%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cxmp%3E"],"daaa43db05ffe9bdd8d734a4389fb3c459caddf1":[async_test('html5lib_tests19.html daaa43db05ffe9bdd8d734a4389fb3c459caddf1'), "%3C%21doctype%20html%3E%3Ciframe%3E%3C/iframe%3E%3Cframeset%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ciframe%3E"],"b3d421e57a4135731309152d7f47e26a4866f3d6":[async_test('html5lib_tests19.html b3d421e57a4135731309152d7f47e26a4866f3d6'), "%3C%21doctype%20html%3E%3Cselect%3E%3C/select%3E%3Cframeset%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cselect%3E"],"aa5eac4b7a0bafdafcd52cb190a8e181ff74144c":[async_test('html5lib_tests19.html aa5eac4b7a0bafdafcd52cb190a8e181ff74144c'), "%3C%21doctype%20html%3E%3Csvg%3E%3C/svg%3E%3Cframeset%3E%3Cframe%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E%0A%7C%20%20%20%20%20%3Cframe%3E"],"91d56a57f4c8af2bce03e9974df0a80f62686fb4":[async_test('html5lib_tests19.html 91d56a57f4c8af2bce03e9974df0a80f62686fb4'), "%3C%21doctype%20html%3E%3Cmath%3E%3C/math%3E%3Cframeset%3E%3Cframe%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E%0A%7C%20%20%20%20%20%3Cframe%3E"],"9cbad5cad719a63d2eb7721de6737a346ad42da1":[async_test('html5lib_tests19.html 9cbad5cad719a63d2eb7721de6737a346ad42da1'), "%3C%21doctype%20html%3E%3Csvg%3E%3CforeignObject%3E%3Cdiv%3E%20%3Cframeset%3E%3Cframe%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E%0A%7C%20%20%20%20%20%3Cframe%3E"],"057c2e91a7e6053d39436efe2bc29049f6fa8e82":[async_test('html5lib_tests19.html 057c2e91a7e6053d39436efe2bc29049f6fa8e82'), "%3C%21doctype%20html%3E%3Csvg%3Ea%3C/svg%3E%3Cframeset%3E%3Cframe%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%22a%22"],"61e6517e5e82cdaed41ab3e1f6fa927731aa0c82":[async_test('html5lib_tests19.html 61e6517e5e82cdaed41ab3e1f6fa927731aa0c82'), "%3C%21doctype%20html%3E%3Csvg%3E%20%3C/svg%3E%3Cframeset%3E%3Cframe%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E%0A%7C%20%20%20%20%20%3Cframe%3E"],"9274ab4f08baa52c5d7016f6062f186730cfbe6c":[async_test('html5lib_tests19.html 9274ab4f08baa52c5d7016f6062f186730cfbe6c'), "%3Chtml%3Eaaa%3Cframeset%3E%3C/frameset%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22aaa%22"],"fc2fa41ebadc21653b38d70c1097bd4ac5979948":[async_test('html5lib_tests19.html fc2fa41ebadc21653b38d70c1097bd4ac5979948'), "%3Chtml%3E%20a%20%3Cframeset%3E%3C/frameset%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22a%20%22"],"473303e65f26fafacbaf01c11b04d745ff293963":[async_test('html5lib_tests19.html 473303e65f26fafacbaf01c11b04d745ff293963'), "%3C%21doctype%20html%3E%3Cdiv%3E%3Cframeset%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E"],"7854276e1637619f693cd87f64542c08c35d40bd":[async_test('html5lib_tests19.html 7854276e1637619f693cd87f64542c08c35d40bd'), "%3C%21doctype%20html%3E%3Cdiv%3E%3Cbody%3E%3Cframeset%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E"],"a2d262d392e8d10645ce559edf401df3f3872eb3":[async_test('html5lib_tests19.html a2d262d392e8d10645ce559edf401df3f3872eb3'), "%3C%21doctype%20html%3E%3Cp%3E%3Cmath%3E%3C/p%3Ea", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%22a%22"],"d5e50987bf495e285e279ff8670255d9b1314f5d":[async_test('html5lib_tests19.html d5e50987bf495e285e279ff8670255d9b1314f5d'), "%3C%21doctype%20html%3E%3Cp%3E%3Cmath%3E%3Cmn%3E%3Cspan%3E%3C/p%3Ea", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cmath%20mn%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cspan%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%22a%22"],"be54d7506e54a127a05b115a8659a5b52fa57f6c":[async_test('html5lib_tests19.html be54d7506e54a127a05b115a8659a5b52fa57f6c'), "%3C%21doctype%20html%3E%3Cmath%3E%3C/html%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cmath%20math%3E"],"af389f1a8ef93c457560fd2445df80a6789dab0d":[async_test('html5lib_tests19.html af389f1a8ef93c457560fd2445df80a6789dab0d'), "%3C%21doctype%20html%3E%3Cmeta%20charset%3D%22ascii%22%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cmeta%3E%0A%7C%20%20%20%20%20%20%20charset%3D%22ascii%22%0A%7C%20%20%20%3Cbody%3E"],"601dfa9502942deb8bf46a91c64f10f649bc1875":[async_test('html5lib_tests19.html 601dfa9502942deb8bf46a91c64f10f649bc1875'), "%3C%21doctype%20html%3E%3Cmeta%20http-equiv%3D%22content-type%22%20content%3D%22text/html%3Bcharset%3Dascii%22%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cmeta%3E%0A%7C%20%20%20%20%20%20%20content%3D%22text/html%3Bcharset%3Dascii%22%0A%7C%20%20%20%20%20%20%20http-equiv%3D%22content-type%22%0A%7C%20%20%20%3Cbody%3E"],"4b01442faf29563d3b736d235515f77c20c81863":[async_test('html5lib_tests19.html 4b01442faf29563d3b736d235515f77c20c81863'), "%3C%21doctype%20html%3E%3Chead%3E%3C%21--aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa--%3E%3Cmeta%20charset%3D%22utf8%22%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3C%21--%20aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa%20--%3E%0A%7C%20%20%20%20%20%3Cmeta%3E%0A%7C%20%20%20%20%20%20%20charset%3D%22utf8%22%0A%7C%20%20%20%3Cbody%3E"],"696a2b60681b0b6758f165a67e29a84b0f75a153":[async_test('html5lib_tests19.html 696a2b60681b0b6758f165a67e29a84b0f75a153'), "%3C%21doctype%20html%3E%3Chtml%20a%3Db%3E%3Chead%3E%3C/head%3E%3Chtml%20c%3Dd%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20a%3D%22b%22%0A%7C%20%20%20c%3D%22d%22%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"7a48b98cbae5cd7cbbb90f138c0d12da6c4448b3":[async_test('html5lib_tests19.html 7a48b98cbae5cd7cbbb90f138c0d12da6c4448b3'), "%3C%21doctype%20html%3E%3Cimage/%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cimg%3E"],"d7693a0f2be68925250d3aa2cf295b1d1a60bf94":[async_test('html5lib_tests19.html d7693a0f2be68925250d3aa2cf295b1d1a60bf94'), "%3C%21doctype%20html%3Ea%3Ci%3Eb%3Ctable%3Ec%3Cb%3Ed%3C/i%3Ee%3C/b%3Ef", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22a%22%0A%7C%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%22bc%22%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%22de%22%0A%7C%20%20%20%20%20%20%20%22f%22%0A%7C%20%20%20%20%20%20%20%3Ctable%3E"],"9e4d91f02184de1b1e5d927144bb06d3bc78bb09":[async_test('html5lib_tests19.html 9e4d91f02184de1b1e5d927144bb06d3bc78bb09'), "%3C%21doctype%20html%3E%3Ctable%3E%3Ci%3Ea%3Cb%3Eb%3Cdiv%3Ec%3Ca%3Ed%3C/i%3Ee%3C/b%3Ef", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%22a%22%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%22b%22%0A%7C%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22c%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%22d%22%0A%7C%20%20%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22e%22%0A%7C%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%22f%22%0A%7C%20%20%20%20%20%3Ctable%3E"],"9655591702381a52fe0eb3224e63e2d8bfd735e8":[async_test('html5lib_tests19.html 9655591702381a52fe0eb3224e63e2d8bfd735e8'), "%3C%21doctype%20html%3E%3Ci%3Ea%3Cb%3Eb%3Cdiv%3Ec%3Ca%3Ed%3C/i%3Ee%3C/b%3Ef", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%22a%22%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%22b%22%0A%7C%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22c%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%22d%22%0A%7C%20%20%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22e%22%0A%7C%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%22f%22"],"fe9aa1c8ec32796e26f3e58022f0e42dc365b5c7":[async_test('html5lib_tests19.html fe9aa1c8ec32796e26f3e58022f0e42dc365b5c7'), "%3C%21doctype%20html%3E%3Ctable%3E%3Ci%3Ea%3Cb%3Eb%3Cdiv%3Ec%3C/i%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%22a%22%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%22b%22%0A%7C%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22c%22%0A%7C%20%20%20%20%20%3Ctable%3E"],"4c9ec04359c3e94d4a56d6932d289f0c4246d1ef":[async_test('html5lib_tests19.html 4c9ec04359c3e94d4a56d6932d289f0c4246d1ef'), "%3C%21doctype%20html%3E%3Ctable%3E%3Ci%3Ea%3Cdiv%3Eb%3Ctr%3Ec%3Cb%3Ed%3C/i%3Ee", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%22a%22%0A%7C%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%22b%22%0A%7C%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%22c%22%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%22d%22%0A%7C%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%22e%22%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E"],"3fcc2f15951b3c3375c3e359cf7888c71187994a":[async_test('html5lib_tests19.html 3fcc2f15951b3c3375c3e359cf7888c71187994a'), "%3C%21doctype%20html%3E%3Ctable%3E%3Ctd%3E%3Ctable%3E%3Ci%3Ea%3Cdiv%3Eb%3Cb%3Ec%3C/i%3Ed", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22a%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22b%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22c%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22d%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctable%3E"],"a94b35c317763de75150df6b436c7c153aeb8c51":[async_test('html5lib_tests19.html a94b35c317763de75150df6b436c7c153aeb8c51'), "%3C%21doctype%20html%3E%3Cbody%3E%3Cbgsound%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cbgsound%3E"],"173b990198dd8fd9534d7808817c19440b75d406":[async_test('html5lib_tests19.html 173b990198dd8fd9534d7808817c19440b75d406'), "%3C%21doctype%20html%3E%3Cbody%3E%3Cbasefont%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cbasefont%3E"],"48ed5945491d4ad0c00acfd01c2060a459436d34":[async_test('html5lib_tests19.html 48ed5945491d4ad0c00acfd01c2060a459436d34'), "%3C%21doctype%20html%3E%3Ca%3E%3Cb%3E%3C/a%3E%3Cbasefont%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%3Cbasefont%3E"],"392b8d4d25351467da961e4ab011a1d4e970b97a":[async_test('html5lib_tests19.html 392b8d4d25351467da961e4ab011a1d4e970b97a'), "%3C%21doctype%20html%3E%3Ca%3E%3Cb%3E%3C/a%3E%3Cbgsound%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%3Cbgsound%3E"],"bd14373173ea3617610fc8154237f59f1a810733":[async_test('html5lib_tests19.html bd14373173ea3617610fc8154237f59f1a810733'), "%3C%21doctype%20html%3E%3Cfigcaption%3E%3Carticle%3E%3C/figcaption%3Ea", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cfigcaption%3E%0A%7C%20%20%20%20%20%20%20%3Carticle%3E%0A%7C%20%20%20%20%20%22a%22"],"db3c4ddb389a2b8f42ca6b3719007d4de2eccc41":[async_test('html5lib_tests19.html db3c4ddb389a2b8f42ca6b3719007d4de2eccc41'), "%3C%21doctype%20html%3E%3Csummary%3E%3Carticle%3E%3C/summary%3Ea", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csummary%3E%0A%7C%20%20%20%20%20%20%20%3Carticle%3E%0A%7C%20%20%20%20%20%22a%22"],"c1741a62627b2e5bb1cfa2b2cd667f3f9f76157e":[async_test('html5lib_tests19.html c1741a62627b2e5bb1cfa2b2cd667f3f9f76157e'), "%3C%21doctype%20html%3E%3Cp%3E%3Ca%3E%3Cplaintext%3Eb", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%3Cplaintext%3E%0A%7C%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%22b%22"],"0d6cf626790e9f06e30ceb6baf3004663b0247e7":[async_test('html5lib_tests19.html 0d6cf626790e9f06e30ceb6baf3004663b0247e7'), "%3C%21DOCTYPE%20html%3E%3Cdiv%3Ea%3Ca%3E%3C/div%3Eb%3Cp%3Ec%3C/p%3Ed", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%22a%22%0A%7C%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%22b%22%0A%7C%20%20%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%20%20%22c%22%0A%7C%20%20%20%20%20%20%20%22d%22"],
+ }
+ init_tests(get_type());
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests2.html b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests2.html
new file mode 100644
index 00000000000..a09d593e271
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests2.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf8">
+ <title>HTML 5 Parser tests html5lib_tests2.html</title>
+ <meta name="timeout" content="long">
+ <meta name="variant" content="?run_type=uri">
+ <meta name="variant" content="?run_type=write">
+ <meta name="variant" content="?run_type=write_single">
+ </head>
+ <body>
+ <h1>html5lib Parser Test</h1>
+ <div id="log"></div>
+ <script src="common.js"></script>
+ <script src="test.js"></script>
+ <script src="template.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ var num_iframes = 8;
+ var order = ['e070301fb578bd639ecbc7ec720fa60222d05826','aaf24dabcb42470e447d241a40def0d136c12b93','b6c1142484570bb90c36e454ee193cca17bb618a','1977644a94de1a04245dfef3f3db69c7ac41aa6f','fb0d7207ed9fbc3fe5d1e0f85ad18c247dfb05a3','d662798ca6dd95a205069658396d0f3d78237233','1ec72d53c4c68f9ca56f037ec53a7dc261886131','2d58ae67534b42e52e34c6b2a275fcb30a878008','14836de42a7fb86b75fef03f08823f90d389b7f3','8ced679aed45a123b97a574f24fba909b65f94dd','932ff3ff2c75f7b28ef562dfa9c7cb208f0712d4','c863d867f843bd66c5303db1634931a36afd3ea9','2221f89de75008a31506b22756a5499bc6bda9bd','7471f6a45872ac6d70f69fc3f4e10b13c7c1ac45','47b9eaef1b5aad0e3963a8d415236fed12702d65','decb4ad6eac317f262b4b87c86b33d2d9d700e75','ffcb1856faa7e09cc892c0f5a4d3353716830784','a259db8ee062d858027148f92811ba0f5796e4b9','bf369032d1e6ebb52ab133e4c4b8c2e872349843','73b97cd984a62703ec54ec4a876ec32aa5fd3b8c','2db9616ed62fc2a26056f3395459869cf556974d','b59aa1c714892618eaccd51696658887fcbd2045','98818e7fda2506603bd208662613edb40297c2d3','e0c43080cf61c0696031bdb097bea4f2a647cfc2','f7753d80a422c40b5fa04d99e52d8ae83369757a','7cbd584aef9508a90c98f80040078149a92ec869','e0f7f130b1e3653dd06f10f3492e4f0bf4cd3cfa','4fb9b13eeb5d8a201884c572764a70477822f2d4','7ec82c93064966931ce76618a0cce4f275aafdaf','a8fb1cffc8683f0c47fdf9963e0d52c627343ff0','8dc47e70b94f2bea514ceaa51153ec1beeeda7ef','571719c0f9e1dae32ef993917b02c57f698be3d9','7f3afa5785d4b7ea37f8bae17226528f2a30e818','37918d1876724d3a8980920cf4cf2cbef2c3ac06','5da4e202a8962cacf567ce864873ddbff73f8217','4ca566310edc49450571677e8ef195883919ec2f','8a559c045c3a880e555d31de4dd3aa0b06930b73','3067a820b0195f9c08b8d0fe1dd7f8d800e10779','e1011849d36ebf9d1577c53d940a75c462dcb1e7','c9938e14b139e9c2af300bacd38f2f3cfca3fe58','0582a2e2c0eb00e0ba60b280187006c5e7de6991','478db7eafb3ac4a6abb8dbe083664c8d3ada35d8','c6abe422542794d7e8196d73283e562c309fe2e3','9fd0577023d0eb3662569333f5f231090439a217','a288ea4fde56fc652f4ec4db0b63af1ddfeac826','0c917166dc089cb23a100af2f07cbf95f164533a','60f3ef7971b3259c3d800da672d886b2db778276','341bdf232d96b774988ee3163c953f2581752335','84570bfd25f23f0f40e31ba0c6a08906a2676b6d','4dbef924230e654860aa288a28f6304a062b3faf','2e8a5d6aa8cb0011b6caa08a44cd8871e4b15b71','06e43760aeadae330ad5ba80c4b93952ba568b29','4e58f3f3c581dec50f939a660fd5b5828396dac4','693974a6cb0defd3e0b2d63b31d420f39c83d262','3e03ddf29af0af9c9ece091251f0c1c5e08a5e41','9a5211623fcdd9fc3ad2ea4addc608d7c2574b90','39f31f0fbfcc91157104d64ca081d4271bc7e838','86d793db69ce071e78a18c85f8345316f09e1790','182036d2ef28f86873aee09b15125c828179c1b4','2a818d5fd74c60ac2bb369fb2355b84edab31777','9f88d21c8b77696f7238064a4ee87931cc16a03f','1d00919bf0b2493dfee7422a24acee9026de5fff','0c48a9e7584ede9d13d606057202883c5cff3eab',];
+ var tests = {
+ "e070301fb578bd639ecbc7ec720fa60222d05826":[async_test('html5lib_tests2.html e070301fb578bd639ecbc7ec720fa60222d05826'), "%3C%21DOCTYPE%20html%3ETest", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22Test%22"],"aaf24dabcb42470e447d241a40def0d136c12b93":[async_test('html5lib_tests2.html aaf24dabcb42470e447d241a40def0d136c12b93'), "%3Ctextarea%3Etest%3C/div%3Etest", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctextarea%3E%0A%7C%20%20%20%20%20%20%20%22test%3C/div%3Etest%22"],"b6c1142484570bb90c36e454ee193cca17bb618a":[async_test('html5lib_tests2.html b6c1142484570bb90c36e454ee193cca17bb618a'), "%3Ctable%3E%3Ctd%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E"],"1977644a94de1a04245dfef3f3db69c7ac41aa6f":[async_test('html5lib_tests2.html 1977644a94de1a04245dfef3f3db69c7ac41aa6f'), "%3Ctable%3E%3Ctd%3Etest%3C/tbody%3E%3C/table%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%22test%22"],"fb0d7207ed9fbc3fe5d1e0f85ad18c247dfb05a3":[async_test('html5lib_tests2.html fb0d7207ed9fbc3fe5d1e0f85ad18c247dfb05a3'), "%3Cframe%3Etest", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22test%22"],"d662798ca6dd95a205069658396d0f3d78237233":[async_test('html5lib_tests2.html d662798ca6dd95a205069658396d0f3d78237233'), "%3C%21DOCTYPE%20html%3E%3Cframeset%3Etest", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E"],"1ec72d53c4c68f9ca56f037ec53a7dc261886131":[async_test('html5lib_tests2.html 1ec72d53c4c68f9ca56f037ec53a7dc261886131'), "%3C%21DOCTYPE%20html%3E%3Cframeset%3E%20te%20st", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E%0A%7C%20%20%20%20%20%22%20%20%22"],"2d58ae67534b42e52e34c6b2a275fcb30a878008":[async_test('html5lib_tests2.html 2d58ae67534b42e52e34c6b2a275fcb30a878008'), "%3C%21DOCTYPE%20html%3E%3Cframeset%3E%3C/frameset%3E%20te%20st", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E%0A%7C%20%20%20%22%20%20%22"],"14836de42a7fb86b75fef03f08823f90d389b7f3":[async_test('html5lib_tests2.html 14836de42a7fb86b75fef03f08823f90d389b7f3'), "%3C%21DOCTYPE%20html%3E%3Cframeset%3E%3C%21DOCTYPE%20html%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E"],"8ced679aed45a123b97a574f24fba909b65f94dd":[async_test('html5lib_tests2.html 8ced679aed45a123b97a574f24fba909b65f94dd'), "%3C%21DOCTYPE%20html%3E%3Cfont%3E%3Cp%3E%3Cb%3Etest%3C/font%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22test%22"],"932ff3ff2c75f7b28ef562dfa9c7cb208f0712d4":[async_test('html5lib_tests2.html 932ff3ff2c75f7b28ef562dfa9c7cb208f0712d4'), "%3C%21DOCTYPE%20html%3E%3Cdt%3E%3Cdiv%3E%3Cdd%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdt%3E%0A%7C%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%3Cdd%3E"],"c863d867f843bd66c5303db1634931a36afd3ea9":[async_test('html5lib_tests2.html c863d867f843bd66c5303db1634931a36afd3ea9'), "%3Cscript%3E%3C/x", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C/x%22%0A%7C%20%20%20%3Cbody%3E"],"2221f89de75008a31506b22756a5499bc6bda9bd":[async_test('html5lib_tests2.html 2221f89de75008a31506b22756a5499bc6bda9bd'), "%3Ctable%3E%3Cplaintext%3E%3Ctd%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cplaintext%3E%0A%7C%20%20%20%20%20%20%20%22%3Ctd%3E%22%0A%7C%20%20%20%20%20%3Ctable%3E"],"7471f6a45872ac6d70f69fc3f4e10b13c7c1ac45":[async_test('html5lib_tests2.html 7471f6a45872ac6d70f69fc3f4e10b13c7c1ac45'), "%3Cplaintext%3E%3C/plaintext%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cplaintext%3E%0A%7C%20%20%20%20%20%20%20%22%3C/plaintext%3E%22"],"47b9eaef1b5aad0e3963a8d415236fed12702d65":[async_test('html5lib_tests2.html 47b9eaef1b5aad0e3963a8d415236fed12702d65'), "%3C%21DOCTYPE%20html%3E%3Ctable%3E%3Ctr%3ETEST", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22TEST%22%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E"],"decb4ad6eac317f262b4b87c86b33d2d9d700e75":[async_test('html5lib_tests2.html decb4ad6eac317f262b4b87c86b33d2d9d700e75'), "%3C%21DOCTYPE%20html%3E%3Cbody%20t1%3D1%3E%3Cbody%20t2%3D2%3E%3Cbody%20t3%3D3%20t4%3D4%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20t1%3D%221%22%0A%7C%20%20%20%20%20t2%3D%222%22%0A%7C%20%20%20%20%20t3%3D%223%22%0A%7C%20%20%20%20%20t4%3D%224%22"],"ffcb1856faa7e09cc892c0f5a4d3353716830784":[async_test('html5lib_tests2.html ffcb1856faa7e09cc892c0f5a4d3353716830784'), "%3C/b%20test", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"a259db8ee062d858027148f92811ba0f5796e4b9":[async_test('html5lib_tests2.html a259db8ee062d858027148f92811ba0f5796e4b9'), "%3C%21DOCTYPE%20html%3E%3C/b%20test%3Cb%20%26%3D%26amp%3EX", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22X%22"],"bf369032d1e6ebb52ab133e4c4b8c2e872349843":[async_test('html5lib_tests2.html bf369032d1e6ebb52ab133e4c4b8c2e872349843'), "%3C%21doctypehtml%3E%3CscrIPt%20type%3Dtext/x-foobar%3Bbaz%3EX%3C/SCRipt", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20type%3D%22text/x-foobar%3Bbaz%22%0A%7C%20%20%20%20%20%20%20%22X%3C/SCRipt%22%0A%7C%20%20%20%3Cbody%3E"],"73b97cd984a62703ec54ec4a876ec32aa5fd3b8c":[async_test('html5lib_tests2.html 73b97cd984a62703ec54ec4a876ec32aa5fd3b8c'), "%26", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22%26%22"],"2db9616ed62fc2a26056f3395459869cf556974d":[async_test('html5lib_tests2.html 2db9616ed62fc2a26056f3395459869cf556974d'), "%26%23", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22%26%23%22"],"b59aa1c714892618eaccd51696658887fcbd2045":[async_test('html5lib_tests2.html b59aa1c714892618eaccd51696658887fcbd2045'), "%26%23X", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22%26%23X%22"],"98818e7fda2506603bd208662613edb40297c2d3":[async_test('html5lib_tests2.html 98818e7fda2506603bd208662613edb40297c2d3'), "%26%23x", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22%26%23x%22"],"e0c43080cf61c0696031bdb097bea4f2a647cfc2":[async_test('html5lib_tests2.html e0c43080cf61c0696031bdb097bea4f2a647cfc2'), "%26%2345", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22-%22"],"f7753d80a422c40b5fa04d99e52d8ae83369757a":[async_test('html5lib_tests2.html f7753d80a422c40b5fa04d99e52d8ae83369757a'), "%26x-test", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22%26x-test%22"],"7cbd584aef9508a90c98f80040078149a92ec869":[async_test('html5lib_tests2.html 7cbd584aef9508a90c98f80040078149a92ec869'), "%3C%21doctypehtml%3E%3Cp%3E%3Cli%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%3Cli%3E"],"e0f7f130b1e3653dd06f10f3492e4f0bf4cd3cfa":[async_test('html5lib_tests2.html e0f7f130b1e3653dd06f10f3492e4f0bf4cd3cfa'), "%3C%21doctypehtml%3E%3Cp%3E%3Cdt%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%3Cdt%3E"],"4fb9b13eeb5d8a201884c572764a70477822f2d4":[async_test('html5lib_tests2.html 4fb9b13eeb5d8a201884c572764a70477822f2d4'), "%3C%21doctypehtml%3E%3Cp%3E%3Cdd%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%3Cdd%3E"],"7ec82c93064966931ce76618a0cce4f275aafdaf":[async_test('html5lib_tests2.html 7ec82c93064966931ce76618a0cce4f275aafdaf'), "%3C%21doctypehtml%3E%3Cp%3E%3Cform%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%3Cform%3E"],"a8fb1cffc8683f0c47fdf9963e0d52c627343ff0":[async_test('html5lib_tests2.html a8fb1cffc8683f0c47fdf9963e0d52c627343ff0'), "%3C%21DOCTYPE%20html%3E%3Cp%3E%3C/P%3EX", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%22X%22"],"8dc47e70b94f2bea514ceaa51153ec1beeeda7ef":[async_test('html5lib_tests2.html 8dc47e70b94f2bea514ceaa51153ec1beeeda7ef'), "%26AMP", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22%26%22"],"571719c0f9e1dae32ef993917b02c57f698be3d9":[async_test('html5lib_tests2.html 571719c0f9e1dae32ef993917b02c57f698be3d9'), "%26AMp%3B", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22%26AMp%3B%22"],"7f3afa5785d4b7ea37f8bae17226528f2a30e818":[async_test('html5lib_tests2.html 7f3afa5785d4b7ea37f8bae17226528f2a30e818'), "%3C%21DOCTYPE%20html%3E%3Chtml%3E%3Chead%3E%3C/head%3E%3Cbody%3E%3CthisISasillyTESTelementNameToMakeSureCrazyTagNamesArePARSEDcorrectLY%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cthisisasillytestelementnametomakesurecrazytagnamesareparsedcorrectly%3E"],"37918d1876724d3a8980920cf4cf2cbef2c3ac06":[async_test('html5lib_tests2.html 37918d1876724d3a8980920cf4cf2cbef2c3ac06'), "%3C%21DOCTYPE%20html%3EX%3C/body%3EX", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22XX%22"],"5da4e202a8962cacf567ce864873ddbff73f8217":[async_test('html5lib_tests2.html 5da4e202a8962cacf567ce864873ddbff73f8217'), "%3C%21DOCTYPE%20html%3E%3C%21--%20X", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3C%21--%20%20X%20--%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"4ca566310edc49450571677e8ef195883919ec2f":[async_test('html5lib_tests2.html 4ca566310edc49450571677e8ef195883919ec2f'), "%3C%21DOCTYPE%20html%3E%3Ctable%3E%3Ccaption%3Etest%20TEST%3C/caption%3E%3Ctd%3Etest", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ccaption%3E%0A%7C%20%20%20%20%20%20%20%20%20%22test%20TEST%22%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%22test%22"],"8a559c045c3a880e555d31de4dd3aa0b06930b73":[async_test('html5lib_tests2.html 8a559c045c3a880e555d31de4dd3aa0b06930b73'), "%3C%21DOCTYPE%20html%3E%3Cselect%3E%3Coption%3E%3Coptgroup%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cselect%3E%0A%7C%20%20%20%20%20%20%20%3Coption%3E%0A%7C%20%20%20%20%20%20%20%3Coptgroup%3E"],"3067a820b0195f9c08b8d0fe1dd7f8d800e10779":[async_test('html5lib_tests2.html 3067a820b0195f9c08b8d0fe1dd7f8d800e10779'), "%3C%21DOCTYPE%20html%3E%3Cselect%3E%3Coptgroup%3E%3Coption%3E%3C/optgroup%3E%3Coption%3E%3Cselect%3E%3Coption%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cselect%3E%0A%7C%20%20%20%20%20%20%20%3Coptgroup%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Coption%3E%0A%7C%20%20%20%20%20%20%20%3Coption%3E%0A%7C%20%20%20%20%20%3Coption%3E"],"e1011849d36ebf9d1577c53d940a75c462dcb1e7":[async_test('html5lib_tests2.html e1011849d36ebf9d1577c53d940a75c462dcb1e7'), "%3C%21DOCTYPE%20html%3E%3Cselect%3E%3Coptgroup%3E%3Coption%3E%3Coptgroup%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cselect%3E%0A%7C%20%20%20%20%20%20%20%3Coptgroup%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Coption%3E%0A%7C%20%20%20%20%20%20%20%3Coptgroup%3E"],"c9938e14b139e9c2af300bacd38f2f3cfca3fe58":[async_test('html5lib_tests2.html c9938e14b139e9c2af300bacd38f2f3cfca3fe58'), "%3C%21DOCTYPE%20html%3E%3Cdatalist%3E%3Coption%3Efoo%3C/datalist%3Ebar", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdatalist%3E%0A%7C%20%20%20%20%20%20%20%3Coption%3E%0A%7C%20%20%20%20%20%20%20%20%20%22foo%22%0A%7C%20%20%20%20%20%22bar%22"],"0582a2e2c0eb00e0ba60b280187006c5e7de6991":[async_test('html5lib_tests2.html 0582a2e2c0eb00e0ba60b280187006c5e7de6991'), "%3C%21DOCTYPE%20html%3E%3Cfont%3E%3Cinput%3E%3Cinput%3E%3C/font%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%3Cinput%3E%0A%7C%20%20%20%20%20%20%20%3Cinput%3E"],"478db7eafb3ac4a6abb8dbe083664c8d3ada35d8":[async_test('html5lib_tests2.html 478db7eafb3ac4a6abb8dbe083664c8d3ada35d8'), "%3C%21DOCTYPE%20html%3E%3C%21--%20XXX%20-%20XXX%20--%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3C%21--%20%20XXX%20-%20XXX%20%20--%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"c6abe422542794d7e8196d73283e562c309fe2e3":[async_test('html5lib_tests2.html c6abe422542794d7e8196d73283e562c309fe2e3'), "%3C%21DOCTYPE%20html%3E%3C%21--%20XXX%20-%20XXX", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3C%21--%20%20XXX%20-%20XXX%20--%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"9fd0577023d0eb3662569333f5f231090439a217":[async_test('html5lib_tests2.html 9fd0577023d0eb3662569333f5f231090439a217'), "%3C%21DOCTYPE%20html%3E%3C%21--%20XXX%20-%20XXX%20-%20XXX%20--%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3C%21--%20%20XXX%20-%20XXX%20-%20XXX%20%20--%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"a288ea4fde56fc652f4ec4db0b63af1ddfeac826":[async_test('html5lib_tests2.html a288ea4fde56fc652f4ec4db0b63af1ddfeac826'), "%3Cisindex%20test%3Dx%20name%3Dx%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cform%3E%0A%7C%20%20%20%20%20%20%20%3Chr%3E%0A%7C%20%20%20%20%20%20%20%3Clabel%3E%0A%7C%20%20%20%20%20%20%20%20%20%22This%20is%20a%20searchable%20index.%20Enter%20search%20keywords%3A%20%22%0A%7C%20%20%20%20%20%20%20%20%20%3Cinput%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20name%3D%22isindex%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20test%3D%22x%22%0A%7C%20%20%20%20%20%20%20%3Chr%3E"],"0c917166dc089cb23a100af2f07cbf95f164533a":[async_test('html5lib_tests2.html 0c917166dc089cb23a100af2f07cbf95f164533a'), "test%0Atest", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22test%0Atest%22"],"60f3ef7971b3259c3d800da672d886b2db778276":[async_test('html5lib_tests2.html 60f3ef7971b3259c3d800da672d886b2db778276'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Ctitle%3Etest%3C/body%3E%3C/title%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctitle%3E%0A%7C%20%20%20%20%20%20%20%22test%3C/body%3E%22"],"341bdf232d96b774988ee3163c953f2581752335":[async_test('html5lib_tests2.html 341bdf232d96b774988ee3163c953f2581752335'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Ctitle%3EX%3C/title%3E%3Cmeta%20name%3Dz%3E%3Clink%20rel%3Dfoo%3E%3Cstyle%3E%0Ax%20%7B%20content%3A%22%3C/style%22%20%7D%20%3C/style%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctitle%3E%0A%7C%20%20%20%20%20%20%20%22X%22%0A%7C%20%20%20%20%20%3Cmeta%3E%0A%7C%20%20%20%20%20%20%20name%3D%22z%22%0A%7C%20%20%20%20%20%3Clink%3E%0A%7C%20%20%20%20%20%20%20rel%3D%22foo%22%0A%7C%20%20%20%20%20%3Cstyle%3E%0A%7C%20%20%20%20%20%20%20%22%0Ax%20%7B%20content%3A%22%3C/style%22%20%7D%20%22"],"84570bfd25f23f0f40e31ba0c6a08906a2676b6d":[async_test('html5lib_tests2.html 84570bfd25f23f0f40e31ba0c6a08906a2676b6d'), "%3C%21DOCTYPE%20html%3E%3Cselect%3E%3Coptgroup%3E%3C/optgroup%3E%3C/select%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cselect%3E%0A%7C%20%20%20%20%20%20%20%3Coptgroup%3E"],"4dbef924230e654860aa288a28f6304a062b3faf":[async_test('html5lib_tests2.html 4dbef924230e654860aa288a28f6304a062b3faf'), "%20%0A%20", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"2e8a5d6aa8cb0011b6caa08a44cd8871e4b15b71":[async_test('html5lib_tests2.html 2e8a5d6aa8cb0011b6caa08a44cd8871e4b15b71'), "%3C%21DOCTYPE%20html%3E%20%20%3Chtml%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"06e43760aeadae330ad5ba80c4b93952ba568b29":[async_test('html5lib_tests2.html 06e43760aeadae330ad5ba80c4b93952ba568b29'), "%3C%21DOCTYPE%20html%3E%3Cscript%3E%0A%3C/script%3E%20%20%3Ctitle%3Ex%3C/title%3E%20%20%3C/head%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%0A%22%0A%7C%20%20%20%20%20%22%20%20%22%0A%7C%20%20%20%20%20%3Ctitle%3E%0A%7C%20%20%20%20%20%20%20%22x%22%0A%7C%20%20%20%20%20%22%20%20%22%0A%7C%20%20%20%3Cbody%3E"],"4e58f3f3c581dec50f939a660fd5b5828396dac4":[async_test('html5lib_tests2.html 4e58f3f3c581dec50f939a660fd5b5828396dac4'), "%3C%21DOCTYPE%20html%3E%3Chtml%3E%3Cbody%3E%3Chtml%20id%3Dx%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20id%3D%22x%22%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"693974a6cb0defd3e0b2d63b31d420f39c83d262":[async_test('html5lib_tests2.html 693974a6cb0defd3e0b2d63b31d420f39c83d262'), "%3C%21DOCTYPE%20html%3EX%3C/body%3E%3Chtml%20id%3D%22x%22%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20id%3D%22x%22%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22X%22"],"3e03ddf29af0af9c9ece091251f0c1c5e08a5e41":[async_test('html5lib_tests2.html 3e03ddf29af0af9c9ece091251f0c1c5e08a5e41'), "%3C%21DOCTYPE%20html%3E%3Chead%3E%3Chtml%20id%3Dx%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20id%3D%22x%22%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"9a5211623fcdd9fc3ad2ea4addc608d7c2574b90":[async_test('html5lib_tests2.html 9a5211623fcdd9fc3ad2ea4addc608d7c2574b90'), "%3C%21DOCTYPE%20html%3EX%3C/html%3EX", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22XX%22"],"39f31f0fbfcc91157104d64ca081d4271bc7e838":[async_test('html5lib_tests2.html 39f31f0fbfcc91157104d64ca081d4271bc7e838'), "%3C%21DOCTYPE%20html%3EX%3C/html%3E%20", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22X%20%22"],"86d793db69ce071e78a18c85f8345316f09e1790":[async_test('html5lib_tests2.html 86d793db69ce071e78a18c85f8345316f09e1790'), "%3C%21DOCTYPE%20html%3EX%3C/html%3E%3Cp%3EX", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22X%22%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%22X%22"],"182036d2ef28f86873aee09b15125c828179c1b4":[async_test('html5lib_tests2.html 182036d2ef28f86873aee09b15125c828179c1b4'), "%3C%21DOCTYPE%20html%3EX%3Cp/x/y/z%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22X%22%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20x%3D%22%22%0A%7C%20%20%20%20%20%20%20y%3D%22%22%0A%7C%20%20%20%20%20%20%20z%3D%22%22"],"2a818d5fd74c60ac2bb369fb2355b84edab31777":[async_test('html5lib_tests2.html 2a818d5fd74c60ac2bb369fb2355b84edab31777'), "%3C%21DOCTYPE%20html%3E%3C%21--x--", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3C%21--%20x%20--%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"9f88d21c8b77696f7238064a4ee87931cc16a03f":[async_test('html5lib_tests2.html 9f88d21c8b77696f7238064a4ee87931cc16a03f'), "%3C%21DOCTYPE%20html%3E%3Ctable%3E%3Ctr%3E%3Ctd%3E%3C/p%3E%3C/table%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cp%3E"],"1d00919bf0b2493dfee7422a24acee9026de5fff":[async_test('html5lib_tests2.html 1d00919bf0b2493dfee7422a24acee9026de5fff'), "%3C%21DOCTYPE%20%3C%21DOCTYPE%20HTML%3E%3E%3C%21--%3C%21--x--%3E--%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20%3C%21doctype%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22%3E%22%0A%7C%20%20%20%20%20%3C%21--%20%3C%21--x%20--%3E%0A%7C%20%20%20%20%20%22--%3E%22"],"0c48a9e7584ede9d13d606057202883c5cff3eab":[async_test('html5lib_tests2.html 0c48a9e7584ede9d13d606057202883c5cff3eab'), "%3C%21doctype%20html%3E%3Cdiv%3E%3Cform%3E%3C/form%3E%3Cdiv%3E%3C/div%3E%3C/div%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%3Cform%3E%0A%7C%20%20%20%20%20%20%20%3Cdiv%3E"],
+ }
+ init_tests(get_type());
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests20.html b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests20.html
new file mode 100644
index 00000000000..19c904fc5ab
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests20.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf8">
+ <title>HTML 5 Parser tests html5lib_tests20.html</title>
+ <meta name="timeout" content="long">
+ <meta name="variant" content="?run_type=uri">
+ <meta name="variant" content="?run_type=write">
+ <meta name="variant" content="?run_type=write_single">
+ </head>
+ <body>
+ <h1>html5lib Parser Test</h1>
+ <div id="log"></div>
+ <script src="common.js"></script>
+ <script src="test.js"></script>
+ <script src="template.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ var num_iframes = 8;
+ var order = ['cbb5f28bedf4361156ef3c9c37e314c6479be137','e108a4952601b4664098344189c875934ea2f7ab','8ecd0d9e2580f78ff920821bd334bd8d04d165e5','ff10749b8b1aca1fba5d07ba86f49612be43caf9','323a6d9f8d2f74e7e5b88599a87dc5673fb7a0b4','bb36fb89d118b55c66f17b24ffff0ca09ccc939b','3fed75e1a7f46a6e2a74a078bfd955e7de05de4f','8cb9d8f92ba130618646d6fd1f307ca73f4e4add','2b9e6cb75876b4a33b77ae4b1bd3ef5e73c4a40e','f95c6bf3f935fad9fc354f4cf6e0161d6ebfb08a','0b07b135bf8399742cc9e6f3d14b2ea32e3354d3','076d3588e85ce9566d9575d1564e72e8480fadc8','dfad8fc515d74c19bad1ab72e7a03d59a11c7778','7ff774f225899091d6d64e5512ada13ce32dd72a','2fd8cab5e3cc4635be76e2d430ad6fe6e79b8167','c7399a2e531694b47b436bd153823f60bba9071e','bc4092e0e1aaa4b97464005963345b4b38e1f2a1','d85e49fc5be07a699f3930464996d7ddb6a8e8bd','09cf43bae3a4d875da56c67a46cf79102b20b456','aa2a707a627408758a0ee845896ef088d6136013','bb0737ce6cdbbcc055771e2400afda545d58778f','454bb6d0471536f7b91793ddbc786761b5733902','3c8ff013bf2e80392671760c8d444730b1923c0a','9a4f0cd0bdc672beb1c1c821599a11fc8a3d139d','f5ca3a789b7451da3e6030443aee6fae734fc7a1','ca8826661175c3a1ff7c6f1ebbfe646b238deb75','9e30ae7bbd1193deb0d3599c071960d395ca01f7','4417ddedee8e753fd6e911192458168d3b77d1e8','2de333e449ca13c462832e799e13795e2cf6e3e4','23d4d0aee62db4adc7381010d80776270a6db47b','5463426618ff46188d19595aa1c7fdd86c6909b3','2649b566bd2bccc59813286d647269ad251e2fdf','5df7907b99976e4051d1dd433e2bdbeb4ce200e3','a7e70930137ff8338778253ac93dc66f11eef966','b92100bddc318e13996fbe96c087c35152cbb4e3','f55b68de8cf9ec17e0512a6caae94e0fbf151260','7fb0d4342e3ed3fabee650b83ce66ffb2f66c173','72a6100cd60dd49f780168137ed09e27a8090b34',];
+ var tests = {
+ "cbb5f28bedf4361156ef3c9c37e314c6479be137":[async_test('html5lib_tests20.html cbb5f28bedf4361156ef3c9c37e314c6479be137'), "%3C%21doctype%20html%3E%3Cp%3E%3Cbutton%3E%3Cbutton%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cbutton%3E%0A%7C%20%20%20%20%20%20%20%3Cbutton%3E"],"e108a4952601b4664098344189c875934ea2f7ab":[async_test('html5lib_tests20.html e108a4952601b4664098344189c875934ea2f7ab'), "%3C%21doctype%20html%3E%3Cp%3E%3Cbutton%3E%3Caddress%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cbutton%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Caddress%3E"],"8ecd0d9e2580f78ff920821bd334bd8d04d165e5":[async_test('html5lib_tests20.html 8ecd0d9e2580f78ff920821bd334bd8d04d165e5'), "%3C%21doctype%20html%3E%3Cp%3E%3Cbutton%3E%3Cblockquote%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cbutton%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cblockquote%3E"],"ff10749b8b1aca1fba5d07ba86f49612be43caf9":[async_test('html5lib_tests20.html ff10749b8b1aca1fba5d07ba86f49612be43caf9'), "%3C%21doctype%20html%3E%3Cp%3E%3Cbutton%3E%3Cmenu%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cbutton%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cmenu%3E"],"323a6d9f8d2f74e7e5b88599a87dc5673fb7a0b4":[async_test('html5lib_tests20.html 323a6d9f8d2f74e7e5b88599a87dc5673fb7a0b4'), "%3C%21doctype%20html%3E%3Cp%3E%3Cbutton%3E%3Cp%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cbutton%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cp%3E"],"bb36fb89d118b55c66f17b24ffff0ca09ccc939b":[async_test('html5lib_tests20.html bb36fb89d118b55c66f17b24ffff0ca09ccc939b'), "%3C%21doctype%20html%3E%3Cp%3E%3Cbutton%3E%3Cul%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cbutton%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cul%3E"],"3fed75e1a7f46a6e2a74a078bfd955e7de05de4f":[async_test('html5lib_tests20.html 3fed75e1a7f46a6e2a74a078bfd955e7de05de4f'), "%3C%21doctype%20html%3E%3Cp%3E%3Cbutton%3E%3Ch1%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cbutton%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ch1%3E"],"8cb9d8f92ba130618646d6fd1f307ca73f4e4add":[async_test('html5lib_tests20.html 8cb9d8f92ba130618646d6fd1f307ca73f4e4add'), "%3C%21doctype%20html%3E%3Cp%3E%3Cbutton%3E%3Ch6%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cbutton%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ch6%3E"],"2b9e6cb75876b4a33b77ae4b1bd3ef5e73c4a40e":[async_test('html5lib_tests20.html 2b9e6cb75876b4a33b77ae4b1bd3ef5e73c4a40e'), "%3C%21doctype%20html%3E%3Cp%3E%3Cbutton%3E%3Clisting%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cbutton%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Clisting%3E"],"f95c6bf3f935fad9fc354f4cf6e0161d6ebfb08a":[async_test('html5lib_tests20.html f95c6bf3f935fad9fc354f4cf6e0161d6ebfb08a'), "%3C%21doctype%20html%3E%3Cp%3E%3Cbutton%3E%3Cpre%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cbutton%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cpre%3E"],"0b07b135bf8399742cc9e6f3d14b2ea32e3354d3":[async_test('html5lib_tests20.html 0b07b135bf8399742cc9e6f3d14b2ea32e3354d3'), "%3C%21doctype%20html%3E%3Cp%3E%3Cbutton%3E%3Cform%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cbutton%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cform%3E"],"076d3588e85ce9566d9575d1564e72e8480fadc8":[async_test('html5lib_tests20.html 076d3588e85ce9566d9575d1564e72e8480fadc8'), "%3C%21doctype%20html%3E%3Cp%3E%3Cbutton%3E%3Cli%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cbutton%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cli%3E"],"dfad8fc515d74c19bad1ab72e7a03d59a11c7778":[async_test('html5lib_tests20.html dfad8fc515d74c19bad1ab72e7a03d59a11c7778'), "%3C%21doctype%20html%3E%3Cp%3E%3Cbutton%3E%3Cdd%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cbutton%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cdd%3E"],"7ff774f225899091d6d64e5512ada13ce32dd72a":[async_test('html5lib_tests20.html 7ff774f225899091d6d64e5512ada13ce32dd72a'), "%3C%21doctype%20html%3E%3Cp%3E%3Cbutton%3E%3Cdt%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cbutton%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cdt%3E"],"2fd8cab5e3cc4635be76e2d430ad6fe6e79b8167":[async_test('html5lib_tests20.html 2fd8cab5e3cc4635be76e2d430ad6fe6e79b8167'), "%3C%21doctype%20html%3E%3Cp%3E%3Cbutton%3E%3Cplaintext%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cbutton%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cplaintext%3E"],"c7399a2e531694b47b436bd153823f60bba9071e":[async_test('html5lib_tests20.html c7399a2e531694b47b436bd153823f60bba9071e'), "%3C%21doctype%20html%3E%3Cp%3E%3Cbutton%3E%3Ctable%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cbutton%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctable%3E"],"bc4092e0e1aaa4b97464005963345b4b38e1f2a1":[async_test('html5lib_tests20.html bc4092e0e1aaa4b97464005963345b4b38e1f2a1'), "%3C%21doctype%20html%3E%3Cp%3E%3Cbutton%3E%3Chr%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cbutton%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Chr%3E"],"d85e49fc5be07a699f3930464996d7ddb6a8e8bd":[async_test('html5lib_tests20.html d85e49fc5be07a699f3930464996d7ddb6a8e8bd'), "%3C%21doctype%20html%3E%3Cp%3E%3Cbutton%3E%3Cxmp%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cbutton%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cxmp%3E"],"09cf43bae3a4d875da56c67a46cf79102b20b456":[async_test('html5lib_tests20.html 09cf43bae3a4d875da56c67a46cf79102b20b456'), "%3C%21doctype%20html%3E%3Cp%3E%3Cbutton%3E%3C/p%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cbutton%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cp%3E"],"aa2a707a627408758a0ee845896ef088d6136013":[async_test('html5lib_tests20.html aa2a707a627408758a0ee845896ef088d6136013'), "%3C%21doctype%20html%3E%3Caddress%3E%3Cbutton%3E%3C/address%3Ea", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Caddress%3E%0A%7C%20%20%20%20%20%20%20%3Cbutton%3E%0A%7C%20%20%20%20%20%22a%22"],"bb0737ce6cdbbcc055771e2400afda545d58778f":[async_test('html5lib_tests20.html bb0737ce6cdbbcc055771e2400afda545d58778f'), "%3Cp%3E%3Ctable%3E%3C/p%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Ctable%3E"],"454bb6d0471536f7b91793ddbc786761b5733902":[async_test('html5lib_tests20.html 454bb6d0471536f7b91793ddbc786761b5733902'), "%3C%21doctype%20html%3E%3Csvg%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E"],"3c8ff013bf2e80392671760c8d444730b1923c0a":[async_test('html5lib_tests20.html 3c8ff013bf2e80392671760c8d444730b1923c0a'), "%3C%21doctype%20html%3E%3Cp%3E%3Cfigcaption%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%3Cfigcaption%3E"],"9a4f0cd0bdc672beb1c1c821599a11fc8a3d139d":[async_test('html5lib_tests20.html 9a4f0cd0bdc672beb1c1c821599a11fc8a3d139d'), "%3C%21doctype%20html%3E%3Cp%3E%3Csummary%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%3Csummary%3E"],"f5ca3a789b7451da3e6030443aee6fae734fc7a1":[async_test('html5lib_tests20.html f5ca3a789b7451da3e6030443aee6fae734fc7a1'), "%3C%21doctype%20html%3E%3Cform%3E%3Ctable%3E%3Cform%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cform%3E%0A%7C%20%20%20%20%20%20%20%3Ctable%3E"],"ca8826661175c3a1ff7c6f1ebbfe646b238deb75":[async_test('html5lib_tests20.html ca8826661175c3a1ff7c6f1ebbfe646b238deb75'), "%3C%21doctype%20html%3E%3Ctable%3E%3Cform%3E%3Cform%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Cform%3E"],"9e30ae7bbd1193deb0d3599c071960d395ca01f7":[async_test('html5lib_tests20.html 9e30ae7bbd1193deb0d3599c071960d395ca01f7'), "%3C%21doctype%20html%3E%3Ctable%3E%3Cform%3E%3C/table%3E%3Cform%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Cform%3E"],"4417ddedee8e753fd6e911192458168d3b77d1e8":[async_test('html5lib_tests20.html 4417ddedee8e753fd6e911192458168d3b77d1e8'), "%3C%21doctype%20html%3E%3Csvg%3E%3CforeignObject%3E%3Cp%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20foreignObject%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cp%3E"],"2de333e449ca13c462832e799e13795e2cf6e3e4":[async_test('html5lib_tests20.html 2de333e449ca13c462832e799e13795e2cf6e3e4'), "%3C%21doctype%20html%3E%3Csvg%3E%3Ctitle%3Eabc", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20title%3E%0A%7C%20%20%20%20%20%20%20%20%20%22abc%22"],"23d4d0aee62db4adc7381010d80776270a6db47b":[async_test('html5lib_tests20.html 23d4d0aee62db4adc7381010d80776270a6db47b'), "%3Coption%3E%3Cspan%3E%3Coption%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Coption%3E%0A%7C%20%20%20%20%20%20%20%3Cspan%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Coption%3E"],"5463426618ff46188d19595aa1c7fdd86c6909b3":[async_test('html5lib_tests20.html 5463426618ff46188d19595aa1c7fdd86c6909b3'), "%3Coption%3E%3Coption%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Coption%3E%0A%7C%20%20%20%20%20%3Coption%3E"],"2649b566bd2bccc59813286d647269ad251e2fdf":[async_test('html5lib_tests20.html 2649b566bd2bccc59813286d647269ad251e2fdf'), "%3Cmath%3E%3Cannotation-xml%3E%3Cdiv%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20annotation-xml%3E%0A%7C%20%20%20%20%20%3Cdiv%3E"],"5df7907b99976e4051d1dd433e2bdbeb4ce200e3":[async_test('html5lib_tests20.html 5df7907b99976e4051d1dd433e2bdbeb4ce200e3'), "%3Cmath%3E%3Cannotation-xml%20encoding%3D%22application/svg%2Bxml%22%3E%3Cdiv%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20annotation-xml%3E%0A%7C%20%20%20%20%20%20%20%20%20encoding%3D%22application/svg%2Bxml%22%0A%7C%20%20%20%20%20%3Cdiv%3E"],"a7e70930137ff8338778253ac93dc66f11eef966":[async_test('html5lib_tests20.html a7e70930137ff8338778253ac93dc66f11eef966'), "%3Cmath%3E%3Cannotation-xml%20encoding%3D%22application/xhtml%2Bxml%22%3E%3Cdiv%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20annotation-xml%3E%0A%7C%20%20%20%20%20%20%20%20%20encoding%3D%22application/xhtml%2Bxml%22%0A%7C%20%20%20%20%20%20%20%20%20%3Cdiv%3E"],"b92100bddc318e13996fbe96c087c35152cbb4e3":[async_test('html5lib_tests20.html b92100bddc318e13996fbe96c087c35152cbb4e3'), "%3Cmath%3E%3Cannotation-xml%20encoding%3D%22aPPlication/xhtmL%2BxMl%22%3E%3Cdiv%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20annotation-xml%3E%0A%7C%20%20%20%20%20%20%20%20%20encoding%3D%22aPPlication/xhtmL%2BxMl%22%0A%7C%20%20%20%20%20%20%20%20%20%3Cdiv%3E"],"f55b68de8cf9ec17e0512a6caae94e0fbf151260":[async_test('html5lib_tests20.html f55b68de8cf9ec17e0512a6caae94e0fbf151260'), "%3Cmath%3E%3Cannotation-xml%20encoding%3D%22text/html%22%3E%3Cdiv%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20annotation-xml%3E%0A%7C%20%20%20%20%20%20%20%20%20encoding%3D%22text/html%22%0A%7C%20%20%20%20%20%20%20%20%20%3Cdiv%3E"],"7fb0d4342e3ed3fabee650b83ce66ffb2f66c173":[async_test('html5lib_tests20.html 7fb0d4342e3ed3fabee650b83ce66ffb2f66c173'), "%3Cmath%3E%3Cannotation-xml%20encoding%3D%22Text/htmL%22%3E%3Cdiv%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20annotation-xml%3E%0A%7C%20%20%20%20%20%20%20%20%20encoding%3D%22Text/htmL%22%0A%7C%20%20%20%20%20%20%20%20%20%3Cdiv%3E"],"72a6100cd60dd49f780168137ed09e27a8090b34":[async_test('html5lib_tests20.html 72a6100cd60dd49f780168137ed09e27a8090b34'), "%3Cmath%3E%3Cannotation-xml%20encoding%3D%22%20text/html%20%22%3E%3Cdiv%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20annotation-xml%3E%0A%7C%20%20%20%20%20%20%20%20%20encoding%3D%22%20text/html%20%22%0A%7C%20%20%20%20%20%3Cdiv%3E"],
+ }
+ init_tests(get_type());
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests21.html b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests21.html
new file mode 100644
index 00000000000..e13295a974e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests21.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf8">
+ <title>HTML 5 Parser tests html5lib_tests21.html</title>
+ <meta name="timeout" content="long">
+ <meta name="variant" content="?run_type=uri">
+ <meta name="variant" content="?run_type=write">
+ <meta name="variant" content="?run_type=write_single">
+ </head>
+ <body>
+ <h1>html5lib Parser Test</h1>
+ <div id="log"></div>
+ <script src="common.js"></script>
+ <script src="test.js"></script>
+ <script src="template.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ var num_iframes = 8;
+ var order = ['49994884ec96a706a3c1b702049a1612e43a81b5','9128ce0d001f8a331dadfd0091dc0faaadcc27a3','250daec0d65f2528955e24fbe667cf40adaee33f','7cdfc1d2d87a4f9ebd754d18dc7b55f73f5ba58b','3d12442cdaef117f92af7ca90e7e03550e07314a','afeea6e5607448d59d16db2c2dad6e0f4f571f25','30b6ff244d2cd3716c1ad482e30ff294dcfed2b7','49b8f552d24bba176c920b40208e1d9f3d866075','60293a1ec80139eb1c9f05e48ca631e812a708da','753ad0dcb4fd3b1d6da2c87dd59116287e08d412','80607dd011814b8d3ef5c9ca380fec044dd5e1aa','b313be34a12fd540ab959b6cf18610fba03cb63f','c9f579bf49de2d4c553d03e43772c0d94be474c0','e714d65a37389755cd7385275f14a757c36b9510','df235b5f7ba9e6e1032bae6c75e92e6a68f48cda','fec253c6085a518dd72fdaff371da31e0d6bdb96','64150a9d88b6214a4a83cf9335e0b0a35e3be170','8c1c2ca15e12599448980201683ece12d4923d9d','32780672eec230ac59d4b61a1adb209bd6a0ed46','be6b00c6bd7e576953b0bceefd9c38d14b452b8d','9df59cd349097dca330fefef6c1b1bbbfddadae6','671f606f5cb7033854d99b96b040994f0f451496','caa80af33c7880aaddd17824efff1774ece01325',];
+ var tests = {
+ "49994884ec96a706a3c1b702049a1612e43a81b5":[async_test('html5lib_tests21.html 49994884ec96a706a3c1b702049a1612e43a81b5'), "%3Csvg%3E%3C%21%5BCDATA%5Bfoo%5D%5D%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%22foo%22"],"9128ce0d001f8a331dadfd0091dc0faaadcc27a3":[async_test('html5lib_tests21.html 9128ce0d001f8a331dadfd0091dc0faaadcc27a3'), "%3Cmath%3E%3C%21%5BCDATA%5Bfoo%5D%5D%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%22foo%22"],"250daec0d65f2528955e24fbe667cf40adaee33f":[async_test('html5lib_tests21.html 250daec0d65f2528955e24fbe667cf40adaee33f'), "%3Cdiv%3E%3C%21%5BCDATA%5Bfoo%5D%5D%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%3C%21--%20%5BCDATA%5Bfoo%5D%5D%20--%3E"],"7cdfc1d2d87a4f9ebd754d18dc7b55f73f5ba58b":[async_test('html5lib_tests21.html 7cdfc1d2d87a4f9ebd754d18dc7b55f73f5ba58b'), "%3Csvg%3E%3C%21%5BCDATA%5Bfoo", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%22foo%22"],"3d12442cdaef117f92af7ca90e7e03550e07314a":[async_test('html5lib_tests21.html 3d12442cdaef117f92af7ca90e7e03550e07314a'), "%3Csvg%3E%3C%21%5BCDATA%5B", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E"],"afeea6e5607448d59d16db2c2dad6e0f4f571f25":[async_test('html5lib_tests21.html afeea6e5607448d59d16db2c2dad6e0f4f571f25'), "%3Csvg%3E%3C%21%5BCDATA%5B%5D%5D%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E"],"30b6ff244d2cd3716c1ad482e30ff294dcfed2b7":[async_test('html5lib_tests21.html 30b6ff244d2cd3716c1ad482e30ff294dcfed2b7'), "%3Csvg%3E%3C%21%5BCDATA%5B%5D%5D%20%3E%5D%5D%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%22%5D%5D%20%3E%22"],"49b8f552d24bba176c920b40208e1d9f3d866075":[async_test('html5lib_tests21.html 49b8f552d24bba176c920b40208e1d9f3d866075'), "%3Csvg%3E%3C%21%5BCDATA%5B%5D%5D", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%22%5D%5D%22"],"60293a1ec80139eb1c9f05e48ca631e812a708da":[async_test('html5lib_tests21.html 60293a1ec80139eb1c9f05e48ca631e812a708da'), "%3Csvg%3E%3C%21%5BCDATA%5B%5D", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%22%5D%22"],"753ad0dcb4fd3b1d6da2c87dd59116287e08d412":[async_test('html5lib_tests21.html 753ad0dcb4fd3b1d6da2c87dd59116287e08d412'), "%3Csvg%3E%3C%21%5BCDATA%5B%5D%3Ea", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%22%5D%3Ea%22"],"80607dd011814b8d3ef5c9ca380fec044dd5e1aa":[async_test('html5lib_tests21.html 80607dd011814b8d3ef5c9ca380fec044dd5e1aa'), "%3C%21DOCTYPE%20html%3E%3Csvg%3E%3C%21%5BCDATA%5Bfoo%5D%5D%5D%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%22foo%5D%22"],"b313be34a12fd540ab959b6cf18610fba03cb63f":[async_test('html5lib_tests21.html b313be34a12fd540ab959b6cf18610fba03cb63f'), "%3C%21DOCTYPE%20html%3E%3Csvg%3E%3C%21%5BCDATA%5Bfoo%5D%5D%5D%5D%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%22foo%5D%5D%22"],"c9f579bf49de2d4c553d03e43772c0d94be474c0":[async_test('html5lib_tests21.html c9f579bf49de2d4c553d03e43772c0d94be474c0'), "%3C%21DOCTYPE%20html%3E%3Csvg%3E%3C%21%5BCDATA%5Bfoo%5D%5D%5D%5D%5D%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%22foo%5D%5D%5D%22"],"e714d65a37389755cd7385275f14a757c36b9510":[async_test('html5lib_tests21.html e714d65a37389755cd7385275f14a757c36b9510'), "%3Csvg%3E%3CforeignObject%3E%3Cdiv%3E%3C%21%5BCDATA%5Bfoo%5D%5D%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20foreignObject%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3C%21--%20%5BCDATA%5Bfoo%5D%5D%20--%3E"],"df235b5f7ba9e6e1032bae6c75e92e6a68f48cda":[async_test('html5lib_tests21.html df235b5f7ba9e6e1032bae6c75e92e6a68f48cda'), "%3Csvg%3E%3C%21%5BCDATA%5B%3Csvg%3E%5D%5D%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%22%3Csvg%3E%22"],"fec253c6085a518dd72fdaff371da31e0d6bdb96":[async_test('html5lib_tests21.html fec253c6085a518dd72fdaff371da31e0d6bdb96'), "%3Csvg%3E%3C%21%5BCDATA%5B%3C/svg%3Ea%5D%5D%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%22%3C/svg%3Ea%22"],"64150a9d88b6214a4a83cf9335e0b0a35e3be170":[async_test('html5lib_tests21.html 64150a9d88b6214a4a83cf9335e0b0a35e3be170'), "%3Csvg%3E%3C%21%5BCDATA%5B%3Csvg%3Ea", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%22%3Csvg%3Ea%22"],"8c1c2ca15e12599448980201683ece12d4923d9d":[async_test('html5lib_tests21.html 8c1c2ca15e12599448980201683ece12d4923d9d'), "%3Csvg%3E%3C%21%5BCDATA%5B%3C/svg%3Ea", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%22%3C/svg%3Ea%22"],"32780672eec230ac59d4b61a1adb209bd6a0ed46":[async_test('html5lib_tests21.html 32780672eec230ac59d4b61a1adb209bd6a0ed46'), "%3Csvg%3E%3C%21%5BCDATA%5B%3Csvg%3E%5D%5D%3E%3Cpath%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%22%3Csvg%3E%22%0A%7C%20%20%20%20%20%20%20%3Csvg%20path%3E"],"be6b00c6bd7e576953b0bceefd9c38d14b452b8d":[async_test('html5lib_tests21.html be6b00c6bd7e576953b0bceefd9c38d14b452b8d'), "%3Csvg%3E%3C%21%5BCDATA%5B%3Csvg%3E%5D%5D%3E%3C/path%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%22%3Csvg%3E%22"],"9df59cd349097dca330fefef6c1b1bbbfddadae6":[async_test('html5lib_tests21.html 9df59cd349097dca330fefef6c1b1bbbfddadae6'), "%3Csvg%3E%3C%21%5BCDATA%5B%3Csvg%3E%5D%5D%3E%3C%21--path--%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%22%3Csvg%3E%22%0A%7C%20%20%20%20%20%20%20%3C%21--%20path%20--%3E"],"671f606f5cb7033854d99b96b040994f0f451496":[async_test('html5lib_tests21.html 671f606f5cb7033854d99b96b040994f0f451496'), "%3Csvg%3E%3C%21%5BCDATA%5B%3Csvg%3E%5D%5D%3Epath", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%22%3Csvg%3Epath%22"],"caa80af33c7880aaddd17824efff1774ece01325":[async_test('html5lib_tests21.html caa80af33c7880aaddd17824efff1774ece01325'), "%3Csvg%3E%3C%21%5BCDATA%5B%3C%21--svg--%3E%5D%5D%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--svg--%3E%22"],
+ }
+ init_tests(get_type());
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests22.html b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests22.html
new file mode 100644
index 00000000000..74886e16603
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests22.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf8">
+ <title>HTML 5 Parser tests html5lib_tests22.html</title>
+ <meta name="timeout" content="long">
+ <meta name="variant" content="?run_type=uri">
+ <meta name="variant" content="?run_type=write">
+ <meta name="variant" content="?run_type=write_single">
+ </head>
+ <body>
+ <h1>html5lib Parser Test</h1>
+ <div id="log"></div>
+ <script src="common.js"></script>
+ <script src="test.js"></script>
+ <script src="template.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ var num_iframes = 8;
+ var order = ['0aae674c4a721f0a6f6205bca13056f08a516b00','9ee2a7fffc0ac4b0a2d59ac154d9d79b3b62499f','eba4be47ca51e9c659aaa2de43e17aded0d13e50','d69b2cbec658966233616e553d8b0b1dd544310d','4685334adccb0ef98b769fb8546b5696e28af968',];
+ var tests = {
+ "0aae674c4a721f0a6f6205bca13056f08a516b00":[async_test('html5lib_tests22.html 0aae674c4a721f0a6f6205bca13056f08a516b00'), "%3Ca%3E%3Cb%3E%3Cbig%3E%3Cem%3E%3Cstrong%3E%3Cdiv%3EX%3C/a%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cbig%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cem%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cstrong%3E%0A%7C%20%20%20%20%20%3Cbig%3E%0A%7C%20%20%20%20%20%20%20%3Cem%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cstrong%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22X%22"],"9ee2a7fffc0ac4b0a2d59ac154d9d79b3b62499f":[async_test('html5lib_tests22.html 9ee2a7fffc0ac4b0a2d59ac154d9d79b3b62499f'), "%3Ca%3E%3Cb%3E%3Cdiv%20id%3D1%3E%3Cdiv%20id%3D2%3E%3Cdiv%20id%3D3%3E%3Cdiv%20id%3D4%3E%3Cdiv%20id%3D5%3E%3Cdiv%20id%3D6%3E%3Cdiv%20id%3D7%3E%3Cdiv%20id%3D8%3EA%3C/a%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20id%3D%221%22%0A%7C%20%20%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20id%3D%222%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20id%3D%223%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20id%3D%224%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20id%3D%225%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20id%3D%226%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20id%3D%227%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20id%3D%228%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22A%22"],"eba4be47ca51e9c659aaa2de43e17aded0d13e50":[async_test('html5lib_tests22.html eba4be47ca51e9c659aaa2de43e17aded0d13e50'), "%3Ca%3E%3Cb%3E%3Cdiv%20id%3D1%3E%3Cdiv%20id%3D2%3E%3Cdiv%20id%3D3%3E%3Cdiv%20id%3D4%3E%3Cdiv%20id%3D5%3E%3Cdiv%20id%3D6%3E%3Cdiv%20id%3D7%3E%3Cdiv%20id%3D8%3E%3Cdiv%20id%3D9%3EA%3C/a%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20id%3D%221%22%0A%7C%20%20%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20id%3D%222%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20id%3D%223%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20id%3D%224%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20id%3D%225%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20id%3D%226%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20id%3D%227%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20id%3D%228%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20id%3D%229%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22A%22"],"d69b2cbec658966233616e553d8b0b1dd544310d":[async_test('html5lib_tests22.html d69b2cbec658966233616e553d8b0b1dd544310d'), "%3Ca%3E%3Cb%3E%3Cdiv%20id%3D1%3E%3Cdiv%20id%3D2%3E%3Cdiv%20id%3D3%3E%3Cdiv%20id%3D4%3E%3Cdiv%20id%3D5%3E%3Cdiv%20id%3D6%3E%3Cdiv%20id%3D7%3E%3Cdiv%20id%3D8%3E%3Cdiv%20id%3D9%3E%3Cdiv%20id%3D10%3EA%3C/a%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20id%3D%221%22%0A%7C%20%20%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20id%3D%222%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20id%3D%223%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20id%3D%224%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20id%3D%225%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20id%3D%226%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20id%3D%227%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20id%3D%228%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20id%3D%229%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20id%3D%2210%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22A%22"],"4685334adccb0ef98b769fb8546b5696e28af968":[async_test('html5lib_tests22.html 4685334adccb0ef98b769fb8546b5696e28af968'), "%3Ccite%3E%3Cb%3E%3Ccite%3E%3Ci%3E%3Ccite%3E%3Ci%3E%3Ccite%3E%3Ci%3E%3Cdiv%3EX%3C/b%3ETEST", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ccite%3E%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ccite%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ccite%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ccite%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22X%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%22TEST%22"],
+ }
+ init_tests(get_type());
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests23.html b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests23.html
new file mode 100644
index 00000000000..b471f34ddf0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests23.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf8">
+ <title>HTML 5 Parser tests html5lib_tests23.html</title>
+ <meta name="timeout" content="long">
+ <meta name="variant" content="?run_type=uri">
+ <meta name="variant" content="?run_type=write">
+ <meta name="variant" content="?run_type=write_single">
+ </head>
+ <body>
+ <h1>html5lib Parser Test</h1>
+ <div id="log"></div>
+ <script src="common.js"></script>
+ <script src="test.js"></script>
+ <script src="template.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ var num_iframes = 8;
+ var order = ['79c0dc8da653d983d07795852b5f38d1533ff404','403404388390abddf3fb44db8dd7d643652f5df9','b9a81ae44ab81719fc6a4e3b6460fc6efc684e65','d271d3662baafff4893d32b250cadcf4c2ff3352','f8e296b2f362a64c1c464bedd6248e314f41c701',];
+ var tests = {
+ "79c0dc8da653d983d07795852b5f38d1533ff404":[async_test('html5lib_tests23.html 79c0dc8da653d983d07795852b5f38d1533ff404'), "%3Cp%3E%3Cfont%20size%3D4%3E%3Cfont%20color%3Dred%3E%3Cfont%20size%3D4%3E%3Cfont%20size%3D4%3E%3Cfont%20size%3D4%3E%3Cfont%20size%3D4%3E%3Cfont%20size%3D4%3E%3Cfont%20color%3Dred%3E%3Cp%3EX", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%20%20size%3D%224%22%0A%7C%20%20%20%20%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20color%3D%22red%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20size%3D%224%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20size%3D%224%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20size%3D%224%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20size%3D%224%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20size%3D%224%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20color%3D%22red%22%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%20%20color%3D%22red%22%0A%7C%20%20%20%20%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20size%3D%224%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20size%3D%224%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20size%3D%224%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20color%3D%22red%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22X%22"],"403404388390abddf3fb44db8dd7d643652f5df9":[async_test('html5lib_tests23.html 403404388390abddf3fb44db8dd7d643652f5df9'), "%3Cp%3E%3Cfont%20size%3D4%3E%3Cfont%20size%3D4%3E%3Cfont%20size%3D4%3E%3Cfont%20size%3D4%3E%3Cp%3EX", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%20%20size%3D%224%22%0A%7C%20%20%20%20%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20size%3D%224%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20size%3D%224%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20size%3D%224%22%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%20%20size%3D%224%22%0A%7C%20%20%20%20%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20size%3D%224%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20size%3D%224%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%22X%22"],"b9a81ae44ab81719fc6a4e3b6460fc6efc684e65":[async_test('html5lib_tests23.html b9a81ae44ab81719fc6a4e3b6460fc6efc684e65'), "%3Cp%3E%3Cfont%20size%3D4%3E%3Cfont%20size%3D4%3E%3Cfont%20size%3D4%3E%3Cfont%20size%3D%225%22%3E%3Cfont%20size%3D4%3E%3Cp%3EX", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%20%20size%3D%224%22%0A%7C%20%20%20%20%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20size%3D%224%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20size%3D%224%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20size%3D%225%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20size%3D%224%22%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%20%20size%3D%224%22%0A%7C%20%20%20%20%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20size%3D%224%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20size%3D%225%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20size%3D%224%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22X%22"],"d271d3662baafff4893d32b250cadcf4c2ff3352":[async_test('html5lib_tests23.html d271d3662baafff4893d32b250cadcf4c2ff3352'), "%3Cp%3E%3Cfont%20size%3D4%20id%3Da%3E%3Cfont%20size%3D4%20id%3Db%3E%3Cfont%20size%3D4%3E%3Cfont%20size%3D4%3E%3Cp%3EX", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%20%20id%3D%22a%22%0A%7C%20%20%20%20%20%20%20%20%20size%3D%224%22%0A%7C%20%20%20%20%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20id%3D%22b%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20size%3D%224%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20size%3D%224%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20size%3D%224%22%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%20%20id%3D%22a%22%0A%7C%20%20%20%20%20%20%20%20%20size%3D%224%22%0A%7C%20%20%20%20%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20id%3D%22b%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20size%3D%224%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20size%3D%224%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20size%3D%224%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22X%22"],"f8e296b2f362a64c1c464bedd6248e314f41c701":[async_test('html5lib_tests23.html f8e296b2f362a64c1c464bedd6248e314f41c701'), "%3Cp%3E%3Cb%20id%3Da%3E%3Cb%20id%3Da%3E%3Cb%20id%3Da%3E%3Cb%3E%3Cobject%3E%3Cb%20id%3Da%3E%3Cb%20id%3Da%3EX%3C/object%3E%3Cp%3EY", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20id%3D%22a%22%0A%7C%20%20%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20id%3D%22a%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20id%3D%22a%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cobject%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20id%3D%22a%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20id%3D%22a%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22X%22%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20id%3D%22a%22%0A%7C%20%20%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20id%3D%22a%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20id%3D%22a%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22Y%22"],
+ }
+ init_tests(get_type());
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests24.html b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests24.html
new file mode 100644
index 00000000000..ecfd895e863
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests24.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf8">
+ <title>HTML 5 Parser tests html5lib_tests24.html</title>
+ <meta name="timeout" content="long">
+ <meta name="variant" content="?run_type=uri">
+ <meta name="variant" content="?run_type=write">
+ <meta name="variant" content="?run_type=write_single">
+ </head>
+ <body>
+ <h1>html5lib Parser Test</h1>
+ <div id="log"></div>
+ <script src="common.js"></script>
+ <script src="test.js"></script>
+ <script src="template.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ var num_iframes = 8;
+ var order = ['692c2dbacf18cb758f26a3d9e7d9add4356f9067','614cc9827d3a0c5f91863dde5281dd0d97f64e6d','c517924583ee71b8e684c9ca1f2eed5e88139a39','140a82fab878c139b388d159c511eb999fe2d8c7','a2ddddcccb652a6529daafd4153a0e12b6d5ca8c','da2e30a0b6577b608bf48bbd11a16ff832bc7e46','66a5777f5453bd4b5161f00df02883b6d71f7cea','c8d97f31b70f67005eeacc3c86ac29e577c3d0ed',];
+ var tests = {
+ "692c2dbacf18cb758f26a3d9e7d9add4356f9067":[async_test('html5lib_tests24.html 692c2dbacf18cb758f26a3d9e7d9add4356f9067'), "%3C%21DOCTYPE%20html%3E%26NotEqualTilde%3B", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22%E2%89%82%CC%B8%22"],"614cc9827d3a0c5f91863dde5281dd0d97f64e6d":[async_test('html5lib_tests24.html 614cc9827d3a0c5f91863dde5281dd0d97f64e6d'), "%3C%21DOCTYPE%20html%3E%26NotEqualTilde%3BA", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22%E2%89%82%CC%B8A%22"],"c517924583ee71b8e684c9ca1f2eed5e88139a39":[async_test('html5lib_tests24.html c517924583ee71b8e684c9ca1f2eed5e88139a39'), "%3C%21DOCTYPE%20html%3E%26ThickSpace%3B", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22%E2%81%9F%E2%80%8A%22"],"140a82fab878c139b388d159c511eb999fe2d8c7":[async_test('html5lib_tests24.html 140a82fab878c139b388d159c511eb999fe2d8c7'), "%3C%21DOCTYPE%20html%3E%26ThickSpace%3BA", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22%E2%81%9F%E2%80%8AA%22"],"a2ddddcccb652a6529daafd4153a0e12b6d5ca8c":[async_test('html5lib_tests24.html a2ddddcccb652a6529daafd4153a0e12b6d5ca8c'), "%3C%21DOCTYPE%20html%3E%26NotSubset%3B", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22%E2%8A%82%E2%83%92%22"],"da2e30a0b6577b608bf48bbd11a16ff832bc7e46":[async_test('html5lib_tests24.html da2e30a0b6577b608bf48bbd11a16ff832bc7e46'), "%3C%21DOCTYPE%20html%3E%26NotSubset%3BA", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22%E2%8A%82%E2%83%92A%22"],"66a5777f5453bd4b5161f00df02883b6d71f7cea":[async_test('html5lib_tests24.html 66a5777f5453bd4b5161f00df02883b6d71f7cea'), "%3C%21DOCTYPE%20html%3E%26Gopf%3B", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22%F0%9D%94%BE%22"],"c8d97f31b70f67005eeacc3c86ac29e577c3d0ed":[async_test('html5lib_tests24.html c8d97f31b70f67005eeacc3c86ac29e577c3d0ed'), "%3C%21DOCTYPE%20html%3E%26Gopf%3BA", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22%F0%9D%94%BEA%22"],
+ }
+ init_tests(get_type());
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests25.html b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests25.html
new file mode 100644
index 00000000000..2ae12eb1c5b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests25.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf8">
+ <title>HTML 5 Parser tests html5lib_tests25.html</title>
+ <meta name="timeout" content="long">
+ <meta name="variant" content="?run_type=uri">
+ <meta name="variant" content="?run_type=write">
+ <meta name="variant" content="?run_type=write_single">
+ </head>
+ <body>
+ <h1>html5lib Parser Test</h1>
+ <div id="log"></div>
+ <script src="common.js"></script>
+ <script src="test.js"></script>
+ <script src="template.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ var num_iframes = 8;
+ var order = ['025adbb619bdef9ad228a6b378b9dd6bef9f93dc','7e561454888535bc5c68e7396de2f4206c81e97d','a14bdd90f5a745296e74c23951245cb7c5046ed1','421ad19f7854b9c8e28a0595a8dd20d6bfcd5376','7e8234523fbf67d37ab60f593e1fc3ac67706651','c705ceb6fb37865e6965641ea80137baf44176b6','277da0c4c937f3852d8a7cacf4e4b426a30b3dda','de4aa726e09215ba9c50b97d257e6c6b880107f1','d46fa11c0107d59c84778beae84f388f55bffc31','578e08f11628dc9841f3eb21c016e1e28cec0304','a6e5387b48c4d0399a802215f7fa206bd0d3b492','d56d47bc9d9c7472fb1706bdecda1bbd165dcf91','2779456edd8407b403561e0cf339c8c2308c88b8','17d197ab2416adec6eb92e398c2db6f7efc98b58','1ccc6e280f6dc773e2e00f2cb70cd96e97078296','48ddaacf5355643f27ef704ece88b227f51fc7cb','bf29bfbd56c9863d19e4d66cd67a0dc1813b2e86','73fc7c062b68d4f89579683dbb7f1eaef4ec27f1','057bc2d868d2f365cb2c0b4d07c231d2fa2b23b7','7f684d19be362ec9aa4fe7ecbba4ff3fc9730a43','d79f9119d02447226cc2d151044e6cffc5409e81',];
+ var tests = {
+ "025adbb619bdef9ad228a6b378b9dd6bef9f93dc":[async_test('html5lib_tests25.html 025adbb619bdef9ad228a6b378b9dd6bef9f93dc'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Cfoo%3EA", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cfoo%3E%0A%7C%20%20%20%20%20%20%20%22A%22"],"7e561454888535bc5c68e7396de2f4206c81e97d":[async_test('html5lib_tests25.html 7e561454888535bc5c68e7396de2f4206c81e97d'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Carea%3EA", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Carea%3E%0A%7C%20%20%20%20%20%22A%22"],"a14bdd90f5a745296e74c23951245cb7c5046ed1":[async_test('html5lib_tests25.html a14bdd90f5a745296e74c23951245cb7c5046ed1'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Cbase%3EA", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cbase%3E%0A%7C%20%20%20%20%20%22A%22"],"421ad19f7854b9c8e28a0595a8dd20d6bfcd5376":[async_test('html5lib_tests25.html 421ad19f7854b9c8e28a0595a8dd20d6bfcd5376'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Cbasefont%3EA", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cbasefont%3E%0A%7C%20%20%20%20%20%22A%22"],"7e8234523fbf67d37ab60f593e1fc3ac67706651":[async_test('html5lib_tests25.html 7e8234523fbf67d37ab60f593e1fc3ac67706651'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Cbgsound%3EA", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cbgsound%3E%0A%7C%20%20%20%20%20%22A%22"],"c705ceb6fb37865e6965641ea80137baf44176b6":[async_test('html5lib_tests25.html c705ceb6fb37865e6965641ea80137baf44176b6'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Cbr%3EA", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cbr%3E%0A%7C%20%20%20%20%20%22A%22"],"277da0c4c937f3852d8a7cacf4e4b426a30b3dda":[async_test('html5lib_tests25.html 277da0c4c937f3852d8a7cacf4e4b426a30b3dda'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Ccol%3EA", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22A%22"],"de4aa726e09215ba9c50b97d257e6c6b880107f1":[async_test('html5lib_tests25.html de4aa726e09215ba9c50b97d257e6c6b880107f1'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Ccommand%3EA", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ccommand%3E%0A%7C%20%20%20%20%20%20%20%22A%22"],"d46fa11c0107d59c84778beae84f388f55bffc31":[async_test('html5lib_tests25.html d46fa11c0107d59c84778beae84f388f55bffc31'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Cmenuitem%3EA", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cmenuitem%3E%0A%7C%20%20%20%20%20%22A%22"],"578e08f11628dc9841f3eb21c016e1e28cec0304":[async_test('html5lib_tests25.html 578e08f11628dc9841f3eb21c016e1e28cec0304'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Cembed%3EA", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cembed%3E%0A%7C%20%20%20%20%20%22A%22"],"a6e5387b48c4d0399a802215f7fa206bd0d3b492":[async_test('html5lib_tests25.html a6e5387b48c4d0399a802215f7fa206bd0d3b492'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Cframe%3EA", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22A%22"],"d56d47bc9d9c7472fb1706bdecda1bbd165dcf91":[async_test('html5lib_tests25.html d56d47bc9d9c7472fb1706bdecda1bbd165dcf91'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Chr%3EA", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Chr%3E%0A%7C%20%20%20%20%20%22A%22"],"2779456edd8407b403561e0cf339c8c2308c88b8":[async_test('html5lib_tests25.html 2779456edd8407b403561e0cf339c8c2308c88b8'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Cimg%3EA", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cimg%3E%0A%7C%20%20%20%20%20%22A%22"],"17d197ab2416adec6eb92e398c2db6f7efc98b58":[async_test('html5lib_tests25.html 17d197ab2416adec6eb92e398c2db6f7efc98b58'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Cinput%3EA", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cinput%3E%0A%7C%20%20%20%20%20%22A%22"],"1ccc6e280f6dc773e2e00f2cb70cd96e97078296":[async_test('html5lib_tests25.html 1ccc6e280f6dc773e2e00f2cb70cd96e97078296'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Ckeygen%3EA", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ckeygen%3E%0A%7C%20%20%20%20%20%22A%22"],"48ddaacf5355643f27ef704ece88b227f51fc7cb":[async_test('html5lib_tests25.html 48ddaacf5355643f27ef704ece88b227f51fc7cb'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Clink%3EA", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Clink%3E%0A%7C%20%20%20%20%20%22A%22"],"bf29bfbd56c9863d19e4d66cd67a0dc1813b2e86":[async_test('html5lib_tests25.html bf29bfbd56c9863d19e4d66cd67a0dc1813b2e86'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Cmeta%3EA", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cmeta%3E%0A%7C%20%20%20%20%20%22A%22"],"73fc7c062b68d4f89579683dbb7f1eaef4ec27f1":[async_test('html5lib_tests25.html 73fc7c062b68d4f89579683dbb7f1eaef4ec27f1'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Cparam%3EA", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cparam%3E%0A%7C%20%20%20%20%20%22A%22"],"057bc2d868d2f365cb2c0b4d07c231d2fa2b23b7":[async_test('html5lib_tests25.html 057bc2d868d2f365cb2c0b4d07c231d2fa2b23b7'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Csource%3EA", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csource%3E%0A%7C%20%20%20%20%20%22A%22"],"7f684d19be362ec9aa4fe7ecbba4ff3fc9730a43":[async_test('html5lib_tests25.html 7f684d19be362ec9aa4fe7ecbba4ff3fc9730a43'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Ctrack%3EA", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctrack%3E%0A%7C%20%20%20%20%20%22A%22"],"d79f9119d02447226cc2d151044e6cffc5409e81":[async_test('html5lib_tests25.html d79f9119d02447226cc2d151044e6cffc5409e81'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Cwbr%3EA", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cwbr%3E%0A%7C%20%20%20%20%20%22A%22"],
+ }
+ init_tests(get_type());
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests26.html b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests26.html
new file mode 100644
index 00000000000..49566d2feb4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests26.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf8">
+ <title>HTML 5 Parser tests html5lib_tests26.html</title>
+ <meta name="timeout" content="long">
+ <meta name="variant" content="?run_type=uri">
+ <meta name="variant" content="?run_type=write">
+ <meta name="variant" content="?run_type=write_single">
+ </head>
+ <body>
+ <h1>html5lib Parser Test</h1>
+ <div id="log"></div>
+ <script src="common.js"></script>
+ <script src="test.js"></script>
+ <script src="template.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ var num_iframes = 8;
+ var order = ['6232bd8c710002d3b3c375903a712d05163a821d','5e4fff339b6d191d80311bfa258a9b62e063c6aa','8695403efa4e413a1ad1f99984a8c0ecba379698','c3aa0a4f4e81fa4a2fd398c7a7a090d2c3f955f4','167bc3c289b234ab99fe96eaa0845682345de48c','3dacba9a76b8c454b42b9868252bbb6b68327184','8f1c4c0f0eee7b8136934ee18bd3beffbc7f2fe0','7369c472433b6dd76585b797fd3708e474601ecc','c085683feffd9da64f8782545042884173a1d1e3','be84971ac4a451e91099d225d0315dd17a88b830','9d63346ca23dc3ee41e29fe7d8403934bce8c610','8434eb9c0c3daf656b3158f5955d07e39ddc6444','6c95a99290e309b638b958272686a21486fa561e','37d360649a2b092ad05e1be1c9ea65bfec83ca6d','8919621ebbd1f4df0fdaacee3e53dc959a2d9235','3723d028349cbbc1a5c3f014987bb11c8ba804d0',];
+ var tests = {
+ "6232bd8c710002d3b3c375903a712d05163a821d":[async_test('html5lib_tests26.html 6232bd8c710002d3b3c375903a712d05163a821d'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Ca%20href%3D%27%231%27%3E%3Cnobr%3E1%3Cnobr%3E%3C/a%3E%3Cbr%3E%3Ca%20href%3D%27%232%27%3E%3Cnobr%3E2%3Cnobr%3E%3C/a%3E%3Cbr%3E%3Ca%20href%3D%27%233%27%3E%3Cnobr%3E3%3Cnobr%3E%3C/a%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20href%3D%22%231%22%0A%7C%20%20%20%20%20%20%20%3Cnobr%3E%0A%7C%20%20%20%20%20%20%20%20%20%221%22%0A%7C%20%20%20%20%20%20%20%3Cnobr%3E%0A%7C%20%20%20%20%20%3Cnobr%3E%0A%7C%20%20%20%20%20%20%20%3Cbr%3E%0A%7C%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20href%3D%22%232%22%0A%7C%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20href%3D%22%232%22%0A%7C%20%20%20%20%20%20%20%3Cnobr%3E%0A%7C%20%20%20%20%20%20%20%20%20%222%22%0A%7C%20%20%20%20%20%20%20%3Cnobr%3E%0A%7C%20%20%20%20%20%3Cnobr%3E%0A%7C%20%20%20%20%20%20%20%3Cbr%3E%0A%7C%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20href%3D%22%233%22%0A%7C%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20href%3D%22%233%22%0A%7C%20%20%20%20%20%20%20%3Cnobr%3E%0A%7C%20%20%20%20%20%20%20%20%20%223%22%0A%7C%20%20%20%20%20%20%20%3Cnobr%3E"],"5e4fff339b6d191d80311bfa258a9b62e063c6aa":[async_test('html5lib_tests26.html 5e4fff339b6d191d80311bfa258a9b62e063c6aa'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Cb%3E%3Cnobr%3E1%3Cnobr%3E%3C/b%3E%3Ci%3E%3Cnobr%3E2%3Cnobr%3E%3C/i%3E3", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%3Cnobr%3E%0A%7C%20%20%20%20%20%20%20%20%20%221%22%0A%7C%20%20%20%20%20%20%20%3Cnobr%3E%0A%7C%20%20%20%20%20%3Cnobr%3E%0A%7C%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%3Cnobr%3E%0A%7C%20%20%20%20%20%20%20%20%20%222%22%0A%7C%20%20%20%20%20%20%20%3Cnobr%3E%0A%7C%20%20%20%20%20%3Cnobr%3E%0A%7C%20%20%20%20%20%20%20%223%22"],"8695403efa4e413a1ad1f99984a8c0ecba379698":[async_test('html5lib_tests26.html 8695403efa4e413a1ad1f99984a8c0ecba379698'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Cb%3E%3Cnobr%3E1%3Ctable%3E%3Cnobr%3E%3C/b%3E%3Ci%3E%3Cnobr%3E2%3Cnobr%3E%3C/i%3E3", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%3Cnobr%3E%0A%7C%20%20%20%20%20%20%20%20%20%221%22%0A%7C%20%20%20%20%20%20%20%20%20%3Cnobr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cnobr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%222%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cnobr%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cnobr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%223%22%0A%7C%20%20%20%20%20%20%20%20%20%3Ctable%3E"],"c3aa0a4f4e81fa4a2fd398c7a7a090d2c3f955f4":[async_test('html5lib_tests26.html c3aa0a4f4e81fa4a2fd398c7a7a090d2c3f955f4'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Cb%3E%3Cnobr%3E1%3Ctable%3E%3Ctr%3E%3Ctd%3E%3Cnobr%3E%3C/b%3E%3Ci%3E%3Cnobr%3E2%3Cnobr%3E%3C/i%3E3", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%3Cnobr%3E%0A%7C%20%20%20%20%20%20%20%20%20%221%22%0A%7C%20%20%20%20%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cnobr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cnobr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%222%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cnobr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cnobr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%223%22"],"167bc3c289b234ab99fe96eaa0845682345de48c":[async_test('html5lib_tests26.html 167bc3c289b234ab99fe96eaa0845682345de48c'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Cb%3E%3Cnobr%3E1%3Cdiv%3E%3Cnobr%3E%3C/b%3E%3Ci%3E%3Cnobr%3E2%3Cnobr%3E%3C/i%3E3", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%3Cnobr%3E%0A%7C%20%20%20%20%20%20%20%20%20%221%22%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cnobr%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cnobr%3E%0A%7C%20%20%20%20%20%20%20%3Cnobr%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cnobr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%222%22%0A%7C%20%20%20%20%20%20%20%20%20%3Cnobr%3E%0A%7C%20%20%20%20%20%20%20%3Cnobr%3E%0A%7C%20%20%20%20%20%20%20%20%20%223%22"],"3dacba9a76b8c454b42b9868252bbb6b68327184":[async_test('html5lib_tests26.html 3dacba9a76b8c454b42b9868252bbb6b68327184'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Cb%3E%3Cnobr%3E1%3Cnobr%3E%3C/b%3E%3Cdiv%3E%3Ci%3E%3Cnobr%3E2%3Cnobr%3E%3C/i%3E3", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%3Cnobr%3E%0A%7C%20%20%20%20%20%20%20%20%20%221%22%0A%7C%20%20%20%20%20%20%20%3Cnobr%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%3Cnobr%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cnobr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%222%22%0A%7C%20%20%20%20%20%20%20%20%20%3Cnobr%3E%0A%7C%20%20%20%20%20%20%20%3Cnobr%3E%0A%7C%20%20%20%20%20%20%20%20%20%223%22"],"8f1c4c0f0eee7b8136934ee18bd3beffbc7f2fe0":[async_test('html5lib_tests26.html 8f1c4c0f0eee7b8136934ee18bd3beffbc7f2fe0'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Cb%3E%3Cnobr%3E1%3Cnobr%3E%3Cins%3E%3C/b%3E%3Ci%3E%3Cnobr%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%3Cnobr%3E%0A%7C%20%20%20%20%20%20%20%20%20%221%22%0A%7C%20%20%20%20%20%20%20%3Cnobr%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cins%3E%0A%7C%20%20%20%20%20%3Cnobr%3E%0A%7C%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%3Cnobr%3E"],"7369c472433b6dd76585b797fd3708e474601ecc":[async_test('html5lib_tests26.html 7369c472433b6dd76585b797fd3708e474601ecc'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Cb%3E%3Cnobr%3E1%3Cins%3E%3Cnobr%3E%3C/b%3E%3Ci%3E2", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%3Cnobr%3E%0A%7C%20%20%20%20%20%20%20%20%20%221%22%0A%7C%20%20%20%20%20%20%20%20%20%3Cins%3E%0A%7C%20%20%20%20%20%20%20%3Cnobr%3E%0A%7C%20%20%20%20%20%3Cnobr%3E%0A%7C%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%222%22"],"c085683feffd9da64f8782545042884173a1d1e3":[async_test('html5lib_tests26.html c085683feffd9da64f8782545042884173a1d1e3'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Cb%3E1%3Cnobr%3E%3C/b%3E%3Ci%3E%3Cnobr%3E2%3C/i%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%221%22%0A%7C%20%20%20%20%20%20%20%3Cnobr%3E%0A%7C%20%20%20%20%20%3Cnobr%3E%0A%7C%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%3Cnobr%3E%0A%7C%20%20%20%20%20%20%20%20%20%222%22"],"be84971ac4a451e91099d225d0315dd17a88b830":[async_test('html5lib_tests26.html be84971ac4a451e91099d225d0315dd17a88b830'), "%3Cp%3E%3Ccode%20x%3C/code%3E%3C/p%3E%0A", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Ccode%3E%0A%7C%20%20%20%20%20%20%20%20%20code%3D%22%22%0A%7C%20%20%20%20%20%20%20%20%20x%3C%3D%22%22%0A%7C%20%20%20%20%20%3Ccode%3E%0A%7C%20%20%20%20%20%20%20code%3D%22%22%0A%7C%20%20%20%20%20%20%20x%3C%3D%22%22%0A%7C%20%20%20%20%20%20%20%22%0A%22"],"9d63346ca23dc3ee41e29fe7d8403934bce8c610":[async_test('html5lib_tests26.html 9d63346ca23dc3ee41e29fe7d8403934bce8c610'), "%3C%21DOCTYPE%20html%3E%3Csvg%3E%3CforeignObject%3E%3Cp%3E%3Ci%3E%3C/p%3Ea", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20foreignObject%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22a%22"],"8434eb9c0c3daf656b3158f5955d07e39ddc6444":[async_test('html5lib_tests26.html 8434eb9c0c3daf656b3158f5955d07e39ddc6444'), "%3C%21DOCTYPE%20html%3E%3Ctable%3E%3Ctr%3E%3Ctd%3E%3Csvg%3E%3CforeignObject%3E%3Cp%3E%3Ci%3E%3C/p%3Ea", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Csvg%20foreignObject%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22a%22"],"6c95a99290e309b638b958272686a21486fa561e":[async_test('html5lib_tests26.html 6c95a99290e309b638b958272686a21486fa561e'), "%3C%21DOCTYPE%20html%3E%3Cmath%3E%3Cmtext%3E%3Cp%3E%3Ci%3E%3C/p%3Ea", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20mtext%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22a%22"],"37d360649a2b092ad05e1be1c9ea65bfec83ca6d":[async_test('html5lib_tests26.html 37d360649a2b092ad05e1be1c9ea65bfec83ca6d'), "%3C%21DOCTYPE%20html%3E%3Ctable%3E%3Ctr%3E%3Ctd%3E%3Cmath%3E%3Cmtext%3E%3Cp%3E%3Ci%3E%3C/p%3Ea", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cmath%20mtext%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22a%22"],"8919621ebbd1f4df0fdaacee3e53dc959a2d9235":[async_test('html5lib_tests26.html 8919621ebbd1f4df0fdaacee3e53dc959a2d9235'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Cdiv%3E%3C%21/div%3Ea", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%3C%21--%20/div%20--%3E%0A%7C%20%20%20%20%20%20%20%22a%22"],"3723d028349cbbc1a5c3f014987bb11c8ba804d0":[async_test('html5lib_tests26.html 3723d028349cbbc1a5c3f014987bb11c8ba804d0'), "%3Cbutton%3E%3Cp%3E%3Cbutton%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cbutton%3E%0A%7C%20%20%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%3Cbutton%3E"],
+ }
+ init_tests(get_type());
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests3.html b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests3.html
new file mode 100644
index 00000000000..f6f9d629110
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests3.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf8">
+ <title>HTML 5 Parser tests html5lib_tests3.html</title>
+ <meta name="timeout" content="long">
+ <meta name="variant" content="?run_type=uri">
+ <meta name="variant" content="?run_type=write">
+ <meta name="variant" content="?run_type=write_single">
+ </head>
+ <body>
+ <h1>html5lib Parser Test</h1>
+ <div id="log"></div>
+ <script src="common.js"></script>
+ <script src="test.js"></script>
+ <script src="template.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ var num_iframes = 8;
+ var order = ['9af28bba864ad2e398d95249fdcd40491e91b23f','be8bf339f25c34d94456b39ceeed74a25167df40','b77d2b4c52c8d57dae80409a39f5e21cb8e5b3bc','7902929c3aa85bf8ffc8d7fa228921acec21808e','16dda22403dee14d6d8627d9139b8c5296f24b61','7022e121d090113a9b6a1f29e8c620b5b6c9b67c','8b5088252a41409e5f5989408f09af986573b007','692cef68475bc2c58dc3a1d6fc804ab69df37117','88bbb8a76e9880c09e8ffcd626660106cf27abce','b43510ea21c96a96255b45aef578af5cbc78475e','5227d81a48fc519767baaca384b9687dad7ba1bf','5bb12f29d0f7c9c30bc8ceb14578c60df73dca2c','9ba44cced626432a79929642154346ab9d01403a','f9031fcb39c793e24b116a1e041dd93ed638a0f4','45ec5c450b3039007112fcb053c2a82ce2e93f17','6a66abfc230b8cfc93c57210ae370b1d5e744b5a','ed9cc49cd8a577e1e6343808c328e242b53ee42d','32c5a1be682ae34b4195cd0481ee6c53c806abeb','daf731117bb7cf43f750f187cbb3528f07c9a012','948e2378d0e6bd68dbc278a993c2774c22b30370','f7fd80272bb4ab6e3bb871de5f7688912740c39f','9eddcf7971dc65d05f25aa4c412acf09a789e5b3','e91b512a3b3307481c8039279d5cf487aa258a9d','6d570cad6386f2e21419f5eb63e7dfa290abe40f',];
+ var tests = {
+ "9af28bba864ad2e398d95249fdcd40491e91b23f":[async_test('html5lib_tests3.html 9af28bba864ad2e398d95249fdcd40491e91b23f'), "%3Chead%3E%3C/head%3E%3Cstyle%3E%3C/style%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cstyle%3E%0A%7C%20%20%20%3Cbody%3E"],"be8bf339f25c34d94456b39ceeed74a25167df40":[async_test('html5lib_tests3.html be8bf339f25c34d94456b39ceeed74a25167df40'), "%3Chead%3E%3C/head%3E%3Cscript%3E%3C/script%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%3Cbody%3E"],"b77d2b4c52c8d57dae80409a39f5e21cb8e5b3bc":[async_test('html5lib_tests3.html b77d2b4c52c8d57dae80409a39f5e21cb8e5b3bc'), "%3Chead%3E%3C/head%3E%3C%21--%20--%3E%3Cstyle%3E%3C/style%3E%3C%21--%20--%3E%3Cscript%3E%3C/script%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cstyle%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%3C%21--%20%20%20--%3E%0A%7C%20%20%20%3C%21--%20%20%20--%3E%0A%7C%20%20%20%3Cbody%3E"],"7902929c3aa85bf8ffc8d7fa228921acec21808e":[async_test('html5lib_tests3.html 7902929c3aa85bf8ffc8d7fa228921acec21808e'), "%3Chead%3E%3C/head%3E%3C%21--%20--%3Ex%3Cstyle%3E%3C/style%3E%3C%21--%20--%3E%3Cscript%3E%3C/script%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3C%21--%20%20%20--%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22x%22%0A%7C%20%20%20%20%20%3Cstyle%3E%0A%7C%20%20%20%20%20%3C%21--%20%20%20--%3E%0A%7C%20%20%20%20%20%3Cscript%3E"],"16dda22403dee14d6d8627d9139b8c5296f24b61":[async_test('html5lib_tests3.html 16dda22403dee14d6d8627d9139b8c5296f24b61'), "%3C%21DOCTYPE%20html%3E%3Chtml%3E%3Chead%3E%3C/head%3E%3Cbody%3E%3Cpre%3E%0A%3C/pre%3E%3C/body%3E%3C/html%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cpre%3E"],"7022e121d090113a9b6a1f29e8c620b5b6c9b67c":[async_test('html5lib_tests3.html 7022e121d090113a9b6a1f29e8c620b5b6c9b67c'), "%3C%21DOCTYPE%20html%3E%3Chtml%3E%3Chead%3E%3C/head%3E%3Cbody%3E%3Cpre%3E%0Afoo%3C/pre%3E%3C/body%3E%3C/html%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cpre%3E%0A%7C%20%20%20%20%20%20%20%22foo%22"],"8b5088252a41409e5f5989408f09af986573b007":[async_test('html5lib_tests3.html 8b5088252a41409e5f5989408f09af986573b007'), "%3C%21DOCTYPE%20html%3E%3Chtml%3E%3Chead%3E%3C/head%3E%3Cbody%3E%3Cpre%3E%0A%0Afoo%3C/pre%3E%3C/body%3E%3C/html%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cpre%3E%0A%7C%20%20%20%20%20%20%20%22%0Afoo%22"],"692cef68475bc2c58dc3a1d6fc804ab69df37117":[async_test('html5lib_tests3.html 692cef68475bc2c58dc3a1d6fc804ab69df37117'), "%3C%21DOCTYPE%20html%3E%3Chtml%3E%3Chead%3E%3C/head%3E%3Cbody%3E%3Cpre%3E%0Afoo%0A%3C/pre%3E%3C/body%3E%3C/html%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cpre%3E%0A%7C%20%20%20%20%20%20%20%22foo%0A%22"],"88bbb8a76e9880c09e8ffcd626660106cf27abce":[async_test('html5lib_tests3.html 88bbb8a76e9880c09e8ffcd626660106cf27abce'), "%3C%21DOCTYPE%20html%3E%3Chtml%3E%3Chead%3E%3C/head%3E%3Cbody%3E%3Cpre%3Ex%3C/pre%3E%3Cspan%3E%0A%3C/span%3E%3C/body%3E%3C/html%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cpre%3E%0A%7C%20%20%20%20%20%20%20%22x%22%0A%7C%20%20%20%20%20%3Cspan%3E%0A%7C%20%20%20%20%20%20%20%22%0A%22"],"b43510ea21c96a96255b45aef578af5cbc78475e":[async_test('html5lib_tests3.html b43510ea21c96a96255b45aef578af5cbc78475e'), "%3C%21DOCTYPE%20html%3E%3Chtml%3E%3Chead%3E%3C/head%3E%3Cbody%3E%3Cpre%3Ex%0Ay%3C/pre%3E%3C/body%3E%3C/html%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cpre%3E%0A%7C%20%20%20%20%20%20%20%22x%0Ay%22"],"5227d81a48fc519767baaca384b9687dad7ba1bf":[async_test('html5lib_tests3.html 5227d81a48fc519767baaca384b9687dad7ba1bf'), "%3C%21DOCTYPE%20html%3E%3Chtml%3E%3Chead%3E%3C/head%3E%3Cbody%3E%3Cpre%3Ex%3Cdiv%3E%0Ay%3C/pre%3E%3C/body%3E%3C/html%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cpre%3E%0A%7C%20%20%20%20%20%20%20%22x%22%0A%7C%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%22%0Ay%22"],"5bb12f29d0f7c9c30bc8ceb14578c60df73dca2c":[async_test('html5lib_tests3.html 5bb12f29d0f7c9c30bc8ceb14578c60df73dca2c'), "%3C%21DOCTYPE%20html%3E%3Cpre%3E%26%23x0a%3B%26%23x0a%3BA%3C/pre%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cpre%3E%0A%7C%20%20%20%20%20%20%20%22%0AA%22"],"9ba44cced626432a79929642154346ab9d01403a":[async_test('html5lib_tests3.html 9ba44cced626432a79929642154346ab9d01403a'), "%3C%21DOCTYPE%20html%3E%3CHTML%3E%3CMETA%3E%3CHEAD%3E%3C/HEAD%3E%3C/HTML%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cmeta%3E%0A%7C%20%20%20%3Cbody%3E"],"f9031fcb39c793e24b116a1e041dd93ed638a0f4":[async_test('html5lib_tests3.html f9031fcb39c793e24b116a1e041dd93ed638a0f4'), "%3C%21DOCTYPE%20html%3E%3CHTML%3E%3CHEAD%3E%3Chead%3E%3C/HEAD%3E%3C/HTML%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"45ec5c450b3039007112fcb053c2a82ce2e93f17":[async_test('html5lib_tests3.html 45ec5c450b3039007112fcb053c2a82ce2e93f17'), "%3Ctextarea%3Efoo%3Cspan%3Ebar%3C/span%3E%3Ci%3Ebaz", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctextarea%3E%0A%7C%20%20%20%20%20%20%20%22foo%3Cspan%3Ebar%3C/span%3E%3Ci%3Ebaz%22"],"6a66abfc230b8cfc93c57210ae370b1d5e744b5a":[async_test('html5lib_tests3.html 6a66abfc230b8cfc93c57210ae370b1d5e744b5a'), "%3Ctitle%3Efoo%3Cspan%3Ebar%3C/em%3E%3Ci%3Ebaz", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Ctitle%3E%0A%7C%20%20%20%20%20%20%20%22foo%3Cspan%3Ebar%3C/em%3E%3Ci%3Ebaz%22%0A%7C%20%20%20%3Cbody%3E"],"ed9cc49cd8a577e1e6343808c328e242b53ee42d":[async_test('html5lib_tests3.html ed9cc49cd8a577e1e6343808c328e242b53ee42d'), "%3C%21DOCTYPE%20html%3E%3Ctextarea%3E%0A%3C/textarea%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctextarea%3E"],"32c5a1be682ae34b4195cd0481ee6c53c806abeb":[async_test('html5lib_tests3.html 32c5a1be682ae34b4195cd0481ee6c53c806abeb'), "%3C%21DOCTYPE%20html%3E%3Ctextarea%3E%0Afoo%3C/textarea%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctextarea%3E%0A%7C%20%20%20%20%20%20%20%22foo%22"],"daf731117bb7cf43f750f187cbb3528f07c9a012":[async_test('html5lib_tests3.html daf731117bb7cf43f750f187cbb3528f07c9a012'), "%3C%21DOCTYPE%20html%3E%3Ctextarea%3E%0A%0Afoo%3C/textarea%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctextarea%3E%0A%7C%20%20%20%20%20%20%20%22%0Afoo%22"],"948e2378d0e6bd68dbc278a993c2774c22b30370":[async_test('html5lib_tests3.html 948e2378d0e6bd68dbc278a993c2774c22b30370'), "%3C%21DOCTYPE%20html%3E%3Chtml%3E%3Chead%3E%3C/head%3E%3Cbody%3E%3Cul%3E%3Cli%3E%3Cdiv%3E%3Cp%3E%3Cli%3E%3C/ul%3E%3C/body%3E%3C/html%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cul%3E%0A%7C%20%20%20%20%20%20%20%3Cli%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cli%3E"],"f7fd80272bb4ab6e3bb871de5f7688912740c39f":[async_test('html5lib_tests3.html f7fd80272bb4ab6e3bb871de5f7688912740c39f'), "%3C%21doctype%20html%3E%3Cnobr%3E%3Cnobr%3E%3Cnobr%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cnobr%3E%0A%7C%20%20%20%20%20%3Cnobr%3E%0A%7C%20%20%20%20%20%3Cnobr%3E"],"9eddcf7971dc65d05f25aa4c412acf09a789e5b3":[async_test('html5lib_tests3.html 9eddcf7971dc65d05f25aa4c412acf09a789e5b3'), "%3C%21doctype%20html%3E%3Cnobr%3E%3Cnobr%3E%3C/nobr%3E%3Cnobr%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cnobr%3E%0A%7C%20%20%20%20%20%3Cnobr%3E%0A%7C%20%20%20%20%20%3Cnobr%3E"],"e91b512a3b3307481c8039279d5cf487aa258a9d":[async_test('html5lib_tests3.html e91b512a3b3307481c8039279d5cf487aa258a9d'), "%3C%21doctype%20html%3E%3Chtml%3E%3Cbody%3E%3Cp%3E%3Ctable%3E%3C/table%3E%3C/body%3E%3C/html%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%3Ctable%3E"],"6d570cad6386f2e21419f5eb63e7dfa290abe40f":[async_test('html5lib_tests3.html 6d570cad6386f2e21419f5eb63e7dfa290abe40f'), "%3Cp%3E%3Ctable%3E%3C/table%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Ctable%3E"],
+ }
+ init_tests(get_type());
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests5.html b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests5.html
new file mode 100644
index 00000000000..b1314ead67d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests5.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf8">
+ <title>HTML 5 Parser tests html5lib_tests5.html</title>
+ <meta name="timeout" content="long">
+ <meta name="variant" content="?run_type=uri">
+ <meta name="variant" content="?run_type=write">
+ <meta name="variant" content="?run_type=write_single">
+ </head>
+ <body>
+ <h1>html5lib Parser Test</h1>
+ <div id="log"></div>
+ <script src="common.js"></script>
+ <script src="test.js"></script>
+ <script src="template.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ var num_iframes = 8;
+ var order = ['c482a88c4feb445945f19c77eda5e460cd6db344','b28eaef63aeeb165eceb56152d50767327f975fa','20c1b55aabcd426fa5975648f21cff40fa3fc2e3','cc87be99b2531e4c0c1fd95f81cd4dd989f699d3','283a0f4eb33a3ee80f718020268bf1794a758ec9','bde8b7a035edd6f123f45708ac10b4f60e81edf4','6ace30add7690cda74de9830481c95bef1f5976d','3c5f82c8db30cc1cce4c7fa8a5d18cf13ce8d007','9cac6179dc295f43afd5a41ed98aef3a9d5a08de','021a5fbf8c725781d08dce099d21f7023c9bb26d','412eae0c0e6e5da254550debd587ff86cff55c0c','410a64500216425d811748b0258c92a49fbad0ff','bd7dfd1a0f74731c22b3e2d331f7c14ba7c9a4e8','5f847a390a413a42fcef3d4510ddc56815c7d722','6d5b2f84df760f8995146c406c2dd07ba5510f7f','eded02e700d7329f650a9a38ef7ea6c0e453766b',];
+ var tests = {
+ "c482a88c4feb445945f19c77eda5e460cd6db344":[async_test('html5lib_tests5.html c482a88c4feb445945f19c77eda5e460cd6db344'), "%3Cstyle%3E%20%3C%21--%20%3C/style%3Ex", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cstyle%3E%0A%7C%20%20%20%20%20%20%20%22%20%3C%21--%20%22%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22x%22"],"b28eaef63aeeb165eceb56152d50767327f975fa":[async_test('html5lib_tests5.html b28eaef63aeeb165eceb56152d50767327f975fa'), "%3Cstyle%3E%20%3C%21--%20%3C/style%3E%20--%3E%20%3C/style%3Ex", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cstyle%3E%0A%7C%20%20%20%20%20%20%20%22%20%3C%21--%20%22%0A%7C%20%20%20%20%20%22%20%22%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22--%3E%20x%22"],"20c1b55aabcd426fa5975648f21cff40fa3fc2e3":[async_test('html5lib_tests5.html 20c1b55aabcd426fa5975648f21cff40fa3fc2e3'), "%3Cstyle%3E%20%3C%21--%3E%20%3C/style%3Ex", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cstyle%3E%0A%7C%20%20%20%20%20%20%20%22%20%3C%21--%3E%20%22%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22x%22"],"cc87be99b2531e4c0c1fd95f81cd4dd989f699d3":[async_test('html5lib_tests5.html cc87be99b2531e4c0c1fd95f81cd4dd989f699d3'), "%3Cstyle%3E%20%3C%21---%3E%20%3C/style%3Ex", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cstyle%3E%0A%7C%20%20%20%20%20%20%20%22%20%3C%21---%3E%20%22%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22x%22"],"283a0f4eb33a3ee80f718020268bf1794a758ec9":[async_test('html5lib_tests5.html 283a0f4eb33a3ee80f718020268bf1794a758ec9'), "%3Ciframe%3E%20%3C%21---%3E%20%3C/iframe%3Ex", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ciframe%3E%0A%7C%20%20%20%20%20%20%20%22%20%3C%21---%3E%20%22%0A%7C%20%20%20%20%20%22x%22"],"bde8b7a035edd6f123f45708ac10b4f60e81edf4":[async_test('html5lib_tests5.html bde8b7a035edd6f123f45708ac10b4f60e81edf4'), "%3Ciframe%3E%20%3C%21---%20%3C/iframe%3E-%3Ex%3C/iframe%3E%20--%3E%20%3C/iframe%3Ex", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ciframe%3E%0A%7C%20%20%20%20%20%20%20%22%20%3C%21---%20%22%0A%7C%20%20%20%20%20%22-%3Ex%20--%3E%20x%22"],"6ace30add7690cda74de9830481c95bef1f5976d":[async_test('html5lib_tests5.html 6ace30add7690cda74de9830481c95bef1f5976d'), "%3Cscript%3E%20%3C%21--%20%3C/script%3E%20--%3E%20%3C/script%3Ex", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%20%3C%21--%20%22%0A%7C%20%20%20%20%20%22%20%22%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22--%3E%20x%22"],"3c5f82c8db30cc1cce4c7fa8a5d18cf13ce8d007":[async_test('html5lib_tests5.html 3c5f82c8db30cc1cce4c7fa8a5d18cf13ce8d007'), "%3Ctitle%3E%20%3C%21--%20%3C/title%3E%20--%3E%20%3C/title%3Ex", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Ctitle%3E%0A%7C%20%20%20%20%20%20%20%22%20%3C%21--%20%22%0A%7C%20%20%20%20%20%22%20%22%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22--%3E%20x%22"],"9cac6179dc295f43afd5a41ed98aef3a9d5a08de":[async_test('html5lib_tests5.html 9cac6179dc295f43afd5a41ed98aef3a9d5a08de'), "%3Ctextarea%3E%20%3C%21---%20%3C/textarea%3E-%3Ex%3C/textarea%3E%20--%3E%20%3C/textarea%3Ex", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctextarea%3E%0A%7C%20%20%20%20%20%20%20%22%20%3C%21---%20%22%0A%7C%20%20%20%20%20%22-%3Ex%20--%3E%20x%22"],"021a5fbf8c725781d08dce099d21f7023c9bb26d":[async_test('html5lib_tests5.html 021a5fbf8c725781d08dce099d21f7023c9bb26d'), "%3Cstyle%3E%20%3C%21%3C/--%20%3C/style%3Ex", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cstyle%3E%0A%7C%20%20%20%20%20%20%20%22%20%3C%21%3C/--%20%22%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22x%22"],"412eae0c0e6e5da254550debd587ff86cff55c0c":[async_test('html5lib_tests5.html 412eae0c0e6e5da254550debd587ff86cff55c0c'), "%3Cp%3E%3Cxmp%3E%3C/xmp%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%3Cxmp%3E"],"410a64500216425d811748b0258c92a49fbad0ff":[async_test('html5lib_tests5.html 410a64500216425d811748b0258c92a49fbad0ff'), "%3Cxmp%3E%20%3C%21--%20%3E%20--%3E%20%3C/xmp%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cxmp%3E%0A%7C%20%20%20%20%20%20%20%22%20%3C%21--%20%3E%20--%3E%20%22"],"bd7dfd1a0f74731c22b3e2d331f7c14ba7c9a4e8":[async_test('html5lib_tests5.html bd7dfd1a0f74731c22b3e2d331f7c14ba7c9a4e8'), "%3Ctitle%3E%26amp%3B%3C/title%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Ctitle%3E%0A%7C%20%20%20%20%20%20%20%22%26%22%0A%7C%20%20%20%3Cbody%3E"],"5f847a390a413a42fcef3d4510ddc56815c7d722":[async_test('html5lib_tests5.html 5f847a390a413a42fcef3d4510ddc56815c7d722'), "%3Ctitle%3E%3C%21--%26amp%3B--%3E%3C/title%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Ctitle%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%26--%3E%22%0A%7C%20%20%20%3Cbody%3E"],"6d5b2f84df760f8995146c406c2dd07ba5510f7f":[async_test('html5lib_tests5.html 6d5b2f84df760f8995146c406c2dd07ba5510f7f'), "%3Ctitle%3E%3C%21--%3C/title%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Ctitle%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%22%0A%7C%20%20%20%3Cbody%3E"],"eded02e700d7329f650a9a38ef7ea6c0e453766b":[async_test('html5lib_tests5.html eded02e700d7329f650a9a38ef7ea6c0e453766b'), "%3Cnoscript%3E%3C%21--%3C/noscript%3E--%3E%3C/noscript%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cnoscript%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%22%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22--%3E%22"],
+ }
+ init_tests(get_type());
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests6.html b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests6.html
new file mode 100644
index 00000000000..2bc2df75b08
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests6.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf8">
+ <title>HTML 5 Parser tests html5lib_tests6.html</title>
+ <meta name="timeout" content="long">
+ <meta name="variant" content="?run_type=uri">
+ <meta name="variant" content="?run_type=write">
+ <meta name="variant" content="?run_type=write_single">
+ </head>
+ <body>
+ <h1>html5lib Parser Test</h1>
+ <div id="log"></div>
+ <script src="common.js"></script>
+ <script src="test.js"></script>
+ <script src="template.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ var num_iframes = 8;
+ var order = ['d6280e971dd654968ee3c867bec8a3c7d1b885e5','c647c78bfe3660e1ea7d50a04440ed5ace26bd98','fa05c524ac7918197adf422a2c4be35d5eca9ddc','652ae0a8ca3ab725b2d10e9866898b3419333f64','03dad50ea8dd5ba10d8ed7c182e6ce5e654c02dc','3ef045a4e33856f8dac96feaf6f9b06df4bbb49e','fe9fca0f0d3f199ab59c8ef90017f34bcc670ecb','9f8748b72268a2f55e31f89ded4321c5aa4cfbb2','33832cc94bb649f53372c331cbf9234f9b131bec','cbec315b899132776db7598e77d306464e274d32','5a5e3a8ce3d91e10976d5f33b40a7f140b76bc36','ee14c28b79472014c7f456e7cf38a0d93d67b4d3','2d5d4c4867479737e6b5c45b0d5c5541b8353b88','2ea8b4e550e7f34dc52aec0b1870f3d729c20962','6d027310e96f9ac1628e4c67f49e0c690a009232','ad38bf32b77d3553168d6009b1b66029e59d8f80','78b741dafb63b9a5a78ad53915c4c4ee35d1ed9c','dbd7339544532dabb0b7a9136f6463a9c13c8897','5289376d3bace713fc7100577490c56e52dbfa46','ec71973ac3055b0dcfd47c0fc7e7dadc17cd6987','8c25d5edc43b61c47914db4e75a4d96bdd6b2be6','747c389eaf38370a1a7ec79bfeeb3b12c6512bfd','80e4700f134aa20d20eb82fd6cb35cb5846e0ce5','dd5e1c5216565fa8a816078e94528d7596cc2d68','b56b3db519a860b7d17e3bef387900a0d633d393','65a48cd67ebd59c603f45a5b9c2ad99a1ce2058a','64ef2f60587cbae9e7ffec9dc1a295ee4e1a116f','cec679ccf989d4a6985421a9cc301ebfa4667c23','4e48da4a2bca8ce4592e83eb0a076e7d61c297b0','3b2d876e5021de26cf6fdc8d76f6953d08d62180','fb1378f51de760693e7b779830d94033e93be24d','50adfdb7bde3e9bee16021cec1acadbe20858971','f9ca74f9f03a884b09d6a0cb6c53ff84807932e1','09f8c3624809ce2d40845ec3dea2bf6b95eadef2','f591efd2366066d4d02bb2f75bc7eb1151df3734','d25453a832050a3d5e5a908387901544ce92cc3b','5e2f65ba7616b7b909591edca14004e84db39220','8a5717873290cad9d9d67ad4785836bed8f93d35','3e215e4e155dec8d3d6a5a9190e78fce621083e1',];
+ var tests = {
+ "d6280e971dd654968ee3c867bec8a3c7d1b885e5":[async_test('html5lib_tests6.html d6280e971dd654968ee3c867bec8a3c7d1b885e5'), "%3C%21doctype%20html%3E%3C/head%3E%20%3Chead%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%22%20%22%0A%7C%20%20%20%3Cbody%3E"],"c647c78bfe3660e1ea7d50a04440ed5ace26bd98":[async_test('html5lib_tests6.html c647c78bfe3660e1ea7d50a04440ed5ace26bd98'), "%3C%21doctype%20html%3E%3Cform%3E%3Cdiv%3E%3C/form%3E%3Cdiv%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cform%3E%0A%7C%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cdiv%3E"],"fa05c524ac7918197adf422a2c4be35d5eca9ddc":[async_test('html5lib_tests6.html fa05c524ac7918197adf422a2c4be35d5eca9ddc'), "%3C%21doctype%20html%3E%3Ctitle%3E%26amp%3B%3C/title%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Ctitle%3E%0A%7C%20%20%20%20%20%20%20%22%26%22%0A%7C%20%20%20%3Cbody%3E"],"652ae0a8ca3ab725b2d10e9866898b3419333f64":[async_test('html5lib_tests6.html 652ae0a8ca3ab725b2d10e9866898b3419333f64'), "%3C%21doctype%20html%3E%3Ctitle%3E%3C%21--%26amp%3B--%3E%3C/title%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Ctitle%3E%0A%7C%20%20%20%20%20%20%20%22%3C%21--%26--%3E%22%0A%7C%20%20%20%3Cbody%3E"],"03dad50ea8dd5ba10d8ed7c182e6ce5e654c02dc":[async_test('html5lib_tests6.html 03dad50ea8dd5ba10d8ed7c182e6ce5e654c02dc'), "%3C%21doctype%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"3ef045a4e33856f8dac96feaf6f9b06df4bbb49e":[async_test('html5lib_tests6.html 3ef045a4e33856f8dac96feaf6f9b06df4bbb49e'), "%3C%21---x", "%23document%0A%7C%20%3C%21--%20-x%20--%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"fe9fca0f0d3f199ab59c8ef90017f34bcc670ecb":[async_test('html5lib_tests6.html fe9fca0f0d3f199ab59c8ef90017f34bcc670ecb'), "%3Cframeset%3E%3C/frameset%3E%0Afoo", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E%0A%7C%20%20%20%22%0A%22"],"9f8748b72268a2f55e31f89ded4321c5aa4cfbb2":[async_test('html5lib_tests6.html 9f8748b72268a2f55e31f89ded4321c5aa4cfbb2'), "%3Cframeset%3E%3C/frameset%3E%0A%3Cnoframes%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E%0A%7C%20%20%20%22%0A%22%0A%7C%20%20%20%3Cnoframes%3E"],"33832cc94bb649f53372c331cbf9234f9b131bec":[async_test('html5lib_tests6.html 33832cc94bb649f53372c331cbf9234f9b131bec'), "%3Cframeset%3E%3C/frameset%3E%0A%3Cdiv%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E%0A%7C%20%20%20%22%0A%22"],"cbec315b899132776db7598e77d306464e274d32":[async_test('html5lib_tests6.html cbec315b899132776db7598e77d306464e274d32'), "%3Cframeset%3E%3C/frameset%3E%0A%3C/html%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E%0A%7C%20%20%20%22%0A%22"],"5a5e3a8ce3d91e10976d5f33b40a7f140b76bc36":[async_test('html5lib_tests6.html 5a5e3a8ce3d91e10976d5f33b40a7f140b76bc36'), "%3Cframeset%3E%3C/frameset%3E%0A%3C/div%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E%0A%7C%20%20%20%22%0A%22"],"ee14c28b79472014c7f456e7cf38a0d93d67b4d3":[async_test('html5lib_tests6.html ee14c28b79472014c7f456e7cf38a0d93d67b4d3'), "%3Cform%3E%3Cform%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cform%3E"],"2d5d4c4867479737e6b5c45b0d5c5541b8353b88":[async_test('html5lib_tests6.html 2d5d4c4867479737e6b5c45b0d5c5541b8353b88'), "%3Cbutton%3E%3Cbutton%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cbutton%3E%0A%7C%20%20%20%20%20%3Cbutton%3E"],"2ea8b4e550e7f34dc52aec0b1870f3d729c20962":[async_test('html5lib_tests6.html 2ea8b4e550e7f34dc52aec0b1870f3d729c20962'), "%3Ctable%3E%3Ctr%3E%3Ctd%3E%3C/th%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E"],"6d027310e96f9ac1628e4c67f49e0c690a009232":[async_test('html5lib_tests6.html 6d027310e96f9ac1628e4c67f49e0c690a009232'), "%3Ctable%3E%3Ccaption%3E%3Ctd%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ccaption%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E"],"ad38bf32b77d3553168d6009b1b66029e59d8f80":[async_test('html5lib_tests6.html ad38bf32b77d3553168d6009b1b66029e59d8f80'), "%3Ctable%3E%3Ccaption%3E%3Cdiv%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ccaption%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cdiv%3E"],"78b741dafb63b9a5a78ad53915c4c4ee35d1ed9c":[async_test('html5lib_tests6.html 78b741dafb63b9a5a78ad53915c4c4ee35d1ed9c'), "%3Ctable%3E%3Ccaption%3E%3Cdiv%3E%3C/caption%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ccaption%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cdiv%3E"],"dbd7339544532dabb0b7a9136f6463a9c13c8897":[async_test('html5lib_tests6.html dbd7339544532dabb0b7a9136f6463a9c13c8897'), "%3Ctable%3E%3Ccaption%3E%3C/table%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ccaption%3E"],"5289376d3bace713fc7100577490c56e52dbfa46":[async_test('html5lib_tests6.html 5289376d3bace713fc7100577490c56e52dbfa46'), "%3Ctable%3E%3Ccaption%3E%3C/body%3E%3C/col%3E%3C/colgroup%3E%3C/html%3E%3C/tbody%3E%3C/td%3E%3C/tfoot%3E%3C/th%3E%3C/thead%3E%3C/tr%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ccaption%3E"],"ec71973ac3055b0dcfd47c0fc7e7dadc17cd6987":[async_test('html5lib_tests6.html ec71973ac3055b0dcfd47c0fc7e7dadc17cd6987'), "%3Ctable%3E%3Ccaption%3E%3Cdiv%3E%3C/div%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ccaption%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cdiv%3E"],"8c25d5edc43b61c47914db4e75a4d96bdd6b2be6":[async_test('html5lib_tests6.html 8c25d5edc43b61c47914db4e75a4d96bdd6b2be6'), "%3Ctable%3E%3Ctr%3E%3Ctd%3E%3C/body%3E%3C/caption%3E%3C/col%3E%3C/colgroup%3E%3C/html%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E"],"747c389eaf38370a1a7ec79bfeeb3b12c6512bfd":[async_test('html5lib_tests6.html 747c389eaf38370a1a7ec79bfeeb3b12c6512bfd'), "%3Ctable%3E%3Ccolgroup%3Efoo", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22foo%22%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ccolgroup%3E"],"80e4700f134aa20d20eb82fd6cb35cb5846e0ce5":[async_test('html5lib_tests6.html 80e4700f134aa20d20eb82fd6cb35cb5846e0ce5'), "%3Ctable%3E%3Ccolgroup%3E%3C/col%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ccolgroup%3E"],"dd5e1c5216565fa8a816078e94528d7596cc2d68":[async_test('html5lib_tests6.html dd5e1c5216565fa8a816078e94528d7596cc2d68'), "%3Cframeset%3E%3Cdiv%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E"],"b56b3db519a860b7d17e3bef387900a0d633d393":[async_test('html5lib_tests6.html b56b3db519a860b7d17e3bef387900a0d633d393'), "%3Cframeset%3E%3C/div%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E"],"65a48cd67ebd59c603f45a5b9c2ad99a1ce2058a":[async_test('html5lib_tests6.html 65a48cd67ebd59c603f45a5b9c2ad99a1ce2058a'), "%3Ctable%3E%3Ctr%3E%3Cdiv%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E"],"64ef2f60587cbae9e7ffec9dc1a295ee4e1a116f":[async_test('html5lib_tests6.html 64ef2f60587cbae9e7ffec9dc1a295ee4e1a116f'), "%3Ctable%3E%3Ctr%3E%3Cdiv%3E%3Ctd%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E"],"cec679ccf989d4a6985421a9cc301ebfa4667c23":[async_test('html5lib_tests6.html cec679ccf989d4a6985421a9cc301ebfa4667c23'), "%3Ctable%3E%3Ctbody%3E%3C/thead%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E"],"4e48da4a2bca8ce4592e83eb0a076e7d61c297b0":[async_test('html5lib_tests6.html 4e48da4a2bca8ce4592e83eb0a076e7d61c297b0'), "%3Ctable%3E%3Ctbody%3E%3C/body%3E%3C/caption%3E%3C/col%3E%3C/colgroup%3E%3C/html%3E%3C/td%3E%3C/th%3E%3C/tr%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E"],"3b2d876e5021de26cf6fdc8d76f6953d08d62180":[async_test('html5lib_tests6.html 3b2d876e5021de26cf6fdc8d76f6953d08d62180'), "%3Ctable%3E%3Ctbody%3E%3C/div%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E"],"fb1378f51de760693e7b779830d94033e93be24d":[async_test('html5lib_tests6.html fb1378f51de760693e7b779830d94033e93be24d'), "%3Ctable%3E%3Ctable%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%3Ctable%3E"],"50adfdb7bde3e9bee16021cec1acadbe20858971":[async_test('html5lib_tests6.html 50adfdb7bde3e9bee16021cec1acadbe20858971'), "%3Ctable%3E%3C/body%3E%3C/caption%3E%3C/col%3E%3C/colgroup%3E%3C/html%3E%3C/tbody%3E%3C/td%3E%3C/tfoot%3E%3C/th%3E%3C/thead%3E%3C/tr%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E"],"f9ca74f9f03a884b09d6a0cb6c53ff84807932e1":[async_test('html5lib_tests6.html f9ca74f9f03a884b09d6a0cb6c53ff84807932e1'), "%3Chtml%3E%3Cframeset%3E%3C/frameset%3E%3C/html%3E%20", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E%0A%7C%20%20%20%22%20%22"],"09f8c3624809ce2d40845ec3dea2bf6b95eadef2":[async_test('html5lib_tests6.html 09f8c3624809ce2d40845ec3dea2bf6b95eadef2'), "%3C%21DOCTYPE%20html%20PUBLIC%20%22-//W3C//DTD%20HTML%204.01//EN%22%3E%3Chtml%3E%3C/html%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%20%22-//W3C//DTD%20HTML%204.01//EN%22%20%22%22%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"f591efd2366066d4d02bb2f75bc7eb1151df3734":[async_test('html5lib_tests6.html f591efd2366066d4d02bb2f75bc7eb1151df3734'), "%3Cparam%3E%3Cframeset%3E%3C/frameset%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E"],"d25453a832050a3d5e5a908387901544ce92cc3b":[async_test('html5lib_tests6.html d25453a832050a3d5e5a908387901544ce92cc3b'), "%3Csource%3E%3Cframeset%3E%3C/frameset%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E"],"5e2f65ba7616b7b909591edca14004e84db39220":[async_test('html5lib_tests6.html 5e2f65ba7616b7b909591edca14004e84db39220'), "%3Ctrack%3E%3Cframeset%3E%3C/frameset%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E"],"8a5717873290cad9d9d67ad4785836bed8f93d35":[async_test('html5lib_tests6.html 8a5717873290cad9d9d67ad4785836bed8f93d35'), "%3C/html%3E%3Cframeset%3E%3C/frameset%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E"],"3e215e4e155dec8d3d6a5a9190e78fce621083e1":[async_test('html5lib_tests6.html 3e215e4e155dec8d3d6a5a9190e78fce621083e1'), "%3C/body%3E%3Cframeset%3E%3C/frameset%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E"],
+ }
+ init_tests(get_type());
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests7.html b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests7.html
new file mode 100644
index 00000000000..8a74e16edad
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests7.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf8">
+ <title>HTML 5 Parser tests html5lib_tests7.html</title>
+ <meta name="timeout" content="long">
+ <meta name="variant" content="?run_type=uri">
+ <meta name="variant" content="?run_type=write">
+ <meta name="variant" content="?run_type=write_single">
+ </head>
+ <body>
+ <h1>html5lib Parser Test</h1>
+ <div id="log"></div>
+ <script src="common.js"></script>
+ <script src="test.js"></script>
+ <script src="template.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ var num_iframes = 8;
+ var order = ['7cb496e242a4dc9aed321252b5ca6ebf4f02ebcd','c0cffec1e999db2aefb2f6beb679fd9620566dbd','7c644a6da21bfd551385b0a5044b82cf7be0a22f','52fde917ba333b89afeff0e31104421455f4bf1b','a8f53ca779c0e5fc484771c4ec2aa6fb6d609779','e4ce65a5fb6a3726b341ec94da583dee7c2c8232','8779e761986b4c724bfe73fee95b7972145fb4d3','620e44a8a55e82cec0d51e9d93025d8a5c4456fc','37b910b755c2df155a3129d5a1150f0c0fdd7934','868bff3a23219b836fdc702063d637f817ce65e1','a33a56f5571b4bcb23138ffb60df3824f5c53773','8ba11b54fa74a1c229d079b2902d6e33e139f33b','84e2152c284f4dfee7d8d12846c08b2c025578a6','8e3432411baa59cbef731ab3ba2703cb5d518453','e2f6144290512430ad25bbf9598eae77288c7b7a','350ebd648764d585f4aa0c29b925e6276579e9d0','9120ef80d3ee017007f3510121ddf7eba31b79e0','2026cd3ed42e41c168dd37c8c2675584f4eef335','ff2e324237e22efc8430ad7137d50d6d3d311820','02c9eb822611b0c206b544e0f2e5044695195ba8','cb3d1a50dd56a85135a0856cfa1c23a091ef2af4','13847685cfff75642823a0e78c6ef232ecb9d94b','99bb5e9a6e0daf62ba418dd97b5e8e3925f4137e','7a8e5ec2c95e725717c564dd49bfa86c2e1a88ba','17dcea170bb74d18ed4776dbb98f0bac6a11364d','9457c10c9f987bbc95937b34763fe956d61d237b','0fa23bb5d8b2a591afb1842b8f4c00c490c127b4','f6d60b3ae48e2b69b4c25125f9b5a3ab4867521b','5b0b3edcc3ce9fdc9f58eb62d326865ca0aab8c8',];
+ var tests = {
+ "7cb496e242a4dc9aed321252b5ca6ebf4f02ebcd":[async_test('html5lib_tests7.html 7cb496e242a4dc9aed321252b5ca6ebf4f02ebcd'), "%3C%21doctype%20html%3E%3Cbody%3E%3Ctitle%3EX%3C/title%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctitle%3E%0A%7C%20%20%20%20%20%20%20%22X%22"],"c0cffec1e999db2aefb2f6beb679fd9620566dbd":[async_test('html5lib_tests7.html c0cffec1e999db2aefb2f6beb679fd9620566dbd'), "%3C%21doctype%20html%3E%3Ctable%3E%3Ctitle%3EX%3C/title%3E%3C/table%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctitle%3E%0A%7C%20%20%20%20%20%20%20%22X%22%0A%7C%20%20%20%20%20%3Ctable%3E"],"7c644a6da21bfd551385b0a5044b82cf7be0a22f":[async_test('html5lib_tests7.html 7c644a6da21bfd551385b0a5044b82cf7be0a22f'), "%3C%21doctype%20html%3E%3Chead%3E%3C/head%3E%3Ctitle%3EX%3C/title%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Ctitle%3E%0A%7C%20%20%20%20%20%20%20%22X%22%0A%7C%20%20%20%3Cbody%3E"],"52fde917ba333b89afeff0e31104421455f4bf1b":[async_test('html5lib_tests7.html 52fde917ba333b89afeff0e31104421455f4bf1b'), "%3C%21doctype%20html%3E%3C/head%3E%3Ctitle%3EX%3C/title%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Ctitle%3E%0A%7C%20%20%20%20%20%20%20%22X%22%0A%7C%20%20%20%3Cbody%3E"],"a8f53ca779c0e5fc484771c4ec2aa6fb6d609779":[async_test('html5lib_tests7.html a8f53ca779c0e5fc484771c4ec2aa6fb6d609779'), "%3C%21doctype%20html%3E%3Ctable%3E%3Cmeta%3E%3C/table%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cmeta%3E%0A%7C%20%20%20%20%20%3Ctable%3E"],"e4ce65a5fb6a3726b341ec94da583dee7c2c8232":[async_test('html5lib_tests7.html e4ce65a5fb6a3726b341ec94da583dee7c2c8232'), "%3C%21doctype%20html%3E%3Ctable%3EX%3Ctr%3E%3Ctd%3E%3Ctable%3E%20%3Cmeta%3E%3C/table%3E%3C/table%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22X%22%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cmeta%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22%20%22"],"8779e761986b4c724bfe73fee95b7972145fb4d3":[async_test('html5lib_tests7.html 8779e761986b4c724bfe73fee95b7972145fb4d3'), "%3C%21doctype%20html%3E%3Chtml%3E%20%3Chead%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"620e44a8a55e82cec0d51e9d93025d8a5c4456fc":[async_test('html5lib_tests7.html 620e44a8a55e82cec0d51e9d93025d8a5c4456fc'), "%3C%21doctype%20html%3E%20%3Chead%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"37b910b755c2df155a3129d5a1150f0c0fdd7934":[async_test('html5lib_tests7.html 37b910b755c2df155a3129d5a1150f0c0fdd7934'), "%3C%21doctype%20html%3E%3Ctable%3E%3Cstyle%3E%20%3Ctr%3Ex%20%3C/style%3E%20%3C/table%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Cstyle%3E%0A%7C%20%20%20%20%20%20%20%20%20%22%20%3Ctr%3Ex%20%22%0A%7C%20%20%20%20%20%20%20%22%20%22"],"868bff3a23219b836fdc702063d637f817ce65e1":[async_test('html5lib_tests7.html 868bff3a23219b836fdc702063d637f817ce65e1'), "%3C%21doctype%20html%3E%3Ctable%3E%3CTBODY%3E%3Cscript%3E%20%3Ctr%3Ex%20%3C/script%3E%20%3C/table%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22%20%3Ctr%3Ex%20%22%0A%7C%20%20%20%20%20%20%20%20%20%22%20%22"],"a33a56f5571b4bcb23138ffb60df3824f5c53773":[async_test('html5lib_tests7.html a33a56f5571b4bcb23138ffb60df3824f5c53773'), "%3C%21doctype%20html%3E%3Cp%3E%3Capplet%3E%3Cp%3EX%3C/p%3E%3C/applet%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Capplet%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22X%22"],"8ba11b54fa74a1c229d079b2902d6e33e139f33b":[async_test('html5lib_tests7.html 8ba11b54fa74a1c229d079b2902d6e33e139f33b'), "%3C%21doctype%20html%3E%3Clisting%3E%0AX%3C/listing%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Clisting%3E%0A%7C%20%20%20%20%20%20%20%22X%22"],"84e2152c284f4dfee7d8d12846c08b2c025578a6":[async_test('html5lib_tests7.html 84e2152c284f4dfee7d8d12846c08b2c025578a6'), "%3C%21doctype%20html%3E%3Cselect%3E%3Cinput%3EX", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cselect%3E%0A%7C%20%20%20%20%20%3Cinput%3E%0A%7C%20%20%20%20%20%22X%22"],"8e3432411baa59cbef731ab3ba2703cb5d518453":[async_test('html5lib_tests7.html 8e3432411baa59cbef731ab3ba2703cb5d518453'), "%3C%21doctype%20html%3E%3Cselect%3E%3Cselect%3EX", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cselect%3E%0A%7C%20%20%20%20%20%22X%22"],"e2f6144290512430ad25bbf9598eae77288c7b7a":[async_test('html5lib_tests7.html e2f6144290512430ad25bbf9598eae77288c7b7a'), "%3C%21doctype%20html%3E%3Ctable%3E%3Cinput%20type%3DhidDEN%3E%3C/table%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Cinput%3E%0A%7C%20%20%20%20%20%20%20%20%20type%3D%22hidDEN%22"],"350ebd648764d585f4aa0c29b925e6276579e9d0":[async_test('html5lib_tests7.html 350ebd648764d585f4aa0c29b925e6276579e9d0'), "%3C%21doctype%20html%3E%3Ctable%3EX%3Cinput%20type%3DhidDEN%3E%3C/table%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22X%22%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Cinput%3E%0A%7C%20%20%20%20%20%20%20%20%20type%3D%22hidDEN%22"],"9120ef80d3ee017007f3510121ddf7eba31b79e0":[async_test('html5lib_tests7.html 9120ef80d3ee017007f3510121ddf7eba31b79e0'), "%3C%21doctype%20html%3E%3Ctable%3E%20%20%3Cinput%20type%3DhidDEN%3E%3C/table%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%22%20%20%22%0A%7C%20%20%20%20%20%20%20%3Cinput%3E%0A%7C%20%20%20%20%20%20%20%20%20type%3D%22hidDEN%22"],"2026cd3ed42e41c168dd37c8c2675584f4eef335":[async_test('html5lib_tests7.html 2026cd3ed42e41c168dd37c8c2675584f4eef335'), "%3C%21doctype%20html%3E%3Ctable%3E%20%20%3Cinput%20type%3D%27hidDEN%27%3E%3C/table%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%22%20%20%22%0A%7C%20%20%20%20%20%20%20%3Cinput%3E%0A%7C%20%20%20%20%20%20%20%20%20type%3D%22hidDEN%22"],"ff2e324237e22efc8430ad7137d50d6d3d311820":[async_test('html5lib_tests7.html ff2e324237e22efc8430ad7137d50d6d3d311820'), "%3C%21doctype%20html%3E%3Ctable%3E%3Cinput%20type%3D%22%20hidden%22%3E%3Cinput%20type%3DhidDEN%3E%3C/table%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cinput%3E%0A%7C%20%20%20%20%20%20%20type%3D%22%20hidden%22%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Cinput%3E%0A%7C%20%20%20%20%20%20%20%20%20type%3D%22hidDEN%22"],"02c9eb822611b0c206b544e0f2e5044695195ba8":[async_test('html5lib_tests7.html 02c9eb822611b0c206b544e0f2e5044695195ba8'), "%3C%21doctype%20html%3E%3Ctable%3E%3Cselect%3EX%3Ctr%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cselect%3E%0A%7C%20%20%20%20%20%20%20%22X%22%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E"],"cb3d1a50dd56a85135a0856cfa1c23a091ef2af4":[async_test('html5lib_tests7.html cb3d1a50dd56a85135a0856cfa1c23a091ef2af4'), "%3C%21doctype%20html%3E%3Cselect%3EX%3C/select%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cselect%3E%0A%7C%20%20%20%20%20%20%20%22X%22"],"13847685cfff75642823a0e78c6ef232ecb9d94b":[async_test('html5lib_tests7.html 13847685cfff75642823a0e78c6ef232ecb9d94b'), "%3C%21DOCTYPE%20hTmL%3E%3Chtml%3E%3C/html%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"99bb5e9a6e0daf62ba418dd97b5e8e3925f4137e":[async_test('html5lib_tests7.html 99bb5e9a6e0daf62ba418dd97b5e8e3925f4137e'), "%3C%21DOCTYPE%20HTML%3E%3Chtml%3E%3C/html%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"7a8e5ec2c95e725717c564dd49bfa86c2e1a88ba":[async_test('html5lib_tests7.html 7a8e5ec2c95e725717c564dd49bfa86c2e1a88ba'), "%3Cdiv%3E%3Cp%3Ea%3C/x%3E%20b", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%20%20%22a%20b%22"],"17dcea170bb74d18ed4776dbb98f0bac6a11364d":[async_test('html5lib_tests7.html 17dcea170bb74d18ed4776dbb98f0bac6a11364d'), "%3Ctable%3E%3Ctr%3E%3Ctd%3E%3Ccode%3E%3C/code%3E%20%3C/table%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ccode%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%22%20%22"],"9457c10c9f987bbc95937b34763fe956d61d237b":[async_test('html5lib_tests7.html 9457c10c9f987bbc95937b34763fe956d61d237b'), "%3Ctable%3E%3Cb%3E%3Ctr%3E%3Ctd%3Eaaa%3C/td%3E%3C/tr%3Ebbb%3C/table%3Eccc", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%22bbb%22%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%22aaa%22%0A%7C%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%22ccc%22"],"0fa23bb5d8b2a591afb1842b8f4c00c490c127b4":[async_test('html5lib_tests7.html 0fa23bb5d8b2a591afb1842b8f4c00c490c127b4'), "A%3Ctable%3E%3Ctr%3E%20B%3C/tr%3E%20B%3C/table%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22A%20B%20B%22%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E"],"f6d60b3ae48e2b69b4c25125f9b5a3ab4867521b":[async_test('html5lib_tests7.html f6d60b3ae48e2b69b4c25125f9b5a3ab4867521b'), "A%3Ctable%3E%3Ctr%3E%20B%3C/tr%3E%20%3C/em%3EC%3C/table%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22A%20BC%22%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%22%20%22"],"5b0b3edcc3ce9fdc9f58eb62d326865ca0aab8c8":[async_test('html5lib_tests7.html 5b0b3edcc3ce9fdc9f58eb62d326865ca0aab8c8'), "%3Cselect%3E%3Ckeygen%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cselect%3E%0A%7C%20%20%20%20%20%3Ckeygen%3E"],
+ }
+ init_tests(get_type());
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests8.html b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests8.html
new file mode 100644
index 00000000000..762533a8c14
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests8.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf8">
+ <title>HTML 5 Parser tests html5lib_tests8.html</title>
+ <meta name="timeout" content="long">
+ <meta name="variant" content="?run_type=uri">
+ <meta name="variant" content="?run_type=write">
+ <meta name="variant" content="?run_type=write_single">
+ </head>
+ <body>
+ <h1>html5lib Parser Test</h1>
+ <div id="log"></div>
+ <script src="common.js"></script>
+ <script src="test.js"></script>
+ <script src="template.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ var num_iframes = 8;
+ var order = ['5097f2cd0124cf5a23c7ccbe25f71a06966503df','0e11d51b0f71098caaccd166c368918c93683a7c','5c8ec9b2d6f03c2e971dc192897f3fcff92e5a32','a1fe2c2debb936fc1bf663f0d7228eb509522467','dbd09e012016b52703ab081360265d3bf96f3c76','a57d838264ec0d79c8b0c3cb1feb5cb941c0084d','263ff1438ee785d081669eea0fa110cca1d0d590','1ace730a87644923b11aa89e4e472cc5dd91edb7','26454c08b0d791754bf2f94fbee62624cae5fa5c',];
+ var tests = {
+ "5097f2cd0124cf5a23c7ccbe25f71a06966503df":[async_test('html5lib_tests8.html 5097f2cd0124cf5a23c7ccbe25f71a06966503df'), "%3Cdiv%3E%0A%3Cdiv%3E%3C/div%3E%0A%3C/span%3Ex", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%22%0A%22%0A%7C%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%22%0Ax%22"],"0e11d51b0f71098caaccd166c368918c93683a7c":[async_test('html5lib_tests8.html 0e11d51b0f71098caaccd166c368918c93683a7c'), "%3Cdiv%3Ex%3Cdiv%3E%3C/div%3E%0A%3C/span%3Ex", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%22x%22%0A%7C%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%22%0Ax%22"],"5c8ec9b2d6f03c2e971dc192897f3fcff92e5a32":[async_test('html5lib_tests8.html 5c8ec9b2d6f03c2e971dc192897f3fcff92e5a32'), "%3Cdiv%3Ex%3Cdiv%3E%3C/div%3Ex%3C/span%3Ex", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%22x%22%0A%7C%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%22xx%22"],"a1fe2c2debb936fc1bf663f0d7228eb509522467":[async_test('html5lib_tests8.html a1fe2c2debb936fc1bf663f0d7228eb509522467'), "%3Cdiv%3Ex%3Cdiv%3E%3C/div%3Ey%3C/span%3Ez", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%22x%22%0A%7C%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%22yz%22"],"dbd09e012016b52703ab081360265d3bf96f3c76":[async_test('html5lib_tests8.html dbd09e012016b52703ab081360265d3bf96f3c76'), "%3Ctable%3E%3Cdiv%3Ex%3Cdiv%3E%3C/div%3Ex%3C/span%3Ex", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%22x%22%0A%7C%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%22xx%22%0A%7C%20%20%20%20%20%3Ctable%3E"],"a57d838264ec0d79c8b0c3cb1feb5cb941c0084d":[async_test('html5lib_tests8.html a57d838264ec0d79c8b0c3cb1feb5cb941c0084d'), "x%3Ctable%3Ex", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22xx%22%0A%7C%20%20%20%20%20%3Ctable%3E"],"263ff1438ee785d081669eea0fa110cca1d0d590":[async_test('html5lib_tests8.html 263ff1438ee785d081669eea0fa110cca1d0d590'), "x%3Ctable%3E%3Ctable%3Ex", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22x%22%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%22x%22%0A%7C%20%20%20%20%20%3Ctable%3E"],"1ace730a87644923b11aa89e4e472cc5dd91edb7":[async_test('html5lib_tests8.html 1ace730a87644923b11aa89e4e472cc5dd91edb7'), "%3Cb%3Ea%3Cdiv%3E%3C/div%3E%3Cdiv%3E%3C/b%3Ey", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%22a%22%0A%7C%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%22y%22"],"26454c08b0d791754bf2f94fbee62624cae5fa5c":[async_test('html5lib_tests8.html 26454c08b0d791754bf2f94fbee62624cae5fa5c'), "%3Ca%3E%3Cdiv%3E%3Cp%3E%3C/a%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ca%3E"],
+ }
+ init_tests(get_type());
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests9.html b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests9.html
new file mode 100644
index 00000000000..8cd9132d16f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tests9.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf8">
+ <title>HTML 5 Parser tests html5lib_tests9.html</title>
+ <meta name="timeout" content="long">
+ <meta name="variant" content="?run_type=uri">
+ <meta name="variant" content="?run_type=write">
+ <meta name="variant" content="?run_type=write_single">
+ </head>
+ <body>
+ <h1>html5lib Parser Test</h1>
+ <div id="log"></div>
+ <script src="common.js"></script>
+ <script src="test.js"></script>
+ <script src="template.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ var num_iframes = 8;
+ var order = ['cb005f4b2a248cc98dc153d7391715b8d113cd0d','6b687e562bd878d3a6098f0a1b1c05b04dc8c02c','a28615629ac367bd8127ff3049e81b349e7ec7f6','d70e711bf9b7582d9b83488ab14f99b53a0f3a26','b2a8131e72e53265479c08cd18d4f4663278a021','a45a8948b799dadc321a86ff0bebf13167b5f076','9d6809ff0d5796525b655f44e8abe4267cfd84e1','2243c76da49f512eddbdf3f63965a70b8f3f5563','64ccbdfede00715ff2b6c0818d78774e0ea49fd4','58a5b5c13c3cc04948ca053afec1879602812beb','3be30b785cfbb6b1210720d032808e6484004fad','fe4054e577d1a3afa91c02b6782e35b76f2b3a50','9f12eef91092bcaaef567214144e1320b389296a','2f18900946d7a7f7922c929b72537e5ce8aacb70','2d4f10eec8e9623ef881edd20a639d3572134fd5','18485b14fd6568a096121ce8b8683a47945326d3','1d7a80644fe4b5f580c39adee71d5432cb186285','224e1bcb8030f0972c17d0fc68d912be17905e1c','e84d33cef974e49b69bdbc0c663c018a4dd010c0','5f4d3b90e4d99fae5ff97ebb9968185c77ffc591','00a77c689b7b8bb6440604f4273de3bfbcbcbe8b','15d4afd62caf2fcb27bb4aff89ba4fcb0e58c0b9','ef6c7a1da34520d2a4a90a0f2e8de9ed334bd482','0705988884bc08d8133e5d8a8eb693db5c86688e','093c0dbf464f9745c3730de57afebd9da308d34c','35aec8963beaced8149a74366eb9b1eb13be6717','931baaac96aab65ad0449b70c374ba56dcdbab9d',];
+ var tests = {
+ "cb005f4b2a248cc98dc153d7391715b8d113cd0d":[async_test('html5lib_tests9.html cb005f4b2a248cc98dc153d7391715b8d113cd0d'), "%3C%21DOCTYPE%20html%3E%3Cmath%3E%3C/math%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cmath%20math%3E"],"6b687e562bd878d3a6098f0a1b1c05b04dc8c02c":[async_test('html5lib_tests9.html 6b687e562bd878d3a6098f0a1b1c05b04dc8c02c'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Cmath%3E%3C/math%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cmath%20math%3E"],"a28615629ac367bd8127ff3049e81b349e7ec7f6":[async_test('html5lib_tests9.html a28615629ac367bd8127ff3049e81b349e7ec7f6'), "%3C%21DOCTYPE%20html%3E%3Cmath%3E%3Cmi%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20mi%3E"],"d70e711bf9b7582d9b83488ab14f99b53a0f3a26":[async_test('html5lib_tests9.html d70e711bf9b7582d9b83488ab14f99b53a0f3a26'), "%3C%21DOCTYPE%20html%3E%3Cmath%3E%3Cannotation-xml%3E%3Csvg%3E%3Cu%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20annotation-xml%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%3Cu%3E"],"b2a8131e72e53265479c08cd18d4f4663278a021":[async_test('html5lib_tests9.html b2a8131e72e53265479c08cd18d4f4663278a021'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Cselect%3E%3Cmath%3E%3C/math%3E%3C/select%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cselect%3E"],"a45a8948b799dadc321a86ff0bebf13167b5f076":[async_test('html5lib_tests9.html a45a8948b799dadc321a86ff0bebf13167b5f076'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Cselect%3E%3Coption%3E%3Cmath%3E%3C/math%3E%3C/option%3E%3C/select%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cselect%3E%0A%7C%20%20%20%20%20%20%20%3Coption%3E"],"9d6809ff0d5796525b655f44e8abe4267cfd84e1":[async_test('html5lib_tests9.html 9d6809ff0d5796525b655f44e8abe4267cfd84e1'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Ctable%3E%3Cmath%3E%3C/math%3E%3C/table%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%3Ctable%3E"],"2243c76da49f512eddbdf3f63965a70b8f3f5563":[async_test('html5lib_tests9.html 2243c76da49f512eddbdf3f63965a70b8f3f5563'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Ctable%3E%3Cmath%3E%3Cmi%3Efoo%3C/mi%3E%3C/math%3E%3C/table%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20mi%3E%0A%7C%20%20%20%20%20%20%20%20%20%22foo%22%0A%7C%20%20%20%20%20%3Ctable%3E"],"64ccbdfede00715ff2b6c0818d78774e0ea49fd4":[async_test('html5lib_tests9.html 64ccbdfede00715ff2b6c0818d78774e0ea49fd4'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Ctable%3E%3Cmath%3E%3Cmi%3Efoo%3C/mi%3E%3Cmi%3Ebar%3C/mi%3E%3C/math%3E%3C/table%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20mi%3E%0A%7C%20%20%20%20%20%20%20%20%20%22foo%22%0A%7C%20%20%20%20%20%20%20%3Cmath%20mi%3E%0A%7C%20%20%20%20%20%20%20%20%20%22bar%22%0A%7C%20%20%20%20%20%3Ctable%3E"],"58a5b5c13c3cc04948ca053afec1879602812beb":[async_test('html5lib_tests9.html 58a5b5c13c3cc04948ca053afec1879602812beb'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Ctable%3E%3Ctbody%3E%3Cmath%3E%3Cmi%3Efoo%3C/mi%3E%3Cmi%3Ebar%3C/mi%3E%3C/math%3E%3C/tbody%3E%3C/table%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20mi%3E%0A%7C%20%20%20%20%20%20%20%20%20%22foo%22%0A%7C%20%20%20%20%20%20%20%3Cmath%20mi%3E%0A%7C%20%20%20%20%20%20%20%20%20%22bar%22%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E"],"3be30b785cfbb6b1210720d032808e6484004fad":[async_test('html5lib_tests9.html 3be30b785cfbb6b1210720d032808e6484004fad'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Ctable%3E%3Ctbody%3E%3Ctr%3E%3Cmath%3E%3Cmi%3Efoo%3C/mi%3E%3Cmi%3Ebar%3C/mi%3E%3C/math%3E%3C/tr%3E%3C/tbody%3E%3C/table%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20mi%3E%0A%7C%20%20%20%20%20%20%20%20%20%22foo%22%0A%7C%20%20%20%20%20%20%20%3Cmath%20mi%3E%0A%7C%20%20%20%20%20%20%20%20%20%22bar%22%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E"],"fe4054e577d1a3afa91c02b6782e35b76f2b3a50":[async_test('html5lib_tests9.html fe4054e577d1a3afa91c02b6782e35b76f2b3a50'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Ctable%3E%3Ctbody%3E%3Ctr%3E%3Ctd%3E%3Cmath%3E%3Cmi%3Efoo%3C/mi%3E%3Cmi%3Ebar%3C/mi%3E%3C/math%3E%3C/td%3E%3C/tr%3E%3C/tbody%3E%3C/table%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cmath%20mi%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22foo%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cmath%20mi%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22bar%22"],"9f12eef91092bcaaef567214144e1320b389296a":[async_test('html5lib_tests9.html 9f12eef91092bcaaef567214144e1320b389296a'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Ctable%3E%3Ctbody%3E%3Ctr%3E%3Ctd%3E%3Cmath%3E%3Cmi%3Efoo%3C/mi%3E%3Cmi%3Ebar%3C/mi%3E%3C/math%3E%3Cp%3Ebaz%3C/td%3E%3C/tr%3E%3C/tbody%3E%3C/table%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cmath%20mi%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22foo%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cmath%20mi%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22bar%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22baz%22"],"2f18900946d7a7f7922c929b72537e5ce8aacb70":[async_test('html5lib_tests9.html 2f18900946d7a7f7922c929b72537e5ce8aacb70'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Ctable%3E%3Ccaption%3E%3Cmath%3E%3Cmi%3Efoo%3C/mi%3E%3Cmi%3Ebar%3C/mi%3E%3C/math%3E%3Cp%3Ebaz%3C/caption%3E%3C/table%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ccaption%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cmath%20mi%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%22foo%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cmath%20mi%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%22bar%22%0A%7C%20%20%20%20%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22baz%22"],"2d4f10eec8e9623ef881edd20a639d3572134fd5":[async_test('html5lib_tests9.html 2d4f10eec8e9623ef881edd20a639d3572134fd5'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Ctable%3E%3Ccaption%3E%3Cmath%3E%3Cmi%3Efoo%3C/mi%3E%3Cmi%3Ebar%3C/mi%3E%3Cp%3Ebaz%3C/table%3E%3Cp%3Equux", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ccaption%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cmath%20mi%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%22foo%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cmath%20mi%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%22bar%22%0A%7C%20%20%20%20%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22baz%22%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%22quux%22"],"18485b14fd6568a096121ce8b8683a47945326d3":[async_test('html5lib_tests9.html 18485b14fd6568a096121ce8b8683a47945326d3'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Ctable%3E%3Ccaption%3E%3Cmath%3E%3Cmi%3Efoo%3C/mi%3E%3Cmi%3Ebar%3C/mi%3Ebaz%3C/table%3E%3Cp%3Equux", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ccaption%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cmath%20mi%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%22foo%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cmath%20mi%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%22bar%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22baz%22%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%22quux%22"],"1d7a80644fe4b5f580c39adee71d5432cb186285":[async_test('html5lib_tests9.html 1d7a80644fe4b5f580c39adee71d5432cb186285'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Ctable%3E%3Ccolgroup%3E%3Cmath%3E%3Cmi%3Efoo%3C/mi%3E%3Cmi%3Ebar%3C/mi%3E%3Cp%3Ebaz%3C/table%3E%3Cp%3Equux", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20mi%3E%0A%7C%20%20%20%20%20%20%20%20%20%22foo%22%0A%7C%20%20%20%20%20%20%20%3Cmath%20mi%3E%0A%7C%20%20%20%20%20%20%20%20%20%22bar%22%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%22baz%22%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ccolgroup%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%22quux%22"],"224e1bcb8030f0972c17d0fc68d912be17905e1c":[async_test('html5lib_tests9.html 224e1bcb8030f0972c17d0fc68d912be17905e1c'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Ctable%3E%3Ctr%3E%3Ctd%3E%3Cselect%3E%3Cmath%3E%3Cmi%3Efoo%3C/mi%3E%3Cmi%3Ebar%3C/mi%3E%3Cp%3Ebaz%3C/table%3E%3Cp%3Equux", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cselect%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22foobarbaz%22%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%22quux%22"],"e84d33cef974e49b69bdbc0c663c018a4dd010c0":[async_test('html5lib_tests9.html e84d33cef974e49b69bdbc0c663c018a4dd010c0'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3Ctable%3E%3Cselect%3E%3Cmath%3E%3Cmi%3Efoo%3C/mi%3E%3Cmi%3Ebar%3C/mi%3E%3Cp%3Ebaz%3C/table%3E%3Cp%3Equux", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cselect%3E%0A%7C%20%20%20%20%20%20%20%22foobarbaz%22%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%22quux%22"],"5f4d3b90e4d99fae5ff97ebb9968185c77ffc591":[async_test('html5lib_tests9.html 5f4d3b90e4d99fae5ff97ebb9968185c77ffc591'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3C/body%3E%3C/html%3E%3Cmath%3E%3Cmi%3Efoo%3C/mi%3E%3Cmi%3Ebar%3C/mi%3E%3Cp%3Ebaz", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20mi%3E%0A%7C%20%20%20%20%20%20%20%20%20%22foo%22%0A%7C%20%20%20%20%20%20%20%3Cmath%20mi%3E%0A%7C%20%20%20%20%20%20%20%20%20%22bar%22%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%22baz%22"],"00a77c689b7b8bb6440604f4273de3bfbcbcbe8b":[async_test('html5lib_tests9.html 00a77c689b7b8bb6440604f4273de3bfbcbcbe8b'), "%3C%21DOCTYPE%20html%3E%3Cbody%3E%3C/body%3E%3Cmath%3E%3Cmi%3Efoo%3C/mi%3E%3Cmi%3Ebar%3C/mi%3E%3Cp%3Ebaz", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20mi%3E%0A%7C%20%20%20%20%20%20%20%20%20%22foo%22%0A%7C%20%20%20%20%20%20%20%3Cmath%20mi%3E%0A%7C%20%20%20%20%20%20%20%20%20%22bar%22%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%22baz%22"],"15d4afd62caf2fcb27bb4aff89ba4fcb0e58c0b9":[async_test('html5lib_tests9.html 15d4afd62caf2fcb27bb4aff89ba4fcb0e58c0b9'), "%3C%21DOCTYPE%20html%3E%3Cframeset%3E%3Cmath%3E%3Cmi%3E%3C/mi%3E%3Cmi%3E%3C/mi%3E%3Cp%3E%3Cspan%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E"],"ef6c7a1da34520d2a4a90a0f2e8de9ed334bd482":[async_test('html5lib_tests9.html ef6c7a1da34520d2a4a90a0f2e8de9ed334bd482'), "%3C%21DOCTYPE%20html%3E%3Cframeset%3E%3C/frameset%3E%3Cmath%3E%3Cmi%3E%3C/mi%3E%3Cmi%3E%3C/mi%3E%3Cp%3E%3Cspan%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E"],"0705988884bc08d8133e5d8a8eb693db5c86688e":[async_test('html5lib_tests9.html 0705988884bc08d8133e5d8a8eb693db5c86688e'), "%3C%21DOCTYPE%20html%3E%3Cbody%20xlink%3Ahref%3Dfoo%3E%3Cmath%20xlink%3Ahref%3Dfoo%3E%3C/math%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20xlink%3Ahref%3D%22foo%22%0A%7C%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20xlink%20href%3D%22foo%22"],"093c0dbf464f9745c3730de57afebd9da308d34c":[async_test('html5lib_tests9.html 093c0dbf464f9745c3730de57afebd9da308d34c'), "%3C%21DOCTYPE%20html%3E%3Cbody%20xlink%3Ahref%3Dfoo%20xml%3Alang%3Den%3E%3Cmath%3E%3Cmi%20xml%3Alang%3Den%20xlink%3Ahref%3Dfoo%3E%3C/mi%3E%3C/math%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20xlink%3Ahref%3D%22foo%22%0A%7C%20%20%20%20%20xml%3Alang%3D%22en%22%0A%7C%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20mi%3E%0A%7C%20%20%20%20%20%20%20%20%20xlink%20href%3D%22foo%22%0A%7C%20%20%20%20%20%20%20%20%20xml%20lang%3D%22en%22"],"35aec8963beaced8149a74366eb9b1eb13be6717":[async_test('html5lib_tests9.html 35aec8963beaced8149a74366eb9b1eb13be6717'), "%3C%21DOCTYPE%20html%3E%3Cbody%20xlink%3Ahref%3Dfoo%20xml%3Alang%3Den%3E%3Cmath%3E%3Cmi%20xml%3Alang%3Den%20xlink%3Ahref%3Dfoo%20/%3E%3C/math%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20xlink%3Ahref%3D%22foo%22%0A%7C%20%20%20%20%20xml%3Alang%3D%22en%22%0A%7C%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20mi%3E%0A%7C%20%20%20%20%20%20%20%20%20xlink%20href%3D%22foo%22%0A%7C%20%20%20%20%20%20%20%20%20xml%20lang%3D%22en%22"],"931baaac96aab65ad0449b70c374ba56dcdbab9d":[async_test('html5lib_tests9.html 931baaac96aab65ad0449b70c374ba56dcdbab9d'), "%3C%21DOCTYPE%20html%3E%3Cbody%20xlink%3Ahref%3Dfoo%20xml%3Alang%3Den%3E%3Cmath%3E%3Cmi%20xml%3Alang%3Den%20xlink%3Ahref%3Dfoo%20/%3Ebar%3C/math%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20xlink%3Ahref%3D%22foo%22%0A%7C%20%20%20%20%20xml%3Alang%3D%22en%22%0A%7C%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20mi%3E%0A%7C%20%20%20%20%20%20%20%20%20xlink%20href%3D%22foo%22%0A%7C%20%20%20%20%20%20%20%20%20xml%20lang%3D%22en%22%0A%7C%20%20%20%20%20%20%20%22bar%22"],
+ }
+ init_tests(get_type());
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tricky01.html b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tricky01.html
new file mode 100644
index 00000000000..f90e7f01f20
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_tricky01.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf8">
+ <title>HTML 5 Parser tests html5lib_tricky01.html</title>
+ <meta name="timeout" content="long">
+ <meta name="variant" content="?run_type=uri">
+ <meta name="variant" content="?run_type=write">
+ <meta name="variant" content="?run_type=write_single">
+ </head>
+ <body>
+ <h1>html5lib Parser Test</h1>
+ <div id="log"></div>
+ <script src="common.js"></script>
+ <script src="test.js"></script>
+ <script src="template.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ var num_iframes = 8;
+ var order = ['06f0a6904729cd6a3ab91f3121c0b0eb54ee04d2','c99581b7d1d8c1cd421054891981c3fe8267e83c','09ba1d973acb46344442ea1e77a37de8736ce6e7','9e40dd21a29521d60a43cb016f4100501ea26ec8','23bed40fe77c77e3119528d9f77e041eeb77eebb','eced3856a69153ad0408470634ee37c284670bcf','f12f21485b685300c282d5eab08fe35c634e7708','8626fa9be928ded0aa6438e32037ef365bfdabc1','ee4120938804980035bacecb2d2597ae8cf254ac',];
+ var tests = {
+ "06f0a6904729cd6a3ab91f3121c0b0eb54ee04d2":[async_test('html5lib_tricky01.html 06f0a6904729cd6a3ab91f3121c0b0eb54ee04d2'), "%3Cb%3E%3Cp%3EBold%20%3C/b%3E%20Not%20bold%3C/p%3E%0AAlso%20not%20bold.", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%22Bold%20%22%0A%7C%20%20%20%20%20%20%20%22%20Not%20bold%22%0A%7C%20%20%20%20%20%22%0AAlso%20not%20bold.%22"],"c99581b7d1d8c1cd421054891981c3fe8267e83c":[async_test('html5lib_tricky01.html c99581b7d1d8c1cd421054891981c3fe8267e83c'), "%3Chtml%3E%0A%3Cfont%20color%3Dred%3E%3Ci%3EItalic%20and%20Red%3Cp%3EItalic%20and%20Red%20%3C/font%3E%20Just%20italic.%3C/p%3E%20Italic%20only.%3C/i%3E%20Plain%0A%3Cp%3EI%20should%20not%20be%20red.%20%3Cfont%20color%3Dred%3ERed.%20%3Ci%3EItalic%20and%20red.%3C/p%3E%0A%3Cp%3EItalic%20and%20red.%20%3C/i%3E%20Red.%3C/font%3E%20I%20should%20not%20be%20red.%3C/p%3E%0A%3Cb%3EBold%20%3Ci%3EBold%20and%20italic%3C/b%3E%20Only%20Italic%20%3C/i%3E%20Plain", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20color%3D%22red%22%0A%7C%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%22Italic%20and%20Red%22%0A%7C%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20color%3D%22red%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22Italic%20and%20Red%20%22%0A%7C%20%20%20%20%20%20%20%20%20%22%20Just%20italic.%22%0A%7C%20%20%20%20%20%20%20%22%20Italic%20only.%22%0A%7C%20%20%20%20%20%22%20Plain%0A%22%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%22I%20should%20not%20be%20red.%20%22%0A%7C%20%20%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%20%20color%3D%22red%22%0A%7C%20%20%20%20%20%20%20%20%20%22Red.%20%22%0A%7C%20%20%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22Italic%20and%20red.%22%0A%7C%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20color%3D%22red%22%0A%7C%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%22%0A%22%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%20%20color%3D%22red%22%0A%7C%20%20%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22Italic%20and%20red.%20%22%0A%7C%20%20%20%20%20%20%20%20%20%22%20Red.%22%0A%7C%20%20%20%20%20%20%20%22%20I%20should%20not%20be%20red.%22%0A%7C%20%20%20%20%20%22%0A%22%0A%7C%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%22Bold%20%22%0A%7C%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%22Bold%20and%20italic%22%0A%7C%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%22%20Only%20Italic%20%22%0A%7C%20%20%20%20%20%22%20Plain%22"],"09ba1d973acb46344442ea1e77a37de8736ce6e7":[async_test('html5lib_tricky01.html 09ba1d973acb46344442ea1e77a37de8736ce6e7'), "%3Chtml%3E%3Cbody%3E%0A%3Cp%3E%3Cfont%20size%3D%227%22%3EFirst%20paragraph.%3C/p%3E%0A%3Cp%3ESecond%20paragraph.%3C/p%3E%3C/font%3E%0A%3Cb%3E%3Cp%3E%3Ci%3EBold%20and%20Italic%3C/b%3E%20Italic%3C/p%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22%0A%22%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%20%20size%3D%227%22%0A%7C%20%20%20%20%20%20%20%20%20%22First%20paragraph.%22%0A%7C%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20size%3D%227%22%0A%7C%20%20%20%20%20%20%20%22%0A%22%0A%7C%20%20%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%20%20%22Second%20paragraph.%22%0A%7C%20%20%20%20%20%22%0A%22%0A%7C%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22Bold%20and%20Italic%22%0A%7C%20%20%20%20%20%20%20%3Ci%3E%0A%7C%20%20%20%20%20%20%20%20%20%22%20Italic%22"],"9e40dd21a29521d60a43cb016f4100501ea26ec8":[async_test('html5lib_tricky01.html 9e40dd21a29521d60a43cb016f4100501ea26ec8'), "%3Chtml%3E%0A%3Cdl%3E%0A%3Cdt%3E%3Cb%3EBoo%0A%3Cdd%3EGoo%3F%0A%3C/dl%3E%0A%3C/html%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdl%3E%0A%7C%20%20%20%20%20%20%20%22%0A%22%0A%7C%20%20%20%20%20%20%20%3Cdt%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22Boo%0A%22%0A%7C%20%20%20%20%20%20%20%3Cdd%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22Goo%3F%0A%22%0A%7C%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%22%0A%22"],"23bed40fe77c77e3119528d9f77e041eeb77eebb":[async_test('html5lib_tricky01.html 23bed40fe77c77e3119528d9f77e041eeb77eebb'), "%3Chtml%3E%3Cbody%3E%0A%3Clabel%3E%3Ca%3E%3Cdiv%3EHello%3Cdiv%3EWorld%3C/div%3E%3C/a%3E%3C/label%3E%20%20%0A%3C/body%3E%3C/html%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22%0A%22%0A%7C%20%20%20%20%20%3Clabel%3E%0A%7C%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22Hello%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%22World%22%0A%7C%20%20%20%20%20%20%20%20%20%22%20%20%0A%22"],"eced3856a69153ad0408470634ee37c284670bcf":[async_test('html5lib_tricky01.html eced3856a69153ad0408470634ee37c284670bcf'), "%3Ctable%3E%3Ccenter%3E%20%3Cfont%3Ea%3C/center%3E%20%3Cimg%3E%20%3Ctr%3E%3Ctd%3E%20%3C/td%3E%20%3C/tr%3E%20%3C/table%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ccenter%3E%0A%7C%20%20%20%20%20%20%20%22%20%22%0A%7C%20%20%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%20%20%22a%22%0A%7C%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%3Cimg%3E%0A%7C%20%20%20%20%20%20%20%22%20%22%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%22%20%22%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%22%20%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22%20%22%0A%7C%20%20%20%20%20%20%20%20%20%22%20%22"],"f12f21485b685300c282d5eab08fe35c634e7708":[async_test('html5lib_tricky01.html f12f21485b685300c282d5eab08fe35c634e7708'), "%3Ctable%3E%3Ctr%3E%3Cp%3E%3Ca%3E%3Cp%3EYou%20should%20see%20this%20text.", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%22You%20should%20see%20this%20text.%22%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E"],"8626fa9be928ded0aa6438e32037ef365bfdabc1":[async_test('html5lib_tricky01.html 8626fa9be928ded0aa6438e32037ef365bfdabc1'), "%3CTABLE%3E%0A%3CTR%3E%0A%3CCENTER%3E%3CCENTER%3E%3CTD%3E%3C/TD%3E%3C/TR%3E%3CTR%3E%0A%3CFONT%3E%0A%3CTABLE%3E%3Ctr%3E%3C/tr%3E%3C/TABLE%3E%0A%3C/P%3E%0A%3Ca%3E%3C/font%3E%3Cfont%3E%3C/a%3E%0AThis%20page%20contains%20an%20insanely%20badly-nested%20tag%20sequence.", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ccenter%3E%0A%7C%20%20%20%20%20%20%20%3Ccenter%3E%0A%7C%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%22%0A%22%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%22%0A%22%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22%0A%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22%0A%22%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%22%0A%22%0A%7C%20%20%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%22%0A%22%0A%7C%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%22%0AThis%20page%20contains%20an%20insanely%20badly-nested%20tag%20sequence.%22"],"ee4120938804980035bacecb2d2597ae8cf254ac":[async_test('html5lib_tricky01.html ee4120938804980035bacecb2d2597ae8cf254ac'), "%3Chtml%3E%0A%3Cbody%3E%0A%3Cb%3E%3Cnobr%3E%3Cdiv%3EThis%20text%20is%20in%20a%20div%20inside%20a%20nobr%3C/nobr%3EMore%20text%20that%20should%20not%20be%20in%20the%20nobr%2C%20i.e.%2C%20the%0Anobr%20should%20have%20closed%20the%20div%20inside%20it%20implicitly.%20%3C/b%3E%3Cpre%3EA%20pre%20tag%20outside%20everything%20else.%3C/pre%3E%0A%3C/body%3E%0A%3C/html%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22%0A%22%0A%7C%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%3Cnobr%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cnobr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22This%20text%20is%20in%20a%20div%20inside%20a%20nobr%22%0A%7C%20%20%20%20%20%20%20%20%20%22More%20text%20that%20should%20not%20be%20in%20the%20nobr%2C%20i.e.%2C%20the%0Anobr%20should%20have%20closed%20the%20div%20inside%20it%20implicitly.%20%22%0A%7C%20%20%20%20%20%20%20%3Cpre%3E%0A%7C%20%20%20%20%20%20%20%20%20%22A%20pre%20tag%20outside%20everything%20else.%22%0A%7C%20%20%20%20%20%20%20%22%0A%0A%22"],
+ }
+ init_tests(get_type());
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_webkit01.html b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_webkit01.html
new file mode 100644
index 00000000000..43f07f59e54
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_webkit01.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf8">
+ <title>HTML 5 Parser tests html5lib_webkit01.html</title>
+ <meta name="timeout" content="long">
+ <meta name="variant" content="?run_type=uri">
+ <meta name="variant" content="?run_type=write">
+ <meta name="variant" content="?run_type=write_single">
+ </head>
+ <body>
+ <h1>html5lib Parser Test</h1>
+ <div id="log"></div>
+ <script src="common.js"></script>
+ <script src="test.js"></script>
+ <script src="template.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ var num_iframes = 8;
+ var order = ['4235382bf15f93f7dd1096832ae74cc71edef4d7','9906bb30ae08654f4c67bf6d97040abbca91082d','97974a9c541d97c7bb5bd8ba97c2ccbe0c6e55bd','f30960ce7d5b25adc846e47823f977616d38b296','f3ed3ec3a14058fd97c9aad83299bc8836d21283','f073fda1df7d917e37a207c326bdc4db0b4b3481','5533bf52e328c5748a203be1bb245848de592783','5b753a783c228a1b423152d9707cf900e57bc5da','eea9ac89544ec31fb78f7629ea0e065bd7422c98','03a99ca235d60b3191a3c5671ff7df5ffca5372d','c37bc2e44b2765025f58c9680a560c1a3dc3ab93','c6b4dc9c0041dd5a069741dbf228f03439115b8d','d4613a2b82f5d4ec251149508096f8071a8714d5','0f78a3fae382185ef9ac8f767efafb401249c1e1','375260e547e078df727a3669f5c8dcef7ccf71a7','3bea2bf663be5de2bbcdad57ac95c5933e266d42','19944775fd9dd871fbc4cf813eb105c29bc5d834','25b53e528a0ad0b002c8a26b7260213a24981860','ce59a8ae9cf138cb81fd017711097d1643c6f227','913071287591cc570d512c824b419d9a172d4339','2669743ff272e43978ac0f8a2f2c602ec9036c26','a9e759bf3ce415ad6216c58ee906639c03ffa03f','bbbea9a3752a36a64f2b62f15383406b16113fe7','e0910f26aac678f50612da8d05d20aa29e140655','f30a9e97cdf3c54ffccaa7b9c2067ff109317530','0d99b69e40dbb898cd4a188aa4920042c30815b4','a20991a86f6d34fd67ddb4002e3972d82230d879','006dbf89bfa3df51d837e7557c3e32dfbc6f0f4c','7e8f1399f9c87dbd103303c6051873079b265360','5081f4afe652b92f23e80d275f67dec9139df8e3','f904db0ad0c00794f8a2ca238b4c36084993c741','d56fcf271bf902fc4739f055f031f0d11620057c','a897ca0ad0492945709d0772c91e33d485ddf9c7','7274654c671e2e1715a017a239a98399496b7ba6','346ed4219453716e3fee23ccddf283fde408d349','4d1b6f58e6bb11d27e2097f656abdd1122a45a67','bb7bc3a43938aef67cffb49084f27cc678cd9b7a','992947d22821e1eb7b9116a99420b6c7f5ad46f2','88eca99701e0ad1fda391722e5f0cdcf1e2b667d','4b36a9545e5d8df93c447eaa8b1dc42d704d9c61','dc2437252e38b998fec43311653af309a65ef35f','ec499b1124d241faaa28e2f985ecf5f3fa00fcf8','cd236e537fa5d967d11efea30d96cd6ef6c9f46b','2ee90ed930fca8db8278161af28adde1e0c3907b','a785e349a36349db19df18c06032315c6356486c','401c8625b8574b46d03b8e95acd29358c82b53d3','1390b296dc6152683e9de9820194bca39e18cbd6','7dc7e88fa9eba71234bdb4037a15a4f70183a466',];
+ var tests = {
+ "4235382bf15f93f7dd1096832ae74cc71edef4d7":[async_test('html5lib_webkit01.html 4235382bf15f93f7dd1096832ae74cc71edef4d7'), "Test", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22Test%22"],"9906bb30ae08654f4c67bf6d97040abbca91082d":[async_test('html5lib_webkit01.html 9906bb30ae08654f4c67bf6d97040abbca91082d'), "%3Cdiv%3E%3C/div%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E"],"97974a9c541d97c7bb5bd8ba97c2ccbe0c6e55bd":[async_test('html5lib_webkit01.html 97974a9c541d97c7bb5bd8ba97c2ccbe0c6e55bd'), "%3Cdiv%3ETest%3C/div%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%22Test%22"],"f30960ce7d5b25adc846e47823f977616d38b296":[async_test('html5lib_webkit01.html f30960ce7d5b25adc846e47823f977616d38b296'), "%3Cdi", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"f3ed3ec3a14058fd97c9aad83299bc8836d21283":[async_test('html5lib_webkit01.html f3ed3ec3a14058fd97c9aad83299bc8836d21283'), "%3Cdiv%3EHello%3C/div%3E%0A%3Cscript%3E%0Aconsole.log%28%22PASS%22%29%3B%0A%3C/script%3E%0A%3Cdiv%3EBye%3C/div%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%22Hello%22%0A%7C%20%20%20%20%20%22%0A%22%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%0Aconsole.log%28%22PASS%22%29%3B%0A%22%0A%7C%20%20%20%20%20%22%0A%22%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%22Bye%22"],"f073fda1df7d917e37a207c326bdc4db0b4b3481":[async_test('html5lib_webkit01.html f073fda1df7d917e37a207c326bdc4db0b4b3481'), "%3Cdiv%20foo%3D%22bar%22%3EHello%3C/div%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20foo%3D%22bar%22%0A%7C%20%20%20%20%20%20%20%22Hello%22"],"5533bf52e328c5748a203be1bb245848de592783":[async_test('html5lib_webkit01.html 5533bf52e328c5748a203be1bb245848de592783'), "%3Cdiv%3EHello%3C/div%3E%0A%3Cscript%3E%0Aconsole.log%28%22FOO%3Cspan%3EBAR%3C/span%3EBAZ%22%29%3B%0A%3C/script%3E%0A%3Cdiv%3EBye%3C/div%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%22Hello%22%0A%7C%20%20%20%20%20%22%0A%22%0A%7C%20%20%20%20%20%3Cscript%3E%0A%7C%20%20%20%20%20%20%20%22%0Aconsole.log%28%22FOO%3Cspan%3EBAR%3C/span%3EBAZ%22%29%3B%0A%22%0A%7C%20%20%20%20%20%22%0A%22%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%22Bye%22"],"5b753a783c228a1b423152d9707cf900e57bc5da":[async_test('html5lib_webkit01.html 5b753a783c228a1b423152d9707cf900e57bc5da'), "%3Cfoo%20bar%3D%22baz%22%3E%3C/foo%3E%3Cpotato%20quack%3D%22duck%22%3E%3C/potato%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cfoo%3E%0A%7C%20%20%20%20%20%20%20bar%3D%22baz%22%0A%7C%20%20%20%20%20%3Cpotato%3E%0A%7C%20%20%20%20%20%20%20quack%3D%22duck%22"],"eea9ac89544ec31fb78f7629ea0e065bd7422c98":[async_test('html5lib_webkit01.html eea9ac89544ec31fb78f7629ea0e065bd7422c98'), "%3Cfoo%20bar%3D%22baz%22%3E%3Cpotato%20quack%3D%22duck%22%3E%3C/potato%3E%3C/foo%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cfoo%3E%0A%7C%20%20%20%20%20%20%20bar%3D%22baz%22%0A%7C%20%20%20%20%20%20%20%3Cpotato%3E%0A%7C%20%20%20%20%20%20%20%20%20quack%3D%22duck%22"],"03a99ca235d60b3191a3c5671ff7df5ffca5372d":[async_test('html5lib_webkit01.html 03a99ca235d60b3191a3c5671ff7df5ffca5372d'), "%3Cfoo%3E%3C/foo%20bar%3D%22baz%22%3E%3Cpotato%3E%3C/potato%20quack%3D%22duck%22%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cfoo%3E%0A%7C%20%20%20%20%20%3Cpotato%3E"],"c37bc2e44b2765025f58c9680a560c1a3dc3ab93":[async_test('html5lib_webkit01.html c37bc2e44b2765025f58c9680a560c1a3dc3ab93'), "%3C/%20tttt%3E", "%23document%0A%7C%20%3C%21--%20%20tttt%20--%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"c6b4dc9c0041dd5a069741dbf228f03439115b8d":[async_test('html5lib_webkit01.html c6b4dc9c0041dd5a069741dbf228f03439115b8d'), "%3Cdiv%20FOO%20%3E%3Cimg%3E%3Cimg%3E%3C/div%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20foo%3D%22%22%0A%7C%20%20%20%20%20%20%20%3Cimg%3E%0A%7C%20%20%20%20%20%20%20%3Cimg%3E"],"d4613a2b82f5d4ec251149508096f8071a8714d5":[async_test('html5lib_webkit01.html d4613a2b82f5d4ec251149508096f8071a8714d5'), "%3Cp%3ETest%3C/p%3Cp%3ETest2%3C/p%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%22TestTest2%22"],"0f78a3fae382185ef9ac8f767efafb401249c1e1":[async_test('html5lib_webkit01.html 0f78a3fae382185ef9ac8f767efafb401249c1e1'), "%3Crdar%3A//problem/6869687%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Crdar%3A%3E%0A%7C%20%20%20%20%20%20%206869687%3D%22%22%0A%7C%20%20%20%20%20%20%20problem%3D%22%22"],"375260e547e078df727a3669f5c8dcef7ccf71a7":[async_test('html5lib_webkit01.html 375260e547e078df727a3669f5c8dcef7ccf71a7'), "%3CA%3Etest%3C%20/A%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%22test%3C%20/A%3E%22"],"3bea2bf663be5de2bbcdad57ac95c5933e266d42":[async_test('html5lib_webkit01.html 3bea2bf663be5de2bbcdad57ac95c5933e266d42'), "%26lt%3B", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22%3C%22"],"19944775fd9dd871fbc4cf813eb105c29bc5d834":[async_test('html5lib_webkit01.html 19944775fd9dd871fbc4cf813eb105c29bc5d834'), "%3Cbody%20foo%3D%27bar%27%3E%3Cbody%20foo%3D%27baz%27%20yo%3D%27mama%27%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20foo%3D%22bar%22%0A%7C%20%20%20%20%20yo%3D%22mama%22"],"25b53e528a0ad0b002c8a26b7260213a24981860":[async_test('html5lib_webkit01.html 25b53e528a0ad0b002c8a26b7260213a24981860'), "%3Cbody%3E%3C/br%20foo%3D%22bar%22%3E%3C/body%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cbr%3E"],"ce59a8ae9cf138cb81fd017711097d1643c6f227":[async_test('html5lib_webkit01.html ce59a8ae9cf138cb81fd017711097d1643c6f227'), "%3Cbdy%3E%3Cbr%20foo%3D%22bar%22%3E%3C/body%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cbdy%3E%0A%7C%20%20%20%20%20%20%20%3Cbr%3E%0A%7C%20%20%20%20%20%20%20%20%20foo%3D%22bar%22"],"913071287591cc570d512c824b419d9a172d4339":[async_test('html5lib_webkit01.html 913071287591cc570d512c824b419d9a172d4339'), "%3Cbody%3E%3C/body%3E%3C/br%20foo%3D%22bar%22%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cbr%3E"],"2669743ff272e43978ac0f8a2f2c602ec9036c26":[async_test('html5lib_webkit01.html 2669743ff272e43978ac0f8a2f2c602ec9036c26'), "%3Cbdy%3E%3C/body%3E%3Cbr%20foo%3D%22bar%22%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cbdy%3E%0A%7C%20%20%20%20%20%20%20%3Cbr%3E%0A%7C%20%20%20%20%20%20%20%20%20foo%3D%22bar%22"],"a9e759bf3ce415ad6216c58ee906639c03ffa03f":[async_test('html5lib_webkit01.html a9e759bf3ce415ad6216c58ee906639c03ffa03f'), "%3Chtml%3E%3Cbody%3E%3C/body%3E%3C/html%3E%3C%21--%20Hi%20there%20--%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%3C%21--%20%20Hi%20there%20%20--%3E"],"bbbea9a3752a36a64f2b62f15383406b16113fe7":[async_test('html5lib_webkit01.html bbbea9a3752a36a64f2b62f15383406b16113fe7'), "%3Chtml%3E%3Cbody%3E%3C/body%3E%3C/html%3Ex%3C%21--%20Hi%20there%20--%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22x%22%0A%7C%20%20%20%20%20%3C%21--%20%20Hi%20there%20%20--%3E"],"e0910f26aac678f50612da8d05d20aa29e140655":[async_test('html5lib_webkit01.html e0910f26aac678f50612da8d05d20aa29e140655'), "%3Chtml%3E%3Cbody%3E%3C/body%3E%3C/html%3Ex%3C%21--%20Hi%20there%20--%3E%3C/html%3E%3C%21--%20Again%20--%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22x%22%0A%7C%20%20%20%20%20%3C%21--%20%20Hi%20there%20%20--%3E%0A%7C%20%3C%21--%20%20Again%20%20--%3E"],"f30a9e97cdf3c54ffccaa7b9c2067ff109317530":[async_test('html5lib_webkit01.html f30a9e97cdf3c54ffccaa7b9c2067ff109317530'), "%3Chtml%3E%3Cbody%3E%3C/body%3E%3C/html%3Ex%3C%21--%20Hi%20there%20--%3E%3C/body%3E%3C/html%3E%3C%21--%20Again%20--%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22x%22%0A%7C%20%20%20%20%20%3C%21--%20%20Hi%20there%20%20--%3E%0A%7C%20%3C%21--%20%20Again%20%20--%3E"],"0d99b69e40dbb898cd4a188aa4920042c30815b4":[async_test('html5lib_webkit01.html 0d99b69e40dbb898cd4a188aa4920042c30815b4'), "%3Chtml%3E%3Cbody%3E%3Cruby%3E%3Cdiv%3E%3Crp%3Exx%3C/rp%3E%3C/div%3E%3C/ruby%3E%3C/body%3E%3C/html%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cruby%3E%0A%7C%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Crp%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22xx%22"],"a20991a86f6d34fd67ddb4002e3972d82230d879":[async_test('html5lib_webkit01.html a20991a86f6d34fd67ddb4002e3972d82230d879'), "%3Chtml%3E%3Cbody%3E%3Cruby%3E%3Cdiv%3E%3Crt%3Exx%3C/rt%3E%3C/div%3E%3C/ruby%3E%3C/body%3E%3C/html%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cruby%3E%0A%7C%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Crt%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22xx%22"],"006dbf89bfa3df51d837e7557c3e32dfbc6f0f4c":[async_test('html5lib_webkit01.html 006dbf89bfa3df51d837e7557c3e32dfbc6f0f4c'), "%3Chtml%3E%3Cframeset%3E%3C%21--1--%3E%3Cnoframes%3EA%3C/noframes%3E%3C%21--2--%3E%3C/frameset%3E%3C%21--3--%3E%3Cnoframes%3EB%3C/noframes%3E%3C%21--4--%3E%3C/html%3E%3C%21--5--%3E%3Cnoframes%3EC%3C/noframes%3E%3C%21--6--%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E%0A%7C%20%20%20%20%20%3C%21--%201%20--%3E%0A%7C%20%20%20%20%20%3Cnoframes%3E%0A%7C%20%20%20%20%20%20%20%22A%22%0A%7C%20%20%20%20%20%3C%21--%202%20--%3E%0A%7C%20%20%20%3C%21--%203%20--%3E%0A%7C%20%20%20%3Cnoframes%3E%0A%7C%20%20%20%20%20%22B%22%0A%7C%20%20%20%3C%21--%204%20--%3E%0A%7C%20%20%20%3Cnoframes%3E%0A%7C%20%20%20%20%20%22C%22%0A%7C%20%3C%21--%205%20--%3E%0A%7C%20%3C%21--%206%20--%3E"],"7e8f1399f9c87dbd103303c6051873079b265360":[async_test('html5lib_webkit01.html 7e8f1399f9c87dbd103303c6051873079b265360'), "%3Cselect%3E%3Coption%3EA%3Cselect%3E%3Coption%3EB%3Cselect%3E%3Coption%3EC%3Cselect%3E%3Coption%3ED%3Cselect%3E%3Coption%3EE%3Cselect%3E%3Coption%3EF%3Cselect%3E%3Coption%3EG%3Cselect%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cselect%3E%0A%7C%20%20%20%20%20%20%20%3Coption%3E%0A%7C%20%20%20%20%20%20%20%20%20%22A%22%0A%7C%20%20%20%20%20%3Coption%3E%0A%7C%20%20%20%20%20%20%20%22B%22%0A%7C%20%20%20%20%20%20%20%3Cselect%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Coption%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22C%22%0A%7C%20%20%20%20%20%3Coption%3E%0A%7C%20%20%20%20%20%20%20%22D%22%0A%7C%20%20%20%20%20%20%20%3Cselect%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Coption%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22E%22%0A%7C%20%20%20%20%20%3Coption%3E%0A%7C%20%20%20%20%20%20%20%22F%22%0A%7C%20%20%20%20%20%20%20%3Cselect%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Coption%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22G%22"],"5081f4afe652b92f23e80d275f67dec9139df8e3":[async_test('html5lib_webkit01.html 5081f4afe652b92f23e80d275f67dec9139df8e3'), "%3Cdd%3E%3Cdd%3E%3Cdt%3E%3Cdt%3E%3Cdd%3E%3Cli%3E%3Cli%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdd%3E%0A%7C%20%20%20%20%20%3Cdd%3E%0A%7C%20%20%20%20%20%3Cdt%3E%0A%7C%20%20%20%20%20%3Cdt%3E%0A%7C%20%20%20%20%20%3Cdd%3E%0A%7C%20%20%20%20%20%20%20%3Cli%3E%0A%7C%20%20%20%20%20%20%20%3Cli%3E"],"f904db0ad0c00794f8a2ca238b4c36084993c741":[async_test('html5lib_webkit01.html f904db0ad0c00794f8a2ca238b4c36084993c741'), "%3Cdiv%3E%3Cb%3E%3C/div%3E%3Cdiv%3E%3Cnobr%3Ea%3Cnobr%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cnobr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22a%22%0A%7C%20%20%20%20%20%20%20%20%20%3Cnobr%3E"],"d56fcf271bf902fc4739f055f031f0d11620057c":[async_test('html5lib_webkit01.html d56fcf271bf902fc4739f055f031f0d11620057c'), "%3Chead%3E%3C/head%3E%0A%3Cbody%3E%3C/body%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%22%0A%22%0A%7C%20%20%20%3Cbody%3E"],"a897ca0ad0492945709d0772c91e33d485ddf9c7":[async_test('html5lib_webkit01.html a897ca0ad0492945709d0772c91e33d485ddf9c7'), "%3Chead%3E%3C/head%3E%20%3Cstyle%3E%3C/style%3Eddd", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%20%20%3Cstyle%3E%0A%7C%20%20%20%22%20%22%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22ddd%22"],"7274654c671e2e1715a017a239a98399496b7ba6":[async_test('html5lib_webkit01.html 7274654c671e2e1715a017a239a98399496b7ba6'), "%3Ckbd%3E%3Ctable%3E%3C/kbd%3E%3Ccol%3E%3Cselect%3E%3Ctr%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ckbd%3E%0A%7C%20%20%20%20%20%20%20%3Cselect%3E%0A%7C%20%20%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ccolgroup%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ccol%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctr%3E"],"346ed4219453716e3fee23ccddf283fde408d349":[async_test('html5lib_webkit01.html 346ed4219453716e3fee23ccddf283fde408d349'), "%3Ckbd%3E%3Ctable%3E%3C/kbd%3E%3Ccol%3E%3Cselect%3E%3Ctr%3E%3C/table%3E%3Cdiv%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ckbd%3E%0A%7C%20%20%20%20%20%20%20%3Cselect%3E%0A%7C%20%20%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ccolgroup%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ccol%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%3Cdiv%3E"],"4d1b6f58e6bb11d27e2097f656abdd1122a45a67":[async_test('html5lib_webkit01.html 4d1b6f58e6bb11d27e2097f656abdd1122a45a67'), "%3Ca%3E%3Cli%3E%3Cstyle%3E%3C/style%3E%3Ctitle%3E%3C/title%3E%3C/a%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%3Cli%3E%0A%7C%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cstyle%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctitle%3E"],"bb7bc3a43938aef67cffb49084f27cc678cd9b7a":[async_test('html5lib_webkit01.html bb7bc3a43938aef67cffb49084f27cc678cd9b7a'), "%3Cfont%3E%3C/p%3E%3Cp%3E%3Cmeta%3E%3Ctitle%3E%3C/title%3E%3C/font%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20%3Cfont%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cmeta%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctitle%3E"],"992947d22821e1eb7b9116a99420b6c7f5ad46f2":[async_test('html5lib_webkit01.html 992947d22821e1eb7b9116a99420b6c7f5ad46f2'), "%3Ca%3E%3Ccenter%3E%3Ctitle%3E%3C/title%3E%3Ca%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%3Ccenter%3E%0A%7C%20%20%20%20%20%20%20%3Ca%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctitle%3E%0A%7C%20%20%20%20%20%20%20%3Ca%3E"],"88eca99701e0ad1fda391722e5f0cdcf1e2b667d":[async_test('html5lib_webkit01.html 88eca99701e0ad1fda391722e5f0cdcf1e2b667d'), "%3Csvg%3E%3Ctitle%3E%3Cdiv%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20title%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cdiv%3E"],"4b36a9545e5d8df93c447eaa8b1dc42d704d9c61":[async_test('html5lib_webkit01.html 4b36a9545e5d8df93c447eaa8b1dc42d704d9c61'), "%3Csvg%3E%3Ctitle%3E%3Crect%3E%3Cdiv%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20title%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Crect%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%3E"],"dc2437252e38b998fec43311653af309a65ef35f":[async_test('html5lib_webkit01.html dc2437252e38b998fec43311653af309a65ef35f'), "%3Csvg%3E%3Ctitle%3E%3Csvg%3E%3Cdiv%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20title%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cdiv%3E"],"ec499b1124d241faaa28e2f985ecf5f3fa00fcf8":[async_test('html5lib_webkit01.html ec499b1124d241faaa28e2f985ecf5f3fa00fcf8'), "%3Cimg%20%3C%3D%22%22%20FAIL%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cimg%3E%0A%7C%20%20%20%20%20%20%20%3C%3D%22%22%0A%7C%20%20%20%20%20%20%20fail%3D%22%22"],"cd236e537fa5d967d11efea30d96cd6ef6c9f46b":[async_test('html5lib_webkit01.html cd236e537fa5d967d11efea30d96cd6ef6c9f46b'), "%3Cul%3E%3Cli%3E%3Cdiv%20id%3D%27foo%27/%3EA%3C/li%3E%3Cli%3EB%3Cdiv%3EC%3C/div%3E%3C/li%3E%3C/ul%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cul%3E%0A%7C%20%20%20%20%20%20%20%3Cli%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20id%3D%22foo%22%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22A%22%0A%7C%20%20%20%20%20%20%20%3Cli%3E%0A%7C%20%20%20%20%20%20%20%20%20%22B%22%0A%7C%20%20%20%20%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22C%22"],"2ee90ed930fca8db8278161af28adde1e0c3907b":[async_test('html5lib_webkit01.html 2ee90ed930fca8db8278161af28adde1e0c3907b'), "%3Csvg%3E%3Cem%3E%3Cdesc%3E%3C/em%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%3Cem%3E%0A%7C%20%20%20%20%20%20%20%3Cdesc%3E"],"a785e349a36349db19df18c06032315c6356486c":[async_test('html5lib_webkit01.html a785e349a36349db19df18c06032315c6356486c'), "%3Csvg%3E%3Ctfoot%3E%3C/mi%3E%3Ctd%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Csvg%20svg%3E%0A%7C%20%20%20%20%20%20%20%3Csvg%20tfoot%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Csvg%20td%3E"],"401c8625b8574b46d03b8e95acd29358c82b53d3":[async_test('html5lib_webkit01.html 401c8625b8574b46d03b8e95acd29358c82b53d3'), "%3Cmath%3E%3Cmrow%3E%3Cmrow%3E%3Cmn%3E1%3C/mn%3E%3C/mrow%3E%3Cmi%3Ea%3C/mi%3E%3C/mrow%3E%3C/math%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cmath%20math%3E%0A%7C%20%20%20%20%20%20%20%3Cmath%20mrow%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cmath%20mrow%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Cmath%20mn%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%221%22%0A%7C%20%20%20%20%20%20%20%20%20%3Cmath%20mi%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%22a%22"],"1390b296dc6152683e9de9820194bca39e18cbd6":[async_test('html5lib_webkit01.html 1390b296dc6152683e9de9820194bca39e18cbd6'), "%3C%21doctype%20html%3E%3Cinput%20type%3D%22hidden%22%3E%3Cframeset%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cframeset%3E"],"7dc7e88fa9eba71234bdb4037a15a4f70183a466":[async_test('html5lib_webkit01.html 7dc7e88fa9eba71234bdb4037a15a4f70183a466'), "%3C%21doctype%20html%3E%3Cinput%20type%3D%22button%22%3E%3Cframeset%3E", "%23document%0A%7C%20%3C%21DOCTYPE%20html%3E%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cinput%3E%0A%7C%20%20%20%20%20%20%20type%3D%22button%22"],
+ }
+ init_tests(get_type());
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_webkit02.html b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_webkit02.html
new file mode 100644
index 00000000000..2d324eb7c05
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/html5lib_webkit02.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf8">
+ <title>HTML 5 Parser tests html5lib_webkit02.html</title>
+ <meta name="timeout" content="long">
+ <meta name="variant" content="?run_type=uri">
+ <meta name="variant" content="?run_type=write">
+ <meta name="variant" content="?run_type=write_single">
+ </head>
+ <body>
+ <h1>html5lib Parser Test</h1>
+ <div id="log"></div>
+ <script src="common.js"></script>
+ <script src="test.js"></script>
+ <script src="template.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ var num_iframes = 8;
+ var order = ['f50b8c15847159a6d2c6ecc2bd1e4a944ba5aae6','326328ea805a2ebdde707e08567713f88a4cf8ab','05138397908cfdad69a3bfe5da5a06098320b504','2aaa2ac0d7cec6144633d8f82f3bcaafa7498cd9','4a256d7ef602c7c917c758e15981b9710f9b4130','98cea04429ddbe4ffaaa0b91fe77b8c0b1f7c1f4','209ad7d6f6c9c53cb856c7d78b2bc4a7f38abd5f','cb9a86fbac96b08a6e708a2dbcd9f78539dfe9c6',];
+ var tests = {
+ "f50b8c15847159a6d2c6ecc2bd1e4a944ba5aae6":[async_test('html5lib_webkit02.html f50b8c15847159a6d2c6ecc2bd1e4a944ba5aae6'), "%3Cfoo%20bar%3Dqux/%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cfoo%3E%0A%7C%20%20%20%20%20%20%20bar%3D%22qux/%22"],"326328ea805a2ebdde707e08567713f88a4cf8ab":[async_test('html5lib_webkit02.html 326328ea805a2ebdde707e08567713f88a4cf8ab'), "%3Cp%20id%3D%22status%22%3E%3Cnoscript%3E%3Cstrong%3EA%3C/strong%3E%3C/noscript%3E%3Cspan%3EB%3C/span%3E%3C/p%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cp%3E%0A%7C%20%20%20%20%20%20%20id%3D%22status%22%0A%7C%20%20%20%20%20%20%20%3Cnoscript%3E%0A%7C%20%20%20%20%20%20%20%20%20%22%3Cstrong%3EA%3C/strong%3E%22%0A%7C%20%20%20%20%20%20%20%3Cspan%3E%0A%7C%20%20%20%20%20%20%20%20%20%22B%22"],"05138397908cfdad69a3bfe5da5a06098320b504":[async_test('html5lib_webkit02.html 05138397908cfdad69a3bfe5da5a06098320b504'), "%3Cdiv%3E%3Csarcasm%3E%3Cdiv%3E%3C/div%3E%3C/sarcasm%3E%3C/div%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Cdiv%3E%0A%7C%20%20%20%20%20%20%20%3Csarcasm%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Cdiv%3E"],"2aaa2ac0d7cec6144633d8f82f3bcaafa7498cd9":[async_test('html5lib_webkit02.html 2aaa2ac0d7cec6144633d8f82f3bcaafa7498cd9'), "%3Chtml%3E%3Cbody%3E%3Cimg%20src%3D%22%22%20border%3D%220%22%20alt%3D%22%3E%3Cdiv%3EA%3C/div%3E%3C/body%3E%3C/html%3E", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E"],"4a256d7ef602c7c917c758e15981b9710f9b4130":[async_test('html5lib_webkit02.html 4a256d7ef602c7c917c758e15981b9710f9b4130'), "%3Ctable%3E%3Ctd%3E%3C/tbody%3EA", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%22A%22%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E"],"98cea04429ddbe4ffaaa0b91fe77b8c0b1f7c1f4":[async_test('html5lib_webkit02.html 98cea04429ddbe4ffaaa0b91fe77b8c0b1f7c1f4'), "%3Ctable%3E%3Ctd%3E%3C/thead%3EA", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%22A%22"],"209ad7d6f6c9c53cb856c7d78b2bc4a7f38abd5f":[async_test('html5lib_webkit02.html 209ad7d6f6c9c53cb856c7d78b2bc4a7f38abd5f'), "%3Ctable%3E%3Ctd%3E%3C/tfoot%3EA", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Ctbody%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%22A%22"],"cb9a86fbac96b08a6e708a2dbcd9f78539dfe9c6":[async_test('html5lib_webkit02.html cb9a86fbac96b08a6e708a2dbcd9f78539dfe9c6'), "%3Ctable%3E%3Cthead%3E%3Ctd%3E%3C/tbody%3EA", "%23document%0A%7C%20%3Chtml%3E%0A%7C%20%20%20%3Chead%3E%0A%7C%20%20%20%3Cbody%3E%0A%7C%20%20%20%20%20%3Ctable%3E%0A%7C%20%20%20%20%20%20%20%3Cthead%3E%0A%7C%20%20%20%20%20%20%20%20%20%3Ctr%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%3Ctd%3E%0A%7C%20%20%20%20%20%20%20%20%20%20%20%20%20%22A%22"],
+ }
+ init_tests(get_type());
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/math-parse01.html b/tests/wpt/web-platform-tests/html/syntax/parsing/math-parse01.html
new file mode 100644
index 00000000000..3aff716d9f7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/math-parse01.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>math in html: parsing</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<h1>math in html: parsing</h1>
+
+<div id="log" style="display:block"></div>
+
+<div style="display:none">
+<div><math id="m1"><mtext/></math></div>
+<div id="d1"><math><mrow/><mi/></math></div>
+<div id="d2"><math><mrow><mrow><mn>1</mn></mrow><mi>a</mi></mrow></math></div>
+<div id="d3">&lang;&rang;</div>
+<div id="d4">&Kopf;</div>
+<div id="d5"><math><semantics><mi>a</mi><annotation-xml><foo/><bar/></annotation-xml></semantics></math></div>
+<div id="d6"><math><semantics><mi>a</mi><annotation-xml encoding="text/html"><div></div></annotation-xml></semantics><mn/></math>
+</div>
+
+
+<script>
+
+test(function() {
+assert_equals(document.getElementById("m1"),document.getElementsByTagName("math")[0]);
+},"The id attribute should be recognised on math elements");
+
+test(function() {
+assert_equals(document.getElementById("d1").firstChild.nodeName,"math")
+},"The node name should be math");
+
+test(function() {
+assert_equals(document.getElementById("d1").firstChild.namespaceURI ,"http://www.w3.org/1998/Math/MathML")
+},"math should be in MathML Namespace");
+
+test(function() {
+assert_equals(document.getElementById("d1").firstChild.childNodes.length ,2)
+},"Math has 2 children (empty tag syntax)");
+
+test(function() {
+assert_equals(document.getElementById("d2").firstChild.childNodes.length ,1)
+},"Nested mrow elements should be parsed correctly");
+
+test(function() {
+assert_equals(document.getElementById("d3").firstChild.nodeValue ,"\u27E8\u27E9")
+},"Testing rang and lang entity code points");
+
+test(function() {
+assert_equals(document.getElementById("d4").firstChild.nodeValue ,"\uD835\uDD42")
+},"Testing Kopf (Plane 1) entity code point");
+
+test(function() {
+assert_equals(document.getElementById("d5").firstChild.firstChild.childNodes[1].childNodes.length ,2)
+},"Empty element tags in annotation-xml parsed as per XML.");
+
+test(function() {
+assert_equals(document.getElementById("d6").firstChild.childNodes.length ,2)
+},"html tags allowed in annotation-xml/@encoding='text/html'.");
+
+</script>
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/math-parse03.html b/tests/wpt/web-platform-tests/html/syntax/parsing/math-parse03.html
new file mode 100755
index 00000000000..a3dbdc4e61a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/math-parse03.html
@@ -0,0 +1,132 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>math in html: parsing</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<h1>math in html: parsing</h1>
+
+<div id="log"></div>
+
+<div>
+<div><MATH id="m1"><Mtext/></math></div>
+<div id="d1"><math><MI MATHVARIANT="BOLD" /></math></div>
+<div id="d2"><math><semantics DEFINITIONurl="www.example.org/FOO"><mi>a</mi><annotation-xml><foo/><bar/></annotation-xml></semantics></math></div>
+<div><math id="m3span-mtext"><mtext><Span>x</Span></mtext></math></div>
+<div><math id="m3span-mi"><mi><Span>x</Span></mi></math></div>
+<div><math id="m3span-mrow"><mi><Span>x</Span></mrow></math></div>
+<div><math id="m3p-mtext"><mtext><P>x</P></mtext></math></div>
+<div><math id="m3p-mi"><mi><P>x</P></mi></math></div>
+<div id="d3p-mrow"><math><mrow><P>x</P><mi>y</mi></mrow></math></div>
+<div><math id="m4"><mtext><Undefinedelement>x</Undefinedelement></mtext></math></div>
+<div><math id="m5"><mtext><mi>x</mi></mtext></math></div>
+<div><math><semantics><mi>x</mi>
+ <annotation-xml><p id="p6default">x</p></annotation-xml>
+ </semantics></math></div>
+<div><math><semantics><mi>x</mi>
+ <annotation-xml encoding=text/html><p id="p6texthtml">x</p></annotation-xml>
+ </semantics></math></div>
+<div><math><semantics><mi>x</mi>
+ <annotation-xml encoding=TEXT/HTML><p id="p6uctexthtml">x</p></annotation-xml>
+ </semantics></math></div>
+<div><math><semantics><mi>x</mi>
+ <annotation-xml encoding=application/xhtml+xml><p id="p6applicationxhtmlxml">x</p></annotation-xml>
+ </semantics></math></div>
+<div><math><semantics><mi>x</mi>
+ <annotation-xml encoding=foo><p id="p6foo">x</p></annotation-xml>
+ </semantics></math></div>
+</div>
+<script>
+test(function() {
+assert_equals(document.getElementById("m1"),document.getElementsByTagName("math")[0]);
+},"MATH element name should be lowercased");
+
+test(function() {
+assert_equals(document.getElementById("d1").firstChild.firstChild.nodeName,"mi");
+assert_equals(document.getElementById("d1").firstChild.firstChild.namespaceURI, "http://www.w3.org/1998/Math/MathML");
+assert_true(document.getElementById("d1").firstChild.firstChild.hasAttribute("mathvariant"));
+assert_equals(document.getElementById("d1").firstChild.firstChild.getAttribute("mathvariant"),"BOLD")
+},"MI element name and mathvariant attribute name should be lowercased, attribute value unchanged");
+
+test(function() {
+assert_true(document.getElementById("d2").firstChild.firstChild.hasAttribute("definitionURL"));
+assert_equals(document.getElementById("d2").firstChild.firstChild.getAttribute("definitionURL"),"www.example.org/FOO")
+},"DEFINITIONurl attribute markup should produce a definitionURL attribute, attribute value unchanged");
+
+test(function() {
+assert_equals(document.getElementById("m3span-mtext").firstChild.firstChild.nodeName,"SPAN");
+assert_equals(document.getElementById("m3span-mtext").firstChild.firstChild.namespaceURI,"http://www.w3.org/1999/xhtml")
+},"html Span in mtext produces SPAN nodename in XHTML namespace");
+
+test(function() {
+assert_equals(document.getElementById("m3span-mi").firstChild.firstChild.nodeName,"SPAN");
+assert_equals(document.getElementById("m3span-mi").firstChild.firstChild.namespaceURI,"http://www.w3.org/1999/xhtml")
+},"html Span in mi produces SPAN nodename in XHTML namespace");
+
+test(function() {
+assert_equals(document.getElementById("m3span-mrow").firstChild.firstChild.nodeName,"SPAN");
+assert_equals(document.getElementById("m3span-mrow").firstChild.firstChild.namespaceURI,"http://www.w3.org/1999/xhtml")
+},"html Span in mrow produces SPAN nodename in XHTML namespace");
+
+test(function() {
+assert_equals(document.getElementById("m3p-mtext").firstChild.firstChild.nodeName,"P");
+assert_equals(document.getElementById("m3p-mtext").firstChild.firstChild.namespaceURI,"http://www.w3.org/1999/xhtml")
+},"html P in mtext produces P nodename in XHTML namespace");
+
+test(function() {
+assert_equals(document.getElementById("m3p-mi").firstChild.firstChild.nodeName,"P");
+assert_equals(document.getElementById("m3p-mi").firstChild.firstChild.namespaceURI,"http://www.w3.org/1999/xhtml")
+},"html P in mi produces P nodename in XHTML namespace");
+
+test(function() {
+assert_equals(document.getElementById("d3p-mrow").childNodes.length ,3)
+},"html P in mrow terminates the math: mrow,P,MI children of div");
+
+test(function() {
+assert_equals(document.getElementById("d3p-mrow").firstChild.childNodes.length ,1)
+},"html P in mrow terminates the math: mrow child of math");
+
+test(function() {
+assert_equals(document.getElementById("d3p-mrow").firstChild.firstChild.childNodes.length ,0)
+},"html P in mrow terminates the math: mrow empty");
+
+test(function() {
+assert_equals(document.getElementById("d3p-mrow").childNodes[0].nodeName,"math");
+assert_equals(document.getElementById("d3p-mrow").childNodes[1].nodeName,"P");
+assert_equals(document.getElementById("d3p-mrow").childNodes[2].nodeName,"MI");
+},"html P in mrow terminates the math: math,P,MI children of div");
+
+test(function() {
+assert_equals(document.getElementById("m4").firstChild.firstChild.nodeName,"UNDEFINEDELEMENT");
+assert_equals(document.getElementById("m4").firstChild.firstChild.namespaceURI,"http://www.w3.org/1999/xhtml")
+},"Undefinedelement in mtext produces UNDEFINEDELEMENT nodename in XHTML namespace");
+
+test(function() {
+assert_equals(document.getElementById("m5").firstChild.firstChild.nodeName,"MI");
+assert_equals(document.getElementById("m5").firstChild.firstChild.namespaceURI,"http://www.w3.org/1999/xhtml")
+},"mi in mtext produces MI nodename in XHTML namespace");
+
+test(function() {
+assert_equals(document.getElementById("p6default").parentNode.nodeName,"DIV")
+},"p in annotation-xml moves to be child of DIV");
+
+test(function() {
+assert_equals(document.getElementById("p6texthtml").parentNode.nodeName,"annotation-xml")
+},"p in annotation-xml encoding=text/html stays as child of annotation-xml");
+
+test(function() {
+assert_equals(document.getElementById("p6uctexthtml").parentNode.nodeName,"annotation-xml")
+},"p in annotation-xml encoding=TEXT/HTML stays as child of annotation-xml");
+
+test(function() {
+assert_equals(document.getElementById("p6applicationxhtmlxml").parentNode.nodeName,"annotation-xml")
+},"p in annotation-xml encoding=application/xhtml+xml stays as child of annotation-xml");
+
+test(function() {
+assert_equals(document.getElementById("p6foo").parentNode.nodeName,"DIV")
+},"p in annotation-xml encoding=foo moves to be child of DIV");
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/named-character-references-data.js b/tests/wpt/web-platform-tests/html/syntax/parsing/named-character-references-data.js
new file mode 100644
index 00000000000..4a205a94b3b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/named-character-references-data.js
@@ -0,0 +1,2233 @@
+window.data = {
+ '&AElig': { 'codepoints': [0x000C6], 'characters': '\xC6' },
+ '&AElig;': { 'codepoints': [0x000C6], 'characters': '\xC6' },
+ '&AMP': { 'codepoints': [0x00026], 'characters': '\x26' },
+ '&AMP;': { 'codepoints': [0x00026], 'characters': '\x26' },
+ '&Aacute': { 'codepoints': [0x000C1], 'characters': '\xC1' },
+ '&Aacute;': { 'codepoints': [0x000C1], 'characters': '\xC1' },
+ '&Abreve;': { 'codepoints': [0x00102], 'characters': '\u0102' },
+ '&Acirc': { 'codepoints': [0x000C2], 'characters': '\xC2' },
+ '&Acirc;': { 'codepoints': [0x000C2], 'characters': '\xC2' },
+ '&Acy;': { 'codepoints': [0x00410], 'characters': '\u0410' },
+ '&Afr;': { 'codepoints': [0x1D504], 'characters': '\uD835\uDD04' },
+ '&Agrave': { 'codepoints': [0x000C0], 'characters': '\xC0' },
+ '&Agrave;': { 'codepoints': [0x000C0], 'characters': '\xC0' },
+ '&Alpha;': { 'codepoints': [0x00391], 'characters': '\u0391' },
+ '&Amacr;': { 'codepoints': [0x00100], 'characters': '\u0100' },
+ '&And;': { 'codepoints': [0x02A53], 'characters': '\u2A53' },
+ '&Aogon;': { 'codepoints': [0x00104], 'characters': '\u0104' },
+ '&Aopf;': { 'codepoints': [0x1D538], 'characters': '\uD835\uDD38' },
+ '&ApplyFunction;': { 'codepoints': [0x02061], 'characters': '\u2061' },
+ '&Aring': { 'codepoints': [0x000C5], 'characters': '\xC5' },
+ '&Aring;': { 'codepoints': [0x000C5], 'characters': '\xC5' },
+ '&Ascr;': { 'codepoints': [0x1D49C], 'characters': '\uD835\uDC9C' },
+ '&Assign;': { 'codepoints': [0x02254], 'characters': '\u2254' },
+ '&Atilde': { 'codepoints': [0x000C3], 'characters': '\xC3' },
+ '&Atilde;': { 'codepoints': [0x000C3], 'characters': '\xC3' },
+ '&Auml': { 'codepoints': [0x000C4], 'characters': '\xC4' },
+ '&Auml;': { 'codepoints': [0x000C4], 'characters': '\xC4' },
+ '&Backslash;': { 'codepoints': [0x02216], 'characters': '\u2216' },
+ '&Barv;': { 'codepoints': [0x02AE7], 'characters': '\u2AE7' },
+ '&Barwed;': { 'codepoints': [0x02306], 'characters': '\u2306' },
+ '&Bcy;': { 'codepoints': [0x00411], 'characters': '\u0411' },
+ '&Because;': { 'codepoints': [0x02235], 'characters': '\u2235' },
+ '&Bernoullis;': { 'codepoints': [0x0212C], 'characters': '\u212C' },
+ '&Beta;': { 'codepoints': [0x00392], 'characters': '\u0392' },
+ '&Bfr;': { 'codepoints': [0x1D505], 'characters': '\uD835\uDD05' },
+ '&Bopf;': { 'codepoints': [0x1D539], 'characters': '\uD835\uDD39' },
+ '&Breve;': { 'codepoints': [0x002D8], 'characters': '\u02D8' },
+ '&Bscr;': { 'codepoints': [0x0212C], 'characters': '\u212C' },
+ '&Bumpeq;': { 'codepoints': [0x0224E], 'characters': '\u224E' },
+ '&CHcy;': { 'codepoints': [0x00427], 'characters': '\u0427' },
+ '&COPY': { 'codepoints': [0x000A9], 'characters': '\xA9' },
+ '&COPY;': { 'codepoints': [0x000A9], 'characters': '\xA9' },
+ '&Cacute;': { 'codepoints': [0x00106], 'characters': '\u0106' },
+ '&Cap;': { 'codepoints': [0x022D2], 'characters': '\u22D2' },
+ '&CapitalDifferentialD;': { 'codepoints': [0x02145], 'characters': '\u2145' },
+ '&Cayleys;': { 'codepoints': [0x0212D], 'characters': '\u212D' },
+ '&Ccaron;': { 'codepoints': [0x0010C], 'characters': '\u010C' },
+ '&Ccedil': { 'codepoints': [0x000C7], 'characters': '\xC7' },
+ '&Ccedil;': { 'codepoints': [0x000C7], 'characters': '\xC7' },
+ '&Ccirc;': { 'codepoints': [0x00108], 'characters': '\u0108' },
+ '&Cconint;': { 'codepoints': [0x02230], 'characters': '\u2230' },
+ '&Cdot;': { 'codepoints': [0x0010A], 'characters': '\u010A' },
+ '&Cedilla;': { 'codepoints': [0x000B8], 'characters': '\xB8' },
+ '&CenterDot;': { 'codepoints': [0x000B7], 'characters': '\xB7' },
+ '&Cfr;': { 'codepoints': [0x0212D], 'characters': '\u212D' },
+ '&Chi;': { 'codepoints': [0x003A7], 'characters': '\u03A7' },
+ '&CircleDot;': { 'codepoints': [0x02299], 'characters': '\u2299' },
+ '&CircleMinus;': { 'codepoints': [0x02296], 'characters': '\u2296' },
+ '&CirclePlus;': { 'codepoints': [0x02295], 'characters': '\u2295' },
+ '&CircleTimes;': { 'codepoints': [0x02297], 'characters': '\u2297' },
+ '&ClockwiseContourIntegral;': { 'codepoints': [0x02232], 'characters': '\u2232' },
+ '&CloseCurlyDoubleQuote;': { 'codepoints': [0x0201D], 'characters': '\u201D' },
+ '&CloseCurlyQuote;': { 'codepoints': [0x02019], 'characters': '\u2019' },
+ '&Colon;': { 'codepoints': [0x02237], 'characters': '\u2237' },
+ '&Colone;': { 'codepoints': [0x02A74], 'characters': '\u2A74' },
+ '&Congruent;': { 'codepoints': [0x02261], 'characters': '\u2261' },
+ '&Conint;': { 'codepoints': [0x0222F], 'characters': '\u222F' },
+ '&ContourIntegral;': { 'codepoints': [0x0222E], 'characters': '\u222E' },
+ '&Copf;': { 'codepoints': [0x02102], 'characters': '\u2102' },
+ '&Coproduct;': { 'codepoints': [0x02210], 'characters': '\u2210' },
+ '&CounterClockwiseContourIntegral;': { 'codepoints': [0x02233], 'characters': '\u2233' },
+ '&Cross;': { 'codepoints': [0x02A2F], 'characters': '\u2A2F' },
+ '&Cscr;': { 'codepoints': [0x1D49E], 'characters': '\uD835\uDC9E' },
+ '&Cup;': { 'codepoints': [0x022D3], 'characters': '\u22D3' },
+ '&CupCap;': { 'codepoints': [0x0224D], 'characters': '\u224D' },
+ '&DD;': { 'codepoints': [0x02145], 'characters': '\u2145' },
+ '&DDotrahd;': { 'codepoints': [0x02911], 'characters': '\u2911' },
+ '&DJcy;': { 'codepoints': [0x00402], 'characters': '\u0402' },
+ '&DScy;': { 'codepoints': [0x00405], 'characters': '\u0405' },
+ '&DZcy;': { 'codepoints': [0x0040F], 'characters': '\u040F' },
+ '&Dagger;': { 'codepoints': [0x02021], 'characters': '\u2021' },
+ '&Darr;': { 'codepoints': [0x021A1], 'characters': '\u21A1' },
+ '&Dashv;': { 'codepoints': [0x02AE4], 'characters': '\u2AE4' },
+ '&Dcaron;': { 'codepoints': [0x0010E], 'characters': '\u010E' },
+ '&Dcy;': { 'codepoints': [0x00414], 'characters': '\u0414' },
+ '&Del;': { 'codepoints': [0x02207], 'characters': '\u2207' },
+ '&Delta;': { 'codepoints': [0x00394], 'characters': '\u0394' },
+ '&Dfr;': { 'codepoints': [0x1D507], 'characters': '\uD835\uDD07' },
+ '&DiacriticalAcute;': { 'codepoints': [0x000B4], 'characters': '\xB4' },
+ '&DiacriticalDot;': { 'codepoints': [0x002D9], 'characters': '\u02D9' },
+ '&DiacriticalDoubleAcute;': { 'codepoints': [0x002DD], 'characters': '\u02DD' },
+ '&DiacriticalGrave;': { 'codepoints': [0x00060], 'characters': '\x60' },
+ '&DiacriticalTilde;': { 'codepoints': [0x002DC], 'characters': '\u02DC' },
+ '&Diamond;': { 'codepoints': [0x022C4], 'characters': '\u22C4' },
+ '&DifferentialD;': { 'codepoints': [0x02146], 'characters': '\u2146' },
+ '&Dopf;': { 'codepoints': [0x1D53B], 'characters': '\uD835\uDD3B' },
+ '&Dot;': { 'codepoints': [0x000A8], 'characters': '\xA8' },
+ '&DotDot;': { 'codepoints': [0x020DC], 'characters': '\u20DC' },
+ '&DotEqual;': { 'codepoints': [0x02250], 'characters': '\u2250' },
+ '&DoubleContourIntegral;': { 'codepoints': [0x0222F], 'characters': '\u222F' },
+ '&DoubleDot;': { 'codepoints': [0x000A8], 'characters': '\xA8' },
+ '&DoubleDownArrow;': { 'codepoints': [0x021D3], 'characters': '\u21D3' },
+ '&DoubleLeftArrow;': { 'codepoints': [0x021D0], 'characters': '\u21D0' },
+ '&DoubleLeftRightArrow;': { 'codepoints': [0x021D4], 'characters': '\u21D4' },
+ '&DoubleLeftTee;': { 'codepoints': [0x02AE4], 'characters': '\u2AE4' },
+ '&DoubleLongLeftArrow;': { 'codepoints': [0x027F8], 'characters': '\u27F8' },
+ '&DoubleLongLeftRightArrow;': { 'codepoints': [0x027FA], 'characters': '\u27FA' },
+ '&DoubleLongRightArrow;': { 'codepoints': [0x027F9], 'characters': '\u27F9' },
+ '&DoubleRightArrow;': { 'codepoints': [0x021D2], 'characters': '\u21D2' },
+ '&DoubleRightTee;': { 'codepoints': [0x022A8], 'characters': '\u22A8' },
+ '&DoubleUpArrow;': { 'codepoints': [0x021D1], 'characters': '\u21D1' },
+ '&DoubleUpDownArrow;': { 'codepoints': [0x021D5], 'characters': '\u21D5' },
+ '&DoubleVerticalBar;': { 'codepoints': [0x02225], 'characters': '\u2225' },
+ '&DownArrow;': { 'codepoints': [0x02193], 'characters': '\u2193' },
+ '&DownArrowBar;': { 'codepoints': [0x02913], 'characters': '\u2913' },
+ '&DownArrowUpArrow;': { 'codepoints': [0x021F5], 'characters': '\u21F5' },
+ '&DownBreve;': { 'codepoints': [0x00311], 'characters': '\u0311' },
+ '&DownLeftRightVector;': { 'codepoints': [0x02950], 'characters': '\u2950' },
+ '&DownLeftTeeVector;': { 'codepoints': [0x0295E], 'characters': '\u295E' },
+ '&DownLeftVector;': { 'codepoints': [0x021BD], 'characters': '\u21BD' },
+ '&DownLeftVectorBar;': { 'codepoints': [0x02956], 'characters': '\u2956' },
+ '&DownRightTeeVector;': { 'codepoints': [0x0295F], 'characters': '\u295F' },
+ '&DownRightVector;': { 'codepoints': [0x021C1], 'characters': '\u21C1' },
+ '&DownRightVectorBar;': { 'codepoints': [0x02957], 'characters': '\u2957' },
+ '&DownTee;': { 'codepoints': [0x022A4], 'characters': '\u22A4' },
+ '&DownTeeArrow;': { 'codepoints': [0x021A7], 'characters': '\u21A7' },
+ '&Downarrow;': { 'codepoints': [0x021D3], 'characters': '\u21D3' },
+ '&Dscr;': { 'codepoints': [0x1D49F], 'characters': '\uD835\uDC9F' },
+ '&Dstrok;': { 'codepoints': [0x00110], 'characters': '\u0110' },
+ '&ENG;': { 'codepoints': [0x0014A], 'characters': '\u014A' },
+ '&ETH': { 'codepoints': [0x000D0], 'characters': '\xD0' },
+ '&ETH;': { 'codepoints': [0x000D0], 'characters': '\xD0' },
+ '&Eacute': { 'codepoints': [0x000C9], 'characters': '\xC9' },
+ '&Eacute;': { 'codepoints': [0x000C9], 'characters': '\xC9' },
+ '&Ecaron;': { 'codepoints': [0x0011A], 'characters': '\u011A' },
+ '&Ecirc': { 'codepoints': [0x000CA], 'characters': '\xCA' },
+ '&Ecirc;': { 'codepoints': [0x000CA], 'characters': '\xCA' },
+ '&Ecy;': { 'codepoints': [0x0042D], 'characters': '\u042D' },
+ '&Edot;': { 'codepoints': [0x00116], 'characters': '\u0116' },
+ '&Efr;': { 'codepoints': [0x1D508], 'characters': '\uD835\uDD08' },
+ '&Egrave': { 'codepoints': [0x000C8], 'characters': '\xC8' },
+ '&Egrave;': { 'codepoints': [0x000C8], 'characters': '\xC8' },
+ '&Element;': { 'codepoints': [0x02208], 'characters': '\u2208' },
+ '&Emacr;': { 'codepoints': [0x00112], 'characters': '\u0112' },
+ '&EmptySmallSquare;': { 'codepoints': [0x025FB], 'characters': '\u25FB' },
+ '&EmptyVerySmallSquare;': { 'codepoints': [0x025AB], 'characters': '\u25AB' },
+ '&Eogon;': { 'codepoints': [0x00118], 'characters': '\u0118' },
+ '&Eopf;': { 'codepoints': [0x1D53C], 'characters': '\uD835\uDD3C' },
+ '&Epsilon;': { 'codepoints': [0x00395], 'characters': '\u0395' },
+ '&Equal;': { 'codepoints': [0x02A75], 'characters': '\u2A75' },
+ '&EqualTilde;': { 'codepoints': [0x02242], 'characters': '\u2242' },
+ '&Equilibrium;': { 'codepoints': [0x021CC], 'characters': '\u21CC' },
+ '&Escr;': { 'codepoints': [0x02130], 'characters': '\u2130' },
+ '&Esim;': { 'codepoints': [0x02A73], 'characters': '\u2A73' },
+ '&Eta;': { 'codepoints': [0x00397], 'characters': '\u0397' },
+ '&Euml': { 'codepoints': [0x000CB], 'characters': '\xCB' },
+ '&Euml;': { 'codepoints': [0x000CB], 'characters': '\xCB' },
+ '&Exists;': { 'codepoints': [0x02203], 'characters': '\u2203' },
+ '&ExponentialE;': { 'codepoints': [0x02147], 'characters': '\u2147' },
+ '&Fcy;': { 'codepoints': [0x00424], 'characters': '\u0424' },
+ '&Ffr;': { 'codepoints': [0x1D509], 'characters': '\uD835\uDD09' },
+ '&FilledSmallSquare;': { 'codepoints': [0x025FC], 'characters': '\u25FC' },
+ '&FilledVerySmallSquare;': { 'codepoints': [0x025AA], 'characters': '\u25AA' },
+ '&Fopf;': { 'codepoints': [0x1D53D], 'characters': '\uD835\uDD3D' },
+ '&ForAll;': { 'codepoints': [0x02200], 'characters': '\u2200' },
+ '&Fouriertrf;': { 'codepoints': [0x02131], 'characters': '\u2131' },
+ '&Fscr;': { 'codepoints': [0x02131], 'characters': '\u2131' },
+ '&GJcy;': { 'codepoints': [0x00403], 'characters': '\u0403' },
+ '&GT': { 'codepoints': [0x0003E], 'characters': '\x3E' },
+ '&GT;': { 'codepoints': [0x0003E], 'characters': '\x3E' },
+ '&Gamma;': { 'codepoints': [0x00393], 'characters': '\u0393' },
+ '&Gammad;': { 'codepoints': [0x003DC], 'characters': '\u03DC' },
+ '&Gbreve;': { 'codepoints': [0x0011E], 'characters': '\u011E' },
+ '&Gcedil;': { 'codepoints': [0x00122], 'characters': '\u0122' },
+ '&Gcirc;': { 'codepoints': [0x0011C], 'characters': '\u011C' },
+ '&Gcy;': { 'codepoints': [0x00413], 'characters': '\u0413' },
+ '&Gdot;': { 'codepoints': [0x00120], 'characters': '\u0120' },
+ '&Gfr;': { 'codepoints': [0x1D50A], 'characters': '\uD835\uDD0A' },
+ '&Gg;': { 'codepoints': [0x022D9], 'characters': '\u22D9' },
+ '&Gopf;': { 'codepoints': [0x1D53E], 'characters': '\uD835\uDD3E' },
+ '&GreaterEqual;': { 'codepoints': [0x02265], 'characters': '\u2265' },
+ '&GreaterEqualLess;': { 'codepoints': [0x022DB], 'characters': '\u22DB' },
+ '&GreaterFullEqual;': { 'codepoints': [0x02267], 'characters': '\u2267' },
+ '&GreaterGreater;': { 'codepoints': [0x02AA2], 'characters': '\u2AA2' },
+ '&GreaterLess;': { 'codepoints': [0x02277], 'characters': '\u2277' },
+ '&GreaterSlantEqual;': { 'codepoints': [0x02A7E], 'characters': '\u2A7E' },
+ '&GreaterTilde;': { 'codepoints': [0x02273], 'characters': '\u2273' },
+ '&Gscr;': { 'codepoints': [0x1D4A2], 'characters': '\uD835\uDCA2' },
+ '&Gt;': { 'codepoints': [0x0226B], 'characters': '\u226B' },
+ '&HARDcy;': { 'codepoints': [0x0042A], 'characters': '\u042A' },
+ '&Hacek;': { 'codepoints': [0x002C7], 'characters': '\u02C7' },
+ '&Hat;': { 'codepoints': [0x0005E], 'characters': '\x5E' },
+ '&Hcirc;': { 'codepoints': [0x00124], 'characters': '\u0124' },
+ '&Hfr;': { 'codepoints': [0x0210C], 'characters': '\u210C' },
+ '&HilbertSpace;': { 'codepoints': [0x0210B], 'characters': '\u210B' },
+ '&Hopf;': { 'codepoints': [0x0210D], 'characters': '\u210D' },
+ '&HorizontalLine;': { 'codepoints': [0x02500], 'characters': '\u2500' },
+ '&Hscr;': { 'codepoints': [0x0210B], 'characters': '\u210B' },
+ '&Hstrok;': { 'codepoints': [0x00126], 'characters': '\u0126' },
+ '&HumpDownHump;': { 'codepoints': [0x0224E], 'characters': '\u224E' },
+ '&HumpEqual;': { 'codepoints': [0x0224F], 'characters': '\u224F' },
+ '&IEcy;': { 'codepoints': [0x00415], 'characters': '\u0415' },
+ '&IJlig;': { 'codepoints': [0x00132], 'characters': '\u0132' },
+ '&IOcy;': { 'codepoints': [0x00401], 'characters': '\u0401' },
+ '&Iacute': { 'codepoints': [0x000CD], 'characters': '\xCD' },
+ '&Iacute;': { 'codepoints': [0x000CD], 'characters': '\xCD' },
+ '&Icirc': { 'codepoints': [0x000CE], 'characters': '\xCE' },
+ '&Icirc;': { 'codepoints': [0x000CE], 'characters': '\xCE' },
+ '&Icy;': { 'codepoints': [0x00418], 'characters': '\u0418' },
+ '&Idot;': { 'codepoints': [0x00130], 'characters': '\u0130' },
+ '&Ifr;': { 'codepoints': [0x02111], 'characters': '\u2111' },
+ '&Igrave': { 'codepoints': [0x000CC], 'characters': '\xCC' },
+ '&Igrave;': { 'codepoints': [0x000CC], 'characters': '\xCC' },
+ '&Im;': { 'codepoints': [0x02111], 'characters': '\u2111' },
+ '&Imacr;': { 'codepoints': [0x0012A], 'characters': '\u012A' },
+ '&ImaginaryI;': { 'codepoints': [0x02148], 'characters': '\u2148' },
+ '&Implies;': { 'codepoints': [0x021D2], 'characters': '\u21D2' },
+ '&Int;': { 'codepoints': [0x0222C], 'characters': '\u222C' },
+ '&Integral;': { 'codepoints': [0x0222B], 'characters': '\u222B' },
+ '&Intersection;': { 'codepoints': [0x022C2], 'characters': '\u22C2' },
+ '&InvisibleComma;': { 'codepoints': [0x02063], 'characters': '\u2063' },
+ '&InvisibleTimes;': { 'codepoints': [0x02062], 'characters': '\u2062' },
+ '&Iogon;': { 'codepoints': [0x0012E], 'characters': '\u012E' },
+ '&Iopf;': { 'codepoints': [0x1D540], 'characters': '\uD835\uDD40' },
+ '&Iota;': { 'codepoints': [0x00399], 'characters': '\u0399' },
+ '&Iscr;': { 'codepoints': [0x02110], 'characters': '\u2110' },
+ '&Itilde;': { 'codepoints': [0x00128], 'characters': '\u0128' },
+ '&Iukcy;': { 'codepoints': [0x00406], 'characters': '\u0406' },
+ '&Iuml': { 'codepoints': [0x000CF], 'characters': '\xCF' },
+ '&Iuml;': { 'codepoints': [0x000CF], 'characters': '\xCF' },
+ '&Jcirc;': { 'codepoints': [0x00134], 'characters': '\u0134' },
+ '&Jcy;': { 'codepoints': [0x00419], 'characters': '\u0419' },
+ '&Jfr;': { 'codepoints': [0x1D50D], 'characters': '\uD835\uDD0D' },
+ '&Jopf;': { 'codepoints': [0x1D541], 'characters': '\uD835\uDD41' },
+ '&Jscr;': { 'codepoints': [0x1D4A5], 'characters': '\uD835\uDCA5' },
+ '&Jsercy;': { 'codepoints': [0x00408], 'characters': '\u0408' },
+ '&Jukcy;': { 'codepoints': [0x00404], 'characters': '\u0404' },
+ '&KHcy;': { 'codepoints': [0x00425], 'characters': '\u0425' },
+ '&KJcy;': { 'codepoints': [0x0040C], 'characters': '\u040C' },
+ '&Kappa;': { 'codepoints': [0x0039A], 'characters': '\u039A' },
+ '&Kcedil;': { 'codepoints': [0x00136], 'characters': '\u0136' },
+ '&Kcy;': { 'codepoints': [0x0041A], 'characters': '\u041A' },
+ '&Kfr;': { 'codepoints': [0x1D50E], 'characters': '\uD835\uDD0E' },
+ '&Kopf;': { 'codepoints': [0x1D542], 'characters': '\uD835\uDD42' },
+ '&Kscr;': { 'codepoints': [0x1D4A6], 'characters': '\uD835\uDCA6' },
+ '&LJcy;': { 'codepoints': [0x00409], 'characters': '\u0409' },
+ '&LT': { 'codepoints': [0x0003C], 'characters': '\x3C' },
+ '&LT;': { 'codepoints': [0x0003C], 'characters': '\x3C' },
+ '&Lacute;': { 'codepoints': [0x00139], 'characters': '\u0139' },
+ '&Lambda;': { 'codepoints': [0x0039B], 'characters': '\u039B' },
+ '&Lang;': { 'codepoints': [0x027EA], 'characters': '\u27EA' },
+ '&Laplacetrf;': { 'codepoints': [0x02112], 'characters': '\u2112' },
+ '&Larr;': { 'codepoints': [0x0219E], 'characters': '\u219E' },
+ '&Lcaron;': { 'codepoints': [0x0013D], 'characters': '\u013D' },
+ '&Lcedil;': { 'codepoints': [0x0013B], 'characters': '\u013B' },
+ '&Lcy;': { 'codepoints': [0x0041B], 'characters': '\u041B' },
+ '&LeftAngleBracket;': { 'codepoints': [0x027E8], 'characters': '\u27E8' },
+ '&LeftArrow;': { 'codepoints': [0x02190], 'characters': '\u2190' },
+ '&LeftArrowBar;': { 'codepoints': [0x021E4], 'characters': '\u21E4' },
+ '&LeftArrowRightArrow;': { 'codepoints': [0x021C6], 'characters': '\u21C6' },
+ '&LeftCeiling;': { 'codepoints': [0x02308], 'characters': '\u2308' },
+ '&LeftDoubleBracket;': { 'codepoints': [0x027E6], 'characters': '\u27E6' },
+ '&LeftDownTeeVector;': { 'codepoints': [0x02961], 'characters': '\u2961' },
+ '&LeftDownVector;': { 'codepoints': [0x021C3], 'characters': '\u21C3' },
+ '&LeftDownVectorBar;': { 'codepoints': [0x02959], 'characters': '\u2959' },
+ '&LeftFloor;': { 'codepoints': [0x0230A], 'characters': '\u230A' },
+ '&LeftRightArrow;': { 'codepoints': [0x02194], 'characters': '\u2194' },
+ '&LeftRightVector;': { 'codepoints': [0x0294E], 'characters': '\u294E' },
+ '&LeftTee;': { 'codepoints': [0x022A3], 'characters': '\u22A3' },
+ '&LeftTeeArrow;': { 'codepoints': [0x021A4], 'characters': '\u21A4' },
+ '&LeftTeeVector;': { 'codepoints': [0x0295A], 'characters': '\u295A' },
+ '&LeftTriangle;': { 'codepoints': [0x022B2], 'characters': '\u22B2' },
+ '&LeftTriangleBar;': { 'codepoints': [0x029CF], 'characters': '\u29CF' },
+ '&LeftTriangleEqual;': { 'codepoints': [0x022B4], 'characters': '\u22B4' },
+ '&LeftUpDownVector;': { 'codepoints': [0x02951], 'characters': '\u2951' },
+ '&LeftUpTeeVector;': { 'codepoints': [0x02960], 'characters': '\u2960' },
+ '&LeftUpVector;': { 'codepoints': [0x021BF], 'characters': '\u21BF' },
+ '&LeftUpVectorBar;': { 'codepoints': [0x02958], 'characters': '\u2958' },
+ '&LeftVector;': { 'codepoints': [0x021BC], 'characters': '\u21BC' },
+ '&LeftVectorBar;': { 'codepoints': [0x02952], 'characters': '\u2952' },
+ '&Leftarrow;': { 'codepoints': [0x021D0], 'characters': '\u21D0' },
+ '&Leftrightarrow;': { 'codepoints': [0x021D4], 'characters': '\u21D4' },
+ '&LessEqualGreater;': { 'codepoints': [0x022DA], 'characters': '\u22DA' },
+ '&LessFullEqual;': { 'codepoints': [0x02266], 'characters': '\u2266' },
+ '&LessGreater;': { 'codepoints': [0x02276], 'characters': '\u2276' },
+ '&LessLess;': { 'codepoints': [0x02AA1], 'characters': '\u2AA1' },
+ '&LessSlantEqual;': { 'codepoints': [0x02A7D], 'characters': '\u2A7D' },
+ '&LessTilde;': { 'codepoints': [0x02272], 'characters': '\u2272' },
+ '&Lfr;': { 'codepoints': [0x1D50F], 'characters': '\uD835\uDD0F' },
+ '&Ll;': { 'codepoints': [0x022D8], 'characters': '\u22D8' },
+ '&Lleftarrow;': { 'codepoints': [0x021DA], 'characters': '\u21DA' },
+ '&Lmidot;': { 'codepoints': [0x0013F], 'characters': '\u013F' },
+ '&LongLeftArrow;': { 'codepoints': [0x027F5], 'characters': '\u27F5' },
+ '&LongLeftRightArrow;': { 'codepoints': [0x027F7], 'characters': '\u27F7' },
+ '&LongRightArrow;': { 'codepoints': [0x027F6], 'characters': '\u27F6' },
+ '&Longleftarrow;': { 'codepoints': [0x027F8], 'characters': '\u27F8' },
+ '&Longleftrightarrow;': { 'codepoints': [0x027FA], 'characters': '\u27FA' },
+ '&Longrightarrow;': { 'codepoints': [0x027F9], 'characters': '\u27F9' },
+ '&Lopf;': { 'codepoints': [0x1D543], 'characters': '\uD835\uDD43' },
+ '&LowerLeftArrow;': { 'codepoints': [0x02199], 'characters': '\u2199' },
+ '&LowerRightArrow;': { 'codepoints': [0x02198], 'characters': '\u2198' },
+ '&Lscr;': { 'codepoints': [0x02112], 'characters': '\u2112' },
+ '&Lsh;': { 'codepoints': [0x021B0], 'characters': '\u21B0' },
+ '&Lstrok;': { 'codepoints': [0x00141], 'characters': '\u0141' },
+ '&Lt;': { 'codepoints': [0x0226A], 'characters': '\u226A' },
+ '&Map;': { 'codepoints': [0x02905], 'characters': '\u2905' },
+ '&Mcy;': { 'codepoints': [0x0041C], 'characters': '\u041C' },
+ '&MediumSpace;': { 'codepoints': [0x0205F], 'characters': '\u205F' },
+ '&Mellintrf;': { 'codepoints': [0x02133], 'characters': '\u2133' },
+ '&Mfr;': { 'codepoints': [0x1D510], 'characters': '\uD835\uDD10' },
+ '&MinusPlus;': { 'codepoints': [0x02213], 'characters': '\u2213' },
+ '&Mopf;': { 'codepoints': [0x1D544], 'characters': '\uD835\uDD44' },
+ '&Mscr;': { 'codepoints': [0x02133], 'characters': '\u2133' },
+ '&Mu;': { 'codepoints': [0x0039C], 'characters': '\u039C' },
+ '&NJcy;': { 'codepoints': [0x0040A], 'characters': '\u040A' },
+ '&Nacute;': { 'codepoints': [0x00143], 'characters': '\u0143' },
+ '&Ncaron;': { 'codepoints': [0x00147], 'characters': '\u0147' },
+ '&Ncedil;': { 'codepoints': [0x00145], 'characters': '\u0145' },
+ '&Ncy;': { 'codepoints': [0x0041D], 'characters': '\u041D' },
+ '&NegativeMediumSpace;': { 'codepoints': [0x0200B], 'characters': '\u200B' },
+ '&NegativeThickSpace;': { 'codepoints': [0x0200B], 'characters': '\u200B' },
+ '&NegativeThinSpace;': { 'codepoints': [0x0200B], 'characters': '\u200B' },
+ '&NegativeVeryThinSpace;': { 'codepoints': [0x0200B], 'characters': '\u200B' },
+ '&NestedGreaterGreater;': { 'codepoints': [0x0226B], 'characters': '\u226B' },
+ '&NestedLessLess;': { 'codepoints': [0x0226A], 'characters': '\u226A' },
+ '&NewLine;': { 'codepoints': [0x0000A], 'characters': '\x0A' },
+ '&Nfr;': { 'codepoints': [0x1D511], 'characters': '\uD835\uDD11' },
+ '&NoBreak;': { 'codepoints': [0x02060], 'characters': '\u2060' },
+ '&NonBreakingSpace;': { 'codepoints': [0x000A0], 'characters': '\xA0' },
+ '&Nopf;': { 'codepoints': [0x02115], 'characters': '\u2115' },
+ '&Not;': { 'codepoints': [0x02AEC], 'characters': '\u2AEC' },
+ '&NotCongruent;': { 'codepoints': [0x02262], 'characters': '\u2262' },
+ '&NotCupCap;': { 'codepoints': [0x0226D], 'characters': '\u226D' },
+ '&NotDoubleVerticalBar;': { 'codepoints': [0x02226], 'characters': '\u2226' },
+ '&NotElement;': { 'codepoints': [0x02209], 'characters': '\u2209' },
+ '&NotEqual;': { 'codepoints': [0x02260], 'characters': '\u2260' },
+ '&NotEqualTilde;': { 'codepoints': [0x02242, 0x00338], 'characters': '\u2242\u0338' },
+ '&NotExists;': { 'codepoints': [0x02204], 'characters': '\u2204' },
+ '&NotGreater;': { 'codepoints': [0x0226F], 'characters': '\u226F' },
+ '&NotGreaterEqual;': { 'codepoints': [0x02271], 'characters': '\u2271' },
+ '&NotGreaterFullEqual;': { 'codepoints': [0x02267, 0x00338], 'characters': '\u2267\u0338' },
+ '&NotGreaterGreater;': { 'codepoints': [0x0226B, 0x00338], 'characters': '\u226B\u0338' },
+ '&NotGreaterLess;': { 'codepoints': [0x02279], 'characters': '\u2279' },
+ '&NotGreaterSlantEqual;': { 'codepoints': [0x02A7E, 0x00338], 'characters': '\u2A7E\u0338' },
+ '&NotGreaterTilde;': { 'codepoints': [0x02275], 'characters': '\u2275' },
+ '&NotHumpDownHump;': { 'codepoints': [0x0224E, 0x00338], 'characters': '\u224E\u0338' },
+ '&NotHumpEqual;': { 'codepoints': [0x0224F, 0x00338], 'characters': '\u224F\u0338' },
+ '&NotLeftTriangle;': { 'codepoints': [0x022EA], 'characters': '\u22EA' },
+ '&NotLeftTriangleBar;': { 'codepoints': [0x029CF, 0x00338], 'characters': '\u29CF\u0338' },
+ '&NotLeftTriangleEqual;': { 'codepoints': [0x022EC], 'characters': '\u22EC' },
+ '&NotLess;': { 'codepoints': [0x0226E], 'characters': '\u226E' },
+ '&NotLessEqual;': { 'codepoints': [0x02270], 'characters': '\u2270' },
+ '&NotLessGreater;': { 'codepoints': [0x02278], 'characters': '\u2278' },
+ '&NotLessLess;': { 'codepoints': [0x0226A, 0x00338], 'characters': '\u226A\u0338' },
+ '&NotLessSlantEqual;': { 'codepoints': [0x02A7D, 0x00338], 'characters': '\u2A7D\u0338' },
+ '&NotLessTilde;': { 'codepoints': [0x02274], 'characters': '\u2274' },
+ '&NotNestedGreaterGreater;': { 'codepoints': [0x02AA2, 0x00338], 'characters': '\u2AA2\u0338' },
+ '&NotNestedLessLess;': { 'codepoints': [0x02AA1, 0x00338], 'characters': '\u2AA1\u0338' },
+ '&NotPrecedes;': { 'codepoints': [0x02280], 'characters': '\u2280' },
+ '&NotPrecedesEqual;': { 'codepoints': [0x02AAF, 0x00338], 'characters': '\u2AAF\u0338' },
+ '&NotPrecedesSlantEqual;': { 'codepoints': [0x022E0], 'characters': '\u22E0' },
+ '&NotReverseElement;': { 'codepoints': [0x0220C], 'characters': '\u220C' },
+ '&NotRightTriangle;': { 'codepoints': [0x022EB], 'characters': '\u22EB' },
+ '&NotRightTriangleBar;': { 'codepoints': [0x029D0, 0x00338], 'characters': '\u29D0\u0338' },
+ '&NotRightTriangleEqual;': { 'codepoints': [0x022ED], 'characters': '\u22ED' },
+ '&NotSquareSubset;': { 'codepoints': [0x0228F, 0x00338], 'characters': '\u228F\u0338' },
+ '&NotSquareSubsetEqual;': { 'codepoints': [0x022E2], 'characters': '\u22E2' },
+ '&NotSquareSuperset;': { 'codepoints': [0x02290, 0x00338], 'characters': '\u2290\u0338' },
+ '&NotSquareSupersetEqual;': { 'codepoints': [0x022E3], 'characters': '\u22E3' },
+ '&NotSubset;': { 'codepoints': [0x02282, 0x020D2], 'characters': '\u2282\u20D2' },
+ '&NotSubsetEqual;': { 'codepoints': [0x02288], 'characters': '\u2288' },
+ '&NotSucceeds;': { 'codepoints': [0x02281], 'characters': '\u2281' },
+ '&NotSucceedsEqual;': { 'codepoints': [0x02AB0, 0x00338], 'characters': '\u2AB0\u0338' },
+ '&NotSucceedsSlantEqual;': { 'codepoints': [0x022E1], 'characters': '\u22E1' },
+ '&NotSucceedsTilde;': { 'codepoints': [0x0227F, 0x00338], 'characters': '\u227F\u0338' },
+ '&NotSuperset;': { 'codepoints': [0x02283, 0x020D2], 'characters': '\u2283\u20D2' },
+ '&NotSupersetEqual;': { 'codepoints': [0x02289], 'characters': '\u2289' },
+ '&NotTilde;': { 'codepoints': [0x02241], 'characters': '\u2241' },
+ '&NotTildeEqual;': { 'codepoints': [0x02244], 'characters': '\u2244' },
+ '&NotTildeFullEqual;': { 'codepoints': [0x02247], 'characters': '\u2247' },
+ '&NotTildeTilde;': { 'codepoints': [0x02249], 'characters': '\u2249' },
+ '&NotVerticalBar;': { 'codepoints': [0x02224], 'characters': '\u2224' },
+ '&Nscr;': { 'codepoints': [0x1D4A9], 'characters': '\uD835\uDCA9' },
+ '&Ntilde': { 'codepoints': [0x000D1], 'characters': '\xD1' },
+ '&Ntilde;': { 'codepoints': [0x000D1], 'characters': '\xD1' },
+ '&Nu;': { 'codepoints': [0x0039D], 'characters': '\u039D' },
+ '&OElig;': { 'codepoints': [0x00152], 'characters': '\u0152' },
+ '&Oacute': { 'codepoints': [0x000D3], 'characters': '\xD3' },
+ '&Oacute;': { 'codepoints': [0x000D3], 'characters': '\xD3' },
+ '&Ocirc': { 'codepoints': [0x000D4], 'characters': '\xD4' },
+ '&Ocirc;': { 'codepoints': [0x000D4], 'characters': '\xD4' },
+ '&Ocy;': { 'codepoints': [0x0041E], 'characters': '\u041E' },
+ '&Odblac;': { 'codepoints': [0x00150], 'characters': '\u0150' },
+ '&Ofr;': { 'codepoints': [0x1D512], 'characters': '\uD835\uDD12' },
+ '&Ograve': { 'codepoints': [0x000D2], 'characters': '\xD2' },
+ '&Ograve;': { 'codepoints': [0x000D2], 'characters': '\xD2' },
+ '&Omacr;': { 'codepoints': [0x0014C], 'characters': '\u014C' },
+ '&Omega;': { 'codepoints': [0x003A9], 'characters': '\u03A9' },
+ '&Omicron;': { 'codepoints': [0x0039F], 'characters': '\u039F' },
+ '&Oopf;': { 'codepoints': [0x1D546], 'characters': '\uD835\uDD46' },
+ '&OpenCurlyDoubleQuote;': { 'codepoints': [0x0201C], 'characters': '\u201C' },
+ '&OpenCurlyQuote;': { 'codepoints': [0x02018], 'characters': '\u2018' },
+ '&Or;': { 'codepoints': [0x02A54], 'characters': '\u2A54' },
+ '&Oscr;': { 'codepoints': [0x1D4AA], 'characters': '\uD835\uDCAA' },
+ '&Oslash': { 'codepoints': [0x000D8], 'characters': '\xD8' },
+ '&Oslash;': { 'codepoints': [0x000D8], 'characters': '\xD8' },
+ '&Otilde': { 'codepoints': [0x000D5], 'characters': '\xD5' },
+ '&Otilde;': { 'codepoints': [0x000D5], 'characters': '\xD5' },
+ '&Otimes;': { 'codepoints': [0x02A37], 'characters': '\u2A37' },
+ '&Ouml': { 'codepoints': [0x000D6], 'characters': '\xD6' },
+ '&Ouml;': { 'codepoints': [0x000D6], 'characters': '\xD6' },
+ '&OverBar;': { 'codepoints': [0x0203E], 'characters': '\u203E' },
+ '&OverBrace;': { 'codepoints': [0x023DE], 'characters': '\u23DE' },
+ '&OverBracket;': { 'codepoints': [0x023B4], 'characters': '\u23B4' },
+ '&OverParenthesis;': { 'codepoints': [0x023DC], 'characters': '\u23DC' },
+ '&PartialD;': { 'codepoints': [0x02202], 'characters': '\u2202' },
+ '&Pcy;': { 'codepoints': [0x0041F], 'characters': '\u041F' },
+ '&Pfr;': { 'codepoints': [0x1D513], 'characters': '\uD835\uDD13' },
+ '&Phi;': { 'codepoints': [0x003A6], 'characters': '\u03A6' },
+ '&Pi;': { 'codepoints': [0x003A0], 'characters': '\u03A0' },
+ '&PlusMinus;': { 'codepoints': [0x000B1], 'characters': '\xB1' },
+ '&Poincareplane;': { 'codepoints': [0x0210C], 'characters': '\u210C' },
+ '&Popf;': { 'codepoints': [0x02119], 'characters': '\u2119' },
+ '&Pr;': { 'codepoints': [0x02ABB], 'characters': '\u2ABB' },
+ '&Precedes;': { 'codepoints': [0x0227A], 'characters': '\u227A' },
+ '&PrecedesEqual;': { 'codepoints': [0x02AAF], 'characters': '\u2AAF' },
+ '&PrecedesSlantEqual;': { 'codepoints': [0x0227C], 'characters': '\u227C' },
+ '&PrecedesTilde;': { 'codepoints': [0x0227E], 'characters': '\u227E' },
+ '&Prime;': { 'codepoints': [0x02033], 'characters': '\u2033' },
+ '&Product;': { 'codepoints': [0x0220F], 'characters': '\u220F' },
+ '&Proportion;': { 'codepoints': [0x02237], 'characters': '\u2237' },
+ '&Proportional;': { 'codepoints': [0x0221D], 'characters': '\u221D' },
+ '&Pscr;': { 'codepoints': [0x1D4AB], 'characters': '\uD835\uDCAB' },
+ '&Psi;': { 'codepoints': [0x003A8], 'characters': '\u03A8' },
+ '&QUOT': { 'codepoints': [0x00022], 'characters': '\x22' },
+ '&QUOT;': { 'codepoints': [0x00022], 'characters': '\x22' },
+ '&Qfr;': { 'codepoints': [0x1D514], 'characters': '\uD835\uDD14' },
+ '&Qopf;': { 'codepoints': [0x0211A], 'characters': '\u211A' },
+ '&Qscr;': { 'codepoints': [0x1D4AC], 'characters': '\uD835\uDCAC' },
+ '&RBarr;': { 'codepoints': [0x02910], 'characters': '\u2910' },
+ '&REG': { 'codepoints': [0x000AE], 'characters': '\xAE' },
+ '&REG;': { 'codepoints': [0x000AE], 'characters': '\xAE' },
+ '&Racute;': { 'codepoints': [0x00154], 'characters': '\u0154' },
+ '&Rang;': { 'codepoints': [0x027EB], 'characters': '\u27EB' },
+ '&Rarr;': { 'codepoints': [0x021A0], 'characters': '\u21A0' },
+ '&Rarrtl;': { 'codepoints': [0x02916], 'characters': '\u2916' },
+ '&Rcaron;': { 'codepoints': [0x00158], 'characters': '\u0158' },
+ '&Rcedil;': { 'codepoints': [0x00156], 'characters': '\u0156' },
+ '&Rcy;': { 'codepoints': [0x00420], 'characters': '\u0420' },
+ '&Re;': { 'codepoints': [0x0211C], 'characters': '\u211C' },
+ '&ReverseElement;': { 'codepoints': [0x0220B], 'characters': '\u220B' },
+ '&ReverseEquilibrium;': { 'codepoints': [0x021CB], 'characters': '\u21CB' },
+ '&ReverseUpEquilibrium;': { 'codepoints': [0x0296F], 'characters': '\u296F' },
+ '&Rfr;': { 'codepoints': [0x0211C], 'characters': '\u211C' },
+ '&Rho;': { 'codepoints': [0x003A1], 'characters': '\u03A1' },
+ '&RightAngleBracket;': { 'codepoints': [0x027E9], 'characters': '\u27E9' },
+ '&RightArrow;': { 'codepoints': [0x02192], 'characters': '\u2192' },
+ '&RightArrowBar;': { 'codepoints': [0x021E5], 'characters': '\u21E5' },
+ '&RightArrowLeftArrow;': { 'codepoints': [0x021C4], 'characters': '\u21C4' },
+ '&RightCeiling;': { 'codepoints': [0x02309], 'characters': '\u2309' },
+ '&RightDoubleBracket;': { 'codepoints': [0x027E7], 'characters': '\u27E7' },
+ '&RightDownTeeVector;': { 'codepoints': [0x0295D], 'characters': '\u295D' },
+ '&RightDownVector;': { 'codepoints': [0x021C2], 'characters': '\u21C2' },
+ '&RightDownVectorBar;': { 'codepoints': [0x02955], 'characters': '\u2955' },
+ '&RightFloor;': { 'codepoints': [0x0230B], 'characters': '\u230B' },
+ '&RightTee;': { 'codepoints': [0x022A2], 'characters': '\u22A2' },
+ '&RightTeeArrow;': { 'codepoints': [0x021A6], 'characters': '\u21A6' },
+ '&RightTeeVector;': { 'codepoints': [0x0295B], 'characters': '\u295B' },
+ '&RightTriangle;': { 'codepoints': [0x022B3], 'characters': '\u22B3' },
+ '&RightTriangleBar;': { 'codepoints': [0x029D0], 'characters': '\u29D0' },
+ '&RightTriangleEqual;': { 'codepoints': [0x022B5], 'characters': '\u22B5' },
+ '&RightUpDownVector;': { 'codepoints': [0x0294F], 'characters': '\u294F' },
+ '&RightUpTeeVector;': { 'codepoints': [0x0295C], 'characters': '\u295C' },
+ '&RightUpVector;': { 'codepoints': [0x021BE], 'characters': '\u21BE' },
+ '&RightUpVectorBar;': { 'codepoints': [0x02954], 'characters': '\u2954' },
+ '&RightVector;': { 'codepoints': [0x021C0], 'characters': '\u21C0' },
+ '&RightVectorBar;': { 'codepoints': [0x02953], 'characters': '\u2953' },
+ '&Rightarrow;': { 'codepoints': [0x021D2], 'characters': '\u21D2' },
+ '&Ropf;': { 'codepoints': [0x0211D], 'characters': '\u211D' },
+ '&RoundImplies;': { 'codepoints': [0x02970], 'characters': '\u2970' },
+ '&Rrightarrow;': { 'codepoints': [0x021DB], 'characters': '\u21DB' },
+ '&Rscr;': { 'codepoints': [0x0211B], 'characters': '\u211B' },
+ '&Rsh;': { 'codepoints': [0x021B1], 'characters': '\u21B1' },
+ '&RuleDelayed;': { 'codepoints': [0x029F4], 'characters': '\u29F4' },
+ '&SHCHcy;': { 'codepoints': [0x00429], 'characters': '\u0429' },
+ '&SHcy;': { 'codepoints': [0x00428], 'characters': '\u0428' },
+ '&SOFTcy;': { 'codepoints': [0x0042C], 'characters': '\u042C' },
+ '&Sacute;': { 'codepoints': [0x0015A], 'characters': '\u015A' },
+ '&Sc;': { 'codepoints': [0x02ABC], 'characters': '\u2ABC' },
+ '&Scaron;': { 'codepoints': [0x00160], 'characters': '\u0160' },
+ '&Scedil;': { 'codepoints': [0x0015E], 'characters': '\u015E' },
+ '&Scirc;': { 'codepoints': [0x0015C], 'characters': '\u015C' },
+ '&Scy;': { 'codepoints': [0x00421], 'characters': '\u0421' },
+ '&Sfr;': { 'codepoints': [0x1D516], 'characters': '\uD835\uDD16' },
+ '&ShortDownArrow;': { 'codepoints': [0x02193], 'characters': '\u2193' },
+ '&ShortLeftArrow;': { 'codepoints': [0x02190], 'characters': '\u2190' },
+ '&ShortRightArrow;': { 'codepoints': [0x02192], 'characters': '\u2192' },
+ '&ShortUpArrow;': { 'codepoints': [0x02191], 'characters': '\u2191' },
+ '&Sigma;': { 'codepoints': [0x003A3], 'characters': '\u03A3' },
+ '&SmallCircle;': { 'codepoints': [0x02218], 'characters': '\u2218' },
+ '&Sopf;': { 'codepoints': [0x1D54A], 'characters': '\uD835\uDD4A' },
+ '&Sqrt;': { 'codepoints': [0x0221A], 'characters': '\u221A' },
+ '&Square;': { 'codepoints': [0x025A1], 'characters': '\u25A1' },
+ '&SquareIntersection;': { 'codepoints': [0x02293], 'characters': '\u2293' },
+ '&SquareSubset;': { 'codepoints': [0x0228F], 'characters': '\u228F' },
+ '&SquareSubsetEqual;': { 'codepoints': [0x02291], 'characters': '\u2291' },
+ '&SquareSuperset;': { 'codepoints': [0x02290], 'characters': '\u2290' },
+ '&SquareSupersetEqual;': { 'codepoints': [0x02292], 'characters': '\u2292' },
+ '&SquareUnion;': { 'codepoints': [0x02294], 'characters': '\u2294' },
+ '&Sscr;': { 'codepoints': [0x1D4AE], 'characters': '\uD835\uDCAE' },
+ '&Star;': { 'codepoints': [0x022C6], 'characters': '\u22C6' },
+ '&Sub;': { 'codepoints': [0x022D0], 'characters': '\u22D0' },
+ '&Subset;': { 'codepoints': [0x022D0], 'characters': '\u22D0' },
+ '&SubsetEqual;': { 'codepoints': [0x02286], 'characters': '\u2286' },
+ '&Succeeds;': { 'codepoints': [0x0227B], 'characters': '\u227B' },
+ '&SucceedsEqual;': { 'codepoints': [0x02AB0], 'characters': '\u2AB0' },
+ '&SucceedsSlantEqual;': { 'codepoints': [0x0227D], 'characters': '\u227D' },
+ '&SucceedsTilde;': { 'codepoints': [0x0227F], 'characters': '\u227F' },
+ '&SuchThat;': { 'codepoints': [0x0220B], 'characters': '\u220B' },
+ '&Sum;': { 'codepoints': [0x02211], 'characters': '\u2211' },
+ '&Sup;': { 'codepoints': [0x022D1], 'characters': '\u22D1' },
+ '&Superset;': { 'codepoints': [0x02283], 'characters': '\u2283' },
+ '&SupersetEqual;': { 'codepoints': [0x02287], 'characters': '\u2287' },
+ '&Supset;': { 'codepoints': [0x022D1], 'characters': '\u22D1' },
+ '&THORN': { 'codepoints': [0x000DE], 'characters': '\xDE' },
+ '&THORN;': { 'codepoints': [0x000DE], 'characters': '\xDE' },
+ '&TRADE;': { 'codepoints': [0x02122], 'characters': '\u2122' },
+ '&TSHcy;': { 'codepoints': [0x0040B], 'characters': '\u040B' },
+ '&TScy;': { 'codepoints': [0x00426], 'characters': '\u0426' },
+ '&Tab;': { 'codepoints': [0x00009], 'characters': '\x09' },
+ '&Tau;': { 'codepoints': [0x003A4], 'characters': '\u03A4' },
+ '&Tcaron;': { 'codepoints': [0x00164], 'characters': '\u0164' },
+ '&Tcedil;': { 'codepoints': [0x00162], 'characters': '\u0162' },
+ '&Tcy;': { 'codepoints': [0x00422], 'characters': '\u0422' },
+ '&Tfr;': { 'codepoints': [0x1D517], 'characters': '\uD835\uDD17' },
+ '&Therefore;': { 'codepoints': [0x02234], 'characters': '\u2234' },
+ '&Theta;': { 'codepoints': [0x00398], 'characters': '\u0398' },
+ '&ThickSpace;': { 'codepoints': [0x0205F, 0x0200A], 'characters': '\u205F\u200A' },
+ '&ThinSpace;': { 'codepoints': [0x02009], 'characters': '\u2009' },
+ '&Tilde;': { 'codepoints': [0x0223C], 'characters': '\u223C' },
+ '&TildeEqual;': { 'codepoints': [0x02243], 'characters': '\u2243' },
+ '&TildeFullEqual;': { 'codepoints': [0x02245], 'characters': '\u2245' },
+ '&TildeTilde;': { 'codepoints': [0x02248], 'characters': '\u2248' },
+ '&Topf;': { 'codepoints': [0x1D54B], 'characters': '\uD835\uDD4B' },
+ '&TripleDot;': { 'codepoints': [0x020DB], 'characters': '\u20DB' },
+ '&Tscr;': { 'codepoints': [0x1D4AF], 'characters': '\uD835\uDCAF' },
+ '&Tstrok;': { 'codepoints': [0x00166], 'characters': '\u0166' },
+ '&Uacute': { 'codepoints': [0x000DA], 'characters': '\xDA' },
+ '&Uacute;': { 'codepoints': [0x000DA], 'characters': '\xDA' },
+ '&Uarr;': { 'codepoints': [0x0219F], 'characters': '\u219F' },
+ '&Uarrocir;': { 'codepoints': [0x02949], 'characters': '\u2949' },
+ '&Ubrcy;': { 'codepoints': [0x0040E], 'characters': '\u040E' },
+ '&Ubreve;': { 'codepoints': [0x0016C], 'characters': '\u016C' },
+ '&Ucirc': { 'codepoints': [0x000DB], 'characters': '\xDB' },
+ '&Ucirc;': { 'codepoints': [0x000DB], 'characters': '\xDB' },
+ '&Ucy;': { 'codepoints': [0x00423], 'characters': '\u0423' },
+ '&Udblac;': { 'codepoints': [0x00170], 'characters': '\u0170' },
+ '&Ufr;': { 'codepoints': [0x1D518], 'characters': '\uD835\uDD18' },
+ '&Ugrave': { 'codepoints': [0x000D9], 'characters': '\xD9' },
+ '&Ugrave;': { 'codepoints': [0x000D9], 'characters': '\xD9' },
+ '&Umacr;': { 'codepoints': [0x0016A], 'characters': '\u016A' },
+ '&UnderBar;': { 'codepoints': [0x0005F], 'characters': '\x5F' },
+ '&UnderBrace;': { 'codepoints': [0x023DF], 'characters': '\u23DF' },
+ '&UnderBracket;': { 'codepoints': [0x023B5], 'characters': '\u23B5' },
+ '&UnderParenthesis;': { 'codepoints': [0x023DD], 'characters': '\u23DD' },
+ '&Union;': { 'codepoints': [0x022C3], 'characters': '\u22C3' },
+ '&UnionPlus;': { 'codepoints': [0x0228E], 'characters': '\u228E' },
+ '&Uogon;': { 'codepoints': [0x00172], 'characters': '\u0172' },
+ '&Uopf;': { 'codepoints': [0x1D54C], 'characters': '\uD835\uDD4C' },
+ '&UpArrow;': { 'codepoints': [0x02191], 'characters': '\u2191' },
+ '&UpArrowBar;': { 'codepoints': [0x02912], 'characters': '\u2912' },
+ '&UpArrowDownArrow;': { 'codepoints': [0x021C5], 'characters': '\u21C5' },
+ '&UpDownArrow;': { 'codepoints': [0x02195], 'characters': '\u2195' },
+ '&UpEquilibrium;': { 'codepoints': [0x0296E], 'characters': '\u296E' },
+ '&UpTee;': { 'codepoints': [0x022A5], 'characters': '\u22A5' },
+ '&UpTeeArrow;': { 'codepoints': [0x021A5], 'characters': '\u21A5' },
+ '&Uparrow;': { 'codepoints': [0x021D1], 'characters': '\u21D1' },
+ '&Updownarrow;': { 'codepoints': [0x021D5], 'characters': '\u21D5' },
+ '&UpperLeftArrow;': { 'codepoints': [0x02196], 'characters': '\u2196' },
+ '&UpperRightArrow;': { 'codepoints': [0x02197], 'characters': '\u2197' },
+ '&Upsi;': { 'codepoints': [0x003D2], 'characters': '\u03D2' },
+ '&Upsilon;': { 'codepoints': [0x003A5], 'characters': '\u03A5' },
+ '&Uring;': { 'codepoints': [0x0016E], 'characters': '\u016E' },
+ '&Uscr;': { 'codepoints': [0x1D4B0], 'characters': '\uD835\uDCB0' },
+ '&Utilde;': { 'codepoints': [0x00168], 'characters': '\u0168' },
+ '&Uuml': { 'codepoints': [0x000DC], 'characters': '\xDC' },
+ '&Uuml;': { 'codepoints': [0x000DC], 'characters': '\xDC' },
+ '&VDash;': { 'codepoints': [0x022AB], 'characters': '\u22AB' },
+ '&Vbar;': { 'codepoints': [0x02AEB], 'characters': '\u2AEB' },
+ '&Vcy;': { 'codepoints': [0x00412], 'characters': '\u0412' },
+ '&Vdash;': { 'codepoints': [0x022A9], 'characters': '\u22A9' },
+ '&Vdashl;': { 'codepoints': [0x02AE6], 'characters': '\u2AE6' },
+ '&Vee;': { 'codepoints': [0x022C1], 'characters': '\u22C1' },
+ '&Verbar;': { 'codepoints': [0x02016], 'characters': '\u2016' },
+ '&Vert;': { 'codepoints': [0x02016], 'characters': '\u2016' },
+ '&VerticalBar;': { 'codepoints': [0x02223], 'characters': '\u2223' },
+ '&VerticalLine;': { 'codepoints': [0x0007C], 'characters': '\x7C' },
+ '&VerticalSeparator;': { 'codepoints': [0x02758], 'characters': '\u2758' },
+ '&VerticalTilde;': { 'codepoints': [0x02240], 'characters': '\u2240' },
+ '&VeryThinSpace;': { 'codepoints': [0x0200A], 'characters': '\u200A' },
+ '&Vfr;': { 'codepoints': [0x1D519], 'characters': '\uD835\uDD19' },
+ '&Vopf;': { 'codepoints': [0x1D54D], 'characters': '\uD835\uDD4D' },
+ '&Vscr;': { 'codepoints': [0x1D4B1], 'characters': '\uD835\uDCB1' },
+ '&Vvdash;': { 'codepoints': [0x022AA], 'characters': '\u22AA' },
+ '&Wcirc;': { 'codepoints': [0x00174], 'characters': '\u0174' },
+ '&Wedge;': { 'codepoints': [0x022C0], 'characters': '\u22C0' },
+ '&Wfr;': { 'codepoints': [0x1D51A], 'characters': '\uD835\uDD1A' },
+ '&Wopf;': { 'codepoints': [0x1D54E], 'characters': '\uD835\uDD4E' },
+ '&Wscr;': { 'codepoints': [0x1D4B2], 'characters': '\uD835\uDCB2' },
+ '&Xfr;': { 'codepoints': [0x1D51B], 'characters': '\uD835\uDD1B' },
+ '&Xi;': { 'codepoints': [0x0039E], 'characters': '\u039E' },
+ '&Xopf;': { 'codepoints': [0x1D54F], 'characters': '\uD835\uDD4F' },
+ '&Xscr;': { 'codepoints': [0x1D4B3], 'characters': '\uD835\uDCB3' },
+ '&YAcy;': { 'codepoints': [0x0042F], 'characters': '\u042F' },
+ '&YIcy;': { 'codepoints': [0x00407], 'characters': '\u0407' },
+ '&YUcy;': { 'codepoints': [0x0042E], 'characters': '\u042E' },
+ '&Yacute': { 'codepoints': [0x000DD], 'characters': '\xDD' },
+ '&Yacute;': { 'codepoints': [0x000DD], 'characters': '\xDD' },
+ '&Ycirc;': { 'codepoints': [0x00176], 'characters': '\u0176' },
+ '&Ycy;': { 'codepoints': [0x0042B], 'characters': '\u042B' },
+ '&Yfr;': { 'codepoints': [0x1D51C], 'characters': '\uD835\uDD1C' },
+ '&Yopf;': { 'codepoints': [0x1D550], 'characters': '\uD835\uDD50' },
+ '&Yscr;': { 'codepoints': [0x1D4B4], 'characters': '\uD835\uDCB4' },
+ '&Yuml;': { 'codepoints': [0x00178], 'characters': '\u0178' },
+ '&ZHcy;': { 'codepoints': [0x00416], 'characters': '\u0416' },
+ '&Zacute;': { 'codepoints': [0x00179], 'characters': '\u0179' },
+ '&Zcaron;': { 'codepoints': [0x0017D], 'characters': '\u017D' },
+ '&Zcy;': { 'codepoints': [0x00417], 'characters': '\u0417' },
+ '&Zdot;': { 'codepoints': [0x0017B], 'characters': '\u017B' },
+ '&ZeroWidthSpace;': { 'codepoints': [0x0200B], 'characters': '\u200B' },
+ '&Zeta;': { 'codepoints': [0x00396], 'characters': '\u0396' },
+ '&Zfr;': { 'codepoints': [0x02128], 'characters': '\u2128' },
+ '&Zopf;': { 'codepoints': [0x02124], 'characters': '\u2124' },
+ '&Zscr;': { 'codepoints': [0x1D4B5], 'characters': '\uD835\uDCB5' },
+ '&aacute': { 'codepoints': [0x000E1], 'characters': '\xE1' },
+ '&aacute;': { 'codepoints': [0x000E1], 'characters': '\xE1' },
+ '&abreve;': { 'codepoints': [0x00103], 'characters': '\u0103' },
+ '&ac;': { 'codepoints': [0x0223E], 'characters': '\u223E' },
+ '&acE;': { 'codepoints': [0x0223E, 0x00333], 'characters': '\u223E\u0333' },
+ '&acd;': { 'codepoints': [0x0223F], 'characters': '\u223F' },
+ '&acirc': { 'codepoints': [0x000E2], 'characters': '\xE2' },
+ '&acirc;': { 'codepoints': [0x000E2], 'characters': '\xE2' },
+ '&acute': { 'codepoints': [0x000B4], 'characters': '\xB4' },
+ '&acute;': { 'codepoints': [0x000B4], 'characters': '\xB4' },
+ '&acy;': { 'codepoints': [0x00430], 'characters': '\u0430' },
+ '&aelig': { 'codepoints': [0x000E6], 'characters': '\xE6' },
+ '&aelig;': { 'codepoints': [0x000E6], 'characters': '\xE6' },
+ '&af;': { 'codepoints': [0x02061], 'characters': '\u2061' },
+ '&afr;': { 'codepoints': [0x1D51E], 'characters': '\uD835\uDD1E' },
+ '&agrave': { 'codepoints': [0x000E0], 'characters': '\xE0' },
+ '&agrave;': { 'codepoints': [0x000E0], 'characters': '\xE0' },
+ '&alefsym;': { 'codepoints': [0x02135], 'characters': '\u2135' },
+ '&aleph;': { 'codepoints': [0x02135], 'characters': '\u2135' },
+ '&alpha;': { 'codepoints': [0x003B1], 'characters': '\u03B1' },
+ '&amacr;': { 'codepoints': [0x00101], 'characters': '\u0101' },
+ '&amalg;': { 'codepoints': [0x02A3F], 'characters': '\u2A3F' },
+ '&amp': { 'codepoints': [0x00026], 'characters': '\x26' },
+ '&amp;': { 'codepoints': [0x00026], 'characters': '\x26' },
+ '&and;': { 'codepoints': [0x02227], 'characters': '\u2227' },
+ '&andand;': { 'codepoints': [0x02A55], 'characters': '\u2A55' },
+ '&andd;': { 'codepoints': [0x02A5C], 'characters': '\u2A5C' },
+ '&andslope;': { 'codepoints': [0x02A58], 'characters': '\u2A58' },
+ '&andv;': { 'codepoints': [0x02A5A], 'characters': '\u2A5A' },
+ '&ang;': { 'codepoints': [0x02220], 'characters': '\u2220' },
+ '&ange;': { 'codepoints': [0x029A4], 'characters': '\u29A4' },
+ '&angle;': { 'codepoints': [0x02220], 'characters': '\u2220' },
+ '&angmsd;': { 'codepoints': [0x02221], 'characters': '\u2221' },
+ '&angmsdaa;': { 'codepoints': [0x029A8], 'characters': '\u29A8' },
+ '&angmsdab;': { 'codepoints': [0x029A9], 'characters': '\u29A9' },
+ '&angmsdac;': { 'codepoints': [0x029AA], 'characters': '\u29AA' },
+ '&angmsdad;': { 'codepoints': [0x029AB], 'characters': '\u29AB' },
+ '&angmsdae;': { 'codepoints': [0x029AC], 'characters': '\u29AC' },
+ '&angmsdaf;': { 'codepoints': [0x029AD], 'characters': '\u29AD' },
+ '&angmsdag;': { 'codepoints': [0x029AE], 'characters': '\u29AE' },
+ '&angmsdah;': { 'codepoints': [0x029AF], 'characters': '\u29AF' },
+ '&angrt;': { 'codepoints': [0x0221F], 'characters': '\u221F' },
+ '&angrtvb;': { 'codepoints': [0x022BE], 'characters': '\u22BE' },
+ '&angrtvbd;': { 'codepoints': [0x0299D], 'characters': '\u299D' },
+ '&angsph;': { 'codepoints': [0x02222], 'characters': '\u2222' },
+ '&angst;': { 'codepoints': [0x000C5], 'characters': '\xC5' },
+ '&angzarr;': { 'codepoints': [0x0237C], 'characters': '\u237C' },
+ '&aogon;': { 'codepoints': [0x00105], 'characters': '\u0105' },
+ '&aopf;': { 'codepoints': [0x1D552], 'characters': '\uD835\uDD52' },
+ '&ap;': { 'codepoints': [0x02248], 'characters': '\u2248' },
+ '&apE;': { 'codepoints': [0x02A70], 'characters': '\u2A70' },
+ '&apacir;': { 'codepoints': [0x02A6F], 'characters': '\u2A6F' },
+ '&ape;': { 'codepoints': [0x0224A], 'characters': '\u224A' },
+ '&apid;': { 'codepoints': [0x0224B], 'characters': '\u224B' },
+ '&apos;': { 'codepoints': [0x00027], 'characters': '\x27' },
+ '&approx;': { 'codepoints': [0x02248], 'characters': '\u2248' },
+ '&approxeq;': { 'codepoints': [0x0224A], 'characters': '\u224A' },
+ '&aring': { 'codepoints': [0x000E5], 'characters': '\xE5' },
+ '&aring;': { 'codepoints': [0x000E5], 'characters': '\xE5' },
+ '&ascr;': { 'codepoints': [0x1D4B6], 'characters': '\uD835\uDCB6' },
+ '&ast;': { 'codepoints': [0x0002A], 'characters': '\x2A' },
+ '&asymp;': { 'codepoints': [0x02248], 'characters': '\u2248' },
+ '&asympeq;': { 'codepoints': [0x0224D], 'characters': '\u224D' },
+ '&atilde': { 'codepoints': [0x000E3], 'characters': '\xE3' },
+ '&atilde;': { 'codepoints': [0x000E3], 'characters': '\xE3' },
+ '&auml': { 'codepoints': [0x000E4], 'characters': '\xE4' },
+ '&auml;': { 'codepoints': [0x000E4], 'characters': '\xE4' },
+ '&awconint;': { 'codepoints': [0x02233], 'characters': '\u2233' },
+ '&awint;': { 'codepoints': [0x02A11], 'characters': '\u2A11' },
+ '&bNot;': { 'codepoints': [0x02AED], 'characters': '\u2AED' },
+ '&backcong;': { 'codepoints': [0x0224C], 'characters': '\u224C' },
+ '&backepsilon;': { 'codepoints': [0x003F6], 'characters': '\u03F6' },
+ '&backprime;': { 'codepoints': [0x02035], 'characters': '\u2035' },
+ '&backsim;': { 'codepoints': [0x0223D], 'characters': '\u223D' },
+ '&backsimeq;': { 'codepoints': [0x022CD], 'characters': '\u22CD' },
+ '&barvee;': { 'codepoints': [0x022BD], 'characters': '\u22BD' },
+ '&barwed;': { 'codepoints': [0x02305], 'characters': '\u2305' },
+ '&barwedge;': { 'codepoints': [0x02305], 'characters': '\u2305' },
+ '&bbrk;': { 'codepoints': [0x023B5], 'characters': '\u23B5' },
+ '&bbrktbrk;': { 'codepoints': [0x023B6], 'characters': '\u23B6' },
+ '&bcong;': { 'codepoints': [0x0224C], 'characters': '\u224C' },
+ '&bcy;': { 'codepoints': [0x00431], 'characters': '\u0431' },
+ '&bdquo;': { 'codepoints': [0x0201E], 'characters': '\u201E' },
+ '&becaus;': { 'codepoints': [0x02235], 'characters': '\u2235' },
+ '&because;': { 'codepoints': [0x02235], 'characters': '\u2235' },
+ '&bemptyv;': { 'codepoints': [0x029B0], 'characters': '\u29B0' },
+ '&bepsi;': { 'codepoints': [0x003F6], 'characters': '\u03F6' },
+ '&bernou;': { 'codepoints': [0x0212C], 'characters': '\u212C' },
+ '&beta;': { 'codepoints': [0x003B2], 'characters': '\u03B2' },
+ '&beth;': { 'codepoints': [0x02136], 'characters': '\u2136' },
+ '&between;': { 'codepoints': [0x0226C], 'characters': '\u226C' },
+ '&bfr;': { 'codepoints': [0x1D51F], 'characters': '\uD835\uDD1F' },
+ '&bigcap;': { 'codepoints': [0x022C2], 'characters': '\u22C2' },
+ '&bigcirc;': { 'codepoints': [0x025EF], 'characters': '\u25EF' },
+ '&bigcup;': { 'codepoints': [0x022C3], 'characters': '\u22C3' },
+ '&bigodot;': { 'codepoints': [0x02A00], 'characters': '\u2A00' },
+ '&bigoplus;': { 'codepoints': [0x02A01], 'characters': '\u2A01' },
+ '&bigotimes;': { 'codepoints': [0x02A02], 'characters': '\u2A02' },
+ '&bigsqcup;': { 'codepoints': [0x02A06], 'characters': '\u2A06' },
+ '&bigstar;': { 'codepoints': [0x02605], 'characters': '\u2605' },
+ '&bigtriangledown;': { 'codepoints': [0x025BD], 'characters': '\u25BD' },
+ '&bigtriangleup;': { 'codepoints': [0x025B3], 'characters': '\u25B3' },
+ '&biguplus;': { 'codepoints': [0x02A04], 'characters': '\u2A04' },
+ '&bigvee;': { 'codepoints': [0x022C1], 'characters': '\u22C1' },
+ '&bigwedge;': { 'codepoints': [0x022C0], 'characters': '\u22C0' },
+ '&bkarow;': { 'codepoints': [0x0290D], 'characters': '\u290D' },
+ '&blacklozenge;': { 'codepoints': [0x029EB], 'characters': '\u29EB' },
+ '&blacksquare;': { 'codepoints': [0x025AA], 'characters': '\u25AA' },
+ '&blacktriangle;': { 'codepoints': [0x025B4], 'characters': '\u25B4' },
+ '&blacktriangledown;': { 'codepoints': [0x025BE], 'characters': '\u25BE' },
+ '&blacktriangleleft;': { 'codepoints': [0x025C2], 'characters': '\u25C2' },
+ '&blacktriangleright;': { 'codepoints': [0x025B8], 'characters': '\u25B8' },
+ '&blank;': { 'codepoints': [0x02423], 'characters': '\u2423' },
+ '&blk12;': { 'codepoints': [0x02592], 'characters': '\u2592' },
+ '&blk14;': { 'codepoints': [0x02591], 'characters': '\u2591' },
+ '&blk34;': { 'codepoints': [0x02593], 'characters': '\u2593' },
+ '&block;': { 'codepoints': [0x02588], 'characters': '\u2588' },
+ '&bne;': { 'codepoints': [0x0003D, 0x020E5], 'characters': '\x3D\u20E5' },
+ '&bnequiv;': { 'codepoints': [0x02261, 0x020E5], 'characters': '\u2261\u20E5' },
+ '&bnot;': { 'codepoints': [0x02310], 'characters': '\u2310' },
+ '&bopf;': { 'codepoints': [0x1D553], 'characters': '\uD835\uDD53' },
+ '&bot;': { 'codepoints': [0x022A5], 'characters': '\u22A5' },
+ '&bottom;': { 'codepoints': [0x022A5], 'characters': '\u22A5' },
+ '&bowtie;': { 'codepoints': [0x022C8], 'characters': '\u22C8' },
+ '&boxDL;': { 'codepoints': [0x02557], 'characters': '\u2557' },
+ '&boxDR;': { 'codepoints': [0x02554], 'characters': '\u2554' },
+ '&boxDl;': { 'codepoints': [0x02556], 'characters': '\u2556' },
+ '&boxDr;': { 'codepoints': [0x02553], 'characters': '\u2553' },
+ '&boxH;': { 'codepoints': [0x02550], 'characters': '\u2550' },
+ '&boxHD;': { 'codepoints': [0x02566], 'characters': '\u2566' },
+ '&boxHU;': { 'codepoints': [0x02569], 'characters': '\u2569' },
+ '&boxHd;': { 'codepoints': [0x02564], 'characters': '\u2564' },
+ '&boxHu;': { 'codepoints': [0x02567], 'characters': '\u2567' },
+ '&boxUL;': { 'codepoints': [0x0255D], 'characters': '\u255D' },
+ '&boxUR;': { 'codepoints': [0x0255A], 'characters': '\u255A' },
+ '&boxUl;': { 'codepoints': [0x0255C], 'characters': '\u255C' },
+ '&boxUr;': { 'codepoints': [0x02559], 'characters': '\u2559' },
+ '&boxV;': { 'codepoints': [0x02551], 'characters': '\u2551' },
+ '&boxVH;': { 'codepoints': [0x0256C], 'characters': '\u256C' },
+ '&boxVL;': { 'codepoints': [0x02563], 'characters': '\u2563' },
+ '&boxVR;': { 'codepoints': [0x02560], 'characters': '\u2560' },
+ '&boxVh;': { 'codepoints': [0x0256B], 'characters': '\u256B' },
+ '&boxVl;': { 'codepoints': [0x02562], 'characters': '\u2562' },
+ '&boxVr;': { 'codepoints': [0x0255F], 'characters': '\u255F' },
+ '&boxbox;': { 'codepoints': [0x029C9], 'characters': '\u29C9' },
+ '&boxdL;': { 'codepoints': [0x02555], 'characters': '\u2555' },
+ '&boxdR;': { 'codepoints': [0x02552], 'characters': '\u2552' },
+ '&boxdl;': { 'codepoints': [0x02510], 'characters': '\u2510' },
+ '&boxdr;': { 'codepoints': [0x0250C], 'characters': '\u250C' },
+ '&boxh;': { 'codepoints': [0x02500], 'characters': '\u2500' },
+ '&boxhD;': { 'codepoints': [0x02565], 'characters': '\u2565' },
+ '&boxhU;': { 'codepoints': [0x02568], 'characters': '\u2568' },
+ '&boxhd;': { 'codepoints': [0x0252C], 'characters': '\u252C' },
+ '&boxhu;': { 'codepoints': [0x02534], 'characters': '\u2534' },
+ '&boxminus;': { 'codepoints': [0x0229F], 'characters': '\u229F' },
+ '&boxplus;': { 'codepoints': [0x0229E], 'characters': '\u229E' },
+ '&boxtimes;': { 'codepoints': [0x022A0], 'characters': '\u22A0' },
+ '&boxuL;': { 'codepoints': [0x0255B], 'characters': '\u255B' },
+ '&boxuR;': { 'codepoints': [0x02558], 'characters': '\u2558' },
+ '&boxul;': { 'codepoints': [0x02518], 'characters': '\u2518' },
+ '&boxur;': { 'codepoints': [0x02514], 'characters': '\u2514' },
+ '&boxv;': { 'codepoints': [0x02502], 'characters': '\u2502' },
+ '&boxvH;': { 'codepoints': [0x0256A], 'characters': '\u256A' },
+ '&boxvL;': { 'codepoints': [0x02561], 'characters': '\u2561' },
+ '&boxvR;': { 'codepoints': [0x0255E], 'characters': '\u255E' },
+ '&boxvh;': { 'codepoints': [0x0253C], 'characters': '\u253C' },
+ '&boxvl;': { 'codepoints': [0x02524], 'characters': '\u2524' },
+ '&boxvr;': { 'codepoints': [0x0251C], 'characters': '\u251C' },
+ '&bprime;': { 'codepoints': [0x02035], 'characters': '\u2035' },
+ '&breve;': { 'codepoints': [0x002D8], 'characters': '\u02D8' },
+ '&brvbar': { 'codepoints': [0x000A6], 'characters': '\xA6' },
+ '&brvbar;': { 'codepoints': [0x000A6], 'characters': '\xA6' },
+ '&bscr;': { 'codepoints': [0x1D4B7], 'characters': '\uD835\uDCB7' },
+ '&bsemi;': { 'codepoints': [0x0204F], 'characters': '\u204F' },
+ '&bsim;': { 'codepoints': [0x0223D], 'characters': '\u223D' },
+ '&bsime;': { 'codepoints': [0x022CD], 'characters': '\u22CD' },
+ '&bsol;': { 'codepoints': [0x0005C], 'characters': '\x5C' },
+ '&bsolb;': { 'codepoints': [0x029C5], 'characters': '\u29C5' },
+ '&bsolhsub;': { 'codepoints': [0x027C8], 'characters': '\u27C8' },
+ '&bull;': { 'codepoints': [0x02022], 'characters': '\u2022' },
+ '&bullet;': { 'codepoints': [0x02022], 'characters': '\u2022' },
+ '&bump;': { 'codepoints': [0x0224E], 'characters': '\u224E' },
+ '&bumpE;': { 'codepoints': [0x02AAE], 'characters': '\u2AAE' },
+ '&bumpe;': { 'codepoints': [0x0224F], 'characters': '\u224F' },
+ '&bumpeq;': { 'codepoints': [0x0224F], 'characters': '\u224F' },
+ '&cacute;': { 'codepoints': [0x00107], 'characters': '\u0107' },
+ '&cap;': { 'codepoints': [0x02229], 'characters': '\u2229' },
+ '&capand;': { 'codepoints': [0x02A44], 'characters': '\u2A44' },
+ '&capbrcup;': { 'codepoints': [0x02A49], 'characters': '\u2A49' },
+ '&capcap;': { 'codepoints': [0x02A4B], 'characters': '\u2A4B' },
+ '&capcup;': { 'codepoints': [0x02A47], 'characters': '\u2A47' },
+ '&capdot;': { 'codepoints': [0x02A40], 'characters': '\u2A40' },
+ '&caps;': { 'codepoints': [0x02229, 0x0FE00], 'characters': '\u2229\uFE00' },
+ '&caret;': { 'codepoints': [0x02041], 'characters': '\u2041' },
+ '&caron;': { 'codepoints': [0x002C7], 'characters': '\u02C7' },
+ '&ccaps;': { 'codepoints': [0x02A4D], 'characters': '\u2A4D' },
+ '&ccaron;': { 'codepoints': [0x0010D], 'characters': '\u010D' },
+ '&ccedil': { 'codepoints': [0x000E7], 'characters': '\xE7' },
+ '&ccedil;': { 'codepoints': [0x000E7], 'characters': '\xE7' },
+ '&ccirc;': { 'codepoints': [0x00109], 'characters': '\u0109' },
+ '&ccups;': { 'codepoints': [0x02A4C], 'characters': '\u2A4C' },
+ '&ccupssm;': { 'codepoints': [0x02A50], 'characters': '\u2A50' },
+ '&cdot;': { 'codepoints': [0x0010B], 'characters': '\u010B' },
+ '&cedil': { 'codepoints': [0x000B8], 'characters': '\xB8' },
+ '&cedil;': { 'codepoints': [0x000B8], 'characters': '\xB8' },
+ '&cemptyv;': { 'codepoints': [0x029B2], 'characters': '\u29B2' },
+ '&cent': { 'codepoints': [0x000A2], 'characters': '\xA2' },
+ '&cent;': { 'codepoints': [0x000A2], 'characters': '\xA2' },
+ '&centerdot;': { 'codepoints': [0x000B7], 'characters': '\xB7' },
+ '&cfr;': { 'codepoints': [0x1D520], 'characters': '\uD835\uDD20' },
+ '&chcy;': { 'codepoints': [0x00447], 'characters': '\u0447' },
+ '&check;': { 'codepoints': [0x02713], 'characters': '\u2713' },
+ '&checkmark;': { 'codepoints': [0x02713], 'characters': '\u2713' },
+ '&chi;': { 'codepoints': [0x003C7], 'characters': '\u03C7' },
+ '&cir;': { 'codepoints': [0x025CB], 'characters': '\u25CB' },
+ '&cirE;': { 'codepoints': [0x029C3], 'characters': '\u29C3' },
+ '&circ;': { 'codepoints': [0x002C6], 'characters': '\u02C6' },
+ '&circeq;': { 'codepoints': [0x02257], 'characters': '\u2257' },
+ '&circlearrowleft;': { 'codepoints': [0x021BA], 'characters': '\u21BA' },
+ '&circlearrowright;': { 'codepoints': [0x021BB], 'characters': '\u21BB' },
+ '&circledR;': { 'codepoints': [0x000AE], 'characters': '\xAE' },
+ '&circledS;': { 'codepoints': [0x024C8], 'characters': '\u24C8' },
+ '&circledast;': { 'codepoints': [0x0229B], 'characters': '\u229B' },
+ '&circledcirc;': { 'codepoints': [0x0229A], 'characters': '\u229A' },
+ '&circleddash;': { 'codepoints': [0x0229D], 'characters': '\u229D' },
+ '&cire;': { 'codepoints': [0x02257], 'characters': '\u2257' },
+ '&cirfnint;': { 'codepoints': [0x02A10], 'characters': '\u2A10' },
+ '&cirmid;': { 'codepoints': [0x02AEF], 'characters': '\u2AEF' },
+ '&cirscir;': { 'codepoints': [0x029C2], 'characters': '\u29C2' },
+ '&clubs;': { 'codepoints': [0x02663], 'characters': '\u2663' },
+ '&clubsuit;': { 'codepoints': [0x02663], 'characters': '\u2663' },
+ '&colon;': { 'codepoints': [0x0003A], 'characters': '\x3A' },
+ '&colone;': { 'codepoints': [0x02254], 'characters': '\u2254' },
+ '&coloneq;': { 'codepoints': [0x02254], 'characters': '\u2254' },
+ '&comma;': { 'codepoints': [0x0002C], 'characters': '\x2C' },
+ '&commat;': { 'codepoints': [0x00040], 'characters': '\x40' },
+ '&comp;': { 'codepoints': [0x02201], 'characters': '\u2201' },
+ '&compfn;': { 'codepoints': [0x02218], 'characters': '\u2218' },
+ '&complement;': { 'codepoints': [0x02201], 'characters': '\u2201' },
+ '&complexes;': { 'codepoints': [0x02102], 'characters': '\u2102' },
+ '&cong;': { 'codepoints': [0x02245], 'characters': '\u2245' },
+ '&congdot;': { 'codepoints': [0x02A6D], 'characters': '\u2A6D' },
+ '&conint;': { 'codepoints': [0x0222E], 'characters': '\u222E' },
+ '&copf;': { 'codepoints': [0x1D554], 'characters': '\uD835\uDD54' },
+ '&coprod;': { 'codepoints': [0x02210], 'characters': '\u2210' },
+ '&copy': { 'codepoints': [0x000A9], 'characters': '\xA9' },
+ '&copy;': { 'codepoints': [0x000A9], 'characters': '\xA9' },
+ '&copysr;': { 'codepoints': [0x02117], 'characters': '\u2117' },
+ '&crarr;': { 'codepoints': [0x021B5], 'characters': '\u21B5' },
+ '&cross;': { 'codepoints': [0x02717], 'characters': '\u2717' },
+ '&cscr;': { 'codepoints': [0x1D4B8], 'characters': '\uD835\uDCB8' },
+ '&csub;': { 'codepoints': [0x02ACF], 'characters': '\u2ACF' },
+ '&csube;': { 'codepoints': [0x02AD1], 'characters': '\u2AD1' },
+ '&csup;': { 'codepoints': [0x02AD0], 'characters': '\u2AD0' },
+ '&csupe;': { 'codepoints': [0x02AD2], 'characters': '\u2AD2' },
+ '&ctdot;': { 'codepoints': [0x022EF], 'characters': '\u22EF' },
+ '&cudarrl;': { 'codepoints': [0x02938], 'characters': '\u2938' },
+ '&cudarrr;': { 'codepoints': [0x02935], 'characters': '\u2935' },
+ '&cuepr;': { 'codepoints': [0x022DE], 'characters': '\u22DE' },
+ '&cuesc;': { 'codepoints': [0x022DF], 'characters': '\u22DF' },
+ '&cularr;': { 'codepoints': [0x021B6], 'characters': '\u21B6' },
+ '&cularrp;': { 'codepoints': [0x0293D], 'characters': '\u293D' },
+ '&cup;': { 'codepoints': [0x0222A], 'characters': '\u222A' },
+ '&cupbrcap;': { 'codepoints': [0x02A48], 'characters': '\u2A48' },
+ '&cupcap;': { 'codepoints': [0x02A46], 'characters': '\u2A46' },
+ '&cupcup;': { 'codepoints': [0x02A4A], 'characters': '\u2A4A' },
+ '&cupdot;': { 'codepoints': [0x0228D], 'characters': '\u228D' },
+ '&cupor;': { 'codepoints': [0x02A45], 'characters': '\u2A45' },
+ '&cups;': { 'codepoints': [0x0222A, 0x0FE00], 'characters': '\u222A\uFE00' },
+ '&curarr;': { 'codepoints': [0x021B7], 'characters': '\u21B7' },
+ '&curarrm;': { 'codepoints': [0x0293C], 'characters': '\u293C' },
+ '&curlyeqprec;': { 'codepoints': [0x022DE], 'characters': '\u22DE' },
+ '&curlyeqsucc;': { 'codepoints': [0x022DF], 'characters': '\u22DF' },
+ '&curlyvee;': { 'codepoints': [0x022CE], 'characters': '\u22CE' },
+ '&curlywedge;': { 'codepoints': [0x022CF], 'characters': '\u22CF' },
+ '&curren': { 'codepoints': [0x000A4], 'characters': '\xA4' },
+ '&curren;': { 'codepoints': [0x000A4], 'characters': '\xA4' },
+ '&curvearrowleft;': { 'codepoints': [0x021B6], 'characters': '\u21B6' },
+ '&curvearrowright;': { 'codepoints': [0x021B7], 'characters': '\u21B7' },
+ '&cuvee;': { 'codepoints': [0x022CE], 'characters': '\u22CE' },
+ '&cuwed;': { 'codepoints': [0x022CF], 'characters': '\u22CF' },
+ '&cwconint;': { 'codepoints': [0x02232], 'characters': '\u2232' },
+ '&cwint;': { 'codepoints': [0x02231], 'characters': '\u2231' },
+ '&cylcty;': { 'codepoints': [0x0232D], 'characters': '\u232D' },
+ '&dArr;': { 'codepoints': [0x021D3], 'characters': '\u21D3' },
+ '&dHar;': { 'codepoints': [0x02965], 'characters': '\u2965' },
+ '&dagger;': { 'codepoints': [0x02020], 'characters': '\u2020' },
+ '&daleth;': { 'codepoints': [0x02138], 'characters': '\u2138' },
+ '&darr;': { 'codepoints': [0x02193], 'characters': '\u2193' },
+ '&dash;': { 'codepoints': [0x02010], 'characters': '\u2010' },
+ '&dashv;': { 'codepoints': [0x022A3], 'characters': '\u22A3' },
+ '&dbkarow;': { 'codepoints': [0x0290F], 'characters': '\u290F' },
+ '&dblac;': { 'codepoints': [0x002DD], 'characters': '\u02DD' },
+ '&dcaron;': { 'codepoints': [0x0010F], 'characters': '\u010F' },
+ '&dcy;': { 'codepoints': [0x00434], 'characters': '\u0434' },
+ '&dd;': { 'codepoints': [0x02146], 'characters': '\u2146' },
+ '&ddagger;': { 'codepoints': [0x02021], 'characters': '\u2021' },
+ '&ddarr;': { 'codepoints': [0x021CA], 'characters': '\u21CA' },
+ '&ddotseq;': { 'codepoints': [0x02A77], 'characters': '\u2A77' },
+ '&deg': { 'codepoints': [0x000B0], 'characters': '\xB0' },
+ '&deg;': { 'codepoints': [0x000B0], 'characters': '\xB0' },
+ '&delta;': { 'codepoints': [0x003B4], 'characters': '\u03B4' },
+ '&demptyv;': { 'codepoints': [0x029B1], 'characters': '\u29B1' },
+ '&dfisht;': { 'codepoints': [0x0297F], 'characters': '\u297F' },
+ '&dfr;': { 'codepoints': [0x1D521], 'characters': '\uD835\uDD21' },
+ '&dharl;': { 'codepoints': [0x021C3], 'characters': '\u21C3' },
+ '&dharr;': { 'codepoints': [0x021C2], 'characters': '\u21C2' },
+ '&diam;': { 'codepoints': [0x022C4], 'characters': '\u22C4' },
+ '&diamond;': { 'codepoints': [0x022C4], 'characters': '\u22C4' },
+ '&diamondsuit;': { 'codepoints': [0x02666], 'characters': '\u2666' },
+ '&diams;': { 'codepoints': [0x02666], 'characters': '\u2666' },
+ '&die;': { 'codepoints': [0x000A8], 'characters': '\xA8' },
+ '&digamma;': { 'codepoints': [0x003DD], 'characters': '\u03DD' },
+ '&disin;': { 'codepoints': [0x022F2], 'characters': '\u22F2' },
+ '&div;': { 'codepoints': [0x000F7], 'characters': '\xF7' },
+ '&divide': { 'codepoints': [0x000F7], 'characters': '\xF7' },
+ '&divide;': { 'codepoints': [0x000F7], 'characters': '\xF7' },
+ '&divideontimes;': { 'codepoints': [0x022C7], 'characters': '\u22C7' },
+ '&divonx;': { 'codepoints': [0x022C7], 'characters': '\u22C7' },
+ '&djcy;': { 'codepoints': [0x00452], 'characters': '\u0452' },
+ '&dlcorn;': { 'codepoints': [0x0231E], 'characters': '\u231E' },
+ '&dlcrop;': { 'codepoints': [0x0230D], 'characters': '\u230D' },
+ '&dollar;': { 'codepoints': [0x00024], 'characters': '\x24' },
+ '&dopf;': { 'codepoints': [0x1D555], 'characters': '\uD835\uDD55' },
+ '&dot;': { 'codepoints': [0x002D9], 'characters': '\u02D9' },
+ '&doteq;': { 'codepoints': [0x02250], 'characters': '\u2250' },
+ '&doteqdot;': { 'codepoints': [0x02251], 'characters': '\u2251' },
+ '&dotminus;': { 'codepoints': [0x02238], 'characters': '\u2238' },
+ '&dotplus;': { 'codepoints': [0x02214], 'characters': '\u2214' },
+ '&dotsquare;': { 'codepoints': [0x022A1], 'characters': '\u22A1' },
+ '&doublebarwedge;': { 'codepoints': [0x02306], 'characters': '\u2306' },
+ '&downarrow;': { 'codepoints': [0x02193], 'characters': '\u2193' },
+ '&downdownarrows;': { 'codepoints': [0x021CA], 'characters': '\u21CA' },
+ '&downharpoonleft;': { 'codepoints': [0x021C3], 'characters': '\u21C3' },
+ '&downharpoonright;': { 'codepoints': [0x021C2], 'characters': '\u21C2' },
+ '&drbkarow;': { 'codepoints': [0x02910], 'characters': '\u2910' },
+ '&drcorn;': { 'codepoints': [0x0231F], 'characters': '\u231F' },
+ '&drcrop;': { 'codepoints': [0x0230C], 'characters': '\u230C' },
+ '&dscr;': { 'codepoints': [0x1D4B9], 'characters': '\uD835\uDCB9' },
+ '&dscy;': { 'codepoints': [0x00455], 'characters': '\u0455' },
+ '&dsol;': { 'codepoints': [0x029F6], 'characters': '\u29F6' },
+ '&dstrok;': { 'codepoints': [0x00111], 'characters': '\u0111' },
+ '&dtdot;': { 'codepoints': [0x022F1], 'characters': '\u22F1' },
+ '&dtri;': { 'codepoints': [0x025BF], 'characters': '\u25BF' },
+ '&dtrif;': { 'codepoints': [0x025BE], 'characters': '\u25BE' },
+ '&duarr;': { 'codepoints': [0x021F5], 'characters': '\u21F5' },
+ '&duhar;': { 'codepoints': [0x0296F], 'characters': '\u296F' },
+ '&dwangle;': { 'codepoints': [0x029A6], 'characters': '\u29A6' },
+ '&dzcy;': { 'codepoints': [0x0045F], 'characters': '\u045F' },
+ '&dzigrarr;': { 'codepoints': [0x027FF], 'characters': '\u27FF' },
+ '&eDDot;': { 'codepoints': [0x02A77], 'characters': '\u2A77' },
+ '&eDot;': { 'codepoints': [0x02251], 'characters': '\u2251' },
+ '&eacute': { 'codepoints': [0x000E9], 'characters': '\xE9' },
+ '&eacute;': { 'codepoints': [0x000E9], 'characters': '\xE9' },
+ '&easter;': { 'codepoints': [0x02A6E], 'characters': '\u2A6E' },
+ '&ecaron;': { 'codepoints': [0x0011B], 'characters': '\u011B' },
+ '&ecir;': { 'codepoints': [0x02256], 'characters': '\u2256' },
+ '&ecirc': { 'codepoints': [0x000EA], 'characters': '\xEA' },
+ '&ecirc;': { 'codepoints': [0x000EA], 'characters': '\xEA' },
+ '&ecolon;': { 'codepoints': [0x02255], 'characters': '\u2255' },
+ '&ecy;': { 'codepoints': [0x0044D], 'characters': '\u044D' },
+ '&edot;': { 'codepoints': [0x00117], 'characters': '\u0117' },
+ '&ee;': { 'codepoints': [0x02147], 'characters': '\u2147' },
+ '&efDot;': { 'codepoints': [0x02252], 'characters': '\u2252' },
+ '&efr;': { 'codepoints': [0x1D522], 'characters': '\uD835\uDD22' },
+ '&eg;': { 'codepoints': [0x02A9A], 'characters': '\u2A9A' },
+ '&egrave': { 'codepoints': [0x000E8], 'characters': '\xE8' },
+ '&egrave;': { 'codepoints': [0x000E8], 'characters': '\xE8' },
+ '&egs;': { 'codepoints': [0x02A96], 'characters': '\u2A96' },
+ '&egsdot;': { 'codepoints': [0x02A98], 'characters': '\u2A98' },
+ '&el;': { 'codepoints': [0x02A99], 'characters': '\u2A99' },
+ '&elinters;': { 'codepoints': [0x023E7], 'characters': '\u23E7' },
+ '&ell;': { 'codepoints': [0x02113], 'characters': '\u2113' },
+ '&els;': { 'codepoints': [0x02A95], 'characters': '\u2A95' },
+ '&elsdot;': { 'codepoints': [0x02A97], 'characters': '\u2A97' },
+ '&emacr;': { 'codepoints': [0x00113], 'characters': '\u0113' },
+ '&empty;': { 'codepoints': [0x02205], 'characters': '\u2205' },
+ '&emptyset;': { 'codepoints': [0x02205], 'characters': '\u2205' },
+ '&emptyv;': { 'codepoints': [0x02205], 'characters': '\u2205' },
+ '&emsp13;': { 'codepoints': [0x02004], 'characters': '\u2004' },
+ '&emsp14;': { 'codepoints': [0x02005], 'characters': '\u2005' },
+ '&emsp;': { 'codepoints': [0x02003], 'characters': '\u2003' },
+ '&eng;': { 'codepoints': [0x0014B], 'characters': '\u014B' },
+ '&ensp;': { 'codepoints': [0x02002], 'characters': '\u2002' },
+ '&eogon;': { 'codepoints': [0x00119], 'characters': '\u0119' },
+ '&eopf;': { 'codepoints': [0x1D556], 'characters': '\uD835\uDD56' },
+ '&epar;': { 'codepoints': [0x022D5], 'characters': '\u22D5' },
+ '&eparsl;': { 'codepoints': [0x029E3], 'characters': '\u29E3' },
+ '&eplus;': { 'codepoints': [0x02A71], 'characters': '\u2A71' },
+ '&epsi;': { 'codepoints': [0x003B5], 'characters': '\u03B5' },
+ '&epsilon;': { 'codepoints': [0x003B5], 'characters': '\u03B5' },
+ '&epsiv;': { 'codepoints': [0x003F5], 'characters': '\u03F5' },
+ '&eqcirc;': { 'codepoints': [0x02256], 'characters': '\u2256' },
+ '&eqcolon;': { 'codepoints': [0x02255], 'characters': '\u2255' },
+ '&eqsim;': { 'codepoints': [0x02242], 'characters': '\u2242' },
+ '&eqslantgtr;': { 'codepoints': [0x02A96], 'characters': '\u2A96' },
+ '&eqslantless;': { 'codepoints': [0x02A95], 'characters': '\u2A95' },
+ '&equals;': { 'codepoints': [0x0003D], 'characters': '\x3D' },
+ '&equest;': { 'codepoints': [0x0225F], 'characters': '\u225F' },
+ '&equiv;': { 'codepoints': [0x02261], 'characters': '\u2261' },
+ '&equivDD;': { 'codepoints': [0x02A78], 'characters': '\u2A78' },
+ '&eqvparsl;': { 'codepoints': [0x029E5], 'characters': '\u29E5' },
+ '&erDot;': { 'codepoints': [0x02253], 'characters': '\u2253' },
+ '&erarr;': { 'codepoints': [0x02971], 'characters': '\u2971' },
+ '&escr;': { 'codepoints': [0x0212F], 'characters': '\u212F' },
+ '&esdot;': { 'codepoints': [0x02250], 'characters': '\u2250' },
+ '&esim;': { 'codepoints': [0x02242], 'characters': '\u2242' },
+ '&eta;': { 'codepoints': [0x003B7], 'characters': '\u03B7' },
+ '&eth': { 'codepoints': [0x000F0], 'characters': '\xF0' },
+ '&eth;': { 'codepoints': [0x000F0], 'characters': '\xF0' },
+ '&euml': { 'codepoints': [0x000EB], 'characters': '\xEB' },
+ '&euml;': { 'codepoints': [0x000EB], 'characters': '\xEB' },
+ '&euro;': { 'codepoints': [0x020AC], 'characters': '\u20AC' },
+ '&excl;': { 'codepoints': [0x00021], 'characters': '\x21' },
+ '&exist;': { 'codepoints': [0x02203], 'characters': '\u2203' },
+ '&expectation;': { 'codepoints': [0x02130], 'characters': '\u2130' },
+ '&exponentiale;': { 'codepoints': [0x02147], 'characters': '\u2147' },
+ '&fallingdotseq;': { 'codepoints': [0x02252], 'characters': '\u2252' },
+ '&fcy;': { 'codepoints': [0x00444], 'characters': '\u0444' },
+ '&female;': { 'codepoints': [0x02640], 'characters': '\u2640' },
+ '&ffilig;': { 'codepoints': [0x0FB03], 'characters': '\uFB03' },
+ '&fflig;': { 'codepoints': [0x0FB00], 'characters': '\uFB00' },
+ '&ffllig;': { 'codepoints': [0x0FB04], 'characters': '\uFB04' },
+ '&ffr;': { 'codepoints': [0x1D523], 'characters': '\uD835\uDD23' },
+ '&filig;': { 'codepoints': [0x0FB01], 'characters': '\uFB01' },
+ '&fjlig;': { 'codepoints': [0x00066, 0x0006A], 'characters': '\x66\x6A' },
+ '&flat;': { 'codepoints': [0x0266D], 'characters': '\u266D' },
+ '&fllig;': { 'codepoints': [0x0FB02], 'characters': '\uFB02' },
+ '&fltns;': { 'codepoints': [0x025B1], 'characters': '\u25B1' },
+ '&fnof;': { 'codepoints': [0x00192], 'characters': '\u0192' },
+ '&fopf;': { 'codepoints': [0x1D557], 'characters': '\uD835\uDD57' },
+ '&forall;': { 'codepoints': [0x02200], 'characters': '\u2200' },
+ '&fork;': { 'codepoints': [0x022D4], 'characters': '\u22D4' },
+ '&forkv;': { 'codepoints': [0x02AD9], 'characters': '\u2AD9' },
+ '&fpartint;': { 'codepoints': [0x02A0D], 'characters': '\u2A0D' },
+ '&frac12': { 'codepoints': [0x000BD], 'characters': '\xBD' },
+ '&frac12;': { 'codepoints': [0x000BD], 'characters': '\xBD' },
+ '&frac13;': { 'codepoints': [0x02153], 'characters': '\u2153' },
+ '&frac14': { 'codepoints': [0x000BC], 'characters': '\xBC' },
+ '&frac14;': { 'codepoints': [0x000BC], 'characters': '\xBC' },
+ '&frac15;': { 'codepoints': [0x02155], 'characters': '\u2155' },
+ '&frac16;': { 'codepoints': [0x02159], 'characters': '\u2159' },
+ '&frac18;': { 'codepoints': [0x0215B], 'characters': '\u215B' },
+ '&frac23;': { 'codepoints': [0x02154], 'characters': '\u2154' },
+ '&frac25;': { 'codepoints': [0x02156], 'characters': '\u2156' },
+ '&frac34': { 'codepoints': [0x000BE], 'characters': '\xBE' },
+ '&frac34;': { 'codepoints': [0x000BE], 'characters': '\xBE' },
+ '&frac35;': { 'codepoints': [0x02157], 'characters': '\u2157' },
+ '&frac38;': { 'codepoints': [0x0215C], 'characters': '\u215C' },
+ '&frac45;': { 'codepoints': [0x02158], 'characters': '\u2158' },
+ '&frac56;': { 'codepoints': [0x0215A], 'characters': '\u215A' },
+ '&frac58;': { 'codepoints': [0x0215D], 'characters': '\u215D' },
+ '&frac78;': { 'codepoints': [0x0215E], 'characters': '\u215E' },
+ '&frasl;': { 'codepoints': [0x02044], 'characters': '\u2044' },
+ '&frown;': { 'codepoints': [0x02322], 'characters': '\u2322' },
+ '&fscr;': { 'codepoints': [0x1D4BB], 'characters': '\uD835\uDCBB' },
+ '&gE;': { 'codepoints': [0x02267], 'characters': '\u2267' },
+ '&gEl;': { 'codepoints': [0x02A8C], 'characters': '\u2A8C' },
+ '&gacute;': { 'codepoints': [0x001F5], 'characters': '\u01F5' },
+ '&gamma;': { 'codepoints': [0x003B3], 'characters': '\u03B3' },
+ '&gammad;': { 'codepoints': [0x003DD], 'characters': '\u03DD' },
+ '&gap;': { 'codepoints': [0x02A86], 'characters': '\u2A86' },
+ '&gbreve;': { 'codepoints': [0x0011F], 'characters': '\u011F' },
+ '&gcirc;': { 'codepoints': [0x0011D], 'characters': '\u011D' },
+ '&gcy;': { 'codepoints': [0x00433], 'characters': '\u0433' },
+ '&gdot;': { 'codepoints': [0x00121], 'characters': '\u0121' },
+ '&ge;': { 'codepoints': [0x02265], 'characters': '\u2265' },
+ '&gel;': { 'codepoints': [0x022DB], 'characters': '\u22DB' },
+ '&geq;': { 'codepoints': [0x02265], 'characters': '\u2265' },
+ '&geqq;': { 'codepoints': [0x02267], 'characters': '\u2267' },
+ '&geqslant;': { 'codepoints': [0x02A7E], 'characters': '\u2A7E' },
+ '&ges;': { 'codepoints': [0x02A7E], 'characters': '\u2A7E' },
+ '&gescc;': { 'codepoints': [0x02AA9], 'characters': '\u2AA9' },
+ '&gesdot;': { 'codepoints': [0x02A80], 'characters': '\u2A80' },
+ '&gesdoto;': { 'codepoints': [0x02A82], 'characters': '\u2A82' },
+ '&gesdotol;': { 'codepoints': [0x02A84], 'characters': '\u2A84' },
+ '&gesl;': { 'codepoints': [0x022DB, 0x0FE00], 'characters': '\u22DB\uFE00' },
+ '&gesles;': { 'codepoints': [0x02A94], 'characters': '\u2A94' },
+ '&gfr;': { 'codepoints': [0x1D524], 'characters': '\uD835\uDD24' },
+ '&gg;': { 'codepoints': [0x0226B], 'characters': '\u226B' },
+ '&ggg;': { 'codepoints': [0x022D9], 'characters': '\u22D9' },
+ '&gimel;': { 'codepoints': [0x02137], 'characters': '\u2137' },
+ '&gjcy;': { 'codepoints': [0x00453], 'characters': '\u0453' },
+ '&gl;': { 'codepoints': [0x02277], 'characters': '\u2277' },
+ '&glE;': { 'codepoints': [0x02A92], 'characters': '\u2A92' },
+ '&gla;': { 'codepoints': [0x02AA5], 'characters': '\u2AA5' },
+ '&glj;': { 'codepoints': [0x02AA4], 'characters': '\u2AA4' },
+ '&gnE;': { 'codepoints': [0x02269], 'characters': '\u2269' },
+ '&gnap;': { 'codepoints': [0x02A8A], 'characters': '\u2A8A' },
+ '&gnapprox;': { 'codepoints': [0x02A8A], 'characters': '\u2A8A' },
+ '&gne;': { 'codepoints': [0x02A88], 'characters': '\u2A88' },
+ '&gneq;': { 'codepoints': [0x02A88], 'characters': '\u2A88' },
+ '&gneqq;': { 'codepoints': [0x02269], 'characters': '\u2269' },
+ '&gnsim;': { 'codepoints': [0x022E7], 'characters': '\u22E7' },
+ '&gopf;': { 'codepoints': [0x1D558], 'characters': '\uD835\uDD58' },
+ '&grave;': { 'codepoints': [0x00060], 'characters': '\x60' },
+ '&gscr;': { 'codepoints': [0x0210A], 'characters': '\u210A' },
+ '&gsim;': { 'codepoints': [0x02273], 'characters': '\u2273' },
+ '&gsime;': { 'codepoints': [0x02A8E], 'characters': '\u2A8E' },
+ '&gsiml;': { 'codepoints': [0x02A90], 'characters': '\u2A90' },
+ '&gt': { 'codepoints': [0x0003E], 'characters': '\x3E' },
+ '&gt;': { 'codepoints': [0x0003E], 'characters': '\x3E' },
+ '&gtcc;': { 'codepoints': [0x02AA7], 'characters': '\u2AA7' },
+ '&gtcir;': { 'codepoints': [0x02A7A], 'characters': '\u2A7A' },
+ '&gtdot;': { 'codepoints': [0x022D7], 'characters': '\u22D7' },
+ '&gtlPar;': { 'codepoints': [0x02995], 'characters': '\u2995' },
+ '&gtquest;': { 'codepoints': [0x02A7C], 'characters': '\u2A7C' },
+ '&gtrapprox;': { 'codepoints': [0x02A86], 'characters': '\u2A86' },
+ '&gtrarr;': { 'codepoints': [0x02978], 'characters': '\u2978' },
+ '&gtrdot;': { 'codepoints': [0x022D7], 'characters': '\u22D7' },
+ '&gtreqless;': { 'codepoints': [0x022DB], 'characters': '\u22DB' },
+ '&gtreqqless;': { 'codepoints': [0x02A8C], 'characters': '\u2A8C' },
+ '&gtrless;': { 'codepoints': [0x02277], 'characters': '\u2277' },
+ '&gtrsim;': { 'codepoints': [0x02273], 'characters': '\u2273' },
+ '&gvertneqq;': { 'codepoints': [0x02269, 0x0FE00], 'characters': '\u2269\uFE00' },
+ '&gvnE;': { 'codepoints': [0x02269, 0x0FE00], 'characters': '\u2269\uFE00' },
+ '&hArr;': { 'codepoints': [0x021D4], 'characters': '\u21D4' },
+ '&hairsp;': { 'codepoints': [0x0200A], 'characters': '\u200A' },
+ '&half;': { 'codepoints': [0x000BD], 'characters': '\xBD' },
+ '&hamilt;': { 'codepoints': [0x0210B], 'characters': '\u210B' },
+ '&hardcy;': { 'codepoints': [0x0044A], 'characters': '\u044A' },
+ '&harr;': { 'codepoints': [0x02194], 'characters': '\u2194' },
+ '&harrcir;': { 'codepoints': [0x02948], 'characters': '\u2948' },
+ '&harrw;': { 'codepoints': [0x021AD], 'characters': '\u21AD' },
+ '&hbar;': { 'codepoints': [0x0210F], 'characters': '\u210F' },
+ '&hcirc;': { 'codepoints': [0x00125], 'characters': '\u0125' },
+ '&hearts;': { 'codepoints': [0x02665], 'characters': '\u2665' },
+ '&heartsuit;': { 'codepoints': [0x02665], 'characters': '\u2665' },
+ '&hellip;': { 'codepoints': [0x02026], 'characters': '\u2026' },
+ '&hercon;': { 'codepoints': [0x022B9], 'characters': '\u22B9' },
+ '&hfr;': { 'codepoints': [0x1D525], 'characters': '\uD835\uDD25' },
+ '&hksearow;': { 'codepoints': [0x02925], 'characters': '\u2925' },
+ '&hkswarow;': { 'codepoints': [0x02926], 'characters': '\u2926' },
+ '&hoarr;': { 'codepoints': [0x021FF], 'characters': '\u21FF' },
+ '&homtht;': { 'codepoints': [0x0223B], 'characters': '\u223B' },
+ '&hookleftarrow;': { 'codepoints': [0x021A9], 'characters': '\u21A9' },
+ '&hookrightarrow;': { 'codepoints': [0x021AA], 'characters': '\u21AA' },
+ '&hopf;': { 'codepoints': [0x1D559], 'characters': '\uD835\uDD59' },
+ '&horbar;': { 'codepoints': [0x02015], 'characters': '\u2015' },
+ '&hscr;': { 'codepoints': [0x1D4BD], 'characters': '\uD835\uDCBD' },
+ '&hslash;': { 'codepoints': [0x0210F], 'characters': '\u210F' },
+ '&hstrok;': { 'codepoints': [0x00127], 'characters': '\u0127' },
+ '&hybull;': { 'codepoints': [0x02043], 'characters': '\u2043' },
+ '&hyphen;': { 'codepoints': [0x02010], 'characters': '\u2010' },
+ '&iacute': { 'codepoints': [0x000ED], 'characters': '\xED' },
+ '&iacute;': { 'codepoints': [0x000ED], 'characters': '\xED' },
+ '&ic;': { 'codepoints': [0x02063], 'characters': '\u2063' },
+ '&icirc': { 'codepoints': [0x000EE], 'characters': '\xEE' },
+ '&icirc;': { 'codepoints': [0x000EE], 'characters': '\xEE' },
+ '&icy;': { 'codepoints': [0x00438], 'characters': '\u0438' },
+ '&iecy;': { 'codepoints': [0x00435], 'characters': '\u0435' },
+ '&iexcl': { 'codepoints': [0x000A1], 'characters': '\xA1' },
+ '&iexcl;': { 'codepoints': [0x000A1], 'characters': '\xA1' },
+ '&iff;': { 'codepoints': [0x021D4], 'characters': '\u21D4' },
+ '&ifr;': { 'codepoints': [0x1D526], 'characters': '\uD835\uDD26' },
+ '&igrave': { 'codepoints': [0x000EC], 'characters': '\xEC' },
+ '&igrave;': { 'codepoints': [0x000EC], 'characters': '\xEC' },
+ '&ii;': { 'codepoints': [0x02148], 'characters': '\u2148' },
+ '&iiiint;': { 'codepoints': [0x02A0C], 'characters': '\u2A0C' },
+ '&iiint;': { 'codepoints': [0x0222D], 'characters': '\u222D' },
+ '&iinfin;': { 'codepoints': [0x029DC], 'characters': '\u29DC' },
+ '&iiota;': { 'codepoints': [0x02129], 'characters': '\u2129' },
+ '&ijlig;': { 'codepoints': [0x00133], 'characters': '\u0133' },
+ '&imacr;': { 'codepoints': [0x0012B], 'characters': '\u012B' },
+ '&image;': { 'codepoints': [0x02111], 'characters': '\u2111' },
+ '&imagline;': { 'codepoints': [0x02110], 'characters': '\u2110' },
+ '&imagpart;': { 'codepoints': [0x02111], 'characters': '\u2111' },
+ '&imath;': { 'codepoints': [0x00131], 'characters': '\u0131' },
+ '&imof;': { 'codepoints': [0x022B7], 'characters': '\u22B7' },
+ '&imped;': { 'codepoints': [0x001B5], 'characters': '\u01B5' },
+ '&in;': { 'codepoints': [0x02208], 'characters': '\u2208' },
+ '&incare;': { 'codepoints': [0x02105], 'characters': '\u2105' },
+ '&infin;': { 'codepoints': [0x0221E], 'characters': '\u221E' },
+ '&infintie;': { 'codepoints': [0x029DD], 'characters': '\u29DD' },
+ '&inodot;': { 'codepoints': [0x00131], 'characters': '\u0131' },
+ '&int;': { 'codepoints': [0x0222B], 'characters': '\u222B' },
+ '&intcal;': { 'codepoints': [0x022BA], 'characters': '\u22BA' },
+ '&integers;': { 'codepoints': [0x02124], 'characters': '\u2124' },
+ '&intercal;': { 'codepoints': [0x022BA], 'characters': '\u22BA' },
+ '&intlarhk;': { 'codepoints': [0x02A17], 'characters': '\u2A17' },
+ '&intprod;': { 'codepoints': [0x02A3C], 'characters': '\u2A3C' },
+ '&iocy;': { 'codepoints': [0x00451], 'characters': '\u0451' },
+ '&iogon;': { 'codepoints': [0x0012F], 'characters': '\u012F' },
+ '&iopf;': { 'codepoints': [0x1D55A], 'characters': '\uD835\uDD5A' },
+ '&iota;': { 'codepoints': [0x003B9], 'characters': '\u03B9' },
+ '&iprod;': { 'codepoints': [0x02A3C], 'characters': '\u2A3C' },
+ '&iquest': { 'codepoints': [0x000BF], 'characters': '\xBF' },
+ '&iquest;': { 'codepoints': [0x000BF], 'characters': '\xBF' },
+ '&iscr;': { 'codepoints': [0x1D4BE], 'characters': '\uD835\uDCBE' },
+ '&isin;': { 'codepoints': [0x02208], 'characters': '\u2208' },
+ '&isinE;': { 'codepoints': [0x022F9], 'characters': '\u22F9' },
+ '&isindot;': { 'codepoints': [0x022F5], 'characters': '\u22F5' },
+ '&isins;': { 'codepoints': [0x022F4], 'characters': '\u22F4' },
+ '&isinsv;': { 'codepoints': [0x022F3], 'characters': '\u22F3' },
+ '&isinv;': { 'codepoints': [0x02208], 'characters': '\u2208' },
+ '&it;': { 'codepoints': [0x02062], 'characters': '\u2062' },
+ '&itilde;': { 'codepoints': [0x00129], 'characters': '\u0129' },
+ '&iukcy;': { 'codepoints': [0x00456], 'characters': '\u0456' },
+ '&iuml': { 'codepoints': [0x000EF], 'characters': '\xEF' },
+ '&iuml;': { 'codepoints': [0x000EF], 'characters': '\xEF' },
+ '&jcirc;': { 'codepoints': [0x00135], 'characters': '\u0135' },
+ '&jcy;': { 'codepoints': [0x00439], 'characters': '\u0439' },
+ '&jfr;': { 'codepoints': [0x1D527], 'characters': '\uD835\uDD27' },
+ '&jmath;': { 'codepoints': [0x00237], 'characters': '\u0237' },
+ '&jopf;': { 'codepoints': [0x1D55B], 'characters': '\uD835\uDD5B' },
+ '&jscr;': { 'codepoints': [0x1D4BF], 'characters': '\uD835\uDCBF' },
+ '&jsercy;': { 'codepoints': [0x00458], 'characters': '\u0458' },
+ '&jukcy;': { 'codepoints': [0x00454], 'characters': '\u0454' },
+ '&kappa;': { 'codepoints': [0x003BA], 'characters': '\u03BA' },
+ '&kappav;': { 'codepoints': [0x003F0], 'characters': '\u03F0' },
+ '&kcedil;': { 'codepoints': [0x00137], 'characters': '\u0137' },
+ '&kcy;': { 'codepoints': [0x0043A], 'characters': '\u043A' },
+ '&kfr;': { 'codepoints': [0x1D528], 'characters': '\uD835\uDD28' },
+ '&kgreen;': { 'codepoints': [0x00138], 'characters': '\u0138' },
+ '&khcy;': { 'codepoints': [0x00445], 'characters': '\u0445' },
+ '&kjcy;': { 'codepoints': [0x0045C], 'characters': '\u045C' },
+ '&kopf;': { 'codepoints': [0x1D55C], 'characters': '\uD835\uDD5C' },
+ '&kscr;': { 'codepoints': [0x1D4C0], 'characters': '\uD835\uDCC0' },
+ '&lAarr;': { 'codepoints': [0x021DA], 'characters': '\u21DA' },
+ '&lArr;': { 'codepoints': [0x021D0], 'characters': '\u21D0' },
+ '&lAtail;': { 'codepoints': [0x0291B], 'characters': '\u291B' },
+ '&lBarr;': { 'codepoints': [0x0290E], 'characters': '\u290E' },
+ '&lE;': { 'codepoints': [0x02266], 'characters': '\u2266' },
+ '&lEg;': { 'codepoints': [0x02A8B], 'characters': '\u2A8B' },
+ '&lHar;': { 'codepoints': [0x02962], 'characters': '\u2962' },
+ '&lacute;': { 'codepoints': [0x0013A], 'characters': '\u013A' },
+ '&laemptyv;': { 'codepoints': [0x029B4], 'characters': '\u29B4' },
+ '&lagran;': { 'codepoints': [0x02112], 'characters': '\u2112' },
+ '&lambda;': { 'codepoints': [0x003BB], 'characters': '\u03BB' },
+ '&lang;': { 'codepoints': [0x027E8], 'characters': '\u27E8' },
+ '&langd;': { 'codepoints': [0x02991], 'characters': '\u2991' },
+ '&langle;': { 'codepoints': [0x027E8], 'characters': '\u27E8' },
+ '&lap;': { 'codepoints': [0x02A85], 'characters': '\u2A85' },
+ '&laquo': { 'codepoints': [0x000AB], 'characters': '\xAB' },
+ '&laquo;': { 'codepoints': [0x000AB], 'characters': '\xAB' },
+ '&larr;': { 'codepoints': [0x02190], 'characters': '\u2190' },
+ '&larrb;': { 'codepoints': [0x021E4], 'characters': '\u21E4' },
+ '&larrbfs;': { 'codepoints': [0x0291F], 'characters': '\u291F' },
+ '&larrfs;': { 'codepoints': [0x0291D], 'characters': '\u291D' },
+ '&larrhk;': { 'codepoints': [0x021A9], 'characters': '\u21A9' },
+ '&larrlp;': { 'codepoints': [0x021AB], 'characters': '\u21AB' },
+ '&larrpl;': { 'codepoints': [0x02939], 'characters': '\u2939' },
+ '&larrsim;': { 'codepoints': [0x02973], 'characters': '\u2973' },
+ '&larrtl;': { 'codepoints': [0x021A2], 'characters': '\u21A2' },
+ '&lat;': { 'codepoints': [0x02AAB], 'characters': '\u2AAB' },
+ '&latail;': { 'codepoints': [0x02919], 'characters': '\u2919' },
+ '&late;': { 'codepoints': [0x02AAD], 'characters': '\u2AAD' },
+ '&lates;': { 'codepoints': [0x02AAD, 0x0FE00], 'characters': '\u2AAD\uFE00' },
+ '&lbarr;': { 'codepoints': [0x0290C], 'characters': '\u290C' },
+ '&lbbrk;': { 'codepoints': [0x02772], 'characters': '\u2772' },
+ '&lbrace;': { 'codepoints': [0x0007B], 'characters': '\x7B' },
+ '&lbrack;': { 'codepoints': [0x0005B], 'characters': '\x5B' },
+ '&lbrke;': { 'codepoints': [0x0298B], 'characters': '\u298B' },
+ '&lbrksld;': { 'codepoints': [0x0298F], 'characters': '\u298F' },
+ '&lbrkslu;': { 'codepoints': [0x0298D], 'characters': '\u298D' },
+ '&lcaron;': { 'codepoints': [0x0013E], 'characters': '\u013E' },
+ '&lcedil;': { 'codepoints': [0x0013C], 'characters': '\u013C' },
+ '&lceil;': { 'codepoints': [0x02308], 'characters': '\u2308' },
+ '&lcub;': { 'codepoints': [0x0007B], 'characters': '\x7B' },
+ '&lcy;': { 'codepoints': [0x0043B], 'characters': '\u043B' },
+ '&ldca;': { 'codepoints': [0x02936], 'characters': '\u2936' },
+ '&ldquo;': { 'codepoints': [0x0201C], 'characters': '\u201C' },
+ '&ldquor;': { 'codepoints': [0x0201E], 'characters': '\u201E' },
+ '&ldrdhar;': { 'codepoints': [0x02967], 'characters': '\u2967' },
+ '&ldrushar;': { 'codepoints': [0x0294B], 'characters': '\u294B' },
+ '&ldsh;': { 'codepoints': [0x021B2], 'characters': '\u21B2' },
+ '&le;': { 'codepoints': [0x02264], 'characters': '\u2264' },
+ '&leftarrow;': { 'codepoints': [0x02190], 'characters': '\u2190' },
+ '&leftarrowtail;': { 'codepoints': [0x021A2], 'characters': '\u21A2' },
+ '&leftharpoondown;': { 'codepoints': [0x021BD], 'characters': '\u21BD' },
+ '&leftharpoonup;': { 'codepoints': [0x021BC], 'characters': '\u21BC' },
+ '&leftleftarrows;': { 'codepoints': [0x021C7], 'characters': '\u21C7' },
+ '&leftrightarrow;': { 'codepoints': [0x02194], 'characters': '\u2194' },
+ '&leftrightarrows;': { 'codepoints': [0x021C6], 'characters': '\u21C6' },
+ '&leftrightharpoons;': { 'codepoints': [0x021CB], 'characters': '\u21CB' },
+ '&leftrightsquigarrow;': { 'codepoints': [0x021AD], 'characters': '\u21AD' },
+ '&leftthreetimes;': { 'codepoints': [0x022CB], 'characters': '\u22CB' },
+ '&leg;': { 'codepoints': [0x022DA], 'characters': '\u22DA' },
+ '&leq;': { 'codepoints': [0x02264], 'characters': '\u2264' },
+ '&leqq;': { 'codepoints': [0x02266], 'characters': '\u2266' },
+ '&leqslant;': { 'codepoints': [0x02A7D], 'characters': '\u2A7D' },
+ '&les;': { 'codepoints': [0x02A7D], 'characters': '\u2A7D' },
+ '&lescc;': { 'codepoints': [0x02AA8], 'characters': '\u2AA8' },
+ '&lesdot;': { 'codepoints': [0x02A7F], 'characters': '\u2A7F' },
+ '&lesdoto;': { 'codepoints': [0x02A81], 'characters': '\u2A81' },
+ '&lesdotor;': { 'codepoints': [0x02A83], 'characters': '\u2A83' },
+ '&lesg;': { 'codepoints': [0x022DA, 0x0FE00], 'characters': '\u22DA\uFE00' },
+ '&lesges;': { 'codepoints': [0x02A93], 'characters': '\u2A93' },
+ '&lessapprox;': { 'codepoints': [0x02A85], 'characters': '\u2A85' },
+ '&lessdot;': { 'codepoints': [0x022D6], 'characters': '\u22D6' },
+ '&lesseqgtr;': { 'codepoints': [0x022DA], 'characters': '\u22DA' },
+ '&lesseqqgtr;': { 'codepoints': [0x02A8B], 'characters': '\u2A8B' },
+ '&lessgtr;': { 'codepoints': [0x02276], 'characters': '\u2276' },
+ '&lesssim;': { 'codepoints': [0x02272], 'characters': '\u2272' },
+ '&lfisht;': { 'codepoints': [0x0297C], 'characters': '\u297C' },
+ '&lfloor;': { 'codepoints': [0x0230A], 'characters': '\u230A' },
+ '&lfr;': { 'codepoints': [0x1D529], 'characters': '\uD835\uDD29' },
+ '&lg;': { 'codepoints': [0x02276], 'characters': '\u2276' },
+ '&lgE;': { 'codepoints': [0x02A91], 'characters': '\u2A91' },
+ '&lhard;': { 'codepoints': [0x021BD], 'characters': '\u21BD' },
+ '&lharu;': { 'codepoints': [0x021BC], 'characters': '\u21BC' },
+ '&lharul;': { 'codepoints': [0x0296A], 'characters': '\u296A' },
+ '&lhblk;': { 'codepoints': [0x02584], 'characters': '\u2584' },
+ '&ljcy;': { 'codepoints': [0x00459], 'characters': '\u0459' },
+ '&ll;': { 'codepoints': [0x0226A], 'characters': '\u226A' },
+ '&llarr;': { 'codepoints': [0x021C7], 'characters': '\u21C7' },
+ '&llcorner;': { 'codepoints': [0x0231E], 'characters': '\u231E' },
+ '&llhard;': { 'codepoints': [0x0296B], 'characters': '\u296B' },
+ '&lltri;': { 'codepoints': [0x025FA], 'characters': '\u25FA' },
+ '&lmidot;': { 'codepoints': [0x00140], 'characters': '\u0140' },
+ '&lmoust;': { 'codepoints': [0x023B0], 'characters': '\u23B0' },
+ '&lmoustache;': { 'codepoints': [0x023B0], 'characters': '\u23B0' },
+ '&lnE;': { 'codepoints': [0x02268], 'characters': '\u2268' },
+ '&lnap;': { 'codepoints': [0x02A89], 'characters': '\u2A89' },
+ '&lnapprox;': { 'codepoints': [0x02A89], 'characters': '\u2A89' },
+ '&lne;': { 'codepoints': [0x02A87], 'characters': '\u2A87' },
+ '&lneq;': { 'codepoints': [0x02A87], 'characters': '\u2A87' },
+ '&lneqq;': { 'codepoints': [0x02268], 'characters': '\u2268' },
+ '&lnsim;': { 'codepoints': [0x022E6], 'characters': '\u22E6' },
+ '&loang;': { 'codepoints': [0x027EC], 'characters': '\u27EC' },
+ '&loarr;': { 'codepoints': [0x021FD], 'characters': '\u21FD' },
+ '&lobrk;': { 'codepoints': [0x027E6], 'characters': '\u27E6' },
+ '&longleftarrow;': { 'codepoints': [0x027F5], 'characters': '\u27F5' },
+ '&longleftrightarrow;': { 'codepoints': [0x027F7], 'characters': '\u27F7' },
+ '&longmapsto;': { 'codepoints': [0x027FC], 'characters': '\u27FC' },
+ '&longrightarrow;': { 'codepoints': [0x027F6], 'characters': '\u27F6' },
+ '&looparrowleft;': { 'codepoints': [0x021AB], 'characters': '\u21AB' },
+ '&looparrowright;': { 'codepoints': [0x021AC], 'characters': '\u21AC' },
+ '&lopar;': { 'codepoints': [0x02985], 'characters': '\u2985' },
+ '&lopf;': { 'codepoints': [0x1D55D], 'characters': '\uD835\uDD5D' },
+ '&loplus;': { 'codepoints': [0x02A2D], 'characters': '\u2A2D' },
+ '&lotimes;': { 'codepoints': [0x02A34], 'characters': '\u2A34' },
+ '&lowast;': { 'codepoints': [0x02217], 'characters': '\u2217' },
+ '&lowbar;': { 'codepoints': [0x0005F], 'characters': '\x5F' },
+ '&loz;': { 'codepoints': [0x025CA], 'characters': '\u25CA' },
+ '&lozenge;': { 'codepoints': [0x025CA], 'characters': '\u25CA' },
+ '&lozf;': { 'codepoints': [0x029EB], 'characters': '\u29EB' },
+ '&lpar;': { 'codepoints': [0x00028], 'characters': '\x28' },
+ '&lparlt;': { 'codepoints': [0x02993], 'characters': '\u2993' },
+ '&lrarr;': { 'codepoints': [0x021C6], 'characters': '\u21C6' },
+ '&lrcorner;': { 'codepoints': [0x0231F], 'characters': '\u231F' },
+ '&lrhar;': { 'codepoints': [0x021CB], 'characters': '\u21CB' },
+ '&lrhard;': { 'codepoints': [0x0296D], 'characters': '\u296D' },
+ '&lrm;': { 'codepoints': [0x0200E], 'characters': '\u200E' },
+ '&lrtri;': { 'codepoints': [0x022BF], 'characters': '\u22BF' },
+ '&lsaquo;': { 'codepoints': [0x02039], 'characters': '\u2039' },
+ '&lscr;': { 'codepoints': [0x1D4C1], 'characters': '\uD835\uDCC1' },
+ '&lsh;': { 'codepoints': [0x021B0], 'characters': '\u21B0' },
+ '&lsim;': { 'codepoints': [0x02272], 'characters': '\u2272' },
+ '&lsime;': { 'codepoints': [0x02A8D], 'characters': '\u2A8D' },
+ '&lsimg;': { 'codepoints': [0x02A8F], 'characters': '\u2A8F' },
+ '&lsqb;': { 'codepoints': [0x0005B], 'characters': '\x5B' },
+ '&lsquo;': { 'codepoints': [0x02018], 'characters': '\u2018' },
+ '&lsquor;': { 'codepoints': [0x0201A], 'characters': '\u201A' },
+ '&lstrok;': { 'codepoints': [0x00142], 'characters': '\u0142' },
+ '&lt': { 'codepoints': [0x0003C], 'characters': '\x3C' },
+ '&lt;': { 'codepoints': [0x0003C], 'characters': '\x3C' },
+ '&ltcc;': { 'codepoints': [0x02AA6], 'characters': '\u2AA6' },
+ '&ltcir;': { 'codepoints': [0x02A79], 'characters': '\u2A79' },
+ '&ltdot;': { 'codepoints': [0x022D6], 'characters': '\u22D6' },
+ '&lthree;': { 'codepoints': [0x022CB], 'characters': '\u22CB' },
+ '&ltimes;': { 'codepoints': [0x022C9], 'characters': '\u22C9' },
+ '&ltlarr;': { 'codepoints': [0x02976], 'characters': '\u2976' },
+ '&ltquest;': { 'codepoints': [0x02A7B], 'characters': '\u2A7B' },
+ '&ltrPar;': { 'codepoints': [0x02996], 'characters': '\u2996' },
+ '&ltri;': { 'codepoints': [0x025C3], 'characters': '\u25C3' },
+ '&ltrie;': { 'codepoints': [0x022B4], 'characters': '\u22B4' },
+ '&ltrif;': { 'codepoints': [0x025C2], 'characters': '\u25C2' },
+ '&lurdshar;': { 'codepoints': [0x0294A], 'characters': '\u294A' },
+ '&luruhar;': { 'codepoints': [0x02966], 'characters': '\u2966' },
+ '&lvertneqq;': { 'codepoints': [0x02268, 0x0FE00], 'characters': '\u2268\uFE00' },
+ '&lvnE;': { 'codepoints': [0x02268, 0x0FE00], 'characters': '\u2268\uFE00' },
+ '&mDDot;': { 'codepoints': [0x0223A], 'characters': '\u223A' },
+ '&macr': { 'codepoints': [0x000AF], 'characters': '\xAF' },
+ '&macr;': { 'codepoints': [0x000AF], 'characters': '\xAF' },
+ '&male;': { 'codepoints': [0x02642], 'characters': '\u2642' },
+ '&malt;': { 'codepoints': [0x02720], 'characters': '\u2720' },
+ '&maltese;': { 'codepoints': [0x02720], 'characters': '\u2720' },
+ '&map;': { 'codepoints': [0x021A6], 'characters': '\u21A6' },
+ '&mapsto;': { 'codepoints': [0x021A6], 'characters': '\u21A6' },
+ '&mapstodown;': { 'codepoints': [0x021A7], 'characters': '\u21A7' },
+ '&mapstoleft;': { 'codepoints': [0x021A4], 'characters': '\u21A4' },
+ '&mapstoup;': { 'codepoints': [0x021A5], 'characters': '\u21A5' },
+ '&marker;': { 'codepoints': [0x025AE], 'characters': '\u25AE' },
+ '&mcomma;': { 'codepoints': [0x02A29], 'characters': '\u2A29' },
+ '&mcy;': { 'codepoints': [0x0043C], 'characters': '\u043C' },
+ '&mdash;': { 'codepoints': [0x02014], 'characters': '\u2014' },
+ '&measuredangle;': { 'codepoints': [0x02221], 'characters': '\u2221' },
+ '&mfr;': { 'codepoints': [0x1D52A], 'characters': '\uD835\uDD2A' },
+ '&mho;': { 'codepoints': [0x02127], 'characters': '\u2127' },
+ '&micro': { 'codepoints': [0x000B5], 'characters': '\xB5' },
+ '&micro;': { 'codepoints': [0x000B5], 'characters': '\xB5' },
+ '&mid;': { 'codepoints': [0x02223], 'characters': '\u2223' },
+ '&midast;': { 'codepoints': [0x0002A], 'characters': '\x2A' },
+ '&midcir;': { 'codepoints': [0x02AF0], 'characters': '\u2AF0' },
+ '&middot': { 'codepoints': [0x000B7], 'characters': '\xB7' },
+ '&middot;': { 'codepoints': [0x000B7], 'characters': '\xB7' },
+ '&minus;': { 'codepoints': [0x02212], 'characters': '\u2212' },
+ '&minusb;': { 'codepoints': [0x0229F], 'characters': '\u229F' },
+ '&minusd;': { 'codepoints': [0x02238], 'characters': '\u2238' },
+ '&minusdu;': { 'codepoints': [0x02A2A], 'characters': '\u2A2A' },
+ '&mlcp;': { 'codepoints': [0x02ADB], 'characters': '\u2ADB' },
+ '&mldr;': { 'codepoints': [0x02026], 'characters': '\u2026' },
+ '&mnplus;': { 'codepoints': [0x02213], 'characters': '\u2213' },
+ '&models;': { 'codepoints': [0x022A7], 'characters': '\u22A7' },
+ '&mopf;': { 'codepoints': [0x1D55E], 'characters': '\uD835\uDD5E' },
+ '&mp;': { 'codepoints': [0x02213], 'characters': '\u2213' },
+ '&mscr;': { 'codepoints': [0x1D4C2], 'characters': '\uD835\uDCC2' },
+ '&mstpos;': { 'codepoints': [0x0223E], 'characters': '\u223E' },
+ '&mu;': { 'codepoints': [0x003BC], 'characters': '\u03BC' },
+ '&multimap;': { 'codepoints': [0x022B8], 'characters': '\u22B8' },
+ '&mumap;': { 'codepoints': [0x022B8], 'characters': '\u22B8' },
+ '&nGg;': { 'codepoints': [0x022D9, 0x00338], 'characters': '\u22D9\u0338' },
+ '&nGt;': { 'codepoints': [0x0226B, 0x020D2], 'characters': '\u226B\u20D2' },
+ '&nGtv;': { 'codepoints': [0x0226B, 0x00338], 'characters': '\u226B\u0338' },
+ '&nLeftarrow;': { 'codepoints': [0x021CD], 'characters': '\u21CD' },
+ '&nLeftrightarrow;': { 'codepoints': [0x021CE], 'characters': '\u21CE' },
+ '&nLl;': { 'codepoints': [0x022D8, 0x00338], 'characters': '\u22D8\u0338' },
+ '&nLt;': { 'codepoints': [0x0226A, 0x020D2], 'characters': '\u226A\u20D2' },
+ '&nLtv;': { 'codepoints': [0x0226A, 0x00338], 'characters': '\u226A\u0338' },
+ '&nRightarrow;': { 'codepoints': [0x021CF], 'characters': '\u21CF' },
+ '&nVDash;': { 'codepoints': [0x022AF], 'characters': '\u22AF' },
+ '&nVdash;': { 'codepoints': [0x022AE], 'characters': '\u22AE' },
+ '&nabla;': { 'codepoints': [0x02207], 'characters': '\u2207' },
+ '&nacute;': { 'codepoints': [0x00144], 'characters': '\u0144' },
+ '&nang;': { 'codepoints': [0x02220, 0x020D2], 'characters': '\u2220\u20D2' },
+ '&nap;': { 'codepoints': [0x02249], 'characters': '\u2249' },
+ '&napE;': { 'codepoints': [0x02A70, 0x00338], 'characters': '\u2A70\u0338' },
+ '&napid;': { 'codepoints': [0x0224B, 0x00338], 'characters': '\u224B\u0338' },
+ '&napos;': { 'codepoints': [0x00149], 'characters': '\u0149' },
+ '&napprox;': { 'codepoints': [0x02249], 'characters': '\u2249' },
+ '&natur;': { 'codepoints': [0x0266E], 'characters': '\u266E' },
+ '&natural;': { 'codepoints': [0x0266E], 'characters': '\u266E' },
+ '&naturals;': { 'codepoints': [0x02115], 'characters': '\u2115' },
+ '&nbsp': { 'codepoints': [0x000A0], 'characters': '\xA0' },
+ '&nbsp;': { 'codepoints': [0x000A0], 'characters': '\xA0' },
+ '&nbump;': { 'codepoints': [0x0224E, 0x00338], 'characters': '\u224E\u0338' },
+ '&nbumpe;': { 'codepoints': [0x0224F, 0x00338], 'characters': '\u224F\u0338' },
+ '&ncap;': { 'codepoints': [0x02A43], 'characters': '\u2A43' },
+ '&ncaron;': { 'codepoints': [0x00148], 'characters': '\u0148' },
+ '&ncedil;': { 'codepoints': [0x00146], 'characters': '\u0146' },
+ '&ncong;': { 'codepoints': [0x02247], 'characters': '\u2247' },
+ '&ncongdot;': { 'codepoints': [0x02A6D, 0x00338], 'characters': '\u2A6D\u0338' },
+ '&ncup;': { 'codepoints': [0x02A42], 'characters': '\u2A42' },
+ '&ncy;': { 'codepoints': [0x0043D], 'characters': '\u043D' },
+ '&ndash;': { 'codepoints': [0x02013], 'characters': '\u2013' },
+ '&ne;': { 'codepoints': [0x02260], 'characters': '\u2260' },
+ '&neArr;': { 'codepoints': [0x021D7], 'characters': '\u21D7' },
+ '&nearhk;': { 'codepoints': [0x02924], 'characters': '\u2924' },
+ '&nearr;': { 'codepoints': [0x02197], 'characters': '\u2197' },
+ '&nearrow;': { 'codepoints': [0x02197], 'characters': '\u2197' },
+ '&nedot;': { 'codepoints': [0x02250, 0x00338], 'characters': '\u2250\u0338' },
+ '&nequiv;': { 'codepoints': [0x02262], 'characters': '\u2262' },
+ '&nesear;': { 'codepoints': [0x02928], 'characters': '\u2928' },
+ '&nesim;': { 'codepoints': [0x02242, 0x00338], 'characters': '\u2242\u0338' },
+ '&nexist;': { 'codepoints': [0x02204], 'characters': '\u2204' },
+ '&nexists;': { 'codepoints': [0x02204], 'characters': '\u2204' },
+ '&nfr;': { 'codepoints': [0x1D52B], 'characters': '\uD835\uDD2B' },
+ '&ngE;': { 'codepoints': [0x02267, 0x00338], 'characters': '\u2267\u0338' },
+ '&nge;': { 'codepoints': [0x02271], 'characters': '\u2271' },
+ '&ngeq;': { 'codepoints': [0x02271], 'characters': '\u2271' },
+ '&ngeqq;': { 'codepoints': [0x02267, 0x00338], 'characters': '\u2267\u0338' },
+ '&ngeqslant;': { 'codepoints': [0x02A7E, 0x00338], 'characters': '\u2A7E\u0338' },
+ '&nges;': { 'codepoints': [0x02A7E, 0x00338], 'characters': '\u2A7E\u0338' },
+ '&ngsim;': { 'codepoints': [0x02275], 'characters': '\u2275' },
+ '&ngt;': { 'codepoints': [0x0226F], 'characters': '\u226F' },
+ '&ngtr;': { 'codepoints': [0x0226F], 'characters': '\u226F' },
+ '&nhArr;': { 'codepoints': [0x021CE], 'characters': '\u21CE' },
+ '&nharr;': { 'codepoints': [0x021AE], 'characters': '\u21AE' },
+ '&nhpar;': { 'codepoints': [0x02AF2], 'characters': '\u2AF2' },
+ '&ni;': { 'codepoints': [0x0220B], 'characters': '\u220B' },
+ '&nis;': { 'codepoints': [0x022FC], 'characters': '\u22FC' },
+ '&nisd;': { 'codepoints': [0x022FA], 'characters': '\u22FA' },
+ '&niv;': { 'codepoints': [0x0220B], 'characters': '\u220B' },
+ '&njcy;': { 'codepoints': [0x0045A], 'characters': '\u045A' },
+ '&nlArr;': { 'codepoints': [0x021CD], 'characters': '\u21CD' },
+ '&nlE;': { 'codepoints': [0x02266, 0x00338], 'characters': '\u2266\u0338' },
+ '&nlarr;': { 'codepoints': [0x0219A], 'characters': '\u219A' },
+ '&nldr;': { 'codepoints': [0x02025], 'characters': '\u2025' },
+ '&nle;': { 'codepoints': [0x02270], 'characters': '\u2270' },
+ '&nleftarrow;': { 'codepoints': [0x0219A], 'characters': '\u219A' },
+ '&nleftrightarrow;': { 'codepoints': [0x021AE], 'characters': '\u21AE' },
+ '&nleq;': { 'codepoints': [0x02270], 'characters': '\u2270' },
+ '&nleqq;': { 'codepoints': [0x02266, 0x00338], 'characters': '\u2266\u0338' },
+ '&nleqslant;': { 'codepoints': [0x02A7D, 0x00338], 'characters': '\u2A7D\u0338' },
+ '&nles;': { 'codepoints': [0x02A7D, 0x00338], 'characters': '\u2A7D\u0338' },
+ '&nless;': { 'codepoints': [0x0226E], 'characters': '\u226E' },
+ '&nlsim;': { 'codepoints': [0x02274], 'characters': '\u2274' },
+ '&nlt;': { 'codepoints': [0x0226E], 'characters': '\u226E' },
+ '&nltri;': { 'codepoints': [0x022EA], 'characters': '\u22EA' },
+ '&nltrie;': { 'codepoints': [0x022EC], 'characters': '\u22EC' },
+ '&nmid;': { 'codepoints': [0x02224], 'characters': '\u2224' },
+ '&nopf;': { 'codepoints': [0x1D55F], 'characters': '\uD835\uDD5F' },
+ '&not': { 'codepoints': [0x000AC], 'characters': '\xAC' },
+ '&not;': { 'codepoints': [0x000AC], 'characters': '\xAC' },
+ '&notin;': { 'codepoints': [0x02209], 'characters': '\u2209' },
+ '&notinE;': { 'codepoints': [0x022F9, 0x00338], 'characters': '\u22F9\u0338' },
+ '&notindot;': { 'codepoints': [0x022F5, 0x00338], 'characters': '\u22F5\u0338' },
+ '&notinva;': { 'codepoints': [0x02209], 'characters': '\u2209' },
+ '&notinvb;': { 'codepoints': [0x022F7], 'characters': '\u22F7' },
+ '&notinvc;': { 'codepoints': [0x022F6], 'characters': '\u22F6' },
+ '&notni;': { 'codepoints': [0x0220C], 'characters': '\u220C' },
+ '&notniva;': { 'codepoints': [0x0220C], 'characters': '\u220C' },
+ '&notnivb;': { 'codepoints': [0x022FE], 'characters': '\u22FE' },
+ '&notnivc;': { 'codepoints': [0x022FD], 'characters': '\u22FD' },
+ '&npar;': { 'codepoints': [0x02226], 'characters': '\u2226' },
+ '&nparallel;': { 'codepoints': [0x02226], 'characters': '\u2226' },
+ '&nparsl;': { 'codepoints': [0x02AFD, 0x020E5], 'characters': '\u2AFD\u20E5' },
+ '&npart;': { 'codepoints': [0x02202, 0x00338], 'characters': '\u2202\u0338' },
+ '&npolint;': { 'codepoints': [0x02A14], 'characters': '\u2A14' },
+ '&npr;': { 'codepoints': [0x02280], 'characters': '\u2280' },
+ '&nprcue;': { 'codepoints': [0x022E0], 'characters': '\u22E0' },
+ '&npre;': { 'codepoints': [0x02AAF, 0x00338], 'characters': '\u2AAF\u0338' },
+ '&nprec;': { 'codepoints': [0x02280], 'characters': '\u2280' },
+ '&npreceq;': { 'codepoints': [0x02AAF, 0x00338], 'characters': '\u2AAF\u0338' },
+ '&nrArr;': { 'codepoints': [0x021CF], 'characters': '\u21CF' },
+ '&nrarr;': { 'codepoints': [0x0219B], 'characters': '\u219B' },
+ '&nrarrc;': { 'codepoints': [0x02933, 0x00338], 'characters': '\u2933\u0338' },
+ '&nrarrw;': { 'codepoints': [0x0219D, 0x00338], 'characters': '\u219D\u0338' },
+ '&nrightarrow;': { 'codepoints': [0x0219B], 'characters': '\u219B' },
+ '&nrtri;': { 'codepoints': [0x022EB], 'characters': '\u22EB' },
+ '&nrtrie;': { 'codepoints': [0x022ED], 'characters': '\u22ED' },
+ '&nsc;': { 'codepoints': [0x02281], 'characters': '\u2281' },
+ '&nsccue;': { 'codepoints': [0x022E1], 'characters': '\u22E1' },
+ '&nsce;': { 'codepoints': [0x02AB0, 0x00338], 'characters': '\u2AB0\u0338' },
+ '&nscr;': { 'codepoints': [0x1D4C3], 'characters': '\uD835\uDCC3' },
+ '&nshortmid;': { 'codepoints': [0x02224], 'characters': '\u2224' },
+ '&nshortparallel;': { 'codepoints': [0x02226], 'characters': '\u2226' },
+ '&nsim;': { 'codepoints': [0x02241], 'characters': '\u2241' },
+ '&nsime;': { 'codepoints': [0x02244], 'characters': '\u2244' },
+ '&nsimeq;': { 'codepoints': [0x02244], 'characters': '\u2244' },
+ '&nsmid;': { 'codepoints': [0x02224], 'characters': '\u2224' },
+ '&nspar;': { 'codepoints': [0x02226], 'characters': '\u2226' },
+ '&nsqsube;': { 'codepoints': [0x022E2], 'characters': '\u22E2' },
+ '&nsqsupe;': { 'codepoints': [0x022E3], 'characters': '\u22E3' },
+ '&nsub;': { 'codepoints': [0x02284], 'characters': '\u2284' },
+ '&nsubE;': { 'codepoints': [0x02AC5, 0x00338], 'characters': '\u2AC5\u0338' },
+ '&nsube;': { 'codepoints': [0x02288], 'characters': '\u2288' },
+ '&nsubset;': { 'codepoints': [0x02282, 0x020D2], 'characters': '\u2282\u20D2' },
+ '&nsubseteq;': { 'codepoints': [0x02288], 'characters': '\u2288' },
+ '&nsubseteqq;': { 'codepoints': [0x02AC5, 0x00338], 'characters': '\u2AC5\u0338' },
+ '&nsucc;': { 'codepoints': [0x02281], 'characters': '\u2281' },
+ '&nsucceq;': { 'codepoints': [0x02AB0, 0x00338], 'characters': '\u2AB0\u0338' },
+ '&nsup;': { 'codepoints': [0x02285], 'characters': '\u2285' },
+ '&nsupE;': { 'codepoints': [0x02AC6, 0x00338], 'characters': '\u2AC6\u0338' },
+ '&nsupe;': { 'codepoints': [0x02289], 'characters': '\u2289' },
+ '&nsupset;': { 'codepoints': [0x02283, 0x020D2], 'characters': '\u2283\u20D2' },
+ '&nsupseteq;': { 'codepoints': [0x02289], 'characters': '\u2289' },
+ '&nsupseteqq;': { 'codepoints': [0x02AC6, 0x00338], 'characters': '\u2AC6\u0338' },
+ '&ntgl;': { 'codepoints': [0x02279], 'characters': '\u2279' },
+ '&ntilde': { 'codepoints': [0x000F1], 'characters': '\xF1' },
+ '&ntilde;': { 'codepoints': [0x000F1], 'characters': '\xF1' },
+ '&ntlg;': { 'codepoints': [0x02278], 'characters': '\u2278' },
+ '&ntriangleleft;': { 'codepoints': [0x022EA], 'characters': '\u22EA' },
+ '&ntrianglelefteq;': { 'codepoints': [0x022EC], 'characters': '\u22EC' },
+ '&ntriangleright;': { 'codepoints': [0x022EB], 'characters': '\u22EB' },
+ '&ntrianglerighteq;': { 'codepoints': [0x022ED], 'characters': '\u22ED' },
+ '&nu;': { 'codepoints': [0x003BD], 'characters': '\u03BD' },
+ '&num;': { 'codepoints': [0x00023], 'characters': '\x23' },
+ '&numero;': { 'codepoints': [0x02116], 'characters': '\u2116' },
+ '&numsp;': { 'codepoints': [0x02007], 'characters': '\u2007' },
+ '&nvDash;': { 'codepoints': [0x022AD], 'characters': '\u22AD' },
+ '&nvHarr;': { 'codepoints': [0x02904], 'characters': '\u2904' },
+ '&nvap;': { 'codepoints': [0x0224D, 0x020D2], 'characters': '\u224D\u20D2' },
+ '&nvdash;': { 'codepoints': [0x022AC], 'characters': '\u22AC' },
+ '&nvge;': { 'codepoints': [0x02265, 0x020D2], 'characters': '\u2265\u20D2' },
+ '&nvgt;': { 'codepoints': [0x0003E, 0x020D2], 'characters': '\x3E\u20D2' },
+ '&nvinfin;': { 'codepoints': [0x029DE], 'characters': '\u29DE' },
+ '&nvlArr;': { 'codepoints': [0x02902], 'characters': '\u2902' },
+ '&nvle;': { 'codepoints': [0x02264, 0x020D2], 'characters': '\u2264\u20D2' },
+ '&nvlt;': { 'codepoints': [0x0003C, 0x020D2], 'characters': '\x3C\u20D2' },
+ '&nvltrie;': { 'codepoints': [0x022B4, 0x020D2], 'characters': '\u22B4\u20D2' },
+ '&nvrArr;': { 'codepoints': [0x02903], 'characters': '\u2903' },
+ '&nvrtrie;': { 'codepoints': [0x022B5, 0x020D2], 'characters': '\u22B5\u20D2' },
+ '&nvsim;': { 'codepoints': [0x0223C, 0x020D2], 'characters': '\u223C\u20D2' },
+ '&nwArr;': { 'codepoints': [0x021D6], 'characters': '\u21D6' },
+ '&nwarhk;': { 'codepoints': [0x02923], 'characters': '\u2923' },
+ '&nwarr;': { 'codepoints': [0x02196], 'characters': '\u2196' },
+ '&nwarrow;': { 'codepoints': [0x02196], 'characters': '\u2196' },
+ '&nwnear;': { 'codepoints': [0x02927], 'characters': '\u2927' },
+ '&oS;': { 'codepoints': [0x024C8], 'characters': '\u24C8' },
+ '&oacute': { 'codepoints': [0x000F3], 'characters': '\xF3' },
+ '&oacute;': { 'codepoints': [0x000F3], 'characters': '\xF3' },
+ '&oast;': { 'codepoints': [0x0229B], 'characters': '\u229B' },
+ '&ocir;': { 'codepoints': [0x0229A], 'characters': '\u229A' },
+ '&ocirc': { 'codepoints': [0x000F4], 'characters': '\xF4' },
+ '&ocirc;': { 'codepoints': [0x000F4], 'characters': '\xF4' },
+ '&ocy;': { 'codepoints': [0x0043E], 'characters': '\u043E' },
+ '&odash;': { 'codepoints': [0x0229D], 'characters': '\u229D' },
+ '&odblac;': { 'codepoints': [0x00151], 'characters': '\u0151' },
+ '&odiv;': { 'codepoints': [0x02A38], 'characters': '\u2A38' },
+ '&odot;': { 'codepoints': [0x02299], 'characters': '\u2299' },
+ '&odsold;': { 'codepoints': [0x029BC], 'characters': '\u29BC' },
+ '&oelig;': { 'codepoints': [0x00153], 'characters': '\u0153' },
+ '&ofcir;': { 'codepoints': [0x029BF], 'characters': '\u29BF' },
+ '&ofr;': { 'codepoints': [0x1D52C], 'characters': '\uD835\uDD2C' },
+ '&ogon;': { 'codepoints': [0x002DB], 'characters': '\u02DB' },
+ '&ograve': { 'codepoints': [0x000F2], 'characters': '\xF2' },
+ '&ograve;': { 'codepoints': [0x000F2], 'characters': '\xF2' },
+ '&ogt;': { 'codepoints': [0x029C1], 'characters': '\u29C1' },
+ '&ohbar;': { 'codepoints': [0x029B5], 'characters': '\u29B5' },
+ '&ohm;': { 'codepoints': [0x003A9], 'characters': '\u03A9' },
+ '&oint;': { 'codepoints': [0x0222E], 'characters': '\u222E' },
+ '&olarr;': { 'codepoints': [0x021BA], 'characters': '\u21BA' },
+ '&olcir;': { 'codepoints': [0x029BE], 'characters': '\u29BE' },
+ '&olcross;': { 'codepoints': [0x029BB], 'characters': '\u29BB' },
+ '&oline;': { 'codepoints': [0x0203E], 'characters': '\u203E' },
+ '&olt;': { 'codepoints': [0x029C0], 'characters': '\u29C0' },
+ '&omacr;': { 'codepoints': [0x0014D], 'characters': '\u014D' },
+ '&omega;': { 'codepoints': [0x003C9], 'characters': '\u03C9' },
+ '&omicron;': { 'codepoints': [0x003BF], 'characters': '\u03BF' },
+ '&omid;': { 'codepoints': [0x029B6], 'characters': '\u29B6' },
+ '&ominus;': { 'codepoints': [0x02296], 'characters': '\u2296' },
+ '&oopf;': { 'codepoints': [0x1D560], 'characters': '\uD835\uDD60' },
+ '&opar;': { 'codepoints': [0x029B7], 'characters': '\u29B7' },
+ '&operp;': { 'codepoints': [0x029B9], 'characters': '\u29B9' },
+ '&oplus;': { 'codepoints': [0x02295], 'characters': '\u2295' },
+ '&or;': { 'codepoints': [0x02228], 'characters': '\u2228' },
+ '&orarr;': { 'codepoints': [0x021BB], 'characters': '\u21BB' },
+ '&ord;': { 'codepoints': [0x02A5D], 'characters': '\u2A5D' },
+ '&order;': { 'codepoints': [0x02134], 'characters': '\u2134' },
+ '&orderof;': { 'codepoints': [0x02134], 'characters': '\u2134' },
+ '&ordf': { 'codepoints': [0x000AA], 'characters': '\xAA' },
+ '&ordf;': { 'codepoints': [0x000AA], 'characters': '\xAA' },
+ '&ordm': { 'codepoints': [0x000BA], 'characters': '\xBA' },
+ '&ordm;': { 'codepoints': [0x000BA], 'characters': '\xBA' },
+ '&origof;': { 'codepoints': [0x022B6], 'characters': '\u22B6' },
+ '&oror;': { 'codepoints': [0x02A56], 'characters': '\u2A56' },
+ '&orslope;': { 'codepoints': [0x02A57], 'characters': '\u2A57' },
+ '&orv;': { 'codepoints': [0x02A5B], 'characters': '\u2A5B' },
+ '&oscr;': { 'codepoints': [0x02134], 'characters': '\u2134' },
+ '&oslash': { 'codepoints': [0x000F8], 'characters': '\xF8' },
+ '&oslash;': { 'codepoints': [0x000F8], 'characters': '\xF8' },
+ '&osol;': { 'codepoints': [0x02298], 'characters': '\u2298' },
+ '&otilde': { 'codepoints': [0x000F5], 'characters': '\xF5' },
+ '&otilde;': { 'codepoints': [0x000F5], 'characters': '\xF5' },
+ '&otimes;': { 'codepoints': [0x02297], 'characters': '\u2297' },
+ '&otimesas;': { 'codepoints': [0x02A36], 'characters': '\u2A36' },
+ '&ouml': { 'codepoints': [0x000F6], 'characters': '\xF6' },
+ '&ouml;': { 'codepoints': [0x000F6], 'characters': '\xF6' },
+ '&ovbar;': { 'codepoints': [0x0233D], 'characters': '\u233D' },
+ '&par;': { 'codepoints': [0x02225], 'characters': '\u2225' },
+ '&para': { 'codepoints': [0x000B6], 'characters': '\xB6' },
+ '&para;': { 'codepoints': [0x000B6], 'characters': '\xB6' },
+ '&parallel;': { 'codepoints': [0x02225], 'characters': '\u2225' },
+ '&parsim;': { 'codepoints': [0x02AF3], 'characters': '\u2AF3' },
+ '&parsl;': { 'codepoints': [0x02AFD], 'characters': '\u2AFD' },
+ '&part;': { 'codepoints': [0x02202], 'characters': '\u2202' },
+ '&pcy;': { 'codepoints': [0x0043F], 'characters': '\u043F' },
+ '&percnt;': { 'codepoints': [0x00025], 'characters': '\x25' },
+ '&period;': { 'codepoints': [0x0002E], 'characters': '\x2E' },
+ '&permil;': { 'codepoints': [0x02030], 'characters': '\u2030' },
+ '&perp;': { 'codepoints': [0x022A5], 'characters': '\u22A5' },
+ '&pertenk;': { 'codepoints': [0x02031], 'characters': '\u2031' },
+ '&pfr;': { 'codepoints': [0x1D52D], 'characters': '\uD835\uDD2D' },
+ '&phi;': { 'codepoints': [0x003C6], 'characters': '\u03C6' },
+ '&phiv;': { 'codepoints': [0x003D5], 'characters': '\u03D5' },
+ '&phmmat;': { 'codepoints': [0x02133], 'characters': '\u2133' },
+ '&phone;': { 'codepoints': [0x0260E], 'characters': '\u260E' },
+ '&pi;': { 'codepoints': [0x003C0], 'characters': '\u03C0' },
+ '&pitchfork;': { 'codepoints': [0x022D4], 'characters': '\u22D4' },
+ '&piv;': { 'codepoints': [0x003D6], 'characters': '\u03D6' },
+ '&planck;': { 'codepoints': [0x0210F], 'characters': '\u210F' },
+ '&planckh;': { 'codepoints': [0x0210E], 'characters': '\u210E' },
+ '&plankv;': { 'codepoints': [0x0210F], 'characters': '\u210F' },
+ '&plus;': { 'codepoints': [0x0002B], 'characters': '\x2B' },
+ '&plusacir;': { 'codepoints': [0x02A23], 'characters': '\u2A23' },
+ '&plusb;': { 'codepoints': [0x0229E], 'characters': '\u229E' },
+ '&pluscir;': { 'codepoints': [0x02A22], 'characters': '\u2A22' },
+ '&plusdo;': { 'codepoints': [0x02214], 'characters': '\u2214' },
+ '&plusdu;': { 'codepoints': [0x02A25], 'characters': '\u2A25' },
+ '&pluse;': { 'codepoints': [0x02A72], 'characters': '\u2A72' },
+ '&plusmn': { 'codepoints': [0x000B1], 'characters': '\xB1' },
+ '&plusmn;': { 'codepoints': [0x000B1], 'characters': '\xB1' },
+ '&plussim;': { 'codepoints': [0x02A26], 'characters': '\u2A26' },
+ '&plustwo;': { 'codepoints': [0x02A27], 'characters': '\u2A27' },
+ '&pm;': { 'codepoints': [0x000B1], 'characters': '\xB1' },
+ '&pointint;': { 'codepoints': [0x02A15], 'characters': '\u2A15' },
+ '&popf;': { 'codepoints': [0x1D561], 'characters': '\uD835\uDD61' },
+ '&pound': { 'codepoints': [0x000A3], 'characters': '\xA3' },
+ '&pound;': { 'codepoints': [0x000A3], 'characters': '\xA3' },
+ '&pr;': { 'codepoints': [0x0227A], 'characters': '\u227A' },
+ '&prE;': { 'codepoints': [0x02AB3], 'characters': '\u2AB3' },
+ '&prap;': { 'codepoints': [0x02AB7], 'characters': '\u2AB7' },
+ '&prcue;': { 'codepoints': [0x0227C], 'characters': '\u227C' },
+ '&pre;': { 'codepoints': [0x02AAF], 'characters': '\u2AAF' },
+ '&prec;': { 'codepoints': [0x0227A], 'characters': '\u227A' },
+ '&precapprox;': { 'codepoints': [0x02AB7], 'characters': '\u2AB7' },
+ '&preccurlyeq;': { 'codepoints': [0x0227C], 'characters': '\u227C' },
+ '&preceq;': { 'codepoints': [0x02AAF], 'characters': '\u2AAF' },
+ '&precnapprox;': { 'codepoints': [0x02AB9], 'characters': '\u2AB9' },
+ '&precneqq;': { 'codepoints': [0x02AB5], 'characters': '\u2AB5' },
+ '&precnsim;': { 'codepoints': [0x022E8], 'characters': '\u22E8' },
+ '&precsim;': { 'codepoints': [0x0227E], 'characters': '\u227E' },
+ '&prime;': { 'codepoints': [0x02032], 'characters': '\u2032' },
+ '&primes;': { 'codepoints': [0x02119], 'characters': '\u2119' },
+ '&prnE;': { 'codepoints': [0x02AB5], 'characters': '\u2AB5' },
+ '&prnap;': { 'codepoints': [0x02AB9], 'characters': '\u2AB9' },
+ '&prnsim;': { 'codepoints': [0x022E8], 'characters': '\u22E8' },
+ '&prod;': { 'codepoints': [0x0220F], 'characters': '\u220F' },
+ '&profalar;': { 'codepoints': [0x0232E], 'characters': '\u232E' },
+ '&profline;': { 'codepoints': [0x02312], 'characters': '\u2312' },
+ '&profsurf;': { 'codepoints': [0x02313], 'characters': '\u2313' },
+ '&prop;': { 'codepoints': [0x0221D], 'characters': '\u221D' },
+ '&propto;': { 'codepoints': [0x0221D], 'characters': '\u221D' },
+ '&prsim;': { 'codepoints': [0x0227E], 'characters': '\u227E' },
+ '&prurel;': { 'codepoints': [0x022B0], 'characters': '\u22B0' },
+ '&pscr;': { 'codepoints': [0x1D4C5], 'characters': '\uD835\uDCC5' },
+ '&psi;': { 'codepoints': [0x003C8], 'characters': '\u03C8' },
+ '&puncsp;': { 'codepoints': [0x02008], 'characters': '\u2008' },
+ '&qfr;': { 'codepoints': [0x1D52E], 'characters': '\uD835\uDD2E' },
+ '&qint;': { 'codepoints': [0x02A0C], 'characters': '\u2A0C' },
+ '&qopf;': { 'codepoints': [0x1D562], 'characters': '\uD835\uDD62' },
+ '&qprime;': { 'codepoints': [0x02057], 'characters': '\u2057' },
+ '&qscr;': { 'codepoints': [0x1D4C6], 'characters': '\uD835\uDCC6' },
+ '&quaternions;': { 'codepoints': [0x0210D], 'characters': '\u210D' },
+ '&quatint;': { 'codepoints': [0x02A16], 'characters': '\u2A16' },
+ '&quest;': { 'codepoints': [0x0003F], 'characters': '\x3F' },
+ '&questeq;': { 'codepoints': [0x0225F], 'characters': '\u225F' },
+ '&quot': { 'codepoints': [0x00022], 'characters': '\x22' },
+ '&quot;': { 'codepoints': [0x00022], 'characters': '\x22' },
+ '&rAarr;': { 'codepoints': [0x021DB], 'characters': '\u21DB' },
+ '&rArr;': { 'codepoints': [0x021D2], 'characters': '\u21D2' },
+ '&rAtail;': { 'codepoints': [0x0291C], 'characters': '\u291C' },
+ '&rBarr;': { 'codepoints': [0x0290F], 'characters': '\u290F' },
+ '&rHar;': { 'codepoints': [0x02964], 'characters': '\u2964' },
+ '&race;': { 'codepoints': [0x0223D, 0x00331], 'characters': '\u223D\u0331' },
+ '&racute;': { 'codepoints': [0x00155], 'characters': '\u0155' },
+ '&radic;': { 'codepoints': [0x0221A], 'characters': '\u221A' },
+ '&raemptyv;': { 'codepoints': [0x029B3], 'characters': '\u29B3' },
+ '&rang;': { 'codepoints': [0x027E9], 'characters': '\u27E9' },
+ '&rangd;': { 'codepoints': [0x02992], 'characters': '\u2992' },
+ '&range;': { 'codepoints': [0x029A5], 'characters': '\u29A5' },
+ '&rangle;': { 'codepoints': [0x027E9], 'characters': '\u27E9' },
+ '&raquo': { 'codepoints': [0x000BB], 'characters': '\xBB' },
+ '&raquo;': { 'codepoints': [0x000BB], 'characters': '\xBB' },
+ '&rarr;': { 'codepoints': [0x02192], 'characters': '\u2192' },
+ '&rarrap;': { 'codepoints': [0x02975], 'characters': '\u2975' },
+ '&rarrb;': { 'codepoints': [0x021E5], 'characters': '\u21E5' },
+ '&rarrbfs;': { 'codepoints': [0x02920], 'characters': '\u2920' },
+ '&rarrc;': { 'codepoints': [0x02933], 'characters': '\u2933' },
+ '&rarrfs;': { 'codepoints': [0x0291E], 'characters': '\u291E' },
+ '&rarrhk;': { 'codepoints': [0x021AA], 'characters': '\u21AA' },
+ '&rarrlp;': { 'codepoints': [0x021AC], 'characters': '\u21AC' },
+ '&rarrpl;': { 'codepoints': [0x02945], 'characters': '\u2945' },
+ '&rarrsim;': { 'codepoints': [0x02974], 'characters': '\u2974' },
+ '&rarrtl;': { 'codepoints': [0x021A3], 'characters': '\u21A3' },
+ '&rarrw;': { 'codepoints': [0x0219D], 'characters': '\u219D' },
+ '&ratail;': { 'codepoints': [0x0291A], 'characters': '\u291A' },
+ '&ratio;': { 'codepoints': [0x02236], 'characters': '\u2236' },
+ '&rationals;': { 'codepoints': [0x0211A], 'characters': '\u211A' },
+ '&rbarr;': { 'codepoints': [0x0290D], 'characters': '\u290D' },
+ '&rbbrk;': { 'codepoints': [0x02773], 'characters': '\u2773' },
+ '&rbrace;': { 'codepoints': [0x0007D], 'characters': '\x7D' },
+ '&rbrack;': { 'codepoints': [0x0005D], 'characters': '\x5D' },
+ '&rbrke;': { 'codepoints': [0x0298C], 'characters': '\u298C' },
+ '&rbrksld;': { 'codepoints': [0x0298E], 'characters': '\u298E' },
+ '&rbrkslu;': { 'codepoints': [0x02990], 'characters': '\u2990' },
+ '&rcaron;': { 'codepoints': [0x00159], 'characters': '\u0159' },
+ '&rcedil;': { 'codepoints': [0x00157], 'characters': '\u0157' },
+ '&rceil;': { 'codepoints': [0x02309], 'characters': '\u2309' },
+ '&rcub;': { 'codepoints': [0x0007D], 'characters': '\x7D' },
+ '&rcy;': { 'codepoints': [0x00440], 'characters': '\u0440' },
+ '&rdca;': { 'codepoints': [0x02937], 'characters': '\u2937' },
+ '&rdldhar;': { 'codepoints': [0x02969], 'characters': '\u2969' },
+ '&rdquo;': { 'codepoints': [0x0201D], 'characters': '\u201D' },
+ '&rdquor;': { 'codepoints': [0x0201D], 'characters': '\u201D' },
+ '&rdsh;': { 'codepoints': [0x021B3], 'characters': '\u21B3' },
+ '&real;': { 'codepoints': [0x0211C], 'characters': '\u211C' },
+ '&realine;': { 'codepoints': [0x0211B], 'characters': '\u211B' },
+ '&realpart;': { 'codepoints': [0x0211C], 'characters': '\u211C' },
+ '&reals;': { 'codepoints': [0x0211D], 'characters': '\u211D' },
+ '&rect;': { 'codepoints': [0x025AD], 'characters': '\u25AD' },
+ '&reg': { 'codepoints': [0x000AE], 'characters': '\xAE' },
+ '&reg;': { 'codepoints': [0x000AE], 'characters': '\xAE' },
+ '&rfisht;': { 'codepoints': [0x0297D], 'characters': '\u297D' },
+ '&rfloor;': { 'codepoints': [0x0230B], 'characters': '\u230B' },
+ '&rfr;': { 'codepoints': [0x1D52F], 'characters': '\uD835\uDD2F' },
+ '&rhard;': { 'codepoints': [0x021C1], 'characters': '\u21C1' },
+ '&rharu;': { 'codepoints': [0x021C0], 'characters': '\u21C0' },
+ '&rharul;': { 'codepoints': [0x0296C], 'characters': '\u296C' },
+ '&rho;': { 'codepoints': [0x003C1], 'characters': '\u03C1' },
+ '&rhov;': { 'codepoints': [0x003F1], 'characters': '\u03F1' },
+ '&rightarrow;': { 'codepoints': [0x02192], 'characters': '\u2192' },
+ '&rightarrowtail;': { 'codepoints': [0x021A3], 'characters': '\u21A3' },
+ '&rightharpoondown;': { 'codepoints': [0x021C1], 'characters': '\u21C1' },
+ '&rightharpoonup;': { 'codepoints': [0x021C0], 'characters': '\u21C0' },
+ '&rightleftarrows;': { 'codepoints': [0x021C4], 'characters': '\u21C4' },
+ '&rightleftharpoons;': { 'codepoints': [0x021CC], 'characters': '\u21CC' },
+ '&rightrightarrows;': { 'codepoints': [0x021C9], 'characters': '\u21C9' },
+ '&rightsquigarrow;': { 'codepoints': [0x0219D], 'characters': '\u219D' },
+ '&rightthreetimes;': { 'codepoints': [0x022CC], 'characters': '\u22CC' },
+ '&ring;': { 'codepoints': [0x002DA], 'characters': '\u02DA' },
+ '&risingdotseq;': { 'codepoints': [0x02253], 'characters': '\u2253' },
+ '&rlarr;': { 'codepoints': [0x021C4], 'characters': '\u21C4' },
+ '&rlhar;': { 'codepoints': [0x021CC], 'characters': '\u21CC' },
+ '&rlm;': { 'codepoints': [0x0200F], 'characters': '\u200F' },
+ '&rmoust;': { 'codepoints': [0x023B1], 'characters': '\u23B1' },
+ '&rmoustache;': { 'codepoints': [0x023B1], 'characters': '\u23B1' },
+ '&rnmid;': { 'codepoints': [0x02AEE], 'characters': '\u2AEE' },
+ '&roang;': { 'codepoints': [0x027ED], 'characters': '\u27ED' },
+ '&roarr;': { 'codepoints': [0x021FE], 'characters': '\u21FE' },
+ '&robrk;': { 'codepoints': [0x027E7], 'characters': '\u27E7' },
+ '&ropar;': { 'codepoints': [0x02986], 'characters': '\u2986' },
+ '&ropf;': { 'codepoints': [0x1D563], 'characters': '\uD835\uDD63' },
+ '&roplus;': { 'codepoints': [0x02A2E], 'characters': '\u2A2E' },
+ '&rotimes;': { 'codepoints': [0x02A35], 'characters': '\u2A35' },
+ '&rpar;': { 'codepoints': [0x00029], 'characters': '\x29' },
+ '&rpargt;': { 'codepoints': [0x02994], 'characters': '\u2994' },
+ '&rppolint;': { 'codepoints': [0x02A12], 'characters': '\u2A12' },
+ '&rrarr;': { 'codepoints': [0x021C9], 'characters': '\u21C9' },
+ '&rsaquo;': { 'codepoints': [0x0203A], 'characters': '\u203A' },
+ '&rscr;': { 'codepoints': [0x1D4C7], 'characters': '\uD835\uDCC7' },
+ '&rsh;': { 'codepoints': [0x021B1], 'characters': '\u21B1' },
+ '&rsqb;': { 'codepoints': [0x0005D], 'characters': '\x5D' },
+ '&rsquo;': { 'codepoints': [0x02019], 'characters': '\u2019' },
+ '&rsquor;': { 'codepoints': [0x02019], 'characters': '\u2019' },
+ '&rthree;': { 'codepoints': [0x022CC], 'characters': '\u22CC' },
+ '&rtimes;': { 'codepoints': [0x022CA], 'characters': '\u22CA' },
+ '&rtri;': { 'codepoints': [0x025B9], 'characters': '\u25B9' },
+ '&rtrie;': { 'codepoints': [0x022B5], 'characters': '\u22B5' },
+ '&rtrif;': { 'codepoints': [0x025B8], 'characters': '\u25B8' },
+ '&rtriltri;': { 'codepoints': [0x029CE], 'characters': '\u29CE' },
+ '&ruluhar;': { 'codepoints': [0x02968], 'characters': '\u2968' },
+ '&rx;': { 'codepoints': [0x0211E], 'characters': '\u211E' },
+ '&sacute;': { 'codepoints': [0x0015B], 'characters': '\u015B' },
+ '&sbquo;': { 'codepoints': [0x0201A], 'characters': '\u201A' },
+ '&sc;': { 'codepoints': [0x0227B], 'characters': '\u227B' },
+ '&scE;': { 'codepoints': [0x02AB4], 'characters': '\u2AB4' },
+ '&scap;': { 'codepoints': [0x02AB8], 'characters': '\u2AB8' },
+ '&scaron;': { 'codepoints': [0x00161], 'characters': '\u0161' },
+ '&sccue;': { 'codepoints': [0x0227D], 'characters': '\u227D' },
+ '&sce;': { 'codepoints': [0x02AB0], 'characters': '\u2AB0' },
+ '&scedil;': { 'codepoints': [0x0015F], 'characters': '\u015F' },
+ '&scirc;': { 'codepoints': [0x0015D], 'characters': '\u015D' },
+ '&scnE;': { 'codepoints': [0x02AB6], 'characters': '\u2AB6' },
+ '&scnap;': { 'codepoints': [0x02ABA], 'characters': '\u2ABA' },
+ '&scnsim;': { 'codepoints': [0x022E9], 'characters': '\u22E9' },
+ '&scpolint;': { 'codepoints': [0x02A13], 'characters': '\u2A13' },
+ '&scsim;': { 'codepoints': [0x0227F], 'characters': '\u227F' },
+ '&scy;': { 'codepoints': [0x00441], 'characters': '\u0441' },
+ '&sdot;': { 'codepoints': [0x022C5], 'characters': '\u22C5' },
+ '&sdotb;': { 'codepoints': [0x022A1], 'characters': '\u22A1' },
+ '&sdote;': { 'codepoints': [0x02A66], 'characters': '\u2A66' },
+ '&seArr;': { 'codepoints': [0x021D8], 'characters': '\u21D8' },
+ '&searhk;': { 'codepoints': [0x02925], 'characters': '\u2925' },
+ '&searr;': { 'codepoints': [0x02198], 'characters': '\u2198' },
+ '&searrow;': { 'codepoints': [0x02198], 'characters': '\u2198' },
+ '&sect': { 'codepoints': [0x000A7], 'characters': '\xA7' },
+ '&sect;': { 'codepoints': [0x000A7], 'characters': '\xA7' },
+ '&semi;': { 'codepoints': [0x0003B], 'characters': '\x3B' },
+ '&seswar;': { 'codepoints': [0x02929], 'characters': '\u2929' },
+ '&setminus;': { 'codepoints': [0x02216], 'characters': '\u2216' },
+ '&setmn;': { 'codepoints': [0x02216], 'characters': '\u2216' },
+ '&sext;': { 'codepoints': [0x02736], 'characters': '\u2736' },
+ '&sfr;': { 'codepoints': [0x1D530], 'characters': '\uD835\uDD30' },
+ '&sfrown;': { 'codepoints': [0x02322], 'characters': '\u2322' },
+ '&sharp;': { 'codepoints': [0x0266F], 'characters': '\u266F' },
+ '&shchcy;': { 'codepoints': [0x00449], 'characters': '\u0449' },
+ '&shcy;': { 'codepoints': [0x00448], 'characters': '\u0448' },
+ '&shortmid;': { 'codepoints': [0x02223], 'characters': '\u2223' },
+ '&shortparallel;': { 'codepoints': [0x02225], 'characters': '\u2225' },
+ '&shy': { 'codepoints': [0x000AD], 'characters': '\xAD' },
+ '&shy;': { 'codepoints': [0x000AD], 'characters': '\xAD' },
+ '&sigma;': { 'codepoints': [0x003C3], 'characters': '\u03C3' },
+ '&sigmaf;': { 'codepoints': [0x003C2], 'characters': '\u03C2' },
+ '&sigmav;': { 'codepoints': [0x003C2], 'characters': '\u03C2' },
+ '&sim;': { 'codepoints': [0x0223C], 'characters': '\u223C' },
+ '&simdot;': { 'codepoints': [0x02A6A], 'characters': '\u2A6A' },
+ '&sime;': { 'codepoints': [0x02243], 'characters': '\u2243' },
+ '&simeq;': { 'codepoints': [0x02243], 'characters': '\u2243' },
+ '&simg;': { 'codepoints': [0x02A9E], 'characters': '\u2A9E' },
+ '&simgE;': { 'codepoints': [0x02AA0], 'characters': '\u2AA0' },
+ '&siml;': { 'codepoints': [0x02A9D], 'characters': '\u2A9D' },
+ '&simlE;': { 'codepoints': [0x02A9F], 'characters': '\u2A9F' },
+ '&simne;': { 'codepoints': [0x02246], 'characters': '\u2246' },
+ '&simplus;': { 'codepoints': [0x02A24], 'characters': '\u2A24' },
+ '&simrarr;': { 'codepoints': [0x02972], 'characters': '\u2972' },
+ '&slarr;': { 'codepoints': [0x02190], 'characters': '\u2190' },
+ '&smallsetminus;': { 'codepoints': [0x02216], 'characters': '\u2216' },
+ '&smashp;': { 'codepoints': [0x02A33], 'characters': '\u2A33' },
+ '&smeparsl;': { 'codepoints': [0x029E4], 'characters': '\u29E4' },
+ '&smid;': { 'codepoints': [0x02223], 'characters': '\u2223' },
+ '&smile;': { 'codepoints': [0x02323], 'characters': '\u2323' },
+ '&smt;': { 'codepoints': [0x02AAA], 'characters': '\u2AAA' },
+ '&smte;': { 'codepoints': [0x02AAC], 'characters': '\u2AAC' },
+ '&smtes;': { 'codepoints': [0x02AAC, 0x0FE00], 'characters': '\u2AAC\uFE00' },
+ '&softcy;': { 'codepoints': [0x0044C], 'characters': '\u044C' },
+ '&sol;': { 'codepoints': [0x0002F], 'characters': '\x2F' },
+ '&solb;': { 'codepoints': [0x029C4], 'characters': '\u29C4' },
+ '&solbar;': { 'codepoints': [0x0233F], 'characters': '\u233F' },
+ '&sopf;': { 'codepoints': [0x1D564], 'characters': '\uD835\uDD64' },
+ '&spades;': { 'codepoints': [0x02660], 'characters': '\u2660' },
+ '&spadesuit;': { 'codepoints': [0x02660], 'characters': '\u2660' },
+ '&spar;': { 'codepoints': [0x02225], 'characters': '\u2225' },
+ '&sqcap;': { 'codepoints': [0x02293], 'characters': '\u2293' },
+ '&sqcaps;': { 'codepoints': [0x02293, 0x0FE00], 'characters': '\u2293\uFE00' },
+ '&sqcup;': { 'codepoints': [0x02294], 'characters': '\u2294' },
+ '&sqcups;': { 'codepoints': [0x02294, 0x0FE00], 'characters': '\u2294\uFE00' },
+ '&sqsub;': { 'codepoints': [0x0228F], 'characters': '\u228F' },
+ '&sqsube;': { 'codepoints': [0x02291], 'characters': '\u2291' },
+ '&sqsubset;': { 'codepoints': [0x0228F], 'characters': '\u228F' },
+ '&sqsubseteq;': { 'codepoints': [0x02291], 'characters': '\u2291' },
+ '&sqsup;': { 'codepoints': [0x02290], 'characters': '\u2290' },
+ '&sqsupe;': { 'codepoints': [0x02292], 'characters': '\u2292' },
+ '&sqsupset;': { 'codepoints': [0x02290], 'characters': '\u2290' },
+ '&sqsupseteq;': { 'codepoints': [0x02292], 'characters': '\u2292' },
+ '&squ;': { 'codepoints': [0x025A1], 'characters': '\u25A1' },
+ '&square;': { 'codepoints': [0x025A1], 'characters': '\u25A1' },
+ '&squarf;': { 'codepoints': [0x025AA], 'characters': '\u25AA' },
+ '&squf;': { 'codepoints': [0x025AA], 'characters': '\u25AA' },
+ '&srarr;': { 'codepoints': [0x02192], 'characters': '\u2192' },
+ '&sscr;': { 'codepoints': [0x1D4C8], 'characters': '\uD835\uDCC8' },
+ '&ssetmn;': { 'codepoints': [0x02216], 'characters': '\u2216' },
+ '&ssmile;': { 'codepoints': [0x02323], 'characters': '\u2323' },
+ '&sstarf;': { 'codepoints': [0x022C6], 'characters': '\u22C6' },
+ '&star;': { 'codepoints': [0x02606], 'characters': '\u2606' },
+ '&starf;': { 'codepoints': [0x02605], 'characters': '\u2605' },
+ '&straightepsilon;': { 'codepoints': [0x003F5], 'characters': '\u03F5' },
+ '&straightphi;': { 'codepoints': [0x003D5], 'characters': '\u03D5' },
+ '&strns;': { 'codepoints': [0x000AF], 'characters': '\xAF' },
+ '&sub;': { 'codepoints': [0x02282], 'characters': '\u2282' },
+ '&subE;': { 'codepoints': [0x02AC5], 'characters': '\u2AC5' },
+ '&subdot;': { 'codepoints': [0x02ABD], 'characters': '\u2ABD' },
+ '&sube;': { 'codepoints': [0x02286], 'characters': '\u2286' },
+ '&subedot;': { 'codepoints': [0x02AC3], 'characters': '\u2AC3' },
+ '&submult;': { 'codepoints': [0x02AC1], 'characters': '\u2AC1' },
+ '&subnE;': { 'codepoints': [0x02ACB], 'characters': '\u2ACB' },
+ '&subne;': { 'codepoints': [0x0228A], 'characters': '\u228A' },
+ '&subplus;': { 'codepoints': [0x02ABF], 'characters': '\u2ABF' },
+ '&subrarr;': { 'codepoints': [0x02979], 'characters': '\u2979' },
+ '&subset;': { 'codepoints': [0x02282], 'characters': '\u2282' },
+ '&subseteq;': { 'codepoints': [0x02286], 'characters': '\u2286' },
+ '&subseteqq;': { 'codepoints': [0x02AC5], 'characters': '\u2AC5' },
+ '&subsetneq;': { 'codepoints': [0x0228A], 'characters': '\u228A' },
+ '&subsetneqq;': { 'codepoints': [0x02ACB], 'characters': '\u2ACB' },
+ '&subsim;': { 'codepoints': [0x02AC7], 'characters': '\u2AC7' },
+ '&subsub;': { 'codepoints': [0x02AD5], 'characters': '\u2AD5' },
+ '&subsup;': { 'codepoints': [0x02AD3], 'characters': '\u2AD3' },
+ '&succ;': { 'codepoints': [0x0227B], 'characters': '\u227B' },
+ '&succapprox;': { 'codepoints': [0x02AB8], 'characters': '\u2AB8' },
+ '&succcurlyeq;': { 'codepoints': [0x0227D], 'characters': '\u227D' },
+ '&succeq;': { 'codepoints': [0x02AB0], 'characters': '\u2AB0' },
+ '&succnapprox;': { 'codepoints': [0x02ABA], 'characters': '\u2ABA' },
+ '&succneqq;': { 'codepoints': [0x02AB6], 'characters': '\u2AB6' },
+ '&succnsim;': { 'codepoints': [0x022E9], 'characters': '\u22E9' },
+ '&succsim;': { 'codepoints': [0x0227F], 'characters': '\u227F' },
+ '&sum;': { 'codepoints': [0x02211], 'characters': '\u2211' },
+ '&sung;': { 'codepoints': [0x0266A], 'characters': '\u266A' },
+ '&sup1': { 'codepoints': [0x000B9], 'characters': '\xB9' },
+ '&sup1;': { 'codepoints': [0x000B9], 'characters': '\xB9' },
+ '&sup2': { 'codepoints': [0x000B2], 'characters': '\xB2' },
+ '&sup2;': { 'codepoints': [0x000B2], 'characters': '\xB2' },
+ '&sup3': { 'codepoints': [0x000B3], 'characters': '\xB3' },
+ '&sup3;': { 'codepoints': [0x000B3], 'characters': '\xB3' },
+ '&sup;': { 'codepoints': [0x02283], 'characters': '\u2283' },
+ '&supE;': { 'codepoints': [0x02AC6], 'characters': '\u2AC6' },
+ '&supdot;': { 'codepoints': [0x02ABE], 'characters': '\u2ABE' },
+ '&supdsub;': { 'codepoints': [0x02AD8], 'characters': '\u2AD8' },
+ '&supe;': { 'codepoints': [0x02287], 'characters': '\u2287' },
+ '&supedot;': { 'codepoints': [0x02AC4], 'characters': '\u2AC4' },
+ '&suphsol;': { 'codepoints': [0x027C9], 'characters': '\u27C9' },
+ '&suphsub;': { 'codepoints': [0x02AD7], 'characters': '\u2AD7' },
+ '&suplarr;': { 'codepoints': [0x0297B], 'characters': '\u297B' },
+ '&supmult;': { 'codepoints': [0x02AC2], 'characters': '\u2AC2' },
+ '&supnE;': { 'codepoints': [0x02ACC], 'characters': '\u2ACC' },
+ '&supne;': { 'codepoints': [0x0228B], 'characters': '\u228B' },
+ '&supplus;': { 'codepoints': [0x02AC0], 'characters': '\u2AC0' },
+ '&supset;': { 'codepoints': [0x02283], 'characters': '\u2283' },
+ '&supseteq;': { 'codepoints': [0x02287], 'characters': '\u2287' },
+ '&supseteqq;': { 'codepoints': [0x02AC6], 'characters': '\u2AC6' },
+ '&supsetneq;': { 'codepoints': [0x0228B], 'characters': '\u228B' },
+ '&supsetneqq;': { 'codepoints': [0x02ACC], 'characters': '\u2ACC' },
+ '&supsim;': { 'codepoints': [0x02AC8], 'characters': '\u2AC8' },
+ '&supsub;': { 'codepoints': [0x02AD4], 'characters': '\u2AD4' },
+ '&supsup;': { 'codepoints': [0x02AD6], 'characters': '\u2AD6' },
+ '&swArr;': { 'codepoints': [0x021D9], 'characters': '\u21D9' },
+ '&swarhk;': { 'codepoints': [0x02926], 'characters': '\u2926' },
+ '&swarr;': { 'codepoints': [0x02199], 'characters': '\u2199' },
+ '&swarrow;': { 'codepoints': [0x02199], 'characters': '\u2199' },
+ '&swnwar;': { 'codepoints': [0x0292A], 'characters': '\u292A' },
+ '&szlig': { 'codepoints': [0x000DF], 'characters': '\xDF' },
+ '&szlig;': { 'codepoints': [0x000DF], 'characters': '\xDF' },
+ '&target;': { 'codepoints': [0x02316], 'characters': '\u2316' },
+ '&tau;': { 'codepoints': [0x003C4], 'characters': '\u03C4' },
+ '&tbrk;': { 'codepoints': [0x023B4], 'characters': '\u23B4' },
+ '&tcaron;': { 'codepoints': [0x00165], 'characters': '\u0165' },
+ '&tcedil;': { 'codepoints': [0x00163], 'characters': '\u0163' },
+ '&tcy;': { 'codepoints': [0x00442], 'characters': '\u0442' },
+ '&tdot;': { 'codepoints': [0x020DB], 'characters': '\u20DB' },
+ '&telrec;': { 'codepoints': [0x02315], 'characters': '\u2315' },
+ '&tfr;': { 'codepoints': [0x1D531], 'characters': '\uD835\uDD31' },
+ '&there4;': { 'codepoints': [0x02234], 'characters': '\u2234' },
+ '&therefore;': { 'codepoints': [0x02234], 'characters': '\u2234' },
+ '&theta;': { 'codepoints': [0x003B8], 'characters': '\u03B8' },
+ '&thetasym;': { 'codepoints': [0x003D1], 'characters': '\u03D1' },
+ '&thetav;': { 'codepoints': [0x003D1], 'characters': '\u03D1' },
+ '&thickapprox;': { 'codepoints': [0x02248], 'characters': '\u2248' },
+ '&thicksim;': { 'codepoints': [0x0223C], 'characters': '\u223C' },
+ '&thinsp;': { 'codepoints': [0x02009], 'characters': '\u2009' },
+ '&thkap;': { 'codepoints': [0x02248], 'characters': '\u2248' },
+ '&thksim;': { 'codepoints': [0x0223C], 'characters': '\u223C' },
+ '&thorn': { 'codepoints': [0x000FE], 'characters': '\xFE' },
+ '&thorn;': { 'codepoints': [0x000FE], 'characters': '\xFE' },
+ '&tilde;': { 'codepoints': [0x002DC], 'characters': '\u02DC' },
+ '&times': { 'codepoints': [0x000D7], 'characters': '\xD7' },
+ '&times;': { 'codepoints': [0x000D7], 'characters': '\xD7' },
+ '&timesb;': { 'codepoints': [0x022A0], 'characters': '\u22A0' },
+ '&timesbar;': { 'codepoints': [0x02A31], 'characters': '\u2A31' },
+ '&timesd;': { 'codepoints': [0x02A30], 'characters': '\u2A30' },
+ '&tint;': { 'codepoints': [0x0222D], 'characters': '\u222D' },
+ '&toea;': { 'codepoints': [0x02928], 'characters': '\u2928' },
+ '&top;': { 'codepoints': [0x022A4], 'characters': '\u22A4' },
+ '&topbot;': { 'codepoints': [0x02336], 'characters': '\u2336' },
+ '&topcir;': { 'codepoints': [0x02AF1], 'characters': '\u2AF1' },
+ '&topf;': { 'codepoints': [0x1D565], 'characters': '\uD835\uDD65' },
+ '&topfork;': { 'codepoints': [0x02ADA], 'characters': '\u2ADA' },
+ '&tosa;': { 'codepoints': [0x02929], 'characters': '\u2929' },
+ '&tprime;': { 'codepoints': [0x02034], 'characters': '\u2034' },
+ '&trade;': { 'codepoints': [0x02122], 'characters': '\u2122' },
+ '&triangle;': { 'codepoints': [0x025B5], 'characters': '\u25B5' },
+ '&triangledown;': { 'codepoints': [0x025BF], 'characters': '\u25BF' },
+ '&triangleleft;': { 'codepoints': [0x025C3], 'characters': '\u25C3' },
+ '&trianglelefteq;': { 'codepoints': [0x022B4], 'characters': '\u22B4' },
+ '&triangleq;': { 'codepoints': [0x0225C], 'characters': '\u225C' },
+ '&triangleright;': { 'codepoints': [0x025B9], 'characters': '\u25B9' },
+ '&trianglerighteq;': { 'codepoints': [0x022B5], 'characters': '\u22B5' },
+ '&tridot;': { 'codepoints': [0x025EC], 'characters': '\u25EC' },
+ '&trie;': { 'codepoints': [0x0225C], 'characters': '\u225C' },
+ '&triminus;': { 'codepoints': [0x02A3A], 'characters': '\u2A3A' },
+ '&triplus;': { 'codepoints': [0x02A39], 'characters': '\u2A39' },
+ '&trisb;': { 'codepoints': [0x029CD], 'characters': '\u29CD' },
+ '&tritime;': { 'codepoints': [0x02A3B], 'characters': '\u2A3B' },
+ '&trpezium;': { 'codepoints': [0x023E2], 'characters': '\u23E2' },
+ '&tscr;': { 'codepoints': [0x1D4C9], 'characters': '\uD835\uDCC9' },
+ '&tscy;': { 'codepoints': [0x00446], 'characters': '\u0446' },
+ '&tshcy;': { 'codepoints': [0x0045B], 'characters': '\u045B' },
+ '&tstrok;': { 'codepoints': [0x00167], 'characters': '\u0167' },
+ '&twixt;': { 'codepoints': [0x0226C], 'characters': '\u226C' },
+ '&twoheadleftarrow;': { 'codepoints': [0x0219E], 'characters': '\u219E' },
+ '&twoheadrightarrow;': { 'codepoints': [0x021A0], 'characters': '\u21A0' },
+ '&uArr;': { 'codepoints': [0x021D1], 'characters': '\u21D1' },
+ '&uHar;': { 'codepoints': [0x02963], 'characters': '\u2963' },
+ '&uacute': { 'codepoints': [0x000FA], 'characters': '\xFA' },
+ '&uacute;': { 'codepoints': [0x000FA], 'characters': '\xFA' },
+ '&uarr;': { 'codepoints': [0x02191], 'characters': '\u2191' },
+ '&ubrcy;': { 'codepoints': [0x0045E], 'characters': '\u045E' },
+ '&ubreve;': { 'codepoints': [0x0016D], 'characters': '\u016D' },
+ '&ucirc': { 'codepoints': [0x000FB], 'characters': '\xFB' },
+ '&ucirc;': { 'codepoints': [0x000FB], 'characters': '\xFB' },
+ '&ucy;': { 'codepoints': [0x00443], 'characters': '\u0443' },
+ '&udarr;': { 'codepoints': [0x021C5], 'characters': '\u21C5' },
+ '&udblac;': { 'codepoints': [0x00171], 'characters': '\u0171' },
+ '&udhar;': { 'codepoints': [0x0296E], 'characters': '\u296E' },
+ '&ufisht;': { 'codepoints': [0x0297E], 'characters': '\u297E' },
+ '&ufr;': { 'codepoints': [0x1D532], 'characters': '\uD835\uDD32' },
+ '&ugrave': { 'codepoints': [0x000F9], 'characters': '\xF9' },
+ '&ugrave;': { 'codepoints': [0x000F9], 'characters': '\xF9' },
+ '&uharl;': { 'codepoints': [0x021BF], 'characters': '\u21BF' },
+ '&uharr;': { 'codepoints': [0x021BE], 'characters': '\u21BE' },
+ '&uhblk;': { 'codepoints': [0x02580], 'characters': '\u2580' },
+ '&ulcorn;': { 'codepoints': [0x0231C], 'characters': '\u231C' },
+ '&ulcorner;': { 'codepoints': [0x0231C], 'characters': '\u231C' },
+ '&ulcrop;': { 'codepoints': [0x0230F], 'characters': '\u230F' },
+ '&ultri;': { 'codepoints': [0x025F8], 'characters': '\u25F8' },
+ '&umacr;': { 'codepoints': [0x0016B], 'characters': '\u016B' },
+ '&uml': { 'codepoints': [0x000A8], 'characters': '\xA8' },
+ '&uml;': { 'codepoints': [0x000A8], 'characters': '\xA8' },
+ '&uogon;': { 'codepoints': [0x00173], 'characters': '\u0173' },
+ '&uopf;': { 'codepoints': [0x1D566], 'characters': '\uD835\uDD66' },
+ '&uparrow;': { 'codepoints': [0x02191], 'characters': '\u2191' },
+ '&updownarrow;': { 'codepoints': [0x02195], 'characters': '\u2195' },
+ '&upharpoonleft;': { 'codepoints': [0x021BF], 'characters': '\u21BF' },
+ '&upharpoonright;': { 'codepoints': [0x021BE], 'characters': '\u21BE' },
+ '&uplus;': { 'codepoints': [0x0228E], 'characters': '\u228E' },
+ '&upsi;': { 'codepoints': [0x003C5], 'characters': '\u03C5' },
+ '&upsih;': { 'codepoints': [0x003D2], 'characters': '\u03D2' },
+ '&upsilon;': { 'codepoints': [0x003C5], 'characters': '\u03C5' },
+ '&upuparrows;': { 'codepoints': [0x021C8], 'characters': '\u21C8' },
+ '&urcorn;': { 'codepoints': [0x0231D], 'characters': '\u231D' },
+ '&urcorner;': { 'codepoints': [0x0231D], 'characters': '\u231D' },
+ '&urcrop;': { 'codepoints': [0x0230E], 'characters': '\u230E' },
+ '&uring;': { 'codepoints': [0x0016F], 'characters': '\u016F' },
+ '&urtri;': { 'codepoints': [0x025F9], 'characters': '\u25F9' },
+ '&uscr;': { 'codepoints': [0x1D4CA], 'characters': '\uD835\uDCCA' },
+ '&utdot;': { 'codepoints': [0x022F0], 'characters': '\u22F0' },
+ '&utilde;': { 'codepoints': [0x00169], 'characters': '\u0169' },
+ '&utri;': { 'codepoints': [0x025B5], 'characters': '\u25B5' },
+ '&utrif;': { 'codepoints': [0x025B4], 'characters': '\u25B4' },
+ '&uuarr;': { 'codepoints': [0x021C8], 'characters': '\u21C8' },
+ '&uuml': { 'codepoints': [0x000FC], 'characters': '\xFC' },
+ '&uuml;': { 'codepoints': [0x000FC], 'characters': '\xFC' },
+ '&uwangle;': { 'codepoints': [0x029A7], 'characters': '\u29A7' },
+ '&vArr;': { 'codepoints': [0x021D5], 'characters': '\u21D5' },
+ '&vBar;': { 'codepoints': [0x02AE8], 'characters': '\u2AE8' },
+ '&vBarv;': { 'codepoints': [0x02AE9], 'characters': '\u2AE9' },
+ '&vDash;': { 'codepoints': [0x022A8], 'characters': '\u22A8' },
+ '&vangrt;': { 'codepoints': [0x0299C], 'characters': '\u299C' },
+ '&varepsilon;': { 'codepoints': [0x003F5], 'characters': '\u03F5' },
+ '&varkappa;': { 'codepoints': [0x003F0], 'characters': '\u03F0' },
+ '&varnothing;': { 'codepoints': [0x02205], 'characters': '\u2205' },
+ '&varphi;': { 'codepoints': [0x003D5], 'characters': '\u03D5' },
+ '&varpi;': { 'codepoints': [0x003D6], 'characters': '\u03D6' },
+ '&varpropto;': { 'codepoints': [0x0221D], 'characters': '\u221D' },
+ '&varr;': { 'codepoints': [0x02195], 'characters': '\u2195' },
+ '&varrho;': { 'codepoints': [0x003F1], 'characters': '\u03F1' },
+ '&varsigma;': { 'codepoints': [0x003C2], 'characters': '\u03C2' },
+ '&varsubsetneq;': { 'codepoints': [0x0228A, 0x0FE00], 'characters': '\u228A\uFE00' },
+ '&varsubsetneqq;': { 'codepoints': [0x02ACB, 0x0FE00], 'characters': '\u2ACB\uFE00' },
+ '&varsupsetneq;': { 'codepoints': [0x0228B, 0x0FE00], 'characters': '\u228B\uFE00' },
+ '&varsupsetneqq;': { 'codepoints': [0x02ACC, 0x0FE00], 'characters': '\u2ACC\uFE00' },
+ '&vartheta;': { 'codepoints': [0x003D1], 'characters': '\u03D1' },
+ '&vartriangleleft;': { 'codepoints': [0x022B2], 'characters': '\u22B2' },
+ '&vartriangleright;': { 'codepoints': [0x022B3], 'characters': '\u22B3' },
+ '&vcy;': { 'codepoints': [0x00432], 'characters': '\u0432' },
+ '&vdash;': { 'codepoints': [0x022A2], 'characters': '\u22A2' },
+ '&vee;': { 'codepoints': [0x02228], 'characters': '\u2228' },
+ '&veebar;': { 'codepoints': [0x022BB], 'characters': '\u22BB' },
+ '&veeeq;': { 'codepoints': [0x0225A], 'characters': '\u225A' },
+ '&vellip;': { 'codepoints': [0x022EE], 'characters': '\u22EE' },
+ '&verbar;': { 'codepoints': [0x0007C], 'characters': '\x7C' },
+ '&vert;': { 'codepoints': [0x0007C], 'characters': '\x7C' },
+ '&vfr;': { 'codepoints': [0x1D533], 'characters': '\uD835\uDD33' },
+ '&vltri;': { 'codepoints': [0x022B2], 'characters': '\u22B2' },
+ '&vnsub;': { 'codepoints': [0x02282, 0x020D2], 'characters': '\u2282\u20D2' },
+ '&vnsup;': { 'codepoints': [0x02283, 0x020D2], 'characters': '\u2283\u20D2' },
+ '&vopf;': { 'codepoints': [0x1D567], 'characters': '\uD835\uDD67' },
+ '&vprop;': { 'codepoints': [0x0221D], 'characters': '\u221D' },
+ '&vrtri;': { 'codepoints': [0x022B3], 'characters': '\u22B3' },
+ '&vscr;': { 'codepoints': [0x1D4CB], 'characters': '\uD835\uDCCB' },
+ '&vsubnE;': { 'codepoints': [0x02ACB, 0x0FE00], 'characters': '\u2ACB\uFE00' },
+ '&vsubne;': { 'codepoints': [0x0228A, 0x0FE00], 'characters': '\u228A\uFE00' },
+ '&vsupnE;': { 'codepoints': [0x02ACC, 0x0FE00], 'characters': '\u2ACC\uFE00' },
+ '&vsupne;': { 'codepoints': [0x0228B, 0x0FE00], 'characters': '\u228B\uFE00' },
+ '&vzigzag;': { 'codepoints': [0x0299A], 'characters': '\u299A' },
+ '&wcirc;': { 'codepoints': [0x00175], 'characters': '\u0175' },
+ '&wedbar;': { 'codepoints': [0x02A5F], 'characters': '\u2A5F' },
+ '&wedge;': { 'codepoints': [0x02227], 'characters': '\u2227' },
+ '&wedgeq;': { 'codepoints': [0x02259], 'characters': '\u2259' },
+ '&weierp;': { 'codepoints': [0x02118], 'characters': '\u2118' },
+ '&wfr;': { 'codepoints': [0x1D534], 'characters': '\uD835\uDD34' },
+ '&wopf;': { 'codepoints': [0x1D568], 'characters': '\uD835\uDD68' },
+ '&wp;': { 'codepoints': [0x02118], 'characters': '\u2118' },
+ '&wr;': { 'codepoints': [0x02240], 'characters': '\u2240' },
+ '&wreath;': { 'codepoints': [0x02240], 'characters': '\u2240' },
+ '&wscr;': { 'codepoints': [0x1D4CC], 'characters': '\uD835\uDCCC' },
+ '&xcap;': { 'codepoints': [0x022C2], 'characters': '\u22C2' },
+ '&xcirc;': { 'codepoints': [0x025EF], 'characters': '\u25EF' },
+ '&xcup;': { 'codepoints': [0x022C3], 'characters': '\u22C3' },
+ '&xdtri;': { 'codepoints': [0x025BD], 'characters': '\u25BD' },
+ '&xfr;': { 'codepoints': [0x1D535], 'characters': '\uD835\uDD35' },
+ '&xhArr;': { 'codepoints': [0x027FA], 'characters': '\u27FA' },
+ '&xharr;': { 'codepoints': [0x027F7], 'characters': '\u27F7' },
+ '&xi;': { 'codepoints': [0x003BE], 'characters': '\u03BE' },
+ '&xlArr;': { 'codepoints': [0x027F8], 'characters': '\u27F8' },
+ '&xlarr;': { 'codepoints': [0x027F5], 'characters': '\u27F5' },
+ '&xmap;': { 'codepoints': [0x027FC], 'characters': '\u27FC' },
+ '&xnis;': { 'codepoints': [0x022FB], 'characters': '\u22FB' },
+ '&xodot;': { 'codepoints': [0x02A00], 'characters': '\u2A00' },
+ '&xopf;': { 'codepoints': [0x1D569], 'characters': '\uD835\uDD69' },
+ '&xoplus;': { 'codepoints': [0x02A01], 'characters': '\u2A01' },
+ '&xotime;': { 'codepoints': [0x02A02], 'characters': '\u2A02' },
+ '&xrArr;': { 'codepoints': [0x027F9], 'characters': '\u27F9' },
+ '&xrarr;': { 'codepoints': [0x027F6], 'characters': '\u27F6' },
+ '&xscr;': { 'codepoints': [0x1D4CD], 'characters': '\uD835\uDCCD' },
+ '&xsqcup;': { 'codepoints': [0x02A06], 'characters': '\u2A06' },
+ '&xuplus;': { 'codepoints': [0x02A04], 'characters': '\u2A04' },
+ '&xutri;': { 'codepoints': [0x025B3], 'characters': '\u25B3' },
+ '&xvee;': { 'codepoints': [0x022C1], 'characters': '\u22C1' },
+ '&xwedge;': { 'codepoints': [0x022C0], 'characters': '\u22C0' },
+ '&yacute': { 'codepoints': [0x000FD], 'characters': '\xFD' },
+ '&yacute;': { 'codepoints': [0x000FD], 'characters': '\xFD' },
+ '&yacy;': { 'codepoints': [0x0044F], 'characters': '\u044F' },
+ '&ycirc;': { 'codepoints': [0x00177], 'characters': '\u0177' },
+ '&ycy;': { 'codepoints': [0x0044B], 'characters': '\u044B' },
+ '&yen': { 'codepoints': [0x000A5], 'characters': '\xA5' },
+ '&yen;': { 'codepoints': [0x000A5], 'characters': '\xA5' },
+ '&yfr;': { 'codepoints': [0x1D536], 'characters': '\uD835\uDD36' },
+ '&yicy;': { 'codepoints': [0x00457], 'characters': '\u0457' },
+ '&yopf;': { 'codepoints': [0x1D56A], 'characters': '\uD835\uDD6A' },
+ '&yscr;': { 'codepoints': [0x1D4CE], 'characters': '\uD835\uDCCE' },
+ '&yucy;': { 'codepoints': [0x0044E], 'characters': '\u044E' },
+ '&yuml': { 'codepoints': [0x000FF], 'characters': '\xFF' },
+ '&yuml;': { 'codepoints': [0x000FF], 'characters': '\xFF' },
+ '&zacute;': { 'codepoints': [0x0017A], 'characters': '\u017A' },
+ '&zcaron;': { 'codepoints': [0x0017E], 'characters': '\u017E' },
+ '&zcy;': { 'codepoints': [0x00437], 'characters': '\u0437' },
+ '&zdot;': { 'codepoints': [0x0017C], 'characters': '\u017C' },
+ '&zeetrf;': { 'codepoints': [0x02128], 'characters': '\u2128' },
+ '&zeta;': { 'codepoints': [0x003B6], 'characters': '\u03B6' },
+ '&zfr;': { 'codepoints': [0x1D537], 'characters': '\uD835\uDD37' },
+ '&zhcy;': { 'codepoints': [0x00436], 'characters': '\u0436' },
+ '&zigrarr;': { 'codepoints': [0x021DD], 'characters': '\u21DD' },
+ '&zopf;': { 'codepoints': [0x1D56B], 'characters': '\uD835\uDD6B' },
+ '&zscr;': { 'codepoints': [0x1D4CF], 'characters': '\uD835\uDCCF' },
+ '&zwj;': { 'codepoints': [0x0200D], 'characters': '\u200D' },
+ '&zwnj;': { 'codepoints': [0x0200C], 'characters': '\u200C' }
+};
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/named-character-references.html b/tests/wpt/web-platform-tests/html/syntax/parsing/named-character-references.html
new file mode 100644
index 00000000000..b784d5e92d1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/named-character-references.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Tests for known named character references</title>
+<meta name=viewport content="width=device-width">
+<!-- Alternative output: http://mathias.html5.org/tests/html/named-character-references/ -->
+<div id=log></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=named-character-references-data.js></script>
+<script>
+ (function() {
+
+ function pad(string, totalCharacters) {
+ return totalCharacters < string.length ? string : (Array(totalCharacters + 1).join('0') + string).slice(-totalCharacters);
+ }
+
+ var dummy = document.createElement('p');
+
+ Object.keys(data).forEach(function(entity) {
+ var object = data[entity];
+ dummy.innerHTML = entity;
+ test(
+ function() {
+ assert_equals(
+ dummy.textContent,
+ object.characters
+ );
+ },
+ entity + ' should match ' + object.codepoints.map(function(codePoint) {
+ return 'U+' + pad(codePoint.toString(16).toUpperCase(), 5);
+ }).join(' ')
+ );
+ });
+
+ }());
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/template.js b/tests/wpt/web-platform-tests/html/syntax/parsing/template.js
new file mode 100644
index 00000000000..b249fb64c71
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/template.js
@@ -0,0 +1,214 @@
+ /*
+ * Template code
+ *
+ * A template is just a javascript structure. An element is represented as:
+ *
+ * [tag_name, {attr_name:attr_value}, child1, child2]
+ *
+ * the children can either be strings (which act like text nodes), other templates or
+ * functions (see below)
+ *
+ * A text node is represented as
+ *
+ * ["{text}", value]
+ *
+ * String values have a simple substitution syntax; ${foo} represents a variable foo.
+ *
+ * It is possible to embed logic in templates by using a function in a place where a
+ * node would usually go. The function must either return part of a template or null.
+ *
+ * In cases where a set of nodes are required as output rather than a single node
+ * with children it is possible to just use a list
+ * [node1, node2, node3]
+ *
+ * Usage:
+ *
+ * render(template, substitutions) - take a template and an object mapping
+ * variable names to parameters and return either a DOM node or a list of DOM nodes
+ *
+ * substitute(template, substitutions) - take a template and variable mapping object,
+ * make the variable substitutions and return the substituted template
+ *
+ */
+
+ function is_single_node(template)
+ {
+ return typeof template[0] === "string";
+ }
+
+ function substitute(template, substitutions)
+ {
+ if (typeof template === "function") {
+ var replacement = template(substitutions);
+ if (replacement)
+ {
+ var rv = substitute(replacement, substitutions);
+ return rv;
+ }
+ else
+ {
+ return null;
+ }
+ }
+ else if (is_single_node(template))
+ {
+ return substitute_single(template, substitutions);
+ }
+ else
+ {
+ return filter(map(template, function(x) {
+ return substitute(x, substitutions);
+ }), function(x) {return x !== null;});
+ }
+ }
+ expose(substitute, "template.substitute");
+
+ function substitute_single(template, substitutions)
+ {
+ var substitution_re = /\${([^ }]*)}/g;
+
+ function do_substitution(input) {
+ var components = input.split(substitution_re);
+ var rv = [];
+ for (var i=0; i<components.length; i+=2)
+ {
+ rv.push(components[i]);
+ if (components[i+1])
+ {
+ rv.push(substitutions[components[i+1]]);
+ }
+ }
+ return rv;
+ }
+
+ var rv = [];
+ rv.push(do_substitution(String(template[0])).join(""));
+
+ if (template[0] === "{text}") {
+ substitute_children(template.slice(1), rv);
+ } else {
+ substitute_attrs(template[1], rv);
+ substitute_children(template.slice(2), rv);
+ }
+
+ function substitute_attrs(attrs, rv)
+ {
+ rv[1] = {};
+ for (name in template[1])
+ {
+ if (attrs.hasOwnProperty(name))
+ {
+ var new_name = do_substitution(name).join("");
+ var new_value = do_substitution(attrs[name]).join("");
+ rv[1][new_name] = new_value;
+ };
+ }
+ }
+
+ function substitute_children(children, rv)
+ {
+ for (var i=0; i<children.length; i++)
+ {
+ if (children[i] instanceof Object) {
+ var replacement = substitute(children[i], substitutions);
+ if (replacement !== null)
+ {
+ if (is_single_node(replacement))
+ {
+ rv.push(replacement);
+ }
+ else
+ {
+ extend(rv, replacement);
+ }
+ }
+ }
+ else
+ {
+ extend(rv, do_substitution(String(children[i])));
+ }
+ }
+ return rv;
+ }
+
+ return rv;
+ }
+
+ function make_dom_single(template)
+ {
+ if (template[0] === "{text}")
+ {
+ var element = document.createTextNode("");
+ for (var i=1; i<template.length; i++)
+ {
+ element.data += template[i];
+ }
+ }
+ else
+ {
+ var element = document.createElement(template[0]);
+ for (name in template[1]) {
+ if (template[1].hasOwnProperty(name))
+ {
+ element.setAttribute(name, template[1][name]);
+ }
+ }
+ for (var i=2; i<template.length; i++)
+ {
+ if (template[i] instanceof Object)
+ {
+ var sub_element = make_dom(template[i]);
+ element.appendChild(sub_element);
+ }
+ else
+ {
+ var text_node = document.createTextNode(template[i]);
+ element.appendChild(text_node);
+ }
+ }
+ }
+
+ return element;
+ }
+
+
+
+ function make_dom(template, substitutions)
+ {
+ if (is_single_node(template))
+ {
+ return make_dom_single(template);
+ }
+ else
+ {
+ return map(template, function(x) {
+ return make_dom_single(x);
+ });
+ }
+ }
+
+ function render(template, substitutions)
+ {
+ return make_dom(substitute(template, substitutions));
+ }
+ expose(render, "template.render");
+
+function expose(object, name)
+{
+ var components = name.split(".");
+ var target = window;
+ for (var i=0; i<components.length - 1; i++)
+ {
+ if (!(components[i] in target))
+ {
+ target[components[i]] = {};
+ }
+ target = target[components[i]];
+ }
+ target[components[components.length - 1]] = object;
+}
+
+function extend(array, items)
+{
+ Array.prototype.push.apply(array, items);
+} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/template/additions-to-foster-parenting/template-is-a-foster-parent-element.html b/tests/wpt/web-platform-tests/html/syntax/parsing/template/additions-to-foster-parenting/template-is-a-foster-parent-element.html
new file mode 100644
index 00000000000..9deed5fd960
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/template/additions-to-foster-parenting/template-is-a-foster-parent-element.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>HTML Templates: Template is a foster parent element</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="assert" content="The last template element with either no table element is below it, or a table element immediately below it, in the stack of open elements is the foster parent element (NOT the template's parent!)">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#foster-parent-addition">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src='../../testcommon.js'></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script type="text/javascript">
+
+
+test(function () {
+ var doc = newHTMLDocument();
+
+ doc.body.innerHTML = '' +
+ '<div id="tmplParent">' +
+ '<template id="tmpl1">' +
+ '<table id="tbl">' +
+ '<tr><td>Cell 1</td></tr>' +
+ // Misplaced <div>. It should be foster parented
+ '<div id="orphanDiv">Orphan div content</div>' +
+ '<tr><td>Cell 2</td></tr>' +
+ '</table>' +
+ '</template>' +
+ '</div>';
+
+ var template = doc.querySelector('#tmpl1');
+ var div = template.content.querySelector('#orphanDiv');
+
+ assert_equals(div.parentNode, template.content, 'Wrong foster parent element');
+
+}, 'Template is a foster parent element. Test <table> immediately below <template>');
+
+
+
+test(function () {
+ var doc = newHTMLDocument();
+
+ doc.body.innerHTML = '' +
+ '<div id="tmplParent">' +
+ '<template id="tmpl1">' +
+ '<tr><td>Cell 1</td></tr>' +
+ // Misplaced <div>. It should be foster parented
+ '<div id="orphanDiv">Orphan div content</div>' +
+ '<tr><td>Cell 2</td></tr>' +
+ '</template>' +
+ '</div>';
+
+ var template = doc.querySelector('#tmpl1');
+ var div = template.content.querySelector('#orphanDiv');
+
+ assert_equals(div.parentNode, template.content, 'Wrong foster parent element');
+
+}, 'Template is a foster parent element. Test <template> element without <table>');
+
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/template/additions-to-foster-parenting/template-is-not-a-foster-parent-element.html b/tests/wpt/web-platform-tests/html/syntax/parsing/template/additions-to-foster-parenting/template-is-not-a-foster-parent-element.html
new file mode 100644
index 00000000000..2780edc8f89
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/template/additions-to-foster-parenting/template-is-not-a-foster-parent-element.html
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>HTML Templates: Template is not a foster parent element</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="assert" content="When template element shouldn't be a foster parent then regular rules of foster parenting should be applied">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#foster-parent-addition">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src='../../testcommon.js'></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script type="text/javascript">
+
+
+test(function () {
+ var doc = newHTMLDocument();
+
+ doc.body.innerHTML = '' +
+ '<div id="tmplParent">' +
+ '<template id="tmpl1">' +
+ '<div id="fosterParent">' +
+ '<table id="tbl">' +
+ '<tr><td>Cell 1</td></tr>' +
+ // Misplaced <div>. It should be foster parented
+ '<div id="orphanDiv">Orphan div content</div>' +
+ '<tr><td>Cell 2</td></tr>' +
+ '</table>' +
+ '</div>' +
+ '</template>' +
+ '</div>';
+
+ var template = doc.querySelector('#tmpl1');
+ var fosterParent = template.content.querySelector('#fosterParent');
+ var div = template.content.querySelector('#orphanDiv');
+
+ assert_equals(div.parentNode, fosterParent, 'Wrong foster parent element');
+
+}, 'Template is not a foster parent element. '
+ + 'Test the case when <template> is higher in stack of open elements');
+
+
+
+test(function () {
+ var doc = newHTMLDocument();
+
+ doc.body.innerHTML = '' +
+ '<div id="fosterParent">' +
+ '<table id="tbl">' +
+ '<tr><td><template id="tmpl1">Template content</template></td></tr>' +
+ // Misplaced <div>. It should be foster parented
+ '<div id="orphanDiv">Orphan div content</div>' +
+ '<tr><td>Cell 2</td></tr>' +
+ '</table>' +
+ '</div>' +
+ '</div>';
+
+ var t = doc.querySelector('#tmpl1');
+ var fosterParent = doc.querySelector('#fosterParent');
+ var div = doc.querySelector('#orphanDiv');
+
+ assert_equals(div.parentNode, fosterParent, 'Wrong foster parent element');
+
+}, 'Template is not a foster parent element. '
+ + 'Test the case when <template> is lower in stack of open elements');
+
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/generating-of-implied-end-tags.html b/tests/wpt/web-platform-tests/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/generating-of-implied-end-tags.html
new file mode 100644
index 00000000000..6526b01bbec
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/generating-of-implied-end-tags.html
@@ -0,0 +1,137 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>HTML Templates: 'In body' insertion mode: when template end tag is met, implied end tags should be generated</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="author" title="Aleksei Yu. Semenov" href="a.semenov@unipro.ru">
+<meta name="assert" content="'In body' insertion mode: when template end tag is met, implied end tags should be generated">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#in-body-addition">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src='../../testcommon.js'></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script type="text/javascript">
+
+
+test(function () {
+ var doc = newHTMLDocument();
+
+ //No end </td></tr></table> tags. Should be added implicitly
+ doc.body.innerHTML = '<template id="tpl">'
+ + '<table id="tbl"><tr id="tr"><td id="td"></template>';
+
+ var template = doc.querySelector('#tpl');
+
+ assert_not_equals(template, null, 'Template element must be parsed');
+
+ assert_equals(doc.querySelector('#tbl'), null, 'Table element should not be available');
+ assert_equals(doc.querySelector('#tr'), null, 'TR element should not be available');
+ assert_equals(doc.querySelector('#td'), null, 'TD element should not be available');
+
+ assert_not_equals(template.content.querySelector('#tbl'), null,
+ 'Template should contain table element');
+ assert_not_equals(template.content.querySelector('#tr'), null,
+ 'Template should contain TR element');
+ assert_not_equals(template.content.querySelector('#td'), null,
+ 'Template should contain TD element');
+
+}, 'Generating of implied end tags. Test table elements');
+
+
+
+test(function () {
+ var doc = newHTMLDocument();
+
+ //No end </div> tag. Should be added implicitly
+ doc.body.innerHTML = '<template id="tpl"><div id="dv">Div content</template>';
+
+ var template = doc.querySelector('#tpl');
+
+ assert_not_equals(template, null, 'Template element must be parsed');
+
+ assert_equals(doc.querySelector('#dv'), null, 'DIV element should not be available');
+
+ assert_not_equals(template.content.querySelector('#dv'), null,
+ 'Template should contain DIV element');
+
+}, 'Generating of implied end tags. Test div element');
+
+
+test(function () {
+ var doc = newHTMLDocument();
+
+ //No end </div> tag. Should be added implicitly after text content
+ doc.body.innerHTML = '<template id="tpl">Template text<div id="dv">Div content</template>';
+
+ var template = doc.querySelector('#tpl');
+
+ assert_not_equals(template, null, 'Template element must be parsed');
+
+ assert_equals(doc.querySelector('#dv'), null, 'DIV element should not be available');
+
+ var div = template.content.querySelector('#dv');
+
+ assert_not_equals( div, null, 'Template should contain DIV element');
+ assert_equals(div.innerText, 'Div content', 'Wrong template content inner text');
+
+}, 'Generating of implied end tags. Test some text and DIV element');
+
+
+test(function () {
+ var doc = newHTMLDocument();
+
+ // Wrong end tag. Correct end tag must be added implicitly, wrong one ignored
+ doc.body.innerHTML = '<template id="tpl"><div id="dv">Div content</span></template>';
+
+ var template = doc.querySelector('#tpl');
+
+ assert_not_equals(template, null, 'Template element must be parsed');
+
+ assert_equals(template.content.childNodes.length, 1,
+ 'Wrong number of template\'s children');
+
+ assert_equals(doc.querySelector('#dv'), null, 'DIV element should not be available');
+
+ assert_not_equals(template.content.querySelector('#dv'), null,
+ 'Template should contain DIV element');
+ assert_equals(template.content.querySelector('#dv').innerText,
+ 'Div content', 'Wrong template content inner text');
+
+}, 'Generating of implied end tags. Test wrong end tag');
+
+
+testInIFrame('../../resources/template-contents-table-no-end-tag.html', function(context) {
+ var doc = context.iframes[0].contentDocument;
+
+ var template = doc.body.querySelector('template');
+
+ assert_not_equals(template, null, 'Template element must be parsed');
+
+ assert_not_equals(template.content.querySelector('table'), null,
+ 'Template should contain table element');
+ assert_not_equals(template.content.querySelector('tr'), null,
+ 'Template should contain TR element');
+ assert_not_equals(template.content.querySelector('td'), null,
+ 'Template should contain TD element');
+
+}, 'Generating of implied end tags. Test table elements. Loading of HTML document from a file');
+
+
+testInIFrame('../../resources/template-contents-div-no-end-tag.html', function(context) {
+ var doc = context.iframes[0].contentDocument;
+
+ var template = doc.body.querySelector('template');
+
+ assert_not_equals(template, null, 'Template element must be parsed');
+
+ var div = template.content.querySelector('div');
+ assert_not_equals(div, null, 'Template should contain div element');
+ assert_equals(div.innerText, 'Hello, template\n ', 'Invalid div contents');
+
+}, 'Generating of implied end tags. Test div element. Loading of HTML document from a file');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/ignore-body-token.html b/tests/wpt/web-platform-tests/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/ignore-body-token.html
new file mode 100644
index 00000000000..7985e148d4b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/ignore-body-token.html
@@ -0,0 +1,133 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>HTML Templates: In body insertion mode: parser should ignore BODY token</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<meta name="assert" content="http://www.w3.org/TR/2013/WD-html-templates-20130214/#in-body-addition">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#in-body-addition">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src='../../testcommon.js'></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script type="text/javascript">
+
+/*
+ * According to http://www.w3.org/TR/2013/WD-html-templates-20130214/#template-contents-insertion-mode
+ * when parser is in "template content" mode and meets <body> tag it should be switched to
+ * "in body" insertion mode.
+ * According to http://www.w3.org/TR/2013/WD-html-templates-20130214/#in-body-addition
+ * this token (BODY) should be ignored
+ */
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var template = doc.createElement('template');
+
+ template.innerHTML = '<body></body>';
+
+ doc.body.appendChild(template);
+
+ assert_equals(template.content.childNodes.length, 0,
+ 'Template cannot contain BODY element');
+
+}, 'Ignore BODY token. Test empty BODY element assigned to template innerHTML');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var template = doc.createElement('template');
+
+ template.innerHTML = '<body><div>Some content</div></body>';
+
+ doc.body.appendChild(template);
+
+ assert_equals(template.content.childNodes.length, 1,
+ 'Wrong number of template content children');
+ assert_equals(template.content.firstChild.nodeName, 'DIV',
+ 'Template should contain children of ignored BODY element');
+
+}, 'Ignore BODY token. Test not empty BODY element assigned to template innerHTML');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var template = doc.createElement('template');
+
+ template.innerHTML = '<body><div <div id="div1">Some content</div></body><div id="div2">Some valid content</div>';
+
+ doc.body.appendChild(template);
+
+ assert_equals(template.content.childNodes.length, 2,
+ 'Wrong number of template content children');
+ assert_not_equals(template.content.querySelector('#div1'), null,
+ 'Template should contain children of the ignored BODY element');
+ assert_not_equals(template.content.querySelector('#div2'), null,
+ 'Template should contain valid element');
+
+}, 'Ignore BODY token. '
+ + 'Test BODY element and some valid element after BODY tag assigned to template innerHTML');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var template = doc.createElement('template');
+
+ template.innerHTML = '<div id="div1">Some valid content</div><body><div id="div2">Some content</div></body>';
+
+ doc.body.appendChild(template);
+
+ assert_equals(template.content.childNodes.length, 2,
+ 'Template cannot contain BODY element');
+ assert_not_equals(template.content.querySelector('#div1'), null,
+ 'Template should contain valid element');
+ assert_not_equals(template.content.querySelector('#div2'), null,
+ 'Template should contain children of the ignored BODY element');
+
+}, 'Ignore BODY token. '
+ + 'Test BODY element and some valid element before BODY tag assigned to template innerHTML');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var template = doc.createElement('template');
+
+ template.innerHTML = '<template id="t2"><body><span>Body!<span></body></template>';
+
+ doc.body.appendChild(template);
+
+ assert_equals(template.content.childNodes.length, 1,
+ 'Template should contain nested template');
+ assert_not_equals(template.content.querySelector('#t2'), null,
+ 'Template should contain nested element');
+
+ var nestedTemplate = template.content.querySelector('#t2');
+
+ assert_equals(nestedTemplate.content.childNodes.length, 1,
+ 'Template cannot contain BODY element');
+ assert_equals(nestedTemplate.content.firstChild.nodeName, 'SPAN',
+ 'Template cannot contain BODY element');
+
+}, 'Ignore BODY token. '
+ + 'Test template with not empty BODY element inside assigned to another '
+ + 'template\'s innerHTML');
+
+
+testInIFrame('../../resources/template-contents-body.html', function(context) {
+ var doc = context.iframes[0].contentDocument;
+
+ var template = doc.body.querySelector('template');
+
+ assert_equals(template.content.childNodes.length, 0,
+ 'Template cannot contain BODY element');
+
+}, 'Ignore BODY token. '
+ + 'Test loading a HTML file with BODY tag inside template');
+
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/ignore-frameset-token.html b/tests/wpt/web-platform-tests/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/ignore-frameset-token.html
new file mode 100644
index 00000000000..297b4d7e799
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/ignore-frameset-token.html
@@ -0,0 +1,126 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>HTML Templates: In body insertion mode: parser should ignore FRAMESET token</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<meta name="assert" content="If parser is in 'in body' insertion mode and meets HTML token it should be ignored">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#in-body-addition">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src='../../testcommon.js'></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script type="text/javascript">
+
+/*
+ * According to http://www.w3.org/TR/2013/WD-html-templates-20130214/#template-contents-insertion-mode
+ * when parser is in "template content" mode and meets <frameset> tag it should be switched to
+ * "in body" insertion mode.
+ * According to https://html.spec.whatwg.org/multipage/#parsing-main-inbody
+ * this token (FRAMESET) should be ignored
+ */
+
+test(function() {
+ var doc = newHTMLDocument();
+ var template = doc.createElement('template');
+
+ template.innerHTML = '<frameset cols="25%,*,25%">'
+ + '<frame src="frame_a.htm">'
+ + '<frame src="frame_b.htm">' + '<frame src="frame_c.htm">'
+ + '</frameset>';
+
+ doc.body.appendChild(template);
+
+ assert_equals(template.content.childNodes.length, 0,
+ 'Template cannot contain FRAMESET element');
+
+}, 'Ignore frameset token. Test FRAMESET element assigned to template innerHTML');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var template = doc.createElement('template');
+
+ template.innerHTML = '<div id="div1">Some text</div>'
+ + '<frameset cols="25%,*,25%">'
+ + '<frame src="frame_a.htm">'
+ + '<frame src="frame_b.htm">'
+ + '<frame src="frame_c.htm">'
+ + '</frameset>';
+
+ doc.body.appendChild(template);
+
+ assert_equals(template.content.childNodes.length, 1,
+ 'Template cannot contain FRAMESET element');
+ assert_not_equals(template.content.querySelector('#div1'), null,
+ 'Template should contain valid element');
+
+}, 'Ignore frameset token. '
+ + 'Test FRAMESET element and some valid element before it, assigned '
+ + 'to the template\'s innerHTML');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var template = doc.createElement('template');
+
+ template.innerHTML = '<frameset cols="25%,*,25%">'
+ + '<frame src="frame_a.htm">'
+ + '<frame src="frame_b.htm">'
+ + '<frame src="frame_c.htm">'
+ + '</frameset><div id="div1">Some text</div>';
+
+ doc.body.appendChild(template);
+
+ assert_equals(template.content.childNodes.length, 1,
+ 'Template cannot contain FRAMESET element');
+ assert_not_equals(template.content.querySelector('#div1'), null,
+ 'Template should contain valid element');
+
+}, 'Ignore frameset token. '
+ + 'Test FRAMESET element and some valid element after it, assigned '
+ + 'to the template\'s innerHTML');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var template = doc.createElement('template');
+
+ template.innerHTML = '<template id="t2">'
+ + '<frameset cols="25%,*,25%">'
+ + '<frame src="frame_a.htm">'
+ + '<frame src="frame_b.htm">'
+ + '<frame src="frame_c.htm">'
+ + '</frameset></template>';
+
+ doc.body.appendChild(template);
+
+ assert_equals(template.content.childNodes.length, 1,
+ 'Template should contain nested template');
+ assert_not_equals(template.content.querySelector('#t2'), null,
+ 'Template should contain nested element');
+
+ var nestedTemplate = template.content.querySelector('#t2');
+
+ assert_equals(nestedTemplate.content.childNodes.length, 0,
+ 'Template cannot contain FRAMESET element');
+
+}, 'Ignore frameset token. '
+ + 'Test FRAMESET tag inside template tag assigned to another template\'s innerHTML');
+
+
+testInIFrame('../../resources/template-contents-frameset.html', function(context) {
+ var doc = context.iframes[0].contentDocument;
+
+ var template = doc.body.querySelector('template');
+
+ assert_equals(template.content.childNodes.length, 0,
+ 'Template cannot contain FRAMESET element');
+}, 'Ignore frameset token. Test loading a HTML file with FRAMESET tag inside template');
+
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/ignore-head-token.html b/tests/wpt/web-platform-tests/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/ignore-head-token.html
new file mode 100644
index 00000000000..28a499628d6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/ignore-head-token.html
@@ -0,0 +1,130 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>HTML Templates: In body insertion mode: parser should ignore HEAD token</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<meta name="assert" content="If parser is in 'in body' insertion mode and meets HEAD token it should be ignored">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#in-body-addition">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src='../../testcommon.js'></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script type="text/javascript">
+
+/*
+ * According to http://www.w3.org/TR/2013/WD-html-templates-20130214/#template-contents-insertion-mode
+ * when parser is in "template content" mode and meets <head> tag it should be switched to
+ * "in body" insertion mode.
+ * According to https://html.spec.whatwg.org/multipage/#parsing-main-inbody
+ * this token (HEAD) should be ignored
+ */
+
+test(function() {
+ var doc = newHTMLDocument();
+ var template = doc.createElement('template');
+
+ template.innerHTML = '<head></head>';
+
+ doc.body.appendChild(template);
+
+ assert_equals(template.content.childNodes.length, 0,
+ 'Template cannot contain HEAD element');
+
+}, 'Ignore HEAD token. Test empty HEAD element assigned to template innerHTML');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var template = doc.createElement('template');
+
+ template.innerHTML = '<head><title>test</title></head>';
+
+ doc.body.appendChild(template);
+
+ assert_equals(template.content.childNodes.length, 1,
+ 'Wrong number of template content children');
+ assert_equals(template.content.firstChild.nodeName, 'TITLE',
+ 'Template should contain children of ignored HEAD element');
+
+}, 'Ignore HEAD token. Test not empty HEAD element assigned to template innerHTML');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var template = doc.createElement('template');
+
+ template.innerHTML = '<div id="div1">Some text</div><head><title>test</title></head>';
+
+ doc.body.appendChild(template);
+
+ assert_equals(template.content.childNodes.length, 2,
+ 'Wrong number of template content children');
+ assert_not_equals(template.content.querySelector('#div1'), null,
+ 'Template should contain valid element');
+ assert_equals(template.content.lastChild.tagName, 'TITLE',
+ 'Template should contain children of ignored HEAD element');
+
+}, 'Ignore HEAD token. '
+ + 'Test HEAD element and some valid element before it, assigned to template innerHTML');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var template = doc.createElement('template');
+
+ template.innerHTML = '<head><title>test</title></head><div id="div1">Some text</div>';
+
+ doc.body.appendChild(template);
+
+ assert_equals(template.content.childNodes.length, 2,
+ 'Wrong number of template content children');
+ assert_equals(template.content.firstChild.tagName, 'TITLE',
+ 'Template should contain children of ignored HEAD element');
+ assert_not_equals(template.content.querySelector('#div1'), null,
+ 'Template should contain valid element');
+
+}, 'Ignore HEAD token. '
+ + 'Test HEAD element and some valid element after it, assigned to template innerHTML');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var template = doc.createElement('template');
+
+ template.innerHTML = '<template id="t2"><head><title>test</title></head></template>';
+
+ doc.body.appendChild(template);
+
+ assert_equals(template.content.childNodes.length, 1,
+ 'Template should contain nested template');
+ assert_not_equals(template.content.querySelector('#t2'), null,
+ 'Template should contain nested element');
+
+ var nestedTemplate = template.content.querySelector('#t2');
+
+ assert_equals(nestedTemplate.content.childNodes.length, 1,
+ 'Wrong number of template content children');
+ assert_equals(nestedTemplate.content.firstChild.tagName, 'TITLE',
+ 'Template should contain children of ignored HEAD element');
+
+}, 'Ignore HEAD token. '
+ + 'Test HEAD tag inside template tag assigned to another template\'s innerHTML');
+
+
+testInIFrame('../../resources/template-contents-head.html', function(context) {
+ var doc = context.iframes[0].contentDocument;
+
+ var template = doc.body.querySelector('template');
+
+ assert_equals(template.content.childNodes.length, 0,
+ 'Template cannot contain HEAD element');
+
+}, 'Ignore HEAD token. Test loading a HTML file with HEAD tag inside template');
+
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/ignore-html-token.html b/tests/wpt/web-platform-tests/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/ignore-html-token.html
new file mode 100644
index 00000000000..80bf61ace90
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/ignore-html-token.html
@@ -0,0 +1,159 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>HTML Templates: In body insertion mode: parser should ignore HTML token</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<meta name="assert" content="If parser is in 'in body' insertion mode and meets HTML token it should be ignored">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#in-body-addition">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src='../../testcommon.js'></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script type="text/javascript">
+
+/*
+ * According to http://www.w3.org/TR/2013/WD-html-templates-20130214/#template-contents-insertion-mode
+ * when parser is in "template content" mode and meets <html> tag it should be switched to
+ * "in body" insertion mode.
+ * According to https://html.spec.whatwg.org/multipage/#parsing-main-inbody
+ * this token (HTML) should be ignored
+ */
+
+test(function() {
+ var doc = newHTMLDocument();
+ var template = doc.createElement('template');
+
+ template.innerHTML = '<html><body></body></html>';
+
+ doc.body.appendChild(template);
+
+ assert_equals(template.content.childNodes.length, 0,
+ 'Template cannot contain HTML element');
+
+}, 'Ignore HTML token. Test HTML element assigned to template innerHTML');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var template = doc.createElement('template');
+
+ template.innerHTML = '<div id="div1">Some text</div><html><body></body></html>';
+
+ doc.body.appendChild(template);
+
+ assert_equals(template.content.childNodes.length, 1,
+ 'Template cannot contain HTML element');
+ assert_not_equals(template.content.querySelector('#div1'), null,
+ 'Template should contain valid element');
+
+}, 'Ignore HTML token.'
+ + 'Test HTML element and some valid element before it, assigned to template innerHTML');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var template = doc.createElement('template');
+
+ template.innerHTML = '<html><body></body></html><div id="div1">Some text</div>';
+
+ doc.body.appendChild(template);
+
+ assert_equals(template.content.childNodes.length, 1,
+ 'Template cannot contain HTML element');
+ assert_not_equals(template.content.querySelector('#div1'), null,
+ 'Template should contain valid element');
+
+}, 'Ignore HTML token. '
+ + 'Test HEAD element and some valid element after it, assigned to template innerHTML');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var template = doc.createElement('template');
+
+ template.innerHTML = '<template id="t2"><html><body></body></html></template>';
+
+ doc.body.appendChild(template);
+
+ assert_equals(template.content.childNodes.length, 1,
+ 'Template should contain nested template');
+ assert_not_equals(template.content.querySelector('#t2'), null,
+ 'Template should contain nested element');
+
+ var nestedTemplate = template.content.querySelector('#t2');
+
+ assert_equals(nestedTemplate.content.childNodes.length, 0,
+ 'Template cannot contain HTML element');
+
+}, 'Ignore HTML token. '
+ + 'Test HTML tag inside template tag assigned to another template\'s innerHTML');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var template = doc.createElement('template');
+
+ template.innerHTML = '<html><div id="div1">Some text</div></html>';
+
+ doc.body.appendChild(template);
+
+ assert_equals(template.content.childNodes.length, 1,
+ 'Template cannot contain HTML element');
+ assert_not_equals(template.content.querySelector('#div1'), null,
+ 'Template should contain a valid element');
+
+}, 'Ignore HTML token. Test some valid element inside HTML element');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var template = doc.createElement('template');
+
+ template.innerHTML = '<html><body><div id="div1">Some text</div><body></html>';
+
+ doc.body.appendChild(template);
+
+ assert_equals(template.content.childNodes.length, 1,
+ 'Template cannot contain HTML element');
+ assert_not_equals(template.content.querySelector('#div1'), null,
+ 'Template should contain valid element');
+
+}, 'Ignore HTML token. Test valid element inside HTML and BODY elements');
+
+
+test(function() {
+ var doc = newHTMLDocument();
+ var template = doc.createElement('template');
+
+ template.innerHTML = '<html><span id="span1">Span</span><body><div id="div1">Some text</div><body></html>';
+
+ doc.body.appendChild(template);
+
+ assert_equals(template.content.childNodes.length, 2,
+ 'Template cannot contain HTML element');
+ assert_not_equals(template.content.querySelector('#div1'), null,
+ 'Template should contain valid DIV element');
+
+ assert_not_equals(template.content.querySelector('#span1'), null,
+ 'Template should contain valid SPAN element');
+
+}, 'Ignore HTML token. Test valid element inside and between HTML and BODY elements');
+
+
+testInIFrame('../../resources/template-contents-html.html', function(context) {
+ var doc = context.iframes[0].contentDocument;
+
+ var template = doc.body.querySelector('template');
+
+ assert_equals(template.content.childNodes.length, 0,
+ 'Template cannot contain HTML element');
+
+}, 'Ignore HTML token. Test loading a HTML file with HTML tag inside template');
+
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/start-tag-body.html b/tests/wpt/web-platform-tests/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/start-tag-body.html
new file mode 100644
index 00000000000..80a4b8dcdd1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/start-tag-body.html
@@ -0,0 +1,98 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>HTML Templates: In body insertion mode: Template contains a start tag whose tag name is body</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="assert" content="If the stack of open elements has a template element in html scope then ignore <body> the token. (fragment or template contents case)">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#in-body-addition">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src='../../testcommon.js'></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script type="text/javascript">
+
+
+test(function () {
+ var doc = newHTMLDocument();
+
+ doc.body.innerHTML = '<template id="tmpl"><body></template>';
+
+ var template = doc.querySelector('#tmpl');
+
+ assert_equals(template.content.childNodes.length, 0, 'Element must be ignored');
+
+}, 'In body insertion mode: Template contains a start tag whose tag name is body.'
+ + 'Test <body> tag only');
+
+
+
+test(function () {
+ var doc = newHTMLDocument();
+
+ doc.body.innerHTML = '<template id="tmpl"><body>Body text content</body></template>';
+
+ var template = doc.querySelector('#tmpl');
+
+ assert_equals(template.content.querySelector('body'), null,
+ '<body> element must be ignored');
+ assert_equals(template.content.childNodes.length, 1, 'Text shouldn\'t be ignored');
+ assert_equals(template.content.firstChild.nodeType, Node.TEXT_NODE,
+ 'Text shouldn\'t be ignored');
+
+}, 'In body insertion mode: Template contains a start tag whose tag name is body. '
+ + 'Test <body> tag containing some text');
+
+
+
+test(function () {
+ var doc = newHTMLDocument();
+
+ doc.body.innerHTML = '<template id="tmpl"><body>'
+ + '<div id="div1">DIV 1</div>'
+ + '<div id="div2">DIV 2</div>'
+ + '</body></template>';
+
+ var template = doc.querySelector('#tmpl');
+
+ assert_equals(template.content.querySelector('body'), null,
+ '<body> element must be ignored');
+ assert_equals(template.content.childNodes.length, 2,
+ 'Only body tag should be ignored');
+ assert_not_equals(template.content.querySelector('#div1'), null,
+ 'Children of <body tag shouldn\'t be ignored');
+ assert_not_equals(template.content.querySelector('#div2'), null,
+ 'Children of <body tag shouldn\'t be ignored');
+
+}, 'In body insertion mode: Template contains a start tag whose tag name is body. '
+ + 'Test <body> tag containing some other elements');
+
+
+
+test(function () {
+ var doc = newHTMLDocument();
+
+ doc.body.innerHTML = '<template id="tmpl1"><template id="tmpl2"><body>'
+ + '<div id="div1">DIV 1</div>'
+ + '<div id="div2">DIV 2</div>'
+ + '</body></template></template>';
+
+ var template = doc.querySelector('#tmpl1').content.querySelector('#tmpl2');
+
+ assert_equals(template.content.querySelector('body'), null,
+ '<body> element must be ignored');
+ assert_equals(template.content.childNodes.length, 2,
+ 'Only body tag should be ignored');
+ assert_not_equals(template.content.querySelector('#div1'), null,
+ 'Children of <body tag shouldn\'t be ignored');
+ assert_not_equals(template.content.querySelector('#div2'), null,
+ 'Children of <body tag shouldn\'t be ignored');
+
+}, 'In body insertion mode: Template contains a start tag whose tag name is body. '
+ + 'Test nested template tag containing <body> tag with some other elements');
+
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/start-tag-html.html b/tests/wpt/web-platform-tests/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/start-tag-html.html
new file mode 100644
index 00000000000..7d3f47884eb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/start-tag-html.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>HTML Templates: In body insertion mode: A start tag whose tag name is html</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="assert" content="If HTML parser is in 'in body' insertion mode and meets HTML start tag, then for each attribute on the token, check to see if the attribute is already present on the top element of the stack of open elements. If it is not, add the attribute and its corresponding value to that element">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#in-body-addition">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src='../../testcommon.js'></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script type="text/javascript">
+
+// test <template><html class="htmlClass"></html></template><html id="htmlId" tabindex="5">
+// id attribute should be added to root <html> element
+// tabindex attribute should not be modified
+//class attribute should be ignored
+testInIFrame('../../resources/html-start-tag.html', function(context) {
+ var doc = context.iframes[0].contentDocument;
+
+ var template = doc.body.querySelector('template');
+
+ var html = doc.documentElement;
+
+ assert_equals(html.getAttribute('tabindex'), '5', 'Attribute should be accessible');
+ assert_equals(html.getAttribute('id'), 'htmlId',
+ 'Attribute \'id\' should be added and accessible');
+ assert_false(html.hasAttribute('class'), 'Attribute \'class\' should be ignored');
+ assert_equals(template.content.childNodes.length, 0, 'Template should not contain HTML element');
+
+
+}, 'In body insertion mode: html start tag should add only absent attributes');
+
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/template-end-tag-without-start-one.html b/tests/wpt/web-platform-tests/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/template-end-tag-without-start-one.html
new file mode 100644
index 00000000000..0039783d95d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/template/additions-to-the-in-body-insertion-mode/template-end-tag-without-start-one.html
@@ -0,0 +1,103 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>HTML Templates: 'In body' insertion mode: Template end tag without start one. Element should be ignored</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="author" title="Aleksei Yu. Semenov" href="a.semenov@unipro.ru">
+<meta name="assert" content="If parser in 'in body' insertion mode meets template end tag and if the stack of open elements has no template element in html scope, then this is a parse error; ignore the token">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#in-body-addition">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src='../../testcommon.js'></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script type="text/javascript">
+
+
+test(function () {
+ var doc = newHTMLDocument();
+
+ doc.body.innerHTML = '</template>';
+
+ assert_equals(doc.body.childNodes.length, 0, 'Element must be ignored');
+
+}, '</template> tag in HTML body without start one should be ignored');
+
+
+
+test(function () {
+ var doc = newHTMLDocument();
+
+ doc.body.innerHTML = '<template id="tmpl"></template></template>';
+
+ assert_equals(doc.body.childNodes.length, 1, 'Element must be ignored');
+ assert_not_equals(doc.querySelector('#tmpl'), null,
+ 'Element should present it document body');
+
+}, '</template> tag in HTML body without start one should be ignored. '
+ + 'Test valid <template> element and </template> tag after it');
+
+
+
+test(function () {
+ var doc = newHTMLDocument();
+
+ doc.body.innerHTML = '</template><template id="tmpl"></template>';
+
+ assert_equals(doc.body.childNodes.length, 1, 'Element must be ignored');
+ assert_not_equals(doc.querySelector('#tmpl'), null,
+ 'Element should present it document body');
+
+}, '</template> tag in HTML body without start one should be ignored. '
+ + 'Test valid <template> element and </template> tag before it');
+
+
+
+test(function () {
+ var doc = newHTMLDocument();
+
+ doc.body.innerHTML = '</template><template id="tmpl"></template><title></title>';
+
+ assert_equals(doc.body.childNodes.length, 2, 'Element must be ignored');
+ assert_not_equals(doc.querySelector('#tmpl'), null,
+ 'Valid element should present it document body');
+ assert_not_equals(doc.querySelector('title'), null,
+ 'Valid title element should present it document body');
+
+}, '</template> tag in HTML body without start one should be ignored. '
+ + 'Test valid <template> element, <title> element and </template> tag before them');
+
+
+
+test(function () {
+ var doc = newHTMLDocument();
+
+ doc.body.innerHTML = '<template id="tmpl"></template><title></title></template>';
+
+ assert_equals(doc.body.childNodes.length, 2, 'Element must be ignored');
+ assert_not_equals(doc.querySelector('#tmpl'), null,
+ 'Valid element should present it document body');
+ assert_not_equals(doc.querySelector('title'), null,
+ 'Valid title element should present it document body');
+
+}, '</template> tag in HTML body without start one should be ignored. '
+ + 'Test valid <template> element, <title> element and </template> tag after them');
+
+
+testInIFrame('../../resources/end-template-tag-in-body.html', function(context) {
+ var doc = context.iframes[0].contentDocument;
+
+ assert_equals(doc.body.querySelector('template'), null,
+ '</template> must be ignored');
+ assert_not_equals(doc.body.querySelector('div'), null,
+ 'Valid element should present it document body');
+
+}, '</template> tag in HTML body without start one should be ignored. '
+ + 'Test HTML document loaded from file');
+
+
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/template/additions-to-the-in-frameset-insertion-mode/end-tag-frameset.html b/tests/wpt/web-platform-tests/html/syntax/parsing/template/additions-to-the-in-frameset-insertion-mode/end-tag-frameset.html
new file mode 100644
index 00000000000..2bc5b72a831
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/template/additions-to-the-in-frameset-insertion-mode/end-tag-frameset.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>HTML Templates: additions to 'in frameset' insertion mode</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="assert" content="If parser is in 'in frameset' insertion mode and meets frameset end tag then if the stack of open elements has a template element in html scope then this is a parse error; ignore the token">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#in-head-addition">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src='../../testcommon.js'></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script type="text/javascript">
+
+testInIFrame('../../resources/frameset-end-tag.html', function(context) {
+ var doc = context.iframes[0].contentDocument;
+
+ var frameset = doc.querySelector('frameset');
+ assert_equals(frameset.children.length, 1, 'Wrong number of frameset children elements');
+
+ var template = frameset.querySelector('template');
+ assert_equals(template.tagName, 'TEMPLATE', 'FRAMESET should contain template element');
+ assert_equals(template.content.childNodes.length, 0,
+ 'Template content should be empty');
+
+}, '</frameset> tag should be ignored if there\'s TEMPLATE element in '
+ + 'the stack of open elements');
+
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/template/additions-to-the-in-head-insertion-mode/generating-of-implied-end-tags.html b/tests/wpt/web-platform-tests/html/syntax/parsing/template/additions-to-the-in-head-insertion-mode/generating-of-implied-end-tags.html
new file mode 100644
index 00000000000..7fc96301e55
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/template/additions-to-the-in-head-insertion-mode/generating-of-implied-end-tags.html
@@ -0,0 +1,138 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>HTML Templates: When template end tag is met, implied end tags should be generated</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="author" title="Aleksei Yu. Semenov" href="a.semenov@unipro.ru">
+<meta name="assert" content="When template end tag is met, implied end tags should be generated">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#in-head-addition">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src='../../testcommon.js'></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script type="text/javascript">
+
+
+test(function () {
+ var doc = newHTMLDocument();
+
+ //No end </td></tr></table> tags. Should be added implicitly
+ doc.head.innerHTML = '<template id="tpl">'
+ + '<table id="tbl"><tr id="tr"><td id="td"></template>';
+
+ var template = doc.querySelector('#tpl');
+
+ assert_not_equals(template, null, 'Template element must be parsed');
+
+ assert_equals(doc.querySelector('#tbl'), null, 'Table element should not be available');
+ assert_equals(doc.querySelector('#tr'), null, 'TR element should not be available');
+ assert_equals(doc.querySelector('#td'), null, 'TD element should not be available');
+
+ assert_not_equals(template.content.querySelector('#tbl'), null,
+ 'Template should contain table element');
+ assert_not_equals(template.content.querySelector('#tr'), null,
+ 'Template should contain TR element');
+ assert_not_equals(template.content.querySelector('#td'), null,
+ 'Template should contain TD element');
+
+}, 'Generating of implied end tags. Test table elements');
+
+
+
+test(function () {
+ var doc = newHTMLDocument();
+
+ //No end </div> tag. Should be added implicitly
+ doc.head.innerHTML = '<template id="tpl"><div id="dv">Div content</template>';
+
+ var template = doc.querySelector('#tpl');
+
+ assert_not_equals(template, null, 'Template element must be parsed');
+
+ assert_equals(doc.querySelector('#dv'), null, 'DIV element should not be available');
+
+ assert_not_equals(template.content.querySelector('#dv'), null,
+ 'Template should contain DIV element');
+
+}, 'Generating of implied end tags. Test DIV element');
+
+
+test(function () {
+ var doc = newHTMLDocument();
+
+ //No end </div> tag. Should be added implicitly after text content
+ doc.head.innerHTML = '<template id="tpl">Template text<div id="dv">Div content</template>';
+
+ var template = doc.querySelector('#tpl');
+
+ assert_not_equals(template, null, 'Template element must be parsed');
+
+ assert_equals(doc.querySelector('#dv'), null, 'DIV element should not be available');
+
+ var div = template.content.querySelector('#dv');
+
+ assert_not_equals( div, null, 'Template should contain DIV element');
+ assert_equals(div.innerText, 'Div content', 'Wrong template content inner text');
+
+}, 'Generating of implied end tags. Test some text and DIV element');
+
+
+test(function () {
+ var doc = newHTMLDocument();
+
+ // Wrong end tag. Correct end tag must be added implicitly, wrong one ignored
+ doc.head.innerHTML = '<template id="tpl"><div id="dv">Div content</span></template>';
+
+ var template = doc.querySelector('#tpl');
+
+ assert_not_equals(template, null, 'Template element must be parsed');
+
+ assert_equals(template.content.childNodes.length, 1,
+ 'Wrong number of template\'s children');
+
+ assert_equals(doc.querySelector('#dv'), null, 'DIV element should not be available');
+
+ assert_not_equals(template.content.querySelector('#dv'), null,
+ 'Template should contain DIV element');
+ assert_equals(template.content.querySelector('#dv').innerText,
+ 'Div content', 'Wrong template content inner text');
+
+}, 'Generating of implied end tags. Test wrong end tag');
+
+
+testInIFrame('../../resources/head-template-contents-table-no-end-tag.html', function(context) {
+ var doc = context.iframes[0].contentDocument;
+
+ var template = doc.head.querySelector('template');
+
+ assert_not_equals(template, null,
+ 'Template element must be parsed');
+
+ assert_not_equals(template.content.querySelector('table'), null,
+ 'Template should contain table element');
+ assert_not_equals(template.content.querySelector('tr'), null,
+ 'Template should contain TR element');
+ assert_not_equals(template.content.querySelector('td'), null,
+ 'Template should contain TD element');
+
+}, 'Generating of implied end tags. Test table elements. Load HTML document from file');
+
+
+testInIFrame('../../resources/head-template-contents-div-no-end-tag.html', function(context) {
+ var doc = context.iframes[0].contentDocument;
+
+ var template = doc.head.querySelector('template');
+
+ assert_not_equals(template, null, 'Template element must be parsed');
+
+ var div = template.content.querySelector('div');
+ assert_not_equals(div, null, 'Template should contain div element');
+ assert_equals(div.innerText, 'Hello, template\n ', 'Invalid div contents');
+
+}, 'Generating of implied end tags. Test div element. Load HTML document from file');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/template/additions-to-the-in-head-insertion-mode/template-end-tag-without-start-one.html b/tests/wpt/web-platform-tests/html/syntax/parsing/template/additions-to-the-in-head-insertion-mode/template-end-tag-without-start-one.html
new file mode 100644
index 00000000000..b7e6009ab13
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/template/additions-to-the-in-head-insertion-mode/template-end-tag-without-start-one.html
@@ -0,0 +1,102 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>HTML Templates: Template end tag without start one. Element should be ignored</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="author" title="Aleksei Yu. Semenov" href="a.semenov@unipro.ru">
+<meta name="assert" content="If parser in 'in head' insertion mode meets template end tag and if the stack of open elements has no template element in html scope, then this is a parse error; ignore the token">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#in-head-addition">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src='../../testcommon.js'></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script type="text/javascript">
+
+
+test(function () {
+ var doc = newHTMLDocument();
+
+ doc.head.innerHTML = '</template>';
+
+ assert_equals(doc.head.childNodes.length, 0, 'Element must be ignored');
+
+}, '</template> tag in HTML head without start one should be ignored');
+
+
+
+test(function () {
+ var doc = newHTMLDocument();
+
+ doc.head.innerHTML = '<template id="tmpl"></template></template>';
+
+ assert_equals(doc.head.childNodes.length, 1, 'Element must be ignored');
+ assert_not_equals(doc.querySelector('#tmpl'), null,
+ 'Element should present it document head');
+
+}, '</template> tag in HTML head without start one should be ignored. '
+ + 'Test valid <template> element and </template> tag after it');
+
+
+
+test(function () {
+ var doc = newHTMLDocument();
+
+ doc.head.innerHTML = '</template><template id="tmpl"></template>';
+
+ assert_equals(doc.head.childNodes.length, 1, 'Element must be ignored');
+ assert_not_equals(doc.querySelector('#tmpl'), null,
+ 'Element should present it document head');
+
+}, '</template> tag in HTML head without start one should be ignored. '
+ + 'Test valid <template> element and </template> tag before it');
+
+
+
+test(function () {
+ var doc = newHTMLDocument();
+
+ doc.head.innerHTML = '</template><template id="tmpl"></template><title></title>';
+
+ assert_equals(doc.head.childNodes.length, 2, 'Element must be ignored');
+ assert_not_equals(doc.querySelector('#tmpl'), null,
+ 'Valid element should present it document head');
+ assert_not_equals(doc.querySelector('title'), null,
+ 'Valid title element should present it document head');
+
+}, '</template> tag in HTML head without start one should be ignored. '
+ + 'Test valid <template> element, <title> element and </template> tag before them');
+
+
+
+test(function () {
+ var doc = newHTMLDocument();
+
+ doc.head.innerHTML = '<template id="tmpl"></template><title></title></template>';
+
+ assert_equals(doc.head.childNodes.length, 2, 'Element must be ignored');
+ assert_not_equals(doc.querySelector('#tmpl'), null,
+ 'Valid element should present it document head');
+ assert_not_equals(doc.querySelector('title'), null,
+ 'Valid title element should present it document head');
+
+}, '</template> tag in HTML head without start one should be ignored. '
+ + 'Test valid <template> element, <title> element and </template> tag after them');
+
+
+testInIFrame('../../resources/end-template-tag-in-head.html', function(context) {
+ var doc = context.iframes[0].contentDocument;
+
+ assert_equals(doc.head.querySelector('template'), null, '</template> must be ignored');
+ assert_not_equals(doc.head.querySelector('title'), null,
+ 'Valid element should present it document head');
+
+}, '</template> tag in HTML head without start one should be ignored. '
+ + 'Test HTML document loaded from file');
+
+
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/template/additions-to-the-in-table-insertion-mode/end-tag-table.html b/tests/wpt/web-platform-tests/html/syntax/parsing/template/additions-to-the-in-table-insertion-mode/end-tag-table.html
new file mode 100644
index 00000000000..76ab5c444ec
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/template/additions-to-the-in-table-insertion-mode/end-tag-table.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>HTML Templates: 'In table' insertion mode: ignore TABLE end tag</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="assert" content="If parser is in 'in table' insertion mode and end tag table is met the ignore this token">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#in-table-addition">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src='../../testcommon.js'></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script type="text/javascript">
+
+
+test(function () {
+ var doc = newHTMLDocument();
+
+ doc.body.innerHTML = '<table id="table">'
+ + '<template id="template">'
+ + '</table>'
+ + '</template>'
+ + '<tr><td></td></tr>'
+ + '</table>';
+
+ var table = doc.querySelector('#table');
+ var template = table.querySelector('#template');
+
+ assert_equals(table.childNodes.length, 2, 'Wrong number of table children');
+ assert_not_equals(template, null, 'Template element must be parsed');
+ assert_equals(table.rows.length, 1, 'Wrong number of table rows');
+ assert_equals(template.childNodes.length, 0, 'Wrong number of the template child nodes');
+ assert_equals(template.content.childNodes.length, 0,
+ 'Wrong number of the template child nodes');
+
+
+}, 'In table insertion mode. Ignore </table> token');
+
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/template/appending-to-a-template/template-child-nodes.html b/tests/wpt/web-platform-tests/html/syntax/parsing/template/appending-to-a-template/template-child-nodes.html
new file mode 100644
index 00000000000..6c68cde500d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/template/appending-to-a-template/template-child-nodes.html
@@ -0,0 +1,117 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>HTML Templates: HTML parser appends child nodes only to the template contents node</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<meta name="assert" content="HTML parser must append template's child nodes only to the template contents node.">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#appending-to-a-template">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src='../../testcommon.js'></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script type="text/javascript">
+
+
+test(function () {
+ var doc = newHTMLDocument();
+ doc.body.innerHTML = '<template id="tmpl1">' +
+ '<div id="div1">This is div inside template</div>' +
+ '<div id="div2">This is another div inside template</div>' +
+ '</template>';
+
+ var template = doc.querySelector('#tmpl1');
+
+ assert_equals(template.childNodes.length, 0, 'Wrong number of template child nodes');
+ assert_equals(template.content.childNodes.length, 2,
+ 'Wrong number of template content child nodes');
+
+ assert_not_equals(template.content.querySelector('#div1'), null,
+ 'Element is absent in the template content');
+ assert_not_equals(template.content.querySelector('#div2'), null,
+ 'Element is absent in the template content');
+
+}, 'Template child nodes must be appended to template content node');
+
+
+
+test(function () {
+ var doc = newHTMLDocument();
+ doc.body.innerHTML = '<template id="tmpl1">' +
+ '<div id="div1">This is div inside template</div>' +
+ '<div id="div2">This is another div inside template</div>' +
+ '<template id="tmpl2">' +
+ '<div id="div3">This is div inside nested template</div>' +
+ '<div id="div4">This is another div inside nested template</div>' +
+ '</template>' +
+ '</template>';
+
+ var template = doc.querySelector('#tmpl1');
+
+ assert_equals(template.childNodes.length, 0,
+ 'Wrong number of template child nodes');
+ assert_equals(template.content.childNodes.length, 3,
+ 'Wrong number of template content child nodes');
+
+ assert_not_equals(template.content.querySelector('#div1'), null,
+ 'Element is absent in the template content');
+ assert_not_equals(template.content.querySelector('#div2'), null,
+ 'Element is absent in the template content');
+
+ var nestedTemplate = template.content.querySelector('#tmpl2');
+
+ assert_equals(nestedTemplate.childNodes.length, 0,
+ 'Wrong number of template child nodes');
+ assert_equals(nestedTemplate.content.childNodes.length, 2,
+ 'Wrong number of nested template content child nodes');
+
+ assert_not_equals(nestedTemplate.content.querySelector('#div3'), null,
+ 'Element is absent in the template content');
+ assert_not_equals(nestedTemplate.content.querySelector('#div4'), null,
+ 'Element is absent in the template content');
+
+}, 'Template child nodes must be appended to template content. Test nested template');
+
+
+
+testInIFrame('../../resources/template-contents.html', function(context) {
+ var doc = context.iframes[0].contentDocument;
+
+ var template = doc.querySelector('template');
+
+ assert_equals(template.childNodes.length, 0, 'Wrong number of template child nodes');
+
+ assert_not_equals(template.content.querySelector('div'), null,
+ 'Element is absent in the template content');
+
+}, 'Template child nodes must be appended to template content node. '
+ + 'Load HTML document from a file');
+
+
+testInIFrame('../../resources/template-contents-nested.html', function(context) {
+ var doc = context.iframes[0].contentDocument;
+
+ var template = doc.querySelector('template');
+
+ assert_equals(template.childNodes.length, 0, 'Wrong number of template child nodes');
+
+ var nestedTemplate = template.content.querySelector('template');
+
+ assert_not_equals(nestedTemplate, null,
+ 'Element is absent in the template content');
+
+ assert_equals(nestedTemplate.childNodes.length, 0,
+ 'Wrong number of template child nodes');
+
+ assert_not_equals(nestedTemplate.content.querySelector('div'), null,
+ 'Element is absent in the template content');
+
+}, 'Template child nodes must be appended to nested template content node. '
+ + 'Load HTML document from a file');
+
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/template/clearing-the-stack-back-to-a-given-context/clearing-stack-back-to-a-table-body-context.html b/tests/wpt/web-platform-tests/html/syntax/parsing/template/clearing-the-stack-back-to-a-given-context/clearing-stack-back-to-a-table-body-context.html
new file mode 100644
index 00000000000..e510028db8a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/template/clearing-the-stack-back-to-a-given-context/clearing-stack-back-to-a-table-body-context.html
@@ -0,0 +1,183 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>HTML Templates: Clearing stack back to a table body context</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="assert" content="Clearing the stack back to a table body context must be aborted if the current node is template">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#clearing-the-stack">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src='../../testcommon.js'></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script type="text/javascript">
+
+function doTest(doc, tagToTest, templateInnerHTML, id, tagName, bodiesNum, footerIsNull,
+ footerId, headerIsNull, headerId) {
+
+ doc.body.innerHTML = '' +
+ '<table id="tbl">' +
+ '<' + tagToTest + '>' +
+ '<template id="tmpl1">' +
+ // When parser meets <tr>, </tbody>, </tfoot>, </thead>, <caption>, <col>,
+ // <colgroup>, <tbody>, <tfoot>, <thead>, </table>
+ // stack must be cleared back to table body context. But <template> tag should
+ // abort this
+ templateInnerHTML +
+ '</template>' +
+ '<tr id="tr">' +
+ '<td id="td">' +
+ '</td>' +
+ '</tr>' +
+ '</' + tagToTest + '>' +
+ '</table>';
+
+ var table = doc.querySelector('#tbl');
+ var tr = doc.querySelector('#tr');
+ var td = doc.querySelector('#td');
+ var template = doc.querySelector('#tmpl1');
+
+ assert_equals(table.rows.length, 1, 'Wrong number of table rows');
+ assert_equals(table.rows[0].cells.length, 1, 'Wrong number of table cells');
+ if (id !== null) {
+ assert_not_equals(template.content.querySelector('#' + id), null,
+ 'Element should present in the template content');
+ }
+ if (tagName !== null) {
+ assert_equals(template.content.querySelector('#' + id).tagName, tagName,
+ 'Wrong element in the template content');
+ }
+
+ assert_equals(table.caption, null, 'Table should have no caption');
+
+ if (bodiesNum) {
+ assert_equals(table.tBodies.length, bodiesNum, 'Table should have '
+ + bodiesNum + ' body');
+ }
+ if (footerIsNull) {
+ assert_equals(table.tFoot, null, 'Table should have no footer');
+ }
+ if (footerId) {
+ assert_not_equals(table.tFoot.id, footerId,
+ 'Table should have no footer with id="' + footerId + '"');
+ }
+ if (headerIsNull) {
+ assert_equals(table.tHead, null, 'Table should have no header');
+ }
+ if (headerId) {
+ assert_not_equals(table.tHead.id, headerId,
+ 'Table should have no header with id="' + headerId + '"');
+ }
+}
+
+
+
+var doc = newHTMLDocument();
+var parameters = [
+ ['Clearing stack back to a table body context. Test <tr> in <tbody>',
+ doc, 'tbody', '<tr id="tr1"><td>Cell content</td></tr>', 'tr1', 'TR'],
+
+ ['Clearing stack back to a table body context. Test <tr> in <thead>',
+ doc, 'thead', '<tr id="tr2"><td>Cell content</td></tr>', 'tr2', 'TR'],
+
+ ['Clearing stack back to a table body context. Test <tr> in <tfoot>',
+ doc, 'tfoot', '<tr id="tr3"><td>Cell content</td></tr>', 'tr3', 'TR'],
+
+ ['Clearing stack back to a table body context. Test </tbody>',
+ doc, 'tbody', '</tbody>', null, null],
+
+ ['Clearing stack back to a table body context. Test </thead>',
+ doc, 'thead', '</thead>', null, null],
+
+ ['Clearing stack back to a table body context. Test </tfoot>',
+ doc, 'tfoot', '</tfoot>', null, null],
+
+ ['Clearing stack back to a table body context. Test <caption> in <tbody>',
+ doc, 'tbody', '<caption id="caption1">Table Caption</caption>', 'caption1', 'CAPTION'],
+
+ ['Clearing stack back to a table body context. Test <caption> in <tfoot>',
+ doc, 'tfoot', '<caption id="caption2">Table Caption</caption>', 'caption2', 'CAPTION'],
+
+ ['Clearing stack back to a table body context. Test <caption> in <thead>',
+ doc, 'thead', '<caption id="caption3">Table Caption</caption>', 'caption3', 'CAPTION'],
+
+ ['Clearing stack back to a table body context. Test <col> in <tbody>',
+ doc, 'tbody', '<col id="col1" width="150"/>', 'col1', 'COL'],
+
+ ['Clearing stack back to a table body context. Test <col> in <tfoot>',
+ doc, 'tfoot', '<col id="col2" width="150"/>', 'col2', 'COL'],
+
+ ['Clearing stack back to a table body context. Test <col> in <thead>',
+ doc, 'thead', '<col id="col3" width="150"/>', 'col3', 'COL'],
+
+ ['Clearing stack back to a table body context. Test <colgroup> in <tbody>',
+ doc, 'tbody', '<colgroup id="colgroup1" width="150"/>', 'colgroup1', 'COLGROUP'],
+
+ ['Clearing stack back to a table body context. Test <colgroup> in <tfoot>',
+ doc, 'tfoot', '<colgroup id="colgroup2" width="150"/>', 'colgroup2', 'COLGROUP'],
+
+ ['Clearing stack back to a table body context. Test <colgroup> in <thead>',
+ doc, 'thead', '<colgroup id="colgroup3" width="150"/>', 'colgroup3', 'COLGROUP'],
+
+ ['Clearing stack back to a table body context. Test <tbody> in <tbody>',
+ doc, 'tbody', '<tbody id="tbody1"></tbody>', 'tbody1', 'TBODY', 1],
+
+ ['Clearing stack back to a table body context. Test <tbody> in <tfoot>',
+ doc, 'tfoot', '<tbody id="tbody2"></tbody>', 'tbody2', 'TBODY', 0],
+
+ ['Clearing stack back to a table body context. Test <tbody> in <thead>',
+ doc, 'thead', '<tbody id="tbody3"></tbody>', 'tbody3', 'TBODY', 0],
+
+ ['Clearing stack back to a table body context. Test <tfoot> in <tbody>',
+ doc, 'tbody', '<tfoot id="tfoot1"></tfoot>', 'tfoot1', 'TFOOT', null, true],
+
+ ['Clearing stack back to a table body context. Test <tfoot> in <tfoot>',
+ doc, 'tfoot', '<tfoot id="tfoot2"></tfoot>', 'tfoot2', 'TFOOT', null, false, 'tfoot2'],
+
+ ['Clearing stack back to a table body context. Test <tfoot> in <thead>',
+ doc, 'thead', '<tfoot id="tfoot3"></tfoot>', 'tfoot3', 'TFOOT', null, true],
+
+ ['Clearing stack back to a table body context. Test <thead> in <tbody>',
+ doc, 'tbody', '<thead id="thead1"></thead>', 'thead1', 'THEAD', null, false, null, true],
+
+ ['Clearing stack back to a table body context. Test <thead> in <tfoot>',
+ doc, 'tfoot', '<thead id="thead2"></thead>', 'thead2', 'THEAD', null, false, null, true],
+
+ ['Clearing stack back to a table body context. Test <thead> in <thead>',
+ doc, 'thead', '<thead id="thead3"></thead>', 'thead3', 'THEAD', null, false, null, false, 'thead3'],
+
+ ['Clearing stack back to a table body context. Test </table> in <tbody>',
+ doc, 'tbody', '</table>', null, null, null, false, null, true],
+
+ ['Clearing stack back to a table body context. Test </table> in <tfoot>',
+ doc, 'tfoot', '</table>', null, null, null, false, null, true],
+
+ ['Clearing stack back to a table body context. Test </table> in <thead>',
+ doc, 'thead', '</table>', null, null],
+
+ ['Clearing stack back to a table body context. Test </tbody> in <thead>',
+ doc, 'thead', '</tbody>', null, null],
+
+ ['Clearing stack back to a table body context. Test </tbody> in <tfoot>',
+ doc, 'tfoot', '</tbody>', null, null],
+
+ ['Clearing stack back to a table body context. Test </thead> in <tbody>',
+ doc, 'tbody', '</thead>', null, null],
+
+ ['Clearing stack back to a table body context. Test </thead> in <tfoot>',
+ doc, 'tfoot', '</thead>', null, null],
+
+ ['Clearing stack back to a table body context. Test </tfoot> in <thead>',
+ doc, 'thead', '</tfoot>', null, null],
+
+ ['Clearing stack back to a table body context. Test </tfoot> in <tbody>',
+ doc, 'tbody', '</tfoot>', null, null]
+];
+
+generate_tests(doTest, parameters, 'Clearing stack back to a table body context.');
+
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/template/clearing-the-stack-back-to-a-given-context/clearing-stack-back-to-a-table-context.html b/tests/wpt/web-platform-tests/html/syntax/parsing/template/clearing-the-stack-back-to-a-given-context/clearing-stack-back-to-a-table-context.html
new file mode 100644
index 00000000000..7c6a609ed7e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/template/clearing-the-stack-back-to-a-given-context/clearing-stack-back-to-a-table-context.html
@@ -0,0 +1,85 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>HTML Templates: Clearing stack back to a table context</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="assert" content="Clearing the stack back to a table context must be aborted if the current node is template">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#clearing-the-stack">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src='../../testcommon.js'></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script type="text/javascript">
+
+function doTest(doc, templateInnerHTML, id, tagName, bodiesNum, footerIsNull,
+ headerIsNull) {
+
+ doc.body.innerHTML = '' +
+ '<table id="tbl">' +
+ '<template id="tmpl1">' +
+ // When parser meets <caption>, <colgroup>, <tbody>, <tfoot>, <thead>, <col>
+ // stack must be cleared back to table context.
+ //But <template> tag should abort this process
+ templateInnerHTML +
+ '</template>' +
+ '<tr id="tr">' +
+ '<td id="td">' +
+ '</td>' +
+ '</tr>' +
+ '</table>';
+
+ var table = doc.querySelector('#tbl');
+ var tr = doc.querySelector('#tr');
+ var td = doc.querySelector('#td');
+ var template = doc.querySelector('#tmpl1');
+
+ assert_equals(table.rows.length, 1, 'Wrong number of table rows');
+ assert_equals(table.rows[0].cells.length, 1, 'Wrong number of table cells');
+ assert_equals(template.parentNode, table, 'Wrong template parent');
+ assert_not_equals(template.content.querySelector('#' + id), null,
+ 'Element should present in the template content');
+ assert_equals(doc.querySelector('#tbl').caption, null, 'Table should have no caption');
+ assert_equals(template.content.querySelector('#' + id).tagName, tagName,
+ 'Wrong element in the template content');
+ if (bodiesNum) {
+ assert_equals(table.tBodies.length, bodiesNum, 'Table should have '
+ + bodiesNum + ' body');
+ }
+ if (footerIsNull) {
+ assert_equals(table.tFoot, null, 'Table should have no footer');
+ }
+ if (headerIsNull) {
+ assert_equals(table.tHead, null, 'Table should have no header');
+ }
+}
+
+
+var doc = newHTMLDocument();
+var parameters = [
+ ['Clearing stack back to a table context. Test <caption>',
+ doc, '<caption id="caption1">Table caption</caption>', 'caption1', 'CAPTION'],
+
+ ['Clearing stack back to a table context. Test <colgroup>',
+ doc, '<colgroup id="colgroup1" width="100%"/>', 'colgroup1', 'COLGROUP'],
+
+ ['Clearing stack back to a table context. Test <tbody>',
+ doc, '<tbody id="tbody1"></tbody>', 'tbody1', 'TBODY', 1],
+
+ ['Clearing stack back to a table context. Test <tfoot>',
+ doc, '<tfoot id="tfoot1"></tfoot>', 'tfoot1', 'TFOOT', null, true],
+
+ ['Clearing stack back to a table context. Test <thead>',
+ doc, '<thead id="thead1"></thead>', 'thead1', 'THEAD', null, false, true],
+
+ ['Clearing stack back to a table context. Test <col>',
+ doc, '<col id="col1" width="100%"/>', 'col1', 'COL']
+];
+
+generate_tests(doTest, parameters, 'Clearing stack back to a table body context.');
+
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/template/clearing-the-stack-back-to-a-given-context/clearing-stack-back-to-a-table-row-context.html b/tests/wpt/web-platform-tests/html/syntax/parsing/template/clearing-the-stack-back-to-a-given-context/clearing-stack-back-to-a-table-row-context.html
new file mode 100644
index 00000000000..7525e0b11c9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/template/clearing-the-stack-back-to-a-given-context/clearing-stack-back-to-a-table-row-context.html
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>HTML Templates: Clearing stack back to a table row context</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="assert" content="Clearing the stack back to a table row context must be aborted if the current node is template">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#clearing-the-stack">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src='../../testcommon.js'></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script type="text/javascript">
+
+function doTest(doc, templateInnerHTML, id, tagName, elementId) {
+
+ doc.body.innerHTML = '' +
+ '<table id="tbl">' +
+ '<tr id="tr">' +
+ '<template id="tmpl1">' +
+ // When parser meets <th>, <td>, </tr>, stack must be cleared
+ // back to table row context.
+ // But <template> tag should abort this
+ templateInnerHTML +
+ '</template>' +
+ '<td id="td">' +
+ '</td>' +
+ '</tr>' +
+ '</table>';
+
+ var table = doc.querySelector('#tbl');
+ var tr = doc.querySelector('#tr');
+ var td = doc.querySelector('#td');
+ var template = doc.querySelector('#tmpl1');
+
+ assert_equals(table.rows.length, 1, 'Wrong number of table rows');
+ assert_equals(table.rows[0].cells.length, 1, 'Wrong number of table cells');
+ assert_equals(template.parentNode, tr, 'Wrong template parent');
+ if (id !== null) {
+ assert_not_equals(template.content.querySelector('#' + id), null,
+ 'Element should present in the template content');
+ }
+ if (tagName !== null) {
+ assert_equals(template.content.querySelector('#' + id).tagName, tagName,
+ 'Wrong element in the template content');
+ }
+ if (elementId) {
+ assert_equals(doc.querySelector('#' + elementId), null,
+ 'Table should have no element with ID ' + elementId);
+ }
+}
+
+
+var doc = newHTMLDocument();
+var parameters = [
+ ['Clearing stack back to a table row context. Test <th>',
+ doc, '<th id="th1">Table header</th>', 'th1', 'TH', 'th1'],
+
+ ['Clearing stack back to a table row context. Test <td>',
+ doc, '<td id="td1">Table cell</td>', 'td1', 'TD', 'td1'],
+
+ ['Clearing stack back to a table row context. Test </tr>',
+ doc, '</tr>', null, null]
+];
+
+generate_tests(doTest, parameters, 'Clearing stack back to a table body context.');
+
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/template/creating-an-element-for-the-token/template-owner-document.html b/tests/wpt/web-platform-tests/html/syntax/parsing/template/creating-an-element-for-the-token/template-owner-document.html
new file mode 100644
index 00000000000..c7a65483148
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/template/creating-an-element-for-the-token/template-owner-document.html
@@ -0,0 +1,242 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>HTML Templates: ownerDocument property of the element in template</title>
+<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<meta name="assert" content="ownerDocument property of the element appended to template must be set to the template contents owner of the ownerDocument of the template element">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#creating-an-element-for-a-token">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src='../../testcommon.js'></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script type="text/javascript">
+
+
+test(function () {
+ var doc = newHTMLDocument();
+ doc.body.innerHTML = '<div><template id="tmpl1"><div id="div">DIV</div></template></div>';
+
+ var template = doc.querySelector('#tmpl1');
+
+ var div = template.content.querySelector('#div');
+
+ assert_equals(div.ownerDocument, template.content.ownerDocument,
+ 'Wrong ownerDocument of the element in template');
+
+}, 'Test ownerDocument property of the element in a template. '
+ + 'Current DOCUMENT has no browsing context. Test template element inside the div');
+
+
+
+test(function () {
+ var doc = newHTMLDocument();
+ doc.body.innerHTML = '<template id="tmpl1"><div id="div">DIV</div></template>';
+
+ var template = doc.querySelector('#tmpl1');
+
+ var div = template.content.querySelector('#div');
+
+ assert_equals(div.ownerDocument, template.content.ownerDocument,
+ 'Wrong ownerDocument of the element in template');
+
+}, 'Test ownerDocument property of the element in a template. '
+ + 'Current DOCUMENT has no browsing context. Test template element '
+ + 'in the root of the body');
+
+
+
+test(function () {
+ var doc = newHTMLDocument();
+ doc.head.innerHTML = '<template id="tmpl1"><div id="div">DIV</div></template>';
+
+ var template = doc.querySelector('#tmpl1');
+
+ var div = template.content.querySelector('#div');
+
+ assert_equals(div.ownerDocument, template.content.ownerDocument,
+ 'Wrong ownerDocument of the element in template');
+
+}, 'Test ownerDocument property of the element in a template. '
+ + 'Current DOCUMENT has no browsing context. Test template element '
+ + 'in the root of the head');
+
+
+
+test(function () {
+ var doc = newHTMLDocument();
+
+ doc.open();
+ doc.write('<frameset><template id="tmpl1"><div id="div">DIV</div></template></frameset>');
+ doc.close();
+
+ var template = doc.querySelector('#tmpl1');
+
+ var div = template.content.querySelector('#div');
+
+ assert_equals(div.ownerDocument, template.content.ownerDocument,
+ 'Wrong ownerDocument of the element in template');
+
+}, 'Test ownerDocument property of the element in a template. '
+ + 'Current DOCUMENT has no browsing context. Test template element '
+ + 'in the root of the frameset');
+
+
+
+test(function () {
+ var doc = newHTMLDocument();
+ doc.body.innerHTML = '<template id="tmpl1">'
+ + '<template id="tmpl2"><div id="div">DIV</div></template></template>';
+
+ var template = doc.querySelector('#tmpl1');
+
+ var nestedTemplate = template.content.querySelector('#tmpl2');
+
+ assert_equals(nestedTemplate.ownerDocument, template.content.ownerDocument,
+ 'Wrong nested template owner document');
+
+ var div = nestedTemplate.content.querySelector('#div');
+
+ assert_equals(div.ownerDocument, nestedTemplate.content.ownerDocument,
+ 'Wrong div ownerDocument');
+
+}, 'Test ownerDocument property of the element in a nested template');
+
+
+
+testInIFrame('../../resources/template-contents.html', function(context) {
+ var doc = context.iframes[0].contentDocument;
+
+ var template = doc.querySelector('template');
+
+ var div = template.content.querySelector('div');
+
+ assert_equals(div.ownerDocument, template.content.ownerDocument,
+ 'Wrong ownerDocument of the element in template');
+
+}, 'Test ownerDocument property of the element in a template. '
+ + 'Load HTML document from a file, current DOCUMENT has browsing context');
+
+
+
+testInIFrame('../../resources/template-contents-nested.html', function(context) {
+ var doc = context.iframes[0].contentDocument;
+
+ var template = doc.querySelector('template');
+
+ var nestedTemplate = template.content.querySelector('template');
+
+ assert_equals(nestedTemplate.ownerDocument, template.content.ownerDocument,
+ 'Wrong nested template owner document');
+
+ var div = nestedTemplate.content.querySelector('div');
+
+ assert_equals(div.ownerDocument, nestedTemplate.content.ownerDocument,
+ 'Wrong div ownerDocument');
+
+}, 'Test ownerDocument property of the element in a nested template. '
+ + 'Load HTML document from a file, current DOCUMENT has browsing context');
+
+
+
+testInIFrame('../../resources/two-templates.html', function(context) {
+ var doc = context.iframes[0].contentDocument;
+
+ var template1 = doc.querySelector('#template1');
+ var div1 = template1.content.querySelector('div');
+ var template2 = doc.querySelector('#template2');
+ var div2 = template2.content.querySelector('div');
+
+ assert_equals(div1.ownerDocument, template1.content.ownerDocument,
+ 'Wrong ownerDocument of the element in template');
+ assert_equals(div2.ownerDocument, template2.content.ownerDocument,
+ 'Wrong ownerDocument of the element in template');
+ assert_equals(div1.ownerDocument, div2.ownerDocument,
+ 'Different elements in the same document should share the same template contents owner');
+
+}, 'Test ownerDocument property of two elements in a template. '
+ + 'Load HTML document from a file, current DOCUMENT has browsing context');
+
+
+var parameters = [];
+
+HTML5_ELEMENTS.forEach(function(value) {
+ if (value !== 'body' && value !== 'html' && value !== 'head' && value !== 'frameset') {
+
+ var doc = newHTMLDocument();
+
+ if (isVoidElement(value)) {
+ doc.body.innerHTML = '<template><' + value + '/></template>';
+ } else {
+ doc.body.innerHTML = '<template><' + value + '></' + value + '></template>';
+ }
+
+ var template = doc.querySelector('template');
+ var element = template.content.querySelector(value);
+
+ doc.body.appendChild(template);
+
+ parameters.push([
+ 'Test ownerDocument for the element ' + value + ' in the template',
+ element,
+ template
+ ]);
+ }
+});
+
+function compare_owners(element, template) {
+ assert_equals(element.ownerDocument, template.content.ownerDocument)
+}
+
+generate_tests(compare_owners, parameters,
+ 'Test ownerDocument property of all HTML5 elements in a template. '
+ + 'Current DOCUMENT has no browsing context.');
+
+var context = newContext();
+parameters = [];
+
+try {
+
+ HTML5_ELEMENTS.forEach(function(value) {
+
+ if (value !== 'body' && value !== 'html' && value !== 'head' && value !== 'frameset') {
+
+ var doc = newRenderedHTMLDocument(context);
+
+ if (isVoidElement(value)) {
+ doc.body.innerHTML = '<template><' + value + '/></template>';
+ } else {
+ doc.body.innerHTML = '<template><' + value + '></' + value + '></template>';
+ }
+
+ var template = doc.querySelector('template');
+ var element = template.content.querySelector(value);
+
+ doc.body.appendChild(template);
+
+ parameters.push([
+ 'Test ownerDocument for the element ' + value + ' in the template. '
+ + 'Document has browsing context',
+ element,
+ template
+ ]);
+ }
+ });
+ generate_tests(compare_owners, parameters,
+ 'Test ownerDocument property of all HTML5 elements in a template. '
+ + 'Current DOCUMENT has browsing context.');
+
+} finally {
+ try {
+ cleanContext(context);
+ } catch (e) {
+ //do nothing
+ }
+}
+
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/test.js b/tests/wpt/web-platform-tests/html/syntax/parsing/test.js
new file mode 100644
index 00000000000..876f8b6821a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/test.js
@@ -0,0 +1,326 @@
+var namespaces = {
+ "html":"http://www.w3.org/1999/xhtml",
+ "mathml":"http://www.w3.org/1998/Math/MathML",
+ "svg":"http://www.w3.org/2000/svg",
+ "xlink":"http://www.w3.org/1999/xlink",
+ "xml":"http://www.w3.org/XML/1998/namespace",
+ "xmlns":"http://www.w3.org/2000/xmlns/"
+};
+
+var prefixes = {};
+for (var prefix in namespaces) {
+ if (namespaces.hasOwnProperty(prefix)) {
+ prefixes[namespaces[prefix]] = prefix;
+ }
+}
+prefixes[namespaces["mathml"]] = "math";
+
+function format(format_string) {
+ var insertions = Array.prototype.slice.call(arguments, 1);
+ var regexp = /%s/g;
+ var match_count = 0;
+ var rv = format_string.replace(regexp, function(match) {
+ var rv = insertions[match_count];
+ match_count++;
+ return rv;
+ });
+ return rv;
+}
+
+function test_serializer(element) {
+ element.normalize();
+ var lines = [];
+ function serialize_element(element, indent) {
+ var indent_spaces = (new Array(indent)).join(" ");
+ switch(element.nodeType) {
+ case Node.DOCUMENT_TYPE_NODE:
+ if (element.name) {
+ if (element.publicId || element.systemId) {
+ var publicId = element.publicId ? element.publicId : "";
+ var systemId = element.systemId ? element.systemId : "";
+ lines.push(format("|%s<!DOCTYPE %s \"%s\" \"%s\">", indent_spaces,
+ element.name, publicId, systemId));
+ } else {
+ lines.push(format("|%s<!DOCTYPE %s>", indent_spaces,
+ element.name));
+ }
+ } else {
+ lines.push(format("|%s<!DOCTYPE >", indent_spaces));
+ }
+ break;
+ case Node.DOCUMENT_NODE:
+ lines.push("#document");
+ break;
+ case Node.DOCUMENT_FRAGMENT_NODE:
+ lines.push("#document-fragment");
+ break;
+ case Node.COMMENT_NODE:
+ lines.push(format("|%s<!-- %s -->", indent_spaces, element.nodeValue));
+ break;
+ case Node.TEXT_NODE:
+ lines.push(format("|%s\"%s\"", indent_spaces, element.nodeValue));
+ break;
+ case Node.ELEMENT_NODE:
+ if (element.getAttribute("data-skip") !== null) {
+ return;
+ }
+ if (element.namespaceURI !== null && element.namespaceURI !== namespaces.html) {
+ var name = format("%s %s", prefixes[element.namespaceURI],
+ element.localName);
+ } else {
+ var name = element.localName;
+ }
+ lines.push(format("|%s<%s>", indent_spaces, name));
+
+ var attributes = Array.prototype.map.call(
+ element.attributes,
+ function(attr) {
+ var name = (attr.namespaceURI ? prefixes[attr.namespaceURI] + " " : "") +
+ attr.localName;
+ return [name, attr.value];
+ });
+ attributes.sort(function (a, b) {
+ var x = a[0];
+ var y = b[0];
+ if (x === y) {
+ return 0;
+ }
+ return x > y ? 1 : -1;
+ });
+
+ attributes.forEach(
+ function(attr) {
+ var indent_spaces = (new Array(indent + 2)).join(" ");
+ lines.push(format("|%s%s=\"%s\"", indent_spaces, attr[0], attr[1]));
+ }
+ );
+ break;
+ }
+ indent += 2;
+ Array.prototype.forEach.call(element.childNodes,
+ function(node) {
+ serialize_element(node, indent);
+ });
+ }
+ serialize_element(element, 0);
+ return lines.join("\n");
+}
+
+function parse_query() {
+ var query = location.search.slice(1);
+ var vars = query.split("&");
+ var fields = vars.map(function (x) {
+ var split = x.split("=");
+ return [split[0], split.slice(1).join("=")];
+ });
+ return fields;
+}
+
+function get_type() {
+ var run_type = "uri";
+ var fields = parse_query();
+ fields.forEach(function(x) {
+ if(x[0] == "run_type") {
+ run_type = x[1];
+ }
+ });
+ return run_type;
+};
+
+var test_in_data_uri = get_test_func(function (iframe, uri_encoded_input) {
+ iframe.src = "data:text/html;charset=utf8," + uri_encoded_input;
+ });
+
+var test_document_write = get_test_func(function(iframe, uri_encoded_input) {
+ iframe.contentDocument.open();
+ var input = decodeURIComponent(uri_encoded_input);
+ iframe.contentDocument.write(input);
+ iframe.contentDocument.close();
+ });
+
+var test_document_write_single = get_test_func(function(iframe, uri_encoded_input) {
+ iframe.contentDocument.open();
+ var input = decodeURIComponent(uri_encoded_input);
+ for (var i=0; i< input.length; i++) {
+ iframe.contentDocument.write(input[i]);
+ }
+ iframe.contentDocument.close();
+ });
+
+function get_test_func(inject_func) {
+ function test_func(iframe, t, test_id, uri_encoded_input, escaped_expected) {
+ var expected = decodeURIComponent(escaped_expected);
+ current_tests[iframe.id] = {test_id:test_id,
+ uri_encoded_input:uri_encoded_input,
+ expected:expected,
+ actual:null
+ };
+
+ iframe.onload = function() {
+ t.step(function() {
+ iframe.onload = null;
+ var serialized_dom = test_serializer(iframe.contentDocument);
+ current_tests[iframe.id].actual = serialized_dom;
+ assert_equals(serialized_dom, expected);
+ t.done();
+ }
+ );
+ };
+ inject_func(iframe, uri_encoded_input);
+ }
+ return test_func;
+}
+
+function test_fragment(iframe, t, test_id, uri_encoded_input, escaped_expected, container) {
+ var input_string = decodeURIComponent(uri_encoded_input);
+ var expected = decodeURIComponent(escaped_expected);
+ current_tests[iframe.id] = {
+ test_id:test_id,
+ input:uri_encoded_input,
+ expected:expected,
+ actual:null,
+ container:container
+ };
+
+ var components = container.split(" ");
+ var container_elem = null;
+ if (components.length > 1) {
+ var namespace = namespaces[components[0]];
+ container_elem = document.createElementNS(namespace,
+ components[0] + ":" +
+ components[1]);
+ } else {
+ container_elem = document.createElement(container);
+ }
+ container_elem.innerHTML = input_string;
+ var serialized_dom = test_serializer(container_elem);
+ current_tests[iframe.id].actual = serialized_dom;
+ serialized_dom = convert_innerHTML(serialized_dom);
+ assert_equals(serialized_dom, expected);
+ t.done();
+}
+
+function convert_innerHTML(serialized_dom) {
+ var lines = serialized_dom.split("\n");
+ lines[0] = "#document";
+ return lines.join("\n");
+}
+
+function print_diffs(test_id, uri_encoded_input, expected, actual, container) {
+ container = container ? container : null;
+ if (actual) {
+ var diffs = mark_diffs(expected, actual);
+ var expected_text = diffs[0];
+ var actual_text = diffs[1];
+ } else {
+ var expected_text = expected;
+ var actual_text = "";
+ }
+
+ var tmpl = ["div", {"id":"${test_id}"},
+ ["h2", {}, "${test_id}"],
+ function(vars) {
+ if (vars.container !== null) {
+ return ["div", {"class":"container"},
+ ["h3", {}, "innerHTML Container"],
+ ["pre", {}, vars.container]];
+ } else {
+ return null;
+ }
+ },
+ ["div", {"id":"input_${test_id}"}, ["h3", {}, "Input"], ["pre", {},
+ ["code", {}, decodeURIComponent(uri_encoded_input)]]],
+ ["div", {"id":"expected_${test_id}"}, ["h3", {}, "Expected"],
+ ["pre", {}, ["code", {}, expected_text]]],
+ ["div", {"id":"actual_${test_id}"}, ["h3", {}, "Actual"],
+ ["pre", {}, ["code", {}, actual_text]]]
+ ];
+
+ var diff_dom = template.render(tmpl, {test_id:test_id, container:container});
+ document.body.appendChild(diff_dom);
+}
+
+var current_tests = {};
+var iframe_map = {};
+
+function init_tests(test_type) {
+ var test_func = null;
+ var test_funcs = {
+ "write":test_document_write,
+ "write_single":test_document_write_single,
+ "uri":test_in_data_uri,
+ "innerHTML":test_fragment
+ };
+ var tests_started = 0;
+ var tests_complete = 0;
+
+ setup(function() {
+ test_func = test_funcs[test_type];
+
+ var fails = [];
+
+ add_result_callback(function(test) {
+ tests_complete++;
+ var iframe = document.getElementById(iframe_map[test.name]);
+ if (test.status !== test.PASS) {
+ fails.push(current_tests[iframe.id]);
+ var new_iframe = document.createElement("iframe");
+ new_iframe.style.display = "none";
+ new_iframe.id = iframe.id;
+ document.body.replaceChild(new_iframe, iframe);
+ iframe = new_iframe;
+ }
+ if (tests_complete === order.length) {
+ done();
+ } else if (tests_started < order.length) {
+ test_next(iframe);
+ }
+ });
+
+ add_completion_callback(function() {
+ fails.forEach(function(t) {
+ print_diffs(t.test_id, t.uri_encoded_input,
+ t.expected, t.actual);
+ });
+ });
+
+ //Create the iframes we will use to test
+ //in the innerHTML case these are not actually used
+ //but it is convenient to reuse the same code
+ for (var i=0; i<num_iframes; i++) {
+ var iframe = document.createElement("iframe");
+ iframe.id = "iframe_" + i;
+ iframe.style.display = "none";
+ document.body.appendChild(iframe);
+ }
+ },
+ {explicit_done:true});
+
+ function test_next(iframe) {
+ var test_id = order[tests_started];
+ tests_started++;
+ var x = tests[test_id];
+ var t = x[0];
+ iframe_map[t.name] = iframe.id;
+ setTimeout(function() {
+ t.step(function() {
+ var string_uri_encoded_input = x[1];
+ var string_escaped_expected = x[2];
+ if (test_type === "innerHTML") {
+ var container = x[3];
+ }
+ test_func(iframe, t, test_id, string_uri_encoded_input, string_escaped_expected,
+ container);
+ });
+ }, 0);
+ }
+
+ onload = function() {
+ Array.prototype.forEach.call(document.getElementsByTagName("iframe"),
+ function(iframe) {
+ if (tests_started<order.length) {
+ test_next(iframe);
+ }
+ });
+ };
+}
diff --git a/tests/wpt/web-platform-tests/html/syntax/parsing/the-end.html b/tests/wpt/web-platform-tests/html/syntax/parsing/the-end.html
new file mode 100644
index 00000000000..0a7babf0b5d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/parsing/the-end.html
@@ -0,0 +1,40 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>The end</title>
+<link rel=help href="https://html.spec.whatwg.org/multipage/#the-end">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+ document.addEventListener("DOMContentLoaded", this.step_func_done(function(e) {
+ assert_equals(e.type, "DOMContentLoaded");
+ assert_true(e.bubbles, "bubbles should be true");
+ assert_false(e.cancelable, "cancelable should be false");
+ assert_equals(e.target, document, "target should be document");
+ assert_true(e.isTrusted, "isTrusted should be true");
+ assert_class_string(e, "Event");
+ }));
+}, "DOMContentLoaded");
+
+async_test(function() {
+ window.addEventListener("load", this.step_func_done(function(e) {
+ assert_equals(e.type, "load");
+ assert_false(e.bubbles, "bubbles should be false");
+ assert_false(e.cancelable, "cancelable should be false");
+ assert_equals(e.target, document, "target should be document");
+ assert_true(e.isTrusted, "isTrusted should be true");
+ assert_class_string(e, "Event");
+ }));
+}, "load");
+
+async_test(function() {
+ var seen = false;
+ document.addEventListener("DOMContentLoaded", this.step_func(function() {
+ seen = true;
+ }));
+ window.addEventListener("load", this.step_func_done(function() {
+ assert_true(seen, "DOMContentLoaded should be fired before load");
+ }));
+}, "order");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/syntax/serializing-html-fragments/.gitkeep b/tests/wpt/web-platform-tests/html/syntax/serializing-html-fragments/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/serializing-html-fragments/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/syntax/serializing-html-fragments/outerHTML.html b/tests/wpt/web-platform-tests/html/syntax/serializing-html-fragments/outerHTML.html
new file mode 100644
index 00000000000..b60347a1067
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/serializing-html-fragments/outerHTML.html
@@ -0,0 +1,171 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>HTML Test: element.outerHTML to verify HTML fragment serialization algorithm</title>
+ <link rel="author" title="Intel" href="http://www.intel.com/">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#html-fragment-serialization-algorithm">
+ <link rel="help" href="https://dvcs.w3.org/hg/innerhtml/raw-file/tip/index.html#widl-Element-outerHTML">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var element = [
+ "a",
+ "abbr",
+ "address",
+ "article",
+ "aside",
+ "audio",
+ "b",
+ "bdi",
+ "bdo",
+ "blockquote",
+ "body",
+ "button",
+ "canvas",
+ "caption",
+ "cite",
+ "code",
+ "colgroup",
+ "command",
+ "datalist",
+ "dd",
+ "del",
+ "details",
+ "dfn",
+ "dialog",
+ "div",
+ "dl",
+ "dt",
+ "em",
+ "fieldset",
+ "figcaption",
+ "figure",
+ "footer",
+ "form",
+ "h1",
+ "h2",
+ "h3",
+ "h4",
+ "h5",
+ "h6",
+ "head",
+ "header",
+ "hgroup",
+ "html",
+ "i",
+ "iframe",
+ "ins",
+ "kbd",
+ "label",
+ "legend",
+ "li",
+ "map",
+ "mark",
+ "menu",
+ "meter",
+ "nav",
+ "noscript",
+ "object",
+ "ol",
+ "optgroup",
+ "option",
+ "output",
+ "p",
+ "pre",
+ "progress",
+ "q",
+ "rp",
+ "rt",
+ "ruby",
+ "s",
+ "samp",
+ "script",
+ "section",
+ "select",
+ "small",
+ "span",
+ "strong",
+ "style",
+ "sub",
+ "summary",
+ "sup",
+ "table",
+ "tbody",
+ "td",
+ "textarea",
+ "tfoot",
+ "th",
+ "thead",
+ "time",
+ "title",
+ "tr",
+ "u",
+ "ul",
+ "var",
+ "video",
+ "data",
+ //"acronym",
+ //"applet",
+ //"basefont",
+ //"bgsound",
+ //"big",
+ //"blink",
+ //"center",
+ //"dir",
+ //"font",
+ //"frame",
+ //"frameset",
+ //"isindex",
+ //"listing",
+ //"marquee",
+ //"multicol",
+ //"nextid",
+ //"nobr",
+ //"noembed",
+ //"noframes",
+ //"plaintext",
+ //"rb",
+ //"spacer",
+ //"strike",
+ //"tt",
+ //"xmp",
+ ];
+
+ var noEndTag = [
+ "area",
+ "base",
+ "br",
+ "col",
+ "embed",
+ "hr",
+ "img",
+ "input",
+ "keygen",
+ "link",
+ "meta",
+ "param",
+ "source",
+ "track",
+ "wbr",
+ ];
+
+ test(function() {
+ element.forEach(function(ele) {
+ test(function() {
+ var e = document.createElement(ele);
+ assert_equals(e.outerHTML, "<" + ele + "></" + ele + ">", ele + " node created." );
+ }, "Node for " + ele);
+ });
+ noEndTag.forEach(function(ele) {
+ test(function() {
+ var e = document.createElement(ele);
+ assert_equals(e.outerHTML, "<" + ele + ">", ele + " node created." );
+ }, "Node for " + ele);
+ });
+ }, document.title);
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/writing/.gitkeep b/tests/wpt/web-platform-tests/html/syntax/writing/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/writing/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/syntax/writing/cdata-sections/.gitkeep b/tests/wpt/web-platform-tests/html/syntax/writing/cdata-sections/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/writing/cdata-sections/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/syntax/writing/character-references/.gitkeep b/tests/wpt/web-platform-tests/html/syntax/writing/character-references/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/writing/character-references/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/syntax/writing/comments/.gitkeep b/tests/wpt/web-platform-tests/html/syntax/writing/comments/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/writing/comments/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/syntax/writing/elements-0/.gitkeep b/tests/wpt/web-platform-tests/html/syntax/writing/elements-0/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/writing/elements-0/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/syntax/writing/elements-0/contains.json b/tests/wpt/web-platform-tests/html/syntax/writing/elements-0/contains.json
new file mode 100644
index 00000000000..39711a0a213
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/writing/elements-0/contains.json
@@ -0,0 +1,26 @@
+[
+ {
+ "id": "start-tags",
+ "original_id": "start-tags"
+ },
+ {
+ "id": "end-tags",
+ "original_id": "end-tags"
+ },
+ {
+ "id": "attributes-0",
+ "original_id": "attributes-0"
+ },
+ {
+ "id": "optional-tags",
+ "original_id": "optional-tags"
+ },
+ {
+ "id": "element-restrictions",
+ "original_id": "element-restrictions"
+ },
+ {
+ "id": "cdata-rcdata-restrictions",
+ "original_id": "cdata-rcdata-restrictions"
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/writing/text/.gitkeep b/tests/wpt/web-platform-tests/html/syntax/writing/text/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/writing/text/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/syntax/writing/text/contains.json b/tests/wpt/web-platform-tests/html/syntax/writing/text/contains.json
new file mode 100644
index 00000000000..870ff58a342
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/writing/text/contains.json
@@ -0,0 +1,6 @@
+[
+ {
+ "id": "newlines",
+ "original_id": "newlines"
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/syntax/writing/the-doctype/.gitkeep b/tests/wpt/web-platform-tests/html/syntax/writing/the-doctype/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/syntax/writing/the-doctype/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/the-xhtml-syntax/.gitkeep b/tests/wpt/web-platform-tests/html/the-xhtml-syntax/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/the-xhtml-syntax/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/the-xhtml-syntax/parsing-xhtml-documents/.gitkeep b/tests/wpt/web-platform-tests/html/the-xhtml-syntax/parsing-xhtml-documents/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/the-xhtml-syntax/parsing-xhtml-documents/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/the-xhtml-syntax/parsing-xhtml-fragments/.gitkeep b/tests/wpt/web-platform-tests/html/the-xhtml-syntax/parsing-xhtml-fragments/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/the-xhtml-syntax/parsing-xhtml-fragments/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/the-xhtml-syntax/serializing-xhtml-fragments/.gitkeep b/tests/wpt/web-platform-tests/html/the-xhtml-syntax/serializing-xhtml-fragments/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/the-xhtml-syntax/serializing-xhtml-fragments/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/the-xhtml-syntax/writing-xhtml-documents/.gitkeep b/tests/wpt/web-platform-tests/html/the-xhtml-syntax/writing-xhtml-documents/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/the-xhtml-syntax/writing-xhtml-documents/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/tools/html5lib_test.xml b/tests/wpt/web-platform-tests/html/tools/html5lib_test.xml
new file mode 100644
index 00000000000..8af4adce16b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/tools/html5lib_test.xml
@@ -0,0 +1,29 @@
+<html xmlns:py="http://genshi.edgewall.org/">
+ <head>
+ <meta charset="utf8"/>
+ <title>HTML 5 Parser tests ${file_name}</title>
+ <meta name="timeout" content="long"/>
+ <meta name="variant" content="?run_type=uri"/>
+ <meta name="variant" content="?run_type=write"/>
+ <meta name="variant" content="?run_type=write_single"/>
+ </head>
+ <body>
+ <h1>html5lib Parser Test</h1>
+ <div id="log"></div>
+ <script src="common.js"></script>
+ <script src="test.js"></script>
+ <script src="template.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ var num_iframes = 8;
+
+ var order = [<py:for each="test in tests">'${test.id}',</py:for>];
+ var tests = {
+ <py:for each="test in tests">"${test.id}":[async_test('${file_name} ${test.id}'), ${test.string_uri_encoded_input}, ${test.string_escaped_expected}],</py:for>
+ }
+ init_tests(get_type());
+ </script>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/tools/html5lib_test_fragment.xml b/tests/wpt/web-platform-tests/html/tools/html5lib_test_fragment.xml
new file mode 100644
index 00000000000..5be259b7490
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/tools/html5lib_test_fragment.xml
@@ -0,0 +1,27 @@
+<html xmlns:py="http://genshi.edgewall.org/">
+ <head>
+ <meta charset="utf8"/>
+ <title>HTML 5 Parser tests ${file_name}</title>
+ <meta name="timeout" content="long"/>
+ </head>
+ <body>
+ <h1>html5lib Parser Test</h1>
+ <div id="log"></div>
+ <script src="common.js"></script>
+ <script src="test.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+
+ var num_iframes = 8;
+
+ var order = [<py:for each="test in tests">'${test.id}',</py:for>];
+ var tests = {
+ <py:for each="test in tests">"${test.id}":[async_test('${file_name} ${test.id}'), ${test.string_uri_encoded_input}, ${test.string_escaped_expected}, '${test.container}'],</py:for>
+ }
+
+ init_tests("innerHTML");
+
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/tools/update_html5lib_tests.py b/tests/wpt/web-platform-tests/html/tools/update_html5lib_tests.py
new file mode 100644
index 00000000000..ae08e82d3e4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/tools/update_html5lib_tests.py
@@ -0,0 +1,152 @@
+import sys
+import os
+import hashlib
+import urllib
+import itertools
+import re
+import json
+import glob
+import shutil
+
+try:
+ import genshi
+ from genshi.template import MarkupTemplate
+
+ from html5lib.tests import support
+except ImportError:
+ print """This script requires the Genshi templating library and html5lib source
+
+It is recommended that these are installed in a virtualenv:
+
+virtualenv venv
+source venv/bin/activate
+pip install genshi
+cd venv
+git clone git@github.com:html5lib/html5lib-python.git html5lib
+cd html5lib
+git submodule init
+git submodule update
+pip install -e ./
+
+Then run this script again, with the virtual environment still active.
+When you are done, type "deactivate" to deactivate the virtual environment.
+"""
+
+TESTS_PATH = "html/syntax/parsing/"
+
+def get_paths():
+ script_path = os.path.split(os.path.abspath(__file__))[0]
+ repo_base = get_repo_base(script_path)
+ tests_path = os.path.join(repo_base, TESTS_PATH)
+ return script_path, tests_path
+
+def get_repo_base(path):
+ while path:
+ if os.path.exists(os.path.join(path, ".git")):
+ return path
+ else:
+ path = os.path.split(path)[0]
+
+def get_expected(data):
+ data = "#document\n" + data
+ return data
+
+def get_hash(data, container=None):
+ if container == None:
+ container = ""
+ return hashlib.sha1("#container%s#data%s"%(container.encode("utf8"),
+ data.encode("utf8"))).hexdigest()
+
+def make_tests(script_dir, out_dir, input_file_name, test_data):
+ tests = []
+ innerHTML_tests = []
+ ids_seen = {}
+ print input_file_name
+ for test in test_data:
+ if "script-off" in test:
+ continue
+ is_innerHTML = "document-fragment" in test
+ data = test["data"]
+ container = test["document-fragment"] if is_innerHTML else None
+ assert test["document"], test
+ expected = get_expected(test["document"])
+ test_list = innerHTML_tests if is_innerHTML else tests
+ test_id = get_hash(data, container)
+ if test_id in ids_seen:
+ print "WARNING: id %s seen multiple times in file %s this time for test (%s, %s) before for test %s, skipping"%(test_id, input_file_name, container, data, ids_seen[test_id])
+ continue
+ ids_seen[test_id] = (container, data)
+ test_list.append({'string_uri_encoded_input':"\"%s\""%urllib.quote(data.encode("utf8")),
+ 'input':data,
+ 'expected':expected,
+ 'string_escaped_expected':json.dumps(urllib.quote(expected.encode("utf8"))),
+ 'id':test_id,
+ 'container':container
+ })
+ path_normal = None
+ if tests:
+ path_normal = write_test_file(script_dir, out_dir,
+ tests, "html5lib_%s"%input_file_name,
+ "html5lib_test.xml")
+ path_innerHTML = None
+ if innerHTML_tests:
+ path_innerHTML = write_test_file(script_dir, out_dir,
+ innerHTML_tests, "html5lib_innerHTML_%s"%input_file_name,
+ "html5lib_test_fragment.xml")
+
+ return path_normal, path_innerHTML
+
+def write_test_file(script_dir, out_dir, tests, file_name, template_file_name):
+ file_name = os.path.join(out_dir, file_name + ".html")
+ short_name = os.path.split(file_name)[1]
+
+ with open(os.path.join(script_dir, template_file_name)) as f:
+ template = MarkupTemplate(f)
+
+ stream = template.generate(file_name=short_name, tests=tests)
+
+ with open(file_name, "w") as f:
+ f.write(stream.render('html', doctype='html5',
+ encoding="utf8"))
+ return file_name
+
+def escape_js_string(in_data):
+ return in_data.encode("utf8").encode("string-escape")
+
+def serialize_filenames(test_filenames):
+ return "[" + ",\n".join("\"%s\""%item for item in test_filenames) + "]"
+
+def main():
+
+ script_dir, out_dir = get_paths()
+
+ test_files = []
+ inner_html_files = []
+
+ if len(sys.argv) > 2:
+ test_iterator = itertools.izip(
+ itertools.repeat(False),
+ sorted(os.path.abspath(item) for item in
+ glob.glob(os.path.join(sys.argv[2], "*.dat"))))
+ else:
+ test_iterator = itertools.chain(
+ itertools.izip(itertools.repeat(False),
+ sorted(support.get_data_files("tree-construction"))),
+ itertools.izip(itertools.repeat(True),
+ sorted(support.get_data_files(
+ os.path.join("tree-construction", "scripted")))))
+
+ for (scripted, test_file) in test_iterator:
+ input_file_name = os.path.splitext(os.path.split(test_file)[1])[0]
+ if scripted:
+ input_file_name = "scripted_" + input_file_name
+ test_data = support.TestData(test_file)
+ test_filename, inner_html_file_name = make_tests(script_dir, out_dir,
+ input_file_name, test_data)
+ if test_filename is not None:
+ test_files.append(test_filename)
+ if inner_html_file_name is not None:
+ inner_html_files.append(inner_html_file_name)
+
+if __name__ == "__main__":
+ main()
diff --git a/tests/wpt/web-platform-tests/html/webappapis/.gitkeep b/tests/wpt/web-platform-tests/html/webappapis/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/webappapis/atob/.gitkeep b/tests/wpt/web-platform-tests/html/webappapis/atob/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/atob/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/webappapis/atob/base64.html b/tests/wpt/web-platform-tests/html/webappapis/atob/base64.html
new file mode 100644
index 00000000000..c33ab228f94
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/atob/base64.html
@@ -0,0 +1,306 @@
+<!doctype html>
+<!-- Originally developed by Aryeh Gregor, funded by Google. Copyright belongs
+to Google. -->
+<title>atob()/btoa() tests</title>
+<meta charset=utf-8>
+<div id=log></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+/**
+ * btoa() as defined by the HTML5 spec, which mostly just references RFC4648.
+ */
+function mybtoa(s) {
+ // String conversion as required by WebIDL.
+ s = String(s);
+
+ // "The btoa() method must throw an INVALID_CHARACTER_ERR exception if the
+ // method's first argument contains any character whose code point is
+ // greater than U+00FF."
+ for (var i = 0; i < s.length; i++) {
+ if (s.charCodeAt(i) > 255) {
+ return "INVALID_CHARACTER_ERR";
+ }
+ }
+
+ var out = "";
+ for (var i = 0; i < s.length; i += 3) {
+ var groupsOfSix = [undefined, undefined, undefined, undefined];
+ groupsOfSix[0] = s.charCodeAt(i) >> 2;
+ groupsOfSix[1] = (s.charCodeAt(i) & 0x03) << 4;
+ if (s.length > i + 1) {
+ groupsOfSix[1] |= s.charCodeAt(i + 1) >> 4;
+ groupsOfSix[2] = (s.charCodeAt(i + 1) & 0x0f) << 2;
+ }
+ if (s.length > i + 2) {
+ groupsOfSix[2] |= s.charCodeAt(i + 2) >> 6;
+ groupsOfSix[3] = s.charCodeAt(i + 2) & 0x3f;
+ }
+ for (var j = 0; j < groupsOfSix.length; j++) {
+ if (typeof groupsOfSix[j] == "undefined") {
+ out += "=";
+ } else {
+ out += btoaLookup(groupsOfSix[j]);
+ }
+ }
+ }
+ return out;
+}
+
+/**
+ * Lookup table for mybtoa(), which converts a six-bit number into the
+ * corresponding ASCII character.
+ */
+function btoaLookup(idx) {
+ if (idx < 26) {
+ return String.fromCharCode(idx + 'A'.charCodeAt(0));
+ }
+ if (idx < 52) {
+ return String.fromCharCode(idx - 26 + 'a'.charCodeAt(0));
+ }
+ if (idx < 62) {
+ return String.fromCharCode(idx - 52 + '0'.charCodeAt(0));
+ }
+ if (idx == 62) {
+ return '+';
+ }
+ if (idx == 63) {
+ return '/';
+ }
+ // Throw INVALID_CHARACTER_ERR exception here -- won't be hit in the tests.
+}
+
+/**
+ * Implementation of atob() according to the HTML spec, except that instead of
+ * throwing INVALID_CHARACTER_ERR we return null.
+ */
+function myatob(input) {
+ // WebIDL requires DOMStrings to just be converted using ECMAScript
+ // ToString, which in our case amounts to calling String().
+ input = String(input);
+
+ // "Remove all space characters from input."
+ input = input.replace(/[ \t\n\f\r]/g, "");
+
+ // "If the length of input divides by 4 leaving no remainder, then: if
+ // input ends with one or two U+003D EQUALS SIGN (=) characters, remove
+ // them from input."
+ if (input.length % 4 == 0 && /==?$/.test(input)) {
+ input = input.replace(/==?$/, "");
+ }
+
+ // "If the length of input divides by 4 leaving a remainder of 1, throw an
+ // INVALID_CHARACTER_ERR exception and abort these steps."
+ //
+ // "If input contains a character that is not in the following list of
+ // characters and character ranges, throw an INVALID_CHARACTER_ERR
+ // exception and abort these steps:
+ //
+ // U+002B PLUS SIGN (+)
+ // U+002F SOLIDUS (/)
+ // U+0030 DIGIT ZERO (0) to U+0039 DIGIT NINE (9)
+ // U+0041 LATIN CAPITAL LETTER A to U+005A LATIN CAPITAL LETTER Z
+ // U+0061 LATIN SMALL LETTER A to U+007A LATIN SMALL LETTER Z"
+ if (input.length % 4 == 1
+ || !/^[+/0-9A-Za-z]*$/.test(input)) {
+ return null;
+ }
+
+ // "Let output be a string, initially empty."
+ var output = "";
+
+ // "Let buffer be a buffer that can have bits appended to it, initially
+ // empty."
+ //
+ // We append bits via left-shift and or. accumulatedBits is used to track
+ // when we've gotten to 24 bits.
+ var buffer = 0;
+ var accumulatedBits = 0;
+
+ // "While position does not point past the end of input, run these
+ // substeps:"
+ for (var i = 0; i < input.length; i++) {
+ // "Find the character pointed to by position in the first column of
+ // the following table. Let n be the number given in the second cell of
+ // the same row."
+ //
+ // "Append to buffer the six bits corresponding to number, most
+ // significant bit first."
+ //
+ // atobLookup() implements the table from the spec.
+ buffer <<= 6;
+ buffer |= atobLookup(input[i]);
+
+ // "If buffer has accumulated 24 bits, interpret them as three 8-bit
+ // big-endian numbers. Append the three characters with code points
+ // equal to those numbers to output, in the same order, and then empty
+ // buffer."
+ accumulatedBits += 6;
+ if (accumulatedBits == 24) {
+ output += String.fromCharCode((buffer & 0xff0000) >> 16);
+ output += String.fromCharCode((buffer & 0xff00) >> 8);
+ output += String.fromCharCode(buffer & 0xff);
+ buffer = accumulatedBits = 0;
+ }
+
+ // "Advance position by one character."
+ }
+
+ // "If buffer is not empty, it contains either 12 or 18 bits. If it
+ // contains 12 bits, discard the last four and interpret the remaining
+ // eight as an 8-bit big-endian number. If it contains 18 bits, discard the
+ // last two and interpret the remaining 16 as two 8-bit big-endian numbers.
+ // Append the one or two characters with code points equal to those one or
+ // two numbers to output, in the same order."
+ if (accumulatedBits == 12) {
+ buffer >>= 4;
+ output += String.fromCharCode(buffer);
+ } else if (accumulatedBits == 18) {
+ buffer >>= 2;
+ output += String.fromCharCode((buffer & 0xff00) >> 8);
+ output += String.fromCharCode(buffer & 0xff);
+ }
+
+ // "Return output."
+ return output;
+}
+
+/**
+ * A lookup table for atob(), which converts an ASCII character to the
+ * corresponding six-bit number.
+ */
+function atobLookup(chr) {
+ if (/[A-Z]/.test(chr)) {
+ return chr.charCodeAt(0) - "A".charCodeAt(0);
+ }
+ if (/[a-z]/.test(chr)) {
+ return chr.charCodeAt(0) - "a".charCodeAt(0) + 26;
+ }
+ if (/[0-9]/.test(chr)) {
+ return chr.charCodeAt(0) - "0".charCodeAt(0) + 52;
+ }
+ if (chr == "+") {
+ return 62;
+ }
+ if (chr == "/") {
+ return 63;
+ }
+ // Throw exception; should not be hit in tests
+}
+
+function btoaException(input) {
+ input = String(input);
+ for (var i = 0; i < input.length; i++) {
+ if (input.charCodeAt(i) > 255) {
+ return true;
+ }
+ }
+ return false;
+}
+
+function testBtoa(input) {
+ // "The btoa() method must throw an INVALID_CHARACTER_ERR exception if the
+ // method's first argument contains any character whose code point is
+ // greater than U+00FF."
+ var normalizedInput = String(input);
+ for (var i = 0; i < normalizedInput.length; i++) {
+ if (normalizedInput.charCodeAt(i) > 255) {
+ assert_throws("InvalidCharacterError", function() { btoa(input); },
+ "Code unit " + i + " has value " + normalizedInput.charCodeAt(i) + ", which is greater than 255");
+ return;
+ }
+ }
+ assert_equals(btoa(input), mybtoa(input));
+ assert_equals(atob(btoa(input)), String(input), "atob(btoa(input)) must be the same as String(input)");
+}
+
+var tests = ["עברית", "", "ab", "abc", "abcd", "abcde",
+ // This one is thrown in because IE9 seems to fail atob(btoa()) on it. Or
+ // possibly to fail btoa(). I actually can't tell what's happening here,
+ // but it doesn't hurt.
+ "\xff\xff\xc0",
+ // Is your DOM implementation binary-safe?
+ "\0a", "a\0b",
+ // WebIDL tests.
+ undefined, null, 7, 12, 1.5, true, false, NaN, +Infinity, -Infinity, 0, -0,
+ {toString: function() { return "foo" }},
+];
+for (var i = 0; i < 258; i++) {
+ tests.push(String.fromCharCode(i));
+}
+tests.push(String.fromCharCode(10000));
+tests.push(String.fromCharCode(65534));
+tests.push(String.fromCharCode(65535));
+
+// This is supposed to be U+10000.
+tests.push(String.fromCharCode(0xd800, 0xdc00));
+tests = tests.map(
+ function(elem) {
+ var expected = mybtoa(elem);
+ if (expected === "INVALID_CHARACTER_ERR") {
+ return ["btoa(" + format_value(elem) + ") must raise INVALID_CHARACTER_ERR", elem];
+ }
+ return ["btoa(" + format_value(elem) + ") == " + format_value(mybtoa(elem)), elem];
+ }
+);
+
+var everything = "";
+for (var i = 0; i < 256; i++) {
+ everything += String.fromCharCode(i);
+}
+tests.push(["btoa(first 256 code points concatenated)", everything]);
+
+generate_tests(testBtoa, tests);
+
+function testAtob(input) {
+ var expected = myatob(input);
+ if (expected === null) {
+ assert_throws("InvalidCharacterError", function() { atob(input) });
+ return;
+ }
+
+ assert_equals(atob(input), expected);
+}
+
+var tests = ["", "abcd", " abcd", "abcd ", " abcd===", "abcd=== ",
+ "abcd ===", "a", "ab", "abc", "abcde", String.fromCharCode(0xd800, 0xdc00),
+ "=", "==", "===", "====", "=====",
+ "a=", "a==", "a===", "a====", "a=====",
+ "ab=", "ab==", "ab===", "ab====", "ab=====",
+ "abc=", "abc==", "abc===", "abc====", "abc=====",
+ "abcd=", "abcd==", "abcd===", "abcd====", "abcd=====",
+ "abcde=", "abcde==", "abcde===", "abcde====", "abcde=====",
+ "=a", "=a=", "a=b", "a=b=", "ab=c", "ab=c=", "abc=d", "abc=d=",
+ // With whitespace
+ "ab\tcd", "ab\ncd", "ab\fcd", "ab\rcd", "ab cd", "ab\u00a0cd",
+ "ab\t\n\f\r cd", " \t\n\f\r ab\t\n\f\r cd\t\n\f\r ",
+ "ab\t\n\f\r =\t\n\f\r =\t\n\f\r ",
+ // Test if any bits are set at the end. These should all be fine, since
+ // they end with A, which becomes 0:
+ "A", "/A", "//A", "///A", "////A",
+ // These are all bad, since they end in / (= 63, all bits set) but their
+ // length isn't a multiple of four characters, so they can't be output by
+ // btoa(). Thus one might expect some UAs to throw exceptions or otherwise
+ // object, since they could never be output by btoa(), so they're good to
+ // test.
+ "/", "A/", "AA/", "AAAA/",
+ // But this one is possible:
+ "AAA/",
+ // Binary-safety tests
+ "\0nonsense", "abcd\0nonsense",
+ // WebIDL tests
+ undefined, null, 7, 12, 1.5, true, false, NaN, +Infinity, -Infinity, 0, -0,
+ {toString: function() { return "foo" }},
+ {toString: function() { return "abcd" }},
+];
+tests = tests.map(
+ function(elem) {
+ if (myatob(elem) === null) {
+ return ["atob(" + format_value(elem) + ") must raise InvalidCharacterError", elem];
+ }
+ return ["atob(" + format_value(elem) + ") == " + format_value(myatob(elem)), elem];
+ }
+);
+
+generate_tests(testAtob, tests);
+</script>
diff --git a/tests/wpt/web-platform-tests/html/webappapis/scripting/.gitkeep b/tests/wpt/web-platform-tests/html/webappapis/scripting/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/scripting/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/webappapis/scripting/enabling-and-disabling-scripting/.gitkeep b/tests/wpt/web-platform-tests/html/webappapis/scripting/enabling-and-disabling-scripting/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/scripting/enabling-and-disabling-scripting/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/webappapis/scripting/event-loops/.gitkeep b/tests/wpt/web-platform-tests/html/webappapis/scripting/event-loops/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/scripting/event-loops/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/webappapis/scripting/event-loops/contains.json b/tests/wpt/web-platform-tests/html/webappapis/scripting/event-loops/contains.json
new file mode 100644
index 00000000000..5d7e5e600e9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/scripting/event-loops/contains.json
@@ -0,0 +1,14 @@
+[
+ {
+ "id": "definitions-1",
+ "original_id": "definitions-1"
+ },
+ {
+ "id": "processing-model-3",
+ "original_id": "processing-model-3"
+ },
+ {
+ "id": "generic-task-sources",
+ "original_id": "generic-task-sources"
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/webappapis/scripting/events/.gitkeep b/tests/wpt/web-platform-tests/html/webappapis/scripting/events/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/scripting/events/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/webappapis/scripting/events/body-onload.html b/tests/wpt/web-platform-tests/html/webappapis/scripting/events/body-onload.html
new file mode 100644
index 00000000000..1e43d1ccd47
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/scripting/events/body-onload.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<title>HTMLBodyElement.onload</title>
+<link rel="author" title="Boris Zbarsky" href="mailto:bzbarsky@mit.edu">
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#handler-window-onload">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var t = async_test("body.onload should set the window.onload handler")
+window.onload = t.step_func(function() {
+ assert_unreached("This handler should be overwritten.")
+})
+var b = document.createElement("body")
+b.onload = t.step_func(function(e) {
+ assert_equals(e.currentTarget, window,
+ "The event should be fired at the window.")
+ t.done()
+})
+</script>
diff --git a/tests/wpt/web-platform-tests/html/webappapis/scripting/events/contains.json b/tests/wpt/web-platform-tests/html/webappapis/scripting/events/contains.json
new file mode 100644
index 00000000000..65f3062d2cd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/scripting/events/contains.json
@@ -0,0 +1,18 @@
+[
+ {
+ "id": "event-handler-attributes",
+ "original_id": "event-handler-attributes"
+ },
+ {
+ "id": "event-handlers-on-elements-document-objects-and-window-objects",
+ "original_id": "event-handlers-on-elements,-document-objects,-and-window-objects"
+ },
+ {
+ "id": "event-firing",
+ "original_id": "event-firing"
+ },
+ {
+ "id": "events-and-the-window-object",
+ "original_id": "events-and-the-window-object"
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/webappapis/scripting/events/event-handler-javascript.html b/tests/wpt/web-platform-tests/html/webappapis/scripting/events/event-handler-javascript.html
new file mode 100644
index 00000000000..657a37839d2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/scripting/events/event-handler-javascript.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<title>Event handler with labels</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body onload="javascript:
+ for (var i = 0; i < 2; ++i) {
+ for (var j = 0; j < 2; ++j) {
+ t.step(function() {
+ assert_equals(i, 0);
+ assert_equals(j, 0);
+ });
+ break javascript;
+ }
+ }
+ t.done();
+">
+<div id="log"></div>
+<script>
+var t = async_test("Event handlers starting with 'javascript:' should treat that as a label.");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/webappapis/scripting/events/event-handler-spec-example.html b/tests/wpt/web-platform-tests/html/webappapis/scripting/events/event-handler-spec-example.html
new file mode 100644
index 00000000000..c06806e3c77
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/scripting/events/event-handler-spec-example.html
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<title>Event handler invocation order</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var objects = [{}, function() {}, new Number(42), new String()];
+var primitives = [42, null, undefined, ""];
+objects.forEach(function(object) {
+ var t = async_test("Event handler listeners should be registered when they " +
+ "are first set to an object value (" +
+ format_value(object) + ").");
+ t.step(function() {
+ var i = 0;
+ var uncalled = "t.step(function() { assert_unreached('First event handler.') })"
+ var button = document.createElement('button');
+ button.onclick = object; // event handler listener is registered here
+ button.addEventListener('click', t.step_func(function () { assert_equals(++i, 2) }), false);
+ button.setAttribute('onclick', uncalled);
+ button.addEventListener('click', t.step_func(function () { assert_equals(++i, 3) }), false);
+ button.onclick = t.step_func(function () { assert_equals(++i, 1); });
+ button.addEventListener('click', t.step_func(function () { assert_equals(++i, 4) }), false);
+ button.click()
+ assert_equals(button.getAttribute("onclick"), uncalled)
+ assert_equals(i, 4);
+ t.done()
+ });
+});
+primitives.forEach(function(primitive) {
+ var t = async_test("Event handler listeners should be registered when they " +
+ "are first set to an object value (" +
+ format_value(primitive) + ").");
+ t.step(function() {
+ var i = 0;
+ var uncalled = "t.step(function() { assert_unreached('First event handler.') })"
+ var button = document.createElement('button');
+ button.onclick = primitive;
+ button.addEventListener('click', t.step_func(function () { assert_equals(++i, 1) }), false);
+ button.setAttribute('onclick', uncalled); // event handler listener is registered here
+ button.addEventListener('click', t.step_func(function () { assert_equals(++i, 3) }), false);
+ button.onclick = t.step_func(function () { assert_equals(++i, 2); });
+ button.addEventListener('click', t.step_func(function () { assert_equals(++i, 4) }), false);
+ button.click()
+ assert_equals(button.getAttribute("onclick"), uncalled)
+ assert_equals(i, 4);
+ t.done()
+ });
+});
+var t = async_test("Event handler listeners should be registered when they " +
+ "are first set to an object value.");
+t.step(function() {
+ var i = 0;
+ var uncalled = "t.step(function() { assert_unreached('First event handler.') })"
+ var button = document.createElement('button');
+ button.addEventListener('click', t.step_func(function () { assert_equals(++i, 1) }), false);
+ button.setAttribute('onclick', uncalled); // event handler listener is registered here
+ button.addEventListener('click', t.step_func(function () { assert_equals(++i, 3) }), false);
+ button.onclick = t.step_func(function () { assert_equals(++i, 2); });
+ button.addEventListener('click', t.step_func(function () { assert_equals(++i, 4) }), false);
+ button.click()
+ assert_equals(button.getAttribute("onclick"), uncalled)
+ assert_equals(i, 4);
+ t.done()
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/html/webappapis/scripting/introduction-5/.gitkeep b/tests/wpt/web-platform-tests/html/webappapis/scripting/introduction-5/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/scripting/introduction-5/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/webappapis/scripting/javascript-protocol/.gitkeep b/tests/wpt/web-platform-tests/html/webappapis/scripting/javascript-protocol/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/scripting/javascript-protocol/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/.gitkeep b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/addEventListener.html b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/addEventListener.html
new file mode 100644
index 00000000000..b2cb36b9729
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/addEventListener.html
@@ -0,0 +1,32 @@
+<!doctype html>
+<html>
+ <head>
+ <title>window.onerror - addEventListener</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id=log></div>
+ <script>
+ setup({allow_uncaught_exception:true});
+ var t = async_test();
+ var ran = false;
+ // spec doesn't say to fire an event so this should do nothing
+ window.addEventListener('error', t.step_func(function(e){
+ ran = true;
+ }), false);
+ </script>
+ <script>
+ undefined_variable;
+ </script>
+ <script>
+ for (;) {}
+ </script>
+ <script>
+ t.step(function(){
+ assert_false(ran, 'ran');
+ t.done();
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/body-onerror-compile-error-data-url.html b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/body-onerror-compile-error-data-url.html
new file mode 100644
index 00000000000..006ca13db04
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/body-onerror-compile-error-data-url.html
@@ -0,0 +1,37 @@
+<!doctype html>
+<html>
+ <head>
+ <title>&lt;body onerror> - compile error in &lt;script src=data:...></title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <script>
+ setup({allow_uncaught_exception:true});
+ var t = async_test();
+ var t_col = async_test(document.title+' (column)');
+ var ran = false;
+ </script>
+ <body onerror="
+ t.step(function(){
+ ran = true;
+ assert_equals(typeof event, 'string', 'first arg');
+ assert_equals(source, 'data:text/javascript,for(;){}', 'second arg');
+ assert_equals(typeof lineno, 'number', 'third arg');
+ });
+ t_col.step(function() {
+ assert_equals(typeof column, 'number', 'fourth arg');
+ });
+ ">
+ <div id=log></div>
+ <script src="data:text/javascript,for(;){}"></script>
+ <script>
+ t.step(function(){
+ assert_true(ran, 'ran');
+ t.done();
+ });
+ t_col.step(function(){
+ t_col.done();
+ });
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/body-onerror-compile-error.html b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/body-onerror-compile-error.html
new file mode 100644
index 00000000000..f80981ddcd3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/body-onerror-compile-error.html
@@ -0,0 +1,39 @@
+<!doctype html>
+<html>
+ <head>
+ <title>&lt;body onerror> - compile error in &lt;script></title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <script>
+ setup({allow_uncaught_exception:true});
+ var t = async_test();
+ var t_col = async_test(document.title+' (column)');
+ var ran = false;
+ </script>
+ <body onerror="
+ t.step(function(){
+ ran = true;
+ assert_equals(typeof event, 'string', 'first arg');
+ assert_equals(source, location.href, 'second arg');
+ assert_equals(typeof lineno, 'number', 'third arg');
+ });
+ t_col.step(function() {
+ assert_equals(typeof column, 'number', 'fourth arg');
+ });
+ ">
+ <div id=log></div>
+ <script>
+ for(;) {}
+ </script>
+ <script>
+ t.step(function(){
+ assert_true(ran, 'ran');
+ t.done();
+ });
+ t_col.step(function(){
+ t_col.done();
+ });
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/body-onerror-runtime-error.html b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/body-onerror-runtime-error.html
new file mode 100644
index 00000000000..95ddd5d5b4e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/body-onerror-runtime-error.html
@@ -0,0 +1,39 @@
+<!doctype html>
+<html>
+ <head>
+ <title>&lt;body onerror> - runtime error in &lt;script></title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <script>
+ setup({allow_uncaught_exception:true});
+ var t = async_test();
+ var t_col = async_test(document.title+' (column)');
+ var ran = false;
+ </script>
+ <body onerror="
+ t.step(function(){
+ ran = true;
+ assert_equals(typeof event, 'string', 'first arg');
+ assert_equals(source, location.href, 'second arg');
+ assert_equals(typeof lineno, 'number', 'third arg');
+ });
+ t_col.step(function(){
+ assert_equals(typeof column, 'number', 'fourth arg');
+ });
+ ">
+ <div id=log></div>
+ <script>
+ undefined_variable;
+ </script>
+ <script>
+ t.step(function(){
+ assert_true(ran, 'ran');
+ t.done();
+ });
+ t_col.step(function(){
+ t_col.done();
+ });
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-cross-origin-setInterval.html b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-cross-origin-setInterval.html
new file mode 100644
index 00000000000..14e9a8bc215
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-cross-origin-setInterval.html
@@ -0,0 +1,34 @@
+<!doctype html>
+<html>
+ <head>
+ <title>window.onerror - compile error in cross-origin setInterval</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id=log></div>
+ <script>
+ setup({allow_uncaught_exception:true});
+ var t = async_test();
+ var t_col = async_test(document.title+' (column)');
+ var ran = false;
+ var col_value;
+ var interval;
+ window.onerror = t.step_func(function(a, b, c, d){
+ clearInterval(interval);
+ ran = true;
+ col_value = d;
+ assert_equals(a, 'Script error.', 'first arg');
+ assert_equals(b, '', 'second arg');
+ assert_equals(c, 0, 'third arg');
+ });
+ function col_check() {
+ assert_equals(col_value, 0, 'fourth arg');
+ t_col.done();
+ }
+ var script = document.createElement('script');
+ script.src = location.href.replace('://', '://www1.').replace(/\/[^\/]+$/, '/support/syntax-error-in-setInterval.js');
+ document.body.appendChild(script);
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-cross-origin-setTimeout.html b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-cross-origin-setTimeout.html
new file mode 100644
index 00000000000..ba3be9d0a84
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-cross-origin-setTimeout.html
@@ -0,0 +1,32 @@
+<!doctype html>
+<html>
+ <head>
+ <title>window.onerror - compile error in cross-origin setTimeout</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id=log></div>
+ <script>
+ setup({allow_uncaught_exception:true});
+ var t = async_test();
+ var t_col = async_test(document.title+' (column)');
+ var ran = false;
+ var col_value;
+ window.onerror = t.step_func(function(a, b, c, d){
+ ran = true;
+ col_value = d;
+ assert_equals(a, 'Script error.', 'first arg');
+ assert_equals(b, '', 'second arg');
+ assert_equals(c, 0, 'third arg');
+ });
+ function col_check() {
+ assert_equals(col_value, 0, 'fourth arg');
+ t_col.done();
+ }
+ var script = document.createElement('script');
+ script.src = location.href.replace('://', '://www1.').replace(/\/[^\/]+$/, '/support/syntax-error-in-setTimeout.js');
+ document.body.appendChild(script);
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-cross-origin.html b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-cross-origin.html
new file mode 100644
index 00000000000..b7e989529fb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-cross-origin.html
@@ -0,0 +1,38 @@
+<!doctype html>
+<html>
+ <head>
+ <title>window.onerror - compile error in &lt;script src=//www1...></title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id=log></div>
+ <script>
+ setup({allow_uncaught_exception:true});
+ var t = async_test();
+ var t_col = async_test(document.title+' (column)');
+ var ran = false;
+ var col_value;
+ window.onerror = t.step_func(function(a, b, c, d){
+ ran = true;
+ col_value = d;
+ assert_equals(a, 'Script error.', 'first arg');
+ assert_equals(b, '', 'second arg');
+ assert_equals(c, 0, 'third arg');
+ });
+ var script = document.createElement('script');
+ script.src = location.href.replace('://', '://www1.').replace(/\/[^\/]+$/, '/support/syntax-error.js');
+ document.body.appendChild(script);
+ onload = function(){
+ t.step(function(){
+ assert_true(ran, 'ran');
+ t.done();
+ });
+ t_col.step(function(){
+ assert_equals(col_value, 0, 'fourth arg');
+ t_col.done();
+ });
+ };
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-data-url.html b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-data-url.html
new file mode 100644
index 00000000000..ef7dd8913d6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-data-url.html
@@ -0,0 +1,36 @@
+<!doctype html>
+<html>
+ <head>
+ <title>window.onerror - compile error in &lt;script src=data:...></title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id=log></div>
+ <script>
+ setup({allow_uncaught_exception:true});
+ var t = async_test();
+ var t_col = async_test(document.title+' (column)');
+ var ran = false;
+ var col_value;
+ window.onerror = t.step_func(function(a, b, c, d){
+ ran = true;
+ col_value = d;
+ assert_equals(typeof a, 'string', 'first arg');
+ assert_equals(b, 'data:text/javascript,for(;) {}', 'second arg');
+ assert_equals(typeof c, 'number', 'third arg');
+ });
+ </script>
+ <script src="data:text/javascript,for(;) {}"></script>
+ <script>
+ t.step(function(){
+ assert_true(ran, 'ran');
+ t.done();
+ });
+ t_col.step(function(){
+ assert_equals(typeof col_value, 'number', 'fourth arg');
+ t_col.done();
+ });
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-in-attribute.html b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-in-attribute.html
new file mode 100644
index 00000000000..864d09fc1e9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-in-attribute.html
@@ -0,0 +1,39 @@
+<!doctype html>
+<html>
+ <head>
+ <title>window.onerror - compile error in attribute</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id=log></div>
+ <script>
+ setup({allow_uncaught_exception:true});
+ var t = async_test();
+ var t_col = async_test(document.title+' (column)');
+ var ran = false;
+ var col_value;
+ window.onerror = t.step_func(function(a, b, c, d){
+ ran = true;
+ col_value = d;
+ assert_equals(typeof a, 'string', 'first arg');
+ assert_equals(b, location.href, 'second arg');
+ assert_equals(typeof c, 'number', 'third arg');
+ });
+ </script>
+ <p onclick="{"></p>
+ <script>
+ t.step(function(){
+ var ev = document.createEvent('Event');
+ ev.initEvent('click', false, false);
+ document.querySelector('p').dispatchEvent(ev);
+ assert_true(ran, 'ran');
+ t.done();
+ });
+ t_col.step(function(){
+ assert_equals(typeof col_value, 'number', 'fourth arg');
+ t_col.done();
+ });
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-in-body-onerror.html b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-in-body-onerror.html
new file mode 100644
index 00000000000..0b094e71c35
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-in-body-onerror.html
@@ -0,0 +1,28 @@
+<!doctype html>
+<html>
+ <head>
+ <title>window.onerror - compile error in &lt;body onerror></title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ setup({allow_uncaught_exception:true});
+ var t = async_test();
+ var ran = false;
+ window.onerror = t.step_func(function(){
+ ran = true;
+ });
+ </script>
+ </head>
+ <body onerror="{"><!-- sets the event handler to null before compiling -->
+ <div id=log></div>
+ <script>
+ for(;) {}
+ </script>
+ <script>
+ t.step(function(){
+ assert_false(ran, 'ran');
+ t.done();
+ });
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-in-setInterval.html b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-in-setInterval.html
new file mode 100644
index 00000000000..39a01335c3b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-in-setInterval.html
@@ -0,0 +1,39 @@
+<!doctype html>
+<html>
+ <head>
+ <title>window.onerror - compile error in setInterval</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id=log></div>
+ <script>
+ setup({allow_uncaught_exception:true});
+ var t = async_test();
+ var t_col = async_test(document.title+' (column)');
+ var ran = false;
+ var col_value;
+ var interval;
+ window.onerror = t.step_func(function(a, b, c, d){
+ clearInterval(interval);
+ ran = true;
+ col_value = d;
+ assert_equals(typeof a, 'string', 'first arg');
+ assert_equals(b, location.href, 'second arg');
+ assert_equals(typeof c, 'number', 'third arg');
+ });
+ interval = setInterval("{", 10);
+ setTimeout(function(){
+ t.step(function(){
+ clearInterval(interval);
+ assert_true(ran, 'ran');
+ t.done();
+ });
+ t_col.step(function(){
+ assert_equals(typeof col_value, 'number', 'fourth arg');
+ t_col.done();
+ });
+ }, 20);
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-in-setTimeout.html b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-in-setTimeout.html
new file mode 100644
index 00000000000..87966031388
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-in-setTimeout.html
@@ -0,0 +1,36 @@
+<!doctype html>
+<html>
+ <head>
+ <title>window.onerror - compile error in setTimeout</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id=log></div>
+ <script>
+ setup({allow_uncaught_exception:true});
+ var t = async_test();
+ var t_col = async_test(document.title+' (column)');
+ var ran = false;
+ var col_value;
+ window.onerror = t.step_func(function(a, b, c, d){
+ ran = true;
+ col_value = d;
+ assert_equals(typeof a, 'string', 'first arg');
+ assert_equals(b, location.href, 'second arg');
+ assert_equals(typeof c, 'number', 'third arg');
+ });
+ setTimeout("{", 10);
+ setTimeout(function(){
+ t.step(function(){
+ assert_true(ran, 'ran');
+ t.done();
+ });
+ t_col.step(function(){
+ assert_equals(typeof col_value, 'number', 'fourth arg');
+ t_col.done();
+ });
+ }, 20);
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-same-origin.html b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-same-origin.html
new file mode 100644
index 00000000000..71c28b584d6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error-same-origin.html
@@ -0,0 +1,36 @@
+<!doctype html>
+<html>
+ <head>
+ <title>window.onerror - compile error in &lt;script src=...></title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id=log></div>
+ <script>
+ setup({allow_uncaught_exception:true});
+ var t = async_test();
+ var t_col = async_test(document.title+' (column)');
+ var ran = false;
+ var col_value;
+ window.onerror = t.step_func(function(a, b, c, d){
+ ran = true;
+ col_value = d;
+ assert_equals(typeof a, 'string', 'first arg');
+ assert_equals(b, document.querySelector('script[src="support/syntax-error.js"]').src, 'second arg');
+ assert_equals(typeof c, 'number', 'third arg');
+ });
+ </script>
+ <script src="support/syntax-error.js"></script>
+ <script>
+ t.step(function(){
+ assert_true(ran, 'ran');
+ t.done();
+ });
+ t_col.step(function(){
+ assert_equals(typeof col_value, 'number', 'fourth arg');
+ t_col.done();
+ });
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error.html b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error.html
new file mode 100644
index 00000000000..a4bdfd9c471
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/compile-error.html
@@ -0,0 +1,38 @@
+<!doctype html>
+<html>
+ <head>
+ <title>window.onerror - compile error in &lt;script></title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id=log></div>
+ <script>
+ setup({allow_uncaught_exception:true});
+ var t = async_test();
+ var t_col = async_test(document.title+' (column)');
+ var ran = false;
+ var col_value;
+ window.onerror = t.step_func(function(a, b, c, d){
+ ran = true;
+ col_value = d;
+ assert_equals(typeof a, 'string', 'first arg');
+ assert_equals(b, location.href, 'second arg');
+ assert_equals(typeof c, 'number', 'third arg');
+ });
+ </script>
+ <script>
+ for(;) {}
+ </script>
+ <script>
+ t.step(function(){
+ assert_true(ran, 'ran');
+ t.done();
+ });
+ t_col.step(function(){
+ assert_equals(typeof col_value, 'number', 'fourth arg');
+ t_col.done();
+ });
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/contains.json b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/contains.json
new file mode 100644
index 00000000000..b49029277f3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/contains.json
@@ -0,0 +1,28 @@
+[
+ {
+ "id": "definitions-0",
+ "original_id": "definitions-0"
+ },
+ {
+ "id": "calling-scripts",
+ "original_id": "calling-scripts"
+ },
+ {
+ "id": "creating-scripts",
+ "original_id": "creating-scripts"
+ },
+ {
+ "id": "killing-scripts",
+ "original_id": "killing-scripts"
+ },
+ {
+ "id": "runtime-script-errors",
+ "original_id": "runtime-script-errors",
+ "children": [
+ {
+ "id": "runtime-script-errors-in-documents",
+ "original_id": "runtime-script-errors-in-documents"
+ }
+ ]
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/runtime-error-cross-origin-setInterval.html b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/runtime-error-cross-origin-setInterval.html
new file mode 100644
index 00000000000..dd97566d701
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/runtime-error-cross-origin-setInterval.html
@@ -0,0 +1,34 @@
+<!doctype html>
+<html>
+ <head>
+ <title>window.onerror - runtime error in cross-origin setInterval</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id=log></div>
+ <script>
+ setup({allow_uncaught_exception:true});
+ var t = async_test();
+ var t_col = async_test(document.title+' (column)');
+ var ran = false;
+ var col_value;
+ var interval;
+ window.onerror = t.step_func(function(a, b, c, d){
+ clearInterval(interval);
+ ran = true;
+ col_value = d;
+ assert_equals(a, 'Script error.', 'first arg');
+ assert_equals(b, '', 'second arg');
+ assert_equals(c, 0, 'third arg');
+ });
+ function col_check() {
+ assert_equals(col_value, 0, 'fourth arg');
+ t_col.done();
+ }
+ var script = document.createElement('script');
+ script.src = location.href.replace('://', '://www1.').replace(/\/[^\/]+$/, '/support/undefined-variable-in-setInterval.js');
+ document.body.appendChild(script);
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/runtime-error-cross-origin-setTimeout.html b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/runtime-error-cross-origin-setTimeout.html
new file mode 100644
index 00000000000..20ee21c6171
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/runtime-error-cross-origin-setTimeout.html
@@ -0,0 +1,32 @@
+<!doctype html>
+<html>
+ <head>
+ <title>window.onerror - runtime error in cross-origin setTimeout</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id=log></div>
+ <script>
+ setup({allow_uncaught_exception:true});
+ var t = async_test();
+ var t_col = async_test(document.title+' (column)');
+ var ran = false;
+ var col_value;
+ window.onerror = t.step_func(function(a, b, c, d){
+ ran = true;
+ col_value = d;
+ assert_equals(a, 'Script error.', 'first arg');
+ assert_equals(b, '', 'second arg');
+ assert_equals(c, 0, 'third arg');
+ });
+ function col_check() {
+ assert_equals(col_value, 0, 'fourth arg');
+ t_col.done();
+ }
+ var script = document.createElement('script');
+ script.src = location.href.replace('://', '://www1.').replace(/\/[^\/]+$/, '/support/undefined-variable-in-setTimeout.js');
+ document.body.appendChild(script);
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/runtime-error-cross-origin.html b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/runtime-error-cross-origin.html
new file mode 100644
index 00000000000..d63aaa6d3b7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/runtime-error-cross-origin.html
@@ -0,0 +1,38 @@
+<!doctype html>
+<html>
+ <head>
+ <title>window.onerror - runtime error in &lt;script src=//www1...></title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id=log></div>
+ <script>
+ setup({allow_uncaught_exception:true});
+ var t = async_test();
+ var t_col = async_test(document.title+' (column)');
+ var ran = false;
+ var col_value;
+ window.onerror = t.step_func(function(a, b, c, d){
+ ran = true;
+ col_value = d;
+ assert_equals(a, 'Script error.', 'first arg');
+ assert_equals(b, '', 'second arg');
+ assert_equals(c, 0, 'third arg');
+ });
+ var script = document.createElement('script');
+ script.src = location.href.replace('://', '://www1.').replace(/\/[^\/]+$/, '/support/undefined-variable.js');
+ document.body.appendChild(script);
+ onload = function(){
+ t.step(function(){
+ assert_true(ran, 'ran');
+ t.done();
+ });
+ t_col.step(function(){
+ assert_equals(col_value, 0, 'fourth arg');
+ t_col.done();
+ });
+ };
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/runtime-error-data-url.html b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/runtime-error-data-url.html
new file mode 100644
index 00000000000..1b203601b24
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/runtime-error-data-url.html
@@ -0,0 +1,36 @@
+<!doctype html>
+<html>
+ <head>
+ <title>window.onerror - runtime error in &lt;script src=data:...></title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id=log></div>
+ <script>
+ setup({allow_uncaught_exception:true});
+ var t = async_test();
+ var t_col = async_test(document.title+' (column)');
+ var ran = false;
+ var col_value;
+ window.onerror = t.step_func(function(a, b, c, d){
+ ran = true;
+ col_value = d;
+ assert_equals(typeof a, 'string', 'first arg');
+ assert_equals(b, 'data:text/javascript,undefined_variable;', 'second arg');
+ assert_equals(typeof c, 'number', 'third arg');
+ });
+ </script>
+ <script src="data:text/javascript,undefined_variable;"></script>
+ <script>
+ t.step(function(){
+ assert_true(ran, 'ran');
+ t.done();
+ });
+ t_col.step(function(){
+ assert_equals(typeof col_value, number, 'fourth arg');
+ t_col.done();
+ });
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/runtime-error-in-attribute.html b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/runtime-error-in-attribute.html
new file mode 100644
index 00000000000..b4f69da7a22
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/runtime-error-in-attribute.html
@@ -0,0 +1,39 @@
+<!doctype html>
+<html>
+ <head>
+ <title>window.onerror - runtime error in attribute</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id=log></div>
+ <script>
+ setup({allow_uncaught_exception:true});
+ var t = async_test();
+ var t_col = async_test(document.title+' (column)');
+ var ran = false;
+ var col_value;
+ window.onerror = t.step_func(function(a, b, c, d){
+ ran = true;
+ col_value = d;
+ assert_equals(typeof a, 'string', 'first arg');
+ assert_equals(b, location.href, 'second arg');
+ assert_equals(typeof c, 'number', 'third arg');
+ });
+ </script>
+ <p onclick="undefined_variable;"></p>
+ <script>
+ t.step(function(){
+ var ev = document.createEvent('Event');
+ ev.initEvent('click', false, false);
+ document.querySelector('p').dispatchEvent(ev);
+ assert_true(ran, 'ran');
+ t.done();
+ });
+ t_col.step(function(){
+ assert_equals(typeof col_value, 'number', 'fourth arg');
+ t_col.done();
+ });
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/runtime-error-in-body-onerror.html b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/runtime-error-in-body-onerror.html
new file mode 100644
index 00000000000..e0fd1dcbd54
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/runtime-error-in-body-onerror.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<html>
+ <head>
+ <title>runtime error in &lt;body onerror></title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ setup({allow_uncaught_exception:true});
+ var t = async_test();
+ var ran = 0;
+ </script>
+ </head>
+ <body onerror="ran++; undefined_variable_in_onerror;">
+ <div id=log></div>
+ <script>
+ undefined_variable;
+ </script>
+ <script>
+ t.step(function(){
+ assert_equals(ran, 1, 'ran');
+ t.done();
+ });
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/runtime-error-in-setInterval.html b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/runtime-error-in-setInterval.html
new file mode 100644
index 00000000000..fcfb6c59759
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/runtime-error-in-setInterval.html
@@ -0,0 +1,39 @@
+<!doctype html>
+<html>
+ <head>
+ <title>window.onerror - runtime error in setInterval</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id=log></div>
+ <script>
+ setup({allow_uncaught_exception:true});
+ var t = async_test();
+ var t_col = async_test(document.title+' (column)');
+ var ran = false;
+ var col_value;
+ var interval;
+ window.onerror = t.step_func(function(a, b, c, d){
+ clearInterval(interval);
+ ran = true;
+ col_value = d;
+ assert_equals(typeof a, 'string', 'first arg');
+ assert_equals(b, location.href, 'second arg');
+ assert_equals(typeof c, 'number', 'third arg');
+ });
+ interval = setInterval("undefined_variable;", 10);
+ setTimeout(function(){
+ clearInterval(interval);
+ t.step(function(){
+ assert_true(ran, 'ran');
+ t.done();
+ });
+ t_col.step(function(){
+ assert_equals(typeof col_value, 'number', 'fourth arg');
+ t_col.done();
+ });
+ }, 20);
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/runtime-error-in-setTimeout.html b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/runtime-error-in-setTimeout.html
new file mode 100644
index 00000000000..c0c69ad7c46
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/runtime-error-in-setTimeout.html
@@ -0,0 +1,36 @@
+<!doctype html>
+<html>
+ <head>
+ <title>window.onerror - runtime error in setTimeout</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id=log></div>
+ <script>
+ setup({allow_uncaught_exception:true});
+ var t = async_test();
+ var t_col = async_test(document.title+' (column)');
+ var ran = false;
+ var col_value;
+ window.onerror = t.step_func(function(a, b, c, d){
+ ran = true;
+ col_value = d;
+ assert_equals(typeof a, 'string', 'first arg');
+ assert_equals(b, location.href, 'second arg');
+ assert_equals(typeof c, 'number', 'third arg');
+ });
+ setTimeout("undefined_variable;", 10);
+ setTimeout(function(){
+ t.step(function(){
+ assert_true(ran, 'ran');
+ t.done();
+ });
+ t_col.step(function(){
+ assert_equals(typeof col_value, 'number', 'fourth arg');
+ t_col.done();
+ });
+ }, 20);
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/runtime-error-in-window-onerror.html b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/runtime-error-in-window-onerror.html
new file mode 100644
index 00000000000..150a793b79e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/runtime-error-in-window-onerror.html
@@ -0,0 +1,29 @@
+<!doctype html>
+<html>
+ <head>
+ <title>runtime error in window.onerror</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id=log></div>
+ <script>
+ setup({allow_uncaught_exception:true});
+ var t = async_test();
+ var ran = 0;
+ window.onerror = function(){
+ ran++;
+ undefined_variable_in_onerror;
+ };
+ </script>
+ <script>
+ undefined_variable;
+ </script>
+ <script>
+ t.step(function(){
+ assert_equals(ran, 1, 'ran');
+ t.done();
+ });
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/runtime-error-same-origin.html b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/runtime-error-same-origin.html
new file mode 100644
index 00000000000..8f3cfb70b2a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/runtime-error-same-origin.html
@@ -0,0 +1,36 @@
+<!doctype html>
+<html>
+ <head>
+ <title>window.onerror - runtime error in &lt;script src=...></title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id=log></div>
+ <script>
+ setup({allow_uncaught_exception:true});
+ var t = async_test();
+ var t_col = async_test(document.title+' (column)');
+ var ran = false;
+ var col_value;
+ window.onerror = t.step_func(function(a, b, c, d){
+ ran = true;
+ col_value = d;
+ assert_equals(typeof a, 'string', 'first arg');
+ assert_equals(b, document.querySelector('script[src="support/undefined-variable.js"]').src, 'second arg');
+ assert_equals(typeof c, 'number', 'third arg');
+ });
+ </script>
+ <script src="support/undefined-variable.js"></script>
+ <script>
+ t.step(function(){
+ assert_true(ran, 'ran');
+ t.done();
+ });
+ t_col.step(function(){
+ assert_equals(typeof col_value, 'number', 'fourth arg');
+ t_col.done();
+ });
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/runtime-error.html b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/runtime-error.html
new file mode 100644
index 00000000000..7907494aa66
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/runtime-error.html
@@ -0,0 +1,38 @@
+<!doctype html>
+<html>
+ <head>
+ <title>window.onerror - runtime error in &lt;script></title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id=log></div>
+ <script>
+ setup({allow_uncaught_exception:true});
+ var t = async_test();
+ var t_col = async_test(document.title+' (column)');
+ var ran = false;
+ var col_value;
+ window.onerror = t.step_func(function(a, b, c, d){
+ ran = true;
+ col_value = d;
+ assert_equals(typeof a, 'string', 'first arg');
+ assert_equals(b, location.href, 'second arg');
+ assert_equals(typeof c, 'number', 'third arg');
+ });
+ </script>
+ <script>
+ undefined_variable;
+ </script>
+ <script>
+ t.step(function(){
+ assert_true(ran, 'ran');
+ t.done();
+ });
+ t_col.step(function(){
+ assert_equals(typeof col_value, 'number', 'fourth arg');
+ t_col.done();
+ });
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/support/syntax-error-in-setInterval.js b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/support/syntax-error-in-setInterval.js
new file mode 100644
index 00000000000..812c0daea13
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/support/syntax-error-in-setInterval.js
@@ -0,0 +1,9 @@
+interval = setInterval('{', 10);
+setTimeout(function(){
+ clearInterval(interval);
+ t.step(function(){
+ assert_true(ran, 'ran');
+ t.done();
+ });
+ t_col.step(col_check);
+}, 20); \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/support/syntax-error-in-setTimeout.js b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/support/syntax-error-in-setTimeout.js
new file mode 100644
index 00000000000..84eb4fc4199
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/support/syntax-error-in-setTimeout.js
@@ -0,0 +1,8 @@
+setTimeout('{', 10);
+setTimeout(function(){
+ t.step(function(){
+ assert_true(ran, 'ran');
+ t.done();
+ });
+ t_col.step(col_check);
+}, 20);
diff --git a/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/support/syntax-error.js b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/support/syntax-error.js
new file mode 100644
index 00000000000..0f74a6fca63
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/support/syntax-error.js
@@ -0,0 +1 @@
+for (;) {} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/support/undefined-variable-in-setInterval.js b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/support/undefined-variable-in-setInterval.js
new file mode 100644
index 00000000000..2950fdb51d1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/support/undefined-variable-in-setInterval.js
@@ -0,0 +1,9 @@
+interval = setInterval('undefined_variable;', 10);
+setTimeout(function(){
+ clearInterval(interval);
+ t.step(function(){
+ assert_true(ran, 'ran');
+ t.done();
+ });
+ t_col.step(col_check);
+}, 20); \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/support/undefined-variable-in-setTimeout.js b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/support/undefined-variable-in-setTimeout.js
new file mode 100644
index 00000000000..6350ab62ebf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/support/undefined-variable-in-setTimeout.js
@@ -0,0 +1,8 @@
+setTimeout('undefined_variable;', 10);
+setTimeout(function(){
+ t.step(function(){
+ assert_true(ran, 'ran');
+ t.done();
+ });
+ t_col.step(col_check);
+}, 20);
diff --git a/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/support/undefined-variable.js b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/support/undefined-variable.js
new file mode 100644
index 00000000000..e73a62ceda3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/support/undefined-variable.js
@@ -0,0 +1 @@
+undefined_variable; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/window-onerror-parse-error.html b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/window-onerror-parse-error.html
new file mode 100644
index 00000000000..3c21df49c94
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/window-onerror-parse-error.html
@@ -0,0 +1,40 @@
+<!doctype html>
+<html>
+ <head>
+ <title>window.onerror: parse errors</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!--
+
+ In https://html.spec.whatwg.org/multipage/#creating-scripts ,
+ step 3 describes parsing the script, and step 5 says:
+ # Otherwise, report the error using the onerror event handler of
+ # the script's global object. If the error is still not handled
+ # after this, then the error may be reported to the user.
+ which links to
+ https://html.spec.whatwg.org/multipage/#report-the-error ,
+ which describes what to do when onerror is a Function.
+
+ -->
+ </head>
+ <body>
+
+ <div id="log"></div>
+ <script>
+ setup({allow_uncaught_exception:true});
+ var error_count = 0;
+ window.onerror = function(msg, url, lineno) {
+ ++error_count;
+ test(function() {assert_equals(url, window.location.href)},
+ "correct url passed to window.onerror");
+ test(function() {assert_equals(lineno, 34)},
+ "correct line number passed to window.onerror");
+ };
+ </script>
+ <script>This script does not parse correctly.</script>
+ <script>
+ test(function() {assert_equals(error_count, 1)},
+ "correct number of calls to window.onerror");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/window-onerror-runtime-error-throw.html b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/window-onerror-runtime-error-throw.html
new file mode 100644
index 00000000000..5d2ef0d29dd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/window-onerror-runtime-error-throw.html
@@ -0,0 +1,39 @@
+<!doctype html>
+<html>
+ <head>
+ <title>window.onerror: runtime scripterrors</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!--
+
+ https://html.spec.whatwg.org/multipage/#runtime-script-errors
+ says what to do for uncaught runtime script errors, and just below
+ describes what to do when onerror is a Function.
+
+ -->
+ </head>
+ <body>
+
+ <div id="log"></div>
+ <script>
+ setup({allow_uncaught_exception:true});
+ var error_count = 0;
+ window.onerror = function(msg, url, lineno) {
+ ++error_count;
+ };
+ </script>
+ <script>
+ try {
+ // This error is caught, so it should NOT trigger onerror.
+ throw "foo";
+ } catch (ex) {
+ }
+ // This error is NOT caught, so it should trigger onerror.
+ throw "bar";
+ </script>
+ <script>
+ test(function() {assert_equals(error_count, 1)},
+ "correct number of calls to window.onerror");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/window-onerror-runtime-error.html b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/window-onerror-runtime-error.html
new file mode 100644
index 00000000000..1fdab521ae6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/scripting/processing-model-2/window-onerror-runtime-error.html
@@ -0,0 +1,43 @@
+<!doctype html>
+<html>
+ <head>
+ <title>window.onerror: runtime scripterrors</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!--
+
+ https://html.spec.whatwg.org/multipage/#runtime-script-errors
+ says what to do for uncaught runtime script errors, and just below
+ describes what to do when onerror is a Function.
+
+ -->
+ </head>
+ <body>
+
+ <div id="log"></div>
+ <script>
+ setup({allow_uncaught_exception:true});
+ var error_count = 0;
+ window.onerror = function(msg, url, lineno) {
+ ++error_count;
+ test(function() {assert_equals(url, window.location.href)},
+ "correct url passed to window.onerror");
+ test(function() {assert_equals(lineno, 36)},
+ "correct line number passed to window.onerror");
+ };
+ </script>
+ <script>
+ try {
+ // This error is caught, so it should NOT trigger onerror.
+ window.nonexistentproperty.oops();
+ } catch (ex) {
+ }
+ // This error is NOT caught, so it should trigger onerror.
+ window.nonexistentproperty.oops();
+ </script>
+ <script>
+ test(function() {assert_equals(error_count, 1)},
+ "correct number of calls to window.onerror");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/.gitkeep b/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-external-interface/.gitkeep b/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-external-interface/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-external-interface/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/.gitkeep b/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID.html b/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID.html
new file mode 100644
index 00000000000..1956a202cee
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>NavigatorID</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src=NavigatorID.js></script>
+<div id="log"></div>
+<script>
+run_test();
+</script>
diff --git a/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID.js b/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID.js
new file mode 100644
index 00000000000..a7e8b1dba8e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID.js
@@ -0,0 +1,50 @@
+function run_test() {
+ test(function() {
+ assert_equals(navigator.appCodeName, "Mozilla");
+ }, "appCodeName");
+
+ test(function() {
+ assert_equals(typeof navigator.appName, "string",
+ "navigator.appName should be a string");
+ }, "appName");
+
+ test(function() {
+ assert_equals(typeof navigator.appVersion, "string",
+ "navigator.appVersion should be a string");
+ }, "appVersion");
+
+ test(function() {
+ assert_equals(typeof navigator.platform, "string",
+ "navigator.platform should be a string");
+ }, "platform");
+
+ test(function() {
+ assert_equals(navigator.product, "Gecko");
+ }, "product");
+
+ test(function() {
+ assert_false(navigator.taintEnabled());
+ }, "taintEnabled");
+
+ test(function() {
+ assert_equals(typeof navigator.userAgent, "string",
+ "navigator.userAgent should be a string");
+ }, "userAgent type");
+
+ test(function() {
+ assert_equals(navigator.vendorSub, "");
+ }, "vendorSub");
+
+ async_test(function() {
+ var request = new XMLHttpRequest();
+ request.onload = this.step_func_done(function() {
+ assert_equals("user-agent: " + navigator.userAgent + "\n",
+ request.response,
+ "userAgent should return the value sent in the " +
+ "User-Agent header");
+ });
+ request.open("GET", "/XMLHttpRequest/resources/inspect-headers.py?" +
+ "filter_name=User-Agent");
+ request.send();
+ }, "userAgent value");
+}
diff --git a/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID.worker.js b/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID.worker.js
new file mode 100644
index 00000000000..9ba7defa1fb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/NavigatorID.worker.js
@@ -0,0 +1,4 @@
+importScripts("/resources/testharness.js")
+importScripts("NavigatorID.js")
+run_test();
+done();
diff --git a/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/contains.json b/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/contains.json
new file mode 100644
index 00000000000..441c24cec97
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/contains.json
@@ -0,0 +1,22 @@
+[
+ {
+ "id": "client-identification",
+ "original_id": "client-identification"
+ },
+ {
+ "id": "custom-handlers",
+ "original_id": "custom-handlers"
+ },
+ {
+ "id": "security-and-privacy",
+ "original_id": "security-and-privacy"
+ },
+ {
+ "id": "sample-handler-impl",
+ "original_id": "sample-handler-impl"
+ },
+ {
+ "id": "manually-releasing-the-storage-mutex",
+ "original_id": "manually-releasing-the-storage-mutex"
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/content.html b/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/content.html
new file mode 100644
index 00000000000..3d0dc9083e6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/content.html
@@ -0,0 +1,136 @@
+<!DOCTYPE html>
+<meta charset='utf-8'>
+<title>registerContentHandler()</title>
+
+<script src='/resources/testharness.js'></script>
+<script src='/resources/testharnessreport.js'></script>
+
+<noscript><p>Enable JavaScript and reload.</p></noscript>
+
+<p><strong>Note:</strong> If your browser limits the number of handler
+registration requests on a page, you might need to disable or significantly
+increase that limit for the tests below to run.</p>
+
+
+<div id='log'></div>
+
+<script>
+test(function () {
+ assert_idl_attribute(navigator, 'registerContentHandler');
+}, 'the registerContentHandler method should exist on the navigator object');
+
+/* Happy path */
+test(function () {
+ navigator.registerContentHandler('text/x-unknown-type', location.href + '/%s', 'foo');
+}, 'a handler with valid arguments should work');
+
+
+/* URL argument */
+test(function () {
+ navigator.registerContentHandler('text/x-unknown-type', '%s', 'foo');
+}, 'a relative URL should work');
+
+test(function () {
+ navigator.registerContentHandler('text/x-unknown-type', location.href + '#%s', 'foo');
+}, 'a URL with a fragment identifier should work');
+
+test(function () {
+ navigator.registerContentHandler('text/x-unknown-type', location.href + '?foo=%s', 'foo');
+}, 'a URL with a query string should work');
+
+test(function () {
+ navigator.registerContentHandler('text/x-unknown-type', location.href + '?foo=%s&bar', 'foo');
+}, 'a URL with a multi-argument query string should work');
+
+test(function () {
+ navigator.registerContentHandler('text/x-unknown-type', location.href + '/%s/bar/baz/', 'foo');
+}, 'a URL with the passed string as a directory name should work');
+
+test(function () {
+ navigator.registerContentHandler('text/x-unknown-type', location.href + '/%s/bar/baz/?foo=1337&bar#baz', 'foo');
+}, 'a URL with the passed string as a directory name followed by a query string and fragment identifier should work');
+
+test(function () {
+ navigator.registerContentHandler('text/x-unknown-type', location.href + '/%s/foo/%s/', 'foo');
+}, 'a URL with the passed string included twice should work');
+
+test(function () {
+ assert_throws('SYNTAX_ERR', function () { navigator.registerContentHandler('text/x-unknown-type', '', 'foo') } );
+}, 'an empty url argument should throw SYNTAX_ERR');
+
+test(function () {
+ assert_throws('SYNTAX_ERR', function () { navigator.registerContentHandler('text/x-unknown-type', 'http://%s.com', 'foo') } );
+}, '%s instead of domain name should throw SYNTAX_ERR');
+
+test(function () {
+ assert_throws('SYNTAX_ERR', function () { navigator.registerContentHandler('text/x-unknown-type', 'http://%s.example.com', 'foo') } );
+}, '%s instead of subdomain name should throw syntax_err');
+
+test(function () {
+ assert_throws('SYNTAX_ERR', function () { navigator.registerContentHandler('text/x-unknown-type', location.href + '', 'foo') } );
+}, 'a url argument without %s should throw SYNTAX_ERR');
+
+test(function () {
+ assert_throws('SYNTAX_ERR', function () { navigator.registerContentHandler('text/x-unknown-type', 'http://example.com', 'foo') } );
+}, 'a url argument pointing to a different domain name, without %s should throw SYNTAX_ERR');
+
+test(function () {
+ assert_throws('SYNTAX_ERR', function () { navigator.registerContentHandler('text/x-unknown-type', location.href + '/%', 'foo') } );
+}, 'a url argument without %s (but with %) should throw SYNTAX_ERR');
+
+test(function () {
+ assert_throws('SYNTAX_ERR', function () { navigator.registerContentHandler('text/x-unknown-type', location.href + '/%a', 'foo') } );
+}, 'a url argument without %s (but with %a) should throw SYNTAX_ERR');
+
+test(function () {
+ assert_throws('SECURITY_ERR', function () { navigator.registerContentHandler('text/x-unknown-type', 'http://example.com/%s', 'foo') } );
+}, 'a url argument pointing to a different domain name should throw SECURITY_ERR');
+
+test(function () {
+ assert_throws('SECURITY_ERR', function () { navigator.registerContentHandler('text/x-unknown-type', 'https://example.com/%s', 'foo') } );
+}, 'a url argument pointing to a different domain name should throw SECURITY_ERR (2)');
+
+test(function () {
+ assert_throws('SECURITY_ERR', function () { navigator.registerContentHandler('text/x-unknown-type', 'http://foobar.example.com/%s', 'foo') } );
+}, 'a url argument pointing to a different domain name should throw SECURITY_ERR (3)');
+
+/* Content type argument */
+
+/* The following MIME types are handled natively by the browser, and must not
+ * be possible to override. Note that this list only covers a few basic content
+ * types. Full lists of content types handled by each browser is found under
+ * /vendor/. */
+
+var blacklist = new Array(
+ 'image/jpeg',
+ 'text/html',
+ 'text/javascript',
+ 'text/plain');
+
+for (var bi=0, bl=blacklist.length; bi<bl; ++bi){
+
+ test(function () {
+ assert_throws('SECURITY_ERR', function () { navigator.registerContentHandler(blacklist[bi], location.href + '/%s', 'foo') } );
+ }, 'attempting to override the ' + blacklist[bi] + ' MIME type should throw SECURITY_ERR');
+
+}
+
+/* Overriding the following MIME types should be possible. */
+var whitelist = new Array('application/atom+xml', /* For feeds. */
+ 'application/rss+xml', /* For feeds. */
+ 'application/x-unrecognized', /* Arbitrary MIME types should be overridable. */
+ 'text/unrecognized',
+ 'foo/bar');
+
+for (var wi=0, wl=whitelist.length; wi<wl; ++wi){
+
+ test(function () {
+ navigator.registerContentHandler(whitelist[wi], location.href + '/%s', 'foo');
+ }, 'overriding the ' + whitelist[wi] + ' MIME type should work');
+
+}
+
+</script>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/content/001.xhtml b/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/content/001.xhtml
new file mode 100644
index 00000000000..a0d2fa15b8c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/content/001.xhtml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>isContentHandlerRegistered for new content type</title>
+<script src='/resources/testharness.js'></script>
+<script src='/resources/testharnessreport.js'></script>
+<script type="application/ecmascript">
+test(function() {
+ assert_equals(navigator.isContentHandlerRegistered('application/x-notRegisteredInOtherTCs-001', location.href.replace(/\/[^\/]*$/, "") + '/%s'), 'new');
+});
+</script>
+</head>
+<body>
+<div id="log"></div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/content/002.xhtml b/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/content/002.xhtml
new file mode 100644
index 00000000000..d5c2ff3e05a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/content/002.xhtml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>isContentHandlerRegistered for content type that is not yet accepted</title>
+<script src='/resources/testharness.js'></script>
+<script src='/resources/testharnessreport.js'></script>
+<script type="application/ecmascript">
+test(function() {
+ var ctype = 'application/x-notRegisteredInOtherTCs-002';
+ var url = location.href.replace(/\/[^\/]*$/, "") + "/%s";
+ navigator.registerContentHandler(ctype, url, 'test');
+ assert_equals(navigator.isContentHandlerRegistered(ctype, url), 'declined');
+});
+</script>
+</head>
+<body>
+<div id="log"></div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/content/003.xhtml b/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/content/003.xhtml
new file mode 100644
index 00000000000..92e7ca8f55e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/content/003.xhtml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Content type case insensitivity in isContentHandlerRegistered</title>
+<script src='/resources/testharness.js'></script>
+<script src='/resources/testharnessreport.js'></script>
+<script type="application/ecmascript">
+test(function() {
+ var ctype = 'application/x-notRegisteredInOtherTCs-003', url = location.href.replace(/\/[^\/]*$/, "") + '/%s';
+ navigator.registerContentHandler(ctype, url, 'test');
+ assert_equals(navigator.isContentHandlerRegistered(ctype.toUpperCase(), url), 'declined');
+});
+</script>
+</head>
+<body>
+<div id="log"></div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/content/004.xhtml b/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/content/004.xhtml
new file mode 100644
index 00000000000..a82f3506bce
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/content/004.xhtml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Non-matching url in isContentHandlerRegistered</title>
+<script src='/resources/testharness.js'></script>
+<script src='/resources/testharnessreport.js'></script>
+<script type="application/ecmascript">
+test(function() {
+ var ctype = 'application/x-notRegisteredInOtherTCs-004', url = location.href.replace(/\/[^\/]*$/, "") + '/%s';
+ navigator.registerContentHandler(ctype, url, 'test');
+ assert_equals(navigator.isContentHandlerRegistered(ctype, 'http://t/core/standards/registerhandler/%s'), 'new');
+});
+</script>
+</head>
+<body>
+<div id="log"></div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/content/005.xhtml b/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/content/005.xhtml
new file mode 100644
index 00000000000..b8c8b58d17f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/content/005.xhtml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Invalid characters in content type in isContentHandlerRegistered</title>
+<script src='/resources/testharness.js'></script>
+<script src='/resources/testharnessreport.js'></script>
+<script type="application/ecmascript">
+test(function() {
+ var ctype = 'application/x-nótRegísteredInOthérTCs-004', url = location.href.replace(/\/[^\/]*$/, "") + '/%s';
+ navigator.registerContentHandler(ctype, url, 'test');
+ assert_equals(navigator.isContentHandlerRegistered(ctype, 'http://t/core/standards/registerhandler/%s'), 'new');
+});
+</script>
+</head>
+<body>
+<div id="log"></div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/content/006.xhtml b/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/content/006.xhtml
new file mode 100644
index 00000000000..86d0cff6190
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/content/006.xhtml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Blacklisted content type and isContentHandlerRegistered</title>
+<script src='/resources/testharness.js'></script>
+<script src='/resources/testharnessreport.js'></script>
+<script type="application/ecmascript">
+test(function() {
+ var ctype = 'application/xhtml+xml', url = location.href.replace(/\/[^\/]*$/, "") + '/%s';
+ navigator.registerContentHandler(ctype, url, 'test');
+ assert_equals(navigator.isContentHandlerRegistered(ctype, 'http://t/core/standards/registerhandler/%s'), 'new');
+});
+</script>
+</head>
+<body>
+<div id="log"></div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/navigator-indexed.html b/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/navigator-indexed.html
new file mode 100644
index 00000000000..a971fe9d1c4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/navigator-indexed.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Test for lack of indexed getter on Navigator</title>
+<link rel="author" title="Ms2ger" href="mailto:Ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-navigator-object">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ assert_false("0" in window.navigator);
+ assert_equals(window.navigator[0], undefined);
+}, "window.navigator[0] should not exist");
+test(function() {
+ window.navigator[0] = "pass";
+ assert_true("0" in window.navigator);
+ assert_equals(window.navigator[0], "pass");
+}, "window.navigator[0] should be settable");
+test(function() {
+ assert_false("-1" in window.navigator);
+ assert_equals(window.navigator[-1], undefined);
+}, "window.navigator[-1] should not exist");
+test(function() {
+ window.navigator[-1] = "pass";
+ assert_true("-1" in window.navigator);
+ assert_equals(window.navigator[-1], "pass");
+}, "window.navigator[-1] should be settable");
+</script>
diff --git a/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol.html b/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol.html
new file mode 100644
index 00000000000..55b4ed71f47
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol.html
@@ -0,0 +1,214 @@
+<!DOCTYPE html>
+<meta charset='utf-8'>
+<title>registerProtocolHandler()</title>
+
+<script src='/resources/testharness.js'></script>
+<script src='/resources/testharnessreport.js'></script>
+
+<noscript><p>Enable JavaScript and reload.</p></noscript>
+
+<p><strong>Note:</strong> If your browser limits the number of handler
+registration requests on a page, you might need to disable or significantly
+increase that limit for the tests below to run.</p>
+
+<div id='log'></div>
+
+<script type='text/javascript'>
+
+test(function () {
+ assert_idl_attribute(navigator, 'registerProtocolHandler');
+}, 'the registerProtocolHandler method should exist on the navigator object');
+
+test(function () {
+ navigator.registerProtocolHandler('tel', location.href + '/%s', 'foo');
+}, 'a handler with valid arguments should work');
+
+
+/* URL argument */
+test(function () {
+ navigator.registerProtocolHandler('tel', '%s', 'foo');
+}, 'a relative URL should work');
+
+test(function () {
+ navigator.registerProtocolHandler('tel', location.href + '#%s', 'foo');
+}, 'a URL with a fragment identifier should work');
+
+test(function () {
+ navigator.registerProtocolHandler('tel', location.href + '?foo=%s', 'foo');
+}, 'a URL with a query string should work');
+
+test(function () {
+ navigator.registerProtocolHandler('tel', location.href + '?foo=%s&bar', 'foo');
+}, 'a URL with a multi-argument query string should work');
+
+test(function () {
+ navigator.registerProtocolHandler('tel', location.href + '/%s/bar/baz/', 'foo');
+}, 'a URL with the passed string as a directory name should work');
+
+test(function () {
+ navigator.registerProtocolHandler('tel', location.href + '/%s/bar/baz/?foo=1337&bar#baz', 'foo');
+}, 'a URL with the passed string as a directory name followed by a query string and fragment identifier should work');
+
+test(function () {
+ navigator.registerProtocolHandler('tel', location.href + '/%s/foo/%s/', 'foo');
+}, 'a URL with the passed string included twice should work');
+
+test(function () {
+ assert_throws('SYNTAX_ERR', function () { navigator.registerProtocolHandler('mailto', '', 'foo') } );
+}, 'an empty url argument should throw SYNTAX_ERR');
+
+test(function () {
+ assert_throws('SYNTAX_ERR', function () { navigator.registerProtocolHandler('mailto', 'http://%s.com', 'foo') } );
+}, '%s instead of domain name should throw SYNTAX_ERR');
+
+test(function () {
+ assert_throws('SYNTAX_ERR', function () { navigator.registerProtocolHandler('mailto', 'http://%s.example.com', 'foo') } );
+}, '%s instead of subdomain name should throw SYNTAX_ERR');
+
+test(function () {
+ assert_throws('SYNTAX_ERR', function () { navigator.registerProtocolHandler('mailto', location.href + '', 'foo') } );
+}, 'a url argument without %s should throw SYNTAX_ERR');
+
+test(function () {
+ assert_throws('SYNTAX_ERR', function () { navigator.registerProtocolHandler('mailto', 'http://example.com', 'foo') } );
+}, 'a url argument pointing to a different domain name, without %s should throw SYNTAX_ERR');
+
+test(function () {
+ assert_throws('SYNTAX_ERR', function () { navigator.registerProtocolHandler('mailto', location.href + '/%', 'foo') } );
+}, 'a url argument without %s (but with %) should throw SYNTAX_ERR');
+
+test(function () {
+ assert_throws('SYNTAX_ERR', function () { navigator.registerProtocolHandler('mailto', location.href + '/%a', 'foo') } );
+}, 'a url argument without %s (but with %a) should throw SYNTAX_ERR');
+
+test(function () {
+ assert_throws('SECURITY_ERR', function () { navigator.registerProtocolHandler('mailto', 'http://example.com/%s', 'foo') } );
+}, 'a url argument pointing to a different domain name should throw SECURITY_ERR');
+
+test(function () {
+ assert_throws('SECURITY_ERR', function () { navigator.registerProtocolHandler('mailto', 'https://example.com/%s', 'foo') } );
+}, 'a url argument pointing to a different domain name should throw SECURITY_ERR (2)');
+
+test(function () {
+ assert_throws('SECURITY_ERR', function () { navigator.registerProtocolHandler('mailto', 'http://foobar.example.com/%s', 'foo') } );
+}, 'a url argument pointing to a different domain name should throw SECURITY_ERR (3)');
+
+test(function () {
+ assert_throws('SECURITY_ERR', function () { navigator.registerProtocolHandler('mailto', 'mailto:%s@example.com', 'foo') } );
+}, 'looping handlers should throw SECURITY_ERR');
+
+test(function () {
+ assert_throws('SECURITY_ERR', function () { navigator.registerProtocolHandler('sms', 'tel:%s', 'foo') } );
+}, 'a url argument pointing to a non-http[s] scheme should throw SECURITY_ERR due to not being of the same origin');
+
+/* Protocol argument */
+test(function () {
+ assert_throws('SYNTAX_ERR', function () { navigator.registerProtocolHandler('unrecognized', location.href + '/%a', 'foo') } );
+}, 'a protocol argument containing an unrecognized scheme should throw SECURITY_ERR'); /* This is a whitelist, not a blacklist. */
+
+test(function () {
+ assert_throws('SYNTAX_ERR', function () { navigator.registerProtocolHandler('mailto:', location.href + '/%a', 'foo') } );
+}, 'a protocol argument containing : should throw SYNTAX_ERR');
+
+test(function () {
+ assert_throws('SYNTAX_ERR', function () { navigator.registerProtocolHandler('mailto://', location.href + '/%a', 'foo') } );
+}, 'a protocol argument containing :// should throw SYNTAX_ERR');
+
+test(function () {
+ assert_throws('SYNTAX_ERR', function () { navigator.registerProtocolHandler('http://', location.href + '/%a', 'foo') } );
+}, 'a protocol argument containing http:// should throw SYNTAX_ERR');
+
+test(function () {
+ assert_throws('SYNTAX_ERR', function () { navigator.registerProtocolHandler('mailto' + String.fromCharCode(0), location.href + '/%a', 'foo') } );
+}, 'a protocol argument containing a null character should throw SYNTAX_ERR');
+
+test(function () {
+ assert_throws('SYNTAX_ERR', function () { navigator.registerProtocolHandler('mailtoo' + String.fromCharCode(8), location.href + '/%a', 'foo') } );
+}, 'a protocol argument containing a backspace character should throw SYNTAX_ERR');
+
+test(function () {
+ assert_throws('SYNTAX_ERR', function () { navigator.registerProtocolHandler('mailto' + String.fromCharCode(10), location.href + '/%a', 'foo') } );
+}, 'a protocol argument containing a LF character should throw SYNTAX_ERR');
+
+test(function () {
+ assert_throws('SYNTAX_ERR', function () { navigator.registerProtocolHandler('mаilto', location.href + '/%a', 'foo') } );
+}, 'a protocol argument containing non-alphanumeric characters (like a cyrillic “а”) should throw SYNTAX_ERR');
+
+test(function () {
+ navigator.registerProtocolHandler('TEL', location.href + '/%s', 'foo');
+}, 'a protocol argument of “TEL” should be equivalent to “tel”');
+
+test(function () {
+ navigator.registerProtocolHandler('teL', location.href + '/%s', 'foo');
+}, 'a protocol argument of “teL” should be equivalent to “tel”');
+
+
+/* Overriding any of the following protocols must never be allowed. That would
+ * break the browser. */
+var blacklist = new Array(
+ 'about',
+ 'attachment',
+ 'blob',
+ 'chrome',
+ 'cid',
+ 'data',
+ 'file',
+ 'ftp',
+ 'http',
+ 'https',
+ 'javascript',
+ 'livescript',
+ 'mid',
+ 'mocha',
+ 'opera',
+ 'operamail',
+ 'res',
+ 'resource',
+ 'shttp',
+ 'tcl',
+ 'vbscript',
+ 'view-source',
+ 'ws',
+ 'wss',
+ 'wyciwyg');
+
+for ( var bi=0, bl=blacklist.length; bi<bl; ++bi ){
+
+ test(function () {
+ assert_throws('SECURITY_ERR', function () { navigator.registerProtocolHandler(blacklist[bi], location.href + '/%s', 'foo') } );
+ }, 'attempting to override the ' + blacklist[bi] + ' protocol should throw SECURITY_ERR');
+
+}
+
+/* The following protocols must be possible to override.
+ * We're just testing that the call goes through here. Whether or not they
+ * actually work as handlers is covered by the interactive tests. */
+var whitelist = new Array(
+ 'geo',
+ 'im',
+ 'irc',
+ 'ircs',
+ 'mailto',
+ 'mms',
+ 'news',
+ 'nntp',
+ 'sms',
+ 'smsto',
+ 'tel',
+ 'urn',
+ 'webcal',
+ 'wtai',
+ 'xmpp');
+
+for ( var wi=0, wl=whitelist.length; wi<wl; ++wi ){
+
+ test(function () {
+ navigator.registerProtocolHandler(whitelist[wi], location.href + '/%s', 'foo');
+ assert_true(true);
+ }, 'overriding the ' + whitelist[wi] + ' protocol should work');
+
+}
+</script>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol/001.xhtml b/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol/001.xhtml
new file mode 100644
index 00000000000..ce9ee1eb038
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol/001.xhtml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>isProtocolHandlerRegistered for new protocol</title>
+<script src='/resources/testharness.js'></script>
+<script src='/resources/testharnessreport.js'></script>
+<script type="application/ecmascript">
+test(function() {
+ var dir_uri = location.href.replace(/\/[^\/]*$/, "");
+ assert_equals(navigator.isProtocolHandlerRegistered('web+CustomProtocolOne', dir_uri + '/%s'), 'new');
+});
+</script>
+</head>
+<body>
+<div id="log"></div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol/002.xhtml b/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol/002.xhtml
new file mode 100644
index 00000000000..ce2c8dc0d60
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol/002.xhtml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>isProtocolHandlerRegistered for protocol that is not yet accepted</title>
+<script src='/resources/testharness.js'></script>
+<script src='/resources/testharnessreport.js'></script>
+<script type="application/ecmascript">
+test(function() {
+ var scheme = 'web+CustomProtocolTwo';
+ var url = location.href.replace(/\/[^\/]*$/, "") + '/%s';
+ navigator.registerProtocolHandler(scheme, url, 'Ignore dialog or decline it');
+ assert_equals(navigator.isProtocolHandlerRegistered(scheme, url), 'declined')
+})
+</script>
+</head>
+<body>
+<div id="log"></div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol/003.xhtml b/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol/003.xhtml
new file mode 100644
index 00000000000..035d5b9a64b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol/003.xhtml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Protocol case insensitivity in isProtocolHandlerRegistered</title>
+<script src='/resources/testharness.js'></script>
+<script src='/resources/testharnessreport.js'></script>
+<script type="application/ecmascript">
+test(function() {
+ var scheme = 'web+CustomProtocolTree', url = location.href.replace(/\/[^\/]*$/, "") + '/%s';
+ navigator.registerProtocolHandler(scheme, url, 'Ignore dialog or decline it');
+ assert_equals(navigator.isProtocolHandlerRegistered(scheme.toUpperCase(), url), 'declined');
+});
+</script>
+</head>
+<body>
+<div id="log"></div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol/004.xhtml b/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol/004.xhtml
new file mode 100644
index 00000000000..3fd14dd1294
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol/004.xhtml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Non-matching url in isProtocolHandlerRegistered</title>
+<script src='/resources/testharness.js'></script>
+<script src='/resources/testharnessreport.js'></script>
+<script type="application/ecmascript">
+test(function() {
+ var scheme = 'web+CustomProtocolFour', url = location.href.replace(/\/[^\/]*$/, "") + '/%s';
+ navigator.registerProtocolHandler(scheme, url, 'Ignore dialog');
+ assert_equals(navigator.isProtocolHandlerRegistered(scheme, 'http://t/core/standards/registerhandler/%s'), 'new');
+});
+</script>
+</head>
+<body>
+<div id="log"></div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol/005.xhtml b/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol/005.xhtml
new file mode 100644
index 00000000000..894ff4a6a23
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol/005.xhtml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Invalid characters in protocol scheme and isProtocolHandlerRegistered</title>
+<script src='/resources/testharness.js'></script>
+<script src='/resources/testharnessreport.js'></script>
+<script type="application/ecmascript">
+test(function() {
+ var scheme = 'web+CústomPrótocolFíve', url = location.href.replace(/\/[^\/]*$/, "") + '/%s';
+ navigator.registerProtocolHandler(scheme, url, 'Ignore dialog or decline it');
+ assert_equals(navigator.isProtocolHandlerRegistered(scheme, url), 'new');
+});
+</script>
+</head>
+<body>
+<div id="log"></div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol/006.xhtml b/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol/006.xhtml
new file mode 100644
index 00000000000..7529a7eb2cb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol/006.xhtml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Scheme outside white list and isProtocolHandlerRegistered</title>
+<script src='/resources/testharness.js'></script>
+<script src='/resources/testharnessreport.js'></script>
+<script type="application/ecmascript">
+test(function() {
+ var dir_uri = location.href.replace(/\/[^\/]*$/, "");
+ var scheme = 'http', url = dir_uri + '/%s';
+ navigator.registerProtocolHandler(scheme, url, 'Ignore dialog or decline it');
+ assert_equals(navigator.isProtocolHandlerRegistered(scheme, url), 'new');
+});
+</script>
+</head>
+<body>
+<div id="log"></div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/html/webappapis/timers/.gitkeep b/tests/wpt/web-platform-tests/html/webappapis/timers/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/timers/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/webappapis/timers/evil-spec-example.html b/tests/wpt/web-platform-tests/html/webappapis/timers/evil-spec-example.html
new file mode 100644
index 00000000000..77a8746908d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/timers/evil-spec-example.html
@@ -0,0 +1,23 @@
+<!doctype html>
+<title>Interaction of setTimeout and WebIDL</title>
+<link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch">
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-windowtimers-settimeout">
+<link rel="help" href="https://heycam.github.io/webidl/#es-operations">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var t = async_test()
+function finishTest() {
+ assert_equals(log, "ONE TWO ")
+ t.done()
+}
+var log = '';
+function logger(s) { log += s + ' '; }
+
+setTimeout({ toString: function () {
+ setTimeout("logger('ONE')", 100);
+ return "logger('TWO'); t.step(finishTest)";
+} }, 100);
+</script>
diff --git a/tests/wpt/web-platform-tests/html/webappapis/user-prompts/.gitkeep b/tests/wpt/web-platform-tests/html/webappapis/user-prompts/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/user-prompts/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/webappapis/user-prompts/dialogs-implemented-using-separate-documents/.gitkeep b/tests/wpt/web-platform-tests/html/webappapis/user-prompts/dialogs-implemented-using-separate-documents/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/user-prompts/dialogs-implemented-using-separate-documents/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/webappapis/user-prompts/printing/.gitkeep b/tests/wpt/web-platform-tests/html/webappapis/user-prompts/printing/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/user-prompts/printing/.gitkeep
diff --git a/tests/wpt/web-platform-tests/html/webappapis/user-prompts/simple-dialogs/.gitkeep b/tests/wpt/web-platform-tests/html/webappapis/user-prompts/simple-dialogs/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/webappapis/user-prompts/simple-dialogs/.gitkeep
diff --git a/tests/wpt/web-platform-tests/http/content_length.html b/tests/wpt/web-platform-tests/http/content_length.html
new file mode 100644
index 00000000000..af8ea44eeef
--- /dev/null
+++ b/tests/wpt/web-platform-tests/http/content_length.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<!-- CAUTION: if updating this test also update the expected content-length in the .headers file -->
+<title>Content-Length Test</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+onload = function() {
+ assert_equals(document.body.textContent, "PASS");
+ done();
+}
+</script>
+<body>PASS
+but FAIL if this is in the body. \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/http/content_length.html.headers b/tests/wpt/web-platform-tests/http/content_length.html.headers
new file mode 100644
index 00000000000..385ea556d7a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/http/content_length.html.headers
@@ -0,0 +1 @@
+Content-Length: 373
diff --git a/tests/wpt/web-platform-tests/images/anim-gr.gif b/tests/wpt/web-platform-tests/images/anim-gr.gif
new file mode 100644
index 00000000000..45263e0afba
--- /dev/null
+++ b/tests/wpt/web-platform-tests/images/anim-gr.gif
Binary files differ
diff --git a/tests/wpt/web-platform-tests/images/anim-gr.png b/tests/wpt/web-platform-tests/images/anim-gr.png
new file mode 100644
index 00000000000..925e2efc9a9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/images/anim-gr.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/images/anim-poster-gr.png b/tests/wpt/web-platform-tests/images/anim-poster-gr.png
new file mode 100644
index 00000000000..6941207373e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/images/anim-poster-gr.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/images/background.png b/tests/wpt/web-platform-tests/images/background.png
new file mode 100644
index 00000000000..6db6c6b1b9d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/images/background.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/images/black-rectangle.png b/tests/wpt/web-platform-tests/images/black-rectangle.png
new file mode 100644
index 00000000000..a0bf1fec6e0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/images/black-rectangle.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/images/blue-area.png b/tests/wpt/web-platform-tests/images/blue-area.png
new file mode 100644
index 00000000000..570ae0f2bf7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/images/blue-area.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/images/blue-border.png b/tests/wpt/web-platform-tests/images/blue-border.png
new file mode 100644
index 00000000000..8f8e41c3d00
--- /dev/null
+++ b/tests/wpt/web-platform-tests/images/blue-border.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/images/blue.png b/tests/wpt/web-platform-tests/images/blue.png
new file mode 100644
index 00000000000..4498dd258a2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/images/blue.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/images/blue96x96.png b/tests/wpt/web-platform-tests/images/blue96x96.png
new file mode 100644
index 00000000000..820f8cace21
--- /dev/null
+++ b/tests/wpt/web-platform-tests/images/blue96x96.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/images/broken.png b/tests/wpt/web-platform-tests/images/broken.png
new file mode 100644
index 00000000000..f2581017b43
--- /dev/null
+++ b/tests/wpt/web-platform-tests/images/broken.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/images/canvas-line.png b/tests/wpt/web-platform-tests/images/canvas-line.png
new file mode 100644
index 00000000000..30f8f454056
--- /dev/null
+++ b/tests/wpt/web-platform-tests/images/canvas-line.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/images/fail.gif b/tests/wpt/web-platform-tests/images/fail.gif
new file mode 100644
index 00000000000..c4addcf0090
--- /dev/null
+++ b/tests/wpt/web-platform-tests/images/fail.gif
Binary files differ
diff --git a/tests/wpt/web-platform-tests/images/ggrr-256x256.png b/tests/wpt/web-platform-tests/images/ggrr-256x256.png
new file mode 100644
index 00000000000..0342e4a3842
--- /dev/null
+++ b/tests/wpt/web-platform-tests/images/ggrr-256x256.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/images/green-100x50.png b/tests/wpt/web-platform-tests/images/green-100x50.png
new file mode 100644
index 00000000000..2b7577d2689
--- /dev/null
+++ b/tests/wpt/web-platform-tests/images/green-100x50.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/images/green-16x16.png b/tests/wpt/web-platform-tests/images/green-16x16.png
new file mode 100644
index 00000000000..e19a3ffddd2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/images/green-16x16.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/images/green-1x1.png b/tests/wpt/web-platform-tests/images/green-1x1.png
new file mode 100644
index 00000000000..862d1dd10cc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/images/green-1x1.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/images/green-256x256.png b/tests/wpt/web-platform-tests/images/green-256x256.png
new file mode 100644
index 00000000000..b06945c3101
--- /dev/null
+++ b/tests/wpt/web-platform-tests/images/green-256x256.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/images/green-2x2.png b/tests/wpt/web-platform-tests/images/green-2x2.png
new file mode 100644
index 00000000000..adc059449c3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/images/green-2x2.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/images/green.png b/tests/wpt/web-platform-tests/images/green.png
new file mode 100644
index 00000000000..28a1faab377
--- /dev/null
+++ b/tests/wpt/web-platform-tests/images/green.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/images/green.svg b/tests/wpt/web-platform-tests/images/green.svg
new file mode 100644
index 00000000000..d91971f784b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/images/green.svg
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="100" height="50">
+ <rect fill="lime" width="100" height="50"/>
+</svg>
diff --git a/tests/wpt/web-platform-tests/images/grgr-256x256.png b/tests/wpt/web-platform-tests/images/grgr-256x256.png
new file mode 100644
index 00000000000..b8c7189d628
--- /dev/null
+++ b/tests/wpt/web-platform-tests/images/grgr-256x256.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/images/movie_300_frame_0.png b/tests/wpt/web-platform-tests/images/movie_300_frame_0.png
new file mode 100644
index 00000000000..b7128250938
--- /dev/null
+++ b/tests/wpt/web-platform-tests/images/movie_300_frame_0.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/images/red-16x16.png b/tests/wpt/web-platform-tests/images/red-16x16.png
new file mode 100644
index 00000000000..9038fef784d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/images/red-16x16.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/images/red-zeroheight.svg b/tests/wpt/web-platform-tests/images/red-zeroheight.svg
new file mode 100644
index 00000000000..de378d44691
--- /dev/null
+++ b/tests/wpt/web-platform-tests/images/red-zeroheight.svg
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="100" height="0">
+ <rect fill="red" width="100" height="100"/>
+</svg>
diff --git a/tests/wpt/web-platform-tests/images/red-zerosize.svg b/tests/wpt/web-platform-tests/images/red-zerosize.svg
new file mode 100644
index 00000000000..dcd33172fca
--- /dev/null
+++ b/tests/wpt/web-platform-tests/images/red-zerosize.svg
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="0" height="0">
+ <rect fill="red" width="100" height="100"/>
+</svg>
diff --git a/tests/wpt/web-platform-tests/images/red-zerowidth.svg b/tests/wpt/web-platform-tests/images/red-zerowidth.svg
new file mode 100644
index 00000000000..66cff813f2a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/images/red-zerowidth.svg
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="0" height="100">
+ <rect fill="red" width="100" height="100"/>
+</svg>
diff --git a/tests/wpt/web-platform-tests/images/red.png b/tests/wpt/web-platform-tests/images/red.png
new file mode 100644
index 00000000000..a6e195d59cc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/images/red.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/images/redtransparent.png b/tests/wpt/web-platform-tests/images/redtransparent.png
new file mode 100644
index 00000000000..75da08c3d66
--- /dev/null
+++ b/tests/wpt/web-platform-tests/images/redtransparent.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/images/rgrg-256x256.png b/tests/wpt/web-platform-tests/images/rgrg-256x256.png
new file mode 100644
index 00000000000..e6fba3daa5d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/images/rgrg-256x256.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/images/rrgg-256x256.png b/tests/wpt/web-platform-tests/images/rrgg-256x256.png
new file mode 100644
index 00000000000..7f635156547
--- /dev/null
+++ b/tests/wpt/web-platform-tests/images/rrgg-256x256.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/images/smiley.png b/tests/wpt/web-platform-tests/images/smiley.png
new file mode 100644
index 00000000000..640a2238c76
--- /dev/null
+++ b/tests/wpt/web-platform-tests/images/smiley.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/images/threecolors.png b/tests/wpt/web-platform-tests/images/threecolors.png
new file mode 100644
index 00000000000..0643e6e70bd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/images/threecolors.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/images/transparent.png b/tests/wpt/web-platform-tests/images/transparent.png
new file mode 100644
index 00000000000..2b498699a80
--- /dev/null
+++ b/tests/wpt/web-platform-tests/images/transparent.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/images/transparent50.png b/tests/wpt/web-platform-tests/images/transparent50.png
new file mode 100644
index 00000000000..55f8e69325b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/images/transparent50.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/images/yellow.png b/tests/wpt/web-platform-tests/images/yellow.png
new file mode 100644
index 00000000000..51e8aaf38c1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/images/yellow.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/images/yellow75.png b/tests/wpt/web-platform-tests/images/yellow75.png
new file mode 100644
index 00000000000..2bb82c98347
--- /dev/null
+++ b/tests/wpt/web-platform-tests/images/yellow75.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/infrastructure/failing-test.html b/tests/wpt/web-platform-tests/infrastructure/failing-test.html
new file mode 100644
index 00000000000..249099c06f6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/infrastructure/failing-test.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Failing test</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+test(function() {
+ assert_unreached("Expected failure");
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/js/builtins/Array.DefineOwnProperty.html b/tests/wpt/web-platform-tests/js/builtins/Array.DefineOwnProperty.html
new file mode 100644
index 00000000000..40ed00a4c71
--- /dev/null
+++ b/tests/wpt/web-platform-tests/js/builtins/Array.DefineOwnProperty.html
@@ -0,0 +1,24 @@
+<!doctype html>
+<title>Array.[[DefineOwnProperty]]</title>
+<link rel=author href=mailto:Ms2ger@gmail.com title=Ms2ger>
+<link rel=help href=http://es5.github.com/#x15.4.5.1>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function() {
+ var arr = new Array;
+ assert_equals(arr.length, 0);
+
+ var called = 0;
+ Object.defineProperty(arr, 0, { get: function() { ++called; return 7 } });
+ assert_equals(arr.length, 1);
+ assert_equals(called, 0);
+
+ assert_equals(arr[0], 7);
+ assert_equals(called, 1);
+
+ assert_equals(String(arr), "7");
+ assert_equals(called, 2);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/js/builtins/Array.prototype.join-order.html b/tests/wpt/web-platform-tests/js/builtins/Array.prototype.join-order.html
new file mode 100644
index 00000000000..e5589803a68
--- /dev/null
+++ b/tests/wpt/web-platform-tests/js/builtins/Array.prototype.join-order.html
@@ -0,0 +1,86 @@
+<!doctype html>
+<title>Array.prototype.join</title>
+<link rel=author href=mailto:Ms2ger@gmail.com title=Ms2ger>
+<link rel=help href=http://es5.github.com/#x15.4.4.5>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+
+<div id=log></div>
+<script>
+var test_error = { name: "test" };
+
+// Step 1.
+test(function() {
+ assert_throws(new TypeError(), function() {
+ [].join.call(null, {
+ toString: function() { assert_unreached(); }
+ });
+ });
+ assert_throws(new TypeError(), function() {
+ [].join.call(undefined, {
+ toString: function() { assert_unreached(); }
+ });
+ });
+}, "Array.prototype.join must call ToObject before looking at the separator argument.")
+
+var generateTest = function(throwing_getter, getter_name) {
+ var throwing_object = {};
+ var interfaces = [Boolean, Number];
+
+ var objects = interfaces.map(function(p) { return p.prototype; });
+ objects.push(throwing_object);
+ objects.forEach(function(object) {
+ Object.defineProperty(object, "length", {
+ get: throwing_getter,
+ configurable: true
+ });
+ });
+
+ [throwing_object, true, false, 0, 1, Math.PI].forEach(function(that) {
+ test(function() {
+ assert_throws(test_error, function() {
+ [].join.call(that, ",");
+ });
+ }, "Array.prototype.join must forward the exception from the this " +
+ "object's length property with this=" + format_value(that) + " and " +
+ "getter " + getter_name + ".")
+ test(function() {
+ assert_throws(test_error, function() {
+ [].join.call(that, {
+ toString: function() { assert_unreached(); }
+ });
+ });
+ }, "Array.prototype.join must get the this object's length property " +
+ "before looking at the separator argument with this=" +
+ format_value(that) + " and getter " + getter_name + ".")
+ });
+ interfaces.forEach(function(iface) {
+ delete iface.length;
+ });
+}
+
+// Step 2.
+test(function() {
+ generateTest(function() { throw test_error; }, "function");
+}, "Step 2.");
+
+// Step 3.
+test(function() {
+ generateTest(function() {
+ return {
+ valueOf: function() { throw test_error; }
+ };
+ }, "valueOf");
+ generateTest(function() {
+ return {
+ toString: function() { throw test_error; }
+ };
+ }, "toString");
+ generateTest(function() {
+ return {
+ valueOf: function() { throw test_error; },
+ toString: function() { assert_unreached("toString should not be invoked if valueOf exists"); }
+ };
+ }, "valueOf and toString");
+}, "Step 3.");
+</script>
diff --git a/tests/wpt/web-platform-tests/js/builtins/Math.max.html b/tests/wpt/web-platform-tests/js/builtins/Math.max.html
new file mode 100644
index 00000000000..a4a6ae27c80
--- /dev/null
+++ b/tests/wpt/web-platform-tests/js/builtins/Math.max.html
@@ -0,0 +1,13 @@
+<!doctype html>
+<title>Math.max</title>
+<link rel=author href=mailto:Ms2ger@gmail.com title=Ms2ger>
+<link rel=help href=http://es5.github.com/#x15.8.2>
+<link rel=help href=http://es5.github.com/#x15.8.2.11>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+
+<div id=log></div>
+<script src=Math.maxmin.js></script>
+<script>
+testMathMaxMin("max");
+</script>
diff --git a/tests/wpt/web-platform-tests/js/builtins/Math.maxmin.js b/tests/wpt/web-platform-tests/js/builtins/Math.maxmin.js
new file mode 100644
index 00000000000..a414465fb42
--- /dev/null
+++ b/tests/wpt/web-platform-tests/js/builtins/Math.maxmin.js
@@ -0,0 +1,57 @@
+function testMathMaxMin(aFun) {
+ var test_error = { name: "test" };
+ test(function() {
+ assert_throws(test_error, function() {
+ Math[aFun](NaN, {
+ valueOf: function() {
+ throw test_error;
+ }
+ });
+ });
+ }, "ToNumber should be called on all arguments: NaN.");
+ test(function() {
+ assert_throws(test_error, function() {
+ Math[aFun](-Infinity, {
+ valueOf: function() {
+ throw test_error;
+ }
+ });
+ });
+ }, "ToNumber should be called on all arguments: -Infinity.");
+ test(function() {
+ assert_throws(test_error, function() {
+ Math[aFun](Infinity, {
+ valueOf: function() {
+ throw test_error;
+ }
+ });
+ });
+ }, "ToNumber should be called on all arguments: Infinity.");
+ test(function() {
+ assert_throws(test_error, function() {
+ Math[aFun]({
+ valueOf: function() {
+ throw test_error;
+ }
+ },
+ {
+ valueOf: function() {
+ throw 7;
+ }
+ });
+ });
+ }, "ToNumber should be called left to right.");
+ test(function() {
+ assert_equals(Math[aFun]("1"), 1);
+ }, "Should return a number.");
+ test(function() {
+ var expected = {
+ "max": 0,
+ "min": -0
+ }
+ assert_equals(Math[aFun](0, -0), expected[aFun]);
+ assert_equals(Math[aFun](-0, 0), expected[aFun]);
+ assert_equals(Math[aFun](0, 0), 0);
+ assert_equals(Math[aFun](-0, -0), -0);
+ }, "Should handle negative zero correctly.");
+}
diff --git a/tests/wpt/web-platform-tests/js/builtins/Math.min.html b/tests/wpt/web-platform-tests/js/builtins/Math.min.html
new file mode 100644
index 00000000000..4ae71b9d76c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/js/builtins/Math.min.html
@@ -0,0 +1,13 @@
+<!doctype html>
+<title>Math.min</title>
+<link rel=author href=mailto:Ms2ger@gmail.com title=Ms2ger>
+<link rel=help href=http://es5.github.com/#x15.8.2>
+<link rel=help href=http://es5.github.com/#x15.8.2.12>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+
+<div id=log></div>
+<script src=Math.maxmin.js></script>
+<script>
+testMathMaxMin("min");
+</script>
diff --git a/tests/wpt/web-platform-tests/js/builtins/Object.prototype.freeze.html b/tests/wpt/web-platform-tests/js/builtins/Object.prototype.freeze.html
new file mode 100644
index 00000000000..47a50b33d77
--- /dev/null
+++ b/tests/wpt/web-platform-tests/js/builtins/Object.prototype.freeze.html
@@ -0,0 +1,52 @@
+<!doctype html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>Object.freeze</title>
+<link rel="author" title="Masaya Iseki" href="mailto:iseki.m.aa@gmail.com">
+<link rel="help" href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.freeze">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+test(function() {
+ [{}, []].forEach(function(that) {
+ assert_false(Object.isFrozen(that));
+ that.prop = 'exist';
+
+ Object.freeze(that);
+ assert_false(Object.isExtensible(that));
+ assert_true(Object.isSealed(that));
+ assert_true(Object.isFrozen(that));
+
+ that.extension = 'This property should not be added';
+ assert_equals(undefined, that.extension, 'Confirm to prevent adding property.');
+
+ that.prop = 'changed';
+ assert_equals('exist', that.prop,
+ 'Confirm to prevent changing a property value.');
+
+ delete that.prop;
+ assert_equals('exist', that.prop, 'Confirm to prevent deleting a property.');
+ });
+});
+
+
+test(function() {
+ ['foo', 42, null, undefined].forEach(function(that) {
+ assert_throws(new TypeError(),
+ function() { Object.freeze(that) });
+ });
+});
+</script>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/js/builtins/Object.prototype.hasOwnProperty-order.html b/tests/wpt/web-platform-tests/js/builtins/Object.prototype.hasOwnProperty-order.html
new file mode 100644
index 00000000000..e67cff61297
--- /dev/null
+++ b/tests/wpt/web-platform-tests/js/builtins/Object.prototype.hasOwnProperty-order.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<title>Object.prototype.hasOwnProperty</title>
+<link rel=author href=mailto:Ms2ger@gmail.com title=Ms2ger>
+<link rel=help href=http://es5.github.com/#x15.4.4.5>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+
+<div id=log></div>
+<script>
+var test_error = { name: "test" };
+
+test(function() {
+ [null, undefined, {}].forEach(function(that) {
+ test(function() {
+ assert_throws(test_error, function() {
+ ({}).hasOwnProperty.call(that, { toString: function() { throw test_error; } });
+ });
+ });
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/js/builtins/Object.prototype.hasOwnProperty-prototype-chain.html b/tests/wpt/web-platform-tests/js/builtins/Object.prototype.hasOwnProperty-prototype-chain.html
new file mode 100644
index 00000000000..402f1ae6fd5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/js/builtins/Object.prototype.hasOwnProperty-prototype-chain.html
@@ -0,0 +1,44 @@
+<!doctype html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>Object.prototype.hasOwnProperty: Check prototype chain</title>
+<link rel="author" title="Masaya Iseki" href="mailto:iseki.m.aa@gmail.com">
+<link rel="help" href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.hasownproperty">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+test(function() {
+ [{}, []].forEach(function(that) {
+ that.prop = 'exists';
+ assert_true(that.hasOwnProperty('prop'));
+ assert_true('hasOwnProperty' in that);
+ assert_false(that.hasOwnProperty('hasOwnProperty'));
+ });
+});
+
+test(function() {
+ ['foo', 42].forEach(function(that) {
+ assert_false(that.hasOwnProperty('hasOwnProperty'));
+ });
+});
+
+test(function() {
+ [null, undefined].forEach(function(that) {
+ assert_throws(new TypeError(),
+ function() { that.hasOwnProperty('hasOwnProperty'); });
+ });
+});
+</script>
+
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/js/builtins/Object.prototype.preventExtensions.html b/tests/wpt/web-platform-tests/js/builtins/Object.prototype.preventExtensions.html
new file mode 100644
index 00000000000..36ac328d2e5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/js/builtins/Object.prototype.preventExtensions.html
@@ -0,0 +1,51 @@
+<!doctype html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>Object.preventExtensions</title>
+<link rel="author" title="Masaya Iseki" href="mailto:iseki.m.aa@gmail.com">
+<link rel="help" href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.preventextensions">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+test(function() {
+ [{}, []].forEach(function(that){
+ assert_true(Object.isExtensible(that));
+ that.prop = 'exist';
+
+ Object.preventExtensions(that);
+ assert_false(Object.isExtensible(that));
+ assert_false(Object.isFrozen(that));
+ assert_false(Object.isSealed(that));
+
+ that.extension = 'This property should not be added';
+ assert_equals(undefined, that.extension, 'Confirm to prevent adding property.');
+
+ that.prop = 'changed';
+ assert_equals('changed', that.prop,
+ 'Confirm to be able to change a property value.');
+
+ delete that.prop;
+ assert_equals(undefined, that.prop, 'Confirm to be able to delete a property.');
+ });
+});
+
+test(function() {
+ ['foo', 42, null, undefined].forEach(function(that) {
+ assert_throws(new TypeError(),
+ function() { Object.preventExtensions(that) });
+ });
+});
+</script>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/js/builtins/Object.prototype.seal.html b/tests/wpt/web-platform-tests/js/builtins/Object.prototype.seal.html
new file mode 100644
index 00000000000..446d627865c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/js/builtins/Object.prototype.seal.html
@@ -0,0 +1,51 @@
+<!doctype html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>Object.seal</title>
+<link rel="author" title="Masaya Iseki" href="mailto:iseki.m.aa@gmail.com">
+<link rel="help" href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.seal">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+test(function() {
+ [{}, []].forEach(function(that) {
+ assert_false(Object.isSealed(that));
+ that.prop = 'exist';
+
+ Object.seal(that);
+ assert_false(Object.isExtensible(that));
+ assert_true(Object.isSealed(that));
+ assert_false(Object.isFrozen(that));
+
+ that.extension = 'This property should not be added';
+ assert_equals(undefined, that.extension, 'Confirm to prevent adding property.');
+
+ that.prop = 'changed';
+ assert_equals('changed', that.prop,
+ 'Confirm to be able to change a property value.');
+
+ delete that.prop;
+ assert_equals('changed', that.prop, 'Confirm to prevent deleting a property.');
+ });
+});
+
+test(function() {
+ ['foo', 42, null, undefined].forEach(function(that) {
+ assert_throws(new TypeError(),
+ function() { Object.seal(that) });
+ });
+});
+</script>
+
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/js/builtins/WeakMap.prototype-properties.html b/tests/wpt/web-platform-tests/js/builtins/WeakMap.prototype-properties.html
new file mode 100644
index 00000000000..c312a83054c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/js/builtins/WeakMap.prototype-properties.html
@@ -0,0 +1,122 @@
+<!doctype html>
+<title>WeakMap.prototype</title>
+<link rel=author href=mailto:Ms2ger@gmail.com title=Ms2ger>
+<link rel=help href=https://people.mozilla.org/~jorendorff/es6-draft.html#sec-properties-of-the-weakmap-prototype-object>
+<link rel=help href=https://people.mozilla.org/~jorendorff/es6-draft.html#sec-functioninitialize>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+function assert_propdesc(obj, prop, Writable, Enumerable, Configurable) {
+ var propdesc = Object.getOwnPropertyDescriptor(obj, prop);
+ assert_equals(typeof propdesc, "object");
+ assert_equals(propdesc.writable, Writable, "[[Writable]]");
+ assert_equals(propdesc.enumerable, Enumerable, "[[Enumerable]]");
+ assert_equals(propdesc.configurable, Configurable, "[[Configurable]]");
+}
+
+function test_length(fun, expected) {
+ test(function() {
+ assert_propdesc(WeakMap.prototype[fun], "length", false, false, true);
+ assert_equals(WeakMap.prototype[fun].length, expected);
+ }, "WeakMap.prototype." + fun + ".length")
+}
+
+function test_thisval(fun, args) {
+ // Step 1-2
+ test(function() {
+ assert_throws(new TypeError(), function() {
+ WeakMap.prototype[fun].apply(null, args);
+ });
+ assert_throws(new TypeError(), function() {
+ WeakMap.prototype[fun].apply(undefined, args);
+ });
+ }, "WeakMap.prototype." + fun + ": ToObject on this")
+ // Step 3
+ test(function() {
+ assert_throws(new TypeError(), function() {
+ WeakMap.prototype[fun].apply({}, args);
+ });
+ }, "WeakMap.prototype." + fun + ": this has no [[WeakMapData]] internal property")
+}
+
+// In every case, the length property of a built-in Function object described
+// in this clause has the attributes { [[Writable]]: false, [[Enumerable]]:
+// false, [[Configurable]]: false }. Every other property described in this
+// clause has the attributes { [[Writable]]: true, [[Enumerable]]: false,
+// [[Configurable]]: true } unless otherwise specified.
+
+test(function() {
+ assert_equals(Object.getPrototypeOf(WeakMap.prototype), Object.prototype);
+}, "The value of the [[Prototype]] internal property of the WeakMap prototype object is the standard built-in Object prototype object (15.2.4).")
+
+// 15.15.5.1 WeakMap.prototype.constructor
+test(function() {
+ assert_equals(WeakMap.prototype.constructor, WeakMap);
+ assert_propdesc(WeakMap.prototype, "constructor", true, false, true);
+}, "The initial value of WeakMap.prototype.constructor is the built-in WeakMap constructor.")
+
+// 15.15.5.2 WeakMap.prototype.clear ()
+test(function() {
+ assert_propdesc(WeakMap.prototype, "clear", true, false, true);
+ test_length("clear", 0);
+ // Step 1-3
+ test_thisval("clear", null);
+ // Step 4-5
+ test(function() {
+ var wm = new WeakMap();
+ var key = {};
+ wm.set(key, "fail");
+ assert_true(wm.has(key));
+ var res = wm.clear();
+ assert_equals(res, undefined);
+ assert_false(wm.has(key));
+ }, "WeakMap.prototype.clear: basic functionality");
+}, "WeakMap.prototype.clear")
+
+// 15.15.5.3 WeakMap.prototype.delete ( key )
+test(function() {
+ assert_propdesc(WeakMap.prototype, "delete", true, false, true);
+ test_length("delete", 1);
+ // Step 1-3
+ test_thisval("delete", [{}]);
+}, "WeakMap.prototype.delete")
+
+// 15.15.5.4 WeakMap.prototype.get ( key )
+test(function() {
+ assert_propdesc(WeakMap.prototype, "get", true, false, true);
+ test_length("get", 1);
+ // Step 1-3
+ test_thisval("get", [{}]);
+
+ // Step 8
+ test(function() {
+ var wm = new WeakMap();
+ var key = {};
+ var res = wm.get({}, {});
+ assert_equals(res, undefined);
+ }, "WeakMap.prototype.get: return undefined");
+}, "WeakMap.prototype.get")
+
+// 15.14.5.5 Map.prototype.has ( key )
+test(function() {
+ assert_propdesc(WeakMap.prototype, "has", true, false, true);
+ test_length("has", 1);
+ // Step 1-3
+ test_thisval("has", [{}]);
+}, "WeakMap.prototype.has")
+
+// 15.14.5.6 Map.prototype.set ( key , value )
+test(function() {
+ assert_propdesc(WeakMap.prototype, "set", true, false, true);
+ test_length("set", 2);
+ // Step 1-3
+ test_thisval("set", [{}, {}]);
+}, "WeakMap.prototype.set")
+
+// 15.15.5.7 Map.prototype.@@toStringTag
+test(function() {
+ assert_class_string(new WeakMap(), "WeakMap");
+ assert_class_string(WeakMap.prototype, "WeakMap");
+}, "WeakMap.prototype.@@toStringTag")
+</script>
diff --git a/tests/wpt/web-platform-tests/lint b/tests/wpt/web-platform-tests/lint
new file mode 100755
index 00000000000..97baabcc6e7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/lint
@@ -0,0 +1,6 @@
+#!/usr/bin/env python
+import sys
+
+from tools.lint import lint
+
+sys.exit(0 if lint.main() == 0 else 1)
diff --git a/tests/wpt/web-platform-tests/manifest b/tests/wpt/web-platform-tests/manifest
new file mode 100755
index 00000000000..f5b0c9bade7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/manifest
@@ -0,0 +1,6 @@
+#!/usr/bin/env python
+import sys
+
+from tools.manifest import update
+
+update.main()
diff --git a/tests/wpt/web-platform-tests/media-source/SourceBuffer-abort-readyState.html b/tests/wpt/web-platform-tests/media-source/SourceBuffer-abort-readyState.html
new file mode 100644
index 00000000000..515031687ae
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/SourceBuffer-abort-readyState.html
@@ -0,0 +1,71 @@
+<!doctype html>
+<html>
+<head>
+ <meta charset='utf-8'>
+ <title>SourceBuffer#abort() when readyState attribute is not in the "open"</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id="log"></div>
+
+<script>
+var contents = {'/media/white.webm': 'video/webm; codecs="vorbis,vp8"',
+ '/media/white.mp4' : 'video/mp4'};
+
+//check the browser supports the MIME used in this test
+function isTypeSupported(mime) {
+ if(!MediaSource.isTypeSupported(mime)) {
+ this.step(function() {
+ assert_unreached("Browser doesn't support the MIME used in this test: " + mime);
+ });
+ this.done();
+ return false;
+ }
+ return true;
+}
+function GET(url, processBody) {
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', url, true);
+ xhr.responseType = 'arraybuffer';
+ xhr.send();
+ xhr.onload = function(e) {
+ if (xhr.status != 200) {
+ alert("Unexpected status code " + xhr.status + " for " + url);
+ return false;
+ }
+ processBody(new Uint8Array(xhr.response));
+ };
+}
+function mediaTest(file, mime) {
+ async_test(function(t) {
+ if(!isTypeSupported.bind(t)(mime)) {
+ return;
+ }
+ GET(file, function(data) {
+ var mediaSource = new MediaSource();
+ var sourceBuffer = null;
+ mediaSource.addEventListener('sourceopen', function(e) {
+ sourceBuffer = mediaSource.addSourceBuffer(mime);
+ mediaSource.endOfStream();
+ assert_equals(mediaSource.readyState, 'ended',
+ 'mediaSource.readyState is "ended" after endOfStream()');
+ });
+ mediaSource.addEventListener('sourceended', t.step_func_done(function(e) {
+ assert_throws({name: 'InvalidStateError'}, function() {
+ sourceBuffer.abort();
+ });
+ }));
+ var video = document.createElement('video');
+ video.src = window.URL.createObjectURL(mediaSource);
+ });
+ }, 'SourceBuffer#abort() (' + mime + ') : If the readyState attribute ' +
+ 'of the parent media source is not in the "open" state then throw ' +
+ 'an INVALID_STATE_ERR exception and abort these steps.');
+}
+for(var file in contents) {
+ mediaTest(file, contents[file]);
+}
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/media-source/SourceBuffer-abort-removed.html b/tests/wpt/web-platform-tests/media-source/SourceBuffer-abort-removed.html
new file mode 100644
index 00000000000..00d65c133b0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/SourceBuffer-abort-removed.html
@@ -0,0 +1,52 @@
+<!doctype html>
+<html>
+<head>
+ <meta charset='utf-8'>
+ <title>SourceBuffer#abort() for already removed buffer from parent media source</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id="log"></div>
+
+<script>
+var mimes = ['video/webm; codecs="vorbis,vp8"', 'video/mp4'];
+
+//check the browser supports the MIME used in this test
+function isTypeSupported(mime) {
+ if(!MediaSource.isTypeSupported(mime)) {
+ this.step(function() {
+ assert_unreached("Browser doesn't support the MIME used in this test: " + mime);
+ });
+ this.done();
+ return false;
+ }
+ return true;
+}
+function mediaTest(mime) {
+ async_test(function(t) {
+ if(!isTypeSupported.bind(t)(mime)) {
+ return;
+ }
+ var mediaSource = new MediaSource();
+ mediaSource.addEventListener('sourceopen', t.step_func_done(function(e) {
+ var sourceBuffer = mediaSource.addSourceBuffer(mime);
+ mediaSource.removeSourceBuffer(sourceBuffer);
+ assert_throws({name: 'InvalidStateError'},
+ function() {
+ sourceBuffer.abort();
+ },
+ 'SourceBuffer#abort() after removing the SourceBuffer object');
+ }), false);
+ var video = document.createElement('video');
+ video.src = window.URL.createObjectURL(mediaSource);
+ }, 'SourceBuffer#abort (' + mime + ') : ' +
+ 'if this object has been removed from the sourceBuffers attribute of the parent media source, ' +
+ 'then throw an INVALID_STATE_ERR exception and abort these steps.');
+}
+mimes.forEach(function(mime) {
+ mediaTest(mime);
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/media-source/SourceBuffer-abort-updating.html b/tests/wpt/web-platform-tests/media-source/SourceBuffer-abort-updating.html
new file mode 100644
index 00000000000..1132d14663e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/SourceBuffer-abort-updating.html
@@ -0,0 +1,92 @@
+<!doctype html>
+<html>
+<head>
+ <meta charset='utf-8'>
+ <title>Check SourceBuffer#abort() when the updating attribute is true</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id="log"></div>
+
+<script>
+var contents = {'/media/white.webm': 'video/webm; codecs="vorbis,vp8"',
+ '/media/white.mp4' : 'video/mp4'};
+
+function GET(url, processBody) {
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', url, true);
+ xhr.responseType = 'arraybuffer';
+ xhr.send();
+ xhr.onload = function(e) {
+ if (xhr.status != 200) {
+ alert("Unexpected status code " + xhr.status + " for " + url);
+ return false;
+ }
+ processBody(new Uint8Array(xhr.response));
+ };
+}
+//check the browser supports the MIME used in this test
+function isTypeSupported(mime) {
+ if(!MediaSource.isTypeSupported(mime)) {
+ this.step(function() {
+ assert_unreached("Browser doesn't support the MIME used in this test: " + mime);
+ });
+ this.done();
+ return false;
+ }
+ return true;
+}
+function mediaTest(file, mime) {
+ async_test(function(t) {
+ if(!isTypeSupported.bind(t)(mime)) {
+ return;
+ }
+ GET(file, function(data) {
+ var mediaSource = new MediaSource();
+ var num_updateend = 0;
+ var events = [];
+ mediaSource.addEventListener('sourceopen', t.step_func(function(e) {
+ var sourceBuffer = mediaSource.addSourceBuffer(mime);
+ assert_equals(sourceBuffer.updating, false);
+ sourceBuffer.addEventListener('updatestart', t.step_func(function(e) {
+ events.push('updatestart');
+ //abort when sourceBuffer#updating is true
+ sourceBuffer.abort();
+
+ assert_equals(sourceBuffer.updating, false,
+ 'Check updating value after calling abort.');
+ assert_equals(sourceBuffer.appendWindowStart, 0);
+ assert_equals(sourceBuffer.appendWindowEnd, Number.POSITIVE_INFINITY);
+ }));
+ sourceBuffer.addEventListener('update', t.step_func(function(e) {
+ assert_unreached("Can't touch this");
+ }));
+ sourceBuffer.addEventListener('updateend', function(e) {
+ events.push('updateend');
+ mediaSource.endOfStream();
+ });
+ sourceBuffer.addEventListener('abort', function(e) {
+ events.push('abort');
+ });
+ sourceBuffer.addEventListener('error', t.step_func(function(e) {
+ assert_unreached("Can't touch this");
+ }));
+ sourceBuffer.appendBuffer(data);
+ }));
+ mediaSource.addEventListener('sourceended', t.step_func_done(function(e) {
+ assert_array_equals(events,
+ ['updatestart', 'abort', 'updateend'],
+ 'Check the sequence of fired events.');
+ }));
+ var video = document.createElement('video');
+ video.src = window.URL.createObjectURL(mediaSource);
+ });
+ }, 'SourceBuffer#abort() (' + mime + ') : Check the algorithm when the updating attribute is true.');
+}
+for(var file in contents) {
+ mediaTest(file, contents[file]);
+}
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/media-source/SourceBuffer-abort.html b/tests/wpt/web-platform-tests/media-source/SourceBuffer-abort.html
new file mode 100644
index 00000000000..7d7c9ff1de0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/SourceBuffer-abort.html
@@ -0,0 +1,34 @@
+<!doctype html>
+<html>
+<head>
+ <meta charset='utf-8'>
+ <title>Check the values of appendWindowStart and appendWindowEnd after abort()</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id="log"></div>
+
+<script>
+var mimes = ['video/webm; codecs="vorbis,vp8"', 'video/mp4'];
+
+mimes.forEach(function(mime) {
+ async_test(function() {
+ assert_true(MediaSource.isTypeSupported(mime),
+ "Browser doesn't support the MIME used in this test: " + mime);
+
+ var mediaSource = new MediaSource();
+ mediaSource.addEventListener('sourceopen', this.step_func_done(function(e) {
+ var sourceBuffer = mediaSource.addSourceBuffer(mime);
+ sourceBuffer.abort();
+ assert_equals(sourceBuffer.appendWindowStart, 0);
+ assert_equals(sourceBuffer.appendWindowEnd, Number.POSITIVE_INFINITY);
+ }));
+
+ var video = document.createElement('video');
+ video.src = window.URL.createObjectURL(mediaSource);
+ }, 'SourceBuffer#abort() (' + mime + '): Check the values of appendWindowStart and appendWindowEnd.');
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/media-source/URL-createObjectURL-null.html b/tests/wpt/web-platform-tests/media-source/URL-createObjectURL-null.html
new file mode 100644
index 00000000000..a4177dd846b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/URL-createObjectURL-null.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<html>
+<head>
+ <meta charset='utf-8'>
+ <title>URL.createObjectURL(null)</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ assert_throws(new TypeError(), function() {
+ window.URL.createObjectURL(null);
+ });
+}, "URL.createObjectURL(null)");
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/media-source/URL-createObjectURL-revoke.html b/tests/wpt/web-platform-tests/media-source/URL-createObjectURL-revoke.html
new file mode 100644
index 00000000000..a194d24636e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/URL-createObjectURL-revoke.html
@@ -0,0 +1,22 @@
+<!doctype html>
+<html>
+<head>
+ <meta charset='utf-8'>
+ <title>Revoking a created URL with URL.revokeObjectURL(url)</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id="log"></div>
+<script>
+var video = document.createElement('video');
+test(function() {
+ var mediaSource = new MediaSource();
+ var url = window.URL.createObjectURL(mediaSource);
+ window.URL.revokeObjectURL(url);
+ video.src = url;
+ assert_equals(mediaSource.readyState, 'closed');
+}, "Check revoking behavior of URL.revokeObjectURL(url).");
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/media-source/URL-createObjectURL.html b/tests/wpt/web-platform-tests/media-source/URL-createObjectURL.html
new file mode 100644
index 00000000000..da82806349a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/URL-createObjectURL.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<html>
+<head>
+ <meta charset='utf-8'>
+ <title>URL.createObjectURL(mediaSource)</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ var mediaSource = new MediaSource();
+ var url = window.URL.createObjectURL(mediaSource);
+ assert_true(url != null);
+ assert_true(url.match(/^blob:.+/) != null);
+}, "URL.createObjectURL(mediaSource) should return a unique Blob URI.");
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/media-source/import_tests.sh b/tests/wpt/web-platform-tests/media-source/import_tests.sh
new file mode 100755
index 00000000000..a87619c0248
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/import_tests.sh
@@ -0,0 +1,52 @@
+#!/bin/bash
+
+if [ $# -lt 1 ]
+then
+ echo "Usage: $0 <Blink directory>"
+ exit -1
+fi
+
+BLINK_ROOT=$1
+LAYOUT_TEST_DIR=$BLINK_ROOT/LayoutTests
+HTTP_MEDIA_TEST_DIR=$LAYOUT_TEST_DIR/http/tests/media
+
+if [ ! -d "$BLINK_ROOT" ]
+then
+ echo "$BLINK_ROOT is not a directory or doesn't exist"
+ exit -1
+fi
+
+if [ ! -d "$LAYOUT_TEST_DIR" ]
+then
+ echo "$LAYOUT_TEST_DIR is not a directory or doesn't exist"
+ exit -1
+fi
+
+#rm -rf *.html *.js webm mp4 manifest.txt
+
+cp $HTTP_MEDIA_TEST_DIR/media-source/mediasource-*.html $HTTP_MEDIA_TEST_DIR/media-source/mediasource-*.js .
+cp -r $HTTP_MEDIA_TEST_DIR/resources/media-source/webm .
+cp -r $HTTP_MEDIA_TEST_DIR/resources/media-source/mp4 .
+
+# Remove Blink-specific files
+rm mediasource-gc-after-decode-error-crash.html
+
+sed -i 's/\/w3c\/resources\//\/resources\//g' *.html
+sed -i 's/\/media\/resources\/media-source\///g' *.html
+sed -i 's/\/media\/resources\/media-source\///g' *.js
+sed -i 's/\/media\/resources\/media-source\///g' webm/*
+
+
+for TEST_FILE in `ls *.html`
+do
+ if [ "$TEST_FILE" = "index.html" ]
+ then
+ continue
+ fi
+ echo -e "$TEST_FILE" >> manifest.txt
+done
+
+cp import_tests-template.txt index.html
+
+chmod -R a+r *.html *.js webm mp4 manifest.txt
+chmod a+rx webm mp4
diff --git a/tests/wpt/web-platform-tests/media-source/index.html b/tests/wpt/web-platform-tests/media-source/index.html
new file mode 100644
index 00000000000..903afffdd56
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/index.html
@@ -0,0 +1,93 @@
+<!doctype html>
+<html>
+ <head>
+ <link rel='stylesheet' href='/resources/testharness.css'>
+ <script>
+ (function() {
+ var testURLs = [];
+ var testIndex = 0;
+ var testCount = 0;
+ var STATUS_STRINGS = ["PASS", "FAIL", "TIMEOUT", "NOTRUN"];
+
+ function onMessage(e)
+ {
+ var testData = e.data;
+
+ //console.log(testData.type, testData);
+
+ if (testData.type == "complete") {
+ var tableBody = document.querySelector("#results tbody");
+ var fragment = document.createDocumentFragment();
+
+ testCount += testData.tests.length;
+
+ for (var i = 0; i < testData.tests.length; ++i) {
+ var testResults = testData.tests[i];
+ var tr = document.createElement("tr");
+ var status = document.createElement("td");
+ var testName = document.createElement("td");
+ var message = document.createElement("td");
+
+ status.textContent = STATUS_STRINGS[testResults.status];
+ tr.className = STATUS_STRINGS[testResults.status].toLowerCase();
+
+ testName.textContent = testResults.name;
+ message.textContent = testResults.message;
+
+ tr.appendChild(status);
+ tr.appendChild(testName);
+ tr.appendChild(message);
+ fragment.appendChild(tr);
+ }
+
+ testIndex++;
+ if (testIndex >= testURLs.length) {
+ return;
+ }
+
+ tableBody.appendChild(fragment);
+ startNextTest();
+ return;
+ }
+ }
+
+ function startNextTest()
+ {
+ var iframe = document.querySelector("iframe");
+ var testURL = testURLs[testIndex];
+
+ var tr = document.createElement("tr");
+ var td = document.createElement("td");
+ td.appendChild(document.createTextNode("Running tests in '" + testURL + "' :"));
+ td.colSpan = 3;
+ tr.appendChild(td);
+ document.querySelector("#results tbody").appendChild(tr);
+
+ iframe.src = testURL;
+ }
+
+ window["onBodyLoad"] = function()
+ {
+ window.addEventListener("message", onMessage);
+ var xhr = new XMLHttpRequest();
+ xhr.open("GET", "manifest.txt", false);
+ xhr.send();
+
+ var str = xhr.response.replace("\r", "");
+ testURLs = xhr.response.replace("\r", "").split("\n");
+ startNextTest();
+ }
+
+
+ })(window);
+ </script>
+ </head>
+ <body onload="onBodyLoad()">
+ <iframe></iframe>
+ <table id="results" style="float:left;">
+ <tbody>
+ </tbody>
+ </table>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/media-source/interfaces.html b/tests/wpt/web-platform-tests/media-source/interfaces.html
new file mode 100644
index 00000000000..9d6985eee7d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/interfaces.html
@@ -0,0 +1,145 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Media Source Extensions IDL tests</title>
+<div id=log></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=/resources/WebIDLParser.js></script>
+<script src=/resources/idlharness.js></script>
+<script type=text/plain class=untested>
+interface EventTarget {
+ void addEventListener(DOMString type, EventListener? callback, optional boolean capture /* = false */);
+ void removeEventListener(DOMString type, EventListener? callback, optional boolean capture /* = false */);
+ boolean dispatchEvent(Event event);
+};
+interface URL {};
+interface HTMLVideoElement {};
+interface AudioTrack {};
+interface VideoTrack {};
+interface TextTrack {};
+interface TimeRanges {};
+typedef double DOMHighResTimeStamp;
+</script>
+<script type=text/plain>
+[Constructor]
+interface MediaSource : EventTarget {
+ readonly attribute SourceBufferList sourceBuffers;
+ readonly attribute SourceBufferList activeSourceBuffers;
+ readonly attribute ReadyState readyState;
+ attribute unrestricted double duration;
+ SourceBuffer addSourceBuffer (DOMString type);
+ void removeSourceBuffer (SourceBuffer sourceBuffer);
+ void endOfStream (optional EndOfStreamError error);
+ static boolean isTypeSupported (DOMString type);
+};
+
+interface SourceBuffer : EventTarget {
+ attribute AppendMode mode;
+ readonly attribute boolean updating;
+ readonly attribute TimeRanges buffered;
+ attribute double timestampOffset;
+ readonly attribute AudioTrackList audioTracks;
+ readonly attribute VideoTrackList videoTracks;
+ readonly attribute TextTrackList textTracks;
+ attribute double appendWindowStart;
+ attribute unrestricted double appendWindowEnd;
+ void appendBuffer (ArrayBuffer data);
+ void appendBuffer (ArrayBufferView data);
+ void appendStream (Stream stream, [EnforceRange] optional unsigned long long maxSize);
+ void abort ();
+ void remove (double start, double end);
+};
+
+interface SourceBufferList : EventTarget {
+ readonly attribute unsigned long length;
+ getter SourceBuffer (unsigned long index);
+};
+
+interface VideoPlaybackQuality {
+ readonly attribute DOMHighResTimeStamp creationTime;
+ readonly attribute unsigned long totalVideoFrames;
+ readonly attribute unsigned long droppedVideoFrames;
+ readonly attribute unsigned long corruptedVideoFrames;
+ readonly attribute double totalFrameDelay;
+};
+
+partial interface URL {
+ static DOMString createObjectURL (MediaSource mediaSource);
+};
+
+partial interface HTMLVideoElement {
+ VideoPlaybackQuality getVideoPlaybackQuality ();
+};
+
+partial interface AudioTrack {
+ attribute DOMString kind;
+ attribute DOMString language;
+ readonly attribute SourceBuffer? sourceBuffer;
+};
+
+partial interface VideoTrack {
+ attribute DOMString kind;
+ attribute DOMString language;
+ readonly attribute SourceBuffer? sourceBuffer;
+};
+
+partial interface TextTrack {
+ attribute DOMString kind;
+ attribute DOMString language;
+ readonly attribute SourceBuffer? sourceBuffer;
+};
+
+enum EndOfStreamError {
+ "network",
+ "decode"
+};
+enum AppendMode {
+ "segments",
+ "sequence"
+};
+
+enum ReadyState {
+ "closed",
+ "open",
+ "ended"
+};
+
+</script>
+<script>
+"use strict";
+var mediaSource;
+var sourceBuffer;
+var video = document.createElement("video");
+var idlCheck = function() {
+ var idlArray = new IdlArray();
+ [].forEach.call(document.querySelectorAll("script[type=text\\/plain]"), function(node) {
+ if (node.className == "untested") {
+ idlArray.add_untested_idls(node.textContent);
+ } else {
+ idlArray.add_idls(node.textContent);
+ }
+ });
+ idlArray.add_objects({
+ MediaSource: ['mediaSource'],
+ SourceBuffer: ['sourceBuffer'],
+ SourceBufferList: ['mediaSource.sourceBuffers'],
+ VideoPlaybackQuality: ['video.getVideoPlaybackQuality()'],
+ });
+ idlArray.test();
+}
+mediaSource = new MediaSource();
+video.src = URL.createObjectURL(mediaSource);
+mediaSource.addEventListener("sourceopen", function () {
+ var defaultType ='video/webm;codecs="vp8,vorbis"';
+ if (video.canPlayType(defaultType)) {
+ sourceBuffer = mediaSource.addSourceBuffer(defaultType);
+ } else {
+ sourceBuffer = mediaSource.addSourceBuffer('video/mp4');
+ }
+ sourceBuffer.addEventListener("updateend", function (e) {
+ mediaSource.endOfStream();
+ idlCheck();
+ });
+ sourceBuffer.appendBuffer(new ArrayBuffer());
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/media-source/manifest.txt b/tests/wpt/web-platform-tests/media-source/manifest.txt
new file mode 100644
index 00000000000..d8714cae22a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/manifest.txt
@@ -0,0 +1,32 @@
+mediasource-addsourcebuffer.html
+mediasource-append-buffer.html
+mediasource-appendwindow.html
+mediasource-buffered.html
+mediasource-closed.html
+mediasource-config-change-mp4-a-bitrate.html
+mediasource-config-change-mp4-av-audio-bitrate.html
+mediasource-config-change-mp4-av-framesize.html
+mediasource-config-change-mp4-av-video-bitrate.html
+mediasource-config-change-mp4-v-bitrate.html
+mediasource-config-change-mp4-v-framerate.html
+mediasource-config-change-mp4-v-framesize.html
+mediasource-config-change-webm-a-bitrate.html
+mediasource-config-change-webm-av-audio-bitrate.html
+mediasource-config-change-webm-av-framesize.html
+mediasource-config-change-webm-av-video-bitrate.html
+mediasource-config-change-webm-v-bitrate.html
+mediasource-config-change-webm-v-framerate.html
+mediasource-config-change-webm-v-framesize.html
+mediasource-duration.html
+mediasource-endofstream-invaliderror.html
+mediasource-getvideoplaybackquality.html
+mediasource-is-type-supported.html
+mediasource-multiple-attach.html
+mediasource-play.html
+mediasource-play-then-seek-back.html
+mediasource-redundant-seek.html
+mediasource-remove.html
+mediasource-seek-beyond-duration.html
+mediasource-seek-during-pending-seek.html
+mediasource-sourcebufferlist.html
+mediasource-sourcebuffer-mode.html
diff --git a/tests/wpt/web-platform-tests/media-source/mediasource-addsourcebuffer.html b/tests/wpt/web-platform-tests/media-source/mediasource-addsourcebuffer.html
new file mode 100644
index 00000000000..61f67f4b27e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mediasource-addsourcebuffer.html
@@ -0,0 +1,153 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>MediaSource.addSourceBuffer() test cases</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="mediasource-util.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ mediasource_test(function(test, mediaElement, mediaSource)
+ {
+ mediaSource.endOfStream();
+ assert_throws("InvalidStateError",
+ function() { mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_VIDEO_TYPE); },
+ "addSourceBuffer() threw an exception when in 'ended' state.");
+ test.done();
+ }, "Test addSourceBuffer() in 'ended' state.");
+
+ mediasource_test(function(test, mediaElement, mediaSource)
+ {
+ assert_throws("InvalidAccessError",
+ function() { mediaSource.addSourceBuffer(""); },
+ "addSourceBuffer() threw an exception when passed an empty string.");
+ test.done();
+ }, "Test addSourceBuffer() with empty type");
+
+ mediasource_test(function(test, mediaElement, mediaSource)
+ {
+ assert_throws("NotSupportedError",
+ function() { mediaSource.addSourceBuffer(null); },
+ "addSourceBuffer() threw an exception when passed null.");
+ test.done();
+ }, "Test addSourceBuffer() with null");
+
+ mediasource_test(function(test, mediaElement, mediaSource)
+ {
+ assert_throws("NotSupportedError",
+ function() { mediaSource.addSourceBuffer("invalidType"); },
+ "addSourceBuffer() threw an exception for an unsupported type.");
+ test.done();
+ }, "Test addSourceBuffer() with unsupported type");
+
+
+ mediasource_test(function(test, mediaElement, mediaSource)
+ {
+ var mimetype = 'video/webm;codecs="vp8,vorbis"';
+
+ assert_true(MediaSource.isTypeSupported(mimetype), mimetype + " is supported");
+
+ var sourceBuffer = mediaSource.addSourceBuffer(mimetype);
+ assert_true(sourceBuffer != null, "New SourceBuffer returned");
+ assert_equals(mediaSource.sourceBuffers[0], sourceBuffer, "SourceBuffer is in mediaSource.sourceBuffers");
+ assert_equals(mediaSource.activeSourceBuffers.length, 0, "SourceBuffer is not in mediaSource.activeSourceBuffers");
+ test.done();
+ }, "Test addSourceBuffer() with Vorbis and VP8");
+
+ mediasource_test(function(test, mediaElement, mediaSource)
+ {
+ var videoMimetype = 'video/webm;codecs="vp8"';
+ var audioMimetype = 'audio/webm;codecs="vorbis"';
+
+ assert_true(MediaSource.isTypeSupported(videoMimetype), videoMimetype + " is supported");
+ assert_true(MediaSource.isTypeSupported(audioMimetype), audioMimetype + " is supported");
+
+ var sourceBufferA = mediaSource.addSourceBuffer(videoMimetype);
+ var sourceBufferB = mediaSource.addSourceBuffer(audioMimetype);
+ assert_equals(mediaSource.sourceBuffers[0], sourceBufferA, "sourceBufferA is in mediaSource.sourceBuffers");
+ assert_equals(mediaSource.activeSourceBuffers.length, 0, "SourceBufferA is not in mediaSource.activeSourceBuffers");
+ assert_equals(mediaSource.sourceBuffers[1], sourceBufferB, "sourceBufferB is in mediaSource.sourceBuffers");
+ assert_equals(mediaSource.activeSourceBuffers.length, 0, "SourceBufferB is not in mediaSource.activeSourceBuffers");
+ test.done();
+ }, "Test addSourceBuffer() with Vorbis and VP8 in separate SourceBuffers");
+
+ mediasource_test(function(test, mediaElement, mediaSource)
+ {
+ var mimetype = MediaSourceUtil.VIDEO_ONLY_TYPE;
+
+ assert_true(MediaSource.isTypeSupported(mimetype), mimetype + " is supported");
+
+ var sourceBuffer = mediaSource.addSourceBuffer(mimetype);
+ assert_true(sourceBuffer != null, "New SourceBuffer returned");
+ assert_equals(mediaSource.sourceBuffers[0], sourceBuffer, "SourceBuffer is in mediaSource.sourceBuffers");
+ assert_equals(mediaSource.activeSourceBuffers.length, 0, "SourceBuffer is in mediaSource.activeSourceBuffers");
+ test.done();
+ }, "Test addSourceBuffer() video only");
+
+ mediasource_test(function(test, mediaElement, mediaSource)
+ {
+ var mimetype = MediaSourceUtil.AUDIO_ONLY_TYPE;
+
+ assert_true(MediaSource.isTypeSupported(mimetype), mimetype + " is supported");
+
+ var sourceBuffer = mediaSource.addSourceBuffer(mimetype);
+ assert_true(sourceBuffer != null, "New SourceBuffer returned");
+ assert_equals(mediaSource.sourceBuffers[0], sourceBuffer, "SourceBuffer is in mediaSource.sourceBuffers");
+ assert_equals(mediaSource.activeSourceBuffers.length, 0, "SourceBuffer is in mediaSource.activeSourceBuffers");
+ test.done();
+ }, "Test addSourceBuffer() audio only");
+
+ mediasource_test(function(test, mediaElement, mediaSource)
+ {
+ var mimetype = 'video/mp4;codecs="avc1.4D4001,mp4a.40.2"';
+
+ assert_true(MediaSource.isTypeSupported(mimetype), mimetype + " is supported");
+
+ var sourceBuffer = mediaSource.addSourceBuffer(mimetype);
+ assert_true(sourceBuffer != null, "New SourceBuffer returned");
+ assert_equals(mediaSource.sourceBuffers[0], sourceBuffer, "SourceBuffer is in mediaSource.sourceBuffers");
+ assert_equals(mediaSource.activeSourceBuffers.length, 0, "SourceBuffer is not in mediaSource.activeSourceBuffers");
+ test.done();
+ }, "Test addSourceBuffer() with AAC and H.264");
+
+ mediasource_test(function(test, mediaElement, mediaSource)
+ {
+ var videoMimetype = 'video/mp4;codecs="avc1.4D4001"';
+ var audioMimetype = 'audio/mp4;codecs="mp4a.40.2"';
+
+ assert_true(MediaSource.isTypeSupported(videoMimetype), videoMimetype + " is supported");
+ assert_true(MediaSource.isTypeSupported(audioMimetype), audioMimetype + " is supported");
+
+ var sourceBufferA = mediaSource.addSourceBuffer(videoMimetype);
+ var sourceBufferB = mediaSource.addSourceBuffer(audioMimetype);
+ assert_equals(mediaSource.sourceBuffers[0], sourceBufferA, "sourceBufferA is in mediaSource.sourceBuffers");
+ assert_equals(mediaSource.activeSourceBuffers.length, 0, "SourceBufferA is not in mediaSource.activeSourceBuffers");
+ assert_equals(mediaSource.sourceBuffers[1], sourceBufferB, "sourceBufferB is in mediaSource.sourceBuffers");
+ assert_equals(mediaSource.activeSourceBuffers.length, 0, "SourceBufferB is not in mediaSource.activeSourceBuffers");
+ test.done();
+ }, "Test addSourceBuffer() with AAC and H.264 in separate SourceBuffers");
+
+ mediasource_test(function(test, mediaElement, mediaSource)
+ {
+ var reachedLimit = false;
+
+ // The 20 here is an arbitrary upper limit to make sure the test terminates. This test
+ // assumes that implementations won't support more than 20 SourceBuffers simultaneously.
+ for (var i = 0; i < 20; ++i) {
+ try {
+ mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_VIDEO_TYPE);
+ } catch(e) {
+ assert_equals(e.name, "QuotaExceededError");
+ reachedLimit = true;
+ break;
+ }
+ }
+ assert_true(reachedLimit, "Reached SourceBuffer limit.");
+ test.done();
+ }, "Test addSourceBuffer() QuotaExceededError.");
+
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/media-source/mediasource-append-buffer.html b/tests/wpt/web-platform-tests/media-source/mediasource-append-buffer.html
new file mode 100644
index 00000000000..3bff4d9fa53
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mediasource-append-buffer.html
@@ -0,0 +1,538 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>SourceBuffer.appendBuffer() test cases</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="mediasource-util.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
+ {
+ test.failOnEvent(mediaElement, 'error');
+
+ test.expectEvent(sourceBuffer, "updatestart", "Append started.");
+ test.expectEvent(sourceBuffer, "update", "Append success.");
+ test.expectEvent(sourceBuffer, "updateend", "Append ended.");
+ sourceBuffer.appendBuffer(mediaData);
+
+ assert_true(sourceBuffer.updating, "updating attribute is true");
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_false(sourceBuffer.updating, "updating attribute is false");
+ test.done();
+ });
+ }, "Test SourceBuffer.appendBuffer() event dispatching.");
+
+ mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
+ {
+ test.failOnEvent(mediaElement, 'error');
+
+ test.expectEvent(sourceBuffer, "updatestart", "Append started.");
+ test.expectEvent(sourceBuffer, "update", "Append success.");
+ test.expectEvent(sourceBuffer, "updateend", "Append ended.");
+ sourceBuffer.appendBuffer(mediaData);
+
+ assert_true(sourceBuffer.updating, "updating attribute is true");
+
+ assert_throws("InvalidStateError",
+ function() { sourceBuffer.appendBuffer(mediaData); },
+ "appendBuffer() throws an exception there is a pending append.");
+
+ assert_true(sourceBuffer.updating, "updating attribute is true");
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_false(sourceBuffer.updating, "updating attribute is false");
+ test.done();
+ });
+ }, "Test SourceBuffer.appendBuffer() call during a pending appendBuffer().");
+
+ mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
+ {
+ test.failOnEvent(mediaElement, 'error');
+
+ test.expectEvent(sourceBuffer, "updatestart", "Append started.");
+ test.expectEvent(sourceBuffer, "abort", "Append aborted.");
+ test.expectEvent(sourceBuffer, "updateend", "Append ended.");
+ sourceBuffer.appendBuffer(mediaData);
+
+ assert_true(sourceBuffer.updating, "updating attribute is true");
+
+ sourceBuffer.abort();
+
+ assert_false(sourceBuffer.updating, "updating attribute is false");
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_false(sourceBuffer.updating, "updating attribute is false");
+ test.done();
+ });
+ }, "Test SourceBuffer.abort() call during a pending appendBuffer().");
+
+ mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
+ {
+ test.failOnEvent(mediaElement, 'error');
+
+ test.expectEvent(sourceBuffer, "updatestart", "Append started.");
+ test.expectEvent(sourceBuffer, "update", "Append success.");
+ test.expectEvent(sourceBuffer, "updateend", "Append ended.");
+ sourceBuffer.appendBuffer(mediaData);
+ assert_true(sourceBuffer.updating, "updating attribute is true");
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_false(sourceBuffer.updating, "updating attribute is false");
+
+ test.expectEvent(mediaSource, "sourceended", "MediaSource sourceended event");
+ mediaSource.endOfStream();
+ assert_equals(mediaSource.readyState, "ended", "MediaSource readyState is 'ended'");
+ });
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_equals(mediaSource.readyState, "ended", "MediaSource readyState is 'ended'");
+
+ test.expectEvent(mediaSource, "sourceopen", "MediaSource sourceopen event");
+ test.expectEvent(sourceBuffer, "updatestart", "Append started.");
+ test.expectEvent(sourceBuffer, "update", "Append success.");
+ test.expectEvent(sourceBuffer, "updateend", "Append ended.");
+ sourceBuffer.appendBuffer(mediaData);
+
+ assert_equals(mediaSource.readyState, "open", "MediaSource readyState is 'open'");
+ assert_true(sourceBuffer.updating, "updating attribute is true");
+ });
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_equals(mediaSource.readyState, "open", "MediaSource readyState is 'open'");
+ assert_false(sourceBuffer.updating, "updating attribute is false");
+ test.done();
+ });
+ }, "Test SourceBuffer.appendBuffer() triggering an 'ended' to 'open' transition.");
+
+ mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
+ {
+ test.expectEvent(sourceBuffer, "updatestart", "Append started.");
+ test.expectEvent(sourceBuffer, "update", "Append success.");
+ test.expectEvent(sourceBuffer, "updateend", "Append ended.");
+ sourceBuffer.appendBuffer(mediaData);
+ assert_true(sourceBuffer.updating, "updating attribute is true");
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_false(sourceBuffer.updating, "updating attribute is false");
+
+ test.expectEvent(mediaSource, "sourceended", "MediaSource sourceended event");
+ mediaSource.endOfStream();
+ assert_equals(mediaSource.readyState, "ended", "MediaSource readyState is 'ended'");
+ });
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_equals(mediaSource.readyState, "ended", "MediaSource readyState is 'ended'");
+
+ test.expectEvent(mediaSource, "sourceopen", "MediaSource sourceopen event");
+ test.expectEvent(sourceBuffer, "updatestart", "Append started.");
+ test.expectEvent(sourceBuffer, "update", "Append success.");
+ test.expectEvent(sourceBuffer, "updateend", "Append ended.");
+ sourceBuffer.appendBuffer(new Uint8Array(0));
+
+ assert_equals(mediaSource.readyState, "open", "MediaSource readyState is 'open'");
+ assert_true(sourceBuffer.updating, "updating attribute is true");
+ });
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_equals(mediaSource.readyState, "open", "MediaSource readyState is 'open'");
+ assert_false(sourceBuffer.updating, "updating attribute is false");
+ test.done();
+ });
+ }, "Test zero byte SourceBuffer.appendBuffer() call triggering an 'ended' to 'open' transition.");
+
+ mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
+ {
+ test.failOnEvent(mediaElement, 'error');
+
+ test.expectEvent(sourceBuffer, "updatestart", "Append started.");
+ test.expectEvent(sourceBuffer, "abort", "Append aborted.");
+ test.expectEvent(sourceBuffer, "updateend", "Append ended.");
+ sourceBuffer.appendBuffer(mediaData);
+
+ assert_true(sourceBuffer.updating, "updating attribute is true");
+ assert_equals(mediaSource.activeSourceBuffers.length, 0, "activeSourceBuffers.length");
+
+ test.expectEvent(mediaSource.sourceBuffers, "removesourcebuffer", "sourceBuffers");
+ mediaSource.removeSourceBuffer(sourceBuffer);
+
+ assert_false(sourceBuffer.updating, "updating attribute is false");
+
+ assert_throws("InvalidStateError",
+ function() { sourceBuffer.appendBuffer(mediaData); },
+ "appendBuffer() throws an exception because it isn't attached to the mediaSource anymore.");
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_false(sourceBuffer.updating, "updating attribute is false");
+ test.done();
+ });
+ }, "Test MediaSource.removeSourceBuffer() call during a pending appendBuffer().");
+
+ mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
+ {
+ test.failOnEvent(mediaElement, 'error');
+
+ test.expectEvent(sourceBuffer, "updatestart", "Append started.");
+ test.expectEvent(sourceBuffer, "updateend", "Append ended.");
+ sourceBuffer.appendBuffer(mediaData);
+
+ assert_true(sourceBuffer.updating, "updating attribute is true");
+
+ assert_throws("InvalidStateError",
+ function() { mediaSource.duration = 1.0; },
+ "set duration throws an exception when updating attribute is true.");
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_false(sourceBuffer.updating, "updating attribute is false");
+ test.done();
+ });
+ }, "Test set MediaSource.duration during a pending appendBuffer() for one of its SourceBuffers.");
+
+ mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
+ {
+ test.failOnEvent(mediaElement, "error");
+ test.failOnEvent(mediaSource, "sourceended");
+
+ test.expectEvent(sourceBuffer, "updatestart", "Append started.");
+ test.expectEvent(sourceBuffer, "updateend", "Append ended.");
+ sourceBuffer.appendBuffer(mediaData);
+
+ assert_true(sourceBuffer.updating, "updating attribute is true");
+
+ assert_throws("InvalidStateError",
+ function() { mediaSource.endOfStream(); },
+ "endOfStream() throws an exception when updating attribute is true.");
+
+ assert_equals(mediaSource.readyState, "open");
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_false(sourceBuffer.updating, "updating attribute is false");
+ assert_equals(mediaSource.readyState, "open");
+ test.done();
+ });
+ }, "Test MediaSource.endOfStream() during a pending appendBuffer() for one of its SourceBuffers.");
+
+ mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
+ {
+ test.failOnEvent(mediaElement, 'error');
+
+ test.expectEvent(sourceBuffer, "updatestart", "Append started.");
+ test.expectEvent(sourceBuffer, "updateend", "Append ended.");
+ sourceBuffer.appendBuffer(mediaData);
+
+ assert_true(sourceBuffer.updating, "updating attribute is true");
+
+ assert_throws("InvalidStateError",
+ function() { sourceBuffer.timestampOffset = 10.0; },
+ "set timestampOffset throws an exception when updating attribute is true.");
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_false(sourceBuffer.updating, "updating attribute is false");
+ test.done();
+ });
+ }, "Test set SourceBuffer.timestampOffset during a pending appendBuffer().");
+
+ mediasource_test(function(test, mediaElement, mediaSource)
+ {
+ var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.VIDEO_ONLY_TYPE);
+
+ test.expectEvent(sourceBuffer, "updatestart", "Append started.");
+ test.expectEvent(sourceBuffer, "update", "Append success.");
+ test.expectEvent(sourceBuffer, "updateend", "Append ended.");
+ sourceBuffer.appendBuffer(new Uint8Array(0));
+
+ assert_true(sourceBuffer.updating, "updating attribute is true");
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_false(sourceBuffer.updating, "updating attribute is false");
+ test.done();
+ });
+ }, "Test appending an empty ArrayBufferView.");
+
+ mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
+ {
+ test.expectEvent(sourceBuffer, "updatestart", "Append started.");
+ test.expectEvent(sourceBuffer, "update", "Append success.");
+ test.expectEvent(sourceBuffer, "updateend", "Append ended.");
+
+ var arrayBufferView = new Uint8Array(mediaData);
+
+ assert_equals(arrayBufferView.length, mediaData.length, "arrayBufferView.length before transfer.");
+
+ // Send the buffer as in a message so it gets neutered.
+ window.postMessage( "test", "*", [arrayBufferView.buffer]);
+
+ assert_equals(arrayBufferView.length, 0, "arrayBufferView.length after transfer.");
+
+ sourceBuffer.appendBuffer(arrayBufferView);
+
+ assert_true(sourceBuffer.updating, "updating attribute is true");
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_false(sourceBuffer.updating, "updating attribute is false");
+ test.done();
+ });
+ }, "Test appending a neutered ArrayBufferView.");
+
+ mediasource_test(function(test, mediaElement, mediaSource)
+ {
+ var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.VIDEO_ONLY_TYPE);
+
+ test.expectEvent(sourceBuffer, "updatestart", "Append started.");
+ test.expectEvent(sourceBuffer, "update", "Append success.");
+ test.expectEvent(sourceBuffer, "updateend", "Append ended.");
+ sourceBuffer.appendBuffer(new ArrayBuffer(0));
+
+ assert_true(sourceBuffer.updating, "updating attribute is true");
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_false(sourceBuffer.updating, "updating attribute is false");
+ test.done();
+ });
+ }, "Test appending an empty ArrayBuffer.");
+
+ mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
+ {
+ test.expectEvent(sourceBuffer, "updatestart", "Append started.");
+ test.expectEvent(sourceBuffer, "update", "Append success.");
+ test.expectEvent(sourceBuffer, "updateend", "Append ended.");
+
+ var arrayBuffer = mediaData.buffer.slice(0);
+
+ assert_equals(arrayBuffer.byteLength, mediaData.buffer.byteLength, "arrayBuffer.byteLength before transfer.");
+
+ // Send the buffer as in a message so it gets neutered.
+ window.postMessage( "test", "*", [arrayBuffer]);
+
+ assert_equals(arrayBuffer.byteLength, 0, "arrayBuffer.byteLength after transfer.");
+
+ sourceBuffer.appendBuffer(arrayBuffer);
+
+ assert_true(sourceBuffer.updating, "updating attribute is true");
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_false(sourceBuffer.updating, "updating attribute is false");
+ test.done();
+ });
+ }, "Test appending a neutered ArrayBuffer.");
+
+ mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
+ {
+ var initSegment = MediaSourceUtil.extractSegmentData(mediaData, segmentInfo.init);
+ var halfIndex = (initSegment.length + 1) / 2;
+ var partialInitSegment = initSegment.subarray(0, halfIndex);
+ var remainingInitSegment = initSegment.subarray(halfIndex);
+ var mediaSegment = MediaSourceUtil.extractSegmentData(mediaData, segmentInfo.media[0]);
+
+ test.expectEvent(sourceBuffer, "updateend", "partialInitSegment append ended.");
+ sourceBuffer.appendBuffer(partialInitSegment);
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_equals(mediaElement.readyState, mediaElement.HAVE_NOTHING);
+ assert_equals(mediaSource.duration, Number.NaN);
+ test.expectEvent(sourceBuffer, "updateend", "remainingInitSegment append ended.");
+ test.expectEvent(mediaElement, "loadedmetadata", "loadedmetadata event received.");
+ sourceBuffer.appendBuffer(remainingInitSegment);
+ });
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_equals(mediaElement.readyState, mediaElement.HAVE_METADATA);
+ assert_equals(mediaSource.duration, segmentInfo.duration);
+ test.expectEvent(sourceBuffer, "updateend", "mediaSegment append ended.");
+ test.expectEvent(mediaElement, "loadeddata", "loadeddata fired.");
+ sourceBuffer.appendBuffer(mediaSegment);
+ });
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_greater_than_equal(mediaElement.readyState, mediaElement.HAVE_CURRENT_DATA);
+ assert_equals(sourceBuffer.updating, false);
+ assert_equals(mediaSource.readyState, "open");
+ test.done();
+ });
+ }, "Test appendBuffer with partial init segments.");
+
+ mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
+ {
+ var initSegment = MediaSourceUtil.extractSegmentData(mediaData, segmentInfo.init);
+ var mediaSegment = MediaSourceUtil.extractSegmentData(mediaData, segmentInfo.media[0]);
+ var halfIndex = (mediaSegment.length + 1) / 2;
+ var partialMediaSegment = mediaSegment.subarray(0, halfIndex);
+ var remainingMediaSegment = mediaSegment.subarray(halfIndex);
+
+ test.expectEvent(sourceBuffer, "updateend", "InitSegment append ended.");
+ test.expectEvent(mediaElement, "loadedmetadata", "loadedmetadata done.");
+ sourceBuffer.appendBuffer(initSegment);
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_equals(mediaElement.readyState, mediaElement.HAVE_METADATA);
+ assert_equals(mediaSource.duration, segmentInfo.duration);
+ test.expectEvent(sourceBuffer, "updateend", "partial media segment append ended.");
+ sourceBuffer.appendBuffer(partialMediaSegment);
+ });
+
+ test.waitForExpectedEvents(function()
+ {
+ test.expectEvent(sourceBuffer, "updateend", "mediaSegment append ended.");
+ test.expectEvent(mediaElement, "loadeddata", "loadeddata fired.");
+ sourceBuffer.appendBuffer(remainingMediaSegment);
+ });
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_greater_than_equal(mediaElement.readyState, mediaElement.HAVE_CURRENT_DATA);
+ assert_equals(mediaSource.readyState, "open");
+ assert_equals(sourceBuffer.updating, false);
+ test.done();
+ });
+ }, "Test appendBuffer with partial media segments.");
+
+ mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
+ {
+ var initSegment = MediaSourceUtil.extractSegmentData(mediaData, segmentInfo.init);
+ var partialInitSegment = initSegment.subarray(0, initSegment.length / 2);
+ var mediaSegment = MediaSourceUtil.extractSegmentData(mediaData, segmentInfo.media[0]);
+
+ test.expectEvent(sourceBuffer, "updateend", "partialInitSegment append ended.");
+ sourceBuffer.appendBuffer(partialInitSegment);
+
+ test.waitForExpectedEvents(function()
+ {
+ // Call abort to reset the parser.
+ sourceBuffer.abort();
+
+ // Append the full intiialization segment.
+ test.expectEvent(sourceBuffer, "updateend", "initSegment append ended.");
+ sourceBuffer.appendBuffer(initSegment);
+ });
+
+ test.waitForExpectedEvents(function()
+ {
+ test.expectEvent(sourceBuffer, "updateend", "mediaSegment append ended.");
+ test.expectEvent(mediaElement, "loadeddata", "loadeddata fired.");
+ sourceBuffer.appendBuffer(mediaSegment);
+ });
+
+ test.waitForExpectedEvents(function()
+ {
+ test.done();
+ });
+ }, "Test abort in the middle of an initialization segment.");
+
+ mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
+ {
+ test.expectEvent(mediaSource.sourceBuffers, "removesourcebuffer", "SourceBuffer removed.");
+ mediaSource.removeSourceBuffer(sourceBuffer);
+ test.waitForExpectedEvents(function()
+ {
+ assert_throws("InvalidStateError",
+ function() { sourceBuffer.abort(); },
+ "sourceBuffer.abort() throws an exception for InvalidStateError.");
+
+ test.done();
+ });
+ }, "Test abort after removing sourcebuffer.");
+
+ mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
+ {
+ var initSegment = MediaSourceUtil.extractSegmentData(mediaData, segmentInfo.init);
+ var mediaSegment = MediaSourceUtil.extractSegmentData(mediaData, segmentInfo.media[0]);
+
+ test.expectEvent(sourceBuffer, "updateend", "initSegment append ended.");
+ sourceBuffer.appendBuffer(initSegment);
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_equals(mediaSource.readyState, "open", "readyState is open after init segment appended.");
+ test.expectEvent(sourceBuffer, "updateend", "mediaSegment append ended.");
+ sourceBuffer.appendBuffer(mediaSegment);
+ });
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_equals(sourceBuffer.buffered.length, 1, "sourceBuffer has a buffered range");
+ assert_equals(mediaSource.readyState, "open", "readyState is open after media segment appended.");
+ test.expectEvent(mediaSource, "sourceended", "source ended");
+ mediaSource.endOfStream();
+ });
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_equals(mediaSource.readyState, "ended", "readyState is ended.");
+ assert_throws("InvalidStateError",
+ function() { sourceBuffer.abort(); },
+ "sourceBuffer.abort() throws an exception for InvalidStateError.");
+ test.done();
+ });
+
+ }, "Test abort after readyState is ended following init segment and media segment.");
+
+ mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
+ {
+ test.expectEvent(sourceBuffer, "updatestart", "Append started.");
+ test.expectEvent(sourceBuffer, "updateend", "Append ended.");
+ sourceBuffer.appendWindowStart = 1;
+ sourceBuffer.appendWindowEnd = 100;
+ sourceBuffer.appendBuffer(mediaData);
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_false(sourceBuffer.updating, "updating attribute is false");
+ sourceBuffer.abort();
+ assert_equals(sourceBuffer.appendWindowStart, 0, "appendWindowStart is reset to 0");
+ assert_equals(sourceBuffer.appendWindowEnd, Number.POSITIVE_INFINITY,
+ "appendWindowEnd is reset to +INFINITY");
+ test.done();
+ });
+ }, "Test abort after appendBuffer update ends.");
+
+ mediasource_test(function(test, mediaElement, mediaSource)
+ {
+ var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.VIDEO_ONLY_TYPE);
+
+ test.expectEvent(sourceBuffer, "updatestart", "Append started.");
+ test.expectEvent(sourceBuffer, "update", "Append success.");
+ test.expectEvent(sourceBuffer, "updateend", "Append ended.");
+
+ assert_throws( { name: "TypeError"} ,
+ function() { sourceBuffer.appendBuffer(null); },
+ "appendBuffer(null) throws an exception.");
+ test.done();
+ }, "Test appending null.");
+
+ mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
+ {
+ mediaSource.removeSourceBuffer(sourceBuffer);
+
+ assert_throws( { name: "InvalidStateError"} ,
+ function() { sourceBuffer.appendBuffer(mediaData); },
+ "appendBuffer() throws an exception when called after removeSourceBuffer().");
+ test.done();
+ }, "Test appending after removeSourceBuffer().");
+
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/media-source/mediasource-appendwindow.html b/tests/wpt/web-platform-tests/media-source/mediasource-appendwindow.html
new file mode 100644
index 00000000000..e1b7c112063
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mediasource-appendwindow.html
@@ -0,0 +1,175 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>SourceBuffer.appendWindowStart and SourceBuffer.appendWindowEnd test cases.</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="mediasource-util.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ mediasource_test(function(test, mediaElement, mediaSource)
+ {
+ var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_VIDEO_TYPE);
+ assert_true(sourceBuffer != null, "New SourceBuffer returned");
+
+ sourceBuffer.appendWindowStart = 100.0;
+ sourceBuffer.appendWindowEnd = 500.0;
+ assert_equals(sourceBuffer.appendWindowStart, 100.0, "appendWindowStart is correctly set'");
+ assert_equals(sourceBuffer.appendWindowEnd, 500.0, "appendWindowEnd is correctly set'");
+
+ sourceBuffer.appendWindowStart = 200.0;
+ sourceBuffer.appendWindowEnd = 400.0;
+ assert_equals(sourceBuffer.appendWindowStart, 200.0, "appendWindowStart is correctly reset'");
+ assert_equals(sourceBuffer.appendWindowEnd, 400.0, "appendWindowEnd is correctly reset'");
+ test.done();
+ }, "Test correctly reset appendWindowStart and appendWindowEnd values");
+
+ mediasource_test(function(test, mediaElement, mediaSource)
+ {
+ var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_VIDEO_TYPE);
+ assert_true(sourceBuffer != null, "New SourceBuffer returned");
+ sourceBuffer.appendWindowEnd = 500.0;
+
+ assert_throws(new TypeError(),
+ function() { sourceBuffer.appendWindowStart = Number.NEGATIVE_INFINITY; },
+ "set appendWindowStart throws an exception for Number.NEGATIVE_INFINITY.");
+
+ assert_throws(new TypeError(),
+ function() { sourceBuffer.appendWindowStart = Number.POSITIVE_INFINITY; },
+ "set appendWindowStart throws an exception for Number.POSITIVE_INFINITY.");
+
+ assert_throws(new TypeError(),
+ function() { sourceBuffer.appendWindowStart = Number.NaN; },
+ "set appendWindowStart throws an exception for Number.NaN.");
+
+ assert_throws("InvalidAccessError",
+ function() { sourceBuffer.appendWindowStart = 600.0; },
+ "set appendWindowStart throws an exception when greater than appendWindowEnd.");
+
+ assert_throws("InvalidAccessError",
+ function() { sourceBuffer.appendWindowStart = sourceBuffer.appendWindowEnd; },
+ "set appendWindowStart throws an exception when equal to appendWindowEnd.");
+
+ assert_throws("InvalidAccessError",
+ function() { sourceBuffer.appendWindowEnd = sourceBuffer.appendWindowStart; },
+ "set appendWindowEnd throws an exception when equal to appendWindowStart.");
+
+ assert_throws("InvalidAccessError",
+ function() { sourceBuffer.appendWindowEnd = sourceBuffer.appendWindowStart - 1; },
+ "set appendWindowEnd throws an exception if less than appendWindowStart.");
+
+ assert_throws("InvalidAccessError",
+ function() { sourceBuffer.appendWindowStart = -100.0; },
+ "set appendWindowStart throws an exception when less than 0.");
+
+ assert_throws("InvalidAccessError",
+ function() { sourceBuffer.appendWindowEnd = -100.0; },
+ "set appendWindowEnd throws an exception when less than 0.");
+
+ assert_throws("InvalidAccessError",
+ function() { sourceBuffer.appendWindowEnd = Number.NaN; },
+ "set appendWindowEnd throws an exception if NaN.");
+
+ assert_throws("InvalidAccessError",
+ function() { sourceBuffer.appendWindowEnd = undefined; },
+ "set appendWindowEnd throws an exception if undefined.");
+
+ assert_throws({name: "TypeError"},
+ function() { sourceBuffer.appendWindowStart = undefined; },
+ "set appendWindowStart throws an exception if undefined.");
+
+ test.done();
+ }, "Test set wrong values to appendWindowStart and appendWindowEnd.");
+
+ mediasource_test(function(test, mediaElement, mediaSource)
+ {
+ var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_VIDEO_TYPE);
+ assert_true(sourceBuffer != null, "New SourceBuffer returned");
+
+ sourceBuffer.appendWindowStart = "";
+ assert_true(sourceBuffer.appendWindowStart == 0, "appendWindowStart is 0");
+
+ sourceBuffer.appendWindowStart = "10";
+ assert_true(sourceBuffer.appendWindowStart == 10, "appendWindowStart is 10");
+
+ sourceBuffer.appendWindowStart = null;
+ assert_true(sourceBuffer.appendWindowStart == 0, "appendWindowStart is 0");
+
+ sourceBuffer.appendWindowStart = true;
+ assert_true(sourceBuffer.appendWindowStart == 1, "appendWindowStart is 1");
+
+ sourceBuffer.appendWindowStart = false;
+ assert_true(sourceBuffer.appendWindowStart == 0, "appendWindowStart is 0");
+
+ sourceBuffer.appendWindowEnd = "100";
+ assert_true(sourceBuffer.appendWindowEnd == 100, "appendWindowEnd is 100");
+
+ test.done();
+
+ }, "Test set correct values to appendWindowStart and appendWindowEnd.");
+
+ mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
+ {
+ mediaSource.removeSourceBuffer(sourceBuffer);
+ assert_throws("InvalidStateError",
+ function() { sourceBuffer.appendWindowStart = 100.0; },
+ "set appendWindowStart throws an exception when mediasource object is not associated with a buffer.");
+
+ assert_throws("InvalidStateError",
+ function() { sourceBuffer.appendWindowEnd = 500.0; },
+ "set appendWindowEnd throws an exception when mediasource object is not associated with a buffer.");
+ test.done();
+
+ }, "Test appendwindow throw error when mediasource object is not associated with a sourebuffer.");
+
+ mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
+ {
+ test.expectEvent(sourceBuffer, "updateend", "sourceBuffer");
+ sourceBuffer.appendBuffer(mediaData);
+ assert_true(sourceBuffer.updating, "updating attribute is true");
+
+ assert_throws("InvalidStateError",
+ function() { sourceBuffer.appendWindowStart = 100.0; },
+ "set appendWindowStart throws an exception when there is a pending append.");
+
+ assert_throws("InvalidStateError",
+ function() { sourceBuffer.appendWindowEnd = 500.0; },
+ "set appendWindowEnd throws an exception when there is a pending append.");
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_false(sourceBuffer.updating, "updating attribute is false");
+ test.done();
+ });
+ }, "Test set appendWindowStart and appendWindowEnd when source buffer updating.");
+
+ mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
+ {
+ test.expectEvent(sourceBuffer, "updateend", "sourceBuffer");
+ sourceBuffer.appendBuffer(mediaData);
+ assert_true(sourceBuffer.updating, "updating attribute is true");
+
+ sourceBuffer.abort();
+ assert_equals(sourceBuffer.appendWindowStart, 0, "appendWindowStart is 0 after an abort'");
+ assert_equals(sourceBuffer.appendWindowEnd, Number.POSITIVE_INFINITY,
+ "appendWindowStart is POSITIVE_INFINITY after an abort");
+ test.waitForExpectedEvents(function()
+ {
+ assert_false(sourceBuffer.updating, "updating attribute is false");
+ test.done();
+ });
+ }, "Test appendWindowStart and appendWindowEnd value after a sourceBuffer.abort().");
+
+ mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
+ {
+ assert_equals(sourceBuffer.appendWindowStart, 0, "appendWindowStart is 0 initially");
+ assert_equals(sourceBuffer.appendWindowEnd, Number.POSITIVE_INFINITY,
+ "appendWindowStart is POSITIVE_INFINITY initially");
+ test.done();
+ }, "Test read appendWindowStart and appendWindowEnd initial values.");
+
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/media-source/mediasource-buffered.html b/tests/wpt/web-platform-tests/media-source/mediasource-buffered.html
new file mode 100644
index 00000000000..e39acd5b28a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mediasource-buffered.html
@@ -0,0 +1,219 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>SourceBuffer.buffered test cases.</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="mediasource-util.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var subType = MediaSourceUtil.getSubType(MediaSourceUtil.AUDIO_ONLY_TYPE);
+
+ var manifestFilenameA = subType + "/test-a-128k-44100Hz-1ch-manifest.json";
+ var manifestFilenameB = subType + "/test-v-128k-320x240-30fps-10kfr-manifest.json";
+
+ var expectationsA = {
+ webm: "{ [0.000, 2.022) }",
+ mp4: "{ [0.000, 2.043) }",
+ };
+
+ var expectationsB = {
+ webm: "{ [0.000, 2.000) }",
+ mp4: "{ [0.000, 2.000) }",
+ };
+
+ function mediaSourceDemuxedTest(callback, description)
+ {
+ mediasource_test(function(test, mediaElement, mediaSource)
+ {
+ mediaElement.pause();
+ test.failOnEvent(mediaElement, "error");
+ test.endOnEvent(mediaElement, "ended");
+
+ MediaSourceUtil.fetchManifestAndData(test, manifestFilenameA, function(typeA, dataA)
+ {
+ MediaSourceUtil.fetchManifestAndData(test, manifestFilenameB, function(typeB, dataB)
+ {
+ mediaSource.addSourceBuffer(typeA);
+ mediaSource.addSourceBuffer(typeB);
+ assert_equals(mediaSource.sourceBuffers.length, 2);
+
+ callback(test, mediaElement, mediaSource, dataA, dataB);
+ });
+ });
+ }, description);
+ };
+
+ function appendData(test, mediaSource, dataA, dataB, callback)
+ {
+ var sourceBufferA = mediaSource.sourceBuffers[0];
+ var sourceBufferB = mediaSource.sourceBuffers[1];
+
+ test.expectEvent(sourceBufferA, "update");
+ test.expectEvent(sourceBufferA, "updateend");
+ sourceBufferA.appendBuffer(dataA);
+
+ test.expectEvent(sourceBufferB, "update");
+ test.expectEvent(sourceBufferB, "updateend");
+ sourceBufferB.appendBuffer(dataB);
+
+ test.waitForExpectedEvents(function()
+ {
+ callback();
+ });
+ }
+
+ mediaSourceDemuxedTest(function(test, mediaElement, mediaSource, dataA, dataB) {
+ test.expectEvent(mediaElement, "loadedmetadata");
+ appendData(test, mediaSource, dataA, dataB, function()
+ {
+ assertBufferedEquals(mediaSource.activeSourceBuffers[0], expectationsA[subType], "mediaSource.activeSourceBuffers[0]");
+ assertBufferedEquals(mediaSource.activeSourceBuffers[1], expectationsB[subType], "mediaSource.activeSourceBuffers[1]");
+ assertBufferedEquals(mediaElement, expectationsB[subType], "mediaElement.buffered");
+
+ mediaSource.endOfStream();
+
+ assertBufferedEquals(mediaSource.activeSourceBuffers[0], expectationsA[subType], "mediaSource.activeSourceBuffers[0]");
+ assertBufferedEquals(mediaSource.activeSourceBuffers[1], expectationsB[subType], "mediaSource.activeSourceBuffers[1]");
+ assertBufferedEquals(mediaElement, expectationsA[subType], "mediaElement.buffered");
+
+ test.done();
+ });
+ }, "Demuxed content with different lengths");
+
+ mediasource_test(function(test, mediaElement, mediaSource)
+ {
+ mediaElement.pause();
+ test.failOnEvent(mediaElement, "error");
+ test.endOnEvent(mediaElement, "ended");
+
+ MediaSourceUtil.fetchManifestAndData(test, subType + "/test-av-384k-44100Hz-1ch-320x240-30fps-10kfr-manifest.json", function(type, data)
+ {
+ var sourceBuffer = mediaSource.addSourceBuffer(type);
+ test.expectEvent(sourceBuffer, "update");
+ test.expectEvent(sourceBuffer, "updateend");
+ sourceBuffer.appendBuffer(data);
+
+ test.waitForExpectedEvents(function()
+ {
+ var expectationsAV = {
+ webm: ["{ [0.000, 2.003) }", "{ [0.000, 2.022) }"],
+ mp4: ["{ [0.000, 2.000) }", "{ [0.000, 2.043) }"],
+ };
+
+ var expectedBeforeEndOfStream = expectationsAV[subType][0];
+ var expectedAfterEndOfStream = expectationsAV[subType][1];
+
+ assertBufferedEquals(mediaSource.activeSourceBuffers[0], expectedBeforeEndOfStream, "mediaSource.activeSourceBuffers[0]");
+ assertBufferedEquals(mediaElement, expectedBeforeEndOfStream, "mediaElement.buffered");
+
+ mediaSource.endOfStream();
+
+ assertBufferedEquals(mediaSource.activeSourceBuffers[0], expectedAfterEndOfStream, "mediaSource.activeSourceBuffers[0]");
+ assertBufferedEquals(mediaElement, expectedAfterEndOfStream, "mediaElement.buffered");
+
+ test.done();
+ });
+ });
+ }, "Muxed content with different lengths");
+
+ mediaSourceDemuxedTest(function(test, mediaElement, mediaSource, dataA, dataB) {
+ var dataBSize = {
+ webm: 318,
+ mp4: 835,
+ };
+ test.expectEvent(mediaElement, "loadedmetadata");
+ appendData(test, mediaSource, dataA, dataB.subarray(0, dataBSize[subType]), function()
+ {
+ assertBufferedEquals(mediaSource.activeSourceBuffers[0], expectationsA[subType], "mediaSource.activeSourceBuffers[0]");
+ assertBufferedEquals(mediaSource.activeSourceBuffers[1], "{ }", "mediaSource.activeSourceBuffers[1]");
+ assertBufferedEquals(mediaElement, "{ }", "mediaElement.buffered");
+
+ mediaSource.endOfStream();
+
+ assertBufferedEquals(mediaSource.activeSourceBuffers[0], expectationsA[subType], "mediaSource.activeSourceBuffers[0]");
+ assertBufferedEquals(mediaSource.activeSourceBuffers[1], "{ }", "mediaSource.activeSourceBuffers[1]");
+ assertBufferedEquals(mediaElement, "{ }", "mediaElement.buffered");
+
+ test.done();
+ });
+ }, "Demuxed content with an empty buffered range on one SourceBuffer");
+
+ mediasource_test(function(test, mediaElement, mediaSource)
+ {
+ mediaElement.pause();
+ test.failOnEvent(mediaElement, "error");
+ test.endOnEvent(mediaElement, "ended");
+
+ MediaSourceUtil.fetchManifestAndData(test, subType + "/test-av-384k-44100Hz-1ch-320x240-30fps-10kfr-manifest.json", function(type, data)
+ {
+ var sourceBuffer = mediaSource.addSourceBuffer(type);
+ test.expectEvent(mediaElement, "loadedmetadata");
+ test.expectEvent(sourceBuffer, "update");
+ test.expectEvent(sourceBuffer, "updateend");
+ sourceBuffer.appendBuffer(data.subarray(0, 4052));
+
+ test.waitForExpectedEvents(function()
+ {
+ assertBufferedEquals(mediaSource.activeSourceBuffers[0], "{ }", "mediaSource.activeSourceBuffers[0]");
+ assertBufferedEquals(mediaElement, "{ }", "mediaElement.buffered");
+
+ mediaSource.endOfStream();
+
+ assertBufferedEquals(mediaSource.activeSourceBuffers[0], "{ }", "mediaSource.activeSourceBuffers[0]");
+ assertBufferedEquals(mediaElement, "{ }", "mediaElement.buffered");
+
+ test.done();
+ });
+ });
+ }, "Muxed content empty buffered ranges.");
+
+ mediasource_test(function(test, mediaElement, mediaSource)
+ {
+ mediaElement.pause();
+ test.failOnEvent(mediaElement, "error");
+ test.endOnEvent(mediaElement, "ended");
+
+ var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_ONLY_TYPE);
+
+ assertBufferedEquals(mediaSource.sourceBuffers[0], "{ }", "mediaSource.sourceBuffers[0]");
+ assertBufferedEquals(mediaElement, "{ }", "mediaElement.buffered");
+ test.done();
+
+ }, "Get buffered range when sourcebuffer is empty.");
+
+ mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
+ {
+ var initSegment = MediaSourceUtil.extractSegmentData(mediaData, segmentInfo.init);
+
+ test.expectEvent(mediaElement, "loadedmetadata");
+ test.expectEvent(sourceBuffer, "updateend", "initSegment append ended.");
+ sourceBuffer.appendBuffer(initSegment);
+ test.waitForExpectedEvents(function()
+ {
+ assertBufferedEquals(mediaSource.sourceBuffers[0], "{ }", "mediaSource.sourceBuffers[0]");
+ assertBufferedEquals(mediaSource.activeSourceBuffers[0], "{ }", "mediaSource.activeSourceBuffers[0]");
+ assertBufferedEquals(mediaElement, "{ }", "mediaElement.buffered");
+ test.done();
+ });
+
+ }, "Get buffered range when only init segment is appended.");
+
+ mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
+ {
+ test.expectEvent(mediaSource.sourceBuffers, "removesourcebuffer", "SourceBuffer removed.");
+ mediaSource.removeSourceBuffer(sourceBuffer);
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_throws("InvalidStateError",
+ function() { sourceBuffer.buffered; },
+ "get sourceBuffer.buffered throws an exception for InvalidStateError.");
+ test.done();
+ });
+ }, "Get buffered range after removing sourcebuffer.");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/media-source/mediasource-closed.html b/tests/wpt/web-platform-tests/media-source/mediasource-closed.html
new file mode 100644
index 00000000000..4f0dcca228c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mediasource-closed.html
@@ -0,0 +1,139 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>MediaSource.readyState equals "closed" test cases.</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="mediasource-util.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ test(function ()
+ {
+ var mediaSource = new MediaSource();
+ assert_equals(mediaSource.sourceBuffers.length, 0, "sourceBuffers is empty");
+ assert_equals(mediaSource.activeSourceBuffers.length, 0, "activeSourceBuffers is empty");
+ assert_equals(mediaSource.readyState, "closed", "readyState is 'closed'");
+ assert_true(isNaN(mediaSource.duration), "duration is NaN");
+ }, "Test attribute values on a closed MediaSource object.");
+
+ test(function ()
+ {
+ var mediaSource = new MediaSource();
+ assert_throws("InvalidStateError",
+ function() { mediaSource.addSourceBuffer(MediaSourceUtil.VIDEO_ONLY_TYPE); },
+ "addSourceBuffer() throws an exception when closed.");
+ }, "Test addSourceBuffer() while closed.");
+
+ mediasource_test(function(test, mediaElement, mediaSource)
+ {
+ var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_ONLY_TYPE);
+
+ // Setup a handler to run when the MediaSource closes.
+ mediaSource.addEventListener('sourceclose', test.step_func(function (event)
+ {
+ assert_equals(mediaSource.sourceBuffers.length, 0, "sourceBuffers is empty");
+ assert_equals(mediaSource.activeSourceBuffers.length, 0, "activeSourceBuffers is empty");
+ assert_equals(mediaSource.readyState, "closed", "readyState is 'closed'");
+ assert_throws("NotFoundError",
+ function() { mediaSource.removeSourceBuffer(sourceBuffer); },
+ "removeSourceBuffer() throws an exception when closed.");
+ test.done();
+ }));
+
+ // Trigger the MediaSource to close.
+ mediaElement.src = "";
+ }, "Test removeSourceBuffer() while closed.");
+
+ test(function ()
+ {
+ var mediaSource = new MediaSource();
+ assert_throws("InvalidStateError",
+ function() { mediaSource.endOfStream(); },
+ "endOfStream() throws an exception when closed.");
+ }, "Test endOfStream() while closed.");
+
+ test(function ()
+ {
+ var mediaSource = new MediaSource();
+ assert_throws("InvalidStateError",
+ function() { mediaSource.endOfStream("decode"); },
+ "endOfStream(decode) throws an exception when closed.");
+ }, "Test endOfStream(decode) while closed.");
+
+ test(function ()
+ {
+ var mediaSource = new MediaSource();
+ assert_throws("InvalidStateError",
+ function() { mediaSource.endOfStream("network"); },
+ "endOfStream(network) throws an exception when closed.");
+ }, "Test endOfStream(network) while closed.");
+
+ test(function ()
+ {
+ var mediaSource = new MediaSource();
+ assert_throws("InvalidStateError",
+ function() { mediaSource.duration = 10; },
+ "Setting duration throws an exception when closed.");
+ }, "Test setting duration while closed.");
+
+ mediasource_test(function(test, mediaElement, mediaSource)
+ {
+ var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_ONLY_TYPE);
+
+ assert_equals(mediaSource.readyState, "open", "readyState is 'open'");
+ // Setup a handler to run when the MediaSource closes.
+ mediaSource.addEventListener("sourceclose", test.step_func(function (event)
+ {
+ assert_equals(mediaSource.readyState, "closed", "readyState is 'closed'");
+ assert_throws("InvalidStateError",
+ function() { mediaSource.duration = 10; },
+ "Setting duration when closed throws an exception");
+ test.done();
+ }));
+
+ // Trigger the MediaSource to close.
+ mediaElement.src = "";
+ }, "Test setting duration while open->closed.");
+
+ mediasource_test(function(test, mediaElement, mediaSource)
+ {
+ var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_ONLY_TYPE);
+
+ assert_equals(mediaSource.readyState, "open", "readyState is 'open'");
+ // Setup a handler to run when the MediaSource closes.
+ mediaSource.addEventListener("sourceclose", test.step_func(function (event)
+ {
+ assert_equals(mediaSource.readyState, "closed", "readyState is 'closed'");
+ assert_true(isNaN(mediaSource.duration), "duration is NaN");
+ test.done();
+ }));
+
+ // Trigger the MediaSource to close.
+ mediaElement.src = "";
+ }, "Test getting duration while open->closed.");
+
+ mediasource_test(function(test, mediaElement, mediaSource)
+ {
+ var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_ONLY_TYPE);
+
+ assert_equals(mediaSource.readyState, "open", "readyState is open");
+
+ // Setup a handler to run when the MediaSource closes.
+ mediaSource.addEventListener("sourceclose", test.step_func(function (event)
+ {
+ assert_equals(mediaSource.readyState, "closed", "readyState is closed");
+ assert_throws("InvalidStateError",
+ function() { sourceBuffer.abort(); },
+ "sourceBuffer.abort() throws INVALID_STATE_ERROR");
+ test.done();
+ }));
+
+ // Trigger the MediaSource to close.
+ mediaElement.src = "";
+ }, "Test sourcebuffer.abort when closed.");
+
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/media-source/mediasource-config-change-mp4-a-bitrate.html b/tests/wpt/web-platform-tests/media-source/mediasource-config-change-mp4-a-bitrate.html
new file mode 100644
index 00000000000..865fadd6d3f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mediasource-config-change-mp4-a-bitrate.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>MP4 audio-only bitrate change.</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="mediasource-util.js"></script>
+ <script src="mediasource-config-changes.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ mediaSourceConfigChangeTest("mp4", "a-128k-44100Hz-1ch", "a-192k-44100Hz-1ch", "Tests mp4 audio-only bitrate changes.");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/media-source/mediasource-config-change-mp4-av-audio-bitrate.html b/tests/wpt/web-platform-tests/media-source/mediasource-config-change-mp4-av-audio-bitrate.html
new file mode 100644
index 00000000000..75d6e4101a4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mediasource-config-change-mp4-av-audio-bitrate.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>MP4 muxed audio &amp; video with an audio bitrate change.</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="mediasource-util.js"></script>
+ <script src="mediasource-config-changes.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ mediaSourceConfigChangeTest("mp4", "av-384k-44100Hz-1ch-640x480-30fps-10kfr", "av-448k-44100Hz-1ch-640x480-30fps-10kfr", "Tests mp4 audio bitrate changes in multiplexed content.");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/media-source/mediasource-config-change-mp4-av-framesize.html b/tests/wpt/web-platform-tests/media-source/mediasource-config-change-mp4-av-framesize.html
new file mode 100644
index 00000000000..33dd51a2e58
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mediasource-config-change-mp4-av-framesize.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>MP4 muxed audio &amp; video with a video frame size change.</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="mediasource-util.js"></script>
+ <script src="mediasource-config-changes.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ mediaSourceConfigChangeTest("mp4", "av-384k-44100Hz-1ch-320x240-30fps-10kfr", "av-384k-44100Hz-1ch-640x480-30fps-10kfr", "Tests mp4 frame size changes in multiplexed content.");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/media-source/mediasource-config-change-mp4-av-video-bitrate.html b/tests/wpt/web-platform-tests/media-source/mediasource-config-change-mp4-av-video-bitrate.html
new file mode 100644
index 00000000000..fce35552491
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mediasource-config-change-mp4-av-video-bitrate.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>MP4 muxed audio &amp; video with a video bitrate change.</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="mediasource-util.js"></script>
+ <script src="mediasource-config-changes.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ mediaSourceConfigChangeTest("mp4", "av-384k-44100Hz-1ch-640x480-30fps-10kfr", "av-640k-44100Hz-1ch-640x480-30fps-10kfr", "Tests mp4 video bitrate changes in multiplexed content.");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/media-source/mediasource-config-change-mp4-v-bitrate.html b/tests/wpt/web-platform-tests/media-source/mediasource-config-change-mp4-v-bitrate.html
new file mode 100644
index 00000000000..ce1977ad186
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mediasource-config-change-mp4-v-bitrate.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>MP4 video-only bitrate change.</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="mediasource-util.js"></script>
+ <script src="mediasource-config-changes.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ mediaSourceConfigChangeTest("mp4", "v-128k-320x240-30fps-10kfr", "v-256k-320x240-30fps-10kfr", "Tests mp4 video-only bitrate changes.");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/media-source/mediasource-config-change-mp4-v-framerate.html b/tests/wpt/web-platform-tests/media-source/mediasource-config-change-mp4-v-framerate.html
new file mode 100644
index 00000000000..65266c4d878
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mediasource-config-change-mp4-v-framerate.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>MP4 video-only frame rate change.</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="mediasource-util.js"></script>
+ <script src="mediasource-config-changes.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ mediaSourceConfigChangeTest("mp4", "v-128k-320x240-24fps-8kfr", "v-128k-320x240-30fps-10kfr", "Tests mp4 video-only frame rate changes.");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/media-source/mediasource-config-change-mp4-v-framesize.html b/tests/wpt/web-platform-tests/media-source/mediasource-config-change-mp4-v-framesize.html
new file mode 100644
index 00000000000..5005903589d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mediasource-config-change-mp4-v-framesize.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>MP4 video-only frame size change.</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="mediasource-util.js"></script>
+ <script src="mediasource-config-changes.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ mediaSourceConfigChangeTest("mp4", "v-128k-320x240-30fps-10kfr", "v-128k-640x480-30fps-10kfr", "Tests mp4 video-only frame size changes.");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/media-source/mediasource-config-change-webm-a-bitrate.html b/tests/wpt/web-platform-tests/media-source/mediasource-config-change-webm-a-bitrate.html
new file mode 100644
index 00000000000..99f661e0372
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mediasource-config-change-webm-a-bitrate.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>WebM audio-only bitrate change.</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="mediasource-util.js"></script>
+ <script src="mediasource-config-changes.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ mediaSourceConfigChangeTest("webm", "a-128k-44100Hz-1ch", "a-192k-44100Hz-1ch", "Tests webm audio-only bitrate changes.");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/media-source/mediasource-config-change-webm-av-audio-bitrate.html b/tests/wpt/web-platform-tests/media-source/mediasource-config-change-webm-av-audio-bitrate.html
new file mode 100644
index 00000000000..e3acc9850be
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mediasource-config-change-webm-av-audio-bitrate.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>WebM muxed audio &amp; video with an audio bitrate change.</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="mediasource-util.js"></script>
+ <script src="mediasource-config-changes.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ mediaSourceConfigChangeTest("webm", "av-384k-44100Hz-1ch-640x480-30fps-10kfr", "av-448k-44100Hz-1ch-640x480-30fps-10kfr", "Tests webm audio bitrate changes in multiplexed content.");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/media-source/mediasource-config-change-webm-av-framesize.html b/tests/wpt/web-platform-tests/media-source/mediasource-config-change-webm-av-framesize.html
new file mode 100644
index 00000000000..875bda40d3c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mediasource-config-change-webm-av-framesize.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>WebM muxed audio &amp; video with a video frame size change.</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="mediasource-util.js"></script>
+ <script src="mediasource-config-changes.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ mediaSourceConfigChangeTest("webm", "av-384k-44100Hz-1ch-320x240-30fps-10kfr", "av-384k-44100Hz-1ch-640x480-30fps-10kfr", "Tests webm frame size changes in multiplexed content.");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/media-source/mediasource-config-change-webm-av-video-bitrate.html b/tests/wpt/web-platform-tests/media-source/mediasource-config-change-webm-av-video-bitrate.html
new file mode 100644
index 00000000000..ca2e620a90c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mediasource-config-change-webm-av-video-bitrate.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>WebM muxed audio &amp; video with a video bitrate change.</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="mediasource-util.js"></script>
+ <script src="mediasource-config-changes.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ mediaSourceConfigChangeTest("webm", "av-384k-44100Hz-1ch-640x480-30fps-10kfr", "av-640k-44100Hz-1ch-640x480-30fps-10kfr", "Tests webm video bitrate changes in multiplexed content.");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/media-source/mediasource-config-change-webm-v-bitrate.html b/tests/wpt/web-platform-tests/media-source/mediasource-config-change-webm-v-bitrate.html
new file mode 100644
index 00000000000..c17f5ae9aa3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mediasource-config-change-webm-v-bitrate.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>WebM video-only bitrate change.</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="mediasource-util.js"></script>
+ <script src="mediasource-config-changes.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ mediaSourceConfigChangeTest("webm", "v-128k-320x240-30fps-10kfr", "v-256k-320x240-30fps-10kfr", "Tests webm video-only bitrate changes.");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/media-source/mediasource-config-change-webm-v-framerate.html b/tests/wpt/web-platform-tests/media-source/mediasource-config-change-webm-v-framerate.html
new file mode 100644
index 00000000000..d66de06b769
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mediasource-config-change-webm-v-framerate.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>WebM video-only frame rate change.</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="mediasource-util.js"></script>
+ <script src="mediasource-config-changes.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ mediaSourceConfigChangeTest("webm", "v-128k-320x240-24fps-8kfr", "v-128k-320x240-30fps-10kfr", "Tests webm video-only frame rate changes.");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/media-source/mediasource-config-change-webm-v-framesize.html b/tests/wpt/web-platform-tests/media-source/mediasource-config-change-webm-v-framesize.html
new file mode 100644
index 00000000000..cd17671c846
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mediasource-config-change-webm-v-framesize.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>WebM video-only frame size change.</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="mediasource-util.js"></script>
+ <script src="mediasource-config-changes.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ mediaSourceConfigChangeTest("webm", "v-128k-320x240-30fps-10kfr", "v-128k-640x480-30fps-10kfr", "Tests webm video-only frame size changes.");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/media-source/mediasource-config-changes.js b/tests/wpt/web-platform-tests/media-source/mediasource-config-changes.js
new file mode 100644
index 00000000000..586e25f2b30
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mediasource-config-changes.js
@@ -0,0 +1,101 @@
+// Extract & return the resolution string from a filename, if any.
+function resolutionFromFilename(filename)
+{
+ resolution = filename.replace(/^.*[^0-9]([0-9]+x[0-9]+)[^0-9].*$/, "$1");
+ if (resolution != filename) {
+ return resolution;
+ }
+ return "";
+}
+
+function appendBuffer(test, sourceBuffer, data)
+{
+ test.expectEvent(sourceBuffer, "update");
+ test.expectEvent(sourceBuffer, "updateend");
+ sourceBuffer.appendBuffer(data);
+}
+
+function mediaSourceConfigChangeTest(directory, idA, idB, description)
+{
+ var manifestFilenameA = directory + "/test-" + idA + "-manifest.json";
+ var manifestFilenameB = directory + "/test-" + idB + "-manifest.json";
+ mediasource_test(function(test, mediaElement, mediaSource)
+ {
+ mediaElement.pause();
+ test.failOnEvent(mediaElement, 'error');
+ var expectResizeEvents = resolutionFromFilename(manifestFilenameA) != resolutionFromFilename(manifestFilenameB);
+ var expectedResizeEventCount = 0;
+
+ MediaSourceUtil.fetchManifestAndData(test, manifestFilenameA, function(typeA, dataA)
+ {
+ MediaSourceUtil.fetchManifestAndData(test, manifestFilenameB, function(typeB, dataB)
+ {
+ assert_equals(typeA, typeB, "Media format types match");
+
+ var sourceBuffer = mediaSource.addSourceBuffer(typeA);
+
+ appendBuffer(test, sourceBuffer, dataA);
+ ++expectedResizeEventCount;
+
+ test.waitForExpectedEvents(function()
+ {
+ // Add the second buffer starting at 0.5 second.
+ sourceBuffer.timestampOffset = 0.5;
+ appendBuffer(test, sourceBuffer, dataB);
+ ++expectedResizeEventCount;
+ });
+
+ test.waitForExpectedEvents(function()
+ {
+ // Add the first buffer starting at 1 second.
+ sourceBuffer.timestampOffset = 1;
+ appendBuffer(test, sourceBuffer, dataA);
+ ++expectedResizeEventCount;
+ });
+
+ test.waitForExpectedEvents(function()
+ {
+ // Add the second buffer starting at 1.5 second.
+ sourceBuffer.timestampOffset = 1.5;
+ appendBuffer(test, sourceBuffer, dataB);
+ ++expectedResizeEventCount;
+ });
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_false(sourceBuffer.updating, "updating");
+ assert_greater_than(mediaSource.duration, 2, "duration");
+
+ // Truncate the presentation to a duration of 2 seconds.
+ mediaSource.duration = 2;
+
+ assert_true(sourceBuffer.updating, "updating");
+ test.expectEvent(sourceBuffer, 'updatestart', 'sourceBuffer');
+ test.expectEvent(sourceBuffer, 'update', 'sourceBuffer');
+ test.expectEvent(sourceBuffer, 'updateend', 'sourceBuffer');
+ });
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_false(sourceBuffer.updating, "updating");
+
+ mediaSource.endOfStream();
+
+ assert_false(sourceBuffer.updating, "updating");
+
+ if (expectResizeEvents) {
+ for (var i = 0; i < expectedResizeEventCount; ++i) {
+ test.expectEvent(mediaElement, "resize");
+ }
+ }
+ test.expectEvent(mediaElement, "ended");
+ mediaElement.play();
+ });
+
+ test.waitForExpectedEvents(function() {
+ test.done();
+ });
+ });
+ });
+ }, description, { timeout: 10000 } );
+};
diff --git a/tests/wpt/web-platform-tests/media-source/mediasource-duration-boundaryconditions.html b/tests/wpt/web-platform-tests/media-source/mediasource-duration-boundaryconditions.html
new file mode 100644
index 00000000000..4521fd08fd3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mediasource-duration-boundaryconditions.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>MediaSource.duration boundary condition test cases.</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="mediasource-util.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ function DurationBoundaryConditionTest(testDurationValue, expectedError, description)
+ {
+ return mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
+ {
+ // Append initialization segment.
+ test.expectEvent(sourceBuffer, "updateend", "sourceBuffer");
+ test.expectEvent(mediaElement, "loadedmetadata", "mediaElement");
+ sourceBuffer.appendBuffer(MediaSourceUtil.extractSegmentData(mediaData, segmentInfo.init));
+ test.waitForExpectedEvents(function()
+ {
+ if (expectedError) {
+ assert_throws(expectedError,
+ function() { mediaSource.duration = testDurationValue; },
+ "mediaSource.duration assignment throws an exception for " + testDurationValue);
+ test.done();
+ return;
+ }
+
+ mediaSource.duration = testDurationValue;
+
+ assert_equals(mediaSource.duration, testDurationValue, "mediaSource.duration");
+ assert_equals(mediaElement.duration, testDurationValue, "mediaElement.duration");
+
+ test.expectEvent(mediaElement, "durationchange", "mediaElement");
+ test.waitForExpectedEvents(function()
+ {
+ assert_equals(mediaSource.duration, testDurationValue, "mediaSource.duration");
+ assert_equals(mediaElement.duration, testDurationValue, "mediaElement.duration");
+ test.done();
+ });
+ });
+
+ }, description);
+ }
+
+ DurationBoundaryConditionTest(Math.pow(2, 31) - 1, null, "Set duration to 2^31 - 1");
+ DurationBoundaryConditionTest(1, null, "Set duration to 1");
+ DurationBoundaryConditionTest(Number.MAX_VALUE, null, "Set duration to Number.MAX_VALUE");
+ DurationBoundaryConditionTest(Number.MIN_VALUE, null, "Set duration to Number.MIN_VALUE");
+ DurationBoundaryConditionTest(Number.MAX_VALUE - 1, null, "Set duration to Number.MAX_VALUE - 1");
+ DurationBoundaryConditionTest(Number.MIN_VALUE - 1, "InvalidAccessError", "Set duration to Number.MIN_VALUE - 1");
+ DurationBoundaryConditionTest(Number.POSITIVE_INFINITY, null, "Set duration to Number.POSITIVE_INFINITY");
+ DurationBoundaryConditionTest(Number.NEGATIVE_INFINITY, "InvalidAccessError", "Set duration to Number.NEGATIVE_INFINITY");
+ DurationBoundaryConditionTest(-1 * Number.MAX_VALUE, "InvalidAccessError", "Set duration to lowest value.");
+ DurationBoundaryConditionTest(-101.9, "InvalidAccessError", "Set duration to a negative double.");
+ DurationBoundaryConditionTest(101.9, null, "Set duration to a positive double.");
+ DurationBoundaryConditionTest(0, null, "Set duration to zero");
+ DurationBoundaryConditionTest(NaN, "InvalidAccessError", "Set duration to NaN");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/media-source/mediasource-duration.html b/tests/wpt/web-platform-tests/media-source/mediasource-duration.html
new file mode 100644
index 00000000000..ca6b25de73f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mediasource-duration.html
@@ -0,0 +1,217 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>MediaSource.duration &amp; HTMLMediaElement.duration test cases.</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="mediasource-util.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ function mediasource_truncated_duration_seek_test(testFunction, description, options)
+ {
+ return mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
+ {
+ assert_greater_than(segmentInfo.duration, 2, 'Sufficient test media duration');
+
+ var fullDuration = segmentInfo.duration;
+ var seekTo = fullDuration / 2.0;
+ var truncatedDuration = seekTo / 2.0;
+
+ mediaElement.play();
+
+ // Append all the segments
+ test.expectEvent(sourceBuffer, 'updateend', 'sourceBuffer');
+ test.expectEvent(mediaElement, 'playing', 'Playing triggered');
+ sourceBuffer.appendBuffer(mediaData);
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_equals(mediaElement.duration, fullDuration, 'mediaElement fullDuration');
+ assert_equals(mediaSource.duration, fullDuration, 'mediaSource fullDuration');
+
+ test.expectEvent(mediaElement, 'seeking', 'seeking to seekTo');
+ test.expectEvent(mediaElement, 'timeupdate', 'timeupdate while seeking to seekTo');
+ test.expectEvent(mediaElement, 'seeked', 'seeked to seekTo');
+ mediaElement.currentTime = seekTo;
+ assert_true(mediaElement.seeking, 'mediaElement.seeking (to seekTo)');
+ });
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_greater_than_equal(mediaElement.currentTime, seekTo, 'Playback time has reached seekTo');
+ assert_equals(mediaElement.duration, fullDuration, 'mediaElement fullDuration after seekTo');
+ assert_equals(mediaSource.duration, fullDuration, 'mediaSource fullDuration after seekTo');
+ assert_false(mediaElement.seeking, 'mediaElement.seeking after seeked to seekTo');
+
+ test.expectEvent(mediaElement, 'seeking', 'Seeking to truncated duration');
+
+ assert_false(sourceBuffer.updating, 'sourceBuffer.updating');
+
+ mediaSource.duration = truncatedDuration;
+
+ assert_true(sourceBuffer.updating, 'sourceBuffer.updating');
+ test.expectEvent(sourceBuffer, 'updatestart', 'sourceBuffer');
+ test.expectEvent(sourceBuffer, 'update', 'sourceBuffer');
+ test.expectEvent(sourceBuffer, 'updateend', 'sourceBuffer');
+
+ assert_true(mediaElement.seeking, 'Seeking after setting truncatedDuration');
+ });
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_equals(mediaElement.currentTime, truncatedDuration,
+ 'Playback time is truncatedDuration while seeking');
+ assert_true(mediaElement.seeking, 'mediaElement.seeking while seeking to truncatedDuration');
+ assert_equals(mediaElement.duration, truncatedDuration,
+ 'mediaElement truncatedDuration during seek to it');
+ assert_equals(mediaSource.duration, truncatedDuration,
+ 'mediaSource truncatedDuration during seek to it');
+
+ testFunction(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData,
+ truncatedDuration);
+ });
+ }, description, options);
+ }
+
+ mediasource_truncated_duration_seek_test(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer,
+ mediaData, truncatedDuration)
+ {
+ // Tests that duration truncation below current playback position
+ // starts seek to new duration.
+ test.done();
+ }, 'Test seek starts on duration truncation below currentTime');
+
+ mediasource_truncated_duration_seek_test(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer,
+ mediaData, truncatedDuration)
+ {
+ // The duration has been truncated at this point, and there is an
+ // outstanding seek pending.
+ test.expectEvent(sourceBuffer, 'updateend', 'updateend after appending more data');
+
+ test.expectEvent(mediaElement, 'timeupdate', 'timeupdate while finishing seek to truncatedDuration');
+ test.expectEvent(mediaElement, 'seeked', 'seeked to truncatedDuration');
+
+ // Allow seek to complete by appending more data beginning at the
+ // truncated duration timestamp.
+ sourceBuffer.timestampOffset = truncatedDuration;
+ sourceBuffer.appendBuffer(mediaData);
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_greater_than_equal(mediaElement.currentTime, truncatedDuration,
+ 'Playback time has reached truncatedDuration');
+ assert_approx_equals(mediaElement.duration, truncatedDuration + segmentInfo.duration, 0.05,
+ 'mediaElement duration increased by new append');
+ assert_equals(mediaSource.duration, mediaElement.duration,
+ 'mediaSource duration increased by new append');
+ assert_false(mediaElement.seeking, 'mediaElement.seeking after seeked to truncatedDuration');
+
+ test.done();
+ });
+ }, 'Test appendBuffer completes previous seek to truncated duration');
+
+ mediasource_truncated_duration_seek_test(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer,
+ mediaData, truncatedDuration)
+ {
+ // The duration has been truncated at this point, and there is an
+ // outstanding seek pending.
+ test.expectEvent(mediaSource, 'sourceended', 'endOfStream acknowledged');
+
+ test.expectEvent(mediaElement, 'timeupdate', 'timeupdate while finishing seek to truncatedDuration');
+ test.expectEvent(mediaElement, 'seeked', 'seeked to truncatedDuration');
+
+ // Call endOfStream() to complete the pending seek.
+ mediaSource.endOfStream();
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_equals(mediaElement.currentTime, truncatedDuration,
+ 'Playback time has reached truncatedDuration');
+ assert_equals(mediaElement.duration, truncatedDuration,
+ 'mediaElement truncatedDuration after seek to it');
+ assert_equals(mediaSource.duration, truncatedDuration,
+ 'mediaSource truncatedDuration after seek to it');
+ assert_false(mediaElement.seeking, 'mediaElement.seeking after seeked to truncatedDuration');
+
+ test.done();
+ });
+ }, 'Test endOfStream completes previous seek to truncated duration');
+
+ mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
+ {
+ assert_greater_than(segmentInfo.duration, 2, 'Sufficient test media duration');
+
+ var fullDuration = segmentInfo.duration;
+ var newDuration = 0.5;
+
+ var expectedDurationChangeEventCount = 1;
+ var durationchangeEventCounter = 0;
+ var durationchangeEventHandler = test.step_func(function(event)
+ {
+ assert_equals(mediaElement.duration, newDuration, 'mediaElement newDuration');
+ assert_equals(mediaSource.duration, newDuration, 'mediaSource newDuration');
+ durationchangeEventCounter++;
+ });
+
+ mediaElement.play();
+
+ // Append all the segments
+ test.expectEvent(sourceBuffer, 'updateend', 'sourceBuffer');
+ test.expectEvent(mediaElement, 'playing', 'Playing triggered');
+ sourceBuffer.appendBuffer(mediaData);
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_equals(mediaElement.duration, fullDuration, 'mediaElement fullDuration');
+ assert_equals(mediaSource.duration, fullDuration, 'mediaSource fullDuration');
+ assert_less_than(mediaElement.currentTime, newDuration / 2, 'mediaElement currentTime');
+
+ // Media load also fires 'durationchange' event, so only start counting them now.
+ mediaElement.addEventListener('durationchange', durationchangeEventHandler);
+
+ assert_false(sourceBuffer.updating, "updating");
+
+ // Truncate duration. This should result in one 'durationchange' fired.
+ mediaSource.duration = newDuration;
+
+ assert_true(sourceBuffer.updating, "updating");
+ test.expectEvent(sourceBuffer, 'updatestart', 'sourceBuffer');
+ test.expectEvent(sourceBuffer, 'update', 'sourceBuffer');
+ test.expectEvent(sourceBuffer, 'updateend', 'sourceBuffer');
+ });
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_false(sourceBuffer.updating, "updating");
+
+ // Set duration again to make sure it does not trigger another 'durationchange' event.
+ mediaSource.duration = newDuration;
+
+ // Mark endOfStream so that playback can reach 'ended' at the new duration.
+ test.expectEvent(mediaSource, 'sourceended', 'endOfStream acknowledged');
+ mediaSource.endOfStream();
+
+ // endOfStream can change duration downwards slightly.
+ // Allow for one more 'durationchange' event only in this case.
+ var currentDuration = mediaSource.duration;
+ if (currentDuration != newDuration) {
+ assert_true(currentDuration > 0 && currentDuration < newDuration, 'adjusted duration');
+ newDuration = currentDuration;
+ ++expectedDurationChangeEventCount;
+ }
+
+ // Allow media to play to end while counting 'durationchange' events.
+ test.expectEvent(mediaElement, 'ended', 'Playback ended');
+ test.waitForExpectedEvents(function()
+ {
+ mediaElement.removeEventListener('durationchange', durationchangeEventHandler);
+ assert_equals(durationchangeEventCounter, expectedDurationChangeEventCount, 'durationchanges');
+ test.done();
+ });
+ });
+ }, 'Test setting same duration multiple times does not fire duplicate durationchange', {timeout: 2500});
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/media-source/mediasource-endofstream-invaliderror.html b/tests/wpt/web-platform-tests/media-source/mediasource-endofstream-invaliderror.html
new file mode 100644
index 00000000000..e0096decc06
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mediasource-endofstream-invaliderror.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Invalid MediaSource.endOfStream() parameter test cases.</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="mediasource-util.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ mediasource_test(function(test, mediaElement, mediaSource)
+ {
+ test.failOnEvent(mediaElement, 'error');
+ assert_equals(mediaSource.readyState, 'open');
+
+ assert_throws(new TypeError(),
+ function() { mediaSource.endOfStream('garbage'); },
+ 'endOfStream(\'garbage\') throws TypeError');
+
+ assert_equals(mediaSource.readyState, 'open');
+ test.done();
+ }, 'Test MediaSource.endOfStream() with invalid non-empty error string.');
+
+ mediasource_test(function(test, mediaElement, mediaSource)
+ {
+ test.failOnEvent(mediaElement, 'error');
+ assert_equals(mediaSource.readyState, 'open');
+
+ assert_throws(new TypeError(),
+ function() { mediaSource.endOfStream(''); },
+ 'endOfStream(\'\') throws TypeError');
+
+ assert_equals(mediaSource.readyState, 'open');
+ test.done();
+ }, 'Test MediaSource.endOfStream() with invalid empty error string.');
+
+ mediasource_test(function(test, mediaElement, mediaSource)
+ {
+ test.failOnEvent(mediaElement, 'error');
+ assert_equals(mediaSource.readyState, 'open');
+
+ assert_throws(new TypeError(),
+ function() { mediaSource.endOfStream(null); },
+ 'endOfStream(null) throws TypeError');
+
+ assert_equals(mediaSource.readyState, 'open');
+ test.done();
+ }, 'Test MediaSource.endOfStream() with invalid null error parameter.');
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/media-source/mediasource-getvideoplaybackquality.html b/tests/wpt/web-platform-tests/media-source/mediasource-getvideoplaybackquality.html
new file mode 100644
index 00000000000..d813d631f95
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mediasource-getvideoplaybackquality.html
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>HTMLVideoElement.getVideoPlaybackQuality() test cases.</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="mediasource-util.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
+ {
+ var previousQuality = mediaElement.getVideoPlaybackQuality();
+ var timeUpdateCount = 0;
+ mediaElement.addEventListener("timeupdate", test.step_func(function (e)
+ {
+ var videoElement = e.target;
+ var newQuality = videoElement.getVideoPlaybackQuality();
+
+ assert_not_equals(previousQuality, newQuality, "Verify new object");
+ assert_greater_than(newQuality.creationTime, previousQuality.creationTime, "creationTime");
+
+ assert_greater_than_equal(newQuality.totalVideoFrames, 0, "totalVideoFrames >= 0");
+ assert_greater_than_equal(newQuality.totalVideoFrames, previousQuality.totalVideoFrames, "totalVideoFrames");
+
+ assert_greater_than_equal(newQuality.droppedVideoFrames, 0, "droppedVideoFrames >= 0");
+ assert_greater_than_equal(newQuality.droppedVideoFrames, previousQuality.droppedVideoFrames, "droppedVideoFrames");
+
+ assert_greater_than_equal(newQuality.corruptedVideoFrames, 0, "corruptedVideoFrames >= 0");
+ assert_greater_than_equal(newQuality.corruptedVideoFrames, previousQuality.corruptedVideoFrames, "corruptedVideoFrames");
+ previousQuality = newQuality;
+ timeUpdateCount++;
+ }));
+
+ test.failOnEvent(mediaElement, 'error');
+
+ test.expectEvent(sourceBuffer, 'updatestart', 'sourceBuffer');
+ test.expectEvent(sourceBuffer, 'update', 'sourceBuffer');
+ test.expectEvent(sourceBuffer, 'updateend', 'sourceBuffer');
+ sourceBuffer.appendBuffer(mediaData);
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_false(sourceBuffer.updating, "updating");
+ assert_greater_than(mediaSource.duration, 1, "duration");
+
+ mediaSource.duration = 1;
+
+ assert_true(sourceBuffer.updating, "updating");
+ test.expectEvent(sourceBuffer, 'updatestart', 'sourceBuffer');
+ test.expectEvent(sourceBuffer, 'update', 'sourceBuffer');
+ test.expectEvent(sourceBuffer, 'updateend', 'sourceBuffer');
+ });
+
+ test.waitForExpectedEvents(function()
+ {
+ mediaSource.endOfStream();
+ mediaElement.play();
+ test.expectEvent(mediaElement, 'ended', 'mediaElement');
+ });
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_greater_than(timeUpdateCount, 2, "timeUpdateCount");
+ test.done();
+ });
+ }, "Test HTMLVideoElement.getVideoPlaybackQuality() with MediaSource API", {timeout: 5000});
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/media-source/mediasource-is-type-supported.html b/tests/wpt/web-platform-tests/media-source/mediasource-is-type-supported.html
new file mode 100644
index 00000000000..289cce272d0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mediasource-is-type-supported.html
@@ -0,0 +1,80 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>MediaSource.isTypeSupported() test cases.</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ // Generate a distinct test for each type in types
+ function test_type_support(types, expectation, description)
+ {
+ for (var i = 0; i < types.length; ++i) {
+ test(function()
+ {
+ assert_equals(MediaSource.isTypeSupported(types[i]),
+ expectation, 'supported');
+ }, description + ' "' + types[i] + '"');
+ }
+ };
+
+ test_type_support([
+ 'video',
+ 'video/',
+ 'video/webm',
+ 'video/webm;',
+ 'video/webm;codecs',
+ 'video/webm;codecs=',
+ 'video/webm;codecs="',
+ 'video/webm;codecs=""',
+ 'video/webm;codecs=","',
+ '',
+ null
+ ], false, 'Test invalid MIME format');
+
+ test_type_support([
+ 'audio/webm;codecs="vp8"',
+ 'audio/mp4;codecs="avc1.4d001e"',
+ ], false, 'Test invalid mismatch between major type and codec ID');
+
+ test_type_support([
+ 'audio/mp4;codecs="vorbis"',
+ 'audio/webm;codecs="mp4a.40.2"',
+ 'video/mp4;codecs="vp8"',
+ 'video/webm;codecs="mp4a.40.2"',
+ 'video/mp4;codecs="vorbis"',
+ 'video/webm;codecs="mp4a.40.2"',
+ ], false, 'Test invalid mismatch between minor type and codec ID');
+
+ test_type_support([
+ 'audio/mp4;codecs="mp4a"',
+ 'audio/mp4;codecs="mp4a.40"',
+ 'audio/mp4;codecs="mp4a.40."',
+ 'audio/mp4;codecs="mp4a.67.3"'
+ ], false, 'Test invalid codec ID');
+
+ test_type_support([
+ 'video/webm;codecs="vp8"',
+ 'video/webm;codecs="vorbis"',
+ 'video/webm;codecs="vp8,vorbis"',
+ 'video/webm;codecs="vorbis, vp8"',
+ 'audio/webm;codecs="vorbis"',
+ 'AUDIO/WEBM;CODECS="vorbis"',
+ ], true, 'Test valid WebM type');
+
+ test_type_support([
+ 'video/mp4;codecs="avc1.4d001e"', // H.264 Main Profile level 3.0
+ 'video/mp4;codecs="avc1.42001e"', // H.264 Baseline Profile level 3.0
+ 'audio/mp4;codecs="mp4a.40.2"', // MPEG4 AAC-LC
+ 'audio/mp4;codecs="mp4a.40.5"', // MPEG4 HE-AAC
+ 'audio/mp4;codecs="mp4a.67"', // MPEG2 AAC-LC
+ 'video/mp4;codecs="mp4a.40.2"',
+ 'video/mp4;codecs="avc1.4d001e,mp4a.40.2"',
+ 'video/mp4;codecs="mp4a.40.2 , avc1.4d001e "',
+ 'video/mp4;codecs="avc1.4d001e,mp4a.40.5"',
+ ], true, 'Test valid MP4 type');
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/media-source/mediasource-multiple-attach.html b/tests/wpt/web-platform-tests/media-source/mediasource-multiple-attach.html
new file mode 100644
index 00000000000..d8152ff3044
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mediasource-multiple-attach.html
@@ -0,0 +1,113 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Test Attaching a MediaSource to multiple HTMLMediaElements.</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="mediasource-util.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ function twoMediaElementTest(testFunction, description)
+ {
+ media_test(function(test)
+ {
+ var firstMediaTag = document.createElement('video');
+ var secondMediaTag = document.createElement('video');
+ document.body.appendChild(firstMediaTag);
+ document.body.appendChild(secondMediaTag);
+
+ // Overload done() so that elements added to the document can be
+ // removed.
+ var removeMediaElements = true;
+ var oldTestDone = test.done.bind(test);
+ test.done = function()
+ {
+ if (removeMediaElements) {
+ document.body.removeChild(secondMediaTag);
+ document.body.removeChild(firstMediaTag);
+ removeMediaElements = false;
+ }
+ oldTestDone();
+ };
+
+ testFunction(test, firstMediaTag, secondMediaTag);
+ }, description);
+ }
+
+ twoMediaElementTest(function(test, firstMediaTag, secondMediaTag)
+ {
+ // When attachment of mediaSource to two MediaElements is done
+ // without an intervening stable state, exactly one of the two
+ // MediaElements should successfully attach, and the other one
+ // should get error event due to mediaSource already in 'open'
+ // readyState.
+ var mediaSource = new MediaSource();
+ var mediaSourceURL = URL.createObjectURL(mediaSource);
+ var gotSourceOpen = false;
+ var gotError = false;
+ var doneIfFinished = test.step_func(function()
+ {
+ if (gotSourceOpen && gotError)
+ test.done();
+ });
+ var errorHandler = test.step_func(function(e)
+ {
+ firstMediaTag.removeEventListener('error', errorHandler);
+ secondMediaTag.removeEventListener('error', errorHandler);
+
+ var eventTarget = e.target;
+ var otherTarget;
+ if (eventTarget == firstMediaTag) {
+ otherTarget = secondMediaTag;
+ } else {
+ assert_equals(eventTarget, secondMediaTag, 'Error target check');
+ otherTarget = firstMediaTag;
+ }
+
+ assert_true(eventTarget.error != null, 'Error state on one tag');
+ assert_equals(eventTarget.error.code, MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED, 'Expected error code');
+ assert_equals(otherTarget.error, null, 'No error on other tag');
+
+ assert_equals(eventTarget.networkState, HTMLMediaElement.NETWORK_NO_SOURCE,
+ 'Tag with error state networkState');
+ assert_equals(otherTarget.networkState, HTMLMediaElement.NETWORK_LOADING,
+ 'Tag without error state networkState');
+
+ gotError = true;
+ doneIfFinished();
+ });
+
+ test.expectEvent(mediaSource, 'sourceopen', 'An attachment succeeded');
+ firstMediaTag.addEventListener('error', errorHandler);
+ secondMediaTag.addEventListener('error', errorHandler);
+
+ firstMediaTag.src = mediaSourceURL;
+ secondMediaTag.src = mediaSourceURL;
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_equals(mediaSource.readyState, 'open', 'Source is opened');
+ gotSourceOpen = true;
+ doneIfFinished();
+ });
+ }, 'Test exactly one succeeds when two MediaElements attach to same MediaSource');
+
+ mediasource_test(function(test, mediaElement, mediaSource) {
+ assert_equals(mediaSource.readyState, 'open', 'Source open');
+ // Set the tag's src attribute. This should close mediaSource,
+ // reattach it to the tag, and initiate source reopening.
+ test.expectEvent(mediaSource, 'sourceopen', 'Source attached again');
+ mediaElement.src = URL.createObjectURL(mediaSource);
+ assert_equals(mediaSource.readyState, 'closed', 'Source closed');
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_equals(mediaSource.readyState, 'open', 'Source reopened');
+ test.done();
+ });
+ }, 'Test that MediaSource can reattach if closed first');
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/media-source/mediasource-play-then-seek-back.html b/tests/wpt/web-platform-tests/media-source/mediasource-play-then-seek-back.html
new file mode 100644
index 00000000000..bb2b747baf1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mediasource-play-then-seek-back.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Simple MediaSource playback &amp; seek test case.</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="mediasource-util.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+
+ mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
+ {
+
+ mediaElement.play();
+ // Append all the segments
+ test.expectEvent(sourceBuffer, 'updateend', 'sourceBuffer');
+ test.expectEvent(mediaElement, 'playing', 'Playing triggered');
+ sourceBuffer.appendBuffer(mediaData);
+
+ function confirmPlayThenEnd()
+ {
+ test.waitForCurrentTimeChange(mediaElement, function ()
+ {
+ assert_greater_than(mediaElement.currentTime, 0.0, 'Playback has started after seek.');
+ test.done();
+ });
+ }
+
+ function finishSeekThenPlay()
+ {
+ assert_true(mediaElement.seeking, 'mediaElement is seeking');
+ assert_equals(mediaElement.currentTime, 0.0, 'Current time is 0.0');
+ test.expectEvent(mediaElement, 'seeked', 'mediaElement finished seek');
+
+ test.waitForExpectedEvents(confirmPlayThenEnd);
+ }
+
+ function delayedPlayHandler()
+ {
+ assert_greater_than(mediaElement.currentTime, 0.0, 'Playback has started.');
+ test.expectEvent(mediaElement, 'seeking', 'mediaElement');
+ mediaElement.currentTime = 0.0;
+
+ test.waitForExpectedEvents(finishSeekThenPlay);
+ }
+
+ test.waitForExpectedEvents(function()
+ {
+ test.waitForCurrentTimeChange(mediaElement, delayedPlayHandler);
+ });
+
+ }, 'Test playing then seeking back.');
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/media-source/mediasource-play.html b/tests/wpt/web-platform-tests/media-source/mediasource-play.html
new file mode 100644
index 00000000000..73153462d77
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mediasource-play.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Simple MediaSource playback test case.</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="mediasource-util.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
+ {
+ test.failOnEvent(mediaElement, 'error');
+ test.endOnEvent(mediaElement, 'ended');
+
+ test.expectEvent(sourceBuffer, 'updatestart', 'sourceBuffer');
+ test.expectEvent(sourceBuffer, 'update', 'sourceBuffer');
+ test.expectEvent(sourceBuffer, 'updateend', 'sourceBuffer');
+
+ sourceBuffer.appendBuffer(mediaData);
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_false(sourceBuffer.updating, "updating");
+ assert_greater_than(mediaSource.duration, 1, "duration");
+
+ mediaSource.duration = 1;
+
+ assert_true(sourceBuffer.updating, "updating");
+ test.expectEvent(sourceBuffer, 'updatestart', 'sourceBuffer');
+ test.expectEvent(sourceBuffer, 'update', 'sourceBuffer');
+ test.expectEvent(sourceBuffer, 'updateend', 'sourceBuffer');
+ });
+
+ test.waitForExpectedEvents(function()
+ {
+ mediaSource.endOfStream();
+ mediaElement.play();
+ });
+ }, "Test normal playback case with MediaSource API", {timeout: 5000});
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/media-source/mediasource-redundant-seek.html b/tests/wpt/web-platform-tests/media-source/mediasource-redundant-seek.html
new file mode 100644
index 00000000000..c1cc84c3096
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mediasource-redundant-seek.html
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Test MediaSource behavior when receiving multiple seek requests during a pending seek.</title>
+ <meta name="timeout" content="long">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="mediasource-util.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+
+ mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
+ {
+ mediaElement.play();
+
+ // Append all media data for complete playback.
+ test.expectEvent(sourceBuffer, 'updateend', 'sourceBuffer end update.');
+ test.expectEvent(mediaElement, 'loadedmetadata', 'Reached HAVE_METADATA');
+ test.expectEvent(mediaElement, 'playing', 'Playing media.');
+ sourceBuffer.appendBuffer(mediaData);
+
+ test.waitForExpectedEvents(function()
+ {
+ var bufferedRanges = mediaElement.buffered;
+
+ assert_greater_than_equal(mediaElement.duration, 4.0, 'Duration is >= 4.0s');
+ assert_equals(bufferedRanges.length, 1, 'Just one buffered range');
+ assert_less_than_equal(bufferedRanges.start(0), 1.0, 'Buffered range starts <= 1.0s');
+ assert_greater_than_equal(bufferedRanges.end(0), 4.0, 'Buffered range ends >= 4.0s');
+
+ test.expectEvent(mediaElement, 'seeking', 'seeking');
+ test.expectEvent(mediaElement, 'timeupdate', 'timeupdate');
+ test.expectEvent(mediaElement, 'seeked', 'seeked');
+
+ // Request seeks.
+ mediaElement.currentTime = 1.0;
+
+ // This 'ephemeral' seek should be invisible to javascript, except any latency incurred in its processing.
+ mediaElement.currentTime = 3.0;
+
+ mediaElement.currentTime = 1.0;
+
+ assert_true(mediaElement.seeking, 'Element is seeking');
+ assert_equals(mediaElement.currentTime, 1.0, 'Element time is at last seek time');
+ });
+
+ test.waitForExpectedEvents(function()
+ {
+ // No more seeking or seeked events should occur.
+ test.failOnEvent(mediaElement, 'seeking');
+ test.failOnEvent(mediaElement, 'seeked');
+
+ assert_false(mediaElement.seeking, 'Element is not seeking');
+ assert_greater_than_equal(mediaElement.currentTime, 1.0, 'Element time is at or after last seek time');
+ assert_less_than(mediaElement.currentTime, 3.0, 'Element time is before the ephemeral seek time');
+
+ var timeBeforeWait = mediaElement.currentTime;
+ test.waitForCurrentTimeChange(mediaElement, function()
+ {
+ // Time should have advanced a little, but not yet reached the ephemeral seek time.
+ assert_greater_than(mediaElement.currentTime, timeBeforeWait, 'Element time has increased');
+ assert_less_than(mediaElement.currentTime, 3.0, 'Element time is still before the ephemeral seek time');
+ test.done();
+ });
+ });
+ }, 'Test redundant fully prebuffered seek');
+
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/media-source/mediasource-remove.html b/tests/wpt/web-platform-tests/media-source/mediasource-remove.html
new file mode 100644
index 00000000000..0b9db531cec
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mediasource-remove.html
@@ -0,0 +1,293 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>SourceBuffer.remove() test cases.</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="mediasource-util.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ mediasource_test(function(test, mediaElement, mediaSource)
+ {
+ var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_VIDEO_TYPE);
+
+ assert_throws("InvalidAccessError", function()
+ {
+ sourceBuffer.remove(-1, 2);
+ }, "remove");
+
+ test.done();
+ }, "Test remove with an negative start.");
+
+ mediasource_test(function(test, mediaElement, mediaSource)
+ {
+ var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_VIDEO_TYPE);
+
+ [ undefined, NaN, Infinity, -Infinity ].forEach(function(item)
+ {
+ assert_throws(new TypeError(), function()
+ {
+ sourceBuffer.remove(item, 2);
+ }, "remove");
+ });
+
+ test.done();
+ }, "Test remove with non-finite start.");
+
+ mediasource_test(function(test, mediaElement, mediaSource)
+ {
+ var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_VIDEO_TYPE);
+
+ mediaSource.duration = 10;
+
+ assert_throws("InvalidAccessError", function()
+ {
+ sourceBuffer.remove(11, 12);
+ }, "remove");
+
+ test.done();
+ }, "Test remove with a start beyond the duration.");
+
+ mediasource_test(function(test, mediaElement, mediaSource)
+ {
+ var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_VIDEO_TYPE);
+
+ mediaSource.duration = 10;
+
+ assert_throws("InvalidAccessError", function()
+ {
+ sourceBuffer.remove(2, 1);
+ }, "remove");
+
+ test.done();
+ }, "Test remove with a start larger than the end.");
+
+ mediasource_test(function(test, mediaElement, mediaSource)
+ {
+ var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_VIDEO_TYPE);
+
+ assert_throws("InvalidAccessError", function()
+ {
+ sourceBuffer.remove(0, Number.NEGATIVE_INFINITY);
+ }, "remove");
+
+ test.done();
+ }, "Test remove with a NEGATIVE_INFINITY end.");
+
+ mediasource_test(function(test, mediaElement, mediaSource)
+ {
+ var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_VIDEO_TYPE);
+
+ assert_throws("InvalidAccessError", function()
+ {
+ sourceBuffer.remove(0, Number.NaN);
+ }, "remove");
+
+ test.done();
+ }, "Test remove with a NaN end.");
+
+ mediasource_test(function(test, mediaElement, mediaSource)
+ {
+ var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_VIDEO_TYPE);
+
+ mediaSource.duration = 10;
+
+ mediaSource.removeSourceBuffer(sourceBuffer);
+
+ assert_throws("InvalidStateError", function()
+ {
+ sourceBuffer.remove(1, 2);
+ }, "remove");
+
+ test.done();
+ }, "Test remove after SourceBuffer removed from mediaSource.");
+
+
+ mediasource_test(function(test, mediaElement, mediaSource)
+ {
+ var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_VIDEO_TYPE);
+
+ mediaSource.duration = 10;
+
+ test.expectEvent(sourceBuffer, "updatestart");
+ test.expectEvent(sourceBuffer, "update");
+ test.expectEvent(sourceBuffer, "updateend");
+ sourceBuffer.remove(1, 2);
+
+ assert_true(sourceBuffer.updating, "updating");
+
+ assert_throws("InvalidStateError", function()
+ {
+ sourceBuffer.remove(3, 4);
+ }, "remove");
+
+ test.waitForExpectedEvents(function()
+ {
+ test.done();
+ });
+ }, "Test remove while update pending.");
+
+ mediasource_test(function(test, mediaElement, mediaSource)
+ {
+ var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_VIDEO_TYPE);
+
+ mediaSource.duration = 10;
+
+ test.expectEvent(sourceBuffer, "updatestart");
+ test.expectEvent(sourceBuffer, "abort");
+ test.expectEvent(sourceBuffer, "updateend");
+ sourceBuffer.remove(1, 2);
+
+ assert_true(sourceBuffer.updating, "updating");
+
+ sourceBuffer.abort();
+
+ assert_false(sourceBuffer.updating, "updating");
+
+ test.waitForExpectedEvents(function()
+ {
+ test.done();
+ });
+ }, "Test aborting a remove operation.");
+
+ mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
+ {
+ sourceBuffer.appendBuffer(mediaData);
+
+ test.expectEvent(sourceBuffer, "updatestart");
+ test.expectEvent(sourceBuffer, "update");
+ test.expectEvent(sourceBuffer, "updateend");
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_less_than(mediaSource.duration, 10)
+
+ mediaSource.duration = 10;
+
+ sourceBuffer.remove(mediaSource.duration, mediaSource.duration + 2);
+
+ assert_true(sourceBuffer.updating, "updating");
+ test.expectEvent(sourceBuffer, "updatestart");
+ test.expectEvent(sourceBuffer, "update");
+ test.expectEvent(sourceBuffer, "updateend");
+ });
+
+ test.waitForExpectedEvents(function()
+ {
+ test.done();
+ });
+
+ }, "Test remove with a start at the duration.");
+
+ mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
+ {
+ test.expectEvent(sourceBuffer, "updatestart");
+ test.expectEvent(sourceBuffer, "update");
+ test.expectEvent(sourceBuffer, "updateend");
+ sourceBuffer.appendBuffer(mediaData);
+
+ test.waitForExpectedEvents(function()
+ {
+ mediaSource.endOfStream();
+
+ assert_equals(mediaSource.readyState, "ended");
+
+ test.expectEvent(sourceBuffer, "updatestart");
+ test.expectEvent(sourceBuffer, "update");
+ test.expectEvent(sourceBuffer, "updateend");
+ sourceBuffer.remove(1, 2);
+
+ assert_true(sourceBuffer.updating, "updating");
+ assert_equals(mediaSource.readyState, "open");
+ });
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_false(sourceBuffer.updating, "updating");
+ test.done();
+ });
+ }, "Test remove transitioning readyState from 'ended' to 'open'.");
+
+ function removeAppendedDataTests(callback, description)
+ {
+ mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
+ {
+ test.expectEvent(sourceBuffer, "updatestart");
+ test.expectEvent(sourceBuffer, "update");
+ test.expectEvent(sourceBuffer, "updateend");
+ sourceBuffer.appendBuffer(mediaData);
+
+ test.waitForExpectedEvents(function()
+ {
+ mediaSource.endOfStream();
+ assert_false(sourceBuffer.updating, "updating");
+
+ var duration = mediaElement.duration.toFixed(3);
+ var subType = MediaSourceUtil.getSubType(segmentInfo.type);
+
+ assertBufferedEquals(sourceBuffer, "{ [0.000, " + duration + ") }", "Initial buffered range.");
+ callback(test, mediaSource, sourceBuffer, duration, subType);
+ });
+ }, description);
+ };
+ function removeAndCheckBufferedRanges(test, mediaSource, sourceBuffer, start, end, expected)
+ {
+ test.expectEvent(sourceBuffer, "updatestart");
+ test.expectEvent(sourceBuffer, "update");
+ test.expectEvent(sourceBuffer, "updateend");
+ sourceBuffer.remove(start, end);
+
+ test.waitForExpectedEvents(function()
+ {
+ mediaSource.endOfStream();
+ assert_false(sourceBuffer.updating, "updating");
+
+ assertBufferedEquals(sourceBuffer, expected, "Buffered ranges after remove().");
+ test.done();
+ });
+ }
+
+ removeAppendedDataTests(function(test, mediaSource, sourceBuffer, duration, subType)
+ {
+ removeAndCheckBufferedRanges(test, mediaSource, sourceBuffer, 0, Number.POSITIVE_INFINITY, "{ }");
+ }, "Test removing all appended data.");
+
+ removeAppendedDataTests(function(test, mediaSource, sourceBuffer, duration, subType)
+ {
+ var expectations = {
+ webm: ("{ [3.187, " + duration + ") }"),
+ mp4: ("{ [3.154, " + duration + ") }"),
+ };
+
+ // Note: Range doesn't start exactly at the end of the remove range because there isn't
+ // a keyframe there. The resulting range starts at the first keyframe >= the end time.
+ removeAndCheckBufferedRanges(test, mediaSource, sourceBuffer, 0, 3, expectations[subType]);
+ }, "Test removing beginning of appended data.");
+
+ removeAppendedDataTests(function(test, mediaSource, sourceBuffer, duration, subType)
+ {
+ var expectations = {
+ webm: ("{ [0.000, 1.012) [3.187, " + duration + ") }"),
+ mp4: ("{ [0.000, 1.022) [3.154, " + duration + ") }"),
+ };
+
+ // Note: The first resulting range ends slightly after start because the removal algorithm only removes
+ // frames with a timestamp >= the start time. If a frame starts before and ends after the remove() start
+ // timestamp, then it stays in the buffer.
+ removeAndCheckBufferedRanges(test, mediaSource, sourceBuffer, 1, 3, expectations[subType]);
+ }, "Test removing the middle of appended data.");
+
+ removeAppendedDataTests(function(test, mediaSource, sourceBuffer, duration, subType)
+ {
+ var expectations = {
+ webm: "{ [0.000, 1.012) }",
+ mp4: "{ [0.000, 1.029) }",
+ };
+
+ removeAndCheckBufferedRanges(test, mediaSource, sourceBuffer, 1, Number.POSITIVE_INFINITY, expectations[subType]);
+ }, "Test removing the end of appended data.");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/media-source/mediasource-removesourcebuffer.html b/tests/wpt/web-platform-tests/media-source/mediasource-removesourcebuffer.html
new file mode 100644
index 00000000000..cbf3a1b37e5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mediasource-removesourcebuffer.html
@@ -0,0 +1,92 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>MediaSource.removeSourceBuffer() test cases.</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="mediasource-util.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ mediasource_test(function(test, mediaElement, mediaSource)
+ {
+ var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_VIDEO_TYPE);
+ assert_true(sourceBuffer != null, "New SourceBuffer returned");
+
+ mediaSource.removeSourceBuffer(sourceBuffer);
+
+ var sourceBuffer2 = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_VIDEO_TYPE);
+ assert_true(sourceBuffer2 != null, "New SourceBuffer returned");
+ assert_true(sourceBuffer != sourceBuffer2, "SourceBuffers are different instances.");
+ assert_equals(mediaSource.sourceBuffers.length, 1, "sourceBuffers.length == 1");
+
+ test.done();
+ }, "Test addSourceBuffer(), removeSourceBuffer(), addSourceBuffer() sequence.");
+
+ mediasource_test(function(test, mediaElement, mediaSource)
+ {
+ assert_throws(new TypeError(),
+ function() { mediaSource.removeSourceBuffer(null); },
+ "removeSourceBuffer() threw an exception when passed null.");
+ test.done();
+ }, "Test removeSourceBuffer() with null");
+
+ mediasource_test(function(test, mediaElement, mediaSource)
+ {
+ var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_VIDEO_TYPE);
+ assert_true(sourceBuffer != null, "New SourceBuffer returned");
+
+ mediaSource.removeSourceBuffer(sourceBuffer);
+
+ assert_throws("NotFoundError",
+ function() { mediaSource.removeSourceBuffer(sourceBuffer); },
+ "removeSourceBuffer() threw an exception when a SourceBuffer that was already removed.");
+
+ test.done();
+ }, "Test calling removeSourceBuffer() twice with the same object.");
+
+ mediasource_test(function(test, mediaElement, mediaSource)
+ {
+ var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_VIDEO_TYPE);
+ assert_true(sourceBuffer != null, "New SourceBuffer returned");
+
+ mediaSource.endOfStream();
+ assert_true(mediaSource.readyState == "ended", "MediaSource in ended state");
+ mediaSource.removeSourceBuffer(sourceBuffer);
+
+ assert_true(mediaSource.sourceBuffers.length == 0, "MediaSource.sourceBuffers is empty");
+ assert_true(mediaSource.activeSourceBuffers.length == 0, "MediaSource.activesourceBuffers is empty");
+
+ test.done();
+ }, "Test calling removeSourceBuffer() in ended state.");
+
+ mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
+ {
+ var initSegment = MediaSourceUtil.extractSegmentData(mediaData, segmentInfo.init);
+
+ test.expectEvent(sourceBuffer, "updateend", "initSegment append ended.");
+ test.expectEvent(mediaElement, "loadedmetadata", "loadedmetadata done.");
+ sourceBuffer.appendBuffer(initSegment);
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_true(mediaSource.sourceBuffers.length == 1, "MediaSource.sourceBuffers is not empty");
+ assert_true(mediaSource.activeSourceBuffers.length == 1, "MediaSource.activesourceBuffers is not empty");
+ assert_equals(mediaElement.readyState, mediaElement.HAVE_METADATA);
+ assert_equals(mediaSource.duration, segmentInfo.duration);
+ test.expectEvent(mediaSource.activeSourceBuffers, "removesourcebuffer", "SourceBuffer removed from activeSourceBuffers.");
+ test.expectEvent(mediaSource.sourceBuffers, "removesourcebuffer", "SourceBuffer removed.");
+ mediaSource.removeSourceBuffer(sourceBuffer);
+ });
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_true(mediaSource.sourceBuffers.length == 0, "MediaSource.sourceBuffers is empty");
+ assert_true(mediaSource.activeSourceBuffers.length == 0, "MediaSource.activesourceBuffers is empty");
+ test.done();
+ });
+ }, "Test removesourcebuffer event on activeSourceBuffers.");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/media-source/mediasource-seek-beyond-duration.html b/tests/wpt/web-platform-tests/media-source/mediasource-seek-beyond-duration.html
new file mode 100644
index 00000000000..3caf5f8dda7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mediasource-seek-beyond-duration.html
@@ -0,0 +1,95 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Test MediaSource behavior when seeking beyond the duration of the clip.</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="mediasource-util.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+
+ function seekToSpecifiedTimeSetEOSAndVerifyDone(test, mediaElement, mediaSource, seekToTime)
+ {
+ assert_less_than(mediaElement.currentTime, mediaElement.duration, 'Not at the end yet.');
+ test.expectEvent(mediaElement, 'seeking', 'mediaElement seeking');
+ // Seek to specified time.
+ mediaElement.currentTime = seekToTime;
+ if (seekToTime >= mediaSource.duration) {
+ assert_equals(mediaElement.currentTime, mediaSource.duration, 'Current time equals duration.');
+ } else {
+ assert_equals(mediaElement.currentTime, seekToTime, 'Current time equals specified seek time.');
+ }
+
+ test.waitForExpectedEvents(function()
+ {
+ test.expectEvent(mediaElement, 'timeupdate', 'mediaElement time updated.');
+ test.expectEvent(mediaElement, 'seeked', 'mediaElement seeked');
+ test.expectEvent(mediaElement, 'ended', 'mediaElement ended.');
+ test.expectEvent(mediaSource, 'sourceended', 'mediaSource ended.');
+ mediaSource.endOfStream();
+ assert_true(mediaElement.seeking, 'mediaElement seeking.');
+ });
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_equals(mediaElement.currentTime, mediaSource.duration, 'Current time equals duration.');
+ test.done();
+ });
+ };
+
+ mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
+ {
+ mediaElement.play();
+ var initSegment = MediaSourceUtil.extractSegmentData(mediaData, segmentInfo.init);
+
+ // Append the initialization segment to trigger a transition to HAVE_METADATA.
+ test.expectEvent(sourceBuffer, 'updateend', 'sourceBuffer end update.');
+ test.expectEvent(mediaElement, 'loadedmetadata', 'Reached HAVE_METADATA');
+ sourceBuffer.appendBuffer(initSegment);
+
+ test.waitForExpectedEvents(function()
+ {
+ // Add sufficient segments to have at least 2s of play-time.
+ var playbackData = MediaSourceUtil.getMediaDataForPlaybackTime(mediaData, segmentInfo, 2.0);
+ test.expectEvent(sourceBuffer, 'updateend', 'sourceBuffer');
+ test.expectEvent(mediaElement, 'playing', 'Playing media.');
+ sourceBuffer.appendBuffer(playbackData);
+ });
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_equals(mediaElement.duration, segmentInfo.duration);
+ assert_greater_than_equal(mediaElement.duration, 2.0, 'Duration is >2.0s.');
+ test.waitForCurrentTimeChange(mediaElement, function()
+ {
+ // Update duration.
+ mediaSource.duration = 1.5;
+ seekToSpecifiedTimeSetEOSAndVerifyDone(test, mediaElement, mediaSource, 1.8);
+ });
+ });
+ }, 'Test seeking beyond updated media duration.');
+
+ mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
+ {
+ mediaElement.play();
+
+ // Append all media data for complete playback.
+ test.expectEvent(sourceBuffer, 'updateend', 'sourceBuffer end update.');
+ test.expectEvent(mediaElement, 'loadedmetadata', 'Reached HAVE_METADATA');
+ test.expectEvent(mediaElement, 'playing', 'Playing media.');
+ sourceBuffer.appendBuffer(mediaData);
+
+ test.waitForExpectedEvents(function()
+ {
+ test.waitForCurrentTimeChange(mediaElement, function()
+ {
+ seekToSpecifiedTimeSetEOSAndVerifyDone(test, mediaElement, mediaSource, mediaSource.duration, mediaSource.duration + 0.1);
+ });
+ });
+
+ }, 'Test seeking beyond media duration.');
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/media-source/mediasource-seek-during-pending-seek.html b/tests/wpt/web-platform-tests/media-source/mediasource-seek-during-pending-seek.html
new file mode 100644
index 00000000000..b12903289dc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mediasource-seek-during-pending-seek.html
@@ -0,0 +1,142 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Test MediaSource behavior when a seek is requested while another seek is pending.</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="mediasource-util.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
+ {
+ mediaElement.play();
+
+ var initSegment = MediaSourceUtil.extractSegmentData(mediaData, segmentInfo.init);
+ var firstSegment = MediaSourceUtil.extractSegmentData(mediaData, segmentInfo.media[0]);
+ var segmentIndex = 2;
+ var secondSegmentInfo = segmentInfo.media[segmentIndex];
+
+ // Append the initialization segment to trigger a transition to HAVE_METADATA.
+ test.expectEvent(sourceBuffer, 'updateend', 'sourceBuffer');
+ test.expectEvent(mediaElement, 'loadedmetadata', 'Reached HAVE_METADATA');
+ sourceBuffer.appendBuffer(initSegment);
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_false(mediaElement.seeking, 'mediaElement is not seeking');
+ assert_equals(mediaElement.readyState, mediaElement.HAVE_METADATA, 'Still in HAVE_METADATA');
+
+ // Seek to a new position before letting the initial seek to 0 completes.
+ test.expectEvent(mediaElement, 'seeking', 'mediaElement');
+ mediaElement.currentTime = secondSegmentInfo.timecode;
+ assert_true(mediaElement.seeking, 'mediaElement is seeking');
+
+ // Append media data for time 0.
+ test.expectEvent(sourceBuffer, 'updateend', 'sourceBuffer');
+ sourceBuffer.appendBuffer(firstSegment);
+ });
+
+ test.waitForExpectedEvents(function()
+ {
+ // Verify that the media data didn't trigger a 'seeking' event or a transition beyond HAVE_METADATA.
+ assert_true(mediaElement.seeking, 'mediaElement is still seeking');
+ assert_equals(mediaElement.readyState, mediaElement.HAVE_METADATA, 'Still in HAVE_METADATA');
+
+ // Append media data for the current position until the element starts playing.
+ test.expectEvent(mediaElement, 'seeked', 'mediaElement finished seek');
+ test.expectEvent(mediaElement, 'playing', 'mediaElement playing');
+
+ MediaSourceUtil.appendUntilEventFires(test, mediaElement, 'playing', sourceBuffer, mediaData, segmentInfo, segmentIndex);
+ });
+
+ test.waitForExpectedEvents(function()
+ {
+ test.expectEvent(mediaSource, 'sourceended', 'mediaSource ended');
+ mediaSource.endOfStream();
+ });
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_greater_than(mediaElement.readyState, mediaElement.HAVE_CURRENT_DATA, 'Greater than HAVE_CURRENT_DATA');
+ test.done();
+ });
+
+ }, 'Test seeking to a new location before transitioning beyond HAVE_METADATA.', {timeout: 10000} );
+
+ mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
+ {
+ mediaElement.play();
+
+ var initSegment = MediaSourceUtil.extractSegmentData(mediaData, segmentInfo.init);
+ var firstSegment = MediaSourceUtil.extractSegmentData(mediaData, segmentInfo.media[0]);
+ var secondSegmentInfo = segmentInfo.media[2];
+ var secondSegment = MediaSourceUtil.extractSegmentData(mediaData, secondSegmentInfo);
+ var segmentIndex = 4;
+ var thirdSegmentInfo = segmentInfo.media[segmentIndex];
+
+ // Append the initialization segment to trigger a transition to HAVE_METADATA.
+ test.expectEvent(sourceBuffer, 'updateend', 'sourceBuffer');
+ test.expectEvent(mediaElement, 'loadedmetadata', 'Reached HAVE_METADATA');
+ sourceBuffer.appendBuffer(initSegment);
+
+ test.waitForExpectedEvents(function()
+ {
+ test.expectEvent(sourceBuffer, 'updateend', 'sourceBuffer');
+ test.expectEvent(mediaElement, 'playing', 'mediaElement playing');
+ sourceBuffer.appendBuffer(firstSegment);
+ });
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_greater_than(mediaElement.readyState, mediaElement.HAVE_CURRENT_DATA, 'Greater than HAVE_CURRENT_DATA');
+
+ // Seek to a new position.
+ test.expectEvent(mediaElement, 'seeking', 'mediaElement');
+ mediaElement.currentTime = secondSegmentInfo.timecode;
+ assert_true(mediaElement.seeking, 'mediaElement is seeking');
+
+ });
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_true(mediaElement.seeking, 'mediaElement is still seeking');
+
+ // Seek to a second position while the first seek is still pending.
+ test.expectEvent(mediaElement, 'seeking', 'mediaElement');
+ mediaElement.currentTime = thirdSegmentInfo.timecode;
+ assert_true(mediaElement.seeking, 'mediaElement is seeking');
+
+ // Append media data for the first seek position.
+ test.expectEvent(sourceBuffer, 'updateend', 'sourceBuffer');
+ sourceBuffer.appendBuffer(secondSegment);
+ });
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_true(mediaElement.seeking, 'mediaElement is still seeking');
+
+ // Append media data for the second seek position.
+ test.expectEvent(sourceBuffer, 'updateend', 'sourceBuffer');
+ test.expectEvent(mediaElement, 'seeked', 'mediaElement finished seek');
+ MediaSourceUtil.appendUntilEventFires(test, mediaElement, 'seeked', sourceBuffer, mediaData, segmentInfo, segmentIndex);
+ });
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_false(mediaElement.seeking, 'mediaElement is no longer seeking');
+
+ test.expectEvent(mediaSource, 'sourceended', 'mediaSource ended');
+ mediaSource.endOfStream();
+ });
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_greater_than(mediaElement.readyState, mediaElement.HAVE_CURRENT_DATA, 'Greater than HAVE_CURRENT_DATA');
+ test.done();
+ });
+ }, 'Test seeking to a new location during a pending seek.', {timeout: 10000} );
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/media-source/mediasource-sequencemode-append-buffer.html b/tests/wpt/web-platform-tests/media-source/mediasource-sequencemode-append-buffer.html
new file mode 100644
index 00000000000..15263eebf7f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mediasource-sequencemode-append-buffer.html
@@ -0,0 +1,129 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>SourceBuffer.mode == "sequence" test cases.</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="mediasource-util.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ function mediasource_sequencemode_test(testFunction, description, options)
+ {
+ return mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
+ {
+ assert_greater_than(segmentInfo.media.length, 3, "at least 3 media segments for supported type");
+ test.failOnEvent(mediaElement, "error");
+ sourceBuffer.mode = "sequence";
+ assert_equals(sourceBuffer.mode, "sequence", "mode after setting it to \"sequence\"");
+
+ var initSegment = MediaSourceUtil.extractSegmentData(mediaData, segmentInfo.init);
+ test.expectEvent(sourceBuffer, "updatestart", "initSegment append started.");
+ test.expectEvent(sourceBuffer, "update", "initSegment append success.");
+ test.expectEvent(sourceBuffer, "updateend", "initSegment append ended.");
+ sourceBuffer.appendBuffer(initSegment);
+ test.waitForExpectedEvents(function()
+ {
+ assert_equals(sourceBuffer.timestampOffset, 0, "timestampOffset initially 0");
+ testFunction(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData);
+ });
+ }, description, options);
+ }
+
+ function append_segment(test, sourceBuffer, mediaData, info, callback)
+ {
+ var mediaSegment = MediaSourceUtil.extractSegmentData(mediaData, info);
+ test.expectEvent(sourceBuffer, "updatestart", "media segment append started.");
+ test.expectEvent(sourceBuffer, "update", "media segment append success.");
+ test.expectEvent(sourceBuffer, "updateend", "media segment append ended.");
+ sourceBuffer.appendBuffer(mediaSegment);
+ test.waitForExpectedEvents(callback);
+ }
+
+ function threeDecimalPlaces(number)
+ {
+ return Number(number.toFixed(3));
+ }
+
+ // Verifies expected times to 3 decimal places before and after mediaSource.endOfStream(),
+ // and calls |callback| on success.
+ function verify_offset_and_buffered(test, mediaSource, sourceBuffer,
+ expectedTimestampOffset, expectedBufferedRangeStartTime,
+ expectedBufferedRangeMaxEndTimeBeforeEOS,
+ expectedBufferedRangeEndTimeAfterEOS,
+ callback) {
+ assert_equals(threeDecimalPlaces(sourceBuffer.timestampOffset),
+ threeDecimalPlaces(expectedTimestampOffset),
+ "expectedTimestampOffset");
+
+ // Prior to EOS, the buffered range end time may not have fully reached the next media
+ // segment's timecode (adjusted by any timestampOffset). It should not exceed it though.
+ // Therefore, an exact assertBufferedEquals() will not work here.
+ assert_equals(sourceBuffer.buffered.length, 1, "sourceBuffer.buffered has 1 range before EOS");
+ assert_equals(threeDecimalPlaces(sourceBuffer.buffered.start(0)),
+ threeDecimalPlaces(expectedBufferedRangeStartTime),
+ "sourceBuffer.buffered range begins where expected before EOS");
+ assert_less_than_equal(threeDecimalPlaces(sourceBuffer.buffered.end(0)),
+ threeDecimalPlaces(expectedBufferedRangeMaxEndTimeBeforeEOS),
+ "sourceBuffer.buffered range ends at or before expected upper bound before EOS");
+
+ test.expectEvent(mediaSource, "sourceended", "mediaSource endOfStream");
+ mediaSource.endOfStream();
+ test.waitForExpectedEvents(function()
+ {
+ assertBufferedEquals(sourceBuffer,
+ "{ [" + expectedBufferedRangeStartTime.toFixed(3) + ", " + expectedBufferedRangeEndTimeAfterEOS.toFixed(3) + ") }",
+ "sourceBuffer.buffered after EOS");
+ callback();
+ });
+ }
+
+ mediasource_sequencemode_test(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
+ {
+ assert_equals(segmentInfo.media[0].timecode, 0, "segment starts at time 0");
+ append_segment(test, sourceBuffer, mediaData, segmentInfo.media[0], function()
+ {
+ verify_offset_and_buffered(test, mediaSource, sourceBuffer,
+ 0, 0,
+ segmentInfo.media[1].timecode + sourceBuffer.timestampOffset,
+ segmentInfo.media[0].highest_end_time + sourceBuffer.timestampOffset,
+ test.done);
+ });
+ }, "Test sequence AppendMode appendBuffer(first media segment)");
+
+ mediasource_sequencemode_test(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
+ {
+ assert_greater_than(segmentInfo.media[1].timecode, 0, "segment starts after time 0");
+ append_segment(test, sourceBuffer, mediaData, segmentInfo.media[1], function()
+ {
+ verify_offset_and_buffered(test, mediaSource, sourceBuffer,
+ -segmentInfo.media[1].timecode, 0,
+ segmentInfo.media[2].timecode + sourceBuffer.timestampOffset,
+ segmentInfo.media[1].highest_end_time + sourceBuffer.timestampOffset,
+ test.done);
+ });
+ }, "Test sequence AppendMode appendBuffer(second media segment)");
+
+ mediasource_sequencemode_test(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
+ {
+ assert_greater_than(segmentInfo.media[1].timecode, 0, "segment starts after time 0");
+ append_segment(test, sourceBuffer, mediaData, segmentInfo.media[1], function()
+ {
+ assert_equals(segmentInfo.media[0].timecode, 0, "segment starts at time 0");
+ append_segment(test, sourceBuffer, mediaData, segmentInfo.media[0], function()
+ {
+ // Current timestampOffset should reflect offset required to put media[0]
+ // immediately after media[1]'s highest frame end timestamp (as was adjusted
+ // by an earlier timestampOffset).
+ verify_offset_and_buffered(test, mediaSource, sourceBuffer,
+ segmentInfo.media[1].highest_end_time - segmentInfo.media[1].timecode, 0,
+ segmentInfo.media[1].timecode + sourceBuffer.timestampOffset,
+ segmentInfo.media[0].highest_end_time + sourceBuffer.timestampOffset,
+ test.done);
+ })
+ });
+ }, "Test sequence AppendMode appendBuffer(second media segment, then first media segment)");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/media-source/mediasource-sourcebuffer-mode.html b/tests/wpt/web-platform-tests/media-source/mediasource-sourcebuffer-mode.html
new file mode 100644
index 00000000000..94843e26166
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mediasource-sourcebuffer-mode.html
@@ -0,0 +1,140 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>SourceBuffer.mode test cases.</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="mediasource-util.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
+ {
+ assert_equals(sourceBuffer.mode, 'segments', 'default append mode should be \'segments\'');
+ test.done();
+ }, 'Test initial value of SourceBuffer.mode is "segments"');
+
+ mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
+ {
+ sourceBuffer.mode = 'sequence';
+ assert_equals(sourceBuffer.mode, 'sequence', 'mode after setting it to \'sequence\'');
+
+ // Setting a mode that is not in AppendMode IDL enum should be ignored and not cause exception.
+ sourceBuffer.mode = 'invalidmode';
+ sourceBuffer.mode = null;
+ sourceBuffer.mode = '';
+ sourceBuffer.mode = 'Segments';
+ assert_equals(sourceBuffer.mode, 'sequence', 'mode unchanged by attempts to set invalid modes');
+
+ sourceBuffer.mode = 'segments';
+ assert_equals(sourceBuffer.mode, 'segments', 'mode after setting it to \'segments\'');
+ test.done();
+ }, 'Test setting SourceBuffer.mode');
+
+ mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
+ {
+ mediaSource.removeSourceBuffer(sourceBuffer);
+ assert_throws('InvalidStateError',
+ function() { sourceBuffer.mode = 'segments'; },
+ 'Setting valid sourceBuffer.mode on removed SourceBuffer should throw InvalidStateError.');
+ test.done();
+ }, 'Test setting a removed SourceBuffer\'s mode');
+
+ mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
+ {
+ sourceBuffer.appendBuffer(mediaData);
+ assert_true(sourceBuffer.updating, 'updating attribute is true');
+ assert_throws('InvalidStateError',
+ function() { sourceBuffer.mode = 'segments'; },
+ 'Setting valid sourceBuffer.mode on updating SourceBuffer threw InvalidStateError.');
+ test.done();
+ }, 'Test setting SourceBuffer.mode while still updating');
+
+ mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
+ {
+ test.expectEvent(sourceBuffer, 'updateend', 'Append ended.');
+ sourceBuffer.appendBuffer(mediaData);
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_false(sourceBuffer.updating, 'updating attribute is false');
+
+ test.expectEvent(mediaSource, 'sourceended', 'MediaSource sourceended event');
+ mediaSource.endOfStream();
+ assert_equals(mediaSource.readyState, 'ended', 'MediaSource readyState is \'ended\'');
+ });
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_equals(mediaSource.readyState, 'ended', 'MediaSource readyState is \'ended\'');
+
+ test.expectEvent(mediaSource, 'sourceopen', 'MediaSource sourceopen event');
+ sourceBuffer.mode = 'segments';
+
+ assert_equals(mediaSource.readyState, 'open', 'MediaSource readyState is \'open\'');
+ });
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_equals(mediaSource.readyState, 'open', 'MediaSource readyState is \'open\'');
+ test.done();
+ });
+ }, 'Test setting SourceBuffer.mode triggers parent MediaSource \'ended\' to \'open\' transition.');
+
+ mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
+ {
+ var initSegment = MediaSourceUtil.extractSegmentData(mediaData, segmentInfo.init);
+ var fullMediaSegment = MediaSourceUtil.extractSegmentData(mediaData, segmentInfo.media[0]);
+ var truncateAt = Math.floor(segmentInfo.media[0].size * 0.5); // Pick first 50% of segment bytes.
+ var partialMediaSegment = fullMediaSegment.subarray(0, truncateAt);
+ var mediaSegmentRemainder = fullMediaSegment.subarray(truncateAt);
+
+ // Append init segment.
+ test.expectEvent(sourceBuffer, 'updateend', 'Init segment append ended.');
+ sourceBuffer.appendBuffer(initSegment);
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_false(sourceBuffer.updating, 'updating attribute is false');
+ assert_equals(sourceBuffer.mode, 'segments');
+ sourceBuffer.mode = 'segments'; // No exception should occur.
+ assert_equals(sourceBuffer.timestampOffset, 0.0);
+ sourceBuffer.timestampOffset = 10.123456789; // No exception should occur.
+ assert_equals(sourceBuffer.timestampOffset, 10.123456789); // Super-precise offsets should round-trip.
+
+ // Append first part of media segment.
+ test.expectEvent(sourceBuffer, 'updateend', 'Partial media segment append ended.');
+ sourceBuffer.appendBuffer(partialMediaSegment);
+ });
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_false(sourceBuffer.updating, 'updating attribute is false');
+ assert_equals(sourceBuffer.mode, 'segments');
+ assert_throws('InvalidStateError',
+ function() { sourceBuffer.mode = 'segments'; },
+ 'Setting valid sourceBuffer.mode while still parsing media segment threw InvalidStateError.');
+ assert_equals(sourceBuffer.timestampOffset, 10.123456789);
+ assert_throws('InvalidStateError',
+ function() { sourceBuffer.timestampOffset = 20.0; },
+ 'Setting valid sourceBuffer.timestampOffset while still parsing media segment threw InvalidStateError.');
+
+ // Append remainder of media segment.
+ test.expectEvent(sourceBuffer, 'updateend', 'Append ended of remainder of media segment.');
+ sourceBuffer.appendBuffer(mediaSegmentRemainder);
+ });
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_false(sourceBuffer.updating, 'updating attribute is false');
+ assert_equals(sourceBuffer.mode, 'segments');
+ sourceBuffer.mode = 'segments'; // No exception should occur.
+ assert_equals(sourceBuffer.timestampOffset, 10.123456789);
+ sourceBuffer.timestampOffset = 20.0; // No exception should occur.
+ test.done();
+ });
+ }, 'Test setting SourceBuffer.mode and SourceBuffer.timestampOffset while parsing media segment.');
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/media-source/mediasource-sourcebufferlist.html b/tests/wpt/web-platform-tests/media-source/mediasource-sourcebufferlist.html
new file mode 100644
index 00000000000..31757acf7d6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mediasource-sourcebufferlist.html
@@ -0,0 +1,83 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>SourceBufferList test cases.</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="mediasource-util.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ function verifySourceBufferLists(mediaSource, expected)
+ {
+ assert_equals(mediaSource.sourceBuffers.length, expected.length, "sourceBuffers length");
+ assert_equals(mediaSource.activeSourceBuffers.length, 0, "activeSourceBuffers length");
+ for (var i = 0; i < expected.length; ++i)
+ assert_equals(mediaSource.sourceBuffers[i], expected[i], "Verifying mediaSource.sourceBuffers[" + i + "]");
+ }
+
+ mediasource_test(function(test, mediaElement, mediaSource)
+ {
+ test.expectEvent(mediaSource.sourceBuffers, "addsourcebuffer", "sourceBuffers");
+ var sourceBufferA = mediaSource.addSourceBuffer(MediaSourceUtil.VIDEO_ONLY_TYPE);
+ var sourceBufferB = null;
+
+ test.waitForExpectedEvents(function()
+ {
+ test.expectEvent(mediaSource.sourceBuffers, "addsourcebuffer", "sourceBuffers");
+ sourceBufferB = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_ONLY_TYPE);
+
+ verifySourceBufferLists(mediaSource, [sourceBufferA, sourceBufferB]);
+ });
+
+ test.waitForExpectedEvents(function()
+ {
+ test.expectEvent(mediaSource.sourceBuffers, "removesourcebuffer", "sourceBuffers");
+ mediaSource.removeSourceBuffer(sourceBufferA);
+
+ verifySourceBufferLists(mediaSource, [sourceBufferB]);
+
+ test.expectEvent(mediaSource.sourceBuffers, "addsourcebuffer", "sourceBuffers");
+ sourceBufferA = mediaSource.addSourceBuffer(MediaSourceUtil.VIDEO_ONLY_TYPE);
+
+ verifySourceBufferLists(mediaSource, [sourceBufferB, sourceBufferA]);
+ });
+
+ test.waitForExpectedEvents(function()
+ {
+ test.done();
+ });
+ }, "Test SourceBufferList event dispatching.");
+
+ mediasource_test(function(test, mediaElement, mediaSource)
+ {
+ test.expectEvent(mediaSource.sourceBuffers, "addsourcebuffer", "sourceBuffers");
+ test.expectEvent(mediaSource.sourceBuffers, "addsourcebuffer", "sourceBuffers");
+ var sourceBufferA = mediaSource.addSourceBuffer(MediaSourceUtil.VIDEO_ONLY_TYPE);
+ var sourceBufferB = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_ONLY_TYPE);
+
+ verifySourceBufferLists(mediaSource, [sourceBufferA, sourceBufferB]);
+
+ test.waitForExpectedEvents(function()
+ {
+ verifySourceBufferLists(mediaSource, [sourceBufferA, sourceBufferB]);
+
+ // Force the media element to close the MediaSource object.
+ test.expectEvent(mediaSource.sourceBuffers, "removesourcebuffer", "sourceBuffers");
+ test.expectEvent(mediaSource, "sourceclose", "mediaSource closing");
+ mediaElement.src = "";
+ });
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_equals(mediaSource.readyState, "closed", "mediaSource is closed.");
+
+ verifySourceBufferLists(mediaSource, []);
+ test.done();
+ });
+ }, "Test that only 1 removesourcebuffer event fires on each SourceBufferList when the MediaSource closes.");
+
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/media-source/mediasource-timestamp-offset.html b/tests/wpt/web-platform-tests/media-source/mediasource-timestamp-offset.html
new file mode 100644
index 00000000000..728dc2c5f5d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mediasource-timestamp-offset.html
@@ -0,0 +1,121 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>SourceBuffer.timestampOffset test cases.</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="mediasource-util.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ function simpleTimestampOffsetTest(value, expected, description)
+ {
+ mediasource_test(function(test, mediaElement, mediaSource)
+ {
+ var segmentInfo = MediaSourceUtil.SEGMENT_INFO;
+ var sourceBuffer = mediaSource.addSourceBuffer(segmentInfo.type);
+
+ if (expected == "TypeError") {
+ assert_throws({name: "TypeError"},
+ function() { sourceBuffer.timestampOffset = value; },
+ "setting timestampOffset to " + description + " throws an exception.");
+ } else {
+ sourceBuffer.timestampOffset = value;
+ assert_equals(sourceBuffer.timestampOffset, expected);
+ }
+
+ test.done();
+ }, "Test setting SourceBuffer.timestampOffset to " + description + ".");
+ }
+
+ simpleTimestampOffsetTest(10.5, 10.5, "a positive number");
+ simpleTimestampOffsetTest(-10.4, -10.4, "a negative number");
+ simpleTimestampOffsetTest(0, 0, "zero");
+ simpleTimestampOffsetTest(Number.POSITIVE_INFINITY, "TypeError", "positive infinity");
+ simpleTimestampOffsetTest(Number.NEGATIVE_INFINITY, "TypeError", "negative infinity");
+ simpleTimestampOffsetTest(Number.NaN, "TypeError", "NaN");
+ simpleTimestampOffsetTest(undefined, "TypeError", "undefined");
+ simpleTimestampOffsetTest(null, 0, "null");
+ simpleTimestampOffsetTest(false, 0, "false");
+ simpleTimestampOffsetTest(true, 1, "true");
+ simpleTimestampOffsetTest("10.5", 10.5, "a number string");
+ simpleTimestampOffsetTest("", 0, "an empty string");
+
+ mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
+ {
+ var initSegment = MediaSourceUtil.extractSegmentData(mediaData, segmentInfo.init);
+ var mediaSegment = MediaSourceUtil.extractSegmentData(mediaData, segmentInfo.media[0]);
+
+ test.expectEvent(sourceBuffer, "updateend", "initSegment append ended.");
+ sourceBuffer.appendBuffer(initSegment);
+
+ test.waitForExpectedEvents(function()
+ {
+ test.expectEvent(sourceBuffer, "updateend", "mediaSegment append ended.");
+ sourceBuffer.appendBuffer(mediaSegment);
+ });
+
+ test.waitForExpectedEvents(function()
+ {
+ mediaSource.endOfStream();
+
+ assert_equals(mediaSource.readyState, "ended");
+
+ mediaSource.sourceBuffers[0].timestampOffset = 2;
+
+ assert_equals(mediaSource.readyState, "open");
+
+ test.expectEvent(mediaSource, "sourceopen", "mediaSource fired 'sourceopen' event.");
+ });
+
+ test.waitForExpectedEvents(function()
+ {
+ test.done();
+ });
+ }, "Test setting timestampOffset in 'ended' state causes a transition to 'open'.");
+
+ mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
+ {
+ var initSegment = MediaSourceUtil.extractSegmentData(mediaData, segmentInfo.init);
+ var mediaSegment = MediaSourceUtil.extractSegmentData(mediaData, segmentInfo.media[0]);
+
+ test.expectEvent(sourceBuffer, "updateend", "initSegment append ended.");
+ sourceBuffer.appendBuffer(initSegment);
+ assert_equals(mediaSource.sourceBuffers[0].timestampOffset, 0, "read initial value");
+
+ test.waitForExpectedEvents(function()
+ {
+ test.expectEvent(sourceBuffer, "updateend", "mediaSegment append ended.");
+ sourceBuffer.appendBuffer(mediaSegment);
+ assert_equals(mediaSource.sourceBuffers[0].timestampOffset, 0,
+ "No change to timestampoffset after segments mode init segment append");
+ });
+
+ test.waitForExpectedEvents(function()
+ {
+ assert_equals(mediaSource.sourceBuffers[0].timestampOffset, 0,
+ "No change to timestampoffset after segments mode media segment append");
+ test.done();
+ });
+ }, "Test getting the initial value of timestampOffset.");
+
+ mediasource_test(function(test, mediaElement, mediaSource)
+ {
+ var sourceBuffer = mediaSource.addSourceBuffer(MediaSourceUtil.AUDIO_VIDEO_TYPE);
+ assert_true(sourceBuffer != null, "New SourceBuffer returned");
+
+ mediaSource.removeSourceBuffer(sourceBuffer);
+ assert_true(mediaSource.sourceBuffers.length == 0, "MediaSource.sourceBuffers is empty");
+ assert_true(mediaSource.activeSourceBuffers.length == 0, "MediaSource.activesourceBuffers is empty");
+
+ assert_throws("InvalidStateError", function()
+ {
+ sourceBuffer.timestampOffset = 10;
+ });
+
+ test.done();
+ }, "Test setting timestampoffset after removing the sourcebuffer.");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/media-source/mediasource-util.js b/tests/wpt/web-platform-tests/media-source/mediasource-util.js
new file mode 100644
index 00000000000..de1560e17ba
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mediasource-util.js
@@ -0,0 +1,431 @@
+(function(window) {
+ setup({ timeout: 12000 });
+
+ var SEGMENT_INFO_LIST = [
+ {
+ url: 'mp4/test.mp4',
+ type: 'video/mp4; codecs="mp4a.40.2,avc1.4d400d"',
+ duration: 6.0756,
+ init: { offset: 0, size: 1197 },
+ media: [
+ { offset: 1241, size: 17845, timecode: 0.000000 },
+ { offset: 19130, size: 5551, timecode: 0.464800 },
+ { offset: 24725, size: 10944, timecode: 0.763600 },
+ { offset: 35713, size: 7131, timecode: 0.863200 },
+ { offset: 42888, size: 2513, timecode: 1.128800 },
+ { offset: 45457, size: 3022, timecode: 1.261600 },
+ { offset: 48479, size: 815, timecode: 1.427600 },
+ { offset: 49338, size: 2818, timecode: 1.460800 },
+ { offset: 52200, size: 11581, timecode: 1.593600 },
+ { offset: 63825, size: 3003, timecode: 1.726400 },
+ { offset: 66872, size: 6390, timecode: 1.892400 },
+ { offset: 73306, size: 3740, timecode: 2.124800 },
+ { offset: 77102, size: 11779, timecode: 2.324000 },
+ { offset: 88881, size: 851, timecode: 2.490000 },
+ { offset: 89776, size: 4236, timecode: 2.523200 },
+ { offset: 94056, size: 9538, timecode: 2.755600 },
+ { offset: 103638, size: 13295, timecode: 3.154000 },
+ { offset: 116977, size: 309, timecode: 3.386400 },
+ { offset: 117330, size: 5806, timecode: 3.419600 },
+ { offset: 123180, size: 4392, timecode: 3.751600 },
+ { offset: 127616, size: 15408, timecode: 3.984000 },
+ { offset: 143068, size: 9899, timecode: 4.216400 },
+ { offset: 153011, size: 11562, timecode: 4.780800 },
+ { offset: 164617, size: 7398, timecode: 4.946800 },
+ { offset: 172059, size: 5698, timecode: 5.212400 },
+ { offset: 177801, size: 11682, timecode: 5.511200 },
+ { offset: 189527, size: 3023, timecode: 5.677200 },
+ { offset: 192594, size: 5726, timecode: 5.843200 },
+ ]
+ },
+ {
+ url: 'webm/test.webm',
+ type: 'video/webm; codecs="vp8, vorbis"',
+ duration: 6.042,
+ init: { offset: 0, size: 4357 },
+ media: [
+ { offset: 4357, size: 11830, timecode: 0 },
+ { offset: 16187, size: 12588, timecode: 0.385 },
+ { offset: 28775, size: 14588, timecode: 0.779 },
+ { offset: 43363, size: 13023, timecode: 1.174 },
+ { offset: 56386, size: 13127, timecode: 1.592 },
+ { offset: 69513, size: 14456, timecode: 1.987 },
+ { offset: 83969, size: 13458, timecode: 2.381 },
+ { offset: 97427, size: 14566, timecode: 2.776 },
+ { offset: 111993, size: 13201, timecode: 3.171 },
+ { offset: 125194, size: 14061, timecode: 3.566 },
+ { offset: 139255, size: 15353, timecode: 3.96 },
+ { offset: 154608, size: 13618, timecode: 4.378 },
+ { offset: 168226, size: 15094, timecode: 4.773 },
+ { offset: 183320, size: 13069, timecode: 5.168 },
+ { offset: 196389, size: 13788, timecode: 5.563 },
+ { offset: 210177, size: 9009, timecode: 5.957 },
+ ],
+ }
+ ];
+ EventExpectationsManager = function(test)
+ {
+ this.test_ = test;
+ this.eventTargetList_ = [];
+ this.waitCallbacks_ = [];
+ };
+
+ EventExpectationsManager.prototype.expectEvent = function(object, eventName, description)
+ {
+ var eventInfo = { 'target': object, 'type': eventName, 'description': description};
+ var expectations = this.getExpectations_(object);
+ expectations.push(eventInfo);
+
+ var t = this;
+ var waitHandler = this.test_.step_func(this.handleWaitCallback_.bind(this));
+ var eventHandler = this.test_.step_func(function(event)
+ {
+ object.removeEventListener(eventName, eventHandler);
+ var expected = expectations[0];
+ assert_equals(event.target, expected.target, "Event target match.");
+ assert_equals(event.type, expected.type, "Event types match.");
+ assert_equals(eventInfo.description, expected.description, "Descriptions match for '" + event.type + "'.");
+
+ expectations.shift(1);
+ if (t.waitCallbacks_.length > 0)
+ setTimeout(waitHandler, 0);
+ });
+ object.addEventListener(eventName, eventHandler);
+ };
+
+ EventExpectationsManager.prototype.waitForExpectedEvents = function(callback)
+ {
+ this.waitCallbacks_.push(callback);
+ setTimeout(this.test_.step_func(this.handleWaitCallback_.bind(this)), 0);
+ };
+
+ EventExpectationsManager.prototype.expectingEvents = function()
+ {
+ for (var i = 0; i < this.eventTargetList_.length; ++i) {
+ if (this.eventTargetList_[i].expectations.length > 0) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ EventExpectationsManager.prototype.handleWaitCallback_ = function()
+ {
+ if (this.waitCallbacks_.length == 0 || this.expectingEvents())
+ return;
+ var callback = this.waitCallbacks_.shift(1);
+ callback();
+ };
+
+ EventExpectationsManager.prototype.getExpectations_ = function(target)
+ {
+ for (var i = 0; i < this.eventTargetList_.length; ++i) {
+ var info = this.eventTargetList_[i];
+ if (info.target == target) {
+ return info.expectations;
+ }
+ }
+ var expectations = [];
+ this.eventTargetList_.push({ 'target': target, 'expectations': expectations });
+ return expectations;
+ };
+
+ function loadData_(test, url, callback, isBinary)
+ {
+ var request = new XMLHttpRequest();
+ request.open("GET", url, true);
+ if (isBinary) {
+ request.responseType = 'arraybuffer';
+ }
+ request.onload = test.step_func(function(event)
+ {
+ if (request.status != 200) {
+ assert_unreached("Unexpected status code : " + request.status);
+ return;
+ }
+ var response = request.response;
+ if (isBinary) {
+ response = new Uint8Array(response);
+ }
+ callback(response);
+ });
+ request.onerror = test.step_func(function(event)
+ {
+ assert_unreached("Unexpected error");
+ });
+ request.send();
+ }
+
+ function openMediaSource_(test, mediaTag, callback)
+ {
+ var mediaSource = new MediaSource();
+ var mediaSourceURL = URL.createObjectURL(mediaSource);
+
+ var eventHandler = test.step_func(onSourceOpen);
+ function onSourceOpen(event)
+ {
+ mediaSource.removeEventListener('sourceopen', eventHandler);
+ URL.revokeObjectURL(mediaSourceURL);
+ callback(mediaSource);
+ }
+
+ mediaSource.addEventListener('sourceopen', eventHandler);
+ mediaTag.src = mediaSourceURL;
+ }
+
+ var MediaSourceUtil = {};
+
+ MediaSourceUtil.loadTextData = function(test, url, callback)
+ {
+ loadData_(test, url, callback, false);
+ };
+
+ MediaSourceUtil.loadBinaryData = function(test, url, callback)
+ {
+ loadData_(test, url, callback, true);
+ };
+
+ MediaSourceUtil.fetchManifestAndData = function(test, manifestFilename, callback)
+ {
+ var baseURL = '';
+ var manifestURL = baseURL + manifestFilename;
+ MediaSourceUtil.loadTextData(test, manifestURL, function(manifestText)
+ {
+ var manifest = JSON.parse(manifestText);
+
+ assert_true(MediaSource.isTypeSupported(manifest.type), manifest.type + " is supported.");
+
+ var mediaURL = baseURL + manifest.url;
+ MediaSourceUtil.loadBinaryData(test, mediaURL, function(mediaData)
+ {
+ callback(manifest.type, mediaData);
+ });
+ });
+ };
+
+ MediaSourceUtil.extractSegmentData = function(mediaData, info)
+ {
+ var start = info.offset;
+ var end = start + info.size;
+ return mediaData.subarray(start, end);
+ }
+
+ MediaSourceUtil.getMediaDataForPlaybackTime = function(mediaData, segmentInfo, playbackTimeToAdd)
+ {
+ assert_less_than_equal(playbackTimeToAdd, segmentInfo.duration);
+ var mediaInfo = segmentInfo.media;
+ var start = mediaInfo[0].offset;
+ var numBytes = 0;
+ var segmentIndex = 0;
+ while (segmentIndex < mediaInfo.length && mediaInfo[segmentIndex].timecode <= playbackTimeToAdd)
+ {
+ numBytes += mediaInfo[segmentIndex].size;
+ ++segmentIndex;
+ }
+ return mediaData.subarray(start, numBytes + start);
+ }
+
+ function getFirstSupportedType(typeList)
+ {
+ for (var i = 0; i < typeList.length; ++i) {
+ if (window.MediaSource && MediaSource.isTypeSupported(typeList[i]))
+ return typeList[i];
+ }
+ return "";
+ }
+
+ function getSegmentInfo()
+ {
+ for (var i = 0; i < SEGMENT_INFO_LIST.length; ++i) {
+ var segmentInfo = SEGMENT_INFO_LIST[i];
+ if (window.MediaSource && MediaSource.isTypeSupported(segmentInfo.type)) {
+ return segmentInfo;
+ }
+ }
+ return null;
+ }
+
+ var audioOnlyTypes = ['audio/mp4;codecs="mp4a.40.2"', 'audio/webm;codecs="vorbis"'];
+ var videoOnlyTypes = ['video/mp4;codecs="avc1.4D4001"', 'video/webm;codecs="vp8"'];
+ var audioVideoTypes = ['video/mp4;codecs="avc1.4D4001,mp4a.40.2"', 'video/webm;codecs="vp8,vorbis"'];
+ MediaSourceUtil.AUDIO_ONLY_TYPE = getFirstSupportedType(audioOnlyTypes);
+ MediaSourceUtil.VIDEO_ONLY_TYPE = getFirstSupportedType(videoOnlyTypes);
+ MediaSourceUtil.AUDIO_VIDEO_TYPE = getFirstSupportedType(audioVideoTypes);
+ MediaSourceUtil.SEGMENT_INFO = getSegmentInfo();
+
+ MediaSourceUtil.getSubType = function(mimetype) {
+ var slashIndex = mimetype.indexOf("/");
+ var semicolonIndex = mimetype.indexOf(";");
+ if (slashIndex <= 0) {
+ assert_unreached("Invalid mimetype '" + mimetype + "'");
+ return;
+ }
+
+ var start = slashIndex + 1;
+ if (semicolonIndex >= 0) {
+ if (semicolonIndex <= start) {
+ assert_unreached("Invalid mimetype '" + mimetype + "'");
+ return;
+ }
+
+ return mimetype.substr(start, semicolonIndex - start)
+ }
+
+ return mimetype.substr(start);
+ };
+
+ MediaSourceUtil.append = function(test, sourceBuffer, data, callback)
+ {
+ function onUpdate() {
+ sourceBuffer.removeEventListener("update", onUpdate);
+ callback();
+ }
+ sourceBuffer.addEventListener("update", onUpdate);
+
+ test.failOnEvent(sourceBuffer, "error");
+
+ sourceBuffer.appendBuffer(data);
+ };
+
+ MediaSourceUtil.appendUntilEventFires = function(test, mediaElement, eventName, sourceBuffer, mediaData, segmentInfo, startingIndex)
+ {
+ var eventFired = false;
+ function onEvent() {
+ mediaElement.removeEventListener(eventName, onEvent);
+ eventFired = true;
+ }
+ mediaElement.addEventListener(eventName, onEvent);
+
+ var i = startingIndex;
+ var onAppendDone = function() {
+ if (eventFired)
+ return;
+
+ i++;
+ MediaSourceUtil.append(test, sourceBuffer, MediaSourceUtil.extractSegmentData(mediaData, segmentInfo.media[i]), onAppendDone);
+ };
+ MediaSourceUtil.append(test, sourceBuffer, MediaSourceUtil.extractSegmentData(mediaData, segmentInfo.media[i]), onAppendDone);
+
+ };
+
+ function addExtraTestMethods(test)
+ {
+ test.failOnEvent = function(object, eventName)
+ {
+ object.addEventListener(eventName, test.step_func(function(event)
+ {
+ assert_unreached("Unexpected event '" + eventName + "'");
+ }));
+ };
+
+ test.endOnEvent = function(object, eventName)
+ {
+ object.addEventListener(eventName, test.step_func(function(event) { test.done(); }));
+ };
+
+ test.eventExpectations_ = new EventExpectationsManager(test);
+ test.expectEvent = function(object, eventName, description)
+ {
+ test.eventExpectations_.expectEvent(object, eventName, description);
+ };
+
+ test.waitForExpectedEvents = function(callback)
+ {
+ test.eventExpectations_.waitForExpectedEvents(callback);
+ };
+
+ test.waitForCurrentTimeChange = function(mediaElement, callback)
+ {
+ var initialTime = mediaElement.currentTime;
+
+ var onTimeUpdate = test.step_func(function()
+ {
+ if (mediaElement.currentTime != initialTime) {
+ mediaElement.removeEventListener('timeupdate', onTimeUpdate);
+ callback();
+ }
+ });
+
+ mediaElement.addEventListener('timeupdate', onTimeUpdate);
+ }
+
+ var oldTestDone = test.done.bind(test);
+ test.done = function()
+ {
+ if (test.status == test.PASS) {
+ assert_false(test.eventExpectations_.expectingEvents(), "No pending event expectations.");
+ }
+ oldTestDone();
+ };
+ };
+
+ window['MediaSourceUtil'] = MediaSourceUtil;
+ window['media_test'] = function(testFunction, description, options)
+ {
+ options = options || {};
+ return async_test(function(test)
+ {
+ addExtraTestMethods(test);
+ testFunction(test);
+ }, description, options);
+ };
+ window['mediasource_test'] = function(testFunction, description, options)
+ {
+ return media_test(function(test)
+ {
+ var mediaTag = document.createElement("video");
+ document.body.appendChild(mediaTag);
+
+ test.removeMediaElement_ = true;
+ test.add_cleanup(function()
+ {
+ if (test.removeMediaElement_) {
+ document.body.removeChild(mediaTag);
+ test.removeMediaElement_ = false;
+ }
+ });
+
+ openMediaSource_(test, mediaTag, function(mediaSource)
+ {
+ testFunction(test, mediaTag, mediaSource);
+ });
+ }, description, options);
+ };
+
+ window['mediasource_testafterdataloaded'] = function(testFunction, description, options)
+ {
+ mediasource_test(function(test, mediaElement, mediaSource)
+ {
+ var segmentInfo = MediaSourceUtil.SEGMENT_INFO;
+
+ if (!segmentInfo) {
+ assert_unreached("No segment info compatible with this MediaSource implementation.");
+ return;
+ }
+
+ test.failOnEvent(mediaElement, 'error');
+
+ var sourceBuffer = mediaSource.addSourceBuffer(segmentInfo.type);
+ MediaSourceUtil.loadBinaryData(test, segmentInfo.url, function(mediaData)
+ {
+ testFunction(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData);
+ });
+ }, description, options);
+ }
+
+ function timeRangesToString(ranges)
+ {
+ var s = "{";
+ for (var i = 0; i < ranges.length; ++i) {
+ s += " [" + ranges.start(i).toFixed(3) + ", " + ranges.end(i).toFixed(3) + ")";
+ }
+ return s + " }";
+ }
+
+ window['assertBufferedEquals'] = function(obj, expected, description)
+ {
+ var actual = timeRangesToString(obj.buffered);
+ assert_equals(actual, expected, description);
+ };
+
+})(window);
diff --git a/tests/wpt/web-platform-tests/media-source/mp4/test-a-128k-44100Hz-1ch-manifest.json b/tests/wpt/web-platform-tests/media-source/mp4/test-a-128k-44100Hz-1ch-manifest.json
new file mode 100644
index 00000000000..f3caa460e9f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mp4/test-a-128k-44100Hz-1ch-manifest.json
@@ -0,0 +1,4 @@
+{
+ "url": "mp4/test-a-128k-44100Hz-1ch.mp4",
+ "type": "audio/mp4;codecs=\"mp4a.40.2\""
+} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/media-source/mp4/test-a-128k-44100Hz-1ch.mp4 b/tests/wpt/web-platform-tests/media-source/mp4/test-a-128k-44100Hz-1ch.mp4
new file mode 100644
index 00000000000..fc7832a5b38
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mp4/test-a-128k-44100Hz-1ch.mp4
Binary files differ
diff --git a/tests/wpt/web-platform-tests/media-source/mp4/test-a-192k-44100Hz-1ch-manifest.json b/tests/wpt/web-platform-tests/media-source/mp4/test-a-192k-44100Hz-1ch-manifest.json
new file mode 100644
index 00000000000..41a6f339b79
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mp4/test-a-192k-44100Hz-1ch-manifest.json
@@ -0,0 +1,4 @@
+{
+ "url": "mp4/test-a-192k-44100Hz-1ch.mp4",
+ "type": "audio/mp4;codecs=\"mp4a.40.2\""
+} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/media-source/mp4/test-a-192k-44100Hz-1ch.mp4 b/tests/wpt/web-platform-tests/media-source/mp4/test-a-192k-44100Hz-1ch.mp4
new file mode 100644
index 00000000000..864a87d25ba
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mp4/test-a-192k-44100Hz-1ch.mp4
Binary files differ
diff --git a/tests/wpt/web-platform-tests/media-source/mp4/test-av-384k-44100Hz-1ch-320x240-30fps-10kfr-manifest.json b/tests/wpt/web-platform-tests/media-source/mp4/test-av-384k-44100Hz-1ch-320x240-30fps-10kfr-manifest.json
new file mode 100644
index 00000000000..7731e3170e5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mp4/test-av-384k-44100Hz-1ch-320x240-30fps-10kfr-manifest.json
@@ -0,0 +1,4 @@
+{
+ "url": "mp4/test-av-384k-44100Hz-1ch-320x240-30fps-10kfr.mp4",
+ "type": "video/mp4;codecs=\"avc1.4D4001,mp4a.40.2\""
+} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/media-source/mp4/test-av-384k-44100Hz-1ch-320x240-30fps-10kfr.mp4 b/tests/wpt/web-platform-tests/media-source/mp4/test-av-384k-44100Hz-1ch-320x240-30fps-10kfr.mp4
new file mode 100644
index 00000000000..e623e8ee4c6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mp4/test-av-384k-44100Hz-1ch-320x240-30fps-10kfr.mp4
Binary files differ
diff --git a/tests/wpt/web-platform-tests/media-source/mp4/test-av-384k-44100Hz-1ch-640x480-30fps-10kfr-manifest.json b/tests/wpt/web-platform-tests/media-source/mp4/test-av-384k-44100Hz-1ch-640x480-30fps-10kfr-manifest.json
new file mode 100644
index 00000000000..78ded611f68
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mp4/test-av-384k-44100Hz-1ch-640x480-30fps-10kfr-manifest.json
@@ -0,0 +1,4 @@
+{
+ "url": "mp4/test-av-384k-44100Hz-1ch-640x480-30fps-10kfr.mp4",
+ "type": "video/mp4;codecs=\"avc1.4D4001,mp4a.40.2\""
+} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/media-source/mp4/test-av-384k-44100Hz-1ch-640x480-30fps-10kfr.mp4 b/tests/wpt/web-platform-tests/media-source/mp4/test-av-384k-44100Hz-1ch-640x480-30fps-10kfr.mp4
new file mode 100644
index 00000000000..946167b56ea
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mp4/test-av-384k-44100Hz-1ch-640x480-30fps-10kfr.mp4
Binary files differ
diff --git a/tests/wpt/web-platform-tests/media-source/mp4/test-av-448k-44100Hz-1ch-640x480-30fps-10kfr-manifest.json b/tests/wpt/web-platform-tests/media-source/mp4/test-av-448k-44100Hz-1ch-640x480-30fps-10kfr-manifest.json
new file mode 100644
index 00000000000..ba46349f93e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mp4/test-av-448k-44100Hz-1ch-640x480-30fps-10kfr-manifest.json
@@ -0,0 +1,4 @@
+{
+ "url": "mp4/test-av-448k-44100Hz-1ch-640x480-30fps-10kfr.mp4",
+ "type": "video/mp4;codecs=\"avc1.4D4001,mp4a.40.2\""
+} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/media-source/mp4/test-av-448k-44100Hz-1ch-640x480-30fps-10kfr.mp4 b/tests/wpt/web-platform-tests/media-source/mp4/test-av-448k-44100Hz-1ch-640x480-30fps-10kfr.mp4
new file mode 100644
index 00000000000..ace4bee53a6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mp4/test-av-448k-44100Hz-1ch-640x480-30fps-10kfr.mp4
Binary files differ
diff --git a/tests/wpt/web-platform-tests/media-source/mp4/test-av-640k-44100Hz-1ch-640x480-30fps-10kfr-manifest.json b/tests/wpt/web-platform-tests/media-source/mp4/test-av-640k-44100Hz-1ch-640x480-30fps-10kfr-manifest.json
new file mode 100644
index 00000000000..24da9b4ce3f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mp4/test-av-640k-44100Hz-1ch-640x480-30fps-10kfr-manifest.json
@@ -0,0 +1,4 @@
+{
+ "url": "mp4/test-av-640k-44100Hz-1ch-640x480-30fps-10kfr.mp4",
+ "type": "video/mp4;codecs=\"avc1.4D4001,mp4a.40.2\""
+} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/media-source/mp4/test-av-640k-44100Hz-1ch-640x480-30fps-10kfr.mp4 b/tests/wpt/web-platform-tests/media-source/mp4/test-av-640k-44100Hz-1ch-640x480-30fps-10kfr.mp4
new file mode 100644
index 00000000000..f224a5426a1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mp4/test-av-640k-44100Hz-1ch-640x480-30fps-10kfr.mp4
Binary files differ
diff --git a/tests/wpt/web-platform-tests/media-source/mp4/test-v-128k-320x240-24fps-8kfr-manifest.json b/tests/wpt/web-platform-tests/media-source/mp4/test-v-128k-320x240-24fps-8kfr-manifest.json
new file mode 100644
index 00000000000..a31b6d0245b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mp4/test-v-128k-320x240-24fps-8kfr-manifest.json
@@ -0,0 +1,4 @@
+{
+ "url": "mp4/test-v-128k-320x240-24fps-8kfr.mp4",
+ "type": "video/mp4;codecs=\"avc1.4D4001\""
+} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/media-source/mp4/test-v-128k-320x240-24fps-8kfr.mp4 b/tests/wpt/web-platform-tests/media-source/mp4/test-v-128k-320x240-24fps-8kfr.mp4
new file mode 100644
index 00000000000..cc55f40fa2e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mp4/test-v-128k-320x240-24fps-8kfr.mp4
Binary files differ
diff --git a/tests/wpt/web-platform-tests/media-source/mp4/test-v-128k-320x240-30fps-10kfr-manifest.json b/tests/wpt/web-platform-tests/media-source/mp4/test-v-128k-320x240-30fps-10kfr-manifest.json
new file mode 100644
index 00000000000..3e02844105b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mp4/test-v-128k-320x240-30fps-10kfr-manifest.json
@@ -0,0 +1,4 @@
+{
+ "url": "mp4/test-v-128k-320x240-30fps-10kfr.mp4",
+ "type": "video/mp4;codecs=\"avc1.4D4001\""
+} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/media-source/mp4/test-v-128k-320x240-30fps-10kfr.mp4 b/tests/wpt/web-platform-tests/media-source/mp4/test-v-128k-320x240-30fps-10kfr.mp4
new file mode 100644
index 00000000000..68d02cdfeca
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mp4/test-v-128k-320x240-30fps-10kfr.mp4
Binary files differ
diff --git a/tests/wpt/web-platform-tests/media-source/mp4/test-v-128k-640x480-30fps-10kfr-manifest.json b/tests/wpt/web-platform-tests/media-source/mp4/test-v-128k-640x480-30fps-10kfr-manifest.json
new file mode 100644
index 00000000000..10c4f4bcbdf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mp4/test-v-128k-640x480-30fps-10kfr-manifest.json
@@ -0,0 +1,4 @@
+{
+ "url": "mp4/test-v-128k-640x480-30fps-10kfr.mp4",
+ "type": "video/mp4;codecs=\"avc1.4D4001\""
+} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/media-source/mp4/test-v-128k-640x480-30fps-10kfr.mp4 b/tests/wpt/web-platform-tests/media-source/mp4/test-v-128k-640x480-30fps-10kfr.mp4
new file mode 100644
index 00000000000..c4f47f03582
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mp4/test-v-128k-640x480-30fps-10kfr.mp4
Binary files differ
diff --git a/tests/wpt/web-platform-tests/media-source/mp4/test-v-256k-320x240-30fps-10kfr-manifest.json b/tests/wpt/web-platform-tests/media-source/mp4/test-v-256k-320x240-30fps-10kfr-manifest.json
new file mode 100644
index 00000000000..42d3e1e524e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mp4/test-v-256k-320x240-30fps-10kfr-manifest.json
@@ -0,0 +1,4 @@
+{
+ "url": "mp4/test-v-256k-320x240-30fps-10kfr.mp4",
+ "type": "video/mp4;codecs=\"avc1.4D4001\""
+} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/media-source/mp4/test-v-256k-320x240-30fps-10kfr.mp4 b/tests/wpt/web-platform-tests/media-source/mp4/test-v-256k-320x240-30fps-10kfr.mp4
new file mode 100644
index 00000000000..6dc4972fd73
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mp4/test-v-256k-320x240-30fps-10kfr.mp4
Binary files differ
diff --git a/tests/wpt/web-platform-tests/media-source/mp4/test.mp4 b/tests/wpt/web-platform-tests/media-source/mp4/test.mp4
new file mode 100644
index 00000000000..eca97aad4bb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/mp4/test.mp4
Binary files differ
diff --git a/tests/wpt/web-platform-tests/media-source/webm/test-a-128k-44100Hz-1ch-manifest.json b/tests/wpt/web-platform-tests/media-source/webm/test-a-128k-44100Hz-1ch-manifest.json
new file mode 100644
index 00000000000..524da8149fe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/webm/test-a-128k-44100Hz-1ch-manifest.json
@@ -0,0 +1,4 @@
+{
+ "url": "webm/test-a-128k-44100Hz-1ch.webm",
+ "type": "audio/webm;codecs=\"vorbis\""
+} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/media-source/webm/test-a-128k-44100Hz-1ch.webm b/tests/wpt/web-platform-tests/media-source/webm/test-a-128k-44100Hz-1ch.webm
new file mode 100644
index 00000000000..c5b064deb9f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/webm/test-a-128k-44100Hz-1ch.webm
Binary files differ
diff --git a/tests/wpt/web-platform-tests/media-source/webm/test-a-192k-44100Hz-1ch-manifest.json b/tests/wpt/web-platform-tests/media-source/webm/test-a-192k-44100Hz-1ch-manifest.json
new file mode 100644
index 00000000000..7f2fa1e8c33
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/webm/test-a-192k-44100Hz-1ch-manifest.json
@@ -0,0 +1,4 @@
+{
+ "url": "webm/test-a-192k-44100Hz-1ch.webm",
+ "type": "audio/webm;codecs=\"vorbis\""
+} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/media-source/webm/test-a-192k-44100Hz-1ch.webm b/tests/wpt/web-platform-tests/media-source/webm/test-a-192k-44100Hz-1ch.webm
new file mode 100644
index 00000000000..53814d3bd69
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/webm/test-a-192k-44100Hz-1ch.webm
Binary files differ
diff --git a/tests/wpt/web-platform-tests/media-source/webm/test-av-384k-44100Hz-1ch-320x240-30fps-10kfr-manifest.json b/tests/wpt/web-platform-tests/media-source/webm/test-av-384k-44100Hz-1ch-320x240-30fps-10kfr-manifest.json
new file mode 100644
index 00000000000..af9f07af15d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/webm/test-av-384k-44100Hz-1ch-320x240-30fps-10kfr-manifest.json
@@ -0,0 +1,4 @@
+{
+ "url": "webm/test-av-384k-44100Hz-1ch-320x240-30fps-10kfr.webm",
+ "type": "video/webm;codecs=\"vp8,vorbis\""
+} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/media-source/webm/test-av-384k-44100Hz-1ch-320x240-30fps-10kfr.webm b/tests/wpt/web-platform-tests/media-source/webm/test-av-384k-44100Hz-1ch-320x240-30fps-10kfr.webm
new file mode 100644
index 00000000000..8b705dbc898
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/webm/test-av-384k-44100Hz-1ch-320x240-30fps-10kfr.webm
Binary files differ
diff --git a/tests/wpt/web-platform-tests/media-source/webm/test-av-384k-44100Hz-1ch-640x480-30fps-10kfr-manifest.json b/tests/wpt/web-platform-tests/media-source/webm/test-av-384k-44100Hz-1ch-640x480-30fps-10kfr-manifest.json
new file mode 100644
index 00000000000..f7ec86b3db9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/webm/test-av-384k-44100Hz-1ch-640x480-30fps-10kfr-manifest.json
@@ -0,0 +1,4 @@
+{
+ "url": "webm/test-av-384k-44100Hz-1ch-640x480-30fps-10kfr.webm",
+ "type": "video/webm;codecs=\"vp8,vorbis\""
+} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/media-source/webm/test-av-384k-44100Hz-1ch-640x480-30fps-10kfr.webm b/tests/wpt/web-platform-tests/media-source/webm/test-av-384k-44100Hz-1ch-640x480-30fps-10kfr.webm
new file mode 100644
index 00000000000..c5e010e3c7e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/webm/test-av-384k-44100Hz-1ch-640x480-30fps-10kfr.webm
Binary files differ
diff --git a/tests/wpt/web-platform-tests/media-source/webm/test-av-448k-44100Hz-1ch-640x480-30fps-10kfr-manifest.json b/tests/wpt/web-platform-tests/media-source/webm/test-av-448k-44100Hz-1ch-640x480-30fps-10kfr-manifest.json
new file mode 100644
index 00000000000..96a59db586e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/webm/test-av-448k-44100Hz-1ch-640x480-30fps-10kfr-manifest.json
@@ -0,0 +1,4 @@
+{
+ "url": "webm/test-av-448k-44100Hz-1ch-640x480-30fps-10kfr.webm",
+ "type": "video/webm;codecs=\"vp8,vorbis\""
+} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/media-source/webm/test-av-448k-44100Hz-1ch-640x480-30fps-10kfr.webm b/tests/wpt/web-platform-tests/media-source/webm/test-av-448k-44100Hz-1ch-640x480-30fps-10kfr.webm
new file mode 100644
index 00000000000..62c43288e68
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/webm/test-av-448k-44100Hz-1ch-640x480-30fps-10kfr.webm
Binary files differ
diff --git a/tests/wpt/web-platform-tests/media-source/webm/test-av-640k-44100Hz-1ch-640x480-30fps-10kfr-manifest.json b/tests/wpt/web-platform-tests/media-source/webm/test-av-640k-44100Hz-1ch-640x480-30fps-10kfr-manifest.json
new file mode 100644
index 00000000000..86723b34a81
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/webm/test-av-640k-44100Hz-1ch-640x480-30fps-10kfr-manifest.json
@@ -0,0 +1,4 @@
+{
+ "url": "webm/test-av-640k-44100Hz-1ch-640x480-30fps-10kfr.webm",
+ "type": "video/webm;codecs=\"vp8,vorbis\""
+} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/media-source/webm/test-av-640k-44100Hz-1ch-640x480-30fps-10kfr.webm b/tests/wpt/web-platform-tests/media-source/webm/test-av-640k-44100Hz-1ch-640x480-30fps-10kfr.webm
new file mode 100644
index 00000000000..93c31b6a979
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/webm/test-av-640k-44100Hz-1ch-640x480-30fps-10kfr.webm
Binary files differ
diff --git a/tests/wpt/web-platform-tests/media-source/webm/test-v-128k-320x240-24fps-8kfr-manifest.json b/tests/wpt/web-platform-tests/media-source/webm/test-v-128k-320x240-24fps-8kfr-manifest.json
new file mode 100644
index 00000000000..00e103aca9b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/webm/test-v-128k-320x240-24fps-8kfr-manifest.json
@@ -0,0 +1,4 @@
+{
+ "url": "webm/test-v-128k-320x240-24fps-8kfr.webm",
+ "type": "video/webm;codecs=\"vp8\""
+} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/media-source/webm/test-v-128k-320x240-24fps-8kfr.webm b/tests/wpt/web-platform-tests/media-source/webm/test-v-128k-320x240-24fps-8kfr.webm
new file mode 100644
index 00000000000..189c472f996
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/webm/test-v-128k-320x240-24fps-8kfr.webm
Binary files differ
diff --git a/tests/wpt/web-platform-tests/media-source/webm/test-v-128k-320x240-30fps-10kfr-manifest.json b/tests/wpt/web-platform-tests/media-source/webm/test-v-128k-320x240-30fps-10kfr-manifest.json
new file mode 100644
index 00000000000..fdeeb401d96
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/webm/test-v-128k-320x240-30fps-10kfr-manifest.json
@@ -0,0 +1,4 @@
+{
+ "url": "webm/test-v-128k-320x240-30fps-10kfr.webm",
+ "type": "video/webm;codecs=\"vp8\""
+} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/media-source/webm/test-v-128k-320x240-30fps-10kfr.webm b/tests/wpt/web-platform-tests/media-source/webm/test-v-128k-320x240-30fps-10kfr.webm
new file mode 100644
index 00000000000..18b2bafc3a6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/webm/test-v-128k-320x240-30fps-10kfr.webm
Binary files differ
diff --git a/tests/wpt/web-platform-tests/media-source/webm/test-v-128k-640x480-30fps-10kfr-manifest.json b/tests/wpt/web-platform-tests/media-source/webm/test-v-128k-640x480-30fps-10kfr-manifest.json
new file mode 100644
index 00000000000..4e304606678
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/webm/test-v-128k-640x480-30fps-10kfr-manifest.json
@@ -0,0 +1,4 @@
+{
+ "url": "webm/test-v-128k-640x480-30fps-10kfr.webm",
+ "type": "video/webm;codecs=\"vp8\""
+} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/media-source/webm/test-v-128k-640x480-30fps-10kfr.webm b/tests/wpt/web-platform-tests/media-source/webm/test-v-128k-640x480-30fps-10kfr.webm
new file mode 100644
index 00000000000..75e38b0bfab
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/webm/test-v-128k-640x480-30fps-10kfr.webm
Binary files differ
diff --git a/tests/wpt/web-platform-tests/media-source/webm/test-v-256k-320x240-30fps-10kfr-manifest.json b/tests/wpt/web-platform-tests/media-source/webm/test-v-256k-320x240-30fps-10kfr-manifest.json
new file mode 100644
index 00000000000..3470674bff5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/webm/test-v-256k-320x240-30fps-10kfr-manifest.json
@@ -0,0 +1,4 @@
+{
+ "url": "webm/test-v-256k-320x240-30fps-10kfr.webm",
+ "type": "video/webm;codecs=\"vp8\""
+} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/media-source/webm/test-v-256k-320x240-30fps-10kfr.webm b/tests/wpt/web-platform-tests/media-source/webm/test-v-256k-320x240-30fps-10kfr.webm
new file mode 100644
index 00000000000..0250d26fafe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/webm/test-v-256k-320x240-30fps-10kfr.webm
Binary files differ
diff --git a/tests/wpt/web-platform-tests/media-source/webm/test-vp8-vorbis-webvtt.webm b/tests/wpt/web-platform-tests/media-source/webm/test-vp8-vorbis-webvtt.webm
new file mode 100644
index 00000000000..c626f86e336
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/webm/test-vp8-vorbis-webvtt.webm
Binary files differ
diff --git a/tests/wpt/web-platform-tests/media-source/webm/test.webm b/tests/wpt/web-platform-tests/media-source/webm/test.webm
new file mode 100644
index 00000000000..6c2138d4eca
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media-source/webm/test.webm
Binary files differ
diff --git a/tests/wpt/web-platform-tests/media/A4.mp4 b/tests/wpt/web-platform-tests/media/A4.mp4
new file mode 100644
index 00000000000..ef66d43b9ea
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media/A4.mp4
Binary files differ
diff --git a/tests/wpt/web-platform-tests/media/A4.ogv b/tests/wpt/web-platform-tests/media/A4.ogv
new file mode 100644
index 00000000000..de99616eceb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media/A4.ogv
Binary files differ
diff --git a/tests/wpt/web-platform-tests/media/foo.vtt b/tests/wpt/web-platform-tests/media/foo.vtt
new file mode 100644
index 00000000000..b533895c604
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media/foo.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000
+Foo
diff --git a/tests/wpt/web-platform-tests/media/foo.vtt.headers b/tests/wpt/web-platform-tests/media/foo.vtt.headers
new file mode 100644
index 00000000000..23de552c1a4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media/foo.vtt.headers
@@ -0,0 +1 @@
+Access-Control-Allow-Origin: * \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/media/green-at-15.mp4 b/tests/wpt/web-platform-tests/media/green-at-15.mp4
new file mode 100644
index 00000000000..a9d2b979d41
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media/green-at-15.mp4
Binary files differ
diff --git a/tests/wpt/web-platform-tests/media/green-at-15.ogv b/tests/wpt/web-platform-tests/media/green-at-15.ogv
new file mode 100644
index 00000000000..50d59dfb38b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media/green-at-15.ogv
Binary files differ
diff --git a/tests/wpt/web-platform-tests/media/movie_300.mp4 b/tests/wpt/web-platform-tests/media/movie_300.mp4
new file mode 100644
index 00000000000..cf59777fb98
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media/movie_300.mp4
Binary files differ
diff --git a/tests/wpt/web-platform-tests/media/movie_300.ogv b/tests/wpt/web-platform-tests/media/movie_300.ogv
new file mode 100644
index 00000000000..0f83996e5dc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media/movie_300.ogv
Binary files differ
diff --git a/tests/wpt/web-platform-tests/media/movie_5.mp4 b/tests/wpt/web-platform-tests/media/movie_5.mp4
new file mode 100644
index 00000000000..fb5dbca2380
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media/movie_5.mp4
Binary files differ
diff --git a/tests/wpt/web-platform-tests/media/movie_5.ogv b/tests/wpt/web-platform-tests/media/movie_5.ogv
new file mode 100644
index 00000000000..e8990d1120a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media/movie_5.ogv
Binary files differ
diff --git a/tests/wpt/web-platform-tests/media/poster.png b/tests/wpt/web-platform-tests/media/poster.png
new file mode 100644
index 00000000000..bf6e253b3df
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media/poster.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/media/sound_5.mp3 b/tests/wpt/web-platform-tests/media/sound_5.mp3
new file mode 100644
index 00000000000..bd202919899
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media/sound_5.mp3
Binary files differ
diff --git a/tests/wpt/web-platform-tests/media/sound_5.oga b/tests/wpt/web-platform-tests/media/sound_5.oga
new file mode 100644
index 00000000000..239ad2bd08c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media/sound_5.oga
Binary files differ
diff --git a/tests/wpt/web-platform-tests/media/white.mp4 b/tests/wpt/web-platform-tests/media/white.mp4
new file mode 100644
index 00000000000..ef609e42813
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media/white.mp4
Binary files differ
diff --git a/tests/wpt/web-platform-tests/media/white.webm b/tests/wpt/web-platform-tests/media/white.webm
new file mode 100644
index 00000000000..bbacad7ffd8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/media/white.webm
Binary files differ
diff --git a/tests/wpt/web-platform-tests/mediacapture-streams/mediastreams-as-media-elements/video-assignment-manual.html b/tests/wpt/web-platform-tests/mediacapture-streams/mediastreams-as-media-elements/video-assignment-manual.html
new file mode 100644
index 00000000000..8d8ee34bcf7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mediacapture-streams/mediastreams-as-media-elements/video-assignment-manual.html
@@ -0,0 +1,56 @@
+<!doctype html>
+<html>
+<head>
+<title>Assigning mediastream to a video element</title>
+<link rel="author" title="Dominique Hazael-Massieux" href="mailto:dom@w3.org"/>
+<link rel="help" href="http://dev.w3.org/2011/webrtc/editor/getusermedia.html#navigatorusermedia">
+<link rel='stylesheet' href='/resources/testharness.css' media='all'/>
+</head>
+<body>
+<p class="instructions">When prompted, accept to share your video stream.</p>
+<h1 class="instructions">Description</h1>
+<p class="instructions">This test checks that the MediaStream object returned by
+the success callback in getUserMedia can be properly assigned to a video element
+via the <code>srcObject</code> attribute.</p>
+
+<video id="vid"></video>
+
+<div id='log'></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src="/common/vendor-prefix.js" data-prefixed-objects='[{"ancestors":["navigator"], "name":"getUserMedia"}]' data-prefixed-prototypes='[{"ancestors":["HTMLMediaElement"],"name":"srcObject"}]'></script>
+<script>
+var vid = document.getElementById("vid");
+var t = async_test("Tests that a MediaStream can be assigned to a video element with srcObject", {timeout: 10000});
+t.step(function() {
+ navigator.getUserMedia({video: true}, t.step_func(function (stream) {
+ var testOncePlaying = function() {
+ assert_equals(vid.played.length, 1, "A MediaStream's timeline always consists of a single range");
+ assert_equals(vid.played.start(0), 0, "A MediaStream's timeline always consists of a single range");
+ assert_equals(vid.played.end(0), vid.currentTime, "A MediaStream's timeline always consists of a single range");
+ assert_equals(vid.readyState, vid.HAVE_ENOUGH_DATA, "Upon selecting a media stream, the UA sets readyState to HAVE_ENOUGH_DATA");
+ var time = vid.currentTime;
+ assert_throws("INVALID_STATE_ERR", function() {
+ vid.currentTime = 0;
+ });
+ assert_equals(vid.currentTime, time, "The UA MUST ignore attempts to set the currentTime attribute");
+ // TODO add test that duration must be set to currentTime
+ // when mediastream is destroyed
+ vid.removeEventListener("timeupdate", testOncePlaying, false);
+ t.done();
+ }
+ vid.addEventListener("timeupdate", t.step_func(testOncePlaying), false);
+ vid.srcObject = stream;
+ vid.play();
+ assert_true(!vid.seeking, "A MediaStream is not seekable");
+ assert_equals(vid.seekable.length, 0, "A MediaStream is not seekable");
+ assert_equals(vid.defaultPlaybackRate, 1, "playback rate is always 1");
+ assert_equals(vid.playbackRate, 1, "playback rate is always 1");
+ assert_equals(vid.buffered.length, 0, "A MediaStream cannot be preloaded. Therefore, there is no buffered timeranges");
+ assert_equals(vid.duration, Infinity, " A MediaStream does not have a pre-defined duration. ");
+ assert_equals(vid.startDate, NaN, " A MediaStream does not specify a timeline offset");
+ }), function(error) {});
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/mediacapture-streams/obtaining-local-multimedia-content/navigatorusermedia/api-present.html b/tests/wpt/web-platform-tests/mediacapture-streams/obtaining-local-multimedia-content/navigatorusermedia/api-present.html
new file mode 100644
index 00000000000..84fece9fc21
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mediacapture-streams/obtaining-local-multimedia-content/navigatorusermedia/api-present.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<html>
+<head>
+<title>getUserMedia: test that getUserMedia is present (with or without vendor prefix)</title>
+<link rel="author" title="Dominique Hazael-Massieux" href="mailto:dom@w3.org"/>
+<link rel="help" href="http://dev.w3.org/2011/webrtc/editor/getusermedia.html#navigatorusermedia">
+<meta name='assert' content='Check that the getUserMedia() method is present.'/>
+<meta name='flags' content='vendor-prefix, dom'/>
+<link rel='stylesheet' href='/resources/testharness.css' media='all'/>
+</head>
+<body>
+<h1 class="instructions">Description</h1>
+<p class="instructions">This test checks for the presence of the
+<code>navigator.getUserMedia</code> method, taking vendor prefixes into account.</p>
+<div id='log'></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src="/common/vendor-prefix.js" data-prefixed-objects='[{"ancestors":["navigator"], "name":"getUserMedia"}]'></script>
+<script>
+test(function () {
+ assert_true(undefined !== navigator.getUserMedia, "navigator.getUserMedia exists");
+ }, "getUserMedia() is present on navigator");
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/mediacapture-streams/obtaining-local-multimedia-content/navigatorusermedia/deny.html b/tests/wpt/web-platform-tests/mediacapture-streams/obtaining-local-multimedia-content/navigatorusermedia/deny.html
new file mode 100644
index 00000000000..0cc3f93cf93
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mediacapture-streams/obtaining-local-multimedia-content/navigatorusermedia/deny.html
@@ -0,0 +1,36 @@
+<!doctype html>
+<html>
+<head>
+ <title>getUserMedia() triggers error callback when auth is denied</title>
+<link rel="author" title="Dominique Hazael-Massieux" href="mailto:dom@w3.org"/>
+<link rel="help" href="http://w3c.github.io/mediacapture-main/getusermedia.html#error-names">
+<link rel="help" href="http://w3c.github.io/mediacapture-main/getusermedia.html#idl-def-MediaStreamError">
+<link rel='stylesheet' href='/resources/testharness.css' media='all'/>
+</head>
+<body>
+<p class="instructions">When prompted, <strong>please deny</strong> access to
+the video stream.</p>
+<h1 class="instructions">Description</h1>
+<p class="instructions">This test checks that the error callback is triggered
+when user denies access to the video stream.</p>
+
+<div id='log'></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src="/common/vendor-prefix.js" data-prefixed-objects='[{"ancestors":["navigator"], "name":"getUserMedia"}]'></script>
+<script>
+var t = async_test("Tests that the error callback is triggered when permission is denied", {timeout:10000});
+t.step(function() {
+ navigator.getUserMedia({video: true}, t.step_func(function (stream) {
+ assert_unreached("The success callback should not be triggered since access is to be denied");
+ t.done();
+ }),
+ t.step_func(function (error) {
+ assert_equals(error.name, "PermissionDeniedError", "Permission denied error returned");
+ assert_equals(error.constraintName, null, "constraintName attribute not set for permission denied");
+ t.done();
+ }));
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/mediacapture-streams/obtaining-local-multimedia-content/navigatorusermedia/empty-option-param.html b/tests/wpt/web-platform-tests/mediacapture-streams/obtaining-local-multimedia-content/navigatorusermedia/empty-option-param.html
new file mode 100644
index 00000000000..4536cb03425
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mediacapture-streams/obtaining-local-multimedia-content/navigatorusermedia/empty-option-param.html
@@ -0,0 +1,36 @@
+<!doctype html>
+<html>
+<head>
+<title>getUserMedia({}) aborts with NOT_SUPPORTED_ERR</title>
+<link rel="author" title="Dominique Hazael-Massieux" href="mailto:dom@w3.org"/>
+<link rel="help" href="http://dev.w3.org/2011/webrtc/editor/getusermedia.html#widl-NavigatorUserMedia-getUserMedia-void-MediaStreamConstraints-constraints-NavigatorUserMediaSuccessCallback-successCallback-NavigatorUserMediaErrorCallback-errorCallback">
+<link rel='stylesheet' href='/resources/testharness.css' media='all'/>
+</head>
+<body>
+<h1 class="instructions">Description</h1>
+<p class="instructions">This test checks that getUserMedia with no value in the
+options parameter raises a NOT_SUPPORTED_ERR exception.</p>
+
+<div id='log'></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src="/common/vendor-prefix.js" data-prefixed-objects='[{"ancestors":["navigator"], "name":"getUserMedia"}]'></script>
+<script>
+var t = async_test("Tests that getUserMedia raises a NOT_SUPPORTED_ERR exception when used with an empty options parameter");
+t.step( function () {
+ // TODO This is no longer what's in the spec, see https://www.w3.org/Bugs/Public/show_bug.cgi?id=22211
+ assert_throws("NOT_SUPPORTED_ERR",
+ function () {
+ navigator.getUserMedia({}, t.step_func(function (stream) {
+ assert_unreached("This should never be triggered since the constraints parameter is empty");
+ t.done();
+ }), t.step_func(function (error) {
+ assert_unreached("This should never be triggered since the constraints parameter is empty");
+ }));
+ });
+ t.done();
+});
+
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/mediacapture-streams/obtaining-local-multimedia-content/navigatorusermedia/getusermedia-impossible-constraint.html b/tests/wpt/web-platform-tests/mediacapture-streams/obtaining-local-multimedia-content/navigatorusermedia/getusermedia-impossible-constraint.html
new file mode 100644
index 00000000000..fcbef13e539
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mediacapture-streams/obtaining-local-multimedia-content/navigatorusermedia/getusermedia-impossible-constraint.html
@@ -0,0 +1,34 @@
+<!doctype html>
+<html>
+<head>
+<title>Trivial mandatory constraint in getUserMedia</title>
+<link rel="author" title="Dominique Hazael-Massieux" href="mailto:dom@w3.org"/>
+<link rel="help" href="http://dev.w3.org/2011/webrtc/editor/getusermedia.html#widl-NavigatorUserMedia-getUserMedia-void-MediaStreamConstraints-constraints-NavigatorUserMediaSuccessCallback-successCallback-NavigatorUserMediaErrorCallback-errorCallback">
+<link rel="help" href="http://dev.w3.org/2011/webrtc/editor/getusermedia.html#idl-def-NavigatorUserMediaError">
+<link rel='stylesheet' href='/resources/testharness.css' media='all'/>
+</head>
+<body>
+<p class="instructions">When prompted, accept to share your video stream.</p>
+<h1 class="instructions">Description</h1>
+<p class="instructions">This test checks that setting a trivial mandatory
+constraint (width &gt;=0) in getUserMedia works</p>
+
+<div id='log'></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src="/common/vendor-prefix.js" data-prefixed-objects='[{"ancestors":["navigator"], "name":"getUserMedia"}]'></script>
+<script>
+var t = async_test("Tests that setting an impossible constraint in getUserMedia fails", {timeout:10000});
+t.step(function() {
+ navigator.getUserMedia({video: {mandatory: {width: {min:Infinity}}}}, t.step_func(function (stream) {
+ assert_unreached("a Video stream of infinite width cannot be created");
+ t.done();
+ }), t.step_func(function(error) {
+ assert_equals(error.name, "ConstraintNotSatisfiedError", "An impossible constraint triggers a ConstraintNotSatisfiedError");
+ assert_equals(error.constraintName, "width", "The name of the not satisfied error is given in error.constraintName");
+ t.done();
+ }));
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/mediacapture-streams/obtaining-local-multimedia-content/navigatorusermedia/getusermedia-optional-constraint.html b/tests/wpt/web-platform-tests/mediacapture-streams/obtaining-local-multimedia-content/navigatorusermedia/getusermedia-optional-constraint.html
new file mode 100644
index 00000000000..9364911fa5f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mediacapture-streams/obtaining-local-multimedia-content/navigatorusermedia/getusermedia-optional-constraint.html
@@ -0,0 +1,33 @@
+<!doctype html>
+<html>
+<head>
+<title>Optional constraint recognized as optional in getUserMedia</title>
+<link rel="author" title="Dominique Hazael-Massieux" href="mailto:dom@w3.org"/>
+<link rel="help" href="http://dev.w3.org/2011/webrtc/editor/getusermedia.html#widl-NavigatorUserMedia-getUserMedia-void-MediaStreamConstraints-constraints-NavigatorUserMediaSuccessCallback-successCallback-NavigatorUserMediaErrorCallback-errorCallback">
+<link rel='stylesheet' href='/resources/testharness.css' media='all'/>
+</head>
+<body>
+<p class="instructions">When prompted, accept to share your video stream.</p>
+<h1 class="instructions">Description</h1>
+<p class="instructions">This test checks that setting an optional constraint in
+getUserMedia is handled as optional</p>
+
+<div id='log'></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src="/common/vendor-prefix.js" data-prefixed-objects='[{"ancestors":["navigator"], "name":"getUserMedia"}]'></script>
+<script>
+var t = async_test("Tests that setting an optional constraint in getUserMedia is handled as optional", {timeout:10000});
+t.step(function() {
+ navigator.getUserMedia({video: {optional: [{width: {min:1024}}, {width: {max: 800}}]}},
+ t.step_func(function (stream) {
+ assert_equals(stream.getVideoTracks().length, 1, "the media stream has exactly one video track");
+ t.done();
+ }),
+ t.step_func(function(error) {
+ assert_unreached("an optional constraint can't stop us from obtaining a video stream");
+ }));
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/mediacapture-streams/obtaining-local-multimedia-content/navigatorusermedia/getusermedia-trivial-constraint.html b/tests/wpt/web-platform-tests/mediacapture-streams/obtaining-local-multimedia-content/navigatorusermedia/getusermedia-trivial-constraint.html
new file mode 100644
index 00000000000..739fdaf814c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mediacapture-streams/obtaining-local-multimedia-content/navigatorusermedia/getusermedia-trivial-constraint.html
@@ -0,0 +1,32 @@
+<!doctype html>
+<html>
+<head>
+<title>Trivial mandatory constraint in getUserMedia</title>
+<link rel="author" title="Dominique Hazael-Massieux" href="mailto:dom@w3.org"/>
+<link rel="help" href="http://dev.w3.org/2011/webrtc/editor/getusermedia.html#widl-NavigatorUserMedia-getUserMedia-void-MediaStreamConstraints-constraints-NavigatorUserMediaSuccessCallback-successCallback-NavigatorUserMediaErrorCallback-errorCallback">
+<link rel='stylesheet' href='/resources/testharness.css' media='all'/>
+</head>
+<body>
+<p class="instructions">When prompted, accept to share your video stream.</p>
+<h1 class="instructions">Description</h1>
+<p class="instructions">This test checks that setting a trivial mandatory
+constraint (width &gt;=0) in getUserMedia works</p>
+
+<div id='log'></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src="/common/vendor-prefix.js" data-prefixed-objects='[{"ancestors":["navigator"], "name":"getUserMedia"}]'></script>
+<script>
+var t = async_test("Tests that setting a trivial mandatory constraint in getUserMedia works", {timeout:10000});
+t.step(function() {
+ navigator.getUserMedia({video: {mandatory: {width: {min:0}}}}, t.step_func(function (stream) {
+ assert_equals(stream.getVideoTracks().length, 1, "the media stream has exactly one video track");
+ t.done();
+ }), t.step_func(function(error) {
+ assert_unreached("a Video stream of minimally zero width can always be created");
+ t.done();
+ }));
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/mediacapture-streams/obtaining-local-multimedia-content/navigatorusermedia/unknownkey-option-param.html b/tests/wpt/web-platform-tests/mediacapture-streams/obtaining-local-multimedia-content/navigatorusermedia/unknownkey-option-param.html
new file mode 100644
index 00000000000..9f99c667f5d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mediacapture-streams/obtaining-local-multimedia-content/navigatorusermedia/unknownkey-option-param.html
@@ -0,0 +1,38 @@
+<!doctype html>
+<html>
+<head>
+<title>getUserMedia({doesnotexist:true}) aborts with NOT_SUPPORTED_ERR</title>
+<link rel="author" title="Dominique Hazael-Massieux" href="mailto:dom@w3.org"/>
+<link rel="help" href="http://dev.w3.org/2011/webrtc/editor/getusermedia.html#widl-NavigatorUserMedia-getUserMedia-void-MediaStreamConstraints-constraints-NavigatorUserMediaSuccessCallback-successCallback-NavigatorUserMediaErrorCallback-errorCallback">
+<link rel='stylesheet' href='/resources/testharness.css' media='all'/>
+</head>
+<body>
+<h1 class="instructions">Description</h1>
+<p class="instructions">This test checks that getUserMedia with an unknown value
+in the options parameter raises a NOT_SUPPORTED_ERR exception.</p>
+
+<div id='log'></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src="/common/vendor-prefix.js" data-prefixed-objects='[{"ancestors":["navigator"], "name":"getUserMedia"}]'></script>
+<script>
+test(function () {
+ // TODO This is no longer what's in the spec, see https://www.w3.org/Bugs/Public/show_bug.cgi?id=22211
+ assert_throws(
+ "NOT_SUPPORTED_ERR",
+ function () {
+ navigator.getUserMedia(
+ {doesnotexist:true},
+ t.step_func(function (stream) {
+ assert_unreached("This should never be triggered since the constraints parameter is unrecognized");
+ }), t.step_func(function (error) {
+ assert_unreached("This should never be triggered since the constraints parameter is unrecognized");
+ }));
+ }
+ )
+ }
+);
+
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/mediacapture-streams/stream-api/introduction/disabled-audio-silence.html b/tests/wpt/web-platform-tests/mediacapture-streams/stream-api/introduction/disabled-audio-silence.html
new file mode 100644
index 00000000000..dfd5abf501e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mediacapture-streams/stream-api/introduction/disabled-audio-silence.html
@@ -0,0 +1,56 @@
+<!doctype html>
+<html>
+<head>
+<title>A disabled audio track is rendered as silence</title>
+<link rel="author" title="Dominique Hazael-Massieux" href="mailto:dom@w3.org"/>
+<link rel="help" href="http://dev.w3.org/2011/webrtc/editor/getusermedia.html#introduction">
+<link rel="help" href="http://dev.w3.org/2011/webrtc/editor/getusermedia.html#mediastreams-as-media-elements">
+<link rel='stylesheet' href='/resources/testharness.css' media='all'/>
+</head>
+<body>
+<p class="instructions">When prompted, accept to share your audio stream.</p>
+<h1 class="instructions">Description</h1>
+<p class="instructions">This test checks that a disabled audio track in a
+MediaStream is rendered as silence. It relies on the
+<a href="https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html">
+Web Audio API</a>.</p>
+
+<div id='log'></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src="/common/vendor-prefix.js" data-prefixed-objects='[{"ancestors":["navigator"], "name":"getUserMedia"}, {"ancestors":["window"], "name":"AudioContext"}]'></script>
+<script>
+var t = async_test("Tests that a disabled audio track in a MediaStream is rendered as silence", {timeout: 200000});
+var aud = document.getElementById("aud");
+t.step(function() {
+ navigator.getUserMedia({audio: true}, t.step_func(function (stream) {
+ var ctx = new AudioContext();
+ var streamSource = ctx.createMediaStreamSource(stream);
+ var silenceDetector = ctx.createScriptProcessor(1024);
+ var count = 10;
+ silenceDetector.onaudioprocess = t.step_func(function (e) {
+ var buffer1 = e.inputBuffer.getChannelData(0);
+ var buffer2 = e.inputBuffer.getChannelData(1);
+ var out = e.outputBuffer.getChannelData(0);
+ out = new Float32Array(buffer1);
+ for (var i = 0; i < buffer1.length; i++) {
+ assert_equals(buffer1[i], 0, "Audio buffer entry #" + i + " in channel 0 is silent");
+ }
+ for (var i = 0; i < buffer2.length; i++) {
+ assert_equals(buffer2[i], 0, "Audio buffer entry #" + i + " in channel 1 is silent");
+ }
+ count--;
+ if (count === 0) {
+ silenceDetector.onaudioprocess = null;
+ t.done();
+ }
+ });
+ stream.getAudioTracks()[0].enabled = false;
+
+ streamSource.connect(silenceDetector);
+ silenceDetector.connect(ctx.destination);
+ }), function(error) {});
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/mediacapture-streams/stream-api/introduction/disabled-video-black.html b/tests/wpt/web-platform-tests/mediacapture-streams/stream-api/introduction/disabled-video-black.html
new file mode 100644
index 00000000000..93e2828a97c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mediacapture-streams/stream-api/introduction/disabled-video-black.html
@@ -0,0 +1,57 @@
+<!doctype html>
+<html>
+<head>
+<title>A disabled video track is rendered as blackness</title>
+<link rel="author" title="Dominique Hazael-Massieux" href="mailto:dom@w3.org"/>
+<link rel="help" href="http://dev.w3.org/2011/webrtc/editor/getusermedia.html#introduction">
+<link rel="help" href="http://dev.w3.org/2011/webrtc/editor/getusermedia.html#mediastreams-as-media-elements">
+<link rel='stylesheet' href='/resources/testharness.css' media='all'/>
+</head>
+<body>
+<p class="instructions">When prompted, accept to share your video stream.</p>
+<h1 class="instructions">Description</h1>
+<p class="instructions">This test checks that a disabled video track in a
+MediaStream is rendered as blackness.</p>
+<video id="vid"></video>
+
+<div id='log'></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src="/common/vendor-prefix.js" data-prefixed-objects='[{"ancestors":["navigator"], "name":"getUserMedia"}]' data-prefixed-prototypes='[{"ancestors":["HTMLMediaElement"],"name":"srcObject"}]'></script>
+<script>
+var vid = document.getElementById("vid");
+var cv = document.createElement("canvas");
+var t = async_test("Tests that a disabled video track in a MediaStream is rendered as blackness", {timeout: 10000});
+t.step(function() {
+ navigator.getUserMedia(
+ {video: true},
+ t.step_func(function (stream) {
+ var testOncePlaying = function() {
+ if (stream.getVideoTracks()[0].enabled) {
+ stream.getVideoTracks()[0].enabled = false;
+ return;
+ }
+
+ vid.removeEventListener("timeupdate", testOncePlaying, false);
+ cv.width = vid.offsetWidth;
+ cv.height = vid.offsetHeight;
+ var ctx = cv.getContext("2d");
+ ctx.drawImage(vid,0,0);
+ var imageData = ctx.getImageData(0, 0, cv.width, cv.height);
+ for (var i = 0; i < imageData.data.length; i+=4) {
+ assert_equals(imageData.data[i], 0, "No red component in pixel #" + i);
+ assert_equals(imageData.data[i + 1], 0, "No green component in pixel #" + i);
+ assert_equals(imageData.data[i + 2], 0, "No blue component in pixel #" + i);
+ assert_equals(imageData.data[i + 3], 255, "No transparency in pixel #" + i);
+ }
+ t.done();
+ }
+ vid.srcObject = stream;
+ vid.play();
+ vid.addEventListener("timeupdate", t.step_func(testOncePlaying), false);
+ }),
+ function(error) {});
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/mediacapture-streams/stream-api/mediastream/audio.html b/tests/wpt/web-platform-tests/mediacapture-streams/stream-api/mediastream/audio.html
new file mode 100644
index 00000000000..2b4cc5719f6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mediacapture-streams/stream-api/mediastream/audio.html
@@ -0,0 +1,36 @@
+<!doctype html>
+<html>
+<head>
+<title>getUserMedia({audio:true}) creates a stream with at least an audio track</title>
+<link rel="author" title="Dominique Hazael-Massieux" href="mailto:dom@w3.org"/>
+<link rel="help" href="http://dev.w3.org/2011/webrtc/editor/getusermedia.html#widl-NavigatorUserMedia-getUserMedia-void-MediaStreamConstraints-constraints-NavigatorUserMediaSuccessCallback-successCallback-NavigatorUserMediaErrorCallback-errorCallback">
+<link rel="help" href="http://dev.w3.org/2011/webrtc/editor/getusermedia.html#widl-MediaStreamTrack-kind">
+<link rel='stylesheet' href='/resources/testharness.css' media='all'/>
+</head>
+<body>
+<p class="instructions">When prompted, accept to share your audio stream.</p>
+<h1 class="instructions">Description</h1>
+<p class="instructions">This test checks that the MediaStream object returned by
+the success callback in getUserMedia has exactly one audio track.</p>
+
+<div id='log'></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src="/common/vendor-prefix.js" data-prefixed-objects='[{"ancestors":["navigator"], "name":"getUserMedia"}, {"ancestors":["window"], "name":"MediaStream"}]'></script>
+<script>
+var astream;
+var t = async_test("Tests that a MediaStream with exactly one audio track is returned", {timeout: 10000});
+t.step(function() {
+ navigator.getUserMedia({audio:true}, t.step_func(function (stream) {
+ astream = stream;
+ assert_true(stream instanceof MediaStream, "getUserMedia success callback comes with a MediaStream object");
+ assert_equals(stream.getAudioTracks().length, 1, "the media stream has exactly one audio track");
+ assert_equals(stream.getAudioTracks()[0].kind, "audio", "getAudioTracks() returns a sequence of tracks whose kind is 'audio'");
+ assert_equals(stream.getVideoTracks().length, 0, "the media stream has zero video track");
+ t.done();
+ }),
+ function(error) {});
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/mediacapture-streams/stream-api/mediastream/mediastream-addtrack.html b/tests/wpt/web-platform-tests/mediacapture-streams/stream-api/mediastream/mediastream-addtrack.html
new file mode 100644
index 00000000000..9dcfc380e71
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mediacapture-streams/stream-api/mediastream/mediastream-addtrack.html
@@ -0,0 +1,55 @@
+<!doctype html>
+<html>
+<head>
+<title>Adding a track to a MediaStream</title>
+<link rel="author" title="Dominique Hazael-Massieux" href="mailto:dom@w3.org"/>
+<link rel="help" href="http://dev.w3.org/2011/webrtc/editor/getusermedia.html#widl-MediaStreamTrackList-add-void-MediaStreamTrack-track">
+<link rel="help" href="http://dev.w3.org/2011/webrtc/editor/getusermedia.html#event-mediastream-addtrack">
+<link rel='stylesheet' href='/resources/testharness.css' media='all'/>
+</head>
+<body>
+<p class="instructions">When prompted, accept to share your audio stream, then your video stream.</p>
+<h1 class="instructions">Description</h1>
+<p class="instructions">This test checks that adding a track to a MediaStream works as expected.</p>
+
+<div id='log'></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src="/common/vendor-prefix.js" data-prefixed-objects='[{"ancestors":["navigator"], "name":"getUserMedia"}]'></script>
+<script>
+var t = async_test("Tests that adding a track to a MediaStream works as expected", {timeout: 20000}); // longer timeout since requires double user interaction
+t.step(function () {
+ var audio, video;
+
+ navigator.getUserMedia({audio: true}, gotAudio, function(error) {});
+ function gotAudio(stream) {
+ audio = stream;
+ navigator.getUserMedia({video: true}, gotVideo, function(error) {});
+ }
+
+ function gotVideo(stream) {
+ video = stream;
+ t.step(function () {
+ assert_equals(video.getAudioTracks().length, 0, "video mediastream starts with no audio track");
+ video.addTrack(audio.getAudioTracks()[0]);
+ assert_equals(video.getAudioTracks().length, 1, "video mediastream has now one audio track");
+ video.addTrack(audio.getAudioTracks()[0]);
+ assert_equals(video.getAudioTracks().length, 1, "video mediastream still has one audio track"); // If track is already in stream's track set, then abort these steps.
+
+ });
+ audio.onaddtrack = t.step_func(function () {
+ assert_unreached("onaddtrack is not fired when the script directly modified the track of a mediastream");
+ });
+ t.step(function () {
+ assert_equals(audio.getVideoTracks().length, 0, "audio mediastream starts with no video track");
+ audio.addTrack(video.getVideoTracks()[0]);
+ assert_equals(audio.getVideoTracks().length, 1, "audio mediastream now has one video track");
+ });
+ t.step(function () {
+ t.done();
+ });
+ }
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/mediacapture-streams/stream-api/mediastream/mediastream-finished-add.html b/tests/wpt/web-platform-tests/mediacapture-streams/stream-api/mediastream/mediastream-finished-add.html
new file mode 100644
index 00000000000..21d61194fff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mediacapture-streams/stream-api/mediastream/mediastream-finished-add.html
@@ -0,0 +1,49 @@
+<!doctype html>
+<html>
+<head>
+<title>Adding a track to a finished MediaStream</title>
+<link rel="author" title="Dominique Hazael-Massieux" href="mailto:dom@w3.org"/>
+<link rel="help" href="http://dev.w3.org/2011/webrtc/editor/getusermedia.html#widl-MediaStreamTrackList-add-void-MediaStreamTrack-track">
+<link rel="help" href="http://dev.w3.org/2011/webrtc/editor/getusermedia.html#widl-MediaStreamTrack-stop-void">
+<link rel='stylesheet' href='/resources/testharness.css' media='all'/>
+</head>
+<body>
+<p class="instructions">When prompted, accept to share your audio stream, then
+your video stream.</p>
+<h1 class="instructions">Description</h1>
+<p class="instructions">This test checks that adding a track to a finished
+MediaStream raises an INVALID_STATE_ERR exception.</p>
+
+<div id='log'></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src="/common/vendor-prefix.js" data-prefixed-objects='[{"ancestors":["navigator"], "name":"getUserMedia"}]'></script>
+<script>
+var t = async_test("Tests that an addition to a finished MediaStream raises an exception", {timeout:20000});
+t.step(function () {
+ var audio, video;
+
+ navigator.getUserMedia({audio:true}, gotAudio, function() {});
+ function gotAudio(stream) {
+ audio = stream;
+ navigator.getUserMedia({video:true}, gotVideo, function() {});
+ }
+
+ function gotVideo(stream) {
+ video = stream;
+ t.step(function () {
+ audio.getAudioTracks()[0].stop();
+ assert_true(audio.ended, "Audio stream is ended after stopping its only audio track");
+ assert_throws("INVALID_STATE_ERR", function () {
+ video.addTrack(audio.getAudioTracks()[0]);
+ }, "Adding a track from a finished stream raises an INVALID_STATE_ERR exception");
+ assert_throws("INVALID_STATE_ERR", function () {
+ audio.removeTrack(audio.getAudioTracks()[0]);
+ }, "Removing a track from a finished stream raises an INVALID_STATE_ERR exception");
+ });
+ t.done();
+ }
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/mediacapture-streams/stream-api/mediastream/mediastream-gettrackid.html b/tests/wpt/web-platform-tests/mediacapture-streams/stream-api/mediastream/mediastream-gettrackid.html
new file mode 100644
index 00000000000..40bbbdbb6b7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mediacapture-streams/stream-api/mediastream/mediastream-gettrackid.html
@@ -0,0 +1,36 @@
+<!doctype html>
+<html>
+<head>
+<title>Retrieving a track from a MediaStream</title>
+<link rel="author" title="Dominique Hazael-Massieux" href="mailto:dom@w3.org"/>
+<link rel="help" href="http://dev.w3.org/2011/webrtc/editor/getusermedia.html#widl-MediaStream-getTrackById-MediaStreamTrack-DOMString-trackId">
+<link rel='stylesheet' href='/resources/testharness.css' media='all'/>
+</head>
+<body>
+<p class="instructions">When prompted, accept to share your video stream.</p>
+<h1 class="instructions">Description</h1>
+<p class="instructions">This test checks that MediaStream.getTrackById behaves as expected</p>
+
+<div id='log'></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src="/common/vendor-prefix.js" data-prefixed-objects='[{"ancestors":["navigator"], "name":"getUserMedia"}]'></script>
+<script>
+var t = async_test("Tests that MediaStream.getTrackById works as expected", {timeout: 10000});
+t.step(function () {
+ navigator.getUserMedia(
+ {video: true},
+ t.step_func(gotVideo),
+ t.step_func(function (error) {
+ assert_unreached('Unexpected getUserMedia error: ' + error);
+ }));
+ function gotVideo(stream) {
+ var track = stream.getVideoTracks()[0];
+ assert_equals(track, stream.getTrackById(track.id), "getTrackById returns track of given id");
+ assert_equals(stream.getTrackById(track.id + "foo"), null, "getTrackById of inexistant id returns null");
+ t.done();
+ }
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/mediacapture-streams/stream-api/mediastream/mediastream-id-manual.html b/tests/wpt/web-platform-tests/mediacapture-streams/stream-api/mediastream/mediastream-id-manual.html
new file mode 100644
index 00000000000..4d4f5683cd9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mediacapture-streams/stream-api/mediastream/mediastream-id-manual.html
@@ -0,0 +1,33 @@
+<!doctype html>
+<html>
+<head>
+<title>getUserMedia() creates a stream with a proper id</title>
+<link rel="author" title="Dominique Hazael-Massieux" href="mailto:dom@w3.org"/>
+<link rel="help" href="http://dev.w3.org/2011/webrtc/editor/getusermedia.html#widl-MediaStream-id">
+<link rel='stylesheet' href='/resources/testharness.css' media='all'/>
+</head>
+<body>
+<p class="instructions">When prompted, accept to share your video stream.</p>
+<h1 class="instructions">Description</h1>
+<p class="instructions">This test checks that the MediaStream object returned by
+the success callback in getUserMedia has a correct id.</p>
+
+<div id='log'></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src="/common/vendor-prefix.js" data-prefixed-objects='[{"ancestors":["navigator"], "name":"getUserMedia"}]'></script>
+<script>
+var t = async_test("Tests that a MediaStream with a correct id is returned");
+var allowedCharacters = /^[\u0021\u0023-\u0027\u002A-\u002B\u002D-\u002E\u0030-\u0039\u0041-\u005A\u005E-\u007E]*$/;
+if (window.navigator.getUserMedia) {
+ navigator.getUserMedia({video:true}, function (stream) {
+ t.step(function () {
+ assert_true(stream.id.length === 36, "the media stream id has 36 characters");
+ assert_regexp_match(stream.id, allowedCharacters, "the media stream id uses the set of allowed characters");
+ });
+ t.done();
+}, function(error) {});
+}
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/mediacapture-streams/stream-api/mediastream/mediastream-idl.html b/tests/wpt/web-platform-tests/mediacapture-streams/stream-api/mediastream/mediastream-idl.html
new file mode 100644
index 00000000000..57ef7daa292
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mediacapture-streams/stream-api/mediastream/mediastream-idl.html
@@ -0,0 +1,53 @@
+<!doctype html>
+<html>
+<head>
+<title>MediaStream constructor algorithm</title>
+<link rel="author" title="Dominique Hazael-Massieux" href="mailto:dom@w3.org"/>
+<link rel="help" href="http://dev.w3.org/2011/webrtc/editor/getusermedia.html#idl-def-MediaStream">
+<link rel="help" href="http://dev.w3.org/2011/webrtc/editor/getusermedia.html#widl-MediaStream-id">
+<link rel="help" href="http://dev.w3.org/2011/webrtc/editor/getusermedia.html#mediastream">
+<link rel="help" href="http://dev.w3.org/2011/webrtc/editor/getusermedia.html#event-mediastream-ended">
+<link rel="help" href="http://dev.w3.org/2011/webrtc/editor/getusermedia.html#widl-MediaStreamTrack-stop-void">
+<link rel="help" href="http://dev.w3.org/2011/webrtc/editor/getusermedia.html#widl-MediaStreamTrack-clone-MediaStreamTrack">
+<link rel='stylesheet' href='/resources/testharness.css' media='all'/>
+</head>
+<body>
+<p class="instructions">When prompted, accept to share your video and audio stream.</p>
+<h1 class="instructions">Description</h1>
+<p class="instructions">This test checks that the MediaStream constructor
+follows the algorithm set in the spec.</p>
+
+<div id='log'></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src="/common/vendor-prefix.js" data-prefixed-objects='[{"ancestors":["navigator"], "name":"getUserMedia"},{"ancestors":["window"], "name":"MediaStream"}]'></script>
+<script>
+var t = async_test("Tests that a MediaStream constructor follows the algorithm set in the spec", {timeout: 10000});
+t.step(function() {
+ navigator.getUserMedia({video: true, audio:true}, t.step_func(function (stream) {
+ var stream1 = new MediaStream();
+ assert_not_equals(stream.id, stream1.id, "Two different MediaStreams have different ids");
+ var stream2 = new MediaStream(stream);
+ assert_not_equals(stream.id, stream2.id, "A MediaStream constructed from another have different ids");
+ var audioTrack1 = stream.getAudioTracks()[0];
+ var videoTrack = stream.getVideoTracks()[0];
+ assert_equals(audioTrack1, stream2.getAudioTracks()[0], "A MediaStream constructed from another share the same audio track");
+ assert_equals(videoTrack, stream2.getVideoTracks()[0], "A MediaStream constructed from another share the same video track");
+ var stream4 = new MediaStream([audioTrack1]);
+ assert_equals(stream4.getTrackById(audioTrack1.id), audioTrack1, "a non-ended track gets added via the MediaStream constructor");
+
+ var audioTrack2 = audioTrack1.clone();
+ audioTrack2.addEventListener("ended", t.step_func(function () {
+ var stream3 = new MediaStream([audioTrack2, videoTrack]);
+ assert_equals(stream3.getTrackById(audioTrack2.id), null, "an ended track doesn't get added via the MediaStream constructor");
+ assert_equals(stream3.getTrackById(videoTrack.id), videoTrack, "a non-ended track gets added via the MediaStream constructor even if the previous track was ended");
+ var stream5 = new MediaStream([audioTrack2]);
+ assert_true(stream5.ended, "a MediaStream created using the MediaStream() constructor whose arguments are lists of MediaStreamTrack objects that are all ended, the MediaStream object MUST be created with its ended attribute set to true");
+ t.done();
+ }), false);
+ audioTrack2.stop();
+ }), function(error) {});
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/mediacapture-streams/stream-api/mediastream/mediastream-removetrack.html b/tests/wpt/web-platform-tests/mediacapture-streams/stream-api/mediastream/mediastream-removetrack.html
new file mode 100644
index 00000000000..7d684cde2c2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mediacapture-streams/stream-api/mediastream/mediastream-removetrack.html
@@ -0,0 +1,49 @@
+<!doctype html>
+<html>
+<head>
+<title>Removing a track from a MediaStream</title>
+<link rel="author" title="Dominique Hazael-Massieux" href="mailto:dom@w3.org"/>
+<link rel="help" href="http://dev.w3.org/2011/webrtc/editor/getusermedia.html#widl-MediaStreamTrackList-remove-void-MediaStreamTrack-track">
+<link rel="help" href="http://dev.w3.org/2011/webrtc/editor/getusermedia.html#event-mediastream-removetrack">
+<link rel='stylesheet' href='/resources/testharness.css' media='all'/>
+</head>
+<body>
+<p class="instructions">When prompted, accept to share your audio stream, then your video stream.</p>
+<h1 class="instructions">Description</h1>
+<p class="instructions">This test checks that removinging a track from a MediaStream works as expected.</p>
+
+<div id='log'></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src="/common/vendor-prefix.js" data-prefixed-objects='[{"ancestors":["navigator"], "name":"getUserMedia"}]'></script>
+<script>
+var t = async_test("Tests that a removal from a MediaStream works as expected", {timeout:10000});
+t.step(function () {
+ var audio;
+ navigator.getUserMedia({audio:true}, gotAudio, function(error) {});
+ function gotAudio(stream) {
+ audio = stream;
+ navigator.getUserMedia({video:true}, gotVideo, function(error) {});
+ }
+
+ function gotVideo(stream) {
+ console.log(stream);
+ var video = stream;
+ console.log(video);
+ video.onremovetrack = function () {
+ assert_unreached("onremovetrack is not triggered when removal of track is triggered by the script itself");
+ };
+ t.step(function () {
+ assert_equals(video.getVideoTracks().length, 1, "video mediastream starts with one video track");
+ video.removeTrack(video.getVideoTracks()[0]);
+ assert_equals(video.getVideoTracks().length, 0, "video mediastream has no video track left");
+ video.removeTrack(audio.getAudioTracks()[0]); // should not throw
+ });
+ t.step(function() {
+ t.done();
+ });
+ }
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/mediacapture-streams/stream-api/mediastream/stream-ended.html b/tests/wpt/web-platform-tests/mediacapture-streams/stream-api/mediastream/stream-ended.html
new file mode 100644
index 00000000000..4d537ca25a1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mediacapture-streams/stream-api/mediastream/stream-ended.html
@@ -0,0 +1,37 @@
+<!doctype html>
+<html>
+<head>
+<title>getUserMedia({video:true}) creates a stream with ended set to false</title>
+<link rel="author" title="Dominique Hazael-Massieux" href="mailto:dom@w3.org"/>
+<link rel="help" href="http://dev.w3.org/2011/webrtc/editor/getusermedia.html#widl-MediaStream-ended">
+<link rel="help" href="http://dev.w3.org/2011/webrtc/editor/getusermedia.html#event-mediastream-ended">
+<link rel='stylesheet' href='/resources/testharness.css' media='all'/>
+</head>
+<body>
+<p class="instructions">When prompted, accept to share your video stream.</p>
+<h1 class="instructions">Description</h1>
+<p class="instructions">This test checks that the MediaStream object returned by
+the success callback in getUserMedia has a ended set to false at start, and
+triggers "onended" when it is set to true.</p>
+
+<div id='log'></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src="/common/vendor-prefix.js" data-prefixed-objects='[{"ancestors":["navigator"], "name":"getUserMedia"}]'></script>
+<script>
+var t = async_test("Tests that a MediaStream handles ended correctly", {timeout:10000});
+t.step(function () {
+ navigator.getUserMedia({video:true}, t.step_func(function (stream) {
+ assert_true(!stream.ended, "the media stream starts with ended set to false");
+ stream.addEventListener("ended", t.step_func(function() {
+ assert_true(stream.ended, "stream.ended now set to true");
+ t.done();
+ }), false);
+ stream.ended = true;
+ assert_true(!stream.ended, "stream.ended should remain false");
+ stream.getVideoTracks()[0].stop();
+ }), function (error) {});
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/mediacapture-streams/stream-api/mediastream/video.html b/tests/wpt/web-platform-tests/mediacapture-streams/stream-api/mediastream/video.html
new file mode 100644
index 00000000000..90d967b8a8e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mediacapture-streams/stream-api/mediastream/video.html
@@ -0,0 +1,34 @@
+<!doctype html>
+<html>
+<head>
+<title>getUserMedia({video:true}) creates a stream with one video track</title>
+<link rel="author" title="Dominique Hazael-Massieux" href="mailto:dom@w3.org"/>
+<link rel="help" href="http://dev.w3.org/2011/webrtc/editor/getusermedia.html#widl-NavigatorUserMedia-getUserMedia-void-MediaStreamConstraints-constraints-NavigatorUserMediaSuccessCallback-successCallback-NavigatorUserMediaErrorCallback-errorCallback">
+<link rel="help" href="http://dev.w3.org/2011/webrtc/editor/getusermedia.html#widl-MediaStreamTrack-kind">
+
+<link rel='stylesheet' href='/resources/testharness.css' media='all'/>
+</head>
+<body>
+<p class="instructions">When prompted, accept to share your video stream.</p>
+<h1 class="instructions">Description</h1>
+<p class="instructions">This test checks that the MediaStream object returned by
+the success callback in getUserMedia has exactly one video track and no audio.</p>
+
+<div id='log'></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src="/common/vendor-prefix.js" data-prefixed-objects='[{"ancestors":["navigator"], "name":"getUserMedia"}, {"ancestors":["window"], "name":"MediaStream"}]'></script>
+<script>
+var t = async_test("Tests that a MediaStream with at least one video track is returned");
+t.step(function() {
+ navigator.getUserMedia({video: true}, t.step_func(function (stream) {
+ assert_true(stream instanceof MediaStream, "getUserMedia success callback comes with a MediaStream object");
+ assert_equals(stream.getAudioTracks().length, 0, "the media stream has zero audio track");
+ assert_equals(stream.getVideoTracks().length, 1, "the media stream has exactly one video track");
+ assert_equals(stream.getVideoTracks()[0].kind, "video", "getAudioTracks() returns a sequence of tracks whose kind is 'video'");
+ t.done();
+ }), function(error) {});
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/mediacapture-streams/stream-api/mediastreamtrack/mediastreamtrack-end.html b/tests/wpt/web-platform-tests/mediacapture-streams/stream-api/mediastreamtrack/mediastreamtrack-end.html
new file mode 100644
index 00000000000..988f1ee3551
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mediacapture-streams/stream-api/mediastreamtrack/mediastreamtrack-end.html
@@ -0,0 +1,40 @@
+<!doctype html>
+<html>
+<head>
+<title>Test that mediastreamtrack are properly ended</title>
+<link rel="author" title="Dominique Hazael-Massieux" href="mailto:dom@w3.org"/>
+<link rel="help" href="http://dev.w3.org/2011/webrtc/editor/getusermedia.html#mediastreamtrack">
+<link rel='stylesheet' href='/resources/testharness.css' media='all'/>
+</head>
+<body>
+<p class="instructions">When prompted, accept to share your video and audio
+stream, and then revoke that permission.</p>
+<h1 class="instructions">Description</h1>
+<p class="instructions">This test checks that the video and audio tracks of
+MediaStream object returned by the success callback in getUserMedia are
+correctly set into ended state when permission is revoked.</p>
+
+<div id='log'></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src="/common/vendor-prefix.js" data-prefixed-objects='[{"ancestors":["navigator"], "name":"getUserMedia"}]'></script>
+<script>
+var t = async_test("Tests that the video MediaStreamTrack objects are properly ended on permission revocation", {timeout: 20000}); // longer timeout since requires user interaction
+t.step(function () {
+ navigator.getUserMedia({audio: true,video: true}, t.step_func(function (stream) {
+ var vidTrack = stream.getVideoTracks()[0];
+ assert_equals(vidTrack.readyState, "live", "The video track object is in live state");
+ var audTrack = stream.getAudioTracks()[0];
+ assert_equals(audTrack.readyState, "live", "The audio track object is in live state");
+ vidTrack.onended = t.step_func(function () {
+ assert_equals(vidTrack.readyState, "ended", "Video track has been ended as expected");
+ assert_equals(audTrack.readyState, "ended", "Audio track has been ended as expected");
+ assert_true(stream.ended, "MediaStream has been ended as expected");
+ t.done();
+ });
+ }), function (error) {}
+ );
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/mediacapture-streams/stream-api/mediastreamtrack/mediastreamtrack-id.html b/tests/wpt/web-platform-tests/mediacapture-streams/stream-api/mediastreamtrack/mediastreamtrack-id.html
new file mode 100644
index 00000000000..8e0eb101fc1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mediacapture-streams/stream-api/mediastreamtrack/mediastreamtrack-id.html
@@ -0,0 +1,29 @@
+<!doctype html>
+<html>
+<head>
+<title>Distinct id for distinct mediastream tracks</title>
+<link rel="author" title="Dominique Hazael-Massieux" href="mailto:dom@w3.org"/>
+<link rel="help" href="http://dev.w3.org/2011/webrtc/editor/getusermedia.html#widl-MediaStreamTrack-id">
+<link rel='stylesheet' href='/resources/testharness.css' media='all'/>
+</head>
+<body>
+<p class="instructions">When prompted, accept to share your audio and video stream.</p>
+<h1 class="instructions">Description</h1>
+<p class="instructions">This test checks that distinct mediastream tracks have distinct ids.</p>
+
+<div id='log'></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src="/common/vendor-prefix.js" data-prefixed-objects='[{"ancestors":["navigator"], "name":"getUserMedia"}]'></script>
+<script>
+var t = async_test("Tests that distinct mediastream tracks have distinct ids ", {timeout: 10000});
+t.step(function () {
+ navigator.getUserMedia({video: true, audio: true}, t.step_func(gotStream), t.step_func(function(error) {t.assert_unreached("Access to audio and video stream is granted");}));
+ function gotStream(stream) {
+ assert_not_equals(stream.getVideoTracks()[0], stream.getAudioTracks()[0].id, "audio and video tracks have distinct ids");
+ t.done();
+ }
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/mediacapture-streams/stream-api/mediastreamtrack/mediastreamtrack-init.html b/tests/wpt/web-platform-tests/mediacapture-streams/stream-api/mediastreamtrack/mediastreamtrack-init.html
new file mode 100644
index 00000000000..42d1ff9dd62
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mediacapture-streams/stream-api/mediastreamtrack/mediastreamtrack-init.html
@@ -0,0 +1,77 @@
+<!doctype html>
+<html>
+<head>
+<title>getUserMedia({video:true}) creates a stream with a properly initialized video track</title>
+<link rel="author" title="Dominique Hazael-Massieux" href="mailto:dom@w3.org"/>
+<link rel="help" href="http://dev.w3.org/2011/webrtc/editor/getusermedia.html#idl-def-MediaStreamTrack">
+<link rel="help" href="http://dev.w3.org/2011/webrtc/editor/getusermedia.html#life-cycle-and-media-flow">
+<link rel="help" href="http://dev.w3.org/2011/webrtc/editor/getusermedia.html#widl-MediaStreamTrack-kind">
+<link rel="help" href="http://dev.w3.org/2011/webrtc/editor/getusermedia.html#widl-MediaStreamTrack-enabled">
+<link rel="help" href="http://dev.w3.org/2011/webrtc/editor/getusermedia.html#widl-MediaStreamTrack-readyState">
+<link rel='stylesheet' href='/resources/testharness.css' media='all'/>
+</head>
+<body>
+<p class="instructions">When prompted, accept to share your video stream.</p>
+<h1 class="instructions">Description</h1>
+<p class="instructions">This test checks that the video track of MediaStream
+object returned by the success callback in getUserMedia is correctly initialized.</p>
+
+<div id='log'></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=/resources/webidl2/lib/webidl2.js></script>
+<script src=/resources/idlharness.js></script>
+<script src="/common/vendor-prefix.js" data-prefixed-objects='[{"ancestors":["navigator"], "name":"getUserMedia"}]'></script>
+<script>
+var t = async_test("Tests that the video MediaStreamTrack objects are properly initialized", {timeout:10000});
+var track = null
+var idl_array = new IdlArray();
+idl_array.add_idls("interface EventTarget {\
+ void addEventListener(DOMString type, EventListener? callback, optional boolean capture = false);\
+ void removeEventListener(DOMString type, EventListener? callback, optional boolean capture = false);\
+ boolean dispatchEvent(Event event);\
+};");
+
+/*idl_array.add_idls("callback interface EventListener {\
+ void handleEvent(Event event);\
+};");*/
+idl_array.add_idls("interface MediaStreamTrack : EventTarget {\
+ readonly attribute DOMString kind;\
+ readonly attribute DOMString id;\
+ readonly attribute DOMString label;\
+ attribute boolean enabled;\
+ readonly attribute boolean muted;\
+ attribute EventHandler onmute;\
+ attribute EventHandler onunmute;\
+ readonly attribute boolean _readonly;\
+ readonly attribute boolean remote;\
+ readonly attribute MediaStreamTrackState readyState;\
+ attribute EventHandler onstarted;\
+ attribute EventHandler onended;\
+ static sequence<SourceInfo> getSourceInfos ();\
+ MediaTrackConstraints? constraints ();\
+ MediaSourceStates states ();\
+ (AllVideoCapabilities or AllAudioCapabilities) capabilities ();\
+ void applyConstraints (MediaTrackConstraints constraints);\
+ attribute EventHandler onoverconstrained;\
+ MediaStreamTrack clone ();\
+ void stop ();\
+};");
+
+t.step(function () {
+ navigator.getUserMedia({video: true}, t.step_func(function (stream) {
+ var videoTracks = stream.getVideoTracks();
+ assert_equals(videoTracks.length, 1, "There is exactly one video track in the media stream");
+ track = videoTracks[0];
+ assert_equals(track.readyState, "live", "The track object is in live state");
+ assert_equals(track.kind, "video", "The track object is of video kind");
+ assert_true(track.enabled, "The track object is enabed"); // Not clear that this is required by the spec, see https://www.w3.org/Bugs/Public/show_bug.cgi?id=22212
+ idl_array.add_objects({MediaStreamTrack: ["track"]});
+ idl_array.test();
+
+ t.done();
+ }), function (error) {});
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/mediacapture-streams/stream-api/video-and-audio-tracks/audiostreamtrack.html b/tests/wpt/web-platform-tests/mediacapture-streams/stream-api/video-and-audio-tracks/audiostreamtrack.html
new file mode 100644
index 00000000000..611fc2803ef
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mediacapture-streams/stream-api/video-and-audio-tracks/audiostreamtrack.html
@@ -0,0 +1,27 @@
+<!doctype html>
+<html>
+<head>
+<title>AudioStreamTrack is defined</title>
+<link rel="author" title="Dominique Hazael-Massieux" href="mailto:dom@w3.org"/>
+<link rel="help" href="http://dev.w3.org/2011/webrtc/editor/getusermedia.html#idl-def-AudioStreamTrack">
+<link rel='stylesheet' href='/resources/testharness.css' media='all'/>
+</head>
+<body>
+
+<h1 class="instructions">Description</h1>
+<p class="instructions">This test verifies the availability of the AudioStreamTrack interface.</p>
+<div id='log'></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=/resources/webidl2/lib/webidl2.js></script>
+<script src=/resources/idlharness.js></script>
+<script>
+var idl_array = new IdlArray();
+idl_array.add_idls("[Constructor(optional MediaTrackConstraints audioConstraints)]\
+interface AudioStreamTrack : MediaStreamTrack {\
+ static sequence<DOMString> getSourceIds ();\
+};");
+idl_array.test();
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/mediacapture-streams/stream-api/video-and-audio-tracks/videostreamtrack.html b/tests/wpt/web-platform-tests/mediacapture-streams/stream-api/video-and-audio-tracks/videostreamtrack.html
new file mode 100644
index 00000000000..1213bb47617
--- /dev/null
+++ b/tests/wpt/web-platform-tests/mediacapture-streams/stream-api/video-and-audio-tracks/videostreamtrack.html
@@ -0,0 +1,27 @@
+<!doctype html>
+<html>
+<head>
+<title>VideoStreamTrack is defined</title>
+<link rel="author" title="Dominique Hazael-Massieux" href="mailto:dom@w3.org"/>
+<link rel="help" href="http://dev.w3.org/2011/webrtc/editor/getusermedia.html#idl-def-VideoStreamTrack">
+<link rel='stylesheet' href='/resources/testharness.css' media='all'/>
+</head>
+<body>
+
+<h1 class="instructions">Description</h1>
+<p class="instructions">This test verifies the availability of the VideoStreamTrack interface.</p>
+<div id='log'></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=/resources/webidl2/lib/webidl2.js></script>
+<script src=/resources/idlharness.js></script>
+<script>
+var idl_array = new IdlArray();
+idl_array.add_idls("[Constructor(optional MediaTrackConstraints videoConstraints)]\
+interface VideoStreamTrack : MediaStreamTrack {\
+ static sequence<DOMString> getSourceIds ();\
+};");
+idl_array.test();
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/microdata/conformance-requirements/.gitkeep b/tests/wpt/web-platform-tests/microdata/conformance-requirements/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/microdata/conformance-requirements/.gitkeep
diff --git a/tests/wpt/web-platform-tests/microdata/converting-html-to-other-formats/.gitkeep b/tests/wpt/web-platform-tests/microdata/converting-html-to-other-formats/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/microdata/converting-html-to-other-formats/.gitkeep
diff --git a/tests/wpt/web-platform-tests/microdata/converting-html-to-other-formats/json/.gitkeep b/tests/wpt/web-platform-tests/microdata/converting-html-to-other-formats/json/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/microdata/converting-html-to-other-formats/json/.gitkeep
diff --git a/tests/wpt/web-platform-tests/microdata/dependencies/.gitkeep b/tests/wpt/web-platform-tests/microdata/dependencies/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/microdata/dependencies/.gitkeep
diff --git a/tests/wpt/web-platform-tests/microdata/encoding-microdata/.gitkeep b/tests/wpt/web-platform-tests/microdata/encoding-microdata/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/microdata/encoding-microdata/.gitkeep
diff --git a/tests/wpt/web-platform-tests/microdata/encoding-microdata/associating-names-with-items/.gitkeep b/tests/wpt/web-platform-tests/microdata/encoding-microdata/associating-names-with-items/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/microdata/encoding-microdata/associating-names-with-items/.gitkeep
diff --git a/tests/wpt/web-platform-tests/microdata/encoding-microdata/items/.gitkeep b/tests/wpt/web-platform-tests/microdata/encoding-microdata/items/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/microdata/encoding-microdata/items/.gitkeep
diff --git a/tests/wpt/web-platform-tests/microdata/encoding-microdata/microdata-and-other-namespaces/.gitkeep b/tests/wpt/web-platform-tests/microdata/encoding-microdata/microdata-and-other-namespaces/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/microdata/encoding-microdata/microdata-and-other-namespaces/.gitkeep
diff --git a/tests/wpt/web-platform-tests/microdata/encoding-microdata/names-the-itemprop-attribute/.gitkeep b/tests/wpt/web-platform-tests/microdata/encoding-microdata/names-the-itemprop-attribute/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/microdata/encoding-microdata/names-the-itemprop-attribute/.gitkeep
diff --git a/tests/wpt/web-platform-tests/microdata/encoding-microdata/names-the-itemprop-attribute/original-id.json b/tests/wpt/web-platform-tests/microdata/encoding-microdata/names-the-itemprop-attribute/original-id.json
new file mode 100644
index 00000000000..144cacfda8b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/microdata/encoding-microdata/names-the-itemprop-attribute/original-id.json
@@ -0,0 +1 @@
+{"original_id":"names:-the-itemprop-attribute"} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/microdata/encoding-microdata/the-microdata-model/.gitkeep b/tests/wpt/web-platform-tests/microdata/encoding-microdata/the-microdata-model/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/microdata/encoding-microdata/the-microdata-model/.gitkeep
diff --git a/tests/wpt/web-platform-tests/microdata/encoding-microdata/values/.gitkeep b/tests/wpt/web-platform-tests/microdata/encoding-microdata/values/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/microdata/encoding-microdata/values/.gitkeep
diff --git a/tests/wpt/web-platform-tests/microdata/iana/.gitkeep b/tests/wpt/web-platform-tests/microdata/iana/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/microdata/iana/.gitkeep
diff --git a/tests/wpt/web-platform-tests/microdata/introduction/.gitkeep b/tests/wpt/web-platform-tests/microdata/introduction/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/microdata/introduction/.gitkeep
diff --git a/tests/wpt/web-platform-tests/microdata/introduction/global-identifiers-for-items/.gitkeep b/tests/wpt/web-platform-tests/microdata/introduction/global-identifiers-for-items/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/microdata/introduction/global-identifiers-for-items/.gitkeep
diff --git a/tests/wpt/web-platform-tests/microdata/introduction/overview/.gitkeep b/tests/wpt/web-platform-tests/microdata/introduction/overview/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/microdata/introduction/overview/.gitkeep
diff --git a/tests/wpt/web-platform-tests/microdata/introduction/selecting-names-when-defining-vocabularies/.gitkeep b/tests/wpt/web-platform-tests/microdata/introduction/selecting-names-when-defining-vocabularies/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/microdata/introduction/selecting-names-when-defining-vocabularies/.gitkeep
diff --git a/tests/wpt/web-platform-tests/microdata/introduction/the-basic-syntax/.gitkeep b/tests/wpt/web-platform-tests/microdata/introduction/the-basic-syntax/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/microdata/introduction/the-basic-syntax/.gitkeep
diff --git a/tests/wpt/web-platform-tests/microdata/introduction/typed-items/.gitkeep b/tests/wpt/web-platform-tests/microdata/introduction/typed-items/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/microdata/introduction/typed-items/.gitkeep
diff --git a/tests/wpt/web-platform-tests/microdata/introduction/using-the-microdata-dom-api/.gitkeep b/tests/wpt/web-platform-tests/microdata/introduction/using-the-microdata-dom-api/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/microdata/introduction/using-the-microdata-dom-api/.gitkeep
diff --git a/tests/wpt/web-platform-tests/microdata/microdata-dom-api/.gitkeep b/tests/wpt/web-platform-tests/microdata/microdata-dom-api/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/microdata/microdata-dom-api/.gitkeep
diff --git a/tests/wpt/web-platform-tests/microdata/microdata-dom-api/001.html b/tests/wpt/web-platform-tests/microdata/microdata-dom-api/001.html
new file mode 100644
index 00000000000..822b0441444
--- /dev/null
+++ b/tests/wpt/web-platform-tests/microdata/microdata-dom-api/001.html
@@ -0,0 +1,3665 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset="UTF-8">
+ <title>Microdata tests</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="http://dev.w3.org/html5/md/#microdata-dom-api">
+ <link rel="help" href="http://dev.w3.org/html5/md/#encoding-microdata">
+ </head>
+ <body>
+ <noscript><p>Enable JavaScript and reload</p></noscript>
+ <div id="log">Running test...</div>
+ <div itemscope itemtype="http://example.com/bar data:text/plain, http://example.com/foo" id="one"></div>
+ <div itemscope itemtype="http://example.com/bar" id="two"></div>
+ <div itemscope itemtype="http://example.com/foo http://example.com/bar" id="three">
+ <div itemscope itemtype="http://example.com/bar data:text/plain," id="four"></div>
+ </div>
+ <div itemscope id="five"></div>
+ <script type="text/javascript">
+/* All tests are stand-alone.
+To reduce this testsuite to show only a single desired test,
+simply remove all test(...) blocks before and after it. */
+
+var urls = {"base":"http://" + location.host + "/",
+ "www":"http://www." + location.host + "/",
+ "www1":"http://www1." + location.host + "/"}
+
+function makeEl(eltype,props,contents) {
+ var elem = document.createElement(eltype);
+ for( var i in props ) {
+ //just in case the framework extends object...
+ if( props.hasOwnProperty(i) ) {
+ elem.setAttribute(i,props[i]);
+ }
+ }
+ if( contents ) {
+ elem.innerHTML = contents;
+ }
+ return elem;
+}
+
+/* getItem tests */
+test(function () {
+ assert_true( !!document.getItems );
+}, 'document.getItems must exist');
+test(function () {
+ assert_true( document.getItems() instanceof NodeList, 'instanceof test' );
+ NodeList.prototype.customProperty = true;
+ assert_true( document.getItems().customProperty, 'inheritance test' );
+}, 'document.getItems must return a NodeList');
+test(function () {
+ assert_equals( document.getItems().length, 5 );
+}, 'document.getItems must locate the correct number of items');
+test(function () {
+ var nlist = document.getItems();
+ var foo = makeEl('div',{itemscope:'itemscope'});
+ document.body.appendChild(foo);
+ var templength = nlist.length;
+ document.body.removeChild(foo);
+ assert_equals( templength, 6 );
+ assert_equals( nlist.length, 5 );
+}, 'document.getItems must return a live NodeList');
+test(function () {
+ var nlist = document.getItems();
+ document.getElementById('one').removeAttribute('itemscope');
+ var templength = nlist.length;
+ document.getElementById('one').setAttribute('itemscope','itemscope');
+ assert_equals( templength, 4 );
+ assert_equals( nlist.length, 5 );
+}, 'live NodeList must notice when itemscope changes');
+test(function () {
+ document.getElementById('one').removeAttribute('itemscope');
+ var templength = document.getItems().length;
+ document.getElementById('one').setAttribute('itemscope','itemscope');
+ assert_equals( templength, 4 );
+ assert_equals( document.getItems().length, 5 );
+}, 'next request must notice when itemscope changes');
+test(function () {
+ assert_equals( document.getItems('http://example.com/').length, 0, 'http://example.com/' );
+ assert_equals( document.getItems('example').length, 0, 'example' );
+ assert_equals( document.getItems('http://example.com/foo').length, 2, 'http://example.com/foo' );
+ assert_equals( document.getItems('http://example.com/bar').length, 4, 'http://example.com/bar' );
+ assert_equals( document.getItems('data:text/plain,').length, 2, 'data:text/plain,' );
+}, 'document.getItems must locate the right number of items for each itemtype');
+test(function () {
+ assert_equals( document.getItems('http://example.com/Foo').length, 0, 'http://example.com/Foo' );
+ assert_equals( document.getItems('HTTP://example.com/foo').length, 0, 'HTTP://example.com/foo' );
+}, 'document.getItems must be case sensitive');
+test(function () {
+ var nlist = document.getItems('http://example.com/foo');
+ var foo = makeEl('div',{itemscope:'itemscope',itemtype:'http://example.com/foo'});
+ document.body.appendChild(foo);
+ var templength = nlist.length;
+ document.body.removeChild(foo);
+ assert_equals( templength, 3 );
+ assert_equals( nlist.length, 2 );
+}, 'document.getItems must return a live NodeList when using URLs');
+test(function () {
+ var nlist = document.getItems('http://example.com/foo');
+ document.getElementById('one').removeAttribute('itemtype');
+ var templength = nlist.length;
+ document.getElementById('one').setAttribute('itemtype','http://example.com/bar data:text/plain, http://example.com/foo');
+ assert_equals( templength, 1 );
+ assert_equals( nlist.length, 2 );
+}, 'live NodeList must notice when itemtype changes');
+test(function () {
+ document.getElementById('one').removeAttribute('itemtype');
+ var templength = document.getItems('http://example.com/foo').length;
+ document.getElementById('one').setAttribute('itemtype','http://example.com/bar data:text/plain, http://example.com/foo');
+ assert_equals( templength, 1 );
+ assert_equals( document.getItems('http://example.com/foo').length, 2 );
+}, 'next request must notice when itemtype changes');
+test(function () {
+ assert_equals( document.getItems('http://example.com/foo data:text/plain,').length, 1, 'basic spaces' );
+ assert_equals( document.getItems(' http://example.com/foo data:text/plain, ').length, 1, 'extraneous spaces' );
+}, 'document.getItems must locate items when parameters are separated by spaces');
+test(function () {
+ assert_equals( document.getItems('http://example.com/foo data:text/plain, http://example.com/foo').length, 1 );
+}, 'document.getItems must ignore duplicated tokens');
+test(function () {
+ var testitems = document.getItems('http://example.com/bar');
+ assert_equals( testitems[0].id, 'one' );
+ assert_equals( testitems[1].id, 'two' );
+ assert_equals( testitems[2].id, 'three' );
+ assert_equals( testitems[3].id, 'four' );
+}, 'document.getItems NodeList must be in source tree order');
+test(function () {
+ assert_true( document.getItems('http://example.com/abc') != document.getItems('http://example.com/def'), 'different tokens' );
+ assert_true( document.getItems() != document.getItems(' '), 'no tokens' );
+}, 'document.getItems must not return the same NodeList for different parameters');
+test(function () {
+ assert_equals( document.getItems('').length, 5, 'empty string' );
+ assert_equals( document.getItems(' ').length, 5, 'string with spaces' );
+}, 'document.getItems must treat no tokens as no parameter');
+//removed due to disputed Web compatibility of casting null with DOM methods
+/*
+test(function () {
+ assert_equals( document.getItems(null).length, 0, 'null' );
+ assert_equals( document.getItems(window.undefined).length, 0, 'undefined' );
+}, 'document.getItems must cast null and undefined to strings');
+*/
+test(function () {
+ var foo = makeEl('div',{itemtype:'http://example.com/foo'});
+ document.body.appendChild(foo);
+ var templength = document.getItems('http://example.com/foo').length;
+ document.body.removeChild(foo);
+ assert_equals( templength, 2 );
+}, 'document.getItems must not find items with itemtype but not itemscope');
+test(function () {
+ var foo = makeEl('div',{itemscope:'itemscope',itemtype:'baz'}),
+ bar = makeEl('div',{itemscope:'itemscope',itemtype:location.href.replace(/\/[^\/]*$/,'/baz')});
+ document.body.appendChild(foo);
+ document.body.appendChild(bar);
+ var unrezlength = document.getItems('baz').length;
+ var rezlength = document.getItems(location.href.replace(/\/[^\/]*$/,'/baz')).length;
+ document.body.removeChild(foo);
+ document.body.removeChild(bar);
+ assert_equals( unrezlength, 1, 'unresolved URL' );
+ assert_equals( rezlength, 1, 'resolved URL' );
+}, 'document.getItems and itemtype must not resolve URLs');
+test(function () {
+ document.getElementById('one').setAttribute('itemprop','test');
+ document.getElementById('four').setAttribute('itemprop','test');
+ var templength = document.getItems().length;
+ document.getElementById('one').removeAttribute('itemprop');
+ document.getElementById('four').removeAttribute('itemprop');
+ assert_equals( templength, 3 );
+}, 'document.getItems must not see items that have the itemprop attribute set');
+
+/* itemScope property tests */
+test(function () {
+ assert_true(makeEl('div',{itemscope:'itemscope'}).itemScope);
+ assert_false(makeEl('div',{}).itemScope);
+}, 'the itemscope attribute must be reflected by the .itemScope property');
+test(function () {
+ assert_equals( typeof makeEl('div',{itemscope:'itemscope'}).itemScope, 'boolean', 'attribute exists' );
+ assert_equals( typeof makeEl('div',{}).itemScope, 'boolean', 'attribute does not exist' );
+}, 'the itemScope property must be boolean');
+test(function () {
+ var testEl = makeEl('div',{});
+ testEl.itemScope = true;
+ assert_true(testEl.itemScope,'writing true');
+ testEl.itemScope = false;
+ assert_false(testEl.itemScope,'writing false');
+}, 'the itemScope property must be read/write');
+test(function () {
+ var testEl = makeEl('div',{});
+ testEl.itemScope = true;
+ assert_true(testEl.hasAttribute('itemscope'),'writing true');
+ testEl.itemScope = false;
+ assert_false(testEl.hasAttribute('itemscope'),'writing false');
+}, 'writing to the itemScope property must toggle existence of the itemscope content attribute');
+test(function () {
+ var testEl = makeEl('div',{});
+ document.body.appendChild(testEl);
+ var numAppend = document.getItems().length;
+ testEl.itemScope = true;
+ var numTrue = document.getItems().length;
+ testEl.itemScope = false;
+ var numFalse = document.getItems().length;
+ document.body.removeChild(testEl);
+ assert_equals(numAppend,5,'after appending the new item');
+ assert_equals(numTrue,6,'after setting the property to true');
+ assert_equals(numFalse,5,'after setting the property to false');
+}, 'writing to the itemScope property must affect whether the element is returned by getItems');
+test(function () {
+ var testEl = makeEl('div',{}), nlist = document.getItems();
+ document.body.appendChild(testEl);
+ var numAppend = nlist.length;
+ testEl.itemScope = true;
+ var numTrue = nlist.length;
+ testEl.itemScope = false;
+ var numFalse = nlist.length;
+ document.body.removeChild(testEl);
+ assert_equals(numAppend,5,'after appending the new item');
+ assert_equals(numTrue,6,'after setting the property to true');
+ assert_equals(numFalse,5,'after setting the property to false');
+}, 'writing to the itemScope property must affect membership of live NodeLists');
+
+/* itemType property tests (properties collection tests are done later) */
+test(function () {
+ assert_equals(makeEl('div',{}).itemType.toString(),'','no attribute');
+ assert_equals(makeEl('div',{itemtype:' foo bar '}).itemType.toString(),' foo bar ','with simple tokens');
+ var testEl = makeEl('div',{itemtype:'foo'});
+ testEl.removeAttribute('itemtype');
+ assert_equals(testEl.itemType.toString(),'','removed attribute');
+}, 'the itemType attribute must be reflected by the .itemRef property');
+test(function () {
+ assert_equals( typeof makeEl('div',{}).itemType, 'object' );
+}, 'the itemType property must be an object');
+test(function () {
+ assert_true( makeEl('div',{}).itemType instanceof DOMTokenList, 'instanceof test' );
+ DOMTokenList.prototype.customProperty = true;
+ assert_true( makeEl('div',{}).itemType.customProperty, 'inheritance test' );
+}, 'the itemType property must implement DOMTokenList');
+test(function () {
+ var testEl = makeEl('div',{});
+ assert_equals( testEl.itemType, testEl.itemType );
+}, 'the itemType property must always reference the same object');
+test(function () {
+ assert_equals( makeEl('div',{itemtype:'test test'}).itemType.length, 2, 'duplicates in initial string should be preserved' );
+ assert_equals( makeEl('div',{itemtype:'test test'}).itemType.item(0), 'test' );
+ assert_true( makeEl('div',{itemtype:'test test'}).itemType.contains('test') );
+}, 'itemType must be correct for an element that has itemtype tokens');
+test(function () {
+ assert_equals( makeEl('div',{itemtype:' '}).itemType.length, 0 );
+}, 'itemType.length must be 0 for an element that has no tokens');
+test(function () {
+ assert_false( makeEl('div',{itemtype:' '}).itemType.contains('foo') );
+}, 'itemType must not contain an undefined class');
+test(function () {
+ assert_equals( makeEl('div',{itemtype:' '}).itemType.item(0), null );
+}, 'itemType.item() must return null for out-of-range index');
+test(function () {
+ assert_equals( makeEl('div',{itemtype:' '}).itemType.item(-1), null );
+}, 'itemType.item() must return null for negative index');
+test(function () {
+ /* the normative part of the spec states that:
+ "unless the length is zero, in which case there are no supported property indices"
+ ...
+ "The term[...] supported property indices [is] used as defined in the WebIDL specification."
+ WebIDL creates actual OwnProperties and then [] just acts as a normal property lookup */
+ assert_equals( makeEl('div',{itemtype:' '}).itemType[0], window.undefined );
+}, 'itemType[index] must be undefined for out-of-range index');
+test(function () {
+ assert_equals( makeEl('div',{itemtype:' '}).itemType[-1], window.undefined );
+}, 'itemType[index] must be undefined for negative index');
+test(function () {
+ assert_equals( makeEl('div',{itemType:' '}).itemType.toString(), ' ' );
+}, 'empty itemType should stringify to contain the attribute\'s whitespace');
+test(function () {
+ assert_throws( 'SYNTAX_ERR', function () { makeEl('div',{itemtype:' '}).itemType.contains(''); } );
+}, 'itemType.contains(empty_string) must throw a SYNTAX_ERR');
+test(function () {
+ assert_throws( 'SYNTAX_ERR', function () { makeEl('div',{itemtype:' '}).itemType.add(''); } );
+}, 'itemType.add(empty_string) must throw a SYNTAX_ERR');
+test(function () {
+ assert_throws( 'SYNTAX_ERR', function () { makeEl('div',{itemtype:' '}).itemType.remove(''); } );
+}, 'itemType.remove(empty_string) must throw a SYNTAX_ERR');
+test(function () {
+ assert_throws( 'SYNTAX_ERR', function () { makeEl('div',{itemtype:' '}).itemType.toggle(''); } );
+}, 'itemType.toggle(empty_string) must throw a SYNTAX_ERR');
+test(function () {
+ assert_throws( 'INVALID_CHARACTER_ERR', function () { makeEl('div',{itemtype:' '}).itemType.contains('a b'); } );
+}, 'itemType.contains(string_with_spaces) must throw an INVALID_CHARACTER_ERR');
+test(function () {
+ assert_throws( 'INVALID_CHARACTER_ERR', function () { makeEl('div',{itemtype:' '}).itemType.add('a b'); } );
+}, 'itemType.add(string_with_spaces) must throw an INVALID_CHARACTER_ERR');
+test(function () {
+ assert_throws( 'INVALID_CHARACTER_ERR', function () { makeEl('div',{itemtype:' '}).itemType.remove('a b'); } );
+}, 'itemType.remove(string_with_spaces) must throw an INVALID_CHARACTER_ERR');
+test(function () {
+ assert_throws( 'INVALID_CHARACTER_ERR', function () { makeEl('div',{itemtype:' '}).itemType.toggle('a b'); } );
+}, 'itemType.toggle(string_with_spaces) must throw an INVALID_CHARACTER_ERR');
+test(function () {
+ var testEl = makeEl('div',{itemtype:'foo'});
+ assert_true( testEl.itemType.contains('foo'), 'before change' );
+ testEl.setAttribute('itemtype','bar');
+ assert_true( testEl.itemType.contains('bar'), 'after change' );
+ assert_false( testEl.itemType.contains('foo'), 'after change' );
+}, 'itemType.contains must update when the underlying attribute is changed');
+test(function () {
+ assert_false( makeEl('div',{itemtype:'foo'}).itemType.contains('FOO') );
+}, 'itemType.contains must be case sensitive');
+test(function () {
+ assert_false( makeEl('div',{itemtype:'foo'}).itemType.contains('foo.') );
+ assert_false( makeEl('div',{itemtype:'foo'}).itemType.contains('foo)') );
+ assert_false( makeEl('div',{itemtype:'foo'}).itemType.contains('foo\'') );
+ assert_false( makeEl('div',{itemtype:'foo'}).itemType.contains('foo$') );
+ assert_false( makeEl('div',{itemtype:'foo'}).itemType.contains('foo~') );
+ assert_false( makeEl('div',{itemtype:'foo'}).itemType.contains('foo?') );
+ assert_false( makeEl('div',{itemtype:'foo'}).itemType.contains('foo\\') );
+}, 'itemType.contains must not match when punctuation characters are added');
+test(function () {
+ var elem = makeEl('div',{itemtype:'foo'});
+ elem.itemType.add('FOO');
+ assert_true( elem.itemType.contains('foo') );
+}, 'itemType.add must not remove existing tokens');
+test(function () {
+ assert_true( makeEl('div',{itemtype:'foo FOO'}).itemType.contains('FOO') );
+}, 'itemType.contains case sensitivity must match a case-specific string');
+test(function () {
+ assert_equals( makeEl('div',{itemtype:'foo FOO'}).itemType.length, 2 );
+}, 'itemType.length must correctly reflect the number of tokens');
+test(function () {
+ assert_equals( makeEl('div',{itemtype:'foo FOO'}).itemType.item(0), 'foo' );
+}, 'itemType.item(0) must return the first token');
+test(function () {
+ var elem = makeEl('div',{itemtype:'foo'});
+ elem.itemType.add('FOO');
+ assert_equals( elem.itemType.item(1), 'FOO' );
+}, 'itemType.item must return case-sensitive strings and preserve token order');
+test(function () {
+ assert_equals( makeEl('div',{itemtype:'foo FOO'}).itemType[0], 'foo' );
+}, 'itemType[0] must return the first token');
+test(function () {
+ assert_equals( makeEl('div',{itemtype:'foo FOO'}).itemType[1], 'FOO' );
+}, 'itemType[index] must return case-sensitive strings and preserve token order');
+test(function () {
+ /* the normative part of the spec states that:
+ "unless the length is zero, in which case there are no supported property indices"
+ ...
+ "The term[...] supported property indices [is] used as defined in the WebIDL specification."
+ WebIDL creates actual OwnProperties and then [] just acts as a normal property lookup */
+ assert_equals( makeEl('div',{itemtype:'foo FOO'}).itemType[2], window.undefined );
+}, 'itemType[index] must still be undefined for out-of-range index when earlier indexes exist');
+test(function () {
+ var elem = makeEl('div',{});
+ elem.itemType.add('foo');
+ elem.itemType.add('FOO');
+ assert_equals( elem.getAttribute('itemtype'), 'foo FOO' );
+}, 'itemtype attribute must update correctly when items have been added through itemType');
+test(function () {
+ var elem = makeEl('div',{});
+ elem.itemType.add('foo');
+ elem.itemType.add('FOO');
+ assert_equals( elem.itemType + '', 'foo FOO' );
+}, 'itemType must stringify correctly when items have been added');
+test(function () {
+ var elem = makeEl('div',{itemtype:'foo FOO'});
+ elem.itemType.add('foo');
+ assert_equals( elem.itemType.length, 2 );
+ assert_equals( elem.itemType + '', 'foo FOO' );
+}, 'itemType.add must not make any changes if an existing token is added');
+test(function () {
+ var elem = makeEl('div',{itemtype:'foo FOO'});
+ elem.itemType.remove('bar');
+ assert_equals( elem.itemType.length, 2 );
+ assert_equals( elem.itemType + '', 'foo FOO' );
+}, 'itemType.remove must not make any changes if a non-existing token is removed');
+test(function () {
+ var elem = makeEl('div',{itemtype:'foo FOO'});
+ elem.itemType.remove('foo');
+ assert_equals( elem.itemType.length, 1 );
+ assert_equals( elem.itemType.toString(), 'FOO' );
+ assert_false( elem.itemType.contains('foo') );
+ assert_true( elem.itemType.contains('FOO') );
+}, 'itemType.remove must remove existing tokens');
+test(function () {
+ var elem = makeEl('div',{itemtype:'test test'});
+ elem.itemType.remove('test');
+ assert_equals( elem.itemType.length, 0 );
+ assert_false( elem.itemType.contains('test') );
+}, 'itemType.remove must remove duplicated tokens');
+test(function () {
+ var elem = makeEl('div',{itemtype:'token1 token2 token3'});
+ elem.itemType.remove('token2');
+ assert_equals( elem.itemType.toString(), 'token1 token3' );
+}, 'itemType.remove must collapse whitespace around removed tokens');
+test(function () {
+ var elem = makeEl('div',{itemtype:' token1 token2 '});
+ elem.itemType.remove('token2');
+ assert_equals( elem.itemType.toString(), 'token1' );
+}, 'itemType.remove must remove all useless whitespace');
+test(function () {
+ var elem = makeEl('div',{itemtype:' token1 token2 token3 '});
+ elem.itemType.remove('token2');
+ assert_equals( elem.itemType.toString(), 'token1 token3' );
+}, 'itemType.remove must collapse multiple whitespace around removed tokens');
+test(function () {
+ var elem = makeEl('div',{itemtype:' token1 token2 token1 '});
+ elem.itemType.remove('token2');
+ assert_equals( elem.itemType.toString(), 'token1' );
+}, 'itemType.remove must remove duplicates when removing tokens');
+test(function () {
+ var elem = makeEl('div',{itemtype:' token1 token2 token3 '});
+ elem.itemType.remove('token1', 'token3');
+ assert_equals( elem.itemType.toString(), 'token2' );
+}, 'itemType.remove must collapse whitespace when removing multiple tokens');
+test(function () {
+ var elem = makeEl('div',{itemtype:' token1 token2 '});
+ elem.itemType.add('token1');
+ assert_equals( elem.itemType.toString(), 'token1 token2' );
+}, 'itemType.add must remove unused whitespace when the token already exists');
+test(function () {
+ var elem = makeEl('div',{itemtype:'FOO'});
+ assert_true(elem.itemType.toggle('foo'));
+ assert_equals( elem.itemType.length, 2 );
+ assert_true( elem.itemType.contains('foo') );
+ assert_true( elem.itemType.contains('FOO') );
+}, 'itemType.toggle must toggle tokens case-sensitively when adding');
+test(function () {
+ var elem = makeEl('div',{itemtype:'foo FOO'});
+ assert_false(elem.itemType.toggle('foo'));
+ assert_false(elem.itemType.toggle('FOO'));
+ assert_false( elem.itemType.contains('foo') );
+ assert_false( elem.itemType.contains('FOO') );
+}, 'itemType.toggle must be able to remove tokens case-sensitively');
+test(function () {
+ var elem = makeEl('div',{itemtype:'foo FOO'});
+ elem.itemType.toggle('foo');
+ elem.itemType.toggle('FOO');
+ assert_equals( elem.getAttribute('itemtype'), '' );
+}, 'itemtype attribute must be empty when all classes have been removed');
+test(function () {
+ var elem = makeEl('div',{itemtype:'foo FOO'});
+ elem.itemType.toggle('foo');
+ elem.itemType.toggle('FOO');
+ assert_equals( elem.itemType.toString(), '' );
+}, 'itemType must stringify to an empty string when all classes have been removed');
+test(function () {
+ var elem = makeEl('div',{itemtype:'foo FOO'});
+ elem.itemType.toggle('foo');
+ elem.itemType.toggle('FOO');
+ assert_equals( elem.itemType.item(0), null );
+}, 'itemType.item(0) must return null when all classes have been removed');
+test(function () {
+ /* the normative part of the spec states that:
+ "unless the length is zero, in which case there are no supported property indices"
+ ...
+ "The term[...] supported property indices [is] used as defined in the WebIDL specification."
+ WebIDL creates actual OwnProperties and then [] just acts as a normal property lookup */
+ var elem = makeEl('div',{itemtype:'foo FOO'});
+ elem.itemType.toggle('foo');
+ elem.itemType.toggle('FOO');
+ assert_equals( elem.itemType[0], window.undefined );
+}, 'itemType[0] must be undefined when all classes have been removed');
+//if the last character of DOMTokenSting underlying character is not a space character, append U+0020", where "space character" is from " \t\r\n\f"
+test(function () {
+ var elem = makeEl('div',{itemtype:'a '});
+ elem.itemType.add('b');
+ assert_equals(elem.itemType.toString(),'a b');
+}, 'itemType.add should treat " " as a space');
+test(function () {
+ var elem = makeEl('div',{itemtype:'a\t'});
+ elem.itemType.add('b');
+ assert_equals(elem.itemType.toString(),'a b');
+}, 'itemType.add should normalize \\t as a space');
+test(function () {
+ var elem = makeEl('div',{itemtype:'a\r'});
+ elem.itemType.add('b');
+ assert_equals(elem.itemType.toString(),'a b');
+}, 'itemType.add should normalize \\r as a space');
+test(function () {
+ var elem = makeEl('div',{itemtype:'a\n'});
+ elem.itemType.add('b');
+ assert_equals(elem.itemType.toString(),'a b');
+}, 'itemType.add should normalize \\n as a space');
+test(function () {
+ var elem = makeEl('div',{itemtype:'a\f'});
+ elem.itemType.add('b');
+ assert_equals(elem.itemType.toString(),'a b');
+}, 'itemType.add should normalize \\f as a space');
+test(function () {
+ var elem = makeEl('div',{itemtype:'foo'});
+ elem.itemType.remove('foo');
+ elem.removeAttribute('itemtype');
+ assert_true( elem.itemType.toggle('foo') );
+}, 'itemType.toggle must work after removing the itemtype attribute');
+test(function () {
+ //WebIDL and ECMAScript 5 - a readonly property has a getter but not a setter
+ //ES5 makes [[Put]] fail but not throw
+ var failed = false;
+ var elem = makeEl('div',{itemtype:'token1'});
+ try {
+ elem.itemType.length = 0;
+ } catch(e) {
+ failed = e;
+ }
+ assert_equals(elem.itemType.length,1);
+ assert_false(failed,'an error was thrown');
+}, 'itemType.length must be read-only');
+test(function () {
+ var failed = false, elem = makeEl('div',{itemtype:'test'}), realList = elem.itemType;
+ try {
+ elem.itemType = 'dummy';
+ } catch(e) {
+ failed = e;
+ }
+ assert_equals(elem.itemType,realList);
+ assert_equals(elem.itemType.toString(),'dummy','attempting to write should modify the underlying string');
+ assert_false(failed,'an error was thrown');
+}, 'itemType must be read-only');
+
+/* itemProp property tests (properties collection tests are done later) */
+test(function () {
+ assert_equals(makeEl('div',{}).itemProp.toString(),'','no attribute');
+ assert_equals(makeEl('div',{itemprop:' ' + urls.www1 + 'foo#bar test '}).itemProp.toString(),' ' + urls.www1 + 'foo#bar test ','with URL and simple tokens');
+ var testEl = makeEl('div',{itemprop:urls.www1 + 'foo#bar'});
+ testEl.removeAttribute('itemprop');
+ assert_equals(testEl.itemProp.toString(),'','removed attribute');
+}, 'the itemprop attribute must be reflected by the .itemProp property');
+test(function () {
+ assert_equals( typeof makeEl('div',{}).itemProp, 'object' );
+}, 'the itemProp property must be an object');
+test(function () {
+ assert_true( makeEl('div',{}).itemProp instanceof DOMTokenList, 'instanceof test' );
+ DOMTokenList.prototype.customProperty = true;
+ assert_true( makeEl('div',{}).itemProp.customProperty, 'inheritance test' );
+}, 'the itemProp property must implement DOMTokenList');
+test(function () {
+ var testEl = makeEl('div',{});
+ assert_equals( testEl.itemProp, testEl.itemProp );
+}, 'the itemProp property must always reference the same object');
+test(function () {
+ assert_equals( makeEl('div',{itemprop:'test test'}).itemProp.length, 2, 'duplicates in initial string should be preserved' );
+ assert_equals( makeEl('div',{itemprop:'test test'}).itemProp.item(0), 'test' );
+ assert_true( makeEl('div',{itemprop:'test test'}).itemProp.contains('test') );
+}, 'itemProp must be correct for an element that has itemprop tokens');
+test(function () {
+ assert_equals( makeEl('div',{itemprop:' '}).itemProp.length, 0 );
+}, 'itemProp.length must be 0 for an element that has no tokens');
+test(function () {
+ assert_false( makeEl('div',{itemprop:' '}).itemProp.contains('foo') );
+}, 'itemProp must not contain an undefined class');
+test(function () {
+ assert_equals( makeEl('div',{itemprop:' '}).itemProp.item(0), null );
+}, 'itemProp.item() must return null for out-of-range index');
+test(function () {
+ assert_equals( makeEl('div',{itemprop:' '}).itemProp.item(-1), null );
+}, 'itemProp.item() must return null for negative index');
+test(function () {
+ /* the normative part of the spec states that:
+ "unless the length is zero, in which case there are no supported property indices"
+ ...
+ "The term[...] supported property indices [is] used as defined in the WebIDL specification."
+ WebIDL creates actual OwnProperties and then [] just acts as a normal property lookup */
+ assert_equals( makeEl('div',{itemprop:' '}).itemProp[0], window.undefined );
+}, 'itemProp[index] must be undefined for out-of-range index');
+test(function () {
+ assert_equals( makeEl('div',{itemprop:' '}).itemProp[-1], window.undefined );
+}, 'itemProp[index] must be undefined for negative index');
+test(function () {
+ assert_equals( makeEl('div',{itemprop:' '}).itemProp.toString(), ' ' );
+}, 'empty itemProp should stringify to contain the attribute\'s whitespace');
+test(function () {
+ assert_throws( 'SYNTAX_ERR', function () { makeEl('div',{itemprop:' '}).itemProp.contains(''); } );
+}, 'itemProp.contains(empty_string) must throw a SYNTAX_ERR');
+test(function () {
+ assert_throws( 'SYNTAX_ERR', function () { makeEl('div',{itemprop:' '}).itemProp.add(''); } );
+}, 'itemProp.add(empty_string) must throw a SYNTAX_ERR');
+test(function () {
+ assert_throws( 'SYNTAX_ERR', function () { makeEl('div',{itemprop:' '}).itemProp.remove(''); } );
+}, 'itemProp.remove(empty_string) must throw a SYNTAX_ERR');
+test(function () {
+ assert_throws( 'SYNTAX_ERR', function () { makeEl('div',{itemprop:' '}).itemProp.toggle(''); } );
+}, 'itemProp.toggle(empty_string) must throw a SYNTAX_ERR');
+test(function () {
+ assert_throws( 'INVALID_CHARACTER_ERR', function () { makeEl('div',{itemprop:' '}).itemProp.contains('a b'); } );
+}, '.contains(string_with_spaces) must throw an INVALID_CHARACTER_ERR');
+test(function () {
+ assert_throws( 'INVALID_CHARACTER_ERR', function () { makeEl('div',{itemprop:' '}).itemProp.add('a b'); } );
+}, 'itemProp.add(string_with_spaces) must throw an INVALID_CHARACTER_ERR');
+test(function () {
+ assert_throws( 'INVALID_CHARACTER_ERR', function () { makeEl('div',{itemprop:' '}).itemProp.remove('a b'); } );
+}, 'itemProp.remove(string_with_spaces) must throw an INVALID_CHARACTER_ERR');
+test(function () {
+ assert_throws( 'INVALID_CHARACTER_ERR', function () { makeEl('div',{itemprop:' '}).itemProp.toggle('a b'); } );
+}, 'itemProp.toggle(string_with_spaces) must throw an INVALID_CHARACTER_ERR');
+test(function () {
+ var testEl = makeEl('div',{itemprop:'foo'});
+ assert_true( testEl.itemProp.contains('foo'), 'before change' );
+ testEl.setAttribute('itemprop','bar');
+ assert_true( testEl.itemProp.contains('bar'), 'after change' );
+ assert_false( testEl.itemProp.contains('foo'), 'after change' );
+}, 'itemProp.contains must update when the underlying attribute is changed');
+test(function () {
+ assert_false( makeEl('div',{itemprop:'foo'}).itemProp.contains('FOO') );
+}, 'itemProp.contains must be case sensitive');
+test(function () {
+ assert_false( makeEl('div',{itemprop:'foo'}).itemProp.contains('foo.') );
+ assert_false( makeEl('div',{itemprop:'foo'}).itemProp.contains('foo)') );
+ assert_false( makeEl('div',{itemprop:'foo'}).itemProp.contains('foo\'') );
+ assert_false( makeEl('div',{itemprop:'foo'}).itemProp.contains('foo$') );
+ assert_false( makeEl('div',{itemprop:'foo'}).itemProp.contains('foo~') );
+ assert_false( makeEl('div',{itemprop:'foo'}).itemProp.contains('foo?') );
+ assert_false( makeEl('div',{itemprop:'foo'}).itemProp.contains('foo\\') );
+}, 'itemProp.contains must not match when punctuation characters are added');
+test(function () {
+ var elem = makeEl('div',{itemprop:'foo'});
+ elem.itemProp.add('FOO');
+ assert_true( elem.itemProp.contains('foo') );
+}, 'itemProp.add must not remove existing tokens');
+test(function () {
+ assert_true( makeEl('div',{itemprop:'foo FOO'}).itemProp.contains('FOO') );
+}, 'itemProp.contains case sensitivity must match a case-specific string');
+test(function () {
+ assert_equals( makeEl('div',{itemprop:'foo FOO'}).itemProp.length, 2 );
+}, 'itemProp.length must correctly reflect the number of tokens');
+test(function () {
+ assert_equals( makeEl('div',{itemprop:'foo FOO'}).itemProp.item(0), 'foo' );
+}, 'itemProp.item(0) must return the first token');
+test(function () {
+ var elem = makeEl('div',{itemprop:'foo'});
+ elem.itemProp.add('FOO');
+ assert_equals( elem.itemProp.item(1), 'FOO' );
+}, 'itemProp.item must return case-sensitive strings and preserve token order');
+test(function () {
+ assert_equals( makeEl('div',{itemprop:'foo FOO'}).itemProp[0], 'foo' );
+}, 'itemProp[0] must return the first token');
+test(function () {
+ assert_equals( makeEl('div',{itemprop:'foo FOO'}).itemProp[1], 'FOO' );
+}, 'itemProp[index] must return case-sensitive strings and preserve token order');
+test(function () {
+ /* the normative part of the spec states that:
+ "unless the length is zero, in which case there are no supported property indices"
+ ...
+ "The term[...] supported property indices [is] used as defined in the WebIDL specification."
+ WebIDL creates actual OwnProperties and then [] just acts as a normal property lookup */
+ assert_equals( makeEl('div',{itemprop:'foo FOO'}).itemProp[2], window.undefined );
+}, 'itemProp[index] must still be undefined for out-of-range index when earlier indexes exist');
+test(function () {
+ var elem = makeEl('div',{});
+ elem.itemProp.add('foo');
+ elem.itemProp.add('FOO');
+ assert_equals( elem.getAttribute('itemprop'), 'foo FOO' );
+}, 'itemprop attribute must update correctly when items have been added through itemProp');
+test(function () {
+ var elem = makeEl('div',{});
+ elem.itemProp.add('foo');
+ elem.itemProp.add('FOO');
+ assert_equals( elem.itemProp + '', 'foo FOO' );
+}, 'itemProp must stringify correctly when items have been added');
+test(function () {
+ var elem = makeEl('div',{itemprop:'foo FOO'});
+ elem.itemProp.add('foo');
+ assert_equals( elem.itemProp.length, 2 );
+ assert_equals( elem.itemProp + '', 'foo FOO' );
+}, 'itemProp.add must not make any changes if an existing token is added');
+test(function () {
+ var elem = makeEl('div',{itemprop:'foo FOO'});
+ elem.itemProp.remove('bar');
+ assert_equals( elem.itemProp.length, 2 );
+ assert_equals( elem.itemProp + '', 'foo FOO' );
+}, 'itemProp.remove must not make any changes if a non-existing token is removed');
+test(function () {
+ var elem = makeEl('div',{itemprop:'foo FOO'});
+ elem.itemProp.remove('foo');
+ assert_equals( elem.itemProp.length, 1 );
+ assert_equals( elem.itemProp.toString(), 'FOO' );
+ assert_false( elem.itemProp.contains('foo') );
+ assert_true( elem.itemProp.contains('FOO') );
+}, 'itemProp.remove must remove existing tokens');
+test(function () {
+ var elem = makeEl('div',{itemprop:'test test'});
+ elem.itemProp.remove('test');
+ assert_equals( elem.itemProp.length, 0 );
+ assert_false( elem.itemProp.contains('test') );
+}, 'itemProp.remove must remove duplicated tokens');
+test(function () {
+ var elem = makeEl('div',{itemprop:'token1 token2 token3'});
+ elem.itemProp.remove('token2');
+ assert_equals( elem.itemProp.toString(), 'token1 token3' );
+}, 'itemProp.remove must collapse whitespace around removed tokens');
+test(function () {
+ var elem = makeEl('div',{itemprop:' token1 token2 token3 '});
+ elem.itemProp.remove('token2');
+ assert_equals( elem.itemProp.toString(), 'token1 token3' );
+}, 'itemProp.remove must remove all useless whitespace');
+test(function () {
+ var elem = makeEl('div',{itemprop:' token1 token2 token3 '});
+ elem.itemProp.remove('token1', 'token3');
+ assert_equals( elem.itemProp.toString(), 'token2' );
+}, 'itemProp.remove must remove useless whitespace when removing multiple tokens');
+test(function () {
+ var elem = makeEl('div',{itemprop:' token1 token1 '});
+ elem.itemProp.add('token1');
+ assert_equals( elem.itemProp.toString(), 'token1' );
+}, 'itemProp.add must remove useless whitespace and duplicates when the token already exists');
+test(function () {
+ var elem = makeEl('div',{itemprop:'FOO'});
+ assert_true(elem.itemProp.toggle('foo'));
+ assert_equals( elem.itemProp.length, 2 );
+ assert_true( elem.itemProp.contains('foo') );
+ assert_true( elem.itemProp.contains('FOO') );
+}, 'itemProp.toggle must toggle tokens case-sensitively when adding');
+test(function () {
+ var elem = makeEl('div',{itemprop:'foo FOO'});
+ assert_false(elem.itemProp.toggle('foo'));
+ assert_false(elem.itemProp.toggle('FOO'));
+ assert_false( elem.itemProp.contains('foo') );
+ assert_false( elem.itemProp.contains('FOO') );
+}, 'itemProp.toggle must be able to remove tokens case-sensitively');
+test(function () {
+ var elem = makeEl('div',{itemprop:'foo FOO'});
+ elem.itemProp.toggle('foo');
+ elem.itemProp.toggle('FOO');
+ assert_equals( elem.getAttribute('itemprop'), '' );
+}, 'itemprop attribute must be empty when all classes have been removed');
+test(function () {
+ var elem = makeEl('div',{itemprop:'foo FOO'});
+ elem.itemProp.toggle('foo');
+ elem.itemProp.toggle('FOO');
+ assert_equals( elem.itemProp.toString(), '' );
+}, 'itemProp must stringify to an empty string when all classes have been removed');
+test(function () {
+ var elem = makeEl('div',{itemprop:'foo FOO'});
+ elem.itemProp.toggle('foo');
+ elem.itemProp.toggle('FOO');
+ assert_equals( elem.itemProp.item(0), null );
+}, 'itemProp.item(0) must return null when all classes have been removed');
+test(function () {
+ /* the normative part of the spec states that:
+ "unless the length is zero, in which case there are no supported property indices"
+ ...
+ "The term[...] supported property indices [is] used as defined in the WebIDL specification."
+ WebIDL creates actual OwnProperties and then [] just acts as a normal property lookup */
+ var elem = makeEl('div',{itemprop:'foo FOO'});
+ elem.itemProp.toggle('foo');
+ elem.itemProp.toggle('FOO');
+ assert_equals( elem.itemProp[0], window.undefined );
+}, 'itemProp[0] must be undefined when all classes have been removed');
+//if the last character of DOMTokenSting underlying character is not a space character, append U+0020", where "space character" is from " \t\r\n\f"
+test(function () {
+ var elem = makeEl('div',{itemprop:'a '});
+ elem.itemProp.add('b');
+ assert_equals(elem.itemProp.toString(),'a b');
+}, 'itemProp.add should treat " " as a space');
+test(function () {
+ var elem = makeEl('div',{itemprop:'a\t'});
+ elem.itemProp.add('b');
+ assert_equals(elem.itemProp.toString(),'a b');
+}, 'itemProp.add should normalize \\t as a space');
+test(function () {
+ var elem = makeEl('div',{itemprop:'a\r'});
+ elem.itemProp.add('b');
+ assert_equals(elem.itemProp.toString(),'a b');
+}, 'itemProp.add should normalize \\r as a space');
+test(function () {
+ var elem = makeEl('div',{itemprop:'a\n'});
+ elem.itemProp.add('b');
+ assert_equals(elem.itemProp.toString(),'a b');
+}, 'itemProp.add should normalize \\n as a space');
+test(function () {
+ var elem = makeEl('div',{itemprop:'a\f'});
+ elem.itemProp.add('b');
+ assert_equals(elem.itemProp.toString(),'a b');
+}, 'itemProp.add should normalize \\f as a space');
+test(function () {
+ var elem = makeEl('div',{itemprop:'foo'});
+ elem.itemProp.remove('foo');
+ elem.removeAttribute('itemprop');
+ assert_true( elem.itemProp.toggle('foo') );
+}, 'itemProp.toggle must work after removing the itemprop attribute');
+test(function () {
+ //WebIDL and ECMAScript 5 - a readonly property has a getter but not a setter
+ //ES5 makes [[Put]] fail but not throw
+ var failed = false;
+ var elem = makeEl('div',{itemprop:'token1'});
+ try {
+ elem.itemProp.length = 0;
+ } catch(e) {
+ failed = e;
+ }
+ assert_equals(elem.itemProp.length,1);
+ assert_false(failed,'an error was thrown');
+}, 'itemProp.length must be read-only');
+test(function () {
+ var failed = false, elem = makeEl('div',{itemprop:'test'}), realList = elem.itemProp;
+ try {
+ elem.itemProp = 'dummy';
+ } catch(e) {
+ failed = e;
+ }
+ assert_equals(elem.itemProp,realList);
+ assert_equals(elem.itemProp.toString(),'dummy','attempting to write should modify the underlying string');
+ assert_false(failed,'an error was thrown');
+}, 'itemProp must be read-only');
+
+/* itemId property tests */
+test(function () {
+ assert_equals( makeEl('div',{itemid:urls.www1 + 'foo'}).itemId, urls.www1 + 'foo' );
+ assert_equals( makeEl('div',{itemid:urls.www1 + 'FOO'}).itemId, urls.www1 + 'FOO', 'case-sensitive' );
+ assert_equals( makeEl('div',{itemid:' ' + urls.www1 + 'foo '}).itemId, urls.www1 + 'foo', 'whitespace' );
+ assert_equals( makeEl('div',{itemid:'data:text/plain,'}).itemId, 'data:text/plain,' );
+ assert_equals( makeEl('div',{itemid:'madeup:onthespot'}).itemId, 'madeup:onthespot' );
+ assert_equals( makeEl('div',{}).itemId, '' );
+}, 'the itemid attribute must be reflected by the .itemId property');
+test(function () {
+ var testEl = makeEl('div',{});
+ testEl.itemId = urls.www1 + 'foo';
+ assert_equals(testEl.itemId,urls.www1 + 'foo','writing a URL');
+ testEl.itemId = '';
+ assert_equals(testEl.itemId,location.href,'writing an empty string');
+}, 'the itemId property must be read/write');
+test(function () {
+ var testEl = makeEl('div',{});
+ testEl.itemId = urls.www1 + 'foo';
+ assert_true(testEl.hasAttribute('itemid'),'writing a URL');
+ assert_equals(testEl.getAttribute('itemid'),urls.www1 + 'foo','writing a URL');
+ testEl = makeEl('div',{})
+ testEl.itemId = '';
+ assert_true(testEl.hasAttribute('itemid'),'writing an empty string');
+ assert_equals(testEl.getAttribute('itemid'),'','writing an empty string');
+}, 'writing to the itemId property must create the itemid content attribute');
+test(function () {
+ assert_equals( makeEl('div',{itemid:'foo'}).itemId, location.href.replace(/\/[^\/]*$/,'\/foo'),'foo' );
+ assert_equals( makeEl('div',{itemid:'foo bar'}).itemId, location.href.replace(/\/[^\/]*$/,'\/foo%20bar'),'foo bar' );
+ assert_equals( makeEl('div',{itemid:'foo\u0129 bar'}).itemId, location.href.replace(/\/[^\/]*$/,'\/foo%C4%A9%20bar'),'foo\u0129 bar' );
+}, 'the itemId property must see the resolved itemid URL');
+test(function () {
+ var testEl = makeEl('div',{});
+ testEl.itemId = 'foo';
+ assert_equals( testEl.itemId, location.href.replace(/\/[^\/]*$/,'\/foo') );
+}, 'the itemId property must see the resolved itemId property URL on setting');
+test(function () {
+ var testEl = makeEl('div',{});
+ testEl.itemId = 'foo';
+ assert_equals( testEl.getAttribute('itemid'), 'foo' );
+}, 'the itemid attribute must see the resolved itemId URL');
+
+/* itemRef property tests (properties collection tests are done later) */
+test(function () {
+ assert_equals(makeEl('div',{}).itemRef.toString(),'','no attribute');
+ assert_equals(makeEl('div',{itemref:' foo bar '}).itemRef.toString(),' foo bar ','with simple tokens');
+ var testEl = makeEl('div',{itemref:'foo'});
+ testEl.removeAttribute('itemref');
+ assert_equals(testEl.itemRef.toString(),'','removed attribute');
+}, 'the itemref attribute must be reflected by the .itemRef property');
+test(function () {
+ assert_equals( typeof makeEl('div',{}).itemRef, 'object' );
+}, 'the itemRef property must be an object');
+test(function () {
+ assert_true( makeEl('div',{}).itemRef instanceof DOMTokenList, 'instanceof test' );
+ DOMTokenList.prototype.customProperty = true;
+ assert_true( makeEl('div',{}).itemRef.customProperty, 'inheritance test' );
+}, 'the itemRef property must implement DOMTokenList');
+test(function () {
+ var testEl = makeEl('div',{});
+ assert_equals( testEl.itemRef, testEl.itemRef );
+}, 'the itemRef property must always reference the same object');
+test(function () {
+ assert_equals( makeEl('div',{itemref:'test test'}).itemRef.length, 2, 'duplicates in initial string should be preserved' );
+ assert_equals( makeEl('div',{itemref:'test test'}).itemRef.item(0), 'test' );
+ assert_true( makeEl('div',{itemref:'test test'}).itemRef.contains('test') );
+}, 'itemRef must be correct for an element that has itemref tokens');
+test(function () {
+ assert_equals( makeEl('div',{itemref:' '}).itemRef.length, 0 );
+}, 'itemRef.length must be 0 for an element that has no tokens');
+test(function () {
+ assert_false( makeEl('div',{itemref:' '}).itemRef.contains('foo') );
+}, 'itemRef must not contain an undefined class');
+test(function () {
+ assert_equals( makeEl('div',{itemref:' '}).itemRef.item(0), null );
+}, 'itemRef.item() must return null for out-of-range index');
+test(function () {
+ assert_equals( makeEl('div',{itemref:' '}).itemRef.item(-1), null );
+}, 'itemRef.item() must return null for negative index');
+test(function () {
+ /* the normative part of the spec states that:
+ "unless the length is zero, in which case there are no supported property indices"
+ ...
+ "The term[...] supported property indices [is] used as defined in the WebIDL specification."
+ WebIDL creates actual OwnProperties and then [] just acts as a normal property lookup */
+ assert_equals( makeEl('div',{itemref:' '}).itemRef[0], window.undefined );
+}, 'itemRef[index] must be undefined for out-of-range index');
+test(function () {
+ assert_equals( makeEl('div',{itemref:' '}).itemRef[-1], window.undefined );
+}, 'itemRef[index] must be undefined for negative index');
+test(function () {
+ assert_equals( makeEl('div',{itemref:' '}).itemRef.toString(), ' ' );
+}, 'empty itemRef should stringify to contain the attribute\'s whitespace');
+test(function () {
+ assert_throws( 'SYNTAX_ERR', function () { makeEl('div',{itemref:' '}).itemRef.contains(''); } );
+}, 'itemRef.contains(empty_string) must throw a SYNTAX_ERR');
+test(function () {
+ assert_throws( 'SYNTAX_ERR', function () { makeEl('div',{itemref:' '}).itemRef.add(''); } );
+}, 'itemRef.add(empty_string) must throw a SYNTAX_ERR');
+test(function () {
+ assert_throws( 'SYNTAX_ERR', function () { makeEl('div',{itemref:' '}).itemRef.remove(''); } );
+}, 'itemRef.remove(empty_string) must throw a SYNTAX_ERR');
+test(function () {
+ assert_throws( 'SYNTAX_ERR', function () { makeEl('div',{itemref:' '}).itemRef.toggle(''); } );
+}, 'itemRef.toggle(empty_string) must throw a SYNTAX_ERR');
+test(function () {
+ assert_throws( 'INVALID_CHARACTER_ERR', function () { makeEl('div',{itemref:' '}).itemRef.contains('a b'); } );
+}, 'itemRef.contains(string_with_spaces) must throw an INVALID_CHARACTER_ERR');
+test(function () {
+ assert_throws( 'INVALID_CHARACTER_ERR', function () { makeEl('div',{itemref:' '}).itemRef.add('a b'); } );
+}, 'itemRef.add(string_with_spaces) must throw an INVALID_CHARACTER_ERR');
+test(function () {
+ assert_throws( 'INVALID_CHARACTER_ERR', function () { makeEl('div',{itemref:' '}).itemRef.remove('a b'); } );
+}, 'itemRef.remove(string_with_spaces) must throw an INVALID_CHARACTER_ERR');
+test(function () {
+ assert_throws( 'INVALID_CHARACTER_ERR', function () { makeEl('div',{itemref:' '}).itemRef.toggle('a b'); } );
+}, 'itemRef.toggle(string_with_spaces) must throw an INVALID_CHARACTER_ERR');
+test(function () {
+ var testEl = makeEl('div',{itemref:'foo'});
+ assert_true( testEl.itemRef.contains('foo'), 'before change' );
+ testEl.setAttribute('itemref','bar');
+ assert_true( testEl.itemRef.contains('bar'), 'after change' );
+ assert_false( testEl.itemRef.contains('foo'), 'after change' );
+}, 'itemRef.contains must update when the underlying attribute is changed');
+test(function () {
+ assert_false( makeEl('div',{itemref:'foo'}).itemRef.contains('FOO') );
+}, 'itemRef.contains must be case sensitive');
+test(function () {
+ assert_false( makeEl('div',{itemref:'foo'}).itemRef.contains('foo.') );
+ assert_false( makeEl('div',{itemref:'foo'}).itemRef.contains('foo)') );
+ assert_false( makeEl('div',{itemref:'foo'}).itemRef.contains('foo\'') );
+ assert_false( makeEl('div',{itemref:'foo'}).itemRef.contains('foo$') );
+ assert_false( makeEl('div',{itemref:'foo'}).itemRef.contains('foo~') );
+ assert_false( makeEl('div',{itemref:'foo'}).itemRef.contains('foo?') );
+ assert_false( makeEl('div',{itemref:'foo'}).itemRef.contains('foo\\') );
+}, 'itemRef.contains must not match when punctuation characters are added');
+test(function () {
+ var elem = makeEl('div',{itemref:'foo'});
+ elem.itemRef.add('FOO');
+ assert_true( elem.itemRef.contains('foo') );
+}, 'itemRef.add must not remove existing tokens');
+test(function () {
+ assert_true( makeEl('div',{itemref:'foo FOO'}).itemRef.contains('FOO') );
+}, 'itemRef.contains case sensitivity must match a case-specific string');
+test(function () {
+ assert_equals( makeEl('div',{itemref:'foo FOO'}).itemRef.length, 2 );
+}, 'itemRef.length must correctly reflect the number of tokens');
+test(function () {
+ assert_equals( makeEl('div',{itemref:'foo FOO'}).itemRef.item(0), 'foo' );
+}, 'itemRef.item(0) must return the first token');
+test(function () {
+ var elem = makeEl('div',{itemref:'foo'});
+ elem.itemRef.add('FOO');
+ assert_equals( elem.itemRef.item(1), 'FOO' );
+}, 'itemRef.item must return case-sensitive strings and preserve token order');
+test(function () {
+ assert_equals( makeEl('div',{itemref:'foo FOO'}).itemRef[0], 'foo' );
+}, 'itemRef[0] must return the first token');
+test(function () {
+ assert_equals( makeEl('div',{itemref:'foo FOO'}).itemRef[1], 'FOO' );
+}, 'itemRef[index] must return case-sensitive strings and preserve token order');
+test(function () {
+ /* the normative part of the spec states that:
+ "unless the length is zero, in which case there are no supported property indices"
+ ...
+ "The term[...] supported property indices [is] used as defined in the WebIDL specification."
+ WebIDL creates actual OwnProperties and then [] just acts as a normal property lookup */
+ assert_equals( makeEl('div',{itemref:'foo FOO'}).itemRef[2], window.undefined );
+}, 'itemRef[index] must still be undefined for out-of-range index when earlier indexes exist');
+test(function () {
+ var elem = makeEl('div',{});
+ elem.itemRef.add('foo');
+ elem.itemRef.add('FOO');
+ assert_equals( elem.getAttribute('itemref'), 'foo FOO' );
+}, 'itemref attribute must update correctly when items have been added through itemRef');
+test(function () {
+ var elem = makeEl('div',{});
+ elem.itemRef.add('foo');
+ elem.itemRef.add('FOO');
+ assert_equals( elem.itemRef + '', 'foo FOO' );
+}, 'itemRef must stringify correctly when items have been added');
+test(function () {
+ var elem = makeEl('div',{itemref:'foo FOO'});
+ elem.itemRef.add('foo');
+ assert_equals( elem.itemRef.length, 2 );
+ assert_equals( elem.itemRef + '', 'foo FOO' );
+}, 'itemRef.add must not make any changes if an existing token is added');
+test(function () {
+ var elem = makeEl('div',{itemref:'foo FOO'});
+ elem.itemRef.remove('bar');
+ assert_equals( elem.itemRef.length, 2 );
+ assert_equals( elem.itemRef + '', 'foo FOO' );
+}, 'itemRef.remove must not make any changes if a non-existing token is removed');
+test(function () {
+ var elem = makeEl('div',{itemref:'foo FOO'});
+ elem.itemRef.remove('foo');
+ assert_equals( elem.itemRef.length, 1 );
+ assert_equals( elem.itemRef.toString(), 'FOO' );
+ assert_false( elem.itemRef.contains('foo') );
+ assert_true( elem.itemRef.contains('FOO') );
+}, 'itemRef.remove must remove existing tokens');
+test(function () {
+ var elem = makeEl('div',{itemref:'test test'});
+ elem.itemRef.remove('test');
+ assert_equals( elem.itemRef.length, 0 );
+ assert_false( elem.itemRef.contains('test') );
+}, 'itemRef.remove must remove duplicated tokens');
+test(function () {
+ var elem = makeEl('div',{itemref:'token1 token2 token3'});
+ elem.itemRef.remove('token2');
+ assert_equals( elem.itemRef.toString(), 'token1 token3' );
+}, 'itemRef.remove must collapse whitespace around removed tokens');
+test(function () {
+ var elem = makeEl('div',{itemref:' token1 token2 '});
+ elem.itemRef.remove('token2');
+ assert_equals( elem.itemRef.toString(), 'token1' );
+}, 'itemRef.remove must remove useless whitespace when removing tokens');
+test(function () {
+ var elem = makeEl('div',{itemref:' token1 token2 token3 '});
+ elem.itemRef.remove('token2');
+ assert_equals( elem.itemRef.toString(), 'token1 token3' );
+}, 'itemRef.remove must remove useless whitespace when removing tokens (2)');
+test(function () {
+ var elem = makeEl('div',{itemref:' token1 token2 token3 '});
+ elem.itemRef.remove('token1', 'token3');
+ assert_equals( elem.itemRef.toString(), 'token2' );
+}, 'itemRef.remove must collapse whitespace when removing multiple tokens');
+test(function () {
+ var elem = makeEl('div',{itemref:' token1 token1 '});
+ elem.itemRef.add('token1');
+ assert_equals( elem.itemRef.toString(), 'token1' );
+}, 'itemRef.add must remove whitespace and duplicate when the token already exists');
+test(function () {
+ var elem = makeEl('div',{itemref:'FOO'});
+ assert_true(elem.itemRef.toggle('foo'));
+ assert_equals( elem.itemRef.length, 2 );
+ assert_true( elem.itemRef.contains('foo') );
+ assert_true( elem.itemRef.contains('FOO') );
+}, 'itemRef.toggle must toggle tokens case-sensitively when adding');
+test(function () {
+ var elem = makeEl('div',{itemref:'foo FOO'});
+ assert_false(elem.itemRef.toggle('foo'));
+ assert_false(elem.itemRef.toggle('FOO'));
+ assert_false( elem.itemRef.contains('foo') );
+ assert_false( elem.itemRef.contains('FOO') );
+}, 'itemRef.toggle must be able to remove tokens case-sensitively');
+test(function () {
+ var elem = makeEl('div',{itemref:'foo FOO'});
+ elem.itemRef.toggle('foo');
+ elem.itemRef.toggle('FOO');
+ assert_equals( elem.getAttribute('itemref'), '' );
+}, 'itemref attribute must be empty when all classes have been removed');
+test(function () {
+ var elem = makeEl('div',{itemref:'foo FOO'});
+ elem.itemRef.toggle('foo');
+ elem.itemRef.toggle('FOO');
+ assert_equals( elem.itemRef.toString(), '' );
+}, 'itemRef must stringify to an empty string when all classes have been removed');
+test(function () {
+ var elem = makeEl('div',{itemref:'foo FOO'});
+ elem.itemRef.toggle('foo');
+ elem.itemRef.toggle('FOO');
+ assert_equals( elem.itemRef.item(0), null );
+}, 'itemRef.item(0) must return null when all classes have been removed');
+test(function () {
+ /* the normative part of the spec states that:
+ "unless the length is zero, in which case there are no supported property indices"
+ ...
+ "The term[...] supported property indices [is] used as defined in the WebIDL specification."
+ WebIDL creates actual OwnProperties and then [] just acts as a normal property lookup */
+ var elem = makeEl('div',{itemref:'foo FOO'});
+ elem.itemRef.toggle('foo');
+ elem.itemRef.toggle('FOO');
+ assert_equals( elem.itemRef[0], window.undefined );
+}, 'itemRef[0] must be undefined when all classes have been removed');
+//if the last character of DOMTokenSting underlying character is not a space character, append U+0020", where "space character" is from " \t\r\n\f"
+test(function () {
+ var elem = makeEl('div',{itemref:'a '});
+ elem.itemRef.add('b');
+ assert_equals(elem.itemRef.toString(),'a b');
+}, 'itemRef.add should treat " " as a space');
+test(function () {
+ var elem = makeEl('div',{itemref:'a\t'});
+ elem.itemRef.add('b');
+ assert_equals(elem.itemRef.toString(),'a b');
+}, 'itemRef.add should normalize \\t as a space');
+test(function () {
+ var elem = makeEl('div',{itemref:'a\r'});
+ elem.itemRef.add('b');
+ assert_equals(elem.itemRef.toString(),'a b');
+}, 'itemRef.add should normalize \\r as a space');
+test(function () {
+ var elem = makeEl('div',{itemref:'a\n'});
+ elem.itemRef.add('b');
+ assert_equals(elem.itemRef.toString(),'a b');
+}, 'itemRef.add should normalize \\n as a space');
+test(function () {
+ var elem = makeEl('div',{itemref:'a\f'});
+ elem.itemRef.add('b');
+ assert_equals(elem.itemRef.toString(),'a b');
+}, 'itemRef.add should normalize \\f as a space');
+test(function () {
+ var elem = makeEl('div',{itemref:'foo'});
+ elem.itemRef.remove('foo');
+ elem.removeAttribute('itemref');
+ assert_true( elem.itemRef.toggle('foo') );
+}, 'itemRef.toggle must work after removing the itemref attribute');
+test(function () {
+ //WebIDL and ECMAScript 5 - a readonly property has a getter but not a setter
+ //ES5 makes [[Put]] fail but not throw
+ var failed = false;
+ var elem = makeEl('div',{itemref:'token1'});
+ try {
+ elem.itemRef.length = 0;
+ } catch(e) {
+ failed = e;
+ }
+ assert_equals(elem.itemRef.length,1);
+ assert_false(failed,'an error was thrown');
+}, 'itemRef.length must be read-only');
+test(function () {
+ var failed = false, elem = makeEl('div',{itemref:'test'}), realList = elem.itemRef;
+ try {
+ elem.itemRef = 'dummy';
+ } catch(e) {
+ failed = e;
+ }
+ assert_equals(elem.itemRef,realList);
+ assert_equals(elem.itemRef.toString(),'dummy','attempting to write should modify the underlying string');
+ assert_false(failed,'an error was thrown');
+}, 'itemRef must be read-only');
+
+/* itemValue property tests */
+test(function () {
+ assert_equals( makeEl('meta',{content:'test'}).itemValue, null, 'meta' );
+ assert_equals( makeEl('audio',{src:'test'}).itemValue, null, 'audio' );
+ assert_equals( makeEl('embed',{src:'test'}).itemValue, null, 'embed' );
+ assert_equals( makeEl('iframe',{src:'test'}).itemValue, null, 'iframe' );
+ assert_equals( makeEl('img',{src:'test'}).itemValue, null, 'img' );
+ assert_equals( makeEl('source',{src:'test'}).itemValue, null, 'source' );
+ assert_equals( makeEl('track',{src:'test'}).itemValue, null, 'track' );
+ assert_equals( makeEl('video',{src:'test'}).itemValue, null, 'video' );
+ assert_equals( makeEl('a',{href:'test'}).itemValue, null, 'a' );
+ assert_equals( makeEl('area',{href:'test'}).itemValue, null, 'area' );
+ assert_equals( makeEl('link',{href:'test'}).itemValue, null, 'link' );
+ assert_equals( makeEl('object',{data:'test'}).itemValue, null, 'object' );
+ assert_equals( makeEl('time',{}).itemValue, null, 'time without datetime' );
+ assert_equals( makeEl('time',{datetime:'test'}).itemValue, null, 'time with datetime' );
+ assert_equals( makeEl('div',{},'test').itemValue, null, 'otherwise' );
+ assert_equals( makeEl('madeuponthespot',{},'test').itemValue, null, 'unknown element' );
+}, 'itemValue must be null if the element does not have an itemprop attribute');
+test(function () {
+ assert_throws( 'INVALID_ACCESS_ERR', function () { var testEl = makeEl('meta',{content:'test'}); testEl.itemValue = 'test2'; }, 'meta' );
+ assert_throws( 'INVALID_ACCESS_ERR', function () { var testEl = makeEl('audio',{content:'test'}); testEl.itemValue = 'test2'; }, 'audio' );
+ assert_throws( 'INVALID_ACCESS_ERR', function () { var testEl = makeEl('embed',{content:'test'}); testEl.itemValue = 'test2'; }, 'embed' );
+ assert_throws( 'INVALID_ACCESS_ERR', function () { var testEl = makeEl('iframe',{content:'test'}); testEl.itemValue = 'test2'; }, 'iframe' );
+ assert_throws( 'INVALID_ACCESS_ERR', function () { var testEl = makeEl('img',{content:'test'}); testEl.itemValue = 'test2'; }, 'img' );
+ assert_throws( 'INVALID_ACCESS_ERR', function () { var testEl = makeEl('source',{content:'test'}); testEl.itemValue = 'test2'; }, 'source' );
+ assert_throws( 'INVALID_ACCESS_ERR', function () { var testEl = makeEl('track',{content:'test'}); testEl.itemValue = 'test2'; }, 'track' );
+ assert_throws( 'INVALID_ACCESS_ERR', function () { var testEl = makeEl('video',{content:'test'}); testEl.itemValue = 'test2'; }, 'video' );
+ assert_throws( 'INVALID_ACCESS_ERR', function () { var testEl = makeEl('a',{href:'test'}); testEl.itemValue = 'test2'; }, 'a' );
+ assert_throws( 'INVALID_ACCESS_ERR', function () { var testEl = makeEl('area',{href:'test'}); testEl.itemValue = 'test2'; }, 'area' );
+ assert_throws( 'INVALID_ACCESS_ERR', function () { var testEl = makeEl('link',{href:'test'}); testEl.itemValue = 'test2'; }, 'link' );
+ assert_throws( 'INVALID_ACCESS_ERR', function () { var testEl = makeEl('object',{data:'test'}); testEl.itemValue = 'test2'; }, 'object' );
+ assert_throws( 'INVALID_ACCESS_ERR', function () { var testEl = makeEl('time',{}); testEl.itemValue = 'test2'; }, 'time without datetime' );
+ assert_throws( 'INVALID_ACCESS_ERR', function () { var testEl = makeEl('time',{datetime:'test'}); testEl.itemValue = 'test2'; }, 'time with datetime' );
+ assert_throws( 'INVALID_ACCESS_ERR', function () { var testEl = makeEl('div',{},'test'); testEl.itemValue = 'test2'; }, 'otherwise' );
+ assert_throws( 'INVALID_ACCESS_ERR', function () { var testEl = makeEl('madeuponthespot',{},'test'); testEl.itemValue = 'test2'; }, 'unknown element' );
+}, 'writing to itemValue must throw an INVALID_ACCESS_ERR error if the element does not have an itemprop attribute');
+test(function () {
+ var testEl;
+ testEl = makeEl('meta',{itemscope:'itemscope',itemprop:'foo',content:'test'});
+ assert_equals( testEl.itemValue, testEl, 'meta' );
+ testEl = makeEl('audio',{itemscope:'itemscope',itemprop:'foo',src:'test'},'fail');
+ assert_equals( testEl.itemValue, testEl, 'audio' );
+ testEl = makeEl('embed',{itemscope:'itemscope',itemprop:'foo',src:'test'});
+ assert_equals( testEl.itemValue, testEl, 'embed' );
+ testEl = makeEl('iframe',{itemscope:'itemscope',itemprop:'foo',src:'test'},'fail');
+ assert_equals( testEl.itemValue, testEl, 'iframe' );
+ testEl = makeEl('img',{itemscope:'itemscope',itemprop:'foo',src:'test'});
+ assert_equals( testEl.itemValue, testEl, 'img' );
+ testEl = makeEl('source',{itemscope:'itemscope',itemprop:'foo',src:'test'});
+ assert_equals( testEl.itemValue, testEl, 'source' );
+ testEl = makeEl('track',{itemscope:'itemscope',itemprop:'foo',src:'test'});
+ assert_equals( testEl.itemValue, testEl, 'track' );
+ testEl = makeEl('video',{itemscope:'itemscope',itemprop:'foo',src:'test'},'fail');
+ assert_equals( testEl.itemValue, testEl, 'video' );
+ testEl = makeEl('a',{itemscope:'itemscope',itemprop:'foo',href:'test'},'fail');
+ assert_equals( testEl.itemValue, testEl, 'a' );
+ testEl = makeEl('area',{itemscope:'itemscope',itemprop:'foo',href:'test'});
+ assert_equals( testEl.itemValue, testEl, 'area' );
+ testEl = makeEl('link',{itemscope:'itemscope',itemprop:'foo',href:'test'});
+ assert_equals( testEl.itemValue, testEl, 'link' );
+ testEl = makeEl('object',{itemscope:'itemscope',itemprop:'foo',data:'test'},'fail');
+ assert_equals( testEl.itemValue, testEl, 'object' );
+ testEl = makeEl('time',{itemscope:'itemscope',itemprop:'foo'},'fail');
+ assert_equals( testEl.itemValue, testEl, 'time without datetime' );
+ testEl = makeEl('time',{itemscope:'itemscope',itemprop:'foo',datetime:'test'},'fail');
+ assert_equals( testEl.itemValue, testEl, 'time with datetime' );
+ testEl = makeEl('div',{itemscope:'itemscope',itemprop:'foo'},'test');
+ assert_equals( testEl.itemValue, testEl, 'otherwise' );
+ testEl = makeEl('madeuponthespot',{itemscope:'itemscope',itemprop:'foo'},'test');
+ assert_equals( testEl.itemValue, testEl, 'unknown element' );
+ testEl = makeEl('madeuponthespot',{itemscope:'itemscope',itemprop:'foo',content:'test',src:'test',href:'test',data:'test',datetime:'test',value:'test'},'test');
+ assert_equals( testEl.itemValue, testEl, 'unknown element with known attributes' );
+ testEl = makeEl('input',{itemscope:'itemscope',itemprop:'foo',value:'test'},'test');
+ assert_equals( testEl.itemValue, testEl, 'input' );
+}, 'itemValue must return the element if the element has an itemscope attribute');
+test(function () {
+ var testEl = makeEl('meta',{itemprop:'foo',content:'test'});
+ assert_equals( testEl.itemValue, 'test', 'reading' );
+ testEl.content = 'retest';
+ assert_equals( testEl.itemValue, 'retest', 'reading after change' );
+ testEl.itemValue = 'bar';
+ assert_equals( testEl.content, 'bar', 'writing (checking content)' );
+ assert_equals( testEl.textContent, '', 'writing (checking textContent)' );
+}, 'itemValue must reflect the content attribute on meta elements');
+test(function () {
+ var testEl = makeEl('audio',{itemprop:'foo',src:urls.base},'contained text');
+ assert_equals( testEl.itemValue, urls.base, 'reading' );
+ testEl.src = urls.www;
+ assert_equals( testEl.itemValue, urls.www, 'reading after change' );
+ testEl.itemValue = urls.www1;
+ assert_equals( testEl.src, urls.www1, 'writing (checking src)' );
+ assert_equals( testEl.textContent, 'contained text', 'writing (checking textContent)' );
+ assert_equals( makeEl('audio',{itemprop:'foo'},'contained text').itemValue, '', 'reading with missing attribute' );
+ testEl.src = 'bar';
+ assert_equals( testEl.itemValue, location.href.replace(/\/[^\/]*$/,'/bar'), 'resolving URLs' );
+}, 'itemValue must reflect the src attribute on audio elements');
+test(function () {
+ var testEl = makeEl('embed',{itemprop:'foo',src:urls.base});
+ assert_equals( testEl.itemValue, urls.base, 'reading' );
+ testEl.src = urls.www;
+ assert_equals( testEl.itemValue, urls.www, 'reading after change' );
+ testEl.itemValue = urls.www1;
+ assert_equals( testEl.src, urls.www1, 'writing (checking src)' );
+ assert_equals( testEl.textContent, '', 'writing (checking textContent)' );
+ testEl.src = 'bar';
+ assert_equals( testEl.itemValue, location.href.replace(/\/[^\/]*$/,'/bar'), 'resolving URLs' );
+}, 'itemValue must reflect the src attribute on embed elements');
+test(function () {
+ var testEl = makeEl('iframe',{itemprop:'foo',src:urls.base},'contained text');
+ assert_equals( testEl.itemValue, urls.base, 'reading' );
+ testEl.src = urls.www;
+ assert_equals( testEl.itemValue, urls.www, 'reading after change' );
+ testEl.itemValue = urls.www1;
+ assert_equals( testEl.src, urls.www1, 'writing (checking src)' );
+ assert_equals( testEl.textContent, 'contained text', 'writing (checking textContent)' );
+ assert_equals( makeEl('iframe',{itemprop:'foo'},'contained text').itemValue, '', 'reading with missing attribute' );
+ testEl.src = 'bar';
+ assert_equals( testEl.itemValue, location.href.replace(/\/[^\/]*$/,'/bar'), 'resolving URLs' );
+}, 'itemValue must reflect the src attribute on iframe elements');
+test(function () {
+ var testEl = makeEl('img',{itemprop:'foo',src:urls.base});
+ assert_equals( testEl.itemValue, urls.base, 'reading' );
+ testEl.src = urls.www;
+ assert_equals( testEl.itemValue, urls.www, 'reading after change' );
+ testEl.itemValue = urls.www1;
+ assert_equals( testEl.src, urls.www1, 'writing (checking src)' );
+ assert_equals( testEl.textContent, '', 'writing (checking textContent)' );
+ testEl.src = 'bar';
+ assert_equals( testEl.itemValue, location.href.replace(/\/[^\/]*$/,'/bar'), 'resolving URLs' );
+}, 'itemValue must reflect the src attribute on img elements');
+test(function () {
+ var testEl = makeEl('source',{itemprop:'foo',src:urls.base});
+ assert_equals( testEl.itemValue, urls.base, 'reading' );
+ testEl.src = urls.www;
+ assert_equals( testEl.itemValue, urls.www, 'reading after change' );
+ testEl.itemValue = urls.www1;
+ assert_equals( testEl.src, urls.www1, 'writing (checking src)' );
+ assert_equals( testEl.textContent, '', 'writing (checking textContent)' );
+ testEl.src = 'bar';
+ assert_equals( testEl.itemValue, location.href.replace(/\/[^\/]*$/,'/bar'), 'resolving URLs' );
+}, 'itemValue must reflect the src attribute on source elements');
+test(function () {
+ var testEl = makeEl('track',{itemprop:'foo',src:urls.base});
+ assert_equals( testEl.itemValue, urls.base, 'reading' );
+ testEl.src = urls.www;
+ assert_equals( testEl.itemValue, urls.www, 'reading after change' );
+ testEl.itemValue = urls.www1;
+ assert_equals( testEl.src, urls.www1, 'writing (checking src)' );
+ assert_equals( testEl.textContent, '', 'writing (checking textContent)' );
+ testEl.src = 'bar';
+ assert_equals( testEl.itemValue, location.href.replace(/\/[^\/]*$/,'/bar'), 'resolving URLs' );
+}, 'itemValue must reflect the src attribute on track elements');
+test(function () {
+ var testEl = makeEl('video',{itemprop:'foo',src:urls.base},'contained text');
+ assert_equals( testEl.itemValue, urls.base, 'reading' );
+ testEl.src = urls.www;
+ assert_equals( testEl.itemValue, urls.www, 'reading after change' );
+ testEl.itemValue = urls.www1;
+ assert_equals( testEl.src, urls.www1, 'writing (checking src)' );
+ assert_equals( testEl.textContent, 'contained text', 'writing (checking textContent)' );
+ assert_equals( makeEl('video',{itemprop:'foo'},'contained text').itemValue, '', 'reading with missing attribute' );
+ testEl.src = 'bar';
+ assert_equals( testEl.itemValue, location.href.replace(/\/[^\/]*$/,'/bar'), 'resolving URLs' );
+}, 'itemValue must reflect the src attribute on video elements');
+test(function () {
+ var testEl = makeEl('a',{itemprop:'foo',href:urls.base},'contained text');
+ assert_equals( testEl.itemValue, urls.base, 'reading' );
+ testEl.href = urls.www;
+ assert_equals( testEl.itemValue, urls.www, 'reading after change' );
+ testEl.itemValue = urls.www1;
+ assert_equals( testEl.href, urls.www1, 'writing (checking href)' );
+ assert_equals( testEl.textContent, 'contained text', 'writing (checking textContent)' );
+ assert_equals( makeEl('a',{itemprop:'foo'},'contained text').itemValue, '', 'reading with missing attribute' );
+ testEl.href = 'bar';
+ assert_equals( testEl.itemValue, location.href.replace(/\/[^\/]*$/,'/bar'), 'resolving URLs' );
+}, 'itemValue must reflect the src attribute on anchor elements');
+test(function () {
+ var testEl = makeEl('area',{itemprop:'foo',href:urls.base});
+ assert_equals( testEl.itemValue, urls.base, 'reading' );
+ testEl.href = urls.www;
+ assert_equals( testEl.itemValue, urls.www, 'reading after change' );
+ testEl.itemValue = urls.www1;
+ assert_equals( testEl.href, urls.www1, 'writing (checking href)' );
+ assert_equals( testEl.textContent, '', 'writing (checking textContent)' );
+ testEl.href = 'bar';
+ assert_equals( testEl.itemValue, location.href.replace(/\/[^\/]*$/,'/bar'), 'resolving URLs' );
+}, 'itemValue must reflect the src attribute on area elements');
+test(function () {
+ var testEl = makeEl('link',{itemprop:'foo',href:urls.base});
+ assert_equals( testEl.itemValue, urls.base, 'reading' );
+ testEl.href = urls.www;
+ assert_equals( testEl.itemValue, urls.www, 'reading after change' );
+ testEl.itemValue = urls.www1;
+ assert_equals( testEl.href, urls.www1, 'writing (checking href)' );
+ assert_equals( testEl.textContent, '', 'writing (checking textContent)' );
+ testEl.href = 'bar';
+ assert_equals( testEl.itemValue, location.href.replace(/\/[^\/]*$/,'/bar'), 'resolving URLs' );
+}, 'itemValue must reflect the src attribute on link elements');
+test(function () {
+ var testEl = makeEl('object',{itemprop:'foo',data:urls.base},'contained text');
+ assert_equals( testEl.itemValue, urls.base, 'reading' );
+ testEl.data = urls.www;
+ assert_equals( testEl.itemValue, urls.www, 'reading after change' );
+ testEl.itemValue = urls.www1;
+ assert_equals( testEl.data, urls.www1, 'writing (checking data)' );
+ assert_equals( testEl.textContent, 'contained text', 'writing (checking textContent)' );
+ assert_equals( makeEl('object',{itemprop:'foo'},'contained text').itemValue, '', 'reading with missing attribute' );
+ testEl.data = 'bar';
+ assert_equals( testEl.itemValue, location.href.replace(/\/[^\/]*$/,'/bar'), 'resolving URLs' );
+}, 'itemValue must reflect the src attribute on object elements');
+test(function () {
+ var testEl = makeEl('time',{itemprop:'foo'},'te <span itemprop="bar" itemscope>st</span> ing');
+ assert_equals( testEl.itemValue, 'te st ing', 'reading' );
+ testEl.innerHTML = 'retest';
+ assert_equals( testEl.itemValue, 'retest', 'reading after change' );
+ testEl.itemValue = '2001-02-03T04:05:06Z';
+ assert_equals( testEl.dateTime, '2001-02-03T04:05:06Z', 'writing (checking dateTime)' );
+ assert_equals( testEl.textContent, 'retest', 'writing (checking textContent)' );
+ assert_equals( testEl.itemValue, '2001-02-03T04:05:06Z', 'writing (checking itemValue)' );
+}, 'itemValue must reflect the dateTime attribute of time elements with no datetime attribute');
+test(function () {
+ var testEl = makeEl('time',{itemprop:'foo',datetime:'test'},'te <span itemprop="bar" itemscope>st</span> ing');
+ assert_equals( testEl.itemValue, 'test', 'reading' );
+ testEl.dateTime = 'retest';
+ assert_equals( testEl.itemValue, 'retest', 'reading after change' );
+ testEl.itemValue = '2001-02-03T04:05:06Z';
+ assert_equals( testEl.dateTime, '2001-02-03T04:05:06Z', 'writing (checking dateTime)' );
+ assert_equals( testEl.textContent, 'te st ing', 'writing (checking textContent)' );
+}, 'itemValue must reflect the datetime attribute of time elements with a datetime attribute');
+test(function () {
+ var testEl = makeEl('div',{itemprop:'foo'},'te <span itemprop="bar" itemscope>st</span> ing');
+ assert_equals( testEl.itemValue, 'te st ing', 'reading' );
+ testEl.innerHTML = 're<strong>te</strong>st';
+ assert_equals( testEl.itemValue, 'retest', 'reading after change' );
+ testEl.itemValue = 'test';
+ assert_equals( testEl.textContent, 'test', 'writing' );
+}, 'itemValue must reflect the textContent of other elements');
+test(function () {
+ var testEl = makeEl('madeuponthespot',{itemprop:'foo'},'te <span itemprop="bar" itemscope>st</span> ing');
+ assert_equals( testEl.itemValue, 'te st ing', 'reading' );
+ testEl.innerHTML = 're<strong>te</strong>st';
+ assert_equals( testEl.itemValue, 'retest', 'reading after change' );
+ testEl.itemValue = 'test';
+ assert_equals( testEl.textContent, 'test', 'writing' );
+}, 'itemValue must reflect the textContent of unknown elements');
+test(function () {
+ var testEl = makeEl('madeuponthespot',{itemprop:'foo',content:'test',src:'test',href:'test',data:'test',datetime:'test',value:'test'},'te <span itemprop="bar" itemscope>st</span> ing');
+ assert_equals( testEl.itemValue, 'te st ing', 'reading' );
+ testEl.innerHTML = 're<strong>te</strong>st';
+ assert_equals( testEl.itemValue, 'retest', 'reading after change' );
+ testEl.itemValue = 'test';
+ assert_equals( testEl.textContent, 'test', 'writing' );
+}, 'itemValue must reflect the textContent of unknown elements with known attributes');
+test(function () {
+ var testEl = makeEl('input',{itemprop:'foo',value:'test'});
+ assert_equals( testEl.itemValue, '', 'reading' );
+ testEl.value = 'retest';
+ assert_equals( testEl.itemValue, '', 'reading after change' );
+}, 'itemValue must not reflect the value of input elements');
+test(function () {
+ var testEl, eltypes = [
+ makeEl('meta',{itemprop:'foo',content:'test'}),
+ makeEl('audio',{itemprop:'foo',src:'test'},'fail'),
+ makeEl('embed',{itemprop:'foo',src:'test'}),
+ makeEl('iframe',{itemprop:'foo',src:'test'},'fail'),
+ makeEl('img',{itemprop:'foo',src:'test'}),
+ makeEl('source',{itemprop:'foo',src:'test'}),
+ makeEl('track',{itemprop:'foo',src:'test'}),
+ makeEl('video',{itemprop:'foo',src:'test'},'fail'),
+ makeEl('a',{itemprop:'foo',href:'test'},'fail'),
+ makeEl('area',{itemprop:'foo',href:'test'}),
+ makeEl('link',{itemprop:'foo',href:'test'}),
+ makeEl('object',{itemprop:'foo',data:'test'},'fail'),
+ makeEl('time',{itemprop:'foo'},'fail'),
+ makeEl('time',{itemprop:'foo',datetime:'test'},'fail'),
+ makeEl('div',{itemprop:'foo'},'test'),
+ makeEl('madeuponthespot',{itemprop:'foo'},'test'),
+ makeEl('madeuponthespot',{itemprop:'foo',content:'test',src:'test',href:'test',data:'test',datetime:'test',value:'test'},'test'),
+ makeEl('input',{itemprop:'foo',value:'test'},'test')
+ ], beforeValues, i;
+ for( i = 0; i < eltypes.length; i++ ) {
+ testEl = eltypes[i];
+ beforeValues = testEl.itemValue;
+ testEl.itemScope = true;
+ assert_equals( testEl.itemValue, testEl, 'itemscope enabled on '+testEl.tagName+' index '+i );
+ testEl.itemScope = false;
+ assert_equals( testEl.itemValue, beforeValues, 'itemscope disabled on '+testEl.tagName+' index '+i );
+ testEl.itemScope = true;
+ testEl.removeAttribute('itemscope');
+ assert_equals( testEl.itemValue, beforeValues, 'itemscope attribute removed on '+testEl.tagName+' index '+i );
+ }
+}, 'dynamic changes of itemscope should change the value exposed through itemValue');
+
+test(function () {
+ var testEl, eltypes = [
+ makeEl('meta',{itemprop:'foo',content:'test'}),
+ makeEl('audio',{itemprop:'foo',src:'test'},'fail'),
+ makeEl('embed',{itemprop:'foo',src:'test'}),
+ makeEl('iframe',{itemprop:'foo',src:'test'},'fail'),
+ makeEl('img',{itemprop:'foo',src:'test'}),
+ makeEl('source',{itemprop:'foo',src:'test'}),
+ makeEl('track',{itemprop:'foo',src:'test'}),
+ makeEl('video',{itemprop:'foo',src:'test'},'fail'),
+ makeEl('a',{itemprop:'foo',href:'test'},'fail'),
+ makeEl('area',{itemprop:'foo',href:'test'}),
+ makeEl('link',{itemprop:'foo',href:'test'}),
+ makeEl('object',{itemprop:'foo',data:'test'},'fail'),
+ makeEl('time',{itemprop:'foo'},'fail'),
+ makeEl('time',{itemprop:'foo',datetime:'test'},'fail'),
+ makeEl('div',{itemprop:'foo'},'test'),
+ makeEl('madeuponthespot',{itemprop:'foo'},'test'),
+ makeEl('madeuponthespot',{itemprop:'foo',content:'test',src:'test',href:'test',data:'test',datetime:'test',value:'test'},'test'),
+ makeEl('input',{itemprop:'foo',value:'test'},'test')
+ ], beforeValues, i;
+ for( i = 0; i < eltypes.length; i++ ) {
+ testEl = eltypes[i];
+ beforeValues = testEl.itemValue;
+ testEl.itemProp.remove('foo');
+ assert_equals( testEl.itemValue, beforeValues, 'itemprop tokens removed on '+testEl.tagName+' index '+i );
+ testEl.removeAttribute('itemprop');
+ assert_equals( testEl.itemValue, null, 'itemprop attribute removed on '+testEl.tagName+' index '+i );
+ testEl.itemProp.toggle('foo');
+ assert_equals( testEl.itemValue, beforeValues, 'itemprop tokens added on '+testEl.tagName+' index '+i );
+ }
+}, 'dynamic changes of itemprop should change the value exposed through itemValue');
+
+/* properties */
+test(function () {
+ assert_equals( typeof makeEl('div',{}).properties, 'object' );
+}, 'the properties property must be an object');
+test(function () {
+ var testEl = makeEl('div',{});
+ assert_true( testEl.properties instanceof HTMLPropertiesCollection, 'instanceof HTMLPropertiesCollection' );
+ assert_true( testEl.properties instanceof HTMLCollection, 'instanceof HTMLCollection' );
+ HTMLPropertiesCollection.prototype.customProperty = true;
+ HTMLCollection.prototype.anotherCustomProperty = true;
+ assert_true( testEl.properties.customProperty, 'inheritance from HTMLPropertiesCollection' );
+ assert_true( testEl.properties.anotherCustomProperty, 'inheritance from HTMLCollection' );
+ HTMLPropertiesCollection.prototype.anotherCustomProperty = false;
+ assert_false( testEl.properties.anotherCustomProperty, 'shadowing by HTMLPropertiesCollection' );
+}, 'the properties property must implement HTMLPropertiesCollection and HTMLCollection');
+test(function () {
+ var failed = false, elem = makeEl('div',{itemscope:'itemscope'}), realList = elem.properties;
+ try {
+ elem.properties = '';
+ } catch(e) {
+ failed = e;
+ }
+ assert_equals(elem.properties,realList);
+ assert_false(failed,'an error was thrown');
+}, 'the properties property must be read-only');
+test(function () {
+ var testEl = makeEl('div',{});
+ assert_equals( testEl.properties, testEl.properties );
+}, 'the properties property must always reference the same object');
+test(function () {
+ var testEl = makeEl('div',{},'<div itemprop="foo">bar</div>');
+ assert_equals( testEl.properties.length, 0, 'length' );
+ assert_true( !testEl.properties.item(0), 'item(0)' );
+ assert_true( !testEl.properties[0], '[0]' );
+ assert_equals( testEl.properties.namedItem('foo').length, 0, 'namedItem' );
+ assert_true( !testEl.properties['foo'], '[namedItem]' );
+ assert_equals( testEl.properties.namedItem('foo').getValues().length, 0, 'namedItem' );
+ assert_equals( testEl.properties.names.length, 0, 'names' );
+}, 'the properties collection must be empty if the element does not have an itemscope property');
+test(function() {
+ var testEl = makeEl('div',{},'<div itemprop="foo">bar</div>');
+ assert_throws( new TypeError(), function() { testEl.properties('foo'); } );
+ assert_throws( new TypeError(), function() { testEl.properties(0); } );
+}, 'the properties collection must not support legacycaller');
+test(function () {
+ var testEl = makeEl('div',{},'<div itemprop="foo">bar</div>');
+ testEl.itemScope = true;
+ assert_equals( testEl.properties.length, 1, 'length' );
+ assert_equals( testEl.properties.item(0), testEl.firstChild, 'item(0)' );
+ assert_equals( testEl.properties[0], testEl.firstChild, '[0]' );
+ assert_equals( testEl.properties.namedItem('foo').length, 1, 'namedItem' );
+ assert_equals( testEl.properties['foo'].length, 1, '[namedItem]' );
+ assert_equals( testEl.properties.namedItem('foo').getValues().length, 1, 'namedItem' );
+ assert_equals( testEl.properties.names.length, 1, 'names' );
+}, 'the properties collection must become populated if the element is given an itemscope property');
+test(function () {
+ var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo">bar</div>');
+ testEl.itemScope = false;
+ assert_equals( testEl.properties.length, 0, 'length' );
+ assert_true( !testEl.properties.item(0), 'item(0)' );
+ assert_true( !testEl.properties[0], '[0]' );
+ assert_equals( testEl.properties.namedItem('foo').length, 0, 'namedItem' );
+ assert_true( !testEl.properties['foo'], '[namedItem]' );
+ assert_equals( testEl.properties.namedItem('foo').getValues().length, 0, 'namedItem' );
+ assert_equals( testEl.properties.names.length, 0, 'names' );
+}, 'the properties collection must become empty if the element\'s itemscope property is removed');
+//properties.item and properties.length (part 1)
+test(function () {
+ var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div><div itemprop="bar"><div itemprop="foo"></div><div itemprop="foo"></div></div><div itemprop="baz qux"></div>');
+ assert_equals( testEl.properties.length, 5 );
+}, 'properties.length must be the total number of properties');
+test(function () {
+ var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div><div itemprop="bar"><div itemprop="foo"></div></div><div itemprop="baz qux"></div>');
+ assert_equals( testEl.properties.item(0), testEl.childNodes[0], 'item(0)' );
+ assert_equals( testEl.properties.item(1), testEl.childNodes[1], 'item(1)' );
+ assert_equals( testEl.properties.item(2), testEl.childNodes[1].childNodes[0], 'item(2)' );
+ assert_equals( testEl.properties.item(3), testEl.childNodes[2], 'item(3)' );
+}, 'properties.item must give each property in tree order');
+test(function () {
+ var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div><div itemprop="bar"><div itemprop="foo"></div></div><div itemprop="baz qux"></div>');
+ testEl.properties.something = "another";
+ var names = Object.getOwnPropertyNames(testEl.properties);
+ assert_array_equals( names, ["0", "1", "2", "3", "foo", "bar", "baz", "qux", "something"] );
+}, 'properties.item must have the right property names on it when enumerated');
+test(function () {
+ var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div><div itemprop="bar"><div itemprop="foo"></div></div><div itemprop="baz qux"></div>');
+ assert_equals( testEl.properties.item(4), null, 'positive index' );
+ assert_equals( testEl.properties.item(-1), null, 'negative index' );
+}, 'properties.item must give null for out of range index');
+test(function () {
+ var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div><div itemprop="bar"><div itemprop="foo"></div></div><div itemprop="baz qux"></div>');
+ assert_equals( testEl.properties[0], testEl.childNodes[0], '[0]' );
+ assert_equals( testEl.properties[1], testEl.childNodes[1], '[1]' );
+ assert_equals( testEl.properties[2], testEl.childNodes[1].childNodes[0], '[2]' );
+ assert_equals( testEl.properties[3], testEl.childNodes[2], '[3]' );
+}, 'properties[index] must give each property in tree order');
+test(function () {
+ var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div><div itemprop="bar"><div itemprop="foo"></div></div><div itemprop="baz qux"></div>');
+ assert_equals( testEl.properties[4], window.undefined, 'positive index' );
+ assert_equals( testEl.properties[-1], window.undefined, 'negative index' );
+}, 'properties[index] must give undefined for out of range index');
+test(function () {
+ var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemscope itemprop="foo"><div itemprop="bar"></div></div><div><div itemprop="baz"></div></div>');
+ assert_equals( testEl.properties.length, 2, 'length' );
+ assert_equals( testEl.properties.item(0), testEl.firstChild, 'properties.item(0)' );
+ assert_equals( testEl.properties[0], testEl.firstChild, 'properties[0]' );
+ assert_equals( testEl.properties.item(1), testEl.childNodes[1].firstChild, 'properties.item(1)' );
+ assert_equals( testEl.properties[1], testEl.childNodes[1].firstChild, 'properties[1]' );
+}, 'properties.item and length must ignore properties of nested items');
+test(function () {
+ //note, itemref ordering is reversed compared with the next test to catch failed sorting algorithms
+ var parEl = makeEl('div',{},'<div itemprop="foo" id="id1"></div><div itemscope itemref="id2 id1"><div itemprop="bar"></div></div><div itemprop="baz" id="id2"><div itemprop="qux"></div></div>');
+ var testEl = parEl.childNodes[1];
+ document.body.appendChild(parEl);
+ var propLength = testEl.properties.length;
+ var item0 = testEl.properties.item(0);
+ var square0 = testEl.properties[0];
+ var item1 = testEl.properties.item(1);
+ var square1 = testEl.properties[1];
+ var item2 = testEl.properties.item(2);
+ var square2 = testEl.properties[2];
+ var item3 = testEl.properties.item(3);
+ var square3 = testEl.properties[3];
+ document.body.removeChild(parEl);
+ assert_equals( propLength, 4, 'length' );
+ assert_equals( item0, parEl.firstChild, 'properties.item(0)' );
+ assert_equals( square0, parEl.firstChild, 'properties[0]' );
+ assert_equals( item1, testEl.firstChild, 'properties.item(1)' );
+ assert_equals( square1, testEl.firstChild, 'properties[1]' );
+ assert_equals( item2, parEl.childNodes[2], 'properties.item(2)' );
+ assert_equals( square2, parEl.childNodes[2], 'properties[2]' );
+ assert_equals( item3, parEl.childNodes[2].firstChild, 'properties.item(3)' );
+ assert_equals( square3, parEl.childNodes[2].firstChild, 'properties[3]' );
+}, 'properties.item and length must see items added with itemref when attached to the document\'s DOM');
+test(function () {
+ var parEl = makeEl('div',{},'<div itemprop="foo" id="id1"></div><div itemscope itemref="id1 id2"><div itemprop="bar"></div></div><div itemprop="baz" id="id2"><div itemprop="qux"></div></div>');
+ var testEl = parEl.childNodes[1];
+ assert_equals( testEl.properties.length, 4, 'length' );
+ assert_equals( testEl.properties.item(0), parEl.firstChild, 'properties.item(0)' );
+ assert_equals( testEl.properties[0], parEl.firstChild, 'properties[0]' );
+ assert_equals( testEl.properties.item(1), testEl.firstChild, 'properties.item(1)' );
+ assert_equals( testEl.properties[1], testEl.firstChild, 'properties[1]' );
+ assert_equals( testEl.properties.item(2), parEl.childNodes[2], 'properties.item(2)' );
+ assert_equals( testEl.properties[2], parEl.childNodes[2], 'properties[2]' );
+ assert_equals( testEl.properties.item(3), parEl.childNodes[2].firstChild, 'properties.item(3)' );
+ assert_equals( testEl.properties[3], parEl.childNodes[2].firstChild, 'properties[3]' );
+}, 'properties.item and length must see items added with itemref');
+test(function () {
+ var parEl = makeEl('div',{},'<div itemscope itemref="id1"></div><div itemprop="foo" id="id1"><div itemprop="bar"></div></div><div itemprop="baz" id="id1"></div>');
+ var testEl = parEl.childNodes[0];
+ assert_equals( testEl.properties.length, 2, 'length' );
+ assert_equals( testEl.properties.item(0), parEl.childNodes[1], 'properties.item(0)' );
+ assert_equals( testEl.properties.item(1), parEl.childNodes[1].firstChild, 'properties.item(1)' );
+ document.body.appendChild(parEl)
+ var length = testEl.properties.length;
+ var item0 = testEl.properties.item(0);
+ var item1 = testEl.properties.item(0);
+ document.body.removeChild(parEl)
+ assert_equals( testEl.properties.length, 2, 'length (attached to document)' );
+ assert_equals( testEl.properties.item(0), parEl.childNodes[1], 'properties.item(0) (attached to document)' );
+ assert_equals( testEl.properties.item(1), parEl.childNodes[1].firstChild, 'properties.item(1) (attached to document)' );
+}, 'itemref must reference the first element with a given ID');
+test(function () {
+ var parEl = makeEl('div',{},'<div itemscope itemref="id1 id1"></div><div itemprop="foo" id="id1"><div itemprop="bar"></div></div><div itemprop="baz" id="id1"></div>');
+ var testEl = parEl.childNodes[0];
+ assert_equals( testEl.properties.length, 2, 'length' );
+ assert_equals( testEl.properties.item(0), parEl.childNodes[1], 'properties.item(0)' );
+ assert_equals( testEl.properties.item(1), parEl.childNodes[1].firstChild, 'properties.item(1)' );
+ document.body.appendChild(parEl)
+ var length = testEl.properties.length;
+ var item0 = testEl.properties.item(0);
+ var item1 = testEl.properties.item(0);
+ document.body.removeChild(parEl)
+ assert_equals( testEl.properties.length, 2, 'length (attached to document)' );
+ assert_equals( testEl.properties.item(0), parEl.childNodes[1], 'properties.item(0) (attached to document)' );
+ assert_equals( testEl.properties.item(1), parEl.childNodes[1].firstChild, 'properties.item(1) (attached to document)' );
+}, 'itemref must ignore duplicated IDs');
+test(function () {
+ var parEl = makeEl('div',{},'<div itemscope itemref="id0 id1"></div><div itemprop="foo" id="id1"><div itemprop="bar"></div></div>');
+ var testEl = parEl.childNodes[0];
+ assert_equals( testEl.properties.length, 2, 'length' );
+ assert_equals( testEl.properties.item(0), parEl.childNodes[1], 'properties.item(0)' );
+ assert_equals( testEl.properties.item(1), parEl.childNodes[1].firstChild, 'properties.item(1)' );
+ document.body.appendChild(parEl)
+ var length = testEl.properties.length;
+ var item0 = testEl.properties.item(0);
+ var item1 = testEl.properties.item(0);
+ document.body.removeChild(parEl)
+ assert_equals( testEl.properties.length, 2, 'length (attached to document)' );
+ assert_equals( testEl.properties.item(0), parEl.childNodes[1], 'properties.item(0) (attached to document)' );
+ assert_equals( testEl.properties.item(1), parEl.childNodes[1].firstChild, 'properties.item(1) (attached to document)' );
+}, 'itemref must ignore non-existent IDs');
+test(function () {
+ var testEl = makeEl('div',{itemscope:'itemscope',itemref:'id1'});
+ var dummyEl = makeEl('div',{id:'id1',itemprop:'foo'});
+ assert_equals( testEl.properties.length, 0 );
+}, 'itemref in a dislocated tree must not reference elements from another dislocated tree');
+test(function () {
+ var testEl = makeEl('div',{itemscope:'itemscope',itemref:'id1'});
+ var dummyEl = makeEl('div',{id:'id1',itemprop:'foo'});
+ document.body.appendChild(dummyEl);
+ var tmp = testEl.properties.length;
+ document.body.removeChild(dummyEl);
+ assert_equals( tmp, 0 );
+}, 'itemref in a dislocated tree must not reference elements from the main document');
+test(function () {
+ var testEl = makeEl('div',{itemscope:'itemscope',itemref:'id1'});
+ var dummyEl = makeEl('div',{id:'id1',itemprop:'foo'});
+ document.body.appendChild(testEl);
+ var tmp = testEl.properties.length;
+ document.body.removeChild(testEl);
+ assert_equals( tmp, 0 );
+}, 'itemref in the main document must not reference elements from a dislocated tree');
+test(function () {
+ var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div>');
+ assert_equals( testEl.properties.length, 1, 'length (before test)' );
+ assert_equals( testEl.properties.item(0), testEl.firstChild, 'properties.item(0) (before test)' );
+ assert_equals( testEl.properties[0], testEl.firstChild, 'properties[0] (before test)' );
+ testEl.appendChild(makeEl('div',{itemprop:'bar'}));
+ assert_equals( testEl.properties.length, 2, 'length after adding a child' );
+ assert_equals( testEl.properties.item(1), testEl.childNodes[1], 'properties.item(1) after adding a child' );
+ assert_equals( testEl.properties[1], testEl.childNodes[1], 'properties[1] after adding a child' );
+ testEl.lastChild.appendChild(makeEl('div',{itemprop:'foo'}));
+ assert_equals( testEl.properties.length, 3, 'length after adding a child with duplicated name' );
+ assert_equals( testEl.properties.item(2), testEl.childNodes[1].firstChild, 'properties.item(2) after adding a child with duplicated name' );
+ assert_equals( testEl.properties[2], testEl.childNodes[1].firstChild, 'properties[2] after adding a child with duplicated name' );
+ testEl.lastChild.removeChild(testEl.lastChild.firstChild);
+ assert_equals( testEl.properties.length, 2, 'length after removing a child' );
+ assert_true( !testEl.properties.item(2), 'properties.item(1) after removing a child' );
+ assert_true( !testEl.properties[2], 'properties[1] after removing a child' );
+}, 'properties.item and length must update when adding property elements');
+test(function () {
+ var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div><div itemprop="bar"></div>');
+ assert_equals( testEl.properties.length, 2, 'length (before test)' );
+ assert_equals( testEl.properties.item(0), testEl.firstChild, 'properties.item(0) (before test)' );
+ assert_equals( testEl.properties[0], testEl.firstChild, 'properties[0] (before test)' );
+ assert_equals( testEl.properties.item(1), testEl.childNodes[1], 'properties.item(1) (before test)' );
+ assert_equals( testEl.properties[1], testEl.childNodes[1], 'properties[1] (before test)' );
+ testEl.appendChild(testEl.firstChild);
+ assert_equals( testEl.properties.length, 2, 'length (after test)' );
+ assert_equals( testEl.properties.item(0), testEl.firstChild, 'properties.item(0) (after test)' );
+ assert_equals( testEl.properties[0], testEl.firstChild, 'properties[0] (after test)' );
+ assert_equals( testEl.properties.item(1), testEl.childNodes[1], 'properties.item(1) (after test)' );
+ assert_equals( testEl.properties[1], testEl.childNodes[1], 'properties[1] (after test)' );
+}, 'properties.item must update when re-ordering property elements, but length must not');
+test(function () {
+ var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div><div></div>');
+ assert_equals( testEl.properties.length, 1, 'length (before test)' );
+ assert_equals( testEl.properties[0], testEl.firstChild, 'properties[0] (before test)' );
+ testEl.lastChild.itemProp.toggle('bar');
+ assert_equals( testEl.properties.length, 2, 'length (after test 1)' );
+ assert_equals( testEl.properties.item(0), testEl.firstChild, 'properties.item(0) after adding a token' );
+ assert_equals( testEl.properties[0], testEl.firstChild, 'properties[0] after adding a token' );
+ assert_equals( testEl.properties.item(1), testEl.childNodes[1], 'properties.item(1) after adding a token' );
+ assert_equals( testEl.properties[1], testEl.childNodes[1], 'properties[1] after adding a token' );
+ testEl.lastChild.removeAttribute('itemprop');
+ assert_equals( testEl.properties.length, 1, 'length after removing an attribute' );
+ assert_equals( testEl.properties.item(0), testEl.firstChild, 'properties.item(0) after removing an attribute' );
+ assert_equals( testEl.properties[0], testEl.firstChild, 'properties[0] after removing an attribute' );
+ assert_true( !testEl.properties.item(1), 'properties.item(1) after removing an attribute' );
+ assert_true( !testEl.properties[1], 'properties[1] after removing an attribute' );
+}, 'properties.item and length must update when changing itemProp of children');
+test(function () {
+ var parEl = makeEl('div',{},'<div itemprop="foo"><div itemprop="bar"></div></div><div itemscope itemref="id1"></div>');
+ var testEl = parEl.childNodes[1];
+ assert_equals( testEl.properties.length, 0, 'length (before test)' );
+ parEl.firstChild.id = 'id1';
+ assert_equals( testEl.properties.length, 2, 'length after id is created' );
+ assert_equals( testEl.properties.item(0), parEl.firstChild, 'properties.item(0) after id is created' );
+ assert_equals( testEl.properties[0], parEl.firstChild, 'properties[0] after id is created' );
+ assert_equals( testEl.properties.item(1), parEl.firstChild.firstChild, 'properties.item(1) after id is created' );
+ assert_equals( testEl.properties[1], parEl.firstChild.firstChild, 'properties[1] after id is created' );
+ parEl.firstChild.removeAttribute('id');
+ assert_equals( testEl.properties.length, 0, 'length after removing an attribute' );
+ assert_true( !testEl.properties.item(0), 'properties.item(0) after removing an attribute' );
+ assert_true( !testEl.properties[0], 'properties[0] after removing an attribute' );
+ document.body.appendChild(parEl);
+ var beflength = testEl.properties.length;
+ parEl.firstChild.id = 'id1';
+ var length1 = testEl.properties.length,
+ item0 = testEl.properties.item(0),
+ prop0 = testEl.properties[0],
+ item1 = testEl.properties.item(1),
+ prop1 = testEl.properties[1];
+ parEl.firstChild.removeAttribute('id');
+ var length2 = testEl.properties.length,
+ bitem = !testEl.properties.item(0),
+ bprop = !testEl.properties[0];
+ document.body.removeChild(parEl);
+ assert_equals( beflength, 0, 'length (before test) when appended to document' );
+ assert_equals( length1, 2, 'length after id is created when appended to document' );
+ assert_equals( item0, parEl.firstChild, 'properties.item(0) after id is created when appended to document' );
+ assert_equals( prop0, parEl.firstChild, 'properties[0] after id is created when appended to document' );
+ assert_equals( item1, parEl.firstChild.firstChild, 'properties.item(1) after id is created when appended to document' );
+ assert_equals( prop1, parEl.firstChild.firstChild, 'properties[1] after id is created when appended to document' );
+ assert_equals( length2, 0, 'length after removing an attribute when appended to document' );
+ assert_true( bitem, 'properties.item(0) after removing an attribute when appended to document' );
+ assert_true( bprop, 'properties[0] after removing an attribute when appended to document' );
+}, 'properties.item and length must update when changing id of referenced sibling');
+test(function () {
+ var parEl = makeEl('div',{},'<div itemprop="foo"><div itemprop="bar"></div></div><div itemscope itemref="id1"></div><div itemprop="baz" id="id1"></div>');
+ var testEl = parEl.childNodes[1];
+ assert_equals( testEl.properties.length, 1, 'length (before test)' );
+ assert_equals( testEl.properties.item(0), parEl.lastChild, 'properties.item(0) (before test)' );
+ assert_equals( testEl.properties[0], parEl.lastChild, 'properties[0] (before test)' );
+ parEl.firstChild.id = 'id1';
+ assert_equals( testEl.properties.length, 2, 'length after id is created' );
+ assert_equals( testEl.properties.item(0), parEl.firstChild, 'properties.item(0) after id is created' );
+ assert_equals( testEl.properties[0], parEl.firstChild, 'properties[0] after id is created' );
+ assert_equals( testEl.properties.item(1), parEl.firstChild.firstChild, 'properties.item(1) after id is created' );
+ assert_equals( testEl.properties[1], parEl.firstChild.firstChild, 'properties[1] after id is created' );
+ parEl.firstChild.removeAttribute('id');
+ assert_equals( testEl.properties.length, 1, 'length after removing an attribute' );
+ assert_equals( testEl.properties.item(0), parEl.lastChild, 'properties.item(0) after removing an attribute' );
+ assert_equals( testEl.properties[0], parEl.lastChild, 'properties[0] after removing an attribute' );
+ document.body.appendChild(parEl);
+ var beflength = testEl.properties.length,
+ befitem = testEl.properties.item(0),
+ befprop = testEl.properties[0];
+ parEl.firstChild.id = 'id1';
+ var length1 = testEl.properties.length,
+ item0 = testEl.properties.item(0),
+ prop0 = testEl.properties[0],
+ item1 = testEl.properties.item(1),
+ prop1 = testEl.properties[1];
+ parEl.firstChild.removeAttribute('id');
+ var length2 = testEl.properties.length,
+ afitem = testEl.properties.item(0),
+ afprop = testEl.properties[0];
+ document.body.removeChild(parEl);
+ assert_equals( beflength, 1, 'length (before test) when appended to document' );
+ assert_equals( befitem, parEl.lastChild, 'properties.item(0) (before test)' );
+ assert_equals( befprop, parEl.lastChild, 'properties[0] (before test)' );
+ assert_equals( length1, 2, 'length after id is created when appended to document' );
+ assert_equals( item0, parEl.firstChild, 'properties.item(0) after id is created when appended to document' );
+ assert_equals( prop0, parEl.firstChild, 'properties[0] after id is created when appended to document' );
+ assert_equals( item1, parEl.firstChild.firstChild, 'properties.item(1) after id is created when appended to document' );
+ assert_equals( prop1, parEl.firstChild.firstChild, 'properties[1] after id is created when appended to document' );
+ assert_equals( length2, 1, 'length after removing an attribute when appended to document' );
+ assert_equals( afitem, parEl.lastChild, 'properties.item(0) after removing an attribute when appended to document' );
+ assert_equals( afprop, parEl.lastChild, 'properties[0] after removing an attribute when appended to document' );
+}, 'properties.item and length must update when changing duplicated id of referenced sibling');
+test(function () {
+ var parEl = makeEl('div',{},'<div id="id1" itemprop="foo"></div><div itemscope></div>');
+ var testEl = parEl.childNodes[1];
+ assert_equals( testEl.properties.length, 0, 'length (before test)' );
+ testEl.itemRef.toggle('id1');
+ assert_equals( testEl.properties.length, 1, 'length after itemref is changed' );
+ assert_equals( testEl.properties.item(0), parEl.firstChild, 'properties.item(0) after itemref is changed' );
+ assert_equals( testEl.properties[0], parEl.firstChild, 'properties[0] after itemref is changed' );
+ testEl.removeAttribute('itemref');
+ assert_equals( testEl.properties.length, 0, 'length after itemref is removed' );
+ assert_true( !testEl.properties.item(0), 'properties.item(0) itemref is removed' );
+ assert_true( !testEl.properties[0], 'properties[0] itemref is removed' );
+ document.body.appendChild(parEl);
+ var beflength = testEl.properties.length;
+ testEl.itemRef.toggle('id1');
+ var length1 = testEl.properties.length,
+ item0 = testEl.properties.item(0),
+ prop0 = testEl.properties[0];
+ testEl.removeAttribute('itemref');
+ var length2 = testEl.properties.length,
+ bitem = !testEl.properties.item(0),
+ bprop = !testEl.properties[0];
+ document.body.removeChild(parEl);
+ assert_equals( beflength, 0, 'length (before test) when appended to document' );
+ assert_equals( length1, 1, 'length after itemref is changed when appended to document' );
+ assert_equals( item0, parEl.firstChild, 'properties.item(0) after itemref is changed when appended to document' );
+ assert_equals( prop0, parEl.firstChild, 'properties[0] after itemref is changed when appended to document' );
+ assert_equals( length2, 0, 'length after itemref is removed when appended to document' );
+ assert_true( bitem, 'properties.item(0) after itemref is removed when appended to document' );
+ assert_true( bprop, 'properties[0] after itemref is removed when appended to document' );
+}, 'properties.item and length must update when changing itemref to point to an element');
+test(function () {
+ var parEl = makeEl('div',{},'<div id="id1"><div></div></div><div itemscope itemref="id1"></div>');
+ var testEl = parEl.childNodes[1];
+ assert_equals( testEl.properties.length, 0, 'length (before test)' );
+ parEl.firstChild.appendChild(makeEl('div',{itemprop:'foo'}));
+ assert_equals( testEl.properties.length, 1, 'length after a referenced element is added' );
+ assert_equals( testEl.properties.item(0), parEl.firstChild.lastChild, 'properties.item(0) after a referenced element is added' );
+ assert_equals( testEl.properties[0], parEl.firstChild.lastChild, 'properties[0] after a referenced element is added' );
+ parEl.firstChild.firstChild.itemProp.toggle('bar');
+ assert_equals( testEl.properties.length, 2, 'length after a referenced itemprop is changed' );
+ assert_equals( testEl.properties.item(0), parEl.firstChild.firstChild, 'properties.item(0) after a referenced itemprop is changed' );
+ assert_equals( testEl.properties[0], parEl.firstChild.firstChild, 'properties[0] after a referenced itemprop is changed' );
+ assert_equals( testEl.properties.item(1), parEl.firstChild.lastChild, 'properties.item(1) after a referenced itemprop is changed' );
+ assert_equals( testEl.properties[1], parEl.firstChild.lastChild, 'properties[1] after a referenced itemprop is changed' );
+ parEl.firstChild.removeChild(parEl.firstChild.firstChild);
+ assert_equals( testEl.properties.length, 1, 'length after a referenced element is removed' );
+ assert_equals( testEl.properties.item(0), parEl.firstChild.firstChild, 'properties.item(0) after a referenced element is removed' );
+ assert_equals( testEl.properties[0], parEl.firstChild.firstChild, 'properties[0] after a referenced element is removed' );
+ assert_true( !testEl.properties.item(1), 'properties.item(1) after a referenced element is removed' );
+ assert_true( !testEl.properties[1], 'properties[1] after a referenced element is removed' );
+ parEl.innerHTML = '<div id="id1"><div></div></div><div itemscope itemref="id1"></div>';
+ testEl = parEl.childNodes[1];
+ document.body.appendChild(parEl);
+ var beflength = testEl.properties.length;
+ parEl.firstChild.appendChild(makeEl('div',{itemprop:'foo'}));
+ var length1 = testEl.properties.length,
+ item0a = testEl.properties.item(0),
+ prop0a = testEl.properties[0],
+ targ0a = parEl.firstChild.lastChild;
+ parEl.firstChild.firstChild.itemProp.toggle('bar');
+ var length2 = testEl.properties.length,
+ item0b = testEl.properties.item(0),
+ prop0b = testEl.properties[0];
+ item1b = testEl.properties.item(1),
+ prop1b = testEl.properties[1],
+ targ0b = parEl.firstChild.firstChild,
+ targ1b = parEl.firstChild.lastChild;
+ parEl.firstChild.removeChild(parEl.firstChild.firstChild);
+ var length3 = testEl.properties.length,
+ item0c = testEl.properties.item(0),
+ prop0c = testEl.properties[0];
+ item1c = testEl.properties.item(1),
+ prop1c = testEl.properties[1],
+ targ0c = parEl.firstChild.firstChild;
+ document.body.removeChild(parEl);
+ assert_equals( beflength, 0, 'length (before test) when appended to document' );
+ assert_equals( length1, 1, 'length after a referenced element is added when appended to document' );
+ assert_equals( item0a, targ0a, 'properties.item(0) after a referenced element is added when appended to document' );
+ assert_equals( prop0a, targ0a, 'properties[0] after a referenced element is added when appended to document' );
+ assert_equals( length2, 2, 'length after a referenced itemprop is changed when appended to document' );
+ assert_equals( item0b, targ0b, 'properties.item(0) after a referenced itemprop is changed when appended to document' );
+ assert_equals( prop0b, targ0b, 'properties[0] after a referenced itemprop is changed when appended to document' );
+ assert_equals( item1b, targ1b, 'properties.item(1) after a referenced itemprop is changed when appended to document' );
+ assert_equals( prop1b, targ1b, 'properties[1] after a referenced itemprop is changed when appended to document' );
+ assert_equals( length3, 1, 'length after a referenced element is removed when appended to document' );
+ assert_equals( item0c, targ0c, 'properties.item(0) after a referenced element is removed when appended to document' );
+ assert_equals( prop0c, targ0c, 'properties[0] after a referenced element is removed when appended to document' );
+ assert_true( !item1c, 'properties.item(1) after a referenced element is removed when appended to document' );
+ assert_true( !prop1c, 'properties[1] after a referenced element is removed when appended to document' );
+}, 'properties.item and length must update when changing children of elements referenced through itemref');
+test(function () {
+ var parEl = makeEl('div',{},'<div id="id1" itemprop="foo"></div><div itemscope itemref="id1"><div itemprop="foo"></div></div>');
+ var testEl = parEl.childNodes[1];
+ assert_equals( testEl.properties.length, 2, 'length (before test)' );
+ assert_equals( testEl.properties[0], parEl.firstChild, 'properties[0] (before test)' );
+ assert_equals( testEl.properties[1], testEl.firstChild, 'properties[1] (before test)' );
+ document.body.appendChild(testEl);
+ var step1length = testEl.properties.length;
+ var step1prop0 = testEl.properties[0];
+ var step1prop1 = testEl.properties[1];
+ parEl.appendChild(testEl);
+ assert_equals( step1length, 1, 'length after changing parent' );
+ assert_equals( step1prop0, testEl.firstChild, 'properties[0] after changing parent' );
+ assert_true( !step1prop1, 'properties[1] after changing parent' );
+ assert_equals( testEl.properties.length, 2, 'length after re-parenting' );
+ assert_equals( testEl.properties[0], parEl.firstChild, 'properties[0] after re-parenting' );
+ assert_equals( testEl.properties[1], testEl.firstChild, 'properties[1] after re-parenting' );
+ document.body.appendChild(parEl);
+ var step2length = testEl.properties.length;
+ var step2prop0 = testEl.properties[0];
+ var step2prop1 = testEl.properties[1];
+ document.createElement('div').appendChild(testEl);
+ var step3length = testEl.properties.length;
+ var step3prop0 = testEl.properties[0];
+ var step3prop1 = testEl.properties[1];
+ parEl.appendChild(testEl);
+ var step4length = testEl.properties.length;
+ var step4prop0 = testEl.properties[0];
+ var step4prop1 = testEl.properties[1];
+ document.body.removeChild(parEl);
+ assert_equals( step2length, 2, 'length (before test) when appended to document' );
+ assert_equals( step2prop0, parEl.firstChild, 'properties[0] (before test) when appended to document' );
+ assert_equals( step2prop1, testEl.firstChild, 'properties[1] (before test) when appended to document' );
+ assert_equals( step3length, 1, 'length after changing parent when appended to document' );
+ assert_equals( step3prop0, testEl.firstChild, 'properties[0] after changing parent when appended to document' );
+ assert_true( !step3prop1, 'properties[1] after changing parent when appended to document' );
+ assert_equals( step4length, 2, 'length after re-parenting when appended to document' );
+ assert_equals( step4prop0, parEl.firstChild, 'properties[0] after re-parenting when appended to document' );
+ assert_equals( step4prop1, testEl.firstChild, 'properties[1] after re-parenting when appended to document' );
+}, 'properties.item and length must update when appending elements with itemref to different parents');
+test(function () {
+ var testEl = makeEl('div',{itemscope:'itemscope'},'<div><div itemprop="foo"></div></div>');
+ assert_equals( testEl.properties.length, 1, 'length (before test)' );
+ assert_equals( testEl.properties.item(0), testEl.firstChild.firstChild, 'properties.item(0) (before test)' );
+ assert_equals( testEl.properties[0], testEl.firstChild.firstChild, 'properties[0] (before test)' );
+ testEl.firstChild.itemScope = true;
+ assert_equals( testEl.properties.length, 0, 'length after setting itemscope' );
+ assert_true( !testEl.properties.item(0), 'properties.item(0) after setting itemscope' );
+ assert_true( !testEl.properties[0], 'properties[0] after setting itemscope' );
+ testEl.firstChild.removeAttribute('itemscope');
+ assert_equals( testEl.properties.length, 1, 'length after removing itemscope attribute' );
+ assert_equals( testEl.properties.item(0), testEl.firstChild.firstChild, 'properties.item(0) after removing itemscope attribute' );
+ assert_equals( testEl.properties[0], testEl.firstChild.firstChild, 'properties[0] after removing itemscope attribute' );
+}, 'properties.item and length must update when changing itemscope of children');
+//properties.namedItem
+test(function () {
+ assert_equals( typeof makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div>').properties.namedItem('foo'), 'object' );
+}, 'the namedItem must return an object');
+test(function () {
+ assert_equals( typeof makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div>').properties['foo'], 'object' );
+}, '.properties[] must also act as .properties.namedItem() when there are matching properties');
+test(function () {
+ assert_equals( typeof makeEl('div',{itemscope:'itemscope'},'').properties.namedItem('foo'), 'object' );
+}, 'the namedItem must return an object even if there are no matching properties');
+test(function () {
+ assert_equals( typeof makeEl('div',{itemscope:'itemscope'},'').properties['foo'], 'undefined' );
+}, '.properties[] must return undefined when no property exists with the given name');
+test(function () {
+ var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div>');
+ var PNL = testEl.properties.namedItem('foo');
+ assert_equals( PNL, testEl.properties.namedItem('foo'), 'before modification' );
+ testEl.innerHTML = '';
+ assert_equals( PNL, testEl.properties.namedItem('foo'), 'after modification' );
+}, 'namedItem must return the same object for the same property name');
+test(function () {
+ var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div>');
+ assert_false( testEl.properties.namedItem('foo') == testEl.properties.namedItem('bar') );
+}, 'namedItem must return a different object for a different property name');
+test(function () {
+ assert_false( makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div>').properties.namedItem('foo') == makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div>').properties.namedItem('foo') );
+}, 'namedItem must return a different object for different elements with the same property name');
+test(function () {
+ var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div>');
+ assert_equals( testEl.properties.namedItem('foo'), testEl.properties['foo'] );
+}, 'namedItem() and properties[] must return the same object for the same property name');
+test(function () {
+ var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div>');
+ assert_true( testEl.properties.namedItem('foo') instanceof PropertyNodeList, 'instanceof PropertyNodeList' );
+ assert_true( testEl.properties.namedItem('foo') instanceof NodeList, 'instanceof NodeList' );
+ PropertyNodeList.prototype.customProperty = true;
+ NodeList.prototype.anotherCustomProperty = true;
+ assert_true( testEl.properties.namedItem('foo').customProperty, 'inheritance from PropertyNodeList' );
+ assert_true( testEl.properties.namedItem('foo').anotherCustomProperty, 'inheritance from NodeList' );
+ PropertyNodeList.prototype.anotherCustomProperty = false;
+ assert_false( testEl.properties.anotherCustomProperty, 'shadowing by PropertyNodeList' );
+}, 'the properties property must implement PropertyNodeList and NodeList');
+test(function () {
+ var failed = false, elem = makeEl('div',{itemscope:'itemscope'});
+ try {
+ elem.properties.namedItem = 'pass';
+ } catch(e) {
+ failed = e;
+ }
+ assert_equals(elem.properties.namedItem,'pass');
+ assert_false(failed,'an error was thrown');
+}, 'the namedItem property must be read/write');
+test(function () {
+ //also tests for sort ordering, which is fairly simple in this case
+ var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div><div itemprop="bar"><div itemprop="baz qux"></div></div><div itemprop="foo"></div>');
+ assert_equals( testEl.properties.namedItem('foo').length, 2, 'length of foo' );
+ assert_equals( testEl.properties.namedItem('bar').length, 1, 'length of bar' );
+ assert_equals( testEl.properties.namedItem('baz').length, 1, 'length of baz' );
+ assert_equals( testEl.properties.namedItem('qux').length, 1, 'length of qux' );
+ assert_equals( testEl.properties.namedItem('foo')[0], testEl.firstChild, 'first foo' );
+ assert_equals( testEl.properties.namedItem('foo')[1], testEl.lastChild, 'last foo' );
+ assert_equals( testEl.properties.namedItem('bar')[0], testEl.childNodes[1], 'bar' );
+ assert_equals( testEl.properties.namedItem('baz')[0], testEl.childNodes[1].firstChild, 'baz' );
+ assert_equals( testEl.properties.namedItem('qux')[0], testEl.childNodes[1].firstChild, 'qux' );
+}, 'PropertyNodeList must contain the correct properties');
+test(function () {
+ var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div><div itemprop="bar"><div itemprop="FOO"></div><div itemprop="foo FOO foo"></div></div><div itemprop="baz qux"></div>');
+ assert_equals( testEl.properties.namedItem('foo').length, 2, 'length of foo' );
+ assert_equals( testEl.properties.namedItem('FOO').length, 2, 'length of FOO' );
+ assert_equals( testEl.properties.namedItem('foo')[0], testEl.firstChild, 'first foo' );
+ assert_equals( testEl.properties.namedItem('foo')[1], testEl.childNodes[1].lastChild, 'last foo' );
+ assert_equals( testEl.properties.namedItem('FOO')[0], testEl.childNodes[1].firstChild, 'first FOO' );
+ assert_equals( testEl.properties.namedItem('FOO')[1], testEl.childNodes[1].lastChild, 'last FOO' );
+}, 'PropertyNodeList must be case sensitive');
+test(function () {
+ var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo bar"></div>');
+ assert_equals( testEl.properties.namedItem('foo bar').length, 0, 'space' );
+ testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo\tbar"></div>');
+ assert_equals( testEl.properties.namedItem('foo\tbar').length, 0, 'tab' );
+ testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo\rbar"></div>');
+ assert_equals( testEl.properties.namedItem('foo\rbar').length, 0, 'carriage return' );
+ testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo\nbar"></div>');
+ assert_equals( testEl.properties.namedItem('foo\nbar').length, 0, 'newline' );
+ testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo\fbar"></div>');
+ assert_equals( testEl.properties.namedItem('foo\fbar').length, 0, 'formfeed' );
+}, 'namedItem must not match property names containing whitespace');
+test(function () {
+ var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="|§!&quot;#¤%&/()=?`\\@£${[]}´€^¨~\'*,;.:-_&lt;&gt;帿ŨÆ"></div>');
+ assert_equals( testEl.properties.namedItem('|§!"#¤%&/()=?`\\@£${[]}´€^¨~\'*,;.:-_<>帿ŨÆ').length, 1 );
+}, 'namedItem must match property names containing other special characters');
+test(function () {
+ var testEl = makeEl('div',{itemscope:'itemscope'});
+ var PNL = testEl.properties.namedItem('foo');
+ testEl.innerHTML = '<div itemprop="foo"></div>';
+ assert_equals( PNL.length, 1 );
+ assert_equals( PNL[0], testEl.firstChild );
+}, 'PropertyNodeList must be live');
+test(function () {
+ var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div><div itemscope><div itemprop="foo"></div><div itemprop="bar"></div></div>');
+ assert_equals( testEl.properties.namedItem('foo').length, 1, 'length of foo' );
+ assert_equals( testEl.properties.namedItem('foo')[0], testEl.firstChild, 'item 0' );
+ assert_equals( testEl.properties.namedItem('bar').length, 0, 'length of bar' );
+}, 'PropertyNodeList must ignore properties of nested items');
+test(function () {
+
+ //note, itemref ordering is reversed compared with the next test to catch failed sorting algorithms - not that that should make much difference here
+ var parEl = makeEl('div',{},'<div itemprop="foo" id="id1"></div><div itemscope itemref="id2 id1"><div itemprop="foo bar"></div></div><div itemprop="baz" id="id2"><div itemprop="qux"></div></div>');
+ var testEl = parEl.childNodes[1];
+ document.body.appendChild(parEl);
+ var fooLength = testEl.properties.namedItem('foo').length;
+ var barLength = testEl.properties.namedItem('bar').length;
+ var bazLength = testEl.properties.namedItem('baz').length;
+ var quxLength = testEl.properties.namedItem('qux').length;
+ var foo0 = testEl.properties.namedItem('foo')[0];
+ var foo1 = testEl.properties.namedItem('foo')[1];
+ var bar0 = testEl.properties.namedItem('bar')[0];
+ var baz0 = testEl.properties.namedItem('baz')[0];
+ var qux0 = testEl.properties.namedItem('qux')[0];
+ document.body.removeChild(parEl);
+ assert_equals( fooLength, 2, 'foo length' );
+ assert_equals( barLength, 1, 'bar length' );
+ assert_equals( bazLength, 1, 'baz length' );
+ assert_equals( quxLength, 1, 'qux length' );
+ assert_equals( foo0, parEl.firstChild, 'foo 0' );
+ assert_equals( foo1, testEl.firstChild, 'foo 1' );
+ assert_equals( bar0, testEl.firstChild, 'bar 0' );
+ assert_equals( baz0, parEl.lastChild, 'baz 0' );
+ assert_equals( qux0, parEl.lastChild.firstChild, 'qux 0' );
+}, 'PropertyNodeList must see items added with itemref when attached to the document\'s DOM');
+test(function () {
+ var parEl = makeEl('div',{},'<div itemprop="foo" id="id1"></div><div itemscope itemref="id1 id2"><div itemprop="foo bar"></div></div><div itemprop="baz" id="id2"><div itemprop="qux"></div></div>');
+ var testEl = parEl.childNodes[1];
+ assert_equals( testEl.properties.namedItem('foo').length, 2, 'foo length' );
+ assert_equals( testEl.properties.namedItem('bar').length, 1, 'bar length' );
+ assert_equals( testEl.properties.namedItem('baz').length, 1, 'baz length' );
+ assert_equals( testEl.properties.namedItem('qux').length, 1, 'qux length' );
+ assert_equals( testEl.properties.namedItem('foo')[0], parEl.firstChild, 'foo 0' );
+ assert_equals( testEl.properties.namedItem('foo')[1], testEl.firstChild, 'foo 1' );
+ assert_equals( testEl.properties.namedItem('bar')[0], testEl.firstChild, 'bar 0' );
+ assert_equals( testEl.properties.namedItem('baz')[0], parEl.lastChild, 'baz 0' );
+ assert_equals( testEl.properties.namedItem('qux')[0], parEl.lastChild.firstChild, 'qux 0' );
+}, 'PropertyNodeList must see items added with itemref');
+test(function () {
+ //this one also tests the live object just in case - further ones will not always do this as its live status will already have been well established
+ var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div>');
+ var PNL = testEl.properties.namedItem('foo');
+ testEl.removeAttribute('itemscope');
+ assert_equals( testEl.properties.namedItem('foo').length, 0, 'removing attribute' );
+ assert_equals( PNL.length, 0, 'removing attribute (live)' );
+ assert_true( !testEl.properties['foo'], 'removing attribute []' );
+ testEl.itemScope = true;
+ assert_equals( testEl.properties.namedItem('foo').length, 1, 'setting itemScope' );
+ assert_equals( testEl.properties.namedItem('foo')[0], testEl.firstChild, 'property 0 after setting itemScope' );
+ assert_equals( PNL.length, 1, 'setting itemScope (live)' );
+ assert_equals( PNL[0], testEl.firstChild, 'property 0 after setting itemScope (live)' );
+ assert_false( !testEl.properties['foo'], 'setting itemScope []' );
+}, 'PropertyNodeList must update when adding itemscope on the root');
+test(function () {
+ var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div>');
+ assert_equals( testEl.properties.namedItem('foo').length, 1, 'foo length (before test)' );
+ assert_equals( testEl.properties.namedItem('foo')[0], testEl.firstChild, 'foo 0 (before test)' );
+ assert_equals( testEl.properties.namedItem('bar').length, 0, 'bar length (before test)' );
+ testEl.appendChild(makeEl('div',{itemprop:'bar'}));
+ assert_equals( testEl.properties.namedItem('foo').length, 1, 'foo length after adding a child' );
+ assert_equals( testEl.properties.namedItem('foo')[0], testEl.firstChild, 'foo 0 after adding a child' );
+ assert_equals( testEl.properties.namedItem('bar').length, 1, 'bar length after adding a child' );
+ assert_equals( testEl.properties.namedItem('bar')[0], testEl.lastChild, 'bar 0 after adding a child' );
+ testEl.lastChild.appendChild(makeEl('div',{itemprop:'foo'}));
+ assert_equals( testEl.properties.namedItem('foo').length, 2, 'foo length after adding a child with duplicated name' );
+ assert_equals( testEl.properties.namedItem('foo')[0], testEl.firstChild, 'foo 0 after adding a child with duplicated name' );
+ assert_equals( testEl.properties.namedItem('foo')[1], testEl.lastChild.firstChild, 'foo 1 after adding a child with duplicated name' );
+ assert_equals( testEl.properties.namedItem('bar').length, 1, 'bar length after adding a child with duplicated name' );
+ assert_equals( testEl.properties.namedItem('bar')[0], testEl.lastChild, 'bar 0 after adding a child with duplicated name' );
+ testEl.lastChild.removeChild(testEl.lastChild.firstChild);
+ assert_equals( testEl.properties.namedItem('foo').length, 1, 'foo length after removing a child' );
+ assert_equals( testEl.properties.namedItem('bar').length, 1, 'bar length after removing a child' );
+}, 'PropertyNodeList must update when adding property elements');
+test(function () {
+ var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div><div itemprop="foo"></div>');
+ var PNL = testEl.properties.namedItem('foo');
+ assert_equals( PNL[0], testEl.firstChild, 'item 0 (before test)' );
+ assert_equals( PNL[1], testEl.lastChild, 'item 1 (before test)' );
+ testEl.appendChild(testEl.firstChild);
+ assert_equals( PNL[0], testEl.firstChild, 'item 0 (after test)' );
+ assert_equals( PNL[1], testEl.lastChild, 'item 1 (after test)' );
+}, 'PropertyNodeList must update when re-ordering property elements');
+test(function () {
+ var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div><div></div>');
+ var PNLfoo = testEl.properties.namedItem('foo'), PNLbar = testEl.properties.namedItem('bar');
+ assert_equals( PNLfoo.length, 1, 'foo length (before test)' );
+ assert_equals( PNLbar.length, 0, 'bar length (before test)' );
+ assert_equals( PNLfoo[0], testEl.firstChild, 'foo[0] (before test)' );
+ testEl.lastChild.itemProp.toggle('bar');
+ assert_equals( PNLfoo.length, 1, 'foo length after adding a token' );
+ assert_equals( PNLbar.length, 1, 'bar length after adding a token' );
+ assert_equals( PNLfoo[0], testEl.firstChild, 'foo[0] after adding a token' );
+ assert_equals( PNLbar[0], testEl.lastChild, 'bar[0] after adding a token' );
+ testEl.lastChild.itemProp.add('foo');
+ assert_equals( PNLfoo.length, 2, 'foo length after adding a duplicated token' );
+ assert_equals( PNLbar.length, 1, 'bar length after adding a duplicated token' );
+ assert_equals( PNLfoo[0], testEl.firstChild, 'foo[0] after adding a duplicated token' );
+ assert_equals( PNLfoo[1], testEl.lastChild, 'foo[1] after adding a duplicated token' );
+ assert_equals( PNLbar[0], testEl.lastChild, 'bar[0] after adding a duplicated token' );
+ testEl.lastChild.removeAttribute('itemprop');
+ assert_equals( PNLfoo.length, 1, 'foo length after removing an attribute' );
+ assert_equals( PNLbar.length, 0, 'bar length after removing an attribute' );
+ assert_equals( PNLfoo[0], testEl.firstChild, 'foo[0] after removing an attribute' );
+}, 'PropertyNodeList must update when changing itemProp of children');
+test(function () {
+ var parEl = makeEl('div',{},'<div itemprop="foo"><div itemprop="bar"></div></div><div itemscope itemref="id1"></div>');
+ var testEl = parEl.childNodes[1];
+ var PNLfoo = testEl.properties.namedItem('foo'), PNLbar = testEl.properties.namedItem('bar');
+ assert_equals( PNLfoo.length, 0, 'foo length (before test)' );
+ assert_equals( PNLbar.length, 0, 'bar length (before test)' );
+ parEl.firstChild.id = 'id1';
+ assert_equals( PNLfoo.length, 1, 'foo length after id is created' );
+ assert_equals( PNLbar.length, 1, 'bar length after id is created' );
+ assert_equals( PNLfoo[0], parEl.firstChild, 'foo[0] after id is created' );
+ assert_equals( PNLbar[0], parEl.firstChild.firstChild, 'bar[0] after id is created' );
+ parEl.firstChild.removeAttribute('id');
+ assert_equals( PNLfoo.length, 0, 'foo length after removing an attribute' );
+ assert_equals( PNLbar.length, 0, 'bar length after removing an attribute' );
+ document.body.appendChild(parEl);
+ var fooLength0 = PNLfoo.length;
+ var barLength0 = PNLbar.length;
+ parEl.firstChild.id = 'id1';
+ var fooLength1 = PNLfoo.length;
+ var barLength1 = PNLbar.length;
+ var foo0 = PNLfoo[0];
+ var bar0 = PNLbar[0];
+ parEl.firstChild.removeAttribute('id');
+ var fooLength2 = PNLfoo.length;
+ var barLength2 = PNLbar.length;
+ document.body.removeChild(parEl);
+ assert_equals( fooLength0, 0, 'foo length (before test) when appended to document' );
+ assert_equals( barLength0, 0, 'bar length (before test) when appended to document' );
+ assert_equals( fooLength1, 1, 'foo length after id is created when appended to document' );
+ assert_equals( barLength1, 1, 'bar length after id is created when appended to document' );
+ assert_equals( foo0, parEl.firstChild, 'foo[0] after id is created when appended to document' );
+ assert_equals( bar0, parEl.firstChild.firstChild, 'bar[0] after id is created when appended to document' );
+ assert_equals( fooLength2, 0, 'foo length after removing an attribute when appended to document' );
+ assert_equals( barLength2, 0, 'bar length after removing an attribute when appended to document' );
+}, 'PropertyNodeList must update when changing id of referenced sibling');
+test(function () {
+ var parEl = makeEl('div',{},'<div itemprop="foo"><div itemprop="bar"></div></div><div itemscope itemref="id1"></div><div itemprop="baz" id="id1"></div>');
+ var testEl = parEl.childNodes[1];
+ var PNLfoo = testEl.properties.namedItem('foo'), PNLbar = testEl.properties.namedItem('bar'), PNLbaz = testEl.properties.namedItem('baz');
+ assert_equals( PNLfoo.length, 0, 'foo length (before test)' );
+ assert_equals( PNLbar.length, 0, 'bar length (before test)' );
+ assert_equals( PNLbaz.length, 1, 'baz length (before test)' );
+ assert_equals( PNLbaz[0], parEl.lastChild, 'baz[0] (before test)' );
+ parEl.firstChild.id = 'id1';
+ assert_equals( PNLfoo.length, 1, 'foo length after id is created' );
+ assert_equals( PNLbar.length, 1, 'bar length after id is created' );
+ assert_equals( PNLbaz.length, 0, 'baz length after id is created' );
+ assert_equals( PNLfoo[0], parEl.firstChild, 'foo[0] after id is created' );
+ assert_equals( PNLbar[0], parEl.firstChild.firstChild, 'bar[0] after id is created' );
+ parEl.firstChild.removeAttribute('id');
+ assert_equals( PNLfoo.length, 0, 'foo length after removing an attribute' );
+ assert_equals( PNLbar.length, 0, 'bar length after removing an attribute' );
+ assert_equals( PNLbaz.length, 1, 'baz length after removing an attribute' );
+ assert_equals( PNLbaz[0], parEl.lastChild, 'baz[0] after removing an attribute' );
+ document.body.appendChild(parEl);
+ var fooLength0 = PNLfoo.length;
+ var barLength0 = PNLbar.length;
+ var bazLength0 = PNLbaz.length;
+ var baz0 = PNLbaz[0];
+ parEl.firstChild.id = 'id1';
+ var fooLength1 = PNLfoo.length;
+ var barLength1 = PNLbar.length;
+ var bazLength1 = PNLbaz.length;
+ var foo0 = PNLfoo[0];
+ var bar0 = PNLbar[0];
+ parEl.firstChild.removeAttribute('id');
+ var fooLength2 = PNLfoo.length;
+ var barLength2 = PNLbar.length;
+ var bazLength2 = PNLbaz.length;
+ var baz1 = PNLbaz[0];
+ document.body.removeChild(parEl);
+ assert_equals( fooLength0, 0, 'foo length (before test) when appended to document' );
+ assert_equals( barLength0, 0, 'bar length (before test) when appended to document' );
+ assert_equals( bazLength0, 1, 'baz length (before test)' );
+ assert_equals( baz0, parEl.lastChild, 'baz[0] (before test)' );
+ assert_equals( fooLength1, 1, 'foo length after id is created when appended to document' );
+ assert_equals( barLength1, 1, 'bar length after id is created when appended to document' );
+ assert_equals( bazLength1, 0, 'baz length after id is created' );
+ assert_equals( foo0, parEl.firstChild, 'foo[0] after id is created when appended to document' );
+ assert_equals( bar0, parEl.firstChild.firstChild, 'bar[0] after id is created when appended to document' );
+ assert_equals( fooLength2, 0, 'foo length after removing an attribute when appended to document' );
+ assert_equals( barLength2, 0, 'bar length after removing an attribute when appended to document' );
+ assert_equals( bazLength2, 1, 'baz length after removing an attribute' );
+ assert_equals( baz0, parEl.lastChild, 'baz[0] after removing an attribute' );
+}, 'PropertyNodeList must update when changing duplicated id of referenced sibling');
+test(function () {
+ var parEl = makeEl('div',{},'<div id="id1" itemprop="foo"></div><div itemscope></div>');
+ var testEl = parEl.childNodes[1];
+ var PNL = testEl.properties.namedItem('foo');
+ assert_equals( PNL.length, 0, 'length (before test)' );
+ testEl.itemRef.toggle('id1');
+ assert_equals( PNL.length, 1, 'length after itemref is changed' );
+ assert_equals( PNL[0], parEl.firstChild, 'item 0 after itemref is changed' );
+ testEl.removeAttribute('itemref');
+ assert_equals( PNL.length, 0, 'length after itemref is removed' );
+ assert_true( !PNL[0], 'item 0 after itemref is removed' );
+ document.body.appendChild(parEl);
+ var length0 = PNL.length;
+ testEl.itemRef.toggle('id1');
+ var length1 = PNL.length;
+ var foo0 = PNL[0];
+ testEl.removeAttribute('itemref');
+ var length2 = PNL.length;
+ var foo1 = PNL[0];
+ document.body.removeChild(parEl);
+ assert_equals( length0, 0, 'length (before test) when appended to document' );
+ assert_equals( length1, 1, 'length after itemref is changed when appended to document' );
+ assert_equals( foo0, parEl.firstChild, 'item 0 after itemref is changed when appended to document' );
+ assert_equals( length2, 0, 'length after itemref is removed when appended to document' );
+ assert_true( !foo1, 'item 0 after itemref is removed when appended to document' );
+}, 'PropertyNodeList must update when changing itemref to point to an element');
+test(function () {
+ var parEl = makeEl('div',{},'<div id="id1"><div></div></div><div itemscope itemref="id1"></div>');
+ var testEl = parEl.childNodes[1];
+ var PNLfoo = testEl.properties.namedItem('foo'), PNLbar = testEl.properties.namedItem('bar');
+ assert_equals( PNLfoo.length, 0, 'foo length (before test)' );
+ assert_equals( PNLbar.length, 0, 'bar length (before test)' );
+ parEl.firstChild.appendChild(makeEl('div',{itemprop:'foo'}));
+ assert_equals( PNLfoo.length, 1, 'foo length after a referenced element is added' );
+ assert_equals( PNLbar.length, 0, 'bar length after a referenced element is added' );
+ assert_equals( PNLfoo.item(0), parEl.firstChild.lastChild, 'foo 0 after a referenced element is added' ); //uses item just for the fun of it
+ parEl.firstChild.firstChild.itemProp.toggle('bar');
+ assert_equals( PNLfoo.length, 1, 'foo length after a referenced itemprop is changed' );
+ assert_equals( PNLbar.length, 1, 'bar length after a referenced itemprop is changed' );
+ assert_equals( PNLfoo[0], parEl.firstChild.lastChild, 'foo 0 after a referenced element is added' );
+ assert_equals( PNLbar[0], parEl.firstChild.firstChild, 'bar 0 after a referenced element is added' );
+ parEl.firstChild.removeChild(parEl.firstChild.firstChild);
+ assert_equals( PNLfoo.length, 1, 'foo length after a referenced element is removed' );
+ assert_equals( PNLbar.length, 0, 'bar length after a referenced element is removed' );
+ assert_equals( PNLfoo[0], parEl.firstChild.firstChild, 'foo 0 after a referenced element is removed' );
+ assert_true( !PNLbar[0], 'bar 0 after a referenced element is removed' );
+ parEl.innerHTML = '<div id="id1"><div></div></div><div itemscope itemref="id1"></div>';
+ testEl = parEl.childNodes[1];
+ PNLfoo = testEl.properties.namedItem('foo');
+ PNLbar = testEl.properties.namedItem('bar');
+ document.body.appendChild(parEl);
+ var step1fooLength = PNLfoo.length;
+ var step1barLength = PNLbar.length;
+ parEl.firstChild.appendChild(makeEl('div',{itemprop:'foo'}));
+ var step2fooLength = PNLfoo.length;
+ var step2barLength = PNLbar.length;
+ var step2foo0 = PNLfoo.item(0); //uses item just for the fun of it
+ var step2fooExpected = parEl.firstChild.lastChild;
+ parEl.firstChild.firstChild.itemProp.toggle('bar');
+ var step3fooLength = PNLfoo.length;
+ var step3barLength = PNLbar.length;
+ var step3foo0 = PNLfoo[0];
+ var step3bar0 = PNLbar[0];
+ var step3fooExpected = parEl.firstChild.lastChild;
+ var step3barExpected = parEl.firstChild.firstChild;
+ parEl.firstChild.removeChild(parEl.firstChild.firstChild);
+ var step4fooLength = PNLfoo.length;
+ var step4barLength = PNLbar.length;
+ var step4foo0 = PNLfoo[0];
+ var step4bar0 = PNLbar[0];
+ var step4fooExpected = parEl.firstChild.firstChild;
+ document.body.removeChild(parEl);
+ assert_equals( step1fooLength, 0, 'foo length (before test) when appended to document' );
+ assert_equals( step1barLength, 0, 'bar length (before test) when appended to document' );
+ assert_equals( step2fooLength, 1, 'foo length after a referenced element is added when appended to document' );
+ assert_equals( step2barLength, 0, 'bar length after a referenced element is added when appended to document' );
+ assert_equals( step2foo0, step2fooExpected, 'foo 0 after a referenced element is added when appended to document' );
+ assert_equals( step3fooLength, 1, 'foo length after a referenced itemprop is changed when appended to document' );
+ assert_equals( step3barLength, 1, 'bar length after a referenced itemprop is changed when appended to document' );
+ assert_equals( step3foo0, step3fooExpected, 'foo 0 after a referenced element is added when appended to document' );
+ assert_equals( step3bar0, step3barExpected, 'bar 0 after a referenced element is added when appended to document' );
+ assert_equals( step4fooLength, 1, 'foo length after a referenced element is removed when appended to document' );
+ assert_equals( step4barLength, 0, 'bar length after a referenced element is removed when appended to document' );
+ assert_equals( step4foo0, step4fooExpected, 'foo 0 after a referenced element is removed when appended to document' );
+ assert_true( !step4bar0, 'bar 0 after a referenced element is removed when appended to document' );
+}, 'PropertyNodeList must update when changing children of elements referenced through itemref');
+test(function () {
+ var parEl = makeEl('div',{},'<div id="id1" itemprop="foo"></div><div itemscope itemref="id1"><div itemprop="foo"></div></div>');
+ var testEl = parEl.childNodes[1];
+ var PNL = testEl.properties.namedItem('foo');
+ assert_equals( PNL.length, 2, 'length (before test)' );
+ assert_equals( PNL[0], parEl.firstChild, 'item 0 (before test)' );
+ assert_equals( PNL[1], testEl.firstChild, 'item 1 (before test)' );
+ document.body.appendChild(testEl);
+ var step1length = PNL.length;
+ var step1prop0 = PNL[0];
+ var step1prop1 = PNL[1];
+ parEl.appendChild(testEl);
+ assert_equals( step1length, 1, 'length after changing parent' );
+ assert_equals( step1prop0, testEl.firstChild, 'item 0 after changing parent' );
+ assert_true( !step1prop1, 'item 1 after changing parent' );
+ assert_equals( PNL.length, 2, 'length after re-parenting' );
+ assert_equals( PNL[0], parEl.firstChild, 'item 0 after re-parenting' );
+ assert_equals( PNL[1], testEl.firstChild, 'item 1 after re-parenting' );
+ document.body.appendChild(parEl);
+ var step2length = PNL.length;
+ var step2prop0 = PNL[0];
+ var step2prop1 = PNL[1];
+ document.createElement('div').appendChild(testEl);
+ var step3length = PNL.length;
+ var step3prop0 = PNL[0];
+ var step3prop1 = PNL[1];
+ parEl.appendChild(testEl);
+ var step4length = PNL.length;
+ var step4prop0 = PNL[0];
+ var step4prop1 = PNL[1];
+ document.body.removeChild(parEl);
+ assert_equals( step2length, 2, 'length (before test) when appended to document' );
+ assert_equals( step2prop0, parEl.firstChild, 'item 0 (before test) when appended to document' );
+ assert_equals( step2prop1, testEl.firstChild, 'item 1 (before test) when appended to document' );
+ assert_equals( step3length, 1, 'length after changing parent when appended to document' );
+ assert_equals( step3prop0, testEl.firstChild, 'item 0 after changing parent when appended to document' );
+ assert_true( !step3prop1, 'item 1 after changing parent when appended to document' );
+ assert_equals( step4length, 2, 'length after re-parenting when appended to document' );
+ assert_equals( step4prop0, parEl.firstChild, 'item 0 after re-parenting when appended to document' );
+ assert_equals( step4prop1, testEl.firstChild, 'item 1 after re-parenting when appended to document' );
+}, 'PropertyNodeList must update when appending elements with itemref to different parents');
+test(function () {
+ var testEl = makeEl('div',{itemscope:'itemscope'},'<div><div itemprop="foo"></div></div>');
+ var PNL = testEl.properties.namedItem('foo');
+ assert_equals( PNL.length, 1, 'length (before test)' );
+ assert_equals( PNL[0], testEl.firstChild.firstChild, 'foo 0 (before test)' );
+ testEl.firstChild.itemScope = true;
+ assert_equals( PNL.length, 0, 'length after setting itemscope' );
+ assert_true( !PNL[0], 'foo 0 after setting itemscope' );
+ testEl.firstChild.removeAttribute('itemscope');
+ assert_equals( PNL.length, 1, 'length after removing itemscope attribute' );
+ assert_equals( PNL[0], testEl.firstChild.firstChild, 'foo 0 after removing itemscope attribute' );
+}, 'PropertyNodeList must update when changing itemscope of children');
+//PropertyNodeList.getValues
+test(function () {
+ var valuesArray = makeEl('div',{}).properties.namedItem('foo').getValues();
+ assert_true( valuesArray instanceof Array, 'instanceof test' );
+ Array.prototype.customProp = true;
+ assert_true( valuesArray.customProp, 'inheritance test' );
+}, 'getValues must return an array');
+test(function () {
+ var testEl = makeEl('div',{});
+ var props = testEl.properties.namedItem('foo');
+ assert_not_equals( props.getValues(), props.getValues() );
+}, 'getValues must always return a newly constructed array');
+test(function () {
+ var parEl = makeEl('div',{},'<div id="id1"></div>');
+ var testEl = makeEl('div',{itemscope:'itemscope',itemref:'id1 id2'});
+ parEl.appendChild(testEl);
+ testEl.appendChild(makeEl('meta',{itemprop:'foo',content:'test'}));
+ testEl.appendChild(makeEl('audio',{itemprop:'foo',src:urls.base},'contained text'));
+ testEl.appendChild(makeEl('embed',{itemprop:'foo',src:urls.base}));
+ testEl.appendChild(makeEl('iframe',{itemprop:'foo',src:urls.base},'contained text'));
+ testEl.appendChild(makeEl('img',{itemprop:'foo',src:urls.base}));
+ testEl.appendChild(makeEl('source',{itemprop:'foo',src:urls.base}));
+ testEl.appendChild(makeEl('track',{itemprop:'foo',src:urls.base}));
+ testEl.appendChild(makeEl('video',{itemprop:'foo',src:urls.base},'contained text'));
+ testEl.appendChild(makeEl('a',{itemprop:'foo',href:urls.base},'contained text'));
+ testEl.appendChild(makeEl('area',{itemprop:'foo',href:urls.base}));
+ testEl.appendChild(makeEl('link',{itemprop:'foo',href:urls.base}));
+ testEl.appendChild(makeEl('object',{itemprop:'foo',data:urls.base},'contained text'));
+ parEl.appendChild(makeEl('time',{itemprop:'foo',id:'id2'},'te <span itemprop="foo" itemscope>st</span> ing'));
+ testEl.appendChild(makeEl('time',{itemprop:'foo',datetime:'test'},'te <span itemprop="foo" itemscope>st</span> ing'));
+ parEl.firstChild.appendChild(makeEl('div',{itemprop:'foo'},'te <span itemprop="foo" itemscope>st</span> ing'));
+ testEl.appendChild(makeEl('madeuponthespot',{itemprop:'foo'},'te <span itemprop="foo" itemscope>st</span> ing'));
+ var PNL = testEl.properties.namedItem('foo');
+ var valuesArray = PNL.getValues();
+ for( var i = 0; i < PNL.length; i++ ) {
+ assert_equals( valuesArray[i], PNL[i].itemValue, 'property index ' + i + ', tag ' + PNL[i].tagName );
+ }
+ assert_equals( valuesArray.length, 20, 'length' );
+}, 'getValues array must contain the same item values as itemValue would return for the given properties');
+test(function () {
+ var parEl = makeEl('div',{},'<div id="id1"></div>');
+ var testEl = makeEl('div',{itemscope:'itemscope',itemref:'id1 id2'});
+ parEl.appendChild(testEl);
+ testEl.appendChild(makeEl('meta',{itemprop:'foo',content:'test'}));
+ testEl.appendChild(makeEl('audio',{itemprop:'foo',src:urls.base},'contained text'));
+ testEl.appendChild(makeEl('embed',{itemprop:'foo',src:urls.base}));
+ testEl.appendChild(makeEl('iframe',{itemprop:'foo',src:urls.base},'contained text'));
+ testEl.appendChild(makeEl('img',{itemprop:'foo',src:urls.base}));
+ testEl.appendChild(makeEl('source',{itemprop:'foo',src:urls.base}));
+ testEl.appendChild(makeEl('track',{itemprop:'foo',src:urls.base}));
+ testEl.appendChild(makeEl('video',{itemprop:'foo',src:urls.base},'contained text'));
+ testEl.appendChild(makeEl('a',{itemprop:'foo',href:urls.base},'contained text'));
+ testEl.appendChild(makeEl('area',{itemprop:'foo',href:urls.base}));
+ testEl.appendChild(makeEl('link',{itemprop:'foo',href:urls.base}));
+ testEl.appendChild(makeEl('object',{itemprop:'foo',data:urls.base},'contained text'));
+ parEl.appendChild(makeEl('time',{itemprop:'foo',id:'id2'},'te <span itemprop="foo" itemscope>st</span> ing'));
+ testEl.appendChild(makeEl('time',{itemprop:'foo',datetime:'test'},'te <span itemprop="foo" itemscope>st</span> ing'));
+ parEl.firstChild.appendChild(makeEl('div',{itemprop:'foo'},'te <span itemprop="foo" itemscope>st</span> ing'));
+ testEl.appendChild(makeEl('madeuponthespot',{itemprop:'foo'},'te <span itemprop="foo" itemscope>st</span> ing'));
+ var PNL = testEl.properties.namedItem('foo');
+ var valuesArray = PNL.getValues();
+ var staticArray = [];
+ for( var i = 0; i < PNL.length; i++ ) {
+ staticArray[i] = PNL[i].itemValue;
+ }
+ testEl.innerHTML = '';
+ parEl.firstChild.firstChild.childNodes[1].itemScope = false;
+ assert_equals( valuesArray.length, staticArray.length, 'length after modification' );
+ for( var j = 0; j < staticArray.length; j++ ) {
+ assert_equals( valuesArray[j], staticArray[j], 'property index ' + j );
+ }
+ assert_equals( valuesArray[1], parEl.firstChild.firstChild.childNodes[1], 'retaining pointer after modification' );
+ staticArray = null;
+ parEl.firstChild.firstChild.innerHTML = '';
+ assert_equals( valuesArray[1] && valuesArray[1].nodeType, 1, 'retaining pointer after removal' );
+}, 'getValues array must not be live');
+//names
+test(function () {
+ assert_equals( typeof makeEl('div',{}).properties.names, 'object' );
+}, 'the names property must be an object');
+test(function () {
+ var testEl = makeEl('div',{});
+ assert_true( testEl.properties.names instanceof DOMStringList, 'instanceof DOMStringList' );
+ DOMStringList.prototype.stringCustomProperty = true;
+ assert_true( testEl.properties.names.stringCustomProperty, 'inheritance from DOMStringList' );
+}, 'the names property must implement DOMStringList');
+test(function () {
+ var failed = false, elem = makeEl('div',{itemscope:'itemscope'}), realList = elem.properties.names;
+ try {
+ elem.properties.names = '';
+ } catch(e) {
+ failed = e;
+ }
+ assert_equals(elem.properties.names,realList);
+ assert_false(failed,'an error was thrown');
+}, 'the names property must be read-only');
+test(function () {
+ var testEl = makeEl('div',{});
+ assert_equals( testEl.properties.names, testEl.properties.names );
+}, 'the names property must always reference the same object');
+test(function () {
+ var testEl = makeEl('div',{});
+ assert_equals( testEl.properties.names.item(0), null, 'item(0)' );
+ assert_equals( testEl.properties.names.item(-1), null, 'item(-1)' );
+}, 'names.item() must return null for out of range indexes');
+test(function () {
+ var testEl = makeEl('div',{});
+ assert_equals( testEl.properties.names[0], window.undefined, '[0]' );
+ assert_equals( testEl.properties.names[-1], window.undefined, '[-1]' );
+}, 'names[index] must return undefined for out of range indexes');
+test(function () {
+ var testEl = makeEl('div',{},'<div itemprop="foo">bar</div>');
+ assert_equals( testEl.properties.names.length, 0, 'length' );
+ assert_true( !testEl.properties.names.item(0), 'item(0)' );
+ assert_true( !testEl.properties.names[0], '[0]' );
+ assert_false( testEl.properties.names.contains('foo'), 'contains' );
+}, 'the names collection must be empty if the element does not have an itemscope property');
+test(function () {
+ var testEl = makeEl('div',{},'<div itemprop="foo">bar</div>');
+ testEl.itemScope = true;
+ assert_equals( testEl.properties.names.length, 1, 'length' );
+ assert_equals( testEl.properties.names.item(0), 'foo', 'item(0)' );
+ assert_equals( testEl.properties.names[0], 'foo', '[0]' );
+ assert_true( testEl.properties.names.contains('foo'), 'contains' );
+}, 'the names collection must become populated if the element is given an itemscope property');
+test(function () {
+ var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo">bar</div>');
+ testEl.itemScope = false;
+ assert_equals( testEl.properties.names.length, 0, 'length' );
+ assert_true( !testEl.properties.names.item(0), 'item(0)' );
+ assert_true( !testEl.properties.names[0], '[0]' );
+ assert_false( testEl.properties.names.contains('foo'), 'contains' );
+}, 'the names collection must become empty if the element\'s itemscope property is removed');
+test(function () {
+ var testEl = makeEl('div',{},'<div itemprop="foo">bar</div>');
+ testEl.properties.names.item = 'test';
+ testEl.properties.names.contains = 'test';
+ assert_equals( testEl.properties.names.item, 'test', 'item' );
+ assert_equals( testEl.properties.names.contains, 'test', 'contains' );
+}, 'the names.item and names.contains methods should be overwriteable');
+test(function () {
+ var testEl = makeEl('div',{},'<div itemprop="foo">bar</div>');
+ testEl.properties.names.localCustomProperty = 'test';
+ assert_equals( testEl.properties.names.localCustomProperty, 'test' );
+}, 'the names.customProperty should be writeable');
+test(function () {
+ //WebIDL and ECMAScript 5 - a readonly property has a getter but not a setter
+ //ES5 makes [[Put]] fail but not throw
+ var failed = false;
+ var elem = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo">bar</div>');
+ try {
+ elem.properties.names.length = 0;
+ } catch(e) {
+ failed = e;
+ }
+ assert_equals(elem.properties.names.length,1);
+ assert_false(failed,'an error was thrown');
+}, 'names.length must be read-only');
+test(function () {
+ var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div><div itemprop="bar"><div itemprop="foo"></div><div itemprop="foo"></div></div><div itemprop="baz qux"></div>');
+ assert_equals( testEl.properties.names.length, 4 );
+}, 'names.length must be the total number of property names');
+test(function () {
+ var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div><div itemprop="bar"><div itemprop="foo"></div><div itemprop="foo"></div></div><div itemprop="baz \t\r\n\fqux"></div>');
+ assert_equals( testEl.properties.names.item(0), 'foo', 'item(0)' );
+ assert_equals( testEl.properties.names.item(1), 'bar', 'item(1)' );
+ assert_equals( testEl.properties.names.item(2), 'baz', 'item(2)' );
+ assert_equals( testEl.properties.names.item(3), 'qux', 'item(3)' );
+ assert_equals( testEl.properties.names[0], 'foo', '[0]' );
+ assert_equals( testEl.properties.names[1], 'bar', '[1]' );
+ assert_equals( testEl.properties.names[2], 'baz', '[2]' );
+ assert_equals( testEl.properties.names[3], 'qux', '[3]' );
+}, 'names.item must give each property name in tree order');
+test(function () {
+ var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div><div itemprop="bar BAR bar"><div itemprop="FOO"></div><div itemprop="foo"></div></div><div itemprop="baz qux"></div>');
+ assert_equals( testEl.properties.names.length, 6, 'length' );
+ assert_equals( testEl.properties.names.item(0), 'foo', 'item(0)' );
+ assert_equals( testEl.properties.names.item(1), 'bar', 'item(1)' );
+ assert_equals( testEl.properties.names.item(2), 'BAR', 'item(2)' );
+ assert_equals( testEl.properties.names.item(3), 'FOO', 'item(3)' );
+ assert_equals( testEl.properties.names.item(4), 'baz', 'item(4)' );
+ assert_equals( testEl.properties.names.item(5), 'qux', 'item(5)' );
+ assert_equals( testEl.properties.names[0], 'foo', '[0]' );
+ assert_equals( testEl.properties.names[1], 'bar', '[1]' );
+ assert_equals( testEl.properties.names[2], 'BAR', '[2]' );
+ assert_equals( testEl.properties.names[3], 'FOO', '[3]' );
+ assert_equals( testEl.properties.names[4], 'baz', '[4]' );
+ assert_equals( testEl.properties.names[5], 'qux', '[5]' );
+}, 'names must be case sensitive');
+test(function () {
+ var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div><div itemprop="bar"><div itemprop="FOO"></div><div itemprop="foo"></div></div><div itemprop="baz qux"></div>');
+ assert_true( testEl.properties.names.contains('foo'), 'foo' );
+ assert_true( testEl.properties.names.contains('FOO'), 'FOO' );
+ assert_true( testEl.properties.names.contains('bar'), 'bar' );
+ assert_false( testEl.properties.names.contains('BAR'), 'BAR' );
+ assert_true( testEl.properties.names.contains('baz'), 'baz' );
+ assert_true( testEl.properties.names.contains('qux'), 'qux' );
+ assert_false( testEl.properties.names.contains('madeup'), 'madeup' );
+}, 'names.contains must return boolean if the name exists');
+test(function () {
+ var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="1"></div>');
+ assert_equals( testEl.properties.names.item('1'), null );
+}, 'names.item must cast to number');
+test(function () {
+ var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div><div itemprop="1"></div>');
+ assert_true( testEl.properties.names.contains({ valueOf: function () { return 2; }, toString: function () { return 'foo'; } }), 'object' );
+ assert_true( testEl.properties.names.contains(1), 'number' );
+}, 'names.contains must cast to string');
+test(function () {
+ var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div><div itemprop="bar"></div>');
+ var namesList = testEl.properties.names;
+ testEl.innerHTML = '<div itemprop="baz"></div>';
+ assert_equals( testEl.properties.names.length, 1, 'length' );
+ assert_equals( testEl.properties.names[0], 'baz', '[0]' );
+}, 'the names collection must be live');
+test(function () {
+ var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="|§!&quot;#¤%&/()=?`\\@£${[]}´€^¨~\'*,;.:-_&lt;&gt;帿ŨÆ"></div>');
+ assert_equals( testEl.properties.names[0], '|§!"#¤%&/()=?`\\@£${[]}´€^¨~\'*,;.:-_<>帿ŨÆ' );
+}, 'names must reflect property names containing special characters');
+test(function () {
+ var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div><div itemscope><div itemprop="bar"></div></div>');
+ assert_equals( testEl.properties.names.length, 1, 'length' );
+ assert_equals( testEl.properties.names[0], 'foo', '[0]' );
+ assert_true( testEl.properties.names.contains('foo'), 'contains(foo)' );
+ assert_false( testEl.properties.names.contains('bar'), 'contains(bar)' );
+}, 'names must ignore properties of nested items');
+test(function () {
+ //note, itemref ordering is reversed compared with the next test to catch failed sorting algorithms
+ var parEl = makeEl('div',{},'<div itemprop="foo" id="id1"></div><div itemscope itemref="id2 id1"><div itemprop="bar"></div></div><div itemprop="baz" id="id2"><div itemprop="qux"></div></div>');
+ var testEl = parEl.childNodes[1];
+ document.body.appendChild(parEl);
+ var length = testEl.properties.names.length;
+ var names0 = testEl.properties.names[0];
+ var names1 = testEl.properties.names[1];
+ var names2 = testEl.properties.names[2];
+ var names3 = testEl.properties.names[3];
+ document.body.removeChild(parEl);
+ assert_equals( length, 4, 'length' );
+ assert_equals( names0, 'foo', 'names[0]' );
+ assert_equals( names1, 'bar', 'names[1]' );
+ assert_equals( names2, 'baz', 'names[2]' );
+ assert_equals( names3, 'qux', 'names[3]' );
+}, 'names must see items added with itemref when attached to the document\'s DOM');
+test(function () {
+ var parEl = makeEl('div',{},'<div itemprop="foo" id="id1"></div><div itemscope itemref="id1 id2"><div itemprop="bar"></div></div><div itemprop="baz" id="id2"><div itemprop="qux"></div></div>');
+ var testEl = parEl.childNodes[1];
+ assert_equals( testEl.properties.names.length, 4, 'length' );
+ assert_equals( testEl.properties.names[0], 'foo', 'names[0]' );
+ assert_equals( testEl.properties.names[1], 'bar', 'names[1]' );
+ assert_equals( testEl.properties.names[2], 'baz', 'names[2]' );
+ assert_equals( testEl.properties.names[3], 'qux', 'names[3]' );
+}, 'names must see items added with itemref');
+test(function () {
+ //this one also tests the live object just in case - further ones will not always do this as its live status will already have been well established
+ var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div>');
+ var DSL = testEl.properties.names;
+ testEl.removeAttribute('itemscope');
+ assert_equals( testEl.properties.names.length, 0, 'removing attribute' );
+ assert_equals( DSL.length, 0, 'removing attribute (live)' );
+ assert_true( !testEl.properties.names[0], 'removing attribute [0]' );
+ assert_true( !DSL[0], 'removing attribute [0] (live)' );
+ testEl.itemScope = true;
+ assert_equals( testEl.properties.names.length, 1, 'setting itemScope' );
+ assert_equals( DSL.length, 1, 'setting itemScope (live)' );
+ assert_equals( testEl.properties.names[0], 'foo', 'names[0] after setting itemScope' );
+ assert_equals( DSL[0], 'foo', 'names[0] after setting itemScope (live)' );
+}, 'names must update when adding itemscope on the root');
+test(function () {
+ var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div>');
+ assert_equals( testEl.properties.names.length, 1, 'length (before test)' );
+ assert_equals( testEl.properties.names[0], 'foo', 'item 0 (before test)' );
+ testEl.appendChild(makeEl('div',{itemprop:'bar'}));
+ assert_equals( testEl.properties.names.length, 2, 'length after adding a child' );
+ assert_equals( testEl.properties.names[0], 'foo', 'item 0 after adding a child' );
+ assert_equals( testEl.properties.names[1], 'bar', 'item 1 after adding a child' );
+ testEl.lastChild.appendChild(makeEl('div',{itemprop:'foo'}));
+ assert_equals( testEl.properties.names.length, 2, 'foo length after adding a child with duplicated name' );
+ assert_equals( testEl.properties.names[0], 'foo', 'item 0 after adding a child with duplicated name' );
+ assert_equals( testEl.properties.names[1], 'bar', 'item 1 after adding a child with duplicated name' );
+ testEl.removeChild(testEl.lastChild);
+ assert_equals( testEl.properties.names.length, 1, 'length after removing a child' );
+ assert_equals( testEl.properties.names[0], 'foo', 'item 0 after removing a child' );
+}, 'names must update when adding property elements');
+test(function () {
+ var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div><div itemprop="bar"></div>');
+ var DSL = testEl.properties.names;
+ assert_equals( DSL[0], 'foo', 'item 0 (before test)' );
+ assert_equals( DSL[1], 'bar', 'item 1 (before test)' );
+ testEl.appendChild(testEl.firstChild);
+ assert_equals( DSL[0], 'bar', 'item 0 (after test)' );
+ assert_equals( DSL[1], 'foo', 'item 1 (after test)' );
+}, 'names must update when re-ordering property elements');
+test(function () {
+ var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div><div></div>');
+ var DSL = testEl.properties.names;
+ assert_equals( DSL.length, 1, 'length (before test)' );
+ assert_equals( DSL[0], 'foo', 'item 0 (before test)' );
+ testEl.lastChild.itemProp.toggle('bar');
+ assert_equals( DSL.length, 2, 'length after adding a token' );
+ assert_equals( DSL[0], 'foo', 'item 0 after adding a token' );
+ assert_equals( DSL[1], 'bar', 'item 1 after adding a token' );
+ testEl.lastChild.itemProp.add('foo');
+ assert_equals( DSL.length, 2, 'length after adding a duplicated token' );
+ assert_equals( DSL[0], 'foo', 'item 0 after adding a duplicated token' );
+ assert_equals( DSL[1], 'bar', 'item 1 after adding a duplicated token' );
+ testEl.lastChild.removeAttribute('itemprop');
+ assert_equals( DSL.length, 1, 'length after removing an attribute' );
+ assert_equals( DSL[0], 'foo', 'item 0 after removing an attribute' );
+ testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div><div itemprop="bar"></div><div itemprop="foo"></div>');
+ DSL = testEl.properties.names;
+ assert_equals( DSL.length, 2, 'length (before second test)' );
+ assert_equals( DSL[0], 'foo', 'item 0 (before second test)' );
+ assert_equals( DSL[1], 'bar', 'item 1 (before second test)' );
+ testEl.firstChild.removeAttribute('itemprop');
+ assert_equals( DSL.length, 2, 'length after removing attribute of first item' );
+ assert_equals( DSL[0], 'bar', 'item 0 after removing attribute of first item' );
+ assert_equals( DSL[1], 'foo', 'item 1 after removing attribute of first item' );
+ testEl.firstChild.itemProp.add('foo');
+ assert_equals( DSL.length, 2, 'length after adding duplicated token to first item' );
+ assert_equals( DSL[0], 'foo', 'item 0 after adding duplicated token to first item' );
+ assert_equals( DSL[1], 'bar', 'item 1 after adding duplicated token to first item' );
+ testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo bar"></div>');
+ DSL = testEl.properties.names;
+ assert_equals( DSL.length, 2, 'length (before third test)' );
+ assert_equals( DSL[0], 'foo', 'item 0 (before third test)' );
+ assert_equals( DSL[1], 'bar', 'item 1 (before third test)' );
+ testEl.firstChild.itemProp.toggle('foo');
+ testEl.firstChild.itemProp.toggle('foo');
+ assert_equals( DSL.length, 2, 'length after swapping tokens' );
+ assert_equals( DSL[0], 'bar', 'item 0 after swapping tokens' );
+ assert_equals( DSL[1], 'foo', 'item 1 after swapping tokens' );
+}, 'names must update when changing itemProp of children');
+test(function () {
+ var parEl = makeEl('div',{},'<div itemprop="foo"><div itemprop="bar"></div></div><div itemscope itemref="id1"></div>');
+ var testEl = parEl.childNodes[1];
+ var DSL = testEl.properties.names;
+ assert_equals( DSL.length, 0, 'length (before test)' );
+ parEl.firstChild.id = 'id1';
+ assert_equals( DSL.length, 2, 'length after id is created' );
+ assert_equals( DSL[0], 'foo', 'item 0 after id is created' );
+ assert_equals( DSL[1], 'bar', 'item 1 after id is created' );
+ parEl.firstChild.removeAttribute('id');
+ assert_equals( DSL.length, 0, 'length after removing an attribute' );
+ document.body.appendChild(parEl);
+ var step1length = DSL.length;
+ parEl.firstChild.id = 'id1';
+ var step2length = DSL.length;
+ var step2item0 = DSL[0];
+ var step2item1 = DSL[1];
+ parEl.firstChild.removeAttribute('id');
+ var step3length = DSL.length;
+ document.body.removeChild(parEl);
+ assert_equals( step1length, 0, 'length (before test) when appended to document' );
+ assert_equals( step2length, 2, 'length after id is created when appended to document' );
+ assert_equals( step2item0, 'foo', 'item 0 after id is created when appended to document' );
+ assert_equals( step2item1, 'bar', 'item 1 after id is created when appended to document' );
+ assert_equals( step3length, 0, 'length after removing an attribute when appended to document' );
+}, 'names must update when changing id of referenced sibling when appended to document');
+test(function () {
+ var parEl = makeEl('div',{},'<div itemprop="foo"><div itemprop="bar"></div></div><div itemscope itemref="id1"></div><div itemprop="baz" id="id1"></div>');
+ var testEl = parEl.childNodes[1];
+ var DSL = testEl.properties.names;
+ assert_equals( DSL.length, 1, 'length (before test)' );
+ assert_equals( DSL[0], 'baz', 'item 0 (before test)' );
+ parEl.firstChild.id = 'id1';
+ assert_equals( DSL.length, 2, 'length after id is created' );
+ assert_equals( DSL[0], 'foo', 'item 0 after id is created' );
+ assert_equals( DSL[1], 'bar', 'item 1 after id is created' );
+ parEl.firstChild.removeAttribute('id');
+ assert_equals( DSL.length, 1, 'length after removing an attribute' );
+ assert_equals( DSL[0], 'baz', 'item 0 after removing an attribute' );
+ document.body.appendChild(parEl);
+ var step1length = DSL.length;
+ var step1item0 = DSL[0];
+ parEl.firstChild.id = 'id1';
+ var step2length = DSL.length;
+ var step2item0 = DSL[0];
+ var step2item1 = DSL[1];
+ parEl.firstChild.removeAttribute('id');
+ var step3length = DSL.length;
+ var step3item0 = DSL[0];
+ document.body.removeChild(parEl);
+ assert_equals( step1length, 1, 'length (before test)' );
+ assert_equals( step1item0, 'baz', 'item 0 (before test)' );
+ assert_equals( step2length, 2, 'length after id is created' );
+ assert_equals( step2item0, 'foo', 'item 0 after id is created' );
+ assert_equals( step2item1, 'bar', 'item 1 after id is created' );
+ assert_equals( step3length, 1, 'length after removing an attribute' );
+ assert_equals( step3item0, 'baz', 'item 0 after removing an attribute' );
+}, 'names must update when changing duplicated id of referenced sibling');
+test(function () {
+ var parEl = makeEl('div',{},'<div id="id1" itemprop="foo"></div><div itemscope></div>');
+ var testEl = parEl.childNodes[1];
+ var DSL = testEl.properties.names;
+ assert_equals( DSL.length, 0, 'length (before test)' );
+ testEl.itemRef.toggle('id1');
+ assert_equals( DSL.length, 1, 'length after itemref is changed' );
+ assert_equals( DSL[0], 'foo', 'item 0 after itemref is changed' );
+ testEl.removeAttribute('itemref');
+ assert_equals( DSL.length, 0, 'length after itemref is removed' );
+ assert_true( !DSL[0], 'item 0 after itemref is removed' );
+ document.body.appendChild(parEl);
+ var step1length = DSL.length;
+ testEl.itemRef.toggle('id1');
+ var step2length = DSL.length;
+ var step2item = DSL[0];
+ testEl.removeAttribute('itemref');
+ var step3length = DSL.length;
+ var step3item = DSL[0];
+ document.body.removeChild(parEl);
+ assert_equals( step1length, 0, 'length (before test)' );
+ assert_equals( step2length, 1, 'length after itemref is changed' );
+ assert_equals( step2item, 'foo', 'item 0 after itemref is changed' );
+ assert_equals( step3length, 0, 'length after itemref is removed' );
+ assert_true( !step3item, 'item 0 after itemref is removed' );
+}, 'names must update when changing itemref to point to an element');
+test(function () {
+ var parEl = makeEl('div',{},'<div id="id1"><div></div></div><div itemscope itemref="id1"></div>');
+ var testEl = parEl.childNodes[1];
+ var DSL = testEl.properties.names;
+ assert_equals( DSL.length, 0, 'length (before test)' );
+ parEl.firstChild.appendChild(makeEl('div',{itemprop:'foo'}));
+ assert_equals( DSL.length, 1, 'length after a referenced element is added' );
+ assert_equals( DSL.item(0), 'foo', 'item 0 after a referenced element is added' ); //uses item just for the fun of it
+ parEl.firstChild.firstChild.itemProp.toggle('bar');
+ assert_equals( DSL.length, 2, 'length after a referenced itemprop is changed' );
+ assert_equals( DSL[0], 'bar', 'item 0 after a referenced element is added' );
+ assert_equals( DSL[1], 'foo', 'item 1 after a referenced element is added' );
+ parEl.firstChild.removeChild(parEl.firstChild.firstChild);
+ assert_equals( DSL.length, 1, 'length after a referenced element is removed' );
+ assert_equals( DSL[0], 'foo', 'item 0 after a referenced element is removed' );
+ parEl.innerHTML = '<div id="id1"><div></div></div><div itemscope itemref="id1"></div>';
+ testEl = parEl.childNodes[1];
+ DSL = testEl.properties.names;
+ document.body.appendChild(parEl);
+ var step1length = DSL.length;
+ parEl.firstChild.appendChild(makeEl('div',{itemprop:'foo'}));
+ var step2length = DSL.length;
+ var step2item0 = DSL.item(0); //uses item just for the fun of it
+ parEl.firstChild.firstChild.itemProp.toggle('bar');
+ var step3length = DSL.length;
+ var step3item0 = DSL[0];
+ var step3item1 = DSL[1];
+ parEl.firstChild.removeChild(parEl.firstChild.firstChild);
+ var step4length = DSL.length;
+ var step4item0 = DSL[0];
+ document.body.removeChild(parEl);
+ assert_equals( step1length, 0, 'length (before test)' );
+ parEl.firstChild.appendChild(makeEl('div',{itemprop:'foo'}));
+ assert_equals( step2length, 1, 'length after a referenced element is added' );
+ assert_equals( step2item0, 'foo', 'item 0 after a referenced element is added' ); //uses item just for the fun of it
+ parEl.firstChild.firstChild.itemProp.toggle('bar');
+ assert_equals( step3length, 2, 'length after a referenced itemprop is changed' );
+ assert_equals( step3item0, 'bar', 'item 0 after a referenced element is added' );
+ assert_equals( step3item1, 'foo', 'item 1 after a referenced element is added' );
+ parEl.firstChild.removeChild(parEl.firstChild.firstChild);
+ assert_equals( step4length, 1, 'length after a referenced element is removed' );
+ assert_equals( step4item0, 'foo', 'item 0 after a referenced element is removed' );
+}, 'names must update when changing children of elements referenced through itemref');
+test(function () {
+ var parEl = makeEl('div',{},'<div id="id1" itemprop="foo"></div><div itemscope itemref="id1"><div itemprop="bar"></div></div>');
+ var testEl = parEl.childNodes[1];
+ var DSL = testEl.properties.names;
+ assert_equals( DSL.length, 2, 'length (before test)' );
+ assert_equals( DSL[0], 'foo', 'item 0 (before test)' );
+ assert_equals( DSL[1], 'bar', 'item 1 (before test)' );
+ document.body.appendChild(testEl);
+ var step1length = DSL.length;
+ var step1prop0 = DSL[0];
+ var step1prop1 = DSL[1];
+ parEl.appendChild(testEl);
+ assert_equals( step1length, 1, 'length after changing parent' );
+ assert_equals( step1prop0, 'bar', 'item 0 after changing parent' );
+ assert_true( !step1prop1, 'item 1 after changing parent' );
+ assert_equals( DSL.length, 2, 'length after re-parenting' );
+ assert_equals( DSL[0], 'foo', 'item 0 after re-parenting' );
+ assert_equals( DSL[1], 'bar', 'item 1 after re-parenting' );
+ document.body.appendChild(parEl);
+ var step2length = DSL.length;
+ var step2prop0 = DSL[0];
+ var step2prop1 = DSL[1];
+ document.createElement('div').appendChild(testEl);
+ var step3length = DSL.length;
+ var step3prop0 = DSL[0];
+ var step3prop1 = DSL[1];
+ parEl.appendChild(testEl);
+ var step4length = DSL.length;
+ var step4prop0 = DSL[0];
+ var step4prop1 = DSL[1];
+ document.body.removeChild(parEl);
+ assert_equals( step2length, 2, 'length (before test) when appended to document' );
+ assert_equals( step2prop0, 'foo', 'item 0 (before test) when appended to document' );
+ assert_equals( step2prop1, 'bar', 'item 1 (before test) when appended to document' );
+ assert_equals( step3length, 1, 'length after changing parent when appended to document' );
+ assert_equals( step3prop0, 'bar', 'item 0 after changing parent when appended to document' );
+ assert_true( !step3prop1, 'item 1 after changing parent when appended to document' );
+ assert_equals( step4length, 2, 'length after re-parenting when appended to document' );
+ assert_equals( step4prop0, 'foo', 'item 0 after re-parenting when appended to document' );
+ assert_equals( step4prop1, 'bar', 'item 1 after re-parenting when appended to document' );
+}, 'names must update when appending elements with itemref to different parents');
+test(function () {
+ var testEl = makeEl('div',{itemscope:'itemscope'},'<div><div itemprop="foo"></div></div>');
+ var DSL = testEl.properties.names;
+ assert_equals( DSL.length, 1, 'length (before test)' );
+ assert_equals( DSL[0], 'foo', 'item 0 (before test)' );
+ testEl.firstChild.itemScope = true;
+ assert_equals( DSL.length, 0, 'length after setting itemscope' );
+ assert_true( !DSL[0], 'item 0 after setting itemscope' );
+ testEl.firstChild.removeAttribute('itemscope');
+ assert_equals( DSL.length, 1, 'length after removing itemscope attribute' );
+ assert_equals( DSL[0], 'foo', 'item 0 after removing itemscope attribute' );
+}, 'names must update when changing itemscope of children');
+
+/* potential bugs */
+test(function () {
+ var parEl = makeEl('div',{},'<div id="id1"></div>');
+ var testEl = makeEl('div',{itemscope:'itemscope',itemref:'id1 id2'});
+ parEl.appendChild(testEl);
+ testEl.appendChild(makeEl('meta',{itemprop:'foo',content:'test'}));
+ testEl.appendChild(makeEl('audio',{itemprop:'foo',src:urls.base},'contained text'));
+ testEl.appendChild(makeEl('embed',{itemprop:'foo',src:urls.base}));
+ testEl.appendChild(makeEl('iframe',{itemprop:'foo',src:urls.base},'contained text'));
+ testEl.appendChild(makeEl('img',{itemprop:'foo',src:urls.base}));
+ testEl.appendChild(makeEl('source',{itemprop:'foo',src:urls.base}));
+ testEl.appendChild(makeEl('track',{itemprop:'foo',src:urls.base}));
+ testEl.appendChild(makeEl('video',{itemprop:'foo',src:urls.base},'contained text'));
+ testEl.appendChild(makeEl('a',{itemprop:'foo',href:urls.base},'contained text'));
+ testEl.appendChild(makeEl('area',{itemprop:'foo',href:urls.base}));
+ testEl.appendChild(makeEl('link',{itemprop:'foo',href:urls.base}));
+ testEl.appendChild(makeEl('object',{itemprop:'foo',data:urls.base},'contained text'));
+ parEl.appendChild(makeEl('time',{itemprop:'bar',id:'id2'},'te <span itemprop="foo" itemscope>st</span> ing'));
+ testEl.appendChild(makeEl('time',{itemprop:'foo',datetime:'test'},'te <span itemprop="foo" itemscope>st</span> ing'));
+ parEl.firstChild.appendChild(makeEl('div',{itemprop:'baz'},'te <span itemprop="foo" itemscope>st</span> ing'));
+ testEl.appendChild(makeEl('madeuponthespot',{itemprop:'baz'},'te <span itemprop="foo" itemscope>st</span> ing'));
+ var properties, PNLfoo, PNLbar, PNLbaz, fooValues, barValues, bazValues, allArrays, snapshot = [];
+ document.body.appendChild(parEl);
+ try {
+ properties = testEl.properties;
+ PNLfoo = properties.namedItem('foo');
+ PNLbar = properties.namedItem('bar');
+ PNLbaz = properties.namedItem('baz');
+ fooValues = PNLfoo.getValues();
+ barValues = PNLbar.getValues();
+ bazValues = PNLbaz.getValues();
+ allArrays = [properties,PNLfoo,PNLbar,PNLbaz,fooValues,barValues,bazValues];
+ for( var a = 0; a < allArrays.length; a++ ) {
+ snapshot[a] = [];
+ for( var b = 0; b < allArrays[a].length; b++ ) {
+ snapshot[a][b] = allArrays[a][b];
+ }
+ }
+ } catch(e) { /* need to clean up */ }
+ document.body.removeChild(parEl);
+ var c, d;
+ for( c = 0; c < allArrays.length; c++ ) {
+ for( d = 0; d < allArrays[c].length; d++ ) {
+ assert_equals( snapshot[c][d], allArrays[c][d], 'allArrays['+c+']['+d+']' );
+ }
+ }
+ var newArrays = [testEl.properties,testEl.properties.namedItem('foo'),testEl.properties.namedItem('bar'),testEl.properties.namedItem('baz'),testEl.properties.namedItem('foo').getValues(),testEl.properties.namedItem('bar').getValues(),testEl.properties.namedItem('baz').getValues()];
+ for( c = 0; c < newArrays.length; c++ ) {
+ for( d = 0; d < newArrays[c].length; d++ ) {
+ assert_equals( snapshot[c][d], newArrays[c][d], 'newArrays['+c+']['+d+']' );
+ }
+ }
+}, 'collections must survive the parent\'s removal from the document');
+test(function () {
+ var testEl = makeEl('div',{itemscope:'itemscope'});
+ testEl.appendChild(makeEl('meta',{itemprop:'foo',content:'test'}));
+ testEl.appendChild(makeEl('audio',{itemprop:'foo',src:urls.base},'contained text'));
+ testEl.appendChild(makeEl('embed',{itemprop:'foo',src:urls.base}));
+ testEl.appendChild(makeEl('iframe',{itemprop:'foo',src:urls.base},'contained text'));
+ testEl.appendChild(makeEl('img',{itemprop:'foo',src:urls.base}));
+ testEl.appendChild(makeEl('source',{itemprop:'foo',src:urls.base}));
+ testEl.appendChild(makeEl('track',{itemprop:'foo',src:urls.base}));
+ testEl.appendChild(makeEl('video',{itemprop:'foo',src:urls.base},'contained text'));
+ testEl.appendChild(makeEl('a',{itemprop:'foo',href:urls.base},'contained text'));
+ testEl.appendChild(makeEl('area',{itemprop:'foo',href:urls.base}));
+ testEl.appendChild(makeEl('link',{itemprop:'foo',href:urls.base}));
+ testEl.appendChild(makeEl('object',{itemprop:'foo',data:urls.base},'contained text'));
+ testEl.appendChild(makeEl('time',{itemprop:'bar',id:'id2'},'te <span itemprop="foo" itemscope>st</span> ing'));
+ testEl.appendChild(makeEl('time',{itemprop:'foo',datetime:'test'},'te <span itemprop="foo" itemscope>st</span> ing'));
+ testEl.appendChild(makeEl('div',{itemprop:'baz'},'te <span itemprop="foo" itemscope>st</span> ing'));
+ testEl.appendChild(makeEl('madeuponthespot',{itemprop:'baz'},'te <span itemprop="foo" itemscope>st</span> ing'));
+ var properties, PNLfoo, PNLbar, PNLbaz, fooValues, barValues, bazValues, allArrays, snapshot = [];
+ document.body.appendChild(testEl);
+ try {
+ properties = testEl.properties;
+ PNLfoo = properties.namedItem('foo');
+ PNLbar = properties.namedItem('bar');
+ PNLbaz = properties.namedItem('baz');
+ fooValues = PNLfoo.getValues();
+ barValues = PNLbar.getValues();
+ bazValues = PNLbaz.getValues();
+ allArrays = [properties,PNLfoo,PNLbar,PNLbaz,fooValues,barValues,bazValues];
+ for( var a = 0; a < allArrays.length; a++ ) {
+ snapshot[a] = [];
+ for( var b = 0; b < allArrays[a].length; b++ ) {
+ snapshot[a][b] = allArrays[a][b];
+ }
+ }
+ } catch(e) { /* need to clean up */ }
+ document.body.removeChild(testEl);
+ var c, d;
+ for( c = 0; c < allArrays.length; c++ ) {
+ for( d = 0; d < allArrays[c].length; d++ ) {
+ assert_equals( snapshot[c][d], allArrays[c][d], 'allArrays['+c+']['+d+']' );
+ }
+ }
+ var newArrays = [testEl.properties,testEl.properties.namedItem('foo'),testEl.properties.namedItem('bar'),testEl.properties.namedItem('baz'),testEl.properties.namedItem('foo').getValues(),testEl.properties.namedItem('bar').getValues(),testEl.properties.namedItem('baz').getValues()];
+ for( c = 0; c < newArrays.length; c++ ) {
+ for( d = 0; d < newArrays[c].length; d++ ) {
+ assert_equals( snapshot[c][d], newArrays[c][d], 'newArrays['+c+']['+d+']' );
+ }
+ }
+}, 'collections must survive the item\'s removal from the document');
+
+/* override_builtins */
+test(function () {
+ //http://dev.w3.org/2006/webapi/WebIDL/#named-properties
+ //[OverrideBuiltins] is not declared for any of the properties, hence no overriding is allowed
+ var testEl = makeEl('div',{itemscope:'itemscope'});
+ var namedItem = testEl.properties.namedItem;
+ var item = testEl.properties.item;
+ var names = testEl.properties.names;
+ testEl.innerHTML = '<div itemprop="namedItem length item names"></div>';
+ assert_equals( testEl.properties['namedItem'], namedItem, 'namedItem' );
+ assert_equals( testEl.properties['length'], 1, 'length' );
+ assert_equals( testEl.properties['item'], item, 'item' );
+ assert_equals( testEl.properties['names'], names, 'names' );
+}, 'itemprop names must not override builtin properties');
+
+/* casting */
+//when calling object[other_object], ECMAScript treats other_object as a named property so it casts it to a string using toString
+//when looking up a named property, ECMAScript and WebIDL <http://dev.w3.org/2006/webapi/WebIDL/#named-properties> will prefer an array index property name
+test(function () {
+ var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="2"></div><div itemprop="0"></div>');
+ assert_equals( testEl.properties.item('0'), testEl.properties.item(0), '0' );
+ assert_equals( testEl.properties.item('2'), testEl.properties.item(2), '2' );
+}, 'properties.item(integerString) should cast to a number');
+test(function () {
+ var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="2"></div><div itemprop="0"></div>');
+ assert_equals( testEl.properties['0'], testEl.properties.item(0), '0' );
+ assert_equals( testEl.properties['2'], window.undefined, '2' );
+}, 'properties[integerString] should act as a numeric index');
+test(function () {
+ var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="0"></div>');
+ assert_equals( testEl.properties.namedItem(0), testEl.properties.namedItem('0'), '0' );
+ assert_true( testEl.properties.namedItem(0) instanceof PropertyNodeList , 'instanceof' );
+}, 'properties.namedItem(integer) should cast to a string');
+test(function () {
+ var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="2 foo"></div><div itemprop="0"></div>');
+ assert_equals( testEl.properties[{ toString: function(){return 'foo';}, valueOf: function(){return 1;} }][0], testEl.firstChild, 'foo' );
+ assert_equals( testEl.properties[{ toString: function(){return '0';}, valueOf: function(){return 1;} }], testEl.firstChild, '0' );
+ assert_equals( testEl.properties[{ toString: function(){return '2';}, valueOf: function(){return 0;} }], window.undefined, '2' );
+}, 'properties[someObject] should cast toString before using whichever casting applies');
+
+/* loops and evil itemref */
+test(function () {
+ //This should have 1 property on each itemscope, pointing only to its direct child
+ var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemscope itemprop="foo"><div itemprop="bar"></div></div>');
+ assert_equals( testEl.properties.length, 1, 'outer length' );
+ assert_equals( testEl.properties[0], testEl.firstChild, 'outer properties[0]' );
+ assert_true( !testEl.properties[1], 'outer properties[1]' );
+ assert_equals( testEl.properties.namedItem('foo').length, 1, 'outer foo.length' );
+ assert_equals( testEl.properties.namedItem('foo')[0], testEl.firstChild, 'outer foo[0]' );
+ assert_true( !testEl.properties.namedItem('foo')[1], 'outer foo[1]' );
+ assert_equals( testEl.properties.namedItem('bar').length, 0, 'outer bar.length' );
+ assert_true( !testEl.properties.namedItem('bar')[0], 'outer bar[0]' );
+ assert_equals( testEl.properties.names.length, 1, 'outer names.length' );
+ assert_equals( testEl.properties.names[0], 'foo', 'outer names[0]' );
+ assert_true( !testEl.properties.names[1], 'outer names[1]' );
+ assert_equals( testEl.firstChild.properties.length, 1, 'inner length' );
+ assert_equals( testEl.firstChild.properties[0], testEl.firstChild.firstChild, 'inner properties[0]' );
+ assert_true( !testEl.firstChild.properties[1], 'inner properties[1]' );
+ assert_equals( testEl.firstChild.properties.namedItem('foo').length, 0, 'inner foo.length' );
+ assert_true( !testEl.firstChild.properties.namedItem('foo')[0], 'inner foo[0]' );
+ assert_equals( testEl.firstChild.properties.namedItem('bar').length, 1, 'inner bar.length' );
+ assert_equals( testEl.firstChild.properties.namedItem('bar')[0], testEl.firstChild.firstChild, 'inner bar[0]' );
+ assert_true( !testEl.firstChild.properties.namedItem('foo')[1], 'inner foo[1]' );
+ assert_equals( testEl.firstChild.properties.names.length, 1, 'inner names.length' );
+ assert_equals( testEl.firstChild.properties.names[0], 'bar', 'inner names[0]' );
+ assert_true( !testEl.firstChild.properties.names[1], 'inner names[1]' );
+}, 'simple nested itemscope');
+test(function () {
+ //This should have 1 property on each itemscope, pointing only to its direct child
+ var testEl = makeEl('div',{itemscope:'itemscope',itemref:'id1'},'<div itemscope itemprop="foo" id="id1" itemref="id2"><div itemprop="bar" id="id2"></div></div>');
+ assert_equals( testEl.properties.length, 1, 'outer length' );
+ assert_equals( testEl.properties[0], testEl.firstChild, 'outer properties[0]' );
+ assert_true( !testEl.properties[1], 'outer properties[1]' );
+ assert_equals( testEl.properties.namedItem('foo').length, 1, 'outer foo.length' );
+ assert_equals( testEl.properties.namedItem('foo')[0], testEl.firstChild, 'outer foo[0]' );
+ assert_true( !testEl.properties.namedItem('foo')[1], 'outer foo[1]' );
+ assert_equals( testEl.properties.namedItem('bar').length, 0, 'outer bar.length' );
+ assert_true( !testEl.properties.namedItem('bar')[0], 'outer bar[0]' );
+ assert_equals( testEl.properties.names.length, 1, 'outer names.length' );
+ assert_equals( testEl.properties.names[0], 'foo', 'outer names[0]' );
+ assert_true( !testEl.properties.names[1], 'outer names[1]' );
+ assert_equals( testEl.firstChild.properties.length, 1, 'inner length' );
+ assert_equals( testEl.firstChild.properties[0], testEl.firstChild.firstChild, 'inner properties[0]' );
+ assert_true( !testEl.firstChild.properties[1], 'inner properties[1]' );
+ assert_equals( testEl.firstChild.properties.namedItem('foo').length, 0, 'inner foo.length' );
+ assert_true( !testEl.firstChild.properties.namedItem('foo')[0], 'inner foo[0]' );
+ assert_equals( testEl.firstChild.properties.namedItem('bar').length, 1, 'inner bar.length' );
+ assert_equals( testEl.firstChild.properties.namedItem('bar')[0], testEl.firstChild.firstChild, 'inner bar[0]' );
+ assert_true( !testEl.firstChild.properties.namedItem('foo')[1], 'inner foo[1]' );
+ assert_equals( testEl.firstChild.properties.names.length, 1, 'inner names.length' );
+ assert_equals( testEl.firstChild.properties.names[0], 'bar', 'inner names[0]' );
+ assert_true( !testEl.firstChild.properties.names[1], 'inner names[1]' );
+ document.body.appendChild(testEl);
+ try {
+ assert_equals( testEl.properties.length, 1, 'outer length when appended to document' );
+ assert_equals( testEl.properties[0], testEl.firstChild, 'outer properties[0] when appended to document' );
+ assert_true( !testEl.properties[1], 'outer properties[1] when appended to document' );
+ assert_equals( testEl.properties.namedItem('foo').length, 1, 'outer foo.length when appended to document' );
+ assert_equals( testEl.properties.namedItem('foo')[0], testEl.firstChild, 'outer foo[0] when appended to document' );
+ assert_true( !testEl.properties.namedItem('foo')[1], 'outer foo[1] when appended to document' );
+ assert_equals( testEl.properties.namedItem('bar').length, 0, 'outer bar.length when appended to document' );
+ assert_true( !testEl.properties.namedItem('bar')[0], 'outer bar[0] when appended to document' );
+ assert_equals( testEl.properties.names.length, 1, 'outer names.length when appended to document' );
+ assert_equals( testEl.properties.names[0], 'foo', 'outer names[0] when appended to document' );
+ assert_true( !testEl.properties.names[1], 'outer names[1] when appended to document' );
+ assert_equals( testEl.firstChild.properties.length, 1, 'inner length when appended to document' );
+ assert_equals( testEl.firstChild.properties[0], testEl.firstChild.firstChild, 'inner properties[0] when appended to document' );
+ assert_true( !testEl.firstChild.properties[1], 'inner properties[1] when appended to document' );
+ assert_equals( testEl.firstChild.properties.namedItem('foo').length, 0, 'inner foo.length when appended to document' );
+ assert_true( !testEl.firstChild.properties.namedItem('foo')[0], 'inner foo[0] when appended to document' );
+ assert_equals( testEl.firstChild.properties.namedItem('bar').length, 1, 'inner bar.length when appended to document' );
+ assert_equals( testEl.firstChild.properties.namedItem('bar')[0], testEl.firstChild.firstChild, 'inner bar[0] when appended to document' );
+ assert_true( !testEl.firstChild.properties.namedItem('foo')[1], 'inner foo[1] when appended to document' );
+ assert_equals( testEl.firstChild.properties.names.length, 1, 'inner names.length when appended to document' );
+ assert_equals( testEl.firstChild.properties.names[0], 'bar', 'inner names[0] when appended to document' );
+ assert_true( !testEl.firstChild.properties.names[1], 'inner names[1] when appended to document' );
+ } catch(e) {
+ document.body.removeChild(testEl);
+ throw (e);
+ }
+ document.body.removeChild(testEl);
+}, 'simple nested itemscope with itemref');
+test(function () {
+ //This should have 3 properties on the item; foo, bar and baz
+ var parEl = makeEl('div',{},'<div itemprop="foo" id="id2"></div><div itemscope itemref="id1 id2"><div itemprop="bar"></div></div><div itemprop="baz" id="id1"></div>');
+ var testEl = parEl.childNodes[1];
+ assert_equals( testEl.properties.length, 3, 'length' );
+ assert_equals( testEl.properties[0], parEl.firstChild, 'properties[0]' );
+ assert_equals( testEl.properties[1], testEl.firstChild, 'properties[1]' );
+ assert_equals( testEl.properties[2], parEl.lastChild, 'properties[2]' );
+ assert_true( !testEl.properties[3], 'properties[3]' );
+ assert_equals( testEl.properties.namedItem('foo').length, 1, 'foo.length' );
+ assert_equals( testEl.properties.namedItem('foo')[0], parEl.firstChild, 'foo[0]' );
+ assert_true( !testEl.properties.namedItem('foo')[1], 'foo[1]' );
+ assert_equals( testEl.properties.namedItem('bar').length, 1, 'bar.length' );
+ assert_equals( testEl.properties.namedItem('bar')[0], testEl.firstChild, 'bar[0]' );
+ assert_true( !testEl.properties.namedItem('bar')[1], 'bar[1]' );
+ assert_equals( testEl.properties.namedItem('baz').length, 1, 'baz.length' );
+ assert_equals( testEl.properties.namedItem('baz')[0], parEl.lastChild, 'baz[0]' );
+ assert_true( !testEl.properties.namedItem('baz')[1], 'baz[1]' );
+ assert_equals( testEl.properties.names.length, 3, 'names.length' );
+ assert_equals( testEl.properties.names[0], 'foo', 'names[0]' );
+ assert_equals( testEl.properties.names[1], 'bar', 'names[1]' );
+ assert_equals( testEl.properties.names[2], 'baz', 'names[2]' );
+ assert_true( !testEl.properties.names[3], 'names[3]' );
+ document.body.appendChild(parEl);
+ try {
+ assert_equals( testEl.properties.length, 3, 'length when appended to document' );
+ assert_equals( testEl.properties[0], parEl.firstChild, 'properties[0] when appended to document' );
+ assert_equals( testEl.properties[1], testEl.firstChild, 'properties[1] when appended to document' );
+ assert_equals( testEl.properties[2], parEl.lastChild, 'properties[2] when appended to document' );
+ assert_true( !testEl.properties[3], 'properties[3] when appended to document' );
+ assert_equals( testEl.properties.namedItem('foo').length, 1, 'foo.length when appended to document' );
+ assert_equals( testEl.properties.namedItem('foo')[0], parEl.firstChild, 'foo[0] when appended to document' );
+ assert_true( !testEl.properties.namedItem('foo')[1], 'foo[1] when appended to document' );
+ assert_equals( testEl.properties.namedItem('bar').length, 1, 'bar.length when appended to document' );
+ assert_equals( testEl.properties.namedItem('bar')[0], testEl.firstChild, 'bar[0] when appended to document' );
+ assert_true( !testEl.properties.namedItem('bar')[1], 'bar[1] when appended to document' );
+ assert_equals( testEl.properties.namedItem('baz').length, 1, 'baz.length when appended to document' );
+ assert_equals( testEl.properties.namedItem('baz')[0], parEl.lastChild, 'baz[0] when appended to document' );
+ assert_true( !testEl.properties.namedItem('baz')[1], 'baz[1] when appended to document' );
+ assert_equals( testEl.properties.names.length, 3, 'names.length when appended to document' );
+ assert_equals( testEl.properties.names[0], 'foo', 'names[0] when appended to document' );
+ assert_equals( testEl.properties.names[1], 'bar', 'names[1] when appended to document' );
+ assert_equals( testEl.properties.names[2], 'baz', 'names[2] when appended to document' );
+ assert_true( !testEl.properties.names[3], 'names[3] when appended to document' );
+ } catch(e) {
+ document.body.removeChild(parEl);
+ throw (e);
+ }
+ document.body.removeChild(parEl);
+}, 'simple sibling itemref');
+test(function () {
+ //This should have no properties
+ var testEl = makeEl('div',{itemscope:'itemscope',id:'id1',itemref:'id1',itemprop:'foo'});
+ assert_equals( testEl.properties.length, 0, 'length' );
+ assert_true( !testEl.properties[0], 'properties[0]' );
+ assert_equals( testEl.properties.namedItem('foo').length, 0, 'foo.length' );
+ assert_true( !testEl.properties.namedItem('foo')[0], 'foo[0]' );
+ assert_equals( testEl.properties.names.length, 0, 'names.length' );
+ assert_true( !testEl.properties.names[0], 'names[0]' );
+ document.body.appendChild(testEl);
+ try {
+ assert_equals( testEl.properties.length, 0, 'length when appended to document' );
+ assert_true( !testEl.properties[0], 'properties[0] when appended to document' );
+ assert_equals( testEl.properties.namedItem('foo').length, 0, 'foo.length when appended to document' );
+ assert_true( !testEl.properties.namedItem('foo')[0], 'foo[0] when appended to document' );
+ assert_equals( testEl.properties.names.length, 0, 'names.length when appended to document' );
+ assert_true( !testEl.properties.names[0], 'names[0] when appended to document' );
+ } catch(e) {
+ document.body.removeChild(testEl);
+ throw (e);
+ }
+ document.body.removeChild(testEl);
+}, 'itemref pointing to itself');
+test(function () {
+ //This should have 1 property, pointing to the child
+ var testEl = makeEl('div',{itemscope:'itemscope',id:'id1',itemref:'id1',itemprop:'foo'},'<div itemprop="bar"></div>');
+ assert_equals( testEl.properties.length, 1, 'length' );
+ assert_equals( testEl.properties[0], testEl.firstChild, 'properties[0]' );
+ assert_true( !testEl.properties[1], 'properties[1]' );
+ assert_equals( testEl.properties.namedItem('foo').length, 0, 'foo.length' );
+ assert_true( !testEl.properties.namedItem('foo')[0], 'foo[0]' );
+ assert_equals( testEl.properties.namedItem('bar').length, 1, 'bar.length' );
+ assert_equals( testEl.properties.namedItem('bar')[0], testEl.firstChild, 'bar[0]' );
+ assert_true( !testEl.properties.namedItem('bar')[1], 'bar[1]' );
+ assert_equals( testEl.properties.names.length, 1, 'names.length' );
+ assert_equals( testEl.properties.names[0], 'bar', 'names[0]' );
+ assert_true( !testEl.properties.names[1], 'names[1]' );
+ document.body.appendChild(testEl);
+ try {
+ assert_equals( testEl.properties.length, 1, 'length when appended to document' );
+ assert_equals( testEl.properties[0], testEl.firstChild, 'properties[0] when appended to document' );
+ assert_true( !testEl.properties[1], 'properties[1] when appended to document' );
+ assert_equals( testEl.properties.namedItem('foo').length, 0, 'foo.length when appended to document' );
+ assert_true( !testEl.properties.namedItem('foo')[0], 'foo[0] when appended to document' );
+ assert_equals( testEl.properties.namedItem('bar').length, 1, 'bar.length when appended to document' );
+ assert_equals( testEl.properties.namedItem('bar')[0], testEl.firstChild, 'bar[0] when appended to document' );
+ assert_true( !testEl.properties.namedItem('bar')[1], 'bar[1] when appended to document' );
+ assert_equals( testEl.properties.names.length, 1, 'names.length when appended to document' );
+ assert_equals( testEl.properties.names[0], 'bar', 'names[0] when appended to document' );
+ assert_true( !testEl.properties.names[1], 'names[1] when appended to document' );
+ } catch(e) {
+ document.body.removeChild(testEl);
+ throw (e);
+ }
+ document.body.removeChild(testEl);
+}, 'itemref pointing to itself with child');
+test(function () {
+ //This should have 1 property on each itemscope, pointing only to its direct child
+ var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemscope itemprop="foo" id="id1" itemref="id1"><div itemprop="bar"></div></div>');
+ assert_equals( testEl.properties.length, 1, 'outer length' );
+ assert_equals( testEl.properties[0], testEl.firstChild, 'outer properties[0]' );
+ assert_true( !testEl.properties[1], 'outer properties[1]' );
+ assert_equals( testEl.properties.namedItem('foo').length, 1, 'outer foo.length' );
+ assert_equals( testEl.properties.namedItem('foo')[0], testEl.firstChild, 'outer foo[0]' );
+ assert_true( !testEl.properties.namedItem('foo')[1], 'outer foo[1]' );
+ assert_equals( testEl.properties.namedItem('bar').length, 0, 'outer bar.length' );
+ assert_true( !testEl.properties.namedItem('bar')[0], 'outer bar[0]' );
+ assert_equals( testEl.properties.names.length, 1, 'outer names.length' );
+ assert_equals( testEl.properties.names[0], 'foo', 'outer names[0]' );
+ assert_true( !testEl.properties.names[1], 'outer names[1]' );
+ assert_equals( testEl.firstChild.properties.length, 1, 'inner length' );
+ assert_equals( testEl.firstChild.properties[0], testEl.firstChild.firstChild, 'inner properties[0]' );
+ assert_true( !testEl.firstChild.properties[1], 'inner properties[1]' );
+ assert_equals( testEl.firstChild.properties.namedItem('foo').length, 0, 'inner foo.length' );
+ assert_true( !testEl.firstChild.properties.namedItem('foo')[0], 'inner foo[0]' );
+ assert_equals( testEl.firstChild.properties.namedItem('bar').length, 1, 'inner bar.length' );
+ assert_equals( testEl.firstChild.properties.namedItem('bar')[0], testEl.firstChild.firstChild, 'inner bar[0]' );
+ assert_true( !testEl.firstChild.properties.namedItem('bar')[1], 'inner bar[1]' );
+ assert_equals( testEl.firstChild.properties.names.length, 1, 'inner names.length' );
+ assert_equals( testEl.firstChild.properties.names[0], 'bar', 'inner names[0]' );
+ assert_true( !testEl.firstChild.properties.names[1], 'inner names[1]' );
+ document.body.appendChild(testEl);
+ try {
+ assert_equals( testEl.properties.length, 1, 'outer length when appended to document' );
+ assert_equals( testEl.properties[0], testEl.firstChild, 'outer properties[0] when appended to document' );
+ assert_true( !testEl.properties[1], 'outer properties[1] when appended to document' );
+ assert_equals( testEl.properties.namedItem('foo').length, 1, 'outer foo.length when appended to document' );
+ assert_equals( testEl.properties.namedItem('foo')[0], testEl.firstChild, 'outer foo[0] when appended to document' );
+ assert_true( !testEl.properties.namedItem('foo')[1], 'outer foo[1] when appended to document' );
+ assert_equals( testEl.properties.namedItem('bar').length, 0, 'outer bar.length when appended to document' );
+ assert_true( !testEl.properties.namedItem('bar')[0], 'outer bar[0] when appended to document' );
+ assert_equals( testEl.properties.names.length, 1, 'outer names.length when appended to document' );
+ assert_equals( testEl.properties.names[0], 'foo', 'outer names[0] when appended to document' );
+ assert_true( !testEl.properties.names[1], 'outer names[1] when appended to document' );
+ assert_equals( testEl.firstChild.properties.length, 1, 'inner length when appended to document' );
+ assert_equals( testEl.firstChild.properties[0], testEl.firstChild.firstChild, 'inner properties[0] when appended to document' );
+ assert_true( !testEl.firstChild.properties[1], 'inner properties[1] when appended to document' );
+ assert_equals( testEl.firstChild.properties.namedItem('foo').length, 0, 'inner foo.length when appended to document' );
+ assert_true( !testEl.firstChild.properties.namedItem('foo')[0], 'inner foo[0] when appended to document' );
+ assert_equals( testEl.firstChild.properties.namedItem('bar').length, 1, 'inner bar.length when appended to document' );
+ assert_equals( testEl.firstChild.properties.namedItem('bar')[0], testEl.firstChild.firstChild, 'inner bar[0] when appended to document' );
+ assert_true( !testEl.firstChild.properties.namedItem('bar')[1], 'inner bar[1] when appended to document' );
+ assert_equals( testEl.firstChild.properties.names.length, 1, 'inner names.length when appended to document' );
+ assert_equals( testEl.firstChild.properties.names[0], 'bar', 'inner names[0] when appended to document' );
+ assert_true( !testEl.firstChild.properties.names[1], 'inner names[1] when appended to document' );
+ } catch(e) {
+ document.body.removeChild(testEl);
+ throw (e);
+ }
+ document.body.removeChild(testEl);
+}, 'nested itemref pointing to itself with child');
+test(function () {
+ //Each itemscope has one property, pointing to the other one
+ var testEl = makeEl('div',{},'<div id="id1" itemprop="foo" itemscope itemref="id2"></div><div id="id2" itemprop="bar" itemscope itemref="id1"></div>');
+ assert_equals( testEl.firstChild.properties.length, 1, 'id1 length' );
+ assert_equals( testEl.firstChild.properties[0], testEl.lastChild, 'id1 properties[0]' );
+ assert_true( !testEl.firstChild.properties[1], 'id1 properties[1]' );
+ assert_equals( testEl.firstChild.properties.namedItem('foo').length, 0, 'id1 foo.length' );
+ assert_true( !testEl.firstChild.properties.namedItem('foo')[0], 'id1 foo[0]' );
+ assert_equals( testEl.firstChild.properties.namedItem('bar').length, 1, 'id1 bar.length' );
+ assert_equals( testEl.firstChild.properties.namedItem('bar')[0], testEl.lastChild, 'id1 bar[0]' );
+ assert_true( !testEl.firstChild.properties.namedItem('bar')[1], 'id1 bar[1]' );
+ assert_equals( testEl.firstChild.properties.names.length, 1, 'id1 names.length' );
+ assert_equals( testEl.firstChild.properties.names[0], 'bar', 'id1 names[0]' );
+ assert_true( !testEl.firstChild.properties.names[1], 'id1 names[1]' );
+ assert_equals( testEl.lastChild.properties.length, 1, 'id2 length' );
+ assert_equals( testEl.lastChild.properties[0], testEl.firstChild, 'id2 properties[0]' );
+ assert_true( !testEl.lastChild.properties[1], 'id2 properties[1]' );
+ assert_equals( testEl.lastChild.properties.namedItem('foo').length, 1, 'id2 foo.length' );
+ assert_equals( testEl.lastChild.properties.namedItem('foo')[0], testEl.firstChild, 'id2 foo[0]' );
+ assert_true( !testEl.lastChild.properties.namedItem('foo')[1], 'id2 foo[1]' );
+ assert_equals( testEl.lastChild.properties.namedItem('bar').length, 0, 'id2 bar.length' );
+ assert_true( !testEl.lastChild.properties.namedItem('bar')[0], 'id2 bar[0]' );
+ assert_equals( testEl.lastChild.properties.names.length, 1, 'id2 names.length' );
+ assert_equals( testEl.lastChild.properties.names[0], 'foo', 'id2 names[0]' );
+ assert_true( !testEl.lastChild.properties.names[1], 'id2 names[1]' );
+ document.body.appendChild(testEl);
+ try {
+ assert_equals( testEl.firstChild.properties.length, 1, 'id1 length when appended to document' );
+ assert_equals( testEl.firstChild.properties[0], testEl.lastChild, 'id1 properties[0] when appended to document' );
+ assert_true( !testEl.firstChild.properties[1], 'id1 properties[1] when appended to document' );
+ assert_equals( testEl.firstChild.properties.namedItem('foo').length, 0, 'id1 foo.length when appended to document' );
+ assert_true( !testEl.firstChild.properties.namedItem('foo')[0], 'id1 foo[0] when appended to document' );
+ assert_equals( testEl.firstChild.properties.namedItem('bar').length, 1, 'id1 bar.length when appended to document' );
+ assert_equals( testEl.firstChild.properties.namedItem('bar')[0], testEl.lastChild, 'id1 bar[0] when appended to document' );
+ assert_true( !testEl.firstChild.properties.namedItem('bar')[1], 'id1 bar[1] when appended to document' );
+ assert_equals( testEl.firstChild.properties.names.length, 1, 'id1 names.length when appended to document' );
+ assert_equals( testEl.firstChild.properties.names[0], 'bar', 'id1 names[0] when appended to document' );
+ assert_true( !testEl.firstChild.properties.names[1], 'id1 names[1] when appended to document' );
+ assert_equals( testEl.lastChild.properties.length, 1, 'id2 length when appended to document' );
+ assert_equals( testEl.lastChild.properties[0], testEl.firstChild, 'id2 properties[0] when appended to document' );
+ assert_true( !testEl.lastChild.properties[1], 'id2 properties[1] when appended to document' );
+ assert_equals( testEl.lastChild.properties.namedItem('foo').length, 1, 'id2 foo.length when appended to document' );
+ assert_equals( testEl.lastChild.properties.namedItem('foo')[0], testEl.firstChild, 'id2 foo[0] when appended to document' );
+ assert_true( !testEl.lastChild.properties.namedItem('foo')[1], 'id2 foo[1] when appended to document' );
+ assert_equals( testEl.lastChild.properties.namedItem('bar').length, 0, 'id2 bar.length when appended to document' );
+ assert_true( !testEl.lastChild.properties.namedItem('bar')[0], 'id2 bar[0] when appended to document' );
+ assert_equals( testEl.lastChild.properties.names.length, 1, 'id2 names.length when appended to document' );
+ assert_equals( testEl.lastChild.properties.names[0], 'foo', 'id2 names[0] when appended to document' );
+ assert_true( !testEl.lastChild.properties.names[1], 'id2 names[1] when appended to document' );
+ } catch(e) {
+ document.body.removeChild(testEl);
+ throw (e);
+ }
+ document.body.removeChild(testEl);
+}, 'mutually referencing siblings');
+test(function () {
+ //Root has 2 properties, foo and bar
+ //Each itemscope has one property, pointing to the other one
+ var testEl = makeEl('div',{itemscope:'itemscope'},'<div id="id1" itemprop="foo" itemscope itemref="id2"></div><div id="id2" itemprop="bar" itemscope itemref="id1"></div>');
+ assert_equals( testEl.properties.length, 2, 'root length' );
+ assert_equals( testEl.properties[0], testEl.firstChild, 'root properties[0]' );
+ assert_equals( testEl.properties[1], testEl.lastChild, 'root properties[1]' );
+ assert_true( !testEl.properties[2], 'root properties[2]' );
+ assert_equals( testEl.properties.namedItem('foo').length, 1, 'root foo.length' );
+ assert_equals( testEl.properties.namedItem('foo')[0], testEl.firstChild, 'root foo[0]' );
+ assert_true( !testEl.properties.namedItem('foo')[1], 'root foo[1]' );
+ assert_equals( testEl.properties.namedItem('bar').length, 1, 'root bar.length' );
+ assert_equals( testEl.properties.namedItem('bar')[0], testEl.lastChild, 'root bar[0]' );
+ assert_true( !testEl.properties.namedItem('bar')[1], 'root bar[1]' );
+ assert_equals( testEl.properties.names.length, 2, 'root names.length' );
+ assert_equals( testEl.properties.names[0], 'foo', 'root names[0]' );
+ assert_equals( testEl.properties.names[1], 'bar', 'root names[1]' );
+ assert_true( !testEl.properties.names[2], 'root names[2]' );
+ assert_equals( testEl.firstChild.properties.length, 1, 'id1 length' );
+ assert_equals( testEl.firstChild.properties[0], testEl.lastChild, 'id1 properties[0]' );
+ assert_true( !testEl.firstChild.properties[1], 'id1 properties[1]' );
+ assert_equals( testEl.firstChild.properties.namedItem('foo').length, 0, 'id1 foo.length' );
+ assert_true( !testEl.firstChild.properties.namedItem('foo')[0], 'id1 foo[0]' );
+ assert_equals( testEl.firstChild.properties.namedItem('bar').length, 1, 'id1 bar.length' );
+ assert_equals( testEl.firstChild.properties.namedItem('bar')[0], testEl.lastChild, 'id1 bar[0]' );
+ assert_true( !testEl.firstChild.properties.namedItem('bar')[1], 'id1 bar[1]' );
+ assert_equals( testEl.firstChild.properties.names.length, 1, 'id1 names.length' );
+ assert_equals( testEl.firstChild.properties.names[0], 'bar', 'id1 names[0]' );
+ assert_true( !testEl.firstChild.properties.names[1], 'id1 names[1]' );
+ assert_equals( testEl.lastChild.properties.length, 1, 'id2 length' );
+ assert_equals( testEl.lastChild.properties[0], testEl.firstChild, 'id2 properties[0]' );
+ assert_true( !testEl.lastChild.properties[1], 'id2 properties[1]' );
+ assert_equals( testEl.lastChild.properties.namedItem('foo').length, 1, 'id2 foo.length' );
+ assert_equals( testEl.lastChild.properties.namedItem('foo')[0], testEl.firstChild, 'id2 foo[0]' );
+ assert_true( !testEl.lastChild.properties.namedItem('foo')[1], 'id2 foo[1]' );
+ assert_equals( testEl.lastChild.properties.namedItem('bar').length, 0, 'id2 bar.length' );
+ assert_true( !testEl.lastChild.properties.namedItem('bar')[0], 'id2 bar[0]' );
+ assert_equals( testEl.lastChild.properties.names.length, 1, 'id2 names.length' );
+ assert_equals( testEl.lastChild.properties.names[0], 'foo', 'id2 names[0]' );
+ assert_true( !testEl.lastChild.properties.names[1], 'id2 names[1]' );
+ document.body.appendChild(testEl);
+ try {
+ assert_equals( testEl.properties.length, 2, 'root length when appended to document' );
+ assert_equals( testEl.properties[0], testEl.firstChild, 'root properties[0] when appended to document' );
+ assert_equals( testEl.properties[1], testEl.lastChild, 'root properties[1] when appended to document' );
+ assert_true( !testEl.properties[2], 'root properties[2] when appended to document' );
+ assert_equals( testEl.properties.namedItem('foo').length, 1, 'root foo.length when appended to document' );
+ assert_equals( testEl.properties.namedItem('foo')[0], testEl.firstChild, 'root foo[0] when appended to document' );
+ assert_true( !testEl.properties.namedItem('foo')[1], 'root foo[1] when appended to document' );
+ assert_equals( testEl.properties.namedItem('bar').length, 1, 'root bar.length when appended to document' );
+ assert_equals( testEl.properties.namedItem('bar')[0], testEl.lastChild, 'root bar[0] when appended to document' );
+ assert_true( !testEl.properties.namedItem('bar')[1], 'root bar[1] when appended to document' );
+ assert_equals( testEl.properties.names.length, 2, 'root names.length when appended to document' );
+ assert_equals( testEl.properties.names[0], 'foo', 'root names[0] when appended to document' );
+ assert_equals( testEl.properties.names[1], 'bar', 'root names[1] when appended to document' );
+ assert_true( !testEl.properties.names[2], 'root names[2] when appended to document' );
+ assert_equals( testEl.firstChild.properties.length, 1, 'id1 length when appended to document' );
+ assert_equals( testEl.firstChild.properties[0], testEl.lastChild, 'id1 properties[0] when appended to document' );
+ assert_true( !testEl.firstChild.properties[1], 'id1 properties[1] when appended to document' );
+ assert_equals( testEl.firstChild.properties.namedItem('foo').length, 0, 'id1 foo.length when appended to document' );
+ assert_true( !testEl.firstChild.properties.namedItem('foo')[0], 'id1 foo[0] when appended to document' );
+ assert_equals( testEl.firstChild.properties.namedItem('bar').length, 1, 'id1 bar.length when appended to document' );
+ assert_equals( testEl.firstChild.properties.namedItem('bar')[0], testEl.lastChild, 'id1 bar[0] when appended to document' );
+ assert_true( !testEl.firstChild.properties.namedItem('bar')[1], 'id1 bar[1] when appended to document' );
+ assert_equals( testEl.firstChild.properties.names.length, 1, 'id1 names.length when appended to document' );
+ assert_equals( testEl.firstChild.properties.names[0], 'bar', 'id1 names[0] when appended to document' );
+ assert_true( !testEl.firstChild.properties.names[1], 'id1 names[1] when appended to document' );
+ assert_equals( testEl.lastChild.properties.length, 1, 'id2 length when appended to document' );
+ assert_equals( testEl.lastChild.properties[0], testEl.firstChild, 'id2 properties[0] when appended to document' );
+ assert_true( !testEl.lastChild.properties[1], 'id2 properties[1] when appended to document' );
+ assert_equals( testEl.lastChild.properties.namedItem('foo').length, 1, 'id2 foo.length when appended to document' );
+ assert_equals( testEl.lastChild.properties.namedItem('foo')[0], testEl.firstChild, 'id2 foo[0] when appended to document' );
+ assert_true( !testEl.lastChild.properties.namedItem('foo')[1], 'id2 foo[1] when appended to document' );
+ assert_equals( testEl.lastChild.properties.namedItem('bar').length, 0, 'id2 bar.length when appended to document' );
+ assert_true( !testEl.lastChild.properties.namedItem('bar')[0], 'id2 bar[0] when appended to document' );
+ assert_equals( testEl.lastChild.properties.names.length, 1, 'id2 names.length when appended to document' );
+ assert_equals( testEl.lastChild.properties.names[0], 'foo', 'id2 names[0] when appended to document' );
+ assert_true( !testEl.lastChild.properties.names[1], 'id2 names[1] when appended to document' );
+ } catch(e) {
+ document.body.removeChild(testEl);
+ throw (e);
+ }
+ document.body.removeChild(testEl);
+}, 'mutually referencing siblings with item parent');
+test(function () {
+ //Root has two properties, foo and bar
+ //Bar has two properties, baz and qux
+ //Qux has one property, bar
+ var testEl = makeEl('div',{itemscope:'itemscope'},'<div itemprop="foo"></div><div id="id1" itemprop="bar" itemscope><div itemprop="baz"></div><div itemprop="qux" itemscope itemref="id1"></div></div>');
+ assert_equals( testEl.properties.length, 2, 'root length' );
+ assert_equals( testEl.properties[0], testEl.firstChild, 'root properties[0]' );
+ assert_equals( testEl.properties[1], testEl.lastChild, 'root properties[1]' );
+ assert_true( !testEl.properties[2], 'root properties[2]' );
+ assert_equals( testEl.properties.namedItem('foo').length, 1, 'root foo.length' );
+ assert_equals( testEl.properties.namedItem('foo')[0], testEl.firstChild, 'root foo[0]' );
+ assert_true( !testEl.properties.namedItem('foo')[1], 'root foo[1]' );
+ assert_equals( testEl.properties.namedItem('bar').length, 1, 'root bar.length' );
+ assert_equals( testEl.properties.namedItem('bar')[0], testEl.lastChild, 'root bar[0]' );
+ assert_true( !testEl.properties.namedItem('bar')[1], 'root bar[1]' );
+ assert_equals( testEl.properties.namedItem('baz').length, 0, 'root baz.length' );
+ assert_true( !testEl.properties.namedItem('baz')[0], 'root baz[0]' );
+ assert_equals( testEl.properties.namedItem('qux').length, 0, 'root qux.length' );
+ assert_true( !testEl.properties.namedItem('qux')[0], 'root qux[0]' );
+ assert_equals( testEl.properties.names.length, 2, 'root names.length' );
+ assert_equals( testEl.properties.names[0], 'foo', 'root names[0]' );
+ assert_equals( testEl.properties.names[1], 'bar', 'root names[1]' );
+ assert_true( !testEl.properties.names[2], 'root names[2]' );
+ assert_equals( testEl.lastChild.properties.length, 2, 'bar length' );
+ assert_equals( testEl.lastChild.properties[0], testEl.lastChild.firstChild, 'bar properties[0]' );
+ assert_equals( testEl.lastChild.properties[1], testEl.lastChild.lastChild, 'bar properties[1]' );
+ assert_true( !testEl.lastChild.properties[2], 'bar properties[2]' );
+ assert_equals( testEl.lastChild.properties.namedItem('foo').length, 0, 'bar foo.length' );
+ assert_true( !testEl.lastChild.properties.namedItem('foo')[0], 'bar foo[0]' );
+ assert_equals( testEl.lastChild.properties.namedItem('bar').length, 0, 'bar bar.length' );
+ assert_true( !testEl.lastChild.properties.namedItem('bar')[0], 'bar bar[0]' );
+ assert_equals( testEl.lastChild.properties.namedItem('baz').length, 1, 'bar baz.length' );
+ assert_equals( testEl.lastChild.properties.namedItem('baz')[0], testEl.lastChild.firstChild, 'bar baz[0]' );
+ assert_true( !testEl.lastChild.properties.namedItem('baz')[1], 'bar baz[1]' );
+ assert_equals( testEl.lastChild.properties.namedItem('qux').length, 1, 'bar qux.length' );
+ assert_equals( testEl.lastChild.properties.namedItem('qux')[0], testEl.lastChild.lastChild, 'bar qux[0]' );
+ assert_true( !testEl.lastChild.properties.namedItem('qux')[1], 'bar qux[1]' );
+ assert_equals( testEl.lastChild.properties.names.length, 2, 'bar names.length' );
+ assert_equals( testEl.lastChild.properties.names[0], 'baz', 'bar names[0]' );
+ assert_equals( testEl.lastChild.properties.names[1], 'qux', 'bar names[1]' );
+ assert_true( !testEl.lastChild.properties.names[2], 'bar names[2]' );
+ assert_equals( testEl.lastChild.lastChild.properties.length, 1, 'qux length' );
+ assert_equals( testEl.lastChild.lastChild.properties[0], testEl.lastChild, 'qux properties[0]' );
+ assert_true( !testEl.lastChild.lastChild.properties[1], 'qux properties[1]' );
+ assert_equals( testEl.lastChild.lastChild.properties.namedItem('foo').length, 0, 'qux foo.length' );
+ assert_true( !testEl.lastChild.lastChild.properties.namedItem('foo')[0], 'qux foo[0]' );
+ assert_equals( testEl.lastChild.lastChild.properties.namedItem('bar').length, 1, 'qux bar.length' );
+ assert_equals( testEl.lastChild.lastChild.properties.namedItem('bar')[0], testEl.lastChild, 'qux bar[0]' );
+ assert_true( !testEl.lastChild.lastChild.properties.namedItem('bar')[1], 'qux bar[1]' );
+ assert_equals( testEl.lastChild.lastChild.properties.namedItem('baz').length, 0, 'qux baz.length' );
+ assert_true( !testEl.lastChild.lastChild.properties.namedItem('baz')[0], 'qux baz[0]' );
+ assert_equals( testEl.lastChild.lastChild.properties.namedItem('qux').length, 0, 'qux qux.length' );
+ assert_true( !testEl.lastChild.lastChild.properties.namedItem('qux')[0], 'qux qux[0]' );
+ assert_equals( testEl.lastChild.lastChild.properties.names.length, 1, 'qux names.length' );
+ assert_equals( testEl.lastChild.lastChild.properties.names[0], 'bar', 'qux names[0]' );
+ assert_true( !testEl.lastChild.lastChild.properties.names[1], 'qux names[1]' );
+ document.body.appendChild(testEl);
+ try {
+ assert_equals( testEl.properties.length, 2, 'root length when appended to document' );
+ assert_equals( testEl.properties[0], testEl.firstChild, 'root properties[0] when appended to document' );
+ assert_equals( testEl.properties[1], testEl.lastChild, 'root properties[1] when appended to document' );
+ assert_true( !testEl.properties[2], 'root properties[2] when appended to document' );
+ assert_equals( testEl.properties.namedItem('foo').length, 1, 'root foo.length when appended to document' );
+ assert_equals( testEl.properties.namedItem('foo')[0], testEl.firstChild, 'root foo[0] when appended to document' );
+ assert_true( !testEl.properties.namedItem('foo')[1], 'root foo[1] when appended to document' );
+ assert_equals( testEl.properties.namedItem('bar').length, 1, 'root bar.length when appended to document' );
+ assert_equals( testEl.properties.namedItem('bar')[0], testEl.lastChild, 'root bar[0] when appended to document' );
+ assert_true( !testEl.properties.namedItem('bar')[1], 'root bar[1] when appended to document' );
+ assert_equals( testEl.properties.namedItem('baz').length, 0, 'root baz.length when appended to document' );
+ assert_true( !testEl.properties.namedItem('baz')[0], 'root baz[0] when appended to document' );
+ assert_equals( testEl.properties.namedItem('qux').length, 0, 'root qux.length when appended to document' );
+ assert_true( !testEl.properties.namedItem('qux')[0], 'root qux[0] when appended to document' );
+ assert_equals( testEl.properties.names.length, 2, 'root names.length when appended to document' );
+ assert_equals( testEl.properties.names[0], 'foo', 'root names[0] when appended to document' );
+ assert_equals( testEl.properties.names[1], 'bar', 'root names[1] when appended to document' );
+ assert_true( !testEl.properties.names[2], 'root names[2] when appended to document' );
+ assert_equals( testEl.lastChild.properties.length, 2, 'bar length when appended to document' );
+ assert_equals( testEl.lastChild.properties[0], testEl.lastChild.firstChild, 'bar properties[0] when appended to document' );
+ assert_equals( testEl.lastChild.properties[1], testEl.lastChild.lastChild, 'bar properties[1] when appended to document' );
+ assert_true( !testEl.lastChild.properties[2], 'bar properties[2] when appended to document' );
+ assert_equals( testEl.lastChild.properties.namedItem('foo').length, 0, 'bar foo.length when appended to document' );
+ assert_true( !testEl.lastChild.properties.namedItem('foo')[0], 'bar foo[0] when appended to document' );
+ assert_equals( testEl.lastChild.properties.namedItem('bar').length, 0, 'bar bar.length when appended to document' );
+ assert_true( !testEl.lastChild.properties.namedItem('bar')[0], 'bar bar[0] when appended to document' );
+ assert_equals( testEl.lastChild.properties.namedItem('baz').length, 1, 'bar baz.length when appended to document' );
+ assert_equals( testEl.lastChild.properties.namedItem('baz')[0], testEl.lastChild.firstChild, 'bar baz[0] when appended to document' );
+ assert_true( !testEl.lastChild.properties.namedItem('baz')[1], 'bar baz[1] when appended to document' );
+ assert_equals( testEl.lastChild.properties.namedItem('qux').length, 1, 'bar qux.length when appended to document' );
+ assert_equals( testEl.lastChild.properties.namedItem('qux')[0], testEl.lastChild.lastChild, 'bar qux[0] when appended to document' );
+ assert_true( !testEl.lastChild.properties.namedItem('qux')[1], 'bar qux[1] when appended to document' );
+ assert_equals( testEl.lastChild.properties.names.length, 2, 'bar names.length when appended to document' );
+ assert_equals( testEl.lastChild.properties.names[0], 'baz', 'bar names[0] when appended to document' );
+ assert_equals( testEl.lastChild.properties.names[1], 'qux', 'bar names[1] when appended to document' );
+ assert_true( !testEl.lastChild.properties.names[2], 'bar names[2] when appended to document' );
+ assert_equals( testEl.lastChild.lastChild.properties.length, 1, 'qux length when appended to document' );
+ assert_equals( testEl.lastChild.lastChild.properties[0], testEl.lastChild, 'qux properties[0] when appended to document' );
+ assert_true( !testEl.lastChild.lastChild.properties[1], 'qux properties[1] when appended to document' );
+ assert_equals( testEl.lastChild.lastChild.properties.namedItem('foo').length, 0, 'qux foo.length when appended to document' );
+ assert_true( !testEl.lastChild.lastChild.properties.namedItem('foo')[0], 'qux foo[0] when appended to document' );
+ assert_equals( testEl.lastChild.lastChild.properties.namedItem('bar').length, 1, 'qux bar.length when appended to document' );
+ assert_equals( testEl.lastChild.lastChild.properties.namedItem('bar')[0], testEl.lastChild, 'qux bar[0] when appended to document' );
+ assert_true( !testEl.lastChild.lastChild.properties.namedItem('bar')[1], 'qux bar[1] when appended to document' );
+ assert_equals( testEl.lastChild.lastChild.properties.namedItem('baz').length, 0, 'qux baz.length when appended to document' );
+ assert_true( !testEl.lastChild.lastChild.properties.namedItem('baz')[0], 'qux baz[0] when appended to document' );
+ assert_equals( testEl.lastChild.lastChild.properties.namedItem('qux').length, 0, 'qux qux.length when appended to document' );
+ assert_true( !testEl.lastChild.lastChild.properties.namedItem('qux')[0], 'qux qux[0] when appended to document' );
+ assert_equals( testEl.lastChild.lastChild.properties.names.length, 1, 'qux names.length when appended to document' );
+ assert_equals( testEl.lastChild.lastChild.properties.names[0], 'bar', 'qux names[0] when appended to document' );
+ assert_true( !testEl.lastChild.lastChild.properties.names[1], 'qux names[1] when appended to document' );
+ } catch(e) {
+ document.body.removeChild(testEl);
+ throw (e);
+ }
+ document.body.removeChild(testEl);
+}, 'itemref referencing parent item');
+test(function () {
+ //foo has one property, bar
+ var testEl = makeEl('div',{id:'id1'},'<div itemprop="bar"></div><div itemscope itemref="id1" itemprop="foo"></div>');
+ assert_equals( testEl.lastChild.properties.length, 1, 'length' );
+ assert_equals( testEl.lastChild.properties[0], testEl.firstChild, 'properties[0]' );
+ assert_true( !testEl.lastChild.properties[1], 'properties[1]' );
+ assert_equals( testEl.lastChild.properties.namedItem('foo').length, 0, 'foo.length' );
+ assert_true( !testEl.lastChild.properties.namedItem('foo')[0], 'foo[0]' );
+ assert_equals( testEl.lastChild.properties.namedItem('bar').length, 1, 'bar.length' );
+ assert_equals( testEl.lastChild.properties.namedItem('bar')[0], testEl.firstChild, 'bar[0]' );
+ assert_true( !testEl.lastChild.properties.namedItem('bar')[1], 'bar[1]' );
+ assert_equals( testEl.lastChild.properties.names.length, 1, 'names.length' );
+ assert_equals( testEl.lastChild.properties.names[0], 'bar', 'names[0]' );
+ assert_true( !testEl.lastChild.properties.names[1], 'names[1]' );
+ document.body.appendChild(testEl);
+ try {
+ assert_equals( testEl.lastChild.properties.length, 1, 'length when appended to document' );
+ assert_equals( testEl.lastChild.properties[0], testEl.firstChild, 'properties[0] when appended to document' );
+ assert_true( !testEl.lastChild.properties[1], 'properties[1] when appended to document' );
+ assert_equals( testEl.lastChild.properties.namedItem('foo').length, 0, 'foo.length when appended to document' );
+ assert_true( !testEl.lastChild.properties.namedItem('foo')[0], 'foo[0] when appended to document' );
+ assert_equals( testEl.lastChild.properties.namedItem('bar').length, 1, 'bar.length when appended to document' );
+ assert_equals( testEl.lastChild.properties.namedItem('bar')[0], testEl.firstChild, 'bar[0] when appended to document' );
+ assert_true( !testEl.lastChild.properties.namedItem('bar')[1], 'bar[1] when appended to document' );
+ assert_equals( testEl.lastChild.properties.names.length, 1, 'names.length when appended to document' );
+ assert_equals( testEl.lastChild.properties.names[0], 'bar', 'names[0] when appended to document' );
+ assert_true( !testEl.lastChild.properties.names[1], 'names[1] when appended to document' );
+ } catch(e) {
+ document.body.removeChild(testEl);
+ throw (e);
+ }
+ document.body.removeChild(testEl);
+}, 'itemref referencing parent without itemscope');
+test(function () {
+ var testDiv = makeEl('div', {itemprop:'bar', id:'foo'}, '');
+ var testSpan = makeEl('span', {itemscope:'itemscope', itemref: 'foo', id: 'foo'}, '');
+ document.body.appendChild(testDiv);
+ document.body.appendChild(testSpan);
+ assert_equals(testSpan.properties.length, 1, 'has one property');
+ assert_equals(testSpan.properties[0], testDiv, 'has first property');
+ assert_equals(testSpan.properties.item(0), testDiv, 'has first property');
+ assert_equals(testSpan.properties.namedItem('bar').length, 1, 'has 1 foo property');
+ assert_equals(testSpan.properties.namedItem('bar').item(0), testDiv, 'div is foo property');
+ assert_equals(testSpan.properties.names.length, 1, 'only has one property');
+ document.body.removeChild(testDiv);
+ document.body.removeChild(testSpan);
+}, 'itemref referencing element with same id');
+test(function () {
+ //Root has three properties, foo, bar and baz
+ //Foo has two properties, bar and baz
+ var testEl = makeEl('div',{itemscope:'itemscope',itemref:'id1'},'<div itemscope itemprop="foo"><div itemprop="bar" id="id1"><div itemprop="baz"></div></div></div>');
+ assert_equals( testEl.properties.length, 3, 'outer length' );
+ assert_equals( testEl.properties[0], testEl.firstChild, 'outer properties[0]' );
+ assert_equals( testEl.properties[1], testEl.firstChild.firstChild, 'outer properties[1]' );
+ assert_equals( testEl.properties[2], testEl.firstChild.firstChild.firstChild, 'outer properties[2]' );
+ assert_true( !testEl.properties[3], 'outer properties[3]' );
+ assert_equals( testEl.properties.namedItem('foo').length, 1, 'outer foo.length' );
+ assert_equals( testEl.properties.namedItem('foo')[0], testEl.firstChild, 'outer foo[0]' );
+ assert_true( !testEl.properties.namedItem('foo')[1], 'outer foo[1]' );
+ assert_equals( testEl.properties.namedItem('bar').length, 1, 'outer bar.length' );
+ assert_equals( testEl.properties.namedItem('bar')[0], testEl.firstChild.firstChild, 'outer bar[0]' );
+ assert_true( !testEl.properties.namedItem('bar')[1], 'outer bar[1]' );
+ assert_equals( testEl.properties.namedItem('baz').length, 1, 'outer baz.length' );
+ assert_equals( testEl.properties.namedItem('baz')[0], testEl.firstChild.firstChild.firstChild, 'outer baz[0]' );
+ assert_true( !testEl.properties.namedItem('baz')[1], 'outer baz[1]' );
+ assert_equals( testEl.properties.names.length, 3, 'outer names.length' );
+ assert_equals( testEl.properties.names[0], 'foo', 'outer names[0]' );
+ assert_equals( testEl.properties.names[1], 'bar', 'outer names[1]' );
+ assert_equals( testEl.properties.names[2], 'baz', 'outer names[2]' );
+ assert_true( !testEl.properties.names[3], 'outer names[3]' );
+ assert_equals( testEl.firstChild.properties.length, 2, 'inner length' );
+ assert_equals( testEl.firstChild.properties[0], testEl.firstChild.firstChild, 'inner properties[0]' );
+ assert_equals( testEl.firstChild.properties[1], testEl.firstChild.firstChild.firstChild, 'inner properties[1]' );
+ assert_true( !testEl.firstChild.properties[2], 'inner properties[2]' );
+ assert_equals( testEl.firstChild.properties.namedItem('foo').length, 0, 'inner foo.length' );
+ assert_true( !testEl.firstChild.properties.namedItem('foo')[0], 'inner foo[0]' );
+ assert_equals( testEl.firstChild.properties.namedItem('bar').length, 1, 'inner bar.length' );
+ assert_equals( testEl.firstChild.properties.namedItem('bar')[0], testEl.firstChild.firstChild, 'inner bar[0]' );
+ assert_true( !testEl.firstChild.properties.namedItem('bar')[1], 'inner bar[1]' );
+ assert_equals( testEl.firstChild.properties.namedItem('baz').length, 1, 'inner baz.length' );
+ assert_equals( testEl.firstChild.properties.namedItem('baz')[0], testEl.firstChild.firstChild.firstChild, 'inner baz[0]' );
+ assert_true( !testEl.firstChild.properties.namedItem('baz')[1], 'inner baz[1]' );
+ assert_equals( testEl.firstChild.properties.names.length, 2, 'inner names.length' );
+ assert_equals( testEl.firstChild.properties.names[0], 'bar', 'inner names[0]' );
+ assert_equals( testEl.firstChild.properties.names[1], 'baz', 'inner names[1]' );
+ assert_true( !testEl.firstChild.properties.names[2], 'inner names[2]' );
+ document.body.appendChild(testEl);
+ try {
+ assert_equals( testEl.properties.length, 3, 'outer length when appended to document' );
+ assert_equals( testEl.properties[0], testEl.firstChild, 'outer properties[0] when appended to document' );
+ assert_equals( testEl.properties[1], testEl.firstChild.firstChild, 'outer properties[1] when appended to document' );
+ assert_equals( testEl.properties[2], testEl.firstChild.firstChild.firstChild, 'outer properties[2] when appended to document' );
+ assert_true( !testEl.properties[3], 'outer properties[3] when appended to document' );
+ assert_equals( testEl.properties.namedItem('foo').length, 1, 'outer foo.length when appended to document' );
+ assert_equals( testEl.properties.namedItem('foo')[0], testEl.firstChild, 'outer foo[0] when appended to document' );
+ assert_true( !testEl.properties.namedItem('foo')[1], 'outer foo[1] when appended to document' );
+ assert_equals( testEl.properties.namedItem('bar').length, 1, 'outer bar.length when appended to document' );
+ assert_equals( testEl.properties.namedItem('bar')[0], testEl.firstChild.firstChild, 'outer bar[0] when appended to document' );
+ assert_true( !testEl.properties.namedItem('bar')[1], 'outer bar[1] when appended to document' );
+ assert_equals( testEl.properties.namedItem('baz').length, 1, 'outer baz.length when appended to document' );
+ assert_equals( testEl.properties.namedItem('baz')[0], testEl.firstChild.firstChild.firstChild, 'outer baz[0] when appended to document' );
+ assert_true( !testEl.properties.namedItem('baz')[1], 'outer baz[1] when appended to document' );
+ assert_equals( testEl.properties.names.length, 3, 'outer names.length when appended to document' );
+ assert_equals( testEl.properties.names[0], 'foo', 'outer names[0] when appended to document' );
+ assert_equals( testEl.properties.names[1], 'bar', 'outer names[1] when appended to document' );
+ assert_equals( testEl.properties.names[2], 'baz', 'outer names[2] when appended to document' );
+ assert_true( !testEl.properties.names[3], 'outer names[3] when appended to document' );
+ assert_equals( testEl.firstChild.properties.length, 2, 'inner length when appended to document' );
+ assert_equals( testEl.firstChild.properties[0], testEl.firstChild.firstChild, 'inner properties[0] when appended to document' );
+ assert_equals( testEl.firstChild.properties[1], testEl.firstChild.firstChild.firstChild, 'inner properties[1] when appended to document' );
+ assert_true( !testEl.firstChild.properties[2], 'inner properties[2] when appended to document' );
+ assert_equals( testEl.firstChild.properties.namedItem('foo').length, 0, 'inner foo.length when appended to document' );
+ assert_true( !testEl.firstChild.properties.namedItem('foo')[0], 'inner foo[0] when appended to document' );
+ assert_equals( testEl.firstChild.properties.namedItem('bar').length, 1, 'inner bar.length when appended to document' );
+ assert_equals( testEl.firstChild.properties.namedItem('bar')[0], testEl.firstChild.firstChild, 'inner bar[0] when appended to document' );
+ assert_true( !testEl.firstChild.properties.namedItem('bar')[1], 'inner bar[1] when appended to document' );
+ assert_equals( testEl.firstChild.properties.namedItem('baz').length, 1, 'inner baz.length when appended to document' );
+ assert_equals( testEl.firstChild.properties.namedItem('baz')[0], testEl.firstChild.firstChild.firstChild, 'inner baz[0] when appended to document' );
+ assert_true( !testEl.firstChild.properties.namedItem('baz')[1], 'inner baz[1] when appended to document' );
+ assert_equals( testEl.firstChild.properties.names.length, 2, 'inner names.length when appended to document' );
+ assert_equals( testEl.firstChild.properties.names[0], 'bar', 'inner names[0] when appended to document' );
+ assert_equals( testEl.firstChild.properties.names[1], 'baz', 'inner names[1] when appended to document' );
+ assert_true( !testEl.firstChild.properties.names[2], 'inner names[2] when appended to document' );
+ } catch(e) {
+ document.body.removeChild(testEl);
+ throw (e);
+ }
+ document.body.removeChild(testEl);
+}, 'itemref pointing to child of nested itemscope');
+
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/microdata/microdata-dom-api/htmlpropertiescollection/.gitkeep b/tests/wpt/web-platform-tests/microdata/microdata-dom-api/htmlpropertiescollection/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/microdata/microdata-dom-api/htmlpropertiescollection/.gitkeep
diff --git a/tests/wpt/web-platform-tests/microdata/terminology/.gitkeep b/tests/wpt/web-platform-tests/microdata/terminology/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/microdata/terminology/.gitkeep
diff --git a/tests/wpt/web-platform-tests/navigation-timing/idlharness.html b/tests/wpt/web-platform-tests/navigation-timing/idlharness.html
new file mode 100644
index 00000000000..edf1a669ea1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/navigation-timing/idlharness.html
@@ -0,0 +1,119 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Navigation Timing IDL tests</title>
+<link rel="author" title="W3C" href="http://www.w3.org/" />
+<link rel="help" href="http://www.w3.org/TR/navigation-timing/#sec-navigation-timing-interface"/>
+<link rel="help" href="http://www.w3.org/TR/navigation-timing/#sec-navigation-info-interface"/>
+<link rel="help" href="http://www.w3.org/TR/navigation-timing/#sec-window.performance-attribute"/>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/webidl2/lib/webidl2.js"></script>
+<script src="/resources/idlharness.js"></script>
+</head>
+<body>
+<h1>Navigation Timing IDL tests</h1>
+<div id="log"></div>
+
+<pre id='untested_idl' style='display:none'>
+
+interface Window {
+};
+
+callback interface EventListener {
+ void handleEvent(Event event);
+};
+
+interface Event {
+ // PhaseType
+ const unsigned short NONE = 0;
+ const unsigned short CAPTURING_PHASE = 1;
+ const unsigned short AT_TARGET = 2;
+ const unsigned short BUBBLING_PHASE = 3;
+ readonly attribute DOMString type;
+ readonly attribute EventTarget? target;
+ readonly attribute EventTarget? currentTarget;
+ readonly attribute unsigned short eventPhase;
+ readonly attribute boolean bubbles;
+ readonly attribute boolean cancelable;
+ readonly attribute DOMTimeStamp timeStamp;
+ void stopPropagation ();
+ void preventDefault ();
+ void initEvent (DOMString eventTypeArg, boolean bubblesArg, boolean cancelableArg);
+ // Introduced in DOM Level 3
+ void stopImmediatePropagation ();
+ readonly attribute boolean defaultPrevented;
+ readonly attribute boolean isTrusted;
+};
+
+interface EventTarget {
+ // Modified in DOM Level 3
+ void addEventListener (DOMString type, EventListener? listener, optional boolean useCapture = false);
+ void removeEventListener (DOMString type, EventListener? listener, optional boolean useCapture = false);
+ boolean dispatchEvent (Event event);
+};
+
+</pre>
+
+<pre id='idl'>
+interface PerformanceTiming {
+ readonly attribute unsigned long long navigationStart;
+ readonly attribute unsigned long long unloadEventStart;
+ readonly attribute unsigned long long unloadEventEnd;
+ readonly attribute unsigned long long redirectStart;
+ readonly attribute unsigned long long redirectEnd;
+ readonly attribute unsigned long long fetchStart;
+ readonly attribute unsigned long long domainLookupStart;
+ readonly attribute unsigned long long domainLookupEnd;
+ readonly attribute unsigned long long connectStart;
+ readonly attribute unsigned long long connectEnd;
+ readonly attribute unsigned long long secureConnectionStart;
+ readonly attribute unsigned long long requestStart;
+ readonly attribute unsigned long long responseStart;
+ readonly attribute unsigned long long responseEnd;
+ readonly attribute unsigned long long domLoading;
+ readonly attribute unsigned long long domInteractive;
+ readonly attribute unsigned long long domContentLoadedEventStart;
+ readonly attribute unsigned long long domContentLoadedEventEnd;
+ readonly attribute unsigned long long domComplete;
+ readonly attribute unsigned long long loadEventStart;
+ readonly attribute unsigned long long loadEventEnd;
+};
+
+interface PerformanceNavigation {
+ const unsigned short TYPE_NAVIGATE = 0;
+ const unsigned short TYPE_RELOAD = 1;
+ const unsigned short TYPE_BACK_FORWARD = 2;
+ const unsigned short TYPE_RESERVED = 255;
+ readonly attribute unsigned short type;
+ readonly attribute unsigned short redirectCount;
+};
+
+interface Performance : EventTarget {
+ readonly attribute PerformanceTiming timing;
+ readonly attribute PerformanceNavigation navigation;
+};
+
+partial interface Window {
+ [Replaceable] readonly attribute Performance performance;
+};
+</pre>
+
+<script>
+(function() {
+ var idl_array = new IdlArray();
+
+ idl_array.add_untested_idls(document.getElementById("untested_idl").textContent);
+ idl_array.add_idls(document.getElementById("idl").textContent);
+
+ idl_array.add_objects({Window: ["window"],
+ Performance: ["window.performance"],
+ PerformanceNavigation: ["window.performance.navigation"],
+ PerformanceTiming: ["window.performance.timing"]});
+
+ idl_array.test();
+})();
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/navigation-timing/resources/blank_page_green.html b/tests/wpt/web-platform-tests/navigation-timing/resources/blank_page_green.html
new file mode 100644
index 00000000000..b8a1947b77e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/navigation-timing/resources/blank_page_green.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
+ <title>Green Test Page</title>
+ </head>
+ <body style="background-color:#00FF00;">
+ <h1>Placeholder</h1>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/navigation-timing/resources/blank_page_green_with_onunload.html b/tests/wpt/web-platform-tests/navigation-timing/resources/blank_page_green_with_onunload.html
new file mode 100644
index 00000000000..2f401747b01
--- /dev/null
+++ b/tests/wpt/web-platform-tests/navigation-timing/resources/blank_page_green_with_onunload.html
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
+ <title>Green Test Page</title>
+ </head>
+ <!-- use onunload to ensure this does not trigger bfcache -->
+ <body style="background-color:#00FF00;" onunload="1;">
+ <h1>Placeholder</h1>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/navigation-timing/resources/blank_page_meta_redirect.html b/tests/wpt/web-platform-tests/navigation-timing/resources/blank_page_meta_redirect.html
new file mode 100644
index 00000000000..50d6e705717
--- /dev/null
+++ b/tests/wpt/web-platform-tests/navigation-timing/resources/blank_page_meta_redirect.html
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
+ <meta http-equiv="refresh" content="1;URL='blank_page_green.html'" />
+ <title>Redirect Placeholder</title>
+ </head>
+ <body style="background-color:#FFFF00";>
+ <h1>Placeholder</h1>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/navigation-timing/resources/blank_page_unload.html b/tests/wpt/web-platform-tests/navigation-timing/resources/blank_page_unload.html
new file mode 100644
index 00000000000..bb2a27f168e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/navigation-timing/resources/blank_page_unload.html
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
+
+ <title>Yellow Test Page</title>
+
+ <script type="text/javascript">
+ function onbeforeunload_handler()
+ {
+ var temp = "onbeforeunload";
+ }
+
+ function onunload_handler()
+ {
+ var temp = "onunload";
+ }
+ </script>
+ </head>
+ <body onbeforeunload="onbeforeunload_handler();"
+ onunload="onunload_handler();"
+ style="background-color:#FFFF00;">
+ <h1>Unload</h1>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/navigation-timing/resources/blank_page_yellow.html b/tests/wpt/web-platform-tests/navigation-timing/resources/blank_page_yellow.html
new file mode 100644
index 00000000000..4e5e1a000c9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/navigation-timing/resources/blank_page_yellow.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
+ <title>Yellow Test Page</title>
+ </head>
+ <body style="background-color:#FFFF00;">
+ <h1>Placeholder</h1>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/navigation-timing/resources/blank_page_yellow_with_onunload.html b/tests/wpt/web-platform-tests/navigation-timing/resources/blank_page_yellow_with_onunload.html
new file mode 100644
index 00000000000..771e0701d9c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/navigation-timing/resources/blank_page_yellow_with_onunload.html
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
+ <title>Yellow Test Page</title>
+ </head>
+ <!-- use onunload to ensure this does not trigger bfcache -->
+ <body style="background-color:#FFFF00;" onunload="1;">
+ <h1>Placeholder</h1>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/navigation-timing/resources/webperftestharness.js b/tests/wpt/web-platform-tests/navigation-timing/resources/webperftestharness.js
new file mode 100644
index 00000000000..750946dde20
--- /dev/null
+++ b/tests/wpt/web-platform-tests/navigation-timing/resources/webperftestharness.js
@@ -0,0 +1,155 @@
+/*
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+ */
+
+//
+// Helper Functions for NavigationTiming W3C tests
+//
+
+var performanceNamespace = window.performance;
+var timingAttributes = [
+ 'connectEnd',
+ 'connectStart',
+ 'domComplete',
+ 'domContentLoadedEventEnd',
+ 'domContentLoadedEventStart',
+ 'domInteractive',
+ 'domLoading',
+ 'domainLookupEnd',
+ 'domainLookupStart',
+ 'fetchStart',
+ 'loadEventEnd',
+ 'loadEventStart',
+ 'navigationStart',
+ 'redirectEnd',
+ 'redirectStart',
+ 'requestStart',
+ 'responseEnd',
+ 'responseStart',
+ 'unloadEventEnd',
+ 'unloadEventStart'
+];
+
+var namespace_check = false;
+
+//
+// All test() functions in the WebPerf test suite should use wp_test() instead.
+//
+// wp_test() validates the window.performance namespace exists prior to running tests and
+// immediately shows a single failure if it does not.
+//
+
+function wp_test(func, msg, properties)
+{
+ // only run the namespace check once
+ if (!namespace_check)
+ {
+ namespace_check = true;
+
+ if (performanceNamespace === undefined || performanceNamespace == null)
+ {
+ // show a single error that window.performance is undefined
+ test(function() { assert_true(performanceNamespace !== undefined && performanceNamespace != null, "window.performance is defined and not null"); }, "window.performance is defined and not null.", {author:"W3C http://www.w3.org/",help:"http://www.w3.org/TR/navigation-timing/#sec-window.performance-attribute",assert:"The window.performance attribute provides a hosting area for performance related attributes. "});
+ }
+ }
+
+ test(func, msg, properties);
+}
+
+function test_namespace(child_name, skip_root)
+{
+ if (skip_root === undefined) {
+ var msg = 'window.performance is defined';
+ wp_test(function () { assert_true(performanceNamespace !== undefined, msg); }, msg,{author:"W3C http://www.w3.org/",help:"http://www.w3.org/TR/navigation-timing/#sec-window.performance-attribute",assert:"The window.performance attribute provides a hosting area for performance related attributes. "});
+ }
+
+ if (child_name !== undefined) {
+ var msg2 = 'window.performance.' + child_name + ' is defined';
+ wp_test(function() { assert_true(performanceNamespace[child_name] !== undefined, msg2); }, msg2,{author:"W3C http://www.w3.org/",help:"http://www.w3.org/TR/navigation-timing/#sec-window.performance-attribute",assert:"The window.performance attribute provides a hosting area for performance related attributes. "});
+ }
+}
+
+function test_attribute_exists(parent_name, attribute_name, properties)
+{
+ var msg = 'window.performance.' + parent_name + '.' + attribute_name + ' is defined.';
+ wp_test(function() { assert_true(performanceNamespace[parent_name][attribute_name] !== undefined, msg); }, msg, properties);
+}
+
+function test_enum(parent_name, enum_name, value, properties)
+{
+ var msg = 'window.performance.' + parent_name + '.' + enum_name + ' is defined.';
+ wp_test(function() { assert_true(performanceNamespace[parent_name][enum_name] !== undefined, msg); }, msg, properties);
+
+ msg = 'window.performance.' + parent_name + '.' + enum_name + ' = ' + value;
+ wp_test(function() { assert_equals(performanceNamespace[parent_name][enum_name], value, msg); }, msg, properties);
+}
+
+function test_timing_order(attribute_name, greater_than_attribute, properties)
+{
+ // ensure it's not 0 first
+ var msg = "window.performance.timing." + attribute_name + " > 0";
+ wp_test(function() { assert_true(performanceNamespace.timing[attribute_name] > 0, msg); }, msg, properties);
+
+ // ensure it's in the right order
+ msg = "window.performance.timing." + attribute_name + " >= window.performance.timing." + greater_than_attribute;
+ wp_test(function() { assert_true(performanceNamespace.timing[attribute_name] >= performanceNamespace.timing[greater_than_attribute], msg); }, msg, properties);
+}
+
+function test_timing_greater_than(attribute_name, greater_than, properties)
+{
+ var msg = "window.performance.timing." + attribute_name + " > " + greater_than;
+ test_greater_than(performanceNamespace.timing[attribute_name], greater_than, msg, properties);
+}
+
+function test_timing_equals(attribute_name, equals, msg, properties)
+{
+ var test_msg = msg || "window.performance.timing." + attribute_name + " == " + equals;
+ test_equals(performanceNamespace.timing[attribute_name], equals, test_msg, properties);
+}
+
+//
+// Non-test related helper functions
+//
+
+function sleep_milliseconds(n)
+{
+ var start = new Date().getTime();
+ while (true) {
+ if ((new Date().getTime() - start) >= n) break;
+ }
+}
+
+//
+// Common helper functions
+//
+
+function test_true(value, msg, properties)
+{
+ wp_test(function () { assert_true(value, msg); }, msg, properties);
+}
+
+function test_equals(value, equals, msg, properties)
+{
+ wp_test(function () { assert_equals(value, equals, msg); }, msg, properties);
+}
+
+function test_greater_than(value, greater_than, msg, properties)
+{
+ wp_test(function () { assert_true(value > greater_than, msg); }, msg, properties);
+}
+
+function test_greater_or_equals(value, greater_than, msg, properties)
+{
+ wp_test(function () { assert_true(value >= greater_than, msg); }, msg, properties);
+}
+
+function test_not_equals(value, notequals, msg, properties)
+{
+ wp_test(function() { assert_true(value !== notequals, msg); }, msg, properties);
+}
diff --git a/tests/wpt/web-platform-tests/navigation-timing/test_document_open.html b/tests/wpt/web-platform-tests/navigation-timing/test_document_open.html
new file mode 100644
index 00000000000..ca88bf0ef5c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/navigation-timing/test_document_open.html
@@ -0,0 +1,83 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8" />
+<title>window.performance.timing for dynamically created documents</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+<link rel="help" href="http://www.w3.org/TR/navigation-timing/#sec-navigation-timing-interface"/>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/webperftestharness.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css" />
+<script>
+setup({explicit_done: true});
+
+// explicitly test the namespace before we start testing
+test_namespace();
+
+var originalTiming = {};
+var didOpen = false;
+
+function onload_test() {
+ if (!didOpen) {
+ setTimeout(testTimingWithDocumentOpen, 0);
+ didOpen = true;
+ }
+}
+
+function testTimingWithDocumentOpen() {
+ var subcontentWindow = document.getElementById("frameContext").contentWindow;
+
+ if (subcontentWindow.performance === undefined)
+ {
+ // avoid script errors
+ done();
+ return;
+ }
+
+ var timing = subcontentWindow.performance.timing;
+ for (i in timingAttributes) {
+ originalTiming[timingAttributes[i]] = timing[timingAttributes[i]];
+ }
+
+ var subdocument = subcontentWindow.document;
+ subdocument.open();
+ subdocument.write('<!DOCTYPE HTML>');
+ subdocument.write('<html>');
+ subdocument.write('<head>');
+ subdocument.write('<meta charset="utf-8" />');
+ subdocument.write('<title><Green Test Page</title>');
+ subdocument.write('</head>');
+ subdocument.write('<body style="background-color:#00FF00;">');
+ subdocument.write('</body>');
+ subdocument.write('</html>');
+ subdocument.close();
+
+ setTimeout(function() {
+ var timing = subcontentWindow.performance.timing;
+ for (var i in timingAttributes) {
+ test_equals(timing[timingAttributes[i]],
+ originalTiming[timingAttributes[i]],
+ timingAttributes[i] + " is the same after document open.");
+ }
+ done();
+ }, 0);
+}
+</script>
+</head>
+<body>
+<h1>Description</h1>
+<p>This test validates window.performance.timing remains constant when a
+document is replaced using document.open.</p>
+
+<p>This page should be loaded with a yellow frame below. It then replaces the
+document in that frame with a green document.</p>
+
+<p>The test passes if all of the checks to performance.timing are correct and
+the frame below ends with a green background.</p>
+
+<div id="log"></div>
+<br />
+<iframe id="frameContext" onload="onload_test();" src="resources/blank_page_yellow.html" style="width: 250px; height: 250px;"></iframe>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/navigation-timing/test_document_readiness_exist.html b/tests/wpt/web-platform-tests/navigation-timing/test_document_readiness_exist.html
new file mode 100644
index 00000000000..a55ca75ff59
--- /dev/null
+++ b/tests/wpt/web-platform-tests/navigation-timing/test_document_readiness_exist.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8" />
+ <title>document.readyState values exist during a navigation</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://www.w3.org/TR/html5/dom.html#resource-metadata-management"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="stylesheet" href="/resources/testharness.css" />
+ <script>
+ setup({ explicit_done: true });
+ var has_loading = (document.readyState == "loading");
+ var has_interactive = (document.readyState == "interactive");
+ var has_complete = (document.readyState == "complete");
+
+ document.onreadystatechange = function()
+ {
+ if (document.readyState == "loading")
+ {
+ has_loading = true;
+ }
+ if (document.readyState == "interactive")
+ {
+ has_interactive = true;
+ }
+ if (document.readyState = "complete")
+ {
+ has_complete = true;
+ }
+ };
+
+ function onload_test()
+ {
+ test(function () { assert_true(has_loading); }, "Document readiness has loading state.");
+ test(function () { assert_true(has_interactive); }, "Document readiness has interactive state.");
+ test(function () { assert_true(has_complete); }, "Document readiness has complete state.");
+ done();
+ }
+ </script>
+
+</head>
+<body onload="onload_test();">
+ <h1>Description</h1>
+ <p>This test validates that the "loading", "interactive" and "complete"
+ document.readyState states are available during a navigation.</p>
+ <p>Refresh this page to guarantee all readyState phases.</p>
+ <div id="log"></div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/navigation-timing/test_navigate_within_document.html b/tests/wpt/web-platform-tests/navigation-timing/test_navigate_within_document.html
new file mode 100644
index 00000000000..e35d67df8e9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/navigation-timing/test_navigate_within_document.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" >
+ <title>window.performance.timing in document navigation</title>
+ <link rel="author" title="Google" href="http://www.google.com/" />
+ <link rel="help" href="http://www.w3.org/TR/navigation-timing/#sec-navigation-timing-interface"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="resources/webperftestharness.js"></script>
+ </head>
+ <body>
+ <h1>Description</h1>
+ <p>This test validates that all of the window.performance.timing attributes remain unchanged after an in document navigation (URL fragment change).</p>
+
+ <div id="log"></div>
+ <script>
+ setup({explicit_done: true});
+
+ // explicitly test the namespace before we start testing
+ test_namespace('timing');
+
+ var timing;
+
+ function check_timing_not_changed()
+ {
+ for (var i = 0; i < timingAttributes.length; ++i)
+ {
+ var property = timingAttributes[i];
+ test_equals(timing[property], initial_timing[property],
+ property + " is the same after in document navigation.");
+ }
+ done();
+ }
+
+ var initial_timing = {};
+ function save_timing_after_load()
+ {
+ for (var i = 0; i < timingAttributes.length; ++i)
+ {
+ var property = timingAttributes[i];
+ initial_timing[property] = timing[property];
+ }
+ window.location.href = "#1";
+ setTimeout("check_timing_not_changed()", 0);
+ }
+
+ function load_handler()
+ {
+ if (performanceNamespace === undefined)
+ {
+ // avoid script errors
+ done();
+ return;
+ }
+
+ timing = performanceNamespace.timing;
+
+ window.removeEventListener("load", load_handler);
+ setTimeout("save_timing_after_load()", 0);
+ }
+
+ window.addEventListener("load", load_handler, false);
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/navigation-timing/test_navigation_attributes_exist.html b/tests/wpt/web-platform-tests/navigation-timing/test_navigation_attributes_exist.html
new file mode 100644
index 00000000000..465409ea413
--- /dev/null
+++ b/tests/wpt/web-platform-tests/navigation-timing/test_navigation_attributes_exist.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>window.performance.navigation attributes</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://www.w3.org/TR/navigation-timing/#sec-navigation-info-interface"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="resources/webperftestharness.js"></script>
+ </head>
+ <body>
+ <h1>Description</h1>
+ <p>This test validates that all of the window.performance.navigation attributes exist (but does not validate that their values are correct).</p>
+
+ <div id="log"></div>
+
+ <script>
+ test_namespace('navigation');
+
+ test_attribute_exists('navigation', 'type');
+ test_attribute_exists('navigation', 'redirectCount');
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/navigation-timing/test_navigation_redirectCount_none.html b/tests/wpt/web-platform-tests/navigation-timing/test_navigation_redirectCount_none.html
new file mode 100644
index 00000000000..2046b32cd64
--- /dev/null
+++ b/tests/wpt/web-platform-tests/navigation-timing/test_navigation_redirectCount_none.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>window.performance.navigation.redirectCount on a non-redirected navigation</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://www.w3.org/TR/navigation-timing/#sec-navigation-timing-interface"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="resources/webperftestharness.js"></script>
+ </head>
+ <body>
+ <h1>Description</h1>
+ <p>This test validates that the value of the window.performance.navigation.redirectCount attribute, as well as the window.performance.timing.redirectStart and redirectEnd attributes on a non-redirected navigation.</p>
+
+ <div id="log"></div>
+
+ <script>
+ test_namespace('navigation');
+
+ if (performanceNamespace !== undefined)
+ {
+ test_equals(performanceNamespace.timing.redirectStart, 0, 'timing.redirectStart on an non-redirected navigation');
+ test_equals(performanceNamespace.timing.redirectEnd, 0, 'timing.redirectEnd on an non-redirected navigation');
+ test_equals(performanceNamespace.navigation.redirectCount, 0, 'navigation.redirectCount on an non-redirected navigation',{help:"http://www.w3.org/TR/navigation-timing/#sec-navigation-info-interface"});
+ }
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/navigation-timing/test_navigation_type_backforward.html b/tests/wpt/web-platform-tests/navigation-timing/test_navigation_type_backforward.html
new file mode 100644
index 00000000000..3583347093d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/navigation-timing/test_navigation_type_backforward.html
@@ -0,0 +1,96 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>window.navigation.type for back and forward navigations</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://www.w3.org/TR/navigation-timing/#sec-navigation-info-interface"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="resources/webperftestharness.js"></script>
+ <link rel="stylesheet" href="/resources/testharness.css" />
+ <script>
+ setup({explicit_done: true});
+
+ // explicitly test the namespace before we start testing
+ test_namespace('navigation');
+
+ function onload_test()
+ {
+ if (performanceNamespace === undefined)
+ {
+ // avoid script errors
+ done();
+ return;
+ }
+
+ // do this with a timeout to see the visuals of the navigations.
+ setTimeout("nav_frame();", 100);
+ }
+
+ var step = 1;
+ function nav_frame()
+ {
+ var navigation_frame = document.getElementById("frameContext").contentWindow;
+ switch (step)
+ {
+ case 1:
+ {
+ navigation_frame.location.href = '/navigation-timing/resources/blank_page_green_with_onunload.html';
+ step++;
+ break;
+ }
+ case 2:
+ {
+ test_equals(navigation_frame.performance.navigation.type,
+ performanceNamespace.navigation.TYPE_NAVIGATE,
+ 'window.performance.navigation.type == TYPE_NAVIGATE');
+ navigation_frame.history.back();
+ step++;
+ break;
+ }
+ case 3:
+ {
+ test_equals(navigation_frame.performance.navigation.type,
+ performanceNamespace.navigation.TYPE_BACK_FORWARD,
+ 'window.performance.navigation.type == TYPE_BACK_FORWARD after history.back()');
+ step++;
+ navigation_frame.history.forward();
+ break;
+ }
+ case 4:
+ {
+ test_equals(navigation_frame.performance.navigation.type,
+ performanceNamespace.navigation.TYPE_BACK_FORWARD,
+ 'window.performance.navigation.type == TYPE_BACK_FORWARD after history.forward()');
+ done();
+ step++;
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ </script>
+
+ </head>
+ <body>
+ <h1>
+ Description</h1>
+ <p>
+ This test validates the value of window.performance.navigation.type with a forward
+ and back navigation.</p>
+
+ <p>This page should be loaded with a yellow background frame below. It should turn green for a starting
+ navigation, back to yellow for a back navigation and then back to green again for a forward navigation.</p>
+
+ <p>Along the navigation timeline the frame.window.performance.type is checked for TYPE_BACK_FORWARD.</p>
+
+ <p>This test passes if all of the checks to the navigation.type are correct throughout the navigation
+ scenario and the frame below ends with a green background. Otherwise, this test fails.</p>
+
+ <div id="log"></div>
+ <br />
+ <iframe id="frameContext" onload="onload_test();" src="resources/blank_page_yellow_with_onunload.html" style="width: 250px; height: 250px;"></iframe>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/navigation-timing/test_navigation_type_enums.html b/tests/wpt/web-platform-tests/navigation-timing/test_navigation_type_enums.html
new file mode 100644
index 00000000000..8bf8e4f3d7a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/navigation-timing/test_navigation_type_enums.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>window.performance.navigation enums</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://www.w3.org/TR/navigation-timing/#sec-navigation-info-interface"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="resources/webperftestharness.js"></script>
+ </head>
+ <body>
+ <h1>Description</h1>
+ <p>This test validates that the TYPE_* enumerations of window.performance.navigation exist and their values are correct.</p>
+
+ <div id="log"></div>
+
+ <script>
+ test_namespace('navigation');
+
+ test_enum('navigation', 'TYPE_NAVIGATE', 0);
+ test_enum('navigation', 'TYPE_RELOAD', 1);
+ test_enum('navigation', 'TYPE_BACK_FORWARD', 2);
+ test_enum('navigation', 'TYPE_RESERVED', 255);
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/navigation-timing/test_navigation_type_reload.html b/tests/wpt/web-platform-tests/navigation-timing/test_navigation_type_reload.html
new file mode 100644
index 00000000000..087100e32cd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/navigation-timing/test_navigation_type_reload.html
@@ -0,0 +1,109 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>window.performance.navigation.type with a reloaded navigation</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://www.w3.org/TR/navigation-timing/#sec-navigation-timing-interface"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="resources/webperftestharness.js"></script>
+ <link rel="stylesheet" href="/resources/testharness.css" />
+ <script>
+ setup({explicit_done: true});
+
+ // explicitly test the namespace before we start testing
+ test_namespace('navigation');
+ var reload_frame;
+ var startingTime;
+
+ function deepCopy(p, c)
+ {
+ var c = c || {};
+ for (var i in p)
+ {
+ if (typeof p[i] === 'object')
+ {
+ c[i] = (p[i].constructor === Array) ? [] : {};
+ deepCopy(p[i], c[i]);
+ } else c[i] = p[i];
+ }
+ return c;
+ }
+
+
+ function onload_test()
+ {
+ reload_frame = document.getElementById("frameContext");
+ reload_frame.onload = function() {
+ /* Need to make sure we don't examine loadEventEnd
+ until after the load event has finished firing */
+ setTimeout(do_test, 0);
+ }
+ setTimeout("reload_the_frame();", 100);
+ }
+
+ function reload_the_frame()
+ {
+ //Before reloading, save the current timing
+ startingTime = deepCopy(reload_frame.contentWindow.performance.timing);
+ reload_frame.contentWindow.location.reload(true);
+ }
+
+ function do_test()
+ {
+ reload_frame.onload = null;
+ if (performanceNamespace)
+ {
+ //Verify that the navigation type has updated to reload
+ test_equals(reload_frame.contentWindow.performance.navigation.type,
+ performanceNamespace.navigation.TYPE_RELOAD,
+ 'window.performance.navigation.type == TYPE_RELOAD,{help:"http://www.w3.org/TR/navigation-timing/#sec-navigation-info-interface"}');
+
+ //Verify that the timing data has been updated into the future
+ var reloadTime = reload_frame.contentWindow.performance.timing;
+ for (attribute in timingAttributes)
+ {
+ var time = timingAttributes[attribute];
+ if (reloadTime[time] === 0)
+ {
+ test_equals(reloadTime[time],
+ startingTime[time],
+ "Reload " + time + "(" + reloadTime[time] + ")" +
+ " == " +
+ "Original " + time + "(" + startingTime[time] + ")");
+ }
+ else
+ {
+ test_greater_than(reloadTime[time],
+ startingTime[time],
+ "Reload " + time + "(" + reloadTime[time] + ")" +
+ " > " +
+ "Original " + time + "(" + startingTime[time] + ")");
+ }
+ }
+ }
+
+ done();
+ }
+ </script>
+ </head>
+ <body onload="onload_test();">
+ <h1>Description</h1>
+ <p>This test validates the value of window.performance.navigation.type and the values of
+ window.performance.timing.* with a reloaded navigation.</p>
+
+ <p>This page should be loaded with a green background frame below. The frame will be automatically reloaded
+ and then verified that
+ <ul>
+ <li>The window.performance.navigation.type = TYPE_RELOAD</li>
+ <li>All of the widow.performance.timing.* values after reload are > all of the window.performance.timing.* values
+ prior to reload.</li>
+ </ul>
+ </p>
+
+ <div id="log"></div>
+ <br />
+ <iframe id="frameContext" src="resources/blank_page_green.html" style="width: 250px; height: 250px;"></iframe>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/navigation-timing/test_no_previous_document.html b/tests/wpt/web-platform-tests/navigation-timing/test_no_previous_document.html
new file mode 100644
index 00000000000..476a6e7a7be
--- /dev/null
+++ b/tests/wpt/web-platform-tests/navigation-timing/test_no_previous_document.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>window.performance.timing attributes on an initial navigation</title>
+ <link rel="author" title="Google" href="http://www.google.com/" />
+ <link rel="help" href="http://www.w3.org/TR/navigation-timing/#sec-navigation-timing-interface"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="resources/webperftestharness.js"></script>
+ <link rel="stylesheet" href="/resources/testharness.css" />
+
+ <script>
+ setup({explicit_done: true});
+
+ var frame;
+ function onload_test()
+ {
+ frame = document.getElementById("frameContext");
+ test_namespace('navigation');
+ if (performanceNamespace)
+ {
+ test_true(frame.contentWindow.performance.navigation.type == performanceNamespace.navigation.TYPE_NAVIGATE,
+ 'timing.navigation.type is TYPE_NAVIGATE',{help:"http://www.w3.org/TR/navigation-timing/#sec-navigation-info-interface"});
+
+ test_equals(frame.contentWindow.performance.timing.unloadEventStart, 0, 'timing.unloadEventStart == 0 on navigation with no previous document');
+ test_equals(frame.contentWindow.performance.timing.unloadEventEnd, 0, 'timing.unloadEventEnd == 0 navigation with no previous document');
+ }
+ done();
+ }
+ </script>
+
+ </head>
+ <body onload="onload_test();">
+ <h1>Description</h1>
+ <p>This test validates the unload event times are 0 when there is no previous document.</p>
+
+ <div id="log"></div><br />
+ <iframe id="frameContext" src="resources/blank_page_green.html" style="width: 250px; height: 250px;"></iframe>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/navigation-timing/test_performance_attributes_exist.html b/tests/wpt/web-platform-tests/navigation-timing/test_performance_attributes_exist.html
new file mode 100644
index 00000000000..28dd846da4c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/navigation-timing/test_performance_attributes_exist.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>window.performance attributes</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://www.w3.org/TR/navigation-timing/#sec-window.performance-attribute"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="resources/webperftestharness.js"></script>
+ <link rel="stylesheet" href="/resources/testharness.css" />
+ </head>
+ <body>
+ <h1>Description</h1>
+ <p>This test validates that the navigation and timing attributes exist for window.performance
+ (but does not validate that their values are correct).</p>
+ <div id="log"></div>
+ <script>
+ test_namespace('navigation');
+ test_namespace('timing', true);
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/navigation-timing/test_performance_attributes_exist_in_object.html b/tests/wpt/web-platform-tests/navigation-timing/test_performance_attributes_exist_in_object.html
new file mode 100644
index 00000000000..60fcdb521ab
--- /dev/null
+++ b/tests/wpt/web-platform-tests/navigation-timing/test_performance_attributes_exist_in_object.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>window.performance attribute exists in an object</title>
+ <link rel="author" title="Google" href="http://www.google.com/" />
+ <link rel="help" href="http://www.w3.org/TR/navigation-timing/#sec-window.performance-attribute"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="resources/webperftestharness.js"></script>
+ <link rel="stylesheet" href="/resources/testharness.css" />
+ <script>
+ function onload_test() {
+ var objWindow =
+ document.getElementById("objectContext").contentDocument.defaultView;
+ performanceNamespace = objWindow.performance;
+ test_namespace('timing');
+ test_namespace('navigation', true);
+ }
+ </script>
+ </head>
+ <body>
+ <h1>Description</h1>
+ <p>This test validates that the window.performance object exists in an
+ object element (but does not validate that their values are correct).</p>
+ <object id="objectContext" onload="onload_test();" data="resources/blank_page_green.html"></object>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/navigation-timing/test_readwrite.html b/tests/wpt/web-platform-tests/navigation-timing/test_readwrite.html
new file mode 100644
index 00000000000..6a216fae4d7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/navigation-timing/test_readwrite.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>window.performance is read/write</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://www.w3.org/TR/navigation-timing/#sec-window.performance-attribute"/>
+ <meta name="assert" content="The window.performance attribute provides a hosting area for performance related attributes. "/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="resources/webperftestharness.js"></script>
+ <link rel="stylesheet" href="/resources/testharness.css" />
+ </head>
+ <body>
+ <h1>Description</h1>
+ <p>This test validates that the window.performance object is read/write.</p>
+ <div id="log"></div>
+ <script>
+ test_namespace();
+
+ window.performance = 'foo';
+ test_equals(window.performance, 'foo', 'window.performance is read/write');
+
+ var performance = 'bar';
+ test_equals(performance, 'bar', 'var performance is read/write');
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/navigation-timing/test_timing_attributes_exist.html b/tests/wpt/web-platform-tests/navigation-timing/test_timing_attributes_exist.html
new file mode 100644
index 00000000000..f3dea6838c4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/navigation-timing/test_timing_attributes_exist.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>window.performance.timing attributes</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://www.w3.org/TR/navigation-timing/#sec-navigation-timing-interface"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="resources/webperftestharness.js"></script>
+ </head>
+ <body>
+ <h1>Description</h1>
+ <p>This test validates that all of the window.performance.timing attributes exist (but does not validate that their values are correct).</p>
+
+ <div id="log"></div>
+
+ <script>
+ test_namespace('timing');
+
+ for (var i = 0; i < timingAttributes.length; ++i)
+ {
+ test_attribute_exists('timing', timingAttributes[i]);
+ }
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/navigation-timing/test_timing_attributes_order.html b/tests/wpt/web-platform-tests/navigation-timing/test_timing_attributes_order.html
new file mode 100644
index 00000000000..5739eb92580
--- /dev/null
+++ b/tests/wpt/web-platform-tests/navigation-timing/test_timing_attributes_order.html
@@ -0,0 +1,110 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>window.performance.timing attribute ordering on a simple navigation</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://www.w3.org/TR/navigation-timing/#sec-navigation-timing-interface"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="resources/webperftestharness.js"></script>
+ <link rel="stylesheet" href="/resources/testharness.css" />
+ <script>
+ setup({explicit_done: true});
+
+ test_namespace('timing');
+
+ var step = 1;
+ function onload_test()
+ {
+ if (step === 1 && window.performance === undefined)
+ {
+ // avoid script errors
+ done();
+ return;
+ }
+
+ var navigation_frame = document.getElementById("frameContext").contentWindow;
+ performanceNamespace = navigation_frame.performance;
+ switch (step)
+ {
+ case 1:
+ {
+ navigation_frame.location.href = '/navigation-timing/resources/blank_page_green.html';
+ step++;
+ break;
+ }
+ case 2:
+ {
+ test_namespace('navigation', true);
+
+ //
+ // Tests
+ //
+ test_equals(performanceNamespace.navigation.type,
+ performanceNamespace.navigation.TYPE_NAVIGATE,
+ 'window.performance.navigation.type == TYPE_NAVIGATE',{help:"http://www.w3.org/TR/navigation-timing/#sec-navigation-info-interface"});
+
+ // navigiation must be non-0
+ test_timing_greater_than('navigationStart', 0);
+
+ // must be no redirection for this test case
+ test_timing_equals('redirectStart', 0);
+ test_timing_equals('redirectEnd', 0);
+
+ // validate attribute ordering
+ test_timing_order('fetchStart', 'navigationStart');
+ test_timing_order('domainLookupStart', 'fetchStart');
+ test_timing_order('domainLookupEnd', 'domainLookupStart');
+ test_timing_order('connectStart', 'domainLookupEnd');
+ test_timing_order('connectEnd', 'connectStart');
+ test_timing_order('requestStart', 'connectEnd');
+ test_timing_order('responseStart', 'requestStart');
+ test_timing_order('responseEnd', 'responseStart');
+ test_timing_order('domLoading', 'fetchStart');
+ test_timing_order('domInteractive', 'responseEnd');
+ test_timing_order('domContentLoadedEventStart', 'domInteractive');
+ test_timing_order('domContentLoadedEventEnd', 'domContentLoadedEventStart');
+ test_timing_order('domComplete', 'domContentLoadedEventEnd');
+ test_timing_order('loadEventStart', 'domContentLoadedEventEnd');
+ test_timing_order('loadEventEnd', 'loadEventStart');
+
+ // setup requires the frame to have a previous page with an onunload event handler.
+ test_timing_order('unloadEventStart', 'navigationStart');
+ test_timing_order('unloadEventEnd', 'unloadEventStart');
+
+ step++;
+ done();
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <h1>Description</h1>
+ <p>This test validates the ordering of the window.performance.timing attributes.</p>
+
+ <p>This page should be loaded with a yellow background frame below which contains an unload event
+ handler.</p>
+
+ <p>After the page loads, the frame is navigated to a new blank page with a green background. At this point, the navigation timeline is verified</p>
+
+ <p>This test passes if all of the checks to the frame.window.performance.timing attributes are
+ correct throughout the navigation scenario and the frame below ends with a green background.
+ Otherwise, this test fails.</p>
+
+ <h1>Setup</h1>
+
+ <div id="log"></div>
+ <br />
+ <iframe id="frameContext"
+ onload="/* Need to make sure we don't examine loadEventEnd
+ until after the load event has finished firing */
+ setTimeout(onload_test, 0);"
+ src="resources/blank_page_unload.html"
+ style="width: 250px; height: 250px;"></iframe>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/navigation-timing/test_timing_client_redirect.html b/tests/wpt/web-platform-tests/navigation-timing/test_timing_client_redirect.html
new file mode 100644
index 00000000000..14caea654b3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/navigation-timing/test_timing_client_redirect.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>window.performance.timing.redirect attributes on a client redirect navigation</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://www.w3.org/TR/navigation-timing/#sec-navigation-timing-interface"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="resources/webperftestharness.js"></script>
+ <link rel="stylesheet" href="/resources/testharness.css" />
+ <script>
+ setup({explicit_done: true});
+
+ test_namespace('navigation');
+ test_namespace('timing', true);
+
+ var redirect_frame;
+ function onload_test()
+ {
+ if (performanceNamespace === undefined)
+ {
+ // avoid script errors
+ done();
+ return;
+ }
+
+ redirect_frame = document.getElementById("frameContext");
+ redirect_frame.onload = do_test;
+ }
+
+ function do_test()
+ {
+ redirect_frame.onload = "";
+ test_true(redirect_frame.contentWindow.performance.navigation.type == performanceNamespace.navigation.TYPE_NAVIGATE,
+ 'timing.navigation.type is TYPE_NAVIGATE',{help:"http://www.w3.org/TR/navigation-timing/#sec-navigation-info-interface"});
+
+ test_equals(redirect_frame.contentWindow.performance.navigation.redirectCount, 0, 'navigation.redirectCount == 0 on an client redirected navigation',{help:"http://www.w3.org/TR/navigation-timing/#sec-navigation-info-interface"});
+ test_equals(redirect_frame.contentWindow.performance.timing.redirectStart, 0, 'timing.redirectStart == 0 on an client redirected navigation');
+ test_equals(redirect_frame.contentWindow.performance.timing.redirectEnd, 0, 'timing.redirectEnd == 0 on an client redirected navigation');
+
+ done();
+ }
+ </script>
+
+ </head>
+ <body onload="onload_test();">
+ <h1>Description</h1>
+ <p>This test validates the values of the window.navigation.redirectCount and the
+ window.performance.timing.redirectStart/End times on a client side redirect.</p>
+
+ <div id="log"></div><br />
+ <iframe id="frameContext" src="resources/blank_page_meta_redirect.html" style="width: 250px; height: 250px;"></iframe>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/navigation-timing/test_timing_reload.html b/tests/wpt/web-platform-tests/navigation-timing/test_timing_reload.html
new file mode 100644
index 00000000000..4b8b791fb01
--- /dev/null
+++ b/tests/wpt/web-platform-tests/navigation-timing/test_timing_reload.html
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>window.performance.timing attributes after a reloaded navigation</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://www.w3.org/TR/navigation-timing/#sec-navigation-timing-interface"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="resources/webperftestharness.js"></script>
+ <link rel="stylesheet" href="/resources/testharness.css" />
+ <script>
+ setup({explicit_done: true});
+
+ // explicitly test the namespace before we start testing
+ test_namespace('navigation');
+
+ var reload_frame;
+ var initial_timing;
+
+ function onload_test()
+ {
+ reload_frame = document.getElementById("frameContext");
+
+ if (reload_frame.contentWindow.performance === undefined)
+ {
+ // avoid script errors
+ done();
+ return;
+ }
+
+ reload_frame.onload = do_test;
+
+ // save frame's initial timings
+ initial_timing = {};
+ var timing = reload_frame.contentWindow.performance.timing;
+
+ for (var i = 0; i < timingAttributes.length; ++i)
+ {
+ var property = timingAttributes[i];
+ initial_timing[property] = timing[property];
+ }
+
+ setTimeout("reload_the_frame();", 100);
+ }
+
+ function reload_the_frame()
+ {
+ reload_frame.contentWindow.location.reload(true);
+ }
+
+ function do_test()
+ {
+ reload_frame.onload = "";
+
+ // ensure the frame reloaded
+ test_equals(reload_frame.contentWindow.performance.navigation.type,
+ performanceNamespace.navigation.TYPE_RELOAD,
+ "window.performance.navigation.type == TYPE_RELOAD", {help:"http://www.w3.org/TR/navigation-timing/#sec-navigation-info-interface"});
+
+ // ensure reload timings changed
+ var timing = reload_frame.contentWindow.performance.timing;
+ for (var i = 0; i < timingAttributes.length; ++i)
+ {
+ var property = timingAttributes[i];
+
+ // ignore any timings that were zero initially
+ if (initial_timing[property] !== 0)
+ {
+ test_not_equals(timing[property], initial_timing[property],
+ property + " is different after the reload.");
+ }
+ }
+
+ done();
+ }
+ </script>
+ </head>
+ <body onload="onload_test();">
+ <h1>Description</h1>
+ <p>This test validates that the window.performance.timing attributes change when a page is reloaded.</p>
+
+ <p>This page should be loaded with a green background frame below. The frame will be automatically reloaded
+ and then verified that the window.performance.timing attributes have been updated to the new reloaded navigation timings.</p>
+
+ <div id="log"></div>
+ <br />
+ <iframe id="frameContext" src="resources/blank_page_green.html" style="width: 250px; height: 250px;"></iframe>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/navigation-timing/test_timing_server_redirect.html b/tests/wpt/web-platform-tests/navigation-timing/test_timing_server_redirect.html
new file mode 100644
index 00000000000..22137be74aa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/navigation-timing/test_timing_server_redirect.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>window.performance.timing.redirect attributes on a same-origin server redirected navigation</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://www.w3.org/TR/navigation-timing/#sec-navigation-timing-interface"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="resources/webperftestharness.js"></script>
+
+ <script>
+ function onload_test()
+ {
+ test_namespace('navigation');
+ if (performanceNamespace === undefined)
+ {
+ // avoid script errors
+ done();
+ return;
+ }
+
+ performanceNamespace = document.getElementById("frameContext").contentWindow.performance;
+ test_equals(performanceNamespace.navigation.type,
+ performanceNamespace.navigation.TYPE_NAVIGATE,
+ 'timing.navigation.type is TYPE_NAVIGATE');
+ test_equals(performanceNamespace.navigation.redirectCount, 1, 'navigation.redirectCount == 1 on an server redirected navigation');
+
+ test_timing_greater_than('navigationStart', 0);
+
+ test_timing_order('redirectStart', 'navigationStart');
+ test_timing_order('redirectEnd', 'redirectStart');
+ test_timing_order('fetchStart', 'redirectEnd');
+ }
+ </script>
+
+ </head>
+ <body>
+ <h1>Description</h1>
+ <p>This test validates the values of the window.performance.redirectCount and the
+ window.performance.timing.redirectStart/End times for a same-origin server side redirect navigation.</p>
+
+ <div id="log"></div>
+ <br />
+ <iframe id="frameContext" onload="onload_test();" src="/common/redirect.py?location=/navigation-timing/resources/blank_page_green.html" style="width: 250px; height: 250px;"></iframe>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/navigation-timing/test_timing_xserver_redirect.html b/tests/wpt/web-platform-tests/navigation-timing/test_timing_xserver_redirect.html
new file mode 100644
index 00000000000..ef00526b0d0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/navigation-timing/test_timing_xserver_redirect.html
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>window.performance.timing.redirect attributes on a cross-origin server redirected navigation</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://www.w3.org/TR/navigation-timing/#sec-navigation-timing-interface"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="resources/webperftestharness.js"></script>
+ <script src="/common/utils.js"></script>
+ <script>
+ setup({explicit_done: true});
+
+ //
+ // Test configuration
+ //
+
+ var subdomain = "www";
+
+ //
+ // Tests
+ //
+ function onload_test()
+ {
+ test_namespace('navigation');
+ if (performanceNamespace === undefined)
+ {
+ // avoid script errors
+ done();
+ return;
+ }
+
+ performanceNamespace = document.getElementById("frameContext").contentWindow.performance;
+ test_equals(performanceNamespace.navigation.type,
+ performanceNamespace.navigation.TYPE_NAVIGATE,
+ 'timing.navigation.type is TYPE_NAVIGATE',{help:"http://www.w3.org/TR/navigation-timing/#sec-navigation-info-interface"});
+ test_equals(performanceNamespace.navigation.redirectCount, 0, 'navigation.redirectCount == 0 on a cross-origin server redirected navigation', {help:"http://www.w3.org/TR/navigation-timing/#sec-navigation-info-interface"});
+
+ test_timing_greater_than('navigationStart', 0);
+
+ test_equals(performanceNamespace.timing.redirectStart, 0, 'timing.redirectStart == 0 on a server redirected navigation from another domain');
+ test_equals(performanceNamespace.timing.redirectEnd, 0, 'timing.redirectEnd == 0 on a server redirected navigation from another domain');
+
+ done();
+ }
+ </script>
+
+ </head>
+ <body>
+ <h1>Description</h1>
+ <p>This test validates the values of the window.performance.redirectCount and the
+ window.performance.timing.redirectStart/End times for a cross-origin server side redirect navigation.</p>
+
+ <div id="log"></div>
+ <br />
+ <iframe id="frameContext" src="" style="width: 250px; height: 250px;"></iframe>
+ <script>
+ // combine the page origin and redirect origin into the IFRAME's src URL
+ var destUrl = make_absolute_url({subdomain: subdomain,
+ path: "/common/redirect.py",
+ query: "location=" + make_absolute_url(
+ {path: "/navigation-timing/resources/blank_page_green.html"})
+ });
+ var frameContext = document.getElementById("frameContext");
+ frameContext.onload = onload_test;
+ frameContext.src = destUrl;
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/navigation-timing/test_unique_performance_objects.html b/tests/wpt/web-platform-tests/navigation-timing/test_unique_performance_objects.html
new file mode 100644
index 00000000000..7d3bb3fe07a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/navigation-timing/test_unique_performance_objects.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>Each window object has a unique performance object</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://www.w3.org/TR/navigation-timing/#sec-window.performance-attribute" />
+ <meta name="assert" content="Each browsing context must have a unique window.performance.timing attribute."/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="resources/webperftestharness.js"></script>
+ <link rel="stylesheet" href="/resources/testharness.css" />
+ </head>
+ <body>
+ <h1>Description</h1>
+ <p>This test validates that each window has a unique window.performance object.</p>
+ <iframe id="frameContext" src="resources/blank_page_green.html" style="display:none;";></iframe>
+ <div id="log"></div>
+ <script>
+ test_namespace('timing');
+
+ if (performanceNamespace !== undefined)
+ {
+ test_not_equals(performanceNamespace.timing,
+ document.getElementById("frameContext").contentWindow.performance.timing,
+ "Different window objects have unique performance objects");
+ }
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/notifications/Notification-permission.html b/tests/wpt/web-platform-tests/notifications/Notification-permission.html
new file mode 100644
index 00000000000..d6501b5b5c3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/notifications/Notification-permission.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Web Notifications Test: Notification - permission (basic)</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="author" title="Xin Liu" href="mailto:xinx.liu@intel.com">
+<link rel="help" title="4.3 Permission" href="http://www.w3.org/TR/notifications/#permission">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+ <div id="log"></div>
+ <script>
+ test(function() {
+ assert_in_array(Notification.permission, ["default", "denied", "granted"], "Notification.permission");
+ }, "Test checks that notification the value of permission is in array");
+ </script>
+</body>
+
diff --git a/tests/wpt/web-platform-tests/notifications/Notification-requestPermission-denied-manual.html b/tests/wpt/web-platform-tests/notifications/Notification-requestPermission-denied-manual.html
new file mode 100644
index 00000000000..583e80e6920
--- /dev/null
+++ b/tests/wpt/web-platform-tests/notifications/Notification-requestPermission-denied-manual.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Web Notifications Test: Notification - requestPermission (deny)</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="author" title="Xin Liu" href="mailto:xinx.liu@intel.com">
+<link rel="help" title="4.3 Permission" href="http://www.w3.org/TR/notifications/#permission">
+<meta name="flags" content="interact">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+ <p>Test Step:</p>
+ <p>1. When ask the user whether showing notifications, make sure choose deny.</p>
+ <div id="log"></div>
+ <script>
+ t = async_test("the notification the value of permission is denied", {timeout: 50000});
+ Notification.requestPermission(t.step_func(function(permission) {
+ assert_equals(permission, "denied", "notification permission");
+ t.done();
+ }));
+ </script>
+</body>
+
diff --git a/tests/wpt/web-platform-tests/notifications/Notification-requestPermission-granted-manual.html b/tests/wpt/web-platform-tests/notifications/Notification-requestPermission-granted-manual.html
new file mode 100644
index 00000000000..4cf29d2731f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/notifications/Notification-requestPermission-granted-manual.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Web Notifications Test: Notification - requestPermission (allow)</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="author" title="Xin Liu" href="mailto:xinx.liu@intel.com">
+<link rel="help" title="4.3 Permission" href="http://www.w3.org/TR/notifications/#permission">
+<meta name="flags" content="interact">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+ <p>Test Step:</p>
+ <p>1. When ask the user whether showing notifications, make sure choose allow.</p>
+ <div id="log"></div>
+ <script>
+ t = async_test("the notification the value of permission is granted", {timeout: 50000});
+ Notification.requestPermission(t.step_func(function(permission) {
+ assert_equals(permission, "granted", "notification permission");
+ t.done();
+ }));
+ </script>
+</body>
+
diff --git a/tests/wpt/web-platform-tests/notifications/README.md b/tests/wpt/web-platform-tests/notifications/README.md
new file mode 100644
index 00000000000..821255358f1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/notifications/README.md
@@ -0,0 +1,5 @@
+Web Notifications test suite.
+
+Latest Editor's Draft: http://dvcs.w3.org/hg/notifications/raw-file/tip/Overview.html
+
+Latest Technical Report: http://www.w3.org/TR/notifications/
diff --git a/tests/wpt/web-platform-tests/notifications/event-onshow.html b/tests/wpt/web-platform-tests/notifications/event-onshow.html
new file mode 100644
index 00000000000..9372c959d4c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/notifications/event-onshow.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Web Notifications Test: notification - onshow (basic)</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="author" title="Xin Liu" href="mailto:xinx.liu@intel.com">
+<link rel="help" title="5 API" href="http://www.w3.org/TR/notifications/">
+<meta name="flags" content="">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+ <div id="log"></div>
+ <script>
+ t = async_test("the notification.onshow event can be invoked", {timeout: 50000});
+ var notification = new Notification("New Email Received", {
+ body: "Room 101"
+ });
+ notification.onshow = t.step_func(function(e) {
+ assert_equals(Object.prototype.toString.call(e), "[object Event]", "the type of event");
+ t.done();
+ });
+ </script>
+</body>
+
diff --git a/tests/wpt/web-platform-tests/notifications/instance.html b/tests/wpt/web-platform-tests/notifications/instance.html
new file mode 100644
index 00000000000..2451b10c6a1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/notifications/instance.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Basic Notification instance tests</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+ var n = new Notification("Radio check",
+ {
+ dir: "ltr",
+ lang: "aa",
+ body: "This is a radio check.",
+ tag: "radio_check999",
+ icon: "http://example.com/icon.png",
+ }
+ );
+ test(function() {
+ assert_true(n instanceof Notification);
+ },"Notification instance exists.");
+ test(function() {
+ assert_true("close" in n);
+ },"Attribute exists: close");
+ test(function() {
+ assert_true("onclick" in n);
+ },"Attribute exists: onclick");
+ test(function() {
+ assert_true("onshow" in n);
+ },"Attribute exists: onshow");
+ test(function() {
+ assert_true("onerror" in n);
+ },"Attribute exists: onerror");
+ test(function() {
+ assert_true("onclose" in n);
+ },"Attribute exists: onclose");
+ test(function() {
+ assert_equals("Radio check", n.title);
+ },"Attribute exists with expected value: title");
+ test(function() {
+ assert_equals("ltr", n.dir);
+ },"Attribute exists with expected value: dir");
+ test(function() {
+ assert_equals("aa", n.lang);
+ },"Attribute exists with expected value: lang");
+ test(function() {
+ assert_equals("This is a radio check.", n.body);
+ },"Attribute exists with expected value: body");
+ test(function() {
+ assert_equals("radio_check999", n.tag);
+ },"Attribute exists with expected value: tag");
+ test(function() {
+ assert_equals("http://example.com/icon.png", n.icon);
+ },"Attribute exists with expected value: icon");
+</script>
diff --git a/tests/wpt/web-platform-tests/notifications/interfaces.html b/tests/wpt/web-platform-tests/notifications/interfaces.html
new file mode 100644
index 00000000000..71232e71249
--- /dev/null
+++ b/tests/wpt/web-platform-tests/notifications/interfaces.html
@@ -0,0 +1,80 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Web Notifications IDL tests</title>
+<div id=log></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=/resources/WebIDLParser.js></script>
+<script src=/resources/idlharness.js></script>
+<script type=text/plain class=untested>
+interface EventTarget {
+ void addEventListener(DOMString type, EventListener? callback, optional boolean capture /* = false */);
+ void removeEventListener(DOMString type, EventListener? callback, optional boolean capture /* = false */);
+ boolean dispatchEvent(Event event);
+};
+[TreatNonCallableAsNull]
+callback EventHandlerNonNull = any (Event event);
+typedef EventHandlerNonNull? EventHandler;
+</script>
+<script type=text/plain>
+[Constructor(DOMString title, optional NotificationOptions options)]
+interface Notification : EventTarget {
+ static readonly attribute NotificationPermission permission;
+ static void requestPermission(optional NotificationPermissionCallback callback);
+
+ attribute EventHandler onclick;
+ attribute EventHandler onshow;
+ attribute EventHandler onerror;
+ attribute EventHandler onclose;
+
+ readonly attribute DOMString title;
+ readonly attribute NotificationDirection dir;
+ readonly attribute DOMString lang;
+ readonly attribute DOMString body;
+ readonly attribute DOMString tag;
+ readonly attribute DOMString icon;
+
+ void close();
+};
+
+dictionary NotificationOptions {
+ NotificationDirection dir = "auto";
+ DOMString lang = "";
+ DOMString body;
+ DOMString tag;
+ DOMString icon;
+};
+
+dictionary GetNotificationsOptions {
+ DOMString tag;
+};
+
+enum NotificationPermission {
+ "default",
+ "denied",
+ "granted"
+};
+
+callback NotificationPermissionCallback = void (NotificationPermission permission);
+
+enum NotificationDirection {
+ "auto",
+ "ltr",
+ "rtl"
+};
+</script>
+<script>
+"use strict";
+var idlArray = new IdlArray();
+[].forEach.call(document.querySelectorAll("script[type=text\\/plain]"), function(node) {
+ if (node.className == "untested") {
+ idlArray.add_untested_idls(node.textContent);
+ } else {
+ idlArray.add_idls(node.textContent);
+ }
+});
+idlArray.add_objects({
+ Notification: ['new Notification("foo")'],
+});
+idlArray.test();
+</script>
diff --git a/tests/wpt/web-platform-tests/notifications/notification-body-basic-manual.html b/tests/wpt/web-platform-tests/notifications/notification-body-basic-manual.html
new file mode 100644
index 00000000000..378ad4e3f1f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/notifications/notification-body-basic-manual.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Web Notifications Test: notification - body (basic)</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="author" title="Xin Liu" href="mailto:xinx.liu@intel.com">
+<link rel="help" title="5 API" href="http://www.w3.org/TR/notifications/">
+<meta name="flags" content="interact">
+<meta name="assert" content="The body attribute must return the notification's body and the empty string otherwise.">
+<body>
+ <p>Test passes if a notification popups and the notification's body content is "Room 101".</p>
+ <script>
+ var notification = new Notification("New Email Received", {
+ body: "Room 101"
+ });
+ </script>
+</body>
+
diff --git a/tests/wpt/web-platform-tests/notifications/notification-body-empty-manual.html b/tests/wpt/web-platform-tests/notifications/notification-body-empty-manual.html
new file mode 100644
index 00000000000..76be5eba6c5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/notifications/notification-body-empty-manual.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Web Notifications Test: notification - body (empty string)</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="author" title="Xin Liu" href="mailto:xinx.liu@intel.com">
+<link rel="help" title="5 API" href="http://www.w3.org/TR/notifications/">
+<meta name="flags" content="interact">
+<meta name="assert" content="The body attribute set empty string, then the notification's body content show nothing.">
+<body>
+ <p>Test passes if a notification popups and the notification have no body content.</p>
+ <script>
+ var notification = new Notification("New Email Received", {
+ body: ""
+ });
+ </script>
+</body>
+
diff --git a/tests/wpt/web-platform-tests/notifications/notification-close-manual.html b/tests/wpt/web-platform-tests/notifications/notification-close-manual.html
new file mode 100644
index 00000000000..7b58e26090c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/notifications/notification-close-manual.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Web Notifications Test: notification - close (basic)</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="author" title="Xin Liu" href="mailto:xinx.liu@intel.com">
+<link rel="help" title="4.6 Closing a notification" href="http://www.w3.org/TR/notifications/#closing-a-notification">
+<meta name="flags" content="interact">
+<meta name="assert" content="The notification.close() method will close this notification.">
+<body>
+ <p>Test passes if a notification popups and it disappears after a while(about 3 seconds).</p>
+ <script>
+ var closetime = 3000;
+ var notification = new Notification("New Email Received", {
+ body: "Room 101"
+ });
+ setTimeout(function() {
+ notification.close();
+ }, closetime);
+ </script>
+</body>
+
diff --git a/tests/wpt/web-platform-tests/notifications/notification-constructor-basic.html b/tests/wpt/web-platform-tests/notifications/notification-constructor-basic.html
new file mode 100644
index 00000000000..7ed12b31d05
--- /dev/null
+++ b/tests/wpt/web-platform-tests/notifications/notification-constructor-basic.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Web Notifications Test: notification - constructor (basic)</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="author" title="Xin Liu" href="mailto:xinx.liu@intel.com">
+<link rel="help" title="5 API" href="http://www.w3.org/TR/notifications/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+ <div id="log"></div>
+ <script>
+ test(function() {
+ var notification = new Notification("New Email Received", {
+ body: "Room 101"
+ });
+ assert_equals(typeof notification, "object");
+ }, "Test checks that notification constructor is correct");
+ </script>
+</body>
+
diff --git a/tests/wpt/web-platform-tests/notifications/notification-constructor-invalid.html b/tests/wpt/web-platform-tests/notifications/notification-constructor-invalid.html
new file mode 100644
index 00000000000..96d9d2f20b6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/notifications/notification-constructor-invalid.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Web Notifications Test: notification - constructor (invalid)</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="author" title="Xin Liu" href="mailto:xinx.liu@intel.com">
+<link rel="help" title="5 API" href="http://www.w3.org/TR/notifications/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+ <div id="log"></div>
+ <script>
+ test(function() {
+ assert_throws("new TypeError()", function() {
+ var notification = new Notification();
+ });
+ }, "Test checks that notification constructor arguments can't be empty");
+ </script>
+</body>
+
diff --git a/tests/wpt/web-platform-tests/notifications/notification-dir-auto-manual.html b/tests/wpt/web-platform-tests/notifications/notification-dir-auto-manual.html
new file mode 100644
index 00000000000..358aa619e7a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/notifications/notification-dir-auto-manual.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Web Notifications Test: notification - dir (dir attribute set to "auto")</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="author" title="Xin Liu" href="mailto:xinx.liu@intel.com">
+<link rel="help" title="4.1 Direction" href="http://www.w3.org/TR/notifications/#direction-0">
+<meta name="flags" content="interact">
+<meta name="assert" content="The dir attribute set 'auto', then the notification's direction is the left edge.">
+<body>
+ <p>Test passes if a notification popups and the notification's direction is the left edge.</p>
+ <script>
+ var notification = new Notification("New Email Received", {
+ body: "Room 101",
+ dir: "auto"
+ });
+ </script>
+</body>
+
diff --git a/tests/wpt/web-platform-tests/notifications/notification-dir-ltr-manual.html b/tests/wpt/web-platform-tests/notifications/notification-dir-ltr-manual.html
new file mode 100644
index 00000000000..d8b74511f20
--- /dev/null
+++ b/tests/wpt/web-platform-tests/notifications/notification-dir-ltr-manual.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Web Notifications Test: notification - dir (dir attribute set to "ltr")</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="author" title="Xin Liu" href="mailto:xinx.liu@intel.com">
+<link rel="help" title="4.1 Direction" href="http://www.w3.org/TR/notifications/#direction-0">
+<meta name="flags" content="interact">
+<meta name="assert" content="The dir attribute set 'ltr', then the notification's direction is the left edge.">
+<body>
+ <p>Test passes if a notification popups and the notification's direction is the left edge.</p>
+ <script>
+ var notification = new Notification("New Email Received", {
+ body: "Room 101",
+ dir: "ltr"
+ });
+ </script>
+</body>
+
diff --git a/tests/wpt/web-platform-tests/notifications/notification-dir-rtl-manual.html b/tests/wpt/web-platform-tests/notifications/notification-dir-rtl-manual.html
new file mode 100644
index 00000000000..544773c9991
--- /dev/null
+++ b/tests/wpt/web-platform-tests/notifications/notification-dir-rtl-manual.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Web Notifications Test: notification - dir (dir attribute set to "rtl")</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="author" title="Xin Liu" href="mailto:xinx.liu@intel.com">
+<link rel="help" title="4.1 Direction" href="http://www.w3.org/TR/notifications/#direction-0">
+<meta name="flags" content="interact">
+<meta name="assert" content="The dir attribute set 'rtl', then the notification's direction is the right edge.">
+<body>
+ <p>Test passes if a notification popups and the notification's direction is the right edge.</p>
+ <script>
+ var notification = new Notification("New Email Received", {
+ body: "Room 101",
+ dir: "rtl"
+ });
+ </script>
+</body>
+
diff --git a/tests/wpt/web-platform-tests/notifications/notification-icon-basic-manual.html b/tests/wpt/web-platform-tests/notifications/notification-icon-basic-manual.html
new file mode 100644
index 00000000000..1d3a95147b1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/notifications/notification-icon-basic-manual.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Web Notifications Test: notification - icon (basic)</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="author" title="Xin Liu" href="mailto:xinx.liu@intel.com">
+<link rel="help" title="5 API" href="http://www.w3.org/TR/notifications/">
+<meta name="flags" content="interact">
+<meta name="assert" content="The icon attribute set valid URL, then notificaiton icon content will show a pictrue.">
+<body>
+ <p><strong>Make sure connect to network.</strong></p>
+ <p>Test passes if a notificaiton popups with a cat pictrue.</p>
+ <script>
+ var notification = new Notification("New Email Received", {
+ body: "Room 101",
+ icon: "http://test.csswg.org/source/support/cat.png"
+ });
+ </script>
+</body>
+
diff --git a/tests/wpt/web-platform-tests/notifications/notification-icon-empty-manual.html b/tests/wpt/web-platform-tests/notifications/notification-icon-empty-manual.html
new file mode 100644
index 00000000000..b153ed7f35c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/notifications/notification-icon-empty-manual.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Web Notifications Test: notification - icon (invalid)</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="author" title="Xin Liu" href="mailto:xinx.liu@intel.com">
+<link rel="help" title="5 API" href="http://www.w3.org/TR/notifications/">
+<meta name="flags" content="interact">
+<meta name="assert" content="The icon attribute set invalid URL, then notificaiton icon content will show nothing.">
+<body>
+ <p>Test passes if a notificaiton popups and notification's icon content show nothing.</p>
+ <script>
+ var notification = new Notification("New Email Received", {
+ body: "Room 101",
+ icon: ""
+ });
+ </script>
+</body>
+
diff --git a/tests/wpt/web-platform-tests/notifications/notification-tag-different-manual.html b/tests/wpt/web-platform-tests/notifications/notification-tag-different-manual.html
new file mode 100644
index 00000000000..ee94e8b3ede
--- /dev/null
+++ b/tests/wpt/web-platform-tests/notifications/notification-tag-different-manual.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Web Notifications Test: notification - tag (with different tag)</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="author" title="Xin Liu" href="mailto:xinx.liu@intel.com">
+<link rel="help" title="5 API" href="http://www.w3.org/TR/notifications/">
+<meta name="flags" content="interact">
+<meta name="assert" content="The tag attribute set different, then the notification's body show different.">
+<body>
+ <p>Test passes if two notifications popups and the notification's body are different.</p>
+ <script>
+ var notification1 = new Notification("New Email Received", {
+ body: "Room 101",
+ tag: "Tom"
+ });
+
+ var notification2 = new Notification("New Email Received", {
+ body: "Room 202",
+ tag: "Rose"
+ });
+ </script>
+</body>
+
diff --git a/tests/wpt/web-platform-tests/notifications/notification-tag-same-manual.html b/tests/wpt/web-platform-tests/notifications/notification-tag-same-manual.html
new file mode 100644
index 00000000000..5099e68c2a0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/notifications/notification-tag-same-manual.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Web Notifications Test: notification - tag (with same tag)</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="author" title="Xin Liu" href="mailto:xinx.liu@intel.com">
+<link rel="help" title="5 API" href="http://www.w3.org/TR/notifications/">
+<meta name="flags" content="interact">
+<meta name="assert" content="The tag attribute set same, then the notification's body only show the latest one.">
+<body>
+ <p>Test passes if only one notification popups and the notification's body is "Room 202".</p>
+ <script>
+ var notification1 = new Notification("New Email Received", {
+ body: "Room 101",
+ tag: "Tom"
+ });
+
+ var notification2 = new Notification("New Email Received", {
+ body: "Room 202",
+ tag: "Tom"
+ });
+ </script>
+</body>
+
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/Not_Use/input_autocomplete.html b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/Not_Use/input_autocomplete.html
new file mode 100644
index 00000000000..7cff30f333b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/Not_Use/input_autocomplete.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Forms</title>
+ <script src="../../resources/testharness.js"></script>
+ <script src="../../resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <p>
+ <h3>input_autocomplete</h3>
+ </p>
+
+ <li>input text in textbox and press enter key.</li>
+ <li>When you input same text, you can see hint text.</li>
+
+ <hr>
+
+ <div id="log"></div>
+
+ <form method="post"
+ enctype="application/x-www-form-urlencoded"
+ action=""
+ id="input_form">
+ <p><input type='text' id='input_text'></p>
+ </form>
+
+ <script>
+
+ var input_text = document.getElementById("input_text");
+ input_text.autocomplete = 'on';
+
+ if (typeof(input_text.autocomplete) == "string") {
+ if (input_text.autocomplete != "on") {
+ test(function() {
+ assert_true(false, "autocomplete attribute is not correct.");
+ });
+ }
+ } else {
+ test(function() {
+ assert_unreached("autocomplete attribute is not exist.");
+ });
+ }
+
+ </script>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/Not_Use/input_list.html b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/Not_Use/input_list.html
new file mode 100644
index 00000000000..b76d5f90735
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/Not_Use/input_list.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Forms</title>
+ <script src="../../resources/testharness.js"></script>
+ <script src="../../resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <p>
+ <h3>input_list</h3>
+ </p>
+ <li>List is showed list when click the input control.</li>
+ <hr>
+
+ <div id="log"></div>
+
+ <form method="post"
+ enctype="application/x-www-form-urlencoded"
+ action=""
+ name="input_form">
+ <p><input type='text' id='input_url' list="urls"></p>
+ <datalist id="urls">
+ <option value="http://www.google.com/" label="Google">
+ <option value="http://www.reddit.com/" label="Reddit">
+ </datalist>
+ </form>
+
+ <script>
+
+ var input_url = document.getElementById("input_url");
+ var ele = input_url.list;
+
+ if (typeof(ele) != "object") {
+ if (typeof(ele) == "null") {
+ test(function() {
+ assert_unreached("list attribute is not correct.");
+ });
+ } else {
+ test(function() {
+ assert_unreached("list attribute is not exist.");
+ });
+ }
+ }
+ </script>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/Not_Use/input_valueasdate.html b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/Not_Use/input_valueasdate.html
new file mode 100644
index 00000000000..5a09ee08bf8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/Not_Use/input_valueasdate.html
@@ -0,0 +1,52 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Forms</title>
+ <script src="../../resources/testharness.js"></script>
+ <script src="../../resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <p>
+ <h3>input_valueAsDate</h3>
+ </p>
+ <li>Date is showed in input when window is loaded.</li>
+ <hr>
+
+ <div id="log"></div>
+
+ <form method="post"
+ enctype="application/x-www-form-urlencoded"
+ action=""
+ name="input_form">
+ <p><input type='date' id='input_date'></p>
+ </form>
+
+ <script>
+
+ var input_date = document.getElementById("input_date");
+ // Setting
+ try {
+ input_date.valueAsDate = new Date();
+ } catch(e) {
+ test(function() {
+ assert_unreached("Failed to set valueAsDate attribute.");
+ });
+ }
+
+ // Getting
+ if (input_date.valueAsDate != null) {
+ if (typeof(input_date.valueAsDate) != "object") {
+ test(function() {
+ assert_true(false, "valueAsDate attribute is not correct.");
+ });
+ }
+ } else {
+ test(function() {
+ assert_unreached("Failed to get valueAsDate attribute.");
+ });
+ }
+
+ </script>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/Not_Use/input_valueasnumber.html b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/Not_Use/input_valueasnumber.html
new file mode 100644
index 00000000000..9e4286b3400
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/Not_Use/input_valueasnumber.html
@@ -0,0 +1,44 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Forms</title>
+ <script src="../../resources/testharness.js"></script>
+ <script src="../../resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <p>
+ <h3>input_valueAsNumber</h3>
+ </p>
+ <li>Number 5 is showed in input when window is loaded.</li>
+ <hr>
+
+ <div id="log"></div>
+
+ <form method="post"
+ enctype="application/x-www-form-urlencoded"
+ action=""
+ name="input_form">
+ <p><input type='number' id='input_number'></p>
+ </form>
+
+ <script>
+
+ var input_number = document.getElementById("input_number");
+ input_number.valueAsNumber = 5;
+
+ if (typeof(input_number.valueAsNumber) == "number") {
+ if (input_number.value != 5) {
+ test(function() {
+ assert_true(false, "valueAsNumber attribute is not correct.");
+ });
+ }
+ } else {
+ test(function() {
+ assert_unreached("valueAsNumber attribute is not exist.");
+ });
+ }
+
+ </script>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/Not_Use/select_length.html b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/Not_Use/select_length.html
new file mode 100644
index 00000000000..8e7e6ed7755
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/Not_Use/select_length.html
@@ -0,0 +1,56 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Forms</title>
+ <script src="../../resources/testharness.js"></script>
+ <script src="../../resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <p>
+ <h3>select_length</h3>
+ </p>
+
+ <li>In select control there is only 3 items.</li>
+
+ <hr>
+
+ <div id="log"></div>
+
+ <form method="post"
+ enctype="application/x-www-form-urlencoded"
+ action=""
+ id="input_form">
+ <p>
+ <label for="unittype">Select unit type:</label>
+ <select id="unittype" name="unittype">
+ <option value="1"> Miner </option>
+ <option value="2"> Puffer </option>
+ <option value="3" selected> Snipey </option>
+ <option value="4"> Max </option>
+ <option value="5"> Firebot </option>
+ </select>
+ </p>
+ </form>
+
+ <script>
+
+ var select = document.getElementById("unittype");
+ var length = select.length;
+ select.length = 3;
+
+ if (typeof(length) == "number") {
+ if (length != 5) {
+ test(function() {
+ assert_true(false, "length attribute is not correct.");
+ });
+ }
+ } else {
+ test(function() {
+ assert_unreached("length attribute is not exist.");
+ });
+ }
+
+ </script>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/Not_Use/select_selectedindex.html b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/Not_Use/select_selectedindex.html
new file mode 100644
index 00000000000..e6d69017987
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/Not_Use/select_selectedindex.html
@@ -0,0 +1,50 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Forms</title>
+ <script src="../../resources/testharness.js"></script>
+ <script src="../../resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <p>
+ <h3>select_selectedIndex</h3>
+ </p>
+
+ <li>In select control second item is selected.</li>
+
+ <hr>
+
+ <div id="log"></div>
+
+ <form method="post"
+ enctype="application/x-www-form-urlencoded"
+ action=""
+ id="input_form">
+ <p>
+ <label for="unittype">Select unit type:</label>
+ <select id="unittype" name="unittype">
+ <option value="1"> Miner </option>
+ <option value="2"> Puffer </option>
+ <option value="3" selected> Snipey </option>
+ <option value="4"> Max </option>
+ <option value="5"> Firebot </option>
+ </select>
+ </p>
+ </form>
+
+ <script>
+
+ var select = document.getElementById("unittype");
+ var selectedindex = select.selectedIndex;
+
+ if (selectedindex != 2) {
+ test(function() {
+ assert_true(false, "selectedindex attribute is not correct.");
+ });
+ }
+
+ select.selectedIndex = 1;
+ </script>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/button_checkvalidity.html b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/button_checkvalidity.html
new file mode 100644
index 00000000000..7e906875674
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/button_checkvalidity.html
@@ -0,0 +1,44 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Forms</title>
+ <script src="../../resources/testharness.js"></script>
+ <script src="../../resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <p>
+ <h3>button_checkValidity</h3>
+ </p>
+
+ <hr>
+
+ <div id="log"></div>
+
+ <form method="post"
+ enctype="application/x-www-form-urlencoded"
+ action=""
+ id="input_form">
+ <p><button id='button_id'>button</button></p>
+ </form>
+ <script>
+
+ var button = document.getElementById("button_id");
+
+ try
+ {
+ var ret = button.checkValidity();
+
+ test(function() {
+ assert_equals(ret, true, "calling of checkValidity method is failed.");
+ });
+ }
+ catch (e) {
+ test(function() {
+ assert_unreached("autofocus attribute is not exist.");
+ });
+ }
+
+ </script>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/button_labels.html b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/button_labels.html
new file mode 100644
index 00000000000..81076d78048
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/button_labels.html
@@ -0,0 +1,48 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Forms</title>
+ <script src="../../resources/testharness.js"></script>
+ <script src="../../resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <p>
+ <h3>button_labels</h3>
+ </p>
+
+ <hr>
+
+ <div id="log"></div>
+
+ <form method="post"
+ enctype="application/x-www-form-urlencoded"
+ action=""
+ id="input_form">
+ <p><label>Full name:<label>(name)<button id='button_id1'>button1</button><small>Format: First Last</small></label></label></p>
+ <p><label>Age: <button id='button_id2'>button2</button></label></p>
+ </form>
+ <script>
+
+ var button1 = document.getElementById("button_id1");
+ var button2 = document.getElementById("button_id2");
+
+ if (typeof(button1.labels) == "object") {
+ if (button1.labels.length == 2 && button2.labels.length == 1) {
+ test(function() {
+ assert_true(true, "labels attribute is correct.");
+ });
+ } else {
+ test(function() {
+ assert_unreached("labels attribute is not correct.");
+ });
+ }
+ } else {
+ test(function() {
+ assert_unreached("labels attribute is not exist.");
+ });
+ }
+
+ </script>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/button_setcustomvalidity.html b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/button_setcustomvalidity.html
new file mode 100644
index 00000000000..f617e5bf2b7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/button_setcustomvalidity.html
@@ -0,0 +1,43 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Forms</title>
+ <script src="../../resources/testharness.js"></script>
+ <script src="../../resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <p>
+ <h3>button_setCustomValidity</h3>
+ </p>
+
+ <hr>
+
+ <div id="log"></div>
+
+ <form method="post"
+ enctype="application/x-www-form-urlencoded"
+ action=""
+ id="input_form">
+ <p><button id='button_id'>button</button></p>
+ </form>
+ <script>
+
+ var button = document.getElementById("button_id");
+
+ try
+ {
+ button.setCustomValidity("custom error");
+ test(function() {
+ assert_true(true, "calling of setCustomValidity method is successed.");
+ });
+ }
+ catch (e) {
+ test(function() {
+ assert_unreached("Error is raised.");
+ });
+ }
+
+ </script>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/button_validationmessage.html b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/button_validationmessage.html
new file mode 100644
index 00000000000..00dc287e41b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/button_validationmessage.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Forms</title>
+ <script src="../../resources/testharness.js"></script>
+ <script src="../../resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <p>
+ <h3>button_validationMessage</h3>
+ </p>
+
+ <hr>
+
+ <div id="log"></div>
+
+ <form method="post"
+ enctype="application/x-www-form-urlencoded"
+ action=""
+ id="input_form">
+ <p><button id='button_id'>button</button></p>
+ </form>
+ <script>
+
+ var button = document.getElementById("button_id");
+
+ if (typeof(button.validationMessage) == "string") {
+ test(function() {
+ assert_equals(button.validationMessage, "", "validationMessage attribute is not correct.");
+ });
+ } else {
+ test(function() {
+ assert_unreached("validationMessage attribute is not exist.");
+ });
+ }
+
+ </script>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/button_validity.html b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/button_validity.html
new file mode 100644
index 00000000000..184f187462a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/button_validity.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Forms</title>
+ <script src="../../resources/testharness.js"></script>
+ <script src="../../resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <p>
+ <h3>button_validity</h3>
+ </p>
+
+ <hr>
+
+ <div id="log"></div>
+
+ <form method="post"
+ enctype="application/x-www-form-urlencoded"
+ action=""
+ id="input_form">
+ <p><button id='button_id'>button</button></p>
+ </form>
+ <script>
+
+ var button = document.getElementById("button_id");
+
+ if (typeof(button.validity) == "object") {
+ test(function() {
+ assert_equals(button.validity.valueMissing, false, "validity attribute is not correct.");
+ });
+ } else {
+ test(function() {
+ assert_unreached("validity attribute is not exist.");
+ });
+ }
+
+ </script>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/button_willvalidate.html b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/button_willvalidate.html
new file mode 100644
index 00000000000..36166611f47
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/button_willvalidate.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Forms</title>
+ <script src="../../resources/testharness.js"></script>
+ <script src="../../resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <p>
+ <h3>button_willValidate</h3>
+ </p>
+
+ <hr>
+
+ <div id="log"></div>
+
+ <form method="post"
+ enctype="application/x-www-form-urlencoded"
+ action=""
+ id="input_form">
+ <p><button id='button_id'>button</button></p>
+ </form>
+ <script>
+
+ var button = document.getElementById("button_id");
+
+ if (typeof(button.willValidate) == "boolean") {
+ test(function() {
+ assert_equals(button.willValidate, true, "willValidate attribute is not correct.");
+ });
+ } else {
+ test(function() {
+ assert_unreached("willValidate attribute is not exist.");
+ });
+ }
+
+ </script>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/fieldset_checkvalidity.html b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/fieldset_checkvalidity.html
new file mode 100644
index 00000000000..4989b2ad82d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/fieldset_checkvalidity.html
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Forms</title>
+ <script src="../../resources/testharness.js"></script>
+ <script src="../../resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <p>
+ <h3>FieldSet_checkValidity</h3>
+ </p>
+
+ <hr>
+
+ <div id="log"></div>
+
+ <form method="post"
+ enctype="application/x-www-form-urlencoded"
+ action=""
+ id="input_form">
+ <fieldset id="input_field">
+ </fieldset>
+ </form>
+ <script>
+
+ var field = document.getElementById("input_field");
+
+ try
+ {
+ var ret = field.checkValidity();
+
+ test(function() {
+ assert_equals(ret, true, "calling of checkValidity method is failed.");
+ });
+ }
+ catch (e) {
+ test(function() {
+ assert_unreached("Error is raised.");
+ });
+ }
+
+ </script>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/fieldset_setcustomvalidity.html b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/fieldset_setcustomvalidity.html
new file mode 100644
index 00000000000..48e3839e6e7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/fieldset_setcustomvalidity.html
@@ -0,0 +1,44 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Forms</title>
+ <script src="../../resources/testharness.js"></script>
+ <script src="../../resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <p>
+ <h3>FieldSet_setCustomValidity</h3>
+ </p>
+
+ <hr>
+
+ <div id="log"></div>
+
+ <form method="post"
+ enctype="application/x-www-form-urlencoded"
+ action=""
+ id="input_form">
+ <fieldset id="input_field">
+ </fieldset>
+ </form>
+ <script>
+
+ var field = document.getElementById("input_field");
+
+ try
+ {
+ field.setCustomValidity("custom error");
+ test(function() {
+ assert_true(true, "calling of setCustomValidity method is successed.");
+ });
+ }
+ catch (e) {
+ test(function() {
+ assert_unreached("Error is raised.");
+ });
+ }
+
+ </script>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/fieldset_validationmessage.html b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/fieldset_validationmessage.html
new file mode 100644
index 00000000000..2b8d00f978a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/fieldset_validationmessage.html
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Forms</title>
+ <script src="../../resources/testharness.js"></script>
+ <script src="../../resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <p>
+ <h3>FieldSet_validationMessage</h3>
+ </p>
+
+ <hr>
+
+ <div id="log"></div>
+
+ <form method="post"
+ enctype="application/x-www-form-urlencoded"
+ action=""
+ id="input_form">
+ <fieldset id="input_field">
+ </fieldset>
+ </form>
+ <script>
+
+ var field = document.getElementById("input_field");
+
+ if (typeof(field.validationMessage) == "string") {
+ test(function() {
+ assert_equals(field.validationMessage, "", "validationMessage attribute is not correct.");
+ });
+ } else {
+ test(function() {
+ assert_unreached("validationMessage attribute is not exist.");
+ });
+ }
+
+ </script>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/fieldset_validity.html b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/fieldset_validity.html
new file mode 100644
index 00000000000..3474275640e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/fieldset_validity.html
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Forms</title>
+ <script src="../../resources/testharness.js"></script>
+ <script src="../../resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <p>
+ <h3>FieldSet_validity</h3>
+ </p>
+
+ <hr>
+
+ <div id="log"></div>
+
+ <form method="post"
+ enctype="application/x-www-form-urlencoded"
+ action=""
+ id="input_form">
+ <fieldset id="input_field">
+ </fieldset>
+ </form>
+ <script>
+
+ var field = document.getElementById("input_field");
+
+ if (typeof(field.validity) == "object") {
+ test(function() {
+ assert_equals(field.validity.valueMissing, false, "validity attribute is not correct.");
+ });
+ } else {
+ test(function() {
+ assert_unreached("validity attribute is not exist.");
+ });
+ }
+
+ </script>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/fieldset_willvalidate.html b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/fieldset_willvalidate.html
new file mode 100644
index 00000000000..c7e5853f4fd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/fieldset_willvalidate.html
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Forms</title>
+ <script src="../../resources/testharness.js"></script>
+ <script src="../../resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <p>
+ <h3>FieldSet_willValidate</h3>
+ </p>
+
+ <hr>
+
+ <div id="log"></div>
+
+ <form method="post"
+ enctype="application/x-www-form-urlencoded"
+ action=""
+ id="input_form">
+ <fieldset id="input_field">
+ </fieldset>
+ </form>
+ <script>
+
+ var field = document.getElementById("input_field");
+
+ if (typeof(field.willValidate) == "boolean") {
+ test(function() {
+ assert_equals(field.willValidate, false, "willValidate attribute is not correct.");
+ });
+ } else {
+ test(function() {
+ assert_unreached("willValidate attribute is not exist.");
+ });
+ }
+
+ </script>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/form_action.html b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/form_action.html
new file mode 100644
index 00000000000..d8e2703f8a5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/form_action.html
@@ -0,0 +1,43 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Forms</title>
+ <script src="../../resources/testharness.js"></script>
+ <script src="../../resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <p>
+ <h3>Form_action</h3>
+ </p>
+
+ <hr>
+
+ <div id="log"></div>
+
+ <form method="post"
+ enctype="application/x-www-form-urlencoded"
+ action="http://www.google.com/"
+ id="input_form">
+ <p><input type=hidden name="custname"></p>
+ <p><input type=hidden name="custtel"></p>
+ <p><input type=hidden name="custemail"></p>
+
+ </form>
+ <script>
+
+ var form = document.getElementById("input_form");
+
+ if (typeof(form.action) == "string") {
+ test(function() {
+ assert_equals(form.action, "http://www.google.com/", "action attribute is not correct.");
+ });
+ } else {
+ test(function() {
+ assert_unreached("action attribute is not exist.");
+ });
+ }
+
+ </script>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/form_checkvalidity.html b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/form_checkvalidity.html
new file mode 100644
index 00000000000..931843d0d57
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/form_checkvalidity.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Forms</title>
+ <script src="../../resources/testharness.js"></script>
+ <script src="../../resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <p>
+ <h3>Form_checkValidity</h3>
+ </p>
+
+ <hr>
+
+ <div id="log"></div>
+
+ <form method="post"
+ enctype="application/x-www-form-urlencoded"
+ action=""
+ id="input_form">
+ <p><input type=hidden name="custname"></p>
+ <p><input type=hidden name="custtel"></p>
+ <p><input type=hidden name="custemail"></p>
+
+ </form>
+ <script>
+
+ var form = document.getElementById("input_form");
+
+ try
+ {
+ var ret = form.checkValidity();
+
+ test(function() {
+ assert_equals(ret, true, "calling of checkValidity method is failed.");
+ });
+ }
+ catch (e) {
+ test(function() {
+ assert_unreached("Error is raised.");
+ });
+ }
+
+ </script>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/form_length.html b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/form_length.html
new file mode 100644
index 00000000000..cf7da08a75f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/form_length.html
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Forms</title>
+ <script src="../../resources/testharness.js"></script>
+ <script src="../../resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <p>
+ <h3>Form_length</h3>
+ </p>
+
+ <hr>
+
+ <div id="log"></div>
+
+ <form method="post"
+ enctype="application/x-www-form-urlencoded"
+ action=""
+ id="input_form">
+ <p><input type=hidden name="custname"></p>
+ <p><input type=hidden name="custtel"></p>
+ <p><input type=hidden name="custemail"></p>
+
+ </form>
+ <script>
+
+ var form = document.getElementById("input_form");
+ var len = form.length;
+
+ test(function() {
+ assert_equals(len, 3, "length attribute is not correct.");
+ });
+
+ </script>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/form_submit.html b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/form_submit.html
new file mode 100644
index 00000000000..a6acd08335f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/form_submit.html
@@ -0,0 +1,51 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Forms</title>
+ <script src="../../resources/testharness.js"></script>
+ <script src="../../resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <p>
+ <h3>Form_submit</h3>
+ </p>
+
+ <hr>
+
+ <div id="log"></div>
+
+ <form method="post"
+ enctype="application/x-www-form-urlencoded"
+ action="?x=1"
+ id="input_form">
+ <p><input type=hidden name="custname"></p>
+ <p><input type=hidden name="custtel"></p>
+ <p><input type=hidden name="custemail"></p>
+
+ </form>
+ <script>
+
+ var form = document.getElementById("input_form");
+
+ try
+ {
+ var url = location.href;
+ pos = url.lastIndexOf("?x=1");
+ if (pos == -1) {
+ form.submit();
+ } else {
+ test(function() {
+ assert_true(true, "calling of submit method is successed.");
+ });
+ }
+ }
+ catch (e) {
+ test(function() {
+ assert_unreached("Error is raised.");
+ });
+ }
+
+ </script>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/input_checkvalidity.html b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/input_checkvalidity.html
new file mode 100644
index 00000000000..1e239b3f294
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/input_checkvalidity.html
@@ -0,0 +1,44 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Forms</title>
+ <script src="../../resources/testharness.js"></script>
+ <script src="../../resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <p>
+ <h3>input_checkValidity</h3>
+ </p>
+
+ <hr>
+
+ <div id="log"></div>
+
+ <form method="post"
+ enctype="application/x-www-form-urlencoded"
+ action=""
+ id="input_form">
+ <p><input type='hidden' id='input_text'></p>
+ </form>
+ <script>
+
+ var input = document.getElementById("input_text");
+
+ try
+ {
+ var ret = input.checkValidity();
+
+ test(function() {
+ assert_equals(ret, true, "calling of checkValidity method is failed.");
+ });
+ }
+ catch (e) {
+ test(function() {
+ assert_unreached("Error is raised.");
+ });
+ }
+
+ </script>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/input_height.html b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/input_height.html
new file mode 100644
index 00000000000..72455038894
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/input_height.html
@@ -0,0 +1,42 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Forms</title>
+ <script src="../../resources/testharness.js"></script>
+ <script src="../../resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <p>
+ <h3>input_height</h3>
+ </p>
+
+ <hr>
+
+ <div id="log"></div>
+
+ <form method="post"
+ enctype="application/x-www-form-urlencoded"
+ action=""
+ name="input_form">
+ <p><input type='image' id='input_text'></p>
+ </form>
+
+ <script>
+
+ var input_text = document.getElementById("input_text");
+ input_text.height = 30;
+
+ if (typeof(input_text.height) == "number") {
+ test(function() {
+ assert_equals(input_text.height, 30, "formTarget attribute is not correct.");
+ });
+ } else {
+ test(function() {
+ assert_unreached("height attribute is not exist.");
+ });
+ }
+
+ </script>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/input_labels.html b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/input_labels.html
new file mode 100644
index 00000000000..ef8f3de1df4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/input_labels.html
@@ -0,0 +1,49 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Forms</title>
+ <script src="../../resources/testharness.js"></script>
+ <script src="../../resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <p>
+ <h3>input_labels</h3>
+ </p>
+
+ <hr>
+
+ <div id="log"></div>
+
+ <form method="post"
+ enctype="application/x-www-form-urlencoded"
+ action=""
+ id="input_form">
+ <p><label>Full name:<label>(name)<input name=fn id='input_text1'> <small>Format: First Last</small></label></label></p>
+ <p><label>Age: <input name=age type=number min=0 id='input_text2'></label></p>
+ <p><label>Post code: <input name=pc> <small>Format: AB12 3CD</small></label></p>
+ </form>
+ <script>
+
+ var input1 = document.getElementById("input_text1");
+ var input2 = document.getElementById("input_text2");
+
+ if (typeof(input1.labels) == "object") {
+ if (input1.labels.length == 2 && input2.labels.length == 1) {
+ test(function() {
+ assert_true(true, "labels attribute is correct.");
+ });
+ } else {
+ test(function() {
+ assert_unreached("labels attribute is not correct.");
+ });
+ }
+ } else {
+ test(function() {
+ assert_unreached("labels attribute is not exist.");
+ });
+ }
+
+ </script>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/input_setcustomvalidity.html b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/input_setcustomvalidity.html
new file mode 100644
index 00000000000..d0f6315fe2c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/input_setcustomvalidity.html
@@ -0,0 +1,43 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Forms</title>
+ <script src="../../resources/testharness.js"></script>
+ <script src="../../resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <p>
+ <h3>input_setCustomValidity</h3>
+ </p>
+
+ <hr>
+
+ <div id="log"></div>
+
+ <form method="post"
+ enctype="application/x-www-form-urlencoded"
+ action=""
+ id="input_form">
+ <p><input type='hidden' id='input_text'></p>
+ </form>
+ <script>
+
+ var input = document.getElementById("input_text");
+
+ try
+ {
+ input.setCustomValidity("custom error");
+ test(function() {
+ assert_true(true, "calling of setCustomValidity method is successed.");
+ });
+ }
+ catch (e) {
+ test(function() {
+ assert_unreached("Error is raised.");
+ });
+ }
+
+ </script>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/input_stepdown.html b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/input_stepdown.html
new file mode 100644
index 00000000000..cddd9dc687e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/input_stepdown.html
@@ -0,0 +1,44 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Forms</title>
+ <script src="../../resources/testharness.js"></script>
+ <script src="../../resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <p>
+ <h3>input_stepDown</h3>
+ </p>
+
+ <hr>
+
+ <div id="log"></div>
+
+ <form method="post"
+ enctype="application/x-www-form-urlencoded"
+ action=""
+ name="input_form">
+ <p><input type='number' id='input_number'></p>
+ </form>
+
+ <script>
+ var input_number = document.getElementById("input_number");
+ input_number.max = "30";
+ input_number.step = "3";
+ input_number.value = "30";
+ input_number.stepDown(5);
+
+ if (typeof(input_number.stepDown) == "function") {
+ test(function() {
+ assert_equals(input_number.value, "15", "call of stepDown method is failed.");
+ });
+ } else {
+ test(function() {
+ assert_unreached("stepDown attribute is not exist.");
+ });
+ }
+
+ </script>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/input_stepup.html b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/input_stepup.html
new file mode 100644
index 00000000000..789eb005efa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/input_stepup.html
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Forms</title>
+ <script src="../../resources/testharness.js"></script>
+ <script src="../../resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <p>
+ <h3>input_stepUp</h3>
+ </p>
+
+ <hr>
+
+ <div id="log"></div>
+
+ <form method="post"
+ enctype="application/x-www-form-urlencoded"
+ action=""
+ name="input_form">
+ <p><input type='number' id='input_number'></p>
+ </form>
+
+ <script>
+
+ var input_number = document.getElementById("input_number");
+ input_number.max = "30";
+ input_number.step = "3";
+ input_number.value = "0";
+ input_number.stepUp(5);
+
+ if (typeof(input_number.stepUp) == "function") {
+ test(function() {
+ assert_equals(input_number.value, "15", "call of stepUp method is failed.");
+ });
+ } else {
+ test(function() {
+ assert_unreached("stepUp attribute is not exist.");
+ });
+ }
+
+ </script>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/input_validationmessage.html b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/input_validationmessage.html
new file mode 100644
index 00000000000..c19d3e74a67
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/input_validationmessage.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Forms</title>
+ <script src="../../resources/testharness.js"></script>
+ <script src="../../resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <p>
+ <h3>input_validationMessage</h3>
+ </p>
+
+ <hr>
+
+ <div id="log"></div>
+
+ <form method="post"
+ enctype="application/x-www-form-urlencoded"
+ action=""
+ id="input_form">
+ <p><input type='hidden' id='input_text'></p>
+ </form>
+ <script>
+
+ var input = document.getElementById("input_text");
+
+ if (typeof(input.validationMessage) == "string") {
+ test(function() {
+ assert_equals(input.validationMessage, "", "validationMessage attribute is not correct.");
+ });
+ } else {
+ test(function() {
+ assert_unreached("validationMessage attribute is not exist.");
+ });
+ }
+
+ </script>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/input_validity.html b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/input_validity.html
new file mode 100644
index 00000000000..32ff63c0839
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/input_validity.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Forms</title>
+ <script src="../../resources/testharness.js"></script>
+ <script src="../../resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <p>
+ <h3>input_validity</h3>
+ </p>
+
+ <hr>
+
+ <div id="log"></div>
+
+ <form method="post"
+ enctype="application/x-www-form-urlencoded"
+ action=""
+ id="input_form">
+ <p><input type='hidden' id='input_text'></p>
+ </form>
+ <script>
+
+ var input = document.getElementById("input_text");
+
+ if (typeof(input.validity) == "object") {
+ test(function() {
+ assert_equals(input.validity.valueMissing, false, "validity attribute is not correct.");
+ });
+ } else {
+ test(function() {
+ assert_unreached("validity attribute is not exist.");
+ });
+ }
+
+ </script>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/input_value_invalidstateerr.html b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/input_value_invalidstateerr.html
new file mode 100644
index 00000000000..ed7ae334ced
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/input_value_invalidstateerr.html
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Forms</title>
+ <script src="../../resources/testharness.js"></script>
+ <script src="../../resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <p>
+ <h3>input_value_INVALID_STATE_ERR</h3>
+ </p>
+
+ <hr>
+
+ <div id="log"></div>
+
+ <form method="post"
+ enctype="application/x-www-form-urlencoded"
+ action=""
+ name="input_form">
+ <p><input type='file' id='input_file'></p>
+ </form>
+
+ <script>
+
+ var input_file = document.getElementById("input_file");
+ try {
+ input_file.value = "val";
+ test(function() {
+ assert_unreached("INVALID_STATE_ERR error is not raised.");
+ });
+ } catch (e) {
+ test(function() {
+ assert_equals(e.code, e["INVALID_STATE_ERR"], "INVALID_STATE_ERR error is not raised.");
+ });
+ }
+
+ </script>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/input_valueasdate_invalidstateerr.html b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/input_valueasdate_invalidstateerr.html
new file mode 100644
index 00000000000..1e1533a9b38
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/input_valueasdate_invalidstateerr.html
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Forms</title>
+ <script src="../../resources/testharness.js"></script>
+ <script src="../../resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <p>
+ <h3>input_valueAsDate_INVALID_STATE_ERR</h3>
+ </p>
+
+ <hr>
+
+ <div id="log"></div>
+
+ <form method="post"
+ enctype="application/x-www-form-urlencoded"
+ action=""
+ name="input_form">
+ <p><input type='checkbox' id='input_checkbox'></p>
+ </form>
+
+ <script>
+ var input_checkbox = document.getElementById("input_checkbox");
+ try {
+ input_checkbox.valueAsDate = new Date('2011-11-01');
+ test(function() {
+ assert_reached("INVALID_STATE_ERR error is not raised.");
+ });
+ }
+ catch (e) {
+ test(function() {
+ assert_equals(e.code, e["INVALID_STATE_ERR"], "INVALID_STATE_ERR error is not raised.");
+ });
+ }
+
+ </script>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/input_valueasnumber_invalidstateerr.html b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/input_valueasnumber_invalidstateerr.html
new file mode 100644
index 00000000000..2450db2c831
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/input_valueasnumber_invalidstateerr.html
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Forms</title>
+ <script src="../../resources/testharness.js"></script>
+ <script src="../../resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <p>
+ <h3>input_valueAsNumber_INVALID_STATE_ERR</h3>
+ </p>
+
+ <hr>
+
+ <div id="log"></div>
+
+ <form method="post"
+ enctype="application/x-www-form-urlencoded"
+ action=""
+ name="input_form">
+ <p><input type='checkbox' id='input_checkbox'></p>
+ </form>
+
+ <script>
+
+ var input_checkbox = document.getElementById("input_checkbox");
+ try {
+ input_checkbox.valueAsNumber = 5;
+ }
+ catch (e) {
+ test(function() {
+ assert_equals(e.code, e["INVALID_STATE_ERR"], "INVALID_STATE_ERR error is not raised.");
+ });
+ }
+
+ </script>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/input_width.html b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/input_width.html
new file mode 100644
index 00000000000..db168147bc7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/input_width.html
@@ -0,0 +1,42 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Forms</title>
+ <script src="../../resources/testharness.js"></script>
+ <script src="../../resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <p>
+ <h3>input_width</h3>
+ </p>
+
+ <hr>
+
+ <div id="log"></div>
+
+ <form method="post"
+ enctype="application/x-www-form-urlencoded"
+ action=""
+ name="input_form">
+ <p><input type='image' id='input_text'></p>
+ </form>
+
+ <script>
+
+ var input_text = document.getElementById("input_text");
+ input_text.width = 30;
+
+ if (typeof(input_text.width) == "number") {
+ test(function() {
+ assert_equals(input_text.width, 30, "width attribute is not correct.");
+ });
+ } else {
+ test(function() {
+ assert_unreached("width attribute is not exist.");
+ });
+ }
+
+ </script>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/input_willvalidate.html b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/input_willvalidate.html
new file mode 100644
index 00000000000..04d360e12f1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/input_willvalidate.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Forms</title>
+ <script src="../../resources/testharness.js"></script>
+ <script src="../../resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <p>
+ <h3>input_willValidate</h3>
+ </p>
+
+ <hr>
+
+ <div id="log"></div>
+
+ <form method="post"
+ enctype="application/x-www-form-urlencoded"
+ action=""
+ id="input_form">
+ <p><input type='hidden' id='input_text'></p>
+ </form>
+ <script>
+
+ var input = document.getElementById("input_text");
+
+ if (typeof(input.willValidate) == "boolean") {
+ test(function() {
+ assert_equals(input.willValidate, false, "willValidate attribute is not correct.");
+ });
+ } else {
+ test(function() {
+ assert_unreached("willValidate attribute is not exist.");
+ });
+ }
+
+ </script>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/keygen_checkvalidity.html b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/keygen_checkvalidity.html
new file mode 100644
index 00000000000..7ea35881273
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/keygen_checkvalidity.html
@@ -0,0 +1,44 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Forms</title>
+ <script src="../../resources/testharness.js"></script>
+ <script src="../../resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <p>
+ <h3>keygen_checkValidity</h3>
+ </p>
+
+ <hr>
+
+ <div id="log"></div>
+
+ <form method="post"
+ enctype="application/x-www-form-urlencoded"
+ action=""
+ id="input_form">
+ <keygen name='key' id='keygen_id'></keygen>
+ </form>
+ <script>
+
+ var keygen = document.getElementById("keygen_id");
+
+ try
+ {
+ var ret = keygen.checkValidity();
+
+ test(function() {
+ assert_equals(ret, true, "calling of checkValidity method is failed.");
+ });
+ }
+ catch (e) {
+ test(function() {
+ assert_unreached("Error is raised.");
+ });
+ }
+
+ </script>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/keygen_labels.html b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/keygen_labels.html
new file mode 100644
index 00000000000..381f221e431
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Forms/contents/Forms/keygen_labels.html
@@ -0,0 +1,48 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Forms</title>
+ <script src="../../resources/testharness.js"></script>
+ <script src="../../resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <p>
+ <h3>keygen_labels</h3>
+ </p>
+
+ <hr>
+
+ <div id="log"></div>
+
+ <form method="post"
+ enctype="application/x-www-form-urlencoded"
+ action=""
+ id="input_form">
+ <p><label>Full name<label>(name):<keygen name='key1' id='keygen_id1'></keygen></label></label></p>
+ <p><label>Age:<keygen name='key2' id='keygen_id2'></keygen></label></p>
+ </form>
+ <script>
+
+ var keygen1 = document.getElementById("keygen_id1");
+ var keygen2 = document.getElementById("keygen_id2");
+
+ if (typeof(keygen1.labels) == "object") {
+ if (keygen1.labels.length == 2 && keygen2.labels.length == 1) {
+ test(function() {
+ assert_true(true, "labels attribute is correct.");
+ });
+ } else {
+ test(function() {
+ assert_unreached("labels attribute is not correct.");
+ });
+ }
+ } else {
+ test(function() {
+ assert_unreached("labels attribute is not exist.");
+ });
+ }
+
+ </script>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Session_History/contents/Session_History/css/result.css b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Session_History/contents/Session_History/css/result.css
new file mode 100644
index 00000000000..7bbc5173053
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Session_History/contents/Session_History/css/result.css
@@ -0,0 +1,12 @@
+.pass {
+ color: green;
+}
+.fail {
+ color: red;
+}
+.manualpass {
+ color: green;
+}
+.manualfail {
+ color: red;
+} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Session_History/contents/Session_History/index.html b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Session_History/contents/Session_History/index.html
new file mode 100644
index 00000000000..7c556410220
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Infraware/Session_History/contents/Session_History/index.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=0.5, maximum-scale=3.0, user-scalable=yes" />
+ <title>Session History</title>
+
+ <script type="text/javascript">
+ </script>
+ </head>
+
+ <body>
+ <p>
+ <b>Session History&nbsp;</b><br/>
+ <hr/>
+ <ol type="1">
+ <font size="2">
+ <!-- <li><a href="history_length.html">history_length</a></li> -->
+ <li><a href="history_state.html">history_state</a></li>
+
+ <li><a href="history_pushstate.html">history_pushState</a></li>
+ <li><a href="history_pushstate_nooptionalparam.html">history_pushState_NoOptionalParam</a></li>
+ <li><a href="history_pushstate_err.html">history_pushState SECURITY_ERR</a></li>
+ <li><a href="history_replacestate.html">history_replaceState</a></li>
+ <li><a href="history_replacestate_nooptionalparam.html">history_replaceStateNoOptionalParam</a></li>
+ <li><a href="history_replacestate_err.html">history_replaceState SECURITY_ERR</a></li>
+
+ <li><a href="history_back.html">history_back</a></li>
+ <li><a href="history_forward.html">history_forward</a></li>
+
+ <li><a href="history_go_minus.html">history_go_minus</a></li>
+ <li><a href="history_go_plus.html">history_go_plus</a></li>
+ <!-- <li><a href="history_go_zero.html">history_go_zero</a></li> -->
+
+ <!-- <li><a href="history_go_under.html">history_go_under</a></li> -->
+ <!-- <li><a href="history_go_over.html">history_go_over</a></li> -->
+
+ <li><a href="location_href.html">location_href</a></li>
+ <li><a href="location_assign.html">location_assign</a></li>
+ <li><a href="location_replace.html">location_replace</a></li>
+ <!-- <li><a href="location_reload.html">location_reload</a></li> -->
+ <li><a href="location_protocol.html">location_protocol</a></li>
+ <li><a href="location_host.html">location_host</a></li>
+ <li><a href="location_hostname.html">location_hostname</a></li>
+ <li><a href="location_port.html">location_port</a></li>
+ <li><a href="location_pathname.html">location_pathname</a></li>
+ <li><a href="location_search.html">location_search</a></li>
+ <li><a href="location_hash.html">location_hash</a></li>
+
+ <li><a href="combination_history_001.html">combination_history_001</a></li>
+ <li><a href="combination_history_002.html">combination_history_002</a></li>
+ <li><a href="combination_history_003.html">combination_history_003</a></li>
+ <li><a href="combination_history_004.html">combination_history_004</a></li>
+ <li><a href="combination_history_005.html">combination_history_005</a></li>
+ <li><a href="combination_history_006.html">combination_history_006</a></li>
+ <li><a href="combination_history_007.html">combination_history_007</a></li>
+
+ </font>
+ </ol>
+ <hr/>
+ <p>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_000.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_000.htm
new file mode 100644
index 00000000000..278157644b1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_000.htm
@@ -0,0 +1,62 @@
+<!doctype html>
+<html>
+ <head>
+ <title>HTML5 Drag and Drop: Fire drag event during the drag and drop processing</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/"/>
+ <link rel="help" href="http://dev.w3.org/html5/spec/dnd.html#drag-and-drop-processing-model"/>
+ <meta name="assert" content="Fire drag event during the drag and drop processing"/>
+ <script src="dragdrop_support.js" type="text/javascript"></script>
+ <script type="text/javascript">
+ var EVENT, TARGET;
+
+ function DragEvent(evt)
+ {
+ if ((TARGET == evt.target) && (EVENT == evt.type))
+ {
+ LogTestResult("PASS");
+ }
+ else
+ {
+ LogTestResult("FAIL");
+ }
+ }
+
+ EVENT = "drag";
+
+ window.onload = function()
+ {
+ TARGET = document.getElementById("target");
+ AddEventListenersForElement(EVENT, DragEvent, false, TARGET);
+ }
+ </script>
+ </head>
+ <body>
+ <pre>Description: Fire drag event during the drag and drop processing</pre>
+ <table id='testtable' border='1'>
+ <tr>
+ <td>Test Result</td>
+ <td>Test Assertion</td>
+ </tr>
+ <tr>
+ <td id='test_result'>Manual</td>
+ <td id='test_assertion'>Test passes if if the word "PASS" appears to the left after following the steps below.
+ <div id="manualsteps">
+ Steps:
+ <ol>
+ <li> Click and drag the blue image
+ </ol>
+ </div>
+ </td>
+ </tr>
+ </table>
+ <p>
+ http://dev.w3.org/html5/spec/dnd.html#drag-and-drop-processing-model
+ </p>
+ <p>
+ If the user agent is still performing the previous iteration of the sequence (if any) when the next iteration becomes due, abort these steps for this iteration (effectively "skipping missed frames" of the drag-and-drop operation).
+ Fire a DND event named drag event at the source node. If this event is canceled, the user agent must set the current drag operation to "none" (no drag operation).
+ </p>
+ <img src="../images/blue.png" style="width:200px; height:100px" draggable="true" id="target"/>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_001.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_001.htm
new file mode 100644
index 00000000000..3514f2193c7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_001.htm
@@ -0,0 +1,62 @@
+<!doctype html>
+<html>
+ <head>
+ <title>HTML5 Drag and Drop: Fire drag event when dragging a div element</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/"/>
+ <link rel="help" href="http://dev.w3.org/html5/spec/dnd.html#drag-and-drop-processing-model"/>
+ <meta name="assert" content="Fire drag event when dragging a div element"/>
+ <script src="dragdrop_support.js" type="text/javascript"></script>
+ <script type="text/javascript">
+ var EVENT, TARGET;
+
+ function DragEvent(evt)
+ {
+ if ((TARGET == evt.target) && (EVENT == evt.type))
+ {
+ LogTestResult("PASS");
+ }
+ else
+ {
+ LogTestResult("FAIL");
+ }
+ }
+
+ EVENT = "drag";
+
+ window.onload = function()
+ {
+ TARGET = document.getElementById("target");
+ AddEventListenersForElement(EVENT, DragEvent, false, TARGET);
+ }
+ </script>
+ </head>
+ <body>
+ <pre>Description: Fire drag event when dragging a div element</pre>
+ <table id='testtable' border='1'>
+ <tr>
+ <td>Test Result</td>
+ <td>Test Assertion</td>
+ </tr>
+ <tr>
+ <td id='test_result'>Manual</td>
+ <td id='test_assertion'>Test passes if if the word "PASS" appears to the left after following the steps below.
+ <div id="manualsteps">
+ Steps:
+ <ol>
+ <li> Click and drag the red box
+ </ol>
+ </div>
+ </td>
+ </tr>
+ </table>
+ <p>
+ http://dev.w3.org/html5/spec/dnd.html#drag-and-drop-processing-model
+ </p>
+ <p>
+ If the user agent is still performing the previous iteration of the sequence (if any) when the next iteration becomes due, abort these steps for this iteration (effectively "skipping missed frames" of the drag-and-drop operation).
+ Fire a DND event named drag event at the source node. If this event is canceled, the user agent must set the current drag operation to "none" (no drag operation).
+ </p>
+ <div id="target" style="border:2px red solid; width:200px; height:50px" draggable="true"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_002.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_002.htm
new file mode 100644
index 00000000000..fdd40b57769
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_002.htm
@@ -0,0 +1,64 @@
+<!doctype html>
+<html>
+ <head>
+ <title>HTML5 Drag and Drop: Fire dragend event during the drag and drop processing</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/"/>
+ <link rel="help" href="http://dev.w3.org/html5/spec/dnd.html#drag-and-drop-processing-model"/>
+ <meta name="assert" content="Fire dragend event during the drag and drop processing"/>
+ <script src="dragdrop_support.js" type="text/javascript"></script>
+ <script type="text/javascript">
+ var EVENT, TARGET;
+
+ function DragendEvent(evt)
+ {
+ if ((TARGET == evt.target) && (EVENT == evt.type))
+ {
+ LogTestResult("PASS");
+ }
+ else
+ {
+ LogTestResult("FAIL");
+ }
+ }
+
+ EVENT = "dragend";
+
+ window.onload = function()
+ {
+ TARGET = document.getElementById("target");
+ AddEventListenersForElement(EVENT, DragendEvent, false, TARGET);
+ }
+ </script>
+ </head>
+ <body>
+ <pre>Description: Fire dragend event during the drag and drop processing</pre>
+ <table id='testtable' border='1'>
+ <tr>
+ <td>Test Result</td>
+ <td>Test Assertion</td>
+ </tr>
+ <tr>
+ <td id='test_result'>Manual</td>
+ <td id='test_assertion'>Test passes if if the word "PASS" appears to the left after following the steps below.
+ <div id="manualsteps">
+ Steps:
+ <ol>
+ <li> Drag the blue image
+ <li> Drop it on the green box
+ </ol>
+ </div>
+ </td>
+ </tr>
+ </table>
+ <p>
+ http://dev.w3.org/html5/spec/dnd.html#drag-and-drop-processing-model
+ </p>
+ <p>
+ If the drag operation failed or succeeded, fire a DND event named dragend at the source node.
+ </p>
+ <img src="../images/blue.png" style="width:200px; height:100px" draggable="true" id="target"/>
+ <br /><br />
+ <input type="text" style="border:2px green solid; width:200px; height:50px"></input>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_003.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_003.htm
new file mode 100644
index 00000000000..bde48b9cc09
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_003.htm
@@ -0,0 +1,67 @@
+<!doctype html>
+<html>
+ <head>
+ <title>HTML5 Drag and Drop: Fire dragenter event during the drag and drop processing</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/"/>
+ <link rel="help" href="http://dev.w3.org/html5/spec/dnd.html#drag-and-drop-processing-model"/>
+ <meta name="assert" content="Fire dragenter event during the drag and drop processing"/>
+ <script src="dragdrop_support.js" type="text/javascript"></script>
+ <script type="text/javascript">
+ var EVENT, TARGET;
+
+ function DragenterEvent(evt)
+ {
+ if ((TARGET == evt.target) && (EVENT == evt.type))
+ {
+ LogTestResult("PASS");
+ }
+ else
+ {
+ LogTestResult("FAIL");
+ }
+ }
+
+ EVENT = "dragenter";
+
+ window.onload = function()
+ {
+ TARGET = document.getElementById("target");
+ AddEventListenersForElement(EVENT, DragenterEvent, false, TARGET);
+ }
+ </script>
+ </head>
+ <body>
+ <pre>Description: Fire dragenter event during the drag and drop processing</pre>
+ <table id='testtable' border='1'>
+ <tr>
+ <td>Test Result</td>
+ <td>Test Assertion</td>
+ </tr>
+ <tr>
+ <td id='test_result'>Manual</td>
+ <td id='test_assertion'>Test passes if if the word "PASS" appears to the left after following the steps below.
+ <div id="manualsteps">
+ Steps:
+ <ol>
+ <li> Select the text inside the red box
+ <li> Drag it and enter the green box
+ </ol>
+ </div>
+ </td>
+ </tr>
+ </table>
+ <p>
+ http://dev.w3.org/html5/spec/dnd.html#drag-and-drop-processing-model
+ </p>
+ <p>
+ If the user is indicating a different immediate user selection than during the last iteration (or if this is the first iteration), and if this immediate user selection is not the same as the current target element, then update the current target element as follows:
+ - If the new immediate user selection is null, Set the current target element to null also.
+ - If the new immediate user selection is in a non-DOM document or application, Set the current target element to the immediate user selection.
+ - Otherwise, Fire a DND event named dragenter at the immediate user selection.
+ </p>
+ <div style="border:2px red solid; width:200px; height:50px">SampleText</div>
+ <br /><br />
+ <input type="text" id="target" style="border:2px green solid; width:200px; height:50px"></input>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_004.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_004.htm
new file mode 100644
index 00000000000..c97cc7dbf11
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_004.htm
@@ -0,0 +1,19 @@
+<!doctype html>
+<html>
+ <head>
+ <title>HTML5 Drag and Drop: Auto state of draggable attribute for 'a' element</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/"/>
+ <link rel="help" href="http://dev.w3.org/html5/spec/dnd.html#the-draggable-attribute"/>
+ <meta name="assert" content="Auto state of draggable attribute for 'a' element"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id=log></div>
+ <a href="#" style="display:none" id="target">Drag this</a>
+ <script type="text/javascript">
+ test(function() {assert_true(document.getElementById("target").draggable)}, "Auto state of draggable attribute for 'a' element");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_005.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_005.htm
new file mode 100644
index 00000000000..28305cd2646
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_005.htm
@@ -0,0 +1,19 @@
+<!doctype html>
+<html>
+ <head>
+ <title>HTML5 Drag and Drop: Auto state of draggable attribute for div element</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/"/>
+ <link rel="help" href="http://dev.w3.org/html5/spec/dnd.html#the-draggable-attribute"/>
+ <meta name="assert" content="Auto state of draggable attribute for div element"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id=log></div>
+ <div style="border:2px red solid; width:200px; height:50px; display:none;" id="target">SampleText</div>
+ <script type="text/javascript">
+ test(function() {assert_false(document.getElementById("target").draggable)}, "Auto state of draggable attribute for div element");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_006.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_006.htm
new file mode 100644
index 00000000000..4d8432b0731
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_006.htm
@@ -0,0 +1,19 @@
+<!doctype html>
+<html>
+ <head>
+ <title>HTML5 Drag and Drop: Auto state of draggable attribute for img element</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/"/>
+ <link rel="help" href="http://dev.w3.org/html5/spec/dnd.html#the-draggable-attribute"/>
+ <meta name="assert" content="Auto state of draggable attribute for img element"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id=log></div>
+ <img style="width:200px; height:100px; display:none;" id="target"/>
+ <script type="text/javascript">
+ test(function() {assert_true(document.getElementById("target").draggable)}, "Auto state of draggable attribute for img element");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_007.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_007.htm
new file mode 100644
index 00000000000..f14c70b3944
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_007.htm
@@ -0,0 +1,19 @@
+<!doctype html>
+<html>
+ <head>
+ <title>HTML5 Drag and Drop: False state of draggable attribute</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/"/>
+ <link rel="help" href="http://dev.w3.org/html5/spec/dnd.html#the-draggable-attribute"/>
+ <meta name="assert" content="False state of draggable attribute"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id=log></div>
+ <a href="#" style="display:none" id="target" draggable="false">Drag this</a>
+ <script type="text/javascript">
+ test(function() {assert_false(document.getElementById("target").draggable)}, "False state of draggable attribute");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_008.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_008.htm
new file mode 100644
index 00000000000..4716e518868
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_008.htm
@@ -0,0 +1,19 @@
+<!doctype html>
+<html>
+ <head>
+ <title>HTML5 Drag and Drop: True state of draggable attribute</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/"/>
+ <link rel="help" href="http://dev.w3.org/html5/spec/dnd.html#the-draggable-attribute"/>
+ <meta name="assert" content="True state of draggable attribute"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id=log></div>
+ <a href="#" style="display:none" id="target" draggable="true">Drag this</a>
+ <script type="text/javascript">
+ test(function() {assert_true(document.getElementById("target").draggable)}, "True state of draggable attribute");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_009.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_009.htm
new file mode 100644
index 00000000000..781a584763f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_009.htm
@@ -0,0 +1,66 @@
+<!doctype html>
+<html>
+ <head>
+ <title>HTML5 Drag and Drop: Fire dragleave event during the drag and drop processing</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/"/>
+ <link rel="help" href="http://dev.w3.org/html5/spec/dnd.html#drag-and-drop-processing-model"/>
+ <meta name="assert" content="Fire dragleave event during the drag and drop processing"/>
+ <script src="dragdrop_support.js" type="text/javascript"></script>
+ <script type="text/javascript">
+ var EVENT, TARGET;
+
+ function DragleaveEvent(evt)
+ {
+ if ((TARGET == evt.target) && (EVENT == evt.type))
+ {
+ LogTestResult("PASS");
+ }
+ else
+ {
+ LogTestResult("FAIL");
+ }
+ }
+
+ EVENT = "dragleave";
+
+ window.onload = function()
+ {
+ TARGET = document.getElementById("target");
+ AddEventListenersForElement(EVENT, DragleaveEvent, false, TARGET);
+ }
+ </script>
+ </head>
+ <body>
+ <pre>Description: Fire dragleave event during the drag and drop processing</pre>
+ <table id='testtable' border='1'>
+ <tr>
+ <td>Test Result</td>
+ <td>Test Assertion</td>
+ </tr>
+ <tr>
+ <td id='test_result'>Manual</td>
+ <td id='test_assertion'>Test passes if if the word "PASS" appears to the left after following the steps below.
+ <div id="manualsteps">
+ Steps:
+ <ol>
+ <li> Select the text inside the red box
+ <li> Drag it over the blue box and drop it on the green box
+ </ol>
+ </div>
+ </td>
+ </tr>
+ </table>
+ <p>
+ http://dev.w3.org/html5/spec/dnd.html#drag-and-drop-processing-model
+ </p>
+ <p>
+ If there is a change in the current target element, and if the previous target element was not null or a part of a non-DOM document, then fire a DND event named dragleave at the previous target element.
+ </p>
+ <div style="border:2px red solid; width:100px">SampleText</div>
+ <br />
+ <div id="target" style="border:2px blue solid; width:200px; height:50px"></div>
+ <br />
+ <input type="text" style="border:2px green solid; width:200px; height:50px"></input>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_010.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_010.htm
new file mode 100644
index 00000000000..08e0a071e72
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_010.htm
@@ -0,0 +1,64 @@
+<!doctype html>
+<html>
+ <head>
+ <title>HTML5 Drag and Drop: Fire dragover event during the drag and drop processing</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/"/>
+ <link rel="help" href="http://dev.w3.org/html5/spec/dnd.html#drag-and-drop-processing-model"/>
+ <meta name="assert" content="Fire dragover event during the drag and drop processing"/>
+ <script src="dragdrop_support.js" type="text/javascript"></script>
+ <script type="text/javascript">
+ var EVENT, TARGET;
+
+ function DragoverEvent(evt)
+ {
+ if ((TARGET == evt.target) && (EVENT == evt.type))
+ {
+ LogTestResult("PASS");
+ }
+ else
+ {
+ LogTestResult("FAIL");
+ }
+ }
+
+ EVENT = "dragover";
+
+ window.onload = function()
+ {
+ TARGET = document.getElementById("target");
+ AddEventListenersForElement(EVENT, DragoverEvent, false, TARGET);
+ }
+ </script>
+ </head>
+ <body>
+ <pre>Description: Fire dragover event during the drag and drop processing</pre>
+ <table id='testtable' border='1'>
+ <tr>
+ <td>Test Result</td>
+ <td>Test Assertion</td>
+ </tr>
+ <tr>
+ <td id='test_result'>Manual</td>
+ <td id='test_assertion'>Test passes if if the word "PASS" appears to the left after following the steps below.
+ <div id="manualsteps">
+ Steps:
+ <ol>
+ <li> Select the text inside the red box.
+ <li> Drag it, hover over the green box and then release the mouse
+ </ol>
+ </div>
+ </td>
+ </tr>
+ </table>
+ <p>
+ http://dev.w3.org/html5/spec/dnd.html#drag-and-drop-processing-model
+ </p>
+ <p>
+ If the current target element is a DOM element, then fire a DND event named dragover at this current target element
+ </p>
+ <div style="border:2px red solid; width:100px">SampleText</div>
+ <br /><br />
+ <div id="target" style="border:2px green solid; width:200px; height:100px"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_011.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_011.htm
new file mode 100644
index 00000000000..dcd7c9c9d6a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_011.htm
@@ -0,0 +1,62 @@
+<!doctype html>
+<html>
+ <head>
+ <title>HTML5 Drag and Drop: Fire dragstart event during the drag and drop processing</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/"/>
+ <link rel="help" href="http://dev.w3.org/html5/spec/dnd.html#drag-and-drop-processing-model"/>
+ <meta name="assert" content="Fire dragstart event during the drag and drop processing"/>
+ <script src="dragdrop_support.js" type="text/javascript"></script>
+ <script type="text/javascript">
+ var EVENT, TARGET;
+
+ function DragstartEvent(evt)
+ {
+ if ((TARGET == evt.target) && (EVENT == evt.type))
+ {
+ LogTestResult("PASS");
+ }
+ else
+ {
+ LogTestResult("FAIL");
+ }
+ }
+
+ EVENT = "dragstart";
+
+ window.onload = function()
+ {
+ TARGET = document.getElementById("target");
+ AddEventListenersForElement(EVENT, DragstartEvent, false, TARGET);
+ }
+ </script>
+ </head>
+ <body>
+ <pre>Description: Fire dragstart event during the drag and drop processing</pre>
+ <table id='testtable' border='1'>
+ <tr>
+ <td>Test Result</td>
+ <td>Test Assertion</td>
+ </tr>
+ <tr>
+ <td id='test_result'>Manual</td>
+ <td id='test_assertion'>Test passes if if the word "PASS" appears to the left after following the steps below.
+ <div id="manualsteps">
+ Steps:
+ <ol>
+ <li> Click and drag the red box
+ </ol>
+ </div>
+ </td>
+ </tr>
+ </table>
+ <p>
+ http://dev.w3.org/html5/spec/dnd.html#drag-and-drop-processing-model
+ </p>
+ <p>
+ If it is an element that is being dragged, then set the drag data store elements list to contain just the source node.
+ Fire a DND event named dragstart at the source node.
+ </p>
+ <div id="target" style="border:2px red solid; width:200px; height:50px" draggable="true"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_012.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_012.htm
new file mode 100644
index 00000000000..b1df40a7022
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_012.htm
@@ -0,0 +1,64 @@
+<!doctype html>
+<html>
+ <head>
+ <title>HTML5 Drag and Drop: Fire drop event during the drag and drop processing</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/"/>
+ <link rel="help" href="http://dev.w3.org/html5/spec/dnd.html#drag-and-drop-processing-model"/>
+ <meta name="assert" content="Fire drop event during the drag and drop processing"/>
+ <script src="dragdrop_support.js" type="text/javascript"></script>
+ <script type="text/javascript">
+ var EVENT, TARGET;
+
+ function DropEvent(evt)
+ {
+ if ((TARGET == evt.target) && (EVENT == evt.type))
+ {
+ LogTestResult("PASS");
+ }
+ else
+ {
+ LogTestResult("FAIL");
+ }
+ }
+
+ EVENT = "drop";
+
+ window.onload = function()
+ {
+ TARGET = document.getElementById("target");
+ AddEventListenersForElement(EVENT, DropEvent, false, TARGET);
+ }
+ </script>
+ </head>
+ <body>
+ <pre>Description: Fire drop event during the drag and drop processing</pre>
+ <table id='testtable' border='1'>
+ <tr>
+ <td>Test Result</td>
+ <td>Test Assertion</td>
+ </tr>
+ <tr>
+ <td id='test_result'>Manual</td>
+ <td id='test_assertion'>Test passes if if the word "PASS" appears to the left after following the steps below.
+ <div id="manualsteps">
+ Steps:
+ <ol>
+ <li> Select the text inside the red box
+ <li> Drag it and drop it on the green box
+ </ol>
+ </div>
+ </td>
+ </tr>
+ </table>
+ <p>
+ http://dev.w3.org/html5/spec/dnd.html#drag-and-drop-processing-model
+ </p>
+ <p>
+ If the drag operation was a success, if the current target element is a DOM element, fire a DND event named drop at it.
+ </p>
+ <div style="border:2px red solid; width:100px">SampleText</div>
+ <br /><br />
+ <input type="text" id="target" style="border:2px green solid; width:200px; height:50px"></input>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_013.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_013.htm
new file mode 100644
index 00000000000..6c2c88afcee
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_013.htm
@@ -0,0 +1,76 @@
+<!doctype html>
+<html>
+ <head>
+ <title>HTML5 Drag and Drop: Set a value to effectAllowed attribute</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/"/>
+ <link rel="help" href="http://dev.w3.org/html5/spec/dnd.html#datatransfer"/>
+ <meta name="assert" content="Set a value to effectAllowed attribute"/>
+ <script src="dragdrop_support.js" type="text/javascript"></script>
+ <script type="text/javascript">
+ var TARGETEVENT1, TARGETEVENT2, TARGET1, TARGET2;
+
+ function DragstartEvent(evt)
+ {
+ if ((TARGET1 == evt.target) && (TARGETEVENT1 == evt.type))
+ {
+ evt.dataTransfer.effectAllowed = "move";
+ }
+ }
+ function DragenterEvent(evt)
+ {
+ if ((TARGET2 == evt.target) && (TARGETEVENT2 == evt.type))
+ {
+ if("move" == evt.dataTransfer.effectAllowed)
+ {
+ LogTestResult("PASS");
+ }
+ else
+ {
+ LogTestResult("FAIL");
+ }
+ }
+ }
+
+ TARGETEVENT1 = "dragstart";
+ TARGETEVENT2 = "dragenter";
+
+ window.onload = function()
+ {
+ TARGET1 = document.getElementById("target1");
+ TARGET2 = document.getElementById("target2");
+ AddEventListenersForElement(TARGETEVENT1, DragstartEvent, false, TARGET1);
+ AddEventListenersForElement(TARGETEVENT2, DragenterEvent, false, TARGET2);
+ }
+ </script>
+ </head>
+ <body>
+ <pre>Description: Set a value to effectAllowed attribute</pre>
+ <table id='testtable' border='1'>
+ <tr>
+ <td>Test Result</td>
+ <td>Test Assertion</td>
+ </tr>
+ <tr>
+ <td id='test_result'>Manual</td>
+ <td id='test_assertion'>Test passes if if the word "PASS" appears to the left after following the steps below.
+ <div id="manualsteps">
+ Steps:
+ <ol>
+ <li> Drag the blue image and enter the green box
+ </ol>
+ </div>
+ </td>
+ </tr>
+ </table>
+ <p>
+ http://dev.w3.org/html5/spec/dnd.html#datatransfer
+ </p>
+ <p>
+ On setting, if the new value is one of "none", "copy", "copyLink", "copyMove", "link", "linkMove", "move", "all", or "uninitialized", then the attribute's current value must be set to the new value.
+ </p>
+ <img src="../images/blue.png" style="width:200px; height:100px" draggable="true" id="target1"/>
+ <br /><br />
+ <input type="text" id="target2" style="border:2px green solid; width:200px; height:50px"></input>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_014.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_014.htm
new file mode 100644
index 00000000000..3959cd2ee82
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_014.htm
@@ -0,0 +1,81 @@
+<!doctype html>
+<html>
+ <head>
+ <title>HTML5 Drag and Drop: files attribute returns a FileList</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/"/>
+ <link rel="help" href="http://dev.w3.org/html5/spec/dnd.html#datatransfer"/>
+ <meta name="assert" content="files attribute returns a FileList"/>
+ <script src="dragdrop_support.js" type="text/javascript"></script>
+ <script type="text/javascript">
+ var EVENT, TARGET;
+
+ function DropEvent(evt)
+ {
+ if ((TARGET == evt.target) && (EVENT == evt.type))
+ {
+ var files = evt.dataTransfer.files;
+ if(('[object FileList]' == files))
+ {
+ LogTestResult("PASS");
+ }
+ else
+ {
+ LogTestResult("FAIL");
+ }
+ }
+ else
+ {
+ LogTestResult("FAIL");
+ }
+ }
+
+ function DragenterEvent(evt)
+ {
+ evt.preventDefault();
+ }
+
+ function DragoverEvent(evt)
+ {
+ evt.preventDefault();
+ }
+
+ EVENT = "drop";
+
+ window.onload = function()
+ {
+ TARGET = document.getElementById("target");
+ AddEventListenersForElement(EVENT, DropEvent, false, TARGET);
+ AddEventListenersForElement("dragenter", DragenterEvent, false, TARGET);
+ AddEventListenersForElement("dragover", DragoverEvent, false, TARGET);
+ }
+ </script>
+ </head>
+ <body>
+ <pre>Description: files attribute returns a FileList</pre>
+ <table id='testtable' border='1'>
+ <tr>
+ <td>Test Result</td>
+ <td>Test Assertion</td>
+ </tr>
+ <tr>
+ <td id='test_result'>Manual</td>
+ <td id='test_assertion'>Test passes if if the word "PASS" appears to the left after following the steps below.
+ <div id="manualsteps">
+ Steps:
+ <ol>
+ <li> Drag a file and drop it in the green box
+ </ol>
+ </div>
+ </td>
+ </tr>
+ </table>
+ <p>
+ http://dev.w3.org/html5/spec/dnd.html#datatransfer
+ </p>
+ <p>
+ The files attribute must return a live FileList sequence consisting of File objects representing the files.
+ </p>
+ <textarea type="text" id="target" style="border:2px green solid; width:200px; height:50px"></textarea>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_015.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_015.htm
new file mode 100644
index 00000000000..1cd64d9453e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_015.htm
@@ -0,0 +1,78 @@
+<!doctype html>
+<html>
+ <head>
+ <title>HTML5 Drag and Drop: Add an item to the drag data store item list whose data is the string given by setData method's second argument</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/"/>
+ <link rel="help" href="http://dev.w3.org/html5/spec/dnd.html#datatransfer"/>
+ <meta name="assert" content="Add an item to the drag data store item list whose data is the string given by setData method's second argument"/>
+ <script src="dragdrop_support.js" type="text/javascript"></script>
+ <script type="text/javascript">
+ var TARGETEVENT1, TARGETEVENT2, TARGET1, TARGET2;
+
+ function DragstartEvent(evt)
+ {
+ if ((TARGET1 == evt.target) && (TARGETEVENT1 == evt.type))
+ {
+ evt.dataTransfer.setData("text", "SetText");
+ }
+ }
+ function DropEvent(evt)
+ {
+ if ((TARGET2 == evt.target) && (TARGETEVENT2 == evt.type))
+ {
+ if("SetText" == evt.dataTransfer.getData("text"))
+ {
+ LogTestResult("PASS");
+ }
+ else
+ {
+ LogTestResult("FAIL");
+ }
+ }
+ }
+
+ TARGETEVENT1 = "dragstart";
+ TARGETEVENT2 = "drop";
+
+ window.onload = function()
+ {
+ TARGET1 = document.getElementById("target1");
+ TARGET2 = document.getElementById("target2");
+ AddEventListenersForElement(TARGETEVENT1, DragstartEvent, false, TARGET1);
+ AddEventListenersForElement(TARGETEVENT2, DropEvent, false, TARGET2);
+ }
+ </script>
+ </head>
+ <body>
+ <pre>Description: Add an item to the drag data store item list whose data is the string given by setData method's second argument</pre>
+ <table id='testtable' border='1'>
+ <tr>
+ <td>Test Result</td>
+ <td>Test Assertion</td>
+ </tr>
+ <tr>
+ <td id='test_result'>Manual</td>
+ <td id='test_assertion'>Test passes if if the word "PASS" appears to the left after following the steps below.
+ <div id="manualsteps">
+ Steps:
+ <ol>
+ <li> Drag the blue image and drop it in the green box
+ </ol>
+ </div>
+ </td>
+ </tr>
+ </table>
+ <p>
+ http://dev.w3.org/html5/spec/dnd.html#datatransfer
+ </p>
+ <p>
+ If format equals "text", change it to "text/plain".
+ Remove the item in the drag data store item list whose kind is Plain Unicode string and whose type string is equal to format, if there is one.
+ Add an item to the drag data store item list whose kind is Plain Unicode string, whose type string is equal to format, and whose data is the string given by the method's second argument.
+ </p>
+ <img src="../images/blue.png" style="width:200px; height:100px" draggable="customValue2" id="target1"/>
+ <br /><br />
+ <input type="text" id="target2" style="border:2px green solid; width:200px; height:50px"></input>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_016.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_016.htm
new file mode 100644
index 00000000000..26b3317c318
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_016.htm
@@ -0,0 +1,72 @@
+<!doctype html>
+<html>
+ <head>
+ <title>HTML5 Drag and Drop: types attribute returns a DOMStringList</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/"/>
+ <link rel="help" href="http://dev.w3.org/html5/spec/dnd.html#datatransfer"/>
+ <meta name="assert" content="types attribute returns a DOMStringList"/>
+ <script src="dragdrop_support.js" type="text/javascript"></script>
+ <script type="text/javascript">
+ var EVENT, TARGET;
+
+ function DropEvent(evt)
+ {
+ if ((TARGET == evt.target) && (EVENT == evt.type))
+ {
+ var types = evt.dataTransfer.types;
+ if(('[object DOMStringList]' == types))
+ {
+ LogTestResult("PASS");
+ }
+ else
+ {
+ LogTestResult("FAIL");
+ }
+ }
+ else
+ {
+ LogTestResult("FAIL");
+ }
+ }
+
+ EVENT = "drop";
+
+ window.onload = function()
+ {
+ TARGET = document.getElementById("target");
+ AddEventListenersForElement(EVENT, DropEvent, false, TARGET);
+ }
+ </script>
+ </head>
+ <body>
+ <pre>Description: types attribute returns a DOMStringList</pre>
+ <table id='testtable' border='1'>
+ <tr>
+ <td>Test Result</td>
+ <td>Test Assertion</td>
+ </tr>
+ <tr>
+ <td id='test_result'>Manual</td>
+ <td id='test_assertion'>Test passes if if the word "PASS" appears to the left after following the steps below.
+ <div id="manualsteps">
+ Steps:
+ <ol>
+ <li> Select the text inside the red box
+ <li> Drag and drop it in the green box
+ </ol>
+ </div>
+ </td>
+ </tr>
+ </table>
+ <p>
+ http://dev.w3.org/html5/spec/dnd.html#datatransfer
+ </p>
+ <p>
+ The types attribute must return a live DOMStringList.
+ </p>
+ <div style="border:2px red solid; width:200px; height:50px">SampleText</div>
+ <br /><br />
+ <input type="text" id="target" style="border:2px green solid; width:200px; height:50px"></input>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_support.js b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_support.js
new file mode 100644
index 00000000000..f5a1d6417f3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/dragdrop/dragdrop_support.js
@@ -0,0 +1,9 @@
+function AddEventListenersForElement(evt, callback, capture, element)
+{
+ element.addEventListener(evt, callback, capture);
+}
+
+function LogTestResult(result)
+{
+ document.getElementById("test_result").firstChild.data = result;
+}
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/foreigncontent/foreign_content_002.html b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/foreigncontent/foreign_content_002.html
new file mode 100644
index 00000000000..47acacfe7f0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/foreigncontent/foreign_content_002.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html >
+<html>
+ <head>
+ <title>HTML 5 Foreign Content SVG in HTML </title>
+ <meta description="Test to verify SVG inside HTML I element parses correctly" />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <script type="text/javascript">
+
+ function RunTest()
+ {
+ try
+ {
+
+ if(document.getElementsByTagName("i")[0].childNodes[1].localName=="svg")
+ {
+ var svgNamespace = "http://www.w3.org/2000/svg";
+ var textElem = document.createElementNS(svgNamespace, "text");
+
+ var textContent = document.createTextNode("FillerText");
+ textElem.appendChild(textContent);
+
+ var container = document.getElementById("svg1");
+ container.appendChild(textElem);
+
+ }
+ }
+ catch(ex)
+ {
+ }
+ }
+ </script>
+ </head>
+
+ <body onLoad="RunTest()">
+
+ <div class="testdata">
+ <p id="instructions">Test passes if 'FillerText' is rendered as italic.</p>
+ </div>
+ <div>
+ <i>
+ <svg id="svg1" width="100px" height="100px">
+ </svg>
+ </i>
+ </div>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/foreigncontent/foreign_content_007.html b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/foreigncontent/foreign_content_007.html
new file mode 100644
index 00000000000..f1ba496bb09
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/foreigncontent/foreign_content_007.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<svg width="100px" height="100px" >
+ <rect width="100px" height="100px" fill="green" />
+</svg>
+
+<div>
+ <p> Test passes if a green rectangle is visible on the page above this line. </p>
+</div>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/foreigncontent/foreign_content_012.html b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/foreigncontent/foreign_content_012.html
new file mode 100644
index 00000000000..09e99e41ab2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/foreigncontent/foreign_content_012.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>HTML 5 Foreign Content SVG in HTML </title>
+ <meta description="Test to verify SVG elements are styled using SCRIPT and STYLE element" />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+
+ <style>
+ svg
+ {
+ display: block;
+ fill: black;
+ }
+ </style>
+ <script>
+ function ChangeColor()
+ {
+ document.getElementById("rect1").style.fill = "green";
+ }
+ </script>
+ </head>
+
+ <body onload="ChangeColor()">
+
+ <div class="testdata">
+ <p id="instructions">Test passes if a green square appears above a black square. </p>
+ </div>
+ <svg width="200px" height="200px">
+ <rect id="rect1" x="0" y="0" width="100px" height="100px" />
+ <rect id="rect2" x="0" y="150" width="100px" height="100px" />
+ </svg>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/foreigncontent/foreign_content_014.html b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/foreigncontent/foreign_content_014.html
new file mode 100644
index 00000000000..d92c14dfa9a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/foreigncontent/foreign_content_014.html
@@ -0,0 +1,98 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>HTML 5 Foreign Content SVG in HTML </title>
+ <meta description="Test to verify SVG elements inside SVG namespace are camelCased" />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+
+ <script type="text/javascript">
+
+ function RunTest()
+ {
+ try
+ {
+ var bResult = "FAIL";
+ var parentNode = document.getElementById("svg1");
+
+ for(var i=1;i<parentNode.childNodes.length;i=i+2)
+ {
+ var idName = parentNode.childNodes[i].id;
+ var tagName = parentNode.childNodes[i].localName;
+ if(idName!=tagName)
+ {
+ bResult = "FAIL";
+ break;
+ }
+ else
+ {
+ bResult = "PASS"
+ }
+ }
+ }
+ catch(ex)
+ {
+ bResult = "PASS";
+ }
+
+ document.getElementById("testresult").innerHTML = bResult;
+ }
+ </script>
+ </head>
+
+ <body onload="RunTest()">
+
+ <div class="testdata">
+ <p id="instructions"> Test passes if the word "PASS" appears below </p>
+ <p> Test Result : </p>
+ <p id="testresult"> RUNNING </div>
+ </div>
+ <svg id="svg1">
+
+ <altglyph id="altGlyph" />
+ <ALTGLYPHDEF id="altGlyphDef" />
+ <AltGlyphItem id="altGlyphItem" />
+ <animatecolor id="animateColor" />
+ <animatemotion id="animateMotion" />
+ <animatetransform id="animateTransform" />
+ <clippath id="clipPath" />
+ <feblend id="feBlend" />
+ <fecolormatrix id="feColorMatrix" />
+
+ <fecomponenttransfer id="feComponentTransfer" />
+ <fecomposite id="feComposite" />
+ <feconvolvematrix id="feConvolveMatrix" />
+ <fediffuselighting id="feDiffuseLighting" />
+ <fedisplacementmap id="feDisplacementMap" />
+ <fedistantlight id="feDistantLight" />
+ <feflood id="feFlood" />
+ <fefunca id="feFuncA" />
+ <fefuncb id="feFuncB" />
+
+ <fefuncg id="feFuncG" />
+ <fefuncr id="feFuncR" />
+ <fegaussianblur id="feGaussianBlur" />
+ <feimage id="feImage" />
+ <femerge id="feMerge" />
+ <femergenode id="feMergeNode" />
+ <femorphology id="feMorphology" />
+ <feoffset id="feOffset" />
+ <fepointlight id="fePointLight" />
+
+ <fespecularlighting id="feSpecularLighting" />
+ <fespotlight id="feSpotLight" />
+ <fetile id="feTile" />
+ <feturbulence id="feTurbulence" />
+ <foreignobject id="foreignObject" />
+ <glyphref id="glyphRef" />
+ <lineargradient id="linearGradient" />
+ <radialgradient id="radialGradient" />
+ <textpath id="textPath" />
+
+ </svg>
+
+
+
+ </body>
+
+</html>
+
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/foreigncontent/foreign_content_015.html b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/foreigncontent/foreign_content_015.html
new file mode 100644
index 00000000000..a4d27873a33
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/foreigncontent/foreign_content_015.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>HTML 5 Foreign Content SVG in HTML </title>
+ <meta description="Test to verify SVG Elements outside SVG namespace are camelCased" />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+
+ <script type="text/javascript">
+
+ function RunTest()
+ {
+ try
+ {
+
+ var parentNode = document.getElementById("div1");
+
+ for(var i=0;i<parentNode.childNodes.length;i++)
+ {
+ var idName = parentNode.childNodes[i].id;
+ var tagName = parentNode.childNodes[i].localName;
+ if(idName==tagName)
+ {
+ document.getElementById("testresult").innerHTML = "FAIL";
+ break;
+ }
+ else
+ {
+ document.getElementById("testresult").innerHTML = "PASS";
+ }
+ }
+ }
+ catch(ex)
+ {
+ document.getElementById("testresult").innerHTML = "FAIL";
+ }
+ }
+ </script>
+ </head>
+
+ <body onload="RunTest()">
+
+ <div id="div1">
+ <AlTglYph id="altGlyph" />
+ </div>
+ <p id="instructions"> Test passes if the word "PASS" appears below </p>
+ <p> Test Result : </p>
+ <div id="testresult"> RUNNING </div>
+
+
+ </body>
+
+</html>
+
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/history/404.html b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/history/404.html
new file mode 100644
index 00000000000..e28f5c575b4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/history/404.html
@@ -0,0 +1 @@
+Page Not Found \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/history/history_000.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/history/history_000.htm
new file mode 100644
index 00000000000..03a36bd5f41
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/history/history_000.htm
@@ -0,0 +1,329 @@
+<!doctype html>
+<html>
+ <head>
+ <meta content="text/html; charset=utf-8" http-equiv="content-type" />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://dev.w3.org/html5/spec/history.html" />
+ <title>HTML5 History Test Cases</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+<body>
+ <div id="log"></div>
+
+ <!-- Use this iframe to test url changes so that the base url does not change. Their document does not matter. -->
+ <iframe id="testframe1" style="display:none" src="./404.html"></iframe>
+ <iframe id="testframe2" style="display:none" src="./404.html"></iframe>
+
+ <script type="text/javascript">
+ var testCollection;
+ var testIndex = 0;
+ var testframe1 = document.getElementById("testframe1");
+ var testframe2 = document.getElementById("testframe2");
+
+ setup(function()
+ {
+ testCollection = [
+ function() {
+ test(function() {
+ assert_inherits(window, "onpopstate", "window inherits'onpopstate' event ");
+ }, "onpopstate in window");
+ },
+ function() {
+ test(function() {
+ assert_inherits(window.history, "pushState", "history inherits property 'pushState'");
+ assert_equals(window.history.pushState.constructor, Function, "pushState is a function");
+ }, "history.pushState is present");
+ },
+ function() {
+ test(function() {
+ assert_inherits(window.history, "replaceState", "history inherits property 'replaceState'");
+ assert_equals(window.history.replaceState.constructor, Function, "replaceState is a function");
+ }, "history.replaceState is present");
+ },
+ function() {
+ test(function() {
+ assert_inherits(window.history, "state", "history inherits property 'state'");
+ }, "history.state is present");
+ },
+ function() {
+ test(function() {
+ assert_equals(window.history.state, null, "history.state initialized to null");
+ }, "history.state is initialized to null");
+ },
+
+ function() {
+ test(function() {
+ var length = history.length;
+ history.pushState(null,null);
+ assert_equals(history.length, length+1, "history.length should be incremented by one");
+ }, "history.pushState increments history.length");
+ },
+
+ function() {
+ var t = async_test("history.pushState clears forward entries");
+ t.step(function() {
+ var length = history.length;
+ //push some extra entries into the session history
+ history.pushState(null,null);
+ history.pushState(null, null);
+ history.pushState(null, null);
+
+ //there should now be three extra
+ assert_equals(history.length, length+3, "Three additional travel entries add to history.length");
+
+ //travel back to the entry that the test started on
+ history.back();
+ history.back();
+ history.back();
+
+ //if the back navs are queued, queue verification task after them
+ queue(
+ t.step_func(function() {
+ //once the .back navigations have completed, push again and verify length is one more than starting value
+ history.pushState(null, null);
+ assert_equals(history.length, length+1, "History.length should now only be one more than original value");
+ t.done();
+ })
+ );
+ });
+ },
+
+ function() {
+ test(function() {
+ testframe1.contentWindow.history.pushState(null,null, "test-pushstate-url");
+ assert_equals(getPageName(testframe1.contentWindow.location.href), "test-pushstate-url", "iframe1 has the pushed url");
+ }, "history.pushState accepts a third parameter 'url' and uses it to alter location");
+ },
+ function() {
+ test(function() {
+ var oldurl = testframe1.contentWindow.location.href.toString();
+ var pagename = getPageName(oldurl);
+ //form a new absolute url (with protocol, host, etc) with "absolute-page" as the name of the page
+ var newurl = oldurl.replace(pagename, "absolute-page");
+
+ testframe1.contentWindow.history.pushState(null,null, newurl);
+ assert_equals(testframe1.contentWindow.location.href, newurl, "iframe1 has the pushed url correctly");
+ }, "history.pushState's url parameter can be an absolute url");
+ },
+
+ function() {
+ test(function() {
+ testframe1.contentWindow.history.pushState(null,null, "multiple-pushstate-url1");
+ testframe2.contentWindow.history.pushState(null,null, "multiple-pushstate-url2");
+
+ assert_equals(getPageName(testframe1.contentWindow.location.href), "multiple-pushstate-url1", "iframe1 has the pushed url");
+ assert_equals(getPageName(testframe2.contentWindow.location.href), "multiple-pushstate-url2", "iframe2 has the pushed url");
+ }, "history.pushState can modify location object in multiple frames");
+ },
+
+ function() {
+ test(function() {
+ //trigger a security error by replacing the host of the current url with a fake one that is cross-domain
+ var testurl = testframe1.contentWindow.location.href.toString().replace(testframe1.contentWindow.location.host, "fakelocation-push");
+ assert_throws("SECURITY_ERR", function() { history.pushState(null, null, testurl); }, "Security_Err 18 should be thrown");
+ }, "history.pushState throws DOMException with code SECURITY_ERR (18)");
+ },
+
+ function() {
+ test(function() {
+ //trigger a data clone error by passing invalid SCA data into the function
+ assert_throws("DATA_CLONE_ERR", function() { history.pushState(document.body, null); }, "pushState should throw an exception DATA_CLONE_ERR with code 25");
+ }, "history.pushState throws DATA_CLONE_ERR(25) for bad state parameter");
+ },
+
+ function() {
+ test(function() {
+ var length = history.length;
+ history.replaceState(null,null);
+ assert_equals(history.length, length, "history.length should not change");
+ }, "history.replaceState does not increment history.length");
+ },
+
+ function() {
+ var t = async_test("history.replaceState does not clear forward entries");
+ t.step(function() {
+ var length = history.length;
+ //push some extra entries into the session history
+ history.pushState(null,null);
+ history.pushState(null, null);
+ history.pushState(null, null);
+
+ //there should now be three extra
+ assert_equals(history.length, length+3, "Three additional travel entries add to history.length");
+
+ //travel back two entries to land in the middle
+ history.back();
+ history.back();
+
+ //if the back navs are queued, queue verification task after them
+ queue(
+ t.step_func(function() {
+ //once the .back navigations have fired, push again and verify length has not changed since the last check
+ history.replaceState(null, null);
+ assert_equals(history.length, length+3, "History.length should still be three more than original value");
+ t.done();
+ })
+ );
+ });
+ },
+
+ function() {
+ test(function() {
+ testframe1.contentWindow.history.replaceState(null,null, "test-replaceState-url");
+ assert_equals(getPageName(testframe1.contentWindow.location.href), "test-replaceState-url", "iframe1 has the pushed url");
+ }, "history.replaceState accepts a third parameter 'url' and uses it to alter location");
+ },
+ function() {
+ test(function() {
+ var oldurl = testframe1.contentWindow.location.href.toString();
+ var pagename = getPageName(oldurl);
+ //form a new absolute url (with protocol, host, etc) with "absolute-page" as the name of the page
+ var newurl = oldurl.replace(pagename, "absolute-page");
+
+ testframe1.contentWindow.history.replaceState(null,null, newurl);
+ assert_equals(testframe1.contentWindow.location.href, newurl, "iframe1 has the pushed url correctly");
+ }, "history.replaceState's url parameter can be an absolute url");
+ },
+
+ function() {
+ test(function() {
+ testframe1.contentWindow.history.replaceState(null,null, "multiple-replaceState-url1");
+ testframe2.contentWindow.history.replaceState(null,null, "multiple-replaceState-url2");
+
+ assert_equals(getPageName(testframe1.contentWindow.location.href), "multiple-replaceState-url1", "iframe1 has the pushed url");
+ assert_equals(getPageName(testframe2.contentWindow.location.href), "multiple-replaceState-url2", "iframe2 has the pushed url");
+ }, "history.replaceState can modify location object in multiple frames");
+ },
+
+ function() {
+ test(function() {
+ //trigger a security error by replacing the host of the current url with a fake one that is cross-domain
+ var testurl = testframe1.contentWindow.location.href.toString().replace(testframe1.contentWindow.location.host, "fakelocation-replace");
+ assert_throws("SECURITY_ERR", function() { history.replaceState(null, null, testurl); }, "Security_Err 18 should be thrown");
+ }, "history.replaceState throws DOMException with code SECURITY_ERR (18)");
+ },
+
+ function() {
+ test(function() {
+ //trigger a data clone error by passing invalid SCA data into the function
+ assert_throws("DATA_CLONE_ERR", function() {history.replaceState(document.body, null);}, "replaceState should throw an exception DATA_CLONE_ERR with code 25");
+ }, "history.replaceState throws DATA_CLONE_ERR(25) for bad state parameter");
+ },
+
+ function() {
+ var t = async_test("PopStateEvent fires on Back navigation");
+ t.step(function() {
+ history.pushState(null, null);
+ history.pushState(null, null);
+ //prepare to end the test as soon as popstate fires
+ onpopstate = function(e) {
+ t.done();
+ }
+ //go back to fire the popstate event
+ history.back();
+ });
+ },
+
+ function() {
+ var t = async_test("PopStateEvent fires on Forward navigation");
+ t.step( function() {
+ onpopstate = null;
+ history.pushState(null, null);
+ history.pushState(null, null);
+ history.back();
+ //if the back navigation is queued, set up the rest of the test after it is done
+ queue(
+ t.step_func(function() {
+ //prepare to end the test as soon as popstate fires
+ onpopstate = function(e) {
+ t.done();
+ }
+ //go forward to fire the popstate event
+ history.forward();
+ })
+ );
+ });
+ },
+
+ function() {
+ var t = async_test("PopStateEvent receives state data on Back navigation");
+ t.step(function() {
+ history.pushState("popstate-data", null);
+ history.pushState(null, null);
+ //prepare the popstate event to validate the data
+ onpopstate = t.step_func(function(e) {
+ assert_equals(e.state, "popstate-data", "State data is passed to the event correctly");
+ t.done();
+ });
+ //go back to fire the popstate event
+ history.back();
+ });
+ },
+
+ function() {
+ test(function() {
+ history.pushState("pushstate-data", null);
+ //history.state should be set immediately
+ assert_equals(history.state, "pushstate-data", "State data is set correctly");
+ }, "history.state is set by history.pushState");
+ },
+
+ function() {
+ test(function() {
+ history.replaceState("replacestate-data", null);
+ //history.state should be set immediately
+ assert_equals(history.state, "replacestate-data", "State data is set correctly");
+ }, "history.state is set by history.replaceState");
+ },
+
+ function() {
+ var t = async_test("history.state changes on navigation");
+ t.step(function() {
+ history.pushState("state-back1", null);
+ history.pushState("state-back2", null);
+ //precondition
+ assert_equals(history.state, "state-back2", "Verify that history.state is set to a second value");
+
+ //set up the popstate event to verify that history.state was changed
+ onpopstate = t.step_func(function(e) {
+ assert_equals(e.state, "state-back1", "Verify that history.state reverted to the first value");
+ t.done();
+ });
+ history.back();
+ });
+ },
+ ];
+ }, {explicit_done:true, timeout:8000});
+
+ //used to get the name of a page within a path
+ // to check correctness of url parameter
+ function getPageName(path) {
+ var path = path || location.pathname;
+ var segments = path.split('/');
+ return segments[segments.length-1];
+ }
+
+ //Callback for result_callback
+ //queues the next test in the array testCollection
+ //serves to make test execution sequential despite asynchronous behaviors
+ function testFinished(test) {
+ if(testIndex < testCollection.length - 1) {
+ //queue the function so that stack remains shallow
+ queue(testCollection[++testIndex]);
+ } else {
+ //when the last test has run, explicitly end test suite
+ done();
+ }
+ }
+ function queue(func) {
+ //50 allows adequate time for .back and .forward navigations to queue first
+ setTimeout(func, 50);
+ }
+
+ add_result_callback(testFinished);
+ //start the first test manually
+ queue(testCollection[testIndex]);
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/images/blue-area.png b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/images/blue-area.png
new file mode 100644
index 00000000000..570ae0f2bf7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/images/blue-area.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/images/blue-border.png b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/images/blue-border.png
new file mode 100644
index 00000000000..8f8e41c3d00
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/images/blue-border.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/images/blue.png b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/images/blue.png
new file mode 100644
index 00000000000..4498dd258a2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/images/blue.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/images/fail.gif b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/images/fail.gif
new file mode 100644
index 00000000000..c4addcf0090
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/images/fail.gif
Binary files differ
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/images/movie_300_frame_0.png b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/images/movie_300_frame_0.png
new file mode 100644
index 00000000000..b7128250938
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/images/movie_300_frame_0.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/images/poster.png b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/images/poster.png
new file mode 100644
index 00000000000..8873ed67873
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/images/poster.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/images/poster_blue.png b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/images/poster_blue.png
new file mode 100644
index 00000000000..69d5a39dc48
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/images/poster_blue.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/images/poster_green.png b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/images/poster_green.png
new file mode 100644
index 00000000000..cac16ede7c0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/images/poster_green.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/images/poster_red.png b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/images/poster_red.png
new file mode 100644
index 00000000000..0fb1f252c22
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/images/poster_red.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/images/rect.svg b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/images/rect.svg
new file mode 100644
index 00000000000..bb0cf97d90e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/images/rect.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="svg-root" width="100" height="50">
+ <rect width="100" height="50" fill="black" />
+</svg>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_001.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_001.htm
new file mode 100644
index 00000000000..24d16cfccea
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_001.htm
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Page with script</title>
+</head>
+<body>
+ <script type="text/javascript">
+ parent.window.postMessage("script ran", "*");
+ </script>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_002.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_002.htm
new file mode 100644
index 00000000000..59b3d16123d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_002.htm
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>HTML5 video with autoplay attribute.</title>
+ <script type="text/javascript" src="/common/media.js"></script>
+</head>
+<body>
+ <script type="text/javascript">
+
+ function do_play(event)
+ {
+ parent.window.postMessage("play event fired", "*");
+ }
+
+ document.write(
+ "<video id='video0' src='" + getVideoURI("/media/green-at-15") + "'" +
+ " autoplay onplay='do_play(event);'>"
+ );
+ </script>
+ Your browser does not support HTML5 video.
+ </video>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_003.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_003.htm
new file mode 100644
index 00000000000..621ece79af6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_003.htm
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>autofocus on form control</title>
+</head>
+<body>
+ <div>Below form control has autofocus attribute set.</div><br />
+ <form action="">
+ <span>Textbox: </span><input autofocus="autofocus" type="text" name="movie" />
+ </form>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_004.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_004.htm
new file mode 100644
index 00000000000..02960d0786e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_004.htm
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>object tag</title>
+</head>
+<body>
+ <object width="400" height="600" data="sandbox.pdf">
+ </object>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_006.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_006.htm
new file mode 100644
index 00000000000..42542ae1472
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_006.htm
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Form submission</title>
+</head>
+<body>
+ <form id="form1" action="standalone-pass.htm">
+ <span>Name: </span><input type="text" name="name" value="browser" /><br />
+ <input id="submitButton" type="submit" value="Submit Form" />
+ </form>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_007.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_007.htm
new file mode 100644
index 00000000000..fc01557c75c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_007.htm
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Form submission</title>
+</head>
+<body>
+ <form id="form1" action="standalone-fail.htm">
+ <span>Name: </span><input type="text" name="name" value="browser" /><br />
+ <input id="submitButton" type="submit" value="Submit Form" />
+ </form>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_008.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_008.htm
new file mode 100644
index 00000000000..115b9729383
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_008.htm
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Page with hyperlink and target set to self</title>
+</head>
+<body>
+ <a id="hyperlink" href="standalone-pass.htm" target="_self">Click here to perform self navigation</a>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_009.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_009.htm
new file mode 100644
index 00000000000..f232dcb7c9a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_009.htm
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Page with showModalDialog() API</title>
+</head>
+<body>
+ <button type="button" onclick="javascript:showModalDialog('standalone-fail.htm')">Click here to call showModalDialog() API</button>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_010.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_010.htm
new file mode 100644
index 00000000000..d4e81bb966d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_010.htm
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Page with window.open()</title>
+</head>
+<body>
+ <button type="button" onclick="javascript:window.open('standalone-fail.htm')">Click here to call window.open() API</button>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_012.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_012.htm
new file mode 100644
index 00000000000..b1e8f92fb4e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_012.htm
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Page with access to document.cookie</title>
+</head>
+<body>
+ <script type="text/javascript">
+ cookie = document.cookie;
+ document.cookie = "name=browser";
+ parent.window.postMessage("cookies are R/W", "*");
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_020.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_020.htm
new file mode 100644
index 00000000000..3304ea84bb5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_020.htm
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Page with iframes</title>
+</head>
+<body>
+ <table cellpadding="5" cellspacing="10">
+ <tr>
+ <td>
+ <span>child iframe with sandbox="allow-scripts" attribute</span><br />
+ <iframe id="Iframe1" src="iframe_sandbox_020a.htm" sandbox="allow-scripts" style="height: 50px; width: 250px;"></iframe>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <span>child iframe with sandbox="" attribute</span><br />
+ <iframe id="Iframe2" src="iframe_sandbox_020a.htm" sandbox="" style="height: 50px; width: 250px;"></iframe>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <span>child iframe without sandbox attribute</span><br />
+ <iframe id="Iframe3" src="iframe_sandbox_020a.htm" style="height: 50px; width: 250px;"></iframe>
+ </td>
+ </tr>
+ </table>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_020a.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_020a.htm
new file mode 100644
index 00000000000..a419c9413f8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_020a.htm
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Page with script</title>
+</head>
+<body>
+ <div>Script Execution: <span id="scriptExecute" style="Color: Green">Blocked</span></div>
+ <script type="text/javascript">
+ document.getElementById("scriptExecute").innerHTML = "Not Blocked";
+ document.getElementById("scriptExecute").style.color = "Red";
+ </script>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_021.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_021.htm
new file mode 100644
index 00000000000..e3041ccef0a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_021.htm
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Page with iframes</title>
+</head>
+<body>
+ <table cellpadding="5" cellspacing="10">
+ <tr>
+ <td>
+ <span>child iframe with sandbox="allow-scripts" attribute</span><br />
+ <iframe id="Iframe1" src="iframe_sandbox_021a.htm" sandbox="allow-scripts" style="height: 50px; width: 250px;"></iframe>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <span>child iframe with sandbox="" attribute</span><br />
+ <iframe id="Iframe2" src="iframe_sandbox_020a.htm" sandbox="" style="height: 50px; width: 250px;"></iframe>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <span>child iframe without sandbox attribute</span><br />
+ <iframe id="Iframe3" src="iframe_sandbox_021a.htm" style="height: 50px; width: 250px;"></iframe>
+ </td>
+ </tr>
+ </table>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_021a.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_021a.htm
new file mode 100644
index 00000000000..4e22a363cab
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_021a.htm
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Page with script</title>
+</head>
+<body>
+ <div>Script Execution: <span id="scriptExecute" style="Color: Red">Blocked</span></div>
+ <script type="text/javascript">
+ document.getElementById("scriptExecute").innerHTML = "Allowed";
+ document.getElementById("scriptExecute").style.color = "Green";
+ </script>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_022.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_022.htm
new file mode 100644
index 00000000000..11382d1d7c6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_022.htm
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>target=_top</title>
+</head>
+<body>
+ <div>hyperlink with target=_top</div>
+ <br />
+ <a href="standalone-pass.htm" target="_top">Open the link in top window</a>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_023.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_023.htm
new file mode 100644
index 00000000000..a65db539bb4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_023.htm
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<head><title>Access parent dom</title>
+</head>
+<body>
+ <script type="text/javascript">
+ if (window.parent.document)
+ {
+ parent.window.postMessage("window.parent.document", "*");
+ }else{
+ parent.window.postMessage("!window.parent.document", "*");
+ }
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_024.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_024.htm
new file mode 100644
index 00000000000..1b0996e5899
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_024.htm
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+<head><title>Page with access to document.cookie</title>
+</head>
+<body>
+ <div>Cookie Read: <span id="readCookie"></span></div>
+ <script type="text/javascript">
+ cookie = document.cookie;
+ document.cookie = "name=browser";
+ parent.window.postMessage("cookies are R/W", "*");
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_026.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_026.htm
new file mode 100644
index 00000000000..5f1a973e1f7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_026.htm
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head><title>Page with access to localStorage and sessionStorage</title>
+</head>
+<body>
+ <script type="text/javascript">
+ if (window.localStorage && window.sessionStorage) {
+ parent.window.postMessage("access to window.localStorage and window.sessionStorage", "*");
+ }
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_027.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_027.htm
new file mode 100644
index 00000000000..366bff6f940
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_027.htm
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<head><title>XMLHttpRequest</title>
+</head>
+<body>
+ <script type="text/javascript">
+ xhrRequest = new XMLHttpRequest();
+
+ xhrRequest.onreadystatechange = function () {
+ if (xhrRequest.readyState == 4 && xhrRequest.status == 200) {
+ //xhr successful
+ parent.window.postMessage("access to window.XMLHttpRequest", "*");
+ }
+ }
+
+ xhrRequest.open("GET", "standalone-pass.htm", true);
+ xhrRequest.send();
+
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_028.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_028.htm
new file mode 100644
index 00000000000..d7ca7614415
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_028.htm
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head><title>Access parent dom</title>
+</head>
+<body>
+ <script type="text/javascript">
+ try
+ {
+ if (window.parent.document)
+ {
+ parent.window.postMessage("window.parent.document", "*");
+ }
+ }
+ catch(e)
+ {
+ parent.window.postMessage("!window.parent.document", "*");
+ }
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_029.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_029.htm
new file mode 100644
index 00000000000..5d5c720bd86
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_029.htm
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+<head><title>Page with access to document.cookie</title>
+</head>
+<body>
+ <div>Cookie Read: <span id="readCookie"></span></div>
+ <script type="text/javascript">
+ try
+ {
+ cookie = document.cookie;
+ document.cookie = "name=browser";
+ parent.window.postMessage("cookies are R/W", "*");
+ }catch(e)
+ {
+ parent.window.postMessage("cookies are not R/W", "*");
+ }
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_031.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_031.htm
new file mode 100644
index 00000000000..7ec7d7a4e81
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_031.htm
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+<head><title>Page with access to localStorage and sessionStorage</title>
+</head>
+<body>
+ <script type="text/javascript">
+ try
+ {
+ if (window.localStorage && window.sessionStorage) {
+ parent.window.postMessage("access to window.localStorage and window.sessionStorage", "*");
+ }
+ }
+ catch(e)
+ {
+ parent.window.postMessage("no access to window.localStorage and window.sessionStorage", "*");
+ }
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_032.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_032.htm
new file mode 100644
index 00000000000..abc0370c2eb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_032.htm
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+<head><title>XMLHttpRequest</title>
+</head>
+<body>
+ <script type="text/javascript">
+
+ try
+ {
+ xhrRequest = new XMLHttpRequest();
+
+ xhrRequest.onreadystatechange = function () {
+ if (xhrRequest.readyState == 4 && xhrRequest.status == 200) {
+ //xhr successful
+ parent.window.postMessage("access to window.XMLHttpRequest", "*");
+ }
+ }
+
+ xhrRequest.open("GET", "standalone-pass.htm", true);
+ xhrRequest.send();
+
+ }catch(e){}
+
+ parent.window.postMessage("no access to window.XMLHttpRequest", "*");
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox.pdf b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox.pdf
new file mode 100644
index 00000000000..0e16bc8d93d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox.pdf
Binary files differ
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_001.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_001.htm
new file mode 100644
index 00000000000..53e2172bc37
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_001.htm
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>HTML5 Sandbox: Allow script execution inside iframe with sandbox attribute when sandbox="allow-scripts".</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://dev.w3.org/html5/spec/Overview.html#sandboxed-scripts-browsing-context-flag" />
+ <meta name="assert" content="Allow script execution inside iframe with sandbox attribute when sandbox='allow-scripts'." />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <script type="text/javascript">
+
+
+ var t = async_test("Allow script execution inside iframe with sandbox attribute when sandbox='allow-scripts'.");
+
+ function callback(event)
+ {
+ t.step(function(){
+ assert_true('sandbox' in document.createElement('iframe'));
+ assert_equals(event.data, "script ran");
+ });
+ t.done();
+ }
+
+ var timer = setTimeout(callback, 8000);
+ window.addEventListener("message", callback, false);
+ </script>
+ <iframe src="iframe_sandbox_001.htm" sandbox="allow-scripts" style="display: none"></iframe>
+ <div id=log></div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_002.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_002.htm
new file mode 100644
index 00000000000..87049d0c1c0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_002.htm
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>HTML5 Sandbox: Allow autoplay for HTML5 Video inside iframe with sandbox attribute if sandbox='allow-scripts'.</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://dev.w3.org/html5/spec/Overview.html#sandboxed-automatic-features-browsing-context-flag" />
+ <meta name="assert" content="Allow autoplay for HTML5 Video inside iframe with sandbox attribute if sandbox='allow-scripts'." />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <script type="text/javascript">
+
+
+ var t = async_test("Allow autoplay for HTML5 Video inside iframe with sandbox attribute if sandbox='allow-scripts'.");
+
+ function callback(event)
+ {
+ t.step(function(){
+ assert_true('sandbox' in document.createElement('iframe'));
+ assert_equals(event.data, "play event fired");
+ });
+ t.done();
+ }
+
+ var timer = setTimeout(callback, 8000);
+ window.addEventListener("message", callback, false);
+ </script>
+ <iframe src="iframe_sandbox_002.htm" sandbox="allow-scripts" style="display: none"></iframe>
+ <div id=log></div>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_003.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_003.htm
new file mode 100644
index 00000000000..21078322b96
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_003.htm
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>HTML5 Sandbox: Block autofocus on form control inside iframe with sandbox attribute.</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://dev.w3.org/html5/spec/Overview.html#sandboxed-automatic-features-browsing-context-flag" />
+ <meta name="assert" content="Block autofocus on form control inside iframe with sandbox attribute." />
+ <script src="sandbox_helper.js" type="text/javascript"></script>
+</head>
+<body>
+ <pre>Description: Block autofocus on form controls inside iframe with sandbox attribute.</pre>
+ <table id='testtable' border='1'>
+ <tr>
+ <td>Test Result</td>
+ <td>Test Assertion</td>
+ </tr>
+ <tr>
+ <td id='test_0_result'>Manual</td>
+ <td id='test_0_assertion'>Test passes if caret (text cursor) is not on the textbox in the below iframe.</td>
+ </tr>
+ </table>
+ <br />
+ <div id="testframe">
+ <pre>iframe with sandbox</pre>
+ <iframe src="iframe_sandbox_003.htm" sandbox style="height: 100px; width: 400px;"></iframe>
+ </div>
+ <script type="text/javascript">
+ DisableTestForNonSupportingBrowsers();
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_004.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_004.htm
new file mode 100644
index 00000000000..21b063aedff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_004.htm
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>HTML5 Sandbox: Block plugins inside iframe with sandbox attribute.</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://dev.w3.org/html5/spec/Overview.html#sandboxed-plugins-browsing-context-flag" />
+ <meta name="assert" content="Block plugins inside iframe with sandbox attribute." />
+ <script src="sandbox_helper.js" type="text/javascript"></script>
+</head>
+<body>
+ <pre>Description: Block plugins inside iframe with sandbox attribute.</pre>
+ <table id='testtable' border='1'>
+ <tr>
+ <td>Test Result</td>
+ <td>Test Assertion</td>
+ </tr>
+ <tr>
+ <td id='test_0_result'>Manual</td>
+ <td id='test_0_assertion'>Test passes if you DO NOT see the 'Sample PDF For Testing' pdf below or 'FAIL'.<br>
+ Test requires that a pdf plugin has been installed!</td>
+ </tr>
+ </table>
+ <br />
+ <div id="testframe">
+ <pre>iframe with sandbox</pre>
+ <iframe sandbox src="iframe_sandbox_004.htm" height="400" width ="600"></iframe>
+ </div>
+ <script type="text/javascript">
+ DisableTestForNonSupportingBrowsers();
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_005.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_005.htm
new file mode 100644
index 00000000000..cc5f815c9d3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_005.htm
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>HTML5 Sandbox: Block script execution inside iframe with sandbox attribute.</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://dev.w3.org/html5/spec/Overview.html#sandboxed-scripts-browsing-context-flag" />
+ <meta name="assert" content="Block script execution inside iframe with sandbox attribute." />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <script type="text/javascript">
+
+
+ var t = async_test("Block script execution inside iframe with sandbox attribute.");
+
+ function callback(event)
+ {
+ t.step(function(){
+ assert_true('sandbox' in document.createElement('iframe'));
+ assert_true(!event);
+ });
+ t.done();
+ }
+
+ var timer = setTimeout(callback, 4000);
+ window.addEventListener("message", callback, false);
+ </script>
+ <iframe src="iframe_sandbox_001.htm" sandbox style="display: none"></iframe>
+ <div id=log></div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_006.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_006.htm
new file mode 100644
index 00000000000..487e8d4cfb8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_006.htm
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>HTML5 Sandbox: Allow form submission inside sandbox iframe when sandbox='allow-forms'</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://dev.w3.org/html5/spec/Overview.html#sandboxed-forms-browsing-context-flag" />
+ <meta name="assert" content="Allow form submission inside sandbox iframe when sandbox='allow-forms'." />
+ <script src="sandbox_helper.js" type="text/javascript"></script>
+</head>
+<body>
+ <pre>Description: Allow form submission inside iframe with sandbox attribute if sandbox='allow-forms'.</pre>
+ <table id='testtable' border='1'>
+ <tr>
+ <td>Test Result</td>
+ <td>Test Assertion</td>
+ </tr>
+ <tr>
+ <td id='test_0_result'>Manual</td>
+ <td id='test_0_assertion'>
+ <div>Steps:</div>
+ <div>1. Click button "Submit Form".</div>
+ <br />
+ <div>Test passes if there is no red on the page and if the word "PASS" appears in the below iframe after following the above steps.</div>
+ </td>
+ </tr>
+ </table>
+ <br />
+ <div id="testframe">
+ <pre>iframe with sandbox="allow-forms"</pre>
+ <iframe src="iframe_sandbox_006.htm" sandbox="allow-forms" style="height: 100px; width: 300px;"></iframe>
+ </div>
+ <script type="text/javascript">
+ DisableTestForNonSupportingBrowsers();
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_007.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_007.htm
new file mode 100644
index 00000000000..5caa12a07a1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_007.htm
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>HTML5 Sandbox: Block form submission inside sandbox iframe</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://dev.w3.org/html5/spec/Overview.html#sandboxed-forms-browsing-context-flag" />
+ <meta name="assert" content="Block form submission inside sandbox iframe." />
+ <script src="sandbox_helper.js" type="text/javascript"></script>
+</head>
+<body>
+ <pre>Description: Block form submission inside iframe with sandbox attribute.</pre>
+ <table id='testtable' border='1'>
+ <tr>
+ <td>Test Result</td>
+ <td>Test Assertion</td>
+ </tr>
+ <tr>
+ <td id='test_0_result'>Manual</td>
+ <td id='test_0_assertion'>
+ <div>Steps:</div>
+ <div>1. Click button "Submit Form".</div>
+ <br />
+ <div>Test passes if there is no red on the page and there is no navigation in the below iframe after following the above steps.</div>
+ </td>
+ </tr>
+ </table>
+ <br />
+ <div id="testframe">
+ <pre>iframe with sandbox="allow-scripts allow-same-origin allow-top-navigation"</pre>
+ <iframe src="iframe_sandbox_007.htm" sandbox="allow-scripts allow-same-origin allow-top-navigation" style="height: 100px; width: 300px;"></iframe>
+ </div>
+ <script type="text/javascript">
+ DisableTestForNonSupportingBrowsers();
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_008.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_008.htm
new file mode 100644
index 00000000000..dde12ef1d33
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_008.htm
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>HTML5 Sandbox: Allow sandboxed iframe content to navigate the sandboxed browsing context itself.</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://dev.w3.org/html5/spec/Overview.html#sandboxed-navigation-browsing-context-flag" />
+ <meta name="assert" content="Allow sandboxed iframe content to navigate the sandboxed browsing context itself." />
+ <script src="sandbox_helper.js" type="text/javascript"></script>
+</head>
+<body>
+ <pre>Description: Allow sandboxed iframe content to navigate the sandboxed browsing context itself.</pre>
+ <table id='testtable' border='1'>
+ <tr>
+ <td>Test Result</td>
+ <td>Test Assertion</td>
+ </tr>
+ <tr>
+ <td id='test_0_result'>Manual</td>
+ <td id='test_0_assertion'>
+ <div>Steps:</div>
+ <div>1. Click link "Click here to perform self navigation".</div>
+ <br />
+ <div>Test passes if there is no red on the page and the word "PASS" appears in the below iframe after following the above steps.</div>
+ </td>
+ </tr>
+ </table>
+ <br />
+ <div id="testframe">
+ <pre>iframe with sandbox=""</pre>
+ <iframe id="iframe1" name="iframe1" src="iframe_sandbox_008.htm" sandbox="" style="height: 100px; width: 350px;"></iframe>
+ </div>
+ <script type="text/javascript">
+ DisableTestForNonSupportingBrowsers();
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_009.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_009.htm
new file mode 100644
index 00000000000..5cb0d90309f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_009.htm
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>HTML5 Sandbox: Block popup created via showModalDialog() inside iframe with sandbox attribute.</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://dev.w3.org/html5/spec/Overview.html#attr-iframe-sandbox" />
+ <meta name="assert" content="Block popup created via showModalDialog() inside iframe with sandbox attribute." />
+ <script src="sandbox_helper.js" type="text/javascript"></script>
+</head>
+<body>
+ <pre>Description: Block popup created via showModalDialog() inside iframe with sandbox attribute.</pre>
+ <table id='testtable' border='1'>
+ <tr>
+ <td>Test Result</td>
+ <td>Test Assertion</td>
+ </tr>
+ <tr>
+ <td id='test_0_result'>Manual</td>
+ <td id='test_0_assertion'>
+ <div>Steps:</div>
+ <div>1. Click button "Click here to call showModalDialog() API".</div>
+ <br />
+ <div>Test passes if there is no red on the page and no new window opens. The user agent may offer the user the option of allowing a new window to open.</div>
+ </td>
+ </tr>
+ </table>
+ <br />
+ <div id="testframe">
+ <pre>iframe with sandbox="allow-scripts allow-same-origin allow-forms allow-top-navigation"</pre>
+ <iframe src="iframe_sandbox_009.htm" sandbox="allow-scripts allow-same-origin allow-forms allow-top-navigation" style="height: 100px; width: 450px;"></iframe>
+ </div>
+ <script type="text/javascript">
+ DisableTestForNonSupportingBrowsers();
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_010.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_010.htm
new file mode 100644
index 00000000000..4341066e1c1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_010.htm
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>HTML5 Sandbox: Block window.open() API inside iframe with sandbox attribute.</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://dev.w3.org/html5/spec/Overview.html#sandboxed-navigation-browsing-context-flag" />
+ <meta name="assert" content="Block window.open() API inside iframe with sandbox attribute." />
+ <script src="sandbox_helper.js" type="text/javascript"></script>
+</head>
+<body>
+ <pre>Description: Block window.open() API inside iframe with sandbox attribute.</pre>
+ <table id='testtable' border='1'>
+ <tr>
+ <td>Test Result</td>
+ <td>Test Assertion</td>
+ </tr>
+ <tr>
+ <td id='test_0_result'>Manual</td>
+ <td id='test_0_assertion'>
+ <div>Steps:</div>
+ <div>1. Click button "Click here to call window.open() API".</div>
+ <br />
+ <div>Test passes if there is no red on the page and no new window opens. The user agent may offer the user the option of allowing a new window to open.</div>
+ </td>
+ </tr>
+ </table>
+ <br />
+ <div id="testframe">
+ <pre>iframe with sandbox="allow-scripts allow-same-origin allow-forms allow-top-navigation"</pre>
+ <iframe src="iframe_sandbox_010.htm" sandbox="allow-scripts allow-same-origin allow-forms allow-top-navigation" style="height: 100px; width: 450px;"></iframe>
+ </div>
+ <script type="text/javascript">
+ DisableTestForNonSupportingBrowsers();
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_011.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_011.htm
new file mode 100644
index 00000000000..0427ec0783e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_011.htm
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>HTML5 Sandbox: iframe sandbox attribute value support DOMSettableTokenList interface.</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://dev.w3.org/html5/spec/Overview.html#the-iframe-element" />
+ <meta name="assert" content="iframe sandbox attribute value support DOMSettableTokenList interface." />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <div id=log></div>
+ <iframe id="iframe1" src="about:blank" sandbox="allow-scripts allow-same-origin allow-forms" style="display : none"></iframe>
+ <script type="text/javascript">
+
+ test(function() {
+ var iframeEle = document.getElementById("iframe1");
+ assert_equals(iframeEle.sandbox.length, 3)
+ }, "DOMSettableTokenList length")
+
+ test(function() {
+ var iframeEle = document.getElementById("iframe1");
+ assert_equals(iframeEle.sandbox.item(1), "allow-same-origin")
+ }, "DOMSettableTokenList item(index)")
+
+ test(function() {
+ var iframeEle = document.getElementById("iframe1");
+ assert_true(iframeEle.sandbox.contains("allow-forms"))
+ }, "DOMSettableTokenList contains(DomString)")
+
+ test(function() {
+ var iframeEle = document.getElementById("iframe1");
+ iframeEle.sandbox.add("ALLOW-SANDBOX");
+ assert_true(iframeEle.sandbox.contains("ALLOW-SANDBOX"))
+ }, "DOMSettableTokenList add(DomString)")
+
+ test(function() {
+ var iframeEle = document.getElementById("iframe1");
+ iframeEle.sandbox.remove("ALLOW-SANDBOX");
+ assert_false(iframeEle.sandbox.contains("ALLOW-SANDBOX"))
+ }, "DOMSettableTokenList remove(DomString)")
+
+ test(function() {
+ var iframeEle = document.getElementById("iframe1");
+ iframeEle.sandbox.remove("ALLOW-SANDBOX");
+ assert_true(
+ iframeEle.sandbox.toggle("allow-top-navigation") && iframeEle.sandbox.contains("allow-top-navigation") &&
+ !iframeEle.sandbox.toggle("allow-top-navigation") && !iframeEle.sandbox.contains("allow-top-navigation")
+ )
+ }, "DOMSettableTokenList toggle(DomString) - Returns true if token is now present (it was added); returns false if it is not (it was removed).")
+
+ test(function() {
+ var iframeEle = document.getElementById("iframe1");
+ assert_equals(iframeEle.sandbox.value, iframeEle.sandbox.toString())
+ }, "DOMSettableTokenList sandbox.toString()")
+
+ test(function() {
+ var iframeEle = document.getElementById("iframe1");
+ iframeEle.sandbox.remove("ALLOW-SANDBOX");
+ assert_true(iframeEle.sandbox.contains("allow-scripts") != iframeEle.sandbox.contains("Allow-SCRIPTS"))
+ }, "DOMSettableTokenList case sensitivity")
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_012.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_012.htm
new file mode 100644
index 00000000000..cf99378cd56
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_012.htm
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>HTML5 Sandbox: value of sandbox attribute must be an unordered set of unique space-separated tokens.</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://dev.w3.org/html5/spec/Overview.html#attr-iframe-sandbox" />
+ <meta name="assert" content="value of sandbox attribute must be an unordered set of unique space-separated tokens." />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <script type="text/javascript">
+
+
+ var t = async_test("value of sandbox attribute must be an unordered set of unique space-separated tokens.");
+
+ function callback(event)
+ {
+ t.step(function(){
+ assert_true('sandbox' in document.createElement('iframe'));
+ assert_equals(event.data, "cookies are R/W");
+ });
+ t.done();
+ }
+
+ var timer = setTimeout(callback, 4000);
+ window.addEventListener("message", callback, false);
+ </script>
+ <div id=log></div>
+
+ <iframe style="display:none" src="iframe_sandbox_012.htm" sandbox=" Allow-Scripts Allow-Same-Origin "></iframe>
+
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_013.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_013.htm
new file mode 100644
index 00000000000..ab0aea079f3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_013.htm
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>HTML5 Sandbox: value of sandbox attribute must be an unordered set of unique space-separated tokens.</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://dev.w3.org/html5/spec/Overview.html#attr-iframe-sandbox" />
+ <meta name="assert" content="value of sandbox attribute must be an unordered set of unique space-separated tokens." />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <script type="text/javascript">
+
+
+ var t = async_test("value of sandbox attribute must be an unordered set of unique space-separated tokens.");
+
+ function callback(event)
+ {
+ t.step(function(){
+ assert_true('sandbox' in document.createElement('iframe'));
+ assert_equals(event.data, "cookies are R/W");
+ });
+ t.done();
+ }
+
+ var timer = setTimeout(callback, 4000);
+ window.addEventListener("message", callback, false);
+ </script>
+ <div id=log></div>
+
+ <iframe style="display:none" src="iframe_sandbox_012.htm" sandbox="
+ allow-scripts
+ allow-same-origin
+ "></iframe>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_014.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_014.htm
new file mode 100644
index 00000000000..774720929cd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_014.htm
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>HTML5 Sandbox: value of sandbox attribute must be an unordered set of unique space-separated tokens.</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://dev.w3.org/html5/spec/Overview.html#attr-iframe-sandbox" />
+ <meta name="assert" content="value of sandbox attribute must be an unordered set of unique space-separated tokens." />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <script type="text/javascript">
+
+
+ var t = async_test("value of sandbox attribute must be an unordered set of unique space-separated tokens.");
+
+ function callback(event)
+ {
+ t.step(function(){
+ assert_true('sandbox' in document.createElement('iframe'));
+ assert_equals(event.data, "cookies are R/W");
+ });
+ t.done();
+ }
+
+ var timer = setTimeout(callback, 4000);
+ window.addEventListener("message", callback, false);
+ </script>
+ <div id=log></div>
+
+ <iframe style="display:none" src="iframe_sandbox_012.htm" sandbox=" allow-scripts allow-same-origin "></iframe>
+
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_015.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_015.htm
new file mode 100644
index 00000000000..a34ede4b396
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_015.htm
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>HTML5 Sandbox: value of sandbox attribute must be an unordered set of unique space-separated tokens.</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://dev.w3.org/html5/spec/Overview.html#attr-iframe-sandbox" />
+ <meta name="assert" content="value of sandbox attribute must be an unordered set of unique space-separated tokens." />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <script type="text/javascript">
+
+
+ var t = async_test("value of sandbox attribute must be an unordered set of unique space-separated tokens.");
+
+ function callback(event)
+ {
+ t.step(function(){
+ assert_true('sandbox' in document.createElement('iframe'));
+ assert_equals(event.data, "cookies are R/W");
+ });
+ t.done();
+ }
+
+ var timer = setTimeout(callback, 4000);
+ window.addEventListener("message", callback, false);
+ </script>
+ <div id=log></div>
+
+ <iframe style="display:none" src="iframe_sandbox_012.htm" sandbox="&#32ALLOW-SCRIPTS&#32allow-same-origin&#32"></iframe>
+
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_016.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_016.htm
new file mode 100644
index 00000000000..e920492621f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_016.htm
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>HTML5 Sandbox: value of sandbox attribute must be an unordered set of unique space-separated tokens.</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://dev.w3.org/html5/spec/Overview.html#attr-iframe-sandbox" />
+ <meta name="assert" content="value of sandbox attribute must be an unordered set of unique space-separated tokens." />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <script type="text/javascript">
+
+
+ var t = async_test("value of sandbox attribute must be an unordered set of unique space-separated tokens.");
+
+ function callback(event)
+ {
+ t.step(function(){
+ assert_true('sandbox' in document.createElement('iframe'));
+ assert_equals(event.data, "cookies are R/W");
+ });
+ t.done();
+ }
+
+ var timer = setTimeout(callback, 4000);
+ window.addEventListener("message", callback, false);
+ </script>
+ <div id=log></div>
+
+ <iframe style="display:none" src="iframe_sandbox_012.htm" sandbox="&#13ALLOW-SCRIPTS&#13allow-same-origin&#13"></iframe>
+
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_017.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_017.htm
new file mode 100644
index 00000000000..ade4c8092da
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_017.htm
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>HTML5 Sandbox: value of sandbox attribute must be an unordered set of unique space-separated tokens.</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://dev.w3.org/html5/spec/Overview.html#attr-iframe-sandbox" />
+ <meta name="assert" content="value of sandbox attribute must be an unordered set of unique space-separated tokens." />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <script type="text/javascript">
+
+
+ var t = async_test("value of sandbox attribute must be an unordered set of unique space-separated tokens.");
+
+ function callback(event)
+ {
+ t.step(function(){
+ assert_true('sandbox' in document.createElement('iframe'));
+ assert_equals(event.data, "cookies are R/W");
+ });
+ t.done();
+ }
+
+ var timer = setTimeout(callback, 4000);
+ window.addEventListener("message", callback, false);
+ </script>
+ <div id=log></div>
+
+ <iframe style="display:none" src="iframe_sandbox_012.htm" sandbox="&#12ALLOW-SCRIPTS&#12allow-same-origin&#12"></iframe>
+
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_018.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_018.htm
new file mode 100644
index 00000000000..77f10d27426
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_018.htm
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>HTML5 Sandbox: value of sandbox attribute must be an unordered set of unique space-separated tokens.</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://dev.w3.org/html5/spec/Overview.html#attr-iframe-sandbox" />
+ <meta name="assert" content="value of sandbox attribute must be an unordered set of unique space-separated tokens." />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <script type="text/javascript">
+
+
+ var t = async_test("value of sandbox attribute must be an unordered set of unique space-separated tokens.");
+
+ function callback(event)
+ {
+ t.step(function(){
+ assert_true('sandbox' in document.createElement('iframe'));
+ assert_equals(event.data, "cookies are R/W");
+ });
+ t.done();
+ }
+
+ var timer = setTimeout(callback, 4000);
+ window.addEventListener("message", callback, false);
+ </script>
+ <div id=log></div>
+
+ <iframe style="display:none" src="iframe_sandbox_012.htm" sandbox="&#10ALLOW-SCRIPTS&#10allow-same-origin&#10"></iframe>
+
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_019.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_019.htm
new file mode 100644
index 00000000000..d91280a60a5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_019.htm
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>HTML5 Sandbox: value of sandbox attribute must be an unordered set of unique space-separated tokens.</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://dev.w3.org/html5/spec/Overview.html#attr-iframe-sandbox" />
+ <meta name="assert" content="value of sandbox attribute must be an unordered set of unique space-separated tokens." />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <script type="text/javascript">
+
+
+ var t = async_test("value of sandbox attribute must be an unordered set of unique space-separated tokens.");
+
+ function callback(event)
+ {
+ t.step(function(){
+ assert_true('sandbox' in document.createElement('iframe'));
+ assert_equals(event.data, "cookies are R/W");
+ });
+ t.done();
+ }
+
+ var timer = setTimeout(callback, 4000);
+ window.addEventListener("message", callback, false);
+ </script>
+ <div id=log></div>
+
+ <iframe style="display:none" src="iframe_sandbox_012.htm" sandbox="&#9ALLOW-SCRIPTS&#9allow-same-origin&#9"></iframe>
+
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_020.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_020.htm
new file mode 100644
index 00000000000..751f8586353
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_020.htm
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>HTML5 Sandbox: Nested iframes cannot have less sandbox restrictions than their most restrictive ancestor iframe.</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://dev.w3.org/html5/spec/Overview.html#attr-iframe-sandbox" />
+ <meta name="assert" content="Nested iframes cannot have less sandbox restrictions than their most restrictive ancestor iframe." />
+ <script src="sandbox_helper.js" type="text/javascript"></script>
+</head>
+<body>
+ <pre>Description: Nested iframes cannot have less sandbox restrictions than their most restrictive ancestor iframe.</pre>
+ <div>This test is to verify script is blocked inside nested iframes if the top-most sandbox iframe has no 'allow-scripts' token.</div>
+ <br />
+ <table id='testtable' border='1'>
+ <tr>
+ <td>Test Result</td>
+ <td>Test Assertion</td>
+ </tr>
+ <tr>
+ <td id='test_0_result'>Manual</td>
+ <td id='test_0_assertion'>Test passes if there is no red on the page.</td>
+ </tr>
+ </table>
+ <br />
+ <div id="testframe">
+ <div style="font-weight:bold">Top-most iframe with sandbox=""</div>
+ <iframe id="iframe1" name="iframe1" src="iframe_sandbox_020.htm" sandbox="" style="height: 330px; width: 400px;"></iframe>
+ </div>
+ <script type="text/javascript">
+ DisableTestForNonSupportingBrowsers();
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_021.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_021.htm
new file mode 100644
index 00000000000..bbdc21f9355
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_021.htm
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>HTML5 Sandbox: Nested iframes cannot have less sandbox restrictions than their most restrictive ancestor iframe.</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://dev.w3.org/html5/spec/Overview.html#attr-iframe-sandbox" />
+ <meta name="assert" content="Nested iframes cannot have less sandbox restrictions than their most restrictive ancestor iframe." />
+ <script src="sandbox_helper.js" type="text/javascript"></script>
+</head>
+<body>
+ <pre>Description: Nested iframes cannot have less sandbox restrictions than their most restrictive ancestor iframe.</pre>
+ <div>This test is to verify script is allowed inside nested iframes if any of the conditions below are true</div>
+ <div>1. both parent sandbox and child sandbox have 'allow-scripts' token.</div>
+ <div>2. parent sandbox has 'allow-scripts' token and nested child iframe has no sandbox attribute.</div>
+ <div>3. parent iframe has no sandbox attribute and child iframe has sandbox='allow-scripts' token.</div>
+ <div>4. both parent and child iframes have no sandbox attribute.</div>
+ <br />
+ <table id='testtable' border='1'>
+ <tr>
+ <td>Test Result</td>
+ <td>Test Assertion</td>
+ </tr>
+ <tr>
+ <td id='test_0_result'>Manual</td>
+ <td id='test_0_assertion'>Test passes if there is no red on the page.</td>
+ </tr>
+ </table>
+ <br />
+ <div id="testframe">
+ <div style="float: left; border: 1px solid; padding: 5px;">
+ <div style="font-weight: bold">Top-most iframe with sandbox="allow-scripts"</div>
+ <iframe id="iframe1" src="iframe_sandbox_021.htm" sandbox="allow-scripts" style="height: 330px; width: 400px;"></iframe>
+ </div>
+ <div style="float: left; border: 1px solid; padding: 5px; margin-left: 20px;">
+ <div style="font-weight: bold">Top-most iframe without sandbox attribute</div>
+ <iframe id="iframe2" src="iframe_sandbox_021.htm" style="height: 330px; width: 400px;"></iframe>
+ </div>
+ </div>
+ <script type="text/javascript">
+ DisableTestForNonSupportingBrowsers();
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_022.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_022.htm
new file mode 100644
index 00000000000..aa08de512b5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_022.htm
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>HTML5 Sandbox: allow sandbox iframe to navigate their top-level browsing context if sandbox="allow-top-navigation".</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://dev.w3.org/html5/spec/Overview.html#sandboxed-scripts-browsing-context-flag" />
+ <meta name="assert" content="Allow sandbox iframe to navigate their top-level browsing context if sandbox='allow-top-navigation'." />
+ <script src="sandbox_helper.js" type="text/javascript"></script>
+</head>
+<body>
+ <pre>Description: Allow sandbox iframe to navigate its top-level browsing context if sandbox='allow-top-navigation'.</pre>
+ <table id='testtable' border='1'>
+ <tr>
+ <td>Test Result</td>
+ <td>Test Assertion</td>
+ </tr>
+ <tr>
+ <td id='test_0_result'>Manual</td>
+ <td id='test_0_assertion'>
+ <div>Steps:</div>
+ <div>1. Click link "Open the link in top window".</div>
+ <br />
+ <div>Test passes if there is no red on the page and no top-level navigation after following the above steps.</div>
+ </td>
+ </tr>
+ </table>
+ <br />
+ <div id="testframe">
+ <pre>iframe with sandbox="allow-top-navigation"</pre>
+ <iframe src="iframe_sandbox_022.htm" sandbox="allow-top-navigation" style="height: 100px; width: 450px;"></iframe>
+ </div>
+ <script type="text/javascript">
+ DisableTestForNonSupportingBrowsers();
+ </script>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_023.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_023.htm
new file mode 100644
index 00000000000..7f8a436b4c9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_023.htm
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>HTML5 Sandbox: Allow sandbox iframe to access other content from the same origin if sandbox="allow-same-origin".</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://dev.w3.org/html5/spec/Overview.html#sandboxed-origin-browsing-context-flag" />
+ <meta name="assert" content=" Allow sandbox iframe to access other content from the same origin if sandbox='allow-same-origin'." />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <script type="text/javascript">
+
+
+ var t = async_test("Allow sandbox iframe to access other content from the same origin if sandbox='allow-same-origin'");
+
+ function callback(event)
+ {
+ t.step(function(){
+ assert_true('sandbox' in document.createElement('iframe'));
+ assert_equals(event.data, "window.parent.document");
+ });
+ t.done();
+ }
+
+ var timer = setTimeout(callback, 4000);
+ window.addEventListener("message", callback, false);
+ </script>
+ <iframe src="iframe_sandbox_023.htm" sandbox="allow-scripts allow-same-origin" style="display:none"></iframe>
+ <div id=log></div>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_024.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_024.htm
new file mode 100644
index 00000000000..935543707d8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_024.htm
@@ -0,0 +1,33 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>HTML5 Sandbox: document.cookie access is allowed inside iframe with sandbox="allow-same-origin".</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://dev.w3.org/html5/spec/Overview.html#sandboxed-origin-browsing-context-flag" />
+ <meta name="assert" content="document.cookie access is allowed inside iframe with sandbox='allow-same-origin'." />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <script type="text/javascript">
+
+
+ var t = async_test("document.cookie access is allowed inside iframe with sandbox='allow-same-origin'.");
+
+ function callback(event)
+ {
+ t.step(function(){
+ assert_true('sandbox' in document.createElement('iframe'));
+ assert_equals(event.data, "cookies are R/W");
+ });
+ t.done();
+ }
+
+ var timer = setTimeout(callback, 4000);
+ window.addEventListener("message", callback, false);
+ </script>
+ <div id=log></div>
+ <iframe src="iframe_sandbox_024.htm" sandbox="allow-scripts allow-same-origin" style="display:none"></iframe>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_025.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_025.htm
new file mode 100644
index 00000000000..ab291e5cee0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_025.htm
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>HTML5 Sandbox: Allow parent content to access sandbox child iframe content when sandbox='allow-same-origin</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://dev.w3.org/html5/spec/Overview.html#sandboxed-origin-browsing-context-flag" />
+ <meta name="assert" content="Allow parent content to access sandbox child iframe content when sandbox='allow-same-origin'" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <script type="text/javascript">
+
+
+
+ var t = async_test("Allow parent content to access sandbox child iframe content when sandbox='allow-same-origin'");
+
+ function callback(event)
+ {
+ t.step(function(){
+ assert_true('sandbox' in document.createElement('iframe'));
+ assert_equals(document.getElementById('sandboxIframe').contentDocument.title, "Page with a message");
+ });
+ t.done();
+ }
+ </script>
+ <div id=log></div>
+
+ <iframe id='sandboxIframe' src="standalone-iframe-content.htm" sandbox="allow-same-origin" onload="callback()" style="display : none"></iframe>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_026.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_026.htm
new file mode 100644
index 00000000000..49243899e22
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_026.htm
@@ -0,0 +1,33 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>HTML5 Sandbox: Allow localStorage and sessionStorage access inside iframe with sandbox='allow-same-origin allow-scripts'.</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://dev.w3.org/html5/spec/Overview.html#sandboxed-origin-browsing-context-flag" />
+ <meta name="assert" content="Allow localStorage and sessionStorage access inside iframe with sandbox='allow-same-origin allow-scripts'." />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <script type="text/javascript">
+
+
+ var t = async_test("Allow localStorage and sessionStorage access inside iframe with sandbox='allow-same-origin allow-scripts'");
+
+ function callback(event)
+ {
+ t.step(function(){
+ assert_true('sandbox' in document.createElement('iframe'));
+ assert_equals(event.data, "access to window.localStorage and window.sessionStorage");
+ });
+ t.done();
+ }
+
+ var timer = setTimeout(callback, 4000);
+ window.addEventListener("message", callback, false);
+ </script>
+ <div id=log></div>
+ <iframe src="iframe_sandbox_026.htm" sandbox="allow-scripts allow-same-origin" style="display : none"></iframe>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_027.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_027.htm
new file mode 100644
index 00000000000..2b9cba5d25a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_027.htm
@@ -0,0 +1,33 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>HTML5 Sandbox: Allow XMLHttpRequest inside iframe with the sandbox attribute if sandbox='allow-same-origin'.</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://dev.w3.org/html5/spec/Overview.html#sandboxed-origin-browsing-context-flag" />
+ <meta name="assert" content="Allow XMLHttpRequest in an iframe with the sandbox attribute if sandbox='allow-same-origin'." />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <script type="text/javascript">
+
+
+ var t = async_test("Allow XMLHttpRequest in an iframe with the sandbox attribute if sandbox='allow-same-origin'.");
+
+ function callback(event)
+ {
+ t.step(function(){
+ assert_true('sandbox' in document.createElement('iframe'));
+ assert_equals(event.data, "access to window.XMLHttpRequest");
+ });
+ t.done();
+ }
+
+ var timer = setTimeout(callback, 4000);
+ window.addEventListener("message", callback, false);
+ </script>
+ <div id=log></div>
+ <iframe src="iframe_sandbox_027.htm" sandbox="allow-scripts allow-same-origin" style="display : none"></iframe>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_028.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_028.htm
new file mode 100644
index 00000000000..56dfb681006
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_028.htm
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>HTML5 Sandbox: Block sandbox iframe from accessing other content from the same origin.</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://dev.w3.org/html5/spec/Overview.html#sandboxed-origin-browsing-context-flag" />
+ <meta name="assert" content="Block sandbox iframe from accessing other content from the same origin." />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <script type="text/javascript">
+
+
+ var t = async_test("Block sandbox iframe from accessing other content from the same origin.");
+
+ function callback(event)
+ {
+ t.step(function(){
+ assert_true('sandbox' in document.createElement('iframe'));
+ assert_equals(event.data, "!window.parent.document");
+ });
+ t.done();
+ }
+
+ var timer = setTimeout(callback, 4000);
+ window.addEventListener("message", callback, false);
+ </script>
+ <iframe src="iframe_sandbox_028.htm" sandbox="allow-scripts" style="display:none"></iframe>
+ <div id=log></div>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_029.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_029.htm
new file mode 100644
index 00000000000..b88b74a229c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_029.htm
@@ -0,0 +1,33 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>HTML5 Sandbox: Block document.cookie inside iframe with the sandbox attribute.</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://dev.w3.org/html5/spec/Overview.html#sandboxed-origin-browsing-context-flag" />
+ <meta name="assert" content="Block document.cookie inside iframe with the sandbox attribute." />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <script type="text/javascript">
+
+
+ var t = async_test("Block document.cookie inside iframe with the sandbox attribute.");
+
+ function callback(event)
+ {
+ t.step(function(){
+ assert_true('sandbox' in document.createElement('iframe'));
+ assert_equals(event.data, "cookies are not R/W");
+ });
+ t.done();
+ }
+
+ var timer = setTimeout(callback, 4000);
+ window.addEventListener("message", callback, false);
+ </script>
+ <div id=log></div>
+ <iframe src="iframe_sandbox_029.htm" sandbox="allow-scripts" style="display:none"></iframe>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_030.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_030.htm
new file mode 100644
index 00000000000..1c3b54cb0dd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_030.htm
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>HTML5 Sandbox: Block parent content to access sandbox child iframe content when sandbox attribute exists</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://dev.w3.org/html5/spec/Overview.html#sandboxed-origin-browsing-context-flag" />
+ <meta name="assert" content="Block parent content to access sandbox child iframe content when sandbox attribute exists" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <script type="text/javascript">
+
+
+
+ var t = async_test("Block parent content to access sandbox child iframe content when sandbox attribute exists");
+
+ function callback(event)
+ {
+ t.step(function(){
+ assert_true('sandbox' in document.createElement('iframe'));
+ try { document.getElementById('sandboxIframe').contentDocument.title; assert_true(false);}
+ catch(e) {assert_true(true);}
+ });
+ t.done();
+ }
+ </script>
+ <div id=log></div>
+
+ <iframe id='sandboxIframe' src="standalone-iframe-content.htm" sandbox onload="callback()" style="display : none"></iframe>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_031.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_031.htm
new file mode 100644
index 00000000000..2582fac3582
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_031.htm
@@ -0,0 +1,33 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>HTML5 Sandbox: Block localStorage and sessionStorage inside iframe with the sandbox attribute.</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://dev.w3.org/html5/spec/Overview.html#sandboxed-origin-browsing-context-flag" />
+ <meta name="assert" content="Block localStorage and sessionStorage inside iframe with the sandbox attribute." />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <script type="text/javascript">
+
+
+ var t = async_test("Block localStorage and sessionStorage inside iframe with the sandbox attribute.");
+
+ function callback(event)
+ {
+ t.step(function(){
+ assert_true('sandbox' in document.createElement('iframe'));
+ assert_equals(event.data, "no access to window.localStorage and window.sessionStorage");
+ });
+ t.done();
+ }
+
+ var timer = setTimeout(callback, 4000);
+ window.addEventListener("message", callback, false);
+ </script>
+ <div id=log></div>
+ <iframe src="iframe_sandbox_031.htm" sandbox="allow-scripts" style="display : none"></iframe>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_032.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_032.htm
new file mode 100644
index 00000000000..1c234fcc960
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_032.htm
@@ -0,0 +1,33 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>HTML5 Sandbox: Block XMLHttpRequest in an iframe with the sandbox attribute.</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://dev.w3.org/html5/spec/Overview.html#sandboxed-origin-browsing-context-flag" />
+ <meta name="assert" content="Block XMLHttpRequest inside sandbox iframe." />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <script type="text/javascript">
+
+
+ var t = async_test("Block XMLHttpRequest in an iframe with the sandbox attribute.");
+
+ function callback(event)
+ {
+ t.step(function(){
+ assert_true('sandbox' in document.createElement('iframe'));
+ assert_equals(event.data, "no access to window.XMLHttpRequest");
+ });
+ t.done();
+ }
+
+ var timer = setTimeout(callback, 4000);
+ window.addEventListener("message", callback, false);
+ </script>
+ <div id=log></div>
+ <iframe src="iframe_sandbox_032.htm" sandbox="allow-scripts" style="display : none"></iframe>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_helper.js b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_helper.js
new file mode 100644
index 00000000000..1472cbf223b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/sandbox_helper.js
@@ -0,0 +1,14 @@
+function IsSandboxSupported() {
+ if ('sandbox' in document.createElement('iframe')) {
+ return true;
+ }
+ return false;
+}
+
+function DisableTestForNonSupportingBrowsers() {
+ //check if sandbox is supported by the browser
+ if (!IsSandboxSupported()) {
+ document.getElementById('testframe').innerHTML = "FAIL: Your browser does not support the sandbox attribute on the iframe element.";
+ document.getElementById('testframe').style.color = "Red";
+ }
+} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/standalone-fail.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/standalone-fail.htm
new file mode 100644
index 00000000000..1725ef060ca
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/standalone-fail.htm
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Page with FAIL message</title>
+</head>
+<body>
+ <div style="color: Red">FAIL!!!</div>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/standalone-iframe-content.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/standalone-iframe-content.htm
new file mode 100644
index 00000000000..e543c21d650
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/standalone-iframe-content.htm
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Page with a message</title>
+</head>
+<body>
+ <div>Hello World.</div>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/standalone-pass.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/standalone-pass.htm
new file mode 100644
index 00000000000..0ca822f8de2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/sandbox/standalone-pass.htm
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Page with PASS message</title>
+</head>
+<body>
+ <div style="color: Green">PASS!!!</div>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/selection/RemoveElementContainingSelection.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/selection/RemoveElementContainingSelection.htm
new file mode 100644
index 00000000000..69150236ec7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/selection/RemoveElementContainingSelection.htm
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title id="desc">HTML5 Selection: Remove the element containing the selection</title>
+ <script type="text/javascript">
+ function RunTest()
+ {
+ try
+ {
+ var selection = window.getSelection();
+ var div1 = document.getElementById("div1");
+ var span1 = document.getElementById("span1");
+ var range = document.createRange();
+ range.selectNode(span1);
+ selection.addRange(range);
+
+ document.body.removeChild(div1);
+
+ if ("" == selection.toString())
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+ }
+ catch (ex)
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+ }
+ </script>
+ </head>
+ <body onload="RunTest();">
+ <div id="div1">some text
+ <span id="span1">aaaaaaaa</span>
+ </div>
+ <div id="div2">Remove the element containing the selection</div>
+ <p>Test passes if the word "PASS" appears below.</p>
+ <div>Test result: </div>
+ <div id="testresult">FAIL</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/selection/addRange.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/selection/addRange.htm
new file mode 100644
index 00000000000..c4b5e99444d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/selection/addRange.htm
@@ -0,0 +1,72 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title id="desc">HTML5 Selection: Add a range to the selection</title>
+ <script type="text/javascript">
+ var testPassed = true;
+
+ function checkSelectionAttributes(anchorNode, anchorOffset, focusNode, focusOffset, collapsed, rangeCount)
+ {
+ var selection = window.getSelection();
+ if (anchorNode != selection.anchorNode)
+ {
+ testPassed = false;
+ }
+ if (anchorOffset != selection.anchorOffset)
+ {
+ testPassed = false;
+ }
+ if (focusNode != selection.focusNode)
+ {
+ testPassed = false;
+ }
+ if (focusOffset != selection.focusOffset)
+ {
+ testPassed = false;
+ }
+ if (collapsed != selection.isCollapsed)
+ {
+ testPassed = false;
+ }
+ if (rangeCount != selection.rangeCount)
+ {
+ testPassed = false;
+ }
+ }
+
+ function RunTest()
+ {
+ try
+ {
+ var selection = window.getSelection();
+ var p1 = document.getElementById("p1");
+
+ var range = document.createRange();
+ range.selectNode(p1);
+ selection.addRange(range);
+
+ checkSelectionAttributes(range.startContainer, range.startOffset, range.endContainer, range.endOffset, range.collapsed, 1);
+ if (p1.firstChild.nodeValue != selection.toString())
+ {
+ testPassed = false;
+ }
+
+ if (testPassed)
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+ }
+ catch (ex)
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+ }
+ </script>
+ </head>
+ <body onload="RunTest();">
+ <p id="p1">Add a range to the selection</p>
+ <p>Test passes if the word "PASS" appears below.</p>
+ <div>Test result: </div>
+ <div id="testresult">FAIL</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/selection/collapse.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/selection/collapse.htm
new file mode 100644
index 00000000000..7c2423021c2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/selection/collapse.htm
@@ -0,0 +1,73 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title id="desc">HTML5 Selection: Collapse the selection using collapse()</title>
+ <script type="text/javascript">
+ var testPassed = true;
+
+ function checkSelectionAttributes(anchorNode, anchorOffset, focusNode, focusOffset, collapsed, rangeCount)
+ {
+ var selection = window.getSelection();
+ if (anchorNode != selection.anchorNode)
+ {
+ testPassed = false;
+ }
+ if (anchorOffset != selection.anchorOffset)
+ {
+ testPassed = false;
+ }
+ if (focusNode != selection.focusNode)
+ {
+ testPassed = false;
+ }
+ if (focusOffset != selection.focusOffset)
+ {
+ testPassed = false;
+ }
+ if (collapsed != selection.isCollapsed)
+ {
+ testPassed = false;
+ }
+ if (rangeCount != selection.rangeCount)
+ {
+ testPassed = false;
+ }
+ }
+
+ function RunTest()
+ {
+ try
+ {
+ var selection = window.getSelection();
+ var p1 = document.getElementById("p1");
+
+ var range = document.createRange();
+ range.selectNode(p1);
+ selection.addRange(range);
+ selection.collapse(p1, 0);
+
+ checkSelectionAttributes(p1, 0, p1, 0, true, 1);
+ if ("" != selection.toString())
+ {
+ testPassed = false;
+ }
+
+ if (testPassed)
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+ }
+ catch (ex)
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+ }
+ </script>
+ </head>
+ <body onload="RunTest();">
+ <p id="p1">Collapse the selection using collapse()</p>
+ <p>Test passes if the word "PASS" appears below.</p>
+ <div>Test result: </div>
+ <div id="testresult">FAIL</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/selection/collapseToEnd.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/selection/collapseToEnd.htm
new file mode 100644
index 00000000000..2f68ec6554b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/selection/collapseToEnd.htm
@@ -0,0 +1,75 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title id="desc">HTML5 Selection: Collapse the selection with collapseToEnd()</title>
+ <script type="text/javascript">
+ var testPassed = true;
+
+ function checkSelectionAttributes(anchorNode, anchorOffset, focusNode, focusOffset, collapsed, rangeCount)
+ {
+ var selection = window.getSelection();
+ if (anchorNode != selection.anchorNode)
+ {
+ testPassed = false;
+ }
+ if (anchorOffset != selection.anchorOffset)
+ {
+ testPassed = false;
+ }
+ if (focusNode != selection.focusNode)
+ {
+ testPassed = false;
+ }
+ if (focusOffset != selection.focusOffset)
+ {
+ testPassed = false;
+ }
+ if (collapsed != selection.isCollapsed)
+ {
+ testPassed = false;
+ }
+ if (rangeCount != selection.rangeCount)
+ {
+ testPassed = false;
+ }
+ }
+
+ function RunTest()
+ {
+ try
+ {
+ var selection = window.getSelection();
+ var p1 = document.getElementById("p1");
+
+ var range = document.createRange();
+ range.selectNode(p1);
+ selection.addRange(range);
+ selection.collapseToEnd();
+
+ range.collapse(false);
+
+ checkSelectionAttributes(range.startContainer, range.startOffset, range.endContainer, range.endOffset, true, 1);
+ if ("" != selection.toString())
+ {
+ testPassed = false;
+ }
+
+ if (testPassed)
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+ }
+ catch (ex)
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+ }
+ </script>
+ </head>
+ <body onload="RunTest();">
+ <p id="p1">Collapse the selection with collapseToEnd()</p>
+ <p>Test passes if the word "PASS" appears below.</p>
+ <div>Test result: </div>
+ <div id="testresult">FAIL</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/selection/collapseToStart.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/selection/collapseToStart.htm
new file mode 100644
index 00000000000..da9676d57b8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/selection/collapseToStart.htm
@@ -0,0 +1,75 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title id="desc">HTML5 Selection: Collapse the selection with collapseToStart()</title>
+ <script type="text/javascript">
+ var testPassed = true;
+
+ function checkSelectionAttributes(anchorNode, anchorOffset, focusNode, focusOffset, collapsed, rangeCount)
+ {
+ var selection = window.getSelection();
+ if (anchorNode != selection.anchorNode)
+ {
+ testPassed = false;
+ }
+ if (anchorOffset != selection.anchorOffset)
+ {
+ testPassed = false;
+ }
+ if (focusNode != selection.focusNode)
+ {
+ testPassed = false;
+ }
+ if (focusOffset != selection.focusOffset)
+ {
+ testPassed = false;
+ }
+ if (collapsed != selection.isCollapsed)
+ {
+ testPassed = false;
+ }
+ if (rangeCount != selection.rangeCount)
+ {
+ testPassed = false;
+ }
+ }
+
+ function RunTest()
+ {
+ try
+ {
+ var selection = window.getSelection();
+ var p1 = document.getElementById("p1");
+
+ var range = document.createRange();
+ range.selectNode(p1);
+ selection.addRange(range);
+ selection.collapseToStart();
+
+ range.collapse(true);
+
+ checkSelectionAttributes(range.startContainer, range.startOffset, range.endContainer, range.endOffset, true, 1);
+ if ("" != selection.toString())
+ {
+ testPassed = false;
+ }
+
+ if (testPassed)
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+ }
+ catch (ex)
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+ }
+ </script>
+ </head>
+ <body onload="RunTest();">
+ <p id="p1">Collapse the selection with collapseToStart()</p>
+ <p>Test passes if the word "PASS" appears below.</p>
+ <div>Test result: </div>
+ <div id="testresult">FAIL</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/selection/deleteFromDocument.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/selection/deleteFromDocument.htm
new file mode 100644
index 00000000000..2373939cc49
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/selection/deleteFromDocument.htm
@@ -0,0 +1,80 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title id="desc">HTML5 Selection: Delete some text from the document while it is part of a selection</title>
+ <script type="text/javascript">
+ var testPassed = true;
+
+ function checkSelectionAttributes(anchorNode, anchorOffset, focusNode, focusOffset, collapsed, rangeCount)
+ {
+ var selection = window.getSelection();
+ if (anchorNode != selection.anchorNode)
+ {
+ testPassed = false;
+ }
+ if (anchorOffset != selection.anchorOffset)
+ {
+ testPassed = false;
+ }
+ if (focusNode != selection.focusNode)
+ {
+ testPassed = false;
+ }
+ if (focusOffset != selection.focusOffset)
+ {
+ testPassed = false;
+ }
+ if (collapsed != selection.isCollapsed)
+ {
+ testPassed = false;
+ }
+ if (rangeCount != selection.rangeCount)
+ {
+ testPassed = false;
+ }
+ }
+
+ function RunTest()
+ {
+ try
+ {
+ var selection = window.getSelection();
+ var p2 = document.getElementById("p2");
+ var expectedResult = "abcdeuvwxyz";
+
+ var range = document.createRange();
+ range.setStart(p2.firstChild, 5);
+ range.setEnd(p2.firstChild, 20);
+ selection.addRange(range);
+ selection.deleteFromDocument();
+ p2.normalize();
+
+ range.collapse(true);
+
+ checkSelectionAttributes(range.startContainer, range.startOffset, range.endContainer, range.endOffset, true, 1);
+
+ if (expectedResult != p2.firstChild.data)
+ {
+ testPassed = false;
+ }
+
+ if (testPassed)
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+ }
+ catch (ex)
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+ }
+ </script>
+ </head>
+ <body onload="RunTest();">
+ <p id="p1">Delete some text from the document while it is part of a selection</p>
+ <p id="p2">abcdefghijklmnopqrstuvwxyz</p>
+ <p>Test passes if the word "PASS" appears below.</p>
+ <div>Test result: </div>
+ <div id="testresult">FAIL</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/selection/getRangeAt.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/selection/getRangeAt.htm
new file mode 100644
index 00000000000..a3911e6cd9d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/selection/getRangeAt.htm
@@ -0,0 +1,59 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title id="desc">HTML5 Selection: Get the range from the selection</title>
+ <script type="text/javascript">
+ function RunTest()
+ {
+ try
+ {
+ var selection = window.getSelection();
+ var p1 = document.getElementById("p1");
+ var testPassed = true;
+
+ var range = document.createRange();
+ range.selectNode(p1);
+ selection.addRange(range);
+
+ var returnedRange = selection.getRangeAt(0);
+
+ if (range.toString() != returnedRange.toString())
+ {
+ testPassed = false;
+ }
+ if (range.startContainer != returnedRange.startContainer)
+ {
+ testPassed = false;
+ }
+ if (range.startOffset != returnedRange.startOffset)
+ {
+ testPassed = false;
+ }
+ if (range.endContainer != returnedRange.endContainer)
+ {
+ testPassed = false;
+ }
+ if (range.endOffset != returnedRange.endOffset)
+ {
+ testPassed = false;
+ }
+
+ if (testPassed)
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+ }
+ catch (ex)
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+ }
+ </script>
+ </head>
+ <body onload="RunTest();">
+ <p id="p1">Get the range from the selection</p>
+ <p>Test passes if the word "PASS" appears below.</p>
+ <div>Test result: </div>
+ <div id="testresult">FAIL</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/selection/insertNodeIntoSelection.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/selection/insertNodeIntoSelection.htm
new file mode 100644
index 00000000000..4ec0d80f359
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/selection/insertNodeIntoSelection.htm
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title id="desc">HTML5 Selection: Insert a new element and text node into an element that is currently selected</title>
+ <script type="text/javascript">
+ function RunTest()
+ {
+ try
+ {
+ var selection = window.getSelection();
+ var expectedText = "some textnew text";
+ var div1 = document.getElementById("div1");
+ var range = document.createRange();
+ range.selectNode(div1);
+ selection.addRange(range);
+
+ var ele = document.createElement("div");
+ var tNode = document.createTextNode("new text");
+ ele.appendChild(tNode);
+ div1.appendChild(ele);
+
+ if (expectedText == selection.toString())
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+ }
+ catch (ex)
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+ }
+ </script>
+ </head>
+ <body onload="RunTest();">
+ <p>This test inserts a new element with a text node child into the current selection.</p>
+ <div id="div1">some text</div>
+ <p>Test passes if the word "PASS" appears below.</p>
+ <div>Test result: </div>
+ <div id="testresult">FAIL</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/selection/removeAllRanges.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/selection/removeAllRanges.htm
new file mode 100644
index 00000000000..869e5391dda
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/selection/removeAllRanges.htm
@@ -0,0 +1,73 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title id="desc">HTML5 Selection: Call removeAllRanges() to clear the selection</title>
+ <script type="text/javascript">
+ var testPassed = true;
+
+ function checkDefaultSelectionAttributes()
+ {
+ var selection = window.getSelection();
+ if (null != selection.anchorNode)
+ {
+ testPassed = false;
+ }
+ if (0 != selection.anchorOffset)
+ {
+ testPassed = false;
+ }
+ if (null != selection.focusNode)
+ {
+ testPassed = false;
+ }
+ if (0 != selection.focusOffset)
+ {
+ testPassed = false;
+ }
+ if (!selection.isCollapsed)
+ {
+ testPassed = false;
+ }
+ if (0 != selection.rangeCount)
+ {
+ testPassed = false;
+ }
+ }
+
+ function RunTest()
+ {
+ try
+ {
+ var selection = window.getSelection();
+ var p1 = document.getElementById("p1");
+
+ var range = document.createRange();
+ range.selectNode(p1);
+ selection.addRange(range);
+ selection.removeAllRanges();
+
+ checkDefaultSelectionAttributes();
+ if ("" != selection.toString())
+ {
+ testPassed = false;
+ }
+
+ if (testPassed)
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+ }
+ catch (ex)
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+ }
+ </script>
+ </head>
+ <body onload="RunTest();">
+ <p id="p1">Call removeAllRanges() to clear the selection</p>
+ <p>Test passes if the word "PASS" appears below.</p>
+ <div>Test result: </div>
+ <div id="testresult">FAIL</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/selection/removeRange.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/selection/removeRange.htm
new file mode 100644
index 00000000000..e35047b4701
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/selection/removeRange.htm
@@ -0,0 +1,72 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title id="desc">HTML5 Selection: Remove the range from the selection</title>
+ <script type="text/javascript">
+ var testPassed = true;
+
+ function checkDefaultSelectionAttributes()
+ {
+ var selection = window.getSelection();
+ if (null != selection.anchorNode)
+ {
+ testPassed = false;
+ }
+ if (0 != selection.anchorOffset)
+ {
+ testPassed = false;
+ }
+ if (null != selection.focusNode)
+ {
+ testPassed = false;
+ }
+ if (0 != selection.focusOffset)
+ {
+ testPassed = false;
+ }
+ if (!selection.isCollapsed)
+ {
+ testPassed = false;
+ }
+ if (0 != selection.rangeCount)
+ {
+ testPassed = false;
+ }
+ }
+
+ function RunTest()
+ {
+ try
+ {
+ var selection = window.getSelection();
+ var p1 = document.getElementById("p1");
+
+ var range = document.createRange();
+ range.selectNode(p1);
+ selection.addRange(range);
+ selection.removeRange(range);
+
+ checkDefaultSelectionAttributes();
+ if ("" != selection.toString())
+ {
+ testPassed = false;
+ }
+ if (testPassed)
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+ }
+ catch (ex)
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+ }
+ </script>
+ </head>
+ <body onload="RunTest();">
+ <p id="p1">Remove the range from the selection by calling removeRange()</p>
+ <p>Test passes if the word "PASS" appears below.</p>
+ <div>Test result: </div>
+ <div id="testresult">FAIL</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/selection/select.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/selection/select.htm
new file mode 100644
index 00000000000..f6a31f24964
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/selection/select.htm
@@ -0,0 +1,72 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title id="desc">HTML5 Selection: Call select() on a text field</title>
+ <script type="text/javascript">
+ var testPassed = true;
+
+ function checkDefaultSelectionAttributes()
+ {
+ var selection = window.getSelection();
+ if (null != selection.anchorNode)
+ {
+ testPassed = false;
+ }
+ if (0 != selection.anchorOffset)
+ {
+ testPassed = false;
+ }
+ if (null != selection.focusNode)
+ {
+ testPassed = false;
+ }
+ if (0 != selection.focusOffset)
+ {
+ testPassed = false;
+ }
+ if (!selection.isCollapsed)
+ {
+ testPassed = false;
+ }
+ if (0 != selection.rangeCount)
+ {
+ testPassed = false;
+ }
+ }
+
+ function RunTest()
+ {
+ try
+ {
+ var input1 = document.getElementById("input1");
+
+ input1.select();
+
+ checkDefaultSelectionAttributes();
+
+ var selectionText = input1.value.substring(input1.selectionStart, input1.selectionEnd);
+ if (input1.value != selectionText)
+ {
+ testPassed = false;
+ }
+
+ if (testPassed)
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+ }
+ catch (ex)
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+ }
+ </script>
+ </head>
+ <body onload="RunTest();">
+ <input style="WIDTH: 500px" id="input1" value="Some text in an input control" type="text" />
+ <p>Select the text in the input element by calling select()</p>
+ <p>Test passes if the word "PASS" appears below.</p>
+ <div>Test result: </div>
+ <div id="testresult">FAIL</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/selection/selectAllChildren.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/selection/selectAllChildren.htm
new file mode 100644
index 00000000000..a3ab4f57d40
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/selection/selectAllChildren.htm
@@ -0,0 +1,32 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title id="desc">HTML5 Selection: Call selectAllChildren() where the parameter is a text node</title>
+ <script type="text/javascript">
+ function RunTest()
+ {
+ try
+ {
+ var selection = window.getSelection();
+ var div1 = document.getElementById("div1");
+ selection.selectAllChildren(div1.firstChild);
+
+ if ("" == selection.toString())
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+ }
+ catch (ex)
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+ }
+ </script>
+ </head>
+ <body onload="RunTest();">
+ <div id="div1">Call selectAllChildren() where the parameter is a text node</div>
+ <p>Test passes if the word "PASS" appears below.</p>
+ <div>Test result: </div>
+ <div id="testresult">FAIL</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/selection/selectionStartEnd.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/selection/selectionStartEnd.htm
new file mode 100644
index 00000000000..c5b69d57060
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/selection/selectionStartEnd.htm
@@ -0,0 +1,74 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title id="desc">HTML5 Selection: Set selectionStart and selectionEnd on a text field</title>
+ <script type="text/javascript">
+ var testPassed = true;
+
+ function checkDefaultSelectionAttributes()
+ {
+ var selection = window.getSelection();
+ if (null != selection.anchorNode)
+ {
+ testPassed = false;
+ }
+ if (0 != selection.anchorOffset)
+ {
+ testPassed = false;
+ }
+ if (null != selection.focusNode)
+ {
+ testPassed = false;
+ }
+ if (0 != selection.focusOffset)
+ {
+ testPassed = false;
+ }
+ if (!selection.isCollapsed)
+ {
+ testPassed = false;
+ }
+ if (0 != selection.rangeCount)
+ {
+ testPassed = false;
+ }
+ }
+
+ function RunTest()
+ {
+ try
+ {
+ var input1 = document.getElementById("input1");
+ var expectedResult = "text";
+
+ input1.selectionStart = 5;
+ input1.selectionEnd = 9;
+
+ checkDefaultSelectionAttributes();
+
+ var selectionText = input1.value.substring(input1.selectionStart, input1.selectionEnd);
+ if (expectedResult != selectionText)
+ {
+ testPassed = false;
+ }
+
+ if (testPassed)
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+ }
+ catch (ex)
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+ }
+ </script>
+ </head>
+ <body onload="RunTest();">
+ <input style="WIDTH: 500px" id="input1" value="Some text in an input control" type="text" />
+ <p>Select some text in the input element by setting selectionStart and selectionEnd</p>
+ <p>Test passes if the word "PASS" appears below.</p>
+ <div>Test result: </div>
+ <div id="testresult">FAIL</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/selection/setSelectionRange.htm b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/selection/setSelectionRange.htm
new file mode 100644
index 00000000000..a6d7a0f2ba1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/selection/setSelectionRange.htm
@@ -0,0 +1,73 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title id="desc">HTML5 Selection: Call setSelectionRange() on a text field</title>
+ <script type="text/javascript">
+ var testPassed = true;
+
+ function checkDefaultSelectionAttributes()
+ {
+ var selection = window.getSelection();
+ if (null != selection.anchorNode)
+ {
+ testPassed = false;
+ }
+ if (0 != selection.anchorOffset)
+ {
+ testPassed = false;
+ }
+ if (null != selection.focusNode)
+ {
+ testPassed = false;
+ }
+ if (0 != selection.focusOffset)
+ {
+ testPassed = false;
+ }
+ if (!selection.isCollapsed)
+ {
+ testPassed = false;
+ }
+ if (0 != selection.rangeCount)
+ {
+ testPassed = false;
+ }
+ }
+
+ function RunTest()
+ {
+ try
+ {
+ var input1 = document.getElementById("input1");
+ var expectedResult = "input";
+
+ input1.setSelectionRange(16, 21);
+
+ checkDefaultSelectionAttributes();
+
+ var selectionText = input1.value.substring(input1.selectionStart, input1.selectionEnd);
+ if (expectedResult != selectionText)
+ {
+ testPassed = false;
+ }
+
+ if (testPassed)
+ {
+ document.getElementById("testresult").firstChild.data = "PASS";
+ }
+ }
+ catch (ex)
+ {
+ document.getElementById("testresult").firstChild.data = "FAIL";
+ }
+ }
+ </script>
+ </head>
+ <body onload="RunTest();">
+ <input style="WIDTH: 500px" id="input1" value="Some text in an input control" type="text" />
+ <p>Call setSelectionRange() on the input element to select some of the text</p>
+ <p>Test passes if the word "PASS" appears below.</p>
+ <div>Test result: </div>
+ <div id="testresult">FAIL</div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/structuredclone/echo.js b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/structuredclone/echo.js
new file mode 100644
index 00000000000..02184921cf3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/structuredclone/echo.js
@@ -0,0 +1 @@
+onmessage = function (ev) { postMessage(ev.data); } \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/structuredclone/structuredclone_0.html b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/structuredclone/structuredclone_0.html
new file mode 100644
index 00000000000..ed0e35d9acf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/structuredclone/structuredclone_0.html
@@ -0,0 +1,400 @@
+<!doctype html>
+<html>
+ <head>
+ <meta content="text/html; charset=utf-8" http-equiv="content-type" />
+ <title>2.8 Common DOM interfaces - Structured Clone Algorithm </title>
+ <link rel="help" href="http://www.w3.org/TR/html5/common-dom-interfaces.html#safe-passing-of-structured-data" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <div id="log"></div>
+
+<script type="text/javascript">
+ var worker;
+ var testCollection;
+ setup(function()
+ {
+ //the worker is used for each test in sequence
+ //worker's callback will be set for each test
+ //worker's internal onmessage echoes the data back to this thread through postMessage
+ worker = new Worker("./echo.js");
+ testCollection = [
+ function() {
+ var t = async_test("Primitive string is cloned");
+ t.id = 0;
+ worker.onmessage = t.step_func(function(e) {assert_equals("primitive string", e.data, "\"primitive string\" === event.data"); t.done(); });
+ t.step(function() { worker.postMessage("primitive string");});
+ },
+ function() {
+ var t = async_test("Primitive integer is cloned");
+ t.id = 1;
+ worker.onmessage = t.step_func(function(e) {assert_equals(2000, e.data, "2000 === event.data"); t.done(); });
+ t.step(function() { worker.postMessage(2000);});
+ },
+ function() {
+ var t = async_test("Primitive floating point is cloned");
+ t.id = 2;
+ worker.onmessage = t.step_func(function(e) {assert_equals(111.456, e.data, "111.456 === event.data"); t.done(); });
+ t.step(function() { worker.postMessage(111.456);});
+ },
+ function() {
+ var t = async_test("Primitive floating point (negative) is cloned");
+ t.id = 3;
+ worker.onmessage = t.step_func(function(e) {assert_equals(-111.456, e.data, "-111.456 === event.data"); t.done(); });
+ t.step(function() { worker.postMessage(-111.456);});
+ },
+ function() {
+ var t = async_test("Primitive number (hex) is cloned");
+ t.id = 4;
+ worker.onmessage = t.step_func(function(e) {assert_equals(0xAB25, e.data, "0xAB25 === event.data"); t.done(); });
+ t.step(function() { worker.postMessage(0xAB25);});
+ },
+ function() {
+ var t = async_test("Primitive number (scientific) is cloned");
+ t.id = 5;
+ worker.onmessage = t.step_func(function(e) {assert_equals(15e2, e.data, "15e2 === event.data"); t.done(); });
+ t.step(function() { worker.postMessage(15e2);});
+ },
+ function() {
+ var t = async_test("Primitive boolean is cloned");
+ t.id = 6;
+ worker.onmessage = t.step_func(function(e) {assert_equals(false, e.data, "false === event.data"); t.done(); });
+ t.step(function() { worker.postMessage(false);});
+ },
+ function() {
+ var t = async_test("Instance of Boolean is cloned");
+ t.id = 7;
+ var obj;
+ t.step(function() {obj = new Boolean(false);});
+ worker.onmessage = t.step_func(function(e) {
+ assert_equals(obj.constructor, e.data.constructor, "Boolean === event.data.constructor");
+ assert_equals(obj.valueOf(), e.data.valueOf(), "(new Boolean(false)).valueof() === event.data.valueOf()");
+ t.done();
+ });
+ t.step(function() { worker.postMessage(obj);});
+ },function() {
+ var t = async_test("Instance of Number is cloned");
+ t.id = 8;
+ var obj;
+ t.step(function() {obj = new Number(2000);});
+ worker.onmessage = t.step_func(function(e) {
+ assert_equals(obj.constructor, e.data.constructor, "Number === event.data.constructor");
+ assert_equals(obj.valueOf(), e.data.valueOf(), "(new Number(2000)).valueof() === event.data.valueOf()");
+ t.done();
+ });
+ t.step(function() { worker.postMessage(obj);});
+ },
+ function() {
+ var t = async_test("Instance of String is cloned");
+ t.id = 9;
+ var obj;
+ t.step(function() { obj = new String("String Object");});
+ worker.onmessage = t.step_func(function(e) {
+ assert_equals(obj.constructor, e.data.constructor, "String === event.data.constructor");
+ assert_equals(obj.valueOf(), e.data.valueOf(), "(new String(\"String Object\")).valueof() === event.data.valueOf()");
+ t.done();
+ });
+ t.step(function() { worker.postMessage(obj);});
+ },
+ function() {
+ var t = async_test("Instance of Date is cloned");
+ t.id = 10;
+ var obj;
+ t.step(function() { obj= new Date(2011,1,1);});
+ worker.onmessage = t.step_func(function(e) {
+ assert_equals(obj.constructor, e.data.constructor, "Date === event.data.constructor");
+ assert_equals(obj.valueOf(), e.data.valueOf(), "(new Date(2011,1,1)).valueof() === event.data.valueOf()");
+ t.done();
+ });
+ t.step(function() { worker.postMessage(obj);});
+ },
+ function() {
+ var t = async_test("Instance of RegExp is cloned");
+ t.id = 11;
+ var obj;
+ t.step(function() {obj = new RegExp("w3+c","g","i");});
+ worker.onmessage = t.step_func(function(e) {
+ assert_equals(obj.constructor, e.data.constructor, "RegExp === event.data.constructor");
+ assert_equals(obj.source, e.data.source, "canon.source === event.data.source");
+ assert_equals(obj.multiline, e.data.multiline, "canon.multiline === event.data.multiline");
+ assert_equals(obj.global, e.data.global, "canon.global === event.data.global");
+ assert_equals(obj.ignoreCase, e.data.ignoreCase, "canon.ignoreCase === event.data.ignoreCase");
+ t.done();
+ });
+ t.step(function() { worker.postMessage(obj);});
+ },
+ function() {
+ var t = async_test("Value 'null' is cloned");
+ t.id = 12;
+ worker.onmessage = t.step_func(function(e) {assert_equals(null, e.data, "null === event.data"); t.done(); });
+ t.step(function() { worker.postMessage(null);});
+ },
+ function() {
+ var t = async_test("Value 'undefined' is cloned");
+ t.id = 13;
+ worker.onmessage = t.step_func(function(e) {assert_equals(undefined, e.data, "undefined === event.data"); t.done(); });
+ t.step(function() { worker.postMessage(undefined);});
+ },
+ function() {
+ var t = async_test("Object properties are cloned");
+ t.id = 14;
+ var obj;
+ t.step(function() {
+ obj= {};
+ obj.a = "test";
+ obj.b = 2;
+ obj["child"] = 3;
+ });
+ worker.onmessage = t.step_func(function(e) {
+ assert_equals(obj.constructor, e.data.constructor, "canon.constructor === event.data.constructor");
+ assert_equals(obj.a, e.data.a, "canon.a === event.data.a");
+ assert_equals(obj.b, e.data.b, "canon.b === event.data.b");
+ assert_equals(obj.child, e.data.child, "canon.child === e.data.child");
+ t.done();
+ });
+ t.step(function() { worker.postMessage(obj);});
+ },
+ function() {
+ var t = async_test("Prototype chains are not walked.");
+ t.id = 15;
+ function Custom() {
+ this.a = "hello";
+ }
+
+ var obj;
+ t.step(function() {
+ Object.defineProperty(Custom.prototype, "b", { enumerable: true, value: 100 });
+ obj = new Custom();
+ });
+ worker.onmessage = t.step_func(function(e) {
+ assert_not_equals(obj.constructor, e.data.constructor, "canon.constructor !== event.data.constructor");
+ assert_equals(Object, e.data.constructor, "Object === e.data.constructor");
+ assert_equals(obj.a, e.data.a, "canon.a === e.data.a");
+ assert_equals(undefined, e.data.b, "undefined === e.data.b");
+ t.done();
+ });
+ t.step(function() { worker.postMessage(obj);});
+ },
+ function() {
+ var t = async_test("Property descriptors of Objects are not cloned");
+ t.id = 16;
+ var obj;
+ t.step(function() {
+ obj = {};
+ Object.defineProperty(obj, "a", { enumerable: true, writable: false, value: 100 });
+ });
+ worker.onmessage = t.step_func(function(e) {
+ var des = Object.getOwnPropertyDescriptor(e.data, "a");
+ assert_equals(obj.constructor, e.data.constructor, "canon.constructor === event.data.constructor");
+ assert_true(des.writable, "Descriptor is writable");
+ t.done();
+ });
+ t.step(function() { worker.postMessage(obj);});
+ },
+ function() {
+ var t = async_test("Cycles are preserved in Objects");
+ t.id = 17;
+ var obj;
+ t.step(function() {
+ obj = {};
+ obj.a = obj;
+ });
+ worker.onmessage = t.step_func(function(e) {
+ assert_equals(obj.constructor, e.data.constructor, "canon.constructor === event.data.constructor");
+ assert_equals(e.data, e.data.a, "cycle is preserved");
+ t.done();
+ });
+ t.step(function() { worker.postMessage(obj);});
+ },
+ function() {
+ var t = async_test("Identity of duplicates is preserved");
+ t.id = 18;
+ var ref;
+ var obj;
+ t.step(function() {
+ ref = {};
+ ref.called = 0;
+ Object.defineProperty(ref, "child", {get: function(){this.called++;}, enumerable: true});
+
+ obj = {a:ref, b:ref};
+ });
+ worker.onmessage = t.step_func(function(e) {
+ assert_equals(obj.constructor, e.data.constructor, "canon.constructor === event.data.constructor");
+ assert_equals(e.data.b.called, 0, "e.data.b.called === 0");
+ t.done();
+ });
+ t.step(function() { worker.postMessage(obj);});
+ },
+ function() {
+ var t = async_test("Property order is preserved");
+ t.id = 19;
+ var obj;
+ t.step(function() {
+ obj = { "a": "hello", "b": "w3c", "c": "and world" };
+ obj["a"] = "named1";
+ });
+ worker.onmessage = t.step_func(function(e) {
+ assert_equals(obj.constructor, e.data.constructor, "canon.constructor === event.data.constructor");
+ var canonNames = Object.getOwnPropertyNames(obj);
+ var testNames = Object.getOwnPropertyNames(e.data);
+ for (var i in canonNames) {
+ assert_equals(canonNames[i], testNames[i], "canonProperty["+i+"] === dataProperty["+i+"]");
+ }
+ t.done();
+ });
+ t.step(function() { worker.postMessage(obj);});
+ },
+ function() {
+ var t = async_test("Enumerable properties of Arrays are cloned");
+ t.id = 20;
+ var obj;
+ t.step(function() {
+ obj = [0,1];
+ obj["a"] = "named1";
+ });
+ worker.onmessage = t.step_func(function(e) {
+ assert_equals(obj.constructor, e.data.constructor, "canon.constructor === event.data.constructor");
+ assert_equals(e.data["a"], "named1", "e.data[\"a\"] === \"named1\"");
+ assert_equals(e.data[0], 0, "e.data[0] === 0");
+ assert_equals(e.data[1], 1, "e.data[1] === 1");
+ t.done();
+ });
+ t.step(function() { worker.postMessage(obj);});
+ },
+ function() {
+ var t = async_test("Property descriptors of Arrays are not cloned");
+ t.id = 21;
+ var obj;
+ t.step(function() {
+ obj = [0, 1];
+ Object.defineProperty(obj, "2", { enumerable: true, writable: false, value: 100 });
+ });
+ worker.onmessage = t.step_func(function(e) {
+ assert_equals(obj.constructor, e.data.constructor, "canon.constructor === event.data.constructor");
+ assert_equals(e.data[0], 0, "e.data[0] === 0");
+ assert_equals(e.data[1], 1, "e.data[1] === 1");
+ var des = Object.getOwnPropertyDescriptor(e.data, "2");
+ assert_true(des.writable, "Descriptor is writable");
+ t.done();
+ });
+ t.step(function() { worker.postMessage(obj);});
+ },
+ function() {
+ var t = async_test("Cycles are preserved in Arrays");
+ t.id = 22;
+ var obj;
+ t.step(function() {
+ obj = [0,1];
+ obj[2] = obj;
+ });
+ worker.onmessage = t.step_func(function(e) {
+ assert_equals(obj.constructor, e.data.constructor, "canon.constructor === event.data.constructor");
+ assert_equals(e.data[0], 0, "e.data[0] === 0");
+ assert_equals(e.data[1], 1, "e.data[1] === 1");
+ assert_equals(e.data[2], e.data, "e.data[2] === e.data");
+ t.done();
+ });
+ t.step(function() { worker.postMessage(obj);});
+ },
+
+ function() {
+ var t = async_test("ImageData object can be cloned");
+ t.id = 23;
+ var obj;
+ t.step(function() {
+ var canvas = document.createElement("canvas");
+ canvas.width = 40;
+ canvas.height = 40;
+ var context = canvas.getContext('2d');
+ obj = context.createImageData(40, 40);
+ assert_true(window.hasOwnProperty("ImageData"), "ImageData constructor must be present");
+ assert_true(obj instanceof ImageData, "ImageData must be returned by .createImageData");
+ });
+ worker.onmessage = t.step_func(function(e) {
+ assert_equals(obj.constructor, e.data.constructor, "canon.constructor === event.data.constructor");
+ assert_not_equals(obj, e.data, "cloned object should be a new instance of ImageData");
+ assert_equals(obj.width, e.data.width, "canon.width === e.data.width");
+ assert_equals(obj.height, e.data.height, "canon.height === e.data.height");
+ assert_array_equals(obj.data, e.data.data, "data arrays are the same");
+ t.done();
+ });
+ t.step(function() { worker.postMessage(obj);});
+ },
+ function() {
+ var t = async_test("ImageData expandos are not cloned");
+ t.id = 24;
+ var obj;
+ t.step(function() {
+ var canvas = document.createElement("canvas");
+ canvas.width = 40;
+ canvas.height = 40;
+ var context = canvas.getContext('2d');
+ obj = context.createImageData(40, 40);
+ assert_true(window.hasOwnProperty("ImageData"), "ImageData constructor must be present");
+ assert_true(obj instanceof ImageData, "ImageData must be returned by .createImageData");
+ obj.foo = "bar";
+ });
+ worker.onmessage = t.step_func(function(e) {
+ assert_equals(obj.constructor, e.data.constructor, "canon.constructor === event.data.constructor");
+ assert_not_equals(obj, e.data, "cloned object should be a new instance of ImageData");
+ assert_equals(obj.width, e.data.width, "canon.width === e.data.width");
+ assert_equals(obj.height, e.data.height, "canon.height === e.data.height");
+ assert_array_equals(obj.data, e.data.data, "data arrays are the same");
+ assert_equals(undefined, e.data.foo, "Expando is lost (undefined === e.data.foo)");
+ t.done();
+ });
+ t.step(function() { worker.postMessage(obj);});
+ },
+ function() {
+ var t = async_test("Window objects cannot be cloned");
+ t.id = 25;
+ worker.onmessage = function() {}; //no op because exception should be thrown.
+ t.step(function() {
+ assert_true(DOMException.hasOwnProperty('DATA_CLONE_ERR'), "DOMException.DATA_CLONE_ERR is present");
+ assert_equals(DOMException.DATA_CLONE_ERR, 25, "DOMException.DATA_CLONE_ERR === 25");
+ assert_throws('DATA_CLONE_ERR', function() {worker.postMessage(window)});
+ });
+ t.done();
+ },
+ function() {
+ var t = async_test("Document objects cannot be cloned");
+ t.id = 26;
+ worker.onmessage = function() {}; //no op because exception should be thrown.
+ t.step(function() {
+ assert_true(DOMException.hasOwnProperty('DATA_CLONE_ERR'), "DOMException.DATA_CLONE_ERR is present");
+ assert_equals(DOMException.DATA_CLONE_ERR, 25, "DOMException.DATA_CLONE_ERR === 25");
+ assert_throws('DATA_CLONE_ERR', function() {worker.postMessage(document)});
+ });
+ t.done();
+ }
+ ];
+ }, {explicit_done:true});
+
+ //Callback for result_callback
+ //queues the next test in the array testCollection
+ //serves to make test execution sequential from the async worker callbacks
+ //alternatively, we would have to create a worker for each test
+ function testFinished(test) {
+ if(test.id < testCollection.length - 1) {
+ //queue the function so that stack remains shallow
+ queue(testCollection[test.id+1]);
+ } else {
+ //when the last test has run, explicitly end test suite
+ done();
+ }
+ }
+ function queue(func) {
+ setTimeout(func, 10);
+ }
+
+ add_result_callback(testFinished);
+ //start the first test manually
+ queue(testCollection[0]);
+
+
+
+
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/xhtml5/colgroup_valign_bottom.xhtml b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/xhtml5/colgroup_valign_bottom.xhtml
new file mode 100644
index 00000000000..84da6dbf6ad
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/xhtml5/colgroup_valign_bottom.xhtml
Binary files differ
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/xhtml5/colgroup_valign_top.xhtml b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/xhtml5/colgroup_valign_top.xhtml
new file mode 100644
index 00000000000..83b8c62e555
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Microsoft/xhtml5/colgroup_valign_top.xhtml
Binary files differ
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/001.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/001.html
new file mode 100644
index 00000000000..665019ed015
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/001.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: inline in markup </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script>log('inline script #1');</script>
+ <script>log('inline script #2');</script>
+
+ <script type="text/javascript">
+
+ var t = async_test()
+
+
+ function test() {
+ assert_array_equals(eventOrder, ['inline script #1', 'inline script #2' ]);
+ t.done();
+}
+ onload = t.step_func(test)
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/002.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/002.html
new file mode 100644
index 00000000000..dcaa163ea70
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/002.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: external in markup </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script src="scripts/include-1.js"></script>
+ <script src="scripts/include-2.js"></script>
+
+ <script type="text/javascript">
+
+ var t = async_test()
+
+
+ function test() {
+ assert_array_equals(eventOrder, ['external script #1', 'external script #2' ]);
+ t.done();
+}
+ onload = t.step_func(test)
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/003.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/003.html
new file mode 100644
index 00000000000..053dd6aca4d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/003.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: inline+external in markup </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script>log('inline script #1')</script>
+ <script src="scripts/include-2.js"></script>
+
+ <script type="text/javascript">
+
+ var t = async_test()
+
+
+ function test() {
+ assert_array_equals(eventOrder, ['inline script #1', 'external script #2' ]);
+ t.done();
+}
+ onload = t.step_func(test)
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/004.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/004.html
new file mode 100644
index 00000000000..838c2feb78b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/004.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: external+inline in markup </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script src="scripts/include-1.js"></script>
+ <script>log('inline script #2')</script>
+
+ <script type="text/javascript">
+ var t = async_test()
+
+ function test() {
+ assert_array_equals(eventOrder, ['external script #1', 'inline script #2' ]);
+ t.done();
+}
+ onload = t.step_func(test)
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/005.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/005.html
new file mode 100644
index 00000000000..b0411284aa9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/005.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: document.write inline in markup </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script>log('inline script #1');
+ document.write( '<script>log(\'doc write script\')<\/script>' );
+ log('end script #1');
+ </script>
+
+ <script type="text/javascript">
+ var t = async_test()
+
+ function test() {
+ assert_array_equals(eventOrder, ['inline script #1', 'doc write script', 'end script #1' ]);
+ t.done();
+ }
+ onload = t.step_func(test)
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/006.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/006.html
new file mode 100644
index 00000000000..3f40ef1c174
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/006.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: document.write inline - multiple</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script>log('inline script #1');
+ document.write( '<script>log(\'doc write script 1\')<\/script>' );
+ document.write( '<script>log(\'doc write script 2\')<\/script>' );
+ eval('log(\'eval 1\')');
+ document.write( '<script>log(\'doc write script 3\')<\/script>' );
+ log('end script #1');
+ </script>
+
+ <script type="text/javascript">
+ var t = async_test()
+
+ function test() {
+ assert_array_equals(eventOrder, ['inline script #1', 'doc write script 1','doc write script 2', 'eval 1','doc write script 3', 'end script #1' ]);
+ t.done();
+}
+ onload = t.step_func(test)
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/007.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/007.html
new file mode 100644
index 00000000000..ee99bc36ea1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/007.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: document.write external</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script>log('inline script #1');
+ document.write( '<script src="scripts/include-1.js">log(\'ignore this\')<\/script>' );
+ log('end script #1');
+ </script>
+
+ <script type="text/javascript">
+ var t = async_test()
+
+ function test() {
+ assert_array_equals(eventOrder, ['inline script #1', 'end script #1', 'external script #1' ]);
+ t.done();
+}
+ onload = t.step_func(test)
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/008.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/008.html
new file mode 100644
index 00000000000..9f6b3876e69
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/008.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: document.write external - multiple</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script>log('inline script #1');
+ document.write( '<script src="scripts/include-1.js">log(\'ignore this\')<\/script>' );
+ document.write( '<script src="scripts/include-2.js">log(\'ignore this\')<\/script>' );
+ log('end script #1');
+ </script>
+
+ <script type="text/javascript">
+ var t = async_test()
+
+ function test() {
+ assert_array_equals(eventOrder, ['inline script #1', 'end script #1', 'external script #1', 'external script #2' ]);
+ t.done();
+}
+ onload = t.step_func(test)
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/009.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/009.html
new file mode 100644
index 00000000000..fc62b9d2b7a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/009.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: document.write external - multiple with doc.write</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script>log('inline script #1');
+ document.write( '<script src="scripts/include-1.js">log(\'ignore this\')<\/script>' );
+ document.write( '<script src="scripts/include-3.js">log(\'ignore this\')<\/script>' );
+ document.write( '<script src="scripts/include-2.js">log(\'ignore this\')<\/script>' );
+ log('end script #1');
+ </script>
+
+ <script type="text/javascript">
+ var t = async_test()
+
+ function test() {
+ assert_array_equals(eventOrder, ['inline script #1', 'end script #1', 'external script #1', 'external script before doc write', 'document.write external script', 'external script after doc write', 'external script #2' ]);
+ t.done();
+}
+ onload = t.step_func(test)
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/010.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/010.html
new file mode 100644
index 00000000000..9c5fd849b99
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/010.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: document.write external + inline - multiple with doc.write</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script>log('inline script #1');
+ document.write( '<script src="scripts/include-1.js">log(\'ignore this\')<\/script>' );
+ document.write( '<script>log(\'inline with doc.write #1\')<\/script>' );
+ document.write( '<script src="scripts/include-2.js">log(\'ignore this\')<\/script>' );
+ log('end script #1');
+ </script>
+
+ <script type="text/javascript">
+ var t = async_test()
+
+ function test() {
+ assert_array_equals(eventOrder, ['inline script #1', 'end script #1', 'external script #1', 'inline with doc.write #1', 'external script #2']);
+ t.done();
+}
+ onload = t.step_func(test)
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/011.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/011.html
new file mode 100644
index 00000000000..7bc10995da5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/011.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: document.write external + inline - multiple with doc.write + subsequent markup</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script>log('inline script #1');
+ document.write( '<script src="scripts/include-1.js">log(\'ignore this\')<\/script>' );
+ document.write( '<script>log(\'inline with doc.write #1\')<\/script>' );
+ document.write( '<script src="scripts/include-2.js">log(\'ignore this\')<\/script>' );
+ log('end script #1');
+ </script>
+
+ <script type="text/javascript">
+ log( 'inline script #2' );
+ var t = async_test()
+
+ function test() {
+ assert_array_equals(eventOrder, ['inline script #1', 'end script #1', 'external script #1', 'inline with doc.write #1', 'external script #2', 'inline script #2']);
+ t.done();
+}
+ onload = t.step_func(test)
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/012.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/012.html
new file mode 100644
index 00000000000..41c3d066dd6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/012.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: document.write external and onload events </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script>log('inline script #1');
+ document.write( '<script src="scripts/include-1.js" onload = "log(\'include-1 load\')">log(\'ignore this\')<\/script>' )
+ document.write( '<script src="scripts/include-3.js" onload = "log(\'include-3 load\')"><\/script>' )
+ document.write( '<script src="scripts/include-2.js" onload = "log(\'include-2 load\')">log(\'ignore this\')<\/script>' )
+ log('end script #1');
+ </script>
+
+ <script type="text/javascript">
+ log( 'inline script #2' );
+ var t = async_test()
+
+ function test() {
+ assert_array_equals(eventOrder, ['inline script #1', 'end script #1', 'external script #1', 'include-1 load', 'external script before doc write', 'document.write external script', 'external script after doc write', 'include-3 load', 'external script #2', 'include-2 load', 'inline script #2']);
+ t.done();
+}
+ onload = t.step_func(test)
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/013.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/013.html
new file mode 100644
index 00000000000..a3a9b825505
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/013.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: DOM added inline script earlier in document</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script>log('inline script #1');
+ testlib.addScript('log(\'head script #1\')', {}, document.getElementsByTagName('head')[0], false);
+ log('end script #1');
+ </script>
+
+ <script type="text/javascript">
+ log( 'inline script #2' );
+ var t = async_test()
+
+ function test() {
+ assert_array_equals(eventOrder, ['inline script #1', 'head script #1','end script #1', 'inline script #2']);
+ t.done();
+}
+ onload = t.step_func(function(){setTimeout(t.step_func(test), 100); })
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/014.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/014.html
new file mode 100644
index 00000000000..eae7076acd0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/014.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: SCRIPT elements that move themselves in DOM </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script>log('inline script #1');
+ document.getElementsByTagName('head')[0].appendChild(document.getElementsByTagName('script')[2]);
+ log('end script #1');
+ </script>
+
+ <script type="text/javascript">
+ log('script #2');
+ var t = async_test()
+
+ function test() {
+ assert_array_equals(eventOrder, ['inline script #1', 'end script #1', 'script #2']);
+ t.done();
+}
+ onload = t.step_func(test)
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/015.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/015.html
new file mode 100644
index 00000000000..88c28a8bce5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/015.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: DOM added inline+external+inline script earlier in document</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script>log('inline script #1');
+ testlib.addScript('log(\'head script #1\')', {}, document.getElementsByTagName('head')[0], false);
+ var s = testlib.addScript('', { 'src':'scripts/include-1.js' }, document.getElementsByTagName('head')[0], false);
+ testlib.addScript('log(\'head script #2\')', {}, document.getElementsByTagName('head')[0], false);
+ log('end script #1');
+ </script>
+
+ <script type="text/javascript">
+ log( 'inline script #2' );
+ var t = async_test()
+
+ ///XXX I think the spec allows this case to race
+ onload = function(){
+ setTimeout(t.step_func(
+ function() {
+ assert_any(assert_array_equals, eventOrder, [['inline script #1', 'head script #1', 'head script #2', 'end script #1', 'external script #1', 'inline script #2'],
+ ['inline script #1', 'head script #1', 'head script #2', 'end script #1', 'inline script #2', 'external script #1']]);
+ t.done();
+ }),
+ 100);}
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/015a.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/015a.html
new file mode 100644
index 00000000000..05113feb7ea
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/015a.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: DOM added inline+external+inline script earlier in document</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script>log('inline script #1');
+ testlib.addScript('log(\'head script #1\')', {}, document.getElementsByTagName('head')[0], false);
+ var s = testlib.addScript('', { 'src':'scripts/include-1.js?pipe=trickle(d1)' }, document.getElementsByTagName('head')[0], false);
+ testlib.addScript('log(\'head script #2\')', {}, document.getElementsByTagName('head')[0], false);
+ log('end script #1');
+ </script>
+
+ <script type="text/javascript">
+ log( 'inline script #2' );
+ var t = async_test()
+
+ function test() {
+ assert_array_equals(eventOrder, ['inline script #1', 'head script #1', 'head script #2', 'end script #1', 'inline script #2', 'external script #1']);
+ t.done();
+ }
+ onload = function(){setTimeout(t.step_func(function() {test.apply(t)}), 2000); }
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/016.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/016.html
new file mode 100644
index 00000000000..7395600215f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/016.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: DOM added inline script later in document</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script>log('inline script #1');
+ testlib.addScript('log(\'body script #1\')', {}, document.body, false);
+ log('end script #1');
+ </script>
+
+ <script type="text/javascript">
+ log( 'inline script #2' );
+ var t = async_test()
+
+ function test() {
+ assert_array_equals(eventOrder, ['inline script #1', 'body script #1', 'end script #1', 'inline script #2']);
+ t.done();
+}
+ onload = t.step_func(function(){setTimeout(t.step_func(test), 100); })
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/017.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/017.html
new file mode 100644
index 00000000000..78a0f7b1a6f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/017.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: multiple DOM added scripts later in document</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script>log('inline script #1');
+ testlib.addScript('log(\'body script #1\')', {}, document.getElementsByTagName('body')[0], false);
+ testlib.addScript('', { 'src':'scripts/include-1.js' }, document.getElementsByTagName('body')[0], false);
+ testlib.addScript('log(\'body script #2\')', {}, document.getElementsByTagName('body')[0], false);
+ log('end script #1');
+ </script>
+
+ <script type="text/javascript">
+ log( 'inline script #2' );
+ var t = async_test()
+
+ //The order of the external script vs the second inline script is undefined because the added script is async by default
+ //But we expect most UAs to have the second order
+ onload = function() {setTimeout(t.step_func(function() {
+ assert_any(assert_array_equals, eventOrder, [
+ ['inline script #1', 'body script #1', 'body script #2', 'end script #1', 'external script #1', 'inline script #2'],
+ ['inline script #1', 'body script #1', 'body script #2', 'end script #1', 'inline script #2', 'external script #1']]);
+ t.done();
+ }), 100);}
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/018.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/018.html
new file mode 100644
index 00000000000..793343c43cf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/018.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: DOM added scripts and doc.write</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script>log('inline script #1');
+ testlib.addScript('', { 'src':'scripts/include-3.js' }, document.getElementsByTagName('head')[0], false);
+ testlib.addScript('log(\'body script #2\')', {}, document.getElementsByTagName('body')[0], true);
+ log('end script #1');
+ </script>
+
+ <script type="text/javascript">
+ log( 'inline script #2' );
+ var t = async_test()
+
+ //XXX Need to test this delaying the document after we insert the external script and delaying the external script itself; afaict the spec allows us to race here on whether the document.write
+ //ever actually happens or not according to whether the insertion point is defined at the point at which the script is executed.
+ function test() {
+ assert_any(assert_array_equals, eventOrder, [
+ ['inline script #1', 'body script #2', 'end script #1', 'external script before doc write', 'document.write external script', 'external script after doc write', 'inline script #2'],
+ ['inline script #1', 'body script #2', 'end script #1', 'inline script #2', 'external script before doc write', 'document.write external script', 'external script after doc write'],
+ ['inline script #1', 'body script #2', 'end script #1', 'inline script #2', 'external script before doc write', 'external script after doc write']
+ ]);
+ t.done();
+}
+ onload = t.step_func(function(){setTimeout(test.apply(t), 100); })
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/019.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/019.html
new file mode 100644
index 00000000000..30fa63432c9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/019.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: DOM added scripts and event handling </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script onload="log('inline #1 load')">
+ log('inline script #1');
+ testlib.addScript('', {'src':'scripts/include-1.js', 'onload':function(){log("external #1 load")}}, document.getElementsByTagName('head')[0], false);
+ log('end script #1');
+ </script>
+
+ <script type="text/javascript">
+ log( 'inline script #2' );
+ var t = async_test()
+
+ function test() {
+ assert_any(assert_array_equals, eventOrder, [['inline script #1', 'end script #1', 'external script #1', 'external #1 load', 'inline script #2'],
+ ['inline script #1', 'end script #1', 'inline script #2', 'external script #1', 'external #1 load']
+ ]);
+ t.done();
+}
+ onload = function(){setTimeout(t.step_func(test), 100); }
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/020.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/020.html
new file mode 100644
index 00000000000..abbfbf7db5d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/020.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: DOM added script with data: URL </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+ <script>log('inline script #1');
+ testlib.addScript('', { 'src':'data:text/javascript,log("data URL script")' }, document.getElementsByTagName('body')[0], true);
+ log('end script #1');
+ </script>
+
+ <script type="text/javascript">
+ log( 'inline script #2' );
+ var t = async_test()
+
+ function test() {
+ assert_any(assert_array_equals, eventOrder, [['inline script #1', 'end script #1', 'data URL script', 'inline script #2'],
+ ['inline script #1', 'end script #1', 'inline script #2', 'data URL script']]);
+ t.done();
+ }
+ onload = function() {setTimeout( t.step_func(test), 100); }
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/021.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/021.html
new file mode 100644
index 00000000000..92b5f064178
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/021.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: DOM added script with javascript: URL </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+ <script>log('inline script #1');
+ testlib.addScript('', { 'src':'javascript:log("JS URL script")' }, document.getElementsByTagName('body')[0], true);
+ log('end script #1');
+ </script>
+
+ <script type="text/javascript">
+ log( 'inline script #2' );
+ var t = async_test()
+
+ function test() {
+ assert_array_equals(eventOrder, ['inline script #1', 'end script #1', /*'JS URL script',*/ 'inline script #2']);
+ t.done();
+/* pass condition changed 2010-12-01 due to CT-198 */
+
+ }
+ onload = t.step_func(function(){setTimeout( test, 100); })
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/022.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/022.html
new file mode 100644
index 00000000000..f56b43171b0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/022.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: DOM added script, late .src </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+ <script>log('inline script #1');
+ var script = testlib.addScript('', { }, document.getElementsByTagName('body')[0], false);
+ script.src='scripts/include-1.js';
+ log('end script #1');
+ </script>
+
+ <script type="text/javascript">
+ log( 'inline script #2' );
+ var t = async_test()
+
+ onload = function() {setTimeout(t.step_func(
+ function() {
+ assert_any(assert_array_equals, eventOrder, [['inline script #1', 'end script #1', 'external script #1', 'inline script #2'],
+ ['inline script #1', 'end script #1', 'inline script #2', 'external script #1']]);
+ t.done()
+ }),
+ 100)}
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/023.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/023.html
new file mode 100644
index 00000000000..dc687ffe4d5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/023.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: DOM added script, even later .src </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+ <script>log('inline script #1');
+ var script = testlib.addScript('', { }, document.getElementsByTagName('body')[0], false);
+ log('end script #1');
+ </script>
+
+ <script type="text/javascript">
+ log( 'inline script #2' );
+ var t = async_test()
+
+ function test() {
+ assert_array_equals(eventOrder, ['inline script #1', 'end script #1', 'inline script #2', 'external script #1']);
+ t.done();
+}
+ onload = t.step_func(function(){
+ script.src='scripts/include-1.js';
+ script.onload = t.step_func(test);
+ })
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/024.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/024.html
new file mode 100644
index 00000000000..37146f8463d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/024.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: DOM added script, .src set twice</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+ <script>log('inline script #1');
+ var script = testlib.addScript('', { }, document.getElementsByTagName('body')[0], false);
+ script.src='scripts/include-1.js';
+ log('end script #1');
+ </script>
+
+ <script type="text/javascript">
+ log( 'inline script #2' );
+ var t = async_test()
+
+ function test() {
+ assert_any(assert_array_equals, eventOrder, [['inline script #1', 'end script #1', 'external script #1', 'inline script #2'],
+ ['inline script #1', 'end script #1', 'inline script #2', 'external script #1']]);
+ t.done();
+ }
+ onload = t.step_func(function(){
+ script.src='scripts/include-2.js'; // needs to be ignored, script already "is executed"
+ setTimeout(t.step_func(test), 100);
+ })
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/025.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/025.html
new file mode 100644
index 00000000000..182be3aef15
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/025.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: DOM added script, .src set on script with content</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+ <script>log('inline script #1');
+ var script = testlib.addScript('log("inline DOM script #1")', { }, document.getElementsByTagName('body')[0], false);
+ script.src='scripts/include-1.js';
+ log('end script #1');
+ </script>
+
+ <script type="text/javascript">
+ log( 'inline script #2' );
+ var t = async_test()
+
+ function test() {
+ assert_array_equals(eventOrder, ['inline script #1', 'inline DOM script #1', 'end script #1', 'inline script #2']);
+ t.done();
+}
+ onload = t.step_func(function(){
+ setTimeout(t.step_func(test), 100);
+ })
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/026.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/026.html
new file mode 100644
index 00000000000..70fac7c7f4b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/026.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: doc write added script, .src set later</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+ <script>log('inline script #1');
+ var t = async_test();
+ document.write('<script><\/script>');
+ var scripts = document.getElementsByTagName('script');
+ scripts[scripts.length - 1].src = 'scripts/include-1.js';
+ log('end script #1');
+ </script>
+
+ <script type="text/javascript">
+ log( 'inline script #2' );
+
+ onload = function() {
+ setTimeout(
+ t.step_func(function() {
+ assert_any(assert_array_equals, eventOrder, [['inline script #1', 'end script #1', 'external script #1', 'inline script #2'],
+ ['inline script #1', 'end script #1', 'inline script #2', 'external script #1']]);
+ t.done();
+ }),
+ 100);
+ }
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/027.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/027.html
new file mode 100644
index 00000000000..d3181d587f5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/027.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: doc write added script with content, .src set later</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+ <script>log('inline script #1');
+ document.write('<script>log(\'doc.write script\')<\/script>');
+ log('end script #1');
+ </script>
+
+ <script type="text/javascript">
+ log( 'inline script #2' );
+ document.getElementsByTagName('script')[4].src='scripts/include-1.js';
+ var t = async_test()
+
+ function test() {
+ assert_array_equals(eventOrder, ['inline script #1', 'doc.write script', 'end script #1', 'inline script #2']);
+ t.done();
+}
+ onload = t.step_func(function(){
+ setTimeout(t.step_func(test), 100);
+ })
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/028.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/028.html
new file mode 100644
index 00000000000..5d0207d85b3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/028.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: javascript: URL</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+ <script>log('inline script #1');
+ window.location.replace('javascript:log(\'JS URL\')');
+ log('end script #1');
+ </script>
+
+ <script type="text/javascript">
+ log( 'inline script #2' );
+ var t = async_test()
+
+ function test() {
+ assert_any(assert_array_equals, eventOrder, [
+ ['inline script #1', 'end script #1', 'JS URL', 'inline script #2'],
+ ['inline script #1', 'end script #1', 'inline script #2', 'JS URL']]);
+ t.done();
+ }
+ onload = t.step_func(test)
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/029.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/029.html
new file mode 100644
index 00000000000..b3beeaef360
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/029.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: javascript: URL in HREF</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+ <p><a href="javascript:log('JS URL')"></a></p>
+ <script>log('inline script #1');
+ if(document.links[0].click){
+ document.links[0].click();
+ }else{
+ var evt = document.createEvent("MouseEvents");
+ evt.initMouseEvent("click", true, true, window,
+ 0, 0, 0, 0, 0, false, false, false, false, 0, null);
+ document.links[0].dispatchEvent(evt);
+ }
+ log('end script #1');
+ </script>
+
+ <script type="text/javascript">
+ log( 'inline script #2' );
+ var t = async_test()
+
+ function test() {
+ assert_any(assert_array_equals, eventOrder, [
+ ['inline script #1', 'end script #1', 'JS URL', 'inline script #2'],
+ ['inline script #1', 'end script #1', 'inline script #2', 'JS URL']]);
+ t.done();
+ }
+ onload = t.step_func(test)
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/030.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/030.html
new file mode 100644
index 00000000000..9c83b9a2619
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/030.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: javascript: URL in HREF, onclick handler</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+ <p><a href="javascript:log('JS URL')" onclick="log('click event');return true;"></a></p>
+ <script>log('inline script #1');
+ if(document.links[0].click){
+ document.links[0].click();
+ }else{
+ var evt = document.createEvent("MouseEvents");
+ evt.initMouseEvent("click", true, true, window,
+ 0, 0, 0, 0, 0, false, false, false, false, 0, null);
+ document.links[0].dispatchEvent(evt);
+ }
+ log('end script #1');
+ </script>
+
+ <script type="text/javascript">
+ log( 'inline script #2' );
+ var t = async_test()
+
+ var w = window;
+ onload = function() {setTimeout(
+ t.step_func(function() {
+ w.assert_any(w.assert_array_equals, w.eventOrder,
+ [['inline script #1', 'click event', 'end script #1', 'JS URL', 'inline script #2'],
+ ['inline script #1', 'click event', 'end script #1', 'inline script #2', 'JS URL']]);
+ t.done();
+ }), 200);
+ }
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/031.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/031.html
new file mode 100644
index 00000000000..166dda47541
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/031.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: focus and blur events</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+ <form><input type="button" onclick="log('click event')" onfocus="log('focus event')" onblur="log('blur event')"><input type="button" onfocus="log('focus el 2 event')" onblur="log('blur event')"></form>
+ <script>log('inline script #1');
+ document.forms[0][0].focus();
+ document.forms[0][1].click();
+ document.forms[0][1].focus();
+ log('end script #1');
+ </script>
+
+ <script type="text/javascript">
+ log('inline script #2');
+ var t = async_test()
+
+ function test() {
+ assert_array_equals(eventOrder, ['inline script #1', 'focus event', 'blur event', 'focus el 2 event', 'end script #1', 'inline script #2']);
+ t.done();
+ }
+ onload = t.step_func(function(){setTimeout(t.step_func(test), 200);})
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/032.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/032.html
new file mode 100644
index 00000000000..a012ab29e57
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/032.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: innerHTML and scripts</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+ <div></div>
+ <script>log('inline script #1');
+ // script added with innerHTML should not run..
+ document.getElementsByTagName('div')[1].innerHTML = '<script>log("innerHTML script runs")<\/script><script src="scripts/include-1.js"><\/script>';
+ log('end script #1');
+ </script>
+
+ <script type="text/javascript">
+ log( 'inline script #2' );
+ var t = async_test()
+
+ function test() {
+ assert_array_equals(eventOrder, ['inline script #1', 'end script #1', 'inline script #2']);
+ t.done();
+}
+ onload = t.step_func(function(){setTimeout(t.step_func(test), 200);})
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/033.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/033.html
new file mode 100644
index 00000000000..035bf0a2311
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/033.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: innerHTML and scripts moved in DOM</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+ <div></div>
+ <script>log('inline script #1');
+ // script added with innerHTML should not run..
+ document.getElementsByTagName('div')[0].innerHTML = '<script>log("innerHTML script runs")<\/script><script src="scripts/include-1.js"><\/script>';
+ try{
+ document.body.appendChild( document.getElementsByTagName('div')[0].firstChild );
+ document.body.appendChild( document.getElementsByTagName('div')[0].firstChild );
+ }catch(e){
+ log('ERROR while testing');
+ }
+ log('end script #1');
+ </script>
+
+ <script type="text/javascript">
+ log( 'inline script #2' );
+ var t = async_test()
+
+ function test() {
+ assert_array_equals(eventOrder, ['inline script #1', 'end script #1', 'inline script #2']);
+ t.done();
+}
+ onload = t.step_func(function(){setTimeout(t.step_func(test), 200);})
+ </script>
+
+</body></html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/034.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/034.html
new file mode 100644
index 00000000000..8dcb4294d56
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/034.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: innerHTML adding frames with JS in</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+ <div></div>
+ <script>log('inline script #1');
+ document.getElementsByTagName('div')[1].innerHTML = '<iframe src="pages/helloworld.html"></iframe>';
+ log('end script #1');
+ </script>
+
+ <script type="text/javascript">
+ log( 'inline script #2' );
+ var t = async_test()
+
+ function test() {
+ assert_array_equals(eventOrder, ['inline script #1', 'end script #1', 'inline script #2', 'frame/popup script']);
+ t.done();
+}
+ onload = t.step_func(function(){setTimeout(t.step_func(test), 200);})
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/035.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/035.html
new file mode 100644
index 00000000000..540439e7e23
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/035.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: innerHTML adding frames with JS in and moving scripts</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+ <div></div>
+ <script>log('inline script #1');
+ document.getElementsByTagName('div')[1].innerHTML = '<iframe src="pages/helloworld.html"></iframe>';
+ log('end script #1');
+ </script>
+
+ <script type="text/javascript">
+ log( 'inline script #2' );
+ var t = async_test()
+
+ function test() {
+ assert_array_equals(eventOrder, ['inline script #1', 'end script #1', 'inline script #2', 'frame/popup script']);
+ t.done();
+/*, ['inline script #1', 'end script #1', 'frame/popup script', 'inline script #2'] */
+
+ }
+ onload = t.step_func(function(){
+ try{
+ document.body.appendChild(document.importNode( top.frames[0].document.getElementsByTagName('script')[0], true ));
+ }catch(e){ log('ERROR - tested functionality not supported'); }
+ setTimeout(t.step_func(test), 200);
+ });
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/036.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/036.html
new file mode 100644
index 00000000000..0eb4a6eb36e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/036.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: DOM cloning</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+ <div></div>
+ <script>log('inline script #1');
+ testlib.addScript('log(\'head script #1\')', {}, document.getElementsByTagName('head')[0], true);
+ log('end script #1');
+ </script>
+
+ <script type="text/javascript">
+ log( 'inline script #2' );
+ try{
+ var script = document.getElementsByTagName('script')[0].cloneNode(true);
+ document.body.appendChild(script);
+ }catch(e){ log('ERROR - tested functionality not supported'); }
+ var t = async_test()
+
+ function test() {
+ assert_array_equals(eventOrder, ['inline script #1', 'head script #1', 'end script #1', 'inline script #2' ]);
+ t.done();
+}
+ onload = t.step_func(function(){
+ setTimeout(t.step_func(test), 200);
+ });
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/037.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/037.html
new file mode 100644
index 00000000000..aff995b4773
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/037.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: DOM movement with appendChild, inline</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+ <div></div>
+ <script>log('inline script #1');
+ var script = testlib.addScript('log(\'head script #1\')', {}, document.getElementsByTagName('head')[0], true);
+ log('end script #1');
+ </script>
+
+ <script type="text/javascript">
+ log( 'inline script #2' );
+ try{
+ document.body.appendChild(script);
+ }catch(e){ log('ERROR - tested functionality not supported'); }
+ var t = async_test()
+
+ function test() {
+ assert_array_equals(eventOrder, ['inline script #1', 'head script #1', 'end script #1', 'inline script #2' ]);
+ t.done();
+}
+ onload = t.step_func(function(){
+ setTimeout(t.step_func(test), 200);
+ });
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/038.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/038.html
new file mode 100644
index 00000000000..3bbfe4604a7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/038.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: DOM movement with appendChild, external</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+ <div></div>
+ <script>log('inline script #1');
+ var script = testlib.addScript('', { 'src':'scripts/include-1.js' }, document.getElementsByTagName('head')[0], true);
+ log('end script #1');
+ </script>
+
+ <script type="text/javascript">
+ log( 'inline script #2' );
+ try{
+ document.body.appendChild(script);
+ }catch(e){ log('ERROR - tested functionality not supported'); }
+ var t = async_test()
+
+ function test() {
+ assert_any(assert_array_equals, eventOrder, [['inline script #1', 'end script #1', 'external script #1', 'inline script #2'],
+ ['inline script #1', 'end script #1', 'inline script #2', 'external script #1']]);
+ t.done();
+}
+ onload = function() {
+ setTimeout(t.step_func(test), 200);
+ };
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/039.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/039.html
new file mode 100644
index 00000000000..a0abdf1610f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/039.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: IFRAMEs added with DOM</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+ <div></div>
+ <script>log('inline script #1');
+ for( var i=0; i<2; i++ ){
+ var iframe=document.createElement('iframe');
+ document.getElementsByTagName('div')[1].appendChild(iframe);
+ iframe.src='pages/helloworld.html?'+i+'&'+Math.random();
+ }
+ log('end script #1');
+ </script>
+
+ <script type="text/javascript">
+ log( 'inline script #2' );
+ var t = async_test()
+
+ function test() {
+ assert_any(assert_array_equals, eventOrder, [
+ ['inline script #1', 'end script #1', 'inline script #2', 'frame/popup script 0', 'frame/popup script 1'],
+ ['inline script #1', 'end script #1', 'inline script #2', 'frame/popup script 1', 'frame/popup script 0']]);
+ t.done();
+ }
+ onload = t.step_func(function() {
+ setTimeout(t.step_func(test), 200);
+ });
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/040.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/040.html
new file mode 100644
index 00000000000..984bc6689dc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/040.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: IFRAMEs added with DOM (innerHTML), javascript: URL</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+ <div></div>
+ <script>log('inline script #1');
+ document.getElementsByTagName('div')[1].innerHTML = '<iframe src="javascript:parent.log(\'JS URL\');\'<html><script>parent.log(\\\'frame script\\\')<\/script></html>\'"></iframe>';
+ log('end script #1');
+ </script>
+
+ <script type="text/javascript">
+ log( 'inline script #2' );
+ var t = async_test()
+
+ function test() {
+ assert_any(assert_array_equals, eventOrder, [
+ ['inline script #1', 'end script #1', 'JS URL', 'inline script #2', 'frame script'],
+ /* the following combination seems quite unlikely? */
+ ['inline script #1', 'end script #1', 'JS URL', 'frame script', 'inline script #2'],
+ ['inline script #1', 'end script #1', 'inline script #2', 'JS URL', 'frame script']]);
+ t.done();
+}
+ onload = t.step_func(function(){
+ setTimeout(t.step_func(test), 200);
+ });
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/041.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/041.html
new file mode 100644
index 00000000000..c2a0b9bc4ec
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/041.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: document.write scripts that write scripts</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script>log('inline script #1');
+ document.write( '<script>log(\'inline with doc.write #1\'); document.write(\'<script src="scripts/include-4.js"><\\\/script>\');log(\'end inline with doc.write\');<\/script>' );
+ document.write( '<script src="scripts/include-1.js">log(\'ignore this\')<\/script>' );
+ log('end script #1');
+ </script>
+
+ <script type="text/javascript">
+ log( 'inline script #2' );
+ var t = async_test()
+
+ function test() {
+ assert_array_equals(eventOrder, ['inline script #1', 'inline with doc.write #1', 'end inline with doc.write', 'end script #1', 'include-4 before doc write', 'include-4 after doc write', 'external script before doc write', 'document.write external script', 'external script after doc write', 'external script #1', 'inline script #2']);
+ t.done();
+}
+ onload = t.step_func(test)
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/042.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/042.html
new file mode 100644
index 00000000000..e91ea116c4e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/042.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: DOM mutation events when adding scripts: DOMNodeInserted </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script>log('inline script #1');
+ document.addEventListener( 'DOMNodeInserted', function(){ log('DOMNodeInserted'); }, false );
+ testlib.addScript('log(\'head script #1\')', {}, document.getElementsByTagName('head')[0], false);
+ log('end script #1');
+ </script>
+
+ <script type="text/javascript">
+ log( 'inline script #2' );
+ var t = async_test()
+
+ function test() {
+ assert_array_equals(eventOrder, ['inline script #1', 'head script #1', 'DOMNodeInserted', 'end script #1', 'inline script #2']);
+ t.done();
+}
+ onload = t.step_func(test)
+ </script>
+
+</body></html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/043.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/043.html
new file mode 100644
index 00000000000..082ca618bab
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/043.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: DOM mutation events when adding external scripts: DOMNodeInserted </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script>log('inline script #1');
+ document.addEventListener( 'DOMNodeInserted', function(){ log('DOMNodeInserted'); }, false );
+ testlib.addScript('', { src: 'scripts/include-1.js' }, document.getElementsByTagName('head')[0], false);
+ log('end script #1');
+ </script>
+
+ <script type="text/javascript">
+ log( 'inline script #2' );
+ var t = async_test()
+
+ function test() {
+ assert_any(assert_array_equals, eventOrder, [['inline script #1', 'DOMNodeInserted', 'end script #1', 'external script #1', 'inline script #2'],
+ ['inline script #1', 'DOMNodeInserted', 'end script #1', 'inline script #2', 'external script #1']]
+ );
+ t.done();
+ }
+ onload = t.step_func(test)
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/044.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/044.html
new file mode 100644
index 00000000000..a0e1c03b08f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/044.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: DOM mutation events when adding scripts: DOMNodeInsertedIntoDocument </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script>log('inline script #1');
+ testlib.addScript('log(\'head script #1\')', {}, document.getElementsByTagName('head')[0], false, function(s){s.addEventListener( 'DOMNodeInsertedIntoDocument', function(){ log('DOMNodeInsertedIntoDocument'); }, false ); } );
+ log('end script #1');
+ </script>
+
+ <script type="text/javascript">
+ log( 'inline script #2' );
+ var t = async_test()
+
+ function test() {
+ assert_array_equals(eventOrder, ['inline script #1', 'head script #1', 'DOMNodeInsertedIntoDocument', 'end script #1', 'inline script #2']);
+ t.done();
+}
+ onload = t.step_func(test)
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/045.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/045.html
new file mode 100644
index 00000000000..70520d06cb2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/045.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: DOM mutation events when adding external scripts: DOMNodeInsertedIntoDocument </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script>log('inline script #1');
+ testlib.addScript('', {src:'scripts/include-1.js'}, document.getElementsByTagName('head')[0], false, function(s){s.addEventListener( 'DOMNodeInsertedIntoDocument', function(){ log('DOMNodeInsertedIntoDocument'); }, false);});
+ log('end script #1');
+ </script>
+
+ <script type="text/javascript">
+ log( 'inline script #2' );
+ var t = async_test()
+
+ onload = t.step_func(function() {
+ assert_any(assert_array_equals, eventOrder, [['inline script #1', 'DOMNodeInsertedIntoDocument', 'end script #1', 'external script #1', 'inline script #2'],
+ ['inline script #1', 'DOMNodeInsertedIntoDocument', 'end script #1', 'inline script #2', 'external script #1']]);
+ t.done();
+ });
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/046.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/046.html
new file mode 100644
index 00000000000..1598234e1ad
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/046.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: no readystatechange events when adding external scripts </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script>log('inline script #1');
+ testlib.addScript('', {src:'scripts/include-1.js', onreadystatechange:function() {log( 'readystatechange '+ this.readyState );}}, document.getElementsByTagName('head')[0], false );
+ log('end script #1');
+ </script>
+
+ <script type="text/javascript">
+ var t = async_test()
+
+ function test() {
+ assert_array_equals(eventOrder, ['inline script #1', 'end script #1', 'external script #1']);
+ t.done();
+ }
+ onload = t.step_func(test);
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/047.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/047.html
new file mode 100644
index 00000000000..ab758d2f5f6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/047.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: adding and removing external script </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script>log('inline script #1');
+ var script=testlib.addScript('', {src:'scripts/include-1.js'}, document.getElementsByTagName('head')[0], false );
+ script.parentNode.removeChild(script);
+ log('end script #1');
+ </script>
+
+ <script type="text/javascript">
+ var t = async_test()
+
+ function test() {
+ assert_array_equals(eventOrder, ['inline script #1', 'end script #1', 'external script #1']);
+ t.done();
+}
+ onload = t.step_func(test)
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/048.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/048.html
new file mode 100644
index 00000000000..ceb18cae570
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/048.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: adding inline script which sets its own .src </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script>log('inline script #1');
+ var script=testlib.addScript('log(\'HEAD script start\');document.getElementsByTagName(\'script\')[0].src=\'scripts/include-1.js\';log(\'HEAD script end\')', {}, document.getElementsByTagName('head')[0], true );
+ log('end script #1');
+ </script>
+
+ <script type="text/javascript">
+ log( 'inline script #2' );
+ var t = async_test()
+
+ function test() {
+ assert_array_equals(eventOrder, ['inline script #1', 'HEAD script start', 'HEAD script end', 'end script #1', 'inline script #2']);
+ t.done();
+}
+ onload = t.step_func(test)
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/049.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/049.html
new file mode 100644
index 00000000000..65705bc1fb8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/049.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: adding external script but removeAttribute( src ) before it runs</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script>log('inline script #1');
+ var script=testlib.addScript('log(\'HEAD script\');', { src:'scripts/include-1.js' }, document.getElementsByTagName('head')[0], false );
+ script.removeAttribute('src');
+ log('end script #1');
+ </script>
+
+ <script type="text/javascript">
+ var t = async_test()
+
+ function test() {
+ assert_array_equals(eventOrder, ['inline script #1', 'end script #1', 'external script #1']);
+ t.done();
+ }
+ onload = t.step_func(test)
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/050.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/050.html
new file mode 100644
index 00000000000..d6e92c0732d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/050.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: adding external script that removes all scripts from document</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script>log('inline script #1');
+ var script=testlib.addScript('', { src:'scripts/include-5.js' }, document.getElementsByTagName('head')[0], false );
+ // caching might affect whether the below script runs or not. Adding Math.random() makes the test a bit more predictable? :-p
+ var script=testlib.addScript('', { src:'scripts/include-1.js?pipe=trickle(d1)&'+Math.random() }, document.getElementsByTagName('head')[0], false );
+ log('end script #1');
+ </script>
+ <script src="scripts/include-2.js?pipe=trickle(d2)"></script>
+ <script type="text/javascript">
+ var t = async_test()
+
+ function test() {
+ assert_array_equals(eventOrder, ['inline script #1', 'end script #1', 'include-5 before removing scripts', 'include-5 after removing scripts', 'external script #1', 'external script #2']),
+ t.done();
+ }
+ onload = t.step_func(test)
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/051.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/051.html
new file mode 100644
index 00000000000..e97c153b1d0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/051.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: interaction of parsing and script execution - script added through DOM</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script>log('inline script #1');
+ testlib.addScript('', { src: 'scripts/count-script-tags.js' }, document.body, true);
+ log('end script #1');
+ </script>
+
+ <script type="text/javascript">
+ log( 'inline script #2' );
+ var t = async_test()
+
+ function test() {
+ assert_any(assert_array_equals, eventOrder, [['inline script #1', 'end script #1', 'script tags in DOM: 5', 'inline script #2'],
+ ['inline script #1', 'end script #1', 'inline script #2', 'script tags in DOM: 6']]);
+ t.done();
+ }
+ onload = function(){setTimeout(t.step_func(test), 100); }
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/052.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/052.html
new file mode 100644
index 00000000000..1147be2476f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/052.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: interaction of parsing and script execution - external script </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script src="scripts/count-script-tags.js"></script>
+
+ <script type="text/javascript">
+ log( 'inline script #2' );
+ var t = async_test()
+
+ function test() {
+ assert_array_equals(eventOrder, ['script tags in DOM: 4', 'inline script #2']);
+ t.done();
+}
+ onload = t.step_func(function(){setTimeout(t.step_func(test), 100); })
+ </script>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/053.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/053.html
new file mode 100644
index 00000000000..12ac6101a13
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/053.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: adding external script that removes itself from document when loading</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script>log('inline script #1');
+ var script=testlib.addScript('', { src:'scripts/include-1.js', onload:function() {this.parentNode.removeChild(this);log('removed ' + this.localName);} }, document.getElementsByTagName('body')[0], true );
+ log('end script #1');
+ </script>
+ <script src="scripts/include-2.js"></script>
+ <script type="text/javascript">
+ log( 'inline script #2' );
+ var t = async_test()
+
+ function test() {
+ assert_any(assert_array_equals, eventOrder, [['inline script #1', 'end script #1', 'external script #1', 'removed script', 'external script #2', 'inline script #2'],
+ ['inline script #1', 'end script #1', 'external script #2', 'external script #1', 'removed script', 'inline script #2'],
+ ['inline script #1', 'end script #1', 'external script #2', 'inline script #2', 'external script #1', 'removed script']]
+ );
+ t.done();
+ }
+ onload = t.step_func(test)
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/054.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/054.html
new file mode 100644
index 00000000000..3dc46643568
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/054.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: removing newly inserted script from DOMNodeInserted handler - external script </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script>log('inline script #1');
+ document.addEventListener( 'DOMNodeInserted', function listener(e){
+ log('DOMNodeInserted event');
+ e.target.parentNode.removeChild(e.target);
+ document.removeEventListener('DOMNodeInserted', listener);
+ }, false );
+ var script=testlib.addScript('', { src:'scripts/include-1.js?'+Math.random() }, document.getElementsByTagName('body')[0], true );
+ log('end script #1');
+ </script>
+ <script type="text/javascript">
+ log( 'inline script #2' );
+ var t = async_test()
+
+ function test() {
+ assert_any(assert_array_equals, eventOrder, [['inline script #1', 'DOMNodeInserted event', 'end script #1', 'inline script #2', 'external script #1'],
+ ['inline script #1', 'DOMNodeInserted event', 'end script #1', 'external script #1', 'inline script #2']]);
+ t.done();
+ }
+ onload = t.step_func(test);
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/055.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/055.html
new file mode 100644
index 00000000000..8916d1a8b9a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/055.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: removing newly inserted script from DOMNodeInserted handler - inline script </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script>log('inline script #1');
+ document.addEventListener( 'DOMNodeInserted', function listener(e){
+ log('DOMNodeInserted event');
+ e.target.parentNode.removeChild(e.target);
+ document.removeEventListener('DOMNodeInserted', listener);
+ }, false );
+ var script=testlib.addScript('log(\'added script\')', { }, document.getElementsByTagName('body')[0], true );
+ log('end script #1');
+ </script>
+ <script type="text/javascript">
+ log( 'inline script #2' );
+ var t = async_test()
+
+ function test() {
+ assert_array_equals(eventOrder, ['inline script #1', 'added script', 'DOMNodeInserted event', 'end script #1', 'inline script #2']);
+ t.done();
+}
+ onload = t.step_func(test);
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/056.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/056.html
new file mode 100644
index 00000000000..873fb34d3d5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/056.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: appending code to initially empty SCRIPT tag in DOM </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+ <script></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script>log('inline script #1');
+ var script=document.getElementsByTagName('script')[3];
+ script.appendChild( document.createTextNode('log("injected script code");') );
+ log('end script #1');
+ </script>
+ <script type="text/javascript">
+ log( 'inline script #2' );
+ var t = async_test()
+
+ function test() {
+ // Test asserts the injected script should run
+ assert_array_equals(eventOrder, ['inline script #1', 'injected script code', 'end script #1', 'inline script #2']);
+ t.done();
+ }
+ onload = t.step_func(test);
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/057.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/057.html
new file mode 100644
index 00000000000..dbec8895f17
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/057.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: appending code to initially non-empty SCRIPT tag in DOM (whitespace only) </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+ <script>
+ </script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script>log('inline script #1');
+ var script=document.getElementsByTagName('script')[3];
+ script.appendChild( document.createTextNode('log("injected script code");') );
+ log('end script #1');
+ </script>
+ <script type="text/javascript">
+ log( 'inline script #2' );
+ var t = async_test()
+
+ function test() {
+ assert_array_equals(eventOrder, ['inline script #1', 'end script #1', 'inline script #2']);
+ t.done();
+}
+ onload = t.step_func(test);
+ </script>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/058.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/058.html
new file mode 100644
index 00000000000..730ba456fea
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/058.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: appending code to initially non-empty SCRIPT tag in DOM (comment only) </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+ <script>/**/</script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script>log('inline script #1');
+ var script=document.getElementsByTagName('script')[3];
+ script.appendChild( document.createTextNode('log("injected script code");') );
+ log('end script #1');
+ </script>
+ <script type="text/javascript">
+ log( 'inline script #2' );
+ var t = async_test()
+
+ function test() {
+ assert_array_equals(eventOrder, ['inline script #1', 'end script #1', 'inline script #2']);
+ t.done();
+}
+ onload = t.step_func(test);
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/059.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/059.html
new file mode 100644
index 00000000000..a3ea560c4f2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/059.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: appending code to initially non-empty SCRIPT tag in DOM after removing its initial child </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+ <script>/**/</script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script>log('inline script #1');
+ var script=document.getElementsByTagName('script')[3];
+ script.removeChild(script.firstChild);
+ script.appendChild( document.createTextNode('log("injected script code");') );
+ log('end script #1');
+ </script>
+ <script type="text/javascript">
+ log( 'inline script #2' );
+ var t = async_test()
+
+ function test() {
+ assert_array_equals(eventOrder, ['inline script #1', 'end script #1', 'inline script #2']);
+ t.done();
+ }
+ onload = t.step_func(test);
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/060.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/060.html
new file mode 100644
index 00000000000..dba77146b82
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/060.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: appending code to initially non-empty SCRIPT tag in DOM after setting innerText/innerHTML</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+ <script>log('HEAD script');</script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script>log('inline script #1');
+ var script=document.getElementsByTagName('script')[3];
+ script.innerHTML='';
+ script.appendChild( document.createTextNode('log("injected script code 1");') );
+ script.innerText='';
+ script.appendChild( document.createTextNode('log("injected script code 2");') );
+ log('end script #1');
+ </script>
+ <script type="text/javascript">
+ log( 'inline script #2' );
+ var t = async_test()
+
+ function test() {
+ assert_array_equals(eventOrder, ['HEAD script', 'inline script #1', 'end script #1', 'inline script #2']);
+ t.done();
+}
+ onload = t.step_func(test);
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/061.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/061.html
new file mode 100644
index 00000000000..df708b7bfe7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/061.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: cloneNode and script execution</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+ <script>log('HEAD script');</script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script>log('inline script #1');
+ var script=document.getElementsByTagName('script')[3];
+ document.body.appendChild( script.cloneNode(true) );
+ log('end script #1');
+ </script>
+ <script type="text/javascript">
+ log( 'inline script #2' );
+ var t = async_test()
+
+ function test() {
+ assert_array_equals(eventOrder, ['HEAD script', 'inline script #1', 'end script #1', 'inline script #2']);
+ t.done();
+}
+ onload = t.step_func(test);
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/062.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/062.html
new file mode 100644
index 00000000000..8eda26b71f5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/062.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: cloneNode (shallow) and script execution</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+ <script>log('HEAD script');</script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script>log('inline script #1');
+ var script=document.getElementsByTagName('script')[3];
+ document.body.appendChild( script.cloneNode(false) ).appendChild(document.createTextNode('log("clone");'));
+ log('end script #1');
+ </script>
+ <script type="text/javascript">
+ log( 'inline script #2' );
+ var t = async_test()
+
+ function test() {
+ assert_array_equals(eventOrder, ['HEAD script', 'inline script #1', 'end script #1', 'inline script #2']);
+ t.done();
+}
+ onload = t.step_func(test);
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/063.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/063.html
new file mode 100644
index 00000000000..9b939c4d4ab
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/063.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: cloneNode (deep) of the currently executing script </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+ <script>log('HEAD script');
+ if( !window.already_cloned ){
+ window.already_cloned=true;
+ var script=document.getElementsByTagName('script')[3];
+ document.getElementsByTagName('head')[0].appendChild( script.cloneNode(true) );
+ }
+ </script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script type="text/javascript">
+ log( 'inline script #2' );
+ var t = async_test()
+
+ function test() {
+ assert_array_equals(eventOrder, ['HEAD script', 'inline script #2']);
+ t.done();
+}
+ onload = t.step_func(test);
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/064.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/064.html
new file mode 100644
index 00000000000..814e62545e1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/064.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: cloneNode with external script</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+ <script src="scripts/include-1.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script>log('inline script #1');
+ var script=document.getElementsByTagName('script')[3];
+ document.body.appendChild( script.cloneNode(true) );
+ log('end script #1');
+ </script>
+ <script type="text/javascript">
+ log( 'inline script #2' );
+ var t = async_test()
+
+ function test() {
+ assert_array_equals(eventOrder, ['external script #1', 'inline script #1', 'end script #1', 'inline script #2']);
+ t.done();
+}
+ onload = t.step_func(test);
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/065.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/065.html
new file mode 100644
index 00000000000..92078df045d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/065.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: cloneNode with external script, changed .src</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+ <script src="scripts/include-1.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script>log('inline script #1');
+ var script=document.getElementsByTagName('script')[3].cloneNode(true);
+ script.src='scripts/include-2.js'
+ document.body.appendChild( script );
+ log('end script #1');
+ </script>
+ <script type="text/javascript">
+ log( 'inline script #2' );
+ var t = async_test()
+
+ function test() {
+ assert_array_equals(eventOrder, ['external script #1', 'inline script #1', 'end script #1', 'inline script #2']);
+ t.done();
+}
+ onload = t.step_func(test);
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/066.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/066.html
new file mode 100644
index 00000000000..58560aee075
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/066.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: cloneNode with external script, removing .src and adding content</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+ <script src="scripts/include-1.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script>log('inline script #1');
+ var script=document.getElementsByTagName('script')[3].cloneNode(true);
+ script.removeAttribute('src');
+ script.appendChild(document.createTextNode( 'log("cloned script");' ));
+ document.body.appendChild( script );
+ log('end script #1');
+ </script>
+ <script type="text/javascript">
+ log( 'inline script #2' );
+ var t = async_test()
+
+ function test() {
+ assert_array_equals(eventOrder, ['external script #1', 'inline script #1', 'end script #1', 'inline script #2']);
+ t.done();
+}
+ onload = t.step_func(test);
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/067.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/067.html
new file mode 100644
index 00000000000..7be0fd0ab0d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/067.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: is a script with syntax error marked as "has run"? </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+ <script>setup({allow_uncaught_exception:true})
+ var t = async_test()
+ </script>
+ <script>
+ log(This script will never run..
+ </script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script>t.step(function() {
+ log('inline script #1');
+ var script=document.getElementsByTagName('script')[3].cloneNode(true);
+ script.removeChild(script.firstChild);
+ script.appendChild(document.createTextNode( 'log("cloned script");' ));
+ document.body.appendChild( script );
+ log('end script #1');
+ })
+ </script>
+ <script type="text/javascript">
+ t.step(function() {
+ log( 'inline script #2' );
+ });
+ function test() {
+ assert_array_equals(eventOrder, ['inline script #1', 'end script #1', 'inline script #2']);
+ t.done();
+ }
+ onload = t.step_func(test);
+</script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/068.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/068.html
new file mode 100644
index 00000000000..c584653c899
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/068.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: external script and parsing of markup added with document.write </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script>
+ log('inline script #1');
+ document.write('<script src="scripts/find-foo.js">log(\'inline code in external script (not expected to run!!)\')<\/script>' + '<div id="foo"></div>');
+ log('end script #1');
+
+ var t = async_test()
+
+
+ function test() {
+ if(!window.findFooLoaded) {
+ return setTimeout(t.step_func(test),200);
+ }
+ assert_array_equals(eventOrder, ['inline script #1', 'end script #1', 'found #foo element: NO']);
+ t.done();
+ }
+ onload = t.step_func(test)
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/069.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/069.html
new file mode 100644
index 00000000000..d76f55f31f3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/069.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html><head>
+ <title>scheduler: external files added through DOM should not block further parsing while loading</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+ <script>
+ // add a script that looks for document.body as first child of HEAD
+ testlib.addScript('',{src:'scripts/find-body.js'},document.getElementsByTagName('head')[0], true );
+ </script>
+</head>
+<body>
+ <script>
+ testlib.addScript('', {src:'scripts/find-foo.js?pipe=trickle(d1)'}, document.getElementsByTagName('head')[0], true);
+ </script>
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+ <p><span id="foo"></span></p>
+
+ <script type="text/javascript">
+ var t = async_test()
+
+ function test() {
+ if(!(window.findFooLoaded && window.findBodyLoaded)) {
+ return setTimeout(t.step_func(test), 200);
+ }
+ assert_array_equals(eventOrder, ['document.body: <BODY>', 'found #foo element: YES']);
+ t.done();
+ }
+ onload = t.step_func(test)
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/070.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/070.html
new file mode 100644
index 00000000000..45928b87338
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/070.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: document.write into IFRAME a script that adds a SCRIPT through DOM</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <iframe></iframe>
+
+ <script type="text/javascript">
+ var doc = document.getElementsByTagName('iframe')[0].contentDocument;
+ doc.open();
+
+ log("calling document.write");
+ doc.write('<script>top.log("inline script #1");'+
+ 'var s=document.createElement("script");'+
+ 's.src="scripts/include-6.js?'+new Date().getTime()+'";'+
+ 'document.getElementsByTagName("head")[0].appendChild(s);'+
+ '<\/script>'+
+ '<div id="foo"></div>'+
+ '<script>top.log("inline script #2");<\/script>'
+ );
+
+ log("calling document.close");
+ doc.close();
+
+ var t = async_test()
+
+
+ function test() {
+ if(!window.include6Loaded) {
+ return setTimeout(t.step_func(test),200);
+ }
+ assert_array_equals(eventOrder, ['calling document.write', 'inline script #1', 'inline script #2', 'calling document.close', 'external script (#foo found? YES)']);
+ t.done();
+}
+
+ onload = t.step_func(test)
+ </script>
+</head>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/071.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/071.html
new file mode 100644
index 00000000000..30429749460
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/071.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: document.write several scripts into IFRAME </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <iframe style="width:1px;height:1px"></iframe>
+
+ <script type="text/javascript">
+ var doc = document.getElementsByTagName('iframe')[0].contentDocument;
+ doc.open();
+
+ var html = '<html><head><title>test</title></head>'+
+ '<script>top.log("inline script #1");'+
+ '<\/script>'+
+ /* made url unique because Chrome will change
+ order depending on file cached status */
+ '<script src="scripts/include-6.js?'+new Date().getTime()+'"><\/script>'+
+ '</head>'+
+ '<body>'+
+ '<div id="foo"></div>'+
+ '</body></html>'+
+ '<script>top.log("inline script #2");<\/script>';
+ log("calling document.write");
+ doc.write(html);
+
+ log("calling document.close");
+ doc.close();
+
+ var t = async_test()
+
+
+ function test() {
+ if( !window.include6Loaded )return setTimeout(t.step_func(test),200); // try checking again if external script didn't run yet
+ assert_array_equals(eventOrder, ['calling document.write',
+ 'inline script #1',
+ 'calling document.close',
+ 'external script (#foo found? NO)',
+ 'inline script #2'
+ ]);
+ t.done();
+}
+
+ onload = t.step_func(test)
+ </script>
+</head>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/072.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/072.html
new file mode 100644
index 00000000000..348381df258
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/072.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: document.write into IFRAME a script that creates new inline script in parent </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <iframe style="width:1px;height:1px"></iframe>
+
+ <script type="text/javascript">
+ var doc = document.getElementsByTagName('iframe')[0].contentDocument;
+ doc.open();
+
+ var html = '<html><head><title>test</title></head>'+
+ '<script>top.log("inline script #1");'+
+ '<\/script>'+
+ '</head>'+
+ '<body>'+
+ '<div id="foo"></div>'+
+ '</body></html>'+
+ '<script>top.testlib.addScript( \'log("inline script added to parent")\', null, top.document.body, true )<\/script>';
+ log("calling document.write");
+ doc.write(html);
+
+ log("calling document.close");
+ doc.close();
+
+ var t = async_test()
+
+
+ function test() {
+ assert_array_equals(eventOrder, ['calling document.write',
+ 'inline script #1',
+ 'inline script added to parent',
+ 'calling document.close',
+ ]);
+ t.done();
+}
+
+ onload = t.step_func(test)
+ </script>
+</head>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/073.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/073.html
new file mode 100644
index 00000000000..56dc9180b04
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/073.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: document.write into IFRAME a script that creates new external script in parent </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <iframe style="width:1px;height:1px"></iframe>
+
+ <script type="text/javascript">
+ var doc = document.getElementsByTagName('iframe')[0].contentDocument;
+ doc.open();
+
+ var html = '<html><head><title>test</title></head>'+
+ '<script>top.log("inline script #1");'+
+ '<\/script>'+
+ '</head>'+
+ '<body>'+
+ '<div id="foo"></div>'+
+ '</body></html>'+
+ '<script>top.testlib.addScript( \'\', { src:\'scripts/include-1.js\' }, top.document.body, true )<\/script>';
+ log("calling document.write");
+ doc.write(html);
+
+ log("calling document.close");
+ doc.close();
+
+ var t = async_test()
+
+
+ function test() {
+
+ assert_array_equals(eventOrder, ['calling document.write',
+ 'inline script #1',
+ 'calling document.close',
+ 'external script #1'
+ ]);
+
+ t.done();
+}
+
+ onload = t.step_func(test)
+ </script>
+</head>
+
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/074.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/074.html
new file mode 100644
index 00000000000..6f1baef6bd4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/074.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: document.write into IFRAME a script that creates new inline script in parent that again adds script to IFRAME </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <iframe style="width:1px;height:1px"></iframe>
+
+ <script type="text/javascript">
+ var doc = document.getElementsByTagName('iframe')[0].contentDocument;
+ doc.open();
+ var str1='';
+ var html = '<html><head><title>test</title></head>'+
+ '<script>top.log("inline script #1");'+
+ '<\/script>'+
+ '</head>'+
+ '<body>'+
+ '<script>top.testlib.addScript( \'top.log("inline script added to parent");top.doc.write( "<script>top.log(\\\\"inline script added to iframe\\\\")<\\\/script>");\', null, top.document.body, true ) <\/script>'+
+ '</body></html>';
+ log("calling document.write");
+ doc.write(html);
+
+ log("calling document.close");
+ doc.close();
+
+ var t = async_test()
+
+
+ function test() {
+ assert_array_equals(eventOrder, ['calling document.write',
+ 'inline script #1',
+ 'inline script added to parent',
+ 'inline script added to iframe',
+ 'calling document.close',
+ ]);
+ t.done();
+}
+
+ onload = t.step_func(test)
+ </script>
+</head>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/075.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/075.html
new file mode 100644
index 00000000000..40ec9bbb6a5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/075.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>dispatchEvent from child frame during document.write :-o </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+ </head>
+ <body onclick="log('click event')">
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <iframe></iframe>
+ <script>
+ var doc = document.getElementsByTagName("iframe")[0].contentDocument;
+ doc.open("text/html");
+ doc.write('<html><head><title>event dispatcher</title></head><body>Before script<script>top.log("inline script before event");var ev = parent.document.createEvent("MouseEvents");ev.initMouseEvent("click", true, false, null, 0, 0, 0, 0, 0, false, false, false, false, 0, null);parent.document.body.dispatchEvent(ev);top.log("inline script after event");</sc'+'ript> After script</body>');
+ log( 'end main script' );
+
+
+ </script>
+
+<script>
+ var t = async_test()
+
+ function test() {
+ if(test.ran)return; test.ran=true;
+
+ assert_array_equals(eventOrder, ['inline script before event',
+ 'click event',
+ 'inline script after event',
+ 'end main script'
+ ]);
+ doc.close();
+ t.done();
+}
+
+ onload = t.step_func(test)
+ /* onload doesn't fire in this test, a fallback.. */
+ setTimeout(t.step_func(test), 800 );
+</script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/076.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/076.html
new file mode 100644
index 00000000000..ad2359019bc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/076.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: adding and removing external and inline scripts </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script>log('inline script #1');
+ var script=testlib.addScript('', {src:'scripts/include-1.js', onload:function(e){ e.target.parentNode.removeChild(e.target); }}, document.getElementsByTagName('head')[0], false );
+ var script=testlib.addScript( 'log( "dynamically added inline script" )', null, document.getElementsByTagName('head')[0], false );
+ script.parentNode.removeChild(script);
+ log('end script #1');
+ </script>
+
+ <script type="text/javascript">
+ log( 'inline script #2' );
+ var t = async_test()
+
+ function test() {
+ }
+ onload = t.step_func(function() {
+ assert_any(assert_array_equals, eventOrder, [['inline script #1', 'dynamically added inline script', 'end script #1', 'external script #1', 'inline script #2'],
+ ['inline script #1', 'dynamically added inline script', 'end script #1', 'inline script #2', 'external script #1']]);
+ t.done();
+ })
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/077.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/077.html
new file mode 100644
index 00000000000..a7a59421250
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/077.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title> adding several types of scripts through the DOM and removing some of them confuses scheduler </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+ <script type="text/javascript">
+ var head = document.getElementsByTagName('head')[0];
+ function createScript(url, contents) {
+ props = {};
+ if (url) {
+ props.src = url;
+ }
+ return testlib.addScript(contents, props, head, false);
+ }
+ var t = async_test()
+
+ function test() {
+ var script = createScript('data:text\/javascript,log("Script #1 ran")');
+ var script2 = createScript('','log("Script #2 ran")');
+ if(script2) {
+ head.removeChild(script2);
+ }
+ var script3 = createScript('data:text\/javascript, log("Script #3 ran"); createScript(\'\', \'log("Script #4 ran")\')');
+ if(script3) {
+ head.removeChild(script3);
+ }
+ setTimeout(t.step_func(function(){
+ assert_array_equals(eventOrder, ['Script #2 ran', 'Script #1 ran', 'Script #3 ran','Script #4 ran']);
+ t.done();
+ }), 400);
+
+ };
+ onload = t.step_func(test)
+ </script>
+ </head>
+ <body>
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+ </body>
+</html*>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/078.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/078.html
new file mode 100644
index 00000000000..556006a24e7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/078.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title> adding several types of scripts through the DOM and removing some of them confuses scheduler (slow-loading scripts) </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+ <script type="text/javascript">
+ setup({explicit_done:true});
+ var head=document.getElementsByTagName('head')[0];
+ function createScript(url, contents) {
+ props = {};
+ if (url) {
+ props.src = url;
+ }
+ return testlib.addScript(contents, props, head, false);
+ }
+ var t = async_test(undefined, {timeout:10000})
+
+ function test() {
+ document.getElementById("log").textContent = "Please wait..."
+ var url = 'scripts/include-1.js?pipe=trickle(d1)';
+ var script = createScript(url);
+ var script2 = createScript('', 'log("Script #2 ran")');
+ head.removeChild(script2);
+ var url = 'scripts/include-2.js?pipe=trickle(d2)';
+ var script3 = createScript(url);
+ head.removeChild(script3);
+
+ setTimeout(t.step_func(function() {
+ done();
+ assert_array_equals(eventOrder, ['Script #2 ran', 'external script #1', 'external script #2']);
+ t.done();
+ }), 5500);
+
+ };
+ onload = t.step_func(test)
+ </script>
+ </head>
+ <body>
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+ </body>
+</html*>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/079.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/079.html
new file mode 100644
index 00000000000..8d684cebf2b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/079.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title> setting location to javascript URL from event handler </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="testlib/testlib.js"></script>
+<script type="text/javascript">
+log('inline script #1');
+var t = async_test()
+
+onload = t.step_func(function() {
+ log('onload handler');
+ document.getElementById("log").textContent = 'please wait...';
+ window.location='javascript:log("javascript: URL")';
+ setTimeout(t.step_func(function(){
+ log('timeout');
+ assert_array_equals(eventOrder, ['inline script #1', 'onload handler', 'onload ends', 'javascript: URL', 'timeout']);
+ t.done();
+ }), 200);
+ log('onload ends');
+});
+</script>
+</head>
+<body>
+<div id="log">FAILED (This TC requires JavaScript enabled)</div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/080.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/080.html
new file mode 100644
index 00000000000..a55bc24d06b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/080.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html><head>
+ <title>scheduler: IFRAMEs added with DOM (appendChild), javascript: URL</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+ <div></div>
+ <script>log('inline script #1');
+ var iframe=document.createElement('iframe');
+ iframe.src='javascript:parent.log(\'JS URL\');\'<html><script>parent.log(\\\'frame script\\\')<\/script></html>\'';
+ document.getElementsByTagName('div')[1].appendChild(iframe);
+ log('end script #1');
+ </script>
+
+ <script type="text/javascript">
+ log( 'inline script #2' );
+ var t = async_test()
+
+ function test() {
+ assert_array_equals(eventOrder, ['inline script #1', 'end script #1', 'inline script #2', 'JS URL', 'frame script']);
+ t.done();
+ }
+ onload = t.step_func(function(){setTimeout(t.step_func(test), 400);})
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/081.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/081.html
new file mode 100644
index 00000000000..94f2be6ddc5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/081.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: slow loading external script added with DOM (appendChild)</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+ <div></div>
+ <script>
+ var t = async_test(undefined, {timeout:5000})
+ log('inline script #1');
+ testlib.addScript('', { src:'scripts/include-1.js?pipe=trickle(d1)&'+Math.random() }, document.getElementsByTagName('head')[0], false );
+ log('end script #1');
+ </script>
+ <script src="scripts/include-2.js"></script>
+ <script>
+ log( 'inline script #2' );
+
+ function test() {
+ assert_array_equals(eventOrder, ['inline script #1', 'end script #1', 'external script #2', 'inline script #2', 'external script #1']);
+ t.done();
+ }
+ onload = t.step_func(function() {
+ setTimeout(t.step_func(test), 12);
+ });
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/082.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/082.html
new file mode 100644
index 00000000000..89f86d4d4f0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/082.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: multiple slow loading external scripts added with DOM (appendChild)</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+ <div></div>
+ <script>
+
+ log('inline script #1');
+ function scriptLoadListener(){
+ log( 'load on '+this.src.match( /include-\d\.js/ ) );
+ }
+ var script=testlib.addScript('', { src:'scripts/include-1.js?pipe=trickle(d1)&' + Math.random(), onload:scriptLoadListener }, document.getElementsByTagName('head')[0], false );
+ var script=testlib.addScript('', { src:'scripts/include-2.js?pipe=trickle(d3)&' + Math.random(), onload:scriptLoadListener }, document.getElementsByTagName('head')[0], false );
+ var script=testlib.addScript('', { src:'scripts/include-7.js?pipe=trickle(d2)&' + Math.random() , onload:scriptLoadListener }, document.getElementsByTagName('head')[0], false );
+ log('end script #1');
+ </script>
+ <script type="text/javascript">
+ log('inline script #2');
+ var t = async_test(undefined, {timeout:10000})
+
+ function test() {
+ assert_array_equals(eventOrder, ['inline script #1', 'end script #1', 'inline script #2', 'external script #1', 'load on include-1.js', 'external script #7', 'load on include-7.js', 'external script #2', 'load on include-2.js']);
+ t.done();
+ }
+ onload = function() {setTimeout(t.step_func(test), 12)};
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/083.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/083.html
new file mode 100644
index 00000000000..f1dd567f3dc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/083.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: event listener defined by script in a document in history</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+ <iframe src="about:blank"></iframe>
+ <script>
+ log('inline script #1');
+ function fireFooEvent(){
+ var evt=document.createEvent('Event');
+ evt.initEvent('foo', true, true);
+ document.dispatchEvent(evt);
+ }
+ var doc = frames[0].document;
+ doc.open('text/html');
+ doc.write('<script>top.log("IFRAME script");top.document.addEventListener("foo", function(e){ console.log(e+ " "+top+" "+self.location.href); top.log("event: "+e.type); }, false)<\/script>');
+ log('end script #1');
+ </script>
+ <script>
+ fireFooEvent();
+ frames[0].location='about:blank'; // returning to about:blank should de-activate document that defined event listener..?
+ </script>
+ <script>
+ fireFooEvent();
+ </script>
+ <script type="text/javascript">
+ log( 'inline script #2' );
+ var t = async_test()
+
+ function test() {
+ assert_equals(frames[0].location.toString(), "about:blank");
+ assert_array_equals(eventOrder, ['inline script #1',
+ 'IFRAME script',
+ 'end script #1',
+ 'event: foo',
+ 'inline script #2'
+ ]);
+ t.done();
+}
+ onload = function() {setTimeout(t.step_func(function() {fireFooEvent(); test()}), 80)};
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/084.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/084.html
new file mode 100644
index 00000000000..5e9adb07d93
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/084.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: event listener defined by script in a removed IFRAME</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+ <iframe src="about:blank"></iframe>
+ <script>
+ log('inline script #1');
+ function fireFooEvent(){
+ var evt=document.createEvent('Event');
+ evt.initEvent('foo', true, true);
+ document.dispatchEvent(evt);
+ }
+ var doc=frames[0].document;
+ doc.open( 'text/html' );
+ doc.write( '<script>top.log("IFRAME script");top.document.addEventListener("foo", function(e){ top.log("event: "+e.type); }, false)<\/script>' );
+ log('end script #1');
+ </script>
+ <script>
+ fireFooEvent();
+ frames[0].frameElement.parentNode.removeChild( frames[0].frameElement ); // removing the IFRAME should de-activate document that defined event listener..?
+ </script>
+ <script>
+ fireFooEvent();
+ </script>
+ <script type="text/javascript">
+ log( 'inline script #2' );
+ var t = async_test()
+
+ function test() {
+ assert_array_equals(eventOrder, ['inline script #1',
+ 'IFRAME script',
+ 'end script #1',
+ 'event: foo',
+ 'inline script #2'
+ ]);
+ t.done();
+}
+ onload = t.step_func(test)
+ </script>
+
+</body></html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/085.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/085.html
new file mode 100644
index 00000000000..e0d165ffc18
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/085.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: async script and slow-loading defer script</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script src="scripts/include-1.js?pipe=trickle(d1)" defer></script>
+ <script src="scripts/include-2.js" async></script>
+
+ <script type="text/javascript">
+ var t = async_test();
+ function test() {
+ assert_array_equals(eventOrder, ['external script #2', 'external script #1']);
+ t.done();
+ }
+ onload = t.step_func(test);
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/086.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/086.html
new file mode 100644
index 00000000000..86db3aea5bd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/086.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: async script and slow-loading async script</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script src="scripts/include-1.js?pipe=trickle(d2)" async></script>
+ <script src="scripts/include-2.js" async></script>
+
+ <script type="text/javascript">
+ var t = async_test();
+ function test() {
+ assert_array_equals(eventOrder, ['external script #2', 'external script #1']);
+ t.done();
+ }
+ onload = t.step_func(test);
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/087.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/087.html
new file mode 100644
index 00000000000..759335474a5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/087.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: multiple defer scripts, one slow loading</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script src="scripts/include-1.js?pipe=trickle(d2)" defer></script>
+ <script src="scripts/include-2.js" defer></script>
+
+ <script type="text/javascript">
+ var t = async_test();
+ function test() {
+ assert_array_equals(eventOrder, ['external script #1', 'external script #2']);
+ t.done();
+ }
+ onload = t.step_func(test);
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/088.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/088.html
new file mode 100644
index 00000000000..f7e7366e1c3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/088.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: multiple scripts with defer and async attributes</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script src="scripts/include-1.js?pipe=trickle(d2)" defer async></script>
+ <script src="scripts/include-2.js" defer async></script>
+
+ <script type="text/javascript">
+ var t = async_test();
+ function test() {
+ assert_array_equals(eventOrder, ['external script #2', 'external script #1']);
+ t.done();
+ }
+ onload = t.step_func(test);
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/089.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/089.html
new file mode 100644
index 00000000000..1b888ea3d4b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/089.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: async attribute on inline script</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script async>
+ var t = async_test();
+ log('inline script #1');
+ t.step(function() {
+ assert_array_equals(eventOrder, ['inline script #1']);
+ });
+ </script>
+ <script async>
+ log('inline script #2');
+ t.step(function() {
+ assert_array_equals(eventOrder, ['inline script #1', 'inline script #2']);
+ });
+ </script>
+
+ <script>
+ log('inline script #3');
+ t.step(function() {
+ assert_array_equals(eventOrder, ['inline script #1', 'inline script #2', 'inline script #3']);
+ });
+ onload = function() {t.done()};
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/090.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/090.html
new file mode 100644
index 00000000000..224e7976331
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/090.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: defer attribute on inline script</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script defer>
+ var t = async_test();
+ log('inline script #1');
+ t.step(function() {
+ assert_array_equals(eventOrder, ['inline script #1']);
+ });
+ </script>
+ <script defer>
+ log('inline script #2');
+ t.step(function() {
+ assert_array_equals(eventOrder, ['inline script #1', 'inline script #2']);
+ });
+ </script>
+
+ <script>
+ log('inline script #3');
+ t.step(function() {
+ assert_array_equals(eventOrder, ['inline script #1', 'inline script #2', 'inline script #3']);
+ });
+ onload = function() {t.done()};
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/091.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/091.html
new file mode 100644
index 00000000000..946cf833328
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/091.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: force-async off on non-parser-inserted script</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script>
+ var t = async_test(undefined, {timeout:4000});
+
+ sources = ["scripts/include-1.js?pipe=trickle(d2)", "scripts/include-2.js?pipe=trickle(d1)"];
+ sources.forEach(function(x) {
+ var script = document.createElement("script");
+ script.src = x;
+ t.step(function() {assert_equals(script.async, true, "async IDL attribute on script creation")});
+ script.async = false;
+ t.step(function() {assert_equals(script.async, false, "async IDL attribute after setting")});
+ t.step(function() {assert_equals(script.getAttribute("async"), null, "async content attribute after setting")});
+ document.head.appendChild(script);
+ });
+
+ onload = t.step_func(function() {
+ assert_array_equals(eventOrder, ['external script #1', 'external script #2']);
+ t.done();
+ });
+ </script>
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/092.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/092.html
new file mode 100644
index 00000000000..d42caa7c0c0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/092.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: defer script and slow-loading non-async external script</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script>
+ var t = async_test(undefined, {timeout:3500});
+
+ var script = document.createElement("script");
+ script.src = "scripts/include-2.js?pipe=trickle(d2)";
+ script.async = false;
+ document.head.appendChild(script);
+
+ onload = t.step_func(function() {
+ assert_array_equals(eventOrder, ['external script #1', 'external script #2']);
+ t.done();
+ });
+ </script>
+ <script defer src="scripts/include-1.js"></script>
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/094.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/094.html
new file mode 100644
index 00000000000..5fe0a005821
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/094.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: parser-created defer script after document load</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script>
+ var t = async_test(undefined, {timeout:3500});
+ onload = t.step_func(function() {
+ document.open();
+ document.write("<title> scheduler: parser-created defer script after document load</title><script src='/resources/testharness.js'><\/script><script src='/resources/testharnessreport.js'><\/script><script src='testlib/testlib.js'><\/script><script>var t=async_test()<\/script><div id=log></div><script defer src='data:text/javascript,t.done();'><\/script>");
+ document.close();
+ setTimeout(t.step_func(function() {assert_unreached()}, 500));
+ })
+ </script>
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/095.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/095.html
new file mode 100644
index 00000000000..13142ef6c42
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/095.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: slow-loading script added from defer blocking load event</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script>
+ var t = async_test(undefined, {timeout:3500});
+ function test() {
+ t.step(function() {
+ assert_array_equals(eventOrder, ['external script #8', 'external script #9']);
+ t.done();
+ });
+ }
+ //assert that the test is completed before onload fires
+ onload = t.step_func(function() {assert_unreached()});
+ </script>
+ <script defer src="scripts/include-8.js"></script>
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/096.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/096.html
new file mode 100644
index 00000000000..d5e1e8b460f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/096.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: defer script added from document.write relative to DOMContentLoaded</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script>
+ log("inline script #1");
+ document.write("<script defer src='scripts/include-1.js'><\/script>")
+ </script>
+ <script>
+ log("inline script #2");
+ var t = async_test();
+
+ addEventListener("DOMContentLoaded", t.step_func(function() {assert_array_equals(eventOrder, ["inline script #1", "inline script #2"])}), false);
+
+ onload = t.step_func(function() {assert_array_equals(eventOrder, ["inline script #1", "inline script #2", "external script #1"]); t.done();});
+ </script>
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/097.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/097.html
new file mode 100644
index 00000000000..083fd390a0b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/097.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: slow-loading async script added from document.write</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script>
+ log("inline script #1");
+ document.write("<script async src='scripts/include-1.js?pipe=trickle(d2)'><\/script>")
+ </script>
+ <script>
+ log("inline script #2");
+ var t = async_test(undefined, {timeout:3500});
+
+ addEventListener("DOMContentLoaded", t.step_func(function() {assert_array_equals(eventOrder, ["inline script #1", "inline script #2"])}), false);
+
+ onload = t.step_func(
+ function() {
+ assert_array_equals(eventOrder, ["inline script #1", "inline script #2", "external script #1"]);
+ t.done();
+ });
+
+ </script>
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/098.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/098.html
new file mode 100644
index 00000000000..2d421a8a37f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/098.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: defer script added from document.write</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script>
+ log("inline script #1");
+ document.write("<script defer src='scripts/include-1.js'><\/script>")
+ </script>
+ <script>
+ log("inline script #2");
+ var t = async_test();
+
+ addEventListener("DOMContentLoaded", t.step_func(function() {assert_array_equals(eventOrder, ["inline script #1", "inline script #2"])}), false);
+
+ onload = t.step_func(function() {assert_array_equals(eventOrder, ["inline script #1", "inline script #2", "external script #1"]); t.done();});
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/099.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/099.html
new file mode 100644
index 00000000000..5c6df576e87
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/099.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: defer adding iframe containing script</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script defer src="scripts/include-11.js"></script>
+ <script>
+ var t = async_test();
+
+ onload = t.step_func(function() {assert_array_equals(eventOrder, ["external script before adding iframe", "script in iframe"]); t.done();});
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/100.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/100.html
new file mode 100644
index 00000000000..d24828c999f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/100.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: defer adding iframe containing script</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script defer src="scripts/include-12.js"></script>
+ <script>
+ var t = async_test();
+
+ onload = t.step_func(function() {assert_array_equals(eventOrder, ["external script before adding object", "script in object"]); t.done();});
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/101.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/101.html
new file mode 100644
index 00000000000..23a9c36c6f0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/101.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: defer script after initial onload event</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script>
+ var t = async_test();
+ onload = t.step_func(
+ function() {
+ document.open();
+ document.write("<title> scheduler: defer script after initial onload event</title><script src='/resources/testharness.js'><\/script><script src='/resources/testharnessreport.js'><\/script><script src='testlib/testlib.js'><\/script><div id='log'>document.written content</div><script>log('inline script #1'); t = async_test();<\/script><script src='scripts/include-1.js'><\/script><script defer src='scripts/include-2.js'><\/script>");
+ document.close();
+ //Note that the *window* object has changed but the *global scope* of the script has not.
+ window.setTimeout(
+ function() {
+ window.t.step(
+ function() {
+ window.assert_array_equals(window.eventOrder, ['inline script #1', 'external script #1', 'external script #2']);
+ window.t.done();
+ })}, 1000);
+ });
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/102.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/102.html
new file mode 100644
index 00000000000..67edbc659ce
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/102.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: defer script after initial onload event</title>
+</head>
+<body>
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script>
+ onload = function() {
+ document.open();
+ document.write("<title> scheduler: defer script after initial onload event</title><script src='/resources/testharness.js'><\/script><script src='/resources/testharnessreport.js'><\/script><script src='testlib/testlib.js'><\/script><div id='log'>document.written content</div><script>var t = async_test(); log('inline script #1')<\/script><script src='scripts/include-1.js'><\/script><script async src='scripts/include-2.js'><\/script>");
+ document.close();
+ window.setTimeout(function() {
+ window.t.step(function() {
+ window.assert_any(window.assert_array_equals, window.eventOrder,
+ [['inline script #1', 'external script #1', 'external script #2'],
+ ['inline script #1', 'external script #2', 'external script #1']]);
+ window.t.done();
+ })},
+ 1000);
+ };
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/103.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/103.html
new file mode 100644
index 00000000000..198c394dee9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/103.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: removing defer attribute at runtime</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="test"></div>
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script id="defer-script" defer src="scripts/include-2.js"></script>
+ <script src="scripts/include-1.js"></script>
+
+ <script>
+ var t = async_test();
+
+ t.step(function() {
+ document.getElementById("defer-script").removeAttribute("defer");
+ });
+
+ var ran_defer_check = false;
+
+ document.addEventListener("readystatechange", t.step_func(function () {
+ if (document.readyState == "interactive") {
+ ran_defer_check = true;
+ assert_array_equals(eventOrder, ["external script #1"]);
+ }
+ }), false);
+
+ addEventListener("load", t.step_func(function () {
+ assert_true(ran_defer_check);
+ assert_array_equals(eventOrder, ["external script #1", "external script #2"]);
+ t.done();
+ }), false);
+
+ </script>
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/104.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/104.html
new file mode 100644
index 00000000000..b5cdb75e385
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/104.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: adding defer attribute at runtime</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="test"></div>
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script id="defer-script" src="scripts/include-1.js"></script>
+ <script src="scripts/include-2.js"></script>
+
+ <script>
+ var t = async_test();
+
+ t.step(function() {
+ document.getElementById("defer-script").setAttribute("defer", "defer");
+ });
+
+ var ran_defer_check = false;
+
+ document.addEventListener("readystatechange", t.step_func(function () {
+ if (document.readyState == "interactive") {
+ ran_defer_check = true;
+ assert_array_equals(eventOrder, ["external script #1", "external script #2"]);
+ }
+ }), false);
+
+ addEventListener("load", t.step_func(function () {
+ assert_true(ran_defer_check);
+ assert_array_equals(eventOrder, ["external script #1", "external script #2"]);
+ t.done();
+ }), false);
+
+ </script>
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/105.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/105.html
new file mode 100644
index 00000000000..abf2c8c211d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/105.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: adding async attribute at runtime</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script>
+ var t = async_test();
+
+ var sources = ["scripts/include-1.js?pipe=trickle(d2)",
+ "scripts/include-2.js"]
+ var scripts = sources.map(function(x) {
+ var script = document.createElement("script");
+ script.src = x;
+ script.async = false;
+ document.body.appendChild(script);
+ return script;
+ });
+ scripts[0].async = true;
+
+ addEventListener("load", t.step_func(function () {
+ assert_array_equals(eventOrder, ["external script #1", "external script #2"]);
+ t.done();
+ }), false);
+
+ </script>
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/106.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/106.html
new file mode 100644
index 00000000000..66eb4e1f098
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/106.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: stylesheets blocking scripts</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+ <div id="test">Test</div>
+
+ <script>
+ var t = async_test();
+ var t0 = Date.now();
+ </script>
+
+ <!-- this stylesheet blocks scripts -->
+ <link rel="stylesheet" href="css/import.css?pipe=trickle(d2)">
+
+ <script>
+ t.step(function() {
+ var t1 = Date.now();
+ assert_true(t1 - t0 > 1000, "Delayed by " + (t1-t0) + "ms expected > 1000ms");
+ t.done();
+ });
+ </script>
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/107.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/107.html
new file mode 100644
index 00000000000..a2d2a33c9aa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/107.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: stylesheets blocking scripts document.write</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+ <div id="test">Test</div>
+
+ <script>
+ var t = async_test();
+ var t0 = Date.now();
+ </script>
+
+ <!-- this stylesheet blocks scripts -->
+ <script>
+ t.step(function() {
+ document.write("<link rel='stylesheet' href='css/import.css?pipe=trickle(d2)'>");
+ var t1 = Date.now();
+ <!-- note that the pass condition here is not per spec (but does match implementations) as of 2012-06-26 -->
+ assert_true(t1-t0 < 1000, "Stylesheet blocked scripts, delayed by " + (t1-t0) + "ms expected < 1000ms");
+ t.done();
+ });
+ </script>
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/108.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/108.html
new file mode 100644
index 00000000000..732fcfa9c1f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/108.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: javascript URL in iframe</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+ <div id="log">Not tested</div>
+ <script>
+ var t = async_test();
+ var iframe_onload = false;
+
+ t.step(function() {
+ log('inline script #1');
+ document.write("<iframe src='javascript:void(top.log(&quot;iframe script #1&quot;));'></iframe>");
+ log('inline script #2')
+ })
+
+ onload = t.step_func(function() {
+ assert_array_equals(eventOrder, ["inline script #1", "inline script #2", "iframe script #1"]);
+ t.done();
+ });
+ </script>
+</body>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/109.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/109.html
new file mode 100644
index 00000000000..c6815b4dc10
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/109.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: javascript URL in iframe, src set via DOM</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+ <div id="log">Not tested</div>
+ <script>
+ var t = async_test();
+
+ t.step(function() {
+ var iframe_onload = false;
+ log("inline script #1");
+ var iframe = document.createElement("iframe");
+ iframe.src = "javascript:void(top.log('JS URL'));";
+ log("inline script #2");
+ iframe.onload = function () { log("iframe onload") };
+ document.body.appendChild(iframe);
+ log("inline script #3");
+ })
+
+ onload = t.step_func(function() {
+ assert_array_equals(eventOrder, ["inline script #1", "inline script #2", "inline script #3", "JS URL", "iframe onload"]);
+ t.done();
+ });
+ </script>
+</body>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/110.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/110.html
new file mode 100644
index 00000000000..de0c5050c37
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/110.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: removing defer script at runtime</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="test"></div>
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script id="defer-script" defer src="scripts/include-2.js"></script>
+ <script src="scripts/include-1.js"></script>
+
+ <script>
+ var t = async_test();
+
+ t.step(function() {
+ var s = document.getElementById("defer-script");
+ s.parentNode.removeChild(s);
+ });
+
+ addEventListener("load", t.step_func(function () {
+ assert_array_equals(eventOrder, ["external script #1", "external script #2"]);
+ t.done();
+ }), false);
+
+ </script>
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/111.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/111.html
new file mode 100644
index 00000000000..7cc092cf82e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/111.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: removing async attribute at runtime</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="test"></div>
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script id="async-script" async src="scripts/include-2.js?pipe=trickle(d1)"></script>
+
+ <script>
+ var t = async_test();
+
+ t.step(function() {
+ document.getElementById("async-script").removeAttribute("async");
+ var s = document.createElement("script");
+ s.async = false;
+ s.src = "scripts/include-1.js";
+ document.body.appendChild(s);
+ });
+
+ addEventListener("load", t.step_func(function () {
+ assert_array_equals(eventOrder, ["external script #1", "external script #2"]);
+ t.done();
+ }), false);
+
+ </script>
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/112.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/112.html
new file mode 100644
index 00000000000..6291005b373
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/112.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: removing async attribute at runtime, script also has defer attribute</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="test"></div>
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script id="async-script" async defer src="scripts/include-1.js?pipe=trickle(d1)"></script>
+
+ <script>
+ var t = async_test();
+
+ addEventListener("DOMContentLoaded", t.step_func(function () {
+ assert_array_equals(eventOrder, []);
+ t.done();
+ }), false);
+
+ addEventListener("load", t.step_func(function () {
+ assert_array_equals(eventOrder, ["external script #1"]);
+ t.done();
+ }), false);
+
+ </script>
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/113.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/113.html
new file mode 100644
index 00000000000..c857c6a97e4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/113.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: Altering DOM using innerHTML during parse </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="test"></div>
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script>
+ var t = async_test();
+
+ addEventListener("load", t.step_func(function () {
+ assert_array_equals(eventOrder, ["inline script #1", "inline script #2"]);
+ t.done();
+ }), false);
+
+ </script>
+ <div id="container">
+ <script>t.step(function() {
+ log("inline script #1");
+ document.getElementById("container").innerHTML = "";
+ });
+ </script>
+ <script>t.step(function() {log("inline script #2")});</script>
+ </div>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/114.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/114.html
new file mode 100644
index 00000000000..784a69f51de
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/114.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: Changing src of defer script before it runs </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="test"></div>
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script id="defer-script" defer src="scripts/include-1.js"></script>
+
+ <script>
+ var t = async_test();
+
+ document.getElementById("defer-script").src = "scripts/include-2.js"
+
+ addEventListener("load", t.step_func(function () {
+ assert_array_equals(eventOrder, ["external script #1"]);
+ t.done();
+ }), false);
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/115.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/115.html
new file mode 100644
index 00000000000..78790c2ef34
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/115.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html><head>
+ <title> scheduler: Removing src of defer script before it runs </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+
+ <div id="test"></div>
+ <div id="log">FAILED (This TC requires JavaScript enabled)</div>
+
+ <script id="defer-script" defer src="scripts/include-1.js">t.step(function() {assert_unreached()})</script>
+
+ <script>
+ var t = async_test();
+
+ document.getElementById("defer-script").removeAttribute("src");
+
+ addEventListener("load", t.step_func(function () {
+ assert_array_equals(eventOrder, ["external script #1"]);
+ t.done();
+ }), false);
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/116.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/116.html
new file mode 100644
index 00000000000..fef7b893871
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/116.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html><head>
+ <title>scheduler: adding script to head of frameset document</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+ <script>
+ // add a script that looks for document.body as first child of HEAD
+ testlib.addScript('',{src:'scripts/find-body.js'},document.getElementsByTagName('head')[0], true );
+ var div = document.createElement("div");
+ div.id = "log";
+ var t = async_test();
+ function test() {
+ if(!(window.findBodyLoaded)) {
+ return setTimeout(t.step_func(test),200);
+ }
+ document.body.appendChild(div);
+ assert_array_equals(eventOrder, ['document.body: <FRAMESET>']);
+ t.done();
+ }
+ onload = t.step_func(test)
+ </script>
+</head>
+<frameset>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/117.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/117.html
new file mode 100644
index 00000000000..3868a292a36
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/117.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html><head>
+ <title>scheduler: inline script created with createContextualFragment</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+ <div id="log"></div>
+ <script>
+ log('inline script #1');
+ var t = async_test();
+
+ t.step(function() {
+ var range = document.createRange();
+ var fragment = range.createContextualFragment("<script>log('fragment script #1')<\/script>");
+ document.body.appendChild(fragment.firstChild);
+ });
+
+ function test() {
+ assert_array_equals(eventOrder, ['inline script #1', 'fragment script #1', 'end inline script #1']);
+ t.done();
+ }
+ onload = t.step_func(test)
+ log('end inline script #1');
+ </script>
+
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/118.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/118.html
new file mode 100644
index 00000000000..f018001db59
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/118.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html><head>
+ <title>scheduler: external script created with createContextualFragment</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+ <div id="log"></div>
+ <script>
+ log('inline script #1');
+ var t = async_test();
+
+ t.step(function() {
+ var range = document.createRange();
+ var fragment = range.createContextualFragment("<script src='scripts/include-1.js'><\/script>");
+ document.body.appendChild(fragment.firstChild);
+ });
+
+ addEventListener("load", t.step_func(function() {
+ assert_array_equals(eventOrder, ['inline script #1', 'end inline script #1', 'external script #1']);
+ t.done();
+ }), false);
+
+ log('end inline script #1');
+ </script>
+
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/119.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/119.html
new file mode 100644
index 00000000000..af74c3d4004
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/119.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html><head>
+ <title>scheduler: external defer script created with createContextualFragment</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+ <div id="log"></div>
+ <script>
+ log('inline script #1');
+ var t = async_test();
+
+ t.step(function() {
+ var range = document.createRange();
+ var fragment = range.createContextualFragment("<script defer src='scripts/include-1.js?pipe=trickle(d1)'><\/script>");
+ document.body.appendChild(fragment.firstChild);
+ });
+
+ addEventListener("DOMContentLoaded", t.step_func(function() {
+ assert_array_equals(eventOrder, ['inline script #1', 'end inline script #1']);
+ t.done();
+ }));
+
+ addEventListener("load", t.step_func(function() {
+ assert_array_equals(eventOrder, ['inline script #1', 'end inline script #1', 'external script #1']);
+ t.done();
+ }));
+
+
+ log('end inline script #1');
+ </script>
+
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/120.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/120.html
new file mode 100644
index 00000000000..d6af5d02e1b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/120.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html><head>
+ <title>scheduler: script created without a window </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<div id="log"></div>
+<script>
+ var t = async_test();
+
+ var doc = document.implementation.createHTMLDocument("");
+ doc.write("<script>t.step(function() {assert_unreached()})<\/script>");
+
+ document.body.appendChild(doc.head.firstChild);
+
+ onload = function() {t.done()}
+</script>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/121.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/121.html
new file mode 100644
index 00000000000..534532ad12a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/121.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html><head>
+ <title>scheduler: altering the type attribute </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<div id="log"></div>
+<script>
+ var t = async_test();
+</script>
+<script id="test" type="text/plain">t.step(function() {assert_unreached()}</script>
+<script>
+t.step(function() {
+ document.getElementById("test").removeAttribute("type");
+ setTimeout(t.step_func(function() {t.done()}), 100);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/122.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/122.html
new file mode 100644
index 00000000000..888681d2aae
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/122.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html><head>
+ <title>scheduler: altering the type attribute and adding/removing external script </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<div id="log"></div>
+<script>
+ var t = async_test(undefined, {timeout:4000});
+</script>
+<script id="test" type="text/plain" src="scripts/include-1.js?pipe=trickle(d1)"></script>
+<script>
+t.step(function() {
+ var script = document.getElementById("test");
+ script.removeAttribute("type");
+ var marker = document.createElement("script");
+ marker.src = "scripts/include-2.js?pipe=trickle(d2)";
+ marker.async = false;
+ script.parentNode.appendChild(marker);
+ script.parentNode.appendChild(script);
+ test(function() {assert_true(script.async)}, "Reinserted script async IDL attribute");
+});
+onload = t.step_func(function () {
+ assert_array_equals(eventOrder, ["external script #1", "external script #2"]);
+ t.done();
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/123.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/123.html
new file mode 100644
index 00000000000..375ae13165b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/123.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html><head>
+ <title>scheduler: altering the type attribute and adding/removing external script with async=false </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<div id="log"></div>
+<script>
+ var t = async_test(undefined, {timeout:4000});
+</script>
+<script id="test" type="text/plain" src="scripts/include-2.js?pipe=trickle(d1)"></script>
+<script>
+t.step(function() {
+ var script = document.getElementById("test");
+ script.removeAttribute("type");
+ script.async = false;
+ var marker = document.createElement("script");
+ marker.src = "scripts/include-1.js?pipe=trickle(d2)";
+ marker.async = false;
+ script.parentNode.appendChild(marker);
+ script.parentNode.appendChild(script);
+});
+onload = t.step_func(function() {
+ assert_array_equals(eventOrder, ["external script #1", "external script #2"]);
+ t.done();
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/124.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/124.html
new file mode 100644
index 00000000000..86eef3f782d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/124.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html><head>
+ <title>scheduler: altering the type attribute and changing script data inline script </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<div id="log"></div>
+<script>
+ var t = async_test();
+</script>
+<script id="test" type="text/plain">t.step(function() {log("inline script #1")});</script>
+<script>
+t.step(function() {
+ log("inline script #2");
+ var script = document.getElementById("test");
+ script.removeAttribute("type");
+ script.appendChild(document.createTextNode(""));
+ log("end inline script #2");
+});
+onload = t.step_func(function() {
+ assert_array_equals(eventOrder, ["inline script #2", "inline script #1", "end inline script #2"]);
+ t.done();
+})
+</script>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/125.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/125.html
new file mode 100644
index 00000000000..6b50ca097be
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/125.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html><head>
+ <title>scheduler: altering the type attribute and changing script data external script </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<div id="log"></div>
+<script>
+ var t = async_test(undefined, {timeout:4000});
+</script>
+<script id="test" type="text/plain" src="scripts/include-1.js?pipe=trickle(d1)"></script>
+<script>
+t.step(function() {
+ var script = document.getElementById("test");
+ script.removeAttribute("type");
+ var marker = document.createElement("script");
+ marker.src = "scripts/include-2.js?pipe=trickle(d2)";
+ marker.async = false;
+ script.parentNode.appendChild(marker);
+ script.appendChild(document.createTextNode(""));
+});
+
+onload = t.step_func(function() {
+ assert_array_equals(eventOrder, ["external script #1", "external script #2"]);
+ t.done();
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/126.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/126.html
new file mode 100644
index 00000000000..5d258b59d4a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/126.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html><head>
+ <title>scheduler: altering the type attribute and changing script data external script async=false </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<div id="log"></div>
+<script>
+ var t = async_test(undefined, {timeout:4000});
+</script>
+<script id="test" type="text/plain" src="scripts/include-2.js"></script>
+<script>
+t.step(function() {
+ var script = document.getElementById("test");
+ script.removeAttribute("type");
+ script.async = false;
+ var marker = document.createElement("script");
+ marker.src = "scripts/include-1.js?pipe=trickle(d2)";
+ marker.async = false;
+ script.parentNode.appendChild(marker);
+ script.appendChild(document.createTextNode(""));
+});
+
+onload = t.step_func(function() {
+ assert_array_equals(eventOrder, ["external script #1", "external script #2"]);
+ t.done();
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/127.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/127.html
new file mode 100644
index 00000000000..efb0fe37747
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/127.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html><head>
+ <title>scheduler: appending non-text children to script </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<div id="log"></div>
+<script>
+ var t = async_test();
+</script>
+<script id="test"></script>
+<script>
+t.step(function() {
+ log("inline script #1");
+ var script = document.getElementById("test");
+
+ var frag = document.createDocumentFragment();
+ var div = document.createElement("div");
+
+ div.textContent = "assert_unreached();"
+ frag.appendChild(document.createTextNode("t.step(function() {log('inline script #2');\n"));
+ frag.appendChild(div);
+ frag.appendChild(document.createTextNode("log('end inline script #2');})"));
+
+ script.appendChild(frag);
+ log("end inline script #1");
+});
+
+onload = t.step_func(function() {
+ assert_array_equals(eventOrder, ["inline script #1", "inline script #2", "end inline script #2", "end inline script #1"]);
+ t.done();
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/128.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/128.html
new file mode 100644
index 00000000000..a21fd8b4bce
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/128.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html><head>
+ <title>scheduler: appending script element to script </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<div id="log"></div>
+<script>
+ var t = async_test();
+</script>
+<script id="test"></script>
+<script>
+t.step(function() {
+ log("inline script #1");
+ var script = document.getElementById("test");
+
+ var frag = document.createDocumentFragment();
+ var inner_script = document.createElement("script");
+
+ inner_script.textContent = "t.step(function() {log('inline script #3');});"
+ frag.appendChild(document.createTextNode("t.step(function() {log('inline script #2');\n"));
+ frag.appendChild(inner_script);
+ frag.appendChild(document.createTextNode("log('end inline script #2');})"));
+
+ script.appendChild(frag);
+ log("end inline script #1");
+});
+
+onload = t.step_func(function() {
+ assert_array_equals(eventOrder, ["inline script #1", "inline script #2", "inline script #3", "end inline script #2", "end inline script #1"]);
+ t.done();
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/129.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/129.html
new file mode 100644
index 00000000000..1148d9faecf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/129.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html><head>
+ <title>scheduler: appending multiple script elements</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<div id="log"></div>
+<script>
+ var t = async_test();
+</script>
+<div id="container"></div>
+<script>
+t.step(function() {
+ log("inline script #1");
+
+ var frag = document.createDocumentFragment();
+
+ scripts = ["2", "3", "4"].map(function(x) {
+ var s = document.createElement("script");
+ s.textContent = "t.step(function() {log('inline script #" + x + "')});";
+ return s
+ });
+
+
+ frag.appendChild(scripts[0]);
+ var div = document.createElement(div);
+ div.appendChild(scripts[1]);
+ frag.appendChild(div);
+ frag.appendChild(scripts[2]);
+
+ document.getElementById("container").appendChild(frag);
+ log("end inline script #1");
+});
+
+onload = t.step_func(function() {
+ assert_array_equals(eventOrder, ["inline script #1", "inline script #2", "inline script #3", "inline script #4", "end inline script #1"]);
+ t.done();
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/130.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/130.html
new file mode 100644
index 00000000000..af60e3cf408
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/130.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html><head>
+ <title>scheduler: appending external script element to script </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<div id="log"></div>
+<script>
+ var t = async_test();
+</script>
+<script id="test"></script>
+<script>
+t.step(function() {
+ log("inline script #1");
+ var script = document.getElementById("test");
+
+ var frag = document.createDocumentFragment();
+ var inner_script = document.createElement("script");
+
+ inner_script.src = "scripts/include-1.js?pipe=trickle(d1)";
+ frag.appendChild(document.createTextNode("t.step(function() {log('inline script #2');\n"));
+ frag.appendChild(inner_script);
+ frag.appendChild(document.createTextNode("log('end inline script #2');})"));
+
+ script.appendChild(frag);
+ log("end inline script #1");
+});
+
+onload = t.step_func(function() {
+ assert_array_equals(eventOrder, ["inline script #1", "inline script #2", "end inline script #2", "end inline script #1", "external script #1"]);
+ t.done();
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/131.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/131.html
new file mode 100644
index 00000000000..f7f14178b83
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/131.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html><head>
+ <title>scheduler: inline svg script </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<div id="log"></div>
+<script>
+ var t = async_test();
+ log("inline script #1")
+</script>
+<svg>
+<script>log("inline script #2")</script>
+</svg>
+<script>
+log("inline script #3");
+t.step(function() {
+ assert_array_equals(eventOrder, ["inline script #1", "inline script #2", "inline script #3"]);
+ t.done();
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/132.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/132.html
new file mode 100644
index 00000000000..9a675be55d1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/132.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html><head>
+ <title>scheduler: external svg script </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<div id="log"></div>
+<script>
+ var t = async_test();
+ log("inline script #1")
+</script>
+<svg>
+<script xlink:href="scripts/include-1.js"></script>
+</svg>
+<script>
+log("inline script #2");
+t.step(function() {
+ assert_array_equals(eventOrder, ["inline script #1", "external script #1", "inline script #2"]);
+ t.done();
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/133.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/133.html
new file mode 100644
index 00000000000..daecb36283b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/133.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html><head>
+ <title>scheduler: inline HTML script added by SVG script </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<div id="log"></div>
+<script>
+ var t = async_test();
+ log("inline script #1")
+</script>
+<svg>
+<script>
+log("inline script #2")
+var s = document.createElement("script");
+s.textContent = "log('inline script #3');";
+document.getElementsByTagName("svg")[0].appendChild(s);
+log("end inline script #2");
+</script>
+</svg>
+<script>
+log("inline script #4");
+t.step(function() {
+ assert_array_equals(eventOrder, ["inline script #1", "inline script #2", "inline script #3",
+ "end inline script #2", "inline script #4"]);
+ t.done();
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/134.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/134.html
new file mode 100644
index 00000000000..14cd5d0d36a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/134.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html><head>
+ <title>scheduler: external HTML script added by SVG script </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<div id="log"></div>
+<script>
+ var t = async_test();
+ log("inline script #1")
+</script>
+<svg>
+<script>
+log("inline script #2")
+var s = document.createElement("script");
+s.src = "scripts/include-1.js"
+document.getElementsByTagName("svg")[0].appendChild(s);
+log("end inline script #2");
+</script>
+</svg>
+<script>
+onload = t.step_func(function() {
+ assert_array_equals(eventOrder, ["inline script #1", "inline script #2",
+ "end inline script #2", "external script #1"]);
+ t.done();
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/135.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/135.html
new file mode 100644
index 00000000000..15ee859828e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/135.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html><head>
+ <title>scheduler: external SVG script added by SVG script </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<div id="log"></div>
+<script>
+ var t = async_test();
+ log("inline script #1")
+</script>
+<svg>
+<script>
+log("inline script #2")
+var s = document.createElementNS("http://www.w3.org/2000/svg", "script");
+s.setAttributeNS("http://www.w3.org/1999/xlink", "href", "scripts/include-1.js");
+document.getElementsByTagName("svg")[0].appendChild(s);
+log("end inline script #2");
+</script>
+</svg>
+<script>
+onload = t.step_func(function() {
+ assert_array_equals(eventOrder, ["inline script #1", "inline script #2",
+ "end inline script #2", "external script #1"]);
+ t.done();
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/136.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/136.html
new file mode 100644
index 00000000000..4a47e8527b1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/136.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html><head>
+ <title>scheduler: DOM added external SVG script, force-async? </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<div id="log"></div>
+<script>
+ var t = async_test(undefined, {timeout:3000});
+</script>
+<svg>
+<script>
+
+var s1 = document.createElement("script");
+s1.src = "scripts/include-1.js";
+s1.async = false;
+
+var s = document.createElementNS("http://www.w3.org/2000/svg", "script");
+s.setAttributeNS("http://www.w3.org/1999/xlink", "href", "scripts/include-2.js?pipe=trickle(d2)");
+
+document.getElementsByTagName("svg")[0].appendChild(s);
+document.getElementsByTagName("svg")[0].appendChild(s1);
+
+</script>
+</svg>
+<script>
+onload = t.step_func(function() {
+ <!-- assumes that the SVg script should be async -->
+ assert_array_equals(eventOrder, ["external script #1", "external script #2"]);
+ t.done();
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/137.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/137.html
new file mode 100644
index 00000000000..c0e695462d6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/137.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html><head>
+ <title>scheduler: SVG script empty xlink:href</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<div id="log"></div>
+<script>
+ var t = async_test(undefined, {timeout:3000});
+</script>
+<svg>
+<script xlink:href="">
+t.step(function() {assert_unreached()});
+</script>
+</svg>
+<script>
+onload = t.step_func(function() {
+ t.done();
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/138.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/138.html
new file mode 100644
index 00000000000..0eaad0765bc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/138.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html><head>
+ <title>scheduler: SVG script nested inlines</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<div id="log"></div>
+<script>
+ var t = async_test(undefined, {timeout:3000});
+</script>
+<svg>
+<script>
+t.step(function() {
+log("inline script #2");
+var a = {
+ <script>
+ t.step(function() {log("inline script #1")})
+ </script>
+a:1}
+log("end inline script #2");
+});
+</script>
+</svg>
+<script>
+onload = t.step_func(function() {
+ assert_array_equals(eventOrder, ["inline script #1", "inline script #2", "end inline script #2"]);
+ t.done();
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/139.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/139.html
new file mode 100644
index 00000000000..f1cbc158c95
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/139.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html><head>
+ <title>scheduler: SVG script nested external in inline</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<div id="log"></div>
+<script>
+ var t = async_test(undefined, {timeout:3000});
+</script>
+<svg>
+<script>
+t.step(function() {
+log("inline script #1");
+var a = {
+ <script xlink:href="scripts/include-1.js">
+ t.step(function() {assert_unreached()})
+ </script>
+a:1}
+log("end inline script #1");
+});
+</script>
+</svg>
+<script>
+onload = t.step_func(function() {
+ assert_array_equals(eventOrder, ["external script #1", "inline script #1", "end inline script #1"]);
+ t.done();
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/140.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/140.html
new file mode 100644
index 00000000000..fbdd1c76e86
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/140.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html><head>
+ <title>scheduler: SVG script nested inline in external</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<div id="log"></div>
+<script>
+ var t = async_test(undefined, {timeout:3000});
+</script>
+<svg>
+<script xlink:href="scripts/include-1.js">
+ <script>
+ t.step(function() {log("inline script #1")});
+ </script>
+</script>
+</svg>
+<script>
+onload = t.step_func(function() {
+ assert_array_equals(eventOrder, ["inline script #1", "external script #1"]);
+ t.done();
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/141.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/141.html
new file mode 100644
index 00000000000..a237373bbde
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/141.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html><head>
+ <title>scheduler: SVG inline script that document.writes inline script </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<div id="log"></div>
+<script>
+ var t = async_test(undefined, {timeout:3000});
+</script>
+<svg>
+<script>
+ t.step(function() {
+ log('inline script #1');
+ document.write("<" + "script>t.step(function() {log('inline script #2')})<" + "/script>");
+ log('end inline script #1');
+ });
+</script>
+</svg>
+<script>
+onload = t.step_func(function() {
+ assert_array_equals(eventOrder, ["inline script #1", "inline script #2", "end inline script #1"]);
+ t.done();
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/142.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/142.html
new file mode 100644
index 00000000000..91f19f7577c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/142.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html><head>
+ <title>scheduler: SVG inline script that document.writes external script </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<div id="log"></div>
+<script>
+ var t = async_test(undefined, {timeout:3000});
+</script>
+<svg>
+<script>
+ t.step(function() {
+ log('inline script #1');
+ document.write("<" + "script xlink:href='scripts/include-1.js'><" + "/script>");
+ log('end inline script #1');
+ });
+</script>
+<script>t.step(function() {log("inline script #2")});</script>
+</svg>
+<script>
+onload = t.step_func(function() {
+ assert_array_equals(eventOrder, ["inline script #1", "end inline script #1", "external script #1", "inline script #2"]);
+ t.done();
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/143.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/143.html
new file mode 100644
index 00000000000..9c0230d89dc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/143.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html><head>
+ <title>scheduler: SVG nested inline script that document.writes inline script </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<div id="log"></div>
+<script>
+ var t = async_test(undefined, {timeout:3000});
+</script>
+<svg>
+<script>
+ t.step(function() {
+ log('inline script #3');
+ });
+ <script>
+ log("inline script #1")
+ document.write("<" + "script>t.step(function() {log('inline script #2')})<" + "/script><" + "/script>");
+ </script>
+ t.step(function() {
+ assert_unreached():
+ });
+</script>
+</svg>
+<script>
+onload = t.step_func(function() {
+ assert_array_equals(eventOrder, ["inline script #1", "inline script #2", "inline script #3"]);
+ t.done();
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/144.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/144.html
new file mode 100644
index 00000000000..96a1f4777fb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/144.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html><head>
+ <title>scheduler: SVG inline script changing the type attribute </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<div id="log"></div>
+<script>
+ var t = async_test(undefined, {timeout:3000});
+</script>
+<svg>
+<script type="text/plain">
+t.step(function() {assert_unreached()});
+</script>
+</svg>
+<script>
+t.step(function() {
+ var s = document.querySelector("svg > script");
+ s.textContent = "t.step(function() {log('inline script #1')})";
+ s.type = "";
+ s.parentNode.appendChild(s);
+});
+onload = t.step_func(function() {
+ assert_array_equals(eventOrder, ["inline script #1"]);
+ t.done();
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/145.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/145.html
new file mode 100644
index 00000000000..655a2132b85
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/145.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html><head>
+ <title>scheduler: SVG inline script adding text to empty script </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<div id="log"></div>
+<script>
+ var t = async_test(undefined, {timeout:3000});
+</script>
+<svg>
+<script></script>
+</svg>
+<script>
+t.step(function() {
+ var s = document.querySelector("svg > script");
+ s.textContent = "t.step(function() {log('inline script #1')})";
+});
+onload = t.step_func(function() {
+ assert_array_equals(eventOrder, ["inline script #1"]);
+ t.done();
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/146.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/146.html
new file mode 100644
index 00000000000..c666a51a310
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/146.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html><head>
+ <title>scheduler: SVG script adding src attribute </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<div id="log"></div>
+<script>var t = async_test();</script>
+<svg>
+<script></script>
+</svg>
+<script>
+t.step(function() {
+ var s = document.querySelector("svg > script");
+ s.src = "scripts/include-1.js";
+});
+onload = t.step_func(function() {
+ assert_array_equals(eventOrder, ["external script #1"]);
+ t.done();
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/147.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/147.html
new file mode 100644
index 00000000000..0542380ff7f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/147.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html><head>
+ <title>scheduler: insert multiple inline scripts; first script moves subsequent scripts </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+<div id="log"></div>
+<script>
+var t = async_test();
+</script>
+<div id="container"></div>
+<script>
+t.step(function() {
+ log("inline script #1");
+ var container = document.getElementById("container");
+
+ var frag = document.createDocumentFragment();
+ var frag_script_1 = document.createElement("script");
+ var frag_script_2 = document.createElement("script");
+ frag_script_2.id = "movee";
+ var frag_script_3 = document.createElement("script");
+
+ frag_script_1.textContent = "t.step(function() {log('inline script #2'); var s = document.getElementById('movee'); s.parentNode.appendChild(s)});";
+ frag_script_2.textContent = "t.step(function() {log('inline script #3');})";
+ frag_script_3.textContent = "t.step(function() {log('inline script #4');})";
+
+ [frag_script_1, frag_script_2, frag_script_3].forEach(function(x) {frag.appendChild(x)});
+
+ container.appendChild(frag);
+});
+
+onload = t.step_func(function() {
+ assert_array_equals(eventOrder, ["inline script #1", "inline script #2", "inline script #3", "inline script #4"]);
+ t.done();
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/148.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/148.html
new file mode 100644
index 00000000000..72a91438042
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/148.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html><head>
+ <title>scheduler: insert multiple inline scripts; first script deletes subsequent script </title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+<div id="log"></div>
+<script>
+var t = async_test();
+</script>
+<div id="container"></div>
+<script>
+t.step(function() {
+ log("inline script #1");
+ var container = document.getElementById("container");
+
+ var frag = document.createDocumentFragment();
+ var frag_script_1 = document.createElement("script");
+ var frag_script_2 = document.createElement("script");
+ frag_script_2.id = "delete";
+ var frag_script_3 = document.createElement("script");
+
+ frag_script_1.textContent = "t.step(function() {log('inline script #2'); var s = document.getElementById('delete'); s.parentNode.removeChild(s)});";
+ frag_script_2.textContent = "t.step(function() {log('inline script #3');})";
+ frag_script_3.textContent = "t.step(function() {log('inline script #4');})";
+
+ [frag_script_1, frag_script_2, frag_script_3].forEach(function(x) {frag.appendChild(x)});
+
+ container.appendChild(frag);
+});
+
+onload = t.step_func(function() {
+ assert_array_equals(eventOrder, ["inline script #1", "inline script #2", "inline script #3", "inline script #4"]);
+ t.done();
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/149.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/149.html
new file mode 100644
index 00000000000..6fe9b68ba21
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/149.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html><head>
+ <title>scheduler: event/for attribute on script</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="testlib/testlib.js"></script>
+</head>
+<body>
+<div id="log"></div>
+<script>
+
+attributes = [
+ {for:"window", event:"onload()", expect:true},
+ {for:"window", event:"onload", expect:true},
+ {for:" WINdow\t\n", event:"ONload\t\n", expect:true},
+ {for:"window", event:"load", expect:false},
+ {for:"window", event:"onpageshow", expect:false},
+ {for:"document", event:"onload", expect:false},
+]
+
+function test_maker(array_name) {
+ return function(x, i) {
+ var title = "for='" + x.for + "' event='" + x.event + "' " + array_name.replace("_", " ") + " " + (x.expect ? "executes immediately" : "does not execute");
+ script_content = "var d =" + array_name + "[" + i + "];"
+ script_content += x.expect?"d[1].step(function() {d[3] = true});":"d[1].step(function() {assert_unreached()});"
+ return [x, async_test(title), script_content, false];
+ }
+}
+
+parser_inserted = attributes.map(test_maker("parser_inserted"));
+dom_inserted = attributes.map(test_maker("dom_inserted"));
+
+parser_inserted.forEach(function(x) {
+ var d = x[0];
+ document.write("<script for='" + d.for + "' event='" + d.event + "'>" + x[2] + "<\/script>");
+});
+
+dom_inserted.forEach(function(x) {
+ var d = x[0];
+ var s = document.createElement("script");
+ s.setAttribute("event", d.event);
+ s.setAttribute("for", d.for);
+ s.textContent = x[2];
+ document.body.appendChild(s);
+});
+</script>
+
+<script>
+var all_tests = parser_inserted.concat(dom_inserted);
+
+all_tests.filter(function(x) {return x[0]["expect"]}).forEach(function(x) {var t = x[1]; t.step(function() {assert_true(x[3])});})
+
+onload = function() {
+ all_tests.forEach(function(x) {var t = x[1]; t.step(function() {t.done()})});
+}
+</script>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/css/background.css b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/css/background.css
new file mode 100644
index 00000000000..1e601c56b53
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/css/background.css
@@ -0,0 +1,3 @@
+ #test {background-image:url("1x1-green.png?pipe=trickle(d2)");
+ background-repeat:repeat;
+ background-color:orange;} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/css/import.css b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/css/import.css
new file mode 100644
index 00000000000..ee2a5ee274a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/css/import.css
@@ -0,0 +1 @@
+@import("background.css") \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/pages/helloworld-postMessage.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/pages/helloworld-postMessage.html
new file mode 100644
index 00000000000..cae2797a483
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/pages/helloworld-postMessage.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html><head>
+ <title> TC component </title>
+</head>
+<body>
+
+ <p>This page should appear in popup or frame</p>
+
+ <script type="text/javascript">
+ var target = opener || top;
+ var id = location.search?' '+location.search.substring(1) : '';
+ target.log('frame/popup script'+id);
+ window.onload=function(){
+ target.log('load event inside frame/popup script'+id);
+ target.postMessage('msg evt frame/popup script'+id, '*');
+ }
+ </script>
+
+</body></html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/pages/helloworld.html b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/pages/helloworld.html
new file mode 100644
index 00000000000..30d5c5fda16
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/pages/helloworld.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html><head>
+ <title> TC component </title>
+</head>
+<body>
+
+ <p>This page should appear in popup or frame</p>
+
+ <script type="text/javascript">
+ var target = top || opener;
+ var id = location.search?' '+parseInt(location.search.substring(1)) : '';
+ target.log('frame/popup script'+id);
+ </script>
+
+</body></html>
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/count-script-tags.js b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/count-script-tags.js
new file mode 100644
index 00000000000..8fba4ecb3c0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/count-script-tags.js
@@ -0,0 +1 @@
+log('script tags in DOM: '+document.getElementsByTagName('script').length); \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/find-body.js b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/find-body.js
new file mode 100644
index 00000000000..22e1050ffc3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/find-body.js
@@ -0,0 +1,2 @@
+log('document.body: '+(document.body?'<BODY>':null));
+var findBodyLoaded=true; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/find-foo.js b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/find-foo.js
new file mode 100644
index 00000000000..52d0ec91cb4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/find-foo.js
@@ -0,0 +1,2 @@
+log('found #foo element: ' + ( document.getElementById('foo') ? 'YES' : 'NO' ));
+var findFooLoaded=true; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/include-1.js b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/include-1.js
new file mode 100644
index 00000000000..8ff291ad57e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/include-1.js
@@ -0,0 +1 @@
+log('external script #1'); \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/include-10.js b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/include-10.js
new file mode 100644
index 00000000000..8dc770ddc05
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/include-10.js
@@ -0,0 +1 @@
+document.write("<script src='scripts/include-9.js?pipe=trickle(d2)' defer></script>");
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/include-11.js b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/include-11.js
new file mode 100644
index 00000000000..a822dd8baf2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/include-11.js
@@ -0,0 +1,4 @@
+log("external script before adding iframe");
+var iframe = document.createElement("iframe");
+iframe.src = "data:text/html,<script>parent.log('script in iframe')</script>"
+document.body.appendChild(iframe); \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/include-12.js b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/include-12.js
new file mode 100644
index 00000000000..7ced0fb424e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/include-12.js
@@ -0,0 +1,4 @@
+log("external script before adding object");
+var object = document.createElement("object");
+object.data = "data:text/html,<script>parent.log('script in object')</script>"
+document.body.appendChild(object); \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/include-2.js b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/include-2.js
new file mode 100644
index 00000000000..31319423afd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/include-2.js
@@ -0,0 +1 @@
+log('external script #2'); \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/include-3.js b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/include-3.js
new file mode 100644
index 00000000000..53352e0f83c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/include-3.js
@@ -0,0 +1,3 @@
+log('external script before doc write');
+document.write( '<script>log(\'document.write external script\');</script>');
+log('external script after doc write'); \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/include-4.js b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/include-4.js
new file mode 100644
index 00000000000..0597a226242
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/include-4.js
@@ -0,0 +1,3 @@
+log('include-4 before doc write');
+document.write( '<script src="scripts/include-3.js"></script>');
+log('include-4 after doc write'); \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/include-5.js b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/include-5.js
new file mode 100644
index 00000000000..52952d73791
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/include-5.js
@@ -0,0 +1,7 @@
+log('include-5 before removing scripts');
+var scripts=[].slice.call(document.getElementsByTagName('script'), 3);
+for(var i = 0; i < scripts.length; i++) {
+ var s = scripts[i];
+ s.parentNode.removeChild(s);
+}
+log('include-5 after removing scripts');
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/include-6.js b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/include-6.js
new file mode 100644
index 00000000000..77da2af2329
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/include-6.js
@@ -0,0 +1,6 @@
+top.log(
+ 'external script (#foo found? ' +
+ (document.getElementById('foo') ? 'YES' : 'NO' ) +
+ ')'
+);
+top.include6Loaded=true; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/include-7.js b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/include-7.js
new file mode 100644
index 00000000000..57c55080158
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/include-7.js
@@ -0,0 +1 @@
+log('external script #7'); \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/include-8.js b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/include-8.js
new file mode 100644
index 00000000000..960f2129feb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/include-8.js
@@ -0,0 +1,4 @@
+log("external script #8");
+var s = document.createElement("script")
+s.src='scripts/include-9.js?pipe=trickle(d2)'
+document.body.appendChild(s);
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/include-9.js b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/include-9.js
new file mode 100644
index 00000000000..9042882024b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/scripts/include-9.js
@@ -0,0 +1,2 @@
+log("external script #9");
+test(); \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/testlib/testlib.js b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/testlib/testlib.js
new file mode 100644
index 00000000000..7b556b150df
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/Opera/script_scheduling/testlib/testlib.js
@@ -0,0 +1,43 @@
+/*
+* Utility functions for script scheduler test
+*/
+(function(){ /* namespace hiding local variables like arOrderOfAllEvents from global scope */
+ window.testlib = {};
+ window.eventOrder = [];
+ var arNumberOfScriptsParsedPerEvent=[];
+ window.log = function (str){
+ eventOrder.push(str);
+ arNumberOfScriptsParsedPerEvent.push(document.getElementsByTagName('script').length);
+ }
+
+ window.testlib.addScript = function(source, attributes, parent, firstInParent,funcPrepare) {
+ try{
+ parent = parent||document.body;
+ var script = document.createElement('script');
+ if(funcPrepare) {
+ funcPrepare(script);
+ }
+ if(source)script.appendChild( document.createTextNode(source) );
+ for( var name in attributes){
+ if(/^on/i.test(name)) {
+ script[name] = attributes[name];
+ } else {
+ script.setAttribute(name, attributes[name]);
+ }
+ }
+ if (firstInParent && parent.firstChild) {
+ parent.insertBefore(script, parent.firstChild);
+ } else {
+ parent.appendChild(script);
+ }
+ } catch(e) {
+ log('ERROR when adding script to DOM!');
+ alert(e);
+ }
+ return script;
+ }
+
+ window.testlib.urlParam = function(relativeURL) {
+ return location.href.replace( /\d*\.html$/, relativeURL);
+ }
+})(); \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/old-tests/submission/migration.txt b/tests/wpt/web-platform-tests/old-tests/submission/migration.txt
new file mode 100644
index 00000000000..9480d754ad0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/old-tests/submission/migration.txt
@@ -0,0 +1,26 @@
+
+TODO:
+
+ Google (not sure how much of that is what's already in)
+ Infraware (these come bundled with resources and require lots of rewriting)
+ Intel (need to check how much overlap there is with existing stuff)
+ Microsoft (lots of things, need to check overlap)
+ Ms2ger (Ms2ger is doing those)
+ Opera (split into multiple PRs)
+ TestTWF_Paris
+ W3C
+
+DONE:
+
+ Apple
+ AryehGregor
+ Baidu
+ Comcast
+ DavidCarlisle
+ html5bidi
+ MathiasBynens
+ PhilipTaylor
+ MOSQUITO
+ Mozilla
+ WebKit
+ \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/page-visibility/idlharness.html b/tests/wpt/web-platform-tests/page-visibility/idlharness.html
new file mode 100644
index 00000000000..c8086a1bc62
--- /dev/null
+++ b/tests/wpt/web-platform-tests/page-visibility/idlharness.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Page Visibility IDL tests</title>
+<link rel="author" title="W3C" href="http://www.w3.org/" />
+<link rel="help" href="http://www.w3.org/TR/page-visibility/#sec-document-interface"/>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/WebIDLParser.js"></script>
+<script src="/resources/idlharness.js"></script>
+</head>
+<body>
+<h1>Page Visibility IDL tests</h1>
+
+<pre id='untested_idl' style='display:none'>
+interface Document {
+};
+</pre>
+
+<pre id='idl'>
+enum VisibilityState { "hidden", "visible", "prerender", "unloaded" };
+
+partial interface Document {
+ readonly attribute boolean hidden;
+ readonly attribute VisibilityState visibilityState;
+};
+</pre>
+
+<script>
+
+(function() {
+ var idl_array = new IdlArray();
+
+ idl_array.add_untested_idls(document.getElementById("untested_idl").textContent);
+ idl_array.add_idls(document.getElementById("idl").textContent);
+
+ idl_array.add_objects({Document: ["window.document"]});
+
+ idl_array.test();
+})();
+
+</script>
+
+<div id="log"></div>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/page-visibility/resources/blank_page_green.html b/tests/wpt/web-platform-tests/page-visibility/resources/blank_page_green.html
new file mode 100644
index 00000000000..b8a1947b77e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/page-visibility/resources/blank_page_green.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
+ <title>Green Test Page</title>
+ </head>
+ <body style="background-color:#00FF00;">
+ <h1>Placeholder</h1>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/page-visibility/resources/pagevistestharness.js b/tests/wpt/web-platform-tests/page-visibility/resources/pagevistestharness.js
new file mode 100644
index 00000000000..d53d73b4235
--- /dev/null
+++ b/tests/wpt/web-platform-tests/page-visibility/resources/pagevistestharness.js
@@ -0,0 +1,121 @@
+/*
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+*/
+
+//
+// Helper Functions for PageVisibility W3C tests
+//
+var VISIBILITY_STATES =
+{
+ HIDDEN: "hidden",
+ VISIBLE: "visible"
+};
+
+var feature_check = false;
+
+//
+// All test() functions in the WebPerf PageVis test suite should use pv_test() instead.
+//
+// pv_test() validates the document.hidden and document.visibilityState attributes
+// exist prior to running tests and immediately shows a failure if they do not.
+//
+
+function pv_test(func, msg, doc)
+{
+ if (!doc)
+ {
+ doc = document;
+ }
+
+ // only run the feature check once, unless func == null, in which case,
+ // this call is intended as a feature check
+ if (!feature_check)
+ {
+ feature_check = true;
+
+ var hiddenVal = doc.hidden;
+ var visStateVal = doc.visibilityState;
+
+ // show a single error that the Page Visibility feature is undefined
+ test(function()
+ {
+ assert_true(hiddenVal !== undefined && hiddenVal != null,
+ "document.hidden is defined and not null.");},
+ "document.hidden is defined and not null.");
+
+ test(function()
+ {
+ assert_true(visStateVal !== undefined && hiddenVal != null,
+ "document.visibilityState is defined and not null.");},
+ "document.visibilityState is defined and not null.");
+
+ }
+
+ if (func)
+ {
+ test(func, msg);
+ }
+}
+
+
+function test_feature_exists(doc, msg)
+{
+ if (!msg)
+ {
+ msg = "";
+ }
+ var hiddenMsg = "document.hidden is defined" + msg + ".";
+ var stateMsg = "document.visibilityState is defined" + msg + ".";
+ pv_test(function(){assert_true(document.hidden !== undefined, hiddenMsg);}, hiddenMsg, doc);
+ pv_test(function(){assert_true(document.visibilityState !== undefined, stateMsg);}, stateMsg, doc);
+}
+
+//
+// Common helper functions
+//
+
+function test_true(value, msg)
+{
+ pv_test(function() { assert_true(value, msg); }, msg);
+}
+
+function test_equals(value, equals, msg)
+{
+ pv_test(function() { assert_equals(value, equals, msg); }, msg);
+}
+
+//
+// asynchronous test helper functions
+//
+
+function add_async_result(test_obj, pass_state)
+{
+ // add assertion to manual test for the pass state
+ test_obj.step(function() { assert_true(pass_state) });
+
+ // end manual test
+ test_obj.done();
+}
+
+function add_async_result_assert(test_obj, func)
+{
+ // add assertion to manual test for the pass state
+ test_obj.step(func);
+
+ // end manual test
+ test_obj.done();
+}
+
+var open_link;
+function TabSwitch()
+{
+ //var open_link = window.open("http://www.bing.com");
+ open_link = window.open('', '_blank');
+ setTimeout(function() { open_link.close(); }, 2000);
+}
diff --git a/tests/wpt/web-platform-tests/page-visibility/test_attributes_exist.html b/tests/wpt/web-platform-tests/page-visibility/test_attributes_exist.html
new file mode 100644
index 00000000000..748161fdf8f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/page-visibility/test_attributes_exist.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>Page Visibility API Definition</title>
+
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="resources/pagevistestharness.js"></script>
+ </head>
+ <body>
+ <h1>Description</h1>
+ <p>This test validates that all of the attributes associated with the Page Visibility feature exist
+ (but does not validate that their values are correct).</p>
+
+ <div id="log"></div>
+
+ <script type="text/javascript" >
+ test_feature_exists();
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/page-visibility/test_child_document.html b/tests/wpt/web-platform-tests/page-visibility/test_child_document.html
new file mode 100644
index 00000000000..77ec8f8fd2e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/page-visibility/test_child_document.html
@@ -0,0 +1,94 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>Page Visibility API Child Document Test</title>
+
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="resources/pagevistestharness.js"></script>
+
+ <style type="text/css">
+ iframe
+ {
+ width:250px;
+ height:250px;
+ margin-left:5px;
+ }
+
+ div.docs
+ {
+ position:relative;
+ float:left;
+ text-align:center;
+ margin:10px;
+ border:solid 1px black;
+ padding:3px;
+ }
+ </style>
+
+ <script type="text/javascript" >
+ setup({explicit_done: true});
+
+ function onload_test()
+ {
+ pv_test();
+
+ var frames = document.getElementsByTagName("iframe");
+ var doc, doc_name;
+
+ for (var i = 0; i < frames.length; i++)
+ {
+ doc = frames[i].contentDocument;
+ doc_name = "IFrame with " + frames[i].id;
+
+ pv_test(function()
+ {
+ test_feature_exists(doc, " for frame with " + frames[i].id);
+ });
+
+ test_equals(doc.visibilityState, VISIBILITY_STATES.VISIBLE,
+ "document.visibilityState for frame with " +
+ frames[i].id + " == " +
+ VISIBILITY_STATES.VISIBLE);
+ }
+
+ done();
+ }
+ </script>
+ </head>
+ <body onload="onload_test()">
+ <h1>Description</h1>
+ <p>This test validates that, within child documents, all of the Page Visibility API attributes exist,
+ are read-only, and match the value of the attributes within the parent document.</p>
+
+ <div id="log"></div>
+
+ <br/>
+
+ <div class="docs">
+ IFrame with no style attribute
+ <br/>
+ <iframe id="no style attribute" src="resources/blank_page_green.html">
+ iframes unsupported
+ </iframe>
+ </div>
+
+ <div class="docs">
+ IFrame with "display:none" style<br/>
+ <iframe id="'display:none' style" style="display:none"
+ src="resources/blank_page_green.html">
+ iframes unsupported
+ </iframe>
+ </div>
+
+ <div class="docs">
+ IFrame with "visibility:hidden" style
+ <br/>
+ <iframe id="'visibility:hidden' style" style="visibility:hidden"
+ src="resources/blank_page_green.html">
+ iframes unsupported
+ </iframe>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/page-visibility/test_default_view.html b/tests/wpt/web-platform-tests/page-visibility/test_default_view.html
new file mode 100644
index 00000000000..6e2f97084f4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/page-visibility/test_default_view.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>Page Visibility Null Default View Test</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="resources/pagevistestharness.js"></script>
+
+ <script type="text/javascript" >
+ setup({explicit_done: true});
+
+ function onload_test()
+ {
+ // inject a windowless subdocument as a child of the root document <html> element
+ var subDoc = document.implementation.createDocument('resources/blank_page_green.html', 'html', null);
+
+ // Test precondition: ensure subdocument has a null default view
+ test_true(subDoc.defaultView == null, "windowless subdocument generated for test has a null default view");
+
+ // check that feature exists within subdocument
+ test_feature_exists(subDoc, 'windowless subdocument');
+
+ // check that the subdocument has a hidden visibility state
+ test_true(subDoc.hidden,
+ "hidden == true for windowless subdocuments with a null default view");
+ test_equals(subDoc.visibilityState, VISIBILITY_STATES.HIDDEN,
+ "visibilityState == " + VISIBILITY_STATES.HIDDEN +
+ " for windowless subdocuments with a null default view");
+
+ done();
+ }
+ </script>
+ </head>
+ <body onload="onload_test()">
+ <h1>Description</h1>
+ <p>This test validates that document.hidden == false and
+ document.visibilityState == "visible" for windowless subdocuments.</p>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/page-visibility/test_minimize-manual.html b/tests/wpt/web-platform-tests/page-visibility/test_minimize-manual.html
new file mode 100644
index 00000000000..28e8486769c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/page-visibility/test_minimize-manual.html
@@ -0,0 +1,188 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>Page Visibility API Operation While Minimizing Browser Window</title>
+ <meta name="flags" content="interact" />
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="resources/pagevistestharness.js"></script>
+
+ </head>
+ <body>
+ <h1>Description</h1>
+ <p>This test validates that the page properly becomes hidden and visible due to minimizing, maximizing, and
+ restoring the browser window.</p>
+
+ <h1>Manual Test Steps:</h1>
+ <p>
+ <ol>
+ <li> Ensure this page is the foreground and click the "Start Test"</li>
+ <li> Minimize the browser</li>
+ <li> Restore or maximize the browser</li>
+ </ol>
+ Note: This test will automatically timeout and fail if not completed within 60 seconds.
+ </p>
+
+ <button onclick="start_test();">Start Test</button>
+
+ <div id="log"></div>
+
+ <br />
+ IFrame with default style:
+ <br />
+ <iframe id="childDocShown" src="resources/blank_page_green.html">
+ iframes unsupported
+ </iframe>
+ <hr />
+ IFrame with "display:none" style:
+ <br />
+ <iframe id="childDocHidden" src="resources/blank_page_green.html" style="display:none">
+ iframes unsupported
+ </iframe>
+
+ <script type="text/javascript" >
+ var child_doc_shown = null;
+ var child_doc_hidden = null;
+ var transition_mode;
+ var manual_test = null;
+
+ var expected_notification_count = 2;
+ var notification_count = new Array();
+ var page_docs = new Array();
+ var notification_handlers = new Array();
+ var two_notifications = false;
+
+ var PAGE_HIDDEN_VAL = "hidden";
+ var PAGE_VISIBLE_VAL = "visible";
+
+ setup({ explicit_done: true });
+
+ function test_transition_init()
+ {
+ child_doc_shown = document.getElementById("childDocShown").contentDocument;
+ child_doc_hidden = document.getElementById("childDocHidden").contentDocument;
+
+ // fill in data for page documents
+ page_docs.push([document, "document"]);
+ page_docs.push([child_doc_shown, "document.getElementById(\"childDocShown\").contentDocument"]);
+ page_docs.push([child_doc_hidden, "document.getElementById(\"childDocHidden\").contentDocument"]);
+
+ notification_handlers[0] = function(){ VerifyNotification(0); };
+ notification_handlers[1] = function(){ VerifyNotification(1); };
+ notification_handlers[2] = function(){ VerifyNotification(2); };
+
+ for (var i in page_docs)
+ {
+ notification_count[i] = 0;
+ page_docs[i][0].addEventListener("visibilitychange", notification_handlers[i]);
+ }
+
+ test_true(!document.hidden, "Page is visible on load.");
+ test_true((!child_doc_shown.hidden) && (!child_doc_hidden.hidden),
+ "All IFrame child documents are visible on load.");
+
+ document.addEventListener("visibilitychange", notification_handlers[0]);
+ document.addEventListener("visibilitychange", VerifyTwoNotifications);
+
+ manual_test = AddManual("Browser minimization has occurred.");
+ }
+
+ function VerifyNotification(doc_index)
+ {
+ doc = page_docs[doc_index][0];
+ docName = page_docs[doc_index][1];
+
+ notification_count[doc_index]++;
+ switch (notification_count[doc_index])
+ {
+ case 1:
+ // First step, check page visibility after tab deselection / minimization.
+ // hidden should change to true; visibilityState should change to "hidden"
+ test_true(doc.hidden, docName + ".hidden == true (after browser frame minimization)");
+ test_true(doc.visibilityState == PAGE_HIDDEN_VAL,
+ docName + ".visibilityState == \"hidden\" (after browser frame minimization)");
+
+ break;
+
+ case 2:
+ //Second step, check page visibility after tab reselection / maximization / restoration.
+ // hidden should change to false; visibilityState should change to "visible"
+ test_true(!doc.hidden,
+ docName + ".hidden == false (after browser frame maximization / restoration)");
+ test_true(doc.visibilityState == PAGE_VISIBLE_VAL,
+ docName + ".visibilityState == \"visible\" (after browser frame maximization / " +
+ "restoration)");
+
+ // perform tests specific to the main document
+ if (doc == document)
+ {
+ //Verify that a second registration to a different callback also occurred
+ test_true(two_notifications, "Two registrations (different callbacks) occurred.");
+
+ //Verify that a second registration to the same callback did not occur
+ test_equals(notification_count[doc_index],
+ expected_notification_count,
+ "Two registrations (same callback) did not occur.");
+
+ // pass the manual item associated with these tests
+ AddManualResult(manual_test, true);
+
+ document.removeEventListener("visibilitychange", VerifyTwoNotifications);
+
+ // schedule the rollup
+ setTimeout(VerifyAllNotifications, 200);
+ }
+
+ //Remove all event listeners and verify that the event does not fire
+ doc.removeEventListener("visibilitychange", notification_handlers[doc_index]);
+ break;
+ case 3:
+ //This step should not have occurred since the event handlers were cleared
+ test_true(false, "Event did not fire when event listener is removed.");
+
+ //On final step, schedule the rollup
+ setTimeout(done, 2000);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ function VerifyAllNotifications()
+ {
+ //On final step, schedule the rollup
+ setTimeout(done, 1000);
+ }
+
+ function VerifyTwoNotifications()
+ {
+ //This is a duplicate registration on visibilitychange and
+ //should never get fired. Check that duplicate_notification
+ //is false to verify that this never occurred.
+ two_notifications = true;
+ }
+
+ // Manual Test helper functions
+ function AddManual(test)
+ {
+ // add asynchronous test for manual tests
+ return async_test(test);
+ }
+
+ function AddManualResult(oManualTest, passState)
+ {
+ // add assertion to manual test for the pass state
+ oManualTest.step(function() {assert_true(passState)});
+
+ // end manual test
+ oManualTest.done();
+ }
+
+ function start_test()
+ {
+ test_transition_init();
+ }
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/page-visibility/test_read_only.html b/tests/wpt/web-platform-tests/page-visibility/test_read_only.html
new file mode 100644
index 00000000000..6d3702292dc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/page-visibility/test_read_only.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>Page Visibility API is Read Only</title>
+
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="resources/pagevistestharness.js"></script>
+
+ <script type="text/javascript">
+ setup({ explicit_done: true });
+ function onload_test()
+ {
+ //check for feature definition first before attempting to overwrite
+ pv_test();
+
+ //Check document.hidden
+ document.hidden = "new value";
+ test_true(document.hidden !== "new value", 'document.hidden is read only.');
+
+ //Check document.visibilityState
+ document.visibilityState = "new value";
+ test_true(document.visibilityState !== "new value",
+ "document.visibilityState is read only.");
+
+ done();
+ }
+ </script>
+ </head>
+ <body onload="onload_test();">
+ <h1>Description</h1>
+ <p>This test validates that the Page Visibility attributes are read only.</p>
+
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/page-visibility/test_tab_state_change-manual.html b/tests/wpt/web-platform-tests/page-visibility/test_tab_state_change-manual.html
new file mode 100644
index 00000000000..c701e507862
--- /dev/null
+++ b/tests/wpt/web-platform-tests/page-visibility/test_tab_state_change-manual.html
@@ -0,0 +1,186 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>Page Visibility API Operation While Changing Tabs</title>
+ <meta name="flags" content="interact" />
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="resources/pagevistestharness.js"></script>
+
+ </head>
+ <body>
+ <h1>Description</h1>
+ <p>This test validates that the page properly becomes hidden and visible due to switching tabs.</p>
+
+ <h1>Manual Test Steps:</h1>
+ <p>
+ <ol>
+ <li> Ensure this page is the foreground and click the "Start Test"</li>
+ <li> Switch to another tab</li>
+ <li> Return to the current tab containing this test page</li>
+ </ol>
+ Note: This test will automatically timeout and fail if not completed within 60 seconds.
+ </p>
+
+ <button onclick="start_test();">Start Test</button>
+
+ <div id="log"></div>
+
+ <br />
+ IFrame with default style:
+ <br />
+ <iframe id="childDocShown" src="resources/blank_page_green.html">
+ iframes unsupported
+ </iframe>
+ <hr />
+ IFrame with "display:none" style:
+ <br />
+ <iframe id="childDocHidden" src="resources/blank_page_green.html" style="display:none">
+ iframes unsupported
+ </iframe>
+
+ <script type="text/javascript" >
+ var child_doc_shown = null;
+ var child_doc_hidden = null;
+ var transition_mode;
+ var manual_test = null;
+
+ var expected_notification_count = 2;
+ var notification_count = new Array();
+ var page_docs = new Array();
+ var notification_handlers = new Array();
+ var two_notifications = false;
+
+ var PAGE_HIDDEN_VAL = "hidden";
+ var PAGE_VISIBLE_VAL = "visible";
+
+ setup({ explicit_done: true });
+
+ function test_transition_init()
+ {
+ child_doc_shown = document.getElementById("childDocShown").contentDocument;
+ child_doc_hidden = document.getElementById("childDocHidden").contentDocument;
+
+ // fill in data for page documents
+ page_docs.push([document, "document"]);
+ page_docs.push([child_doc_shown, "document.getElementById(\"childDocShown\").contentDocument"]);
+ page_docs.push([child_doc_hidden, "document.getElementById(\"childDocHidden\").contentDocument"]);
+
+ notification_handlers[0] = function(){ VerifyNotification(0); };
+ notification_handlers[1] = function(){ VerifyNotification(1); };
+ notification_handlers[2] = function(){ VerifyNotification(2); };
+
+ for (var i in page_docs)
+ {
+ notification_count[i] = 0;
+ page_docs[i][0].addEventListener("visibilitychange", notification_handlers[i]);
+ }
+
+ test_true(!document.hidden, "Page is visible on load.");
+ test_true((!child_doc_shown.hidden) && (!child_doc_hidden.hidden),
+ "All IFrame child documents are visible on load.");
+
+ document.addEventListener("visibilitychange", notification_handlers[0]);
+ document.addEventListener("visibilitychange", VerifyTwoNotifications);
+
+ manual_test = AddManual("Browser tab switch has occurred.");
+ }
+
+ function VerifyNotification(doc_index)
+ {
+ doc = page_docs[doc_index][0];
+ docName = page_docs[doc_index][1];
+
+ notification_count[doc_index]++;
+ switch (notification_count[doc_index])
+ {
+ case 1:
+ // First step, check page visibility after tab deselection / minimization.
+ // hidden should change to true; visibilityState should change to "hidden"
+ test_true(doc.hidden, docName + ".hidden == true (after tab switch)");
+ test_true(doc.visibilityState == PAGE_HIDDEN_VAL,
+ docName + ".visibilityState == \"hidden\" (after tab switch)");
+
+ break;
+
+ case 2:
+ //Second step, check page visibility after tab reselection / maximization / restoration.
+ // hidden should change to false; visibilityState should change to "visible"
+ test_true(!doc.hidden,
+ docName + ".hidden == false (after return to original tab)");
+ test_true(doc.visibilityState == PAGE_VISIBLE_VAL,
+ docName + ".visibilityState == \"visible\" (after return to original tab)");
+
+ // perform tests specific to the main document
+ if (doc == document)
+ {
+ //Verify that a second registration to a different callback also occurred
+ test_true(two_notifications, "Two registrations (different callbacks) occurred.");
+
+ //Verify that a second registration to the same callback did not occur
+ test_equals(notification_count[doc_index],
+ expected_notification_count,
+ "Two registrations (same callback) did not occur.");
+
+ // pass the manual item associated with these tests
+ AddManualResult(manual_test, true);
+
+ document.removeEventListener("visibilitychange", VerifyTwoNotifications);
+
+ // schedule the rollup
+ setTimeout(VerifyAllNotifications, 200);
+ }
+
+ //Remove all event listeners and verify that the event does not fire
+ doc.removeEventListener("visibilitychange", notification_handlers[doc_index]);
+ break;
+ case 3:
+ //This step should not have occurred since the event handlers were cleared
+ test_true(false, "Event did not fire when event listener is removed.");
+
+ //On final step, schedule the rollup
+ setTimeout(done, 2000);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ function VerifyAllNotifications()
+ {
+ //On final step, schedule the rollup
+ setTimeout(done, 1000);
+ }
+
+ function VerifyTwoNotifications()
+ {
+ //This is a duplicate registration on visibilitychange and
+ //should never get fired. Check that duplicate_notification
+ //is false to verify that this never occurred.
+ two_notifications = true;
+ }
+
+ // Manual Test helper functions
+ function AddManual(test)
+ {
+ // add asynchronous test for manual tests
+ return async_test(test);
+ }
+
+ function AddManualResult(oManualTest, passState)
+ {
+ // add assertion to manual test for the pass state
+ oManualTest.step(function() {assert_true(passState)});
+
+ // end manual test
+ oManualTest.done();
+ }
+
+ function start_test()
+ {
+ test_transition_init();
+ }
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/performance-timeline/idlharness.html b/tests/wpt/web-platform-tests/performance-timeline/idlharness.html
new file mode 100644
index 00000000000..db93932025f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/performance-timeline/idlharness.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Performance Timeline IDL tests</title>
+<link rel="author" title="W3C" href="http://www.w3.org/" />
+<link rel="help" href="http://www.w3.org/TR/performance-timeline/#performanceentry"/>
+<link rel="help" href="http://www.w3.org/TR/performance-timeline/#performance"/>
+<link rel="help" href="http://www.w3.org/TR/performance-timeline/#performanceentrylist"/>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/WebIDLParser.js"></script>
+<script src="/resources/idlharness.js"></script>
+</head>
+<body>
+<h1>Performance Timeline IDL tests</h1>
+<div id="log"></div>
+
+<pre id='untested_idl' style='display:none'>
+interface Performance {
+};
+</pre>
+
+<pre id='idl'>
+interface PerformanceEntry {
+ readonly attribute DOMString name;
+ readonly attribute DOMString entryType;
+ readonly attribute DOMHighResTimeStamp startTime;
+ readonly attribute DOMHighResTimeStamp duration;
+};
+
+partial interface Performance {
+ PerformanceEntryList getEntries();
+ PerformanceEntryList getEntriesByType(DOMString entryType);
+ PerformanceEntryList getEntriesByName(DOMString name, optional DOMString entryType);
+};
+
+typedef sequence &lt;PerformanceEntry> PerformanceEntryList;
+</pre>
+
+<script>
+var idl_array;
+setup(function() {
+ idl_array = new IdlArray();
+ idl_array.add_untested_idls(document.getElementById("untested_idl").textContent);
+ idl_array.add_idls(document.getElementById("idl").textContent);
+ idl_array.add_objects({
+ Performance: ["window.performance"]
+ });
+});
+idl_array.test();
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/pointerevents/README.md b/tests/wpt/web-platform-tests/pointerevents/README.md
new file mode 100644
index 00000000000..07004cf4eac
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/README.md
@@ -0,0 +1,9 @@
+Directory for Pointer Events Tests
+
+Latest Editor's Draft: https://dvcs.w3.org/hg/pointerevents/raw-file/tip/pointerEvents.html
+
+Latest W3C Technical Report: http://www.w3.org/TR/pointerevents/
+
+Discussion forum for tests: http://lists.w3.org/Archives/Public/public-test-infra/
+
+Test Assertion table: https://www.w3.org/wiki/PointerEvents/TestAssertions
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_button_attribute_mouse-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_button_attribute_mouse-manual.html
new file mode 100644
index 00000000000..a31e53d3285
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_button_attribute_mouse-manual.html
@@ -0,0 +1,57 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Button and buttons attribute test for mouse</title>
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="pointerevent_support.js"></script>
+ </head>
+ <body onload="run()">
+ <h1>Button attribute test for mouse</h1>
+ <h2>This test is for mouse only</h2>
+ <h4>
+ Test Description: This test checks if button attribute for mouse handled properly.
+ <p>Put your mouse over the black rectangle</p>
+ </h4>
+ <p>
+ <div id="target0" style="background:black"></div>
+ <script>
+ var eventTested = false;
+ var detected_pointertypes = {};
+
+ setup({ explicit_done: true });
+ add_completion_callback(showPointerTypes);
+
+ function run() {
+ var target0 = document.getElementById("target0");
+
+ // If pointerType is "mouse" and no mouse button is depressed, then the button attribute of the pointermove event must be -1 and the buttons attribute must be 0.
+ // TA: 5.8
+ on_event(target0, "pointerover", function (event) {
+ detected_pointertypes[event.pointerType] = true;
+ if(event.pointerType != "mouse") {
+ alert("Use mouse for this test please!");
+ return;
+ }
+ if (eventTested == false) {
+ test(function() {
+ assert_true(event.button == -1, "If mouse buttons are released button attribute is -1")
+ }, "If mouse buttons are released button attribute is -1");
+ test(function() {
+ assert_true(event.buttons == 0, "If mouse buttons are released buttons attribute is 0")
+ }, "If mouse buttons are released buttons attribute is 0");
+ eventTested = true;
+ done();
+ }
+ });
+ }
+ </script>
+ <h1>Pointer Events button attribute test for mouse test</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_capture_mouse-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_capture_mouse-manual.html
new file mode 100644
index 00000000000..c4c7bc8c7c4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_capture_mouse-manual.html
@@ -0,0 +1,132 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Set/Release capture</title>
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!-- Additional helper script for common checks across event types -->
+ <script type="text/javascript" src="pointerevent_support.js"></script>
+ </head>
+ <body>
+ <h1>Pointer Events capture test</h1>
+ <h4>
+ Test Description: This test checks if setCapture/releaseCapture functions works properly. Complete the following actions:
+ <ol>
+ <li> Move your mouse over the black rectangle. pointermove event should be logged in the black rectangle</li>
+ <li> Move your mouse over the purple rectangle. pointerover event should be logged in the purple rectangle</li>
+ <li> Press and hold left mouse button over "Set Capture" button. "gotpointercapture" should be logged in the black rectangle</li>
+ <li> Move your mouse anywhere. pointermove should be logged in the black rectangle</li>
+ <li> Move your mouse over the purple rectangle. Nothig should happen</li>
+ <li> Move your mouse over the black rectangle. pointermove should be logged in the black rectangle</li>
+ <li> Release left mouse button. "lostpointercapture" should be logged in the black rectangle</li>
+ </ol>
+ </h4>
+ Test passes if the proper behaviour of the events is observed.
+ <div id="target0"></div>
+ <br>
+ <div id="target1"></div>
+ <br>
+ <input type="button" id="btnCapture" value="Set Capture">
+ <script type='text/javascript'>
+ var isPointerCapture = false;
+ var pointermoveNoCaptureGot0 = false;
+ var pointermoveCaptureGot0 = false;
+ var pointermoveNoCaptureGot1 = false;
+ var ownEventForTheCapturedTargetGot = false;
+ var count=0;
+
+ var detected_pointertypes = {};
+ add_completion_callback(showPointerTypes);
+
+ var target0 = document.getElementById('target0');
+ var target1 = document.getElementById('target1');
+ var captureButton = document.getElementById('btnCapture');
+
+ var test_gotpointercapture = async_test("gotpointercapture event received");
+ var test_lostpointercapture = async_test("lostpointercapture event received");
+
+ window.onload = function() {
+ on_event(captureButton, 'pointerdown', function(e) {
+ if(isPointerCapture == false) {
+ isPointerCapture = true;
+ sPointerCapture(e);
+ }
+ });
+
+ on_event(target0, 'gotpointercapture', function(e) {
+ test_gotpointercapture.done();
+ log("gotpointercapture", target0);
+ });
+
+ on_event(target0, 'lostpointercapture', function(e) {
+ test_lostpointercapture.done();
+ isPointerCapture = false;
+ log("lostpointercapture", target0);
+ });
+
+ run();
+ }
+
+ function run() {
+ var test_pointermove0 = async_test("pointerover event for black rectangle received")
+ var test_pointermove1 = async_test("pointerover event for purple rectangle received")
+
+ on_event(target0, "pointermove", function (event) {
+ detected_pointertypes[ event.pointerType ] = true;
+ if(!pointermoveNoCaptureGot0) {
+ test_pointermove0.done();
+ log("pointermove", document.getElementById('target0'));
+ pointermoveNoCaptureGot0 = true;
+ }
+ if(isPointerCapture) {
+ if(!pointermoveCaptureGot0) {
+ test(function() {
+ assert_true(event.relatedTarget==null, "relatedTarget is null when the capture is set")
+ }, "relatedTarget is null when the capture is set. relatedTarget is " + event.relatedTarget);
+ test(function() {
+ assert_true((event.clientX < target0.getBoundingClientRect().left)||
+ (event.clientX > target0.getBoundingClientRect().right)||
+ (event.clientY < target0.getBoundingClientRect().top)||
+ (event.clientY > target0.getBoundingClientRect().bottom),
+ "pointermove received for captured element while out of it")
+ }, "pointermove received for captured element while out of it");
+ log("pointermove", document.getElementById('target0'));
+ pointermoveCaptureGot0 = true;
+ }
+ if((event.clientX > target0.getBoundingClientRect().left)&&
+ (event.clientX < target0.getBoundingClientRect().right)&&
+ (event.clientY > target0.getBoundingClientRect().top)&&
+ (event.clientY < target0.getBoundingClientRect().bottom)&&
+ !ownEventForTheCapturedTargetGot) {
+ test(function() {
+ assert_true(true, "pointermove received for captured element while inside of it");
+ }, "pointermove received for captured element while inside of it");
+ log("pointermove", document.getElementById('target0'));
+ ownEventForTheCapturedTargetGot = true;
+ }
+ }
+ });
+
+ on_event(target1, "pointermove", function (event) {
+ if(isPointerCapture == true) {
+ test(function() {
+ assert_unreached("pointermove shouldn't trigger for this target when capture is enabled");
+ }, "pointermove shouldn't trigger for the purple rectangle while the black rectangle has capture");
+ }
+ if(!pointermoveNoCaptureGot1) {
+ test_pointermove1.done();
+ log("pointermove", document.getElementById('target1'));
+ pointermoveNoCaptureGot1 = true;
+ }
+ });
+ }
+ </script>
+ <h1>Pointer Events Capture Test</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_capture_suppressing_mouse-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_capture_suppressing_mouse-manual.html
new file mode 100644
index 00000000000..60e22d4b7d5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_capture_suppressing_mouse-manual.html
@@ -0,0 +1,175 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Set/Release capture</title>
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!-- Additional helper script for common checks across event types -->
+ <script type="text/javascript" src="pointerevent_support.js"></script>
+ </head>
+ <body>
+ <h1>Pointer Events capture test</h1>
+ <h4>
+ Test Description: This test checks if setCapture/releaseCapture functions works properly. Complete the following actions:
+ <ol>
+ <li> Put your mouse over the black rectangle. pointerover and pointerenter should be logged inside of it.</li>
+ <li> Move your mouse out of the black rectangle. pointerout and pointerleave should be logged inside of it</li>
+ <li> Put your mouse over the purple rectangle. pointerover and pointerenter should be logged inside of it.</li>
+ <li> Move your mouse out of the purple rectangle. pointerout and pointerleave should be logged inside of it</li>
+ <li> Press and hold left mouse button over "Set Capture" button. "gotpointercapture" should be logged in the black rectangle</li>
+ <li> Put your mouse over the purple rectangle and then move it out. Nothing should happen</li>
+ <li> Put your mouse over the black rectangle. pointerover and pointerenter should be logged inside of it.</li>
+ <li> Move your mouse out of the black rectangle. pointerout and pointerleave should be logged inside of it</li>
+ <li> Release left mouse button. "lostpointercapture" should be logged in the black rectangle</li>
+ </ol>
+ </h4>
+ Test passes if the proper behaviour of the events is observed.
+ <div id="target0"></div>
+ <br>
+ <div id="target1"></div>
+ <br>
+ <input type="button" id="btnCapture" value="Set Capture">
+ <script type='text/javascript'>
+ var isPointerCapture = false;
+ var isRelatedTargetValueTested = false;
+ var count = 0;
+
+ var detected_pointertypes = {};
+ add_completion_callback(showPointerTypes);
+
+ var target0 = document.getElementById('target0');
+ var target1 = document.getElementById('target1');
+ var captureButton = document.getElementById('btnCapture');
+
+ var test_gotpointercapture = async_test("gotpointercapture event received");
+ var test_lostpointercapture = async_test("lostpointercapture event received");
+
+ var test_pointerover_no_capture = async_test("pointerover event without capture received");
+ var test_pointerover_capture = async_test("pointerover event with capture received");
+
+ var test_pointerout_no_capture = async_test("pointerout event without capture received");
+ var test_pointerout_capture = async_test("pointerout event with capture received");
+
+ var test_pointerenter_no_capture = async_test("pointerenter event without capture received");
+ var test_pointerenter_capture = async_test("pointerenter event with capture received");
+
+ var test_pointerleave_no_capture = async_test("pointerleave event without capture received");
+ var test_pointerleave_capture = async_test("pointerleave event with capture received");
+
+ window.onload = function() {
+ on_event(captureButton, 'pointerdown', function(e) {
+ if(isPointerCapture == false) {
+ sPointerCapture(e);
+ isPointerCapture = true;
+ }
+ });
+
+ on_event(target0, 'gotpointercapture', function(e) {
+ test_gotpointercapture.done();
+ log("gotpointercapture", target0);
+ });
+
+ on_event(target0, 'lostpointercapture', function(e) {
+ isPointerCapture = false;
+ test_lostpointercapture.done();
+ log("lostpointercapture", target0);
+ });
+
+ run();
+ }
+
+ function run() {
+ on_event(target0, "pointerover", function (event) {
+ detected_pointertypes[ event.pointerType ] = true;
+ log("pointerover", target0);
+ if(isPointerCapture) {
+ test_pointerover_capture.done();
+ if (!isRelatedTargetValueTested) {
+ test(function() {
+ assert_true(event.relatedTarget==null, "relatedTarget is null when the capture is set")
+ }, "relatedTarget is null when the capture is set. relatedTarget is " + event.relatedTarget);
+ isRelatedTargetValueTested = true;
+ }
+ }
+ else {
+ test_pointerover_no_capture.done();
+ }
+ });
+
+ on_event(target0, "pointerout", function (event) {
+ log("pointerout", target0);
+ if(isPointerCapture) {
+ test_pointerout_capture.done();
+ }
+ else {
+ test_pointerout_no_capture.done();
+ }
+ });
+
+ on_event(target0, "pointerenter", function (event) {
+ log("pointerenter", target0);
+ if(isPointerCapture) {
+ test_pointerenter_capture.done();
+ }
+ else {
+ test_pointerenter_no_capture.done();
+ }
+ });
+
+ on_event(target0, "pointerleave", function (event) {
+ log("pointerleave", target0);
+ if(isPointerCapture) {
+ test_pointerleave_capture.done();
+ }
+ else {
+ test_pointerleave_no_capture.done();
+ }
+ });
+
+ // fail if capture is set but event is received for the non-captured target
+ on_event(target1, "pointerover", function (event) {
+ log("pointerover", target1);
+ if(isPointerCapture == true) {
+ test(function() {
+ assert_unreached("pointerover shouldn't trigger for this target when capture is enabled");
+ }, "pointerover shouldn't trigger for the purple rectangle while the black rectangle has capture");
+ }
+ });
+
+ on_event(target1, "pointerout", function (event) {
+ log("pointerout", target1);
+ if(isPointerCapture == true) {
+ test(function() {
+ assert_unreached("pointerout shouldn't trigger for this target when capture is enabled");
+ }, "pointerout shouldn't trigger for the purple rectangle while the black rectangle has capture");
+ }
+ });
+
+ on_event(target1, "pointerenter", function (event) {
+ log("pointerenter", target1);
+ if(isPointerCapture == true) {
+ test(function() {
+ assert_unreached("pointerenter shouldn't trigger for this target when capture is enabled");
+ }, "pointerenter shouldn't trigger for the purple rectangle while the black rectangle has capture");
+ }
+ });
+
+ on_event(target1, "pointerleave", function (event) {
+ log("pointerleave", target1);
+ if(isPointerCapture == true) {
+ test(function() {
+ assert_unreached("pointerleave shouldn't trigger for this target when capture is enabled");
+ }, "pointerleave shouldn't trigger for the purple rectangle while the black rectangle has capture");
+ }
+ });
+ }
+ </script>
+ <h1>Pointer Events Capture Test</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_change-touch-action-onpointerdown_touch-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_change-touch-action-onpointerdown_touch-manual.html
new file mode 100644
index 00000000000..04d56cb7a51
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_change-touch-action-onpointerdown_touch-manual.html
@@ -0,0 +1,135 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Change touch-action on pointerdown</title>
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ <style>
+ #target0 {
+ background: black;
+ width: 700px;
+ height: 430px;
+ color: white;
+ overflow-y: auto;
+ overflow-x: auto;
+ white-space: nowrap;
+ }
+ </style>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Events touch-action attribute support</h1>
+ <h4>Test Description: Press and hold your touch. Try to scroll text in any direction.
+ Then release your touch and try to scroll again. Expected: no panning.
+ </h4>
+ <p>Note: this test is for touch-devices only</p>
+ <div id="target0" style="touch-action: auto;">
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ </div>
+ <script type='text/javascript'>
+ var detected_pointertypes = {};
+
+ var styleIsChanged = false;
+ var scrollIsReceived = false;
+ var firstTouchCompleted = false;
+ var countToPass = 50;
+ var xScr0, yScr0, xScr1, yScr1;
+
+ setup({ explicit_done: true });
+ add_completion_callback(showPointerTypes);
+
+ function run() {
+ var target0 = document.getElementById("target0");
+
+ on_event(target0, 'scroll', function(event) {
+ if(!scrollIsReceived && firstTouchCompleted) {
+ test(function() {
+ failOnScroll();
+ }, "scroll was received while shouldn't");
+ scrollIsReceived = true;
+ }
+ done();
+ });
+
+ on_event(target0, 'pointerdown', function(event) {
+ detected_pointertypes[event.pointerType] = true;
+ if(!styleIsChanged) {
+ var before = document.getElementById('target0').style.touchAction;
+
+ document.getElementById('target0').style.touchAction = 'none';
+
+ var after = document.getElementById('target0').style.touchAction;
+
+ test(function() {
+ assert_true(before != after, "touch-action was changed");
+ }, "touch-action was changed");
+
+ styleIsChanged = true;
+ }
+ });
+
+ on_event(target0, 'pointerup', function(event) {
+ firstTouchCompleted = true;
+ });
+ }
+ </script>
+ <h1>touch-action: auto to none</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_constructor.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_constructor.html
new file mode 100644
index 00000000000..eaf1d792832
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_constructor.html
@@ -0,0 +1,100 @@
+<!doctype html>
+<html>
+ <head>
+ <title>PointerEvent: Constructor test</title>
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!-- Additional helper script for common checks across event types -->
+ <script type="text/javascript" src="pointerevent_support.js"></script>
+ </head>
+ <body>
+ <h1>PointerEvent: Dispatch custom event</h1>
+ <h4>Test Description: This test checks if PointerEvent constructor works properly using synthetic pointerover and pointerout events. For valid results, this test must be run without generating real (trusted) pointerover or pointerout events on the black rectangle below.</h4>
+ <div id="target0"></div>
+ <script>
+ var detected_pointertypes = {};
+ add_completion_callback(showPointerTypes);
+
+ async_test(function() {
+ var target0 = document.getElementById("target0");
+ // set values for non-default constructor
+ var testBubbles = true;
+ var testCancelable = true;
+ var testPointerId = 42;
+ var testPointerType = 'pen';
+ var testClientX = 300;
+ var testClientY = 500;
+ var testWidth = 3;
+ var testHeight = 5;
+ var testTiltX = -45;
+ var testTiltY = 30;
+ var testPressure = 0.4;
+ var testIsPrimary = true;
+
+ on_event(target0, "pointerover", this.step_func(function(event) {
+ detected_pointertypes[ event.pointerType ] = true;
+ generate_tests(assert_equals, [
+ ["custom bubbles", event.bubbles, testBubbles],
+ ["custom cancelable", event.cancelable, testCancelable],
+ ["custom pointerId", event.pointerId, testPointerId],
+ ["custom pointerType", event.pointerType, testPointerType],
+ ["custom width", event.width, testWidth],
+ ["custom height", event.height, testHeight],
+ ["custom clientX", event.clientX, testClientX],
+ ["custom clientY", event.clientY, testClientY],
+ ["custom tiltX", event.tiltX, testTiltX],
+ ["custom tiltY", event.tiltY, testTiltY],
+ ["custom isPrimary", event.isPrimary, testIsPrimary]
+ ]);
+ test(function() {
+ assert_approx_equals(event.pressure, testPressure, 0.00000001, "custom pressure: ");
+ }, "custom pressure: ");
+ }));
+
+ on_event(target0, "pointerout", this.step_func(function(event) {
+ generate_tests(assert_equals, [
+ ["default pointerId", event.pointerId, 0],
+ ["default pointerType", event.pointerType, ""],
+ ["default width", event.width, 0],
+ ["default height", event.height, 0],
+ ["default tiltX", event.tiltX, 0],
+ ["default tiltY", event.tiltY, 0],
+ ["default pressure", event.pressure, 0],
+ ["default isPrimary", event.isPrimary, false]
+ ]);
+ }));
+
+ on_event(window, "load", this.step_func_done(function() {
+ assert_not_equals(window.PointerEvent, undefined);
+
+ var pointerEventCustom = new PointerEvent("pointerover",
+ {bubbles: testBubbles,
+ cancelable: testCancelable,
+ pointerId: testPointerId,
+ pointerType: testPointerType,
+ width: testWidth,
+ height: testHeight,
+ clientX: testClientX,
+ clientY: testClientY,
+ tiltX: testTiltX,
+ tiltY: testTiltY,
+ pressure: testPressure,
+ isPrimary: testIsPrimary
+ });
+ // A PointerEvent created with a PointerEvent constructor must have all its attributes set to the corresponding values provided to the constructor.
+ // For attributes where values are not provided to the constructor, the corresponding default values must be used.
+ // TA: 12.1
+ target0.dispatchEvent(pointerEventCustom);
+ var pointerEventDefault = new PointerEvent("pointerout");
+ target0.dispatchEvent(pointerEventDefault);
+ }, "PointerEvent constructor"));
+ })
+ </script>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_gotpointercapture_before_first_pointerevent-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_gotpointercapture_before_first_pointerevent-manual.html
new file mode 100644
index 00000000000..754a58facfd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_gotpointercapture_before_first_pointerevent-manual.html
@@ -0,0 +1,97 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Pointer Event: gotpiontercapture is fired first and asynchronously.</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <meta name="assert" content="After setting capture, the gotpointercapture dispatched to the capturing element before any other event is fired." />
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <!-- /resources/testharness.js -->
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!-- Additional helper script for common checks across event types -->
+ <script type="text/javascript" src="pointerevent_support.js"></script>
+ <script type="text/javascript">
+ var detected_pointertypes = {};
+ var test_pointerEvent = async_test("gotpointercapture event"); // set up test harness
+ // showPointerTypes is defined in pointerevent_support.js
+ // Requirements: the callback function will reference the test_pointerEvent object and
+ // will fail unless the async_test is created with the var name "test_pointerEvent".
+ add_completion_callback(showPointerTypes);
+
+ var target0;
+ var listener;
+ var pointerdown_event;
+ var detected_pointerEvents = new Array();
+ var eventRcvd = false;
+ var isWaiting = false;
+
+
+ function run() {
+ target0 = document.getElementById("target0");
+ target0.style["touchAction"] = "none";
+ listener = document.getElementById("listener");
+
+ // listen to all events
+ for (var i = 0; i < All_Pointer_Events.length; i++) {
+ on_event(listener, All_Pointer_Events[i], function (event) {
+ if (event.type == "gotpointercapture") {
+ check_PointerEvent(event);
+
+ // TA: 10.2
+ assert_true(isWaiting, "gotpointercapture must be fired asynchronously");
+ isWaiting = false;
+
+ // if any events have been received with same pointerId before gotpointercapture, then fail
+ var eventsRcvd_str = "";
+ if (eventRcvd) {
+ eventsRcvd_str = "Events received before gotpointercapture: ";
+ for (var i = 0; i < detected_pointerEvents.length; i++) {
+ eventsRcvd_str += detected_pointerEvents[i] + ", ";
+ }
+ }
+ test_pointerEvent.step(function () {
+ assert_false(eventRcvd, "no other events should be received before gotpointercapture." + eventsRcvd_str);
+ assert_equals(event.pointerId, pointerdown_event.pointerId, "pointerID is same for pointerdown and gotpointercapture");
+ });
+ }
+ else {
+ if (pointerdown_event.pointerId === event.pointerId) {
+ assert_false(isWaiting, event.type + " must be fired after gotpointercapture");
+ detected_pointerEvents.push(event.type);
+ eventRcvd = true;
+ test_pointerEvent.done(); // complete test
+ }
+ }
+ });
+ }
+
+ // set pointer capture
+ on_event(target0, "pointerdown", function (event) {
+ detected_pointertypes[event.pointerType] = true;
+ pointerdown_event = event;
+ listener.setPointerCapture(event.pointerId);
+ isWaiting = true;
+ });
+ }
+ </script>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Event: Dispatch gotpointercapture event</h1>
+ <h4>Test Description:
+ After pointer capture is set for a pointer, and prior to dispatching the first event for the pointer, the gotpointercapture
+ event must be dispatched to the element that is receiving the pointer capture. The gotpointercapture event must be dispatched asynchronously.
+ </h4>
+ <br />
+ <div id="target0">
+ Use the mouse, touch or pen to tap/click this box.
+ </div>
+ <div id="listener">Do not hover over or touch this element. </div>
+ <div id="complete-notice">
+ <p>Test complete: Scroll to Summary to view Pass/Fail Results.</p>
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ <p>Refresh the page to run the tests again with a different pointer type.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_lostpointercapture_for_disconnected_node-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_lostpointercapture_for_disconnected_node-manual.html
new file mode 100644
index 00000000000..4d152b73a6a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_lostpointercapture_for_disconnected_node-manual.html
@@ -0,0 +1,78 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Lostpointercapture fires on document when target is removed</title>
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ </head>
+ <body>
+ <h1>Pointer Events - lostpointercapture when capturing element is removed</h1>
+ <h4>
+ Test Description:
+ This test checks if lostpointercapture is fired at the document when the capturing node is removed from the document.
+ Complete the following actions:
+ <ol>
+ <li>Press and hold left mouse button over "Set Capture" button. "gotpointercapture" should be logged inside of the black rectangle.
+ <li>"lostpointercapture" should be logged inside of the black rectangle after a short delay.
+ </ol>
+ </h4>
+ <div id="target0"></div>
+ <div id="target1" style="background:black; color:white"></div>
+ <br>
+ <input type="button" id="btnCapture" value="Set Capture">
+ <script type='text/javascript'>
+ var isDisconnected = false;
+ var count = 0;
+
+ var detected_pointertypes = {};
+ add_completion_callback(showPointerTypes);
+
+ var target0 = document.getElementById('target0');
+ var target1 = document.getElementById('target1');
+ var captureButton = document.getElementById('btnCapture');
+
+ var test_lostpointercapture = async_test("lostpointercapture event received");
+
+ window.onload = function() {
+ on_event(captureButton, 'pointerdown', function(event) {
+ detected_pointertypes[event.pointerType] = true;
+ sPointerCapture(event);
+ });
+
+ on_event(target0, 'gotpointercapture', function(e) {
+ log("gotpointercapture", target1);
+ setTimeout(function() {
+ isDisconnected = true;
+ target0.parentNode.removeChild(target0);
+ }, 250);
+ });
+
+ on_event(target0, 'lostpointercapture', function(e) {
+ log("lostpointercapture on element", target1);
+ test(function() {
+ // TA: 11.3
+ assert_unreached("lostpointercapture must be fired on the document, not the capturing element");
+ }, "lostpointercapture must not be dispatched on the disconnected node");
+ });
+
+ on_event(document, 'lostpointercapture', function(e) {
+ log("lostpointercapture on document", target1);
+ test(function() {
+ // TA: 11.3
+ assert_true(isDisconnected, "lostpointercapture must be fired on the document");
+
+ }, "lostpointercapture is dispatched on the document");
+ test_lostpointercapture.done();
+ });
+ }
+ </script>
+ <h1>Pointer Events Capture Test</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_lostpointercapture_is_first-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_lostpointercapture_is_first-manual.html
new file mode 100644
index 00000000000..566676d2aef
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_lostpointercapture_is_first-manual.html
@@ -0,0 +1,111 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Lostpointercapture triggers first and asynchronously</title>
+ <meta name="assert" content="TA11.1: After pointer capture is released for a pointer, and prior to any subsequent events for the pointer, the lostpointercapture event must be dispatched to the element from which pointer capture was removed; TA11.2: lostpointercapture must be dispatched asynchronously.">
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Events capture test - lostpointercapture order</h1>
+ <h4>
+ Test Description:
+ This test checks if lostpointercapture is handled asynchronously and prior to all subsequent events.
+ Complete the following actions:
+ <ol>
+ <li>Press and hold left mouse button over "Set Capture" button. "gotpointercapture" should be logged inside of the black rectangle
+ <li>"lostpointercapture" should be logged inside of the black rectangle after a short delay
+ </ol>
+ </h4>
+ Test passes if lostpointercapture is dispatched after releasing the mouse button and before any additional pointer events.
+ <div id="target0" style="background:black; color:white"></div>
+ <br>
+ <input type="button" id="btnCapture" value="Set Capture">
+ <script type='text/javascript'>
+ var detected_pointertypes = {};
+ var detected_pointerEvents = new Array();
+ var pointerdown_event = null;
+
+ var test_pointerEvent = async_test("lostpointercapture is dispatched prior to subsequent events"); // set up test harness
+
+ var isPointerCapture = false;
+ var count=0;
+
+ var testStarted = false;
+ var eventRcvd = false;
+ var isAsync = false;
+
+ add_completion_callback(showPointerTypes);
+
+ var target0 = document.getElementById('target0');
+ var captureButton = document.getElementById('btnCapture');
+
+ function run() {
+ on_event(captureButton, 'pointerdown', function(event) {
+ detected_pointertypes[event.pointerType] = true;
+ pointerdown_event = event;
+ if(isPointerCapture == false) {
+ isPointerCapture = true;
+ captureButton.value = 'Release Capture';
+ sPointerCapture(event);
+ }
+ });
+
+ // After pointer capture is released for a pointer, and prior to any subsequent events for the pointer,
+ // the lostpointercapture event must be dispatched to the element from which pointer capture was removed.
+ // TA: 11.1
+ // listen to all events
+ for (var i = 0; i < All_Pointer_Events.length; i++) {
+ on_event(target0, All_Pointer_Events[i], function (event) {
+ // if the event was gotpointercapture, just log it and return
+ if (event.type == "gotpointercapture") {
+ testStarted = true;
+ rPointerCapture(event);
+ isAsync = true;
+ log("gotpointercapture", target0);
+ return;
+ }
+ else if (event.type == "lostpointercapture") {
+ log("lostpointercapture", target0);
+ captureButton.value = 'Set Capture';
+ isPointerCapture = false;
+
+ // TA: 11.2
+ test_pointerEvent.step(function () {
+ assert_true(isAsync, "lostpointercapture must be fired asynchronously");
+ });
+
+ // if any events have been received with same pointerId before lostpointercapture, then fail
+ var eventsRcvd_str = "";
+ if (eventRcvd) {
+ eventsRcvd_str = "Events received before lostpointercapture: ";
+ for (var i = 0; i < detected_pointerEvents.length; i++) {
+ eventsRcvd_str += detected_pointerEvents[i] + ", ";
+ }
+ }
+ test_pointerEvent.step(function () {
+ assert_false(eventRcvd, "no other events should be received before lostpointercapture." + eventsRcvd_str);
+ assert_equals(event.pointerId, pointerdown_event.pointerId, "pointerID is same for pointerdown and lostpointercapture");
+ });
+ test_pointerEvent.done(); // complete test
+ }
+ else {
+ if (testStarted && pointerdown_event != null && pointerdown_event.pointerId === event.pointerId) {
+ detected_pointerEvents.push(event.type);
+ eventRcvd = true;
+ }
+ }
+ });
+ }
+ }
+ </script>
+ <h1>Pointer Events Capture Test</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointercancel_touch-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointercancel_touch-manual.html
new file mode 100644
index 00000000000..70a65eeb5ca
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointercancel_touch-manual.html
@@ -0,0 +1,77 @@
+<!doctype html>
+<html>
+ <head>
+ <title>PointerCancel - touch</title>
+ <meta name="viewport" content="width=device-width">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <!-- Additional helper script for common checks across event types -->
+ <script type="text/javascript" src="pointerevent_support.js"></script>
+ </head>
+ <body class="scrollable" onload="run()">
+ <h1>pointercancel test</h1>
+ <h3>Warning: this test works properly only for devices that have touchscreen</h3>
+ <h4>
+ Test Description: This test checks if pointercancel event triggers.
+ <p>Start touch over the black rectangle and then move your finger to scroll the page.</p>
+ </h4>
+ <p>
+ <div id="target0" style="background: black"></div>
+ <script>
+ var detected_pointertypes = {};
+ var test_pointerEvent = async_test("pointercancel event received");
+ // showPointerTypes is defined in pointerevent_support.js
+ // Requirements: the callback function will reference the test_pointerEvent object and
+ // will fail unless the async_test is created with the var name "test_pointerEvent".
+ add_completion_callback(showPointerTypes);
+
+ var pointerdown_event = null;
+ var pointercancel_event = null;
+
+ function run() {
+ var target0 = document.getElementById("target0");
+
+ on_event(target0, "pointerdown", function (event) {
+ pointerdown_event = event;
+ detected_pointertypes[event.pointerType] = true;
+ });
+
+ on_event(target0, "pointercancel", function (event) {
+ pointercancel_event = event;
+ test_pointerEvent.step(function () {
+ assert_not_equals(pointerdown_event, null, "pointerdown was received: ");
+ assert_equals(event.pointerId, pointerdown_event.pointerId, "pointerId should be the same for pointerdown and pointercancel");
+ assert_equals(event.pointerType, pointerdown_event.pointerType, "pointerType should be the same for pointerdown and pointercancel");
+ assert_equals(event.isPrimary, pointerdown_event.isPrimary, "isPrimary should be the same for pointerdown and pointercancel");
+ check_PointerEvent(event);
+ });
+ });
+
+ on_event(target0, "pointerout", function (event) {
+ test_pointerEvent.step(function () {
+ assert_not_equals(pointercancel_event, null, "pointercancel was received before pointerout: ");
+ assert_equals(event.pointerId, pointerdown_event.pointerId, "pointerId should be the same for pointerout and pointercancel");
+ assert_equals(event.pointerType, pointerdown_event.pointerType, "pointerType should be the same for pointerout and pointercancel");
+ assert_equals(event.isPrimary, pointerdown_event.isPrimary, "isPrimary should be the same for pointerout and pointercancel");
+ });
+ });
+
+ on_event(target0, "pointerleave", function (event) {
+ test_pointerEvent.step(function () {
+ assert_not_equals(pointercancel_event, null, "pointercancel was received before pointerleave: ");
+ assert_equals(event.pointerId, pointerdown_event.pointerId, "pointerId should be the same for pointerleave and pointercancel");
+ assert_equals(event.pointerType, pointerdown_event.pointerType, "pointerType should be the same for pointerleave and pointercancel");
+ assert_equals(event.isPrimary, pointerdown_event.isPrimary, "isPrimary should be the same for pointerleave and pointercancel");
+ });
+ test_pointerEvent.done();
+ });
+ }
+ </script>
+ <h1>Pointer Events pointercancel Tests</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerdown-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerdown-manual.html
new file mode 100644
index 00000000000..0167e08ba5a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerdown-manual.html
@@ -0,0 +1,59 @@
+<!doctype html>
+<html>
+ <!--
+Test cases for Pointer Events v1 spec
+This document references Test Assertions (abbrev TA below) written by Cathy Chan
+http://www.w3.org/wiki/PointerEvents/TestAssertions
+-->
+ <head>
+ <title>Pointer Events pointerdown tests</title>
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!-- Additional helper script for common checks across event types -->
+ <script type="text/javascript" src="pointerevent_support.js"></script>
+ <script>
+ var detected_pointertypes = {};
+ var test_pointerEvent = async_test("pointerdown event received");
+ // showPointerTypes is defined in pointerevent_support.js
+ // Requirements: the callback function will reference the test_pointerEvent object and
+ // will fail unless the async_test is created with the var name "test_pointerEvent".
+ add_completion_callback(showPointerTypes);
+
+
+ function run() {
+ var target0 = document.getElementById("target0");
+ var pointerover_event;
+
+ on_event(target0, "pointerover", function (event) {
+ detected_pointertypes[event.pointerType] = true;
+ pointerover_event = event;
+ check_PointerEvent(event);
+ });
+
+ on_event(target0, "pointerdown", function (event) {
+ check_PointerEvent(event);
+
+ test_pointerEvent.step(function () {
+ assert_equals(event.pointerType, pointerover_event.pointerType, "pointerType is same for pointerover and pointerdown");
+ assert_equals(event.isPrimary, pointerover_event.isPrimary, "isPrimary is same for pointerover and pointerdown");
+ });
+
+ test_pointerEvent.done();
+ });
+ }
+ </script>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Events pointerdown tests</h1>
+ <div id="target0">
+ Start with your pointing device outside of this box, then click here.
+ </div>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ <p>Refresh the page to run the tests again with a different pointer type.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerenter-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerenter-manual.html
new file mode 100644
index 00000000000..613eb8e4064
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerenter-manual.html
@@ -0,0 +1,52 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Pointer Event: Dispatch pointerenter. </title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/"/>
+ <meta name="assert" content="When a pointing device is moved into the hit test boundaries of an element or one of its descendants, the pointerenter event must be dispatched."/>
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <!-- /resources/testharness.js -->
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!-- Additional helper script for common checks across event types -->
+ <script type="text/javascript" src="pointerevent_support.js"></script>
+ <script type="text/javascript">
+ var detected_pointertypes = {};
+ var test_pointerEvent = async_test("pointerenter event"); // set up test harness
+ // showPointerTypes is defined in pointerevent_support.js
+ // Requirements: the callback function will reference the test_pointerEvent object and
+ // will fail unless the async_test is created with the var name "test_pointerEvent".
+ add_completion_callback(showPointerTypes);
+
+ function run() {
+ var target0 = document.getElementById("target0");
+
+ on_event(target0, "pointerenter", function (event) {
+ detected_pointertypes[event.pointerType] = true;
+ check_PointerEvent(event);
+ test_pointerEvent.step(function () {
+ assert_equals(event.type, "pointerenter", "pointer event received: " + event.type);
+ });
+ test_pointerEvent.done(); // complete test
+ });
+ }
+ </script>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Event: Dispatch pointerenter</h1>
+ <h4>
+ Test Description:
+ When a pointing device is moved into the hit test boundaries of an element or one of its descendants, the pointerenter event must be dispatched.
+ </h4>
+ <div id="target0">
+ Use the mouse or pen to move over this box.
+ </div>
+ <div id="complete-notice">
+ <p>Test complete: Scroll to Summary to view Pass/Fail Results.</p>
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ <p>Refresh the page to run the tests again with a different pointer type.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerenter_does_not_bubble-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerenter_does_not_bubble-manual.html
new file mode 100644
index 00000000000..3f0583364a2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerenter_does_not_bubble-manual.html
@@ -0,0 +1,88 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Pointer Event: The pointerenter event does not bubble </title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/"/>
+ <meta name="assert" content="The pointerenter event must not bubble up to parent elements."/>
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <!-- /resources/testharness.js -->
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!-- Additional helper script for common checks across event types -->
+ <script type="text/javascript" src="pointerevent_support.js"></script>
+ <script type="text/javascript">
+ var detected_pointertypes = {};
+ var test_pointerEvent = async_test("pointerEnter event does not bubble"); // set up test harness
+ // showPointerTypes is defined in pointerevent_support.js
+ // Requirements: the callback function will reference the test_pointerEvent object and
+ // will fail unless the async_test is created with the var name "test_pointerEvent".
+ add_completion_callback(showPointerTypes);
+
+ var pointerenter_event = null;
+
+ function run() {
+ var target0 = document.getElementById("target0");
+ var parent0 = document.getElementById("parent0");
+
+ on_event(target0, "pointerenter", function (event) {
+ pointerenter_event = event;
+
+ check_PointerEvent(event);
+ test_pointerEvent.step(function () {
+ assert_equals(event.type, "pointerenter", "pointer event received: " + event.type);
+ assert_false(event.bubbles, "pointerenter event.bubbles should be false: " + event.bubbles);
+ });
+ });
+ on_event(target0, "pointerout", function (event) {
+ test_pointerEvent.step(function () {
+ assert_not_equals(pointerenter_event, null, "pointerout event was never received: ");
+ });
+ test_pointerEvent.done(); // complete test
+ });
+
+ // parent
+ on_event(parent0, "pointerenter", function (event) {
+ detected_pointertypes[event.pointerType] = true;
+ test_pointerEvent.step(function () {
+ assert_equals(event.target.id, "parent0", "Recieved " + event.type + " in parent for " + event.target.id);
+ });
+ });
+ }
+
+ </script>
+ <style>
+ #target0 {
+ background: purple;
+ border: 1px solid orange;
+ width:50px;
+ height:50px;
+ }
+ #parent0 {
+ background: black;
+ border: 1px solid orange;
+ width:100px;
+ height:100px;
+ }
+ </style>
+ </head>
+ <body onload="run()">
+ <h1> Pointer Event: pointerenter does not bubble</h1>
+ <h4>
+ Test Description:
+ The pointerenter event must not bubble up to parent elements.
+ </h4>
+ <div id="instructions">
+ Use the mouse or pen to hover over then out of the purple box nested in the black box. Or with touch, tap on the purple box.
+ </div>
+ <div id="parent0">
+ <div id="target0"></div>
+ </div>
+ <div id="complete-notice">
+ <p>Test complete: Scroll to Summary to view Pass/Fail Results.</p>
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ <p>Refresh the page to run the tests again with a different pointer type.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerenter_nohover-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerenter_nohover-manual.html
new file mode 100644
index 00000000000..32675bbb441
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerenter_nohover-manual.html
@@ -0,0 +1,74 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Pointer Event: Dispatch pointerenter. (nohover)</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/"/>
+ <meta name="assert" content="When a pointing device that does not support hover is moved into the hit test boundaries of an element
+or one of its descendants as a result of a pointerdown event, the pointerenter event must be dispatched. "/>
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <!-- /resources/testharness.js -->
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!-- Additional helper script for common checks across event types -->
+ <script type="text/javascript" src="pointerevent_support.js"></script>
+ <script type="text/javascript">
+ var detected_pointertypes = {};
+ var test_pointerEvent = async_test("pointerenter event"); // set up test harness
+ // showPointerTypes is defined in pointerevent_support.js
+ // Requirements: the callback function will reference the test_pointerEvent object and
+ // will fail unless the async_test is created with the var name "test_pointerEvent".
+ add_completion_callback(showPointerTypes);
+
+ var test_pointerEnter;
+ var f_pointerenter_rcvd = false;
+ var pointerenter_event;
+
+ function run() {
+ var target0 = document.getElementById("target0");
+
+ on_event(target0, "pointerdown", function (event) {
+ if(event.pointerType == 'touch') {
+ check_PointerEvent(event);
+ test_pointerEvent.step(function () {
+ assert_equals(event.type, "pointerdown", "pointer event received: " + event.type);
+ assert_true(f_pointerenter_rcvd, "pointerenter event should have been received before pointerdown");
+ assert_equals(event.pointerType, pointerenter_event.pointerType, "pointerType is same for pointerenter and pointerdown");
+ assert_equals(event.isPrimary, pointerenter_event.isPrimary, "isPrimary is same for pointerenter and pointerdown");
+ });
+ test_pointerEvent.done(); // complete test
+ }
+ });
+
+ on_event(target0, "pointerenter", function (event) {
+ detected_pointertypes[event.pointerType] = true;
+ if(event.pointerType == 'touch') {
+ pointerenter_event = event;
+ check_PointerEvent(event);
+ test_pointerEvent.step(function () {
+ assert_equals(event.type, "pointerenter", "pointer event received: " + event.type);
+ });
+ f_pointerenter_rcvd = true;
+ }
+ });
+ }
+ </script>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Event: Dispatch pointerenter (nohover)</h1>
+ <h4>
+ Test Description:
+ When a pointing device that does not support hover is moved into the hit test boundaries of an element or one of its
+ descendants as a result of a pointerdown event, the pointerenter event must be dispatched.
+ </h4>
+ <br />
+ <div id="target0">
+ Tap here.
+ </div>
+ <div id="complete-notice">
+ <p>Test complete: Scroll to Summary to view Pass/Fail Results.</p>
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerleave_after_pointercancel_touch-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerleave_after_pointercancel_touch-manual.html
new file mode 100644
index 00000000000..56be26549f8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerleave_after_pointercancel_touch-manual.html
@@ -0,0 +1,66 @@
+<!doctype html>
+<html>
+ <head>
+ <title>pointerleave after pointercancel</title>
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!-- Additional helper script for common checks across event types -->
+ <script type="text/javascript" src="pointerevent_support.js"></script>
+ </head>
+ <body class="scrollable" onload="run()">
+ <h2>pointerleave after pointercancel</h2>
+ <h4>Test Description: This test checks if pointerleave event triggers after pointercancel. Start touch on the black rectangle and move your touch to scroll in any direction. </h4>
+ <p>Note: this test is for touch devices only</p>
+ <div id="target0"></div>
+ <script>
+ var test_pointerleave = async_test("pointerleave event received");
+ // showPointerTypes is defined in pointerevent_support.js
+ // Requirements: the callback function will reference the test_pointerEvent object and
+ // will fail unless the async_test is created with the var name "test_pointerEvent".
+ add_completion_callback(showPointerTypes);
+
+ var eventTested = false;
+ var pointercancel_event = null;
+ var detected_pointertypes = {};
+
+ function run() {
+ var target0 = document.getElementById("target0");
+
+ on_event(target0, "pointercancel", function (event) {
+ detected_pointertypes[event.pointerType] = true;
+ pointercancel_event = event;
+ });
+
+ // After firing the pointercancel event the pointerleave event must be dispatched.
+ // TA: 4.3.1
+ on_event(target0, "pointerleave", function (event) {
+ if(event.pointerType == 'touch') {
+ if(pointercancel_event != null) {
+ if(eventTested == false) {
+ test_pointerleave.step(function() {
+ assert_equals(event.pointerType, pointercancel_event.pointerType, "pointerType is same for pointercancel and pointerleave");
+ assert_equals(event.isPrimary, pointercancel_event.isPrimary, "isPrimary is same for pointercancel and pointerleave");
+ });
+ eventTested = true;
+ test_pointerleave.done();
+ }
+ }
+ else {
+ test_pointerleave.step(function() {
+ assert_unreached("pointerleave received before pointercancel");
+ }, "pointerleave received before pointercancel");
+ }
+ }
+ });
+ }
+
+ </script>
+ <h1>Pointer Events pointerleave tests</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerleave_after_pointerup_nohover-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerleave_after_pointerup_nohover-manual.html
new file mode 100644
index 00000000000..30412378428
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerleave_after_pointerup_nohover-manual.html
@@ -0,0 +1,67 @@
+<!doctype html>
+<html>
+ <head>
+ <title>pointerleave after pointerup</title>
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!-- Additional helper script for common checks across event types -->
+ <script type="text/javascript" src="pointerevent_support.js"></script>
+ </head>
+ <body onload="run()">
+ <h2>pointerleave after pointerup</h2>
+ <h4>Test Description: This test checks if pointerleave event triggers for devices that don't support hover. Tap the black rectangle. </h4>
+ <p>Note: this test is only for devices that do not support hover.</p>
+ <div id="target0"></div>
+ <script>
+ var test_pointerleave = async_test("pointerleave event received");
+ // showPointerTypes is defined in pointerevent_support.js
+ // Requirements: the callback function will reference the test_pointerEvent object and
+ // will fail unless the async_test is created with the var name "test_pointerEvent".
+ add_completion_callback(showPointerTypes);
+
+ var eventTested = false;
+ var isPointerupReceived = false;
+ var pointerup_event = null;
+ var detected_pointertypes = {};
+
+ function run() {
+ var target0 = document.getElementById("target0");
+
+ on_event(target0, "pointerup", function (event) {
+ detected_pointertypes[event.pointerType] = true;
+ pointerup_event = event;
+ });
+
+ // For input devices that do not support hover, a pointerleave event must follow the pointerup event.
+ // TA: 3.6
+ on_event(target0, "pointerleave", function (event) {
+ if(event.pointerType == 'touch') {
+ if(pointerup_event != null) {
+ if(eventTested == false) {
+ eventTested = true;
+ test_pointerleave.step(function() {
+ assert_equals(event.pointerType, pointerup_event.pointerType, "pointerType is same for pointerup and pointerleave");
+ assert_equals(event.isPrimary, pointerup_event.isPrimary, "isPrimary is same for pointerup and pointerleave");
+ });
+ test_pointerleave.done();
+ }
+ }
+ else {
+ test_pointerleave.step(function() {
+ assert_unreached("pointerleave received before pointerup");
+ }, "pointerleave received before pointerup");
+ }
+ }
+ });
+ }
+
+ </script>
+ <h1>Pointer Events pointerleave tests</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerleave_descendant_over-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerleave_descendant_over-manual.html
new file mode 100644
index 00000000000..8f4f4bfc7a1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerleave_descendant_over-manual.html
@@ -0,0 +1,61 @@
+<!doctype html>
+<html>
+ <head>
+ <title>pointerleave + descendant</title>
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ </head>
+ <body onload="run()">
+ <h1>pointerleave</h1>
+ <h4>
+ Test Description: This test checks if pointerleave event works properly.
+ <ol>
+ <li>Put your mouse over the black rectangle
+ <li>Then move it into the purple rectangle
+ <li>Click on the purple rectangle to complete the test
+ </ol>
+ Note: when you entered the black rectangle once don't leave it before the end of the test to get proper results.
+ </h4>
+ <p>
+ <div id="target0" style="background:black">
+ <div id="target1" style="background:purple"></div>
+ </div>
+ <script>
+ var eventTested = false;
+ var pointerleaveReceived = false;
+ var detected_pointertypes = {};
+
+ add_completion_callback(showPointerTypes);
+
+ function run() {
+ var target0 = document.getElementById("target0");
+
+ // The pointerleave event must not be dispatched when the pointer enters a child element without leaving the hit test boundaries of the parent. (as distinct from pointerout)
+ // TA: 9.2
+ on_event(target1, "pointerdown", function(event) {
+ detected_pointertypes[event.pointerType] = true;
+
+ test(function() {
+ assert_true(!pointerleaveReceived, "pointerleave shouldn't be received on descendant's pointerover")
+ }, "pointerleave shouldn't be received on descendant's pointerover");
+ });
+
+ on_event(target0, "pointerleave", function (event) {
+ if (eventTested == false) {
+ pointerleaveReceived = true;
+ eventTested = true;
+ }
+ });
+ }
+ </script>
+ <h1>Pointer Events pointerleave tests</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ <p>Refresh the page to run the tests again with a different pointer type.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerleave_descendants-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerleave_descendants-manual.html
new file mode 100644
index 00000000000..ac9edcff38a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerleave_descendants-manual.html
@@ -0,0 +1,52 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Pointerleave + descendant</title>
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ </head>
+ <body onload="run()">
+ <h1>pointerleave</h1>
+ <h4>
+ Test Description: This test checks if pointerleave event works properly.
+ <p>Put your mouse over the black rectangle and then move it out through purple rectangle boundaries.</p>
+ </h4>
+ <p>
+ <div id="target0" style="background:black; height: 47px;">
+ <div style="background:purple; height: 35px; width: 90%; position: absolute"></div>
+ </div>
+ <script>
+ var eventTested = false;
+ var detected_pointertypes = {};
+
+ add_completion_callback(showPointerTypes);
+
+ function run() {
+ var target0 = document.getElementById("target0");
+ var test_pointerleave = async_test("pointerleave event received");
+
+ on_event(target0, "pointerover", function(event) {
+ detected_pointertypes[ event.pointerType ] = true;
+ });
+
+ // When a pointing device is moved off of the hit test boundaries of an element and all of its descendants, the pointerleave event must be dispatched.
+ // TA: 9.1
+ on_event(target0, "pointerleave", function (event) {
+ if (eventTested == false) {
+ test_pointerleave.done();
+ eventTested = true;
+ }
+ });
+ }
+ </script>
+ <h1>Pointer Events pointerleave tests</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ <p>Refresh the page to run the tests again with a different pointer type.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerleave_does_not_bubble-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerleave_does_not_bubble-manual.html
new file mode 100644
index 00000000000..c0e551cd658
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerleave_does_not_bubble-manual.html
@@ -0,0 +1,77 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Pointer Event: The pointerleave event does not bubble </title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/"/>
+ <meta name="assert" content="The pointerleave event must not bubble up to parent elements."/>
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <!-- /resources/testharness.js -->
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!-- Additional helper script for common checks across event types -->
+ <script type="text/javascript" src="pointerevent_support.js"></script>
+ <script type="text/javascript">
+ var detected_pointertypes = {};
+ var test_pointerEvent = async_test("pointerLeave event does not bubble"); // set up test harness
+ // showPointerTypes is defined in pointerevent_support.js
+ // Requirements: the callback function will reference the test_pointerEvent object and
+ // will fail unless the async_test is created with the var name "test_pointerEvent".
+ add_completion_callback(showPointerTypes);
+
+ function run() {
+ var target0 = document.getElementById("target0");
+ var parent0 = document.getElementById("parent0");
+
+ on_event(target0, "pointerleave", function (event) {
+ detected_pointertypes[event.pointerType] = true;
+ check_PointerEvent(event);
+ test_pointerEvent.step(function () {
+ assert_equals(event.type, "pointerleave", "pointer event received: " + event.type);
+ assert_false(event.bubbles, "pointerleave event.bubbles should be false: " + event.bubbles);
+ });
+ });
+
+ on_event(parent0, "pointerleave", function (event) {
+ test_pointerEvent.step(function () {
+ assert_equals(event.target.id, "parent0", "Recieved " + event.type + " in parent for " + event.target.id);
+ });
+ test_pointerEvent.done(); // complete test
+ });
+ }
+ </script>
+ <style>
+ #target0 {
+ background: purple;
+ border: 1px solid orange;
+ width:50px;
+ height:50px;
+ }
+ #parent0 {
+ background: black;
+ border: 1px solid orange;
+ width:100px;
+ height:100px;
+ }
+ </style>
+ </head>
+ <body onload="run()">
+ <h1> Pointer Event: pointerleave does not bubble</h1>
+ <h4>
+ Test Description:
+ The pointerleave event must not bubble up to parent elements.
+ </h4>
+ <div id="instructions">
+ Use the mouse or pen to hover over then out of the purple box nested in the black box. Or with touch, tap on the purple box.
+ </div>
+ <div id="parent0">
+ <div id="target0"></div>
+ </div>
+ <div id="complete-notice">
+ <p>Test complete: Scroll to Summary to view Pass/Fail Results.</p>
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ <p>Refresh the page to run the tests again with a different pointer type.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerleave_mouse-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerleave_mouse-manual.html
new file mode 100644
index 00000000000..708aed91af4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerleave_mouse-manual.html
@@ -0,0 +1,53 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Pointer Event: Dispatch pointerleave (mouse). </title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/"/>
+ <meta name="assert" content="When a pointing device that has continuous position (such as a mouse) leaves the hit test boundaries of an element, the pointerleave event must be dispatched."/>
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <!-- /resources/testharness.js -->
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!-- Additional helper script for common checks across event types -->
+ <script type="text/javascript" src="pointerevent_support.js"></script>
+ <script type="text/javascript">
+ var detected_pointertypes = {};
+ var test_pointerEvent = async_test("pointerleave event"); // set up test harness;
+ // showPointerTypes is defined in pointerevent_support.js
+ // Requirements: the callback function will reference the test_pointerEvent object and
+ // will fail unless the async_test is created with the var name "test_pointerEvent".
+ add_completion_callback(showPointerTypes);
+
+ function run() {
+ var target0 = document.getElementById("target0");
+
+ on_event(target0, "pointerleave", function (event) {
+ detected_pointertypes[event.pointerType] = true;
+ check_PointerEvent(event);
+ test_pointerEvent.step(function () {
+ assert_equals(event.pointerType, "mouse", "Test should be run using a mouse as input.");
+ assert_equals(event.type, "pointerleave", "The " + event.type + " event was received.");
+ });
+ test_pointerEvent.done(); // complete test
+ });
+ }
+ </script>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Event: Dispatch pointerleave (mouse)</h1>
+ <h4>
+ Test Description:
+ When a pointing device that has continuous position (such as a mouse) leaves the hit test boundaries of an element, the pointerleave event must be dispatched.
+ </h4>
+ <br />
+ <div id="target0">
+ Use a mouse to move over then out of this element
+ </div>
+ <div id="complete-notice">
+ <p>Test complete: Scroll to Summary to view Pass/Fail Results.</p>
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerleave_pen-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerleave_pen-manual.html
new file mode 100644
index 00000000000..38a2f697920
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerleave_pen-manual.html
@@ -0,0 +1,58 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Pointer Event: Dispatch pointerleave (pen). </title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/"/>
+ <meta name="assert" content="When a pointing device that supports hover (pen stylus) leaves the range of the digitizer while over an element, the pointerleave event must be dispatched."/>
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <!-- /resources/testharness.js -->
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!-- Additional helper script for common checks across event types -->
+ <script type="text/javascript" src="pointerevent_support.js"></script>
+ <script type="text/javascript">
+ var detected_pointertypes = {};
+ var test_pointerEvent = async_test("pointerleave event"); // set up test harness
+ // showPointerTypes is defined in pointerevent_support.js
+ // Requirements: the callback function will reference the test_pointerEvent object and
+ // will fail unless the async_test is created with the var name "test_pointerEvent".
+ add_completion_callback(showPointerTypes);
+
+ function run() {
+ var target0 = document.getElementById("target0");
+
+ on_event(target0, "pointerleave", function (event) {
+ detected_pointertypes[event.pointerType] = true;
+ check_PointerEvent(event);
+ test_pointerEvent.step(function () {
+ assert_equals(event.pointerType, "pen", "Test should be run using a pen as input");
+ assert_equals(event.type, "pointerleave", "The " + event.type + " event was received");
+ assert_true((event.clientX > target0.getBoundingClientRect().left)&&
+ (event.clientX < target0.getBoundingClientRect().right)&&
+ (event.clientY > target0.getBoundingClientRect().top)&&
+ (event.clientY < target0.getBoundingClientRect().bottom),
+ "pointerleave should be received inside of target bounds");
+ });
+ test_pointerEvent.done(); // complete test
+ });
+ }
+ </script>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Event: Dispatch pointerleave (pen)</h1>
+ <h4>
+ Test Description:
+ When a pointing device that supports hover (pen stylus) leaves the range of the digitizer while over an element, the pointerleave event must be dispatched.
+ </h4>
+ <br />
+ <div id="target0">
+ Use a pen to hover over then lift up away from this element.
+ </div>
+ <div id="complete-notice">
+ <p>Test complete: Scroll to Summary to view Pass/Fail Results.</p>
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerleave_touch-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerleave_touch-manual.html
new file mode 100644
index 00000000000..3044327a5ff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerleave_touch-manual.html
@@ -0,0 +1,53 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Pointer Event: Dispatch pointerleave (touch). </title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/"/>
+ <meta name="assert" content="When a pointing device that does not support hover (such as a finger) leaves the hit test boundaries as a result of a pointerup event, the pointerleave event must be dispatched. "/>
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <!-- /resources/testharness.js -->
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!-- Additional helper script for common checks across event types -->
+ <script type="text/javascript" src="pointerevent_support.js"></script>
+ <script type="text/javascript">
+ var detected_pointertypes = {};
+ var test_pointerEvent = async_test("pointerleave event");
+ // showPointerTypes is defined in pointerevent_support.js
+ // Requirements: the callback function will reference the test_pointerEvent object and
+ // will fail unless the async_test is created with the var name "test_pointerEvent".
+ add_completion_callback(showPointerTypes);
+
+ function run() {
+ var target0 = document.getElementById("target0");
+
+ on_event(target0, "pointerleave", function (event) {
+ detected_pointertypes[event.pointerType] = true;
+ check_PointerEvent(event);
+ test_pointerEvent.step(function () {
+ assert_equals(event.pointerType, "touch", "Test should be run using touch input");
+ assert_equals(event.type, "pointerleave", "The " + event.type + " event received");
+ });
+ test_pointerEvent.done(); // complete test
+ });
+ }
+ </script>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Event: Dispatch pointerleave (touch)</h1>
+ <h4>
+ Test Description:
+ When a pointing device that does not support hover (such as a finger) leaves the hit test boundaries as a result of a pointerup event, the pointerleave event must be dispatched.
+ </h4>
+ <br />
+ <div id="target0">
+ Use touch to tap on this box.
+ </div>
+ <div id="complete-notice">
+ <p>Test complete: Scroll to Summary to view Pass/Fail Results.</p>
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointermove-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointermove-manual.html
new file mode 100644
index 00000000000..cf1a1ee4ee8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointermove-manual.html
@@ -0,0 +1,44 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Pointermove</title>
+ <meta name="viewport" content="width=device-width">
+ <meta name="assert" content="When a pointer changes coordinates, the pointermove event must be dispatched."/>
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!-- Additional helper script for common checks across event types -->
+ <script type="text/javascript" src="pointerevent_support.js"></script>
+ </head>
+ <body onload="run()">
+ <h2>PointerMove</h2>
+ <h4>Test Description: This test checks if pointermove event triggers. Move your mouse over the black rectangle or slide it if you are using touchscreen.</h4>
+ <div id="target0" style="background:black"></div>
+ <script>
+ var eventTested = false;
+ var detected_pointertypes = {};
+ var test_pointermove = async_test("pointermove event received");
+ add_completion_callback(showPointerTypes);
+
+ function run() {
+ var target0 = document.getElementById("target0");
+
+ // When a pointer changes coordinates, the pointermove event must be dispatched.
+ // TA: 5.3
+ on_event(target0, "pointermove", function (event) {
+ detected_pointertypes[event.pointerType] = true;
+ if (eventTested == false) {
+ test_pointermove.done();
+ eventTested = true;
+ }
+ });
+ }
+ </script>
+ <h1>Pointer Events pointermove Tests</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ <p>Refresh the page to run the tests again with a different pointer type.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointermove_isprimary_same_as_pointerdown-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointermove_isprimary_same_as_pointerdown-manual.html
new file mode 100644
index 00000000000..b43d59f4f6e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointermove_isprimary_same_as_pointerdown-manual.html
@@ -0,0 +1,70 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Pointer Event: pointermove has same isPrimary as last pointerdown with the same pointerId</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/"/>
+ <meta name="assert" content="The isPrimary attribute of a pointermove event must have the same value as the isPrimary attribute of the last pointerdown event with the same pointerId attribute."/>
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <!-- /resources/testharness.js -->
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!-- Additional helper script for common checks across event types -->
+ <script type="text/javascript" src="pointerevent_support.js"></script>
+ <script type="text/javascript">
+ var detected_pointertypes = {};
+ var test_pointerEvent = async_test("pointermove has same isPrimary as last pointerdown"); // set up test harness
+ // showPointerTypes is defined in pointerevent_support.js
+ // Requirements: the callback function will reference the test_pointerEvent object and
+ // will fail unless the async_test is created with the var name "test_pointerEvent".
+ add_completion_callback(showPointerTypes);
+
+ var pointermove_event = null;
+ var pointerdown_event = null;
+
+ function run() {
+ var target0 = document.getElementById("target0");
+
+ on_event(target0, "pointermove", function (event) {
+ if (pointerdown_event != null) {
+ test_pointerEvent.step(function () {
+ assert_equals(event.pointerId, pointerdown_event.pointerId, "pointermove.pointerId should be the same as pointerdown.pointerId.");
+ assert_equals(event.isPrimary, pointerdown_event.isPrimary, "pointermove.isPrimary should be the same as pointerdown.isPrimary.");
+ });
+ pointermove_event = event;
+ }
+ });
+
+ on_event(target0, "pointerdown", function (event) {
+ pointerdown_event = event;
+ detected_pointertypes[event.pointerType] = true;
+ });
+
+ on_event(target0, "pointerup", function (event) {
+ test_pointerEvent.step(function () {
+ assert_not_equals(pointermove_event, null, "pointermove event was never received: ");
+ });
+ test_pointerEvent.done(); // complete test
+ });
+ }
+ </script>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Event: pointermove has the same isPrimary as last pointerdown with the same pointerId</h1>
+ <h4>Test Description:
+ The isPrimary attribute of a pointermove event must have the same value as the isPrimary attribute of the last pointerdown event with the same pointerId attribute.
+ </h4>
+ <div id="instructions">
+ Press and hold a mouse button, touch contact or pen contact on this element. Move around inside the element while maintaining contact/button down. Only use one device per test run.
+ <p>Lift off of the element to complete the test.</p>
+ </div>
+ <div id="target0" style="touch-action: none;">
+ </div>
+ <div id="complete-notice">
+ <p>Test complete: Scroll to Summary to view Pass/Fail Results.</p>
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ <p>Refresh the page to run the tests again with a different pointer type.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointermove_pointertype-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointermove_pointertype-manual.html
new file mode 100644
index 00000000000..4c410159c13
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointermove_pointertype-manual.html
@@ -0,0 +1,64 @@
+<!doctype html>
+<html>
+ <head>
+ <title>pointerType conservation</title>
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ </head>
+ <body onload="run()">
+ <h1>pointerType conservation</h1>
+ <h4>Test Description: This test checks if pointerType attribute defined properly.</h4>
+ <div id="instructions">
+ Press and move a mouse button, touch contact or pen contact on the black rectangle. Only use one device per test run.
+ </div>
+ <p>Note: This test may be run with different pointer devices, however only one device should be used per test run.
+ <p>
+ <div id="target0"></div>
+ <script>
+ var eventTested = false;
+ var pointerTypeGot = false;
+ var pointerdown_event;
+ var detected_pointertypes = {};
+
+ setup({ explicit_done: true });
+
+ add_completion_callback(showPointerTypes);
+
+ function run() {
+ var target0 = document.getElementById("target0");
+
+ on_event(target0, "pointerover", function(event) {
+ detected_pointertypes[ event.pointerType ] = true;
+ });
+
+ // The pointerType attribute of a pointermove event must have the same value as the pointerType attribute of the last pointerdown event with the same pointerId attribute.
+ // TA: 5.1
+ on_event(target0, "pointerdown", function (event) {
+ pointerdown_event = event;
+ pointerTypeGot = true;
+ });
+
+ on_event(target0, "pointermove", function (event) {
+ if(pointerTypeGot == true) {
+ if(!eventTested) {
+ test(function() {
+ assert_equals(event.pointerId, pointerdown_event.pointerId, "pointer IDs are equal: ");
+ assert_equals(event.pointerType, pointerdown_event.pointerType, "pointerType of pointermove event matches pointerdown event: ");
+ }, "pointerType is dispatched properly");
+ }
+ done();
+ }
+ });
+ }
+ </script>
+ <h1>Pointer Events pointerType conservation tests</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ <p>Refresh the page to run the tests again with a different pointer type.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerout-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerout-manual.html
new file mode 100644
index 00000000000..473fa14ebbc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerout-manual.html
@@ -0,0 +1,46 @@
+<!doctype html>
+<html>
+ <head>
+ <title>pointerout</title>
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!-- Additional helper script for common checks across event types -->
+ <script type="text/javascript" src="pointerevent_support.js"></script>
+ </head>
+ <body onload="run()">
+ <h2>pointerout</h2>
+ <h4>Test Description: This test checks if pointerout event triggers. Put your mouse over the black rectangle and then move it out of the rectangle boundaries. If you are using touchscreen tap the black rectangle. </h4>
+ <div id="target0" style="background: black"></div>
+ <script>
+ var test_pointerEvent = async_test("pointerout event received");
+ // showPointerTypes is defined in pointerevent_support.js
+ // Requirements: the callback function will reference the test_pointerEvent object and
+ // will fail unless the async_test is created with the var name "test_pointerEvent".
+ add_completion_callback(showPointerTypes);
+
+ var eventTested = false;
+ var detected_pointertypes = {};
+
+ function run() {
+ var target0 = document.getElementById("target0");
+
+ on_event(target0, "pointerout", function (event) {
+ detected_pointertypes[event.pointerType] = true;
+ if (eventTested == false) {
+ eventTested = true;
+ check_PointerEvent(event);
+ test_pointerEvent.done();
+ }
+ });
+ }
+ </script>
+ <h1>Pointer Events pointerout tests</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ <p>Refresh the page to run the tests again with a different pointer type.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerout_after_pointercancel_touch-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerout_after_pointercancel_touch-manual.html
new file mode 100644
index 00000000000..1888591a7c2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerout_after_pointercancel_touch-manual.html
@@ -0,0 +1,67 @@
+<!doctype html>
+<html>
+ <head>
+ <title>pointerout</title>
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!-- Additional helper script for common checks across event types -->
+ <script type="text/javascript" src="pointerevent_support.js"></script>
+ </head>
+ <body class="scrollable" onload="run()">
+ <h2>pointerout</h2>
+ <h4>Test Description: This test checks if pointerout event triggers after pointercancel. Start touch on the black rectangle and move your touch to scroll in any direction. </h4>
+ <p>Note: this test is for touch devices only</p>
+ <div id="target0"></div>
+ <script>
+ var test_pointerout = async_test("pointerout event received");
+ // showPointerTypes is defined in pointerevent_support.js
+ // Requirements: the callback function will reference the test_pointerEvent object and
+ // will fail unless the async_test is created with the var name "test_pointerEvent".
+ add_completion_callback(showPointerTypes);
+
+ var eventTested = false;
+ var pointercancel_event = null;
+ var detected_pointertypes = {};
+
+ function run() {
+ var target0 = document.getElementById("target0");
+
+ on_event(target0, "pointercancel", function (event) {
+ detected_pointertypes[event.pointerType] = true;
+ pointercancel_event = event;
+ });
+
+ // After firing the pointercancel event the pointerout event must be dispatched.
+ // TA: 4.3
+ on_event(target0, "pointerout", function (event) {
+ if(event.pointerType == 'touch') {
+ if(pointercancel_event != null) {
+ if (eventTested == false) {
+ test_pointerout.step(function() {
+ assert_equals(event.pointerType, pointercancel_event.pointerType, "pointerType is same for pointercancel and pointerout");
+ assert_equals(event.isPrimary, pointercancel_event.isPrimary, "isPrimary is same for pointercancel and pointerout");
+ });
+ eventTested = true;
+ test_pointerout.done();
+ }
+ }
+ else {
+ test_pointerout.step(function() {
+ assert_true(false,
+ "pointercancel received before pointerout");
+ }, "pointercancel received before pointerout");
+ }
+ }
+ });
+ }
+
+ </script>
+ <h1>Pointer Events pointerout tests</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerout_after_pointerup_nohover-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerout_after_pointerup_nohover-manual.html
new file mode 100644
index 00000000000..44813033a72
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerout_after_pointerup_nohover-manual.html
@@ -0,0 +1,67 @@
+<!doctype html>
+<html>
+ <head>
+ <title>pointerout</title>
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!-- Additional helper script for common checks across event types -->
+ <script type="text/javascript" src="pointerevent_support.js"></script>
+ </head>
+ <body onload="run()">
+ <h2>pointerout</h2>
+ <h4>Test Description: This test checks if pointerout event triggers for devices that don't support hover. Tap the black rectangle. </h4>
+ <p>Note: this test is only for devices that do not support hover.</p>
+ <div id="target0"></div>
+ <script>
+ var test_pointerout = async_test("pointerout event received");
+ // showPointerTypes is defined in pointerevent_support.js
+ // Requirements: the callback function will reference the test_pointerEvent object and
+ // will fail unless the async_test is created with the var name "test_pointerEvent".
+ add_completion_callback(showPointerTypes);
+
+ var eventTested = false;
+ var pointerup_event = null;
+ var detected_pointertypes = {};
+
+ function run() {
+ var target0 = document.getElementById("target0");
+
+ on_event(target0, "pointerup", function (event) {
+ detected_pointertypes[event.pointerType] = true;
+ pointerup_event = event;
+ });
+
+ // For input devices that do not support hover, a pointerout event must follow the pointerup event.
+ // TA: 3.6
+ on_event(target0, "pointerout", function (event) {
+ if(event.pointerType == 'touch') {
+ if(pointerup_event != null) {
+ if(eventTested == false) {
+ test_pointerout.step(function() {
+ assert_equals(event.pointerType, pointerup_event.pointerType, "pointerType is same for pointerup and pointerout");
+ assert_equals(event.isPrimary, pointerup_event.isPrimary, "isPrimary is same for pointerup and pointerout");
+ });
+ eventTested = true;
+ test_pointerout.done();
+ }
+ }
+ else {
+ test_pointerout.step(function() {
+ assert_true(false,
+ "pointerup received before pointerout");
+ }, "pointerup received before pointerout");
+ }
+ }
+ });
+ }
+
+ </script>
+ <h1>Pointer Events pointerout tests</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerout_pen-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerout_pen-manual.html
new file mode 100644
index 00000000000..3973948c164
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerout_pen-manual.html
@@ -0,0 +1,57 @@
+<!doctype html>
+<html>
+ <head>
+ <title>pointerout</title>
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!-- Additional helper script for common checks across event types -->
+ <script type="text/javascript" src="pointerevent_support.js"></script>
+ </head>
+ <body onload="run()">
+ <h2>pointerout</h2>
+ <h4>Test Description: This test checks if pointerout event triggers for pen. Place your pen over the black rectangle and then pull the pen out of the digitizer's detectable range. </h4>
+ <p>Note: this test is for devices that support hover - for pen only</p>
+ <div id="target0"></div>
+ <script>
+ var test_pointerout = async_test("pointerout event received");
+ // showPointerTypes is defined in pointerevent_support.js
+ // Requirements: the callback function will reference the test_pointerEvent object and
+ // will fail unless the async_test is created with the var name "test_pointerEvent".
+ add_completion_callback(showPointerTypes);
+
+ var eventTested = false;
+ var isPointerupReceived = false;
+ var detected_pointertypes = {};
+
+ function run() {
+ var target0 = document.getElementById("target0");
+
+ // When a pen stylus leaves the hover range detectable by the digitizer the pointerout event must be dispatched.
+ // TA: 7.2
+ on_event(target0, "pointerout", function (event) {
+ detected_pointertypes[event.pointerType] = true;
+ if(event.pointerType == 'pen') {
+ if (eventTested == false) {
+ eventTested = true;
+ test_pointerout.done();
+ }
+ }
+ else {
+ test_pointerout.step(function() {
+ assert_true(false,
+ "you have to use pen for this test");
+ }, "you have to use pen for this test");
+ }
+ });
+ }
+
+ </script>
+ <h1>Pointer Events pointerout tests</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerout_received_once-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerout_received_once-manual.html
new file mode 100644
index 00000000000..4827ae91de1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerout_received_once-manual.html
@@ -0,0 +1,58 @@
+<!doctype html>
+<html>
+ <head>
+ <title>pointerout received just once</title>
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <meta name="viewport" content="width=device-width">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ </head>
+ <body onload="run()">
+ <h1>pointerout received just once</h1>
+ <h4>
+ Test Description: This test checks if pointerout event dispatched properly.
+ <ol>
+ <li>Put your mouse over the black rectangle.
+ <li>Move your mouse out of the black rectangle
+ </ol>
+ </h4>
+ <p>
+ <div id="target0" style="background:black"></div>
+ <script>
+ var pointeroutCounter = 0;
+ var detected_pointertypes = {};
+
+ setup({ explicit_done: true });
+ add_completion_callback(showPointerTypes);
+
+ function run() {
+ var target0 = document.getElementById("target0");
+
+ // When a mouse passes through dispatches one event
+ // TA: 7.4
+ on_event(target0, "pointerover", function (event) {
+ pointeroutCounter = 0;
+ detected_pointertypes[event.pointerType] = true;
+ });
+
+ on_event(target0, "pointerout", function (event) {
+ pointeroutCounter++;
+
+ setTimeout(function() {
+ test(function() {
+ assert_true(pointeroutCounter == 1, "pointerout received just once")
+ }, "pointerout received just once");
+ done();
+ }, 5000);
+ });
+ }
+ </script>
+ <h1>Pointer Events pointerout received once test</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ <p>Refresh the page to run the tests again with a different pointer type.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerover-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerover-manual.html
new file mode 100644
index 00000000000..4601c08aaaf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerover-manual.html
@@ -0,0 +1,52 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Pointer Event: Dispatch pointerover. </title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/"/>
+ <meta name="assert" content="When a pointing device is moved into the hit test boundaries of an element, the pointerover event must be dispatched. "/>
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <!-- /resources/testharness.js -->
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!-- Additional helper script for common checks across event types -->
+ <script type="text/javascript" src="pointerevent_support.js"></script>
+ <script type="text/javascript">
+ var detected_pointertypes = {};
+ var test_pointerEvent = async_test("pointerover is dispatched"); // set up test harness;
+ // showPointerTypes is defined in pointerevent_support.js
+ // Requirements: the callback function will reference the test_pointerEvent object and
+ // will fail unless the async_test is created with the var name "test_pointerEvent".
+ add_completion_callback(showPointerTypes);
+
+ function run() {
+ var target0 = document.getElementById("target0");
+
+ on_event(target0, "pointerover", function (event) {
+ detected_pointertypes[event.pointerType] = true;
+ test_pointerEvent.step(function () {
+ check_PointerEvent(event);
+ assert_equals(event.type, "pointerover", "Pointer Event received");
+ });
+ test_pointerEvent.done(); // complete test
+ });
+ }
+ </script>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Event: Dispatch pointerover.</h1>
+ <h4>Test Description:
+ When a pointing device is moved into the hit test boundaries of an element, the pointerover event must be dispatched.
+ </h4>
+ <br />
+ <div id="target0">
+ Use mouse, touch or pen to hover or contact this element..
+ </div>
+ <div id="complete-notice">
+ <p>Test complete: Scroll to Summary to view Pass/Fail Results.</p>
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ <p>Refresh the page to run the tests again with a different pointer type.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointertype_mouse-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointertype_mouse-manual.html
new file mode 100644
index 00000000000..b1e7d7046ea
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointertype_mouse-manual.html
@@ -0,0 +1,63 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Pointer Event: If a pointer event is initiated by a mouse device, then the pointerType must be "mouse"</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/"/>
+ <meta name="assert" content="If a pointer event is initiated by a mouse device, then the pointerType must be 'mouse'."/>
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <!-- /resources/testharness.js -->
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!-- Additional helper script for common checks across event types -->
+ <script type="text/javascript" src="pointerevent_support.js"></script>
+ <script type="text/javascript">
+ var detected_pointertypes = {};
+ var test_pointerEvent = async_test("pointer event have pointerType as mouse"); // set up test harness
+ var eventTested = false;
+
+ // showPointerTypes is defined in pointerevent_support.js
+ // Requirements: the callback function will reference the test_pointerEvent object and
+ // will fail unless the async_test is created with the var name "test_pointerEvent".
+ add_completion_callback(showPointerTypes);
+
+ function eventHandler(event) {
+ detected_pointertypes[event.pointerType] = true;
+ if(!eventTested && event.type == "pointerover") {
+ check_PointerEvent(event);
+ test_pointerEvent.step(function () {
+ assert_equals(event.pointerType, "mouse", "Verify event.pointerType is 'mouse'.");
+ });
+ eventTested = true;
+ }
+ if (event.type == "pointerup") {
+ test_pointerEvent.done(); // complete test
+ }
+ }
+
+ function run() {
+ var target0 = document.getElementById("target0");
+
+ // listen for all events.
+ for (var i = 0; i < All_Pointer_Events.length; i++) {
+ on_event(target0, All_Pointer_Events[i], eventHandler);
+ }
+ }
+ </script>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Event: Dispatch pointer events with pointerType equal to "mouse"</h1>
+ <h4>Test Description:
+ If a pointer event is initiated by a mouse device, then the pointerType must be 'mouse'.
+ </h4>
+ <br />
+ <div id="target0">
+ Using the mouse, click this element.
+ </div>
+ <div id="complete-notice">
+ <p>Test complete: Scroll to Summary to view Pass/Fail Results.</p>
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointertype_pen-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointertype_pen-manual.html
new file mode 100644
index 00000000000..0aabfce4fc9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointertype_pen-manual.html
@@ -0,0 +1,61 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Pointer Event: If a pointer event is initiated by a pen device, then the pointerType must be "pen"</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/"/>
+ <meta name="assert" content="If a pointer event is initiated by a pen device, then the pointerType must be 'pen'."/>
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <!-- /resources/testharness.js -->
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!-- Additional helper script for common checks across event types -->
+ <script type="text/javascript" src="pointerevent_support.js"></script>
+ <script type="text/javascript">
+ var detected_pointertypes = {};
+ var test_pointerEvent = async_test("pointer event has pointerType as pen"); // set up test harness
+ var eventTested = false;
+ // showPointerTypes is defined in pointerevent_support.js
+ // Requirements: the callback function will reference the test_pointerEvent object and
+ // will fail unless the async_test is created with the var name "test_pointerEvent".
+ add_completion_callback(showPointerTypes);
+
+ function eventHandler(event) {
+ detected_pointertypes[event.pointerType] = true;
+ if(!eventTested) {
+ check_PointerEvent(event);
+ test_pointerEvent.step(function () {
+ assert_equals(event.pointerType, "pen", "Verify event.pointerType is 'pen'.");
+ });
+ eventTested = true;
+ }
+ if (event.type == "pointerup") {
+ test_pointerEvent.done(); // complete test
+ }
+ }
+
+ function run() {
+ var target0 = document.getElementById("target0");
+ // listen for all events.
+ for (var i = 0; i < All_Pointer_Events.length; i++) {
+ on_event(target0, All_Pointer_Events[i], eventHandler);
+ }
+ }
+ </script>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Event: Dispatch pointer events with pointerType equal to "pen"</h1>
+ <h4>Test Description:
+ If a pointer event is initiated by a pen device, then the pointerType must be 'pen'.
+ </h4>
+ <br />
+ <div id="target0">
+ Using pen, tap here.
+ </div>
+ <div id="complete-notice">
+ <p>Test complete: Scroll to Summary to view Pass/Fail Results.</p>
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointertype_touch-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointertype_touch-manual.html
new file mode 100644
index 00000000000..c06fbe48c6d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointertype_touch-manual.html
@@ -0,0 +1,62 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Pointer Event: If a pointer event is initiated by a touch device, then the pointerType must be "touch"</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/"/>
+ <meta name="assert" content="If a pointer event is initiated by a touch device, then the pointerType must be 'touch'."/>
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <!-- /resources/testharness.js -->
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!-- Additional helper script for common checks across event types -->
+ <script type="text/javascript" src="pointerevent_support.js"></script>
+ <script type="text/javascript">
+ var detected_pointertypes = {};
+ var test_pointerEvent = async_test("pointer event has pointerType as touch"); // set up test harness
+ var eventTested = false;
+ // showPointerTypes is defined in pointerevent_support.js
+ // Requirements: the callback function will reference the test_pointerEvent object and
+ // will fail unless the async_test is created with the var name "test_pointerEvent".
+ add_completion_callback(showPointerTypes);
+
+ function eventHandler(event) {
+ detected_pointertypes[event.pointerType] = true;
+ if(!eventTested) {
+ check_PointerEvent(event);
+ test_pointerEvent.step(function () {
+ assert_equals(event.pointerType, "touch", "Verify event.pointerType is 'touch'.");
+ });
+ eventTested = true;
+ }
+ if (event.type == "pointerup") {
+ test_pointerEvent.done(); // complete test
+ }
+ }
+
+ function run() {
+ var target0 = document.getElementById("target0");
+
+ // listen for all events.
+ for (var i = 0; i < All_Pointer_Events.length; i++) {
+ on_event(target0, All_Pointer_Events[i], eventHandler);
+ }
+ }
+ </script>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Event: Dispatch pointer events with pointerType equal to "touch"</h1>
+ <h4>Test Description:
+ If a pointer event is initiated by a touch device, then the pointerType must be 'touch'.
+ </h4>
+ <br />
+ <div id="target0">
+ Using touch, tap here.
+ </div>
+ <div id="complete-notice">
+ <p>Test complete: Scroll to Summary to view Pass/Fail Results.</p>
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerup-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerup-manual.html
new file mode 100644
index 00000000000..30a03f23dcf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerup-manual.html
@@ -0,0 +1,44 @@
+<!doctype html>
+<html>
+ <head>
+ <title>pointerup</title>
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!-- Additional helper script for common checks across event types -->
+ <script type="text/javascript" src="pointerevent_support.js"></script>
+ </head>
+ <body onload="run()">
+ <h1>pointerup</h1>
+ <h4>Test Description: This test checks if pointerup event triggers. Press mouse left button and release it over the black rectangle or tap it if you are using a touchscreen.</h4>
+ <div id="target0" style="background:black"></div>
+ <script>
+ var detected_pointertypes = {};
+ var test_pointerEvent = async_test("pointerup event received");
+ // showPointerTypes is defined in pointerevent_support.js
+ // Requirements: the callback function will reference the test_pointerEvent object and
+ // will fail unless the async_test is created with the var name "test_pointerEvent".
+ add_completion_callback(showPointerTypes);
+
+ function run() {
+ var target0 = document.getElementById("target0");
+
+ on_event(target0, "pointerup", function (event) {
+ detected_pointertypes[event.pointerType] = true;
+ test_pointerEvent.step(function () {
+ check_PointerEvent(event);
+ assert_equals(event.type, "pointerup", "Pointer Event received.");
+ });
+ test_pointerEvent.done();
+ });
+ }
+ </script>
+ <h1>Pointer Events pointerup tests</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ <p>Refresh the page to run the tests again with a different pointer type.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerup_isprimary_same_as_pointerdown-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerup_isprimary_same_as_pointerdown-manual.html
new file mode 100644
index 00000000000..994061b8bf0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerup_isprimary_same_as_pointerdown-manual.html
@@ -0,0 +1,63 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Pointer Event: pointerup has same isPrimary as last pointerdown with the same pointerId</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/"/>
+ <meta name="assert" content="The isPrimary attribute of a pointerup event must have the same value as the isPrimary attribute of the last pointerdown event with the same pointerId attribute."/>
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <!-- /resources/testharness.js -->
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!-- Additional helper script for common checks across event types -->
+ <script type="text/javascript" src="pointerevent_support.js"></script>
+ <script type="text/javascript">
+ var detected_pointertypes = {};
+ var test_pointerEvent = async_test("pointerup has same isPrimary as last pointerdown"); // set up test harness
+ // showPointerTypes is defined in pointerevent_support.js
+ // Requirements: the callback function will reference the test_pointerEvent object and
+ // will fail unless the async_test is created with the var name "test_pointerEvent".
+ add_completion_callback(showPointerTypes);
+
+ var pointerup_event = null;
+ var pointerdown_event = null;
+
+ function run() {
+ var target0 = document.getElementById("target0");
+
+ on_event(target0, "pointerup", function (event) {
+ if (pointerdown_event != null) {
+ test_pointerEvent.step(function () {
+ assert_equals(event.pointerId, pointerdown_event.pointerId, "pointerup.pointerId should be the same as pointerdown.pointerId.");
+ assert_equals(event.isPrimary, pointerdown_event.isPrimary, "pointerup.isPrimary should be the same as pointerdown.isPrimary.");
+ });
+ pointerup_event = event;
+ test_pointerEvent.done(); // complete test
+ }
+ });
+
+ on_event(target0, "pointerdown", function (event) {
+ pointerdown_event = event;
+ detected_pointertypes[event.pointerType] = true;
+ });
+ }
+ </script>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Event: pointerup has the same isPrimary as last pointerdown with the same pointerId</h1>
+ <h4>Test Description:
+ The isPrimary attribute of a pointerup event must have the same value as the isPrimary attribute of the last pointerdown event with the same pointerId attribute.
+ </h4>
+ <div id="instructions">
+ Press and release a mouse button, touch contact or pen contact on this element. Only use one device per test run.
+ </div>
+ <div id="target0" style="touch-action: none;">
+ </div>
+ <div id="complete-notice">
+ <p>Test complete: Scroll to Summary to view Pass/Fail Results.</p>
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ <p>Refresh the page to run the tests again with a different pointer type.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerup_pointertype-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerup_pointertype-manual.html
new file mode 100644
index 00000000000..b356484bacc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_pointerup_pointertype-manual.html
@@ -0,0 +1,64 @@
+<!doctype html>
+<html>
+ <head>
+ <title>pointerType conservation</title>
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ </head>
+ <body onload="run()">
+ <h1>pointerType conservation</h1>
+ <h4>Test Description: This test checks if pointerType attribute defined properly.</h4>
+ <div id="instructions">
+ Press and release a mouse button, touch contact or pen contact on the black rectangle. Only use one device per test run.
+ </div>
+ <p>Note: This test may be run with different pointer devices, however only one device should be used per test run.
+ <p>
+ <div id="target0"></div>
+ <script>
+ var eventTested = false;
+ var pointerTypeGot = false;
+ var pointerdown_event;
+ var detected_pointertypes = {};
+
+ setup({ explicit_done: true });
+
+ add_completion_callback(showPointerTypes);
+
+ function run() {
+ var target0 = document.getElementById("target0");
+
+ on_event(target0, "pointerover", function(event) {
+ detected_pointertypes[ event.pointerType ] = true;
+ });
+
+ // The pointerType attribute of a pointerup event must have the same value as the pointerType attribute of the last pointerdown event with the same pointerId attribute.
+ // TA: 3.1
+ on_event(target0, "pointerdown", function (event) {
+ pointerdown_event = event;
+ pointerTypeGot = true;
+ });
+
+ on_event(target0, "pointerup", function (event) {
+ if(pointerTypeGot == true) {
+ if(!eventTested) {
+ test(function() {
+ assert_equals(event.pointerId, pointerdown_event.pointerId, "pointer IDs are equal: ");
+ assert_equals(event.pointerType, pointerdown_event.pointerType, "pointerType of pointerup event matches pointerdown event: ");
+ }, "pointerType is dispatched properly");
+ }
+ done();
+ }
+ });
+ }
+ </script>
+ <h1>Pointer Events pointerType conservation tests</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ <p>Refresh the page to run the tests again with a different pointer type.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_releasepointercapture_events_to_original_target-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_releasepointercapture_events_to_original_target-manual.html
new file mode 100644
index 00000000000..f3991d98d74
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_releasepointercapture_events_to_original_target-manual.html
@@ -0,0 +1,116 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Pointer Event: releasePointerCapture() - subsequent events follow normal hitting testing mechanisms</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/"/>
+ <meta name="assert" content="After invoking the releasePointerCapture method on an element, subsequent events for the specified pointer must follow normal hit testing mechanisms for determining the event target"/>
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!-- Additional helper script for common checks across event types -->
+ <script type="text/javascript" src="pointerevent_support.js"></script>
+ <script type="text/javascript">
+ var detected_pointertypes = {};
+ var test_pointerEvent = async_test("lostpointercapture: subsequent events to target."); // set up test harness
+ var suppressedEventsFail = false;
+ // showPointerTypes is defined in pointerevent_support.js
+ // Requirements: the callback function will reference the test_pointerEvent object and
+ // will fail unless the async_test is created with the var name "test_pointerEvent".
+ add_completion_callback(showPointerTypes);
+
+ var captured_event;
+ var f_gotPointerCapture = false;
+ var f_lostPointerCapture = false;
+
+ function listenerEventHandler(event) {
+ detected_pointertypes[event.pointerType] = true;
+ if (event.type == "gotpointercapture") {
+ f_gotPointerCapture = true;
+ check_PointerEvent(event);
+ }
+ else if (event.type == "lostpointercapture") {
+ f_lostPointerCapture = true;
+ f_gotPointerCapture = false;
+ check_PointerEvent(event);
+ }
+ else if(event.type == "pointerover" || event.type == "pointerenter" || event.type == "pointerout" || event.type == "pointerleave") {
+ if(!suppressedEventsFail) {
+ test(function() {
+ assert_true(false, "Suppressed events were received");
+ }, "Suppressed events were received");
+ suppressedEventsFail = true;
+ }
+ }
+ else if (event.pointerId == captured_event.pointerId) {
+ if (f_gotPointerCapture && event.type == "pointermove") {
+ // on first event received for capture, release capture
+ listener.releasePointerCapture(event.pointerId);
+ }
+ else {
+ // if any other events are received after releaseCapture, then the test fails
+ test_pointerEvent.step(function () {
+ assert_true(false, event.target.id + "-" + event.type + " should be handled by target element handler");
+ });
+ }
+ }
+ }
+
+ function targetEventHandler(event) {
+ if (f_gotPointerCapture) {
+ if(event.type != "pointerout" && event.type != "pointerleave") {
+ test_pointerEvent.step(function () {
+ assert_true(false, "The Target element should not have received any events while capture is active. Event recieved:" + event.type + ". ");
+ });
+ }
+ }
+
+ if (event.type == "pointerdown") {
+ // pointerdown event received will be used to capture events.
+ listener.setPointerCapture(event.pointerId);
+ captured_event = event;
+ }
+
+ if (f_lostPointerCapture) {
+ test_pointerEvent.step(function () {
+ assert_equals(event.pointerId, captured_event.pointerId, "pointerID is same for event captured and after release");
+ });
+ if (event.type == "pointerup") {
+ test_pointerEvent.done(); // complete test
+ }
+ }
+ }
+
+ function run() {
+ var listener = document.getElementById("listener");
+ var target0 = document.getElementById("target0");
+ target0.style["touchAction"] = "none";
+
+ // target0 and listener - handle all events
+ for (var i = 0; i < All_Pointer_Events.length; i++) {
+ on_event(target0, All_Pointer_Events[i], targetEventHandler);
+ on_event(listener, All_Pointer_Events[i], listenerEventHandler);
+ }
+ }
+ </script>
+ </head>
+ <body onload="run()">
+ <div id="listener"></div>
+ <h1>Pointer Event: releasePointerCapture() - subsequent events follow normal hitting testing mechanisms</h1>
+ <h4>
+ Test Description:
+ After invoking the releasePointerCapture method on an element, subsequent events for the specified
+ pointer must follow normal hit testing mechanisms for determining the event target
+ </h4>
+ <br />
+ <div id="target0">
+ Use mouse, touch or pen to contact here and move around.
+ </div>
+ <div id="complete-notice">
+ <p>Test complete: Scroll to Summary to view Pass/Fail Results.</p>
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ <p>Refresh the page to run the tests again with a different pointer type.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_releasepointercapture_invalid_pointerid-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_releasepointercapture_invalid_pointerid-manual.html
new file mode 100644
index 00000000000..fe2ab006181
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_releasepointercapture_invalid_pointerid-manual.html
@@ -0,0 +1,76 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Pointer Event: releasePointerCapture DOMException - InvalidPointerId</title>
+ <meta name="assert" content="releasePointerCapture DOMException - InvalidPointerId"/>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/"/>
+ <link rel="help" href="http://www.w3.org/wiki/PointerEvents/TestAssertions">
+ <meta name="assert" content="When the releasePointerCapture method is invoked, if the provided pointerId value does not match any of the active pointers, a DOMException with the name InvalidPointerId must be thrown."/>
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <!-- /resources/testharness.js -->
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!-- Additional helper script for common checks across event types -->
+ <script type="text/javascript" src="pointerevent_support.js"></script>
+ <script type="text/javascript">
+ var detected_pointertypes = {};
+ var test_pointerEvent = async_test("releasePointerCapture: DOMException InvalidPointerId"); // set up test harness
+ // showPointerTypes is defined in pointerevent_support.js
+ // Requirements: the callback function will reference the test_pointerEvent object and
+ // will fail unless the async_test is created with the var name "test_pointerEvent".
+ add_completion_callback(showPointerTypes);
+
+ var invalid_pointerId = 314159265358973923;
+
+ function run() {
+ var target0 = document.getElementById("target0");
+ target0.style["touchAction"] = "none";
+ var listener = document.getElementById("listener");
+
+ // try to release pointer capture with an invalid id
+ on_event(listener, "pointermove", function (event) {
+ detected_pointertypes[event.pointerType] = true;
+
+ try {
+ listener.releasePointerCapture(invalid_pointerId);
+
+ test_pointerEvent.step(function () {
+ assert_true(false, "DOMException not thrown. Expected: InvalidPointerId should have been thrown");
+ });
+ } catch (e) {
+ test_pointerEvent.step(function () {
+ assert_true(e.name == "InvalidPointerId", "DOMException should be InvalidPointerId");
+ });
+ }
+ test_pointerEvent.done(); // complete test
+ });
+
+ // set pointer capture
+ on_event(target0, "pointerdown", function (event) {
+ detected_pointertypes[event.pointerType] = true;
+ listener.setPointerCapture(event.pointerId);
+ });
+ }
+ </script>
+ </head>
+ <body onload="run()">
+ <div id="listener"></div>
+ <h1> Pointer Event: releasePointerCapture() DOMException - InvalidPointerId</h1>
+ <h4>
+ Test Description:
+ Upon invocation of the releasePointerCapture method, if the provided pointerId value does not match any of the
+ active pointers, a DOMException with the name InvalidPointerId must be thrown.
+ </h4>
+ <br />
+ <div id="target0">
+ Use the mouse, touch or pen to move over or contact this box.
+ </div>
+ <div id="complete-notice">
+ <p>Test complete: Scroll to Summary to view Pass/Fail Results.</p>
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ <p>Refresh the page to run the tests again with a different pointer type.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_releasepointercapture_onpointercancel_touch-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_releasepointercapture_onpointercancel_touch-manual.html
new file mode 100644
index 00000000000..105e3b5a974
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_releasepointercapture_onpointercancel_touch-manual.html
@@ -0,0 +1,71 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Release capture on pointercancel</title>
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ </head>
+ <body class="scrollable">
+ <h1>Pointer Events Capture Test - release capture on pointercancel</h1>
+ <h4>
+ Test Description: This test checks if setCapture/releaseCapture functions works properly. Complete the following actions:
+ <ol>
+ <li> Touch black rectangle and do not release your touch
+ <li> Move your touch to scroll the page. "lostpointercapture" should be logged inside of the black rectangle immediately after "pointercancel"
+ </ol>
+ </h4>
+ Test passes if the proper behavior of the events is observed.
+ <div id="target0" style="background:black; color:white"></div>
+
+ <script type='text/javascript'>
+ var pointercancelGot = false;
+ var count=0;
+ var detected_pointertypes = {};
+ var test_pointerEvent = async_test("pointer capture is released on pointercancel");
+
+ var target0 = document.getElementById('target0');
+
+ add_completion_callback(showPointerTypes);
+
+ window.onload = function() {
+ on_event(target0, 'pointerdown', function(e) {
+ detected_pointertypes[e.pointerType] = true;
+ test_pointerEvent.step(function () {
+ assert_equals(e.pointerType, "touch", "Test should be run using a touch as input");
+ });
+ isPointerCapture = true;
+ sPointerCapture(e);
+ pointercancelGot = false;
+ });
+
+ on_event(target0, 'gotpointercapture', function(e) {
+ log("gotpointercapture", document.getElementById('target0'));
+ });
+
+ // If the setPointerCapture method has been invoked on the pointer specified by pointerId, and the releasePointerCapture method has not been invoked, a lostpointercapture event must be dispatched to the element on which the setPointerCapture method was invoked. Furthermore, subsequent events for the specified pointer must follow normal hit testing mechanisms for determining the event target.
+ // TA: 4.4
+ on_event(target0, 'lostpointercapture', function(e) {
+ log("lostpointercapture", document.getElementById('target0'));
+ test_pointerEvent.step(function () {
+ assert_true(pointercancelGot, "pointercancel was received before lostpointercapture");
+ });
+ test_pointerEvent.done();
+ });
+
+ on_event(target0, 'pointercancel', function(e) {
+ log("pointercancel", target0);
+ pointercancelGot = true;
+ });
+ }
+ </script>
+ <h1>Pointer Events Capture Test</h1>
+ <div id="complete-notice">
+ <p>Test complete: Scroll to Summary to view Pass/Fail Results.</p>
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_releasepointercapture_onpointerup_mouse-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_releasepointercapture_onpointerup_mouse-manual.html
new file mode 100644
index 00000000000..df515436c05
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_releasepointercapture_onpointerup_mouse-manual.html
@@ -0,0 +1,79 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Release capture on pointerup</title>
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ </head>
+ <body>
+ <h1>Pointer Events Capture Test - release capture on pointerup</h1>
+ <h4>
+ Test Description: This test checks if setCapture/releaseCapture functions works properly. Complete the following actions:
+ <ol>
+ <li> Press and hold left mouse button over "Set Capture" button
+ <li> Release left mouse button anywhere over the document. "lostpointercapture" should be logged inside of the black rectangle immediately after "pointerup"
+ </ol>
+ </h4>
+ Test passes if the proper behavior of the events is observed.
+ <div id="target0" style="background:black; color:white"></div>
+ <br>
+ <input type="button" id="btnCapture" value="Set Capture">
+ <script type='text/javascript'>
+ var isPointerCapture = false;
+ var pointerupGot = false;
+ var count=0;
+
+ var detected_pointertypes = {};
+ add_completion_callback(showPointerTypes);
+
+ var target0 = document.getElementById('target0');
+ var captureButton = document.getElementById('btnCapture');
+
+ setup({ explicit_done: true });
+
+ window.onload = function() {
+ on_event(captureButton, 'pointerdown', function(e) {
+ detected_pointertypes[e.pointerType] = true;
+ if(isPointerCapture == false) {
+ isPointerCapture = true;
+ sPointerCapture(e);
+ pointerupGot = false;
+ }
+ });
+
+ on_event(target0, 'gotpointercapture', function(e) {
+ log("gotpointercapture", document.getElementById('target0'));
+ });
+
+ // If the setPointerCapture method has been invoked on the pointer specified by pointerId,
+ // and the releasePointerCapture method has not been invoked,a lostpointercapture event must be
+ // dispatched to the element on which the setPointerCapture method was invoked. Furthermore,
+ // subsequent events for the specified pointer must follow normal hit testing mechanisms for
+ // determining the event target.
+ // TA: 3.7
+ on_event(target0, 'lostpointercapture', function(e) {
+ test(function() {
+ assert_true(pointerupGot, "pointerup was received before lostpointercapture")
+ }, "pointerup was received before lostpointercapture");
+ log("lostpointercapture", document.getElementById('target0'));
+ isPointerCapture = false;
+ done();
+ });
+
+ on_event(target0, 'pointerup', function(e) {
+ log("pointerup", target0);
+ pointerupGot = true;
+ });
+ }
+ </script>
+ <h1>Pointer Events Capture Test</h1>
+ <div id="complete-notice">
+ <p>Test complete: Scroll to Summary to view Pass/Fail Results.</p>
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_setpointercapture_disconnected-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_setpointercapture_disconnected-manual.html
new file mode 100644
index 00000000000..9e9646525fa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_setpointercapture_disconnected-manual.html
@@ -0,0 +1,55 @@
+<!doctype html>
+<html>
+ <head>
+ <title>setPointerCapture() throws on disconnected node</title>
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ <script type="text/javascript">
+ var detected_pointertypes = {};
+ add_completion_callback(showPointerTypes);
+ var test_setPointerCapture = async_test("setPointerCapture: DOMException InvalidStateError");
+
+ function run() {
+ var target0 = document.getElementById("target0");
+ var target1 = document.getElementById("target1");
+
+ target1.parentNode.removeChild(target1);
+
+ on_event(target0, "pointerdown", function (event) {
+ detected_pointertypes[ event.pointerType ] = true;
+ try {
+ target1.setPointerCapture(event.pointerId);
+
+ test_setPointerCapture.step(function() {
+ assert_unreached("DOMException: InvalidStateError should have been thrown.");
+ });
+ } catch (e) {
+ // TA: 13.4
+ test_setPointerCapture.step(function() {
+ assert_equals(e.name, "InvalidStateError", "DOMException should be InvalidStateError");
+ });
+ }
+ test_setPointerCapture.done();
+ });
+ }
+ </script>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Event: DOMException InvalidStateError</h1>
+ <h4>Test Description:
+ When the setPointerCapture method is invoked, if the target node does not participate in its ownerDocument's tree, a DOMException with the name InvalidStateError must be thrown.
+ </h4>
+ <br>
+ <div id="target0">
+ Use the mouse, touch or pen to contact this box.
+ </div>
+ <div id="target1"></div>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_setpointercapture_inactive_button_mouse-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_setpointercapture_inactive_button_mouse-manual.html
new file mode 100644
index 00000000000..b3e8debb716
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_setpointercapture_inactive_button_mouse-manual.html
@@ -0,0 +1,58 @@
+<!doctype html>
+<html>
+ <head>
+ <title>setPointerCapture + inactive button state</title>
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <meta name="viewport" content="width=device-width">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ </head>
+ <body onload="run()">
+ <h1>setPointerCapture</h1>
+ <h4>
+ Test Description: This test checks if setPointerCapture works properly.
+ <ol>
+ <li>Put your mouse over the black rectangle
+ <li>Move you mouse out to complete the test
+ </ol>
+ </h4>
+ <p>
+ <div id="target0" style="background:black; color:white;"></div>
+ <script>
+ var detected_pointertypes = {};
+
+ var captureGot = false;
+
+ setup({ explicit_done: true });
+ add_completion_callback(showPointerTypes);
+
+ function run() {
+ var target0 = document.getElementById("target0");
+
+ on_event(target0, "pointerover", function (event) {
+ detected_pointertypes[event.pointerType] = true;
+ target0.setPointerCapture(event.pointerId);
+ });
+
+ // When the setPointerCapture method is invoked, if the specified pointer is not in active button state, then the method must have no effect on subsequent pointer events.
+ // TA: 13.2
+ on_event(target0, "pointerout", function (event) {
+ test(function() {
+ assert_false(captureGot, "pointer capture is not set while button state is inactive")
+ }, "pointer capture is not set while button state is inactive");
+ done();
+ });
+
+ on_event(target0, 'gotpointercapture', function(e) {
+ captureGot = true;
+ });
+ }
+ </script>
+ <h1>Pointer Events setPointerCapture Tests</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_setpointercapture_invalid_pointerid-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_setpointercapture_invalid_pointerid-manual.html
new file mode 100644
index 00000000000..4dbe858db16
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_setpointercapture_invalid_pointerid-manual.html
@@ -0,0 +1,65 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Pointer Event: gotPiontercapture is fired first.</title>
+ <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://www.w3.org/wiki/PointerEvents/TestAssertions">
+ <meta name="assert" content="When the setPointerCapture method is invoked, if the provided pointerId value does not match any of the active pointers, a DOMException with the name InvalidPointerId must be thrown." />
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <!-- /resources/testharness.js -->
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <!-- Additional helper script for common checks across event types -->
+ <script type="text/javascript" src="pointerevent_support.js"></script>
+ <script type="text/javascript">
+ var detected_pointertypes = {};
+ var test_pointerEvent = async_test("setPointerCapture: DOMException InvalidPointerId"); // set up test harness
+ // showPointerTypes is defined in pointerevent_support.js
+ // Requirements: the callback function will reference the test_pointerEvent object and
+ // will fail unless the async_test is created with the var name "test_pointerEvent".
+ add_completion_callback(showPointerTypes);
+
+ var INVALID_POINTERID = -39548;
+
+ function run() {
+ var target0 = document.getElementById("target0");
+ target0.style["touchAction"] = "none";
+ var listener = document.getElementById("complete-notice");
+
+ on_event(target0, "pointerdown", function (event) {
+ detected_pointertypes[event.pointerType] = true;
+
+ try {
+ listener.setPointerCapture(INVALID_POINTERID);
+
+ test_pointerEvent.step(function () {
+ assert_true(false, "DOMException: InvalidPointerId should have been thrown.");
+ });
+ } catch (e) {
+ test_pointerEvent.step(function () {
+ assert_equals(e.name, "InvalidPointerId", "DOMException should be InvalidPointerId");
+ });
+ }
+ test_pointerEvent.done(); // complete test
+ });
+ }
+ </script>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Event: DOMException InvalidPointerId</h1>
+ <h4>Test Description:
+ When the setPointerCapture method is invoked, if the provided pointerId value does not match any of the active pointers, a DOMException with the name InvalidPointerId must be thrown.
+ </h4>
+ <br />
+ <div id="target0">
+ Use the mouse, touch or pen to contact this box.
+ </div>
+ <div id="complete-notice">
+ <p>Test complete: Scroll to Summary to view Pass/Fail Results.</p>
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ <p>Refresh the page to run the tests again with a different pointer type.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_setpointercapture_relatedtarget-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_setpointercapture_relatedtarget-manual.html
new file mode 100644
index 00000000000..45b67414b26
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_setpointercapture_relatedtarget-manual.html
@@ -0,0 +1,101 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Set/Release capture + relatedTarget</title>
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ </head>
+ <body>
+ <h1>Pointer Events Capture Test - capture and relatedTarget</h1>
+ <h4>
+ Test Description: This test checks if setCapture/releaseCapture functions works properly. Complete the following actions:
+ <ol>
+ <li> Put your mouse over the lower rectangle. pointerover should be received for the purple rectangle
+ <li> Press and hold left mouse button over "Set Capture" button
+ <li> Put your mouse over the upper rectangle. pointerover should be received for the black rectangle
+ <li> Release left mouse button to complete the test.
+ </ol>
+ </h4>
+ Test passes if the proper behavior of the events is observed.
+
+ <div id="target0" style="background:black; color:white"></div>
+ <br>
+ <div id="target1" style="background:purple; color:white"></div>
+ <br>
+ <input type="button" id="btnCapture" value="Set Capture">
+ <script type='text/javascript'>
+ var isPointerCapture = false;
+ var isPointeroverGot = false;
+ var count=0;
+
+ var detected_pointertypes = {};
+ add_completion_callback(showPointerTypes);
+
+ var target0 = document.getElementById('target0');
+ var target1 = document.getElementById('target1');
+ var captureButton = document.getElementById('btnCapture');
+
+ setup({ explicit_done: true });
+
+ window.onload = function() {
+ on_event(captureButton, 'pointerdown', function(e) {
+ if(isPointerCapture == false) {
+ isPointerCapture = true;
+ sPointerCapture(e);
+ }
+ else {
+ isPointerCapture = false;
+ rPointerCapture(e);
+ }
+ });
+
+ on_event(target0, 'gotpointercapture', function(e) {
+ log("gotpointercapture", document.getElementById('target0'));
+ });
+
+ on_event(target0, 'lostpointercapture', function(e) {
+ log("lostpointercapture", document.getElementById('target0'));
+ isPointerCapture = false;
+ });
+
+ run();
+ }
+
+ function run() {
+ // After invoking the setPointerCapture method on an element, subsequent pointer events for the specified pointer must be targeted at that element.
+ // Additionally, the relatedTarget property of all such pointer events must be set to null.
+ // TA: 13.3
+ on_event(target0, "pointerover", function (event) {
+ log("pointerover", document.getElementById('target0'));
+ if(isPointerCapture && isPointeroverGot) {
+ test(function() {
+ assert_true(event.relatedTarget==null, "relatedTarget is null when the capture is set")
+ }, "relatedTarget is null when the capture is set. relatedTarget is " + event.relatedTarget);
+ done();
+ }
+ });
+
+ on_event(target1, "pointerover", function (event) {
+ detected_pointertypes[ event.pointerType ] = true;
+ if(!isPointeroverGot) {
+ test(function() {
+ assert_true(isPointerCapture==false, "pointerover shouldn't trigger for this target when capture is enabled");
+ }, "pointerover shouldn't trigger for the purple rectangle while the black rectangle has capture");
+ isPointeroverGot = true;
+ log("pointerover", document.getElementById('target1'));
+ }
+ });
+ }
+ </script>
+ <h1>Pointer Events Capture Test</h1>
+ <div id="complete-notice">
+ <p>Test complete: Scroll to Summary to view Pass/Fail Results.</p>
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ <p>Refresh the page to run the tests again with a different pointer type.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_styles.css b/tests/wpt/web-platform-tests/pointerevents/pointerevent_styles.css
new file mode 100644
index 00000000000..55265af4141
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_styles.css
@@ -0,0 +1,61 @@
+#target0 {
+background: black;
+color: white;
+white-space: nowrap;
+overflow-y: auto;
+overflow-x: auto;
+}
+
+#target1 {
+background: purple;
+color: white;
+white-space: nowrap;
+overflow-y: auto;
+overflow-x: auto;
+}
+
+.scroller {
+width: 700px;
+height: 430px;
+margin: 20px;
+overflow: auto;
+background: black;
+}
+
+.scroller > div {
+height: 1000px;
+width: 1000px;
+color: white;
+}
+
+.scroller > div div {
+height: 100%;
+width: 100%;
+color: white;
+}
+
+div {
+margin: 0em;
+padding: 2em;
+}
+
+#complete-notice {
+background: #afa;
+border: 1px solid #0a0;
+display: none;
+}
+
+#pointertype-log {
+font-weight: bold;
+}
+
+#listener {
+background: orange;
+border: 1px solid orange;
+position: absolute;
+top: -100px;
+}
+
+body.scrollable {
+min-height: 5000px;
+}
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_support.js b/tests/wpt/web-platform-tests/pointerevents/pointerevent_support.js
new file mode 100644
index 00000000000..b3fb661f8b7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_support.js
@@ -0,0 +1,170 @@
+var All_Pointer_Events = [
+ "pointerdown",
+ "pointerup",
+ "pointercancel",
+ "pointermove",
+ "pointerover",
+ "pointerout",
+ "pointerenter",
+ "pointerleave",
+ "gotpointercapture",
+ "lostpointercapture"];
+
+// Check for conformance to PointerEvent interface
+// TA: 1.1, 1.2, 1.6, 1.7, 1.8, 1.9, 1.10, 1.11, 1.12, 1.13
+function check_PointerEvent(event) {
+ test(function () {
+ assert_true(event instanceof PointerEvent, "event is a PointerEvent event");
+ }, event.type + " event is a PointerEvent event");
+
+
+ // Check attributes for conformance to WebIDL:
+ // * attribute exists
+ // * has proper type
+ // * if the attribute is "readonly", it cannot be changed
+ // TA: 1.1, 1.2
+ var idl_type_check = {
+ "long": function (v) { return typeof v === "number" && Math.round(v) === v; },
+ "float": function (v) { return typeof v === "number"; },
+ "string": function (v) { return typeof v === "string"; },
+ "boolean": function (v) { return typeof v === "boolean" }
+ };
+ [
+ ["readonly", "long", "pointerId"],
+ ["readonly", "float", "width"],
+ ["readonly", "float", "height"],
+ ["readonly", "float", "pressure"],
+ ["readonly", "long", "tiltX"],
+ ["readonly", "long", "tiltY"],
+ ["readonly", "string", "pointerType"],
+ ["readonly", "boolean", "isPrimary"]
+ ].forEach(function (attr) {
+ var readonly = attr[0];
+ var type = attr[1];
+ var name = attr[2];
+
+
+ // existence check
+ test(function () {
+ assert_true(name in event, name + " attribute in " + event.type + " event");
+ }, event.type + "." + name + " attribute exists");
+
+
+ // readonly check
+ if (readonly === "readonly") {
+ test(function () {
+ assert_readonly(event.type, name, event.type + "." + name + " cannot be changed");
+ }, event.type + "." + name + " is readonly");
+ }
+
+
+ // type check
+ test(function () {
+ assert_true(idl_type_check[type](event[name]), name + " attribute of type " + type);
+ }, event.type + "." + name + " IDL type " + type + " (JS type was " + typeof event[name] + ")");
+ });
+
+
+ // Check the pressure value
+ // TA: 1.6, 1.7, 1.8
+ test(function () {
+ // TA: 1.6
+ assert_greater_than_equal(event.pressure, 0, "pressure is greater than or equal to 0");
+ assert_less_than_equal(event.pressure, 1, "pressure is less than or equal to 1");
+
+
+ // TA: 1.7, 1.8
+ if (event.pointerType === "mouse") {
+ if (event.buttons === 0) {
+ assert_equals(event.pressure, 0, "pressure is 0 for mouse with no buttons pressed");
+ } else {
+ assert_equals(event.pressure, 0.5, "pressure is 0.5 for mouse with a button pressed");
+ }
+ }
+ }, event.type + ".pressure value is valid");
+
+
+ // Check mouse-specific properties
+ if (event.pointerType === "mouse") {
+ // TA: 1.9, 1.10, 1.13
+ test(function () {
+ assert_equals(event.tiltX, 0, event.type + ".tiltX is 0 for mouse");
+ assert_equals(event.tiltY, 0, event.type + ".tiltY is 0 for mouse");
+ assert_true(event.isPrimary, event.type + ".isPrimary is true for mouse");
+ }, event.type + " properties for pointerType = mouse");
+ // Check properties for pointers other than mouse
+ }
+}
+
+function showPointerTypes() {
+ var complete_notice = document.getElementById("complete-notice");
+ var pointertype_log = document.getElementById("pointertype-log");
+ var pointertypes = Object.keys(detected_pointertypes);
+ pointertype_log.innerHTML = pointertypes.length ?
+ pointertypes.join(",") : "(none)";
+ complete_notice.style.display = "block";
+}
+
+function log(msg, el) {
+ if (++count > 10){
+ count = 0;
+ el.innerHTML = ' ';
+ }
+ el.innerHTML = msg + '; ' + el.innerHTML;
+}
+
+ function failOnScroll() {
+ assert_true(false,
+ "scroll received while shouldn't");
+}
+
+function updateDescriptionNextStep() {
+ document.getElementById('desc').innerHTML = "Test Description: Try to scroll text RIGHT.";
+}
+
+function updateDescriptionComplete() {
+ document.getElementById('desc').innerHTML = "Test Description: Test complete";
+}
+
+function updateDescriptionSecondStepTouchActionElement(target, scrollReturnInterval) {
+ window.setTimeout(function() {
+ objectScroller(target, 'up', 0);}
+ , scrollReturnInterval);
+ document.getElementById('desc').innerHTML = "Test Description: Try to scroll element RIGHT moving your outside of the red border";
+}
+
+function updateDescriptionThirdStepTouchActionElement(target, scrollReturnInterval) {
+ window.setTimeout(function() {
+ objectScroller(target, 'left', 0);}
+ , scrollReturnInterval);
+ document.getElementById('desc').innerHTML = "Test Description: Try to scroll element DOWN then RIGHT starting your touch inside of the element. Then tap complete button";
+}
+
+function updateDescriptionFourthStepTouchActionElement(target, scrollReturnInterval) {
+ document.getElementById('desc').innerHTML = "Test Description: Try to scroll element RIGHT starting your touch inside of the element";
+}
+
+function objectScroller(target, direction, value) {
+ if (direction == 'up') {
+ target.scrollTop = 0;
+ } else if (direction == 'left') {
+ target.scrollLeft = 0;
+ }
+}
+
+function sPointerCapture(e) {
+ try {
+ target0.setPointerCapture(e.pointerId);
+ }
+ catch(e) {
+ }
+}
+
+function rPointerCapture(e) {
+ try {
+ captureButton.value = 'Set Capture';
+ target0.releasePointerCapture(e.pointerId);
+ }
+ catch(e) {
+ }
+} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-auto-css_touch-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-auto-css_touch-manual.html
new file mode 100644
index 00000000000..f5e9d12c353
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-auto-css_touch-manual.html
@@ -0,0 +1,129 @@
+<!doctype html>
+<html>
+ <head>
+ <title>touch-action: auto</title>
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ <style>
+ #target0 {
+ width: 700px;
+ height: 430px;
+ touch-action: auto;
+ }
+ </style>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Events touch-action attribute support</h1>
+ <h4 id="desc">Test Description: Try to scroll text DOWN. Wait for description update. Expected: pan enabled</h4>
+ <p>Note: this test is for touch-devices only</p>
+ <div id="target0">
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ </div>
+ <script type='text/javascript'>
+ var detected_pointertypes = {};
+
+ var xScrollIsReceived = false;
+ var yScrollIsReceived = false;
+ var xScr0, yScr0, xScr1, yScr1;
+
+ add_completion_callback(showPointerTypes);
+
+ function run() {
+ var target0 = document.getElementById("target0");
+
+ var test_touchaction = async_test("touch-action attribute test");
+
+ xScr0 = target0.scrollLeft;
+ yScr0 = target0.scrollTop;
+
+ on_event(target0, 'pointerdown', function(event) {
+ detected_pointertypes[event.pointerType] = true;
+ test_touchaction.step(function() {
+ assert_equals(event.pointerType, "touch", "wrong pointer type was detected: ");
+ });
+ });
+
+ on_event(target0, 'scroll', function(event) {
+ xScr1 = target0.scrollLeft;
+ yScr1 = target0.scrollTop;
+
+ if(xScr1 != xScr0) {
+ xScrollIsReceived = true;
+ }
+
+ if(yScr1 != yScr0) {
+ test_touchaction.step(function () {
+ yScrollIsReceived = true;
+ assert_true(true, "y-scroll received.");
+ });
+ updateDescriptionNextStep();
+ }
+
+ if(xScrollIsReceived && yScrollIsReceived) {
+ test_touchaction.done();
+ updateDescriptionComplete();
+ }
+ });
+ }
+ </script>
+ <h1>touch-action: auto</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-button-test_touch-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-button-test_touch-manual.html
new file mode 100644
index 00000000000..01a1c88c181
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-button-test_touch-manual.html
@@ -0,0 +1,109 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Button touch-action test</title>
+ <meta name="assert" content="TA15.11 -The touch-action CSS property applies to button elements.">
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ <style>
+ #target0 {
+ height: 150px;
+ width: 200px;
+ overflow-y: auto;
+ background: black;
+ padding: 100px;
+ position: relative;
+ }
+ button {
+ touch-action: none;
+ width: 350px;
+ height: 350px;
+ border: 2px solid red;
+ }
+ </style>
+ </head>
+ <body onload="run()">
+ <h2>Pointer Events touch-action attribute support</h2>
+ <h4 id="desc">Test Description: Try to scroll black element DOWN moving your touch outside of the red border. Wait for description update.</h4>
+ <p>Note: this test is for touch only</p>
+ <div id="target0">
+ <button>Test Button</button>
+ </div>
+ <br>
+ <input type="button" id="btnComplete" value="Complete test">
+
+ <script type='text/javascript'>
+ var detected_pointertypes = {};
+ var xScrollIsReceived = false;
+ var yScrollIsReceived = false;
+ var xScr0, yScr0, xScr1, yScr1;
+ var scrollReturnInterval = 1000;
+ var isFirstPart = true;
+ setup({ explicit_timeout: true });
+ add_completion_callback(showPointerTypes);
+
+ function run() {
+ var target0 = document.getElementById("target0");
+ var btnComplete = document.getElementById("btnComplete");
+
+ //TA 15.11
+ var test_touchaction_div = async_test("touch-action attribute test out of element");
+ var test_touchaction_button = async_test("touch-action attribute test in element");
+
+ xScr0 = target0.scrollLeft;
+ yScr0 = target0.scrollTop;
+
+ on_event(btnComplete, 'click', function(event) {
+ test_touchaction_button.step(function() {
+ assert_equals(target0.scrollLeft, 0, "button scroll x offset should be 0 in the end of the test");
+ assert_equals(target0.scrollTop, 0, "button scroll y offset should be 0 in the end of the test");
+ assert_true(xScrollIsReceived && yScrollIsReceived, "target0 x and y scroll offsets should be greater than 0 after first two interactions (outside red border) respectively");
+ });
+ test_touchaction_button.done();
+ updateDescriptionComplete();
+ });
+
+ on_event(btnComplete, 'pointerdown', function(event) {
+ detected_pointertypes[event.pointerType] = true;
+ });
+
+ on_event(target0, 'scroll', function(event) {
+ if(isFirstPart) {
+ xScr1 = target0.scrollLeft;
+ yScr1 = target0.scrollTop;
+
+ if(xScr1 != xScr0) {
+ xScrollIsReceived = true;
+ }
+
+ if(yScr1 != yScr0) {
+ test_touchaction_div.step(function () {
+ yScrollIsReceived = true;
+ });
+ updateDescriptionSecondStepTouchActionElement(target0, scrollReturnInterval);
+ }
+
+ if(xScrollIsReceived && yScrollIsReceived) {
+ test_touchaction_div.done();
+ updateDescriptionThirdStepTouchActionElement(target0, scrollReturnInterval);
+ setTimeout(function() {
+ isFirstPart = false;
+ }, 2 * scrollReturnInterval); // avoid immediate triggering while scroll is still being performed
+ }
+ }
+ else {
+ test_touchaction_button.step(failOnScroll, "scroll received while shouldn't");
+ }
+ });
+ }
+ </script>
+ <h1>touch-action: none</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-illegal.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-illegal.html
new file mode 100644
index 00000000000..5fe6179840e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-illegal.html
@@ -0,0 +1,67 @@
+<!doctype html>
+<html>
+ <head>
+ <title>touch-action: illegal</title>
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ <style>
+ #target0 {
+ width: 700px;
+ height: 50px;
+ touch-action: pan-x none;
+ }
+ #target1 {
+ width: 700px;
+ height: 50px;
+ background: black;
+ margin-top: 5px;
+ touch-action: pan-y none;
+ }
+ #target2 {
+ width: 700px;
+ height: 50px;
+ background: black;
+ margin-top: 5px;
+ touch-action: auto none;
+ }
+ </style>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Events touch-action attribute support</h1>
+ <h4 id="desc">Test Description: Test will automatically check behaviour of following combinations: 'pan-x none', 'pan-y none', 'auto none'</h4>
+ <div id="target0"></div>
+ <div id="target1"></div>
+ <div id="target2"></div>
+ <script type='text/javascript'>
+ var detected_pointertypes = {};
+
+ setup({ explicit_done: true });
+ add_completion_callback(showPointerTypes);
+
+ function run() {
+ var target0 = document.getElementById('target0');
+ var target1 = document.getElementById('target1');
+ var target2 = document.getElementById('target2');
+
+ test(function() {
+ assert_true(getComputedStyle(target0).touchAction == 'auto', "'pan-x none' is corrected properly");
+ }, "'pan-x none' is corrected properly");
+ test(function() {
+ assert_true(getComputedStyle(target1).touchAction == 'auto', "'pan-y none' is corrected properly");
+ }, "'pan-y none' is corrected properly");
+ test(function() {
+ assert_true(getComputedStyle(target2).touchAction == 'auto', "'auto none' is corrected properly");
+ }, "'auto none' is corrected properly");
+ done();
+ }
+ </script>
+ <h1>touch-action: none</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-inherit_child-auto-child-none_touch-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-inherit_child-auto-child-none_touch-manual.html
new file mode 100644
index 00000000000..364c9c11f6a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-inherit_child-auto-child-none_touch-manual.html
@@ -0,0 +1,117 @@
+<!doctype html>
+<html>
+ <head>
+ <title>touch-action: parent > child: auto > child: none</title>
+ <meta name="assert" content="TA15.5 - when a user touches an element, the effect of that touch is determined by the value of the touch-action property and the default touch behaviors on the element and its ancestors. Scrollable-Parent, Child: `auto`, Grand-Child: `none`">
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ <style>
+ .scroller > div {
+ touch-action: auto;
+ }
+ .scroller > div div {
+ touch-action: none;
+ }
+ </style>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Events touch-action attribute support</h1>
+ <h4 id="desc">Test Description: Try to scroll element DOWN then RIGHT. Tap Complete button under the rectangle when done. Expected: no panning.</h4>
+ <p>Note: this test is for touch-devices only</p>
+ <div class="scroller" id="target0">
+ <div>
+ <div>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ </div>
+ </div>
+ </div>
+ <input type="button" id="btnComplete" value="Complete test">
+ <script type='text/javascript'>
+ var detected_pointertypes = {};
+ add_completion_callback(showPointerTypes);
+
+ var test_touchaction = async_test("touch-action attribute test");
+
+ function run() {
+ var target0 = document.getElementById("target0");
+ var btnComplete = document.getElementById("btnComplete");
+
+ // Check if touch-action attribute works properly for embedded divs
+ // Scrollable-Parent, Child: `auto`, Grand-Child: `none`
+ // TA: 15.5
+ on_event(btnComplete, 'click', function(event) {
+ detected_pointertypes[event.pointerType] = true;
+ test_touchaction.step(function() {
+ assert_equals(target0.scrollLeft, 0, "scroll x offset should be 0 in the end of the test");
+ assert_equals(target0.scrollTop, 0, "scroll y offset should be 0 in the end of the test");
+ });
+ test_touchaction.done();
+ updateDescriptionComplete();
+ });
+
+ on_event(target0, 'scroll', function(event) {
+ test_touchaction.step(failOnScroll, "scroll received while touch-action is none");
+ });
+ }
+ </script>
+ <h1>behaviour: none</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-inherit_child-none_touch-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-inherit_child-none_touch-manual.html
new file mode 100644
index 00000000000..786819b8588
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-inherit_child-none_touch-manual.html
@@ -0,0 +1,112 @@
+<!doctype html>
+<html>
+ <head>
+ <title>touch-action: child: none</title>
+ <meta name="assert" content="TA15.9 - when a user touches an element, the effect of that touch is determined by the value of the touch-action property and the default touch behaviors on the element and its ancestors. Scrollable-Parent, Child: `none`">
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ <style>
+ .scroller > div {
+ touch-action: none;
+ }
+ </style>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Events touch-action attribute support</h1>
+ <h4 id="desc">Test Description: Try to scroll element DOWN then RIGHT. Tap Complete button under the rectangle when done. Expected: no panning</h4>
+ <p>Note: this test is for touch-devices only</p>
+ <div class="scroller" id="target0">
+ <div>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ </div>
+ </div>
+ <input type="button" id="btnComplete" value="Complete test">
+ <script type='text/javascript'>
+ var detected_pointertypes = {};
+ add_completion_callback(showPointerTypes);
+
+ var test_touchaction = async_test("touch-action attribute test");
+
+ function run() {
+ var target0 = document.getElementById("target0");
+ var btnComplete = document.getElementById("btnComplete");
+
+ // Check if touch-action attribute works properly for embedded divs
+ //
+ // TA: 15.9
+ on_event(btnComplete, 'click', function(event) {
+ detected_pointertypes[event.pointerType] = true;
+ test_touchaction.step(function() {
+ assert_equals(target0.scrollLeft, 0, "scroll x offset should be 0 in the end of the test");
+ assert_equals(target0.scrollTop, 0, "scroll y offset should be 0 in the end of the test");
+ });
+ test_touchaction.done();
+ updateDescriptionComplete();
+ });
+
+ on_event(target0, 'scroll', function(event) {
+ test_touchaction.step(failOnScroll, "scroll received while touch-action is none");
+ });
+ }
+ </script>
+ <h1>behaviour: none</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-x_touch-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-x_touch-manual.html
new file mode 100644
index 00000000000..09a97e3cbe2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-x_touch-manual.html
@@ -0,0 +1,112 @@
+<!doctype html>
+<html>
+ <head>
+ <title>touch-action: parent > child: pan-x > child: pan-x</title>
+ <meta name="assert" content="TA15.6 - when a user touches an element, the effect of that touch is determined by the value of the touch-action property and the default touch behaviors on the element and its ancestors. Scrollable-Parent, Child: `pan-x`, Grand-Child: `pan-x`">
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ <style>
+ .scroller > div {
+ touch-action: pan-x;
+ }
+ .scroller > div div {
+ touch-action: pan-x;
+ }
+ </style>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Events touch-action attribute support</h1>
+ <h4 id="desc">Test Description: Try to scroll element DOWN then RIGHT. Tap Complete button under the rectangle when done. Expected: only pans in x direction.</h4>
+ <p>Note: this test is for touch-devices only</p>
+ <div class="scroller" id="target0">
+ <div>
+ <div>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ </div>
+ </div>
+ </div>
+ <input type="button" id="btnComplete" value="Complete test">
+ <script type='text/javascript'>
+ var detected_pointertypes = {};
+ var test_touchaction = async_test("touch-action attribute test");
+ add_completion_callback(showPointerTypes);
+
+ function run() {
+ var target0 = document.getElementById("target0");
+ var btnComplete = document.getElementById("btnComplete");
+
+ // Check if touch-action attribute works properly for embedded divs
+ //
+ // TA: 15.6
+ on_event(btnComplete, 'click', function(event) {
+ detected_pointertypes[event.pointerType] = true;
+ test_touchaction.step(function() {
+ assert_not_equals(target0.scrollLeft, 0, "scroll x offset should not be 0 in the end of the test");
+ assert_equals(target0.scrollTop, 0, "scroll y offset should be 0 in the end of the test");
+ });
+ test_touchaction.done();
+ updateDescriptionComplete();
+ });
+ }
+ </script>
+ <h1>behaviour: pan-x</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-y_touch-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-y_touch-manual.html
new file mode 100644
index 00000000000..527e5537400
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-y_touch-manual.html
@@ -0,0 +1,117 @@
+<!doctype html>
+<html>
+ <head>
+ <title>touch-action: parent > child: pan-x > child: pan-y</title>
+ <meta name="assert" content="TA15.13 - Touch action inherits child 'pan-x' -> child 'pan-y' test">
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ <style>
+ .scroller > div {
+ touch-action: pan-x;
+ }
+ .scroller > div div {
+ touch-action: pan-y;
+ }
+ </style>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Events touch-action attribute support</h1>
+ <h4 id="desc">Test Description: Try to scroll element DOWN then RIGHT. Tap Complete button under the rectangle when done. Expected: no panning/zooming/etc.</h4>
+ <p>Note: this test is for touch-devices only</p>
+ <div class="scroller" id="target0">
+ <div>
+ <div>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ </div>
+ </div>
+ </div>
+ <input type="button" id="btnComplete" value="Complete test">
+ <script type='text/javascript'>
+ var detected_pointertypes = {};
+ add_completion_callback(showPointerTypes);
+
+ var test_touchaction = async_test("touch-action attribute test");
+
+ function run() {
+ var target0 = document.getElementById("target0");
+ var btnComplete = document.getElementById("btnComplete");
+
+ // Check if touch-action attribute works properly for embedded divs
+ // Scrollable-Parent, Child: `pan-x`, Grand-Child: `pan-y`
+ // TA: 15.13
+ on_event(btnComplete, 'click', function(event) {
+ detected_pointertypes[event.pointerType] = true;
+ test_touchaction.step(function() {
+ assert_equals(target0.scrollLeft, 0, "scroll x offset should be 0 in the end of the test");
+ assert_equals(target0.scrollTop, 0, "scroll y offset should be 0 in the end of the test");
+ });
+ test_touchaction.done();
+ updateDescriptionComplete();
+ });
+
+ on_event(target0, 'scroll', function(event) {
+ test_touchaction.step(failOnScroll, "scroll received while touch-action is none");
+ });
+ }
+ </script>
+ <h1>behaviour: none</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-inherit_highest-parent-none_touch-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-inherit_highest-parent-none_touch-manual.html
new file mode 100644
index 00000000000..b13013c4376
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-inherit_highest-parent-none_touch-manual.html
@@ -0,0 +1,133 @@
+<!doctype html>
+<html>
+ <head>
+ <title>touch-action: parent: none + two embedded children</title>
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ <style>
+ #divParent {
+ touch-action: none;
+ }
+ </style>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Events touch-action attribute support</h1>
+ <h4 id="desc">Test Description: Try to scroll text DOWN. Wait for description update. Expected: pan enabled</h4>
+ <p>Note: this test is for touch-devices only</p>
+ <div id="divParent">
+ <div class="scroller" id="target0">
+ <div>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ </div>
+ </div>
+ </div>
+ <script type='text/javascript'>
+ var detected_pointertypes = {};
+
+ var xScrollIsReceived = false;
+ var yScrollIsReceived = false;
+ var xScr0, yScr0, xScr1, yScr1;
+
+ add_completion_callback(showPointerTypes);
+ add_completion_callback(enableScrolling);
+
+ function run() {
+ var target0 = document.getElementById("target0");
+
+ var test_touchaction = async_test("touch-action attribute test");
+
+ xScr0 = target0.scrollLeft;
+ yScr0 = target0.scrollTop;
+
+ on_event(target0, 'pointerdown', function(event) {
+ detected_pointertypes[event.pointerType] = true;
+ });
+
+ // Check if touch-action attribute works properly for embedded divs
+ //
+ // TA: 15.
+ on_event(target0, 'scroll', function(event) {
+ xScr1 = target0.scrollLeft;
+ yScr1 = target0.scrollTop;
+
+ if(xScr1 != xScr0) {
+ xScrollIsReceived = true;
+ }
+
+ if(yScr1 != yScr0) {
+ yScrollIsReceived = true;
+ updateDescriptionNextStep();
+ }
+
+ if(xScrollIsReceived && yScrollIsReceived) {
+ test_touchaction.done();
+ updateDescriptionComplete();
+ }
+ });
+ }
+
+ function enableScrolling() {
+ document.getElementById('divParent').setAttribute('style', 'touch-action: auto');
+ }
+ </script>
+ <h1>behaviour: auto</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-inherit_parent-none_touch-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-inherit_parent-none_touch-manual.html
new file mode 100644
index 00000000000..163ef9b8ef4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-inherit_parent-none_touch-manual.html
@@ -0,0 +1,112 @@
+<!doctype html>
+<html>
+ <head>
+ <title>touch-action: inherit from parent: none</title>
+ <meta name="assert" content="TA15.8 - when a user touches an element, the effect of that touch is determined by the value of the touch-action property and the default touch behaviors on the element and its ancestors. Scrollable-Parent: `none` Child: `auto`">
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ <style>
+ .scroller {
+ touch-action: none;
+ }
+ </style>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Events touch-action attribute support</h1>
+ <h4 id="desc">Test Description: Try to scroll element DOWN then RIGHT. Tap Complete button under the rectangle when done. Expected: no panning</h4>
+ <p>Note: this test is for touch-devices only</p>
+ <div class="scroller" id="target0">
+ <div>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ </div>
+ </div>
+ <input type="button" id="btnComplete" value="Complete test">
+ <script type='text/javascript'>
+ var detected_pointertypes = {};
+ add_completion_callback(showPointerTypes);
+
+ var test_touchaction = async_test("touch-action attribute test");
+
+ function run() {
+ var target0 = document.getElementById("target0");
+ var btnComplete = document.getElementById("btnComplete");
+
+ // Check if touch-action attribute works properly for embedded divs
+ //
+ // TA: 15.8
+ on_event(btnComplete, 'click', function(event) {
+ detected_pointertypes[event.pointerType] = true;
+ test_touchaction.step(function() {
+ assert_equals(target0.scrollLeft, 0, "scroll x offset should be 0 in the end of the test");
+ assert_equals(target0.scrollTop, 0, "scroll y offset should be 0 in the end of the test");
+ });
+ test_touchaction.done();
+ updateDescriptionComplete();
+ });
+
+ on_event(target0, 'scroll', function(event) {
+ test_touchaction.step(failOnScroll, "scroll received while touch-action is none");
+ });
+ }
+ </script>
+ <h1>behaviour: none</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-keyboard-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-keyboard-manual.html
new file mode 100644
index 00000000000..3fef3f646f7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-keyboard-manual.html
@@ -0,0 +1,124 @@
+<!doctype html>
+<html>
+ <head>
+ <title>touch-action: keyboard</title>
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ <style>
+ #target0 {
+ width: 700px;
+ height: 430px;
+ touch-action: none;
+ }
+ </style>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Events touch-action attribute support</h1>
+ <h4 id="desc">Test Description: Press DOWN ARROW key. Wait for description update. Expected: pan enabled</h4>
+ <p>Note: this test is for keyboard only</p>
+ <div id="target0">
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ </div>
+ <script type='text/javascript'>
+
+ var xScrollIsReceived = false;
+ var yScrollIsReceived = false;
+ var xScr0, yScr0, xScr1, yScr1;
+
+ function run() {
+ var target0 = document.getElementById("target0");
+
+ var test_touchaction = async_test("touch-action attribute test");
+
+ xScr0 = target0.scrollLeft;
+ yScr0 = target0.scrollTop;
+
+ target0.focus();
+
+ on_event(target0, 'scroll', function(event) {
+ xScr1 = target0.scrollLeft;
+ yScr1 = target0.scrollTop;
+
+ if(xScr1 != xScr0) {
+ xScrollIsReceived = true;
+ }
+
+ if(yScr1 != yScr0) {
+ test_touchaction.step(function () {
+ yScrollIsReceived = true;
+ assert_true(true, "y-scroll received.");
+ });
+ updateDescriptionNextStepKeyboard();
+ }
+
+ if(xScrollIsReceived && yScrollIsReceived) {
+ test_touchaction.done();
+ updateDescriptionComplete();
+ }
+ });
+ }
+
+ function updateDescriptionNextStepKeyboard() {
+ document.getElementById('desc').innerHTML = "Test Description: press RIGHT ARROW key.";
+ }
+ </script>
+ <h1>touch-action: none</h1>
+ <div id="complete-notice">
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-mouse-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-mouse-manual.html
new file mode 100644
index 00000000000..fcc8584515c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-mouse-manual.html
@@ -0,0 +1,130 @@
+<!doctype html>
+<html>
+ <head>
+ <title>touch-action: mouse</title>
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ <style>
+ #target0 {
+ width: 700px;
+ height: 430px;
+ touch-action: none;
+ }
+ </style>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Events touch-action attribute support</h1>
+ <h4 id="desc">Test Description: Try to scroll text down using mouse (use mouse wheel or click on the scrollbar). Wait for description update.</h4>
+ <p>Note: this test is for mouse only</p>
+ <div id="target0">
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ </div>
+ <script type='text/javascript'>
+ var detected_pointertypes = {};
+
+ var xScrollIsReceived = false;
+ var yScrollIsReceived = false;
+ var xScr0, yScr0, xScr1, yScr1;
+
+ add_completion_callback(showPointerTypes);
+
+ function run() {
+ var target0 = document.getElementById("target0");
+
+ var test_touchaction = async_test("touch-action attribute test");
+
+ xScr0 = target0.scrollLeft;
+ yScr0 = target0.scrollTop;
+
+ on_event(target0, 'pointerdown', function(event) {
+ detected_pointertypes[event.pointerType] = true;
+ });
+
+ on_event(target0, 'scroll', function(event) {
+ xScr1 = target0.scrollLeft;
+ yScr1 = target0.scrollTop;
+
+ if(xScr1 != xScr0) {
+ xScrollIsReceived = true;
+ }
+
+ if(yScr1 != yScr0) {
+ test_touchaction.step(function () {
+ yScrollIsReceived = true;
+ assert_true(true, "y-scroll received.");
+ });
+ updateDescriptionNextStepMouse();
+ }
+
+ if(xScrollIsReceived && yScrollIsReceived) {
+ test_touchaction.done();
+ updateDescriptionComplete();
+ }
+ });
+ }
+
+ function updateDescriptionNextStepMouse() {
+ document.getElementById('desc').innerHTML = "Test Description: Try to scroll text right using mouse (use mouse wheel or click on the scrollbar).";
+ }
+ </script>
+ <h1>touch-action: none</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-none-css_touch-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-none-css_touch-manual.html
new file mode 100644
index 00000000000..dec694f3eca
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-none-css_touch-manual.html
@@ -0,0 +1,111 @@
+<!doctype html>
+<html>
+ <head>
+ <title>touch-action: none</title>
+ <meta name="assert" content="TA15.2 - With `touch-action: none` on a swiped or click/dragged element, `pointerdown+(optional pointermove)+pointerup` must be dispatched.">
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ <style>
+ #target0 {
+ width: 700px;
+ height: 430px;
+ touch-action: none;
+ }
+ </style>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Events touch-action attribute support</h1>
+ <h4 id="desc">Test Description: Try to scroll element DOWN then RIGHT. Tap Complete button under the rectangle when done. Expected: no panning/zooming/etc.</h4>
+ <p>Note: this test is for touch-devices only</p>
+ <div id="target0">
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ </div>
+ <input type="button" id="btnComplete" value="Complete test">
+ <script type='text/javascript'>
+ var detected_pointertypes = {};
+
+ var test_touchaction = async_test("touch-action attribute test");
+ add_completion_callback(showPointerTypes);
+
+ function run() {
+ var target0 = document.getElementById("target0");
+ var btnComplete = document.getElementById("btnComplete");
+
+ // Check if "touch-action: none" attribute works properly
+ //TA: 15.2
+ on_event(btnComplete, 'click', function(event) {
+ detected_pointertypes[event.pointerType] = true;
+ test_touchaction.step(function() {
+ assert_equals(target0.scrollLeft, 0, "scroll x offset should be 0 in the end of the test");
+ assert_equals(target0.scrollTop, 0, "scroll y offset should be 0 in the end of the test");
+ });
+ test_touchaction.done();
+ updateDescriptionComplete();
+ });
+
+ on_event(target0, 'scroll', function(event) {
+ test_touchaction.step(failOnScroll, "scroll received while touch-action is none");
+ });
+ }
+ </script>
+ <h1>touch-action: none</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-pan-x-css_touch-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-pan-x-css_touch-manual.html
new file mode 100644
index 00000000000..e757baec6be
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-pan-x-css_touch-manual.html
@@ -0,0 +1,106 @@
+<!doctype html>
+<html>
+ <head>
+ <title>touch-action: pan-x</title>
+ <meta name="assert" content="TA15.3 - With `touch-action: pan-x` on a swiped or click/dragged element, only panning on the x-axis should be possible.">
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ <style>
+ #target0 {
+ width: 700px;
+ height: 430px;
+ touch-action: pan-x;
+ }
+ </style>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Events touch-action attribute support</h1>
+ <h4 id="desc">Test Description: Try to scroll element DOWN then RIGHT. Tap Complete button under the rectangle when done. Expected: only pans in x direction.</h4>
+ <p>Note: this test is for touch-devices only</p>
+ <div id="target0">
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ </div>
+ <input type="button" id="btnComplete" value="Complete test">
+ <script type='text/javascript'>
+ var detected_pointertypes = {};
+ var test_touchaction = async_test("touch-action attribute test");
+ add_completion_callback(showPointerTypes);
+
+ function run() {
+ var target0 = document.getElementById("target0");
+ var btnComplete = document.getElementById("btnComplete");
+
+ // Check if "touch-action: pan-x" attribute works properly
+ //TA: 15.3
+ on_event(btnComplete, 'click', function(event) {
+ detected_pointertypes[event.pointerType] = true;
+ test_touchaction.step(function() {
+ assert_not_equals(target0.scrollLeft, 0, "scroll x offset should not be 0 in the end of the test");
+ assert_equals(target0.scrollTop, 0, "scroll y offset should be 0 in the end of the test");
+ });
+ test_touchaction.done();
+ updateDescriptionComplete();
+ });
+ }
+ </script>
+ <h1>touch-action: pan-x</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-pan-x-pan-y-pan-y_touch-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-pan-x-pan-y-pan-y_touch-manual.html
new file mode 100644
index 00000000000..e89b8b742e9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-pan-x-pan-y-pan-y_touch-manual.html
@@ -0,0 +1,111 @@
+<!doctype html>
+<html>
+ <head>
+ <title>touch-action: parent > child: pan-x pan-y > child: pan-y</title>
+ <meta name="assert" content="TA15.17 - Touch action 'pan-x pan-y' 'pan-y' test">
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ <style>
+ .scroller > div {
+ touch-action: pan-x pan-y;
+ }
+ .scroller > div div {
+ touch-action: pan-y;
+ }
+ </style>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Events touch-action attribute support</h1>
+ <h4 id="desc">Test Description: Try to scroll element DOWN then RIGHT. Tap Complete button under the rectangle when done. Expected: only pans in y direction.</h4>
+ <p>Note: this test is for touch-devices only</p>
+ <div class="scroller" id="target0">
+ <div>
+ <div>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ </div>
+ </div>
+ </div>
+ <input type="button" id="btnComplete" value="Complete test">
+ <script type='text/javascript'>
+ var detected_pointertypes = {};
+ add_completion_callback(showPointerTypes);
+
+ var test_touchaction = async_test("touch-action attribute test");
+
+ function run() {
+ var target0 = document.getElementById("target0");
+ var btnComplete = document.getElementById("btnComplete");
+
+ // Check if touch-action attribute works properly for embedded divs
+ //
+ // TA: 15.17
+ on_event(btnComplete, 'click', function(event) {
+ detected_pointertypes[event.pointerType] = true;
+ test_touchaction.step(function() {
+ assert_equals(target0.scrollLeft, 0, "scroll x offset should be 0 in the end of the test");
+ assert_not_equals(target0.scrollTop, 0, "scroll y offset should not be 0 in the end of the test");
+ });
+ test_touchaction.done();
+ updateDescriptionComplete();
+ });
+ }
+ </script>
+ <h1>behaviour: pan-y</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-pan-x-pan-y_touch-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-pan-x-pan-y_touch-manual.html
new file mode 100644
index 00000000000..0c900ff7407
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-pan-x-pan-y_touch-manual.html
@@ -0,0 +1,126 @@
+<!doctype html>
+<html>
+ <head>
+ <title>touch-action: pan-x pan-y</title>
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ <style>
+ #target0 {
+ width: 700px;
+ height: 430px;
+ touch-action: pan-x pan-y;
+ }
+ </style>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Events touch-action attribute support</h1>
+ <h4 id="desc">Test Description: Try to scroll text DOWN. Wait for description update. Expected: pan enabled</h4>
+ <p>Note: this test is for touch-devices only</p>
+ <div id="target0">
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ </div>
+ <script type='text/javascript'>
+ var detected_pointertypes = {};
+
+ var xScrollIsReceived = false;
+ var yScrollIsReceived = false;
+ var xScr0, yScr0, xScr1, yScr1;
+
+ add_completion_callback(showPointerTypes);
+
+ function run() {
+ var target0 = document.getElementById("target0");
+
+ var test_touchaction = async_test("touch-action attribute test");
+
+ xScr0 = target0.scrollLeft;
+ yScr0 = target0.scrollTop;
+
+ on_event(target0, 'pointerdown', function(event) {
+ detected_pointertypes[event.pointerType] = true;
+ });
+
+ on_event(target0, 'scroll', function(event) {
+ xScr1 = target0.scrollLeft;
+ yScr1 = target0.scrollTop;
+
+ if(xScr1 != xScr0) {
+ xScrollIsReceived = true;
+ }
+
+ if(yScr1 != yScr0) {
+ test_touchaction.step(function () {
+ yScrollIsReceived = true;
+ assert_true(true, "y-scroll received.");
+ });
+ updateDescriptionNextStep();
+ }
+
+ if(xScrollIsReceived && yScrollIsReceived) {
+ test_touchaction.done();
+ updateDescriptionComplete();
+ }
+ });
+ }
+ </script>
+ <h1>touch-action: pan-x pan-y</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-pan-y-css_touch-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-pan-y-css_touch-manual.html
new file mode 100644
index 00000000000..4ad39ecc838
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-pan-y-css_touch-manual.html
@@ -0,0 +1,106 @@
+<!doctype html>
+<html>
+ <head>
+ <title>touch-action: pan-y</title>
+ <meta name="assert" content="TA15.4 - With `touch-action: pan-y` on a swiped or click/dragged element, only panning in the y-axis should be possible.">
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ <style>
+ #target0 {
+ width: 700px;
+ height: 430px;
+ touch-action: pan-y;
+ }
+ </style>
+ </head>
+ <body onload="run()">
+ <h1>Pointer Events touch-action attribute support</h1>
+ <h4 id="desc">Test Description: Try to scroll element DOWN then RIGHT. Tap Complete button under the rectangle when done. Expected: only pans in y direction.</h4>
+ <p>Note: this test is for touch-devices only</p>
+ <div id="target0">
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
+ nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
+ Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
+ lobortis nisl ut aliquip ex ea commodo consequat.
+ </p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ <p>Lorem ipsum dolor sit amet...</p>
+ </div>
+ <input type="button" id="btnComplete" value="Complete test">
+ <script type='text/javascript'>
+ var detected_pointertypes = {};
+ var test_touchaction = async_test("touch-action attribute test");
+ add_completion_callback(showPointerTypes);
+
+ function run() {
+ var target0 = document.getElementById("target0");
+ var btnComplete = document.getElementById("btnComplete");
+
+ // Check if "touch-action: pan-y" attribute works properly
+ //TA: 15.4
+ on_event(btnComplete, 'click', function(event) {
+ detected_pointertypes[event.pointerType] = true;
+ test_touchaction.step(function() {
+ assert_equals(target0.scrollLeft, 0, "scroll x offset should be 0 in the end of the test");
+ assert_not_equals(target0.scrollTop, 0, "scroll y offset should not be 0 in the end of the test");
+ });
+ test_touchaction.done();
+ updateDescriptionComplete();
+ });
+ }
+ </script>
+ <h1>touch-action: pan-y</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-span-test_touch-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-span-test_touch-manual.html
new file mode 100644
index 00000000000..41635e0bf94
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-span-test_touch-manual.html
@@ -0,0 +1,113 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Span touch-action test</title>
+ <meta name="assert" content="TA15.18 - The touch-action CSS property applies to all elements except non-replaced inline elements."
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ <style>
+ #target0 {
+ height: 150px;
+ width: 200px;
+ overflow-y: auto;
+ background: black;
+ padding: 100px;
+ position: relative;
+ }
+ #testspan {
+ touch-action: none;
+ font-size: 72pt;
+ padding: 0px 0px 180px 0px;
+ border: 2px solid red;
+ }
+ </style>
+ </head>
+ <body onload="run()">
+ <h2>Pointer Events touch-action attribute support</h2>
+ <h4 id="desc">Test Description: Try to scroll black element DOWN moving your touch outside of the red border. Wait for description update.</h4>
+ <p>Note: this test is for touch only</p>
+ <div id="target0">
+ <span id="testspan">
+ Test span
+ </span>
+ </div>
+ <input type="button" id="btnComplete" value="Complete test">
+
+ <script type='text/javascript'>
+ var detected_pointertypes = {};
+
+ var xScrollIsReceived = false;
+ var yScrollIsReceived = false;
+ var failScrollIsReceived = false;
+ var xScr0, yScr0, xScr1, yScr1;
+ var scrollReturnInterval = 500;
+ var isFirstPart = true;
+ setup({ explicit_timeout: true });
+ add_completion_callback(showPointerTypes);
+
+ function run() {
+ var target0 = document.getElementById("target0");
+ var btnComplete = document.getElementById("btnComplete");
+
+ //TA 15.18
+ var test_touchaction_div = async_test("touch-action attribute test out of element");
+ var test_touchaction_span = async_test("touch-action attribute test in element");
+
+ xScr0 = target0.scrollLeft;
+ yScr0 = target0.scrollTop;
+
+ on_event(btnComplete, 'click', function(event) {
+ test_touchaction_span.step(function() {
+ assert_not_equals(target0.scrollLeft, 0, "span scroll x offset should not be 0 in the end of the test");
+ assert_not_equals(target0.scrollTop, 0, "span scroll y offset should not be 0 in the end of the test");
+ assert_true(!isFirstPart, "target0 x and y scroll offsets should be greater than 0 after first two interactions (outside red border) respectively");
+ });
+ test_touchaction_span.done();
+ updateDescriptionComplete();
+ });
+
+ on_event(btnComplete, 'pointerdown', function(event) {
+ detected_pointertypes[event.pointerType] = true;
+ });
+
+ on_event(target0, 'scroll', function(event) {
+ if(isFirstPart) {
+ xScr1 = target0.scrollLeft;
+ yScr1 = target0.scrollTop;
+
+ if(xScr1 != xScr0) {
+ xScrollIsReceived = true;
+ }
+
+ if(yScr1 != yScr0) {
+ test_touchaction_div.step(function () {
+ yScrollIsReceived = true;
+ });
+ updateDescriptionSecondStepTouchActionElement(target0, scrollReturnInterval);
+ }
+
+ if(xScrollIsReceived && yScrollIsReceived) {
+ test_touchaction_div.done();
+ updateDescriptionThirdStepTouchActionElement(target0, scrollReturnInterval);
+ setTimeout(function() {
+ isFirstPart = false;
+ xScr0 = target0.scrollLeft;
+ xScr0 = target0.scrollLeft;
+ xScrollIsReceived = false;
+ yScrollIsReceived = false;
+ }, 2 * scrollReturnInterval); // avoid immediate triggering while scroll is still being performed
+ }
+ }
+ });
+ }
+ </script>
+ <h1>touch-action: none</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-svg-test_touch-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-svg-test_touch-manual.html
new file mode 100644
index 00000000000..6c9c0b3f68c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-svg-test_touch-manual.html
@@ -0,0 +1,122 @@
+<!doctype html>
+<html>
+ <head>
+ <title>SVG test</title>
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ <style>
+ #target0 {
+ height: 350px;
+ width: 300px;
+ overflow-y: auto;
+ background: black;
+ padding: 100px;
+ position: relative;
+ }
+ </style>
+ </head>
+ <body onload="run()">
+ <h2>Pointer Events touch-action attribute support</h2>
+ <h4 id="desc">Test Description: Try to scroll black element DOWN moving your touch outside of the red border. Wait for description update.</h4>
+ <p>Note: this test is for touch only</p>
+ <div id="target0">
+ <svg width="555" height="555" style="touch-action: none; border: 4px double red;">
+ <circle cx="305" cy="305" r="250" stroke="green" stroke-width="4" fill="yellow" />
+ Sorry, your browser does not support inline SVG.
+ </svg>
+ </div>
+ <br>
+ <input type="button" id="btnComplete" value="Complete test">
+ <script type='text/javascript'>
+ var detected_pointertypes = {};
+ var xScrollIsReceived = false;
+ var yScrollIsReceived = false;
+ var xScr0, yScr0, xScr1, yScr1;
+ var scrollReturnInterval = 1000;
+ var isFirstPart = true;
+ setup({ explicit_timeout: true });
+ add_completion_callback(showPointerTypes);
+
+ function run() {
+ var target0 = document.getElementById("target0");
+ var btnComplete = document.getElementById("btnComplete");
+
+ var test_touchaction_div = async_test("touch-action attribute test out of SVG");
+ var test_touchaction_svg = async_test("touch-action attribute test in SVG");
+
+ xScr0 = target0.scrollLeft;
+ yScr0 = target0.scrollTop;
+
+ on_event(btnComplete, 'click', function(event) {
+ test_touchaction_svg.step(function() {
+ assert_equals(target0.scrollLeft, 0, "SVG scroll x offset should be 0 in the end of the test");
+ assert_equals(target0.scrollTop, 0, "SVG scroll y offset should be 0 in the end of the test");
+ });
+ test_touchaction_svg.done();
+ updateDescriptionComplete();
+ });
+
+ on_event(btnComplete, 'pointerdown', function(event) {
+ detected_pointertypes[event.pointerType] = true;
+ });
+
+ on_event(target0, 'scroll', function(event) {
+ if(isFirstPart) {
+ xScr1 = target0.scrollLeft;
+ yScr1 = target0.scrollTop;
+
+ if(xScr1 != xScr0) {
+ xScrollIsReceived = true;
+ }
+
+ if(yScr1 != yScr0) {
+ test_touchaction_div.step(function () {
+ yScrollIsReceived = true;
+ assert_true(true, "y-scroll received.");
+ });
+ updateDescriptionSecondStepSVG();
+ }
+
+ if(xScrollIsReceived && yScrollIsReceived) {
+ test_touchaction_div.done();
+ updateDescriptionThirdStepSVG();
+ setTimeout(function() {
+ isFirstPart = false;
+ }, 2 * scrollReturnInterval);
+ }
+ }
+ });
+ }
+
+ function updateDescriptionSecondStepSVG() {
+ window.setTimeout(function() {
+ objectScroller(target0, 'up', 0);}
+ , scrollReturnInterval);
+ document.getElementById('desc').innerHTML = "Test Description: Try to scroll element RIGHT moving your touch outside of the red border";
+ }
+
+ function updateDescriptionThirdStepSVG() {
+ window.setTimeout(function() {
+ objectScroller(target0, 'left', 0);}
+ , scrollReturnInterval);
+ document.getElementById('desc').innerHTML = "Test Description: Try to scroll element DOWN then RIGHT starting your touch inside of the circle. Tap Complete button under the rectangle when done";
+ }
+
+ function objectScroller(target, direction, value) {
+ if (direction == 'up') {
+ target.scrollTop = 0;
+ } else if (direction == 'left') {
+ target.scrollLeft = 0;
+ }
+ }
+ </script>
+ <h1>touch-action: none</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-table-test_touch-manual.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-table-test_touch-manual.html
new file mode 100644
index 00000000000..fcc3a3e7cad
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-table-test_touch-manual.html
@@ -0,0 +1,141 @@
+<!doctype html>
+<html>
+ <head>
+ <title>Table touch-action test</title>
+ <meta name="assert" content="TA15.19 The touch-action CSS property applies to all elements except table rows, row groups, table columns, and column groups.">
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ <style>
+ #target0 {
+ height: 150px;
+ width: 200px;
+ overflow-y: auto;
+ background: black;
+ padding: 100px;
+ position: relative;
+ }
+ #testtable{
+ color: white;
+ width: 350px;
+ padding: 0px 0px 200px 0px;
+ border: 2px solid green;
+ }
+ .testtd, .testth {
+ border: 2px solid green;
+ height: 80px;
+ }
+ #row1 {
+ touch-action: none;
+ }
+ #cell3 {
+ touch-action: none;
+ }
+ </style>
+ </head>
+ <body onload="run()">
+ <h2>Pointer Events touch-action attribute support</h2>
+ <h4 id="desc">Test Description: Try to scroll element DOWN starting your touch over the 1st Row. Wait for description update.</h4>
+ <p>Note: this test is for touch only</p>
+ <div id="target0">
+ <table id="testtable">
+ <caption>The caption, first row element, and cell 3 have touch-action: none.</caption>
+ <tr id="row1"><th class="testth">Header 1 <td class="testtd">Cell 1 <td class="testtd">Cell 2</tr>
+ <tr id="row2"><th class="testth">Header 2 <td id="cell3" class="testtd">Cell 3 <td class="testtd">Cell 4</tr>
+ <tr id="row3"> <th class="testth">Header 3 <td class="testtd">Cell 5 <td class="testtd"> Cell 6</tr>
+ </table>
+ </div>
+ <br>
+ <input type="button" id="btnComplete" value="Complete test">
+
+ <script type='text/javascript'>
+ var detected_pointertypes = {};
+ var xScrollIsReceived = false;
+ var yScrollIsReceived = false;
+ var xScr0, yScr0, xScr1, yScr1;
+ var scrollReturnInterval = 1000;
+ var isFirstPart = true;
+ setup({ explicit_timeout: true });
+ add_completion_callback(showPointerTypes);
+
+ function run() {
+ var target0 = document.getElementById("target0");
+ var btnComplete = document.getElementById("btnComplete");
+
+ //TA 15.19
+ var test_touchaction_cell = async_test("touch-action attribute test on the cell");
+ var test_touchaction_row = async_test("touch-action attribute test on the row");
+
+ xScr0 = target0.scrollLeft;
+ yScr0 = target0.scrollTop;
+
+ on_event(btnComplete, 'click', function(event) {
+ test_touchaction_cell.step(function() {
+ assert_equals(target0.scrollLeft, 0, "table scroll x offset should be 0 in the end of the test");
+ assert_equals(target0.scrollTop, 0, "table scroll y offset should be 0 in the end of the test");
+ assert_true(xScrollIsReceived && yScrollIsReceived, "target0 x and y scroll offsets should be greater than 0 after first two interactions (outside red border) respectively");
+ });
+ test_touchaction_cell.done();
+ updateDescriptionComplete();
+ });
+
+ on_event(btnComplete, 'pointerdown', function(event) {
+ detected_pointertypes[event.pointerType] = true;
+ });
+
+ on_event(target0, 'scroll', function(event) {
+ if(isFirstPart) {
+ xScr1 = target0.scrollLeft;
+ yScr1 = target0.scrollTop;
+
+ if(xScr1 != xScr0) {
+ xScrollIsReceived = true;
+ }
+
+ if(yScr1 != yScr0) {
+ test_touchaction_row.step(function () {
+ yScrollIsReceived = true;
+ });
+ updateDescriptionSecondStepTable(target0, scrollReturnInterval);
+ }
+
+ if(xScrollIsReceived && yScrollIsReceived) {
+ test_touchaction_row.done();
+ updateDescriptionThirdStepTable(target0, scrollReturnInterval);
+ setTimeout(function() {
+ isFirstPart = false;
+ }, 2 * scrollReturnInterval); // avoid immediate triggering while scroll is still being performed
+ }
+ }
+ else {
+ test_touchaction_cell.step(failOnScroll, "scroll received while shouldn't");
+ }
+ });
+ }
+
+ function updateDescriptionSecondStepTable(target, scrollReturnInterval, element) {
+ window.setTimeout(function() {
+ objectScroller(target, 'up', 0);
+ }
+ , scrollReturnInterval);
+ document.getElementById('desc').innerHTML = "Test Description: Try to scroll element RIGHT staring your touch over the Row 1";
+ }
+
+ function updateDescriptionThirdStepTable(target, scrollReturnInterval) {
+ window.setTimeout(function() {
+ objectScroller(target, 'left', 0);
+ }
+ , scrollReturnInterval);
+ document.getElementById('desc').innerHTML = "Test Description: Try to scroll element DOWN then RIGHT starting your touch inside of the Cell 3";
+ }
+
+ </script>
+ <h1>touch-action: none</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-verification.html b/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-verification.html
new file mode 100644
index 00000000000..2e694229a21
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerevents/pointerevent_touch-action-verification.html
@@ -0,0 +1,101 @@
+<!doctype html>
+<html>
+ <head>
+ <title>touch-action: basic verification</title>
+ <meta name="assert" content="TA15.20 - The touch-action CSS property determines whether touch input MAY trigger default behavior supplied by the user agent.
+ auto: The user agent MAY determine any permitted touch behaviors, such as panning and zooming manipulations of the viewport, for touches that begin on the element.
+ none: Touches that begin on the element MUST NOT trigger default touch behaviors.
+ pan-x: The user agent MAY consider touches that begin on the element only for the purposes of horizontally scrolling the element's nearest ancestor with horizontally scrollable content.
+ pan-y: The user agent MAY consider touches that begin on the element only for the purposes of vertically scrolling the element's nearest ancestor with vertically scrollable content.
+ manipulation: The user agent MAY consider touches that begin on the element only for the purposes of scrolling and continuous zooming. Any additional behaviors supported by auto are out of scope for this specification.">
+ <meta name="viewport" content="width=device-width">
+ <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="pointerevent_support.js"></script>
+ <style>
+ #target0 {
+ width: 700px;
+ height: 20px;
+ touch-action: auto;
+ }
+ #target1 {
+ width: 700px;
+ height: 20px;
+ touch-action: none;
+ background: black;
+ margin-top: 5px;
+ touch-action: pan-x;
+ }
+ #target2 {
+ width: 700px;
+ height: 20px;
+ touch-action: none;
+ background: black;
+ margin-top: 5px;
+ touch-action: pan-y;
+ }
+ #target3 {
+ width: 700px;
+ height: 20px;
+ touch-action: none;
+ background: black;
+ margin-top: 5px;
+ touch-action: none;
+ }
+ #target4 {
+ width: 700px;
+ height: 20px;
+ touch-action: none;
+ background: black;
+ margin-top: 5px;
+ touch-action: manipulation;
+ }
+ </style>
+ </head>
+ <body onload="run()">
+ <h2>Pointer Events touch-action attribute support</h2>
+ <h4 id="desc">Test Description: Test will automatically check behaviour of following values: 'auto', 'pan-x', 'pan-y', ' none', 'manipulation'</h4>
+ <div id="target0"></div>
+ <div id="target1"></div>
+ <div id="target2"></div>
+ <div id="target3"></div>
+ <div id="target4"></div>
+ <script type='text/javascript'>
+ var detected_pointertypes = {};
+
+ setup({ explicit_done: true });
+
+ function run() {
+ var target0 = document.getElementById('target0');
+ var target1 = document.getElementById('target1');
+ var target2 = document.getElementById('target2');
+ var target3 = document.getElementById('target3');
+ var target4 = document.getElementById('target4');
+
+ //TA 15.20
+ test(function() {
+ assert_true(getComputedStyle(target0).touchAction == 'auto', "'auto' is set properly");
+ }, "'auto' is set properly");
+ test(function() {
+ assert_true(getComputedStyle(target1).touchAction == 'pan-x', "'pan-x' is corrected properly");
+ }, "'pan-x' is corrected properly");
+ test(function() {
+ assert_true(getComputedStyle(target2).touchAction == 'pan-y', "'pan-y' is set properly");
+ }, "'pan-y' is set properly");
+ test(function() {
+ assert_true(getComputedStyle(target3).touchAction == 'none', "'none' is set properly");
+ }, "'none' is set properly");
+ test(function() {
+ assert_true(getComputedStyle(target4).touchAction == 'manipulation', "'manipulation' is set properly");
+ }, "'manipulation' is set properly");
+ done();
+ }
+ </script>
+ <h1>touch-action: basic verification</h1>
+ <div id="complete-notice">
+ <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+ </div>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/pointerlock/constructor.html b/tests/wpt/web-platform-tests/pointerlock/constructor.html
new file mode 100644
index 00000000000..8c43cf6dafc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerlock/constructor.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Pointer Lock event constructor</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="http://www.w3.org/TR/pointerlock/#pointerlockchange-and-pointerlockerror-events">
+ <link rel="help" href="http://www.w3.org/TR/dom/#interface-event">
+ </head>
+ <body>
+ <p>Create Pointer Lock events and check each default value.</p>
+ <div id='log'></div>
+ <script>
+test(function() {
+ var ev = new MouseEvent("pointerlockchange");
+ assert_equals(ev.type, "pointerlockchange");
+ assert_equals(ev.target, null);
+ assert_equals(ev.currentTarget, null);
+ assert_equals(ev.bubbles, false);
+ assert_equals(ev.eventPhase, Event.NONE);
+ assert_equals(ev.cancelable, false);
+ assert_true("preventDefault" in ev);
+ assert_equals(ev.defaultPrevented, false);
+ assert_true(ev.timeStamp > 0);
+ assert_true("initEvent" in ev);
+ assert_true("movementX" in ev, "movementX exists");
+ assert_true("movementY" in ev, "movementY exists");
+ assert_equals(ev.movementX, 0);
+ assert_equals(ev.movementY, 0);
+}, "Default event values for mouse event interface and its pointer lock extensions.");
+test(function() {
+ var ev = new MouseEvent("pointerlockerror",
+ { type: "trololol",
+ bubbles: true,
+ cancelable: false,
+ get defaultPrevented() {
+ assert_unreached("Should not look at the defaultPrevented property.");
+ },
+ movementX: 10,
+ movementY: 10});
+ assert_equals(ev.type, "pointerlockerror");
+ assert_equals(ev.bubbles, true); // this is synthetic event, so follow the dictionary
+ assert_equals(ev.cancelable, false);
+ assert_equals(ev.defaultPrevented, false);
+ assert_equals(ev.movementX, 10); // this is synthetic event, so follow the dictionary
+ assert_equals(ev.movementY, 10); // this is synthetic event, so follow the dictionary
+}, "Default event values for pointerlockerror using a dictionary");
+ </script>
+
+</body>
+
+</html>
diff --git a/tests/wpt/web-platform-tests/pointerlock/idlharness.html b/tests/wpt/web-platform-tests/pointerlock/idlharness.html
new file mode 100644
index 00000000000..5fb2ca08ae8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/pointerlock/idlharness.html
@@ -0,0 +1,79 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Pointer Lock IDL tests</title>
+<link rel="author" title="W3C" href="http://www.w3.org/" />
+<link rel="help" href="http://www.w3.org/TR/pointerlock/#element-interface"/>
+<link rel="help" href="http://www.w3.org/TR/pointerlock/#extensions-to-the-document-interface">
+<link rel="help" href="http://www.w3.org/TR/pointerlock/#extensions-to-the-mouseevent-interface">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/WebIDLParser.js"></script>
+<script src="/resources/idlharness.js"></script>
+</head>
+
+<body>
+<h1>Pointer Lock IDL tests</h1>
+
+<pre id='untested_idl' style='display:none'>
+
+interface EventTarget {
+};
+
+interface Node : EventTarget {
+};
+
+interface Element : Node {
+};
+
+interface Document : Node {
+};
+
+interface Event {
+};
+
+interface MouseEvent : Event {
+};
+</pre>
+
+<pre id='idl'>
+
+partial interface Element {
+ void requestPointerLock ();
+};
+
+partial interface Document {
+ attribute EventHandler? onpointerlockchange;
+ attribute EventHandler? onpointerlockerror;
+ readonly attribute Element? pointerLockElement;
+ void exitPointerLock ();
+};
+
+partial interface MouseEvent {
+ readonly attribute long movementX;
+ readonly attribute long movementY;
+};
+
+</pre>
+
+<div id="log"></div>
+
+<script>
+
+var idl_array = new IdlArray();
+
+setup(function() {
+ idl_array.add_untested_idls(document.getElementById("untested_idl").textContent);
+ idl_array.add_idls(document.getElementById("idl").textContent);
+
+ idl_array.add_objects({ Document: ["window.document"],
+ Element: ["window.document.documentElement"],
+ MouseEvent: ["new MouseEvent('mousemove')", "new MouseEvent('pointerlockchange')"] });
+});
+
+idl_array.test();
+
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/progress-events/Status.html b/tests/wpt/web-platform-tests/progress-events/Status.html
new file mode 100644
index 00000000000..f2aee75d7f6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/progress-events/Status.html
@@ -0,0 +1,26 @@
+<!doctype html>
+<html>
+<head>
+ <title>Progress Events Test Status</title>
+</head>
+<body>
+
+<h2>Progress Events Test Suite Status</h2>
+
+<p>This test suite is part of the
+<a href="http://www.w3.org/2008/webapps/wiki/">Web Application WG's</a>
+Test Repository as described in WebApps'
+<a href="http://www.w3.org/2008/webapps/wiki/Testing">Testing Wiki</a>.
+</p>
+
+<p>The test suite is for the
+<a href="http://dev.w3.org/2006/webapi/progress/">Progress Events</a> specification.
+</p>
+
+<ul>
+ <li>Test suite status: The group has reviewed and approved all tests in the approved folder.</li>
+ <li>Test suite Facilitator: Jungkee Song</li>
+</ul>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/progress-events/constructor.html b/tests/wpt/web-platform-tests/progress-events/constructor.html
new file mode 100644
index 00000000000..a99013a281c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/progress-events/constructor.html
@@ -0,0 +1,43 @@
+<!doctype html>
+<title>ProgressEvent constructor</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function() {
+ var ev = new ProgressEvent("test")
+ assert_equals(ev.type, "test")
+ assert_equals(ev.target, null)
+ assert_equals(ev.currentTarget, null)
+ assert_equals(ev.eventPhase, Event.NONE)
+ assert_equals(ev.bubbles, false)
+ assert_equals(ev.cancelable, false)
+ assert_equals(ev.defaultPrevented, false)
+ assert_true(ev.timeStamp > 0)
+ assert_true("initEvent" in ev)
+ assert_equals(ev.lengthComputable, false)
+ assert_equals(ev.loaded, 0)
+ assert_equals(ev.total, 0)
+}, "Default event values.")
+test(function() {
+ var ev = new ProgressEvent("test")
+ assert_equals(ev["initProgressEvent"], undefined)
+}, "There must not be a initProgressEvent().")
+test(function() {
+ var ev = new ProgressEvent("I am an event", { type: "trololol", bubbles: true, cancelable: false})
+ assert_equals(ev.type, "I am an event")
+ assert_equals(ev.bubbles, true)
+ assert_equals(ev.cancelable, false)
+}, "Basic test.")
+test(function() {
+ var ev = new ProgressEvent(null, { lengthComputable: "hah", loaded: "2" })
+ assert_equals(ev.type, "null")
+ assert_equals(ev.lengthComputable, true)
+ assert_equals(ev.loaded, 2)
+}, "ECMAScript value conversion test.")
+test(function() {
+ var ev = new ProgressEvent("Xx", { lengthcomputable: true})
+ assert_equals(ev.type, "Xx")
+ assert_equals(ev.lengthComputable, false)
+}, "ProgressEventInit members must be matched case-sensitively.")
+</script>
diff --git a/tests/wpt/web-platform-tests/progress-events/interface.html b/tests/wpt/web-platform-tests/progress-events/interface.html
new file mode 100644
index 00000000000..3bd7a0dadef
--- /dev/null
+++ b/tests/wpt/web-platform-tests/progress-events/interface.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<title>The ProgressEvent interface</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ assert_equals(typeof ProgressEvent, "function")
+ assert_equals(ProgressEvent.length, 1)
+ assert_throws(new TypeError(), function() {
+ "use strict";
+ delete ProgressEvent.length;
+ })
+})
+test(function() {
+ var desc = Object.getOwnPropertyDescriptor(ProgressEvent, "prototype")
+ assert_equals(desc.value, ProgressEvent.prototype)
+ assert_equals(desc.writable, false)
+ assert_equals(desc.enumerable, false)
+ assert_equals(desc.configurable, false)
+ assert_throws(new TypeError(), function() {
+ "use strict";
+ delete ProgressEvent.prototype;
+ })
+ assert_equals(ProgressEvent.prototype.constructor, ProgressEvent)
+ assert_equals(Object.getPrototypeOf(ProgressEvent.prototype), Event.prototype)
+}, "interface prototype object")
+var attributes = [
+ ["boolean", "lengthComputable"],
+ ["unsigned long long", "loaded"],
+ ["unsigned long long", "total"]
+];
+attributes.forEach(function(a) {
+ test(function() {
+ var desc = Object.getOwnPropertyDescriptor(ProgressEvent.prototype, a[1])
+ assert_equals(desc.enumerable, true)
+ assert_equals(desc.configurable, true)
+ assert_throws(new TypeError(), function() {
+ ProgressEvent.prototype[a[1]]
+ })
+ })
+})
+test(function() {
+ for (var p in window) {
+ assert_not_equals(p, "ProgressEvent")
+ }
+}, "Interface objects properties should not be Enumerable")
+test(function() {
+ assert_true(!!window.ProgressEvent, "Interface should exist.")
+ assert_true(delete window.ProgressEvent, "The delete operator should return true.")
+ assert_equals(window.ProgressEvent, undefined, "Interface should be gone.")
+}, "Should be able to delete ProgressEvent.")
+</script>
diff --git a/tests/wpt/web-platform-tests/progress-events/tests/submissions/Samsung/firing-events-http-content-length.html b/tests/wpt/web-platform-tests/progress-events/tests/submissions/Samsung/firing-events-http-content-length.html
new file mode 100644
index 00000000000..d897a71109e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/progress-events/tests/submissions/Samsung/firing-events-http-content-length.html
@@ -0,0 +1,38 @@
+<!doctype html>
+<html>
+ <head>
+ <title>ProgressEvent: firing events for HTTP with Content-Length</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="http://dvcs.w3.org/hg/progress/raw-file/tip/Overview.html#firing-events-using-the-progressevent-interface-for-http" data-tested-assertations="/following-sibling::ol/li[1] /following-sibling::ol/li[2]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test();
+
+ test.step(function() {
+ var xhr = new XMLHttpRequest();
+
+ xhr.onprogress = function(pe) {
+ test.step(function() {
+ if(pe.type == "progress") {
+ assert_true(pe.loaded >= 0, "loaded is initialize to the number of HTTP entity body bytes transferred.");
+ assert_true(pe.lengthComputable, "lengthComputable is true.");
+ assert_not_equals(pe.total, 0, "total is not zero.");
+ }
+ }, "Check lengthComputed, loaded, total when Content-Length is given.");
+ }
+
+ // "loadstart", "error", "abort", "load" tests are out of scope.
+ // They SHOULD be tested in each spec that implement ProgressEvent.
+
+ xhr.onloadend = function(pe) {
+ test.done();
+ }
+ xhr.open("GET", "resources/img.jpg", true);
+ xhr.send(null);
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/progress-events/tests/submissions/Samsung/firing-events-http-no-content-length.html b/tests/wpt/web-platform-tests/progress-events/tests/submissions/Samsung/firing-events-http-no-content-length.html
new file mode 100644
index 00000000000..b30b03afe08
--- /dev/null
+++ b/tests/wpt/web-platform-tests/progress-events/tests/submissions/Samsung/firing-events-http-no-content-length.html
@@ -0,0 +1,38 @@
+<!doctype html>
+<html>
+ <head>
+ <title>ProgressEvent: firing events for HTTP with no Content-Length</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <link rel="help" href="http://dvcs.w3.org/hg/progress/raw-file/tip/Overview.html#firing-events-using-the-progressevent-interface-for-http" data-tested-assertations="/following-sibling::ol/li[1] /following-sibling::ol/li[2]" />
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ var test = async_test();
+
+ test.step(function() {
+ var xhr = new XMLHttpRequest();
+
+ xhr.onprogress = function(pe) {
+ test.step(function() {
+ if(pe.type == "progress") {
+ assert_true(pe.loaded >= 0, "loaded is initialize to the number of HTTP entity body bytes transferred.");
+ assert_false(pe.lengthComputable, "lengthComputable is false.");
+ assert_equals(pe.total, 0, "total is zero.");
+ }
+ }, "Check lengthComputed, loaded, total when Content-Length is NOT given.");
+ }
+
+ // "loadstart", "error", "abort", "load" tests are out of scope.
+ // They SHOULD be tested in each spec that implement ProgressEvent.
+
+ xhr.onloadend = function(pe) {
+ test.done();
+ }
+ xhr.open("GET", "resources/no-content-length.py", true);
+ xhr.send(null);
+ })
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/progress-events/tests/submissions/Samsung/resources/no-content-length.py b/tests/wpt/web-platform-tests/progress-events/tests/submissions/Samsung/resources/no-content-length.py
new file mode 100644
index 00000000000..0b47ff146cc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/progress-events/tests/submissions/Samsung/resources/no-content-length.py
@@ -0,0 +1,15 @@
+def main(request, response):
+ response.headers.update([('Transfer-Encoding', 'chunked'),
+ ('Content-Type', 'text/html'),
+ ('Connection', 'keep-alive')])
+ response.write_status_headers()
+ response.explicit_flush = True
+
+ string = "W3C"
+ for i in xrange(1000):
+ response.writer.write("%s\r\n%s\r\n" % (len(string), string))
+ response.writer.flush();
+
+ response.writer.write("0\r\n\r\n")
+ response.writer.flush();
+
diff --git a/tests/wpt/web-platform-tests/proximity/DeviceProximityEvent_tests.html b/tests/wpt/web-platform-tests/proximity/DeviceProximityEvent_tests.html
new file mode 100644
index 00000000000..d4d08fda7f1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/proximity/DeviceProximityEvent_tests.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<meta charset=utf8>
+<meta content="width=device-width, initial-scale=1" name=viewport>
+<title>Proximity Events Test Suite</title>
+<h1>Test Suite for Proximity Events</h1>
+<div id="log"></div>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="DeviceProximityEvent_tests.js"></script>
+
diff --git a/tests/wpt/web-platform-tests/proximity/DeviceProximityEvent_tests.js b/tests/wpt/web-platform-tests/proximity/DeviceProximityEvent_tests.js
new file mode 100644
index 00000000000..4d3c00c0a3c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/proximity/DeviceProximityEvent_tests.js
@@ -0,0 +1,439 @@
+(function() {
+ //inheritance tests
+ test(function() {
+ var event = new DeviceProximityEvent('');
+ assert_true(event instanceof window.DeviceProximityEvent);
+ }, 'the event is an instance of DeviceProximityEvent');
+
+ test(function() {
+ var event = new DeviceProximityEvent('');
+ assert_true(event instanceof window.Event);
+ }, 'the event inherits from Event');
+
+ //Type attribute tests
+ test(function() {
+ assert_throws(new TypeError(), function() {
+ new DeviceProximityEvent();
+ }, 'First argument is required, so was expecting a TypeError.');
+ }, 'Missing type argument');
+
+ test(function() {
+ var event = new DeviceProximityEvent(undefined);
+ assert_equals(event.type, 'undefined');
+ }, 'Event type set to undefined');
+
+ test(function() {
+ var event = new DeviceProximityEvent(null);
+ assert_equals(event.type, 'null');
+ }, 'type argument is null');
+
+ test(function() {
+ var event = new DeviceProximityEvent(123);
+ assert_equals(event.type, '123');
+ }, 'type argument is number');
+
+ test(function() {
+ var event = new DeviceProximityEvent(new Number(123));
+ assert_equals(event.type, '123');
+ }, 'type argument is Number');
+
+ test(function() {
+ var event = new DeviceProximityEvent([]);
+ assert_equals(event.type, '');
+ }, 'type argument is array');
+
+ test(function() {
+ var event = new DeviceProximityEvent(new Array());
+ assert_equals(event.type, '');
+ }, 'type argument is instance of Array');
+
+ test(function() {
+ var event = new DeviceProximityEvent(['t', ['e', ['s', ['t']]]]);
+ assert_equals(event.type, 't,e,s,t');
+ }, 'type argument is nested array');
+
+ test(function() {
+ var event = new DeviceProximityEvent(Math);
+ assert_equals(event.type, '[object Math]');
+ }, 'type argument is host object');
+
+ test(function() {
+ var event = new DeviceProximityEvent(true);
+ assert_equals(event.type, 'true');
+ }, 'type argument is boolean (true)');
+
+ test(function() {
+ var event = new DeviceProximityEvent(new Boolean(true));
+ assert_equals(event.type, 'true');
+ }, 'type argument is instance of Boolean (true)');
+
+ test(function() {
+ var event = new DeviceProximityEvent(false);
+ assert_equals(event.type, 'false');
+ }, 'type argument is boolean (false)');
+
+ test(function() {
+ var event = new DeviceProximityEvent(new Boolean(false));
+ assert_equals(event.type, 'false');
+ }, 'type argument is instance of Boolean (false)');
+
+ test(function() {
+ var event = new DeviceProximityEvent('test');
+ assert_equals(event.type, 'test');
+ }, 'type argument is string');
+
+ test(function() {
+ var event = new DeviceProximityEvent(new String('test'));
+ assert_equals(event.type, 'test');
+ }, 'type argument is instance of String');
+
+ test(function() {
+ var event = new DeviceProximityEvent(function test() {});
+ assert_regexp_match(event.type, /function test.+{\s?}/);
+ }, 'type argument is function');
+
+ test(function() {
+ var event = new DeviceProximityEvent({
+ toString: function() {
+ return '123';
+ }
+ });
+ assert_equals(event.type, '123');
+ }, 'type argument is complext object, with toString method');
+
+ test(function() {
+ assert_throws(new TypeError(), function() {
+ new DeviceProximityEvent({
+ toString: function() {
+ return function() {}
+ }
+ });
+ });
+ }, 'toString is of type function');
+
+ //eventInitDict attribute tests
+ test(function() {
+ var event = new DeviceProximityEvent('test', undefined);
+ assert_equals(event.value, Infinity);
+ assert_equals(event.min, -Infinity);
+ assert_equals(event.max, Infinity);
+ }, 'eventInitDict argument sets to undefined');
+
+ test(function() {
+ var event = new DeviceProximityEvent('test', null);
+ assert_equals(event.value, Infinity);
+ assert_equals(event.min, -Infinity);
+ assert_equals(event.max, Infinity);
+ }, 'eventInitDict argument is null');
+
+ test(function() {
+ var date = new Date();
+ assert_throws(new TypeError(), function() {
+ new DeviceProximityEvent('test', date);
+ });
+ }, 'eventInitDict argument is Date object');
+
+ test(function() {
+ var regexp = /abc/;
+ assert_throws(new TypeError(), function() {
+ new DeviceProximityEvent('test', regexp);
+ });
+ }, 'eventInitDict argument is RegExp object');
+
+ test(function() {
+ assert_throws(new TypeError(), function() {
+ new DeviceProximityEvent('test', false);
+ });
+ }, 'eventInitDict argument is boolean');
+
+ test(function() {
+ assert_throws(new TypeError(), function() {
+ new DeviceProximityEvent('test', 123);
+ });
+ }, 'eventInitDict argument is number');
+
+ test(function() {
+ assert_throws(new TypeError(), function() {
+ new DeviceProximityEvent('test', 'hello');
+ });
+ }, 'eventInitDict argument is string');
+
+ //test readonly attribute unrestricted double value;
+ test(function() {
+ var event = new DeviceProximityEvent('test');
+ assert_idl_attribute(event, 'value', 'must have attribute value');
+ }, 'value attribute exist');
+
+ test(function() {
+ var event = new DeviceProximityEvent('test');
+ assert_readonly(event, 'value', 'readonly attribute value');
+ }, 'value attribute is readonly');
+
+ test(function() {
+ var event = new DeviceProximityEvent('test');
+ assert_equals(event.value, Infinity);
+ }, 'value initializes to positive Infinity');
+
+ test(function() {
+ var event = new DeviceProximityEvent('test', {
+ value: Infinity
+ });
+ assert_equals(event.value, Infinity);
+ }, 'value set to positive Infinity');
+
+ test(function() {
+ var event = new DeviceProximityEvent('test', {
+ value: -Infinity
+ });
+ assert_equals(event.value, -Infinity);
+ }, 'value set to negative Infinity');
+
+ test(function() {
+ var event = new DeviceProximityEvent('test', {
+ value: 0
+ });
+ assert_equals(event.value, 0);
+ }, 'value set to 0');
+
+ test(function() {
+ var event = new DeviceProximityEvent('test', {
+ value: 1
+ });
+ assert_equals(event.value, 1);
+ }, 'value set to 1');
+
+ test(function() {
+ var event = new DeviceProximityEvent('test', {
+ value: 0.5
+ });
+ assert_equals(event.value, 0.5);
+ }, 'value set to 0.5');
+
+ test(function() {
+ var event = new DeviceProximityEvent('test', {
+ value: false
+ });
+ assert_equals(event.value, 0, 'value set to false, converts to 0.');
+ }, 'value set to false');
+
+ test(function() {
+ var event = new DeviceProximityEvent('test', {
+ value: true
+ });
+ assert_equals(event.value, 1, 'value set to true, converts to 1.');
+ }, 'value set to true');
+
+
+ test(function() {
+ var prop = {
+ value: undefined
+ };
+ try {
+ var event = new DeviceProximityEvent('test', prop);
+ assert_true(isNaN(event.value));
+ } catch(e) {
+ assert_unreached('error message: ' + e.message);
+ }
+ }, 'value of undefined resolves to NaN');
+
+ test(function() {
+ var event = new DeviceProximityEvent('test', {
+ value: null
+ });
+ assert_equals(event.value, 0, 'value resolves to 0');
+ }, 'value of null resolves to 0');
+
+ test(function() {
+ var event = new DeviceProximityEvent('test', {
+ value: ''
+ });
+ assert_equals(event.value, 0, 'value must resolve to 0');
+ }, 'value of empty string must resolve to 0');
+
+ test(function() {
+ var event = new DeviceProximityEvent('test', {
+ value: '\u0020'
+ });
+ assert_equals(event.value, 0, 'value must resolve to 0');
+ }, 'value of U+0020 must resolve to 0');
+
+ test(function() {
+ var event = new DeviceProximityEvent('test', {
+ value: '\u0020\u0020\u0020\u0020\u0020\u0020'
+ });
+ assert_equals(event.value, 0, 'value must resolve to 0');
+ }, 'value of multiple U+0020 must resolve to 0');
+
+ test(function() {
+ var event = new DeviceProximityEvent('test', {
+ value: '\u0020\u0020\u00201234\u0020\u0020\u0020'
+ });
+ assert_equals(event.value, 1234, 'converts to 1234');
+ }, 'value converts to 1234');
+
+ test(function() {
+ var event = new DeviceProximityEvent('test', {
+ value: []
+ });
+ assert_equals(event.value, 0, 'converts to 0');
+ }, 'value converts to 0');
+
+
+ test(function() {
+ var prop = {
+ value: {}
+ };
+ try {
+ var event = new DeviceProximityEvent('test', prop);
+ assert_true(isNaN(event.value));
+ } catch(e) {
+ assert_unreached('error message: ' + e.message);
+ }
+ }, 'value of {} resolves to NaN');
+
+ test(function() {
+ var prop = {
+ get value() {
+ return NaN;
+ }
+ };
+ try {
+ var event = new DeviceProximityEvent('test', prop);
+ assert_true(isNaN(event.value));
+ } catch(e) {
+ assert_unreached('error message: ' + e.message);
+ }
+ }, 'value resolves to NaN');
+
+ test(function() {
+ var prop = {
+ get value() {
+ return '123';
+ }
+ };
+ var event = new DeviceProximityEvent('test', prop);
+ assert_equals(event.value, 123, 'converts to 123');
+ }, 'value resolves 123');
+
+ //test readonly attribute unrestricted double min
+ test(function() {
+ var event = new DeviceProximityEvent('test');
+ assert_idl_attribute(event, 'min', 'must have attribute min');
+ }, 'min attribute exist');
+
+ test(function() {
+ var event = new DeviceProximityEvent('test');
+ assert_readonly(event, 'min', 'readonly attribute min');
+ }, 'min attribute is readonly');
+
+ test(function() {
+ var event = new DeviceProximityEvent('test');
+ assert_equals(event.min, -Infinity);
+ }, 'min initializes to negative Infinity');
+
+ //test readonly attribute unrestricted double max;
+ test(function() {
+ var event = new DeviceProximityEvent('test');
+ assert_idl_attribute(event, 'max', 'must have attribute max');
+ }, 'max attribute exist');
+
+ test(function() {
+ var event = new DeviceProximityEvent('test');
+ assert_readonly(event, 'max', 'readonly attribute max');
+ }, 'max attribute is readonly');
+
+ test(function() {
+ var event = new DeviceProximityEvent('test');
+ assert_equals(event.max, Infinity);
+ }, 'max initializes to positive Infinity');
+
+ //test attribute EventHandler ondeviceproximity;
+ test(function() {
+ var desc = 'Expected to find ondeviceproximity attribute on window object';
+ assert_idl_attribute(window, 'ondeviceproximity', desc);
+ }, 'ondeviceproximity exists');
+
+ test(function() {
+ var desc = 'window.ondeviceproximity must be null';
+ assert_equals(window.ondeviceproximity, null, desc);
+ }, 'ondeviceproximity is null');
+
+ test(function() {
+ var desc = 'window.ondeviceproximity did not accept callable object',
+ func = function() {},
+ descidl = 'Expected to find ondeviceproximity attribute on window object';
+ assert_idl_attribute(window, 'ondeviceproximity', descidl);
+ window.ondeviceproximity = func;
+ assert_equals(window.ondeviceproximity, func, desc);
+ }, 'ondeviceproximity is set to function');
+
+ test(function() {
+ var desc = 'window.ondeviceproximity did not treat noncallable as null';
+ window.ondeviceproximity = function() {};
+ window.ondeviceproximity = {};
+ assert_equals(window.ondeviceproximity, null, desc);
+ }, 'treat object as null');
+
+ test(function() {
+ var desc = 'window.ondeviceproximity did not treat noncallable as null';
+ window.ondeviceproximity = function() {};
+ window.ondeviceproximity = {
+ call: 'test'
+ };
+ assert_equals(window.ondeviceproximity, null, desc);
+ }, 'treat object with non-callable call property as null');
+
+ test(function() {
+ var desc = 'window.ondeviceproximity did not treat noncallable (string) as null';
+ window.ondeviceproximity = function() {};
+ window.ondeviceproximity = 'string';
+ assert_equals(window.ondeviceproximity, null, desc);
+ }, 'treat string as null');
+
+ test(function() {
+ var desc = 'window.ondeviceproximity did not treat noncallable (number) as null';
+ window.ondeviceproximity = function() {};
+ window.ondeviceproximity = 123;
+ assert_equals(window.ondeviceproximity, null, desc);
+ }, 'treat number as null');
+
+ test(function() {
+ var desc = 'window.ondeviceproximity did not treat noncallable (undefined) as null';
+ window.ondeviceproximity = function() {};
+ window.ondeviceproximity = undefined;
+ assert_equals(window.ondeviceproximity, null, desc);
+ }, 'treat undefined as null');
+
+ test(function() {
+ var desc = 'window.ondeviceproximity did not treat noncallable (array) as null';
+ window.ondeviceproximity = function() {};
+ window.ondeviceproximity = [];
+ assert_equals(window.ondeviceproximity, null, desc);
+ }, 'treat array as null');
+
+ test(function() {
+ var desc = 'window.ondeviceproximity did not treat noncallable host object as null';
+ window.ondeviceproximity = function() {};
+ window.ondeviceproximity = Node;
+ assert_equals(window.ondeviceproximity, null, desc);
+ }, 'treat non-callable host object as null');
+
+ //Async tests
+ var t = async_test('test if device proximity event received');
+ window.addEventListener('deviceproximity', function(e) {
+ t.step(function() {
+ var msg = 'expected instance of DeviceProximityEvent: ';
+ assert_true(e instanceof window.DeviceProximityEvent, msg);
+ });
+ t.done();
+ });
+
+ var t2 = async_test('test if user proximity event received');
+ window.ondeviceproximity = function(e) {
+ t2.step(function() {
+ var msg = 'expected instance of DeviceProximityEvent: ';
+ assert_true(e instanceof window.DeviceProximityEvent, msg);
+ });
+ t2.done();
+ };
+})();
diff --git a/tests/wpt/web-platform-tests/proximity/UserProximityEvent_tests.html b/tests/wpt/web-platform-tests/proximity/UserProximityEvent_tests.html
new file mode 100644
index 00000000000..f58550db0b7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/proximity/UserProximityEvent_tests.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<meta charset=utf8>
+<meta content="width=device-width, initial-scale=1" name=viewport>
+<title>Proximity Events Test Suite</title>
+<h1>Test Suite for Proximity Events</h1>
+<div id="log"></div>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="UserProximityEvent_tests.js"></script>
+
diff --git a/tests/wpt/web-platform-tests/proximity/UserProximityEvent_tests.js b/tests/wpt/web-platform-tests/proximity/UserProximityEvent_tests.js
new file mode 100644
index 00000000000..cac5bd58617
--- /dev/null
+++ b/tests/wpt/web-platform-tests/proximity/UserProximityEvent_tests.js
@@ -0,0 +1,342 @@
+(function() {
+ //inheritance tests
+ test(function() {
+ var event = new UserProximityEvent('');
+ assert_true(event instanceof window.UserProximityEvent);
+ }, 'the event is an instance of UserProximityEvent');
+
+ test(function() {
+ var event = new UserProximityEvent('');
+ assert_true(event instanceof window.Event);
+ }, 'the event inherits from Event');
+
+ //Type attribute tests
+ test(function() {
+ assert_throws(new TypeError(), function() {
+ new UserProximityEvent();
+ }, 'First argument is required, so was expecting a TypeError.');
+ }, 'Missing type argument');
+
+ test(function() {
+ var event = new UserProximityEvent(undefined);
+ assert_equals(event.type, 'undefined');
+ }, 'Event type set to undefined');
+
+ test(function() {
+ var event = new UserProximityEvent(null);
+ assert_equals(event.type, 'null');
+ }, 'type argument is null');
+
+ test(function() {
+ var event = new UserProximityEvent(123);
+ assert_equals(event.type, '123');
+ }, 'type argument is number');
+
+ test(function() {
+ var event = new UserProximityEvent(new Number(123));
+ assert_equals(event.type, '123');
+ }, 'type argument is Number');
+
+ test(function() {
+ var event = new UserProximityEvent([]);
+ assert_equals(event.type, '');
+ }, 'type argument is array');
+
+ test(function() {
+ var event = new UserProximityEvent(new Array());
+ assert_equals(event.type, '');
+ }, 'type argument is instance of Array');
+
+ test(function() {
+ var event = new UserProximityEvent(['t', ['e', ['s', ['t']]]]);
+ assert_equals(event.type, 't,e,s,t');
+ }, 'type argument is nested array');
+
+ test(function() {
+ var event = new UserProximityEvent(Math);
+ assert_equals(event.type, '[object Math]');
+ }, 'type argument is host object');
+
+ test(function() {
+ var event = new UserProximityEvent(true);
+ assert_equals(event.type, 'true');
+ }, 'type argument is boolean (true)');
+
+ test(function() {
+ var event = new UserProximityEvent(new Boolean(true));
+ assert_equals(event.type, 'true');
+ }, 'type argument is instance of Boolean (true)');
+
+ test(function() {
+ var event = new UserProximityEvent(false);
+ assert_equals(event.type, 'false');
+ }, 'type argument is boolean (false)');
+
+ test(function() {
+ var event = new UserProximityEvent(new Boolean(false));
+ assert_equals(event.type, 'false');
+ }, 'type argument is instance of Boolean (false)');
+
+ test(function() {
+ var event = new UserProximityEvent('test');
+ assert_equals(event.type, 'test');
+ }, 'type argument is string');
+
+ test(function() {
+ var event = new UserProximityEvent(new String('test'));
+ assert_equals(event.type, 'test');
+ }, 'type argument is instance of String');
+
+ test(function() {
+ var event = new UserProximityEvent(function test() {});
+ assert_regexp_match(event.type, /function test.+{\s?}/);
+ }, 'type argument is function');
+
+ test(function() {
+ var event = new UserProximityEvent({
+ toString: function() {
+ return '123';
+ }
+ });
+ assert_equals(event.type, '123');
+ }, 'type argument is complext object, with toString method');
+
+ test(function() {
+ assert_throws(new TypeError(), function() {
+ new UserProximityEvent({
+ toString: function() {
+ return function() {}
+ }
+ });
+ });
+ }, 'toString is of type function');
+
+ //eventInitDict attribute tests
+ test(function() {
+ var event = new UserProximityEvent('test', undefined);
+ assert_false(event.near);
+ }, 'eventInitDict argument sets to undefined');
+
+ test(function() {
+ var event = new UserProximityEvent('test', null);
+ assert_false(event.near);
+ }, 'eventInitDict argument is null');
+
+ test(function() {
+ var date = new Date();
+ assert_throws(new TypeError(), function() {
+ new UserProximityEvent('test', date);
+ });
+ }, 'eventInitDict argument is Date object');
+
+ test(function() {
+ var regexp = /abc/;
+ assert_throws(new TypeError(), function() {
+ new UserProximityEvent('test', regexp);
+ });
+ }, 'eventInitDict argument is RegExp object');
+
+ test(function() {
+ assert_throws(new TypeError(), function() {
+ new UserProximityEvent('test', false);
+ });
+ }, 'eventInitDict argument is boolean');
+
+ test(function() {
+ assert_throws(new TypeError(), function() {
+ new UserProximityEvent('test', 123);
+ });
+ }, 'eventInitDict argument is number');
+
+ test(function() {
+ assert_throws(new TypeError(), function() {
+ new UserProximityEvent('test', 'hello');
+ });
+ }, 'eventInitDict argument is string');
+
+ //test readonly attribute boolean near;
+ test(function() {
+ var event = new UserProximityEvent('test');
+ assert_idl_attribute(event, 'near', 'must have attribute near');
+ }, 'must have attribute near');
+
+ test(function() {
+ var event = new UserProximityEvent('test');
+ assert_readonly(event, 'near', 'readonly attribute near');
+ }, 'near is readonly');
+
+ test(function() {
+ var event = new UserProximityEvent('test');
+ assert_false(event.near, 'near initializes to false');
+ }, 'near initializes to false');
+
+ test(function() {
+ var event = new UserProximityEvent('test', {
+ near: false
+ });
+ assert_false(event.near, 'near set to false');
+ }, 'near set to false');
+
+ test(function() {
+ var event = new UserProximityEvent('test', {
+ near: true
+ });
+ assert_true(event.near, 'near set to true');
+ }, 'near set to true');
+
+ test(function() {
+ var event = new UserProximityEvent('test', {
+ near: undefined
+ });
+ assert_false(event.near, 'argument is truthy');
+ }, 'near set to undefined');
+
+ test(function() {
+ var event = new UserProximityEvent('test', {
+ near: null
+ });
+ assert_false(event.near, 'argument is flasy');
+ }, 'near set to null');
+
+ test(function() {
+ var event = new UserProximityEvent('test', {
+ near: 0
+ });
+ assert_false(event.near, 'argument is flasy');
+ }, 'near set to 0');
+
+ test(function() {
+ var event = new UserProximityEvent('test', {
+ near: ''
+ });
+ assert_false(event.near, 'argument is flasy');
+ }, 'near set to empty string');
+
+ test(function() {
+ var event = new UserProximityEvent('test', {
+ near: '\u0020'
+ });
+ assert_true(event.near, 'argument is truthy');
+ }, 'near set to U+0020');
+
+ test(function() {
+ var event = new UserProximityEvent('test', {
+ near: 1
+ });
+ assert_true(event.near, 'argument is truthy');
+ }, 'near set to 1');
+
+ test(function() {
+ var event = new UserProximityEvent('test', {
+ near: []
+ });
+ assert_true(event.near, 'argument is truthy');
+ }, 'near set to []');
+
+ test(function() {
+ var event = new UserProximityEvent('test', {
+ near: {}
+ });
+ assert_true(event.near, 'argument is truthy');
+ }, 'near set to {}');
+
+ test(function() {
+ var dict = {
+ get test() {
+ return false;
+ }
+ };
+ var event = new UserProximityEvent('test', {
+ near: dict.test
+ });
+ assert_false(event.near, 'explict false');
+ }, 'near set to object that resolves to false');
+
+ test(function() {
+ var desc = 'Expected to find onuserproximity attribute on window object';
+ assert_idl_attribute(window, 'onuserproximity', desc);
+ }, 'onuserproximity exists');
+
+ test(function() {
+ var desc = 'window.onuserproximity must be null';
+ assert_equals(window.onuserproximity, null, desc);
+ }, 'onuserproximity is null');
+
+ test(function() {
+ var desc = 'window.onuserproximity did not accept callable object',
+ func = function() {},
+ descidl = 'onuserproximity does not exist';
+ window.onuserproximity = func;
+ assert_equals(window.onuserproximity, func, descidl);
+ }, 'onuserproximity exists and can be set to a function');
+
+ test(function() {
+ var desc = 'window.onuserproximity did not treat noncallable as null';
+ window.onuserproximity = function() {};
+ window.onuserproximity = {};
+ assert_equals(window.onuserproximity, null, desc);
+ }, 'treat object as null');
+
+ test(function() {
+ var desc = 'window.onuserproximity did not treat noncallable as null';
+ window.onuserproximity = function() {};
+ window.onuserproximity = {
+ call: 'test'
+ };
+ assert_equals(window.onuserproximity, null, desc);
+ }, 'treat object with non-callable call property as null');
+
+ test(function() {
+ var desc = 'window.onuserproximity did not treat noncallable (string) as null';
+ window.onuserproximity = function() {};
+ window.onuserproximity = 'string';
+ assert_equals(window.onuserproximity, null, desc);
+ }, 'treat string as null');
+
+ test(function() {
+ var desc = 'window.onuserproximity did not treat noncallable (number) as null';
+ window.onuserproximity = function() {};
+ window.onuserproximity = 123;
+ assert_equals(window.onuserproximity, null, desc);
+ }, 'treat number as null');
+
+ test(function() {
+ var desc = 'window.onuserproximity did not treat noncallable (undefined) as null';
+ window.onuserproximity = function() {};
+ window.onuserproximity = undefined;
+ assert_equals(window.onuserproximity, null, desc);
+ }, 'treat undefined as null');
+
+ test(function() {
+ var desc = 'window.onuserproximity did not treat noncallable (array) as null';
+ window.onuserproximity = function() {};
+ window.onuserproximity = [];
+ assert_equals(window.onuserproximity, null, desc);
+ }, 'treat array as null');
+
+ test(function() {
+ var desc = 'window.onuserproximity did not treat noncallable host object as null';
+ window.onuserproximity = function() {};
+ window.onuserproximity = Node;
+ assert_equals(window.onuserproximity, null, desc);
+ }, 'treat non-callable host object as null');
+
+ //Async tests
+ var t = async_test('test if user proximity event received');
+ window.addEventListener('userproximity', function(e) {
+ t.step(function() {
+ var msg = 'expected instance of UserProximityEvent: ';
+ assert_true(e instanceof window.UserProximityEvent, msg);
+ });
+ t.done();
+ });
+
+ var t2 = async_test('test if user proximity event received (idl attribute)');
+ window.onuserproximity = function(e) {
+ t2.step(function() {
+ var msg = 'expected instance of UserProximityEvent: ';
+ assert_true(e instanceof window.UserProximityEvent, msg);
+ });
+ t2.done();
+ };
+})();
diff --git a/tests/wpt/web-platform-tests/proximity/idlharness.html b/tests/wpt/web-platform-tests/proximity/idlharness.html
new file mode 100644
index 00000000000..a84b54af462
--- /dev/null
+++ b/tests/wpt/web-platform-tests/proximity/idlharness.html
@@ -0,0 +1,76 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Proximity Events IDL tests</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="http://www.w3.org/TR/proximity/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/webidl2/lib/webidl2.js"></script>
+<script src="/resources/idlharness.js"></script>
+<style>
+ pre {
+ display: none;
+ }
+</style>
+<div id="log"></div>
+
+<pre id="untested_idl">
+interface Window {
+};
+
+interface Event {
+};
+
+dictionary EventInit {
+};
+</pre>
+
+<pre id='idl'>
+partial interface Window {
+ attribute EventHandler ondeviceproximity;
+ attribute EventHandler onuserproximity;
+};
+
+dictionary DeviceProximityEventInit : EventInit {
+ double value;
+ double min;
+ double max;
+};
+
+[Constructor (DOMString type, optional DeviceProximityEventInit eventInitDict)]
+interface DeviceProximityEvent : Event {
+ readonly attribute unrestricted double value;
+ readonly attribute unrestricted double min;
+ readonly attribute unrestricted double max;
+};
+
+dictionary UserProximityEventInit : EventInit {
+ boolean near;
+};
+
+[Constructor (DOMString type, optional UserProximityEventInit eventInitDict)]
+interface UserProximityEvent : Event {
+ readonly attribute boolean near;
+};
+</pre>
+
+<script>
+(function() {
+ "use strict";
+ var idl_array = new IdlArray();
+ // replace 'EventHandler' and 'unrestricted double' unrecognised by idlharness.js
+ var idls = document.getElementById('idl').textContent.replace(/EventHandler/g, 'Function?').replace(/unrestricted double/g, 'double');
+
+ idl_array.add_untested_idls(document.getElementById('untested_idl').textContent);
+ idl_array.add_idls(idls);
+
+ idl_array.add_objects({
+ Window: ['window'],
+ DeviceProximityEvent: ['new DeviceProximityEvent("foo")'],
+ UserProximityEvent: ['new UserProximityEvent("foo")']
+ });
+
+ idl_array.test();
+})();
+</script>
+
diff --git a/tests/wpt/web-platform-tests/quirks-mode/active-and-hover-manual.html b/tests/wpt/web-platform-tests/quirks-mode/active-and-hover-manual.html
new file mode 100644
index 00000000000..f334d88fb73
--- /dev/null
+++ b/tests/wpt/web-platform-tests/quirks-mode/active-and-hover-manual.html
@@ -0,0 +1,182 @@
+<!doctype html>
+<html>
+ <head>
+ <title>The :active and :hover quirk</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <style> iframe { width:100%; height:200px; } </style>
+ </head>
+ <body>
+ <p>Click on the boxes below (using a pointing device). <button onclick="timeout()">Abort and show results</button></p>
+ <div id=log></div>
+ <p>quirks:
+ <iframe id=quirks></iframe>
+ <p>almost:
+ <iframe id=almost></iframe>
+ <p>standards:
+ <iframe id=standards></iframe>
+ <script type="text/plain" id=html_tmpl>
+<html id=html class=x lang=en>
+<style>
+.t:not(area), img { display:inline-block; vertical-align:middle; width:50px; height:50px; background-color:#eee; margin:0 0.5em }
+.done.done { background-color:lime }
+link::before { content:'' }
+table, tbody, tr, td { display:inline }
+</style>
+<style>{style}</style>
+<body id=body class=x>
+a<a href=# id=a class=t></a>
+b<a id=b class=t></a>
+c<map id=map1 name=map1 class=x><area href=# coords=0,0,50,50 id=c class=t></map><img id=img1 class=x usemap=#map1 src=/images/transparent.png>
+d<map id=map2 name=map2 class=x><area coords=0,0,50,50 id=d class=t></map><img id=img2 class=x usemap=#map2 src=/images/transparent.png>
+e<link href=# id=e class=t>
+f<link rel=stylesheet href=# id=f class=t>
+g<link id=g class=t>
+h<button id=h class=t></button>
+i<input type=submit id=i class=t value>
+j<input type=image id=j class=t alt>
+k<input type=reset id=k class=t value>
+l<input type=button id=l class=t value>
+m<menuitem id=m class=t></menuitem>
+n<img tabindex=0 id=n class=t src=/images/transparent.png>
+o<a href=# id=a_ancestor class=x><table id=table class=x><tbody id=tbody class=x><tr id=tr class=x><td id=td class=x><a href=# id=o class=t></a></table></a>
+</script>
+ <script>
+ setup({explicit_done:true, explicit_timeout:true});
+ onload = function() {
+
+ var links_only = [
+ {input:':active', prop:'background-attachment', value:'fixed'},
+ {input:':hover', prop:'background-position', value:'1px 2px'},
+ {input:':hover:active', prop:'background-repeat', value:'repeat-x'},
+ {input:':active:active', prop:'border-collapse', value:'collapse'},
+ {input:':hover:hover', prop:'border-spacing', value:'1px 2px'},
+ {input:'*:active', prop:'border-top-style', value:'dotted'},
+ {input:'*:hover', prop:'border-right-style', value:'dotted'},
+ ];
+
+ var any_elm = [
+ // type selector
+ {input:'a:active, map:active, area:active, link:active, button:active, input:active, menuitem:active, img:active, table:active, tbody:active, tr:active, td:active, body:active, html:active', prop:'top', value:'1px'},
+ {input:'a:hover, map:hover, area:hover, link:hover, button:hover, input:hover, menuitem:hover, img:hover, table:hover, tbody:hover, tr:hover, td:hover, body:hover, html:hover', prop:'right', value:'1px'},
+ // attribute selector
+ {input:'[id]:active', prop:'bottom', value:'1px'},
+ {input:'[id]:hover', prop:'left', value:'1px'},
+ // id selector
+ {input:'#a:active, #b:active, #map1:active, #c:active, #img1:active, #map2:active, #d:active, #img2:active, #e:active, #f:active, #g:active, #h:active, #i:active, #j:active, #k:active, #l:active, #m:active, #n:active, #o:active, #a_ancestor:active, #table:active, #tbody:active, #tr:active, #td:active, #body:active, #html:active', prop:'caption-side', value:'bottom'},
+ {input:'#a:hover, #b:hover, #map1:hover, #c:hover, #img1:hover, #map2:hover, #d:hover, #img2:hover, #e:hover, #f:hover, #g:hover, #h:hover, #i:hover, #j:hover, #k:hover, #l:hover, #m:hover, #n:hover, #o:hover, #a_ancestor:hover, #table:hover, #tbody:hover, #tr:hover, #td:hover, #body:hover, #html:hover', prop:'clear', value:'left'},
+ {input:':active#a, :active#b, :active#map1, :active#c, :active#img1, :active#map2, :active#d, :active#img2, :active#e, :active#f, :active#g, :active#h, :active#i, :active#j, :active#k, :active#l, :active#m, :active#n, :active#o, :active#a_ancestor, :active#table, :active#tbody, :active#tr, :active#td, :active#body, :active#html', prop:'list-style-type', value:'circle'},
+ {input:':hover#a, :hover#b, :hover#map1, :hover#c, :hover#img1, :hover#map2, :hover#d, :hover#img2, :hover#e, :hover#f, :hover#g, :hover#h, :hover#i, :hover#j, :hover#k, :hover#l, :hover#m, :hover#n, :hover#o, :hover#a_ancestor, :hover#table, :hover#tbody, :hover#tr, :hover#td, :hover#body, :hover#html', prop:'max-height', value:'10000px'},
+ // class selector
+ {input:'.t:active, .x:active', prop:'cursor', value:'move'},
+ {input:'.t:hover, .x:hover', prop:'empty-cells', value:'hide'},
+ {input:':active.t, :active.x', prop:'max-width', value:'10000px'},
+ {input:':hover.t, :hover.x', prop:'min-height', value:'1px'},
+ // pseudo-class selector
+ {input:':lang(en):active', prop:'font-style', value:'italic'},
+ {input:':lang(en):hover', prop:'font-variant', value:'small-caps'},
+ {input:':active:lang(en)', prop:'min-width', value:'1px'},
+ {input:':hover:lang(en)', prop:'overflow', value:'hidden'},
+ // pseudo-element selector
+ {input:':active::before', prop:'top', value:'1px', pseudoElt:'::before'},
+ {input:':hover::before', prop:'right', value:'1px', pseudoElt:'::before'},
+ {input:':active::after', prop:'bottom', value:'1px', pseudoElt:'::after'},
+ {input:':hover::after', prop:'left', value:'1px', pseudoElt:'::after'},
+ // as argument
+ //{input:':matches(:active)', prop:'font-weight', value:'bold'},
+ //{input:':matches(:hover)', prop:'list-style-position', value:'inside'},
+ ];
+
+ var stylesheet = '';
+ function serialize(t) {
+ return t.input + '{' + t.prop + ':' + t.value + '}';
+ }
+
+ links_only.concat(any_elm).forEach(function(t) {
+ stylesheet += serialize(t);
+ });
+ var html = document.getElementById('html_tmpl').textContent.replace('{style}', stylesheet);
+ var a_doctype = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">';
+ var s_doctype = '<!DOCTYPE HTML>';
+ var q = document.getElementById('quirks').contentWindow;
+ var a = document.getElementById('almost').contentWindow;
+ var s = document.getElementById('standards').contentWindow;
+ q.document.open();
+ q.document.write(html);
+ q.document.close();
+ a.document.open();
+ a.document.write(a_doctype + html);
+ a.document.close();
+ s.document.open();
+ s.document.write(s_doctype + html);
+ s.document.close();
+ q.mode = 'quirks';
+ a.mode = 'almost';
+ s.mode = 'standards';
+ [q, a, s].forEach(function(win) {
+ win.onmousedown = win.onmouseup = run_tests;
+ win.onclick = function(e) {
+ e.preventDefault();
+ };
+ });
+ var test_count = 0;
+ var total_test_count = q.document.querySelectorAll('.t').length * 3;
+
+ function check_matches(id, win, elm, t, expectMatch) {
+ var prefix = id + ', ' + win.mode + ': ';
+
+ // .getComputedStyle can be checked both for pseudo-elements and normal elements
+ test(function() {
+ assert_equals(win.getComputedStyle(elm, t.pseudoElt).getPropertyValue(t.prop) === t.value, expectMatch);
+ }, prefix + 'getComputedStyle(' + elm.id + ') with selector ' + t.input);
+
+ // .matches doesn't work with pseudo-elements
+ if (!t.pseudoElt) {
+ test(function() {
+ assert_equals(elm.matches(t.input), expectMatch);
+ }, prefix + elm.id + '.matches("' + t.input + '")');
+ }
+ }
+
+ function run_tests(e) {
+ var elm = e.target;
+ if (elm.classList.contains('t') && !elm.classList.contains('done')) {
+ if (!elm.matches('.t:active')) {
+ return;
+ }
+ if (elm.tagName != 'AREA') {
+ elm.classList.add('done');
+ } else {
+ // For <area> we want to style the <img> instead.
+ if (elm.parentNode.nextElementSibling.tagName != 'IMG') {
+ throw new Error("<area>'s parent's next element sibling wasn't an <img>");
+ }
+ elm.parentNode.nextElementSibling.classList.add('done');
+ }
+ var id = elm.id;
+ var win = elm.ownerDocument.defaultView;
+ do {
+ if (win.mode === 'quirks') {
+ links_only.forEach(function(t) {
+ var elmIsLink = elm.matches('a[href], area[href], link[href]');
+ check_matches(id, win, elm, t, elmIsLink);
+ });
+ } else {
+ links_only.forEach(function(t) {
+ check_matches(id, win, elm, t, true);
+ });
+ }
+ any_elm.forEach(function(t) {
+ check_matches(id, win, elm, t, true);
+ });
+ } while (elm = elm.parentElement);
+ test_count++;
+ if (test_count === total_test_count) {
+ done();
+ }
+ }
+ }
+ }
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/quirks-mode/blocks-ignore-line-height.html b/tests/wpt/web-platform-tests/quirks-mode/blocks-ignore-line-height.html
new file mode 100644
index 00000000000..608a7c15c79
--- /dev/null
+++ b/tests/wpt/web-platform-tests/quirks-mode/blocks-ignore-line-height.html
@@ -0,0 +1,85 @@
+<!doctype html>
+<html>
+ <head>
+ <title>The blocks ignore line-height quirk</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <style> iframe { width:200px; height:20px; } </style>
+ </head>
+ <body>
+ <div id=log></div>
+ <iframe id=quirks></iframe>
+ <iframe id=almost></iframe>
+ <iframe id=standards></iframe>
+ <script>
+ setup({explicit_done:true});
+ onload = function() {
+ var html = "<style id=style></style>";
+ var a_doctype = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">';
+ var s_doctype = '<!DOCTYPE HTML>';
+ var q = document.getElementById('quirks').contentWindow;
+ var a = document.getElementById('almost').contentWindow;
+ var s = document.getElementById('standards').contentWindow;
+ q.document.open();
+ q.document.write(html);
+ q.document.close();
+ a.document.open();
+ a.document.write(a_doctype + html);
+ a.document.close();
+ s.document.open();
+ s.document.write(s_doctype + html);
+ s.document.close();
+ [q, a, s].forEach(function(win) {
+ ['style', 'test', 'ref', 's_ref'].forEach(function(id) {
+ win.__proto__.__defineGetter__(id, function() { return win.document.getElementById(id); });
+ });
+ });
+
+ var tests = [
+ {style:'#ref { display:block }', body:
+ '<div id=test><font size=1>x</font></div>'+
+ '<font id=ref size=1>x</font>'+
+ '<div id=s_ref>x</div>'},
+
+ {style:'#ref { display:block }', body:
+ '<div id=test><font size=1>x</font><br><font size=1>x</font></div>'+
+ '<font id=ref size=1>x<br>x</font>'+
+ '<div id=s_ref>x<br>x</div>'},
+
+ {style:'#ref { display:block }', body:
+ '<div id=test><font size=1>foo</font><br><font size=1>foo</font><div>x</div></div>'+
+ '<font id=ref size=1>foo<br>foo<br><font size=3>x</font></font>'+
+ '<div id=s_ref>x<br>x<br>x</div>'},
+
+ {style:'#ref { display:block } div, #ref { line-height:2 } span { font-size:50% }', body:
+ '<div id=test><span>x</span></div>'+
+ '<span id=ref>x</span>'+
+ '<div id=s_ref>x</div>'},
+ ];
+
+ tests.forEach(function(t) {
+ test(function() {
+ q.style.textContent = t.style;
+ a.style.textContent = t.style;
+ s.style.textContent = t.style;
+ q.document.body.innerHTML = t.body;
+ a.document.body.innerHTML = t.body;
+ s.document.body.innerHTML = t.body;
+
+ assert_equals(q.getComputedStyle(q.test).height,
+ q.getComputedStyle(q.ref).height,
+ 'quirks mode');
+ assert_equals(a.getComputedStyle(a.test).height,
+ a.getComputedStyle(a.ref).height,
+ 'almost standards mode');
+ assert_equals(s.getComputedStyle(s.test).height,
+ s.getComputedStyle(s.s_ref).height,
+ 'standards mode');
+ }, document.title+', '+t.style+t.body);
+ });
+
+ done();
+ }
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/quirks-mode/font-element-text-decoration-color/001-a.html b/tests/wpt/web-platform-tests/quirks-mode/font-element-text-decoration-color/001-a.html
new file mode 100644
index 00000000000..c8ed1903fd8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/quirks-mode/font-element-text-decoration-color/001-a.html
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<link rel=match href=001-ref.html>
+<title>The font element text decoration color quirk, 001, almost standards mode</title>
+<style>[id] > * { color:fuchsia }</style>
+<div>Quirk should apply:</div>
+<div><u>foo <font style="color:fuchsia">style</font> bar</u></div>
+<div><u>foo <font color="fuchsia">color</font> bar</u></div>
+<div><u>foo <font color="fuchsia" style="color:fuchsia">color and style</font> bar</u></div>
+<div><u>foo <font color="x" style="color:fuchsia">color=x and style</font> bar</u></div>
+<div><u>foo <font color="transparent" style="color:fuchsia">color=transparent and style</font> bar</u></div>
+<div><u>foo <font color="" style="color:fuchsia">color="" and style</font> bar</u></div>
+<div><u>foo <font style="display:block; color:fuchsia">block</font> bar</u></div>
+<div><s>foo <font color="fuchsia">line-through</font> bar</s></div>
+<div><u style="text-decoration:overline">foo <font color="fuchsia">overline</font> bar</u></div>
+<div>Quirks should not apply:</div>
+<div><u>foo <span style="color:fuchsia">span</span> bar</u></div>
+<div><u id="no-namespace">FAIL (script didn't run)</u></div>
+<script>
+var a = document.getElementById('no-namespace');
+a.textContent = 'foo ';
+var elm = document.createElementNS('', 'font');
+elm.textContent = 'no-namespace font element';
+a.appendChild(elm);
+a.appendChild(document.createTextNode(' bar'));
+</script>
+<div><u id="uppercase">FAIL (script didn't run)</u></div>
+<script>
+var a = document.getElementById('uppercase');
+a.textContent = 'foo ';
+var elm = document.createElementNS('http://www.w3.org/1999/xhtml', 'FONT');
+elm.textContent = 'uppercase FONT element';
+a.appendChild(elm);
+a.appendChild(document.createTextNode(' bar'));
+</script>
diff --git a/tests/wpt/web-platform-tests/quirks-mode/font-element-text-decoration-color/001-q.html b/tests/wpt/web-platform-tests/quirks-mode/font-element-text-decoration-color/001-q.html
new file mode 100644
index 00000000000..9025e728991
--- /dev/null
+++ b/tests/wpt/web-platform-tests/quirks-mode/font-element-text-decoration-color/001-q.html
@@ -0,0 +1,33 @@
+<link rel=match href=001-ref.html>
+<title>The font element text decoration color quirk, 001, quirks mode</title>
+<style>[id] > * { color:fuchsia }</style>
+<div>Quirk should apply:</div>
+<div><u>foo <font style="color:fuchsia">style</font> bar</u></div>
+<div><u>foo <font color="fuchsia">color</font> bar</u></div>
+<div><u>foo <font color="fuchsia" style="color:fuchsia">color and style</font> bar</u></div>
+<div><u>foo <font color="x" style="color:fuchsia">color=x and style</font> bar</u></div>
+<div><u>foo <font color="transparent" style="color:fuchsia">color=transparent and style</font> bar</u></div>
+<div><u>foo <font color="" style="color:fuchsia">color="" and style</font> bar</u></div>
+<div><u>foo <font style="display:block; color:fuchsia">block</font> bar</u></div>
+<div><s>foo <font color="fuchsia">line-through</font> bar</s></div>
+<div><u style="text-decoration:overline">foo <font color="fuchsia">overline</font> bar</u></div>
+<div>Quirks should not apply:</div>
+<div><u>foo <span style="color:fuchsia">span</span> bar</u></div>
+<div><u id="no-namespace">FAIL (script didn't run)</u></div>
+<script>
+var a = document.getElementById('no-namespace');
+a.textContent = 'foo ';
+var elm = document.createElementNS('', 'font');
+elm.textContent = 'no-namespace font element';
+a.appendChild(elm);
+a.appendChild(document.createTextNode(' bar'));
+</script>
+<div><u id="uppercase">FAIL (script didn't run)</u></div>
+<script>
+var a = document.getElementById('uppercase');
+a.textContent = 'foo ';
+var elm = document.createElementNS('http://www.w3.org/1999/xhtml', 'FONT');
+elm.textContent = 'uppercase FONT element';
+a.appendChild(elm);
+a.appendChild(document.createTextNode(' bar'));
+</script>
diff --git a/tests/wpt/web-platform-tests/quirks-mode/font-element-text-decoration-color/001-ref.html b/tests/wpt/web-platform-tests/quirks-mode/font-element-text-decoration-color/001-ref.html
new file mode 100644
index 00000000000..a6fec366db2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/quirks-mode/font-element-text-decoration-color/001-ref.html
@@ -0,0 +1,21 @@
+<title>Reference for The font element text decoration color quirk, 001</title>
+<style>
+span, div > div { color:fuchsia }
+.under { text-decoration:underline }
+.over { text-decoration:overline }
+.strike { text-decoration:line-through }
+</style>
+<div>Quirk should apply:</div>
+<div><u>foo </u><span class="under">style</span><u> bar</u></div>
+<div><u>foo </u><span class="under">color</span><u> bar</u></div>
+<div><u>foo </u><span class="under">color and style</span><u> bar</u></div>
+<div><u>foo </u><span class="under">color=x and style</span><u> bar</u></div>
+<div><u>foo </u><span class="under">color=transparent and style</span><u> bar</u></div>
+<div><u>foo </u><span class="under">color="" and style</span><u> bar</u></div>
+<div><u>foo</u><div class="under">block</div><u>bar</u></div>
+<div><s>foo </s><span class="strike">line-through</span><s> bar</s></div>
+<div><u class="over">foo </u><span class="over">overline</span><u class="over"> bar</u></div>
+<div>Quirks should not apply:</div>
+<div><u>foo <span>span</span> bar</u></div>
+<div><u>foo <span>no-namespace font element</span> bar</u></div>
+<div><u>foo <span>uppercase FONT element</span> bar</u></div>
diff --git a/tests/wpt/web-platform-tests/quirks-mode/font-element-text-decoration-color/001-s.html b/tests/wpt/web-platform-tests/quirks-mode/font-element-text-decoration-color/001-s.html
new file mode 100644
index 00000000000..bac80e53bae
--- /dev/null
+++ b/tests/wpt/web-platform-tests/quirks-mode/font-element-text-decoration-color/001-s.html
@@ -0,0 +1,34 @@
+<!doctype html>
+<link rel=match href=001-ref.html>
+<title>The font element text decoration color quirk, 001, standards mode</title>
+<style>[id] > * { color:fuchsia }</style>
+<div>Quirk should apply:</div>
+<div><u>foo <font style="color:fuchsia">style</font> bar</u></div>
+<div><u>foo <font color="fuchsia">color</font> bar</u></div>
+<div><u>foo <font color="fuchsia" style="color:fuchsia">color and style</font> bar</u></div>
+<div><u>foo <font color="x" style="color:fuchsia">color=x and style</font> bar</u></div>
+<div><u>foo <font color="transparent" style="color:fuchsia">color=transparent and style</font> bar</u></div>
+<div><u>foo <font color="" style="color:fuchsia">color="" and style</font> bar</u></div>
+<div><u>foo <font style="display:block; color:fuchsia">block</font> bar</u></div>
+<div><s>foo <font color="fuchsia">line-through</font> bar</s></div>
+<div><u style="text-decoration:overline">foo <font color="fuchsia">overline</font> bar</u></div>
+<div>Quirks should not apply:</div>
+<div><u>foo <span style="color:fuchsia">span</span> bar</u></div>
+<div><u id="no-namespace">FAIL (script didn't run)</u></div>
+<script>
+var a = document.getElementById('no-namespace');
+a.textContent = 'foo ';
+var elm = document.createElementNS('', 'font');
+elm.textContent = 'no-namespace font element';
+a.appendChild(elm);
+a.appendChild(document.createTextNode(' bar'));
+</script>
+<div><u id="uppercase">FAIL (script didn't run)</u></div>
+<script>
+var a = document.getElementById('uppercase');
+a.textContent = 'foo ';
+var elm = document.createElementNS('http://www.w3.org/1999/xhtml', 'FONT');
+elm.textContent = 'uppercase FONT element';
+a.appendChild(elm);
+a.appendChild(document.createTextNode(' bar'));
+</script>
diff --git a/tests/wpt/web-platform-tests/quirks-mode/font-element-text-decoration-color/001-x.xhtml b/tests/wpt/web-platform-tests/quirks-mode/font-element-text-decoration-color/001-x.xhtml
new file mode 100644
index 00000000000..7a5090c366b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/quirks-mode/font-element-text-decoration-color/001-x.xhtml
@@ -0,0 +1,23 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<link rel="match" href="001-ref.html"/>
+<title>The font element text decoration color quirk, 001, XHTML</title>
+<style>[id] > * { color:fuchsia }</style>
+</head>
+<body>
+<div>Quirk should apply:</div>
+<div><u>foo <font style="color:fuchsia">style</font> bar</u></div>
+<div><u>foo <font color="fuchsia">color</font> bar</u></div>
+<div><u>foo <font color="fuchsia" style="color:fuchsia">color and style</font> bar</u></div>
+<div><u>foo <font color="x" style="color:fuchsia">color=x and style</font> bar</u></div>
+<div><u>foo <font color="transparent" style="color:fuchsia">color=transparent and style</font> bar</u></div>
+<div><u>foo <font color="" style="color:fuchsia">color="" and style</font> bar</u></div>
+<div><u>foo <font style="display:block; color:fuchsia">block</font> bar</u></div>
+<div><s>foo <font color="fuchsia">line-through</font> bar</s></div>
+<div><u style="text-decoration:overline">foo <font color="fuchsia">overline</font> bar</u></div>
+<div>Quirks should not apply:</div>
+<div><u>foo <span style="color:fuchsia">span</span> bar</u></div>
+<div><u id="no-namespace">foo <font xmlns="">no-namespace font element</font> bar</u></div>
+<div><u id="uppercase">foo <FONT>uppercase FONT element</FONT> bar</u></div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/quirks-mode/hashless-hex-color.html b/tests/wpt/web-platform-tests/quirks-mode/hashless-hex-color.html
new file mode 100644
index 00000000000..8cac7d52926
--- /dev/null
+++ b/tests/wpt/web-platform-tests/quirks-mode/hashless-hex-color.html
@@ -0,0 +1,500 @@
+<!doctype html>
+<html>
+ <head>
+ <title>The hashless hex color quirk</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <style> iframe { width:20px; height:20px; } </style>
+ </head>
+ <body>
+ <div id=log></div>
+ <iframe id=quirks></iframe>
+ <iframe id=almost></iframe>
+ <iframe id=standards></iframe>
+ <script>
+ setup({explicit_done:true});
+ onload = function() {
+ var html = "<style id=style></style><div id=test></div><div id=ref></div><svg><circle id=svg /><circle id=svg_ref /></svg>";
+ var a_doctype = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">';
+ var s_doctype = '<!DOCTYPE HTML>';
+ var q = document.getElementById('quirks').contentWindow;
+ var a = document.getElementById('almost').contentWindow;
+ var s = document.getElementById('standards').contentWindow;
+ q.document.open();
+ q.document.write(html);
+ q.document.close();
+ a.document.open();
+ a.document.write(a_doctype + html);
+ a.document.close();
+ s.document.open();
+ s.document.write(s_doctype + html);
+ s.document.close();
+ [q, a, s].forEach(function(win) {
+ ['style', 'test', 'ref', 'svg', 'svg_ref'].forEach(function(id) {
+ win[id] = win.document.getElementById(id);
+ });
+ });
+
+ var tests = [
+ {input:"123", q:"#000123"},
+ {input:"023", q:"#000023"},
+ {input:"003", q:"#000003"},
+ {input:"000", q:"#000"},
+ {input:"abc", q:"#abc"},
+ {input:"ABC", q:"#abc"},
+ {input:"1ab", q:"#0001ab"},
+ {input:"1AB", q:"#0001ab"},
+ {input:"112233", q:"#123"},
+ {input:"012233", q:"#012233"},
+ {input:"002233", q:"#023"},
+ {input:"000233", q:"#000233"},
+ {input:"000033", q:"#003"},
+ {input:"000003", q:"#000003"},
+ {input:"000000", q:"#000000"},
+ {input:"aabbcc", q:"#abc"},
+ {input:"AABBCC", q:"#abc"},
+ {input:"11aabb", q:"#1ab"},
+ {input:"11AABB", q:"#1ab"},
+ {input:"\\31 23", q:"#123"},
+ {input:"\\61 bc", q:"#abc"},
+ {input:"\\41 BC", q:"#abc"},
+ {input:"\\31 ab", q:"#1ab"},
+ {input:"\\31 AB", q:"#1ab"},
+ {input:"\\31 12233", q:"#123"},
+ {input:"\\61 abbcc", q:"#abc"},
+ {input:"\\41 ABBCC", q:"#abc"},
+ {input:"\\31 1aabb", q:"#1ab"},
+ {input:"\\31 1AABB", q:"#1ab"},
+ {input:"12\\33 ", q:"#000123"},
+ {input:"1", q:"#000001"},
+ {input:"12", q:"#000012"},
+ {input:"1234", q:"#001234"},
+ {input:"12345", q:"#012345"},
+ {input:"1234567"},
+ {input:"12345678"},
+ {input:"a"},
+ {input:"aa"},
+ {input:"aaaa"},
+ {input:"aaaaa"},
+ {input:"aaaaaaa"},
+ {input:"aaaaaaaa"},
+ {input:"A"},
+ {input:"AA"},
+ {input:"AAAA"},
+ {input:"AAAAA"},
+ {input:"AAAAAAA"},
+ {input:"AAAAAAAA"},
+ {input:"1a", q:"#00001a"},
+ {input:"1abc", q:"#001abc"},
+ {input:"1abcd", q:"#01abcd"},
+ {input:"1abcdef"},
+ {input:"1abcdeff"},
+ {input:"+1", q:"#000001"},
+ {input:"+12", q:"#000012"},
+ {input:"+123", q:"#000123"},
+ {input:"+1234", q:"#001234"},
+ {input:"+12345", q:"#012345"},
+ {input:"+123456", q:"#123456"},
+ {input:"+1234567"},
+ {input:"+12345678"},
+ {input:"-1"},
+ {input:"-12"},
+ {input:"-123"},
+ {input:"-1234"},
+ {input:"-12345"},
+ {input:"-123456"},
+ {input:"-1234567"},
+ {input:"-12345678"},
+ {input:"+1a", q:"#00001a"},
+ {input:"+12a", q:"#00012a"},
+ {input:"+123a", q:"#00123a"},
+ {input:"+1234a", q:"#01234a"},
+ {input:"+12345a", q:"#12345a"},
+ {input:"+123456a"},
+ {input:"+1234567a"},
+ {input:"-1a"},
+ {input:"-12a"},
+ {input:"-123a"},
+ {input:"-1234a"},
+ {input:"-12345a"},
+ {input:"-123456a"},
+ {input:"-1234567a"},
+ {input:"-12345678a"},
+ {input:"+1A", q:"#00001a"},
+ {input:"+12A", q:"#00012a"},
+ {input:"+123A", q:"#00123a"},
+ {input:"+1234A", q:"#01234a"},
+ {input:"+12345A", q:"#12345a"},
+ {input:"+123456A"},
+ {input:"+1234567A"},
+ {input:"-1A"},
+ {input:"-12A"},
+ {input:"-123A"},
+ {input:"-1234A"},
+ {input:"-12345A"},
+ {input:"-123456A"},
+ {input:"-1234567A"},
+ {input:"-12345678A"},
+ {input:"+a"},
+ {input:"+aa"},
+ {input:"+aaa"},
+ {input:"+aaaa"},
+ {input:"+aaaaa"},
+ {input:"+aaaaaa"},
+ {input:"+aaaaaaa"},
+ {input:"+aaaaaaaa"},
+ {input:"-a"},
+ {input:"-aa"},
+ {input:"-aaa"},
+ {input:"-aaaa"},
+ {input:"-aaaaa"},
+ {input:"-aaaaaa"},
+ {input:"-aaaaaaa"},
+ {input:"-aaaaaaaa"},
+ {input:"-aaaaaaaaa"},
+ {input:"+A"},
+ {input:"+AA"},
+ {input:"+AAA"},
+ {input:"+AAAA"},
+ {input:"+AAAAA"},
+ {input:"+AAAAAA"},
+ {input:"+AAAAAAA"},
+ {input:"+AAAAAAAA"},
+ {input:"-A"},
+ {input:"-AA"},
+ {input:"-AAA"},
+ {input:"-AAAA"},
+ {input:"-AAAAA"},
+ {input:"-AAAAAA"},
+ {input:"-AAAAAAA"},
+ {input:"-AAAAAAAA"},
+ {input:"-AAAAAAAAA"},
+ {input:"1.1"},
+ {input:"1.11"},
+ {input:"1.111"},
+ {input:"1.1111"},
+ {input:"1.11111"},
+ {input:"1.111111"},
+ {input:"1.1111111"},
+ {input:"+1.1"},
+ {input:"+1.11"},
+ {input:"+1.111"},
+ {input:"+1.1111"},
+ {input:"+1.11111"},
+ {input:"+1.111111"},
+ {input:"+1.1111111"},
+ {input:"-1.1"},
+ {input:"-1.11"},
+ {input:"-1.111"},
+ {input:"-1.1111"},
+ {input:"-1.11111"},
+ {input:"-1.111111"},
+ {input:"-1.1111111"},
+ {input:"1.1a"},
+ {input:"1.11a"},
+ {input:"1.111a"},
+ {input:"1.1111a"},
+ {input:"1.11111a"},
+ {input:"1.111111a"},
+ {input:"+1.1a"},
+ {input:"+1.11a"},
+ {input:"+1.111a"},
+ {input:"+1.1111a"},
+ {input:"+1.11111a"},
+ {input:"+1.111111a"},
+ {input:"-1.1a"},
+ {input:"-1.11a"},
+ {input:"-1.111a"},
+ {input:"-1.1111a"},
+ {input:"-1.11111a"},
+ {input:"-1.111111a"},
+ {input:"1.0"},
+ {input:"11.0"},
+ {input:"111.0"},
+ {input:"1111.0"},
+ {input:"11111.0"},
+ {input:"111111.0"},
+ {input:"1111111.0"},
+ {input:"11111111.0"},
+ {input:"+1.0"},
+ {input:"+11.0"},
+ {input:"+111.0"},
+ {input:"+1111.0"},
+ {input:"+11111.0"},
+ {input:"+111111.0"},
+ {input:"+1111111.0"},
+ {input:"+11111111.0"},
+ {input:"-1.0"},
+ {input:"-11.0"},
+ {input:"-111.0"},
+ {input:"-1111.0"},
+ {input:"-11111.0"},
+ {input:"-111111.0"},
+ {input:"-1111111.0"},
+ {input:"-11111111.0"},
+ {input:"1.0a"},
+ {input:"11.0a"},
+ {input:"111.0a"},
+ {input:"1111.0a"},
+ {input:"11111.0a"},
+ {input:"111111.0a"},
+ {input:"1111111.0a"},
+ {input:"+1.0a"},
+ {input:"+11.0a"},
+ {input:"+111.0a"},
+ {input:"+1111.0a"},
+ {input:"+11111.0a"},
+ {input:"+111111.0a"},
+ {input:"+1111111.0a"},
+ {input:"-1.0a"},
+ {input:"-11.0a"},
+ {input:"-111.0a"},
+ {input:"-1111.0a"},
+ {input:"-11111.0a"},
+ {input:"-111111.0a"},
+ {input:"-1111111.0a"},
+ {input:"+/**/123"},
+ {input:"-/**/123"},
+ {input:"+/**/123456"},
+ {input:"-/**/123456"},
+ {input:"+/**/abc"},
+ {input:"-/**/abc"},
+ {input:"+/**/abcdef"},
+ {input:"-/**/abcdef"},
+ {input:"+/**/12a"},
+ {input:"-/**/12a"},
+ {input:"+/**/12345a"},
+ {input:"-/**/12345a"},
+ {input:"abg"},
+ {input:"aabbcg"},
+ {input:"1ag"},
+ {input:"1122ag"},
+ {input:"ABG"},
+ {input:"AABBCG"},
+ {input:"1AG"},
+ {input:"1122AG"},
+ {input:"@a"},
+ {input:"@ab"},
+ {input:"@abc"},
+ {input:"@abcd"},
+ {input:"@abcde"},
+ {input:"@abcdef"},
+ {input:"@1"},
+ {input:"@11"},
+ {input:"@111"},
+ {input:"@1111"},
+ {input:"@11111"},
+ {input:"@111111"},
+ {input:"@1a"},
+ {input:"@11a"},
+ {input:"@111a"},
+ {input:"@1111a"},
+ {input:"@11111a"},
+ {input:'"a"'},
+ {input:'"ab"'},
+ {input:'"abc"'},
+ {input:'"abcd"'},
+ {input:'"abcde"'},
+ {input:'"abcdef"'},
+ {input:'"1"'},
+ {input:'"11"'},
+ {input:'"111"'},
+ {input:'"1111"'},
+ {input:'"11111"'},
+ {input:'"111111"'},
+ {input:'"1a"'},
+ {input:'"11a"'},
+ {input:'"111a"'},
+ {input:'"1111a"'},
+ {input:'"11111a"'},
+ {input:"url(a)", svg:'url(a)'},
+ {input:"url(aa)", svg:'url(aa)'},
+ {input:"url(aaa)", svg:'url(aaa)'},
+ {input:"url(aaaa)", svg:'url(aaaa)'},
+ {input:"url(aaaaa)", svg:'url(aaaaa)'},
+ {input:"url(aaaaaa)", svg:'url(aaaaaa)'},
+ {input:"url('a')", svg:'url(a)'},
+ {input:"url('aa')", svg:'url(aa)'},
+ {input:"url('aaa')", svg:'url(aaa)'},
+ {input:"url('aaaa')", svg:'url(aaaa)'},
+ {input:"url('aaaaa')", svg:'url(aaaaa)'},
+ {input:"url('aaaaaa')", svg:'url(aaaaaa)'},
+ {input:"#a"},
+ {input:"#aa"},
+ {input:"#aaaa"},
+ {input:"#aaaaa"},
+ {input:"#aaaaaaa"},
+ {input:"#1"},
+ {input:"#11"},
+ {input:"#1111"},
+ {input:"#11111"},
+ {input:"#1111111"},
+ {input:"#1a"},
+ {input:"#111a"},
+ {input:"#1111a"},
+ {input:"#111111a"},
+ {input:"1%"},
+ {input:"11%"},
+ {input:"111%"},
+ {input:"1111%"},
+ {input:"11111%"},
+ {input:"111111%"},
+ {input:"calc(123)"},
+ {input:"rgb(119, 255, 255)", q:"#7ff", s:"#7ff", svg:"#7ff"},
+ {input:"rgba(119, 255, 255, 001)", q:"#7ff", s:"#7ff", svg:"#7ff"},
+ {input:"hsl(100, 100%, 100%)", q:"#fff", s:"#fff", svg:"#fff"},
+ {input:"hsla(100, 100%, 100%, 001)", q:"#fff", s:"#fff", svg:"#fff"},
+ {input:"rgb(calc(100 + 155), 255, 255)", q:"#fff", s:"#fff", svg:"#fff"},
+ {input:"rgba(calc(100 + 155), 255, 255, 001)", q:"#fff", s:"#fff", svg:"#fff"},
+ {input:"hsl(calc(050 + 050), 100%, 100%)", q:"#fff", s:"#fff", svg:"#fff"},
+ {input:"hsla(calc(050 + 050), 100%, 100%, 001)", q:"#fff", s:"#fff", svg:"#fff"},
+ {input:"rgb(/**/255, 255, 255)", q:"#fff", s:"#fff", svg:"#fff"},
+ {input:"rgb(/**/255/**/, /**/255/**/, /**/255/**/)", q:"#fff", s:"#fff", svg:"#fff"},
+ {input:"rgb(calc(/**/100/**/ + /**/155/**/), 255, 255)", q:"#fff", s:"#fff", svg:"#fff"},
+ {input:"#123 123 abc 12a", q:"#123 #000123 #abc #00012a", shorthand:true},
+ {input:"rgb(119, 255, 255) 123", q:"#7ff #000123", shorthand:true},
+ {input:"123 rgb(119, 255, 255)", q:"#000123 #7ff", shorthand:true},
+ {input:"1e1"},
+ {input:"11e1"},
+ {input:"111e1"},
+ {input:"1111e1"},
+ {input:"11111e1"},
+ {input:"111111e1"},
+ {input:"1e+1"},
+ {input:"11e+1"},
+ {input:"111e+1"},
+ {input:"1111e+1"},
+ {input:"11111e+1"},
+ {input:"111111e+1"},
+ {input:"1e-0"},
+ {input:"11e-0"},
+ {input:"111e-0"},
+ {input:"1111e-0"},
+ {input:"11111e-0"},
+ {input:"111111e-0"},
+ {input:"1e1a"},
+ {input:"11e1a"},
+ {input:"111e1a"},
+ {input:"1111e1a"},
+ {input:"11111e1a"},
+ {input:"111111e1a"},
+ {desc:"1111111111...", input:"1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"},
+ {desc:"1111111111...a", input:"1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111a"},
+ {desc:"a1111111111...", input:"a1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"},
+ ];
+
+ var props = [
+ {prop:'background-color', check:'background-color'},
+ {prop:'border-color', check:'border-top-color', check_also:['border-right-color', 'border-bottom-color', 'border-left-color']},
+ {prop:'border-top-color', check:'border-top-color'},
+ {prop:'border-right-color', check:'border-right-color'},
+ {prop:'border-bottom-color', check:'border-bottom-color'},
+ {prop:'border-left-color', check:'border-left-color'},
+ {prop:'color', check:'color'},
+ ];
+ var style_template = '#test{{prop}:{test};}' +
+ '#ref{{prop}:{ref};}';
+
+ tests.forEach(function(t) {
+ var name = t.desc || t.input;
+ var test_q = async_test(name + ' (quirks)');
+ var test_a = async_test(name + ' (almost standards)');
+ var test_s = async_test(name + ' (standards)');
+ var test_svg = async_test(name + ' (SVG)');
+ for (var i in props) {
+ if (t.shorthand && !(props[i].check_also)) {
+ continue;
+ }
+ test_q.step(function() {
+ q.style.textContent = style_template.replace('{test}', t.input)
+ .replace('{ref}', t.q).replace(/\{prop\}/g, props[i].prop);
+ assert_equals(q.getComputedStyle(q.test).getPropertyValue(props[i].check),
+ q.getComputedStyle(q.ref).getPropertyValue(props[i].check),
+ props[i].prop);
+ if (t.shorthand && props[i].check_also) {
+ for (var j in props[i].check_also) {
+ assert_equals(q.getComputedStyle(q.test).getPropertyValue(props[i].check_also[j]),
+ q.getComputedStyle(q.ref).getPropertyValue(props[i].check_also[j]),
+ props[i].prop + ' checking ' + props[i].check_also[j]);
+ }
+ }
+ });
+ test_a.step(function() {
+ a.style.textContent = style_template.replace('{test}', t.input)
+ .replace('{ref}', t.s).replace(/\{prop\}/g, props[i].prop);
+ assert_equals(a.getComputedStyle(a.test).getPropertyValue(props[i].check),
+ a.getComputedStyle(a.ref).getPropertyValue(props[i].check),
+ props[i].prop);
+ if (t.shorthand && props[i].check_also) {
+ for (var j in props[i].check_also) {
+ assert_equals(a.getComputedStyle(q.test).getPropertyValue(props[i].check_also[j]),
+ a.getComputedStyle(q.ref).getPropertyValue(props[i].check_also[j]),
+ props[i].prop + ' checking ' + props[i].check_also[j]);
+ }
+ }
+ });
+ test_s.step(function() {
+ s.style.textContent = style_template.replace('{test}', t.input)
+ .replace('{ref}', t.s).replace(/\{prop\}/g, props[i].prop);
+ assert_equals(s.getComputedStyle(s.test).getPropertyValue(props[i].check),
+ s.getComputedStyle(s.ref).getPropertyValue(props[i].check),
+ props[i].prop);
+ if (t.shorthand && props[i].check_also) {
+ for (var j in props[i].check_also) {
+ assert_equals(s.getComputedStyle(q.test).getPropertyValue(props[i].check_also[j]),
+ s.getComputedStyle(q.ref).getPropertyValue(props[i].check_also[j]),
+ props[i].prop + ' checking ' + props[i].check_also[j]);
+ }
+ }
+ });
+ test_svg.step(function() {
+ q.svg.setAttribute('fill', t.input);
+ a.svg.setAttribute('fill', t.input);
+ s.svg.setAttribute('fill', t.input);
+ if (t.svg) {
+ q.svg_ref.setAttribute('fill', t.svg);
+ a.svg_ref.setAttribute('fill', t.svg);
+ s.svg_ref.setAttribute('fill', t.svg);
+ } else {
+ q.svg_ref.removeAttribute('fill');
+ a.svg_ref.removeAttribute('fill');
+ s.svg_ref.removeAttribute('fill');
+ }
+ assert_equals(q.getComputedStyle(q.svg).fill, q.getComputedStyle(q.svg_ref).fill, 'SVG fill="" in quirks mode');
+ assert_equals(a.getComputedStyle(a.svg).fill, a.getComputedStyle(a.svg_ref).fill, 'SVG fill="" in almost standards mode');
+ assert_equals(s.getComputedStyle(s.svg).fill, s.getComputedStyle(s.svg_ref).fill, 'SVG fill="" in standards mode');
+ });
+ }
+ test_q.done();
+ test_a.done();
+ test_s.done();
+ test_svg.done();
+ });
+
+ var other_tests = [
+ {input:'background:abc', prop:'background-color'},
+ {input:'border-top:1px solid abc', prop:'border-top-color'},
+ {input:'border-right:1px solid abc', prop:'border-right-color'},
+ {input:'border-bottom:1px solid abc', prop:'border-bottom-color'},
+ {input:'border-left:1px solid abc', prop:'border-left-color'},
+ {input:'border:1px solid abc', prop:'border-top-color'},
+ {input:'outline-color:abc', prop:'outline-color'},
+ {input:'outline:1px solid abc', prop:'outline-color'}
+ ];
+
+ var other_template = "#test{{test};}"
+
+ other_tests.forEach(function(t) {
+ test(function() {
+ q.style.textContent = other_template.replace('{test}', t.input);
+ assert_equals(q.getComputedStyle(q.test).getPropertyValue(t.prop),
+ q.getComputedStyle(q.ref).getPropertyValue(t.prop),
+ 'quirk was supported');
+ }, document.title+', excluded property '+t.input);
+ });
+
+ done();
+ }
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/quirks-mode/line-height-calculation.html b/tests/wpt/web-platform-tests/quirks-mode/line-height-calculation.html
new file mode 100644
index 00000000000..c9289ce31cb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/quirks-mode/line-height-calculation.html
@@ -0,0 +1,94 @@
+<!doctype html>
+<html>
+ <head>
+ <title>The line height calculation quirk</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <style> iframe { width:200px; height:20px; } </style>
+ </head>
+ <body>
+ <div id=log></div>
+ <iframe id=quirks></iframe>
+ <iframe id=almost></iframe>
+ <iframe id=standards></iframe>
+ <script>
+ setup({explicit_done:true});
+ onload = function() {
+ var html = "<style id=style></style>";
+ var png = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg==";
+ var preload = new Image();
+ preload.src = png;
+ var a_doctype = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">';
+ var s_doctype = '<!DOCTYPE HTML>';
+ var q = document.getElementById('quirks').contentWindow;
+ var a = document.getElementById('almost').contentWindow;
+ var s = document.getElementById('standards').contentWindow;
+ q.document.open();
+ q.document.write(html);
+ q.document.close();
+ a.document.open();
+ a.document.write(a_doctype + html);
+ a.document.close();
+ s.document.open();
+ s.document.write(s_doctype + html);
+ s.document.close();
+ [q, a, s].forEach(function(win) {
+ ['style', 'test', 'ref', 's_ref'].forEach(function(id) {
+ win.__proto__.__defineGetter__(id, function() { return win.document.getElementById(id); });
+ });
+ });
+
+ var tests = [
+ {style:'', body:'<div id=test><img src="{png}"></div><img id=ref src="{png}"><div id=s_ref>x</div>'},
+ {style:'', body:'<div id=test><img src="{png}"> <img src="{png}"></div><div id=ref>x</div><div id=s_ref>x</div>'},
+ {style:'', body:'<table><tr><td id=test><img src="{png}"><tr><td><img id=ref src="{png}"><tr><td id=s_ref>x</table>'},
+ {style:'', body:'<table><tr><td id=test><img src="{png}"> <img src="{png}"><tr><td id=ref>x<tr><td id=s_ref>x</table>'},
+ {style:'', body:'<pre id=test><img src="{png}"></pre><img id=ref src="{png}"><pre id=s_ref>x</pre>'},
+ {style:'', body:'<pre id=test><img src="{png}"> </pre><pre id=ref>x</pre><pre id=s_ref>x</pre>'},
+ {style:'span { margin:1px }', body:'<div id=test><span></span></div><div id=ref></div><div id=s_ref>x</div>'},
+ {style:'span { padding:1px 0 }', body:'<div id=test><span></span></div><div id=ref></div><div id=s_ref></div>'},
+ {style:'span { margin:0 1px }', body:'<div id=test><span></span></div><div id=ref></div><div id=s_ref>x</div>'},
+ {style:'span { margin:0 1px; padding:1px 0 }', body:'<div id=test><span></span></div><div id=ref></div><div id=s_ref>x</div>'},
+ {style:'span { border-width:1px 0; border-style:solid }', body:'<div id=test><span></span></div><div id=ref></div><div id=s_ref></div>'},
+ {style:'span { border-width:1px; border-style:solid none }', body:'<div id=test><span></span></div><div id=ref></div><div id=s_ref></div>'},
+ {style:'span { border-width:1px; border-style:solid hidden }', body:'<div id=test><span></span></div><div id=ref></div><div id=s_ref></div>'},
+ {style:'span { border-right:1px solid }', body:'<div id=test><span></span></div><div id=ref>x</div><div id=s_ref>x</div>'},
+ {style:'span { border-left:1px solid }', body:'<div id=test><span></span></div><div id=ref>x</div><div id=s_ref>x</div>'},
+ {style:'span { padding-right:1px }', body:'<div id=test><span></span></div><div id=ref>x</div><div id=s_ref>x</div>'},
+ {style:'span { padding-left:1px }', body:'<div id=test><span></span></div><div id=ref>x</div><div id=s_ref>x</div>'},
+ {style:'span { display:inline-block; height:1px }', body:'<div id=test><i><span></span> </i></div><span id=ref></span><div id=s_ref>x</div>'}, /* 16.6.1: "If a space (U+0020) at the end of a line has 'white-space' set to 'normal', 'nowrap', or 'pre-line', it is also removed." */
+ {style:'', body:'<div id=test><img src="{png}" border=1></div><img id=ref src="{png}" height=3><div id=s_ref>x</div>'},
+ {style:'#test img { padding:1px }', body:'<div id=test><img src="{png}"></div><img id=ref src="{png}" height=3><div id=s_ref>x</div>'},
+ {style:'iframe { height:1px }', body:'<div id=test><iframe></iframe></div><img id=ref src="{png}" height=5><div id=s_ref>x</div>'},
+ {style:'#test::before { content:"" } #test::before, span { border:solid }', body:'<div id=test></div><div id=ref><span>x</span></div><div id=s_ref><span>x</span></div>'},
+ {style:'div { line-height: 0;} span { margin:0 1px; line-height: normal; }', body:'<div id=test>x<span></span></div><div id=ref>x</div><div id=s_ref>x<span>x</span></div>'},
+ ];
+
+ tests.forEach(function(t) {
+ test(function() {
+ var style = t.style.replace(/\{png\}/g, png);
+ var body = t.body.replace(/\{png\}/g, png);
+ q.style.textContent = style;
+ a.style.textContent = style;
+ s.style.textContent = style;
+ q.document.body.innerHTML = body;
+ a.document.body.innerHTML = body;
+ s.document.body.innerHTML = body;
+
+ assert_equals(q.getComputedStyle(q.test).height,
+ q.getComputedStyle(q.ref).height,
+ 'quirks mode');
+ assert_equals(a.getComputedStyle(a.test).height,
+ a.getComputedStyle(a.ref).height,
+ 'almost standards mode');
+ assert_equals(s.getComputedStyle(s.test).height,
+ s.getComputedStyle(s.s_ref).height,
+ 'standards mode');
+ }, document.title+', '+t.style+t.body);
+ });
+
+ done();
+ }
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/quirks-mode/percentage-height-calculation.html b/tests/wpt/web-platform-tests/quirks-mode/percentage-height-calculation.html
new file mode 100644
index 00000000000..03aae3f3e21
--- /dev/null
+++ b/tests/wpt/web-platform-tests/quirks-mode/percentage-height-calculation.html
@@ -0,0 +1,142 @@
+<!doctype html>
+<html>
+ <head>
+ <title>The percentage height calculation quirk</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <style> iframe { width:20px; height:200px } </style>
+ </head>
+ <body>
+ <div id=log></div>
+ <iframe id=quirks></iframe>
+ <iframe id=almost></iframe>
+ <iframe id=standards></iframe>
+ <script>
+ setup({explicit_done:true});
+ onload = function() {
+ var html = "<style id=style></style>";
+ var png = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg==";
+ var a_doctype = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">';
+ var s_doctype = '<!DOCTYPE HTML>';
+ var q = document.getElementById('quirks').contentWindow;
+ var a = document.getElementById('almost').contentWindow;
+ var s = document.getElementById('standards').contentWindow;
+ q.document.open();
+ q.document.write(html);
+ q.document.close();
+ a.document.open();
+ a.document.write(a_doctype + html);
+ a.document.close();
+ s.document.open();
+ s.document.write(s_doctype + html);
+ s.document.close();
+ [q, a, s].forEach(function(win) {
+ ['style', 'test'].forEach(function(id) {
+ win.__proto__.__defineGetter__(id, function() { return win.document.getElementById(id); });
+ });
+ });
+
+ var tests = [
+ {style:'#test { height:100% }', body:'<div id=test></div>', q:184, s:0},
+ {style:'#test { height:50% }', body:'<div id=test></div>', q:92, s:0},
+ {style:'#test { height:25% }', body:'<div id=test></div>', q:46, s:0},
+ {style:'#test { height:12.5% }', body:'<div id=test></div>', q:23, s:0},
+ {style:'#test { height:100% }', body:'<div><div id=test></div></div>', q:184, s:0},
+ {style:'', body:'<img id=test src="{png}" height=100%>', q:184, s:1},
+ {style:'', body:'<img id=test src="{png}" height=100% border=10>', q:184, s:1},
+ {style:'', body:'<table id=test height=100%><tr><td></table>', q:184, s:6},
+ {style:'#foo { height:100px } #test { height:100% }', body:'<div id=foo><div><div id=test></div></div></div>', q:100, s:0},
+ {style:'#foo { position:absolute } #test { height:100% }', body:'<div id=foo><div><div id=test></div></div></div>', q:0, s:0},
+ {style:'#foo { position:relative } #test { height:100% }', body:'<div id=foo><div><div id=test></div></div></div>', q:184, s:0},
+ {style:'#foo { height:100px } #test { height:100%; position:absolute }', body:'<div id=foo><div><div id=test></div></div></div>', q:200, s:200},
+ {style:'#foo { height:100px } #test { height:100%; position:fixed }', body:'<div id=foo><div><div id=test></div></div></div>', q:200, s:200},
+ {style:'#foo { height:100px } #test { height:100%; position:relative }', body:'<div id=foo><div><div id=test></div></div></div>', q:100, s:0},
+ {style:'#foo { height:100px } #test { height:calc(100% + 1px) }', body:'<div id=foo><div id=test></div></div>', q:101, s:101},
+ {style:'#foo { height:100px } #test { height:5px; height:calc(100% + 1px) }', body:'<div id=foo><div><div id=test></div></div></div>', q:0, s:0},
+ {style:'html { display:inline } #test { height:100% }', body:'<div id=test></div>', q:184, s:0}, // display:inline on root has no effect
+ {style:'html { margin:10px } body { display:inline } #test { height:100% }', body:'<div id=test></div>', q:200, s:0},
+ {style:'body { margin:0 } #test { height:100% }', body:'<div id=test></div>', q:200, s:0},
+ {style:'body { margin:0; padding:10px } #test { height:100% }', body:'<div id=test></div>', q:180, s:0},
+ {style:'body { margin:0; border:10px solid } #test { height:100% }', body:'<div id=test></div>', q:180, s:0},
+ {style:'html { margin:10px } #test { height:100% }', body:'<div id=test></div>', q:164, s:0},
+ {style:'html { padding:10px } #test { height:100% }', body:'<div id=test></div>', q:164, s:0},
+ {style:'html { border:10px solid } #test { height:100% }', body:'<div id=test></div>', q:164, s:0},
+ {style:'html { position:absolute } #test { height:100% }', body:'<div id=test></div>', q:0, s:0},
+ {style:'body { position:absolute } #test { height:100% }', body:'<div id=test></div>', q:0, s:0},
+ {style:'html { height:100%; margin:10px } #test { height:100% }', body:'<div id=test></div>', q:184, s:0},
+ {style:'html { height:100%; padding:10px } #test { height:100% }', body:'<div id=test></div>', q:184, s:0},
+ {style:'html { height:100%; border:10px solid } #test { height:100% }', body:'<div id=test></div>', q:184, s:0},
+ {style:'body { height:100%; margin:10px } #test { height:100% }', body:'<div id=test></div>', q:200, s:0},
+ {style:'body { height:100%; padding:10px } #test { height:100% }', body:'<div id=test></div>', q:200, s:0},
+ {style:'body { height:100%; border:10px solid } #test { height:100% }', body:'<div id=test></div>', q:200, s:0},
+ {style:'html { position:absolute; height:100%; margin:10px } #test { height:100% }', body:'<div id=test></div>', q:184, s:0},
+ {style:'html { position:absolute; height:100%; padding:10px } #test { height:100% }', body:'<div id=test></div>', q:184, s:0},
+ {style:'html { position:absolute; height:100%; border:10px solid } #test { height:100% }', body:'<div id=test></div>', q:184, s:0},
+ {style:'body { margin:99px 0 } #test { height:100% }', body:'<div id=test></div>', q:2, s:0},
+ {style:'body { margin:110px 0 } #test { height:100% }', body:'<div id=test></div>', q:0, s:0},
+ {style:'html, body { border:10px none } #test { height:100% }', body:'<div id=test></div>', q:184, s:0},
+ {style:'html, body { border:10px hidden } #test { height:100% }', body:'<div id=test></div>', q:184, s:0},
+ ];
+
+ tests.forEach(function(t) {
+ test(function() {
+ var style = t.style.replace(/\{png\}/g, png);
+ var body = t.body.replace(/\{png\}/g, png);
+ q.style.textContent = style;
+ a.style.textContent = style;
+ s.style.textContent = style;
+ q.document.body.innerHTML = body;
+ a.document.body.innerHTML = body;
+ s.document.body.innerHTML = body;
+
+ assert_equals(q.getComputedStyle(q.test).height,
+ t.q + 'px',
+ 'quirks mode');
+ assert_equals(a.getComputedStyle(a.test).height,
+ t.s + 'px',
+ 'almost standards mode');
+ assert_equals(s.getComputedStyle(s.test).height,
+ t.s + 'px',
+ 'standards mode');
+ }, document.title+', '+t.style+t.body);
+ });
+
+ var xml_tests = [
+ {input:'<html xmlns="{html}"><head><style>#test { height:100% }</style></head><body><div id="test"/></body></html>', q:184, s:0},
+ {input:'<html xmlns="{html}"><head><style>#test { height:100% }</style></head><body/><div id="test"/></html>', q:200, s:0},
+ {input:'<html xmlns="{html}"><head><style>#test { height:100% }</style></head><span><body><div id="test"/></body></span></html>', q:200, s:0},
+ {input:'<html xmlns="{html}"><head><style>#test { height:100% }</style></head><body><body><div id="test"/></body></body></html>', q:200, s:0},
+ {input:'<html><head xmlns="{html}"><style>#test { height:100% }</style></head><body xmlns="{html}"><div id="test"/></body></html>', q:200, s:0},
+ {input:'<div xmlns="{html}"><head><style>#test { height:100% }</style></head><body><div id="test"/></body></div>', q:200, s:0},
+ {input:'<html xmlns="{html}"><head><style>#test { height:100% }</style></head><body xmlns=""><div xmlns="{html}" id="test"/></body></html>', q:200, s:0},
+ {input:'<HTML xmlns="{html}"><head><style>#test { height:100% }</style></head><body><div id="test"/></body></HTML>', q:200, s:0},
+ {input:'<html xmlns="{html}"><head><style>#test { height:100% }</style></head><BODY><div id="test"/></BODY></html>', q:200, s:0},
+ ];
+
+ var parser = new DOMParser();
+
+ xml_tests.forEach(function(t) {
+ test(function() {
+ var input = t.input.replace(/\{html\}/g, 'http://www.w3.org/1999/xhtml')
+ .replace(/\{png\}/g, png);
+ var root = parser.parseFromString(input, 'text/xml').documentElement;
+ q.document.replaceChild(root.cloneNode(true), q.document.documentElement);
+ a.document.replaceChild(root.cloneNode(true), a.document.documentElement);
+ s.document.replaceChild(root, s.document.documentElement);
+ assert_equals(q.getComputedStyle(q.test).height,
+ t.q + 'px',
+ 'quirks mode');
+ assert_equals(a.getComputedStyle(a.test).height,
+ t.s + 'px',
+ 'almost standards mode');
+ assert_equals(s.getComputedStyle(s.test).height,
+ t.s + 'px',
+ 'standards mode');
+ }, document.title+', '+t.input);
+ });
+
+ done();
+ }
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/quirks-mode/table-cell-nowrap-minimum-width-calculation.html b/tests/wpt/web-platform-tests/quirks-mode/table-cell-nowrap-minimum-width-calculation.html
new file mode 100644
index 00000000000..6b07246e852
--- /dev/null
+++ b/tests/wpt/web-platform-tests/quirks-mode/table-cell-nowrap-minimum-width-calculation.html
@@ -0,0 +1,70 @@
+<!doctype html>
+<html>
+ <head>
+ <title>The table cell nowrap minimum width calculation quirk</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <style> iframe { width:200px; height:20px; } </style>
+ </head>
+ <body>
+ <div id=log></div>
+ <iframe id=quirks></iframe>
+ <iframe id=almost></iframe>
+ <iframe id=standards></iframe>
+ <script>
+ setup({explicit_done:true});
+ onload = function() {
+ var html = "<style id=style></style>";
+ var png = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg==";
+ var preload = new Image();
+ preload.src = png;
+ var a_doctype = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">';
+ var s_doctype = '<!DOCTYPE HTML>';
+ var q = document.getElementById('quirks').contentWindow;
+ var a = document.getElementById('almost').contentWindow;
+ var s = document.getElementById('standards').contentWindow;
+ q.document.open();
+ q.document.write(html);
+ q.document.close();
+ a.document.open();
+ a.document.write(a_doctype + html);
+ a.document.close();
+ s.document.open();
+ s.document.write(s_doctype + html);
+ s.document.close();
+ [q, a, s].forEach(function(win) {
+ ['style', 'test', 'ref', 's_ref'].forEach(function(id) {
+ win.__proto__.__defineGetter__(id, function() { return win.document.getElementById(id); });
+ });
+ });
+ q.title = 'quirks mode';
+ a.title = 'almost standards mode';
+ s.title = 'standards mode';
+
+ var tests = [
+ {desc:"basic",
+ style:'table { width:8px } #test { width:10px }',
+ body:'<table><tr><td id=test nowrap></table>'+
+ '<table><tr><td id=ref><img src="{png}" width=10></table>'+
+ '<table><tr><td id=s_ref></table>'},
+ ];
+
+ tests.forEach(function(t) {
+ test(function() {
+ var style = t.style.replace(/\{png\}/g, png);
+ var body = t.body.replace(/\{png\}/g, png);
+ [q, a, s].forEach(function(win) {
+ win.style.textContent = style;
+ win.document.body.innerHTML = body;
+ assert_equals(win.getComputedStyle(win.test).width,
+ win.getComputedStyle(win == q ? win.ref : win.s_ref).width,
+ win.title);
+ });
+ }, document.title+', '+t.desc);
+ });
+
+ done();
+ }
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/quirks-mode/table-cell-width-calculation.html b/tests/wpt/web-platform-tests/quirks-mode/table-cell-width-calculation.html
new file mode 100644
index 00000000000..09e651e2d00
--- /dev/null
+++ b/tests/wpt/web-platform-tests/quirks-mode/table-cell-width-calculation.html
@@ -0,0 +1,172 @@
+<!doctype html>
+<html>
+ <head>
+ <title>The table cell width calculation quirk</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <style> iframe { width:200px; height:20px; } </style>
+ </head>
+ <body>
+ <div id=log></div>
+ <iframe id=quirks></iframe>
+ <iframe id=almost></iframe>
+ <iframe id=standards></iframe>
+ <script>
+ setup({explicit_done:true});
+ onload = function() {
+ var html = "<style id=style></style><table><tr><td id=test></table><table><tr><td id=ref></table><table><tr><td id=s_ref></table>";
+ var png = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg==";
+ var preload = new Image();
+ preload.src = png;
+ var a_doctype = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">';
+ var s_doctype = '<!DOCTYPE HTML>';
+ var q = document.getElementById('quirks').contentWindow;
+ var a = document.getElementById('almost').contentWindow;
+ var s = document.getElementById('standards').contentWindow;
+ q.document.open();
+ q.document.write(html);
+ q.document.close();
+ a.document.open();
+ a.document.write(a_doctype + html);
+ a.document.close();
+ s.document.open();
+ s.document.write(s_doctype + html);
+ s.document.close();
+ [q, a, s].forEach(function(win) {
+ ['style', 'test', 'ref', 's_ref'].forEach(function(id) {
+ win.__proto__.__defineGetter__(id, function() { return win.document.getElementById(id); });
+ });
+ });
+ q.title = 'quirks mode';
+ a.title = 'almost standards mode';
+ s.title = 'standards mode';
+
+ var tests = [
+ {desc:"baseline",
+ style:'table { width:8px }', // cell content width should be 2px (2px cell-spacing, 1px padding)
+ test:'<img src="{png}">',
+ ref:'<img src="{png}">',
+ s_ref:'<img src="{png}">'},
+
+ {desc:"basic",
+ style:'table { width:8px }',
+ test:'<img src="{png}"><img src="{png}"><img src="{png}">',
+ ref:'<nobr><img src="{png}"><img src="{png}"><img src="{png}"></nobr>',
+ s_ref:'<nobr><img src="{png}"><img src="{png}"><br><img src="{png}"></nobr>'},
+
+ {desc:"inline-block",
+ style:'table { width:8px } img { display:inline-block }',
+ test:'<img src="{png}"><img src="{png}"><img src="{png}">',
+ ref:'<nobr><img src="{png}"><img src="{png}"><img src="{png}"></nobr>',
+ s_ref:'<nobr><img src="{png}"><img src="{png}"><br><img src="{png}"></nobr>'},
+
+ {desc:"img in span",
+ style:'table { width:8px }',
+ test:'<span><img src="{png}"><img src="{png}"><img src="{png}"></span>',
+ ref:'<nobr><img src="{png}"><img src="{png}"><img src="{png}"></nobr>',
+ s_ref:'<nobr><img src="{png}"><img src="{png}"><br><img src="{png}"></nobr>'},
+
+ {desc:"the don't-wrap rule is only for the purpose of calculating the width of the cell",
+ style:'table { width:8px }',
+ test:'<img src="{png}"><wbr><img src="{png}"><img src="{png}"><img src="{png}">',
+ ref:'<nobr><img src="{png}"><img src="{png}"><img src="{png}"><br><img src="{png}"></nobr>',
+ s_ref:'<nobr><img src="{png}"><img src="{png}"><br><img src="{png}"><img src="{png}"></nobr>'},
+
+ {desc:"the quirk only applies when the cell is the containing block",
+ style:'table { width:8px }',
+ test:'<div><img src="{png}"><img src="{png}"><img src="{png}"></div>',
+ ref:'<nobr><img src="{png}"><img src="{png}"><br><img src="{png}"><img src="{png}"></nobr>',
+ s_ref:'<nobr><img src="{png}"><img src="{png}"><br><img src="{png}"><img src="{png}"></nobr>'},
+
+ {desc:"the quirk shouldn't apply for generated content",
+ style:'table { width:8px } #test::before { content:url("{png}") url("{png}") url("{png}") }',
+ test:'',
+ ref:'<nobr><img src="{png}"><img src="{png}"><br><img src="{png}"></nobr>',
+ s_ref:'<nobr><img src="{png}"><img src="{png}"><br><img src="{png}"></nobr>'},
+
+ {desc:"the quirk shouldn't apply for <input>",
+ style:'table { width:8px }',
+ test:'<input type=image src="{png}"><input type=image src="{png}"><input type=image src="{png}">',
+ ref:'<nobr><img src="{png}"><img src="{png}"><br><img src="{png}"></nobr>',
+ s_ref:'<nobr><img src="{png}"><img src="{png}"><br><img src="{png}"></nobr>'},
+
+ {desc:"the quirk shouldn't apply for <object>",
+ style:'table { width:8px }',
+ test:'<object data="{png}"></object><object data="{png}"></object><object data="{png}"></object>',
+ ref:'<nobr><img src="{png}"><img src="{png}"><br><img src="{png}"></nobr>',
+ s_ref:'<nobr><img src="{png}"><img src="{png}"><br><img src="{png}"></nobr>'},
+
+ {desc:"the quirk shouldn't apply for <embed>",
+ style:'table { width:8px }',
+ test:'<embed src="{png}"><embed src="{png}"><embed src="{png}">',
+ ref:'<nobr><img src="{png}"><img src="{png}"><br><img src="{png}"></nobr>',
+ s_ref:'<nobr><img src="{png}"><img src="{png}"><br><img src="{png}"></nobr>'},
+
+ {desc:"the quirk shouldn't apply for <video poster>",
+ style:'table { width:8px }',
+ test:'<video poster="{png}"></video><video poster="{png}"></video><video poster="{png}"></video>',
+ ref:'<nobr><img src="{png}"><img src="{png}"><br><img src="{png}"></nobr>',
+ s_ref:'<nobr><img src="{png}"><img src="{png}"><br><img src="{png}"></nobr>'},
+
+ {desc:"non-auto width on cell",
+ style:'td { width:2px }',
+ test:'<img src="{png}"><img src="{png}"><img src="{png}">',
+ ref:'<nobr><img src="{png}"><img src="{png}"><br><img src="{png}"></nobr>',
+ s_ref:'<nobr><img src="{png}"><img src="{png}"><br><img src="{png}"></nobr>'},
+
+ {desc:"zero width on cell, specified with on table",
+ style:'table { width:8px } td { width:0 }',
+ test:'<img src="{png}"><img src="{png}"><img src="{png}">',
+ ref:'<nobr><img src="{png}"><img src="{png}"><br><img src="{png}"></nobr>',
+ s_ref:'<nobr><img src="{png}"><img src="{png}"><br><img src="{png}"></nobr>'},
+
+ // tests below use overwrite body.innerHTML so tests using test/ref/s_ref props need to be above
+ {desc:"display:table-cell on span",
+ style:'div { display:table; width:2px } span { display:table-cell }',
+ body:'<div><span id=test><img src="{png}"><img src="{png}"><img src="{png}"></span></div>'+
+ '<div><span id=ref><nobr><img src="{png}"><img src="{png}"><img src="{png}"></nobr></span></div>'+
+ '<div><span id=s_ref><nobr><img src="{png}"><img src="{png}"><br><img src="{png}"></nobr></span></div>'},
+
+ {desc:"display:table-cell on span, wbr",
+ style:'div { display:table; width:2px } span { display:table-cell }',
+ body:'<div><span id=test><img src="{png}"><wbr><img src="{png}"><img src="{png}"><img src="{png}"></span></div>'+
+ '<div><span id=ref><nobr><img src="{png}"><img src="{png}"><img src="{png}"><br><img src="{png}"></nobr></span></div>'+
+ '<div><span id=s_ref><nobr><img src="{png}"><img src="{png}"><br><img src="{png}"><img src="{png}"></nobr></span></div>'},
+ ];
+
+ tests.forEach(function(t) {
+ test(function() {
+ var style = t.style.replace(/\{png\}/g, png);
+ var test = t.test && t.test.replace(/\{png\}/g, png);
+ var ref = t.ref && t.ref.replace(/\{png\}/g, png);
+ var s_ref = t.s_ref && t.s_ref.replace(/\{png\}/g, png);
+ var body = t.body && t.body.replace(/\{png\}/g, png);
+ [q, a, s].forEach(function(win) {
+ win.style.textContent = style;
+ if (body !== undefined) {
+ win.document.body.innerHTML = body;
+ } else {
+ win.test.innerHTML = test;
+ win.ref.innerHTML = ref;
+ win.s_ref.innerHTML = s_ref;
+ }
+ assert_equals(win.getComputedStyle(win.test).width,
+ win.getComputedStyle(win == q ? win.ref : win.s_ref).width,
+ 'cell width, '+win.title);
+ var test_imgs = win.test.querySelectorAll('img');
+ var ref_imgs = win.ref.querySelectorAll('img');
+ var s_ref_imgs = win.s_ref.querySelectorAll('img');
+ for (var i = 0; i < test_imgs.length; ++i) {
+ assert_equals(test_imgs[i].offsetLeft,
+ win == q ? ref_imgs[i].offsetLeft : s_ref_imgs[i].offsetLeft,
+ 'img '+i+' offsetLeft, '+win.title);
+ }
+ });
+ }, document.title+', '+t.desc);
+ });
+
+ done();
+ }
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/quirks-mode/unitless-length.html b/tests/wpt/web-platform-tests/quirks-mode/unitless-length.html
new file mode 100644
index 00000000000..b2f05c01049
--- /dev/null
+++ b/tests/wpt/web-platform-tests/quirks-mode/unitless-length.html
@@ -0,0 +1,226 @@
+<!doctype html>
+<html>
+ <head>
+ <title>The unitless length quirk</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <style> iframe { width:20px; height:20px; } </style>
+ </head>
+ <body>
+ <div id=log></div>
+ <iframe id=quirks></iframe>
+ <iframe id=almost></iframe>
+ <iframe id=standards></iframe>
+ <script>
+ setup({explicit_done:true});
+ onload = function() {
+ var html = "<style id=style></style><div id=test></div><div id=ref></div>";
+ var a_doctype = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">';
+ var s_doctype = '<!DOCTYPE HTML>';
+ var q = document.getElementById('quirks').contentWindow;
+ var a = document.getElementById('almost').contentWindow;
+ var s = document.getElementById('standards').contentWindow;
+ q.document.open();
+ q.document.write(html);
+ q.document.close();
+ a.document.open();
+ a.document.write(a_doctype + html);
+ a.document.close();
+ s.document.open();
+ s.document.write(s_doctype + html);
+ s.document.close();
+ [q, a, s].forEach(function(win) {
+ ['style', 'test', 'ref'].forEach(function(id) {
+ win[id] = win.document.getElementById(id);
+ });
+ });
+
+ var tests = [
+ {input:"1", q:"1px"},
+ {input:"+1", q:"1px"},
+ {input:"-1", q:"-1px"},
+ {input:"1.5", q:"1.5px"},
+ {input:"+1.5", q:"1.5px"},
+ {input:"-1.5", q:"-1.5px"},
+ {input:"\\31 "},
+ {input:"+\\31 "},
+ {input:"-\\31 "},
+ {input:"\\31 .5"},
+ {input:"+\\31 .5"},
+ {input:"-\\31 .5"},
+ {input:"1\\31 "},
+ {input:"+1\\31 "},
+ {input:"-1\\31 "},
+ {input:"1\\31 .5"},
+ {input:"+1\\31 .5"},
+ {input:"-1\\31 .5"},
+ {input:"a"},
+ {input:"A"},
+ {input:"1a"},
+ {input:"+1a"},
+ {input:"-1a"},
+ {input:"+1A"},
+ {input:"-1A"},
+ {input:"+a"},
+ {input:"-a"},
+ {input:"+A"},
+ {input:"-A"},
+ {input:"@a"},
+ {input:"@1"},
+ {input:"@1a"},
+ {input:'"a"'},
+ {input:'"1"'},
+ {input:'"1a"'},
+ {input:"url(1)"},
+ {input:"url('1')"},
+ {input:"#1"},
+ {input:"#01"},
+ {input:"#001"},
+ {input:"#0001"},
+ {input:"#00001"},
+ {input:"#000001"},
+ {input:"+/**/1"},
+ {input:"-/**/1"},
+ {input:"calc(1)"},
+ {input:"calc(2 * 2px)", q:"4px", s:"4px"},
+ {input:"1px 2", q:"1px 2px", shorthand:true},
+ {input:"1 2px", q:"1px 2px", shorthand:true},
+ {input:"1px calc(2)", shorthand:true},
+ {input:"calc(1) 2px", shorthand:true},
+ {input:"1 +2", q:"1px 2px", shorthand:true},
+ {input:"1 -2", q:"1px -2px", shorthand:true},
+ ];
+
+ var props = [
+ {prop:'background-position', check:'background-position', check_also:[]},
+ {prop:'border-spacing', check:'border-spacing', check_also:[]},
+ {prop:'border-top-width', check:'border-top-width'},
+ {prop:'border-right-width', check:'border-right-width'},
+ {prop:'border-bottom-width', check:'border-bottom-width'},
+ {prop:'border-left-width', check:'border-left-width'},
+ {prop:'border-width', check:'border-top-width', check_also:['border-right-width', 'border-bottom-width', 'border-left-width']},
+ {prop:'bottom', check:'bottom'},
+ {prop:'clip', check:'clip'},
+ {prop:'font-size', check:'font-size'},
+ {prop:'height', check:'height'},
+ {prop:'left', check:'left'},
+ {prop:'letter-spacing', check:'letter-spacing'},
+ {prop:'margin-right', check:'margin-right'},
+ {prop:'margin-left', check:'margin-left'},
+ {prop:'margin-top', check:'margin-top'},
+ {prop:'margin-bottom', check:'margin-bottom'},
+ {prop:'margin', check:'margin-top', check_also:['margin-right', 'margin-bottom', 'margin-left']},
+ {prop:'max-height', check:'max-height'},
+ {prop:'max-width', check:'max-width'},
+ {prop:'min-height', check:'min-height'},
+ {prop:'min-width', check:'min-width'},
+ {prop:'padding-top', check:'padding-top'},
+ {prop:'padding-right', check:'padding-right'},
+ {prop:'padding-bottom', check:'padding-bottom'},
+ {prop:'padding-left', check:'padding-left'},
+ {prop:'padding', check:'padding-top', check_also:['padding-right', 'padding-bottom', 'padding-left']},
+ {prop:'right', check:'right'},
+ {prop:'text-indent', check:'text-indent'},
+ {prop:'top', check:'top'},
+ {prop:'vertical-align', check:'vertical-align'},
+ {prop:'width', check:'width'},
+ {prop:'word-spacing', check:'word-spacing'},
+ ];
+ var style_template = '#test{border-style:solid;position:relative;{prop}:{test};}' +
+ '#ref{border-style:solid;position:relative;{prop}:{ref};}';
+
+ tests.forEach(function(t) {
+ var test_q = async_test(t.input + ' (quirks)');
+ var test_a = async_test(t.input + ' (almost standards)');
+ var test_s = async_test(t.input + ' (standards)');
+ for (var i in props) {
+ if (t.shorthand && !(props[i].check_also)) {
+ continue;
+ }
+ test_q.step(function() {
+ q.style.textContent = style_template.replace('{test}', t.input)
+ .replace('{ref}', t.q).replace(/\{prop\}/g, props[i].prop)
+ .replace(/clip:[^;]+/g, function(match) {
+ return 'clip:rect(auto, auto, auto, ' + match.substr(5) + ')';
+ });
+ assert_equals(q.getComputedStyle(q.test).getPropertyValue(props[i].check),
+ q.getComputedStyle(q.ref).getPropertyValue(props[i].check),
+ props[i].prop);
+ if (t.shorthand && props[i].check_also) {
+ for (var j in props[i].check_also) {
+ assert_equals(q.getComputedStyle(q.test).getPropertyValue(props[i].check_also[j]),
+ q.getComputedStyle(q.ref).getPropertyValue(props[i].check_also[j]),
+ props[i].prop + ', checking ' + props[i].check_also[j]);
+ }
+ }
+ });
+ test_a.step(function() {
+ a.style.textContent = style_template.replace('{test}', t.input)
+ .replace('{ref}', t.s).replace(/\{prop\}/g, props[i].prop)
+ .replace(/clip:[^;]+/g, function(match) {
+ return 'clip:rect(auto, auto, auto, ' + match.substr(5) + ')';
+ });
+ assert_equals(a.getComputedStyle(a.test).getPropertyValue(props[i].check),
+ a.getComputedStyle(a.ref).getPropertyValue(props[i].check),
+ props[i].prop + ' in almost standards mode');
+ if (t.shorthand && props[i].check_also) {
+ for (var j in props[i].check_also) {
+ assert_equals(a.getComputedStyle(a.test).getPropertyValue(props[i].check_also[j]),
+ a.getComputedStyle(a.ref).getPropertyValue(props[i].check_also[j]),
+ props[i].prop + ', checking ' + props[i].check_also[j]);
+ }
+ }
+ });
+ test_s.step(function() {
+ s.style.textContent = style_template.replace('{test}', t.input)
+ .replace('{ref}', t.s).replace(/\{prop\}/g, props[i].prop)
+ .replace(/clip:[^;]+/g, function(match) {
+ return 'clip:rect(auto, auto, auto, ' + match.substr(5) + ')';
+ });
+ assert_equals(s.getComputedStyle(s.test).getPropertyValue(props[i].check),
+ s.getComputedStyle(s.ref).getPropertyValue(props[i].check),
+ props[i].prop + ' in standards mode');
+ if (t.shorthand && props[i].check_also) {
+ for (var j in props[i].check_also) {
+ assert_equals(s.getComputedStyle(s.test).getPropertyValue(props[i].check_also[j]),
+ s.getComputedStyle(s.ref).getPropertyValue(props[i].check_also[j]),
+ props[i].prop + ', checking ' + props[i].check_also[j]);
+ }
+ }
+ });
+ }
+ test_q.done();
+ test_a.done();
+ test_s.done();
+
+ });
+
+ var other_tests = [
+ {input:'background:1 1', prop:'background-position'},
+ {input:'border-top:red solid 1', prop:'border-top-width'},
+ {input:'border-right:red solid 1', prop:'border-right-width'},
+ {input:'border-bottom:red solid 1', prop:'border-bottom-width'},
+ {input:'border-left:red solid 1', prop:'border-left-width'},
+ {input:'border:red solid 1', prop:'border-top-width'},
+ {input:'font:normal normal normal 40 sans-serif', prop:'font-size'},
+ {input:'outline:red solid 1', prop:'outline-width'},
+ {input:'outline-width:1', prop:'outline-width'},
+ ];
+
+ var other_template = "#test{position:relative;outline-style:solid;{test}}" +
+ "#ref{outline-style:solid}";
+
+ other_tests.forEach(function(t) {
+ test(function() {
+ q.style.textContent = other_template.replace('{test}', t.input);
+ assert_equals(q.getComputedStyle(q.test).getPropertyValue(t.prop),
+ q.getComputedStyle(q.ref).getPropertyValue(t.prop),
+ 'quirk was supported');
+ }, 'Excluded property '+t.input);
+ });
+
+ done();
+ }
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/resource-timing/resources/resource_timing_test0.css b/tests/wpt/web-platform-tests/resource-timing/resources/resource_timing_test0.css
new file mode 100644
index 00000000000..8bc8326ba67
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resource-timing/resources/resource_timing_test0.css
@@ -0,0 +1,4 @@
+div#resource_link_css
+{
+ color:hotpink;
+} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resource-timing/resources/resource_timing_test0.html b/tests/wpt/web-platform-tests/resource-timing/resources/resource_timing_test0.html
new file mode 100644
index 00000000000..167c65c5c45
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resource-timing/resources/resource_timing_test0.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>
+ Child Frame
+ </title>
+ </head>
+ <body style="background-color: #C0C0C0">
+
+ <h1>
+ Child Document
+ </h1>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resource-timing/resources/resource_timing_test0.js b/tests/wpt/web-platform-tests/resource-timing/resources/resource_timing_test0.js
new file mode 100644
index 00000000000..cf1c1df3920
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resource-timing/resources/resource_timing_test0.js
@@ -0,0 +1,3 @@
+// This is a test script for purposes of testing the
+// script initiator type in the Resource Timing feature
+var testDummyValue = 0;
diff --git a/tests/wpt/web-platform-tests/resource-timing/resources/resource_timing_test0.png b/tests/wpt/web-platform-tests/resource-timing/resources/resource_timing_test0.png
new file mode 100644
index 00000000000..be211bc3771
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resource-timing/resources/resource_timing_test0.png
Binary files differ
diff --git a/tests/wpt/web-platform-tests/resource-timing/resources/resource_timing_test0.xml b/tests/wpt/web-platform-tests/resource-timing/resources/resource_timing_test0.xml
new file mode 100644
index 00000000000..91cd676be6e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resource-timing/resources/resource_timing_test0.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<TESTDATA>
+ <ITEM>
+ <DATA>Test XML Data</DATA>
+ </ITEM>
+</TESTDATA>
diff --git a/tests/wpt/web-platform-tests/resource-timing/resources/webperftestharness.js b/tests/wpt/web-platform-tests/resource-timing/resources/webperftestharness.js
new file mode 100644
index 00000000000..98b2954bad3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resource-timing/resources/webperftestharness.js
@@ -0,0 +1,145 @@
+//
+// Helper Functions for NavigationTiming W3C tests
+//
+
+var performanceNamespace = window.performance;
+var timingAttributes = [
+ 'connectEnd',
+ 'connectStart',
+ 'domComplete',
+ 'domContentLoadedEventEnd',
+ 'domContentLoadedEventStart',
+ 'domInteractive',
+ 'domLoading',
+ 'domainLookupEnd',
+ 'domainLookupStart',
+ 'fetchStart',
+ 'loadEventEnd',
+ 'loadEventStart',
+ 'navigationStart',
+ 'redirectEnd',
+ 'redirectStart',
+ 'requestStart',
+ 'responseEnd',
+ 'responseStart',
+ 'unloadEventEnd',
+ 'unloadEventStart'
+];
+
+var namespace_check = false;
+
+//
+// All test() functions in the WebPerf test suite should use wp_test() instead.
+//
+// wp_test() validates the window.performance namespace exists prior to running tests and
+// immediately shows a single failure if it does not.
+//
+
+function wp_test(func, msg, properties)
+{
+ // only run the namespace check once
+ if (!namespace_check)
+ {
+ namespace_check = true;
+
+ if (performanceNamespace === undefined || performanceNamespace == null)
+ {
+ // show a single error that window.performance is undefined
+ test(function() { assert_true(performanceNamespace !== undefined && performanceNamespace != null, "window.performance is defined and not null"); }, "window.performance is defined and not null.", {author:"W3C http://www.w3.org/",help:"http://www.w3.org/TR/navigation-timing/#sec-window.performance-attribute",assert:"The window.performance attribute provides a hosting area for performance related attributes. "});
+ }
+ }
+
+ test(func, msg, properties);
+}
+
+function test_namespace(child_name, skip_root)
+{
+ if (skip_root === undefined) {
+ var msg = 'window.performance is defined';
+ wp_test(function () { assert_true(performanceNamespace !== undefined, msg); }, msg,{author:"W3C http://www.w3.org/",help:"http://www.w3.org/TR/navigation-timing/#sec-window.performance-attribute",assert:"The window.performance attribute provides a hosting area for performance related attributes. "});
+ }
+
+ if (child_name !== undefined) {
+ var msg2 = 'window.performance.' + child_name + ' is defined';
+ wp_test(function() { assert_true(performanceNamespace[child_name] !== undefined, msg2); }, msg2,{author:"W3C http://www.w3.org/",help:"http://www.w3.org/TR/navigation-timing/#sec-window.performance-attribute",assert:"The window.performance attribute provides a hosting area for performance related attributes. "});
+ }
+}
+
+function test_attribute_exists(parent_name, attribute_name, properties)
+{
+ var msg = 'window.performance.' + parent_name + '.' + attribute_name + ' is defined.';
+ wp_test(function() { assert_true(performanceNamespace[parent_name][attribute_name] !== undefined, msg); }, msg, properties);
+}
+
+function test_enum(parent_name, enum_name, value, properties)
+{
+ var msg = 'window.performance.' + parent_name + '.' + enum_name + ' is defined.';
+ wp_test(function() { assert_true(performanceNamespace[parent_name][enum_name] !== undefined, msg); }, msg, properties);
+
+ msg = 'window.performance.' + parent_name + '.' + enum_name + ' = ' + value;
+ wp_test(function() { assert_equals(performanceNamespace[parent_name][enum_name], value, msg); }, msg, properties);
+}
+
+function test_timing_order(attribute_name, greater_than_attribute, properties)
+{
+ // ensure it's not 0 first
+ var msg = "window.performance.timing." + attribute_name + " > 0";
+ wp_test(function() { assert_true(performanceNamespace.timing[attribute_name] > 0, msg); }, msg, properties);
+
+ // ensure it's in the right order
+ msg = "window.performance.timing." + attribute_name + " >= window.performance.timing." + greater_than_attribute;
+ wp_test(function() { assert_true(performanceNamespace.timing[attribute_name] >= performanceNamespace.timing[greater_than_attribute], msg); }, msg, properties);
+}
+
+function test_timing_greater_than(attribute_name, greater_than, properties)
+{
+ var msg = "window.performance.timing." + attribute_name + " > " + greater_than;
+ test_greater_than(performanceNamespace.timing[attribute_name], greater_than, msg, properties);
+}
+
+function test_timing_equals(attribute_name, equals, msg, properties)
+{
+ var test_msg = msg || "window.performance.timing." + attribute_name + " == " + equals;
+ test_equals(performanceNamespace.timing[attribute_name], equals, test_msg, properties);
+}
+
+//
+// Non-test related helper functions
+//
+
+function sleep_milliseconds(n)
+{
+ var start = new Date().getTime();
+ while (true) {
+ if ((new Date().getTime() - start) >= n) break;
+ }
+}
+
+//
+// Common helper functions
+//
+
+function test_true(value, msg, properties)
+{
+ wp_test(function () { assert_true(value, msg); }, msg, properties);
+}
+
+function test_equals(value, equals, msg, properties)
+{
+ wp_test(function () { assert_equals(value, equals, msg); }, msg, properties);
+}
+
+function test_greater_than(value, greater_than, msg, properties)
+{
+ wp_test(function () { assert_true(value > greater_than, msg); }, msg, properties);
+}
+
+function test_greater_or_equals(value, greater_than, msg, properties)
+{
+ wp_test(function () { assert_true(value >= greater_than, msg); }, msg, properties);
+}
+
+function test_not_equals(value, notequals, msg, properties)
+{
+ wp_test(function() { assert_true(value !== notequals, msg); }, msg, properties);
+}
diff --git a/tests/wpt/web-platform-tests/resource-timing/test_resource_timing.html b/tests/wpt/web-platform-tests/resource-timing/test_resource_timing.html
new file mode 100644
index 00000000000..f4e851abb20
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resource-timing/test_resource_timing.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="UTF-8" />
+ <title>window.performance Resource Timing Entries exist</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="https://w3c.github.io/web-performance/specs/ResourceTiming/Overview.html"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="test_resource_timing.js"></script>
+ </head>
+ <body>
+ <h1>Description</h1>
+ <p>
+ NOTE: Due to caching behavior in the browser, it is possible that when revisiting this page, some resources
+ may not have to be fetched from the network. As a result, the performance timeline will not contain entries
+ for these resources. This test will fail if any entries are missing to ensure that all resources are fetched
+ from the network and entries for these resources exist in the Performance Timeline. If revisiting this page,
+ please either perform a full reload of the page or clear the cache between visits.
+ </p>
+
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/resource-timing/test_resource_timing.js b/tests/wpt/web-platform-tests/resource-timing/test_resource_timing.js
new file mode 100644
index 00000000000..0072d50e58a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resource-timing/test_resource_timing.js
@@ -0,0 +1,182 @@
+var TEST_ALLOWED_TIMING_DELTA = 20;
+
+var waitTimer;
+var expectedEntries = {};
+
+var initiatorTypes = ["iframe", "img", "link", "script", "xmlhttprequest"];
+
+var tests = {};
+setup(function() {
+ for (var i in initiatorTypes) {
+ var type = initiatorTypes[i];
+ tests[type] = {
+ "entry": async_test("window.performance.getEntriesByName() and window.performance.getEntriesByNameType() return same data (" + type + ")"),
+ "simple_attrs": async_test("PerformanceEntry has correct name, initiatorType, startTime, and duration (" + type + ")"),
+ "timing_attrs": async_test("PerformanceEntry has correct order of timing attributes (" + type + ")")
+ };
+ }
+});
+
+function resolve(path) {
+ var a = document.createElement("a");
+ a.href = path;
+ return a.href;
+}
+
+onload = function()
+{
+ // check that the Performance Timeline API exists
+ test(function() {
+ assert_idl_attribute(window.performance, "getEntriesByName",
+ "window.performance.getEntriesByName() is defined");
+ });
+ test(function() {
+ assert_idl_attribute(window.performance, "getEntriesByType",
+ "window.performance.getEntriesByType() is defined");
+ });
+ test(function() {
+ assert_idl_attribute(window.performance, "getEntries",
+ "window.performance.getEntries() is defined");
+ });
+
+ var expected_entry;
+ var url;
+ var type;
+ var startTime;
+ var element;
+ for (var i in initiatorTypes) {
+ startTime = window.performance.now();
+ type = initiatorTypes[i];
+ if (type != "xmlhttprequest") {
+ element = document.createElement(type);
+ } else {
+ element = null;
+ }
+ switch (type) {
+ case "iframe":
+ url = resolve("resources/resource_timing_test0.html");
+ element.src = url;
+ break;
+ case "img":
+ url = resolve("resources/resource_timing_test0.png");
+ element.src = url;
+ break;
+ case "link":
+ element.rel = "stylesheet";
+ url = resolve("resources/resource_timing_test0.css");
+ element.href = url;
+ break;
+ case "script":
+ element.type = "text/javascript";
+ url = resolve("resources/resource_timing_test0.js");
+ element.src = url;
+ break;
+ case "xmlhttprequest":
+ var xmlhttp = new XMLHttpRequest();
+ url = resolve("resources/resource_timing_test0.xml");
+ xmlhttp.open('GET', url, true);
+ xmlhttp.send();
+ break;
+ }
+
+ expected_entry = {name:url,
+ startTime: startTime,
+ initiatorType: type};
+
+ switch (type) {
+ case "link":
+ poll_for_stylesheet_load(expected_entry);
+ document.body.appendChild(element);
+ break;
+ case "xmlhttprequest":
+ xmlhttp.onload = (function(entry) {
+ return function (event) {
+ resource_load(entry);
+ };
+ })(expected_entry);
+ break;
+ default:
+ element.onload = (function(entry) {
+ return function (event) {
+ resource_load(entry);
+ };
+ })(expected_entry);
+ document.body.appendChild(element);
+ }
+
+ }
+};
+
+function poll_for_stylesheet_load(expected_entry) {
+ function inner() {
+ for(var i=0; i<document.styleSheets.length; i++) {
+ var sheet = document.styleSheets[i];
+ if (sheet.href === expected_entry.name) {
+ try {
+ // try/catch avoids throwing if sheet object exists before it is loaded,
+ // which is a bug, but not what we are trying to test here.
+ var hasRules = sheet.cssRules.length > 0;
+ } catch(e) {
+ hasRules = false;
+ }
+ if (hasRules) {
+ setTimeout(function() {
+ resource_load(expected_entry);
+ }, 200);
+ return;
+ }
+ }
+ }
+ setTimeout(inner, 100);
+ }
+ inner();
+}
+
+function resource_load(expected)
+{
+ var t = tests[expected.initiatorType];
+
+ t["entry"].step(function() {
+ var entries_by_name = window.performance.getEntriesByName(expected.name);
+ assert_equals(entries_by_name.length, 1, "should have a single entry for each resource (without type)");
+ var entries_by_name_type = window.performance.getEntriesByName(expected.name, "resource");
+ assert_equals(entries_by_name_type.length, 1, "should have a single entry for each resource (with type)");
+ assert_not_equals(entries_by_name, entries_by_name_type, "values should be copies");
+ for (p in entries_by_name[0]) {
+ assert_equals(entries_by_name[0][p], entries_by_name_type[0][p], "Property " + p + " should match");
+ }
+ this.done();
+ });
+
+ t["simple_attrs"].step(function() {
+ var actual = window.performance.getEntriesByName(expected.name)[0];
+ var expected_type = expected.initiatorType;
+ if (expected.initiatorType == "iframe") {
+ expected_type = "subdocument";
+ }
+ assert_equals(actual.name, expected.name);
+ assert_equals(actual.initiatorType, expected_type);
+ assert_equals(actual.entryType, "resource");
+ assert_greater_than_equal(actual.startTime, expected.startTime, "startTime is after the script to initiate the load ran");
+ assert_equals(actual.duration, (actual.responseEnd - actual.startTime));
+ this.done();
+ });
+
+ t["timing_attrs"].step(function test() {
+ var actual = window.performance.getEntriesByName(expected.name)[0];
+ assert_equals(actual.redirectStart, 0, "redirectStart time");
+ assert_equals(actual.redirectEnd, 0, "redirectEnd time");
+ assert_true(actual.secureConnectionStart == undefined ||
+ actual.secureConnectionStart == 0, "secureConnectionStart time");
+ assert_equals(actual.fetchStart, actual.startTime, "fetchStart is equal to startTime");
+ assert_greater_than_equal(actual.domainLookupStart, actual.fetchStart, "domainLookupStart after fetchStart");
+ assert_greater_than_equal(actual.domainLookupEnd, actual.domainLookupStart, "domainLookupEnd after domainLookupStart");
+ assert_greater_than_equal(actual.connectStart, actual.domainLookupEnd, "connectStart after domainLookupEnd");
+ assert_greater_than_equal(actual.connectEnd, actual.connectStart, "connectEnd after connectStart");
+ assert_greater_than_equal(actual.requestStart, actual.connectEnd, "requestStart after connectEnd");
+ assert_greater_than_equal(actual.responseStart, actual.requestStart, "responseStart after requestStart");
+ assert_greater_than_equal(actual.responseEnd, actual.responseStart, "responseEnd after responseStart");
+ this.done();
+ });
+
+}
diff --git a/tests/wpt/web-platform-tests/resources/.gitignore b/tests/wpt/web-platform-tests/resources/.gitignore
new file mode 100644
index 00000000000..04fdeda1cc4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/.gitignore
@@ -0,0 +1,3 @@
+ROBIN-TODO.txt
+scratch
+node_modules
diff --git a/tests/wpt/web-platform-tests/resources/.gitmodules b/tests/wpt/web-platform-tests/resources/.gitmodules
new file mode 100644
index 00000000000..89035729d51
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "webidl2"]
+ path = webidl2
+ url = https://github.com/darobin/webidl2.js.git
diff --git a/tests/wpt/web-platform-tests/resources/.htaccess b/tests/wpt/web-platform-tests/resources/.htaccess
new file mode 100644
index 00000000000..fd46101ca00
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/.htaccess
@@ -0,0 +1,2 @@
+# make tests that use utf-16 not inherit the encoding for testharness.js et. al.
+AddCharset utf-8 .css .js
diff --git a/tests/wpt/web-platform-tests/resources/apisample-error-worker.js b/tests/wpt/web-platform-tests/resources/apisample-error-worker.js
new file mode 100644
index 00000000000..c0285c37d5a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/apisample-error-worker.js
@@ -0,0 +1,3 @@
+importScripts("testharness.js");
+
+throw new Error("This failure is expected.");
diff --git a/tests/wpt/web-platform-tests/resources/apisample-worker.js b/tests/wpt/web-platform-tests/resources/apisample-worker.js
new file mode 100644
index 00000000000..6fd1ceb5376
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/apisample-worker.js
@@ -0,0 +1,34 @@
+importScripts("testharness.js");
+
+test(
+ function(test) {
+ assert_true(true, "True is true");
+ },
+ "Worker test that completes successfully");
+
+test(
+ function(test) {
+ assert_true(false, "Failing test");
+ },
+ "Worker test that fails ('FAIL')");
+
+async_test(
+ function(test) {
+ assert_true(true, "True is true");
+ },
+ "Worker test that times out ('TIMEOUT')");
+
+async_test("Worker test that doesn't run ('NOT RUN')");
+
+async_test(
+ function(test) {
+ self.setTimeout(
+ function() {
+ test.done();
+ },
+ 0);
+ },
+ "Worker async_test that completes successfully");
+
+// An explicit done() is required for dedicated and shared web workers.
+done();
diff --git a/tests/wpt/web-platform-tests/resources/apisample.htm b/tests/wpt/web-platform-tests/resources/apisample.htm
new file mode 100644
index 00000000000..6eb3279f5f6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/apisample.htm
@@ -0,0 +1,175 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>Sample HTML5 API Tests</title>
+<meta name="timeout" content="6000">
+</head>
+<body onload="load_test_attr.done()">
+<h1>Sample HTML5 API Tests</h1>
+<div id="log"></div>
+<script src="testharness.js"></script>
+<script src="testharnessreport.js"></script>
+<script>
+ setup_run = false;
+ setup(function() {
+ setup_run = true;
+ });
+ test(function() {assert_true(setup_run)}, "Setup function ran");
+
+ // Two examples for testing events from handler and attributes
+ var load_test_event = async_test("window onload event fires when set from the handler");
+
+ function windowLoad()
+ {
+ load_test_event.done();
+ }
+ on_event(window, "load", windowLoad);
+
+ // see the body onload below
+ var load_test_attr = async_test("body element fires the onload event set from the attribute");
+</script>
+<script>
+ function bodyElement()
+ {
+ assert_equals(document.body, document.getElementsByTagName("body")[0]);
+ }
+ test(bodyElement, "document.body should be the first body element in the document");
+
+ test(function() {
+ assert_equals(1,1);
+ assert_equals(NaN, NaN, "NaN case");
+ assert_equals(0, 0, "Zero case");
+ }, "assert_equals tests")
+
+ test(function() {
+ assert_equals(-0, 0, "Zero case");
+ }, "assert_equals tests expected to fail")
+
+ test(function() {
+ assert_not_equals({}, {}, "object case");
+ assert_not_equals(-0, 0, "Zero case");
+ }, "assert_not_equals tests")
+
+ function testAssertPass()
+ {
+ assert_true(true);
+ }
+ test(testAssertPass, "assert_true expected to pass");
+
+ function testAssertFalse()
+ {
+ assert_true(false, "false should not be true");
+ }
+ test(testAssertFalse, "assert_true expected to fail");
+
+ function basicAssertArrayEquals()
+ {
+ assert_array_equals([1, NaN], [1, NaN], "[1, NaN] is equal to [1, NaN]");
+ }
+ test(basicAssertArrayEquals, "basic assert_array_equals test");
+
+ function basicAssertObjectEquals()
+ {
+ assert_object_equals([1, 2, [1, 2]], { 0: 1, 1: 2, 2: { 0: 1, 1: 2} }, "array is equal to object")
+ }
+ test(basicAssertObjectEquals, "basic assert_object_equals test");
+
+ function basicAssertApproxEquals()
+ {
+ assert_approx_equals(10, 11, 1, "10 is approximately (+/- 1) 11")
+ }
+ test(basicAssertApproxEquals, "basic assert_approx_equals test");
+
+ function basicAssertLessThan()
+ {
+ assert_less_than(10, 11, "10 is less than 11")
+ }
+ test(basicAssertApproxEquals, "basic assert_less_than test");
+
+ function basicAssertGreaterThan()
+ {
+ assert_greater_than(10, 11, "10 is not greater than 11");
+ }
+ test(basicAssertGreaterThan, "assert_greater_than expected to fail");
+
+ function basicAssertGreaterThanEqual()
+ {
+ assert_greater_than_equal(10, 10, "10 is greater than or equal to 10")
+ }
+ test(basicAssertGreaterThanEqual, "basic assert_greater_than_equal test");
+
+ function basicAssertLessThanEqual()
+ {
+ assert_greater_than_equal('10', 10, "'10' is not a number")
+ }
+ test(basicAssertLessThanEqual, "assert_less_than_equal expected to fail");
+
+ function testAssertInherits() {
+ var A = function(){this.a = "a"}
+ A.prototype = {b:"b"}
+ var a = new A();
+ assert_exists(a, "a");
+ assert_not_exists(a, "b");
+ assert_inherits(a, "b");
+ }
+ test(testAssertInherits, "test for assert[_not]_exists and insert_inherits")
+
+ test(function()
+ {
+ var a = document.createElement("a")
+ var b = document.createElement("b")
+ assert_throws("NOT_FOUND_ERR", function(){a.removeChild(b)});
+ }, "Test throw DOM exception")
+
+ test(function()
+ {
+ var a = document.createTextNode("a")
+ var b = document.createElement("b")
+ assert_throws("NOT_FOUND_ERR", function(){a.appendChild(b)});
+ }, "Test throw DOM exception expected to fail")
+
+ test(function()
+ {
+ var e = {code:0, name:"TEST_ERR", TEST_ERR:0}
+ assert_throws("TEST_ERR", function() {throw e});
+ }, "Test assert_throws with non-DOM-exception expected to Fail");
+
+ var t = async_test("Test step_func")
+ setTimeout(
+ t.step_func(
+ function () {
+ assert_true(true); t.done();
+ }), 0);
+
+ async_test(function(t) {
+ setTimeout(t.step_func(function (){assert_true(true); t.done();}), 0);
+ }, "Test async test with callback");
+
+ async_test(function() {
+ setTimeout(this.step_func(function (){assert_true(true); this.done();}), 0);
+ }, "Test async test with callback and `this` obj.");
+
+ async_test("test should timeout (fail) with the default of 2 seconds").step(function(){});
+
+ async_test("test should timeout (fail) with a custom set timeout value of 1 second",
+ {timeout:1000}).step(function(){});
+
+ async_test("async test that is never started, should have status Not Run", {timeout:1000});
+
+
+ test(function(t) {
+ window.global = 1;
+ t.add_cleanup(function() {delete window.global});
+ assert_equals(window.global, 1);
+ },
+ "Test that defines a global and cleans it up");
+
+ test(function() {assert_equals(window.global, undefined)},
+ "Test that cleanup handlers from previous test ran");
+
+</script>
+</body>
+</html>
+
+
+
diff --git a/tests/wpt/web-platform-tests/resources/apisample10.html b/tests/wpt/web-platform-tests/resources/apisample10.html
new file mode 100644
index 00000000000..a1a7070fbfd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/apisample10.html
@@ -0,0 +1,119 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>Async Tests and Promises</title>
+</head>
+<body>
+<h1>Async Tests and Promises</h1>
+<p>This test assumes ECMAScript 6 Promise support. Some failures are expected.</p>
+<div id="log"></div>
+<script src="testharness.js"></script>
+<script src="testharnessreport.js"></script>
+<script>
+
+test(function() {
+ var p = new Promise(function(resolve, reject) {});
+ assert_true('then' in p);
+ assert_equals(typeof Promise.resolve, 'function');
+ assert_equals(typeof Promise.reject, 'function');
+}, "Promises are supported in your browser");
+
+(function() {
+ var t = async_test("Promise resolution");
+ t.step(function() {
+ Promise.resolve('x').then(
+ t.step_func(function(value) {
+ assert_equals(value, 'x');
+ t.done();
+ }),
+ t.unreached_func('Promise should not reject')
+ );
+ });
+}());
+
+(function() {
+ var t = async_test("Promise rejection");
+ t.step(function() {
+ Promise.reject(Error('fail')).then(
+ t.unreached_func('Promise should reject'),
+ t.step_func(function(reason) {
+ assert_true(reason instanceof Error);
+ assert_equals(reason.message, 'fail');
+ t.done();
+ })
+ );
+ });
+}());
+
+(function() {
+ var t = async_test("Promises resolution chaining");
+ t.step(function() {
+ var resolutions = [];
+ Promise.resolve('a').then(
+ t.step_func(function(value) {
+ resolutions.push(value);
+ return 'b';
+ })
+ ).then(
+ t.step_func(function(value) {
+ resolutions.push(value);
+ return 'c';
+ })
+ ).then(
+ t.step_func(function(value) {
+ resolutions.push(value);
+
+ assert_array_equals(resolutions, ['a', 'b', 'c']);
+ t.done();
+ })
+ ).catch(
+ t.unreached_func('promise should not have rejected')
+ );
+ });
+}());
+
+(function() {
+ var t = async_test("Use of step_func with Promises");
+ t.step(function() {
+ var resolutions = [];
+ Promise.resolve('x').then(
+ t.step_func_done(),
+ t.unreached_func('Promise should not have rejected')
+ );
+ });
+}());
+
+(function() {
+ var t = async_test("Promises and test assertion failures (should fail)");
+ t.step(function() {
+ var resolutions = [];
+ Promise.resolve('x').then(
+ t.step_func(function(value) {
+ assert_true(false, 'This failure is expected');
+ })
+ ).then(
+ t.unreached_func('Promise should not have resolved')
+ ).catch(
+ t.unreached_func('Promise should not have rejected')
+ );
+ });
+}());
+
+(function() {
+ var t = async_test("Use of unreached_func with Promises (should fail)");
+ t.step(function() {
+ var resolutions = [];
+ var r;
+ var p = new Promise(function(resolve, reject) {
+ // Reject instead of resolve, to demonstrate failure.
+ reject(123);
+ });
+ p.then(
+ function(value) {
+ assert_equals(value, 123, 'This should not actually happen');
+ },
+ t.unreached_func('This failure is expected')
+ );
+ });
+}());
+</script>
diff --git a/tests/wpt/web-platform-tests/resources/apisample11.html b/tests/wpt/web-platform-tests/resources/apisample11.html
new file mode 100644
index 00000000000..d33edd79db9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/apisample11.html
@@ -0,0 +1,99 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>Example with iframe that notifies containing document via callbacks</title>
+<script src="testharness.js"></script>
+<script src="testharnessreport.js"></script>
+</head>
+<body onload="start_test_in_iframe()">
+<h1>Callbacks From Tests Running In An IFRAME</h1>
+<p>A test is run inside an <tt>iframe</tt> with a same origin document. The
+containing document should receive callbacks as the tests progress inside the
+<tt>iframe</tt>. A single passing test is expected in the summary below.
+<div id="log"></div>
+
+<script>
+var callbacks = [];
+var START = 1
+var TEST_STATE = 2
+var RESULT = 3
+var COMPLETION = 4
+var test_complete = false;
+
+setup({explicit_done: true});
+
+// The following callbacks are called for tests in this document as well as the
+// tests in the IFRAME. Currently, callbacks invoked from this document and any
+// child document are indistinguishable from each other.
+
+function start_callback(properties) {
+ callbacks.push(START);
+}
+
+function test_state_callback(test) {
+ callbacks.push(TEST_STATE);
+}
+
+function result_callback(test) {
+ callbacks.push(RESULT);
+}
+
+function completion_callback(tests, status) {
+ if (test_complete) {
+ return;
+ }
+ test_complete = true;
+ callbacks.push(COMPLETION);
+ verify_received_callbacks();
+ done();
+}
+
+function verify_received_callbacks() {
+ var copy_of_callbacks = callbacks.slice(0);
+
+ // Note that you can't run test assertions directly in a callback even if
+ // this is a file test. When the callback is invoked from a same-origin child
+ // page, the callstack reaches into the calling child document. Any
+ // exception thrown in a callback will be handled by the child rather than
+ // this document.
+ test(
+ function() {
+ // callbacks list should look like:
+ // START 1*(TEST_STATE) RESULT COMPLETION
+ assert_equals(copy_of_callbacks.shift(), START,
+ "The first received callback should be 'start_callback'.");
+ assert_equals(copy_of_callbacks.shift(), TEST_STATE,
+ "'test_state_callback' should be received before any " +
+ "result or completion callbacks.");
+ while(copy_of_callbacks.length > 0) {
+ var callback = copy_of_callbacks.shift();
+ if (callback != TEST_STATE) {
+ copy_of_callbacks.unshift(callback);
+ break;
+ }
+ }
+ assert_equals(copy_of_callbacks.shift(), RESULT,
+ "'test_state_callback' should be followed by 'result_callback'.");
+ assert_equals(copy_of_callbacks.shift(), COMPLETION,
+ "Final 'result_callback' should be followed by 'completion_callback'.");
+ assert_equals(copy_of_callbacks.length, 0,
+ "'completion_callback' should be the last callback.");
+ });
+}
+
+function start_test_in_iframe() {
+ // This document is going to clear any received callbacks and maintain
+ // radio silence until the test in the iframe runs to completion. The
+ // completion_callback() will then complete the testing on this document.
+ callbacks.length = 0;
+ var iframe = document.createElement("iframe");
+ // apisample6.html has a single test.
+ iframe.src = "apisample6.html";
+ iframe.style.setProperty("display", "none");
+ document.getElementById("target").appendChild(iframe);
+}
+</script>
+
+<div id="target">
+</div>
+</body>
diff --git a/tests/wpt/web-platform-tests/resources/apisample12.html b/tests/wpt/web-platform-tests/resources/apisample12.html
new file mode 100644
index 00000000000..e16ebcf44e8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/apisample12.html
@@ -0,0 +1,67 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>Example with iframe that notifies containing document via cross document messaging</title>
+<script src="testharness.js"></script>
+<script src="testharnessreport.js"></script>
+</head>
+<body>
+<h1>Notifications From Tests Running In An IFRAME</h1>
+<p>A test is run inside an <tt>iframe</tt> with a same origin document. The
+containing document should receive messages via <tt>postMessage</tt>/
+<tt>onmessage</tt> as the tests progress inside the <tt>iframe</tt>. A single
+passing test is expected in the summary below.
+</p>
+<div id="log"></div>
+
+<script>
+var t = async_test("Containing document receives messages");
+var start_received = false;
+var result_received = false;
+var completion_received = false;
+
+// These are the messages that are expected to be seen while running the tests
+// in the IFRAME.
+var expected_messages = [
+ t.step_func(
+ function(message) {
+ assert_equals(message.data.type, "start");
+ assert_own_property(message.data, "properties");
+ }),
+
+ t.step_func(
+ function(message) {
+ assert_equals(message.data.type, "test_state");
+ assert_equals(message.data.test.status, message.data.test.NOTRUN);
+ }),
+
+ t.step_func(
+ function(message) {
+ assert_equals(message.data.type, "result");
+ assert_equals(message.data.test.status, message.data.test.PASS);
+ }),
+
+ t.step_func(
+ function(message) {
+ assert_equals(message.data.type, "complete");
+ assert_equals(message.data.tests.length, 1);
+ assert_equals(message.data.tests[0].status,
+ message.data.tests[0].PASS);
+ assert_equals(message.data.status.status, message.data.status.OK);
+ t.done();
+ }),
+
+ t.unreached_func("Too many messages received")
+];
+
+on_event(window,
+ "message",
+ function(message) {
+ var handler = expected_messages.shift();
+ handler(message);
+ });
+</script>
+<iframe src="apisample6.html" style="display:none">
+ <!-- apisample6 implements a file_is_test test. -->
+</iframe>
+</body>
diff --git a/tests/wpt/web-platform-tests/resources/apisample13.html b/tests/wpt/web-platform-tests/resources/apisample13.html
new file mode 100644
index 00000000000..cddd90fe508
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/apisample13.html
@@ -0,0 +1,132 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>Promise Tests</title>
+</head>
+<body>
+<h1>Promise Tests</h1>
+<p>This test demonstrates the use of <tt>promise_test</tt>. Assumes ECMAScript 6
+Promise support. Some failures are expected.</p>
+<div id="log"></div>
+<script src="testharness.js"></script>
+<script src="testharnessreport.js"></script>
+<script>
+test(
+ function() {
+ var p = new Promise(function(resolve, reject){});
+ assert_true("then" in p);
+ assert_equals(typeof Promise.resolve, "function");
+ assert_equals(typeof Promise.reject, "function");
+ },
+ "Promises are supported in your browser");
+
+promise_test(
+ function() {
+ return Promise.resolve("x")
+ .then(
+ function(value) {
+ assert_equals(value,
+ "x",
+ "Fulfilled promise should pass result to " +
+ "fulfill reaction.");
+ });
+ },
+ "Promise fulfillment with result");
+
+promise_test(
+ function(t) {
+ return Promise.reject(new Error("fail"))
+ .then(t.unreached_func("Promise should reject"),
+ function(reason) {
+ assert_true(
+ reason instanceof Error,
+ "Rejected promise should pass reason to fulfill reaction.");
+ assert_equals(
+ reason.message,
+ "fail",
+ "Rejected promise should pass reason to reject reaction.");
+ });
+ },
+ "Promise rejection with result");
+
+promise_test(
+ function() {
+ var resolutions = [];
+ return Promise.resolve("a")
+ .then(
+ function(value) {
+ resolutions.push(value);
+ return "b";
+ })
+ .then(
+ function(value) {
+ resolutions.push(value);
+ return "c";
+ })
+ .then(
+ function(value) {
+ resolutions.push(value);
+ assert_array_equals(resolutions, ["a", "b", "c"]);
+ });
+ },
+ "Chain of promise resolutions");
+
+promise_test(
+ function(t) {
+ var resolutions = [];
+ return Promise.resolve("x")
+ .then(
+ function(value) {
+ assert_true(false, "Expected failure.");
+ })
+ .then(t.unreached_func("UNEXPECTED FAILURE: Promise should not have resolved."));
+ },
+ "Assertion failure in a fulfill reaction (should FAIL with an expected failure)");
+
+promise_test(
+ function(t) {
+ return new Promise(
+ function(resolve, reject) {
+ reject(123);
+ })
+ .then(t.unreached_func("UNEXPECTED FAILURE: Fulfill reaction reached after rejection."),
+ t.unreached_func("Expected failure."));
+ },
+ "unreached_func as reactor (should FAIL with an expected failure)");
+
+promise_test(
+ function() {
+ return true;
+ },
+ "promise_test with function that doesn't return a Promise");
+
+promise_test(function(){},
+ "promise_test with function that doesn't return anything");
+
+promise_test(
+ function() {
+ return Promise.reject("Expected rejection");
+ },
+ "promise_test with unhandled rejection (should FAIL)");
+
+promise_test(
+ function() {
+ return Promise.resolve(10)
+ .then(
+ function(value) {
+ throw Error("Expected exception.");
+ });
+ },
+ "promise_test with unhandled exception in fulfill reaction (should FAIL)");
+
+promise_test(
+ function(t) {
+ return Promise.reject(10)
+ .then(
+ t.unreached_func("UNEXPECTED FAILURE: Fulfill reaction reached after rejection."),
+ function(value) {
+ throw Error("Expected exception.");
+ });
+ },
+ "promise_test with unhandled exception in reject reaction (should FAIL)");
+</script>
diff --git a/tests/wpt/web-platform-tests/resources/apisample14.html b/tests/wpt/web-platform-tests/resources/apisample14.html
new file mode 100644
index 00000000000..3d809f97e7f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/apisample14.html
@@ -0,0 +1,29 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>Dedicated Worker Tests</title>
+<script src="testharness.js"></script>
+<script src="testharnessreport.js"></script>
+</head>
+<body>
+<h1>Dedicated Web Worker Tests</h1>
+<p>Demonstrates running <tt>testharness</tt> based tests inside a dedicated web worker.
+<p>The test harness is expected to fail due to an uncaught exception in one worker.</p>
+<div id="log"></div>
+
+<script>
+test(function(t) {
+ assert_true("Worker" in self, "Browser should support Workers");
+ },
+ "Browser supports Workers");
+
+fetch_tests_from_worker(new Worker("apisample-worker.js"));
+
+fetch_tests_from_worker(new Worker("apisample-error-worker.js"));
+
+test(function(t) {
+ assert_false(false, "False is false");
+ },
+ "Test running on main document.");
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/resources/apisample15.html b/tests/wpt/web-platform-tests/resources/apisample15.html
new file mode 100644
index 00000000000..0785797d403
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/apisample15.html
@@ -0,0 +1,26 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>Example with a shared worker</title>
+<script src="testharness.js"></script>
+<script src="testharnessreport.js"></script>
+</head>
+<body>
+<h1>Shared Web Worker Tests</h1>
+<p>Demonstrates running <tt>testharness</tt> based tests inside a shared worker.
+<p>The test harness should time out due to one of the tests in the worker timing out.
+<p>This test assumes that the browser supports <a href="http://www.w3.org/TR/workers/#shared-workers-and-the-sharedworker-interface">shared web workers</a>.
+<div id="log"></div>
+
+<script>
+test(
+ function(t) {
+ assert_true("SharedWorker" in self,
+ "Browser should support SharedWorkers");
+ },
+ "Browser supports SharedWorkers");
+
+fetch_tests_from_worker(new SharedWorker("apisample-worker.js",
+ "My shared worker"));
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/resources/apisample16.html b/tests/wpt/web-platform-tests/resources/apisample16.html
new file mode 100644
index 00000000000..00be84c7530
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/apisample16.html
@@ -0,0 +1,62 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>Example with a service worker</title>
+<script src="testharness.js"></script>
+<script src="testharnessreport.js"></script>
+</head>
+<body>
+<h1>Service Worker Tests</h1>
+<p>Demonstrates running <tt>testharness</tt> based tests inside a service worker.
+<p>The test harness should time out due to one of the tests inside the worker timing out.
+<p>This test assumes that the browser supports <a href="http://www.w3.org/TR/service-workers/">ServiceWorkers</a>.
+<div id="log"></div>
+
+<script>
+test(
+ function(t) {
+ assert_true("serviceWorker" in navigator,
+ "navigator.serviceWorker exists");
+ },
+ "Browser supports ServiceWorker");
+
+promise_test(
+ function() {
+ // Since the service worker registration could be in an indeterminate
+ // state (due to, for example, a previous test run failing), we start by
+ // unregstering our service worker and then registering it again.
+ var scope = "/service-worker-scope";
+ var worker_url = "apisample-worker.js";
+
+ return navigator.serviceWorker.register(worker_url, {scope: scope})
+ .then(
+ function(registration) {
+ return registration.unregister();
+ })
+ .then(
+ function() {
+ return navigator.serviceWorker.register(worker_url, {scope: scope});
+ })
+ .then(
+ function(registration) {
+ add_completion_callback(
+ function() {
+ registration.unregister();
+ });
+
+ return new Promise(
+ function(resolve) {
+ registration.addEventListener("updatefound",
+ function() {
+ resolve(registration.installing);
+ });
+ });
+ })
+ .then(
+ function(worker) {
+ fetch_tests_from_worker(worker);
+ });
+ },
+ "Register ServiceWorker");
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/resources/apisample2.htm b/tests/wpt/web-platform-tests/resources/apisample2.htm
new file mode 100644
index 00000000000..49eed8d9de0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/apisample2.htm
@@ -0,0 +1,19 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>Sample HTML5 API Tests</title>
+</head>
+<body onload="load_test_attr.done()">
+<h1>Sample HTML5 API Tests</h1>
+<p>There should be two results</p>
+<div id="log"></div>
+<script src="testharness.js"></script>
+<script src="testharnessreport.js"></script>
+<script>
+setup({explicit_done:true})
+test(function() {assert_true(true)}, "Test defined before onload");
+
+onload = function() {test(function (){assert_true(true)}, "Test defined after onload");
+done();
+}
+</script>
diff --git a/tests/wpt/web-platform-tests/resources/apisample3.htm b/tests/wpt/web-platform-tests/resources/apisample3.htm
new file mode 100644
index 00000000000..80a892b9dd7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/apisample3.htm
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>Sample HTML5 API Tests</title>
+</head>
+<script src="testharness.js"></script>
+
+<body onload="load_test_attr.done()">
+<h1>Sample HTML5 API Tests</h1>
+<div id="log"></div>
+<script>
+setup({explicit_timeout:true});
+var t = async_test("This test should give a status of 'Not Run' without a delay");
+timeout();
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/resources/apisample4.htm b/tests/wpt/web-platform-tests/resources/apisample4.htm
new file mode 100644
index 00000000000..731a3cb678f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/apisample4.htm
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>Harness Handling Uncaught Exception</title>
+</head>
+<script src="testharness.js"></script>
+
+<body>
+<h1>Harness Handling Uncaught Exception</h1>
+<div id="log"></div>
+<script>
+var t = async_test("This should show a harness status of 'Error' and a test status of 'Not Run'");
+throw new Error("Example Error");
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/resources/apisample5.htm b/tests/wpt/web-platform-tests/resources/apisample5.htm
new file mode 100644
index 00000000000..3853ccf421b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/apisample5.htm
@@ -0,0 +1,18 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>Harness Ignoring Uncaught Exception</title>
+</head>
+<script src="testharness.js"></script>
+
+<body>
+<h1>Harness Ignoring Uncaught Exception</h1>
+<div id="log"></div>
+<script>
+setup({allow_uncaught_exception:true});
+var t = async_test("setup({allow_uncaught_exception:true}) should allow tests to pass even if there is an exception");
+onerror = t.step_func(function() {t.done()});
+throw new Error("Example Error");
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/resources/apisample6.html b/tests/wpt/web-platform-tests/resources/apisample6.html
new file mode 100644
index 00000000000..526e4649d28
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/apisample6.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML>
+<title>Example with file_is_test</title>
+<script src="testharness.js"></script>
+<script src="testharnessreport.js"></script>
+<script>
+onload = function() {
+ assert_true(true);
+ done();
+}
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/apisample7.html b/tests/wpt/web-platform-tests/resources/apisample7.html
new file mode 100644
index 00000000000..03b20efdd1c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/apisample7.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML>
+<title>Example with file_is_test (should fail)</title>
+<script src="testharness.js"></script>
+<script src="testharnessreport.js"></script>
+<script>
+onload = function() {
+ assert_true(false);
+ done();
+}
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/apisample8.html b/tests/wpt/web-platform-tests/resources/apisample8.html
new file mode 100644
index 00000000000..821320f4509
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/apisample8.html
@@ -0,0 +1,8 @@
+<!DOCTYPE HTML>
+<title>Example single page test with no body</title>
+<script src="testharness.js"></script>
+<script src="testharnessreport.js"></script>
+<script>
+assert_true(true);
+done();
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/apisample9.html b/tests/wpt/web-platform-tests/resources/apisample9.html
new file mode 100644
index 00000000000..269a6cf818f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/apisample9.html
@@ -0,0 +1,7 @@
+<!DOCTYPE HTML>
+<title>Example single page test with no asserts</title>
+<script src="testharness.js"></script>
+<script src="testharnessreport.js"></script>
+<script>
+done();
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/docs/api.md b/tests/wpt/web-platform-tests/resources/docs/api.md
new file mode 100644
index 00000000000..4598a9b15a9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/docs/api.md
@@ -0,0 +1,548 @@
+## Introduction ##
+
+testharness.js provides a framework for writing testcases. It is intended to
+provide a convenient API for making common assertions, and to work both
+for testing synchronous and asynchronous DOM features in a way that
+promotes clear, robust, tests.
+
+## Basic Usage ##
+
+The test harness script can be used from HTML or SVG documents and web worker
+scripts.
+
+From an HTML or SVG document, start by importing both `testharness.js` and
+`testharnessreport.js` scripts into the document:
+
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+Refer to the [Web Workers](#web-workers) section for details and an example on
+testing within a web worker.
+
+Within each file one may define one or more tests. Each test is atomic in the
+sense that a single test has a single result (`PASS`/`FAIL`/`TIMEOUT`/`NOTRUN`).
+Within each test one may have a number of asserts. The test fails at the first
+failing assert, and the remainder of the test is (typically) not run.
+
+If the file containing the tests is a HTML file, a table containing the test
+results will be added to the document after all tests have run. By default this
+will be added to a `div` element with `id=log` if it exists, or a new `div`
+element appended to `document.body` if it does not.
+
+NOTE: By default tests must be created before the load event fires. For ways
+to create tests after the load event, see "Determining when all tests
+are complete", below.
+
+## Synchronous Tests ##
+
+To create a synchronous test use the test() function:
+
+ test(test_function, name, properties)
+
+`test_function` is a function that contains the code to test. For example a
+trivial passing test would be:
+
+ test(function() {assert_true(true)}, "assert_true with true")
+
+The function passed in is run in the `test()` call.
+
+`properties` is a javascript object for passing extra options to the
+test. Currently it is only used to provide test-specific
+metadata, as described in the [metadata](#metadata) section below.
+
+## Asynchronous Tests ##
+
+Testing asynchronous features is somewhat more complex since the result of
+a test may depend on one or more events or other callbacks. The API provided
+for testing these features is indended to be rather low-level but hopefully
+applicable to many situations.
+
+To create a test, one starts by getting a Test object using async_test:
+
+ async_test(name, properties)
+
+e.g.
+ var t = async_test("Simple async test")
+
+Assertions can be added to the test by calling the step method of the test
+object with a function containing the test assertions:
+
+ t.step(function() {assert_true(true)});
+
+When all the steps are complete, the done() method must be called:
+
+ t.done();
+
+As a convenience, async_test can also takes a function as first argument.
+This function is called with the test object as both its `this` object and
+first argument. The above example can be rewritten as:
+
+ async_test(function(t) {
+ object.some_event = function() {
+ t.step(function (){assert_true(true); t.done();});
+ };
+ }, "Simple async test");
+
+which avoids cluttering the global scope with references to async
+tests instances.
+
+The properties argument is identical to that for `test()`.
+
+In many cases it is convenient to run a step in response to an event or a
+callback. A convenient method of doing this is through the step_func method
+which returns a function that, when called runs a test step. For example
+
+ object.some_event = t.step_func(function(e) {assert_true(e.a)});
+
+For asynchronous callbacks that should never execute, `unreached_func` can
+be used. For example:
+
+ object.some_event = t.unreached_func("some_event should not fire");
+
+## Promise Tests ##
+
+`promise_test` can be used to test APIs that are based on Promises:
+
+ promise_test(test_function, name, properties)
+
+`test_function` is a function that receives a test as an argument and returns a
+promise. The test completes when the returned promise resolves. The test fails
+if the returned promise rejects.
+
+E.g.:
+
+ function foo() {
+ return Promise.resolve("foo");
+ }
+
+ promise_test(function() {
+ return foo()
+ .then(function(result) {
+ assert_equals(result, "foo", "foo should return 'foo'");
+ });
+ }, "Simple example");
+
+In the example above, `foo()` returns a Promise that resolves with the string
+"foo". The `test_function` passed into `promise_test` invokes `foo` and attaches
+a resolve reaction that verifies the returned value.
+
+Note that in the promise chain constructed in `test_function` assertions don't
+need to wrapped in `step` or `step_func` calls.
+
+`promise_rejects` can be used to test Promises that need to reject:
+
+ promise_rejects(test_object, code, promise)
+
+The `code` argument is equivalent to the same argument to the `assert_throws`
+function.
+
+Here's an example where the `bar()` function returns a Promise that rejects
+with a TypeError:
+
+ function bar() {
+ return Promise.reject(new TypeError());
+ }
+
+ promise_test(function(t) {
+ return promise_rejects(t, new TypeError(), bar);
+ }, "Another example");
+
+## Single Page Tests ##
+
+Sometimes, particularly when dealing with asynchronous behaviour,
+having exactly one test per page is desirable, and the overhead of
+wrapping everything in functions for isolation becomes
+burdensome. For these cases `testharness.js` support "single page
+tests".
+
+In order for a test to be interpreted as a single page test, the
+it must simply not call `test()` or `async_test()` anywhere on the page, and
+must call the `done()` function to indicate that the test is complete. All
+the `assert_*` functions are avaliable as normal, but are called without
+the normal step function wrapper. For example:
+
+ <!doctype html>
+ <title>Example single-page test</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <body>
+ <script>
+ assert_equals(document.body, document.getElementsByTagName("body")[0])
+ done()
+ </script>
+
+The test title for sinple page tests is always taken from `document.title`.
+
+## Making assertions ##
+
+Functions for making assertions start `assert_`. The full list of
+asserts avaliable is documented in the [asserts](#asserts) section
+below.. The general signature is
+
+ assert_something(actual, expected, description)
+
+although not all assertions precisely match this pattern e.g. `assert_true`
+only takes `actual` and `description` as arguments.
+
+The description parameter is used to present more useful error messages when
+a test fails
+
+NOTE: All asserts must be located in a `test()` or a step of an
+`async_test()`, unless the test is a single page test. Asserts outside
+these places won't be detected correctly by the harness and may cause
+unexpected exceptions that will lead to an error in the harness.
+
+## Cleanup ##
+
+Occasionally tests may create state that will persist beyond the test itself.
+In order to ensure that tests are independent, such state should be cleaned
+up once the test has a result. This can be achieved by adding cleanup
+callbacks to the test. Such callbacks are registered using the `add_cleanup`
+function on the test object. All registered callbacks will be run as soon as
+the test result is known. For example
+
+ test(function() {
+ window.some_global = "example";
+ this.add_cleanup(function() {delete window.some_global});
+ assert_true(false);
+ });
+
+## Harness Timeout ##
+
+The overall harness admits two timeout values `"normal"` (the
+default) and `"long"`, used for tests which have an unusually long
+runtime. After the timeout is reached, the harness will stop
+waiting for further async tests to complete. By default the
+timeouts are set to 10s and 60s, respectively, but may be changed
+when the test is run on hardware with different performance
+characteristics to a common desktop computer. In order to opt-in
+to the longer test timeout, the test must specify a meta element:
+
+ <meta name="timeout" content="long">
+
+Occasionally tests may have a race between the harness timing out and
+a particular test failing; typically when the test waits for some event
+that never occurs. In this case it is possible to use `test.force_timeout()`
+in place of `assert_unreached()`, to immediately fail the test but with a
+status of `TIMEOUT`. This should only be used as a last resort when it is
+not possible to make the test reliable in some other way.
+
+## Setup ##
+
+Sometimes tests require non-trivial setup that may fail. For this purpose
+there is a `setup()` function, that may be called with one or two arguments.
+The two argument version is:
+
+ setup(func, properties)
+
+The one argument versions may omit either argument.
+func is a function to be run synchronously. `setup()` becomes a no-op once
+any tests have returned results. Properties are global properties of the test
+harness. Currently recognised properties are:
+
+`explicit_done` - Wait for an explicit call to done() before declaring all
+tests complete (see below; implicitly true for single page tests)
+
+`output_document` - The document to which results should be logged. By default
+this is the current document but could be an ancestor document in some cases
+e.g. a SVG test loaded in an HTML wrapper
+
+`explicit_timeout` - disable file timeout; only stop waiting for results
+when the `timeout()` function is called (typically for use when integrating
+with some existing test framework that has its own timeout mechanism).
+
+`allow_uncaught_exception` - don't treat an uncaught exception as an error;
+needed when e.g. testing the `window.onerror` handler.
+
+`timeout_multiplier` - Multiplier to apply to per-test timeouts.
+
+## Determining when all tests are complete ##
+
+By default the test harness will assume there are no more results to come
+when:
+
+ 1. There are no `Test` objects that have been created but not completed
+ 2. The load event on the document has fired
+
+This behaviour can be overridden by setting the `explicit_done` property to
+true in a call to `setup()`. If `explicit_done` is true, the test harness will
+not assume it is done until the global `done()` function is called. Once `done()`
+is called, the two conditions above apply like normal.
+
+Dedicated and shared workers don't have an event that corresponds to the `load`
+event in a document. Therefore these worker tests always behave as if the
+`explicit_done` property is set to true. Service workers depend on the
+[install](https://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html#service-worker-global-scope-install-event)
+event which is fired following the completion of [running the
+worker](https://html.spec.whatwg.org/multipage/workers.html#run-a-worker).
+
+## Generating tests ##
+
+There are scenarios in which is is desirable to create a large number of
+(synchronous) tests that are internally similar but vary in the parameters
+used. To make this easier, the `generate_tests` function allows a single
+function to be called with each set of parameters in a list:
+
+ generate_tests(test_function, parameter_lists, properties)
+
+For example:
+
+ generate_tests(assert_equals, [
+ ["Sum one and one", 1+1, 2],
+ ["Sum one and zero", 1+0, 1]
+ ])
+
+Is equivalent to:
+
+ test(function() {assert_equals(1+1, 2)}, "Sum one and one")
+ test(function() {assert_equals(1+0, 1)}, "Sum one and zero")
+
+Note that the first item in each parameter list corresponds to the name of
+the test.
+
+The properties argument is identical to that for `test()`. This may be a
+single object (used for all generated tests) or an array.
+
+## Callback API ##
+
+The framework provides callbacks corresponding to 4 events:
+
+ * `start` - triggered when the first Test is created
+ * `test_state` - triggered when a test state changes
+ * `result` - triggered when a test result is recieved
+ * `complete` - triggered when all results are recieved
+
+The page defining the tests may add callbacks for these events by calling
+the following methods:
+
+ `add_start_callback(callback)` - callback called with no arguments
+
+ `add_test_state_callback(callback)` - callback called with a test argument
+
+ `add_result_callback(callback)` - callback called with a test argument
+
+ `add_completion_callback(callback)` - callback called with an array of tests
+ and an status object
+
+tests have the following properties:
+
+ * `status` - A status code. This can be compared to the `PASS`, `FAIL`,
+ `TIMEOUT` and `NOTRUN` properties on the test object
+
+ * `message` - A message indicating the reason for failure. In the future this
+ will always be a string
+
+ The status object gives the overall status of the harness. It has the
+ following properties:
+
+ * `status` - Can be compared to the `OK`, `ERROR` and `TIMEOUT` properties
+
+ * `message` - An error message set when the status is `ERROR`
+
+## External API ##
+
+In order to collect the results of multiple pages containing tests, the test
+harness will, when loaded in a nested browsing context, attempt to call
+certain functions in each ancestor and opener browsing context:
+
+ * start - `start_callback`
+ * test\_state - `test_state_callback`
+ * result - `result_callback`
+ * complete - `completion_callback`
+
+These are given the same arguments as the corresponding internal callbacks
+described above.
+
+## External API through cross-document messaging ##
+
+Where supported, the test harness will also send messages using cross-document
+messaging to each ancestor and opener browsing context. Since it uses the
+wildcard keyword (\*), cross-origin communication is enabled and script on
+different origins can collect the results.
+
+This API follows similar conventions as those described above only slightly
+modified to accommodate message event API. Each message is sent by the harness
+is passed a single vanilla object, available as the `data` property of the event
+object. These objects are structures as follows:
+
+ * start - `{ type: "start" }`
+ * test\_state - `{ type: "test_state", test: Test }`
+ * result - `{ type: "result", test: Test }`
+ * complete - `{ type: "complete", tests: [Test, ...], status: TestsStatus }`
+
+## Web Workers ##
+
+The `testharness.js` script can be used from within [dedicated workers, shared
+workers](https://html.spec.whatwg.org/multipage/workers.html) and [service
+workers](https://slightlyoff.github.io/ServiceWorker/spec/service_worker/).
+
+Testing from a worker script is different from testing from an HTML document in
+several ways:
+
+* Workers have no reporting capability since they are runing in the background.
+ Hence they rely on `testharness.js` running in a companion client HTML document
+ for reporting.
+
+* Shared and service workers do not have a unique client document since there
+ could be more than one document that communicates with these workers. So a
+ client document needs to explicitly connect to a worker and fetch test results
+ from it using `fetch_tests_from_worker`. This is true even for a dedicated
+ worker. Once connected, the individual tests running in the worker (or those
+ that have already run to completion) will be automatically reflected in the
+ client document.
+
+* The client document controls the timeout of the tests. All worker scripts act
+ as if they were started with the `explicit_timeout` option (see the [Harness
+ timeout](#harness-timeout) section).
+
+* Dedicated and shared workers don't have an equivalent of an `onload` event.
+ Thus the test harness has no way to know when all tests have completed (see
+ [Determining when all tests are
+ complete](#determining-when-all-tests-are-complete)). So these worker tests
+ behave as if they were started with the `explicit_done` option. Service
+ workers depend on the
+ [oninstall](https://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html#service-worker-global-scope-install-event)
+ event and don't require an explicit `done` call.
+
+Here's an example that uses a dedicated worker.
+
+`worker.js`:
+
+ importScripts("/resources/testharness.js");
+
+ test(function(t) {
+ assert_true(true, "true is true");
+ }, "Simple test");
+
+ // done() is needed because the testharness is running as if explicit_done
+ // was specified.
+ done();
+
+`test.html`:
+
+ <!DOCTYPE html>
+ <title>Simple test</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <div id="log"></div>
+ <script>
+
+ fetch_tests_from_worker(new Worker("worker.js"));
+
+ </script>
+
+The argument to the `fetch_tests_from_worker` function can be a
+[`Worker`](https://html.spec.whatwg.org/multipage/workers.html#dedicated-workers-and-the-worker-interface),
+a [`SharedWorker`](https://html.spec.whatwg.org/multipage/workers.html#shared-workers-and-the-sharedworker-interface)
+or a [`ServiceWorker`](https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#service-worker-obj).
+Once called, the containing document fetches all the tests from the worker and
+behaves as if those tests were running in the containing document itself.
+
+## List of Assertions ##
+
+### `assert_true(actual, description)`
+asserts that `actual` is strictly true
+
+### `assert_false(actual, description)`
+asserts that `actual` is strictly false
+
+### `assert_equals(actual, expected, description)`
+asserts that `actual` is the same value as `expected`
+
+### `assert_not_equals(actual, expected, description)`
+asserts that `actual` is a different value to `expected`.
+This means that `expected` is a misnomer.
+
+### `assert_in_array(actual, expected, description)`
+asserts that `expected` is an Array, and `actual` is equal to one of the
+members i.e. `expected.indexOf(actual) != -1`
+
+### `assert_array_equals(actual, expected, description)`
+asserts that `actual` and `expected` have the same
+length and the value of each indexed property in `actual` is the strictly equal
+to the corresponding property value in `expected`
+
+### `assert_approx_equals(actual, expected, epsilon, description)`
+asserts that `actual` is a number within +`- `epsilon` of `expected`
+
+### `assert_less_than(actual, expected, description)`
+asserts that `actual` is a number less than `expected`
+
+### `assert_greater_than(actual, expected, description)`
+asserts that `actual` is a number greater than `expected`
+
+### `assert_between_exclusive(actual, lower, upper, description`
+asserts that `actual` is a number between `lower` and `upper` but not
+equal to either of them
+
+### `assert_less_than_equal(actual, expected, description)`
+asserts that `actual` is a number less than or equal to `expected`
+
+### `assert_greater_than_equal(actual, expected, description)`
+asserts that `actual` is a number greater than or equal to `expected`
+
+### `assert_between_inclusive(actual, lower, upper, description`
+asserts that `actual` is a number between `lower` and `upper` or
+equal to either of them
+
+### `assert_regexp_match(actual, expected, description)`
+asserts that `actual` matches the regexp `expected`
+
+### `assert_class_string(object, class_name, description)`
+asserts that the class string of `object` as returned in
+`Object.prototype.toString` is equal to `class_name`.
+
+### `assert_own_property(object, property_name, description)`
+assert that object has own property `property_name`
+
+### `assert_inherits(object, property_name, description)`
+assert that object does not have an own property named
+`property_name` but that `property_name` is present in the prototype
+chain for object
+
+### `assert_idl_attribute(object, attribute_name, description)`
+assert that an object that is an instance of some interface has the
+attribute attribute_name following the conditions specified by WebIDL
+
+### `assert_readonly(object, property_name, description)`
+assert that property `property_name` on object is readonly
+
+### `assert_throws(code, func, description)`
+`code` - the expected exception. This can take several forms:
+
+ * string - the thrown exception must be a DOMException with the given
+ name, e.g., "TimeoutError" (for compatibility with existing
+ tests, a constant is also supported, e.g., "TIMEOUT_ERR")
+ * object - the thrown exception must have a property called "name" that
+ matches code.name
+ * null - allow any exception (in general, one of the options above
+ should be used)
+
+`func` - a function that should throw
+
+### `assert_unreached(description)`
+asserts if called. Used to ensure that some codepath is *not* taken e.g.
+an event does not fire.
+
+### `assert_any(assert_func, actual, expected_array, extra_arg_1, ... extra_arg_N)`
+asserts that one `assert_func(actual, expected_array_N, extra_arg1, ..., extra_arg_N)`
+ is true for some `expected_array_N` in `expected_array`. This only works for `assert_func`
+ with signature `assert_func(actual, expected, args_1, ..., args_N)`. Note that tests
+ with multiple allowed pass conditions are bad practice unless the spec specifically
+ allows multiple behaviours. Test authors should not use this method simply to hide
+ UA bugs.
+
+### `assert_exists(object, property_name, description)`
+**deprecated**
+asserts that object has an own property `property_name`
+
+### `assert_not_exists(object, property_name, description)`
+**deprecated**
+assert that object does not have own property `property_name`
+
+## Metadata ##
+
+It is possible to add optional metadata to tests; this can be done in
+one of two ways; either by adding `<meta>` elements to the head of the
+document containing the tests, or by adding the metadata to individual
+`[async_]test` calls, as properties.
diff --git a/tests/wpt/web-platform-tests/resources/docs/idlharness.md b/tests/wpt/web-platform-tests/resources/docs/idlharness.md
new file mode 100644
index 00000000000..52f590070cd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/docs/idlharness.md
@@ -0,0 +1,118 @@
+## Introduction ##
+
+`idlharness.js` automatically generates browser tests for WebIDL interfaces, using
+the testharness.js framework. To use, first include the following:
+
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+ <script src=/resources/WebIDLParser.js></script>
+ <script src=/resources/idlharness.js></script>
+
+Then you'll need some type of IDLs. Here's some script that can be run on a
+spec written in HTML, which will grab all the elements with `class="idl"`,
+concatenate them, and replace the body so you can copy-paste:
+
+ var s = "";
+ [].forEach.call(document.getElementsByClassName("idl"), function(idl) {
+ //https://www.w3.org/Bugs/Public/show_bug.cgi?id=14914
+ if (!idl.classList.contains("extract"))
+ {
+ s += idl.textContent + "\n\n";
+ }
+ });
+ document.body.innerHTML = '<pre></pre>';
+ document.body.firstChild.textContent = s;
+
+Once you have that, put it in your script somehow. The easiest way is to
+embed it literally in an HTML file with `<script type=text/plain>` or similar,
+so that you don't have to do any escaping. Another possibility is to put it
+in a separate .idl file that's fetched via XHR or similar. Sample usage:
+
+ var idl_array = new IdlArray();
+ idl_array.add_untested_idls("interface Node { readonly attribute DOMString nodeName; };");
+ idl_array.add_idls("interface Document : Node { readonly attribute DOMString URL; };");
+ idl_array.add_objects({Document: ["document"]});
+ idl_array.test();
+
+This tests that `window.Document` exists and meets all the requirements of
+WebIDL. It also tests that window.document (the result of evaluating the
+string "document") has URL and nodeName properties that behave as they
+should, and otherwise meets WebIDL's requirements for an object whose
+primary interface is Document. It does not test that window.Node exists,
+which is what you want if the Node interface is already tested in some other
+specification's suite and your specification only extends or refers to it.
+Of course, each IDL string can define many different things, and calls to
+add_objects() can register many different objects for different interfaces:
+this is a very simple example.
+
+## Public methods of IdlArray ##
+
+IdlArray objects can be obtained with `new IdlArray()`. Anything not
+documented in this section should be considered an implementation detail,
+and outside callers should not use it.
+
+### `add_idls(idl_string)`
+ Parses `idl_string` (throwing on parse error) and adds the results to the
+ IdlArray. All the definitions will be tested when you run test(). If
+ some of the definitions refer to other definitions, those must be present
+ too. For instance, if `idl_string` says that `Document` inherits from `Node`,
+ the `Node` interface must also have been provided in some call to `add_idls()`
+ or `add_untested_idls()`.
+
+### `add_untested_idls(idl_string)`
+ Like `add_idls()`, but the definitions will not be tested. If an untested
+ interface is added and then extended with a tested partial interface, the
+ members of the partial interface will still be tested. Also, all the
+ members will still be tested for objects added with `add_objects()`, because
+ you probably want to test that (for instance) window.document has all the
+ properties from `Node`, not just `Document`, even if the `Node` interface itself
+ is tested in a different test suite.
+
+### `add_objects(dict)`
+ `dict` should be an object whose keys are the names of interfaces or
+ exceptions, and whose values are arrays of strings. When an interface or
+ exception is tested, every string registered for it with `add_objects()`
+ will be evaluated, and tests will be run on the result to verify that it
+ correctly implements that interface or exception. This is the only way to
+ test anything about `[NoInterfaceObject]` interfaces, and there are many
+ tests that can't be run on any interface without an object to fiddle with.
+
+ The interface has to be the *primary* interface of all the objects
+ provided. For example, don't pass `{Node: ["document"]}`, but rather
+ `{Document: ["document"]}`. Assuming the `Document` interface was declared to
+ inherit from `Node`, this will automatically test that document implements
+ the `Node` interface too.
+
+ Warning: methods will be called on any provided objects, in a manner that
+ WebIDL requires be safe. For instance, if a method has mandatory
+ arguments, the test suite will try calling it with too few arguments to
+ see if it throws an exception. If an implementation incorrectly runs the
+ function instead of throwing, this might have side effects, possibly even
+ preventing the test suite from running correctly.
+
+### `prevent_multiple_testing(name)`
+ This is a niche method for use in case you're testing many objects that
+ implement the same interfaces, and don't want to retest the same
+ interfaces every single time. For instance, HTML defines many interfaces
+ that all inherit from `HTMLElement`, so the HTML test suite has something
+ like
+ `.add_objects({
+ HTMLHtmlElement: ['document.documentElement'],
+ HTMLHeadElement: ['document.head'],
+ HTMLBodyElement: ['document.body'],
+ ...
+ })`
+ and so on for dozens of element types. This would mean that it would
+ retest that each and every one of those elements implements `HTMLElement`,
+ `Element`, and `Node`, which would be thousands of basically redundant tests.
+ The test suite therefore calls `prevent_multiple_testing("HTMLElement")`.
+ This means that once one object has been tested to implement `HTMLElement`
+ and its ancestors, no other object will be. Thus in the example code
+ above, the harness would test that `document.documentElement` correctly
+ implements `HTMLHtmlElement`, `HTMLElement`, `Element`, and `Node`; but
+ `document.head` would only be tested for `HTMLHeadElement`, and so on for
+ further objects.
+
+### `test()`
+ Run all tests. This should be called after you've called all other
+ methods to add IDLs and objects.
diff --git a/tests/wpt/web-platform-tests/resources/idlharness.js b/tests/wpt/web-platform-tests/resources/idlharness.js
new file mode 100644
index 00000000000..884daeae216
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/idlharness.js
@@ -0,0 +1,1636 @@
+/*
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+*/
+
+/* For user documentation see docs/idlharness.md */
+
+/**
+ * Notes for people who want to edit this file (not just use it as a library):
+ *
+ * Most of the interesting stuff happens in the derived classes of IdlObject,
+ * especially IdlInterface. The entry point for all IdlObjects is .test(),
+ * which is called by IdlArray.test(). An IdlObject is conceptually just
+ * "thing we want to run tests on", and an IdlArray is an array of IdlObjects
+ * with some additional data thrown in.
+ *
+ * The object model is based on what WebIDLParser.js produces, which is in turn
+ * based on its pegjs grammar. If you want to figure out what properties an
+ * object will have from WebIDLParser.js, the best way is to look at the
+ * grammar:
+ *
+ * https://github.com/darobin/webidl.js/blob/master/lib/grammar.peg
+ *
+ * So for instance:
+ *
+ * // interface definition
+ * interface
+ * = extAttrs:extendedAttributeList? S? "interface" S name:identifier w herit:ifInheritance? w "{" w mem:ifMember* w "}" w ";" w
+ * { return { type: "interface", name: name, inheritance: herit, members: mem, extAttrs: extAttrs }; }
+ *
+ * This means that an "interface" object will have a .type property equal to
+ * the string "interface", a .name property equal to the identifier that the
+ * parser found, an .inheritance property equal to either null or the result of
+ * the "ifInheritance" production found elsewhere in the grammar, and so on.
+ * After each grammatical production is a JavaScript function in curly braces
+ * that gets called with suitable arguments and returns some JavaScript value.
+ *
+ * (Note that the version of WebIDLParser.js we use might sometimes be
+ * out-of-date or forked.)
+ *
+ * The members and methods of the classes defined by this file are all at least
+ * briefly documented, hopefully.
+ */
+(function(){
+"use strict";
+/// Helpers ///
+function constValue (cnt) {
+ if (cnt.type === "null") return null;
+ if (cnt.type === "NaN") return NaN;
+ if (cnt.type === "Infinity") return cnt.negative ? -Infinity : Infinity;
+ return cnt.value;
+}
+
+/// IdlArray ///
+// Entry point
+self.IdlArray = function()
+//@{
+{
+ /**
+ * A map from strings to the corresponding named IdlObject, such as
+ * IdlInterface or IdlException. These are the things that test() will run
+ * tests on.
+ */
+ this.members = {};
+
+ /**
+ * A map from strings to arrays of strings. The keys are interface or
+ * exception names, and are expected to also exist as keys in this.members
+ * (otherwise they'll be ignored). This is populated by add_objects() --
+ * see documentation at the start of the file. The actual tests will be
+ * run by calling this.members[name].test_object(obj) for each obj in
+ * this.objects[name]. obj is a string that will be eval'd to produce a
+ * JavaScript value, which is supposed to be an object implementing the
+ * given IdlObject (interface, exception, etc.).
+ */
+ this.objects = {};
+
+ /**
+ * When adding multiple collections of IDLs one at a time, an earlier one
+ * might contain a partial interface or implements statement that depends
+ * on a later one. Save these up and handle them right before we run
+ * tests.
+ *
+ * .partials is simply an array of objects from WebIDLParser.js'
+ * "partialinterface" production. .implements maps strings to arrays of
+ * strings, such that
+ *
+ * A implements B;
+ * A implements C;
+ * D implements E;
+ *
+ * results in { A: ["B", "C"], D: ["E"] }.
+ */
+ this.partials = [];
+ this["implements"] = {};
+};
+
+//@}
+IdlArray.prototype.add_idls = function(raw_idls)
+//@{
+{
+ /** Entry point. See documentation at beginning of file. */
+ this.internal_add_idls(WebIDL2.parse(raw_idls));
+};
+
+//@}
+IdlArray.prototype.add_untested_idls = function(raw_idls)
+//@{
+{
+ /** Entry point. See documentation at beginning of file. */
+ var parsed_idls = WebIDL2.parse(raw_idls);
+ for (var i = 0; i < parsed_idls.length; i++)
+ {
+ parsed_idls[i].untested = true;
+ if ("members" in parsed_idls[i])
+ {
+ for (var j = 0; j < parsed_idls[i].members.length; j++)
+ {
+ parsed_idls[i].members[j].untested = true;
+ }
+ }
+ }
+ this.internal_add_idls(parsed_idls);
+};
+
+//@}
+IdlArray.prototype.internal_add_idls = function(parsed_idls)
+//@{
+{
+ /**
+ * Internal helper called by add_idls() and add_untested_idls().
+ * parsed_idls is an array of objects that come from WebIDLParser.js's
+ * "definitions" production. The add_untested_idls() entry point
+ * additionally sets an .untested property on each object (and its
+ * .members) so that they'll be skipped by test() -- they'll only be
+ * used for base interfaces of tested interfaces, return types, etc.
+ */
+ parsed_idls.forEach(function(parsed_idl)
+ {
+ if (parsed_idl.type == "interface" && parsed_idl.partial)
+ {
+ this.partials.push(parsed_idl);
+ return;
+ }
+
+ if (parsed_idl.type == "implements")
+ {
+ if (!(parsed_idl.target in this["implements"]))
+ {
+ this["implements"][parsed_idl.target] = [];
+ }
+ this["implements"][parsed_idl.target].push(parsed_idl["implements"]);
+ return;
+ }
+
+ parsed_idl.array = this;
+ if (parsed_idl.name in this.members)
+ {
+ throw "Duplicate identifier " + parsed_idl.name;
+ }
+ switch(parsed_idl.type)
+ {
+ case "interface":
+ this.members[parsed_idl.name] =
+ new IdlInterface(parsed_idl, /* is_callback = */ false);
+ break;
+
+ case "dictionary":
+ // Nothing to test, but we need the dictionary info around for type
+ // checks
+ this.members[parsed_idl.name] = new IdlDictionary(parsed_idl);
+ break;
+
+ case "typedef":
+ this.members[parsed_idl.name] = new IdlTypedef(parsed_idl);
+ break;
+
+ case "callback":
+ // TODO
+ console.log("callback not yet supported");
+ break;
+
+ case "enum":
+ this.members[parsed_idl.name] = new IdlEnum(parsed_idl);
+ break;
+
+ case "callback interface":
+ this.members[parsed_idl.name] =
+ new IdlInterface(parsed_idl, /* is_callback = */ true);
+ break;
+
+ default:
+ throw parsed_idl.name + ": " + parsed_idl.type + " not yet supported";
+ }
+ }.bind(this));
+};
+
+//@}
+IdlArray.prototype.add_objects = function(dict)
+//@{
+{
+ /** Entry point. See documentation at beginning of file. */
+ for (var k in dict)
+ {
+ if (k in this.objects)
+ {
+ this.objects[k] = this.objects[k].concat(dict[k]);
+ }
+ else
+ {
+ this.objects[k] = dict[k];
+ }
+ }
+};
+
+//@}
+IdlArray.prototype.prevent_multiple_testing = function(name)
+//@{
+{
+ /** Entry point. See documentation at beginning of file. */
+ this.members[name].prevent_multiple_testing = true;
+};
+
+//@}
+IdlArray.prototype.recursively_get_implements = function(interface_name)
+//@{
+{
+ /**
+ * Helper function for test(). Returns an array of things that implement
+ * interface_name, so if the IDL contains
+ *
+ * A implements B;
+ * B implements C;
+ * B implements D;
+ *
+ * then recursively_get_implements("A") should return ["B", "C", "D"].
+ */
+ var ret = this["implements"][interface_name];
+ if (ret === undefined)
+ {
+ return [];
+ }
+ for (var i = 0; i < this["implements"][interface_name].length; i++)
+ {
+ ret = ret.concat(this.recursively_get_implements(ret[i]));
+ if (ret.indexOf(ret[i]) != ret.lastIndexOf(ret[i]))
+ {
+ throw "Circular implements statements involving " + ret[i];
+ }
+ }
+ return ret;
+};
+
+//@}
+IdlArray.prototype.test = function()
+//@{
+{
+ /** Entry point. See documentation at beginning of file. */
+
+ // First merge in all the partial interfaces and implements statements we
+ // encountered.
+ this.partials.forEach(function(parsed_idl)
+ {
+ if (!(parsed_idl.name in this.members)
+ || !(this.members[parsed_idl.name] instanceof IdlInterface))
+ {
+ throw "Partial interface " + parsed_idl.name + " with no original interface";
+ }
+ if (parsed_idl.extAttrs)
+ {
+ parsed_idl.extAttrs.forEach(function(extAttr)
+ {
+ this.members[parsed_idl.name].extAttrs.push(extAttr);
+ }.bind(this));
+ }
+ parsed_idl.members.forEach(function(member)
+ {
+ this.members[parsed_idl.name].members.push(new IdlInterfaceMember(member));
+ }.bind(this));
+ }.bind(this));
+ this.partials = [];
+
+ for (var lhs in this["implements"])
+ {
+ this.recursively_get_implements(lhs).forEach(function(rhs)
+ {
+ var errStr = lhs + " implements " + rhs + ", but ";
+ if (!(lhs in this.members)) throw errStr + lhs + " is undefined.";
+ if (!(this.members[lhs] instanceof IdlInterface)) throw errStr + lhs + " is not an interface.";
+ if (!(rhs in this.members)) throw errStr + rhs + " is undefined.";
+ if (!(this.members[rhs] instanceof IdlInterface)) throw errStr + rhs + " is not an interface.";
+ this.members[rhs].members.forEach(function(member)
+ {
+ this.members[lhs].members.push(new IdlInterfaceMember(member));
+ }.bind(this));
+ }.bind(this));
+ }
+ this["implements"] = {};
+
+ // Now run test() on every member, and test_object() for every object.
+ for (var name in this.members)
+ {
+ this.members[name].test();
+ if (name in this.objects)
+ {
+ this.objects[name].forEach(function(str)
+ {
+ this.members[name].test_object(str);
+ }.bind(this));
+ }
+ }
+};
+
+//@}
+IdlArray.prototype.assert_type_is = function(value, type)
+//@{
+{
+ /**
+ * Helper function that tests that value is an instance of type according
+ * to the rules of WebIDL. value is any JavaScript value, and type is an
+ * object produced by WebIDLParser.js' "type" production. That production
+ * is fairly elaborate due to the complexity of WebIDL's types, so it's
+ * best to look at the grammar to figure out what properties it might have.
+ */
+ if (type.idlType == "any")
+ {
+ // No assertions to make
+ return;
+ }
+
+ if (type.nullable && value === null)
+ {
+ // This is fine
+ return;
+ }
+
+ if (type.array)
+ {
+ // TODO: not supported yet
+ return;
+ }
+
+ if (type.sequence)
+ {
+ assert_true(Array.isArray(value), "is not array");
+ if (!value.length)
+ {
+ // Nothing we can do.
+ return;
+ }
+ this.assert_type_is(value[0], type.idlType.idlType);
+ return;
+ }
+
+ type = type.idlType;
+
+ switch(type)
+ {
+ case "void":
+ assert_equals(value, undefined);
+ return;
+
+ case "boolean":
+ assert_equals(typeof value, "boolean");
+ return;
+
+ case "byte":
+ assert_equals(typeof value, "number");
+ assert_equals(value, Math.floor(value), "not an integer");
+ assert_true(-128 <= value && value <= 127, "byte " + value + " not in range [-128, 127]");
+ return;
+
+ case "octet":
+ assert_equals(typeof value, "number");
+ assert_equals(value, Math.floor(value), "not an integer");
+ assert_true(0 <= value && value <= 255, "octet " + value + " not in range [0, 255]");
+ return;
+
+ case "short":
+ assert_equals(typeof value, "number");
+ assert_equals(value, Math.floor(value), "not an integer");
+ assert_true(-32768 <= value && value <= 32767, "short " + value + " not in range [-32768, 32767]");
+ return;
+
+ case "unsigned short":
+ assert_equals(typeof value, "number");
+ assert_equals(value, Math.floor(value), "not an integer");
+ assert_true(0 <= value && value <= 65535, "unsigned short " + value + " not in range [0, 65535]");
+ return;
+
+ case "long":
+ assert_equals(typeof value, "number");
+ assert_equals(value, Math.floor(value), "not an integer");
+ assert_true(-2147483648 <= value && value <= 2147483647, "long " + value + " not in range [-2147483648, 2147483647]");
+ return;
+
+ case "unsigned long":
+ assert_equals(typeof value, "number");
+ assert_equals(value, Math.floor(value), "not an integer");
+ assert_true(0 <= value && value <= 4294967295, "unsigned long " + value + " not in range [0, 4294967295]");
+ return;
+
+ case "long long":
+ assert_equals(typeof value, "number");
+ return;
+
+ case "unsigned long long":
+ case "DOMTimeStamp":
+ assert_equals(typeof value, "number");
+ assert_true(0 <= value, "unsigned long long is negative");
+ return;
+
+ case "float":
+ case "double":
+ case "DOMHighResTimeStamp":
+ case "unrestricted float":
+ case "unrestricted double":
+ // TODO: distinguish these cases
+ assert_equals(typeof value, "number");
+ return;
+
+ case "DOMString":
+ case "ByteString":
+ case "USVString":
+ // TODO: https://github.com/w3c/testharness.js/issues/92
+ assert_equals(typeof value, "string");
+ return;
+
+ case "object":
+ assert_true(typeof value == "object" || typeof value == "function", "wrong type: not object or function");
+ return;
+ }
+
+ if (!(type in this.members))
+ {
+ throw "Unrecognized type " + type;
+ }
+
+ if (this.members[type] instanceof IdlInterface)
+ {
+ // We don't want to run the full
+ // IdlInterface.prototype.test_instance_of, because that could result
+ // in an infinite loop. TODO: This means we don't have tests for
+ // NoInterfaceObject interfaces, and we also can't test objects that
+ // come from another self.
+ assert_true(typeof value == "object" || typeof value == "function", "wrong type: not object or function");
+ if (value instanceof Object
+ && !this.members[type].has_extended_attribute("NoInterfaceObject")
+ && type in self)
+ {
+ assert_true(value instanceof self[type], "not instanceof " + type);
+ }
+ }
+ else if (this.members[type] instanceof IdlEnum)
+ {
+ assert_equals(typeof value, "string");
+ }
+ else if (this.members[type] instanceof IdlDictionary)
+ {
+ // TODO: Test when we actually have something to test this on
+ }
+ else if (this.members[type] instanceof IdlTypedef)
+ {
+ // TODO: Test when we actually have something to test this on
+ }
+ else
+ {
+ throw "Type " + type + " isn't an interface or dictionary";
+ }
+};
+//@}
+
+/// IdlObject ///
+function IdlObject() {}
+IdlObject.prototype.test = function()
+//@{
+{
+ /**
+ * By default, this does nothing, so no actual tests are run for IdlObjects
+ * that don't define any (e.g., IdlDictionary at the time of this writing).
+ */
+};
+
+//@}
+IdlObject.prototype.has_extended_attribute = function(name)
+//@{
+{
+ /**
+ * This is only meaningful for things that support extended attributes,
+ * such as interfaces, exceptions, and members.
+ */
+ return this.extAttrs.some(function(o)
+ {
+ return o.name == name;
+ });
+};
+
+//@}
+
+/// IdlDictionary ///
+// Used for IdlArray.prototype.assert_type_is
+function IdlDictionary(obj)
+//@{
+{
+ /**
+ * obj is an object produced by the WebIDLParser.js "dictionary"
+ * production.
+ */
+
+ /** Self-explanatory. */
+ this.name = obj.name;
+
+ /** An array of objects produced by the "dictionaryMember" production. */
+ this.members = obj.members;
+
+ /**
+ * The name (as a string) of the dictionary type we inherit from, or null
+ * if there is none.
+ */
+ this.base = obj.inheritance;
+}
+
+//@}
+IdlDictionary.prototype = Object.create(IdlObject.prototype);
+
+/// IdlInterface ///
+function IdlInterface(obj, is_callback) {
+ /**
+ * obj is an object produced by the WebIDLParser.js "exception" or
+ * "interface" production, as appropriate.
+ */
+
+ /** Self-explanatory. */
+ this.name = obj.name;
+
+ /** A back-reference to our IdlArray. */
+ this.array = obj.array;
+
+ /**
+ * An indicator of whether we should run tests on the (exception) interface
+ * object and (exception) interface prototype object. Tests on members are
+ * controlled by .untested on each member, not this.
+ */
+ this.untested = obj.untested;
+
+ /** An array of objects produced by the "ExtAttr" production. */
+ this.extAttrs = obj.extAttrs;
+
+ /** An array of IdlInterfaceMembers. */
+ this.members = obj.members.map(function(m){return new IdlInterfaceMember(m); });
+
+ /**
+ * The name (as a string) of the type we inherit from, or null if there is
+ * none.
+ */
+ this.base = obj.inheritance;
+
+ this._is_callback = is_callback;
+}
+IdlInterface.prototype = Object.create(IdlObject.prototype);
+IdlInterface.prototype.is_callback = function()
+//@{
+{
+ return this._is_callback;
+};
+//@}
+
+IdlInterface.prototype.has_constants = function()
+//@{
+{
+ return this.members.some(function(member) {
+ return member.type === "const";
+ });
+};
+//@}
+
+IdlInterface.prototype.is_global = function()
+//@{
+{
+ return this.extAttrs.some(function(attribute) {
+ return attribute.name === "Global" ||
+ attribute.name === "PrimaryGlobal";
+ });
+};
+//@}
+
+IdlInterface.prototype.test = function()
+//@{
+{
+ if (this.has_extended_attribute("NoInterfaceObject"))
+ {
+ // No tests to do without an instance. TODO: We should still be able
+ // to run tests on the prototype object, if we obtain one through some
+ // other means.
+ return;
+ }
+
+ if (!this.untested)
+ {
+ // First test things to do with the exception/interface object and
+ // exception/interface prototype object.
+ this.test_self();
+ }
+ // Then test things to do with its members (constants, fields, attributes,
+ // operations, . . .). These are run even if .untested is true, because
+ // members might themselves be marked as .untested. This might happen to
+ // interfaces if the interface itself is untested but a partial interface
+ // that extends it is tested -- then the interface itself and its initial
+ // members will be marked as untested, but the members added by the partial
+ // interface are still tested.
+ this.test_members();
+};
+//@}
+
+IdlInterface.prototype.test_self = function()
+//@{
+{
+ test(function()
+ {
+ // This function tests WebIDL as of 2015-01-13.
+ // TODO: Consider [Exposed].
+
+ // "For every interface that is exposed in a given ECMAScript global
+ // environment and:
+ // * is a callback interface that has constants declared on it, or
+ // * is a non-callback interface that is not declared with the
+ // [NoInterfaceObject] extended attribute,
+ // a corresponding property MUST exist on the ECMAScript global object.
+ // The name of the property is the identifier of the interface, and its
+ // value is an object called the interface object.
+ // The property has the attributes { [[Writable]]: true,
+ // [[Enumerable]]: false, [[Configurable]]: true }."
+ if (this.is_callback() && !this.has_constants()) {
+ return;
+ }
+
+ // TODO: Should we test here that the property is actually writable
+ // etc., or trust getOwnPropertyDescriptor?
+ assert_own_property(self, this.name,
+ "self does not have own property " + format_value(this.name));
+ var desc = Object.getOwnPropertyDescriptor(self, this.name);
+ assert_false("get" in desc, "self's property " + format_value(this.name) + " has getter");
+ assert_false("set" in desc, "self's property " + format_value(this.name) + " has setter");
+ assert_true(desc.writable, "self's property " + format_value(this.name) + " is not writable");
+ assert_false(desc.enumerable, "self's property " + format_value(this.name) + " is enumerable");
+ assert_true(desc.configurable, "self's property " + format_value(this.name) + " is not configurable");
+
+ if (this.is_callback()) {
+ // "The internal [[Prototype]] property of an interface object for
+ // a callback interface MUST be the Object.prototype object."
+ assert_equals(Object.getPrototypeOf(self[this.name]), Object.prototype,
+ "prototype of self's property " + format_value(this.name) + " is not Object.prototype");
+
+ return;
+ }
+
+ // "The interface object for a given non-callback interface is a
+ // function object."
+ // "If an object is defined to be a function object, then it has
+ // characteristics as follows:"
+
+ // Its [[Prototype]] internal property is otherwise specified (see
+ // below).
+
+ // "* Its [[Get]] internal property is set as described in ECMA-262
+ // section 9.1.8."
+ // Not much to test for this.
+
+ // "* Its [[Construct]] internal property is set as described in
+ // ECMA-262 section 19.2.2.3."
+ // Tested below if no constructor is defined. TODO: test constructors
+ // if defined.
+
+ // "* Its @@hasInstance property is set as described in ECMA-262
+ // section 19.2.3.8, unless otherwise specified."
+ // TODO
+
+ // ES6 (rev 30) 19.1.3.6:
+ // "Else, if O has a [[Call]] internal method, then let builtinTag be
+ // "Function"."
+ assert_class_string(self[this.name], "Function", "class string of " + this.name);
+
+ // "The [[Prototype]] internal property of an interface object for a
+ // non-callback interface is determined as follows:"
+ var prototype = Object.getPrototypeOf(self[this.name]);
+ if (this.base) {
+ // "* If the interface inherits from some other interface, the
+ // value of [[Prototype]] is the interface object for that other
+ // interface."
+ var has_interface_object =
+ !this.array
+ .members[this.base]
+ .has_extended_attribute("NoInterfaceObject");
+ if (has_interface_object) {
+ assert_own_property(self, this.base,
+ 'should inherit from ' + this.base +
+ ', but self has no such property');
+ assert_equals(prototype, self[this.base],
+ 'prototype of ' + this.name + ' is not ' +
+ this.base);
+ }
+ } else {
+ // "If the interface doesn't inherit from any other interface, the
+ // value of [[Prototype]] is %FunctionPrototype% ([ECMA-262],
+ // section 6.1.7.4)."
+ assert_equals(prototype, Function.prototype,
+ "prototype of self's property " + format_value(this.name) + " is not Function.prototype");
+ }
+
+ if (!this.has_extended_attribute("Constructor")) {
+ // "The internal [[Call]] method of the interface object behaves as
+ // follows . . .
+ //
+ // "If I was not declared with a [Constructor] extended attribute,
+ // then throw a TypeError."
+ assert_throws(new TypeError(), function() {
+ self[this.name]();
+ }.bind(this), "interface object didn't throw TypeError when called as a function");
+ assert_throws(new TypeError(), function() {
+ new self[this.name]();
+ }.bind(this), "interface object didn't throw TypeError when called as a constructor");
+ }
+ }.bind(this), this.name + " interface: existence and properties of interface object");
+
+ if (!this.is_callback()) {
+ test(function() {
+ // This function tests WebIDL as of 2014-10-25.
+ // https://heycam.github.io/webidl/#es-interface-call
+
+ assert_own_property(self, this.name,
+ "self does not have own property " + format_value(this.name));
+
+ // "Interface objects for non-callback interfaces MUST have a
+ // property named “length” with attributes { [[Writable]]: false,
+ // [[Enumerable]]: false, [[Configurable]]: true } whose value is
+ // a Number."
+ assert_own_property(self[this.name], "length");
+ var desc = Object.getOwnPropertyDescriptor(self[this.name], "length");
+ assert_false("get" in desc, this.name + ".length has getter");
+ assert_false("set" in desc, this.name + ".length has setter");
+ assert_false(desc.writable, this.name + ".length is writable");
+ assert_false(desc.enumerable, this.name + ".length is enumerable");
+ assert_true(desc.configurable, this.name + ".length is not configurable");
+
+ var constructors = this.extAttrs
+ .filter(function(attr) { return attr.name == "Constructor"; });
+ var expected_length;
+ if (!constructors.length) {
+ // "If the [Constructor] extended attribute, does not appear on
+ // the interface definition, then the value is 0."
+ expected_length = 0;
+ } else {
+ // "Otherwise, the value is determined as follows: . . .
+ // "Return the length of the shortest argument list of the
+ // entries in S."
+ expected_length = constructors.map(function(attr) {
+ return attr.arguments ? attr.arguments.filter(function(arg) {
+ return !arg.optional;
+ }).length : 0;
+ })
+ .reduce(function(m, n) { return Math.min(m, n); });
+ }
+ assert_equals(self[this.name].length, expected_length, "wrong value for " + this.name + ".length");
+ }.bind(this), this.name + " interface object length");
+ }
+
+ // TODO: Test named constructors if I find any interfaces that have them.
+
+ test(function()
+ {
+ // This function tests WebIDL as of 2015-01-21.
+ // https://heycam.github.io/webidl/#interface-object
+
+ if (this.is_callback() && !this.has_constants()) {
+ return;
+ }
+
+ assert_own_property(self, this.name,
+ "self does not have own property " + format_value(this.name));
+
+ if (this.is_callback()) {
+ assert_false("prototype" in self[this.name],
+ this.name + ' should not have a "prototype" property');
+ return;
+ }
+
+ // "An interface object for a non-callback interface must have a
+ // property named “prototype” with attributes { [[Writable]]: false,
+ // [[Enumerable]]: false, [[Configurable]]: false } whose value is an
+ // object called the interface prototype object. This object has
+ // properties that correspond to the regular attributes and regular
+ // operations defined on the interface, and is described in more detail
+ // in section 4.5.4 below."
+ assert_own_property(self[this.name], "prototype",
+ 'interface "' + this.name + '" does not have own property "prototype"');
+ var desc = Object.getOwnPropertyDescriptor(self[this.name], "prototype");
+ assert_false("get" in desc, this.name + ".prototype has getter");
+ assert_false("set" in desc, this.name + ".prototype has setter");
+ assert_false(desc.writable, this.name + ".prototype is writable");
+ assert_false(desc.enumerable, this.name + ".prototype is enumerable");
+ assert_false(desc.configurable, this.name + ".prototype is configurable");
+
+ // Next, test that the [[Prototype]] of the interface prototype object
+ // is correct. (This is made somewhat difficult by the existence of
+ // [NoInterfaceObject].)
+ // TODO: Aryeh thinks there's at least other place in this file where
+ // we try to figure out if an interface prototype object is
+ // correct. Consolidate that code.
+
+ // "The interface prototype object for a given interface A must have an
+ // internal [[Prototype]] property whose value is returned from the
+ // following steps:
+ // "If A is declared with the [Global] or [PrimaryGlobal] extended
+ // attribute, and A supports named properties, then return the named
+ // properties object for A, as defined in section 4.5.5 below.
+ // "Otherwise, if A is declared to inherit from another interface, then
+ // return the interface prototype object for the inherited interface.
+ // "Otherwise, if A is declared with the [ArrayClass] extended
+ // attribute, then return %ArrayPrototype% ([ECMA-262], section
+ // 6.1.7.4).
+ // "Otherwise, return %ObjectPrototype% ([ECMA-262], section 6.1.7.4).
+ // ([ECMA-262], section 15.2.4).
+ if (this.name === "Window") {
+ assert_class_string(Object.getPrototypeOf(self[this.name].prototype),
+ 'WindowProperties',
+ 'Class name for prototype of Window' +
+ '.prototype is not "WindowProperties"');
+ } else {
+ var inherit_interface, inherit_interface_has_interface_object;
+ if (this.base) {
+ inherit_interface = this.base;
+ inherit_interface_has_interface_object =
+ !this.array
+ .members[inherit_interface]
+ .has_extended_attribute("NoInterfaceObject");
+ } else if (this.has_extended_attribute('ArrayClass')) {
+ inherit_interface = 'Array';
+ inherit_interface_has_interface_object = true;
+ } else {
+ inherit_interface = 'Object';
+ inherit_interface_has_interface_object = true;
+ }
+ if (inherit_interface_has_interface_object) {
+ assert_own_property(self, inherit_interface,
+ 'should inherit from ' + inherit_interface + ', but self has no such property');
+ assert_own_property(self[inherit_interface], 'prototype',
+ 'should inherit from ' + inherit_interface + ', but that object has no "prototype" property');
+ assert_equals(Object.getPrototypeOf(self[this.name].prototype),
+ self[inherit_interface].prototype,
+ 'prototype of ' + this.name + '.prototype is not ' + inherit_interface + '.prototype');
+ } else {
+ // We can't test that we get the correct object, because this is the
+ // only way to get our hands on it. We only test that its class
+ // string, at least, is correct.
+ assert_class_string(Object.getPrototypeOf(self[this.name].prototype),
+ inherit_interface + 'Prototype',
+ 'Class name for prototype of ' + this.name +
+ '.prototype is not "' + inherit_interface + 'Prototype"');
+ }
+ }
+
+ // "The class string of an interface prototype object is the
+ // concatenation of the interface’s identifier and the string
+ // “Prototype”."
+ assert_class_string(self[this.name].prototype, this.name + "Prototype",
+ "class string of " + this.name + ".prototype");
+ // String() should end up calling {}.toString if nothing defines a
+ // stringifier.
+ if (!this.has_stringifier()) {
+ assert_equals(String(self[this.name].prototype), "[object " + this.name + "Prototype]",
+ "String(" + this.name + ".prototype)");
+ }
+ }.bind(this), this.name + " interface: existence and properties of interface prototype object");
+
+ test(function()
+ {
+ if (this.is_callback() && !this.has_constants()) {
+ return;
+ }
+
+ assert_own_property(self, this.name,
+ "self does not have own property " + format_value(this.name));
+
+ if (this.is_callback()) {
+ assert_false("prototype" in self[this.name],
+ this.name + ' should not have a "prototype" property');
+ return;
+ }
+
+ assert_own_property(self[this.name], "prototype",
+ 'interface "' + this.name + '" does not have own property "prototype"');
+
+ // "If the [NoInterfaceObject] extended attribute was not specified on
+ // the interface, then the interface prototype object must also have a
+ // property named “constructor” with attributes { [[Writable]]: true,
+ // [[Enumerable]]: false, [[Configurable]]: true } whose value is a
+ // reference to the interface object for the interface."
+ assert_own_property(self[this.name].prototype, "constructor",
+ this.name + '.prototype does not have own property "constructor"');
+ var desc = Object.getOwnPropertyDescriptor(self[this.name].prototype, "constructor");
+ assert_false("get" in desc, this.name + ".prototype.constructor has getter");
+ assert_false("set" in desc, this.name + ".prototype.constructor has setter");
+ assert_true(desc.writable, this.name + ".prototype.constructor is not writable");
+ assert_false(desc.enumerable, this.name + ".prototype.constructor is enumerable");
+ assert_true(desc.configurable, this.name + ".prototype.constructor in not configurable");
+ assert_equals(self[this.name].prototype.constructor, self[this.name],
+ this.name + '.prototype.constructor is not the same object as ' + this.name);
+ }.bind(this), this.name + ' interface: existence and properties of interface prototype object\'s "constructor" property');
+};
+
+//@}
+IdlInterface.prototype.test_member_const = function(member)
+//@{
+{
+ test(function()
+ {
+ if (this.is_callback() && !this.has_constants()) {
+ return;
+ }
+
+ assert_own_property(self, this.name,
+ "self does not have own property " + format_value(this.name));
+
+ // "For each constant defined on an interface A, there must be
+ // a corresponding property on the interface object, if it
+ // exists."
+ assert_own_property(self[this.name], member.name);
+ // "The value of the property is that which is obtained by
+ // converting the constant’s IDL value to an ECMAScript
+ // value."
+ assert_equals(self[this.name][member.name], constValue(member.value),
+ "property has wrong value");
+ // "The property has attributes { [[Writable]]: false,
+ // [[Enumerable]]: true, [[Configurable]]: false }."
+ var desc = Object.getOwnPropertyDescriptor(self[this.name], member.name);
+ assert_false("get" in desc, "property has getter");
+ assert_false("set" in desc, "property has setter");
+ assert_false(desc.writable, "property is writable");
+ assert_true(desc.enumerable, "property is not enumerable");
+ assert_false(desc.configurable, "property is configurable");
+ }.bind(this), this.name + " interface: constant " + member.name + " on interface object");
+ // "In addition, a property with the same characteristics must
+ // exist on the interface prototype object."
+ test(function()
+ {
+ if (this.is_callback() && !this.has_constants()) {
+ return;
+ }
+
+ assert_own_property(self, this.name,
+ "self does not have own property " + format_value(this.name));
+
+ if (this.is_callback()) {
+ assert_false("prototype" in self[this.name],
+ this.name + ' should not have a "prototype" property');
+ return;
+ }
+
+ assert_own_property(self[this.name], "prototype",
+ 'interface "' + this.name + '" does not have own property "prototype"');
+
+ assert_own_property(self[this.name].prototype, member.name);
+ assert_equals(self[this.name].prototype[member.name], constValue(member.value),
+ "property has wrong value");
+ var desc = Object.getOwnPropertyDescriptor(self[this.name], member.name);
+ assert_false("get" in desc, "property has getter");
+ assert_false("set" in desc, "property has setter");
+ assert_false(desc.writable, "property is writable");
+ assert_true(desc.enumerable, "property is not enumerable");
+ assert_false(desc.configurable, "property is configurable");
+ }.bind(this), this.name + " interface: constant " + member.name + " on interface prototype object");
+};
+
+
+//@}
+IdlInterface.prototype.test_member_attribute = function(member)
+//@{
+{
+ test(function()
+ {
+ if (this.is_callback() && !this.has_constants()) {
+ return;
+ }
+
+ assert_own_property(self, this.name,
+ "self does not have own property " + format_value(this.name));
+ assert_own_property(self[this.name], "prototype",
+ 'interface "' + this.name + '" does not have own property "prototype"');
+
+ if (member["static"]) {
+ assert_own_property(self[this.name], member.name,
+ "The interface object must have a property " +
+ format_value(member.name));
+ } else if (this.is_global()) {
+ assert_own_property(self, member.name,
+ "The global object must have a property " +
+ format_value(member.name));
+ assert_false(member.name in self[this.name].prototype,
+ "The prototype object must not have a property " +
+ format_value(member.name));
+ do_interface_attribute_asserts(self, member);
+ } else {
+ assert_true(member.name in self[this.name].prototype,
+ "The prototype object must have a property " +
+ format_value(member.name));
+
+ if (!member.has_extended_attribute("LenientThis")) {
+ assert_throws(new TypeError(), function() {
+ self[this.name].prototype[member.name];
+ }.bind(this), "getting property on prototype object must throw TypeError");
+ } else {
+ assert_equals(self[this.name].prototype[member.name], undefined,
+ "getting property on prototype object must return undefined");
+ }
+ do_interface_attribute_asserts(self[this.name].prototype, member);
+ }
+ }.bind(this), this.name + " interface: attribute " + member.name);
+};
+
+//@}
+IdlInterface.prototype.test_member_operation = function(member)
+//@{
+{
+ test(function()
+ {
+ if (this.is_callback() && !this.has_constants()) {
+ return;
+ }
+
+ assert_own_property(self, this.name,
+ "self does not have own property " + format_value(this.name));
+
+ if (this.is_callback()) {
+ assert_false("prototype" in self[this.name],
+ this.name + ' should not have a "prototype" property');
+ return;
+ }
+
+ assert_own_property(self[this.name], "prototype",
+ 'interface "' + this.name + '" does not have own property "prototype"');
+
+ // "For each unique identifier of an operation defined on the
+ // interface, there must be a corresponding property on the
+ // interface prototype object (if it is a regular operation) or
+ // the interface object (if it is a static operation), unless
+ // the effective overload set for that identifier and operation
+ // and with an argument count of 0 (for the ECMAScript language
+ // binding) has no entries."
+ //
+ var memberHolderObject;
+ if (member["static"]) {
+ assert_own_property(self[this.name], member.name,
+ "interface prototype object missing static operation");
+ memberHolderObject = self[this.name];
+ } else if (this.is_global()) {
+ assert_own_property(self, member.name,
+ "global object missing non-static operation");
+ memberHolderObject = self;
+ } else {
+ assert_own_property(self[this.name].prototype, member.name,
+ "interface prototype object missing non-static operation");
+ memberHolderObject = self[this.name].prototype;
+ }
+
+ var desc = Object.getOwnPropertyDescriptor(memberHolderObject, member.name);
+ // "The property has attributes { [[Writable]]: true,
+ // [[Enumerable]]: true, [[Configurable]]: true }."
+ assert_false("get" in desc, "property has getter");
+ assert_false("set" in desc, "property has setter");
+ assert_true(desc.writable, "property is not writable");
+ assert_true(desc.enumerable, "property is not enumerable");
+ assert_true(desc.configurable, "property is not configurable");
+ // "The value of the property is a Function object whose
+ // behavior is as follows . . ."
+ assert_equals(typeof memberHolderObject[member.name], "function",
+ "property must be a function");
+ // "The value of the Function object’s “length” property is
+ // a Number determined as follows:
+ // ". . .
+ // "Return the length of the shortest argument list of the
+ // entries in S."
+ //
+ // TODO: Doesn't handle overloading or variadic arguments.
+ assert_equals(memberHolderObject[member.name].length,
+ member.arguments.filter(function(arg) {
+ return !arg.optional;
+ }).length,
+ "property has wrong .length");
+
+ // Make some suitable arguments
+ var args = member.arguments.map(function(arg) {
+ return create_suitable_object(arg.idlType);
+ });
+
+ // "Let O be a value determined as follows:
+ // ". . .
+ // "Otherwise, throw a TypeError."
+ // This should be hit if the operation is not static, there is
+ // no [ImplicitThis] attribute, and the this value is null.
+ //
+ // TODO: We currently ignore the [ImplicitThis] case.
+ if (!member["static"]) {
+ assert_throws(new TypeError(), function() {
+ self[this.name].prototype[member.name].apply(null, args);
+ }, "calling operation with this = null didn't throw TypeError");
+ }
+
+ // ". . . If O is not null and is also not a platform object
+ // that implements interface I, throw a TypeError."
+ //
+ // TODO: Test a platform object that implements some other
+ // interface. (Have to be sure to get inheritance right.)
+ assert_throws(new TypeError(), function() {
+ self[this.name].prototype[member.name].apply({}, args);
+ }, "calling operation with this = {} didn't throw TypeError");
+ }.bind(this), this.name + " interface: operation " + member.name +
+ "(" + member.arguments.map(function(m) { return m.idlType.idlType; }) +
+ ")");
+};
+
+//@}
+IdlInterface.prototype.test_member_stringifier = function(member)
+//@{
+{
+ test(function()
+ {
+ if (this.is_callback() && !this.has_constants()) {
+ return;
+ }
+
+ assert_own_property(self, this.name,
+ "self does not have own property " + format_value(this.name));
+
+ if (this.is_callback()) {
+ assert_false("prototype" in self[this.name],
+ this.name + ' should not have a "prototype" property');
+ return;
+ }
+
+ assert_own_property(self[this.name], "prototype",
+ 'interface "' + this.name + '" does not have own property "prototype"');
+
+ // ". . . the property exists on the interface prototype object."
+ var interfacePrototypeObject = self[this.name].prototype;
+ assert_own_property(self[this.name].prototype, "toString",
+ "interface prototype object missing non-static operation");
+
+ var desc = Object.getOwnPropertyDescriptor(interfacePrototypeObject, "toString");
+ // "The property has attributes { [[Writable]]: B,
+ // [[Enumerable]]: true, [[Configurable]]: B }, where B is false if the
+ // stringifier is unforgeable on the interface, and true otherwise."
+ assert_false("get" in desc, "property has getter");
+ assert_false("set" in desc, "property has setter");
+ assert_true(desc.writable, "property is not writable");
+ assert_true(desc.enumerable, "property is not enumerable");
+ assert_true(desc.configurable, "property is not configurable");
+ // "The value of the property is a Function object, which behaves as
+ // follows . . ."
+ assert_equals(typeof interfacePrototypeObject.toString, "function",
+ "property must be a function");
+ // "The value of the Function object’s “length” property is the Number
+ // value 0."
+ assert_equals(interfacePrototypeObject.toString.length, 0,
+ "property has wrong .length");
+
+ // "Let O be the result of calling ToObject on the this value."
+ assert_throws(new TypeError(), function() {
+ self[this.name].prototype.toString.apply(null, []);
+ }, "calling stringifier with this = null didn't throw TypeError");
+
+ // "If O is not an object that implements the interface on which the
+ // stringifier was declared, then throw a TypeError."
+ //
+ // TODO: Test a platform object that implements some other
+ // interface. (Have to be sure to get inheritance right.)
+ assert_throws(new TypeError(), function() {
+ self[this.name].prototype.toString.apply({}, []);
+ }, "calling stringifier with this = {} didn't throw TypeError");
+ }.bind(this), this.name + " interface: stringifier");
+};
+
+//@}
+IdlInterface.prototype.test_members = function()
+//@{
+{
+ for (var i = 0; i < this.members.length; i++)
+ {
+ var member = this.members[i];
+ if (member.untested) {
+ continue;
+ }
+
+ switch (member.type) {
+ case "const":
+ this.test_member_const(member);
+ break;
+
+ case "attribute":
+ // For unforgeable attributes, we do the checks in
+ // test_interface_of instead.
+ if (!member.has_extended_attribute("Unforgeable")) {
+ this.test_member_attribute(member);
+ }
+ break;
+
+ case "operation":
+ // TODO: Need to correctly handle multiple operations with the same
+ // identifier.
+ if (member.name) {
+ this.test_member_operation(member);
+ } else if (member.stringifier) {
+ this.test_member_stringifier(member);
+ }
+ break;
+
+ default:
+ // TODO: check more member types.
+ break;
+ }
+ }
+};
+
+//@}
+IdlInterface.prototype.test_object = function(desc)
+//@{
+{
+ var obj, exception = null;
+ try
+ {
+ obj = eval(desc);
+ }
+ catch(e)
+ {
+ exception = e;
+ }
+
+ // TODO: WebIDLParser doesn't currently support named legacycallers, so I'm
+ // not sure what those would look like in the AST
+ var expected_typeof = this.members.some(function(member)
+ {
+ return member.legacycaller
+ || ("idlType" in member && member.idlType.legacycaller)
+ || ("idlType" in member && typeof member.idlType == "object"
+ && "idlType" in member.idlType && member.idlType.idlType == "legacycaller");
+ }) ? "function" : "object";
+
+ this.test_primary_interface_of(desc, obj, exception, expected_typeof);
+ var current_interface = this;
+ while (current_interface)
+ {
+ if (!(current_interface.name in this.array.members))
+ {
+ throw "Interface " + current_interface.name + " not found (inherited by " + this.name + ")";
+ }
+ if (current_interface.prevent_multiple_testing && current_interface.already_tested)
+ {
+ return;
+ }
+ current_interface.test_interface_of(desc, obj, exception, expected_typeof);
+ current_interface = this.array.members[current_interface.base];
+ }
+};
+
+//@}
+IdlInterface.prototype.test_primary_interface_of = function(desc, obj, exception, expected_typeof)
+//@{
+{
+ // We can't easily test that its prototype is correct if there's no
+ // interface object, or the object is from a different global environment
+ // (not instanceof Object). TODO: test in this case that its prototype at
+ // least looks correct, even if we can't test that it's actually correct.
+ if (!this.has_extended_attribute("NoInterfaceObject")
+ && (typeof obj != expected_typeof || obj instanceof Object))
+ {
+ test(function()
+ {
+ assert_equals(exception, null, "Unexpected exception when evaluating object");
+ assert_equals(typeof obj, expected_typeof, "wrong typeof object");
+ assert_own_property(self, this.name,
+ "self does not have own property " + format_value(this.name));
+ assert_own_property(self[this.name], "prototype",
+ 'interface "' + this.name + '" does not have own property "prototype"');
+
+ // "The value of the internal [[Prototype]] property of the
+ // platform object is the interface prototype object of the primary
+ // interface from the platform object’s associated global
+ // environment."
+ assert_equals(Object.getPrototypeOf(obj),
+ self[this.name].prototype,
+ desc + "'s prototype is not " + this.name + ".prototype");
+ }.bind(this), this.name + " must be primary interface of " + desc);
+ }
+
+ // "The class string of a platform object that implements one or more
+ // interfaces must be the identifier of the primary interface of the
+ // platform object."
+ test(function()
+ {
+ assert_equals(exception, null, "Unexpected exception when evaluating object");
+ assert_equals(typeof obj, expected_typeof, "wrong typeof object");
+ assert_class_string(obj, this.name, "class string of " + desc);
+ if (!this.has_stringifier())
+ {
+ assert_equals(String(obj), "[object " + this.name + "]", "String(" + desc + ")");
+ }
+ }.bind(this), "Stringification of " + desc);
+};
+
+//@}
+IdlInterface.prototype.test_interface_of = function(desc, obj, exception, expected_typeof)
+//@{
+{
+ // TODO: Indexed and named properties, more checks on interface members
+ this.already_tested = true;
+
+ for (var i = 0; i < this.members.length; i++)
+ {
+ var member = this.members[i];
+ if (member.has_extended_attribute("Unforgeable"))
+ {
+ test(function()
+ {
+ assert_equals(exception, null, "Unexpected exception when evaluating object");
+ assert_equals(typeof obj, expected_typeof, "wrong typeof object");
+ do_interface_attribute_asserts(obj, member);
+ }.bind(this), this.name + " interface: " + desc + ' must have own property "' + member.name + '"');
+ }
+ else if ((member.type == "const"
+ || member.type == "attribute"
+ || member.type == "operation")
+ && member.name)
+ {
+ test(function()
+ {
+ assert_equals(exception, null, "Unexpected exception when evaluating object");
+ assert_equals(typeof obj, expected_typeof, "wrong typeof object");
+ if (!member["static"]) {
+ assert_inherits(obj, member.name);
+ if (member.type == "const")
+ {
+ assert_equals(obj[member.name], constValue(member.value));
+ }
+ if (member.type == "attribute")
+ {
+ // Attributes are accessor properties, so they might
+ // legitimately throw an exception rather than returning
+ // anything.
+ var property, thrown = false;
+ try
+ {
+ property = obj[member.name];
+ }
+ catch (e)
+ {
+ thrown = true;
+ }
+ if (!thrown)
+ {
+ this.array.assert_type_is(property, member.idlType);
+ }
+ }
+ if (member.type == "operation")
+ {
+ assert_equals(typeof obj[member.name], "function");
+ }
+ }
+ }.bind(this), this.name + " interface: " + desc + ' must inherit property "' + member.name + '" with the proper type (' + i + ')');
+ }
+ // TODO: This is wrong if there are multiple operations with the same
+ // identifier.
+ // TODO: Test passing arguments of the wrong type.
+ if (member.type == "operation" && member.name && member.arguments.length)
+ {
+ test(function()
+ {
+ assert_equals(exception, null, "Unexpected exception when evaluating object");
+ assert_equals(typeof obj, expected_typeof, "wrong typeof object");
+ if (!member["static"]) {
+ assert_inherits(obj, member.name);
+ }
+ else
+ {
+ assert_false(member.name in obj);
+ }
+ var args = [];
+ for (var i = 0; i < member.arguments.length; i++)
+ {
+ if (member.arguments[i].optional)
+ {
+ break;
+ }
+ assert_throws(new TypeError(), function()
+ {
+ obj[member.name].apply(obj, args);
+ }.bind(this), "Called with " + i + " arguments");
+
+ args.push(create_suitable_object(member.arguments[i].idlType));
+ }
+ }.bind(this), this.name + " interface: calling " + member.name +
+ "(" + member.arguments.map(function(m) { return m.idlType.idlType; }) +
+ ") on " + desc + " with too few arguments must throw TypeError");
+ }
+ }
+};
+
+//@}
+IdlInterface.prototype.has_stringifier = function()
+//@{
+{
+ if (this.members.some(function(member) { return member.stringifier; })) {
+ return true;
+ }
+ if (this.base &&
+ this.array.members[this.base].has_stringifier()) {
+ return true;
+ }
+ return false;
+};
+
+//@}
+function do_interface_attribute_asserts(obj, member)
+//@{
+{
+ // This function tests WebIDL as of 2015-01-27.
+ // TODO: Consider [Exposed].
+
+ // This is called by test_member_attribute() with the prototype as obj if
+ // it is not a global, and the global otherwise, and by test_interface_of()
+ // with the object as obj.
+
+ // "For each exposed attribute of the interface, whether it was declared on
+ // the interface itself or one of its consequential interfaces, there MUST
+ // exist a corresponding property. The characteristics of this property are
+ // as follows:"
+
+ // "The name of the property is the identifier of the attribute."
+ assert_own_property(obj, member.name);
+
+ // "The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
+ // true, [[Configurable]]: configurable }, where:
+ // "configurable is false if the attribute was declared with the
+ // [Unforgeable] extended attribute and true otherwise;
+ // "G is the attribute getter, defined below; and
+ // "S is the attribute setter, also defined below."
+ var desc = Object.getOwnPropertyDescriptor(obj, member.name);
+ assert_false("value" in desc, 'property descriptor has value but is supposed to be accessor');
+ assert_false("writable" in desc, 'property descriptor has "writable" field but is supposed to be accessor');
+ assert_true(desc.enumerable, "property is not enumerable");
+ if (member.has_extended_attribute("Unforgeable"))
+ {
+ assert_false(desc.configurable, "[Unforgeable] property must not be configurable");
+ }
+ else
+ {
+ assert_true(desc.configurable, "property must be configurable");
+ }
+
+
+ // "The attribute getter is a Function object whose behavior when invoked
+ // is as follows:"
+ assert_equals(typeof desc.get, "function", "getter must be Function");
+
+ // "If the attribute is a regular attribute, then:"
+ if (!member["static"]) {
+ // "If O is not a platform object that implements I, then:
+ // "If the attribute was specified with the [LenientThis] extended
+ // attribute, then return undefined.
+ // "Otherwise, throw a TypeError."
+ if (!member.has_extended_attribute("LenientThis")) {
+ assert_throws(new TypeError(), function() {
+ desc.get.call({});
+ }.bind(this), "calling getter on wrong object type must throw TypeError");
+ } else {
+ assert_equals(desc.get.call({}), undefined,
+ "calling getter on wrong object type must return undefined");
+ }
+ }
+
+ // "The value of the Function object’s “length” property is the Number
+ // value 0."
+ assert_equals(desc.get.length, 0, "getter length must be 0");
+
+
+ // TODO: Test calling setter on the interface prototype (should throw
+ // TypeError in most cases).
+ if (member.readonly
+ && !member.has_extended_attribute("PutForwards")
+ && !member.has_extended_attribute("Replaceable"))
+ {
+ // "The attribute setter is undefined if the attribute is declared
+ // readonly and has neither a [PutForwards] nor a [Replaceable]
+ // extended attribute declared on it."
+ assert_equals(desc.set, undefined, "setter must be undefined for readonly attributes");
+ }
+ else
+ {
+ // "Otherwise, it is a Function object whose behavior when
+ // invoked is as follows:"
+ assert_equals(typeof desc.set, "function", "setter must be function for PutForwards, Replaceable, or non-readonly attributes");
+
+ // "If the attribute is a regular attribute, then:"
+ if (!member["static"]) {
+ // "If /validThis/ is false and the attribute was not specified
+ // with the [LenientThis] extended attribute, then throw a
+ // TypeError."
+ // "If the attribute is declared with a [Replaceable] extended
+ // attribute, then: ..."
+ // "If validThis is false, then return."
+ if (!member.has_extended_attribute("LenientThis")) {
+ assert_throws(new TypeError(), function() {
+ desc.set.call({});
+ }.bind(this), "calling setter on wrong object type must throw TypeError");
+ } else {
+ assert_equals(desc.set.call({}), undefined,
+ "calling setter on wrong object type must return undefined");
+ }
+ }
+
+ // "The value of the Function object’s “length” property is the Number
+ // value 1."
+ assert_equals(desc.set.length, 1, "setter length must be 1");
+ }
+}
+//@}
+
+/// IdlInterfaceMember ///
+function IdlInterfaceMember(obj)
+//@{
+{
+ /**
+ * obj is an object produced by the WebIDLParser.js "ifMember" production.
+ * We just forward all properties to this object without modification,
+ * except for special extAttrs handling.
+ */
+ for (var k in obj)
+ {
+ this[k] = obj[k];
+ }
+ if (!("extAttrs" in this))
+ {
+ this.extAttrs = [];
+ }
+}
+
+//@}
+IdlInterfaceMember.prototype = Object.create(IdlObject.prototype);
+
+/// Internal helper functions ///
+function create_suitable_object(type)
+//@{
+{
+ /**
+ * type is an object produced by the WebIDLParser.js "type" production. We
+ * return a JavaScript value that matches the type, if we can figure out
+ * how.
+ */
+ if (type.nullable)
+ {
+ return null;
+ }
+ switch (type.idlType)
+ {
+ case "any":
+ case "boolean":
+ return true;
+
+ case "byte": case "octet": case "short": case "unsigned short":
+ case "long": case "unsigned long": case "long long":
+ case "unsigned long long": case "float": case "double":
+ case "unrestricted float": case "unrestricted double":
+ return 7;
+
+ case "DOMString":
+ case "ByteString":
+ case "USVString":
+ return "foo";
+
+ case "object":
+ return {a: "b"};
+
+ case "Node":
+ return document.createTextNode("abc");
+ }
+ return null;
+}
+//@}
+
+/// IdlEnum ///
+// Used for IdlArray.prototype.assert_type_is
+function IdlEnum(obj)
+//@{
+{
+ /**
+ * obj is an object produced by the WebIDLParser.js "dictionary"
+ * production.
+ */
+
+ /** Self-explanatory. */
+ this.name = obj.name;
+
+ /** An array of values produced by the "enum" production. */
+ this.values = obj.values;
+
+}
+//@}
+
+IdlEnum.prototype = Object.create(IdlObject.prototype);
+
+/// IdlTypedef ///
+// Used for IdlArray.prototype.assert_type_is
+function IdlTypedef(obj)
+//@{
+{
+ /**
+ * obj is an object produced by the WebIDLParser.js "typedef"
+ * production.
+ */
+
+ /** Self-explanatory. */
+ this.name = obj.name;
+
+ /** An array of values produced by the "typedef" production. */
+ this.values = obj.values;
+
+}
+//@}
+
+IdlTypedef.prototype = Object.create(IdlObject.prototype);
+
+}());
+// vim: set expandtab shiftwidth=4 tabstop=4 foldmarker=@{,@} foldmethod=marker:
diff --git a/tests/wpt/web-platform-tests/resources/readme.md b/tests/wpt/web-platform-tests/resources/readme.md
new file mode 100644
index 00000000000..5c5b36c2869
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/readme.md
@@ -0,0 +1,23 @@
+## Introdution ##
+
+testharness.js provides a framework for writing low-level tests of
+browser functionality in javascript. It provides a convenient API for
+making assertions and is intended to work for both simple synchronous
+tests and for tests of asynchronous behaviour.
+
+## Getting Started ##
+
+To use testharness.js you must include two scripts, in the order given:
+
+``` html
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+```
+
+## Full documentation ##
+
+Full user documentation for the API is in the
+[docs/api.md](https://github.com/w3c/testharness.js/blob/master/docs/api.md) file.
+
+You can also read a tutorial on
+[Using testharness.js](http://darobin.github.com/test-harness-tutorial/docs/using-testharness.html).
diff --git a/tests/wpt/web-platform-tests/resources/testharness.css b/tests/wpt/web-platform-tests/resources/testharness.css
new file mode 100644
index 00000000000..e2ed5a043f9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/testharness.css
@@ -0,0 +1,102 @@
+html {
+ font-family:DejaVu Sans, Bitstream Vera Sans, Arial, Sans;
+}
+
+#log .warning,
+#log .warning a {
+ color: black;
+ background: yellow;
+}
+
+#log .error,
+#log .error a {
+ color: white;
+ background: red;
+}
+
+section#summary {
+ margin-bottom:1em;
+}
+
+table#results {
+ border-collapse:collapse;
+ table-layout:fixed;
+ width:100%;
+}
+
+table#results th:first-child,
+table#results td:first-child {
+ width:4em;
+}
+
+table#results th:last-child,
+table#results td:last-child {
+ width:50%;
+}
+
+table#results.assertions th:last-child,
+table#results.assertions td:last-child {
+ width:35%;
+}
+
+table#results th {
+ padding:0;
+ padding-bottom:0.5em;
+ border-bottom:medium solid black;
+}
+
+table#results td {
+ padding:1em;
+ padding-bottom:0.5em;
+ border-bottom:thin solid black;
+}
+
+tr.pass > td:first-child {
+ color:green;
+}
+
+tr.fail > td:first-child {
+ color:red;
+}
+
+tr.timeout > td:first-child {
+ color:red;
+}
+
+tr.notrun > td:first-child {
+ color:blue;
+}
+
+.pass > td:first-child, .fail > td:first-child, .timeout > td:first-child, .notrun > td:first-child {
+ font-variant:small-caps;
+}
+
+table#results span {
+ display:block;
+}
+
+table#results span.expected {
+ font-family:DejaVu Sans Mono, Bitstream Vera Sans Mono, Monospace;
+ white-space:pre;
+}
+
+table#results span.actual {
+ font-family:DejaVu Sans Mono, Bitstream Vera Sans Mono, Monospace;
+ white-space:pre;
+}
+
+span.ok {
+ color:green;
+}
+
+tr.error {
+ color:red;
+}
+
+span.timeout {
+ color:red;
+}
+
+span.ok, span.timeout, span.error {
+ font-variant:small-caps;
+} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/testharness.js b/tests/wpt/web-platform-tests/resources/testharness.js
new file mode 100644
index 00000000000..ab88e541fcb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/testharness.js
@@ -0,0 +1,2427 @@
+/*global self*/
+/*jshint latedef: nofunc*/
+/*
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+*/
+
+/* Documentation is in docs/api.md */
+
+(function ()
+{
+ var debug = false;
+ // default timeout is 10 seconds, test can override if needed
+ var settings = {
+ output:true,
+ harness_timeout:{
+ "normal":10000,
+ "long":60000
+ },
+ test_timeout:null
+ };
+
+ var xhtml_ns = "http://www.w3.org/1999/xhtml";
+
+ /*
+ * TestEnvironment is an abstraction for the environment in which the test
+ * harness is used. Each implementation of a test environment has to provide
+ * the following interface:
+ *
+ * interface TestEnvironment {
+ * // Invoked after the global 'tests' object has been created and it's
+ * // safe to call add_*_callback() to register event handlers.
+ * void on_tests_ready();
+ *
+ * // Invoked after setup() has been called to notify the test environment
+ * // of changes to the test harness properties.
+ * void on_new_harness_properties(object properties);
+ *
+ * // Should return a new unique default test name.
+ * DOMString next_default_test_name();
+ *
+ * // Should return the test harness timeout duration in milliseconds.
+ * float test_timeout();
+ *
+ * // Should return the global scope object.
+ * object global_scope();
+ * };
+ */
+
+ /*
+ * A test environment with a DOM. The global object is 'window'. By default
+ * test results are displayed in a table. Any parent windows receive
+ * callbacks or messages via postMessage() when test events occur. See
+ * apisample11.html and apisample12.html.
+ */
+ function WindowTestEnvironment() {
+ this.name_counter = 0;
+ this.window_cache = null;
+ this.output_handler = null;
+ this.all_loaded = false;
+ var this_obj = this;
+ on_event(window, 'load', function() {
+ this_obj.all_loaded = true;
+ });
+ }
+
+ WindowTestEnvironment.prototype._dispatch = function(selector, callback_args, message_arg) {
+ this._forEach_windows(
+ function(w, is_same_origin) {
+ if (is_same_origin && selector in w) {
+ try {
+ w[selector].apply(undefined, callback_args);
+ } catch (e) {
+ if (debug) {
+ throw e;
+ }
+ }
+ }
+ if (supports_post_message(w) && w !== self) {
+ w.postMessage(message_arg, "*");
+ }
+ });
+ };
+
+ WindowTestEnvironment.prototype._forEach_windows = function(callback) {
+ // Iterate of the the windows [self ... top, opener]. The callback is passed
+ // two objects, the first one is the windows object itself, the second one
+ // is a boolean indicating whether or not its on the same origin as the
+ // current window.
+ var cache = this.window_cache;
+ if (!cache) {
+ cache = [[self, true]];
+ var w = self;
+ var i = 0;
+ var so;
+ var origins = location.ancestorOrigins;
+ while (w != w.parent) {
+ w = w.parent;
+ // In WebKit, calls to parent windows' properties that aren't on the same
+ // origin cause an error message to be displayed in the error console but
+ // don't throw an exception. This is a deviation from the current HTML5
+ // spec. See: https://bugs.webkit.org/show_bug.cgi?id=43504
+ // The problem with WebKit's behavior is that it pollutes the error console
+ // with error messages that can't be caught.
+ //
+ // This issue can be mitigated by relying on the (for now) proprietary
+ // `location.ancestorOrigins` property which returns an ordered list of
+ // the origins of enclosing windows. See:
+ // http://trac.webkit.org/changeset/113945.
+ if (origins) {
+ so = (location.origin == origins[i]);
+ } else {
+ so = is_same_origin(w);
+ }
+ cache.push([w, so]);
+ i++;
+ }
+ w = window.opener;
+ if (w) {
+ // window.opener isn't included in the `location.ancestorOrigins` prop.
+ // We'll just have to deal with a simple check and an error msg on WebKit
+ // browsers in this case.
+ cache.push([w, is_same_origin(w)]);
+ }
+ this.window_cache = cache;
+ }
+
+ forEach(cache,
+ function(a) {
+ callback.apply(null, a);
+ });
+ };
+
+ WindowTestEnvironment.prototype.on_tests_ready = function() {
+ var output = new Output();
+ this.output_handler = output;
+
+ var this_obj = this;
+ add_start_callback(function (properties) {
+ this_obj.output_handler.init(properties);
+ this_obj._dispatch("start_callback", [properties],
+ { type: "start", properties: properties });
+ });
+ add_test_state_callback(function(test) {
+ this_obj.output_handler.show_status();
+ this_obj._dispatch("test_state_callback", [test],
+ { type: "test_state", test: test.structured_clone() });
+ });
+ add_result_callback(function (test) {
+ this_obj.output_handler.show_status();
+ this_obj._dispatch("result_callback", [test],
+ { type: "result", test: test.structured_clone() });
+ });
+ add_completion_callback(function (tests, harness_status) {
+ this_obj.output_handler.show_results(tests, harness_status);
+ var cloned_tests = map(tests, function(test) { return test.structured_clone(); });
+ this_obj._dispatch("completion_callback", [tests, harness_status],
+ { type: "complete", tests: cloned_tests,
+ status: harness_status.structured_clone() });
+ });
+ };
+
+ WindowTestEnvironment.prototype.next_default_test_name = function() {
+ //Don't use document.title to work around an Opera bug in XHTML documents
+ var title = document.getElementsByTagName("title")[0];
+ var prefix = (title && title.firstChild && title.firstChild.data) || "Untitled";
+ var suffix = this.name_counter > 0 ? " " + this.name_counter : "";
+ this.name_counter++;
+ return prefix + suffix;
+ };
+
+ WindowTestEnvironment.prototype.on_new_harness_properties = function(properties) {
+ this.output_handler.setup(properties);
+ };
+
+ WindowTestEnvironment.prototype.add_on_loaded_callback = function(callback) {
+ on_event(window, 'load', callback);
+ };
+
+ WindowTestEnvironment.prototype.test_timeout = function() {
+ var metas = document.getElementsByTagName("meta");
+ for (var i = 0; i < metas.length; i++) {
+ if (metas[i].name == "timeout") {
+ if (metas[i].content == "long") {
+ return settings.harness_timeout.long;
+ }
+ break;
+ }
+ }
+ return settings.harness_timeout.normal;
+ };
+
+ WindowTestEnvironment.prototype.global_scope = function() {
+ return window;
+ };
+
+ /*
+ * Base TestEnvironment implementation for a generic web worker.
+ *
+ * Workers accumulate test results. One or more clients can connect and
+ * retrieve results from a worker at any time.
+ *
+ * WorkerTestEnvironment supports communicating with a client via a
+ * MessagePort. The mechanism for determining the appropriate MessagePort
+ * for communicating with a client depends on the type of worker and is
+ * implemented by the various specializations of WorkerTestEnvironment
+ * below.
+ *
+ * A client document using testharness can use fetch_tests_from_worker() to
+ * retrieve results from a worker. See apisample16.html.
+ */
+ function WorkerTestEnvironment() {
+ this.name_counter = 0;
+ this.all_loaded = true;
+ this.message_list = [];
+ this.message_ports = [];
+ }
+
+ WorkerTestEnvironment.prototype._dispatch = function(message) {
+ this.message_list.push(message);
+ for (var i = 0; i < this.message_ports.length; ++i)
+ {
+ this.message_ports[i].postMessage(message);
+ }
+ };
+
+ // The only requirement is that port has a postMessage() method. It doesn't
+ // have to be an instance of a MessagePort, and often isn't.
+ WorkerTestEnvironment.prototype._add_message_port = function(port) {
+ this.message_ports.push(port);
+ for (var i = 0; i < this.message_list.length; ++i)
+ {
+ port.postMessage(this.message_list[i]);
+ }
+ };
+
+ WorkerTestEnvironment.prototype.next_default_test_name = function() {
+ var suffix = this.name_counter > 0 ? " " + this.name_counter : "";
+ this.name_counter++;
+ return "Untitled" + suffix;
+ };
+
+ WorkerTestEnvironment.prototype.on_new_harness_properties = function() {};
+
+ WorkerTestEnvironment.prototype.on_tests_ready = function() {
+ var this_obj = this;
+ add_start_callback(
+ function(properties) {
+ this_obj._dispatch({
+ type: "start",
+ properties: properties,
+ });
+ });
+ add_test_state_callback(
+ function(test) {
+ this_obj._dispatch({
+ type: "test_state",
+ test: test.structured_clone()
+ });
+ });
+ add_result_callback(
+ function(test) {
+ this_obj._dispatch({
+ type: "result",
+ test: test.structured_clone()
+ });
+ });
+ add_completion_callback(
+ function(tests, harness_status) {
+ this_obj._dispatch({
+ type: "complete",
+ tests: map(tests,
+ function(test) {
+ return test.structured_clone();
+ }),
+ status: harness_status.structured_clone()
+ });
+ });
+ };
+
+ WorkerTestEnvironment.prototype.add_on_loaded_callback = function() {};
+
+ WorkerTestEnvironment.prototype.test_timeout = function() {
+ // Tests running in a worker don't have a default timeout. I.e. all
+ // worker tests behave as if settings.explicit_timeout is true.
+ return null;
+ };
+
+ WorkerTestEnvironment.prototype.global_scope = function() {
+ return self;
+ };
+
+ /*
+ * Dedicated web workers.
+ * https://html.spec.whatwg.org/multipage/workers.html#dedicatedworkerglobalscope
+ *
+ * This class is used as the test_environment when testharness is running
+ * inside a dedicated worker.
+ */
+ function DedicatedWorkerTestEnvironment() {
+ WorkerTestEnvironment.call(this);
+ // self is an instance of DedicatedWorkerGlobalScope which exposes
+ // a postMessage() method for communicating via the message channel
+ // established when the worker is created.
+ this._add_message_port(self);
+ }
+ DedicatedWorkerTestEnvironment.prototype = Object.create(WorkerTestEnvironment.prototype);
+
+ DedicatedWorkerTestEnvironment.prototype.on_tests_ready = function() {
+ WorkerTestEnvironment.prototype.on_tests_ready.call(this);
+ // In the absence of an onload notification, we a require dedicated
+ // workers to explicitly signal when the tests are done.
+ tests.wait_for_finish = true;
+ };
+
+ /*
+ * Shared web workers.
+ * https://html.spec.whatwg.org/multipage/workers.html#sharedworkerglobalscope
+ *
+ * This class is used as the test_environment when testharness is running
+ * inside a shared web worker.
+ */
+ function SharedWorkerTestEnvironment() {
+ WorkerTestEnvironment.call(this);
+ var this_obj = this;
+ // Shared workers receive message ports via the 'onconnect' event for
+ // each connection.
+ self.addEventListener("connect",
+ function(message_event) {
+ this_obj._add_message_port(message_event.source);
+ });
+ }
+ SharedWorkerTestEnvironment.prototype = Object.create(WorkerTestEnvironment.prototype);
+
+ SharedWorkerTestEnvironment.prototype.on_tests_ready = function() {
+ WorkerTestEnvironment.prototype.on_tests_ready.call(this);
+ // In the absence of an onload notification, we a require shared
+ // workers to explicitly signal when the tests are done.
+ tests.wait_for_finish = true;
+ };
+
+ /*
+ * Service workers.
+ * http://www.w3.org/TR/service-workers/
+ *
+ * This class is used as the test_environment when testharness is running
+ * inside a service worker.
+ */
+ function ServiceWorkerTestEnvironment() {
+ WorkerTestEnvironment.call(this);
+ this.all_loaded = false;
+ this.on_loaded_callback = null;
+ var this_obj = this;
+ self.addEventListener("message",
+ function(event) {
+ if (event.data.type && event.data.type === "connect") {
+ this_obj._add_message_port(event.ports[0]);
+ event.ports[0].start();
+ }
+ });
+
+ // The oninstall event is received after the service worker script and
+ // all imported scripts have been fetched and executed. It's the
+ // equivalent of an onload event for a document. All tests should have
+ // been added by the time this event is received, thus it's not
+ // necessary to wait until the onactivate event.
+ on_event(self, "install",
+ function(event) {
+ this_obj.all_loaded = true;
+ if (this_obj.on_loaded_callback) {
+ this_obj.on_loaded_callback();
+ }
+ });
+ }
+ ServiceWorkerTestEnvironment.prototype = Object.create(WorkerTestEnvironment.prototype);
+
+ ServiceWorkerTestEnvironment.prototype.add_on_loaded_callback = function(callback) {
+ if (this.all_loaded) {
+ callback();
+ } else {
+ this.on_loaded_callback = callback;
+ }
+ };
+
+ function create_test_environment() {
+ if ('document' in self) {
+ return new WindowTestEnvironment();
+ }
+ if ('DedicatedWorkerGlobalScope' in self &&
+ self instanceof DedicatedWorkerGlobalScope) {
+ return new DedicatedWorkerTestEnvironment();
+ }
+ if ('SharedWorkerGlobalScope' in self &&
+ self instanceof SharedWorkerGlobalScope) {
+ return new SharedWorkerTestEnvironment();
+ }
+ if ('ServiceWorkerGlobalScope' in self &&
+ self instanceof ServiceWorkerGlobalScope) {
+ return new ServiceWorkerTestEnvironment();
+ }
+ throw new Error("Unsupported test environment");
+ }
+
+ var test_environment = create_test_environment();
+
+ function is_shared_worker(worker) {
+ return 'SharedWorker' in self && worker instanceof SharedWorker;
+ }
+
+ function is_service_worker(worker) {
+ return 'ServiceWorker' in self && worker instanceof ServiceWorker;
+ }
+
+ /*
+ * API functions
+ */
+
+ function test(func, name, properties)
+ {
+ var test_name = name ? name : test_environment.next_default_test_name();
+ properties = properties ? properties : {};
+ var test_obj = new Test(test_name, properties);
+ test_obj.step(func, test_obj, test_obj);
+ if (test_obj.phase === test_obj.phases.STARTED) {
+ test_obj.done();
+ }
+ }
+
+ function async_test(func, name, properties)
+ {
+ if (typeof func !== "function") {
+ properties = name;
+ name = func;
+ func = null;
+ }
+ var test_name = name ? name : test_environment.next_default_test_name();
+ properties = properties ? properties : {};
+ var test_obj = new Test(test_name, properties);
+ if (func) {
+ test_obj.step(func, test_obj, test_obj);
+ }
+ return test_obj;
+ }
+
+ function promise_test(func, name, properties) {
+ var test = async_test(name, properties);
+ Promise.resolve(test.step(func, test, test))
+ .then(
+ function() {
+ test.done();
+ })
+ .catch(test.step_func(
+ function(value) {
+ if (value instanceof AssertionError) {
+ throw value;
+ }
+ assert(false, "promise_test", null,
+ "Unhandled rejection with value: ${value}", {value:value});
+ }));
+ }
+
+ function promise_rejects(test, expected, promise) {
+ return promise.then(test.unreached_func("Should have rejected.")).catch(function(e) {
+ assert_throws(expected, function() { throw e });
+ });
+ }
+
+ function setup(func_or_properties, maybe_properties)
+ {
+ var func = null;
+ var properties = {};
+ if (arguments.length === 2) {
+ func = func_or_properties;
+ properties = maybe_properties;
+ } else if (func_or_properties instanceof Function) {
+ func = func_or_properties;
+ } else {
+ properties = func_or_properties;
+ }
+ tests.setup(func, properties);
+ test_environment.on_new_harness_properties(properties);
+ }
+
+ function done() {
+ if (tests.tests.length === 0) {
+ tests.set_file_is_test();
+ }
+ if (tests.file_is_test) {
+ tests.tests[0].done();
+ }
+ tests.end_wait();
+ }
+
+ function generate_tests(func, args, properties) {
+ forEach(args, function(x, i)
+ {
+ var name = x[0];
+ test(function()
+ {
+ func.apply(this, x.slice(1));
+ },
+ name,
+ Array.isArray(properties) ? properties[i] : properties);
+ });
+ }
+
+ function on_event(object, event, callback)
+ {
+ object.addEventListener(event, callback, false);
+ }
+
+ expose(test, 'test');
+ expose(async_test, 'async_test');
+ expose(promise_test, 'promise_test');
+ expose(promise_rejects, 'promise_rejects');
+ expose(generate_tests, 'generate_tests');
+ expose(setup, 'setup');
+ expose(done, 'done');
+ expose(on_event, 'on_event');
+
+ /*
+ * Return a string truncated to the given length, with ... added at the end
+ * if it was longer.
+ */
+ function truncate(s, len)
+ {
+ if (s.length > len) {
+ return s.substring(0, len - 3) + "...";
+ }
+ return s;
+ }
+
+ /*
+ * Return true if object is probably a Node object.
+ */
+ function is_node(object)
+ {
+ // I use duck-typing instead of instanceof, because
+ // instanceof doesn't work if the node is from another window (like an
+ // iframe's contentWindow):
+ // http://www.w3.org/Bugs/Public/show_bug.cgi?id=12295
+ if ("nodeType" in object &&
+ "nodeName" in object &&
+ "nodeValue" in object &&
+ "childNodes" in object) {
+ try {
+ object.nodeType;
+ } catch (e) {
+ // The object is probably Node.prototype or another prototype
+ // object that inherits from it, and not a Node instance.
+ return false;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /*
+ * Convert a value to a nice, human-readable string
+ */
+ function format_value(val, seen)
+ {
+ if (!seen) {
+ seen = [];
+ }
+ if (typeof val === "object" && val !== null) {
+ if (seen.indexOf(val) >= 0) {
+ return "[...]";
+ }
+ seen.push(val);
+ }
+ if (Array.isArray(val)) {
+ return "[" + val.map(function(x) {return format_value(x, seen);}).join(", ") + "]";
+ }
+
+ switch (typeof val) {
+ case "string":
+ val = val.replace("\\", "\\\\");
+ for (var i = 0; i < 32; i++) {
+ var replace = "\\";
+ switch (i) {
+ case 0: replace += "0"; break;
+ case 1: replace += "x01"; break;
+ case 2: replace += "x02"; break;
+ case 3: replace += "x03"; break;
+ case 4: replace += "x04"; break;
+ case 5: replace += "x05"; break;
+ case 6: replace += "x06"; break;
+ case 7: replace += "x07"; break;
+ case 8: replace += "b"; break;
+ case 9: replace += "t"; break;
+ case 10: replace += "n"; break;
+ case 11: replace += "v"; break;
+ case 12: replace += "f"; break;
+ case 13: replace += "r"; break;
+ case 14: replace += "x0e"; break;
+ case 15: replace += "x0f"; break;
+ case 16: replace += "x10"; break;
+ case 17: replace += "x11"; break;
+ case 18: replace += "x12"; break;
+ case 19: replace += "x13"; break;
+ case 20: replace += "x14"; break;
+ case 21: replace += "x15"; break;
+ case 22: replace += "x16"; break;
+ case 23: replace += "x17"; break;
+ case 24: replace += "x18"; break;
+ case 25: replace += "x19"; break;
+ case 26: replace += "x1a"; break;
+ case 27: replace += "x1b"; break;
+ case 28: replace += "x1c"; break;
+ case 29: replace += "x1d"; break;
+ case 30: replace += "x1e"; break;
+ case 31: replace += "x1f"; break;
+ }
+ val = val.replace(RegExp(String.fromCharCode(i), "g"), replace);
+ }
+ return '"' + val.replace(/"/g, '\\"') + '"';
+ case "boolean":
+ case "undefined":
+ return String(val);
+ case "number":
+ // In JavaScript, -0 === 0 and String(-0) == "0", so we have to
+ // special-case.
+ if (val === -0 && 1/val === -Infinity) {
+ return "-0";
+ }
+ return String(val);
+ case "object":
+ if (val === null) {
+ return "null";
+ }
+
+ // Special-case Node objects, since those come up a lot in my tests. I
+ // ignore namespaces.
+ if (is_node(val)) {
+ switch (val.nodeType) {
+ case Node.ELEMENT_NODE:
+ var ret = "<" + val.localName;
+ for (var i = 0; i < val.attributes.length; i++) {
+ ret += " " + val.attributes[i].name + '="' + val.attributes[i].value + '"';
+ }
+ ret += ">" + val.innerHTML + "</" + val.localName + ">";
+ return "Element node " + truncate(ret, 60);
+ case Node.TEXT_NODE:
+ return 'Text node "' + truncate(val.data, 60) + '"';
+ case Node.PROCESSING_INSTRUCTION_NODE:
+ return "ProcessingInstruction node with target " + format_value(truncate(val.target, 60)) + " and data " + format_value(truncate(val.data, 60));
+ case Node.COMMENT_NODE:
+ return "Comment node <!--" + truncate(val.data, 60) + "-->";
+ case Node.DOCUMENT_NODE:
+ return "Document node with " + val.childNodes.length + (val.childNodes.length == 1 ? " child" : " children");
+ case Node.DOCUMENT_TYPE_NODE:
+ return "DocumentType node";
+ case Node.DOCUMENT_FRAGMENT_NODE:
+ return "DocumentFragment node with " + val.childNodes.length + (val.childNodes.length == 1 ? " child" : " children");
+ default:
+ return "Node object of unknown type";
+ }
+ }
+
+ /* falls through */
+ default:
+ return typeof val + ' "' + truncate(String(val), 60) + '"';
+ }
+ }
+ expose(format_value, "format_value");
+
+ /*
+ * Assertions
+ */
+
+ function assert_true(actual, description)
+ {
+ assert(actual === true, "assert_true", description,
+ "expected true got ${actual}", {actual:actual});
+ }
+ expose(assert_true, "assert_true");
+
+ function assert_false(actual, description)
+ {
+ assert(actual === false, "assert_false", description,
+ "expected false got ${actual}", {actual:actual});
+ }
+ expose(assert_false, "assert_false");
+
+ function same_value(x, y) {
+ if (y !== y) {
+ //NaN case
+ return x !== x;
+ }
+ if (x === 0 && y === 0) {
+ //Distinguish +0 and -0
+ return 1/x === 1/y;
+ }
+ return x === y;
+ }
+
+ function assert_equals(actual, expected, description)
+ {
+ /*
+ * Test if two primitives are equal or two objects
+ * are the same object
+ */
+ if (typeof actual != typeof expected) {
+ assert(false, "assert_equals", description,
+ "expected (" + typeof expected + ") ${expected} but got (" + typeof actual + ") ${actual}",
+ {expected:expected, actual:actual});
+ return;
+ }
+ assert(same_value(actual, expected), "assert_equals", description,
+ "expected ${expected} but got ${actual}",
+ {expected:expected, actual:actual});
+ }
+ expose(assert_equals, "assert_equals");
+
+ function assert_not_equals(actual, expected, description)
+ {
+ /*
+ * Test if two primitives are unequal or two objects
+ * are different objects
+ */
+ assert(!same_value(actual, expected), "assert_not_equals", description,
+ "got disallowed value ${actual}",
+ {actual:actual});
+ }
+ expose(assert_not_equals, "assert_not_equals");
+
+ function assert_in_array(actual, expected, description)
+ {
+ assert(expected.indexOf(actual) != -1, "assert_in_array", description,
+ "value ${actual} not in array ${expected}",
+ {actual:actual, expected:expected});
+ }
+ expose(assert_in_array, "assert_in_array");
+
+ function assert_object_equals(actual, expected, description)
+ {
+ //This needs to be improved a great deal
+ function check_equal(actual, expected, stack)
+ {
+ stack.push(actual);
+
+ var p;
+ for (p in actual) {
+ assert(expected.hasOwnProperty(p), "assert_object_equals", description,
+ "unexpected property ${p}", {p:p});
+
+ if (typeof actual[p] === "object" && actual[p] !== null) {
+ if (stack.indexOf(actual[p]) === -1) {
+ check_equal(actual[p], expected[p], stack);
+ }
+ } else {
+ assert(same_value(actual[p], expected[p]), "assert_object_equals", description,
+ "property ${p} expected ${expected} got ${actual}",
+ {p:p, expected:expected, actual:actual});
+ }
+ }
+ for (p in expected) {
+ assert(actual.hasOwnProperty(p),
+ "assert_object_equals", description,
+ "expected property ${p} missing", {p:p});
+ }
+ stack.pop();
+ }
+ check_equal(actual, expected, []);
+ }
+ expose(assert_object_equals, "assert_object_equals");
+
+ function assert_array_equals(actual, expected, description)
+ {
+ assert(actual.length === expected.length,
+ "assert_array_equals", description,
+ "lengths differ, expected ${expected} got ${actual}",
+ {expected:expected.length, actual:actual.length});
+
+ for (var i = 0; i < actual.length; i++) {
+ assert(actual.hasOwnProperty(i) === expected.hasOwnProperty(i),
+ "assert_array_equals", description,
+ "property ${i}, property expected to be ${expected} but was ${actual}",
+ {i:i, expected:expected.hasOwnProperty(i) ? "present" : "missing",
+ actual:actual.hasOwnProperty(i) ? "present" : "missing"});
+ assert(same_value(expected[i], actual[i]),
+ "assert_array_equals", description,
+ "property ${i}, expected ${expected} but got ${actual}",
+ {i:i, expected:expected[i], actual:actual[i]});
+ }
+ }
+ expose(assert_array_equals, "assert_array_equals");
+
+ function assert_approx_equals(actual, expected, epsilon, description)
+ {
+ /*
+ * Test if two primitive numbers are equal withing +/- epsilon
+ */
+ assert(typeof actual === "number",
+ "assert_approx_equals", description,
+ "expected a number but got a ${type_actual}",
+ {type_actual:typeof actual});
+
+ assert(Math.abs(actual - expected) <= epsilon,
+ "assert_approx_equals", description,
+ "expected ${expected} +/- ${epsilon} but got ${actual}",
+ {expected:expected, actual:actual, epsilon:epsilon});
+ }
+ expose(assert_approx_equals, "assert_approx_equals");
+
+ function assert_less_than(actual, expected, description)
+ {
+ /*
+ * Test if a primitive number is less than another
+ */
+ assert(typeof actual === "number",
+ "assert_less_than", description,
+ "expected a number but got a ${type_actual}",
+ {type_actual:typeof actual});
+
+ assert(actual < expected,
+ "assert_less_than", description,
+ "expected a number less than ${expected} but got ${actual}",
+ {expected:expected, actual:actual});
+ }
+ expose(assert_less_than, "assert_less_than");
+
+ function assert_greater_than(actual, expected, description)
+ {
+ /*
+ * Test if a primitive number is greater than another
+ */
+ assert(typeof actual === "number",
+ "assert_greater_than", description,
+ "expected a number but got a ${type_actual}",
+ {type_actual:typeof actual});
+
+ assert(actual > expected,
+ "assert_greater_than", description,
+ "expected a number greater than ${expected} but got ${actual}",
+ {expected:expected, actual:actual});
+ }
+ expose(assert_greater_than, "assert_greater_than");
+
+ function assert_between_exclusive(actual, lower, upper, description)
+ {
+ /*
+ * Test if a primitive number is between two others
+ */
+ assert(typeof actual === "number",
+ "assert_between_exclusive", description,
+ "expected a number but got a ${type_actual}",
+ {type_actual:typeof actual});
+
+ assert(actual > lower && actual < upper,
+ "assert_between_exclusive", description,
+ "expected a number greater than ${lower} " +
+ "and less than ${upper} but got ${actual}",
+ {lower:lower, upper:upper, actual:actual});
+ }
+ expose(assert_between_exclusive, "assert_between_exclusive");
+
+ function assert_less_than_equal(actual, expected, description)
+ {
+ /*
+ * Test if a primitive number is less than or equal to another
+ */
+ assert(typeof actual === "number",
+ "assert_less_than_equal", description,
+ "expected a number but got a ${type_actual}",
+ {type_actual:typeof actual});
+
+ assert(actual <= expected,
+ "assert_less_than_equal", description,
+ "expected a number less than or equal to ${expected} but got ${actual}",
+ {expected:expected, actual:actual});
+ }
+ expose(assert_less_than_equal, "assert_less_than_equal");
+
+ function assert_greater_than_equal(actual, expected, description)
+ {
+ /*
+ * Test if a primitive number is greater than or equal to another
+ */
+ assert(typeof actual === "number",
+ "assert_greater_than_equal", description,
+ "expected a number but got a ${type_actual}",
+ {type_actual:typeof actual});
+
+ assert(actual >= expected,
+ "assert_greater_than_equal", description,
+ "expected a number greater than or equal to ${expected} but got ${actual}",
+ {expected:expected, actual:actual});
+ }
+ expose(assert_greater_than_equal, "assert_greater_than_equal");
+
+ function assert_between_inclusive(actual, lower, upper, description)
+ {
+ /*
+ * Test if a primitive number is between to two others or equal to either of them
+ */
+ assert(typeof actual === "number",
+ "assert_between_inclusive", description,
+ "expected a number but got a ${type_actual}",
+ {type_actual:typeof actual});
+
+ assert(actual >= lower && actual <= upper,
+ "assert_between_inclusive", description,
+ "expected a number greater than or equal to ${lower} " +
+ "and less than or equal to ${upper} but got ${actual}",
+ {lower:lower, upper:upper, actual:actual});
+ }
+ expose(assert_between_inclusive, "assert_between_inclusive");
+
+ function assert_regexp_match(actual, expected, description) {
+ /*
+ * Test if a string (actual) matches a regexp (expected)
+ */
+ assert(expected.test(actual),
+ "assert_regexp_match", description,
+ "expected ${expected} but got ${actual}",
+ {expected:expected, actual:actual});
+ }
+ expose(assert_regexp_match, "assert_regexp_match");
+
+ function assert_class_string(object, class_string, description) {
+ assert_equals({}.toString.call(object), "[object " + class_string + "]",
+ description);
+ }
+ expose(assert_class_string, "assert_class_string");
+
+
+ function _assert_own_property(name) {
+ return function(object, property_name, description)
+ {
+ assert(object.hasOwnProperty(property_name),
+ name, description,
+ "expected property ${p} missing", {p:property_name});
+ };
+ }
+ expose(_assert_own_property("assert_exists"), "assert_exists");
+ expose(_assert_own_property("assert_own_property"), "assert_own_property");
+
+ function assert_not_exists(object, property_name, description)
+ {
+ assert(!object.hasOwnProperty(property_name),
+ "assert_not_exists", description,
+ "unexpected property ${p} found", {p:property_name});
+ }
+ expose(assert_not_exists, "assert_not_exists");
+
+ function _assert_inherits(name) {
+ return function (object, property_name, description)
+ {
+ assert(typeof object === "object",
+ name, description,
+ "provided value is not an object");
+
+ assert("hasOwnProperty" in object,
+ name, description,
+ "provided value is an object but has no hasOwnProperty method");
+
+ assert(!object.hasOwnProperty(property_name),
+ name, description,
+ "property ${p} found on object expected in prototype chain",
+ {p:property_name});
+
+ assert(property_name in object,
+ name, description,
+ "property ${p} not found in prototype chain",
+ {p:property_name});
+ };
+ }
+ expose(_assert_inherits("assert_inherits"), "assert_inherits");
+ expose(_assert_inherits("assert_idl_attribute"), "assert_idl_attribute");
+
+ function assert_readonly(object, property_name, description)
+ {
+ var initial_value = object[property_name];
+ try {
+ //Note that this can have side effects in the case where
+ //the property has PutForwards
+ object[property_name] = initial_value + "a"; //XXX use some other value here?
+ assert(same_value(object[property_name], initial_value),
+ "assert_readonly", description,
+ "changing property ${p} succeeded",
+ {p:property_name});
+ } finally {
+ object[property_name] = initial_value;
+ }
+ }
+ expose(assert_readonly, "assert_readonly");
+
+ function assert_throws(code, func, description)
+ {
+ try {
+ func.call(this);
+ assert(false, "assert_throws", description,
+ "${func} did not throw", {func:func});
+ } catch (e) {
+ if (e instanceof AssertionError) {
+ throw e;
+ }
+ if (code === null) {
+ return;
+ }
+ if (typeof code === "object") {
+ assert(typeof e == "object" && "name" in e && e.name == code.name,
+ "assert_throws", description,
+ "${func} threw ${actual} (${actual_name}) expected ${expected} (${expected_name})",
+ {func:func, actual:e, actual_name:e.name,
+ expected:code,
+ expected_name:code.name});
+ return;
+ }
+
+ var code_name_map = {
+ INDEX_SIZE_ERR: 'IndexSizeError',
+ HIERARCHY_REQUEST_ERR: 'HierarchyRequestError',
+ WRONG_DOCUMENT_ERR: 'WrongDocumentError',
+ INVALID_CHARACTER_ERR: 'InvalidCharacterError',
+ NO_MODIFICATION_ALLOWED_ERR: 'NoModificationAllowedError',
+ NOT_FOUND_ERR: 'NotFoundError',
+ NOT_SUPPORTED_ERR: 'NotSupportedError',
+ INVALID_STATE_ERR: 'InvalidStateError',
+ SYNTAX_ERR: 'SyntaxError',
+ INVALID_MODIFICATION_ERR: 'InvalidModificationError',
+ NAMESPACE_ERR: 'NamespaceError',
+ INVALID_ACCESS_ERR: 'InvalidAccessError',
+ TYPE_MISMATCH_ERR: 'TypeMismatchError',
+ SECURITY_ERR: 'SecurityError',
+ NETWORK_ERR: 'NetworkError',
+ ABORT_ERR: 'AbortError',
+ URL_MISMATCH_ERR: 'URLMismatchError',
+ QUOTA_EXCEEDED_ERR: 'QuotaExceededError',
+ TIMEOUT_ERR: 'TimeoutError',
+ INVALID_NODE_TYPE_ERR: 'InvalidNodeTypeError',
+ DATA_CLONE_ERR: 'DataCloneError'
+ };
+
+ var name = code in code_name_map ? code_name_map[code] : code;
+
+ var name_code_map = {
+ IndexSizeError: 1,
+ HierarchyRequestError: 3,
+ WrongDocumentError: 4,
+ InvalidCharacterError: 5,
+ NoModificationAllowedError: 7,
+ NotFoundError: 8,
+ NotSupportedError: 9,
+ InvalidStateError: 11,
+ SyntaxError: 12,
+ InvalidModificationError: 13,
+ NamespaceError: 14,
+ InvalidAccessError: 15,
+ TypeMismatchError: 17,
+ SecurityError: 18,
+ NetworkError: 19,
+ AbortError: 20,
+ URLMismatchError: 21,
+ QuotaExceededError: 22,
+ TimeoutError: 23,
+ InvalidNodeTypeError: 24,
+ DataCloneError: 25,
+
+ EncodingError: 0,
+ NotReadableError: 0,
+ UnknownError: 0,
+ ConstraintError: 0,
+ DataError: 0,
+ TransactionInactiveError: 0,
+ ReadOnlyError: 0,
+ VersionError: 0,
+ OperationError: 0,
+ };
+
+ if (!(name in name_code_map)) {
+ throw new AssertionError('Test bug: unrecognized DOMException code "' + code + '" passed to assert_throws()');
+ }
+
+ var required_props = { code: name_code_map[name] };
+
+ if (required_props.code === 0 ||
+ (typeof e == "object" &&
+ "name" in e &&
+ e.name !== e.name.toUpperCase() &&
+ e.name !== "DOMException")) {
+ // New style exception: also test the name property.
+ required_props.name = name;
+ }
+
+ //We'd like to test that e instanceof the appropriate interface,
+ //but we can't, because we don't know what window it was created
+ //in. It might be an instanceof the appropriate interface on some
+ //unknown other window. TODO: Work around this somehow?
+
+ assert(typeof e == "object",
+ "assert_throws", description,
+ "${func} threw ${e} with type ${type}, not an object",
+ {func:func, e:e, type:typeof e});
+
+ for (var prop in required_props) {
+ assert(typeof e == "object" && prop in e && e[prop] == required_props[prop],
+ "assert_throws", description,
+ "${func} threw ${e} that is not a DOMException " + code + ": property ${prop} is equal to ${actual}, expected ${expected}",
+ {func:func, e:e, prop:prop, actual:e[prop], expected:required_props[prop]});
+ }
+ }
+ }
+ expose(assert_throws, "assert_throws");
+
+ function assert_unreached(description) {
+ assert(false, "assert_unreached", description,
+ "Reached unreachable code");
+ }
+ expose(assert_unreached, "assert_unreached");
+
+ function assert_any(assert_func, actual, expected_array)
+ {
+ var args = [].slice.call(arguments, 3);
+ var errors = [];
+ var passed = false;
+ forEach(expected_array,
+ function(expected)
+ {
+ try {
+ assert_func.apply(this, [actual, expected].concat(args));
+ passed = true;
+ } catch (e) {
+ errors.push(e.message);
+ }
+ });
+ if (!passed) {
+ throw new AssertionError(errors.join("\n\n"));
+ }
+ }
+ expose(assert_any, "assert_any");
+
+ function Test(name, properties)
+ {
+ if (tests.file_is_test && tests.tests.length) {
+ throw new Error("Tried to create a test with file_is_test");
+ }
+ this.name = name;
+
+ this.phase = this.phases.INITIAL;
+
+ this.status = this.NOTRUN;
+ this.timeout_id = null;
+ this.index = null;
+
+ this.properties = properties;
+ var timeout = properties.timeout ? properties.timeout : settings.test_timeout;
+ if (timeout !== null) {
+ this.timeout_length = timeout * tests.timeout_multiplier;
+ } else {
+ this.timeout_length = null;
+ }
+
+ this.message = null;
+ this.stack = null;
+
+ this.steps = [];
+
+ this.cleanup_callbacks = [];
+
+ tests.push(this);
+ }
+
+ Test.statuses = {
+ PASS:0,
+ FAIL:1,
+ TIMEOUT:2,
+ NOTRUN:3
+ };
+
+ Test.prototype = merge({}, Test.statuses);
+
+ Test.prototype.phases = {
+ INITIAL:0,
+ STARTED:1,
+ HAS_RESULT:2,
+ COMPLETE:3
+ };
+
+ Test.prototype.structured_clone = function()
+ {
+ if (!this._structured_clone) {
+ var msg = this.message;
+ msg = msg ? String(msg) : msg;
+ this._structured_clone = merge({
+ name:String(this.name),
+ properties:merge({}, this.properties),
+ }, Test.statuses);
+ }
+ this._structured_clone.status = this.status;
+ this._structured_clone.message = this.message;
+ this._structured_clone.stack = this.stack;
+ this._structured_clone.index = this.index;
+ return this._structured_clone;
+ };
+
+ Test.prototype.step = function(func, this_obj)
+ {
+ if (this.phase > this.phases.STARTED) {
+ return;
+ }
+ this.phase = this.phases.STARTED;
+ //If we don't get a result before the harness times out that will be a test timout
+ this.set_status(this.TIMEOUT, "Test timed out");
+
+ tests.started = true;
+ tests.notify_test_state(this);
+
+ if (this.timeout_id === null) {
+ this.set_timeout();
+ }
+
+ this.steps.push(func);
+
+ if (arguments.length === 1) {
+ this_obj = this;
+ }
+
+ try {
+ return func.apply(this_obj, Array.prototype.slice.call(arguments, 2));
+ } catch (e) {
+ if (this.phase >= this.phases.HAS_RESULT) {
+ return;
+ }
+ var message = String((typeof e === "object" && e !== null) ? e.message : e);
+ var stack = e.stack ? e.stack : null;
+
+ this.set_status(this.FAIL, message, stack);
+ this.phase = this.phases.HAS_RESULT;
+ this.done();
+ }
+ };
+
+ Test.prototype.step_func = function(func, this_obj)
+ {
+ var test_this = this;
+
+ if (arguments.length === 1) {
+ this_obj = test_this;
+ }
+
+ return function()
+ {
+ return test_this.step.apply(test_this, [func, this_obj].concat(
+ Array.prototype.slice.call(arguments)));
+ };
+ };
+
+ Test.prototype.step_func_done = function(func, this_obj)
+ {
+ var test_this = this;
+
+ if (arguments.length === 1) {
+ this_obj = test_this;
+ }
+
+ return function()
+ {
+ if (func) {
+ test_this.step.apply(test_this, [func, this_obj].concat(
+ Array.prototype.slice.call(arguments)));
+ }
+ test_this.done();
+ };
+ };
+
+ Test.prototype.unreached_func = function(description)
+ {
+ return this.step_func(function() {
+ assert_unreached(description);
+ });
+ };
+
+ Test.prototype.add_cleanup = function(callback) {
+ this.cleanup_callbacks.push(callback);
+ };
+
+ Test.prototype.force_timeout = function() {
+ this.set_status(this.TIMEOUT);
+ this.phase = this.phases.HAS_RESULT;
+ };
+
+ Test.prototype.set_timeout = function()
+ {
+ if (this.timeout_length !== null) {
+ var this_obj = this;
+ this.timeout_id = setTimeout(function()
+ {
+ this_obj.timeout();
+ }, this.timeout_length);
+ }
+ };
+
+ Test.prototype.set_status = function(status, message, stack)
+ {
+ this.status = status;
+ this.message = message;
+ this.stack = stack ? stack : null;
+ };
+
+ Test.prototype.timeout = function()
+ {
+ this.timeout_id = null;
+ this.set_status(this.TIMEOUT, "Test timed out");
+ this.phase = this.phases.HAS_RESULT;
+ this.done();
+ };
+
+ Test.prototype.done = function()
+ {
+ if (this.phase == this.phases.COMPLETE) {
+ return;
+ }
+
+ if (this.phase <= this.phases.STARTED) {
+ this.set_status(this.PASS, null);
+ }
+
+ this.phase = this.phases.COMPLETE;
+
+ clearTimeout(this.timeout_id);
+ tests.result(this);
+ this.cleanup();
+ };
+
+ Test.prototype.cleanup = function() {
+ forEach(this.cleanup_callbacks,
+ function(cleanup_callback) {
+ cleanup_callback();
+ });
+ };
+
+ /*
+ * A RemoteTest object mirrors a Test object on a remote worker. The
+ * associated RemoteWorker updates the RemoteTest object in response to
+ * received events. In turn, the RemoteTest object replicates these events
+ * on the local document. This allows listeners (test result reporting
+ * etc..) to transparently handle local and remote events.
+ */
+ function RemoteTest(clone) {
+ var this_obj = this;
+ Object.keys(clone).forEach(
+ function(key) {
+ this_obj[key] = clone[key];
+ });
+ this.index = null;
+ this.phase = this.phases.INITIAL;
+ this.update_state_from(clone);
+ tests.push(this);
+ }
+
+ RemoteTest.prototype.structured_clone = function() {
+ var clone = {};
+ Object.keys(this).forEach(
+ function(key) {
+ if (typeof(this[key]) === "object") {
+ clone[key] = merge({}, this[key]);
+ } else {
+ clone[key] = this[key];
+ }
+ });
+ clone.phases = merge({}, this.phases);
+ return clone;
+ };
+
+ RemoteTest.prototype.cleanup = function() {};
+ RemoteTest.prototype.phases = Test.prototype.phases;
+ RemoteTest.prototype.update_state_from = function(clone) {
+ this.status = clone.status;
+ this.message = clone.message;
+ this.stack = clone.stack;
+ if (this.phase === this.phases.INITIAL) {
+ this.phase = this.phases.STARTED;
+ }
+ };
+ RemoteTest.prototype.done = function() {
+ this.phase = this.phases.COMPLETE;
+ }
+
+ /*
+ * A RemoteWorker listens for test events from a worker. These events are
+ * then used to construct and maintain RemoteTest objects that mirror the
+ * tests running on the remote worker.
+ */
+ function RemoteWorker(worker) {
+ this.running = true;
+ this.tests = new Array();
+
+ var this_obj = this;
+ worker.onerror = function(error) { this_obj.worker_error(error); };
+
+ var message_port;
+
+ if (is_service_worker(worker)) {
+ // The ServiceWorker's implicit MessagePort is currently not
+ // reliably accessible from the ServiceWorkerGlobalScope due to
+ // Blink setting MessageEvent.source to null for messages sent via
+ // ServiceWorker.postMessage(). Until that's resolved, create an
+ // explicit MessageChannel and pass one end to the worker.
+ var message_channel = new MessageChannel();
+ message_port = message_channel.port1;
+ message_port.start();
+ worker.postMessage({type: "connect"}, [message_channel.port2]);
+ } else if (is_shared_worker(worker)) {
+ message_port = worker.port;
+ } else {
+ message_port = worker;
+ }
+
+ // Keeping a reference to the worker until worker_done() is seen
+ // prevents the Worker object and its MessageChannel from going away
+ // before all the messages are dispatched.
+ this.worker = worker;
+
+ message_port.onmessage =
+ function(message) {
+ if (this_obj.running && (message.data.type in this_obj.message_handlers)) {
+ this_obj.message_handlers[message.data.type].call(this_obj, message.data);
+ }
+ };
+ }
+
+ RemoteWorker.prototype.worker_error = function(error) {
+ var message = error.message || String(error);
+ var filename = (error.filename ? " " + error.filename: "");
+ // FIXME: Display worker error states separately from main document
+ // error state.
+ this.worker_done({
+ status: {
+ status: tests.status.ERROR,
+ message: "Error in worker" + filename + ": " + message,
+ stack: e.stack
+ }
+ });
+ error.preventDefault();
+ };
+
+ RemoteWorker.prototype.test_state = function(data) {
+ var remote_test = this.tests[data.test.index];
+ if (!remote_test) {
+ remote_test = new RemoteTest(data.test);
+ this.tests[data.test.index] = remote_test;
+ }
+ remote_test.update_state_from(data.test);
+ tests.notify_test_state(remote_test);
+ };
+
+ RemoteWorker.prototype.test_done = function(data) {
+ var remote_test = this.tests[data.test.index];
+ remote_test.update_state_from(data.test);
+ remote_test.done();
+ tests.result(remote_test);
+ };
+
+ RemoteWorker.prototype.worker_done = function(data) {
+ if (tests.status.status === null &&
+ data.status.status !== data.status.OK) {
+ tests.status.status = data.status.status;
+ tests.status.message = data.status.message;
+ tests.status.stack = data.status.stack;
+ }
+ this.running = false;
+ this.worker = null;
+ if (tests.all_done()) {
+ tests.complete();
+ }
+ };
+
+ RemoteWorker.prototype.message_handlers = {
+ test_state: RemoteWorker.prototype.test_state,
+ result: RemoteWorker.prototype.test_done,
+ complete: RemoteWorker.prototype.worker_done
+ };
+
+ /*
+ * Harness
+ */
+
+ function TestsStatus()
+ {
+ this.status = null;
+ this.message = null;
+ this.stack = null;
+ }
+
+ TestsStatus.statuses = {
+ OK:0,
+ ERROR:1,
+ TIMEOUT:2
+ };
+
+ TestsStatus.prototype = merge({}, TestsStatus.statuses);
+
+ TestsStatus.prototype.structured_clone = function()
+ {
+ if (!this._structured_clone) {
+ var msg = this.message;
+ msg = msg ? String(msg) : msg;
+ this._structured_clone = merge({
+ status:this.status,
+ message:msg,
+ stack:this.stack
+ }, TestsStatus.statuses);
+ }
+ return this._structured_clone;
+ };
+
+ function Tests()
+ {
+ this.tests = [];
+ this.num_pending = 0;
+
+ this.phases = {
+ INITIAL:0,
+ SETUP:1,
+ HAVE_TESTS:2,
+ HAVE_RESULTS:3,
+ COMPLETE:4
+ };
+ this.phase = this.phases.INITIAL;
+
+ this.properties = {};
+
+ this.wait_for_finish = false;
+ this.processing_callbacks = false;
+
+ this.allow_uncaught_exception = false;
+
+ this.file_is_test = false;
+
+ this.timeout_multiplier = 1;
+ this.timeout_length = test_environment.test_timeout();
+ this.timeout_id = null;
+
+ this.start_callbacks = [];
+ this.test_state_callbacks = [];
+ this.test_done_callbacks = [];
+ this.all_done_callbacks = [];
+
+ this.pending_workers = [];
+
+ this.status = new TestsStatus();
+
+ var this_obj = this;
+
+ test_environment.add_on_loaded_callback(function() {
+ if (this_obj.all_done()) {
+ this_obj.complete();
+ }
+ });
+
+ this.set_timeout();
+ }
+
+ Tests.prototype.setup = function(func, properties)
+ {
+ if (this.phase >= this.phases.HAVE_RESULTS) {
+ return;
+ }
+
+ if (this.phase < this.phases.SETUP) {
+ this.phase = this.phases.SETUP;
+ }
+
+ this.properties = properties;
+
+ for (var p in properties) {
+ if (properties.hasOwnProperty(p)) {
+ var value = properties[p];
+ if (p == "allow_uncaught_exception") {
+ this.allow_uncaught_exception = value;
+ } else if (p == "explicit_done" && value) {
+ this.wait_for_finish = true;
+ } else if (p == "explicit_timeout" && value) {
+ this.timeout_length = null;
+ if (this.timeout_id)
+ {
+ clearTimeout(this.timeout_id);
+ }
+ } else if (p == "timeout_multiplier") {
+ this.timeout_multiplier = value;
+ }
+ }
+ }
+
+ if (func) {
+ try {
+ func();
+ } catch (e) {
+ this.status.status = this.status.ERROR;
+ this.status.message = String(e);
+ this.status.stack = e.stack ? e.stack : null;
+ }
+ }
+ this.set_timeout();
+ };
+
+ Tests.prototype.set_file_is_test = function() {
+ if (this.tests.length > 0) {
+ throw new Error("Tried to set file as test after creating a test");
+ }
+ this.wait_for_finish = true;
+ this.file_is_test = true;
+ // Create the test, which will add it to the list of tests
+ async_test();
+ };
+
+ Tests.prototype.set_timeout = function() {
+ var this_obj = this;
+ clearTimeout(this.timeout_id);
+ if (this.timeout_length !== null) {
+ this.timeout_id = setTimeout(function() {
+ this_obj.timeout();
+ }, this.timeout_length);
+ }
+ };
+
+ Tests.prototype.timeout = function() {
+ if (this.status.status === null) {
+ this.status.status = this.status.TIMEOUT;
+ }
+ this.complete();
+ };
+
+ Tests.prototype.end_wait = function()
+ {
+ this.wait_for_finish = false;
+ if (this.all_done()) {
+ this.complete();
+ }
+ };
+
+ Tests.prototype.push = function(test)
+ {
+ if (this.phase < this.phases.HAVE_TESTS) {
+ this.start();
+ }
+ this.num_pending++;
+ test.index = this.tests.push(test);
+ this.notify_test_state(test);
+ };
+
+ Tests.prototype.notify_test_state = function(test) {
+ var this_obj = this;
+ forEach(this.test_state_callbacks,
+ function(callback) {
+ callback(test, this_obj);
+ });
+ };
+
+ Tests.prototype.all_done = function() {
+ return (this.tests.length > 0 && test_environment.all_loaded &&
+ this.num_pending === 0 && !this.wait_for_finish &&
+ !this.processing_callbacks &&
+ !this.pending_workers.some(function(w) { return w.running; }));
+ };
+
+ Tests.prototype.start = function() {
+ this.phase = this.phases.HAVE_TESTS;
+ this.notify_start();
+ };
+
+ Tests.prototype.notify_start = function() {
+ var this_obj = this;
+ forEach (this.start_callbacks,
+ function(callback)
+ {
+ callback(this_obj.properties);
+ });
+ };
+
+ Tests.prototype.result = function(test)
+ {
+ if (this.phase > this.phases.HAVE_RESULTS) {
+ return;
+ }
+ this.phase = this.phases.HAVE_RESULTS;
+ this.num_pending--;
+ this.notify_result(test);
+ };
+
+ Tests.prototype.notify_result = function(test) {
+ var this_obj = this;
+ this.processing_callbacks = true;
+ forEach(this.test_done_callbacks,
+ function(callback)
+ {
+ callback(test, this_obj);
+ });
+ this.processing_callbacks = false;
+ if (this_obj.all_done()) {
+ this_obj.complete();
+ }
+ };
+
+ Tests.prototype.complete = function() {
+ if (this.phase === this.phases.COMPLETE) {
+ return;
+ }
+ this.phase = this.phases.COMPLETE;
+ var this_obj = this;
+ this.tests.forEach(
+ function(x)
+ {
+ if (x.phase < x.phases.COMPLETE) {
+ this_obj.notify_result(x);
+ x.cleanup();
+ x.phase = x.phases.COMPLETE;
+ }
+ }
+ );
+ this.notify_complete();
+ };
+
+ Tests.prototype.notify_complete = function() {
+ var this_obj = this;
+ if (this.status.status === null) {
+ this.status.status = this.status.OK;
+ }
+
+ forEach (this.all_done_callbacks,
+ function(callback)
+ {
+ callback(this_obj.tests, this_obj.status);
+ });
+ };
+
+ Tests.prototype.fetch_tests_from_worker = function(worker) {
+ if (this.phase >= this.phases.COMPLETE) {
+ return;
+ }
+
+ this.pending_workers.push(new RemoteWorker(worker));
+ };
+
+ function fetch_tests_from_worker(port) {
+ tests.fetch_tests_from_worker(port);
+ }
+ expose(fetch_tests_from_worker, 'fetch_tests_from_worker');
+
+ function timeout() {
+ if (tests.timeout_length === null) {
+ tests.timeout();
+ }
+ }
+ expose(timeout, 'timeout');
+
+ function add_start_callback(callback) {
+ tests.start_callbacks.push(callback);
+ }
+
+ function add_test_state_callback(callback) {
+ tests.test_state_callbacks.push(callback);
+ }
+
+ function add_result_callback(callback)
+ {
+ tests.test_done_callbacks.push(callback);
+ }
+
+ function add_completion_callback(callback)
+ {
+ tests.all_done_callbacks.push(callback);
+ }
+
+ expose(add_start_callback, 'add_start_callback');
+ expose(add_test_state_callback, 'add_test_state_callback');
+ expose(add_result_callback, 'add_result_callback');
+ expose(add_completion_callback, 'add_completion_callback');
+
+ /*
+ * Output listener
+ */
+
+ function Output() {
+ this.output_document = document;
+ this.output_node = null;
+ this.enabled = settings.output;
+ this.phase = this.INITIAL;
+ }
+
+ Output.prototype.INITIAL = 0;
+ Output.prototype.STARTED = 1;
+ Output.prototype.HAVE_RESULTS = 2;
+ Output.prototype.COMPLETE = 3;
+
+ Output.prototype.setup = function(properties) {
+ if (this.phase > this.INITIAL) {
+ return;
+ }
+
+ //If output is disabled in testharnessreport.js the test shouldn't be
+ //able to override that
+ this.enabled = this.enabled && (properties.hasOwnProperty("output") ?
+ properties.output : settings.output);
+ };
+
+ Output.prototype.init = function(properties) {
+ if (this.phase >= this.STARTED) {
+ return;
+ }
+ if (properties.output_document) {
+ this.output_document = properties.output_document;
+ } else {
+ this.output_document = document;
+ }
+ this.phase = this.STARTED;
+ };
+
+ Output.prototype.resolve_log = function() {
+ var output_document;
+ if (typeof this.output_document === "function") {
+ output_document = this.output_document.apply(undefined);
+ } else {
+ output_document = this.output_document;
+ }
+ if (!output_document) {
+ return;
+ }
+ var node = output_document.getElementById("log");
+ if (!node) {
+ if (!document.body || document.readyState == "loading") {
+ return;
+ }
+ node = output_document.createElement("div");
+ node.id = "log";
+ output_document.body.appendChild(node);
+ }
+ this.output_document = output_document;
+ this.output_node = node;
+ };
+
+ Output.prototype.show_status = function() {
+ if (this.phase < this.STARTED) {
+ this.init();
+ }
+ if (!this.enabled) {
+ return;
+ }
+ if (this.phase < this.HAVE_RESULTS) {
+ this.resolve_log();
+ this.phase = this.HAVE_RESULTS;
+ }
+ var done_count = tests.tests.length - tests.num_pending;
+ if (this.output_node) {
+ if (done_count < 100 ||
+ (done_count < 1000 && done_count % 100 === 0) ||
+ done_count % 1000 === 0) {
+ this.output_node.textContent = "Running, " +
+ done_count + " complete, " +
+ tests.num_pending + " remain";
+ }
+ }
+ };
+
+ Output.prototype.show_results = function (tests, harness_status) {
+ if (this.phase >= this.COMPLETE) {
+ return;
+ }
+ if (!this.enabled) {
+ return;
+ }
+ if (!this.output_node) {
+ this.resolve_log();
+ }
+ this.phase = this.COMPLETE;
+
+ var log = this.output_node;
+ if (!log) {
+ return;
+ }
+ var output_document = this.output_document;
+
+ while (log.lastChild) {
+ log.removeChild(log.lastChild);
+ }
+
+ var script_prefix = null;
+ var scripts = document.getElementsByTagName("script");
+ for (var i = 0; i < scripts.length; i++) {
+ var src;
+ if (scripts[i].src) {
+ src = scripts[i].src;
+ } else if (scripts[i].href) {
+ //SVG case
+ src = scripts[i].href.baseVal;
+ }
+
+ var matches = src && src.match(/^(.*\/|)testharness\.js$/);
+ if (matches) {
+ script_prefix = matches[1];
+ break;
+ }
+ }
+
+ if (script_prefix !== null) {
+ var stylesheet = output_document.createElementNS(xhtml_ns, "link");
+ stylesheet.setAttribute("rel", "stylesheet");
+ stylesheet.setAttribute("href", script_prefix + "testharness.css");
+ var heads = output_document.getElementsByTagName("head");
+ if (heads.length) {
+ heads[0].appendChild(stylesheet);
+ }
+ }
+
+ var status_text_harness = {};
+ status_text_harness[harness_status.OK] = "OK";
+ status_text_harness[harness_status.ERROR] = "Error";
+ status_text_harness[harness_status.TIMEOUT] = "Timeout";
+
+ var status_text = {};
+ status_text[Test.prototype.PASS] = "Pass";
+ status_text[Test.prototype.FAIL] = "Fail";
+ status_text[Test.prototype.TIMEOUT] = "Timeout";
+ status_text[Test.prototype.NOTRUN] = "Not Run";
+
+ var status_number = {};
+ forEach(tests,
+ function(test) {
+ var status = status_text[test.status];
+ if (status_number.hasOwnProperty(status)) {
+ status_number[status] += 1;
+ } else {
+ status_number[status] = 1;
+ }
+ });
+
+ function status_class(status)
+ {
+ return status.replace(/\s/g, '').toLowerCase();
+ }
+
+ var summary_template = ["section", {"id":"summary"},
+ ["h2", {}, "Summary"],
+ function()
+ {
+
+ var status = status_text_harness[harness_status.status];
+ var rv = [["section", {},
+ ["p", {},
+ "Harness status: ",
+ ["span", {"class":status_class(status)},
+ status
+ ],
+ ]
+ ]];
+
+ if (harness_status.status === harness_status.ERROR) {
+ rv[0].push(["pre", {}, harness_status.message]);
+ if (harness_status.stack) {
+ rv[0].push(["pre", {}, harness_status.stack]);
+ }
+ }
+ return rv;
+ },
+ ["p", {}, "Found ${num_tests} tests"],
+ function() {
+ var rv = [["div", {}]];
+ var i = 0;
+ while (status_text.hasOwnProperty(i)) {
+ if (status_number.hasOwnProperty(status_text[i])) {
+ var status = status_text[i];
+ rv[0].push(["div", {"class":status_class(status)},
+ ["label", {},
+ ["input", {type:"checkbox", checked:"checked"}],
+ status_number[status] + " " + status]]);
+ }
+ i++;
+ }
+ return rv;
+ },
+ ];
+
+ log.appendChild(render(summary_template, {num_tests:tests.length}, output_document));
+
+ forEach(output_document.querySelectorAll("section#summary label"),
+ function(element)
+ {
+ on_event(element, "click",
+ function(e)
+ {
+ if (output_document.getElementById("results") === null) {
+ e.preventDefault();
+ return;
+ }
+ var result_class = element.parentNode.getAttribute("class");
+ var style_element = output_document.querySelector("style#hide-" + result_class);
+ var input_element = element.querySelector("input");
+ if (!style_element && !input_element.checked) {
+ style_element = output_document.createElementNS(xhtml_ns, "style");
+ style_element.id = "hide-" + result_class;
+ style_element.textContent = "table#results > tbody > tr."+result_class+"{display:none}";
+ output_document.body.appendChild(style_element);
+ } else if (style_element && input_element.checked) {
+ style_element.parentNode.removeChild(style_element);
+ }
+ });
+ });
+
+ // This use of innerHTML plus manual escaping is not recommended in
+ // general, but is necessary here for performance. Using textContent
+ // on each individual <td> adds tens of seconds of execution time for
+ // large test suites (tens of thousands of tests).
+ function escape_html(s)
+ {
+ return s.replace(/\&/g, "&amp;")
+ .replace(/</g, "&lt;")
+ .replace(/"/g, "&quot;")
+ .replace(/'/g, "&#39;");
+ }
+
+ function has_assertions()
+ {
+ for (var i = 0; i < tests.length; i++) {
+ if (tests[i].properties.hasOwnProperty("assert")) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ function get_assertion(test)
+ {
+ if (test.properties.hasOwnProperty("assert")) {
+ if (Array.isArray(test.properties.assert)) {
+ return test.properties.assert.join(' ');
+ }
+ return test.properties.assert;
+ }
+ return '';
+ }
+
+ log.appendChild(document.createElementNS(xhtml_ns, "section"));
+ var assertions = has_assertions();
+ var html = "<h2>Details</h2><table id='results' " + (assertions ? "class='assertions'" : "" ) + ">" +
+ "<thead><tr><th>Result</th><th>Test Name</th>" +
+ (assertions ? "<th>Assertion</th>" : "") +
+ "<th>Message</th></tr></thead>" +
+ "<tbody>";
+ for (var i = 0; i < tests.length; i++) {
+ html += '<tr class="' +
+ escape_html(status_class(status_text[tests[i].status])) +
+ '"><td>' +
+ escape_html(status_text[tests[i].status]) +
+ "</td><td>" +
+ escape_html(tests[i].name) +
+ "</td><td>" +
+ (assertions ? escape_html(get_assertion(tests[i])) + "</td><td>" : "") +
+ escape_html(tests[i].message ? tests[i].message : " ") +
+ (tests[i].stack ? "<pre>" +
+ escape_html(tests[i].stack) +
+ "</pre>": "") +
+ "</td></tr>";
+ }
+ html += "</tbody></table>";
+ try {
+ log.lastChild.innerHTML = html;
+ } catch (e) {
+ log.appendChild(document.createElementNS(xhtml_ns, "p"))
+ .textContent = "Setting innerHTML for the log threw an exception.";
+ log.appendChild(document.createElementNS(xhtml_ns, "pre"))
+ .textContent = html;
+ }
+ };
+
+ /*
+ * Template code
+ *
+ * A template is just a javascript structure. An element is represented as:
+ *
+ * [tag_name, {attr_name:attr_value}, child1, child2]
+ *
+ * the children can either be strings (which act like text nodes), other templates or
+ * functions (see below)
+ *
+ * A text node is represented as
+ *
+ * ["{text}", value]
+ *
+ * String values have a simple substitution syntax; ${foo} represents a variable foo.
+ *
+ * It is possible to embed logic in templates by using a function in a place where a
+ * node would usually go. The function must either return part of a template or null.
+ *
+ * In cases where a set of nodes are required as output rather than a single node
+ * with children it is possible to just use a list
+ * [node1, node2, node3]
+ *
+ * Usage:
+ *
+ * render(template, substitutions) - take a template and an object mapping
+ * variable names to parameters and return either a DOM node or a list of DOM nodes
+ *
+ * substitute(template, substitutions) - take a template and variable mapping object,
+ * make the variable substitutions and return the substituted template
+ *
+ */
+
+ function is_single_node(template)
+ {
+ return typeof template[0] === "string";
+ }
+
+ function substitute(template, substitutions)
+ {
+ if (typeof template === "function") {
+ var replacement = template(substitutions);
+ if (!replacement) {
+ return null;
+ }
+
+ return substitute(replacement, substitutions);
+ }
+
+ if (is_single_node(template)) {
+ return substitute_single(template, substitutions);
+ }
+
+ return filter(map(template, function(x) {
+ return substitute(x, substitutions);
+ }), function(x) {return x !== null;});
+ }
+
+ function substitute_single(template, substitutions)
+ {
+ var substitution_re = /\$\{([^ }]*)\}/g;
+
+ function do_substitution(input) {
+ var components = input.split(substitution_re);
+ var rv = [];
+ for (var i = 0; i < components.length; i += 2) {
+ rv.push(components[i]);
+ if (components[i + 1]) {
+ rv.push(String(substitutions[components[i + 1]]));
+ }
+ }
+ return rv;
+ }
+
+ function substitute_attrs(attrs, rv)
+ {
+ rv[1] = {};
+ for (var name in template[1]) {
+ if (attrs.hasOwnProperty(name)) {
+ var new_name = do_substitution(name).join("");
+ var new_value = do_substitution(attrs[name]).join("");
+ rv[1][new_name] = new_value;
+ }
+ }
+ }
+
+ function substitute_children(children, rv)
+ {
+ for (var i = 0; i < children.length; i++) {
+ if (children[i] instanceof Object) {
+ var replacement = substitute(children[i], substitutions);
+ if (replacement !== null) {
+ if (is_single_node(replacement)) {
+ rv.push(replacement);
+ } else {
+ extend(rv, replacement);
+ }
+ }
+ } else {
+ extend(rv, do_substitution(String(children[i])));
+ }
+ }
+ return rv;
+ }
+
+ var rv = [];
+ rv.push(do_substitution(String(template[0])).join(""));
+
+ if (template[0] === "{text}") {
+ substitute_children(template.slice(1), rv);
+ } else {
+ substitute_attrs(template[1], rv);
+ substitute_children(template.slice(2), rv);
+ }
+
+ return rv;
+ }
+
+ function make_dom_single(template, doc)
+ {
+ var output_document = doc || document;
+ var element;
+ if (template[0] === "{text}") {
+ element = output_document.createTextNode("");
+ for (var i = 1; i < template.length; i++) {
+ element.data += template[i];
+ }
+ } else {
+ element = output_document.createElementNS(xhtml_ns, template[0]);
+ for (var name in template[1]) {
+ if (template[1].hasOwnProperty(name)) {
+ element.setAttribute(name, template[1][name]);
+ }
+ }
+ for (var i = 2; i < template.length; i++) {
+ if (template[i] instanceof Object) {
+ var sub_element = make_dom(template[i]);
+ element.appendChild(sub_element);
+ } else {
+ var text_node = output_document.createTextNode(template[i]);
+ element.appendChild(text_node);
+ }
+ }
+ }
+
+ return element;
+ }
+
+ function make_dom(template, substitutions, output_document)
+ {
+ if (is_single_node(template)) {
+ return make_dom_single(template, output_document);
+ }
+
+ return map(template, function(x) {
+ return make_dom_single(x, output_document);
+ });
+ }
+
+ function render(template, substitutions, output_document)
+ {
+ return make_dom(substitute(template, substitutions), output_document);
+ }
+
+ /*
+ * Utility funcions
+ */
+ function assert(expected_true, function_name, description, error, substitutions)
+ {
+ if (tests.tests.length === 0) {
+ tests.set_file_is_test();
+ }
+ if (expected_true !== true) {
+ var msg = make_message(function_name, description,
+ error, substitutions);
+ throw new AssertionError(msg);
+ }
+ }
+
+ function AssertionError(message)
+ {
+ this.message = message;
+ this.stack = this.get_stack();
+ }
+
+ AssertionError.prototype = Object.create(Error.prototype);
+
+ AssertionError.prototype.get_stack = function() {
+ var lines = new Error().stack.split("\n");
+ var rv = [];
+ var re = /\/resources\/testharness\.js/;
+ var i = 0;
+ // Fire remove any preamble that doesn't match the regexp
+ while (!re.test(lines[i])) {
+ i++
+ }
+ // Then remove top frames in testharness.js itself
+ while (re.test(lines[i])) {
+ i++
+ }
+ return lines.slice(i).join("\n");
+ }
+
+ function make_message(function_name, description, error, substitutions)
+ {
+ for (var p in substitutions) {
+ if (substitutions.hasOwnProperty(p)) {
+ substitutions[p] = format_value(substitutions[p]);
+ }
+ }
+ var node_form = substitute(["{text}", "${function_name}: ${description}" + error],
+ merge({function_name:function_name,
+ description:(description?description + " ":"")},
+ substitutions));
+ return node_form.slice(1).join("");
+ }
+
+ function filter(array, callable, thisObj) {
+ var rv = [];
+ for (var i = 0; i < array.length; i++) {
+ if (array.hasOwnProperty(i)) {
+ var pass = callable.call(thisObj, array[i], i, array);
+ if (pass) {
+ rv.push(array[i]);
+ }
+ }
+ }
+ return rv;
+ }
+
+ function map(array, callable, thisObj)
+ {
+ var rv = [];
+ rv.length = array.length;
+ for (var i = 0; i < array.length; i++) {
+ if (array.hasOwnProperty(i)) {
+ rv[i] = callable.call(thisObj, array[i], i, array);
+ }
+ }
+ return rv;
+ }
+
+ function extend(array, items)
+ {
+ Array.prototype.push.apply(array, items);
+ }
+
+ function forEach (array, callback, thisObj)
+ {
+ for (var i = 0; i < array.length; i++) {
+ if (array.hasOwnProperty(i)) {
+ callback.call(thisObj, array[i], i, array);
+ }
+ }
+ }
+
+ function merge(a,b)
+ {
+ var rv = {};
+ var p;
+ for (p in a) {
+ rv[p] = a[p];
+ }
+ for (p in b) {
+ rv[p] = b[p];
+ }
+ return rv;
+ }
+
+ function expose(object, name)
+ {
+ var components = name.split(".");
+ var target = test_environment.global_scope();
+ for (var i = 0; i < components.length - 1; i++) {
+ if (!(components[i] in target)) {
+ target[components[i]] = {};
+ }
+ target = target[components[i]];
+ }
+ target[components[components.length - 1]] = object;
+ }
+
+ function is_same_origin(w) {
+ try {
+ 'random_prop' in w;
+ return true;
+ } catch (e) {
+ return false;
+ }
+ }
+
+ function supports_post_message(w)
+ {
+ var supports;
+ var type;
+ // Given IE implements postMessage across nested iframes but not across
+ // windows or tabs, you can't infer cross-origin communication from the presence
+ // of postMessage on the current window object only.
+ //
+ // Touching the postMessage prop on a window can throw if the window is
+ // not from the same origin AND post message is not supported in that
+ // browser. So just doing an existence test here won't do, you also need
+ // to wrap it in a try..cacth block.
+ try {
+ type = typeof w.postMessage;
+ if (type === "function") {
+ supports = true;
+ }
+
+ // IE8 supports postMessage, but implements it as a host object which
+ // returns "object" as its `typeof`.
+ else if (type === "object") {
+ supports = true;
+ }
+
+ // This is the case where postMessage isn't supported AND accessing a
+ // window property across origins does NOT throw (e.g. old Safari browser).
+ else {
+ supports = false;
+ }
+ } catch (e) {
+ // This is the case where postMessage isn't supported AND accessing a
+ // window property across origins throws (e.g. old Firefox browser).
+ supports = false;
+ }
+ return supports;
+ }
+
+ /**
+ * Setup globals
+ */
+
+ var tests = new Tests();
+
+ addEventListener("error", function(e) {
+ if (tests.file_is_test) {
+ var test = tests.tests[0];
+ if (test.phase >= test.phases.HAS_RESULT) {
+ return;
+ }
+ test.set_status(test.FAIL, e.message, e.stack);
+ test.phase = test.phases.HAS_RESULT;
+ test.done();
+ done();
+ } else if (!tests.allow_uncaught_exception) {
+ tests.status.status = tests.status.ERROR;
+ tests.status.message = e.message;
+ tests.status.stack = e.stack;
+ }
+ });
+
+ test_environment.on_tests_ready();
+
+})();
+// vim: set expandtab shiftwidth=4 tabstop=4:
diff --git a/tests/wpt/web-platform-tests/resources/testharnessreport.js b/tests/wpt/web-platform-tests/resources/testharnessreport.js
new file mode 100644
index 00000000000..f27f25a58ba
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/testharnessreport.js
@@ -0,0 +1,21 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+var props = {output:%(output)d,
+ explicit_timeout: true};
+
+if (window.opener && "timeout_multiplier" in window.opener) {
+ props["timeout_multiplier"] = window.opener.timeout_multiplier;
+}
+
+if (window.opener && window.opener.explicit_timeout) {
+ props["explicit_timeout"] = window.opener.explicit_timeout;
+}
+
+setup(props);
+add_completion_callback(function() {
+ add_completion_callback(function(tests, status) {
+ window.opener.done(tests, status)
+ })
+});
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/.gitignore b/tests/wpt/web-platform-tests/resources/webidl2/.gitignore
new file mode 100644
index 00000000000..1d72980cd7e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/.gitignore
@@ -0,0 +1,4 @@
+scratch
+node_modules
+lib-cov
+browser-tests.html
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/.gitmodules b/tests/wpt/web-platform-tests/resources/webidl2/.gitmodules
new file mode 100644
index 00000000000..a3f5485cd33
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "test/widlproc"]
+ path = test/widlproc
+ url = https://github.com/dontcallmedom/widlproc.git
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/.travis.yml b/tests/wpt/web-platform-tests/resources/webidl2/.travis.yml
new file mode 100644
index 00000000000..6e5919de39a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/.travis.yml
@@ -0,0 +1,3 @@
+language: node_js
+node_js:
+ - "0.10"
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/README.md b/tests/wpt/web-platform-tests/resources/webidl2/README.md
new file mode 100644
index 00000000000..83aa27d71c7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/README.md
@@ -0,0 +1,725 @@
+
+# WebIDL 2
+
+[![NPM version](https://badge.fury.io/js/webidl2.png)](http://badge.fury.io/js/webidl2)
+
+Purpose
+=======
+
+This is a parser for the [WebIDL](http://dev.w3.org/2006/webapi/WebIDL/) language. If
+you don't know what that is, then you probably don't need it. It is meant to be used
+both in Node and in the browser (the parser likely works in other JS environments, but
+not the test suite).
+
+What of v1?
+-----------
+There was a previous incarnation of this project. I had written it in the most quick
+and dirty manner that was handy because I required it as a dependency in an experiment.
+As these things tend to happen, some people started using that, which then had to be
+maintained. But since it was not built on solid foundations, it was painful to keep
+up to date with the specification, which is a bit of a moving target.
+
+So I started from scratch. Compared to the previous version (which used a parser generator)
+this one is about 6x less code (which translates to 4x smaller minified or 2x smaller
+minizipped) and 4x faster. The test suite is reasonably complete (95% coverage), much more
+than previously. This version is up to date with WebIDL, rather than a couple years' behind.
+It also has *far* better error reporting.
+
+The AST you get from parsing is very similar to the one you got in v1, but some adjustments
+have been made in order to be more systematic, and to map better to what's actually in the spec
+now. If you used v1, you will need to tweak your code but the result ought to be simpler and
+you ought to be able to be a fair bit less defensive against irregularities in the way
+information is represented.
+
+Installation
+============
+
+Just the usual. For Node:
+
+ npm install webidl2
+
+In the browser:
+
+ <script src='webidl2.js'></script>
+
+Documentation
+=============
+
+The API to WebIDL2 is trivial: you parse a string of WebIDL and it returns a syntax tree.
+
+Parsing
+-------
+In Node, that happens with:
+
+ var WebIDL2 = require("webidl2");
+ var tree = WebIDL2.parse("string of WebIDL");
+
+In the browser:
+
+ <script src='webidl2.js'></script>
+ <script>
+ var tree = WebIDL2.parse("string of WebIDL");
+ </script>
+
+Errors
+------
+When there is a syntax error in the WebIDL, it throws an exception object with the following
+properties:
+
+* `message`: the error message
+* `line`: the line at which the error occurred.
+* `input`: a short peek at the text at the point where the error happened
+* `tokens`: the five tokens at the point of error, as understood by the tokeniser
+ (this is the same content as `input`, but seen from the tokeniser's point of view)
+
+The exception also has a `toString()` method that hopefully should produce a decent
+error message.
+
+AST (Abstract Syntax Tree)
+--------------------------
+The `parse()` method returns a tree object representing the parse tree of the IDL.
+Comment and white space are not represented in the AST.
+
+The root of this object is always an array of definitions (where definitions are
+any of interfaces, exceptions, callbacks, etc. — anything that can occur at the root
+of the IDL).
+
+### IDL Type
+
+This structure is used in many other places (operation return types, argument types, etc.).
+It captures a WebIDL type with a number of options. Types look like this and are typically
+attached to a field called `idlType`:
+
+ {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ }
+
+Where the fields are as follows:
+
+* `sequence`: Boolean indicating whether this is a sequence or not. Deprecated. Use
+ `generic` instead.
+* `generic`: String indicating the generic type (e.g. "Promise", "sequence"). `null`
+ otherwise.
+* `nullable`: Boolean indicating whether this is nullable or not.
+* `array`: Either `false` to indicate that it is not an array, or a number for the level of
+ array nesting.
+* `union`: Boolean indicating whether this is a union type or not.
+* `idlType`: Can be different things depending on context. In most cases, this will just
+ be a string with the type name. But the reason this field isn't called "typeName" is
+ because it can take more complex values. If the type is a union, then this contains an
+ array of the types it unites. If it is a generic type, it contains the IDL type
+ description for the type in the sequence, the eventual value of the promise, etc.
+
+#### Interactions between `nullable` and `array`
+
+A more complex data model for our AST would likely represent `Foo[][][]` as a series of
+nested types four levels deep with three anonymous array types eventually containing a
+`Foo` type. But experience shows that such structures are cumbersome to use, and so we
+have a simpler model in which the depth of the array is specified with the `array` field.
+
+This is all fine and well, and in the vast majority of cases is actually simpler. But it
+does run afoul of cases in which it is necessary to distinguish between `Foo[][][]?`,
+`Foo?[][][]`, `Foo[][]?[]`, or even `Foo?[]?[]?[]?`.
+
+For this, when a type is an array type an additional `nullableArray` field is made available
+that captures which of the arrays contain nullable elements. It contains booleans that are
+true if the given array depth contains nullable elements, and false otherwise (mapping that to
+the syntax, and item is true if there is a `?` preceding the `[]`). These examples ought to
+clarify the model:
+
+ Foo[][][]?
+ -> nullable: true
+ -> nullableArray: [false, false, false]
+ Foo?[][][]
+ -> nullable: false
+ -> nullableArray: [true, false, false]
+ Foo[][]?[]
+ -> nullable: false
+ -> nullableArray: [false, false, true]
+ Foo?[]?[]?[]?
+ -> nullable: true
+ -> nullableArray: [true, true, true]
+
+Of particular importance, please note that the overall type is only `nullable` if there is
+a `?` at the end.
+
+### Interface
+Interfaces look like this:
+
+ {
+ "type": "interface",
+ "name": "Animal",
+ "partial": false,
+ "members": [...],
+ "inheritance": null,
+ "extAttrs": [...]
+ },
+ {
+ "type": "interface",
+ "name": "Human",
+ "partial": false,
+ "members": [...],
+ "inheritance": "Animal",
+ "extAttrs": [...]
+ }
+
+The fields are as follows:
+
+* `type`: Always "interface".
+* `name`: The name of the interface
+* `partial`: A boolean indicating whether it's a partial interface.
+* `members`: An array of interface members (attributes, operations, etc.). Empty if there are none.
+* `inheritance`: A string giving the name of an interface this one inherits from, `null` otherwise.
+ **NOTE**: In v1 this was an array, but multiple inheritance is no longer supported so this didn't make
+ sense.
+* `extAttrs`: A list of [extended attributes](#extended-attributes).
+
+### Callback Interfaces
+
+These are captured by the same structure as [Interfaces](#interface) except that
+their `type` field is "callback interface".
+
+### Callback
+
+A callback looks like this:
+
+ {
+ "type": "callback",
+ "name": "AsyncOperationCallback",
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "arguments": [...],
+ "extAttrs": []
+ }
+
+The fields are as follows:
+
+* `type`: Always "callback".
+* `name`: The name of the callback.
+* `idlType`: An [IDL Type](#idl-type) describing what the callback returns.
+* `arguments`: A list of [arguments](#arguments), as in function paramters.
+* `extAttrs`: A list of [extended attributes](#extended-attributes).
+
+### Dictionary
+
+A dictionary looks like this:
+
+ {
+ "type": "dictionary",
+ "name": "PaintOptions",
+ "partial": false,
+ "members": [
+ {
+ "type": "field",
+ "name": "fillPattern",
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": true,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "extAttrs": [],
+ "default": {
+ "type": "string",
+ "value": "black"
+ }
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+
+The fields are as follows:
+
+* `type`: Always "dictionary".
+* `name`: The dictionary name.
+* `partial`: Boolean indicating whether it's a partial dictionary.
+* `members`: An array of members (see below).
+* `inheritance`: A string indicating which dictionary is being inherited from, `null` otherwise.
+* `extAttrs`: A list of [extended attributes](#extended-attributes).
+
+All the members are fields as follows:
+
+* `type`: Always "field".
+* `name`: The name of the field.
+* `idlType`: An [IDL Type](#idl-type) describing what field's type.
+* `extAttrs`: A list of [extended attributes](#extended-attributes).
+* `default`: A [default value](#default-and-const-values), absent if there is none.
+
+### Exception
+
+An exception looks like this:
+
+ {
+ "type": "exception",
+ "name": "HierarchyRequestError",
+ "members": [
+ {
+ "type": "field",
+ "name": "code",
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned short"
+ },
+ "extAttrs": []
+ }
+ ],
+ "inheritance": "DOMException",
+ "extAttrs": []
+ }
+
+The fields are as follows:
+
+* `type`: Always "exception".
+* `name`: The exception name.
+* `members`: An array of members (constants or fields, where fields are described below).
+* `inheritance`: A string indicating which exception is being inherited from, `null` otherwise.
+* `extAttrs`: A list of [extended attributes](#extended-attributes).
+
+Members that aren't [constants](#constants) have the following fields:
+
+* `type`: Always "field".
+* `name`: The field's name.
+* `idlType`: An [IDL Type](#idl-type) describing what field's type.
+* `extAttrs`: A list of [extended attributes](#extended-attributes).
+
+### Enum
+
+An enum looks like this:
+
+ {
+ "type": "enum",
+ "name": "MealType",
+ "values": [
+ "rice",
+ "noodles",
+ "other"
+ ],
+ "extAttrs": []
+ }
+
+The fields are as follows:
+
+* `type`: Always "enum".
+* `name`: The enum's name.
+* `value`: An array of values (strings).
+* `extAttrs`: A list of [extended attributes](#extended-attributes).
+
+### Typedef
+
+A typedef looks like this:
+
+ {
+ "type": "typedef",
+ "typeExtAttrs": [],
+ "idlType": {
+ "sequence": true,
+ "generic": "sequence",
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Point"
+ }
+ },
+ "name": "PointSequence",
+ "extAttrs": []
+ }
+
+The fields are as follows:
+
+* `type`: Always "typedef".
+* `name`: The typedef's name.
+* `idlType`: An [IDL Type](#idl-type) describing what typedef's type.
+* `extAttrs`: A list of [extended attributes](#extended-attributes).
+* `typeExtAttrs`: A list of [extended attributes](#extended-attributes) that apply to the
+type rather than to the typedef as a whole.
+
+### Implements
+
+An implements definition looks like this:
+
+ {
+ "type": "implements",
+ "target": "Node",
+ "implements": "EventTarget",
+ "extAttrs": []
+ }
+
+The fields are as follows:
+
+* `type`: Always "implements".
+* `target`: The interface that implements another.
+* `implements`: The interface that is being implemented by the target.
+* `extAttrs`: A list of [extended attributes](#extended-attributes).
+
+### Operation Member
+
+An operation looks like this:
+
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "intersection",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": true,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "long"
+ },
+ "name": "ints"
+ }
+ ],
+ "extAttrs": []
+ }
+
+The fields are as follows:
+
+* `type`: Always "operation".
+* `getter`: True if a getter operation.
+* `setter`: True if a setter operation.
+* `creator`: True if a creator operation.
+* `deleter`: True if a deleter operation.
+* `legacycaller`: True if a legacycaller operation.
+* `static`: True if a static operation.
+* `stringifier`: True if a stringifier operation.
+* `idlType`: An [IDL Type](#idl-type) of what the operation returns. If a stringifier, may be absent.
+* `name`: The name of the operation. If a stringifier, may be `null`.
+* `arguments`: An array of [arguments](#arguments) for the operation.
+* `extAttrs`: A list of [extended attributes](#extended-attributes).
+
+### Attribute Member
+
+An attribute member looks like this:
+
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "RegExp"
+ },
+ "name": "regexp",
+ "extAttrs": []
+ }
+
+The fields are as follows:
+
+* `type`: Always "attribute".
+* `name`: The attribute's name.
+* `static`: True if it's a static attribute.
+* `stringifier`: True if it's a stringifier attribute.
+* `inherit`: True if it's an inherit attribute.
+* `readonly`: True if it's a read-only attribute.
+* `idlType`: An [IDL Type](#idl-type) for the attribute.
+* `extAttrs`: A list of [extended attributes](#extended-attributes).
+
+### Constant Member
+
+A constant member looks like this:
+
+ {
+ "type": "const",
+ "nullable": false,
+ "idlType": "boolean",
+ "name": "DEBUG",
+ "value": {
+ "type": "boolean",
+ "value": false
+ },
+ "extAttrs": []
+ }
+
+The fields are as follows:
+
+* `type`: Always "const".
+* `nullable`: Whether its type is nullable.
+* `idlType`: The type of the constant (a simple type, the type name).
+* `name`: The name of the constant.
+* `value`: The constant value as described by [Const Values](#default-and-const-values)
+* `extAttrs`: A list of [extended attributes](#extended-attributes).
+
+### Serializer Member
+
+Serializers come in many shapes, which are best understood by looking at the
+examples below that map the IDL to the produced AST.
+
+ // serializer;
+ {
+ "type": "serializer",
+ "extAttrs": []
+ }
+
+ // serializer DOMString serialize();
+ {
+ "type": "serializer",
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "operation": {
+ "name": "serialize",
+ "arguments": []
+ },
+ "extAttrs": []
+ }
+
+ // serializer = { from, to, amount, description };
+ {
+ "type": "serializer",
+ "patternMap": true,
+ "names": [
+ "from",
+ "to",
+ "amount",
+ "description"
+ ],
+ "extAttrs": []
+ }
+
+ // serializer = number;
+ {
+ "type": "serializer",
+ "name": "number",
+ "extAttrs": []
+ }
+
+ // serializer = [ name, number ];
+ {
+ "type": "serializer",
+ "patternList": true,
+ "names": [
+ "name",
+ "number"
+ ],
+ "extAttrs": []
+ }
+
+The common fields are as follows:
+
+* `type`: Always "serializer".
+* `extAttrs`: A list of [extended attributes](#extended-attributes).
+
+For a simple serializer, that's all there is. If the serializer is an operation, it will
+have:
+
+* `idlType`: An [IDL Type](#idl-type) describing what the serializer returns.
+* `operation`: An object with the following fields:
+ * `name`: The name of the operation.
+ * `arguments`: An array of [arguments](#arguments) for the operation.
+
+If the serializer is a pattern map:
+
+* `patternMap`: Always true.
+* `names`: An array of names in the pattern map.
+
+If the serializer is a pattern list:
+
+* `patternList`: Always true.
+* `names`: An array of names in the pattern list.
+
+Finally, if the serializer is a named serializer:
+
+* `name`: The serializer's name.
+
+### Iterator Member
+
+Iterator members look like this
+
+ {
+ "type": "iterator",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Session2"
+ },
+ "iteratorObject": "SessionIterator",
+ "extAttrs": []
+ }
+
+* `type`: Always "iterator".
+* `iteratorObject`: The string on the right-hand side; absent if there isn't one.
+* the rest: same as on [operations](#operation-member).
+
+### Arguments
+
+The arguments (e.g. for an operation) look like this:
+
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": true,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "long"
+ },
+ "name": "ints"
+ }
+ ]
+
+The fields are as follows:
+
+* `optional`: True if the argument is optional.
+* `variadic`: True if the argument is variadic.
+* `idlType`: An [IDL Type](#idl-type) describing the type of the argument.
+* `name`: The argument's name.
+* `extAttrs`: A list of [extended attributes](#extended-attributes).
+
+### Extended Attributes
+
+Extended attributes are arrays of items that look like this:
+
+ "extAttrs": [
+ {
+ "name": "TreatNullAs",
+ "arguments": null,
+ "rhs": {
+ "type": "identifier",
+ "value": "EmptyString"
+ }
+ }
+ ]
+
+The fields are as follows:
+
+* `name`: The extended attribute's name.
+* `arguments`: If the extended attribute takes arguments (e.g. `[Foo()]`) or if
+ its right-hand side does (e.g. `[NamedConstructor=Name(DOMString blah)]`) they
+ are listed here. Note that an empty arguments list will produce an empty array,
+ whereas the lack thereof will yield a `null`. If there is an `rhs` field then
+ they are the right-hand side's arguments, otherwise they apply to the extended
+ attribute directly.
+* `rhs`: If there is a right-hand side, this will capture its `type` (always
+ "identifier" in practice, though it may be extended in the future) and its
+ `value`.
+* `typePair`: If the extended attribute is a `MapClass` this will capture the
+ map's key type and value type respectively.
+
+### Default and Const Values
+
+Dictionary fields and operation arguments can take default values, and constants take
+values, all of which have the following fields:
+
+* `type`: One of string, number, boolean, null, Infinity, or NaN.
+
+For string, number, and boolean:
+
+* `value`: The value of the given type.
+
+For Infinity:
+
+* `negative`: Boolean indicating whether this is negative Infinity or not.
+
+
+Testing
+=======
+
+In order to run the tests you need to ensure that the widlproc submodule inside `test` is
+initialised and up to date:
+
+ git submodule init
+ git submodule update
+
+Running
+-------
+The test runs with mocha and expect.js. Normally, running mocha in the root directory
+should be enough once you're set up.
+
+Coverage
+--------
+Current test coverage, as documented in `coverage.html`, is 95%. You can run your own
+coverage analysis with:
+
+ jscoverage lib lib-cov
+
+That will create the lib-cov directory with instrumented code; the test suite knows
+to use that if needed. You can then run the tests with:
+
+ JSCOV=1 mocha --reporter html-cov > coverage.html
+
+Note that I've been getting weirdly overescaped results from the html-cov reporter,
+so you might wish to try this instead:
+
+ JSCOV=1 mocha --reporter html-cov | sed "s/&lt;/</g" | sed "s/&gt;/>/g" | sed "s/&quot;/\"/g" > coverage.html
+
+Browser tests
+-------------
+In order to test in the browser, get inside `test/web` and run `make-web-tests.js`. This
+will generate a `browser-tests.html` file that you can open in a browser. As of this
+writing tests pass in the latest Firefox, Chrome, Opera, and Safari. Testing on IE
+and older versions will happen progressively.
+
+TODO
+====
+
+* add some tests to address coverage limitations
+* add a push API for processors that need to process things like comments
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/coverage.html b/tests/wpt/web-platform-tests/resources/webidl2/coverage.html
new file mode 100644
index 00000000000..46e7ed324ec
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/coverage.html
@@ -0,0 +1,341 @@
+<!DOCTYPE html><html><head><title>Coverage</title><script>
+
+headings = [];
+
+onload = function(){
+ headings = document.querySelectorAll('h2');
+};
+
+onscroll = function(e){
+ var heading = find(window.scrollY);
+ if (!heading) return;
+ var links = document.querySelectorAll('#menu a')
+ , link;
+
+ for (var i = 0, len = links.length; i < len; ++i) {
+ link = links[i];
+ link.className = link.getAttribute('href') == '#' + heading.id
+ ? 'active'
+ : '';
+ }
+};
+
+function find(y) {
+ var i = headings.length
+ , heading;
+
+ while (i--) {
+ heading = headings[i];
+ if (y >= heading.offsetTop) {
+ return heading;
+ }
+ }
+}
+</script>
+<style>
+
+body {
+ font: 14px/1.6 "Helvetica Neue", Helvetica, Arial, sans-serif;
+ margin: 0;
+ color: #2C2C2C;
+ border-top: 2px solid #ddd;
+}
+
+#coverage {
+ padding: 60px;
+}
+
+h1 a {
+ color: inherit;
+ font-weight: inherit;
+}
+
+h1 a:hover {
+ text-decoration: none;
+}
+
+.onload h1 {
+ opacity: 1;
+}
+
+h2 {
+ width: 80%;
+ margin-top: 80px;
+ margin-bottom: 0;
+ font-weight: 100;
+ letter-spacing: 1px;
+ border-bottom: 1px solid #eee;
+}
+
+a {
+ color: #8A6343;
+ font-weight: bold;
+ text-decoration: none;
+}
+
+a:hover {
+ text-decoration: underline;
+}
+
+ul {
+ margin-top: 20px;
+ padding: 0 15px;
+ width: 100%;
+}
+
+ul li {
+ float: left;
+ width: 40%;
+ margin-top: 5px;
+ margin-right: 60px;
+ list-style: none;
+ border-bottom: 1px solid #eee;
+ padding: 5px 0;
+ font-size: 12px;
+}
+
+ul::after {
+ content: '.';
+ height: 0;
+ display: block;
+ visibility: hidden;
+ clear: both;
+}
+
+code {
+ font: 12px monaco, monospace;
+}
+
+pre {
+ margin: 30px;
+ padding: 30px;
+ border: 1px solid #eee;
+ border-bottom-color: #ddd;
+ -webkit-border-radius: 2px;
+ -moz-border-radius: 2px;
+ -webkit-box-shadow: inset 0 0 10px #eee;
+ -moz-box-shadow: inset 0 0 10px #eee;
+ overflow-x: auto;
+}
+
+img {
+ margin: 30px;
+ padding: 1px;
+ -webkit-border-radius: 3px;
+ -moz-border-radius: 3px;
+ -webkit-box-shadow: 0 3px 10px #dedede, 0 1px 5px #888;
+ -moz-box-shadow: 0 3px 10px #dedede, 0 1px 5px #888;
+ max-width: 100%;
+}
+
+footer {
+ background: #eee;
+ width: 100%;
+ padding: 50px 0;
+ text-align: right;
+ border-top: 1px solid #ddd;
+}
+
+footer span {
+ display: block;
+ margin-right: 30px;
+ color: #888;
+ font-size: 12px;
+}
+
+#menu {
+ position: fixed;
+ font-size: 12px;
+ overflow-y: auto;
+ top: 0;
+ right: 0;
+ margin: 0;
+ height: 100%;
+ padding: 15px 0;
+ text-align: right;
+ border-left: 1px solid #eee;
+ -moz-box-shadow: 0 0 2px #888
+ , inset 5px 0 20px rgba(0,0,0,.5)
+ , inset 5px 0 3px rgba(0,0,0,.3);
+ -webkit-box-shadow: 0 0 2px #888
+ , inset 5px 0 20px rgba(0,0,0,.5)
+ , inset 5px 0 3px rgba(0,0,0,.3);
+ -webkit-font-smoothing: antialiased;
+ background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGYAAABmCAMAAAAOARRQAAABelBMVEUjJSU6OzshIyM5OjoqKy02NjgsLS01NTYjJCUzNTUgISMlJSc0NTUvMDA6PDwlJyg1NjYoKis2NjYrLS02ODkpKyw0NDYrLC04ODovLzA4Ojo0NDUtLy86OjwjIyU4OTosLS82ODgtLS8hIyQvMTEnKCooKSsrKy0qLCwkJSUnKCkrLCwpKiwwMjIxMzMqLC0tLS0pKissLC00NTYwMDIwMTQpKysoKSovMDEtLzA2OTkxMzUrKywvLy8qKyszNTY5OzsqKiw6OjswMDExNDUoKiozNDUvMDIyNDY1Njg2Njk5OTozMzU0NjY4ODkiIyUiIyQ4OTkuMDEmKCowMjQwMTErLS4qKywwMTMhIiMpKiopKy0tLjAkJScxNDQvLzExNDYyNDQmKCk5OTslJig5OjskJSYxMzQrLS8gISIwMTIoKCk1NTUlJSUnJygwMDA4ODgiIiMhISI8PDw6Ojo5OTkpKSojIyQ7OzsyMjIpKSssLCw6Ozw1NjlrfLakAAAg2UlEQVR42jR6i3ea6rYvPgANIAhVXh8WvkQlioUiFlFcBtAmoiRNdzxqu9p0J7vrdK29zuPeex77nnvO/35n1r1ndHRktI0jTOacv/l7lCBK5UqVpOha/YxmWK7BC4TQFKVXrbYsnimqxuuMVlOQ0XltWjUdCwRJ1M+tC1KudOs9q6+da2adUewG0SC0SwELfHtgDds93VEuydEbl3QMWeNoYkR7b/0x1ZRobGI3mLwzAhePqTAwhg6aogjNsGy7/jwQ4rkdqe7CWLxF8k9LfMVFyRS7VJqtkrW8Vt/bkR8FZJao16ipknbC3Yw2lM7laO6HBEOadEZ2tpf65c4v8e3u7FyU6qbiNNyCuzXZ6pawgnwgmrpTT/Q7w2EZmiIJ0dzWDI7mhQ80IfRnMu2kzA5r5r1pIFoia+/d93HRYp1GV8TbrkWoU/+jdI0Ff6yGwTjT1Hn8J+8m1rKpGiYPuNiHnMtNMIv+zpsk84MYTNW1/+DpwXLvckdOCMYowVNPREe0QlM8xRHXXFhcNDzupwsSmb5pH+0t0RP2Qk+QtI7F1Qm6JRC6ZPBtPq/dq/kH+jxtCljn9TIpW6rQIgmSVyj6lPICIw4N/taka41PFUInth0je9+jO6Kt1G4/a7V2LEgG02B0pHVuCZrgltSKMuIl5SyufUv9mYuQi+mFgzbBEtFo2g+Dh4sSTrLNu8JPh00sQydpb00tqXBvqRN7Q7kqzcnIxCGnvZt/WmJacoOEO6Dcn8Qre03pOCSQxbMOXUuDNx9SxuLz4W1I18gvjViQ67zV0rxdWL8Te/TQkuo8STS41DR48W7L6YP2uWIqiUV8rd6Gbf/rnegKZeG8TpAM6afhGze9JAOxbLjsnUXEbrZ9vLYd7MT32cPF5mKKxmjy7huaoD9n62GOxni3iIJwv0IzZAZjdZkUtolCNLVfYZNaquFjGszVVf+J0vrz4CawoKdHnOzb0NMH7CDBOybfYNJ4rfeMyFNjkFYVTzMFs87rnPGXLUOeNKRVc0LnU7/UIgelzsy3CMuth0YfvnY0wsD3vODUL3eJcKqHQpm8yM3XZQWJxO6Un9iYloyyLpOwN2obHy6W6gbpcb44XmyC+mg+itAcaprGcrwZCqMj/GmtKn0zPvpTz/Cv1dw21XwP3cRupg3H3MF/S71eTKj1YrdwKdc2Mw0fRmb2sFf8lW3aU6JbIZSEPqvXvjM7G/aApyXlXeqKfMq0g/Su3rUGJPSPrtGElgknrZM3xUXqsAP6zMCNVn5u8aJnSNpJv2uru7t2jfRziW2+GuhqfldUNbPk71olwo+46ePUo1U3WKk/e5YK07F/wGRgcpODmQnIlVeHCWBE4puBi2jq28UKpqiN1/4UOrGz59TNYrrQHtd+11sG40BGD+pXdelNqGOg4NXe8W4eacJV/NS9/2Umtym6WQqveqR9xdCMElpxnbkalM4Vf9uaEcWZaKdyibEIjWKxJZPN95niCL3GiaXyssIrHxoLkqkzLCXULN46/f2h3tQJgyip+Tk9EAjJ9aJshq7t8X45aowSKspMSvPf7r9R8yxNptIaHS5ozuEm6luPDApugyNP8OaqiQ4BjaequXA54SLC83eHIY2r+CZp4409Xqw8Aa2oI7XkCrQi+in0w5AqF/kLNrcUz+qkl/lAobY1jSnx5OJNhyXIz3qfNFlXc0TKaglNwdWkWYt9QQ1Kr6W8zue21iNrdJk+N5oCr2O9nEtWKC7IS5J/zdDEYrmnAYfg6agCy+qcgz7ZofeDc4PbUWSvkshWuAc7OjiUyLkj+RAtdlwXJcjxdpkTTHDhK8lBCi8+JtvDVL1W6elmOM++YS0LuSlaP1oUvAeiW3cFnvTr8EbTz1tsSMYdGeZe40sRWu5uAfj7q+ZoKv2FNQ0p5XY1lmlcigHZqTPpabufEVrNuNPi165w3uCVQJHyJqmSJ7ZHnguqwtCmwViIJijj04ba2JNYtB+yORf5gg1/9t9iw4vUpeqiunSAbf+IBdj/b+iG2qrHvuNP0Vd/+ThVZT/lrvHYjjgDbbyxaqgHNM2uhxa1GW3UedZYhMMwM4mQhltouK+IV4NdbIQNM+8Yv311RZk9kT4tiYR4LkyFcuPpdcjuhUuFqBAWRZa11lcZ3gEBlXywsNhrt+plISZP5DlsV9l4EgY6J3yZPTUcMrgaWAT3oI79eSbGEbcJpr6BD8kyDiVt+G0/hXosQN4NFXKlfWIfsIs0BHODVok1/IGnKFHJYIquh8Xo+2+bkQNTGgWmN/fZ0Y33LSj6lr1GyV7mWIKg7ZTRZPGuhF/zjRNcQ1UPtSYgnWQxSs0yrVhwNDcdGMNSNe2JT3WuzbAM3HykyAajS3Uphf6STKEqxLas9EnmnhA/lyj9Uj+JoY7SVgVmGLl46Rm2u98sbkap2lzAdKBG4r6LgulQOSSjQv1GWdQ0jtDUK/mAaqM1Uqjpu4k3Rvfvxv7YTxLSK+wN3E5jVIzmF23uZ7hiH/sVP49D7tvoKp4S8b1LuvRlivVB/algbhcFITYVXvDpLzpDfplR2uD5V4XJFxpjmIpLc9Y5sB2TpBRix7Bme6GZIq+06v3XzNeTcA4obQIKxrnT4C2JpOqD92dbmSX8MGazly5EsZVMvSU1f4RZwyu8iQXbVdeLlZrjuTT1jrY1uk5c7iZ7RsvhhluqAkq4JpVQAg7RJFtSu+xgJ8Pv6O1j5DkLxT8mkbfyRW5DrQmG7hiDIjCgBsADbjuof6YHLGeV6a5Q1Smx9joUXPpdaaDx97A/Wq00oJkdR7ZYuQRfS533JtxO1erduqWOYIt3wh0wpbLuCNIYkwxbswbikCUu2CDCS+Q+7rgVtfRcm+SOcdKPRlZ/rE7wNVUEE39KTS5uvUKN1PUnkloPkyzhyGQ8qkouEjJ3H/VXdqG6asSRiw3ecMlBvDDt8dDhBHXMwZ2Cajzjr7/76T+IavqPYvz6r7//E/3X3+N//h/0QozbjPgPiir69P/8X3/9F/yv8b/827/++98WItPu5/Hvwd8YPf5bp/2/lX/T/+Of/0MJ/lYTa+L/Ef+d9vN/3/2T6P/+jyTzu/evf6U7vxN7B6pJkRtAF6jUr8I+P8RsP/ptGhfqFk+pQ/DgAy6NJtRYJdXmp4gK7WLqLKJ+MaKhGjOojvL+SnIWrkpy0SLHDe4QuyNzaEA15mLMCcmE8Em+4HdOihW4/ZWuppJEmzeAwcDtv7MuLc9y2V5atvxXNe3S4DUMt5/Qy2LM9kSYKiVWBuKlfp4nxTntpuW03JbIlkiRvBXmT23g1I2OYe6IizUHPIq6zm6mbfsbteKmi/sg9J+ocQBMctGFO7iljo8TPN+z3jxw4do+ZwfqoR9dkNTKHyM305GpTkfhcHexVkPVGEbUOjuo9f0UMPHBFlGEx0SLvJvVRKTwW7PSew5oPme+E42+frJa9cGt2njS3dK5kIif2eYbhuSEQXEqMVfUjhGIuin0G0/W5ezJyJQy3SpMLai4M0JUWb5u1k9tny5bd1pPwYBpQuDCXZl62xg4CdVEAtflXHs6JKmP/pH6mOl796Lgopj0o8d5kKh00hxG3OSdEE/QBo9Hgr8JJqAeLDwJohG5j/DGh61Rc/+tf22/8kEnxHNCEjo0ElvvGfESZkqmz2BDcKV1H1buSkhkdg7p1IMGs2s17nYjpblrWuE2K9WEO/hcRp5e9oOF/QBmOaDtgil+oaU6szPrdwW65fOB0KUTsVUn7LFU7J8e6cxJIl9+FHw5MQMzuQJ+4oxMH3iW/5GK+hWuG0T+gTLs+fAjdtUd58TmIUq04EeyRCYCjkldow234aIgR5bqwrtZosZ+6YEqAmDqatJ9lWasz4IquKALPtd92hGI3Z2BdzzZue+REl1Om4DIWD+RrtUTOJLI+S0jHowXXdAxsGLSd40zYNuEUlOGhrwL6c7tcOtUOvpJCP7QBQS19H+GvZn05ewjlVLz+IGKoC9TyfQjLMBNmXCuqqtTdOSukZW48B0HqgSTCBrBnlFvF4CG2Su7yFzqmJFURK3UmTT3ru050r0ptUpMilYnBJWfl2Bv6kPlUuE1kxxpdzui9AubsR2N2boVSu81OulAwBqoSr1LZ0LLYOomyZHmjqnXlP72s8LnDouEJjtodBvdHaG1jMySYO7crWd90MpCRyCG14vb5IE7Arupw/y/RcCm/Tm3zK6zYj8PYNaGldiUfkB/LHWcmf2lVM+mwyU27a0qq2tscrQ/vzBjN26DnntIrOyGizzXK35yKQdYnUABkyN4saz3WD/viF+eCcsXnIajdWYJWaYHRstIis9CS+tqnFGmz2j5uzfr3Z4prqgK4XOT/PyftvjZqIm8lhkfxJ7Ol3CJF1piYBGAG8wtAk56Drw1YwmOpcz+NdfkSpSLplRXLXHL0Rquj6YW/gabqgK7Dgr6NwtH0B/AN7XrN+MVJ6AmXmUuqmQulrNNYPmH0RoDogydOKLo/QbfYNARSQQKISRCzRXU+q9WWJFL3LZW6u34CkeG97xC0NNGaJ0bvK6SnZS3zPskr5EtuCgjMWR5o2x5BqhKmDWJPRe7JMEOyRb5uUKlHaGVtq5ivSOaSliSXp9SQm2qk8MRJh10MAp9QQ2H5t59J8rjiwSZtoIfMGjlLPVNdYl/LBR0AO6WLGDmkLkIPRE45Y9MftdAK/yNu1Hn6tzOQTesgQ+8fSzB19wO91vCnO23vOWQdwJ63SJrYjdfKFW6W281PKs2k8iT9ai1cgJ4sa3xqdvmtxR8/+D1B8AKc2u+6JftryRhMWSQtoSBgIyyQGyxcnELuAasXN12oSriU4RMz1DD6RL0TSV+om7i1Yt+jEE/jnawM8cX/UhN4nkiv/w9eALrzNhXuQfOzFL0Fi6SjF7/4Qn8rLYBoa85cvgAnkCEBP+HPbEnquVXCZsMS/yzYw2Vru60P/+nJPYKkzZFjmbykzUoEqV836T5q3fP/L383dF82tx18/AZgZczMAgyeWYKmSZIqtHL+e+O4ZRcq9VI3g/qPeCoiK4pcgEqdbS0S/Be54sbVQOuJVPNBblIghzeasNu7h/g+Sz1IdhI5lCwq1nUb3Ji4OCIcqQZqtqJ5w7rXrg/DA9IgVmEGhDgGecEwnCTHffXcXs0V3OCEVzYDKS1vp/oX+ng+6XVU86UjA6FMO2RXOOOrqY1GgPvrAk9HV/BXtCu5RuwF8qgdGDLsBcui4E33ymdBip1X8uKyhIWT8qNRDsXz+gvO9UiEC0d8RG4Tf2x8H4slljgHtCBcxHLTWOYJm5H/fCPCzOgf9qgOUxTRZ0Pc6ha5yLuLVT9ntvIa6gacE99mCovdUumTQdRP4RPsS9129eEe2uSvvGh0bV4Y3QPPhPZMqhZWSMa5R0Hc1SGO4IVOQc0FrirlibTVfKRrYkD8kz3b+X65/QkUNaZdrdl3mCap0Hf3YcCw/LiouJYNbqz88UqeDYv93yO7vvXtgl4XCyAO4ODkY6W+83+LZU//p3/zXNGGrUKClCiOnL27iJZbNWDF02XXAOeFlB7IaADoMH1Yqr+UP9biyZDEa/iJt4MDeIz6GKTdLVBfWGVtRN4fdT2rgReX8UXwF2zOrradm4J0nyTgdPnai3RvzpZvCKDUqjOwD/QA6EDaMCLewX6QWYVnHY1sx1bd8ovYnPm1ZvPH+rE20lWjOCnZ66/xDt0QAl15FjfBcZp+i9OU0RNPQ0t3x2pSNWo8eiYudwsnuP1Hq6iH1LJCJynkYsfgJ0p3pF6SoQk2l+jqE8CPk+ziGJRSKjs+W5AO185umPdkYzlK4wl7TC9NxyyDP7ZoyYVoXiuS6SjnInlLWrwz1i8bGTKXX0AVQWkSfIlglW3zRJRJ8bg5VgE6ZEnqNu9B++0GNQvDQJvFize4ESNKBJP+8vA3LM4AX5SIBq08Mob+7QMTCZx4nwP/64+4BnlZC+8WtlP/CXw6t1PwMwkJ3jhP1FiXLhDF/3I6FGUzO2DSi9ABxKyyL9paZxSEz40ZCPQToDAJu1959k7QdbVxgB4icsu2s4zsTPJhcEDo+N1GX4zSk/wriRh8AqwL62972i9HJHd1ydaLXVzvKvOfGGw5RVcUVMiKXFH4APdkQU/dc5BX0YfKTNZYXCW9mb8bc8mufoQP6BbdQmT99ZjoYfr/go4TgQX9IDgztim7wyFeGMfbNaeqj8Dzs38pgcqwSv2hbqB3oSGKWKy+sesY7p57wAHldqE6NDudk/W7s/zjrK4rZFlFvaGxnSZdHbc1y47qDN6xkoK8O3bfr2j41dlJZ71rB4dlDqapPFa8N6xBrprUdtenUCHwxKNhw1uuTBh+9uU45k4REpQABN2bAO9DSLqoIL26gNroWgup5pUMxHUNSq4Gyz47vBPvilpo5f9OYI2ddAqTqmnxXERxQJ3UK8fHbVE9HagHi3+tqNRoNsArdmAxHA5LwtQo9ZAaNKUTljnokljo2x8scqVpEEIPc01fPCdHOCg0DeWBz8D5TVAAfx8aRH5X2ZYNI3ebKDZdeJ+oBDAxmRqJ30Eh2/DaeAy5diVNMpEDmXiPDsGTzBLXy8eVDdJoIafgx/gxMyQi454QrW56nCyeELgSuNNEmYkflF+t3CZQOVRWjKhIuCclmQSlAXT3+4JGG75B4t/5hQ+ldMP4LsAW6z3XmU6IJJwpnGVnsgUZhoY1fZlwTR8wSU7xRejf2uCx9Z5trVTRRJP9KnEb134dEieil6eCOGWgboI7xsqsqM99jfJLTePjygKlH2CVxxsse9QRzTBFjD/Kjqitr/CCTBt/SJ6nLxz7cKP9pFqBpp0lN5y+adKNsZjrPuroemZauH9aTTFD3EKHW8S55XBLFQAt1jgxTQCTwxmx/JyfsZDN1RroN3VaxpSenpIX7K+ZbL8VdlQDcI4Cbzg3QJLa9yVqNxUelu+EtxLVqeekaAvSJkO6sSVqbUajxqhKshNpvZqoeApF0k/0P0ikkwUcbdwc4A1ejN7Oo0O15kG7hTMoK3hZRBCX7YYeLW0wvcXx/18n/u37yLgzBYVBUvORGli+sfRcX/74uD6P4hq+7xu54TlWJLFzT63uwUDwuEDdOjJQqx7JV+ZjaEAPi7t0MMrR4Q8Rkf18uxD6RK0RKh0hL8YU+DeL97i4pa5ZSyAfXKwZRS/8gXcxdZXm62RBDj8U3sN8x95b5PpPs/mCBKYvpaA50pN5Ct/499AFTtwQ5vgeSh+NHrKIi4NVpwM/XzRaNfJD856lPE6M21zWPguFsH7jbLVyEDfRmt4VwrhCJ5VTYmcSPfGgO5clfN+vbaDZ7sakU5+2vZ2WCDY031NxJarVytfDDVtiafcTGO2rJ/taoL3zChN2qmjxofczTOYQPPVQPh0JVtYgdUQINcSiNEEy58UdYXX1MpWUCEBx7LbcGtAm8XWRQTVOaoV3ySri4RShhs/B/0m4jX6OAwXOvcA09bNSG4czEGv/Wey6V/jbTCNTW6awXdNTcA1GsPe1E9fZdGl7R0vyoVpIdJtfC6d32NNErrvq/R+d65VG+YOwRXppXxOCYyGNSf1K3x6VxAW/vtz4EC1SgCOSPdN62sLsoIzuDfg8GwZAbquVO8HIuFP/ToVoeUB7nnwMF35a1wK1tI6fkrqFKhQdeJpwyls0pIy8AZde3/6LUUbFaYJthyUJSU/kqDXTLQElnn0Jr4B2RVghNrmNmoEn7pXIeshPguXVsvwoTdmClq49JJU3LWhHyWTrJL9bRP6VKv3tZoA/th77p5Jw++OEENvyvWy/pNeExiDUVQaXIRGh8xySZTI36yueFaSXo1uJY0RnXYgEOoWWOJHeaVuX/bGNhHsh2yinznl/++NJcE9j6fBPRcBdq9hb8awNw8U7Bl6GM7x69EDOIIbX/npZ++amlHR9L/35mE/2Ss4gb0xCcY4VyTFLRE796vHysLAamqcyO+aFQyJIDBNslbH2/MrAvZiSEIedc/cqjmv4fbda2pXbv+F5a2szSsdkm9noiNURXt8edUhGUF6fSZWd1IJaXKFwD+49R6eCXD4Bkef7j9tRtNMVgW8BhRz/Qpy1TmeYk0doyjZoJSbePOReVHgkFsCFuQJ+Lgc4BxeAsK/cOiNDRmdNw0ctYhn/nQ498dYI5znzGLoJi1rav7Cn88rL3wLePVtDK5gl77Tki3gHEsIAQ2+IKgarj7Y8W1IQzV5V9N+0TjLqbg68WfKcOmBCOj3JkwJhVIkwDhc+JorXuZEPMEh0vvH3x7iqf+VAwXgd4diZiaJD1zHL9Snx6Wfg4IugreyhabQkcir+y5XgDtdx3Avs7lkeeCBwDvZoTUCXx5QrZkcEqWfYEiEYRs/EphmRALSNGR1Iclgdr5VFoELpzF4++f35w3/j0t5ucW3n2ch4PQCLuUXupsPRR7UA5FjSKrMtPcKAZJfagO4lGE7FH3YKMjorpK0ZxAv+i2JkJhtAMWWWFej4RhPR/cJ3DxwocCvXDi4SGZU4cu+K32XndiFWgopAl+0GApcwf1XvymJcFs39jExIBO4yUjU9MExBLQYc9H+W7+IgdESPRpciT+rKZPebVtaVq+1GYO/5xTAL3HASjNTGIgMvdjWbgc7JvdE1zIFpuC0U9ESiZyzBixzxWxj4Kwh8My34q+FK3KNLtmsA1qyrmKSNQOXCPUZd+ONelBTvFoUI/CYsqa/RhtKiyMf2CgSFqEPk59Y3uqnlZ8gFpswfSYyko23yVZYxzKGxGm49Zqxg1l8oz5Ra9XaRwHkuxepmgyhm0SoNy2KlbcEqK+9QqS9PNx9Ihm9U7gsR55SSJ1FBDNnkuWKxIZ0SDpXuOGwZdoUbOMDPHP4vBAgz2VlSEJAHZGJVbYIg7l/FO5KfIVvxC8pPPxMGcNMoevFDeStt2iqztE10n2TA4dgJH76YS9HDhKHD3iCx6ieFX84BAI3QQnngh76f5ruPQVbr5qZmck/5UjDc26lfrOvUBWy0Ogl8bCoOkMOns81TnC3cuUS9KW8+9A+fe3XYZOFUPG1u5epSSmDLw0s5s2F0W30ANeo+zJkJQz9SPZgzwYpEoktofhGVfmLOAB20boCbW1QWq/NpET/hnMecw/uSyAH4NJc3ECOU4nnkK1fj3S/i5dwb3R7k00AqQQUwt7Ie1qV0aY/VQX0J8hLPy7eBNXMHYZYDNxHZ2Qh6AuXJxq+AeRec/Q+JLhZV6hpXwQEzw7bf5v9uUf2vpq3qlhmy0IIGTkwYdCfSAFmqbdo+3XvDTDjFJde0mbeQLcn2n31xaAqJ0ixO/CLsT4I4G4DoncVTgRGNBtsCcjISWT+oeXZ4Iedw/8OsJI1aPnNKLX/60VvcZb94uasRxCkqlPQ11u1Sa2hHvB80WQENxVyzjns0/PiEByyil21Te6oisk3mNCEMrhouCFO3yEZTHHOCMy9eb/4Tmi8cVf3Lf7P53SY2hX3PSN033As3ETIMLHWumWEO9JXHA2y2SIBlIPpLGG2qvNsCIlIr+B1SWAqRKm2w6Blf7U+zCSBwJrfHG5i8J5Gax/cVonMlon7aHJX/gSvucIncRP93XCqkv7D8IFKFsLiBgHqUpXhE3pYjEcV1dk/JD9zFVCfEaQIVX8Jmfz7IIofcBKQ4OaG+C3xC2veX9CD+iAFXDNaGg9eTVxvkbJRJlW4Nk9Wk13kn696jWppRDe/8pDrYMO9ZyxZ98ReKSz9kWKLLyk2zCZgAniCkLJVX3n1M9DYbomyahWiv/KixRIV9hj/oFz87I+HLznbPTjpa+D+bZQnMuRsljTpv90vQUt/pK7jCFnA30B/jtroSF2/m/gpWn1aQs5WeA6ghzF8SdqWI20fghdSeDOCSCmLgTkfaGgGDmw7nHFkRzGtag57IHS2na06I+gzEphXo1w/Zx2BM/jKL2nZoFjHggtFQjYi8nSVRSXIE58RPbBObXk7uuIL9+rs/5Zo7suJInEUxgsiZZAWS25iBtpEiZeBgDtghEoAE0sjcayNq85M4tbu/LF5h51335PsGzQ09O875+vUS89lkWMyNOFoip2PuyWyMP/iU2XIZdfCCJNDjebDoBLQdpy7QQZC7s9c0wjHJervQNDu2jWzBW5MSAJMr7bP+Iv92BkS/GGgzjEn7MF1IRKFwwzbjbS4/slGOmhx9cZrFu7HSEefojNv3r0UaKfKOWzXsq1zEugbzlMDFsacRJJI/iJlK3vtkZ+PLZIVMFlKA32wbq2Kd5T0uCLZ1CPkAfCdzkz2EYscjDcZq2AWfziN2covN4kXE1lQXPPLTNM1xx3tbiepcO/t3SWm4w87qfh99SL0ZnY+LKFPLPeXVM2mIIoVWt+9Nk0I7nY4O79iGYqxZ8RVz289an6NVdJWnSKZvJQCAuHNiVaDxPAFoH392t9wot5t0/qmU95eEWNbU2udUW5sN9JVqcYlvAIfLeYC33oUzzxZgSktsv21mA7Uly1FA5VnoJFh6N244Wmv3YJGFv/TCPryaw+ZORlpZjQdq/2DYXr3EZskfed0G61P09ipTKmlTQ1067Rg5+PAk5FlQ9e0SWbGf2B/08kqymOTMVOznsALHHNFH4LFRKl2F/NOiYFl9khNHnSu9Ak5sq26Ynl/i2fdTle29Y1ugqmR5Yj4YT9pvslFyYCbw0mNFr5rVQm1LvkG27QMq9ph3t8fmn6r6SQ4oSbr5tz+J1kIawGzDxb6VYOvvWhobDTXfBeNv3b4aNm5XUinsCGqG2q/45m3+LoCOsddFceYhRx1Tsss9PLdPfJdErFMjYd3gddjiP0+XQjcRadZP6bwNLySvunFf20Czy6JqdEW2a96KxdYdOryBv1BjbuUq2yCHeh+6sk7fGmmPi50pe/1l5TyPe5oHW9oPnhPswLyf2TFDdCyYlhwBCstv5C1HwlW7xWoGT9XZt4qVj5WryLPLLD6h/5cMLEjWzgCeAIKNsLak92aBqBsHl4AJwl2N4jfvbSkBExGimv0nFvv09uDScQbjx+w4kPQjgjlW+g9ws9VEJvI2k8N6XxVu0uIwovgTFdunG24gBtaDi+y1YLQwZ8mwbip5fVlO3k0n0AEr/ETbtu8Vjkm+nNSiEb7X/3fMjBL5A8PdgG+/FnbexbFFExmEfetXAnisEKy5z44WVPpQZjSy/jzeGn4yDRsFGqhh87QPaDBWhlo37IFbe/C0xynS91d2tP/AJoJS0sVF6iwAAAAAElFTkSuQmCC");
+}
+
+#menu::after {
+ display: block;
+ content: '';
+ padding-top: 80px;
+}
+
+#logo {
+ position: fixed;
+ bottom: 10px;
+ right: 10px;
+ background: rgba(255,255,255,.1);
+ font-size: 11px;
+ display: block;
+ width: 20px;
+ height: 20px;
+ line-height: 20px;
+ text-align: center;
+ -webkit-border-radius: 20px;
+ -moz-border-radius: 20px;
+ -webkit-box-shadow: 0 0 3px rgba(0,0,0,.2);
+ -moz-box-shadow: 0 0 3px rgba(0,0,0,.2);
+ color: inherit;
+}
+
+#menu li a {
+ display: block;
+ color: white;
+ padding: 0 35px 0 25px;
+ -webkit-transition: background 300ms;
+ -moz-transition: background 300ms;
+}
+
+#menu li {
+ position: relative;
+ list-style: none;
+}
+
+#menu a:hover,
+#menu a.active {
+ text-decoration: none;
+ background: rgba(255,255,255,.1);
+}
+
+#menu li:hover .cov {
+ opacity: 1;
+}
+
+#menu li .dirname {
+ opacity: .60;
+ padding-right: 2px;
+}
+
+#menu li .basename {
+ opacity: 1;
+}
+
+#menu .cov {
+ background: rgba(0,0,0,.4);
+ position: absolute;
+ top: 0;
+ right: 8px;
+ font-size: 9px;
+ opacity: .6;
+ text-align: left;
+ width: 17px;
+ -webkit-border-radius: 10px;
+ -moz-border-radius: 10px;
+ padding: 2px 3px;
+ text-align: center;
+}
+
+#stats:nth-child(2n) {
+ display: inline-block;
+ margin-top: 15px;
+ border: 1px solid #eee;
+ padding: 10px;
+ -webkit-box-shadow: inset 0 0 2px #eee;
+ -moz-box-shadow: inset 0 0 2px #eee;
+ -webkit-border-radius: 5px;
+ -moz-border-radius: 5px;
+}
+
+#stats div {
+ float: left;
+ padding: 0 5px;
+}
+
+#stats::after {
+ display: block;
+ content: '';
+ clear: both;
+}
+
+#stats .sloc::after {
+ content: ' SLOC';
+ color: #b6b6b6;
+}
+
+#stats .percentage::after {
+ content: ' coverage';
+ color: #b6b6b6;
+}
+
+#stats .hits,
+#stats .misses {
+ display: none;
+}
+
+.high {
+ color: #00d4b4;
+}
+.medium {
+ color: #e87d0d;
+}
+.low {
+ color: #d4081a;
+}
+.terrible {
+ color: #d4081a;
+ font-weight: bold;
+}
+
+table {
+ width: 80%;
+ margin-top: 10px;
+ border-collapse: collapse;
+ border: 1px solid #cbcbcb;
+ color: #363636;
+ -webkit-border-radius: 3px;
+ -moz-border-radius: 3px;
+}
+
+table thead {
+ display: none;
+}
+
+table td.line,
+table td.hits {
+ width: 20px;
+ background: #eaeaea;
+ text-align: center;
+ font-size: 11px;
+ padding: 0 10px;
+ color: #949494;
+}
+
+table td.hits {
+ width: 10px;
+ padding: 2px 5px;
+ color: rgba(0,0,0,.2);
+ background: #f0f0f0;
+}
+
+tr.miss td.line,
+tr.miss td.hits {
+ background: #e6c3c7;
+}
+
+tr.miss td {
+ background: #f8d5d8;
+}
+
+td.source {
+ padding-left: 15px;
+ line-height: 15px;
+ white-space: pre;
+ font: 12px monaco, monospace;
+}
+
+code .comment { color: #ddd }
+code .init { color: #2F6FAD }
+code .string { color: #5890AD }
+code .keyword { color: #8A6343 }
+code .number { color: #2F6FAD }
+</style></head><body><div id="coverage"><h1 id="overview">Coverage</h1><div id="menu"><li><a href="#overview">overview</a></li><li><span class="cov high">95</span><a href="#webidl2.js"><span class="basename">webidl2.js</span></a></li><a id="logo" href="http://visionmedia.github.com/mocha/">m</a></div><div id="stats" class="high"><div class="percentage">95%</div><div class="sloc">572</div><div class="hits">548</div><div class="misses">24</div></div><div id="files"><div class="file"><h2 id="webidl2.js">webidl2.js</h2><div id="stats" class="high"><div class="percentage">95%</div><div class="sloc">572</div><div class="hits">548</div><div class="misses">24</div></div><table id="source"><thead><tr><th>Line</th><th>Hits</th><th>Source</th></tr></thead><tbody><tr><td class="line">1</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">2</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">3</td><td class="hits">1</td><td class="source"><span class="k">(</span><span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">4</td><td class="hits">1</td><td class="source"> <span class="k">var</span> tokenise <span class="k">=</span> <span class="k">function</span> <span class="k">(</span>str<span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">5</td><td class="hits">47</td><td class="source"> <span class="k">var</span> tokens <span class="k">=</span> <span class="k">[]</span></td></tr><tr><td class="line">6</td><td class="hits"></td><td class="source"> <span class="k">,</span> re <span class="k">=</span> <span class="k">{</span></td></tr><tr><td class="line">7</td><td class="hits"></td><td class="source"> <span class="s">"float"</span><span class="k">:</span> <span class="s">/^-?(([0-9]+\.[0-9]*|[0-9]*\.[0-9]+)([Ee][-+]?[0-9]+)?|[0-9]+[Ee][-+]?[0-9]+)/</span></td></tr><tr><td class="line">8</td><td class="hits"></td><td class="source"> <span class="k">,</span> <span class="s">"integer"</span><span class="k">:</span> <span class="s">/^-?(0([Xx][0-9A-Fa-f]+|[0-7]*)|[1-9][0-9]*)/</span></td></tr><tr><td class="line">9</td><td class="hits"></td><td class="source"> <span class="k">,</span> <span class="s">"identifier"</span><span class="k">:</span> <span class="s">/^[A-Z_a-z][0-9A-Z_a-z]*/</span></td></tr><tr><td class="line">10</td><td class="hits"></td><td class="source"> <span class="k">,</span> <span class="s">"string"</span><span class="k">:</span> <span class="s">/^"[^"]*"/</span></td></tr><tr><td class="line">11</td><td class="hits"></td><td class="source"> <span class="k">,</span> <span class="s">"whitespace"</span><span class="k">:</span> <span class="s">/^(?:[\t\n\r ]+|[\t\n\r ]*((\/\/.*|\/\*(.|\n|\r)*?\*\/)[\t\n\r ]*))+/</span></td></tr><tr><td class="line">12</td><td class="hits"></td><td class="source"> <span class="k">,</span> <span class="s">"other"</span><span class="k">:</span> <span class="s">/^[^\t\n\r 0-9A-Z_a-z]/</span></td></tr><tr><td class="line">13</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">14</td><td class="hits"></td><td class="source"> <span class="k">,</span> types <span class="k">=</span> <span class="k">[]</span></td></tr><tr><td class="line">15</td><td class="hits"></td><td class="source"> <span class="k">;</span></td></tr><tr class="hit"> <td class="line">16</td><td class="hits">329</td><td class="source"> <span class="k">for</span> <span class="k">(</span><span class="k">var</span> k <span class="k">in</span> re<span class="k">)</span> types<span class="k">.</span>push<span class="k">(</span>k<span class="k">);</span></td></tr><tr class="hit"> <td class="line">17</td><td class="hits">47</td><td class="source"> <span class="k">while</span> <span class="k">(</span>str<span class="k">.</span>length <span class="k">></span> <span class="s">0</span><span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">18</td><td class="hits">2914</td><td class="source"> <span class="k">var</span> matched <span class="k">=</span> <span class="k">false</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">19</td><td class="hits">2914</td><td class="source"> <span class="k">for</span> <span class="k">(</span><span class="k">var</span> i <span class="k">=</span> <span class="s">0</span><span class="k">,</span> n <span class="k">=</span> types<span class="k">.</span>length<span class="k">;</span> i <span class="k"><</span> n<span class="k">;</span> i<span class="k">++)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">20</td><td class="hits">13325</td><td class="source"> <span class="k">var</span> type <span class="k">=</span> types<span class="k">[</span>i<span class="k">];</span></td></tr><tr class="hit"> <td class="line">21</td><td class="hits">13325</td><td class="source"> str <span class="k">=</span> str<span class="k">.</span>replace<span class="k">(</span>re<span class="k">[</span>type<span class="k">],</span> <span class="k">function</span> <span class="k">(</span>tok<span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">22</td><td class="hits">2914</td><td class="source"> tokens<span class="k">.</span>push<span class="k">(</span><span class="k">{</span> type<span class="k">:</span> type<span class="k">,</span> value<span class="k">:</span> tok <span class="k">}</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">23</td><td class="hits">2914</td><td class="source"> matched <span class="k">=</span> <span class="k">true</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">24</td><td class="hits">2914</td><td class="source"> <span class="k">return</span> <span class="s">""</span><span class="k">;</span></td></tr><tr><td class="line">25</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">26</td><td class="hits">16239</td><td class="source"> <span class="k">if</span> <span class="k">(</span>matched<span class="k">)</span> <span class="k">break</span><span class="k">;</span></td></tr><tr><td class="line">27</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">28</td><td class="hits">5828</td><td class="source"> <span class="k">if</span> <span class="k">(</span>matched<span class="k">)</span> <span class="k">continue</span><span class="k">;</span></td></tr><tr class="miss"> <td class="line">29</td><td class="hits">0</td><td class="source"> <span class="k">throw</span> <span class="k">new</span> Error<span class="k">(</span><span class="s">"Token stream not progressing"</span><span class="k">);</span></td></tr><tr><td class="line">30</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">31</td><td class="hits">47</td><td class="source"> <span class="k">return</span> tokens<span class="k">;</span></td></tr><tr><td class="line">32</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">33</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">34</td><td class="hits">1</td><td class="source"> <span class="k">var</span> parse <span class="k">=</span> <span class="k">function</span> <span class="k">(</span>tokens<span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">35</td><td class="hits">47</td><td class="source"> <span class="k">var</span> line <span class="k">=</span> <span class="s">1</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">36</td><td class="hits">47</td><td class="source"> tokens <span class="k">=</span> tokens<span class="k">.</span>slice<span class="k">();</span></td></tr><tr><td class="line">37</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">38</td><td class="hits">47</td><td class="source"> <span class="k">var</span> FLOAT <span class="k">=</span> <span class="s">"float"</span></td></tr><tr><td class="line">39</td><td class="hits"></td><td class="source"> <span class="k">,</span> INT <span class="k">=</span> <span class="s">"integer"</span></td></tr><tr><td class="line">40</td><td class="hits"></td><td class="source"> <span class="k">,</span> ID <span class="k">=</span> <span class="s">"identifier"</span></td></tr><tr><td class="line">41</td><td class="hits"></td><td class="source"> <span class="k">,</span> STR <span class="k">=</span> <span class="s">"string"</span></td></tr><tr><td class="line">42</td><td class="hits"></td><td class="source"> <span class="k">,</span> OTHER <span class="k">=</span> <span class="s">"other"</span></td></tr><tr><td class="line">43</td><td class="hits"></td><td class="source"> <span class="k">;</span></td></tr><tr><td class="line">44</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">45</td><td class="hits">47</td><td class="source"> <span class="k">var</span> WebIDLParseError <span class="k">=</span> <span class="k">function</span> <span class="k">(</span>str<span class="k">,</span> line<span class="k">,</span> input<span class="k">,</span> tokens<span class="k">)</span> <span class="k">{</span></td></tr><tr class="miss"> <td class="line">46</td><td class="hits">0</td><td class="source"> <span class="k">this</span><span class="k">.</span>message <span class="k">=</span> str<span class="k">;</span></td></tr><tr class="miss"> <td class="line">47</td><td class="hits">0</td><td class="source"> <span class="k">this</span><span class="k">.</span>line <span class="k">=</span> line<span class="k">;</span></td></tr><tr class="miss"> <td class="line">48</td><td class="hits">0</td><td class="source"> <span class="k">this</span><span class="k">.</span>input <span class="k">=</span> input<span class="k">;</span></td></tr><tr class="miss"> <td class="line">49</td><td class="hits">0</td><td class="source"> <span class="k">this</span><span class="k">.</span>tokens <span class="k">=</span> tokens<span class="k">;</span></td></tr><tr><td class="line">50</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">51</td><td class="hits">47</td><td class="source"> WebIDLParseError<span class="k">.</span>prototype<span class="k">.</span>toString <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="miss"> <td class="line">52</td><td class="hits">0</td><td class="source"> <span class="k">return</span> <span class="k">this</span><span class="k">.</span>message <span class="k">+</span> <span class="s">", line "</span> <span class="k">+</span> <span class="k">this</span><span class="k">.</span>line <span class="k">+</span> <span class="s">" (tokens: '"</span> <span class="k">+</span> <span class="k">this</span><span class="k">.</span>input <span class="k">+</span> <span class="s">"')</span><span class="t">\n</span><span class="s">"</span> <span class="k">+</span></td></tr><tr><td class="line">53</td><td class="hits"></td><td class="source"> JSON<span class="k">.</span>stringify<span class="k">(</span><span class="k">this</span><span class="k">.</span>tokens<span class="k">,</span> <span class="k">null</span><span class="k">,</span> <span class="s">4</span><span class="k">);</span></td></tr><tr><td class="line">54</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">55</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">56</td><td class="hits">47</td><td class="source"> <span class="k">var</span> error <span class="k">=</span> <span class="k">function</span> <span class="k">(</span>str<span class="k">)</span> <span class="k">{</span></td></tr><tr class="miss"> <td class="line">57</td><td class="hits">0</td><td class="source"> <span class="k">var</span> tok <span class="k">=</span> <span class="s">""</span><span class="k">,</span> numTokens <span class="k">=</span> <span class="s">0</span><span class="k">,</span> maxTokens <span class="k">=</span> <span class="s">5</span><span class="k">;</span></td></tr><tr class="miss"> <td class="line">58</td><td class="hits">0</td><td class="source"> <span class="k">while</span> <span class="k">(</span>numTokens <span class="k"><</span> maxTokens <span class="k">&amp;&amp;</span> tokens<span class="k">.</span>length <span class="k">></span> numTokens<span class="k">)</span> <span class="k">{</span></td></tr><tr class="miss"> <td class="line">59</td><td class="hits">0</td><td class="source"> tok <span class="k">+=</span> tokens<span class="k">[</span>numTokens<span class="k">].</span>value<span class="k">;</span></td></tr><tr class="miss"> <td class="line">60</td><td class="hits">0</td><td class="source"> numTokens<span class="k">++;</span></td></tr><tr><td class="line">61</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="miss"> <td class="line">62</td><td class="hits">0</td><td class="source"> <span class="k">throw</span> <span class="k">new</span> WebIDLParseError<span class="k">(</span>str<span class="k">,</span> line<span class="k">,</span> tok<span class="k">,</span> tokens<span class="k">.</span>slice<span class="k">(</span><span class="s">0</span><span class="k">,</span> <span class="s">5</span><span class="k">));</span></td></tr><tr><td class="line">63</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">64</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">65</td><td class="hits">47</td><td class="source"> <span class="k">var</span> last_token <span class="k">=</span> <span class="k">null</span><span class="k">;</span></td></tr><tr><td class="line">66</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">67</td><td class="hits">47</td><td class="source"> <span class="k">var</span> consume <span class="k">=</span> <span class="k">function</span> <span class="k">(</span>type<span class="k">,</span> value<span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">68</td><td class="hits">8778</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>tokens<span class="k">.</span>length <span class="k">||</span> tokens<span class="k">[</span><span class="s">0</span><span class="k">].</span>type <span class="k">!==</span> type<span class="k">)</span> <span class="k">return</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">69</td><td class="hits">5470</td><td class="source"> <span class="k">if</span> <span class="k">(</span><span class="k">typeof</span> value <span class="k">===</span> <span class="s">"undefined"</span> <span class="k">||</span> tokens<span class="k">[</span><span class="s">0</span><span class="k">].</span>value <span class="k">===</span> value<span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">70</td><td class="hits">1738</td><td class="source"> last_token <span class="k">=</span> tokens<span class="k">.</span>shift<span class="k">();</span></td></tr><tr class="hit"> <td class="line">71</td><td class="hits">1738</td><td class="source"> <span class="k">return</span> last_token<span class="k">;</span></td></tr><tr><td class="line">72</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">73</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">74</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">75</td><td class="hits">47</td><td class="source"> <span class="k">var</span> ws <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">76</td><td class="hits">6961</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>tokens<span class="k">.</span>length<span class="k">)</span> <span class="k">return</span><span class="k">;</span></td></tr><tr><td class="line">77</td><td class="hits"></td><td class="source"> <span class="c">// console.log("tokens.length", tokens.length, tokens[0]);</span></td></tr><tr class="hit"> <td class="line">78</td><td class="hits">6115</td><td class="source"> <span class="k">if</span> <span class="k">(</span>tokens<span class="k">[</span><span class="s">0</span><span class="k">].</span>type <span class="k">===</span> <span class="s">"whitespace"</span><span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">79</td><td class="hits">1172</td><td class="source"> <span class="k">var</span> t <span class="k">=</span> tokens<span class="k">.</span>shift<span class="k">();</span></td></tr><tr class="hit"> <td class="line">80</td><td class="hits">2294</td><td class="source"> t<span class="k">.</span>value<span class="k">.</span>replace<span class="k">(</span><span class="s">/\n/g</span><span class="k">,</span> <span class="k">function</span> <span class="k">(</span>m<span class="k">)</span> <span class="k">{</span> line<span class="k">++;</span> <span class="k">return</span> m<span class="k">;</span> <span class="k">}</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">81</td><td class="hits">1172</td><td class="source"> <span class="k">return</span> t<span class="k">;</span></td></tr><tr><td class="line">82</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">83</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">84</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">85</td><td class="hits">47</td><td class="source"> <span class="k">var</span> all_ws <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">86</td><td class="hits">5366</td><td class="source"> <span class="k">var</span> t <span class="k">=</span> <span class="k">{</span> type<span class="k">:</span> <span class="s">"whitespace"</span><span class="k">,</span> value<span class="k">:</span> <span class="s">""</span> <span class="k">}</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">87</td><td class="hits">5366</td><td class="source"> <span class="k">while</span> <span class="k">(</span><span class="k">true</span><span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">88</td><td class="hits">6538</td><td class="source"> <span class="k">var</span> w <span class="k">=</span> ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">89</td><td class="hits">11904</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>w<span class="k">)</span> <span class="k">break</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">90</td><td class="hits">1172</td><td class="source"> t<span class="k">.</span>value <span class="k">+=</span> w<span class="k">.</span>value<span class="k">;</span></td></tr><tr><td class="line">91</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">92</td><td class="hits">6538</td><td class="source"> <span class="k">if</span> <span class="k">(</span>t<span class="k">.</span>value<span class="k">.</span>length <span class="k">></span> <span class="s">0</span><span class="k">)</span> <span class="k">return</span> t<span class="k">;</span></td></tr><tr><td class="line">93</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">94</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">95</td><td class="hits">47</td><td class="source"> <span class="k">var</span> integer_type <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">96</td><td class="hits">273</td><td class="source"> <span class="k">var</span> ret <span class="k">=</span> <span class="s">""</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">97</td><td class="hits">273</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">98</td><td class="hits">312</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"unsigned"</span><span class="k">))</span> ret <span class="k">=</span> <span class="s">"unsigned "</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">99</td><td class="hits">273</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">100</td><td class="hits">287</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"short"</span><span class="k">))</span> <span class="k">return</span> ret <span class="k">+</span> <span class="s">"short"</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">101</td><td class="hits">259</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"long"</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">102</td><td class="hits">41</td><td class="source"> ret <span class="k">+=</span> <span class="s">"long"</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">103</td><td class="hits">41</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">104</td><td class="hits">43</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"long"</span><span class="k">))</span> <span class="k">return</span> ret <span class="k">+</span> <span class="s">" long"</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">105</td><td class="hits">39</td><td class="source"> <span class="k">return</span> ret<span class="k">;</span></td></tr><tr><td class="line">106</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">107</td><td class="hits">218</td><td class="source"> <span class="k">if</span> <span class="k">(</span>ret<span class="k">)</span> error<span class="k">(</span><span class="s">"Failed to parse integer type"</span><span class="k">);</span></td></tr><tr><td class="line">108</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">109</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">110</td><td class="hits">47</td><td class="source"> <span class="k">var</span> float_type <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">111</td><td class="hits">218</td><td class="source"> <span class="k">var</span> ret <span class="k">=</span> <span class="s">""</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">112</td><td class="hits">218</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">113</td><td class="hits">222</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"unrestricted"</span><span class="k">))</span> ret <span class="k">=</span> <span class="s">"unrestricted "</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">114</td><td class="hits">218</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">115</td><td class="hits">257</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"float"</span><span class="k">))</span> <span class="k">return</span> ret <span class="k">+</span> <span class="s">"float"</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">116</td><td class="hits">182</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"double"</span><span class="k">))</span> <span class="k">return</span> ret <span class="k">+</span> <span class="s">"double"</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">117</td><td class="hits">176</td><td class="source"> <span class="k">if</span> <span class="k">(</span>ret<span class="k">)</span> error<span class="k">(</span><span class="s">"Failed to parse float type"</span><span class="k">);</span></td></tr><tr><td class="line">118</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">119</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">120</td><td class="hits">47</td><td class="source"> <span class="k">var</span> primitive_type <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">121</td><td class="hits">273</td><td class="source"> <span class="k">var</span> num_type <span class="k">=</span> integer_type<span class="k">()</span> <span class="k">||</span> float_type<span class="k">();</span></td></tr><tr class="hit"> <td class="line">122</td><td class="hits">370</td><td class="source"> <span class="k">if</span> <span class="k">(</span>num_type<span class="k">)</span> <span class="k">return</span> num_type<span class="k">;</span></td></tr><tr class="hit"> <td class="line">123</td><td class="hits">176</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">124</td><td class="hits">186</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"boolean"</span><span class="k">))</span> <span class="k">return</span> <span class="s">"boolean"</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">125</td><td class="hits">167</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"byte"</span><span class="k">))</span> <span class="k">return</span> <span class="s">"byte"</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">126</td><td class="hits">168</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"octet"</span><span class="k">))</span> <span class="k">return</span> <span class="s">"octet"</span><span class="k">;</span></td></tr><tr><td class="line">127</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">128</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">129</td><td class="hits">47</td><td class="source"> <span class="k">var</span> const_value <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">130</td><td class="hits">17</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"true"</span><span class="k">))</span> <span class="k">return</span> <span class="k">true</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">131</td><td class="hits">19</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"false"</span><span class="k">))</span> <span class="k">return</span> <span class="k">false</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">132</td><td class="hits">17</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"null"</span><span class="k">))</span> <span class="k">return</span> <span class="k">null</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">133</td><td class="hits">14</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"Infinity"</span><span class="k">))</span> <span class="k">return</span> Infinity<span class="k">;</span></td></tr><tr class="hit"> <td class="line">134</td><td class="hits">13</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"NaN"</span><span class="k">))</span> <span class="k">return</span> NaN<span class="k">;</span></td></tr><tr class="hit"> <td class="line">135</td><td class="hits">11</td><td class="source"> <span class="k">var</span> ret <span class="k">=</span> consume<span class="k">(</span>FLOAT<span class="k">)</span> <span class="k">||</span> consume<span class="k">(</span>INT<span class="k">);</span></td></tr><tr class="hit"> <td class="line">136</td><td class="hits">19</td><td class="source"> <span class="k">if</span> <span class="k">(</span>ret<span class="k">)</span> <span class="k">return</span> <span class="s">1</span> <span class="k">*</span> ret<span class="k">.</span>value<span class="k">;</span></td></tr><tr class="hit"> <td class="line">137</td><td class="hits">3</td><td class="source"> <span class="k">var</span> tok <span class="k">=</span> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"-"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">138</td><td class="hits">3</td><td class="source"> <span class="k">if</span> <span class="k">(</span>tok<span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">139</td><td class="hits">2</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"Infinity"</span><span class="k">))</span> <span class="k">return</span> <span class="k">-</span>Infinity<span class="k">;</span></td></tr><tr class="miss"> <td class="line">140</td><td class="hits">0</td><td class="source"> <span class="k">else</span> tokens<span class="k">.</span>unshift<span class="k">(</span>tok<span class="k">);</span></td></tr><tr><td class="line">141</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">142</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">143</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">144</td><td class="hits">47</td><td class="source"> <span class="k">var</span> type_suffix <span class="k">=</span> <span class="k">function</span> <span class="k">(</span>obj<span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">145</td><td class="hits">249</td><td class="source"> <span class="k">while</span> <span class="k">(</span><span class="k">true</span><span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">146</td><td class="hits">263</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">147</td><td class="hits">263</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"?"</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">148</td><td class="hits">11</td><td class="source"> <span class="k">if</span> <span class="k">(</span>obj<span class="k">.</span>nullable<span class="k">)</span> error<span class="k">(</span><span class="s">"Can't nullable more than once"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">149</td><td class="hits">11</td><td class="source"> obj<span class="k">.</span>nullable <span class="k">=</span> <span class="k">true</span><span class="k">;</span></td></tr><tr><td class="line">150</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">151</td><td class="hits">252</td><td class="source"> <span class="k">else</span> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"["</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">152</td><td class="hits">3</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">153</td><td class="hits">3</td><td class="source"> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"]"</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Unterminated array type"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">154</td><td class="hits">5</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>obj<span class="k">.</span>array<span class="k">)</span> obj<span class="k">.</span>array <span class="k">=</span> <span class="s">1</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">155</td><td class="hits">1</td><td class="source"> <span class="k">else</span> obj<span class="k">.</span>array<span class="k">++;</span></td></tr><tr><td class="line">156</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">157</td><td class="hits">249</td><td class="source"> <span class="k">else</span> <span class="k">return</span><span class="k">;</span></td></tr><tr><td class="line">158</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">159</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">160</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">161</td><td class="hits">47</td><td class="source"> <span class="k">var</span> single_type <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">162</td><td class="hits">261</td><td class="source"> <span class="k">var</span> prim <span class="k">=</span> primitive_type<span class="k">()</span></td></tr><tr><td class="line">163</td><td class="hits"></td><td class="source"> <span class="k">,</span> ret <span class="k">=</span> <span class="k">{</span> sequence<span class="k">:</span> <span class="k">false</span><span class="k">,</span> nullable<span class="k">:</span> <span class="k">false</span><span class="k">,</span> array<span class="k">:</span> <span class="k">false</span><span class="k">,</span> union<span class="k">:</span> <span class="k">false</span> <span class="k">}</span></td></tr><tr><td class="line">164</td><td class="hits"></td><td class="source"> <span class="k">;</span></td></tr><tr class="hit"> <td class="line">165</td><td class="hits">261</td><td class="source"> <span class="k">if</span> <span class="k">(</span>prim<span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">166</td><td class="hits">99</td><td class="source"> ret<span class="k">.</span>idlType <span class="k">=</span> prim<span class="k">;</span></td></tr><tr><td class="line">167</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">168</td><td class="hits">162</td><td class="source"> <span class="k">else</span> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"sequence"</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">169</td><td class="hits">4</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">170</td><td class="hits">4</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"<"</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="miss"> <td class="line">171</td><td class="hits">0</td><td class="source"> ret<span class="k">.</span>idlType <span class="k">=</span> <span class="s">"sequence"</span><span class="k">;</span></td></tr><tr><td class="line">172</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">173</td><td class="hits"></td><td class="source"> <span class="k">else</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">174</td><td class="hits">4</td><td class="source"> ret<span class="k">.</span>sequence <span class="k">=</span> <span class="k">true</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">175</td><td class="hits">4</td><td class="source"> ret<span class="k">.</span>idlType <span class="k">=</span> type<span class="k">()</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Error parsing sequence type"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">176</td><td class="hits">4</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">177</td><td class="hits">4</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">">"</span><span class="k">))</span> error<span class="k">(</span><span class="s">"Unterminated sequence"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">178</td><td class="hits">4</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">179</td><td class="hits">5</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"?"</span><span class="k">))</span> ret<span class="k">.</span>nullable <span class="k">=</span> <span class="k">true</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">180</td><td class="hits">4</td><td class="source"> <span class="k">return</span> ret<span class="k">;</span></td></tr><tr><td class="line">181</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">182</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">183</td><td class="hits"></td><td class="source"> <span class="k">else</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">184</td><td class="hits">158</td><td class="source"> <span class="k">var</span> name <span class="k">=</span> consume<span class="k">(</span>ID<span class="k">);</span></td></tr><tr class="hit"> <td class="line">185</td><td class="hits">169</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>name<span class="k">)</span> <span class="k">return</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">186</td><td class="hits">147</td><td class="source"> ret<span class="k">.</span>idlType <span class="k">=</span> name<span class="k">.</span>value<span class="k">;</span></td></tr><tr><td class="line">187</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">188</td><td class="hits">246</td><td class="source"> type_suffix<span class="k">(</span>ret<span class="k">);</span></td></tr><tr class="hit"> <td class="line">189</td><td class="hits">246</td><td class="source"> <span class="k">if</span> <span class="k">(</span>ret<span class="k">.</span>nullable <span class="k">&amp;&amp;</span> ret<span class="k">.</span>idlType <span class="k">===</span> <span class="s">"any"</span><span class="k">)</span> error<span class="k">(</span><span class="s">"Type any cannot be made nullable"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">190</td><td class="hits">246</td><td class="source"> <span class="k">return</span> ret<span class="k">;</span></td></tr><tr><td class="line">191</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">192</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">193</td><td class="hits">47</td><td class="source"> <span class="k">var</span> union_type <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">194</td><td class="hits">11</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">195</td><td class="hits">19</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"("</span><span class="k">))</span> <span class="k">return</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">196</td><td class="hits">3</td><td class="source"> <span class="k">var</span> ret <span class="k">=</span> <span class="k">{</span> sequence<span class="k">:</span> <span class="k">false</span><span class="k">,</span> nullable<span class="k">:</span> <span class="k">false</span><span class="k">,</span> array<span class="k">:</span> <span class="k">false</span><span class="k">,</span> union<span class="k">:</span> <span class="k">true</span><span class="k">,</span> idlType<span class="k">:</span> <span class="k">[]</span> <span class="k">}</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">197</td><td class="hits">3</td><td class="source"> <span class="k">var</span> fst <span class="k">=</span> type<span class="k">()</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Union type with no content"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">198</td><td class="hits">3</td><td class="source"> ret<span class="k">.</span>idlType<span class="k">.</span>push<span class="k">(</span>fst<span class="k">);</span></td></tr><tr class="hit"> <td class="line">199</td><td class="hits">3</td><td class="source"> <span class="k">while</span> <span class="k">(</span><span class="k">true</span><span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">200</td><td class="hits">7</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">201</td><td class="hits">10</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"or"</span><span class="k">))</span> <span class="k">break</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">202</td><td class="hits">4</td><td class="source"> <span class="k">var</span> typ <span class="k">=</span> type<span class="k">()</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"No type after 'or' in union type"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">203</td><td class="hits">4</td><td class="source"> ret<span class="k">.</span>idlType<span class="k">.</span>push<span class="k">(</span>typ<span class="k">);</span></td></tr><tr><td class="line">204</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">205</td><td class="hits">3</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">")"</span><span class="k">))</span> error<span class="k">(</span><span class="s">"Unterminated union type"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">206</td><td class="hits">3</td><td class="source"> type_suffix<span class="k">(</span>ret<span class="k">);</span></td></tr><tr class="hit"> <td class="line">207</td><td class="hits">3</td><td class="source"> <span class="k">return</span> ret<span class="k">;</span></td></tr><tr><td class="line">208</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">209</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">210</td><td class="hits">47</td><td class="source"> <span class="k">var</span> type <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">211</td><td class="hits">261</td><td class="source"> <span class="k">return</span> single_type<span class="k">()</span> <span class="k">||</span> union_type<span class="k">();</span></td></tr><tr><td class="line">212</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">213</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">214</td><td class="hits">47</td><td class="source"> <span class="k">var</span> argument <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">215</td><td class="hits">79</td><td class="source"> <span class="k">var</span> ret <span class="k">=</span> <span class="k">{</span> optional<span class="k">:</span> <span class="k">false</span><span class="k">,</span> variadic<span class="k">:</span> <span class="k">false</span> <span class="k">}</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">216</td><td class="hits">79</td><td class="source"> ret<span class="k">.</span>extAttrs <span class="k">=</span> extended_attrs<span class="k">();</span></td></tr><tr class="hit"> <td class="line">217</td><td class="hits">79</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">218</td><td class="hits">79</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"optional"</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">219</td><td class="hits">2</td><td class="source"> ret<span class="k">.</span>optional <span class="k">=</span> <span class="k">true</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">220</td><td class="hits">2</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr><td class="line">221</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">222</td><td class="hits">79</td><td class="source"> ret<span class="k">.</span>type <span class="k">=</span> type<span class="k">();</span></td></tr><tr class="hit"> <td class="line">223</td><td class="hits">87</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>ret<span class="k">.</span>type<span class="k">)</span> <span class="k">return</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">224</td><td class="hits">71</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>ret<span class="k">.</span>optional<span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">225</td><td class="hits">69</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">226</td><td class="hits">69</td><td class="source"> <span class="k">if</span> <span class="k">(</span>tokens<span class="k">.</span>length <span class="k">>=</span> <span class="s">3</span> <span class="k">&amp;&amp;</span></td></tr><tr><td class="line">227</td><td class="hits"></td><td class="source"> tokens<span class="k">[</span><span class="s">0</span><span class="k">].</span>type <span class="k">===</span> <span class="s">"other"</span> <span class="k">&amp;&amp;</span> tokens<span class="k">[</span><span class="s">0</span><span class="k">].</span>value <span class="k">===</span> <span class="s">"."</span> <span class="k">&amp;&amp;</span></td></tr><tr><td class="line">228</td><td class="hits"></td><td class="source"> tokens<span class="k">[</span><span class="s">1</span><span class="k">].</span>type <span class="k">===</span> <span class="s">"other"</span> <span class="k">&amp;&amp;</span> tokens<span class="k">[</span><span class="s">1</span><span class="k">].</span>value <span class="k">===</span> <span class="s">"."</span> <span class="k">&amp;&amp;</span></td></tr><tr><td class="line">229</td><td class="hits"></td><td class="source"> tokens<span class="k">[</span><span class="s">2</span><span class="k">].</span>type <span class="k">===</span> <span class="s">"other"</span> <span class="k">&amp;&amp;</span> tokens<span class="k">[</span><span class="s">2</span><span class="k">].</span>value <span class="k">===</span> <span class="s">"."</span></td></tr><tr><td class="line">230</td><td class="hits"></td><td class="source"> <span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">231</td><td class="hits">4</td><td class="source"> tokens<span class="k">.</span>shift<span class="k">();</span></td></tr><tr class="hit"> <td class="line">232</td><td class="hits">4</td><td class="source"> tokens<span class="k">.</span>shift<span class="k">();</span></td></tr><tr class="hit"> <td class="line">233</td><td class="hits">4</td><td class="source"> tokens<span class="k">.</span>shift<span class="k">();</span></td></tr><tr class="hit"> <td class="line">234</td><td class="hits">4</td><td class="source"> ret<span class="k">.</span>variadic <span class="k">=</span> <span class="k">true</span><span class="k">;</span></td></tr><tr><td class="line">235</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">236</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">237</td><td class="hits">71</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">238</td><td class="hits">71</td><td class="source"> <span class="k">var</span> name <span class="k">=</span> consume<span class="k">(</span>ID<span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"No name in argument"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">239</td><td class="hits">71</td><td class="source"> ret<span class="k">.</span>name <span class="k">=</span> name<span class="k">.</span>value<span class="k">;</span></td></tr><tr class="hit"> <td class="line">240</td><td class="hits">71</td><td class="source"> <span class="k">if</span> <span class="k">(</span>ret<span class="k">.</span>optional<span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">241</td><td class="hits">2</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">242</td><td class="hits">2</td><td class="source"> ret<span class="k">[</span><span class="s">"default"</span><span class="k">]</span> <span class="k">=</span> default_<span class="k">();</span></td></tr><tr><td class="line">243</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">244</td><td class="hits">71</td><td class="source"> <span class="k">return</span> ret<span class="k">;</span></td></tr><tr><td class="line">245</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">246</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">247</td><td class="hits">47</td><td class="source"> <span class="k">var</span> argument_list <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">248</td><td class="hits">59</td><td class="source"> <span class="k">var</span> arg <span class="k">=</span> argument<span class="k">(),</span> ret <span class="k">=</span> <span class="k">[];</span></td></tr><tr class="hit"> <td class="line">249</td><td class="hits">67</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>arg<span class="k">)</span> <span class="k">return</span> ret<span class="k">;</span></td></tr><tr class="hit"> <td class="line">250</td><td class="hits">51</td><td class="source"> ret<span class="k">.</span>push<span class="k">(</span>arg<span class="k">);</span></td></tr><tr class="hit"> <td class="line">251</td><td class="hits">51</td><td class="source"> <span class="k">while</span> <span class="k">(</span><span class="k">true</span><span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">252</td><td class="hits">71</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">253</td><td class="hits">122</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">","</span><span class="k">))</span> <span class="k">return</span> ret<span class="k">;</span></td></tr><tr class="hit"> <td class="line">254</td><td class="hits">20</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">255</td><td class="hits">20</td><td class="source"> <span class="k">var</span> nxt <span class="k">=</span> argument<span class="k">()</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Trailing comma in arguments list"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">256</td><td class="hits">20</td><td class="source"> ret<span class="k">.</span>push<span class="k">(</span>nxt<span class="k">);</span></td></tr><tr><td class="line">257</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">258</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">259</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">260</td><td class="hits">47</td><td class="source"> <span class="k">var</span> simple_extended_attr <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">261</td><td class="hits">17</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">262</td><td class="hits">17</td><td class="source"> <span class="k">var</span> name <span class="k">=</span> consume<span class="k">(</span>ID<span class="k">);</span></td></tr><tr class="hit"> <td class="line">263</td><td class="hits">17</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>name<span class="k">)</span> <span class="k">return</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">264</td><td class="hits">17</td><td class="source"> <span class="k">var</span> ret <span class="k">=</span> <span class="k">{</span></td></tr><tr><td class="line">265</td><td class="hits"></td><td class="source"> name<span class="k">:</span> name<span class="k">.</span>value</td></tr><tr><td class="line">266</td><td class="hits"></td><td class="source"> <span class="k">,</span> <span class="s">"arguments"</span><span class="k">:</span> <span class="k">null</span></td></tr><tr><td class="line">267</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">268</td><td class="hits">17</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">269</td><td class="hits">17</td><td class="source"> <span class="k">var</span> eq <span class="k">=</span> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"="</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">270</td><td class="hits">17</td><td class="source"> <span class="k">if</span> <span class="k">(</span>eq<span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">271</td><td class="hits">5</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">272</td><td class="hits">5</td><td class="source"> ret<span class="k">.</span>rhs <span class="k">=</span> consume<span class="k">(</span>ID<span class="k">);</span></td></tr><tr class="hit"> <td class="line">273</td><td class="hits">5</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>ret<span class="k">.</span>rhs<span class="k">)</span> <span class="k">return</span> error<span class="k">(</span><span class="s">"No right hand side to extended attribute assignment"</span><span class="k">);</span></td></tr><tr><td class="line">274</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">275</td><td class="hits">17</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">276</td><td class="hits">17</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"("</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">277</td><td class="hits">2</td><td class="source"> ret<span class="k">[</span><span class="s">"arguments"</span><span class="k">]</span> <span class="k">=</span> argument_list<span class="k">();</span></td></tr><tr class="hit"> <td class="line">278</td><td class="hits">2</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">279</td><td class="hits">2</td><td class="source"> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">")"</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Unclosed argument in extended attribute"</span><span class="k">);</span></td></tr><tr><td class="line">280</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">281</td><td class="hits">17</td><td class="source"> <span class="k">return</span> ret<span class="k">;</span></td></tr><tr><td class="line">282</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">283</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">284</td><td class="hits"></td><td class="source"> <span class="c">// Note: we parse something simpler than the official syntax. It's all that ever</span></td></tr><tr><td class="line">285</td><td class="hits"></td><td class="source"> <span class="c">// seems to be used</span></td></tr><tr class="hit"> <td class="line">286</td><td class="hits">47</td><td class="source"> <span class="k">var</span> extended_attrs <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">287</td><td class="hits">415</td><td class="source"> <span class="k">var</span> eas <span class="k">=</span> <span class="k">[];</span></td></tr><tr class="hit"> <td class="line">288</td><td class="hits">415</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">289</td><td class="hits">815</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"["</span><span class="k">))</span> <span class="k">return</span> eas<span class="k">;</span></td></tr><tr class="hit"> <td class="line">290</td><td class="hits">15</td><td class="source"> eas<span class="k">[</span><span class="s">0</span><span class="k">]</span> <span class="k">=</span> simple_extended_attr<span class="k">()</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Extended attribute with not content"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">291</td><td class="hits">15</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">292</td><td class="hits">15</td><td class="source"> <span class="k">while</span> <span class="k">(</span>consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">","</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">293</td><td class="hits">2</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">294</td><td class="hits">2</td><td class="source"> eas<span class="k">.</span>push<span class="k">(</span>simple_extended_attr<span class="k">()</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Trailing comma in extended attribute"</span><span class="k">));</span></td></tr><tr class="hit"> <td class="line">295</td><td class="hits">2</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr><td class="line">296</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">297</td><td class="hits">15</td><td class="source"> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"]"</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"No end of extended attribute"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">298</td><td class="hits">15</td><td class="source"> <span class="k">return</span> eas<span class="k">;</span></td></tr><tr><td class="line">299</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">300</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">301</td><td class="hits">47</td><td class="source"> <span class="k">var</span> default_ <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">302</td><td class="hits">11</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">303</td><td class="hits">11</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"="</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">304</td><td class="hits">5</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">305</td><td class="hits">5</td><td class="source"> <span class="k">var</span> def <span class="k">=</span> const_value<span class="k">();</span></td></tr><tr class="hit"> <td class="line">306</td><td class="hits">5</td><td class="source"> <span class="k">if</span> <span class="k">(</span><span class="k">typeof</span> def <span class="k">!==</span> <span class="s">"undefined"</span><span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">307</td><td class="hits">3</td><td class="source"> <span class="k">return</span> def<span class="k">;</span></td></tr><tr><td class="line">308</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">309</td><td class="hits"></td><td class="source"> <span class="k">else</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">310</td><td class="hits">2</td><td class="source"> <span class="k">var</span> str <span class="k">=</span> consume<span class="k">(</span>STR<span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"No value for default"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">311</td><td class="hits">2</td><td class="source"> <span class="k">return</span> str<span class="k">;</span></td></tr><tr><td class="line">312</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">313</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">314</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">315</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">316</td><td class="hits">47</td><td class="source"> <span class="k">var</span> const_ <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">317</td><td class="hits">180</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">318</td><td class="hits">348</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"const"</span><span class="k">))</span> <span class="k">return</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">319</td><td class="hits">12</td><td class="source"> <span class="k">var</span> ret <span class="k">=</span> <span class="k">{</span> type<span class="k">:</span> <span class="s">"const"</span><span class="k">,</span> nullable<span class="k">:</span> <span class="k">false</span> <span class="k">}</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">320</td><td class="hits">12</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">321</td><td class="hits">12</td><td class="source"> <span class="k">var</span> typ <span class="k">=</span> primitive_type<span class="k">();</span></td></tr><tr class="hit"> <td class="line">322</td><td class="hits">12</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>typ<span class="k">)</span> <span class="k">{</span></td></tr><tr class="miss"> <td class="line">323</td><td class="hits">0</td><td class="source"> typ <span class="k">=</span> consume<span class="k">(</span>ID<span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"No type for const"</span><span class="k">);</span></td></tr><tr class="miss"> <td class="line">324</td><td class="hits">0</td><td class="source"> typ <span class="k">=</span> typ<span class="k">.</span>value<span class="k">;</span></td></tr><tr><td class="line">325</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">326</td><td class="hits">12</td><td class="source"> ret<span class="k">.</span>idlType <span class="k">=</span> typ<span class="k">;</span></td></tr><tr class="hit"> <td class="line">327</td><td class="hits">12</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">328</td><td class="hits">12</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"?"</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">329</td><td class="hits">1</td><td class="source"> ret<span class="k">.</span>nullable <span class="k">=</span> <span class="k">true</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">330</td><td class="hits">1</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr><td class="line">331</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">332</td><td class="hits">12</td><td class="source"> <span class="k">var</span> name <span class="k">=</span> consume<span class="k">(</span>ID<span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"No name for const"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">333</td><td class="hits">12</td><td class="source"> ret<span class="k">.</span>name <span class="k">=</span> name<span class="k">.</span>value<span class="k">;</span></td></tr><tr class="hit"> <td class="line">334</td><td class="hits">12</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">335</td><td class="hits">12</td><td class="source"> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"="</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"No value assignment for const"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">336</td><td class="hits">12</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">337</td><td class="hits">12</td><td class="source"> <span class="k">var</span> cnt <span class="k">=</span> const_value<span class="k">();</span></td></tr><tr class="hit"> <td class="line">338</td><td class="hits">24</td><td class="source"> <span class="k">if</span> <span class="k">(</span><span class="k">typeof</span> cnt <span class="k">!==</span> <span class="s">"undefined"</span><span class="k">)</span> ret<span class="k">.</span>value <span class="k">=</span> cnt<span class="k">;</span></td></tr><tr class="miss"> <td class="line">339</td><td class="hits">0</td><td class="source"> <span class="k">else</span> error<span class="k">(</span><span class="s">"No value for const"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">340</td><td class="hits">12</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">341</td><td class="hits">12</td><td class="source"> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">";"</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Unterminated const"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">342</td><td class="hits">12</td><td class="source"> <span class="k">return</span> ret<span class="k">;</span></td></tr><tr><td class="line">343</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">344</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">345</td><td class="hits">47</td><td class="source"> <span class="k">var</span> inheritance <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">346</td><td class="hits">89</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">347</td><td class="hits">89</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">":"</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">348</td><td class="hits">9</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">349</td><td class="hits">9</td><td class="source"> <span class="k">var</span> inh <span class="k">=</span> consume<span class="k">(</span>ID<span class="k">)</span> <span class="k">||</span> error <span class="k">(</span><span class="s">"No type in inheritance"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">350</td><td class="hits">9</td><td class="source"> <span class="k">return</span> inh<span class="k">.</span>value<span class="k">;</span></td></tr><tr><td class="line">351</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">352</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">353</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">354</td><td class="hits">47</td><td class="source"> <span class="k">var</span> operation_rest <span class="k">=</span> <span class="k">function</span> <span class="k">(</span>ret<span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">355</td><td class="hits">56</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">356</td><td class="hits">57</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>ret<span class="k">)</span> ret <span class="k">=</span> <span class="k">{}</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">357</td><td class="hits">56</td><td class="source"> <span class="k">var</span> name <span class="k">=</span> consume<span class="k">(</span>ID<span class="k">);</span></td></tr><tr class="hit"> <td class="line">358</td><td class="hits">56</td><td class="source"> ret<span class="k">.</span>name <span class="k">=</span> name <span class="k">?</span> name<span class="k">.</span>value <span class="k">:</span> <span class="k">null</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">359</td><td class="hits">56</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">360</td><td class="hits">56</td><td class="source"> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"("</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Invalid operation"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">361</td><td class="hits">56</td><td class="source"> ret<span class="k">[</span><span class="s">"arguments"</span><span class="k">]</span> <span class="k">=</span> argument_list<span class="k">();</span></td></tr><tr class="hit"> <td class="line">362</td><td class="hits">56</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">363</td><td class="hits">56</td><td class="source"> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">")"</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Unterminated operation"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">364</td><td class="hits">56</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">365</td><td class="hits">56</td><td class="source"> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">";"</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Unterminated operation"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">366</td><td class="hits">56</td><td class="source"> <span class="k">return</span> ret<span class="k">;</span></td></tr><tr><td class="line">367</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">368</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">369</td><td class="hits">47</td><td class="source"> <span class="k">var</span> callback <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">370</td><td class="hits">144</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">371</td><td class="hits">144</td><td class="source"> <span class="k">var</span> ret<span class="k">;</span></td></tr><tr class="hit"> <td class="line">372</td><td class="hits">286</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"callback"</span><span class="k">))</span> <span class="k">return</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">373</td><td class="hits">2</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">374</td><td class="hits">2</td><td class="source"> <span class="k">var</span> tok <span class="k">=</span> consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"interface"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">375</td><td class="hits">2</td><td class="source"> <span class="k">if</span> <span class="k">(</span>tok<span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">376</td><td class="hits">1</td><td class="source"> tokens<span class="k">.</span>unshift<span class="k">(</span>tok<span class="k">);</span></td></tr><tr class="hit"> <td class="line">377</td><td class="hits">1</td><td class="source"> ret <span class="k">=</span> interface_<span class="k">();</span></td></tr><tr class="hit"> <td class="line">378</td><td class="hits">1</td><td class="source"> ret<span class="k">.</span>type <span class="k">=</span> <span class="s">"callback interface"</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">379</td><td class="hits">1</td><td class="source"> <span class="k">return</span> ret<span class="k">;</span></td></tr><tr><td class="line">380</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">381</td><td class="hits">1</td><td class="source"> <span class="k">var</span> name <span class="k">=</span> consume<span class="k">(</span>ID<span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"No name for callback"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">382</td><td class="hits">1</td><td class="source"> ret <span class="k">=</span> <span class="k">{</span> type<span class="k">:</span> <span class="s">"callback"</span><span class="k">,</span> name<span class="k">:</span> name<span class="k">.</span>value <span class="k">}</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">383</td><td class="hits">1</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">384</td><td class="hits">1</td><td class="source"> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"="</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"No assignment in callback"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">385</td><td class="hits">1</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">386</td><td class="hits">1</td><td class="source"> ret<span class="k">.</span>idlType <span class="k">=</span> return_type<span class="k">();</span></td></tr><tr class="hit"> <td class="line">387</td><td class="hits">1</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">388</td><td class="hits">1</td><td class="source"> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"("</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"No arguments in callback"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">389</td><td class="hits">1</td><td class="source"> ret<span class="k">[</span><span class="s">"arguments"</span><span class="k">]</span> <span class="k">=</span> argument_list<span class="k">();</span></td></tr><tr class="hit"> <td class="line">390</td><td class="hits">1</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">391</td><td class="hits">1</td><td class="source"> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">")"</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Unterminated callback"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">392</td><td class="hits">1</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">393</td><td class="hits">1</td><td class="source"> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">";"</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Unterminated callback"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">394</td><td class="hits">1</td><td class="source"> <span class="k">return</span> ret<span class="k">;</span></td></tr><tr><td class="line">395</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">396</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">397</td><td class="hits">47</td><td class="source"> <span class="k">var</span> attribute <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">398</td><td class="hits">154</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">399</td><td class="hits">154</td><td class="source"> <span class="k">var</span> grabbed <span class="k">=</span> <span class="k">[]</span></td></tr><tr><td class="line">400</td><td class="hits"></td><td class="source"> <span class="k">,</span> ret <span class="k">=</span> <span class="k">{</span></td></tr><tr><td class="line">401</td><td class="hits"></td><td class="source"> type<span class="k">:</span> <span class="s">"attribute"</span></td></tr><tr><td class="line">402</td><td class="hits"></td><td class="source"> <span class="k">,</span> <span class="s">"static"</span><span class="k">:</span> <span class="k">false</span></td></tr><tr><td class="line">403</td><td class="hits"></td><td class="source"> <span class="k">,</span> stringifier<span class="k">:</span> <span class="k">false</span></td></tr><tr><td class="line">404</td><td class="hits"></td><td class="source"> <span class="k">,</span> inherit<span class="k">:</span> <span class="k">false</span></td></tr><tr><td class="line">405</td><td class="hits"></td><td class="source"> <span class="k">,</span> readonly<span class="k">:</span> <span class="k">false</span></td></tr><tr><td class="line">406</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">407</td><td class="hits">154</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"static"</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">408</td><td class="hits">2</td><td class="source"> ret<span class="k">[</span><span class="s">"static"</span><span class="k">]</span> <span class="k">=</span> <span class="k">true</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">409</td><td class="hits">2</td><td class="source"> grabbed<span class="k">.</span>push<span class="k">(</span>last_token<span class="k">);</span></td></tr><tr><td class="line">410</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">411</td><td class="hits">152</td><td class="source"> <span class="k">else</span> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"stringifier"</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">412</td><td class="hits">4</td><td class="source"> ret<span class="k">.</span>stringifier <span class="k">=</span> <span class="k">true</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">413</td><td class="hits">4</td><td class="source"> grabbed<span class="k">.</span>push<span class="k">(</span>last_token<span class="k">);</span></td></tr><tr><td class="line">414</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">415</td><td class="hits">154</td><td class="source"> <span class="k">var</span> w <span class="k">=</span> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">416</td><td class="hits">159</td><td class="source"> <span class="k">if</span> <span class="k">(</span>w<span class="k">)</span> grabbed<span class="k">.</span>push<span class="k">(</span>w<span class="k">);</span></td></tr><tr class="hit"> <td class="line">417</td><td class="hits">154</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"inherit"</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">418</td><td class="hits">1</td><td class="source"> <span class="k">if</span> <span class="k">(</span>ret<span class="k">[</span><span class="s">"static"</span><span class="k">]</span> <span class="k">||</span> ret<span class="k">.</span>stringifier<span class="k">)</span> error<span class="k">(</span><span class="s">"Cannot have a static or stringifier inherit"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">419</td><td class="hits">1</td><td class="source"> ret<span class="k">.</span>inherit <span class="k">=</span> <span class="k">true</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">420</td><td class="hits">1</td><td class="source"> grabbed<span class="k">.</span>push<span class="k">(</span>last_token<span class="k">);</span></td></tr><tr class="hit"> <td class="line">421</td><td class="hits">1</td><td class="source"> <span class="k">var</span> w <span class="k">=</span> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">422</td><td class="hits">2</td><td class="source"> <span class="k">if</span> <span class="k">(</span>w<span class="k">)</span> grabbed<span class="k">.</span>push<span class="k">(</span>w<span class="k">);</span></td></tr><tr><td class="line">423</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">424</td><td class="hits">154</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"readonly"</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">425</td><td class="hits">32</td><td class="source"> ret<span class="k">.</span>readonly <span class="k">=</span> <span class="k">true</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">426</td><td class="hits">32</td><td class="source"> grabbed<span class="k">.</span>push<span class="k">(</span>last_token<span class="k">);</span></td></tr><tr class="hit"> <td class="line">427</td><td class="hits">32</td><td class="source"> <span class="k">var</span> w <span class="k">=</span> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">428</td><td class="hits">64</td><td class="source"> <span class="k">if</span> <span class="k">(</span>w<span class="k">)</span> grabbed<span class="k">.</span>push<span class="k">(</span>w<span class="k">);</span></td></tr><tr><td class="line">429</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">430</td><td class="hits">154</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"attribute"</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">431</td><td class="hits">60</td><td class="source"> tokens <span class="k">=</span> grabbed<span class="k">.</span>concat<span class="k">(</span>tokens<span class="k">);</span></td></tr><tr class="hit"> <td class="line">432</td><td class="hits">60</td><td class="source"> <span class="k">return</span><span class="k">;</span></td></tr><tr><td class="line">433</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">434</td><td class="hits">94</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">435</td><td class="hits">94</td><td class="source"> ret<span class="k">.</span>idlType <span class="k">=</span> type<span class="k">()</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"No type in attribute"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">436</td><td class="hits">94</td><td class="source"> <span class="k">if</span> <span class="k">(</span>ret<span class="k">.</span>idlType<span class="k">.</span>sequence<span class="k">)</span> error<span class="k">(</span><span class="s">"Attributes cannot accept sequence types"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">437</td><td class="hits">94</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">438</td><td class="hits">94</td><td class="source"> <span class="k">var</span> name <span class="k">=</span> consume<span class="k">(</span>ID<span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"No name in attribute"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">439</td><td class="hits">94</td><td class="source"> ret<span class="k">.</span>name <span class="k">=</span> name<span class="k">.</span>value<span class="k">;</span></td></tr><tr class="hit"> <td class="line">440</td><td class="hits">94</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">441</td><td class="hits">94</td><td class="source"> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">";"</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Unterminated attribute"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">442</td><td class="hits">94</td><td class="source"> <span class="k">return</span> ret<span class="k">;</span></td></tr><tr><td class="line">443</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">444</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">445</td><td class="hits">47</td><td class="source"> <span class="k">var</span> return_type <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">446</td><td class="hits">61</td><td class="source"> <span class="k">var</span> typ <span class="k">=</span> type<span class="k">();</span></td></tr><tr class="hit"> <td class="line">447</td><td class="hits">61</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>typ<span class="k">)</span> <span class="k">{</span></td></tr><tr class="miss"> <td class="line">448</td><td class="hits">0</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"void"</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="miss"> <td class="line">449</td><td class="hits">0</td><td class="source"> <span class="k">return</span> <span class="s">"void"</span><span class="k">;</span></td></tr><tr><td class="line">450</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="miss"> <td class="line">451</td><td class="hits">0</td><td class="source"> <span class="k">else</span> error<span class="k">(</span><span class="s">"No return type"</span><span class="k">);</span></td></tr><tr><td class="line">452</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">453</td><td class="hits">61</td><td class="source"> <span class="k">return</span> typ<span class="k">;</span></td></tr><tr><td class="line">454</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">455</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">456</td><td class="hits">47</td><td class="source"> <span class="k">var</span> operation <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">457</td><td class="hits">60</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">458</td><td class="hits">60</td><td class="source"> <span class="k">var</span> ret <span class="k">=</span> <span class="k">{</span></td></tr><tr><td class="line">459</td><td class="hits"></td><td class="source"> type<span class="k">:</span> <span class="s">"operation"</span></td></tr><tr><td class="line">460</td><td class="hits"></td><td class="source"> <span class="k">,</span> getter<span class="k">:</span> <span class="k">false</span></td></tr><tr><td class="line">461</td><td class="hits"></td><td class="source"> <span class="k">,</span> setter<span class="k">:</span> <span class="k">false</span></td></tr><tr><td class="line">462</td><td class="hits"></td><td class="source"> <span class="k">,</span> creator<span class="k">:</span> <span class="k">false</span></td></tr><tr><td class="line">463</td><td class="hits"></td><td class="source"> <span class="k">,</span> deleter<span class="k">:</span> <span class="k">false</span></td></tr><tr><td class="line">464</td><td class="hits"></td><td class="source"> <span class="k">,</span> legacycaller<span class="k">:</span> <span class="k">false</span></td></tr><tr><td class="line">465</td><td class="hits"></td><td class="source"> <span class="k">,</span> <span class="s">"static"</span><span class="k">:</span> <span class="k">false</span></td></tr><tr><td class="line">466</td><td class="hits"></td><td class="source"> <span class="k">,</span> stringifier<span class="k">:</span> <span class="k">false</span></td></tr><tr><td class="line">467</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">468</td><td class="hits">60</td><td class="source"> <span class="k">while</span> <span class="k">(</span><span class="k">true</span><span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">469</td><td class="hits">78</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">470</td><td class="hits">87</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"getter"</span><span class="k">))</span> ret<span class="k">.</span>getter <span class="k">=</span> <span class="k">true</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">471</td><td class="hits">74</td><td class="source"> <span class="k">else</span> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"setter"</span><span class="k">))</span> ret<span class="k">.</span>setter <span class="k">=</span> <span class="k">true</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">472</td><td class="hits">65</td><td class="source"> <span class="k">else</span> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"creator"</span><span class="k">))</span> ret<span class="k">.</span>creator <span class="k">=</span> <span class="k">true</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">473</td><td class="hits">65</td><td class="source"> <span class="k">else</span> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"deleter"</span><span class="k">))</span> ret<span class="k">.</span>deleter <span class="k">=</span> <span class="k">true</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">474</td><td class="hits">62</td><td class="source"> <span class="k">else</span> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"legacycaller"</span><span class="k">))</span> ret<span class="k">.</span>legacycaller <span class="k">=</span> <span class="k">true</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">475</td><td class="hits">60</td><td class="source"> <span class="k">else</span> <span class="k">break</span><span class="k">;</span></td></tr><tr><td class="line">476</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">477</td><td class="hits">60</td><td class="source"> <span class="k">if</span> <span class="k">(</span>ret<span class="k">.</span>getter <span class="k">||</span> ret<span class="k">.</span>setter <span class="k">||</span> ret<span class="k">.</span>creator <span class="k">||</span> ret<span class="k">.</span>deleter <span class="k">||</span> ret<span class="k">.</span>legacycaller<span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">478</td><td class="hits">17</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">479</td><td class="hits">17</td><td class="source"> ret<span class="k">.</span>idlType <span class="k">=</span> return_type<span class="k">();</span></td></tr><tr class="hit"> <td class="line">480</td><td class="hits">17</td><td class="source"> operation_rest<span class="k">(</span>ret<span class="k">);</span></td></tr><tr class="hit"> <td class="line">481</td><td class="hits">17</td><td class="source"> <span class="k">return</span> ret<span class="k">;</span></td></tr><tr><td class="line">482</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">483</td><td class="hits">43</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"static"</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">484</td><td class="hits">1</td><td class="source"> ret<span class="k">[</span><span class="s">"static"</span><span class="k">]</span> <span class="k">=</span> <span class="k">true</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">485</td><td class="hits">1</td><td class="source"> ret<span class="k">.</span>idlType <span class="k">=</span> return_type<span class="k">();</span></td></tr><tr class="hit"> <td class="line">486</td><td class="hits">1</td><td class="source"> operation_rest<span class="k">(</span>ret<span class="k">);</span></td></tr><tr class="hit"> <td class="line">487</td><td class="hits">1</td><td class="source"> <span class="k">return</span> ret<span class="k">;</span></td></tr><tr><td class="line">488</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">489</td><td class="hits">42</td><td class="source"> <span class="k">else</span> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"stringifier"</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">490</td><td class="hits">3</td><td class="source"> ret<span class="k">.</span>stringifier <span class="k">=</span> <span class="k">true</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">491</td><td class="hits">3</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">492</td><td class="hits">4</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">";"</span><span class="k">))</span> <span class="k">return</span> ret<span class="k">;</span></td></tr><tr class="hit"> <td class="line">493</td><td class="hits">2</td><td class="source"> ret<span class="k">.</span>idlType <span class="k">=</span> return_type<span class="k">();</span></td></tr><tr class="hit"> <td class="line">494</td><td class="hits">2</td><td class="source"> operation_rest<span class="k">(</span>ret<span class="k">);</span></td></tr><tr class="hit"> <td class="line">495</td><td class="hits">2</td><td class="source"> <span class="k">return</span> ret<span class="k">;</span></td></tr><tr><td class="line">496</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">497</td><td class="hits">39</td><td class="source"> ret<span class="k">.</span>idlType <span class="k">=</span> return_type<span class="k">();</span></td></tr><tr class="hit"> <td class="line">498</td><td class="hits">39</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">499</td><td class="hits">39</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"iterator"</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">500</td><td class="hits">4</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">501</td><td class="hits">4</td><td class="source"> ret<span class="k">.</span>type <span class="k">=</span> <span class="s">"iterator"</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">502</td><td class="hits">4</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"object"</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">503</td><td class="hits">1</td><td class="source"> ret<span class="k">.</span>iteratorObject <span class="k">=</span> <span class="s">"object"</span><span class="k">;</span></td></tr><tr><td class="line">504</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">505</td><td class="hits">3</td><td class="source"> <span class="k">else</span> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"="</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">506</td><td class="hits">2</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">507</td><td class="hits">2</td><td class="source"> <span class="k">var</span> name <span class="k">=</span> consume<span class="k">(</span>ID<span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"No right hand side in iterator"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">508</td><td class="hits">2</td><td class="source"> ret<span class="k">.</span>iteratorObject <span class="k">=</span> name<span class="k">.</span>value<span class="k">;</span></td></tr><tr><td class="line">509</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">510</td><td class="hits">4</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">511</td><td class="hits">4</td><td class="source"> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">";"</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Unterminated iterator"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">512</td><td class="hits">4</td><td class="source"> <span class="k">return</span> ret<span class="k">;</span></td></tr><tr><td class="line">513</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">514</td><td class="hits"></td><td class="source"> <span class="k">else</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">515</td><td class="hits">35</td><td class="source"> operation_rest<span class="k">(</span>ret<span class="k">);</span></td></tr><tr class="hit"> <td class="line">516</td><td class="hits">35</td><td class="source"> <span class="k">return</span> ret<span class="k">;</span></td></tr><tr><td class="line">517</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">518</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">519</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">520</td><td class="hits">47</td><td class="source"> <span class="k">var</span> identifiers <span class="k">=</span> <span class="k">function</span> <span class="k">(</span>arr<span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">521</td><td class="hits">5</td><td class="source"> <span class="k">while</span> <span class="k">(</span><span class="k">true</span><span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">522</td><td class="hits">11</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">523</td><td class="hits">11</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">","</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">524</td><td class="hits">6</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">525</td><td class="hits">6</td><td class="source"> <span class="k">var</span> name <span class="k">=</span> consume<span class="k">(</span>ID<span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Trailing comma in identifiers list"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">526</td><td class="hits">6</td><td class="source"> arr<span class="k">.</span>push<span class="k">(</span>name<span class="k">.</span>value<span class="k">);</span></td></tr><tr><td class="line">527</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">528</td><td class="hits">5</td><td class="source"> <span class="k">else</span> <span class="k">break</span><span class="k">;</span></td></tr><tr><td class="line">529</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">530</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">531</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">532</td><td class="hits">47</td><td class="source"> <span class="k">var</span> serialiser <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">533</td><td class="hits">164</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">534</td><td class="hits">318</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"serializer"</span><span class="k">))</span> <span class="k">return</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">535</td><td class="hits">10</td><td class="source"> <span class="k">var</span> ret <span class="k">=</span> <span class="k">{</span> type<span class="k">:</span> <span class="s">"serializer"</span> <span class="k">}</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">536</td><td class="hits">10</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">537</td><td class="hits">10</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"="</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">538</td><td class="hits">8</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">539</td><td class="hits">8</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"{"</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">540</td><td class="hits">5</td><td class="source"> ret<span class="k">.</span>patternMap <span class="k">=</span> <span class="k">true</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">541</td><td class="hits">5</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">542</td><td class="hits">5</td><td class="source"> <span class="k">var</span> id <span class="k">=</span> consume<span class="k">(</span>ID<span class="k">);</span></td></tr><tr class="hit"> <td class="line">543</td><td class="hits">5</td><td class="source"> <span class="k">if</span> <span class="k">(</span>id <span class="k">&amp;&amp;</span> id<span class="k">.</span>value <span class="k">===</span> <span class="s">"getter"</span><span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">544</td><td class="hits">1</td><td class="source"> ret<span class="k">.</span>names <span class="k">=</span> <span class="k">[</span><span class="s">"getter"</span><span class="k">];</span></td></tr><tr><td class="line">545</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">546</td><td class="hits">4</td><td class="source"> <span class="k">else</span> <span class="k">if</span> <span class="k">(</span>id <span class="k">&amp;&amp;</span> id<span class="k">.</span>value <span class="k">===</span> <span class="s">"inherit"</span><span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">547</td><td class="hits">2</td><td class="source"> ret<span class="k">.</span>names <span class="k">=</span> <span class="k">[</span><span class="s">"inherit"</span><span class="k">];</span></td></tr><tr class="hit"> <td class="line">548</td><td class="hits">2</td><td class="source"> identifiers<span class="k">(</span>ret<span class="k">.</span>names<span class="k">);</span></td></tr><tr><td class="line">549</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">550</td><td class="hits">2</td><td class="source"> <span class="k">else</span> <span class="k">if</span> <span class="k">(</span>id<span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">551</td><td class="hits">2</td><td class="source"> ret<span class="k">.</span>names <span class="k">=</span> <span class="k">[</span>id<span class="k">.</span>value<span class="k">];</span></td></tr><tr class="hit"> <td class="line">552</td><td class="hits">2</td><td class="source"> identifiers<span class="k">(</span>ret<span class="k">.</span>names<span class="k">);</span></td></tr><tr><td class="line">553</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">554</td><td class="hits"></td><td class="source"> <span class="k">else</span> <span class="k">{</span></td></tr><tr class="miss"> <td class="line">555</td><td class="hits">0</td><td class="source"> ret<span class="k">.</span>names <span class="k">=</span> <span class="k">[];</span></td></tr><tr><td class="line">556</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">557</td><td class="hits">5</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">558</td><td class="hits">5</td><td class="source"> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"}"</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Unterminated serializer pattern map"</span><span class="k">);</span></td></tr><tr><td class="line">559</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">560</td><td class="hits">3</td><td class="source"> <span class="k">else</span> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"["</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">561</td><td class="hits">2</td><td class="source"> ret<span class="k">.</span>patternList <span class="k">=</span> <span class="k">true</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">562</td><td class="hits">2</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">563</td><td class="hits">2</td><td class="source"> <span class="k">var</span> id <span class="k">=</span> consume<span class="k">(</span>ID<span class="k">);</span></td></tr><tr class="hit"> <td class="line">564</td><td class="hits">2</td><td class="source"> <span class="k">if</span> <span class="k">(</span>id <span class="k">&amp;&amp;</span> id<span class="k">.</span>value <span class="k">===</span> <span class="s">"getter"</span><span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">565</td><td class="hits">1</td><td class="source"> ret<span class="k">.</span>names <span class="k">=</span> <span class="k">[</span><span class="s">"getter"</span><span class="k">];</span></td></tr><tr><td class="line">566</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">567</td><td class="hits">1</td><td class="source"> <span class="k">else</span> <span class="k">if</span> <span class="k">(</span>id<span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">568</td><td class="hits">1</td><td class="source"> ret<span class="k">.</span>names <span class="k">=</span> <span class="k">[</span>id<span class="k">.</span>value<span class="k">];</span></td></tr><tr class="hit"> <td class="line">569</td><td class="hits">1</td><td class="source"> identifiers<span class="k">(</span>ret<span class="k">.</span>names<span class="k">);</span></td></tr><tr><td class="line">570</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">571</td><td class="hits"></td><td class="source"> <span class="k">else</span> <span class="k">{</span></td></tr><tr class="miss"> <td class="line">572</td><td class="hits">0</td><td class="source"> ret<span class="k">.</span>names <span class="k">=</span> <span class="k">[];</span></td></tr><tr><td class="line">573</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">574</td><td class="hits">2</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">575</td><td class="hits">2</td><td class="source"> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"]"</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Unterminated serializer pattern list"</span><span class="k">);</span></td></tr><tr><td class="line">576</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">577</td><td class="hits"></td><td class="source"> <span class="k">else</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">578</td><td class="hits">1</td><td class="source"> <span class="k">var</span> name <span class="k">=</span> consume<span class="k">(</span>ID<span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Invalid serializer"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">579</td><td class="hits">1</td><td class="source"> ret<span class="k">.</span>name <span class="k">=</span> name<span class="k">.</span>value<span class="k">;</span></td></tr><tr><td class="line">580</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">581</td><td class="hits">8</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">582</td><td class="hits">8</td><td class="source"> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">";"</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Unterminated serializer"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">583</td><td class="hits">8</td><td class="source"> <span class="k">return</span> ret<span class="k">;</span></td></tr><tr><td class="line">584</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">585</td><td class="hits">2</td><td class="source"> <span class="k">else</span> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">";"</span><span class="k">))</span> <span class="k">{</span></td></tr><tr><td class="line">586</td><td class="hits"></td><td class="source"> <span class="c">// noop, just parsing</span></td></tr><tr><td class="line">587</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">588</td><td class="hits"></td><td class="source"> <span class="k">else</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">589</td><td class="hits">1</td><td class="source"> ret<span class="k">.</span>idlType <span class="k">=</span> return_type<span class="k">();</span></td></tr><tr class="hit"> <td class="line">590</td><td class="hits">1</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">591</td><td class="hits">1</td><td class="source"> ret<span class="k">.</span>operation <span class="k">=</span> operation_rest<span class="k">();</span></td></tr><tr><td class="line">592</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">593</td><td class="hits">2</td><td class="source"> <span class="k">return</span> ret<span class="k">;</span></td></tr><tr><td class="line">594</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">595</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">596</td><td class="hits">47</td><td class="source"> <span class="k">var</span> interface_ <span class="k">=</span> <span class="k">function</span> <span class="k">(</span>isPartial<span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">597</td><td class="hits">144</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">598</td><td class="hits">210</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"interface"</span><span class="k">))</span> <span class="k">return</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">599</td><td class="hits">78</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">600</td><td class="hits">78</td><td class="source"> <span class="k">var</span> name <span class="k">=</span> consume<span class="k">(</span>ID<span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"No name for interface"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">601</td><td class="hits">78</td><td class="source"> <span class="k">var</span> ret <span class="k">=</span> <span class="k">{</span></td></tr><tr><td class="line">602</td><td class="hits"></td><td class="source"> type<span class="k">:</span> <span class="s">"interface"</span></td></tr><tr><td class="line">603</td><td class="hits"></td><td class="source"> <span class="k">,</span> name<span class="k">:</span> name<span class="k">.</span>value</td></tr><tr><td class="line">604</td><td class="hits"></td><td class="source"> <span class="k">,</span> partial<span class="k">:</span> <span class="k">false</span></td></tr><tr><td class="line">605</td><td class="hits"></td><td class="source"> <span class="k">,</span> members<span class="k">:</span> <span class="k">[]</span></td></tr><tr><td class="line">606</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">607</td><td class="hits">155</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>isPartial<span class="k">)</span> ret<span class="k">.</span>inheritance <span class="k">=</span> inheritance<span class="k">()</span> <span class="k">||</span> <span class="k">null</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">608</td><td class="hits">78</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">609</td><td class="hits">78</td><td class="source"> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"{"</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Bodyless interface"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">610</td><td class="hits">78</td><td class="source"> <span class="k">while</span> <span class="k">(</span><span class="k">true</span><span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">611</td><td class="hits">251</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">612</td><td class="hits">251</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"}"</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">613</td><td class="hits">78</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">614</td><td class="hits">78</td><td class="source"> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">";"</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Missing semicolon after interface"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">615</td><td class="hits">78</td><td class="source"> <span class="k">return</span> ret<span class="k">;</span></td></tr><tr><td class="line">616</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">617</td><td class="hits">173</td><td class="source"> <span class="k">var</span> ea <span class="k">=</span> extended_attrs<span class="k">();</span></td></tr><tr class="hit"> <td class="line">618</td><td class="hits">173</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">619</td><td class="hits">173</td><td class="source"> <span class="k">var</span> cnt <span class="k">=</span> const_<span class="k">();</span></td></tr><tr class="hit"> <td class="line">620</td><td class="hits">173</td><td class="source"> <span class="k">if</span> <span class="k">(</span>cnt<span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">621</td><td class="hits">9</td><td class="source"> cnt<span class="k">.</span>extAttrs <span class="k">=</span> ea<span class="k">;</span></td></tr><tr class="hit"> <td class="line">622</td><td class="hits">9</td><td class="source"> ret<span class="k">.</span>members<span class="k">.</span>push<span class="k">(</span>cnt<span class="k">);</span></td></tr><tr class="hit"> <td class="line">623</td><td class="hits">9</td><td class="source"> <span class="k">continue</span><span class="k">;</span></td></tr><tr><td class="line">624</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">625</td><td class="hits">164</td><td class="source"> <span class="k">var</span> mem <span class="k">=</span> serialiser<span class="k">()</span> <span class="k">||</span> attribute<span class="k">()</span> <span class="k">||</span> operation<span class="k">()</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Unknown member"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">626</td><td class="hits">164</td><td class="source"> mem<span class="k">.</span>extAttrs <span class="k">=</span> ea<span class="k">;</span></td></tr><tr class="hit"> <td class="line">627</td><td class="hits">164</td><td class="source"> ret<span class="k">.</span>members<span class="k">.</span>push<span class="k">(</span>mem<span class="k">);</span></td></tr><tr><td class="line">628</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">629</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">630</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">631</td><td class="hits">47</td><td class="source"> <span class="k">var</span> partial <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">632</td><td class="hits">66</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">633</td><td class="hits">130</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"partial"</span><span class="k">))</span> <span class="k">return</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">634</td><td class="hits">2</td><td class="source"> <span class="k">var</span> thing <span class="k">=</span> dictionary<span class="k">(</span><span class="k">true</span><span class="k">)</span> <span class="k">||</span> interface_<span class="k">(</span><span class="k">true</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Partial doesn't apply to anything"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">635</td><td class="hits">2</td><td class="source"> thing<span class="k">.</span>partial <span class="k">=</span> <span class="k">true</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">636</td><td class="hits">2</td><td class="source"> <span class="k">return</span> thing<span class="k">;</span></td></tr><tr><td class="line">637</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">638</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">639</td><td class="hits">47</td><td class="source"> <span class="k">var</span> dictionary <span class="k">=</span> <span class="k">function</span> <span class="k">(</span>isPartial<span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">640</td><td class="hits">66</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">641</td><td class="hits">128</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"dictionary"</span><span class="k">))</span> <span class="k">return</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">642</td><td class="hits">4</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">643</td><td class="hits">4</td><td class="source"> <span class="k">var</span> name <span class="k">=</span> consume<span class="k">(</span>ID<span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"No name for dictionary"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">644</td><td class="hits">4</td><td class="source"> <span class="k">var</span> ret <span class="k">=</span> <span class="k">{</span></td></tr><tr><td class="line">645</td><td class="hits"></td><td class="source"> type<span class="k">:</span> <span class="s">"dictionary"</span></td></tr><tr><td class="line">646</td><td class="hits"></td><td class="source"> <span class="k">,</span> name<span class="k">:</span> name<span class="k">.</span>value</td></tr><tr><td class="line">647</td><td class="hits"></td><td class="source"> <span class="k">,</span> partial<span class="k">:</span> <span class="k">false</span></td></tr><tr><td class="line">648</td><td class="hits"></td><td class="source"> <span class="k">,</span> members<span class="k">:</span> <span class="k">[]</span></td></tr><tr><td class="line">649</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">650</td><td class="hits">7</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>isPartial<span class="k">)</span> ret<span class="k">.</span>inheritance <span class="k">=</span> inheritance<span class="k">()</span> <span class="k">||</span> <span class="k">null</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">651</td><td class="hits">4</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">652</td><td class="hits">4</td><td class="source"> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"{"</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Bodyless dictionary"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">653</td><td class="hits">4</td><td class="source"> <span class="k">while</span> <span class="k">(</span><span class="k">true</span><span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">654</td><td class="hits">13</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">655</td><td class="hits">13</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"}"</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">656</td><td class="hits">4</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">657</td><td class="hits">4</td><td class="source"> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">";"</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Missing semicolon after dictionary"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">658</td><td class="hits">4</td><td class="source"> <span class="k">return</span> ret<span class="k">;</span></td></tr><tr><td class="line">659</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">660</td><td class="hits">9</td><td class="source"> <span class="k">var</span> ea <span class="k">=</span> extended_attrs<span class="k">();</span></td></tr><tr class="hit"> <td class="line">661</td><td class="hits">9</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">662</td><td class="hits">9</td><td class="source"> <span class="k">var</span> typ <span class="k">=</span> type<span class="k">()</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"No type for dictionary member"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">663</td><td class="hits">9</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">664</td><td class="hits">9</td><td class="source"> <span class="k">var</span> name <span class="k">=</span> consume<span class="k">(</span>ID<span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"No name for dictionary member"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">665</td><td class="hits">9</td><td class="source"> ret<span class="k">.</span>members<span class="k">.</span>push<span class="k">(</span><span class="k">{</span></td></tr><tr><td class="line">666</td><td class="hits"></td><td class="source"> type<span class="k">:</span> <span class="s">"field"</span></td></tr><tr><td class="line">667</td><td class="hits"></td><td class="source"> <span class="k">,</span> name<span class="k">:</span> name<span class="k">.</span>value</td></tr><tr><td class="line">668</td><td class="hits"></td><td class="source"> <span class="k">,</span> idlType<span class="k">:</span> typ</td></tr><tr><td class="line">669</td><td class="hits"></td><td class="source"> <span class="k">,</span> extAttrs<span class="k">:</span> ea</td></tr><tr><td class="line">670</td><td class="hits"></td><td class="source"> <span class="k">,</span> <span class="s">"default"</span><span class="k">:</span> default_<span class="k">()</span></td></tr><tr><td class="line">671</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">672</td><td class="hits">9</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">673</td><td class="hits">9</td><td class="source"> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">";"</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Unterminated dictionary member"</span><span class="k">);</span></td></tr><tr><td class="line">674</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">675</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">676</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">677</td><td class="hits">47</td><td class="source"> <span class="k">var</span> exception <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">678</td><td class="hits">61</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">679</td><td class="hits">113</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"exception"</span><span class="k">))</span> <span class="k">return</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">680</td><td class="hits">9</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">681</td><td class="hits">9</td><td class="source"> <span class="k">var</span> name <span class="k">=</span> consume<span class="k">(</span>ID<span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"No name for exception"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">682</td><td class="hits">9</td><td class="source"> <span class="k">var</span> ret <span class="k">=</span> <span class="k">{</span></td></tr><tr><td class="line">683</td><td class="hits"></td><td class="source"> type<span class="k">:</span> <span class="s">"exception"</span></td></tr><tr><td class="line">684</td><td class="hits"></td><td class="source"> <span class="k">,</span> name<span class="k">:</span> name<span class="k">.</span>value</td></tr><tr><td class="line">685</td><td class="hits"></td><td class="source"> <span class="k">,</span> members<span class="k">:</span> <span class="k">[]</span></td></tr><tr><td class="line">686</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">687</td><td class="hits">9</td><td class="source"> ret<span class="k">.</span>inheritance <span class="k">=</span> inheritance<span class="k">()</span> <span class="k">||</span> <span class="k">null</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">688</td><td class="hits">9</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">689</td><td class="hits">9</td><td class="source"> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"{"</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Bodyless exception"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">690</td><td class="hits">9</td><td class="source"> <span class="k">while</span> <span class="k">(</span><span class="k">true</span><span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">691</td><td class="hits">16</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">692</td><td class="hits">16</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"}"</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">693</td><td class="hits">9</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">694</td><td class="hits">9</td><td class="source"> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">";"</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Missing semicolon after exception"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">695</td><td class="hits">9</td><td class="source"> <span class="k">return</span> ret<span class="k">;</span></td></tr><tr><td class="line">696</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">697</td><td class="hits">7</td><td class="source"> <span class="k">var</span> ea <span class="k">=</span> extended_attrs<span class="k">();</span></td></tr><tr class="hit"> <td class="line">698</td><td class="hits">7</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">699</td><td class="hits">7</td><td class="source"> <span class="k">var</span> cnt <span class="k">=</span> const_<span class="k">();</span></td></tr><tr class="hit"> <td class="line">700</td><td class="hits">7</td><td class="source"> <span class="k">if</span> <span class="k">(</span>cnt<span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">701</td><td class="hits">3</td><td class="source"> cnt<span class="k">.</span>extAttrs <span class="k">=</span> ea<span class="k">;</span></td></tr><tr class="hit"> <td class="line">702</td><td class="hits">3</td><td class="source"> ret<span class="k">.</span>members<span class="k">.</span>push<span class="k">(</span>cnt<span class="k">);</span></td></tr><tr><td class="line">703</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">704</td><td class="hits"></td><td class="source"> <span class="k">else</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">705</td><td class="hits">4</td><td class="source"> <span class="k">var</span> typ <span class="k">=</span> type<span class="k">();</span></td></tr><tr class="hit"> <td class="line">706</td><td class="hits">4</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">707</td><td class="hits">4</td><td class="source"> <span class="k">var</span> name <span class="k">=</span> consume<span class="k">(</span>ID<span class="k">);</span></td></tr><tr class="hit"> <td class="line">708</td><td class="hits">4</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">709</td><td class="hits">4</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>typ <span class="k">||</span> <span class="k">!</span>name <span class="k">||</span> <span class="k">!</span>consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">";"</span><span class="k">))</span> error<span class="k">(</span><span class="s">"Unknown member in exception body"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">710</td><td class="hits">4</td><td class="source"> ret<span class="k">.</span>members<span class="k">.</span>push<span class="k">(</span><span class="k">{</span></td></tr><tr><td class="line">711</td><td class="hits"></td><td class="source"> type<span class="k">:</span> <span class="s">"field"</span></td></tr><tr><td class="line">712</td><td class="hits"></td><td class="source"> <span class="k">,</span> name<span class="k">:</span> name<span class="k">.</span>value</td></tr><tr><td class="line">713</td><td class="hits"></td><td class="source"> <span class="k">,</span> idlType<span class="k">:</span> typ</td></tr><tr><td class="line">714</td><td class="hits"></td><td class="source"> <span class="k">,</span> extAttrs<span class="k">:</span> ea</td></tr><tr><td class="line">715</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">);</span></td></tr><tr><td class="line">716</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">717</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">718</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">719</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">720</td><td class="hits">47</td><td class="source"> <span class="k">var</span> enum_ <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">721</td><td class="hits">52</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">722</td><td class="hits">103</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"enum"</span><span class="k">))</span> <span class="k">return</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">723</td><td class="hits">1</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">724</td><td class="hits">1</td><td class="source"> <span class="k">var</span> name <span class="k">=</span> consume<span class="k">(</span>ID<span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"No name for enum"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">725</td><td class="hits">1</td><td class="source"> <span class="k">var</span> ret <span class="k">=</span> <span class="k">{</span></td></tr><tr><td class="line">726</td><td class="hits"></td><td class="source"> type<span class="k">:</span> <span class="s">"enum"</span></td></tr><tr><td class="line">727</td><td class="hits"></td><td class="source"> <span class="k">,</span> name<span class="k">:</span> name<span class="k">.</span>value</td></tr><tr><td class="line">728</td><td class="hits"></td><td class="source"> <span class="k">,</span> values<span class="k">:</span> <span class="k">[]</span></td></tr><tr><td class="line">729</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">730</td><td class="hits">1</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">731</td><td class="hits">1</td><td class="source"> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"{"</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"No curly for enum"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">732</td><td class="hits">1</td><td class="source"> <span class="k">var</span> saw_comma <span class="k">=</span> <span class="k">false</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">733</td><td class="hits">1</td><td class="source"> <span class="k">while</span> <span class="k">(</span><span class="k">true</span><span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">734</td><td class="hits">4</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">735</td><td class="hits">4</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">"}"</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">736</td><td class="hits">1</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">737</td><td class="hits">1</td><td class="source"> <span class="k">if</span> <span class="k">(</span>saw_comma<span class="k">)</span> error<span class="k">(</span><span class="s">"Trailing comma in enum"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">738</td><td class="hits">1</td><td class="source"> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">";"</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"No semicolon after enum"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">739</td><td class="hits">1</td><td class="source"> <span class="k">return</span> ret<span class="k">;</span></td></tr><tr><td class="line">740</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">741</td><td class="hits">3</td><td class="source"> <span class="k">var</span> val <span class="k">=</span> consume<span class="k">(</span>STR<span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Unexpected value in enum"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">742</td><td class="hits">3</td><td class="source"> ret<span class="k">.</span>values<span class="k">.</span>push<span class="k">(</span>val<span class="k">.</span>value<span class="k">.</span>replace<span class="k">(</span><span class="s">/"/g</span><span class="k">,</span> <span class="s">""</span><span class="k">));</span></td></tr><tr class="hit"> <td class="line">743</td><td class="hits">3</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">744</td><td class="hits">3</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">","</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">745</td><td class="hits">2</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">746</td><td class="hits">2</td><td class="source"> saw_comma <span class="k">=</span> <span class="k">true</span><span class="k">;</span></td></tr><tr><td class="line">747</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">748</td><td class="hits"></td><td class="source"> <span class="k">else</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">749</td><td class="hits">1</td><td class="source"> saw_comma <span class="k">=</span> <span class="k">false</span><span class="k">;</span></td></tr><tr><td class="line">750</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">751</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">752</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">753</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">754</td><td class="hits">47</td><td class="source"> <span class="k">var</span> typedef <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">755</td><td class="hits">51</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">756</td><td class="hits">99</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"typedef"</span><span class="k">))</span> <span class="k">return</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">757</td><td class="hits">3</td><td class="source"> <span class="k">var</span> ret <span class="k">=</span> <span class="k">{</span></td></tr><tr><td class="line">758</td><td class="hits"></td><td class="source"> type<span class="k">:</span> <span class="s">"typedef"</span></td></tr><tr><td class="line">759</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">760</td><td class="hits">3</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">761</td><td class="hits">3</td><td class="source"> ret<span class="k">.</span>extAttrs <span class="k">=</span> extended_attrs<span class="k">();</span></td></tr><tr class="hit"> <td class="line">762</td><td class="hits">3</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">763</td><td class="hits">3</td><td class="source"> ret<span class="k">.</span>idlType <span class="k">=</span> type<span class="k">()</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"No type in typedef"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">764</td><td class="hits">3</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">765</td><td class="hits">3</td><td class="source"> <span class="k">var</span> name <span class="k">=</span> consume<span class="k">(</span>ID<span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"No name in typedef"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">766</td><td class="hits">3</td><td class="source"> ret<span class="k">.</span>name <span class="k">=</span> name<span class="k">.</span>value<span class="k">;</span></td></tr><tr class="hit"> <td class="line">767</td><td class="hits">3</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">768</td><td class="hits">3</td><td class="source"> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">";"</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Unterminated typedef"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">769</td><td class="hits">3</td><td class="source"> <span class="k">return</span> ret<span class="k">;</span></td></tr><tr><td class="line">770</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">771</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">772</td><td class="hits">47</td><td class="source"> <span class="k">var</span> implements_ <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">773</td><td class="hits">48</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">774</td><td class="hits">48</td><td class="source"> <span class="k">var</span> target <span class="k">=</span> consume<span class="k">(</span>ID<span class="k">);</span></td></tr><tr class="hit"> <td class="line">775</td><td class="hits">95</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>target<span class="k">)</span> <span class="k">return</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">776</td><td class="hits">1</td><td class="source"> <span class="k">var</span> w <span class="k">=</span> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">777</td><td class="hits">1</td><td class="source"> <span class="k">if</span> <span class="k">(</span>consume<span class="k">(</span>ID<span class="k">,</span> <span class="s">"implements"</span><span class="k">))</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">778</td><td class="hits">1</td><td class="source"> <span class="k">var</span> ret <span class="k">=</span> <span class="k">{</span></td></tr><tr><td class="line">779</td><td class="hits"></td><td class="source"> type<span class="k">:</span> <span class="s">"implements"</span></td></tr><tr><td class="line">780</td><td class="hits"></td><td class="source"> <span class="k">,</span> target<span class="k">:</span> target<span class="k">.</span>value</td></tr><tr><td class="line">781</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">782</td><td class="hits">1</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">783</td><td class="hits">1</td><td class="source"> <span class="k">var</span> imp <span class="k">=</span> consume<span class="k">(</span>ID<span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"Incomplete implements statement"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">784</td><td class="hits">1</td><td class="source"> ret<span class="k">[</span><span class="s">"implements"</span><span class="k">]</span> <span class="k">=</span> imp<span class="k">.</span>value<span class="k">;</span></td></tr><tr class="hit"> <td class="line">785</td><td class="hits">1</td><td class="source"> all_ws<span class="k">();</span></td></tr><tr class="hit"> <td class="line">786</td><td class="hits">1</td><td class="source"> consume<span class="k">(</span>OTHER<span class="k">,</span> <span class="s">";"</span><span class="k">)</span> <span class="k">||</span> error<span class="k">(</span><span class="s">"No terminating ; for implements statement"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">787</td><td class="hits">1</td><td class="source"> <span class="k">return</span> ret<span class="k">;</span></td></tr><tr><td class="line">788</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">789</td><td class="hits"></td><td class="source"> <span class="k">else</span> <span class="k">{</span></td></tr><tr><td class="line">790</td><td class="hits"></td><td class="source"> <span class="c">// rollback</span></td></tr><tr class="miss"> <td class="line">791</td><td class="hits">0</td><td class="source"> tokens<span class="k">.</span>unshift<span class="k">(</span>w<span class="k">);</span></td></tr><tr class="miss"> <td class="line">792</td><td class="hits">0</td><td class="source"> tokens<span class="k">.</span>unshift<span class="k">(</span>target<span class="k">);</span></td></tr><tr><td class="line">793</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">794</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">795</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">796</td><td class="hits">47</td><td class="source"> <span class="k">var</span> definition <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">797</td><td class="hits">144</td><td class="source"> <span class="k">return</span> callback<span class="k">()</span> <span class="k">||</span></td></tr><tr><td class="line">798</td><td class="hits"></td><td class="source"> interface_<span class="k">()</span> <span class="k">||</span></td></tr><tr><td class="line">799</td><td class="hits"></td><td class="source"> partial<span class="k">()</span> <span class="k">||</span></td></tr><tr><td class="line">800</td><td class="hits"></td><td class="source"> dictionary<span class="k">()</span> <span class="k">||</span></td></tr><tr><td class="line">801</td><td class="hits"></td><td class="source"> exception<span class="k">()</span> <span class="k">||</span></td></tr><tr><td class="line">802</td><td class="hits"></td><td class="source"> enum_<span class="k">()</span> <span class="k">||</span></td></tr><tr><td class="line">803</td><td class="hits"></td><td class="source"> typedef<span class="k">()</span> <span class="k">||</span></td></tr><tr><td class="line">804</td><td class="hits"></td><td class="source"> implements_<span class="k">()</span></td></tr><tr><td class="line">805</td><td class="hits"></td><td class="source"> <span class="k">;</span></td></tr><tr><td class="line">806</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">807</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">808</td><td class="hits">47</td><td class="source"> <span class="k">var</span> definitions <span class="k">=</span> <span class="k">function</span> <span class="k">()</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">809</td><td class="hits">47</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>tokens<span class="k">.</span>length<span class="k">)</span> <span class="k">return</span> <span class="k">[];</span></td></tr><tr class="hit"> <td class="line">810</td><td class="hits">47</td><td class="source"> <span class="k">var</span> defs <span class="k">=</span> <span class="k">[];</span></td></tr><tr class="hit"> <td class="line">811</td><td class="hits">47</td><td class="source"> <span class="k">while</span> <span class="k">(</span><span class="k">true</span><span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">812</td><td class="hits">144</td><td class="source"> <span class="k">var</span> ea <span class="k">=</span> extended_attrs<span class="k">()</span></td></tr><tr><td class="line">813</td><td class="hits"></td><td class="source"> <span class="k">,</span> def <span class="k">=</span> definition<span class="k">();</span></td></tr><tr class="hit"> <td class="line">814</td><td class="hits">144</td><td class="source"> <span class="k">if</span> <span class="k">(!</span>def<span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">815</td><td class="hits">47</td><td class="source"> <span class="k">if</span> <span class="k">(</span>ea<span class="k">.</span>length<span class="k">)</span> error<span class="k">(</span><span class="s">"Stray extended attributes"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">816</td><td class="hits">47</td><td class="source"> <span class="k">break</span><span class="k">;</span></td></tr><tr><td class="line">817</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">818</td><td class="hits">97</td><td class="source"> def<span class="k">.</span>extAttrs <span class="k">=</span> ea<span class="k">;</span></td></tr><tr class="hit"> <td class="line">819</td><td class="hits">97</td><td class="source"> defs<span class="k">.</span>push<span class="k">(</span>def<span class="k">);</span></td></tr><tr><td class="line">820</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr class="hit"> <td class="line">821</td><td class="hits">47</td><td class="source"> <span class="k">return</span> defs<span class="k">;</span></td></tr><tr><td class="line">822</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">823</td><td class="hits">47</td><td class="source"> <span class="k">var</span> res <span class="k">=</span> definitions<span class="k">();</span></td></tr><tr class="hit"> <td class="line">824</td><td class="hits">47</td><td class="source"> <span class="k">if</span> <span class="k">(</span>tokens<span class="k">.</span>length<span class="k">)</span> error<span class="k">(</span><span class="s">"Unrecognised tokens"</span><span class="k">);</span></td></tr><tr class="hit"> <td class="line">825</td><td class="hits">47</td><td class="source"> <span class="k">return</span> res<span class="k">;</span></td></tr><tr><td class="line">826</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr><td class="line">827</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"> <td class="line">828</td><td class="hits">1</td><td class="source"> <span class="k">var</span> obj <span class="k">=</span> <span class="k">{</span></td></tr><tr><td class="line">829</td><td class="hits"></td><td class="source"> parse<span class="k">:</span> <span class="k">function</span> <span class="k">(</span>str<span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">830</td><td class="hits">47</td><td class="source"> <span class="k">var</span> tokens <span class="k">=</span> tokenise<span class="k">(</span>str<span class="k">);</span></td></tr><tr><td class="line">831</td><td class="hits"></td><td class="source"> <span class="c">// console.log(tokens);</span></td></tr><tr class="hit"> <td class="line">832</td><td class="hits">47</td><td class="source"> <span class="k">return</span> parse<span class="k">(</span>tokens<span class="k">);</span></td></tr><tr><td class="line">833</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">834</td><td class="hits"></td><td class="source"> <span class="k">}</span><span class="k">;</span></td></tr><tr class="hit"> <td class="line">835</td><td class="hits">1</td><td class="source"> <span class="k">if</span> <span class="k">(</span><span class="k">typeof</span> module <span class="k">!==</span> <span class="s">"undefined"</span> <span class="k">&amp;&amp;</span> module<span class="k">.</span>exports<span class="k">)</span> <span class="k">{</span></td></tr><tr class="hit"> <td class="line">836</td><td class="hits">1</td><td class="source"> module<span class="k">.</span>exports <span class="k">=</span> obj<span class="k">;</span></td></tr><tr><td class="line">837</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">838</td><td class="hits"></td><td class="source"> <span class="k">else</span> <span class="k">{</span></td></tr><tr class="miss"> <td class="line">839</td><td class="hits">0</td><td class="source"> window<span class="k">.</span>WebIDL2 <span class="k">=</span> obj<span class="k">;</span></td></tr><tr><td class="line">840</td><td class="hits"></td><td class="source"> <span class="k">}</span></td></tr><tr><td class="line">841</td><td class="hits"></td><td class="source"><span class="k">}</span><span class="k">());</span></td></tr></tbody></table></div></div></div></body></html>
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/index.js b/tests/wpt/web-platform-tests/resources/webidl2/index.js
new file mode 100644
index 00000000000..09f9eb46aa7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/index.js
@@ -0,0 +1 @@
+module.exports = require("./lib/webidl2.js");
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/lib/webidl2.js b/tests/wpt/web-platform-tests/resources/webidl2/lib/webidl2.js
new file mode 100644
index 00000000000..103a7f48bd8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/lib/webidl2.js
@@ -0,0 +1,924 @@
+
+
+(function () {
+ var tokenise = function (str) {
+ var tokens = []
+ , re = {
+ "float": /^-?(([0-9]+\.[0-9]*|[0-9]*\.[0-9]+)([Ee][-+]?[0-9]+)?|[0-9]+[Ee][-+]?[0-9]+)/
+ , "integer": /^-?(0([Xx][0-9A-Fa-f]+|[0-7]*)|[1-9][0-9]*)/
+ , "identifier": /^[A-Z_a-z][0-9A-Z_a-z]*/
+ , "string": /^"[^"]*"/
+ , "whitespace": /^(?:[\t\n\r ]+|[\t\n\r ]*((\/\/.*|\/\*(.|\n|\r)*?\*\/)[\t\n\r ]*))+/
+ , "other": /^[^\t\n\r 0-9A-Z_a-z]/
+ }
+ , types = []
+ ;
+ for (var k in re) types.push(k);
+ while (str.length > 0) {
+ var matched = false;
+ for (var i = 0, n = types.length; i < n; i++) {
+ var type = types[i];
+ str = str.replace(re[type], function (tok) {
+ tokens.push({ type: type, value: tok });
+ matched = true;
+ return "";
+ });
+ if (matched) break;
+ }
+ if (matched) continue;
+ throw new Error("Token stream not progressing");
+ }
+ return tokens;
+ };
+
+ var parse = function (tokens, opt) {
+ var line = 1;
+ tokens = tokens.slice();
+
+ var FLOAT = "float"
+ , INT = "integer"
+ , ID = "identifier"
+ , STR = "string"
+ , OTHER = "other"
+ ;
+
+ var WebIDLParseError = function (str, line, input, tokens) {
+ this.message = str;
+ this.line = line;
+ this.input = input;
+ this.tokens = tokens;
+ };
+ WebIDLParseError.prototype.toString = function () {
+ return this.message + ", line " + this.line + " (tokens: '" + this.input + "')\n" +
+ JSON.stringify(this.tokens, null, 4);
+ };
+
+ var error = function (str) {
+ var tok = "", numTokens = 0, maxTokens = 5;
+ while (numTokens < maxTokens && tokens.length > numTokens) {
+ tok += tokens[numTokens].value;
+ numTokens++;
+ }
+ throw new WebIDLParseError(str, line, tok, tokens.slice(0, 5));
+ };
+
+ var last_token = null;
+
+ var consume = function (type, value) {
+ if (!tokens.length || tokens[0].type !== type) return;
+ if (typeof value === "undefined" || tokens[0].value === value) {
+ last_token = tokens.shift();
+ if (type === ID) last_token.value = last_token.value.replace(/^_/, "");
+ return last_token;
+ }
+ };
+
+ var ws = function () {
+ if (!tokens.length) return;
+ if (tokens[0].type === "whitespace") {
+ var t = tokens.shift();
+ t.value.replace(/\n/g, function (m) { line++; return m; });
+ return t;
+ }
+ };
+
+ var all_ws = function (store, pea) { // pea == post extended attribute, tpea = same for types
+ var t = { type: "whitespace", value: "" };
+ while (true) {
+ var w = ws();
+ if (!w) break;
+ t.value += w.value;
+ }
+ if (t.value.length > 0) {
+ if (store) {
+ var w = t.value
+ , re = {
+ "ws": /^([\t\n\r ]+)/
+ , "line-comment": /^\/\/(.*)\n?/m
+ , "multiline-comment": /^\/\*((?:.|\n|\r)*?)\*\//
+ }
+ , wsTypes = []
+ ;
+ for (var k in re) wsTypes.push(k);
+ while (w.length) {
+ var matched = false;
+ for (var i = 0, n = wsTypes.length; i < n; i++) {
+ var type = wsTypes[i];
+ w = w.replace(re[type], function (tok, m1) {
+ store.push({ type: type + (pea ? ("-" + pea) : ""), value: m1 });
+ matched = true;
+ return "";
+ });
+ if (matched) break;
+ }
+ if (matched) continue;
+ throw new Error("Surprising white space construct."); // this shouldn't happen
+ }
+ }
+ return t;
+ }
+ };
+
+ var integer_type = function () {
+ var ret = "";
+ all_ws();
+ if (consume(ID, "unsigned")) ret = "unsigned ";
+ all_ws();
+ if (consume(ID, "short")) return ret + "short";
+ if (consume(ID, "long")) {
+ ret += "long";
+ all_ws();
+ if (consume(ID, "long")) return ret + " long";
+ return ret;
+ }
+ if (ret) error("Failed to parse integer type");
+ };
+
+ var float_type = function () {
+ var ret = "";
+ all_ws();
+ if (consume(ID, "unrestricted")) ret = "unrestricted ";
+ all_ws();
+ if (consume(ID, "float")) return ret + "float";
+ if (consume(ID, "double")) return ret + "double";
+ if (ret) error("Failed to parse float type");
+ };
+
+ var primitive_type = function () {
+ var num_type = integer_type() || float_type();
+ if (num_type) return num_type;
+ all_ws();
+ if (consume(ID, "boolean")) return "boolean";
+ if (consume(ID, "byte")) return "byte";
+ if (consume(ID, "octet")) return "octet";
+ };
+
+ var const_value = function () {
+ if (consume(ID, "true")) return { type: "boolean", value: true };
+ if (consume(ID, "false")) return { type: "boolean", value: false };
+ if (consume(ID, "null")) return { type: "null" };
+ if (consume(ID, "Infinity")) return { type: "Infinity", negative: false };
+ if (consume(ID, "NaN")) return { type: "NaN" };
+ var ret = consume(FLOAT) || consume(INT);
+ if (ret) return { type: "number", value: 1 * ret.value };
+ var tok = consume(OTHER, "-");
+ if (tok) {
+ if (consume(ID, "Infinity")) return { type: "Infinity", negative: true };
+ else tokens.unshift(tok);
+ }
+ };
+
+ var type_suffix = function (obj) {
+ while (true) {
+ all_ws();
+ if (consume(OTHER, "?")) {
+ if (obj.nullable) error("Can't nullable more than once");
+ obj.nullable = true;
+ }
+ else if (consume(OTHER, "[")) {
+ all_ws();
+ consume(OTHER, "]") || error("Unterminated array type");
+ if (!obj.array) {
+ obj.array = 1;
+ obj.nullableArray = [obj.nullable];
+ }
+ else {
+ obj.array++;
+ obj.nullableArray.push(obj.nullable);
+ }
+ obj.nullable = false;
+ }
+ else return;
+ }
+ };
+
+ var single_type = function () {
+ var prim = primitive_type()
+ , ret = { sequence: false, generic: null, nullable: false, array: false, union: false }
+ , name
+ , value
+ ;
+ if (prim) {
+ ret.idlType = prim;
+ }
+ else if (name = consume(ID)) {
+ value = name.value;
+ all_ws();
+ // Generic types
+ if (consume(OTHER, "<")) {
+ // backwards compat
+ if (value === "sequence") {
+ ret.sequence = true;
+ }
+ ret.generic = value;
+ ret.idlType = type() || error("Error parsing generic type " + value);
+ all_ws();
+ if (!consume(OTHER, ">")) error("Unterminated generic type " + value);
+ all_ws();
+ if (consume(OTHER, "?")) ret.nullable = true;
+ return ret;
+ }
+ else {
+ ret.idlType = value;
+ }
+ }
+ else {
+ return;
+ }
+ type_suffix(ret);
+ if (ret.nullable && !ret.array && ret.idlType === "any") error("Type any cannot be made nullable");
+ return ret;
+ };
+
+ var union_type = function () {
+ all_ws();
+ if (!consume(OTHER, "(")) return;
+ var ret = { sequence: false, generic: null, nullable: false, array: false, union: true, idlType: [] };
+ var fst = type() || error("Union type with no content");
+ ret.idlType.push(fst);
+ while (true) {
+ all_ws();
+ if (!consume(ID, "or")) break;
+ var typ = type() || error("No type after 'or' in union type");
+ ret.idlType.push(typ);
+ }
+ if (!consume(OTHER, ")")) error("Unterminated union type");
+ type_suffix(ret);
+ return ret;
+ };
+
+ var type = function () {
+ return single_type() || union_type();
+ };
+
+ var argument = function (store) {
+ var ret = { optional: false, variadic: false };
+ ret.extAttrs = extended_attrs(store);
+ all_ws(store, "pea");
+ var opt_token = consume(ID, "optional");
+ if (opt_token) {
+ ret.optional = true;
+ all_ws();
+ }
+ ret.idlType = type();
+ if (!ret.idlType) {
+ if (opt_token) tokens.unshift(opt_token);
+ return;
+ }
+ var type_token = last_token;
+ if (!ret.optional) {
+ all_ws();
+ if (tokens.length >= 3 &&
+ tokens[0].type === "other" && tokens[0].value === "." &&
+ tokens[1].type === "other" && tokens[1].value === "." &&
+ tokens[2].type === "other" && tokens[2].value === "."
+ ) {
+ tokens.shift();
+ tokens.shift();
+ tokens.shift();
+ ret.variadic = true;
+ }
+ }
+ all_ws();
+ var name = consume(ID);
+ if (!name) {
+ if (opt_token) tokens.unshift(opt_token);
+ tokens.unshift(type_token);
+ return;
+ }
+ ret.name = name.value;
+ if (ret.optional) {
+ all_ws();
+ ret["default"] = default_();
+ }
+ return ret;
+ };
+
+ var argument_list = function (store) {
+ var ret = []
+ , arg = argument(store ? ret : null)
+ ;
+ if (!arg) return;
+ ret.push(arg);
+ while (true) {
+ all_ws(store ? ret : null);
+ if (!consume(OTHER, ",")) return ret;
+ var nxt = argument(store ? ret : null) || error("Trailing comma in arguments list");
+ ret.push(nxt);
+ }
+ };
+
+ var type_pair = function () {
+ all_ws();
+ var k = type();
+ if (!k) return;
+ all_ws()
+ if (!consume(OTHER, ",")) return;
+ all_ws();
+ var v = type();
+ if (!v) return;
+ return [k, v];
+ };
+
+ var simple_extended_attr = function (store) {
+ all_ws();
+ var name = consume(ID);
+ if (!name) return;
+ var ret = {
+ name: name.value
+ , "arguments": null
+ };
+ all_ws();
+ var eq = consume(OTHER, "=");
+ if (eq) {
+ all_ws();
+ ret.rhs = consume(ID);
+ if (!ret.rhs) return error("No right hand side to extended attribute assignment");
+ }
+ all_ws();
+ if (consume(OTHER, "(")) {
+ var args, pair;
+ // [Constructor(DOMString str)]
+ if (args = argument_list(store)) {
+ ret["arguments"] = args;
+ }
+ // [MapClass(DOMString, DOMString)]
+ else if (pair = type_pair()) {
+ ret.typePair = pair;
+ }
+ // [Constructor()]
+ else {
+ ret["arguments"] = [];
+ }
+ all_ws();
+ consume(OTHER, ")") || error("Unexpected token in extended attribute argument list or type pair");
+ }
+ return ret;
+ };
+
+ // Note: we parse something simpler than the official syntax. It's all that ever
+ // seems to be used
+ var extended_attrs = function (store) {
+ var eas = [];
+ all_ws(store);
+ if (!consume(OTHER, "[")) return eas;
+ eas[0] = simple_extended_attr(store) || error("Extended attribute with not content");
+ all_ws();
+ while (consume(OTHER, ",")) {
+ eas.push(simple_extended_attr(store) || error("Trailing comma in extended attribute"));
+ all_ws();
+ }
+ consume(OTHER, "]") || error("No end of extended attribute");
+ return eas;
+ };
+
+ var default_ = function () {
+ all_ws();
+ if (consume(OTHER, "=")) {
+ all_ws();
+ var def = const_value();
+ if (def) {
+ return def;
+ }
+ else {
+ var str = consume(STR) || error("No value for default");
+ str.value = str.value.replace(/^"/, "").replace(/"$/, "");
+ return str;
+ }
+ }
+ };
+
+ var const_ = function (store) {
+ all_ws(store, "pea");
+ if (!consume(ID, "const")) return;
+ var ret = { type: "const", nullable: false };
+ all_ws();
+ var typ = primitive_type();
+ if (!typ) {
+ typ = consume(ID) || error("No type for const");
+ typ = typ.value;
+ }
+ ret.idlType = typ;
+ all_ws();
+ if (consume(OTHER, "?")) {
+ ret.nullable = true;
+ all_ws();
+ }
+ var name = consume(ID) || error("No name for const");
+ ret.name = name.value;
+ all_ws();
+ consume(OTHER, "=") || error("No value assignment for const");
+ all_ws();
+ var cnt = const_value();
+ if (cnt) ret.value = cnt;
+ else error("No value for const");
+ all_ws();
+ consume(OTHER, ";") || error("Unterminated const");
+ return ret;
+ };
+
+ var inheritance = function () {
+ all_ws();
+ if (consume(OTHER, ":")) {
+ all_ws();
+ var inh = consume(ID) || error ("No type in inheritance");
+ return inh.value;
+ }
+ };
+
+ var operation_rest = function (ret, store) {
+ all_ws();
+ if (!ret) ret = {};
+ var name = consume(ID);
+ ret.name = name ? name.value : null;
+ all_ws();
+ consume(OTHER, "(") || error("Invalid operation");
+ ret["arguments"] = argument_list(store) || [];
+ all_ws();
+ consume(OTHER, ")") || error("Unterminated operation");
+ all_ws();
+ consume(OTHER, ";") || error("Unterminated operation");
+ return ret;
+ };
+
+ var callback = function (store) {
+ all_ws(store, "pea");
+ var ret;
+ if (!consume(ID, "callback")) return;
+ all_ws();
+ var tok = consume(ID, "interface");
+ if (tok) {
+ tokens.unshift(tok);
+ ret = interface_();
+ ret.type = "callback interface";
+ return ret;
+ }
+ var name = consume(ID) || error("No name for callback");
+ ret = { type: "callback", name: name.value };
+ all_ws();
+ consume(OTHER, "=") || error("No assignment in callback");
+ all_ws();
+ ret.idlType = return_type();
+ all_ws();
+ consume(OTHER, "(") || error("No arguments in callback");
+ ret["arguments"] = argument_list(store) || [];
+ all_ws();
+ consume(OTHER, ")") || error("Unterminated callback");
+ all_ws();
+ consume(OTHER, ";") || error("Unterminated callback");
+ return ret;
+ };
+
+ var attribute = function (store) {
+ all_ws(store, "pea");
+ var grabbed = []
+ , ret = {
+ type: "attribute"
+ , "static": false
+ , stringifier: false
+ , inherit: false
+ , readonly: false
+ };
+ if (consume(ID, "static")) {
+ ret["static"] = true;
+ grabbed.push(last_token);
+ }
+ else if (consume(ID, "stringifier")) {
+ ret.stringifier = true;
+ grabbed.push(last_token);
+ }
+ var w = all_ws();
+ if (w) grabbed.push(w);
+ if (consume(ID, "inherit")) {
+ if (ret["static"] || ret.stringifier) error("Cannot have a static or stringifier inherit");
+ ret.inherit = true;
+ grabbed.push(last_token);
+ var w = all_ws();
+ if (w) grabbed.push(w);
+ }
+ if (consume(ID, "readonly")) {
+ ret.readonly = true;
+ grabbed.push(last_token);
+ var w = all_ws();
+ if (w) grabbed.push(w);
+ }
+ if (!consume(ID, "attribute")) {
+ tokens = grabbed.concat(tokens);
+ return;
+ }
+ all_ws();
+ ret.idlType = type() || error("No type in attribute");
+ if (ret.idlType.sequence) error("Attributes cannot accept sequence types");
+ all_ws();
+ var name = consume(ID) || error("No name in attribute");
+ ret.name = name.value;
+ all_ws();
+ consume(OTHER, ";") || error("Unterminated attribute");
+ return ret;
+ };
+
+ var return_type = function () {
+ var typ = type();
+ if (!typ) {
+ if (consume(ID, "void")) {
+ return "void";
+ }
+ else error("No return type");
+ }
+ return typ;
+ };
+
+ var operation = function (store) {
+ all_ws(store, "pea");
+ var ret = {
+ type: "operation"
+ , getter: false
+ , setter: false
+ , creator: false
+ , deleter: false
+ , legacycaller: false
+ , "static": false
+ , stringifier: false
+ };
+ while (true) {
+ all_ws();
+ if (consume(ID, "getter")) ret.getter = true;
+ else if (consume(ID, "setter")) ret.setter = true;
+ else if (consume(ID, "creator")) ret.creator = true;
+ else if (consume(ID, "deleter")) ret.deleter = true;
+ else if (consume(ID, "legacycaller")) ret.legacycaller = true;
+ else break;
+ }
+ if (ret.getter || ret.setter || ret.creator || ret.deleter || ret.legacycaller) {
+ all_ws();
+ ret.idlType = return_type();
+ operation_rest(ret, store);
+ return ret;
+ }
+ if (consume(ID, "static")) {
+ ret["static"] = true;
+ ret.idlType = return_type();
+ operation_rest(ret, store);
+ return ret;
+ }
+ else if (consume(ID, "stringifier")) {
+ ret.stringifier = true;
+ all_ws();
+ if (consume(OTHER, ";")) return ret;
+ ret.idlType = return_type();
+ operation_rest(ret, store);
+ return ret;
+ }
+ ret.idlType = return_type();
+ all_ws();
+ if (consume(ID, "iterator")) {
+ all_ws();
+ ret.type = "iterator";
+ if (consume(ID, "object")) {
+ ret.iteratorObject = "object";
+ }
+ else if (consume(OTHER, "=")) {
+ all_ws();
+ var name = consume(ID) || error("No right hand side in iterator");
+ ret.iteratorObject = name.value;
+ }
+ all_ws();
+ consume(OTHER, ";") || error("Unterminated iterator");
+ return ret;
+ }
+ else {
+ operation_rest(ret, store);
+ return ret;
+ }
+ };
+
+ var identifiers = function (arr) {
+ while (true) {
+ all_ws();
+ if (consume(OTHER, ",")) {
+ all_ws();
+ var name = consume(ID) || error("Trailing comma in identifiers list");
+ arr.push(name.value);
+ }
+ else break;
+ }
+ };
+
+ var serialiser = function (store) {
+ all_ws(store, "pea");
+ if (!consume(ID, "serializer")) return;
+ var ret = { type: "serializer" };
+ all_ws();
+ if (consume(OTHER, "=")) {
+ all_ws();
+ if (consume(OTHER, "{")) {
+ ret.patternMap = true;
+ all_ws();
+ var id = consume(ID);
+ if (id && id.value === "getter") {
+ ret.names = ["getter"];
+ }
+ else if (id && id.value === "inherit") {
+ ret.names = ["inherit"];
+ identifiers(ret.names);
+ }
+ else if (id) {
+ ret.names = [id.value];
+ identifiers(ret.names);
+ }
+ else {
+ ret.names = [];
+ }
+ all_ws();
+ consume(OTHER, "}") || error("Unterminated serializer pattern map");
+ }
+ else if (consume(OTHER, "[")) {
+ ret.patternList = true;
+ all_ws();
+ var id = consume(ID);
+ if (id && id.value === "getter") {
+ ret.names = ["getter"];
+ }
+ else if (id) {
+ ret.names = [id.value];
+ identifiers(ret.names);
+ }
+ else {
+ ret.names = [];
+ }
+ all_ws();
+ consume(OTHER, "]") || error("Unterminated serializer pattern list");
+ }
+ else {
+ var name = consume(ID) || error("Invalid serializer");
+ ret.name = name.value;
+ }
+ all_ws();
+ consume(OTHER, ";") || error("Unterminated serializer");
+ return ret;
+ }
+ else if (consume(OTHER, ";")) {
+ // noop, just parsing
+ }
+ else {
+ ret.idlType = return_type();
+ all_ws();
+ ret.operation = operation_rest(null, store);
+ }
+ return ret;
+ };
+
+ var interface_ = function (isPartial, store) {
+ all_ws(isPartial ? null : store, "pea");
+ if (!consume(ID, "interface")) return;
+ all_ws();
+ var name = consume(ID) || error("No name for interface");
+ var mems = []
+ , ret = {
+ type: "interface"
+ , name: name.value
+ , partial: false
+ , members: mems
+ };
+ if (!isPartial) ret.inheritance = inheritance() || null;
+ all_ws();
+ consume(OTHER, "{") || error("Bodyless interface");
+ while (true) {
+ all_ws(store ? mems : null);
+ if (consume(OTHER, "}")) {
+ all_ws();
+ consume(OTHER, ";") || error("Missing semicolon after interface");
+ return ret;
+ }
+ var ea = extended_attrs(store ? mems : null);
+ all_ws();
+ var cnt = const_(store ? mems : null);
+ if (cnt) {
+ cnt.extAttrs = ea;
+ ret.members.push(cnt);
+ continue;
+ }
+ var mem = serialiser(store ? mems : null) ||
+ attribute(store ? mems : null) ||
+ operation(store ? mems : null) ||
+ error("Unknown member");
+ mem.extAttrs = ea;
+ ret.members.push(mem);
+ }
+ };
+
+ var partial = function (store) {
+ all_ws(store, "pea");
+ if (!consume(ID, "partial")) return;
+ var thing = dictionary(true, store) ||
+ interface_(true, store) ||
+ error("Partial doesn't apply to anything");
+ thing.partial = true;
+ return thing;
+ };
+
+ var dictionary = function (isPartial, store) {
+ all_ws(isPartial ? null : store, "pea");
+ if (!consume(ID, "dictionary")) return;
+ all_ws();
+ var name = consume(ID) || error("No name for dictionary");
+ var mems = []
+ , ret = {
+ type: "dictionary"
+ , name: name.value
+ , partial: false
+ , members: mems
+ };
+ if (!isPartial) ret.inheritance = inheritance() || null;
+ all_ws();
+ consume(OTHER, "{") || error("Bodyless dictionary");
+ while (true) {
+ all_ws(store ? mems : null);
+ if (consume(OTHER, "}")) {
+ all_ws();
+ consume(OTHER, ";") || error("Missing semicolon after dictionary");
+ return ret;
+ }
+ var ea = extended_attrs(store ? mems : null);
+ all_ws(store ? mems : null, "pea");
+ var typ = type() || error("No type for dictionary member");
+ all_ws();
+ var name = consume(ID) || error("No name for dictionary member");
+ ret.members.push({
+ type: "field"
+ , name: name.value
+ , idlType: typ
+ , extAttrs: ea
+ , "default": default_()
+ });
+ all_ws();
+ consume(OTHER, ";") || error("Unterminated dictionary member");
+ }
+ };
+
+ var exception = function (store) {
+ all_ws(store, "pea");
+ if (!consume(ID, "exception")) return;
+ all_ws();
+ var name = consume(ID) || error("No name for exception");
+ var mems = []
+ , ret = {
+ type: "exception"
+ , name: name.value
+ , members: mems
+ };
+ ret.inheritance = inheritance() || null;
+ all_ws();
+ consume(OTHER, "{") || error("Bodyless exception");
+ while (true) {
+ all_ws(store ? mems : null);
+ if (consume(OTHER, "}")) {
+ all_ws();
+ consume(OTHER, ";") || error("Missing semicolon after exception");
+ return ret;
+ }
+ var ea = extended_attrs(store ? mems : null);
+ all_ws(store ? mems : null, "pea");
+ var cnt = const_();
+ if (cnt) {
+ cnt.extAttrs = ea;
+ ret.members.push(cnt);
+ }
+ else {
+ var typ = type();
+ all_ws();
+ var name = consume(ID);
+ all_ws();
+ if (!typ || !name || !consume(OTHER, ";")) error("Unknown member in exception body");
+ ret.members.push({
+ type: "field"
+ , name: name.value
+ , idlType: typ
+ , extAttrs: ea
+ });
+ }
+ }
+ };
+
+ var enum_ = function (store) {
+ all_ws(store, "pea");
+ if (!consume(ID, "enum")) return;
+ all_ws();
+ var name = consume(ID) || error("No name for enum");
+ var vals = []
+ , ret = {
+ type: "enum"
+ , name: name.value
+ , values: vals
+ };
+ all_ws();
+ consume(OTHER, "{") || error("No curly for enum");
+ var saw_comma = false;
+ while (true) {
+ all_ws(store ? vals : null);
+ if (consume(OTHER, "}")) {
+ all_ws();
+ if (saw_comma) error("Trailing comma in enum");
+ consume(OTHER, ";") || error("No semicolon after enum");
+ return ret;
+ }
+ var val = consume(STR) || error("Unexpected value in enum");
+ ret.values.push(val.value.replace(/"/g, ""));
+ all_ws(store ? vals : null);
+ if (consume(OTHER, ",")) {
+ if (store) vals.push({ type: "," });
+ all_ws(store ? vals : null);
+ saw_comma = true;
+ }
+ else {
+ saw_comma = false;
+ }
+ }
+ };
+
+ var typedef = function (store) {
+ all_ws(store, "pea");
+ if (!consume(ID, "typedef")) return;
+ var ret = {
+ type: "typedef"
+ };
+ all_ws();
+ ret.typeExtAttrs = extended_attrs();
+ all_ws(store, "tpea");
+ ret.idlType = type() || error("No type in typedef");
+ all_ws();
+ var name = consume(ID) || error("No name in typedef");
+ ret.name = name.value;
+ all_ws();
+ consume(OTHER, ";") || error("Unterminated typedef");
+ return ret;
+ };
+
+ var implements_ = function (store) {
+ all_ws(store, "pea");
+ var target = consume(ID);
+ if (!target) return;
+ var w = all_ws();
+ if (consume(ID, "implements")) {
+ var ret = {
+ type: "implements"
+ , target: target.value
+ };
+ all_ws();
+ var imp = consume(ID) || error("Incomplete implements statement");
+ ret["implements"] = imp.value;
+ all_ws();
+ consume(OTHER, ";") || error("No terminating ; for implements statement");
+ return ret;
+ }
+ else {
+ // rollback
+ tokens.unshift(w);
+ tokens.unshift(target);
+ }
+ };
+
+ var definition = function (store) {
+ return callback(store) ||
+ interface_(false, store) ||
+ partial(store) ||
+ dictionary(false, store) ||
+ exception(store) ||
+ enum_(store) ||
+ typedef(store) ||
+ implements_(store)
+ ;
+ };
+
+ var definitions = function (store) {
+ if (!tokens.length) return [];
+ var defs = [];
+ while (true) {
+ var ea = extended_attrs(store ? defs : null)
+ , def = definition(store ? defs : null);
+ if (!def) {
+ if (ea.length) error("Stray extended attributes");
+ break;
+ }
+ def.extAttrs = ea;
+ defs.push(def);
+ }
+ return defs;
+ };
+ var res = definitions(opt.ws);
+ if (tokens.length) error("Unrecognised tokens");
+ return res;
+ };
+
+ var inNode = typeof module !== "undefined" && module.exports
+ , obj = {
+ parse: function (str, opt) {
+ if (!opt) opt = {};
+ var tokens = tokenise(str);
+ return parse(tokens, opt);
+ }
+ };
+
+ if (inNode) module.exports = obj;
+ else self.WebIDL2 = obj;
+}());
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/lib/writer.js b/tests/wpt/web-platform-tests/resources/webidl2/lib/writer.js
new file mode 100644
index 00000000000..ba836373823
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/lib/writer.js
@@ -0,0 +1,236 @@
+
+(function () {
+
+ var write = function (ast, opt) {
+ var curPea = ""
+ , curTPea = ""
+ , opt = opt || {}
+ , noop = function (str) { return str; }
+ , optNames = "type".split(" ")
+ , context = []
+ ;
+ for (var i = 0, n = optNames.length; i < n; i++) {
+ var o = optNames[i];
+ if (!opt[o]) opt[o] = noop;
+ }
+
+ var literal = function (it) {
+ return it.value;
+ };
+ var wsPea = function (it) {
+ curPea += it.value;
+ return "";
+ };
+ var wsTPea = function (it) {
+ curTPea += it.value;
+ return "";
+ };
+ var lineComment = function (it) {
+ return "//" + it.value + "\n";
+ };
+ var multilineComment = function (it) {
+ return "/*" + it.value + "*/";
+ };
+ var type = function (it) {
+ if (typeof it === "string") return opt.type(it); // XXX should maintain some context
+ if (it.union) return "(" + it.idlType.map(type).join(" or ") + ")";
+ var ret = "";
+ if (it.sequence) ret += "sequence<";
+ ret += type(it.idlType);
+ if (it.array) {
+ for (var i = 0, n = it.nullableArray.length; i < n; i++) {
+ var val = it.nullableArray[i];
+ if (val) ret += "?";
+ ret += "[]";
+ }
+ }
+ if (it.sequence) ret += ">";
+ if (it.nullable) ret += "?";
+
+ return ret;
+ };
+ var const_value = function (it) {
+ var tp = it. type;
+ if (tp === "boolean") return it.value ? "true" : "false";
+ else if (tp === "null") return "null";
+ else if (tp === "Infinity") return (it.negative ? "-" : "") + "Infinity";
+ else if (tp === "NaN") return "NaN";
+ else if (tp === "number") return it.value;
+ else return '"' + it.value + '"';
+ };
+ var argument = function (arg, pea) {
+ var ret = extended_attributes(arg.extAttrs, pea);
+ if (arg.optional) ret += "optional ";
+ ret += type(arg.idlType);
+ if (arg.variadic) ret += "...";
+ ret += " " + arg.name;
+ if (arg["default"]) ret += " = " + const_value(arg["default"]);
+ return ret;
+ };
+ var args = function (its) {
+ var res = ""
+ , pea = ""
+ ;
+ for (var i = 0, n = its.length; i < n; i++) {
+ var arg = its[i];
+ if (arg.type === "ws") res += arg.value;
+ else if (arg.type === "ws-pea") pea += arg.value;
+ else {
+ res += argument(arg, pea);
+ if (i < n - 1) res += ",";
+ pea = "";
+ }
+ }
+ return res;
+ };
+ var make_ext_at = function (it) {
+ if (it["arguments"] === null) return it.name;
+ context.unshift(it);
+ var ret = it.name + "(" + (it["arguments"].length ? args(it["arguments"]) : "") + ")";
+ context.shift(); // XXX need to add more contexts, but not more than needed for ReSpec
+ return ret;
+ };
+ var extended_attributes = function (eats, pea) {
+ if (!eats || !eats.length) return "";
+ return "[" + eats.map(make_ext_at).join(", ") + "]" + pea;
+ };
+
+ var modifiers = "getter setter creator deleter legacycaller stringifier static".split(" ");
+ var operation = function (it) {
+ var ret = extended_attributes(it.extAttrs, curPea);
+ curPea = "";
+ if (it.stringifier && !it.idlType) return "stringifier;";
+ for (var i = 0, n = modifiers.length; i < n; i++) {
+ var mod = modifiers[i];
+ if (it[mod]) ret += mod + " ";
+ }
+ ret += type(it.idlType) + " ";
+ if (it.name) ret += it.name;
+ ret += "(" + args(it["arguments"]) + ");";
+ return ret;
+ };
+
+ var attribute = function (it) {
+ var ret = extended_attributes(it.extAttrs, curPea);
+ curPea = "";
+ if (it["static"]) ret += "static ";
+ if (it.stringifier) ret += "stringifier ";
+ if (it.readonly) ret += "readonly ";
+ if (it.inherit) ret += "inherit ";
+ ret += "attribute " + type(it.idlType) + " " + it.name + ";";
+ return ret;
+ };
+
+ var interface_ = function (it) {
+ var ret = extended_attributes(it.extAttrs, curPea);
+ curPea = "";
+ if (it.partial) ret += "partial ";
+ ret += "interface " + it.name + " ";
+ if (it.inheritance) ret += ": " + it.inheritance + " ";
+ ret += "{" + iterate(it.members) + "};";
+ return ret;
+ };
+
+ var dictionary = function (it) {
+ var ret = extended_attributes(it.extAttrs, curPea);
+ curPea = "";
+ if (it.partial) ret += "partial ";
+ ret += "dictionary " + it.name + " ";
+ ret += "{" + iterate(it.members) + "};";
+ return ret;
+ };
+ var field = function (it) {
+ var ret = extended_attributes(it.extAttrs, curPea);
+ curPea = "";
+ ret += type(it.idlType) + " " + it.name;
+ if (it["default"]) ret += " = " + const_value(it["default"]);
+ ret += ";";
+ return ret;
+ };
+ var exception = function (it) {
+ var ret = extended_attributes(it.extAttrs, curPea);
+ curPea = "";
+ ret += "exception " + it.name + " ";
+ if (it.inheritance) ret += ": " + it.inheritance + " ";
+ ret += "{" + iterate(it.members) + "};";
+ return ret;
+ };
+ var const_ = function (it) {
+ var ret = extended_attributes(it.extAttrs, curPea);
+ curPea = "";
+ return ret + "const " + type(it.idlType) + " " + it.name + " = " + const_value(it.value) + ";";
+ };
+ var typedef = function (it) {
+ var ret = extended_attributes(it.extAttrs, curPea);
+ curPea = "";
+ ret += "typedef " + extended_attributes(it.typeExtAttrs, curTPea);
+ curTPea = "";
+ return ret + type(it.idlType) + " " + it.name + ";";
+ };
+ var implements_ = function (it) {
+ var ret = extended_attributes(it.extAttrs, curPea);
+ curPea = "";
+ return ret + it.target + " implements " + it["implements"] + ";";
+ };
+ var callback = function (it) {
+ var ret = extended_attributes(it.extAttrs, curPea);
+ curPea = "";
+ return ret + "callback " + it.name + " = " + type(it.idlType) +
+ "(" + args(it["arguments"]) + ");";
+ };
+ var enum_ = function (it) {
+ var ret = extended_attributes(it.extAttrs, curPea);
+ curPea = "";
+ ret += "enum " + it.name + " {";
+ for (var i = 0, n = it.values.length; i < n; i++) {
+ var v = it.values[i];
+ if (typeof v === "string") ret += '"' + v + '"';
+ else if (v.type === "ws") ret += v.value;
+ else if (v.type === ",") ret += ",";
+ }
+ return ret + "};";
+ };
+
+ var table = {
+ ws: literal
+ , "ws-pea": wsPea
+ , "ws-tpea": wsTPea
+ , "line-comment": lineComment
+ , "multiline-comment": multilineComment
+ , "interface": interface_
+ , operation: operation
+ , attribute: attribute
+ , dictionary: dictionary
+ , field: field
+ , exception: exception
+ , "const": const_
+ , typedef: typedef
+ , "implements": implements_
+ , callback: callback
+ , "enum": enum_
+ };
+ var dispatch = function (it) {
+ return table[it.type](it);
+ };
+ var iterate = function (things) {
+ if (!things) return;
+ var ret = "";
+ for (var i = 0, n = things.length; i < n; i++) ret += dispatch(things[i]);
+ return ret;
+ };
+ return iterate(ast);
+ };
+
+
+ var inNode = typeof module !== "undefined" && module.exports
+ , obj = {
+ write: function (ast, opt) {
+ if (!opt) opt = {};
+ return write(ast, opt);
+ }
+ };
+
+ if (inNode) module.exports = obj;
+ else window.WebIDL2Writer = obj;
+
+}());
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/package.json b/tests/wpt/web-platform-tests/resources/webidl2/package.json
new file mode 100644
index 00000000000..5a0637ee110
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/package.json
@@ -0,0 +1,22 @@
+{
+ "name": "webidl2"
+, "description": "A WebIDL Parser"
+, "version": "2.0.4"
+, "author": "Robin Berjon <robin@berjon.com>"
+, "license": "MIT"
+, "dependencies": {
+ }
+, "devDependencies": {
+ "mocha": "1.7.4"
+ , "expect.js": "0.2.0"
+ , "underscore": "1.4.3"
+ , "jsondiffpatch": "0.0.5"
+ , "benchmark": "*"
+ , "microtime": "*"
+ }
+, "scripts": {
+ "test": "mocha"
+ }
+, "repository": "git://github.com/darobin/webidl2.js"
+, "main": "index"
+}
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/invalid.js b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid.js
new file mode 100644
index 00000000000..c9821803726
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid.js
@@ -0,0 +1,42 @@
+
+// NOTES:
+// - the errors actually still need to be reviewed to check that they
+// are fully correct interpretations of the IDLs
+
+var wp = process.env.JSCOV ? require("../lib-cov/webidl2") : require("../lib/webidl2")
+, expect = require("expect.js")
+, pth = require("path")
+, fs = require("fs")
+;
+describe("Parses all of the invalid IDLs to check that they blow up correctly", function () {
+ var dir = pth.join(__dirname, "invalid/idl")
+ , skip = {}
+ , idls = fs.readdirSync(dir)
+ .filter(function (it) { return (/\.w?idl$/).test(it) && !skip[it]; })
+ .map(function (it) { return pth.join(dir, it); })
+ , errors = idls.map(function (it) { return pth.join(__dirname, "invalid", "json", pth.basename(it).replace(/\.w?idl/, ".json")); })
+ ;
+
+ for (var i = 0, n = idls.length; i < n; i++) {
+ var idl = idls[i], error = JSON.parse(fs.readFileSync(errors[i], "utf8"));
+ var func = (function (idl, err) {
+ return function () {
+ var error;
+ try {
+ var ast = wp.parse(fs.readFileSync(idl, "utf8"));
+ console.log(JSON.stringify(ast, null, 4));
+ }
+ catch (e) {
+ error = e;
+ }
+ finally {
+ expect(error).to.be.ok();
+ expect(error.message).to.equal(err.message);
+ expect(error.line).to.equal(err.line);
+ }
+
+ };
+ }(idl, error));
+ it("should produce the right error for " + idl, func);
+ }
+});
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/enum.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/enum.widl
new file mode 100644
index 00000000000..c355c3251c0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/enum.widl
@@ -0,0 +1 @@
+enum foo { 1, 2, 3}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/module.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/module.widl
new file mode 100644
index 00000000000..a4c79fdf155
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/module.widl
@@ -0,0 +1,25 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+module gfx {
+
+ module geom {
+ interface Shape { /* ... */ };
+ interface Rectangle : Shape { /* ... */ };
+ interface Path : Shape { /* ... */ };
+ };
+
+ interface GraphicsContext {
+ void fillShape(geom::Shape s);
+ void strokeShape(geom::Shape s);
+ };
+};
+
+module gui {
+
+ interface Widget { /* ... */ };
+
+ interface Window : Widget {
+ gfx::GraphicsContext getGraphicsContext();
+ };
+
+ interface Button : Widget { /* ... */ };
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/nonnullableany.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/nonnullableany.widl
new file mode 100644
index 00000000000..38957655523
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/nonnullableany.widl
@@ -0,0 +1,3 @@
+interface NonNullable {
+ attribute any? foo;
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/nonnullableobjects.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/nonnullableobjects.widl
new file mode 100644
index 00000000000..1deac5aeec9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/nonnullableobjects.widl
@@ -0,0 +1,5 @@
+interface Foo {};
+
+interface NonNullable {
+ attribute Foo?? foo;
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/raises.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/raises.widl
new file mode 100644
index 00000000000..ff65522f2b3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/raises.widl
@@ -0,0 +1,18 @@
+// getraises and setraises are not longer valid Web IDL
+interface Person {
+
+ // An attribute that can raise an exception if it is set to an invalid value.
+ attribute DOMString name setraises (InvalidName);
+
+ // An attribute whose value cannot be assigned to, and which can raise an
+ // exception some circumstances.
+ readonly attribute DOMString petName getraises (NoSuchPet);
+};
+
+exception SomeException {
+};
+
+interface ExceptionThrower {
+ // This attribute always throws a SomeException and never returns a value.
+ attribute long valueOf getraises(SomeException);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/scopedname.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/scopedname.widl
new file mode 100644
index 00000000000..cfcb1ccc939
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/scopedname.widl
@@ -0,0 +1,2 @@
+// scoped names are no longer valid in WebIDL
+ typedef gfx::geom::geom2d::Point Point;
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/sequenceAsAttribute.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/sequenceAsAttribute.widl
new file mode 100644
index 00000000000..c23da82ac22
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/sequenceAsAttribute.widl
@@ -0,0 +1,3 @@
+interface sequenceAsAttribute {
+ attribute sequence<short> invalid;
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/special-omittable.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/special-omittable.widl
new file mode 100644
index 00000000000..bdfbfa70973
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/special-omittable.widl
@@ -0,0 +1,8 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+// omittable is no longer a recognized keywoard as of 20110905
+interface Dictionary {
+ readonly attribute unsigned long propertyCount;
+
+ omittable getter float getProperty(DOMString propertyName);
+ omittable setter void setProperty(DOMString propertyName, float propertyValue);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/stringconstants.idl b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/stringconstants.idl
new file mode 100644
index 00000000000..44fd3ff136e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/idl/stringconstants.idl
@@ -0,0 +1,3 @@
+interface Util {
+ const DOMString hello = "world";
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/enum.json b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/enum.json
new file mode 100644
index 00000000000..166115801c3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/enum.json
@@ -0,0 +1,4 @@
+{
+ "message": "Unexpected value in enum"
+, "line": 1
+}
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/module.json b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/module.json
new file mode 100644
index 00000000000..3b0984d973f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/module.json
@@ -0,0 +1,4 @@
+{
+ "message": "Unrecognised tokens"
+, "line": 2
+}
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/nonnullableany.json b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/nonnullableany.json
new file mode 100644
index 00000000000..cf5229e8e44
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/nonnullableany.json
@@ -0,0 +1,4 @@
+{
+ "message": "Type any cannot be made nullable"
+, "line": 2
+}
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/nonnullableobjects.json b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/nonnullableobjects.json
new file mode 100644
index 00000000000..23cbb3e5d18
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/nonnullableobjects.json
@@ -0,0 +1,4 @@
+{
+ "message": "Can't nullable more than once"
+, "line": 4
+}
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/raises.json b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/raises.json
new file mode 100644
index 00000000000..8b67afe4fc9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/raises.json
@@ -0,0 +1,4 @@
+{
+ "message": "Unterminated attribute"
+, "line": 5
+}
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/scopedname.json b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/scopedname.json
new file mode 100644
index 00000000000..8e2cd803287
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/scopedname.json
@@ -0,0 +1,4 @@
+{
+ "message": "No name in typedef"
+, "line": 2
+}
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/sequenceAsAttribute.json b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/sequenceAsAttribute.json
new file mode 100644
index 00000000000..b714f5d9243
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/sequenceAsAttribute.json
@@ -0,0 +1,4 @@
+{
+ "message": "Attributes cannot accept sequence types"
+, "line": 2
+}
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/special-omittable.json b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/special-omittable.json
new file mode 100644
index 00000000000..7acb08834b0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/special-omittable.json
@@ -0,0 +1,4 @@
+{
+ "message": "Invalid operation"
+, "line": 6
+}
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/stringconstants.json b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/stringconstants.json
new file mode 100644
index 00000000000..d5bf1a8832c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/invalid/json/stringconstants.json
@@ -0,0 +1,4 @@
+{
+ "message": "No value for const"
+, "line": 2
+}
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/mocha.opts b/tests/wpt/web-platform-tests/resources/webidl2/test/mocha.opts
new file mode 100644
index 00000000000..5ada47be16b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/mocha.opts
@@ -0,0 +1 @@
+--reporter spec
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax.js b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax.js
new file mode 100644
index 00000000000..6f9de3637d1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax.js
@@ -0,0 +1,36 @@
+
+var wp = process.env.JSCOV ? require("../lib-cov/webidl2") : require("../lib/webidl2")
+, expect = require("expect.js")
+, pth = require("path")
+, fs = require("fs")
+, jdp = require("jsondiffpatch")
+, debug = true
+;
+describe("Parses all of the IDLs to produce the correct ASTs", function () {
+ var dir = pth.join(__dirname, "syntax/idl")
+ , skip = {} // use if we have a broken test
+ , idls = fs.readdirSync(dir)
+ .filter(function (it) { return (/\.widl$/).test(it) && !skip[it]; })
+ .map(function (it) { return pth.join(dir, it); })
+ , jsons = idls.map(function (it) { return pth.join(__dirname, "syntax/json", pth.basename(it).replace(".widl", ".json")); })
+ ;
+
+ for (var i = 0, n = idls.length; i < n; i++) {
+ var idl = idls[i], json = jsons[i];
+ var func = (function (idl, json) {
+ return function () {
+ try {
+ var diff = jdp.diff(JSON.parse(fs.readFileSync(json, "utf8")),
+ wp.parse(fs.readFileSync(idl, "utf8")));
+ if (diff && debug) console.log(JSON.stringify(diff, null, 4));
+ expect(diff).to.be(undefined);
+ }
+ catch (e) {
+ console.log(e.toString());
+ throw e;
+ }
+ };
+ }(idl, json));
+ it("should produce the same AST for " + idl, func);
+ }
+});
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/allowany.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/allowany.widl
new file mode 100644
index 00000000000..2343bb96374
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/allowany.widl
@@ -0,0 +1,6 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface B {
+ void g();
+ void g(B b);
+ void g([AllowAny] DOMString s);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/array.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/array.widl
new file mode 100644
index 00000000000..22e21fb6564
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/array.widl
@@ -0,0 +1,5 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+[Constructor]
+interface LotteryResults {
+ readonly attribute unsigned short[][] numbers;
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/attributes.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/attributes.widl
new file mode 100644
index 00000000000..7e1d691cbe2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/attributes.widl
@@ -0,0 +1,14 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+exception InvalidName {
+ DOMString reason;
+};
+
+exception NoSuchPet { };
+
+interface Person {
+
+ // A simple attribute that can be set to any value the range an unsigned
+ // short can take.
+ attribute unsigned short age;
+
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/callback.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/callback.widl
new file mode 100644
index 00000000000..d92f6a18c0a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/callback.widl
@@ -0,0 +1,5 @@
+callback AsyncOperationCallback = void (DOMString status);
+
+callback interface EventHandler {
+ void eventOccurred(DOMString details);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/caller.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/caller.widl
new file mode 100644
index 00000000000..92acb1c0176
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/caller.widl
@@ -0,0 +1,5 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface NumberQuadrupler {
+ // This operation simply returns four times the given number x.
+ legacycaller float compute(float x);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/constants.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/constants.widl
new file mode 100644
index 00000000000..5e28ae9c116
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/constants.widl
@@ -0,0 +1,18 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface Util {
+ const boolean DEBUG = false;
+ const short negative = -1;
+ const octet LF = 10;
+ const unsigned long BIT_MASK = 0x0000fc00;
+ const float AVOGADRO = 6.022e23;
+ const unrestricted float sobig = Infinity;
+ const unrestricted double minusonedividedbyzero = -Infinity;
+ const short notanumber = NaN;
+};
+
+exception Error {
+ const short ERR_UNKNOWN = 0;
+ const short ERR_OUT_OF_MEMORY = 1;
+
+ short errorCode;
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/constructor.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/constructor.widl
new file mode 100644
index 00000000000..f93ec08a6e6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/constructor.widl
@@ -0,0 +1,9 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+[Constructor,
+ Constructor(float radius)]
+interface Circle {
+ attribute float r;
+ attribute float cx;
+ attribute float cy;
+ readonly attribute float circumference;
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/dictionary-inherits.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/dictionary-inherits.widl
new file mode 100644
index 00000000000..48f8a0fdceb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/dictionary-inherits.widl
@@ -0,0 +1,9 @@
+dictionary PaintOptions {
+ DOMString? fillPattern = "black";
+ DOMString? strokePattern = null;
+ Point position;
+};
+
+dictionary WetPaintOptions : PaintOptions {
+ float hydrometry;
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/dictionary.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/dictionary.widl
new file mode 100644
index 00000000000..f46b7ba7806
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/dictionary.widl
@@ -0,0 +1,11 @@
+// Extracted from Web IDL editors draft May 31 2011
+dictionary PaintOptions {
+ DOMString? fillPattern = "black";
+ DOMString? strokePattern = null;
+ Point position;
+};
+
+partial dictionary A {
+ long h;
+ long d;
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/documentation-dos.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/documentation-dos.widl
new file mode 100644
index 00000000000..fb801101f14
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/documentation-dos.widl
@@ -0,0 +1,33 @@
+/**
+* \brief Testing documentation features
+*
+* This is a
+* single paragraph
+*
+* <p>This is valid.</p>
+* <p>This is <em>valid</em>.</p>
+* <p>This is <b>valid</b>.</p>
+* <p>This is <a href=''>valid</a>.</p>
+* <ul>
+* <li>This</li>
+* <li>is</li>
+* <li>valid</li>
+* </ul>
+* <dl>
+* <dt>This</dt>
+* <dd>valid</dd>
+* </dl>
+* <table>
+* <tr>
+* <td>this</td>
+* <td>is</td>
+* </tr>
+* <tr>
+* <td>valid</td>
+* </tr>
+* </table>
+* <p>This is <br> valid.</p>
+* <p>This is <br /> valid.</p>
+* <p>This is <br/> valid.</p>
+*/
+interface Documentation {}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/documentation.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/documentation.widl
new file mode 100644
index 00000000000..003e9226f67
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/documentation.widl
@@ -0,0 +1,34 @@
+/**
+* \brief Testing documentation features
+*
+* This is a
+* single paragraph
+*
+* <p>This is valid.</p>
+* <p>This is <em>valid</em>.</p>
+* <p>This is <b>valid</b>.</p>
+* <p>This is <a href=''>valid</a>.</p>
+* <ul>
+* <li>This</li>
+* <li>is</li>
+* <li>valid</li>
+* </ul>
+* <dl>
+* <dt>This</dt>
+* <dd>valid</dd>
+* </dl>
+* <table>
+* <tr>
+* <td>this</td>
+* <td>is</td>
+* </tr>
+* <tr>
+* <td>valid</td>
+* </tr>
+* </table>
+* <p>This is <br> valid.</p>
+* <p>This is <br /> valid.</p>
+* <p>This is <br/> valid.</p>
+* <p><img src="foo.png" alt="Valid"/></p>
+*/
+interface Documentation {}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/enum.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/enum.widl
new file mode 100644
index 00000000000..851fca2e6f6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/enum.widl
@@ -0,0 +1,8 @@
+enum MealType { "rice", "noodles", "other" };
+
+interface Meal {
+ attribute MealType type;
+ attribute float size; // in grams
+
+ void initialize(MealType type, float size);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/equivalent-decl.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/equivalent-decl.widl
new file mode 100644
index 00000000000..6b3e0eda284
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/equivalent-decl.widl
@@ -0,0 +1,18 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface Dictionary {
+ readonly attribute unsigned long propertyCount;
+
+ getter float getProperty(DOMString propertyName);
+ setter void setProperty(DOMString propertyName, float propertyValue);
+};
+
+
+interface Dictionary {
+ readonly attribute unsigned long propertyCount;
+
+ float getProperty(DOMString propertyName);
+ void setProperty(DOMString propertyName, float propertyValue);
+
+ getter float (DOMString propertyName);
+ setter void (DOMString propertyName, float propertyValue);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/exception-inheritance.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/exception-inheritance.widl
new file mode 100644
index 00000000000..258fdeba6f4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/exception-inheritance.widl
@@ -0,0 +1,7 @@
+// from http://lists.w3.org/Archives/Public/public-script-coord/2010OctDec/0112.html
+ exception DOMException {
+ unsigned short code;
+ };
+
+ exception HierarchyRequestError : DOMException { };
+ exception NoModificationAllowedError : DOMException { }; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/exception.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/exception.widl
new file mode 100644
index 00000000000..f4b6ae29e10
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/exception.widl
@@ -0,0 +1,8 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface Dahut {
+ attribute DOMString type;
+};
+
+exception SomeException {
+};
+
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/generic.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/generic.widl
new file mode 100644
index 00000000000..18c79a50d8d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/generic.widl
@@ -0,0 +1,17 @@
+interface Foo {
+ Promise<ResponsePromise<sequence<DOMString?>>> bar();
+};
+
+// Extracted from https://slightlyoff.github.io/ServiceWorker/spec/service_worker/ on 2014-05-08
+
+interface ServiceWorkerClients {
+ Promise<Client[]?> getServiced();
+ Promise<any> reloadAll();
+};
+
+// Extracted from https://slightlyoff.github.io/ServiceWorker/spec/service_worker/ on 2014-05-13
+
+interface FetchEvent : Event {
+ ResponsePromise<any> default();
+};
+
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/getter-setter.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/getter-setter.widl
new file mode 100644
index 00000000000..bdf87e1c7c7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/getter-setter.widl
@@ -0,0 +1,7 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface Dictionary {
+ readonly attribute unsigned long propertyCount;
+
+ getter float (DOMString propertyName);
+ setter void (DOMString propertyName, float propertyValue);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/identifier-qualified-names.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/identifier-qualified-names.widl
new file mode 100644
index 00000000000..33893d4c644
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/identifier-qualified-names.widl
@@ -0,0 +1,44 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+ // Typedef identifier: "number"
+ // Qualified name: "::framework::number"
+ typedef float number;
+
+ // Exception identifier: "FrameworkException"
+ // Qualified name: "::framework::FrameworkException"
+ exception FrameworkException {
+
+ // Constant identifier: "ERR_NOT_FOUND"
+ // Qualified name: "::framework::FrameworkException::ERR_NOT_FOUND"
+ const long ERR_NOT_FOUND = 1;
+
+ // Exception field identifier: "code"
+ long code;
+ };
+
+ // Interface identifier: "System"
+ // Qualified name: "::framework::System"
+ interface System {
+
+ // Operation identifier: "createObject"
+ // Operation argument identifier: "interface"
+ object createObject(DOMString _interface);
+
+ // Operation has no identifier; it declares a getter.
+ getter DOMString (DOMString keyName);
+ };
+
+
+ // Interface identifier: "TextField"
+ // Qualified name: "::framework::gui::TextField"
+ interface TextField {
+
+ // Attribute identifier: "const"
+ attribute boolean _const;
+
+ // Attribute identifier: "value"
+ attribute DOMString? _value;
+ };
+
+interface Foo {
+ void op(object interface);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/implements.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/implements.widl
new file mode 100644
index 00000000000..7a310926f1c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/implements.widl
@@ -0,0 +1,14 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+ interface Node {
+ readonly attribute unsigned short nodeType;
+ // ...
+ };
+
+ interface EventTarget {
+ void addEventListener(DOMString type,
+ EventListener listener,
+ boolean useCapture);
+ // ...
+ };
+
+ Node implements EventTarget;
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/indexed-properties.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/indexed-properties.widl
new file mode 100644
index 00000000000..acf0ed3bf84
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/indexed-properties.widl
@@ -0,0 +1,12 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface OrderedMap {
+ readonly attribute unsigned long size;
+
+ getter any getByIndex(unsigned long index);
+ setter void setByIndex(unsigned long index, any value);
+ deleter void removeByIndex(unsigned long index);
+
+ getter any get(DOMString name);
+ setter creator void set(DOMString name, any value);
+ deleter void remove(DOMString name);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/inherits-getter.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/inherits-getter.widl
new file mode 100644
index 00000000000..558e8116494
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/inherits-getter.widl
@@ -0,0 +1,16 @@
+interface Animal {
+
+ // A simple attribute that can be set to any string value.
+ readonly attribute DOMString name;
+};
+
+interface Person : Animal {
+
+ // An attribute whose value cannot be assigned to.
+ readonly attribute unsigned short age;
+
+ // An attribute that can raise an exception if it is set to an invalid value.
+ // Its getter behavior is inherited from Animal, and need not be specified
+ // the description of Person.
+ inherit attribute DOMString name;
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/interface-inherits.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/interface-inherits.widl
new file mode 100644
index 00000000000..7921def7727
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/interface-inherits.widl
@@ -0,0 +1,12 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface Animal {
+ attribute DOMString name;
+};
+
+interface Human : Animal {
+ attribute Dog pet;
+};
+
+interface Dog : Animal {
+ attribute Human owner;
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/iterator.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/iterator.widl
new file mode 100644
index 00000000000..3bf1b36dec6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/iterator.widl
@@ -0,0 +1,35 @@
+interface SessionManager {
+ Session getSessionForUser(DOMString username);
+ readonly attribute unsigned long sessionCount;
+
+ Session iterator;
+};
+
+interface Session {
+ readonly attribute DOMString username;
+ // ...
+};
+
+interface SessionManager2 {
+ Session2 getSessionForUser(DOMString username);
+ readonly attribute unsigned long sessionCount;
+
+ Session2 iterator = SessionIterator;
+};
+
+interface Session2 {
+ readonly attribute DOMString username;
+ // ...
+};
+
+interface SessionIterator {
+ readonly attribute unsigned long remainingSessions;
+};
+
+ interface NodeList {
+ Node iterator = NodeIterator;
+ };
+
+ interface NodeIterator {
+ Node iterator object;
+ }; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/map.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/map.widl
new file mode 100644
index 00000000000..19b54f80a61
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/map.widl
@@ -0,0 +1,5 @@
+// Extracted from https://slightlyoff.github.io/ServiceWorker/spec/service_worker/ on 2014-05-06
+
+[MapClass(DOMString, DOMString)]
+interface HeaderMap {
+};
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/namedconstructor.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/namedconstructor.widl
new file mode 100644
index 00000000000..c468b78f8e1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/namedconstructor.widl
@@ -0,0 +1,6 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+[NamedConstructor=Audio,
+ NamedConstructor=Audio(DOMString src)]
+interface HTMLAudioElement : HTMLMediaElement {
+ // ...
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/nointerfaceobject.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/nointerfaceobject.widl
new file mode 100644
index 00000000000..c17d75ff8fd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/nointerfaceobject.widl
@@ -0,0 +1,5 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+[NoInterfaceObject]
+interface Query {
+ any lookupEntry(unsigned long key);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/nullable.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/nullable.widl
new file mode 100644
index 00000000000..ccbf625ff8a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/nullable.widl
@@ -0,0 +1,9 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface MyConstants {
+ const boolean? ARE_WE_THERE_YET = false;
+};
+
+interface Node {
+ readonly attribute DOMString? namespaceURI;
+ // ...
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/nullableobjects.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/nullableobjects.widl
new file mode 100644
index 00000000000..83d1d40b2ac
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/nullableobjects.widl
@@ -0,0 +1,13 @@
+// Extracted from WebIDL spec 2011-05-23
+
+interface A {
+ // ...
+};
+interface B {
+ // ...
+};
+interface C {
+ void f(A? x);
+ void f(B? x);
+
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/operation-optional-arg.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/operation-optional-arg.widl
new file mode 100644
index 00000000000..379053b45f1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/operation-optional-arg.widl
@@ -0,0 +1,4 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface ColorCreator {
+ object createColor(float v1, float v2, float v3, optional float alpha = 3.5);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/overloading.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/overloading.widl
new file mode 100644
index 00000000000..ef1288a8877
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/overloading.widl
@@ -0,0 +1,20 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface A {
+ // ...
+};
+
+interface B {
+ // ...
+};
+
+interface C {
+ void f(A x);
+ void f(B x);
+};
+
+interface A {
+ /* f1 */ void f(DOMString a);
+ /* f2 */ void f([AllowAny] DOMString a, DOMString b, float... c);
+ /* f3 */ void f();
+ /* f4 */ void f(long a, DOMString b, optional DOMString c, float... d);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/overridebuiltins.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/overridebuiltins.widl
new file mode 100644
index 00000000000..79211c29e84
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/overridebuiltins.widl
@@ -0,0 +1,6 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+[OverrideBuiltins]
+interface StringMap2 {
+ readonly attribute unsigned long length;
+ getter DOMString lookup(DOMString key);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/partial-interface.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/partial-interface.widl
new file mode 100644
index 00000000000..90e7e0ea421
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/partial-interface.widl
@@ -0,0 +1,7 @@
+interface Foo {
+ attribute DOMString bar;
+};
+
+partial interface Foo {
+ attribute DOMString quux;
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/primitives.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/primitives.widl
new file mode 100644
index 00000000000..92939601a1a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/primitives.widl
@@ -0,0 +1,19 @@
+interface Primitives {
+ attribute boolean truth;
+ attribute byte character;
+ attribute octet value;
+ attribute short number;
+ attribute unsigned short positive;
+ attribute long big;
+ attribute unsigned long bigpositive;
+ attribute long long bigbig;
+ attribute unsigned long long bigbigpositive;
+ attribute float real;
+ attribute double bigreal;
+ attribute unrestricted float realwithinfinity;
+ attribute unrestricted double bigrealwithinfinity;
+ attribute DOMString string;
+ attribute ByteString bytes;
+ attribute Date date;
+ attribute RegExp regexp;
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/prototyperoot.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/prototyperoot.widl
new file mode 100644
index 00000000000..30dd5cbca13
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/prototyperoot.widl
@@ -0,0 +1,5 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+[PrototypeRoot]
+interface Node {
+ readonly attribute unsigned short nodeType;
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/putforwards.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/putforwards.widl
new file mode 100644
index 00000000000..1e50a4ee394
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/putforwards.widl
@@ -0,0 +1,5 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface Person {
+ [PutForwards=full] readonly attribute Name name;
+ attribute unsigned short age;
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/reg-operations.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/reg-operations.widl
new file mode 100644
index 00000000000..13997cb1d12
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/reg-operations.widl
@@ -0,0 +1,17 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface Dimensions {
+ attribute unsigned long width;
+ attribute unsigned long height;
+};
+
+exception NoPointerDevice { };
+
+interface Button {
+
+ // An operation that takes no arguments, returns a boolean
+ boolean isMouseOver();
+
+ // Overloaded operations.
+ void setDimensions(Dimensions size);
+ void setDimensions(unsigned long width, unsigned long height);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/replaceable.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/replaceable.widl
new file mode 100644
index 00000000000..c14d0c37689
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/replaceable.widl
@@ -0,0 +1,5 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface Counter {
+ [Replaceable] readonly attribute unsigned long value;
+ void increment();
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/sequence.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/sequence.widl
new file mode 100644
index 00000000000..6ba0d390d25
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/sequence.widl
@@ -0,0 +1,12 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+// edited to remove sequence as attributes, now invalid
+interface Canvas {
+ void drawPolygon(sequence<float> coordinates);
+ sequence<float> getInflectionPoints();
+ // ...
+};
+
+// Make sure sequence can still be registered as a type.
+interface Foo {
+ sequence bar();
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/serializer.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/serializer.widl
new file mode 100644
index 00000000000..6f6ccd0e8d5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/serializer.widl
@@ -0,0 +1,64 @@
+interface Transaction {
+ readonly attribute Account from;
+ readonly attribute Account to;
+ readonly attribute float amount;
+ readonly attribute DOMString description;
+ readonly attribute unsigned long number;
+
+ serializer;
+};
+
+interface Account {
+ attribute DOMString name;
+ attribute unsigned long number;
+ serializer DOMString serialize();
+};
+
+interface Transaction2 {
+ readonly attribute Account2 from;
+ readonly attribute Account2 to;
+ readonly attribute float amount;
+ readonly attribute DOMString description;
+ readonly attribute unsigned long number;
+
+ serializer = { from, to, amount, description };
+};
+
+interface Account2 {
+ attribute DOMString name;
+ attribute unsigned long number;
+ serializer = number;
+};
+
+interface Account3 {
+ attribute DOMString name;
+ attribute unsigned long number;
+
+ serializer = { attribute };
+};
+
+interface Account4 {
+ getter object getItem(unsigned long index);
+ serializer = { getter };
+};
+
+interface Account5 : Account {
+ attribute DOMString secondname;
+ serializer = { inherit, secondname };
+};
+
+interface Account6 : Account {
+ attribute DOMString secondname;
+ serializer = { inherit, attribute };
+};
+
+interface Account7 {
+ attribute DOMString name;
+ attribute unsigned long number;
+ serializer = [ name, number ];
+};
+
+interface Account8 {
+ getter object getItem(unsigned long index);
+ serializer = [ getter ];
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/static.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/static.widl
new file mode 100644
index 00000000000..5b2cd36590f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/static.widl
@@ -0,0 +1,11 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface Point { /* ... */ };
+
+interface Circle {
+ attribute float cx;
+ attribute float cy;
+ attribute float radius;
+
+ static readonly attribute long triangulationCount;
+ static Point triangulate(Circle c1, Circle c2, Circle c3);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/stringifier-attribute.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/stringifier-attribute.widl
new file mode 100644
index 00000000000..c964ecb93e6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/stringifier-attribute.widl
@@ -0,0 +1,6 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+[Constructor]
+interface Student {
+ attribute unsigned long id;
+ stringifier attribute DOMString name;
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/stringifier-custom.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/stringifier-custom.widl
new file mode 100644
index 00000000000..b5d7c87e7f4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/stringifier-custom.widl
@@ -0,0 +1,9 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+[Constructor]
+interface Student {
+ attribute unsigned long id;
+ attribute DOMString? familyName;
+ attribute DOMString givenName;
+
+ stringifier DOMString ();
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/stringifier.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/stringifier.widl
new file mode 100644
index 00000000000..4eb483d9b53
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/stringifier.widl
@@ -0,0 +1,8 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface A {
+ stringifier DOMString ();
+};
+
+interface A {
+ stringifier;
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/treatasnull.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/treatasnull.widl
new file mode 100644
index 00000000000..d3c55b008c0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/treatasnull.widl
@@ -0,0 +1,7 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface Dog {
+ attribute DOMString name;
+ attribute DOMString owner;
+
+ boolean isMemberOfBreed([TreatNullAs=EmptyString] DOMString breedName);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/treatasundefined.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/treatasundefined.widl
new file mode 100644
index 00000000000..e30050f8413
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/treatasundefined.widl
@@ -0,0 +1,7 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface Cat {
+ attribute DOMString name;
+ attribute DOMString owner;
+
+ boolean isMemberOfBreed([TreatUndefinedAs=EmptyString] DOMString breedName);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/typedef.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/typedef.widl
new file mode 100644
index 00000000000..b4c17d8d36a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/typedef.widl
@@ -0,0 +1,22 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+ interface Point {
+ attribute float x;
+ attribute float y;
+ };
+
+ typedef sequence<Point> PointSequence;
+
+ interface Rect {
+ attribute Point topleft;
+ attribute Point bottomright;
+ };
+
+ interface Widget {
+
+ readonly attribute Rect bounds;
+
+ boolean pointWithinBounds(Point p);
+ boolean allPointsWithinBounds(PointSequence ps);
+ };
+
+ typedef [Clamp] octet value; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/typesuffixes.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/typesuffixes.widl
new file mode 100644
index 00000000000..95e31c16902
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/typesuffixes.widl
@@ -0,0 +1,3 @@
+interface Suffixes {
+ void test(sequence<DOMString[]?>? foo);
+};
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/uniontype.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/uniontype.widl
new file mode 100644
index 00000000000..4d99f019630
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/uniontype.widl
@@ -0,0 +1,3 @@
+interface Union {
+ attribute (float or (Date or Event) or (Node or DOMString)?) test;
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/variadic-operations.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/variadic-operations.widl
new file mode 100644
index 00000000000..51fae4cc1ea
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/idl/variadic-operations.widl
@@ -0,0 +1,7 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface IntegerSet {
+ readonly attribute unsigned long cardinality;
+
+ void union(long... ints);
+ void intersection(long... ints);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/allowany.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/allowany.json
new file mode 100644
index 00000000000..8abc7f9e092
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/allowany.json
@@ -0,0 +1,109 @@
+[
+ {
+ "type": "interface",
+ "name": "B",
+ "partial": false,
+ "members": [
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "g",
+ "arguments": [],
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "g",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "B"
+ },
+ "name": "b"
+ }
+ ],
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "g",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [
+ {
+ "name": "AllowAny",
+ "arguments": null
+ }
+ ],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "s"
+ }
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/array.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/array.json
new file mode 100644
index 00000000000..39afaf6c8eb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/array.json
@@ -0,0 +1,34 @@
+[
+ {
+ "type": "interface",
+ "name": "LotteryResults",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": 2,
+ "nullableArray": [false, false],
+ "union": false,
+ "idlType": "unsigned short"
+ },
+ "name": "numbers",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": [
+ {
+ "name": "Constructor",
+ "arguments": null
+ }
+ ]
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/attributes.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/attributes.json
new file mode 100644
index 00000000000..cdf46b0ecc2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/attributes.json
@@ -0,0 +1,56 @@
+[
+ {
+ "type": "exception",
+ "name": "InvalidName",
+ "members": [
+ {
+ "type": "field",
+ "name": "reason",
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "exception",
+ "name": "NoSuchPet",
+ "members": [],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "Person",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned short"
+ },
+ "name": "age",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/callback.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/callback.json
new file mode 100644
index 00000000000..19ef4a6fa4e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/callback.json
@@ -0,0 +1,76 @@
+[
+ {
+ "type": "callback",
+ "name": "AsyncOperationCallback",
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "status"
+ }
+ ],
+ "extAttrs": []
+ },
+ {
+ "type": "callback interface",
+ "name": "EventHandler",
+ "partial": false,
+ "members": [
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "eventOccurred",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "details"
+ }
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/caller.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/caller.json
new file mode 100644
index 00000000000..a0fb5e396a5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/caller.json
@@ -0,0 +1,47 @@
+[
+ {
+ "type": "interface",
+ "name": "NumberQuadrupler",
+ "partial": false,
+ "members": [
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": true,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "compute",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "x"
+ }
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/constants.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/constants.json
new file mode 100644
index 00000000000..0fe6e92afc3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/constants.json
@@ -0,0 +1,141 @@
+[
+ {
+ "type": "interface",
+ "name": "Util",
+ "partial": false,
+ "members": [
+ {
+ "type": "const",
+ "nullable": false,
+ "idlType": "boolean",
+ "name": "DEBUG",
+ "value": {
+ "type": "boolean",
+ "value": false
+ },
+ "extAttrs": []
+ },
+ {
+ "type": "const",
+ "nullable": false,
+ "idlType": "short",
+ "name": "negative",
+ "value": {
+ "type": "number",
+ "value": -1
+ },
+ "extAttrs": []
+ },
+ {
+ "type": "const",
+ "nullable": false,
+ "idlType": "octet",
+ "name": "LF",
+ "value": {
+ "type": "number",
+ "value": 10
+ },
+ "extAttrs": []
+ },
+ {
+ "type": "const",
+ "nullable": false,
+ "idlType": "unsigned long",
+ "name": "BIT_MASK",
+ "value": {
+ "type": "number",
+ "value": 64512
+ },
+ "extAttrs": []
+ },
+ {
+ "type": "const",
+ "nullable": false,
+ "idlType": "float",
+ "name": "AVOGADRO",
+ "value": {
+ "type": "number",
+ "value": 6.022e+23
+ },
+ "extAttrs": []
+ },
+ {
+ "type": "const",
+ "nullable": false,
+ "idlType": "unrestricted float",
+ "name": "sobig",
+ "value": {
+ "type": "Infinity",
+ "negative": false
+ },
+ "extAttrs": []
+ },
+ {
+ "type": "const",
+ "nullable": false,
+ "idlType": "unrestricted double",
+ "name": "minusonedividedbyzero",
+ "value": {
+ "type": "Infinity",
+ "negative": true
+ },
+ "extAttrs": []
+ },
+ {
+ "type": "const",
+ "nullable": false,
+ "idlType": "short",
+ "name": "notanumber",
+ "value": {
+ "type": "NaN"
+ },
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "exception",
+ "name": "Error",
+ "members": [
+ {
+ "type": "const",
+ "nullable": false,
+ "idlType": "short",
+ "name": "ERR_UNKNOWN",
+ "value": {
+ "type": "number",
+ "value": 0
+ },
+ "extAttrs": []
+ },
+ {
+ "type": "const",
+ "nullable": false,
+ "idlType": "short",
+ "name": "ERR_OUT_OF_MEMORY",
+ "value": {
+ "type": "number",
+ "value": 1
+ },
+ "extAttrs": []
+ },
+ {
+ "type": "field",
+ "name": "errorCode",
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "short"
+ },
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/constructor.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/constructor.json
new file mode 100644
index 00000000000..e5944f32ee8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/constructor.json
@@ -0,0 +1,103 @@
+[
+ {
+ "type": "interface",
+ "name": "Circle",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "r",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "cx",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "cy",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "circumference",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": [
+ {
+ "name": "Constructor",
+ "arguments": null
+ },
+ {
+ "name": "Constructor",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "radius"
+ }
+ ]
+ }
+ ]
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/dictionary-inherits.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/dictionary-inherits.json
new file mode 100644
index 00000000000..367d7b1b4f3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/dictionary-inherits.json
@@ -0,0 +1,79 @@
+[
+ {
+ "type": "dictionary",
+ "name": "PaintOptions",
+ "partial": false,
+ "members": [
+ {
+ "type": "field",
+ "name": "fillPattern",
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": true,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "extAttrs": [],
+ "default": {
+ "type": "string",
+ "value": "black"
+ }
+ },
+ {
+ "type": "field",
+ "name": "strokePattern",
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": true,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "extAttrs": [],
+ "default": {
+ "type": "null"
+ }
+ },
+ {
+ "type": "field",
+ "name": "position",
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Point"
+ },
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "dictionary",
+ "name": "WetPaintOptions",
+ "partial": false,
+ "members": [
+ {
+ "type": "field",
+ "name": "hydrometry",
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "extAttrs": []
+ }
+ ],
+ "inheritance": "PaintOptions",
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/dictionary.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/dictionary.json
new file mode 100644
index 00000000000..7396cabae09
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/dictionary.json
@@ -0,0 +1,91 @@
+[
+ {
+ "type": "dictionary",
+ "name": "PaintOptions",
+ "partial": false,
+ "members": [
+ {
+ "type": "field",
+ "name": "fillPattern",
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": true,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "extAttrs": [],
+ "default": {
+ "type": "string",
+ "value": "black"
+ }
+ },
+ {
+ "type": "field",
+ "name": "strokePattern",
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": true,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "extAttrs": [],
+ "default": {
+ "type": "null"
+ }
+ },
+ {
+ "type": "field",
+ "name": "position",
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Point"
+ },
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "dictionary",
+ "name": "A",
+ "partial": true,
+ "members": [
+ {
+ "type": "field",
+ "name": "h",
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "long"
+ },
+ "extAttrs": []
+ },
+ {
+ "type": "field",
+ "name": "d",
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "long"
+ },
+ "extAttrs": []
+ }
+ ],
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/documentation-dos.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/documentation-dos.json
new file mode 100644
index 00000000000..340e039b449
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/documentation-dos.json
@@ -0,0 +1,10 @@
+[
+ {
+ "type": "interface",
+ "name": "Documentation",
+ "partial": false,
+ "members": [],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/documentation.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/documentation.json
new file mode 100644
index 00000000000..340e039b449
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/documentation.json
@@ -0,0 +1,10 @@
+[
+ {
+ "type": "interface",
+ "name": "Documentation",
+ "partial": false,
+ "members": [],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/enum.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/enum.json
new file mode 100644
index 00000000000..bd9058c594f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/enum.json
@@ -0,0 +1,105 @@
+[
+ {
+ "type": "enum",
+ "name": "MealType",
+ "values": [
+ "rice",
+ "noodles",
+ "other"
+ ],
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "Meal",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "MealType"
+ },
+ "name": "type",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "size",
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "initialize",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "MealType"
+ },
+ "name": "type"
+ },
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "size"
+ }
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/equivalent-decl.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/equivalent-decl.json
new file mode 100644
index 00000000000..55a787fdcf0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/equivalent-decl.json
@@ -0,0 +1,312 @@
+[
+ {
+ "type": "interface",
+ "name": "Dictionary",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "propertyCount",
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": true,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "getProperty",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "propertyName"
+ }
+ ],
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": true,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "setProperty",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "propertyName"
+ },
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "propertyValue"
+ }
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "Dictionary",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "propertyCount",
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "getProperty",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "propertyName"
+ }
+ ],
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "setProperty",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "propertyName"
+ },
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "propertyValue"
+ }
+ ],
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": true,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": null,
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "propertyName"
+ }
+ ],
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": true,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": null,
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "propertyName"
+ },
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "propertyValue"
+ }
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/exception-inheritance.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/exception-inheritance.json
new file mode 100644
index 00000000000..f4dc68699a6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/exception-inheritance.json
@@ -0,0 +1,37 @@
+[
+ {
+ "type": "exception",
+ "name": "DOMException",
+ "members": [
+ {
+ "type": "field",
+ "name": "code",
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned short"
+ },
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "exception",
+ "name": "HierarchyRequestError",
+ "members": [],
+ "inheritance": "DOMException",
+ "extAttrs": []
+ },
+ {
+ "type": "exception",
+ "name": "NoModificationAllowedError",
+ "members": [],
+ "inheritance": "DOMException",
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/exception.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/exception.json
new file mode 100644
index 00000000000..3f16de828ac
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/exception.json
@@ -0,0 +1,35 @@
+[
+ {
+ "type": "interface",
+ "name": "Dahut",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "type",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "exception",
+ "name": "SomeException",
+ "members": [],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/generic.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/generic.json
new file mode 100644
index 00000000000..70eafdedef8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/generic.json
@@ -0,0 +1,156 @@
+[
+ {
+ "type": "interface",
+ "name": "Foo",
+ "partial": false,
+ "members": [
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": "Promise",
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": {
+ "sequence": false,
+ "generic": "ResponsePromise",
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": {
+ "sequence": true,
+ "generic": "sequence",
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": true,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ }
+ }
+ }
+ },
+ "name": "bar",
+ "arguments": [],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "ServiceWorkerClients",
+ "partial": false,
+ "members": [
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": "Promise",
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": true,
+ "nullableArray": [false],
+ "array": 1,
+ "union": false,
+ "idlType": "Client"
+ }
+ },
+ "name": "getServiced",
+ "arguments": [],
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": "Promise",
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "any"
+ }
+ },
+ "name": "reloadAll",
+ "arguments": [],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "FetchEvent",
+ "partial": false,
+ "members": [
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": "ResponsePromise",
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "any"
+ }
+ },
+ "name": "default",
+ "arguments": [],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": "Event",
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/getter-setter.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/getter-setter.json
new file mode 100644
index 00000000000..94d20d594db
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/getter-setter.json
@@ -0,0 +1,114 @@
+[
+ {
+ "type": "interface",
+ "name": "Dictionary",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "propertyCount",
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": true,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": null,
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "propertyName"
+ }
+ ],
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": true,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": null,
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "propertyName"
+ },
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "propertyValue"
+ }
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/identifier-qualified-names.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/identifier-qualified-names.json
new file mode 100644
index 00000000000..a91f8c8eb53
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/identifier-qualified-names.json
@@ -0,0 +1,217 @@
+[
+ {
+ "type": "typedef",
+ "typeExtAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "number",
+ "extAttrs": []
+ },
+ {
+ "type": "exception",
+ "name": "FrameworkException",
+ "members": [
+ {
+ "type": "const",
+ "nullable": false,
+ "idlType": "long",
+ "name": "ERR_NOT_FOUND",
+ "value": {
+ "type": "number",
+ "value": 1
+ },
+ "extAttrs": []
+ },
+ {
+ "type": "field",
+ "name": "code",
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "long"
+ },
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "System",
+ "partial": false,
+ "members": [
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "object"
+ },
+ "name": "createObject",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "interface"
+ }
+ ],
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": true,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": null,
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "keyName"
+ }
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "TextField",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "boolean"
+ },
+ "name": "const",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": true,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "value",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "Foo",
+ "partial": false,
+ "members": [
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "op",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "object"
+ },
+ "name": "interface"
+ }
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/implements.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/implements.json
new file mode 100644
index 00000000000..fa00e337426
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/implements.json
@@ -0,0 +1,107 @@
+[
+ {
+ "type": "interface",
+ "name": "Node",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned short"
+ },
+ "name": "nodeType",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "EventTarget",
+ "partial": false,
+ "members": [
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "addEventListener",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "type"
+ },
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "EventListener"
+ },
+ "name": "listener"
+ },
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "boolean"
+ },
+ "name": "useCapture"
+ }
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "implements",
+ "target": "Node",
+ "implements": "EventTarget",
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/indexed-properties.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/indexed-properties.json
new file mode 100644
index 00000000000..23cc4ab1023
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/indexed-properties.json
@@ -0,0 +1,272 @@
+[
+ {
+ "type": "interface",
+ "name": "OrderedMap",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "size",
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": true,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "any"
+ },
+ "name": "getByIndex",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "index"
+ }
+ ],
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": true,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "setByIndex",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "index"
+ },
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "any"
+ },
+ "name": "value"
+ }
+ ],
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": true,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "removeByIndex",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "index"
+ }
+ ],
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": true,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "any"
+ },
+ "name": "get",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "name"
+ }
+ ],
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": true,
+ "creator": true,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "set",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "name"
+ },
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "any"
+ },
+ "name": "value"
+ }
+ ],
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": true,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "remove",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "name"
+ }
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/inherits-getter.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/inherits-getter.json
new file mode 100644
index 00000000000..468e3caef71
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/inherits-getter.json
@@ -0,0 +1,71 @@
+[
+ {
+ "type": "interface",
+ "name": "Animal",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "name",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "Person",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned short"
+ },
+ "name": "age",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": true,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "name",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": "Animal",
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/interface-inherits.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/interface-inherits.json
new file mode 100644
index 00000000000..eee07cd1dec
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/interface-inherits.json
@@ -0,0 +1,80 @@
+[
+ {
+ "type": "interface",
+ "name": "Animal",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "name",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "Human",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Dog"
+ },
+ "name": "pet",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": "Animal",
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "Dog",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Human"
+ },
+ "name": "owner",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": "Animal",
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/iterator.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/iterator.json
new file mode 100644
index 00000000000..cc3c9ec505d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/iterator.json
@@ -0,0 +1,301 @@
+[
+ {
+ "type": "interface",
+ "name": "SessionManager",
+ "partial": false,
+ "members": [
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Session"
+ },
+ "name": "getSessionForUser",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "username"
+ }
+ ],
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "sessionCount",
+ "extAttrs": []
+ },
+ {
+ "type": "iterator",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Session"
+ },
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "Session",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "username",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "SessionManager2",
+ "partial": false,
+ "members": [
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Session2"
+ },
+ "name": "getSessionForUser",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "username"
+ }
+ ],
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "sessionCount",
+ "extAttrs": []
+ },
+ {
+ "type": "iterator",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Session2"
+ },
+ "iteratorObject": "SessionIterator",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "Session2",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "username",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "SessionIterator",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "remainingSessions",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "NodeList",
+ "partial": false,
+ "members": [
+ {
+ "type": "iterator",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Node"
+ },
+ "iteratorObject": "NodeIterator",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "NodeIterator",
+ "partial": false,
+ "members": [
+ {
+ "type": "iterator",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Node"
+ },
+ "iteratorObject": "object",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/map.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/map.json
new file mode 100644
index 00000000000..03ce9412ed0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/map.json
@@ -0,0 +1,29 @@
+[
+ {
+ "type": "interface",
+ "name": "HeaderMap",
+ "partial": false,
+ "members": [],
+ "inheritance": null,
+ "extAttrs": [{
+ "name": "MapClass",
+ "arguments": null,
+ "typePair": [{
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ }]
+ }]
+ }
+]
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/namedconstructor.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/namedconstructor.json
new file mode 100644
index 00000000000..a947a64a4e2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/namedconstructor.json
@@ -0,0 +1,42 @@
+[
+ {
+ "type": "interface",
+ "name": "HTMLAudioElement",
+ "partial": false,
+ "members": [],
+ "inheritance": "HTMLMediaElement",
+ "extAttrs": [
+ {
+ "name": "NamedConstructor",
+ "arguments": null,
+ "rhs": {
+ "type": "identifier",
+ "value": "Audio"
+ }
+ },
+ {
+ "name": "NamedConstructor",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "src"
+ }
+ ],
+ "rhs": {
+ "type": "identifier",
+ "value": "Audio"
+ }
+ }
+ ]
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/nointerfaceobject.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/nointerfaceobject.json
new file mode 100644
index 00000000000..90f0d63c82e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/nointerfaceobject.json
@@ -0,0 +1,52 @@
+[
+ {
+ "type": "interface",
+ "name": "Query",
+ "partial": false,
+ "members": [
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "any"
+ },
+ "name": "lookupEntry",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "key"
+ }
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": [
+ {
+ "name": "NoInterfaceObject",
+ "arguments": null
+ }
+ ]
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/nullable.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/nullable.json
new file mode 100644
index 00000000000..300442f0d46
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/nullable.json
@@ -0,0 +1,48 @@
+[
+ {
+ "type": "interface",
+ "name": "MyConstants",
+ "partial": false,
+ "members": [
+ {
+ "type": "const",
+ "nullable": true,
+ "idlType": "boolean",
+ "name": "ARE_WE_THERE_YET",
+ "value": {
+ "type": "boolean",
+ "value": false
+ },
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "Node",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": true,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "namespaceURI",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/nullableobjects.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/nullableobjects.json
new file mode 100644
index 00000000000..40f7db0c1c9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/nullableobjects.json
@@ -0,0 +1,99 @@
+[
+ {
+ "type": "interface",
+ "name": "A",
+ "partial": false,
+ "members": [],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "B",
+ "partial": false,
+ "members": [],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "C",
+ "partial": false,
+ "members": [
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "f",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": true,
+ "array": false,
+ "union": false,
+ "idlType": "A"
+ },
+ "name": "x"
+ }
+ ],
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "f",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": true,
+ "array": false,
+ "union": false,
+ "idlType": "B"
+ },
+ "name": "x"
+ }
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/operation-optional-arg.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/operation-optional-arg.json
new file mode 100644
index 00000000000..6ca32576b7a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/operation-optional-arg.json
@@ -0,0 +1,93 @@
+[
+ {
+ "type": "interface",
+ "name": "ColorCreator",
+ "partial": false,
+ "members": [
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "object"
+ },
+ "name": "createColor",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "v1"
+ },
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "v2"
+ },
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "v3"
+ },
+ {
+ "optional": true,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "alpha",
+ "default": {
+ "type": "number",
+ "value": 3.5
+ }
+ }
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/overloading.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/overloading.json
new file mode 100644
index 00000000000..c3baa439623
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/overloading.json
@@ -0,0 +1,312 @@
+[
+ {
+ "type": "interface",
+ "name": "A",
+ "partial": false,
+ "members": [],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "B",
+ "partial": false,
+ "members": [],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "C",
+ "partial": false,
+ "members": [
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "f",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "A"
+ },
+ "name": "x"
+ }
+ ],
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "f",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "B"
+ },
+ "name": "x"
+ }
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "A",
+ "partial": false,
+ "members": [
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "f",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "a"
+ }
+ ],
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "f",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [
+ {
+ "name": "AllowAny",
+ "arguments": null
+ }
+ ],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "a"
+ },
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "b"
+ },
+ {
+ "optional": false,
+ "variadic": true,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "c"
+ }
+ ],
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "f",
+ "arguments": [],
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "f",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "long"
+ },
+ "name": "a"
+ },
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "b"
+ },
+ {
+ "optional": true,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "c"
+ },
+ {
+ "optional": false,
+ "variadic": true,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "d"
+ }
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/overridebuiltins.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/overridebuiltins.json
new file mode 100644
index 00000000000..9e2f795e2ae
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/overridebuiltins.json
@@ -0,0 +1,69 @@
+[
+ {
+ "type": "interface",
+ "name": "StringMap2",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "length",
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": true,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "lookup",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "key"
+ }
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": [
+ {
+ "name": "OverrideBuiltins",
+ "arguments": null
+ }
+ ]
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/partial-interface.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/partial-interface.json
new file mode 100644
index 00000000000..53c65a453bd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/partial-interface.json
@@ -0,0 +1,53 @@
+[
+ {
+ "type": "interface",
+ "name": "Foo",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "bar",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "Foo",
+ "partial": true,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "quux",
+ "extAttrs": []
+ }
+ ],
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/primitives.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/primitives.json
new file mode 100644
index 00000000000..7160c2a4ce0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/primitives.json
@@ -0,0 +1,300 @@
+[
+ {
+ "type": "interface",
+ "name": "Primitives",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "boolean"
+ },
+ "name": "truth",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "byte"
+ },
+ "name": "character",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "octet"
+ },
+ "name": "value",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "short"
+ },
+ "name": "number",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned short"
+ },
+ "name": "positive",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "long"
+ },
+ "name": "big",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "bigpositive",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "long long"
+ },
+ "name": "bigbig",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long long"
+ },
+ "name": "bigbigpositive",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "real",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "double"
+ },
+ "name": "bigreal",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unrestricted float"
+ },
+ "name": "realwithinfinity",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unrestricted double"
+ },
+ "name": "bigrealwithinfinity",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "string",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "ByteString"
+ },
+ "name": "bytes",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Date"
+ },
+ "name": "date",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "RegExp"
+ },
+ "name": "regexp",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/prototyperoot.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/prototyperoot.json
new file mode 100644
index 00000000000..666798d94cf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/prototyperoot.json
@@ -0,0 +1,33 @@
+[
+ {
+ "type": "interface",
+ "name": "Node",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned short"
+ },
+ "name": "nodeType",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": [
+ {
+ "name": "PrototypeRoot",
+ "arguments": null
+ }
+ ]
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/putforwards.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/putforwards.json
new file mode 100644
index 00000000000..bd5e619cac5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/putforwards.json
@@ -0,0 +1,54 @@
+[
+ {
+ "type": "interface",
+ "name": "Person",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Name"
+ },
+ "name": "name",
+ "extAttrs": [
+ {
+ "name": "PutForwards",
+ "arguments": null,
+ "rhs": {
+ "type": "identifier",
+ "value": "full"
+ }
+ }
+ ]
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned short"
+ },
+ "name": "age",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/reg-operations.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/reg-operations.json
new file mode 100644
index 00000000000..c827fff03b6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/reg-operations.json
@@ -0,0 +1,168 @@
+[
+ {
+ "type": "interface",
+ "name": "Dimensions",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "width",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "height",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "exception",
+ "name": "NoPointerDevice",
+ "members": [],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "Button",
+ "partial": false,
+ "members": [
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "boolean"
+ },
+ "name": "isMouseOver",
+ "arguments": [],
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "setDimensions",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Dimensions"
+ },
+ "name": "size"
+ }
+ ],
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "setDimensions",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "width"
+ },
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "height"
+ }
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/replaceable.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/replaceable.json
new file mode 100644
index 00000000000..4d25f3d9317
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/replaceable.json
@@ -0,0 +1,54 @@
+[
+ {
+ "type": "interface",
+ "name": "Counter",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "value",
+ "extAttrs": [
+ {
+ "name": "Replaceable",
+ "arguments": null
+ }
+ ]
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "increment",
+ "arguments": [],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/sequence.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/sequence.json
new file mode 100644
index 00000000000..7ddd402b402
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/sequence.json
@@ -0,0 +1,113 @@
+[
+ {
+ "type": "interface",
+ "name": "Canvas",
+ "partial": false,
+ "members": [
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "drawPolygon",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": true,
+ "generic": "sequence",
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ }
+ },
+ "name": "coordinates"
+ }
+ ],
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": true,
+ "generic": "sequence",
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ }
+ },
+ "name": "getInflectionPoints",
+ "arguments": [],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "Foo",
+ "partial": false,
+ "members": [
+
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "sequence"
+ },
+ "name": "bar",
+ "arguments": [],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/serializer.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/serializer.json
new file mode 100644
index 00000000000..79b501fcbc4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/serializer.json
@@ -0,0 +1,591 @@
+[
+ {
+ "type": "interface",
+ "name": "Transaction",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Account"
+ },
+ "name": "from",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Account"
+ },
+ "name": "to",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "amount",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "description",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "number",
+ "extAttrs": []
+ },
+ {
+ "type": "serializer",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "Account",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "name",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "number",
+ "extAttrs": []
+ },
+ {
+ "type": "serializer",
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "operation": {
+ "name": "serialize",
+ "arguments": []
+ },
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "Transaction2",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Account2"
+ },
+ "name": "from",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Account2"
+ },
+ "name": "to",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "amount",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "description",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "number",
+ "extAttrs": []
+ },
+ {
+ "type": "serializer",
+ "patternMap": true,
+ "names": [
+ "from",
+ "to",
+ "amount",
+ "description"
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "Account2",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "name",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "number",
+ "extAttrs": []
+ },
+ {
+ "type": "serializer",
+ "name": "number",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "Account3",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "name",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "number",
+ "extAttrs": []
+ },
+ {
+ "type": "serializer",
+ "patternMap": true,
+ "names": [
+ "attribute"
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "Account4",
+ "partial": false,
+ "members": [
+ {
+ "type": "operation",
+ "getter": true,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "object"
+ },
+ "name": "getItem",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "index"
+ }
+ ],
+ "extAttrs": []
+ },
+ {
+ "type": "serializer",
+ "patternMap": true,
+ "names": [
+ "getter"
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "Account5",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "secondname",
+ "extAttrs": []
+ },
+ {
+ "type": "serializer",
+ "patternMap": true,
+ "names": [
+ "inherit",
+ "secondname"
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": "Account",
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "Account6",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "secondname",
+ "extAttrs": []
+ },
+ {
+ "type": "serializer",
+ "patternMap": true,
+ "names": [
+ "inherit",
+ "attribute"
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": "Account",
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "Account7",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "name",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "number",
+ "extAttrs": []
+ },
+ {
+ "type": "serializer",
+ "patternList": true,
+ "names": [
+ "name",
+ "number"
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "Account8",
+ "partial": false,
+ "members": [
+ {
+ "type": "operation",
+ "getter": true,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "object"
+ },
+ "name": "getItem",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "index"
+ }
+ ],
+ "extAttrs": []
+ },
+ {
+ "type": "serializer",
+ "patternList": true,
+ "names": [
+ "getter"
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/static.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/static.json
new file mode 100644
index 00000000000..faab12b2966
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/static.json
@@ -0,0 +1,151 @@
+[
+ {
+ "type": "interface",
+ "name": "Point",
+ "partial": false,
+ "members": [],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "Circle",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "cx",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "cy",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "radius",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": true,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "long"
+ },
+ "name": "triangulationCount",
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": true,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Point"
+ },
+ "name": "triangulate",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Circle"
+ },
+ "name": "c1"
+ },
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Circle"
+ },
+ "name": "c2"
+ },
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Circle"
+ },
+ "name": "c3"
+ }
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/stringifier-attribute.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/stringifier-attribute.json
new file mode 100644
index 00000000000..196ee6f1a7c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/stringifier-attribute.json
@@ -0,0 +1,50 @@
+[
+ {
+ "type": "interface",
+ "name": "Student",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "id",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": true,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "name",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": [
+ {
+ "name": "Constructor",
+ "arguments": null
+ }
+ ]
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/stringifier-custom.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/stringifier-custom.json
new file mode 100644
index 00000000000..b4ab7392e5a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/stringifier-custom.json
@@ -0,0 +1,88 @@
+[
+ {
+ "type": "interface",
+ "name": "Student",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "id",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": true,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "familyName",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "givenName",
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": null,
+ "arguments": [],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": [
+ {
+ "name": "Constructor",
+ "arguments": null
+ }
+ ]
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/stringifier.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/stringifier.json
new file mode 100644
index 00000000000..ad3abde85f4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/stringifier.json
@@ -0,0 +1,52 @@
+[
+ {
+ "type": "interface",
+ "name": "A",
+ "partial": false,
+ "members": [
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": null,
+ "arguments": [],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "A",
+ "partial": false,
+ "members": [
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": true,
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/treatasnull.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/treatasnull.json
new file mode 100644
index 00000000000..8bacb967acc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/treatasnull.json
@@ -0,0 +1,90 @@
+[
+ {
+ "type": "interface",
+ "name": "Dog",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "name",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "owner",
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "boolean"
+ },
+ "name": "isMemberOfBreed",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [
+ {
+ "name": "TreatNullAs",
+ "arguments": null,
+ "rhs": {
+ "type": "identifier",
+ "value": "EmptyString"
+ }
+ }
+ ],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "breedName"
+ }
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/treatasundefined.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/treatasundefined.json
new file mode 100644
index 00000000000..91c4d25f5d1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/treatasundefined.json
@@ -0,0 +1,90 @@
+[
+ {
+ "type": "interface",
+ "name": "Cat",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "name",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "owner",
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "boolean"
+ },
+ "name": "isMemberOfBreed",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [
+ {
+ "name": "TreatUndefinedAs",
+ "arguments": null,
+ "rhs": {
+ "type": "identifier",
+ "value": "EmptyString"
+ }
+ }
+ ],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ },
+ "name": "breedName"
+ }
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/typedef.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/typedef.json
new file mode 100644
index 00000000000..ffdeea945d7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/typedef.json
@@ -0,0 +1,226 @@
+[
+ {
+ "type": "interface",
+ "name": "Point",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "x",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ "name": "y",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "typedef",
+ "typeExtAttrs": [],
+ "idlType": {
+ "sequence": true,
+ "generic": "sequence",
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Point"
+ }
+ },
+ "name": "PointSequence",
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "Rect",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Point"
+ },
+ "name": "topleft",
+ "extAttrs": []
+ },
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Point"
+ },
+ "name": "bottomright",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "interface",
+ "name": "Widget",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Rect"
+ },
+ "name": "bounds",
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "boolean"
+ },
+ "name": "pointWithinBounds",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Point"
+ },
+ "name": "p"
+ }
+ ],
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "boolean"
+ },
+ "name": "allPointsWithinBounds",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "PointSequence"
+ },
+ "name": "ps"
+ }
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ },
+ {
+ "type": "typedef",
+ "typeExtAttrs": [
+ {
+ "name": "Clamp",
+ "arguments": null
+ }
+ ],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "octet"
+ },
+ "name": "value",
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/typesuffixes.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/typesuffixes.json
new file mode 100644
index 00000000000..790c444ef46
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/typesuffixes.json
@@ -0,0 +1,55 @@
+[
+ {
+ "type": "interface",
+ "name": "Suffixes",
+ "partial": false,
+ "members": [
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "test",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": false,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": true,
+ "generic": "sequence",
+ "nullable": true,
+ "array": false,
+ "union": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": true,
+ "array": 1,
+ "nullableArray": [false],
+ "union": false,
+ "idlType": "DOMString"
+ }
+ },
+ "name": "foo"
+ }
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/uniontype.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/uniontype.json
new file mode 100644
index 00000000000..43e25fd6bfb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/uniontype.json
@@ -0,0 +1,87 @@
+[
+ {
+ "type": "interface",
+ "name": "Union",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": true,
+ "idlType": [
+ {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "float"
+ },
+ {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": true,
+ "idlType": [
+ {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Date"
+ },
+ {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Event"
+ }
+ ]
+ },
+ {
+ "sequence": false,
+ "generic": null,
+ "nullable": true,
+ "array": false,
+ "union": true,
+ "idlType": [
+ {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "Node"
+ },
+ {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "DOMString"
+ }
+ ]
+ }
+ ]
+ },
+ "name": "test",
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/variadic-operations.json b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/variadic-operations.json
new file mode 100644
index 00000000000..431ec0cb115
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/syntax/json/variadic-operations.json
@@ -0,0 +1,100 @@
+[
+ {
+ "type": "interface",
+ "name": "IntegerSet",
+ "partial": false,
+ "members": [
+ {
+ "type": "attribute",
+ "static": false,
+ "stringifier": false,
+ "inherit": false,
+ "readonly": true,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "unsigned long"
+ },
+ "name": "cardinality",
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "union",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": true,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "long"
+ },
+ "name": "ints"
+ }
+ ],
+ "extAttrs": []
+ },
+ {
+ "type": "operation",
+ "getter": false,
+ "setter": false,
+ "creator": false,
+ "deleter": false,
+ "legacycaller": false,
+ "static": false,
+ "stringifier": false,
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "void"
+ },
+ "name": "intersection",
+ "arguments": [
+ {
+ "optional": false,
+ "variadic": true,
+ "extAttrs": [],
+ "idlType": {
+ "sequence": false,
+ "generic": null,
+ "nullable": false,
+ "array": false,
+ "union": false,
+ "idlType": "long"
+ },
+ "name": "ints"
+ }
+ ],
+ "extAttrs": []
+ }
+ ],
+ "inheritance": null,
+ "extAttrs": []
+ }
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/web/make-web-tests.js b/tests/wpt/web-platform-tests/resources/webidl2/test/web/make-web-tests.js
new file mode 100644
index 00000000000..34c5a5c2b46
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/web/make-web-tests.js
@@ -0,0 +1,51 @@
+
+// generates tests that work in a browser
+
+// XXX
+// have it run through valid and invalid properly
+
+var pth = require("path")
+, fs = require("fs")
+, dir = function (path) {
+ return pth.join(__dirname, "..", path);
+ }
+, allFromDir = function (dir, ext, asJSON) {
+ return fs.readdirSync(dir)
+ .filter(function (it) { return ext.test(it); })
+ .map(function (it) {
+ var cnt = fs.readFileSync(pth.join(dir, it), "utf8");
+ return asJSON ? JSON.parse(cnt) : cnt;
+ });
+ }
+, data = {
+ valid: {
+ json: allFromDir(dir("syntax/json"), /\.json$/, true)
+ , idl: allFromDir(dir("syntax/idl"), /\.w?idl$/, false)
+ }
+ , invalid:{
+ json: allFromDir(dir("invalid/json"), /\.json$/, true)
+ , idl: allFromDir(dir("invalid/idl"), /\.w?idl$/, false)
+ }
+ }
+, html = [
+ "<!DOCTYPE html>"
+ , "<html>"
+ , " <head><meta charset='utf-8''><link rel='stylesheet' href='../../node_modules/mocha/mocha.css'>"
+ , " <title>WebIDL2 Browser Tests</title>"
+ , " <script>var data = " + JSON.stringify(data) + "</script>"
+ , " </head>"
+ , " <body><div id='mocha'></div>"
+ , " <script src='https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js'></script>"
+ , " <script src='../../node_modules/expect.js/expect.js'></script>"
+ , " <script src='../../node_modules/mocha/mocha.js'></script>"
+ , " <script src='../../node_modules/jsondiffpatch/jsondiffpatch.min.js'></script>"
+ , " <script src='../../lib/webidl2.js'></script>"
+ , " <script>mocha.setup('bdd');</script>"
+ , " <script src='run-tests.js'></script>"
+ , " <script>mocha.run();</script>"
+ , " </body>"
+ , "</html>"
+ ].join("\n")
+;
+
+fs.writeFileSync("browser-tests.html", html, "utf8");
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/web/run-tests.js b/tests/wpt/web-platform-tests/resources/webidl2/test/web/run-tests.js
new file mode 100644
index 00000000000..a72800b8bdb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/web/run-tests.js
@@ -0,0 +1,48 @@
+
+describe("Parses all of the IDLs to produce the correct ASTs", function () {
+ for (var i = 0, n = data.valid.idl.length; i < n; i++) {
+ var idl = data.valid.idl[i], json = data.valid.json[i];
+ var func = (function (idl, json) {
+ return function () {
+ try {
+ // the AST contains NaN and +/-Infinity that cannot be serialised to JSON
+ // the stored JSON ASTs use the same replacement function as is used below
+ // so we compare based on that
+ var diff = jsondiffpatch.diff(json, WebIDL2.parse(idl));
+ if (diff && debug) console.log(JSON.stringify(diff, null, 4));
+ expect(diff).to.be(undefined);
+ }
+ catch (e) {
+ console.log(e.toString());
+ throw e;
+ }
+ };
+ }(idl, json));
+ it("should produce the same AST for " + i, func);
+ }
+});
+
+describe("Parses all of the invalid IDLs to check that they blow up correctly", function () {
+ for (var i = 0, n = data.invalid.idl.length; i < n; i++) {
+ var idl = data.invalid.idl[i], error = data.invalid.json[i];
+ var func = (function (idl, err) {
+ return function () {
+ var error;
+ try {
+ var ast = WebIDL2.parse(idl);
+ console.log(JSON.stringify(ast, null, 4));
+ }
+ catch (e) {
+ error = e;
+ }
+ finally {
+ expect(error).to.be.ok();
+ expect(error.message).to.equal(err.message);
+ expect(error.line).to.equal(err.line);
+ }
+
+ };
+ }(idl, error));
+ it("should produce the right error for " + i, func);
+ }
+});
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/.gitignore b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/.gitignore
new file mode 100644
index 00000000000..bffeb270d0e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/.gitignore
@@ -0,0 +1,3 @@
+obj/
+test/valid/obj
+test/invalid/obj
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/LICENSE b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/LICENSE
new file mode 100644
index 00000000000..d6456956733
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/Makefile b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/Makefile
new file mode 100644
index 00000000000..d517466e48d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/Makefile
@@ -0,0 +1,158 @@
+########################################################################
+# $Id$
+# Copyright 2009 Aplix Corporation. All rights reserved.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+# http://www.apache.org/licenses/LICENSE-2.0
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+########################################################################
+
+UNAME = $(shell uname)
+INCDIRS = $(OBJDIR)
+SRCDIR = src
+DOCDIR = doc
+EXAMPLESDIR = examples
+OBJDIR = obj
+
+########################################################################
+# Linux configuration
+#
+ifneq (,$(filter Linux%, $(UNAME)))
+
+CFLAGS = -g -Wall -Werror -O0 $(patsubst %, -I%, $(INCDIRS))
+OBJSUFFIX = .o
+EXESUFFIX =
+#LIBS = -lefence
+OBJOPTION = -o
+EXEOPTION = -o
+
+else
+########################################################################
+# Darwin configuration
+#
+ifneq (,$(filter Darwin%, $(UNAME)))
+
+CFLAGS = -g -Wall -Werror -O2 $(patsubst %, -I%, $(INCDIRS))
+OBJSUFFIX = .o
+EXESUFFIX =
+OBJOPTION = -o
+# The -o in the following line has a space after it, which must not be removed.
+EXEOPTION = -o
+
+else
+########################################################################
+# Windows (cygwin but using MS compiler) configuration
+#
+# this is messy - should probably use vcvars.bat
+ifneq (,$(filter CYGWIN%, $(UNAME)))
+VISUALSTUDIODIR = $(wildcard /cygdrive/c/Program*Files/Microsoft*Visual*Studio*8)
+SDKDIR = $(wildcard /cygdrive/c/Program*Files/Microsoft*SDKs/Windows/*/Lib)
+ifeq (,$(VISUALSTUDIODIR))
+VISUALSTUDIODIR = $(wildcard /cygdrive/c/Program\ Files\ */Microsoft*Visual*Studio*10*)
+endif
+ifeq (,$(VISUALSTUDIODIR))
+VISUALSTUDIODIR = $(wildcard /cygdrive/c/Program\ Files\ */Microsoft*Visual*Studio*11*)
+endif
+# this is revelvant for vs2012 and windows 8 - sdk location has changed
+ifeq (,$(SDKDIR))
+SDKDIR = $(wildcard /cygdrive/c/Program\ Files\ */Windows*Kits)
+endif
+
+ifeq (,$(VISUALSTUDIODIR))
+$(error Could not find MS Visual Studio)
+else
+WINVISUALSTUDIODIR = $(shell cygpath -w '$(VISUALSTUDIODIR)')
+WINSDKDIR = $(shell cygpath -w '$(SDKDIR)')
+
+#$(error $(VISUALSTUDIODIR))
+
+CC = \
+ Lib='$(WINVISUALSTUDIODIR)\VC\LIB;$(WINVISUALSTUDIODIR)\VC\PlatformSDK\Lib;$(WINSDKDIR)' \
+ PATH='$(VISUALSTUDIODIR)/Common7/IDE:$(VISUALSTUDIODIR)/VC/BIN:$(VISUALSTUDIODIR)/Common7/Tools:$(VISUALSTUDIODIR)/SDK/v2.0/bin:$(VISUALSTUDIODIR)/8.0/Lib/win8/um/x86:'$$PATH \
+ Include='$(WINVISUALSTUDIODIR)\VC\INCLUDE;$(WINVISUALSTUDIODIR)\VC\PlatformSDK\Include' \
+ cl
+endif
+
+CFLAGS = /nologo /WX /W3 /wd4996 /Zi /O2 $(patsubst %, /I%, $(INCDIRS))
+OBJSUFFIX = .obj
+EXESUFFIX = .exe
+OBJOPTION = /Fo
+EXEOPTION = /Fe
+
+endif
+endif
+endif
+
+########################################################################
+# Common makefile
+#
+WIDLPROC = $(OBJDIR)/widlproc$(EXESUFFIX)
+DTD = $(OBJDIR)/widlprocxml.dtd
+
+ALL = $(WIDLPROC) $(DTD)
+all : $(ALL)
+
+SRCS = \
+ comment.c \
+ lex.c \
+ main.c \
+ misc.c \
+ node.c \
+ parse.c \
+ process.c
+
+OBJS = $(patsubst %.c, $(OBJDIR)/%$(OBJSUFFIX), $(SRCS))
+$(WIDLPROC) : $(OBJS)
+ $(CC) $(CFLAGS) $(EXEOPTION)$@ $^ $(LIBS)
+
+$(OBJDIR)/%$(OBJSUFFIX) : $(SRCDIR)/%.c
+ mkdir -p $(dir $@)
+ $(CC) $(CFLAGS) $(OBJOPTION)$@ -c $<
+
+$(OBJDIR)/%.d : $(SRCDIR)/%.c
+ mkdir -p $(dir $@)
+ cc $(patsubst %, -I%, $(INCDIRS)) -MM -MG -MT $(patsubst %.d, %$(OBJSUFFIX), $@) $< | sed '$(patsubst %, s| \(%\)| $(OBJDIR)/\1|;, $(AUTOGENHEADERS))' >$@
+
+include $(patsubst %.c, $(OBJDIR)/%.d, $(SRCS))
+
+
+$(DTD) : $(DOCDIR)/htmltodtd.xsl $(DOCDIR)/widlproc.html
+ xsltproc -html $^ >$@
+
+clean :
+ rm -f $(ALL) $(OBJS)
+
+veryclean :
+ rm -rf $(OBJDIR)
+
+SVNFILES = $(shell test -d .svn && svn info -R . | sed -n 's/^Path: \(.*\)$$/\1/p')
+SVNBRANCH = $(shell test -d .svn && svn info . | sed -n 's|^URL:.*/\([^/]*\)$$|\1|p')
+SVNREV = $(shell test -d .svn && svn info -R . | sed -n 's/^Last Changed Rev: \([0-9][0-9]*\)$$/\1/p' | sort -g | tail -1)
+
+SVNLOG = history
+$(SVNLOG) : $(SVNFILES)
+ svn log -vrHEAD:311 >$@
+
+zip : $(OBJDIR)/widlproc-$(SVNBRANCH)$(SVNREV).zip
+$(OBJDIR)/widlproc-$(SVNBRANCH)$(SVNREV).zip : $(WIDLPROC) $(DTD) $(DOCDIR)/widlproc.html $(SRCDIR)/widlprocxmltohtml.xsl Makefile $(SVNLOG)
+ rm -f $@
+ zip -j $@ $^ -x Makefile
+ zip $@ examples/*.widl examples/*.css examples/Makefile examples/README examples/*.xsl examples/*.html
+
+srczip : widlproc-src-$(SVNBRANCH)$(SVNREV).zip
+
+widlproc-src-%.zip : $(SVNFILES) $(SVNLOG)
+ zip $@ $^
+
+examples :
+ $(MAKE) -C examples SRCDIR=../src OBJDIR=../obj EXAMPLESOBJDIR=../obj/examples
+
+test : $(OBJS)
+ $(MAKE) -C test SRCDIR=../src OBJDIR=../obj
+
+.DELETE_ON_ERROR:
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/README.md b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/README.md
new file mode 100644
index 00000000000..8ed824e7d9d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/README.md
@@ -0,0 +1,40 @@
+# Uses
+
+widlproc can be used to validate WebIDL in W3C specifications. It serves as the basis for the [W3C Web IDL on-line checker](http://www.w3.org/2009/07/webidl-check).
+
+widlproc's generated XML is used to generate [webinos JavaScript APIs specifications](http://dev.webinos.org/specifications/draft/).
+
+# License
+
+widlproc is licensed under the Apache 2 License.
+
+# Others
+
+See also [webidl.js](https://github.com/darobin/webidl.js), a JavaScript-based Web IDL parser used by various tools in W3C.
+
+# Credits
+
+Most of the work on widlproc was done by Tim Renouf and Paddy Byers. Aplix corporation owns the copyright of the code up to June 2011.
+
+The tool is kept up to date with the changes in the spec by Dominique Hazael-Massieux, through funding from the [webinos project](http://webinos.org/) since June 2011.
+
+# Documentation
+
+See doc/widlproc.html in the tree.
+
+# Build Instructions
+
+## Windows
+
+Install requirements
+* Cygwin - must install must install libs/libxslt
+* Visual Studio express 2012 or 2010 (see difference below)
+
+makefile uses cygwin make. References are coded in the make file to detect teh current version of visual studio
+
+# Future work
+windows build could be improved to handle multipe versions with vcvars.bat
+http://stackoverflow.com/questions/62029/vs2008-command-prompt-cygwin
+
+
+
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/doc/htmltodtd.xsl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/doc/htmltodtd.xsl
new file mode 100644
index 00000000000..d8b7f5973fb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/doc/htmltodtd.xsl
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="us-ascii"?>
+<!--====================================================================
+$Id$
+Copyright 2009 Aplix Corporation. All rights reserved.
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Stylesheet to extract DTD for widlprocxml from widlproc.html
+=====================================================================-->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+<xsl:output method="text" encoding="us-ascii" indent="no"/>
+
+<!-- <pre class="dtd"> element -->
+<xsl:template match="pre[@class='dtd']">
+ <xsl:value-of select="."/>
+</xsl:template>
+
+<!--Ignore other text. -->
+<xsl:template match="text()" priority="-100"/>
+
+</xsl:stylesheet>
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/doc/widlproc.html b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/doc/widlproc.html
new file mode 100644
index 00000000000..4eb42c39bb9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/doc/widlproc.html
@@ -0,0 +1,1124 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<!--====================================================================
+Copyright 2009 Aplix Corporation. All rights reserved.
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+=====================================================================-->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
+<title>widlproc</title>
+<style type="text/css">
+ body { color: black; font: 10pt verdana; }
+ a:link { text-decoration: none; }
+ a:visited { text-decoration: none; }
+ a:hover { text-decoration: underline; }
+ dt { margin-top: 0.5em; }
+ dd { margin-left: 1em; margin-bottom: 0.5em; }
+ li { margin-bottom: 0; }
+ h4 { font-size: 10pt; }
+ table { border: 1px solid; border-collapse: collapse; }
+ td { border: 1px solid; }
+ th { border: 1px solid; }
+ code { background-color: #f0f0f0; }
+ pre { background-color: #f0f0f0; }
+ .indent { margin-left: 3em; }
+ .issue { background-color: #00CCCC; }
+</style>
+</head>
+<body>
+<h1>widlproc</h1>
+
+<p>Tim Renouf, Aplix Corp</p>
+<p>$Id$
+</p>
+
+<h2>Introduction</h2>
+
+<p>
+widlproc is a processor that accepts as input
+<a href="#webidl">Web IDL</a> (the 30 September 2009 editor's draft),
+with comments in a subset of the format used by
+<a href="#doxygen">Doxygen</a>.
+The format it accepts is proposed by Aplix for authoring
+<a href="#bondi">BONDI</a> interface definitions.
+</p>
+
+<p>
+The output of widlproc is an XML representation of the
+<a href="#webidl">Web IDL</a> input,
+with added XML elements representing the
+<a href="#doxygen">Doxygen</a>-like comments.
+</p>
+
+<h2>Usage</h2>
+
+<p>
+<code>widlproc <i>filename</i></code>
+</p>
+
+<p>
+widlproc reads the file named <em>filename</em>, and
+sends its XML output format to stdout.
+</p>
+
+<h2>Input format</h2>
+
+<p>
+The input format accepted by widlproc is
+<a href="#webidl">Web IDL</a>
+(with an extension used in the
+<a href="#w3cgeo">W3C Geolocation API</a>),
+with comments in a format reminiscent of that used by
+<a href="#doxygen">Doxygen</a>.
+</p>
+
+<h3>Web IDL extension from W3C geolocation API</h3>
+
+<h4>double</h4>
+
+<p>
+<code>double</code> is allowed as a DeclarationType or a BoxedType.
+</p>
+
+<h3>Doxygen-like comment introduction</h3>
+
+<p>
+Only a small subset of Doxygen functionality is supported by
+widlproc, plus additions to handle the BONDI concepts of API features
+and device capabilities.
+</p>
+
+<p>
+In particular, no links are added automatically. (This could be added
+in the future.)
+</p>
+
+<h3>Doxygen comment block</h3>
+
+<h4>Comment referral point</h4>
+
+<p>
+Each <em>Doxygen comment block</em> refers to a <em>comment referral
+point</em> in the Web IDL, one of
+module, interface, exception, const, attribute, operation or argument.
+</p>
+
+<h4>Block comment</h4>
+
+<p>
+A block comment (delimited by <code>/* */</code>) whose first character
+after the <code>/*</code> is <code>!</code> or a second <code>*</code>
+is a <em>Doxygen comment block</em>.
+</p>
+
+<p>
+Normally the comment block refers to the next comment referral point in
+the Web IDL.
+If the first character is <code>&lt;</code>, so the comment block is introduced
+with <code>/**&lt;</code> or <code>/*!&lt;</code> , then the comment block
+refers back to the previous comment referral point.
+</p>
+
+<p>
+The text of the comment block
+excludes the initial <code>!</code> or <code>*</code> (and the <code>&lt;</code>
+for a referring back block),
+and excludes an initial (after whitespace) <code>*</code>
+on each line,
+and, when not in a <a href="#code"><code>\code</code></a> block,
+excludes any line consisting entirely of whitespace, then <code>*</code>
+characters, then whitespace.
+</p>
+
+<p>
+widlproc does not support Doxygen commands to force a comment
+block to refer to a different referral point.
+</p>
+
+<h4>Inline comments</h4>
+
+<p>
+The maximal sequence of inline comments (delimited by <code>//</code>)
+on adjacent lines, where all of the following conditions hold:
+</p>
+<ul>
+<li>
+each has a first character after the <code>/</code> of <code>!</code> or
+a third <code>/</code>;
+<li>
+no comment referral point intervenes;
+<li>
+either each comment in the sequence starts with a <code>&lt;</code>
+(see below), or none does;
+<li>
+the sequence contains at least two inline comments, or, if only one,
+then it starts with <code>&lt;</code> (see below);
+</ul>
+<p>
+forms a <em>Doxygen comment block</em>.
+</p>
+
+<p>
+Normally the comment block refers to the next comment referral point in
+the Web IDL.
+If the first character of each comment is <code>&lt;</code>, so each
+comment in the block is introduced
+with <code>///&lt;</code> or <code>//!&lt;</code> , then the comment block
+refers back to the previous comment referral point.
+</p>
+
+<p>
+The text of the comment block
+excludes the initial <code>!</code> or <code>/</code> (and the <code>&lt;</code>
+for a referring back block) of each inline comment,
+and, when not in a <a href="#code"><code>\code</code></a> block,
+excludes any line consisting entirely of whitespace, then <code>/</code>
+characters, then whitespace.
+</p>
+
+<p>
+widlproc does not support Doxygen commands to force a comment
+block to refer to a different referral point.
+</p>
+
+<h3>Paragraph</h3>
+
+<p>
+A comment block is broken into zero or more <em>paragraph</em>s.
+One or more blank lines break the paragraphs (unless in a
+<a href="#code"><code>\code</code></a> block).
+</p>
+
+<p>
+Certain commands (below) also start a new paragraph.
+</p>
+
+<p>
+An
+<a href="#html">HTML block element</a>
+is a paragraph.
+A blank line (other than in a
+<a href="#code"><code>\code</code></a> block)
+implicitly closes any open HTML elements, thus ending the paragraph.
+</p>
+
+<h3>Doxygen-like commands</h3>
+
+<p>
+widlproc supports a small subset of Doxygen commands, plus some additions
+to handle BONDI API features and device capabilities.
+</p>
+
+<p>
+A command is always introduced with a <code>\</code> character.
+The Doxygen alternative (from JavaDoc) of <code>@</code> is not
+supported.
+</p>
+
+<h4 id="api-feature">\api-feature</h4>
+
+<p>
+Starts a new paragraph. The following word is the name of an API feature
+used by the method being documented. The remainder of the paragraph is
+any description required of how (eg in what circumstance) the API feature
+is used.
+</p>
+
+<h4>\name</h4>
+
+<p>
+Declares a name for the document node associated with the current referral
+point. This is useful for the root document node that otherwise does not have
+a WebIDL identifier.
+</p>
+
+<h4>\author</h4>
+
+<p>
+Starts a new paragraph. The remainder of the paragraph contains
+information about a single author of the specification. Multiple
+<code>\author</code> commands should be used for multiple authors.
+</p>
+
+<p>
+(Here widlproc differs from Doxygen; Doxygen also allows
+multiple authors on separate lines to appear in one <code>\author</code>
+paragraph.)
+</p>
+
+<h4>\b</h4>
+
+<p>
+This renders the next word as bold. It is equivalent to enclosing the
+next word with <code>&lt;b> &lt;/b></code>.
+</p>
+
+<h4>\brief</h4>
+
+<p>
+Starts a new paragraph. The remainder of the paragraph contains a brief
+description of the entity being documented.
+</p>
+
+<h4 id="code">\code, \endcode</h4>
+
+<p>
+<code>\code</code>
+starts a new paragraph which is a <em>code block</em>. The code block
+ends at the next <code>\endcode</code> command.
+</p>
+
+<p>
+Within the code block, whitespace and newlines are passed verbatim into
+the output.
+</p>
+
+<h4 id="def-api-feature">\def-api-feature</h4>
+
+<p>
+Starts a new paragraph. The following word is the name of the API feature
+which is defined here. The description is an <em>def-api-feature block</em>,
+consisting of the
+remainder of the paragraph, together with
+further paragraphs in the same block comment each of which is a plain
+paragraph, a paragraph started due to HTML markup, a <code>\brief</code>
+paragraph, or a
+<a href="#device-cap"><code>\device-cap</code></a>
+paragraph.
+</p>
+
+<h4 id="def-api-feature-set">\def-api-feature-set</h4>
+
+<p>
+Starts a new paragraph. The following word is the name of the API feature
+set which is defined here. The description is an <em>def-api-feature-set block</em>,
+consisting of the
+remainder of the paragraph, together with
+further paragraphs in the same block comment each of which is a plain
+paragraph, a paragraph started due to HTML markup, a <code>\brief</code>
+paragraph, or a
+<a href="#device-cap"><code>\api-feature</code></a>
+paragraph.
+</p>
+
+<h4>\def-device-cap</h4>
+
+<p>
+Starts a new paragraph. The following word is the name of the device capability
+which is defined here. The description consists of the
+remainder of the paragraph, together with
+further paragraphs in the same block comment each of which is a plain
+paragraph, a paragraph started due to HTML markup, a <code>\brief</code>
+paragraph, or a
+<a href="#param"><code>\param</code></a>
+paragraph.
+</p>
+
+<h4 id="def-instantiated">\def-instantiated</h4>
+
+<p>
+Starts a new paragraph. The description is an <em>def-instantiated block</em>,
+consisting of the
+remainder of the paragraph, together with
+further paragraphs in the same block comment each of which is a plain
+paragraph, a paragraph started due to HTML markup, a <code>\brief</code>
+paragraph, or a
+<a href="#api-feature"><code>\api-feature</code></a>
+paragraph.
+</p>
+
+<h4 id="device-cap">\device-cap</h4>
+
+<p>
+Starts a new paragraph.
+This command can appear only inside an
+<a href="#def-api-feature">def-api-feature block</a>.
+The following word is the name of a device capability
+used by the API feature being documented.
+The remainder of the paragraph is
+any description required of how (eg in what circumstance) the device capability
+is used.
+</p>
+
+<h4>\n</h4>
+
+<p>
+Creates a line break in the output.
+</p>
+
+<h4 id="param">\param</h4>
+
+<p>
+Starts a new paragraph. This takes the following word as the name of
+a parameter (argument) of the entity being documented, then makes the
+remainder of the paragraph refer to that parameter.
+</p>
+
+<h4>\return</h4>
+
+<p>
+Starts a new paragraph. The remainder of the paragraph is made to refer to
+the return type of the entity being documented.
+</p>
+
+<h4>\throw</h4>
+
+<p>
+Starts a new paragraph. The next word is taken to be the name of an
+exception thrown by the entity being documented, and the remainder of
+the paragraph documents that exception (in the <code>raises</code> list of
+an <code>operation</code>, or the <code>setraises</code>
+clause of an <code>attribute</code>).
+</p>
+
+<h4>\version</h4>
+
+<p>
+Starts a new paragraph. The remainder of the paragraph contains
+version number information.
+</p>
+
+<h3>Escape sequences</h3>
+
+<p>
+The following escape sequences are recognized in a comment block:
+</p>
+
+<table>
+<tr>
+<th>escape sequence
+<th>result
+<tr>
+<td><code>\\</code>
+<td><code>\</code>
+<tr>
+<td><code>\&amp;</code>
+<td><code>&amp;</code> (escaped to <code>&amp;amp;</code> in output XML)
+<tr>
+<td><code>\$</code>
+<td><code>$</code>
+<tr>
+<td><code>\#</code>
+<td><code>#</code>
+<tr>
+<td><code>\&lt;</code>
+<td><code>&lt;</code> (escaped to <code>&amp;lt;</code> in output XML)
+<tr>
+<td><code>\></code>
+<td><code>></code>
+<tr>
+<td><code>\%</code>
+<td><code>%</code>
+</table>
+
+<p>
+Some of these escape sequences are used to avoid Doxygen features that
+widlproc does not currently implement. In particular,
+widlproc insists on a <code>$</code> being escaped, to
+allow for possible future functionality.
+</p>
+
+<h3 id="html">HTML in comments</h3>
+
+<p>
+widlproc accepts a small subset of HTML elements.
+</p>
+
+<p>
+An HTML block element is a paragraph.
+A blank line (other than in a
+<a href="#code"><code>\code</code></a> block)
+implicitly closes any open HTML elements, thus ending the paragraph.
+</p>
+
+<p>
+The following HTML block elements are accepted:
+<code>dl</code>
+<code>ol</code>
+<code>p</code>
+<code>table</code>
+<code>ul</code>
+</p>
+
+<p>
+The following HTML inline elements are accepted:
+<code>a</code>
+<code>img</code>
+<code>b</code>
+<code>br</code>
+<code>em</code>
+</p>
+
+<p>
+The following HTML elements are accepted where valid inside one of the
+other elements:
+<code>dd</code>
+<code>dt</code>
+<code>li</code>
+<code>td</code>
+<code>th</code>
+<code>tr</code>
+</p>
+
+
+<h2>Output format</h2>
+
+<p>
+The output of widlproc is an XML representation of the
+<a href="#webidl">Web IDL</a>,
+with added XML elements representing the
+<a href="#doxygen">Doxygen</a>-like comments.
+</p>
+
+<h3>Annotated document type declaration</h3>
+
+<pre class="dtd">
+&lt;!-- Autogenerated from widlproc.html : do not edit. -->
+</pre>
+
+<h4>Entities used elsewhere</h4>
+
+<pre class="dtd">
+&lt;!ENTITY % block 'dl | p | table | ul' >
+&lt;!ENTITY % Block '(%block;)*' >
+&lt;!ENTITY % inline 'a | b | br | em | img' >
+&lt;!ENTITY % Inline '(#PCDATA | %inline;)*' >
+&lt;!ENTITY % Flow '(#PCDATA | %inline; | %block;)*' >
+
+&lt;!ELEMENT webidl (#PCDATA | ref)* >
+</pre>
+
+<p>
+The <code>&lt;webidl></code> element contains the literal text of the
+original Web IDL that the parent
+element was parsed from, minus the comments, with each reference to
+an interface name
+enclosed in a <code>&lt;ref></code>..<code>&lt;/ref></code>.
+</p>
+
+<h4>Definitions</h4>
+
+<p>
+<em>Definitions</em> is the root element of the XML document.
+</p>
+
+<p>
+The <em>ExtendedAttributeList</em> specifies any extended attributes
+for the <em>Interface</em>, <em>Dictionary</em>, <em>Exception</em>,
+<em>Typedef</em>, <em>Valuetype</em> or <em>Const</em> in the
+<em>Definition</em>.
+</p>
+
+<pre class="dtd">
+&lt;!ELEMENT Definitions ( webidl, descriptive?, (Interface | Dictionary | Callback
+ | Enum | Exception | Typedef | Implements)*) >
+</pre>
+
+<h4>Interface</h4>
+
+<p>
+An <em>Interface</em> represents an interface. The <em>name</em>
+attribute specifies the name of the interface. The <em>descriptive</em> element
+provides its documentation if any.
+The <em>id</em> attribute specifies the absolute scoped name of the interface.
+</p>
+
+<p>The <em>partial</em> attribute indicates that the definition of the interface complements an existing definition. The <em>callback</em> attribute specificies that a given interface is a callback interface.</p>
+
+<p>
+The <em>InterfaceInheritance</em> element indicates that the interface
+inherits from other interface(s). Each <em>Name</em> in the
+<em>InterfaceInheritance</em> has a <em>name</em> attribute giving the
+scoped name of the interface being inherited from.
+</p>
+
+<pre class="dtd">
+&lt;!ELEMENT Interface (webidl, descriptive?, ExtendedAttributeList?,
+ InterfaceInheritance?, (Const | Attribute | Operation | Stringifier* | Serializer* | Iterator | IteratorObject)* ) >
+&lt;!ATTLIST Interface name CDATA #REQUIRED
+ partial (partial) #IMPLIED
+ callback (callback) #IMPLIED
+ id CDATA #REQUIRED >
+
+&lt;!ELEMENT InterfaceInheritance (Name+) >
+
+&lt;!ELEMENT Name EMPTY >
+&lt;!ATTLIST Name name CDATA #REQUIRED >
+</pre>
+
+<h4>Dictionary</h4>
+
+<p>
+A <em>Dictionary</em> represents a dictionary. The <em>name</em>
+attribute specifies the name of the dictionary. The <em>descriptive</em> element
+provides its documentation if any.
+The <em>id</em> attribute specifies the absolute scoped name of the dictionary.
+</p>
+
+<p>The <em>partial</em> attribute indicates that the definition of the interface complements an existing definition.</p>
+
+<p>
+The <em>DictionaryInheritance</em> element indicates that the dictionary
+inherits from other dictionary(s). Each <em>Name</em> in the
+<em>DictionaryInheritance</em> has a <em>name</em> attribute giving the
+scoped name of the dictionary being inherited from.
+</p>
+
+
+<pre class="dtd">
+&lt;!ELEMENT Dictionary (webidl, descriptive?, DictionaryInheritance?, DictionaryMember* ) >
+&lt;!ATTLIST Dictionary name CDATA #REQUIRED
+ partial (partial) #IMPLIED
+ id CDATA #REQUIRED >
+
+&lt;!ELEMENT DictionaryInheritance (Name+) >
+</pre>
+
+<h4>Callback</h4>
+
+<p>
+A <em>Callback</em> represents a callback type. The <em>name</em>
+attribute specifies the name of the dictionary. The <em>descriptive</em> element
+provides its documentation if any.</p>
+
+<p>The <em>Type</em> element specifies its return type.</p>
+
+<p>
+An <em>Argument</em> is an argument to an operation.
+The <em>Type</em> element specifies its type. The <em>name</em>
+attribute specifies its name if it has one.
+</p>
+
+<pre class="dtd">
+&lt;!ELEMENT Callback (webidl, descriptive?, Type, ArgumentList? ) >
+&lt;!ATTLIST Callback name CDATA #REQUIRED
+ id CDATA #REQUIRED>
+</pre>
+
+
+<h4>Enum</h4>
+
+<p>
+An <em>Enum</em> represents an enumeration. The <em>name</em>
+attribute specifies the name of the enumeration. The <em>descriptive</em> element
+provides its documentation if any.
+</p>
+
+<p>
+The <em>EnumValue</em> element indicates the values defined for that enumeration in its <em>stringvalue</em> attribute.
+</p>
+
+
+<pre class="dtd">
+&lt;!ELEMENT Enum (webidl, descriptive?, EnumValue* ) >
+&lt;!ATTLIST Enum name CDATA #REQUIRED
+ id CDATA #REQUIRED >
+
+&lt;!ELEMENT EnumValue (webidl, descriptive?) >
+&lt;!ATTLIST EnumValue stringvalue CDATA #REQUIRED >
+</pre>
+
+
+
+<h4>Exception</h4>
+
+<p>
+An <em>Exception</em> represents an exception.
+The <em>name</em>
+attribute specifies the name of the exception.
+The <em>descriptive</em> element
+provides its documentation if any.
+The <em>id</em> attribute specifies the absolute scoped name of the exception.
+</p>
+
+<p>
+An <em>ExceptionField</em> represents a field in an exception.
+The <em>name</em>
+attribute specifies the name of the field.
+The <em>Type</em> element specifies its type.
+The <em>descriptive></em> element
+provides its documentation if any.
+The <em>id</em> attribute specifies the absolute scoped name of the field.
+</p>
+
+<p>
+The <em>ExceptionInheritance</em> element indicates that the exception
+inherits from another exception. The <em>Name</em> in the
+<em>ExceptionInheritance</em> has a <em>name</em> attribute giving the
+scoped name of the exception being inherited from.
+</p>
+
+
+<pre class="dtd">
+&lt;!ELEMENT Exception (webidl, descriptive?, ExtendedAttributeList?, ExceptionInheritance?,
+ (Const | ExceptionField)* ) >
+&lt;!ATTLIST Exception name CDATA #REQUIRED
+ id CDATA #REQUIRED >
+
+&lt;!ELEMENT ExceptionInheritance (Name) >
+&lt;!ELEMENT ExceptionField (webidl, descriptive?, ExtendedAttributeList?, (Type)) >
+&lt;!ATTLIST ExceptionField name CDATA #REQUIRED
+ id CDATA #REQUIRED >
+</pre>
+
+<h4>Typedef</h4>
+
+<p>
+A <em>Typedef</em> represents a type definition.
+The <em>name</em>
+attribute specifies the name of the new type.
+The <em>Type</em> element specifies it in terms of other types.
+The <em>descriptive></em> element
+provides its documentation if any.
+The <em>id</em> attribute specifies the absolute scoped name of the typedef.
+</p>
+
+<pre class="dtd">
+&lt;!ELEMENT Typedef (webidl, descriptive?, ExtendedAttributeList?, (Type)) >
+&lt;!ATTLIST Typedef name CDATA #REQUIRED
+ id CDATA #REQUIRED >
+</pre>
+
+<h4>Implements</h4>
+
+<p>
+An <em>Implements</em> represents Web IDL's
+<code><i>ScopedName</i> implements <i>ScopedName</i>;</code>
+syntax. The <em>name1</em> and <em>name2</em> attributes give the
+first and second scoped names respectively.
+The <em>descriptive></em> element
+provides the <em>Implements</em>'s documentation if any.
+</p>
+
+<pre class="dtd">
+&lt;!ELEMENT Implements (webidl, descriptive?, ExtendedAttributeList?) >
+&lt;!ATTLIST Implements name1 CDATA #REQUIRED
+ name2 CDATA #REQUIRED >
+</pre>
+
+<h4>Const</h4>
+
+<p>
+<em>Const</em> represents Web IDL's
+<code>const <i>Type</i> <i>identifier</i> = <i>ConstExpr</i>;</code>
+syntax.
+The <em>Type</em> specifies the constant's type, the
+<em>name</em> attribute specifies the constant's name, and the
+<em>value</em> attribute specifies its value.
+The <em>descriptive></em> element
+provides the <em>Const</em>'s documentation if any.
+The <em>id</em> attribute specifies the absolute scoped name of the const.
+</p>
+
+<pre class="dtd">
+&lt;!ELEMENT Const (webidl, descriptive?, ExtendedAttributeList?, Type) >
+&lt;!ATTLIST Const name CDATA #REQUIRED
+ value CDATA #IMPLIED
+ id CDATA #REQUIRED >
+</pre>
+
+<h4>Stringifier</h4>
+
+<p>
+A <em>Stringifier</em> represents the Web IDL <code>stringifier;</code>
+syntax as an interface member.
+The <em>descriptive></em> element
+provides the <em>Stringifier</em>'s documentation if any.
+</p>
+
+<pre class="dtd">
+&lt;!ELEMENT Stringifier (webidl, descriptive?, ExtendedAttributeList?) >
+</pre>
+
+<h4>Attribute</h4>
+
+<p>
+An <em>Attribute</em> represents an attribute as an interface member.
+The <em>Type</em> element specifies its type. The <em>name</em>
+attribute specifies its name. Each of the <em>stringifier</em>, <em>static</em> and
+<em>readonly</em> attributes is set to a value the same as the attribute
+name when the corresponding keyword appears in the Web IDL input. The <em>inherit</em> attribute is set to <em>inherit</em> when the attribute inherits its getter.
+</p>
+
+
+<p>
+The <em>descriptive></em> element provides the attribute's documentation
+if any.
+The <em>id</em> attribute specifies the absolute scoped name of the attribute.
+</p>
+
+<pre class="dtd">
+&lt;!ELEMENT Attribute (webidl, descriptive?, ExtendedAttributeList?, (Type)) >
+&lt;!ATTLIST Attribute stringifier (stringifier) #IMPLIED
+ readonly (readonly) #IMPLIED
+ inherit (inherit) #IMPLIED
+ static (static) #IMPLIED
+ name CDATA #REQUIRED
+ id CDATA #REQUIRED >
+
+</pre>
+
+
+<h4>Operation</h4>
+
+<p>
+An <em>Operation</em> represents a method on interface.
+The <em>Type</em> element specifies its return type. The <em>name</em>
+attribute specifies its name.
+</p>
+
+<p>
+Each of the <em>stringifier</em>, <em>static</em>, <em>getter</em>,
+<em>setter</em>, <em>creator</em>, <em>deleter</em> and <em>legacycaller</em>, <em>serializer</em>
+attributes is set to a value the same as the attribute
+name when the corresponding keyword appears in the Web IDL input.
+</p>
+
+
+<p>
+The <em>descriptive></em> element provides the attribute's documentation
+if any.
+The <em>id</em> attribute specifies the absolute scoped name of the operation if it has one.
+</p>
+
+<p>
+An <em>Argument</em> is an argument to an operation.
+The <em>Type</em> element specifies its type. The <em>name</em>
+attribute specifies its name if it has one.
+</p>
+
+<p>
+Each of the <em>optional</em> and <em>ellipsis</em>
+attributes is set to a value the same as the attribute
+name when the corresponding syntax appears in the Web IDL input.
+</p>
+
+<p>The
+<em>value</em> attribute used on optional arguments specifies default value for non-string values, and <em>stringvalue</em> for string values.</p>
+
+
+<pre class="dtd">
+&lt;!ELEMENT Operation (webidl, descriptive?, ExtendedAttributeList?,
+ (Type), ArgumentList) >
+&lt;!ATTLIST Operation stringifier (stringifier) #IMPLIED
+ static (static) #IMPLIED
+ getter (getter) #IMPLIED
+ setter (setter) #IMPLIED
+ creator (creator) #IMPLIED
+ deleter (deleter) #IMPLIED
+ serializer (serializer) #IMPLIED
+ legacycaller (legacycaller) #IMPLIED
+ name NMTOKEN #IMPLIED
+ id NMTOKEN #IMPLIED >
+
+
+&lt;!ELEMENT ArgumentList (Argument*) >
+
+&lt;!ELEMENT Argument (descriptive?, ExtendedAttributeList?, (Type)) >
+&lt;!ATTLIST Argument
+ optional (optional) #IMPLIED
+ ellipsis (ellipsis) #IMPLIED
+ value CDATA #IMPLIED
+ stringvalue CDATA #IMPLIED
+ name NMTOKEN #REQUIRED >
+</pre>
+
+<h4>Serializer</h4>
+<p>A <em>Serializer</em> represents a serializer for an interface, either defined in the prose or via a pattern.</p>
+
+<p>The <em>descriptive</em> element provides the serializer's documentation if any.</p>
+
+
+<p>The <em>attribute</em> attribute defines the attribute that is used for serialization if any.</p>
+
+<p>The optional <em>Map</em> and <em>List</em> elements describe the pattern (if any) for the serializer. They take <em>PatternAttribute</em> elements with a <em>name</em> attribute that describes the attributes used for serialization.</p>
+
+<p><em>Map</em> elements take a <em>pattern</em> attribute that can be set to either "getter" (if the getter is used for serialization), "all" if all serializable attributes are to be used, or "selection" if the attributes named as children elements are to be used. Optionally, they take a <em>inherit</em> attribute set to "inherit" if the serialization takes also into account inherited attributes.</p>
+
+<p><em>List</em> elements take a <em>pattern</em> attribute that can be set to either "getter" (if the getter is used for serialization), or "selection" if the attributes named as children elements are to be used.</p>
+
+<pre class="dtd">
+&lt;!ELEMENT Serializer (webidl, descriptive?, ExtendedAttributeList?, (Map | List)?) >
+&lt;!ATTLIST Serializer attribute CDATA #IMPLIED >
+
+&lt;!ELEMENT Map ((PatternAttribute*)) >
+
+&lt;!ATTLIST Map inherit (inherit) #IMPLIED
+ pattern (getter|all|selection) #REQUIRED>
+
+&lt;!ELEMENT List ((PatternAttribute*)) >
+
+&lt;!ATTLIST List pattern (getter|selection) #REQUIRED>
+
+&lt;!ELEMENT PatternAttribute EMPTY>
+&lt;!ATTLIST PatternAttribute name CDATA #REQUIRED>
+
+</pre>
+
+<h4>Iterator</h4>
+<p>An <em>Iterator</em> element defines whether the interface has a custom iterator; the type of the iterated objects is defined in the <em>Type</em> child. If that interator implements a particular interface, the name of that interface is set in the <em>interface</em> attribute.</p>
+<pre class="dtd">
+&lt;!ELEMENT Iterator (webidl, descriptive?, ExtendedAttributeList?, Type) >
+&lt;!ATTLIST Iterator interface CDATA #IMPLIED>
+</pre>
+
+<h4>IteratorObject</h4>
+<p>An <em>IteratorObject</em> element denotes that the interface serves as an iterator object interface; the type of the iterated objects is defined in the <em>Type</em> child.</p>
+
+<pre class="dtd">
+&lt;!ELEMENT IteratorObject (webidl, descriptive?, ExtendedAttributeList?, Type) >
+</pre>
+
+
+<h4>DictionaryMember</h4>
+
+<p>
+A <em>DictionaryMember</em> represents a member of a dictionary.
+The <em>Type</em> element specifies its type. The <em>name</em>
+attribute specifies its name.
+</p>
+
+<p>
+The <em>descriptive></em> element provides the dictionary member's documentation
+if any.
+The <em>id</em> attribute specifies the absolute scoped name of the attribute.
+</p>
+
+<p>The
+<em>value</em> attribute specifies its value for non-string values, and <em>stringvalue</em> for string values.</p>
+
+<pre class="dtd">
+&lt;!ELEMENT DictionaryMember (webidl, descriptive?, ExtendedAttributeList?, Type) >
+&lt;!ATTLIST DictionaryMember name CDATA #REQUIRED
+ id CDATA #REQUIRED
+ value CDATA #IMPLIED
+ stringvalue CDATA #IMPLIED >
+
+</pre>
+
+
+<h4>Extended attributes</h4>
+
+<p>
+An <em>ExtendedAttributeList</em> contains one or more
+<em>ExtendedAttribute</em> element. Each <em>ExtendedAttribute</em>
+has:
+</p>
+<ul>
+<li>
+a <em>name</em> attribute giving the name of the extended attribute;
+<li>
+if the extended attribute contains an <code>=</code> sign followed by a
+value, a <em>value</em> attribute giving the value, which is a scoped
+name or an identifier;
+<li>
+if the extended attribute contains parentheses (either with or without
+an <code>=</code> sign), an <em>ArgumentList</em> element giving the
+contents of the parentheses.
+</ul>
+<p>
+If the <em>value</em> attribute and the <em>ArgumentList</em> element are
+both present, then <em>value</em> must give an identifier rather than
+a scoped name.
+</p>
+
+<pre class="dtd">
+&lt;!ELEMENT ExtendedAttributeList (ExtendedAttribute+) >
+
+&lt;!ELEMENT ExtendedAttribute (webidl, ArgumentList?) >
+&lt;!ATTLIST ExtendedAttribute name NMTOKEN #REQUIRED
+ value CDATA #IMPLIED >
+</pre>
+
+<h4>Type</h4>
+
+<p>
+<em>Type</em> represents a type. It has one of these forms:
+</p>
+<ul>
+<li>
+The <code>any</code>, <code>object</code> and <code>void</code>
+types have the attribute
+<em>type</em> set to the type, and no other attributes or elements.
+Note that the <code>void</code> type appears only when the <em>Type</em>
+element is a child of <em>Operation</em>.
+<li>
+A type that is an interface has the attribute <em>name</em> set to the
+name of that interface, and no other attributes or elements.
+<li>
+For the primitive types <code>short</code>, <code>unsigned short</code>,
+<code>long</code>, <code>unsigned long</code>, <code>long long</code>,
+<code>unsigned long long</code>, <code>float</code>, <code>double</code>,
+<code>boolean</code>, <code>octet</code>, <code>byte</code> and <code>DOMString</code>,
+there is an attribute <em>type</em>
+whose value is one of those strings, and no other attributes or elements.
+However, if the type was specified in the Web IDL with a trailing <code>?</code>
+sign, then there is an attribute <em>nullable</em> with the value
+<code>nullable</code>.
+</ul>
+<p>
+The restrictions on which combinations of elements and attributes are
+permitted are not encoded by the DTD.
+</p>
+<p>
+The <em>descriptive</em> element provides the documentation
+if any, when the <em>Type</em> is a child of <em>Operation</em>, and thus
+representing an operation's return type.
+</p>
+
+<p>The <em>ExtendedAttributeList</em> element provides the optional extended attributes that can be defined for a type through typedef, &agrave; la <code>typedef [Clamp] octet Value;</code>.</p>
+
+<!-- can't use enumerated values for the values of type, since DTD don't allow enumerated values to have space in them (which would be needed e.g. for "long long") -->
+<pre class="dtd">
+&lt;!ELEMENT Type (descriptive?, ExtendedAttributeList?, Type*) >
+&lt;!ATTLIST Type type CDATA #IMPLIED
+ name NMTOKEN #IMPLIED
+ nullable (nullable) #IMPLIED >
+</pre>
+
+<h4>Sequence</h4>
+
+<p>For a sequence type, the <em>Type</em> element with an attribute <em>type</em> set to <em>sequence</em> contains an element <em>Type</em> giving the sequence element type, and no other attributes or elements. If the sequence is specified in the Web IDL with a trailing <code>?</code>
+sign, then there is an attribute <em>nullable</em> with the value
+<code>nullable</code>.
+
+
+<h4>Array</h4>
+
+<p>For an array type, the <em>Type</em> element with an attribute <em>type</em> set to <em>array</em> contains an element <em>Type</em> giving the array element type. If the array is specified in the Web IDL with a trailing <code>?</code>
+sign, then there is an attribute <em>nullable</em> with the value
+<code>nullable</code>.
+
+<h4>Union</h4>
+
+<p>For a union type, the <em>Type</em> element with an attribute <em>type</em> set to <em>union</em> contains at least two element <em>Type</em> giving the union members type. If the union is specified in the Web IDL with a trailing <code>?</code>
+sign, then there is an attribute <em>nullable</em> with the value
+<code>nullable</code>.
+
+
+
+<h4>Descriptive elements</h4>
+
+<p>
+The following elements contain documentation, extracted from the
+Doxygen-like comments in the input. <code>&lt;param></code>
+derives only from a <code>\param</code> command used inside a
+<code>\def-device-cap</code> block; any other <code>\param</code> command
+is linked to a parameter (argument) of the method being documented.
+</p>
+
+<pre class="dtd">
+&lt;!ELEMENT descriptive (description | brief | throw | author
+ | version | Code | api-feature | device-cap | def-api-feature
+ | def-api-feature-set | def-device-cap | def-instantiated | param)* >
+
+&lt;!ELEMENT description %Block; >
+
+&lt;!ELEMENT brief %Inline; >
+
+&lt;!ELEMENT throw %Inline; >
+
+&lt;!ELEMENT author %Inline; >
+
+&lt;!ELEMENT version %Inline; >
+
+&lt;!ELEMENT Code %Inline; >
+
+&lt;!ELEMENT api-feature %Inline; >
+&lt;!ATTLIST api-feature identifier CDATA #REQUIRED >
+
+&lt;!ELEMENT device-cap %Inline; >
+&lt;!ATTLIST device-cap identifier CDATA #REQUIRED >
+
+&lt;!ELEMENT param %Inline; >
+&lt;!ATTLIST param identifier CDATA #REQUIRED >
+
+&lt;!ELEMENT def-api-feature (descriptive?) >
+&lt;!ATTLIST def-api-feature identifier CDATA #REQUIRED >
+
+&lt;!ELEMENT def-api-feature-set (descriptive?) >
+&lt;!ATTLIST def-api-feature-set identifier CDATA #REQUIRED >
+
+&lt;!ELEMENT def-instantiated (descriptive?) >
+
+&lt;!ELEMENT def-device-cap (descriptive?) >
+&lt;!ATTLIST def-device-cap identifier CDATA #REQUIRED >
+
+&lt;!ELEMENT ref (#PCDATA) >
+</pre>
+
+<h4>XHTML elements</h4>
+
+<p>
+The following XHTML elements are part of widlprocxml:
+</p>
+
+<pre class="dtd">
+&lt;!ELEMENT a %Inline; >
+&lt;!ATTLIST a href CDATA #REQUIRED >
+
+&lt;!ELEMENT b %Inline; >
+
+&lt;!ELEMENT br EMPTY >
+
+&lt;!ELEMENT dd %Flow; >
+
+&lt;!ELEMENT dl ((dt | dd)*) >
+
+&lt;!ELEMENT dt %Inline; >
+
+&lt;!ELEMENT em %Inline; >
+
+&lt;!ELEMENT img %Inline; >
+&lt;!ATTLIST img src CDATA #REQUIRED
+ alt CDATA #IMPLIED>
+
+
+&lt;!ELEMENT li %Flow; >
+
+&lt;!ELEMENT p %Inline; >
+
+&lt;!ELEMENT table (tr*) >
+
+&lt;!ELEMENT td %Flow; >
+
+&lt;!ELEMENT th %Flow; >
+
+&lt;!ELEMENT tr ((th | td)*) >
+
+&lt;!ELEMENT ul (li*) >
+</pre>
+
+
+<h2>Bibliography</h2>
+
+<p id="bondi">
+BONDI - an open source industry collaboration for widget and web technologies,
+<a href="http://bondi.omtp.org/">http://bondi.omtp.org/</a>
+</p>
+
+<p id="doxygen">
+Doxygen Source code documentation generator tool,
+<a href="http://www.stack.nl/~dimitri/doxygen/index.html">
+http://www.stack.nl/~dimitri/doxygen/index.html</a>
+</p>
+
+<p id="w3cgeo">
+W3C Geolocation API Specification Editor's Draft 3 April 2009,
+<a href="http://dev.w3.org/geo/api/spec-source.html">
+http://dev.w3.org/geo/api/spec-source.html</a>
+</p>
+
+<p id="webidl">
+Web IDL W3C Editor's Draft 3 May 2011,
+<a href="http://dev.w3.org/2006/webapi/WebIDL">http://dev.w3.org/2006/webapi/WebIDL</a>
+</p>
+
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/examples/Makefile b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/examples/Makefile
new file mode 100644
index 00000000000..614453d23c0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/examples/Makefile
@@ -0,0 +1,79 @@
+########################################################################
+# $Id$
+# Copyright 2009 Aplix Corporation. All rights reserved.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+# http://www.apache.org/licenses/LICENSE-2.0
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+########################################################################
+
+UNAME = $(shell uname)
+EXAMPLESDIR = .
+# The settings of SRCDIR (where to find the xsl style sheets), OBJDIR (where to
+# find widlproc and widlprocxml.dtd) and EXAMPLESOBJDIR (where to put the
+# resulting html files and any intermediate files) reflect the directory
+# structure of the released widlproc.zip file when unzipped. ../Makefile calls
+# this Makefile with these settings overridden to reflect the directory
+# structure in svn.
+SRCDIR = ..
+OBJDIR = ..
+EXAMPLESOBJDIR = obj
+
+########################################################################
+# Linux configuration
+#
+ifneq (,$(filter Linux%, $(UNAME)))
+
+EXESUFFIX =
+
+else
+########################################################################
+# Darwin configuration
+#
+ifneq (,$(filter Darwin%, $(UNAME)))
+
+EXESUFFIX =
+
+else
+########################################################################
+# Windows (cygwin but using MS compiler) configuration
+#
+ifneq (,$(filter CYGWIN%, $(UNAME)))
+
+EXESUFFIX = .exe
+
+endif
+endif
+endif
+
+########################################################################
+# Common makefile
+#
+WIDLPROC = $(OBJDIR)/widlproc$(EXESUFFIX)
+DTD = $(OBJDIR)/widlprocxml.dtd
+
+WIDLS = $(patsubst $(EXAMPLESDIR)/%, %, $(wildcard $(EXAMPLESDIR)/*.widl))
+
+test : $(patsubst %.widl, $(EXAMPLESOBJDIR)/%.html, $(WIDLS)) $(EXAMPLESOBJDIR)/widlhtml.css
+ @echo "$@ pass"
+
+$(EXAMPLESOBJDIR)/%.html : $(EXAMPLESOBJDIR)/%.widlprocxml $(SRCDIR)/widlprocxmltohtml.xsl Makefile
+ cp $(SRCDIR)/widlprocxmltohtml.xsl $(dir $@)/
+ xsltproc $(dir $@)/widlprocxmltohtml.xsl $< >$@
+
+$(EXAMPLESOBJDIR)/%.widlprocxml : $(EXAMPLESDIR)/%.widl $(WIDLPROC) $(DTD) Makefile
+ mkdir -p $(dir $@)
+ $(WIDLPROC) $< >$@
+ cp $(OBJDIR)/widlprocxml.dtd $(dir $@)/
+ xmllint --noout --dtdvalid $(DTD) $@
+
+$(EXAMPLESOBJDIR)/widlhtml.css : $(EXAMPLESDIR)/widlhtml.css
+ cp $< $@
+
+.DELETE_ON_ERROR:
+
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/examples/README b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/examples/README
new file mode 100644
index 00000000000..efbb72dda8d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/examples/README
@@ -0,0 +1,41 @@
+########################################################################
+# $Id$
+# Copyright 2009 Aplix Corporation. All rights reserved.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+# http://www.apache.org/licenses/LICENSE-2.0
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+########################################################################
+
+This examples directory contains two of the BONDI .widl files, a Makefile
+that processes them to generate html, and a .css file that the resulting
+html uses.
+
+The Makefile processes the .widl files as follows:
+
+ 1. For each .widl, generate the .widlprocxml file (an XML representation
+ of the information in the .widl) using widlproc.
+
+ 2. Validate (using xmllint) each .widlprocxml against the DTD.
+
+ 3. We want any reference in the resulting html to a type elsewhere in the
+ API to be a link. This is where we achieve this. First generate a
+ list of fqids (fully qualified identifiers) from fqid attributes in
+ the XML by running all .widlprocxml files through the style sheet
+ widlprocxmlfqids.xsl.
+
+ 4. Turn that list of fqids into a sed script that turns a <ref> to an
+ fqid into a <ref ref=".."> to the fqid in the right .html file.
+
+ 5. For each .widlprocxml file, generate a .widlprocxml2 file by running
+ it through the sed script generated above.
+
+ 6. For each .widlprocxml2 file, generate a .html file by running it through
+ the widlprocxmltohtml.xsl style sheet.
+
+See the Makefile for details.
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/examples/bondi.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/examples/bondi.widl
new file mode 100644
index 00000000000..200b95fe9c1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/examples/bondi.widl
@@ -0,0 +1,227 @@
+/*
+ * Licensed to OMTP Ltd. (OMTP) under one or more contributor license agreements.
+ * See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership.
+ *
+ * The Reference Implementation (save for such parts of the reference implementation made
+ * available under separate terms and conditions) is made available under the terms of the
+ * Apache License, version 2.0, subject to the condition that any "Works" and "Derivative
+ * Works" used or distributed for commercial purposes must be and remain compliant with the
+ * BONDI specification as promulgated by OMTP in each release. Your implementation of the
+ * Reference Implementation (whether object or source) must maintain these conditions, and
+ * you must notify any recipient of this condition in a conspicuous way.
+ *
+ * You may not use this BONDI Reference Implementation except in compliance with the License.
+ *
+ * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 or at
+ * http://bondi.omtp.org/BONDI-LICENSE-2.0
+ */
+
+/**
+ * \brief Common BONDI functionality.
+ *
+ * These definitions can be used in all other BONDI modules as dependencies.
+ * \version 1.1
+ */
+module bondi {
+
+ /**
+ * \brief Array of DOMStrings.
+ */
+ typedef sequence<DOMString> StringArray;
+
+ /**
+ * \brief Array of 8-bit unsigned integer values.
+ */
+ typedef sequence<octet> ByteArray;
+
+ /**
+ * \brief Array of 16-bit signed integer values.
+ */
+ typedef sequence<short> ShortArray;
+
+ /**
+ * \brief Array of 32-bit signed integer values.
+ */
+ typedef sequence<long> LongArray;
+
+ /**
+ * \brief Array of floating point values.
+ */
+ typedef sequence<float> FloatArray;
+
+ /**
+ * \brief Generic Map object.
+ */
+ typedef Object Map;
+
+ /**
+ * \brief Generic success callback interface.
+ */
+ [Callback=FunctionOnly, NoInterfaceObject] interface SuccessCallback {
+ /**
+ * \brief Method invoked when the asynchronous call completes successfully
+ */
+ void onSuccess();
+ };
+
+
+ /**
+ * \brief Success callback interface for requestFeature invocations
+ */
+ [Callback=FunctionOnly, NoInterfaceObject] interface RequestFeatureSuccessCallback {
+ /**
+ * \brief Method invoked upon a succesful requestFeature invocation
+ *
+ * \param ob Object implementing the JavaScript API associated with the requested Feature.
+ */
+ void onSuccess(in Object ob);
+ };
+
+
+ /**
+ * \brief Generic error callback interface.
+ */
+ [Callback=FunctionOnly, NoInterfaceObject] interface ErrorCallback {
+ /**
+ * \brief Method invoked when an error occurs
+ *
+ * \param error The error that is raised.
+ */
+ void onError(in GenericError error);
+ };
+
+ /**
+ * \brief Generic error interface.
+ *
+ *
+ */
+
+
+ interface GenericError {
+
+ /**
+ * \brief 16-bit error code.
+ */
+ readonly attribute unsigned short code;
+ };
+
+ /**
+ * \brief DeviceApiError error interface.
+ *
+ * The error codes must be in the range 10000-19999.
+ */
+
+ interface DeviceAPIError : GenericError {
+
+ /**
+ * \brief Unknown error.
+ */
+ const unsigned short UNKNOWN_ERROR = 10000;
+
+ /**
+ * \brief Invalid value was specified as input parameter.
+ */
+ const unsigned short INVALID_ARGUMENT_ERROR = 10001;
+
+ /**
+ * \brief The searched value or object was not found.
+ */
+ const unsigned short NOT_FOUND_ERROR = 10002;
+
+ /**
+ * \brief Operation is pending.
+ */
+ const unsigned short PENDING_OPERATION_ERROR = 10003;
+
+ /**
+ * \brief Input/Output error.
+ */
+ const unsigned short IO_ERROR = 10004;
+
+ /**
+ * \brief Not supported error.
+ */
+ const unsigned short NOT_SUPPORTED_ERROR = 10005;
+ };
+
+ /**
+ * \brief Security error interface.
+ *
+ * The error codes must be in the range 20000-29999
+ */
+ interface SecurityError : GenericError {
+ const unsigned short PERMISSION_DENIED_ERROR = 20000;
+ };
+
+ /**
+ * \brief PendingOperation.
+ *
+ * Interface that is returned by asynchronous operations in order to
+ * provide a cancellation operation.
+ */
+ interface PendingOperation {
+ /**
+ * \brief Call to cancel the underlying asynchronous operation.
+ *
+ * This call is always successful, i.e. the pending operation i.e.
+ * either cancelled or one of the callback is called.
+ *
+ * \return <em>false</em> if the cancellation did not succeed
+ * either because the pending operation finished already or because
+ * the cancellation cannot succeed due to technical limitations in
+ * the underlying implementation. Consquently the pending operation
+ * completes and depending on the success or failure the appropriate
+ * callbacks will be called.
+ * <em>true</em> if the cancellation did succeed. No callbacks will
+ * be called by the cancelled pending operation.
+ */
+ boolean cancel();
+ };
+
+ /**
+ * \brief BONDI root API.
+ * bondi root property exists in the global object
+ * \def-api-feature http://bondi.omtp.org/api/bondi.requestfeature
+ */
+ interface Bondi {
+ /**
+ * \brief Requests a feature.
+ *
+ * This function requests a named feature
+ * asynchronously and returns a pending operation object.
+ * If it succeeds it calls the successCallback and passes in
+ * the object of the requested feature. If it fails it calls
+ * the errorCallback passing in a DeviceAPIError which provides
+ * an error message and error code indicating the nature of the error.
+ *
+ * If the requested feature binds itself to a root namespace
+ * ( for example, "bondi.pim.contact") this will happen prior to the
+ * successCallback being invoked.
+ *
+ * \param successCallback the success callback function
+ * \param errorCallback the error callback function
+ * \param name the feature name IRI
+ *
+ * \return PendingOperation enabling the requester to cancel this request.
+ *
+ * The errorCallback will receive one of the following errors:
+ * \throw DeviceAPIError INVALID_ARGUMENT_ERROR if a malformed
+ * argument has been supplied or a required argument has been omitted.
+ * \throw DeviceAPIError NOT_FOUND_ERROR if the requested feature could not be found.
+ * \throw SecurityError PERMISSION_DENIED_ERROR if the
+ * requested feature is not permitted to load/bind or that
+ * access to a required device capability has been denied.
+ * \throw DeviceAPIError UNKNOWN_ERROR if an error occurred and a pending
+ * operation object can't be returned.
+ */
+ PendingOperation requestFeature(in RequestFeatureSuccessCallback successCallback,
+ in ErrorCallback errorCallback,
+ in DOMString name)
+ raises(DeviceAPIError, SecurityError);
+ };
+ interface BondiObject {
+ readonly attribute Bondi bondi;
+ };
+ Window implements bondiObject;
+};
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/examples/filesystem.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/examples/filesystem.widl
new file mode 100644
index 00000000000..35f602b858a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/examples/filesystem.widl
@@ -0,0 +1,1038 @@
+/*
+ * Licensed to OMTP Ltd. (OMTP) under one or more contributor license agreements.
+ * See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership.
+ *
+ * The Reference Implementation (save for such parts of the reference implementation made
+ * available under separate terms and conditions) is made available under the terms of the
+ * Apache License, version 2.0, subject to the condition that any "Works" and "Derivative
+ * Works" used or distributed for commercial purposes must be and remain compliant with the
+ * BONDI specification as promulgated by OMTP in each release. Your implementation of the
+ * Reference Implementation (whether object or source) must maintain these conditions, and
+ * you must notify any recipient of this condition in a conspicuous way.
+ *
+ * You may not use this BONDI Reference Implementation except in compliance with the License.
+ *
+ * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 or at
+ * http://bondi.omtp.org/BONDI-LICENSE-2.0
+ */
+
+/**
+ * \brief BONDI filesystem API.
+ *
+ * The BONDI filesystem API provides access to the filesystem of a device. The
+ * filesystem is abstractly represented as a collection of disjoint filesystem
+ * root locations each corresponding to some specific location in the device
+ * filesystem. The filesystem API exposes the hierarchies below these root
+ * locations as a single virtual filesystem but provides no access to other
+ * parts of the device filesystem.
+ *
+ * The roots that are exposed are determined by the platform also by the
+ * context in which the filesystem API is invoked.
+ *
+ * Each root has a string name. Each file or directory within the virtual
+ * filesystem is addressed using a fully-qualified path of the form:
+ * <em>&lt;root name&gt;/&lt;path&gt;</em> where <em>&lt;rootname&gt;</em> is
+ * the name of the root and <em>&lt;path&gt;</em> is the path to the file or
+ * directory relative to that root.
+ *
+ * The list of the supported root locations can be retrieved by calling
+ * filesystem.getRootLocations().
+ *
+ * The default location for a specific type of file, if one exists, can be
+ * obtained by calling the filesystem.getDefaultLocation(...) method. A set of
+ * platform-independent symbolic names for media types is defined. The default
+ * location for a given file type may itself be a root, or some subdirectory of
+ * a root. Although the set of roots available on a device is
+ * platform-dependent, the getDefaultLocation(...) functionality can be used to
+ * ensure that web applications can be written in a platform-independent way.
+ *
+ * In order to access specific locations which are prefixed with a value
+ * retrieved by filesystem.getDefaultLocation or some root location returned by
+ * filesystem.getRootLocations a File handle must be retrieved using the
+ * filesystem.resolve call.
+ *
+ * A File handle represents either a file or a directory. If it is a file the
+ * isFile attribute will be <em>true</em>, otherwise the isDirectory attribute
+ * will be <em>true</em>. A file can be opened for reading and writing, using a
+ * FileStream handle. A directory can be used to list its contents which is a
+ * list of files and sub-directories. There is a resolve method on directories
+ * as well in order to resolve files or sub-directories more conveniently than
+ * processing directory listings.
+ *
+ * The "/" character is used as the (path) component separator.
+ * The use of "." or ".." in location components is not required to be
+ * supported.
+ *
+ * All path characters need to be <a href="http://www.ietf.org/rfc/rfc2279.txt">UTF-8</a> encoded.
+ *
+ * \code
+ * function errorCB(err) {
+ * alert("BONDI filesystem API couldn't be requested: " + err.message);
+ * }
+ *
+ * function successCB() {
+ * var docLocation = bondi.filesystem.getDefaultLocation("documents");
+ * var docDir = bondi.filesystem.resolve(docLocation);
+ * var docFiles = docDir.listFiles();
+ * for(var i = 0; i &lt; docFiles.length; i++) {
+ * // displays name of each image file in image directory
+ * alert(docFiles[i].name);
+ * }
+ * var testFile = docDir.createFile("test.txt");
+ * var out = testFile.open("w", "UTF-8");
+ * // writes Hello World to test.txt
+ * out.write("Hello World");
+ * out.close();
+ * }
+ *
+ * bondi.requestFeature(successCB, errorCB, "filesystem");
+ * \endcode
+ *
+ * \def-api-feature http://bondi.omtp.org/api/filesystem.read
+ * \brief Filesystem read operations, including reading directory listings,
+ * file contents and resolving root locations.
+ * \device-cap io.file.read
+ *
+ * \def-api-feature http://bondi.omtp.org/api/filesystem.write
+ * \brief Filesystem write operations, including creating files/directories,
+ * writing to files, deleting files/directories, moving and copying
+ * files.
+ * \device-cap io.file.write
+ *
+ * \def-api-feature-set http://bondi.omtp.org/api/filesystem
+ * \brief All the FileSystem features
+ * \api-feature http://bondi.omtp.org/api/filesystem.read
+ * \api-feature http://bondi.omtp.org/api/filesystem.write
+ *
+ * \def-device-cap io.file.read
+ * \brief Read directory or file
+ * \param name Name of directory or file, in virtual filesystem,
+ * e.g. rootlocation/filename
+ *
+ * \def-device-cap io.file.write
+ * \brief Write directory or file
+ * \param name Name of directory or file, in virtual filesystem,
+ * e.g. rootlocation/filename
+ *
+ * \author Paddy Byers &lt;paddy@aplixcorp.com&gt;
+ * \author Anselm R Garbe &lt;anselm@aplixcorp.com&gt;
+ * \version 1.1
+ */
+module filesystem {
+
+ /**
+ * \brief Array of File handles.
+ *
+ * This array type is returned when directory listings are requested.
+ */
+ typedef sequence<File> FileArray;
+
+ /**
+ * \brief File system specific success callback.
+ *
+ * This callback interface specifies a success callback with a function
+ * taking a File object as input argument. It is used in asynchronous
+ * operations such as copying, moving and deleting files.
+ */
+ [Callback=FunctionOnly, NoInterfaceObject] interface FileSystemSuccessCallback {
+ /**
+ * \brief Method invoked when the asynchronous call completes succesfully
+ *
+ * \param file The file resulting from the asynchronous call
+ */
+ void onSuccess(in File file);
+ };
+
+ /**
+ * \brief Manager class exposed as the filesystem modules API.
+ *
+ * This manager class exposes the filesystem base API, such as
+ * determining root and default locations, resolving a given location
+ * into a File Handle and registering filesystem listeners for
+ * filesystem events.
+ *
+ * \code
+ * function errorCB(err) {
+ * alert("BONDI filesystem API couldn't be requested: " + err.message);
+ * }
+ *
+ * function successCB() {
+ * var docLocation = bondi.filesystem.getDefaultLocation("documents");
+ * var docDir = bondi.filesystem.resolve(docLocation);
+ * var docFiles = docDir.listFiles();
+ * for(var i = 0; i &lt; docFiles.length; i++) {
+ * // displays name of each image file in image directory
+ * alert(docFiles[i].name);
+ * }
+ * var testFile = docDir.createFile("test.txt");
+ * var out = testFile.open("w", "UTF-8");
+ * // writes Hello World to test.txt
+ * out.write("Hello World");
+ * out.close();
+ * }
+ *
+ * bondi.requestFeature(successCB, errorCB, "filesystem");
+ * \endcode
+ */
+ interface FileSystemManager {
+
+ /**
+ * \brief Contains the platform-dependent maximum path length.
+ *
+ * Read-only.
+ *
+ * \code
+ * alert(bondi.filesystem.maxPathLength);
+ * \endcode
+ */
+ readonly attribute unsigned long maxPathLength;
+
+ /**
+ * \brief Returns a default location path for the given arguments,
+ * including the root location prefix.
+ *
+ * Optionally this method can be called with the space argument
+ * specifying the minimum free disk space required.
+ *
+ * This function resolves location specifiers to location paths.
+ * The following location specifiers are supported:
+ * \n "wgt:package" the widget package location
+ * \n "wgt:private" the widgets private storage
+ * \n "wgt:public" the widgets public storage
+ * \n "wgt:temp" the widgets temporary storage
+ * \n "documents" the documents location,
+ * e.g. the "My Documents" directory on some systems
+ * \n "images" the images location,
+ * e.g. the "My Pictures" directory on some systems
+ * \n "videos" the videos location,
+ * e.g. the "My Videos" directory on some systems
+ * \n "temp" the temporary storage,
+ * e.g resolving to "Temp"
+ * \n "sdcard" the sdcard storage, if any
+ *
+ * \code
+ * var wgtLocation = bondi.filesystem.getDefaultLocation('wgt:package');
+ * \endcode
+ *
+ * \param specifier the location specifier, see above for supported specifiers.
+ * \param minFreeSpace optional, minimum required free disk space in bytes for
+ * this location, <em>0</em> (default) means no limitation
+ * \return the location as a string or <em>null</em> if there
+ * is no location for the given specifier or if there is not
+ * enough space left for the requested space in bytes.
+ * \throw DeviceAPIError INVALID_ARGUMENT_ERROR if the
+ * specifier or space arguments are invalid
+ */
+ DOMString getDefaultLocation(in DOMString specifier, in unsigned long minFreeSpace)
+ raises(DeviceAPIError);
+
+ /**
+ * \brief Returns all root locations.
+ *
+ * The root locations are symbolic names for filesystem
+ * locations which are accessible and supported by the
+ * underlying platform.
+ *
+ * Usually the following root locations will be supported:
+ * \n "documents" represents "My Documents" on some platforms
+ * \n "images" represents "My Pictures" on some platforms
+ * \n "videos" represents "My Videos" on some platforms
+ * \n "temp" represents "tmp" on some platforms
+ * \n "sdcard" represents the sdcard on some platforms
+ *
+ * See also the getDefaultLocation method.
+ *
+ * \code
+ * var locations = bondi.filesystem.getRootLocations();
+ * for(var i = 0; i &lt; locations.length; i++) {
+ * // locations[i] is a resolvable root location
+ * }
+ * \endcode
+ *
+ * \return string array of root locations.
+ */
+ StringArray getRootLocations();
+
+ /**
+ * \brief Resolves a location to a File handle.
+ *
+ * Validates and resolves the given location to a File handle
+ * and returns a handle. A valid location is prefixed with a
+ * valid root or default location and must address an existing
+ * and accessible file.
+ *
+ * \api-feature http://bondi.omtp.org/api/filesystem.read
+ *
+ * \code
+ * var location = bondi.filesystem.getDefaultLocation("temp");
+ * var temp = bondi.filesystem.resolve(location);
+ * var documents = bondi.filesystem.getDefaultLocation("documents");
+ * var mydoc = bondi.filesystem.resolve(documents + "/data/2009/mydoc.txt");
+ * \endcode
+ *
+ * \param location the location to resolve. Must be absolute
+ * prefixed by a valid root or default location.
+ * \return the resolved file object.
+ * \throw SecurityError PERMISSION_DENIED_ERROR when
+ * access is denied by the security policy.
+ * \throw DeviceAPIError INVALID_ARGUMENT_ERROR if invalid location was given.
+ */
+ File resolve(in DOMString location)
+ raises(SecurityError, DeviceAPIError);
+
+ /**
+ * \brief Registers a filesystem event listener.
+ *
+ * Filesystem event listeners are used in order to retrieve
+ * notifications if root or default locations such as storage
+ * cards are mounted/unmounted into/from the device filesystem.
+ *
+ * \api-feature http://bondi.omtp.org/api/filesystem.read
+ *
+ * \code
+ * var listener = { mountEvent: function(location) { alert('mounted ' + location); },
+ * unmountEvent: function(location) { alert('unmounted ' + location); };
+ * bondi.filesystem.registerEventListener(listener);
+ * \endcode
+ *
+ * \param listener the listener interface implementation
+ * \throw DeviceAPIError INVALID_ARGUMENT_ERROR if the given listener
+ * is invalid or not a listener.
+ */
+ void registerEventListener(in FileSystemListener listener)
+ raises(DeviceAPIError);
+
+ /**
+ * \brief Unregisters a filesystem event listener.
+ *
+ * \code
+ * bondi.filesystem.unregisterEventListener(listener);
+ * \endcode
+ *
+ * \param listener the listener interface implementation
+ * \throw DeviceAPIError INVALID_ARGUMENT_ERROR if the given listener
+ * is invalid or not a listener.
+ */
+ void unregisterEventListener(in FileSystemListener listener)
+ raises(DeviceAPIError);
+ };
+
+ /**
+ * \brief Filesystem event listener class.
+ *
+ * This listener implements two methods to retrieve mount and unmount
+ * notifications if root or default locations on a storage card get
+ * available or unavailable.
+ *
+ * \code
+ * var fsEventImpl = {
+ * mountEvent: function(location) {
+ * // location has been mounted
+ * },
+ * unmountEvent: function(location) {
+ * // location has been unmounted
+ * }
+ * };
+ * \endcode
+ */
+ interface FileSystemListener {
+
+ /**
+ * \brief Called when a new root location gets available.
+ *
+ * A new location could be a storage card for example.
+ *
+ * \param location the newly available location
+ */
+ void mountEvent(in DOMString location);
+
+ /**
+ * \brief Called when a location gets unavailable.
+ *
+ * Such a location could be a storage card for example.
+ *
+ * \param location the location which is becoming unavailable
+ */
+ void unmountEvent(in DOMString location);
+ };
+
+ /**
+ * \brief File class.
+ *
+ * This interface represents the file abstraction in use. A file handle
+ * can address files or directories. A file handle represents a file
+ * if the isFile property is <em>true</em>, otherwise it represents a
+ * directory.
+ *
+ * A file handle representing a file can be opened for I/O operations
+ * such as reading and writing.
+ *
+ * A file handle representing a directory can list all files in the
+ * current directory.
+ *
+ * \code
+ *
+ * // list directory contents
+ * var files = dir.listFiles();
+ * for(var i = 0; i &lt; files.length; i++) {
+ * // alerts each name of dir's contents
+ * alert(files[i].name);
+ * }
+ *
+ * // opens a file for writing
+ * var file = dir.createFile("test.txt");
+ * var out = file.open("w", "UTF-8");
+ * // writes Hello World to test.txt
+ * out.write("Hello World");
+ * out.close();
+ * \endcode
+ */
+ interface File {
+
+ /**
+ * \brief Parent directory handle.
+ *
+ * Read-only.
+ *
+ * <em>null</em> if there is no parent directory.
+ *
+ * If there is no parent directory, this represents a root location.
+ *
+ * \code
+ * var parent = file.parent;
+ * if(parent != null) {
+ * // parent directory handle
+ * }
+ * \endcode
+ */
+ readonly attribute File parent;
+
+ /**
+ * \brief File/directory access state in the filesystem.
+ *
+ * Read-only.
+ *
+ * <em>false</em> if there is write access.
+ *
+ * This attribute represents the actual state of a
+ * file/directory in the filesystem. It does not check if the
+ * accessor has io.file.write permission.
+ *
+ * \code
+ * if(file.readOnly) {
+ * // file cannot be written
+ * }
+ * \endcode
+ */
+ readonly attribute boolean readOnly;
+
+ /**
+ * \brief File type.
+ *
+ * Read-only.
+ *
+ * <em>true</em> if this handle is a file.
+ * <em>false</em> if this handle is a directory.
+ *
+ * \code
+ * if(file.isFile) {
+ * // is a file
+ * }
+ * \endcode
+ */
+ readonly attribute boolean isFile;
+
+ /**
+ * \brief File type.
+ *
+ * Read-only.
+ *
+ * <em>true</em> if this handle is a directory.
+ * <em>false</em> if this handle is a file.
+ *
+ * \code
+ * if(file.isDirectory) {
+ * // is a directory
+ * }
+ * \endcode
+ */
+ readonly attribute boolean isDirectory;
+
+ /**
+ * \brief Creation timestamp.
+ *
+ * Read-only.
+ *
+ * The creation timestamp of this file. This is the timestamp
+ * when the file was first created in the filesystem. This is
+ * equivalent to the timestamp when a call to createFile()
+ * succeeds.
+ *
+ * It is unspecified and platform-dependent if the creation
+ * timestamp changes when a file is moved.
+ *
+ * \code
+ * alert(file.created); // displays the creation timestamp
+ * \endcode
+ *
+ */
+ readonly attribute Date created;
+
+ /**
+ * \brief Modification timestamp.
+ *
+ * Read-only.
+ *
+ * The modification timestamp of this file. This is the timestamp
+ * of the most recent modification to the file, usually when the last
+ * write operation succeeded. Opening a file for reading does not change
+ * the modification timestamp.
+ *
+ * \code
+ * alert(file.modified); // displays the modification timestamp
+ * \endcode
+ *
+ */
+ readonly attribute Date modified;
+
+ /**
+ * \brief Path of this file, excluding the file name.
+ *
+ * Read-only.
+ *
+ * If the file path is <em>/baz/foo.bar</em>, then
+ * the path is <em>/baz/</em>.
+ *
+ * The encoding of file paths is <a href="http://www.ietf.org/rfc/rfc2279.txt">UTF-8</a>.
+ *
+ * \code
+ * alert(file.path); // should be /baz/ if the file is /baz/foo.bar
+ * \endcode
+ */
+ readonly attribute DOMString path;
+
+ /**
+ * \brief File name, excluding any path components.
+ *
+ * Read-only.
+ *
+ * Assumed the file path is <em>/baz/foo.bar</em>, then
+ * the file name is <em>foo.bar</em>.
+ *
+ * The encoding of file names is <a href="http://www.ietf.org/rfc/rfc2279.txt">UTF-8</a>.
+ *
+ * \code
+ * alert(file.name); // should be foo.bar if the file path is /baz/foo.bar
+ * \endcode
+ */
+ readonly attribute DOMString name;
+
+ /**
+ * \brief Absolute path of this file.
+ *
+ * Read-only.
+ *
+ * Assumed the file path is <em>/baz/foo.bar</em>, then this is the absolute path.
+ *
+ * The encoding of file paths is <a href="http://www.ietf.org/rfc/rfc2279.txt">UTF-8</a>.
+ *
+ * \code
+ * alert(file.absolutePath); // should be /baz/foo.bar if the file is /baz/foo.bar
+ * \endcode
+ */
+ readonly attribute DOMString absolutePath;
+
+ /**
+ * \brief Size in bytes of this file.
+ *
+ * Read-only.
+ *
+ * If it is attempted to read this attribute on a directory,
+ * <em>undefined</em> is returned.
+ *
+ * \code
+ * alert(file.fileSize); // displays the file size
+ * \endcode
+ */
+ readonly attribute unsigned long fileSize;
+
+ /**
+ * \brief Files metadata.
+ *
+ * The actual map contents are implementation dependent.
+ *
+ * \code
+ * // should display the file author, if supported by the
+ * // platform, undefined otherwise
+ * alert(file.metadata.author);
+ * \endcode
+ */
+ readonly attribute Map metadata;
+
+ /**
+ * \brief Returns list of all files of this directory.
+ *
+ * The list of files contains directories and files, it does
+ * not contain the directories "." and "..".
+ *
+ * \api-feature http://bondi.omtp.org/api/filesystem.read
+ *
+ * \code
+ * var files = dir.listFiles();
+ * for(var i = 0; i &lt; files.length; i++) {
+ * // files[i] iterate over all files of this directory
+ * }
+ * \endcode
+ *
+ * \return array of contents of this directory.
+ * \throw SecurityError PERMISSION_DENIED_ERROR when
+ * access is denied by the security policy.
+ * \throw DeviceAPIError IO_ERROR if this is not a directory.
+ */
+ FileArray listFiles()
+ raises(SecurityError, DeviceAPIError);
+
+ /**
+ * \brief Opens the file in the given mode supporting the given
+ * encoding.
+ *
+ * \api-feature http://bondi.omtp.org/api/filesystem.read
+ * \api-feature http://bondi.omtp.org/api/filesystem.write
+ *
+ * \code
+ * // opens file for reading
+ * var in = file.open("r", "UTF-8");
+ * \endcode
+ *
+ * \param mode the mode for opening a file
+ * \n "r" for reading
+ * \n "a" for appending
+ * \n "w" for [over]writing
+ * \param encoding the encoding for read/write operations on the file,
+ * supported encodings are:
+ * \n "<a href="http://www.ietf.org/rfc/rfc2279.txt">UTF-8</a>" default encoding
+ * \n "<a href="http://en.wikipedia.org/wiki/ISO/IEC_8859-1">ISO8859-1</a>" latin1 encoding
+ * \return file stream handle to read/write from/to.
+ * \throw SecurityError PERMISSION_DENIED_ERROR when
+ * access is denied by the security policy.
+ * \throw DeviceAPIError INVALID_ARGUMENT_ERROR if invalid mode
+ * or unsupported encoding is supplied.
+ * \throw DeviceAPIError IO_ERROR if this is not a file.
+ */
+ FileStream open(in DOMString mode, in DOMString encoding)
+ raises(SecurityError, DeviceAPIError);
+
+ /**
+ * \brief Copies this file.
+ *
+ * The copy will be created in the given path. If this function
+ * fails and the error callback is called, it will pass an
+ * DeviceAPIError IO_ERROR to the callback.
+ *
+ * The encoding of file paths is <a href="http://www.ietf.org/rfc/rfc2279.txt">UTF-8</a>.
+ *
+ * \api-feature http://bondi.omtp.org/api/filesystem.write
+ *
+ * \code
+ * // copies this file to /temp/file.copy
+ * var op = file.copyTo(function(copiedFile) { alert("file copied"); }, null, "/temp/file.copy", false);
+ * \endcode
+ *
+ * \param successCallback called when the file has been copied.
+ * \param errorCallback called if an error occured.
+ * \param filePath the new file path, [a-Z0-9_- /]+ are allowed
+ * \param overwrite <em>true</em> enforces overwriting an existing file.
+ * \return PendingOperation enabling the requester to cancel this request.
+ * \throw SecurityError PERMISSION_DENIED_ERROR when
+ * access is denied by the security policy.
+ * \throw DeviceAPIError IO_ERROR if it is attempted to move to a directory.
+ * \throw DeviceAPIError IO_ERROR if overwrite is <em>false</em> and target file exists.
+ * \throw DeviceAPIError IO_ERROR if any characters in the path are not supported.
+ * \throw DeviceAPIError IO_ERROR if the file cannot be copied.
+ */
+ PendingOperation copyTo(in FileSystemSuccessCallback successCallback,
+ in ErrorCallback errorCallback,
+ in DOMString filePath,
+ in boolean overwrite)
+ raises(SecurityError, DeviceAPIError);
+
+ /**
+ * \brief Moves this file.
+ *
+ * The file will be moved atomically to the given path. This is
+ * different to copyTo and deleting the old file, because this
+ * operation does not need extra disk space on certain platforms.
+ * If this function fails and the error callback is called, it
+ * will pass an DeviceAPIError IO_ERROR to the callback.
+ *
+ * The encoding of file paths is <a href="http://www.ietf.org/rfc/rfc2279.txt">UTF-8</a>.
+ *
+ * \api-feature http://bondi.omtp.org/api/filesystem.write
+ *
+ * \code
+ * // moves this file to /temp/file.move
+ * var op = file.moveTo(function(movedFile) { file = movedFile; }, null, "/temp/file.move");
+ * \endcode
+ *
+ * \param successCallback called when the file has been copied.
+ * \param errorCallback called if an error occured.
+ * \param filePath the new file name, [a-Z0-9_- /]+ are allowed
+ * \param overwrite <em>true</em> enforces overwriting an existing file.
+ * \return PendingOperation enabling the requester to cancel this request.
+ * \throw SecurityError PERMISSION_DENIED_ERROR when
+ * access is denied by the security policy.
+ * \throw DeviceAPIError IO_ERROR if it is attempted to move to a directory.
+ * \throw DeviceAPIError IO_ERROR if overwrite is <em>false</em> and target file exists.
+ * \throw DeviceAPIError IO_ERROR if any characters in the path are not supported.
+ * \throw DeviceAPIError IO_ERROR if the file cannot be moved.
+ */
+ PendingOperation moveTo(in FileSystemSuccessCallback successCallback,
+ in ErrorCallback errorCallback,
+ in DOMString filePath,
+ in boolean overwrite)
+ raises(SecurityError, DeviceAPIError);
+
+ /**
+ * \brief Creates a directory.
+ *
+ * The new directory will be created relatively to the current
+ * directory this operation is performed on. It will attempt to
+ * create all necessary sub-directories as well. The use of "."
+ * or ".." in path components is not supported. If the
+ * bottom-most directory being created already exists this
+ * method will throw an IO_ERROR.
+ *
+ * The encoding of file paths is <a href="http://www.ietf.org/rfc/rfc2279.txt">UTF-8</a>.
+ *
+ * \api-feature http://bondi.omtp.org/api/filesystem.write
+ *
+ * \code
+ * var newDir = dir.createDirectory("newDir");
+ * var anotherNewDir = dir.createDirectory("newDir1/subNewDir1");
+ * \endcode
+ *
+ * \param dirPath the new directory path, it should only contain
+ * characters supported by the underlying filesystem.
+ * \return file handle of the new directory
+ * \throw SecurityError PERMISSION_DENIED_ERROR when
+ * access is denied by the security policy.
+ * \throw DeviceAPIError IO_ERROR if this is not a directory.
+ * \throw DeviceAPIError IO_ERROR if any path component does not exist.
+ * \throw DeviceAPIError IO_ERROR if a file with the same name exists.
+ * \throw DeviceAPIError IO_ERROR if any characters in the path are not supported.
+ * \throw DeviceAPIError IO_ERROR if the directory cannot be created.
+ */
+ File createDirectory(in DOMString dirPath)
+ raises(SecurityError, DeviceAPIError);
+
+ /**
+ * \brief Creates a new empty file.
+ *
+ * The new empty file is created in the given path relatively
+ * to the current directory the operation is performed on. The
+ * use of "." or ".." in path components is not supported. If
+ * the bottom-most file being created already exists this
+ * method will throw an IO_ERROR. If any path component does
+ * not exist this method will throw an IO_ERROR.
+ *
+ * The encoding of file paths is <a href="http://www.ietf.org/rfc/rfc2279.txt">UTF-8</a>.
+ *
+ * \api-feature http://bondi.omtp.org/api/filesystem.write
+ *
+ * \code
+ * var newFile = dir.createFile("newFile");
+ * \endcode
+ *
+ * \param filePath the new file path, it should only contain
+ * characters supported by the underlying filesystem.
+ * \return file handle of the new empty file
+ * \throw SecurityError PERMISSION_DENIED_ERROR when
+ * access is denied by the security policy.
+ * \throw DeviceAPIError IO_ERROR if this is not a directory.
+ * \throw DeviceAPIError IO_ERROR if any path component does not exist.
+ * \throw DeviceAPIError IO_ERROR if the file already exists.
+ * \throw DeviceAPIError IO_ERROR if any characters in the path are not supported.
+ * \throw DeviceAPIError IO_ERROR if the file cannot be created.
+ */
+ File createFile(in DOMString filePath)
+ raises(SecurityError, DeviceAPIError);
+
+ /**
+ * \brief Resolves an existing file or directory relatively to
+ * the current directory this operation is performed on; and
+ * returns a file handle for it.
+ *
+ * The filePath is not allowed to contain the "." or ".." directories.
+ *
+ * The encoding of file paths is <a href="http://www.ietf.org/rfc/rfc2279.txt">UTF-8</a>.
+ *
+ * \api-feature http://bondi.omtp.org/api/filesystem.read
+ *
+ * \code
+ * var hellofile = dir.resolve("foo/hello.txt");
+ * \endcode
+ *
+ * \param filePath the relative file/directory path to resolve.
+ * \return file handle of the file or <em>null</em> if it cannot be resolved.
+ * \throw SecurityError PERMISSION_DENIED_ERROR when
+ * access is denied by the security policy.
+ * \throw DeviceAPIError IO_ERROR if this is not a directory.
+ * \throw DeviceAPIError IO_ERROR if any characters in the path are not supported.
+ * \throw DeviceAPIError IO_ERROR if the file or directory cannot be resolved.
+ */
+ File resolve(in DOMString filePath)
+ raises(SecurityError, DeviceAPIError);
+
+ /**
+ * \brief Deletes this directory.
+ *
+ * This function attempts to delete a directory or directory
+ * tree synchronously and returns <em>true</em> on success,
+ * <em>false</em> otherwise. It may throw an IO_ERROR if a
+ * recursive deletion partially fails and any deleted data so
+ * far cannot be recovered. This might happen due the lack of
+ * filesystem permissions or if any directories or files are
+ * openened by other processes.
+ *
+ * \api-feature http://bondi.omtp.org/api/filesystem.write
+ *
+ * \code
+ * var fullPath = dir.fullPath;
+ * if(dir.deleteDirectory(true)) {
+ * // subsequent accesses to dir will throw an error
+ * alert(fullPath + ' deleted');
+ * }
+ * \endcode
+ *
+ * \param recursive <em>true</em> means a recursive deletion, this
+ * will destroy all data recursively, use with caution.
+ * \return <em>true</em> on success
+ * \throw SecurityError PERMISSION_DENIED_ERROR when
+ * access is denied by the security policy.
+ * \throw DeviceAPIError IO_ERROR if this is a file.
+ * \throw DeviceAPIError IO_ERROR if the directory is not empty and
+ * this operation is not performed recursively.
+ * \throw DeviceAPIError IO_ERROR if the directory or any file or sub-directory cannot be deleted.
+ */
+ boolean deleteDirectory(in boolean recursive)
+ raises(SecurityError, DeviceAPIError);
+
+ /**
+ * \brief Deletes this file.
+ *
+ * Returns <em>true</em> on success, <em>false</em> otherwise.
+ *
+ * \api-feature http://bondi.omtp.org/api/filesystem.write
+ *
+ * \code
+ * var fullPath = dir.fullPath;
+ * if(dir.deleteFile()) {
+ * // subsequent accesses to dir will throw an error
+ * alert(fullPath + ' deleted');
+ * }
+ * \endcode
+ *
+ * \return <em>true</em> on success
+ * \throw SecurityError PERMISSION_DENIED_ERROR when
+ * access is denied by the security policy.
+ * \throw DeviceAPIError IO_ERROR if this is a directory.
+ * \throw DeviceAPIError IO_ERROR if the file cannot be deleted due
+ * the lack of filesystem permissions or if it is locked or
+ * opened by another process.
+ */
+ boolean deleteFile()
+ raises(SecurityError, DeviceAPIError);
+ };
+
+ /**
+ * \brief FileStream API.
+ *
+ * A FileStream represents a handle to a File opened for read and/or
+ * write operations. Read and write operations are performed relative
+ * to a file pointer which represents the current position in the file.
+ *
+ * A series of read/write methods are available that permit both binary and
+ * text to be processed.
+ *
+ * Once a file stream is closed, any operation attempted on this stream
+ * will result in a normal JavaScript error.
+ */
+ interface FileStream {
+
+ /**
+ * \brief Indicates whether or not the current file pointer is at the end
+ * of the file.
+ *
+ * <em>true</em> if the position is at the end of the current file stream.
+ *
+ * \code
+ * if(stream.eof) {
+ * // file has been read completely
+ * }
+ * \endcode
+ */
+ readonly attribute boolean eof;
+
+ /**
+ * \brief Get/set stream position for reads/writes.
+ *
+ * The stream position is an offset of bytes from the start of
+ * the file stream. When invoking an operation that reads or
+ * writes from the stream, the operation will take place from
+ * the position in the position attribute.
+ *
+ * \code
+ * alert(stream.position); // displays current stream position
+ * // alters current stream position to the begin of the file,
+ * // like seek() in C
+ * stream.position = 0;
+ * \endcode
+ * \throw DeviceAPIError IO_ERROR if a position was given that is out of the stream range.
+ */
+ attribute unsigned long position
+ setraises(DeviceAPIError);
+
+ /**
+ * \brief Returns the number of bytes that are available for
+ * reading from the stream.
+ *
+ * The number of bytes available for reading is the maximum
+ * amount of bytes that can be read in the next read operation.
+ *
+ * -1 if eof is <em>true</em>.
+ *
+ * \code
+ * alert(stream.bytesAvailable); // displays the available bytes to be read
+ * \endcode
+ */
+ readonly attribute unsigned long bytesAvailable;
+
+ /**
+ * \brief Closes this FileStream.
+ *
+ * Flushes any pending buffered writes and closes the File. Always succeeds.
+ * Note that pending writes might not succeed.
+ *
+ * \code
+ * stream.close(); // closes this stream, no subsequent access to stream allowed
+ * \endcode
+ */
+ void close();
+
+ /**
+ * \brief Reads the specified number of characters.
+ *
+ * Reads specified number of characters and returns them as string.
+ * The resulting string length might be shorter than charCount if eof
+ * is <em>true</em>.
+ *
+ * \code
+ * var text = stream.read(0);
+ * stream.close();
+ * \endcode
+ *
+ * \param charCount number of characters being read, if
+ * <em>0</em> it will read as long as bytes are available.
+ * \return the result of read characters as a string.
+ * \throw DeviceAPIError IO_ERROR if an error occurs during read.
+ */
+ DOMString read(in unsigned long charCount)
+ raises(DeviceAPIError);
+
+ /**
+ * \brief Reads the specified number of bytes from this FileStream.
+ *
+ * If 0 is supplied it will read all available bytes in a
+ * single read operation.
+ *
+ * \code
+ * // reads up to 256 bytes from the stream
+ * var raw = stream.readBytes(256);
+ * for(var i = 0; i &lt; raw.length; i++) {
+ * // raw[i] contains the i-th byte of the current data chunk
+ * }
+ * \endcode
+ *
+ * \param byteCount number of bytes being read. Must not be <em>0</em>.
+ * \return the result of read bytes as a byte (or number) array.
+ * \throw DeviceAPIError IO_ERROR if an error occurs during readBytes.
+ */
+ ByteArray readBytes(in unsigned long byteCount)
+ raises(DeviceAPIError);
+
+ /**
+ * \brief Reads the specified number of bytes from this FileStream, encoding
+ * the result in base64.
+ *
+ * If 0 is supplied it will read all available bytes in a
+ * single read operation.
+ *
+ * \code
+ * // reads up to 256 bytes from the stream
+ * var base64 = stream.readBase64(256);
+ * \endcode
+ *
+ * \param byteCount number of bytes being read. Must not be <em>0</em>.
+ * \return the result of read bytes as base64 encoding string.
+ * \throw DeviceAPIError IO_ERROR if an error occurs during readBase64.
+ */
+ DOMString readBase64(in unsigned long byteCount)
+ raises(DeviceAPIError);
+
+ /**
+ * \brief Writes the specified DOMString to this FileStream.
+ *
+ * \code
+ * var text = "Hello world";
+ * stream.write(text);
+ * \endcode
+ *
+ * \param stringData the actual string to be written.
+ * \throw DeviceAPIError IO_ERROR if an error occurs during write.
+ */
+ void write(in DOMString stringData)
+ raises(DeviceAPIError);
+
+ /**
+ * \brief Writes the specified bytes to this FileStream.
+ *
+ * \code
+ * var bytes = in.readBytes(256);
+ * out.writeBytes(bytes); // writes the bytes read from in to out
+ * \endcode
+ *
+ * \param byteData the byte data array being written.
+ * \throw DeviceAPIError IO_ERROR if an error occurs during writeBytes.
+ */
+ void writeBytes(in ByteArray byteData)
+ raises(DeviceAPIError);
+
+ /**
+ * \brief Converts the specified base64 DOMString to bytes and writes the
+ * result to this FileStream.
+ *
+ * \code
+ * var base64 = in.readBase64(256);
+ * out.writeBase64(base64); // writes the base64 data read from in to out
+ * \endcode
+ *
+ * \param base64Data the base64 data being written.
+ * \throw DeviceAPIError IO_ERROR if an error occurs during writeBase64.
+ */
+ void writeBase64(in DOMString base64Data)
+ raises(DeviceAPIError);
+ };
+
+ /**
+ * \brief Specifies what is instantiated at feature request
+ * \def-instantiated
+ * \api-feature http://bondi.omtp.org/api/filesystem.read
+ * \api-feature http://bondi.omtp.org/api/filesystem.write
+ */
+ interface FileSystemManagerObject {
+ readonly attribute FileSystemManager fileSystemManager;
+ };
+ bondi implements FileSystemManagerObject;
+
+};
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/examples/spectowidl.xsl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/examples/spectowidl.xsl
new file mode 100644
index 00000000000..44252770940
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/examples/spectowidl.xsl
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--====================================================================
+$Id$
+Copyright 2009 Aplix Corporation. All rights reserved.
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+XSLT stylesheet to extract Web IDL snippets from Web IDL spec.
+=====================================================================-->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+<xsl:output method="text" encoding="utf-8"/>
+
+<xsl:template match="code[@class='idl-code']">
+ <xsl:value-of select="."/><xsl:text>
+</xsl:text>
+</xsl:template>
+
+<xsl:template match="text()"/>
+
+</xsl:stylesheet>
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/examples/widlhtml.css b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/examples/widlhtml.css
new file mode 100644
index 00000000000..8543097a3cc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/examples/widlhtml.css
@@ -0,0 +1,100 @@
+body {
+ padding: 2em;
+ margin: 0;
+ font-family: sans-serif;
+ color: black;
+ background: white;
+ background-position: top left;
+ background-attachment: fixed;
+ background-repeat: no-repeat;
+}
+:link { color: #00C; background: transparent }
+:visited { color: #609; background: transparent }
+a:active { color: #C00; background: transparent }
+a:link img, a:visited img { border-style: none } /* no border on img links */
+
+h1, h2, h3, h4, h5, h6 { text-align: left }
+/* background should be transparent, but WebTV has a bug */
+h1, h2, h3 { color: #009393; background: white }
+h1 { font: 170% sans-serif }
+h2 { font: 140% sans-serif }
+h3 { font: 120% sans-serif }
+h4 { font: bold 100% sans-serif }
+h5 { font: italic 100% sans-serif }
+h6 { font: small-caps 100% sans-serif; margin-bottom: 0 }
+
+.hide { display: none }
+
+code { font-size: 120% }
+
+ul.toc, ol.toc, ul.authors {
+ list-style: none;
+}
+
+.hide { display: none }
+
+div.head { margin-bottom: 1em }
+div.head h1 { margin-top: 2em; clear: both }
+div.head table { margin-left: 2em; margin-top: 2em }
+div.constraint, div.issue, div.note, div.notice { margin-left: 2em; }
+div.exampleInner pre { margin-left: 1em; margin-top: 0em; margin-bottom: 0em}
+div.exampleOuter {border: 4px double gray; margin: 0em; padding: 0em}
+div.exampleInner { background-color: #d5dee3;
+ border-top-width: 4px;
+ border-top-style: double;
+ border-top-color: #d3d3d3;
+ border-bottom-width: 4px;
+ border-bottom-style: double;
+ border-bottom-color: #d3d3d3;
+ padding: 4px; margin: 0em }
+div.exampleWrapper { margin: 4px }
+div.exampleHeader { font-weight: bold; margin: 4px}
+div.term { font: 100% sans-serif; color:#000000; font-weight: bold; line-height: 60%}
+div.list { font: 100% sans-serif; color:#000000; font-weight: normal; line-height: 60%}
+
+.optional {text-decoration: line-through; display: none;}
+
+.copyright,.legalnotice { font-size: small }
+.copyright small { font-size: small }
+
+@media screen { /* hide from IE3 */
+a[href]:hover { background: #ffa }
+}
+
+ol.enumar { list-style-type: decimal; }
+ol.enumla { list-style-type: lower-alpha; }
+ol.enumlr { list-style-type: lower-roman; }
+ol.enumua { list-style-type: upper-alpha; }
+ol.enumur { list-style-type: upper-roman; }
+
+/* BONDI additions */
+
+.toc {
+ list-style-type: none;
+}
+
+pre {
+ background-color:#D5DEE3;
+ overflow: auto;
+ padding: 1em;
+}
+
+.examplecode {
+ background-color: #EEE;
+}
+
+.def-api-feature-set dt, .def-api-feature dt, dt .def-device-cap, dt.const code { font: bold 100% sans-serif; }
+dt.attribute code, dt.method code { font: italic 100% sans-serif; }
+
+.def-device-caps dd { margin-bottom: 2em }
+
+dt.method { margin-top: 2em }
+
+.summary td {
+ text-align: left;
+ background-color: #BBDDDD;
+ color: inherit;
+ font-family: monospace;
+ white-space:pre;
+ padding: .3em 1em .3em 1em;
+}
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/comment.c b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/comment.c
new file mode 100644
index 00000000000..622a7bea7b4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/comment.c
@@ -0,0 +1,1827 @@
+/***********************************************************************
+ * $Id$
+ * Copyright 2009 Aplix Corporation. All rights reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ***********************************************************************/
+#include <assert.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "comment.h"
+#include "entities.h"
+#include "lex.h"
+#include "misc.h"
+#include "node.h"
+#include "os.h"
+#include "process.h"
+
+/* struct cnode : a node in the comment parse tree */
+struct cnode {
+ struct cnode *next;
+ struct cnode *children;
+ struct cnode *parent;
+ const struct cnodefuncs *funcs;
+ const char *attrtext;
+ const char *filename;
+ unsigned int linenum;
+};
+
+struct cnodefuncs {
+ int indesc; /* non-zero if it outputs its own xml element that does
+ not want to be inside <description> */
+ int needpara; /* non-zero if text must be in a para node that is a child
+ of this one */
+ int (*askend)(struct cnode *cnode, const struct cnodefuncs *type);
+ void (*end)(struct cnode *cnode);
+ void (*output)(struct cnode *cnode, unsigned int indent);
+};
+
+struct paramcnode {
+ struct cnode cn;
+ int inout;
+ char name[1];
+};
+
+/* struct comment : a doxygen comment */
+struct comment {
+ struct comment *next;
+ struct node *node;
+ unsigned int type;
+ const char *filename;
+ unsigned int linenum;
+ struct cnode root;
+ int back; /* Whether the comment refers back rather than forward. */
+ char *text;
+};
+
+
+static struct node *lastidentifier;
+static struct comment *comments;
+static int incode, inhtmlblock;
+static struct comment *curcomment;
+
+/***********************************************************************
+ * htmleldescs : table of recnogized HTML elements
+ */
+#define HTMLEL_EMPTY 1
+#define HTMLEL_INLINE 2
+#define HTMLEL_BLOCK 4
+#define HTMLEL_AUTOCLOSE 8
+#define HTMLEL_LI 0x10
+#define HTMLEL_DLCONTENTS 0x20
+#define HTMLEL_TABLECONTENTS 0x40
+#define HTMLEL_TRCONTENTS 0x80
+
+#define HTMLEL_FLOW (HTMLEL_BLOCK | HTMLEL_INLINE)
+
+struct htmleldesc {
+ unsigned int namelen;
+ const char *name;
+ unsigned int flags;
+ unsigned int content;
+};
+
+static const struct htmleldesc htmleldescs[] = {
+ { 1, "a", HTMLEL_INLINE, 0 },
+ { 1, "b", HTMLEL_INLINE, 0 },
+ { 2, "br", HTMLEL_INLINE, HTMLEL_EMPTY },
+ { 3, "img", HTMLEL_INLINE, HTMLEL_EMPTY },
+ { 2, "dd", HTMLEL_DLCONTENTS, HTMLEL_FLOW },
+ { 2, "dl", HTMLEL_BLOCK, HTMLEL_DLCONTENTS },
+ { 2, "dt", HTMLEL_DLCONTENTS, HTMLEL_INLINE },
+ { 2, "em", HTMLEL_INLINE, 0 },
+ { 2, "li", HTMLEL_LI, HTMLEL_FLOW },
+ { 2, "ol", HTMLEL_BLOCK, HTMLEL_LI },
+ { 1, "p", HTMLEL_BLOCK, HTMLEL_INLINE },
+ { 2, "td", HTMLEL_TRCONTENTS | HTMLEL_AUTOCLOSE, HTMLEL_FLOW },
+ { 2, "th", HTMLEL_TRCONTENTS | HTMLEL_AUTOCLOSE, HTMLEL_FLOW },
+ { 2, "tr", HTMLEL_TABLECONTENTS | HTMLEL_AUTOCLOSE, HTMLEL_TRCONTENTS },
+ { 5, "table", HTMLEL_BLOCK, HTMLEL_TABLECONTENTS },
+ { 2, "ul", HTMLEL_BLOCK, HTMLEL_LI },
+ { 0, 0, 0, 0 }
+};
+#define HTMLELDESC_B (htmleldescs + 1)
+#define HTMLELDESC_BR (htmleldescs + 2)
+
+/***********************************************************************
+ * addcomment : add a comment to the list of comments if it has doxygen syntax
+ *
+ * Enter: tok struct
+ */
+void
+addcomment(struct tok *tok)
+{
+ if (tok->len >= 1 && (tok->start[0] == '!'
+ || (tok->type == TOK_BLOCKCOMMENT && tok->start[0] == '*')
+ || (tok->type == TOK_INLINECOMMENT && tok->start[0] == '/')))
+ {
+ struct comment *comment;
+ comment = memalloc(sizeof(struct comment));
+ comment->text = memalloc(tok->len + 1);
+ memcpy(comment->text, tok->start, tok->len);
+ comment->text[tok->len] = 0;
+ comment->type = tok->type;
+ comment->filename = tok->filename;
+ comment->linenum = tok->linenum;
+ comment->node = 0;
+ comment->back = 0;
+ if (comment->text[1] == '<') {
+ comment->back = 1;
+ if (!lastidentifier) {
+ locerrorexit(comment->filename, comment->linenum,
+ "no identifier to attach doxygen comment to");
+ }
+ comment->node = lastidentifier;
+ }
+ comment->next = comments;
+ comments = comment;
+ }
+}
+
+/***********************************************************************
+ * setcommentnode : set parse node to attach comments to
+ *
+ * Enter: node2 = parse node for identifier
+ */
+void
+setcommentnode(struct node *node2)
+{
+ struct comment *comment = comments;
+ while (comment && !comment->node) {
+ comment->node = node2;
+ comment = comment->next;
+ }
+ lastidentifier = node2;
+}
+
+/***********************************************************************
+ * joininlinecomments : join adjacent inline comments
+ *
+ * Enter: comment = list of comment structs
+ *
+ * Return: new list of comment structs
+ *
+ * This function also discards any single inline comment that does not
+ * refer back.
+ */
+static struct comment *
+joininlinecomments(struct comment *comments)
+{
+ struct comment **pcomment;
+ pcomment = &comments;
+ for (;;) {
+ struct comment *comment;
+ comment = *pcomment;
+ if (!comment)
+ break;
+ if (comment->type != TOK_INLINECOMMENT) {
+ /* Keep block comment as is. */
+ pcomment = &comment->next;
+ } else if (!comment->back && (!comment->next
+ || comment->next->type != TOK_INLINECOMMENT
+ || comment->next->filename != comment->filename
+ || comment->next->linenum != comment->linenum + 1))
+ {
+ /* Discard single // comment that does not refer back. */
+ *pcomment = comment->next;
+
+ } else {
+ /* Find sequence of adjacent // comments (adjacent lines,
+ * referring to same node) and join them. We do this in two
+ * passes, one to count the length of the comment and one
+ * to join. Note that the list is still in reverse order,
+ * so we expect the line number to decrease by 1 each time. */
+ struct comment *newcomment = 0, *comment2;
+ const char *filename = comment->filename;
+ unsigned int linenum = comment->linenum;
+ for (;;) {
+ char *wp = newcomment->text;
+ comment2 = comment;
+ do {
+ unsigned int len = strlen(comment2->text);
+ if (newcomment)
+ memcpy(wp, comment2->text, len);
+ wp += len;
+ linenum--;
+ comment2 = comment2->next;
+ } while (comment2 && comment2->filename == filename
+ && comment2->linenum == linenum
+ && comment2->node == comment->node);
+ /* Finished a pass. */
+ if (newcomment) {
+ *wp = 0;
+ break;
+ }
+ newcomment = memalloc(sizeof(struct comment)
+ + wp - newcomment->text);
+ newcomment->node = comment->node;
+ newcomment->type = comment->type;
+ newcomment->filename = filename;
+ newcomment->linenum = linenum + 1;
+ }
+ /* Replace the scanned comment struct with newcomment in the
+ * list. */
+ newcomment->next = comment2;
+ *pcomment = newcomment;
+ pcomment = &newcomment->next;
+ }
+ }
+ return comments;
+}
+
+/***********************************************************************
+ * outputchildren : call output recursively on children of cnode
+ *
+ * Enter: cnode
+ * indent = indent (nesting) level of parent
+ * indesc = whether already in <description> or other top-level
+ * descriptive element
+ */
+static void
+outputchildren(struct cnode *cnode, unsigned int indent, int indesc)
+{
+ int curindesc = indesc;
+ cnode = cnode->children;
+ while (cnode) {
+ if (curindesc != cnode->funcs->indesc) {
+ assert(!indesc);
+ printf("%*s<%sdescription>\n", indent + 1, "", curindesc ? "/" : "");
+ curindesc = !curindesc;
+ }
+ (*cnode->funcs->output)(cnode, indent + 2);
+ cnode = cnode->next;
+ }
+ if (curindesc != indesc)
+ printf("%*s<%sdescription>\n", indent + 1, "", curindesc ? "/" : "");
+}
+
+/***********************************************************************
+ * default_askend : ask node if it wants to end at a para start (default
+ * implementation)
+ *
+ * Enter: cnode
+ * type = 0 else cnodefuncs for newly starting para
+ *
+ * Return: non-zero if this node wants to end
+ */
+static int
+default_askend(struct cnode *cnode, const struct cnodefuncs *type)
+{
+ return 1;
+}
+
+/***********************************************************************
+ * root_askend : ask root node if it wants to end at a para start
+ *
+ * Enter: cnode for root
+ * type = 0 else cnodefuncs for newly starting para
+ *
+ * Return: non-zero if this node wants to end
+ */
+static int
+root_askend(struct cnode *cnode, const struct cnodefuncs *type)
+{
+ return 0;
+}
+
+/***********************************************************************
+ * root_output : output root cnode
+ *
+ * Enter: cnode for root
+ * indent = indent (nesting) level
+ */
+static void
+root_output(struct cnode *cnode, unsigned int indent)
+{
+ outputchildren(cnode, indent, 0);
+}
+
+/***********************************************************************
+ * cnode type root
+ */
+static const struct cnodefuncs root_funcs = {
+ 0, /* !indesc */
+ 1, /* needpara */
+ &root_askend,
+ 0, /* end */
+ &root_output,
+};
+
+/***********************************************************************
+ * endcnode : end current cnode
+ *
+ * Enter: cnode = current cnode
+ *
+ * Return: cnode = new current code (parent of old one)
+ */
+static struct cnode *
+endcnode(struct cnode *cnode)
+{
+ if (cnode->funcs->end)
+ (*cnode->funcs->end)(cnode);
+ /* Reverse the children list. */
+ {
+ struct cnode *child = cnode->children;
+ cnode->children = 0;
+ while (child) {
+ struct cnode *next = child->next;
+ child->next = cnode->children;
+ cnode->children = child;
+ child = next;
+ }
+ }
+ return cnode->parent;
+}
+
+/***********************************************************************
+ * endspecificcnode : end a specific type of cnode
+ *
+ * Enter: cnode = current cnode
+ * type = type of node to end
+ * filename, linenum = filename and line number (for error reporting)
+ *
+ * Return: new current cnode
+ */
+static struct cnode *
+endspecificcnode(struct cnode *cnode, const struct cnodefuncs *type,
+ const char *filename, unsigned int linenum)
+{
+ while (cnode->funcs != type) {
+ if (cnode->funcs == &root_funcs)
+ locerrorexit(filename, linenum, "unmatched \\endcode");
+ cnode = endcnode(cnode);
+ }
+ return cnode;
+}
+
+/***********************************************************************
+ * startcnode : start a newly created cnode
+ *
+ * Enter: cnode = current cnode
+ * newcnode = new cnode to start
+ *
+ * Return: new current cnode (which is the same as newcnode)
+ */
+static struct cnode *
+startcnode(struct cnode *cnode, struct cnode *newcnode)
+{
+ newcnode->parent = cnode;
+ newcnode->next = cnode->children;
+ cnode->children = newcnode;
+ return newcnode;
+}
+
+/***********************************************************************
+ * para_output : output para cnode
+ *
+ * Enter: cnode for root
+ * indent = indent (nesting) level
+ */
+static void
+para_output(struct cnode *cnode, unsigned int indent)
+{
+ printf("%*s<p>\n", indent, "");
+ outputchildren(cnode, indent, 1);
+ printf("%*s</p>\n", indent, "");
+}
+
+/***********************************************************************
+ * para_end : end a para cnode
+ *
+ * Enter: cnode struct
+ */
+static void
+para_end(struct cnode *cnode)
+{
+ /* If the para cnode is empty, remove it. */
+ if (!cnode->children)
+ cnode->parent->children = cnode->next;
+}
+
+/***********************************************************************
+ * cnode type para
+ */
+static const struct cnodefuncs para_funcs = {
+ 1, /* indesc */
+ 0, /* !needpara */
+ &default_askend,
+ &para_end, /* end */
+ &para_output,
+};
+
+/***********************************************************************
+ * brief_output : output brief cnode
+ *
+ * Enter: cnode for root
+ * indent = indent (nesting) level
+ */
+static void
+brief_output(struct cnode *cnode, unsigned int indent)
+{
+ printf("%*s<brief>\n", indent, "");
+ outputchildren(cnode, indent, 1);
+ printf("%*s</brief>\n", indent, "");
+}
+
+/***********************************************************************
+ * cnode type brief
+ */
+static const struct cnodefuncs brief_funcs = {
+ 0, /* !indesc */
+ 0, /* !needpara */
+ &default_askend,
+ 0, /* end */
+ &brief_output,
+};
+
+/***********************************************************************
+ * return_output : output return cnode
+ *
+ * Enter: cnode for root
+ * indent = indent (nesting) level
+ */
+static void
+return_output(struct cnode *cnode, unsigned int indent)
+{
+ printf("%*s<description><p>\n", indent, "");
+ outputchildren(cnode, indent, 1);
+ printf("%*s</p></description>\n", indent, "");
+}
+
+/***********************************************************************
+ * cnode type return
+ */
+static const struct cnodefuncs return_funcs = {
+ 0, /* !indesc */
+ 0, /* !needpara */
+ &default_askend,
+ 0, /* end */
+ &return_output,
+};
+
+/***********************************************************************
+ * author_output : output name cnode
+ *
+ * Enter: cnode for root
+ * indent = indent (nesting) level
+ */
+static void
+name_output(struct cnode *cnode, unsigned int indent)
+{
+ printf("%*s<name>\n", indent, "");
+ outputchildren(cnode, indent, 1);
+ printf("%*s</name>\n", indent, "");
+}
+
+/***********************************************************************
+ * cnode type name
+ */
+static const struct cnodefuncs name_funcs = {
+ 0, /* !indesc */
+ 0, /* !needpara */
+ &default_askend,
+ 0, /* end */
+ &name_output,
+};
+
+/***********************************************************************
+ * author_output : output author cnode
+ *
+ * Enter: cnode for root
+ * indent = indent (nesting) level
+ */
+static void
+author_output(struct cnode *cnode, unsigned int indent)
+{
+ printf("%*s<author>\n", indent, "");
+ outputchildren(cnode, indent, 1);
+ printf("%*s</author>\n", indent, "");
+}
+
+/***********************************************************************
+ * cnode type author
+ */
+static const struct cnodefuncs author_funcs = {
+ 0, /* !indesc */
+ 0, /* !needpara */
+ &default_askend,
+ 0, /* end */
+ &author_output,
+};
+
+/***********************************************************************
+ * version_output : output version cnode
+ *
+ * Enter: cnode for root
+ * indent = indent (nesting) level
+ */
+static void
+version_output(struct cnode *cnode, unsigned int indent)
+{
+ printf("%*s<version>\n", indent, "");
+ outputchildren(cnode, indent, 1);
+ printf("%*s</version>\n", indent, "");
+}
+
+/***********************************************************************
+ * cnode type version
+ */
+static const struct cnodefuncs version_funcs = {
+ 0, /* !indesc */
+ 0, /* !needpara */
+ &default_askend,
+ 0, /* end */
+ &version_output,
+};
+
+/***********************************************************************
+ * cnode type code
+ */
+/***********************************************************************
+ * code_end : end a code cnode
+ *
+ * Enter: cnode struct
+ */
+static void
+code_end(struct cnode *cnode)
+{
+ if (incode) {
+ /* The incode flag has not been cleared, so this code cnode is
+ * being ended implicitly. We complain about that. */
+ locerrorexit(cnode->filename, cnode->linenum, "mismatched \\code");
+ }
+}
+
+/***********************************************************************
+ * code_output : output code cnode
+ *
+ * Enter: cnode for root
+ * indent = indent (nesting) level
+ */
+static void
+code_output(struct cnode *cnode, unsigned int indent)
+{
+ /* Note capitalization to differentiate it from HTML code element. */
+ if(cnode->attrtext)
+ printf("%*s<Code %s>", indent, "", cnode->attrtext);
+ else
+ printf("%*s<Code>", indent, "");
+ outputchildren(cnode, indent, 1);
+ printf("</Code>\n");
+}
+
+static const struct cnodefuncs code_funcs = {
+ 0, /* indesc */
+ 0, /* !needpara */
+ &default_askend,
+ &code_end, /* end */
+ &code_output,
+};
+
+/***********************************************************************
+ * startpara : start a new para cnode in the parse tree
+ *
+ * Enter: cnode = current cnode
+ * type = vtable for particular type of cnode
+ *
+ * Return: new current cnode
+ */
+static struct cnode *
+startpara(struct cnode *cnode, const struct cnodefuncs *type)
+{
+ struct cnode *newcnode;
+ while ((*cnode->funcs->askend)(cnode, type))
+ cnode = endcnode(cnode);
+ newcnode = memalloc(sizeof(struct cnode));
+ newcnode->funcs = type;
+ return startcnode(cnode, newcnode);
+}
+
+/***********************************************************************
+ * cnode type text
+ */
+struct textcnode {
+ struct cnode cn;
+ unsigned char *data;
+ unsigned int len;
+ unsigned int max;
+};
+
+/***********************************************************************
+ * text_end : end a text cnode
+ *
+ * Enter: cnode struct
+ */
+static void
+text_end(struct cnode *cnode)
+{
+ struct textcnode *textcnode = (void *)cnode;
+ textcnode->data[textcnode->len] = 0;
+ textcnode->max = textcnode->len + 1;
+ textcnode->data = memrealloc(textcnode->data, textcnode->max);
+}
+
+/***********************************************************************
+ * text_output : output text cnode
+ *
+ * Enter: cnode for root
+ * indent = indent (nesting) level
+ */
+static void
+text_output(struct cnode *cnode, unsigned int indent)
+{
+ /* We do not indent, in case this is inside a code cnode. */
+ struct textcnode *textcnode = (void *)cnode;
+ unsigned int len = textcnode->len;
+ unsigned const char *p = textcnode->data;
+ while (len) {
+ unsigned int thislen;
+ const char *thisptr;
+ thislen = p[0];
+ /* (void *) cast is to avoid a warning from the MS compiler.
+ * I think the warning is wrong, but I could be wrong. */
+ memcpy((void *)&thisptr, p + 1, sizeof(void *));
+ p += 1 + sizeof(void *);
+ len -= 1 + sizeof(void *);
+ printtext(thisptr, thislen, 0);
+ }
+}
+
+static const struct cnodefuncs text_funcs = {
+ 1, /* !indesc */
+ 0, /* !needpara */
+ &default_askend,
+ &text_end, /* end */
+ &text_output,
+};
+
+/***********************************************************************
+ * cnode type html (HTML element)
+ */
+struct htmlcnode {
+ struct cnode cn;
+ const struct htmleldesc *desc;
+ char attrs[1];
+};
+
+/***********************************************************************
+ * html_end : end an html cnode
+ *
+ * Enter: cnode struct
+ */
+static void
+html_end(struct cnode *cnode)
+{
+ if (((struct htmlcnode *)cnode)->desc->flags & HTMLEL_BLOCK)
+ inhtmlblock--;
+}
+
+/***********************************************************************
+ * html_output : output html cnode
+ *
+ * Enter: cnode for root
+ * indent = indent (nesting) level
+ */
+static void
+html_output(struct cnode *cnode, unsigned int indent)
+{
+ struct htmlcnode *htmlcnode = (void *)cnode;
+ if (!(htmlcnode->desc->flags & HTMLEL_INLINE))
+ printf("%*s", indent, "");
+ if (htmlcnode->cn.children) {
+ printf("<%s%s>", htmlcnode->desc->name, htmlcnode->attrs);
+ if (!(htmlcnode->desc->flags & HTMLEL_INLINE))
+ putchar('\n');
+ outputchildren(&htmlcnode->cn, indent, 1);
+ if (!(htmlcnode->desc->flags & HTMLEL_INLINE))
+ printf("%*s", indent, "");
+ printf("</%s>", htmlcnode->desc->name);
+ } else
+ printf("<%s%s/>", htmlcnode->desc->name, htmlcnode->attrs);
+ if (!(htmlcnode->desc->flags & HTMLEL_INLINE))
+ putchar('\n');
+}
+
+static const struct cnodefuncs html_funcs = {
+ 1, /* indesc */
+ 0, /* !needpara */
+ &default_askend,
+ &html_end, /* end */
+ &html_output,
+};
+
+/***********************************************************************
+ * starthtmlcnode : start a new html cnode
+ *
+ * Enter: cnode = current cnode
+ * htmleldesc = html element descriptor
+ * attrs = attributes text
+ * attrslen = length of attributes text
+ * filename
+ * linenum = line number
+ *
+ * Return: new current cnode
+ */
+static struct cnode *
+starthtmlcnode(struct cnode *cnode, const struct htmleldesc *htmleldesc,
+ const char *attrs, unsigned int attrslen,
+ const char *filename, unsigned int linenum)
+{
+ struct htmlcnode *htmlcnode;
+ /* First close enough elements to get to a content
+ * model that will accept this new element. */
+ for (;;) {
+ if (cnode->funcs != &html_funcs) {
+ /* Not in any html element. We can accept any block element
+ * (in which case we need to close the current paragraph
+ * first) or any inline element (in which case we need to
+ * close the current text cnode first). */
+ if (!(htmleldesc->flags & HTMLEL_INLINE)) {
+ if (!(htmleldesc->flags & HTMLEL_BLOCK))
+ locerrorexit(filename, linenum, "<%s> not valid here", htmleldesc->name);
+ while ((*cnode->funcs->askend)(cnode, 0))
+ cnode = endcnode(cnode);
+ } else {
+ while (cnode->funcs == &text_funcs)
+ cnode = endcnode(cnode);
+ }
+ break;
+ }
+ htmlcnode = (struct htmlcnode *)cnode;
+ if (!(htmleldesc->flags & htmlcnode->desc->content))
+ locerrorexit(filename, linenum, "<%s> not valid here", htmleldesc->name);
+ break;
+ }
+ if (htmleldesc->flags & HTMLEL_BLOCK)
+ inhtmlblock++;
+ /* Create the new html cnode. */
+ htmlcnode = memalloc(sizeof(struct htmlcnode) + attrslen);
+ htmlcnode->desc = htmleldesc;
+ htmlcnode->cn.funcs = &html_funcs;
+ htmlcnode->cn.filename = filename;
+ htmlcnode->cn.linenum = linenum;
+ memcpy(htmlcnode->attrs, attrs, attrslen);
+ htmlcnode->attrs[attrslen] = 0;
+ /* Start the html cnode. */
+ cnode = startcnode(cnode, &htmlcnode->cn);
+ return cnode;
+}
+
+/***********************************************************************
+ * param_output : output param cnode
+ *
+ * Enter: cnode for param
+ * indent = indent (nesting) level
+ *
+ * This is only used for a \param inside a \def-device-cap. A normal
+ * \param that gets attached to a function argument gets changed to
+ * a \return so it does not use this output function.
+ */
+static void
+param_output(struct cnode *cnode, unsigned int indent)
+{
+ struct paramcnode *paramcnode = (void *)cnode;
+ printf("%*s<param identifier=\"%s\">\n", indent, "", paramcnode->name);
+ outputchildren(&paramcnode->cn, indent, 1);
+ printf("%*s</param>\n", indent, "");
+}
+
+/***********************************************************************
+ * cnode type param
+ */
+static const struct cnodefuncs param_funcs = {
+ 0, /* !indesc */
+ 0, /* !needpara */
+ &default_askend,
+ 0, /* end */
+ &param_output,
+};
+
+/***********************************************************************
+ * cnode type throw
+ */
+static const struct cnodefuncs throw_funcs = {
+ 0, /* !indesc */
+ 0, /* !needpara */
+ &default_askend,
+ 0, /* end */
+ &return_output,
+};
+
+/***********************************************************************
+ * startparamcnode : start param (or throw) cnode
+ *
+ * Enter: cnode = current cnode
+ * word = name of param
+ * wordlen = length of name
+ * inout = bit 0 = in, bit 1 = out
+ * type = &param_funcs or &throw_funcs
+ *
+ * Return: new current cnode
+ */
+static struct cnode *
+startparamcnode(struct cnode *cnode, const char *word, unsigned int wordlen,
+ int inout, const struct cnodefuncs *funcs)
+{
+ struct paramcnode *paramcnode;
+ paramcnode = memalloc(sizeof(struct paramcnode) + wordlen);
+ paramcnode->cn.funcs = funcs;
+ memcpy(paramcnode->name, word, wordlen);
+ paramcnode->name[wordlen] = 0;
+ paramcnode->inout = inout;
+ return startcnode(cnode, &paramcnode->cn);
+}
+
+/***********************************************************************
+ * api_feature_output : output api-feature cnode
+ *
+ * Enter: cnode for root
+ * indent = indent (nesting) level
+ */
+static void
+api_feature_output(struct cnode *cnode, unsigned int indent)
+{
+ struct paramcnode *paramcnode = (void *)cnode;
+ printf("%*s<api-feature identifier=\"%s\">\n", indent, "", paramcnode->name);
+ outputchildren(cnode, indent, 1);
+ printf("%*s</api-feature>\n", indent, "");
+}
+
+/***********************************************************************
+ * cnode type api_feature
+ */
+static const struct cnodefuncs api_feature_funcs = {
+ 0, /* !indesc */
+ 0, /* needpara */
+ &default_askend,
+ 0, /* end */
+ &api_feature_output,
+};
+
+/***********************************************************************
+ * device_cap_output : output device-cap cnode
+ *
+ * Enter: cnode for root
+ * indent = indent (nesting) level
+ */
+static void
+device_cap_output(struct cnode *cnode, unsigned int indent)
+{
+ struct paramcnode *paramcnode = (void *)cnode;
+ printf("%*s<device-cap identifier=\"%s\">\n", indent, "", paramcnode->name);
+ outputchildren(cnode, indent, 1);
+ printf("%*s</device-cap>\n", indent, "");
+}
+
+/***********************************************************************
+ * cnode type device_cap
+ */
+static const struct cnodefuncs device_cap_funcs = {
+ 0, /* !indesc */
+ 0, /* needpara */
+ &default_askend,
+ 0, /* end */
+ &device_cap_output,
+};
+
+/***********************************************************************
+ * def_api_feature_askend : ask if def-api-feature cnode wants to end at new para
+ *
+ * Enter: cnode for def-api-feature
+ * type = cnodefuncs for new para (0 if html block element)
+ *
+ * Return: non-zero to end the def-api-feature
+ */
+static int
+def_api_feature_askend(struct cnode *cnode, const struct cnodefuncs *type)
+{
+ /* A def-api-feature does not end at a plain para, an html block element,
+ * a brief para, or a device-cap. */
+ if (!type || type == &para_funcs || type == &device_cap_funcs || type == &brief_funcs)
+ return 0;
+ return 1;
+}
+
+/***********************************************************************
+ * def_api_feature_output : output def-api-feature cnode
+ *
+ * Enter: cnode for root
+ * indent = indent (nesting) level
+ */
+static void
+def_api_feature_output(struct cnode *cnode, unsigned int indent)
+{
+ struct paramcnode *paramcnode = (void *)cnode;
+ printf("%*s<def-api-feature identifier=\"%s\">\n", indent, "", paramcnode->name);
+ printf("%*s<descriptive>\n", indent + 2, "");
+ outputchildren(cnode, indent + 2, 0);
+ printf("%*s</descriptive>\n", indent + 2, "");
+ printf("%*s</def-api-feature>\n", indent, "");
+}
+
+/***********************************************************************
+ * cnode type def_api_feature
+ */
+static const struct cnodefuncs def_api_feature_funcs = {
+ 0, /* !indesc */
+ 1, /* needpara */
+ &def_api_feature_askend,
+ 0, /* end */
+ &def_api_feature_output,
+};
+
+/***********************************************************************
+ * def_api_feature_set_askend : ask if def-api-feature-set cnode wants to end at new para
+ *
+ * Enter: cnode for def-api-feature-set
+ * type = cnodefuncs for new para (0 if html block element)
+ *
+ * Return: non-zero to end the def-api-feature-set
+ */
+static int
+def_api_feature_set_askend(struct cnode *cnode, const struct cnodefuncs *type)
+{
+ /* A def-api-feature-set does not end at a plain para, an html block element,
+ * a brief para, or an api-feature. */
+ if (!type || type == &para_funcs || type == &api_feature_funcs || type == &brief_funcs)
+ return 0;
+ return 1;
+}
+
+/***********************************************************************
+ * def_api_feature_set_output : output def-api-feature-set cnode
+ *
+ * Enter: cnode for root
+ * indent = indent (nesting) level
+ */
+static void
+def_api_feature_set_output(struct cnode *cnode, unsigned int indent)
+{
+ struct paramcnode *paramcnode = (void *)cnode;
+ printf("%*s<def-api-feature-set identifier=\"%s\">\n", indent, "", paramcnode->name);
+ printf("%*s<descriptive>\n", indent + 2, "");
+ outputchildren(cnode, indent + 2, 0);
+ printf("%*s</descriptive>\n", indent + 2, "");
+ printf("%*s</def-api-feature-set>\n", indent, "");
+}
+
+/***********************************************************************
+ * cnode type def_api_feature_set
+ */
+static const struct cnodefuncs def_api_feature_set_funcs = {
+ 0, /* !indesc */
+ 1, /* needpara */
+ &def_api_feature_set_askend,
+ 0, /* end */
+ &def_api_feature_set_output,
+};
+
+/***********************************************************************
+ * def_instantiated_askend : ask if def-instantiated cnode wants to end at new para
+ *
+ * Enter: cnode for def-instantiated
+ * type = cnodefuncs for new para (0 if html block element)
+ *
+ * Return: non-zero to end the def-instantiated
+ */
+static int
+def_instantiated_askend(struct cnode *cnode, const struct cnodefuncs *type)
+{
+ /* A def-instantiated does not end at a plain para, an html block element,
+ * a brief para, or an api-feature. */
+ if (!type || type == &para_funcs || type == &api_feature_funcs || type == &brief_funcs)
+ return 0;
+ return 1;
+}
+
+/***********************************************************************
+ * def_instantiated_output : output def-instantiated cnode
+ *
+ * Enter: cnode for root
+ * indent = indent (nesting) level
+ */
+static void
+def_instantiated_output(struct cnode *cnode, unsigned int indent)
+{
+ printf("%*s<def-instantiated>\n", indent, "");
+ printf("%*s<descriptive>\n", indent + 2, "");
+ outputchildren(cnode, indent + 2, 0);
+ printf("%*s</descriptive>\n", indent + 2, "");
+ printf("%*s</def-instantiated>\n", indent, "");
+}
+
+/***********************************************************************
+ * cnode type def_instantiated
+ */
+static const struct cnodefuncs def_instantiated_funcs = {
+ 0, /* !indesc */
+ 1, /* needpara */
+ &def_instantiated_askend,
+ 0, /* end */
+ &def_instantiated_output,
+};
+
+/***********************************************************************
+ * def_device_cap_askend : ask if def-device-cap cnode wants to end at new para
+ *
+ * Enter: cnode for def-device-cap
+ * type = cnodefuncs for new para (0 if html block element)
+ *
+ * Return: non-zero to end the def-device-cap
+ */
+static int
+def_device_cap_askend(struct cnode *cnode, const struct cnodefuncs *type)
+{
+ /* A def-device-cap does not end at a plain para, an html block element,
+ * a \brief para, or a param. */
+ if (!type || type == &para_funcs || type == &param_funcs || type == &brief_funcs)
+ return 0;
+ return 1;
+}
+
+/***********************************************************************
+ * def_device_cap_output : output def_device-cap cnode
+ *
+ * Enter: cnode for root
+ * indent = indent (nesting) level
+ */
+static void
+def_device_cap_output(struct cnode *cnode, unsigned int indent)
+{
+ struct paramcnode *paramcnode = (void *)cnode;
+ printf("%*s<def-device-cap identifier=\"%s\">\n", indent, "", paramcnode->name);
+ printf("%*s<descriptive>\n", indent + 2, "");
+ outputchildren(cnode, indent + 2, 0);
+ printf("%*s</descriptive>\n", indent + 2, "");
+ printf("%*s</def-device-cap>\n", indent, "");
+}
+
+/***********************************************************************
+ * cnode type def_device_cap
+ */
+static const struct cnodefuncs def_device_cap_funcs = {
+ 0, /* !indesc */
+ 1, /* needpara */
+ &def_device_cap_askend,
+ 0, /* end */
+ &def_device_cap_output,
+};
+
+/***********************************************************************
+ * addtext : add text to current text node, starting one if necessary
+ *
+ * Enter: cnode = current cnode
+ * text
+ * len = length of text
+ *
+ * Return: new current cnode
+ */
+static struct cnode *
+addtext(struct cnode *cnode, const char *text, unsigned int len)
+{
+ struct textcnode *textcnode;
+ if (!len)
+ return cnode;
+ if (cnode->funcs != &text_funcs) {
+ /* Start new text cnode. */
+ textcnode = memalloc(sizeof(struct textcnode));
+ textcnode->cn.funcs = &text_funcs;
+ cnode = startcnode(cnode, &textcnode->cn);
+ }
+ textcnode = (void *)cnode;
+ do {
+ unsigned char buf[1 + sizeof(void *)];
+ unsigned int thislen = len;
+ if (thislen > 255)
+ thislen = 255;
+ /* Encode a record as a single byte length followed by a pointer. */
+ buf[0] = thislen;
+ memcpy(buf + 1, &text, sizeof(void *));
+ /* Add to the text cnode's data. */
+ if (textcnode->len + sizeof(buf) >= textcnode->max) {
+ /* Need to reallocate (or allocate) data buffer. */
+ textcnode->max = textcnode->max ? 2 * textcnode->max : 1024;
+ textcnode->data = memrealloc(textcnode->data, textcnode->max);
+ }
+ memcpy(textcnode->data + textcnode->len, buf, sizeof(buf));
+ textcnode->len += sizeof(buf);
+ text += thislen;
+ len -= thislen;
+ } while (len);
+ return &textcnode->cn;
+}
+
+/***********************************************************************
+ * iswhitespace : determine if character is whitespace
+ *
+ * Enter: ch = character
+ *
+ * Return: 1 if whitespace
+ */
+static inline int
+iswhitespace(int ch)
+{
+ unsigned int i = ch - 1;
+ if (i >= 32)
+ return 0;
+ return 0x80001100 >> i & 1;
+}
+
+/***********************************************************************
+ * parseword : parse the next word, ignoring leading whitespace
+ *
+ * Enter: *pp = text pointer
+ *
+ * Return: 0 else start of word (*pp updated to just beyond end)
+ */
+static const char *
+parseword(const char **pp)
+{
+ const char *p = *pp, *word = 0;
+ int ch = *p;
+ while (iswhitespace(ch))
+ ch = *++p;
+ word = p;
+ while ((unsigned)((ch & ~0x20) - 'A') <= 'Z' - 'A'
+ || (unsigned)(ch - '0') < 10 || ch == '_' || ch == '.'
+ || ch == ':' || ch == '/' || ch == '-')
+ {
+ ch = *++p;
+ }
+ if (p == word)
+ return 0;
+ *pp = p;
+ return word;
+}
+
+/***********************************************************************
+ * Doxygen command handlers
+ *
+ * Enter: p = text just after command
+ * *pcnode = pointer to current cnode struct
+ * type = 0 else cnodefuncs pointer for type of node to start
+ * filename, linenum = current filename and line number (for error reporting)
+ *
+ * Return: p = updated if extra text was eaten
+ *
+ * On return, *pnode is updated if any node was closed or opened.
+ */
+
+/***********************************************************************
+ * Doxygen command handler : \b
+ */
+static const char *
+dox_b(const char *p, struct cnode **pcnode, const struct cnodefuncs *type,
+ const char *filename, unsigned int linenum, const char *cmdname)
+{
+ struct cnode *cnode = *pcnode;
+ const char *word = parseword(&p);
+ /* Silently ignore \b with no following word. */
+ if (word) {
+ struct cnode *mycnode;
+ mycnode = cnode = starthtmlcnode(cnode, HTMLELDESC_B, 0, 0, filename, linenum);
+ cnode = addtext(cnode, word, p - word);
+ while (cnode != mycnode)
+ cnode = endcnode(cnode);
+ cnode = endcnode(cnode);
+ }
+ *pcnode = cnode;
+ return p;
+}
+
+/***********************************************************************
+ * Doxygen command handler : \n
+ */
+static const char *
+dox_n(const char *p, struct cnode **pcnode, const struct cnodefuncs *type,
+ const char *filename, unsigned int linenum, const char *cmdname)
+{
+ struct cnode *cnode = *pcnode;
+ cnode = starthtmlcnode(cnode, HTMLELDESC_BR, 0, 0, filename, linenum);
+ cnode = endcnode(cnode);
+ *pcnode = cnode;
+ return p;
+}
+
+/***********************************************************************
+ * Doxygen command handler : \code
+ */
+static const char *
+dox_code(const char *p, struct cnode **pcnode, const struct cnodefuncs *type,
+ const char *filename, unsigned int linenum, const char *cmdname)
+{
+ *pcnode = startpara(*pcnode, &code_funcs);
+ (*pcnode)->filename = filename;
+ (*pcnode)->linenum = linenum; /* for reporting mismatched \code error */
+ incode = 1;
+ return p;
+}
+
+/***********************************************************************
+ * Doxygen command handler : \endcode
+ */
+static const char *
+dox_endcode(const char *p, struct cnode **pcnode, const struct cnodefuncs *type,
+ const char *filename, unsigned int linenum, const char *cmdname)
+{
+ incode = 0;
+ *pcnode = endspecificcnode(*pcnode, &code_funcs, filename, linenum);
+ return p;
+}
+
+/***********************************************************************
+ * Doxygen command handler : \param
+ */
+static const char *
+dox_param(const char *p, struct cnode **pcnode, const struct cnodefuncs *type,
+ const char *filename, unsigned int linenum, const char *cmdname)
+{
+ struct cnode *cnode = *pcnode;
+ unsigned int inout = 0;
+ const char *word;
+ /* Check for "in", "out" or both as attributes. */
+ if (*p == '[') {
+ for (;;) {
+ p++;
+ if (!memcmp(p, "in", 2)) {
+ inout |= 1;
+ p += 2;
+ } else if (!memcmp(p, "out", 3)) {
+ inout |= 2;
+ p += 3;
+ } else
+ break;
+ if (*p != ',')
+ break;
+ }
+ if (*p != ']')
+ locerrorexit(filename, linenum, "bad attributes on \\param");
+ p++;
+ }
+ /* Get the next word as the parameter name. */
+ word = parseword(&p);
+ if (!word)
+ locerrorexit(filename, linenum, "expected word after \\param");
+ /* Close any open nodes. */
+ while ((*cnode->funcs->askend)(cnode, type))
+ cnode = endcnode(cnode);
+ /* Create a new param cnode. */
+ cnode = startparamcnode(cnode, word, p - word, inout, type);
+ cnode->filename = filename;
+ cnode->linenum = linenum;
+ *pcnode = cnode;
+ return p;
+}
+
+/***********************************************************************
+ * Doxygen command handler : \brief, \return
+ */
+static const char *
+dox_para(const char *p, struct cnode **pcnode, const struct cnodefuncs *type,
+ const char *filename, unsigned int linenum, const char *cmdname)
+{
+ *pcnode = startpara(*pcnode, type);
+ return p;
+}
+
+/***********************************************************************
+ * Doxygen command handler : \throw
+ */
+static const char *
+dox_throw(const char *p, struct cnode **pcnode, const struct cnodefuncs *type,
+ const char *filename, unsigned int linenum, const char *cmdname)
+{
+ struct cnode *cnode = *pcnode;
+ const char *word;
+ /* Get the next word as the exception name. */
+ word = parseword(&p);
+ if (!word)
+ locerrorexit(filename, linenum, "expected word after \\throw");
+ /* Close any open nodes. */
+ while ((*cnode->funcs->askend)(cnode, type))
+ cnode = endcnode(cnode);
+ /* Create a new throw cnode. */
+ cnode = startparamcnode(cnode, word, p - word, 0, type);
+ cnode->filename = filename;
+ cnode->linenum = linenum;
+ *pcnode = cnode;
+ return p;
+}
+
+/***********************************************************************
+ * Doxygen command handler : \lang
+ */
+static const char *
+dox_attr(const char *p, struct cnode **pcnode, const struct cnodefuncs *type,
+ const char *filename, unsigned int linenum, const char *cmdname)
+{
+ struct cnode *cnode = *pcnode;
+ const char *word;
+ int len, wordlen, offset = 0;
+ char *attrtext;
+ /* Get the next word as the attribute value. */
+ word = parseword(&p);
+ if (!word)
+ locerrorexit(filename, linenum, "expected word after \\%s", cmdname);
+
+ len = strlen(cmdname) + (wordlen = p-word) + 4; /* p="word"\0 */
+ if(cnode->attrtext)
+ len += (offset = strlen(cnode->attrtext)) + 1; /* add space for space */
+ attrtext = memalloc(len);
+ if(offset) {
+ memcpy(attrtext, cnode->attrtext, offset);
+ attrtext[offset++] = ' ';
+ memfree(((void*)cnode->attrtext));
+ }
+ offset += sprintf(&attrtext[offset], "%s=\"", cmdname);
+ memcpy(&attrtext[offset], word, wordlen);
+ strcpy(&attrtext[offset + wordlen], "\"");
+ cnode->attrtext = attrtext;
+ /* skip delimiter because it won't be done otherwise */
+ if(incode && iswhitespace(*p)) ++p;
+ return p;
+}
+
+/***********************************************************************
+ * commands : table of Doxygen commands
+ */
+struct command {
+ const char *(*func)(const char *p, struct cnode **pcnode, const struct cnodefuncs *type, const char *filename, unsigned int linenum, const char *cmdname);
+ const struct cnodefuncs *type;
+ unsigned int namelen;
+ const char *name;
+};
+static const struct command commands[] = {
+ { &dox_throw, &def_api_feature_funcs, 15, "def-api-feature" },
+ { &dox_throw, &def_api_feature_set_funcs, 19, "def-api-feature-set" },
+ { &dox_para, &def_instantiated_funcs, 16, "def-instantiated" },
+ { &dox_para, &name_funcs, 4, "name" },
+ { &dox_para, &author_funcs, 6, "author" },
+ { &dox_b, 0, 1, "b" },
+ { &dox_para, &brief_funcs, 5, "brief" },
+ { &dox_code, 0, 4, "code" },
+ { &dox_throw, &def_device_cap_funcs, 14, "def-device-cap" },
+ { &dox_attr, 0, 4, "lang" },
+ { &dox_endcode, 0, 7, "endcode" },
+ { &dox_n, 0, 1, "n" },
+ { &dox_param, &param_funcs, 5, "param" },
+ { &dox_para, &return_funcs, 6, "return" },
+ { &dox_throw, &throw_funcs, 5, "throw" },
+ { &dox_throw, &api_feature_funcs, 11, "api-feature" },
+ { &dox_throw, &device_cap_funcs, 10, "device-cap" },
+ { &dox_para, &version_funcs, 7, "version" },
+ { 0, 0, 0 }
+};
+
+/***********************************************************************
+ * parsehtmltag : parse html tag
+ *
+ * Enter: start = start of tag, the '<' char
+ * *pcnode = current cnode
+ * filename = filename
+ * *plinenum = current line number
+ *
+ * Return: just after the tag
+ * *pcnode and *plinenum updated if applicable
+ */
+static const char *
+parsehtmltag(const char *start, struct cnode **pcnode,
+ const char *filename, unsigned int *plinenum)
+{
+ struct cnode *cnode = *pcnode;
+ const char *end = start + 1, *endname = 0, *name = end;
+ int ch = *end;
+ int quote = 0;
+ int close = 0;
+ unsigned int linenum = *plinenum;
+ const struct htmleldesc *htmleldesc;
+ if (ch == '/') {
+ close = 1;
+ ch = *++end;
+ name = end;
+ }
+ /* Find the end of the tag. */
+ for (;;) {
+ if (!ch)
+ locerrorexit(filename, *plinenum, "unterminated HTML tag");
+ if (ch == '\n')
+ linenum++;
+ else if (iswhitespace(ch) || ch == '/') {
+ if (!endname)
+ endname = end;
+ } else if (!quote) {
+ if (ch == '"' || ch == '\'')
+ quote = ch;
+ else if (ch == '>')
+ break;
+ } else {
+ if (ch == quote)
+ quote = 0;
+ }
+ ch = *++end;
+ }
+ if (!endname)
+ endname = end;
+ end++;
+ /* See if it's an xml open-close tag. */
+ if (!close && endname != name && end[-2] == '/')
+ close = 2;
+ /* Find the tag from our list. */
+ htmleldesc = htmleldescs;
+ for (;;) {
+ if (!htmleldesc->namelen) {
+ locerrorexit(filename, *plinenum, "unrecognized HTML tag %.*s",
+ end - start, start);
+ }
+ if (htmleldesc->namelen == endname - name
+ && !strncasecmp(htmleldesc->name, name, endname - name))
+ {
+ break;
+ }
+ htmleldesc++;
+ }
+ if (close == 1) {
+ /* Closing tag. Find open element to close. */
+ for (;;) {
+ struct htmlcnode *htmlcnode;
+ if (cnode->funcs != &text_funcs) {
+ if (cnode->funcs != &html_funcs) {
+ locerrorexit(filename, *plinenum, "mismatched %.*s",
+ end - start, start);
+ }
+ htmlcnode = (struct htmlcnode *)cnode;
+ if (htmlcnode->desc == htmleldesc)
+ break;
+ if (!(htmlcnode->desc->flags & HTMLEL_AUTOCLOSE)) {
+ locerrorexit(filename, htmlcnode->cn.linenum,
+ "mismatched <%.*s>",
+ htmlcnode->desc->namelen, htmlcnode->desc->name);
+ }
+ }
+ cnode = endcnode(cnode);
+ }
+ cnode = endcnode(cnode);
+ } else {
+ /* Opening tag. */
+ if (close !=2)
+ cnode = starthtmlcnode(cnode, htmleldesc, endname, end - 1 - endname, filename, *plinenum);
+ else // don't include the closing "/" in the attributes list
+ cnode = starthtmlcnode(cnode, htmleldesc, endname, end - 2 - endname, filename, *plinenum);
+ if (close == 2 || (htmleldesc->content & HTMLEL_EMPTY)) {
+ /* Empty element -- close it again. */
+ cnode = endcnode(cnode);
+ }
+ }
+ *pcnode = cnode;
+ *plinenum = linenum;
+ return end;
+}
+
+/***********************************************************************
+ * parsecomment : parse one comment
+ *
+ * Enter: comment struct
+ */
+static void
+parsecomment(struct comment *comment)
+{
+ struct cnode *cnode = &comment->root;
+ const char *p = comment->text + comment->back;
+ unsigned int linenum = comment->linenum - 1;
+ int ch;
+ curcomment = comment;
+ incode = 0;
+ inhtmlblock = 0;
+ cnode->funcs = &root_funcs;
+ for (;;) {
+ /* Start of new line. */
+ const char *starttext;
+ ch = *p;
+ linenum++;
+ {
+ /* Find first non-whitespace character. */
+ const char *p2 = p;
+ int ch2 = ch;
+ while (iswhitespace(ch2))
+ ch2 = *++p2;
+ if (comment->type == TOK_BLOCKCOMMENT && ch2 == '*') {
+ /* Ignore initial * in block comment (even in \code block). */
+ ch2 = *++p2;
+ ch = ch2;
+ p = p2;
+ if (ch == '*')
+ goto checkforlineofstars;
+ while (iswhitespace(ch2))
+ ch2 = *++p2;
+ }
+ if (comment->type == TOK_INLINECOMMENT && ch2 == '/') {
+checkforlineofstars:
+ if (!incode) {
+ /* Ignore whole line of * for block comment or / for inline
+ * comment if that is the only thing on the line. */
+ const char *p3 = p2;
+ int ch3;
+ do ch3 = *++p3; while (ch3 == ch2);
+ while (iswhitespace(ch3)) ch3 = *++p3;
+ if (!ch3 || ch3 == '\n') {
+ /* Reached end of line (or whole comment) -- treat as
+ * empty line. */
+ ch2 = ch3;
+ p2 = p3;
+ }
+ }
+ }
+ if (!incode) {
+ /* Only allow whitespace omission above to take effect if
+ * not in \code block. */
+ ch = ch2;
+ p = p2;
+ }
+ }
+ if (!ch) {
+ /* End of comments -- finish. */
+ break;
+ }
+ if (!incode && !inhtmlblock && ch == '\n') {
+ /* Blank line -- finish any para, but only if not in code and
+ * not in any HTML block element. */
+ while ((*cnode->funcs->askend)(cnode, 0))
+ cnode = endcnode(cnode);
+ p++;
+ continue;
+ }
+ /* Start new para if there isn't already one going. */
+ if (cnode->funcs->needpara)
+ cnode = startpara(cnode, &para_funcs);
+ /* Process text on the line. */
+ starttext = p;
+ while (ch && ch != '\n') {
+ if (ch != '\\' && ch != '<' /* && ch != '@' */ && ch != '$'
+ && ch != '&' && ch != '\r')
+ {
+ ch = *++p;
+ continue;
+ }
+ /* Output any pending text. */
+ if (p - starttext)
+ cnode = addtext(cnode, starttext, p - starttext);
+ /* Ignore \r in DOS line returns */
+ if (ch == '\r') {
+ ch = *++p;
+ starttext = p;
+ continue;
+ }
+ if (ch == '$')
+ locerrorexit(comment->filename, linenum, "use \\$ instead of $");
+ /* See if it is an html named entity. */
+ if (ch == '&' && p[1] != '#') {
+ const char *entity = ENTITIES;
+ /* This search could be faster if the entity names were put
+ * in a hash table or something. */
+ const char *semicolon = strchr(p, ';');
+ unsigned int len;
+ if (!semicolon)
+ locerrorexit(comment->filename, linenum, "unterminated HTML entity");
+ p++;
+ for (;;) {
+ len = strlen(entity);
+ if (!len)
+ locerrorexit(comment->filename, linenum, "unrecognised HTML entity &%.*s;", semicolon - p, p);
+ if (len == semicolon - p && !memcmp(p, entity, len))
+ break;
+ entity += len + 1;
+ entity += strlen(entity) + 1;
+ }
+ entity += len + 1;
+ cnode = addtext(cnode, entity, strlen(entity));
+ p = semicolon + 1;
+ ch = *p;
+ starttext = p;
+ continue;
+ }
+ /* See if it is a backslash escape sequence. */
+ else if (ch == '\\') {
+ const char *match = "\\@&$#<>%";
+ const char *pos;
+ ch = p[1];
+ pos = strchr(match, ch);
+ if (pos) {
+ /* Got a \ escape sequence. */
+ const char *text =
+ "\\\0 @\0 &amp;\0$\0 #\0 &lt;\0 >\0 %"
+ + 6 * (pos - match);
+ cnode = addtext(cnode, text, strlen(text));
+ p += 2;
+ ch = *p;
+ starttext = p;
+ continue;
+ }
+ } else if (ch == '<') {
+ if (incode) {
+ ch = *++p;
+ starttext = p;
+ continue;
+ }
+ /* It's an html tag. */
+ p = parsehtmltag(p, &cnode, comment->filename, &linenum);
+ ch = *p;
+ starttext = p;
+ continue;
+ }
+ {
+ /* Got a doxygen command. First work out its length. */
+ const char *start = ++p;
+ unsigned int cmdlen;
+ const struct command *command;
+ ch = *p;
+ while ((unsigned)((ch & ~0x20) - 'A') <= 'Z' - 'A'
+ || (unsigned)(ch - '0') < 10 || ch == '_' || ch == '-')
+ {
+ ch = *++p;
+ }
+ cmdlen = p - start;
+ if (!cmdlen)
+ locerrorexit(comment->filename, linenum, "\\ or @ without Doxygen command");
+ /* Look it up in the table. */
+ command = commands;
+ for (;;) {
+ if (!command->namelen) {
+ locerrorexit(comment->filename, linenum, "unrecognized Doxygen command '%.*s'",
+ cmdlen + 1, start - 1);
+ }
+ if (command->namelen == cmdlen
+ && !memcmp(command->name, start, cmdlen))
+ {
+ break;
+ }
+ command++;
+ }
+ p = (*command->func)(p, &cnode, command->type,
+ comment->filename, linenum, command->name);
+ ch = *p;
+ starttext = p;
+ }
+ }
+ if (p - starttext) {
+ /* Start new para if there isn't already one going. */
+ if (cnode->funcs->needpara)
+ cnode = startpara(cnode, &para_funcs);
+ cnode = addtext(cnode, starttext, p - starttext);
+ }
+ if (!ch)
+ break;
+ if (cnode->funcs == &text_funcs)
+ addtext(cnode, "\n", 1);
+ p++;
+ }
+ /* Finish the root cnode. */
+ do
+ cnode = endcnode(cnode);
+ while (cnode);
+ assert(!incode);
+ assert(!inhtmlblock);
+}
+
+/***********************************************************************
+ * parsecomments : parse comments
+ *
+ * Enter: comment = first comment in list
+ */
+static void
+parsecomments(struct comment *comment)
+{
+ while (comment) {
+ parsecomment(comment);
+ comment = comment->next;
+ }
+}
+
+/***********************************************************************
+ * attachcommenttonode : attach comment struct to node
+ *
+ * Enter: node = parse node for identifier
+ * comment = comment struct
+ */
+static void
+attachcommenttonode(struct node *node, struct comment *comment)
+{
+ comment->next = node->comments;
+ node->comments = comment;
+}
+
+/***********************************************************************
+ * attachcomments : attach comments to applicable parse nodes
+ *
+ * Enter: comment = first in (reversed) list of comment structs
+ * root = root parse node (for attaching \file comment blocks to)
+ */
+static void
+attachcomments(struct comment *comment, struct node *root)
+{
+ while (comment) {
+ struct comment *next = comment->next;
+ /* See if there are any \param, \return, \throw, \def-api-feature or
+ * \def-device-cap cnodes to detach and attach
+ * elsewhere. (This only looks at top-level nodes, direct children
+ * of the root, so does not detach a \param inside a
+ * \def-device-cap.) */
+ struct cnode **pcnode = &comment->root.children;
+ for (;;) {
+ struct cnode *cnode = *pcnode;
+ if (!cnode)
+ break;
+ if (cnode->funcs == &param_funcs || cnode->funcs == &return_funcs
+ || cnode->funcs == &throw_funcs)
+ {
+ /* Found a \param or \return or \throw to detach. Find the
+ * parameter/exception of the same name, or the return type. */
+ struct node *node;
+ struct comment *newcomment;
+ if (cnode->funcs == &param_funcs) {
+ node = findparamidentifier(comment->node,
+ ((struct paramcnode *)cnode)->name);
+ if (!node)
+ locerrorexit(comment->filename, cnode->linenum, "no parameter '%s' found", ((struct paramcnode *)cnode)->name);
+ } else if (cnode->funcs == &return_funcs) {
+ node = findreturntype(comment->node);
+ if (!node)
+ locerrorexit(comment->filename, cnode->linenum, "no return type found");
+ } else {
+ node = findthrowidentifier(comment->node,
+ ((struct paramcnode *)cnode)->name);
+ if (!node)
+ locerrorexit(comment->filename, cnode->linenum, "no exception '%s' found", ((struct paramcnode *)cnode)->name);
+ }
+ /* Detach the cnode from its old comment. */
+ *pcnode = cnode->next;
+ /* Create a new comment struct to contain this cnode. */
+ newcomment = memalloc(sizeof(struct comment));
+ newcomment->root.funcs = &root_funcs;
+ newcomment->linenum = cnode->linenum;
+ /* Attach the cnode. */
+ newcomment->root.children = cnode;
+ cnode->parent = &newcomment->root;
+ cnode->next = 0;
+ /* Make the cnode a \return one, just so even a \param
+ * uses return_output. */
+ cnode->funcs = &return_funcs;
+ /* Attach the new comment struct to the parse node. */
+ attachcommenttonode(node, newcomment);
+ } else {
+ pcnode = &cnode->next;
+ }
+ }
+ /* Now attach the comment to its identifier parse node. */
+ {
+ struct node *node = comment->node;
+ if (!node)
+ node = root;
+ attachcommenttonode(node, comment);
+ }
+ comment = next;
+ }
+}
+
+/***********************************************************************
+ * processcomments : join, parse and attach comments
+ *
+ * Enter: root = root parse node
+ */
+void
+processcomments(struct node *root)
+{
+ comments = joininlinecomments(comments);
+ parsecomments(comments);
+ attachcomments(comments, root);
+}
+
+/***********************************************************************
+ * outputdescriptive : output descriptive elements for a node
+ *
+ * Enter: node = identifier node that might have some comments
+ * indent = indent (nesting) level
+ */
+void
+outputdescriptive(struct node *node, unsigned int indent)
+{
+ struct comment *comment = node->comments;
+ int indescriptive = 0;
+ while (comment) {
+ struct cnode *root = &comment->root;
+ if (!indescriptive)
+ printf("%*s<descriptive>\n", indent, "");
+ indescriptive = 1;
+ (*root->funcs->output)(root, indent + 2);
+ comment = comment->next;
+ }
+ if (indescriptive)
+ printf("%*s</descriptive>\n", indent, "");
+}
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/comment.h b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/comment.h
new file mode 100644
index 00000000000..96d18e2cc8a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/comment.h
@@ -0,0 +1,25 @@
+/***********************************************************************
+ * $Id$
+ * Copyright 2009 Aplix Corporation. All rights reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ***********************************************************************/
+#ifndef comment_h
+#define comment_h
+
+struct tok;
+struct node;
+
+void addcomment(struct tok *tok);
+void setcommentnode(struct node *node2);
+void processcomments(struct node *root);
+void outputdescriptive(struct node *node, unsigned int indent);
+
+#endif /* ndef comment_h */
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/entities.h b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/entities.h
new file mode 100644
index 00000000000..ff74c1cb3b2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/entities.h
@@ -0,0 +1,271 @@
+/***********************************************************************
+ * $Id$
+ * Copyright 2009 Aplix Corporation. All rights reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ***********************************************************************/
+#ifndef entities_h
+#define entities_h
+
+#define ENTITIES \
+"nbsp\0&#160;\0" \
+"iexcl\0&#161;\0" \
+"cent\0&#162;\0" \
+"pound\0&#163;\0" \
+"curren\0&#164;\0" \
+"yen\0&#165;\0" \
+"brvbar\0&#166;\0" \
+"sect\0&#167;\0" \
+"uml\0&#168;\0" \
+"copy\0&#169;\0" \
+"ordf\0&#170;\0" \
+"laquo\0&#171;\0" \
+"not\0&#172;\0" \
+"shy\0&#173;\0" \
+"reg\0&#174;\0" \
+"macr\0&#175;\0" \
+"deg\0&#176;\0" \
+"plusmn\0&#177;\0" \
+"sup2\0&#178;\0" \
+"sup3\0&#179;\0" \
+"acute\0&#180;\0" \
+"micro\0&#181;\0" \
+"para\0&#182;\0" \
+"middot\0&#183;\0" \
+"cedil\0&#184;\0" \
+"sup1\0&#185;\0" \
+"ordm\0&#186;\0" \
+"raquo\0&#187;\0" \
+"frac14\0&#188;\0" \
+"frac12\0&#189;\0" \
+"frac34\0&#190;\0" \
+"iquest\0&#191;\0" \
+"Agrave\0&#192;\0" \
+"Aacute\0&#193;\0" \
+"Acirc\0&#194;\0" \
+"Atilde\0&#195;\0" \
+"Auml\0&#196;\0" \
+"Aring\0&#197;\0" \
+"AElig\0&#198;\0" \
+"Ccedil\0&#199;\0" \
+"Egrave\0&#200;\0" \
+"Eacute\0&#201;\0" \
+"Ecirc\0&#202;\0" \
+"Euml\0&#203;\0" \
+"Igrave\0&#204;\0" \
+"Iacute\0&#205;\0" \
+"Icirc\0&#206;\0" \
+"Iuml\0&#207;\0" \
+"ETH\0&#208;\0" \
+"Ntilde\0&#209;\0" \
+"Ograve\0&#210;\0" \
+"Oacute\0&#211;\0" \
+"Ocirc\0&#212;\0" \
+"Otilde\0&#213;\0" \
+"Ouml\0&#214;\0" \
+"times\0&#215;\0" \
+"Oslash\0&#216;\0" \
+"Ugrave\0&#217;\0" \
+"Uacute\0&#218;\0" \
+"Ucirc\0&#219;\0" \
+"Uuml\0&#220;\0" \
+"Yacute\0&#221;\0" \
+"THORN\0&#222;\0" \
+"szlig\0&#223;\0" \
+"agrave\0&#224;\0" \
+"aacute\0&#225;\0" \
+"acirc\0&#226;\0" \
+"atilde\0&#227;\0" \
+"auml\0&#228;\0" \
+"aring\0&#229;\0" \
+"aelig\0&#230;\0" \
+"ccedil\0&#231;\0" \
+"egrave\0&#232;\0" \
+"eacute\0&#233;\0" \
+"ecirc\0&#234;\0" \
+"euml\0&#235;\0" \
+"igrave\0&#236;\0" \
+"iacute\0&#237;\0" \
+"icirc\0&#238;\0" \
+"iuml\0&#239;\0" \
+"eth\0&#240;\0" \
+"ntilde\0&#241;\0" \
+"ograve\0&#242;\0" \
+"oacute\0&#243;\0" \
+"ocirc\0&#244;\0" \
+"otilde\0&#245;\0" \
+"ouml\0&#246;\0" \
+"divide\0&#247;\0" \
+"oslash\0&#248;\0" \
+"ugrave\0&#249;\0" \
+"uacute\0&#250;\0" \
+"ucirc\0&#251;\0" \
+"uuml\0&#252;\0" \
+"yacute\0&#253;\0" \
+"thorn\0&#254;\0" \
+"yuml\0&#255;\0" \
+"fnof\0&#402;\0" \
+"Alpha\0&#913;\0" \
+"Beta\0&#914;\0" \
+"Gamma\0&#915;\0" \
+"Delta\0&#916;\0" \
+"Epsilon\0&#917;\0" \
+"Zeta\0&#918;\0" \
+"Eta\0&#919;\0" \
+"Theta\0&#920;\0" \
+"Iota\0&#921;\0" \
+"Kappa\0&#922;\0" \
+"Lambda\0&#923;\0" \
+"Mu\0&#924;\0" \
+"Nu\0&#925;\0" \
+"Xi\0&#926;\0" \
+"Omicron\0&#927;\0" \
+"Pi\0&#928;\0" \
+"Rho\0&#929;\0" \
+"Sigma\0&#931;\0" \
+"Tau\0&#932;\0" \
+"Upsilon\0&#933;\0" \
+"Phi\0&#934;\0" \
+"Chi\0&#935;\0" \
+"Psi\0&#936;\0" \
+"Omega\0&#937;\0" \
+"alpha\0&#945;\0" \
+"beta\0&#946;\0" \
+"gamma\0&#947;\0" \
+"delta\0&#948;\0" \
+"epsilon\0&#949;\0" \
+"zeta\0&#950;\0" \
+"eta\0&#951;\0" \
+"theta\0&#952;\0" \
+"iota\0&#953;\0" \
+"kappa\0&#954;\0" \
+"lambda\0&#955;\0" \
+"mu\0&#956;\0" \
+"nu\0&#957;\0" \
+"xi\0&#958;\0" \
+"omicron\0&#959;\0" \
+"pi\0&#960;\0" \
+"rho\0&#961;\0" \
+"sigmaf\0&#962;\0" \
+"sigma\0&#963;\0" \
+"tau\0&#964;\0" \
+"upsilon\0&#965;\0" \
+"phi\0&#966;\0" \
+"chi\0&#967;\0" \
+"psi\0&#968;\0" \
+"omega\0&#969;\0" \
+"thetasym\0&#977;\0" \
+"upsih\0&#978;\0" \
+"piv\0&#982;\0" \
+"bull\0&#8226;\0" \
+"hellip\0&#8230;\0" \
+"prime\0&#8242;\0" \
+"Prime\0&#8243;\0" \
+"oline\0&#8254;\0" \
+"frasl\0&#8260;\0" \
+"weierp\0&#8472;\0" \
+"image\0&#8465;\0" \
+"real\0&#8476;\0" \
+"trade\0&#8482;\0" \
+"alefsym\0&#8501;\0" \
+"larr\0&#8592;\0" \
+"uarr\0&#8593;\0" \
+"rarr\0&#8594;\0" \
+"darr\0&#8595;\0" \
+"harr\0&#8596;\0" \
+"crarr\0&#8629;\0" \
+"lArr\0&#8656;\0" \
+"uArr\0&#8657;\0" \
+"rArr\0&#8658;\0" \
+"dArr\0&#8659;\0" \
+"hArr\0&#8660;\0" \
+"forall\0&#8704;\0" \
+"part\0&#8706;\0" \
+"exist\0&#8707;\0" \
+"empty\0&#8709;\0" \
+"nabla\0&#8711;\0" \
+"isin\0&#8712;\0" \
+"notin\0&#8713;\0" \
+"ni\0&#8715;\0" \
+"prod\0&#8719;\0" \
+"sum\0&#8721;\0" \
+"minus\0&#8722;\0" \
+"lowast\0&#8727;\0" \
+"radic\0&#8730;\0" \
+"prop\0&#8733;\0" \
+"infin\0&#8734;\0" \
+"ang\0&#8736;\0" \
+"and\0&#8743;\0" \
+"or\0&#8744;\0" \
+"cap\0&#8745;\0" \
+"cup\0&#8746;\0" \
+"int\0&#8747;\0" \
+"there4\0&#8756;\0" \
+"sim\0&#8764;\0" \
+"cong\0&#8773;\0" \
+"asymp\0&#8776;\0" \
+"ne\0&#8800;\0" \
+"equiv\0&#8801;\0" \
+"le\0&#8804;\0" \
+"ge\0&#8805;\0" \
+"sub\0&#8834;\0" \
+"sup\0&#8835;\0" \
+"nsub\0&#8836;\0" \
+"sube\0&#8838;\0" \
+"supe\0&#8839;\0" \
+"oplus\0&#8853;\0" \
+"otimes\0&#8855;\0" \
+"perp\0&#8869;\0" \
+"sdot\0&#8901;\0" \
+"lceil\0&#8968;\0" \
+"rceil\0&#8969;\0" \
+"lfloor\0&#8970;\0" \
+"rfloor\0&#8971;\0" \
+"lang\0&#9001;\0" \
+"rang\0&#9002;\0" \
+"loz\0&#9674;\0" \
+"spades\0&#9824;\0" \
+"clubs\0&#9827;\0" \
+"hearts\0&#9829;\0" \
+"diams\0&#9830;\0" \
+"quot\0&#34;\0" \
+"amp\0&#38;\0" \
+"lt\0&#60;\0" \
+"gt\0&#62;\0" \
+"OElig\0&#338;\0" \
+"oelig\0&#339;\0" \
+"Scaron\0&#352;\0" \
+"scaron\0&#353;\0" \
+"Yuml\0&#376;\0" \
+"circ\0&#710;\0" \
+"tilde\0&#732;\0" \
+"ensp\0&#8194;\0" \
+"emsp\0&#8195;\0" \
+"thinsp\0&#8201;\0" \
+"zwnj\0&#8204;\0" \
+"zwj\0&#8205;\0" \
+"lrm\0&#8206;\0" \
+"rlm\0&#8207;\0" \
+"ndash\0&#8211;\0" \
+"mdash\0&#8212;\0" \
+"lsquo\0&#8216;\0" \
+"rsquo\0&#8217;\0" \
+"sbquo\0&#8218;\0" \
+"ldquo\0&#8220;\0" \
+"rdquo\0&#8221;\0" \
+"bdquo\0&#8222;\0" \
+"dagger\0&#8224;\0" \
+"Dagger\0&#8225;\0" \
+"permil\0&#8240;\0" \
+"lsaquo\0&#8249;\0" \
+"rsaquo\0&#8250;\0" \
+"euro\0&#8364;\0"
+
+#endif /* ndef entities_h */
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/lex.c b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/lex.c
new file mode 100644
index 00000000000..9f9103386bd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/lex.c
@@ -0,0 +1,560 @@
+/***********************************************************************
+ * $Id$
+ * Copyright 2009 Aplix Corporation. All rights reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ***********************************************************************/
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include "lex.h"
+#include "misc.h"
+#include "node.h"
+#include "process.h"
+
+struct file {
+ struct file *next;
+ const char *filename;
+ char *buf;
+ const char *pos, *end;
+ unsigned int linenum;
+};
+
+const char keywords[] = KEYWORDS;
+
+static struct file *file, *firstfile;
+static struct tok tok;
+
+/***********************************************************************
+ * readinput : read all input files into memory
+ *
+ * Enter: argv = 0-terminated array of filenames
+ */
+void
+readinput(const char *const *argv)
+{
+ struct file **pfile = &file;
+ for (;;) {
+ struct file *file;
+ const char *filename = *argv++;
+ char *buf = 0;
+ int len = 0, thislen, isstdin;
+ FILE *handle;
+ if (!filename)
+ break;
+ /* Read the file. */
+ isstdin = !strcmp(filename, "-");
+ if (isstdin) {
+ handle = stdin;
+ filename = "<stdin>";
+ } else {
+ handle = fopen(filename, "rb");
+ if (!handle)
+ errorexit("%s: %s", filename, strerror(errno));
+ }
+ for (;;) {
+ thislen = len ? len * 2 : 4096;
+ buf = memrealloc(buf, len + thislen + 1);
+ thislen = fread(buf + len, 1, thislen, handle);
+ if (!thislen)
+ break;
+ len += thislen;
+ }
+ if (ferror(handle))
+ errorexit("%s: I/O error", filename);
+ if (!isstdin)
+ fclose(handle);
+ buf[len] = 0;
+ buf = memrealloc(buf, len + 1);
+ /* Create the file struct for it. */
+ file = memalloc(sizeof(struct file));
+ *pfile = file;
+ pfile = &file->next;
+ file->filename = filename;
+ file->pos = file->buf = buf;
+ file->end = buf + len;
+ file->linenum = 1;
+ }
+ *pfile = 0;
+ firstfile = file;
+}
+
+/***********************************************************************
+ * lexerrorexit : error and exit with line number
+ */
+static void
+lexerrorexit(const char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ vlocerrorexit(file->filename, file->linenum, format, ap);
+ va_end(ap);
+}
+
+/***********************************************************************
+ * lexblockcomment : lex a block comment
+ *
+ * Enter: start = start of comment
+ *
+ * Return: tok struct, lifetime until next call to lex
+ */
+static struct tok *
+lexblockcomment(const char *start)
+{
+ const char *p = start + 1;
+ tok.filename = file->filename;
+ tok.linenum = file->linenum;
+ for (;;) {
+ int ch = *++p;
+ if (!ch)
+ lexerrorexit("unterminated block comment");
+ if (ch != '*') {
+ if (ch == '\n')
+ file->linenum++;
+ continue;
+ }
+ ch = p[1];
+ if (!ch)
+ lexerrorexit("unterminated block comment");
+ if (ch == '/')
+ break;
+ }
+ p += 2;
+ file->pos = p;
+ tok.type = TOK_BLOCKCOMMENT;
+ tok.start = start + 2;
+ tok.len = p - start - 4;
+ return &tok;
+}
+
+/***********************************************************************
+ * lexinlinecomment : lex an inline comment
+ *
+ * Enter: start = start of comment, starts with "//"
+ *
+ * Return: tok struct, lifetime until next call to lex
+ */
+static struct tok *
+lexinlinecomment(const char *start)
+{
+ const char *p = start + 2;
+ p = start + 1;
+ for (;;) {
+ int ch = *++p;
+ if (!ch || ch == '\n')
+ break;
+ }
+ p++;
+ file->pos = p;
+ tok.type = TOK_INLINECOMMENT;
+ tok.start = start + 2;
+ tok.len = p - start - 2;
+ tok.filename = file->filename;
+ tok.linenum = file->linenum++;
+ return &tok;
+}
+
+/***********************************************************************
+ * lexnumber : lex a number (or just a '-' symbol)
+ *
+ * Enter: start = start of token
+ *
+ * Return: tok struct, lifetime until next call to lex
+ *
+ * The IDL grammar seems to say that a float can't start with a
+ * decimal point, so that's what we have implemented here.
+ */
+static struct tok *
+lexnumber(const char *start)
+{
+ for (;;) {
+ const char *p = start;
+ const char *octalend = start;
+ int ch = *p;
+ enum { STATE_START, STATE_INT, STATE_HEX, STATE_OCTAL, STATE_BADOCTAL,
+ STATE_DP, STATE_EXPSTART, STATE_EXPSIGN, STATE_EXP
+ } state = STATE_START;
+ if (ch == '-') {
+ ch = *++p;
+ if (ch == 'I') { // starts of Infinity
+ char * infinity = "-Infinity";
+ unsigned int len = strlen(infinity);
+ if (!memcmp(start, infinity, len)) {
+ tok.type = TOK_minusinfinity;
+ tok.start = start;
+ tok.len = len;
+ tok.filename = file->filename;
+ tok.linenum = file->linenum;
+ file->pos = start + len;
+ return &tok;
+ }
+ }
+ }
+ if (ch == '0') {
+ state = STATE_OCTAL;
+ ch = *++p;
+ if ((ch & ~0x20) == 'X') {
+ state = STATE_HEX;
+ ch = *++p;
+ }
+ }
+
+ for (;;) {
+ if ((unsigned)(ch - '0') >= 8) {
+ if ((ch & -2) == '8') {
+ if (state == STATE_OCTAL) {
+ state = STATE_BADOCTAL;
+ octalend = p;
+ }
+ } else if ((unsigned)((ch & ~0x20) - 'A') <= 'F' - 'A') {
+ if (state != STATE_HEX) {
+ if ((ch & ~0x20) != 'E')
+ break;
+ if (state == STATE_HEX || state >= STATE_EXPSTART || state == STATE_START)
+ break;
+ state = STATE_EXPSTART;
+ }
+ } else if (ch == '.') {
+ if (state == STATE_HEX || state >= STATE_DP)
+ break;
+ state = STATE_DP;
+ } else if (ch == '-') {
+ if (state != STATE_EXPSTART)
+ break;
+ state = STATE_EXPSIGN;
+ } else
+ break;
+ }
+ ch = *++p;
+ if (state == STATE_START)
+ state = STATE_INT;
+ else if (state == STATE_EXPSTART || state == STATE_EXPSIGN)
+ state = STATE_EXP;
+ }
+ switch (state) {
+ case STATE_START:
+ /* Must have just been a - character by itself. */
+ tok.type = '-';
+ p = start + 1;
+ break;
+ case STATE_BADOCTAL:
+ p = octalend;
+ /* fall through... */
+ case STATE_INT:
+ case STATE_OCTAL:
+ tok.type = TOK_INTEGER;
+ break;
+ case STATE_HEX:
+ if (p - start == 2 || (p - start == 3 && *start == '-'))
+ p = start + 1;
+ tok.type = TOK_INTEGER;
+ break;
+ case STATE_EXP:
+ case STATE_DP:
+ tok.type = TOK_FLOAT;
+ break;
+ case STATE_EXPSIGN:
+ p--;
+ /* fall through... */
+ case STATE_EXPSTART:
+ p--;
+ tok.type = TOK_FLOAT;
+ break;
+ }
+ tok.start = start;
+ tok.len = p - start;
+ tok.filename = file->filename;
+ tok.linenum = file->linenum;
+ file->pos = p;
+ return &tok;
+ }
+}
+
+/***********************************************************************
+ * lexstring : lex a quoted string
+ *
+ * Enter: start = start of token
+ *
+ * Return: tok struct, lifetime until next call to lex
+ */
+static struct tok *
+lexstring(const char *start)
+{
+ for (;;) {
+ const char *p = start + 1;
+ int ch = *p;
+ for (;;) {
+ if (!ch || ch == '\n')
+ lexerrorexit("unterminated string");
+ if (ch == '"') {
+ tok.type = TOK_STRING;
+ tok.start = start + 1;
+ tok.len = p - start - 1;
+ tok.filename = file->filename;
+ tok.linenum = file->linenum;
+ file->pos = p + 1;
+ return &tok;
+ }
+ /* Note the IDL spec doesn't seem to allow for escape sequences
+ * in strings. */
+ ch = *++p;
+ }
+ }
+}
+
+/***********************************************************************
+ * lexidentifier : lex an identifier
+ *
+ * Enter: start = start of token
+ *
+ * Return: tok struct, lifetime until next call to lex
+ */
+static struct tok *
+lexidentifier(const char *start)
+{
+ const char *p = start + 1;
+ for (;;) {
+ int ch = *p;
+ if (ch != '_' && (unsigned)(ch - '0') >= 10
+ && (unsigned)((ch & ~0x20) - 'A') > 'Z' - 'A')
+ {
+ break;
+ }
+ p++;
+ }
+ tok.type = TOK_IDENTIFIER;
+ tok.start = start;
+ tok.len = p - start;
+ tok.filename = file->filename;
+ tok.linenum = file->linenum;
+ file->pos = p;
+ /* See if this is a keyword. (This search is a bit n-squared.) */
+ {
+ unsigned int type = TOK_DOMString;
+ p = keywords;
+ for (;;) {
+ unsigned int len = strlen(p);
+ if (!len)
+ break;
+ if (len == tok.len && !memcmp(start, p, len)) {
+ tok.type = type;
+ break;
+ }
+ p += len + 1;
+ type++;
+ }
+ }
+ return &tok;
+}
+
+/***********************************************************************
+ * lex : retrieve next token
+ *
+ * Return: tok struct, lifetime until next call to lex
+ */
+struct tok *
+lex(void)
+{
+ const char *p;
+ int ch;
+ for (;;) {
+ if (!file) {
+ tok.type = TOK_EOF;
+ tok.start = "end of file";
+ tok.len = strlen(tok.start);
+ return &tok;
+ }
+ tok.prestart = p = file->pos;
+ /* Flush whitespace. */
+ for (;;) {
+ ch = *p++;
+ switch (ch) {
+ case ' ':
+ case '\t':
+ case '\r':
+ continue;
+ case '\n':
+ ++file->linenum;
+ tok.prestart = p;
+ continue;
+ }
+ break;
+ }
+ p--;
+ if (ch)
+ break;
+ if (p != file->end)
+ lexerrorexit("\\0 byte not allowed");
+ file = file->next;
+ }
+ /* See if we have a comment. */
+ tok.start = p;
+ if (ch == '/') {
+ switch (*++p) {
+ case '*':
+ return lexblockcomment(p - 1);
+ case '/':
+ return lexinlinecomment(p - 1);
+ }
+ tok.type = '/';
+ } else {
+ /* Handle things that start with '-', which is either '-' as a token,
+ * or a number. Handle numbers. */
+ if (ch == '-' || (unsigned)(ch - '0') < 10)
+ return lexnumber(p);
+ /* Handle string. */
+ if (ch == '"')
+ return lexstring(p);
+ /* Handle identifier. */
+ if (ch == '_' || (unsigned)((ch & ~0x20) - 'A') <= 'Z' - 'A')
+ return lexidentifier(p);
+ /* The only multi-symbol token are ... and [] */
+ if (ch == '.') {
+ tok.type = '.';
+ if (*++p == '.' && p[1] == '.') {
+ tok.type = TOK_ELLIPSIS;
+ p += 2;
+ }
+ goto done;
+ }
+ if (ch == '[') {
+ tok.type = '[';
+ if (*++p == ']') {
+ tok.type = TOK_DOUBLEBRACKET;
+ p++;
+ }
+ goto done;
+ }
+ }
+ /* Single symbol token. */
+ tok.type = ch;
+ p++;
+done:
+ tok.filename = file->filename;
+ tok.linenum = file->linenum;
+ tok.len = p - tok.start;
+ file->pos = p;
+ return &tok;
+}
+
+/***********************************************************************
+ * outputwidl : output literal Web IDL input that node was parsed from
+ *
+ * Enter: node = parse node to output literal Web IDL for
+ */
+void
+outputwidl(struct node *node)
+{
+ const char *start = node->wsstart, *end = node->end;
+ /* Find the file that start is in. */
+ struct file *file = firstfile;
+ while (start < file->buf || start >= file->end) {
+ file = file->next;
+ assert(file);
+ }
+ /* Find the (current or) next node that has node->start set. Any such
+ * node needs to be put inside a <ref> element. */
+ while (node && !node->start)
+ node = nodewalk(node);
+ /* Output until we get to the end. This has to cope with the text
+ * spanning multiple input files. */
+ for (;;) {
+ int final = end >= file->buf && end <= file->end;
+ const char *thisend = final ? end : file->end;
+ /* Output the Web IDL, omitting comments. */
+ while (start != end) {
+ const char *p, *p2, *comment, *endcomment;
+ int ch;
+ if (node && start == node->start) {
+ /* We are on the start of the present node in the tree
+ * walk. Put it in a <ref>. */
+ fputs("<ref>", stdout);
+ printtext(node->start, node->end - node->start, 1);
+ fputs("</ref>", stdout);
+ start = node->end;
+ /* Skip to the next node with node->start set if any. */
+ do
+ node = nodewalk(node);
+ while (node && !node->start);
+ continue;
+ }
+ p2 = thisend;
+ if (node && node->start >= file->buf && node->start < p2)
+ p2 = node->start;
+ p = memchr(start, '/', p2 - start);
+ if (!p) {
+ printtext(start, p2 - start, 1);
+ if (p2 != thisend) {
+ start = p2;
+ continue;
+ }
+ break;
+ }
+ /* See if we're at the start of a comment. If so find the end. */
+ comment = 0;
+ if (p + 1 != thisend) {
+ switch (p[1]) {
+ case '*':
+ /* Block comment. */
+ comment = p;
+ p++;
+ do
+ p = memchr(p + 1, '*', thisend - p - 1);
+ while (p[1] != '/');
+ endcomment = p + 2;
+ break;
+ case '/':
+ /* Inline comment. */
+ comment = p;
+ p = memchr(p, '\n', thisend - p);
+ if (!p)
+ p = thisend;
+ endcomment = p;
+ break;
+ }
+ }
+ if (!comment) {
+ /* Not at start of comment. */
+ p++;
+ printtext(start, p - start, 1);
+ start = p;
+ assert(start <= end);
+ continue;
+ }
+ /* If the comment has only whitespace before it on the line,
+ * eat that up. */
+ p = comment;
+ while (p != start && ((ch = p[-1]) == ' ' || ch == '\t'))
+ p--;
+ if (p == start || p[-1] == '\n') {
+ comment = p;
+ /* If the comment has only whitespace after it to the end
+ * of the line, eat that and the newline up. This always
+ * happens for an inline comment on a line by itself. */
+ p = endcomment;
+ while (p != thisend && ((ch = *p) == ' ' || ch == '\t'))
+ p++;
+ if (p != thisend && *p == '\n')
+ p++;
+ endcomment = p;
+ }
+ printtext(start, comment - start, 1);
+ start = endcomment;
+ if (start > thisend)
+ start = thisend;
+ }
+ if (final)
+ break;
+ file = file->next;
+ assert(file);
+ start = file->buf;
+ }
+}
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/lex.h b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/lex.h
new file mode 100644
index 00000000000..e30b77b365c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/lex.h
@@ -0,0 +1,141 @@
+
+/***********************************************************************
+ * $Id$
+ * Copyright 2009 Aplix Corporation. All rights reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ***********************************************************************/
+#ifndef lex_h
+#define lex_h
+
+// starting from "attribute" are the list of names allowed as arguments identifier
+#define KEYWORDS \
+ "DOMString\0" \
+ "ByteString\0" \
+ "Date\0" \
+ "RegExp\0" \
+ "false\0" \
+ "object\0" \
+ "true\0" \
+ "any\0" \
+ "boolean\0" \
+ "byte\0" \
+ "double\0" \
+ "float\0" \
+ "Infinity\0" \
+ "-Infinity\0" \
+ "iterator\0" \
+ "long\0" \
+ "NaN\0" \
+ "null\0" \
+ "octet\0" \
+ "optional\0" \
+ "or\0" \
+ "readonly\0" \
+ "sequence\0" \
+ "short\0" \
+ "unsigned\0" \
+ "void\0" \
+ "attribute\0" \
+ "callback\0" \
+ "const\0" \
+ "creator\0" \
+ "deleter\0" \
+ "dictionary\0" \
+ "enum\0" \
+ "exception\0" \
+ "getter\0" \
+ "implements\0" \
+ "inherit\0" \
+ "interface\0" \
+ "legacycaller\0" \
+ "partial\0" \
+ "serializer\0" \
+ "setter\0" \
+ "static\0" \
+ "stringifier\0" \
+ "typedef\0" \
+ "unrestricted\0"
+
+
+enum toktype {
+ TOK_EOF = -1,
+ TOK_BLOCKCOMMENT = 0x80,
+ TOK_INLINECOMMENT, TOK_INTEGER, TOK_FLOAT, TOK_IDENTIFIER,
+ TOK_STRING, TOK_ELLIPSIS, TOK_DOUBLEBRACKET,
+ /* Keywords must be in the same order as above. */
+ TOK_DOMString,
+ TOK_ByteString,
+ TOK_Date,
+ TOK_RegExp,
+ TOK_false,
+ TOK_object,
+ TOK_true,
+ TOK_any,
+ TOK_boolean,
+ TOK_byte,
+ TOK_double,
+ TOK_float,
+ TOK_infinity,
+ TOK_minusinfinity,
+ TOK_iterator,
+ TOK_long,
+ TOK_NaN,
+ TOK_null,
+ TOK_octet,
+ TOK_optional,
+ TOK_or,
+ TOK_readonly,
+ TOK_sequence,
+ TOK_short,
+ TOK_unsigned,
+ TOK_void,
+ /* Below that line are keywords that are allowed as arguments names */
+ TOK_attribute,
+ TOK_callback,
+ TOK_const,
+ TOK_creator,
+ TOK_deleter,
+ TOK_dictionary,
+ TOK_enum,
+ TOK_exception,
+ TOK_getter,
+ TOK_implements,
+ TOK_inherit,
+ TOK_interface,
+ TOK_legacycaller,
+ TOK_partial,
+ TOK_serializer,
+ TOK_setter,
+ TOK_static,
+ TOK_stringifier,
+ TOK_typedef,
+ TOK_unrestricted,
+};
+
+struct tok {
+ enum toktype type;
+ const char *filename;
+ unsigned int linenum;
+ const char *prestart;
+ const char *start;
+ unsigned int len;
+};
+
+extern const char *filename;
+extern const char keywords[];
+
+struct node;
+
+void readinput(const char *const *argv);
+struct tok *lex(void);
+void outputwidl(struct node *node);
+
+#endif /* ndef lex_h */
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/main.c b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/main.c
new file mode 100644
index 00000000000..df90e347de8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/main.c
@@ -0,0 +1,63 @@
+/***********************************************************************
+ * $Id$
+ * Copyright 2009 Aplix Corporation. All rights reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ***********************************************************************/
+#include <string.h>
+#include "misc.h"
+#include "process.h"
+
+static const char nodtdopt[] = "-no-dtd-ref";
+const char *progname;
+
+/***********************************************************************
+ * options : process command line options
+ *
+ * Enter: argv
+ *
+ * Return: argv stepped to point to first non-option argument
+ */
+static const char *const *
+options(int argc, const char *const *argv)
+{
+ /* Set progname for error messages etc. */
+ {
+ const char *base;
+ progname = argv[0];
+ base = strrchr(progname, '/');
+#ifdef DIRSEP
+ {
+ const char *base2 = strrchr(base, '\\');
+ if (base2 > base)
+ base = base2;
+ }
+#endif /* def DIRSEP */
+ if (base)
+ progname = base + 1;
+ }
+ return (argc > 1 && strncmp(argv[1], nodtdopt, sizeof nodtdopt) == 0)
+ ? argv + 2 : argv + 1;
+}
+
+/***********************************************************************
+ * main : main code for bondiidl command
+ */
+int
+main(int argc, char **argv)
+{
+ const char *const *parg;
+ parg = options(argc, (const char *const *)argv);
+ if (!*parg)
+ errorexit("usage: %s [-no-dtd-ref] <interface>.widl ...", progname);
+ processfiles(parg, parg == (const char *const *)argv + 1);
+ return 0;
+}
+
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/misc.c b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/misc.c
new file mode 100644
index 00000000000..37aff3f34db
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/misc.c
@@ -0,0 +1,119 @@
+/***********************************************************************
+ * $Id$
+ * Copyright 2009 Aplix Corporation. All rights reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ***********************************************************************/
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "misc.h"
+#include "os.h" /* to get va_copy on windows */
+
+extern const char *progname;
+
+/***********************************************************************
+ * memory allocation wrappers
+ */
+void *
+memalloc(size_t size)
+{
+ void *ptr = malloc(size);
+ if (!ptr)
+ errorexit("out of memory");
+ /* Zero initialise memory from memalloc. */
+ memset(ptr, 0, size);
+ return ptr;
+}
+
+void *
+memrealloc(void *ptr, size_t size)
+{
+ void *newptr = realloc(ptr, size);
+ if (!newptr)
+ errorexit("out of memory");
+ return newptr;
+}
+
+void
+memfree(void *ptr)
+{
+ *(int *)ptr = 0xfefefefe;
+ free(ptr);
+}
+
+/***********************************************************************
+ * vmemprintf, memprintf : allocate buffer and sprintf into it
+ */
+char *
+memprintf(const char *format, ...)
+{
+ va_list ap;
+ char *buf;
+ va_start(ap, format);
+ buf = vmemprintf(format, ap);
+ va_end(ap);
+ return buf;
+}
+
+char *
+vmemprintf(const char *format, va_list ap)
+{
+ char *buf;
+ unsigned int max, len;
+ va_list ap2;
+ max = 16;
+ for (;;) {
+ va_copy(ap2, ap);
+ buf = memalloc(max);
+ len = vsnprintf(buf, max, format, ap2);
+ va_end(ap2);
+ if (len < max)
+ break;
+ memfree(buf);
+ max *= 2;
+ }
+ return buf;
+}
+
+/***********************************************************************
+ * errorexit : print error message then exit
+ */
+void
+vlocerrorexit(const char *filename, unsigned int linenum,
+ const char *format, va_list ap)
+{
+ if (filename)
+ fprintf(stderr, linenum ? "%s: %i: " : "%s: ", filename, linenum);
+ vfprintf(stderr, format, ap);
+ fputc('\n', stderr);
+ exit(1);
+}
+
+void
+locerrorexit(const char *filename, unsigned int linenum,
+ const char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ vlocerrorexit(filename, linenum, format, ap);
+ va_end(ap);
+}
+
+void
+errorexit(const char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ vlocerrorexit(0, 0, format, ap);
+ va_end(ap);
+}
+
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/misc.h b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/misc.h
new file mode 100644
index 00000000000..01c36d218ed
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/misc.h
@@ -0,0 +1,31 @@
+/***********************************************************************
+ * $Id$
+ * Copyright 2009 Aplix Corporation. All rights reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ***********************************************************************/
+#ifndef misc_h
+#define misc_h
+#include <stdarg.h>
+#include <stdlib.h>
+
+void *memalloc(size_t size);
+void *memrealloc(void *ptr, size_t size);
+void memfree(void *ptr);
+
+char *vmemprintf(const char *format, va_list ap);
+char *memprintf(const char *format, ...);
+
+void vlocerrorexit(const char *filename, unsigned int linenum, const char *format, va_list ap);
+void locerrorexit(const char *filename, unsigned int linenum, const char *format, ...);
+void errorexit(const char *format, ...);
+
+#endif /* ndef misc_h */
+
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/node.c b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/node.c
new file mode 100644
index 00000000000..d8f737909a4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/node.c
@@ -0,0 +1,331 @@
+/***********************************************************************
+ * $Id$
+ * Copyright 2009 Aplix Corporation. All rights reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Node-specific functions
+ ***********************************************************************/
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include "comment.h"
+#include "lex.h"
+#include "misc.h"
+#include "node.h"
+#include "process.h"
+
+struct node *
+newelement(const char *name)
+{
+ struct element *element = memalloc(sizeof(struct element));
+ element->n.type = NODE_ELEMENT;
+ element->name = name;
+ return &element->n;
+}
+
+struct node *
+newattr(const char *name, const char *val)
+{
+ struct attr *attr = memalloc(sizeof(struct attr));
+ attr->n.type = NODE_ATTR;
+ attr->name = name;
+ attr->value = val;
+ return &attr->n;
+}
+
+struct node *
+newattrlist(void)
+{
+ struct attrlist *attrlist = memalloc(sizeof(struct attrlist));
+ attrlist->n.type = NODE_ATTRLIST;
+ return &attrlist->n;
+}
+
+/***********************************************************************
+ * addnode : add node as child of another node
+ *
+ * Enter: parent node
+ * child node
+ *
+ * The children list is constructed backwards. This is fixed later with
+ * a call to reversechildren.
+ *
+ * If child is an attrlist, its children are added to parent and the
+ * attrlist is freed.
+ */
+void
+addnode(struct node *parent, struct node *child)
+{
+ if (!child)
+ return;
+ if (child->type == NODE_ATTRLIST) {
+ /* Add the attrs in the attrlist to parent. */
+ struct node *child2;
+ reversechildren(child);
+ child2 = child->children;
+ memfree(child);
+ while (child2) {
+ struct node *next = child2->next;
+ addnode(parent, child2);
+ child2 = next;
+ }
+ } else {
+ child->next = parent->children;
+ parent->children = child;
+ child->parent = parent;
+ }
+}
+
+/***********************************************************************
+ * reversechildren : recursively reverse child lists
+ *
+ * Also sets parent field on each node.
+ */
+void
+reversechildren(struct node *node)
+{
+ struct node *newlist = 0;
+ struct node *child = node->children;
+ while (child) {
+ struct node *next = child->next;
+ child->parent = node;
+ child->next = newlist;
+ newlist = child;
+ reversechildren(child);
+ child = next;
+ }
+ node->children = newlist;
+}
+
+/***********************************************************************
+ * nodeisempty : test if node is empty (has no children)
+ */
+int
+nodeisempty(struct node *node)
+{
+ return !node->children;
+}
+
+/***********************************************************************
+ * nodewalk : single step of depth last traversal of node tree
+ *
+ * Return: next node in walk, 0 if finished
+ */
+struct node *
+nodewalk(struct node *node)
+{
+ if (node->children)
+ return node->children;
+ if (node->next)
+ return node->next;
+ do {
+ node = node->parent;
+ if (!node)
+ return 0;
+ } while (!node->next);
+ return node->next;
+}
+
+/***********************************************************************
+ * findchildelement : find child element of a particular name
+ *
+ * Enter: node = element
+ * name = name to find
+ *
+ * Return: 0 else child element of that name
+ */
+static struct node *
+findchildelement(struct node *node, const char *name)
+{
+ node = node->children;
+ while (node) {
+ if (node->type == NODE_ELEMENT) {
+ struct element *element = (void *)node;
+ if (!strcmp(element->name, name))
+ break;
+ }
+ node = node->next;
+ }
+ return node;
+}
+
+/***********************************************************************
+ * getattr : get value of attribute
+ *
+ * Enter: node = element to find attribute in
+ * name = name of attribute
+ *
+ * Return: 0 if not found, else 0-terminated string value
+ */
+const char *
+getattr(struct node *node, const char *name)
+{
+ node = node->children;
+ while (node) {
+ if (node->type == NODE_ATTR) {
+ struct attr *attr = (void *)node;
+ if (!strcmp(attr->name, name))
+ return attr->value;
+ }
+ node = node->next;
+ }
+ return 0;
+}
+
+/***********************************************************************
+ * findchildelementwithnameattr : find child element with a name attribute
+ * of a particular value
+ *
+ * Enter: node = element
+ * name = name to find
+ *
+ * Return: 0 else child element with name attr of that value
+ */
+static struct node *
+findchildelementwithnameattr(struct node *node, const char *name)
+{
+ node = node->children;
+ while (node) {
+ if (node->type == NODE_ELEMENT) {
+ const char *s = getattr(node, "name");
+ if (s && !strcmp(s, name))
+ break;
+ }
+ node = node->next;
+ }
+ return node;
+}
+
+/***********************************************************************
+ * findreturntype : find Type parse node for return type
+ *
+ * Enter: node = Operation element
+ *
+ * Return: 0 if not found, else Type parse node for return type
+ */
+struct node *
+findreturntype(struct node *node)
+{
+ return findchildelement(node, "Type");
+}
+
+/***********************************************************************
+ * findparamidentifier : find identifier parse node for parameter
+ *
+ * Enter: node = Operation element
+ * name = parameter name to find
+ *
+ * Return: 0 if not found, else node struct for parameter identifier
+ */
+struct node *
+findparamidentifier(struct node *node, const char *name)
+{
+ node = findchildelement(node, "ArgumentList");
+ if (node)
+ node = findchildelementwithnameattr(node, name);
+ return node;
+}
+
+/***********************************************************************
+ * findthrowidentifier : find identifier parse node for exception name
+ *
+ * Enter: node = Operation element
+ * name = exception name to find
+ *
+ * Return: 0 if not found, else node for Name element, child of Raises
+ * or SetRaises
+ */
+struct node *
+findthrowidentifier(struct node *node, const char *name)
+{
+ struct node *node2 = findchildelement(node, "Raises");
+ if (node2)
+ node2 = findchildelementwithnameattr(node2, name);
+ if (!node2) {
+ node2 = findchildelement(node, "SetRaises");
+ if (node2)
+ node2 = findchildelementwithnameattr(node2, name);
+ }
+ return node2;
+}
+
+/***********************************************************************
+ * outputid : output the id of a node
+ */
+static void
+outputid(struct node *node)
+{
+ if (node->parent)
+ outputid(node->parent);
+ if (node->id) {
+ fputs("::", stdout);
+ printtext(node->id, strlen(node->id), 1);
+ }
+}
+
+/***********************************************************************
+ * outputnode : output node and its children
+ *
+ * Enter: node = node to output, assumed to be an element
+ * indent
+ */
+void
+outputnode(struct node *node, unsigned int indent)
+{
+ struct element *element = (void *)node;
+ struct node *child;
+ int empty = 1;
+ printf("%*s<%s", indent, "", element->name);
+ child = element->n.children;
+ while (child) {
+ switch(child->type) {
+ case NODE_ELEMENT:
+ empty = 0;
+ break;
+ case NODE_ATTR:
+ {
+ struct attr *attr = (void *)child;
+ printf(" %s=\"", attr->name);
+ printtext(attr->value, strlen(attr->value), 1);
+ printf("\"");
+ }
+ break;
+ }
+ child = child->next;
+ }
+ if (node->id) {
+ printf(" id=\"");
+ outputid(node);
+ printf("\"");
+ }
+ if (!empty || node->comments || node->wsstart) {
+ printf(">\n");
+ if (node->wsstart) {
+ printf("%*s <webidl>", indent, "");
+ outputwidl(node);
+ printf("</webidl>\n");
+ }
+ outputdescriptive(node, indent + 2);
+ child = element->n.children;
+ while (child) {
+ switch(child->type) {
+ case NODE_ELEMENT:
+ outputnode(child, indent + 2);
+ break;
+ }
+ child = child->next;
+ }
+ printf("%*s</%s>\n", indent, "", element->name);
+ } else
+ printf("/>\n");
+}
+
+
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/node.h b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/node.h
new file mode 100644
index 00000000000..2d6e38e5323
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/node.h
@@ -0,0 +1,65 @@
+/***********************************************************************
+ * $Id$
+ * Copyright 2009 Aplix Corporation. All rights reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ***********************************************************************/
+#ifndef node_h
+#define node_h
+
+/* struct node : a node in the parse tree (excluding comments) */
+enum { NODE_ELEMENT, NODE_ATTR, NODE_ATTRLIST };
+struct node {
+ int type;
+ struct node *next;
+ struct node *parent;
+ struct node *children;
+ struct comment *comments; /* list of comments attached to this node */
+ /* If wsstart and end are set, they give the literal Web IDL that can
+ * be output in a <webidl> element. */
+ const char *wsstart;
+ /* If start and end are set, they give the text of a scoped name that
+ * can be enclosed in a <ref> when outputting a <webidl> element for
+ * an ancestor element. */
+ const char *start;
+ const char *end;
+ const char *id;
+};
+
+struct element {
+ struct node n;
+ const char *name;
+};
+
+struct attr {
+ struct node n;
+ const char *name;
+ const char *value;
+};
+
+struct attrlist {
+ struct node n;
+};
+
+struct node *newelement(const char *name);
+struct node *newattr(const char *name, const char *val);
+struct node *newattrlist(void);
+void addnode(struct node *parent, struct node *child);
+void reversechildren(struct node *node);
+int nodeisempty(struct node *node);
+const char *getattr(struct node *node, const char *name);
+struct node *nodewalk(struct node *node);
+struct node *findreturntype(struct node *node);
+struct node *findparamidentifier(struct node *node, const char *name);
+struct node *findthrowidentifier(struct node *node, const char *name);
+void outputnode(struct node *node, unsigned int indent);
+
+#endif /* ndef node_h */
+
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/os.h b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/os.h
new file mode 100644
index 00000000000..ac8f4189d19
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/os.h
@@ -0,0 +1,31 @@
+/***********************************************************************
+ * $Id$
+ * Copyright 2009 Aplix Corporation. All rights reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ***********************************************************************/
+#ifndef os_h
+#define os_h
+
+/* Linux configuration */
+#if defined(__gnu_linux__)
+
+
+/* Windows configuration */
+#elif defined(_MSC_VER)
+
+#define inline __inline
+#define strncasecmp strnicmp
+#define snprintf _snprintf
+#define va_copy(a,b) ((a)=(b))
+
+#endif
+
+#endif /* ndef os_h */
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/parse.c b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/parse.c
new file mode 100644
index 00000000000..c0e8454ceac
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/parse.c
@@ -0,0 +1,1414 @@
+/***********************************************************************
+ * $Id$
+ * Copyright 2009 Aplix Corporation. All rights reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Hand-crafted recursive descent parser for Web IDL grammar.
+ ***********************************************************************/
+#include <assert.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "comment.h"
+#include "lex.h"
+#include "misc.h"
+#include "node.h"
+#include "parse.h"
+
+/***********************************************************************
+ * tokerrorexit : error and exit with line number from token
+ */
+static void
+tokerrorexit(struct tok *tok, const char *format, ...)
+{
+ va_list ap;
+ char *m;
+ va_start(ap, format);
+ m = vmemprintf(format, ap);
+ if (tok->type == TOK_EOF)
+ locerrorexit(tok->filename, tok->linenum, "at end of input: %s", m);
+ else
+ locerrorexit(tok->filename, tok->linenum, "at '%.*s': %s", tok->len, tok->start, m);
+ va_end(ap);
+}
+
+/***********************************************************************
+ * lexnocomment : lex next token, discarding or storing comments
+ *
+ * A block comment starting with |** or |*! is a doxygen comment.
+ * If it starts with |**< or |*!< then it refers to the previous
+ * identifier, not the next one. (I am using | to represent / otherwise
+ * this comment would be illegal.)
+ *
+ * An inline comment starting with /// or //! is a doxygen comment.
+ * If it starts with ///< or //!< then it refers to the previous
+ * identifier, not the next one.
+ */
+static struct tok *
+lexnocomment(void)
+{
+ struct tok *tok;
+ for (;;) {
+ tok = lex();
+ if (tok->type != TOK_BLOCKCOMMENT && tok->type != TOK_INLINECOMMENT)
+ break;
+ addcomment(tok);
+ }
+ return tok;
+}
+
+/***********************************************************************
+ * eat : check token then read the following one
+ *
+ * Enter: tok struct
+ * type = type of token expected, error given if no match
+ *
+ * On return, tok is updated to the following token.
+ */
+static void
+eat(struct tok *tok, int type)
+{
+ if (tok->type != type) {
+ const char *p;
+ if (type < TOK_DOMString)
+ tokerrorexit(tok, "expected '%c'", type);
+ p = keywords;
+ while (type != TOK_DOMString) {
+ p += strlen(p) + 1;
+ type--;
+ }
+ tokerrorexit(tok, "expected '%s'", p);
+ }
+ lexnocomment();
+}
+
+/***********************************************************************
+ * setid : flag that an id attribute is required on node
+ *
+ * Enter: node
+ *
+ * node->id is set to the value of the name attribute. This makes
+ * outputnode give it an id attribute whose value is the id attribute
+ * of the parent if any, then "::", then node->id.
+ */
+static void
+setid(struct node *node)
+{
+ node->id = getattr(node, "name");
+}
+
+/***********************************************************************
+ * setidentifier : allocate 0-terminated string for identifier token
+ *
+ * Enter: tok = token, error given if not identifier
+ *
+ * Return: allocated 0-terminated string
+ */
+static char *
+setidentifier(struct tok *tok)
+{
+ char *s;
+ if (tok->type != TOK_IDENTIFIER)
+ tokerrorexit(tok, "expected identifier");
+ s = memprintf("%.*s", tok->len, tok->start);
+ return s;
+}
+
+/***********************************************************************
+ * setargumentname : allocate 0-terminated string for identifier token
+ *
+ * Enter: tok = token, error given if not identifier
+ *
+ * Return: allocated 0-terminated string
+ */
+static char *
+setargumentname(struct tok *tok)
+{
+ char *s;
+ if (tok->type != TOK_IDENTIFIER && tok->type < TOK_attribute)
+ tokerrorexit(tok, "expected argument name");
+ s = memprintf("%.*s", tok->len, tok->start);
+ return s;
+}
+
+
+/* Prototypes for funcs that have a forward reference. */
+static struct node *parsetype(struct tok *tok);
+static struct node *parsedefaultvalue(struct tok *tok, struct node *parent);
+static struct node *parseuniontype(struct tok *tok);
+static struct node *parseargumentlist(struct tok *tok);
+static void parsedefinitions(struct tok *tok, struct node *parent);
+static struct node *parsetypesuffixstartingwitharray(struct tok *tok, struct node *node);
+
+/***********************************************************************
+ * parsescopedname : parse [53] ScopedName
+ *
+ * Enter: tok = next token
+ * name = name of attribute to put scoped name in
+ * ref = whether to enable enclosing of the name in <ref> in
+ * outputwidl
+ *
+ * Return: node struct for new attribute
+ * tok updated
+ */
+static struct node *
+parsescopedname(struct tok *tok, const char *name, int ref)
+{
+ const char *start = tok->start, *end;
+ struct node *node;
+ unsigned int len = 0;
+ char *s = memalloc(3);
+ if (tok->type != TOK_IDENTIFIER)
+ tokerrorexit(tok, "expected identifier");
+ s = memrealloc(s, len + tok->len + 1);
+ memcpy(s + len, tok->start, tok->len);
+ len += tok->len;
+ end = tok->start + tok->len;
+ lexnocomment();
+ s[len] = 0;
+ node = newattr(name, s);
+ if (ref) {
+ node->start = start;
+ node->end = end;
+ }
+ return node;
+}
+
+/***********************************************************************
+ * parsescopednamelist : parse [51] ScopedNameList
+ *
+ * Enter: tok = next token
+ * name = name of element for scoped name list
+ * name2 = name of element for entry in list
+ * comment = whether to attach documentation to each name
+ *
+ * Return: node for list of scoped names
+ * tok updated
+ */
+static struct node *
+parsescopednamelist(struct tok *tok, const char *name, const char *name2,
+ int comment)
+{
+ struct node *node = newelement(name);
+ for (;;) {
+ struct node *attr = parsescopedname(tok, "name", 1);
+ struct node *n = newelement(name2);
+ if (comment)
+ setcommentnode(n);
+ addnode(n, attr);
+ addnode(node, n);
+ if (tok->type != ',')
+ break;
+ lexnocomment();
+ }
+ return node;
+}
+
+/***********************************************************************
+ * parsereturntype : parse [50] ReturnType
+ *
+ * Enter: tok = next token
+ *
+ * Return: node for type
+ * tok updated
+ */
+static struct node *
+parsereturntype(struct tok *tok)
+{
+ if (tok->type == TOK_void) {
+ struct node *node = newelement("Type");
+ addnode(node, newattr("type", "void"));
+ lexnocomment();
+ return node;
+ }
+ return parsetype(tok);
+}
+
+/***********************************************************************
+ * parseunsignedintegertype : parse [46] UnsignedIntegerType
+ *
+ * Enter: tok = next token (one of "unsigned", "short" or "long")
+ *
+ * Return: 0-terminated canonical string for the type
+ * tok updated to just past UnsignedIntegerType
+ */
+static const char *
+parseunsignedintegertype(struct tok *tok)
+{
+ static const char *names[] = {
+ "short", "long", "long long", 0,
+ "unsigned short", "unsigned long", "unsigned long long" };
+ enum { TYPE_SHORT, TYPE_LONG, TYPE_LONGLONG,
+ TYPE_UNSIGNED = 4 };
+ int type = 0;
+ if (tok->type == TOK_unsigned) {
+ type = TYPE_UNSIGNED;
+ lexnocomment();
+ }
+ if (tok->type == TOK_short) {
+ type |= TYPE_SHORT;
+ lexnocomment();
+ } else if (tok->type != TOK_long)
+ tokerrorexit(tok, "expected 'short' or 'long' after 'unsigned'");
+ else {
+ type |= TYPE_LONG;
+ lexnocomment();
+ if (tok->type == TOK_long) {
+ type += TYPE_LONGLONG - TYPE_LONG;
+ lexnocomment();
+ }
+ }
+ return names[type];
+}
+/***********************************************************************
+ * parsetypesuffix : parse [44] TypeSuffix
+ *
+ * Enter: tok = next token
+ *
+ * Return: node for type
+ * tok updated
+ */
+static struct node *
+parsetypesuffix(struct tok *tok, struct node *node)
+{
+ if (tok->type == TOK_DOUBLEBRACKET) {
+ struct node *typenode = node;
+ node = newelement("Type");
+ addnode(node, newattr("type", "array"));
+ addnode(node, typenode);
+ lexnocomment();
+ node = parsetypesuffix(tok, node);
+ } else if (tok->type == '?') {
+ addnode(node, newattr("nullable", "nullable"));
+ lexnocomment();
+ node = parsetypesuffixstartingwitharray(tok, node);
+ }
+ return node;
+}
+
+/***********************************************************************
+ * parsetypesuffixstartingwitharray : parse [44] TypeSuffixStartingWithArray
+ *
+ * Enter: tok = next token
+ *
+ * Return: node for type
+ * tok updated
+ */
+static struct node *
+parsetypesuffixstartingwitharray(struct tok *tok, struct node *node)
+{
+ if (tok->type == TOK_DOUBLEBRACKET) {
+ struct node *typenode = node;
+ node = newelement("Type");
+ addnode(node, newattr("type", "array"));
+ addnode(node, typenode);
+ lexnocomment();
+ node = parsetypesuffix(tok, node);
+ }
+ return node;
+}
+
+/***********************************************************************
+ * parseprimitiveorstringtype : parse [45] PrimitiveOrString
+ *
+ * Enter: tok = next token
+ *
+ * Return: node for type
+ * tok updated
+ */
+static struct node *
+parseprimitiveorstringtype(struct tok *tok)
+{
+ struct node *node;
+ switch (tok->type) {
+ case TOK_unsigned:
+ case TOK_short:
+ case TOK_long:
+ node = newelement("Type");
+ addnode(node, newattr("type", parseunsignedintegertype(tok)));
+ break;
+ default:
+ node = newelement("Type");
+ switch (tok->type) {
+ default:
+ tokerrorexit(tok, "expected type");
+ break;
+ case TOK_unrestricted:
+ lexnocomment();
+ if (tok->type == TOK_float) {
+ addnode(node, newattr("type", "unrestricted float"));
+ } else if (tok->type == TOK_double) {
+ addnode(node, newattr("type", "unrestricted double"));
+ } else {
+ tokerrorexit(tok, "expected float or double after unrestricted");
+ }
+ break;
+ case TOK_boolean:
+ addnode(node, newattr("type", "boolean"));
+ break;
+ case TOK_byte:
+ addnode(node, newattr("type", "byte"));
+ break;
+ case TOK_octet:
+ addnode(node, newattr("type", "octet"));
+ break;
+ case TOK_float:
+ addnode(node, newattr("type", "float"));
+ break;
+ case TOK_double:
+ addnode(node, newattr("type", "double"));
+ break;
+ case TOK_DOMString:
+ addnode(node, newattr("type", "DOMString"));
+ break;
+ case TOK_ByteString:
+ addnode(node, newattr("type", "ByteString"));
+ break;
+ case TOK_Date:
+ addnode(node, newattr("type", "Date"));
+ break;
+ case TOK_RegExp:
+ addnode(node, newattr("type", "RegExp"));
+ break;
+
+ }
+ lexnocomment();
+ }
+ return node;
+}
+
+/***********************************************************************
+ * parsenonanytype : parse NonAnyType
+ *
+ * Enter: tok = next token
+ *
+ * Return: node for type
+ * tok updated
+ */
+static struct node *
+parsenonanytype(struct tok *tok)
+{
+ struct node *node;
+ switch (tok->type) {
+ case TOK_IDENTIFIER:
+ node = newelement("Type");
+ addnode(node, parsescopedname(tok, "name", 1));
+ node = parsetypesuffix(tok, node);
+ break;
+ case TOK_sequence:
+ node = newelement("Type");
+ addnode(node, newattr("type", "sequence"));
+ lexnocomment();
+ eat(tok, '<');
+ addnode(node, parsetype(tok));
+ eat(tok, '>');
+ if (tok->type == '?') {
+ addnode(node, newattr("nullable", "nullable"));
+ lexnocomment();
+ }
+ break;
+ case TOK_object:
+ node = newelement("Type");
+ addnode(node, newattr("type", "object"));
+ lexnocomment();
+ node = parsetypesuffix(tok, node);
+ break;
+ default:
+ node = parseprimitiveorstringtype(tok);
+ node = parsetypesuffix(tok, node);
+ break;
+ }
+ return node;
+}
+
+/***********************************************************************
+ * parseunionmembertype: parse UnionMemberType
+ *
+ * Enter: tok = next token
+ *
+ * Return: node for type
+ * tok updated
+ */
+static struct node *
+parseunionmembertype(struct tok *tok)
+{
+ struct node *node;
+ if (tok->type == TOK_any) {
+ struct node *typenode = newelement("Type");
+ addnode(typenode, newattr("type", "any"));
+ lexnocomment();
+ eat(tok, TOK_DOUBLEBRACKET);
+ node = newelement("Type");
+ addnode(node, newattr("type", "array"));
+ addnode(node, typenode);
+ lexnocomment();
+ node = parsetypesuffix(tok, node);
+ } else if (tok->type == '(') {
+ node = parseuniontype(tok);
+ } else {
+ node = parsenonanytype(tok);
+ }
+ return node;
+}
+
+
+/***********************************************************************
+ * parseuniontype : parse UnionType
+ *
+ * Enter: tok = next token
+ *
+ * Return: node for type
+ * tok updated
+ */
+static struct node *
+parseuniontype(struct tok *tok)
+{
+ struct node *node;
+ eat(tok, '(');
+ node = newelement("Type");
+ addnode(node, newattr("type", "union"));
+ if (tok->type != ')') {
+ for (;;) {
+ addnode(node, parseunionmembertype(tok));
+ if (tok->type != TOK_or)
+ break;
+ lexnocomment();
+ }
+ }
+ eat(tok, ')');
+ node = parsetypesuffix(tok, node);
+ return node;
+}
+
+/***********************************************************************
+ * parsetype : parse [44] Type
+ *
+ * Enter: tok = next token
+ *
+ * Return: node for type
+ * tok updated
+ */
+static struct node *
+parsetype(struct tok *tok)
+{
+ struct node *node;
+ if (tok->type == '(') {
+ node = parseuniontype(tok);
+ } else if (tok->type == TOK_any) {
+ node = newelement("Type");
+ addnode(node, newattr("type", "any"));
+ lexnocomment();
+ node = parsetypesuffixstartingwitharray(tok, node);
+ } else {
+ node = parsenonanytype(tok);
+ }
+ return node;
+}
+
+
+/***********************************************************************
+ * parseextendedattribute : parse [39] ExtendedAttribute
+ *
+ * Enter: tok = next token
+ *
+ * Return: node for extended attribute
+ *
+ * This parses the various forms of extended attribute, as in
+ * rules [57] [58] [59] [60] [61].
+ *
+ * This does not spot the error that you cannot have a ScopedName
+ * and an ArgumentList.
+ */
+static struct node *
+parseextendedattribute(struct tok *tok)
+{
+ const char *start ;
+ struct node *node = newelement("ExtendedAttribute");
+ char *attrname = setidentifier(tok);
+ addnode(node, newattr("name", attrname));
+ start = tok->prestart;
+ node->wsstart = start;
+ node->end = tok->start + tok->len;
+ if(!strcmp(attrname, "Constructor") || !strcmp(attrname, "NamedConstructor")) {
+ setcommentnode(node);
+ }
+ lexnocomment();
+ if (tok->type == '=') {
+ lexnocomment();
+ addnode(node, parsescopedname(tok, "value", 0));
+ }
+ if (tok->type == '(') {
+ lexnocomment();
+ addnode(node, parseargumentlist(tok));
+ node->end = tok->start + tok->len;
+ eat(tok, ')');
+ }
+ return node;
+}
+
+/***********************************************************************
+ * parseextendedattributelist : parse [37] ExtendedAttributeList
+ *
+ * Enter: tok = next token
+ *
+ * Return: 0 else node for extended attribute list
+ * tok updated if anything parsed
+ */
+static struct node *
+parseextendedattributelist(struct tok *tok)
+{
+ struct node *node;
+ if (tok->type != '[')
+ return 0;
+ node = newelement("ExtendedAttributeList");
+ for (;;) {
+ lexnocomment();
+ addnode(node, parseextendedattribute(tok));
+ if (tok->type != ',')
+ break;
+ }
+ if (tok->type != ']')
+ tokerrorexit(tok, "expected ',' or ']'");
+ lexnocomment();
+ return node;
+}
+
+/***********************************************************************
+ * parseexceptionfield : parse [36] ExceptionField
+ *
+ * Enter: tok = next token
+ * eal = 0 else extended attribute list node
+ *
+ * Return: new node for the exceptionfield
+ * tok updated
+ */
+static struct node *
+parseexceptionfield(struct tok *tok, struct node *eal)
+{
+ struct node *node = newelement("ExceptionField");
+ if (eal) addnode(node, eal);
+ setcommentnode(node);
+ addnode(node, parsetype(tok));
+ addnode(node, newattr("name", setidentifier(tok)));
+ tok = lexnocomment();
+ return node;
+}
+
+/***********************************************************************
+ * parseargument : parse [31] Argument
+ *
+ * Enter: tok = next token
+ *
+ * Return: new node
+ *
+ * tok updated on return
+ */
+static struct node *
+parseargument(struct tok *tok)
+{
+ struct node *node = newelement("Argument");
+ struct node *eal = parseextendedattributelist(tok);
+ setcommentnode(node);
+ if (eal) addnode(node, eal);
+ if (tok->type == TOK_optional) {
+ addnode(node, newattr("optional", "optional"));
+ lexnocomment();
+ }
+ addnode(node, parsetype(tok));
+ if (tok->type == TOK_ELLIPSIS) {
+ addnode(node, newattr("ellipsis", "ellipsis"));
+ lexnocomment();
+ }
+ addnode(node, newattr("name", setargumentname(tok)));
+ lexnocomment();
+ // Optional default value
+ if (tok->type == '=') {
+ tok = lexnocomment();
+ node = parsedefaultvalue(tok, node);
+ }
+ return node;
+}
+
+/***********************************************************************
+ * parseargumentlist : parse [29] ArgumentList
+ *
+ * Enter: tok = next token
+ *
+ * Return: new node for the arglist
+ * tok updated
+ */
+static struct node *
+parseargumentlist(struct tok *tok)
+{
+ struct node *node = newelement("ArgumentList");
+ /* We rely on the fact that ArgumentList is always followed by ')'. */
+ if (tok->type != ')') {
+ for (;;) {
+ addnode(node, parseargument(tok));
+ if (tok->type != ',')
+ break;
+ lexnocomment();
+ }
+ }
+ return node;
+}
+
+
+/***********************************************************************
+ * parseoperationrest : parse [25] OperationRest
+ *
+ * Enter: tok = next token
+ * node
+ *
+ * Return: node
+ * tok on terminating ';'
+ */
+static struct node *
+parseoperationrest(struct tok *tok, struct node *node)
+{
+ if (tok->type == TOK_IDENTIFIER) {
+ addnode(node, newattr("name", setidentifier(tok)));
+ lexnocomment();
+ }
+ eat(tok, '(');
+ addnode(node, parseargumentlist(tok));
+ eat(tok, ')');
+ return node;
+}
+
+/***********************************************************************
+ * parsereturntypeandoperationrest: parse ReturnType OperationRest
+ * Enter: tok = next token
+ * eal
+ * attrs list of attributes
+ * Return: node
+ * tok on terminating ';'
+ */
+static struct node *
+parsereturntypeandoperationrest(struct tok *tok, struct node *eal, struct node *attrs)
+{
+ struct node *node = newelement("Operation");
+ struct node *nodeType = parsereturntype(tok);
+ if (eal) addnode(node, eal);
+ setcommentnode(node);
+ addnode(node, attrs);
+ addnode(node, nodeType);
+ return parseoperationrest(tok, node);
+}
+
+/***********************************************************************
+ * parseiteratorrest : parse OptionalIteratorInterface
+ *
+ * Enter: tok = next token
+ * node
+ *
+ * Return: node
+ * tok on terminating ';'
+ */
+static struct node *
+parseoptionaliteratorinterface(struct tok *tok, struct node *node)
+{
+ if (tok->type == '=') {
+ lexnocomment();
+ addnode(node, newattr("interface", setidentifier(tok)));
+ lexnocomment();
+ }
+ return node;
+}
+
+/***********************************************************************
+ * parseoperationoriteratorrest : parse [25] OperationOrIteratorRest
+ *
+ * Enter: tok = next token
+ * eal = 0 else extended attribute list node
+ * attrs = list-of-attrs node containing attrs to add to new node
+ *
+ * Return: new node
+ * tok on terminating ';'
+ */
+static struct node *
+parseoperationoriteratorrest(struct tok *tok, struct node *eal, struct node *attrs)
+{
+ struct node *node;
+ struct node *nodeType = parsereturntype(tok);
+ unsigned int isIterator = 0;
+ if (tok->type == TOK_iterator) {
+ lexnocomment();
+ if (tok->type == TOK_object) {
+ lexnocomment();
+ node = newelement("IteratorObject");
+ addnode(node, nodeType);
+ return node;
+ } else {
+ node = newelement("Iterator");
+ isIterator = 1;
+ }
+ } else {
+ node = newelement("Operation");
+ }
+ if (eal) addnode(node, eal);
+ setcommentnode(node);
+ addnode(node, attrs);
+ addnode(node, nodeType);
+ if (isIterator)
+ return parseoptionaliteratorinterface(tok, node);
+ else
+ return parseoperationrest(tok, node);
+}
+
+
+/***********************************************************************
+ * parseattribute : parse [17] Attribute
+ *
+ * Enter: tok = next token ("readonly" or "attribute")
+ * eal = 0 else extended attribute list node
+ * attrs = list-of-attrs node containing attrs to add to new node
+ *
+ * Return: node
+ * tok on terminating ';'
+ */
+static struct node *
+parseattribute(struct tok *tok, struct node *eal, struct node *attrs)
+{
+ struct node *node = newelement("Attribute");
+ if (eal) addnode(node, eal);
+ setcommentnode(node);
+ addnode(node, attrs);
+ if (tok->type == TOK_inherit) {
+ lexnocomment();
+ addnode(node, newattr("inherit", "inherit"));
+ }
+ if (tok->type == TOK_readonly) {
+ lexnocomment();
+ addnode(node, newattr("readonly", "readonly"));
+ }
+ eat(tok, TOK_attribute);
+ addnode(node, parsetype(tok));
+ addnode(node, newattr("name", setidentifier(tok)));
+ lexnocomment();
+ return node;
+}
+
+/***********************************************************************
+ * parseserializer : parse Serializer
+ *
+ * Enter: tok = next token
+ * eal
+ *
+ * Return: node updated with value
+ * tok updated
+ */
+static struct node *
+parseserializer (struct tok *tok, struct node *eal) {
+ struct node *nodeAttribute;
+ struct node *node = newelement("Serializer");
+ if (tok->type == '=') {
+ if (eal) addnode(node, eal);
+ lexnocomment();
+ if (tok->type == TOK_IDENTIFIER) {
+ addnode(node, newattr("attribute", setidentifier(tok)));
+ lexnocomment();
+ } else if (tok->type == '{') {
+ unsigned int done = 0;
+ struct node *nodeMap = newelement("Map");
+ lexnocomment();
+ if (tok->type == TOK_getter) {
+ addnode(nodeMap, newattr("pattern", "getter"));
+ done = 1;
+ } else if (tok->type == TOK_attribute) {
+ addnode(nodeMap, newattr("pattern", "all"));
+ done = 1;
+ } else if (tok->type == TOK_inherit) {
+ addnode(nodeMap, newattr("inherit", "inherit"));
+ lexnocomment();
+ eat(tok, ',');
+ if (tok->type == TOK_attribute) {
+ addnode(nodeMap, newattr("pattern", "all"));
+ done = 1;
+ }
+ } else if (tok->type != TOK_IDENTIFIER) {
+ tokerrorexit(tok, "expected 'attribute', 'getter', 'inherit' or attribute identifiers in serializer map");
+ }
+ if (done) {
+ lexnocomment();
+ eat(tok, '}');
+ } else {
+ addnode(nodeMap, newattr("pattern", "selection"));
+ do {
+ if (tok->type != TOK_IDENTIFIER)
+ tokerrorexit(tok, "expected attribute identifiers in serializer map %s", tok->prestart);
+ nodeAttribute = newelement("PatternAttribute");
+ addnode(nodeAttribute, newattr("name", setidentifier(tok)));
+ addnode(nodeMap, nodeAttribute);
+ lexnocomment();
+ if (tok->type == ',')
+ lexnocomment();
+ } while (tok->type != '}');
+ eat(tok, '}');
+ }
+ addnode(node, nodeMap);
+ } else if (tok->type == '[') {
+ struct node *nodeList = newelement("List");
+ lexnocomment();
+ if (tok->type == TOK_getter) {
+ addnode(nodeList, newattr("pattern", "getter"));
+ lexnocomment();
+ eat(tok, ']');
+ } else {
+ addnode(nodeList, newattr("pattern", "selection"));
+ do {
+ if (tok->type != TOK_IDENTIFIER)
+ tokerrorexit(tok, "expected attribute identifiers in serializer list");
+ nodeAttribute = newelement("PatternAttribute");
+ addnode(nodeAttribute, newattr("name", setidentifier(tok)));
+ addnode(nodeList, nodeAttribute);
+ lexnocomment();
+ if (tok->type == ',')
+ lexnocomment();
+ } while (tok->type != ']');
+ eat(tok, ']');
+ }
+ addnode(node, nodeList);
+ } else {
+ tokerrorexit(tok, "Expected '{', '[' or an attribute identifier in the serializer declaration");
+ }
+ return node;
+ } else {
+ if (eal) addnode(node, eal);
+ return node;
+ }
+}
+
+/***********************************************************************
+ * parseattributeoroperationoriterator : parse [15] AttributeOrOperationOrIterator
+ *
+ * Enter: tok = next token
+ * eal = 0 else extended attribute list node
+ *
+ * Return: new node
+ * tok on terminating ';'
+ */
+static struct node *
+parseattributeoroperationoriterator(struct tok *tok, struct node *eal)
+{
+ int alreadyseen ;
+ struct node *attrs = newattrlist();
+ if (tok->type == TOK_serializer) {
+ lexnocomment();
+ if (tok->type == '=' || tok->type ==';') {
+ return parseserializer(tok, eal);
+ } else {
+ addnode(attrs, newattr("serializer", "serializer"));
+ return parsereturntypeandoperationrest(tok, eal, attrs);
+ }
+ }
+ if (tok->type == TOK_stringifier) {
+ addnode(attrs, newattr("stringifier", "stringifier"));
+ lexnocomment();
+ if (tok->type == ';') {
+ struct node *node = newelement("Stringifier");
+ if (eal) addnode(node, eal);
+ return node;
+ }
+ }
+ if (tok->type == TOK_static) {
+ lexnocomment();
+ addnode(attrs, newattr("static", "static"));
+ }
+ if (tok->type == TOK_inherit || tok->type == TOK_readonly || tok->type == TOK_attribute)
+ return parseattribute(tok, eal, attrs);
+ if (!nodeisempty(attrs))
+ return parsereturntypeandoperationrest(tok, eal, attrs);
+ alreadyseen = 0;
+ for (;;) {
+ static const int t[] = { TOK_getter,
+ TOK_setter, TOK_creator, TOK_deleter, TOK_legacycaller,
+ 0 };
+ const int *tt = t;
+ char *s;
+ while (*tt && *tt != tok->type)
+ tt++;
+ if (!*tt)
+ break;
+ s = memprintf("%.*s", tok->len, tok->start);
+ if (alreadyseen & (1 << (tt - t)))
+ tokerrorexit(tok, "'%s' qualifier cannot be repeated", s);
+ alreadyseen |= 1 << (tt - t);
+ addnode(attrs, newattr(s, s));
+ lexnocomment();
+ }
+ if (!nodeisempty(attrs))
+ return parsereturntypeandoperationrest(tok, eal, attrs);
+ else
+ return parseoperationoriteratorrest(tok, eal, attrs);
+}
+
+
+/***********************************************************************
+ * parseconstexpr : parse ConstValue
+ *
+ * Enter: tok = next token
+ * node
+ *
+ * Return: node updated with value
+ * tok updated
+ */
+static struct node *
+parseconstexpr (struct tok *tok, struct node *node) {
+ char *s;
+ switch(tok->type) {
+ case TOK_true:
+ case TOK_false:
+ case TOK_minusinfinity:
+ case TOK_INTEGER:
+ case TOK_FLOAT:
+ case TOK_null:
+ case TOK_infinity:
+ case TOK_NaN:
+ break;
+ default:
+ tokerrorexit(tok, "expected constant value");
+ break;
+ }
+ s = memalloc(tok->len + 1);
+ memcpy(s, tok->start, tok->len);
+ s[tok->len] = 0;
+ if (tok->type != TOK_STRING) {
+ addnode(node, newattr("value", s));
+ } else {
+ addnode(node, newattr("stringvalue", s));
+ }
+ lexnocomment();
+ return node;
+}
+
+/***********************************************************************
+ * parsedefaultvalue : parse DefaultValue
+ *
+ * Enter: tok = next token
+ * node
+ *
+ * Return: node updated with value
+ * tok updated
+ */
+static struct node *
+parsedefaultvalue (struct tok *tok, struct node *node) {
+ char *s;
+ if (tok->type == TOK_STRING) {
+ s = memalloc(tok->len + 1);
+ memcpy(s, tok->start, tok->len);
+ s[tok->len] = 0;
+ addnode(node, newattr("stringvalue", s));
+ lexnocomment();
+ return node;
+ } else {
+ return parseconstexpr(tok, node);
+ }
+}
+
+
+
+/***********************************************************************
+ * parsedictionarymember : parse DictionaryMember
+ *
+ * Enter: tok = next token
+ * eal = 0 else extended attribute list node
+ *
+ * Return: new node
+ * tok on terminating ';'
+ */
+static struct node *
+parsedictionarymember(struct tok *tok, struct node *eal)
+{
+ struct node *node = newelement("DictionaryMember");
+ if (eal) addnode(node, eal);
+ setcommentnode(node);
+ addnode(node, parsetype(tok));
+ addnode(node, newattr("name", setidentifier(tok)));
+ tok = lexnocomment();
+ // Optional value
+ if (tok->type == '=') {
+ tok = lexnocomment();
+ node = parsedefaultvalue(tok, node);
+ }
+ return node;
+}
+
+/***********************************************************************
+ * parseconst : parse [12] Const
+ *
+ * Enter: tok = next token, known to be TOK_const
+ * eal = 0 else extended attribute list node
+ *
+ * Return: new node for the const
+ * tok on terminating ';'
+ */
+static struct node *
+parseconst(struct tok *tok, struct node *eal)
+{
+ struct node *node = newelement("Const");
+ setcommentnode(node);
+ if (eal) addnode(node, eal);
+ tok = lexnocomment();
+ switch(tok->type) {
+ case TOK_boolean:
+ case TOK_byte:
+ case TOK_octet:
+ case TOK_float:
+ case TOK_double:
+ case TOK_unsigned:
+ case TOK_unrestricted:
+ case TOK_short:
+ case TOK_long:
+ addnode(node, parsetype(tok));
+ break;
+ default:
+ tokerrorexit(tok, "expected acceptable constant type");
+ break;
+ }
+ addnode(node, newattr("name", setidentifier(tok)));
+ tok = lexnocomment();
+ eat(tok, '=');
+ node = parseconstexpr(tok, node);
+ return node;
+}
+
+/***********************************************************************
+ * parseimplementsstatement : parse [11] ImplementsStatement
+ *
+ * Enter: tok = next token, known to be :: or TOK_IDENTIFIER
+ * eal = 0 else extended attribute list node
+ *
+ * Return: new node for the typedef
+ * tok updated to the terminating ';'
+ */
+static struct node *
+parseimplementsstatement(struct tok *tok, struct node *eal)
+{
+ struct node *node = newelement("Implements");
+ setcommentnode(node);
+ if (eal) addnode(node, eal);
+ addnode(node, parsescopedname(tok, "name1", 1));
+ eat(tok, TOK_implements);
+ addnode(node, parsescopedname(tok, "name2", 1));
+ return node;
+}
+
+/***********************************************************************
+ * parsetypedef : parse [10] Typedef
+ *
+ * Enter: tok = next token, known to be TOK_typedef
+ * eal = 0 else extended attribute list node
+ *
+ * Return: new node for the typedef
+ * tok updated to the terminating ';'
+ */
+static struct node *
+parsetypedef(struct tok *tok, struct node *eal)
+{
+struct node *ealtype;
+struct node *typenode;
+ struct node *node = newelement("Typedef");
+ setcommentnode(node);
+ if (eal) addnode(node, eal);
+ tok = lexnocomment();
+ ealtype = parseextendedattributelist(tok);
+ typenode = parsetype(tok);
+ if (ealtype) addnode(typenode, ealtype);
+ addnode(node, typenode);
+ addnode(node, newattr("name", setidentifier(tok)));
+ tok = lexnocomment();
+ return node;
+}
+
+/***********************************************************************
+ * parseexception : parse [8] Exception
+ *
+ * Enter: tok = next token, known to be TOK_exception
+ * eal = 0 else extended attribute list node
+ *
+ * Return: new node for the exception
+ * tok updated to the terminating ';'
+ */
+static struct node *
+parseexception(struct tok *tok, struct node *eal)
+{
+ struct node *node = newelement("Exception");
+ setcommentnode(node);
+ if (eal) addnode(node, eal);
+ tok = lexnocomment();
+ addnode(node, newattr("name", setidentifier(tok)));
+ lexnocomment();
+ if (tok->type == ':') {
+ lexnocomment();
+ addnode(node, parsescopednamelist(tok, "ExceptionInheritance", "Name", 1));
+ }
+ eat(tok, '{');
+ while (tok->type != '}') {
+ const char *start = tok->prestart;
+ struct node *node2;
+ struct node *eal = parseextendedattributelist(tok);
+ if (tok->type == TOK_const)
+ node2 = parseconst(tok, eal);
+ else
+ node2 = parseexceptionfield(tok, eal);
+ addnode(node, node2);
+ node2->wsstart = start;
+ node2->end = tok->start + tok->len;
+ setid(node2);
+ eat(tok, ';');
+ }
+ lexnocomment();
+ return node;
+}
+
+/***********************************************************************
+ * parseinterface : parse [4] Interface
+ *
+ * Enter: tok = next token, known to be TOK_interface
+ * eal = 0 else extended attribute list node
+ *
+ * Return: new node for the interface
+ * tok updated to the terminating ';'
+ */
+static struct node *
+parseinterface(struct tok *tok, struct node *eal)
+{
+ struct node *node = newelement("Interface");
+ if (eal) addnode(node, eal);
+ setcommentnode(node);
+ tok = lexnocomment();
+ addnode(node, newattr("name", setidentifier(tok)));
+ tok = lexnocomment();
+ if (tok->type == ':') {
+ lexnocomment();
+ addnode(node, parsescopednamelist(tok, "InterfaceInheritance", "Name", 1));
+ }
+ eat(tok, '{');
+ while (tok->type != '}') {
+ const char *start = tok->prestart;
+ struct node *eal = parseextendedattributelist(tok);
+ struct node *node2;
+ if (tok->type == TOK_const)
+ addnode(node, node2 = parseconst(tok, eal));
+ else
+ addnode(node, node2 = parseattributeoroperationoriterator(tok, eal));
+ node2->wsstart = start;
+ node2->end = tok->start + tok->len;
+ setid(node2);
+ eat(tok, ';');
+ }
+ lexnocomment();
+ return node;
+}
+
+/***********************************************************************
+ * parsecallback : parse Callback
+ *
+ * Enter: tok = next token, known to be TOK_dictionary
+ * eal = 0 else extended attribute list node
+ *
+ * Return: new node for the enum
+ * tok updated to the terminating ';'
+ */
+static struct node *
+parsecallback(struct tok *tok, struct node *eal)
+{
+ struct node *node;
+ if (tok->type == TOK_interface) {
+ node = parseinterface(tok, eal);
+ addnode(node, newattr("callback", "callback"));
+ } else {
+ node = newelement("Callback");
+ if (eal) addnode(node, eal);
+ setcommentnode(node);
+ addnode(node, newattr("name", setidentifier(tok)));
+ tok = lexnocomment();
+ eat(tok, '=');
+ addnode(node, parsereturntype(tok));
+ eat(tok, '(');
+ addnode(node, parseargumentlist(tok));
+ eat(tok, ')');
+ }
+ return node;
+}
+
+/***********************************************************************
+ * parsedictionary : parse Dictionary
+ *
+ * Enter: tok = next token, known to be TOK_dictionary
+ * eal = 0 else extended attribute list node
+ *
+ * Return: new node for the dictionary
+ * tok updated to the terminating ';'
+ */
+static struct node *
+parsedictionary(struct tok *tok, struct node *eal)
+{
+ struct node *node = newelement("Dictionary");
+ if (eal) addnode(node, eal);
+ setcommentnode(node);
+ tok = lexnocomment();
+ addnode(node, newattr("name", setidentifier(tok)));
+ tok = lexnocomment();
+ if (tok->type == ':') {
+ lexnocomment();
+ addnode(node, parsescopednamelist(tok, "DictionaryInheritance", "Name", 1));
+ }
+ eat(tok, '{');
+ while (tok->type != '}') {
+ const char *start = tok->prestart;
+ struct node *eal = parseextendedattributelist(tok);
+ struct node *node2;
+ if (tok->type == TOK_const)
+ addnode(node, node2 = parseconst(tok, eal));
+ else
+ addnode(node, node2 = parsedictionarymember(tok, eal));
+ node2->wsstart = start;
+ node2->end = tok->start + tok->len;
+ setid(node2);
+ eat(tok, ';');
+ }
+ lexnocomment();
+ return node;
+}
+
+/***********************************************************************
+ * parseenum : parse Enum
+ *
+ * Enter: tok = next token, known to be TOK_dictionary
+ * eal = 0 else extended attribute list node
+ *
+ * Return: new node for the enum
+ * tok updated to the terminating ';'
+ */
+static struct node *
+parseenum(struct tok *tok, struct node *eal)
+{
+ char *s;
+ struct node *node = newelement("Enum");
+ if (eal) addnode(node, eal);
+ setcommentnode(node);
+ tok = lexnocomment();
+ addnode(node, newattr("name", setidentifier(tok)));
+ tok = lexnocomment();
+ eat(tok, '{');
+ while (tok->type != '}') {
+ if (tok->type == TOK_STRING) {
+ const char *start = tok->prestart;
+ struct node *node2 = newelement("EnumValue");
+ setcommentnode(node2);
+
+ s = memalloc(tok->len + 1);
+ memcpy(s, tok->start, tok->len);
+ s[tok->len] = 0;
+ addnode(node2, newattr("stringvalue", s));
+ node2->wsstart = start;
+ node2->end = tok->start + tok->len;
+ setid(node2);
+ addnode(node, node2);
+ } else {
+ tokerrorexit(tok, "expected string in enum");
+ }
+ lexnocomment();
+ if (tok->type == ',') {
+ lexnocomment();
+ }
+ }
+ eat(tok, '}');
+ return node;
+}
+
+/***********************************************************************
+ * parsedefinitions : parse [1] Definitions
+ *
+ * Enter: tok = next token
+ * parent = parent node to add definitions to
+ *
+ * On return, tok has been updated.
+ */
+static void
+parsedefinitions(struct tok *tok, struct node *parent)
+{
+ parent->wsstart = tok->prestart;
+ for (;;) {
+ const char *wsstart = tok->prestart;
+ struct node *eal = parseextendedattributelist(tok);
+ struct node *node;
+ switch (tok->type) {
+ case TOK_partial:
+ eat(tok, TOK_partial);
+ if (tok->type == TOK_dictionary) {
+ node = parsedictionary(tok, eal);
+ } else {
+ node = parseinterface(tok, eal);
+ }
+ addnode(node, newattr("partial", "partial"));
+ break;
+ case TOK_interface:
+ node = parseinterface(tok, eal);
+ break;
+ case TOK_callback:
+ eat(tok, TOK_callback);
+ node = parsecallback(tok, eal);
+ break;
+ case TOK_dictionary:
+ node = parsedictionary(tok, eal);
+ break;
+ case TOK_enum:
+ node = parseenum(tok, eal);
+ break;
+ case TOK_exception:
+ node = parseexception(tok, eal);
+ break;
+ case TOK_typedef:
+ node = parsetypedef(tok, eal);
+ break;
+ case TOK_IDENTIFIER:
+ node = parseimplementsstatement(tok, eal);
+ break;
+ default:
+ if (eal)
+ tokerrorexit(tok, "expected definition after extended attribute list");
+ node = 0;
+ break;
+ }
+ if (!node)
+ break;
+ node->wsstart = wsstart;
+ node->end = tok->start + tok->len;
+ eat(tok, ';');
+ addnode(parent, node);
+ setid(node);
+ parent->end = node->end;
+ }
+}
+
+/***********************************************************************
+ * parse
+ *
+ * Return: root element containing (possibly empty) list of definitions
+ */
+struct node *
+parse(void)
+{
+ struct tok *tok;
+ struct node *root = newelement("Definitions");
+ setcommentnode(root);
+ tok = lexnocomment();
+ parsedefinitions(tok, root);
+ if (tok->type != TOK_EOF)
+ tokerrorexit(tok, "expected end of input");
+ reversechildren(root);
+ return root;
+}
+
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/parse.h b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/parse.h
new file mode 100644
index 00000000000..ad9071b453e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/parse.h
@@ -0,0 +1,19 @@
+/***********************************************************************
+ * $Id$
+ * Copyright 2009 Aplix Corporation. All rights reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ***********************************************************************/
+#ifndef parse_h
+#define parse_h
+
+struct node *parse(void);
+
+#endif /* ndef parse_h */
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/process.c b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/process.c
new file mode 100644
index 00000000000..d6a343b8aa0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/process.c
@@ -0,0 +1,319 @@
+/***********************************************************************
+ * $Id$
+ * Copyright 2009 Aplix Corporation. All rights reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ***********************************************************************/
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include "comment.h"
+#include "lex.h"
+#include "misc.h"
+#include "node.h"
+#include "os.h"
+#include "parse.h"
+#include "process.h"
+
+#if 0
+static const char ntnames[] = { NTNAMES };
+#endif /*0*/
+
+/***********************************************************************
+ * printtext : print text with xml entity escapes
+ *
+ * Enter: s = text
+ * len = number of bytes
+ * escamp = whether to escape &
+ *
+ * This also escapes double quote mark so it can be used for an
+ * attribute value. It also turns a tab into spaces.
+ */
+void
+printtext(const char *s, unsigned int len, int escamp)
+{
+ const char *p = s, *end = s + len;
+ unsigned int count = 0;
+ while (p != end) {
+ int ch = *p;
+ char buf[9];
+ const char *seq = 0;
+ count++;
+ switch (ch) {
+ case '<':
+ seq = "&lt;";
+ break;
+ case '&':
+ seq = escamp ? "&amp;" : "&";
+ break;
+ case '"':
+ seq = "&quot;";
+ break;
+ case '\n':
+ p++;
+ count = 0;
+ continue;
+ case '\t':
+ seq = " " + ((count - 1) & 7);
+ count = 0;
+ break;
+ default:
+ if ((unsigned char)ch >= 0x20) {
+ p++;
+ continue;
+ }
+ snprintf(buf, 9, "&#%i;", ch);
+ seq = buf;
+ break;
+ }
+ if (p - s != fwrite(s, 1, p - s, stdout))
+ errorexit("write error");
+ fputs(seq, stdout);
+ s = ++p;
+ }
+ if (p - s != fwrite(s, 1, p - s, stdout))
+ errorexit("write error");
+}
+
+#if 0
+/***********************************************************************
+ * outputnodeastext : output parse node and descendants as deparsed text
+ *
+ * Enter: node = parse node
+ * needspace = true if last output char was an identifier char
+ *
+ * Return: updated needspace value
+ */
+static int
+outputnodeastext(struct node *node, int needspace)
+{
+ if (node->type >= NT_START) {
+ struct node *child = node->children;
+ while (child) {
+ needspace = outputnodeastext(child, needspace);
+ child = child->next;
+ }
+ } else {
+ unsigned int len = strlen(node->name);
+ if (len) {
+ int ch = node->name[0];
+ if (ch == '_' || ((unsigned)(ch - '0') < 10
+ || (unsigned)((ch & ~0x20) - 'A') < 26))
+ {
+ if (needspace) putchar(' ');
+ }
+ ch = node->name[len - 1];
+ if (ch == '_' || ((unsigned)(ch - '0') < 10
+ || (unsigned)((ch & ~0x20) - 'A') < 26))
+ {
+ needspace = 1;
+ }
+ printtext(node->name, len, 1);
+ }
+ }
+ return needspace;
+}
+
+/***********************************************************************
+ * printfqid : print fully-qualified id
+ *
+ * Enter: node struct
+ *
+ * Return: whether anything printed
+ */
+static int
+printfqid(struct node *node)
+{
+ int any = 0;
+ struct node *identifier;
+ if (node->parent) {
+ any = printfqid(node->parent);
+ }
+ switch (node->type) {
+ case NT_Module:
+ case NT_Interface:
+ case NT_Typedef:
+ case NT_Operation:
+ case NT_Attribute:
+ case NT_Const:
+ if (any)
+ printf(":");
+ /* Find identifier child if any. */
+ identifier = node->children;
+ while (identifier) {
+ if (identifier->type == TOK_IDENTIFIER)
+ break;
+ if (identifier->type == NT_TypedefRest) {
+ identifier = identifier->children;
+ continue;
+ }
+ identifier = identifier->next;
+ }
+ if (identifier) {
+ printtext(identifier->name, strlen(identifier->name), 1);
+ any = 1;
+ }
+ break;
+ }
+ return any;
+}
+
+/***********************************************************************
+ * output : output subtree of parse tree
+ *
+ * Enter: node = root of subtree
+ * extendedattributelist = 0 else extended attribute list node
+ * applying to node
+ * indent = indent (nesting) level
+ */
+static void outputchildren(struct node *node, struct node *identifier, unsigned int indent);
+
+static void
+output(struct node *node, struct node *extendedattributelist,
+ unsigned int indent)
+{
+ if (extendedattributelist) {
+ node->wsstart = extendedattributelist->wsstart;
+ node->start = extendedattributelist->start;
+ }
+ if (node->type == NT_ExtendedAttribute) {
+ printf("%*s<ExtendedAttribute value=\"", indent, "");
+ outputnodeastext(node, 0);
+ printf("\"/>\n");
+ } else if (node->type == NT_BooleanLiteral) {
+ printf("%*s<BooleanLiteral value=\"%s\"/>", indent, "",
+ node->children->name);
+ } else if (node->type == NT_ReadOnly) {
+ printf("%*s<ReadOnly/>\n", indent, "");
+ } else if (node->type >= NT_START) {
+ const char *ntname;
+ /* Find identifier child if any. */
+ struct node *identifier = node->children;
+ while (identifier) {
+ if (identifier->type == TOK_IDENTIFIER)
+ break;
+ identifier = identifier->next;
+ }
+ /* Find nonterminal name. */
+ ntname = ntnames + 2;
+ while (node->type - NT_START != ((unsigned char)ntname[-2] | (unsigned char)ntname[-1] << 8))
+ ntname += strlen(ntname) + 3;
+ /* Output start of element. */
+ printf("%*s<%s", indent, "", ntname);
+ /* Output identifier if any as attribute. */
+ if (identifier) {
+ printf(" identifier=\"");
+ printtext(identifier->name, strlen(identifier->name), 1);
+ printf("\"");
+ }
+ switch (node->type) {
+ case NT_Module:
+ case NT_Interface:
+ case NT_Typedef:
+ case NT_Const:
+ /* Output fully qualified id. */
+ printf(" fqid=\"");
+ printfqid(node);
+ printf("\"");
+ break;
+ }
+ if (!identifier && !extendedattributelist && !node->children && !node->comments)
+ printf("/>\n");
+ else {
+ printf(">\n");
+ /* Output descriptive elements (doxygen comments) for node. */
+ outputdescriptive(node, indent + 2);
+ /* Output descriptive elements (doxygen comments) for identifier. */
+ if (identifier)
+ outputdescriptive(identifier, indent + 2);
+ /* Output extended attribute list. */
+ if (extendedattributelist)
+ output(extendedattributelist, 0, indent + 2);
+ /* Output children (excluding identifier child). */
+ outputchildren(node, identifier, indent + 2);
+ printf("%*s</%s>\n", indent, "", ntname);
+ }
+ } else switch (node->type) {
+ case TOK_DOMString:
+ case TOK_any:
+ case TOK_boolean:
+ case TOK_octet:
+ case TOK_float:
+ case TOK_double:
+ case TOK_Object:
+ case TOK_unsigned:
+ case TOK_short:
+ case TOK_long:
+ case TOK_void:
+ printf("%*s<%s/>\n", indent, "", node->name);
+ break;
+ case TOK_INTEGER:
+ printf("%*s<integer value=\"", indent, "");
+ printtext(node->name, strlen(node->name), 1);
+ printf("\"/>\n");
+ break;
+ case TOK_FLOAT:
+ printf("%*s<Float value=\"", indent, "");
+ printtext(node->name, strlen(node->name), 1);
+ printf("\"/>\n");
+ break;
+ case TOK_STRING:
+ printf("%*s<string value=\"", indent, "");
+ printtext(node->name, strlen(node->name), 1);
+ printf("\"/>\n");
+ break;
+ }
+}
+
+/***********************************************************************
+ * outputchildren : call output for each child of node
+ *
+ * Enter: node
+ * identifier = child node to omit from output
+ * indent = indent (nesting) level
+ */
+static void
+outputchildren(struct node *node, struct node *identifier, unsigned int indent)
+{
+ struct node *extendedattributelist;
+ struct node *child;
+ child = node->children;
+ extendedattributelist = 0;
+ while (child) {
+ if (child->type == NT_ExtendedAttributeList && node->type != NT_Argument)
+ extendedattributelist = child;
+ else {
+ if (identifier != child)
+ output(child, extendedattributelist, indent);
+ extendedattributelist = 0;
+ }
+ child = child->next;
+ }
+}
+#endif /*0*/
+
+/***********************************************************************
+ * processfiles : process input files
+ *
+ * Enter: name = filename
+ */
+void
+processfiles(const char *const *names, int dtdref)
+{
+ struct node *root;
+ readinput(names);
+ root = parse();
+ processcomments(root);
+ printf("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
+ if(dtdref)
+ printf("<!DOCTYPE Definitions SYSTEM \"widlprocxml.dtd\">\n");
+ outputnode(root, 0);
+}
+
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/process.h b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/process.h
new file mode 100644
index 00000000000..bb92b22ce13
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/process.h
@@ -0,0 +1,27 @@
+/***********************************************************************
+ * $Id$
+ * Copyright 2009 Aplix Corporation. All rights reserved.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ***********************************************************************/
+#ifndef process_h
+#define process_h
+
+#if 0
+#define NT_START 0x100
+#include "nonterminals.h"
+#endif/*0*/
+
+void printtext(const char *s, unsigned int len, int escamp);
+
+void processfiles(const char *const *names, int dtdref);
+
+#endif /* ndef process_h */
+
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/widlprocxmltohtml.xsl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/widlprocxmltohtml.xsl
new file mode 100644
index 00000000000..2b583371e7d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/src/widlprocxmltohtml.xsl
@@ -0,0 +1,828 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--====================================================================
+$Id: widlprocxmltohtml.xsl 407 2009-10-26 13:48:48Z tpr $
+Copyright 2009 Aplix Corporation. All rights reserved.
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+XSLT stylesheet to convert widlprocxml into html documentation.
+=====================================================================-->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+<xsl:output method="html" encoding="utf-8" indent="yes" doctype-public="html"/>
+
+<xsl:param name="date" select="'error: missing date'"/>
+
+<xsl:variable name="title" select="concat('The ',/Definitions/descriptive/name,' Module - Version ',/Definitions/descriptive/version)"/>
+
+<!--Root of document.-->
+<xsl:template match="/">
+ <html>
+ <head>
+ <link rel="stylesheet" type="text/css" href="widlhtml.css" media="screen"/>
+ <title>
+ <xsl:value-of select="$title"/>
+ </title>
+ </head>
+ <body>
+ <xsl:apply-templates/>
+ </body>
+ </html>
+</xsl:template>
+
+<!--Root of Definitions.-->
+<xsl:template match="Definitions">
+ <div class="api" id="{@id}">
+ <a href="http://bondi.omtp.org"><img src="http://www.omtp.org/images/BondiSmall.jpg" alt="Bondi logo"/></a>
+ <h1><xsl:value-of select="$title"/></h1>
+ <h3>12 May 2009</h3>
+
+ <h2>Authors</h2>
+ <ul class="authors">
+ <xsl:apply-templates select="descriptive/author"/>
+ </ul>
+
+ <p class="copyright"><small>© The authors, 2012. All rights reserved.</small></p>
+
+ <hr/>
+
+ <h2>Abstract</h2>
+
+ <xsl:apply-templates select="descriptive/brief"/>
+ <xsl:apply-templates select="descriptive/description"/>
+ <xsl:apply-templates select="descriptive/Code"/>
+
+ <h2>Table of Contents</h2>
+ <ul class="toc">
+ <li><a href="#intro">Introduction</a>
+ <ul>
+ <xsl:if test="descriptive/def-api-feature-set">
+ <li><a href="#def-api-feature-sets">Feature set</a></li>
+ </xsl:if>
+ <xsl:if test="descriptive/def-api-feature">
+ <li><a href="#def-api-features">Features</a></li>
+ </xsl:if>
+ <xsl:if test="descriptive/def-device-cap">
+ <li><a href="#def-device-caps">Device Capabilities</a></li>
+ </xsl:if>
+ </ul>
+ </li>
+ <xsl:if test="Typedef">
+ <li><a href="#typedefs">Type Definitions</a>
+ <ul class="toc">
+ <xsl:for-each select="Typedef[descriptive]">
+ <li><a href="#{@id}"><code><xsl:value-of select="@name"/></code></a></li>
+ </xsl:for-each>
+ </ul>
+ </li>
+ </xsl:if>
+ <xsl:if test="Interface">
+ <li><a href="#interfaces">Interfaces</a>
+ <ul class="toc">
+ <xsl:for-each select="Interface[descriptive]">
+ <li><a href="#{@id}"><code><xsl:value-of select="@name"/></code></a></li>
+ </xsl:for-each>
+ </ul>
+ </li>
+ </xsl:if>
+ <xsl:if test="Dictionary">
+ <li><a href="#dictionaries">Dictionary types</a>
+ <ul class="toc">
+ <xsl:for-each select="Dictionary[descriptive]">
+ <li><a href="#{@id}"><code><xsl:value-of select="@name"/></code></a></li>
+ </xsl:for-each>
+ </ul>
+ </li>
+ </xsl:if>
+ <xsl:if test="Callback">
+ <li><a href="#callbacks">Callbacks</a>
+ <ul class="toc">
+ <xsl:for-each select="Callback[descriptive]">
+ <li><a href="#{@id}"><code><xsl:value-of select="@name"/></code></a></li>
+ </xsl:for-each>
+ </ul>
+ </li>
+ </xsl:if>
+ <xsl:if test="Enum">
+ <li><a href="#enums">Enums</a>
+ <ul class="toc">
+ <xsl:for-each select="Enum[descriptive]">
+ <li><a href="#{@id}"><code><xsl:value-of select="@name"/></code></a></li>
+ </xsl:for-each>
+ </ul>
+ </li>
+ </xsl:if>
+ </ul>
+
+ <hr/>
+
+ <h2>Summary of Methods</h2>
+ <xsl:call-template name="summary"/>
+
+ <h2 id="intro">Introduction</h2>
+
+ <xsl:apply-templates select="descriptive/description"/>
+ <xsl:apply-templates select="descriptive/Code"/>
+
+ <xsl:if test="descriptive/def-api-feature-set">
+ <div id="def-api-feature-sets" class="def-api-feature-sets">
+ <h3 id="features">Feature set</h3>
+ <p>This is the URI used to declare this API's feature set, for use in bondi.requestFeature. For the URL, the list of features included by the feature set is provided.</p>
+ <xsl:apply-templates select="descriptive/def-api-feature-set"/>
+ </div>
+ </xsl:if>
+ <xsl:if test="descriptive/def-api-feature">
+ <div id="def-api-features" class="def-api-features">
+ <h3 id="features">Features</h3>
+ <p>This is the list of URIs used to declare this API's features, for use in bondi.requestFeature. For each URL, the list of functions covered is provided.</p>
+ <xsl:apply-templates select="Interface/descriptive/def-instantiated"/>
+ <xsl:apply-templates select="descriptive/def-api-feature"/>
+ </div>
+ </xsl:if>
+ <xsl:if test="descriptive/def-device-cap">
+ <div class="def-device-caps" id="def-device-caps">
+ <h3>Device capabilities</h3>
+ <dl>
+ <xsl:apply-templates select="descriptive/def-device-cap"/>
+ </dl>
+ </div>
+ </xsl:if>
+ <xsl:if test="Typedef">
+ <div class="typedefs" id="typedefs">
+ <h2>Type Definitions</h2>
+ <xsl:apply-templates select="Typedef[descriptive]"/>
+ </div>
+ </xsl:if>
+ <xsl:if test="Interface">
+ <div class="interfaces" id="interfaces">
+ <h2>Interfaces</h2>
+ <xsl:apply-templates select="Interface"/>
+ </div>
+ </xsl:if>
+ <xsl:if test="Dictionary">
+ <div class="dictionaries" id="dictionaries">
+ <h2>Dictionary types</h2>
+ <xsl:apply-templates select="Dictionary"/>
+ </div>
+ </xsl:if>
+ <xsl:if test="Callback">
+ <div class="callbacks" id="callbacks">
+ <h2>Callbacks</h2>
+ <xsl:apply-templates select="Callback"/>
+ </div>
+ </xsl:if>
+ <xsl:if test="Enum">
+ <div class="enums" id="enums">
+ <h2>Enums</h2>
+ <xsl:apply-templates select="Enum"/>
+ </div>
+ </xsl:if>
+ </div>
+</xsl:template>
+
+<!--def-api-feature-set-->
+<xsl:template match="def-api-feature-set">
+ <dl class="def-api-feature-set">
+ <dt><xsl:value-of select="@identifier"/></dt>
+ <dd>
+ <xsl:apply-templates select="descriptive/brief"/>
+ <xsl:apply-templates select="descriptive"/>
+ <xsl:apply-templates select="descriptive/Code"/>
+ <xsl:if test="descriptive/api-feature">
+ <div class="api-features">
+ <p>
+ Includes API features:
+ </p>
+ <ul>
+ <xsl:for-each select="descriptive/api-feature">
+ <li><code><xsl:value-of select="@identifier"/></code></li>
+ </xsl:for-each>
+ </ul>
+ </div>
+ </xsl:if>
+ </dd>
+ </dl>
+</xsl:template>
+
+<!--def-api-feature-->
+<xsl:template match="def-api-feature">
+ <dl class="def-api-feature">
+ <dt><xsl:value-of select="@identifier"/></dt>
+ <dd>
+ <xsl:apply-templates select="descriptive/brief"/>
+ <xsl:apply-templates select="descriptive"/>
+ <xsl:apply-templates select="descriptive/Code"/>
+ <xsl:if test="descriptive/device-cap">
+ <div class="device-caps">
+ <p>
+ Device capabilities:
+ </p>
+ <ul>
+ <xsl:for-each select="descriptive/device-cap">
+ <li><code><xsl:value-of select="@identifier"/></code></li>
+ </xsl:for-each>
+ </ul>
+ </div>
+ </xsl:if>
+ </dd>
+ </dl>
+</xsl:template>
+
+<!--def-device-cap-->
+<xsl:template match="def-device-cap">
+ <dt class="def-device-cap"><code><xsl:value-of select="@identifier"/></code></dt>
+ <dd>
+ <xsl:apply-templates select="descriptive/brief"/>
+ <xsl:apply-templates select="descriptive"/>
+ <xsl:apply-templates select="descriptive/Code"/>
+ <xsl:if test="descriptive/param">
+ <div class="device-caps">
+ <p>Security parameters:</p>
+ <ul>
+ <xsl:apply-templates select="descriptive/param"/>
+ </ul>
+ </div>
+ </xsl:if>
+ </dd>
+</xsl:template>
+
+<!--Exception: not implemented-->
+<!--Valuetype: not implemented-->
+<xsl:template match="Exception|Valuetype|Const">
+ <xsl:if test="descriptive">
+ <xsl:message terminate="yes">element <xsl:value-of select="name()"/> not supported</xsl:message>
+ </xsl:if>
+</xsl:template>
+
+<!--Typedef.-->
+<xsl:template match="Typedef[descriptive]">
+ <div class="typedef" id="{@id}">
+ <h3>2.<xsl:number value="position()"/>. <code><xsl:value-of select="@name"/></code></h3>
+ <xsl:apply-templates select="descriptive/brief"/>
+ <xsl:apply-templates select="webidl"/>
+ <xsl:apply-templates select="descriptive"/>
+ <xsl:apply-templates select="descriptive/Code"/>
+ </div>
+</xsl:template>
+
+<!--Interface.-->
+<xsl:template match="Interface[descriptive]">
+ <xsl:variable name="name" select="@name"/>
+ <div class="interface" id="{@id}">
+ <h3><code><xsl:value-of select="@name"/></code></h3>
+ <xsl:apply-templates select="descriptive/brief"/>
+ <xsl:apply-templates select="webidl"/>
+ <xsl:apply-templates select="../Implements[@name2=$name]/webidl"/>
+ <xsl:apply-templates select="descriptive"/>
+ <xsl:apply-templates select="descriptive/Code"/>
+ <xsl:apply-templates select="InterfaceInheritance"/>
+ <xsl:if test="Const/descriptive">
+ <div class="consts">
+ <h4>Constants</h4>
+ <dl>
+ <xsl:apply-templates select="Const"/>
+ </dl>
+ </div>
+ </xsl:if>
+ <xsl:if test="ExtendedAttributeList/ExtendedAttribute/descriptive">
+ <div class="constructors">
+ <h4>Constructors</h4>
+ <dl>
+ <xsl:apply-templates select="ExtendedAttributeList/ExtendedAttribute"/>
+ </dl>
+ </div>
+ </xsl:if>
+ <xsl:if test="Attribute/descriptive">
+ <div class="attributes">
+ <h4>Attributes</h4>
+ <dl>
+ <xsl:apply-templates select="Attribute"/>
+ </dl>
+ </div>
+ </xsl:if>
+ <xsl:if test="Operation/descriptive">
+ <div class="methods">
+ <h4>Methods</h4>
+ <dl>
+ <xsl:apply-templates select="Operation"/>
+ </dl>
+ </div>
+ </xsl:if>
+ </div>
+</xsl:template>
+<xsl:template match="Interface[not(descriptive)]">
+</xsl:template>
+
+<!--Dictionary.-->
+<xsl:template match="Dictionary[descriptive]">
+ <xsl:variable name="name" select="@name"/>
+ <div class="dictionary" id="{@id}">
+ <h3><code><xsl:value-of select="@name"/></code></h3>
+ <xsl:apply-templates select="descriptive/brief"/>
+ <xsl:apply-templates select="webidl"/>
+ <xsl:apply-templates select="descriptive"/>
+ <xsl:apply-templates select="descriptive/Code"/>
+ <xsl:apply-templates select="InterfaceInheritance"/>
+ <xsl:if test="Const/descriptive">
+ <div class="consts">
+ <h4>Constants</h4>
+ <dl>
+ <xsl:apply-templates select="Const"/>
+ </dl>
+ </div>
+ </xsl:if>
+ <xsl:if test="Attribute/descriptive">
+ <div class="attributes">
+ <h4>Attributes</h4>
+ <dl>
+ <xsl:apply-templates select="Attribute"/>
+ </dl>
+ </div>
+ </xsl:if>
+ </div>
+</xsl:template>
+<xsl:template match="Dictionary[not(descriptive)]">
+</xsl:template>
+
+<xsl:template match="InterfaceInheritance/ScopedNameList">
+ <p>
+ <xsl:text>This interface inherits from: </xsl:text>
+ <xsl:for-each select="Name">
+ <code><xsl:value-of select="@name"/></code>
+ <xsl:if test="position!=last()">, </xsl:if>
+ </xsl:for-each>
+ </p>
+</xsl:template>
+
+<!--Attribute-->
+<xsl:template match="Attribute">
+ <dt class="attribute" id="{@name}">
+ <code>
+ <xsl:if test="@stringifier">
+ stringifier
+ </xsl:if>
+ <xsl:if test="@readonly">
+ readonly
+ </xsl:if>
+ <xsl:apply-templates select="Type"/>
+ <xsl:text> </xsl:text>
+ <xsl:value-of select="@name"/>
+ </code></dt>
+ <dd>
+ <xsl:apply-templates select="descriptive/brief"/>
+ <xsl:apply-templates select="descriptive"/>
+ <xsl:apply-templates select="GetRaises"/>
+ <xsl:apply-templates select="SetRaises"/>
+ <xsl:apply-templates select="descriptive/Code"/>
+ </dd>
+</xsl:template>
+
+<!--Const-->
+<xsl:template match="Const">
+ <dt class="const" id="{@id}">
+ <code>
+ <xsl:apply-templates select="Type"/>
+ <xsl:text> </xsl:text>
+ <xsl:value-of select="@name"/>
+ </code>
+ </dt>
+ <dd>
+ <xsl:apply-templates select="descriptive/brief"/>
+ <xsl:apply-templates select="descriptive"/>
+ <xsl:apply-templates select="descriptive/Code"/>
+ </dd>
+</xsl:template>
+
+<!--ExtendedAttribute name==Constructor || name==NamedConstructor-->
+<xsl:template match="ExtendedAttributeList/ExtendedAttribute">
+ <dt class="constructor" id="{concat(@name,generate-id(.))}">
+ <code>
+ <xsl:value-of select="../../@name"/>
+ <xsl:text>(</xsl:text>
+ <xsl:apply-templates select="ArgumentList">
+ <xsl:with-param name="nodesc" select="1"/>
+ </xsl:apply-templates>
+ <xsl:text>);</xsl:text>
+ </code>
+ </dt>
+ <dd>
+ <xsl:apply-templates select="descriptive/brief"/>
+ <xsl:apply-templates select="descriptive"/>
+ <xsl:apply-templates select="ArgumentList"/>
+ <xsl:apply-templates select="Raises"/>
+ <xsl:if test="descriptive/api-feature">
+ <div class="api-features">
+ <h6>API features</h6>
+ <dl>
+ <xsl:apply-templates select="descriptive/api-feature"/>
+ </dl>
+ </div>
+ </xsl:if>
+ <xsl:apply-templates select="webidl"/>
+ <xsl:apply-templates select="descriptive/Code"/>
+ </dd>
+</xsl:template>
+
+<!--Operation-->
+<xsl:template match="Operation">
+ <dt class="method" id="{concat(@name,generate-id(.))}">
+ <code>
+ <xsl:if test="@stringifier">
+ <xsl:value-of select="concat(@stringifier, ' ')"/>
+ </xsl:if>
+ <xsl:if test="@omittable">
+ <xsl:value-of select="concat(@omittable, ' ')"/>
+ </xsl:if>
+ <xsl:if test="@getter">
+ <xsl:value-of select="concat(@getter, ' ')"/>
+ </xsl:if>
+ <xsl:if test="@setter">
+ <xsl:value-of select="concat(@setter, ' ')"/>
+ </xsl:if>
+ <xsl:if test="@creator">
+ <xsl:value-of select="concat(@creator, ' ')"/>
+ </xsl:if>
+ <xsl:if test="@deleter">
+ <xsl:value-of select="concat(@deleter, ' ')"/>
+ </xsl:if>
+ <xsl:if test="@caller">
+ <xsl:value-of select="concat(@caller, ' ')"/>
+ </xsl:if>
+ <xsl:apply-templates select="Type"/>
+ <xsl:text> </xsl:text>
+ <xsl:value-of select="@name"/>
+ <xsl:text>(</xsl:text>
+ <xsl:apply-templates select="ArgumentList">
+ <xsl:with-param name="nodesc" select="1"/>
+ </xsl:apply-templates>
+ <xsl:text>);</xsl:text>
+ </code>
+ </dt>
+ <dd>
+ <xsl:apply-templates select="descriptive/brief"/>
+ <xsl:apply-templates select="webidl"/>
+ <xsl:apply-templates select="descriptive/Code"/>
+ <xsl:apply-templates select="descriptive"/>
+ <xsl:apply-templates select="ArgumentList"/>
+ <xsl:if test="Type/descriptive">
+ <div class="returntype">
+ <h5>Return value</h5>
+ <xsl:apply-templates select="Type/descriptive"/>
+ </div>
+ </xsl:if>
+ <xsl:apply-templates select="Raises"/>
+ <xsl:if test="descriptive/api-feature">
+ <div class="api-features">
+ <h6>API features</h6>
+ <dl>
+ <xsl:apply-templates select="descriptive/api-feature"/>
+ </dl>
+ </div>
+ </xsl:if>
+ <xsl:apply-templates select="descriptive/Code"/>
+ </dd>
+</xsl:template>
+
+<!--Callback-->
+<xsl:template match="Callback">
+ <xsl:variable name="name" select="@name"/>
+ <div class="callback" id="{@id}">
+ <h3><code><xsl:value-of select="@name"/></code></h3>
+
+ <dd>
+ <xsl:apply-templates select="descriptive/brief"/>
+ <xsl:apply-templates select="webidl"/>
+ <xsl:apply-templates select="descriptive"/>
+ <div class="synopsis">
+ <h6>Signature</h6>
+ <pre>
+ <xsl:apply-templates select="Type"/>
+ <xsl:text> </xsl:text>
+ <xsl:value-of select="@name"/>
+ <xsl:text>(</xsl:text>
+ <xsl:apply-templates select="ArgumentList">
+ <xsl:with-param name="nodesc" select="1"/>
+ </xsl:apply-templates>
+ <xsl:text>);
+</xsl:text></pre>
+ </div>
+ <xsl:apply-templates select="descriptive"/>
+ <xsl:apply-templates select="ArgumentList"/>
+ <xsl:if test="Type/descriptive">
+ <div class="returntype">
+ <h5>Return value</h5>
+ <xsl:apply-templates select="Type/descriptive"/>
+ </div>
+ </xsl:if>
+ <xsl:apply-templates select="descriptive/Code"/>
+ </dd>
+ </div>
+</xsl:template>
+
+<!--ArgumentList. This is passed $nodesc=true to output just the argument
+ types and names, and not any documentation for them.-->
+<xsl:template match="ArgumentList">
+ <xsl:param name="nodesc"/>
+ <xsl:choose>
+ <xsl:when test="$nodesc">
+ <!--$nodesc is true: just output the types and names-->
+ <xsl:apply-templates select="Argument[1]">
+ <xsl:with-param name="nodesc" select="'nocomma'"/>
+ </xsl:apply-templates>
+ <xsl:apply-templates select="Argument[position() != 1]">
+ <xsl:with-param name="nodesc" select="'comma'"/>
+ </xsl:apply-templates>
+ </xsl:when>
+ <xsl:when test="Argument">
+ <!--$nodesc is false: output the documentation-->
+ <div class="parameters">
+ <h6>Parameters</h6>
+ <ul>
+ <xsl:apply-templates/>
+ </ul>
+ </div>
+ </xsl:when>
+ </xsl:choose>
+</xsl:template>
+
+<!--Argument. This is passed $nodesc=false to output the documentation,
+ or $nodesc="nocomma" to output the type and name, or $nodesc="comma"
+ to output a comma then the type and name. -->
+<xsl:template match="Argument">
+ <xsl:param name="nodesc"/>
+ <xsl:choose>
+ <xsl:when test="$nodesc">
+ <!--$nodesc is true: just output the types and names-->
+ <xsl:if test="$nodesc = 'comma'">
+ <!--Need a comma first.-->
+ <xsl:text>, </xsl:text>
+ </xsl:if>
+ <xsl:if test="@in"><xsl:value-of select="concat(@in, ' ')"/></xsl:if>
+ <xsl:if test="@optional"><xsl:value-of select="concat(@optional, ' ')"/></xsl:if>
+ <xsl:apply-templates select="Type"/>
+ <xsl:if test="@ellipsis"><xsl:text>...</xsl:text></xsl:if>
+ <xsl:text> </xsl:text>
+ <xsl:value-of select="@name"/>
+ <xsl:if test="@value">
+ <xsl:text>Default value: </xsl:text><xsl:value-of select="@value"/>
+ </xsl:if>
+ <xsl:if test="@stringvalue">
+ <xsl:text>Default value: "</xsl:text><xsl:value-of select="@stringvalue"/><xsl:text>"</xsl:text>
+ </xsl:if>
+ </xsl:when>
+ <xsl:otherwise>
+ <!--$nodesc is false: output the documentation-->
+ <li class="param">
+ <xsl:value-of select="@name"/>:
+ <xsl:apply-templates select="descriptive"/>
+ </li>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+<!--Raises (for an Operation). It is already known that the list
+ is not empty.-->
+<xsl:template match="Raises">
+ <div class="exceptionlist">
+ <h5>Exceptions</h5>
+ <ul>
+ <xsl:apply-templates/>
+ </ul>
+ </div>
+</xsl:template>
+
+<!--RaiseException, the name of an exception in a Raises.-->
+<xsl:template match="RaiseException">
+ <li class="exception">
+ <xsl:value-of select="@name"/>:
+ <xsl:apply-templates select="descriptive"/>
+ </li>
+</xsl:template>
+
+<!--Type.-->
+<xsl:template match="Type">
+ <xsl:choose>
+ <xsl:when test="Type">
+ <xsl:text>sequence &lt;</xsl:text>
+ <xsl:apply-templates/>
+ <xsl:text>></xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="@name"/>
+ <xsl:value-of select="@type"/>
+ <xsl:if test="@nullable">
+ <xsl:text>?</xsl:text>
+ </xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+<!--Enum.-->
+<xsl:template match="Enum[descriptive]">
+ <xsl:variable name="name" select="@name"/>
+ <div class="enum" id="{@id}">
+ <h3><code><xsl:value-of select="@name"/></code></h3>
+ <xsl:apply-templates select="descriptive/brief"/>
+ <xsl:apply-templates select="webidl"/>
+ <xsl:apply-templates select="descriptive"/>
+ <xsl:apply-templates select="descriptive/Code"/>
+ <div class="enumvalues">
+ <h4>Values</h4>
+ <dl>
+ <xsl:apply-templates select="EnumValue"/>
+ </dl>
+ </div>
+ </div>
+</xsl:template>
+<xsl:template match="Enum[not(descriptive)]">
+</xsl:template>
+
+<!--EnumValue-->
+<xsl:template match="EnumValue">
+ <dt class="enumvalue" id="{@id}">
+ <code>
+ <xsl:value-of select="@stringvalue"/>
+ </code>
+ </dt>
+ <dd>
+ <xsl:apply-templates select="descriptive/brief"/>
+ <xsl:apply-templates select="descriptive"/>
+ <xsl:apply-templates select="descriptive/Code"/>
+ </dd>
+</xsl:template>
+
+<xsl:template match="descriptive[not(author)]">
+ <xsl:apply-templates select="version"/>
+ <xsl:if test="author">
+ </xsl:if>
+ <xsl:apply-templates select="description"/>
+</xsl:template>
+
+<!--brief-->
+<xsl:template match="brief">
+ <div class="brief">
+ <p>
+ <xsl:apply-templates/>
+ </p>
+ </div>
+</xsl:template>
+
+<!--description in ReturnType or Argument or ScopedName-->
+<xsl:template match="Type/descriptive/description|Argument/descriptive/description|Name/descriptive/description">
+ <!--If the description contains just a single <p> then we omit
+ the <p> and just do its contents.-->
+ <xsl:choose>
+ <xsl:when test="p and count(*) = 1">
+ <xsl:apply-templates select="p/*|p/text()"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <div class="description">
+ <xsl:apply-templates/>
+ </div>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+<!--Other description-->
+<xsl:template match="description">
+ <div class="description">
+ <xsl:apply-templates/>
+ </div>
+</xsl:template>
+
+<!--Code-->
+<xsl:template match="Code">
+ <div class="example">
+ <xsl:choose>
+ <xsl:when test="@lang">
+ <h5><xsl:value-of select="@lang"/></h5>
+ </xsl:when>
+ <xsl:otherwise>
+ <h5>Code example</h5>
+ </xsl:otherwise>
+ </xsl:choose>
+ <pre class="examplecode"><xsl:apply-templates/></pre>
+ </div>
+</xsl:template>
+
+<!--webidl : literal Web IDL from input-->
+<xsl:template match="webidl">
+ <h5>WebIDL</h5>
+ <pre class="webidl"><xsl:apply-templates/></pre>
+</xsl:template>
+
+<!--author-->
+<xsl:template match="author">
+ <li class="author"><xsl:apply-templates/></li>
+</xsl:template>
+
+<!--version-->
+<xsl:template match="version">
+ <div class="version">
+ <h2>
+ Version: <xsl:apply-templates/>
+ </h2>
+ </div>
+</xsl:template>
+
+<!--api-feature-->
+<xsl:template match="api-feature">
+ <dt>
+ <xsl:value-of select="@identifier"/>
+ </dt>
+ <dd>
+ <xsl:apply-templates/>
+ </dd>
+</xsl:template>
+
+<!--param-->
+<xsl:template match="param">
+ <li>
+ <code><xsl:value-of select="@identifier"/></code>:
+ <xsl:apply-templates/>
+ </li>
+</xsl:template>
+
+<!--def-instantiated.
+ This assumes that only one interface in the module has a def-instantiated,
+ and that interface contains just one attribute.-->
+<xsl:template match="def-instantiated">
+ <xsl:variable name="ifacename" select="../../@name"/>
+ <p>
+ <xsl:choose>
+ <xsl:when test="count(descriptive/api-feature)=1">
+ When the feature
+ </xsl:when>
+ <xsl:otherwise>
+ When any of the features
+ </xsl:otherwise>
+ </xsl:choose>
+ </p>
+ <ul>
+ <xsl:for-each select="descriptive/api-feature">
+ <li><code>
+ <xsl:value-of select="@identifier"/>
+ </code></li>
+ </xsl:for-each>
+ </ul>
+ <p>
+ is successfully requested, the interface
+ <code><xsl:apply-templates select="../../Attribute/Type"/></code>
+ is instantiated, and the resulting object appears in the global
+ namespace as
+ <code><xsl:value-of select="../../../Implements[@name2=$ifacename]/@name1"/>.<xsl:value-of select="../../Attribute/@name"/></code>.
+ </p>
+</xsl:template>
+
+
+
+<!--html elements-->
+<xsl:template match="a|b|br|dd|dl|dt|em|li|p|table|td|th|tr|ul">
+ <xsl:element name="{name()}"><xsl:for-each select="@*"><xsl:attribute name="{name()}"><xsl:value-of select="."/></xsl:attribute></xsl:for-each><xsl:apply-templates/></xsl:element>
+</xsl:template>
+
+<xsl:template name="summary">
+ <table class="summary">
+ <thead>
+ <tr><th>Interface</th><th>Method</th></tr>
+ </thead>
+ <tbody>
+ <xsl:for-each select="Interface[descriptive]">
+ <tr><td><a href="#{@id}"><xsl:value-of select="@name"/></a></td>
+ <td>
+ <xsl:for-each select="Operation">
+
+ <xsl:apply-templates select="Type"/>
+ <xsl:text> </xsl:text>
+ <a href="#{concat(@name,generate-id(.))}"><xsl:value-of select="@name"/></a>
+ <xsl:text>(</xsl:text>
+ <xsl:for-each select="ArgumentList/Argument">
+ <xsl:variable name="type"><xsl:apply-templates select="Type"/></xsl:variable>
+ <xsl:value-of select="concat(normalize-space($type),' ',@name)"/>
+ <xsl:if test="position() != last()">, </xsl:if>
+ </xsl:for-each>
+ <xsl:text>)</xsl:text>
+ <xsl:if test="position()!=last()"><br/></xsl:if>
+ </xsl:for-each>
+ </td>
+ </tr>
+ </xsl:for-each>
+ </tbody>
+ </table>
+</xsl:template>
+
+<!--<ref> element in literal Web IDL.-->
+<xsl:template match="ref[@ref]">
+ <a href="{@ref}">
+ <xsl:apply-templates/>
+ </a>
+</xsl:template>
+
+</xsl:stylesheet>
+
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/Makefile b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/Makefile
new file mode 100644
index 00000000000..c40939e36fc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/Makefile
@@ -0,0 +1,91 @@
+########################################################################
+# $Id: Makefile 418 2010-06-16 15:26:51Z tpr $
+# Copyright 2009 Aplix Corporation. All rights reserved.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+# http://www.apache.org/licenses/LICENSE-2.0
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+########################################################################
+
+UNAME = $(shell uname)
+VALIDTESTDIR = valid/idl
+VALIDTESTREFDIR = valid/xml
+VALIDTESTOBJDIR = valid/obj
+INVALIDTESTDIR = invalid/idl
+INVALIDTESTREFDIR = invalid/error
+INVALIDTESTOBJDIR = invalid/obj
+
+# The settings of SRCDIR (where to find the xsl style sheets), OBJDIR (where to
+# find widlproc and widlprocxml.dtd) and VALDTESTOBJDIR (where to put the
+# resulting XML files) reflect the directory
+# structure of the released widlproc.zip file when unzipped. ../Makefile calls
+# this Makefile with these settings overridden to reflect the directory
+# structure in svn.
+SRCDIR = ..
+OBJDIR = ..
+
+########################################################################
+# Linux configuration
+#
+ifneq (,$(filter Linux%, $(UNAME)))
+
+EXESUFFIX =
+
+else
+########################################################################
+# Darwin configuration
+#
+ifneq (,$(filter Darwin%, $(UNAME)))
+
+EXESUFFIX =
+
+else
+########################################################################
+# Windows (cygwin but using MS compiler) configuration
+#
+ifneq (,$(filter CYGWIN%, $(UNAME)))
+
+EXESUFFIX = .exe
+
+endif
+endif
+endif
+
+########################################################################
+# Common makefile
+#
+WIDLPROC = $(OBJDIR)/widlproc$(EXESUFFIX)
+DTD = $(OBJDIR)/widlprocxml.dtd
+
+VALID_WIDLS = $(patsubst $(VALIDTESTDIR)/%, %, $(wildcard $(VALIDTESTDIR)/*.widl))
+INVALID_WIDLS = $(patsubst $(INVALIDTESTDIR)/%, %, $(wildcard $(INVALIDTESTDIR)/*.widl))
+
+test : $(patsubst %.widl, $(VALIDTESTOBJDIR)/%.widlprocxml, $(VALID_WIDLS)) $(patsubst %.widl, $(INVALIDTESTOBJDIR)/%.txt, $(INVALID_WIDLS)) $(WIDLPROC)
+ @echo "$@ pass"
+
+#$(EXAMPLESOBJDIR)/%.html : $(EXAMPLESOBJDIR)/%.widlprocxml $(SRCDIR)/widlprocxmltohtml.xsl Makefile
+# cp $(SRCDIR)/widlprocxmltohtml.xsl $(dir $@)/
+# xsltproc $(dir $@)/widlprocxmltohtml.xsl $< >$@
+
+
+$(VALIDTESTOBJDIR)/%.widlprocxml : $(VALIDTESTDIR)/%.widl $(WIDLPROC) $(DTD) Makefile $(patsubst %.widl, $(VALIDTESTREFDIR)/%.widlprocxml, $(VALID_WIDLS))
+ mkdir -p $(dir $@)
+ $(WIDLPROC) $< >$@
+ cp $(OBJDIR)/widlprocxml.dtd $(dir $@)/
+ xmllint --noout --dtdvalid $(DTD) $@
+ diff $@ $(VALIDTESTREFDIR)/`basename $@`
+
+$(INVALIDTESTOBJDIR)/%.txt : $(INVALIDTESTDIR)/%.widl $(WIDLPROC) Makefile $(patsubst %.widl, $(INVALIDTESTREFDIR)/%.txt, $(INVALID_WIDLS))
+ mkdir -p $(dir $@)
+ -$(WIDLPROC) $< >$@ 2>&1
+ diff $@ $(INVALIDTESTREFDIR)/`basename $@`
+
+
+
+.DELETE_ON_ERROR:
+
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/error/enum.txt b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/error/enum.txt
new file mode 100644
index 00000000000..6f8ba8eef46
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/error/enum.txt
@@ -0,0 +1 @@
+invalid/idl/enum.widl: 1: at '1': expected string in enum
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/error/module.txt b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/error/module.txt
new file mode 100644
index 00000000000..7e504316e51
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/error/module.txt
@@ -0,0 +1 @@
+invalid/idl/module.widl: 2: at 'gfx': expected 'implements'
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/error/nonnullableany.txt b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/error/nonnullableany.txt
new file mode 100644
index 00000000000..eeeb25f12ab
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/error/nonnullableany.txt
@@ -0,0 +1 @@
+invalid/idl/nonnullableany.widl: 2: at '?': expected identifier
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/error/nonnullableobjects.txt b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/error/nonnullableobjects.txt
new file mode 100644
index 00000000000..526622599b7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/error/nonnullableobjects.txt
@@ -0,0 +1 @@
+invalid/idl/nonnullableobjects.widl: 4: at '?': expected identifier
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/error/scopedname.txt b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/error/scopedname.txt
new file mode 100644
index 00000000000..5646608cd37
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/error/scopedname.txt
@@ -0,0 +1 @@
+invalid/idl/scopedname.widl: 2: at ':': expected identifier
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/error/sequenceAsAttribute.txt b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/error/sequenceAsAttribute.txt
new file mode 100644
index 00000000000..15960cb8b5f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/error/sequenceAsAttribute.txt
@@ -0,0 +1 @@
+invalid/idl/sequenceAsAttribute.widl: 2: at 'sequence': expected type
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/error/stringconstants.idl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/error/stringconstants.idl
new file mode 100644
index 00000000000..155a892c55a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/error/stringconstants.idl
@@ -0,0 +1 @@
+invalid/idl/stringconstants.idl: 2: at 'DOMString': expected acceptable constant type
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/idl/enum.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/idl/enum.widl
new file mode 100644
index 00000000000..c355c3251c0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/idl/enum.widl
@@ -0,0 +1 @@
+enum foo { 1, 2, 3}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/idl/module.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/idl/module.widl
new file mode 100644
index 00000000000..a4c79fdf155
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/idl/module.widl
@@ -0,0 +1,25 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+module gfx {
+
+ module geom {
+ interface Shape { /* ... */ };
+ interface Rectangle : Shape { /* ... */ };
+ interface Path : Shape { /* ... */ };
+ };
+
+ interface GraphicsContext {
+ void fillShape(geom::Shape s);
+ void strokeShape(geom::Shape s);
+ };
+};
+
+module gui {
+
+ interface Widget { /* ... */ };
+
+ interface Window : Widget {
+ gfx::GraphicsContext getGraphicsContext();
+ };
+
+ interface Button : Widget { /* ... */ };
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/idl/nonnullableany.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/idl/nonnullableany.widl
new file mode 100644
index 00000000000..38957655523
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/idl/nonnullableany.widl
@@ -0,0 +1,3 @@
+interface NonNullable {
+ attribute any? foo;
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/idl/nonnullableobjects.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/idl/nonnullableobjects.widl
new file mode 100644
index 00000000000..1deac5aeec9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/idl/nonnullableobjects.widl
@@ -0,0 +1,5 @@
+interface Foo {};
+
+interface NonNullable {
+ attribute Foo?? foo;
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/idl/raises.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/idl/raises.widl
new file mode 100644
index 00000000000..ff65522f2b3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/idl/raises.widl
@@ -0,0 +1,18 @@
+// getraises and setraises are not longer valid Web IDL
+interface Person {
+
+ // An attribute that can raise an exception if it is set to an invalid value.
+ attribute DOMString name setraises (InvalidName);
+
+ // An attribute whose value cannot be assigned to, and which can raise an
+ // exception some circumstances.
+ readonly attribute DOMString petName getraises (NoSuchPet);
+};
+
+exception SomeException {
+};
+
+interface ExceptionThrower {
+ // This attribute always throws a SomeException and never returns a value.
+ attribute long valueOf getraises(SomeException);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/idl/scopedname.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/idl/scopedname.widl
new file mode 100644
index 00000000000..cfcb1ccc939
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/idl/scopedname.widl
@@ -0,0 +1,2 @@
+// scoped names are no longer valid in WebIDL
+ typedef gfx::geom::geom2d::Point Point;
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/idl/sequenceAsAttribute.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/idl/sequenceAsAttribute.widl
new file mode 100644
index 00000000000..c23da82ac22
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/idl/sequenceAsAttribute.widl
@@ -0,0 +1,3 @@
+interface sequenceAsAttribute {
+ attribute sequence<short> invalid;
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/idl/special-omittable.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/idl/special-omittable.widl
new file mode 100644
index 00000000000..bdfbfa70973
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/idl/special-omittable.widl
@@ -0,0 +1,8 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+// omittable is no longer a recognized keywoard as of 20110905
+interface Dictionary {
+ readonly attribute unsigned long propertyCount;
+
+ omittable getter float getProperty(DOMString propertyName);
+ omittable setter void setProperty(DOMString propertyName, float propertyValue);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/idl/stringconstants.idl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/idl/stringconstants.idl
new file mode 100644
index 00000000000..44fd3ff136e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/invalid/idl/stringconstants.idl
@@ -0,0 +1,3 @@
+interface Util {
+ const DOMString hello = "world";
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/allowany.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/allowany.widl
new file mode 100644
index 00000000000..2343bb96374
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/allowany.widl
@@ -0,0 +1,6 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface B {
+ void g();
+ void g(B b);
+ void g([AllowAny] DOMString s);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/array.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/array.widl
new file mode 100644
index 00000000000..22e21fb6564
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/array.widl
@@ -0,0 +1,5 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+[Constructor]
+interface LotteryResults {
+ readonly attribute unsigned short[][] numbers;
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/attributes.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/attributes.widl
new file mode 100644
index 00000000000..7e1d691cbe2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/attributes.widl
@@ -0,0 +1,14 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+exception InvalidName {
+ DOMString reason;
+};
+
+exception NoSuchPet { };
+
+interface Person {
+
+ // A simple attribute that can be set to any value the range an unsigned
+ // short can take.
+ attribute unsigned short age;
+
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/callback.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/callback.widl
new file mode 100644
index 00000000000..d92f6a18c0a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/callback.widl
@@ -0,0 +1,5 @@
+callback AsyncOperationCallback = void (DOMString status);
+
+callback interface EventHandler {
+ void eventOccurred(DOMString details);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/caller.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/caller.widl
new file mode 100644
index 00000000000..92acb1c0176
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/caller.widl
@@ -0,0 +1,5 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface NumberQuadrupler {
+ // This operation simply returns four times the given number x.
+ legacycaller float compute(float x);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/constants.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/constants.widl
new file mode 100644
index 00000000000..5e28ae9c116
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/constants.widl
@@ -0,0 +1,18 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface Util {
+ const boolean DEBUG = false;
+ const short negative = -1;
+ const octet LF = 10;
+ const unsigned long BIT_MASK = 0x0000fc00;
+ const float AVOGADRO = 6.022e23;
+ const unrestricted float sobig = Infinity;
+ const unrestricted double minusonedividedbyzero = -Infinity;
+ const short notanumber = NaN;
+};
+
+exception Error {
+ const short ERR_UNKNOWN = 0;
+ const short ERR_OUT_OF_MEMORY = 1;
+
+ short errorCode;
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/constructor.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/constructor.widl
new file mode 100644
index 00000000000..f93ec08a6e6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/constructor.widl
@@ -0,0 +1,9 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+[Constructor,
+ Constructor(float radius)]
+interface Circle {
+ attribute float r;
+ attribute float cx;
+ attribute float cy;
+ readonly attribute float circumference;
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/dictionary-inherits.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/dictionary-inherits.widl
new file mode 100644
index 00000000000..48f8a0fdceb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/dictionary-inherits.widl
@@ -0,0 +1,9 @@
+dictionary PaintOptions {
+ DOMString? fillPattern = "black";
+ DOMString? strokePattern = null;
+ Point position;
+};
+
+dictionary WetPaintOptions : PaintOptions {
+ float hydrometry;
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/dictionary.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/dictionary.widl
new file mode 100644
index 00000000000..f46b7ba7806
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/dictionary.widl
@@ -0,0 +1,11 @@
+// Extracted from Web IDL editors draft May 31 2011
+dictionary PaintOptions {
+ DOMString? fillPattern = "black";
+ DOMString? strokePattern = null;
+ Point position;
+};
+
+partial dictionary A {
+ long h;
+ long d;
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/documentation-dos.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/documentation-dos.widl
new file mode 100644
index 00000000000..fb801101f14
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/documentation-dos.widl
@@ -0,0 +1,33 @@
+/**
+* \brief Testing documentation features
+*
+* This is a
+* single paragraph
+*
+* <p>This is valid.</p>
+* <p>This is <em>valid</em>.</p>
+* <p>This is <b>valid</b>.</p>
+* <p>This is <a href=''>valid</a>.</p>
+* <ul>
+* <li>This</li>
+* <li>is</li>
+* <li>valid</li>
+* </ul>
+* <dl>
+* <dt>This</dt>
+* <dd>valid</dd>
+* </dl>
+* <table>
+* <tr>
+* <td>this</td>
+* <td>is</td>
+* </tr>
+* <tr>
+* <td>valid</td>
+* </tr>
+* </table>
+* <p>This is <br> valid.</p>
+* <p>This is <br /> valid.</p>
+* <p>This is <br/> valid.</p>
+*/
+interface Documentation {}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/documentation.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/documentation.widl
new file mode 100644
index 00000000000..003e9226f67
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/documentation.widl
@@ -0,0 +1,34 @@
+/**
+* \brief Testing documentation features
+*
+* This is a
+* single paragraph
+*
+* <p>This is valid.</p>
+* <p>This is <em>valid</em>.</p>
+* <p>This is <b>valid</b>.</p>
+* <p>This is <a href=''>valid</a>.</p>
+* <ul>
+* <li>This</li>
+* <li>is</li>
+* <li>valid</li>
+* </ul>
+* <dl>
+* <dt>This</dt>
+* <dd>valid</dd>
+* </dl>
+* <table>
+* <tr>
+* <td>this</td>
+* <td>is</td>
+* </tr>
+* <tr>
+* <td>valid</td>
+* </tr>
+* </table>
+* <p>This is <br> valid.</p>
+* <p>This is <br /> valid.</p>
+* <p>This is <br/> valid.</p>
+* <p><img src="foo.png" alt="Valid"/></p>
+*/
+interface Documentation {}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/enum.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/enum.widl
new file mode 100644
index 00000000000..851fca2e6f6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/enum.widl
@@ -0,0 +1,8 @@
+enum MealType { "rice", "noodles", "other" };
+
+interface Meal {
+ attribute MealType type;
+ attribute float size; // in grams
+
+ void initialize(MealType type, float size);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/equivalent-decl.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/equivalent-decl.widl
new file mode 100644
index 00000000000..6b3e0eda284
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/equivalent-decl.widl
@@ -0,0 +1,18 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface Dictionary {
+ readonly attribute unsigned long propertyCount;
+
+ getter float getProperty(DOMString propertyName);
+ setter void setProperty(DOMString propertyName, float propertyValue);
+};
+
+
+interface Dictionary {
+ readonly attribute unsigned long propertyCount;
+
+ float getProperty(DOMString propertyName);
+ void setProperty(DOMString propertyName, float propertyValue);
+
+ getter float (DOMString propertyName);
+ setter void (DOMString propertyName, float propertyValue);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/exception-inheritance.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/exception-inheritance.widl
new file mode 100644
index 00000000000..258fdeba6f4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/exception-inheritance.widl
@@ -0,0 +1,7 @@
+// from http://lists.w3.org/Archives/Public/public-script-coord/2010OctDec/0112.html
+ exception DOMException {
+ unsigned short code;
+ };
+
+ exception HierarchyRequestError : DOMException { };
+ exception NoModificationAllowedError : DOMException { }; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/exception.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/exception.widl
new file mode 100644
index 00000000000..f4b6ae29e10
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/exception.widl
@@ -0,0 +1,8 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface Dahut {
+ attribute DOMString type;
+};
+
+exception SomeException {
+};
+
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/getter-setter.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/getter-setter.widl
new file mode 100644
index 00000000000..bdf87e1c7c7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/getter-setter.widl
@@ -0,0 +1,7 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface Dictionary {
+ readonly attribute unsigned long propertyCount;
+
+ getter float (DOMString propertyName);
+ setter void (DOMString propertyName, float propertyValue);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/identifier-qualified-names.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/identifier-qualified-names.widl
new file mode 100644
index 00000000000..33893d4c644
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/identifier-qualified-names.widl
@@ -0,0 +1,44 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+ // Typedef identifier: "number"
+ // Qualified name: "::framework::number"
+ typedef float number;
+
+ // Exception identifier: "FrameworkException"
+ // Qualified name: "::framework::FrameworkException"
+ exception FrameworkException {
+
+ // Constant identifier: "ERR_NOT_FOUND"
+ // Qualified name: "::framework::FrameworkException::ERR_NOT_FOUND"
+ const long ERR_NOT_FOUND = 1;
+
+ // Exception field identifier: "code"
+ long code;
+ };
+
+ // Interface identifier: "System"
+ // Qualified name: "::framework::System"
+ interface System {
+
+ // Operation identifier: "createObject"
+ // Operation argument identifier: "interface"
+ object createObject(DOMString _interface);
+
+ // Operation has no identifier; it declares a getter.
+ getter DOMString (DOMString keyName);
+ };
+
+
+ // Interface identifier: "TextField"
+ // Qualified name: "::framework::gui::TextField"
+ interface TextField {
+
+ // Attribute identifier: "const"
+ attribute boolean _const;
+
+ // Attribute identifier: "value"
+ attribute DOMString? _value;
+ };
+
+interface Foo {
+ void op(object interface);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/implements.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/implements.widl
new file mode 100644
index 00000000000..7a310926f1c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/implements.widl
@@ -0,0 +1,14 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+ interface Node {
+ readonly attribute unsigned short nodeType;
+ // ...
+ };
+
+ interface EventTarget {
+ void addEventListener(DOMString type,
+ EventListener listener,
+ boolean useCapture);
+ // ...
+ };
+
+ Node implements EventTarget;
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/indexed-properties.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/indexed-properties.widl
new file mode 100644
index 00000000000..acf0ed3bf84
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/indexed-properties.widl
@@ -0,0 +1,12 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface OrderedMap {
+ readonly attribute unsigned long size;
+
+ getter any getByIndex(unsigned long index);
+ setter void setByIndex(unsigned long index, any value);
+ deleter void removeByIndex(unsigned long index);
+
+ getter any get(DOMString name);
+ setter creator void set(DOMString name, any value);
+ deleter void remove(DOMString name);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/inherits-getter.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/inherits-getter.widl
new file mode 100644
index 00000000000..558e8116494
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/inherits-getter.widl
@@ -0,0 +1,16 @@
+interface Animal {
+
+ // A simple attribute that can be set to any string value.
+ readonly attribute DOMString name;
+};
+
+interface Person : Animal {
+
+ // An attribute whose value cannot be assigned to.
+ readonly attribute unsigned short age;
+
+ // An attribute that can raise an exception if it is set to an invalid value.
+ // Its getter behavior is inherited from Animal, and need not be specified
+ // the description of Person.
+ inherit attribute DOMString name;
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/interface-inherits.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/interface-inherits.widl
new file mode 100644
index 00000000000..7921def7727
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/interface-inherits.widl
@@ -0,0 +1,12 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface Animal {
+ attribute DOMString name;
+};
+
+interface Human : Animal {
+ attribute Dog pet;
+};
+
+interface Dog : Animal {
+ attribute Human owner;
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/iterator.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/iterator.widl
new file mode 100644
index 00000000000..3bf1b36dec6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/iterator.widl
@@ -0,0 +1,35 @@
+interface SessionManager {
+ Session getSessionForUser(DOMString username);
+ readonly attribute unsigned long sessionCount;
+
+ Session iterator;
+};
+
+interface Session {
+ readonly attribute DOMString username;
+ // ...
+};
+
+interface SessionManager2 {
+ Session2 getSessionForUser(DOMString username);
+ readonly attribute unsigned long sessionCount;
+
+ Session2 iterator = SessionIterator;
+};
+
+interface Session2 {
+ readonly attribute DOMString username;
+ // ...
+};
+
+interface SessionIterator {
+ readonly attribute unsigned long remainingSessions;
+};
+
+ interface NodeList {
+ Node iterator = NodeIterator;
+ };
+
+ interface NodeIterator {
+ Node iterator object;
+ }; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/namedconstructor.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/namedconstructor.widl
new file mode 100644
index 00000000000..c468b78f8e1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/namedconstructor.widl
@@ -0,0 +1,6 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+[NamedConstructor=Audio,
+ NamedConstructor=Audio(DOMString src)]
+interface HTMLAudioElement : HTMLMediaElement {
+ // ...
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/nointerfaceobject.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/nointerfaceobject.widl
new file mode 100644
index 00000000000..c17d75ff8fd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/nointerfaceobject.widl
@@ -0,0 +1,5 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+[NoInterfaceObject]
+interface Query {
+ any lookupEntry(unsigned long key);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/nullable.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/nullable.widl
new file mode 100644
index 00000000000..ccbf625ff8a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/nullable.widl
@@ -0,0 +1,9 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface MyConstants {
+ const boolean? ARE_WE_THERE_YET = false;
+};
+
+interface Node {
+ readonly attribute DOMString? namespaceURI;
+ // ...
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/nullableobjects.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/nullableobjects.widl
new file mode 100644
index 00000000000..83d1d40b2ac
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/nullableobjects.widl
@@ -0,0 +1,13 @@
+// Extracted from WebIDL spec 2011-05-23
+
+interface A {
+ // ...
+};
+interface B {
+ // ...
+};
+interface C {
+ void f(A? x);
+ void f(B? x);
+
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/operation-optional-arg.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/operation-optional-arg.widl
new file mode 100644
index 00000000000..379053b45f1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/operation-optional-arg.widl
@@ -0,0 +1,4 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface ColorCreator {
+ object createColor(float v1, float v2, float v3, optional float alpha = 3.5);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/overloading.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/overloading.widl
new file mode 100644
index 00000000000..ef1288a8877
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/overloading.widl
@@ -0,0 +1,20 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface A {
+ // ...
+};
+
+interface B {
+ // ...
+};
+
+interface C {
+ void f(A x);
+ void f(B x);
+};
+
+interface A {
+ /* f1 */ void f(DOMString a);
+ /* f2 */ void f([AllowAny] DOMString a, DOMString b, float... c);
+ /* f3 */ void f();
+ /* f4 */ void f(long a, DOMString b, optional DOMString c, float... d);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/overridebuiltins.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/overridebuiltins.widl
new file mode 100644
index 00000000000..79211c29e84
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/overridebuiltins.widl
@@ -0,0 +1,6 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+[OverrideBuiltins]
+interface StringMap2 {
+ readonly attribute unsigned long length;
+ getter DOMString lookup(DOMString key);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/partial-interface.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/partial-interface.widl
new file mode 100644
index 00000000000..90e7e0ea421
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/partial-interface.widl
@@ -0,0 +1,7 @@
+interface Foo {
+ attribute DOMString bar;
+};
+
+partial interface Foo {
+ attribute DOMString quux;
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/primitives.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/primitives.widl
new file mode 100644
index 00000000000..92939601a1a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/primitives.widl
@@ -0,0 +1,19 @@
+interface Primitives {
+ attribute boolean truth;
+ attribute byte character;
+ attribute octet value;
+ attribute short number;
+ attribute unsigned short positive;
+ attribute long big;
+ attribute unsigned long bigpositive;
+ attribute long long bigbig;
+ attribute unsigned long long bigbigpositive;
+ attribute float real;
+ attribute double bigreal;
+ attribute unrestricted float realwithinfinity;
+ attribute unrestricted double bigrealwithinfinity;
+ attribute DOMString string;
+ attribute ByteString bytes;
+ attribute Date date;
+ attribute RegExp regexp;
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/prototyperoot.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/prototyperoot.widl
new file mode 100644
index 00000000000..30dd5cbca13
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/prototyperoot.widl
@@ -0,0 +1,5 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+[PrototypeRoot]
+interface Node {
+ readonly attribute unsigned short nodeType;
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/putforwards.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/putforwards.widl
new file mode 100644
index 00000000000..1e50a4ee394
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/putforwards.widl
@@ -0,0 +1,5 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface Person {
+ [PutForwards=full] readonly attribute Name name;
+ attribute unsigned short age;
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/reg-operations.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/reg-operations.widl
new file mode 100644
index 00000000000..13997cb1d12
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/reg-operations.widl
@@ -0,0 +1,17 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface Dimensions {
+ attribute unsigned long width;
+ attribute unsigned long height;
+};
+
+exception NoPointerDevice { };
+
+interface Button {
+
+ // An operation that takes no arguments, returns a boolean
+ boolean isMouseOver();
+
+ // Overloaded operations.
+ void setDimensions(Dimensions size);
+ void setDimensions(unsigned long width, unsigned long height);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/replaceable.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/replaceable.widl
new file mode 100644
index 00000000000..c14d0c37689
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/replaceable.widl
@@ -0,0 +1,5 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface Counter {
+ [Replaceable] readonly attribute unsigned long value;
+ void increment();
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/sequence.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/sequence.widl
new file mode 100644
index 00000000000..a1aa931f5f0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/sequence.widl
@@ -0,0 +1,7 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+// edited to remove sequence as attributes, now invalid
+interface Canvas {
+ void drawPolygon(sequence<float> coordinates);
+ sequence<float> getInflectionPoints();
+ // ...
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/serializer.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/serializer.widl
new file mode 100644
index 00000000000..6f6ccd0e8d5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/serializer.widl
@@ -0,0 +1,64 @@
+interface Transaction {
+ readonly attribute Account from;
+ readonly attribute Account to;
+ readonly attribute float amount;
+ readonly attribute DOMString description;
+ readonly attribute unsigned long number;
+
+ serializer;
+};
+
+interface Account {
+ attribute DOMString name;
+ attribute unsigned long number;
+ serializer DOMString serialize();
+};
+
+interface Transaction2 {
+ readonly attribute Account2 from;
+ readonly attribute Account2 to;
+ readonly attribute float amount;
+ readonly attribute DOMString description;
+ readonly attribute unsigned long number;
+
+ serializer = { from, to, amount, description };
+};
+
+interface Account2 {
+ attribute DOMString name;
+ attribute unsigned long number;
+ serializer = number;
+};
+
+interface Account3 {
+ attribute DOMString name;
+ attribute unsigned long number;
+
+ serializer = { attribute };
+};
+
+interface Account4 {
+ getter object getItem(unsigned long index);
+ serializer = { getter };
+};
+
+interface Account5 : Account {
+ attribute DOMString secondname;
+ serializer = { inherit, secondname };
+};
+
+interface Account6 : Account {
+ attribute DOMString secondname;
+ serializer = { inherit, attribute };
+};
+
+interface Account7 {
+ attribute DOMString name;
+ attribute unsigned long number;
+ serializer = [ name, number ];
+};
+
+interface Account8 {
+ getter object getItem(unsigned long index);
+ serializer = [ getter ];
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/static.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/static.widl
new file mode 100644
index 00000000000..5b2cd36590f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/static.widl
@@ -0,0 +1,11 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface Point { /* ... */ };
+
+interface Circle {
+ attribute float cx;
+ attribute float cy;
+ attribute float radius;
+
+ static readonly attribute long triangulationCount;
+ static Point triangulate(Circle c1, Circle c2, Circle c3);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/stringifier-attribute.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/stringifier-attribute.widl
new file mode 100644
index 00000000000..c964ecb93e6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/stringifier-attribute.widl
@@ -0,0 +1,6 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+[Constructor]
+interface Student {
+ attribute unsigned long id;
+ stringifier attribute DOMString name;
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/stringifier-custom.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/stringifier-custom.widl
new file mode 100644
index 00000000000..b5d7c87e7f4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/stringifier-custom.widl
@@ -0,0 +1,9 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+[Constructor]
+interface Student {
+ attribute unsigned long id;
+ attribute DOMString? familyName;
+ attribute DOMString givenName;
+
+ stringifier DOMString ();
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/stringifier.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/stringifier.widl
new file mode 100644
index 00000000000..4eb483d9b53
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/stringifier.widl
@@ -0,0 +1,8 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface A {
+ stringifier DOMString ();
+};
+
+interface A {
+ stringifier;
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/treatasnull.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/treatasnull.widl
new file mode 100644
index 00000000000..d3c55b008c0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/treatasnull.widl
@@ -0,0 +1,7 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface Dog {
+ attribute DOMString name;
+ attribute DOMString owner;
+
+ boolean isMemberOfBreed([TreatNullAs=EmptyString] DOMString breedName);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/treatasundefined.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/treatasundefined.widl
new file mode 100644
index 00000000000..e30050f8413
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/treatasundefined.widl
@@ -0,0 +1,7 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface Cat {
+ attribute DOMString name;
+ attribute DOMString owner;
+
+ boolean isMemberOfBreed([TreatUndefinedAs=EmptyString] DOMString breedName);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/typedef.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/typedef.widl
new file mode 100644
index 00000000000..b4c17d8d36a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/typedef.widl
@@ -0,0 +1,22 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+ interface Point {
+ attribute float x;
+ attribute float y;
+ };
+
+ typedef sequence<Point> PointSequence;
+
+ interface Rect {
+ attribute Point topleft;
+ attribute Point bottomright;
+ };
+
+ interface Widget {
+
+ readonly attribute Rect bounds;
+
+ boolean pointWithinBounds(Point p);
+ boolean allPointsWithinBounds(PointSequence ps);
+ };
+
+ typedef [Clamp] octet value; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/typesuffixes.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/typesuffixes.widl
new file mode 100644
index 00000000000..95e31c16902
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/typesuffixes.widl
@@ -0,0 +1,3 @@
+interface Suffixes {
+ void test(sequence<DOMString[]?>? foo);
+};
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/uniontype.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/uniontype.widl
new file mode 100644
index 00000000000..4d99f019630
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/uniontype.widl
@@ -0,0 +1,3 @@
+interface Union {
+ attribute (float or (Date or Event) or (Node or DOMString)?) test;
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/variadic-operations.widl b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/variadic-operations.widl
new file mode 100644
index 00000000000..51fae4cc1ea
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/idl/variadic-operations.widl
@@ -0,0 +1,7 @@
+// Extracted from http://dev.w3.org/2006/webapi/WebIDL/ on 2011-05-06
+interface IntegerSet {
+ readonly attribute unsigned long cardinality;
+
+ void union(long... ints);
+ void intersection(long... ints);
+}; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/allowany.widlprocxml b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/allowany.widlprocxml
new file mode 100644
index 00000000000..7da508bcb5c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/allowany.widlprocxml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface B {
+ void g();
+ void g(<ref>B</ref> b);
+ void g([AllowAny] DOMString s);
+};</webidl>
+ <Interface name="B" id="::B">
+ <webidl>interface B {
+ void g();
+ void g(<ref>B</ref> b);
+ void g([AllowAny] DOMString s);
+};</webidl>
+ <Operation name="g" id="::B::g">
+ <webidl> void g();</webidl>
+ <Type type="void"/>
+ <ArgumentList/>
+ </Operation>
+ <Operation name="g" id="::B::g">
+ <webidl> void g(<ref>B</ref> b);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="b">
+ <Type name="B"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation name="g" id="::B::g">
+ <webidl> void g([AllowAny] DOMString s);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="s">
+ <ExtendedAttributeList>
+ <ExtendedAttribute name="AllowAny">
+ <webidl>AllowAny</webidl>
+ </ExtendedAttribute>
+ </ExtendedAttributeList>
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/array.widlprocxml b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/array.widlprocxml
new file mode 100644
index 00000000000..3df72ff1608
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/array.widlprocxml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>[Constructor]
+interface LotteryResults {
+ readonly attribute unsigned short[][] numbers;
+};</webidl>
+ <Interface name="LotteryResults" id="::LotteryResults">
+ <webidl>[Constructor]
+interface LotteryResults {
+ readonly attribute unsigned short[][] numbers;
+};</webidl>
+ <ExtendedAttributeList>
+ <ExtendedAttribute name="Constructor">
+ <webidl>Constructor</webidl>
+ </ExtendedAttribute>
+ </ExtendedAttributeList>
+ <Attribute readonly="readonly" name="numbers" id="::LotteryResults::numbers">
+ <webidl> readonly attribute unsigned short[][] numbers;</webidl>
+ <Type type="array">
+ <Type type="array">
+ <Type type="unsigned short"/>
+ </Type>
+ </Type>
+ </Attribute>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/attributes.widlprocxml b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/attributes.widlprocxml
new file mode 100644
index 00000000000..89bd8ac9b01
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/attributes.widlprocxml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>exception InvalidName {
+ DOMString reason;
+};
+
+exception NoSuchPet { };
+
+interface Person {
+
+ attribute unsigned short age;
+
+};</webidl>
+ <Exception name="InvalidName" id="::InvalidName">
+ <webidl>exception InvalidName {
+ DOMString reason;
+};</webidl>
+ <ExceptionField name="reason" id="::InvalidName::reason">
+ <webidl> DOMString reason;</webidl>
+ <Type type="DOMString"/>
+ </ExceptionField>
+ </Exception>
+ <Exception name="NoSuchPet" id="::NoSuchPet">
+ <webidl>exception NoSuchPet { };</webidl>
+ </Exception>
+ <Interface name="Person" id="::Person">
+ <webidl>interface Person {
+
+ attribute unsigned short age;
+
+};</webidl>
+ <Attribute name="age" id="::Person::age">
+ <webidl> attribute unsigned short age;</webidl>
+ <Type type="unsigned short"/>
+ </Attribute>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/callback.widlprocxml b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/callback.widlprocxml
new file mode 100644
index 00000000000..9eac06ce279
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/callback.widlprocxml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>callback AsyncOperationCallback = void (DOMString status);
+
+callback interface EventHandler {
+ void eventOccurred(DOMString details);
+};</webidl>
+ <Callback name="AsyncOperationCallback" id="::AsyncOperationCallback">
+ <webidl>callback AsyncOperationCallback = void (DOMString status);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="status">
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </Callback>
+ <Interface name="EventHandler" callback="callback" id="::EventHandler">
+ <webidl>callback interface EventHandler {
+ void eventOccurred(DOMString details);
+};</webidl>
+ <Operation name="eventOccurred" id="::EventHandler::eventOccurred">
+ <webidl> void eventOccurred(DOMString details);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="details">
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/caller.widlprocxml b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/caller.widlprocxml
new file mode 100644
index 00000000000..9754d4e0268
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/caller.widlprocxml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface NumberQuadrupler {
+ legacycaller float compute(float x);
+};</webidl>
+ <Interface name="NumberQuadrupler" id="::NumberQuadrupler">
+ <webidl>interface NumberQuadrupler {
+ legacycaller float compute(float x);
+};</webidl>
+ <Operation legacycaller="legacycaller" name="compute" id="::NumberQuadrupler::compute">
+ <webidl> legacycaller float compute(float x);</webidl>
+ <Type type="float"/>
+ <ArgumentList>
+ <Argument name="x">
+ <Type type="float"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/constants.widlprocxml b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/constants.widlprocxml
new file mode 100644
index 00000000000..51cb4331f75
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/constants.widlprocxml
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Util {
+ const boolean DEBUG = false;
+ const short negative = -1;
+ const octet LF = 10;
+ const unsigned long BIT_MASK = 0x0000fc00;
+ const float AVOGADRO = 6.022e23;
+ const unrestricted float sobig = Infinity;
+ const unrestricted double minusonedividedbyzero = -Infinity;
+ const short notanumber = NaN;
+};
+
+exception Error {
+ const short ERR_UNKNOWN = 0;
+ const short ERR_OUT_OF_MEMORY = 1;
+
+ short errorCode;
+};</webidl>
+ <Interface name="Util" id="::Util">
+ <webidl>interface Util {
+ const boolean DEBUG = false;
+ const short negative = -1;
+ const octet LF = 10;
+ const unsigned long BIT_MASK = 0x0000fc00;
+ const float AVOGADRO = 6.022e23;
+ const unrestricted float sobig = Infinity;
+ const unrestricted double minusonedividedbyzero = -Infinity;
+ const short notanumber = NaN;
+};</webidl>
+ <Const name="DEBUG" value="false" id="::Util::DEBUG">
+ <webidl> const boolean DEBUG = false;</webidl>
+ <Type type="boolean"/>
+ </Const>
+ <Const name="negative" value="-1" id="::Util::negative">
+ <webidl> const short negative = -1;</webidl>
+ <Type type="short"/>
+ </Const>
+ <Const name="LF" value="10" id="::Util::LF">
+ <webidl> const octet LF = 10;</webidl>
+ <Type type="octet"/>
+ </Const>
+ <Const name="BIT_MASK" value="0x0000fc00" id="::Util::BIT_MASK">
+ <webidl> const unsigned long BIT_MASK = 0x0000fc00;</webidl>
+ <Type type="unsigned long"/>
+ </Const>
+ <Const name="AVOGADRO" value="6.022e23" id="::Util::AVOGADRO">
+ <webidl> const float AVOGADRO = 6.022e23;</webidl>
+ <Type type="float"/>
+ </Const>
+ <Const name="sobig" value="Infinity" id="::Util::sobig">
+ <webidl> const unrestricted float sobig = Infinity;</webidl>
+ <Type type="unrestricted float"/>
+ </Const>
+ <Const name="minusonedividedbyzero" value="-Infinity" id="::Util::minusonedividedbyzero">
+ <webidl> const unrestricted double minusonedividedbyzero = -Infinity;</webidl>
+ <Type type="unrestricted double"/>
+ </Const>
+ <Const name="notanumber" value="NaN" id="::Util::notanumber">
+ <webidl> const short notanumber = NaN;</webidl>
+ <Type type="short"/>
+ </Const>
+ </Interface>
+ <Exception name="Error" id="::Error">
+ <webidl>exception Error {
+ const short ERR_UNKNOWN = 0;
+ const short ERR_OUT_OF_MEMORY = 1;
+
+ short errorCode;
+};</webidl>
+ <Const name="ERR_UNKNOWN" value="0" id="::Error::ERR_UNKNOWN">
+ <webidl> const short ERR_UNKNOWN = 0;</webidl>
+ <Type type="short"/>
+ </Const>
+ <Const name="ERR_OUT_OF_MEMORY" value="1" id="::Error::ERR_OUT_OF_MEMORY">
+ <webidl> const short ERR_OUT_OF_MEMORY = 1;</webidl>
+ <Type type="short"/>
+ </Const>
+ <ExceptionField name="errorCode" id="::Error::errorCode">
+ <webidl> short errorCode;</webidl>
+ <Type type="short"/>
+ </ExceptionField>
+ </Exception>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/constructor.widlprocxml b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/constructor.widlprocxml
new file mode 100644
index 00000000000..8e78fbab365
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/constructor.widlprocxml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>[Constructor,
+ Constructor(float radius)]
+interface Circle {
+ attribute float r;
+ attribute float cx;
+ attribute float cy;
+ readonly attribute float circumference;
+};</webidl>
+ <Interface name="Circle" id="::Circle">
+ <webidl>[Constructor,
+ Constructor(float radius)]
+interface Circle {
+ attribute float r;
+ attribute float cx;
+ attribute float cy;
+ readonly attribute float circumference;
+};</webidl>
+ <ExtendedAttributeList>
+ <ExtendedAttribute name="Constructor">
+ <webidl>Constructor</webidl>
+ </ExtendedAttribute>
+ <ExtendedAttribute name="Constructor">
+ <webidl> Constructor(float radius)</webidl>
+ <ArgumentList>
+ <Argument name="radius">
+ <Type type="float"/>
+ </Argument>
+ </ArgumentList>
+ </ExtendedAttribute>
+ </ExtendedAttributeList>
+ <Attribute name="r" id="::Circle::r">
+ <webidl> attribute float r;</webidl>
+ <Type type="float"/>
+ </Attribute>
+ <Attribute name="cx" id="::Circle::cx">
+ <webidl> attribute float cx;</webidl>
+ <Type type="float"/>
+ </Attribute>
+ <Attribute name="cy" id="::Circle::cy">
+ <webidl> attribute float cy;</webidl>
+ <Type type="float"/>
+ </Attribute>
+ <Attribute readonly="readonly" name="circumference" id="::Circle::circumference">
+ <webidl> readonly attribute float circumference;</webidl>
+ <Type type="float"/>
+ </Attribute>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/dictionary-inherits.widlprocxml b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/dictionary-inherits.widlprocxml
new file mode 100644
index 00000000000..269a83cd849
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/dictionary-inherits.widlprocxml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>dictionary PaintOptions {
+ DOMString? fillPattern = &quot;black&quot;;
+ DOMString? strokePattern = null;
+ <ref>Point</ref> position;
+};
+
+dictionary WetPaintOptions : <ref>PaintOptions</ref> {
+ float hydrometry;
+};</webidl>
+ <Dictionary name="PaintOptions" id="::PaintOptions">
+ <webidl>dictionary PaintOptions {
+ DOMString? fillPattern = &quot;black&quot;;
+ DOMString? strokePattern = null;
+ <ref>Point</ref> position;
+};</webidl>
+ <DictionaryMember name="fillPattern" stringvalue="black" id="::PaintOptions::fillPattern">
+ <webidl> DOMString? fillPattern = &quot;black&quot;;</webidl>
+ <Type type="DOMString" nullable="nullable"/>
+ </DictionaryMember>
+ <DictionaryMember name="strokePattern" value="null" id="::PaintOptions::strokePattern">
+ <webidl> DOMString? strokePattern = null;</webidl>
+ <Type type="DOMString" nullable="nullable"/>
+ </DictionaryMember>
+ <DictionaryMember name="position" id="::PaintOptions::position">
+ <webidl> <ref>Point</ref> position;</webidl>
+ <Type name="Point"/>
+ </DictionaryMember>
+ </Dictionary>
+ <Dictionary name="WetPaintOptions" id="::WetPaintOptions">
+ <webidl>dictionary WetPaintOptions : <ref>PaintOptions</ref> {
+ float hydrometry;
+};</webidl>
+ <DictionaryInheritance>
+ <Name name="PaintOptions"/>
+ </DictionaryInheritance>
+ <DictionaryMember name="hydrometry" id="::WetPaintOptions::hydrometry">
+ <webidl> float hydrometry;</webidl>
+ <Type type="float"/>
+ </DictionaryMember>
+ </Dictionary>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/dictionary.widlprocxml b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/dictionary.widlprocxml
new file mode 100644
index 00000000000..978ccb4e271
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/dictionary.widlprocxml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>dictionary PaintOptions {
+ DOMString? fillPattern = &quot;black&quot;;
+ DOMString? strokePattern = null;
+ <ref>Point</ref> position;
+};
+
+partial dictionary A {
+ long h;
+ long d;
+};</webidl>
+ <Dictionary name="PaintOptions" id="::PaintOptions">
+ <webidl>dictionary PaintOptions {
+ DOMString? fillPattern = &quot;black&quot;;
+ DOMString? strokePattern = null;
+ <ref>Point</ref> position;
+};</webidl>
+ <DictionaryMember name="fillPattern" stringvalue="black" id="::PaintOptions::fillPattern">
+ <webidl> DOMString? fillPattern = &quot;black&quot;;</webidl>
+ <Type type="DOMString" nullable="nullable"/>
+ </DictionaryMember>
+ <DictionaryMember name="strokePattern" value="null" id="::PaintOptions::strokePattern">
+ <webidl> DOMString? strokePattern = null;</webidl>
+ <Type type="DOMString" nullable="nullable"/>
+ </DictionaryMember>
+ <DictionaryMember name="position" id="::PaintOptions::position">
+ <webidl> <ref>Point</ref> position;</webidl>
+ <Type name="Point"/>
+ </DictionaryMember>
+ </Dictionary>
+ <Dictionary name="A" partial="partial" id="::A">
+ <webidl>partial dictionary A {
+ long h;
+ long d;
+};</webidl>
+ <DictionaryMember name="h" id="::A::h">
+ <webidl> long h;</webidl>
+ <Type type="long"/>
+ </DictionaryMember>
+ <DictionaryMember name="d" id="::A::d">
+ <webidl> long d;</webidl>
+ <Type type="long"/>
+ </DictionaryMember>
+ </Dictionary>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/documentation-dos.widlprocxml b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/documentation-dos.widlprocxml
new file mode 100644
index 00000000000..1611f0e576a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/documentation-dos.widlprocxml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Documentation {};</webidl>
+ <Interface name="Documentation" id="::Documentation">
+ <webidl>interface Documentation {};</webidl>
+ <descriptive>
+ <brief>
+ Testing documentation features
+ </brief>
+ <description>
+ <p>
+This is a
+single paragraph
+ </p>
+ <p>
+This is valid. </p>
+ <p>
+This is <em>valid</em>. </p>
+ <p>
+This is <b>valid</b>. </p>
+ <p>
+This is <a href=''>valid</a>. </p>
+ <ul>
+ <li>
+This </li>
+ <li>
+is </li>
+ <li>
+valid </li>
+ </ul>
+ <dl>
+ <dt>
+This </dt>
+ <dd>
+valid </dd>
+ </dl>
+ <table>
+ <tr>
+ <td>
+this </td>
+ <td>
+is </td>
+ </tr>
+ <tr>
+ <td>
+valid </td>
+ </tr>
+ </table>
+ <p>
+This is <br/> valid. </p>
+ <p>
+This is <br /> valid. </p>
+ <p>
+This is <br/> valid. </p>
+ </description>
+ </descriptive>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/documentation.widlprocxml b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/documentation.widlprocxml
new file mode 100644
index 00000000000..afe4527c221
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/documentation.widlprocxml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Documentation {};</webidl>
+ <Interface name="Documentation" id="::Documentation">
+ <webidl>interface Documentation {};</webidl>
+ <descriptive>
+ <brief>
+ Testing documentation features
+ </brief>
+ <description>
+ <p>
+This is a
+single paragraph
+ </p>
+ <p>
+This is valid. </p>
+ <p>
+This is <em>valid</em>. </p>
+ <p>
+This is <b>valid</b>. </p>
+ <p>
+This is <a href=''>valid</a>. </p>
+ <ul>
+ <li>
+This </li>
+ <li>
+is </li>
+ <li>
+valid </li>
+ </ul>
+ <dl>
+ <dt>
+This </dt>
+ <dd>
+valid </dd>
+ </dl>
+ <table>
+ <tr>
+ <td>
+this </td>
+ <td>
+is </td>
+ </tr>
+ <tr>
+ <td>
+valid </td>
+ </tr>
+ </table>
+ <p>
+This is <br/> valid. </p>
+ <p>
+This is <br /> valid. </p>
+ <p>
+This is <br/> valid. </p>
+ <p>
+<img src="foo.png" alt="Valid"/> </p>
+ </description>
+ </descriptive>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/enum.widlprocxml b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/enum.widlprocxml
new file mode 100644
index 00000000000..e1e8258fbd0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/enum.widlprocxml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>enum MealType { &quot;rice&quot;, &quot;noodles&quot;, &quot;other&quot; };
+
+interface Meal {
+ attribute <ref>MealType</ref> type;
+ attribute float size;
+
+ void initialize(<ref>MealType</ref> type, float size);
+};</webidl>
+ <Enum name="MealType" id="::MealType">
+ <webidl>enum MealType { &quot;rice&quot;, &quot;noodles&quot;, &quot;other&quot; };</webidl>
+ <EnumValue stringvalue="rice">
+ <webidl> &quot;rice</webidl>
+ </EnumValue>
+ <EnumValue stringvalue="noodles">
+ <webidl> &quot;noodles</webidl>
+ </EnumValue>
+ <EnumValue stringvalue="other">
+ <webidl> &quot;other</webidl>
+ </EnumValue>
+ </Enum>
+ <Interface name="Meal" id="::Meal">
+ <webidl>interface Meal {
+ attribute <ref>MealType</ref> type;
+ attribute float size;
+
+ void initialize(<ref>MealType</ref> type, float size);
+};</webidl>
+ <Attribute name="type" id="::Meal::type">
+ <webidl> attribute <ref>MealType</ref> type;</webidl>
+ <Type name="MealType"/>
+ </Attribute>
+ <Attribute name="size" id="::Meal::size">
+ <webidl> attribute float size;</webidl>
+ <Type type="float"/>
+ </Attribute>
+ <Operation name="initialize" id="::Meal::initialize">
+ <webidl> void initialize(<ref>MealType</ref> type, float size);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="type">
+ <Type name="MealType"/>
+ </Argument>
+ <Argument name="size">
+ <Type type="float"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/equivalent-decl.widlprocxml b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/equivalent-decl.widlprocxml
new file mode 100644
index 00000000000..c322d0a5e22
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/equivalent-decl.widlprocxml
@@ -0,0 +1,111 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Dictionary {
+ readonly attribute unsigned long propertyCount;
+
+ getter float getProperty(DOMString propertyName);
+ setter void setProperty(DOMString propertyName, float propertyValue);
+};
+
+
+interface Dictionary {
+ readonly attribute unsigned long propertyCount;
+
+ float getProperty(DOMString propertyName);
+ void setProperty(DOMString propertyName, float propertyValue);
+
+ getter float (DOMString propertyName);
+ setter void (DOMString propertyName, float propertyValue);
+};</webidl>
+ <Interface name="Dictionary" id="::Dictionary">
+ <webidl>interface Dictionary {
+ readonly attribute unsigned long propertyCount;
+
+ getter float getProperty(DOMString propertyName);
+ setter void setProperty(DOMString propertyName, float propertyValue);
+};</webidl>
+ <Attribute readonly="readonly" name="propertyCount" id="::Dictionary::propertyCount">
+ <webidl> readonly attribute unsigned long propertyCount;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Operation getter="getter" name="getProperty" id="::Dictionary::getProperty">
+ <webidl> getter float getProperty(DOMString propertyName);</webidl>
+ <Type type="float"/>
+ <ArgumentList>
+ <Argument name="propertyName">
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation setter="setter" name="setProperty" id="::Dictionary::setProperty">
+ <webidl> setter void setProperty(DOMString propertyName, float propertyValue);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="propertyName">
+ <Type type="DOMString"/>
+ </Argument>
+ <Argument name="propertyValue">
+ <Type type="float"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+ <Interface name="Dictionary" id="::Dictionary">
+ <webidl>interface Dictionary {
+ readonly attribute unsigned long propertyCount;
+
+ float getProperty(DOMString propertyName);
+ void setProperty(DOMString propertyName, float propertyValue);
+
+ getter float (DOMString propertyName);
+ setter void (DOMString propertyName, float propertyValue);
+};</webidl>
+ <Attribute readonly="readonly" name="propertyCount" id="::Dictionary::propertyCount">
+ <webidl> readonly attribute unsigned long propertyCount;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Operation name="getProperty" id="::Dictionary::getProperty">
+ <webidl> float getProperty(DOMString propertyName);</webidl>
+ <Type type="float"/>
+ <ArgumentList>
+ <Argument name="propertyName">
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation name="setProperty" id="::Dictionary::setProperty">
+ <webidl> void setProperty(DOMString propertyName, float propertyValue);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="propertyName">
+ <Type type="DOMString"/>
+ </Argument>
+ <Argument name="propertyValue">
+ <Type type="float"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation getter="getter">
+ <webidl> getter float (DOMString propertyName);</webidl>
+ <Type type="float"/>
+ <ArgumentList>
+ <Argument name="propertyName">
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation setter="setter">
+ <webidl> setter void (DOMString propertyName, float propertyValue);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="propertyName">
+ <Type type="DOMString"/>
+ </Argument>
+ <Argument name="propertyValue">
+ <Type type="float"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/exception-inheritance.widlprocxml b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/exception-inheritance.widlprocxml
new file mode 100644
index 00000000000..3a1f868a4b4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/exception-inheritance.widlprocxml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl> exception DOMException {
+ unsigned short code;
+ };
+
+ exception HierarchyRequestError : <ref>DOMException</ref> { };
+ exception NoModificationAllowedError : <ref>DOMException</ref> { };</webidl>
+ <Exception name="DOMException" id="::DOMException">
+ <webidl> exception DOMException {
+ unsigned short code;
+ };</webidl>
+ <ExceptionField name="code" id="::DOMException::code">
+ <webidl> unsigned short code;</webidl>
+ <Type type="unsigned short"/>
+ </ExceptionField>
+ </Exception>
+ <Exception name="HierarchyRequestError" id="::HierarchyRequestError">
+ <webidl> exception HierarchyRequestError : <ref>DOMException</ref> { };</webidl>
+ <ExceptionInheritance>
+ <Name name="DOMException"/>
+ </ExceptionInheritance>
+ </Exception>
+ <Exception name="NoModificationAllowedError" id="::NoModificationAllowedError">
+ <webidl> exception NoModificationAllowedError : <ref>DOMException</ref> { };</webidl>
+ <ExceptionInheritance>
+ <Name name="DOMException"/>
+ </ExceptionInheritance>
+ </Exception>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/exception.widlprocxml b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/exception.widlprocxml
new file mode 100644
index 00000000000..ac93320fe16
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/exception.widlprocxml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Dahut {
+ attribute DOMString type;
+};
+
+exception SomeException {
+};</webidl>
+ <Interface name="Dahut" id="::Dahut">
+ <webidl>interface Dahut {
+ attribute DOMString type;
+};</webidl>
+ <Attribute name="type" id="::Dahut::type">
+ <webidl> attribute DOMString type;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ </Interface>
+ <Exception name="SomeException" id="::SomeException">
+ <webidl>exception SomeException {
+};</webidl>
+ </Exception>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/getter-setter.widlprocxml b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/getter-setter.widlprocxml
new file mode 100644
index 00000000000..76afc058c68
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/getter-setter.widlprocxml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Dictionary {
+ readonly attribute unsigned long propertyCount;
+
+ getter float (DOMString propertyName);
+ setter void (DOMString propertyName, float propertyValue);
+};</webidl>
+ <Interface name="Dictionary" id="::Dictionary">
+ <webidl>interface Dictionary {
+ readonly attribute unsigned long propertyCount;
+
+ getter float (DOMString propertyName);
+ setter void (DOMString propertyName, float propertyValue);
+};</webidl>
+ <Attribute readonly="readonly" name="propertyCount" id="::Dictionary::propertyCount">
+ <webidl> readonly attribute unsigned long propertyCount;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Operation getter="getter">
+ <webidl> getter float (DOMString propertyName);</webidl>
+ <Type type="float"/>
+ <ArgumentList>
+ <Argument name="propertyName">
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation setter="setter">
+ <webidl> setter void (DOMString propertyName, float propertyValue);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="propertyName">
+ <Type type="DOMString"/>
+ </Argument>
+ <Argument name="propertyValue">
+ <Type type="float"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/identifier-qualified-names.widlprocxml b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/identifier-qualified-names.widlprocxml
new file mode 100644
index 00000000000..b6024e5ff68
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/identifier-qualified-names.widlprocxml
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl> typedef float number;
+
+ exception FrameworkException {
+
+ const long ERR_NOT_FOUND = 1;
+
+ long code;
+ };
+
+ interface System {
+
+ object createObject(DOMString _interface);
+
+ getter DOMString (DOMString keyName);
+ };
+
+
+ interface TextField {
+
+ attribute boolean _const;
+
+ attribute DOMString? _value;
+ };
+
+interface Foo {
+ void op(object interface);
+};</webidl>
+ <Typedef name="number" id="::number">
+ <webidl> typedef float number;</webidl>
+ <Type type="float"/>
+ </Typedef>
+ <Exception name="FrameworkException" id="::FrameworkException">
+ <webidl> exception FrameworkException {
+
+ const long ERR_NOT_FOUND = 1;
+
+ long code;
+ };</webidl>
+ <Const name="ERR_NOT_FOUND" value="1" id="::FrameworkException::ERR_NOT_FOUND">
+ <webidl> const long ERR_NOT_FOUND = 1;</webidl>
+ <Type type="long"/>
+ </Const>
+ <ExceptionField name="code" id="::FrameworkException::code">
+ <webidl> long code;</webidl>
+ <Type type="long"/>
+ </ExceptionField>
+ </Exception>
+ <Interface name="System" id="::System">
+ <webidl> interface System {
+
+ object createObject(DOMString _interface);
+
+ getter DOMString (DOMString keyName);
+ };</webidl>
+ <Operation name="createObject" id="::System::createObject">
+ <webidl> object createObject(DOMString _interface);</webidl>
+ <Type type="object"/>
+ <ArgumentList>
+ <Argument name="_interface">
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation getter="getter">
+ <webidl> getter DOMString (DOMString keyName);</webidl>
+ <Type type="DOMString"/>
+ <ArgumentList>
+ <Argument name="keyName">
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+ <Interface name="TextField" id="::TextField">
+ <webidl> interface TextField {
+
+ attribute boolean _const;
+
+ attribute DOMString? _value;
+ };</webidl>
+ <Attribute name="_const" id="::TextField::_const">
+ <webidl> attribute boolean _const;</webidl>
+ <Type type="boolean"/>
+ </Attribute>
+ <Attribute name="_value" id="::TextField::_value">
+ <webidl> attribute DOMString? _value;</webidl>
+ <Type type="DOMString" nullable="nullable"/>
+ </Attribute>
+ </Interface>
+ <Interface name="Foo" id="::Foo">
+ <webidl>interface Foo {
+ void op(object interface);
+};</webidl>
+ <Operation name="op" id="::Foo::op">
+ <webidl> void op(object interface);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="interface">
+ <Type type="object"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/implements.widlprocxml b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/implements.widlprocxml
new file mode 100644
index 00000000000..3d1c1ab8478
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/implements.widlprocxml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl> interface Node {
+ readonly attribute unsigned short nodeType;
+ };
+
+ interface EventTarget {
+ void addEventListener(DOMString type,
+ <ref>EventListener</ref> listener,
+ boolean useCapture);
+ };
+
+ <ref>Node</ref> implements <ref>EventTarget</ref>;</webidl>
+ <Interface name="Node" id="::Node">
+ <webidl> interface Node {
+ readonly attribute unsigned short nodeType;
+ };</webidl>
+ <Attribute readonly="readonly" name="nodeType" id="::Node::nodeType">
+ <webidl> readonly attribute unsigned short nodeType;</webidl>
+ <Type type="unsigned short"/>
+ </Attribute>
+ </Interface>
+ <Interface name="EventTarget" id="::EventTarget">
+ <webidl> interface EventTarget {
+ void addEventListener(DOMString type,
+ <ref>EventListener</ref> listener,
+ boolean useCapture);
+ };</webidl>
+ <Operation name="addEventListener" id="::EventTarget::addEventListener">
+ <webidl> void addEventListener(DOMString type,
+ <ref>EventListener</ref> listener,
+ boolean useCapture);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="type">
+ <Type type="DOMString"/>
+ </Argument>
+ <Argument name="listener">
+ <Type name="EventListener"/>
+ </Argument>
+ <Argument name="useCapture">
+ <Type type="boolean"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+ <Implements name1="Node" name2="EventTarget">
+ <webidl> <ref>Node</ref> implements <ref>EventTarget</ref>;</webidl>
+ </Implements>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/indexed-properties.widlprocxml b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/indexed-properties.widlprocxml
new file mode 100644
index 00000000000..fb83621b60d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/indexed-properties.widlprocxml
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface OrderedMap {
+ readonly attribute unsigned long size;
+
+ getter any getByIndex(unsigned long index);
+ setter void setByIndex(unsigned long index, any value);
+ deleter void removeByIndex(unsigned long index);
+
+ getter any get(DOMString name);
+ setter creator void set(DOMString name, any value);
+ deleter void remove(DOMString name);
+};</webidl>
+ <Interface name="OrderedMap" id="::OrderedMap">
+ <webidl>interface OrderedMap {
+ readonly attribute unsigned long size;
+
+ getter any getByIndex(unsigned long index);
+ setter void setByIndex(unsigned long index, any value);
+ deleter void removeByIndex(unsigned long index);
+
+ getter any get(DOMString name);
+ setter creator void set(DOMString name, any value);
+ deleter void remove(DOMString name);
+};</webidl>
+ <Attribute readonly="readonly" name="size" id="::OrderedMap::size">
+ <webidl> readonly attribute unsigned long size;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Operation getter="getter" name="getByIndex" id="::OrderedMap::getByIndex">
+ <webidl> getter any getByIndex(unsigned long index);</webidl>
+ <Type type="any"/>
+ <ArgumentList>
+ <Argument name="index">
+ <Type type="unsigned long"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation setter="setter" name="setByIndex" id="::OrderedMap::setByIndex">
+ <webidl> setter void setByIndex(unsigned long index, any value);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="index">
+ <Type type="unsigned long"/>
+ </Argument>
+ <Argument name="value">
+ <Type type="any"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation deleter="deleter" name="removeByIndex" id="::OrderedMap::removeByIndex">
+ <webidl> deleter void removeByIndex(unsigned long index);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="index">
+ <Type type="unsigned long"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation getter="getter" name="get" id="::OrderedMap::get">
+ <webidl> getter any get(DOMString name);</webidl>
+ <Type type="any"/>
+ <ArgumentList>
+ <Argument name="name">
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation setter="setter" creator="creator" name="set" id="::OrderedMap::set">
+ <webidl> setter creator void set(DOMString name, any value);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="name">
+ <Type type="DOMString"/>
+ </Argument>
+ <Argument name="value">
+ <Type type="any"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation deleter="deleter" name="remove" id="::OrderedMap::remove">
+ <webidl> deleter void remove(DOMString name);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="name">
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/inherits-getter.widlprocxml b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/inherits-getter.widlprocxml
new file mode 100644
index 00000000000..55e7a317fd9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/inherits-getter.widlprocxml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Animal {
+
+ readonly attribute DOMString name;
+};
+
+interface Person : <ref>Animal</ref> {
+
+ readonly attribute unsigned short age;
+
+ inherit attribute DOMString name;
+};</webidl>
+ <Interface name="Animal" id="::Animal">
+ <webidl>interface Animal {
+
+ readonly attribute DOMString name;
+};</webidl>
+ <Attribute readonly="readonly" name="name" id="::Animal::name">
+ <webidl> readonly attribute DOMString name;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ </Interface>
+ <Interface name="Person" id="::Person">
+ <webidl>interface Person : <ref>Animal</ref> {
+
+ readonly attribute unsigned short age;
+
+ inherit attribute DOMString name;
+};</webidl>
+ <InterfaceInheritance>
+ <Name name="Animal"/>
+ </InterfaceInheritance>
+ <Attribute readonly="readonly" name="age" id="::Person::age">
+ <webidl> readonly attribute unsigned short age;</webidl>
+ <Type type="unsigned short"/>
+ </Attribute>
+ <Attribute inherit="inherit" name="name" id="::Person::name">
+ <webidl> inherit attribute DOMString name;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/interface-inherits.widlprocxml b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/interface-inherits.widlprocxml
new file mode 100644
index 00000000000..94f0e29df05
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/interface-inherits.widlprocxml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Animal {
+ attribute DOMString name;
+};
+
+interface Human : <ref>Animal</ref> {
+ attribute <ref>Dog</ref> pet;
+};
+
+interface Dog : <ref>Animal</ref> {
+ attribute <ref>Human</ref> owner;
+};</webidl>
+ <Interface name="Animal" id="::Animal">
+ <webidl>interface Animal {
+ attribute DOMString name;
+};</webidl>
+ <Attribute name="name" id="::Animal::name">
+ <webidl> attribute DOMString name;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ </Interface>
+ <Interface name="Human" id="::Human">
+ <webidl>interface Human : <ref>Animal</ref> {
+ attribute <ref>Dog</ref> pet;
+};</webidl>
+ <InterfaceInheritance>
+ <Name name="Animal"/>
+ </InterfaceInheritance>
+ <Attribute name="pet" id="::Human::pet">
+ <webidl> attribute <ref>Dog</ref> pet;</webidl>
+ <Type name="Dog"/>
+ </Attribute>
+ </Interface>
+ <Interface name="Dog" id="::Dog">
+ <webidl>interface Dog : <ref>Animal</ref> {
+ attribute <ref>Human</ref> owner;
+};</webidl>
+ <InterfaceInheritance>
+ <Name name="Animal"/>
+ </InterfaceInheritance>
+ <Attribute name="owner" id="::Dog::owner">
+ <webidl> attribute <ref>Human</ref> owner;</webidl>
+ <Type name="Human"/>
+ </Attribute>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/iterator.widlprocxml b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/iterator.widlprocxml
new file mode 100644
index 00000000000..8ca95fbbd17
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/iterator.widlprocxml
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface SessionManager {
+ <ref>Session</ref> getSessionForUser(DOMString username);
+ readonly attribute unsigned long sessionCount;
+
+ <ref>Session</ref> iterator;
+};
+
+interface Session {
+ readonly attribute DOMString username;
+};
+
+interface SessionManager2 {
+ <ref>Session2</ref> getSessionForUser(DOMString username);
+ readonly attribute unsigned long sessionCount;
+
+ <ref>Session2</ref> iterator = SessionIterator;
+};
+
+interface Session2 {
+ readonly attribute DOMString username;
+};
+
+interface SessionIterator {
+ readonly attribute unsigned long remainingSessions;
+};
+
+ interface NodeList {
+ <ref>Node</ref> iterator = NodeIterator;
+ };
+
+ interface NodeIterator {
+ <ref>Node</ref> iterator object;
+ };</webidl>
+ <Interface name="SessionManager" id="::SessionManager">
+ <webidl>interface SessionManager {
+ <ref>Session</ref> getSessionForUser(DOMString username);
+ readonly attribute unsigned long sessionCount;
+
+ <ref>Session</ref> iterator;
+};</webidl>
+ <Operation name="getSessionForUser" id="::SessionManager::getSessionForUser">
+ <webidl> <ref>Session</ref> getSessionForUser(DOMString username);</webidl>
+ <Type name="Session"/>
+ <ArgumentList>
+ <Argument name="username">
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Attribute readonly="readonly" name="sessionCount" id="::SessionManager::sessionCount">
+ <webidl> readonly attribute unsigned long sessionCount;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Iterator>
+ <webidl> <ref>Session</ref> iterator;</webidl>
+ <Type name="Session"/>
+ </Iterator>
+ </Interface>
+ <Interface name="Session" id="::Session">
+ <webidl>interface Session {
+ readonly attribute DOMString username;
+};</webidl>
+ <Attribute readonly="readonly" name="username" id="::Session::username">
+ <webidl> readonly attribute DOMString username;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ </Interface>
+ <Interface name="SessionManager2" id="::SessionManager2">
+ <webidl>interface SessionManager2 {
+ <ref>Session2</ref> getSessionForUser(DOMString username);
+ readonly attribute unsigned long sessionCount;
+
+ <ref>Session2</ref> iterator = SessionIterator;
+};</webidl>
+ <Operation name="getSessionForUser" id="::SessionManager2::getSessionForUser">
+ <webidl> <ref>Session2</ref> getSessionForUser(DOMString username);</webidl>
+ <Type name="Session2"/>
+ <ArgumentList>
+ <Argument name="username">
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Attribute readonly="readonly" name="sessionCount" id="::SessionManager2::sessionCount">
+ <webidl> readonly attribute unsigned long sessionCount;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Iterator interface="SessionIterator">
+ <webidl> <ref>Session2</ref> iterator = SessionIterator;</webidl>
+ <Type name="Session2"/>
+ </Iterator>
+ </Interface>
+ <Interface name="Session2" id="::Session2">
+ <webidl>interface Session2 {
+ readonly attribute DOMString username;
+};</webidl>
+ <Attribute readonly="readonly" name="username" id="::Session2::username">
+ <webidl> readonly attribute DOMString username;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ </Interface>
+ <Interface name="SessionIterator" id="::SessionIterator">
+ <webidl>interface SessionIterator {
+ readonly attribute unsigned long remainingSessions;
+};</webidl>
+ <Attribute readonly="readonly" name="remainingSessions" id="::SessionIterator::remainingSessions">
+ <webidl> readonly attribute unsigned long remainingSessions;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ </Interface>
+ <Interface name="NodeList" id="::NodeList">
+ <webidl> interface NodeList {
+ <ref>Node</ref> iterator = NodeIterator;
+ };</webidl>
+ <Iterator interface="NodeIterator">
+ <webidl> <ref>Node</ref> iterator = NodeIterator;</webidl>
+ <Type name="Node"/>
+ </Iterator>
+ </Interface>
+ <Interface name="NodeIterator" id="::NodeIterator">
+ <webidl> interface NodeIterator {
+ <ref>Node</ref> iterator object;
+ };</webidl>
+ <IteratorObject>
+ <webidl> <ref>Node</ref> iterator object;</webidl>
+ <Type name="Node"/>
+ </IteratorObject>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/module.widlprocxml b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/module.widlprocxml
new file mode 100644
index 00000000000..b575b8705af
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/module.widlprocxml
@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <Module name="gfx" id="::gfx">
+ <webidl>module gfx {
+
+ module geom {
+ interface Shape { };
+ interface Rectangle : <ref>Shape</ref> { };
+ interface Path : <ref>Shape</ref> { };
+ };
+
+ interface GraphicsContext {
+ void fillShape(<ref>geom::Shape</ref> s);
+ void strokeShape(<ref>geom::Shape</ref> s);
+ };
+};</webidl>
+ <Module name="geom" id="::gfx::geom">
+ <webidl> module geom {
+ interface Shape { };
+ interface Rectangle : <ref>Shape</ref> { };
+ interface Path : <ref>Shape</ref> { };
+ };</webidl>
+ <Interface name="Shape" id="::gfx::geom::Shape">
+ <webidl> interface Shape { };</webidl>
+ </Interface>
+ <Interface name="Rectangle" id="::gfx::geom::Rectangle">
+ <webidl> interface Rectangle : <ref>Shape</ref> { };</webidl>
+ <InterfaceInheritance>
+ <Name name="Shape"/>
+ </InterfaceInheritance>
+ </Interface>
+ <Interface name="Path" id="::gfx::geom::Path">
+ <webidl> interface Path : <ref>Shape</ref> { };</webidl>
+ <InterfaceInheritance>
+ <Name name="Shape"/>
+ </InterfaceInheritance>
+ </Interface>
+ </Module>
+ <Interface name="GraphicsContext" id="::gfx::GraphicsContext">
+ <webidl> interface GraphicsContext {
+ void fillShape(<ref>geom::Shape</ref> s);
+ void strokeShape(<ref>geom::Shape</ref> s);
+ };</webidl>
+ <Operation name="fillShape" id="::gfx::GraphicsContext::fillShape">
+ <webidl> void fillShape(<ref>geom::Shape</ref> s);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="s">
+ <Type name="geom::Shape"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation name="strokeShape" id="::gfx::GraphicsContext::strokeShape">
+ <webidl> void strokeShape(<ref>geom::Shape</ref> s);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="s">
+ <Type name="geom::Shape"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+ </Module>
+ <Module name="gui" id="::gui">
+ <webidl>module gui {
+
+ interface Widget { };
+
+ interface Window : <ref>Widget</ref> {
+ <ref>gfx::GraphicsContext</ref> getGraphicsContext();
+ };
+
+ interface Button : <ref>Widget</ref> { };
+};</webidl>
+ <Interface name="Widget" id="::gui::Widget">
+ <webidl> interface Widget { };</webidl>
+ </Interface>
+ <Interface name="Window" id="::gui::Window">
+ <webidl> interface Window : <ref>Widget</ref> {
+ <ref>gfx::GraphicsContext</ref> getGraphicsContext();
+ };</webidl>
+ <InterfaceInheritance>
+ <Name name="Widget"/>
+ </InterfaceInheritance>
+ <Operation name="getGraphicsContext" id="::gui::Window::getGraphicsContext">
+ <webidl> <ref>gfx::GraphicsContext</ref> getGraphicsContext();</webidl>
+ <Type name="gfx::GraphicsContext"/>
+ <ArgumentList/>
+ </Operation>
+ </Interface>
+ <Interface name="Button" id="::gui::Button">
+ <webidl> interface Button : <ref>Widget</ref> { };</webidl>
+ <InterfaceInheritance>
+ <Name name="Widget"/>
+ </InterfaceInheritance>
+ </Interface>
+ </Module>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/namedconstructor.widlprocxml b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/namedconstructor.widlprocxml
new file mode 100644
index 00000000000..9f661612879
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/namedconstructor.widlprocxml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>[NamedConstructor=Audio,
+ NamedConstructor=Audio(DOMString src)]
+interface HTMLAudioElement : <ref>HTMLMediaElement</ref> {
+};</webidl>
+ <Interface name="HTMLAudioElement" id="::HTMLAudioElement">
+ <webidl>[NamedConstructor=Audio,
+ NamedConstructor=Audio(DOMString src)]
+interface HTMLAudioElement : <ref>HTMLMediaElement</ref> {
+};</webidl>
+ <ExtendedAttributeList>
+ <ExtendedAttribute name="NamedConstructor" value="Audio">
+ <webidl>NamedConstructor</webidl>
+ </ExtendedAttribute>
+ <ExtendedAttribute name="NamedConstructor" value="Audio">
+ <webidl> NamedConstructor=Audio(DOMString src)</webidl>
+ <ArgumentList>
+ <Argument name="src">
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </ExtendedAttribute>
+ </ExtendedAttributeList>
+ <InterfaceInheritance>
+ <Name name="HTMLMediaElement"/>
+ </InterfaceInheritance>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/namespaceobject.widlprocxml b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/namespaceobject.widlprocxml
new file mode 100644
index 00000000000..af0cde93719
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/namespaceobject.widlprocxml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <Module name="acme" id="::acme">
+ <webidl>[NamespaceObject]
+module acme {
+
+ exception DeviceException { };
+
+ module pim {
+
+ [Constructor]
+ interface Contact { };
+
+ [Constructor,
+ NamedConstructor=RecurringEvent(long freq)]
+ interface CalendarEvent { };
+ };
+};</webidl>
+ <ExtendedAttributeList>
+ <ExtendedAttribute name="NamespaceObject"/>
+ </ExtendedAttributeList>
+ <Exception name="DeviceException" id="::acme::DeviceException">
+ <webidl> exception DeviceException { };</webidl>
+ </Exception>
+ <Module name="pim" id="::acme::pim">
+ <webidl> module pim {
+
+ [Constructor]
+ interface Contact { };
+
+ [Constructor,
+ NamedConstructor=RecurringEvent(long freq)]
+ interface CalendarEvent { };
+ };</webidl>
+ <Interface name="Contact" id="::acme::pim::Contact">
+ <webidl> [Constructor]
+ interface Contact { };</webidl>
+ <ExtendedAttributeList>
+ <ExtendedAttribute name="Constructor"/>
+ </ExtendedAttributeList>
+ </Interface>
+ <Interface name="CalendarEvent" id="::acme::pim::CalendarEvent">
+ <webidl> [Constructor,
+ NamedConstructor=RecurringEvent(long freq)]
+ interface CalendarEvent { };</webidl>
+ <ExtendedAttributeList>
+ <ExtendedAttribute name="Constructor"/>
+ <ExtendedAttribute name="NamedConstructor" value="RecurringEvent">
+ <ArgumentList>
+ <Argument name="freq">
+ <Type type="long"/>
+ </Argument>
+ </ArgumentList>
+ </ExtendedAttribute>
+ </ExtendedAttributeList>
+ </Interface>
+ </Module>
+ </Module>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/nointerfaceobject.widlprocxml b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/nointerfaceobject.widlprocxml
new file mode 100644
index 00000000000..f64f116b60f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/nointerfaceobject.widlprocxml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>[NoInterfaceObject]
+interface Query {
+ any lookupEntry(unsigned long key);
+};</webidl>
+ <Interface name="Query" id="::Query">
+ <webidl>[NoInterfaceObject]
+interface Query {
+ any lookupEntry(unsigned long key);
+};</webidl>
+ <ExtendedAttributeList>
+ <ExtendedAttribute name="NoInterfaceObject">
+ <webidl>NoInterfaceObject</webidl>
+ </ExtendedAttribute>
+ </ExtendedAttributeList>
+ <Operation name="lookupEntry" id="::Query::lookupEntry">
+ <webidl> any lookupEntry(unsigned long key);</webidl>
+ <Type type="any"/>
+ <ArgumentList>
+ <Argument name="key">
+ <Type type="unsigned long"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/nullable.widlprocxml b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/nullable.widlprocxml
new file mode 100644
index 00000000000..8739e443262
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/nullable.widlprocxml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface MyConstants {
+ const boolean? ARE_WE_THERE_YET = false;
+};
+
+interface Node {
+ readonly attribute DOMString? namespaceURI;
+};</webidl>
+ <Interface name="MyConstants" id="::MyConstants">
+ <webidl>interface MyConstants {
+ const boolean? ARE_WE_THERE_YET = false;
+};</webidl>
+ <Const name="ARE_WE_THERE_YET" value="false" id="::MyConstants::ARE_WE_THERE_YET">
+ <webidl> const boolean? ARE_WE_THERE_YET = false;</webidl>
+ <Type type="boolean" nullable="nullable"/>
+ </Const>
+ </Interface>
+ <Interface name="Node" id="::Node">
+ <webidl>interface Node {
+ readonly attribute DOMString? namespaceURI;
+};</webidl>
+ <Attribute readonly="readonly" name="namespaceURI" id="::Node::namespaceURI">
+ <webidl> readonly attribute DOMString? namespaceURI;</webidl>
+ <Type type="DOMString" nullable="nullable"/>
+ </Attribute>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/nullableobjects.widlprocxml b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/nullableobjects.widlprocxml
new file mode 100644
index 00000000000..22d9fdd25d6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/nullableobjects.widlprocxml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface A {
+};
+interface B {
+};
+interface C {
+ void f(<ref>A</ref>? x);
+ void f(<ref>B</ref>? x);
+
+};</webidl>
+ <Interface name="A" id="::A">
+ <webidl>interface A {
+};</webidl>
+ </Interface>
+ <Interface name="B" id="::B">
+ <webidl>interface B {
+};</webidl>
+ </Interface>
+ <Interface name="C" id="::C">
+ <webidl>interface C {
+ void f(<ref>A</ref>? x);
+ void f(<ref>B</ref>? x);
+
+};</webidl>
+ <Operation name="f" id="::C::f">
+ <webidl> void f(<ref>A</ref>? x);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="x">
+ <Type name="A" nullable="nullable"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation name="f" id="::C::f">
+ <webidl> void f(<ref>B</ref>? x);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="x">
+ <Type name="B" nullable="nullable"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/operation-optional-arg.widlprocxml b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/operation-optional-arg.widlprocxml
new file mode 100644
index 00000000000..54aef1f87e3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/operation-optional-arg.widlprocxml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface ColorCreator {
+ object createColor(float v1, float v2, float v3, optional float alpha = 3.5);
+};</webidl>
+ <Interface name="ColorCreator" id="::ColorCreator">
+ <webidl>interface ColorCreator {
+ object createColor(float v1, float v2, float v3, optional float alpha = 3.5);
+};</webidl>
+ <Operation name="createColor" id="::ColorCreator::createColor">
+ <webidl> object createColor(float v1, float v2, float v3, optional float alpha = 3.5);</webidl>
+ <Type type="object"/>
+ <ArgumentList>
+ <Argument name="v1">
+ <Type type="float"/>
+ </Argument>
+ <Argument name="v2">
+ <Type type="float"/>
+ </Argument>
+ <Argument name="v3">
+ <Type type="float"/>
+ </Argument>
+ <Argument optional="optional" name="alpha" value="3.5">
+ <Type type="float"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/overloading.widlprocxml b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/overloading.widlprocxml
new file mode 100644
index 00000000000..db6da7a68c7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/overloading.widlprocxml
@@ -0,0 +1,113 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface A {
+};
+
+interface B {
+};
+
+interface C {
+ void f(<ref>A</ref> x);
+ void f(<ref>B</ref> x);
+};
+
+interface A {
+void f(DOMString a);
+void f([AllowAny] DOMString a, DOMString b, float... c);
+void f();
+void f(long a, DOMString b, optional DOMString c, float... d);
+};</webidl>
+ <Interface name="A" id="::A">
+ <webidl>interface A {
+};</webidl>
+ </Interface>
+ <Interface name="B" id="::B">
+ <webidl>interface B {
+};</webidl>
+ </Interface>
+ <Interface name="C" id="::C">
+ <webidl>interface C {
+ void f(<ref>A</ref> x);
+ void f(<ref>B</ref> x);
+};</webidl>
+ <Operation name="f" id="::C::f">
+ <webidl> void f(<ref>A</ref> x);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="x">
+ <Type name="A"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation name="f" id="::C::f">
+ <webidl> void f(<ref>B</ref> x);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="x">
+ <Type name="B"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+ <Interface name="A" id="::A">
+ <webidl>interface A {
+void f(DOMString a);
+void f([AllowAny] DOMString a, DOMString b, float... c);
+void f();
+void f(long a, DOMString b, optional DOMString c, float... d);
+};</webidl>
+ <Operation name="f" id="::A::f">
+ <webidl> void f(DOMString a);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="a">
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation name="f" id="::A::f">
+ <webidl> void f([AllowAny] DOMString a, DOMString b, float... c);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="a">
+ <ExtendedAttributeList>
+ <ExtendedAttribute name="AllowAny">
+ <webidl>AllowAny</webidl>
+ </ExtendedAttribute>
+ </ExtendedAttributeList>
+ <Type type="DOMString"/>
+ </Argument>
+ <Argument name="b">
+ <Type type="DOMString"/>
+ </Argument>
+ <Argument ellipsis="ellipsis" name="c">
+ <Type type="float"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation name="f" id="::A::f">
+ <webidl> void f();</webidl>
+ <Type type="void"/>
+ <ArgumentList/>
+ </Operation>
+ <Operation name="f" id="::A::f">
+ <webidl> void f(long a, DOMString b, optional DOMString c, float... d);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="a">
+ <Type type="long"/>
+ </Argument>
+ <Argument name="b">
+ <Type type="DOMString"/>
+ </Argument>
+ <Argument optional="optional" name="c">
+ <Type type="DOMString"/>
+ </Argument>
+ <Argument ellipsis="ellipsis" name="d">
+ <Type type="float"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/overridebuiltins.widlprocxml b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/overridebuiltins.widlprocxml
new file mode 100644
index 00000000000..56c92517beb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/overridebuiltins.widlprocxml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>[OverrideBuiltins]
+interface StringMap2 {
+ readonly attribute unsigned long length;
+ getter DOMString lookup(DOMString key);
+};</webidl>
+ <Interface name="StringMap2" id="::StringMap2">
+ <webidl>[OverrideBuiltins]
+interface StringMap2 {
+ readonly attribute unsigned long length;
+ getter DOMString lookup(DOMString key);
+};</webidl>
+ <ExtendedAttributeList>
+ <ExtendedAttribute name="OverrideBuiltins">
+ <webidl>OverrideBuiltins</webidl>
+ </ExtendedAttribute>
+ </ExtendedAttributeList>
+ <Attribute readonly="readonly" name="length" id="::StringMap2::length">
+ <webidl> readonly attribute unsigned long length;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Operation getter="getter" name="lookup" id="::StringMap2::lookup">
+ <webidl> getter DOMString lookup(DOMString key);</webidl>
+ <Type type="DOMString"/>
+ <ArgumentList>
+ <Argument name="key">
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/partial-interface.widlprocxml b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/partial-interface.widlprocxml
new file mode 100644
index 00000000000..8d7dcb4e4f7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/partial-interface.widlprocxml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Foo {
+ attribute DOMString bar;
+};
+
+partial interface Foo {
+ attribute DOMString quux;
+};</webidl>
+ <Interface name="Foo" id="::Foo">
+ <webidl>interface Foo {
+ attribute DOMString bar;
+};</webidl>
+ <Attribute name="bar" id="::Foo::bar">
+ <webidl> attribute DOMString bar;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ </Interface>
+ <Interface name="Foo" partial="partial" id="::Foo">
+ <webidl>partial interface Foo {
+ attribute DOMString quux;
+};</webidl>
+ <Attribute name="quux" id="::Foo::quux">
+ <webidl> attribute DOMString quux;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/primitives.widlprocxml b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/primitives.widlprocxml
new file mode 100644
index 00000000000..46977a2d74e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/primitives.widlprocxml
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Primitives {
+ attribute boolean truth;
+ attribute byte character;
+ attribute octet value;
+ attribute short number;
+ attribute unsigned short positive;
+ attribute long big;
+ attribute unsigned long bigpositive;
+ attribute long long bigbig;
+ attribute unsigned long long bigbigpositive;
+ attribute float real;
+ attribute double bigreal;
+ attribute unrestricted float realwithinfinity;
+ attribute unrestricted double bigrealwithinfinity;
+ attribute DOMString string;
+ attribute ByteString bytes;
+ attribute Date date;
+ attribute RegExp regexp;
+};</webidl>
+ <Interface name="Primitives" id="::Primitives">
+ <webidl>interface Primitives {
+ attribute boolean truth;
+ attribute byte character;
+ attribute octet value;
+ attribute short number;
+ attribute unsigned short positive;
+ attribute long big;
+ attribute unsigned long bigpositive;
+ attribute long long bigbig;
+ attribute unsigned long long bigbigpositive;
+ attribute float real;
+ attribute double bigreal;
+ attribute unrestricted float realwithinfinity;
+ attribute unrestricted double bigrealwithinfinity;
+ attribute DOMString string;
+ attribute ByteString bytes;
+ attribute Date date;
+ attribute RegExp regexp;
+};</webidl>
+ <Attribute name="truth" id="::Primitives::truth">
+ <webidl> attribute boolean truth;</webidl>
+ <Type type="boolean"/>
+ </Attribute>
+ <Attribute name="character" id="::Primitives::character">
+ <webidl> attribute byte character;</webidl>
+ <Type type="byte"/>
+ </Attribute>
+ <Attribute name="value" id="::Primitives::value">
+ <webidl> attribute octet value;</webidl>
+ <Type type="octet"/>
+ </Attribute>
+ <Attribute name="number" id="::Primitives::number">
+ <webidl> attribute short number;</webidl>
+ <Type type="short"/>
+ </Attribute>
+ <Attribute name="positive" id="::Primitives::positive">
+ <webidl> attribute unsigned short positive;</webidl>
+ <Type type="unsigned short"/>
+ </Attribute>
+ <Attribute name="big" id="::Primitives::big">
+ <webidl> attribute long big;</webidl>
+ <Type type="long"/>
+ </Attribute>
+ <Attribute name="bigpositive" id="::Primitives::bigpositive">
+ <webidl> attribute unsigned long bigpositive;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Attribute name="bigbig" id="::Primitives::bigbig">
+ <webidl> attribute long long bigbig;</webidl>
+ <Type type="long long"/>
+ </Attribute>
+ <Attribute name="bigbigpositive" id="::Primitives::bigbigpositive">
+ <webidl> attribute unsigned long long bigbigpositive;</webidl>
+ <Type type="unsigned long long"/>
+ </Attribute>
+ <Attribute name="real" id="::Primitives::real">
+ <webidl> attribute float real;</webidl>
+ <Type type="float"/>
+ </Attribute>
+ <Attribute name="bigreal" id="::Primitives::bigreal">
+ <webidl> attribute double bigreal;</webidl>
+ <Type type="double"/>
+ </Attribute>
+ <Attribute name="realwithinfinity" id="::Primitives::realwithinfinity">
+ <webidl> attribute unrestricted float realwithinfinity;</webidl>
+ <Type type="unrestricted float"/>
+ </Attribute>
+ <Attribute name="bigrealwithinfinity" id="::Primitives::bigrealwithinfinity">
+ <webidl> attribute unrestricted double bigrealwithinfinity;</webidl>
+ <Type type="unrestricted double"/>
+ </Attribute>
+ <Attribute name="string" id="::Primitives::string">
+ <webidl> attribute DOMString string;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ <Attribute name="bytes" id="::Primitives::bytes">
+ <webidl> attribute ByteString bytes;</webidl>
+ <Type type="ByteString"/>
+ </Attribute>
+ <Attribute name="date" id="::Primitives::date">
+ <webidl> attribute Date date;</webidl>
+ <Type type="Date"/>
+ </Attribute>
+ <Attribute name="regexp" id="::Primitives::regexp">
+ <webidl> attribute RegExp regexp;</webidl>
+ <Type type="RegExp"/>
+ </Attribute>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/prototyperoot.widlprocxml b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/prototyperoot.widlprocxml
new file mode 100644
index 00000000000..2e56cd75ec3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/prototyperoot.widlprocxml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>[PrototypeRoot]
+interface Node {
+ readonly attribute unsigned short nodeType;
+};</webidl>
+ <Interface name="Node" id="::Node">
+ <webidl>[PrototypeRoot]
+interface Node {
+ readonly attribute unsigned short nodeType;
+};</webidl>
+ <ExtendedAttributeList>
+ <ExtendedAttribute name="PrototypeRoot">
+ <webidl>PrototypeRoot</webidl>
+ </ExtendedAttribute>
+ </ExtendedAttributeList>
+ <Attribute readonly="readonly" name="nodeType" id="::Node::nodeType">
+ <webidl> readonly attribute unsigned short nodeType;</webidl>
+ <Type type="unsigned short"/>
+ </Attribute>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/putforwards.widlprocxml b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/putforwards.widlprocxml
new file mode 100644
index 00000000000..634fad55a56
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/putforwards.widlprocxml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Person {
+ [PutForwards=full] readonly attribute <ref>Name</ref> name;
+ attribute unsigned short age;
+};</webidl>
+ <Interface name="Person" id="::Person">
+ <webidl>interface Person {
+ [PutForwards=full] readonly attribute <ref>Name</ref> name;
+ attribute unsigned short age;
+};</webidl>
+ <Attribute readonly="readonly" name="name" id="::Person::name">
+ <webidl> [PutForwards=full] readonly attribute <ref>Name</ref> name;</webidl>
+ <ExtendedAttributeList>
+ <ExtendedAttribute name="PutForwards" value="full">
+ <webidl>PutForwards</webidl>
+ </ExtendedAttribute>
+ </ExtendedAttributeList>
+ <Type name="Name"/>
+ </Attribute>
+ <Attribute name="age" id="::Person::age">
+ <webidl> attribute unsigned short age;</webidl>
+ <Type type="unsigned short"/>
+ </Attribute>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/reg-operations.widlprocxml b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/reg-operations.widlprocxml
new file mode 100644
index 00000000000..3b756ed68d8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/reg-operations.widlprocxml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Dimensions {
+ attribute unsigned long width;
+ attribute unsigned long height;
+};
+
+exception NoPointerDevice { };
+
+interface Button {
+
+ boolean isMouseOver();
+
+ void setDimensions(<ref>Dimensions</ref> size);
+ void setDimensions(unsigned long width, unsigned long height);
+};</webidl>
+ <Interface name="Dimensions" id="::Dimensions">
+ <webidl>interface Dimensions {
+ attribute unsigned long width;
+ attribute unsigned long height;
+};</webidl>
+ <Attribute name="width" id="::Dimensions::width">
+ <webidl> attribute unsigned long width;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Attribute name="height" id="::Dimensions::height">
+ <webidl> attribute unsigned long height;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ </Interface>
+ <Exception name="NoPointerDevice" id="::NoPointerDevice">
+ <webidl>exception NoPointerDevice { };</webidl>
+ </Exception>
+ <Interface name="Button" id="::Button">
+ <webidl>interface Button {
+
+ boolean isMouseOver();
+
+ void setDimensions(<ref>Dimensions</ref> size);
+ void setDimensions(unsigned long width, unsigned long height);
+};</webidl>
+ <Operation name="isMouseOver" id="::Button::isMouseOver">
+ <webidl> boolean isMouseOver();</webidl>
+ <Type type="boolean"/>
+ <ArgumentList/>
+ </Operation>
+ <Operation name="setDimensions" id="::Button::setDimensions">
+ <webidl> void setDimensions(<ref>Dimensions</ref> size);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="size">
+ <Type name="Dimensions"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation name="setDimensions" id="::Button::setDimensions">
+ <webidl> void setDimensions(unsigned long width, unsigned long height);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="width">
+ <Type type="unsigned long"/>
+ </Argument>
+ <Argument name="height">
+ <Type type="unsigned long"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/replaceable.widlprocxml b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/replaceable.widlprocxml
new file mode 100644
index 00000000000..f9762166825
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/replaceable.widlprocxml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Counter {
+ [Replaceable] readonly attribute unsigned long value;
+ void increment();
+};</webidl>
+ <Interface name="Counter" id="::Counter">
+ <webidl>interface Counter {
+ [Replaceable] readonly attribute unsigned long value;
+ void increment();
+};</webidl>
+ <Attribute readonly="readonly" name="value" id="::Counter::value">
+ <webidl> [Replaceable] readonly attribute unsigned long value;</webidl>
+ <ExtendedAttributeList>
+ <ExtendedAttribute name="Replaceable">
+ <webidl>Replaceable</webidl>
+ </ExtendedAttribute>
+ </ExtendedAttributeList>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Operation name="increment" id="::Counter::increment">
+ <webidl> void increment();</webidl>
+ <Type type="void"/>
+ <ArgumentList/>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/sequence.widlprocxml b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/sequence.widlprocxml
new file mode 100644
index 00000000000..d5f4564175b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/sequence.widlprocxml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Canvas {
+ void drawPolygon(sequence&lt;float> coordinates);
+ sequence&lt;float> getInflectionPoints();
+};</webidl>
+ <Interface name="Canvas" id="::Canvas">
+ <webidl>interface Canvas {
+ void drawPolygon(sequence&lt;float> coordinates);
+ sequence&lt;float> getInflectionPoints();
+};</webidl>
+ <Operation name="drawPolygon" id="::Canvas::drawPolygon">
+ <webidl> void drawPolygon(sequence&lt;float> coordinates);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="coordinates">
+ <Type type="sequence">
+ <Type type="float"/>
+ </Type>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation name="getInflectionPoints" id="::Canvas::getInflectionPoints">
+ <webidl> sequence&lt;float> getInflectionPoints();</webidl>
+ <Type type="sequence">
+ <Type type="float"/>
+ </Type>
+ <ArgumentList/>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/serializer.widlprocxml b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/serializer.widlprocxml
new file mode 100644
index 00000000000..eb4219f8a5e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/serializer.widlprocxml
@@ -0,0 +1,296 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Transaction {
+ readonly attribute <ref>Account</ref> from;
+ readonly attribute <ref>Account</ref> to;
+ readonly attribute float amount;
+ readonly attribute DOMString description;
+ readonly attribute unsigned long number;
+
+ serializer;
+};
+
+interface Account {
+ attribute DOMString name;
+ attribute unsigned long number;
+ serializer DOMString serialize();
+};
+
+interface Transaction2 {
+ readonly attribute <ref>Account2</ref> from;
+ readonly attribute <ref>Account2</ref> to;
+ readonly attribute float amount;
+ readonly attribute DOMString description;
+ readonly attribute unsigned long number;
+
+ serializer = { from, to, amount, description };
+};
+
+interface Account2 {
+ attribute DOMString name;
+ attribute unsigned long number;
+ serializer = number;
+};
+
+interface Account3 {
+ attribute DOMString name;
+ attribute unsigned long number;
+
+ serializer = { attribute };
+};
+
+interface Account4 {
+ getter object getItem(unsigned long index);
+ serializer = { getter };
+};
+
+interface Account5 : <ref>Account</ref> {
+ attribute DOMString secondname;
+ serializer = { inherit, secondname };
+};
+
+interface Account6 : <ref>Account</ref> {
+ attribute DOMString secondname;
+ serializer = { inherit, attribute };
+};
+
+interface Account7 {
+ attribute DOMString name;
+ attribute unsigned long number;
+ serializer = [ name, number ];
+};
+
+interface Account8 {
+ getter object getItem(unsigned long index);
+ serializer = [ getter ];
+};</webidl>
+ <Interface name="Transaction" id="::Transaction">
+ <webidl>interface Transaction {
+ readonly attribute <ref>Account</ref> from;
+ readonly attribute <ref>Account</ref> to;
+ readonly attribute float amount;
+ readonly attribute DOMString description;
+ readonly attribute unsigned long number;
+
+ serializer;
+};</webidl>
+ <Attribute readonly="readonly" name="from" id="::Transaction::from">
+ <webidl> readonly attribute <ref>Account</ref> from;</webidl>
+ <Type name="Account"/>
+ </Attribute>
+ <Attribute readonly="readonly" name="to" id="::Transaction::to">
+ <webidl> readonly attribute <ref>Account</ref> to;</webidl>
+ <Type name="Account"/>
+ </Attribute>
+ <Attribute readonly="readonly" name="amount" id="::Transaction::amount">
+ <webidl> readonly attribute float amount;</webidl>
+ <Type type="float"/>
+ </Attribute>
+ <Attribute readonly="readonly" name="description" id="::Transaction::description">
+ <webidl> readonly attribute DOMString description;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ <Attribute readonly="readonly" name="number" id="::Transaction::number">
+ <webidl> readonly attribute unsigned long number;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Serializer>
+ <webidl> serializer;</webidl>
+ </Serializer>
+ </Interface>
+ <Interface name="Account" id="::Account">
+ <webidl>interface Account {
+ attribute DOMString name;
+ attribute unsigned long number;
+ serializer DOMString serialize();
+};</webidl>
+ <Attribute name="name" id="::Account::name">
+ <webidl> attribute DOMString name;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ <Attribute name="number" id="::Account::number">
+ <webidl> attribute unsigned long number;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Operation serializer="serializer" name="serialize" id="::Account::serialize">
+ <webidl> serializer DOMString serialize();</webidl>
+ <Type type="DOMString"/>
+ <ArgumentList/>
+ </Operation>
+ </Interface>
+ <Interface name="Transaction2" id="::Transaction2">
+ <webidl>interface Transaction2 {
+ readonly attribute <ref>Account2</ref> from;
+ readonly attribute <ref>Account2</ref> to;
+ readonly attribute float amount;
+ readonly attribute DOMString description;
+ readonly attribute unsigned long number;
+
+ serializer = { from, to, amount, description };
+};</webidl>
+ <Attribute readonly="readonly" name="from" id="::Transaction2::from">
+ <webidl> readonly attribute <ref>Account2</ref> from;</webidl>
+ <Type name="Account2"/>
+ </Attribute>
+ <Attribute readonly="readonly" name="to" id="::Transaction2::to">
+ <webidl> readonly attribute <ref>Account2</ref> to;</webidl>
+ <Type name="Account2"/>
+ </Attribute>
+ <Attribute readonly="readonly" name="amount" id="::Transaction2::amount">
+ <webidl> readonly attribute float amount;</webidl>
+ <Type type="float"/>
+ </Attribute>
+ <Attribute readonly="readonly" name="description" id="::Transaction2::description">
+ <webidl> readonly attribute DOMString description;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ <Attribute readonly="readonly" name="number" id="::Transaction2::number">
+ <webidl> readonly attribute unsigned long number;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Serializer>
+ <webidl> serializer = { from, to, amount, description };</webidl>
+ <Map pattern="selection">
+ <PatternAttribute name="from"/>
+ <PatternAttribute name="to"/>
+ <PatternAttribute name="amount"/>
+ <PatternAttribute name="description"/>
+ </Map>
+ </Serializer>
+ </Interface>
+ <Interface name="Account2" id="::Account2">
+ <webidl>interface Account2 {
+ attribute DOMString name;
+ attribute unsigned long number;
+ serializer = number;
+};</webidl>
+ <Attribute name="name" id="::Account2::name">
+ <webidl> attribute DOMString name;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ <Attribute name="number" id="::Account2::number">
+ <webidl> attribute unsigned long number;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Serializer attribute="number">
+ <webidl> serializer = number;</webidl>
+ </Serializer>
+ </Interface>
+ <Interface name="Account3" id="::Account3">
+ <webidl>interface Account3 {
+ attribute DOMString name;
+ attribute unsigned long number;
+
+ serializer = { attribute };
+};</webidl>
+ <Attribute name="name" id="::Account3::name">
+ <webidl> attribute DOMString name;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ <Attribute name="number" id="::Account3::number">
+ <webidl> attribute unsigned long number;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Serializer>
+ <webidl> serializer = { attribute };</webidl>
+ <Map pattern="all"/>
+ </Serializer>
+ </Interface>
+ <Interface name="Account4" id="::Account4">
+ <webidl>interface Account4 {
+ getter object getItem(unsigned long index);
+ serializer = { getter };
+};</webidl>
+ <Operation getter="getter" name="getItem" id="::Account4::getItem">
+ <webidl> getter object getItem(unsigned long index);</webidl>
+ <Type type="object"/>
+ <ArgumentList>
+ <Argument name="index">
+ <Type type="unsigned long"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Serializer>
+ <webidl> serializer = { getter };</webidl>
+ <Map pattern="getter"/>
+ </Serializer>
+ </Interface>
+ <Interface name="Account5" id="::Account5">
+ <webidl>interface Account5 : <ref>Account</ref> {
+ attribute DOMString secondname;
+ serializer = { inherit, secondname };
+};</webidl>
+ <InterfaceInheritance>
+ <Name name="Account"/>
+ </InterfaceInheritance>
+ <Attribute name="secondname" id="::Account5::secondname">
+ <webidl> attribute DOMString secondname;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ <Serializer>
+ <webidl> serializer = { inherit, secondname };</webidl>
+ <Map inherit="inherit" pattern="selection">
+ <PatternAttribute name="secondname"/>
+ </Map>
+ </Serializer>
+ </Interface>
+ <Interface name="Account6" id="::Account6">
+ <webidl>interface Account6 : <ref>Account</ref> {
+ attribute DOMString secondname;
+ serializer = { inherit, attribute };
+};</webidl>
+ <InterfaceInheritance>
+ <Name name="Account"/>
+ </InterfaceInheritance>
+ <Attribute name="secondname" id="::Account6::secondname">
+ <webidl> attribute DOMString secondname;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ <Serializer>
+ <webidl> serializer = { inherit, attribute };</webidl>
+ <Map inherit="inherit" pattern="all"/>
+ </Serializer>
+ </Interface>
+ <Interface name="Account7" id="::Account7">
+ <webidl>interface Account7 {
+ attribute DOMString name;
+ attribute unsigned long number;
+ serializer = [ name, number ];
+};</webidl>
+ <Attribute name="name" id="::Account7::name">
+ <webidl> attribute DOMString name;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ <Attribute name="number" id="::Account7::number">
+ <webidl> attribute unsigned long number;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Serializer>
+ <webidl> serializer = [ name, number ];</webidl>
+ <List pattern="selection">
+ <PatternAttribute name="name"/>
+ <PatternAttribute name="number"/>
+ </List>
+ </Serializer>
+ </Interface>
+ <Interface name="Account8" id="::Account8">
+ <webidl>interface Account8 {
+ getter object getItem(unsigned long index);
+ serializer = [ getter ];
+};</webidl>
+ <Operation getter="getter" name="getItem" id="::Account8::getItem">
+ <webidl> getter object getItem(unsigned long index);</webidl>
+ <Type type="object"/>
+ <ArgumentList>
+ <Argument name="index">
+ <Type type="unsigned long"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Serializer>
+ <webidl> serializer = [ getter ];</webidl>
+ <List pattern="getter"/>
+ </Serializer>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/special-omittable.widlprocxml b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/special-omittable.widlprocxml
new file mode 100644
index 00000000000..1986d190a80
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/special-omittable.widlprocxml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <Interface name="Dictionary" id="::Dictionary">
+ <webidl>interface Dictionary {
+ readonly attribute unsigned long propertyCount;
+
+ omittable getter float getProperty(DOMString propertyName);
+ omittable setter void setProperty(DOMString propertyName, float propertyValue);
+};</webidl>
+ <Attribute readonly="readonly" name="propertyCount" id="::Dictionary::propertyCount">
+ <webidl> readonly attribute unsigned long propertyCount;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Operation omittable="omittable" getter="getter" name="getProperty" id="::Dictionary::getProperty">
+ <webidl> omittable getter float getProperty(DOMString propertyName);</webidl>
+ <Type type="float"/>
+ <ArgumentList>
+ <Argument name="propertyName">
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation omittable="omittable" setter="setter" name="setProperty" id="::Dictionary::setProperty">
+ <webidl> omittable setter void setProperty(DOMString propertyName, float propertyValue);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="propertyName">
+ <Type type="DOMString"/>
+ </Argument>
+ <Argument name="propertyValue">
+ <Type type="float"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/static.widlprocxml b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/static.widlprocxml
new file mode 100644
index 00000000000..03c14e16eba
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/static.widlprocxml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Point { };
+
+interface Circle {
+ attribute float cx;
+ attribute float cy;
+ attribute float radius;
+
+ static readonly attribute long triangulationCount;
+ static <ref>Point</ref> triangulate(<ref>Circle</ref> c1, <ref>Circle</ref> c2, <ref>Circle</ref> c3);
+};</webidl>
+ <Interface name="Point" id="::Point">
+ <webidl>interface Point { };</webidl>
+ </Interface>
+ <Interface name="Circle" id="::Circle">
+ <webidl>interface Circle {
+ attribute float cx;
+ attribute float cy;
+ attribute float radius;
+
+ static readonly attribute long triangulationCount;
+ static <ref>Point</ref> triangulate(<ref>Circle</ref> c1, <ref>Circle</ref> c2, <ref>Circle</ref> c3);
+};</webidl>
+ <Attribute name="cx" id="::Circle::cx">
+ <webidl> attribute float cx;</webidl>
+ <Type type="float"/>
+ </Attribute>
+ <Attribute name="cy" id="::Circle::cy">
+ <webidl> attribute float cy;</webidl>
+ <Type type="float"/>
+ </Attribute>
+ <Attribute name="radius" id="::Circle::radius">
+ <webidl> attribute float radius;</webidl>
+ <Type type="float"/>
+ </Attribute>
+ <Attribute static="static" readonly="readonly" name="triangulationCount" id="::Circle::triangulationCount">
+ <webidl> static readonly attribute long triangulationCount;</webidl>
+ <Type type="long"/>
+ </Attribute>
+ <Operation static="static" name="triangulate" id="::Circle::triangulate">
+ <webidl> static <ref>Point</ref> triangulate(<ref>Circle</ref> c1, <ref>Circle</ref> c2, <ref>Circle</ref> c3);</webidl>
+ <Type name="Point"/>
+ <ArgumentList>
+ <Argument name="c1">
+ <Type name="Circle"/>
+ </Argument>
+ <Argument name="c2">
+ <Type name="Circle"/>
+ </Argument>
+ <Argument name="c3">
+ <Type name="Circle"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/stringifier-attribute.widlprocxml b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/stringifier-attribute.widlprocxml
new file mode 100644
index 00000000000..082ce4d341b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/stringifier-attribute.widlprocxml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>[Constructor]
+interface Student {
+ attribute unsigned long id;
+ stringifier attribute DOMString name;
+};</webidl>
+ <Interface name="Student" id="::Student">
+ <webidl>[Constructor]
+interface Student {
+ attribute unsigned long id;
+ stringifier attribute DOMString name;
+};</webidl>
+ <ExtendedAttributeList>
+ <ExtendedAttribute name="Constructor">
+ <webidl>Constructor</webidl>
+ </ExtendedAttribute>
+ </ExtendedAttributeList>
+ <Attribute name="id" id="::Student::id">
+ <webidl> attribute unsigned long id;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Attribute stringifier="stringifier" name="name" id="::Student::name">
+ <webidl> stringifier attribute DOMString name;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/stringifier-custom.widlprocxml b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/stringifier-custom.widlprocxml
new file mode 100644
index 00000000000..cdab1ccfc37
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/stringifier-custom.widlprocxml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>[Constructor]
+interface Student {
+ attribute unsigned long id;
+ attribute DOMString? familyName;
+ attribute DOMString givenName;
+
+ stringifier DOMString ();
+};</webidl>
+ <Interface name="Student" id="::Student">
+ <webidl>[Constructor]
+interface Student {
+ attribute unsigned long id;
+ attribute DOMString? familyName;
+ attribute DOMString givenName;
+
+ stringifier DOMString ();
+};</webidl>
+ <ExtendedAttributeList>
+ <ExtendedAttribute name="Constructor">
+ <webidl>Constructor</webidl>
+ </ExtendedAttribute>
+ </ExtendedAttributeList>
+ <Attribute name="id" id="::Student::id">
+ <webidl> attribute unsigned long id;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Attribute name="familyName" id="::Student::familyName">
+ <webidl> attribute DOMString? familyName;</webidl>
+ <Type type="DOMString" nullable="nullable"/>
+ </Attribute>
+ <Attribute name="givenName" id="::Student::givenName">
+ <webidl> attribute DOMString givenName;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ <Operation stringifier="stringifier">
+ <webidl> stringifier DOMString ();</webidl>
+ <Type type="DOMString"/>
+ <ArgumentList/>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/stringifier.widlprocxml b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/stringifier.widlprocxml
new file mode 100644
index 00000000000..4a18b80b704
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/stringifier.widlprocxml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface A {
+ stringifier DOMString ();
+};
+
+interface A {
+ stringifier;
+};</webidl>
+ <Interface name="A" id="::A">
+ <webidl>interface A {
+ stringifier DOMString ();
+};</webidl>
+ <Operation stringifier="stringifier">
+ <webidl> stringifier DOMString ();</webidl>
+ <Type type="DOMString"/>
+ <ArgumentList/>
+ </Operation>
+ </Interface>
+ <Interface name="A" id="::A">
+ <webidl>interface A {
+ stringifier;
+};</webidl>
+ <Stringifier>
+ <webidl> stringifier;</webidl>
+ </Stringifier>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/treatasnull.widlprocxml b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/treatasnull.widlprocxml
new file mode 100644
index 00000000000..a57ae163f0b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/treatasnull.widlprocxml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Dog {
+ attribute DOMString name;
+ attribute DOMString owner;
+
+ boolean isMemberOfBreed([TreatNullAs=EmptyString] DOMString breedName);
+};</webidl>
+ <Interface name="Dog" id="::Dog">
+ <webidl>interface Dog {
+ attribute DOMString name;
+ attribute DOMString owner;
+
+ boolean isMemberOfBreed([TreatNullAs=EmptyString] DOMString breedName);
+};</webidl>
+ <Attribute name="name" id="::Dog::name">
+ <webidl> attribute DOMString name;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ <Attribute name="owner" id="::Dog::owner">
+ <webidl> attribute DOMString owner;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ <Operation name="isMemberOfBreed" id="::Dog::isMemberOfBreed">
+ <webidl> boolean isMemberOfBreed([TreatNullAs=EmptyString] DOMString breedName);</webidl>
+ <Type type="boolean"/>
+ <ArgumentList>
+ <Argument name="breedName">
+ <ExtendedAttributeList>
+ <ExtendedAttribute name="TreatNullAs" value="EmptyString">
+ <webidl>TreatNullAs</webidl>
+ </ExtendedAttribute>
+ </ExtendedAttributeList>
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/treatasundefined.widlprocxml b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/treatasundefined.widlprocxml
new file mode 100644
index 00000000000..17e71081da0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/treatasundefined.widlprocxml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Cat {
+ attribute DOMString name;
+ attribute DOMString owner;
+
+ boolean isMemberOfBreed([TreatUndefinedAs=EmptyString] DOMString breedName);
+};</webidl>
+ <Interface name="Cat" id="::Cat">
+ <webidl>interface Cat {
+ attribute DOMString name;
+ attribute DOMString owner;
+
+ boolean isMemberOfBreed([TreatUndefinedAs=EmptyString] DOMString breedName);
+};</webidl>
+ <Attribute name="name" id="::Cat::name">
+ <webidl> attribute DOMString name;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ <Attribute name="owner" id="::Cat::owner">
+ <webidl> attribute DOMString owner;</webidl>
+ <Type type="DOMString"/>
+ </Attribute>
+ <Operation name="isMemberOfBreed" id="::Cat::isMemberOfBreed">
+ <webidl> boolean isMemberOfBreed([TreatUndefinedAs=EmptyString] DOMString breedName);</webidl>
+ <Type type="boolean"/>
+ <ArgumentList>
+ <Argument name="breedName">
+ <ExtendedAttributeList>
+ <ExtendedAttribute name="TreatUndefinedAs" value="EmptyString">
+ <webidl>TreatUndefinedAs</webidl>
+ </ExtendedAttribute>
+ </ExtendedAttributeList>
+ <Type type="DOMString"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/typedef.widlprocxml b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/typedef.widlprocxml
new file mode 100644
index 00000000000..785f6706e6d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/typedef.widlprocxml
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl> interface Point {
+ attribute float x;
+ attribute float y;
+ };
+
+ typedef sequence&lt;<ref>Point</ref>> PointSequence;
+
+ interface Rect {
+ attribute <ref>Point</ref> topleft;
+ attribute <ref>Point</ref> bottomright;
+ };
+
+ interface Widget {
+
+ readonly attribute <ref>Rect</ref> bounds;
+
+ boolean pointWithinBounds(<ref>Point</ref> p);
+ boolean allPointsWithinBounds(<ref>PointSequence</ref> ps);
+ };
+
+ typedef [Clamp] octet value;</webidl>
+ <Interface name="Point" id="::Point">
+ <webidl> interface Point {
+ attribute float x;
+ attribute float y;
+ };</webidl>
+ <Attribute name="x" id="::Point::x">
+ <webidl> attribute float x;</webidl>
+ <Type type="float"/>
+ </Attribute>
+ <Attribute name="y" id="::Point::y">
+ <webidl> attribute float y;</webidl>
+ <Type type="float"/>
+ </Attribute>
+ </Interface>
+ <Typedef name="PointSequence" id="::PointSequence">
+ <webidl> typedef sequence&lt;<ref>Point</ref>> PointSequence;</webidl>
+ <Type type="sequence">
+ <Type name="Point"/>
+ </Type>
+ </Typedef>
+ <Interface name="Rect" id="::Rect">
+ <webidl> interface Rect {
+ attribute <ref>Point</ref> topleft;
+ attribute <ref>Point</ref> bottomright;
+ };</webidl>
+ <Attribute name="topleft" id="::Rect::topleft">
+ <webidl> attribute <ref>Point</ref> topleft;</webidl>
+ <Type name="Point"/>
+ </Attribute>
+ <Attribute name="bottomright" id="::Rect::bottomright">
+ <webidl> attribute <ref>Point</ref> bottomright;</webidl>
+ <Type name="Point"/>
+ </Attribute>
+ </Interface>
+ <Interface name="Widget" id="::Widget">
+ <webidl> interface Widget {
+
+ readonly attribute <ref>Rect</ref> bounds;
+
+ boolean pointWithinBounds(<ref>Point</ref> p);
+ boolean allPointsWithinBounds(<ref>PointSequence</ref> ps);
+ };</webidl>
+ <Attribute readonly="readonly" name="bounds" id="::Widget::bounds">
+ <webidl> readonly attribute <ref>Rect</ref> bounds;</webidl>
+ <Type name="Rect"/>
+ </Attribute>
+ <Operation name="pointWithinBounds" id="::Widget::pointWithinBounds">
+ <webidl> boolean pointWithinBounds(<ref>Point</ref> p);</webidl>
+ <Type type="boolean"/>
+ <ArgumentList>
+ <Argument name="p">
+ <Type name="Point"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation name="allPointsWithinBounds" id="::Widget::allPointsWithinBounds">
+ <webidl> boolean allPointsWithinBounds(<ref>PointSequence</ref> ps);</webidl>
+ <Type type="boolean"/>
+ <ArgumentList>
+ <Argument name="ps">
+ <Type name="PointSequence"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+ <Typedef name="value" id="::value">
+ <webidl> typedef [Clamp] octet value;</webidl>
+ <Type type="octet">
+ <ExtendedAttributeList>
+ <ExtendedAttribute name="Clamp">
+ <webidl>Clamp</webidl>
+ </ExtendedAttribute>
+ </ExtendedAttributeList>
+ </Type>
+ </Typedef>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/typesuffixes.widlprocxml b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/typesuffixes.widlprocxml
new file mode 100644
index 00000000000..830fe62bc0d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/typesuffixes.widlprocxml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Suffixes {
+ void test(sequence&lt;DOMString[]?>? foo);
+};</webidl>
+ <Interface name="Suffixes" id="::Suffixes">
+ <webidl>interface Suffixes {
+ void test(sequence&lt;DOMString[]?>? foo);
+};</webidl>
+ <Operation name="test" id="::Suffixes::test">
+ <webidl> void test(sequence&lt;DOMString[]?>? foo);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument name="foo">
+ <Type type="sequence" nullable="nullable">
+ <Type type="array" nullable="nullable">
+ <Type type="DOMString"/>
+ </Type>
+ </Type>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/uniontype.widlprocxml b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/uniontype.widlprocxml
new file mode 100644
index 00000000000..7d088079956
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/uniontype.widlprocxml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface Union {
+ attribute (float or (Date or <ref>Event</ref>) or (<ref>Node</ref> or DOMString)?) test;
+};</webidl>
+ <Interface name="Union" id="::Union">
+ <webidl>interface Union {
+ attribute (float or (Date or <ref>Event</ref>) or (<ref>Node</ref> or DOMString)?) test;
+};</webidl>
+ <Attribute name="test" id="::Union::test">
+ <webidl> attribute (float or (Date or <ref>Event</ref>) or (<ref>Node</ref> or DOMString)?) test;</webidl>
+ <Type type="union">
+ <Type type="float"/>
+ <Type type="union">
+ <Type type="Date"/>
+ <Type name="Event"/>
+ </Type>
+ <Type type="union" nullable="nullable">
+ <Type name="Node"/>
+ <Type type="DOMString"/>
+ </Type>
+ </Type>
+ </Attribute>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/variadic-operations.widlprocxml b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/variadic-operations.widlprocxml
new file mode 100644
index 00000000000..0bc9f784413
--- /dev/null
+++ b/tests/wpt/web-platform-tests/resources/webidl2/test/widlproc/test/valid/xml/variadic-operations.widlprocxml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Definitions SYSTEM "widlprocxml.dtd">
+<Definitions>
+ <webidl>interface IntegerSet {
+ readonly attribute unsigned long cardinality;
+
+ void union(long... ints);
+ void intersection(long... ints);
+};</webidl>
+ <Interface name="IntegerSet" id="::IntegerSet">
+ <webidl>interface IntegerSet {
+ readonly attribute unsigned long cardinality;
+
+ void union(long... ints);
+ void intersection(long... ints);
+};</webidl>
+ <Attribute readonly="readonly" name="cardinality" id="::IntegerSet::cardinality">
+ <webidl> readonly attribute unsigned long cardinality;</webidl>
+ <Type type="unsigned long"/>
+ </Attribute>
+ <Operation name="union" id="::IntegerSet::union">
+ <webidl> void union(long... ints);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument ellipsis="ellipsis" name="ints">
+ <Type type="long"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ <Operation name="intersection" id="::IntegerSet::intersection">
+ <webidl> void intersection(long... ints);</webidl>
+ <Type type="void"/>
+ <ArgumentList>
+ <Argument ellipsis="ellipsis" name="ints">
+ <Type type="long"/>
+ </Argument>
+ </ArgumentList>
+ </Operation>
+ </Interface>
+</Definitions>
diff --git a/tests/wpt/web-platform-tests/selectors-api/tests/submissions/Opera/ParentNode-query-queryAll.html b/tests/wpt/web-platform-tests/selectors-api/tests/submissions/Opera/ParentNode-query-queryAll.html
new file mode 100644
index 00000000000..f27e4e66f0c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/selectors-api/tests/submissions/Opera/ParentNode-query-queryAll.html
@@ -0,0 +1,89 @@
+<!DOCTYPE html>
+<meta charset="UTF-8">
+<title>Selectors-API Level 2 Test Suite: HTML with Selectors Level 3</title>
+<!-- Selectors API Test Suite Version 3 -->
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/dom/nodes/selectors.js"></script>
+<script src="/dom/nodes/ParentNode-querySelector-All.js"></script>
+<script src="ParentNode-query-queryAll.js"></script>
+<style>iframe { visibility: hidden; position: absolute; }</style>
+
+<div id="log">This test requires JavaScript.</div>
+
+<script>
+var docType = "html"; // Only run tests suitable for HTML
+
+var frame = document.createElement("iframe"),
+ doc;
+
+frame.onload = init;
+frame.src = "/dom/nodes/ParentNode-querySelector-All-content.html#target";
+document.body.appendChild(frame);
+
+function init() {
+ /*
+ * This test suite tests Selectors API methods in 4 different contexts:
+ * 1. Document node
+ * 2. In-document Element node
+ * 3. Detached Element node (an element with no parent, not in the document)
+ * 4. Document Fragment node
+ *
+ * For each context, the following tests are run:
+ *
+ * The interface check tests ensure that each type of node exposes the Selectors API methods.
+ *
+ * The matches() tests are run
+ * All the selectors tested for both the valid and invalid selector tests are found in selectors.js.
+ * See comments in that file for documentation of the format used.
+ *
+ * The level2-lib.js file contains all the common test functions for running each of the aforementioned tests
+ */
+
+ // Prepare the nodes for testing
+ doc = frame.contentDocument; // Document Node tests
+
+ var element = doc.getElementById("root"); // In-document Element Node tests
+
+ //Setup the namespace tests
+ setupSpecialElements(element);
+
+ var outOfScope = element.cloneNode(true); // Append this to the body before running the in-document
+ // Element tests, but after running the Document tests. This
+ // tests that no elements that are not descendants of element
+ // are selected.
+
+ traverse(outOfScope, function(elem) { // Annotate each element as being a clone; used for verifying
+ elem.setAttribute("data-clone", ""); // that none of these elements ever match.
+ });
+
+
+ var detached = element.cloneNode(true); // Detached Element Node tests
+
+ var fragment = doc.createDocumentFragment(); // Fragment Node tests
+ fragment.appendChild(element.cloneNode(true));
+
+ // Setup Tests
+ interfaceCheckQuery("Document", doc);
+ interfaceCheckQuery("Detached Element", detached);
+ interfaceCheckQuery("Fragment", fragment);
+ interfaceCheckQuery("In-document Element", element);
+
+ runSpecialSelectorTests("Document", doc);
+ runSpecialSelectorTests("Detached Element", detached);
+ runSpecialSelectorTests("Fragment", fragment);
+ runSpecialSelectorTests("In-document Element", element);
+
+ verifyStaticList("Document", doc);
+ verifyStaticList("Detached Element", detached);
+ verifyStaticList("Fragment", fragment);
+ verifyStaticList("In-document Element", element);
+
+ runInvalidSelectorTestQuery("Document", doc, invalidSelectors);
+ runInvalidSelectorTestQuery("Detached Element", detached, invalidSelectors);
+ runInvalidSelectorTestQuery("Fragment", fragment, invalidSelectors);
+ runInvalidSelectorTestQuery("In-document Element", element, invalidSelectors);
+
+ runValidSelectorTest("In-document", doc, scopedSelectors, "html");
+}
+</script>
diff --git a/tests/wpt/web-platform-tests/selectors-api/tests/submissions/Opera/ParentNode-query-queryAll.js b/tests/wpt/web-platform-tests/selectors-api/tests/submissions/Opera/ParentNode-query-queryAll.js
new file mode 100644
index 00000000000..e55a0fb2ea8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/selectors-api/tests/submissions/Opera/ParentNode-query-queryAll.js
@@ -0,0 +1,278 @@
+/*
+ * Check that the query and queryAll methods exist on the given Node
+ */
+function interfaceCheckQuery(type, obj) {
+ test(function() {
+ var q = typeof obj.query === "function";
+ assert_true(q, type + " supports query.");
+ }, type + " supports query")
+
+ test(function() {
+ var qa = typeof obj.queryAll === "function";
+ assert_true( qa, type + " supports queryAll.");
+ }, type + " supports queryAll")
+}
+
+/*
+ * Verify that the NodeList returned by queryAll is static and and that a new list is created after
+ * each call. A static list should not be affected by subsequent changes to the DOM.
+ */
+function verifyStaticList(type, root) {
+ var pre, post, preLength;
+
+ test(function() {
+ pre = root.queryAll("div");
+ preLength = pre.length;
+
+ var div = doc.createElement("div");
+ (root.body || root).appendChild(div);
+
+ assert_equals(pre.length, preLength, "The length of the NodeList should not change.")
+ }, type + ": static NodeList")
+
+ test(function() {
+ post = root.queryAll("div"),
+ assert_equals(post.length, preLength + 1, "The length of the new NodeList should be 1 more than the previous list.")
+ }, type + ": new NodeList")
+}
+
+/*
+ * Verify handling of special values for the selector parameter, including stringification of
+ * null and undefined, and the handling of the empty string.
+ */
+function runSpecialSelectorTests(type, root) {
+ test(function() { // 1
+ assert_equals(root.queryAll(null).length, 1, "This should query one element with the tag name 'NULL'.");
+ }, type + ".queryAll null")
+
+ test(function() { // 2
+ assert_equals(root.queryAll(undefined).length, 1, "This should query one elements with the tag name 'UNDEFINED'.");
+ }, type + ".queryAll undefined")
+
+ test(function() { // 3
+ assert_throws(TypeError(), function() {
+ root.queryAll();
+ }, "This should throw a TypeError.")
+ }, type + ".queryAll no parameter")
+
+ test(function() { // 4
+ var elm = root.query(null)
+ assert_not_equals(elm, null, "This should query an element.");
+ assert_equals(elm.tagName.toUpperCase(), "NULL", "The tag name should be 'NULL'.")
+ }, type + ".query null")
+
+ test(function() { // 5
+ var elm = root.query(undefined)
+ assert_not_equals(elm, undefined, "This should query an element.");
+ assert_equals(elm.tagName.toUpperCase(), "UNDEFINED", "The tag name should be 'UNDEFINED'.")
+ }, type + ".query undefined")
+
+ test(function() { // 6
+ assert_throws(TypeError(), function() {
+ root.query();
+ }, "This should throw a TypeError.")
+ }, type + ".query no parameter.")
+
+ test(function() { // 7
+ result = root.queryAll("*");
+ var i = 0;
+ traverse(root, function(elem) {
+ if (elem !== root) {
+ assert_equals(elem, result[i++], "The result in index " + i + " should be in tree order.")
+ }
+ })
+ }, type + ".queryAll tree order");
+}
+
+/*
+ * Execute queries with the specified valid selectors for both query() and queryAll()
+ * Only run these tests when results are expected. Don't run for syntax error tests.
+ *
+ * context.queryAll(selector, refNodes)
+ * context.queryAll(selector) // Only if refNodes is not specified
+ * root.queryAll(selector, context) // Only if refNodes is not specified
+ * root.queryAll(selector, refNodes) // Only if context is not specified
+ * root.queryAll(selector) // Only if neither context nor refNodes is specified
+ *
+ * Equivalent tests will be run for .query() as well.
+ */
+function runValidSelectorTest(type, root, selectors, docType) {
+ var nodeType = getNodeType(root);
+
+ for (var i = 0; i < selectors.length; i++) {
+ var s = selectors[i];
+ var n = s["name"];
+ var q = s["selector"];
+ var e = s["expect"];
+
+ var ctx = s["ctx"];
+ var ref = s["ref"];
+
+ if (!s["exclude"] || (s["exclude"].indexOf(nodeType) === -1 && s["exclude"].indexOf(docType) === -1)) {
+ //console.log("Running tests " + nodeType + ": " + s["testType"] + "&" + testType + "=" + (s["testType"] & testType) + ": " + JSON.stringify(s))
+ var foundall, found, context, refNodes, refArray;
+
+ if (s["testType"] & TEST_FIND) {
+
+
+ /*
+ * If ctx and ref are specified:
+ * context.queryAll(selector, refNodes)
+ * context.query(selector, refNodes)
+ */
+ if (ctx && ref) {
+ context = root.querySelector(ctx);
+ refNodes = root.querySelectorAll(ref);
+ refArray = Array.prototype.slice.call(refNodes, 0);
+
+ test(function() {
+ foundall = context.queryAll(q, refNodes);
+ verifyNodeList(foundall, expect);
+ }, type + " [Context Element].queryAll: " + n + " (with refNodes NodeList): " + q);
+
+ test(function() {
+ foundall = context.queryAll(q, refArray);
+ verifyNodeList(foundall, expect);
+ }, type + " [Context Element].queryAll: " + n + " (with refNodes Array): " + q);
+
+ test(function() {
+ found = context.query(q, refNodes);
+ verifyElement(found, foundall, expect)
+ }, type + " [Context Element].query: " + n + " (with refNodes NodeList): " + q);
+
+ test(function() {
+ found = context.query(q, refArray);
+ verifyElement(found, foundall, expect)
+ }, type + " [Context Element].query: " + n + " (with refNodes Array): " + q);
+ }
+
+
+ /*
+ * If ctx is specified, ref is not:
+ * context.queryAll(selector)
+ * context.query(selector)
+ * root.queryAll(selector, context)
+ * root.query(selector, context)
+ */
+ if (ctx && !ref) {
+ context = root.querySelector(ctx);
+
+ test(function() {
+ foundall = context.queryAll(q);
+ verifyNodeList(foundall, expect);
+ }, type + " [Context Element].queryAll: " + n + " (with no refNodes): " + q);
+
+ test(function() {
+ found = context.query(q);
+ verifyElement(found, foundall, expect)
+ }, type + " [Context Element].query: " + n + " (with no refNodes): " + q);
+
+ test(function() {
+ foundall = root.queryAll(q, context);
+ verifyNodeList(foundall, expect);
+ }, type + " [Root Node].queryAll: " + n + " (with refNode Element): " + q);
+
+ test(function() {
+ foundall = root.query(q, context);
+ verifyElement(found, foundall, expect);
+ }, type + " [Root Node].query: " + n + " (with refNode Element): " + q);
+ }
+
+ /*
+ * If ref is specified, ctx is not:
+ * root.queryAll(selector, refNodes)
+ * root.query(selector, refNodes)
+ */
+ if (!ctx && ref) {
+ refNodes = root.querySelectorAll(ref);
+ refArray = Array.prototype.slice.call(refNodes, 0);
+
+ test(function() {
+ foundall = root.queryAll(q, refNodes);
+ verifyNodeList(foundall, expect);
+ }, type + " [Root Node].queryAll: " + n + " (with refNodes NodeList): " + q);
+
+ test(function() {
+ foundall = root.queryAll(q, refArray);
+ verifyNodeList(foundall, expect);
+ }, type + " [Root Node].queryAll: " + n + " (with refNodes Array): " + q);
+
+ test(function() {
+ found = root.query(q, refNodes);
+ verifyElement(found, foundall, expect);
+ }, type + " [Root Node].query: " + n + " (with refNodes NodeList): " + q);
+
+ test(function() {
+ found = root.query(q, refArray);
+ verifyElement(found, foundall, expect);
+ }, type + " [Root Node].query: " + n + " (with refNodes Array): " + q);
+ }
+
+ /*
+ * If neither ctx nor ref is specified:
+ * root.queryAll(selector)
+ * root.query(selector)
+ */
+ if (!ctx && !ref) {
+ test(function() {
+ foundall = root.queryAll(q);
+ verifyNodeList(foundall, expect);
+ }, type + ".queryAll: " + n + " (with no refNodes): " + q);
+
+ test(function() {
+ found = root.query(q);
+ verifyElement(found, foundall, expect);
+ }, type + ".query: " + n + " (with no refNodes): " + q);
+ }
+ }
+ } else {
+ //console.log("Excluding for " + nodeType + ": " + s["testType"] + "&" + testType + "=" + (s["testType"] & testType) + ": " + JSON.stringify(s))
+ }
+ }
+}
+
+/*
+ * Execute queries with the specified invalid selectors for both query() and queryAll()
+ * Only run these tests when errors are expected. Don't run for valid selector tests.
+ */
+function runInvalidSelectorTestQuery(type, root, selectors) {
+ for (var i = 0; i < selectors.length; i++) {
+ var s = selectors[i];
+ var n = s["name"];
+ var q = s["selector"];
+
+ test(function() {
+ assert_throws("SyntaxError", function() {
+ root.query(q)
+ })
+ }, type + ".query: " + n + ": " + q);
+
+ test(function() {
+ assert_throws("SyntaxError", function() {
+ root.queryAll(q)
+ })
+ }, type + ".queryAll: " + n + ": " + q);
+ }
+}
+
+function verifyNodeList(resultAll, expect) {
+ assert_not_equals(resultAll, null, "The method should not return null.");
+ assert_equals(resultAll.length, e.length, "The method should return the expected number of matches.");
+
+ for (var i = 0; i < e.length; i++) {
+ assert_not_equals(resultAll[i], null, "The item in index " + i + " should not be null.")
+ assert_equals(resultAll[i].getAttribute("id"), e[i], "The item in index " + i + " should have the expected ID.");
+ assert_false(resultAll[i].hasAttribute("data-clone"), "This should not be a cloned element.");
+ }
+}
+
+function verifyElement(result, resultAll, expect) {
+ if (expect.length > 0) {
+ assert_not_equals(result, null, "The method should return a match.")
+ assert_equals(found.getAttribute("id"), e[0], "The method should return the first match.");
+ assert_equals(result, resultAll[0], "The result should match the first item from querySelectorAll.");
+ assert_false(found.hasAttribute("data-clone"), "This should not be annotated as a cloned element.");
+ } else {
+ assert_equals(result, null, "The method should not match anything.");
+ }
+}
diff --git a/tests/wpt/web-platform-tests/selectors/attribute-selectors/attribute-case/cssom.html b/tests/wpt/web-platform-tests/selectors/attribute-selectors/attribute-case/cssom.html
new file mode 100644
index 00000000000..4b1c7d3bcc1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/selectors/attribute-selectors/attribute-case/cssom.html
@@ -0,0 +1,65 @@
+<!doctype html>
+<title>Selectors: CSSOM of case-sensitivity attribute selector</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+function new_sheet(use_media) {
+ var style = document.getElementsByTagName('style')[0];
+ if (style)
+ style.parentNode.removeChild(style);
+ style = document.createElement('style');
+ document.head.appendChild(style);
+ if (use_media) {
+ style.textContent = '@media all {}';
+ return style.sheet.cssRules[0];
+ }
+ return style.sheet;
+}
+
+var tests = [
+ // test input, expected serialization
+ ['[foo="bar"] /* sanity check */', '[foo="bar"]'],
+ ['[foo="bar" i]', '[foo="bar" i]'],
+ ['[foo="bar" /**/ i]', '[foo="bar" i]'],
+ ['[foo="bar"/**/i]', '[foo="bar" i]'],
+]
+
+tests.forEach(function(arr) {
+ var input = arr[0];
+ var expected = arr[1];
+ ["", " in @media"].forEach(function(use_media) {
+ test(function() {
+ var sheet = new_sheet(use_media);
+ sheet.insertRule(input + ' {}', 0);
+ assert_equals(sheet.cssRules.length, 1);
+ }, input + ' insertRule' + use_media);
+
+ test(function() {
+ var sheet = new_sheet(use_media);
+ sheet.insertRule(input + ' {}', 0);
+ assert_equals(sheet.cssRules[0].cssText.substr(0, expected.length), expected);
+ }, input + ' getting CSSRule#cssText' + use_media);
+
+ test(function() {
+ var sheet = new_sheet(use_media);
+ sheet.insertRule('before_set {}', 0);
+ sheet.cssRules[0].cssText = input + ' {}';
+ assert_equals(sheet.cssRules[0].cssText.substr(0, expected.length), expected);
+ }, input + ' setting CSSRule#cssText' + use_media);
+
+ test(function() {
+ var sheet = new_sheet(use_media);
+ sheet.insertRule(input + ' {}', 0);
+ assert_equals(sheet.cssRules[0].selectorText, expected);
+ }, input + ' getting CSSStyleRule#selectorText' + use_media);
+
+ test(function() {
+ var sheet = new_sheet(use_media);
+ sheet.insertRule('foobar {}', 0);
+ sheet.cssRules[0].selectorText = input;
+ assert_equals(sheet.cssRules[0].selectorText, expected);
+ }, input + ' setting CSSStyleRule#selectorText' + use_media);
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/selectors/attribute-selectors/attribute-case/resources/semantics-quirks.html b/tests/wpt/web-platform-tests/selectors/attribute-selectors/attribute-case/resources/semantics-quirks.html
new file mode 100644
index 00000000000..b6c3dfe4ea0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/selectors/attribute-selectors/attribute-case/resources/semantics-quirks.html
@@ -0,0 +1,4 @@
+<style></style>
+<script>
+var mode = "quirks mode";
+</script>
diff --git a/tests/wpt/web-platform-tests/selectors/attribute-selectors/attribute-case/resources/semantics-xml.xhtml b/tests/wpt/web-platform-tests/selectors/attribute-selectors/attribute-case/resources/semantics-xml.xhtml
new file mode 100644
index 00000000000..f4d40fb852b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/selectors/attribute-selectors/attribute-case/resources/semantics-xml.xhtml
@@ -0,0 +1,10 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<style></style>
+</head>
+<body>
+<script>
+var mode = "XML";
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/selectors/attribute-selectors/attribute-case/resources/syntax-quirks.html b/tests/wpt/web-platform-tests/selectors/attribute-selectors/attribute-case/resources/syntax-quirks.html
new file mode 100644
index 00000000000..4606419b31c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/selectors/attribute-selectors/attribute-case/resources/syntax-quirks.html
@@ -0,0 +1,5 @@
+<style></style>
+<div id=test foo="BAR"></div>
+<script>
+var mode = "quirks mode";
+</script>
diff --git a/tests/wpt/web-platform-tests/selectors/attribute-selectors/attribute-case/resources/syntax-xml.xhtml b/tests/wpt/web-platform-tests/selectors/attribute-selectors/attribute-case/resources/syntax-xml.xhtml
new file mode 100644
index 00000000000..19491c94c46
--- /dev/null
+++ b/tests/wpt/web-platform-tests/selectors/attribute-selectors/attribute-case/resources/syntax-xml.xhtml
@@ -0,0 +1,11 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<style></style>
+</head>
+<body>
+<div id="test" foo="BAR"/>
+<script>
+var mode = "XML";
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/selectors/attribute-selectors/attribute-case/semantics.html b/tests/wpt/web-platform-tests/selectors/attribute-selectors/attribute-case/semantics.html
new file mode 100644
index 00000000000..7b6d7373af0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/selectors/attribute-selectors/attribute-case/semantics.html
@@ -0,0 +1,146 @@
+<!doctype html>
+<title>Selectors: semantics of case-sensitivity attribute selector</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style></style>
+<div id=log></div>
+<iframe id="quirks" src="resources/semantics-quirks.html"></iframe>
+<iframe id="xml" src="resources/semantics-xml.xhtml"></iframe>
+<script>
+setup({explicit_done:true});
+var match = [
+ // [selector, attrs...] (each attr is [ns, name, value])
+ ["[foo='BAR'] /* sanity check (match) */", ["", "foo", "BAR"]],
+ ["[foo='bar' i]", ["", "foo", "BAR"]],
+ ["[foo='' i]", ["", "foo", ""]],
+ ["[foo='a\u0308' i] /* COMBINING in both */", ["", "foo", "A\u0308"]],
+ ["[foo='A\u0308' i] /* COMBINING in both */", ["", "foo", "a\u0308"]],
+ ["[*|foo='bar' i]", ["", "foo", "x"], ["a", "foo", "x"], ["b", "foo", "BAR"], ["c", "foo", "x"]],
+ ["[*|foo='bar' i]", ["", "foo", "BAR"], ["a", "foo", "x"], ["b", "foo", "x"], ["c", "foo", "x"]],
+ ["[align='left' i]", ["", "align", "LEFT"]],
+ ["[align='LEFT' i]", ["", "align", "left"]],
+ ["[class='a' i]", ["", "class", "A"]],
+ ["[class='A' i]", ["", "class", "a"]],
+ ["[id='a' i]", ["", "id", "A"]],
+ ["[id='A' i]", ["", "id", "a"]],
+ ["[lang='a' i]", ["", "lang", "A"]],
+ ["[lang='A' i]", ["", "lang", "a"]],
+ ["[*|lang='a' i]", ["http://www.w3.org/XML/1998/namespace", "lang", "A"]],
+ ["[*|lang='A' i]", ["http://www.w3.org/XML/1998/namespace", "lang", "a"]],
+ ["@namespace x 'http://www.w3.org/XML/1998/namespace'; [x|lang='A' i]", ["http://www.w3.org/XML/1998/namespace", "lang", "a"]],
+ ["[foo='bar' i][foo='bar' i]", ["", "foo", "BAR"]],
+ ["[foo='BAR'][foo='bar' i]", ["", "foo", "BAR"]],
+ ["[foo='bar' i][foo='BAR']", ["", "foo", "BAR"]],
+];
+var nomatch = [
+ ["[missingattr] /* sanity check (no match) */", ["", "foo", "BAR"]],
+ ["[foo='' i]", ["", "foo", "BAR"]],
+ ["[foo='\u0000' i] /* \\0 in selector */", ["", "foo", ""]],
+ ["[foo='' i] /* \\0 in attribute */", ["", "foo", "\u0000"]],
+ ["[foo='\u00E4' i]", ["", "foo", "\u00C4"]],
+ ["[foo='\u00C4' i]", ["", "foo", "\u00E4"]],
+ ["[foo='a\u0308' i] /* COMBINING in selector */", ["", "foo", "\u00C4"]],
+ ["[foo='a\u0308' i] /* COMBINING in selector */", ["", "foo", "\u00E4"]],
+ ["[foo='A\u0308' i] /* COMBINING in selector */", ["", "foo", "\u00C4"]],
+ ["[foo='A\u0308' i] /* COMBINING in selector */", ["", "foo", "\u00E4"]],
+ ["[foo='\u00E4' i] /* COMBINING in attribute */", ["", "foo", "a\u0308"]],
+ ["[foo='\u00E4' i] /* COMBINING in attribute */", ["", "foo", "A\u0308"]],
+ ["[foo='\u00C4' i] /* COMBINING in attribute */", ["", "foo", "a\u0308"]],
+ ["[foo='\u00C4' i] /* COMBINING in attribute */", ["", "foo", "A\u0308"]],
+ ["[foo='a\u0308' i] /* COMBINING in selector */", ["", "foo", "a"]],
+ ["[foo='a\u0308' i] /* COMBINING in selector */", ["", "foo", "A"]],
+ ["[foo='A\u0308' i] /* COMBINING in selector */", ["", "foo", "a"]],
+ ["[foo='A\u0308' i] /* COMBINING in selector */", ["", "foo", "A"]],
+ ["[foo='a' i] /* COMBINING in attribute */", ["", "foo", "a\u0308"]],
+ ["[foo='A' i] /* COMBINING in attribute */", ["", "foo", "a\u0308"]],
+ ["[foo='a' i] /* COMBINING in attribute */", ["", "foo", "A\u0308"]],
+ ["[foo='A' i] /* COMBINING in attribute */", ["", "foo", "A\u0308"]],
+ ["[foo='i' i]", ["", "foo", "\u0130"]],
+ ["[foo='i' i]", ["", "foo", "\u0131"]],
+ ["[foo='I' i]", ["", "foo", "\u0130"]],
+ ["[foo='I' i]", ["", "foo", "\u0131"]],
+ ["[foo='\u0130' i]", ["", "foo", "i"]],
+ ["[foo='\u0131' i]", ["", "foo", "i"]],
+ ["[foo='\u0130' i]", ["", "foo", "I"]],
+ ["[foo='\u0131' i]", ["", "foo", "I"]],
+ ["[foo='bar' i]", ["", "foo", "x"], ["a", "foo", "BAR"]],
+ ["[|foo='bar' i]", ["", "foo", "x"], ["a", "foo", "BAR"]],
+ ["[foo='bar' i]", ["", "FOO", "bar"]],
+ ["[foo='\t' i] /* tab in selector */", ["", "foo", " "]],
+ ["[foo=' ' i] /* tab in attribute */", ["", "foo", "\t"]],
+ ["@namespace x 'a'; [x|foo='' i]", ["A", "foo", ""]],
+ ["@namespace x 'A'; [x|foo='' i]", ["a", "foo", ""]],
+ ["[foo='bar' i][foo='bar']", ["", "foo", "BAR"]],
+ ["[foo='bar' i]", ["", "baz", "BAR"]],
+];
+var mode = "standards mode";
+function format_attrs(attrs) {
+ var rv = [];
+ attrs.forEach(function(attr) {
+ var str = "";
+ var ns = attr[0];
+ var name = attr[1];
+ var value = attr[2];
+ if (ns)
+ str += "{" + ns + "}";
+ str += name + "=\"" + value + "\"";
+ rv.push(str);
+ });
+ return rv.join(" ");
+}
+onload = function() {
+ var quirks = document.getElementById('quirks').contentWindow;
+ var xml = document.getElementById('xml').contentWindow;
+ [window, quirks, xml].forEach(function(global) {
+ var style = global.document.getElementsByTagName('style')[0];
+ var elm;
+ function clean_slate() {
+ style.textContent = '';
+ if (elm)
+ elm.parentNode.removeChild(elm);
+ elm = global.document.createElement('div');
+ global.document.body.appendChild(elm);
+ }
+ function set_attrs(attrs) {
+ attrs.forEach(function(attr) {
+ elm.setAttributeNS(attr[0], attr[1], attr[2]);
+ });
+ }
+ match.forEach(function(arr) {
+ var s = arr[0];
+ var attrs = arr.slice(1);
+ var ns_decl = s.substr(0, "@namespace".length) == "@namespace";
+ test(function() {
+ clean_slate();
+ set_attrs(attrs);
+ style.textContent = s + ' { visibility:hidden }';
+ assert_equals(style.sheet.cssRules.length, (ns_decl ? 2 : 1), 'rule didn\'t parse into CSSOM');
+ assert_equals(global.getComputedStyle(elm).visibility, 'hidden', 'selector didn\'t match');
+ }, s + ' <div ' + format_attrs(attrs) + '> in ' + global.mode);
+ if (!ns_decl) {
+ test(function() {
+ assert_equals(global.document.querySelector(s), elm, 'selector didn\'t match');
+ }, s + ' <div ' + format_attrs(attrs) + '> with querySelector in ' + global.mode);
+ }
+ });
+ nomatch.forEach(function(arr) {
+ var s = arr[0];
+ var attrs = arr.slice(1);
+ var ns_decl = s.substr(0, "@namespace".length) == "@namespace";
+ test(function() {
+ clean_slate();
+ set_attrs(attrs);
+ style.textContent = s + ' { visibility:hidden }';
+ assert_equals(style.sheet.cssRules.length, (ns_decl ? 2 : 1), 'rule didn\'t parse into CSSOM');
+ assert_equals(global.getComputedStyle(elm).visibility, 'visible', 'selector matched');
+ }, s + ' <div ' + format_attrs(attrs) + '> in ' + global.mode);
+ if (!ns_decl) {
+ test(function() {
+ assert_equals(global.document.querySelector(s), null, 'selector matched');
+ }, s + ' <div ' + format_attrs(attrs) + '> with querySelector in ' + global.mode);
+ }
+ });
+ });
+ done();
+};
+</script>
diff --git a/tests/wpt/web-platform-tests/selectors/attribute-selectors/attribute-case/syntax.html b/tests/wpt/web-platform-tests/selectors/attribute-selectors/attribute-case/syntax.html
new file mode 100644
index 00000000000..754af95c9d0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/selectors/attribute-selectors/attribute-case/syntax.html
@@ -0,0 +1,117 @@
+<!doctype html>
+<title>Selectors: syntax of case-sensitivity attribute selector</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style></style>
+<div id=log></div>
+<div id=test foo="BAR"></div>
+<iframe id="quirks" src="resources/syntax-quirks.html"></iframe>
+<iframe id="xml" src="resources/syntax-xml.xhtml"></iframe>
+<script>
+setup({explicit_done:true});
+var valid = [
+ "[foo='BAR'] /* sanity check (valid) */",
+ "[foo='bar' i]",
+ "[foo=bar i]",
+ '[foo="bar" i]',
+ "[foo='bar'i]",
+ "[foo='bar'i ]",
+ "[foo='bar' i ]",
+ "[foo='bar' /**/ i]",
+ "[foo='bar' i /**/ ]",
+ "[foo='bar'/**/i/**/]",
+ "[foo=bar/**/i]",
+ "[foo='bar'\ti\t] /* \\t */",
+ "[foo='bar'\ni\n] /* \\n */",
+ "[foo='bar'\ri\r] /* \\r */",
+ "[foo='bar' \\i]",
+ "[foo='bar' \\69]",
+ "[foo~='bar' i]",
+ "[foo^='bar' i]",
+ "[foo$='bar' i]",
+ "[|foo='bar' i]",
+ "[*|foo='bar' i]",
+];
+var invalid = [
+ "[foo[ /* sanity check (invalid) */",
+ "[foo='bar' i i]",
+ "[foo='bar' I]",
+ "[foo i ='bar']",
+ "[foo= i 'bar']",
+ "[i foo='bar']",
+ "[foo='bar' i\u0000] /* \\0 */",
+ "[foo='bar' \u0130]",
+ "[foo='bar' \u0131]",
+ "[foo='bar' ii]",
+ "[foo='bar' ij]",
+ "[foo='bar' j]",
+ "[foo='bar' \\\\i]",
+ "[foo='bar' \\\\69]",
+ "[foo='bar' i()]",
+ "[foo='bar' i ()]",
+ "[foo='bar' () i]",
+ "[foo='bar' (i)]",
+ "[foo='bar' i []]",
+ "[foo='bar' [] i]",
+ "[foo='bar' [i]]",
+ "[foo='bar' i {}]",
+ "[foo='bar' {} i]",
+ "[foo='bar' {i}]",
+ "[foo='bar' 1i]",
+ "[foo='bar' 1]",
+ "[foo='bar' 'i']",
+ "[foo='bar' url(i)]",
+ "[foo='bar' ,i]",
+ "[foo='bar' i,]",
+ "[foo='bar']i",
+ "[foo='bar' |i]",
+ "[foo='bar' \\|i]",
+ "[foo='bar' *|i]",
+ "[foo='bar' \\*|i]",
+ "[foo='bar' *]",
+ "[foo='bar' \\*]",
+ "[foo i]",
+ "[foo/**/i]",
+];
+var mode = "standards mode";
+onload = function() {
+ var quirks = document.getElementById('quirks').contentWindow;
+ var xml = document.getElementById('xml').contentWindow;
+ [window, quirks, xml].forEach(function(global) {
+ var style = global.document.getElementsByTagName('style')[0];
+ var elm = global.document.getElementById('test');
+ function clean_slate() {
+ style.textContent = '';
+ assert_equals(style.sheet.cssRules.length, 0, 'CSSOM was not empty for empty stylesheet');
+ assert_equals(global.getComputedStyle(elm).visibility, 'visible', 'computed style for empty stylesheet');
+ }
+ valid.forEach(function(s) {
+ test(function() {
+ clean_slate();
+ style.textContent = s + ' { visibility:hidden }';
+ assert_equals(style.sheet.cssRules.length, 1, 'valid rule didn\'t parse into CSSOM');
+ assert_equals(global.getComputedStyle(elm).visibility, 'hidden', 'valid selector didn\'t match');
+ }, s + ' in ' + global.mode);
+ test(function() {
+ assert_equals(global.document.querySelector(s), elm, 'valid selector');
+ }, s + ' with querySelector in ' + global.mode);
+ });
+ invalid.forEach(function(s) {
+ test(function() {
+ clean_slate();
+ style.textContent = s + ' { visibility:hidden }';
+ assert_equals(style.sheet.cssRules.length, 0, 'invalid rule parsed into CSSOM');
+ assert_equals(global.getComputedStyle(elm).visibility, 'visible', 'invalid selector matched');
+ }, s + ' in ' + global.mode);
+ test(function() {
+ // Should be TypeError but this is not widely implemented yet
+ // and this isn't intended to be a querySelector API conformance test.
+ assert_throws(null, function() {
+ global.document.querySelector(s);
+ }, 'invalid selector');
+ }, s + ' with querySelector in ' + global.mode);
+ });
+ });
+ done();
+};
+</script>
diff --git a/tests/wpt/web-platform-tests/serve b/tests/wpt/web-platform-tests/serve
new file mode 100755
index 00000000000..51761b02c62
--- /dev/null
+++ b/tests/wpt/web-platform-tests/serve
@@ -0,0 +1,5 @@
+#!/usr/bin/env python
+import serve
+
+if __name__ == "__main__":
+ serve.main()
diff --git a/tests/wpt/web-platform-tests/serve.py b/tests/wpt/web-platform-tests/serve.py
new file mode 100644
index 00000000000..536ed4963e5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/serve.py
@@ -0,0 +1,5 @@
+#!/usr/bin/env python
+from tools.serve import serve
+
+def main():
+ serve.main()
diff --git a/tests/wpt/web-platform-tests/server-side.md b/tests/wpt/web-platform-tests/server-side.md
new file mode 100644
index 00000000000..46a9e8367c3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/server-side.md
@@ -0,0 +1,234 @@
+# Writing Complex Tests #
+
+For many tests, writing one or more static HTML files is
+sufficient. However there are a large class of tests for which this
+approach is insufficient, including:
+
+* Tests that require cross-domain access
+
+* Tests that depend on setting specific headers or status codes
+
+* Tests that need to inspect the browser sent request
+
+* Tests that require state to be stored on the server
+
+* Tests that require precise timing of the response.
+
+To make writing such tests possible, we are using a number of
+server-side components designed to make it easy to manipulate the
+precise details of the response:
+
+* *wptserve*, a custom python HTTP server.
+
+* *pywebsocket*, an existing websockets server
+
+This document will concentrate on the features of wptserve available
+to test authors.
+
+## Introduction to wptserve ##
+
+wptserve is a python-based web server. By default it serves static
+files in the testsuite. For more sophisticated requirements, several
+mechanisms are available to take control of the response. These are
+outlined below.
+
+## Pipes ##
+
+Suitable for:
+
+ * Cross domain requests
+ * Adding headers or status codes to static files
+ * Controlling the sending of static file bodies
+
+Pipes are designed to allow simple manipulation of the way that
+static files are sent without requiring any custom code. They are also
+useful for cross-origin tests because they can be used to activate a
+substitution mechanism which can fill in details of ports and server
+names in the setup on which the tests are being run.
+
+Pipes are indicated by adding a query string to a request for a static
+resource, with the parameter name `pipe`. The value of the query
+should be a `|` serperated list of pipe functions. For example to
+return a `.html` file with the status code 410 and a Content-Type of
+text/plain, one might use:
+
+ /resources/example.html?pipe=status(410)|header(Content-Type,text/plain)
+
+There are a selection of pipe functions provided with wptserve and
+more may be added if there are good use cases.
+
+### sub ###
+
+Used to subsitute variables from the server environment, or from the
+request into the response. A typical use case is for testing
+cross-domain since the exact domain name and ports of the servers are
+generally unknown.
+
+Substitutions are marked in a file using a block delimited by `{{`
+and `}}`. Inside the block the following variables are avalible:
+
+* `{{host}}` - the host name of the server exclusing any subdomain part.
+* `{{domains[]}}` - the domain name of a particular subdomain
+ e.g. `{{domains[www]}}` for the `www` subdomain.
+* `{{ports[][]}}` - The port number of servers, by protocol
+ e.g. `{{ports[http][1]}}` for the second (i.e. non-default) http
+ server.
+* `{{headers[]}}` - The HTTP headers in the request
+ e.g. `{{headers[X-Test]}}` for a hypothetical `X-Test` header.
+* `{{GET[]}}` - The query parameters for the request
+ e.g. `{{GET[id]}}` for an id parameter sent with the request.
+
+So, for example, to write a javascript file called `xhr.js` that does a
+cross domain XHR test to a different subdomain and port, one would
+write in the file:
+
+ var server_url = "http://{{domains[www]}}:{{ports[http][1]}}/path/to/resource";
+ //Create the actual XHR and so on
+
+The file would then be included as:
+
+ <script src="xhr.js?pipe=sub"></script>
+
+### status ###
+
+Used to set the HTTP status of the response, for example:
+
+ example.js?pipe=status(410)
+
+### headers ###
+
+Used to add or replace http headers in the response. Takes two or
+three arguments; the header name, the header value and whether to
+append the header rather than replace an existing header (default:
+False). So, for example, a request for:
+
+ example.html?pipe=header(Content-Type,text/plain)
+
+causes example.html to be returned with a text/plain content type
+whereas:
+
+ example.html?pipe=header(Content-Type,text/plain,True)
+
+Will cause example.html to be returned with both text/html and
+text/plain content-type headers.
+
+### slice ###
+
+Used to send only part of a response body. Takes the start and,
+optionally, end bytes as arguments, although either can be null to
+indicate the start or end of the file, respectively. So for example:
+
+ example.txt?pipe=slice(10,20)
+
+Would result in a response with a body containing 10 bytes of
+example.txt including byte 10 but excluding byte 20.
+
+ example.txt?pipe=slice(10)
+
+Would cause all bytes from byte 10 of example.txt to be sent, but:
+
+ example.txt?pipe=slice(null,20)
+
+Would send the first 20 bytes of example.txt.
+
+### trickle ###
+
+Used to send the body of a response in chunks with delays. Takes a
+single argument that is a microsyntax consisting of colon-separated
+commands. There are three types of commands:
+
+* Bare numbers represent a number of bytes to send
+
+* Numbers prefixed `d` indicate a delay in seconds
+
+* Numbers prefixed `r` must only appear at the end of the command, and
+ indicate that the preceding N items must be repeated until there is
+ no more content to send.
+
+In the absence of a repetition command, the entire remainder of the content is
+sent at once when the command list is exhausted. So for example:
+
+ example.txt?pipe=trickle(d1)
+
+causes a 1s delay before sending the entirety of example.txt.
+
+ example.txt?pipe=trickle(100:d1)
+
+causes 100 bytes of example.txt to be sent, followed by a 1s delay,
+and then the remainder of the file to be sent. On the other hand:
+
+ example.txt?pipe=trickle(100:d1:r2)
+
+Will cause the file to be sent in 100 byte chunks separated by a 1s
+delay until the whole content has been sent.
+
+## asis files ##
+
+Suitable for:
+
+ * Static, HTTP-non-compliant responses
+
+asis files are simply files with the extension `.asis`. They are sent
+byte for byte to the server without adding a HTTP status line,
+headers, or anything else. This makes them suitable for testing
+situations where the precise bytes on the wire are static, and control
+over the timing is unnecessary, but the response does not conform to
+HTTP requirements.
+
+## py files ##
+
+Suitable for:
+
+ * All tests requiring dynamic responses
+ * Tests that need to store server side state.
+
+The most flexible mechanism for writing tests is to use `.py`
+files. These are interpreted as code and are suitable for the same
+kinds of tasks that one might achieve using cgi, PHP or a similar
+technology. Unlike cgi or PHP, the file is not executed directly and
+does not produce output by writing to `stdout`. Instead files must
+contain (at least) a function named `main`, with the signature:
+
+ def main(request, response):
+ pass
+
+Here `request` is a `Request` object that contains details of the
+request, and `response` is a `Response` object that can be used to set
+properties of the response. Full details of these objects is
+provided in the [wptserve documentation](http://wptserve.readthedocs.org/en/latest/).
+
+In many cases tests will not need to work with the `response` object
+directly. Instead they can set the status, headers and body simply by
+returning values from the `main` function. If any value is returned,
+it is interpreted as the response body. If two values are returned
+they are interpreted as headers and body, and three values are
+interpreted as status, headers, body. So, for example:
+
+ def main(request, response):
+ return "TEST"
+
+creates a response with no non-default headers and the body
+`TEST`. Headers can be added as follows:
+
+ def main(request, response):
+ return ([("Content-Type", "text/plain"), ("X-Test", "test")],
+ "TEST")
+
+And a status code as:
+
+ def main(request, response):
+ return (410,
+ [("Content-Type", "text/plain"), ("X-Test", "test")],
+ "TEST")
+
+A custom status string may be returned by using a tuple `code, string`
+in place of the code alone.
+
+At the other end of the scale, some tests require precision over the
+exact bytes sent over the wire and their timing. This can be achieved
+using the `writer` property of the response, which exposes a
+`ResponseWriter` object that allows wither writing specific parts of
+the request or direct access to the underlying socket.
+
+For full documentation on the facilities available in `.py` files, see
+the [wptserve documentation](http://wptserve.readthedocs.org/en/latest/).
diff --git a/tests/wpt/web-platform-tests/service-workers/specgen.json b/tests/wpt/web-platform-tests/service-workers/specgen.json
new file mode 100644
index 00000000000..5d76da8271a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/specgen.json
@@ -0,0 +1,658 @@
+{
+ "sections": [
+ {
+ "href": "#introduction",
+ "id": "introduction",
+ "hash": "da39a3ee5e6b4b0d3255bfef95601890afd80709",
+ "secno": "1",
+ "testable": false
+ },
+ {
+ "href": "#about",
+ "id": "about",
+ "hash": "8d3cf149aa73cff52328509ebbaffd933e8fb6af",
+ "secno": "1.1",
+ "testable": false
+ },
+ {
+ "href": "#dependencies",
+ "id": "dependencies",
+ "hash": "1355f2d7ec9bf4e617ee632c0db44f834c96435b",
+ "secno": "1.2",
+ "testable": false
+ },
+ {
+ "href": "#motivations",
+ "id": "motivations",
+ "hash": "92d899bc1e63a170d2324638d16f580b97b4f4d6",
+ "secno": "1.3",
+ "testable": false
+ },
+ {
+ "href": "#concepts",
+ "id": "concepts",
+ "hash": "589023372dc033b0a77be1cd01f54f5f8c3ebfa8",
+ "secno": "2",
+ "testable": false
+ },
+ {
+ "href": "#document-context",
+ "id": "document-context",
+ "hash": "34feeb18dea978349a2f76e6b17c127123b3db74",
+ "secno": "3",
+ "testable": false
+ },
+ {
+ "href": "#service-worker-obj",
+ "id": "service-worker-obj",
+ "hash": "6cbd0107199072ab86b36e72d08d5465b42e6da8",
+ "secno": "3.1",
+ "testPageHash": "8dbbc9aa4300f0203524f3e405dbf7ca462e7164",
+ "testPagePath": "stub-3.1-service-worker-obj.html",
+ "testable": true
+ },
+ {
+ "href": "#service-worker-scope",
+ "id": "service-worker-scope",
+ "hash": "136f25ef227515a7be9b32c44967f68b34ad8924",
+ "secno": "3.1.1",
+ "testPageHash": "965a00b32d56192330aa9f6337072bb3633ad382",
+ "testPagePath": "stub-3.1.1-service-worker-scope.html",
+ "testable": true
+ },
+ {
+ "href": "#service-worker-url",
+ "id": "service-worker-url",
+ "hash": "df66a1b4b3bfa3e7ab96fd491a6829fab1d18a88",
+ "secno": "3.1.2",
+ "testPageHash": "92f6aed1437bb39c5941b495ac6c5f342c025b38",
+ "testPagePath": "stub-3.1.2-service-worker-url.html",
+ "testable": true
+ },
+ {
+ "href": "#service-worker-state",
+ "id": "service-worker-state",
+ "hash": "8f80f2b4cbb1c228867c9dd90c05cbecfc92dd77",
+ "secno": "3.1.3",
+ "testPageHash": "4aad1dc47572879fdc2c79a814ad21e1ef9a64ec",
+ "testPagePath": "stub-3.1.3-service-worker-state.html",
+ "testable": true
+ },
+ {
+ "href": "#service-worker-on-state-change",
+ "id": "service-worker-on-state-change",
+ "hash": "0f8fd9d1431deacea72fe739f42992ab5a396bf2",
+ "secno": "3.1.4",
+ "testPageHash": "6bb309bccc1e7c74ade7fc4c6e400bafb60daceb",
+ "testPagePath": "stub-3.1.4-service-worker-on-state-change.html",
+ "testable": true
+ },
+ {
+ "href": "#navigator-service-worker",
+ "id": "navigator-service-worker",
+ "hash": "22f1ebbafca6976d0f4814b0fbb8f173bf919f06",
+ "secno": "3.2",
+ "testPageHash": "6d597735816a09ec774150029ed5136198f52ab7",
+ "testPagePath": "stub-3.2-navigator-service-worker.html",
+ "testable": true
+ },
+ {
+ "href": "#navigator-service-worker-installing",
+ "id": "navigator-service-worker-installing",
+ "hash": "9675c3cdf5ba4b4155284e06a19e4de631645509",
+ "secno": "3.2.1",
+ "testPageHash": "2c8e56e74c130104e395de46bad20fb5d3021d95",
+ "testPagePath": "stub-3.2.1-navigator-service-worker-installing.html",
+ "testable": true
+ },
+ {
+ "href": "#navigator-service-worker-waiting",
+ "id": "navigator-service-worker-waiting",
+ "hash": "88b4db92cc49109e6a15ddebdd219690d9648e76",
+ "secno": "3.2.2",
+ "testPageHash": "1cf6ed58bf5ecf963fed8c3d9211b853dab564e2",
+ "testPagePath": "stub-3.2.2-navigator-service-worker-waiting.html",
+ "testable": true
+ },
+ {
+ "href": "#navigator-service-worker-active",
+ "id": "navigator-service-worker-active",
+ "hash": "0da48e885c77da60d1837197780049904789e3cb",
+ "secno": "3.2.3",
+ "testPageHash": "f5dca8c6eb5f29a0f9a5f06e25861e7f3106cc67",
+ "testPagePath": "stub-3.2.3-navigator-service-worker-active.html",
+ "testable": true
+ },
+ {
+ "href": "#navigator-service-worker-controller",
+ "id": "navigator-service-worker-controller",
+ "hash": "293433ccb7bb2a22d8d5a81e788892e071b25e65",
+ "secno": "3.2.4",
+ "testPageHash": "6452f431d0765d7aa3135d18fee43e6664dcbb12",
+ "testPagePath": "stub-3.2.4-navigator-service-worker-controller.html",
+ "testable": true
+ },
+ {
+ "href": "#navigator-service-worker-ready",
+ "id": "navigator-service-worker-ready",
+ "hash": "6240fde8d7168beeb95f4f36aa9e143319b2061b",
+ "secno": "3.2.5",
+ "testPageHash": "ae4fd694c88bab72f338d97bf96b7d23e2e83e87",
+ "testPagePath": "stub-3.2.5-navigator-service-worker-ready.html",
+ "testable": true
+ },
+ {
+ "href": "#navigator-service-worker-getAll",
+ "id": "navigator-service-worker-getAll",
+ "hash": "292ee3af2cc8fadc24302446809d04bf2e9811a5",
+ "secno": "3.2.6",
+ "testPageHash": "4096ae712cc3e753456fbe05bb4d0cfc4399d2c9",
+ "testPagePath": "stub-3.2.6-navigator-service-worker-getAll.html",
+ "testable": true
+ },
+ {
+ "href": "#navigator-service-worker-register",
+ "id": "navigator-service-worker-register",
+ "hash": "c999dc5f67126c9f0f02b25fd943a34b48cff618",
+ "secno": "3.2.7",
+ "testPageHash": "bde900b97dbb08b053ff8115775ea3b79a124b6e",
+ "testPagePath": "stub-3.2.7-navigator-service-worker-register.html",
+ "testable": true
+ },
+ {
+ "href": "#navigator-service-worker-unregister",
+ "id": "navigator-service-worker-unregister",
+ "hash": "fd196f926f181563855e4683cc995405c1e611d0",
+ "secno": "3.2.8",
+ "testPageHash": "dbd99a1dcbcb629431617790a305e840495049eb",
+ "testPagePath": "stub-3.2.8-navigator-service-worker-unregister.html",
+ "testable": true
+ },
+ {
+ "href": "#navigator-service-worker-onupdatefound",
+ "id": "navigator-service-worker-onupdatefound",
+ "hash": "2bb5aabaca24a68f9e6b4c4443968178eb1ccfe8",
+ "secno": "3.2.9",
+ "testPageHash": "eef0c1c39577abefb3654a6e9917ff2da657871b",
+ "testPagePath": "stub-3.2.9-navigator-service-worker-onupdatefound.html",
+ "testable": true
+ },
+ {
+ "href": "#navigator-service-worker-oncontrollerchange",
+ "id": "navigator-service-worker-oncontrollerchange",
+ "hash": "c89a4ffba10d9285e07c38c28718719d87053994",
+ "secno": "3.2.10",
+ "testPageHash": "35e0ce2b8f4527ebbd75d4dfa3436fd7f8c79792",
+ "testPagePath": "stub-3.2.10-navigator-service-worker-oncontrollerchange.html",
+ "testable": true
+ },
+ {
+ "href": "#navigator-service-worker-onreloadpage",
+ "id": "navigator-service-worker-onreloadpage",
+ "hash": "424441910abf2e1bdc3db658fe46827f7abe60a4",
+ "secno": "3.2.11",
+ "testPageHash": "ae614de17e5f339b65f77cafa6e0f5625491abfb",
+ "testPagePath": "stub-3.2.11-navigator-service-worker-onreloadpage.html",
+ "testable": true
+ },
+ {
+ "href": "#navigator-service-worker-onerror",
+ "id": "navigator-service-worker-onerror",
+ "hash": "710f7fcd2f5340147b9e030bc5932b8242cef828",
+ "secno": "3.2.12",
+ "testPageHash": "cd62779e27151d55f14ac6ab7aa41dcf723e0ac7",
+ "testPagePath": "stub-3.2.12-navigator-service-worker-onerror.html",
+ "testable": true
+ },
+ {
+ "href": "#execution-context",
+ "id": "execution-context",
+ "hash": "ddf24f0adf58237e264c3c43cb7ab07af3013c9d",
+ "secno": "4",
+ "testable": false
+ },
+ {
+ "href": "#service-worker-global-scope",
+ "id": "service-worker-global-scope",
+ "hash": "e6b8bb7f99c125f4226fc5b6c51cf03a7437f2ef",
+ "secno": "4.1",
+ "testPageHash": "2f596b6b07bcfb71c01d75f725eb52c84e9c69dd",
+ "testPagePath": "stub-4.1-service-worker-global-scope.html",
+ "testable": true
+ },
+ {
+ "href": "#service-worker-global-scope-caches",
+ "id": "service-worker-global-scope-caches",
+ "hash": "43d3c9f441b3a7abd0d3a7f55d93faaceeb7d97d",
+ "secno": "4.1.1",
+ "testPageHash": "f19b91c887f6312688b66b1988147a599cd9470f",
+ "testPagePath": "stub-4.1.1-service-worker-global-scope-caches.html",
+ "testable": true
+ },
+ {
+ "href": "#service-worker-global-scope-clients",
+ "id": "service-worker-global-scope-clients",
+ "hash": "cb83230107645229da9776ed0fc9f7bc6fcce747",
+ "secno": "4.1.2",
+ "testPageHash": "45b3aae572f7161748fa98e97b4f2b738c3dcfef",
+ "testPagePath": "stub-4.1.2-service-worker-global-scope-clients.html",
+ "testable": true
+ },
+ {
+ "href": "#service-worker-global-scope-scope",
+ "id": "service-worker-global-scope-scope",
+ "hash": "08c808048b647aa9d4cc0b0a0f70b06ca89af4a3",
+ "secno": "4.1.3",
+ "testPageHash": "bfe7eaf8deb8de7d2ccfbba97640478b1c81d6c7",
+ "testPagePath": "stub-4.1.3-service-worker-global-scope-scope.html",
+ "testable": true
+ },
+ {
+ "href": "#service-worker-global-scope-fetch",
+ "id": "service-worker-global-scope-fetch",
+ "hash": "b66133d8a2c67f9b10c274d5b05383ff76d2cd42",
+ "secno": "4.1.4",
+ "testPageHash": "2b1ffa915afddeb099dfff23f4ecf555b0710ed4",
+ "testPagePath": "stub-4.1.4-service-worker-global-scope-fetch.html",
+ "testable": true
+ },
+ {
+ "href": "#service-worker-global-scope-update",
+ "id": "service-worker-global-scope-update",
+ "hash": "3ddf48cecb4d4a67a329248787dd220ce17f4eff",
+ "secno": "4.1.5",
+ "testPageHash": "15879bf45f460c0ab0c02793655096c1bca418a7",
+ "testPagePath": "stub-4.1.5-service-worker-global-scope-update.html",
+ "testable": true
+ },
+ {
+ "href": "#service-worker-global-scope-unregister",
+ "id": "service-worker-global-scope-unregister",
+ "hash": "fff9ef2daa5689b38a17eeb9a6bd7071098ca778",
+ "secno": "4.1.6",
+ "testPageHash": "c4bf327228628b794db9c6f2eb17519e37cea6b9",
+ "testPagePath": "stub-4.1.6-service-worker-global-scope-unregister.html",
+ "testable": true
+ },
+ {
+ "href": "#service-worker-global-scope-onmessage",
+ "id": "service-worker-global-scope-onmessage",
+ "hash": "bc8f6aed2d515dc7f6b0757afa02f37899082668",
+ "secno": "4.1.7",
+ "testPageHash": "9e6f2732d21871ec06e9541ea881baf962f7cdf4",
+ "testPagePath": "stub-4.1.7-service-worker-global-scope-onmessage.html",
+ "testable": true
+ },
+ {
+ "href": "#client",
+ "id": "client",
+ "hash": "47a1c10cd9e4db9a5c86d9bcf80477f771ea954c",
+ "secno": "4.2",
+ "testPageHash": "21d74c1af0b3176b029c9b62b37fe73436e0f197",
+ "testPagePath": "stub-4.2-client.html",
+ "testable": true
+ },
+ {
+ "href": "#service-worker-clients",
+ "id": "service-worker-clients",
+ "hash": "c2c6f4873f07b53705a46b2bd44ba10f84dd2b56",
+ "secno": "4.3",
+ "testPageHash": "9c0366e6cfd28caaeaf940bad2b3c7ace93037f6",
+ "testPagePath": "stub-4.3-service-worker-clients.html",
+ "testable": true
+ },
+ {
+ "href": "#get-serviced-method",
+ "id": "get-serviced-method",
+ "hash": "299abaa21cf096e423edfa19755987986f742a1f",
+ "secno": "4.3.1",
+ "testPageHash": "efeb1c2dc8144c30e6628cb56b3e532531ee1e88",
+ "testPagePath": "stub-4.3.1-get-serviced-method.html",
+ "testable": true
+ },
+ {
+ "href": "#reloadall-method",
+ "id": "reloadall-method",
+ "hash": "bb4d775d261e69cbeaf65c123e949c24cf542ae7",
+ "secno": "4.3.2",
+ "testPageHash": "d1a4dde873b77201b4de745d2083bf63549b0b8b",
+ "testPagePath": "stub-4.3.2-reloadall-method.html",
+ "testable": true
+ },
+ {
+ "href": "#request-objects",
+ "id": "request-objects",
+ "hash": "65ae6c08f720a2eedb7b140f5635a5ac46ddadfc",
+ "secno": "4.4",
+ "testPageHash": "ec493c70e8a0d8d3eeb0ecaef59610aed97d298e",
+ "testPagePath": "stub-4.4-request-objects.html",
+ "testable": true
+ },
+ {
+ "href": "#response-objects",
+ "id": "response-objects",
+ "hash": "2efbff63c70ab92f93e4acd021409b9df4776882",
+ "secno": "4.5",
+ "testPageHash": "8340b69d62f111f56095c5fe9047d9215fa7aefc",
+ "testPagePath": "stub-4.5-response-objects.html",
+ "testable": true
+ },
+ {
+ "href": "#abstract-response",
+ "id": "abstract-response",
+ "hash": "bddc306a9892c0bca43e8b361c1ee22b87759e23",
+ "secno": "4.5.1",
+ "testable": false
+ },
+ {
+ "href": "#response",
+ "id": "response",
+ "hash": "6471d25755bdab0d4f72413f9367b7bb36c53a6f",
+ "secno": "4.5.2",
+ "testPageHash": "346d63cc7eb8ee412f5f704ba241205c8d437540",
+ "testPagePath": "stub-4.5.2-response.html",
+ "testable": true
+ },
+ {
+ "href": "#header",
+ "id": "header",
+ "hash": "da39a3ee5e6b4b0d3255bfef95601890afd80709",
+ "secno": "4.5.3",
+ "testable": false
+ },
+ {
+ "href": "#opaque-response",
+ "id": "opaque-response",
+ "hash": "df5431f4fbd26d81f2d4f567309c6a7a26dbfd4a",
+ "secno": "4.5.4",
+ "testPageHash": "85373f290cf594f0f09eb0a76bc6ef6299be595f",
+ "testPagePath": "stub-4.5.4-opaque-response.html",
+ "testable": true
+ },
+ {
+ "href": "#cors-response",
+ "id": "cors-response",
+ "hash": "da39a3ee5e6b4b0d3255bfef95601890afd80709",
+ "secno": "4.5.5",
+ "testable": false
+ },
+ {
+ "href": "#cache-objects",
+ "id": "cache-objects",
+ "hash": "001d0dfb8fbcbcb6443d1be2b722c9a84d6fd95b",
+ "secno": "4.6",
+ "testPageHash": "c1ef341d15a8c76d015eef57842ed10e62c02927",
+ "testPagePath": "stub-4.6-cache-objects.html",
+ "testable": true
+ },
+ {
+ "href": "#cache-lifetimes",
+ "id": "cache-lifetimes",
+ "hash": "7c73698ca9b686a0314ddf368bf8ad4ca6af392f",
+ "secno": "4.6.1",
+ "testPageHash": "f3524320a98f2fbdc5d711de82770957a7f5ec4b",
+ "testPagePath": "stub-4.6.1-cache-lifetimes.html",
+ "testable": true
+ },
+ {
+ "href": "#cache",
+ "id": "cache",
+ "hash": "bf1fe844577ab57a60eb550be24335a3321ca2ee",
+ "secno": "4.6.2",
+ "testPageHash": "c55b7b05c8e2f4b65722e16cdbcd78ffdfe1e4bf",
+ "testPagePath": "stub-4.6.2-cache.html",
+ "testable": true
+ },
+ {
+ "href": "#cache-storage",
+ "id": "cache-storage",
+ "hash": "9cdaac070f56e55d66a89cd4b6e669a04aa73b82",
+ "secno": "4.6.3",
+ "testPageHash": "ee6902f170d94cc1e3a4a00f4c90e7e19c4dff95",
+ "testPagePath": "stub-4.6.3-cache-storage.html",
+ "testable": true
+ },
+ {
+ "href": "#events",
+ "id": "events",
+ "hash": "da39a3ee5e6b4b0d3255bfef95601890afd80709",
+ "secno": "4.7",
+ "testable": false
+ },
+ {
+ "href": "#install-phase-event",
+ "id": "install-phase-event",
+ "hash": "8495382b418adbbed436b2002ab0155a3a295ef2",
+ "secno": "4.7.1",
+ "testPageHash": "e48e98d51936bd57d21903615203f2b78d3f4b12",
+ "testPagePath": "stub-4.7.1-install-phase-event.html",
+ "testable": true
+ },
+ {
+ "href": "#wait-until-method",
+ "id": "wait-until-method",
+ "hash": "295fb5d4932396fd13365ed2fe57aa672f1f2a56",
+ "secno": "4.7.1.1",
+ "testPageHash": "c3769e51852b8438a97c39c50fa62351a73c4ee6",
+ "testPagePath": "stub-4.7.1.1-wait-until-method.html",
+ "testable": true
+ },
+ {
+ "href": "#install-event",
+ "id": "install-event",
+ "hash": "3a0f6da1771c22ab21ddc00729433a4d95ac6782",
+ "secno": "4.7.2",
+ "testPageHash": "9a103cc461eaca3da75db583ce08f13ecd2b1a98",
+ "testPagePath": "stub-4.7.2-install-event.html",
+ "testable": true
+ },
+ {
+ "href": "#install-event-section",
+ "id": "install-event-section",
+ "hash": "4631577df2efc1a4350000461629bc1ca93dbd14",
+ "secno": "4.7.2.1",
+ "testPageHash": "32f54e74bef784d2f0ac772b44abeee06573062d",
+ "testPagePath": "stub-4.7.2.1-install-event-section.html",
+ "testable": true
+ },
+ {
+ "href": "#replace-method",
+ "id": "replace-method",
+ "hash": "b9093b05204d09748311023b4c737ede02ff8115",
+ "secno": "4.7.2.2",
+ "testPageHash": "372bed923f8c35c4923634ae27fa121919ac0fec",
+ "testPagePath": "stub-4.7.2.2-replace-method.html",
+ "testable": true
+ },
+ {
+ "href": "#activate-event",
+ "id": "activate-event",
+ "hash": "ac3d03aa0ed961fb1122850aeab92c302c55ecd0",
+ "secno": "4.7.3",
+ "testPageHash": "6241762ab1d6f430fa9b7cc8f02a00e6591c6bc6",
+ "testPagePath": "stub-4.7.3-activate-event.html",
+ "testable": true
+ },
+ {
+ "href": "#fetch-event",
+ "id": "fetch-event",
+ "hash": "da39a3ee5e6b4b0d3255bfef95601890afd80709",
+ "secno": "4.7.4",
+ "testable": false
+ },
+ {
+ "href": "#fetch-event-section",
+ "id": "fetch-event-section",
+ "hash": "ae24fda9664a3bd7b7fe2a8712ac469c3ee7128e",
+ "secno": "4.7.4.1",
+ "testPageHash": "393fc7b65e9f5afd18da666b6b206ccd639397cd",
+ "testPagePath": "stub-4.7.4.1-fetch-event-section.html",
+ "testable": true
+ },
+ {
+ "href": "#respond-with-method",
+ "id": "respond-with-method",
+ "hash": "7e4f010e2ec1ea0500b435cf599ba58942164457",
+ "secno": "4.7.4.2",
+ "testPageHash": "31e0acd058b9a5b722ae9f405b50bc94d31596b8",
+ "testPagePath": "stub-4.7.4.2-respond-with-method.html",
+ "testable": true
+ },
+ {
+ "href": "#default-method",
+ "id": "default-method",
+ "hash": "4d6f8f93b2e10ab0e486dbf464ff107ec1a6aa4c",
+ "secno": "4.7.4.3",
+ "testPageHash": "34e015c973887e2b3bf8b6db62f75d5d417a43cc",
+ "testPagePath": "stub-4.7.4.3-default-method.html",
+ "testable": true
+ },
+ {
+ "href": "#is-reload-attribute",
+ "id": "is-reload-attribute",
+ "hash": "6e1afd9e8940e9cd38aa7de1ed57e8c5b1a60e3d",
+ "secno": "4.7.4.4",
+ "testPageHash": "703a6469782d37be3c25e2214f897d1064acca47",
+ "testPagePath": "stub-4.7.4.4-is-reload-attribute.html",
+ "testable": true
+ },
+ {
+ "href": "#security-considerations",
+ "id": "security-considerations",
+ "hash": "5b02b143172647dd7f74f0464dffa7ec7d0e8f94",
+ "secno": "5",
+ "testable": false
+ },
+ {
+ "href": "#origin-relativity",
+ "id": "origin-relativity",
+ "hash": "72bbbd7d3d43a859af6ff9f19353210ddfcc26de",
+ "secno": "5.1",
+ "testPageHash": "1c92607dfac57b0f59654d059a4a67e0f984b84d",
+ "testPagePath": "stub-5.1-origin-relativity.html",
+ "testable": true
+ },
+ {
+ "href": "#cross-origin-resources",
+ "id": "cross-origin-resources",
+ "hash": "6176879ecfb5ae769679ceef4ee1e8889be8df92",
+ "secno": "5.2",
+ "testPageHash": "bcf85ba278c70c086645c416cee729ce753bc528",
+ "testPagePath": "stub-5.2-cross-origin-resources.html",
+ "testable": true
+ },
+ {
+ "href": "#storage-considerations",
+ "id": "storage-considerations",
+ "hash": "e101cee2062749b1a73086492377458251a5e875",
+ "secno": "6",
+ "testable": false
+ },
+ {
+ "href": "#extensibility",
+ "id": "extensibility",
+ "hash": "ef1b382bb89c52e01edad421b02b237765a21ce7",
+ "secno": "7",
+ "testable": false
+ },
+ {
+ "href": "#algorithms",
+ "id": "algorithms",
+ "hash": "d130247eab1d368efea646ff369e65f6c0c19481",
+ "secno": "8",
+ "testable": false
+ },
+ {
+ "href": "#registration-algorithm",
+ "id": "registration-algorithm",
+ "hash": "b688d090671c08ca17ea7cadc561e6d471ee099e",
+ "secno": "8.1",
+ "testable": false
+ },
+ {
+ "href": "#update-algorithm",
+ "id": "update-algorithm",
+ "hash": "679a19fef428affc83103c1eec0dbd3be40c4e2a",
+ "secno": "8.2",
+ "testable": false
+ },
+ {
+ "href": "#soft-update-algorithm",
+ "id": "soft-update-algorithm",
+ "hash": "8eb103f5cd0e595ee5e25f075e8c6239211e482a",
+ "secno": "8.3",
+ "testable": false
+ },
+ {
+ "href": "#installation-algorithm",
+ "id": "installation-algorithm",
+ "hash": "5874d9247d979009b67aedf964ae097837cfb3d9",
+ "secno": "8.4",
+ "testable": false
+ },
+ {
+ "href": "#activation-algorithm",
+ "id": "activation-algorithm",
+ "hash": "648b34baf6e7c2096a842e6d367949117843108e",
+ "secno": "8.5",
+ "testable": false
+ },
+ {
+ "href": "#on-fetch-request-algorithm",
+ "id": "on-fetch-request-algorithm",
+ "hash": "e1da43671071ec307f99cd781fc9b46353f3adfd",
+ "secno": "8.6",
+ "testable": false
+ },
+ {
+ "href": "#on-document-unload-algorithm",
+ "id": "on-document-unload-algorithm",
+ "hash": "8a7196b5dd04ad4fb9b96e16a52f4f7ac1906763",
+ "secno": "8.7",
+ "testable": false
+ },
+ {
+ "href": "#unregistration-algorithm",
+ "id": "unregistration-algorithm",
+ "hash": "0114db166d42211d0d7ab4b8e77de64a9fc97517",
+ "secno": "8.8",
+ "testable": false
+ },
+ {
+ "href": "#update-state-algorithm",
+ "id": "update-state-algorithm",
+ "hash": "2ed8a1e7479f1a8ad038aa44ccdd5e4f6b65cf05",
+ "secno": "8.9",
+ "testable": false
+ },
+ {
+ "href": "#scope-match-algorithm",
+ "id": "scope-match-algorithm",
+ "hash": "a2117fb34a8fa4ca3e832d9276477cfc1318dd1a",
+ "secno": "8.10",
+ "testable": false
+ },
+ {
+ "href": "#get-registration-algorithm",
+ "id": "get-registration-algorithm",
+ "hash": "b20332db952ba8f4b7e5f65b740a18da4a199c2e",
+ "secno": "8.11",
+ "testable": false
+ },
+ {
+ "href": "#get-newest-worker-algorithm",
+ "id": "get-newest-worker-algorithm",
+ "hash": "72dc1cbee8c98501931c411018fd1cad4376142b",
+ "secno": "8.12",
+ "testable": false
+ },
+ {
+ "href": "#acknowledgements",
+ "id": "acknowledgements",
+ "hash": "6347067ca5a574f8cc80c76d95dee568042d059b",
+ "secno": "9",
+ "testable": false
+ }
+ ],
+ "specUrl": "https://slightlyoff.github.io/ServiceWorker/spec/service_worker/"
+} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/service-workers/stub-3.1-service-worker-obj.html b/tests/wpt/web-platform-tests/service-workers/stub-3.1-service-worker-obj.html
new file mode 100644
index 00000000000..588720e0754
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/stub-3.1-service-worker-obj.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: ServiceWorker</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#service-worker-obj">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ <script src=/resources/WebIDLParser.js></script>
+ <script src=/resources/idlharness.js></script>
+
+ </head>
+ <body>
+
+<script type=text/plain id="idl_0">
+[Constructor()] // no-op constructor
+interface ServiceWorker : Worker {
+ readonly attribute DOMString scope;
+ readonly attribute DOMString url;
+ readonly attribute ServiceWorkerState state;
+
+ // event
+ attribute EventHandler onstatechange;
+};
+
+enum ServiceWorkerState {
+ "installing",
+ "installed",
+ "activating",
+ "activated",
+ "redundant"
+};
+</pre>
+
+<!--
+The `ServiceWorker` interface represents the document-side view of a Service
+Worker. This object provides a no-op constructor. Callers should note that only
+`ServiceWorker` objects created by the user agent (see
+`navigator.serviceWorker.installing`, `navigator.serviceWorker.waiting`,
+`navigator.serviceWorker.active` and `navigator.serviceWorker.controller`) will
+provide meaningful functionality.
+-->
+
+
+ <script type=text/plain id="untested_idls">
+ interface EventHandler {};
+ interface Worker {};
+ </pre>
+
+ <script>
+ var idl_array = new IdlArray();
+ idl_array.add_untested_idls(document.getElementById("untested_idls").textContent);
+ idl_array.add_idls(document.getElementById("idl_0").textContent);
+ idl_array.add_objects({
+ ServiceWorker: ["throw new Error ('No object defined for the ServiceWorker interface')"],
+ ServiceWorkerState: ["throw new Error ('No object defined for the ServiceWorkerState enum')"]
+ });
+ idl_array.test();
+ </script>
+
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/service-workers/stub-3.1.1-service-worker-scope.html b/tests/wpt/web-platform-tests/service-workers/stub-3.1.1-service-worker-scope.html
new file mode 100644
index 00000000000..47b49353424
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/stub-3.1.1-service-worker-scope.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: scope</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#service-worker-scope">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+The `scope` of a `ServiceWorker` object reflects the [URL scope][1] of the
+associated Service Worker [registration][2]. The `scope` attribute must return
+the [serialization][3] of the URL representing the [URL scope][1] of the
+associated Service Worker [registration][2].
+
+For example, consider a document created by a navigation to
+`https://example.com/app.html` which [matches][4] via the following
+registration call which has been previously executed:
+// Script on the page https://example.com/app.html
+navigator.serviceWorker.register("/service_worker.js", { scope: "/*" });
+The value of `navigator.serviceWorker.controller.scope` will be
+`"https://example.com/*"`.
+
+
+
+[1]: #url-scope
+[2]: #registration
+[3]: http://url.spec.whatwg.org/#concept-url-serializer
+[4]: #on-fetch-request-algorithm
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section scope so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/service-workers/stub-3.1.2-service-worker-url.html b/tests/wpt/web-platform-tests/service-workers/stub-3.1.2-service-worker-url.html
new file mode 100644
index 00000000000..be17bb8d39d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/stub-3.1.2-service-worker-url.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: url</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#service-worker-url">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+The `url` attribute must return the [serialization][1] of the URL of the script
+of the Service Worker, identified by its [URL scope][2], that is associated
+with the [ServiceWorkerGlobalScope][3] object. The `url` attribute is always an
+[absolute URL][4] corresponding to the script file which the Service Worker
+evaluates.
+
+In the example in section 3.1.1, the value of
+`navigator.serviceWorker.controller.url` will be
+`"https://example.com/service_worker.js"`.
+
+
+
+[1]: http://url.spec.whatwg.org/#concept-url-serializer
+[2]: #url-scope
+[3]: #service-worker-global-scope-interface
+[4]: http://url.spec.whatwg.org/#concept-absolute-url
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section url so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/service-workers/stub-3.1.3-service-worker-state.html b/tests/wpt/web-platform-tests/service-workers/stub-3.1.3-service-worker-state.html
new file mode 100644
index 00000000000..40f4da40a25
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/stub-3.1.3-service-worker-state.html
@@ -0,0 +1,76 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: state</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#service-worker-state">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+The [ServiceWorker][1] object can be in several states. The `state` attribute
+must return the current state, which must be one of the following values
+defined in the [ServiceWorkerState][2] enumeration:
+
+`"installing"`:
+ The Service Worker represented by the [ServiceWorker][1] object has entered
+ and is running the steps in the [installation process][3]. During this
+ state, `e.waitUntil(p)` can be called inside the `oninstall` event handler
+ of the associcated [ServiceWorkerGloberScope][4] object to extend the life
+ of the [installing worker][5] until the passed [Promise][6] resolves
+ successfully. This is primarily used to ensure that the Service Worker is
+ not active until all of the core caches are populated.
+`"installed"`:
+ The Service Worker represented by the [ServiceWorker][1] object has
+ completed the steps in the [installation process][3]. The Service Worker in
+ this state is considered the [worker in waiting][7].
+`"activating"`:
+ The Service Worker represented by the [ServiceWorker][1] object has entered
+ and is running the steps in the [activation process][8]. During this state,
+ `e.waitUntil(p)` can be called inside the `onactivate` event handler of the
+ associated [ServiceWorkerGloberScope][9] object to extend the life of the
+ activating [active worker][10] until the passed [Promise][6] resolves
+ successfully. Note that no [functional events][11] are dispatched until the
+ state becomes `"activated"`.
+`"activated"`:
+ The Service Worker represented by the [ServiceWorker][1] object has
+ completed the steps in the [activation process][8]. The Service Worker in
+ this state is considered the [active worker][10] ready to [control][12] the
+ documents in matching scope upon subsequence [navigation][13].
+`"redundant"`:
+ A newly created Service Worker [registration][14] is replacing the current
+ [registration][14] of the Service Worker.
+
+
+
+[1]: #service-worker-interface
+[2]: #service-worker-state-enum
+[3]: #installation-process
+[4]: #service-worker-glober-scope-interface
+[5]: #installing-worker
+[6]: http://goo.gl/3TobQS
+[7]: #worker-in-waiting
+[8]: #activation-process
+[9]: #service-worker-global-scope-interface
+[10]: #active-worker
+[11]: #functional-events
+[12]: #document-control
+[13]: http://www.whatwg.org/specs/web-apps/current-work/multipage/history.html#navigate
+[14]: #registration
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section state so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/service-workers/stub-3.1.4-service-worker-on-state-change.html b/tests/wpt/web-platform-tests/service-workers/stub-3.1.4-service-worker-on-state-change.html
new file mode 100644
index 00000000000..36138742016
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/stub-3.1.4-service-worker-on-state-change.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: onstatechange</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#service-worker-on-state-change">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+`onstatechange` is the [event handler][1] that must be supported as attribute
+by the `[ServiceWorker][2]` object. A `statechange` event using the
+`[Event][3]` interface is dispatched on `[ServiceWorker][2]` object when the
+`state` attribute of the `ServiceWorker` object is changed.
+
+[1]: http://goo.gl/rBfiz0
+[2]: #service-worker-interface
+[3]: http://goo.gl/Mzv7Dv
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section onstatechange so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/service-workers/stub-3.2-navigator-service-worker.html b/tests/wpt/web-platform-tests/service-workers/stub-3.2-navigator-service-worker.html
new file mode 100644
index 00000000000..0855d6cc05b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/stub-3.2-navigator-service-worker.html
@@ -0,0 +1,84 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: navigator.serviceWorker</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#navigator-service-worker">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ <script src=/resources/WebIDLParser.js></script>
+ <script src=/resources/idlharness.js></script>
+
+ </head>
+ <body>
+
+<!--
+The `serviceWorker` attribute of the [Navigator][1] interface must return an
+instance of the `ServiceWorkerContainer` interface, which provides access to
+registration, removal, upgrade, and communication with Service Workers that are
+(or will become) active for the current document. Communication with these
+workers is provided via standard [HTML5 messaging APIs][2], and [messaging
+occurs as per usual with Web Workers][3].
+-->
+<script type=text/plain id="idl_0">
+partial interface Navigator {
+ readonly attribute ServiceWorkerContainer serviceWorker;
+};
+
+interface ServiceWorkerContainer : EventTarget {
+ [Unforgeable] readonly attribute ServiceWorker? installing;
+ [Unforgeable] readonly attribute ServiceWorker? waiting;
+ [Unforgeable] readonly attribute ServiceWorker? active;
+ [Unforgeable] readonly attribute ServiceWorker? controller;
+ readonly attribute Promise<ServiceWorker> ready;
+
+ Promise<sequence<ServiceWorker>?> getAll();
+ Promise<ServiceWorker> register(DOMString url, optional RegistrationOptionList options);
+ Promise<any> unregister(DOMString? scope);
+
+ // events
+ attribute EventHandler onupdatefound;
+ attribute EventHandler oncontrollerchange;
+ attribute EventHandler onreloadpage;
+ attribute EventHandler onerror;
+};
+
+dictionary RegistrationOptionList {
+ DOMString scope = "/*";
+};
+
+interface ReloadPageEvent : Event {
+ void waitUntil(Promise<any> f);
+};
+</script>
+
+<!--
+[1]: http://goo.gl/I7WAhg
+[2]: http://www.whatwg.org/specs/web-apps/current-work/multipage/web-messaging.html
+[3]: http://www.w3.org/TR/workers/#dom-worker-postmessage
+-->
+
+
+ <script type=text/plain id="untested_idls">
+ interface ServiceWorker {};
+ interface EventHandler {};
+ interface EventTarget {};
+ interface Event {};
+ </pre>
+
+ <script>
+ var idl_array = new IdlArray();
+ idl_array.add_untested_idls(document.getElementById("untested_idls").textContent);
+ idl_array.add_idls(document.getElementById("idl_0").textContent);
+ idl_array.add_objects({
+ Navigator: ["throw new Error ('No object defined for the Navigator interface')"],
+ ServiceWorkerContainer: ["throw new Error ('No object defined for the ServiceWorkerContainer interface')"],
+ RegistrationOptionList: ["throw new Error ('No object defined for the RegistrationOptionList dictionary')"],
+ ReloadPageEvent: ["throw new Error ('No object defined for the ReloadPageEvent interface')"]
+ });
+ idl_array.test();
+ </script>
+
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/service-workers/stub-3.2.1-navigator-service-worker-installing.html b/tests/wpt/web-platform-tests/service-workers/stub-3.2.1-navigator-service-worker-installing.html
new file mode 100644
index 00000000000..d73a35b1f6c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/stub-3.2.1-navigator-service-worker-installing.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: installing</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#navigator-service-worker-installing">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+`navigator.serviceWorker.installing` must return a [ServiceWorker][1] object
+representing the [installing worker][2] that is currently undergoing the
+installation process (from step 1 to step 7 of the [_Installation
+algorithm][3]) for the given [URL scope][4] in which the document may be
+[controlled][5] when the Service Worker becomes the [active worker][6].
+`navigator.serviceWorker.installing` returns `null` if no Service Worker
+[registration][7] is in the [installation process][8].
+
+[1]: #service-worker-interface
+[2]: #installing-worker
+[3]: #installation-algorithm
+[4]: #url-scope
+[5]: #document-control
+[6]: #active-worker
+[7]: #service-worker-registration-internal-interface
+[8]: #installation-process
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section installing so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/service-workers/stub-3.2.10-navigator-service-worker-oncontrollerchange.html b/tests/wpt/web-platform-tests/service-workers/stub-3.2.10-navigator-service-worker-oncontrollerchange.html
new file mode 100644
index 00000000000..1e23e8247a8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/stub-3.2.10-navigator-service-worker-oncontrollerchange.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: oncontrollerchange</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#navigator-service-worker-oncontrollerchange">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+`navigator.serviceWorker.oncontrollerchange` is the [event handler][1] that
+must be supported as attribute by the `[ServiceWorkerContainer][2]` object. A
+`controllerchange` event using the `[Event][3]` interface is dispatched on
+`[ServiceWorkerContainer][2]` object (See step 7 of the [_Activation
+algorithm][4]) when the associated Service Worker [registration][5] for the
+document enters the [activation process][6]. When the [activation process][6]
+is triggered by `replace()` method call within the event handler of the
+`install` event, `navigator.serviceWorker.controller` immediately reflects the
+[active worker][7] as the Service Worker that [controls][8] the document.
+
+[1]: http://goo.gl/rBfiz0
+[2]: #service-worker-container-interface
+[3]: http://goo.gl/Mzv7Dv
+[4]: #activation-algorithm
+[5]: #registration
+[6]: #activation-process
+[7]: #active-worker
+[8]: #document-control
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section oncontrollerchange so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/service-workers/stub-3.2.11-navigator-service-worker-onreloadpage.html b/tests/wpt/web-platform-tests/service-workers/stub-3.2.11-navigator-service-worker-onreloadpage.html
new file mode 100644
index 00000000000..ef3fd10fb9e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/stub-3.2.11-navigator-service-worker-onreloadpage.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: onreloadpage</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#navigator-service-worker-onreloadpage">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+`navigator.serviceWorker.onreloadpage` is the [event handler][1] that must be
+supported as attribute by the `[ServiceWorkerContainer][2]` object. An event
+named `reloadpage` using the `[ReloadPageEvent][3]` interface is dispatched on
+`[ServiceWorkerContainer][2]` object when the page reload is triggered by the
+`[self.clients.reloadAll()][4]` method call from the [active worker][5],
+represented by its associated [ServiceWorkerGlobalScope][6] object, for the
+document.
+
+[1]: http://goo.gl/rBfiz0
+[2]: #service-worker-container-interface
+[3]: #reload-page-event-interface
+[4]: #reloadall-method
+[5]: #active-worker
+[6]: #service-worker-global-scope-interface
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section onreloadpage so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/service-workers/stub-3.2.12-navigator-service-worker-onerror.html b/tests/wpt/web-platform-tests/service-workers/stub-3.2.12-navigator-service-worker-onerror.html
new file mode 100644
index 00000000000..e2542569866
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/stub-3.2.12-navigator-service-worker-onerror.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: onerror</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#navigator-service-worker-onerror">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+`navigator.serviceWorker.onerror` is the [event handler][1] that must be
+supported as attribute by the `[ServiceWorkerContainer][2]` object. An event
+named `error` using the `[ErrorEvent][3]` interface is dispatched on
+`[ServiceWorkerContainer][2]` object for any error from the associated
+`[ServiceWorker][4]` objects.
+
+[1]: http://goo.gl/rBfiz0
+[2]: #service-worker-container-interface
+[3]: http://goo.gl/FKuWgu
+[4]: #service-worker-interface
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section onerror so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/service-workers/stub-3.2.2-navigator-service-worker-waiting.html b/tests/wpt/web-platform-tests/service-workers/stub-3.2.2-navigator-service-worker-waiting.html
new file mode 100644
index 00000000000..2852d97fb68
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/stub-3.2.2-navigator-service-worker-waiting.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: waiting</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#navigator-service-worker-waiting">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+`navigator.serviceWorker.waiting` must return a [ServiceWorker][1] object
+representing the waiting Service Worker that is considered the [worker in
+waiting][2] for the document. `navigator.serviceWorker.waiting` returns `null`
+if there is no [worker in waiting][2] for the document.
+
+[1]: #service-worker-interface
+[2]: #worker-in-waiting
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section waiting so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/service-workers/stub-3.2.3-navigator-service-worker-active.html b/tests/wpt/web-platform-tests/service-workers/stub-3.2.3-navigator-service-worker-active.html
new file mode 100644
index 00000000000..3ac45d1b42e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/stub-3.2.3-navigator-service-worker-active.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: active</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#navigator-service-worker-active">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+`navigator.serviceWorker.active` must return a [ServiceWorker][1] object
+representing the [active worker][2] that is currently undergoing or completed
+the activation process (from step 4 to step 9 of the [_Activation
+algorithm][3]) for the given [URL scope][4] in which the document is controlled
+(or to be controlled). `navigator.serviceWorker.active` returns `null` if no
+Service Worker [registration][5] is in the [activation process][6].
+
+[1]: #service-worker-interface
+[2]: #active-worker
+[3]: #activation-algorithm
+[4]: #url-scope
+[5]: #service-worker-registration-internal-interface
+[6]: #activation-process
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section active so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/service-workers/stub-3.2.4-navigator-service-worker-controller.html b/tests/wpt/web-platform-tests/service-workers/stub-3.2.4-navigator-service-worker-controller.html
new file mode 100644
index 00000000000..90378dd619e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/stub-3.2.4-navigator-service-worker-controller.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: controller</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#navigator-service-worker-controller">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+`navigator.serviceWorker.controller` must return a [ServiceWorker][1] object
+representing the [active worker][2] that currently handles resource requests
+for the document. `navigator.serviceWorker.controller` returns `null` if the
+current document was not [created under a Service Worker][3] (See step 6-1 of
+[_OnFetchRequest][3] algorithm) or the request is a force refresh
+(shift+refresh).
+
+[1]: #service-worker-interface
+[2]: #active-worker
+[3]: #on-fetch-request-algorithm
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section controller so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/service-workers/stub-3.2.5-navigator-service-worker-ready.html b/tests/wpt/web-platform-tests/service-workers/stub-3.2.5-navigator-service-worker-ready.html
new file mode 100644
index 00000000000..f3b1ca78f35
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/stub-3.2.5-navigator-service-worker-ready.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: ready</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#navigator-service-worker-ready">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+`navigator.serviceWorker.ready` attribute must return the result of running
+these steps:
+
+1. Let `promise` be a newly-created [promise][1].
+2. Return `promise`.
+3. Run the following steps asynchronously:
+ 1. Let `registration` be the result of running [_ScopeMatch
+ algorithm][2] with document's url as its argument.
+ 2. If `registration` is null, then:
+ 1. Wait for the document to have a matching [registration][3].
+ 3. If the [registration][3], represented by `registration`, for the
+ document has an [active worker][4], then:
+ 1. Resolve `promise` with the [ServiceWorker][5] object associated
+ with the [active worker][4].
+ 2. Abort these steps.
+ 4. If the [registration][3], represented by `registration`, for the
+ document has a [worker in waiting][6], then:
+ 1. Resolve `promise` with the [ServiceWorker][5] object associated
+ with the [worker in waiting][6].
+ 2. Abort these steps.
+ 5. Wait until the [registration][3], represented by `registration`,
+ for the document acquires a [worker in waiting][6] through a new
+ [installation process][7].
+ 6. Resolve `promise` with the [ServiceWorker][5] object associated
+ with the [worker in waiting][6].
+Note that `ready` attribute is desinged in a way that the returned [promise][1]
+will never reject. Instead, it waits until the [promise][1] resolves with a
+newly installed [worker in waiting][6]. Hence, the `state` of the acquired
+[`ServiceWorker`][8] object is either `installed`, `activating` or `activated`.
+
+
+
+[1]: http://goo.gl/3TobQS
+[2]: #scope-match-algorithm
+[3]: #registration
+[4]: #active-worker
+[5]: #service-worker-interface
+[6]: #worker-in-waiting
+[7]: #installation-process
+[8]: #service-worker
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section ready so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/service-workers/stub-3.2.6-navigator-service-worker-getAll.html b/tests/wpt/web-platform-tests/service-workers/stub-3.2.6-navigator-service-worker-getAll.html
new file mode 100644
index 00000000000..18180b9b74a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/stub-3.2.6-navigator-service-worker-getAll.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: getAll()</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#navigator-service-worker-getAll">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+`navigator.serviceWorker.getAll()` method must return a promise that resolves
+with the array of the ServiceWorker objects in `installing`, `installed`,
+`activating` and `activated` states.
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section getAll() so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/service-workers/stub-3.2.7-navigator-service-worker-register.html b/tests/wpt/web-platform-tests/service-workers/stub-3.2.7-navigator-service-worker-register.html
new file mode 100644
index 00000000000..c9253dd7129
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/stub-3.2.7-navigator-service-worker-register.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: register()</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#navigator-service-worker-register">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+`navigator.serviceWorker.register(url, options)` method must run the
+[Registration algorithm][1] passing `url` and `options`.`scope` as the
+arguments.
+
+[1]: #registration-algorithm
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section register() so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/service-workers/stub-3.2.8-navigator-service-worker-unregister.html b/tests/wpt/web-platform-tests/service-workers/stub-3.2.8-navigator-service-worker-unregister.html
new file mode 100644
index 00000000000..c4c0c247e5e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/stub-3.2.8-navigator-service-worker-unregister.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: unregister()</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#navigator-service-worker-unregister">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+`navigator.serviceWorker.unregister(scope)` method must run the [Unregistration
+algorithm][1] passing `scope` as the argument.
+
+[1]: #unregistration-algorithm
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section unregister() so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/service-workers/stub-3.2.9-navigator-service-worker-onupdatefound.html b/tests/wpt/web-platform-tests/service-workers/stub-3.2.9-navigator-service-worker-onupdatefound.html
new file mode 100644
index 00000000000..4502b2e19b9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/stub-3.2.9-navigator-service-worker-onupdatefound.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: onupdatefound</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#navigator-service-worker-onupdatefound">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+`navigator.serviceWorker.onupdatefound` is the [event handler][1] that must be
+supported as attribute by the `[ServiceWorkerContainer][2]` object. An
+`updatefound` event using the `[Event][3]` interface is dispatched on
+`[ServiceWorkerContainer][2]` object (See step 4 of the [_Installation
+algorithm][4]) when the associated Service Worker [registration][5] for the
+document enters the [installation process][6] such that
+`navigator.serviceWorker.installing` becomes the new [installing worker][7].
+
+[1]: http://goo.gl/rBfiz0
+[2]: #service-worker-container-interface
+[3]: http://goo.gl/Mzv7Dv
+[4]: #installation-algorithm
+[5]: #registration
+[6]: #installation-process
+[7]: #installing-worker
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section onupdatefound so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/service-workers/stub-4.1-service-worker-global-scope.html b/tests/wpt/web-platform-tests/service-workers/stub-4.1-service-worker-global-scope.html
new file mode 100644
index 00000000000..ce6a045e25e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/stub-4.1-service-worker-global-scope.html
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: ServiceWorkerGlobalScope</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#service-worker-global-scope">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ <script src=/resources/WebIDLParser.js></script>
+ <script src=/resources/idlharness.js></script>
+
+ </head>
+ <body>
+
+<script type=text/plain id="idl_0">
+[Global]
+interface ServiceWorkerGlobalScope : WorkerGlobalScope {
+ readonly attribute CacheStorage caches;
+ // A container for a list of window objects, identifiable by ID, that
+ // correspond to windows (or workers) that are "controlled" by this SW
+ readonly attribute ServiceWorkerClients clients;
+ [Unforgeable] readonly attribute DOMString scope;
+
+ Promise<any> fetch((Request or ScalarValueString) request);
+
+ void update();
+ void unregister();
+
+ attribute EventHandler oninstall;
+ attribute EventHandler onactivate;
+ attribute EventHandler onfetch;
+ attribute EventHandler onbeforeevicted;
+ attribute EventHandler onevicted;
+
+ // The event.source of these MessageEvents are instances of Client
+ attribute EventHandler onmessage;
+
+ // close() method inherited from WorkerGlobalScope is not exposed.
+};
+</pre>
+
+<!--
+The `ServiceWorkerGlobalScope` interface represents the global execution
+context of a Service Worker. `ServiceWorkerGlobalScope` object provides
+generic, event-driven, time-limited script execution contexts that run at an
+origin. Once successfully [registered][1], a Service Worker is started, kept
+alive and killed by their relationship to events, not documents. Any type of
+synchronous requests MUST NOT be initiated inside of a Service Worker.
+
+[1]: #navigator-service-worker-register
+-->
+
+
+ <script type=text/plain id="untested_idls">
+ interface CacheStorage {};
+ interface ServiceWorkerClients {};
+ interface Request {};
+ interface ScalarValueString {};
+ interface EventHandler {};
+ interface WorkerGlobalScope {};
+ </pre>
+
+ <script>
+ var idl_array = new IdlArray();
+ idl_array.add_untested_idls(document.getElementById("untested_idls").textContent);
+ idl_array.add_idls(document.getElementById("idl_0").textContent);
+ idl_array.add_objects({
+ ServiceWorkerGlobalScope: ["throw new Error ('No object defined for the ServiceWorkerGlobalScope interface')"]
+ });
+ idl_array.test();
+ </script>
+
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/service-workers/stub-4.1.1-service-worker-global-scope-caches.html b/tests/wpt/web-platform-tests/service-workers/stub-4.1.1-service-worker-global-scope-caches.html
new file mode 100644
index 00000000000..4e68cc27980
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/stub-4.1.1-service-worker-global-scope-caches.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: caches</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#service-worker-global-scope-caches">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+`self.caches` must return the `[CacheStorage][1]` object that is the global
+asynchronous map object for the `[ServiceWorkerGlobalScope][2]` execution
+context containing the cache objects keyed by the name of the caches. Caches
+are always enumerable via `self.caches` in insertion order (per [ECMAScript 6
+Map objects][3].)
+
+[1]: #cache-storage-interface
+[2]: #service-worker-global-scope-interface
+[3]: http://goo.gl/gNnDPO
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section caches so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/service-workers/stub-4.1.2-service-worker-global-scope-clients.html b/tests/wpt/web-platform-tests/service-workers/stub-4.1.2-service-worker-global-scope-clients.html
new file mode 100644
index 00000000000..8499c717b84
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/stub-4.1.2-service-worker-global-scope-clients.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: clients</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#service-worker-global-scope-clients">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+`self.clients` must return the `[ServiceWorkerClients][1]` object containing a
+list of client objects, identifiable by ID, that correspond to windows or
+workers that are [controlled][2] by this Service Worker.
+
+[1]: #service-worker-clients-interface
+[2]: #document-control
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section clients so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/service-workers/stub-4.1.3-service-worker-global-scope-scope.html b/tests/wpt/web-platform-tests/service-workers/stub-4.1.3-service-worker-global-scope-scope.html
new file mode 100644
index 00000000000..3784e1eeb41
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/stub-4.1.3-service-worker-global-scope-scope.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: scope</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#service-worker-global-scope-scope">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+The `scope` attribute of a [ServiceWorkerGlobalScope][1] object reflects the
+[URL scope][2] of the associated Service Worker [registration][3]. The `scope`
+attribute must return the [serialization][4] of the URL representing the [URL
+scope][2] of the associated Service Worker [registration][3].
+
+[1]: #service-worker-global-scope-interface
+[2]: #url-scope
+[3]: #registration
+[4]: http://url.spec.whatwg.org/#concept-url-serializer
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section scope so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/service-workers/stub-4.1.4-service-worker-global-scope-fetch.html b/tests/wpt/web-platform-tests/service-workers/stub-4.1.4-service-worker-global-scope-fetch.html
new file mode 100644
index 00000000000..29548a760ba
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/stub-4.1.4-service-worker-global-scope-fetch.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: fetch(request)</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#service-worker-global-scope-fetch">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+`self.fetch(request)` method must run these steps:
+
+1. Let `request` be a [request][1] represented by `request`.
+2. Set [`client`][2] of `request` to the [JavaScript global
+ environment][3] represented by `self` object.
+3. Let `promise` be a newly-created [promise][4].
+4. Return `promise.`
+5. Run the following steps asynchronously:
+ 1. Let `response` be the result of running [fetch algorithm][5] with
+ `request` as its argument.
+ 2. If `response` is a [network error][6], then:
+ 1. Reject `promise` with a new [DOMException][7] whose name is
+ "[NetworkError][8]".
+ 3. Else,
+ 1. Resolve `promise` with a new [Response][9] object associated
+ with `response`.
+
+
+
+[1]: http://goo.gl/ucOuXl
+[2]: http://goo.gl/Oxj4xQ
+[3]: http://goo.gl/ifwwCC
+[4]: http://goo.gl/3TobQS
+[5]: http://goo.gl/fGMifs
+[6]: http://goo.gl/jprjjc
+[7]: http://goo.gl/A0U8qC
+[8]: http://goo.gl/lud5HB
+[9]: http://goo.gl/Deazjv
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section fetch(request) so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/service-workers/stub-4.1.5-service-worker-global-scope-update.html b/tests/wpt/web-platform-tests/service-workers/stub-4.1.5-service-worker-global-scope-update.html
new file mode 100644
index 00000000000..ee9552b4d72
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/stub-4.1.5-service-worker-global-scope-update.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: update()</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#service-worker-global-scope-update">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+`update()` pings the server for an updated version of this script without
+consulting caches. `self.update()` method must run the [_SoftUpdate
+algorithm][1] passing its serviceWorkerRegistration object as the argument
+which is the result of running the [_GetRegistration algorithm][2] with
+`self.scope` as the argument. (This is conceptually the same operation that UA
+does maximum once per every 24 hours.)
+
+[1]: #soft-update-algorithm
+[2]: #get-registration-algorithm
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section update() so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/service-workers/stub-4.1.6-service-worker-global-scope-unregister.html b/tests/wpt/web-platform-tests/service-workers/stub-4.1.6-service-worker-global-scope-unregister.html
new file mode 100644
index 00000000000..9f76ee34a2f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/stub-4.1.6-service-worker-global-scope-unregister.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: unregister()</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#service-worker-global-scope-unregister">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+`self.unregister()` method must run the [Unregistration algorithm][1]
+implicitly passing `self.scope` as the argument.
+
+[1]: #unregistration-algorithm
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section unregister() so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/service-workers/stub-4.1.7-service-worker-global-scope-onmessage.html b/tests/wpt/web-platform-tests/service-workers/stub-4.1.7-service-worker-global-scope-onmessage.html
new file mode 100644
index 00000000000..d536a2c0ae9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/stub-4.1.7-service-worker-global-scope-onmessage.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: onmessage</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#service-worker-global-scope-onmessage">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+`self.onmessage` is the [event handler][1] that must be supported as attribute
+by the `ServiceWorkerGlobalScope` object. `ServiceWorkerGlobalScope` objects
+act as if they had an implicit `[MessagePort][2]` associated with them. This
+port is part of a channel that is set up when the worker is created, but it is
+not exposed. This object must never be garbage collected before the
+`ServiceWorkerGlobalScope` object.
+
+All messages received by that port must immediately be retargeted at the
+`ServiceWorkerGlobalScope` object. That is, an event named `message` using the
+`[MessageEvent][3]` interface is dispatched on ServiceWorkerGlobalScope object.
+The `event.source` of these `[MessageEvent][3]`s are instances of `[Client][4]`.
+
+
+
+[1]: http://goo.gl/rBfiz0
+[2]: http://goo.gl/tHBrI6
+[3]: http://goo.gl/S5e0b6
+[4]: #client-interface
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section onmessage so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/service-workers/stub-4.2-client.html b/tests/wpt/web-platform-tests/service-workers/stub-4.2-client.html
new file mode 100644
index 00000000000..96976c1ee1d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/stub-4.2-client.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: Client</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#client">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ <script src=/resources/WebIDLParser.js></script>
+ <script src=/resources/idlharness.js></script>
+
+ </head>
+ <body>
+
+<script type=text/plain id="idl_0">
+[Constructor()] // no-op constructor
+interface Client {
+ readonly attribute unsigned long id;
+ void postMessage(any message, DOMString targetOrigin,
+ optional sequence<Transferable> transfer);
+};
+</pre>
+
+<!--
+The `Client` interface represents the window or the worker (defined as client)
+that is [controlled][1] by the Service Worker. This object provides a no-op
+constructor. Callers should note that only `Client` objects created by the user
+agent (see [`this.clients.getServiced()`][2]) will provide meaningful
+functionality.
+
+The `id` of a `Client` identifies the specific client object from the list of
+client objects serviced by the Service Worker. The `postMessage(message,
+targetOrigin, transfer)` method of a `[Client][3]`, when called, causes a
+`[MessageEvent][4]` to be dispatched at the client object.
+
+
+
+[1]: #document-control
+[2]: #get-serviced-method
+[3]: #client-interface
+[4]: http://goo.gl/4SLWiH
+-->
+
+
+ <script type=text/plain id="untested_idls">
+ interface Transferable {};
+ </pre>
+
+ <script>
+ var idl_array = new IdlArray();
+ idl_array.add_untested_idls(document.getElementById("untested_idls").textContent);
+ idl_array.add_idls(document.getElementById("idl_0").textContent);
+ idl_array.add_objects({
+ Client: ["throw new Error ('No object defined for the Client interface')"]
+ });
+ idl_array.test();
+ </script>
+
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/service-workers/stub-4.3-service-worker-clients.html b/tests/wpt/web-platform-tests/service-workers/stub-4.3-service-worker-clients.html
new file mode 100644
index 00000000000..beb5d59b7dd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/stub-4.3-service-worker-clients.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: ServiceWorkerClients</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#service-worker-clients">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ <script src=/resources/WebIDLParser.js></script>
+ <script src=/resources/idlharness.js></script>
+
+ </head>
+ <body>
+
+<script type=text/plain id="idl_0">
+interface ServiceWorkerClients {
+ // A list of client objects, identifiable by ID, that correspond to windows
+ // (or workers) that are "controlled" by this SW
+ Promise<sequence<Client>?> getServiced();
+ Promise<any> reloadAll();
+};
+</pre>
+
+<!--
+The `ServiceWorkerClients` interface represents a container for a list of
+`[Client][1]` objects.
+
+[1]: #client-interface
+-->
+
+
+ <script type=text/plain id="untested_idls">
+ interface Client {};
+ </pre>
+
+ <script>
+ var idl_array = new IdlArray();
+ idl_array.add_untested_idls(document.getElementById("untested_idls").textContent);
+ idl_array.add_idls(document.getElementById("idl_0").textContent);
+ idl_array.add_objects({
+ ServiceWorkerClients: ["throw new Error ('No object defined for the ServiceWorkerClients interface')"]
+ });
+ idl_array.test();
+ </script>
+
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/service-workers/stub-4.3.1-get-serviced-method.html b/tests/wpt/web-platform-tests/service-workers/stub-4.3.1-get-serviced-method.html
new file mode 100644
index 00000000000..8543bd44621
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/stub-4.3.1-get-serviced-method.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: getServiced()</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#get-serviced-method">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+The `getServiced()` method of a `ServiceWorkerClients`, when called, returns a
+[Promise][1] that will resolve with a list of `[Client][2]` objects that are
+[controlled][3] by this Service Worker.
+
+[1]: http://goo.gl/3TobQS
+[2]: #client-interface
+[3]: #document-control
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section getServiced() so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/service-workers/stub-4.3.2-reloadall-method.html b/tests/wpt/web-platform-tests/service-workers/stub-4.3.2-reloadall-method.html
new file mode 100644
index 00000000000..dd79a9168dc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/stub-4.3.2-reloadall-method.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: reloadAll()</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#reloadall-method">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+`reloadAll()` provides a mechanism for the worker to request synchronized
+re-fetch of all documents whose URLs match the registration's [URL scope][1].
+An event named `reloadpage` is dispatched on the `navigator.serviceWorker`
+object of each document. The in-document handlers may allow the event to
+continue, request an extension (via [`e.waitUntil()`][2]), or cancel the
+collective reload by calling [`e.preventDefault()`][3].
+
+[1]: #url-scope
+[2]: #wait-until-method
+[3]: http://goo.gl/2zH6ie
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section reloadAll() so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/service-workers/stub-4.4-request-objects.html b/tests/wpt/web-platform-tests/service-workers/stub-4.4-request-objects.html
new file mode 100644
index 00000000000..aa3502bfd0b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/stub-4.4-request-objects.html
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: Request Objects</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#request-objects">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ <script src=/resources/WebIDLParser.js></script>
+ <script src=/resources/idlharness.js></script>
+
+ </head>
+ <body>
+
+<script type=text/plain id="idl_0">
+[Constructor(optional RequestInit init)]
+interface Request {
+ attribute unsigned long timeout;
+ attribute DOMString url;
+ attribute ByteString method;
+ readonly attribute DOMString origin;
+ readonly attribute Mode mode;
+ attribute boolean synchronous;
+ attribute boolean forcePreflight;
+ attribute boolean omitCredentials;
+ readonly attribute DOMString referrer;
+ readonly attribute HeaderMap headers; // alternative: sequence<Header> headers;
+ attribute any body;
+};
+
+dictionary RequestInit {
+ unsigned long timeout = 0;
+ DOMString url;
+ boolean synchronous = false;
+ boolean forcePreflight = false;
+ boolean omitCredentials = false;
+ ByteString method = "GET";
+ HeaderMap headers;
+ any body;
+};
+
+enum Mode {
+ "same origin",
+ "tainted cross-origin",
+ "CORS",
+ "CORS-with-forced-preflight"
+};
+
+[MapClass(DOMString, DOMString)]
+interface HeaderMap {
+};
+</pre>
+
+
+
+
+ <script>
+ var idl_array = new IdlArray();
+ idl_array.add_untested_idls(document.getElementById("untested_idls").textContent);
+ idl_array.add_idls(document.getElementById("idl_0").textContent);
+ idl_array.add_objects({
+ Request: ["throw new Error ('No object defined for the Request interface')"],
+ RequestInit: ["throw new Error ('No object defined for the RequestInit dictionary')"],
+ Mode: ["throw new Error ('No object defined for the Mode enum')"],
+ HeaderMap: ["throw new Error ('No object defined for the HeaderMap interface')"]
+ });
+ idl_array.test();
+ </script>
+
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/service-workers/stub-4.5-response-objects.html b/tests/wpt/web-platform-tests/service-workers/stub-4.5-response-objects.html
new file mode 100644
index 00000000000..a3345864c25
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/stub-4.5-response-objects.html
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: Response Objects</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#response-objects">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ <script src=/resources/WebIDLParser.js></script>
+ <script src=/resources/idlharness.js></script>
+
+ </head>
+ <body>
+
+<!--
+`Response` objects model HTTP responses.
+-->
+<script type=text/plain id="idl_0">
+[Constructor]
+interface AbstractResponse {
+};
+
+interface OpaqueResponse : AbstractResponse {
+ readonly attribute unsigned short status;
+ readonly attribute ByteString statusText;
+ // Returns a filtered list of headers. See prose for details.
+ readonly attribute HeaderMap headers;
+ // No setter for headers
+ readonly attribute DOMString url;
+};
+
+interface CORSResponse : Response {
+ readonly attribute HeaderMap headers;
+};
+
+[Constructor(optional ResponseInit responseInitDict)]
+interface Response : AbstractResponse {
+ attribute unsigned short status;
+ attribute ByteString statusText;
+ readonly attribute HeaderMap headers;
+ attribute DOMString url;
+ Promise<Blob> toBlob();
+};
+
+dictionary ResponseInit {
+ unsigned short status = 200;
+ ByteString statusText = "OK";
+ HeaderMap headers;
+};
+</pre>
+
+
+
+ <script type=text/plain id="untested_idls">
+ interface HeaderMap {};
+ interface Blob {};
+ </pre>
+
+ <script>
+ var idl_array = new IdlArray();
+ idl_array.add_untested_idls(document.getElementById("untested_idls").textContent);
+ idl_array.add_idls(document.getElementById("idl_0").textContent);
+ idl_array.add_objects({
+ AbstractResponse: ["throw new Error ('No object defined for the AbstractResponse interface')"],
+ OpaqueResponse: ["throw new Error ('No object defined for the OpaqueResponse interface')"],
+ CORSResponse: ["throw new Error ('No object defined for the CORSResponse interface')"],
+ Response: ["throw new Error ('No object defined for the Response interface')"],
+ ResponseInit: ["throw new Error ('No object defined for the ResponseInit dictionary')"]
+ });
+ idl_array.test();
+ </script>
+
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/service-workers/stub-4.5.2-response.html b/tests/wpt/web-platform-tests/service-workers/stub-4.5.2-response.html
new file mode 100644
index 00000000000..0a8715c7511
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/stub-4.5.2-response.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: Response</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#response">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+`Response` objects are mutable and constructable. They model HTTP responses.
+The `fetch()` API returns this type for same-origin responses.
+
+It may be possible to set the `Location` header of a `Response` object to
+someplace not in the current origin but this is not a security issue.
+Cross-origin response bodies are opaque to script, and since only same-origin
+documents will encounter these responses, the only systems the Service Worker
+can "lie to" are same-origin (and therefore safe from the perspective of other
+origins).
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section Response so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/service-workers/stub-4.5.4-opaque-response.html b/tests/wpt/web-platform-tests/service-workers/stub-4.5.4-opaque-response.html
new file mode 100644
index 00000000000..1698558daec
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/stub-4.5.4-opaque-response.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: OpaqueResponse</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#opaque-response">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+`OpaqueResponse` objects are immutable but constructable. The `fetch()` API
+returns this type for cross-origin responses.
+
+Their role is to encapsulate the security properties of the web platform. As
+such, their `body` attribute will always be `undefined` and the list of
+readable `headers` is heavily filtered.
+
+`OpaqueResponse` objects may be forwarded on to rendering documents in exactly
+the same way as mutable `Response` objects.
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section OpaqueResponse so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/service-workers/stub-4.6-cache-objects.html b/tests/wpt/web-platform-tests/service-workers/stub-4.6-cache-objects.html
new file mode 100644
index 00000000000..3bb47b27ef6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/stub-4.6-cache-objects.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: Caches</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-objects">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+To allow authors to fully manage their content caches for offline use, the
+`[ServiceWorkerGlobalScope][1]` execution context provides the caching methods
+largely conforming to [ECMAScript 6 Map objects][2] with additional convenience
+methods. A domain can have multiple, named `[Cache][3]` objects, whose contents
+are entirely under the control of scripts. Caches are not shared across
+domains, and they are completely isolated from the browser's HTTP cache.
+
+[1]: #service-worker-global-scope-interface
+[2]: http://goo.gl/gNnDPO
+[3]: #cache-interface
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section Caches so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/service-workers/stub-4.6.1-cache-lifetimes.html b/tests/wpt/web-platform-tests/service-workers/stub-4.6.1-cache-lifetimes.html
new file mode 100644
index 00000000000..9068d0c3ba7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/stub-4.6.1-cache-lifetimes.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: Understanding Cache Lifetimes</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-lifetimes">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+The `[Cache][1]` instances are not part of the browser's HTTP cache. The
+`[Cache][1]` objects are exactly what authors have to manage themselves. The
+`[Cache][1]` objects do not get updated unless authors explicitly request them
+to be. The `[Cache][1]` objects do not expire unless authors delete the
+entries. The `[Cache][1]` objects do not disappear just because the Service
+Worker script is updated. That is, caches are not updated automatically.
+Updates must be manually managed. This implies that authors should version
+their caches by name and make sure to use the caches only from the version of
+the ServiceWorker that can safely operate on.
+
+[1]: #cache-interface
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section Understanding Cache Lifetimes so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/service-workers/stub-4.6.2-cache.html b/tests/wpt/web-platform-tests/service-workers/stub-4.6.2-cache.html
new file mode 100644
index 00000000000..faee336b8b8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/stub-4.6.2-cache.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: Cache</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ <script src=/resources/WebIDLParser.js></script>
+ <script src=/resources/idlharness.js></script>
+
+ </head>
+ <body>
+
+<script type=text/plain id="idl_0">
+[Exposed=(Window,Worker)]
+interface Cache {
+ Promise<Response> match(RequestInfo request, optional CacheQueryOptions options);
+ Promise<sequence<Response>> matchAll(optional RequestInfo request, optional CacheQueryOptions options);
+ Promise<void> add(RequestInfo request);
+ Promise<void> addAll(sequence<RequestInfo> requests);
+ Promise<void> put(RequestInfo request, Response response);
+ Promise<boolean> delete(RequestInfo request, optional CacheQueryOptions options);
+ Promise<sequence<Request>> keys(optional RequestInfo request, optional CacheQueryOptions options);
+};
+
+dictionary CacheQueryOptions {
+ boolean ignoreSearch = false;
+ boolean ignoreMethod = false;
+ boolean ignoreVary = false;
+ DOMString cacheName;
+};
+
+dictionary CacheBatchOperation {
+ DOMString type;
+ Request request;
+ Response response;
+ CacheQueryOptions options;
+};
+</pre>
+
+
+
+ <script type=text/plain id="untested_idls">
+ interface AbstractResponse {};
+ interface Request {};
+ interface ScalarValueString {};
+ </pre>
+
+ <script>
+ var idl_array = new IdlArray();
+ idl_array.add_untested_idls(document.getElementById("untested_idls").textContent);
+ idl_array.add_idls(document.getElementById("idl_0").textContent);
+ idl_array.add_objects({
+ Cache: ["throw new Error ('No object defined for the Cache interface')"],
+ QueryParams: ["throw new Error ('No object defined for the QueryParams dictionary')"],
+ CacheIterationCallback: ["throw new Error ('No object defined for the CacheIterationCallback callback')"]
+ });
+ idl_array.test();
+ </script>
+
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/service-workers/stub-4.6.3-cache-storage.html b/tests/wpt/web-platform-tests/service-workers/stub-4.6.3-cache-storage.html
new file mode 100644
index 00000000000..875220ea9ff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/stub-4.6.3-cache-storage.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: CacheStorage</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cache-storage">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ <script src=/resources/WebIDLParser.js></script>
+ <script src=/resources/idlharness.js></script>
+
+ </head>
+ <body>
+
+<script type=text/plain id="idl_0">
+[Constructor(sequence<any> iterable)]
+interface CacheStorage {
+ Promise<any> match(ScalarValueString url, optional DOMString cacheName);
+ Promise<Cache> get(DOMString key);
+ Promise<boolean> has(DOMString key);
+ Promise<any> set(DOMString key, Cache val);
+ Promise<any> clear();
+ Promise<any> delete(DOMString key);
+ void forEach(CacheStorageIterationCallback callback, optional object thisArg);
+ Promise<sequence<any>> entries();
+ Promise<sequence<DOMString>> keys();
+ Promise<sequence<Cache>> values();
+ Promise<unsigned long> size();
+};
+
+callback CacheStorageIterationCallback = void (Cache value, DOMString key, CacheStorage map);
+</pre>
+
+<!--
+**Note**:[CacheStorage][1]interface is designed to largely conform
+to[ECMAScript 6 Map objects][2]but entirely async, and with additional
+convenience methods.
+
+[1]: #cache-storage-interface
+[2]: http://goo.gl/gNnDPO
+-->
+
+
+ <script type=text/plain id="untested_idls">
+ interface ScalarValueString {};
+ interface Cache {};
+ </pre>
+
+ <script>
+ var idl_array = new IdlArray();
+ idl_array.add_untested_idls(document.getElementById("untested_idls").textContent);
+ idl_array.add_idls(document.getElementById("idl_0").textContent);
+ idl_array.add_objects({
+ CacheStorage: ["throw new Error ('No object defined for the CacheStorage interface')"],
+ CacheStorageIterationCallback: ["throw new Error ('No object defined for the CacheStorageIterationCallback callback')"]
+ });
+ idl_array.test();
+ </script>
+
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/service-workers/stub-4.7.1-install-phase-event.html b/tests/wpt/web-platform-tests/service-workers/stub-4.7.1-install-phase-event.html
new file mode 100644
index 00000000000..195c38d9415
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/stub-4.7.1-install-phase-event.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: InstallPhaseEvent</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#install-phase-event">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ <script src=/resources/WebIDLParser.js></script>
+ <script src=/resources/idlharness.js></script>
+
+ </head>
+ <body>
+
+<script type=text/plain id="idl_0">
+interface InstallPhaseEvent : Event {
+ Promise<any> waitUntil(Promise<any> f);
+};
+</pre>
+
+<!--
+Service Workers have two [Lifecycle events][1], `[install][2]` and
+`[activate][3]`. Service Workers use the `[InstallPhaseEvent][4]` interface for
+`[activate][3]` event and the `[InstallEvent][5]` interface, which inherits
+from the `[InstallPhaseEvent][4]` interface, for `[install][2]` event.
+
+[1]: #lifecycle-events
+[2]: #install-event
+[3]: #activate-event
+[4]: #install-phase-event-interface
+[5]: #install-event-interface
+-->
+
+
+ <script type=text/plain id="untested_idls">
+ interface Event {};
+ </pre>
+
+ <script>
+ var idl_array = new IdlArray();
+ idl_array.add_untested_idls(document.getElementById("untested_idls").textContent);
+ idl_array.add_idls(document.getElementById("idl_0").textContent);
+ idl_array.add_objects({
+ InstallPhaseEvent: ["throw new Error ('No object defined for the InstallPhaseEvent interface')"]
+ });
+ idl_array.test();
+ </script>
+
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/service-workers/stub-4.7.1.1-wait-until-method.html b/tests/wpt/web-platform-tests/service-workers/stub-4.7.1.1-wait-until-method.html
new file mode 100644
index 00000000000..84b730f5c73
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/stub-4.7.1.1-wait-until-method.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: event.waitUntil(f)</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#wait-until-method">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+`event.waitUntil(f)` method, when called in `oninstall` or `onactivate`,
+extends the lifetime of the event. When called in `oninstall`, it delays
+treating the installing worker until the passed [Promise][1] resolves
+successfully. This is primarily used to ensure that a `ServiceWorker` is not
+active until all of the core caches it depends on are populated. When called in
+`onactivate`, it delays treating the activating worker until the passed
+[Promise][1] resolves successfully. This is primarily used to ensure that any
+[Functional events][2] are not dispatched to the `ServiceWorker` until it
+upgrades database schemas and deletes the outdated cache entries.
+
+[1]: http://goo.gl/3TobQS
+[2]: #functional-events
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section event.waitUntil(f) so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/service-workers/stub-4.7.2-install-event.html b/tests/wpt/web-platform-tests/service-workers/stub-4.7.2-install-event.html
new file mode 100644
index 00000000000..a2a5b1d310b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/stub-4.7.2-install-event.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: install Event</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#install-event">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+An event named `[install][1]` using the `[InstallEvent][2]` interface is
+dispatched on `ServiceWorkerGlobalScope` object when the state of the
+associated `ServiceWorker` changes its value to `installing`. (See step 3 of
+[_Installation algorithm][3])
+
+[1]: #install-event
+[2]: #install-event-interface
+[3]: #installation-algorithm
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section install Event so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/service-workers/stub-4.7.2.1-install-event-section.html b/tests/wpt/web-platform-tests/service-workers/stub-4.7.2.1-install-event-section.html
new file mode 100644
index 00000000000..c305159b1d2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/stub-4.7.2.1-install-event-section.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: InstallEvent</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#install-event-section">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ <script src=/resources/WebIDLParser.js></script>
+ <script src=/resources/idlharness.js></script>
+
+ </head>
+ <body>
+
+<script type=text/plain id="idl_0">
+interface InstallEvent : InstallPhaseEvent {
+ readonly attribute ServiceWorker? activeWorker;
+ void replace();
+};
+</pre>
+
+<!--
+Service Workers use the `[InstallEvent][1]` interface for `[install][2]` event.
+
+[1]: #install-event-interface
+[2]: #install-event
+-->
+
+
+ <script type=text/plain id="untested_idls">
+ interface ServiceWorker {};
+ interface InstallPhaseEvent {};
+ </pre>
+
+ <script>
+ var idl_array = new IdlArray();
+ idl_array.add_untested_idls(document.getElementById("untested_idls").textContent);
+ idl_array.add_idls(document.getElementById("idl_0").textContent);
+ idl_array.add_objects({
+ InstallEvent: ["throw new Error ('No object defined for the InstallEvent interface')"]
+ });
+ idl_array.test();
+ </script>
+
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/service-workers/stub-4.7.2.2-replace-method.html b/tests/wpt/web-platform-tests/service-workers/stub-4.7.2.2-replace-method.html
new file mode 100644
index 00000000000..78c916f0ee9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/stub-4.7.2.2-replace-method.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: event.replace()</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#replace-method">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+`replace()` interacts with `waitUntil` method in the following way:
+
+- Successful installation can be delayed by `waitUntil`, perhaps by
+ subsequent event handlers.
+- Replacement only happens upon successful installation
+- Therefore, replacement of the [active worker][1] (if any) is not
+ immediate, however it may occur as soon as the end of the current turn.
+
+
+
+[1]: #navigator-service-worker-active
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section event.replace() so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/service-workers/stub-4.7.3-activate-event.html b/tests/wpt/web-platform-tests/service-workers/stub-4.7.3-activate-event.html
new file mode 100644
index 00000000000..82c049a9417
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/stub-4.7.3-activate-event.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: activate Event</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#activate-event">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+An event named `[activate][1]` using the `[InstallPhaseEvent][2]` interface is
+dispatched on `ServiceWorkerGlobalScope` object when the state of the
+associated `ServiceWorker` changes its value to `activating`. (See step 6 of
+[_Activation algorithm][3])
+
+Service Workers use the `[InstallPhaseEvent][4]` interface for `[activate][1]`
+event.
+
+
+
+[1]: #activate-event
+[2]: #install-phase-event
+[3]: #activation-algorithm
+[4]: #install-phase-event-interface
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section activate Event so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/service-workers/stub-4.7.4.1-fetch-event-section.html b/tests/wpt/web-platform-tests/service-workers/stub-4.7.4.1-fetch-event-section.html
new file mode 100644
index 00000000000..8555903d3cc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/stub-4.7.4.1-fetch-event-section.html
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: FetchEvent</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#fetch-event-section">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ <script src=/resources/WebIDLParser.js></script>
+ <script src=/resources/idlharness.js></script>
+
+ </head>
+ <body>
+
+<script type=text/plain id="idl_0">
+[Constructor]
+interface FetchEvent : Event {
+ readonly attribute Request request;
+ readonly attribute Client client; // The window issuing the request.
+ readonly attribute Context context;
+ readonly attribute boolean isReload;
+
+ void respondWith(Promise<AbstractResponse> r);
+ Promise<any> forwardTo(ScalarValueString url);
+ Promise<any> default();
+};
+
+enum Context {
+ "connect",
+ "font",
+ "img",
+ "object",
+ "script",
+ "style",
+ "worker",
+ "popup",
+ "child",
+ "navigate"
+};
+</pre>
+
+<!--
+Service Workers use the `[FetchEvent][1]` interface for `[fetch][2]` event.
+
+[1]: #fetch-event-interface
+[2]: #fetch-event
+-->
+
+
+ <script type=text/plain id="untested_idls">
+ interface Request {};
+ interface Client {};
+ interface AbstractResponse {};
+ interface ScalarValueString {};
+ interface Event {};
+ </pre>
+
+ <script>
+ var idl_array = new IdlArray();
+ idl_array.add_untested_idls(document.getElementById("untested_idls").textContent);
+ idl_array.add_idls(document.getElementById("idl_0").textContent);
+ idl_array.add_objects({
+ FetchEvent: ["throw new Error ('No object defined for the FetchEvent interface')"],
+ Context: ["throw new Error ('No object defined for the Context enum')"]
+ });
+ idl_array.test();
+ </script>
+
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/service-workers/stub-4.7.4.2-respond-with-method.html b/tests/wpt/web-platform-tests/service-workers/stub-4.7.4.2-respond-with-method.html
new file mode 100644
index 00000000000..f178a50cfbf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/stub-4.7.4.2-respond-with-method.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: event.respondWith(r)</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#respond-with-method">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+`event.respondWith(r)` method must run the steps, from step 10 to step 15,
+defined in the [_OnFetchRequest algorithm][1].
+
+The `r` argument must resolve with a [AbstractResponse][2], else a
+[NetworkError][3] is thrown. If the request is a top-level navigation and the
+return value is a [OpaqueResponse][4] (an opaque response body), a
+[NetworkError][3] is thrown. The final URL of all successful (non
+network-error) responses is the [requested][5] URL. Renderer-side security
+checks about tainting for cross-origin content are tied to the transparency (or
+opacity) of the [Response][6] body, not URLs.
+
+
+
+[1]: #on-fetch-request-algorithm
+[2]: #abstract-response-interface
+[3]: http://w3c.github.io/dom/#networkerror
+[4]: #opaque-response-interface
+[5]: #request-objects
+[6]: #response-interface
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section event.respondWith(r) so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/service-workers/stub-4.7.4.3-default-method.html b/tests/wpt/web-platform-tests/service-workers/stub-4.7.4.3-default-method.html
new file mode 100644
index 00000000000..52a8dbda4b8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/stub-4.7.4.3-default-method.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: event.default()</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#default-method">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+`event.default()` method must run these steps:
+
+1. Let `promise` be a newly-created [promise][1].
+2. Return `promise.`
+3. Run the following steps asynchronously:
+ 1. Let `request` be `event`'s `request`.
+ 2. Set `request`'s [skip service worker flag][2].
+ 3. Let `response` be the result of running [fetch algorithm][3] with
+ `request` as its argument.
+ 4. If `response` is a [network error][4], then:
+ 1. Reject `promise` with a new [DOMException][5] whose name is
+ "[NetworkError][6]".
+ 5. Else,
+ 1. Resolve `promise` with a new [Response][7] object associated
+ with `response`.
+
+
+
+[1]: http://goo.gl/3TobQS
+[2]: http://goo.gl/gP7IWW
+[3]: http://goo.gl/fGMifs
+[4]: http://goo.gl/jprjjc
+[5]: http://goo.gl/A0U8qC
+[6]: http://goo.gl/lud5HB
+[7]: http://goo.gl/Deazjv
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section event.default() so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/service-workers/stub-4.7.4.4-is-reload-attribute.html b/tests/wpt/web-platform-tests/service-workers/stub-4.7.4.4-is-reload-attribute.html
new file mode 100644
index 00000000000..f116b6875c9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/stub-4.7.4.4-is-reload-attribute.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: event.isReload</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#is-reload-attribute">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+Returns true if `event` was dispatched with the user's intention for the page
+reload, and false otherwise. Pressing the refresh button should be considered a
+reload while clicking a link and pressing the back button should not. The
+behavior of the `Ctrl+l enter` is left to the implementations of the user
+agents.
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section event.isReload so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/service-workers/stub-5.1-origin-relativity.html b/tests/wpt/web-platform-tests/service-workers/stub-5.1-origin-relativity.html
new file mode 100644
index 00000000000..e885de650dd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/stub-5.1-origin-relativity.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: Origin Relativity</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#origin-relativity">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+One of the advanced concerns that major applications would encounter is whether
+they can be hosted from a CDN. By definition, these are servers in other
+places, often on other domains. Therefore, Service Workers cannot be hosted on
+CDNs. But they can include resources via [importScripts()][1]. The reason for
+this restriction is that Service Workers create the opportunity for a bad actor
+to turn a bad day into a bad eternity.
+
+[1]: http://goo.gl/Owcfs2
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section Origin Relativity so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/service-workers/stub-5.2-cross-origin-resources.html b/tests/wpt/web-platform-tests/service-workers/stub-5.2-cross-origin-resources.html
new file mode 100644
index 00000000000..3a10c9e0883
--- /dev/null
+++ b/tests/wpt/web-platform-tests/service-workers/stub-5.2-cross-origin-resources.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html>
+<title>Service Workers: Cross-Origin Resources &amp; CORS</title>
+ <head>
+ <link rel="help" href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/#cross-origin-resources">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+
+ </head>
+ <body>
+
+<!--
+
+Applications tend to cache items that come from a CDN or other domain. It is
+possible to request many of them directly using <script>, <img>, <video> and
+<link> elements. It would be hugely limiting if this sort of runtime
+collaboration broke when offline. Similarly, it is possible to XHR many sorts
+of off-domain resources when appropriate CORS headers are set.
+
+ServiceWorkers enable this by allowing `Cache`s to fetch and cache off-origin
+items. Some restrictions apply, however. First, unlike same-origin resources
+which are managed in the `Cache` as `[Promise][1]`s for `Response` instances,
+the objects stored are `[Promise][1]`s for `OpaqueResponse` instances.
+`OpaqueResponse` provides a much less expressive API than `Response`; the
+bodies and headers cannot be read or set, nor many of the other aspects of
+their content inspected. They can be passed to `respondWith()` and
+`forwardTo()` in the same manner as `Response`s, but cannot be meaningfully
+created programmatically. These limitations are necessary to preserve the
+security invariants of the platform. Allowing `Cache`s to store them allows
+applications to avoid re-architecting in most cases.
+
+
+
+[1]: http://goo.gl/3TobQS
+
+-->
+
+
+
+ <script>
+ test(function() {
+ // not_implemented();
+ }, "There are no tests for section Cross-Origin Resources &amp; CORS so far.");
+ </script>
+
+ </body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/shadow-dom/LICENSE b/tests/wpt/web-platform-tests/shadow-dom/LICENSE
new file mode 100644
index 00000000000..531fac43af2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/LICENSE
@@ -0,0 +1,107 @@
+Copyright 2012, Google Inc.
+All rights reserved.
+
+Licensed under the W3C Test Suite License (the "License"); you may not
+use this software except in compliance with the License. You may
+obtain a copy of the License at
+
+ http://www.w3.org/Consortium/Legal/2008/04-testsuite-license.html
+
+Alternatively, this software may be distributed under the terms of the
+W3C 3-clause BSD License. You may obtain a copy of the W3C 3-clause
+BSD License at
+
+ http://www.w3.org/Consortium/Legal/2008/03-bsd-license.html
+
+
+W3C Test Suite Licence
+
+This document, Test Suites and other documents that link to this
+statement are provided by the copyright holders under the following
+license: By using and/or copying this document, or the W3C document
+from which this statement is linked, you (the licensee) agree that you
+have read, understood, and will comply with the following terms and
+conditions:
+
+Permission to copy, and distribute the contents of this document, or
+the W3C document from which this statement is linked, in any medium
+for any purpose and without fee or royalty is hereby granted, provided
+that you include the following on ALL copies of the document, or
+portions thereof, that you use:
+
+ 1. A link or URL to the original W3C document.
+ 2. The pre-existing copyright notice of the original author, or if
+it doesn't exist, a notice (hypertext is preferred, but a textual
+representation is permitted) of the form: "Copyright ©
+[$date-of-document] World Wide Web Consortium, (Massachusetts
+Institute of Technology, European Research Consortium for Informatics
+and Mathematics, Keio University) and others. All Rights
+Reserved. http://www.w3.org/Consortium/Legal/2008/04-testsuite-copyright.html"
+ 3. If it exists, the STATUS of the W3C document. When space
+permits, inclusion of the full text of this NOTICE should be
+provided. We request that authorship attribution be provided in any
+software, documents, or other items or products that you create
+pursuant to the implementation of the contents of this document, or
+any portion thereof.
+
+No right to create modifications or derivatives of W3C documents is
+granted pursuant to this license. However, if additional requirements
+(documented in the Copyright FAQ) are satisfied, the right to create
+modifications or derivatives is sometimes granted by the W3C to
+individuals complying with those requirements.
+
+If a Test Suite distinguishes the test harness (or, framework for
+navigation) and the actual tests, permission is given to remove or
+alter the harness or navigation if the Test Suite in question allows
+to do so. The tests themselves shall NOT be changed in any way.
+
+The name and trademarks of W3C and other copyright holders may NOT be
+used in advertising or publicity pertaining to this document or other
+documents that link to this statement without specific, written prior
+permission. Title to copyright in this document will at all times
+remain with copyright holders. Permission is given to use the
+trademarked string W3C within claims of performance concerning W3C
+Specifications or features described therein, and there only, if the
+test suite so authorizes.
+
+THIS WORK IS PROVIDED BY W3C, MIT, ERCIM, KEIO UNIVERSITY, THE
+COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL W3C, MIT, ERCIM, KEIO UNIVERSITY, THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGE.
+
+
+W3C 3-clause BSD License
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+ * Redistributions of works must retain the original copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the original
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of the W3C nor the names of its contributors may
+be used to endorse or promote products derived from this work without
+specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/extensions-to-element-interface/attributes/test-001.html b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/extensions-to-element-interface/attributes/test-001.html
new file mode 100644
index 00000000000..3d0b11841cd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/extensions-to-element-interface/attributes/test-001.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_10_02_01_01</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#shadow-aware-attributes">
+<meta name="assert" content="Extensions to Element Interface: pseudo of type DOMString attribute. Test getter when there is a custom pseudo-element associated with this element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function () {
+
+ var d = newHTMLDocument();
+
+ var widget = d.createElement('div');
+ d.body.appendChild(widget);
+
+ var s = widget.createShadowRoot();
+
+ var thumb = d.createElement('span');
+ thumb.innerHTML = 'This is a pseudo-element';
+ thumb.pseudo = 'x-thumb';
+ s.appendChild(thumb);
+
+ var style = d.createElement('style');
+ style.innerHTML = '' +
+ 'div::x-thumb {' +
+ 'font-size: 30px;' +
+ '}';
+ d.body.appendChild(style);
+
+ assert_true(thumb.pseudo != null, 'attribute \'pseudo\' must not be null');
+
+ assert_equals(thumb.pseudo, 'x-thumb', 'attribute \'pseudo\' must return ' +
+ 'the current custom pseudo-element value')
+
+}, 'A_10_02_01_01_T01');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/extensions-to-element-interface/attributes/test-005.html b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/extensions-to-element-interface/attributes/test-005.html
new file mode 100644
index 00000000000..ebc56e654cb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/extensions-to-element-interface/attributes/test-005.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_10_02_01_05</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#shadow-aware-attributes">
+<meta name="assert" content="Extensions to Element Interface: shadowRoot of type ShadowRoot">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function () {
+
+ var d = newHTMLDocument();
+
+ var host = d.createElement('div');
+ d.body.appendChild(host);
+
+ //old tree
+ var s1 = host.createShadowRoot();
+ //young tree
+ var s2 = host.createShadowRoot();
+
+ assert_equals(host.shadowRoot, s2, 'attribute shadowRoot must return the youngest tree that has ' +
+ 'the context object as its shadow host');
+
+
+}, 'A_10_02_01_05_T01');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/extensions-to-element-interface/attributes/test-006.html b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/extensions-to-element-interface/attributes/test-006.html
new file mode 100644
index 00000000000..a2d497d2a1b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/extensions-to-element-interface/attributes/test-006.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_10_02_01_06</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#shadow-aware-attributes">
+<meta name="assert" content="Extensions to Element Interface: shadowRoot of type ShadowRoot">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function () {
+
+ var d = newHTMLDocument();
+
+ var host = d.createElement('div');
+ d.body.appendChild(host);
+
+ assert_equals(host.shadowRoot, null, 'attribute shadowRoot must return null if no shadow tree is accesible');
+
+
+}, 'A_10_02_01_06_T01');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/extensions-to-element-interface/methods/elements-001.html b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/extensions-to-element-interface/methods/elements-001.html
new file mode 100644
index 00000000000..5449547e112
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/extensions-to-element-interface/methods/elements-001.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: HTML elements can host shadow trees</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="author" title="Mikhail Fursov" href="mailto:mfursov@unipro.ru">
+<link rel="author" title="Yuta Kitamura" href="mailto:yutak@google.com">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#partial-element-methods">
+<meta name="assert" content="All HTML elements must be able to host shadow trees.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+function testElement(elementName) {
+ var doc = document.implementation.createHTMLDocument('Test');
+ var element = doc.createElement(elementName);
+ doc.body.appendChild(element);
+
+ var shadowRoot1 = element.createShadowRoot();
+ assert_equals(shadowRoot1.ownerDocument, doc);
+
+ var shadowRoot2 = element.createShadowRoot();
+ assert_equals(shadowRoot2.ownerDocument, doc);
+}
+
+var testParameters = HTML5_ELEMENT_NAMES.map(function (name) {
+ return [
+ 'Checks whether an element "' + name + '" can create a shadow root.',
+ name
+ ];
+});
+
+generate_tests(testElement, testParameters);
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/extensions-to-element-interface/methods/non-element-nodes-001.html b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/extensions-to-element-interface/methods/non-element-nodes-001.html
new file mode 100644
index 00000000000..23dfc3d7cbe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/extensions-to-element-interface/methods/non-element-nodes-001.html
@@ -0,0 +1,136 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: Non-element node cannot be a shadow host</title>
+<link rel="author" title="Aleksei Yu. Semenov" href="mailto:sgrekhov@unipro.ru">
+<link rel="author" title="Mikhail Fursov" href="mailto:mfursov@unipro.ru">
+<link rel="author" title="Yuta Kitamura" href="mailto:yutak@google.com">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#partial-element-methods">
+<meta name="assert" content="Nodes, that are not elements, are not allowed to become shadow hosts.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var XHTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';
+
+function createTextNode() {
+ var doc = document.implementation.createHTMLDocument('Test Document');
+ var node = doc.createTextNode('Text Node');
+ doc.body.appendChild(node);
+ return node;
+}
+
+function createCommentNode() {
+ var doc = document.implementation.createHTMLDocument('Test Document');
+ var node = doc.createComment('Comment Node');
+ doc.body.appendChild(node);
+ return node;
+}
+
+function createCDATASectionNode() {
+ var doc = document.implementation.createDocument(XHTML_NAMESPACE, 'html');
+ var node = doc.createCDATASection('CDATA Section Node');
+ doc.documentElement.appendChild(node);
+ return node;
+}
+
+function createAttributeNode() {
+ var doc = document.implementation.createDocument(XHTML_NAMESPACE, 'html');
+ var node = doc.createAttribute('attribute-node');
+ doc.documentElement.setAttributeNode(node);
+ return node;
+}
+
+function createDocumentFragmentNode() {
+ var doc = document.implementation.createDocument(XHTML_NAMESPACE, 'html');
+ var node = doc.createDocumentFragment();
+ doc.documentElement.appendChild(node);
+ return node;
+}
+
+function createEntityReferenceNode() {
+ var doc = document.implementation.createDocument(XHTML_NAMESPACE, 'html');
+ var node = doc.createEntityReference('entity-reference-node');
+ doc.documentElement.appendChild(node);
+ return node;
+}
+
+function createProcessingInstructionNode() {
+ var doc = document.implementation.createDocument(XHTML_NAMESPACE, 'html');
+ var node = doc.createProcessingInstruction('processing-instruction-node');
+ doc.documentElement.appendChild(node);
+ return node;
+}
+
+function createDocumentNode() {
+ return document.implementation.createDocument(XHTML_NAMESPACE, 'html');
+}
+
+var factories = [
+ ['a text node', createTextNode],
+ ['a comment node', createCommentNode],
+ ['a CDATA section node', createCDATASectionNode],
+ ['an attribute node', createAttributeNode],
+ ['a document fragment node', createDocumentFragmentNode],
+ ['an entity reference node', createEntityReferenceNode],
+ ['a processing instruction node', createProcessingInstructionNode],
+ ['a document node', createDocumentNode]
+];
+
+// Non-element nodes should not have createShadowRoot() method.
+var noCreateShadowRootTestParameters = factories.map(
+ function (nameAndFactory) {
+ var name = nameAndFactory[0];
+ var factory = nameAndFactory[1];
+ return [
+ 'Checks whether ' + name + ' does not have createShadowRoot() ' +
+ 'method.',
+ factory
+ ];
+ });
+
+function testNoCreateShadowRoot(factory) {
+ var node = factory();
+ assert_equals(node.createShadowRoot, undefined);
+}
+
+generate_tests(testNoCreateShadowRoot, noCreateShadowRootTestParameters);
+
+// When createShadowRoot() is called on non-element nodes, it should throw
+// InvalidNodeTypeError (step 1 of section 10.2.2).
+function testThrowInvalidNodeTypeError(factory) {
+ var node = factory();
+ node.createShadowRoot = Element.prototype.createShadowRoot;
+ assert_throws('InvalidNodeTypeError',
+ function () { node.createShadowRoot(); });
+}
+
+var throwInvalidNodeTypeErrorTestParameters = factories.map(
+ function (nameAndFactory) {
+ var name = nameAndFactory[0];
+ var factory = nameAndFactory[1];
+ return [
+ 'When createShadowRoot() is called on ' + name + ', ' +
+ 'InvalidNodeTypeError should be thrown.',
+ factory
+ ];
+ });
+
+generate_tests(testThrowInvalidNodeTypeError,
+ throwInvalidNodeTypeErrorTestParameters);
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/extensions-to-element-interface/methods/test-001.html b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/extensions-to-element-interface/methods/test-001.html
new file mode 100644
index 00000000000..5db05bc30ed
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/extensions-to-element-interface/methods/test-001.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_10_02_02_01</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#shadow-aware-methods">
+<meta name="assert" content="Extensions to Element Interface: createShadowRoot method creates new instance of Shadow root object">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function () {
+
+ var d = newHTMLDocument();
+
+ var host = d.createElement('div');
+ d.body.appendChild(host);
+
+ var s = host.createShadowRoot();
+
+ assert_true(s instanceof ShadowRoot, 'createShadowRoot() method should create new instance ' +
+ 'of ShadowRoot object');
+
+}, 'A_10_02_02_01_T01');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/extensions-to-element-interface/methods/test-002.html b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/extensions-to-element-interface/methods/test-002.html
new file mode 100644
index 00000000000..6e6ab48bccc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/extensions-to-element-interface/methods/test-002.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_10_02_02_02</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#shadow-aware-methods">
+<meta name="assert" content="Extensions to Element Interface: createShadowRoot method">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var host = d.createElement('div');
+ d.body.appendChild(host);
+
+ var span = d.createElement('span');
+ span.innerHTML = 'Some text';
+ host.appendChild(span);
+
+ var s = host.createShadowRoot();
+
+ // span should become invisible as shadow root content
+ assert_equals(span.offsetTop, 0, 'createShadowRoot() method should establish ' +
+ 'the context object as the shadow host of the ShadowRoot object');
+
+}), 'A_10_02_02_02_T01');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/extensions-to-element-interface/methods/test-003.html b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/extensions-to-element-interface/methods/test-003.html
new file mode 100644
index 00000000000..f916fb0e098
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/extensions-to-element-interface/methods/test-003.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_10_02_02_03</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#shadow-aware-methods">
+<meta name="assert" content="Extensions to Element Interface: createShadowRoot method">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var host = d.createElement('div');
+ d.body.appendChild(host);
+
+ var span = d.createElement('span');
+ span.setAttribute('id', 'sp0');
+ span.innerHTML = 'Some text';
+ host.appendChild(span);
+
+ //old tree
+ var s1 = host.createShadowRoot();
+ s1.innerHTML = '<span id="sp1">Span 1</span>';
+ //young tree
+ var s2 = host.createShadowRoot();
+ s2.innerHTML = '<span id="sp2">Span 2</span>';
+
+ // span should become invisible as shadow root content
+ assert_equals(span.offsetTop, 0, 'Point 1:createShadowRoot() method should add ' +
+ 'the ShadowRoot object at the top of the tree stack of its host');
+ assert_equals(s1.querySelector('#sp1').offsetTop, 0, 'Point 2:createShadowRoot() method should add ' +
+ 'the ShadowRoot object at the top of the tree stack of its host');
+ assert_true(s2.querySelector('#sp2').offsetTop > 0, 'Point 3:createShadowRoot() method should add ' +
+ 'the ShadowRoot object at the top of the tree stack of its host');
+
+
+}), 'A_10_02_02_03_T01');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/extensions-to-event-interface/event-path-001.html b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/extensions-to-event-interface/event-path-001.html
new file mode 100644
index 00000000000..e1a251dd606
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/extensions-to-event-interface/event-path-001.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test - event path</title>
+<link rel="author" title="Kazuhito Hokamura" href="mailto:k.hokamura@gmail.com">
+<link rel="help" href="https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#extensions-to-event">
+<meta name="assert" content="Extensions to Event Interface: event.path cross the shadow boundary">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var t = async_test('event.path cross the shadow boundary');
+
+t.step(unit(function(ctx) {
+ var doc = newRenderedHTMLDocument(ctx);
+ var host = doc.createElement('div');
+
+ var shadowRoot = host.createShadowRoot();
+ var child = doc.createElement('div');
+
+ doc.body.appendChild(host);
+ shadowRoot.appendChild(child);
+
+ child.addEventListener('click', t.step_func(function(e) {
+ assert_equals(e.path.length, 7, 'path.length');
+ assert_equals(e.path[0], child, 'path[0] should be child');
+ assert_equals(e.path[1], shadowRoot, 'path[1] should be shadowRoot');
+ assert_equals(e.path[2], host, 'path[2] should be host');
+ assert_equals(e.path[3], doc.body, 'path[3] should be body');
+ assert_equals(e.path[4], doc.documentElement, 'path[4] should be html');
+ assert_equals(e.path[5], doc, 'path[5] should be document');
+ assert_equals(e.path[6], ctx.iframes[0].contentWindow, 'path[6] should be window');
+
+ t.done();
+ }));
+
+ var event = doc.createEvent('HTMLEvents');
+ event.initEvent('click', true, false);
+ child.dispatchEvent(event);
+}));
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/extensions-to-event-interface/event-path-002.html b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/extensions-to-event-interface/event-path-002.html
new file mode 100644
index 00000000000..d3da92bf4a1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/extensions-to-event-interface/event-path-002.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test - event path</title>
+<link rel="author" title="Kazuhito Hokamura" href="mailto:k.hokamura@gmail.com">
+<link rel="help" href="https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#extensions-to-event">
+<meta name="assert" content="Extensions to Event Interface: event.path is readonly">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var t = async_test('event.path is readonly');
+
+t.step(unit(function(ctx) {
+ var doc = newRenderedHTMLDocument(ctx);
+ var div = doc.createElement('div');
+ doc.body.appendChild(div);
+
+ div.addEventListener('click', t.step_func(function(e) {
+ var obj = {};
+ e.path = obj;
+ assert_not_equals(e.path, obj);
+
+ t.done();
+ }));
+
+ var event = doc.createEvent('HTMLEvents');
+ event.initEvent('click', true, false);
+ div.dispatchEvent(event);
+}));
+</script>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/activeElement-confirm-return-null.html b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/activeElement-confirm-return-null.html
new file mode 100644
index 00000000000..fbd2bd566d5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/activeElement-confirm-return-null.html
@@ -0,0 +1,78 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: Confirm activeElement return null</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="author" title="Masaya Iseki" href="mailto:iseki.m.aa@gmail.com">
+<link rel="help" href="http://w3c.github.io/webcomponents/spec/shadow/#attributes">
+<meta name="assert" content="ShadowRoot Object: confirm activeElement return null">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var host = d.createElement('div');
+ d.body.appendChild(host);
+ var s = host.createShadowRoot();
+
+ assert_equals(s.activeElement, null, 'activeElement attribute of the ShadowRoot must return null if there\'s no focused element');
+
+}), 'confirm activeElement return null');
+
+
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var host = d.createElement('div');
+ d.body.appendChild(host);
+ var s = host.createShadowRoot();
+
+ var inp = d.createElement('input');
+ d.body.appendChild(inp);
+
+ inp.focus();
+
+ assert_equals(s.activeElement, null, 'activeElement attribute of the ShadowRoot must return null if there\'s no focused element in the shadow tree');
+
+}), 'confirm activeElement return null when there is other element in body');
+
+
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var host = d.createElement('div');
+ d.body.appendChild(host);
+ var s = host.createShadowRoot();
+
+ var inp = d.createElement('input');
+ d.body.appendChild(inp);
+
+ var inp2 = d.createElement('input');
+ s.appendChild(inp2);
+
+ inp.focus();
+
+ assert_equals(s.activeElement, null, 'activeElement attribute of the ShadowRoot must return null if there\'s no focused element in the shadow tree');
+
+}), 'confirm activeElement return null when focus on the element in the outer shadow tree');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-007.html b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-007.html
new file mode 100644
index 00000000000..15c9e130828
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-007.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_10_01_01_03_01</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#shadow-root-attributes">
+<meta name="assert" content="ShadowRoot Object: readonly attribute Element? activeElement; actual value">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var host = d.createElement('div');
+ host.setAttribute('id', 'shRoot');
+ d.body.appendChild(host);
+ var s = host.createShadowRoot();
+
+ var inp = d.createElement('input');
+ inp.setAttribute('type', 'text');
+ inp.setAttribute('id', 'inpId');
+ inp.setAttribute('value', 'Some text');
+ s.appendChild(inp);
+
+ inp.focus();
+
+ assert_true(s.activeElement != null, 'Point 1: activeElement attribute of the ShadowRoot ' +
+ 'must return the currently focused element in the shadow tree');
+ assert_equals(s.activeElement.tagName, 'INPUT', 'Point 2: activeElement attribute of the ShadowRoot ' +
+ 'must return the currently focused element in the shadow tree');
+
+}), 'A_10_01_01_03_01_T01');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-009.html b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-009.html
new file mode 100644
index 00000000000..865cb160b22
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-009.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_10_01_01_04_01</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#shadow-root-attributes">
+<meta name="assert" content="ShadowRoot Object: innerHTML of type DOMString; Test getter">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var host = d.createElement('div');
+ d.body.appendChild(host);
+ var s = host.createShadowRoot();
+
+ var span = d.createElement('span');
+ span.innerHTML = 'Some text';
+ s.appendChild(span);
+
+ assert_equals(s.innerHTML.toLowerCase(), '<span>some text</span>',
+ 'Wrong value of ShadowRoot innerHTML attribute');
+
+}), 'A_10_01_01_04_01_T01');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-010.html b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-010.html
new file mode 100644
index 00000000000..9c6b978db75
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-010.html
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_10_01_01_04_02</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#shadow-root-attributes">
+<meta name="assert" content="ShadowRoot Object: innerHTML of type DOMString; Test setter">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var host = d.createElement('div');
+ d.body.appendChild(host);
+ var s = host.createShadowRoot();
+
+ var span = d.createElement('span');
+ span.innerHTML = 'Some text';
+ s.appendChild(span);
+
+ s.innerHTML = '<input type="text"><div>new text</div>';
+
+ assert_equals(s.innerHTML.toLowerCase(), '<input type="text"><div>new text</div>',
+ 'Wrong value of ShadowRoot innerHTML attribute');
+
+}), 'A_10_01_01_04_02_T01_01');
+
+
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var host = d.createElement('div');
+ d.body.appendChild(host);
+ var s = host.createShadowRoot();
+
+ var span = d.createElement('span');
+ span.setAttribute('id', 'spanId');
+ span.innerHTML = 'Some text';
+ s.appendChild(span);
+
+ s.innerHTML = '<input type="text" id="inputId"><div id="divId">new text</div>';
+
+ assert_equals(s.querySelector('#spanId'), null, 'Point 1:innerHTML attribute must replace all content of ' +
+ 'the ShadowRoot object');
+
+ assert_true(s.querySelector('#inputId') != null, 'Point 2:innerHTML attribute must replace all content of ' +
+ 'the ShadowRoot object');
+ assert_equals(s.querySelector('#inputId').getAttribute('id'), 'inputId',
+ 'Point 3:innerHTML attribute must replace all content of the ShadowRoot object');
+
+ assert_true(s.querySelector('#divId') != null, 'Point 3:innerHTML attribute must replace all content of ' +
+ 'the ShadowRoot object');
+ assert_equals(s.querySelector('#divId').getAttribute('id'), 'divId',
+ 'Point 4:innerHTML attribute must replace all content of the ShadowRoot object');
+}), 'A_10_01_01_04_02_T01_02');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-011.html b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-011.html
new file mode 100644
index 00000000000..2789e841edd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-011.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_10_01_01_05_01</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#shadow-root-attributes">
+<meta name="assert" content="ShadowRoot Object: styleSheets of type StyleSheetList, readonly">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var host = d.createElement('div');
+ d.body.appendChild(host);
+ var s = host.createShadowRoot();
+
+ assert_true(s.styleSheets != null, 'ShadowRoot styleSheets attribute shouldn\'t be null');
+ assert_equals(s.styleSheets.length, 0, 'attribute must return the shadow root style sheets only');
+
+}), 'A_10_01_01_05_01_T01');
+
+
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var host = d.createElement('div');
+ d.body.appendChild(host);
+ var s = host.createShadowRoot();
+
+ var style = d.createElement('style');
+ s.appendChild(style);
+
+ assert_true(s.styleSheets != null, 'ShadowRoot styleSheets attribute shouldn\'t be null');
+ assert_equals(s.styleSheets.length, 1, 'attribute must return the shadow root style sheets');
+
+}), 'A_10_01_01_05_01_T02');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-012.html b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-012.html
new file mode 100644
index 00000000000..6413f1b2dd5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-012.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_10_01_01_06</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#shadow-root-attributes">
+<meta name="assert" content="ShadowRoot Object: The nodeType attribute of a ShadowRoot instance must return DOCUMENT_FRAGMENT_NODE">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var host = d.createElement('div');
+ d.body.appendChild(host);
+ var s = host.createShadowRoot();
+
+ assert_equals(s.nodeType, 11, 'The nodeType attribute of a ShadowRoot ' +
+ 'instance must return DOCUMENT_FRAGMENT_NODE');
+
+}), 'A_10_01_01_06_T01');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-013.html b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-013.html
new file mode 100644
index 00000000000..efc01bbd5a1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-013.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_10_01_01_07</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#shadow-root-attributes">
+<meta name="assert" content="ShadowRoot Object: The nodeName attribute of a ShadowRoot instance must return "#document-fragment".">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var host = d.createElement('div');
+ d.body.appendChild(host);
+ var s = host.createShadowRoot();
+
+ assert_equals(s.nodeName, '#document-fragment', 'The nodeName attribute of a ShadowRoot instance ' +
+ 'must return "#document-fragment".');
+
+}), 'A_10_01_01_07_T01');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-014.html b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-014.html
new file mode 100644
index 00000000000..a067f13ba08
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-014.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: ShadowRoot olderShadowRoot</title>
+<link rel="author" title="Kenji Baheux" href="mailto:kenjibaheux@google.com">
+<link rel="author" title="Kyohei Tsukuda" href="tsukuda.kyouhei@gmail.com">
+<link rel="help" href="http://w3c.github.io/webcomponents/spec/shadow/#widl-ShadowRoot-olderShadowRoot">
+<meta name="assert" content="The ShadowRoot element: olderShadowRoot attribute">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var host = d.createElement('div');
+ d.body.appendChild(host);
+
+ // Shadow root and older Shadow root to play with
+ var oldRoot = host.createShadowRoot();
+
+ var div = d.createElement('div');
+ div.innerHTML = '' +
+ '<span id="spandex">This is a shadow root content</span>' +
+ '<content><span id="contentId">This is the content fallback</span></content>';
+ oldRoot.appendChild(div);
+ var youngRoot = host.createShadowRoot();
+
+ assert_equals(oldRoot.olderShadowRoot, null, 'If the context object is the oldest shadow root, return null');
+ assert_equals(youngRoot.olderShadowRoot, oldRoot, 'Return the older shadow root relative to the context object');
+
+}), 'ShadowRoot.olderShadowRoot_T01');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-001.html b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-001.html
new file mode 100644
index 00000000000..0b63fdaac54
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-001.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_10_01_02_01</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#shadow-root-methods">
+<meta name="assert" content="ShadowRoot Object: HTMLElement getElementById(DOMString elementId) method">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function () {
+
+ var d = newHTMLDocument();
+
+ var el = d.createElement('div');
+ d.body.appendChild(el);
+
+ var s = el.createShadowRoot();
+
+ var child = d.createElement('span');
+ child.setAttribute('id', 'span_id');
+ s.appendChild(child);
+
+ assert_true(s.getElementById('span_id') != null, 'Point 1: ShadowRoot getElementById() ' +
+ 'method should return child element');
+ assert_equals(s.getElementById('span_id').getAttribute('id'), 'span_id', 'Point 2: ' +
+ 'ShadowRoot getElementById() method should return child element');
+
+}, 'A_10_01_02_01_T01');
+
+
+
+test(function () {
+
+ var d = newHTMLDocument();
+
+ var el = d.createElement('div');
+ d.body.appendChild(el);
+
+ var s = el.createShadowRoot();
+
+ assert_true(s.getElementById('span_id') == null, ' ShadowRoot getElementById() ' +
+ 'method should return null if matching element not found');
+
+}, 'A_10_01_02_01_T02');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-002.html b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-002.html
new file mode 100644
index 00000000000..f3c91213bb6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-002.html
@@ -0,0 +1,83 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_10_01_02_02</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#shadow-root-methods">
+<meta name="assert" content="ShadowRoot Object: NodeList getElementsByClassName(DOMString className) method">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function () {
+
+ var d = newHTMLDocument();
+
+ var el = d.createElement('div');
+ d.body.appendChild(el);
+
+ var s = el.createShadowRoot();
+
+ assert_equals(s.getElementsByClassName('clazz').length, 0, 'ShadowRoot getElementsByClassName() ' +
+ 'method should return empty list if there\'s no matching child elements');
+
+}, 'A_10_01_02_02_T01');
+
+
+
+test(function () {
+
+ var d = newHTMLDocument();
+
+ var el = d.createElement('div');
+ d.body.appendChild(el);
+
+ var s = el.createShadowRoot();
+
+ var child = d.createElement('span');
+ child.setAttribute('class', 'clazz');
+ s.appendChild(child);
+
+ assert_equals(s.getElementsByClassName('clazz').length, 1, 'ShadowRoot getElementsByClassName() ' +
+ 'method should return matching child element');
+
+}, 'A_10_01_02_02_T02');
+
+
+test(function () {
+
+ var d = newHTMLDocument();
+
+ var el = d.createElement('div');
+ d.body.appendChild(el);
+
+ var s = el.createShadowRoot();
+
+ var child = d.createElement('span');
+ child.setAttribute('class', 'clazz');
+ s.appendChild(child);
+
+ var child2 = d.createElement('span');
+ child2.setAttribute('class', 'clazz');
+ s.appendChild(child2);
+
+ assert_equals(s.getElementsByClassName('clazz').length, 2, 'ShadowRoot getElementsByClassName() ' +
+ 'method should return matching child elements');
+
+}, 'A_10_01_02_02_T03');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-003.html b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-003.html
new file mode 100644
index 00000000000..bd8ce05be77
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-003.html
@@ -0,0 +1,154 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_10_01_02_03</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#shadow-root-methods">
+<meta name="assert" content="ShadowRoot Object: NodeList getElementsByTagNameNS(DOMString? namespace, DOMString localName) method">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function () {
+
+ var d = newHTMLDocument();
+
+ var el = d.createElement('div');
+ d.body.appendChild(el);
+
+ var s = el.createShadowRoot();
+
+ assert_equals(s.getElementsByTagNameNS('*', 'div').length, 0, 'ShadowRoot getElementsByTagNameNS() ' +
+ 'method should return empty list if there\'s no matching child elements');
+
+}, 'A_10_01_02_03_T01');
+
+
+
+test(function () {
+
+ var d = newHTMLDocument();
+
+ var el = d.createElement('div');
+ d.body.appendChild(el);
+
+ var s = el.createShadowRoot();
+
+ var child = d.createElement('span');
+ s.appendChild(child);
+
+ assert_equals(s.getElementsByTagNameNS('*','span').length, 1, 'ShadowRoot getElementsByTagNameNS() ' +
+ 'method should return matching child element');
+
+}, 'A_10_01_02_03_T02');
+
+
+test(function () {
+
+ var d = newHTMLDocument();
+
+ var el = d.createElement('div');
+ d.body.appendChild(el);
+
+ var s = el.createShadowRoot();
+
+ var child = d.createElement('span');
+ s.appendChild(child);
+
+ var child2 = d.createElement('span');
+ s.appendChild(child2);
+
+ assert_equals(s.getElementsByTagNameNS('*', 'span').length, 2, 'ShadowRoot getElementsByTagNameNS() ' +
+ 'method should return matching child elements');
+
+}, 'A_10_01_02_03_T03');
+
+
+test(function () {
+
+ var d = newHTMLDocument();
+
+ var el = d.createElement('div');
+ d.body.appendChild(el);
+
+ var s = el.createShadowRoot();
+
+ assert_equals(s.getElementsByTagNameNS('http://www.w3c.org/namespace', 'div').length, 0,
+ 'ShadowRoot getElementsByTagNameNS() method should return empty list if there\'s no ' +
+ 'matching child elements');
+
+}, 'A_10_01_02_03_T04');
+
+
+
+test(function () {
+
+ var d = newHTMLDocument();
+
+ var el = d.createElement('div');
+ d.body.appendChild(el);
+
+ var s = el.createShadowRoot();
+
+ var child = d.createElementNS('http://www.w3c.org/namespace','span');
+ s.appendChild(child);
+
+ assert_equals(s.getElementsByTagNameNS('http://www.w3c.org/namespace','span').length, 1,
+ 'ShadowRoot getElementsByTagNameNS() method should return matching child element');
+
+}, 'A_10_01_02_03_T05');
+
+
+test(function () {
+
+ var d = newHTMLDocument();
+
+ var el = d.createElement('div');
+ d.body.appendChild(el);
+
+ var s = el.createShadowRoot();
+
+ var child = d.createElementNS('http://www.w3c.org/namespace','span');
+ s.appendChild(child);
+
+ var child2 = d.createElementNS('http://www.w3c.org/namespace','span');
+ s.appendChild(child2);
+
+ assert_equals(s.getElementsByTagNameNS('http://www.w3c.org/namespace', 'span').length, 2,
+ 'ShadowRoot getElementsByTagNameNS() method should return matching child elements');
+
+}, 'A_10_01_02_03_T06');
+
+
+test(function () {
+
+ var d = newHTMLDocument();
+
+ var el = d.createElement('div');
+ d.body.appendChild(el);
+
+ var s = el.createShadowRoot();
+
+ var child = d.createElement('span');
+ s.appendChild(child);
+
+ assert_equals(s.getElementsByTagNameNS('http://www.w3c.org/namespace','span').length, 0,
+ 'ShadowRoot getElementsByTagNameNS() method should return element from wrong namespace');
+
+}, 'A_10_01_02_03_T07');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-004.html b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-004.html
new file mode 100644
index 00000000000..53f4a2ab328
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-004.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_10_01_02_04</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#shadow-root-methods">
+<meta name="assert" content="ShadowRoot Object: Selection? getSelection() method">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(unit(function (ctx) {
+ var d = newRenderedHTMLDocument(ctx);
+
+ var host = d.createElement('div');
+ d.body.appendChild(host);
+ var s = host.createShadowRoot();
+
+ var span = d.createElement('span');
+ span.innerHTML = 'Some text';
+ s.appendChild(span);
+
+ var range = d.createRange();
+ range.setStart(span.firstChild, 0);
+ range.setEnd(span.firstChild, 3);
+
+ var selection = window.getSelection();
+ selection.removeAllRanges();
+ selection.addRange(range);
+
+ var sl = s.getSelection();
+ assert_equals(sl.toString(), 'Som', 'The getSelection() method of the shadow root object must return ' +
+ 'the current selection in this shadow tree');
+
+}), 'A_10_01_02_04_T01');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-005.html b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-005.html
new file mode 100644
index 00000000000..8ce777f5e33
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-005.html
@@ -0,0 +1,80 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_10_01_02_05</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#shadow-root-methods">
+<meta name="assert" content="ShadowRoot Object: NodeList getElementsBytagName(DOMString tagName) method">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function () {
+
+ var d = newHTMLDocument();
+
+ var el = d.createElement('div');
+ d.body.appendChild(el);
+
+ var s = el.createShadowRoot();
+
+ assert_equals(s.getElementsByTagName('span').length, 0, 'ShadowRoot getElementsByTagName() ' +
+ 'method should return empty list if there\'s no matching child elements');
+
+}, 'A_10_01_02_05_T01');
+
+
+
+test(function () {
+
+ var d = newHTMLDocument();
+
+ var el = d.createElement('div');
+ d.body.appendChild(el);
+
+ var s = el.createShadowRoot();
+
+ var child = d.createElement('span');
+ s.appendChild(child);
+
+ assert_equals(s.getElementsByTagName('span').length, 1, 'ShadowRoot getElementsByTagName() ' +
+ 'method should return matching child element');
+
+}, 'A_10_01_02_05_T02');
+
+
+test(function () {
+
+ var d = newHTMLDocument();
+
+ var el = d.createElement('div');
+ d.body.appendChild(el);
+
+ var s = el.createShadowRoot();
+
+ var child = d.createElement('span');
+ s.appendChild(child);
+
+ var child2 = d.createElement('span');
+ s.appendChild(child2);
+
+ assert_equals(s.getElementsByTagName('span').length, 2, 'ShadowRoot getElementsByTagName() ' +
+ 'method should return matching child elements');
+
+}, 'A_10_01_02_05_T03');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-006.html b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-006.html
new file mode 100644
index 00000000000..30b63067354
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-006.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_10_01_02_06_01</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#shadow-root-methods">
+<meta name="assert" content="ShadowRoot Object: Element? elementFromPoint(float x, float y) method">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function () {
+
+ var d = newHTMLDocument();
+
+ var el = d.createElement('div');
+ d.body.appendChild(el);
+
+ try {
+ el.elementFromPoint(1, 1);
+ assert_true(false, 'TypeMismatchError should be thrown');
+ } catch(e) {
+ assert_true(e instanceof TypeError, 'Wrong error type');
+ }
+
+}, 'A_10_01_02_06_01_T01');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-007.html b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-007.html
new file mode 100644
index 00000000000..eac430adec2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-007.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_10_01_02_06_02</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#shadow-root-methods">
+<meta name="assert" content="ShadowRoot Object: Element? elementFromPoint(float x, float y) method">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function () {
+
+ var d = newHTMLDocument();
+
+ var el = d.createElement('div');
+ d.body.appendChild(el);
+
+ var s = el.createShadowRoot();
+
+ var span = d.createElement('span');
+ span.innerHTML = 'Some text';
+ s.appendChild(span);
+
+ assert_equals(s.elementFromPoint(-1, 1), null, 'If x argument of elementFromPoint(x, y) is less ' +
+ 'than zero then method shold return null');
+
+}, 'A_10_01_02_06_02_T01');
+
+
+test(function () {
+
+ var d = newHTMLDocument();
+
+ var el = d.createElement('div');
+ d.body.appendChild(el);
+
+ var s = el.createShadowRoot();
+
+ var span = d.createElement('span');
+ span.innerHTML = 'Some text';
+ s.appendChild(span);
+
+ assert_equals(s.elementFromPoint(1, -1), null, 'If y argument of elementFromPoint(x, y) is less ' +
+ 'than zero then method shold return null');
+
+}, 'A_10_01_02_06_02_T02');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-010.html b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-010.html
new file mode 100644
index 00000000000..699d7237693
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/shadowroot-object/shadowroot-methods/test-010.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_10_01_02_09</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#shadow-root-methods">
+<meta name="assert" content="ShadowRoot Object: Invoking the cloneNode() method on a ShadowRoot instance must always throw a DATA_CLONE_ERR exception.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(unit(function (ctx) {
+ var d = newRenderedHTMLDocument(ctx);
+
+ var host = d.createElement('div');
+ d.body.appendChild(host);
+ var s = host.createShadowRoot();
+
+ try {
+ s.cloneNode();
+ assert_true(false, 'Invoking the cloneNode() method on a ShadowRoot instance must always ' +
+ 'throw a DATA_CLONE_ERR exception.');
+ } catch (e) {
+ assert_equals(e.code, 25, 'Wrong exceprion type');
+ }
+}), 'A_10_01_02_09_T01');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/the-content-html-element/test-001.html b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/the-content-html-element/test-001.html
new file mode 100644
index 00000000000..2b5b5692cbd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/the-content-html-element/test-001.html
@@ -0,0 +1,82 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_10_04_01</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#content-element">
+<meta name="assert" content="The content HTML element: fallback content">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ d.body.innerHTML =
+ '<ul class="cls">' +
+ '<li id="li1" class="shadow">1</li>' +
+ '<li id="li2" class="shadow2">2</li>' +
+ '<li id="li3" class="shadow">3</li>' +
+ '<li id="li4">4</li>' +
+ '<li id="li5" class="shadow">5</li>' +
+ '<li id="li6" class="shadow2">6</li>' +
+ '</ul>';
+
+ var host = d.querySelector('.cls');
+ //Shadow root to play with
+ var s = host.createShadowRoot();
+
+ var div = d.createElement('div');
+ div.innerHTML = '' +
+ '<ul><content select=".clazz"><span id="spandex">This is fallback content</span></content></ul>';
+ s.appendChild(div);
+
+ assert_true(s.querySelector('#spandex').offsetTop > 0, 'Fallback content should be rendered');
+
+}), 'A_10_04_01_T01');
+
+
+
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ d.body.innerHTML =
+ '<ul class="cls">' +
+ '<li id="li1" class="shadow">1</li>' +
+ '<li id="li2" class="shadow2">2</li>' +
+ '<li id="li3" class="shadow">3</li>' +
+ '<li id="li4">4</li>' +
+ '<li id="li5" class="shadow">5</li>' +
+ '<li id="li6" class="shadow2">6</li>' +
+ '</ul>';
+
+ var host = d.querySelector('.cls');
+ //Shadow root to play with
+ var s = host.createShadowRoot();
+
+ var div = d.createElement('div');
+ div.innerHTML = '' +
+ '<ul><content select=".shadow"><span id="spandex">This is fallback content</span></content></ul>';
+ s.appendChild(div);
+
+ assert_equals(s.querySelector('#spandex').offsetTop, 0, 'Fallback content should not be rendered');
+
+}), 'A_10_04_01_T02');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/the-content-html-element/test-002.html b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/the-content-html-element/test-002.html
new file mode 100644
index 00000000000..5eb8dc1f9cc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/the-content-html-element/test-002.html
@@ -0,0 +1,98 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_10_04_02</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#content-element">
+<meta name="assert" content="The content HTML element: select attribute">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ d.body.innerHTML =
+ '<ul class="cls">' +
+ '<li id="li1" class="shadow">1</li>' +
+ '<li id="li2" class="shadow2">2</li>' +
+ '<li id="li3" class="shadow">3</li>' +
+ '<li id="li4">4</li>' +
+ '<li id="li5" class="shadow">5</li>' +
+ '<li id="li6" class="shadow2">6</li>' +
+ '</ul>';
+
+ var host = d.querySelector('.cls');
+ //Shadow root to play with
+ var s = host.createShadowRoot();
+
+ var div = d.createElement('div');
+ div.innerHTML = '' +
+ '<ul><content select=".shadow"><span id="spandex">This is fallback content</span></content></ul>';
+ s.appendChild(div);
+
+ assert_equals(s.querySelector('#spandex').offsetTop, 0, 'Fallback content should not be rendered');
+
+ assert_equals(d.querySelector('#li2').offsetTop, 0, 'Point 1: Element should not be rendered');
+ assert_equals(d.querySelector('#li4').offsetTop, 0, 'Point 2: Element should not be rendered');
+ assert_equals(d.querySelector('#li6').offsetTop, 0, 'Point 3: Element should not be rendered');
+
+ assert_true(d.querySelector('#li1').offsetTop > 0, 'Point 11: Element should be rendered');
+ assert_true(d.querySelector('#li3').offsetTop > 0, 'Point 12: Element should be rendered');
+ assert_true(d.querySelector('#li5').offsetTop > 0, 'Point 13: Element should be rendered');
+
+}), 'A_10_04_02_T01_01');
+
+
+
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ d.body.innerHTML =
+ '<ul class="cls">' +
+ '<li id="li1" class="shadow">1</li>' +
+ '<li id="li2" class="shadow2">2</li>' +
+ '<li id="li3" class="shadow">3</li>' +
+ '<li id="li4">4</li>' +
+ '<li id="li5" class="shadow">5</li>' +
+ '<li id="li6" class="shadow2">6</li>' +
+ '</ul>';
+
+ var host = d.querySelector('.cls');
+ //Shadow root to play with
+ var s = host.createShadowRoot();
+
+ var div = d.createElement('div');
+ div.innerHTML = '' +
+ '<ul><content select=".shadow, #li4"><span id="spandex">This is fallback content</span></content></ul>';
+ s.appendChild(div);
+
+ assert_equals(s.querySelector('#spandex').offsetTop, 0, 'Fallback content should not be rendered');
+
+ assert_equals(d.querySelector('#li2').offsetTop, 0, 'Point 1: Element should not be rendered');
+ assert_equals(d.querySelector('#li6').offsetTop, 0, 'Point 2: Element should not be rendered');
+
+ assert_true(d.querySelector('#li1').offsetTop > 0, 'Point 11: Element should be rendered');
+ assert_true(d.querySelector('#li3').offsetTop > 0, 'Point 12: Element should be rendered');
+ assert_true(d.querySelector('#li5').offsetTop > 0, 'Point 13: Element should be rendered');
+ assert_true(d.querySelector('#li4').offsetTop > 0, 'Point 14: Element should be rendered');
+
+}), 'A_10_04_02_T01_02');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/the-content-html-element/test-003.html b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/the-content-html-element/test-003.html
new file mode 100644
index 00000000000..00461ef8a6c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/the-content-html-element/test-003.html
@@ -0,0 +1,130 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_10_04_03</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#content-element">
+<meta name="assert" content="The content HTML element: invalid select attribute">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ d.body.innerHTML =
+ '<ul class="cls">' +
+ '<li id="li1" class="shadow">1</li>' +
+ '<li id="li2" class="shadow2">2</li>' +
+ '<li id="li3" class="shadow">3</li>' +
+ '<li id="li4">4</li>' +
+ '<li id="li5" class="shadow">5</li>' +
+ '<li id="li6" class="shadow2">6</li>' +
+ '</ul>';
+
+ var host = d.querySelector('.cls');
+ //Shadow root to play with
+ var s = host.createShadowRoot();
+
+ var div = d.createElement('div');
+ div.innerHTML = '' +
+ '<ul><content select="&@()"><span id="spandex">This is fallback content</span></content></ul>';
+ s.appendChild(div);
+
+ assert_true(s.querySelector('#spandex').offsetTop > 0, 'Fallback content should be rendered');
+
+ assert_equals(d.querySelector('#li1').offsetTop, 0, 'Point 1: Element should not be rendered');
+ assert_equals(d.querySelector('#li2').offsetTop, 0, 'Point 2: Element should not be rendered');
+ assert_equals(d.querySelector('#li3').offsetTop, 0, 'Point 3: Element should not be rendered');
+ assert_equals(d.querySelector('#li4').offsetTop, 0, 'Point 4: Element should not be rendered');
+ assert_equals(d.querySelector('#li5').offsetTop, 0, 'Point 5: Element should not be rendered');
+ assert_equals(d.querySelector('#li6').offsetTop, 0, 'Point 6: Element should not be rendered');
+
+}), 'A_10_04_03_T01');
+
+
+test(unit(function (ctx) {
+
+var d = newRenderedHTMLDocument(ctx);
+
+ d.body.innerHTML =
+ '<ul class="cls">' +
+ '<li id="li1" class="shadow">1</li>' +
+ '<li id="li2" class="shadow2">2</li>' +
+ '<li id="li3" class="shadow">3</li>' +
+ '<li id="li4">4</li>' +
+ '<li id="li5" class="shadow">5</li>' +
+ '<li id="li6" class="shadow2">6</li>' +
+ '</ul>';
+
+ var host = d.querySelector('.cls');
+ //Shadow root to play with
+ var s = host.createShadowRoot();
+
+ var div = d.createElement('div');
+ div.innerHTML = '' +
+ '<ul><content select=".shadow, &@()"><span id="spandex">This is fallback content</span></content></ul>';
+ s.appendChild(div);
+
+ assert_true(s.querySelector('#spandex').offsetTop > 0, 'Fallback content should be rendered');
+
+ assert_equals(d.querySelector('#li1').offsetTop, 0, 'Point 1: Element should not be rendered');
+ assert_equals(d.querySelector('#li2').offsetTop, 0, 'Point 2: Element should not be rendered');
+ assert_equals(d.querySelector('#li3').offsetTop, 0, 'Point 3: Element should not be rendered');
+ assert_equals(d.querySelector('#li4').offsetTop, 0, 'Point 4: Element should not be rendered');
+ assert_equals(d.querySelector('#li5').offsetTop, 0, 'Point 5: Element should not be rendered');
+ assert_equals(d.querySelector('#li6').offsetTop, 0, 'Point 6: Element should not be rendered');
+
+}), 'A_10_04_03_T02');
+
+
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ d.body.innerHTML =
+ '<ul class="cls">' +
+ '<li id="li1" class="shadow">1</li>' +
+ '<li id="li2" class="shadow2">2</li>' +
+ '<li id="li3" class="shadow">3</li>' +
+ '<li id="li4">4</li>' +
+ '<li id="li5" class="shadow">5</li>' +
+ '<li id="li6" class="shadow2">6</li>' +
+ '</ul>';
+
+ var host = d.querySelector('.cls');
+ //Shadow root to play with
+ var s = host.createShadowRoot();
+
+ var div = d.createElement('div');
+ div.innerHTML = '' +
+ '<ul><content select=".shadow, &@(), #li4"><span id="spandex">This is fallback content</span></content></ul>';
+ s.appendChild(div);
+
+ assert_true(s.querySelector('#spandex').offsetTop > 0, 'Fallback content should be rendered');
+
+ assert_equals(d.querySelector('#li1').offsetTop, 0, 'Point 1: Element should not be rendered');
+ assert_equals(d.querySelector('#li2').offsetTop, 0, 'Point 2: Element should not be rendered');
+ assert_equals(d.querySelector('#li3').offsetTop, 0, 'Point 3: Element should not be rendered');
+ assert_equals(d.querySelector('#li4').offsetTop, 0, 'Point 4: Element should not be rendered');
+ assert_equals(d.querySelector('#li5').offsetTop, 0, 'Point 5: Element should not be rendered');
+ assert_equals(d.querySelector('#li6').offsetTop, 0, 'Point 6: Element should not be rendered');
+
+}), 'A_10_04_03_T03');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/the-content-html-element/test-004.html b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/the-content-html-element/test-004.html
new file mode 100644
index 00000000000..cb08e7a999f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/the-content-html-element/test-004.html
@@ -0,0 +1,163 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_10_04_04</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#content-element">
+<meta name="assert" content="The content HTML element: reset-style-inheritance attribute">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ d.body.innerHTML =
+ '<ul id="shHost">' +
+ '<li id="li1" class="shadow">1</li>' +
+ '<li id="li2" class="shadow2">2</li>' +
+ '<li id="li3" class="shadow">3</li>' +
+ '<li id="li4">4</li>' +
+ '<li id="li5" class="shadow">5</li>' +
+ '<li id="li6" class="shadow2">6</li>' +
+ '</ul>';
+
+
+ var defHeight1 = d.querySelector('#li1').offsetHeight;
+ var defHeight2 = d.querySelector('#li2').offsetHeight;
+ var defHeight3 = d.querySelector('#li3').offsetHeight;
+ var defHeight4 = d.querySelector('#li4').offsetHeight;
+ var defHeight5 = d.querySelector('#li5').offsetHeight;
+ var defHeight6 = d.querySelector('#li6').offsetHeight;
+
+ assert_true(defHeight1 > 0, 'Point 1: Element height should be greater than zero');
+ assert_true(defHeight2 > 0, 'Point 2: Element height should be greater than zero');
+ assert_true(defHeight3 > 0, 'Point 3: Element height should be greater than zero');
+ assert_true(defHeight4 > 0, 'Point 4: Element height should be greater than zero');
+ assert_true(defHeight5 > 0, 'Point 5: Element height should be greater than zero');
+ assert_true(defHeight6 > 0, 'Point 6: Element height should be greater than zero');
+
+ var host = d.querySelector('#shHost');
+
+ d.body.setAttribute('style', 'font-size: 30px');
+
+ var height1 = d.querySelector('#li1').offsetHeight;
+ var height2 = d.querySelector('#li2').offsetHeight;
+ var height3 = d.querySelector('#li3').offsetHeight;
+ var height4 = d.querySelector('#li4').offsetHeight;
+ var height5 = d.querySelector('#li5').offsetHeight;
+ var height6 = d.querySelector('#li6').offsetHeight;
+
+
+ assert_true(height1 > defHeight1, 'Point 11: Element height should be changed');
+ assert_true(height2 > defHeight2, 'Point 12: Element height should be changed');
+ assert_true(height3 > defHeight3, 'Point 13: Element height should be changed');
+ assert_true(height4 > defHeight4, 'Point 14: Element height should be changed');
+ assert_true(height5 > defHeight5, 'Point 15: Element height should be changed');
+ assert_true(height6 > defHeight6, 'Point 16: Element height should be changed');
+
+ //Shadow root to play with
+ var s = host.createShadowRoot();
+
+ var div = d.createElement('div');
+ div.innerHTML ='<ul><content select=".shadow" reset-style-inheritance=true></content></ul>';
+ s.appendChild(div);
+
+ assert_equals(d.querySelector('#li1').offsetHeight, defHeight1, 'Point 21: Inherited ' +
+ 'element style should be reset');
+ assert_equals(d.querySelector('#li3').offsetHeight, defHeight3, 'Point 22: Inherited ' +
+ 'element style should be reset');
+ assert_equals(d.querySelector('#li5').offsetHeight, defHeight5, 'Point 23: Inherited ' +
+ 'element style should be reset');
+
+ assert_equals(d.querySelector('#li2').offsetHeight, 0, 'Point 24: Element shouldn\'t be rendered');
+ assert_equals(d.querySelector('#li4').offsetHeight, 0, 'Point 25: Element shouldn\'t be rendered');
+ assert_equals(d.querySelector('#li6').offsetHeight, 0, 'Point 26: Element shouldn\'t be rendered');
+
+}), 'A_10_04_04_T01');
+
+
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ d.body.innerHTML =
+ '<ul id="shHost">' +
+ '<li id="li1" class="shadow">1</li>' +
+ '<li id="li2" class="shadow2">2</li>' +
+ '<li id="li3" class="shadow">3</li>' +
+ '<li id="li4">4</li>' +
+ '<li id="li5" class="shadow">5</li>' +
+ '<li id="li6" class="shadow2">6</li>' +
+ '</ul>';
+
+
+ var defHeight1 = d.querySelector('#li1').offsetHeight;
+ var defHeight2 = d.querySelector('#li2').offsetHeight;
+ var defHeight3 = d.querySelector('#li3').offsetHeight;
+ var defHeight4 = d.querySelector('#li4').offsetHeight;
+ var defHeight5 = d.querySelector('#li5').offsetHeight;
+ var defHeight6 = d.querySelector('#li6').offsetHeight;
+
+ assert_true(defHeight1 > 0, 'Point 1: Element height should be greater than zero');
+ assert_true(defHeight2 > 0, 'Point 2: Element height should be greater than zero');
+ assert_true(defHeight3 > 0, 'Point 3: Element height should be greater than zero');
+ assert_true(defHeight4 > 0, 'Point 4: Element height should be greater than zero');
+ assert_true(defHeight5 > 0, 'Point 5: Element height should be greater than zero');
+ assert_true(defHeight6 > 0, 'Point 6: Element height should be greater than zero');
+
+ var host = d.querySelector('#shHost');
+
+ d.body.setAttribute('style', 'font-size: 30px');
+
+ var height1 = d.querySelector('#li1').offsetHeight;
+ var height2 = d.querySelector('#li2').offsetHeight;
+ var height3 = d.querySelector('#li3').offsetHeight;
+ var height4 = d.querySelector('#li4').offsetHeight;
+ var height5 = d.querySelector('#li5').offsetHeight;
+ var height6 = d.querySelector('#li6').offsetHeight;
+
+
+ assert_true(height1 > defHeight1, 'Point 11: Element height should be changed');
+ assert_true(height2 > defHeight2, 'Point 12: Element height should be changed');
+ assert_true(height3 > defHeight3, 'Point 13: Element height should be changed');
+ assert_true(height4 > defHeight4, 'Point 14: Element height should be changed');
+ assert_true(height5 > defHeight5, 'Point 15: Element height should be changed');
+ assert_true(height6 > defHeight6, 'Point 16: Element height should be changed');
+
+ //Shadow root to play with
+ var s = host.createShadowRoot();
+
+ var div = d.createElement('div');
+ div.innerHTML ='<ul><content select=".shadow" reset-style-inheritance></content></ul>';
+ s.appendChild(div);
+
+ assert_equals(d.querySelector('#li1').offsetHeight, defHeight1, 'Point 21: Inherited ' +
+ 'element style should be reset');
+ assert_equals(d.querySelector('#li3').offsetHeight, defHeight3, 'Point 22: Inherited ' +
+ 'element style should be reset');
+ assert_equals(d.querySelector('#li5').offsetHeight, defHeight5, 'Point 23: Inherited ' +
+ 'element style should be reset');
+
+ assert_equals(d.querySelector('#li2').offsetHeight, 0, 'Point 24: Element shouldn\'t be rendered');
+ assert_equals(d.querySelector('#li4').offsetHeight, 0, 'Point 25: Element shouldn\'t be rendered');
+ assert_equals(d.querySelector('#li6').offsetHeight, 0, 'Point 26: Element shouldn\'t be rendered');
+
+}), 'A_10_04_04_T02');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/the-content-html-element/test-005.html b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/the-content-html-element/test-005.html
new file mode 100644
index 00000000000..9d24c6e0f18
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/the-content-html-element/test-005.html
@@ -0,0 +1,94 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_10_04_05</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#content-element">
+<meta name="assert" content="The content HTML element: reset-style-inheritance attribute">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ d.body.innerHTML =
+ '<ul id="shHost">' +
+ '<li id="li1" class="shadow">1</li>' +
+ '<li id="li2" class="shadow2">2</li>' +
+ '<li id="li3" class="shadow">3</li>' +
+ '<li id="li4">4</li>' +
+ '<li id="li5" class="shadow">5</li>' +
+ '<li id="li6" class="shadow2">6</li>' +
+ '</ul>';
+
+
+ var defHeight1 = d.querySelector('#li1').offsetHeight;
+ var defHeight2 = d.querySelector('#li2').offsetHeight;
+ var defHeight3 = d.querySelector('#li3').offsetHeight;
+ var defHeight4 = d.querySelector('#li4').offsetHeight;
+ var defHeight5 = d.querySelector('#li5').offsetHeight;
+ var defHeight6 = d.querySelector('#li6').offsetHeight;
+
+ assert_true(defHeight1 > 0, 'Point 1: Element height should be greater than zero');
+ assert_true(defHeight2 > 0, 'Point 2: Element height should be greater than zero');
+ assert_true(defHeight3 > 0, 'Point 3: Element height should be greater than zero');
+ assert_true(defHeight4 > 0, 'Point 4: Element height should be greater than zero');
+ assert_true(defHeight5 > 0, 'Point 5: Element height should be greater than zero');
+ assert_true(defHeight6 > 0, 'Point 6: Element height should be greater than zero');
+
+ var host = d.querySelector('#shHost');
+
+ d.body.setAttribute('style', 'font-size: 30px');
+
+ var height1 = d.querySelector('#li1').offsetHeight;
+ var height2 = d.querySelector('#li2').offsetHeight;
+ var height3 = d.querySelector('#li3').offsetHeight;
+ var height4 = d.querySelector('#li4').offsetHeight;
+ var height5 = d.querySelector('#li5').offsetHeight;
+ var height6 = d.querySelector('#li6').offsetHeight;
+
+
+ assert_true(height1 > defHeight1, 'Point 11: Element height should be changed');
+ assert_true(height2 > defHeight2, 'Point 12: Element height should be changed');
+ assert_true(height3 > defHeight3, 'Point 13: Element height should be changed');
+ assert_true(height4 > defHeight4, 'Point 14: Element height should be changed');
+ assert_true(height5 > defHeight5, 'Point 15: Element height should be changed');
+ assert_true(height6 > defHeight6, 'Point 16: Element height should be changed');
+
+ //Shadow root to play with
+ var s = host.createShadowRoot();
+
+ var div = d.createElement('div');
+ div.innerHTML ='<ul><content select=".shadow"></content></ul>';
+ s.appendChild(div);
+
+ assert_equals(d.querySelector('#li1').offsetHeight, height1, 'Point 21: Inherited ' +
+ 'element style should be reset');
+ assert_equals(d.querySelector('#li3').offsetHeight, height3, 'Point 22: Inherited ' +
+ 'element style should be reset');
+ assert_equals(d.querySelector('#li5').offsetHeight, height5, 'Point 23: Inherited ' +
+ 'element style should be reset');
+
+ assert_equals(d.querySelector('#li2').offsetHeight, 0, 'Point 24: Element shouldn\'t be rendered');
+ assert_equals(d.querySelector('#li4').offsetHeight, 0, 'Point 25: Element shouldn\'t be rendered');
+ assert_equals(d.querySelector('#li6').offsetHeight, 0, 'Point 26: Element shouldn\'t be rendered');
+
+}), 'A_10_04_05_T01');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/the-content-html-element/test-006.html b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/the-content-html-element/test-006.html
new file mode 100644
index 00000000000..67a57bcf331
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/the-content-html-element/test-006.html
@@ -0,0 +1,94 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_10_04_06</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#content-element">
+<meta name="assert" content="The content HTML element: getDistributedNodes method">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ d.body.innerHTML =
+ '<ul class="cls">' +
+ '<li id="li1" class="shadow">1</li>' +
+ '<li id="li2" class="shadow2">2</li>' +
+ '<li id="li3" class="shadow">3</li>' +
+ '<li id="li4">4</li>' +
+ '<li id="li5" class="shadow">5</li>' +
+ '<li id="li6" class="shadow2">6</li>' +
+ '</ul>';
+
+ var host = d.querySelector('.cls');
+ //Shadow root to play with
+ var s = host.createShadowRoot();
+
+ var div = d.createElement('div');
+ div.innerHTML = '' +
+ '<ul><content id="contentId" select=".clazz"><span id="spandex">This is fallback content</span></content></ul>';
+ s.appendChild(div);
+
+ assert_equals(s.querySelector('#contentId').getDistributedNodes().length, 1,
+ 'Fallback content should show up as distributed nodes');
+
+ assert_equals(s.querySelector('#contentId').getDistributedNodes()[0].id, 'spandex',
+ 'Fallback content should show up as distributed nodes');
+
+}), 'A_10_04_06_T01');
+
+
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ d.body.innerHTML =
+ '<ul class="cls">' +
+ '<li id="li1" class="shadow">1</li>' +
+ '<li id="li2" class="shadow2">2</li>' +
+ '<li id="li3" class="shadow">3</li>' +
+ '<li id="li4">4</li>' +
+ '<li id="li5" class="shadow">5</li>' +
+ '<li id="li6" class="shadow2">6</li>' +
+ '</ul>';
+
+ var host = d.querySelector('.cls');
+ //Shadow root to play with
+ var s = host.createShadowRoot();
+
+ var div = d.createElement('div');
+ div.innerHTML = '' +
+ '<ul><content id="contentId" select=".shadow"><span id="spandex">This is fallback content</span></content></ul>';
+ s.appendChild(div);
+
+ assert_equals(s.querySelector('#contentId').getDistributedNodes().length, 3,
+ 'Wrond distributed nodes collection size');
+
+ assert_equals(s.querySelector('#contentId').getDistributedNodes()[0].getAttribute('id'), 'li1',
+ 'Point 1: wrong element in distributed nodes collection');
+ assert_equals(s.querySelector('#contentId').getDistributedNodes()[1].getAttribute('id'), 'li3',
+ 'Point 2: wrong element in distributed nodes collection');
+ assert_equals(s.querySelector('#contentId').getDistributedNodes()[2].getAttribute('id'), 'li5',
+ 'Point 3: wrong element in distributed nodes collection');
+
+
+}), 'A_10_04_06_T02');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/the-shadow-html-element/test-001.html b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/the-shadow-html-element/test-001.html
new file mode 100644
index 00000000000..5349a6a198e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/the-shadow-html-element/test-001.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_10_05_01</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#shadow-element">
+<meta name="assert" content="The shadow HTML element: fallback content">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var host = d.createElement('div');
+ d.body.appendChild(host);
+
+ //Shadow root to play with
+ var s = host.createShadowRoot();
+
+ var div = d.createElement('div');
+ div.innerHTML = '' +
+ '<span id="spandex">This is a shadow root content</span>' +
+ '<shadow><span id="shadowId">This is a shadow fallback content</span></shadow>';
+ s.appendChild(div);
+
+ assert_true(s.querySelector('#shadowId').offsetTop == 0, 'Shadow fallback content should not be rendered in this case');
+
+}), 'A_10_05_01_T01');
+
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var host = d.createElement('div');
+ d.body.appendChild(host);
+
+ //Shadow root to play with
+ var s = host.createShadowRoot();
+
+ var div = d.createElement('div');
+ div.innerHTML = '' +
+ '<span id="spandex">This is a shadow root content</span>' +
+ '<content><span id="contentId">This is a content fallback</span></content>';
+ s.appendChild(div);
+
+ assert_true(s.querySelector('#contentId').offsetTop > 0, 'Fallback content should be rendered');
+
+}), 'A_10_05_01_T02');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/the-shadow-html-element/test-002.html b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/the-shadow-html-element/test-002.html
new file mode 100644
index 00000000000..6cd360b1680
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/the-shadow-html-element/test-002.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_10_05_02</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#shadow-element">
+<meta name="assert" content="The shadow HTML element: shadow insertion point">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var host = d.createElement('div');
+ d.body.appendChild(host);
+
+ //old tree
+ var s1 = host.createShadowRoot();
+ s1.innerHTML = '<span id="sp1">This is an old tree</span>';
+ //young tree
+ var s2 = host.createShadowRoot();
+
+ var div = d.createElement('div');
+ div.innerHTML = '' +
+ '<span id="spandex">This is a shadow root content</span>' +
+ '<shadow><span id="shadowId">This is a shadow fallback content</span></shadow>';
+ s2.appendChild(div);
+
+ assert_equals(s2.querySelector('#shadowId').offsetTop, 0, 'Fallback content should not be rendered');
+ assert_true(s1.querySelector('#sp1').offsetTop > 0, 'Old tree should be rendered');
+ assert_true(s2.querySelector('#spandex').offsetTop > 0, 'Element should be rendered');
+
+}), 'A_10_05_02_T01');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/the-shadow-html-element/test-003.html b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/the-shadow-html-element/test-003.html
new file mode 100644
index 00000000000..0c1561a6db8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/the-shadow-html-element/test-003.html
@@ -0,0 +1,189 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_10_05_03</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#shadow-element">
+<meta name="assert" content="The shadow HTML element: reset-style-inheritance attribute">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+// test reset-style-inheritance=true
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ d.body.innerHTML =
+ '<ul id="shHost">' +
+ '<li id="li1" class="shadow">1</li>' +
+ '<li id="li2" class="shadow2">2</li>' +
+ '<li id="li3" class="shadow">3</li>' +
+ '<li id="li4">4</li>' +
+ '<li id="li5" class="shadow">5</li>' +
+ '<li id="li6" class="shadow2">6</li>' +
+ '</ul>';
+
+
+ var defHeight1 = d.querySelector('#li1').offsetHeight;
+ var defHeight2 = d.querySelector('#li2').offsetHeight;
+ var defHeight3 = d.querySelector('#li3').offsetHeight;
+ var defHeight4 = d.querySelector('#li4').offsetHeight;
+ var defHeight5 = d.querySelector('#li5').offsetHeight;
+ var defHeight6 = d.querySelector('#li6').offsetHeight;
+
+ assert_true(defHeight1 > 0, 'Point 1: Element height should be greater than zero');
+ assert_true(defHeight2 > 0, 'Point 2: Element height should be greater than zero');
+ assert_true(defHeight3 > 0, 'Point 3: Element height should be greater than zero');
+ assert_true(defHeight4 > 0, 'Point 4: Element height should be greater than zero');
+ assert_true(defHeight5 > 0, 'Point 5: Element height should be greater than zero');
+ assert_true(defHeight6 > 0, 'Point 6: Element height should be greater than zero');
+
+ var host = d.querySelector('#shHost');
+
+ d.body.setAttribute('style', 'font-size: 30px');
+
+ var height1 = d.querySelector('#li1').offsetHeight;
+ var height2 = d.querySelector('#li2').offsetHeight;
+ var height3 = d.querySelector('#li3').offsetHeight;
+ var height4 = d.querySelector('#li4').offsetHeight;
+ var height5 = d.querySelector('#li5').offsetHeight;
+ var height6 = d.querySelector('#li6').offsetHeight;
+
+
+ assert_true(height1 > defHeight1, 'Point 11: Element height should be changed');
+ assert_true(height2 > defHeight2, 'Point 12: Element height should be changed');
+ assert_true(height3 > defHeight3, 'Point 13: Element height should be changed');
+ assert_true(height4 > defHeight4, 'Point 14: Element height should be changed');
+ assert_true(height5 > defHeight5, 'Point 15: Element height should be changed');
+ assert_true(height6 > defHeight6, 'Point 16: Element height should be changed');
+
+ //Shadow root to play with
+ var s = host.createShadowRoot();
+
+ var div = d.createElement('div');
+ div.innerHTML ='<ul><content select=".shadow"></content></ul>';
+ s.appendChild(div);
+
+ assert_equals(d.querySelector('#li1').offsetHeight, height1, 'Point 21: Element height should not be changed');
+ assert_equals(d.querySelector('#li3').offsetHeight, height3, 'Point 22: Element height should not be changed');
+ assert_equals(d.querySelector('#li5').offsetHeight, height5, 'Point 23: Element height should not be changed');
+
+ assert_equals(d.querySelector('#li2').offsetHeight, 0, 'Point 24: Element shouldn\'t be rendered');
+ assert_equals(d.querySelector('#li4').offsetHeight, 0, 'Point 25: Element shouldn\'t be rendered');
+ assert_equals(d.querySelector('#li6').offsetHeight, 0, 'Point 26: Element shouldn\'t be rendered');
+
+ //Young tree
+ var s2 = host.createShadowRoot();
+
+ var div2 = d.createElement('div');
+ div2.innerHTML = '<shadow reset-style-inheritance=true></shadow>';
+ s2.appendChild(div2);
+
+ //styles should be reset
+ assert_equals(d.querySelector('#li1').offsetHeight, defHeight1, 'Point 31: Inherited ' +
+ 'element style should be reset');
+ assert_equals(d.querySelector('#li3').offsetHeight, defHeight3, 'Point 32: Inherited ' +
+ 'element style should be reset');
+ assert_equals(d.querySelector('#li5').offsetHeight, defHeight5, 'Point 33: Inherited ' +
+ 'element style should be reset');
+
+}), 'A_10_05_03_T01');
+
+
+//test reset-style-inheritance
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ d.body.innerHTML =
+ '<ul id="shHost">' +
+ '<li id="li1" class="shadow">1</li>' +
+ '<li id="li2" class="shadow2">2</li>' +
+ '<li id="li3" class="shadow">3</li>' +
+ '<li id="li4">4</li>' +
+ '<li id="li5" class="shadow">5</li>' +
+ '<li id="li6" class="shadow2">6</li>' +
+ '</ul>';
+
+
+ var defHeight1 = d.querySelector('#li1').offsetHeight;
+ var defHeight2 = d.querySelector('#li2').offsetHeight;
+ var defHeight3 = d.querySelector('#li3').offsetHeight;
+ var defHeight4 = d.querySelector('#li4').offsetHeight;
+ var defHeight5 = d.querySelector('#li5').offsetHeight;
+ var defHeight6 = d.querySelector('#li6').offsetHeight;
+
+ assert_true(defHeight1 > 0, 'Point 1: Element height should be greater than zero');
+ assert_true(defHeight2 > 0, 'Point 2: Element height should be greater than zero');
+ assert_true(defHeight3 > 0, 'Point 3: Element height should be greater than zero');
+ assert_true(defHeight4 > 0, 'Point 4: Element height should be greater than zero');
+ assert_true(defHeight5 > 0, 'Point 5: Element height should be greater than zero');
+ assert_true(defHeight6 > 0, 'Point 6: Element height should be greater than zero');
+
+ var host = d.querySelector('#shHost');
+
+ d.body.setAttribute('style', 'font-size: 30px');
+
+ var height1 = d.querySelector('#li1').offsetHeight;
+ var height2 = d.querySelector('#li2').offsetHeight;
+ var height3 = d.querySelector('#li3').offsetHeight;
+ var height4 = d.querySelector('#li4').offsetHeight;
+ var height5 = d.querySelector('#li5').offsetHeight;
+ var height6 = d.querySelector('#li6').offsetHeight;
+
+
+ assert_true(height1 > defHeight1, 'Point 11: Element height should be changed');
+ assert_true(height2 > defHeight2, 'Point 12: Element height should be changed');
+ assert_true(height3 > defHeight3, 'Point 13: Element height should be changed');
+ assert_true(height4 > defHeight4, 'Point 14: Element height should be changed');
+ assert_true(height5 > defHeight5, 'Point 15: Element height should be changed');
+ assert_true(height6 > defHeight6, 'Point 16: Element height should be changed');
+
+ //Shadow root to play with
+ var s = host.createShadowRoot();
+
+ var div = d.createElement('div');
+ div.innerHTML ='<ul><content select=".shadow"></content></ul>';
+ s.appendChild(div);
+
+ assert_equals(d.querySelector('#li1').offsetHeight, height1, 'Point 21: Element height should not be changed');
+ assert_equals(d.querySelector('#li3').offsetHeight, height3, 'Point 22: Element height should not be changed');
+ assert_equals(d.querySelector('#li5').offsetHeight, height5, 'Point 23: Element height should not be changed');
+
+ assert_equals(d.querySelector('#li2').offsetHeight, 0, 'Point 24: Element shouldn\'t be rendered');
+ assert_equals(d.querySelector('#li4').offsetHeight, 0, 'Point 25: Element shouldn\'t be rendered');
+ assert_equals(d.querySelector('#li6').offsetHeight, 0, 'Point 26: Element shouldn\'t be rendered');
+
+ //Young tree
+ var s2 = host.createShadowRoot();
+
+ var div2 = d.createElement('div');
+ div2.innerHTML = '<shadow reset-style-inheritance></shadow>';
+ s2.appendChild(div2);
+
+ //styles should be reset
+ assert_equals(d.querySelector('#li1').offsetHeight, defHeight1, 'Point 31: Inherited ' +
+ 'element style should be reset');
+ assert_equals(d.querySelector('#li3').offsetHeight, defHeight3, 'Point 32: Inherited ' +
+ 'element style should be reset');
+ assert_equals(d.querySelector('#li5').offsetHeight, defHeight5, 'Point 33: Inherited ' +
+ 'element style should be reset');
+
+}), 'A_10_05_03_T02');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/the-shadow-html-element/test-004.html b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/the-shadow-html-element/test-004.html
new file mode 100644
index 00000000000..199b1c551df
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/elements-and-dom-objects/the-shadow-html-element/test-004.html
@@ -0,0 +1,107 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_10_05_04</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#shadow-element">
+<meta name="assert" content="The shadow HTML element: no reset-style-inheritance attribute">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+// test no reset-style-inheritance
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ d.body.innerHTML =
+ '<ul id="shHost">' +
+ '<li id="li1" class="shadow">1</li>' +
+ '<li id="li2" class="shadow2">2</li>' +
+ '<li id="li3" class="shadow">3</li>' +
+ '<li id="li4">4</li>' +
+ '<li id="li5" class="shadow">5</li>' +
+ '<li id="li6" class="shadow2">6</li>' +
+ '</ul>';
+
+
+ var defHeight1 = d.querySelector('#li1').offsetHeight;
+ var defHeight2 = d.querySelector('#li2').offsetHeight;
+ var defHeight3 = d.querySelector('#li3').offsetHeight;
+ var defHeight4 = d.querySelector('#li4').offsetHeight;
+ var defHeight5 = d.querySelector('#li5').offsetHeight;
+ var defHeight6 = d.querySelector('#li6').offsetHeight;
+
+ assert_true(defHeight1 > 0, 'Point 1: Element height should be greater than zero');
+ assert_true(defHeight2 > 0, 'Point 2: Element height should be greater than zero');
+ assert_true(defHeight3 > 0, 'Point 3: Element height should be greater than zero');
+ assert_true(defHeight4 > 0, 'Point 4: Element height should be greater than zero');
+ assert_true(defHeight5 > 0, 'Point 5: Element height should be greater than zero');
+ assert_true(defHeight6 > 0, 'Point 6: Element height should be greater than zero');
+
+ var host = d.querySelector('#shHost');
+
+ d.body.setAttribute('style', 'font-size: 30px');
+
+ var height1 = d.querySelector('#li1').offsetHeight;
+ var height2 = d.querySelector('#li2').offsetHeight;
+ var height3 = d.querySelector('#li3').offsetHeight;
+ var height4 = d.querySelector('#li4').offsetHeight;
+ var height5 = d.querySelector('#li5').offsetHeight;
+ var height6 = d.querySelector('#li6').offsetHeight;
+
+
+ assert_true(height1 > defHeight1, 'Point 11: Element height should be changed');
+ assert_true(height2 > defHeight2, 'Point 12: Element height should be changed');
+ assert_true(height3 > defHeight3, 'Point 13: Element height should be changed');
+ assert_true(height4 > defHeight4, 'Point 14: Element height should be changed');
+ assert_true(height5 > defHeight5, 'Point 15: Element height should be changed');
+ assert_true(height6 > defHeight6, 'Point 16: Element height should be changed');
+
+ //Shadow root to play with
+ var s = host.createShadowRoot();
+
+ var div = d.createElement('div');
+ div.innerHTML ='<ul><content select=".shadow"></content></ul>';
+ s.appendChild(div);
+
+ assert_equals(d.querySelector('#li1').offsetHeight, height1, 'Point 21: Element height should not be changed');
+ assert_equals(d.querySelector('#li3').offsetHeight, height3, 'Point 22: Element height should not be changed');
+ assert_equals(d.querySelector('#li5').offsetHeight, height5, 'Point 23: Element height should not be changed');
+
+ assert_equals(d.querySelector('#li2').offsetHeight, 0, 'Point 24: Element shouldn\'t be rendered');
+ assert_equals(d.querySelector('#li4').offsetHeight, 0, 'Point 25: Element shouldn\'t be rendered');
+ assert_equals(d.querySelector('#li6').offsetHeight, 0, 'Point 26: Element shouldn\'t be rendered');
+
+ //Young tree
+ var s2 = host.createShadowRoot();
+
+ var div2 = d.createElement('div');
+ div2.innerHTML = '<shadow></shadow>';
+ s2.appendChild(div2);
+
+ //styles should be reset
+ assert_equals(d.querySelector('#li1').offsetHeight, height1, 'Point 31: Inherited ' +
+ 'element style should not be reset');
+ assert_equals(d.querySelector('#li3').offsetHeight, height3, 'Point 32: Inherited ' +
+ 'element style should not be reset');
+ assert_equals(d.querySelector('#li5').offsetHeight, height5, 'Point 33: Inherited ' +
+ 'element style should not be reset');
+
+}), 'A_10_05_04_T01');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/events/event-dispatch/test-001.html b/tests/wpt/web-platform-tests/shadow-dom/events/event-dispatch/test-001.html
new file mode 100644
index 00000000000..54b2b566d43
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/events/event-dispatch/test-001.html
@@ -0,0 +1,258 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_05_05_01</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#event-dispatch">
+<meta name="assert" content="Event Dispatch: At the time of event dispatch:The Event target and currentTarget attributes must return the relative target for the node on which event listeners are invoked">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_05_05_01_T01 = async_test('A_05_05_01_T01');
+
+A_05_05_01_T01.step(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var invoked = false;
+
+ roots = createTestMediaPlayer(d);
+
+ //expected result of what relative target should be see
+ //see at http://www.w3.org/TR/shadow-dom/#event-retargeting-example
+
+ //For #volume-slider-thumb relative target #volume-slider-thumb
+ roots.volumeShadowRoot.querySelector('#volume-slider-thumb').addEventListener('click',
+ A_05_05_01_T01.step_func(function(event) {
+ invoked = true;
+ assert_equals(event.target.getAttribute('id'), 'volume-slider-thumb',
+ 'Point 1: Wrong target');
+ assert_equals(event.currentTarget.getAttribute('id'), 'volume-slider-thumb',
+ 'Point 1: Wrong currentTarget');
+ }), false);
+
+ var event = d.createEvent('HTMLEvents');
+ event.initEvent ('click', true, false);
+ roots.volumeShadowRoot.querySelector('#volume-slider-thumb').dispatchEvent(event);
+
+ assert_true(invoked, 'Event listener was not invoked');
+
+ A_05_05_01_T01.done();
+}));
+
+
+var A_05_05_01_T02 = async_test('A_05_05_01_T02');
+
+A_05_05_01_T02.step(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var invoked = false;
+
+ roots = createTestMediaPlayer(d);
+
+ //expected result of what relative target should be see
+ //see at http://www.w3.org/TR/shadow-dom/#event-retargeting-example
+
+ //For #volume-shadow-root relative target #volume-slider-thumb
+ roots.volumeShadowRoot.addEventListener('click',
+ A_05_05_01_T02.step_func(function(event) {
+ invoked = true;
+ assert_equals(event.target.getAttribute('id'), 'volume-slider-thumb',
+ 'Wrong target');
+ assert_true(event.currentTarget == roots.volumeShadowRoot,
+ 'Wrong currentTarget');
+ }), false);
+
+ var event = d.createEvent('HTMLEvents');
+ event.initEvent ('click', true, false);
+ roots.volumeShadowRoot.querySelector('#volume-slider-thumb').dispatchEvent(event);
+
+ assert_true(invoked, 'Event listener was not invoked');
+
+ A_05_05_01_T02.done();
+}));
+
+
+var A_05_05_01_T03 = async_test('A_05_05_01_T03');
+
+A_05_05_01_T03.step(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var invoked = false;
+
+ roots = createTestMediaPlayer(d);
+
+ //expected result of what relative target should be see
+ //see at http://www.w3.org/TR/shadow-dom/#event-retargeting-example
+
+ //For #volume-slider relative target #volume-slider
+ roots.playerShadowRoot.querySelector('#volume-slider').addEventListener('click',
+ A_05_05_01_T03.step_func(function(event) {
+ invoked = true;
+ assert_equals(event.target.getAttribute('id'), 'volume-slider',
+ 'Wrong target');
+ assert_true(event.currentTarget.getAttribute('id'), 'volume-slider',
+ 'Wrong currentTarget');
+ }), false);
+
+ var event = d.createEvent('HTMLEvents');
+ event.initEvent ('click', true, false);
+ roots.volumeShadowRoot.querySelector('#volume-slider-thumb').dispatchEvent(event);
+
+ assert_true(invoked, 'Event listener was not invoked');
+
+ A_05_05_01_T03.done();
+}));
+
+
+
+var A_05_05_01_T04 = async_test('A_05_05_01_T04');
+
+A_05_05_01_T04.step(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var invoked = false;
+
+ roots = createTestMediaPlayer(d);
+
+ //expected result of what relative target should be see
+ //see at http://www.w3.org/TR/shadow-dom/#event-retargeting-example
+
+ //For #volume-slider-container relative target #volume-slider
+ roots.playerShadowRoot.querySelector('#volume-slider-container').addEventListener('click',
+ A_05_05_01_T04.step_func(function(event) {
+ invoked = true;
+ assert_equals(event.target.getAttribute('id'), 'volume-slider',
+ 'Wrong target');
+ assert_true(event.currentTarget.getAttribute('id'), 'volume-slider',
+ 'Wrong currentTarget');
+ }), false);
+
+ var event = d.createEvent('HTMLEvents');
+ event.initEvent ('click', true, false);
+ roots.volumeShadowRoot.querySelector('#volume-slider-thumb').dispatchEvent(event);
+
+ assert_true(invoked, 'Event listener was not invoked');
+
+ A_05_05_01_T04.done();
+}));
+
+
+var A_05_05_01_T05 = async_test('A_05_05_01_T05');
+
+A_05_05_01_T05.step(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var invoked = false;
+
+ roots = createTestMediaPlayer(d);
+
+ //expected result of what relative target should be see
+ //see at http://www.w3.org/TR/shadow-dom/#event-retargeting-example
+
+ //For #controls relative target #volume-slider
+ roots.playerShadowRoot.querySelector('#controls').addEventListener('click',
+ A_05_05_01_T05.step_func(function(event) {
+ invoked = true;
+ assert_equals(event.target.getAttribute('id'), 'volume-slider',
+ 'Wrong target');
+ assert_true(event.currentTarget.getAttribute('id'), 'volume-slider',
+ 'Wrong currentTarget');
+ }), false);
+
+ var event = d.createEvent('HTMLEvents');
+ event.initEvent ('click', true, false);
+ roots.volumeShadowRoot.querySelector('#volume-slider-thumb').dispatchEvent(event);
+
+ assert_true(invoked, 'Event listener was not invoked');
+
+ A_05_05_01_T05.done();
+}));
+
+
+var A_05_05_01_T06 = async_test('A_05_05_01_T06');
+
+A_05_05_01_T06.step(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var invoked = false;
+
+ roots = createTestMediaPlayer(d);
+
+ //expected result of what relative target should be see
+ //see at http://www.w3.org/TR/shadow-dom/#event-retargeting-example
+
+ //For #player-shadow-root relative target #volume-slider
+ roots.playerShadowRoot.addEventListener('click',
+ A_05_05_01_T06.step_func(function(event) {
+ invoked = true;
+ assert_equals(event.target.getAttribute('id'), 'volume-slider',
+ 'Wrong target');
+ assert_true(event.currentTarget.getAttribute('id'), 'volume-slider',
+ 'Wrong currentTarget');
+ }), false);
+
+ var event = d.createEvent('HTMLEvents');
+ event.initEvent ('click', true, false);
+ roots.volumeShadowRoot.querySelector('#volume-slider-thumb').dispatchEvent(event);
+
+ assert_true(invoked, 'Event listener was not invoked');
+
+ A_05_05_01_T06.done();
+}));
+
+
+
+var A_05_05_01_T07 = async_test('A_05_05_01_T07');
+
+A_05_05_01_T07.step(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var invoked = false;
+
+ roots = createTestMediaPlayer(d);
+
+ //expected result of what relative target should be see
+ //see at http://www.w3.org/TR/shadow-dom/#event-retargeting-example
+
+ //For #player relative target #player
+ d.querySelector('#player').addEventListener('click',
+ A_05_05_01_T07.step_func(function(event) {
+ invoked = true;
+ assert_equals(event.target.getAttribute('id'), 'player',
+ 'Wrong target');
+ assert_true(event.currentTarget.getAttribute('id'), 'player',
+ 'Wrong currentTarget');
+ }), false);
+
+ var event = d.createEvent('HTMLEvents');
+ event.initEvent ('click', true, false);
+ roots.volumeShadowRoot.querySelector('#volume-slider-thumb').dispatchEvent(event);
+
+ assert_true(invoked, 'Event listener was not invoked');
+
+ A_05_05_01_T07.done();
+}));
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/events/event-dispatch/test-002.html b/tests/wpt/web-platform-tests/shadow-dom/events/event-dispatch/test-002.html
new file mode 100644
index 00000000000..4a8214a16df
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/events/event-dispatch/test-002.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_05_05_02</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#event-dispatch">
+<meta name="assert" content="Event Dispatch: The MouseEvent relatedTarget attribute must return the adjusted related target">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_05_05_02_T01 = async_test('A_05_05_02_T01');
+
+A_05_05_02_T01.step(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var invoked = false;
+
+ roots = createTestMediaPlayer(d);
+
+ //expected result of what relative target should be see
+ //see at http://www.w3.org/TR/shadow-dom/#event-retargeting-example
+
+ //For #volume-shadow-root adjusted related target #volume-shadow-root
+ roots.volumeShadowRoot.addEventListener('mouseover',
+ A_05_05_02_T01.step_func(function(event) {
+ invoked = true;
+ assert_true(event.relatedTarget === roots.volumeShadowRoot,
+ 'Wrong relatedTarget');
+ }), false);
+
+
+
+
+ var evt = document.createEvent("MouseEvents");
+ evt.initMouseEvent("mouseover", true, false, window,
+ 0, 10, 10, 10, 10, false, false, false, false, 0, roots.volumeShadowRoot);
+
+ roots.volumeShadowRoot.querySelector('#volume-slider-thumb').dispatchEvent(evt);
+ assert_true(invoked, 'Event listener was not invoked');
+ A_05_05_02_T01.done();
+}));
+
+//TODO (sgrekhov) Add tests for other nodes from http://www.w3.org/TR/shadow-dom/#event-retargeting-example
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/events/event-dispatch/test-003.html b/tests/wpt/web-platform-tests/shadow-dom/events/event-dispatch/test-003.html
new file mode 100644
index 00000000000..da3d62fee30
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/events/event-dispatch/test-003.html
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_05_05_03</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#event-dispatch">
+<meta name="assert" content="Event Dispatch: If the relatedTarget and target are the same for a given node, its the event listeners must not be invoked.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_05_05_03_T01 = async_test('A_05_05_03_T01');
+
+A_05_05_03_T01.step(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var host = d.createElement('div');
+ host.setAttribute('style', 'height:50%; width:100%');
+ host.setAttribute('id', 'host');
+ d.body.appendChild(host);
+
+ //Shadow root to play with
+ var s = host.createShadowRoot();
+
+ var div1 = d.createElement('div');
+ div1.setAttribute('style', 'height:100%; width:100%');
+ div1.setAttribute('id', 'div1');
+ s.appendChild(div1);
+
+ s.addEventListener('mouseover', A_05_05_03_T01.step_func(function(event) {
+ assert_true(false, 'Event listeners shouldn\'t be invoked if target and relatedTarget ' +
+ 'are the same');
+ }), false);
+
+
+ var evt = document.createEvent("MouseEvents");
+ evt.initMouseEvent("mouseover", true, false, window,
+ 0, 10, 10, 10, 10, false, false, false, false, 0, div1);
+
+ div1.dispatchEvent(evt);
+
+ A_05_05_03_T01.done();
+}));
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/events/event-retargeting/test-001.html b/tests/wpt/web-platform-tests/shadow-dom/events/event-retargeting/test-001.html
new file mode 100644
index 00000000000..4504baf6219
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/events/event-retargeting/test-001.html
@@ -0,0 +1,107 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_05_01_01</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#event-retargeting">
+<meta name="assert" content="Event Retargeting:test that event.target is retargeted when event crosses shadow boundary and vice versa">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_05_01_01_T1 = async_test('A_05_01_01_T1');
+
+A_05_01_01_T1.step(function () {
+ var iframe = document.createElement('iframe');
+ iframe.src = '../../resources/blank.html';
+ document.body.appendChild(iframe);
+
+ iframe.onload = A_05_01_01_T1.step_func(function () {
+
+ try {
+ var d = iframe.contentDocument;
+ var div = d.createElement('div');
+ d.body.appendChild(div);
+
+ var s = div.createShadowRoot();
+
+ var div2 = d.createElement('div');
+ s.appendChild(div2);
+
+ var inp = d.createElement('input');
+ inp.setAttribute('type', 'text');
+ inp.setAttribute('id', 'inpid');
+ div2.appendChild(inp);
+
+ div2.addEventListener('click', A_05_01_01_T1.step_func(function (event) {
+ assert_equals(event.target.tagName, 'INPUT', 'Information about target of the event that ' +
+ 'doesn\'t cross the shadow boundaries should not be adjusted');
+ }), false);
+
+ var event = d.createEvent('HTMLEvents');
+ event.initEvent ("click", true, false);
+ inp.dispatchEvent(event);
+ } finally {
+ iframe.parentNode.removeChild(iframe);
+ }
+ A_05_01_01_T1.done();
+ });
+});
+
+
+
+var A_05_01_01_T2 = async_test('A_05_01_01_T2');
+
+A_05_01_01_T2.step(function () {
+ var iframe = document.createElement('iframe');
+ iframe.src = '../../resources/blank.html';
+ document.body.appendChild(iframe);
+
+ iframe.onload = A_05_01_01_T2.step_func(function () {
+
+ try {
+ var d = iframe.contentDocument;
+
+ var div = d.createElement('div');
+ d.body.appendChild(div);
+
+ var s = div.createShadowRoot();
+
+ var div2 = d.createElement('div');
+ s.appendChild(div2);
+
+ var inp = d.createElement('input');
+ inp.setAttribute('type', 'text');
+ inp.setAttribute('id', 'inpid');
+ div2.appendChild(inp);
+
+ div.addEventListener('click', A_05_01_01_T2.step_func(function (event) {
+ assert_equals(event.target.tagName, 'DIV', 'Information about event target crossing ' +
+ 'the shadow boundaries should be adjusted');
+ }), false);
+
+ var event = d.createEvent('HTMLEvents');
+ event.initEvent ("click", true, false);
+ inp.dispatchEvent(event);
+ } finally {
+ iframe.parentNode.removeChild(iframe);
+ }
+ A_05_01_01_T2.done();
+ });
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/events/event-retargeting/test-002.html b/tests/wpt/web-platform-tests/shadow-dom/events/event-retargeting/test-002.html
new file mode 100644
index 00000000000..6013f7d3cb9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/events/event-retargeting/test-002.html
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_05_01_02</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#event-retargeting">
+<meta name="assert" content="Event Retargeting:Event retargeting for document nodes distributed among insertion points">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_05_01_02_T1 = async_test('A_05_01_02_T1');
+
+A_05_01_02_T1.step(function () {
+ var iframe = document.createElement('iframe');
+ iframe.src = '../../resources/bobs_page.html';
+ document.body.appendChild(iframe);
+
+ iframe.onload = A_05_01_02_T1.step_func(function () {
+
+ try {
+ var d = iframe.contentDocument;
+
+ var ul = d.querySelector('ul.stories');
+ var s = ul.createShadowRoot();
+
+ //make shadow subtree
+ var div = document.createElement('div');
+ div.innerHTML = '<ul id="ip_wrapper"><content select=".shadow"></content></ul>';
+ s.appendChild(div);
+
+ d.body.addEventListener('click', A_05_01_02_T1.step_func(function (event) {
+ assert_equals(event.target.tagName, 'LI', 'Incorrect target');
+ }), false);
+
+ var event = d.createEvent('HTMLEvents');
+ event.initEvent ("click", true, false);
+ d.querySelector('#li3').dispatchEvent(event);
+ } finally {
+ iframe.parentNode.removeChild(iframe);
+ }
+ A_05_01_02_T1.done();
+ });
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/events/event-retargeting/test-003.html b/tests/wpt/web-platform-tests/shadow-dom/events/event-retargeting/test-003.html
new file mode 100644
index 00000000000..134430d61f0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/events/event-retargeting/test-003.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_05_01_03</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#event-retargeting">
+<meta name="assert" content="Event Retargeting:Event retargeting for fallback content">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_05_01_03_T01 = async_test('A_05_01_03_T01');
+
+A_05_01_03_T01.step(unit(function (ctx) {
+ var d = newRenderedHTMLDocument(ctx);
+
+ d.body.innerHTML = '' +
+ '<div id="main">' +
+ '<div id="shadow-root">' +
+ '<span>1</span>' +
+ '<span>2</span>' +
+ '<span>3</span>' +
+ '</div>' +
+ '</div>';
+
+ var ul = d.querySelector('#shadow-root');
+ var s = ul.createShadowRoot();
+
+ //make shadow subtree
+ var div = document.createElement('div');
+ div.innerHTML = '<content select=".shadow"><span id="flbk">Fallback item</span></content>';
+ s.appendChild(div);
+
+ d.body.addEventListener('click', A_05_01_03_T01.step_func(function (event) {
+ assert_equals(event.target.getAttribute('id'), 'shadow-root', 'Information about ' +
+ 'event target crossing the shadow boundaries should be adjusted for the fallback ' +
+ 'content');
+ }), false);
+
+ var event = d.createEvent('HTMLEvents');
+ event.initEvent ("click", true, false);
+ s.querySelector('#flbk').dispatchEvent(event);
+
+ A_05_01_03_T01.done();
+}));
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/events/event-retargeting/test-004.html b/tests/wpt/web-platform-tests/shadow-dom/events/event-retargeting/test-004.html
new file mode 100644
index 00000000000..8e861686173
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/events/event-retargeting/test-004.html
@@ -0,0 +1,365 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_05_01_04</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#event-retargeting">
+<meta name="assert" content="Event Retargeting:Retargeting algorithm">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_05_01_04_T01 = async_test('A_05_01_04_T01');
+
+A_05_01_04_T01.step(unit(function (ctx) {
+ var d = newRenderedHTMLDocument(ctx);
+ var invoked = false;
+ roots = createTestMediaPlayer(d);
+
+ //expected result of what relative target should be see
+ //see at http://www.w3.org/TR/shadow-dom/#event-retargeting-example
+ //For #volume-slider-thumb relative target is #volume-slider-thumb
+ roots.volumeShadowRoot.querySelector('#volume-slider-thumb').addEventListener('click',
+ A_05_01_04_T01.step_func(function (event) {
+ invoked = true;
+ assert_equals(event.target.getAttribute('id'), 'volume-slider-thumb',
+ 'Wrong related target');
+ }), false);
+
+ var event = d.createEvent('HTMLEvents');
+ event.initEvent ("click", true, false);
+ roots.volumeShadowRoot.querySelector('#volume-slider-thumb').dispatchEvent(event);
+
+ assert_true(invoked, 'Event listener was not invoked');
+
+ A_05_01_04_T01.done();
+}));
+
+
+
+var A_05_01_04_T02 = async_test('A_05_01_04_T02');
+
+A_05_01_04_T02.step(unit(function (ctx) {
+ var d = newRenderedHTMLDocument(ctx);
+ var invoked = false;
+ roots = createTestMediaPlayer(d);
+
+ //expected result of what relative target should be see
+ //see at http://www.w3.org/TR/shadow-dom/#event-retargeting-example
+
+ //For #volume-shadow-root relative target is #volume-slider-thumb
+ roots.volumeShadowRoot.addEventListener('click',
+ A_05_01_04_T02.step_func(function (event) {
+ invoked = true;
+ assert_equals(event.target.getAttribute('id'), 'volume-slider-thumb',
+ 'Wrong related target');
+ }), false);
+
+ var event = d.createEvent('HTMLEvents');
+ event.initEvent ("click", true, false);
+ roots.volumeShadowRoot.querySelector('#volume-slider-thumb').dispatchEvent(event);
+
+ assert_true(invoked, 'Event listener was not invoked');
+
+ A_05_01_04_T02.done();
+}));
+
+
+
+
+var A_05_01_04_T03 = async_test('A_05_01_04_T03');
+
+A_05_01_04_T03.step(unit(function (ctx) {
+ var d = newRenderedHTMLDocument(ctx);
+ var invoked = false;
+ roots = createTestMediaPlayer(d);
+
+ //expected result of what relative target should be see
+ //see at http://www.w3.org/TR/shadow-dom/#event-retargeting-example
+
+ //For #volume-slider relative target is #volume-slider
+ roots.playerShadowRoot.querySelector('#volume-slider').addEventListener('click',
+ A_05_01_04_T03.step_func(function (event) {
+ invoked = true;
+ assert_equals(event.target.getAttribute('id'), 'volume-slider',
+ 'Wrong related target');
+ }), false);
+
+ var event = d.createEvent('HTMLEvents');
+ event.initEvent ("click", true, false);
+ roots.volumeShadowRoot.querySelector('#volume-slider-thumb').dispatchEvent(event);
+
+ assert_true(invoked, 'Event listener was not invoked');
+
+ A_05_01_04_T03.done();
+}));
+
+
+var A_05_01_04_T04 = async_test('A_05_01_04_T04');
+
+A_05_01_04_T04.step(unit(function (ctx) {
+ var d = newRenderedHTMLDocument(ctx);
+ var invoked = false;
+ roots = createTestMediaPlayer(d);
+
+ //expected result of what relative target should be see
+ //see at http://www.w3.org/TR/shadow-dom/#event-retargeting-example
+
+ //For #volume-slider-container relative target is #volume-slider
+ roots.playerShadowRoot.querySelector('#volume-slider-container').addEventListener('click',
+ A_05_01_04_T04.step_func(function (event) {
+ invoked = true;
+ assert_equals(event.target.getAttribute('id'), 'volume-slider',
+ 'Wrong related target');
+ }), false);
+
+ var event = d.createEvent('HTMLEvents');
+ event.initEvent ("click", true, false);
+ roots.volumeShadowRoot.querySelector('#volume-slider-thumb').dispatchEvent(event);
+
+ assert_true(invoked, 'Event listener was not invoked');
+
+ A_05_01_04_T04.done();
+}));
+
+
+var A_05_01_04_T05 = async_test('A_05_01_04_T05');
+
+A_05_01_04_T05.step(unit(function (ctx) {
+ var d = newRenderedHTMLDocument(ctx);
+ var invoked = false;
+ roots = createTestMediaPlayer(d);
+
+ //expected result of what relative target should be see
+ //see at http://www.w3.org/TR/shadow-dom/#event-retargeting-example
+
+ //For #controls relative target is #volume-slider
+ roots.playerShadowRoot.querySelector('#controls').addEventListener('click',
+ A_05_01_04_T05.step_func(function (event) {
+ invoked = true;
+ assert_equals(event.target.getAttribute('id'), 'volume-slider',
+ 'Wrong related target');
+ }), false);
+
+ var event = d.createEvent('HTMLEvents');
+ event.initEvent ("click", true, false);
+ roots.volumeShadowRoot.querySelector('#volume-slider-thumb').dispatchEvent(event);
+
+ assert_true(invoked, 'Event listener was not invoked');
+
+ A_05_01_04_T05.done();
+}));
+
+
+var A_05_01_04_T06 = async_test('A_05_01_04_T06');
+
+A_05_01_04_T06.step(unit(function (ctx) {
+ var d = newRenderedHTMLDocument(ctx);
+ var invoked = false;
+ roots = createTestMediaPlayer(d);
+
+ //expected result of what relative target should be see
+ //see at http://www.w3.org/TR/shadow-dom/#event-retargeting-example
+
+ //For #player-shadow-root relative target is #volume-slider
+ roots.playerShadowRoot.addEventListener('click',
+ A_05_01_04_T06.step_func(function (event) {
+ invoked = true;
+ assert_equals(event.target.getAttribute('id'), 'volume-slider',
+ 'Wrong related target');
+ }), false);
+
+ var event = d.createEvent('HTMLEvents');
+ event.initEvent ("click", true, false);
+ roots.volumeShadowRoot.querySelector('#volume-slider-thumb').dispatchEvent(event);
+
+ assert_true(invoked, 'Event listener was not invoked');
+
+ A_05_01_04_T06.done();
+}));
+
+
+
+var A_05_01_04_T07 = async_test('A_05_01_04_T07');
+
+A_05_01_04_T07.step(unit(function (ctx) {
+ var d = newRenderedHTMLDocument(ctx);
+ var invoked = false;
+ roots = createTestMediaPlayer(d);
+
+ //expected result of what relative target should be see
+ //see at http://www.w3.org/TR/shadow-dom/#event-retargeting-example
+
+ //For #player relative target is #player
+ d.querySelector('#player').addEventListener('click',
+ A_05_01_04_T07.step_func(function (event) {
+ invoked = true;
+ assert_equals(event.target.getAttribute('id'), 'player',
+ 'Wrong related target');
+ }), false);
+
+ var event = d.createEvent('HTMLEvents');
+ event.initEvent ("click", true, false);
+ roots.volumeShadowRoot.querySelector('#volume-slider-thumb').dispatchEvent(event);
+
+ assert_true(invoked, 'Event listener was not invoked');
+
+ A_05_01_04_T07.done();
+}));
+
+
+var A_05_01_04_T08 = async_test('A_05_01_04_T08');
+
+A_05_01_04_T08.step(unit(function (ctx) {
+ var d = newRenderedHTMLDocument(ctx);
+ var invoked = false;
+ roots = createTestMediaPlayer(d);
+
+ //expected result of what relative target should be see
+ //see at http://www.w3.org/TR/shadow-dom/#event-retargeting-example
+
+ //For #volume-slider relative target is #volume-slider
+ roots.playerShadowRoot.querySelector('#volume-slider').addEventListener('click',
+ A_05_01_04_T08.step_func(function (event) {
+ invoked = true;
+ assert_equals(event.target.getAttribute('id'), 'volume-slider',
+ 'Wrong related target');
+ }), false);
+
+ var event = d.createEvent('HTMLEvents');
+ event.initEvent ("click", true, false);
+ roots.playerShadowRoot.querySelector('#volume-slider').dispatchEvent(event);
+
+ assert_true(invoked, 'Event listener was not invoked');
+
+ A_05_01_04_T08.done();
+}));
+
+
+var A_05_01_04_T09 = async_test('A_05_01_04_T09');
+
+A_05_01_04_T09.step(unit(function (ctx) {
+ var d = newRenderedHTMLDocument(ctx);
+ var invoked = false;
+ roots = createTestMediaPlayer(d);
+
+ //expected result of what relative target should be see
+ //see at http://www.w3.org/TR/shadow-dom/#event-retargeting-example
+
+ //For #volume-slider-container relative target is #volume-slider
+ roots.playerShadowRoot.querySelector('#volume-slider-container').addEventListener('click',
+ A_05_01_04_T09.step_func(function (event) {
+ invoked = true;
+ assert_equals(event.target.getAttribute('id'), 'volume-slider',
+ 'Wrong related target');
+ }), false);
+
+ var event = d.createEvent('HTMLEvents');
+ event.initEvent ("click", true, false);
+ roots.playerShadowRoot.querySelector('#volume-slider').dispatchEvent(event);
+
+ assert_true(invoked, 'Event listener was not invoked');
+
+ A_05_01_04_T09.done();
+}));
+
+
+var A_05_01_04_T10 = async_test('A_05_01_04_T10');
+
+A_05_01_04_T10.step(unit(function (ctx) {
+ var d = newRenderedHTMLDocument(ctx);
+ var invoked = false;
+ roots = createTestMediaPlayer(d);
+
+ //expected result of what relative target should be see
+ //see at http://www.w3.org/TR/shadow-dom/#event-retargeting-example
+
+ //For #controls relative target is #volume-slider
+ roots.playerShadowRoot.querySelector('#controls').addEventListener('click',
+ A_05_01_04_T10.step_func(function (event) {
+ invoked = true;
+ assert_equals(event.target.getAttribute('id'), 'volume-slider',
+ 'Wrong related target');
+ }), false);
+
+ var event = d.createEvent('HTMLEvents');
+ event.initEvent ("click", true, false);
+ roots.playerShadowRoot.querySelector('#volume-slider').dispatchEvent(event);
+
+ assert_true(invoked, 'Event listener was not invoked');
+
+ A_05_01_04_T10.done();
+}));
+
+
+var A_05_01_04_T11 = async_test('A_05_01_04_T11');
+
+A_05_01_04_T11.step(unit(function (ctx) {
+ var d = newRenderedHTMLDocument(ctx);
+ var invoked = false;
+ roots = createTestMediaPlayer(d);
+
+ //expected result of what relative target should be see
+ //see at http://www.w3.org/TR/shadow-dom/#event-retargeting-example
+
+ //For #player-shadow-root relative target is #volume-slider
+ roots.playerShadowRoot.addEventListener('click',
+ A_05_01_04_T11.step_func(function (event) {
+ invoked = true;
+ assert_equals(event.target.getAttribute('id'), 'volume-slider',
+ 'Wrong related target');
+ }), false);
+
+ var event = d.createEvent('HTMLEvents');
+ event.initEvent ("click", true, false);
+ roots.playerShadowRoot.querySelector('#volume-slider').dispatchEvent(event);
+
+ assert_true(invoked, 'Event listener was not invoked');
+
+ A_05_01_04_T11.done();
+}));
+
+
+
+var A_05_01_04_T12 = async_test('A_05_01_04_T12');
+
+A_05_01_04_T12.step(unit(function (ctx) {
+ var d = newRenderedHTMLDocument(ctx);
+ var invoked = false;
+ roots = createTestMediaPlayer(d);
+
+ //expected result of what relative target should be see
+ //see at http://www.w3.org/TR/shadow-dom/#event-retargeting-example
+
+ //For #player relative target is #player
+ d.querySelector('#player').addEventListener('click',
+ A_05_01_04_T12.step_func(function (event) {
+ invoked = true;
+ assert_equals(event.target.getAttribute('id'), 'player',
+ 'Wrong related target');
+ }), false);
+
+ var event = d.createEvent('HTMLEvents');
+ event.initEvent ("click", true, false);
+ roots.playerShadowRoot.querySelector('#volume-slider').dispatchEvent(event);
+
+ assert_true(invoked, 'Event listener was not invoked');
+
+ A_05_01_04_T12.done();
+}));
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/events/events-that-are-always-stopped/test-001.html b/tests/wpt/web-platform-tests/shadow-dom/events/events-that-are-always-stopped/test-001.html
new file mode 100644
index 00000000000..e93bc840afc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/events/events-that-are-always-stopped/test-001.html
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_05_04_01</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#events-that-are-always-stopped">
+<meta name="assert" content="The following events must always be stopped at the nearest shadow boundary: abort, error, select, change, load, reset, resize, scroll, selectstart">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_05_04_01_T01 = async_test('A_05_04_01_T01');
+
+A_05_04_01_T01.step(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var host = d.createElement('div');
+ host.setAttribute('style', 'height:50%; width:100%');
+ host.setAttribute('id', 'host');
+ d.body.appendChild(host);
+
+ //Shadow root to play with
+ var s = host.createShadowRoot();
+
+ var inp1 = d.createElement('input');
+ inp1.setAttribute('id', 'inp1');
+ inp1.setAttribute('type', 'checkbox');
+ s.appendChild(inp1);
+
+ s.addEventListener('abort', A_05_04_01_T01.step_func(function(event) {
+ assert_equals(event.target.getAttribute('id'), 'inp1', 'Inside shadoe tree: Wrong target');
+ }), false);
+
+ d.body.addEventListener('abort', A_05_04_01_T01.step_func(function(event) {
+ assert_true(false, 'Abort event should always be stopped at Shadow boundary');
+ }), false);
+
+ var event = d.createEvent('UIEvent');
+ event.initUIEvent ('abort', true, false);
+ inp1.dispatchEvent(event);
+
+ A_05_04_01_T01.done();
+}));
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/events/events-that-are-always-stopped/test-002.html b/tests/wpt/web-platform-tests/shadow-dom/events/events-that-are-always-stopped/test-002.html
new file mode 100644
index 00000000000..c4d9ec2bc40
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/events/events-that-are-always-stopped/test-002.html
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_05_04_02</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#events-that-are-always-stopped">
+<meta name="assert" content="The following events must always be stopped at the nearest shadow boundary: abort, error, select, change, load, reset, resize, scroll, selectstart">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_05_04_02_T01 = async_test('A_05_04_02_T01');
+
+A_05_04_02_T01.step(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var host = d.createElement('div');
+ host.setAttribute('style', 'height:50%; width:100%');
+ host.setAttribute('id', 'host');
+ d.body.appendChild(host);
+
+ //Shadow root to play with
+ var s = host.createShadowRoot();
+
+ var inp1 = d.createElement('input');
+ inp1.setAttribute('id', 'inp1');
+ inp1.setAttribute('type', 'checkbox');
+ s.appendChild(inp1);
+
+ s.addEventListener('error', A_05_04_02_T01.step_func(function(event) {
+ assert_equals(event.target.getAttribute('id'), 'inp1', 'Inside shadoe tree: Wrong target');
+ }), false);
+
+ d.body.addEventListener('error', A_05_04_02_T01.step_func(function(event) {
+ assert_true(false, 'error event should always be stopped at Shadow boundary');
+ }), false);
+
+ var event = d.createEvent('UIEvent');
+ event.initUIEvent ('error', true, false);
+ inp1.dispatchEvent(event);
+
+ A_05_04_02_T01.done();
+}));
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/events/events-that-are-always-stopped/test-003.html b/tests/wpt/web-platform-tests/shadow-dom/events/events-that-are-always-stopped/test-003.html
new file mode 100644
index 00000000000..f5674f5ae26
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/events/events-that-are-always-stopped/test-003.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_05_04_03</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#events-that-are-always-stopped">
+<meta name="assert" content="The following events must always be stopped at the nearest shadow boundary: abort, error, select, change, load, reset, resize, scroll, selectstart">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_05_04_03_T01 = async_test('A_05_04_03_T01');
+
+A_05_04_03_T01.step(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var host = d.createElement('div');
+ host.setAttribute('style', 'height:50%; width:100%');
+ host.setAttribute('id', 'host');
+ d.body.appendChild(host);
+
+ //Shadow root to play with
+ var s = host.createShadowRoot();
+
+ var inp1 = d.createElement('input');
+ inp1.setAttribute('id', 'inp1');
+ inp1.setAttribute('type', 'text');
+ inp1.setAttribute('value', '12345');
+ s.appendChild(inp1);
+
+ s.addEventListener('select', A_05_04_03_T01.step_func(function(event) {
+ assert_equals(event.target.getAttribute('id'), 'inp1', 'Inside shadoe tree: Wrong target');
+ }), false);
+
+ d.body.addEventListener('select', A_05_04_03_T01.step_func(function(event) {
+ assert_true(false, 'select event should always be stopped at Shadow boundary');
+ }), false);
+
+ var event = d.createEvent('UIEvent');
+ event.initUIEvent ('select', true, false);
+ inp1.dispatchEvent(event);
+
+ A_05_04_03_T01.done();
+}));
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/events/events-that-are-always-stopped/test-004.html b/tests/wpt/web-platform-tests/shadow-dom/events/events-that-are-always-stopped/test-004.html
new file mode 100644
index 00000000000..56c7be9d514
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/events/events-that-are-always-stopped/test-004.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_05_04_04</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#events-that-are-always-stopped">
+<meta name="assert" content="The following events must always be stopped at the nearest shadow boundary: abort, error, select, change, load, reset, resize, scroll, selectstart">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_05_04_04_T01 = async_test('A_05_04_04_T01');
+
+A_05_04_04_T01.step(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var host = d.createElement('div');
+ host.setAttribute('style', 'height:50%; width:100%');
+ host.setAttribute('id', 'host');
+ d.body.appendChild(host);
+
+ //Shadow root to play with
+ var s = host.createShadowRoot();
+
+ var inp1 = d.createElement('input');
+ inp1.setAttribute('id', 'inp1');
+ inp1.setAttribute('type', 'text');
+ inp1.setAttribute('value', '12345');
+ s.appendChild(inp1);
+
+ s.addEventListener('change', A_05_04_04_T01.step_func(function(event) {
+ assert_equals(event.target.getAttribute('id'), 'inp1', 'Inside shadoe tree: Wrong target');
+ }), false);
+
+ d.body.addEventListener('change', A_05_04_04_T01.step_func(function(event) {
+ assert_true(false, 'change event should always be stopped at Shadow boundary');
+ }), false);
+
+ var event = d.createEvent('HTMLEvents');
+ event.initEvent ('change', true, false);
+ inp1.dispatchEvent(event);
+
+ A_05_04_04_T01.done();
+}));
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/events/events-that-are-always-stopped/test-005.html b/tests/wpt/web-platform-tests/shadow-dom/events/events-that-are-always-stopped/test-005.html
new file mode 100644
index 00000000000..f2b8cad556a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/events/events-that-are-always-stopped/test-005.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_05_04_05</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#events-that-are-always-stopped">
+<meta name="assert" content="The following events must always be stopped at the nearest shadow boundary: abort, error, select, change, load, reset, resize, scroll, selectstart">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_05_04_05_T01 = async_test('A_05_04_05_T01');
+
+A_05_04_05_T01.step(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var host = d.createElement('div');
+ host.setAttribute('style', 'height:50%; width:100%');
+ host.setAttribute('id', 'host');
+ d.body.appendChild(host);
+
+ //Shadow root to play with
+ var s = host.createShadowRoot();
+
+ var inp1 = d.createElement('input');
+ inp1.setAttribute('id', 'inp1');
+ inp1.setAttribute('type', 'text');
+ inp1.setAttribute('value', '12345');
+ s.appendChild(inp1);
+
+ s.addEventListener('load', A_05_04_05_T01.step_func(function(event) {
+ assert_equals(event.target.getAttribute('id'), 'inp1', 'Inside shadoe tree: Wrong target');
+ }), false);
+
+ d.body.addEventListener('load', A_05_04_05_T01.step_func(function(event) {
+ assert_true(false, 'load event should always be stopped at Shadow boundary');
+ }), false);
+
+ var event = d.createEvent('UIEvent');
+ event.initUIEvent ('load', true, false);
+ inp1.dispatchEvent(event);
+
+ A_05_04_05_T01.done();
+}));
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/events/events-that-are-always-stopped/test-006.html b/tests/wpt/web-platform-tests/shadow-dom/events/events-that-are-always-stopped/test-006.html
new file mode 100644
index 00000000000..a055fd4d394
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/events/events-that-are-always-stopped/test-006.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_05_04_06</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#events-that-are-always-stopped">
+<meta name="assert" content="The following events must always be stopped at the nearest shadow boundary: abort, error, select, change, load, reset, resize, scroll, selectstart">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_05_04_06_T01 = async_test('A_05_04_06_T01');
+
+A_05_04_06_T01.step(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var host = d.createElement('div');
+ host.setAttribute('style', 'height:50%; width:100%');
+ host.setAttribute('id', 'host');
+ d.body.appendChild(host);
+
+ //Shadow root to play with
+ var s = host.createShadowRoot();
+
+ var inp1 = d.createElement('input');
+ inp1.setAttribute('id', 'inp1');
+ inp1.setAttribute('type', 'text');
+ inp1.setAttribute('value', '12345');
+ s.appendChild(inp1);
+
+ s.addEventListener('reset', A_05_04_06_T01.step_func(function(event) {
+ assert_equals(event.target.getAttribute('id'), 'inp1', 'Inside shadoe tree: Wrong target');
+ }), false);
+
+ d.body.addEventListener('reset', A_05_04_06_T01.step_func(function(event) {
+ assert_true(false, 'reset event should always be stopped at Shadow boundary');
+ }), false);
+
+ var event = d.createEvent('HTMLEvents');
+ event.initEvent ('reset', true, false);
+ inp1.dispatchEvent(event);
+
+ A_05_04_06_T01.done();
+}));
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/events/events-that-are-always-stopped/test-007.html b/tests/wpt/web-platform-tests/shadow-dom/events/events-that-are-always-stopped/test-007.html
new file mode 100644
index 00000000000..c9db1cd94d7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/events/events-that-are-always-stopped/test-007.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_05_04_07</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#events-that-are-always-stopped">
+<meta name="assert" content="The following events must always be stopped at the nearest shadow boundary: abort, error, select, change, load, reset, resize, scroll, selectstart">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_05_04_07_T01 = async_test('A_05_04_07_T01');
+
+A_05_04_07_T01.step(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var host = d.createElement('div');
+ host.setAttribute('style', 'height:50%; width:100%');
+ host.setAttribute('id', 'host');
+ d.body.appendChild(host);
+
+ //Shadow root to play with
+ var s = host.createShadowRoot();
+
+ var inp1 = d.createElement('input');
+ inp1.setAttribute('id', 'inp1');
+ inp1.setAttribute('type', 'text');
+ inp1.setAttribute('value', '12345');
+ s.appendChild(inp1);
+
+ s.addEventListener('resize', A_05_04_07_T01.step_func(function(event) {
+ assert_equals(event.target.getAttribute('id'), 'inp1', 'Inside shadoe tree: Wrong target');
+ }), false);
+
+ d.body.addEventListener('resize', A_05_04_07_T01.step_func(function(event) {
+ assert_true(false, 'resize event should always be stopped at Shadow boundary');
+ }), false);
+
+ var event = d.createEvent('UIEvent');
+ event.initUIEvent ('resize', true, false);
+ inp1.dispatchEvent(event);
+
+ A_05_04_07_T01.done();
+}));
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/events/events-that-are-always-stopped/test-008.html b/tests/wpt/web-platform-tests/shadow-dom/events/events-that-are-always-stopped/test-008.html
new file mode 100644
index 00000000000..f251a0c1a84
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/events/events-that-are-always-stopped/test-008.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_05_04_08</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#events-that-are-always-stopped">
+<meta name="assert" content="The following events must always be stopped at the nearest shadow boundary: abort, error, select, change, load, reset, resize, scroll, selectstart">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_05_04_08_T01 = async_test('A_05_04_08_T01');
+
+A_05_04_08_T01.step(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var host = d.createElement('div');
+ host.setAttribute('style', 'height:50%; width:100%');
+ host.setAttribute('id', 'host');
+ d.body.appendChild(host);
+
+ //Shadow root to play with
+ var s = host.createShadowRoot();
+
+ var inp1 = d.createElement('input');
+ inp1.setAttribute('id', 'inp1');
+ inp1.setAttribute('type', 'text');
+ inp1.setAttribute('value', '12345');
+ s.appendChild(inp1);
+
+ s.addEventListener('scroll', A_05_04_08_T01.step_func(function(event) {
+ assert_equals(event.target.getAttribute('id'), 'inp1', 'Inside shadoe tree: Wrong target');
+ }), false);
+
+ d.body.addEventListener('scroll', A_05_04_08_T01.step_func(function(event) {
+ assert_true(false, 'scroll event should always be stopped at Shadow boundary');
+ }), false);
+
+ var event = d.createEvent('UIEvent');
+ event.initUIEvent ('scroll', true, false);
+ inp1.dispatchEvent(event);
+
+ A_05_04_08_T01.done();
+}));
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/events/events-that-are-always-stopped/test-009.html b/tests/wpt/web-platform-tests/shadow-dom/events/events-that-are-always-stopped/test-009.html
new file mode 100644
index 00000000000..f6172892911
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/events/events-that-are-always-stopped/test-009.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_05_04_09</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#events-that-are-always-stopped">
+<meta name="assert" content="The following events must always be stopped at the nearest shadow boundary: abort, error, select, change, load, reset, resize, scroll, selectstart">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_05_04_09_T01 = async_test('A_05_04_09_T01');
+
+A_05_04_09_T01.step(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var host = d.createElement('div');
+ host.setAttribute('style', 'height:50%; width:100%');
+ host.setAttribute('id', 'host');
+ d.body.appendChild(host);
+
+ //Shadow root to play with
+ var s = host.createShadowRoot();
+
+ var inp1 = d.createElement('input');
+ inp1.setAttribute('id', 'inp1');
+ inp1.setAttribute('type', 'text');
+ inp1.setAttribute('value', '12345');
+ s.appendChild(inp1);
+
+ s.addEventListener('selectstart', A_05_04_09_T01.step_func(function(event) {
+ assert_equals(event.target.getAttribute('id'), 'inp1', 'Inside shadoe tree: Wrong target');
+ }), false);
+
+ d.body.addEventListener('selectstart', A_05_04_09_T01.step_func(function(event) {
+ assert_true(false, 'selectstart event should always be stopped at Shadow boundary');
+ }), false);
+
+ var event = d.createEvent('UIEvent');
+ event.initUIEvent ('selectstart', true, false);
+ inp1.dispatchEvent(event);
+
+ A_05_04_09_T01.done();
+}));
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/events/retargeting-focus-events/test-001.html b/tests/wpt/web-platform-tests/shadow-dom/events/retargeting-focus-events/test-001.html
new file mode 100644
index 00000000000..e230765ddd7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/events/retargeting-focus-events/test-001.html
@@ -0,0 +1,322 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_05_03_01</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#retargeting-focus-events">
+<meta name="assert" content="Retargeting focus events:The focus, DOMFocusIn, blur, and DOMFocusOut events must be treated in the same way as events with a relatedTarget, where the corresponding node that is losing focus as a result of target gaining focus or the node that is gaining focus, and thus causing the blurring of target acts as the related target">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+//blur and focus events are not bubbling. So this test tests only DOMFocusIn and DOMFocusOut
+//which do bubble
+
+//test DOMFocusOut event
+var A_05_03_01_T01 = async_test('A_05_03_01_T01');
+
+A_05_03_01_T01.step(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var host = d.createElement('div');
+ host.setAttribute('style', 'height:50%; width:100%');
+ host.setAttribute('id', 'host');
+ d.body.appendChild(host);
+
+ //Shadow root to play with
+ var s = host.createShadowRoot();
+
+ var inp1 = d.createElement('input');
+ inp1.setAttribute('id', 'inp1');
+ inp1.setAttribute('type', 'checkbox');
+ s.appendChild(inp1);
+
+ var inp2 = d.createElement('input');
+ inp2.setAttribute('id', 'inp2');
+ inp2.setAttribute('type', 'checkbox');
+ d.body.appendChild(inp2);
+
+ s.addEventListener('DOMFocusOut', A_05_03_01_T01.step_func(function(event) {
+ assert_equals(event.target.getAttribute('id'), 'inp1', 'Inside shadow tree: Wrong target');
+ }), false);
+
+ d.body.addEventListener('DOMFocusOut', A_05_03_01_T01.step_func(function(event) {
+ assert_equals(event.target.getAttribute('id'), 'host', 'Inside shadow tree: Wrong target');
+ }), false);
+
+ inp1.focus();
+ inp2.focus();
+
+ A_05_03_01_T01.done();
+}));
+
+
+//test DOMFocusIn event
+var A_05_03_01_T02 = async_test('A_05_03_01_T02');
+
+A_05_03_01_T02.step(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var host = d.createElement('div');
+ host.setAttribute('style', 'height:50%; width:100%');
+ host.setAttribute('id', 'host');
+ d.body.appendChild(host);
+
+ //Shadow root to play with
+ var s = host.createShadowRoot();
+
+ var inp1 = d.createElement('input');
+ inp1.setAttribute('id', 'inp1');
+ inp1.setAttribute('type', 'checkbox');
+ s.appendChild(inp1);
+
+ var inp2 = d.createElement('input');
+ inp2.setAttribute('id', 'inp2');
+ inp2.setAttribute('type', 'checkbox');
+ d.body.appendChild(inp2);
+
+ inp2.focus();
+
+ s.addEventListener('DOMFocusIn', A_05_03_01_T02.step_func(function(event) {
+ assert_equals(event.target.getAttribute('id'), 'inp1', 'Inside shadoe tree: Wrong target');
+ }), false);
+
+ d.body.addEventListener('DOMFocusIn', A_05_03_01_T02.step_func(function(event) {
+ assert_equals(event.target.getAttribute('id'), 'host', 'Outside shadow tree: Wrong target');
+ }), false);
+
+ inp1.focus();
+
+ A_05_03_01_T02.done();
+}));
+
+
+//gaining and loosing focus elements are in the same tree.
+//DOMFocusIn event should be stopped at shadow boundary
+var A_05_03_01_T03 = async_test('A_05_03_01_T03');
+
+
+A_05_03_01_T03.step(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var host = d.createElement('div');
+ host.setAttribute('style', 'height:50%; width:100%');
+ host.setAttribute('id', 'host');
+ d.body.appendChild(host);
+
+ //Shadow root to play with
+ var s = host.createShadowRoot();
+
+ var inp1 = d.createElement('input');
+ inp1.setAttribute('id', 'inp1');
+ inp1.setAttribute('type', 'checkbox');
+ s.appendChild(inp1);
+
+ var inp2 = d.createElement('input');
+ inp2.setAttribute('id', 'inp2');
+ inp2.setAttribute('type', 'checkbox');
+ s.appendChild(inp2);
+
+ inp1.focus();
+
+ d.body.addEventListener('DOMFocusIn', A_05_03_01_T03.step_func(function(event) {
+ assert_true(false, 'Event should be stopped at Shadow boundary');
+ }), false);
+
+ inp2.focus();
+
+ A_05_03_01_T03.done();
+}));
+
+
+
+
+//gaining and loosing focus elements are in the same tree.
+//DOMFocusOut event should be stopped at shadow boundary
+var A_05_03_01_T04 = async_test('A_05_03_01_T04');
+
+A_05_03_01_T04.step(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var host = d.createElement('div');
+ host.setAttribute('style', 'height:50%; width:100%');
+ host.setAttribute('id', 'host');
+ d.body.appendChild(host);
+
+ //Shadow root to play with
+ var s = host.createShadowRoot();
+
+ var inp1 = d.createElement('input');
+ inp1.setAttribute('id', 'inp1');
+ inp1.setAttribute('type', 'checkbox');
+ s.appendChild(inp1);
+
+ var inp2 = d.createElement('input');
+ inp2.setAttribute('id', 'inp2');
+ inp2.setAttribute('type', 'checkbox');
+ s.appendChild(inp2);
+
+ inp1.focus();
+
+ d.body.addEventListener('DOMFocusOut', A_05_03_01_T04.step_func(function(event) {
+ assert_true(false, 'Event should be stopped at Shadow boundary');
+ }), false);
+
+ inp2.focus();
+
+ A_05_03_01_T04.done();
+}));
+
+
+
+
+//Retargeting shouldn't occur for DOM tree nodes distributed
+//among insertion point. Check DOMFocusOut
+var A_05_03_01_T05 = async_test('A_05_03_01_T05');
+
+A_05_03_01_T05.step(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var host = d.createElement('div');
+ host.setAttribute('id', 'host');
+ d.body.appendChild(host);
+
+ var inp1 = d.createElement('input');
+ inp1.setAttribute('id', 'inp1');
+ inp1.setAttribute('type', 'checkbox');
+ inp1.setAttribute('class', 'clazz1');
+ host.appendChild(inp1);
+
+ var inp2 = d.createElement('input');
+ inp2.setAttribute('id', 'inp2');
+ inp2.setAttribute('type', 'checkbox');
+ inp2.setAttribute('class', 'clazz2');
+ host.appendChild(inp2);
+
+ var inp3 = d.createElement('input');
+ inp3.setAttribute('id', 'inp3');
+ inp3.setAttribute('type', 'checkbox');
+ inp3.setAttribute('class', 'clazz1');
+ host.appendChild(inp3);
+
+
+ //Shadow root to play with
+ var s = host.createShadowRoot();
+
+ var shadowDiv = document.createElement('div');
+ shadowDiv.innerHTML = '<content select=".clazz1"></content>';
+ s.appendChild(shadowDiv);
+
+ //element outside the shadow tree
+ var inp4 = d.createElement('input');
+ inp4.setAttribute('id', 'inp4');
+ inp4.setAttribute('type', 'checkbox');
+ inp4.setAttribute('class', 'clazz1');
+ d.body.appendChild(inp4);
+
+ inp1.focus();
+
+ s.addEventListener('DOMFocusOut', A_05_03_01_T05.step_func(function(event) {
+ assert_equals(event.target.getAttribute('id'), 'inp1', 'Inside shadow tree: ' +
+ 'Event for nodes, distributed ' +
+ 'agains insertion points shouldn\'t be retargeted');
+ }), false);
+
+
+ d.body.addEventListener('DOMFocusOut', A_05_03_01_T05.step_func(function(event) {
+ assert_equals(event.target.getAttribute('id'), 'inp1', 'Outside shadow tree: ' +
+ 'Event for nodes, distributed ' +
+ 'agains insertion points shouldn\'t be retargeted');
+ }), false);
+
+ inp4.focus();
+
+ A_05_03_01_T05.done();
+}));
+
+
+//Retargeting shouldn't occur for DOM tree nodes distributed
+//among insertion points. Check DOMFocusIn
+var A_05_03_01_T06 = async_test('A_05_03_01_T06');
+
+A_05_03_01_T06.step(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var host = d.createElement('div');
+ host.setAttribute('id', 'host');
+ d.body.appendChild(host);
+
+ var inp1 = d.createElement('input');
+ inp1.setAttribute('id', 'inp1');
+ inp1.setAttribute('type', 'checkbox');
+ inp1.setAttribute('class', 'clazz1');
+ host.appendChild(inp1);
+
+ var inp2 = d.createElement('input');
+ inp2.setAttribute('id', 'inp2');
+ inp2.setAttribute('type', 'checkbox');
+ inp2.setAttribute('class', 'clazz2');
+ host.appendChild(inp2);
+
+ var inp3 = d.createElement('input');
+ inp3.setAttribute('id', 'inp3');
+ inp3.setAttribute('type', 'checkbox');
+ inp3.setAttribute('class', 'clazz1');
+ host.appendChild(inp3);
+
+
+ //Shadow root to play with
+ var s = host.createShadowRoot();
+
+ var shadowDiv = document.createElement('div');
+ shadowDiv.innerHTML = '<content select=".clazz1"></content>';
+ s.appendChild(shadowDiv);
+
+ //element outside the shadow tree
+ var inp4 = d.createElement('input');
+ inp4.setAttribute('id', 'inp4');
+ inp4.setAttribute('type', 'checkbox');
+ inp4.setAttribute('class', 'clazz1');
+ d.body.appendChild(inp4);
+
+ inp4.focus();
+
+ s.addEventListener('DOMFocusIn', A_05_03_01_T06.step_func(function(event) {
+ assert_equals(event.target.getAttribute('id'), 'inp1', 'Inside shadow tree: ' +
+ 'Event for nodes, distributed ' +
+ 'agains insertion points shouldn\'t be retargeted');
+ }), false);
+
+
+ d.body.addEventListener('DOMFocusIn', A_05_03_01_T05.step_func(function(event) {
+ assert_equals(event.target.getAttribute('id'), 'inp1', 'Outside shadow tree: ' +
+ 'Event for nodes, distributed ' +
+ 'agains insertion points shouldn\'t be retargeted');
+ }), false);
+
+ inp1.focus();
+
+ A_05_03_01_T06.done();
+}));
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/events/retargeting-focus-events/test-002.html b/tests/wpt/web-platform-tests/shadow-dom/events/retargeting-focus-events/test-002.html
new file mode 100644
index 00000000000..7ce91498a95
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/events/retargeting-focus-events/test-002.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_05_03_02</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#retargeting-focus-events">
+<meta name="assert" content="Retargeting focus events:The blur event must be treated in the same way as events with a relatedTarget, where the node that is gaining focus causing the blurring of target acts as the related target">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+//test blur event
+var A_05_03_02_T01 = async_test('A_05_03_02_T01');
+
+
+A_05_03_02_T01.step(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var invoked = false;
+
+ var roots = createTestMediaPlayer(d);
+
+ roots.playerShadowRoot.querySelector('.volume-slider').focus();
+
+ //expected result of what relative target should be see
+ //see at http://www.w3.org/TR/shadow-dom/#event-retargeting-example
+
+ //For #volume-slider relative target is #volume-slider
+ roots.playerShadowRoot.querySelector('.volume-slider').addEventListener('blur',
+ A_05_03_02_T01.step_func(function(event) {
+ invoked = true;
+ assert_equals(event.target.getAttribute('id'), 'volume-slider',
+ 'Wrong target');
+ }), false);
+
+ // move focus out of shadow tree. blur should be fired
+ d.querySelector('#outside-control').focus();
+
+ assert_true(invoked, 'Event listener was not invoked');
+
+ A_05_03_02_T01.done();
+}));
+
+
+//TODO (sgrekhov) add test for the case when related target differs from the
+//node on which event listener is invoked
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/events/retargeting-focus-events/test-003.html b/tests/wpt/web-platform-tests/shadow-dom/events/retargeting-focus-events/test-003.html
new file mode 100644
index 00000000000..a565f8ddf26
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/events/retargeting-focus-events/test-003.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_05_03_03</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#retargeting-focus-events">
+<meta name="assert" content="Retargeting focus events:The focus event must be treated in the same way as events with a relatedTarget, where the corresponding node that is losing focus as a result of target gaining focus or the node that is gaining focus">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+//test focus event
+var A_05_03_03_T01 = async_test('A_05_03_03_T01');
+
+
+A_05_03_03_T01.step(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var invoked = false;
+
+ var roots = createTestMediaPlayer(d);
+
+ d.querySelector('#outside-control').focus();
+
+ //expected result of what relative target should be see
+ //see at http://www.w3.org/TR/shadow-dom/#event-retargeting-example
+
+ //For #volume-slider relative target is #volume-slider
+ roots.playerShadowRoot.querySelector('.volume-slider').addEventListener('focus',
+ A_05_03_03_T01.step_func(function(event) {
+ invoked = true;
+ assert_equals(event.target.getAttribute('id'), 'volume-slider',
+ 'Wrong target');
+ }), false);
+
+ roots.playerShadowRoot.querySelector('.volume-slider').focus();
+
+ assert_true(invoked, 'Event listener was not invoked');
+
+ A_05_03_03_T01.done();
+}));
+
+
+//TODO (sgrekhov) add test for the case when related target differs from the
+//node on which event listener is invoked
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/events/retargeting-relatedtarget/test-001.html b/tests/wpt/web-platform-tests/shadow-dom/events/retargeting-relatedtarget/test-001.html
new file mode 100644
index 00000000000..1c60896737e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/events/retargeting-relatedtarget/test-001.html
@@ -0,0 +1,69 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_05_02_01</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-201305214#retargeting-related-target">
+<meta name="assert" content="Retargeting relatedTarget:Event retargeting is a process of computing relative targets for each ancestor of the node at which the event is dispatched. A relative target is a DOM node that most accurately represents the target of a dispatched event at a given ancestor while maintaining the upper boundary encapsulation.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_05_02_01_T01 = async_test('A_05_02_01_T1');
+
+A_05_02_01_T01.step(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var host = d.createElement('div');
+ host.setAttribute('style', 'height:100%; width:100%');
+ host.setAttribute('id', 'host');
+ d.body.appendChild(host);
+
+ //Shadow root to play with
+ var s = host.createShadowRoot();
+
+ var div1 = d.createElement('div');
+ div1.setAttribute('style', 'height:40px; width:100%');
+ div1.setAttribute('id', 'div1');
+ s.appendChild(div1);
+
+ var div2 = d.createElement('div');
+ div2.setAttribute('style', 'height:40px; width:100%');
+ div2.setAttribute('id', 'div2');
+ s.appendChild(div2);
+
+ s.addEventListener('mouseover', A_05_02_01_T01.step_func(function(event) {
+ assert_equals(event.relatedTarget.getAttribute('id'), 'div1', 'Wrong relatedTarget');
+ }), false);
+
+ d.body.addEventListener('mouseover', A_05_02_01_T01.step_func(function(event) {
+ assert_true(false, 'Event must be stopped at Shadow boundary');
+ }), false);
+
+
+ var evt = document.createEvent("MouseEvents");
+ evt.initMouseEvent("mouseover", true, false, window,
+ 0, 10, 10, 10, 10, false, false, false, false, 0, div1);
+
+ div2.dispatchEvent(evt);
+
+
+ A_05_02_01_T01.done();
+}));
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/events/retargeting-relatedtarget/test-002.html b/tests/wpt/web-platform-tests/shadow-dom/events/retargeting-relatedtarget/test-002.html
new file mode 100644
index 00000000000..98f52072ce8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/events/retargeting-relatedtarget/test-002.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_05_02_02</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-201305214#retargeting-related-target">
+<meta name="assert" content="Retargeting relatedTarget:For a given node, the relatedTarget must be changed to its ancestor (or self) that is in the same shadow tree as the node">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_05_02_02_T01 = async_test('A_05_02_02_T01');
+
+A_05_02_02_T01.step(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var host = d.createElement('div');
+ host.setAttribute('style', 'height:50%; width:100%');
+ host.setAttribute('id', 'host');
+ d.body.appendChild(host);
+
+ //Shadow root to play with
+ var s = host.createShadowRoot();
+
+ var div1 = d.createElement('div');
+ div1.setAttribute('style', 'height:100%; width:100%');
+ div1.setAttribute('id', 'div1');
+ s.appendChild(div1);
+
+ var div2 = d.createElement('div');
+ div2.setAttribute('style', 'height:100%; width:100%');
+ div2.setAttribute('id', 'div2');
+ d.body.appendChild(div2);
+
+ d.body.addEventListener('mouseover', A_05_02_02_T01.step_func(function(event) {
+ assert_equals(event.relatedTarget.getAttribute('id'), 'host', 'Wrong related target');
+ }), false);
+
+
+ var evt = document.createEvent("MouseEvents");
+ evt.initMouseEvent("mouseover", true, false, window,
+ 0, 10, 10, 10, 10, false, false, false, false, 0, div1);
+
+ div2.dispatchEvent(evt);
+
+ A_05_02_02_T01.done();
+}));
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/events/retargeting-relatedtarget/test-003.html b/tests/wpt/web-platform-tests/shadow-dom/events/retargeting-relatedtarget/test-003.html
new file mode 100644
index 00000000000..d10ae575e60
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/events/retargeting-relatedtarget/test-003.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_05_02_03</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-201305214#retargeting-related-target">
+<meta name="assert" content="Retargeting relatedTarget:Event listeners must not be invoked on a node for which the target and relatedTarget are the same.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_05_02_03_T01 = async_test('A_05_02_03_T01');
+
+A_05_02_03_T01.step(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var host = d.createElement('div');
+ host.setAttribute('style', 'height:50%; width:100%');
+ host.setAttribute('id', 'host');
+ d.body.appendChild(host);
+
+ //Shadow root to play with
+ var s = host.createShadowRoot();
+
+ var div1 = d.createElement('div');
+ div1.setAttribute('style', 'height:100%; width:100%');
+ div1.setAttribute('id', 'div1');
+ s.appendChild(div1);
+
+ var div2 = d.createElement('div');
+ div2.setAttribute('style', 'height:100%; width:100%');
+ div2.setAttribute('id', 'div2');
+ s.appendChild(div2);
+
+ s.addEventListener('mouseover', A_05_02_03_T01.step_func(function(event) {
+ assert_true(false, 'Event listeners shouldn\'t be invoked if target and relatedTarget are the same');
+ }), false);
+
+
+ var evt = document.createEvent("MouseEvents");
+ evt.initMouseEvent("mouseover", true, false, window,
+ 0, 10, 10, 10, 10, false, false, false, false, 0, div1);
+
+ div1.dispatchEvent(evt);
+
+ A_05_02_03_T01.done();
+}));
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/events/test-001.html b/tests/wpt/web-platform-tests/shadow-dom/events/test-001.html
new file mode 100644
index 00000000000..cb3097ccff6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/events/test-001.html
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_05_00_01</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#events">
+<meta name="assert" content="Events:The mutation event types must never be dispatched in a shadow DOM subtree.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_05_00_01_T1 = async_test('A_05_00_01_T1');
+
+A_05_00_01_T1.step(function () {
+ var iframe = document.createElement('iframe');
+ iframe.src = '../resources/blank.html';
+ document.body.appendChild(iframe);
+
+ iframe.onload = A_05_00_01_T1.step_func(function () {
+
+ try {
+ var d = iframe.contentDocument;
+
+ var div = d.createElement('div');
+ d.body.appendChild(div);
+
+ var s = div.createShadowRoot();
+
+ var div2 = d.createElement('div');
+ s.appendChild(div2);
+
+ var inp = d.createElement('input');
+ inp.setAttribute('type', 'text');
+ inp.setAttribute('id', 'inpid');
+ div2.appendChild(inp);
+
+ div2.addEventListener('DOMAttrModified', A_05_00_01_T1.step_func(function (event) {
+ assert_true(false, 'The mutation event types must never be dispatched in a shadow DOM subtree');
+ }), false);
+ /*
+ var attr = inp.getAttributeNode ("value");
+ var event = d.createEvent('MutationEvent');
+ event.initMutationEvent ("DOMAttrModified", true, true, attr, null, 'new value', "value", MutationEvent.MODIFICATION);
+ inp.dispatchEvent(event);
+ */
+ inp.value = 'new value';
+ inp.setAttribute ("newAttr" , "firstValue");
+ inp.setAttribute ("newAttr" , "secondValue");
+ inp.removeAttribute ("newAttr");
+ } finally {
+ iframe.parentNode.removeChild(iframe);
+ }
+ A_05_00_01_T1.done();
+ });
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/html-elements-and-their-shadow-trees/test-001.html b/tests/wpt/web-platform-tests/shadow-dom/html-elements-and-their-shadow-trees/test-001.html
new file mode 100644
index 00000000000..029f26debe0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/html-elements-and-their-shadow-trees/test-001.html
@@ -0,0 +1,232 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_09_00_01</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#html-elements-and-their-shadow-trees">
+<meta name="assert" content="HTML Elements and Their Shadow Trees: If the element can have fallback content, UA should allow the shadow tree to contain at least one insertion point.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+//test iframe
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ // create element
+ var el = d.createElement('iframe');
+ d.body.appendChild(el);
+
+ el.innerHTML = '' +
+ '<span id="shadow">This is a node that should be distributed</span>' +
+ '<span id="flbk">This is a fallback content</span>';
+
+ var s = el.createShadowRoot();
+ s.innerHTML = '<content select="#shadow"></content>';
+
+ assert_true(d.querySelector('#shadow').offsetTop > 0, 'Iframe should allow at least one insertion point');
+ assert_equals(d.querySelector('#flbk').offsetTop, 0, 'Fallback content shouldn\'t be rendered');
+
+}), 'A_09_00_01_T01');
+
+
+//test object
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ // create element
+ var el = d.createElement('object');
+ d.body.appendChild(el);
+
+ el.innerHTML = '' +
+ '<span id="shadow">This is a node that should be distributed</span>' +
+ '<span id="flbk">This is a fallback content</span>';
+
+ var s = el.createShadowRoot();
+ s.innerHTML = '<content select="#shadow"></content>';
+
+ assert_true(d.querySelector('#shadow').offsetTop > 0, 'object should allow at least one insertion point');
+ assert_equals(d.querySelector('#flbk').offsetTop, 0, 'Fallback content shouldn\'t be rendered');
+
+}), 'A_09_00_01_T02');
+
+
+//test video
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ // create element
+ var el = d.createElement('video');
+ d.body.appendChild(el);
+
+ el.innerHTML = '' +
+ '<span id="shadow">This is a node that should be distributed</span>' +
+ '<span id="flbk">This is a fallback content</span>';
+
+ var s = el.createShadowRoot();
+ s.innerHTML = '<content select="#shadow"></content>';
+
+ assert_true(d.querySelector('#shadow').offsetTop > 0, 'video should allow at least one insertion point');
+ assert_equals(d.querySelector('#flbk').offsetTop, 0, 'Fallback content shouldn\'t be rendered');
+
+}), 'A_09_00_01_T03');
+
+
+//test audio
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ // create element
+ var el = d.createElement('audio');
+ d.body.appendChild(el);
+
+ el.innerHTML = '' +
+ '<span id="shadow">This is a node that should be distributed</span>' +
+ '<span id="flbk">This is a fallback content</span>';
+
+ var s = el.createShadowRoot();
+ s.innerHTML = '<content select="#shadow"></content>';
+
+ assert_true(d.querySelector('#shadow').offsetTop > 0, 'audio should allow at least one insertion point');
+ assert_equals(d.querySelector('#flbk').offsetTop, 0, 'Fallback content shouldn\'t be rendered');
+
+}), 'A_09_00_01_T04');
+
+
+//test canvas
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ // create element
+ var el = d.createElement('canvas');
+ d.body.appendChild(el);
+
+ el.innerHTML = '' +
+ '<span id="shadow">This is a node that should be distributed</span>' +
+ '<span id="flbk">This is a fallback content</span>';
+
+ var s = el.createShadowRoot();
+ s.innerHTML = '<content select="#shadow"></content>';
+
+ assert_true(d.querySelector('#shadow').offsetTop > 0, 'canvas should allow at least one insertion point');
+ assert_equals(d.querySelector('#flbk').offsetTop, 0, 'Fallback content shouldn\'t be rendered');
+
+}), 'A_09_00_01_T05');
+
+
+//test map
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var img = d.createElement('img');
+ img.setAttribute('usemap', '#theMap');
+ img.setAttribute('width', '20px');
+ img.setAttribute('height', '20px');
+ d.body.appendChild(img);
+
+
+ // create element
+ var el = d.createElement('map');
+ el.setAttribute('name', 'theMap');
+ d.body.appendChild(el);
+
+ el.innerHTML = '' +
+ '<span id="shadow">This is a node that should be distributed</span>' +
+ '<span id="flbk">This is a fallback content</span>';
+
+
+ var s = el.createShadowRoot();
+ s.innerHTML = '<content select="#shadow"></content>';
+
+ assert_true(d.querySelector('#shadow').offsetTop > 0, 'map should allow at least one insertion point');
+ assert_equals(d.querySelector('#flbk').offsetTop, 0, 'Fallback content shouldn\'t be rendered');
+
+}), 'A_09_00_01_T06');
+
+
+//test textarea
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ // create element
+ var el = d.createElement('textarea');
+ d.body.appendChild(el);
+
+ el.innerHTML = '' +
+ '<span id="shadow">This is a node that should be distributed</span>' +
+ '<span id="flbk">This is a fallback content</span>';
+
+ var s = el.createShadowRoot();
+ s.innerHTML = '<content select="#shadow"></content>';
+
+ assert_true(d.querySelector('#shadow').offsetTop > 0, 'textarea should allow at least one insertion point');
+ assert_equals(d.querySelector('#flbk').offsetTop, 0, 'Fallback content shouldn\'t be rendered');
+
+}), 'A_09_00_01_T07');
+
+
+//test progress
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ // create element
+ var el = d.createElement('progress');
+ d.body.appendChild(el);
+
+ el.innerHTML = '' +
+ '<span id="shadow">This is a node that should be distributed</span>' +
+ '<span id="flbk">This is a fallback content</span>';
+
+ var s = el.createShadowRoot();
+ s.innerHTML = '<content select="#shadow"></content>';
+
+ assert_true(d.querySelector('#shadow').offsetTop > 0, 'progress should allow at least one insertion point');
+ assert_equals(d.querySelector('#flbk').offsetTop, 0, 'Fallback content shouldn\'t be rendered');
+
+}), 'A_09_00_01_T08');
+
+
+//test meter
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ // create element
+ var el = d.createElement('meter');
+ d.body.appendChild(el);
+
+ el.innerHTML = '' +
+ '<span id="shadow">This is a node that should be distributed</span>' +
+ '<span id="flbk">This is a fallback content</span>';
+
+ var s = el.createShadowRoot();
+ s.innerHTML = '<content select="#shadow"></content>';
+
+ assert_true(d.querySelector('#shadow').offsetTop > 0, 'meter should allow at least one insertion point');
+ assert_equals(d.querySelector('#flbk').offsetTop, 0, 'Fallback content shouldn\'t be rendered');
+
+}), 'A_09_00_01_T09');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/html-elements-and-their-shadow-trees/test-002.html b/tests/wpt/web-platform-tests/shadow-dom/html-elements-and-their-shadow-trees/test-002.html
new file mode 100644
index 00000000000..d5b4705370e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/html-elements-and-their-shadow-trees/test-002.html
@@ -0,0 +1,82 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_09_00_02</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#html-elements-and-their-shadow-trees">
+<meta name="assert" content="HTML Elements and Their Shadow Trees: Elements that have no fallback content should allow the shadow tree to contain no insertion points or an insertion point that matches nothing">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+//test img
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ // create element
+ var el = d.createElement('img');
+ d.body.appendChild(el);
+
+ var s = el.createShadowRoot();
+
+ s.innerHTML = '<content id="cont" select="#shadow"></content>';
+
+ assert_true(s.querySelector('#cont') != null, 'img should allow one insertion point ' +
+ 'that matches nothing');
+
+}), 'A_09_00_02_T01');
+
+
+//test embed
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ // create element
+ var el = d.createElement('embed');
+ d.body.appendChild(el);
+
+ var s = el.createShadowRoot();
+
+ s.innerHTML = '<content id="cont" select="#shadow"></content>';
+
+ assert_true(s.querySelector('#cont') != null, 'embed should allow one insertion point ' +
+ 'that matches nothing');
+
+}), 'A_09_00_02_T02');
+
+
+//test embed
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ // create element
+ var el = d.createElement('input');
+ d.body.appendChild(el);
+
+ var s = el.createShadowRoot();
+
+ s.innerHTML = '<content id="cont" select="#shadow"></content>';
+
+ assert_true(s.querySelector('#cont') != null, 'input should allow one insertion point ' +
+ 'that matches nothing');
+
+}), 'A_09_00_02_T03');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/html-elements-and-their-shadow-trees/test-003.html b/tests/wpt/web-platform-tests/shadow-dom/html-elements-and-their-shadow-trees/test-003.html
new file mode 100644
index 00000000000..00c20159995
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/html-elements-and-their-shadow-trees/test-003.html
@@ -0,0 +1,73 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_09_00_03</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#html-elements-and-their-shadow-trees">
+<meta name="assert" content="HTML Elements and Their Shadow Trees: Check that fieldset can contain at least two insertion points with matching criteria 'legend:first-of-type' and 'universal selector'">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+//test universal selector
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ // create element
+ var el = d.createElement('fieldset');
+ d.body.appendChild(el);
+
+ el.innerHTML = '' +
+ '<span id="shadow">This is a node that should be distributed</span>' +
+ '<span id="flbk">This is a fallback content</span>';
+
+ var s = el.createShadowRoot();
+ s.innerHTML = '<content select="#shadow"></content>';
+
+ assert_true(d.querySelector('#shadow').offsetTop > 0, 'fieldset should allow at least one insertion point');
+ assert_equals(d.querySelector('#flbk').offsetTop, 0, 'Fallback content shouldn\'t be rendered');
+
+}), 'A_09_00_03_T01');
+
+
+
+//test legend:first-of-type
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ // create element
+ var el = d.createElement('fieldset');
+ d.body.appendChild(el);
+
+ el.innerHTML = '' +
+ '<legend>'
+ '<span id="shadow">This is a node that should be distributed</span>' +
+ '</legend>' +
+ '<span id="flbk">Unlucky content</span>';
+
+ var s = el.createShadowRoot();
+ s.innerHTML = '<content select="legend:first-of-type"></content>';
+
+ assert_true(d.querySelector('#shadow').offsetTop > 0, 'fieldset should allow insertion point ' +
+ 'with legend:first-of-type matching criteria');
+ assert_equals(d.querySelector('#flbk').offsetTop, 0, 'Fallback content shouldn\'t be rendered');
+
+}), 'A_09_00_03_T02');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/html-elements-and-their-shadow-trees/test-004.html b/tests/wpt/web-platform-tests/shadow-dom/html-elements-and-their-shadow-trees/test-004.html
new file mode 100644
index 00000000000..579f9616a06
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/html-elements-and-their-shadow-trees/test-004.html
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_09_00_04</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#html-elements-and-their-shadow-trees">
+<meta name="assert" content="HTML Elements and Their Shadow Trees: Check that details can contain at least two insertion points with matching criteria 'summary:first-of-type' and 'universal selector'">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+//test universal selector
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ // create element
+ var el = d.createElement('details');
+ el.setAttribute('open', 'open');
+ d.body.appendChild(el);
+
+ el.innerHTML = '' +
+ '<span id="shadow">This is a node that should be distributed</span>' +
+ '<span id="flbk">This is a fallback content</span>';
+
+ var s = el.createShadowRoot();
+ s.innerHTML = '<content select="#shadow"></content>';
+
+ assert_true(d.querySelector('#shadow').offsetTop > 0, '\'details\' should allow at least one insertion point');
+ assert_equals(d.querySelector('#flbk').offsetTop, 0, 'Fallback content shouldn\'t be rendered');
+
+}), 'A_09_00_04_T01');
+
+
+
+//test summary:first-of-type
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ // create element
+ var el = d.createElement('details');
+ el.setAttribute('open', 'open');
+ d.body.appendChild(el);
+
+ el.innerHTML = '' +
+ '<summary>' +
+ '<span id="shadow">This is a node that should be distributed</span>' +
+ '</summary>' +
+ '<span id="flbk">Unlucky content</span>';
+
+ var s = el.createShadowRoot();
+ s.innerHTML = '<content select="summary:first-of-type"></content>';
+
+ assert_true(d.querySelector('#shadow').offsetTop > 0, 'details should allow insertion point' +
+ 'with summary:first-of-type matching criteria');
+ assert_equals(d.querySelector('#flbk').offsetTop, 0, 'Fallback content shouldn\'t be rendered');
+
+}), 'A_09_00_04_T02');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/html-elements-in-shadow-trees/html-forms/test-001.html b/tests/wpt/web-platform-tests/shadow-dom/html-elements-in-shadow-trees/html-forms/test-001.html
new file mode 100644
index 00000000000..aea6682bd07
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/html-elements-in-shadow-trees/html-forms/test-001.html
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_08_02_01</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#html-forms">
+<meta name="assert" content="HTML Elements in shadow trees: Form elements and form-associated elements in shadow tree are not accessible using document DOM object's tree accessors">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+//test form-associated elements
+test(function () {
+ var d = newHTMLDocument();
+
+ var form = d.createElement('form');
+ form.setAttribute('id', 'form_id');
+ d.body.appendChild(form);
+
+ var div = d.createElement('div');
+ d.body.appendChild(div);
+ var s = div.createShadowRoot();
+
+
+ HTML5_FORM_ASSOCIATED_ELEMENTS.forEach(function (tagName) {
+
+ var el = d.createElement(tagName);
+ el.setAttribute('form', 'form_id');
+ el.setAttribute('id', tagName + '_id');
+ s.appendChild(el);
+
+ assert_equals(d.querySelector('#' + tagName + '_id'), null, 'Form-associated element ' + tagName +
+ ' in shadow tree must not be accessible using owner\'s document tree accessors');
+ });
+}, 'A_08_02_01_T01');
+
+
+//test form elements
+test(function () {
+ var d = newHTMLDocument();
+
+ var form = d.createElement('form');
+ d.body.appendChild(form);
+
+ var div = d.createElement('div');
+ form.appendChild(div);
+ s = div.createShadowRoot();
+
+ HTML5_FORM_ASSOCIATED_ELEMENTS.forEach(function (tagName) {
+
+ var el = d.createElement(tagName);
+ el.setAttribute('id', tagName + '_id');
+ s.appendChild(el);
+
+ assert_equals(d.querySelector('#' + tagName + '_id'), null, 'Form element ' + tagName +
+ ' in shadow tree must not be accessible using owner\'s document tree accessors');
+ });
+}, 'A_08_02_01_T02');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/html-elements-in-shadow-trees/html-forms/test-002.html b/tests/wpt/web-platform-tests/shadow-dom/html-elements-in-shadow-trees/html-forms/test-002.html
new file mode 100644
index 00000000000..8d7eb575878
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/html-elements-in-shadow-trees/html-forms/test-002.html
@@ -0,0 +1,103 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_08_02_02</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#html-forms">
+<meta name="assert" content="HTML Elements in shadow trees: Form elements and form-associated elements in shadow tree must be accessible using shadow tree accessors">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+//test form-associated elements
+test(function () {
+ var d = newHTMLDocument();
+
+ var form = d.createElement('form');
+ form.setAttribute('id', 'form_id');
+ d.body.appendChild(form);
+
+ var div = d.createElement('div');
+ d.body.appendChild(div);
+ var s = div.createShadowRoot();
+
+
+ HTML5_FORM_ASSOCIATED_ELEMENTS.forEach(function (tagName) {
+
+ var el = d.createElement(tagName);
+ el.setAttribute('form', 'form_id');
+ el.setAttribute('id', tagName + '_id');
+ s.appendChild(el);
+
+ assert_true(s.querySelector('#' + tagName + '_id') != null, 'Form-associated element ' + tagName +
+ ' in shadow tree must be accessible shadow tree accessors');
+ assert_equals(s.querySelector('#' + tagName + '_id').getAttribute('id'), tagName + '_id',
+ 'Form-associated element ' + tagName + ' in shadow tree must be accessible shadow tree accessors');
+ });
+}, 'A_08_02_02_T01');
+
+
+//test form elements
+test(function () {
+ var d = newHTMLDocument();
+
+ var form = d.createElement('form');
+ d.body.appendChild(form);
+
+ var div = d.createElement('div');
+ form.appendChild(div);
+ var s = div.createShadowRoot();
+
+ HTML5_FORM_ASSOCIATED_ELEMENTS.forEach(function (tagName) {
+
+ var el = d.createElement(tagName);
+ el.setAttribute('id', tagName + '_id');
+ s.appendChild(el);
+
+ assert_true(s.querySelector('#' + tagName + '_id') != null, 'Form-associated element ' + tagName +
+ ' in shadow tree must be accessible shadow tree accessors');
+ assert_equals(s.querySelector('#' + tagName + '_id').getAttribute('id'), tagName + '_id',
+ 'Form element ' + tagName + ' in shadow tree must be accessible shadow tree accessors');
+ });
+}, 'A_08_02_02_T02');
+
+
+//test distributed form elements
+test(function () {
+ var d = newHTMLDocument();
+
+ HTML5_FORM_ASSOCIATED_ELEMENTS.forEach(function (tagName) {
+
+ var form = d.createElement('form');
+ d.body.appendChild(form);
+
+ var div = d.createElement('div');
+ form.appendChild(div);
+
+ var el = d.createElement(tagName);
+ el.setAttribute('id', tagName + '_id');
+ div.appendChild(el);
+
+ var s = div.createShadowRoot();
+ s.innerHTML = '<content select="' + tagName + '"></content>';
+
+ assert_true(s.querySelector('#' + tagName + '_id') == null, 'Distributed form-associated element ' + tagName +
+ ' in shadow tree must not be accessible shadow tree accessors');
+ });
+}, 'A_08_02_02_T03');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/html-elements-in-shadow-trees/html-forms/test-003.html b/tests/wpt/web-platform-tests/shadow-dom/html-elements-in-shadow-trees/html-forms/test-003.html
new file mode 100644
index 00000000000..78a0749420d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/html-elements-in-shadow-trees/html-forms/test-003.html
@@ -0,0 +1,90 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_08_02_03</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#inert-html-elements">
+<meta name="assert" content="HTML Elements in shadow trees: form should submit elements in shadow tree">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_08_02_03_T01 = async_test('A_08_02_03_T01', { timeout: 5000 });
+
+A_08_02_03_T01.checkIframeContent = A_08_02_03_T01.step_func(function () {
+ //remember value to check before cleaning the context (it'll destroy the iframe)
+ var valueToCheck = A_08_02_03_T01.iframe.contentWindow.document.URL;
+ cleanContext(A_08_02_03_T01.ctx);
+
+ assert_true(valueToCheck.indexOf('inp1=value1') > 0,
+ 'html form should submit all of its fields');
+
+ // Expected behavior is not quite clear. See https://www.w3.org/Bugs/Public/show_bug.cgi?id=20320
+ assert_true(valueToCheck.indexOf('inp2=value2') > 0,
+ 'html form should submit all of its fields including the shadow ones');
+
+ A_08_02_03_T01.done();
+});
+
+
+A_08_02_03_T01.step(function () {
+
+ A_08_02_03_T01.ctx = newContext();
+ var d = newRenderedHTMLDocument(A_08_02_03_T01.ctx);
+
+ //create iframe
+ var iframe = document.createElement('iframe');
+
+ iframe.src = '../../resources/blank.html';
+ iframe.setAttribute('name', 'targetIframe');
+ d.body.appendChild(iframe);
+
+ A_08_02_03_T01.iframe = iframe;
+
+ // create form
+ var form = d.createElement('form');
+ form.setAttribute('target', 'targetIframe');
+ form.setAttribute('method', 'GET');
+ form.setAttribute('action', '../../resources/blank.html');
+ d.body.appendChild(form);
+
+ //create Shadow root
+ var root = d.createElement('div');
+ form.appendChild(root);
+ var s = root.createShadowRoot();
+
+
+ var input1 = d.createElement('input');
+ input1.setAttribute('type', 'text');
+ input1.setAttribute('name', 'inp1');
+ input1.setAttribute('value', 'value1');
+ form.appendChild(input1);
+
+ var input2 = d.createElement('input');
+ input2.setAttribute('type', 'text');
+ input2.setAttribute('name', 'inp2');
+ input2.setAttribute('value', 'value2');
+ s.appendChild(input2);
+
+ //submit the form
+ form.submit();
+
+ // set timeout to give the iframe time to load content
+ setTimeout('A_08_02_03_T01.checkIframeContent()', 2000);
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/html-elements-in-shadow-trees/inert-html-elements/test-001.html b/tests/wpt/web-platform-tests/shadow-dom/html-elements-in-shadow-trees/inert-html-elements/test-001.html
new file mode 100644
index 00000000000..b283c63c998
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/html-elements-in-shadow-trees/inert-html-elements/test-001.html
@@ -0,0 +1,80 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_08_01_01</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#inert-html-elements">
+<meta name="assert" content="HTML Elements in shadow trees: base element must behave as inert, or not part of the document tree">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_08_01_01_T01 = async_test('A_08_01_01_T01', { timeout: 5000 });
+
+A_08_01_01_T01.checkIframeContent = A_08_01_01_T01.step_func(function () {
+ //remember value to check before cleaning the context (it'll destroy the iframe)
+ var valueToCheck = A_08_01_01_T01.iframe.contentWindow;
+ cleanContext(A_08_01_01_T01.ctx);
+
+ assert_equals(valueToCheck, null,
+ 'base html element ih a shadow tree must beahve like inert one');
+
+ A_08_01_01_T01.done();
+});
+
+
+A_08_01_01_T01.step(function () {
+
+ A_08_01_01_T01.ctx = newContext();
+ var d = newRenderedHTMLDocument(A_08_01_01_T01.ctx);
+
+ //create iframe
+ var iframe = document.createElement('iframe');
+
+ iframe.src = '../../resources/blank.html';
+ iframe.setAttribute('name', 'targetIframe');
+ d.body.appendChild(iframe);
+
+ A_08_01_01_T01.iframe = iframe;
+
+ // create a link
+ var link = d.createElement('a');
+ link.setAttribute('href', '../../resources/bobs_page.html');
+ link.innerHTML = 'the link';
+ d.body.appendChild(link);
+
+ //create Shadow root
+ var root = d.createElement('div');
+ d.body.appendChild(root);
+ var s = root.createShadowRoot();
+
+ // create base element, set iframe as a target
+ var base = d.createElement('base');
+ base.setAttribute('target', 'targetIframe');
+ s.appendChild(base);
+
+ //click the link
+ link.click();
+
+ //Expected: base should be inert therefore document d
+ // should be reloaded, so iframe context shouldn't be affected
+
+ // set timeout to give the iframe time to load content
+ setTimeout('A_08_01_01_T01.checkIframeContent()', 2000);
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/html-elements-in-shadow-trees/inert-html-elements/test-002.html b/tests/wpt/web-platform-tests/shadow-dom/html-elements-in-shadow-trees/inert-html-elements/test-002.html
new file mode 100644
index 00000000000..bb7903938b9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/html-elements-in-shadow-trees/inert-html-elements/test-002.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_08_01_02</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#inert-html-elements">
+<meta name="assert" content="HTML Elements in shadow trees: link element must behave as inert not as part of the document tree">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var link = d.createElement('link');
+ link.setAttribute('href', 'testharness.css');
+ link.setAttribute('rel', 'stylesheet');
+
+ //create Shadow root
+ var root = d.createElement('div');
+ d.body.appendChild(root);
+ var s = root.createShadowRoot();
+
+ s.appendChild(link);
+
+ assert_equals(d.styleSheets.length, 0, 'link element must behave as inert not as part of the document tree');
+
+
+}), 'A_08_01_02_T01');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/resources/blank.html b/tests/wpt/web-platform-tests/shadow-dom/resources/blank.html
new file mode 100644
index 00000000000..5469aa6d0a1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/resources/blank.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html>
+<head></head>
+<body></body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/shadow-dom/resources/bobs_page.html b/tests/wpt/web-platform-tests/shadow-dom/resources/bobs_page.html
new file mode 100644
index 00000000000..c5b04eb1fb7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/resources/bobs_page.html
@@ -0,0 +1,35 @@
+<html>
+<head>
+</head>
+<body>
+ <ul class='stories'>
+ <li id='li1'><a href='#1'>Link1</a></li>
+ <li id='li2' title="li2"><a href='#2'>Link 2</a></li>
+ <li id='li3' class='shadow'><a href='#3'>Link 3 Shadow</a></li>
+ <li id='li4' class='shadow2'><a href='#4'>Link 4 Shadow 2</a></li>
+ <li id='li5'><a id="a5" class="shadow" href='#5'>Link 5</a></li>
+ <li id='li6' class='shadow'><a href='#5'>Link 6 Shadow</a></li>
+ </ul>
+ <div id="divid" class='breaking'>
+ <span id='spandex'>Some text</span>
+ <ul id="ul2">
+ <li id='li11'>Item 11</li>
+ <li id='li12'>Item 12</li>
+ <li id='li13' class='shadow'>Item 13 Shadow</li>
+ <li id='li14' class='shadow2'>Item 14 Shadow 2</li>
+ <li id='li15'>Item 15</li>
+ <li id='li16' class='shadow'>Item 16 Shadow</li>
+ </ul>
+ </div>
+ <div id="links-wrapper">
+ <a href='#10' id='link10'>Link 10</a>
+ <a href='#11' id='link11'>Link 11</a>
+ </div>
+ <div id="inputs-wrapper">
+ <input type='text' id='inp1' disabled/>
+ <input type='text' id='inp2'/>
+ <input type='checkbox' id='chb1' checked>
+ <input type='checkbox' id='chb2'>
+ </div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/composition/test-001.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/composition/test-001.html
new file mode 100644
index 00000000000..f180a805036
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/composition/test-001.html
@@ -0,0 +1,164 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_04_07_01</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#multiple-shadow-subtrees">
+<meta name="assert" content="Composition:Composition algorithm">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(unit(function (ctx) {
+ var d = newRenderedHTMLDocument(ctx);
+ var div = d.createElement('div');
+ div.innerHTML = '' +
+ '<ul id="host">' +
+ '<li id="li1" class="shadow">' +
+ '<a id="a11" class="cl1" href="#">Link11 Shadow</a>' +
+ '<a id="a12" class="cl2" href="#">Link12 Shadow</a>' +
+ '<a id="a13" class="cl1" href="#">Link13 Shadow</a>' +
+ '</li>' +
+ '<li id="li2">' +
+ '<a id="a21" href="#">Link21</a><a id="a22" href="#">Link22</a>' +
+ '</li>' +
+ '<li id="li3" class="shadow">' +
+ '<a id="a31" href="#">Link31 Shadow</a><a id="a32" href="#">Link32 Shadow</a>' +
+ '</li>' +
+ '<li id="li4" class="shadow2">' +
+ '<a id="a41" href="#">Link41 Shadow 2</a><a id="a42" href="#">Link22 Shadow 2</a>' +
+ '</li>' +
+ '<li id="li5" class="shadow2">' +
+ '<a id="a51" href="#">Link51 Shadow</a><a id="a52" href="#">Link52 Shadow 2</a>' +
+ '</li>' +
+ '</ul>';
+
+ d.body.appendChild(div);
+
+ //make nested shadow tree to check the reprojection
+ var li1 = d.querySelector('#li1');
+ var s = li1.createShadowRoot();
+ var shadowLI1 = document.createElement('li');
+ shadowLI1.innerHTML = '<content select=".cl1"></content>';
+ s.appendChild(shadowLI1);
+
+ //Shadow root to play with
+ var ul = d.querySelector('#host');
+
+ //make an old shadow tree
+ var s2 = ul.createShadowRoot();
+ var div2 = d.createElement('div');
+ div2.innerHTML = '<ul><content select=".shadow2"></content></ul>';
+ s2.appendChild(div2);
+
+ // At this point visible: li4 and li5
+ assert_true(d.querySelector('#li4').offsetTop > 0, 'Point 1: Node that match insertion ' +
+ 'point criteria should be rendered');
+ assert_true(d.querySelector('#li5').offsetTop > 0, 'Point 2: Node that match insertion ' +
+ 'point criteria should be rendered');
+ assert_equals(d.querySelector('#li1').offsetTop, 0, 'Point 3: Node that doen\'t match ' +
+ 'insertion point criteria shouldn\'t be rendered');
+ assert_equals(d.querySelector('#li2').offsetTop, 0, 'Point 4: Node that doen\'t match ' +
+ 'insertion point criteria shouldn\'t be rendered');
+ assert_equals(d.querySelector('#li3').offsetTop, 0, 'Point 5: Node that doen\'t match ' +
+ 'insertion point criteria shouldn\'t be rendered');
+
+ //check the nested tree
+ assert_equals(d.querySelector('#a11').offsetTop, 0,
+ 'Point 6: Aleady distributed nodes should behave like a shadow host child nodes');
+ assert_equals(d.querySelector('#a13').offsetTop, 0,
+ 'Point 7: Aleady distributed nodes should behave like a shadow host child nodes');
+ assert_equals(d.querySelector('#a12').offsetTop, 0,
+ 'Point 8: Aleady distributed nodes should behave like a shadow host child nodes');
+
+
+
+ //make a young shadow tree
+ var s3 = ul.createShadowRoot();
+ var div3 = d.createElement('div');
+ div3.innerHTML = '<ul><content select=".shadow"></content></ul>';
+ s3.appendChild(div3);
+
+ //At this point: li1 and li3 visible, others not
+ assert_true(d.querySelector('#li1').offsetTop > 0, 'Point 21: Node that match insertion ' +
+ 'point criteria should be rendered');
+ assert_true(d.querySelector('#li3').offsetTop > 0, 'Point 22: Node that match insertion ' +
+ 'point criteria should be rendered');
+ assert_equals(d.querySelector('#li2').offsetTop, 0, 'Point 23: Node that doen\'t match ' +
+ 'insertion point criteria shouldn\'t be rendered');
+ assert_equals(d.querySelector('#li4').offsetTop, 0, 'Point 24: Node that doen\'t match ' +
+ 'insertion point criteria shouldn\'t be rendered');
+ assert_equals(d.querySelector('#li5').offsetTop, 0, 'Point 25: Node that doen\'t match ' +
+ 'insertion point criteria shouldn\'t be rendered');
+
+ //check the reprojected nodes (a11 and a13 visible, a12 not)
+ assert_true(d.querySelector('#a11').offsetTop > 0,
+ 'Point 26: Aleady distributed nodes should behave like a shadow host child nodes');
+ assert_equals(d.querySelector('#a12').offsetTop, 0,
+ 'Point 27: Aleady distributed nodes should behave like a shadow host child nodes');
+ assert_true(d.querySelector('#a13').offsetTop > 0,
+ 'Point 28: Aleady distributed nodes should behave like a shadow host child nodes');
+
+ var shadow = d.createElement('shadow');
+ s3.appendChild(shadow);
+
+ //At this point: li1, li3, li4 and li5 visible li2 not
+ assert_true(d.querySelector('#li1').offsetTop > 0, 'Point 31: Node that match insertion ' +
+ 'point criteria should be rendered');
+ assert_true(d.querySelector('#li3').offsetTop > 0, 'Point 32: Node that match insertion ' +
+ 'point criteria should be rendered');
+ assert_equals(d.querySelector('#li2').offsetTop, 0, 'Point 33: Node that doen\'t match ' +
+ 'insertion point criteria shouldn\'t be rendered');
+ assert_true(d.querySelector('#li4').offsetTop > 0, 'Point 34: Node that doen\'t match ' +
+ 'insertion point criteria shouldn\'t be rendered');
+ assert_true(d.querySelector('#li5').offsetTop > 0, 'Point 35: Node that doen\'t match ' +
+ 'insertion point criteria shouldn\'t be rendered');
+
+ //check the reprojected nodes (a11 and a13 visible, a12 not)
+ assert_true(d.querySelector('#a11').offsetTop > 0,
+ 'Point 36: Aleady distributed nodes should behave like a shadow host child nodes');
+ assert_equals(d.querySelector('#a12').offsetTop, 0,
+ 'Point 37: Aleady distributed nodes should behave like a shadow host child nodes');
+ assert_true(d.querySelector('#a13').offsetTop > 0,
+ 'Point 38: Aleady distributed nodes should behave like a shadow host child nodes');
+
+ var shadow2 = d.createElement('shadow');
+ s3.appendChild(shadow2);
+
+ // Nothing should be changed
+ //At this point: li1, li3, li4 and li5 visible li2 not
+ assert_true(d.querySelector('#li1').offsetTop > 0, 'Point 41: Node that match insertion ' +
+ 'point criteria should be rendered');
+ assert_true(d.querySelector('#li3').offsetTop > 0, 'Point 42: Node that match insertion ' +
+ 'point criteria should be rendered');
+ assert_equals(d.querySelector('#li2').offsetTop, 0, 'Point 43: Node that doen\'t match ' +
+ 'insertion point criteria shouldn\'t be rendered');
+ assert_true(d.querySelector('#li4').offsetTop > 0, 'Point 44: Node that doen\'t match ' +
+ 'insertion point criteria shouldn\'t be rendered');
+ assert_true(d.querySelector('#li5').offsetTop > 0, 'Point 45: Node that doen\'t match ' +
+ 'insertion point criteria shouldn\'t be rendered');
+
+ //check the reprojected nodes (a11 and a13 visible, a12 not)
+ assert_true(d.querySelector('#a11').offsetTop > 0,
+ 'Point 46: Aleady distributed nodes should behave like a shadow host child nodes');
+ assert_equals(d.querySelector('#a12').offsetTop, 0,
+ 'Point 47: Aleady distributed nodes should behave like a shadow host child nodes');
+ assert_true(d.querySelector('#a13').offsetTop > 0,
+ 'Point 48: Aleady distributed nodes should behave like a shadow host child nodes');
+}), 'A_04_07_01');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/content-pseudo-element/test-001.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/content-pseudo-element/test-001.html
new file mode 100644
index 00000000000..ffafc7795e5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/content-pseudo-element/test-001.html
@@ -0,0 +1,77 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_04_04_01</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="author" title="Tetsuharu OHZEKI" href="mailto:saneyuki.snyk@gmail.com">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#distributed-pseudo-element">
+<meta name="assert" content="Matching Children, Distributed To Insertion Points">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_04_04_01_T1 = async_test('A_04_04_01_T01');
+
+A_04_04_01_T1.step(function () {
+ var iframe = document.createElement('iframe');
+ iframe.src = '../../resources/bobs_page.html';
+ document.body.appendChild(iframe);
+
+ iframe.onload = A_04_04_01_T1.step_func(function () {
+ try {
+ var d = iframe.contentDocument;
+
+ //make shadow tree
+ var ul = d.querySelector('ul.stories');
+ var s = createSR(ul);
+ var subdiv1 = d.createElement('div');
+ subdiv1.innerHTML = '<ul><content select="li"></content></ul>';
+ s.appendChild(subdiv1);
+
+ var shadowStyle = d.createElement('style');
+ shadowStyle.innerHTML = '*::content .shadow { display:none; }';
+ s.appendChild(shadowStyle);
+
+ //The order of DOM elements should be the following:
+ //li3, li6 - invisible. Other elements visible
+ var li3 = d.querySelector('#li3');
+ var li6 = d.querySelector('#li6');
+ assert_equals(window.getComputedStyle(li3).display, "none",
+ 'Point 1: Elements that don\'t mach insertion point criteria participate in distribution');
+ assert_equals(window.getComputedStyle(li6).display, "none",
+ 'Point 2: Elements that don\'t mach insertion point criteria participate in distribution');
+
+ var li1 = d.querySelector('#li1');
+ var li2 = d.querySelector('#li2');
+ var li4 = d.querySelector('#li4');
+ var li5 = d.querySelector('#li5');
+ assert_not_equals(window.getComputedStyle(li1).display, "none",
+ 'Point 3: ::content pseudo-element should be a valid insertion point matching criteria, element should be visible');
+ assert_not_equals(window.getComputedStyle(li2).display, "none",
+ 'Point 4: ::content pseudo-element should be a valid insertion point matching criteria, element should be visible');
+ assert_not_equals(window.getComputedStyle(li4).display, "none",
+ 'Point 5: ::content pseudo-element should be a valid insertion point matching criteria, element should be visible');
+ assert_not_equals(window.getComputedStyle(li5).display, "none",
+ 'Point 6: ::content pseudo-element should be a valid insertion point matching criteria, element should be visible');
+ } finally {
+ iframe.parentNode.removeChild(iframe);
+ }
+ A_04_04_01_T1.done();
+ });
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/content-pseudo-element/test-002.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/content-pseudo-element/test-002.html
new file mode 100644
index 00000000000..d583cfed4d6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/content-pseudo-element/test-002.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_04_04_01</title>
+<link rel="author" title="Tetsuharu OHZEKI" href="mailto:saneyuki.snyk@gmail.com">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#distributed-pseudo-element">
+<meta name="assert" content="::content pseudo-element, Relative Selector">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_04_04_01_T2 = async_test('A_04_04_01_T02');
+
+A_04_04_01_T2.step(function () {
+ var iframe = document.createElement('iframe');
+ iframe.src = '../../resources/bobs_page.html';
+ document.body.appendChild(iframe);
+
+ iframe.onload = A_04_04_01_T2.step_func(function () {
+ try {
+ var d = iframe.contentDocument;
+
+ //make shadow tree
+ var ul = d.querySelector('ul.stories');
+ var s = createSR(ul);
+ var subdiv1 = d.createElement('div');
+ subdiv1.innerHTML = '<ul><content select="li"></content></ul>';
+ s.appendChild(subdiv1);
+
+ var shadowStyle = d.createElement('style');
+ shadowStyle.innerHTML = '*::content > .shadow { display:none; }';
+ s.appendChild(shadowStyle);
+
+ //The order of DOM elements should be the following:
+ //li3, li6 - invisible. Other elements visible
+ var li3 = d.querySelector('#li3');
+ var li6 = d.querySelector('#li6');
+ assert_equals(window.getComputedStyle(li3).display, "none",
+ 'Point 1: Elements that don\'t mach insertion point criteria participate in distribution');
+ assert_equals(window.getComputedStyle(li6).display, "none",
+ 'Point 2: Elements that don\'t mach insertion point criteria participate in distribution');
+
+ var a5 = d.querySelector('#a5');
+ assert_not_equals(window.getComputedStyle(a5).display, "none",
+ 'Point 3: ::content pseudo-element with relative selector should be a valid insertion point matching criteria, element should be visible');
+ } finally {
+ iframe.parentNode.removeChild(iframe);
+ }
+ A_04_04_01_T2.done();
+ });
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/custom-pseudo-elements/test-001.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/custom-pseudo-elements/test-001.html
new file mode 100644
index 00000000000..a31030c4f59
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/custom-pseudo-elements/test-001.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_04_10_01</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#custom-pseudo-elements">
+<meta name="assert" content="Custom Pseudo-Elements: test valid pseudo-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+// Test fails. See https://bugs.webkit.org/show_bug.cgi?id=103973
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var style = d.createElement('style');
+ style.innerHTML = 'span {' +
+ 'font-size: 10px;' +
+ '}';
+ d.head.appendChild(style);
+
+ var widget = d.createElement('div');
+ d.body.appendChild(widget);
+
+ var s = widget.createShadowRoot();
+
+ var thumb = d.createElement('span');
+ thumb.innerHTML = 'This is a pseudo-element';
+ //FIXME test works if prefixed version of API used.
+ //In other words works if webkitPseudo property is used
+ //thumb.webkitPseudo = 'x-thumb';
+ thumb.pseudo = 'x-thumb';
+ s.appendChild(thumb);
+
+ var height = thumb.offsetHeight;
+
+ assert_true(height > 0, 'Element should be rendered');
+
+ style = d.createElement('style');
+ style.innerHTML = 'div::x-thumb {' +
+ 'font-size: 30px;' +
+ '}';
+ d.body.appendChild(style);
+
+ assert_true(thumb.offsetHeight > height, 'Pseudo-element style should be applied');
+
+}), 'A_04_10_01_T01');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-002-ref.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-002-ref.html
new file mode 100644
index 00000000000..6cc4b52ec6a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-002-ref.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Shadow DOM - The older tree is inserted into shadow, and the original branch is inserted into content.</title>
+ <link rel="author" title="Hiroyuki Hayashi" href="mailto:hyshhryk@gmail.com">
+ </head>
+ <body>
+ <div>
+ <p>Younger tree's node</p>
+ <p>Older tree's node</p>
+ <p>Original tree's node</p>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-002.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-002.html
new file mode 100644
index 00000000000..4d589b50550
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-002.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Shadow DOM Test - Tests shadow inserts older tree.</title>
+ <link rel="match" href="hosting-multiple-shadow-trees-002-ref.html">
+ <link rel="author" title="Hiroyuki Hayashi" href="mailto:hyshhryk@gmail.com">
+ <link rel="help" href="http://www.w3.org/TR/shadow-dom/#multiple-shadow-trees">
+ <script src="../testcommon.js"></script>
+ <meta name="assert" content="The older tree is inserted into <shadow>, and the original branch is inserted into <content>.">
+ </head>
+ <body>
+ <div id='host'>
+ <p>Original tree's node</p>
+ </div>
+ <script>
+ var shadowRoot = host.createShadowRoot();
+ shadowRoot.innerHTML = "<div><p>Older tree's node</p><content></content></div>";
+ var shadowRoot = host.createShadowRoot();
+ shadowRoot.innerHTML = "<div><p>Younger tree's node</p><shadow></shadow></div>";
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-003-ref.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-003-ref.html
new file mode 100644
index 00000000000..629821c2c75
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-003-ref.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Shadow DOM - The shadow should insert original tree's node if no older shadow tree exists.</title>
+ <link rel="author" title="Hiroyuki Hayashi" href="mailto:hyshhryk@gmail.com">
+ </head>
+ <body>
+ <div>
+ <p>Younger tree's node</p>
+ <p>Older tree's node</p>
+ <p>Original tree's node</p>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-003.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-003.html
new file mode 100644
index 00000000000..b9f237275f9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-003.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Shadow DOM Test - Tests shadow should insert original tree's node if no older shadow tree exists.</title>
+ <link rel="match" href="hosting-multiple-shadow-trees-003-ref.html">
+ <link rel="author" title="Hiroyuki Hayashi" href="mailto:hyshhryk@gmail.com">
+ <link rel="help" href="http://www.w3.org/TR/shadow-dom/#multiple-shadow-trees">
+ <script src="../testcommon.js"></script>
+ <meta name="assert" content="The <shadow> should insert original tree's node if no older shadow tree exists.">
+ </head>
+ <body>
+ <div id='host'>
+ <p>Original tree's node</p>
+ </div>
+ <script>
+ var shadowRoot = host.createShadowRoot();
+ shadowRoot.innerHTML = "<div><p>Older tree's node</p><shadow></shadow></div>";
+ var shadowRoot = host.createShadowRoot();
+ shadowRoot.innerHTML = "<div><p>Younger tree's node</p><shadow></shadow></div>";
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-004-ref.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-004-ref.html
new file mode 100644
index 00000000000..29d5eff0e21
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-004-ref.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Shadow DOM - The only first shadow element is used.</title>
+ <link rel="author" title="Hiroyuki Hayashi" href="mailto:hyshhryk@gmail.com">
+ </head>
+ <body>
+ <div>
+ <p>1st shadow tree's node</p>
+ <p>2nd shadow tree's node</p>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-004.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-004.html
new file mode 100644
index 00000000000..5dfffd13a9a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-004.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Shadow DOM Test - The only first shadow element is used.</title>
+ <link rel="match" href="hosting-multiple-shadow-trees-004-ref.html">
+ <link rel="author" title="Hiroyuki Hayashi" href="mailto:hyshhryk@gmail.com">
+ <link rel="help" href="http://www.w3.org/TR/shadow-dom/#multiple-shadow-trees">
+ <script src="../testcommon.js"></script>
+ <meta name="assert" content="The only first <shadow> element is used when the shadow tree has multiple <shadow> elements. Original tree's node is not inserted into the second <shadow> element.">
+ </head>
+ <body>
+ <div id='host'>
+ <p>Original tree's node</p>
+ </div>
+ <script>
+ var shadowRoot = host.createShadowRoot();
+ shadowRoot.innerHTML = "<div><p>1st shadow tree's node</p></div>";
+ var shadowRoot = host.createShadowRoot();
+ shadowRoot.innerHTML = "<div><shadow></shadow><p>2nd shadow tree's node</p><shadow></shadow></div>";
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-005-ref.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-005-ref.html
new file mode 100644
index 00000000000..6d7b13af706
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-005-ref.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Shadow DOM - Older shadow tree is not used</title>
+ <link rel="author" title="Hiroyuki Hayashi" href="mailto:hyshhryk@gmail.com">
+ </head>
+ <body>
+ <div>
+ <p>2nd shadow tree's node</p>
+ <p>Original tree's node</p>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-005.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-005.html
new file mode 100644
index 00000000000..82d54d0cb87
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-005.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Shadow DOM Test - The older shadow tree is not used.</title>
+ <link rel="match" href="hosting-multiple-shadow-trees-005-ref.html">
+ <link rel="author" title="Hiroyuki Hayashi" href="mailto:hyshhryk@gmail.com">
+ <link rel="help" href="http://www.w3.org/TR/shadow-dom/#multiple-shadow-trees">
+ <script src="../testcommon.js"></script>
+ <meta name="assert" content="The older shadow tree is not used when the youngest shadow tree doesn't have <shadow>. The original tree's node is inserted into <content> instead.">
+ </head>
+ <body>
+ <div id='host'>
+ <p>Original tree's node</p>
+ </div>
+ <script>
+ var shadowRoot = host.createShadowRoot();
+ shadowRoot.innerHTML = "<div><p>1st shadow tree's node</p><shadow></shadow></div>";
+ var shadowRoot = host.createShadowRoot();
+ shadowRoot.innerHTML = "<div><p>2nd shadow tree's node</p><content></content></div>";
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-006-ref.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-006-ref.html
new file mode 100644
index 00000000000..ea90ce8ad35
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-006-ref.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Shadow DOM - Content and shadow elements are both inserted</title>
+ <link rel="author" title="Hiroyuki Hayashi" href="mailto:hyshhryk@gmail.com">
+ </head>
+ <body>
+ <div>
+ <p>2nd shadow tree's node</p>
+ <p>Original tree's node</p>
+ <p>1st shadow tree's node</p>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-006.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-006.html
new file mode 100644
index 00000000000..a352be28790
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees-006.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Shadow DOM Test - Content and shadow elements are both inserted.</title>
+ <link rel="match" href="hosting-multiple-shadow-trees-006-ref.html">
+ <link rel="author" title="Hiroyuki Hayashi" href="mailto:hyshhryk@gmail.com">
+ <link rel="help" href="http://www.w3.org/TR/shadow-dom/#multiple-shadow-trees">
+ <script src="../testcommon.js"></script>
+ <meta name="assert" content="The <content> element assigns the original tree and the <shadow> element assigns an older shadow tree. They are both in the youngest shadow tree.">
+ </head>
+ <body>
+ <div id='host'>
+ <p>Original tree's node</p>
+ </div>
+ <script>
+ var shadowRoot = host.createShadowRoot();
+ shadowRoot.innerHTML = "<div><p>1st shadow tree's node</p></div>";
+ var shadowRoot = host.createShadowRoot();
+ shadowRoot.innerHTML = "<div><p>2nd shadow tree's node</p><content></content><shadow></shadow></div>";
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees/test-001.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees/test-001.html
new file mode 100644
index 00000000000..a62bcf32ed6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees/test-001.html
@@ -0,0 +1,128 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_04_05_01</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#multiple-shadow-subtrees">
+<meta name="assert" content="Hosting Multiple Shadow Subtrees:The shadow insertion point designates a place in the shadow DOM subtree, where an older tree is inserted when rendering">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_04_05_01_T1 = async_test('A_04_05_01_T01');
+
+
+// Check that only the younger tree is visible if there's no shadow insertion point
+A_04_05_01_T1.step(function () {
+ var iframe = document.createElement('iframe');
+ iframe.src = '../../resources/bobs_page.html';
+ document.body.appendChild(iframe);
+
+ iframe.onload = A_04_05_01_T1.step_func(function () {
+ try {
+ var d = iframe.contentDocument;
+ var ul = d.querySelector('ul.stories');
+
+ //make old shadow subtree
+ var s1 = ul.createShadowRoot();
+ var subdiv1 = d.createElement('div');
+ subdiv1.innerHTML = '<ul><content select=".shadow"></content></ul>';
+ s1.appendChild(subdiv1);
+
+ //make younger shadow subtree
+ var s2 = ul.createShadowRoot();
+ var subdiv2 = d.createElement('div');
+ subdiv2.innerHTML = '<ul><content select=".shadow2"></content></ul>';
+ s2.appendChild(subdiv2);
+
+ //The order of DOM elements should be the following:
+ //li4 visible. Other elements invisible
+ assert_true(d.querySelector('#li4').offsetTop > 0,
+ 'Only the younger tree should take part in the distribution');
+
+ assert_equals(d.querySelector('#li1').offsetTop, 0,
+ 'Point 1: Elements that don\'t mach insertion point criteria participate in distribution');
+ assert_equals(d.querySelector('#li2').offsetTop, 0,
+ 'Point 2: Elements that don\'t mach insertion point criteria participate in distribution');
+ assert_equals(d.querySelector('#li3').offsetTop, 0,
+ 'Point 3: Elements that don\'t mach insertion point criteria participate in distribution');
+ assert_equals(d.querySelector('#li5').offsetTop, 0,
+ 'Point 4: Elements that don\'t mach insertion point criteria participate in distribution');
+ assert_equals(d.querySelector('#li6').offsetTop, 0,
+ 'Point 5: Elements that don\'t mach insertion point criteria participate in distribution');
+
+ } finally {
+ iframe.parentNode.removeChild(iframe);
+ }
+ A_04_05_01_T1.done();
+ });
+});
+
+
+
+//Check that both the younger tree and the older one are visible
+//if there's a shadow insertion point for the older tree
+var A_04_05_01_T2 = async_test('A_04_05_01_T02');
+
+A_04_05_01_T2.step(function () {
+ var iframe = document.createElement('iframe');
+ iframe.src = '../../resources/bobs_page.html';
+ document.body.appendChild(iframe);
+
+ iframe.onload = A_04_05_01_T2.step_func(function () {
+ try {
+ var d = iframe.contentDocument;
+ var ul = d.querySelector('ul.stories');
+
+ //make old shadow subtree
+ var s1 = ul.createShadowRoot();
+ var subdiv1 = d.createElement('div');
+ subdiv1.innerHTML = '<ul><content select=".shadow"></content></ul>';
+ s1.appendChild(subdiv1);
+
+ //make younger shadow subtree
+ var s2 = ul.createShadowRoot();
+ var subdiv2 = d.createElement('div');
+ subdiv2.innerHTML = '<ul><content select=".shadow2"></content></ul>';
+ s2.appendChild(subdiv2);
+
+ //add a shadow insertion point for the older tree
+ s2.appendChild(d.createElement('shadow'));
+
+ //The order of DOM elements should be the following:
+ //li4, li3, li6 visible. Other elements invisible
+ assert_true(d.querySelector('#li4').offsetTop > 0,
+ 'Younger tree should take part in the distribution');
+ assert_true(d.querySelector('#li3').offsetTop > d.querySelector('#li4').offsetTop,
+ 'Point 1: Older tree should take part in the distribution');
+ assert_true(d.querySelector('#li6').offsetTop > d.querySelector('#li3').offsetTop,
+ 'Point 2: Older tree should take part in the distribution');
+
+ assert_equals(d.querySelector('#li1').offsetTop, 0,
+ 'Point 3: Elements that don\'t mach insertion point criteria participate in distribution');
+ assert_equals(d.querySelector('#li2').offsetTop, 0,
+ 'Point 4: Elements that don\'t mach insertion point criteria participate in distribution');
+ assert_equals(d.querySelector('#li5').offsetTop, 0,
+ 'Point 5: Elements that don\'t mach insertion point criteria participate in distribution');
+ } finally {
+ iframe.parentNode.removeChild(iframe);
+ }
+ A_04_05_01_T2.done();
+ });
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees/test-002.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees/test-002.html
new file mode 100644
index 00000000000..a9e967878c2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees/test-002.html
@@ -0,0 +1,86 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_04_05_02</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#multiple-shadow-subtrees">
+<meta name="assert" content="Hosting Multiple Shadow Subtrees:If multiple shadow insertion points exist in a shadow DOM subtree, only the first, in tree order, is recognized">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_04_05_02_T1 = async_test('A_04_05_02_T01');
+
+A_04_05_02_T1.step(function () {
+ var iframe = document.createElement('iframe');
+ iframe.src = '../../resources/bobs_page.html';
+ document.body.appendChild(iframe);
+
+ iframe.onload = A_04_05_02_T1.step_func(function () {
+ try {
+ var d = iframe.contentDocument;
+ var ul = d.querySelector('ul.stories');
+
+ //make the oldest shadow subtree
+ var s1 = ul.createShadowRoot();
+ var subdiv1 = d.createElement('div');
+ subdiv1.innerHTML = '<ul><content select="#li1"></content></ul>';
+ s1.appendChild(subdiv1);
+
+ //make an old shadow subtree
+ var s2 = ul.createShadowRoot();
+ var subdiv2 = d.createElement('div');
+ subdiv2.innerHTML = '<ul><content select=".shadow"></content></ul>';
+ s2.appendChild(subdiv2);
+
+ //make the youngest shadow subtree
+ var s3 = ul.createShadowRoot();
+ var subdiv3 = d.createElement('div');
+ subdiv3.innerHTML = '<ul><content select=".shadow2"></content></ul>';
+ s3.appendChild(subdiv3);
+
+ //add a shadow insertion point for the old tree
+ s3.appendChild(d.createElement('shadow'));
+ //add another shadow insertion point for the older tree.
+ //Shouldn't match
+ s3.appendChild(d.createElement('shadow'));
+
+
+ //The order of DOM elements should be the following:
+ //li4, li3, li6 visible. Other elements invisible
+ assert_true(d.querySelector('#li4').offsetTop > 0,
+ 'Only the younger tree should take part in the distribution');
+ assert_true(d.querySelector('#li3').offsetTop > d.querySelector('#li4').offsetTop,
+ 'Point 1: Older tree should take part in the distribution');
+ assert_true(d.querySelector('#li6').offsetTop > d.querySelector('#li3').offsetTop,
+ 'Point 2: Older tree should take part in the distribution');
+
+ assert_equals(d.querySelector('#li1').offsetTop, 0,
+ 'The oldest tree shouldn\'t take part in the distribution');
+ assert_equals(d.querySelector('#li2').offsetTop, 0,
+ 'Point 3: Elements that don\'t mach insertion point criteria participate in distribution');
+ assert_equals(d.querySelector('#li5').offsetTop, 0,
+ 'Point 4: Elements that don\'t mach insertion point criteria participate in distribution');
+
+ } finally {
+ iframe.parentNode.removeChild(iframe);
+ }
+ A_04_05_02_T1.done();
+ });
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees/test-003.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees/test-003.html
new file mode 100644
index 00000000000..13dbe3f4e96
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/hosting-multiple-shadow-trees/test-003.html
@@ -0,0 +1,88 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_04_05_03</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#multiple-shadow-subtrees">
+<meta name="assert" content="Hosting Multiple Shadow Subtrees:When an insertion point or a shadow insertion point has nothing assigned or distributed to them, the fallback content must be used instead when rendering">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_04_05_03_T1 = async_test('A_04_05_03_T01');
+
+A_04_05_03_T1.step(function () {
+ var iframe = document.createElement('iframe');
+ iframe.src = '../../resources/bobs_page.html';
+ document.body.appendChild(iframe);
+
+ iframe.onload = A_04_05_03_T1.step_func(function () {
+ try {
+ var d = iframe.contentDocument;
+ var ul = d.querySelector('ul.stories');
+
+ //make the oldest shadow subtree
+ var s1 = ul.createShadowRoot();
+ var subdiv1 = d.createElement('div');
+ subdiv1.innerHTML = '<ul><content select="#li1"></content></ul>';
+ s1.appendChild(subdiv1);
+
+ //make an old shadow subtree
+ var s2 = ul.createShadowRoot();
+ var subdiv2 = d.createElement('div');
+ subdiv2.innerHTML = '<ul><content select=".shadow"></content></ul>';
+ s2.appendChild(subdiv2);
+
+ //make the youngest shadow subtree
+ var s3 = ul.createShadowRoot();
+ var subdiv3 = d.createElement('div');
+ subdiv3.innerHTML = '<ul><content select=".shadow2"></content></ul>' +
+ '<shadow><span id="spn_first">The first span</span></shadow>' +
+ '<shadow><span id="spn_second">The second span</span></shadow>';
+
+ s3.appendChild(subdiv3);
+
+ //The order of DOM elements should be the following:
+ //li4, li3, li6 visible. Other elements invisible
+ assert_true(d.querySelector('#li4').offsetTop > 0,
+ 'Only the younger tree should take part in the distribution');
+ assert_true(d.querySelector('#li3').offsetTop > d.querySelector('#li4').offsetTop,
+ 'Point 1: Older tree should take part in the distribution');
+ assert_true(d.querySelector('#li6').offsetTop > d.querySelector('#li3').offsetTop,
+ 'Point 2: Older tree should take part in the distribution');
+
+ assert_equals(d.querySelector('#li1').offsetTop, 0,
+ 'The oldest tree shouldn\'t take part in the distribution');
+ assert_equals(d.querySelector('#li2').offsetTop, 0,
+ 'Point 3: Elements that don\'t mach insertion point criteria participate in distribution');
+ assert_equals(d.querySelector('#li5').offsetTop, 0,
+ 'Point 4: Elements that don\'t mach insertion point criteria participate in distribution');
+
+ //spn_first should be invisible, spn_second visible
+ assert_equals(s3.querySelector('#spn_first').offsetTop, 0,
+ 'Shadow insertion point should be active');
+ assert_true(s3.querySelector('#spn_second').offsetTop > 0,
+ 'Shadow insertion point should be inactive');
+
+ } finally {
+ iframe.parentNode.removeChild(iframe);
+ }
+ A_04_05_03_T1.done();
+ });
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/lower-boundary-encapsulation/distribution-001-ref.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/lower-boundary-encapsulation/distribution-001-ref.html
new file mode 100644
index 00000000000..e19d98845c3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/lower-boundary-encapsulation/distribution-001-ref.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: Distribution: Unordered list (Reference)</title>
+<link rel="author" title="Yuta Kitamura" href="mailto:yutak@google.com">
+</head>
+<body>
+<p>
+You should see an unordered list below, consisting of ten elements
+each of which contains a capital letter ranging from "A" to "J",
+in alphabetical order.
+</p>
+<ul>
+<li>A</li>
+<li>B</li>
+<li>C</li>
+<li>D</li>
+<li>E</li>
+<li>F</li>
+<li>G</li>
+<li>H</li>
+<li>I</li>
+<li>J</li>
+</ul>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/lower-boundary-encapsulation/distribution-001.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/lower-boundary-encapsulation/distribution-001.html
new file mode 100644
index 00000000000..891b4248946
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/lower-boundary-encapsulation/distribution-001.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: Distribution: Unordered list</title>
+<link rel="match" href="distribution-001-ref.html">
+<link rel="author" title="Yuta Kitamura" href="mailto:yutak@google.com">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#shadow-trees">
+<meta name="assert" content="Lower-boundary Encapsulation: Each insertion point participates in distribution by providing a matching criteria for the child nodes. The matching criteria determines whether a given node could be distributed to a given insertion point.">
+<script src="../../testcommon.js"></script>
+</head>
+<body>
+<p>
+You should see an unordered list below, consisting of ten elements
+each of which contains a capital letter ranging from "A" to "J",
+in alphabetical order.
+</p>
+<ul id="list">
+<li>H</li>
+<li class="first">B</li>
+<li class="second">E</li>
+<li>I</li>
+<li class="first">C</li>
+</ul>
+<script>
+var shadowRoot = document.getElementById('list').createShadowRoot();
+shadowRoot.innerHTML =
+ '<li>A</li>' +
+ '<content select=".first"></content>' +
+ '<li>D</li>' +
+ '<content select=".second"></content>' +
+ '<li>F</li>' +
+ '<content select="img"></content>' +
+ '<li>G</li>' +
+ '<content></content>' +
+ '<li>J</li>';
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/lower-boundary-encapsulation/distribution-002-ref.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/lower-boundary-encapsulation/distribution-002-ref.html
new file mode 100644
index 00000000000..5114b64b4ea
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/lower-boundary-encapsulation/distribution-002-ref.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: Distribution: Ordered list (Reference)</title>
+<link rel="author" title="Yuta Kitamura" href="mailto:yutak@google.com">
+<style>
+ol {
+ list-style-type: decimal;
+}
+</style>
+</head>
+<body>
+<p>
+You should see an ordered list below, consisting of ten elements numbered
+from 1 through 10, and each line should contain a capital letter ranging from
+"A" to "J", in alphabetical order.
+</p>
+<ol>
+<li>A</li>
+<li>B</li>
+<li>C</li>
+<li>D</li>
+<li>E</li>
+<li>F</li>
+<li>G</li>
+<li>H</li>
+<li>I</li>
+<li>J</li>
+</ol>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/lower-boundary-encapsulation/distribution-002.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/lower-boundary-encapsulation/distribution-002.html
new file mode 100644
index 00000000000..e0d93ad6f34
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/lower-boundary-encapsulation/distribution-002.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: Distribution: Ordered list</title>
+<link rel="match" href="distribution-002-ref.html">
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="author" title="Yuta Kitamura" href="mailto:yutak@google.com">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#shadow-trees">
+<meta name="assert" content="Lower-boundary Encapsulation: Each insertion point participates in distribution by providing a matching criteria for the child nodes. The matching criteria determines whether a given node could be distributed to a given insertion point.">
+<script src="../../testcommon.js"></script>
+<style>
+ol {
+ list-style-type: decimal;
+}
+</style>
+</head>
+<body>
+<p>
+You should see an ordered list below, consisting of ten elements numbered
+from 1 through 10, and each line should contain a capital letter ranging from
+"A" to "J", in alphabetical order.
+</p>
+<ol id="list">
+<li>H</li>
+<li class="first">B</li>
+<li class="second">E</li>
+<li>I</li>
+<li class="first">C</li>
+</ol>
+<script>
+var shadowRoot = document.getElementById('list').createShadowRoot();
+shadowRoot.innerHTML =
+ '<li>A</li>' +
+ '<content select=".first"></content>' +
+ '<li>D</li>' +
+ '<content select=".second"></content>' +
+ '<li>F</li>' +
+ '<content select="img"></content>' +
+ '<li>G</li>' +
+ '<content></content>' +
+ '<li>J</li>';
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/lower-boundary-encapsulation/distribution-003.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/lower-boundary-encapsulation/distribution-003.html
new file mode 100644
index 00000000000..e21fc90f738
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/lower-boundary-encapsulation/distribution-003.html
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: Invariants after distribution</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="author" title="Yuta Kitamura" href="mailto:yutak@google.com">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#lower-boundary-encapsulation">
+<meta name="assert" content="Lower-boundary encapsulation: The distribution does not affect the state of the document tree or shadow trees">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var distributionTest = async_test(
+ 'Distribution should not affect the state of the document trees and ' +
+ 'the shadow trees.');
+
+distributionTest.step(function () {
+ var shadowHost = document.createElement('ul');
+ shadowHost.innerHTML =
+ '<li class="first">host 1</li>' +
+ '<li class="second">host 2</li>';
+ shadowHost.style.visibility = 'hidden';
+ document.body.appendChild(shadowHost);
+ var host1 = shadowHost.querySelector('.first');
+ var host2 = shadowHost.querySelector('.second');
+
+ var shadowRoot = shadowHost.createShadowRoot();
+ shadowRoot.innerHTML =
+ '<li class="first">shadow 1</li>' +
+ '<content select=".second"></content>' +
+ '<li class="second">shadow 2</li>';
+ var shadow1 = shadowRoot.querySelector('.first');
+ var shadow2 = shadowRoot.querySelector('.second');
+ var content = shadowRoot.querySelector('content');
+
+ // Let the rendering happen.
+ window.setTimeout(distributionTest.step_func(function () {
+ assert_equals(host1.textContent, 'host 1');
+ assert_equals(host2.textContent, 'host 2');
+ assert_equals(shadow1.textContent, 'shadow 1');
+ assert_equals(shadow2.textContent, 'shadow 2');
+ assert_equals(content.textContent, '');
+
+ assert_equals(shadowHost.children.length, 2);
+ assert_equals(shadowHost.children[0], host1);
+ assert_equals(shadowHost.children[1], host2);
+ assert_equals(shadowRoot.children.length, 3);
+ assert_equals(shadowRoot.children[0], shadow1);
+ assert_equals(shadowRoot.children[1], content);
+ assert_equals(shadowRoot.children[2], shadow2);
+
+ assert_equals(host1.tagName, 'LI');
+ assert_equals(shadow1.tagName, 'LI');
+ assert_equals(content.tagName, 'CONTENT');
+
+ document.body.removeChild(shadowHost);
+ distributionTest.done();
+ }), 0);
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/lower-boundary-encapsulation/test-003.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/lower-boundary-encapsulation/test-003.html
new file mode 100644
index 00000000000..3dea1f6838a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/lower-boundary-encapsulation/test-003.html
@@ -0,0 +1,131 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_04_02_03</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#lower-boundary-encapsulation">
+<meta name="assert" content="Lower-boundary encapsulation: The distribution is a result of executing a stable algorithm">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_04_02_03_T1 = async_test('A_04_02_03_T01');
+
+A_04_02_03_T1.step(function () {
+ var iframe = document.createElement('iframe');
+ iframe.src = '../../resources/bobs_page.html';
+ document.body.appendChild(iframe);
+
+ iframe.onload = A_04_02_03_T1.step_func(function () {
+ try {
+ var d = iframe.contentDocument;
+ var ul = d.querySelector('ul.stories');
+ var s = ul.createShadowRoot();
+
+ //make shadow subtree
+ var subdiv1 = document.createElement('div');
+ subdiv1.innerHTML = '<ul><content select=".shadow"></content></ul>';
+ s.appendChild(subdiv1);
+
+ //The order of <li> elements at this point should be the following:
+ //li3, li6, li11, li12, 1i13, li14, li15. Other elements (li1, li2, li4, li5) invisible
+ assert_true(d.querySelector('#li3').offsetTop < d.querySelector('#li6').offsetTop,
+ 'Point 1: Elements that mach insertion point criteria don\'t participate in distribution');
+ assert_true(d.querySelector('#li6').offsetTop < d.querySelector('#li11').offsetTop,
+ 'Point 2: Elements that mach insertion point criteria don\'t participate in distribution');
+ assert_true(d.querySelector('#li11').offsetTop < d.querySelector('#li12').offsetTop,
+ 'Point 3: Elements that mach insertion point criteria don\'t participate in distribution');
+ assert_true(d.querySelector('#li12').offsetTop < d.querySelector('#li13').offsetTop,
+ 'Point 4: Elements that mach insertion point criteria don\'t participate in distribution');
+ assert_true(d.querySelector('#li13').offsetTop < d.querySelector('#li14').offsetTop,
+ 'Point 5: Elements that mach insertion point criteria don\'t participate in distribution');
+ assert_true(d.querySelector('#li14').offsetTop < d.querySelector('#li15').offsetTop,
+ 'Point 6: Elements that mach insertion point criteria don\'t participate in distribution');
+
+ assert_equals(d.querySelector('#li1').offsetTop, 0,
+ 'Point 7: Elements that don\'t mach insertion point criteria participate in distribution');
+ assert_equals(d.querySelector('#li2').offsetTop, 0,
+ 'Point 8: Elements that don\'t mach insertion point criteria participate in distribution');
+ assert_equals(d.querySelector('#li4').offsetTop, 0,
+ 'Point 9: Elements that don\'t mach insertion point criteria participate in distribution');
+ assert_equals(d.querySelector('#li5').offsetTop, 0,
+ 'Point 10: Elements that don\'t mach insertion point criteria participate in distribution');
+
+ var subdiv2 = document.createElement('div');
+ subdiv2.innerHTML = '<ul><content select=".shadow2"></content></ul>';
+ s.appendChild(subdiv2);
+
+ // When class name changed distribution must reoccur
+ //The order of <li> elements should now be the following:
+ //li3, li6, li4, li11, li12, 1i13, li14, li15. Invisible: li1, li2, li5
+ assert_true(d.querySelector('#li3').offsetTop < d.querySelector('#li6').offsetTop,
+ 'Point 11: Elements that mach insertion point criteria don\'t participate in distribution');
+ assert_true(d.querySelector('#li6').offsetTop < d.querySelector('#li4').offsetTop,
+ 'Point 12: Elements that mach insertion point criteria don\'t participate in distribution');
+ assert_true(d.querySelector('#li4').offsetTop < d.querySelector('#li11').offsetTop,
+ 'Point 13: Elements that mach insertion point criteria don\'t participate in distribution');
+ assert_true(d.querySelector('#li11').offsetTop < d.querySelector('#li12').offsetTop,
+ 'Point 14: Elements that mach insertion point criteria don\'t participate in distribution');
+ assert_true(d.querySelector('#li12').offsetTop < d.querySelector('#li13').offsetTop,
+ 'Point 15: Elements that mach insertion point criteria don\'t participate in distribution');
+ assert_true(d.querySelector('#li13').offsetTop < d.querySelector('#li14').offsetTop,
+ 'Point 16: Elements that mach insertion point criteria don\'t participate in distribution');
+ assert_true(d.querySelector('#li14').offsetTop < d.querySelector('#li15').offsetTop,
+ 'Point 17: Elements that mach insertion point criteria don\'t participate in distribution');
+
+ assert_equals(d.querySelector('#li1').offsetTop, 0,
+ 'Point 18: Elements that don\'t mach insertion point criteria participate in distribution');
+ assert_equals(d.querySelector('#li2').offsetTop, 0,
+ 'Point 19: Elements that don\'t mach insertion point criteria participate in distribution');
+ assert_equals(d.querySelector('#li5').offsetTop, 0,
+ 'Point 20: Elements that don\'t mach insertion point criteria participate in distribution');
+
+ var subdiv3 = document.createElement('div');
+ subdiv3.innerHTML = '<ul><content select=".shadow"></content></ul>';
+ s.appendChild(subdiv3);
+
+ //There should be no change. Order:
+ //li3, li6, li4, li11, li12, 1i13, li14, li15. Invisible: li1, li2, li5
+ assert_true(d.querySelector('#li3').offsetTop < d.querySelector('#li6').offsetTop,
+ 'Point 21: Elements that mach insertion point criteria don\'t participate in distribution');
+ assert_true(d.querySelector('#li6').offsetTop < d.querySelector('#li4').offsetTop,
+ 'Point 22: Elements that mach insertion point criteria don\'t participate in distribution');
+ assert_true(d.querySelector('#li4').offsetTop < d.querySelector('#li11').offsetTop,
+ 'Point 23: Elements that mach insertion point criteria don\'t participate in distribution');
+ assert_true(d.querySelector('#li11').offsetTop < d.querySelector('#li12').offsetTop,
+ 'Point 24: Elements that mach insertion point criteria don\'t participate in distribution');
+ assert_true(d.querySelector('#li12').offsetTop < d.querySelector('#li13').offsetTop,
+ 'Point 25: Elements that mach insertion point criteria don\'t participate in distribution');
+ assert_true(d.querySelector('#li13').offsetTop < d.querySelector('#li14').offsetTop,
+ 'Point 26: Elements that mach insertion point criteria don\'t participate in distribution');
+ assert_true(d.querySelector('#li14').offsetTop < d.querySelector('#li15').offsetTop,
+ 'Point 27: Elements that mach insertion point criteria don\'t participate in distribution');
+
+ assert_equals(d.querySelector('#li1').offsetTop, 0,
+ 'Point 28: Elements that don\'t mach insertion point criteria participate in distribution');
+ assert_equals(d.querySelector('#li2').offsetTop, 0,
+ 'Point 29: Elements that don\'t mach insertion point criteria participate in distribution');
+ assert_equals(d.querySelector('#li5').offsetTop, 0,
+ 'Point 30: Elements that don\'t mach insertion point criteria participate in distribution');
+ } finally {
+ iframe.parentNode.removeChild(iframe);
+ }
+ A_04_02_03_T1.done();
+ });
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/lower-boundary-encapsulation/test-004.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/lower-boundary-encapsulation/test-004.html
new file mode 100644
index 00000000000..ea67f9bb058
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/lower-boundary-encapsulation/test-004.html
@@ -0,0 +1,103 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_04_02_04</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#lower-boundary-encapsulation">
+<meta name="assert" content="Lower-boundary encapsulation: The distribution reoccurs whenever any variable affecting it is changed">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_04_02_04_T1 = async_test('A_04_02_04_T01');
+
+A_04_02_04_T1.step(function () {
+ var iframe = document.createElement('iframe');
+ iframe.src = '../../resources/bobs_page.html';
+ document.body.appendChild(iframe);
+
+ iframe.onload = A_04_02_04_T1.step_func(function () {
+ try {
+ var d = iframe.contentDocument;
+ var ul = d.querySelector('ul.stories');
+ var s = ul.createShadowRoot();
+
+ //make shadow subtree
+ var subdiv1 = document.createElement('div');
+ subdiv1.innerHTML = '<ul><content select=".shadow"></content></ul>';
+ s.appendChild(subdiv1);
+
+
+ //The order of <li> elements at this point should be the following:
+ //li3, li6, li11, li12, 1i13, li14, li15. Other elements (li1, li2, li4, li5) invisible
+ assert_true(d.querySelector('#li3').offsetTop < d.querySelector('#li6').offsetTop,
+ 'Point 1: Elements that mach insertion point criteria don\'t participate in distribution');
+ assert_true(d.querySelector('#li6').offsetTop < d.querySelector('#li11').offsetTop,
+ 'Point 2: Elements that mach insertion point criteria don\'t participate in distribution');
+ assert_true(d.querySelector('#li11').offsetTop < d.querySelector('#li12').offsetTop,
+ 'Point 3: Elements that mach insertion point criteria don\'t participate in distribution');
+ assert_true(d.querySelector('#li12').offsetTop < d.querySelector('#li13').offsetTop,
+ 'Point 4: Elements that mach insertion point criteria don\'t participate in distribution');
+ assert_true(d.querySelector('#li13').offsetTop < d.querySelector('#li14').offsetTop,
+ 'Point 5: Elements that mach insertion point criteria don\'t participate in distribution');
+ assert_true(d.querySelector('#li14').offsetTop < d.querySelector('#li15').offsetTop,
+ 'Point 6: Elements that mach insertion point criteria don\'t participate in distribution');
+
+ assert_equals(d.querySelector('#li1').offsetTop, 0,
+ 'Point 7: Elements that don\'t mach insertion point criteria participate in distribution');
+ assert_equals(d.querySelector('#li2').offsetTop, 0,
+ 'Point 8: Elements that don\'t mach insertion point criteria participate in distribution');
+ assert_equals(d.querySelector('#li4').offsetTop, 0,
+ 'Point 9: Elements that don\'t mach insertion point criteria participate in distribution');
+ assert_equals(d.querySelector('#li5').offsetTop, 0,
+ 'Point 10: Elements that don\'t mach insertion point criteria participate in distribution');
+
+ var li5 = d.querySelector('#li5');
+ li5.className = 'shadow';
+
+ // When class name changed distribution must reoccur
+ //The order of <li> elements should now be the following:
+ //li3, li6, li5, li11, li12, 1i13, li14, li15. Invisible: li1, li2, li4
+ assert_true(d.querySelector('#li3').offsetTop < d.querySelector('#li6').offsetTop,
+ 'Point 11: Elements that mach insertion point criteria don\'t participate in distribution');
+ assert_true(d.querySelector('#li6').offsetTop < d.querySelector('#li5').offsetTop,
+ 'Point 12: Elements that mach insertion point criteria don\'t participate in distribution');
+ assert_true(d.querySelector('#li5').offsetTop < d.querySelector('#li11').offsetTop,
+ 'Point 13: Elements that mach insertion point criteria don\'t participate in distribution');
+ assert_true(d.querySelector('#li11').offsetTop < d.querySelector('#li12').offsetTop,
+ 'Point 14: Elements that mach insertion point criteria don\'t participate in distribution');
+ assert_true(d.querySelector('#li12').offsetTop < d.querySelector('#li13').offsetTop,
+ 'Point 15: Elements that mach insertion point criteria don\'t participate in distribution');
+ assert_true(d.querySelector('#li13').offsetTop < d.querySelector('#li14').offsetTop,
+ 'Point 16: Elements that mach insertion point criteria don\'t participate in distribution');
+ assert_true(d.querySelector('#li14').offsetTop < d.querySelector('#li15').offsetTop,
+ 'Point 17: Elements that mach insertion point criteria don\'t participate in distribution');
+
+ assert_equals(d.querySelector('#li1').offsetTop, 0,
+ 'Point 18: Elements that don\'t mach insertion point criteria participate in distribution');
+ assert_equals(d.querySelector('#li2').offsetTop, 0,
+ 'Point 19: Elements that don\'t mach insertion point criteria participate in distribution');
+ assert_equals(d.querySelector('#li4').offsetTop, 0,
+ 'Point 20: Elements that don\'t mach insertion point criteria participate in distribution');
+ } finally {
+ iframe.parentNode.removeChild(iframe);
+ }
+ A_04_02_04_T1.done();
+ });
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/lower-boundary-encapsulation/test-005.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/lower-boundary-encapsulation/test-005.html
new file mode 100644
index 00000000000..b15b603a6f0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/lower-boundary-encapsulation/test-005.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_04_02_05</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#lower-boundary-encapsulation">
+<meta name="assert" content="Lower-boundary encapsulation: An insertion point may be active or inactive. An active insertion point participates in the distribution process, whereas the inactive insertion does not">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_04_02_05_T1 = async_test('A_04_02_05_T01');
+
+A_04_02_05_T1.step(function () {
+ var iframe = document.createElement('iframe');
+ iframe.src = '../../resources/bobs_page.html';
+ document.body.appendChild(iframe);
+
+ iframe.onload = A_04_02_05_T1.step_func(function () {
+ try {
+ var d = iframe.contentDocument;
+ var ul = d.querySelector("ul.stories");
+ var s = ul.createShadowRoot();
+
+ //make shadow subtree
+ var subdiv1 = document.createElement('div');
+ subdiv1.innerHTML = "<ul><content select='.nobody'><span id='shadowspan'>Inactive insertion point</span></content></ul>";
+ s.appendChild(subdiv1);
+
+ assert_true(s.querySelector('#shadowspan').offsetTop > 0,
+ 'Inactive insertion point should be in a fallback content');
+
+ // All li1-li6 should be invisible, shadowspan visible
+ assert_equals(d.querySelector('#li1').offsetTop, 0,
+ 'Point 1: Elements that don\'t mach insertion point criteria participate in distribution');
+ assert_equals(d.querySelector('#li2').offsetTop, 0,
+ 'Point 2: Elements that don\'t mach insertion point criteria participate in distribution');
+ assert_equals(d.querySelector('#li3').offsetTop, 0,
+ 'Point 3: Elements that don\'t mach insertion point criteria participate in distribution');
+ assert_equals(d.querySelector('#li4').offsetTop, 0,
+ 'Point 4: Elements that don\'t mach insertion point criteria participate in distribution');
+ assert_equals(d.querySelector('#li5').offsetTop, 0,
+ 'Point 5: Elements that don\'t mach insertion point criteria participate in distribution');
+ assert_equals(d.querySelector('#li6').offsetTop, 0,
+ 'Point 6: Elements that don\'t mach insertion point criteria participate in distribution');
+ } finally {
+ iframe.parentNode.removeChild(iframe);
+ }
+ A_04_02_05_T1.done();
+ });
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/nested-shadow-trees/nested_tree_reftest-ref.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/nested-shadow-trees/nested_tree_reftest-ref.html
new file mode 100644
index 00000000000..f4b8bab7602
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/nested-shadow-trees/nested_tree_reftest-ref.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" >
+ <title>Shadow DOM Test Ref file - Tests nested shadow tree.</title>
+ <link rel="author" title="shingo.miyazawa" href="mailto:kumatronik@gmail.com" >
+ <script src="../../testcommon.js"></script>
+ <meta name="assert" content="nested shadow tree style is valid." >
+ <style>
+ #host {
+ width: 100px;
+ height: 100px;
+ background-color: red;
+ }
+ </style>
+ </head>
+ <body>
+ <p>The test passes if there is a green square. Test failed if there is a red square.</p>
+ <div id='host'>
+ <div id="sub" style="width: 100%;height:100%;">
+ <div style="width:100%; height:100%;background-color: green;"></div>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/nested-shadow-trees/nested_tree_reftest.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/nested-shadow-trees/nested_tree_reftest.html
new file mode 100644
index 00000000000..679b70f0dde
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/nested-shadow-trees/nested_tree_reftest.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" >
+ <title>Shadow DOM Test - Tests nested shadow tree.</title>
+ <link rel="match" href="nested_tree_reftest-ref.html" >
+ <link rel="author" title="shingo.miyazawa" href="mailto:kumatronik@gmail.com" >
+ <link rel="help" href="https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#nested-shadow-trees" >
+ <script src="../../testcommon.js"></script>
+ <meta name="assert" content="nested shadow tree style is valid." >
+ <style>
+ #host {
+ width: 100px;
+ height: 100px;
+ background-color: red;
+ }
+ </style>
+ </head>
+ <body>
+ <p>The test passes if there is a green square. Test failed if there is a red square.</p>
+ <div id='host'>
+ </div>
+ <script>
+ var shadowRoot = document.getElementById('host').createShadowRoot();
+ shadowRoot.innerHTML = '<div id="sub" style="width: 100%;height:100%;"></div>';
+ var nestedRoot = shadowRoot.getElementById('sub').createShadowRoot();
+ nestedRoot.innerHTML = '<div style="width:100%; height:100%;background-color: green;"></div>';
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/nested-shadow-trees/test-001.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/nested-shadow-trees/test-001.html
new file mode 100644
index 00000000000..68bda04cc7a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/nested-shadow-trees/test-001.html
@@ -0,0 +1,99 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_04_08_01</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#nested-shadow-subtrees">
+<meta name="assert" content="Nested Shadow Subtrees:Any element in a shadow tree can be a shadow host, thus producing nested shadow trees">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_04_08_01_T1 = async_test('A_04_08_01_T01');
+
+A_04_08_01_T1.step(function () {
+ var iframe = document.createElement('iframe');
+ iframe.src = '../../resources/bobs_page.html';
+ document.body.appendChild(iframe);
+
+ iframe.onload = A_04_08_01_T1.step_func(function () {
+ try {
+ var d = iframe.contentDocument;
+ var ul = d.querySelector('ul.stories');
+
+ //make a shadow subtree
+ var s1 = ul.createShadowRoot();
+ var subdiv1 = d.createElement('div');
+ subdiv1.innerHTML = '<ul><content select=".shadow"></content></ul>' +
+ '<div id="host_div">' +
+ '<span id="sh_span">This span should be visible</span>' +
+ '<ul id="host">' +
+ '<li id="sh_li1">Shadow li 1</li>' +
+ '<li id="sh_li2">Shadow li 2</li>' +
+ '<li id="sh_li3" class="shadow2">Shadow li 3</li>' +
+ '<li id="sh_li4">Shadow li 4</li>' +
+ '<li id="sh_li5">Shadow li 5</li>' +
+ '</ul>' +
+ '</div>';
+ s1.appendChild(subdiv1);
+
+ //make nested shadow subtree
+ var sh_ul = s1.querySelector('#host');
+ var s2 = sh_ul.createShadowRoot();
+ var subdiv2 = d.createElement('div');
+ subdiv2.innerHTML = '<ul><content select=".shadow2"></content></ul>';
+ s2.appendChild(subdiv2);
+
+ //The order of DOM elements should be the following:
+ //li4, li3 and sh_li3 visible. Other elements invisible
+ assert_true(d.querySelector('#li3').offsetTop > 0,
+ 'Point 1: Shadow tree should take part in the distribution');
+ assert_true(d.querySelector('#li6').offsetTop > d.querySelector('#li3').offsetTop,
+ 'Point 2: Shadow tree should take part in the distribution');
+ assert_true(s1.querySelector('#sh_li3').offsetTop > 0,
+ 'Nested shadow subtree should take part in the distribution');
+
+ assert_equals(d.querySelector('#li1').offsetTop, 0,
+ 'Point 3: Elements that don\'t mach insertion point criteria participate in distribution');
+ assert_equals(d.querySelector('#li2').offsetTop, 0,
+ 'Point 4: Elements that don\'t mach insertion point criteria participate in distribution');
+ assert_equals(d.querySelector('#li4').offsetTop, 0,
+ 'Point 5: Elements that don\'t mach insertion point criteria participate in distribution');
+ assert_equals(d.querySelector('#li5').offsetTop, 0,
+ 'Point 6: Elements that don\'t mach insertion point criteria participate in distribution');
+
+ assert_equals(s1.querySelector('#sh_li1').offsetTop, 0,
+ 'Point 7: Elements of the nested shadow subtree that don\'t mach insertion point criteria participate in distribution');
+ assert_equals(s1.querySelector('#sh_li2').offsetTop, 0,
+ 'Point 8: Elements of the nested shadow subtree that don\'t mach insertion point criteria participate in distribution');
+ assert_equals(s1.querySelector('#sh_li4').offsetTop, 0,
+ 'Point 9: Elements of the nested shadow subtree that don\'t mach insertion point criteria participate in distribution');
+ assert_equals(s1.querySelector('#sh_li5').offsetTop, 0,
+ 'Point 10: Elements of the nested shadow subtree that don\'t mach insertion point criteria participate in distribution');
+
+ assert_true(s1.querySelector('#sh_span').offsetTop > 0,
+ 'Shadow subtree elements that are not shadow host should take part in the distribution');
+
+
+ } finally {
+ iframe.parentNode.removeChild(iframe);
+ }
+ A_04_08_01_T1.done();
+ });
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/rendering-shadow-trees/test-001.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/rendering-shadow-trees/test-001.html
new file mode 100644
index 00000000000..3671669e216
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/rendering-shadow-trees/test-001.html
@@ -0,0 +1,256 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_04_09_01</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#multiple-shadow-subtrees">
+<meta name="assert" content="Rendering Shadow DOM Subtrees:rendering algorithm">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+ var div = d.createElement('div');
+ div.innerHTML = '' +
+ '<ul id="host">' +
+ '<li id="li1" class="shadow">' +
+ '<a id="a11" class="cl1" href="#">Link11 Shadow</a>' +
+ '<a id="a12" class="cl2" href="#">Link12 Shadow</a>' +
+ '<a id="a13" class="cl1" href="#">Link13 Shadow</a>' +
+ '<a id="a14" class="cl3" href="#">Link14 Shadow</a>' +
+ '</li>' +
+ '<li id="li2">' +
+ '<a id="a21" href="#">Link21</a><a id="a22" href="#">Link22</a>' +
+ '</li>' +
+ '<li id="li3" class="shadow">' +
+ '<a id="a31" href="#">Link31 Shadow</a><a id="a32" href="#">Link32 Shadow</a>' +
+ '</li>' +
+ '<li id="li4" class="shadow2">' +
+ '<a id="a41" href="#">Link41 Shadow 2</a><a id="a42" href="#">Link22 Shadow 2</a>' +
+ '</li>' +
+ '<li id="li5" class="shadow2">' +
+ '<a id="a51" href="#">Link51 Shadow</a><a id="a52" href="#">Link52 Shadow 2</a>' +
+ '</li>' +
+ '</ul>';
+
+ d.body.appendChild(div);
+
+ //make nested shadow tree to check the reprojection
+ var li1 = d.querySelector('#li1');
+ var s = li1.createShadowRoot();
+ var shadowLI1 = document.createElement('li');
+ shadowLI1.innerHTML = '<content select=".cl1"></content>';
+ s.appendChild(shadowLI1);
+
+ //check the tree. a11 and a13 should be visible
+ assert_true(d.querySelector('#a11').offsetTop > 0,
+ 'Point 1: Node that matches insertion point criteria should be rendered');
+ assert_true(d.querySelector('#a13').offsetTop > 0,
+ 'Point 2: Node that matches insertion point criteria should be rendered');
+ assert_equals(d.querySelector('#a12').offsetTop, 0,
+ 'Point 3: Node that doesn\'t match insertion point criteria shouldn\'t be rendered');
+ assert_equals(d.querySelector('#a14').offsetTop, 0,
+ 'Point 4: Node that doesn\'t match insertion point criteria shouldn\'t be rendered');
+
+
+ var shadowLI2 = document.createElement('li');
+ shadowLI2.innerHTML = '<content select=".cl3"></content>';
+ s.appendChild(shadowLI2);
+
+ //At this point a11, a13 and a14 should be visible
+ assert_true(d.querySelector('#a11').offsetTop > 0,
+ 'Point 11: Node that matches insertion point criteria should be rendered');
+ assert_true(d.querySelector('#a13').offsetTop > 0,
+ 'Point 12: Node that matches insertion point criteria should be rendered');
+ assert_true(d.querySelector('#a14').offsetTop > d.querySelector('#a13').offsetTop,
+ 'Point 13: Node that matches insertion point criteria should be rendered');
+ assert_equals(d.querySelector('#a12').offsetTop, 0,
+ 'Point 14: Node that doesn\'t match insertion point criteria shouldn\'t be rendered');
+
+
+ //Shadow root to play with
+ var ul = d.querySelector('#host');
+
+ //make an old shadow tree
+ var s2 = ul.createShadowRoot();
+ var div2 = d.createElement('div');
+ div2.innerHTML = '<ul><content select=".shadow"></content></ul>';
+ s2.appendChild(div2);
+
+ // At this point visible: li1 and li3
+ assert_true(d.querySelector('#li1').offsetTop > 0, 'Point 21: Node that match insertion ' +
+ 'point criteria should be rendered');
+ assert_true(d.querySelector('#li3').offsetTop > 0, 'Point 22: Node that match insertion ' +
+ 'point criteria should be rendered');
+ assert_equals(d.querySelector('#li2').offsetTop, 0, 'Point 23: Node that doen\'t match ' +
+ 'insertion point criteria shouldn\'t be rendered');
+ assert_equals(d.querySelector('#li4').offsetTop, 0, 'Point 24: Node that doen\'t match ' +
+ 'insertion point criteria shouldn\'t be rendered');
+ assert_equals(d.querySelector('#li5').offsetTop, 0, 'Point 25: Node that doen\'t match ' +
+ 'insertion point criteria shouldn\'t be rendered');
+
+ //check the reprojected nodes
+ assert_true(d.querySelector('#a11').offsetTop > 0,
+ 'Point 26: Node that matches insertion point criteria should be rendered');
+ assert_true(d.querySelector('#a13').offsetTop > 0,
+ 'Point 27: Node that matches insertion point criteria should be rendered');
+ assert_true(d.querySelector('#a14').offsetTop > d.querySelector('#a13').offsetTop,
+ 'Point 28: Node that matches insertion point criteria should be rendered');
+ assert_equals(d.querySelector('#a12').offsetTop, 0,
+ 'Point 29: Node that doesn\'t match insertion point criteria shouldn\'t be rendered');
+
+
+
+ //make a young shadow tree
+ var s3 = ul.createShadowRoot();
+ var div3 = d.createElement('div');
+ div3.innerHTML = '<ul><content select=".shadow2"></content></ul>';
+ s3.appendChild(div3);
+
+ //At this point: li4 and li5 visible, others not
+ assert_true(d.querySelector('#li4').offsetTop > 0, 'Point 31: Node that match insertion ' +
+ 'point criteria should be rendered');
+ assert_true(d.querySelector('#li5').offsetTop > 0, 'Point 32: Node that match insertion ' +
+ 'point criteria should be rendered');
+ assert_equals(d.querySelector('#li1').offsetTop, 0, 'Point 33: Node that doen\'t match ' +
+ 'insertion point criteria shouldn\'t be rendered');
+ assert_equals(d.querySelector('#li2').offsetTop, 0, 'Point 34: Node that doen\'t match ' +
+ 'insertion point criteria shouldn\'t be rendered');
+ assert_equals(d.querySelector('#li3').offsetTop, 0, 'Point 35: Node that doen\'t match ' +
+ 'insertion point criteria shouldn\'t be rendered');
+
+ //check the reprojected nodes (all invisible)
+ assert_equals(d.querySelector('#a11').offsetTop, 0,
+ 'Point 36: Aleady distributed nodes should behave like a shadow host child nodes');
+ assert_equals(d.querySelector('#a12').offsetTop, 0,
+ 'Point 37: Aleady distributed nodes should behave like a shadow host child nodes');
+ assert_equals(d.querySelector('#a13').offsetTop, 0,
+ 'Point 38: Aleady distributed nodes should behave like a shadow host child nodes');
+ assert_equals(d.querySelector('#a14').offsetTop, 0,
+ 'Point 39: Aleady distributed nodes should behave like a shadow host child nodes');
+
+ var shadow = d.createElement('shadow');
+ s3.appendChild(shadow);
+
+ //At this point: li1, li3, li4 and li5 visible li2 not
+ assert_true(d.querySelector('#li1').offsetTop > 0, 'Point 41: Node that match insertion ' +
+ 'point criteria should be rendered');
+ assert_true(d.querySelector('#li3').offsetTop > 0, 'Point 42: Node that match insertion ' +
+ 'point criteria should be rendered');
+ assert_equals(d.querySelector('#li2').offsetTop, 0, 'Point 43: Node that doen\'t match ' +
+ 'insertion point criteria shouldn\'t be rendered');
+ assert_true(d.querySelector('#li4').offsetTop > 0, 'Point 44: Node that doen\'t match ' +
+ 'insertion point criteria shouldn\'t be rendered');
+ assert_true(d.querySelector('#li5').offsetTop > 0, 'Point 45: Node that doen\'t match ' +
+ 'insertion point criteria shouldn\'t be rendered');
+
+ //check the reprojected nodes (a11, a13, a14 visible, a12 not)
+ assert_true(d.querySelector('#a11').offsetTop > 0,
+ 'Point 46: Aleady distributed nodes should behave like a shadow host child nodes');
+ assert_equals(d.querySelector('#a12').offsetTop, 0,
+ 'Point 47: Aleady distributed nodes should behave like a shadow host child nodes');
+ assert_true(d.querySelector('#a13').offsetTop > 0,
+ 'Point 48: Aleady distributed nodes should behave like a shadow host child nodes');
+ assert_true(d.querySelector('#a14').offsetTop > 0,
+ 'Point 49: Aleady distributed nodes should behave like a shadow host child nodes');
+
+ var shadow2 = d.createElement('shadow');
+ s3.appendChild(shadow2);
+
+ // Nothing should be changed
+ //At this point: li1, li3, li4 and li5 visible li2 not
+ assert_true(d.querySelector('#li1').offsetTop > 0, 'Point 51: Node that match insertion ' +
+ 'point criteria should be rendered');
+ assert_true(d.querySelector('#li3').offsetTop > 0, 'Point 52: Node that match insertion ' +
+ 'point criteria should be rendered');
+ assert_equals(d.querySelector('#li2').offsetTop, 0, 'Point 53: Node that doen\'t match ' +
+ 'insertion point criteria shouldn\'t be rendered');
+ assert_true(d.querySelector('#li4').offsetTop > 0, 'Point 54: Node that doen\'t match ' +
+ 'insertion point criteria shouldn\'t be rendered');
+ assert_true(d.querySelector('#li5').offsetTop > 0, 'Point 55: Node that doen\'t match ' +
+ 'insertion point criteria shouldn\'t be rendered');
+
+ //check the reprojected nodes (a11 and a13 visible, a12 not)
+ assert_true(d.querySelector('#a11').offsetTop > 0,
+ 'Point 56: Aleady distributed nodes should behave like a shadow host child nodes');
+ assert_equals(d.querySelector('#a12').offsetTop, 0,
+ 'Point 57: Aleady distributed nodes should behave like a shadow host child nodes');
+ assert_true(d.querySelector('#a13').offsetTop > 0,
+ 'Point 58: Aleady distributed nodes should behave like a shadow host child nodes');
+ assert_true(d.querySelector('#a14').offsetTop > 0,
+ 'Point 59: Aleady distributed nodes should behave like a shadow host child nodes');
+
+ //replace the nested tree by younger one
+ var s4 = li1.createShadowRoot();
+ var shadowLI4 = document.createElement('li');
+ shadowLI4.innerHTML = '<content select=".cl2"></content>';
+ s4.appendChild(shadowLI4);
+
+ //At this point: li1, li3, li4 and li5 visible li2 not
+ assert_true(d.querySelector('#li1').offsetTop > 0, 'Point 61: Node that match insertion ' +
+ 'point criteria should be rendered');
+ assert_true(d.querySelector('#li3').offsetTop > 0, 'Point 62: Node that match insertion ' +
+ 'point criteria should be rendered');
+ assert_equals(d.querySelector('#li2').offsetTop, 0, 'Point 63: Node that doen\'t match ' +
+ 'insertion point criteria shouldn\'t be rendered');
+ assert_true(d.querySelector('#li4').offsetTop > 0, 'Point 64: Node that doen\'t match ' +
+ 'insertion point criteria shouldn\'t be rendered');
+ assert_true(d.querySelector('#li5').offsetTop > 0, 'Point 65: Node that doen\'t match ' +
+ 'insertion point criteria shouldn\'t be rendered');
+
+ //check the reprojected nodes (a12 visible, others not)
+ assert_equals(d.querySelector('#a11').offsetTop, 0,
+ 'Point 66: Aleady distributed nodes should behave like a shadow host child nodes');
+ assert_true(d.querySelector('#a12').offsetTop > 0,
+ 'Point 67: Aleady distributed nodes should behave like a shadow host child nodes');
+ assert_equals(d.querySelector('#a13').offsetTop, 0,
+ 'Point 68: Aleady distributed nodes should behave like a shadow host child nodes');
+ assert_equals(d.querySelector('#a14').offsetTop, 0,
+ 'Point 69: Aleady distributed nodes should behave like a shadow host child nodes');
+
+
+ //Let's check that if we add a shadow insertion point to the tree nothing is
+ //changed in the nested three (old tree is still invisible)
+ var shadow3 = d.createElement('shadow');
+ s3.appendChild(shadow3);
+
+ //At this point: li1, li3, li4 and li5 visible li2 not
+ assert_true(d.querySelector('#li1').offsetTop > 0, 'Point 61: Node that match insertion ' +
+ 'point criteria should be rendered');
+ assert_true(d.querySelector('#li3').offsetTop > 0, 'Point 62: Node that match insertion ' +
+ 'point criteria should be rendered');
+ assert_equals(d.querySelector('#li2').offsetTop, 0, 'Point 63: Node that doen\'t match ' +
+ 'insertion point criteria shouldn\'t be rendered');
+ assert_true(d.querySelector('#li4').offsetTop > 0, 'Point 64: Node that doen\'t match ' +
+ 'insertion point criteria shouldn\'t be rendered');
+ assert_true(d.querySelector('#li5').offsetTop > 0, 'Point 65: Node that doen\'t match ' +
+ 'insertion point criteria shouldn\'t be rendered');
+
+ //check the reprojected nodes (a12 visible, others not)
+ assert_equals(d.querySelector('#a11').offsetTop, 0,
+ 'Point 66: Aleady distributed nodes should behave like a shadow host child nodes');
+ assert_true(d.querySelector('#a12').offsetTop > 0,
+ 'Point 67: Aleady distributed nodes should behave like a shadow host child nodes');
+ assert_equals(d.querySelector('#a13').offsetTop, 0,
+ 'Point 68: Aleady distributed nodes should behave like a shadow host child nodes');
+ assert_equals(d.querySelector('#a14').offsetTop, 0,
+ 'Point 69: Aleady distributed nodes should behave like a shadow host child nodes');
+}), 'A_04_09_01_T01');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/reprojection/reprojection-001-ref.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/reprojection/reprojection-001-ref.html
new file mode 100644
index 00000000000..98c7a609c4f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/reprojection/reprojection-001-ref.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>Shadow DOM Test: Basic reprojection (reference)</title>
+<link rel="author" title="Anna Ogawa" href="mailto:anna.ogawa.0219@gmail.com">
+<link rel="author" title="Hayato Ito" href="mailto:hayato@google.com">
+<style>
+.pass { color: green; }
+</style>
+</head>
+<body>
+<p>You should see green text saying "Apple" and "Orange" below.</p>
+<div id="host">
+ <div id="host2">
+ <div>Hello a Shadow Root2.</div>
+ <div>
+ Hello a Shadow Root.
+ <div class="pass">Apple.</div>
+ <div class="pass">Orange.</div>
+ <div>Banana.</div>
+ </div>
+ </div>
+</div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/reprojection/reprojection-001.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/reprojection/reprojection-001.html
new file mode 100644
index 00000000000..6f957709e9c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/reprojection/reprojection-001.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>Shadow DOM Test - Tests a reprojection.</title>
+<link rel="match" href="reprojection-001-ref.html">
+<link rel="author" title="Anna Ogawa" href="mailto:anna.ogawa.0219@gmail.com">
+<link rel="author" title="Hayato Ito" href="mailto:hayato@google.com">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#reprojection">
+<meta name="assert" content="a node is distributed into more than one insertion point.">
+<script src="../../testcommon.js"></script>
+<style>
+.pass { color: green; }
+</style>
+</head>
+<body>
+<p>You should see green text saying "Apple" and "Orange" below.</p>
+<div id="host">
+ <div class="pass">Apple.</div>
+ <div class="pass">Orange.</div>
+</div>
+<script>
+ var shadowRoot = host.createShadowRoot(host);
+ shadowRoot.innerHTML = '<div id="host2">Hello a Shadow Root.<content></content><div>Banana.</div></div>';
+ var host2 = shadowRoot.getElementById("host2");
+ var shadowRoot2 = host2.createShadowRoot(host2);
+ shadowRoot2.innerHTML = '<div>Hello a Shadow Root2.</div><div><content></content></div>';
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/reprojection/reprojection-002-ref.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/reprojection/reprojection-002-ref.html
new file mode 100644
index 00000000000..8e538c91e59
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/reprojection/reprojection-002-ref.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>Shadow DOM Test: Basic reprojection with a select attribute (reference)</title>
+<link rel="author" title="Anna Ogawa" href="mailto:anna.ogawa.0219@gmail.com">
+<link rel="author" title="Hayato Ito" href="mailto:hayato@google.com">
+<style>
+.pass { color: green; }
+</style>
+</head>
+<body>
+<p>You should see green text saying "Apple" below.</p>
+<div id="host">
+ <div>Hello a Shadow Root2.</div>
+ <div>
+ <div class="pass">Apple.</div>
+ </div>
+</div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/reprojection/reprojection-002.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/reprojection/reprojection-002.html
new file mode 100644
index 00000000000..8cc408d8860
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/reprojection/reprojection-002.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<!DOCTYPE html>
+<head>
+<meta charset="utf-8">
+<title>Shadow DOM Test - Tests a reprojection with a select attribute.</title>
+<link rel="match" href="reprojection-002-ref.html">
+<link rel="author" title="Anna Ogawa" href="mailto:anna.ogawa.0219@gmail.com">
+<link rel="author" title="Hayato Ito" href="mailto:hayato@google.com">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#reprojection">
+<meta name="assert" content="A node is distributed into more than one insertion point with a select attribute.">
+<script src="../../testcommon.js"></script>
+<style>
+.pass { color: green; }
+.fail { color: red; }
+</style>
+</head>
+<body>
+<p>You should see green text saying "Apple" below.</p>
+<div id="host">
+ <div class="A pass">Apple.</div>
+ <div class="B fail">Orange.</div>
+</div>
+<script>
+ var shadowRoot = host.createShadowRoot();
+ shadowRoot.innerHTML = '<div id="host2">Hello a Shadow Root.<content></content><div class="fail">Banana.</div></div>';
+ var host2 = shadowRoot.getElementById("host2");
+ var shadowRoot2 = host2.createShadowRoot();
+ shadowRoot2.innerHTML = '<div>Hello a Shadow Root2.</div><div><content select=".A"></content></div>';
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/reprojection/test-001.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/reprojection/test-001.html
new file mode 100644
index 00000000000..eaaa0c7de2c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/reprojection/test-001.html
@@ -0,0 +1,176 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_04_06_01</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#reprojection">
+<meta name="assert" content="Reprojection: The nodes distributed into that insertion point must appear as if they were child nodes of the shadow host in the context of distribution within the shadow DOM subtree, hosted by said shadow host">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_04_06_01_T01 = async_test('A_04_06_01_T01');
+
+A_04_06_01_T01.step(function () {
+ var iframe = document.createElement('iframe');
+ iframe.src = '../../resources/blank.html';
+ document.body.appendChild(iframe);
+
+ iframe.onload = A_04_06_01_T01.step_func(function () {
+ try {
+ var d = iframe.contentDocument;
+
+ var div = d.createElement('div');
+ div.innerHTML = '' +
+ '<ul id="host">' +
+ '<li id="li1" class="shadow">' +
+ '<a id="a11" class="cl1" href="#">Link11 Shadow</a>' +
+ '<a id="a12" class="cl2" href="#">Link12 Shadow</a>' +
+ '<a id="a13" class="cl1" href="#">Link13 Shadow</a>' +
+ '</li>' +
+ '<li id="li2">' +
+ '<a id="a21" href="#">Link21</a><a id="a22" href="#">Link22</a>' +
+ '</li>' +
+ '<li id="li3" class="shadow">' +
+ '<a id="a31" href="#">Link31 Shadow</a><a id="a32" href="#">Link32 Shadow</a>' +
+ '</li>' +
+ '<li id="li4" class="shadow2">' +
+ '<a id="a41" href="#">Link41 Shadow 2</a><a id="a42" href="#">Link22 Shadow 2</a>' +
+ '</li>' +
+ '<li id="li5" class="shadow2">' +
+ '<a id="a51" href="#">Link51 Shadow</a><a id="a52" href="#">Link52 Shadow 2</a>' +
+ '</li>' +
+ '</ul>';
+
+ d.body.appendChild(div);
+
+ var li1 = d.querySelector('#li1');
+ var s = li1.createShadowRoot();
+ //make shadow subtree
+ var shadowLI1 = document.createElement('li');
+ shadowLI1.innerHTML = '<li><content select=".cl1"></content></li>';
+ s.appendChild(shadowLI1);
+
+ var ul = d.querySelector('#host');
+ var s2 = ul.createShadowRoot();
+ var div2 = document.createElement('div');
+ div2.innerHTML = '<ul><content select=".shadow"></content></ul>';
+ s2.appendChild(div2);
+
+
+ assert_true(d.querySelector('#li1').offsetTop > 0, 'Point 1: Node that match insertion ' +
+ 'point criteria should be rendered');
+ assert_true(d.querySelector('#li3').offsetTop > 0, 'Point 2: Node that match insertion ' +
+ 'point criteria should be rendered');
+ assert_equals(d.querySelector('#li2').offsetTop, 0, 'Point 3: Node that doen\'t match ' +
+ 'insertion point criteria shouldn\'t be rendered');
+ assert_equals(d.querySelector('#li4').offsetTop, 0, 'Point 4: Node that doen\'t match ' +
+ 'insertion point criteria shouldn\'t be rendered');
+ assert_equals(d.querySelector('#li5').offsetTop, 0, 'Point 5: Node that doen\'t match ' +
+ 'insertion point criteria shouldn\'t be rendered');
+
+ //check the nested tree
+ assert_true(d.querySelector('#a11').offsetTop > 0,
+ 'Point 6: Aleady distributed nodes should behave like a shadow host child nodes');
+ assert_true(d.querySelector('#a13').offsetTop > 0,
+ 'Point 7: Aleady distributed nodes should behave like a shadow host child nodes');
+ assert_equals(d.querySelector('#a12').offsetTop, 0,
+ 'Point 8: Aleady distributed nodes should behave like a shadow host child nodes');
+ } finally {
+ iframe.parentNode.removeChild(iframe);
+ }
+ A_04_06_01_T01.done();
+ });
+});
+
+
+
+var A_04_06_01_T02 = async_test('A_04_06_01_T02');
+
+A_04_06_01_T02.step(function () {
+ var iframe = document.createElement('iframe');
+ iframe.src = '../../resources/blank.html';
+ document.body.appendChild(iframe);
+
+ iframe.onload = A_04_06_01_T02.step_func(function () {
+ try {
+ var d = iframe.contentDocument;
+
+ var div = d.createElement('div');
+ div.innerHTML = '' +
+ '<ul id="host">' +
+ '<li id="li1" class="shadow">' +
+ '<a id="a11" class="cl1" href="#">Link11 Shadow</a>' +
+ '<a id="a12" class="cl2" href="#">Link12 Shadow</a>' +
+ '<a id="a13" class="cl1" href="#">Link13 Shadow</a>' +
+ '</li>' +
+ '<li id="li2">' +
+ '<a id="a21" href="#">Link21</a><a id="a22" href="#">Link22</a>' +
+ '</li>' +
+ '<li id="li3" class="shadow">' +
+ '<a id="a31" href="#">Link31 Shadow</a><a id="a32" href="#">Link32 Shadow</a>' +
+ '</li>' +
+ '<li id="li4" class="shadow2">' +
+ '<a id="a41" href="#">Link41 Shadow 2</a><a id="a42" href="#">Link22 Shadow 2</a>' +
+ '</li>' +
+ '<li id="li5" class="shadow2">' +
+ '<a class="cl1" id="a51" href="#">Link51 Shadow</a><a id="a52" href="#">Link52 Shadow 2</a>' +
+ '</li>' +
+ '</ul>';
+
+ d.body.appendChild(div);
+
+ var li1 = d.querySelector('#li1');
+ var s = li1.createShadowRoot();
+ //make shadow subtree
+ var shadowLI1 = document.createElement('li');
+ shadowLI1.innerHTML = '<li><content select=".cl1"></content></li>';
+ s.appendChild(shadowLI1);
+
+ var ul = d.querySelector('#host');
+ var s2 = ul.createShadowRoot();
+ var div2 = document.createElement('div');
+ div2.innerHTML = '<li><content select=".cl1"></content></li>';
+ s2.appendChild(div2);
+
+ // The second distribution shouldn't render anything
+ assert_equals(d.querySelector('#li1').offsetTop, 0, 'Point 1: Node that doen\'t match ' +
+ 'insertion point criteria shouldn\'t be rendered');
+ assert_equals(d.querySelector('#li2').offsetTop, 0, 'Point 2: Node that doen\'t match ' +
+ 'insertion point criteria shouldn\'t be rendered');
+ assert_equals(d.querySelector('#li3').offsetTop, 0, 'Point 3: Node that doen\'t match ' +
+ 'insertion point criteria shouldn\'t be rendered');
+ assert_equals(d.querySelector('#li4').offsetTop, 0, 'Point 4: Node that doen\'t match ' +
+ 'insertion point criteria shouldn\'t be rendered');
+ assert_equals(d.querySelector('#li5').offsetTop, 0, 'Point 5: Node that doen\'t match ' +
+ 'insertion point criteria shouldn\'t be rendered');
+
+ //check the nested tree
+ assert_equals(d.querySelector('#a11').offsetTop, 0,
+ 'Point 6: Aleady distributed nodes should behave like a shadow host child nodes');
+ assert_equals(d.querySelector('#a13').offsetTop, 0,
+ 'Point 7: Aleady distributed nodes should behave like a shadow host child nodes');
+ assert_equals(d.querySelector('#a12').offsetTop, 0,
+ 'Point 8: Aleady distributed nodes should behave like a shadow host child nodes');
+ } finally {
+ iframe.parentNode.removeChild(iframe);
+ }
+ A_04_06_01_T02.done();
+ });
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-001.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-001.html
new file mode 100644
index 00000000000..2291c9329d0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-001.html
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_04_03_01</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#matching-insertion-points">
+<meta name="assert" content="Matching Insertion Points: A valid selector fragment may contain a type selector">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_04_03_01_T1 = async_test('A_04_03_01_T01');
+
+
+A_04_03_01_T1.step(function () {
+ var iframe = document.createElement('iframe');
+ iframe.src = '../../resources/bobs_page.html';
+ document.body.appendChild(iframe);
+
+ iframe.onload = A_04_03_01_T1.step_func(function () {
+ try {
+ var d = iframe.contentDocument;
+ var div = d.querySelector('#divid');
+ var s = div.createShadowRoot();
+
+ //make shadow subtree
+ var subdiv1 = document.createElement('div');
+ subdiv1.innerHTML = '<content select="span"></content>';
+ s.appendChild(subdiv1);
+
+ //The order of DOM elements should be the following:
+ // <ul class='stories'>, <span>. Invisible: <ul id="ul2">
+
+ assert_true(d.querySelector('ul.stories').offsetTop < d.querySelector('#spandex').offsetTop,
+ 'A valid selector fragment may contain \'span\' type selector');
+
+ assert_equals(d.querySelector('#ul2').offsetTop, 0,
+ '<ul> element shouldn\'t match "span" type selector');
+ } finally {
+ iframe.parentNode.removeChild(iframe);
+ }
+ A_04_03_01_T1.done();
+ });
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-002.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-002.html
new file mode 100644
index 00000000000..ca64b9ed103
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-002.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_04_03_02</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#matching-insertion-points">
+<meta name="assert" content="Matching Insertion Points: A valid selector fragment may contain an universal selector">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_04_03_02_T1 = async_test('A_04_03_02_T01');
+
+
+A_04_03_02_T1.step(function () {
+ var iframe = document.createElement('iframe');
+ iframe.src = '../../resources/bobs_page.html';
+ document.body.appendChild(iframe);
+
+ iframe.onload = A_04_03_02_T1.step_func(function () {
+ try {
+ var d = iframe.contentDocument;
+ var ul = d.querySelector('ul.stories');
+ var s = ul.createShadowRoot();
+
+ //make shadow subtree
+ var subdiv1 = document.createElement('div');
+
+ // TODO add tests for namespace universal selector ns|*
+ subdiv1.innerHTML = '<ul><content select="*"></content></ul>';
+ s.appendChild(subdiv1);
+
+ //The order of DOM elements should be the following:
+ // li1-li6 should be visible and located on-order
+ assert_true(d.querySelector('#li1').offsetTop < d.querySelector('#li2').offsetTop,
+ 'Point 1: Elements that mach insertion point criteria don\'t participate in distribution');
+ assert_true(d.querySelector('#li2').offsetTop < d.querySelector('#li3').offsetTop,
+ 'Point 2: Elements that mach insertion point criteria don\'t participate in distribution');
+ assert_true(d.querySelector('#li3').offsetTop < d.querySelector('#li4').offsetTop,
+ 'Point 3: Elements that mach insertion point criteria don\'t participate in distribution');
+ assert_true(d.querySelector('#li4').offsetTop < d.querySelector('#li5').offsetTop,
+ 'Point 4: Elements that mach insertion point criteria don\'t participate in distribution');
+ assert_true(d.querySelector('#li5').offsetTop < d.querySelector('#li6').offsetTop,
+ 'Point 5: Elements that mach insertion point criteria don\'t participate in distribution');
+ } finally {
+ iframe.parentNode.removeChild(iframe);
+ }
+ A_04_03_02_T1.done();
+ });
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-003.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-003.html
new file mode 100644
index 00000000000..0eca071503f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-003.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_04_03_03</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#matching-insertion-points">
+<meta name="assert" content="Matching Insertion Points: A valid selector fragment may contain a class selector">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_04_03_03_T01 = async_test('A_04_03_03_T01');
+
+
+A_04_03_03_T01.step(function () {
+ var iframe = document.createElement('iframe');
+ iframe.src = '../../resources/bobs_page.html';
+ document.body.appendChild(iframe);
+
+ iframe.onload = A_04_03_03_T01.step_func(function () {
+ try {
+ var d = iframe.contentDocument;
+ var ul = d.querySelector('ul.stories');
+ var s = ul.createShadowRoot();
+
+ //make shadow subtree
+ var subdiv1 = document.createElement('div');
+ subdiv1.innerHTML = '<ul><content select=".shadow"></content></ul>';
+ s.appendChild(subdiv1);
+
+ //The order of DOM elements should be the following:
+ //li3, li6. Other elements invisible
+ assert_true(d.querySelector('#li3').offsetTop < d.querySelector('#li6').offsetTop,
+ 'Class name should be a valid insertion point matching criteria');
+ assert_true(d.querySelector('#li3').offsetTop > 0,
+ 'Class name should be a valid insertion point matching criteria, element should be visible');
+
+ assert_equals(d.querySelector('#li1').offsetTop, 0,
+ 'Point 1: Elements that don\'t mach insertion point criteria participate in distribution');
+ assert_equals(d.querySelector('#li2').offsetTop, 0,
+ 'Point 2: Elements that don\'t mach insertion point criteria participate in distribution');
+ assert_equals(d.querySelector('#li4').offsetTop, 0,
+ 'Point 3: Elements that don\'t mach insertion point criteria participate in distribution');
+ assert_equals(d.querySelector('#li5').offsetTop, 0,
+ 'Point 4: Elements that don\'t mach insertion point criteria participate in distribution');
+ } finally {
+ iframe.parentNode.removeChild(iframe);
+ }
+ A_04_03_03_T01.done();
+ });
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-004.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-004.html
new file mode 100644
index 00000000000..f90d8a4a530
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-004.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_04_03_04</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#matching-insertion-points">
+<meta name="assert" content="Matching Insertion Points: A valid selector fragment may contain an ID selector">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_04_03_04_T01 = async_test('A_04_03_04_T01');
+
+A_04_03_04_T01.step(function () {
+ var iframe = document.createElement('iframe');
+ iframe.src = '../../resources/bobs_page.html';
+ document.body.appendChild(iframe);
+
+ iframe.onload = A_04_03_04_T01.step_func(function () {
+ try {
+ var d = iframe.contentDocument;
+ var ul = d.querySelector('ul.stories');
+ var s = ul.createShadowRoot();
+
+ //make shadow subtree
+ var subdiv1 = document.createElement('div');
+ subdiv1.innerHTML = '<ul><content select="#li4"></content></ul>';
+ s.appendChild(subdiv1);
+
+ //The order of DOM elements should be the following:
+ //li4. Other elements invisible
+ assert_true(d.querySelector('#li4').offsetTop > 0,
+ 'Class name should be a valid insertion point matching criteria, element should be visible');
+
+ assert_equals(d.querySelector('#li1').offsetTop, 0,
+ 'Point 1: Elements that don\'t mach insertion point criteria participate in distribution');
+ assert_equals(d.querySelector('#li2').offsetTop, 0,
+ 'Point 2: Elements that don\'t mach insertion point criteria participate in distribution');
+ assert_equals(d.querySelector('#li3').offsetTop, 0,
+ 'Point 3: Elements that don\'t mach insertion point criteria participate in distribution');
+ assert_equals(d.querySelector('#li5').offsetTop, 0,
+ 'Point 4: Elements that don\'t mach insertion point criteria participate in distribution');
+ assert_equals(d.querySelector('#li6').offsetTop, 0,
+ 'Point 5: Elements that don\'t mach insertion point criteria participate in distribution');
+ } finally {
+ iframe.parentNode.removeChild(iframe);
+ }
+ A_04_03_04_T01.done();
+ });
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-005.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-005.html
new file mode 100644
index 00000000000..3fca25f375b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-005.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_04_03_05</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#matching-insertion-points">
+<meta name="assert" content="Matching Insertion Points: A valid selector fragment may contain an attribute selector">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_04_03_05_T01 = async_test('A_04_03_05_T01');
+
+A_04_03_05_T01.step(function () {
+ var iframe = document.createElement('iframe');
+ iframe.src = '../../resources/bobs_page.html';
+ document.body.appendChild(iframe);
+
+ iframe.onload = A_04_03_05_T01.step_func(function () {
+ try {
+ var d = iframe.contentDocument;
+ var ul = d.querySelector('ul.stories');
+ var s = ul.createShadowRoot();
+
+ //make shadow subtree
+ var subdiv1 = document.createElement('div');
+ subdiv1.innerHTML = '<ul><content select="li[title]"></content></ul>';
+ s.appendChild(subdiv1);
+
+ //The order of DOM elements should be the following:
+ //li2. Other elements invisible
+ assert_true(d.querySelector('#li2').offsetTop > 0,
+ 'Attribute should be a valid insertion point matching criteria, element should be visible');
+
+ assert_equals(d.querySelector('#li1').offsetTop, 0,
+ 'Point 1: Elements that don\'t mach insertion point criteria participate in distribution');
+ assert_equals(d.querySelector('#li3').offsetTop, 0,
+ 'Point 2: Elements that don\'t mach insertion point criteria participate in distribution');
+ assert_equals(d.querySelector('#li4').offsetTop, 0,
+ 'Point 3: Elements that don\'t mach insertion point criteria participate in distribution');
+ assert_equals(d.querySelector('#li5').offsetTop, 0,
+ 'Point 4: Elements that don\'t mach insertion point criteria participate in distribution');
+ assert_equals(d.querySelector('#li6').offsetTop, 0,
+ 'Point 5: Elements that don\'t mach insertion point criteria participate in distribution');
+ } finally {
+ iframe.parentNode.removeChild(iframe);
+ }
+ A_04_03_05_T01.done();
+ });
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-006.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-006.html
new file mode 100644
index 00000000000..b6731d5d867
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-006.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_04_03_06_01</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#matching-insertion-points">
+<meta name="assert" content="Matching Insertion Points: A valid selector fragment may contain a :link pseudo-class selector">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_04_03_06_01_T01 = async_test('A_04_03_06_01_T01');
+
+
+A_04_03_06_01_T01.step(function () {
+ var iframe = document.createElement('iframe');
+ iframe.src = '../../resources/bobs_page.html';
+ document.body.appendChild(iframe);
+
+ iframe.onload = A_04_03_06_01_T01.step_func(function () {
+ try {
+
+ var d = iframe.contentDocument;
+ var div = d.querySelector('#links-wrapper');
+ var s = div.createShadowRoot();
+
+ //make shadow subtree
+ var subdiv1 = document.createElement('div');
+ subdiv1.innerHTML = '<content select=":link"></content>';
+ s.appendChild(subdiv1);
+
+ //All links elements should be visible
+ assert_true(d.querySelector('#link10').offsetTop > 0,
+ 'Point 1: <a> tag should match :link pseudo-class selector');
+ assert_true(d.querySelector('#link11').offsetTop > 0,
+ 'Point 2: <a> tag should match :link pseudo-class selector');
+ } finally {
+ iframe.parentNode.removeChild(iframe);
+ }
+ A_04_03_06_01_T01.done();
+ });
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-007.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-007.html
new file mode 100644
index 00000000000..f1cf07f1794
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-007.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_04_03_06_03</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#matching-insertion-points">
+<meta name="assert" content="Matching Insertion Points: A valid selector fragment may contain a :target pseudo-class selector">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_04_03_06_03_T01 = async_test('A_04_03_06_03_T01');
+
+
+A_04_03_06_03_T01.step(function () {
+ var iframe = document.createElement('iframe');
+ iframe.src = '../../resources/bobs_page.html#link10';
+ document.body.appendChild(iframe);
+
+ iframe.onload = A_04_03_06_03_T01.step_func(function () {
+ try {
+
+ var d = iframe.contentDocument;
+ var div = d.querySelector('#links-wrapper');
+ var s = div.createShadowRoot();
+
+ //make shadow subtree
+ var subdiv1 = document.createElement('div');
+ subdiv1.innerHTML = '<content select=":target"></content>';
+ s.appendChild(subdiv1);
+
+ //link10 should be visible, link11 not
+ assert_true(d.querySelector('#link10').offsetTop > 0,
+ 'Element should match :target pseudo-class selector');
+ assert_equals(d.querySelector('#link11').offsetTop, 0,
+ 'Element shouldn\'t match :target pseudo-class selector');
+
+ } finally {
+ iframe.parentNode.removeChild(iframe);
+ }
+ A_04_03_06_03_T01.done();
+ });
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-008.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-008.html
new file mode 100644
index 00000000000..f90e04b3c40
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-008.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_04_03_06_04</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#matching-insertion-points">
+<meta name="assert" content="Matching Insertion Points: A valid selector fragment may contain a :enabled pseudo-class selector">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_04_03_06_04_T01 = async_test('A_04_03_06_04_T01');
+
+
+A_04_03_06_04_T01.step(function () {
+ var iframe = document.createElement('iframe');
+ iframe.src = '../../resources/bobs_page.html';
+ document.body.appendChild(iframe);
+
+ iframe.onload = A_04_03_06_04_T01.step_func(function () {
+ try {
+
+ var d = iframe.contentDocument;
+ var div = d.querySelector('#inputs-wrapper');
+ var s = div.createShadowRoot();
+
+ //make shadow subtree
+ var subdiv1 = document.createElement('div');
+ subdiv1.innerHTML = '<content select=":enabled"></content>';
+ s.appendChild(subdiv1);
+
+ //inp2 should be visible, inp1 not
+ assert_true(d.querySelector('#inp2').offsetTop > 0,
+ 'Element should match :enabled pseudo-class selector');
+ assert_equals(d.querySelector('#inp1').offsetTop, 0,
+ 'Element shouldn\'t match :enabled pseudo-class selector');
+
+ } finally {
+ iframe.parentNode.removeChild(iframe);
+ }
+ A_04_03_06_04_T01.done();
+ });
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-009.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-009.html
new file mode 100644
index 00000000000..1dc5b81625d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-009.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_04_03_06_05</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#matching-insertion-points">
+<meta name="assert" content="Matching Insertion Points: A valid selector fragment may contain a :disabled pseudo-class selector">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_04_03_06_05_T01 = async_test('A_04_03_06_05_T01');
+
+
+A_04_03_06_05_T01.step(function () {
+ var iframe = document.createElement('iframe');
+ iframe.src = '../../resources/bobs_page.html';
+ document.body.appendChild(iframe);
+
+ iframe.onload = A_04_03_06_05_T01.step_func(function () {
+ try {
+
+ var d = iframe.contentDocument;
+ var div = d.querySelector('#inputs-wrapper');
+ var s = div.createShadowRoot();
+
+ //make shadow subtree
+ var subdiv1 = document.createElement('div');
+ subdiv1.innerHTML = '<content select=":disabled"></content>';
+ s.appendChild(subdiv1);
+
+ //inp1 should be visible, inp2 not
+ assert_true(d.querySelector('#inp1').offsetTop > 0,
+ 'Element should match :disabled pseudo-class selector');
+ assert_equals(d.querySelector('#inp2').offsetTop, 0,
+ 'Element shouldn\'t match :disabled pseudo-class selector');
+
+ } finally {
+ iframe.parentNode.removeChild(iframe);
+ }
+ A_04_03_06_05_T01.done();
+ });
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-010.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-010.html
new file mode 100644
index 00000000000..9ad8a6c0909
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-010.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_04_03_06_06</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#matching-insertion-points">
+<meta name="assert" content="Matching Insertion Points: A valid selector fragment may contain a :checked pseudo-class selector">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_04_03_06_06_T01 = async_test('A_04_03_06_06_T01');
+
+
+A_04_03_06_06_T01.step(function () {
+ var iframe = document.createElement('iframe');
+ iframe.src = '../../resources/bobs_page.html';
+ document.body.appendChild(iframe);
+
+ iframe.onload = A_04_03_06_06_T01.step_func(function () {
+ try {
+
+ var d = iframe.contentDocument;
+ var div = d.querySelector('#inputs-wrapper');
+ var s = div.createShadowRoot();
+
+ //make shadow subtree
+ var subdiv1 = document.createElement('div');
+ subdiv1.innerHTML = '<content select=":checked"></content>';
+ s.appendChild(subdiv1);
+
+ //chb1 should be visible, chb2 not
+ assert_true(d.querySelector('#chb1').offsetTop > 0,
+ 'Element should match :checked pseudo-class selector');
+ assert_equals(d.querySelector('#chb2').offsetTop, 0,
+ 'Element shouldn\'t match :checked pseudo-class selector');
+
+ } finally {
+ iframe.parentNode.removeChild(iframe);
+ }
+ A_04_03_06_06_T01.done();
+ });
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-011.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-011.html
new file mode 100644
index 00000000000..4def9a0c648
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-011.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_04_03_06_07</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#matching-insertion-points">
+<meta name="assert" content="Matching Insertion Points: A valid selector fragment may contain a :indeterminate pseudo-class selector">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_04_03_06_07_T01 = async_test('A_04_03_06_07_T01');
+
+
+A_04_03_06_07_T01.step(function () {
+ var iframe = document.createElement('iframe');
+ iframe.src = '../../resources/bobs_page.html';
+ document.body.appendChild(iframe);
+
+ iframe.onload = A_04_03_06_07_T01.step_func(function () {
+ try {
+
+ var d = iframe.contentDocument;
+ var div = d.querySelector('#inputs-wrapper');
+ var s = div.createShadowRoot();
+
+ d.querySelector('#chb1').indeterminate = true;
+
+ //make shadow subtree
+ var subdiv1 = document.createElement('div');
+ subdiv1.innerHTML = '<content select=":indeterminate"></content>';
+ s.appendChild(subdiv1);
+
+ //chb1 should be visible, chb2 not
+ assert_true(d.querySelector('#chb1').offsetTop > 0,
+ 'Element should match :indeterminate pseudo-class selector');
+ assert_equals(d.querySelector('#chb2').offsetTop, 0,
+ 'Element shouldn\'t match :indeterminate pseudo-class selector');
+
+ } finally {
+ iframe.parentNode.removeChild(iframe);
+ }
+ A_04_03_06_07_T01.done();
+ });
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-012.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-012.html
new file mode 100644
index 00000000000..a7dd85cd9df
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-012.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_04_03_06_08</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#matching-insertion-points">
+<meta name="assert" content="Matching Insertion Points: A valid selector fragment may contain a :nth-child() pseudo-class selector">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_04_03_06_08_T01 = async_test('A_04_03_06_08_T01');
+
+
+A_04_03_06_08_T01.step(function () {
+ var iframe = document.createElement('iframe');
+ iframe.src = '../../resources/bobs_page.html';
+ document.body.appendChild(iframe);
+
+ iframe.onload = A_04_03_06_08_T01.step_func(function () {
+ try {
+
+ var d = iframe.contentDocument;
+ var ul = d.querySelector('ul.stories');
+ var s = ul.createShadowRoot();
+
+ //make shadow subtree
+ var subdiv1 = document.createElement('div');
+ subdiv1.innerHTML = '<ul><content select=":nth-child(odd)"></content></ul>';
+ s.appendChild(subdiv1);
+
+ //li1, li3, li5 should be visible, li2, li4, li6 not
+ assert_true(d.querySelector('#li1').offsetTop > 0,
+ '1-st element should match :nth-child(odd) pseudo-class selector');
+ assert_true(d.querySelector('#li3').offsetTop > 0,
+ '3-rd element should match :nth-child(odd) pseudo-class selector');
+ assert_true(d.querySelector('#li5').offsetTop > 0,
+ '5-th element should match :nth-child(odd) pseudo-class selector');
+ assert_equals(d.querySelector('#li2').offsetTop, 0,
+ '2-nd element shouldn\'t match :nth-child() pseudo-class selector');
+ assert_equals(d.querySelector('#li4').offsetTop, 0,
+ '4-th element shouldn\'t match :nth-child() pseudo-class selector');
+ assert_equals(d.querySelector('#li6').offsetTop, 0,
+ '6-nd element shouldn\'t match :nth-child() pseudo-class selector');
+
+ } finally {
+ iframe.parentNode.removeChild(iframe);
+ }
+ A_04_03_06_08_T01.done();
+ });
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-013.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-013.html
new file mode 100644
index 00000000000..31e4f310a69
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-013.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_04_03_06_09</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#matching-insertion-points">
+<meta name="assert" content="Matching Insertion Points: A valid selector fragment may contain a :nth-last-child() pseudo-class selector">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_04_03_06_09_T01 = async_test('A_04_03_06_09_T01');
+
+
+A_04_03_06_09_T01.step(function () {
+ var iframe = document.createElement('iframe');
+ iframe.src = '../../resources/bobs_page.html';
+ document.body.appendChild(iframe);
+
+ iframe.onload = A_04_03_06_09_T01.step_func(function () {
+ try {
+
+ var d = iframe.contentDocument;
+ var ul = d.querySelector('ul.stories');
+ var s = ul.createShadowRoot();
+
+ //make shadow subtree
+ var subdiv1 = document.createElement('div');
+ subdiv1.innerHTML = '<ul><content select=":nth-last-child(2)"></content></ul>';
+ s.appendChild(subdiv1);
+
+ //li6 should be invisible, all other visible
+ assert_true(d.querySelector('#li1').offsetTop > 0,
+ 'Point 1: element should match :nth-last-child(2) pseudo-class selector');
+ assert_true(d.querySelector('#li2').offsetTop > 0,
+ 'Point 2: element should match :nth-last-child(2) pseudo-class selector');
+ assert_true(d.querySelector('#li3').offsetTop > 0,
+ 'Point 3: element should match :nth-last-child(2) pseudo-class selector');
+ assert_true(d.querySelector('#li4').offsetTop > 0,
+ 'Point 4: element should match :nth-last-child(2) pseudo-class selector');
+ assert_true(d.querySelector('#li5').offsetTop > 0,
+ 'Point 5: element should match :nth-last-child(2) pseudo-class selector');
+ assert_equals(d.querySelector('#li6').offsetTop, 0,
+ 'Element shouldn\'t match :nth-last-child(2) pseudo-class selector');
+
+ } finally {
+ iframe.parentNode.removeChild(iframe);
+ }
+ A_04_03_06_09_T01.done();
+ });
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-014.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-014.html
new file mode 100644
index 00000000000..3f0eaad05bc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-014.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_04_03_06_10</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#matching-insertion-points">
+<meta name="assert" content="Matching Insertion Points: A valid selector fragment may contain a :nth-of-type() pseudo-class selector">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_04_03_06_10_T01 = async_test('A_04_03_06_10_T01');
+
+
+A_04_03_06_10_T01.step(function () {
+ var iframe = document.createElement('iframe');
+ iframe.src = '../../resources/bobs_page.html';
+ document.body.appendChild(iframe);
+
+ iframe.onload = A_04_03_06_10_T01.step_func(function () {
+ try {
+
+ var d = iframe.contentDocument;
+ var ul = d.querySelector('ul.stories');
+ var s = ul.createShadowRoot();
+
+ //make shadow subtree
+ var subdiv1 = document.createElement('div');
+ subdiv1.innerHTML = '<ul><content select=":nth-of-type(2n+1)"></content></ul>';
+ s.appendChild(subdiv1);
+
+ //li1, li3, li5 should be visible, li2, li4, li6 not
+ assert_true(d.querySelector('#li1').offsetTop > 0,
+ '1-st element should match :nth-of-type(2n+1) pseudo-class selector');
+ assert_true(d.querySelector('#li3').offsetTop > 0,
+ '3-rd element should match :nth-of-type(2n+1) pseudo-class selector');
+ assert_true(d.querySelector('#li5').offsetTop > 0,
+ '5-th element should match :nth-of-type(2n+1) pseudo-class selector');
+ assert_equals(d.querySelector('#li2').offsetTop, 0,
+ '2-nd element shouldn\'t match :nth-of-type(2n+1) pseudo-class selector');
+ assert_equals(d.querySelector('#li4').offsetTop, 0,
+ '4-th element shouldn\'t match :nth-of-type(2n+1) pseudo-class selector');
+ assert_equals(d.querySelector('#li6').offsetTop, 0,
+ '6-nd element shouldn\'t match :nth-of-type(2n+1) pseudo-class selector');
+
+ } finally {
+ iframe.parentNode.removeChild(iframe);
+ }
+ A_04_03_06_10_T01.done();
+ });
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-015.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-015.html
new file mode 100644
index 00000000000..a074086f88e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-015.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_04_03_06_11</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#matching-insertion-points">
+<meta name="assert" content="Matching Insertion Points: A valid selector fragment may contain a :nth-last-of-type() pseudo-class selector">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_04_03_06_11_T01 = async_test('A_04_03_06_11_T01');
+
+
+A_04_03_06_11_T01.step(function () {
+ var iframe = document.createElement('iframe');
+ iframe.src = '../../resources/bobs_page.html';
+ document.body.appendChild(iframe);
+
+ iframe.onload = A_04_03_06_11_T01.step_func(function () {
+ try {
+
+ var d = iframe.contentDocument;
+ var ul = d.querySelector('ul.stories');
+ var s = ul.createShadowRoot();
+
+ //make shadow subtree
+ var subdiv1 = document.createElement('div');
+ subdiv1.innerHTML = '<ul><content select=":nth-last-of-type(2)"></content></ul>';
+ s.appendChild(subdiv1);
+
+ //li6 should be invisible, all others visible
+ assert_true(d.querySelector('#li1').offsetTop > 0,
+ 'Point 1: element should match :nth-last-of-type(2) pseudo-class selector');
+ assert_true(d.querySelector('#li2').offsetTop > 0,
+ 'Point 2: element should match :nth-last-of-type(2) pseudo-class selector');
+ assert_true(d.querySelector('#li3').offsetTop > 0,
+ 'Point 3: element should match :nth-last-of-type(2) pseudo-class selector');
+ assert_true(d.querySelector('#li4').offsetTop > 0,
+ 'Point 4: element should match :nth-last-of-type(2) pseudo-class selector');
+ assert_true(d.querySelector('#li5').offsetTop > 0,
+ 'Point 5: element should match :nth-last-of-type(2) pseudo-class selector');
+ assert_equals(d.querySelector('#li6').offsetTop, 0,
+ 'Element shouldn\'t match :nth-last-of-type(2) pseudo-class selector');
+
+ } finally {
+ iframe.parentNode.removeChild(iframe);
+ }
+ A_04_03_06_11_T01.done();
+ });
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-016.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-016.html
new file mode 100644
index 00000000000..919c3262624
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-016.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_04_03_06_12</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#matching-insertion-points">
+<meta name="assert" content="Matching Insertion Points: A valid selector fragment may contain a :first-child pseudo-class selector">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_04_03_06_12_T01 = async_test('A_04_03_06_12_T01');
+
+
+A_04_03_06_12_T01.step(function () {
+ var iframe = document.createElement('iframe');
+ iframe.src = '../../resources/bobs_page.html';
+ document.body.appendChild(iframe);
+
+ iframe.onload = A_04_03_06_12_T01.step_func(function () {
+ try {
+
+ var d = iframe.contentDocument;
+ var ul = d.querySelector('ul.stories');
+ var s = ul.createShadowRoot();
+
+ //make shadow subtree
+ var subdiv1 = document.createElement('div');
+ subdiv1.innerHTML = '<ul><content select=":first-child"></content></ul>';
+ s.appendChild(subdiv1);
+
+ //li1 should be visible, all other not
+ assert_true(d.querySelector('#li1').offsetTop > 0,
+ 'Element should match :first-child pseudo-class selector');
+ assert_equals(d.querySelector('#li2').offsetTop, 0,
+ 'Point 1: element shouldn\'t match :first-child pseudo-class selector');
+ assert_equals(d.querySelector('#li3').offsetTop, 0,
+ 'Point 2: element shouldn\'t match :first-child pseudo-class selector');
+ assert_equals(d.querySelector('#li4').offsetTop, 0,
+ 'Point 3: element shouldn\'t match :first-child pseudo-class selector');
+ assert_equals(d.querySelector('#li5').offsetTop, 0,
+ 'Point 4: element shouldn\'t match :first-child pseudo-class selector');
+ assert_equals(d.querySelector('#li6').offsetTop, 0,
+ 'Point 5: element shouldn\'t match :first-child pseudo-class selector');
+
+ } finally {
+ iframe.parentNode.removeChild(iframe);
+ }
+ A_04_03_06_12_T01.done();
+ });
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-017.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-017.html
new file mode 100644
index 00000000000..711c8c65add
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-017.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_04_03_06_13</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#matching-insertion-points">
+<meta name="assert" content="Matching Insertion Points: A valid selector fragment may contain a :last-child pseudo-class selector">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_04_03_06_13_T01 = async_test('A_04_03_06_13_T01');
+
+
+A_04_03_06_13_T01.step(function () {
+ var iframe = document.createElement('iframe');
+ iframe.src = '../../resources/bobs_page.html';
+ document.body.appendChild(iframe);
+
+ iframe.onload = A_04_03_06_13_T01.step_func(function () {
+ try {
+
+ var d = iframe.contentDocument;
+ var ul = d.querySelector('ul.stories');
+ var s = ul.createShadowRoot();
+
+ //make shadow subtree
+ var subdiv1 = document.createElement('div');
+ subdiv1.innerHTML = '<ul><content select=":last-child"></content></ul>';
+ s.appendChild(subdiv1);
+
+ //li6 should be visible, all other not
+ assert_true(d.querySelector('#li6').offsetTop > 0,
+ 'Element should match :last-child pseudo-class selector');
+ assert_equals(d.querySelector('#li1').offsetTop, 0,
+ 'Point 1: element shouldn\'t match :last-child pseudo-class selector');
+ assert_equals(d.querySelector('#li2').offsetTop, 0,
+ 'Point 2: element shouldn\'t match :last-child pseudo-class selector');
+ assert_equals(d.querySelector('#li3').offsetTop, 0,
+ 'Point 3: element shouldn\'t match :last-child pseudo-class selector');
+ assert_equals(d.querySelector('#li4').offsetTop, 0,
+ 'Point 4: element shouldn\'t match :last-child pseudo-class selector');
+ assert_equals(d.querySelector('#li5').offsetTop, 0,
+ 'Point 5: element shouldn\'t match :last-child pseudo-class selector');
+
+ } finally {
+ iframe.parentNode.removeChild(iframe);
+ }
+ A_04_03_06_13_T01.done();
+ });
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-018.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-018.html
new file mode 100644
index 00000000000..93f991fd45e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-018.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_04_03_06_14</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#matching-insertion-points">
+<meta name="assert" content="Matching Insertion Points: A valid selector fragment may contain a :nth-last-of-type() pseudo-class selector">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_04_03_06_14_T01 = async_test('A_04_03_06_14_T01');
+
+
+A_04_03_06_14_T01.step(function () {
+ var iframe = document.createElement('iframe');
+ iframe.src = '../../resources/bobs_page.html';
+ document.body.appendChild(iframe);
+
+ iframe.onload = A_04_03_06_14_T01.step_func(function () {
+ try {
+
+ var d = iframe.contentDocument;
+ var ul = d.querySelector('ul.stories');
+ var s = ul.createShadowRoot();
+
+ //make shadow subtree
+ var subdiv1 = document.createElement('div');
+ subdiv1.innerHTML = '<ul><content select=":first-of-type"></content></ul>';
+ s.appendChild(subdiv1);
+
+ //li1 should be visible, all others not
+ assert_true(d.querySelector('#li1').offsetTop > 0,
+ 'Element should match :first-of-type pseudo-class selector');
+ assert_equals(d.querySelector('#li2').offsetTop, 0,
+ 'Point 1: element shouldn\'t match :first-of-type pseudo-class selector');
+ assert_equals(d.querySelector('#li3').offsetTop, 0,
+ 'Point 2: element shouldn\'t match :first-of-type pseudo-class selector');
+ assert_equals(d.querySelector('#li4').offsetTop, 0,
+ 'Point 3: element shouldn\'t match :first-of-type pseudo-class selector');
+ assert_equals(d.querySelector('#li5').offsetTop, 0,
+ 'Point 4: element shouldn\'t match :first-of-type pseudo-class selector');
+ assert_equals(d.querySelector('#li6').offsetTop, 0,
+ 'Point 5: element shouldn\'t match :first-of-type pseudo-class selector');
+
+ } finally {
+ iframe.parentNode.removeChild(iframe);
+ }
+ A_04_03_06_14_T01.done();
+ });
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-019.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-019.html
new file mode 100644
index 00000000000..8b7a07f5019
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-019.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_04_03_06_15</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#matching-insertion-points">
+<meta name="assert" content="Matching Insertion Points: A valid selector fragment may contain a :last-of-type pseudo-class selector">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_04_03_06_15_T01 = async_test('A_04_03_06_15_T01');
+
+
+A_04_03_06_15_T01.step(function () {
+ var iframe = document.createElement('iframe');
+ iframe.src = '../../resources/bobs_page.html';
+ document.body.appendChild(iframe);
+
+ iframe.onload = A_04_03_06_15_T01.step_func(function () {
+ try {
+
+ var d = iframe.contentDocument;
+ var ul = d.querySelector('ul.stories');
+ var s = ul.createShadowRoot();
+
+ //make shadow subtree
+ var subdiv1 = document.createElement('div');
+ subdiv1.innerHTML = '<ul><content select=":last-of-type"></content></ul>';
+ s.appendChild(subdiv1);
+
+ //li6 must be visible, all others not
+ assert_true(d.querySelector('#li6').offsetTop > 0,
+ 'Element should match :last-of-type pseudo-class selector');
+ assert_equals(d.querySelector('#li1').offsetTop, 0,
+ 'Point 1: element shouldn\'t match :last-of-type pseudo-class selector');
+ assert_equals(d.querySelector('#li2').offsetTop, 0,
+ 'Point 2: element shouldn\'t match :last-of-type pseudo-class selector');
+ assert_equals(d.querySelector('#li3').offsetTop, 0,
+ 'Point 3: element shouldn\'t match :last-of-type pseudo-class selector');
+ assert_equals(d.querySelector('#li4').offsetTop, 0,
+ 'Point 4: element shouldn\'t match :last-of-type pseudo-class selector');
+ assert_equals(d.querySelector('#li5').offsetTop, 0,
+ 'Point 5: element shouldn\'t match :last-of-type pseudo-class selector');
+
+ } finally {
+ iframe.parentNode.removeChild(iframe);
+ }
+ A_04_03_06_15_T01.done();
+ });
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-020.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-020.html
new file mode 100644
index 00000000000..15ad4e620e3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/satisfying-matching-criteria/test-020.html
@@ -0,0 +1,79 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_04_03_06_16</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#matching-insertion-points">
+<meta name="assert" content="Matching Insertion Points: A valid selector fragment may contain a :only-of-type pseudo-class selector">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_04_03_06_16_T01 = async_test('A_04_03_06_16_T01');
+
+
+A_04_03_06_16_T01.step(function () {
+ var iframe = document.createElement('iframe');
+ iframe.src = '../../resources/bobs_page.html';
+ document.body.appendChild(iframe);
+
+ iframe.onload = A_04_03_06_16_T01.step_func(function () {
+ try {
+
+ var d = iframe.contentDocument;
+ var ul = d.querySelector('ul.stories');
+ var s = ul.createShadowRoot();
+
+ //make shadow subtree
+ var subdiv1 = document.createElement('div');
+ subdiv1.innerHTML = '<ul><content select=":only-of-type"></content></ul>';
+ s.appendChild(subdiv1);
+
+ //All li1-li6 elements should be invisible
+ assert_equals(d.querySelector('#li1').offsetTop, 0,
+ 'Point 1: element shouldn\'t match :only-of-type pseudo-class selector');
+ assert_equals(d.querySelector('#li2').offsetTop, 0,
+ 'Point 2: element shouldn\'t match :only-of-type pseudo-class selector');
+ assert_equals(d.querySelector('#li3').offsetTop, 0,
+ 'Point 3: element shouldn\'t match :only-of-type pseudo-class selector');
+ assert_equals(d.querySelector('#li4').offsetTop, 0,
+ 'Point 4: element shouldn\'t match :only-of-type pseudo-class selector');
+ assert_equals(d.querySelector('#li5').offsetTop, 0,
+ 'Point 5: element shouldn\'t match :only-of-type pseudo-class selector');
+ assert_equals(d.querySelector('#li6').offsetTop, 0,
+ 'Point 6: element shouldn\'t match :only-of-type pseudo-class selector');
+
+ var s2 = d.querySelector('#divid').createShadowRoot();
+
+ //make shadow subtree
+ var subdiv2 = document.createElement('div');
+ subdiv2.innerHTML = '<content select=":only-of-type"></content>';
+ s2.appendChild(subdiv2);
+
+ //Span and ul both should be visible
+ assert_true(d.querySelector('#spandex').offsetTop > 0,
+ 'Point 7: Element should match :only-of-type pseudo-class selector');
+ assert_true(d.querySelector('#ul2').offsetTop > 0,
+ 'Point 8: Element should match :only-of-type pseudo-class selector');
+ } finally {
+ iframe.parentNode.removeChild(iframe);
+ }
+ A_04_03_06_16_T01.done();
+ });
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/shadow-root-001-ref.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/shadow-root-001-ref.html
new file mode 100644
index 00000000000..d80fcccbf39
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/shadow-root-001-ref.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: Basic shadow root (reference)</title>
+<link rel="author" title="Hayato Ito" href="mailto:hayato@google.com">
+<link rel="author" title="Yuta Kitamura" href="mailto:yutak@google.com">
+<style>
+p { color: black; }
+div { color: green; }
+</style>
+</head>
+<body>
+<p>You should see green text saying "PASS" below.</p>
+<div>PASS</div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/shadow-root-001.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/shadow-root-001.html
new file mode 100644
index 00000000000..8ab15a1ac3e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/shadow-root-001.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: Basic shadow root</title>
+<link rel="match" href="shadow-root-001-ref.html">
+<link rel="author" title="Hayato Ito" href="mailto:hayato@google.com">
+<link rel="author" title="Yuta Kitamura" href="mailto:yutak@google.com">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#shadow-trees">
+<meta name="assert" content="When a shadow root is attached, the shadow tree is rendered.">
+<script src="../testcommon.js"></script>
+<style>
+p { color: black; }
+* { color: red; }
+</style>
+</head>
+<body>
+<p>You should see green text saying "PASS" below.</p>
+<div id="host">FAIL</div>
+<script>
+var shadowRoot = window.host.createShadowRoot();
+shadowRoot.innerHTML =
+ '<style>#pass { color: green; }</style>\n' +
+ '<div id="pass">PASS</div>';
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/shadow-root-002-ref.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/shadow-root-002-ref.html
new file mode 100644
index 00000000000..77b472d7825
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/shadow-root-002-ref.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: Basic distribution (reference)</title>
+<link rel="author" title="Anna Ogawa" href="mailto:anna.ogawa.0219@gmail.com">
+<link rel="author" title="Yuta Kitamura" href="mailto:yutak@google.com">
+<style>
+p { color: black; }
+div { color: green; }
+</style>
+</head>
+<body>
+<p>
+You should see four lines of green text "A", "B", "C" and "D" below,
+in this order.
+</p>
+<div>A</div>
+<div>B</div>
+<div>C</div>
+<div>D</div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/shadow-root-002.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/shadow-root-002.html
new file mode 100644
index 00000000000..23d0cdd30a2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/shadow-root-002.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<meta charset="utf-8">
+<title>Shadow DOM Test: Basic distribution</title>
+<link rel="match" href="shadow-root-002-ref.html">
+<link rel="author" title="Anna Ogawa" href="mailto:anna.ogawa.0219@gmail.com">
+<link rel="author" title="Yuta Kitamura" href="mailto:yutak@google.com">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#shadow-trees">
+<meta name="assert" content="On distribution, content element is replaced with the shadow host's children.">
+<script src="../testcommon.js"></script>
+<style>
+p { color: black; }
+.pass { color: green; }
+* { color: red; }
+</style>
+</head>
+<body>
+<p>
+You should see four lines of green text "A", "B", "C" and "D" below,
+in this order.
+</p>
+<div id="host">
+<div class="pass">B</div>
+<div class="pass">C</div>
+</div>
+<script>
+var shadowRoot = window.host.createShadowRoot();
+
+shadowRoot.innerHTML =
+ '<style>\n' +
+ '.shadow-pass { color: green; }\n' +
+ '* { color: red; }\n' +
+ '</style>' +
+ '<div class="shadow-pass">A</div>\n' +
+ '<content>FAIL</content>' +
+ '<div class="shadow-pass">D</div>';
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/text-decoration-001-ref.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/text-decoration-001-ref.html
new file mode 100644
index 00000000000..db3eede5662
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/text-decoration-001-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Shadow DOM Test</title>
+ <link rel="author" title="Masaya Iseki" href="mailto:iseki.m.aa@gmail.com">
+ </head>
+ <body>
+ <span>
+ if NOT underlined, it is success.
+ </span>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/text-decoration-001.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/text-decoration-001.html
new file mode 100644
index 00000000000..f22c3a3854e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/text-decoration-001.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" >
+ <title>Text Decoration Under Line Test</title>
+ <link rel="match" href="text-decoration-001-ref.html">
+ <link rel="author" title="Masaya Iseki" href="mailto:iseki.m.aa@gmail.com">
+ <link rel="help" href="https://www.w3.org/TR/shadow-dom/#text-decoration-property">
+ <meta name="assert" content="When shadow host has text-decoration, shadow tree is not affected.">
+ </head>
+ <body>
+ <span id="parent" style="text-decoration: underline">
+ </span>
+ <script>
+ var parent = document.getElementById('parent');
+ var shadow = parent.webkitCreateShadowRoot();
+ var child = document.createElement('span');
+ child.textContent = "if NOT underlined, it is success.";
+ shadow.appendChild(child);
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/upper-boundary-encapsulation/dom-tree-accessors-001.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/upper-boundary-encapsulation/dom-tree-accessors-001.html
new file mode 100644
index 00000000000..c55a6091cfb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/upper-boundary-encapsulation/dom-tree-accessors-001.html
@@ -0,0 +1,225 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: Upper-boundary encapsulation: document's DOM tree accessors</title>
+<link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="author" title="Mikhail Fursov" href="mailto:mfursov@unipro.ru">
+<link rel="author" title="Yuta Kitamura" href="mailto:yutak@google.com">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#upper-boundary-encapsulation">
+<meta name="assert" content="Upper-boundary encapsulation: The shadow nodes and named shadow elements are not accessible using shadow host's document DOM tree accessors.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+// A document's "DOM tree accessors" include:
+// (document.)head, title, body, images, embeds, plugins, links, forms,
+// scripts, getElementsByName(), cssElementMap, and currentScript
+//
+// Of these, it is unclear how document.cssElementMap can be tested.
+// Except for it, there is a test corresponding to each accessor.
+//
+// Additionally, there are obsolete accessors
+// <http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#other-elements,-attributes-and-apis>:
+// (document.)anchors, applets, and all.
+//
+// and some accessors defined in the DOM specification (formerly known as
+// "DOM Core") <http://dom.spec.whatwg.org/#interface-document>:
+// (document.)documentElement, getElementsByTagName(),
+// getElementsByTagNameNS(), getElementsByClassName(), and getElementById().
+//
+// As it seems reasonable to have tests for these accessors, this file also
+// includes tests for them, except for document.documentElement which is
+// unclear whether we can test; the distribution process of Shadow DOM does not
+// alter the host element, so the document element (e.g. <html>) cannot be
+// replaced with an element in a shadow tree.
+
+// ----------------------------------------------------------------------------
+// Constants and utility functions
+
+// Place the same HTML content into both the host document and the shadow root.
+// To differentiate these two, a class name is assigned to every element by
+// populateTestContentToHostDocument() and populateTestContentToShadowRoot().
+var HTML_CONTENT = [
+ '<head>',
+ '<title></title>',
+ '<link rel="help" href="#">',
+ '</head>',
+ '<body>',
+ '<p></p>',
+ '<a name="test-name"></a>',
+ '<a href="#"></a>',
+ '<area href="#">',
+ '<img src="#" alt="">',
+ '<embed></embed>',
+ '<form></form>',
+ '<script><' + '/script>',
+ '<applet></applet>',
+ '</body>'
+].join('\n');
+
+function addClassNameToAllElements(document, root, className) {
+ var nodeIterator = document.createNodeIterator(
+ root, NodeFilter.SHOW_ELEMENT, null);
+ var node;
+ while (node = nodeIterator.nextNode())
+ node.className = className;
+}
+
+function populateTestContentToHostDocument(document) {
+ document.documentElement.innerHTML = HTML_CONTENT;
+ addClassNameToAllElements(document, document.documentElement, 'host');
+}
+
+function populateTestContentToShadowRoot(shadowRoot) {
+ shadowRoot.innerHTML = HTML_CONTENT;
+ addClassNameToAllElements(shadowRoot.ownerDocument, shadowRoot, 'shadow');
+}
+
+function createDocumentForTesting() {
+ var doc = document.implementation.createHTMLDocument('');
+ populateTestContentToHostDocument(doc);
+ var shadowRoot = doc.documentElement.createShadowRoot();
+ populateTestContentToShadowRoot(shadowRoot);
+ return doc;
+}
+
+// Make sure the given HTMLCollection contains at least one elements and
+// all elements have the class named "host". This function works well with
+// HTMLCollection, HTMLAllCollection, and NodeList consisting of elements.
+function assert_collection(collection) {
+ assert_true(collection.length > 0);
+ Array.prototype.forEach.call(collection, function (element) {
+ assert_equals(element.className, 'host');
+ });
+}
+
+// ----------------------------------------------------------------------------
+// Tests for DOM tree accessors defined in HTML specification
+
+test(function () {
+ var doc = createDocumentForTesting();
+ assert_equals(doc.head.className, 'host');
+ assert_equals(doc.body.className, 'host');
+},
+ '<head> and <body> in a shadow tree should not be accessible from ' +
+ 'owner document\'s "head" and "body" properties, respectively.'
+);
+
+test(function () {
+ var doc = document.implementation.createHTMLDocument('');
+ populateTestContentToHostDocument(doc);
+ var shadowRoot = doc.documentElement.createShadowRoot();
+ populateTestContentToShadowRoot(shadowRoot);
+
+ // Replace the content of <title> to distinguish elements in a host
+ // document and a shadow tree.
+ doc.getElementsByTagName('title')[0].innerText = 'Title of host document';
+ shadowRoot.getElementsByTagName('title')[0].innerText =
+ 'Title of shadow tree';
+
+ assert_equals(doc.title, 'Title of host document');
+},
+ 'The content of title element in a shadow tree should not be accessible ' +
+ 'from owner document\'s "title" attribute.'
+);
+
+function testHTMLCollection(accessor) {
+ var doc = createDocumentForTesting();
+ assert_collection(doc[accessor]);
+}
+
+generate_tests(
+ testHTMLCollection,
+ ['images', 'embeds', 'plugins', 'links', 'forms', 'scripts'].map(
+ function (accessor) {
+ return [
+ 'Elements in a shadow tree should not be accessible from ' +
+ 'owner document\'s "' + accessor + '" attribute.',
+ accessor
+ ];
+ }));
+
+test(function () {
+ var doc = createDocumentForTesting();
+ assert_collection(doc.getElementsByName('test-name'));
+},
+ 'Elements in a shadow tree should not be accessible from owner ' +
+ 'document\'s getElementsByName() method.'
+);
+
+// ----------------------------------------------------------------------------
+// Tests for obsolete accessors
+
+generate_tests(
+ testHTMLCollection,
+ ['anchors', 'applets', 'all'].map(
+ function (accessor) {
+ return [
+ 'Elements in a shadow tree should not be accessible from ' +
+ 'owner document\'s "' + accessor + '" attribute.',
+ accessor
+ ];
+ }));
+
+// ----------------------------------------------------------------------------
+// Tests for accessors defined in DOM specification
+
+test(function () {
+ var doc = createDocumentForTesting();
+ assert_collection(doc.getElementsByTagName('p'));
+},
+ 'Elements in a shadow tree should not be accessible from owner ' +
+ 'document\'s getElementsByTagName() method.'
+);
+
+test(function () {
+ // Create a XML document.
+ var namespace = 'http://www.w3.org/1999/xhtml';
+ var doc = document.implementation.createDocument(namespace, 'html');
+ doc.documentElement.appendChild(doc.createElementNS(namespace, 'head'));
+ var body = doc.createElementNS(namespace, 'body');
+ var pHost = doc.createElementNS(namespace, 'p');
+ pHost.className = "host";
+ body.appendChild(pHost);
+ doc.documentElement.appendChild(body);
+
+ var shadowRoot = body.createShadowRoot();
+ var pShadow = doc.createElementNS(namespace, 'p');
+ pShadow.className = "shadow";
+ shadowRoot.appendChild(pShadow);
+
+ assert_collection(doc.getElementsByTagNameNS(namespace, 'p'));
+},
+ 'Elements in a shadow tree should not be accessible from owner ' +
+ 'document\'s getElementsByTagNameNS() method.'
+);
+
+test(function () {
+ var doc = document.implementation.createHTMLDocument('');
+ populateTestContentToHostDocument(doc);
+ var shadowRoot = doc.documentElement.createShadowRoot();
+ populateTestContentToShadowRoot(shadowRoot);
+
+ shadowRoot.getElementsByTagName('p')[0].id = 'test-id';
+ assert_equals(doc.getElementById('test-id'), null);
+},
+ 'Elements in a shadow tree should not be accessible from owner ' +
+ 'document\'s getElementById() method.'
+);
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/upper-boundary-encapsulation/dom-tree-accessors-002.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/upper-boundary-encapsulation/dom-tree-accessors-002.html
new file mode 100644
index 00000000000..747ae6749b4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/upper-boundary-encapsulation/dom-tree-accessors-002.html
@@ -0,0 +1,92 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: Upper-boundary encapsulation: shadow root's DOM tree accessors</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="author" title="Mikhail Fursov" href="mailto:mfursov@unipro.ru">
+<link rel="author" title="Yuta Kitamura" href="mailto:yutak@google.com">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#upper-boundary-encapsulation">
+<meta name="assert" content="Upper-boundary encapsulation: The nodes are accessible using shadow root's DOM tree accessor methods.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+function assert_singleton_node_list(nodeList, expectedNode) {
+ assert_equals(nodeList.length, 1);
+ assert_equals(nodeList[0], expectedNode);
+}
+
+test(function () {
+ var doc = document.implementation.createHTMLDocument('Test');
+ var shadowRoot = doc.body.createShadowRoot();
+ var image = doc.createElement('img');
+ shadowRoot.appendChild(image);
+
+ assert_singleton_node_list(shadowRoot.getElementsByTagName('img'), image);
+},
+ 'Elements in a shadow tree should be accessible via shadow root\'s ' +
+ 'getElementsByTagName() DOM tree accessor.'
+);
+
+test(function () {
+ var namespace = 'http://www.w3.org/1999/xhtml';
+ var doc = document.implementation.createDocument(namespace, 'html');
+ doc.documentElement.appendChild(doc.createElementNS(namespace, 'head'));
+ var body = doc.createElementNS(namespace, 'body');
+ var imageHost = doc.createElementNS(namespace, 'img');
+ body.appendChild(imageHost);
+ doc.documentElement.appendChild(body);
+
+ var shadowRoot = body.createShadowRoot();
+ var imageShadow = doc.createElementNS(namespace, 'img');
+ shadowRoot.appendChild(imageShadow);
+
+ assert_singleton_node_list(
+ shadowRoot.getElementsByTagNameNS(namespace, 'img'), imageShadow);
+},
+ 'Elements in a shadow tree should be accessible via shadow root\'s ' +
+ 'getElementsByTagNameNS() DOM tree accessor.'
+);
+
+test(function () {
+ var doc = document.implementation.createHTMLDocument('Test');
+ var shadowRoot = doc.body.createShadowRoot();
+ var div = doc.createElement('div');
+ div.className = 'div-class';
+ shadowRoot.appendChild(div);
+
+ assert_singleton_node_list(
+ shadowRoot.getElementsByClassName('div-class'), div);
+},
+ 'Elements in a shadow tree should be accessible via shadow root\'s ' +
+ 'getElementsByClassName() DOM tree accessor.'
+);
+
+test(function () {
+ var doc = document.implementation.createHTMLDocument('Test');
+ var shadowRoot = doc.body.createShadowRoot();
+ var div = doc.createElement('div');
+ div.id = 'div-id';
+ shadowRoot.appendChild(div);
+
+ assert_equals(shadowRoot.getElementById('div-id'), div);
+},
+ 'Elements in a shadow tree should be accessible via shadow root\'s ' +
+ 'getElementById() DOM tree accessor.'
+);
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/upper-boundary-encapsulation/ownerdocument-001.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/upper-boundary-encapsulation/ownerdocument-001.html
new file mode 100644
index 00000000000..69eb0325af5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/upper-boundary-encapsulation/ownerdocument-001.html
@@ -0,0 +1,109 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: Upper-boundary encapsuration on ownerDocument: basic tests</title>
+<link rel="author" title="Aleksei Yu. Semenov" href="mailto:sgrekhov@unipro.ru">
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="author" title="Mikhail Fursov" href="mailto:mfursov@unipro.ru">
+<link rel="author" title="Yuta Kitamura" href="mailto:yutak@google.com">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#upper-boundary-encapsulation">
+<meta name="assert" content="Upper-boundary encapsulation: The ownerDocument property of all nodes in shadow tree refers to the document of the shadow host.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function () {
+ var doc = document.implementation.createHTMLDocument('Test');
+ doc.body.innerHTML = '<div>A<div>B</div>C<div><span>D</span></div>E</div>';
+ var nodeIterator = doc.createNodeIterator(doc.documentElement,
+ NodeFilter.SHOW_ELEMENT, null);
+ var node;
+ while (node = nodeIterator.nextNode()) {
+ var shadowRoot = node.createShadowRoot();
+ assert_equals(shadowRoot.ownerDocument, doc);
+ }
+}, 'ownerDocument property of a shadow root should be the document of the ' +
+ 'shadow host, regardless of the location of the shadow host.');
+
+test(function () {
+ var MAX_DEPTH = 16;
+ var doc = document.implementation.createHTMLDocument('Test');
+ var tail = doc.body;
+ for (var depth = 1; depth <= MAX_DEPTH; ++depth) {
+ var div = doc.createElement('div');
+ div.id = 'depth-' + depth;
+ tail.appendChild(div);
+ tail = div;
+ }
+
+ for (var depth = 1; depth <= MAX_DEPTH; ++depth) {
+ var host = doc.getElementById('depth-' + depth);
+ var shadowRoot = host.createShadowRoot();
+ assert_equals(shadowRoot.ownerDocument, doc,
+ 'ownerDocument mismatch for #depth-' + depth);
+ }
+}, 'ownerDocument property of elements in a shadow tree should match ' +
+ 'the document of the shadow host, regardless of the element\'s location ' +
+ 'in a shadow tree.');
+
+test(function () {
+ var doc = document.implementation.createHTMLDocument('Test');
+ var shadowRoot = doc.body.createShadowRoot();
+ var div = doc.createElement('div');
+ shadowRoot.appendChild(div);
+ assert_equals(div.ownerDocument, doc);
+}, 'Elements added to a shadow tree should automatically get a valid ' +
+ 'ownerDocument.');
+
+test(function () {
+ var doc1 = document.implementation.createHTMLDocument('Test 1');
+ var doc2 = document.implementation.createHTMLDocument('Test 2');
+ var shadowRoot = doc1.body.createShadowRoot();
+ var div = doc2.createElement('div');
+ shadowRoot.appendChild(div);
+ assert_equals(div.ownerDocument, doc1);
+}, 'ownerDocument property of an element in a shadow tree should be the ' +
+ 'document of the shadow host, even if the host element is created from ' +
+ 'another document.');
+
+test(function () {
+ var doc1 = document.implementation.createHTMLDocument('Test 1');
+ var doc2 = document.implementation.createHTMLDocument('Test 2');
+ var shadowRoot = doc1.body.createShadowRoot();
+ doc2.body.innerHTML =
+ '<div id="root">A<div>B</div>C<div><span>D</span></div>E</div>';
+ shadowRoot.appendChild(doc2.getElementById('root'));
+ var nodeIterator = doc1.createNodeIterator(
+ shadowRoot.getElementById('root'), 0xFFFFFFFF, null);
+ var node;
+ while (node = nodeIterator.nextNode()) {
+ assert_equals(node.ownerDocument, doc1);
+ }
+}, 'All children nodes of a shadow root get a valid ownerDocument when ' +
+ 'added to a shadow tree.');
+
+test(function () {
+ var doc1 = document.implementation.createHTMLDocument('Test 1');
+ var doc2 = document.implementation.createHTMLDocument('Test 2');
+ var shadowRoot = doc1.body.createShadowRoot();
+ doc2.body.innerHTML = '<div id="parent"><div id="child"></div></div>';
+ shadowRoot.appendChild(doc2.getElementById('child'));
+ assert_equals(doc2.getElementById('parent').ownerDocument, doc2);
+}, 'ownerDocument property of a node should remain the same, even if its ' +
+ 'child is adopted into a shadow tree.');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/upper-boundary-encapsulation/ownerdocument-002.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/upper-boundary-encapsulation/ownerdocument-002.html
new file mode 100644
index 00000000000..291b8c89383
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/upper-boundary-encapsulation/ownerdocument-002.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: Upper-boundary encapsuration on ownerDocument: with all HTML5 elements</title>
+<link rel="author" title="Aleksei Yu. Semenov" href="mailto:sgrekhov@unipro.ru">
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="author" title="Mikhail Fursov" href="mailto:mfursov@unipro.ru">
+<link rel="author" title="Yuta Kitamura" href="mailto:yutak@google.com">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#upper-boundary-encapsulation">
+<meta name="assert" content="Upper-boundary encapsulation: The ownerDocument property of all nodes in shadow tree refers to the document of the shadow host.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+function testElement(elementName) {
+ var doc = document.implementation.createHTMLDocument('Test');
+ var element = doc.createElement(elementName);
+ doc.body.appendChild(element);
+ var shadowRoot = element.createShadowRoot();
+ HTML5_ELEMENT_NAMES.forEach(function (name) {
+ shadowRoot.appendChild(doc.createElement(name));
+ });
+
+ var iterator = doc.createNodeIterator(shadowRoot, 0xFFFFFFFF, null);
+ var node;
+ while (node = iterator.nextNode()) {
+ assert_equals(node.ownerDocument, doc);
+ }
+}
+
+var testParameters = HTML5_ELEMENT_NAMES.map(function (name) {
+ return [
+ 'ownerDocument property of any elements in a shadow tree should ' +
+ 'match the document of the shadow host, when the host is a "' +
+ name + '" element.',
+ name
+ ];
+});
+
+generate_tests(testElement, testParameters);
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/upper-boundary-encapsulation/selectors-api-001.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/upper-boundary-encapsulation/selectors-api-001.html
new file mode 100644
index 00000000000..5cb990df71c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/upper-boundary-encapsulation/selectors-api-001.html
@@ -0,0 +1,81 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: Upper-boundary encapsulation: document's Selector APIs</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="author" title="Yuta Kitamura" href="mailto:yutak@google.com">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#upper-boundary-encapsulation">
+<meta name="assert" content="Upper-boundary encapsulation: Nodes in a shadow tree must not be accessible through selector APIs of owner document.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+// Return a document containing the structure below:
+//
+// <body> - - - - - {shadow-root}
+// | |
+// | +-- <p class="test-class" id="test-id">
+// |
+// +-- <p class="test-class" id="test-id">
+function createTestDocument() {
+ var doc = document.implementation.createHTMLDocument('Test');
+ var pHost = doc.createElement('p');
+ pHost.className = 'test-class';
+ pHost.id = 'test-id';
+ doc.body.appendChild(pHost);
+ var shadowRoot = doc.body.createShadowRoot();
+ var pShadow = doc.createElement('p');
+ pShadow.className = 'test-class';
+ pShadow.id = 'test-id';
+ shadowRoot.appendChild(pShadow);
+ return {
+ doc: doc,
+ pHost: pHost,
+ pShadow: pShadow
+ };
+}
+
+test(function () {
+ var documentObject = createTestDocument();
+ var doc = documentObject.doc;
+ var pHost = documentObject.pHost;
+ assert_equals(doc.querySelector('p'), pHost);
+ assert_equals(doc.querySelector('.test-class'), pHost);
+ assert_equals(doc.querySelector('#test-id'), pHost);
+},
+ 'Elements in a shadow tree should not be accessible from ' +
+ 'owner document\'s querySelector() method.'
+);
+
+function assert_singleton_node_list(nodeList, expectedNode) {
+ assert_equals(nodeList.length, 1);
+ assert_equals(nodeList[0], expectedNode);
+}
+
+test(function () {
+ var documentObject = createTestDocument();
+ var doc = documentObject.doc;
+ var pHost = documentObject.pHost;
+ assert_singleton_node_list(doc.querySelectorAll('p'), pHost);
+ assert_singleton_node_list(doc.querySelectorAll('.test-class'), pHost);
+ assert_singleton_node_list(doc.querySelectorAll('#test-id'), pHost);
+},
+ 'Elements in a shadow tree should not be accessible from ' +
+ 'owner document\'s querySelectorAll() method.'
+);
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/upper-boundary-encapsulation/selectors-api-002.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/upper-boundary-encapsulation/selectors-api-002.html
new file mode 100644
index 00000000000..06f553ac35e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/upper-boundary-encapsulation/selectors-api-002.html
@@ -0,0 +1,85 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: Upper-boundary encapsulation: shadow root's Selector APIs</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="author" title="Mikhail Fursov" href="mailto:mfursov@unipro.ru">
+<link rel="author" title="Yuta Kitamura" href="mailto:yutak@google.com">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#upper-boundary-encapsulation">
+<meta name="assert" content="Upper-boundary encapsulation: Nodes in a shadow tree must be accessible through selector APIs of the shadow root.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+// Return a document containing the structure below:
+//
+// <body> - - - - - {shadow-root}
+// | |
+// | +-- <p class="test-class" id="test-id">
+// |
+// +-- <p class="test-class" id="test-id">
+function createTestDocument() {
+ var doc = document.implementation.createHTMLDocument('Test');
+ var pHost = doc.createElement('p');
+ pHost.className = 'test-class';
+ pHost.id = 'test-id';
+ doc.body.appendChild(pHost);
+ var shadowRoot = doc.body.createShadowRoot();
+ var pShadow = doc.createElement('p');
+ pShadow.className = 'test-class';
+ pShadow.id = 'test-id';
+ shadowRoot.appendChild(pShadow);
+ return {
+ doc: doc,
+ shadowRoot: shadowRoot,
+ pHost: pHost,
+ pShadow: pShadow
+ };
+}
+
+test(function () {
+ var documentObject = createTestDocument();
+ var shadowRoot = documentObject.shadowRoot;
+ var pShadow = documentObject.pShadow;
+ assert_equals(shadowRoot.querySelector('p'), pShadow);
+ assert_equals(shadowRoot.querySelector('.test-class'), pShadow);
+ assert_equals(shadowRoot.querySelector('#test-id'), pShadow);
+},
+ 'Elements in a shadow tree should be accessible from ' +
+ 'shadow root\'s querySelector() method.'
+);
+
+function assert_singleton_node_list(nodeList, expectedNode) {
+ assert_equals(nodeList.length, 1);
+ assert_equals(nodeList[0], expectedNode);
+}
+
+test(function () {
+ var documentObject = createTestDocument();
+ var shadowRoot = documentObject.shadowRoot;
+ var pShadow = documentObject.pShadow;
+ assert_singleton_node_list(shadowRoot.querySelectorAll('p'), pShadow);
+ assert_singleton_node_list(shadowRoot.querySelectorAll('.test-class'),
+ pShadow);
+ assert_singleton_node_list(shadowRoot.querySelectorAll('#test-id'),
+ pShadow);
+},
+ 'Elements in a shadow tree should be accessible from ' +
+ 'shadow root\'s querySelectorAll() method.'
+);
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/upper-boundary-encapsulation/shadow-root-001.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/upper-boundary-encapsulation/shadow-root-001.html
new file mode 100644
index 00000000000..4110efcddaf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/upper-boundary-encapsulation/shadow-root-001.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: Shadow root's parentNode() and parentElement()</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="author" title="Mikhail Fursov" href="mailto:mfursov@unipro.ru">
+<link rel="author" title="Yuta Kitamura" href="mailto:yutak@google.com">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#upper-boundary-encapsulation">
+<meta name="assert" content="Upper-boundary encapsulation: The parentNode and parentElement attributes of the shadow root object must always return null.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function () {
+ var doc = document.implementation.createHTMLDocument('Test');
+ var shadowRoot = doc.body.createShadowRoot();
+ assert_equals(shadowRoot.parentNode, null);
+}, 'The parentNode attribute of a shadow root must always return null.');
+
+test(function () {
+ var doc = document.implementation.createHTMLDocument('Test');
+ var shadowRoot = doc.body.createShadowRoot();
+ assert_equals(shadowRoot.parentElement, null);
+}, 'The parentElement attribute of a shadow root must always return null.');
+
+test(function () {
+ var doc = document.implementation.createHTMLDocument('Test');
+ var outerShadowRoot = doc.body.createShadowRoot();
+ var div = doc.createElement('div');
+ outerShadowRoot.appendChild(div);
+ var innerShadowRoot = div.createShadowRoot();
+ assert_equals(innerShadowRoot.parentNode, null);
+},
+ 'The parentNode attribute of a shadow root must always return null, ' +
+ 'even if the shadow root is nested inside another shadow root.'
+);
+
+test(function () {
+ var doc = document.implementation.createHTMLDocument('Test');
+ var outerShadowRoot = doc.body.createShadowRoot();
+ var div = doc.createElement('div');
+ outerShadowRoot.appendChild(div);
+ var innerShadowRoot = div.createShadowRoot();
+ assert_equals(innerShadowRoot.parentElement, null);
+},
+ 'The parentElement attribute of a shadow root must always return null, ' +
+ 'even if the shadow root is nested inside another shadow root.'
+);
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/upper-boundary-encapsulation/test-005.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/upper-boundary-encapsulation/test-005.html
new file mode 100644
index 00000000000..574a983058c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/upper-boundary-encapsulation/test-005.html
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_04_01_05</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#upper-boundary-encapsulation">
+<meta name="assert" content="Upper-boundary encapsulation:The nodes with a unique id and named elements are not addressable from any attributes of elements in shadow host's document">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+// check label.for attribute
+test(function () {
+ var d = newHTMLDocument();
+ var div = d.createElement('div');
+ d.body.appendChild(div);
+ var s = div.createShadowRoot();
+
+ // node in shadow with id
+ var input = d.createElement('input');
+ input.setAttribute('type', 'text');
+ input.setAttribute('id', 'input_id');
+ d.body.appendChild(input);
+ s.appendChild(input);
+
+ // node in host with a reference to host element with id
+ var label = d.createElement('label');
+ label.setAttribute('for', 'input_id');
+ d.body.appendChild(label);
+
+ assert_equals(label.control, null, 'Elements in shadow DOM must not be accessible from ' +
+ 'owner\'s document label.for attribute');
+
+}, 'A_04_01_05_T01');
+
+// check form associated elements
+test(function () {
+
+ HTML5_FORM_ASSOCIATED_ELEMENTS.forEach(function (tagName) {
+ var d = newHTMLDocument();
+ var div = d.createElement('div');
+ d.body.appendChild(div);
+ var s = div.createShadowRoot();
+
+ var form = d.createElement('form');
+ form.setAttribute('id', 'form_id');
+ d.body.appendChild(form);
+
+ var el = d.createElement(tagName);
+ el.setAttribute('form', 'form_id');
+ d.body.appendChild(el);
+
+ s.appendChild(form);
+
+ assert_equals(el.form, null, 'Elements in shadow DOM must not be accessible from ' +
+ 'owner\'s document ' + tagName + '.form attribute');
+ });
+}, 'A_04_01_05_T02');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/upper-boundary-encapsulation/test-007.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/upper-boundary-encapsulation/test-007.html
new file mode 100644
index 00000000000..2145374ef41
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/upper-boundary-encapsulation/test-007.html
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_04_01_07</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#upper-boundary-encapsulation">
+<meta name="assert" content="Upper-boundary encapsulation:The nodes with a unique id and named elements are addressable from any attributes of elements in the same shadow DOM subtree">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+// check for label.control
+test(function () {
+ var d = newHTMLDocument();
+ var div = d.createElement('div');
+ d.body.appendChild(div);
+ var s = div.createShadowRoot();
+
+ var input = d.createElement('input');
+ input.setAttribute('type', 'text');
+ input.setAttribute('id', 'input_id');
+ d.body.appendChild(input);
+
+ var label = d.createElement('label');
+ label.setAttribute('for', 'input_id');
+ s.appendChild(label);
+ s.appendChild(input);
+
+ assert_equals(label.control, input, 'Elements in shadow DOM must be accessible from ' +
+ 'shadow document label.for attribute');
+
+}, 'A_04_01_07_T01');
+
+// check for elem.form associated elements
+test(function () {
+
+ HTML5_FORM_ASSOCIATED_ELEMENTS.forEach(function (tagName) {
+ d = newHTMLDocument();
+
+ var form = d.createElement('form');
+ var el = d.createElement(tagName);
+
+ d.body.appendChild(form);
+ d.body.appendChild(el);
+
+ form.setAttribute('id', 'form_id');
+ el.setAttribute('form', 'form_id');
+
+ div = d.createElement('div');
+ d.body.appendChild(div);
+
+ var s = div.createShadowRoot();
+ s.appendChild(form);
+ s.appendChild(el);
+
+ assert_equals(el.form, form, 'Elements in shadow DOM must be accessible from ' +
+ 'shadow document ' + tagName + '.form attribute');
+ });
+}, 'A_04_01_07_T02');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/upper-boundary-encapsulation/test-009.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/upper-boundary-encapsulation/test-009.html
new file mode 100644
index 00000000000..10260da9ab3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/upper-boundary-encapsulation/test-009.html
@@ -0,0 +1,285 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_04_01_09</title>
+<link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="author" title="Mikhail Fursov" href="mailto:mfursov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#upper-boundary-encapsulation">
+<meta name="assert" content="Upper-boundary encapsulation: no nodes other than shadow root descendants are accessible with shadow root DOM tree accessor methods">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_04_01_09 = new Object();
+
+A_04_01_09.setupBlock = function (ctx, prefix, root) {
+ // create <div id='prefix+_id1' class='cls'><p class='cls'><div id='prefix+_id2' class='cls'></div></p></div> like structure
+ // where <p> will be used as shadow host element
+
+ ctx[prefix + '_div1'] = ctx.d.createElement('div');
+ ctx[prefix + '_div1'].setAttribute('id', prefix + '_id1');
+ ctx[prefix + '_div1'].setAttribute('class', 'cls');
+
+ ctx[prefix + '_p1'] = ctx.d.createElement('p');
+ ctx[prefix + '_p1'].setAttribute('class', 'cls');
+ ctx[prefix + '_p1'].setAttribute('test', 'A_04_01_09');
+
+ ctx[prefix + '_div2'] = ctx.d.createElement('div');
+ ctx[prefix + '_div2'].setAttribute('id', prefix + '_id2');
+ ctx[prefix + '_div2'].setAttribute('class', 'cls');
+ ctx[prefix + '_div2'].setAttribute('test', 'A_04_01_09');
+
+ root.appendChild(ctx[prefix + '_div1']);
+ ctx[prefix + '_div1'].appendChild(ctx[prefix + '_p1']);
+ ctx[prefix + '_p1'].appendChild(ctx[prefix + '_div2']);
+};
+
+A_04_01_09.setup = function () {
+ var ctx = {};
+
+ ctx.d = newHTMLDocument();
+ A_04_01_09.setupBlock(ctx, 'd', ctx.d.body);
+
+ ctx.s1 = ctx.d_p1.createShadowRoot();
+ A_04_01_09.setupBlock(ctx, 's1', ctx.s1);
+
+ ctx.s2 = ctx.s1_p1.createShadowRoot();
+ A_04_01_09.setupBlock(ctx, 's2', ctx.s2);
+
+ assert_true(ctx.d_div1 != null, 'setup:d_div1');
+ assert_true(ctx.d_div2 != null, 'setup:d_div2');
+ assert_true(ctx.s1_div1 != null, 'setup: s1_div1');
+ assert_true(ctx.s1_div2 != null, 'setup: s1_div2');
+ assert_true(ctx.s2_div1 != null, 'setup: s2_div1');
+ assert_true(ctx.s2_div2 != null, 'setup: s2_div2');
+
+ return ctx;
+};
+
+//check getElementsByTagName
+test(function () {
+ var ctx = A_04_01_09.setup();
+
+ assert_nodelist_contents_equal_noorder(
+ ctx.s1.getElementsByTagName('div'), [ctx.s1_div1, ctx.s1_div2],
+ 'nodes, other than shadow root descendants, should not be accessible with ' +
+ 'ShadowRoot.getElementsByTagName (s1)');
+
+ assert_nodelist_contents_equal_noorder(
+ ctx.s2.getElementsByTagName('div'), [ctx.s2_div1, ctx.s2_div2],
+ 'nodes, other than shadow root descendants, should not be accessible with ' +
+ 'ShadowRoot.getElementsByTagName (s2)');
+
+}, 'A_04_01_09_T01');
+
+// getElementsByTagNameNS
+test(function () {
+ var ctx = A_04_01_09.setup();
+
+ assert_nodelist_contents_equal_noorder(
+ ctx.s1.getElementsByTagNameNS('*', 'div'), [ctx.s1_div1, ctx.s1_div2],
+ 'nodes, other than shadow root descendants, should not be accessible with ' +
+ 'ShadowRoot.getElementsByTagNameNS (s1)');
+
+ assert_nodelist_contents_equal_noorder(
+ ctx.s2.getElementsByTagNameNS('*', 'div'), [ctx.s2_div1, ctx.s2_div2],
+ 'nodes, other than shadow root descendants, should not be accessible with ' +
+ 'ShadowRoot.getElementsByTagNameNS (s2)');
+
+}, 'A_04_01_09_T02');
+
+//check getElementsByClassName
+test(function () {
+ var ctx = A_04_01_09.setup();
+
+ assert_nodelist_contents_equal_noorder(
+ ctx.s1.getElementsByClassName('cls'), [ctx.s1_div1, ctx.s1_p1, ctx.s1_div2],
+ 'nodes, other than shadow root descendants, should not be accessible with ' +
+ 'ShadowRoot.getElementsByClassName (s1)');
+
+ assert_nodelist_contents_equal_noorder(
+ ctx.s2.getElementsByClassName('cls'), [ctx.s2_div1, ctx.s2_p1, ctx.s2_div2],
+ 'nodes, other than shadow root descendants, should not be accessible with ' +
+ 'ShadowRoot.getElementsByClassName (s2)');
+
+}, 'A_04_01_09_T03');
+
+// check getElementById
+test(function () {
+ var ctx = A_04_01_09.setup();
+
+ assert_equals(ctx.s1.getElementById('d_id1'), null, 'Expected no access to d_div1 from s1.getElementById()');
+ assert_equals(ctx.s1.getElementById('d_id2'), null, 'Expected no access to d_div2 from s1.getElementById()');
+ assert_equals(ctx.s2.getElementById('d_id1'), null, 'Expected no access to d_div1 from s2.getElementById()');
+ assert_equals(ctx.s2.getElementById('d_id2'), null, 'Expected no access to d_div1 from s2.getElementById()');
+
+
+ assert_equals(ctx.s1.getElementById('s1_id1'), ctx.s1_div1, 'Expected access to s1_div1 form s1.getElementById()');
+ assert_equals(ctx.s1.getElementById('s1_id2'), ctx.s1_div2, 'Expected access to s1_div2 form s1.getElementById()');
+ assert_equals(ctx.s2.getElementById('s2_id1'), ctx.s2_div1, 'Expected access to s2_div1 form s2.getElementById()');
+ assert_equals(ctx.s2.getElementById('s2_id2'), ctx.s2_div2, 'Expected access to s2_div2 form s2.getElementById()');
+
+
+ assert_equals(ctx.s1.getElementById('s2_id1'), null, 'Expected no access to s2_div1 form s1.getElementById()');
+ assert_equals(ctx.s1.getElementById('s2_id2'), null, 'Expected no access to s2_div2 form s1.getElementById()');
+ assert_equals(ctx.s2.getElementById('s1_id1'), null, 'Expected no access to s1_div1 form s2.getElementById()');
+ assert_equals(ctx.s2.getElementById('s1_id2'), null, 'Expected no access to s1_div2 form s2.getElementById()');
+
+}, 'A_04_01_09_T04');
+
+
+// check querySelector for id
+test(function () {
+ var ctx = A_04_01_09.setup();
+
+ assert_equals(ctx.d.querySelector('#s1_id1'), null, 'Expected no access to s1_div1 from d.querySelector()');
+ assert_equals(ctx.d.querySelector('#s1_id2'), null, 'Expected no access to s1_div2 from d.querySelector()');
+ assert_equals(ctx.d.querySelector('#s2_id1'), null, 'Expected no access to s2_div1 from d.querySelector()');
+ assert_equals(ctx.d.querySelector('#s2_id2'), null, 'Expected no access to s2_div1 from d.querySelector()');
+
+ assert_equals(ctx.s1.querySelector('#d_id1'), null, 'Expected no access to d_div1 from s1.querySelector()');
+ assert_equals(ctx.s1.querySelector('#d_id2'), null, 'Expected no access to d_div2 from s1.querySelector()');
+ assert_equals(ctx.s2.querySelector('#d_id1'), null, 'Expected no access to d_div1 from s2.querySelector()');
+ assert_equals(ctx.s2.querySelector('#d_id2'), null, 'Expected no access to d_div1 from s2.querySelector()');
+
+ assert_equals(ctx.d.querySelector('#d_id1'), ctx.d_div1, 'Expected access to d_div1 form d.querySelector()');
+ assert_equals(ctx.d.querySelector('#d_id2'), ctx.d_div2, 'Expected access to d_div2 form d.querySelector()');
+ assert_equals(ctx.s1.querySelector('#s1_id1'), ctx.s1_div1, 'Expected access to s1_div1 form s1.querySelector()');
+ assert_equals(ctx.s1.querySelector('#s1_id2'), ctx.s1_div2, 'Expected access to s1_div2 form s1.querySelector()');
+ assert_equals(ctx.s2.querySelector('#s2_id1'), ctx.s2_div1, 'Expected access to s2_div1 form s2.querySelector()');
+ assert_equals(ctx.s2.querySelector('#s2_id2'), ctx.s2_div2, 'Expected access to s2_div2 form s2.querySelector()');
+
+ assert_equals(ctx.s1.querySelector('#s2_id1'), null, 'Expected no access to s2_div1 form s1.querySelector()');
+ assert_equals(ctx.s1.querySelector('#s2_id2'), null, 'Expected no access to s2_div2 form s1.querySelector()');
+ assert_equals(ctx.s2.querySelector('#s1_id1'), null, 'Expected no access to s1_div1 form s2.querySelector()');
+ assert_equals(ctx.s2.querySelector('#s1_id2'), null, 'Expected no access to s1_div2 form s2.querySelector()');
+
+}, 'A_04_01_09_T05');
+
+
+//check querySelector for element
+test(function () {
+ var ctx = A_04_01_09.setup();
+
+ assert_equals(ctx.d.querySelector('p'), ctx.d_p1, 'Expected access to d_p1 from d.querySelector()');
+ assert_equals(ctx.s1.querySelector('p'), ctx.s1_p1, 'Expected access to s1_p1 from s1.querySelector()');
+ assert_equals(ctx.s2.querySelector('p'), ctx.s2_p1, 'Expected access to s2_p1 from s2.querySelector()');
+
+}, 'A_04_01_09_T06');
+
+// check querySelectorAll for element
+test(function () {
+ var ctx = A_04_01_09.setup();
+
+ assert_nodelist_contents_equal_noorder(ctx.d.querySelectorAll('p'), [ctx.d_p1], 'Expected access to d_p1 from d.querySelectorAll()');
+ assert_nodelist_contents_equal_noorder(ctx.s1.querySelectorAll('p'), [ctx.s1_p1], 'Expected access to s1_p1 s1.querySelectorAll');
+ assert_nodelist_contents_equal_noorder(ctx.s2.querySelectorAll('p'), [ctx.s2_p1], 'Expected access to s2_p1 from s2.querySelectorAll');
+
+}, 'A_04_01_09_T07');
+
+// check querySelectorAll for class
+test(function () {
+ var ctx = A_04_01_09.setup();
+
+ assert_nodelist_contents_equal_noorder(ctx.d.querySelectorAll('.cls'), [ctx.d_div1, ctx.d_p1, ctx.d_div2], 'd.querySelectorAll() return wrong result');
+ assert_nodelist_contents_equal_noorder(ctx.s1.querySelectorAll('.cls'), [ctx.s1_div1, ctx.s1_p1, ctx.s1_div2], 's1.querySelectorAll() return wrong result');
+ assert_nodelist_contents_equal_noorder(ctx.s2.querySelectorAll('.cls'), [ctx.s2_div1, ctx.s2_p1, ctx.s2_div2], 's2.querySelectorAll() return wrong result');
+
+}, 'A_04_01_09_T08');
+
+//check querySelectorAll with whildcat
+test(function () {
+ var ctx = A_04_01_09.setup();
+
+ //assert_nodelist_contents_equal_noorder(ctx.d.querySelectorAll('*'), [ctx.d_div1, ctx.d_p1, ctx.d_div2], 'd.querySelectorAll');
+ assert_nodelist_contents_equal_noorder(ctx.s1.querySelectorAll('*'), [ctx.s1_div1, ctx.s1_p1, ctx.s1_div2], 's1.querySelectorAll(\'*\') return wrong result');
+ assert_nodelist_contents_equal_noorder(ctx.s2.querySelectorAll('*'), [ctx.s2_div1, ctx.s2_p1, ctx.s2_div2], 's2.querySelectorAll(\'*\') return wrong result');
+
+}, 'A_04_01_09_T09');
+
+//check querySelectorAll with attribute value
+test(function () {
+ var ctx = A_04_01_09.setup();
+
+ assert_nodelist_contents_equal_noorder(ctx.d.querySelectorAll('[test=A_04_01_09]'), [ctx.d_p1, ctx.d_div2], 'd.querySelectorAll(\'[test=A_04_01_09]\') return wrong result');
+ assert_nodelist_contents_equal_noorder(ctx.s1.querySelectorAll('[test=A_04_01_09]'), [ctx.s1_p1, ctx.s1_div2], 's1.querySelectorAll(\'[test=A_04_01_09]\') return wrong result');
+ assert_nodelist_contents_equal_noorder(ctx.s2.querySelectorAll('[test=A_04_01_09]'), [ctx.s2_p1, ctx.s2_div2], 's2.querySelectorAll(\'[test=A_04_01_09]\') return wrong result');
+
+}, 'A_04_01_09_T10');
+
+//check querySelectorAll with parent-child selection
+test(function () {
+ var ctx = A_04_01_09.setup();
+
+ assert_nodelist_contents_equal_noorder(ctx.d.querySelectorAll('div:first-child'), [ctx.d_div1, ctx.d_div2], 'd.querySelectorAll(\'div:first-child\') return wrong result');
+ assert_nodelist_contents_equal_noorder(ctx.s1.querySelectorAll('div:first-child'), [ctx.s1_div1,ctx.s1_div2], 's1.querySelectorAll(\'div:first-child\') return wrong result');
+ assert_nodelist_contents_equal_noorder(ctx.s2.querySelectorAll('div:first-child'), [ctx.s2_div1,ctx.s2_div2], 's2.querySelectorAll(\'div:first-child\') return wrong result');
+
+}, 'A_04_01_09_T11');
+
+//check querySelectorAll with parent-child selection
+test(function () {
+ var ctx = A_04_01_09.setup();
+
+ assert_nodelist_contents_equal_noorder(ctx.d.querySelectorAll('div:last-child'), [ctx.d_div2], 'd.querySelectorAll(\'div:last-child\') return wrong result');
+ assert_nodelist_contents_equal_noorder(ctx.s1.querySelectorAll('div:last-child'), [ctx.s1_div1, ctx.s1_div2], 's1.querySelectorAll(\'div:last-child\') return wrong result');
+ assert_nodelist_contents_equal_noorder(ctx.s2.querySelectorAll('div:last-child'), [ctx.s2_div1, ctx.s2_div2], 's2.querySelectorAll(\'div:last-child\') return wrong result');
+
+}, 'A_04_01_09_T12');
+
+//check querySelectorAll with parent-child selection
+test(function () {
+ var ctx = A_04_01_09.setup();
+
+ assert_nodelist_contents_equal_noorder(ctx.d.querySelectorAll('p:only-child'), [ctx.d_p1], 'd.querySelectorAll(\'p:only-child\') return wrong result');
+ assert_nodelist_contents_equal_noorder(ctx.s1.querySelectorAll('p:only-child'), [ctx.s1_p1], 's1.querySelectorAll(\'p:only-child\') return wrong result');
+ assert_nodelist_contents_equal_noorder(ctx.s2.querySelectorAll('p:only-child'), [ctx.s2_p1], 's2.querySelectorAll(\'p:only-child\') return wrong result');
+
+}, 'A_04_01_09_T13');
+
+//check querySelectorAll with parent-child selection
+test(function () {
+ var ctx = A_04_01_09.setup();
+
+ assert_nodelist_contents_equal_noorder(ctx.d.querySelectorAll('div:empty'), [ctx.d_div2], 'd.querySelectorAll(\'div:empty\') return wrong result');
+ assert_nodelist_contents_equal_noorder(ctx.s1.querySelectorAll('div:empty'), [ctx.s1_div2], 's1.querySelectorAll(\'div:empty\') return wrong result');
+ assert_nodelist_contents_equal_noorder(ctx.s2.querySelectorAll('div:empty'), [ctx.s2_div2], 's2.querySelectorAll(\'div:empty\') return wrong result');
+
+}, 'A_04_01_09_T14');
+
+//check querySelectorAll with parent-child selection
+test(function () {
+ var ctx = A_04_01_09.setup();
+
+ assert_nodelist_contents_equal_noorder(ctx.d.querySelectorAll('p div'), [ctx.d_div2], 'd.querySelectorAll(\'p div\') return wrong result');
+ assert_nodelist_contents_equal_noorder(ctx.s1.querySelectorAll('p div'), [ctx.s1_div2], 's1.querySelectorAll(\'p div\') return wrong result');
+ assert_nodelist_contents_equal_noorder(ctx.s2.querySelectorAll('p div'), [ctx.s2_div2], 's2.querySelectorAll(\'p div\') return wrong result');
+
+}, 'A_04_01_09_T15');
+
+//check querySelectorAll with parent-child selection
+test(function () {
+ var ctx = A_04_01_09.setup();
+
+ assert_nodelist_contents_equal_noorder(ctx.d.querySelectorAll('p > div'), [ctx.d_div2], 'd.querySelectorAll(\'p > div\') return wrong result');
+ assert_nodelist_contents_equal_noorder(ctx.s1.querySelectorAll('p > div'), [ctx.s1_div2], 's1.querySelectorAll(\'p > div\') return wrong result');
+ assert_nodelist_contents_equal_noorder(ctx.s2.querySelectorAll('p > div'), [ctx.s2_div2], 's2.querySelectorAll(\'p > div\') return wrong result');
+
+}, 'A_04_01_09_T16');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/upper-boundary-encapsulation/test-011.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/upper-boundary-encapsulation/test-011.html
new file mode 100644
index 00000000000..18fcfd75e74
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/upper-boundary-encapsulation/test-011.html
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_04_01_11</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#upper-boundary-encapsulation">
+<meta name="assert" content="Upper-boundary encapsulation:The style sheets, represented by the shadow nodes are not accessible using shadow host document's CSSOM extensions">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+// check that <style> element added to head is not exposed
+var A_04_01_11_T1 = async_test('A_04_01_11_T01');
+
+A_04_01_11_T1.step(function () {
+ var ctx = newContext();
+ var iframe = newIFrame(ctx, '../../resources/blank.html');
+ iframe.onload = A_04_01_11_T1.step_func(step_unit(function () {
+ var d = iframe.contentDocument;
+ var initialStyleSheetsCount = d.styleSheets.length;
+ var s = d.head.createShadowRoot();
+ var style = d.createElement('style');
+ s.appendChild(style);
+ assert_equals(d.styleSheets.length, initialStyleSheetsCount, 'style elements in shadow DOM must not be exposed via ' +
+ 'the document.styleSheets collection ');
+
+ }, ctx, A_04_01_11_T1));
+});
+
+
+// check that <link> element added to head is not exposed
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+ var initialStyleSheetsCount = d.styleSheets.length;
+
+ var link = d.createElement('link');
+ link.setAttribute('href', 'testharness.css');
+ link.setAttribute('rel', 'stylesheet');
+ d.body.appendChild(link);
+
+ //create Shadow root
+ var root = d.createElement('div');
+ d.body.appendChild(root);
+ var s = root.createShadowRoot();
+
+ s.appendChild(link);
+
+ assert_equals(d.styleSheets.length, initialStyleSheetsCount, 'stylesheet link elements in shadow DOM must not be ' +
+ 'exposed via the document.styleSheets collection');
+
+
+}), 'A_04_01_11_T2');
+
+// TODO check selectedStyleSheetSet, lastStyleSheetSet, preferredStyleSheetSet, styleSheetSets
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/upper-boundary-encapsulation/window-named-properties-001.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/upper-boundary-encapsulation/window-named-properties-001.html
new file mode 100644
index 00000000000..9fbd1ee927a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/upper-boundary-encapsulation/window-named-properties-001.html
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: Window object named properties: Frames</title>
+<link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="author" title="Yuta Kitamura" href="mailto:yutak@google.com">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#upper-boundary-encapsulation">
+<meta name="assert" content="Upper-boundary encapsulation: The nodes and named elements are not accessible from Window object named properties.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(function () {
+ var host = document.createElement('div');
+ try {
+ host.style.display = 'none';
+ document.body.appendChild(host);
+ var shadowRoot = host.createShadowRoot();
+ var iframe = document.createElement('iframe');
+ iframe.style.display = 'none';
+ iframe.name = 'test-name';
+ shadowRoot.appendChild(iframe);
+ assert_false('test-name' in window);
+ } finally {
+ if (host.parentNode)
+ host.parentNode.removeChild(host);
+ }
+},
+ 'An iframe element in a shadow tree should not be accessible from ' +
+ 'window\'s named properties with its "name" attribute value.'
+);
+
+var frameTest = async_test(
+ 'A frame element in a shadow tree should not be accessible from ' +
+ 'window\'s named properties with its "name" attribute value.');
+
+frameTest.step(function () {
+ // To test a document with frames, an iframe containing frames is created.
+ var srcdoc = [
+ '<!DOCTYPE html>',
+ '<html>',
+ '<head>',
+ '<title>Frames Test</title>',
+ '<script src="../../testcommon.js"><' + '/script>',
+ '</head>',
+ '<frameset id="host" cols="50%,*">',
+ '<frame src="about:blank" name="host-frame1">',
+ '<frame src="about:blank" name="host-frame2">',
+ '</frameset>',
+ '</html>'
+ ].join('\n');
+ var iframe = document.createElement('iframe');
+ iframe.srcdoc = srcdoc;
+ iframe.style.display = 'none';
+
+ iframe.addEventListener('load', frameTest.step_func(function (event) {
+ try {
+ var doc = iframe.contentDocument;
+ var win = iframe.contentWindow;
+ var shadowRoot = doc.getElementById('host').createShadowRoot();
+ shadowRoot.innerHTML =
+ '<frame src="about:blank" name="shadow-frame1">\n' +
+ '<frame src="about:blank" name="shadow-frame2">';
+ assert_false('shadow-frame1' in win);
+ assert_false('shadow-frame2' in win);
+ frameTest.done();
+ } finally {
+ if (iframe.parentNode)
+ iframe.parentNode.removeChild(iframe);
+ }
+ }));
+
+ document.body.appendChild(iframe);
+});
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/upper-boundary-encapsulation/window-named-properties-002.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/upper-boundary-encapsulation/window-named-properties-002.html
new file mode 100644
index 00000000000..cfbf4b5d435
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/upper-boundary-encapsulation/window-named-properties-002.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: Window object named properties: "name" attribute</title>
+<link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="author" title="Yuta Kitamura" href="mailto:yutak@google.com">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#upper-boundary-encapsulation">
+<meta name="assert" content="Upper-boundary encapsulation: The nodes and named elements are not accessible from Window object named properties.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+function testNameAttribute(elementName) {
+ var doc = document.implementation.createHTMLDocument('Title');
+ var shadowRoot = doc.body.createShadowRoot();
+ var element = doc.createElement(elementName);
+ element.name = 'test-name';
+ shadowRoot.appendChild(element);
+ assert_false('test-name' in window);
+}
+
+var namedElements = [
+ 'a', 'applet', 'area', 'embed', 'form', 'frameset', 'img', 'object'
+];
+
+var nameAttributeTestParameter = namedElements.map(function (elementName) {
+ return [
+ '"' + elementName + '" element with name attribute in a shadow tree ' +
+ 'should not be accessible from window object\'s named property.',
+ elementName
+ ];
+});
+
+generate_tests(testNameAttribute, nameAttributeTestParameter);
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/upper-boundary-encapsulation/window-named-properties-003.html b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/upper-boundary-encapsulation/window-named-properties-003.html
new file mode 100644
index 00000000000..bde896d9641
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/shadow-trees/upper-boundary-encapsulation/window-named-properties-003.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: Window object named properties: "id" attribute</title>
+<link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="author" title="Yuta Kitamura" href="mailto:yutak@google.com">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#upper-boundary-encapsulation">
+<meta name="assert" content="Upper-boundary encapsulation: The nodes and named elements are not accessible from Window object named properties.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+function testIDAttribute(elementName) {
+ var doc = document.implementation.createHTMLDocument('Title');
+ var shadowRoot = doc.body.createShadowRoot();
+ var element = doc.createElement(elementName);
+ element.id = 'test-id';
+ shadowRoot.appendChild(element);
+ assert_false('test-id' in window);
+}
+
+var idAttributeTestParameter = HTML5_ELEMENT_NAMES.map(function (elementName) {
+ return [
+ '"' + elementName + '" element with id attribute in a shadow tree ' +
+ 'should not be accessible from window object\'s named property.',
+ elementName
+ ];
+});
+
+generate_tests(testIDAttribute, idAttributeTestParameter);
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/styles/css-variables/test-001.html b/tests/wpt/web-platform-tests/shadow-dom/styles/css-variables/test-001.html
new file mode 100644
index 00000000000..8d7b57bd075
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/styles/css-variables/test-001.html
@@ -0,0 +1,73 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_06_01_01</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#css-variables">
+<meta name="assert" content="CSS variables: The shadow host styles being inherited by the children of the shadow root must also apply to CSS Variables.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+//TODO For now (November, 2012) CSS variables support is not implemented yet
+// so this test won't work. Treat it as a placeholder for now
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+ d.head.innerHtml = '' +
+ '<style>' +
+ 'body {font-size:10px;}' +
+ '</style>';
+
+ d.body.innerHTML =
+ '<ul id="shHost">' +
+ '<li id="li1" class="shadow">1</li>' +
+ '<li id="li2" class="shadow2">2</li>' +
+ '<li id="li3" class="shadow">3</li>' +
+ '<li id="li4">4</li>' +
+ '<li id="li5" class="shadow">5</li>' +
+ '<li id="li6" class="shadow2">6</li>' +
+ '</ul>';
+
+
+ var host = d.querySelector('#shHost');
+ var s = host.createShadowRoot();
+
+ var div = d.createElement('div');
+ div.innerHTML ='<ul><content select=".shadow"></content></ul>';
+ s.appendChild(div);
+
+ var defHeight1 = d.querySelector('#li1').offsetHeight;
+ var defHeight3 = d.querySelector('#li3').offsetHeight;
+ var defHeight5 = d.querySelector('#li5').offsetHeight;
+
+ var style = d.createElement('style');
+ style.innerHTML =':root {' +
+ 'var-text-size: 30px;' +
+ '}' +
+ 'body {' +
+ 'font-size: var(text-size);' +
+ '}';
+ s.appendChild(style);
+
+ assert_true(d.querySelector('#li1').offsetHeight > defHeight1, 'Point 1: Element height should be changed');
+ assert_true(d.querySelector('#li3').offsetHeight > defHeight3, 'Point 2: Element height should be changed');
+ assert_true(d.querySelector('#li5').offsetHeight > defHeight5, 'Point 3: Element height should be changed');
+
+}), 'A_06_01_01_T01');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/styles/deep-combinator/deep-combinator-001.html b/tests/wpt/web-platform-tests/shadow-dom/styles/deep-combinator/deep-combinator-001.html
new file mode 100644
index 00000000000..c60403ff58c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/styles/deep-combinator/deep-combinator-001.html
@@ -0,0 +1,157 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: /deep/ combinator</title>
+<link rel="author" title="Kenji Baheux" href="mailto:kenjibaheux@google.com">
+<link rel="help" href="http://dev.w3.org/csswg/css-scoping/#deep-combinator">
+<meta name="assert" content="/deep/ should select through all Shadow trees">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(unit(function (ctx) {
+ var d = newRenderedHTMLDocument(ctx);
+
+ var outerhost = d.createElement('div');
+ outerhost.setAttribute('id', 'foo-host');
+ var span0 = d.createElement('span');
+ span0.setAttribute('id', 'outer-host');
+ outerhost.appendChild(span0);
+
+ var outerroot = outerhost.createShadowRoot();
+
+ var div1 = d.createElement('div');
+ var span1 = d.createElement('span');
+ span1.setAttribute('id', 'not-top');
+ div1.appendChild(span1);
+ outerroot.appendChild(div1);
+
+ var span2 = d.createElement('span');
+ span2.setAttribute('id', 'top');
+ outerroot.appendChild(span2);
+
+
+ var innerhost = d.createElement('div');
+ innerhost.setAttribute('id', 'bar-host');
+ var span3 = d.createElement('span');
+ span3.setAttribute('id', 'inner-host');
+ innerhost.appendChild(span3);
+
+ var innerroot = innerhost.createShadowRoot();
+
+ var span4 = d.createElement('span');
+ span4.setAttribute('id', 'nested');
+ innerroot.appendChild(span4);
+ outerroot.appendChild(innerhost);
+
+ d.body.appendChild(outerhost);
+
+
+ assert_equals(d.querySelectorAll('#foo-host /deep/ span').length, 5, 'Point 1: match only direct children of the outer shadow tree');
+ assert_equals(d.querySelectorAll('#foo-host /deep/ span')[0], span1, 'Point 2: incorrect match');
+ assert_equals(d.querySelectorAll('#foo-host /deep/ span')[1], span2, 'Point 3: incorrect match');
+ assert_equals(d.querySelectorAll('#foo-host /deep/ span')[2], span4, 'Point 4: incorrect match');
+ assert_equals(d.querySelectorAll('#foo-host /deep/ span')[3], span3, 'Point 5: incorrect match');
+ assert_equals(d.querySelectorAll('#foo-host /deep/ span')[4], span0, 'Point 6: incorrect match');
+ }), 'SD_SHADOW_DEEP_QUERYSELECTOR_T1');
+
+test(unit(function (ctx) {
+ var d = newRenderedHTMLDocument(ctx);
+
+ var outerhost = d.createElement('div');
+ outerhost.setAttribute('id', 'foo-host');
+ var span0 = d.createElement('span');
+ span0.setAttribute('id', 'outer-host');
+ outerhost.appendChild(span0);
+
+ var s1 = outerhost.createShadowRoot();
+
+ var div1 = d.createElement('div');
+ var span1 = d.createElement('span');
+ span1.setAttribute('id', 'not-top');
+ div1.appendChild(span1);
+ s1.appendChild(div1);
+
+ var span2 = d.createElement('span');
+ span2.setAttribute('id', 'top');
+ s1.appendChild(span2);
+
+
+ var innerhost = d.createElement('div');
+ innerhost.setAttribute('id', 'bar-host');
+ var span3 = d.createElement('span');
+ span3.setAttribute('id', 'inner-host');
+ innerhost.appendChild(span3);
+
+ var s2 = innerhost.createShadowRoot();
+
+ var span4 = d.createElement('span');
+ span4.setAttribute('id', 'nested');
+ s2.appendChild(span4);
+ s1.appendChild(innerhost);
+
+ d.body.appendChild(outerhost);
+
+
+ assert_equals(s1.querySelectorAll('* /deep/ span').length, 3, 'Point 1: match only in the inner shadow tree');
+ assert_equals(s1.querySelectorAll('* /deep/ span')[0], span1, 'Point 2: incorrect match');
+ assert_equals(s1.querySelectorAll('* /deep/ span')[1], span4, 'Point 4: incorrect match');
+ assert_equals(s1.querySelectorAll('* /deep/ span')[2], span3, 'Point 5: incorrect match');
+ }), 'SD_SHADOW_DEEP_QUERYSELECTOR_T2');
+
+test(unit(function (ctx) {
+ var d = newRenderedHTMLDocument(ctx);
+
+ var outerhost = d.createElement('div');
+ outerhost.setAttribute('id', 'foo-host');
+ var span0 = d.createElement('span');
+ span0.setAttribute('id', 'outer-host');
+ outerhost.appendChild(span0);
+
+ var s1 = outerhost.createShadowRoot();
+
+ var div1 = d.createElement('div');
+ var span1 = d.createElement('span');
+ span1.setAttribute('id', 'not-top');
+ div1.appendChild(span1);
+ s1.appendChild(div1);
+
+ var span2 = d.createElement('span');
+ span2.setAttribute('id', 'top');
+ s1.appendChild(span2);
+
+
+ var innerhost = d.createElement('div');
+ innerhost.setAttribute('id', 'bar-host');
+ var span3 = d.createElement('span');
+ span3.setAttribute('id', 'inner-host');
+ innerhost.appendChild(span3);
+
+ var s2 = innerhost.createShadowRoot();
+
+ var span4 = d.createElement('span');
+ span4.setAttribute('id', 'nested');
+ s2.appendChild(span4);
+ s1.appendChild(innerhost);
+
+ d.body.appendChild(outerhost);
+
+
+ assert_equals(s2.querySelectorAll('* /deep/ span').length, 0, 'Point 1: no match');
+ }), 'SD_SHADOW_DEEP_QUERYSELECTOR_T3');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/styles/not-apply-in-shadow-root-001-ref.html b/tests/wpt/web-platform-tests/shadow-dom/styles/not-apply-in-shadow-root-001-ref.html
new file mode 100644
index 00000000000..fdcc6e5ba21
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/styles/not-apply-in-shadow-root-001-ref.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test</title>
+<link rel="author" title="Kazuhito Hokamura" href="mailto:k.hokamura@gmail.com">
+<style>
+div {
+ width: 100px;
+ height: 100px;
+ background: green;
+}
+</style>
+</head>
+<body>
+<p>Test passes if following box is green.</p>
+<div></div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/styles/not-apply-in-shadow-root-001.html b/tests/wpt/web-platform-tests/shadow-dom/styles/not-apply-in-shadow-root-001.html
new file mode 100644
index 00000000000..abef32a1811
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/styles/not-apply-in-shadow-root-001.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test - Tests CSS rules must not apply in a shadow root</title>
+<link rel="match" href="not-apply-in-shadow-root-001-ref.html">
+<link rel="author" title="Kazuhito Hokamura" href="mailto:k.hokamura@gmail.com">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#styles">
+<meta name="assert" content="Styles: CSS rules declared in an enclosing tree must not apply in a shadow tree if apply-author-styles flag is not set.">
+<script src="../testcommon.js"></script>
+<style>
+div {
+ width: 100px;
+ height: 100px;
+ background: green;
+}
+</style>
+</head>
+<body>
+<p>Test passes if following box is green.</p>
+<div id="shadow-host"></div>
+<script>
+var shadowHost = document.getElementById('shadow-host');
+var shadowRoot = shadowHost.createShadowRoot();
+var style = document.createElement('style');
+style.innerHTML = 'div { background: red }';
+
+shadowRoot.appendChild(style);
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/styles/shadow-pseudoelement/shadow-pseudoelement-001.html b/tests/wpt/web-platform-tests/shadow-dom/styles/shadow-pseudoelement/shadow-pseudoelement-001.html
new file mode 100644
index 00000000000..a0048c8ee3b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/styles/shadow-pseudoelement/shadow-pseudoelement-001.html
@@ -0,0 +1,151 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: ::shadow pseudo element</title>
+<link rel="author" title="Kenji Baheux" href="mailto:kenjibaheux@google.com">
+<link rel="help" href="http://dev.w3.org/csswg/css-scoping/#shadow-pseudoelement">
+<meta name="assert" content="::shadow should match a shadow root">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(unit(function (ctx) {
+ var d = newRenderedHTMLDocument(ctx);
+
+ var outerhost = d.createElement('div');
+ outerhost.setAttribute('id', 'foo-host');
+ var span0 = d.createElement('span');
+ span0.setAttribute('id', 'outer-host');
+ outerhost.appendChild(span0);
+
+ var s1 = outerhost.createShadowRoot();
+
+ var div1 = d.createElement('div');
+ var span1 = d.createElement('span');
+ span1.setAttribute('id', 'not-top');
+ div1.appendChild(span1);
+ s1.appendChild(div1);
+
+ var span2 = d.createElement('span');
+ span2.setAttribute('id', 'top');
+ s1.appendChild(span2);
+
+
+ var innerhost = d.createElement('div');
+ innerhost.setAttribute('id', 'bar-host');
+ var span3 = d.createElement('span');
+ span3.setAttribute('id', 'inner-host');
+ innerhost.appendChild(span3);
+
+ var s2 = innerhost.createShadowRoot();
+
+ var span4 = d.createElement('span');
+ span4.setAttribute('id', 'nested');
+ s2.appendChild(span4);
+ s1.appendChild(innerhost);
+
+ d.body.appendChild(outerhost);
+
+ assert_equals(d.querySelectorAll('#foo-host::shadow span').length, 3, 'Point 1: match only direct children of the outer shadow tree');
+ assert_equals(d.querySelectorAll('#foo-host::shadow span')[0], span1, 'Point 2: incorrect match');
+ assert_equals(d.querySelectorAll('#foo-host::shadow span')[1], span2, 'Point 3: incorrect match');
+ assert_equals(d.querySelectorAll('#foo-host::shadow span')[2], span3, 'Point 4: incorrect match');
+ }), 'SD_SHADOW_PSEUDOELEMENT_QUERYSELECTOR_T1');
+
+test(unit(function (ctx) {
+ var d = newRenderedHTMLDocument(ctx);
+
+ var outerhost = d.createElement('div');
+ outerhost.setAttribute('id', 'foo-host');
+ var span0 = d.createElement('span');
+ span0.setAttribute('id', 'outer-host');
+ outerhost.appendChild(span0);
+
+ var s1 = outerhost.createShadowRoot();
+
+ var div1 = d.createElement('div');
+ var span1 = d.createElement('span');
+ span1.setAttribute('id', 'not-top');
+ div1.appendChild(span1);
+ s1.appendChild(div1);
+
+ var span2 = d.createElement('span');
+ span2.setAttribute('id', 'top');
+ s1.appendChild(span2);
+
+
+ var innerhost = d.createElement('div');
+ innerhost.setAttribute('id', 'bar-host');
+ var span3 = d.createElement('span');
+ span3.setAttribute('id', 'inner-host');
+ innerhost.appendChild(span3);
+
+ var s2 = innerhost.createShadowRoot();
+
+ var span4 = d.createElement('span');
+ span4.setAttribute('id', 'nested');
+ s2.appendChild(span4);
+ s1.appendChild(innerhost);
+
+ d.body.appendChild(outerhost);
+
+ assert_equals(s1.querySelectorAll('*::shadow span').length, 1, 'Point 1: match only in the inner shadow tree');
+ assert_equals(s1.querySelectorAll('*::shadow span')[0], span4, 'Point 2: incorrect match');
+ }), 'SD_SHADOW_PSEUDOELEMENT_QUERYSELECTOR_T2');
+
+test(unit(function (ctx) {
+ var d = newRenderedHTMLDocument(ctx);
+
+ var outerhost = d.createElement('div');
+ outerhost.setAttribute('id', 'foo-host');
+ var span0 = d.createElement('span');
+ span0.setAttribute('id', 'outer-host');
+ outerhost.appendChild(span0);
+
+ var s1 = outerhost.createShadowRoot();
+
+ var div1 = d.createElement('div');
+ var span1 = d.createElement('span');
+ span1.setAttribute('id', 'not-top');
+ div1.appendChild(span1);
+ s1.appendChild(div1);
+
+ var span2 = d.createElement('span');
+ span2.setAttribute('id', 'top');
+ s1.appendChild(span2);
+
+
+ var innerhost = d.createElement('div');
+ innerhost.setAttribute('id', 'bar-host');
+ var span3 = d.createElement('span');
+ span3.setAttribute('id', 'inner-host');
+ innerhost.appendChild(span3);
+
+ var s2 = innerhost.createShadowRoot();
+
+ var span4 = d.createElement('span');
+ span4.setAttribute('id', 'nested');
+ s2.appendChild(span4);
+ s1.appendChild(innerhost);
+
+ d.body.appendChild(outerhost);
+
+ assert_equals(s2.querySelectorAll('*::shadow span').length, 0, 'Point 1: no match');
+ }), 'SD_SHADOW_PSEUDOELEMENT_QUERYSELECTOR_T3');
+
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/styles/test-001.html b/tests/wpt/web-platform-tests/shadow-dom/styles/test-001.html
new file mode 100644
index 00000000000..0d4fd2f0737
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/styles/test-001.html
@@ -0,0 +1,174 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_06_00_01</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#styles">
+<meta name="assert" content="Styles: CSS rules declared in an enclosing tree must not apply in a shadow tree if apply-author-styles flag is set to false for this tree">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+//test apply-author-styles flag of ShadowRoot object (default value)
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ d.head.innerHTML = '<style>' +
+ '.invis {' +
+ 'display:none;' +
+ '}' +
+ '</style>';
+
+ var host = d.createElement('div');
+ d.body.appendChild(host);
+
+ //Shadow root to play with
+ var s = host.createShadowRoot();
+
+ var div1 = d.createElement('div');
+ div1.innerHTML ='<span id="shd" class="invis">This is the shadow tree</span>';
+ s.appendChild(div1);
+
+ //apply-author-styles flag is false by default. Invisible style shouldn't be applied
+ assert_true(s.querySelector('#shd').offsetTop > 0,
+ 'CSS styles declared in enclosing tree must not be applied in a shadow tree ' +
+ 'if the apply-author-styles flag is set to false');
+
+
+}), 'A_06_00_01_T01');
+
+
+//test apply-author-styles flag of ShadowRoot object (set it)
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ d.head.innerHTML = '<style>' +
+ '.invis {' +
+ 'display:none;' +
+ '}' +
+ '</style>';
+
+ var host = d.createElement('div');
+ d.body.appendChild(host);
+
+ //Shadow root to play with
+ var s = host.createShadowRoot();
+ s.applyAuthorStyles = false;
+
+ var div1 = d.createElement('div');
+ div1.innerHTML ='<span id="shd" class="invis">This is the shadow tree</span>';
+ s.appendChild(div1);
+
+ //apply-author-styles flag is set to false. Invisible style shouldn't be applied
+ assert_true(s.querySelector('#shd').offsetTop > 0,
+ 'CSS styles declared in enclosing tree must not be applied in a shadow tree ' +
+ 'if the apply-author-styles flag is set to false');
+
+
+}), 'A_06_00_01_T02');
+
+//test apply-author-styles flag in a nested tree (default value)
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ d.head.innerHTML = '<style>' +
+ '.invis {' +
+ 'display:none;' +
+ '}' +
+ '</style>';
+
+ var host = d.createElement('div');
+ d.body.appendChild(host);
+
+ //Shadow root to play with
+ var s1 = host.createShadowRoot();
+
+ var div1 = d.createElement('div');
+ div1.innerHTML = '<span id="shd1" class="invis">This is an old shadow tree</span>';
+ s1.appendChild(div1);
+
+ //younger tree
+ var s2 = host.createShadowRoot();
+ var div1 = d.createElement('div');
+ div1.innerHTML = '<span id="shd2" class="invis">This is a young shadow tree</span>' +
+ '<shadow><span id="shd3" class="invis">This is the shadow tree fallback content</span></shadow>';
+ s2.appendChild(div1);
+
+
+ //apply-author-styles flag is false by default. Invisible style shouldn't be applied
+ //shd1 and shd2 should be visible. sh3 not because the tree should be active
+ assert_true(s1.querySelector('#shd1').offsetTop > 0,
+ 'Point 1: CSS styles declared in enclosing tree must not be applied in a shadow tree ' +
+ 'if the apply-author-styles flag is set to false');
+ assert_true(s2.querySelector('#shd2').offsetTop > 0,
+ 'Point 2: CSS styles declared in enclosing tree must not be applied in a shadow tree ' +
+ 'if the apply-author-styles flag is set to false');
+ assert_equals(s2.querySelector('#shd3').offsetTop, 0,
+ 'Fallback content shouldn\'t be rendered for active tree');
+
+
+}), 'A_06_00_01_T03');
+
+
+//test apply-author-styles flag in a nested tree (set it)
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ d.head.innerHTML = '<style>' +
+ '.invis {' +
+ 'display:none;' +
+ '}' +
+ '</style>';
+
+ var host = d.createElement('div');
+ d.body.appendChild(host);
+
+ //Shadow root to play with
+ var s1 = host.createShadowRoot();
+ s1.applyAuthorStyles = false;
+
+ var div1 = d.createElement('div');
+ div1.innerHTML = '<span id="shd1" class="invis">This is an old shadow tree</span>';
+ s1.appendChild(div1);
+
+ //younger tree
+ var s2 = host.createShadowRoot();
+ var div1 = d.createElement('div');
+ div1.innerHTML = '<span id="shd2" class="invis">This is a young shadow tree</span>' +
+ '<shadow><span id="shd3" class="invis">This is the shadow tree fallback content</span></shadow>';
+ s2.appendChild(div1);
+
+
+ //apply-author-styles flag is set to false. Invisible style shouldn't be applied
+ //shd1 and shd2 should be visible. sh3 not because the tree should be active
+ assert_true(s1.querySelector('#shd1').offsetTop > 0,
+ 'Point 1: CSS styles declared in enclosing tree must not be applied in a shadow tree ' +
+ 'if the apply-author-styles flag is set to false');
+ assert_true(s2.querySelector('#shd2').offsetTop > 0,
+ 'Point 2: CSS styles declared in enclosing tree must not be applied in a shadow tree ' +
+ 'if the apply-author-styles flag is set to false');
+ assert_equals(s2.querySelector('#shd3').offsetTop, 0,
+ 'Fallback content shouldn\'t be rendered for active tree');
+
+
+}), 'A_06_00_01_T04');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/styles/test-002.html b/tests/wpt/web-platform-tests/shadow-dom/styles/test-002.html
new file mode 100644
index 00000000000..40d4bd91cda
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/styles/test-002.html
@@ -0,0 +1,149 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_06_00_02</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#styles">
+<meta name="assert" content="Styles: CSS rules declared in an enclosing tree must be applied in a shadow tree if apply-author-styles flag is set to true for this tree">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+//test apply-author-styles flag of ShadowRoot object
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ d.head.innerHTML = '<style>' +
+ '.invis {' +
+ 'display:none;' +
+ '}' +
+ '</style>';
+
+ var host = d.createElement('div');
+ d.body.appendChild(host);
+
+ //Shadow root to play with
+ var s = host.createShadowRoot();
+ s.applyAuthorStyles = true;
+
+ var div1 = d.createElement('div');
+ div1.innerHTML ='<span id="shd" class="invis">This is the shadow tree</span>';
+ s.appendChild(div1);
+
+ //apply-author-styles flag is set to true. Invisible style should be applied
+ assert_equals(s.querySelector('#shd').offsetTop, 0,
+ 'CSS styles declared in enclosing tree must be applied in a shadow tree ' +
+ 'if the apply-author-styles flag is set to true');
+
+
+}), 'A_06_00_02_T01');
+
+
+//test apply-author-styles flag in a nested tree (set it)
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ d.head.innerHTML = '<style>' +
+ '.invis {' +
+ 'display:none;' +
+ '}' +
+ '</style>';
+
+ var host = d.createElement('div');
+ d.body.appendChild(host);
+
+ //Shadow root to play with
+ var s1 = host.createShadowRoot();
+ s1.applyAuthorStyles = true;
+
+ var div1 = d.createElement('div');
+ div1.innerHTML = '<span id="shd1" class="invis">This is an old shadow tree</span>';
+ s1.appendChild(div1);
+
+ //younger tree
+ var s2 = host.createShadowRoot();
+ s2.applyAuthorStyles = true;
+ var div1 = d.createElement('div');
+ div1.innerHTML = '<span id="shd2" class="invis">This is a young shadow tree</span>' +
+ '<shadow><span id="shd3" class="invis">This is the shadow tree fallback content</span></shadow>';
+ s2.appendChild(div1);
+
+
+ //apply-author-styles flag is set to true. Invisible style should be applied
+ //shd1 and shd2 should be invisible. sh3 invisible too because the tree should be active
+ assert_equals(s1.querySelector('#shd1').offsetTop, 0,
+ 'Point 1: CSS styles declared in enclosing tree must be applied in a shadow tree ' +
+ 'if the apply-author-styles flag is set to true');
+ assert_equals(s2.querySelector('#shd2').offsetTop, 0,
+ 'Point 2: CSS styles declared in enclosing tree must be applied in a shadow tree ' +
+ 'if the apply-author-styles flag is set to true');
+ assert_equals(s2.querySelector('#shd3').offsetTop, 0,
+ 'Fallback content shouldn\'t be rendered for active tree');
+
+
+}), 'A_06_00_02_T02');
+
+
+
+//test different apply-author-styles flag values in a nested young and old trees
+test(unit(function (ctx) {
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ d.head.innerHTML = '<style>' +
+ '.invis {' +
+ 'display:none;' +
+ '}' +
+ '</style>';
+
+ var host = d.createElement('div');
+ d.body.appendChild(host);
+
+ //Shadow root to play with
+ var s1 = host.createShadowRoot();
+ s1.applyAuthorStyles = true;
+
+ var div1 = d.createElement('div');
+ div1.innerHTML = '<span id="shd1" class="invis">This is an old shadow tree</span>';
+ s1.appendChild(div1);
+
+ //younger tree
+ var s2 = host.createShadowRoot();
+ //applyAuthorStyles false by default
+ var div1 = d.createElement('div');
+ div1.innerHTML = '<span id="shd2" class="invis">This is a young shadow tree</span>' +
+ '<shadow><span id="shd3" class="invis">This is the shadow tree fallback content</span></shadow>';
+ s2.appendChild(div1);
+
+
+ //apply-author-styles flag is set to true. Invisible style should be applied
+ //shd1 and shd2 should be invisible. sh3 invisible too because the tree should be active
+ assert_equals(s1.querySelector('#shd1').offsetTop, 0,
+ 'Point 1: CSS styles declared in enclosing tree must be applied in a shadow tree ' +
+ 'if the apply-author-styles flag is set to true');
+ assert_true(s2.querySelector('#shd2').offsetTop > 0,
+ 'Point 2: CSS styles declared in enclosing tree must be applied in a shadow tree ' +
+ 'if the apply-author-styles flag is set to true');
+ assert_equals(s2.querySelector('#shd3').offsetTop, 0,
+ 'Fallback content shouldn\'t be rendered for active tree');
+
+
+}), 'A_06_00_02_T03');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/styles/test-003.html b/tests/wpt/web-platform-tests/shadow-dom/styles/test-003.html
new file mode 100644
index 00000000000..ac5b34a0f71
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/styles/test-003.html
@@ -0,0 +1,69 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_06_00_03</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#styles">
+<meta name="assert" content="Styles: Each shadow root has an associated list of zero or more style sheets, named shadow root style sheets">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(unit(function (ctx) {
+ var d = newRenderedHTMLDocument(ctx);
+ var host = d.createElement('div');
+ d.body.appendChild(host);
+
+ //Shadow root to play with
+ var s = host.createShadowRoot();
+
+ assert_equals(s.styleSheets.length, 0, 'There should be no style sheets');
+}), 'A_06_00_03_T01');
+
+
+test(unit(function (ctx) {
+ var d = newRenderedHTMLDocument(ctx);
+ var host = d.createElement('div');
+ host.setAttribute('style', 'width:100px');
+ d.body.appendChild(host);
+
+ //Shadow root to play with
+ var s = host.createShadowRoot();
+
+ assert_equals(s.styleSheets.length, 0, 'There should be no style sheets');
+}), 'A_06_00_03_T02');
+
+//TODO Now this tests produces an error on Chromium because styleSheets.length
+//returns 0 when the shadow root is orphaned.
+//Tracking bug: http://crbug.com/392771
+test(unit(function (ctx) {
+ var d = newRenderedHTMLDocument(ctx);
+ var host = d.createElement('div');
+
+ //Shadow root to play with
+ var s = host.createShadowRoot();
+
+ var style = d.createElement('style');
+ style.textContent = 'div {width: 50%;}';
+ s.appendChild(style);
+
+ // The following line fixes the issue on Chromium, http://crbug.com/392771
+ // d.body.appendChild(host);
+ assert_equals(s.styleSheets.length, 1, 'Style sheet is not accessible via styleSheets');
+}), 'A_06_00_03_T03');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/styles/test-005.html b/tests/wpt/web-platform-tests/shadow-dom/styles/test-005.html
new file mode 100644
index 00000000000..313fc104fcc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/styles/test-005.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_06_00_06</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#styles">
+<meta name="assert" content="Styles:CSS rules declared in a shadow root style sheets must not apply in the document tree,">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+//check querySelector method
+test(unit(function (ctx) {
+ var d = newRenderedHTMLDocument(ctx);
+
+ d.body.innerHTML =
+ '<div>' +
+ '<span class="invis" id="theTreeSpan">This is an element in the document tree</span>' +
+ '</div>' +
+ '<div id="sr">' +
+ '</div>';
+
+ var host = d.querySelector('#sr');
+
+ //Shadow root to play with
+ var s = host.createShadowRoot();
+
+ var style = d.createElement('style');
+ style.innerHTML ='.invis {display:none}';
+ s.appendChild(style);
+
+ var span = d.createElement('span');
+ span.setAttribute('id', 'theShadowSpan');
+ span.setAttribute('class', 'invis');
+ s.appendChild(span);
+
+ //theTreeSpan should be visible, theShadowSpan not
+ assert_true(d.querySelector('#theTreeSpan').offsetTop > 0,
+ 'CSS styles declared in shadow tree must not be applied to the elements ' +
+ 'in the document tree');
+
+ //theTreeSpan should be visible, theShadowSpan not
+ assert_equals(s.querySelector('#theShadowSpan').offsetTop, 0,
+ 'CSS styles declared in shadow tree must be applied to the element ' +
+ 'in the same shadow tree');
+
+}), 'A_06_00_06_T01');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/styles/test-007.html b/tests/wpt/web-platform-tests/shadow-dom/styles/test-007.html
new file mode 100644
index 00000000000..b8553c463a8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/styles/test-007.html
@@ -0,0 +1,134 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_06_00_08</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#styles">
+<meta name="assert" content="Styles:The @host @-rule matches a shadow host in the nesting tree.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+// The some of the tests below fails.
+// See https://bugs.webkit.org/show_bug.cgi?id=103608
+
+
+
+//Test fails. See https://bugs.webkit.org/show_bug.cgi?id=103608
+test(unit(function (ctx) {
+ var d = newRenderedHTMLDocument(ctx);
+
+ d.head.innerHTML = ':host {display:none;}';
+
+ d.body.innerHTML =
+ '<ul class="cls">' +
+ '<li id="li1" class="shadow">1</li>' +
+ '<li id="li2" class="shadow2">2</li>' +
+ '<li id="li3" class="shadow">3</li>' +
+ '<li id="li4">4</li>' +
+ '<li id="li5" class="shadow">5</li>' +
+ '<li id="li6" class="shadow2">6</li>' +
+ '</ul>';
+
+ var host = d.querySelector('.cls');
+ //Shadow root to play with
+ var s = host.createShadowRoot();
+
+ var div = d.createElement('div');
+ div.innerHTML ='<ul><content select=".shadow"></content></ul>';
+ s.appendChild(div);
+
+ //:host rule shouldn't take any effect
+ assert_true(d.querySelector('#li1').offsetTop > 0,
+ 'Point 1: element should be rendered');
+ assert_true(d.querySelector('#li3').offsetTop > 0,
+ 'Point 2: element should be rendered');
+ assert_true(d.querySelector('#li5').offsetTop > 0,
+ 'Point 3: element should be rendered');
+
+
+}), 'A_06_00_08_T01');
+
+//TODO (sgrekhov) Check the expected result at https://www.w3.org/Bugs/Public/show_bug.cgi?id=20150
+test(unit(function (ctx) {
+ var d = newRenderedHTMLDocument(ctx);
+
+ d.body.innerHTML =
+ '<ul class="cls">' +
+ '<li id="li1" class="shadow">1</li>' +
+ '<li id="li2" class="shadow2">2</li>' +
+ '<li id="li3" class="shadow">3</li>' +
+ '<li id="li4">4</li>' +
+ '<li id="li5" class="shadow">5</li>' +
+ '<li id="li6" class="shadow2">6</li>' +
+ '</ul>';
+
+ var host = d.querySelector('.cls');
+ //Shadow root to play with
+ var s = host.createShadowRoot();
+
+ var div = d.createElement('div');
+ div.innerHTML ='<ul><content select=".shadow"></content></ul>';
+ s.appendChild(div);
+
+ var style = d.createElement('style');
+ style.innerHTML = ':host ul {display:none;}';
+ s.appendChild(style);
+
+ assert_equals(d.querySelector('#li1').offsetTop, 0,
+ 'Point 1: element should be rendered');
+ assert_equals(d.querySelector('#li3').offsetTop, 0,
+ 'Point 2: element should be rendered');
+ assert_equals(d.querySelector('#li5').offsetTop, 0,
+ 'Point 3: element should be rendered');
+
+
+}), 'A_06_00_08_T02');
+
+
+//Test fails. See https://bugs.webkit.org/show_bug.cgi?id=103608
+test(unit(function (ctx) {
+ var d = newRenderedHTMLDocument(ctx);
+
+ var host = d.createElement('div');
+ host.className = 'gone';
+ d.body.appendChild(host);
+
+ //Older tree
+ var s1 = host.createShadowRoot();
+ var div1 = d.createElement('div');
+ div1.innerHTML = '<span id="shd1">This is an old shadow tree</span>';
+ s1.appendChild(div1);
+
+ //Younger tree
+ var s2 = host.createShadowRoot();
+ var div1 = d.createElement('div');
+ div1.innerHTML = '<span id="shd2">This is a young shadow tree</span>' +
+ '<shadow><span id="shd3">This is the shadow tree fallback content</span></shadow>';
+ s2.appendChild(div1);
+
+ var style = d.createElement('style');
+ style.innerHTML = ':host {display:none;}';
+ s2.appendChild(style);
+
+ assert_equals(s1.querySelector('#shd1').offsetTop, 0,
+ 'Point 1: element should not be rendered');
+
+
+}), 'A_06_00_08_T03');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/styles/test-008.html b/tests/wpt/web-platform-tests/shadow-dom/styles/test-008.html
new file mode 100644
index 00000000000..a248333b374
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/styles/test-008.html
@@ -0,0 +1,96 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_06_00_09</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#styles">
+<meta name="assert" content="Styles:the styles of the shadow host are inherited by the children of the shadow root">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(unit(function (ctx) {
+ var d = newRenderedHTMLDocument(ctx);
+
+ d.body.innerHTML = '' +
+ '<div id="shHost" style="font-size:10px">' +
+ '<span id="spn1">This is a shadow host child</span>' +
+ '</div>';
+
+ var host = d.querySelector('#shHost');
+
+ var s = host.createShadowRoot();
+
+ var div = d.createElement('div');
+ div.innerHTML ='<span id="spn2">This is a shadow root child</span>';
+ s.appendChild(div);
+
+ assert_equals(d.querySelector('#spn1').offsetTop, 0,
+ 'Element should not be rendered');
+ assert_true(s.querySelector('#spn2').offsetTop > 0,
+ 'Element should be rendered');
+
+ var oldHeight = s.querySelector('#spn2').offsetHeight;
+
+ host.setAttribute('style', 'font-size:20px');
+
+ assert_true(s.querySelector('#spn2').offsetHeight > oldHeight,
+ 'Shadow host style must be aplied to the shadow root children');
+
+}), 'A_06_00_09_T01');
+
+
+
+
+test(unit(function (ctx) {
+ var d = newRenderedHTMLDocument(ctx);
+
+ d.body.innerHTML =
+ '<ul class="cls" style="font-size: 10px">' +
+ '<li id="li1" class="shadow">1</li>' +
+ '<li id="li2" class="shadow2">2</li>' +
+ '<li id="li3" class="shadow">3</li>' +
+ '<li id="li4">4</li>' +
+ '<li id="li5" class="shadow">5</li>' +
+ '<li id="li6" class="shadow2">6</li>' +
+ '</ul>';
+
+ var host = d.querySelector('.cls');
+ //Shadow root to play with
+ var s = host.createShadowRoot();
+
+ var div = d.createElement('div');
+ div.innerHTML ='<ul><content select=".shadow"></content></ul>';
+ s.appendChild(div);
+
+ var height1 = d.querySelector('#li1').offsetHeight;
+ var height3 = d.querySelector('#li3').offsetHeight;
+ var height5 = d.querySelector('#li5').offsetHeight;
+
+ host.setAttribute('style', 'font-size: 20px');
+
+ assert_true(d.querySelector('#li1').offsetHeight > height1,
+ 'Point 1: Shadow host style must be aplied to the shadow root children');
+ assert_true(d.querySelector('#li3').offsetHeight > height3,
+ 'Point 2: Shadow host style must be aplied to the shadow root children');
+ assert_true(d.querySelector('#li5').offsetHeight > height5,
+ 'Point 3: Shadow host style must be aplied to the shadow root children');
+
+
+}), 'A_06_00_09_T02');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/styles/test-009.html b/tests/wpt/web-platform-tests/shadow-dom/styles/test-009.html
new file mode 100644
index 00000000000..90d565b266f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/styles/test-009.html
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_06_00_10</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#styles">
+<meta name="assert" content="Styles:the styles of the insertion point nodes are inherited by those child nodes of the shadow host that are assigned to this insertion point">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(unit(function (ctx) {
+ var d = newRenderedHTMLDocument(ctx);
+
+ d.body.innerHTML =
+ '<ul class="cls" style="font-size: 10px">' +
+ '<li id="li1" class="shadow">1</li>' +
+ '<li id="li2" class="shadow2">2</li>' +
+ '<li id="li3" class="shadow">3</li>' +
+ '<li id="li4">4</li>' +
+ '<li id="li5" class="shadow">5</li>' +
+ '<li id="li6" class="shadow2">6</li>' +
+ '</ul>';
+
+
+ var height1 = d.querySelector('#li1').offsetHeight;
+ var height2 = d.querySelector('#li2').offsetHeight;
+ var height3 = d.querySelector('#li3').offsetHeight;
+ var height4 = d.querySelector('#li4').offsetHeight;
+ var height5 = d.querySelector('#li5').offsetHeight;
+ var height6 = d.querySelector('#li6').offsetHeight;
+
+ assert_true(height1 > 0, 'Point 1: Element height should be greater than zero');
+ assert_true(height2 > 0, 'Point 2: Element height should be greater than zero');
+ assert_true(height3 > 0, 'Point 3: Element height should be greater than zero');
+ assert_true(height4 > 0, 'Point 4: Element height should be greater than zero');
+ assert_true(height5 > 0, 'Point 5: Element height should be greater than zero');
+ assert_true(height6 > 0, 'Point 6: Element height should be greater than zero');
+
+ var host = d.querySelector('.cls');
+ //Shadow root to play with
+ var s = host.createShadowRoot();
+
+ var div = d.createElement('div');
+ div.innerHTML ='<ul><content select=".shadow" style="font-size:20px"></content></ul>';
+ s.appendChild(div);
+
+
+ host.setAttribute('style', 'font-size: 20px');
+
+ assert_true(d.querySelector('#li1').offsetHeight > height1,
+ 'Point 11: Insertion point style must be aplied to the node distributed into this point');
+ assert_true(d.querySelector('#li3').offsetHeight > height3,
+ 'Point 12: Insertion point style must be aplied to the node distributed into this point');
+ assert_true(d.querySelector('#li5').offsetHeight > height5,
+ 'Point 13: Insertion point style must be aplied to the node distributed into this point');
+
+}), 'A_06_00_10_T01');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/styles/test-010.html b/tests/wpt/web-platform-tests/shadow-dom/styles/test-010.html
new file mode 100644
index 00000000000..97d6e6a2406
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/styles/test-010.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_06_00_11</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#styles">
+<meta name="assert" content="Styles:the styles of the shadow insertion point node are inherited by the child nodes of the shadow root of the shadow tree, distributed to this shadow insertion point">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+// Test fails. See https://bugs.webkit.org/show_bug.cgi?id=103625
+test(unit(function (ctx) {
+ var d = newRenderedHTMLDocument(ctx);
+
+ var host = d.createElement('div');
+ d.body.appendChild(host);
+
+ //Old tree
+ var s1 = host.createShadowRoot();
+
+ var div1 = d.createElement('div');
+ div1.setAttribute('style', 'font-size: 10px');
+ div1.innerHTML = '<span id="shd1">This is an old shadow tree</span>';
+ s1.appendChild(div1);
+
+ var height1 = s1.querySelector('#shd1').offsetHeight;
+
+ assert_true(height1 > 0, 'Element height should be greater than zero');
+
+ //younger tree
+ var s2 = host.createShadowRoot();
+ var div2 = d.createElement('div');
+ div2.innerHTML = '<shadow style="font-size:20px"></shadow>';
+ s2.appendChild(div2);
+
+ assert_true(s1.querySelector('#shd1').offsetHeight > height1,
+ 'Shadow insertion point style must be aplied to the child nodes of ' +
+ 'the shadow host that are assigned to this insertion point');
+}), 'A_06_00_11_T01');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/testcommon.js b/tests/wpt/web-platform-tests/shadow-dom/testcommon.js
new file mode 100644
index 00000000000..4d01f57cd4c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/testcommon.js
@@ -0,0 +1,273 @@
+// Copyright 2012 Google Inc. All Rights Reserved.
+
+/*
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+*/
+
+"use strict";
+
+var HTML5_ELEMENT_NAMES = [
+ 'a', 'abbr', 'address', 'area', 'article', 'aside', 'audio',
+ 'b', 'base', 'bdi', 'bdo', 'blockquote', 'body', 'br', 'button',
+ 'canvas', 'caption', 'cite', 'code', 'col', 'colgroup', 'command',
+ 'datalist', 'dd', 'del', 'details', 'dfn', 'dialog', 'div', 'dl', 'dt',
+ 'em', 'embed',
+ 'fieldset', 'figcaption', 'figure', 'footer', 'form',
+ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr',
+ 'html',
+ 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'keygen',
+ 'label', 'legend', 'li', 'link',
+ 'map', 'mark', 'menu', 'meta', 'meter',
+ 'nav', 'noscript',
+ 'object', 'ol', 'optgroup', 'option', 'output',
+ 'p', 'param', 'pre', 'progress',
+ 'q',
+ 'rp', 'rt', 'ruby',
+ 's', 'samp', 'script', 'section', 'select', 'small', 'source', 'span',
+ 'strong', 'style', 'sub',
+ 'table', 'tbody', 'td', 'textarea', 'tfoot', 'th', 'thead', 'time',
+ 'title', 'tr', 'track',
+ 'u', 'ul',
+ 'var', 'video',
+ 'wbr'
+];
+
+// http://www.whatwg.org/specs/web-apps/current-work/multipage/forms.html#form-associated-element
+var HTML5_FORM_ASSOCIATED_ELEMENTS = ['button', 'fieldset', 'input', 'keygen', 'label',
+ 'object', 'output', 'select', 'textarea'];
+
+// Whether to work around vendor prefixes.
+var USE_VENDOR_SPECIFIC_WORKAROUND = true;
+
+function activateVendorSpecificWorkaround() {
+ if (Element.prototype.webkitCreateShadowRoot &&
+ !Element.prototype.createShadowRoot) {
+ Element.prototype.createShadowRoot =
+ Element.prototype.webkitCreateShadowRoot;
+
+ Object.defineProperty(Element.prototype, 'pseudo', {
+ get: function () { return this.webkitPseudo; },
+ set: function (value) { return this.webkitPseudo = value; }
+ });
+
+ Object.defineProperty(Element.prototype, 'shadowRoot', {
+ get: function () { return this.webkitShadowRoot; }
+ });
+ }
+}
+
+if (USE_VENDOR_SPECIFIC_WORKAROUND)
+ activateVendorSpecificWorkaround();
+
+// ----------------------------------------------------------------------------
+// Deprecated: The code below is preserved only for the existing tests that are
+// using it. Now vendor prefixes are handled in a way that does not require
+// manual intervention. New tests should just use unprefixed APIs and you
+// are all set.
+//
+// These functions will eventually be removed when no tests use them.
+
+function ShadowDomNotSupportedError() {
+ this.message = "Shadow DOM is not supported";
+}
+
+// To allow using of both prefixed and non-prefixed API we do
+// the following hook
+function addPrefixed(element) {
+ if (element && !element.pseudo) {
+ Object.defineProperty(element, 'pseudo', {
+ get: function () { return element.webkitPseudo; },
+ set: function (value) { return element.webkitPseudo = value; }
+ });
+ }
+}
+
+function addDocumentPrefixed(d) {
+ if (d) {
+ if (d.body) {
+ addPrefixed(d.body);
+ }
+ if (d.head) {
+ addPrefixed(d.head);
+ }
+ if (d.documentElement) {
+ addPrefixed(d.documentElement);
+ }
+ d.oldCreate = d.createElement;
+ d.createElement = function(tagName) {
+ var el = d.oldCreate(tagName);
+ addPrefixed(el);
+ return el;
+ };
+ }
+}
+
+
+function rethrowInternalErrors(e) {
+ if (e instanceof ShadowDomNotSupportedError) {
+ throw e;
+ }
+
+}
+
+function newDocument() {
+ var d = document.implementation.createDocument(
+ 'http://www.w3.org/1999/xhtml', 'html');
+ //FIXME remove the call below when non-prefixed API is used
+ addDocumentPrefixed(d);
+ return d;
+}
+
+function newHTMLDocument() {
+ var d = document.implementation.createHTMLDocument('Test Document');
+ //FIXME remove the call below when non-prefixed API is used
+ addDocumentPrefixed(d);
+ return d;
+}
+
+function newIFrame(ctx, src) {
+ if (typeof(ctx) == 'undefined' || typeof (ctx.iframes) != 'object') {
+ assert_unreached('Illegal context object in newIFrame');
+ }
+
+ var iframe = document.createElement('iframe');
+ if (!ctx.debug) {
+ iframe.style.display = 'none';
+ }
+ if (typeof(src) != 'undefined') {
+ iframe.src = src;
+ }
+ document.body.appendChild(iframe);
+ ctx.iframes.push(iframe);
+
+ assert_true(typeof(iframe.contentWindow) != 'undefined'
+ && typeof(iframe.contentWindow.document) != 'undefined'
+ && iframe.contentWindow.document != document, 'Failed to create new rendered document'
+ );
+ return iframe;
+}
+function newRenderedHTMLDocument(ctx) {
+ var frame = newIFrame(ctx);
+ var d = frame.contentWindow.document;
+ //FIXME remove the call below when non-prefixed API is used
+ addDocumentPrefixed(d);
+ return d;
+}
+
+// End deprecated.
+// ----------------------------------------------------------------------------
+
+function newContext() {
+ return {iframes:[]};
+}
+
+function cleanContext(ctx) {
+ if (!ctx.debug) {
+ ctx.iframes.forEach(function (e) {
+ e.parentNode.removeChild(e);
+ });
+ }
+}
+
+function unit(f) {
+ return function () {
+ var ctx = newContext();
+ try {
+ f(ctx);
+ } catch(e) {
+ console.log(e.getMessage());
+ } finally {
+ cleanContext(ctx);
+ }
+ }
+}
+
+function step_unit(f, ctx, t) {
+ return function () {
+ var done = false;
+ try {
+ f();
+ done = true;
+ } finally {
+ if (done) {
+ t.done();
+ }
+ cleanContext(ctx);
+ }
+ }
+}
+
+function assert_nodelist_contents_equal_noorder(actual, expected, message) {
+ assert_equals(actual.length, expected.length, message);
+ var used = [];
+ for (var i = 0; i < expected.length; i++) {
+ used.push(false);
+ }
+ for (i = 0; i < expected.length; i++) {
+ var found = false;
+ for (var j = 0; j < actual.length; j++) {
+ if (used[j] == false && expected[i] == actual[j]) {
+ used[j] = true;
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ assert_unreached(message + ". Fail reason: element not found: " + expected[i]);
+ }
+ }
+}
+
+
+//Example taken from http://www.w3.org/TR/shadow-dom/#event-retargeting-example
+function createTestMediaPlayer(d) {
+ d.body.innerHTML = '' +
+ '<div id="player">' +
+ '<input type="checkbox" id="outside-control">' +
+ '<div id="player-shadow-root">' +
+ '</div>' +
+ '</div>';
+
+ var playerShadowRoot = d.querySelector('#player-shadow-root').createShadowRoot();
+ playerShadowRoot.innerHTML = '' +
+ '<div id="controls">' +
+ '<button class="play-button">PLAY</button>' +
+ '<input type="range" id="timeline">' +
+ '<div id="timeline-shadow-root">' +
+ '</div>' +
+ '</input>' +
+ '<div class="volume-slider-container" id="volume-slider-container">' +
+ '<input type="range" class="volume-slider" id="volume-slider">' +
+ '<div id="volume-shadow-root">' +
+ '</div>' +
+ '</input>' +
+ '</div>' +
+ '</div>';
+
+ var timeLineShadowRoot = playerShadowRoot.querySelector('#timeline-shadow-root').createShadowRoot();
+ timeLineShadowRoot.innerHTML = '<div class="slider-thumb" id="timeline-slider-thumb"></div>';
+
+ var volumeShadowRoot = playerShadowRoot.querySelector('#volume-shadow-root').createShadowRoot();
+ volumeShadowRoot.innerHTML = '<div class="slider-thumb" id="volume-slider-thumb"></div>';
+
+ return {
+ 'playerShadowRoot': playerShadowRoot,
+ 'timeLineShadowRoot': timeLineShadowRoot,
+ 'volumeShadowRoot': volumeShadowRoot
+ };
+}
+
+//FIXME This call of initKeyboardEvent works for WebKit-only.
+//See https://bugs.webkit.org/show_bug.cgi?id=16735
+// and https://bugs.webkit.org/show_bug.cgi?id=13368. Add check for browser here
+function fireKeyboardEvent(doc, element, key) {
+ var event = doc.createEvent('KeyboardEvent');
+ event.initKeyboardEvent("keydown", true, true, doc.defaultView, key, 0, false, false, false, false);
+ element.dispatchEvent(event);
+}
diff --git a/tests/wpt/web-platform-tests/shadow-dom/user-interaction/active-element/test-001.html b/tests/wpt/web-platform-tests/shadow-dom/user-interaction/active-element/test-001.html
new file mode 100644
index 00000000000..8643959917c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/user-interaction/active-element/test-001.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_07_03_01</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#active-element">
+<meta name="assert" content="User Interaction: each shadow root must also have an activeElement property to store the value of the focused element in the shadow tree.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(unit(function (ctx) {
+ var d = newRenderedHTMLDocument(ctx);
+
+ var host = d.createElement('div');
+ d.body.appendChild(host);
+ var s = host.createShadowRoot();
+
+ var inp = d.createElement('input');
+ inp.setAttribute('type', 'text');
+ inp.setAttribute('id', 'inpId');
+ inp.setAttribute('value', 'Some text');
+ s.appendChild(inp);
+
+ inp.focus();
+
+ assert_equals(s.activeElement.tagName, 'INPUT', 'Point 1:activeElement property of shadow root ' +
+ 'must return the value of the focused element in the shadow tree');
+ assert_equals(s.activeElement.getAttribute('id'), 'inpId', 'Point 2:activeElement property of shadow root ' +
+ 'must return the value of the focused element in the shadow tree');
+
+}), 'A_07_03_01_T01');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/user-interaction/active-element/test-002.html b/tests/wpt/web-platform-tests/shadow-dom/user-interaction/active-element/test-002.html
new file mode 100644
index 00000000000..80382085a8e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/user-interaction/active-element/test-002.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_07_03_02</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#active-element">
+<meta name="assert" content="User Interaction: Document's activeElement property must be adjusted">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(unit(function (ctx) {
+ var d = newRenderedHTMLDocument(ctx);
+
+ var host = d.createElement('div');
+ host.setAttribute('id', 'shRoot');
+ d.body.appendChild(host);
+ var s = host.createShadowRoot();
+
+ var inp = d.createElement('input');
+ inp.setAttribute('type', 'text');
+ inp.setAttribute('id', 'inpId');
+ inp.setAttribute('value', 'Some text');
+ s.appendChild(inp);
+
+ inp.focus();
+
+ assert_equals(d.activeElement.tagName, 'DIV', 'Point 1: document\'s activeElement property ' +
+ 'must return adjusted the value of the focused element in the shadow tree');
+ assert_equals(d.activeElement.getAttribute('id'), 'shRoot', 'Point 2: document\'s activeElement property ' +
+ 'must return adjusted the value of the focused element in the shadow tree');
+
+}), 'A_07_03_02_T01');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/user-interaction/editing/inheritance-of-content-editable-001.html b/tests/wpt/web-platform-tests/shadow-dom/user-interaction/editing/inheritance-of-content-editable-001.html
new file mode 100644
index 00000000000..992a036a8a4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/user-interaction/editing/inheritance-of-content-editable-001.html
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: Inheritance of contentEditable attribute</title>
+<link rel="author" title="Moto Ishizawa" href="mailto:summerwind.jp@gmail.com">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#editing">
+<meta name="assert" content="User Interaction: Shadow trees must not be propagated contentEditable attribute from shadow host">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(unit(function (ctx) {
+ var d = newRenderedHTMLDocument(ctx);
+
+ var host = d.createElement('div');
+ host.contentEditable = "true";
+ d.body.appendChild(host);
+
+ var s = host.createShadowRoot();
+
+ assert_equals(host.contentEditable, "true");
+ assert_equals(s.contentEditable, undefined);
+}), 'contentEditable of shadow trees must be undefined when contentEditable attribute of shadow host is "true"');
+
+test(unit(function (ctx) {
+ var d = newRenderedHTMLDocument(ctx);
+
+ var host = d.createElement('div');
+ host.contentEditable = "false";
+ d.body.appendChild(host);
+
+ var s = host.createShadowRoot();
+
+ assert_equals(host.contentEditable, 'false');
+ assert_equals(s.contentEditable, undefined);
+}), 'contentEditable of shadow trees must be undefined when contentEditable of shadow host is "false"');
+
+test(unit(function (ctx) {
+ var d = newRenderedHTMLDocument(ctx);
+
+ var host = d.createElement('div');
+ d.body.appendChild(host);
+ d.body.contentEditable = "true";
+
+ var s = host.createShadowRoot();
+
+ assert_equals(host.contentEditable, 'inherit');
+ assert_equals(s.contentEditable, undefined);
+}), 'contentEditable of shadow trees must be undefined when contentEditable attribute of shadow host is "inherit"');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/user-interaction/focus-navigation/test-001.html b/tests/wpt/web-platform-tests/shadow-dom/user-interaction/focus-navigation/test-001.html
new file mode 100644
index 00000000000..d26563b2389
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/user-interaction/focus-navigation/test-001.html
@@ -0,0 +1,86 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_07_02_01</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#focus-navigation">
+<meta name="assert" content="User Interaction: The navigation order within a shadow tree must be computed as a list of focusable elements in tree order as-rendered">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_07_02_01_T01 = async_test('A_07_02_01_T01');
+
+A_07_02_01_T01.step(unit(function (ctx) {
+
+ var counter = 0;
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var chb1 = d.createElement('input');
+ chb1.setAttribute('type', 'checkbox');
+ chb1.setAttribute('id', 'chb1');
+ chb1.addEventListener('focus', A_07_02_01_T01.step_func(function(event) {
+ assert_equals(counter++, 0, 'Point 1: wrong focus navigation order');
+ }), false);
+ d.body.appendChild(chb1);
+
+ var host = d.createElement('div');
+ d.body.appendChild(host);
+ var s = host.createShadowRoot();
+
+ var inp1 = d.createElement('input');
+ inp1.setAttribute('type', 'text');
+ inp1.setAttribute('id', 'shInp1');
+ inp1.setAttribute('value', 'Input 1');
+ inp1.addEventListener('focus', A_07_02_01_T01.step_func(function(event) {
+ assert_equals(counter++, 1, 'Point 2: wrong focus navigation order');
+ }), false);
+ s.appendChild(inp1);
+
+ var inp2 = d.createElement('input');
+ inp2.setAttribute('type', 'text');
+ inp2.setAttribute('id', 'shInp2');
+ inp2.setAttribute('value', 'Input 2');
+ inp2.addEventListener('focus', A_07_02_01_T01.step_func(function(event) {
+ assert_equals(counter++, 2, 'Point 3: wrong focus navigation order');
+ }), false);
+ s.appendChild(inp2);
+
+ var chb2 = d.createElement('input');
+ chb2.setAttribute('type', 'checkbox');
+ chb2.setAttribute('id', 'chb2');
+ chb2.addEventListener('focus', A_07_02_01_T01.step_func(function(event) {
+ assert_equals(counter++, 3, 'Point 4: wrong focus navigation order');
+ }), false);
+ d.body.appendChild(chb2);
+
+ chb1.focus();
+
+ //simulate TAB clicks
+ fireKeyboardEvent(d, chb1, 'U+0009');
+
+ fireKeyboardEvent(d, inp1, 'U+0009');
+
+ fireKeyboardEvent(d, inp2, 'U+0009');
+
+ fireKeyboardEvent(d, chb2, 'U+0009');
+
+ A_07_02_01_T01.done();
+}));
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/user-interaction/focus-navigation/test-002.html b/tests/wpt/web-platform-tests/shadow-dom/user-interaction/focus-navigation/test-002.html
new file mode 100644
index 00000000000..2fa3e4eb9ec
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/user-interaction/focus-navigation/test-002.html
@@ -0,0 +1,238 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_07_02_02</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#focus-navigation">
+<meta name="assert" content="User Interaction: The navigation order within a shadow tree must be computed as a list of focusable elements in tree order as-rendered with the exception of any elements, distributed its insertion points, and is called shadow DOM navigation order.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_07_02_02_T01 = async_test('A_07_02_02_T01');
+var A_07_02_02_T02 = async_test('A_07_02_02_T02');
+
+A_07_02_02_T01.step(unit(function (ctx) {
+
+ var counter = 0;
+
+ var expectations = [];
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var host = d.createElement('div');
+ d.body.appendChild(host);
+
+ var chb1 = d.createElement('input');
+ chb1.setAttribute('type', 'checkbox');
+ chb1.setAttribute('id', 'chb1');
+ chb1.addEventListener('focus', A_07_02_02_T01.step_func(function(event) {
+ assert_true(false, 'Element shouldn\'t be rendered');
+ }), false);
+ host.appendChild(chb1);
+
+ var chb2 = d.createElement('input');
+ chb2.setAttribute('type', 'checkbox');
+ chb2.setAttribute('id', 'chb2');
+ chb2.setAttribute('class', 'shadow');
+ chb2.addEventListener('focus', A_07_02_02_T01.step_func(function(event) {
+ assert_equals(counter++, 0, 'Point 1: wrong focus navigation order');
+ expectations[1] = true;
+ }), false);
+ expectations[1] = false;
+ host.appendChild(chb2);
+
+ var chb3 = d.createElement('input');
+ chb3.setAttribute('type', 'checkbox');
+ chb3.setAttribute('id', 'chb3');
+ chb3.setAttribute('class', 'shadow');
+ chb3.addEventListener('focus', A_07_02_02_T01.step_func(function(event) {
+ assert_equals(counter++, 1, 'Point 2: wrong focus navigation order');
+ expectations[2] = true;
+ }), false);
+ expectations[2] = false;
+ host.appendChild(chb3);
+
+ var s = host.createShadowRoot();
+
+ var div = d.createElement('div');
+ div.innerHTML = '<content select=".shadow"></content>';
+ s.appendChild(div);
+
+ var inp1 = d.createElement('input');
+ inp1.setAttribute('type', 'text');
+ inp1.setAttribute('id', 'shInp1');
+ inp1.setAttribute('value', 'Input 1');
+ inp1.addEventListener('focus', A_07_02_02_T01.step_func(function(event) {
+ expectations[3] = false;
+ }), false);
+ expectations[3] = true;
+ s.appendChild(inp1);
+
+ var inp2 = d.createElement('input');
+ inp2.setAttribute('type', 'text');
+ inp2.setAttribute('id', 'shInp2');
+ inp2.setAttribute('value', 'Input 2');
+ inp2.addEventListener('focus', A_07_02_02_T01.step_func(function(event) {
+ expectations[4] = false;
+ }), false);
+ expectations[4] = true;
+ s.appendChild(inp2);
+
+ var chb4 = d.createElement('input');
+ chb4.setAttribute('type', 'checkbox');
+ chb4.setAttribute('id', 'chb4');
+ chb4.addEventListener('focus', A_07_02_02_T01.step_func(function(event) {
+ assert_equals(counter++, 2, 'Point 5: wrong focus navigation order');
+ expectations[5] = true;
+ }), false);
+ expectations[5] = false;
+ d.body.appendChild(chb4);
+
+ chb2.focus();
+
+ //simulate TAB clicks
+ fireKeyboardEvent(d, chb2, 'U+0009');
+
+ fireKeyboardEvent(d, chb3, 'U+0009');
+
+ fireKeyboardEvent(d, inp1, 'U+0009');
+
+ fireKeyboardEvent(d, inp2, 'U+0009');
+
+ fireKeyboardEvent(d, chb4, 'U+0009');
+
+ for (var i = 1; i < expectations.length; i++) {
+ if (!expectations[i]) {
+ assert_true(false, 'Point ' + i + ' event listener was not invoked');
+ }
+ }
+
+ A_07_02_02_T01.done();
+}));
+
+
+
+A_07_02_02_T02.step(unit(function (ctx) {
+
+ var counter = 0;
+
+ var expectations = [];
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var chb0 = d.createElement('input');
+ chb0.setAttribute('type', 'checkbox');
+ chb0.setAttribute('id', 'chb0');
+ d.body.appendChild(chb0);
+
+
+ var host = d.createElement('div');
+ d.body.appendChild(host);
+
+ var chb1 = d.createElement('input');
+ chb1.setAttribute('type', 'checkbox');
+ chb1.setAttribute('id', 'chb1');
+ chb1.addEventListener('focus', A_07_02_02_T02.step_func(function(event) {
+ assert_true(false, 'Element shouldn\'t be rendered');
+ }), false);
+ host.appendChild(chb1);
+
+ var chb2 = d.createElement('input');
+ chb2.setAttribute('type', 'checkbox');
+ chb2.setAttribute('id', 'chb2');
+ chb2.setAttribute('class', 'shadow');
+ chb2.addEventListener('focus', A_07_02_02_T02.step_func(function(event) {
+ assert_equals(counter++, 2, 'Point 3: wrong focus navigation order');
+ expectations[1] = true;
+ }), false);
+ expectations[1] = false;
+ host.appendChild(chb2);
+
+ var chb3 = d.createElement('input');
+ chb3.setAttribute('type', 'checkbox');
+ chb3.setAttribute('id', 'chb3');
+ chb3.setAttribute('class', 'shadow');
+ chb3.addEventListener('focus', A_07_02_02_T02.step_func(function(event) {
+ assert_equals(counter++, 3, 'Point 4: wrong focus navigation order');
+ expectations[2] = true;
+ }), false);
+ expectations[2] = false;
+ host.appendChild(chb3);
+
+ var s = host.createShadowRoot();
+
+ var div = d.createElement('div');
+ div.innerHTML = '<content select=".shadow"></content>';
+ s.appendChild(div);
+
+ var inp1 = d.createElement('input');
+ inp1.setAttribute('type', 'text');
+ inp1.setAttribute('id', 'shInp1');
+ inp1.setAttribute('value', 'Input 1');
+ inp1.addEventListener('focus', A_07_02_02_T02.step_func(function(event) {
+ assert_equals(counter++, 0, 'Point 1: wrong focus navigation order');
+
+ expectations[3] = true;
+ }), false);
+ expectations[3] = false;
+ s.appendChild(inp1);
+
+ var inp2 = d.createElement('input');
+ inp2.setAttribute('type', 'text');
+ inp2.setAttribute('id', 'shInp2');
+ inp2.setAttribute('value', 'Input 2');
+ inp2.addEventListener('focus', A_07_02_02_T02.step_func(function(event) {
+ assert_equals(counter++, 1, 'Point 2: wrong focus navigation order');
+ expectations[4] = true;
+ }), false);
+ expectations[4] = false;
+ s.appendChild(inp2);
+
+ var chb4 = d.createElement('input');
+ chb4.setAttribute('type', 'checkbox');
+ chb4.setAttribute('id', 'chb4');
+ chb4.addEventListener('focus', A_07_02_02_T02.step_func(function(event) {
+ assert_equals(counter++, 4, 'Point 5: wrong focus navigation order');
+ expectations[5] = true;
+ }), false);
+ expectations[5] = false;
+ d.body.appendChild(chb4);
+
+ chb0.focus();
+
+ //simulate TAB clicks
+ fireKeyboardEvent(d, inp1, 'U+0009');
+
+ fireKeyboardEvent(d, inp2, 'U+0009');
+
+ fireKeyboardEvent(d, chb2, 'U+0009');
+
+ fireKeyboardEvent(d, chb3, 'U+0009');
+
+ fireKeyboardEvent(d, chb4, 'U+0009');
+
+ for (var i = 1; i < expectations.length; i++) {
+ if (!expectations[i]) {
+ assert_true(false, 'Point ' + i + ' event listener was not invoked');
+ }
+ }
+
+ A_07_02_02_T02.done();
+}));
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/user-interaction/focus-navigation/test-003.html b/tests/wpt/web-platform-tests/shadow-dom/user-interaction/focus-navigation/test-003.html
new file mode 100644
index 00000000000..1abd9e4d373
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/user-interaction/focus-navigation/test-003.html
@@ -0,0 +1,237 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_07_02_03</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#focus-navigation">
+<meta name="assert" content="User Interaction: For sequential focus navigation, the shadow DOM navigation order sequence must be inserted into the document navigation order in place of the shadow host as if the shadow host were assigned the value of auto for determining its position and shadow host is not focusable">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_07_02_03_T01 = async_test('A_07_02_03_T01');
+
+A_07_02_03_T01.step(unit(function (ctx) {
+
+ var counter = 0;
+
+ var invoked = [];
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var chb1 = d.createElement('input');
+ chb1.setAttribute('type', 'checkbox');
+ // TODO according CSS3 nav-index is a replacement for tabindex
+ //chb1.setAttribute('nav-index', '4');
+ chb1.setAttribute('tabindex', '4');
+ chb1.setAttribute('id', 'chb1');
+ chb1.addEventListener('focus', A_07_02_03_T01.step_func(function(event) {
+ assert_equals(counter++, 1, 'Point 1: wrong focus navigation order');
+ invoked[1] = true;
+ }), false);
+ invoked[1] = false;
+ d.body.appendChild(chb1);
+
+ var host = d.createElement('div');
+ d.body.appendChild(host);
+ var s = host.createShadowRoot();
+
+ var inp1 = d.createElement('input');
+ inp1.setAttribute('type', 'text');
+ inp1.setAttribute('id', 'shInp1');
+ //inp1.setAttribute('nav-index', '3');
+ inp1.setAttribute('tabindex', '3');
+ inp1.setAttribute('value', 'Input 1');
+ inp1.addEventListener('focus', A_07_02_03_T01.step_func(function(event) {
+ assert_equals(counter++, 4, 'Point 2: wrong focus navigation order');
+ invoked[2] = true;
+ }), false);
+ invoked[2] = false;
+ s.appendChild(inp1);
+
+ var inp2 = d.createElement('input');
+ inp2.setAttribute('type', 'text');
+ inp2.setAttribute('id', 'shInp2');
+ //inp2.setAttribute('nav-index', '2');
+ inp2.setAttribute('tabindex', '2');
+ inp2.setAttribute('value', 'Input 2');
+ inp2.addEventListener('focus', A_07_02_03_T01.step_func(function(event) {
+ assert_equals(counter++, 3, 'Point 3: wrong focus navigation order');
+ invoked[3] = true;
+ }), false);
+ invoked[3] = false;
+ s.appendChild(inp2);
+
+ var chb2 = d.createElement('input');
+ chb2.setAttribute('type', 'checkbox');
+ chb2.setAttribute('id', 'chb2');
+ //chb2.setAttribute('nav-index', '1');
+ chb2.setAttribute('tabindex', '1');
+ chb2.addEventListener('focus', A_07_02_03_T01.step_func(function(event) {
+ assert_equals(counter++, 0, 'Point 4: wrong focus navigation order');
+ invoked[4] = true;
+ }), false);
+ invoked[4] = false;
+ d.body.appendChild(chb2);
+
+ var chb3 = d.createElement('input');
+ chb3.setAttribute('type', 'checkbox');
+ chb3.setAttribute('id', 'chb3');
+ //chb3.setAttribute('nav-index', '5');
+ chb3.setAttribute('tabindex', '5');
+ chb3.addEventListener('focus', A_07_02_03_T01.step_func(function(event) {
+ assert_equals(counter++, 2, 'Point 5: wrong focus navigation order');
+ invoked[5] = true;
+ }), false);
+ invoked[5] = false;
+ d.body.appendChild(chb3);
+
+ chb2.focus();
+
+ //simulate TAB clicks. Expected order: chb2, chb1, chb3, inp2, inp1
+ fireKeyboardEvent(d, chb2, 'U+0009');
+
+ fireKeyboardEvent(d, chb1, 'U+0009');
+
+ fireKeyboardEvent(d, chb3, 'U+0009');
+
+ fireKeyboardEvent(d, inp2, 'U+0009');
+
+ fireKeyboardEvent(d, inp1, 'U+0009');
+
+ for (var i = 1; i < invoked.length; i++) {
+ if (!invoked[i]) {
+ assert_true(false, 'Piont ' + i + ' event listener was not invoked');
+ }
+ }
+
+ A_07_02_03_T01.done();
+}));
+
+// test nodes, distributed into insertion points
+var A_07_02_03_T02 = async_test('A_07_02_03_T02');
+
+A_07_02_03_T02.step(unit(function (ctx) {
+
+ var counter = 0;
+
+ var invoked = [];
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var host = d.createElement('div');
+ d.body.appendChild(host);
+
+ var chb1 = d.createElement('input');
+ chb1.setAttribute('type', 'checkbox');
+ chb1.setAttribute('id', 'chb1');
+ chb1.setAttribute('tabindex', '1');
+ chb1.addEventListener('focus', A_07_02_03_T02.step_func(function(event) {
+ assert_equals(counter++, 0, 'Point 1: wrong focus navigation order');
+ invoked[1] = true;
+ }), false);
+ invoked[1] = false;
+ d.body.appendChild(chb1);
+
+ var chb2 = d.createElement('input');
+ chb2.setAttribute('type', 'checkbox');
+ chb2.setAttribute('id', 'chb2');
+ chb2.setAttribute('class', 'shadow');
+ chb2.setAttribute('tabindex', '3');
+ chb2.addEventListener('focus', A_07_02_03_T02.step_func(function(event) {
+ assert_equals(counter++, 2, 'Point 2: wrong focus navigation order');
+ invoked[2] = true;
+ }), false);
+ invoked[2] = false;
+ host.appendChild(chb2);
+
+ var chb3 = d.createElement('input');
+ chb3.setAttribute('type', 'checkbox');
+ chb3.setAttribute('id', 'chb3');
+ chb3.setAttribute('class', 'shadow');
+ chb3.setAttribute('tabindex', '2');
+ chb3.addEventListener('focus', A_07_02_03_T02.step_func(function(event) {
+ assert_equals(counter++, 1, 'Point 3: wrong focus navigation order');
+ invoked[3] = true;
+ }), false);
+ invoked[3] = false;
+ host.appendChild(chb3);
+
+ var s = host.createShadowRoot();
+
+ var div = d.createElement('div');
+ div.innerHTML = '<content select=".shadow"></content>';
+ s.appendChild(div);
+
+ var inp1 = d.createElement('input');
+ inp1.setAttribute('type', 'text');
+ inp1.setAttribute('id', 'shInp1');
+ inp1.setAttribute('value', 'Input 1');
+ inp1.setAttribute('tabindex', '4');
+ inp1.addEventListener('focus', A_07_02_03_T02.step_func(function(event) {
+ assert_equals(counter++, 4, 'Point 4: wrong focus navigation order');
+ invoked[4] = true;
+ }), false);
+ invoked[4] = false;
+ s.appendChild(inp1);
+
+ var inp2 = d.createElement('input');
+ inp2.setAttribute('type', 'text');
+ inp2.setAttribute('id', 'shInp2');
+ inp2.setAttribute('value', 'Input 2');
+ inp2.setAttribute('tabindex', '5');
+ inp2.addEventListener('focus', A_07_02_03_T02.step_func(function(event) {
+ assert_equals(counter++, 5, 'Point 5: wrong focus navigation order');
+ invoked[5] = true;
+ }), false);
+ invoked[5] = false;
+ s.appendChild(inp2);
+
+ var chb4 = d.createElement('input');
+ chb4.setAttribute('type', 'checkbox');
+ chb4.setAttribute('id', 'chb4');
+ chb4.setAttribute('tabindex', '6');
+ chb4.addEventListener('focus', A_07_02_03_T02.step_func(function(event) {
+ assert_equals(counter++, 3, 'Point 6: wrong focus navigation order');
+ invoked[6] = true;
+ }), false);
+ invoked[6] = false;
+ d.body.appendChild(chb4);
+
+ chb1.focus();
+
+ //simulate TAB clicks
+ //Expected order: chb1, chb3, chb2, chb4, inp1, inp2
+ fireKeyboardEvent(d, chb1, 'U+0009');
+ fireKeyboardEvent(d, chb3, 'U+0009');
+ fireKeyboardEvent(d, chb2, 'U+0009');
+ fireKeyboardEvent(d, chb4, 'U+0009');
+ fireKeyboardEvent(d, inp1, 'U+0009');
+ fireKeyboardEvent(d, inp2, 'U+0009');
+
+
+
+ for (var i = 1; i < invoked.length; i++) {
+ if (!invoked[i]) {
+ assert_true(false, 'Piont ' + i + ' event listener was not invoked');
+ }
+ }
+
+ A_07_02_03_T02.done();
+}));
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/user-interaction/focus-navigation/test-004.html b/tests/wpt/web-platform-tests/shadow-dom/user-interaction/focus-navigation/test-004.html
new file mode 100644
index 00000000000..0785ef2b8d1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/user-interaction/focus-navigation/test-004.html
@@ -0,0 +1,427 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_07_02_04</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#focus-navigation">
+<meta name="assert" content="User Interaction: For sequential focus navigation, the shadow DOM navigation order sequence must be inserted into the document navigation order immediately after the shadow host, if the shadow host is focusable;">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+var A_07_02_04_T01 = async_test('A_07_02_04_T01');
+
+A_07_02_04_T01.step(unit(function (ctx) {
+
+ var counter = 0;
+
+ var invoked = [];
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var chb1 = d.createElement('input');
+ chb1.setAttribute('type', 'checkbox');
+ // TODO according CSS3 nav-index is a replacement for tabindex
+ //chb1.setAttribute('nav-index', '4');
+ chb1.setAttribute('tabindex', '1');
+ chb1.setAttribute('id', 'chb1');
+ chb1.addEventListener('focus', A_07_02_04_T01.step_func(function(event) {
+ assert_equals(counter++, 0, 'Point 1: wrong focus navigation order');
+ invoked[1] = true;
+ }), false);
+ invoked[1] = false;
+ d.body.appendChild(chb1);
+
+ var host = d.createElement('div');
+ //make shadow host focusable
+ host.setAttribute('tabindex', '3');
+ d.body.appendChild(host);
+ var s = host.createShadowRoot();
+
+ var inp1 = d.createElement('input');
+ inp1.setAttribute('type', 'text');
+ inp1.setAttribute('id', 'shInp1');
+ //inp1.setAttribute('nav-index', '3');
+ inp1.setAttribute('tabindex', '2');
+ inp1.setAttribute('value', 'Input 1');
+ inp1.addEventListener('focus', A_07_02_04_T01.step_func(function(event) {
+ assert_equals(counter++, 3, 'Point 2: wrong focus navigation order');
+ invoked[2] = true;
+ }), false);
+ invoked[2] = false;
+ s.appendChild(inp1);
+
+ var inp2 = d.createElement('input');
+ inp2.setAttribute('type', 'text');
+ inp2.setAttribute('id', 'shInp2');
+ //inp2.setAttribute('nav-index', '2');
+ inp2.setAttribute('tabindex', '1');
+ inp2.setAttribute('value', 'Input 2');
+ inp2.addEventListener('focus', A_07_02_04_T01.step_func(function(event) {
+ assert_equals(counter++, 2, 'Point 3: wrong focus navigation order');
+ invoked[3] = true;
+ }), false);
+ invoked[3] = false;
+ s.appendChild(inp2);
+
+ var chb2 = d.createElement('input');
+ chb2.setAttribute('type', 'checkbox');
+ chb2.setAttribute('id', 'chb2');
+ //chb2.setAttribute('nav-index', '1');
+ chb2.setAttribute('tabindex', '2');
+ chb2.addEventListener('focus', A_07_02_04_T01.step_func(function(event) {
+ assert_equals(counter++, 1, 'Point 4: wrong focus navigation order');
+ invoked[4] = true;
+ }), false);
+ invoked[4] = false;
+ d.body.appendChild(chb2);
+
+ var chb3 = d.createElement('input');
+ chb3.setAttribute('type', 'checkbox');
+ chb3.setAttribute('id', 'chb3');
+ //chb3.setAttribute('nav-index', '5');
+ chb3.setAttribute('tabindex', '4');
+ chb3.addEventListener('focus', A_07_02_04_T01.step_func(function(event) {
+ assert_equals(counter++, 4, 'Point 5: wrong focus navigation order');
+ invoked[5] = true;
+ }), false);
+ invoked[5] = false;
+ d.body.appendChild(chb3);
+
+ chb1.focus();
+
+ //simulate TAB clicks. Expected order: chb1, chb2, inp2, inp1, chb3
+ fireKeyboardEvent(d, chb1, 'U+0009');
+
+ fireKeyboardEvent(d, chb2, 'U+0009');
+
+ fireKeyboardEvent(d, inp2, 'U+0009');
+
+ fireKeyboardEvent(d, inp1, 'U+0009');
+
+ fireKeyboardEvent(d, chb3, 'U+0009');
+
+ for (var i = 1; i < invoked.length; i++) {
+ if (!invoked[i]) {
+ assert_true(false, 'Piont ' + i + ' event listener was not invoked');
+ }
+ }
+
+ A_07_02_04_T01.done();
+}));
+
+
+
+// test nodes, distributed into insertion points
+var A_07_02_04_T02 = async_test('A_07_02_04_T02');
+
+A_07_02_04_T02.step(unit(function (ctx) {
+
+ var counter = 0;
+
+ var invoked = [];
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var host = d.createElement('div');
+ host.setAttribute('tabindex', '3');
+ d.body.appendChild(host);
+
+ var chb1 = d.createElement('input');
+ chb1.setAttribute('type', 'checkbox');
+ chb1.setAttribute('id', 'chb1');
+ chb1.setAttribute('tabindex', '1');
+ chb1.addEventListener('focus', A_07_02_04_T02.step_func(function(event) {
+ assert_equals(counter++, 0, 'Point 1: wrong focus navigation order');
+ invoked[1] = true;
+ }), false);
+ invoked[1] = false;
+ d.body.appendChild(chb1);
+
+ var chb2 = d.createElement('input');
+ chb2.setAttribute('type', 'checkbox');
+ chb2.setAttribute('id', 'chb2');
+ chb2.setAttribute('class', 'shadow');
+ chb2.setAttribute('tabindex', '3');
+ chb2.addEventListener('focus', A_07_02_04_T02.step_func(function(event) {
+ assert_equals(counter++, 4, 'Point 2: wrong focus navigation order');
+ invoked[2] = true;
+ }), false);
+ invoked[2] = false;
+ host.appendChild(chb2);
+
+ var chb3 = d.createElement('input');
+ chb3.setAttribute('type', 'checkbox');
+ chb3.setAttribute('id', 'chb3');
+ chb3.setAttribute('class', 'shadow');
+ chb3.setAttribute('tabindex', '2');
+ chb3.addEventListener('focus', A_07_02_04_T02.step_func(function(event) {
+ assert_equals(counter++, 1, 'Point 3: wrong focus navigation order');
+ invoked[3] = true;
+ }), false);
+ invoked[3] = false;
+ host.appendChild(chb3);
+
+ var s = host.createShadowRoot();
+
+ var div = d.createElement('div');
+ div.innerHTML = '<content select=".shadow"></content>';
+ s.appendChild(div);
+
+ var inp1 = d.createElement('input');
+ inp1.setAttribute('type', 'text');
+ inp1.setAttribute('id', 'shInp1');
+ inp1.setAttribute('value', 'Input 1');
+ inp1.setAttribute('tabindex', '4');
+ inp1.addEventListener('focus', A_07_02_04_T02.step_func(function(event) {
+ assert_equals(counter++, 3, 'Point 4: wrong focus navigation order');
+ invoked[4] = true;
+ }), false);
+ invoked[4] = false;
+ s.appendChild(inp1);
+
+ var inp2 = d.createElement('input');
+ inp2.setAttribute('type', 'text');
+ inp2.setAttribute('id', 'shInp2');
+ inp2.setAttribute('value', 'Input 2');
+ inp2.setAttribute('tabindex', '4');
+ inp2.addEventListener('focus', A_07_02_04_T02.step_func(function(event) {
+ assert_equals(counter++, 5, 'Point 5: wrong focus navigation order');
+ invoked[5] = true;
+ }), false);
+ invoked[5] = false;
+ d.body.appendChild(inp2);
+
+ var chb4 = d.createElement('input');
+ chb4.setAttribute('type', 'checkbox');
+ chb4.setAttribute('id', 'chb4');
+ chb4.setAttribute('tabindex', '2');
+ chb4.addEventListener('focus', A_07_02_04_T02.step_func(function(event) {
+ assert_equals(counter++, 2, 'Point 6: wrong focus navigation order');
+ invoked[6] = true;
+ }), false);
+ invoked[6] = false;
+ d.body.appendChild(chb4);
+
+ chb1.focus();
+
+ //simulate TAB clicks
+ //Expected order: chb1, chb3, chb4, chb2, inp1, inp2
+ fireKeyboardEvent(d, chb1, 'U+0009');
+ fireKeyboardEvent(d, chb3, 'U+0009');
+ fireKeyboardEvent(d, chb4, 'U+0009');
+ fireKeyboardEvent(d, chb2, 'U+0009');
+ fireKeyboardEvent(d, inp1, 'U+0009');
+ fireKeyboardEvent(d, inp2, 'U+0009');
+
+
+
+ for (var i = 1; i < invoked.length; i++) {
+ if (!invoked[i]) {
+ assert_true(false, 'Point ' + i + ' event listener was not invoked');
+ }
+ }
+
+ A_07_02_04_T02.done();
+}));
+
+
+
+// Shadow root is the first in nav order
+var A_07_02_04_T03 = async_test('A_07_02_04_T03');
+
+A_07_02_04_T03.step(unit(function (ctx) {
+
+ var counter = 0;
+
+ var invoked = [];
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var chb1 = d.createElement('input');
+ chb1.setAttribute('type', 'checkbox');
+ chb1.setAttribute('tabindex', '3');
+ chb1.setAttribute('id', 'chb1');
+ chb1.addEventListener('focus', A_07_02_04_T03.step_func(function(event) {
+ assert_equals(counter++, 4, 'Point 1: wrong focus navigation order');
+ invoked[1] = true;
+ }), false);
+ invoked[1] = false;
+ d.body.appendChild(chb1);
+
+ var host = d.createElement('div');
+ host.setAttribute('tabindex', '1');
+ d.body.appendChild(host);
+ var s = host.createShadowRoot();
+
+ var inp1 = d.createElement('input');
+ inp1.setAttribute('type', 'text');
+ inp1.setAttribute('id', 'shInp1');
+ inp1.setAttribute('tabindex', '2');
+ inp1.setAttribute('value', 'Input 1');
+ inp1.addEventListener('focus', A_07_02_04_T03.step_func(function(event) {
+ assert_equals(counter++, 1, 'Point 2: wrong focus navigation order');
+ invoked[2] = true;
+ }), false);
+ invoked[2] = false;
+ s.appendChild(inp1);
+
+ var inp2 = d.createElement('input');
+ inp2.setAttribute('type', 'text');
+ inp2.setAttribute('id', 'shInp2');
+ inp2.setAttribute('tabindex', '1');
+ inp2.setAttribute('value', 'Input 2');
+ inp2.addEventListener('focus', A_07_02_04_T03.step_func(function(event) {
+ assert_equals(counter++, 0, 'Point 3: wrong focus navigation order');
+ invoked[3] = true;
+ }), false);
+ invoked[3] = false;
+ s.appendChild(inp2);
+
+ var chb2 = d.createElement('input');
+ chb2.setAttribute('type', 'checkbox');
+ chb2.setAttribute('id', 'chb2');
+ chb2.setAttribute('tabindex', '3');
+ chb2.addEventListener('focus', A_07_02_04_T03.step_func(function(event) {
+ assert_equals(counter++, 2, 'Point 4: wrong focus navigation order');
+ invoked[4] = true;
+ }), false);
+ invoked[4] = false;
+ s.appendChild(chb2);
+
+ var chb3 = d.createElement('input');
+ chb3.setAttribute('type', 'checkbox');
+ chb3.setAttribute('id', 'chb3');
+ chb3.setAttribute('tabindex', '2');
+ chb3.addEventListener('focus', A_07_02_04_T03.step_func(function(event) {
+ assert_equals(counter++, 3, 'Point 5: wrong focus navigation order');
+ invoked[5] = true;
+ }), false);
+ invoked[5] = false;
+ d.body.appendChild(chb3);
+
+ host.focus();
+
+ //simulate TAB clicks. Expected order: inp2, inp1, chb2, chb3, chb1
+ fireKeyboardEvent(d, inp2, 'U+0009');
+ fireKeyboardEvent(d, inp1, 'U+0009');
+ fireKeyboardEvent(d, chb2, 'U+0009');
+ fireKeyboardEvent(d, chb3, 'U+0009');
+ fireKeyboardEvent(d, chb1, 'U+0009');
+
+ for (var i = 1; i < invoked.length; i++) {
+ if (!invoked[i]) {
+ assert_true(false, 'Piont ' + i + ' event listener was not invoked');
+ }
+ }
+
+ A_07_02_04_T03.done();
+}));
+
+
+//Shadow root is the last in nav order
+var A_07_02_04_T04 = async_test('A_07_02_04_T04');
+
+A_07_02_04_T04.step(unit(function (ctx) {
+
+ var counter = 0;
+
+ var invoked = [];
+
+ var d = newRenderedHTMLDocument(ctx);
+
+ var chb1 = d.createElement('input');
+ chb1.setAttribute('type', 'checkbox');
+ chb1.setAttribute('tabindex', '1');
+ chb1.setAttribute('id', 'chb1');
+ chb1.addEventListener('focus', A_07_02_04_T04.step_func(function(event) {
+ assert_equals(counter++, 0, 'Point 1: wrong focus navigation order');
+ invoked[1] = true;
+ }), false);
+ invoked[1] = false;
+ d.body.appendChild(chb1);
+
+ var host = d.createElement('div');
+ host.setAttribute('tabindex', '3');
+ d.body.appendChild(host);
+ var s = host.createShadowRoot();
+
+ var inp1 = d.createElement('input');
+ inp1.setAttribute('type', 'text');
+ inp1.setAttribute('id', 'shInp1');
+ inp1.setAttribute('tabindex', '2');
+ inp1.setAttribute('value', 'Input 1');
+ inp1.addEventListener('focus', A_07_02_04_T04.step_func(function(event) {
+ assert_equals(counter++, 3, 'Point 2: wrong focus navigation order');
+ invoked[2] = true;
+ }), false);
+ invoked[2] = false;
+ s.appendChild(inp1);
+
+ var inp2 = d.createElement('input');
+ inp2.setAttribute('type', 'text');
+ inp2.setAttribute('id', 'shInp2');
+ inp2.setAttribute('tabindex', '1');
+ inp2.setAttribute('value', 'Input 2');
+ inp2.addEventListener('focus', A_07_02_04_T04.step_func(function(event) {
+ assert_equals(counter++, 2, 'Point 3: wrong focus navigation order');
+ invoked[3] = true;
+ }), false);
+ invoked[3] = false;
+ s.appendChild(inp2);
+
+ var chb2 = d.createElement('input');
+ chb2.setAttribute('type', 'checkbox');
+ chb2.setAttribute('id', 'chb2');
+ chb2.setAttribute('tabindex', '3');
+ chb2.addEventListener('focus', A_07_02_04_T04.step_func(function(event) {
+ assert_equals(counter++, 4, 'Point 4: wrong focus navigation order');
+ invoked[4] = true;
+ }), false);
+ invoked[4] = false;
+ s.appendChild(chb2);
+
+ var chb3 = d.createElement('input');
+ chb3.setAttribute('type', 'checkbox');
+ chb3.setAttribute('id', 'chb3');
+ chb3.setAttribute('tabindex', '2');
+ chb3.addEventListener('focus', A_07_02_04_T04.step_func(function(event) {
+ assert_equals(counter++, 1, 'Point 5: wrong focus navigation order');
+ invoked[5] = true;
+ }), false);
+ invoked[5] = false;
+ d.body.appendChild(chb3);
+
+ chb1.focus();
+
+ //simulate TAB clicks. Expected order: inp2, inp1, chb2, chb3, chb1
+ fireKeyboardEvent(d, chb1, 'U+0009');
+ fireKeyboardEvent(d, chb3, 'U+0009');
+ fireKeyboardEvent(d, inp2, 'U+0009');
+ fireKeyboardEvent(d, inp1, 'U+0009');
+ fireKeyboardEvent(d, chb2, 'U+0009');
+
+ for (var i = 1; i < invoked.length; i++) {
+ if (!invoked[i]) {
+ assert_true(false, 'Piont ' + i + ' event listener was not invoked');
+ }
+ }
+
+ A_07_02_04_T04.done();
+}));
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/user-interaction/ranges-and-selections/test-001.html b/tests/wpt/web-platform-tests/shadow-dom/user-interaction/ranges-and-selections/test-001.html
new file mode 100644
index 00000000000..ef505610b4b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/user-interaction/ranges-and-selections/test-001.html
@@ -0,0 +1,80 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_07_01_01</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#ranges-and-selection">
+<meta name="assert" content="User Interaction: Selection, returned by the window.getSelection() method must never return a selection within a shadow tree">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(unit(function (ctx) {
+ var d = newRenderedHTMLDocument(ctx);
+
+ var host = d.createElement('div');
+ d.body.appendChild(host);
+ var s = host.createShadowRoot();
+
+ var span = d.createElement('span');
+ span.innerHTML = 'Some text';
+ s.appendChild(span);
+
+ var range = d.createRange();
+ range.setStart(span.firstChild, 0);
+ range.setEnd(span.firstChild, 3);
+
+ var selection = window.getSelection();
+ selection.removeAllRanges();
+ selection.addRange(range);
+
+ var sl = window.getSelection();
+ assert_equals(sl.toString(), '', 'window.getSelection() method must never return a selection ' +
+ 'within a shadow tree');
+
+}), 'A_07_07_01_T01');
+
+
+// test distributed nodes
+test(unit(function (ctx) {
+ var d = newRenderedHTMLDocument(ctx);
+
+ var host = d.createElement('div');
+ d.body.appendChild(host);
+
+ var span = d.createElement('span');
+ span.innerHTML = 'Some text';
+ host.appendChild(span);
+
+ var s = host.createShadowRoot();
+ s.innerHTML = '<content select="span"></content>';
+
+ var range = d.createRange();
+ range.setStart(span.firstChild, 0);
+ range.setEnd(span.firstChild, 3);
+
+ var selection = window.getSelection();
+ selection.removeAllRanges();
+ selection.addRange(range);
+
+ var sl = window.getSelection();
+ assert_equals(sl.toString(), '', 'window.getSelection() method must never return a selection ' +
+ 'within a shadow tree');
+
+}), 'A_07_07_01_T02');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/shadow-dom/user-interaction/ranges-and-selections/test-002.html b/tests/wpt/web-platform-tests/shadow-dom/user-interaction/ranges-and-selections/test-002.html
new file mode 100644
index 00000000000..66cea994547
--- /dev/null
+++ b/tests/wpt/web-platform-tests/shadow-dom/user-interaction/ranges-and-selections/test-002.html
@@ -0,0 +1,80 @@
+<!DOCTYPE html>
+<!--
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+-->
+<html>
+<head>
+<title>Shadow DOM Test: A_07_01_02</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#ranges-and-selection">
+<meta name="assert" content="User Interaction: The getSelection() method of the shadow root object must return the current selection in this shadow tree.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+</head>
+<body>
+<div id="log"></div>
+<script>
+test(unit(function (ctx) {
+ var d = newRenderedHTMLDocument(ctx);
+
+ var host = d.createElement('div');
+ d.body.appendChild(host);
+ var s = host.createShadowRoot();
+
+ var span = d.createElement('span');
+ span.innerHTML = 'Some text';
+ s.appendChild(span);
+
+ var range = d.createRange();
+ range.setStart(span.firstChild, 0);
+ range.setEnd(span.firstChild, 3);
+
+ var selection = window.getSelection();
+ selection.removeAllRanges();
+ selection.addRange(range);
+
+ var sl = s.getSelection();
+ assert_equals(sl.toString(), 'Som', 'The getSelection() method of the shadow root object must return ' +
+ 'the current selection in this shadow tree');
+
+}), 'A_07_01_02_T01');
+
+
+//test distributed nodes
+test(unit(function (ctx) {
+ var d = newRenderedHTMLDocument(ctx);
+
+ var host = d.createElement('div');
+ d.body.appendChild(host);
+
+ var span = d.createElement('span');
+ span.innerHTML = 'Some text';
+ host.appendChild(span);
+
+ var s = host.createShadowRoot();
+ s.innerHTML = '<content select="span"></content>';
+
+ var range = d.createRange();
+ range.setStart(span.firstChild, 0);
+ range.setEnd(span.firstChild, 3);
+
+ var selection = window.getSelection();
+ selection.removeAllRanges();
+ selection.addRange(range);
+
+ var sl = s.getSelection();
+ assert_equals(sl.toString(), 'Som', 'The getSelection() method of the shadow root object must return ' +
+ 'the current selection in this shadow tree');
+
+}), 'A_07_07_02_T02');
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/subresource-integrity/loads-scripts-with-base64-encoded-sha-digests.js b/tests/wpt/web-platform-tests/subresource-integrity/loads-scripts-with-base64-encoded-sha-digests.js
new file mode 100644
index 00000000000..8008093e353
--- /dev/null
+++ b/tests/wpt/web-platform-tests/subresource-integrity/loads-scripts-with-base64-encoded-sha-digests.js
@@ -0,0 +1 @@
+loads_scripts_with_base64_encoded_sha_digests=true; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/subresource-integrity/loads-scripts-with-correct-content-type.js b/tests/wpt/web-platform-tests/subresource-integrity/loads-scripts-with-correct-content-type.js
new file mode 100644
index 00000000000..6e4eb646f6f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/subresource-integrity/loads-scripts-with-correct-content-type.js
@@ -0,0 +1 @@
+loads_scripts_with_correct_content_type=true; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/subresource-integrity/loads-scripts-with-improper-integrity-uri-scheme.js b/tests/wpt/web-platform-tests/subresource-integrity/loads-scripts-with-improper-integrity-uri-scheme.js
new file mode 100644
index 00000000000..ccd7fd9f431
--- /dev/null
+++ b/tests/wpt/web-platform-tests/subresource-integrity/loads-scripts-with-improper-integrity-uri-scheme.js
@@ -0,0 +1 @@
+loads_scripts_with_improper_integrity_uri_scheme=true; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/subresource-integrity/loads-scripts-with-incorrect-content-type.js b/tests/wpt/web-platform-tests/subresource-integrity/loads-scripts-with-incorrect-content-type.js
new file mode 100644
index 00000000000..20dbc1acafa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/subresource-integrity/loads-scripts-with-incorrect-content-type.js
@@ -0,0 +1 @@
+loads_scripts_with_incorrect_content_type=true; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/subresource-integrity/loads-scripts-with-matching-digest.js b/tests/wpt/web-platform-tests/subresource-integrity/loads-scripts-with-matching-digest.js
new file mode 100644
index 00000000000..1f57048d90d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/subresource-integrity/loads-scripts-with-matching-digest.js
@@ -0,0 +1 @@
+loads_scripts_with_matching_digest=true; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/subresource-integrity/loads-scripts-with-non-matching-digest.js b/tests/wpt/web-platform-tests/subresource-integrity/loads-scripts-with-non-matching-digest.js
new file mode 100644
index 00000000000..24db0b83bd6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/subresource-integrity/loads-scripts-with-non-matching-digest.js
@@ -0,0 +1 @@
+loads_scripts_with_non_matching_digest=true; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/subresource-integrity/loads-scripts-with-unhyphenated-digest-name.js b/tests/wpt/web-platform-tests/subresource-integrity/loads-scripts-with-unhyphenated-digest-name.js
new file mode 100644
index 00000000000..9dee23b7dc2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/subresource-integrity/loads-scripts-with-unhyphenated-digest-name.js
@@ -0,0 +1 @@
+loads_scripts_with_unhyphenated_digest_name=true; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/subresource-integrity/loads-scripts-with-weak-digest-algorithms.js b/tests/wpt/web-platform-tests/subresource-integrity/loads-scripts-with-weak-digest-algorithms.js
new file mode 100644
index 00000000000..ebee868e52c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/subresource-integrity/loads-scripts-with-weak-digest-algorithms.js
@@ -0,0 +1 @@
+loads_scripts_with_weak_digest_algorithms=true; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/subresource-integrity/subresource-integrity.html b/tests/wpt/web-platform-tests/subresource-integrity/subresource-integrity.html
new file mode 100644
index 00000000000..74b2d17e71e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/subresource-integrity/subresource-integrity.html
@@ -0,0 +1,79 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Subresource Integrity</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+
+<script>
+ var loads_scripts_with_badly_encoded_digest;
+ var loads_scripts_with_correct_content_type;
+ var loads_scripts_with_improper_integrity_uri_scheme;
+ var loads_scripts_with_incorrect_content_type;
+ var loads_scripts_with_matching_digest;
+ var loads_scripts_with_non_matching_digest;
+ var loads_scripts_with_weak_digest_algorithms;
+</script>
+
+<!-- Should load -->
+<script src="loads-scripts-with-correct-content-type.js" integrity="ni:///sha-256;ZrrvOG-Kjz4R-FDFrfSQCQC_oMDfc0kQ3DJNd5URlrY?ct=application/javascript"></script>
+
+<!-- Shouldn't load. Correct URI is ni:///sha-256;J9PNsSFLX168LnQhGZeryaLZDmTLy_fMdx4pO-LhjW4 -->
+<script src="loads-scripts-with-improper-integrity-uri-scheme.js" integrity="wrong:///sha-256;J9PNsSFLX168LnQhGZeryaLZDmTLy_fMdx4pO-LhjW4"></script>
+
+<!-- Shouldn't load. Correct URI is ni:///sha-256;LiWoBTgUHmhVG6gn0dO9R0lBEItHgny2pnvLtBOc0tI?ct=application/javascript -->
+<script src="loads-scripts-with-incorrect-content-type.js" integrity="ni:///sha-256;LiWoBTgUHmhVG6gn0dO9R0lBEItHgny2pnvLtBOc0tI?ct=text/plain"></script>
+
+<!-- Should load -->
+<script src="loads-scripts-with-matching-digest.js" integrity="ni:///sha-256;EKclUXH9SRRUv3FmL7bIEV0z2s3EvzHFxzHKCnfHT_E"></script>
+
+<!-- Shouldn't load. Correct URI is ni:///sha-256;mmx3g0H5KnIi_lnkuMJzYK7q6ss-Wnp-7zoGvgiQVtU -->
+<script src="loads-scripts-with-non-matching-digest.js" integrity="ni:///sha-256;EKclUXH9SRRUv3FmL7bIEV0z2s3EvzHFxzHKCnfHT_E"></script>
+
+<!-- Shouldn't load. MD5 is considered to be a weak algorithm -->
+<script src="loads-scripts-with-weak-digest-algorithms.js" integrity="ni:///md5;XHzXKrCo5jhDN4BvNhs-4A"></script>
+
+<!-- Should load -->
+<script src="loads-scripts-with-base64-encoded-sha-digests.js" integrity="ni:///sha-256;+xc7GxEqWw6VtSIsI5W90RQtOrfjeGD+6WFgxZgiuOw="></script>
+
+<!-- Should load -->
+<script src="loads-scripts-with-unhyphenated-digest-name.js" integrity="ni:///sha256;ZR6E3E_G_B3WNdop4bYFtnXaj5bH02S3znD__KOC8Io"></script>
+
+
+<script>
+ function assert_undefined(actual) {
+ assert_equals(actual, undefined, "Should be undefined.");
+ }
+
+ test(function() {
+ assert_true(loads_scripts_with_correct_content_type)
+ }, "Loads scripts with correct content type");
+
+ test(function() {
+ assert_undefined(loads_scripts_with_improper_integrity_uri_scheme)
+ }, "Doesn't load scripts with improper integrity URI scheme");
+
+ test(function() {
+ assert_undefined(loads_scripts_with_incorrect_content_type)
+ }, "Doesn't load scripts with incorrect content-type");
+
+ test(function() {
+ assert_true(loads_scripts_with_matching_digest)
+ }, "Loads scripts with matching digest");
+
+ test(function() {
+ assert_undefined(loads_scripts_with_non_matching_digest)
+ }, "Doesn't load scripts with non-matching digest");
+
+ test(function() {
+ assert_undefined(loads_scripts_with_weak_digest_algorithms)
+ }, "Doesn't load scripts using weak digest algorithm");
+
+ test(function() {
+ assert_true(loads_scripts_with_base64_encoded_sha_digests)
+ }, "Loads scripts with base64 encoded sha digests");
+
+ test(function() {
+ assert_true(loads_scripts_with_unhyphenated_digest_name)
+ }, "Loads scripts with unhyphenated digest names");
+</script>
diff --git a/tests/wpt/web-platform-tests/subresource-integrity/tools/generate_javascript.py b/tests/wpt/web-platform-tests/subresource-integrity/tools/generate_javascript.py
new file mode 100644
index 00000000000..3a28dd437ad
--- /dev/null
+++ b/tests/wpt/web-platform-tests/subresource-integrity/tools/generate_javascript.py
@@ -0,0 +1,45 @@
+from os import path, listdir
+from hashlib import sha256, md5
+from base64 import urlsafe_b64encode
+import re
+
+JS_DIR = path.normpath(path.join(__file__, "..", ".."))
+
+'''
+Yield each file in the javascript directory
+'''
+def js_files():
+ for f in listdir(JS_DIR):
+ if path.isfile(f) and f.endswith(".js"):
+ yield f
+
+'''
+URL-safe base64 encode a binary digest and strip any padding.
+'''
+def format_digest(digest):
+ return urlsafe_b64encode(digest).rstrip("=")
+
+'''
+Generate an encoded sha256 URI.
+'''
+def sha256_uri(content):
+ return "ni:///sha-256;%s" % format_digest(sha256(content).digest())
+
+'''
+Generate an encoded md5 digest URI.
+'''
+def md5_uri(content):
+ return "ni:///md5;%s" % format_digest(md5(content).digest())
+
+def main():
+ for file in js_files():
+ print "Generating content for %s" % file
+ base = path.splitext(path.basename(file))[0]
+ var_name = re.sub(r"[^a-z0-9]", "_", base)
+ content = "%s=true;" % var_name
+ with open(file, "w") as f: f.write(content)
+ print "\tSHA256 integrity: %s" % sha256_uri(content)
+ print "\tMD5 integrity: %s" % md5_uri(content)
+
+if __name__ == "__main__":
+ main()
diff --git a/tests/wpt/web-platform-tests/tools/.gitmodules b/tests/wpt/web-platform-tests/tools/.gitmodules
new file mode 100644
index 00000000000..00ffb68b8e6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/.gitmodules
@@ -0,0 +1,14 @@
+[submodule "tools/wptserve"]
+ path = wptserve
+ url = https://github.com/w3c/wptserve.git
+ ignore = dirty
+[submodule "tools/pywebsocket"]
+ path = pywebsocket
+ url = https://github.com/w3c/pywebsocket.git
+ ignore = dirty
+[submodule "html5lib"]
+ path = html5lib
+ url = https://github.com/html5lib/html5lib-python.git
+[submodule "tools/six"]
+ path = six
+ url = https://github.com/jgraham/six.git
diff --git a/tests/wpt/web-platform-tests/tools/__init__.py b/tests/wpt/web-platform-tests/tools/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/__init__.py
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/.gitignore b/tests/wpt/web-platform-tests/tools/html5lib/.gitignore
new file mode 100644
index 00000000000..73d97fec073
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/.gitignore
@@ -0,0 +1,20 @@
+# Because we never want compiled Python
+__pycache__/
+*.pyc
+
+# Ignore stuff produced by distutils
+/build/
+/dist/
+/MANIFEST
+
+# Generated by parse.py -p
+stats.prof
+
+# From cover (esp. in combination with nose)
+.coverage
+
+# Because tox's data is inherently local
+/.tox/
+
+# We have no interest in built Sphinx files
+/doc/_build
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/.gitmodules b/tests/wpt/web-platform-tests/tools/html5lib/.gitmodules
new file mode 100644
index 00000000000..dbca470328d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "testdata"]
+ path = html5lib/tests/testdata
+ url = https://github.com/html5lib/html5lib-tests.git
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/.travis.yml b/tests/wpt/web-platform-tests/tools/html5lib/.travis.yml
new file mode 100644
index 00000000000..dd3130019e7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/.travis.yml
@@ -0,0 +1,37 @@
+language: python
+python:
+ - "2.6"
+ - "2.7"
+ - "3.2"
+ - "3.3"
+ - "3.4"
+ - "pypy"
+
+env:
+ - USE_OPTIONAL=true
+ - USE_OPTIONAL=false
+
+matrix:
+ exclude:
+ - python: "2.7"
+ env: USE_OPTIONAL=false
+ - python: "3.4"
+ env: USE_OPTIONAL=false
+ include:
+ - python: "2.7"
+ env: USE_OPTIONAL=false FLAKE=true
+ - python: "3.4"
+ env: USE_OPTIONAL=false FLAKE=true
+
+before_install:
+ - git submodule update --init --recursive
+
+install:
+ - bash requirements-install.sh
+
+script:
+ - nosetests
+ - bash flake8-run.sh
+
+after_script:
+ - python debug-info.py
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/AUTHORS.rst b/tests/wpt/web-platform-tests/tools/html5lib/AUTHORS.rst
new file mode 100644
index 00000000000..4148a6ed262
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/AUTHORS.rst
@@ -0,0 +1,34 @@
+Credits
+=======
+
+``html5lib`` is written and maintained by:
+
+- James Graham
+- Geoffrey Sneddon
+- Łukasz Langa
+
+
+Patches and suggestions
+-----------------------
+(In chronological order, by first commit:)
+
+- Anne van Kesteren
+- Lachlan Hunt
+- lantis63
+- Sam Ruby
+- Tim Fletcher
+- Thomas Broyer
+- Mark Pilgrim
+- Philip Taylor
+- Ryan King
+- Edward Z. Yang
+- fantasai
+- Philip Jägenstedt
+- Ms2ger
+- Andy Wingo
+- Andreas Madsack
+- Karim Valiev
+- Mohammad Taha Jahangir
+- Juan Carlos Garcia Segovia
+- Mike West
+- Marc DM
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/CHANGES.rst b/tests/wpt/web-platform-tests/tools/html5lib/CHANGES.rst
new file mode 100644
index 00000000000..1431b3c9b8f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/CHANGES.rst
@@ -0,0 +1,171 @@
+Change Log
+----------
+
+0.9999
+~~~~~~
+
+Released on XXX, 2014
+
+* XXX
+
+
+0.999
+~~~~~
+
+Released on December 23, 2013
+
+* Fix #127: add work-around for CPython issue #20007: .read(0) on
+ http.client.HTTPResponse drops the rest of the content.
+
+* Fix #115: lxml treewalker can now deal with fragments containing, at
+ their root level, text nodes with non-ASCII characters on Python 2.
+
+
+0.99
+~~~~
+
+Released on September 10, 2013
+
+* No library changes from 1.0b3; released as 0.99 as pip has changed
+ behaviour from 1.4 to avoid installing pre-release versions per
+ PEP 440.
+
+
+1.0b3
+~~~~~
+
+Released on July 24, 2013
+
+* Removed ``RecursiveTreeWalker`` from ``treewalkers._base``. Any
+ implementation using it should be moved to
+ ``NonRecursiveTreeWalker``, as everything bundled with html5lib has
+ for years.
+
+* Fix #67 so that ``BufferedStream`` to correctly returns a bytes
+ object, thereby fixing any case where html5lib is passed a
+ non-seekable RawIOBase-like object.
+
+
+1.0b2
+~~~~~
+
+Released on June 27, 2013
+
+* Removed reordering of attributes within the serializer. There is now
+ an ``alphabetical_attributes`` option which preserves the previous
+ behaviour through a new filter. This allows attribute order to be
+ preserved through html5lib if the tree builder preserves order.
+
+* Removed ``dom2sax`` from DOM treebuilders. It has been replaced by
+ ``treeadapters.sax.to_sax`` which is generic and supports any
+ treewalker; it also resolves all known bugs with ``dom2sax``.
+
+* Fix treewalker assertions on hitting bytes strings on
+ Python 2. Previous to 1.0b1, treewalkers coped with mixed
+ bytes/unicode data on Python 2; this reintroduces this prior
+ behaviour on Python 2. Behaviour is unchanged on Python 3.
+
+
+1.0b1
+~~~~~
+
+Released on May 17, 2013
+
+* Implementation updated to implement the `HTML specification
+ <http://www.whatwg.org/specs/web-apps/current-work/>`_ as of 5th May
+ 2013 (`SVN <http://svn.whatwg.org/webapps/>`_ revision r7867).
+
+* Python 3.2+ supported in a single codebase using the ``six`` library.
+
+* Removed support for Python 2.5 and older.
+
+* Removed the deprecated Beautiful Soup 3 treebuilder.
+ ``beautifulsoup4`` can use ``html5lib`` as a parser instead. Note that
+ since it doesn't support namespaces, foreign content like SVG and
+ MathML is parsed incorrectly.
+
+* Removed ``simpletree`` from the package. The default tree builder is
+ now ``etree`` (using the ``xml.etree.cElementTree`` implementation if
+ available, and ``xml.etree.ElementTree`` otherwise).
+
+* Removed the ``XHTMLSerializer`` as it never actually guaranteed its
+ output was well-formed XML, and hence provided little of use.
+
+* Removed default DOM treebuilder, so ``html5lib.treebuilders.dom`` is no
+ longer supported. ``html5lib.treebuilders.getTreeBuilder("dom")`` will
+ return the default DOM treebuilder, which uses ``xml.dom.minidom``.
+
+* Optional heuristic character encoding detection now based on
+ ``charade`` for Python 2.6 - 3.3 compatibility.
+
+* Optional ``Genshi`` treewalker support fixed.
+
+* Many bugfixes, including:
+
+ * #33: null in attribute value breaks XML AttValue;
+
+ * #4: nested, indirect descendant, <button> causes infinite loop;
+
+ * `Google Code 215
+ <http://code.google.com/p/html5lib/issues/detail?id=215>`_: Properly
+ detect seekable streams;
+
+ * `Google Code 206
+ <http://code.google.com/p/html5lib/issues/detail?id=206>`_: add
+ support for <video preload=...>, <audio preload=...>;
+
+ * `Google Code 205
+ <http://code.google.com/p/html5lib/issues/detail?id=205>`_: add
+ support for <video poster=...>;
+
+ * `Google Code 202
+ <http://code.google.com/p/html5lib/issues/detail?id=202>`_: Unicode
+ file breaks InputStream.
+
+* Source code is now mostly PEP 8 compliant.
+
+* Test harness has been improved and now depends on ``nose``.
+
+* Documentation updated and moved to http://html5lib.readthedocs.org/.
+
+
+0.95
+~~~~
+
+Released on February 11, 2012
+
+
+0.90
+~~~~
+
+Released on January 17, 2010
+
+
+0.11.1
+~~~~~~
+
+Released on June 12, 2008
+
+
+0.11
+~~~~
+
+Released on June 10, 2008
+
+
+0.10
+~~~~
+
+Released on October 7, 2007
+
+
+0.9
+~~~
+
+Released on March 11, 2007
+
+
+0.2
+~~~
+
+Released on January 8, 2007
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/CONTRIBUTING.rst b/tests/wpt/web-platform-tests/tools/html5lib/CONTRIBUTING.rst
new file mode 100644
index 00000000000..8c5e198535d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/CONTRIBUTING.rst
@@ -0,0 +1,60 @@
+Contributing
+============
+
+Pull requests are more than welcome — both to the library and to the
+documentation. Some useful information:
+
+- We aim to follow PEP 8 in the library, but ignoring the
+ 79-character-per-line limit, instead following a soft limit of 99,
+ but allowing lines over this where it is the readable thing to do.
+
+- We aim to follow PEP 257 for all docstrings, and make them properly
+ parseable by Sphinx while generating API documentation.
+
+- We keep ``pyflakes`` reporting no errors or warnings at all times.
+
+- We keep the master branch passing all tests at all times on all
+ supported versions.
+
+`Travis CI <https://travis-ci.org/html5lib/html5lib-python/>`_ is run
+against all pull requests and should enforce all of the above.
+
+We use `Opera Critic <https://critic.hoppipolla.co.uk/>`_ as an external
+code-review tool, which uses your GitHub login to authenticate. You'll
+get email notifications for issues raised in the review.
+
+
+Patch submission guidelines
+---------------------------
+
+- **Create a new Git branch specific to your change.** Do not put
+ multiple fixes/features in the same pull request. If you find an
+ unrelated bug, create a distinct branch and submit a separate pull
+ request for the bugfix. This makes life much easier for maintainers
+ and will speed up merging your patches.
+
+- **Write a test** whenever possible. Following existing tests is often
+ easiest, and a good way to tell whether the feature you're modifying
+ is easily testable.
+
+- **Make sure documentation is updated.** Keep docstrings current, and
+ if necessary, update the Sphinx documentation in ``doc/``.
+
+- **Add a changelog entry** at the top of ``CHANGES.rst`` following
+ existing entries' styles.
+
+- **Run tests with tox** if possible, to make sure your changes are
+ compatible with all supported Python versions.
+
+- **Squash commits** before submitting the pull request so that a single
+ commit contains the entire change, and only that change (see the first
+ bullet).
+
+- **Don't rebase after creating the pull request.** Merge with upstream,
+ if necessary, and use ``git commit --fixup`` for fixing issues raised
+ in a Critic review or by a failing Travis build. The reviewer will
+ squash and rebase your pull request while accepting it. Even though
+ GitHub won't recognize the pull request as accepted, the squashed
+ commits will properly specify you as the author.
+
+- **Attribute yourself** in ``AUTHORS.rst``.
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/LICENSE b/tests/wpt/web-platform-tests/tools/html5lib/LICENSE
new file mode 100644
index 00000000000..c87fa7a0006
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2006-2013 James Graham and other contributors
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/MANIFEST.in b/tests/wpt/web-platform-tests/tools/html5lib/MANIFEST.in
new file mode 100644
index 00000000000..1edd0b7deea
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/MANIFEST.in
@@ -0,0 +1,6 @@
+include LICENSE
+include CHANGES.rst
+include README.rst
+include requirements*.txt
+graft html5lib/tests/testdata
+recursive-include html5lib/tests *.py
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/README.rst b/tests/wpt/web-platform-tests/tools/html5lib/README.rst
new file mode 100644
index 00000000000..9e0a0f74048
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/README.rst
@@ -0,0 +1,157 @@
+html5lib
+========
+
+.. image:: https://travis-ci.org/html5lib/html5lib-python.png?branch=master
+ :target: https://travis-ci.org/html5lib/html5lib-python
+
+html5lib is a pure-python library for parsing HTML. It is designed to
+conform to the WHATWG HTML specification, as is implemented by all major
+web browsers.
+
+
+Usage
+-----
+
+Simple usage follows this pattern:
+
+.. code-block:: python
+
+ import html5lib
+ with open("mydocument.html", "rb") as f:
+ document = html5lib.parse(f)
+
+or:
+
+.. code-block:: python
+
+ import html5lib
+ document = html5lib.parse("<p>Hello World!")
+
+By default, the ``document`` will be an ``xml.etree`` element instance.
+Whenever possible, html5lib chooses the accelerated ``ElementTree``
+implementation (i.e. ``xml.etree.cElementTree`` on Python 2.x).
+
+Two other tree types are supported: ``xml.dom.minidom`` and
+``lxml.etree``. To use an alternative format, specify the name of
+a treebuilder:
+
+.. code-block:: python
+
+ import html5lib
+ with open("mydocument.html", "rb") as f:
+ lxml_etree_document = html5lib.parse(f, treebuilder="lxml")
+
+When using with ``urllib2`` (Python 2), the charset from HTTP should be
+pass into html5lib as follows:
+
+.. code-block:: python
+
+ from contextlib import closing
+ from urllib2 import urlopen
+ import html5lib
+
+ with closing(urlopen("http://example.com/")) as f:
+ document = html5lib.parse(f, encoding=f.info().getparam("charset"))
+
+When using with ``urllib.request`` (Python 3), the charset from HTTP
+should be pass into html5lib as follows:
+
+.. code-block:: python
+
+ from urllib.request import urlopen
+ import html5lib
+
+ with urlopen("http://example.com/") as f:
+ document = html5lib.parse(f, encoding=f.info().get_content_charset())
+
+To have more control over the parser, create a parser object explicitly.
+For instance, to make the parser raise exceptions on parse errors, use:
+
+.. code-block:: python
+
+ import html5lib
+ with open("mydocument.html", "rb") as f:
+ parser = html5lib.HTMLParser(strict=True)
+ document = parser.parse(f)
+
+When you're instantiating parser objects explicitly, pass a treebuilder
+class as the ``tree`` keyword argument to use an alternative document
+format:
+
+.. code-block:: python
+
+ import html5lib
+ parser = html5lib.HTMLParser(tree=html5lib.getTreeBuilder("dom"))
+ minidom_document = parser.parse("<p>Hello World!")
+
+More documentation is available at http://html5lib.readthedocs.org/.
+
+
+Installation
+------------
+
+html5lib works on CPython 2.6+, CPython 3.2+ and PyPy. To install it,
+use:
+
+.. code-block:: bash
+
+ $ pip install html5lib
+
+
+Optional Dependencies
+---------------------
+
+The following third-party libraries may be used for additional
+functionality:
+
+- ``datrie`` can be used to improve parsing performance (though in
+ almost all cases the improvement is marginal);
+
+- ``lxml`` is supported as a tree format (for both building and
+ walking) under CPython (but *not* PyPy where it is known to cause
+ segfaults);
+
+- ``genshi`` has a treewalker (but not builder); and
+
+- ``charade`` can be used as a fallback when character encoding cannot
+ be determined; ``chardet``, from which it was forked, can also be used
+ on Python 2.
+
+- ``ordereddict`` can be used under Python 2.6
+ (``collections.OrderedDict`` is used instead on later versions) to
+ serialize attributes in alphabetical order.
+
+
+Bugs
+----
+
+Please report any bugs on the `issue tracker
+<https://github.com/html5lib/html5lib-python/issues>`_.
+
+
+Tests
+-----
+
+Unit tests require the ``nose`` library and can be run using the
+``nosetests`` command in the root directory; ``ordereddict`` is
+required under Python 2.6. All should pass.
+
+Test data are contained in a separate `html5lib-tests
+<https://github.com/html5lib/html5lib-tests>`_ repository and included
+as a submodule, thus for git checkouts they must be initialized::
+
+ $ git submodule init
+ $ git submodule update
+
+If you have all compatible Python implementations available on your
+system, you can run tests on all of them using the ``tox`` utility,
+which can be found on PyPI.
+
+
+Questions?
+----------
+
+There's a mailing list available for support on Google Groups,
+`html5lib-discuss <http://groups.google.com/group/html5lib-discuss>`_,
+though you may get a quicker response asking on IRC in `#whatwg on
+irc.freenode.net <http://wiki.whatwg.org/wiki/IRC>`_.
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/debug-info.py b/tests/wpt/web-platform-tests/tools/html5lib/debug-info.py
new file mode 100644
index 00000000000..b5d2bb6a305
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/debug-info.py
@@ -0,0 +1,37 @@
+from __future__ import print_function, unicode_literals
+
+import platform
+import sys
+
+
+info = {
+ "impl": platform.python_implementation(),
+ "version": platform.python_version(),
+ "revision": platform.python_revision(),
+ "maxunicode": sys.maxunicode,
+ "maxsize": sys.maxsize
+}
+
+search_modules = ["charade", "chardet", "datrie", "genshi", "html5lib", "lxml", "six"]
+found_modules = []
+
+for m in search_modules:
+ try:
+ __import__(m)
+ except ImportError:
+ pass
+ else:
+ found_modules.append(m)
+
+info["modules"] = ", ".join(found_modules)
+
+
+print("""html5lib debug info:
+
+Python %(version)s (revision: %(revision)s)
+Implementation: %(impl)s
+
+sys.maxunicode: %(maxunicode)X
+sys.maxsize: %(maxsize)X
+
+Installed modules: %(modules)s""" % info)
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/doc/Makefile b/tests/wpt/web-platform-tests/tools/html5lib/doc/Makefile
new file mode 100644
index 00000000000..e0e58667e7d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/doc/Makefile
@@ -0,0 +1,177 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS =
+SPHINXBUILD = sphinx-build
+PAPER =
+BUILDDIR = _build
+
+# User-friendly check for sphinx-build
+ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
+$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
+endif
+
+# Internal variables.
+PAPEROPT_a4 = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+# the i18n builder cannot share the environment and doctrees with the others
+I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
+
+help:
+ @echo "Please use \`make <target>' where <target> is one of"
+ @echo " html to make standalone HTML files"
+ @echo " dirhtml to make HTML files named index.html in directories"
+ @echo " singlehtml to make a single large HTML file"
+ @echo " pickle to make pickle files"
+ @echo " json to make JSON files"
+ @echo " htmlhelp to make HTML files and a HTML help project"
+ @echo " qthelp to make HTML files and a qthelp project"
+ @echo " devhelp to make HTML files and a Devhelp project"
+ @echo " epub to make an epub"
+ @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+ @echo " latexpdf to make LaTeX files and run them through pdflatex"
+ @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
+ @echo " text to make text files"
+ @echo " man to make manual pages"
+ @echo " texinfo to make Texinfo files"
+ @echo " info to make Texinfo files and run them through makeinfo"
+ @echo " gettext to make PO message catalogs"
+ @echo " changes to make an overview of all changed/added/deprecated items"
+ @echo " xml to make Docutils-native XML files"
+ @echo " pseudoxml to make pseudoxml-XML files for display purposes"
+ @echo " linkcheck to check all external links for integrity"
+ @echo " doctest to run all doctests embedded in the documentation (if enabled)"
+
+clean:
+ rm -rf $(BUILDDIR)/*
+
+html:
+ $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+dirhtml:
+ $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
+
+singlehtml:
+ $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
+ @echo
+ @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
+
+pickle:
+ $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
+ @echo
+ @echo "Build finished; now you can process the pickle files."
+
+json:
+ $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
+ @echo
+ @echo "Build finished; now you can process the JSON files."
+
+htmlhelp:
+ $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
+ @echo
+ @echo "Build finished; now you can run HTML Help Workshop with the" \
+ ".hhp project file in $(BUILDDIR)/htmlhelp."
+
+qthelp:
+ $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
+ @echo
+ @echo "Build finished; now you can run "qcollectiongenerator" with the" \
+ ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
+ @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/html5lib.qhcp"
+ @echo "To view the help file:"
+ @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/html5lib.qhc"
+
+devhelp:
+ $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
+ @echo
+ @echo "Build finished."
+ @echo "To view the help file:"
+ @echo "# mkdir -p $$HOME/.local/share/devhelp/html5lib"
+ @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/html5lib"
+ @echo "# devhelp"
+
+epub:
+ $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
+ @echo
+ @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
+
+latex:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo
+ @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
+ @echo "Run \`make' in that directory to run these through (pdf)latex" \
+ "(use \`make latexpdf' here to do that automatically)."
+
+latexpdf:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo "Running LaTeX files through pdflatex..."
+ $(MAKE) -C $(BUILDDIR)/latex all-pdf
+ @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+latexpdfja:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo "Running LaTeX files through platex and dvipdfmx..."
+ $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
+ @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+text:
+ $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
+ @echo
+ @echo "Build finished. The text files are in $(BUILDDIR)/text."
+
+man:
+ $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
+ @echo
+ @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
+
+texinfo:
+ $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+ @echo
+ @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
+ @echo "Run \`make' in that directory to run these through makeinfo" \
+ "(use \`make info' here to do that automatically)."
+
+info:
+ $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+ @echo "Running Texinfo files through makeinfo..."
+ make -C $(BUILDDIR)/texinfo info
+ @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
+
+gettext:
+ $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
+ @echo
+ @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
+
+changes:
+ $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
+ @echo
+ @echo "The overview file is in $(BUILDDIR)/changes."
+
+linkcheck:
+ $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
+ @echo
+ @echo "Link check complete; look for any errors in the above output " \
+ "or in $(BUILDDIR)/linkcheck/output.txt."
+
+doctest:
+ $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
+ @echo "Testing of doctests in the sources finished, look at the " \
+ "results in $(BUILDDIR)/doctest/output.txt."
+
+xml:
+ $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
+ @echo
+ @echo "Build finished. The XML files are in $(BUILDDIR)/xml."
+
+pseudoxml:
+ $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
+ @echo
+ @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/doc/changes.rst b/tests/wpt/web-platform-tests/tools/html5lib/doc/changes.rst
new file mode 100644
index 00000000000..ded3b705d0f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/doc/changes.rst
@@ -0,0 +1,3 @@
+.. :changelog:
+
+.. include:: ../CHANGES.rst
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/doc/conf.py b/tests/wpt/web-platform-tests/tools/html5lib/doc/conf.py
new file mode 100644
index 00000000000..434f21c42eb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/doc/conf.py
@@ -0,0 +1,280 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# html5lib documentation build configuration file, created by
+# sphinx-quickstart on Wed May 8 00:04:49 2013.
+#
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys, os
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#sys.path.insert(0, os.path.abspath('.'))
+
+# -- General configuration -----------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.viewcode']
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = 'html5lib'
+copyright = '2006 - 2013, James Graham, Geoffrey Sneddon, and contributors'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+version = '1.0'
+# The full version, including alpha/beta/rc tags.
+sys.path.append(os.path.abspath('..'))
+from html5lib import __version__
+release = __version__
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#language = 'en'
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = ['_build', 'theme']
+
+# The reST default role (used for this markup: `text`) to use for all documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+# If true, keep warnings as "system message" paragraphs in the built documents.
+#keep_warnings = False
+
+
+# -- Options for HTML output ---------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages. See the documentation for
+# a list of builtin themes.
+html_theme = 'default'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further. For a list of options available for each theme, see the
+# documentation.
+#html_theme_options = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+#html_theme_path = []
+
+# The name for this set of Sphinx documents. If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# A shorter title for the navigation bar. Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_domain_indices = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+#html_show_sourcelink = True
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+#html_show_sphinx = True
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+#html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it. The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# This is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = None
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'html5libdoc'
+
+
+# -- Options for LaTeX output --------------------------------------------------
+
+latex_elements = {
+# The paper size ('letterpaper' or 'a4paper').
+#'papersize': 'letterpaper',
+
+# The font size ('10pt', '11pt' or '12pt').
+#'pointsize': '10pt',
+
+# Additional stuff for the LaTeX preamble.
+#'preamble': '',
+}
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, documentclass [howto/manual]).
+latex_documents = [
+ ('index', 'html5lib.tex', 'html5lib Documentation',
+ 'James Graham, Geoffrey Sneddon, and contributors', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# If true, show page references after internal links.
+#latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+#latex_show_urls = False
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_domain_indices = True
+
+
+# -- Options for manual page output --------------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+ ('index', 'html5lib', 'html5lib Documentation',
+ ['James Graham, Geoffrey Sneddon, and contributors'], 1)
+]
+
+# If true, show URL addresses after external links.
+#man_show_urls = False
+
+
+# -- Options for Texinfo output ------------------------------------------------
+
+# Grouping the document tree into Texinfo files. List of tuples
+# (source start file, target name, title, author,
+# dir menu entry, description, category)
+texinfo_documents = [
+ ('index', 'html5lib', 'html5lib Documentation',
+ 'James Graham, Geoffrey Sneddon, and contributors', 'html5lib', 'One line description of project.',
+ 'Miscellaneous'),
+]
+
+# Documents to append as an appendix to all manuals.
+#texinfo_appendices = []
+
+# If false, no module index is generated.
+#texinfo_domain_indices = True
+
+# How to display URL addresses: 'footnote', 'no', or 'inline'.
+#texinfo_show_urls = 'footnote'
+
+# If true, do not generate a @detailmenu in the "Top" node's menu.
+#texinfo_no_detailmenu = False
+
+class CExtMock(object):
+ """Required for autodoc on readthedocs.org where you cannot build C extensions."""
+ def __init__(self, *args, **kwargs):
+ pass
+
+ def __call__(self, *args, **kwargs):
+ return CExtMock()
+
+ @classmethod
+ def __getattr__(cls, name):
+ if name in ('__file__', '__path__'):
+ return '/dev/null'
+ else:
+ return CExtMock()
+
+try:
+ import lxml # flake8: noqa
+except ImportError:
+ sys.modules['lxml'] = CExtMock()
+ sys.modules['lxml.etree'] = CExtMock()
+ print("warning: lxml modules mocked.")
+
+try:
+ import genshi # flake8: noqa
+except ImportError:
+ sys.modules['genshi'] = CExtMock()
+ sys.modules['genshi.core'] = CExtMock()
+ print("warning: genshi modules mocked.")
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/doc/html5lib.filters.rst b/tests/wpt/web-platform-tests/tools/html5lib/doc/html5lib.filters.rst
new file mode 100644
index 00000000000..1fda38a735a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/doc/html5lib.filters.rst
@@ -0,0 +1,59 @@
+filters Package
+===============
+
+:mod:`_base` Module
+-------------------
+
+.. automodule:: html5lib.filters._base
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+:mod:`alphabeticalattributes` Module
+------------------------------------
+
+.. automodule:: html5lib.filters.alphabeticalattributes
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+:mod:`inject_meta_charset` Module
+---------------------------------
+
+.. automodule:: html5lib.filters.inject_meta_charset
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+:mod:`lint` Module
+------------------
+
+.. automodule:: html5lib.filters.lint
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+:mod:`optionaltags` Module
+--------------------------
+
+.. automodule:: html5lib.filters.optionaltags
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+:mod:`sanitizer` Module
+-----------------------
+
+.. automodule:: html5lib.filters.sanitizer
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+:mod:`whitespace` Module
+------------------------
+
+.. automodule:: html5lib.filters.whitespace
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/doc/html5lib.rst b/tests/wpt/web-platform-tests/tools/html5lib/doc/html5lib.rst
new file mode 100644
index 00000000000..d4ed12b4646
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/doc/html5lib.rst
@@ -0,0 +1,77 @@
+html5lib Package
+================
+
+:mod:`html5lib` Package
+-----------------------
+
+.. automodule:: html5lib.__init__
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+:mod:`constants` Module
+-----------------------
+
+.. automodule:: html5lib.constants
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+:mod:`html5parser` Module
+-------------------------
+
+.. automodule:: html5lib.html5parser
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+:mod:`ihatexml` Module
+----------------------
+
+.. automodule:: html5lib.ihatexml
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+:mod:`inputstream` Module
+-------------------------
+
+.. automodule:: html5lib.inputstream
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+:mod:`sanitizer` Module
+-----------------------
+
+.. automodule:: html5lib.sanitizer
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+:mod:`tokenizer` Module
+-----------------------
+
+.. automodule:: html5lib.tokenizer
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+:mod:`utils` Module
+-------------------
+
+.. automodule:: html5lib.utils
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+Subpackages
+-----------
+
+.. toctree::
+
+ html5lib.filters
+ html5lib.serializer
+ html5lib.treebuilders
+ html5lib.treewalkers
+
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/doc/html5lib.serializer.rst b/tests/wpt/web-platform-tests/tools/html5lib/doc/html5lib.serializer.rst
new file mode 100644
index 00000000000..fa9547421b1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/doc/html5lib.serializer.rst
@@ -0,0 +1,19 @@
+serializer Package
+==================
+
+:mod:`serializer` Package
+-------------------------
+
+.. automodule:: html5lib.serializer
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+:mod:`htmlserializer` Module
+----------------------------
+
+.. automodule:: html5lib.serializer.htmlserializer
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/doc/html5lib.treebuilders.rst b/tests/wpt/web-platform-tests/tools/html5lib/doc/html5lib.treebuilders.rst
new file mode 100644
index 00000000000..9911983948d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/doc/html5lib.treebuilders.rst
@@ -0,0 +1,43 @@
+treebuilders Package
+====================
+
+:mod:`treebuilders` Package
+---------------------------
+
+.. automodule:: html5lib.treebuilders
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+:mod:`_base` Module
+-------------------
+
+.. automodule:: html5lib.treebuilders._base
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+:mod:`dom` Module
+-----------------
+
+.. automodule:: html5lib.treebuilders.dom
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+:mod:`etree` Module
+-------------------
+
+.. automodule:: html5lib.treebuilders.etree
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+:mod:`etree_lxml` Module
+------------------------
+
+.. automodule:: html5lib.treebuilders.etree_lxml
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/doc/html5lib.treewalkers.rst b/tests/wpt/web-platform-tests/tools/html5lib/doc/html5lib.treewalkers.rst
new file mode 100644
index 00000000000..80595e2d7d0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/doc/html5lib.treewalkers.rst
@@ -0,0 +1,59 @@
+treewalkers Package
+===================
+
+:mod:`treewalkers` Package
+--------------------------
+
+.. automodule:: html5lib.treewalkers
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+:mod:`_base` Module
+-------------------
+
+.. automodule:: html5lib.treewalkers._base
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+:mod:`dom` Module
+-----------------
+
+.. automodule:: html5lib.treewalkers.dom
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+:mod:`etree` Module
+-------------------
+
+.. automodule:: html5lib.treewalkers.etree
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+:mod:`genshistream` Module
+--------------------------
+
+.. automodule:: html5lib.treewalkers.genshistream
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+:mod:`lxmletree` Module
+-----------------------
+
+.. automodule:: html5lib.treewalkers.lxmletree
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+:mod:`pulldom` Module
+---------------------
+
+.. automodule:: html5lib.treewalkers.pulldom
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/doc/index.rst b/tests/wpt/web-platform-tests/tools/html5lib/doc/index.rst
new file mode 100644
index 00000000000..ca2e1b969cd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/doc/index.rst
@@ -0,0 +1,21 @@
+Overview
+========
+
+.. include:: ../README.rst
+ :start-line: 6
+
+.. toctree::
+ :maxdepth: 2
+
+ movingparts
+ changes
+ License <license>
+
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
+
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/doc/license.rst b/tests/wpt/web-platform-tests/tools/html5lib/doc/license.rst
new file mode 100644
index 00000000000..7e6291f3b9b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/doc/license.rst
@@ -0,0 +1,4 @@
+License
+=======
+
+.. include:: ../LICENSE
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/doc/make.bat b/tests/wpt/web-platform-tests/tools/html5lib/doc/make.bat
new file mode 100644
index 00000000000..e88c769ce33
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/doc/make.bat
@@ -0,0 +1,242 @@
+@ECHO OFF
+
+REM Command file for Sphinx documentation
+
+if "%SPHINXBUILD%" == "" (
+ set SPHINXBUILD=sphinx-build
+)
+set BUILDDIR=_build
+set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
+set I18NSPHINXOPTS=%SPHINXOPTS% .
+if NOT "%PAPER%" == "" (
+ set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
+ set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
+)
+
+if "%1" == "" goto help
+
+if "%1" == "help" (
+ :help
+ echo.Please use `make ^<target^>` where ^<target^> is one of
+ echo. html to make standalone HTML files
+ echo. dirhtml to make HTML files named index.html in directories
+ echo. singlehtml to make a single large HTML file
+ echo. pickle to make pickle files
+ echo. json to make JSON files
+ echo. htmlhelp to make HTML files and a HTML help project
+ echo. qthelp to make HTML files and a qthelp project
+ echo. devhelp to make HTML files and a Devhelp project
+ echo. epub to make an epub
+ echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
+ echo. text to make text files
+ echo. man to make manual pages
+ echo. texinfo to make Texinfo files
+ echo. gettext to make PO message catalogs
+ echo. changes to make an overview over all changed/added/deprecated items
+ echo. xml to make Docutils-native XML files
+ echo. pseudoxml to make pseudoxml-XML files for display purposes
+ echo. linkcheck to check all external links for integrity
+ echo. doctest to run all doctests embedded in the documentation if enabled
+ goto end
+)
+
+if "%1" == "clean" (
+ for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
+ del /q /s %BUILDDIR%\*
+ goto end
+)
+
+
+%SPHINXBUILD% 2> nul
+if errorlevel 9009 (
+ echo.
+ echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
+ echo.installed, then set the SPHINXBUILD environment variable to point
+ echo.to the full path of the 'sphinx-build' executable. Alternatively you
+ echo.may add the Sphinx directory to PATH.
+ echo.
+ echo.If you don't have Sphinx installed, grab it from
+ echo.http://sphinx-doc.org/
+ exit /b 1
+)
+
+if "%1" == "html" (
+ %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The HTML pages are in %BUILDDIR%/html.
+ goto end
+)
+
+if "%1" == "dirhtml" (
+ %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
+ goto end
+)
+
+if "%1" == "singlehtml" (
+ %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
+ goto end
+)
+
+if "%1" == "pickle" (
+ %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can process the pickle files.
+ goto end
+)
+
+if "%1" == "json" (
+ %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can process the JSON files.
+ goto end
+)
+
+if "%1" == "htmlhelp" (
+ %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can run HTML Help Workshop with the ^
+.hhp project file in %BUILDDIR%/htmlhelp.
+ goto end
+)
+
+if "%1" == "qthelp" (
+ %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can run "qcollectiongenerator" with the ^
+.qhcp project file in %BUILDDIR%/qthelp, like this:
+ echo.^> qcollectiongenerator %BUILDDIR%\qthelp\html5lib.qhcp
+ echo.To view the help file:
+ echo.^> assistant -collectionFile %BUILDDIR%\qthelp\html5lib.ghc
+ goto end
+)
+
+if "%1" == "devhelp" (
+ %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished.
+ goto end
+)
+
+if "%1" == "epub" (
+ %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The epub file is in %BUILDDIR%/epub.
+ goto end
+)
+
+if "%1" == "latex" (
+ %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
+ goto end
+)
+
+if "%1" == "latexpdf" (
+ %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
+ cd %BUILDDIR%/latex
+ make all-pdf
+ cd %BUILDDIR%/..
+ echo.
+ echo.Build finished; the PDF files are in %BUILDDIR%/latex.
+ goto end
+)
+
+if "%1" == "latexpdfja" (
+ %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
+ cd %BUILDDIR%/latex
+ make all-pdf-ja
+ cd %BUILDDIR%/..
+ echo.
+ echo.Build finished; the PDF files are in %BUILDDIR%/latex.
+ goto end
+)
+
+if "%1" == "text" (
+ %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The text files are in %BUILDDIR%/text.
+ goto end
+)
+
+if "%1" == "man" (
+ %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The manual pages are in %BUILDDIR%/man.
+ goto end
+)
+
+if "%1" == "texinfo" (
+ %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
+ goto end
+)
+
+if "%1" == "gettext" (
+ %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
+ goto end
+)
+
+if "%1" == "changes" (
+ %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.The overview file is in %BUILDDIR%/changes.
+ goto end
+)
+
+if "%1" == "linkcheck" (
+ %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Link check complete; look for any errors in the above output ^
+or in %BUILDDIR%/linkcheck/output.txt.
+ goto end
+)
+
+if "%1" == "doctest" (
+ %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Testing of doctests in the sources finished, look at the ^
+results in %BUILDDIR%/doctest/output.txt.
+ goto end
+)
+
+if "%1" == "xml" (
+ %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The XML files are in %BUILDDIR%/xml.
+ goto end
+)
+
+if "%1" == "pseudoxml" (
+ %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml.
+ goto end
+)
+
+:end
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/doc/modules.rst b/tests/wpt/web-platform-tests/tools/html5lib/doc/modules.rst
new file mode 100644
index 00000000000..59fbcc86bc1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/doc/modules.rst
@@ -0,0 +1,7 @@
+html5lib
+========
+
+.. toctree::
+ :maxdepth: 4
+
+ html5lib
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/doc/movingparts.rst b/tests/wpt/web-platform-tests/tools/html5lib/doc/movingparts.rst
new file mode 100644
index 00000000000..36539785a7e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/doc/movingparts.rst
@@ -0,0 +1,209 @@
+The moving parts
+================
+
+html5lib consists of a number of components, which are responsible for
+handling its features.
+
+
+Tree builders
+-------------
+
+The parser reads HTML by tokenizing the content and building a tree that
+the user can later access. There are three main types of trees that
+html5lib can build:
+
+* ``etree`` - this is the default; builds a tree based on ``xml.etree``,
+ which can be found in the standard library. Whenever possible, the
+ accelerated ``ElementTree`` implementation (i.e.
+ ``xml.etree.cElementTree`` on Python 2.x) is used.
+
+* ``dom`` - builds a tree based on ``xml.dom.minidom``.
+
+* ``lxml.etree`` - uses lxml's implementation of the ``ElementTree``
+ API. The performance gains are relatively small compared to using the
+ accelerated ``ElementTree`` module.
+
+You can specify the builder by name when using the shorthand API:
+
+.. code-block:: python
+
+ import html5lib
+ with open("mydocument.html", "rb") as f:
+ lxml_etree_document = html5lib.parse(f, treebuilder="lxml")
+
+When instantiating a parser object, you have to pass a tree builder
+class in the ``tree`` keyword attribute:
+
+.. code-block:: python
+
+ import html5lib
+ parser = html5lib.HTMLParser(tree=SomeTreeBuilder)
+ document = parser.parse("<p>Hello World!")
+
+To get a builder class by name, use the ``getTreeBuilder`` function:
+
+.. code-block:: python
+
+ import html5lib
+ parser = html5lib.HTMLParser(tree=html5lib.getTreeBuilder("dom"))
+ minidom_document = parser.parse("<p>Hello World!")
+
+The implementation of builders can be found in `html5lib/treebuilders/
+<https://github.com/html5lib/html5lib-python/tree/master/html5lib/treebuilders>`_.
+
+
+Tree walkers
+------------
+
+Once a tree is ready, you can work on it either manually, or using
+a tree walker, which provides a streaming view of the tree. html5lib
+provides walkers for all three supported types of trees (``etree``,
+``dom`` and ``lxml``).
+
+The implementation of walkers can be found in `html5lib/treewalkers/
+<https://github.com/html5lib/html5lib-python/tree/master/html5lib/treewalkers>`_.
+
+Walkers make consuming HTML easier. html5lib uses them to provide you
+with has a couple of handy tools.
+
+
+HTMLSerializer
+~~~~~~~~~~~~~~
+
+The serializer lets you write HTML back as a stream of bytes.
+
+.. code-block:: pycon
+
+ >>> import html5lib
+ >>> element = html5lib.parse('<p xml:lang="pl">Witam wszystkich')
+ >>> walker = html5lib.getTreeWalker("etree")
+ >>> stream = walker(element)
+ >>> s = html5lib.serializer.HTMLSerializer()
+ >>> output = s.serialize(stream)
+ >>> for item in output:
+ ... print("%r" % item)
+ '<p'
+ ' '
+ 'xml:lang'
+ '='
+ 'pl'
+ '>'
+ 'Witam wszystkich'
+
+You can customize the serializer behaviour in a variety of ways, consult
+the :class:`~html5lib.serializer.htmlserializer.HTMLSerializer`
+documentation.
+
+
+Filters
+~~~~~~~
+
+You can alter the stream content with filters provided by html5lib:
+
+* :class:`alphabeticalattributes.Filter
+ <html5lib.filters.alphabeticalattributes.Filter>` sorts attributes on
+ tags to be in alphabetical order
+
+* :class:`inject_meta_charset.Filter
+ <html5lib.filters.inject_meta_charset.Filter>` sets a user-specified
+ encoding in the correct ``<meta>`` tag in the ``<head>`` section of
+ the document
+
+* :class:`lint.Filter <html5lib.filters.lint.Filter>` raises
+ ``LintError`` exceptions on invalid tag and attribute names, invalid
+ PCDATA, etc.
+
+* :class:`optionaltags.Filter <html5lib.filters.optionaltags.Filter>`
+ removes tags from the stream which are not necessary to produce valid
+ HTML
+
+* :class:`sanitizer.Filter <html5lib.filters.sanitizer.Filter>` removes
+ unsafe markup and CSS. Elements that are known to be safe are passed
+ through and the rest is converted to visible text. The default
+ configuration of the sanitizer follows the `WHATWG Sanitization Rules
+ <http://wiki.whatwg.org/wiki/Sanitization_rules>`_.
+
+* :class:`whitespace.Filter <html5lib.filters.whitespace.Filter>`
+ collapses all whitespace characters to single spaces unless they're in
+ ``<pre/>`` or ``textarea`` tags.
+
+To use a filter, simply wrap it around a stream:
+
+.. code-block:: python
+
+ >>> import html5lib
+ >>> from html5lib.filters import sanitizer
+ >>> dom = html5lib.parse("<p><script>alert('Boo!')", treebuilder="dom")
+ >>> walker = html5lib.getTreeWalker("dom")
+ >>> stream = walker(dom)
+ >>> sane_stream = sanitizer.Filter(stream) clean_stream = sanitizer.Filter(stream)
+
+
+Tree adapters
+-------------
+
+Used to translate one type of tree to another. More documentation
+pending, sorry.
+
+
+Encoding discovery
+------------------
+
+Parsed trees are always Unicode. However a large variety of input
+encodings are supported. The encoding of the document is determined in
+the following way:
+
+* The encoding may be explicitly specified by passing the name of the
+ encoding as the encoding parameter to the
+ :meth:`~html5lib.html5parser.HTMLParser.parse` method on
+ ``HTMLParser`` objects.
+
+* If no encoding is specified, the parser will attempt to detect the
+ encoding from a ``<meta>`` element in the first 512 bytes of the
+ document (this is only a partial implementation of the current HTML
+ 5 specification).
+
+* If no encoding can be found and the chardet library is available, an
+ attempt will be made to sniff the encoding from the byte pattern.
+
+* If all else fails, the default encoding will be used. This is usually
+ `Windows-1252 <http://en.wikipedia.org/wiki/Windows-1252>`_, which is
+ a common fallback used by Web browsers.
+
+
+Tokenizers
+----------
+
+The part of the parser responsible for translating a raw input stream
+into meaningful tokens is the tokenizer. Currently html5lib provides
+two.
+
+To set up a tokenizer, simply pass it when instantiating
+a :class:`~html5lib.html5parser.HTMLParser`:
+
+.. code-block:: python
+
+ import html5lib
+ from html5lib import sanitizer
+
+ p = html5lib.HTMLParser(tokenizer=sanitizer.HTMLSanitizer)
+ p.parse("<p>Surprise!<script>alert('Boo!');</script>")
+
+HTMLTokenizer
+~~~~~~~~~~~~~
+
+This is the default tokenizer, the heart of html5lib. The implementation
+can be found in `html5lib/tokenizer.py
+<https://github.com/html5lib/html5lib-python/blob/master/html5lib/tokenizer.py>`_.
+
+HTMLSanitizer
+~~~~~~~~~~~~~
+
+This is a tokenizer that removes unsafe markup and CSS styles from the
+input. Elements that are known to be safe are passed through and the
+rest is converted to visible text. The default configuration of the
+sanitizer follows the `WHATWG Sanitization Rules
+<http://wiki.whatwg.org/wiki/Sanitization_rules>`_.
+
+The implementation can be found in `html5lib/sanitizer.py
+<https://github.com/html5lib/html5lib-python/blob/master/html5lib/sanitizer.py>`_.
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/flake8-run.sh b/tests/wpt/web-platform-tests/tools/html5lib/flake8-run.sh
new file mode 100755
index 00000000000..d1a587d3506
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/flake8-run.sh
@@ -0,0 +1,14 @@
+#!/bin/bash -e
+
+if [[ ! -x $(which flake8) ]]; then
+ echo "fatal: flake8 not found on $PATH. Exiting."
+ exit 1
+fi
+
+if [[ $TRAVIS != "true" || $FLAKE == "true" ]]; then
+ find html5lib/ -name '*.py' -and -not -name 'constants.py' -print0 | xargs -0 flake8 --ignore=E501
+ flake1=$?
+ flake8 --max-line-length=99 --ignore=E126 html5lib/constants.py
+ flake2=$?
+ exit $[$flake1 || $flake2]
+fi
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/__init__.py b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/__init__.py
new file mode 100644
index 00000000000..a67a652b999
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/__init__.py
@@ -0,0 +1,23 @@
+"""
+HTML parsing library based on the WHATWG "HTML5"
+specification. The parser is designed to be compatible with existing
+HTML found in the wild and implements well-defined error recovery that
+is largely compatible with modern desktop web browsers.
+
+Example usage:
+
+import html5lib
+f = open("my_document.html")
+tree = html5lib.parse(f)
+"""
+
+from __future__ import absolute_import, division, unicode_literals
+
+from .html5parser import HTMLParser, parse, parseFragment
+from .treebuilders import getTreeBuilder
+from .treewalkers import getTreeWalker
+from .serializer import serialize
+
+__all__ = ["HTMLParser", "parse", "parseFragment", "getTreeBuilder",
+ "getTreeWalker", "serialize"]
+__version__ = "0.9999-dev"
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/constants.py b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/constants.py
new file mode 100644
index 00000000000..e7089846d59
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/constants.py
@@ -0,0 +1,3104 @@
+from __future__ import absolute_import, division, unicode_literals
+
+import string
+import gettext
+_ = gettext.gettext
+
+EOF = None
+
+E = {
+ "null-character":
+ _("Null character in input stream, replaced with U+FFFD."),
+ "invalid-codepoint":
+ _("Invalid codepoint in stream."),
+ "incorrectly-placed-solidus":
+ _("Solidus (/) incorrectly placed in tag."),
+ "incorrect-cr-newline-entity":
+ _("Incorrect CR newline entity, replaced with LF."),
+ "illegal-windows-1252-entity":
+ _("Entity used with illegal number (windows-1252 reference)."),
+ "cant-convert-numeric-entity":
+ _("Numeric entity couldn't be converted to character "
+ "(codepoint U+%(charAsInt)08x)."),
+ "illegal-codepoint-for-numeric-entity":
+ _("Numeric entity represents an illegal codepoint: "
+ "U+%(charAsInt)08x."),
+ "numeric-entity-without-semicolon":
+ _("Numeric entity didn't end with ';'."),
+ "expected-numeric-entity-but-got-eof":
+ _("Numeric entity expected. Got end of file instead."),
+ "expected-numeric-entity":
+ _("Numeric entity expected but none found."),
+ "named-entity-without-semicolon":
+ _("Named entity didn't end with ';'."),
+ "expected-named-entity":
+ _("Named entity expected. Got none."),
+ "attributes-in-end-tag":
+ _("End tag contains unexpected attributes."),
+ 'self-closing-flag-on-end-tag':
+ _("End tag contains unexpected self-closing flag."),
+ "expected-tag-name-but-got-right-bracket":
+ _("Expected tag name. Got '>' instead."),
+ "expected-tag-name-but-got-question-mark":
+ _("Expected tag name. Got '?' instead. (HTML doesn't "
+ "support processing instructions.)"),
+ "expected-tag-name":
+ _("Expected tag name. Got something else instead"),
+ "expected-closing-tag-but-got-right-bracket":
+ _("Expected closing tag. Got '>' instead. Ignoring '</>'."),
+ "expected-closing-tag-but-got-eof":
+ _("Expected closing tag. Unexpected end of file."),
+ "expected-closing-tag-but-got-char":
+ _("Expected closing tag. Unexpected character '%(data)s' found."),
+ "eof-in-tag-name":
+ _("Unexpected end of file in the tag name."),
+ "expected-attribute-name-but-got-eof":
+ _("Unexpected end of file. Expected attribute name instead."),
+ "eof-in-attribute-name":
+ _("Unexpected end of file in attribute name."),
+ "invalid-character-in-attribute-name":
+ _("Invalid character in attribute name"),
+ "duplicate-attribute":
+ _("Dropped duplicate attribute on tag."),
+ "expected-end-of-tag-name-but-got-eof":
+ _("Unexpected end of file. Expected = or end of tag."),
+ "expected-attribute-value-but-got-eof":
+ _("Unexpected end of file. Expected attribute value."),
+ "expected-attribute-value-but-got-right-bracket":
+ _("Expected attribute value. Got '>' instead."),
+ 'equals-in-unquoted-attribute-value':
+ _("Unexpected = in unquoted attribute"),
+ 'unexpected-character-in-unquoted-attribute-value':
+ _("Unexpected character in unquoted attribute"),
+ "invalid-character-after-attribute-name":
+ _("Unexpected character after attribute name."),
+ "unexpected-character-after-attribute-value":
+ _("Unexpected character after attribute value."),
+ "eof-in-attribute-value-double-quote":
+ _("Unexpected end of file in attribute value (\")."),
+ "eof-in-attribute-value-single-quote":
+ _("Unexpected end of file in attribute value (')."),
+ "eof-in-attribute-value-no-quotes":
+ _("Unexpected end of file in attribute value."),
+ "unexpected-EOF-after-solidus-in-tag":
+ _("Unexpected end of file in tag. Expected >"),
+ "unexpected-character-after-solidus-in-tag":
+ _("Unexpected character after / in tag. Expected >"),
+ "expected-dashes-or-doctype":
+ _("Expected '--' or 'DOCTYPE'. Not found."),
+ "unexpected-bang-after-double-dash-in-comment":
+ _("Unexpected ! after -- in comment"),
+ "unexpected-space-after-double-dash-in-comment":
+ _("Unexpected space after -- in comment"),
+ "incorrect-comment":
+ _("Incorrect comment."),
+ "eof-in-comment":
+ _("Unexpected end of file in comment."),
+ "eof-in-comment-end-dash":
+ _("Unexpected end of file in comment (-)"),
+ "unexpected-dash-after-double-dash-in-comment":
+ _("Unexpected '-' after '--' found in comment."),
+ "eof-in-comment-double-dash":
+ _("Unexpected end of file in comment (--)."),
+ "eof-in-comment-end-space-state":
+ _("Unexpected end of file in comment."),
+ "eof-in-comment-end-bang-state":
+ _("Unexpected end of file in comment."),
+ "unexpected-char-in-comment":
+ _("Unexpected character in comment found."),
+ "need-space-after-doctype":
+ _("No space after literal string 'DOCTYPE'."),
+ "expected-doctype-name-but-got-right-bracket":
+ _("Unexpected > character. Expected DOCTYPE name."),
+ "expected-doctype-name-but-got-eof":
+ _("Unexpected end of file. Expected DOCTYPE name."),
+ "eof-in-doctype-name":
+ _("Unexpected end of file in DOCTYPE name."),
+ "eof-in-doctype":
+ _("Unexpected end of file in DOCTYPE."),
+ "expected-space-or-right-bracket-in-doctype":
+ _("Expected space or '>'. Got '%(data)s'"),
+ "unexpected-end-of-doctype":
+ _("Unexpected end of DOCTYPE."),
+ "unexpected-char-in-doctype":
+ _("Unexpected character in DOCTYPE."),
+ "eof-in-innerhtml":
+ _("XXX innerHTML EOF"),
+ "unexpected-doctype":
+ _("Unexpected DOCTYPE. Ignored."),
+ "non-html-root":
+ _("html needs to be the first start tag."),
+ "expected-doctype-but-got-eof":
+ _("Unexpected End of file. Expected DOCTYPE."),
+ "unknown-doctype":
+ _("Erroneous DOCTYPE."),
+ "expected-doctype-but-got-chars":
+ _("Unexpected non-space characters. Expected DOCTYPE."),
+ "expected-doctype-but-got-start-tag":
+ _("Unexpected start tag (%(name)s). Expected DOCTYPE."),
+ "expected-doctype-but-got-end-tag":
+ _("Unexpected end tag (%(name)s). Expected DOCTYPE."),
+ "end-tag-after-implied-root":
+ _("Unexpected end tag (%(name)s) after the (implied) root element."),
+ "expected-named-closing-tag-but-got-eof":
+ _("Unexpected end of file. Expected end tag (%(name)s)."),
+ "two-heads-are-not-better-than-one":
+ _("Unexpected start tag head in existing head. Ignored."),
+ "unexpected-end-tag":
+ _("Unexpected end tag (%(name)s). Ignored."),
+ "unexpected-start-tag-out-of-my-head":
+ _("Unexpected start tag (%(name)s) that can be in head. Moved."),
+ "unexpected-start-tag":
+ _("Unexpected start tag (%(name)s)."),
+ "missing-end-tag":
+ _("Missing end tag (%(name)s)."),
+ "missing-end-tags":
+ _("Missing end tags (%(name)s)."),
+ "unexpected-start-tag-implies-end-tag":
+ _("Unexpected start tag (%(startName)s) "
+ "implies end tag (%(endName)s)."),
+ "unexpected-start-tag-treated-as":
+ _("Unexpected start tag (%(originalName)s). Treated as %(newName)s."),
+ "deprecated-tag":
+ _("Unexpected start tag %(name)s. Don't use it!"),
+ "unexpected-start-tag-ignored":
+ _("Unexpected start tag %(name)s. Ignored."),
+ "expected-one-end-tag-but-got-another":
+ _("Unexpected end tag (%(gotName)s). "
+ "Missing end tag (%(expectedName)s)."),
+ "end-tag-too-early":
+ _("End tag (%(name)s) seen too early. Expected other end tag."),
+ "end-tag-too-early-named":
+ _("Unexpected end tag (%(gotName)s). Expected end tag (%(expectedName)s)."),
+ "end-tag-too-early-ignored":
+ _("End tag (%(name)s) seen too early. Ignored."),
+ "adoption-agency-1.1":
+ _("End tag (%(name)s) violates step 1, "
+ "paragraph 1 of the adoption agency algorithm."),
+ "adoption-agency-1.2":
+ _("End tag (%(name)s) violates step 1, "
+ "paragraph 2 of the adoption agency algorithm."),
+ "adoption-agency-1.3":
+ _("End tag (%(name)s) violates step 1, "
+ "paragraph 3 of the adoption agency algorithm."),
+ "adoption-agency-4.4":
+ _("End tag (%(name)s) violates step 4, "
+ "paragraph 4 of the adoption agency algorithm."),
+ "unexpected-end-tag-treated-as":
+ _("Unexpected end tag (%(originalName)s). Treated as %(newName)s."),
+ "no-end-tag":
+ _("This element (%(name)s) has no end tag."),
+ "unexpected-implied-end-tag-in-table":
+ _("Unexpected implied end tag (%(name)s) in the table phase."),
+ "unexpected-implied-end-tag-in-table-body":
+ _("Unexpected implied end tag (%(name)s) in the table body phase."),
+ "unexpected-char-implies-table-voodoo":
+ _("Unexpected non-space characters in "
+ "table context caused voodoo mode."),
+ "unexpected-hidden-input-in-table":
+ _("Unexpected input with type hidden in table context."),
+ "unexpected-form-in-table":
+ _("Unexpected form in table context."),
+ "unexpected-start-tag-implies-table-voodoo":
+ _("Unexpected start tag (%(name)s) in "
+ "table context caused voodoo mode."),
+ "unexpected-end-tag-implies-table-voodoo":
+ _("Unexpected end tag (%(name)s) in "
+ "table context caused voodoo mode."),
+ "unexpected-cell-in-table-body":
+ _("Unexpected table cell start tag (%(name)s) "
+ "in the table body phase."),
+ "unexpected-cell-end-tag":
+ _("Got table cell end tag (%(name)s) "
+ "while required end tags are missing."),
+ "unexpected-end-tag-in-table-body":
+ _("Unexpected end tag (%(name)s) in the table body phase. Ignored."),
+ "unexpected-implied-end-tag-in-table-row":
+ _("Unexpected implied end tag (%(name)s) in the table row phase."),
+ "unexpected-end-tag-in-table-row":
+ _("Unexpected end tag (%(name)s) in the table row phase. Ignored."),
+ "unexpected-select-in-select":
+ _("Unexpected select start tag in the select phase "
+ "treated as select end tag."),
+ "unexpected-input-in-select":
+ _("Unexpected input start tag in the select phase."),
+ "unexpected-start-tag-in-select":
+ _("Unexpected start tag token (%(name)s in the select phase. "
+ "Ignored."),
+ "unexpected-end-tag-in-select":
+ _("Unexpected end tag (%(name)s) in the select phase. Ignored."),
+ "unexpected-table-element-start-tag-in-select-in-table":
+ _("Unexpected table element start tag (%(name)s) in the select in table phase."),
+ "unexpected-table-element-end-tag-in-select-in-table":
+ _("Unexpected table element end tag (%(name)s) in the select in table phase."),
+ "unexpected-char-after-body":
+ _("Unexpected non-space characters in the after body phase."),
+ "unexpected-start-tag-after-body":
+ _("Unexpected start tag token (%(name)s)"
+ " in the after body phase."),
+ "unexpected-end-tag-after-body":
+ _("Unexpected end tag token (%(name)s)"
+ " in the after body phase."),
+ "unexpected-char-in-frameset":
+ _("Unexpected characters in the frameset phase. Characters ignored."),
+ "unexpected-start-tag-in-frameset":
+ _("Unexpected start tag token (%(name)s)"
+ " in the frameset phase. Ignored."),
+ "unexpected-frameset-in-frameset-innerhtml":
+ _("Unexpected end tag token (frameset) "
+ "in the frameset phase (innerHTML)."),
+ "unexpected-end-tag-in-frameset":
+ _("Unexpected end tag token (%(name)s)"
+ " in the frameset phase. Ignored."),
+ "unexpected-char-after-frameset":
+ _("Unexpected non-space characters in the "
+ "after frameset phase. Ignored."),
+ "unexpected-start-tag-after-frameset":
+ _("Unexpected start tag (%(name)s)"
+ " in the after frameset phase. Ignored."),
+ "unexpected-end-tag-after-frameset":
+ _("Unexpected end tag (%(name)s)"
+ " in the after frameset phase. Ignored."),
+ "unexpected-end-tag-after-body-innerhtml":
+ _("Unexpected end tag after body(innerHtml)"),
+ "expected-eof-but-got-char":
+ _("Unexpected non-space characters. Expected end of file."),
+ "expected-eof-but-got-start-tag":
+ _("Unexpected start tag (%(name)s)"
+ ". Expected end of file."),
+ "expected-eof-but-got-end-tag":
+ _("Unexpected end tag (%(name)s)"
+ ". Expected end of file."),
+ "eof-in-table":
+ _("Unexpected end of file. Expected table content."),
+ "eof-in-select":
+ _("Unexpected end of file. Expected select content."),
+ "eof-in-frameset":
+ _("Unexpected end of file. Expected frameset content."),
+ "eof-in-script-in-script":
+ _("Unexpected end of file. Expected script content."),
+ "eof-in-foreign-lands":
+ _("Unexpected end of file. Expected foreign content"),
+ "non-void-element-with-trailing-solidus":
+ _("Trailing solidus not allowed on element %(name)s"),
+ "unexpected-html-element-in-foreign-content":
+ _("Element %(name)s not allowed in a non-html context"),
+ "unexpected-end-tag-before-html":
+ _("Unexpected end tag (%(name)s) before html."),
+ "XXX-undefined-error":
+ _("Undefined error (this sucks and should be fixed)"),
+}
+
+namespaces = {
+ "html": "http://www.w3.org/1999/xhtml",
+ "mathml": "http://www.w3.org/1998/Math/MathML",
+ "svg": "http://www.w3.org/2000/svg",
+ "xlink": "http://www.w3.org/1999/xlink",
+ "xml": "http://www.w3.org/XML/1998/namespace",
+ "xmlns": "http://www.w3.org/2000/xmlns/"
+}
+
+scopingElements = frozenset((
+ (namespaces["html"], "applet"),
+ (namespaces["html"], "caption"),
+ (namespaces["html"], "html"),
+ (namespaces["html"], "marquee"),
+ (namespaces["html"], "object"),
+ (namespaces["html"], "table"),
+ (namespaces["html"], "td"),
+ (namespaces["html"], "th"),
+ (namespaces["mathml"], "mi"),
+ (namespaces["mathml"], "mo"),
+ (namespaces["mathml"], "mn"),
+ (namespaces["mathml"], "ms"),
+ (namespaces["mathml"], "mtext"),
+ (namespaces["mathml"], "annotation-xml"),
+ (namespaces["svg"], "foreignObject"),
+ (namespaces["svg"], "desc"),
+ (namespaces["svg"], "title"),
+))
+
+formattingElements = frozenset((
+ (namespaces["html"], "a"),
+ (namespaces["html"], "b"),
+ (namespaces["html"], "big"),
+ (namespaces["html"], "code"),
+ (namespaces["html"], "em"),
+ (namespaces["html"], "font"),
+ (namespaces["html"], "i"),
+ (namespaces["html"], "nobr"),
+ (namespaces["html"], "s"),
+ (namespaces["html"], "small"),
+ (namespaces["html"], "strike"),
+ (namespaces["html"], "strong"),
+ (namespaces["html"], "tt"),
+ (namespaces["html"], "u")
+))
+
+specialElements = frozenset((
+ (namespaces["html"], "address"),
+ (namespaces["html"], "applet"),
+ (namespaces["html"], "area"),
+ (namespaces["html"], "article"),
+ (namespaces["html"], "aside"),
+ (namespaces["html"], "base"),
+ (namespaces["html"], "basefont"),
+ (namespaces["html"], "bgsound"),
+ (namespaces["html"], "blockquote"),
+ (namespaces["html"], "body"),
+ (namespaces["html"], "br"),
+ (namespaces["html"], "button"),
+ (namespaces["html"], "caption"),
+ (namespaces["html"], "center"),
+ (namespaces["html"], "col"),
+ (namespaces["html"], "colgroup"),
+ (namespaces["html"], "command"),
+ (namespaces["html"], "dd"),
+ (namespaces["html"], "details"),
+ (namespaces["html"], "dir"),
+ (namespaces["html"], "div"),
+ (namespaces["html"], "dl"),
+ (namespaces["html"], "dt"),
+ (namespaces["html"], "embed"),
+ (namespaces["html"], "fieldset"),
+ (namespaces["html"], "figure"),
+ (namespaces["html"], "footer"),
+ (namespaces["html"], "form"),
+ (namespaces["html"], "frame"),
+ (namespaces["html"], "frameset"),
+ (namespaces["html"], "h1"),
+ (namespaces["html"], "h2"),
+ (namespaces["html"], "h3"),
+ (namespaces["html"], "h4"),
+ (namespaces["html"], "h5"),
+ (namespaces["html"], "h6"),
+ (namespaces["html"], "head"),
+ (namespaces["html"], "header"),
+ (namespaces["html"], "hr"),
+ (namespaces["html"], "html"),
+ (namespaces["html"], "iframe"),
+ # Note that image is commented out in the spec as "this isn't an
+ # element that can end up on the stack, so it doesn't matter,"
+ (namespaces["html"], "image"),
+ (namespaces["html"], "img"),
+ (namespaces["html"], "input"),
+ (namespaces["html"], "isindex"),
+ (namespaces["html"], "li"),
+ (namespaces["html"], "link"),
+ (namespaces["html"], "listing"),
+ (namespaces["html"], "marquee"),
+ (namespaces["html"], "menu"),
+ (namespaces["html"], "meta"),
+ (namespaces["html"], "nav"),
+ (namespaces["html"], "noembed"),
+ (namespaces["html"], "noframes"),
+ (namespaces["html"], "noscript"),
+ (namespaces["html"], "object"),
+ (namespaces["html"], "ol"),
+ (namespaces["html"], "p"),
+ (namespaces["html"], "param"),
+ (namespaces["html"], "plaintext"),
+ (namespaces["html"], "pre"),
+ (namespaces["html"], "script"),
+ (namespaces["html"], "section"),
+ (namespaces["html"], "select"),
+ (namespaces["html"], "style"),
+ (namespaces["html"], "table"),
+ (namespaces["html"], "tbody"),
+ (namespaces["html"], "td"),
+ (namespaces["html"], "textarea"),
+ (namespaces["html"], "tfoot"),
+ (namespaces["html"], "th"),
+ (namespaces["html"], "thead"),
+ (namespaces["html"], "title"),
+ (namespaces["html"], "tr"),
+ (namespaces["html"], "ul"),
+ (namespaces["html"], "wbr"),
+ (namespaces["html"], "xmp"),
+ (namespaces["svg"], "foreignObject")
+))
+
+htmlIntegrationPointElements = frozenset((
+ (namespaces["mathml"], "annotaion-xml"),
+ (namespaces["svg"], "foreignObject"),
+ (namespaces["svg"], "desc"),
+ (namespaces["svg"], "title")
+))
+
+mathmlTextIntegrationPointElements = frozenset((
+ (namespaces["mathml"], "mi"),
+ (namespaces["mathml"], "mo"),
+ (namespaces["mathml"], "mn"),
+ (namespaces["mathml"], "ms"),
+ (namespaces["mathml"], "mtext")
+))
+
+adjustForeignAttributes = {
+ "xlink:actuate": ("xlink", "actuate", namespaces["xlink"]),
+ "xlink:arcrole": ("xlink", "arcrole", namespaces["xlink"]),
+ "xlink:href": ("xlink", "href", namespaces["xlink"]),
+ "xlink:role": ("xlink", "role", namespaces["xlink"]),
+ "xlink:show": ("xlink", "show", namespaces["xlink"]),
+ "xlink:title": ("xlink", "title", namespaces["xlink"]),
+ "xlink:type": ("xlink", "type", namespaces["xlink"]),
+ "xml:base": ("xml", "base", namespaces["xml"]),
+ "xml:lang": ("xml", "lang", namespaces["xml"]),
+ "xml:space": ("xml", "space", namespaces["xml"]),
+ "xmlns": (None, "xmlns", namespaces["xmlns"]),
+ "xmlns:xlink": ("xmlns", "xlink", namespaces["xmlns"])
+}
+
+unadjustForeignAttributes = dict([((ns, local), qname) for qname, (prefix, local, ns) in
+ adjustForeignAttributes.items()])
+
+spaceCharacters = frozenset((
+ "\t",
+ "\n",
+ "\u000C",
+ " ",
+ "\r"
+))
+
+tableInsertModeElements = frozenset((
+ "table",
+ "tbody",
+ "tfoot",
+ "thead",
+ "tr"
+))
+
+asciiLowercase = frozenset(string.ascii_lowercase)
+asciiUppercase = frozenset(string.ascii_uppercase)
+asciiLetters = frozenset(string.ascii_letters)
+digits = frozenset(string.digits)
+hexDigits = frozenset(string.hexdigits)
+
+asciiUpper2Lower = dict([(ord(c), ord(c.lower()))
+ for c in string.ascii_uppercase])
+
+# Heading elements need to be ordered
+headingElements = (
+ "h1",
+ "h2",
+ "h3",
+ "h4",
+ "h5",
+ "h6"
+)
+
+voidElements = frozenset((
+ "base",
+ "command",
+ "event-source",
+ "link",
+ "meta",
+ "hr",
+ "br",
+ "img",
+ "embed",
+ "param",
+ "area",
+ "col",
+ "input",
+ "source",
+ "track"
+))
+
+cdataElements = frozenset(('title', 'textarea'))
+
+rcdataElements = frozenset((
+ 'style',
+ 'script',
+ 'xmp',
+ 'iframe',
+ 'noembed',
+ 'noframes',
+ 'noscript'
+))
+
+booleanAttributes = {
+ "": frozenset(("irrelevant",)),
+ "style": frozenset(("scoped",)),
+ "img": frozenset(("ismap",)),
+ "audio": frozenset(("autoplay", "controls")),
+ "video": frozenset(("autoplay", "controls")),
+ "script": frozenset(("defer", "async")),
+ "details": frozenset(("open",)),
+ "datagrid": frozenset(("multiple", "disabled")),
+ "command": frozenset(("hidden", "disabled", "checked", "default")),
+ "hr": frozenset(("noshade")),
+ "menu": frozenset(("autosubmit",)),
+ "fieldset": frozenset(("disabled", "readonly")),
+ "option": frozenset(("disabled", "readonly", "selected")),
+ "optgroup": frozenset(("disabled", "readonly")),
+ "button": frozenset(("disabled", "autofocus")),
+ "input": frozenset(("disabled", "readonly", "required", "autofocus", "checked", "ismap")),
+ "select": frozenset(("disabled", "readonly", "autofocus", "multiple")),
+ "output": frozenset(("disabled", "readonly")),
+}
+
+# entitiesWindows1252 has to be _ordered_ and needs to have an index. It
+# therefore can't be a frozenset.
+entitiesWindows1252 = (
+ 8364, # 0x80 0x20AC EURO SIGN
+ 65533, # 0x81 UNDEFINED
+ 8218, # 0x82 0x201A SINGLE LOW-9 QUOTATION MARK
+ 402, # 0x83 0x0192 LATIN SMALL LETTER F WITH HOOK
+ 8222, # 0x84 0x201E DOUBLE LOW-9 QUOTATION MARK
+ 8230, # 0x85 0x2026 HORIZONTAL ELLIPSIS
+ 8224, # 0x86 0x2020 DAGGER
+ 8225, # 0x87 0x2021 DOUBLE DAGGER
+ 710, # 0x88 0x02C6 MODIFIER LETTER CIRCUMFLEX ACCENT
+ 8240, # 0x89 0x2030 PER MILLE SIGN
+ 352, # 0x8A 0x0160 LATIN CAPITAL LETTER S WITH CARON
+ 8249, # 0x8B 0x2039 SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+ 338, # 0x8C 0x0152 LATIN CAPITAL LIGATURE OE
+ 65533, # 0x8D UNDEFINED
+ 381, # 0x8E 0x017D LATIN CAPITAL LETTER Z WITH CARON
+ 65533, # 0x8F UNDEFINED
+ 65533, # 0x90 UNDEFINED
+ 8216, # 0x91 0x2018 LEFT SINGLE QUOTATION MARK
+ 8217, # 0x92 0x2019 RIGHT SINGLE QUOTATION MARK
+ 8220, # 0x93 0x201C LEFT DOUBLE QUOTATION MARK
+ 8221, # 0x94 0x201D RIGHT DOUBLE QUOTATION MARK
+ 8226, # 0x95 0x2022 BULLET
+ 8211, # 0x96 0x2013 EN DASH
+ 8212, # 0x97 0x2014 EM DASH
+ 732, # 0x98 0x02DC SMALL TILDE
+ 8482, # 0x99 0x2122 TRADE MARK SIGN
+ 353, # 0x9A 0x0161 LATIN SMALL LETTER S WITH CARON
+ 8250, # 0x9B 0x203A SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+ 339, # 0x9C 0x0153 LATIN SMALL LIGATURE OE
+ 65533, # 0x9D UNDEFINED
+ 382, # 0x9E 0x017E LATIN SMALL LETTER Z WITH CARON
+ 376 # 0x9F 0x0178 LATIN CAPITAL LETTER Y WITH DIAERESIS
+)
+
+xmlEntities = frozenset(('lt;', 'gt;', 'amp;', 'apos;', 'quot;'))
+
+entities = {
+ "AElig": "\xc6",
+ "AElig;": "\xc6",
+ "AMP": "&",
+ "AMP;": "&",
+ "Aacute": "\xc1",
+ "Aacute;": "\xc1",
+ "Abreve;": "\u0102",
+ "Acirc": "\xc2",
+ "Acirc;": "\xc2",
+ "Acy;": "\u0410",
+ "Afr;": "\U0001d504",
+ "Agrave": "\xc0",
+ "Agrave;": "\xc0",
+ "Alpha;": "\u0391",
+ "Amacr;": "\u0100",
+ "And;": "\u2a53",
+ "Aogon;": "\u0104",
+ "Aopf;": "\U0001d538",
+ "ApplyFunction;": "\u2061",
+ "Aring": "\xc5",
+ "Aring;": "\xc5",
+ "Ascr;": "\U0001d49c",
+ "Assign;": "\u2254",
+ "Atilde": "\xc3",
+ "Atilde;": "\xc3",
+ "Auml": "\xc4",
+ "Auml;": "\xc4",
+ "Backslash;": "\u2216",
+ "Barv;": "\u2ae7",
+ "Barwed;": "\u2306",
+ "Bcy;": "\u0411",
+ "Because;": "\u2235",
+ "Bernoullis;": "\u212c",
+ "Beta;": "\u0392",
+ "Bfr;": "\U0001d505",
+ "Bopf;": "\U0001d539",
+ "Breve;": "\u02d8",
+ "Bscr;": "\u212c",
+ "Bumpeq;": "\u224e",
+ "CHcy;": "\u0427",
+ "COPY": "\xa9",
+ "COPY;": "\xa9",
+ "Cacute;": "\u0106",
+ "Cap;": "\u22d2",
+ "CapitalDifferentialD;": "\u2145",
+ "Cayleys;": "\u212d",
+ "Ccaron;": "\u010c",
+ "Ccedil": "\xc7",
+ "Ccedil;": "\xc7",
+ "Ccirc;": "\u0108",
+ "Cconint;": "\u2230",
+ "Cdot;": "\u010a",
+ "Cedilla;": "\xb8",
+ "CenterDot;": "\xb7",
+ "Cfr;": "\u212d",
+ "Chi;": "\u03a7",
+ "CircleDot;": "\u2299",
+ "CircleMinus;": "\u2296",
+ "CirclePlus;": "\u2295",
+ "CircleTimes;": "\u2297",
+ "ClockwiseContourIntegral;": "\u2232",
+ "CloseCurlyDoubleQuote;": "\u201d",
+ "CloseCurlyQuote;": "\u2019",
+ "Colon;": "\u2237",
+ "Colone;": "\u2a74",
+ "Congruent;": "\u2261",
+ "Conint;": "\u222f",
+ "ContourIntegral;": "\u222e",
+ "Copf;": "\u2102",
+ "Coproduct;": "\u2210",
+ "CounterClockwiseContourIntegral;": "\u2233",
+ "Cross;": "\u2a2f",
+ "Cscr;": "\U0001d49e",
+ "Cup;": "\u22d3",
+ "CupCap;": "\u224d",
+ "DD;": "\u2145",
+ "DDotrahd;": "\u2911",
+ "DJcy;": "\u0402",
+ "DScy;": "\u0405",
+ "DZcy;": "\u040f",
+ "Dagger;": "\u2021",
+ "Darr;": "\u21a1",
+ "Dashv;": "\u2ae4",
+ "Dcaron;": "\u010e",
+ "Dcy;": "\u0414",
+ "Del;": "\u2207",
+ "Delta;": "\u0394",
+ "Dfr;": "\U0001d507",
+ "DiacriticalAcute;": "\xb4",
+ "DiacriticalDot;": "\u02d9",
+ "DiacriticalDoubleAcute;": "\u02dd",
+ "DiacriticalGrave;": "`",
+ "DiacriticalTilde;": "\u02dc",
+ "Diamond;": "\u22c4",
+ "DifferentialD;": "\u2146",
+ "Dopf;": "\U0001d53b",
+ "Dot;": "\xa8",
+ "DotDot;": "\u20dc",
+ "DotEqual;": "\u2250",
+ "DoubleContourIntegral;": "\u222f",
+ "DoubleDot;": "\xa8",
+ "DoubleDownArrow;": "\u21d3",
+ "DoubleLeftArrow;": "\u21d0",
+ "DoubleLeftRightArrow;": "\u21d4",
+ "DoubleLeftTee;": "\u2ae4",
+ "DoubleLongLeftArrow;": "\u27f8",
+ "DoubleLongLeftRightArrow;": "\u27fa",
+ "DoubleLongRightArrow;": "\u27f9",
+ "DoubleRightArrow;": "\u21d2",
+ "DoubleRightTee;": "\u22a8",
+ "DoubleUpArrow;": "\u21d1",
+ "DoubleUpDownArrow;": "\u21d5",
+ "DoubleVerticalBar;": "\u2225",
+ "DownArrow;": "\u2193",
+ "DownArrowBar;": "\u2913",
+ "DownArrowUpArrow;": "\u21f5",
+ "DownBreve;": "\u0311",
+ "DownLeftRightVector;": "\u2950",
+ "DownLeftTeeVector;": "\u295e",
+ "DownLeftVector;": "\u21bd",
+ "DownLeftVectorBar;": "\u2956",
+ "DownRightTeeVector;": "\u295f",
+ "DownRightVector;": "\u21c1",
+ "DownRightVectorBar;": "\u2957",
+ "DownTee;": "\u22a4",
+ "DownTeeArrow;": "\u21a7",
+ "Downarrow;": "\u21d3",
+ "Dscr;": "\U0001d49f",
+ "Dstrok;": "\u0110",
+ "ENG;": "\u014a",
+ "ETH": "\xd0",
+ "ETH;": "\xd0",
+ "Eacute": "\xc9",
+ "Eacute;": "\xc9",
+ "Ecaron;": "\u011a",
+ "Ecirc": "\xca",
+ "Ecirc;": "\xca",
+ "Ecy;": "\u042d",
+ "Edot;": "\u0116",
+ "Efr;": "\U0001d508",
+ "Egrave": "\xc8",
+ "Egrave;": "\xc8",
+ "Element;": "\u2208",
+ "Emacr;": "\u0112",
+ "EmptySmallSquare;": "\u25fb",
+ "EmptyVerySmallSquare;": "\u25ab",
+ "Eogon;": "\u0118",
+ "Eopf;": "\U0001d53c",
+ "Epsilon;": "\u0395",
+ "Equal;": "\u2a75",
+ "EqualTilde;": "\u2242",
+ "Equilibrium;": "\u21cc",
+ "Escr;": "\u2130",
+ "Esim;": "\u2a73",
+ "Eta;": "\u0397",
+ "Euml": "\xcb",
+ "Euml;": "\xcb",
+ "Exists;": "\u2203",
+ "ExponentialE;": "\u2147",
+ "Fcy;": "\u0424",
+ "Ffr;": "\U0001d509",
+ "FilledSmallSquare;": "\u25fc",
+ "FilledVerySmallSquare;": "\u25aa",
+ "Fopf;": "\U0001d53d",
+ "ForAll;": "\u2200",
+ "Fouriertrf;": "\u2131",
+ "Fscr;": "\u2131",
+ "GJcy;": "\u0403",
+ "GT": ">",
+ "GT;": ">",
+ "Gamma;": "\u0393",
+ "Gammad;": "\u03dc",
+ "Gbreve;": "\u011e",
+ "Gcedil;": "\u0122",
+ "Gcirc;": "\u011c",
+ "Gcy;": "\u0413",
+ "Gdot;": "\u0120",
+ "Gfr;": "\U0001d50a",
+ "Gg;": "\u22d9",
+ "Gopf;": "\U0001d53e",
+ "GreaterEqual;": "\u2265",
+ "GreaterEqualLess;": "\u22db",
+ "GreaterFullEqual;": "\u2267",
+ "GreaterGreater;": "\u2aa2",
+ "GreaterLess;": "\u2277",
+ "GreaterSlantEqual;": "\u2a7e",
+ "GreaterTilde;": "\u2273",
+ "Gscr;": "\U0001d4a2",
+ "Gt;": "\u226b",
+ "HARDcy;": "\u042a",
+ "Hacek;": "\u02c7",
+ "Hat;": "^",
+ "Hcirc;": "\u0124",
+ "Hfr;": "\u210c",
+ "HilbertSpace;": "\u210b",
+ "Hopf;": "\u210d",
+ "HorizontalLine;": "\u2500",
+ "Hscr;": "\u210b",
+ "Hstrok;": "\u0126",
+ "HumpDownHump;": "\u224e",
+ "HumpEqual;": "\u224f",
+ "IEcy;": "\u0415",
+ "IJlig;": "\u0132",
+ "IOcy;": "\u0401",
+ "Iacute": "\xcd",
+ "Iacute;": "\xcd",
+ "Icirc": "\xce",
+ "Icirc;": "\xce",
+ "Icy;": "\u0418",
+ "Idot;": "\u0130",
+ "Ifr;": "\u2111",
+ "Igrave": "\xcc",
+ "Igrave;": "\xcc",
+ "Im;": "\u2111",
+ "Imacr;": "\u012a",
+ "ImaginaryI;": "\u2148",
+ "Implies;": "\u21d2",
+ "Int;": "\u222c",
+ "Integral;": "\u222b",
+ "Intersection;": "\u22c2",
+ "InvisibleComma;": "\u2063",
+ "InvisibleTimes;": "\u2062",
+ "Iogon;": "\u012e",
+ "Iopf;": "\U0001d540",
+ "Iota;": "\u0399",
+ "Iscr;": "\u2110",
+ "Itilde;": "\u0128",
+ "Iukcy;": "\u0406",
+ "Iuml": "\xcf",
+ "Iuml;": "\xcf",
+ "Jcirc;": "\u0134",
+ "Jcy;": "\u0419",
+ "Jfr;": "\U0001d50d",
+ "Jopf;": "\U0001d541",
+ "Jscr;": "\U0001d4a5",
+ "Jsercy;": "\u0408",
+ "Jukcy;": "\u0404",
+ "KHcy;": "\u0425",
+ "KJcy;": "\u040c",
+ "Kappa;": "\u039a",
+ "Kcedil;": "\u0136",
+ "Kcy;": "\u041a",
+ "Kfr;": "\U0001d50e",
+ "Kopf;": "\U0001d542",
+ "Kscr;": "\U0001d4a6",
+ "LJcy;": "\u0409",
+ "LT": "<",
+ "LT;": "<",
+ "Lacute;": "\u0139",
+ "Lambda;": "\u039b",
+ "Lang;": "\u27ea",
+ "Laplacetrf;": "\u2112",
+ "Larr;": "\u219e",
+ "Lcaron;": "\u013d",
+ "Lcedil;": "\u013b",
+ "Lcy;": "\u041b",
+ "LeftAngleBracket;": "\u27e8",
+ "LeftArrow;": "\u2190",
+ "LeftArrowBar;": "\u21e4",
+ "LeftArrowRightArrow;": "\u21c6",
+ "LeftCeiling;": "\u2308",
+ "LeftDoubleBracket;": "\u27e6",
+ "LeftDownTeeVector;": "\u2961",
+ "LeftDownVector;": "\u21c3",
+ "LeftDownVectorBar;": "\u2959",
+ "LeftFloor;": "\u230a",
+ "LeftRightArrow;": "\u2194",
+ "LeftRightVector;": "\u294e",
+ "LeftTee;": "\u22a3",
+ "LeftTeeArrow;": "\u21a4",
+ "LeftTeeVector;": "\u295a",
+ "LeftTriangle;": "\u22b2",
+ "LeftTriangleBar;": "\u29cf",
+ "LeftTriangleEqual;": "\u22b4",
+ "LeftUpDownVector;": "\u2951",
+ "LeftUpTeeVector;": "\u2960",
+ "LeftUpVector;": "\u21bf",
+ "LeftUpVectorBar;": "\u2958",
+ "LeftVector;": "\u21bc",
+ "LeftVectorBar;": "\u2952",
+ "Leftarrow;": "\u21d0",
+ "Leftrightarrow;": "\u21d4",
+ "LessEqualGreater;": "\u22da",
+ "LessFullEqual;": "\u2266",
+ "LessGreater;": "\u2276",
+ "LessLess;": "\u2aa1",
+ "LessSlantEqual;": "\u2a7d",
+ "LessTilde;": "\u2272",
+ "Lfr;": "\U0001d50f",
+ "Ll;": "\u22d8",
+ "Lleftarrow;": "\u21da",
+ "Lmidot;": "\u013f",
+ "LongLeftArrow;": "\u27f5",
+ "LongLeftRightArrow;": "\u27f7",
+ "LongRightArrow;": "\u27f6",
+ "Longleftarrow;": "\u27f8",
+ "Longleftrightarrow;": "\u27fa",
+ "Longrightarrow;": "\u27f9",
+ "Lopf;": "\U0001d543",
+ "LowerLeftArrow;": "\u2199",
+ "LowerRightArrow;": "\u2198",
+ "Lscr;": "\u2112",
+ "Lsh;": "\u21b0",
+ "Lstrok;": "\u0141",
+ "Lt;": "\u226a",
+ "Map;": "\u2905",
+ "Mcy;": "\u041c",
+ "MediumSpace;": "\u205f",
+ "Mellintrf;": "\u2133",
+ "Mfr;": "\U0001d510",
+ "MinusPlus;": "\u2213",
+ "Mopf;": "\U0001d544",
+ "Mscr;": "\u2133",
+ "Mu;": "\u039c",
+ "NJcy;": "\u040a",
+ "Nacute;": "\u0143",
+ "Ncaron;": "\u0147",
+ "Ncedil;": "\u0145",
+ "Ncy;": "\u041d",
+ "NegativeMediumSpace;": "\u200b",
+ "NegativeThickSpace;": "\u200b",
+ "NegativeThinSpace;": "\u200b",
+ "NegativeVeryThinSpace;": "\u200b",
+ "NestedGreaterGreater;": "\u226b",
+ "NestedLessLess;": "\u226a",
+ "NewLine;": "\n",
+ "Nfr;": "\U0001d511",
+ "NoBreak;": "\u2060",
+ "NonBreakingSpace;": "\xa0",
+ "Nopf;": "\u2115",
+ "Not;": "\u2aec",
+ "NotCongruent;": "\u2262",
+ "NotCupCap;": "\u226d",
+ "NotDoubleVerticalBar;": "\u2226",
+ "NotElement;": "\u2209",
+ "NotEqual;": "\u2260",
+ "NotEqualTilde;": "\u2242\u0338",
+ "NotExists;": "\u2204",
+ "NotGreater;": "\u226f",
+ "NotGreaterEqual;": "\u2271",
+ "NotGreaterFullEqual;": "\u2267\u0338",
+ "NotGreaterGreater;": "\u226b\u0338",
+ "NotGreaterLess;": "\u2279",
+ "NotGreaterSlantEqual;": "\u2a7e\u0338",
+ "NotGreaterTilde;": "\u2275",
+ "NotHumpDownHump;": "\u224e\u0338",
+ "NotHumpEqual;": "\u224f\u0338",
+ "NotLeftTriangle;": "\u22ea",
+ "NotLeftTriangleBar;": "\u29cf\u0338",
+ "NotLeftTriangleEqual;": "\u22ec",
+ "NotLess;": "\u226e",
+ "NotLessEqual;": "\u2270",
+ "NotLessGreater;": "\u2278",
+ "NotLessLess;": "\u226a\u0338",
+ "NotLessSlantEqual;": "\u2a7d\u0338",
+ "NotLessTilde;": "\u2274",
+ "NotNestedGreaterGreater;": "\u2aa2\u0338",
+ "NotNestedLessLess;": "\u2aa1\u0338",
+ "NotPrecedes;": "\u2280",
+ "NotPrecedesEqual;": "\u2aaf\u0338",
+ "NotPrecedesSlantEqual;": "\u22e0",
+ "NotReverseElement;": "\u220c",
+ "NotRightTriangle;": "\u22eb",
+ "NotRightTriangleBar;": "\u29d0\u0338",
+ "NotRightTriangleEqual;": "\u22ed",
+ "NotSquareSubset;": "\u228f\u0338",
+ "NotSquareSubsetEqual;": "\u22e2",
+ "NotSquareSuperset;": "\u2290\u0338",
+ "NotSquareSupersetEqual;": "\u22e3",
+ "NotSubset;": "\u2282\u20d2",
+ "NotSubsetEqual;": "\u2288",
+ "NotSucceeds;": "\u2281",
+ "NotSucceedsEqual;": "\u2ab0\u0338",
+ "NotSucceedsSlantEqual;": "\u22e1",
+ "NotSucceedsTilde;": "\u227f\u0338",
+ "NotSuperset;": "\u2283\u20d2",
+ "NotSupersetEqual;": "\u2289",
+ "NotTilde;": "\u2241",
+ "NotTildeEqual;": "\u2244",
+ "NotTildeFullEqual;": "\u2247",
+ "NotTildeTilde;": "\u2249",
+ "NotVerticalBar;": "\u2224",
+ "Nscr;": "\U0001d4a9",
+ "Ntilde": "\xd1",
+ "Ntilde;": "\xd1",
+ "Nu;": "\u039d",
+ "OElig;": "\u0152",
+ "Oacute": "\xd3",
+ "Oacute;": "\xd3",
+ "Ocirc": "\xd4",
+ "Ocirc;": "\xd4",
+ "Ocy;": "\u041e",
+ "Odblac;": "\u0150",
+ "Ofr;": "\U0001d512",
+ "Ograve": "\xd2",
+ "Ograve;": "\xd2",
+ "Omacr;": "\u014c",
+ "Omega;": "\u03a9",
+ "Omicron;": "\u039f",
+ "Oopf;": "\U0001d546",
+ "OpenCurlyDoubleQuote;": "\u201c",
+ "OpenCurlyQuote;": "\u2018",
+ "Or;": "\u2a54",
+ "Oscr;": "\U0001d4aa",
+ "Oslash": "\xd8",
+ "Oslash;": "\xd8",
+ "Otilde": "\xd5",
+ "Otilde;": "\xd5",
+ "Otimes;": "\u2a37",
+ "Ouml": "\xd6",
+ "Ouml;": "\xd6",
+ "OverBar;": "\u203e",
+ "OverBrace;": "\u23de",
+ "OverBracket;": "\u23b4",
+ "OverParenthesis;": "\u23dc",
+ "PartialD;": "\u2202",
+ "Pcy;": "\u041f",
+ "Pfr;": "\U0001d513",
+ "Phi;": "\u03a6",
+ "Pi;": "\u03a0",
+ "PlusMinus;": "\xb1",
+ "Poincareplane;": "\u210c",
+ "Popf;": "\u2119",
+ "Pr;": "\u2abb",
+ "Precedes;": "\u227a",
+ "PrecedesEqual;": "\u2aaf",
+ "PrecedesSlantEqual;": "\u227c",
+ "PrecedesTilde;": "\u227e",
+ "Prime;": "\u2033",
+ "Product;": "\u220f",
+ "Proportion;": "\u2237",
+ "Proportional;": "\u221d",
+ "Pscr;": "\U0001d4ab",
+ "Psi;": "\u03a8",
+ "QUOT": "\"",
+ "QUOT;": "\"",
+ "Qfr;": "\U0001d514",
+ "Qopf;": "\u211a",
+ "Qscr;": "\U0001d4ac",
+ "RBarr;": "\u2910",
+ "REG": "\xae",
+ "REG;": "\xae",
+ "Racute;": "\u0154",
+ "Rang;": "\u27eb",
+ "Rarr;": "\u21a0",
+ "Rarrtl;": "\u2916",
+ "Rcaron;": "\u0158",
+ "Rcedil;": "\u0156",
+ "Rcy;": "\u0420",
+ "Re;": "\u211c",
+ "ReverseElement;": "\u220b",
+ "ReverseEquilibrium;": "\u21cb",
+ "ReverseUpEquilibrium;": "\u296f",
+ "Rfr;": "\u211c",
+ "Rho;": "\u03a1",
+ "RightAngleBracket;": "\u27e9",
+ "RightArrow;": "\u2192",
+ "RightArrowBar;": "\u21e5",
+ "RightArrowLeftArrow;": "\u21c4",
+ "RightCeiling;": "\u2309",
+ "RightDoubleBracket;": "\u27e7",
+ "RightDownTeeVector;": "\u295d",
+ "RightDownVector;": "\u21c2",
+ "RightDownVectorBar;": "\u2955",
+ "RightFloor;": "\u230b",
+ "RightTee;": "\u22a2",
+ "RightTeeArrow;": "\u21a6",
+ "RightTeeVector;": "\u295b",
+ "RightTriangle;": "\u22b3",
+ "RightTriangleBar;": "\u29d0",
+ "RightTriangleEqual;": "\u22b5",
+ "RightUpDownVector;": "\u294f",
+ "RightUpTeeVector;": "\u295c",
+ "RightUpVector;": "\u21be",
+ "RightUpVectorBar;": "\u2954",
+ "RightVector;": "\u21c0",
+ "RightVectorBar;": "\u2953",
+ "Rightarrow;": "\u21d2",
+ "Ropf;": "\u211d",
+ "RoundImplies;": "\u2970",
+ "Rrightarrow;": "\u21db",
+ "Rscr;": "\u211b",
+ "Rsh;": "\u21b1",
+ "RuleDelayed;": "\u29f4",
+ "SHCHcy;": "\u0429",
+ "SHcy;": "\u0428",
+ "SOFTcy;": "\u042c",
+ "Sacute;": "\u015a",
+ "Sc;": "\u2abc",
+ "Scaron;": "\u0160",
+ "Scedil;": "\u015e",
+ "Scirc;": "\u015c",
+ "Scy;": "\u0421",
+ "Sfr;": "\U0001d516",
+ "ShortDownArrow;": "\u2193",
+ "ShortLeftArrow;": "\u2190",
+ "ShortRightArrow;": "\u2192",
+ "ShortUpArrow;": "\u2191",
+ "Sigma;": "\u03a3",
+ "SmallCircle;": "\u2218",
+ "Sopf;": "\U0001d54a",
+ "Sqrt;": "\u221a",
+ "Square;": "\u25a1",
+ "SquareIntersection;": "\u2293",
+ "SquareSubset;": "\u228f",
+ "SquareSubsetEqual;": "\u2291",
+ "SquareSuperset;": "\u2290",
+ "SquareSupersetEqual;": "\u2292",
+ "SquareUnion;": "\u2294",
+ "Sscr;": "\U0001d4ae",
+ "Star;": "\u22c6",
+ "Sub;": "\u22d0",
+ "Subset;": "\u22d0",
+ "SubsetEqual;": "\u2286",
+ "Succeeds;": "\u227b",
+ "SucceedsEqual;": "\u2ab0",
+ "SucceedsSlantEqual;": "\u227d",
+ "SucceedsTilde;": "\u227f",
+ "SuchThat;": "\u220b",
+ "Sum;": "\u2211",
+ "Sup;": "\u22d1",
+ "Superset;": "\u2283",
+ "SupersetEqual;": "\u2287",
+ "Supset;": "\u22d1",
+ "THORN": "\xde",
+ "THORN;": "\xde",
+ "TRADE;": "\u2122",
+ "TSHcy;": "\u040b",
+ "TScy;": "\u0426",
+ "Tab;": "\t",
+ "Tau;": "\u03a4",
+ "Tcaron;": "\u0164",
+ "Tcedil;": "\u0162",
+ "Tcy;": "\u0422",
+ "Tfr;": "\U0001d517",
+ "Therefore;": "\u2234",
+ "Theta;": "\u0398",
+ "ThickSpace;": "\u205f\u200a",
+ "ThinSpace;": "\u2009",
+ "Tilde;": "\u223c",
+ "TildeEqual;": "\u2243",
+ "TildeFullEqual;": "\u2245",
+ "TildeTilde;": "\u2248",
+ "Topf;": "\U0001d54b",
+ "TripleDot;": "\u20db",
+ "Tscr;": "\U0001d4af",
+ "Tstrok;": "\u0166",
+ "Uacute": "\xda",
+ "Uacute;": "\xda",
+ "Uarr;": "\u219f",
+ "Uarrocir;": "\u2949",
+ "Ubrcy;": "\u040e",
+ "Ubreve;": "\u016c",
+ "Ucirc": "\xdb",
+ "Ucirc;": "\xdb",
+ "Ucy;": "\u0423",
+ "Udblac;": "\u0170",
+ "Ufr;": "\U0001d518",
+ "Ugrave": "\xd9",
+ "Ugrave;": "\xd9",
+ "Umacr;": "\u016a",
+ "UnderBar;": "_",
+ "UnderBrace;": "\u23df",
+ "UnderBracket;": "\u23b5",
+ "UnderParenthesis;": "\u23dd",
+ "Union;": "\u22c3",
+ "UnionPlus;": "\u228e",
+ "Uogon;": "\u0172",
+ "Uopf;": "\U0001d54c",
+ "UpArrow;": "\u2191",
+ "UpArrowBar;": "\u2912",
+ "UpArrowDownArrow;": "\u21c5",
+ "UpDownArrow;": "\u2195",
+ "UpEquilibrium;": "\u296e",
+ "UpTee;": "\u22a5",
+ "UpTeeArrow;": "\u21a5",
+ "Uparrow;": "\u21d1",
+ "Updownarrow;": "\u21d5",
+ "UpperLeftArrow;": "\u2196",
+ "UpperRightArrow;": "\u2197",
+ "Upsi;": "\u03d2",
+ "Upsilon;": "\u03a5",
+ "Uring;": "\u016e",
+ "Uscr;": "\U0001d4b0",
+ "Utilde;": "\u0168",
+ "Uuml": "\xdc",
+ "Uuml;": "\xdc",
+ "VDash;": "\u22ab",
+ "Vbar;": "\u2aeb",
+ "Vcy;": "\u0412",
+ "Vdash;": "\u22a9",
+ "Vdashl;": "\u2ae6",
+ "Vee;": "\u22c1",
+ "Verbar;": "\u2016",
+ "Vert;": "\u2016",
+ "VerticalBar;": "\u2223",
+ "VerticalLine;": "|",
+ "VerticalSeparator;": "\u2758",
+ "VerticalTilde;": "\u2240",
+ "VeryThinSpace;": "\u200a",
+ "Vfr;": "\U0001d519",
+ "Vopf;": "\U0001d54d",
+ "Vscr;": "\U0001d4b1",
+ "Vvdash;": "\u22aa",
+ "Wcirc;": "\u0174",
+ "Wedge;": "\u22c0",
+ "Wfr;": "\U0001d51a",
+ "Wopf;": "\U0001d54e",
+ "Wscr;": "\U0001d4b2",
+ "Xfr;": "\U0001d51b",
+ "Xi;": "\u039e",
+ "Xopf;": "\U0001d54f",
+ "Xscr;": "\U0001d4b3",
+ "YAcy;": "\u042f",
+ "YIcy;": "\u0407",
+ "YUcy;": "\u042e",
+ "Yacute": "\xdd",
+ "Yacute;": "\xdd",
+ "Ycirc;": "\u0176",
+ "Ycy;": "\u042b",
+ "Yfr;": "\U0001d51c",
+ "Yopf;": "\U0001d550",
+ "Yscr;": "\U0001d4b4",
+ "Yuml;": "\u0178",
+ "ZHcy;": "\u0416",
+ "Zacute;": "\u0179",
+ "Zcaron;": "\u017d",
+ "Zcy;": "\u0417",
+ "Zdot;": "\u017b",
+ "ZeroWidthSpace;": "\u200b",
+ "Zeta;": "\u0396",
+ "Zfr;": "\u2128",
+ "Zopf;": "\u2124",
+ "Zscr;": "\U0001d4b5",
+ "aacute": "\xe1",
+ "aacute;": "\xe1",
+ "abreve;": "\u0103",
+ "ac;": "\u223e",
+ "acE;": "\u223e\u0333",
+ "acd;": "\u223f",
+ "acirc": "\xe2",
+ "acirc;": "\xe2",
+ "acute": "\xb4",
+ "acute;": "\xb4",
+ "acy;": "\u0430",
+ "aelig": "\xe6",
+ "aelig;": "\xe6",
+ "af;": "\u2061",
+ "afr;": "\U0001d51e",
+ "agrave": "\xe0",
+ "agrave;": "\xe0",
+ "alefsym;": "\u2135",
+ "aleph;": "\u2135",
+ "alpha;": "\u03b1",
+ "amacr;": "\u0101",
+ "amalg;": "\u2a3f",
+ "amp": "&",
+ "amp;": "&",
+ "and;": "\u2227",
+ "andand;": "\u2a55",
+ "andd;": "\u2a5c",
+ "andslope;": "\u2a58",
+ "andv;": "\u2a5a",
+ "ang;": "\u2220",
+ "ange;": "\u29a4",
+ "angle;": "\u2220",
+ "angmsd;": "\u2221",
+ "angmsdaa;": "\u29a8",
+ "angmsdab;": "\u29a9",
+ "angmsdac;": "\u29aa",
+ "angmsdad;": "\u29ab",
+ "angmsdae;": "\u29ac",
+ "angmsdaf;": "\u29ad",
+ "angmsdag;": "\u29ae",
+ "angmsdah;": "\u29af",
+ "angrt;": "\u221f",
+ "angrtvb;": "\u22be",
+ "angrtvbd;": "\u299d",
+ "angsph;": "\u2222",
+ "angst;": "\xc5",
+ "angzarr;": "\u237c",
+ "aogon;": "\u0105",
+ "aopf;": "\U0001d552",
+ "ap;": "\u2248",
+ "apE;": "\u2a70",
+ "apacir;": "\u2a6f",
+ "ape;": "\u224a",
+ "apid;": "\u224b",
+ "apos;": "'",
+ "approx;": "\u2248",
+ "approxeq;": "\u224a",
+ "aring": "\xe5",
+ "aring;": "\xe5",
+ "ascr;": "\U0001d4b6",
+ "ast;": "*",
+ "asymp;": "\u2248",
+ "asympeq;": "\u224d",
+ "atilde": "\xe3",
+ "atilde;": "\xe3",
+ "auml": "\xe4",
+ "auml;": "\xe4",
+ "awconint;": "\u2233",
+ "awint;": "\u2a11",
+ "bNot;": "\u2aed",
+ "backcong;": "\u224c",
+ "backepsilon;": "\u03f6",
+ "backprime;": "\u2035",
+ "backsim;": "\u223d",
+ "backsimeq;": "\u22cd",
+ "barvee;": "\u22bd",
+ "barwed;": "\u2305",
+ "barwedge;": "\u2305",
+ "bbrk;": "\u23b5",
+ "bbrktbrk;": "\u23b6",
+ "bcong;": "\u224c",
+ "bcy;": "\u0431",
+ "bdquo;": "\u201e",
+ "becaus;": "\u2235",
+ "because;": "\u2235",
+ "bemptyv;": "\u29b0",
+ "bepsi;": "\u03f6",
+ "bernou;": "\u212c",
+ "beta;": "\u03b2",
+ "beth;": "\u2136",
+ "between;": "\u226c",
+ "bfr;": "\U0001d51f",
+ "bigcap;": "\u22c2",
+ "bigcirc;": "\u25ef",
+ "bigcup;": "\u22c3",
+ "bigodot;": "\u2a00",
+ "bigoplus;": "\u2a01",
+ "bigotimes;": "\u2a02",
+ "bigsqcup;": "\u2a06",
+ "bigstar;": "\u2605",
+ "bigtriangledown;": "\u25bd",
+ "bigtriangleup;": "\u25b3",
+ "biguplus;": "\u2a04",
+ "bigvee;": "\u22c1",
+ "bigwedge;": "\u22c0",
+ "bkarow;": "\u290d",
+ "blacklozenge;": "\u29eb",
+ "blacksquare;": "\u25aa",
+ "blacktriangle;": "\u25b4",
+ "blacktriangledown;": "\u25be",
+ "blacktriangleleft;": "\u25c2",
+ "blacktriangleright;": "\u25b8",
+ "blank;": "\u2423",
+ "blk12;": "\u2592",
+ "blk14;": "\u2591",
+ "blk34;": "\u2593",
+ "block;": "\u2588",
+ "bne;": "=\u20e5",
+ "bnequiv;": "\u2261\u20e5",
+ "bnot;": "\u2310",
+ "bopf;": "\U0001d553",
+ "bot;": "\u22a5",
+ "bottom;": "\u22a5",
+ "bowtie;": "\u22c8",
+ "boxDL;": "\u2557",
+ "boxDR;": "\u2554",
+ "boxDl;": "\u2556",
+ "boxDr;": "\u2553",
+ "boxH;": "\u2550",
+ "boxHD;": "\u2566",
+ "boxHU;": "\u2569",
+ "boxHd;": "\u2564",
+ "boxHu;": "\u2567",
+ "boxUL;": "\u255d",
+ "boxUR;": "\u255a",
+ "boxUl;": "\u255c",
+ "boxUr;": "\u2559",
+ "boxV;": "\u2551",
+ "boxVH;": "\u256c",
+ "boxVL;": "\u2563",
+ "boxVR;": "\u2560",
+ "boxVh;": "\u256b",
+ "boxVl;": "\u2562",
+ "boxVr;": "\u255f",
+ "boxbox;": "\u29c9",
+ "boxdL;": "\u2555",
+ "boxdR;": "\u2552",
+ "boxdl;": "\u2510",
+ "boxdr;": "\u250c",
+ "boxh;": "\u2500",
+ "boxhD;": "\u2565",
+ "boxhU;": "\u2568",
+ "boxhd;": "\u252c",
+ "boxhu;": "\u2534",
+ "boxminus;": "\u229f",
+ "boxplus;": "\u229e",
+ "boxtimes;": "\u22a0",
+ "boxuL;": "\u255b",
+ "boxuR;": "\u2558",
+ "boxul;": "\u2518",
+ "boxur;": "\u2514",
+ "boxv;": "\u2502",
+ "boxvH;": "\u256a",
+ "boxvL;": "\u2561",
+ "boxvR;": "\u255e",
+ "boxvh;": "\u253c",
+ "boxvl;": "\u2524",
+ "boxvr;": "\u251c",
+ "bprime;": "\u2035",
+ "breve;": "\u02d8",
+ "brvbar": "\xa6",
+ "brvbar;": "\xa6",
+ "bscr;": "\U0001d4b7",
+ "bsemi;": "\u204f",
+ "bsim;": "\u223d",
+ "bsime;": "\u22cd",
+ "bsol;": "\\",
+ "bsolb;": "\u29c5",
+ "bsolhsub;": "\u27c8",
+ "bull;": "\u2022",
+ "bullet;": "\u2022",
+ "bump;": "\u224e",
+ "bumpE;": "\u2aae",
+ "bumpe;": "\u224f",
+ "bumpeq;": "\u224f",
+ "cacute;": "\u0107",
+ "cap;": "\u2229",
+ "capand;": "\u2a44",
+ "capbrcup;": "\u2a49",
+ "capcap;": "\u2a4b",
+ "capcup;": "\u2a47",
+ "capdot;": "\u2a40",
+ "caps;": "\u2229\ufe00",
+ "caret;": "\u2041",
+ "caron;": "\u02c7",
+ "ccaps;": "\u2a4d",
+ "ccaron;": "\u010d",
+ "ccedil": "\xe7",
+ "ccedil;": "\xe7",
+ "ccirc;": "\u0109",
+ "ccups;": "\u2a4c",
+ "ccupssm;": "\u2a50",
+ "cdot;": "\u010b",
+ "cedil": "\xb8",
+ "cedil;": "\xb8",
+ "cemptyv;": "\u29b2",
+ "cent": "\xa2",
+ "cent;": "\xa2",
+ "centerdot;": "\xb7",
+ "cfr;": "\U0001d520",
+ "chcy;": "\u0447",
+ "check;": "\u2713",
+ "checkmark;": "\u2713",
+ "chi;": "\u03c7",
+ "cir;": "\u25cb",
+ "cirE;": "\u29c3",
+ "circ;": "\u02c6",
+ "circeq;": "\u2257",
+ "circlearrowleft;": "\u21ba",
+ "circlearrowright;": "\u21bb",
+ "circledR;": "\xae",
+ "circledS;": "\u24c8",
+ "circledast;": "\u229b",
+ "circledcirc;": "\u229a",
+ "circleddash;": "\u229d",
+ "cire;": "\u2257",
+ "cirfnint;": "\u2a10",
+ "cirmid;": "\u2aef",
+ "cirscir;": "\u29c2",
+ "clubs;": "\u2663",
+ "clubsuit;": "\u2663",
+ "colon;": ":",
+ "colone;": "\u2254",
+ "coloneq;": "\u2254",
+ "comma;": ",",
+ "commat;": "@",
+ "comp;": "\u2201",
+ "compfn;": "\u2218",
+ "complement;": "\u2201",
+ "complexes;": "\u2102",
+ "cong;": "\u2245",
+ "congdot;": "\u2a6d",
+ "conint;": "\u222e",
+ "copf;": "\U0001d554",
+ "coprod;": "\u2210",
+ "copy": "\xa9",
+ "copy;": "\xa9",
+ "copysr;": "\u2117",
+ "crarr;": "\u21b5",
+ "cross;": "\u2717",
+ "cscr;": "\U0001d4b8",
+ "csub;": "\u2acf",
+ "csube;": "\u2ad1",
+ "csup;": "\u2ad0",
+ "csupe;": "\u2ad2",
+ "ctdot;": "\u22ef",
+ "cudarrl;": "\u2938",
+ "cudarrr;": "\u2935",
+ "cuepr;": "\u22de",
+ "cuesc;": "\u22df",
+ "cularr;": "\u21b6",
+ "cularrp;": "\u293d",
+ "cup;": "\u222a",
+ "cupbrcap;": "\u2a48",
+ "cupcap;": "\u2a46",
+ "cupcup;": "\u2a4a",
+ "cupdot;": "\u228d",
+ "cupor;": "\u2a45",
+ "cups;": "\u222a\ufe00",
+ "curarr;": "\u21b7",
+ "curarrm;": "\u293c",
+ "curlyeqprec;": "\u22de",
+ "curlyeqsucc;": "\u22df",
+ "curlyvee;": "\u22ce",
+ "curlywedge;": "\u22cf",
+ "curren": "\xa4",
+ "curren;": "\xa4",
+ "curvearrowleft;": "\u21b6",
+ "curvearrowright;": "\u21b7",
+ "cuvee;": "\u22ce",
+ "cuwed;": "\u22cf",
+ "cwconint;": "\u2232",
+ "cwint;": "\u2231",
+ "cylcty;": "\u232d",
+ "dArr;": "\u21d3",
+ "dHar;": "\u2965",
+ "dagger;": "\u2020",
+ "daleth;": "\u2138",
+ "darr;": "\u2193",
+ "dash;": "\u2010",
+ "dashv;": "\u22a3",
+ "dbkarow;": "\u290f",
+ "dblac;": "\u02dd",
+ "dcaron;": "\u010f",
+ "dcy;": "\u0434",
+ "dd;": "\u2146",
+ "ddagger;": "\u2021",
+ "ddarr;": "\u21ca",
+ "ddotseq;": "\u2a77",
+ "deg": "\xb0",
+ "deg;": "\xb0",
+ "delta;": "\u03b4",
+ "demptyv;": "\u29b1",
+ "dfisht;": "\u297f",
+ "dfr;": "\U0001d521",
+ "dharl;": "\u21c3",
+ "dharr;": "\u21c2",
+ "diam;": "\u22c4",
+ "diamond;": "\u22c4",
+ "diamondsuit;": "\u2666",
+ "diams;": "\u2666",
+ "die;": "\xa8",
+ "digamma;": "\u03dd",
+ "disin;": "\u22f2",
+ "div;": "\xf7",
+ "divide": "\xf7",
+ "divide;": "\xf7",
+ "divideontimes;": "\u22c7",
+ "divonx;": "\u22c7",
+ "djcy;": "\u0452",
+ "dlcorn;": "\u231e",
+ "dlcrop;": "\u230d",
+ "dollar;": "$",
+ "dopf;": "\U0001d555",
+ "dot;": "\u02d9",
+ "doteq;": "\u2250",
+ "doteqdot;": "\u2251",
+ "dotminus;": "\u2238",
+ "dotplus;": "\u2214",
+ "dotsquare;": "\u22a1",
+ "doublebarwedge;": "\u2306",
+ "downarrow;": "\u2193",
+ "downdownarrows;": "\u21ca",
+ "downharpoonleft;": "\u21c3",
+ "downharpoonright;": "\u21c2",
+ "drbkarow;": "\u2910",
+ "drcorn;": "\u231f",
+ "drcrop;": "\u230c",
+ "dscr;": "\U0001d4b9",
+ "dscy;": "\u0455",
+ "dsol;": "\u29f6",
+ "dstrok;": "\u0111",
+ "dtdot;": "\u22f1",
+ "dtri;": "\u25bf",
+ "dtrif;": "\u25be",
+ "duarr;": "\u21f5",
+ "duhar;": "\u296f",
+ "dwangle;": "\u29a6",
+ "dzcy;": "\u045f",
+ "dzigrarr;": "\u27ff",
+ "eDDot;": "\u2a77",
+ "eDot;": "\u2251",
+ "eacute": "\xe9",
+ "eacute;": "\xe9",
+ "easter;": "\u2a6e",
+ "ecaron;": "\u011b",
+ "ecir;": "\u2256",
+ "ecirc": "\xea",
+ "ecirc;": "\xea",
+ "ecolon;": "\u2255",
+ "ecy;": "\u044d",
+ "edot;": "\u0117",
+ "ee;": "\u2147",
+ "efDot;": "\u2252",
+ "efr;": "\U0001d522",
+ "eg;": "\u2a9a",
+ "egrave": "\xe8",
+ "egrave;": "\xe8",
+ "egs;": "\u2a96",
+ "egsdot;": "\u2a98",
+ "el;": "\u2a99",
+ "elinters;": "\u23e7",
+ "ell;": "\u2113",
+ "els;": "\u2a95",
+ "elsdot;": "\u2a97",
+ "emacr;": "\u0113",
+ "empty;": "\u2205",
+ "emptyset;": "\u2205",
+ "emptyv;": "\u2205",
+ "emsp13;": "\u2004",
+ "emsp14;": "\u2005",
+ "emsp;": "\u2003",
+ "eng;": "\u014b",
+ "ensp;": "\u2002",
+ "eogon;": "\u0119",
+ "eopf;": "\U0001d556",
+ "epar;": "\u22d5",
+ "eparsl;": "\u29e3",
+ "eplus;": "\u2a71",
+ "epsi;": "\u03b5",
+ "epsilon;": "\u03b5",
+ "epsiv;": "\u03f5",
+ "eqcirc;": "\u2256",
+ "eqcolon;": "\u2255",
+ "eqsim;": "\u2242",
+ "eqslantgtr;": "\u2a96",
+ "eqslantless;": "\u2a95",
+ "equals;": "=",
+ "equest;": "\u225f",
+ "equiv;": "\u2261",
+ "equivDD;": "\u2a78",
+ "eqvparsl;": "\u29e5",
+ "erDot;": "\u2253",
+ "erarr;": "\u2971",
+ "escr;": "\u212f",
+ "esdot;": "\u2250",
+ "esim;": "\u2242",
+ "eta;": "\u03b7",
+ "eth": "\xf0",
+ "eth;": "\xf0",
+ "euml": "\xeb",
+ "euml;": "\xeb",
+ "euro;": "\u20ac",
+ "excl;": "!",
+ "exist;": "\u2203",
+ "expectation;": "\u2130",
+ "exponentiale;": "\u2147",
+ "fallingdotseq;": "\u2252",
+ "fcy;": "\u0444",
+ "female;": "\u2640",
+ "ffilig;": "\ufb03",
+ "fflig;": "\ufb00",
+ "ffllig;": "\ufb04",
+ "ffr;": "\U0001d523",
+ "filig;": "\ufb01",
+ "fjlig;": "fj",
+ "flat;": "\u266d",
+ "fllig;": "\ufb02",
+ "fltns;": "\u25b1",
+ "fnof;": "\u0192",
+ "fopf;": "\U0001d557",
+ "forall;": "\u2200",
+ "fork;": "\u22d4",
+ "forkv;": "\u2ad9",
+ "fpartint;": "\u2a0d",
+ "frac12": "\xbd",
+ "frac12;": "\xbd",
+ "frac13;": "\u2153",
+ "frac14": "\xbc",
+ "frac14;": "\xbc",
+ "frac15;": "\u2155",
+ "frac16;": "\u2159",
+ "frac18;": "\u215b",
+ "frac23;": "\u2154",
+ "frac25;": "\u2156",
+ "frac34": "\xbe",
+ "frac34;": "\xbe",
+ "frac35;": "\u2157",
+ "frac38;": "\u215c",
+ "frac45;": "\u2158",
+ "frac56;": "\u215a",
+ "frac58;": "\u215d",
+ "frac78;": "\u215e",
+ "frasl;": "\u2044",
+ "frown;": "\u2322",
+ "fscr;": "\U0001d4bb",
+ "gE;": "\u2267",
+ "gEl;": "\u2a8c",
+ "gacute;": "\u01f5",
+ "gamma;": "\u03b3",
+ "gammad;": "\u03dd",
+ "gap;": "\u2a86",
+ "gbreve;": "\u011f",
+ "gcirc;": "\u011d",
+ "gcy;": "\u0433",
+ "gdot;": "\u0121",
+ "ge;": "\u2265",
+ "gel;": "\u22db",
+ "geq;": "\u2265",
+ "geqq;": "\u2267",
+ "geqslant;": "\u2a7e",
+ "ges;": "\u2a7e",
+ "gescc;": "\u2aa9",
+ "gesdot;": "\u2a80",
+ "gesdoto;": "\u2a82",
+ "gesdotol;": "\u2a84",
+ "gesl;": "\u22db\ufe00",
+ "gesles;": "\u2a94",
+ "gfr;": "\U0001d524",
+ "gg;": "\u226b",
+ "ggg;": "\u22d9",
+ "gimel;": "\u2137",
+ "gjcy;": "\u0453",
+ "gl;": "\u2277",
+ "glE;": "\u2a92",
+ "gla;": "\u2aa5",
+ "glj;": "\u2aa4",
+ "gnE;": "\u2269",
+ "gnap;": "\u2a8a",
+ "gnapprox;": "\u2a8a",
+ "gne;": "\u2a88",
+ "gneq;": "\u2a88",
+ "gneqq;": "\u2269",
+ "gnsim;": "\u22e7",
+ "gopf;": "\U0001d558",
+ "grave;": "`",
+ "gscr;": "\u210a",
+ "gsim;": "\u2273",
+ "gsime;": "\u2a8e",
+ "gsiml;": "\u2a90",
+ "gt": ">",
+ "gt;": ">",
+ "gtcc;": "\u2aa7",
+ "gtcir;": "\u2a7a",
+ "gtdot;": "\u22d7",
+ "gtlPar;": "\u2995",
+ "gtquest;": "\u2a7c",
+ "gtrapprox;": "\u2a86",
+ "gtrarr;": "\u2978",
+ "gtrdot;": "\u22d7",
+ "gtreqless;": "\u22db",
+ "gtreqqless;": "\u2a8c",
+ "gtrless;": "\u2277",
+ "gtrsim;": "\u2273",
+ "gvertneqq;": "\u2269\ufe00",
+ "gvnE;": "\u2269\ufe00",
+ "hArr;": "\u21d4",
+ "hairsp;": "\u200a",
+ "half;": "\xbd",
+ "hamilt;": "\u210b",
+ "hardcy;": "\u044a",
+ "harr;": "\u2194",
+ "harrcir;": "\u2948",
+ "harrw;": "\u21ad",
+ "hbar;": "\u210f",
+ "hcirc;": "\u0125",
+ "hearts;": "\u2665",
+ "heartsuit;": "\u2665",
+ "hellip;": "\u2026",
+ "hercon;": "\u22b9",
+ "hfr;": "\U0001d525",
+ "hksearow;": "\u2925",
+ "hkswarow;": "\u2926",
+ "hoarr;": "\u21ff",
+ "homtht;": "\u223b",
+ "hookleftarrow;": "\u21a9",
+ "hookrightarrow;": "\u21aa",
+ "hopf;": "\U0001d559",
+ "horbar;": "\u2015",
+ "hscr;": "\U0001d4bd",
+ "hslash;": "\u210f",
+ "hstrok;": "\u0127",
+ "hybull;": "\u2043",
+ "hyphen;": "\u2010",
+ "iacute": "\xed",
+ "iacute;": "\xed",
+ "ic;": "\u2063",
+ "icirc": "\xee",
+ "icirc;": "\xee",
+ "icy;": "\u0438",
+ "iecy;": "\u0435",
+ "iexcl": "\xa1",
+ "iexcl;": "\xa1",
+ "iff;": "\u21d4",
+ "ifr;": "\U0001d526",
+ "igrave": "\xec",
+ "igrave;": "\xec",
+ "ii;": "\u2148",
+ "iiiint;": "\u2a0c",
+ "iiint;": "\u222d",
+ "iinfin;": "\u29dc",
+ "iiota;": "\u2129",
+ "ijlig;": "\u0133",
+ "imacr;": "\u012b",
+ "image;": "\u2111",
+ "imagline;": "\u2110",
+ "imagpart;": "\u2111",
+ "imath;": "\u0131",
+ "imof;": "\u22b7",
+ "imped;": "\u01b5",
+ "in;": "\u2208",
+ "incare;": "\u2105",
+ "infin;": "\u221e",
+ "infintie;": "\u29dd",
+ "inodot;": "\u0131",
+ "int;": "\u222b",
+ "intcal;": "\u22ba",
+ "integers;": "\u2124",
+ "intercal;": "\u22ba",
+ "intlarhk;": "\u2a17",
+ "intprod;": "\u2a3c",
+ "iocy;": "\u0451",
+ "iogon;": "\u012f",
+ "iopf;": "\U0001d55a",
+ "iota;": "\u03b9",
+ "iprod;": "\u2a3c",
+ "iquest": "\xbf",
+ "iquest;": "\xbf",
+ "iscr;": "\U0001d4be",
+ "isin;": "\u2208",
+ "isinE;": "\u22f9",
+ "isindot;": "\u22f5",
+ "isins;": "\u22f4",
+ "isinsv;": "\u22f3",
+ "isinv;": "\u2208",
+ "it;": "\u2062",
+ "itilde;": "\u0129",
+ "iukcy;": "\u0456",
+ "iuml": "\xef",
+ "iuml;": "\xef",
+ "jcirc;": "\u0135",
+ "jcy;": "\u0439",
+ "jfr;": "\U0001d527",
+ "jmath;": "\u0237",
+ "jopf;": "\U0001d55b",
+ "jscr;": "\U0001d4bf",
+ "jsercy;": "\u0458",
+ "jukcy;": "\u0454",
+ "kappa;": "\u03ba",
+ "kappav;": "\u03f0",
+ "kcedil;": "\u0137",
+ "kcy;": "\u043a",
+ "kfr;": "\U0001d528",
+ "kgreen;": "\u0138",
+ "khcy;": "\u0445",
+ "kjcy;": "\u045c",
+ "kopf;": "\U0001d55c",
+ "kscr;": "\U0001d4c0",
+ "lAarr;": "\u21da",
+ "lArr;": "\u21d0",
+ "lAtail;": "\u291b",
+ "lBarr;": "\u290e",
+ "lE;": "\u2266",
+ "lEg;": "\u2a8b",
+ "lHar;": "\u2962",
+ "lacute;": "\u013a",
+ "laemptyv;": "\u29b4",
+ "lagran;": "\u2112",
+ "lambda;": "\u03bb",
+ "lang;": "\u27e8",
+ "langd;": "\u2991",
+ "langle;": "\u27e8",
+ "lap;": "\u2a85",
+ "laquo": "\xab",
+ "laquo;": "\xab",
+ "larr;": "\u2190",
+ "larrb;": "\u21e4",
+ "larrbfs;": "\u291f",
+ "larrfs;": "\u291d",
+ "larrhk;": "\u21a9",
+ "larrlp;": "\u21ab",
+ "larrpl;": "\u2939",
+ "larrsim;": "\u2973",
+ "larrtl;": "\u21a2",
+ "lat;": "\u2aab",
+ "latail;": "\u2919",
+ "late;": "\u2aad",
+ "lates;": "\u2aad\ufe00",
+ "lbarr;": "\u290c",
+ "lbbrk;": "\u2772",
+ "lbrace;": "{",
+ "lbrack;": "[",
+ "lbrke;": "\u298b",
+ "lbrksld;": "\u298f",
+ "lbrkslu;": "\u298d",
+ "lcaron;": "\u013e",
+ "lcedil;": "\u013c",
+ "lceil;": "\u2308",
+ "lcub;": "{",
+ "lcy;": "\u043b",
+ "ldca;": "\u2936",
+ "ldquo;": "\u201c",
+ "ldquor;": "\u201e",
+ "ldrdhar;": "\u2967",
+ "ldrushar;": "\u294b",
+ "ldsh;": "\u21b2",
+ "le;": "\u2264",
+ "leftarrow;": "\u2190",
+ "leftarrowtail;": "\u21a2",
+ "leftharpoondown;": "\u21bd",
+ "leftharpoonup;": "\u21bc",
+ "leftleftarrows;": "\u21c7",
+ "leftrightarrow;": "\u2194",
+ "leftrightarrows;": "\u21c6",
+ "leftrightharpoons;": "\u21cb",
+ "leftrightsquigarrow;": "\u21ad",
+ "leftthreetimes;": "\u22cb",
+ "leg;": "\u22da",
+ "leq;": "\u2264",
+ "leqq;": "\u2266",
+ "leqslant;": "\u2a7d",
+ "les;": "\u2a7d",
+ "lescc;": "\u2aa8",
+ "lesdot;": "\u2a7f",
+ "lesdoto;": "\u2a81",
+ "lesdotor;": "\u2a83",
+ "lesg;": "\u22da\ufe00",
+ "lesges;": "\u2a93",
+ "lessapprox;": "\u2a85",
+ "lessdot;": "\u22d6",
+ "lesseqgtr;": "\u22da",
+ "lesseqqgtr;": "\u2a8b",
+ "lessgtr;": "\u2276",
+ "lesssim;": "\u2272",
+ "lfisht;": "\u297c",
+ "lfloor;": "\u230a",
+ "lfr;": "\U0001d529",
+ "lg;": "\u2276",
+ "lgE;": "\u2a91",
+ "lhard;": "\u21bd",
+ "lharu;": "\u21bc",
+ "lharul;": "\u296a",
+ "lhblk;": "\u2584",
+ "ljcy;": "\u0459",
+ "ll;": "\u226a",
+ "llarr;": "\u21c7",
+ "llcorner;": "\u231e",
+ "llhard;": "\u296b",
+ "lltri;": "\u25fa",
+ "lmidot;": "\u0140",
+ "lmoust;": "\u23b0",
+ "lmoustache;": "\u23b0",
+ "lnE;": "\u2268",
+ "lnap;": "\u2a89",
+ "lnapprox;": "\u2a89",
+ "lne;": "\u2a87",
+ "lneq;": "\u2a87",
+ "lneqq;": "\u2268",
+ "lnsim;": "\u22e6",
+ "loang;": "\u27ec",
+ "loarr;": "\u21fd",
+ "lobrk;": "\u27e6",
+ "longleftarrow;": "\u27f5",
+ "longleftrightarrow;": "\u27f7",
+ "longmapsto;": "\u27fc",
+ "longrightarrow;": "\u27f6",
+ "looparrowleft;": "\u21ab",
+ "looparrowright;": "\u21ac",
+ "lopar;": "\u2985",
+ "lopf;": "\U0001d55d",
+ "loplus;": "\u2a2d",
+ "lotimes;": "\u2a34",
+ "lowast;": "\u2217",
+ "lowbar;": "_",
+ "loz;": "\u25ca",
+ "lozenge;": "\u25ca",
+ "lozf;": "\u29eb",
+ "lpar;": "(",
+ "lparlt;": "\u2993",
+ "lrarr;": "\u21c6",
+ "lrcorner;": "\u231f",
+ "lrhar;": "\u21cb",
+ "lrhard;": "\u296d",
+ "lrm;": "\u200e",
+ "lrtri;": "\u22bf",
+ "lsaquo;": "\u2039",
+ "lscr;": "\U0001d4c1",
+ "lsh;": "\u21b0",
+ "lsim;": "\u2272",
+ "lsime;": "\u2a8d",
+ "lsimg;": "\u2a8f",
+ "lsqb;": "[",
+ "lsquo;": "\u2018",
+ "lsquor;": "\u201a",
+ "lstrok;": "\u0142",
+ "lt": "<",
+ "lt;": "<",
+ "ltcc;": "\u2aa6",
+ "ltcir;": "\u2a79",
+ "ltdot;": "\u22d6",
+ "lthree;": "\u22cb",
+ "ltimes;": "\u22c9",
+ "ltlarr;": "\u2976",
+ "ltquest;": "\u2a7b",
+ "ltrPar;": "\u2996",
+ "ltri;": "\u25c3",
+ "ltrie;": "\u22b4",
+ "ltrif;": "\u25c2",
+ "lurdshar;": "\u294a",
+ "luruhar;": "\u2966",
+ "lvertneqq;": "\u2268\ufe00",
+ "lvnE;": "\u2268\ufe00",
+ "mDDot;": "\u223a",
+ "macr": "\xaf",
+ "macr;": "\xaf",
+ "male;": "\u2642",
+ "malt;": "\u2720",
+ "maltese;": "\u2720",
+ "map;": "\u21a6",
+ "mapsto;": "\u21a6",
+ "mapstodown;": "\u21a7",
+ "mapstoleft;": "\u21a4",
+ "mapstoup;": "\u21a5",
+ "marker;": "\u25ae",
+ "mcomma;": "\u2a29",
+ "mcy;": "\u043c",
+ "mdash;": "\u2014",
+ "measuredangle;": "\u2221",
+ "mfr;": "\U0001d52a",
+ "mho;": "\u2127",
+ "micro": "\xb5",
+ "micro;": "\xb5",
+ "mid;": "\u2223",
+ "midast;": "*",
+ "midcir;": "\u2af0",
+ "middot": "\xb7",
+ "middot;": "\xb7",
+ "minus;": "\u2212",
+ "minusb;": "\u229f",
+ "minusd;": "\u2238",
+ "minusdu;": "\u2a2a",
+ "mlcp;": "\u2adb",
+ "mldr;": "\u2026",
+ "mnplus;": "\u2213",
+ "models;": "\u22a7",
+ "mopf;": "\U0001d55e",
+ "mp;": "\u2213",
+ "mscr;": "\U0001d4c2",
+ "mstpos;": "\u223e",
+ "mu;": "\u03bc",
+ "multimap;": "\u22b8",
+ "mumap;": "\u22b8",
+ "nGg;": "\u22d9\u0338",
+ "nGt;": "\u226b\u20d2",
+ "nGtv;": "\u226b\u0338",
+ "nLeftarrow;": "\u21cd",
+ "nLeftrightarrow;": "\u21ce",
+ "nLl;": "\u22d8\u0338",
+ "nLt;": "\u226a\u20d2",
+ "nLtv;": "\u226a\u0338",
+ "nRightarrow;": "\u21cf",
+ "nVDash;": "\u22af",
+ "nVdash;": "\u22ae",
+ "nabla;": "\u2207",
+ "nacute;": "\u0144",
+ "nang;": "\u2220\u20d2",
+ "nap;": "\u2249",
+ "napE;": "\u2a70\u0338",
+ "napid;": "\u224b\u0338",
+ "napos;": "\u0149",
+ "napprox;": "\u2249",
+ "natur;": "\u266e",
+ "natural;": "\u266e",
+ "naturals;": "\u2115",
+ "nbsp": "\xa0",
+ "nbsp;": "\xa0",
+ "nbump;": "\u224e\u0338",
+ "nbumpe;": "\u224f\u0338",
+ "ncap;": "\u2a43",
+ "ncaron;": "\u0148",
+ "ncedil;": "\u0146",
+ "ncong;": "\u2247",
+ "ncongdot;": "\u2a6d\u0338",
+ "ncup;": "\u2a42",
+ "ncy;": "\u043d",
+ "ndash;": "\u2013",
+ "ne;": "\u2260",
+ "neArr;": "\u21d7",
+ "nearhk;": "\u2924",
+ "nearr;": "\u2197",
+ "nearrow;": "\u2197",
+ "nedot;": "\u2250\u0338",
+ "nequiv;": "\u2262",
+ "nesear;": "\u2928",
+ "nesim;": "\u2242\u0338",
+ "nexist;": "\u2204",
+ "nexists;": "\u2204",
+ "nfr;": "\U0001d52b",
+ "ngE;": "\u2267\u0338",
+ "nge;": "\u2271",
+ "ngeq;": "\u2271",
+ "ngeqq;": "\u2267\u0338",
+ "ngeqslant;": "\u2a7e\u0338",
+ "nges;": "\u2a7e\u0338",
+ "ngsim;": "\u2275",
+ "ngt;": "\u226f",
+ "ngtr;": "\u226f",
+ "nhArr;": "\u21ce",
+ "nharr;": "\u21ae",
+ "nhpar;": "\u2af2",
+ "ni;": "\u220b",
+ "nis;": "\u22fc",
+ "nisd;": "\u22fa",
+ "niv;": "\u220b",
+ "njcy;": "\u045a",
+ "nlArr;": "\u21cd",
+ "nlE;": "\u2266\u0338",
+ "nlarr;": "\u219a",
+ "nldr;": "\u2025",
+ "nle;": "\u2270",
+ "nleftarrow;": "\u219a",
+ "nleftrightarrow;": "\u21ae",
+ "nleq;": "\u2270",
+ "nleqq;": "\u2266\u0338",
+ "nleqslant;": "\u2a7d\u0338",
+ "nles;": "\u2a7d\u0338",
+ "nless;": "\u226e",
+ "nlsim;": "\u2274",
+ "nlt;": "\u226e",
+ "nltri;": "\u22ea",
+ "nltrie;": "\u22ec",
+ "nmid;": "\u2224",
+ "nopf;": "\U0001d55f",
+ "not": "\xac",
+ "not;": "\xac",
+ "notin;": "\u2209",
+ "notinE;": "\u22f9\u0338",
+ "notindot;": "\u22f5\u0338",
+ "notinva;": "\u2209",
+ "notinvb;": "\u22f7",
+ "notinvc;": "\u22f6",
+ "notni;": "\u220c",
+ "notniva;": "\u220c",
+ "notnivb;": "\u22fe",
+ "notnivc;": "\u22fd",
+ "npar;": "\u2226",
+ "nparallel;": "\u2226",
+ "nparsl;": "\u2afd\u20e5",
+ "npart;": "\u2202\u0338",
+ "npolint;": "\u2a14",
+ "npr;": "\u2280",
+ "nprcue;": "\u22e0",
+ "npre;": "\u2aaf\u0338",
+ "nprec;": "\u2280",
+ "npreceq;": "\u2aaf\u0338",
+ "nrArr;": "\u21cf",
+ "nrarr;": "\u219b",
+ "nrarrc;": "\u2933\u0338",
+ "nrarrw;": "\u219d\u0338",
+ "nrightarrow;": "\u219b",
+ "nrtri;": "\u22eb",
+ "nrtrie;": "\u22ed",
+ "nsc;": "\u2281",
+ "nsccue;": "\u22e1",
+ "nsce;": "\u2ab0\u0338",
+ "nscr;": "\U0001d4c3",
+ "nshortmid;": "\u2224",
+ "nshortparallel;": "\u2226",
+ "nsim;": "\u2241",
+ "nsime;": "\u2244",
+ "nsimeq;": "\u2244",
+ "nsmid;": "\u2224",
+ "nspar;": "\u2226",
+ "nsqsube;": "\u22e2",
+ "nsqsupe;": "\u22e3",
+ "nsub;": "\u2284",
+ "nsubE;": "\u2ac5\u0338",
+ "nsube;": "\u2288",
+ "nsubset;": "\u2282\u20d2",
+ "nsubseteq;": "\u2288",
+ "nsubseteqq;": "\u2ac5\u0338",
+ "nsucc;": "\u2281",
+ "nsucceq;": "\u2ab0\u0338",
+ "nsup;": "\u2285",
+ "nsupE;": "\u2ac6\u0338",
+ "nsupe;": "\u2289",
+ "nsupset;": "\u2283\u20d2",
+ "nsupseteq;": "\u2289",
+ "nsupseteqq;": "\u2ac6\u0338",
+ "ntgl;": "\u2279",
+ "ntilde": "\xf1",
+ "ntilde;": "\xf1",
+ "ntlg;": "\u2278",
+ "ntriangleleft;": "\u22ea",
+ "ntrianglelefteq;": "\u22ec",
+ "ntriangleright;": "\u22eb",
+ "ntrianglerighteq;": "\u22ed",
+ "nu;": "\u03bd",
+ "num;": "#",
+ "numero;": "\u2116",
+ "numsp;": "\u2007",
+ "nvDash;": "\u22ad",
+ "nvHarr;": "\u2904",
+ "nvap;": "\u224d\u20d2",
+ "nvdash;": "\u22ac",
+ "nvge;": "\u2265\u20d2",
+ "nvgt;": ">\u20d2",
+ "nvinfin;": "\u29de",
+ "nvlArr;": "\u2902",
+ "nvle;": "\u2264\u20d2",
+ "nvlt;": "<\u20d2",
+ "nvltrie;": "\u22b4\u20d2",
+ "nvrArr;": "\u2903",
+ "nvrtrie;": "\u22b5\u20d2",
+ "nvsim;": "\u223c\u20d2",
+ "nwArr;": "\u21d6",
+ "nwarhk;": "\u2923",
+ "nwarr;": "\u2196",
+ "nwarrow;": "\u2196",
+ "nwnear;": "\u2927",
+ "oS;": "\u24c8",
+ "oacute": "\xf3",
+ "oacute;": "\xf3",
+ "oast;": "\u229b",
+ "ocir;": "\u229a",
+ "ocirc": "\xf4",
+ "ocirc;": "\xf4",
+ "ocy;": "\u043e",
+ "odash;": "\u229d",
+ "odblac;": "\u0151",
+ "odiv;": "\u2a38",
+ "odot;": "\u2299",
+ "odsold;": "\u29bc",
+ "oelig;": "\u0153",
+ "ofcir;": "\u29bf",
+ "ofr;": "\U0001d52c",
+ "ogon;": "\u02db",
+ "ograve": "\xf2",
+ "ograve;": "\xf2",
+ "ogt;": "\u29c1",
+ "ohbar;": "\u29b5",
+ "ohm;": "\u03a9",
+ "oint;": "\u222e",
+ "olarr;": "\u21ba",
+ "olcir;": "\u29be",
+ "olcross;": "\u29bb",
+ "oline;": "\u203e",
+ "olt;": "\u29c0",
+ "omacr;": "\u014d",
+ "omega;": "\u03c9",
+ "omicron;": "\u03bf",
+ "omid;": "\u29b6",
+ "ominus;": "\u2296",
+ "oopf;": "\U0001d560",
+ "opar;": "\u29b7",
+ "operp;": "\u29b9",
+ "oplus;": "\u2295",
+ "or;": "\u2228",
+ "orarr;": "\u21bb",
+ "ord;": "\u2a5d",
+ "order;": "\u2134",
+ "orderof;": "\u2134",
+ "ordf": "\xaa",
+ "ordf;": "\xaa",
+ "ordm": "\xba",
+ "ordm;": "\xba",
+ "origof;": "\u22b6",
+ "oror;": "\u2a56",
+ "orslope;": "\u2a57",
+ "orv;": "\u2a5b",
+ "oscr;": "\u2134",
+ "oslash": "\xf8",
+ "oslash;": "\xf8",
+ "osol;": "\u2298",
+ "otilde": "\xf5",
+ "otilde;": "\xf5",
+ "otimes;": "\u2297",
+ "otimesas;": "\u2a36",
+ "ouml": "\xf6",
+ "ouml;": "\xf6",
+ "ovbar;": "\u233d",
+ "par;": "\u2225",
+ "para": "\xb6",
+ "para;": "\xb6",
+ "parallel;": "\u2225",
+ "parsim;": "\u2af3",
+ "parsl;": "\u2afd",
+ "part;": "\u2202",
+ "pcy;": "\u043f",
+ "percnt;": "%",
+ "period;": ".",
+ "permil;": "\u2030",
+ "perp;": "\u22a5",
+ "pertenk;": "\u2031",
+ "pfr;": "\U0001d52d",
+ "phi;": "\u03c6",
+ "phiv;": "\u03d5",
+ "phmmat;": "\u2133",
+ "phone;": "\u260e",
+ "pi;": "\u03c0",
+ "pitchfork;": "\u22d4",
+ "piv;": "\u03d6",
+ "planck;": "\u210f",
+ "planckh;": "\u210e",
+ "plankv;": "\u210f",
+ "plus;": "+",
+ "plusacir;": "\u2a23",
+ "plusb;": "\u229e",
+ "pluscir;": "\u2a22",
+ "plusdo;": "\u2214",
+ "plusdu;": "\u2a25",
+ "pluse;": "\u2a72",
+ "plusmn": "\xb1",
+ "plusmn;": "\xb1",
+ "plussim;": "\u2a26",
+ "plustwo;": "\u2a27",
+ "pm;": "\xb1",
+ "pointint;": "\u2a15",
+ "popf;": "\U0001d561",
+ "pound": "\xa3",
+ "pound;": "\xa3",
+ "pr;": "\u227a",
+ "prE;": "\u2ab3",
+ "prap;": "\u2ab7",
+ "prcue;": "\u227c",
+ "pre;": "\u2aaf",
+ "prec;": "\u227a",
+ "precapprox;": "\u2ab7",
+ "preccurlyeq;": "\u227c",
+ "preceq;": "\u2aaf",
+ "precnapprox;": "\u2ab9",
+ "precneqq;": "\u2ab5",
+ "precnsim;": "\u22e8",
+ "precsim;": "\u227e",
+ "prime;": "\u2032",
+ "primes;": "\u2119",
+ "prnE;": "\u2ab5",
+ "prnap;": "\u2ab9",
+ "prnsim;": "\u22e8",
+ "prod;": "\u220f",
+ "profalar;": "\u232e",
+ "profline;": "\u2312",
+ "profsurf;": "\u2313",
+ "prop;": "\u221d",
+ "propto;": "\u221d",
+ "prsim;": "\u227e",
+ "prurel;": "\u22b0",
+ "pscr;": "\U0001d4c5",
+ "psi;": "\u03c8",
+ "puncsp;": "\u2008",
+ "qfr;": "\U0001d52e",
+ "qint;": "\u2a0c",
+ "qopf;": "\U0001d562",
+ "qprime;": "\u2057",
+ "qscr;": "\U0001d4c6",
+ "quaternions;": "\u210d",
+ "quatint;": "\u2a16",
+ "quest;": "?",
+ "questeq;": "\u225f",
+ "quot": "\"",
+ "quot;": "\"",
+ "rAarr;": "\u21db",
+ "rArr;": "\u21d2",
+ "rAtail;": "\u291c",
+ "rBarr;": "\u290f",
+ "rHar;": "\u2964",
+ "race;": "\u223d\u0331",
+ "racute;": "\u0155",
+ "radic;": "\u221a",
+ "raemptyv;": "\u29b3",
+ "rang;": "\u27e9",
+ "rangd;": "\u2992",
+ "range;": "\u29a5",
+ "rangle;": "\u27e9",
+ "raquo": "\xbb",
+ "raquo;": "\xbb",
+ "rarr;": "\u2192",
+ "rarrap;": "\u2975",
+ "rarrb;": "\u21e5",
+ "rarrbfs;": "\u2920",
+ "rarrc;": "\u2933",
+ "rarrfs;": "\u291e",
+ "rarrhk;": "\u21aa",
+ "rarrlp;": "\u21ac",
+ "rarrpl;": "\u2945",
+ "rarrsim;": "\u2974",
+ "rarrtl;": "\u21a3",
+ "rarrw;": "\u219d",
+ "ratail;": "\u291a",
+ "ratio;": "\u2236",
+ "rationals;": "\u211a",
+ "rbarr;": "\u290d",
+ "rbbrk;": "\u2773",
+ "rbrace;": "}",
+ "rbrack;": "]",
+ "rbrke;": "\u298c",
+ "rbrksld;": "\u298e",
+ "rbrkslu;": "\u2990",
+ "rcaron;": "\u0159",
+ "rcedil;": "\u0157",
+ "rceil;": "\u2309",
+ "rcub;": "}",
+ "rcy;": "\u0440",
+ "rdca;": "\u2937",
+ "rdldhar;": "\u2969",
+ "rdquo;": "\u201d",
+ "rdquor;": "\u201d",
+ "rdsh;": "\u21b3",
+ "real;": "\u211c",
+ "realine;": "\u211b",
+ "realpart;": "\u211c",
+ "reals;": "\u211d",
+ "rect;": "\u25ad",
+ "reg": "\xae",
+ "reg;": "\xae",
+ "rfisht;": "\u297d",
+ "rfloor;": "\u230b",
+ "rfr;": "\U0001d52f",
+ "rhard;": "\u21c1",
+ "rharu;": "\u21c0",
+ "rharul;": "\u296c",
+ "rho;": "\u03c1",
+ "rhov;": "\u03f1",
+ "rightarrow;": "\u2192",
+ "rightarrowtail;": "\u21a3",
+ "rightharpoondown;": "\u21c1",
+ "rightharpoonup;": "\u21c0",
+ "rightleftarrows;": "\u21c4",
+ "rightleftharpoons;": "\u21cc",
+ "rightrightarrows;": "\u21c9",
+ "rightsquigarrow;": "\u219d",
+ "rightthreetimes;": "\u22cc",
+ "ring;": "\u02da",
+ "risingdotseq;": "\u2253",
+ "rlarr;": "\u21c4",
+ "rlhar;": "\u21cc",
+ "rlm;": "\u200f",
+ "rmoust;": "\u23b1",
+ "rmoustache;": "\u23b1",
+ "rnmid;": "\u2aee",
+ "roang;": "\u27ed",
+ "roarr;": "\u21fe",
+ "robrk;": "\u27e7",
+ "ropar;": "\u2986",
+ "ropf;": "\U0001d563",
+ "roplus;": "\u2a2e",
+ "rotimes;": "\u2a35",
+ "rpar;": ")",
+ "rpargt;": "\u2994",
+ "rppolint;": "\u2a12",
+ "rrarr;": "\u21c9",
+ "rsaquo;": "\u203a",
+ "rscr;": "\U0001d4c7",
+ "rsh;": "\u21b1",
+ "rsqb;": "]",
+ "rsquo;": "\u2019",
+ "rsquor;": "\u2019",
+ "rthree;": "\u22cc",
+ "rtimes;": "\u22ca",
+ "rtri;": "\u25b9",
+ "rtrie;": "\u22b5",
+ "rtrif;": "\u25b8",
+ "rtriltri;": "\u29ce",
+ "ruluhar;": "\u2968",
+ "rx;": "\u211e",
+ "sacute;": "\u015b",
+ "sbquo;": "\u201a",
+ "sc;": "\u227b",
+ "scE;": "\u2ab4",
+ "scap;": "\u2ab8",
+ "scaron;": "\u0161",
+ "sccue;": "\u227d",
+ "sce;": "\u2ab0",
+ "scedil;": "\u015f",
+ "scirc;": "\u015d",
+ "scnE;": "\u2ab6",
+ "scnap;": "\u2aba",
+ "scnsim;": "\u22e9",
+ "scpolint;": "\u2a13",
+ "scsim;": "\u227f",
+ "scy;": "\u0441",
+ "sdot;": "\u22c5",
+ "sdotb;": "\u22a1",
+ "sdote;": "\u2a66",
+ "seArr;": "\u21d8",
+ "searhk;": "\u2925",
+ "searr;": "\u2198",
+ "searrow;": "\u2198",
+ "sect": "\xa7",
+ "sect;": "\xa7",
+ "semi;": ";",
+ "seswar;": "\u2929",
+ "setminus;": "\u2216",
+ "setmn;": "\u2216",
+ "sext;": "\u2736",
+ "sfr;": "\U0001d530",
+ "sfrown;": "\u2322",
+ "sharp;": "\u266f",
+ "shchcy;": "\u0449",
+ "shcy;": "\u0448",
+ "shortmid;": "\u2223",
+ "shortparallel;": "\u2225",
+ "shy": "\xad",
+ "shy;": "\xad",
+ "sigma;": "\u03c3",
+ "sigmaf;": "\u03c2",
+ "sigmav;": "\u03c2",
+ "sim;": "\u223c",
+ "simdot;": "\u2a6a",
+ "sime;": "\u2243",
+ "simeq;": "\u2243",
+ "simg;": "\u2a9e",
+ "simgE;": "\u2aa0",
+ "siml;": "\u2a9d",
+ "simlE;": "\u2a9f",
+ "simne;": "\u2246",
+ "simplus;": "\u2a24",
+ "simrarr;": "\u2972",
+ "slarr;": "\u2190",
+ "smallsetminus;": "\u2216",
+ "smashp;": "\u2a33",
+ "smeparsl;": "\u29e4",
+ "smid;": "\u2223",
+ "smile;": "\u2323",
+ "smt;": "\u2aaa",
+ "smte;": "\u2aac",
+ "smtes;": "\u2aac\ufe00",
+ "softcy;": "\u044c",
+ "sol;": "/",
+ "solb;": "\u29c4",
+ "solbar;": "\u233f",
+ "sopf;": "\U0001d564",
+ "spades;": "\u2660",
+ "spadesuit;": "\u2660",
+ "spar;": "\u2225",
+ "sqcap;": "\u2293",
+ "sqcaps;": "\u2293\ufe00",
+ "sqcup;": "\u2294",
+ "sqcups;": "\u2294\ufe00",
+ "sqsub;": "\u228f",
+ "sqsube;": "\u2291",
+ "sqsubset;": "\u228f",
+ "sqsubseteq;": "\u2291",
+ "sqsup;": "\u2290",
+ "sqsupe;": "\u2292",
+ "sqsupset;": "\u2290",
+ "sqsupseteq;": "\u2292",
+ "squ;": "\u25a1",
+ "square;": "\u25a1",
+ "squarf;": "\u25aa",
+ "squf;": "\u25aa",
+ "srarr;": "\u2192",
+ "sscr;": "\U0001d4c8",
+ "ssetmn;": "\u2216",
+ "ssmile;": "\u2323",
+ "sstarf;": "\u22c6",
+ "star;": "\u2606",
+ "starf;": "\u2605",
+ "straightepsilon;": "\u03f5",
+ "straightphi;": "\u03d5",
+ "strns;": "\xaf",
+ "sub;": "\u2282",
+ "subE;": "\u2ac5",
+ "subdot;": "\u2abd",
+ "sube;": "\u2286",
+ "subedot;": "\u2ac3",
+ "submult;": "\u2ac1",
+ "subnE;": "\u2acb",
+ "subne;": "\u228a",
+ "subplus;": "\u2abf",
+ "subrarr;": "\u2979",
+ "subset;": "\u2282",
+ "subseteq;": "\u2286",
+ "subseteqq;": "\u2ac5",
+ "subsetneq;": "\u228a",
+ "subsetneqq;": "\u2acb",
+ "subsim;": "\u2ac7",
+ "subsub;": "\u2ad5",
+ "subsup;": "\u2ad3",
+ "succ;": "\u227b",
+ "succapprox;": "\u2ab8",
+ "succcurlyeq;": "\u227d",
+ "succeq;": "\u2ab0",
+ "succnapprox;": "\u2aba",
+ "succneqq;": "\u2ab6",
+ "succnsim;": "\u22e9",
+ "succsim;": "\u227f",
+ "sum;": "\u2211",
+ "sung;": "\u266a",
+ "sup1": "\xb9",
+ "sup1;": "\xb9",
+ "sup2": "\xb2",
+ "sup2;": "\xb2",
+ "sup3": "\xb3",
+ "sup3;": "\xb3",
+ "sup;": "\u2283",
+ "supE;": "\u2ac6",
+ "supdot;": "\u2abe",
+ "supdsub;": "\u2ad8",
+ "supe;": "\u2287",
+ "supedot;": "\u2ac4",
+ "suphsol;": "\u27c9",
+ "suphsub;": "\u2ad7",
+ "suplarr;": "\u297b",
+ "supmult;": "\u2ac2",
+ "supnE;": "\u2acc",
+ "supne;": "\u228b",
+ "supplus;": "\u2ac0",
+ "supset;": "\u2283",
+ "supseteq;": "\u2287",
+ "supseteqq;": "\u2ac6",
+ "supsetneq;": "\u228b",
+ "supsetneqq;": "\u2acc",
+ "supsim;": "\u2ac8",
+ "supsub;": "\u2ad4",
+ "supsup;": "\u2ad6",
+ "swArr;": "\u21d9",
+ "swarhk;": "\u2926",
+ "swarr;": "\u2199",
+ "swarrow;": "\u2199",
+ "swnwar;": "\u292a",
+ "szlig": "\xdf",
+ "szlig;": "\xdf",
+ "target;": "\u2316",
+ "tau;": "\u03c4",
+ "tbrk;": "\u23b4",
+ "tcaron;": "\u0165",
+ "tcedil;": "\u0163",
+ "tcy;": "\u0442",
+ "tdot;": "\u20db",
+ "telrec;": "\u2315",
+ "tfr;": "\U0001d531",
+ "there4;": "\u2234",
+ "therefore;": "\u2234",
+ "theta;": "\u03b8",
+ "thetasym;": "\u03d1",
+ "thetav;": "\u03d1",
+ "thickapprox;": "\u2248",
+ "thicksim;": "\u223c",
+ "thinsp;": "\u2009",
+ "thkap;": "\u2248",
+ "thksim;": "\u223c",
+ "thorn": "\xfe",
+ "thorn;": "\xfe",
+ "tilde;": "\u02dc",
+ "times": "\xd7",
+ "times;": "\xd7",
+ "timesb;": "\u22a0",
+ "timesbar;": "\u2a31",
+ "timesd;": "\u2a30",
+ "tint;": "\u222d",
+ "toea;": "\u2928",
+ "top;": "\u22a4",
+ "topbot;": "\u2336",
+ "topcir;": "\u2af1",
+ "topf;": "\U0001d565",
+ "topfork;": "\u2ada",
+ "tosa;": "\u2929",
+ "tprime;": "\u2034",
+ "trade;": "\u2122",
+ "triangle;": "\u25b5",
+ "triangledown;": "\u25bf",
+ "triangleleft;": "\u25c3",
+ "trianglelefteq;": "\u22b4",
+ "triangleq;": "\u225c",
+ "triangleright;": "\u25b9",
+ "trianglerighteq;": "\u22b5",
+ "tridot;": "\u25ec",
+ "trie;": "\u225c",
+ "triminus;": "\u2a3a",
+ "triplus;": "\u2a39",
+ "trisb;": "\u29cd",
+ "tritime;": "\u2a3b",
+ "trpezium;": "\u23e2",
+ "tscr;": "\U0001d4c9",
+ "tscy;": "\u0446",
+ "tshcy;": "\u045b",
+ "tstrok;": "\u0167",
+ "twixt;": "\u226c",
+ "twoheadleftarrow;": "\u219e",
+ "twoheadrightarrow;": "\u21a0",
+ "uArr;": "\u21d1",
+ "uHar;": "\u2963",
+ "uacute": "\xfa",
+ "uacute;": "\xfa",
+ "uarr;": "\u2191",
+ "ubrcy;": "\u045e",
+ "ubreve;": "\u016d",
+ "ucirc": "\xfb",
+ "ucirc;": "\xfb",
+ "ucy;": "\u0443",
+ "udarr;": "\u21c5",
+ "udblac;": "\u0171",
+ "udhar;": "\u296e",
+ "ufisht;": "\u297e",
+ "ufr;": "\U0001d532",
+ "ugrave": "\xf9",
+ "ugrave;": "\xf9",
+ "uharl;": "\u21bf",
+ "uharr;": "\u21be",
+ "uhblk;": "\u2580",
+ "ulcorn;": "\u231c",
+ "ulcorner;": "\u231c",
+ "ulcrop;": "\u230f",
+ "ultri;": "\u25f8",
+ "umacr;": "\u016b",
+ "uml": "\xa8",
+ "uml;": "\xa8",
+ "uogon;": "\u0173",
+ "uopf;": "\U0001d566",
+ "uparrow;": "\u2191",
+ "updownarrow;": "\u2195",
+ "upharpoonleft;": "\u21bf",
+ "upharpoonright;": "\u21be",
+ "uplus;": "\u228e",
+ "upsi;": "\u03c5",
+ "upsih;": "\u03d2",
+ "upsilon;": "\u03c5",
+ "upuparrows;": "\u21c8",
+ "urcorn;": "\u231d",
+ "urcorner;": "\u231d",
+ "urcrop;": "\u230e",
+ "uring;": "\u016f",
+ "urtri;": "\u25f9",
+ "uscr;": "\U0001d4ca",
+ "utdot;": "\u22f0",
+ "utilde;": "\u0169",
+ "utri;": "\u25b5",
+ "utrif;": "\u25b4",
+ "uuarr;": "\u21c8",
+ "uuml": "\xfc",
+ "uuml;": "\xfc",
+ "uwangle;": "\u29a7",
+ "vArr;": "\u21d5",
+ "vBar;": "\u2ae8",
+ "vBarv;": "\u2ae9",
+ "vDash;": "\u22a8",
+ "vangrt;": "\u299c",
+ "varepsilon;": "\u03f5",
+ "varkappa;": "\u03f0",
+ "varnothing;": "\u2205",
+ "varphi;": "\u03d5",
+ "varpi;": "\u03d6",
+ "varpropto;": "\u221d",
+ "varr;": "\u2195",
+ "varrho;": "\u03f1",
+ "varsigma;": "\u03c2",
+ "varsubsetneq;": "\u228a\ufe00",
+ "varsubsetneqq;": "\u2acb\ufe00",
+ "varsupsetneq;": "\u228b\ufe00",
+ "varsupsetneqq;": "\u2acc\ufe00",
+ "vartheta;": "\u03d1",
+ "vartriangleleft;": "\u22b2",
+ "vartriangleright;": "\u22b3",
+ "vcy;": "\u0432",
+ "vdash;": "\u22a2",
+ "vee;": "\u2228",
+ "veebar;": "\u22bb",
+ "veeeq;": "\u225a",
+ "vellip;": "\u22ee",
+ "verbar;": "|",
+ "vert;": "|",
+ "vfr;": "\U0001d533",
+ "vltri;": "\u22b2",
+ "vnsub;": "\u2282\u20d2",
+ "vnsup;": "\u2283\u20d2",
+ "vopf;": "\U0001d567",
+ "vprop;": "\u221d",
+ "vrtri;": "\u22b3",
+ "vscr;": "\U0001d4cb",
+ "vsubnE;": "\u2acb\ufe00",
+ "vsubne;": "\u228a\ufe00",
+ "vsupnE;": "\u2acc\ufe00",
+ "vsupne;": "\u228b\ufe00",
+ "vzigzag;": "\u299a",
+ "wcirc;": "\u0175",
+ "wedbar;": "\u2a5f",
+ "wedge;": "\u2227",
+ "wedgeq;": "\u2259",
+ "weierp;": "\u2118",
+ "wfr;": "\U0001d534",
+ "wopf;": "\U0001d568",
+ "wp;": "\u2118",
+ "wr;": "\u2240",
+ "wreath;": "\u2240",
+ "wscr;": "\U0001d4cc",
+ "xcap;": "\u22c2",
+ "xcirc;": "\u25ef",
+ "xcup;": "\u22c3",
+ "xdtri;": "\u25bd",
+ "xfr;": "\U0001d535",
+ "xhArr;": "\u27fa",
+ "xharr;": "\u27f7",
+ "xi;": "\u03be",
+ "xlArr;": "\u27f8",
+ "xlarr;": "\u27f5",
+ "xmap;": "\u27fc",
+ "xnis;": "\u22fb",
+ "xodot;": "\u2a00",
+ "xopf;": "\U0001d569",
+ "xoplus;": "\u2a01",
+ "xotime;": "\u2a02",
+ "xrArr;": "\u27f9",
+ "xrarr;": "\u27f6",
+ "xscr;": "\U0001d4cd",
+ "xsqcup;": "\u2a06",
+ "xuplus;": "\u2a04",
+ "xutri;": "\u25b3",
+ "xvee;": "\u22c1",
+ "xwedge;": "\u22c0",
+ "yacute": "\xfd",
+ "yacute;": "\xfd",
+ "yacy;": "\u044f",
+ "ycirc;": "\u0177",
+ "ycy;": "\u044b",
+ "yen": "\xa5",
+ "yen;": "\xa5",
+ "yfr;": "\U0001d536",
+ "yicy;": "\u0457",
+ "yopf;": "\U0001d56a",
+ "yscr;": "\U0001d4ce",
+ "yucy;": "\u044e",
+ "yuml": "\xff",
+ "yuml;": "\xff",
+ "zacute;": "\u017a",
+ "zcaron;": "\u017e",
+ "zcy;": "\u0437",
+ "zdot;": "\u017c",
+ "zeetrf;": "\u2128",
+ "zeta;": "\u03b6",
+ "zfr;": "\U0001d537",
+ "zhcy;": "\u0436",
+ "zigrarr;": "\u21dd",
+ "zopf;": "\U0001d56b",
+ "zscr;": "\U0001d4cf",
+ "zwj;": "\u200d",
+ "zwnj;": "\u200c",
+}
+
+replacementCharacters = {
+ 0x0: "\uFFFD",
+ 0x0d: "\u000D",
+ 0x80: "\u20AC",
+ 0x81: "\u0081",
+ 0x81: "\u0081",
+ 0x82: "\u201A",
+ 0x83: "\u0192",
+ 0x84: "\u201E",
+ 0x85: "\u2026",
+ 0x86: "\u2020",
+ 0x87: "\u2021",
+ 0x88: "\u02C6",
+ 0x89: "\u2030",
+ 0x8A: "\u0160",
+ 0x8B: "\u2039",
+ 0x8C: "\u0152",
+ 0x8D: "\u008D",
+ 0x8E: "\u017D",
+ 0x8F: "\u008F",
+ 0x90: "\u0090",
+ 0x91: "\u2018",
+ 0x92: "\u2019",
+ 0x93: "\u201C",
+ 0x94: "\u201D",
+ 0x95: "\u2022",
+ 0x96: "\u2013",
+ 0x97: "\u2014",
+ 0x98: "\u02DC",
+ 0x99: "\u2122",
+ 0x9A: "\u0161",
+ 0x9B: "\u203A",
+ 0x9C: "\u0153",
+ 0x9D: "\u009D",
+ 0x9E: "\u017E",
+ 0x9F: "\u0178",
+}
+
+encodings = {
+ '437': 'cp437',
+ '850': 'cp850',
+ '852': 'cp852',
+ '855': 'cp855',
+ '857': 'cp857',
+ '860': 'cp860',
+ '861': 'cp861',
+ '862': 'cp862',
+ '863': 'cp863',
+ '865': 'cp865',
+ '866': 'cp866',
+ '869': 'cp869',
+ 'ansix341968': 'ascii',
+ 'ansix341986': 'ascii',
+ 'arabic': 'iso8859-6',
+ 'ascii': 'ascii',
+ 'asmo708': 'iso8859-6',
+ 'big5': 'big5',
+ 'big5hkscs': 'big5hkscs',
+ 'chinese': 'gbk',
+ 'cp037': 'cp037',
+ 'cp1026': 'cp1026',
+ 'cp154': 'ptcp154',
+ 'cp367': 'ascii',
+ 'cp424': 'cp424',
+ 'cp437': 'cp437',
+ 'cp500': 'cp500',
+ 'cp775': 'cp775',
+ 'cp819': 'windows-1252',
+ 'cp850': 'cp850',
+ 'cp852': 'cp852',
+ 'cp855': 'cp855',
+ 'cp857': 'cp857',
+ 'cp860': 'cp860',
+ 'cp861': 'cp861',
+ 'cp862': 'cp862',
+ 'cp863': 'cp863',
+ 'cp864': 'cp864',
+ 'cp865': 'cp865',
+ 'cp866': 'cp866',
+ 'cp869': 'cp869',
+ 'cp936': 'gbk',
+ 'cpgr': 'cp869',
+ 'cpis': 'cp861',
+ 'csascii': 'ascii',
+ 'csbig5': 'big5',
+ 'cseuckr': 'cp949',
+ 'cseucpkdfmtjapanese': 'euc_jp',
+ 'csgb2312': 'gbk',
+ 'cshproman8': 'hp-roman8',
+ 'csibm037': 'cp037',
+ 'csibm1026': 'cp1026',
+ 'csibm424': 'cp424',
+ 'csibm500': 'cp500',
+ 'csibm855': 'cp855',
+ 'csibm857': 'cp857',
+ 'csibm860': 'cp860',
+ 'csibm861': 'cp861',
+ 'csibm863': 'cp863',
+ 'csibm864': 'cp864',
+ 'csibm865': 'cp865',
+ 'csibm866': 'cp866',
+ 'csibm869': 'cp869',
+ 'csiso2022jp': 'iso2022_jp',
+ 'csiso2022jp2': 'iso2022_jp_2',
+ 'csiso2022kr': 'iso2022_kr',
+ 'csiso58gb231280': 'gbk',
+ 'csisolatin1': 'windows-1252',
+ 'csisolatin2': 'iso8859-2',
+ 'csisolatin3': 'iso8859-3',
+ 'csisolatin4': 'iso8859-4',
+ 'csisolatin5': 'windows-1254',
+ 'csisolatin6': 'iso8859-10',
+ 'csisolatinarabic': 'iso8859-6',
+ 'csisolatincyrillic': 'iso8859-5',
+ 'csisolatingreek': 'iso8859-7',
+ 'csisolatinhebrew': 'iso8859-8',
+ 'cskoi8r': 'koi8-r',
+ 'csksc56011987': 'cp949',
+ 'cspc775baltic': 'cp775',
+ 'cspc850multilingual': 'cp850',
+ 'cspc862latinhebrew': 'cp862',
+ 'cspc8codepage437': 'cp437',
+ 'cspcp852': 'cp852',
+ 'csptcp154': 'ptcp154',
+ 'csshiftjis': 'shift_jis',
+ 'csunicode11utf7': 'utf-7',
+ 'cyrillic': 'iso8859-5',
+ 'cyrillicasian': 'ptcp154',
+ 'ebcdiccpbe': 'cp500',
+ 'ebcdiccpca': 'cp037',
+ 'ebcdiccpch': 'cp500',
+ 'ebcdiccphe': 'cp424',
+ 'ebcdiccpnl': 'cp037',
+ 'ebcdiccpus': 'cp037',
+ 'ebcdiccpwt': 'cp037',
+ 'ecma114': 'iso8859-6',
+ 'ecma118': 'iso8859-7',
+ 'elot928': 'iso8859-7',
+ 'eucjp': 'euc_jp',
+ 'euckr': 'cp949',
+ 'extendedunixcodepackedformatforjapanese': 'euc_jp',
+ 'gb18030': 'gb18030',
+ 'gb2312': 'gbk',
+ 'gb231280': 'gbk',
+ 'gbk': 'gbk',
+ 'greek': 'iso8859-7',
+ 'greek8': 'iso8859-7',
+ 'hebrew': 'iso8859-8',
+ 'hproman8': 'hp-roman8',
+ 'hzgb2312': 'hz',
+ 'ibm037': 'cp037',
+ 'ibm1026': 'cp1026',
+ 'ibm367': 'ascii',
+ 'ibm424': 'cp424',
+ 'ibm437': 'cp437',
+ 'ibm500': 'cp500',
+ 'ibm775': 'cp775',
+ 'ibm819': 'windows-1252',
+ 'ibm850': 'cp850',
+ 'ibm852': 'cp852',
+ 'ibm855': 'cp855',
+ 'ibm857': 'cp857',
+ 'ibm860': 'cp860',
+ 'ibm861': 'cp861',
+ 'ibm862': 'cp862',
+ 'ibm863': 'cp863',
+ 'ibm864': 'cp864',
+ 'ibm865': 'cp865',
+ 'ibm866': 'cp866',
+ 'ibm869': 'cp869',
+ 'iso2022jp': 'iso2022_jp',
+ 'iso2022jp2': 'iso2022_jp_2',
+ 'iso2022kr': 'iso2022_kr',
+ 'iso646irv1991': 'ascii',
+ 'iso646us': 'ascii',
+ 'iso88591': 'windows-1252',
+ 'iso885910': 'iso8859-10',
+ 'iso8859101992': 'iso8859-10',
+ 'iso885911987': 'windows-1252',
+ 'iso885913': 'iso8859-13',
+ 'iso885914': 'iso8859-14',
+ 'iso8859141998': 'iso8859-14',
+ 'iso885915': 'iso8859-15',
+ 'iso885916': 'iso8859-16',
+ 'iso8859162001': 'iso8859-16',
+ 'iso88592': 'iso8859-2',
+ 'iso885921987': 'iso8859-2',
+ 'iso88593': 'iso8859-3',
+ 'iso885931988': 'iso8859-3',
+ 'iso88594': 'iso8859-4',
+ 'iso885941988': 'iso8859-4',
+ 'iso88595': 'iso8859-5',
+ 'iso885951988': 'iso8859-5',
+ 'iso88596': 'iso8859-6',
+ 'iso885961987': 'iso8859-6',
+ 'iso88597': 'iso8859-7',
+ 'iso885971987': 'iso8859-7',
+ 'iso88598': 'iso8859-8',
+ 'iso885981988': 'iso8859-8',
+ 'iso88599': 'windows-1254',
+ 'iso885991989': 'windows-1254',
+ 'isoceltic': 'iso8859-14',
+ 'isoir100': 'windows-1252',
+ 'isoir101': 'iso8859-2',
+ 'isoir109': 'iso8859-3',
+ 'isoir110': 'iso8859-4',
+ 'isoir126': 'iso8859-7',
+ 'isoir127': 'iso8859-6',
+ 'isoir138': 'iso8859-8',
+ 'isoir144': 'iso8859-5',
+ 'isoir148': 'windows-1254',
+ 'isoir149': 'cp949',
+ 'isoir157': 'iso8859-10',
+ 'isoir199': 'iso8859-14',
+ 'isoir226': 'iso8859-16',
+ 'isoir58': 'gbk',
+ 'isoir6': 'ascii',
+ 'koi8r': 'koi8-r',
+ 'koi8u': 'koi8-u',
+ 'korean': 'cp949',
+ 'ksc5601': 'cp949',
+ 'ksc56011987': 'cp949',
+ 'ksc56011989': 'cp949',
+ 'l1': 'windows-1252',
+ 'l10': 'iso8859-16',
+ 'l2': 'iso8859-2',
+ 'l3': 'iso8859-3',
+ 'l4': 'iso8859-4',
+ 'l5': 'windows-1254',
+ 'l6': 'iso8859-10',
+ 'l8': 'iso8859-14',
+ 'latin1': 'windows-1252',
+ 'latin10': 'iso8859-16',
+ 'latin2': 'iso8859-2',
+ 'latin3': 'iso8859-3',
+ 'latin4': 'iso8859-4',
+ 'latin5': 'windows-1254',
+ 'latin6': 'iso8859-10',
+ 'latin8': 'iso8859-14',
+ 'latin9': 'iso8859-15',
+ 'ms936': 'gbk',
+ 'mskanji': 'shift_jis',
+ 'pt154': 'ptcp154',
+ 'ptcp154': 'ptcp154',
+ 'r8': 'hp-roman8',
+ 'roman8': 'hp-roman8',
+ 'shiftjis': 'shift_jis',
+ 'tis620': 'cp874',
+ 'unicode11utf7': 'utf-7',
+ 'us': 'ascii',
+ 'usascii': 'ascii',
+ 'utf16': 'utf-16',
+ 'utf16be': 'utf-16-be',
+ 'utf16le': 'utf-16-le',
+ 'utf8': 'utf-8',
+ 'windows1250': 'cp1250',
+ 'windows1251': 'cp1251',
+ 'windows1252': 'cp1252',
+ 'windows1253': 'cp1253',
+ 'windows1254': 'cp1254',
+ 'windows1255': 'cp1255',
+ 'windows1256': 'cp1256',
+ 'windows1257': 'cp1257',
+ 'windows1258': 'cp1258',
+ 'windows936': 'gbk',
+ 'x-x-big5': 'big5'}
+
+tokenTypes = {
+ "Doctype": 0,
+ "Characters": 1,
+ "SpaceCharacters": 2,
+ "StartTag": 3,
+ "EndTag": 4,
+ "EmptyTag": 5,
+ "Comment": 6,
+ "ParseError": 7
+}
+
+tagTokenTypes = frozenset((tokenTypes["StartTag"], tokenTypes["EndTag"],
+ tokenTypes["EmptyTag"]))
+
+
+prefixes = dict([(v, k) for k, v in namespaces.items()])
+prefixes["http://www.w3.org/1998/Math/MathML"] = "math"
+
+
+class DataLossWarning(UserWarning):
+ pass
+
+
+class ReparseException(Exception):
+ pass
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/filters/__init__.py b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/filters/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/filters/__init__.py
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/filters/_base.py b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/filters/_base.py
new file mode 100644
index 00000000000..c7dbaed0fab
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/filters/_base.py
@@ -0,0 +1,12 @@
+from __future__ import absolute_import, division, unicode_literals
+
+
+class Filter(object):
+ def __init__(self, source):
+ self.source = source
+
+ def __iter__(self):
+ return iter(self.source)
+
+ def __getattr__(self, name):
+ return getattr(self.source, name)
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/filters/alphabeticalattributes.py b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/filters/alphabeticalattributes.py
new file mode 100644
index 00000000000..fed6996c1d9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/filters/alphabeticalattributes.py
@@ -0,0 +1,20 @@
+from __future__ import absolute_import, division, unicode_literals
+
+from . import _base
+
+try:
+ from collections import OrderedDict
+except ImportError:
+ from ordereddict import OrderedDict
+
+
+class Filter(_base.Filter):
+ def __iter__(self):
+ for token in _base.Filter.__iter__(self):
+ if token["type"] in ("StartTag", "EmptyTag"):
+ attrs = OrderedDict()
+ for name, value in sorted(token["data"].items(),
+ key=lambda x: x[0]):
+ attrs[name] = value
+ token["data"] = attrs
+ yield token
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/filters/inject_meta_charset.py b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/filters/inject_meta_charset.py
new file mode 100644
index 00000000000..ca33b70b530
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/filters/inject_meta_charset.py
@@ -0,0 +1,65 @@
+from __future__ import absolute_import, division, unicode_literals
+
+from . import _base
+
+
+class Filter(_base.Filter):
+ def __init__(self, source, encoding):
+ _base.Filter.__init__(self, source)
+ self.encoding = encoding
+
+ def __iter__(self):
+ state = "pre_head"
+ meta_found = (self.encoding is None)
+ pending = []
+
+ for token in _base.Filter.__iter__(self):
+ type = token["type"]
+ if type == "StartTag":
+ if token["name"].lower() == "head":
+ state = "in_head"
+
+ elif type == "EmptyTag":
+ if token["name"].lower() == "meta":
+ # replace charset with actual encoding
+ has_http_equiv_content_type = False
+ for (namespace, name), value in token["data"].items():
+ if namespace is not None:
+ continue
+ elif name.lower() == 'charset':
+ token["data"][(namespace, name)] = self.encoding
+ meta_found = True
+ break
+ elif name == 'http-equiv' and value.lower() == 'content-type':
+ has_http_equiv_content_type = True
+ else:
+ if has_http_equiv_content_type and (None, "content") in token["data"]:
+ token["data"][(None, "content")] = 'text/html; charset=%s' % self.encoding
+ meta_found = True
+
+ elif token["name"].lower() == "head" and not meta_found:
+ # insert meta into empty head
+ yield {"type": "StartTag", "name": "head",
+ "data": token["data"]}
+ yield {"type": "EmptyTag", "name": "meta",
+ "data": {(None, "charset"): self.encoding}}
+ yield {"type": "EndTag", "name": "head"}
+ meta_found = True
+ continue
+
+ elif type == "EndTag":
+ if token["name"].lower() == "head" and pending:
+ # insert meta into head (if necessary) and flush pending queue
+ yield pending.pop(0)
+ if not meta_found:
+ yield {"type": "EmptyTag", "name": "meta",
+ "data": {(None, "charset"): self.encoding}}
+ while pending:
+ yield pending.pop(0)
+ meta_found = True
+ state = "post_head"
+
+ if state == "in_head":
+ pending.append(token)
+ else:
+ yield token
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/filters/lint.py b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/filters/lint.py
new file mode 100644
index 00000000000..7cc99a4ba7c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/filters/lint.py
@@ -0,0 +1,93 @@
+from __future__ import absolute_import, division, unicode_literals
+
+from gettext import gettext
+_ = gettext
+
+from . import _base
+from ..constants import cdataElements, rcdataElements, voidElements
+
+from ..constants import spaceCharacters
+spaceCharacters = "".join(spaceCharacters)
+
+
+class LintError(Exception):
+ pass
+
+
+class Filter(_base.Filter):
+ def __iter__(self):
+ open_elements = []
+ contentModelFlag = "PCDATA"
+ for token in _base.Filter.__iter__(self):
+ type = token["type"]
+ if type in ("StartTag", "EmptyTag"):
+ name = token["name"]
+ if contentModelFlag != "PCDATA":
+ raise LintError(_("StartTag not in PCDATA content model flag: %(tag)s") % {"tag": name})
+ if not isinstance(name, str):
+ raise LintError(_("Tag name is not a string: %(tag)r") % {"tag": name})
+ if not name:
+ raise LintError(_("Empty tag name"))
+ if type == "StartTag" and name in voidElements:
+ raise LintError(_("Void element reported as StartTag token: %(tag)s") % {"tag": name})
+ elif type == "EmptyTag" and name not in voidElements:
+ raise LintError(_("Non-void element reported as EmptyTag token: %(tag)s") % {"tag": token["name"]})
+ if type == "StartTag":
+ open_elements.append(name)
+ for name, value in token["data"]:
+ if not isinstance(name, str):
+ raise LintError(_("Attribute name is not a string: %(name)r") % {"name": name})
+ if not name:
+ raise LintError(_("Empty attribute name"))
+ if not isinstance(value, str):
+ raise LintError(_("Attribute value is not a string: %(value)r") % {"value": value})
+ if name in cdataElements:
+ contentModelFlag = "CDATA"
+ elif name in rcdataElements:
+ contentModelFlag = "RCDATA"
+ elif name == "plaintext":
+ contentModelFlag = "PLAINTEXT"
+
+ elif type == "EndTag":
+ name = token["name"]
+ if not isinstance(name, str):
+ raise LintError(_("Tag name is not a string: %(tag)r") % {"tag": name})
+ if not name:
+ raise LintError(_("Empty tag name"))
+ if name in voidElements:
+ raise LintError(_("Void element reported as EndTag token: %(tag)s") % {"tag": name})
+ start_name = open_elements.pop()
+ if start_name != name:
+ raise LintError(_("EndTag (%(end)s) does not match StartTag (%(start)s)") % {"end": name, "start": start_name})
+ contentModelFlag = "PCDATA"
+
+ elif type == "Comment":
+ if contentModelFlag != "PCDATA":
+ raise LintError(_("Comment not in PCDATA content model flag"))
+
+ elif type in ("Characters", "SpaceCharacters"):
+ data = token["data"]
+ if not isinstance(data, str):
+ raise LintError(_("Attribute name is not a string: %(name)r") % {"name": data})
+ if not data:
+ raise LintError(_("%(type)s token with empty data") % {"type": type})
+ if type == "SpaceCharacters":
+ data = data.strip(spaceCharacters)
+ if data:
+ raise LintError(_("Non-space character(s) found in SpaceCharacters token: %(token)r") % {"token": data})
+
+ elif type == "Doctype":
+ name = token["name"]
+ if contentModelFlag != "PCDATA":
+ raise LintError(_("Doctype not in PCDATA content model flag: %(name)s") % {"name": name})
+ if not isinstance(name, str):
+ raise LintError(_("Tag name is not a string: %(tag)r") % {"tag": name})
+ # XXX: what to do with token["data"] ?
+
+ elif type in ("ParseError", "SerializeError"):
+ pass
+
+ else:
+ raise LintError(_("Unknown token type: %(type)s") % {"type": type})
+
+ yield token
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/filters/optionaltags.py b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/filters/optionaltags.py
new file mode 100644
index 00000000000..fefe0b3097b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/filters/optionaltags.py
@@ -0,0 +1,205 @@
+from __future__ import absolute_import, division, unicode_literals
+
+from . import _base
+
+
+class Filter(_base.Filter):
+ def slider(self):
+ previous1 = previous2 = None
+ for token in self.source:
+ if previous1 is not None:
+ yield previous2, previous1, token
+ previous2 = previous1
+ previous1 = token
+ yield previous2, previous1, None
+
+ def __iter__(self):
+ for previous, token, next in self.slider():
+ type = token["type"]
+ if type == "StartTag":
+ if (token["data"] or
+ not self.is_optional_start(token["name"], previous, next)):
+ yield token
+ elif type == "EndTag":
+ if not self.is_optional_end(token["name"], next):
+ yield token
+ else:
+ yield token
+
+ def is_optional_start(self, tagname, previous, next):
+ type = next and next["type"] or None
+ if tagname in 'html':
+ # An html element's start tag may be omitted if the first thing
+ # inside the html element is not a space character or a comment.
+ return type not in ("Comment", "SpaceCharacters")
+ elif tagname == 'head':
+ # A head element's start tag may be omitted if the first thing
+ # inside the head element is an element.
+ # XXX: we also omit the start tag if the head element is empty
+ if type in ("StartTag", "EmptyTag"):
+ return True
+ elif type == "EndTag":
+ return next["name"] == "head"
+ elif tagname == 'body':
+ # A body element's start tag may be omitted if the first thing
+ # inside the body element is not a space character or a comment,
+ # except if the first thing inside the body element is a script
+ # or style element and the node immediately preceding the body
+ # element is a head element whose end tag has been omitted.
+ if type in ("Comment", "SpaceCharacters"):
+ return False
+ elif type == "StartTag":
+ # XXX: we do not look at the preceding event, so we never omit
+ # the body element's start tag if it's followed by a script or
+ # a style element.
+ return next["name"] not in ('script', 'style')
+ else:
+ return True
+ elif tagname == 'colgroup':
+ # A colgroup element's start tag may be omitted if the first thing
+ # inside the colgroup element is a col element, and if the element
+ # is not immediately preceeded by another colgroup element whose
+ # end tag has been omitted.
+ if type in ("StartTag", "EmptyTag"):
+ # XXX: we do not look at the preceding event, so instead we never
+ # omit the colgroup element's end tag when it is immediately
+ # followed by another colgroup element. See is_optional_end.
+ return next["name"] == "col"
+ else:
+ return False
+ elif tagname == 'tbody':
+ # A tbody element's start tag may be omitted if the first thing
+ # inside the tbody element is a tr element, and if the element is
+ # not immediately preceeded by a tbody, thead, or tfoot element
+ # whose end tag has been omitted.
+ if type == "StartTag":
+ # omit the thead and tfoot elements' end tag when they are
+ # immediately followed by a tbody element. See is_optional_end.
+ if previous and previous['type'] == 'EndTag' and \
+ previous['name'] in ('tbody', 'thead', 'tfoot'):
+ return False
+ return next["name"] == 'tr'
+ else:
+ return False
+ return False
+
+ def is_optional_end(self, tagname, next):
+ type = next and next["type"] or None
+ if tagname in ('html', 'head', 'body'):
+ # An html element's end tag may be omitted if the html element
+ # is not immediately followed by a space character or a comment.
+ return type not in ("Comment", "SpaceCharacters")
+ elif tagname in ('li', 'optgroup', 'tr'):
+ # A li element's end tag may be omitted if the li element is
+ # immediately followed by another li element or if there is
+ # no more content in the parent element.
+ # An optgroup element's end tag may be omitted if the optgroup
+ # element is immediately followed by another optgroup element,
+ # or if there is no more content in the parent element.
+ # A tr element's end tag may be omitted if the tr element is
+ # immediately followed by another tr element, or if there is
+ # no more content in the parent element.
+ if type == "StartTag":
+ return next["name"] == tagname
+ else:
+ return type == "EndTag" or type is None
+ elif tagname in ('dt', 'dd'):
+ # A dt element's end tag may be omitted if the dt element is
+ # immediately followed by another dt element or a dd element.
+ # A dd element's end tag may be omitted if the dd element is
+ # immediately followed by another dd element or a dt element,
+ # or if there is no more content in the parent element.
+ if type == "StartTag":
+ return next["name"] in ('dt', 'dd')
+ elif tagname == 'dd':
+ return type == "EndTag" or type is None
+ else:
+ return False
+ elif tagname == 'p':
+ # A p element's end tag may be omitted if the p element is
+ # immediately followed by an address, article, aside,
+ # blockquote, datagrid, dialog, dir, div, dl, fieldset,
+ # footer, form, h1, h2, h3, h4, h5, h6, header, hr, menu,
+ # nav, ol, p, pre, section, table, or ul, element, or if
+ # there is no more content in the parent element.
+ if type in ("StartTag", "EmptyTag"):
+ return next["name"] in ('address', 'article', 'aside',
+ 'blockquote', 'datagrid', 'dialog',
+ 'dir', 'div', 'dl', 'fieldset', 'footer',
+ 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
+ 'header', 'hr', 'menu', 'nav', 'ol',
+ 'p', 'pre', 'section', 'table', 'ul')
+ else:
+ return type == "EndTag" or type is None
+ elif tagname == 'option':
+ # An option element's end tag may be omitted if the option
+ # element is immediately followed by another option element,
+ # or if it is immediately followed by an <code>optgroup</code>
+ # element, or if there is no more content in the parent
+ # element.
+ if type == "StartTag":
+ return next["name"] in ('option', 'optgroup')
+ else:
+ return type == "EndTag" or type is None
+ elif tagname in ('rt', 'rp'):
+ # An rt element's end tag may be omitted if the rt element is
+ # immediately followed by an rt or rp element, or if there is
+ # no more content in the parent element.
+ # An rp element's end tag may be omitted if the rp element is
+ # immediately followed by an rt or rp element, or if there is
+ # no more content in the parent element.
+ if type == "StartTag":
+ return next["name"] in ('rt', 'rp')
+ else:
+ return type == "EndTag" or type is None
+ elif tagname == 'colgroup':
+ # A colgroup element's end tag may be omitted if the colgroup
+ # element is not immediately followed by a space character or
+ # a comment.
+ if type in ("Comment", "SpaceCharacters"):
+ return False
+ elif type == "StartTag":
+ # XXX: we also look for an immediately following colgroup
+ # element. See is_optional_start.
+ return next["name"] != 'colgroup'
+ else:
+ return True
+ elif tagname in ('thead', 'tbody'):
+ # A thead element's end tag may be omitted if the thead element
+ # is immediately followed by a tbody or tfoot element.
+ # A tbody element's end tag may be omitted if the tbody element
+ # is immediately followed by a tbody or tfoot element, or if
+ # there is no more content in the parent element.
+ # A tfoot element's end tag may be omitted if the tfoot element
+ # is immediately followed by a tbody element, or if there is no
+ # more content in the parent element.
+ # XXX: we never omit the end tag when the following element is
+ # a tbody. See is_optional_start.
+ if type == "StartTag":
+ return next["name"] in ['tbody', 'tfoot']
+ elif tagname == 'tbody':
+ return type == "EndTag" or type is None
+ else:
+ return False
+ elif tagname == 'tfoot':
+ # A tfoot element's end tag may be omitted if the tfoot element
+ # is immediately followed by a tbody element, or if there is no
+ # more content in the parent element.
+ # XXX: we never omit the end tag when the following element is
+ # a tbody. See is_optional_start.
+ if type == "StartTag":
+ return next["name"] == 'tbody'
+ else:
+ return type == "EndTag" or type is None
+ elif tagname in ('td', 'th'):
+ # A td element's end tag may be omitted if the td element is
+ # immediately followed by a td or th element, or if there is
+ # no more content in the parent element.
+ # A th element's end tag may be omitted if the th element is
+ # immediately followed by a td or th element, or if there is
+ # no more content in the parent element.
+ if type == "StartTag":
+ return next["name"] in ('td', 'th')
+ else:
+ return type == "EndTag" or type is None
+ return False
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/filters/sanitizer.py b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/filters/sanitizer.py
new file mode 100644
index 00000000000..b206b54e7a7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/filters/sanitizer.py
@@ -0,0 +1,12 @@
+from __future__ import absolute_import, division, unicode_literals
+
+from . import _base
+from ..sanitizer import HTMLSanitizerMixin
+
+
+class Filter(_base.Filter, HTMLSanitizerMixin):
+ def __iter__(self):
+ for token in _base.Filter.__iter__(self):
+ token = self.sanitize_token(token)
+ if token:
+ yield token
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/filters/whitespace.py b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/filters/whitespace.py
new file mode 100644
index 00000000000..dfc60eebd35
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/filters/whitespace.py
@@ -0,0 +1,38 @@
+from __future__ import absolute_import, division, unicode_literals
+
+import re
+
+from . import _base
+from ..constants import rcdataElements, spaceCharacters
+spaceCharacters = "".join(spaceCharacters)
+
+SPACES_REGEX = re.compile("[%s]+" % spaceCharacters)
+
+
+class Filter(_base.Filter):
+
+ spacePreserveElements = frozenset(["pre", "textarea"] + list(rcdataElements))
+
+ def __iter__(self):
+ preserve = 0
+ for token in _base.Filter.__iter__(self):
+ type = token["type"]
+ if type == "StartTag" \
+ and (preserve or token["name"] in self.spacePreserveElements):
+ preserve += 1
+
+ elif type == "EndTag" and preserve:
+ preserve -= 1
+
+ elif not preserve and type == "SpaceCharacters" and token["data"]:
+ # Test on token["data"] above to not introduce spaces where there were not
+ token["data"] = " "
+
+ elif not preserve and type == "Characters":
+ token["data"] = collapse_spaces(token["data"])
+
+ yield token
+
+
+def collapse_spaces(text):
+ return SPACES_REGEX.sub(' ', text)
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/html5parser.py b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/html5parser.py
new file mode 100644
index 00000000000..5b9ce7d7206
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/html5parser.py
@@ -0,0 +1,2723 @@
+from __future__ import absolute_import, division, unicode_literals
+from six import with_metaclass
+
+import types
+
+from . import inputstream
+from . import tokenizer
+
+from . import treebuilders
+from .treebuilders._base import Marker
+
+from . import utils
+from . import constants
+from .constants import spaceCharacters, asciiUpper2Lower
+from .constants import specialElements
+from .constants import headingElements
+from .constants import cdataElements, rcdataElements
+from .constants import tokenTypes, ReparseException, namespaces
+from .constants import htmlIntegrationPointElements, mathmlTextIntegrationPointElements
+from .constants import adjustForeignAttributes as adjustForeignAttributesMap
+
+
+def parse(doc, treebuilder="etree", encoding=None,
+ namespaceHTMLElements=True):
+ """Parse a string or file-like object into a tree"""
+ tb = treebuilders.getTreeBuilder(treebuilder)
+ p = HTMLParser(tb, namespaceHTMLElements=namespaceHTMLElements)
+ return p.parse(doc, encoding=encoding)
+
+
+def parseFragment(doc, container="div", treebuilder="etree", encoding=None,
+ namespaceHTMLElements=True):
+ tb = treebuilders.getTreeBuilder(treebuilder)
+ p = HTMLParser(tb, namespaceHTMLElements=namespaceHTMLElements)
+ return p.parseFragment(doc, container=container, encoding=encoding)
+
+
+def method_decorator_metaclass(function):
+ class Decorated(type):
+ def __new__(meta, classname, bases, classDict):
+ for attributeName, attribute in classDict.items():
+ if isinstance(attribute, types.FunctionType):
+ attribute = function(attribute)
+
+ classDict[attributeName] = attribute
+ return type.__new__(meta, classname, bases, classDict)
+ return Decorated
+
+
+class HTMLParser(object):
+ """HTML parser. Generates a tree structure from a stream of (possibly
+ malformed) HTML"""
+
+ def __init__(self, tree=None, tokenizer=tokenizer.HTMLTokenizer,
+ strict=False, namespaceHTMLElements=True, debug=False):
+ """
+ strict - raise an exception when a parse error is encountered
+
+ tree - a treebuilder class controlling the type of tree that will be
+ returned. Built in treebuilders can be accessed through
+ html5lib.treebuilders.getTreeBuilder(treeType)
+
+ tokenizer - a class that provides a stream of tokens to the treebuilder.
+ This may be replaced for e.g. a sanitizer which converts some tags to
+ text
+ """
+
+ # Raise an exception on the first error encountered
+ self.strict = strict
+
+ if tree is None:
+ tree = treebuilders.getTreeBuilder("etree")
+ self.tree = tree(namespaceHTMLElements)
+ self.tokenizer_class = tokenizer
+ self.errors = []
+
+ self.phases = dict([(name, cls(self, self.tree)) for name, cls in
+ getPhases(debug).items()])
+
+ def _parse(self, stream, innerHTML=False, container="div",
+ encoding=None, parseMeta=True, useChardet=True, **kwargs):
+
+ self.innerHTMLMode = innerHTML
+ self.container = container
+ self.tokenizer = self.tokenizer_class(stream, encoding=encoding,
+ parseMeta=parseMeta,
+ useChardet=useChardet,
+ parser=self, **kwargs)
+ self.reset()
+
+ while True:
+ try:
+ self.mainLoop()
+ break
+ except ReparseException:
+ self.reset()
+
+ def reset(self):
+ self.tree.reset()
+ self.firstStartTag = False
+ self.errors = []
+ self.log = [] # only used with debug mode
+ # "quirks" / "limited quirks" / "no quirks"
+ self.compatMode = "no quirks"
+
+ if self.innerHTMLMode:
+ self.innerHTML = self.container.lower()
+
+ if self.innerHTML in cdataElements:
+ self.tokenizer.state = self.tokenizer.rcdataState
+ elif self.innerHTML in rcdataElements:
+ self.tokenizer.state = self.tokenizer.rawtextState
+ elif self.innerHTML == 'plaintext':
+ self.tokenizer.state = self.tokenizer.plaintextState
+ else:
+ # state already is data state
+ # self.tokenizer.state = self.tokenizer.dataState
+ pass
+ self.phase = self.phases["beforeHtml"]
+ self.phase.insertHtmlElement()
+ self.resetInsertionMode()
+ else:
+ self.innerHTML = False
+ self.phase = self.phases["initial"]
+
+ self.lastPhase = None
+
+ self.beforeRCDataPhase = None
+
+ self.framesetOK = True
+
+ @property
+ def documentEncoding(self):
+ """The name of the character encoding
+ that was used to decode the input stream,
+ or :obj:`None` if that is not determined yet.
+
+ """
+ if not hasattr(self, 'tokenizer'):
+ return None
+ return self.tokenizer.stream.charEncoding[0]
+
+ def isHTMLIntegrationPoint(self, element):
+ if (element.name == "annotation-xml" and
+ element.namespace == namespaces["mathml"]):
+ return ("encoding" in element.attributes and
+ element.attributes["encoding"].translate(
+ asciiUpper2Lower) in
+ ("text/html", "application/xhtml+xml"))
+ else:
+ return (element.namespace, element.name) in htmlIntegrationPointElements
+
+ def isMathMLTextIntegrationPoint(self, element):
+ return (element.namespace, element.name) in mathmlTextIntegrationPointElements
+
+ def mainLoop(self):
+ CharactersToken = tokenTypes["Characters"]
+ SpaceCharactersToken = tokenTypes["SpaceCharacters"]
+ StartTagToken = tokenTypes["StartTag"]
+ EndTagToken = tokenTypes["EndTag"]
+ CommentToken = tokenTypes["Comment"]
+ DoctypeToken = tokenTypes["Doctype"]
+ ParseErrorToken = tokenTypes["ParseError"]
+
+ for token in self.normalizedTokens():
+ new_token = token
+ while new_token is not None:
+ currentNode = self.tree.openElements[-1] if self.tree.openElements else None
+ currentNodeNamespace = currentNode.namespace if currentNode else None
+ currentNodeName = currentNode.name if currentNode else None
+
+ type = new_token["type"]
+
+ if type == ParseErrorToken:
+ self.parseError(new_token["data"], new_token.get("datavars", {}))
+ new_token = None
+ else:
+ if (len(self.tree.openElements) == 0 or
+ currentNodeNamespace == self.tree.defaultNamespace or
+ (self.isMathMLTextIntegrationPoint(currentNode) and
+ ((type == StartTagToken and
+ token["name"] not in frozenset(["mglyph", "malignmark"])) or
+ type in (CharactersToken, SpaceCharactersToken))) or
+ (currentNodeNamespace == namespaces["mathml"] and
+ currentNodeName == "annotation-xml" and
+ token["name"] == "svg") or
+ (self.isHTMLIntegrationPoint(currentNode) and
+ type in (StartTagToken, CharactersToken, SpaceCharactersToken))):
+ phase = self.phase
+ else:
+ phase = self.phases["inForeignContent"]
+
+ if type == CharactersToken:
+ new_token = phase.processCharacters(new_token)
+ elif type == SpaceCharactersToken:
+ new_token = phase.processSpaceCharacters(new_token)
+ elif type == StartTagToken:
+ new_token = phase.processStartTag(new_token)
+ elif type == EndTagToken:
+ new_token = phase.processEndTag(new_token)
+ elif type == CommentToken:
+ new_token = phase.processComment(new_token)
+ elif type == DoctypeToken:
+ new_token = phase.processDoctype(new_token)
+
+ if (type == StartTagToken and token["selfClosing"]
+ and not token["selfClosingAcknowledged"]):
+ self.parseError("non-void-element-with-trailing-solidus",
+ {"name": token["name"]})
+
+ # When the loop finishes it's EOF
+ reprocess = True
+ phases = []
+ while reprocess:
+ phases.append(self.phase)
+ reprocess = self.phase.processEOF()
+ if reprocess:
+ assert self.phase not in phases
+
+ def normalizedTokens(self):
+ for token in self.tokenizer:
+ yield self.normalizeToken(token)
+
+ def parse(self, stream, encoding=None, parseMeta=True, useChardet=True):
+ """Parse a HTML document into a well-formed tree
+
+ stream - a filelike object or string containing the HTML to be parsed
+
+ The optional encoding parameter must be a string that indicates
+ the encoding. If specified, that encoding will be used,
+ regardless of any BOM or later declaration (such as in a meta
+ element)
+ """
+ self._parse(stream, innerHTML=False, encoding=encoding,
+ parseMeta=parseMeta, useChardet=useChardet)
+ return self.tree.getDocument()
+
+ def parseFragment(self, stream, container="div", encoding=None,
+ parseMeta=False, useChardet=True):
+ """Parse a HTML fragment into a well-formed tree fragment
+
+ container - name of the element we're setting the innerHTML property
+ if set to None, default to 'div'
+
+ stream - a filelike object or string containing the HTML to be parsed
+
+ The optional encoding parameter must be a string that indicates
+ the encoding. If specified, that encoding will be used,
+ regardless of any BOM or later declaration (such as in a meta
+ element)
+ """
+ self._parse(stream, True, container=container, encoding=encoding)
+ return self.tree.getFragment()
+
+ def parseError(self, errorcode="XXX-undefined-error", datavars={}):
+ # XXX The idea is to make errorcode mandatory.
+ self.errors.append((self.tokenizer.stream.position(), errorcode, datavars))
+ if self.strict:
+ raise ParseError
+
+ def normalizeToken(self, token):
+ """ HTML5 specific normalizations to the token stream """
+
+ if token["type"] == tokenTypes["StartTag"]:
+ token["data"] = dict(token["data"][::-1])
+
+ return token
+
+ def adjustMathMLAttributes(self, token):
+ replacements = {"definitionurl": "definitionURL"}
+ for k, v in replacements.items():
+ if k in token["data"]:
+ token["data"][v] = token["data"][k]
+ del token["data"][k]
+
+ def adjustSVGAttributes(self, token):
+ replacements = {
+ "attributename": "attributeName",
+ "attributetype": "attributeType",
+ "basefrequency": "baseFrequency",
+ "baseprofile": "baseProfile",
+ "calcmode": "calcMode",
+ "clippathunits": "clipPathUnits",
+ "contentscripttype": "contentScriptType",
+ "contentstyletype": "contentStyleType",
+ "diffuseconstant": "diffuseConstant",
+ "edgemode": "edgeMode",
+ "externalresourcesrequired": "externalResourcesRequired",
+ "filterres": "filterRes",
+ "filterunits": "filterUnits",
+ "glyphref": "glyphRef",
+ "gradienttransform": "gradientTransform",
+ "gradientunits": "gradientUnits",
+ "kernelmatrix": "kernelMatrix",
+ "kernelunitlength": "kernelUnitLength",
+ "keypoints": "keyPoints",
+ "keysplines": "keySplines",
+ "keytimes": "keyTimes",
+ "lengthadjust": "lengthAdjust",
+ "limitingconeangle": "limitingConeAngle",
+ "markerheight": "markerHeight",
+ "markerunits": "markerUnits",
+ "markerwidth": "markerWidth",
+ "maskcontentunits": "maskContentUnits",
+ "maskunits": "maskUnits",
+ "numoctaves": "numOctaves",
+ "pathlength": "pathLength",
+ "patterncontentunits": "patternContentUnits",
+ "patterntransform": "patternTransform",
+ "patternunits": "patternUnits",
+ "pointsatx": "pointsAtX",
+ "pointsaty": "pointsAtY",
+ "pointsatz": "pointsAtZ",
+ "preservealpha": "preserveAlpha",
+ "preserveaspectratio": "preserveAspectRatio",
+ "primitiveunits": "primitiveUnits",
+ "refx": "refX",
+ "refy": "refY",
+ "repeatcount": "repeatCount",
+ "repeatdur": "repeatDur",
+ "requiredextensions": "requiredExtensions",
+ "requiredfeatures": "requiredFeatures",
+ "specularconstant": "specularConstant",
+ "specularexponent": "specularExponent",
+ "spreadmethod": "spreadMethod",
+ "startoffset": "startOffset",
+ "stddeviation": "stdDeviation",
+ "stitchtiles": "stitchTiles",
+ "surfacescale": "surfaceScale",
+ "systemlanguage": "systemLanguage",
+ "tablevalues": "tableValues",
+ "targetx": "targetX",
+ "targety": "targetY",
+ "textlength": "textLength",
+ "viewbox": "viewBox",
+ "viewtarget": "viewTarget",
+ "xchannelselector": "xChannelSelector",
+ "ychannelselector": "yChannelSelector",
+ "zoomandpan": "zoomAndPan"
+ }
+ for originalName in list(token["data"].keys()):
+ if originalName in replacements:
+ svgName = replacements[originalName]
+ token["data"][svgName] = token["data"][originalName]
+ del token["data"][originalName]
+
+ def adjustForeignAttributes(self, token):
+ replacements = adjustForeignAttributesMap
+
+ for originalName in token["data"].keys():
+ if originalName in replacements:
+ foreignName = replacements[originalName]
+ token["data"][foreignName] = token["data"][originalName]
+ del token["data"][originalName]
+
+ def reparseTokenNormal(self, token):
+ self.parser.phase()
+
+ def resetInsertionMode(self):
+ # The name of this method is mostly historical. (It's also used in the
+ # specification.)
+ last = False
+ newModes = {
+ "select": "inSelect",
+ "td": "inCell",
+ "th": "inCell",
+ "tr": "inRow",
+ "tbody": "inTableBody",
+ "thead": "inTableBody",
+ "tfoot": "inTableBody",
+ "caption": "inCaption",
+ "colgroup": "inColumnGroup",
+ "table": "inTable",
+ "head": "inBody",
+ "body": "inBody",
+ "frameset": "inFrameset",
+ "html": "beforeHead"
+ }
+ for node in self.tree.openElements[::-1]:
+ nodeName = node.name
+ new_phase = None
+ if node == self.tree.openElements[0]:
+ assert self.innerHTML
+ last = True
+ nodeName = self.innerHTML
+ # Check for conditions that should only happen in the innerHTML
+ # case
+ if nodeName in ("select", "colgroup", "head", "html"):
+ assert self.innerHTML
+
+ if not last and node.namespace != self.tree.defaultNamespace:
+ continue
+
+ if nodeName in newModes:
+ new_phase = self.phases[newModes[nodeName]]
+ break
+ elif last:
+ new_phase = self.phases["inBody"]
+ break
+
+ self.phase = new_phase
+
+ def parseRCDataRawtext(self, token, contentType):
+ """Generic RCDATA/RAWTEXT Parsing algorithm
+ contentType - RCDATA or RAWTEXT
+ """
+ assert contentType in ("RAWTEXT", "RCDATA")
+
+ self.tree.insertElement(token)
+
+ if contentType == "RAWTEXT":
+ self.tokenizer.state = self.tokenizer.rawtextState
+ else:
+ self.tokenizer.state = self.tokenizer.rcdataState
+
+ self.originalPhase = self.phase
+
+ self.phase = self.phases["text"]
+
+
+def getPhases(debug):
+ def log(function):
+ """Logger that records which phase processes each token"""
+ type_names = dict((value, key) for key, value in
+ constants.tokenTypes.items())
+
+ def wrapped(self, *args, **kwargs):
+ if function.__name__.startswith("process") and len(args) > 0:
+ token = args[0]
+ try:
+ info = {"type": type_names[token['type']]}
+ except:
+ raise
+ if token['type'] in constants.tagTokenTypes:
+ info["name"] = token['name']
+
+ self.parser.log.append((self.parser.tokenizer.state.__name__,
+ self.parser.phase.__class__.__name__,
+ self.__class__.__name__,
+ function.__name__,
+ info))
+ return function(self, *args, **kwargs)
+ else:
+ return function(self, *args, **kwargs)
+ return wrapped
+
+ def getMetaclass(use_metaclass, metaclass_func):
+ if use_metaclass:
+ return method_decorator_metaclass(metaclass_func)
+ else:
+ return type
+
+ class Phase(with_metaclass(getMetaclass(debug, log))):
+ """Base class for helper object that implements each phase of processing
+ """
+
+ def __init__(self, parser, tree):
+ self.parser = parser
+ self.tree = tree
+
+ def processEOF(self):
+ raise NotImplementedError
+
+ def processComment(self, token):
+ # For most phases the following is correct. Where it's not it will be
+ # overridden.
+ self.tree.insertComment(token, self.tree.openElements[-1])
+
+ def processDoctype(self, token):
+ self.parser.parseError("unexpected-doctype")
+
+ def processCharacters(self, token):
+ self.tree.insertText(token["data"])
+
+ def processSpaceCharacters(self, token):
+ self.tree.insertText(token["data"])
+
+ def processStartTag(self, token):
+ return self.startTagHandler[token["name"]](token)
+
+ def startTagHtml(self, token):
+ if not self.parser.firstStartTag and token["name"] == "html":
+ self.parser.parseError("non-html-root")
+ # XXX Need a check here to see if the first start tag token emitted is
+ # this token... If it's not, invoke self.parser.parseError().
+ for attr, value in token["data"].items():
+ if attr not in self.tree.openElements[0].attributes:
+ self.tree.openElements[0].attributes[attr] = value
+ self.parser.firstStartTag = False
+
+ def processEndTag(self, token):
+ return self.endTagHandler[token["name"]](token)
+
+ class InitialPhase(Phase):
+ def processSpaceCharacters(self, token):
+ pass
+
+ def processComment(self, token):
+ self.tree.insertComment(token, self.tree.document)
+
+ def processDoctype(self, token):
+ name = token["name"]
+ publicId = token["publicId"]
+ systemId = token["systemId"]
+ correct = token["correct"]
+
+ if (name != "html" or publicId is not None or
+ systemId is not None and systemId != "about:legacy-compat"):
+ self.parser.parseError("unknown-doctype")
+
+ if publicId is None:
+ publicId = ""
+
+ self.tree.insertDoctype(token)
+
+ if publicId != "":
+ publicId = publicId.translate(asciiUpper2Lower)
+
+ if (not correct or token["name"] != "html"
+ or publicId.startswith(
+ ("+//silmaril//dtd html pro v0r11 19970101//",
+ "-//advasoft ltd//dtd html 3.0 aswedit + extensions//",
+ "-//as//dtd html 3.0 aswedit + extensions//",
+ "-//ietf//dtd html 2.0 level 1//",
+ "-//ietf//dtd html 2.0 level 2//",
+ "-//ietf//dtd html 2.0 strict level 1//",
+ "-//ietf//dtd html 2.0 strict level 2//",
+ "-//ietf//dtd html 2.0 strict//",
+ "-//ietf//dtd html 2.0//",
+ "-//ietf//dtd html 2.1e//",
+ "-//ietf//dtd html 3.0//",
+ "-//ietf//dtd html 3.2 final//",
+ "-//ietf//dtd html 3.2//",
+ "-//ietf//dtd html 3//",
+ "-//ietf//dtd html level 0//",
+ "-//ietf//dtd html level 1//",
+ "-//ietf//dtd html level 2//",
+ "-//ietf//dtd html level 3//",
+ "-//ietf//dtd html strict level 0//",
+ "-//ietf//dtd html strict level 1//",
+ "-//ietf//dtd html strict level 2//",
+ "-//ietf//dtd html strict level 3//",
+ "-//ietf//dtd html strict//",
+ "-//ietf//dtd html//",
+ "-//metrius//dtd metrius presentational//",
+ "-//microsoft//dtd internet explorer 2.0 html strict//",
+ "-//microsoft//dtd internet explorer 2.0 html//",
+ "-//microsoft//dtd internet explorer 2.0 tables//",
+ "-//microsoft//dtd internet explorer 3.0 html strict//",
+ "-//microsoft//dtd internet explorer 3.0 html//",
+ "-//microsoft//dtd internet explorer 3.0 tables//",
+ "-//netscape comm. corp.//dtd html//",
+ "-//netscape comm. corp.//dtd strict html//",
+ "-//o'reilly and associates//dtd html 2.0//",
+ "-//o'reilly and associates//dtd html extended 1.0//",
+ "-//o'reilly and associates//dtd html extended relaxed 1.0//",
+ "-//softquad software//dtd hotmetal pro 6.0::19990601::extensions to html 4.0//",
+ "-//softquad//dtd hotmetal pro 4.0::19971010::extensions to html 4.0//",
+ "-//spyglass//dtd html 2.0 extended//",
+ "-//sq//dtd html 2.0 hotmetal + extensions//",
+ "-//sun microsystems corp.//dtd hotjava html//",
+ "-//sun microsystems corp.//dtd hotjava strict html//",
+ "-//w3c//dtd html 3 1995-03-24//",
+ "-//w3c//dtd html 3.2 draft//",
+ "-//w3c//dtd html 3.2 final//",
+ "-//w3c//dtd html 3.2//",
+ "-//w3c//dtd html 3.2s draft//",
+ "-//w3c//dtd html 4.0 frameset//",
+ "-//w3c//dtd html 4.0 transitional//",
+ "-//w3c//dtd html experimental 19960712//",
+ "-//w3c//dtd html experimental 970421//",
+ "-//w3c//dtd w3 html//",
+ "-//w3o//dtd w3 html 3.0//",
+ "-//webtechs//dtd mozilla html 2.0//",
+ "-//webtechs//dtd mozilla html//"))
+ or publicId in
+ ("-//w3o//dtd w3 html strict 3.0//en//",
+ "-/w3c/dtd html 4.0 transitional/en",
+ "html")
+ or publicId.startswith(
+ ("-//w3c//dtd html 4.01 frameset//",
+ "-//w3c//dtd html 4.01 transitional//")) and
+ systemId is None
+ or systemId and systemId.lower() == "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd"):
+ self.parser.compatMode = "quirks"
+ elif (publicId.startswith(
+ ("-//w3c//dtd xhtml 1.0 frameset//",
+ "-//w3c//dtd xhtml 1.0 transitional//"))
+ or publicId.startswith(
+ ("-//w3c//dtd html 4.01 frameset//",
+ "-//w3c//dtd html 4.01 transitional//")) and
+ systemId is not None):
+ self.parser.compatMode = "limited quirks"
+
+ self.parser.phase = self.parser.phases["beforeHtml"]
+
+ def anythingElse(self):
+ self.parser.compatMode = "quirks"
+ self.parser.phase = self.parser.phases["beforeHtml"]
+
+ def processCharacters(self, token):
+ self.parser.parseError("expected-doctype-but-got-chars")
+ self.anythingElse()
+ return token
+
+ def processStartTag(self, token):
+ self.parser.parseError("expected-doctype-but-got-start-tag",
+ {"name": token["name"]})
+ self.anythingElse()
+ return token
+
+ def processEndTag(self, token):
+ self.parser.parseError("expected-doctype-but-got-end-tag",
+ {"name": token["name"]})
+ self.anythingElse()
+ return token
+
+ def processEOF(self):
+ self.parser.parseError("expected-doctype-but-got-eof")
+ self.anythingElse()
+ return True
+
+ class BeforeHtmlPhase(Phase):
+ # helper methods
+ def insertHtmlElement(self):
+ self.tree.insertRoot(impliedTagToken("html", "StartTag"))
+ self.parser.phase = self.parser.phases["beforeHead"]
+
+ # other
+ def processEOF(self):
+ self.insertHtmlElement()
+ return True
+
+ def processComment(self, token):
+ self.tree.insertComment(token, self.tree.document)
+
+ def processSpaceCharacters(self, token):
+ pass
+
+ def processCharacters(self, token):
+ self.insertHtmlElement()
+ return token
+
+ def processStartTag(self, token):
+ if token["name"] == "html":
+ self.parser.firstStartTag = True
+ self.insertHtmlElement()
+ return token
+
+ def processEndTag(self, token):
+ if token["name"] not in ("head", "body", "html", "br"):
+ self.parser.parseError("unexpected-end-tag-before-html",
+ {"name": token["name"]})
+ else:
+ self.insertHtmlElement()
+ return token
+
+ class BeforeHeadPhase(Phase):
+ def __init__(self, parser, tree):
+ Phase.__init__(self, parser, tree)
+
+ self.startTagHandler = utils.MethodDispatcher([
+ ("html", self.startTagHtml),
+ ("head", self.startTagHead)
+ ])
+ self.startTagHandler.default = self.startTagOther
+
+ self.endTagHandler = utils.MethodDispatcher([
+ (("head", "body", "html", "br"), self.endTagImplyHead)
+ ])
+ self.endTagHandler.default = self.endTagOther
+
+ def processEOF(self):
+ self.startTagHead(impliedTagToken("head", "StartTag"))
+ return True
+
+ def processSpaceCharacters(self, token):
+ pass
+
+ def processCharacters(self, token):
+ self.startTagHead(impliedTagToken("head", "StartTag"))
+ return token
+
+ def startTagHtml(self, token):
+ return self.parser.phases["inBody"].processStartTag(token)
+
+ def startTagHead(self, token):
+ self.tree.insertElement(token)
+ self.tree.headPointer = self.tree.openElements[-1]
+ self.parser.phase = self.parser.phases["inHead"]
+
+ def startTagOther(self, token):
+ self.startTagHead(impliedTagToken("head", "StartTag"))
+ return token
+
+ def endTagImplyHead(self, token):
+ self.startTagHead(impliedTagToken("head", "StartTag"))
+ return token
+
+ def endTagOther(self, token):
+ self.parser.parseError("end-tag-after-implied-root",
+ {"name": token["name"]})
+
+ class InHeadPhase(Phase):
+ def __init__(self, parser, tree):
+ Phase.__init__(self, parser, tree)
+
+ self.startTagHandler = utils.MethodDispatcher([
+ ("html", self.startTagHtml),
+ ("title", self.startTagTitle),
+ (("noscript", "noframes", "style"), self.startTagNoScriptNoFramesStyle),
+ ("script", self.startTagScript),
+ (("base", "basefont", "bgsound", "command", "link"),
+ self.startTagBaseLinkCommand),
+ ("meta", self.startTagMeta),
+ ("head", self.startTagHead)
+ ])
+ self.startTagHandler.default = self.startTagOther
+
+ self. endTagHandler = utils.MethodDispatcher([
+ ("head", self.endTagHead),
+ (("br", "html", "body"), self.endTagHtmlBodyBr)
+ ])
+ self.endTagHandler.default = self.endTagOther
+
+ # the real thing
+ def processEOF(self):
+ self.anythingElse()
+ return True
+
+ def processCharacters(self, token):
+ self.anythingElse()
+ return token
+
+ def startTagHtml(self, token):
+ return self.parser.phases["inBody"].processStartTag(token)
+
+ def startTagHead(self, token):
+ self.parser.parseError("two-heads-are-not-better-than-one")
+
+ def startTagBaseLinkCommand(self, token):
+ self.tree.insertElement(token)
+ self.tree.openElements.pop()
+ token["selfClosingAcknowledged"] = True
+
+ def startTagMeta(self, token):
+ self.tree.insertElement(token)
+ self.tree.openElements.pop()
+ token["selfClosingAcknowledged"] = True
+
+ attributes = token["data"]
+ if self.parser.tokenizer.stream.charEncoding[1] == "tentative":
+ if "charset" in attributes:
+ self.parser.tokenizer.stream.changeEncoding(attributes["charset"])
+ elif ("content" in attributes and
+ "http-equiv" in attributes and
+ attributes["http-equiv"].lower() == "content-type"):
+ # Encoding it as UTF-8 here is a hack, as really we should pass
+ # the abstract Unicode string, and just use the
+ # ContentAttrParser on that, but using UTF-8 allows all chars
+ # to be encoded and as a ASCII-superset works.
+ data = inputstream.EncodingBytes(attributes["content"].encode("utf-8"))
+ parser = inputstream.ContentAttrParser(data)
+ codec = parser.parse()
+ self.parser.tokenizer.stream.changeEncoding(codec)
+
+ def startTagTitle(self, token):
+ self.parser.parseRCDataRawtext(token, "RCDATA")
+
+ def startTagNoScriptNoFramesStyle(self, token):
+ # Need to decide whether to implement the scripting-disabled case
+ self.parser.parseRCDataRawtext(token, "RAWTEXT")
+
+ def startTagScript(self, token):
+ self.tree.insertElement(token)
+ self.parser.tokenizer.state = self.parser.tokenizer.scriptDataState
+ self.parser.originalPhase = self.parser.phase
+ self.parser.phase = self.parser.phases["text"]
+
+ def startTagOther(self, token):
+ self.anythingElse()
+ return token
+
+ def endTagHead(self, token):
+ node = self.parser.tree.openElements.pop()
+ assert node.name == "head", "Expected head got %s" % node.name
+ self.parser.phase = self.parser.phases["afterHead"]
+
+ def endTagHtmlBodyBr(self, token):
+ self.anythingElse()
+ return token
+
+ def endTagOther(self, token):
+ self.parser.parseError("unexpected-end-tag", {"name": token["name"]})
+
+ def anythingElse(self):
+ self.endTagHead(impliedTagToken("head"))
+
+ # XXX If we implement a parser for which scripting is disabled we need to
+ # implement this phase.
+ #
+ # class InHeadNoScriptPhase(Phase):
+ class AfterHeadPhase(Phase):
+ def __init__(self, parser, tree):
+ Phase.__init__(self, parser, tree)
+
+ self.startTagHandler = utils.MethodDispatcher([
+ ("html", self.startTagHtml),
+ ("body", self.startTagBody),
+ ("frameset", self.startTagFrameset),
+ (("base", "basefont", "bgsound", "link", "meta", "noframes", "script",
+ "style", "title"),
+ self.startTagFromHead),
+ ("head", self.startTagHead)
+ ])
+ self.startTagHandler.default = self.startTagOther
+ self.endTagHandler = utils.MethodDispatcher([(("body", "html", "br"),
+ self.endTagHtmlBodyBr)])
+ self.endTagHandler.default = self.endTagOther
+
+ def processEOF(self):
+ self.anythingElse()
+ return True
+
+ def processCharacters(self, token):
+ self.anythingElse()
+ return token
+
+ def startTagHtml(self, token):
+ return self.parser.phases["inBody"].processStartTag(token)
+
+ def startTagBody(self, token):
+ self.parser.framesetOK = False
+ self.tree.insertElement(token)
+ self.parser.phase = self.parser.phases["inBody"]
+
+ def startTagFrameset(self, token):
+ self.tree.insertElement(token)
+ self.parser.phase = self.parser.phases["inFrameset"]
+
+ def startTagFromHead(self, token):
+ self.parser.parseError("unexpected-start-tag-out-of-my-head",
+ {"name": token["name"]})
+ self.tree.openElements.append(self.tree.headPointer)
+ self.parser.phases["inHead"].processStartTag(token)
+ for node in self.tree.openElements[::-1]:
+ if node.name == "head":
+ self.tree.openElements.remove(node)
+ break
+
+ def startTagHead(self, token):
+ self.parser.parseError("unexpected-start-tag", {"name": token["name"]})
+
+ def startTagOther(self, token):
+ self.anythingElse()
+ return token
+
+ def endTagHtmlBodyBr(self, token):
+ self.anythingElse()
+ return token
+
+ def endTagOther(self, token):
+ self.parser.parseError("unexpected-end-tag", {"name": token["name"]})
+
+ def anythingElse(self):
+ self.tree.insertElement(impliedTagToken("body", "StartTag"))
+ self.parser.phase = self.parser.phases["inBody"]
+ self.parser.framesetOK = True
+
+ class InBodyPhase(Phase):
+ # http://www.whatwg.org/specs/web-apps/current-work/#parsing-main-inbody
+ # the really-really-really-very crazy mode
+ def __init__(self, parser, tree):
+ Phase.__init__(self, parser, tree)
+
+ # Keep a ref to this for special handling of whitespace in <pre>
+ self.processSpaceCharactersNonPre = self.processSpaceCharacters
+
+ self.startTagHandler = utils.MethodDispatcher([
+ ("html", self.startTagHtml),
+ (("base", "basefont", "bgsound", "command", "link", "meta",
+ "noframes", "script", "style", "title"),
+ self.startTagProcessInHead),
+ ("body", self.startTagBody),
+ ("frameset", self.startTagFrameset),
+ (("address", "article", "aside", "blockquote", "center", "details",
+ "details", "dir", "div", "dl", "fieldset", "figcaption", "figure",
+ "footer", "header", "hgroup", "main", "menu", "nav", "ol", "p",
+ "section", "summary", "ul"),
+ self.startTagCloseP),
+ (headingElements, self.startTagHeading),
+ (("pre", "listing"), self.startTagPreListing),
+ ("form", self.startTagForm),
+ (("li", "dd", "dt"), self.startTagListItem),
+ ("plaintext", self.startTagPlaintext),
+ ("a", self.startTagA),
+ (("b", "big", "code", "em", "font", "i", "s", "small", "strike",
+ "strong", "tt", "u"), self.startTagFormatting),
+ ("nobr", self.startTagNobr),
+ ("button", self.startTagButton),
+ (("applet", "marquee", "object"), self.startTagAppletMarqueeObject),
+ ("xmp", self.startTagXmp),
+ ("table", self.startTagTable),
+ (("area", "br", "embed", "img", "keygen", "wbr"),
+ self.startTagVoidFormatting),
+ (("param", "source", "track"), self.startTagParamSource),
+ ("input", self.startTagInput),
+ ("hr", self.startTagHr),
+ ("image", self.startTagImage),
+ ("isindex", self.startTagIsIndex),
+ ("textarea", self.startTagTextarea),
+ ("iframe", self.startTagIFrame),
+ (("noembed", "noframes", "noscript"), self.startTagRawtext),
+ ("select", self.startTagSelect),
+ (("rp", "rt"), self.startTagRpRt),
+ (("option", "optgroup"), self.startTagOpt),
+ (("math"), self.startTagMath),
+ (("svg"), self.startTagSvg),
+ (("caption", "col", "colgroup", "frame", "head",
+ "tbody", "td", "tfoot", "th", "thead",
+ "tr"), self.startTagMisplaced)
+ ])
+ self.startTagHandler.default = self.startTagOther
+
+ self.endTagHandler = utils.MethodDispatcher([
+ ("body", self.endTagBody),
+ ("html", self.endTagHtml),
+ (("address", "article", "aside", "blockquote", "button", "center",
+ "details", "dialog", "dir", "div", "dl", "fieldset", "figcaption", "figure",
+ "footer", "header", "hgroup", "listing", "main", "menu", "nav", "ol", "pre",
+ "section", "summary", "ul"), self.endTagBlock),
+ ("form", self.endTagForm),
+ ("p", self.endTagP),
+ (("dd", "dt", "li"), self.endTagListItem),
+ (headingElements, self.endTagHeading),
+ (("a", "b", "big", "code", "em", "font", "i", "nobr", "s", "small",
+ "strike", "strong", "tt", "u"), self.endTagFormatting),
+ (("applet", "marquee", "object"), self.endTagAppletMarqueeObject),
+ ("br", self.endTagBr),
+ ])
+ self.endTagHandler.default = self.endTagOther
+
+ def isMatchingFormattingElement(self, node1, node2):
+ if node1.name != node2.name or node1.namespace != node2.namespace:
+ return False
+ elif len(node1.attributes) != len(node2.attributes):
+ return False
+ else:
+ attributes1 = sorted(node1.attributes.items())
+ attributes2 = sorted(node2.attributes.items())
+ for attr1, attr2 in zip(attributes1, attributes2):
+ if attr1 != attr2:
+ return False
+ return True
+
+ # helper
+ def addFormattingElement(self, token):
+ self.tree.insertElement(token)
+ element = self.tree.openElements[-1]
+
+ matchingElements = []
+ for node in self.tree.activeFormattingElements[::-1]:
+ if node is Marker:
+ break
+ elif self.isMatchingFormattingElement(node, element):
+ matchingElements.append(node)
+
+ assert len(matchingElements) <= 3
+ if len(matchingElements) == 3:
+ self.tree.activeFormattingElements.remove(matchingElements[-1])
+ self.tree.activeFormattingElements.append(element)
+
+ # the real deal
+ def processEOF(self):
+ allowed_elements = frozenset(("dd", "dt", "li", "p", "tbody", "td",
+ "tfoot", "th", "thead", "tr", "body",
+ "html"))
+ for node in self.tree.openElements[::-1]:
+ if node.name not in allowed_elements:
+ self.parser.parseError("expected-closing-tag-but-got-eof")
+ break
+ # Stop parsing
+
+ def processSpaceCharactersDropNewline(self, token):
+ # Sometimes (start of <pre>, <listing>, and <textarea> blocks) we
+ # want to drop leading newlines
+ data = token["data"]
+ self.processSpaceCharacters = self.processSpaceCharactersNonPre
+ if (data.startswith("\n") and
+ self.tree.openElements[-1].name in ("pre", "listing", "textarea")
+ and not self.tree.openElements[-1].hasContent()):
+ data = data[1:]
+ if data:
+ self.tree.reconstructActiveFormattingElements()
+ self.tree.insertText(data)
+
+ def processCharacters(self, token):
+ if token["data"] == "\u0000":
+ # The tokenizer should always emit null on its own
+ return
+ self.tree.reconstructActiveFormattingElements()
+ self.tree.insertText(token["data"])
+ # This must be bad for performance
+ if (self.parser.framesetOK and
+ any([char not in spaceCharacters
+ for char in token["data"]])):
+ self.parser.framesetOK = False
+
+ def processSpaceCharacters(self, token):
+ self.tree.reconstructActiveFormattingElements()
+ self.tree.insertText(token["data"])
+
+ def startTagProcessInHead(self, token):
+ return self.parser.phases["inHead"].processStartTag(token)
+
+ def startTagBody(self, token):
+ self.parser.parseError("unexpected-start-tag", {"name": "body"})
+ if (len(self.tree.openElements) == 1
+ or self.tree.openElements[1].name != "body"):
+ assert self.parser.innerHTML
+ else:
+ self.parser.framesetOK = False
+ for attr, value in token["data"].items():
+ if attr not in self.tree.openElements[1].attributes:
+ self.tree.openElements[1].attributes[attr] = value
+
+ def startTagFrameset(self, token):
+ self.parser.parseError("unexpected-start-tag", {"name": "frameset"})
+ if (len(self.tree.openElements) == 1 or self.tree.openElements[1].name != "body"):
+ assert self.parser.innerHTML
+ elif not self.parser.framesetOK:
+ pass
+ else:
+ if self.tree.openElements[1].parent:
+ self.tree.openElements[1].parent.removeChild(self.tree.openElements[1])
+ while self.tree.openElements[-1].name != "html":
+ self.tree.openElements.pop()
+ self.tree.insertElement(token)
+ self.parser.phase = self.parser.phases["inFrameset"]
+
+ def startTagCloseP(self, token):
+ if self.tree.elementInScope("p", variant="button"):
+ self.endTagP(impliedTagToken("p"))
+ self.tree.insertElement(token)
+
+ def startTagPreListing(self, token):
+ if self.tree.elementInScope("p", variant="button"):
+ self.endTagP(impliedTagToken("p"))
+ self.tree.insertElement(token)
+ self.parser.framesetOK = False
+ self.processSpaceCharacters = self.processSpaceCharactersDropNewline
+
+ def startTagForm(self, token):
+ if self.tree.formPointer:
+ self.parser.parseError("unexpected-start-tag", {"name": "form"})
+ else:
+ if self.tree.elementInScope("p", variant="button"):
+ self.endTagP(impliedTagToken("p"))
+ self.tree.insertElement(token)
+ self.tree.formPointer = self.tree.openElements[-1]
+
+ def startTagListItem(self, token):
+ self.parser.framesetOK = False
+
+ stopNamesMap = {"li": ["li"],
+ "dt": ["dt", "dd"],
+ "dd": ["dt", "dd"]}
+ stopNames = stopNamesMap[token["name"]]
+ for node in reversed(self.tree.openElements):
+ if node.name in stopNames:
+ self.parser.phase.processEndTag(
+ impliedTagToken(node.name, "EndTag"))
+ break
+ if (node.nameTuple in specialElements and
+ node.name not in ("address", "div", "p")):
+ break
+
+ if self.tree.elementInScope("p", variant="button"):
+ self.parser.phase.processEndTag(
+ impliedTagToken("p", "EndTag"))
+
+ self.tree.insertElement(token)
+
+ def startTagPlaintext(self, token):
+ if self.tree.elementInScope("p", variant="button"):
+ self.endTagP(impliedTagToken("p"))
+ self.tree.insertElement(token)
+ self.parser.tokenizer.state = self.parser.tokenizer.plaintextState
+
+ def startTagHeading(self, token):
+ if self.tree.elementInScope("p", variant="button"):
+ self.endTagP(impliedTagToken("p"))
+ if self.tree.openElements[-1].name in headingElements:
+ self.parser.parseError("unexpected-start-tag", {"name": token["name"]})
+ self.tree.openElements.pop()
+ self.tree.insertElement(token)
+
+ def startTagA(self, token):
+ afeAElement = self.tree.elementInActiveFormattingElements("a")
+ if afeAElement:
+ self.parser.parseError("unexpected-start-tag-implies-end-tag",
+ {"startName": "a", "endName": "a"})
+ self.endTagFormatting(impliedTagToken("a"))
+ if afeAElement in self.tree.openElements:
+ self.tree.openElements.remove(afeAElement)
+ if afeAElement in self.tree.activeFormattingElements:
+ self.tree.activeFormattingElements.remove(afeAElement)
+ self.tree.reconstructActiveFormattingElements()
+ self.addFormattingElement(token)
+
+ def startTagFormatting(self, token):
+ self.tree.reconstructActiveFormattingElements()
+ self.addFormattingElement(token)
+
+ def startTagNobr(self, token):
+ self.tree.reconstructActiveFormattingElements()
+ if self.tree.elementInScope("nobr"):
+ self.parser.parseError("unexpected-start-tag-implies-end-tag",
+ {"startName": "nobr", "endName": "nobr"})
+ self.processEndTag(impliedTagToken("nobr"))
+ # XXX Need tests that trigger the following
+ self.tree.reconstructActiveFormattingElements()
+ self.addFormattingElement(token)
+
+ def startTagButton(self, token):
+ if self.tree.elementInScope("button"):
+ self.parser.parseError("unexpected-start-tag-implies-end-tag",
+ {"startName": "button", "endName": "button"})
+ self.processEndTag(impliedTagToken("button"))
+ return token
+ else:
+ self.tree.reconstructActiveFormattingElements()
+ self.tree.insertElement(token)
+ self.parser.framesetOK = False
+
+ def startTagAppletMarqueeObject(self, token):
+ self.tree.reconstructActiveFormattingElements()
+ self.tree.insertElement(token)
+ self.tree.activeFormattingElements.append(Marker)
+ self.parser.framesetOK = False
+
+ def startTagXmp(self, token):
+ if self.tree.elementInScope("p", variant="button"):
+ self.endTagP(impliedTagToken("p"))
+ self.tree.reconstructActiveFormattingElements()
+ self.parser.framesetOK = False
+ self.parser.parseRCDataRawtext(token, "RAWTEXT")
+
+ def startTagTable(self, token):
+ if self.parser.compatMode != "quirks":
+ if self.tree.elementInScope("p", variant="button"):
+ self.processEndTag(impliedTagToken("p"))
+ self.tree.insertElement(token)
+ self.parser.framesetOK = False
+ self.parser.phase = self.parser.phases["inTable"]
+
+ def startTagVoidFormatting(self, token):
+ self.tree.reconstructActiveFormattingElements()
+ self.tree.insertElement(token)
+ self.tree.openElements.pop()
+ token["selfClosingAcknowledged"] = True
+ self.parser.framesetOK = False
+
+ def startTagInput(self, token):
+ framesetOK = self.parser.framesetOK
+ self.startTagVoidFormatting(token)
+ if ("type" in token["data"] and
+ token["data"]["type"].translate(asciiUpper2Lower) == "hidden"):
+ # input type=hidden doesn't change framesetOK
+ self.parser.framesetOK = framesetOK
+
+ def startTagParamSource(self, token):
+ self.tree.insertElement(token)
+ self.tree.openElements.pop()
+ token["selfClosingAcknowledged"] = True
+
+ def startTagHr(self, token):
+ if self.tree.elementInScope("p", variant="button"):
+ self.endTagP(impliedTagToken("p"))
+ self.tree.insertElement(token)
+ self.tree.openElements.pop()
+ token["selfClosingAcknowledged"] = True
+ self.parser.framesetOK = False
+
+ def startTagImage(self, token):
+ # No really...
+ self.parser.parseError("unexpected-start-tag-treated-as",
+ {"originalName": "image", "newName": "img"})
+ self.processStartTag(impliedTagToken("img", "StartTag",
+ attributes=token["data"],
+ selfClosing=token["selfClosing"]))
+
+ def startTagIsIndex(self, token):
+ self.parser.parseError("deprecated-tag", {"name": "isindex"})
+ if self.tree.formPointer:
+ return
+ form_attrs = {}
+ if "action" in token["data"]:
+ form_attrs["action"] = token["data"]["action"]
+ self.processStartTag(impliedTagToken("form", "StartTag",
+ attributes=form_attrs))
+ self.processStartTag(impliedTagToken("hr", "StartTag"))
+ self.processStartTag(impliedTagToken("label", "StartTag"))
+ # XXX Localization ...
+ if "prompt" in token["data"]:
+ prompt = token["data"]["prompt"]
+ else:
+ prompt = "This is a searchable index. Enter search keywords: "
+ self.processCharacters(
+ {"type": tokenTypes["Characters"], "data": prompt})
+ attributes = token["data"].copy()
+ if "action" in attributes:
+ del attributes["action"]
+ if "prompt" in attributes:
+ del attributes["prompt"]
+ attributes["name"] = "isindex"
+ self.processStartTag(impliedTagToken("input", "StartTag",
+ attributes=attributes,
+ selfClosing=token["selfClosing"]))
+ self.processEndTag(impliedTagToken("label"))
+ self.processStartTag(impliedTagToken("hr", "StartTag"))
+ self.processEndTag(impliedTagToken("form"))
+
+ def startTagTextarea(self, token):
+ self.tree.insertElement(token)
+ self.parser.tokenizer.state = self.parser.tokenizer.rcdataState
+ self.processSpaceCharacters = self.processSpaceCharactersDropNewline
+ self.parser.framesetOK = False
+
+ def startTagIFrame(self, token):
+ self.parser.framesetOK = False
+ self.startTagRawtext(token)
+
+ def startTagRawtext(self, token):
+ """iframe, noembed noframes, noscript(if scripting enabled)"""
+ self.parser.parseRCDataRawtext(token, "RAWTEXT")
+
+ def startTagOpt(self, token):
+ if self.tree.openElements[-1].name == "option":
+ self.parser.phase.processEndTag(impliedTagToken("option"))
+ self.tree.reconstructActiveFormattingElements()
+ self.parser.tree.insertElement(token)
+
+ def startTagSelect(self, token):
+ self.tree.reconstructActiveFormattingElements()
+ self.tree.insertElement(token)
+ self.parser.framesetOK = False
+ if self.parser.phase in (self.parser.phases["inTable"],
+ self.parser.phases["inCaption"],
+ self.parser.phases["inColumnGroup"],
+ self.parser.phases["inTableBody"],
+ self.parser.phases["inRow"],
+ self.parser.phases["inCell"]):
+ self.parser.phase = self.parser.phases["inSelectInTable"]
+ else:
+ self.parser.phase = self.parser.phases["inSelect"]
+
+ def startTagRpRt(self, token):
+ if self.tree.elementInScope("ruby"):
+ self.tree.generateImpliedEndTags()
+ if self.tree.openElements[-1].name != "ruby":
+ self.parser.parseError()
+ self.tree.insertElement(token)
+
+ def startTagMath(self, token):
+ self.tree.reconstructActiveFormattingElements()
+ self.parser.adjustMathMLAttributes(token)
+ self.parser.adjustForeignAttributes(token)
+ token["namespace"] = namespaces["mathml"]
+ self.tree.insertElement(token)
+ # Need to get the parse error right for the case where the token
+ # has a namespace not equal to the xmlns attribute
+ if token["selfClosing"]:
+ self.tree.openElements.pop()
+ token["selfClosingAcknowledged"] = True
+
+ def startTagSvg(self, token):
+ self.tree.reconstructActiveFormattingElements()
+ self.parser.adjustSVGAttributes(token)
+ self.parser.adjustForeignAttributes(token)
+ token["namespace"] = namespaces["svg"]
+ self.tree.insertElement(token)
+ # Need to get the parse error right for the case where the token
+ # has a namespace not equal to the xmlns attribute
+ if token["selfClosing"]:
+ self.tree.openElements.pop()
+ token["selfClosingAcknowledged"] = True
+
+ def startTagMisplaced(self, token):
+ """ Elements that should be children of other elements that have a
+ different insertion mode; here they are ignored
+ "caption", "col", "colgroup", "frame", "frameset", "head",
+ "option", "optgroup", "tbody", "td", "tfoot", "th", "thead",
+ "tr", "noscript"
+ """
+ self.parser.parseError("unexpected-start-tag-ignored", {"name": token["name"]})
+
+ def startTagOther(self, token):
+ self.tree.reconstructActiveFormattingElements()
+ self.tree.insertElement(token)
+
+ def endTagP(self, token):
+ if not self.tree.elementInScope("p", variant="button"):
+ self.startTagCloseP(impliedTagToken("p", "StartTag"))
+ self.parser.parseError("unexpected-end-tag", {"name": "p"})
+ self.endTagP(impliedTagToken("p", "EndTag"))
+ else:
+ self.tree.generateImpliedEndTags("p")
+ if self.tree.openElements[-1].name != "p":
+ self.parser.parseError("unexpected-end-tag", {"name": "p"})
+ node = self.tree.openElements.pop()
+ while node.name != "p":
+ node = self.tree.openElements.pop()
+
+ def endTagBody(self, token):
+ if not self.tree.elementInScope("body"):
+ self.parser.parseError()
+ return
+ elif self.tree.openElements[-1].name != "body":
+ for node in self.tree.openElements[2:]:
+ if node.name not in frozenset(("dd", "dt", "li", "optgroup",
+ "option", "p", "rp", "rt",
+ "tbody", "td", "tfoot",
+ "th", "thead", "tr", "body",
+ "html")):
+ # Not sure this is the correct name for the parse error
+ self.parser.parseError(
+ "expected-one-end-tag-but-got-another",
+ {"expectedName": "body", "gotName": node.name})
+ break
+ self.parser.phase = self.parser.phases["afterBody"]
+
+ def endTagHtml(self, token):
+ # We repeat the test for the body end tag token being ignored here
+ if self.tree.elementInScope("body"):
+ self.endTagBody(impliedTagToken("body"))
+ return token
+
+ def endTagBlock(self, token):
+ # Put us back in the right whitespace handling mode
+ if token["name"] == "pre":
+ self.processSpaceCharacters = self.processSpaceCharactersNonPre
+ inScope = self.tree.elementInScope(token["name"])
+ if inScope:
+ self.tree.generateImpliedEndTags()
+ if self.tree.openElements[-1].name != token["name"]:
+ self.parser.parseError("end-tag-too-early", {"name": token["name"]})
+ if inScope:
+ node = self.tree.openElements.pop()
+ while node.name != token["name"]:
+ node = self.tree.openElements.pop()
+
+ def endTagForm(self, token):
+ node = self.tree.formPointer
+ self.tree.formPointer = None
+ if node is None or not self.tree.elementInScope(node):
+ self.parser.parseError("unexpected-end-tag",
+ {"name": "form"})
+ else:
+ self.tree.generateImpliedEndTags()
+ if self.tree.openElements[-1] != node:
+ self.parser.parseError("end-tag-too-early-ignored",
+ {"name": "form"})
+ self.tree.openElements.remove(node)
+
+ def endTagListItem(self, token):
+ if token["name"] == "li":
+ variant = "list"
+ else:
+ variant = None
+ if not self.tree.elementInScope(token["name"], variant=variant):
+ self.parser.parseError("unexpected-end-tag", {"name": token["name"]})
+ else:
+ self.tree.generateImpliedEndTags(exclude=token["name"])
+ if self.tree.openElements[-1].name != token["name"]:
+ self.parser.parseError(
+ "end-tag-too-early",
+ {"name": token["name"]})
+ node = self.tree.openElements.pop()
+ while node.name != token["name"]:
+ node = self.tree.openElements.pop()
+
+ def endTagHeading(self, token):
+ for item in headingElements:
+ if self.tree.elementInScope(item):
+ self.tree.generateImpliedEndTags()
+ break
+ if self.tree.openElements[-1].name != token["name"]:
+ self.parser.parseError("end-tag-too-early", {"name": token["name"]})
+
+ for item in headingElements:
+ if self.tree.elementInScope(item):
+ item = self.tree.openElements.pop()
+ while item.name not in headingElements:
+ item = self.tree.openElements.pop()
+ break
+
+ def endTagFormatting(self, token):
+ """The much-feared adoption agency algorithm"""
+ # http://svn.whatwg.org/webapps/complete.html#adoptionAgency revision 7867
+ # XXX Better parseError messages appreciated.
+
+ # Step 1
+ outerLoopCounter = 0
+
+ # Step 2
+ while outerLoopCounter < 8:
+
+ # Step 3
+ outerLoopCounter += 1
+
+ # Step 4:
+
+ # Let the formatting element be the last element in
+ # the list of active formatting elements that:
+ # - is between the end of the list and the last scope
+ # marker in the list, if any, or the start of the list
+ # otherwise, and
+ # - has the same tag name as the token.
+ formattingElement = self.tree.elementInActiveFormattingElements(
+ token["name"])
+ if (not formattingElement or
+ (formattingElement in self.tree.openElements and
+ not self.tree.elementInScope(formattingElement.name))):
+ # If there is no such node, then abort these steps
+ # and instead act as described in the "any other
+ # end tag" entry below.
+ self.endTagOther(token)
+ return
+
+ # Otherwise, if there is such a node, but that node is
+ # not in the stack of open elements, then this is a
+ # parse error; remove the element from the list, and
+ # abort these steps.
+ elif formattingElement not in self.tree.openElements:
+ self.parser.parseError("adoption-agency-1.2", {"name": token["name"]})
+ self.tree.activeFormattingElements.remove(formattingElement)
+ return
+
+ # Otherwise, if there is such a node, and that node is
+ # also in the stack of open elements, but the element
+ # is not in scope, then this is a parse error; ignore
+ # the token, and abort these steps.
+ elif not self.tree.elementInScope(formattingElement.name):
+ self.parser.parseError("adoption-agency-4.4", {"name": token["name"]})
+ return
+
+ # Otherwise, there is a formatting element and that
+ # element is in the stack and is in scope. If the
+ # element is not the current node, this is a parse
+ # error. In any case, proceed with the algorithm as
+ # written in the following steps.
+ else:
+ if formattingElement != self.tree.openElements[-1]:
+ self.parser.parseError("adoption-agency-1.3", {"name": token["name"]})
+
+ # Step 5:
+
+ # Let the furthest block be the topmost node in the
+ # stack of open elements that is lower in the stack
+ # than the formatting element, and is an element in
+ # the special category. There might not be one.
+ afeIndex = self.tree.openElements.index(formattingElement)
+ furthestBlock = None
+ for element in self.tree.openElements[afeIndex:]:
+ if element.nameTuple in specialElements:
+ furthestBlock = element
+ break
+
+ # Step 6:
+
+ # If there is no furthest block, then the UA must
+ # first pop all the nodes from the bottom of the stack
+ # of open elements, from the current node up to and
+ # including the formatting element, then remove the
+ # formatting element from the list of active
+ # formatting elements, and finally abort these steps.
+ if furthestBlock is None:
+ element = self.tree.openElements.pop()
+ while element != formattingElement:
+ element = self.tree.openElements.pop()
+ self.tree.activeFormattingElements.remove(element)
+ return
+
+ # Step 7
+ commonAncestor = self.tree.openElements[afeIndex - 1]
+
+ # Step 8:
+ # The bookmark is supposed to help us identify where to reinsert
+ # nodes in step 15. We have to ensure that we reinsert nodes after
+ # the node before the active formatting element. Note the bookmark
+ # can move in step 9.7
+ bookmark = self.tree.activeFormattingElements.index(formattingElement)
+
+ # Step 9
+ lastNode = node = furthestBlock
+ innerLoopCounter = 0
+
+ index = self.tree.openElements.index(node)
+ while innerLoopCounter < 3:
+ innerLoopCounter += 1
+ # Node is element before node in open elements
+ index -= 1
+ node = self.tree.openElements[index]
+ if node not in self.tree.activeFormattingElements:
+ self.tree.openElements.remove(node)
+ continue
+ # Step 9.6
+ if node == formattingElement:
+ break
+ # Step 9.7
+ if lastNode == furthestBlock:
+ bookmark = self.tree.activeFormattingElements.index(node) + 1
+ # Step 9.8
+ clone = node.cloneNode()
+ # Replace node with clone
+ self.tree.activeFormattingElements[
+ self.tree.activeFormattingElements.index(node)] = clone
+ self.tree.openElements[
+ self.tree.openElements.index(node)] = clone
+ node = clone
+ # Step 9.9
+ # Remove lastNode from its parents, if any
+ if lastNode.parent:
+ lastNode.parent.removeChild(lastNode)
+ node.appendChild(lastNode)
+ # Step 9.10
+ lastNode = node
+
+ # Step 10
+ # Foster parent lastNode if commonAncestor is a
+ # table, tbody, tfoot, thead, or tr we need to foster
+ # parent the lastNode
+ if lastNode.parent:
+ lastNode.parent.removeChild(lastNode)
+
+ if commonAncestor.name in frozenset(("table", "tbody", "tfoot", "thead", "tr")):
+ parent, insertBefore = self.tree.getTableMisnestedNodePosition()
+ parent.insertBefore(lastNode, insertBefore)
+ else:
+ commonAncestor.appendChild(lastNode)
+
+ # Step 11
+ clone = formattingElement.cloneNode()
+
+ # Step 12
+ furthestBlock.reparentChildren(clone)
+
+ # Step 13
+ furthestBlock.appendChild(clone)
+
+ # Step 14
+ self.tree.activeFormattingElements.remove(formattingElement)
+ self.tree.activeFormattingElements.insert(bookmark, clone)
+
+ # Step 15
+ self.tree.openElements.remove(formattingElement)
+ self.tree.openElements.insert(
+ self.tree.openElements.index(furthestBlock) + 1, clone)
+
+ def endTagAppletMarqueeObject(self, token):
+ if self.tree.elementInScope(token["name"]):
+ self.tree.generateImpliedEndTags()
+ if self.tree.openElements[-1].name != token["name"]:
+ self.parser.parseError("end-tag-too-early", {"name": token["name"]})
+
+ if self.tree.elementInScope(token["name"]):
+ element = self.tree.openElements.pop()
+ while element.name != token["name"]:
+ element = self.tree.openElements.pop()
+ self.tree.clearActiveFormattingElements()
+
+ def endTagBr(self, token):
+ self.parser.parseError("unexpected-end-tag-treated-as",
+ {"originalName": "br", "newName": "br element"})
+ self.tree.reconstructActiveFormattingElements()
+ self.tree.insertElement(impliedTagToken("br", "StartTag"))
+ self.tree.openElements.pop()
+
+ def endTagOther(self, token):
+ for node in self.tree.openElements[::-1]:
+ if node.name == token["name"]:
+ self.tree.generateImpliedEndTags(exclude=token["name"])
+ if self.tree.openElements[-1].name != token["name"]:
+ self.parser.parseError("unexpected-end-tag", {"name": token["name"]})
+ while self.tree.openElements.pop() != node:
+ pass
+ break
+ else:
+ if node.nameTuple in specialElements:
+ self.parser.parseError("unexpected-end-tag", {"name": token["name"]})
+ break
+
+ class TextPhase(Phase):
+ def __init__(self, parser, tree):
+ Phase.__init__(self, parser, tree)
+ self.startTagHandler = utils.MethodDispatcher([])
+ self.startTagHandler.default = self.startTagOther
+ self.endTagHandler = utils.MethodDispatcher([
+ ("script", self.endTagScript)])
+ self.endTagHandler.default = self.endTagOther
+
+ def processCharacters(self, token):
+ self.tree.insertText(token["data"])
+
+ def processEOF(self):
+ self.parser.parseError("expected-named-closing-tag-but-got-eof",
+ {"name": self.tree.openElements[-1].name})
+ self.tree.openElements.pop()
+ self.parser.phase = self.parser.originalPhase
+ return True
+
+ def startTagOther(self, token):
+ assert False, "Tried to process start tag %s in RCDATA/RAWTEXT mode" % token['name']
+
+ def endTagScript(self, token):
+ node = self.tree.openElements.pop()
+ assert node.name == "script"
+ self.parser.phase = self.parser.originalPhase
+ # The rest of this method is all stuff that only happens if
+ # document.write works
+
+ def endTagOther(self, token):
+ self.tree.openElements.pop()
+ self.parser.phase = self.parser.originalPhase
+
+ class InTablePhase(Phase):
+ # http://www.whatwg.org/specs/web-apps/current-work/#in-table
+ def __init__(self, parser, tree):
+ Phase.__init__(self, parser, tree)
+ self.startTagHandler = utils.MethodDispatcher([
+ ("html", self.startTagHtml),
+ ("caption", self.startTagCaption),
+ ("colgroup", self.startTagColgroup),
+ ("col", self.startTagCol),
+ (("tbody", "tfoot", "thead"), self.startTagRowGroup),
+ (("td", "th", "tr"), self.startTagImplyTbody),
+ ("table", self.startTagTable),
+ (("style", "script"), self.startTagStyleScript),
+ ("input", self.startTagInput),
+ ("form", self.startTagForm)
+ ])
+ self.startTagHandler.default = self.startTagOther
+
+ self.endTagHandler = utils.MethodDispatcher([
+ ("table", self.endTagTable),
+ (("body", "caption", "col", "colgroup", "html", "tbody", "td",
+ "tfoot", "th", "thead", "tr"), self.endTagIgnore)
+ ])
+ self.endTagHandler.default = self.endTagOther
+
+ # helper methods
+ def clearStackToTableContext(self):
+ # "clear the stack back to a table context"
+ while self.tree.openElements[-1].name not in ("table", "html"):
+ # self.parser.parseError("unexpected-implied-end-tag-in-table",
+ # {"name": self.tree.openElements[-1].name})
+ self.tree.openElements.pop()
+ # When the current node is <html> it's an innerHTML case
+
+ # processing methods
+ def processEOF(self):
+ if self.tree.openElements[-1].name != "html":
+ self.parser.parseError("eof-in-table")
+ else:
+ assert self.parser.innerHTML
+ # Stop parsing
+
+ def processSpaceCharacters(self, token):
+ originalPhase = self.parser.phase
+ self.parser.phase = self.parser.phases["inTableText"]
+ self.parser.phase.originalPhase = originalPhase
+ self.parser.phase.processSpaceCharacters(token)
+
+ def processCharacters(self, token):
+ originalPhase = self.parser.phase
+ self.parser.phase = self.parser.phases["inTableText"]
+ self.parser.phase.originalPhase = originalPhase
+ self.parser.phase.processCharacters(token)
+
+ def insertText(self, token):
+ # If we get here there must be at least one non-whitespace character
+ # Do the table magic!
+ self.tree.insertFromTable = True
+ self.parser.phases["inBody"].processCharacters(token)
+ self.tree.insertFromTable = False
+
+ def startTagCaption(self, token):
+ self.clearStackToTableContext()
+ self.tree.activeFormattingElements.append(Marker)
+ self.tree.insertElement(token)
+ self.parser.phase = self.parser.phases["inCaption"]
+
+ def startTagColgroup(self, token):
+ self.clearStackToTableContext()
+ self.tree.insertElement(token)
+ self.parser.phase = self.parser.phases["inColumnGroup"]
+
+ def startTagCol(self, token):
+ self.startTagColgroup(impliedTagToken("colgroup", "StartTag"))
+ return token
+
+ def startTagRowGroup(self, token):
+ self.clearStackToTableContext()
+ self.tree.insertElement(token)
+ self.parser.phase = self.parser.phases["inTableBody"]
+
+ def startTagImplyTbody(self, token):
+ self.startTagRowGroup(impliedTagToken("tbody", "StartTag"))
+ return token
+
+ def startTagTable(self, token):
+ self.parser.parseError("unexpected-start-tag-implies-end-tag",
+ {"startName": "table", "endName": "table"})
+ self.parser.phase.processEndTag(impliedTagToken("table"))
+ if not self.parser.innerHTML:
+ return token
+
+ def startTagStyleScript(self, token):
+ return self.parser.phases["inHead"].processStartTag(token)
+
+ def startTagInput(self, token):
+ if ("type" in token["data"] and
+ token["data"]["type"].translate(asciiUpper2Lower) == "hidden"):
+ self.parser.parseError("unexpected-hidden-input-in-table")
+ self.tree.insertElement(token)
+ # XXX associate with form
+ self.tree.openElements.pop()
+ else:
+ self.startTagOther(token)
+
+ def startTagForm(self, token):
+ self.parser.parseError("unexpected-form-in-table")
+ if self.tree.formPointer is None:
+ self.tree.insertElement(token)
+ self.tree.formPointer = self.tree.openElements[-1]
+ self.tree.openElements.pop()
+
+ def startTagOther(self, token):
+ self.parser.parseError("unexpected-start-tag-implies-table-voodoo", {"name": token["name"]})
+ # Do the table magic!
+ self.tree.insertFromTable = True
+ self.parser.phases["inBody"].processStartTag(token)
+ self.tree.insertFromTable = False
+
+ def endTagTable(self, token):
+ if self.tree.elementInScope("table", variant="table"):
+ self.tree.generateImpliedEndTags()
+ if self.tree.openElements[-1].name != "table":
+ self.parser.parseError("end-tag-too-early-named",
+ {"gotName": "table",
+ "expectedName": self.tree.openElements[-1].name})
+ while self.tree.openElements[-1].name != "table":
+ self.tree.openElements.pop()
+ self.tree.openElements.pop()
+ self.parser.resetInsertionMode()
+ else:
+ # innerHTML case
+ assert self.parser.innerHTML
+ self.parser.parseError()
+
+ def endTagIgnore(self, token):
+ self.parser.parseError("unexpected-end-tag", {"name": token["name"]})
+
+ def endTagOther(self, token):
+ self.parser.parseError("unexpected-end-tag-implies-table-voodoo", {"name": token["name"]})
+ # Do the table magic!
+ self.tree.insertFromTable = True
+ self.parser.phases["inBody"].processEndTag(token)
+ self.tree.insertFromTable = False
+
+ class InTableTextPhase(Phase):
+ def __init__(self, parser, tree):
+ Phase.__init__(self, parser, tree)
+ self.originalPhase = None
+ self.characterTokens = []
+
+ def flushCharacters(self):
+ data = "".join([item["data"] for item in self.characterTokens])
+ if any([item not in spaceCharacters for item in data]):
+ token = {"type": tokenTypes["Characters"], "data": data}
+ self.parser.phases["inTable"].insertText(token)
+ elif data:
+ self.tree.insertText(data)
+ self.characterTokens = []
+
+ def processComment(self, token):
+ self.flushCharacters()
+ self.parser.phase = self.originalPhase
+ return token
+
+ def processEOF(self):
+ self.flushCharacters()
+ self.parser.phase = self.originalPhase
+ return True
+
+ def processCharacters(self, token):
+ if token["data"] == "\u0000":
+ return
+ self.characterTokens.append(token)
+
+ def processSpaceCharacters(self, token):
+ # pretty sure we should never reach here
+ self.characterTokens.append(token)
+ # assert False
+
+ def processStartTag(self, token):
+ self.flushCharacters()
+ self.parser.phase = self.originalPhase
+ return token
+
+ def processEndTag(self, token):
+ self.flushCharacters()
+ self.parser.phase = self.originalPhase
+ return token
+
+ class InCaptionPhase(Phase):
+ # http://www.whatwg.org/specs/web-apps/current-work/#in-caption
+ def __init__(self, parser, tree):
+ Phase.__init__(self, parser, tree)
+
+ self.startTagHandler = utils.MethodDispatcher([
+ ("html", self.startTagHtml),
+ (("caption", "col", "colgroup", "tbody", "td", "tfoot", "th",
+ "thead", "tr"), self.startTagTableElement)
+ ])
+ self.startTagHandler.default = self.startTagOther
+
+ self.endTagHandler = utils.MethodDispatcher([
+ ("caption", self.endTagCaption),
+ ("table", self.endTagTable),
+ (("body", "col", "colgroup", "html", "tbody", "td", "tfoot", "th",
+ "thead", "tr"), self.endTagIgnore)
+ ])
+ self.endTagHandler.default = self.endTagOther
+
+ def ignoreEndTagCaption(self):
+ return not self.tree.elementInScope("caption", variant="table")
+
+ def processEOF(self):
+ self.parser.phases["inBody"].processEOF()
+
+ def processCharacters(self, token):
+ return self.parser.phases["inBody"].processCharacters(token)
+
+ def startTagTableElement(self, token):
+ self.parser.parseError()
+ # XXX Have to duplicate logic here to find out if the tag is ignored
+ ignoreEndTag = self.ignoreEndTagCaption()
+ self.parser.phase.processEndTag(impliedTagToken("caption"))
+ if not ignoreEndTag:
+ return token
+
+ def startTagOther(self, token):
+ return self.parser.phases["inBody"].processStartTag(token)
+
+ def endTagCaption(self, token):
+ if not self.ignoreEndTagCaption():
+ # AT this code is quite similar to endTagTable in "InTable"
+ self.tree.generateImpliedEndTags()
+ if self.tree.openElements[-1].name != "caption":
+ self.parser.parseError("expected-one-end-tag-but-got-another",
+ {"gotName": "caption",
+ "expectedName": self.tree.openElements[-1].name})
+ while self.tree.openElements[-1].name != "caption":
+ self.tree.openElements.pop()
+ self.tree.openElements.pop()
+ self.tree.clearActiveFormattingElements()
+ self.parser.phase = self.parser.phases["inTable"]
+ else:
+ # innerHTML case
+ assert self.parser.innerHTML
+ self.parser.parseError()
+
+ def endTagTable(self, token):
+ self.parser.parseError()
+ ignoreEndTag = self.ignoreEndTagCaption()
+ self.parser.phase.processEndTag(impliedTagToken("caption"))
+ if not ignoreEndTag:
+ return token
+
+ def endTagIgnore(self, token):
+ self.parser.parseError("unexpected-end-tag", {"name": token["name"]})
+
+ def endTagOther(self, token):
+ return self.parser.phases["inBody"].processEndTag(token)
+
+ class InColumnGroupPhase(Phase):
+ # http://www.whatwg.org/specs/web-apps/current-work/#in-column
+
+ def __init__(self, parser, tree):
+ Phase.__init__(self, parser, tree)
+
+ self.startTagHandler = utils.MethodDispatcher([
+ ("html", self.startTagHtml),
+ ("col", self.startTagCol)
+ ])
+ self.startTagHandler.default = self.startTagOther
+
+ self.endTagHandler = utils.MethodDispatcher([
+ ("colgroup", self.endTagColgroup),
+ ("col", self.endTagCol)
+ ])
+ self.endTagHandler.default = self.endTagOther
+
+ def ignoreEndTagColgroup(self):
+ return self.tree.openElements[-1].name == "html"
+
+ def processEOF(self):
+ if self.tree.openElements[-1].name == "html":
+ assert self.parser.innerHTML
+ return
+ else:
+ ignoreEndTag = self.ignoreEndTagColgroup()
+ self.endTagColgroup(impliedTagToken("colgroup"))
+ if not ignoreEndTag:
+ return True
+
+ def processCharacters(self, token):
+ ignoreEndTag = self.ignoreEndTagColgroup()
+ self.endTagColgroup(impliedTagToken("colgroup"))
+ if not ignoreEndTag:
+ return token
+
+ def startTagCol(self, token):
+ self.tree.insertElement(token)
+ self.tree.openElements.pop()
+
+ def startTagOther(self, token):
+ ignoreEndTag = self.ignoreEndTagColgroup()
+ self.endTagColgroup(impliedTagToken("colgroup"))
+ if not ignoreEndTag:
+ return token
+
+ def endTagColgroup(self, token):
+ if self.ignoreEndTagColgroup():
+ # innerHTML case
+ assert self.parser.innerHTML
+ self.parser.parseError()
+ else:
+ self.tree.openElements.pop()
+ self.parser.phase = self.parser.phases["inTable"]
+
+ def endTagCol(self, token):
+ self.parser.parseError("no-end-tag", {"name": "col"})
+
+ def endTagOther(self, token):
+ ignoreEndTag = self.ignoreEndTagColgroup()
+ self.endTagColgroup(impliedTagToken("colgroup"))
+ if not ignoreEndTag:
+ return token
+
+ class InTableBodyPhase(Phase):
+ # http://www.whatwg.org/specs/web-apps/current-work/#in-table0
+ def __init__(self, parser, tree):
+ Phase.__init__(self, parser, tree)
+ self.startTagHandler = utils.MethodDispatcher([
+ ("html", self.startTagHtml),
+ ("tr", self.startTagTr),
+ (("td", "th"), self.startTagTableCell),
+ (("caption", "col", "colgroup", "tbody", "tfoot", "thead"),
+ self.startTagTableOther)
+ ])
+ self.startTagHandler.default = self.startTagOther
+
+ self.endTagHandler = utils.MethodDispatcher([
+ (("tbody", "tfoot", "thead"), self.endTagTableRowGroup),
+ ("table", self.endTagTable),
+ (("body", "caption", "col", "colgroup", "html", "td", "th",
+ "tr"), self.endTagIgnore)
+ ])
+ self.endTagHandler.default = self.endTagOther
+
+ # helper methods
+ def clearStackToTableBodyContext(self):
+ while self.tree.openElements[-1].name not in ("tbody", "tfoot",
+ "thead", "html"):
+ # self.parser.parseError("unexpected-implied-end-tag-in-table",
+ # {"name": self.tree.openElements[-1].name})
+ self.tree.openElements.pop()
+ if self.tree.openElements[-1].name == "html":
+ assert self.parser.innerHTML
+
+ # the rest
+ def processEOF(self):
+ self.parser.phases["inTable"].processEOF()
+
+ def processSpaceCharacters(self, token):
+ return self.parser.phases["inTable"].processSpaceCharacters(token)
+
+ def processCharacters(self, token):
+ return self.parser.phases["inTable"].processCharacters(token)
+
+ def startTagTr(self, token):
+ self.clearStackToTableBodyContext()
+ self.tree.insertElement(token)
+ self.parser.phase = self.parser.phases["inRow"]
+
+ def startTagTableCell(self, token):
+ self.parser.parseError("unexpected-cell-in-table-body",
+ {"name": token["name"]})
+ self.startTagTr(impliedTagToken("tr", "StartTag"))
+ return token
+
+ def startTagTableOther(self, token):
+ # XXX AT Any ideas on how to share this with endTagTable?
+ if (self.tree.elementInScope("tbody", variant="table") or
+ self.tree.elementInScope("thead", variant="table") or
+ self.tree.elementInScope("tfoot", variant="table")):
+ self.clearStackToTableBodyContext()
+ self.endTagTableRowGroup(
+ impliedTagToken(self.tree.openElements[-1].name))
+ return token
+ else:
+ # innerHTML case
+ assert self.parser.innerHTML
+ self.parser.parseError()
+
+ def startTagOther(self, token):
+ return self.parser.phases["inTable"].processStartTag(token)
+
+ def endTagTableRowGroup(self, token):
+ if self.tree.elementInScope(token["name"], variant="table"):
+ self.clearStackToTableBodyContext()
+ self.tree.openElements.pop()
+ self.parser.phase = self.parser.phases["inTable"]
+ else:
+ self.parser.parseError("unexpected-end-tag-in-table-body",
+ {"name": token["name"]})
+
+ def endTagTable(self, token):
+ if (self.tree.elementInScope("tbody", variant="table") or
+ self.tree.elementInScope("thead", variant="table") or
+ self.tree.elementInScope("tfoot", variant="table")):
+ self.clearStackToTableBodyContext()
+ self.endTagTableRowGroup(
+ impliedTagToken(self.tree.openElements[-1].name))
+ return token
+ else:
+ # innerHTML case
+ assert self.parser.innerHTML
+ self.parser.parseError()
+
+ def endTagIgnore(self, token):
+ self.parser.parseError("unexpected-end-tag-in-table-body",
+ {"name": token["name"]})
+
+ def endTagOther(self, token):
+ return self.parser.phases["inTable"].processEndTag(token)
+
+ class InRowPhase(Phase):
+ # http://www.whatwg.org/specs/web-apps/current-work/#in-row
+ def __init__(self, parser, tree):
+ Phase.__init__(self, parser, tree)
+ self.startTagHandler = utils.MethodDispatcher([
+ ("html", self.startTagHtml),
+ (("td", "th"), self.startTagTableCell),
+ (("caption", "col", "colgroup", "tbody", "tfoot", "thead",
+ "tr"), self.startTagTableOther)
+ ])
+ self.startTagHandler.default = self.startTagOther
+
+ self.endTagHandler = utils.MethodDispatcher([
+ ("tr", self.endTagTr),
+ ("table", self.endTagTable),
+ (("tbody", "tfoot", "thead"), self.endTagTableRowGroup),
+ (("body", "caption", "col", "colgroup", "html", "td", "th"),
+ self.endTagIgnore)
+ ])
+ self.endTagHandler.default = self.endTagOther
+
+ # helper methods (XXX unify this with other table helper methods)
+ def clearStackToTableRowContext(self):
+ while self.tree.openElements[-1].name not in ("tr", "html"):
+ self.parser.parseError("unexpected-implied-end-tag-in-table-row",
+ {"name": self.tree.openElements[-1].name})
+ self.tree.openElements.pop()
+
+ def ignoreEndTagTr(self):
+ return not self.tree.elementInScope("tr", variant="table")
+
+ # the rest
+ def processEOF(self):
+ self.parser.phases["inTable"].processEOF()
+
+ def processSpaceCharacters(self, token):
+ return self.parser.phases["inTable"].processSpaceCharacters(token)
+
+ def processCharacters(self, token):
+ return self.parser.phases["inTable"].processCharacters(token)
+
+ def startTagTableCell(self, token):
+ self.clearStackToTableRowContext()
+ self.tree.insertElement(token)
+ self.parser.phase = self.parser.phases["inCell"]
+ self.tree.activeFormattingElements.append(Marker)
+
+ def startTagTableOther(self, token):
+ ignoreEndTag = self.ignoreEndTagTr()
+ self.endTagTr(impliedTagToken("tr"))
+ # XXX how are we sure it's always ignored in the innerHTML case?
+ if not ignoreEndTag:
+ return token
+
+ def startTagOther(self, token):
+ return self.parser.phases["inTable"].processStartTag(token)
+
+ def endTagTr(self, token):
+ if not self.ignoreEndTagTr():
+ self.clearStackToTableRowContext()
+ self.tree.openElements.pop()
+ self.parser.phase = self.parser.phases["inTableBody"]
+ else:
+ # innerHTML case
+ assert self.parser.innerHTML
+ self.parser.parseError()
+
+ def endTagTable(self, token):
+ ignoreEndTag = self.ignoreEndTagTr()
+ self.endTagTr(impliedTagToken("tr"))
+ # Reprocess the current tag if the tr end tag was not ignored
+ # XXX how are we sure it's always ignored in the innerHTML case?
+ if not ignoreEndTag:
+ return token
+
+ def endTagTableRowGroup(self, token):
+ if self.tree.elementInScope(token["name"], variant="table"):
+ self.endTagTr(impliedTagToken("tr"))
+ return token
+ else:
+ self.parser.parseError()
+
+ def endTagIgnore(self, token):
+ self.parser.parseError("unexpected-end-tag-in-table-row",
+ {"name": token["name"]})
+
+ def endTagOther(self, token):
+ return self.parser.phases["inTable"].processEndTag(token)
+
+ class InCellPhase(Phase):
+ # http://www.whatwg.org/specs/web-apps/current-work/#in-cell
+ def __init__(self, parser, tree):
+ Phase.__init__(self, parser, tree)
+ self.startTagHandler = utils.MethodDispatcher([
+ ("html", self.startTagHtml),
+ (("caption", "col", "colgroup", "tbody", "td", "tfoot", "th",
+ "thead", "tr"), self.startTagTableOther)
+ ])
+ self.startTagHandler.default = self.startTagOther
+
+ self.endTagHandler = utils.MethodDispatcher([
+ (("td", "th"), self.endTagTableCell),
+ (("body", "caption", "col", "colgroup", "html"), self.endTagIgnore),
+ (("table", "tbody", "tfoot", "thead", "tr"), self.endTagImply)
+ ])
+ self.endTagHandler.default = self.endTagOther
+
+ # helper
+ def closeCell(self):
+ if self.tree.elementInScope("td", variant="table"):
+ self.endTagTableCell(impliedTagToken("td"))
+ elif self.tree.elementInScope("th", variant="table"):
+ self.endTagTableCell(impliedTagToken("th"))
+
+ # the rest
+ def processEOF(self):
+ self.parser.phases["inBody"].processEOF()
+
+ def processCharacters(self, token):
+ return self.parser.phases["inBody"].processCharacters(token)
+
+ def startTagTableOther(self, token):
+ if (self.tree.elementInScope("td", variant="table") or
+ self.tree.elementInScope("th", variant="table")):
+ self.closeCell()
+ return token
+ else:
+ # innerHTML case
+ assert self.parser.innerHTML
+ self.parser.parseError()
+
+ def startTagOther(self, token):
+ return self.parser.phases["inBody"].processStartTag(token)
+
+ def endTagTableCell(self, token):
+ if self.tree.elementInScope(token["name"], variant="table"):
+ self.tree.generateImpliedEndTags(token["name"])
+ if self.tree.openElements[-1].name != token["name"]:
+ self.parser.parseError("unexpected-cell-end-tag",
+ {"name": token["name"]})
+ while True:
+ node = self.tree.openElements.pop()
+ if node.name == token["name"]:
+ break
+ else:
+ self.tree.openElements.pop()
+ self.tree.clearActiveFormattingElements()
+ self.parser.phase = self.parser.phases["inRow"]
+ else:
+ self.parser.parseError("unexpected-end-tag", {"name": token["name"]})
+
+ def endTagIgnore(self, token):
+ self.parser.parseError("unexpected-end-tag", {"name": token["name"]})
+
+ def endTagImply(self, token):
+ if self.tree.elementInScope(token["name"], variant="table"):
+ self.closeCell()
+ return token
+ else:
+ # sometimes innerHTML case
+ self.parser.parseError()
+
+ def endTagOther(self, token):
+ return self.parser.phases["inBody"].processEndTag(token)
+
+ class InSelectPhase(Phase):
+ def __init__(self, parser, tree):
+ Phase.__init__(self, parser, tree)
+
+ self.startTagHandler = utils.MethodDispatcher([
+ ("html", self.startTagHtml),
+ ("option", self.startTagOption),
+ ("optgroup", self.startTagOptgroup),
+ ("select", self.startTagSelect),
+ (("input", "keygen", "textarea"), self.startTagInput),
+ ("script", self.startTagScript)
+ ])
+ self.startTagHandler.default = self.startTagOther
+
+ self.endTagHandler = utils.MethodDispatcher([
+ ("option", self.endTagOption),
+ ("optgroup", self.endTagOptgroup),
+ ("select", self.endTagSelect)
+ ])
+ self.endTagHandler.default = self.endTagOther
+
+ # http://www.whatwg.org/specs/web-apps/current-work/#in-select
+ def processEOF(self):
+ if self.tree.openElements[-1].name != "html":
+ self.parser.parseError("eof-in-select")
+ else:
+ assert self.parser.innerHTML
+
+ def processCharacters(self, token):
+ if token["data"] == "\u0000":
+ return
+ self.tree.insertText(token["data"])
+
+ def startTagOption(self, token):
+ # We need to imply </option> if <option> is the current node.
+ if self.tree.openElements[-1].name == "option":
+ self.tree.openElements.pop()
+ self.tree.insertElement(token)
+
+ def startTagOptgroup(self, token):
+ if self.tree.openElements[-1].name == "option":
+ self.tree.openElements.pop()
+ if self.tree.openElements[-1].name == "optgroup":
+ self.tree.openElements.pop()
+ self.tree.insertElement(token)
+
+ def startTagSelect(self, token):
+ self.parser.parseError("unexpected-select-in-select")
+ self.endTagSelect(impliedTagToken("select"))
+
+ def startTagInput(self, token):
+ self.parser.parseError("unexpected-input-in-select")
+ if self.tree.elementInScope("select", variant="select"):
+ self.endTagSelect(impliedTagToken("select"))
+ return token
+ else:
+ assert self.parser.innerHTML
+
+ def startTagScript(self, token):
+ return self.parser.phases["inHead"].processStartTag(token)
+
+ def startTagOther(self, token):
+ self.parser.parseError("unexpected-start-tag-in-select",
+ {"name": token["name"]})
+
+ def endTagOption(self, token):
+ if self.tree.openElements[-1].name == "option":
+ self.tree.openElements.pop()
+ else:
+ self.parser.parseError("unexpected-end-tag-in-select",
+ {"name": "option"})
+
+ def endTagOptgroup(self, token):
+ # </optgroup> implicitly closes <option>
+ if (self.tree.openElements[-1].name == "option" and
+ self.tree.openElements[-2].name == "optgroup"):
+ self.tree.openElements.pop()
+ # It also closes </optgroup>
+ if self.tree.openElements[-1].name == "optgroup":
+ self.tree.openElements.pop()
+ # But nothing else
+ else:
+ self.parser.parseError("unexpected-end-tag-in-select",
+ {"name": "optgroup"})
+
+ def endTagSelect(self, token):
+ if self.tree.elementInScope("select", variant="select"):
+ node = self.tree.openElements.pop()
+ while node.name != "select":
+ node = self.tree.openElements.pop()
+ self.parser.resetInsertionMode()
+ else:
+ # innerHTML case
+ assert self.parser.innerHTML
+ self.parser.parseError()
+
+ def endTagOther(self, token):
+ self.parser.parseError("unexpected-end-tag-in-select",
+ {"name": token["name"]})
+
+ class InSelectInTablePhase(Phase):
+ def __init__(self, parser, tree):
+ Phase.__init__(self, parser, tree)
+
+ self.startTagHandler = utils.MethodDispatcher([
+ (("caption", "table", "tbody", "tfoot", "thead", "tr", "td", "th"),
+ self.startTagTable)
+ ])
+ self.startTagHandler.default = self.startTagOther
+
+ self.endTagHandler = utils.MethodDispatcher([
+ (("caption", "table", "tbody", "tfoot", "thead", "tr", "td", "th"),
+ self.endTagTable)
+ ])
+ self.endTagHandler.default = self.endTagOther
+
+ def processEOF(self):
+ self.parser.phases["inSelect"].processEOF()
+
+ def processCharacters(self, token):
+ return self.parser.phases["inSelect"].processCharacters(token)
+
+ def startTagTable(self, token):
+ self.parser.parseError("unexpected-table-element-start-tag-in-select-in-table", {"name": token["name"]})
+ self.endTagOther(impliedTagToken("select"))
+ return token
+
+ def startTagOther(self, token):
+ return self.parser.phases["inSelect"].processStartTag(token)
+
+ def endTagTable(self, token):
+ self.parser.parseError("unexpected-table-element-end-tag-in-select-in-table", {"name": token["name"]})
+ if self.tree.elementInScope(token["name"], variant="table"):
+ self.endTagOther(impliedTagToken("select"))
+ return token
+
+ def endTagOther(self, token):
+ return self.parser.phases["inSelect"].processEndTag(token)
+
+ class InForeignContentPhase(Phase):
+ breakoutElements = frozenset(["b", "big", "blockquote", "body", "br",
+ "center", "code", "dd", "div", "dl", "dt",
+ "em", "embed", "h1", "h2", "h3",
+ "h4", "h5", "h6", "head", "hr", "i", "img",
+ "li", "listing", "menu", "meta", "nobr",
+ "ol", "p", "pre", "ruby", "s", "small",
+ "span", "strong", "strike", "sub", "sup",
+ "table", "tt", "u", "ul", "var"])
+
+ def __init__(self, parser, tree):
+ Phase.__init__(self, parser, tree)
+
+ def adjustSVGTagNames(self, token):
+ replacements = {"altglyph": "altGlyph",
+ "altglyphdef": "altGlyphDef",
+ "altglyphitem": "altGlyphItem",
+ "animatecolor": "animateColor",
+ "animatemotion": "animateMotion",
+ "animatetransform": "animateTransform",
+ "clippath": "clipPath",
+ "feblend": "feBlend",
+ "fecolormatrix": "feColorMatrix",
+ "fecomponenttransfer": "feComponentTransfer",
+ "fecomposite": "feComposite",
+ "feconvolvematrix": "feConvolveMatrix",
+ "fediffuselighting": "feDiffuseLighting",
+ "fedisplacementmap": "feDisplacementMap",
+ "fedistantlight": "feDistantLight",
+ "feflood": "feFlood",
+ "fefunca": "feFuncA",
+ "fefuncb": "feFuncB",
+ "fefuncg": "feFuncG",
+ "fefuncr": "feFuncR",
+ "fegaussianblur": "feGaussianBlur",
+ "feimage": "feImage",
+ "femerge": "feMerge",
+ "femergenode": "feMergeNode",
+ "femorphology": "feMorphology",
+ "feoffset": "feOffset",
+ "fepointlight": "fePointLight",
+ "fespecularlighting": "feSpecularLighting",
+ "fespotlight": "feSpotLight",
+ "fetile": "feTile",
+ "feturbulence": "feTurbulence",
+ "foreignobject": "foreignObject",
+ "glyphref": "glyphRef",
+ "lineargradient": "linearGradient",
+ "radialgradient": "radialGradient",
+ "textpath": "textPath"}
+
+ if token["name"] in replacements:
+ token["name"] = replacements[token["name"]]
+
+ def processCharacters(self, token):
+ if token["data"] == "\u0000":
+ token["data"] = "\uFFFD"
+ elif (self.parser.framesetOK and
+ any(char not in spaceCharacters for char in token["data"])):
+ self.parser.framesetOK = False
+ Phase.processCharacters(self, token)
+
+ def processStartTag(self, token):
+ currentNode = self.tree.openElements[-1]
+ if (token["name"] in self.breakoutElements or
+ (token["name"] == "font" and
+ set(token["data"].keys()) & set(["color", "face", "size"]))):
+ self.parser.parseError("unexpected-html-element-in-foreign-content",
+ {"name": token["name"]})
+ while (self.tree.openElements[-1].namespace !=
+ self.tree.defaultNamespace and
+ not self.parser.isHTMLIntegrationPoint(self.tree.openElements[-1]) and
+ not self.parser.isMathMLTextIntegrationPoint(self.tree.openElements[-1])):
+ self.tree.openElements.pop()
+ return token
+
+ else:
+ if currentNode.namespace == namespaces["mathml"]:
+ self.parser.adjustMathMLAttributes(token)
+ elif currentNode.namespace == namespaces["svg"]:
+ self.adjustSVGTagNames(token)
+ self.parser.adjustSVGAttributes(token)
+ self.parser.adjustForeignAttributes(token)
+ token["namespace"] = currentNode.namespace
+ self.tree.insertElement(token)
+ if token["selfClosing"]:
+ self.tree.openElements.pop()
+ token["selfClosingAcknowledged"] = True
+
+ def processEndTag(self, token):
+ nodeIndex = len(self.tree.openElements) - 1
+ node = self.tree.openElements[-1]
+ if node.name != token["name"]:
+ self.parser.parseError("unexpected-end-tag", {"name": token["name"]})
+
+ while True:
+ if node.name.translate(asciiUpper2Lower) == token["name"]:
+ # XXX this isn't in the spec but it seems necessary
+ if self.parser.phase == self.parser.phases["inTableText"]:
+ self.parser.phase.flushCharacters()
+ self.parser.phase = self.parser.phase.originalPhase
+ while self.tree.openElements.pop() != node:
+ assert self.tree.openElements
+ new_token = None
+ break
+ nodeIndex -= 1
+
+ node = self.tree.openElements[nodeIndex]
+ if node.namespace != self.tree.defaultNamespace:
+ continue
+ else:
+ new_token = self.parser.phase.processEndTag(token)
+ break
+ return new_token
+
+ class AfterBodyPhase(Phase):
+ def __init__(self, parser, tree):
+ Phase.__init__(self, parser, tree)
+
+ self.startTagHandler = utils.MethodDispatcher([
+ ("html", self.startTagHtml)
+ ])
+ self.startTagHandler.default = self.startTagOther
+
+ self.endTagHandler = utils.MethodDispatcher([("html", self.endTagHtml)])
+ self.endTagHandler.default = self.endTagOther
+
+ def processEOF(self):
+ # Stop parsing
+ pass
+
+ def processComment(self, token):
+ # This is needed because data is to be appended to the <html> element
+ # here and not to whatever is currently open.
+ self.tree.insertComment(token, self.tree.openElements[0])
+
+ def processCharacters(self, token):
+ self.parser.parseError("unexpected-char-after-body")
+ self.parser.phase = self.parser.phases["inBody"]
+ return token
+
+ def startTagHtml(self, token):
+ return self.parser.phases["inBody"].processStartTag(token)
+
+ def startTagOther(self, token):
+ self.parser.parseError("unexpected-start-tag-after-body",
+ {"name": token["name"]})
+ self.parser.phase = self.parser.phases["inBody"]
+ return token
+
+ def endTagHtml(self, name):
+ if self.parser.innerHTML:
+ self.parser.parseError("unexpected-end-tag-after-body-innerhtml")
+ else:
+ self.parser.phase = self.parser.phases["afterAfterBody"]
+
+ def endTagOther(self, token):
+ self.parser.parseError("unexpected-end-tag-after-body",
+ {"name": token["name"]})
+ self.parser.phase = self.parser.phases["inBody"]
+ return token
+
+ class InFramesetPhase(Phase):
+ # http://www.whatwg.org/specs/web-apps/current-work/#in-frameset
+ def __init__(self, parser, tree):
+ Phase.__init__(self, parser, tree)
+
+ self.startTagHandler = utils.MethodDispatcher([
+ ("html", self.startTagHtml),
+ ("frameset", self.startTagFrameset),
+ ("frame", self.startTagFrame),
+ ("noframes", self.startTagNoframes)
+ ])
+ self.startTagHandler.default = self.startTagOther
+
+ self.endTagHandler = utils.MethodDispatcher([
+ ("frameset", self.endTagFrameset)
+ ])
+ self.endTagHandler.default = self.endTagOther
+
+ def processEOF(self):
+ if self.tree.openElements[-1].name != "html":
+ self.parser.parseError("eof-in-frameset")
+ else:
+ assert self.parser.innerHTML
+
+ def processCharacters(self, token):
+ self.parser.parseError("unexpected-char-in-frameset")
+
+ def startTagFrameset(self, token):
+ self.tree.insertElement(token)
+
+ def startTagFrame(self, token):
+ self.tree.insertElement(token)
+ self.tree.openElements.pop()
+
+ def startTagNoframes(self, token):
+ return self.parser.phases["inBody"].processStartTag(token)
+
+ def startTagOther(self, token):
+ self.parser.parseError("unexpected-start-tag-in-frameset",
+ {"name": token["name"]})
+
+ def endTagFrameset(self, token):
+ if self.tree.openElements[-1].name == "html":
+ # innerHTML case
+ self.parser.parseError("unexpected-frameset-in-frameset-innerhtml")
+ else:
+ self.tree.openElements.pop()
+ if (not self.parser.innerHTML and
+ self.tree.openElements[-1].name != "frameset"):
+ # If we're not in innerHTML mode and the the current node is not a
+ # "frameset" element (anymore) then switch.
+ self.parser.phase = self.parser.phases["afterFrameset"]
+
+ def endTagOther(self, token):
+ self.parser.parseError("unexpected-end-tag-in-frameset",
+ {"name": token["name"]})
+
+ class AfterFramesetPhase(Phase):
+ # http://www.whatwg.org/specs/web-apps/current-work/#after3
+ def __init__(self, parser, tree):
+ Phase.__init__(self, parser, tree)
+
+ self.startTagHandler = utils.MethodDispatcher([
+ ("html", self.startTagHtml),
+ ("noframes", self.startTagNoframes)
+ ])
+ self.startTagHandler.default = self.startTagOther
+
+ self.endTagHandler = utils.MethodDispatcher([
+ ("html", self.endTagHtml)
+ ])
+ self.endTagHandler.default = self.endTagOther
+
+ def processEOF(self):
+ # Stop parsing
+ pass
+
+ def processCharacters(self, token):
+ self.parser.parseError("unexpected-char-after-frameset")
+
+ def startTagNoframes(self, token):
+ return self.parser.phases["inHead"].processStartTag(token)
+
+ def startTagOther(self, token):
+ self.parser.parseError("unexpected-start-tag-after-frameset",
+ {"name": token["name"]})
+
+ def endTagHtml(self, token):
+ self.parser.phase = self.parser.phases["afterAfterFrameset"]
+
+ def endTagOther(self, token):
+ self.parser.parseError("unexpected-end-tag-after-frameset",
+ {"name": token["name"]})
+
+ class AfterAfterBodyPhase(Phase):
+ def __init__(self, parser, tree):
+ Phase.__init__(self, parser, tree)
+
+ self.startTagHandler = utils.MethodDispatcher([
+ ("html", self.startTagHtml)
+ ])
+ self.startTagHandler.default = self.startTagOther
+
+ def processEOF(self):
+ pass
+
+ def processComment(self, token):
+ self.tree.insertComment(token, self.tree.document)
+
+ def processSpaceCharacters(self, token):
+ return self.parser.phases["inBody"].processSpaceCharacters(token)
+
+ def processCharacters(self, token):
+ self.parser.parseError("expected-eof-but-got-char")
+ self.parser.phase = self.parser.phases["inBody"]
+ return token
+
+ def startTagHtml(self, token):
+ return self.parser.phases["inBody"].processStartTag(token)
+
+ def startTagOther(self, token):
+ self.parser.parseError("expected-eof-but-got-start-tag",
+ {"name": token["name"]})
+ self.parser.phase = self.parser.phases["inBody"]
+ return token
+
+ def processEndTag(self, token):
+ self.parser.parseError("expected-eof-but-got-end-tag",
+ {"name": token["name"]})
+ self.parser.phase = self.parser.phases["inBody"]
+ return token
+
+ class AfterAfterFramesetPhase(Phase):
+ def __init__(self, parser, tree):
+ Phase.__init__(self, parser, tree)
+
+ self.startTagHandler = utils.MethodDispatcher([
+ ("html", self.startTagHtml),
+ ("noframes", self.startTagNoFrames)
+ ])
+ self.startTagHandler.default = self.startTagOther
+
+ def processEOF(self):
+ pass
+
+ def processComment(self, token):
+ self.tree.insertComment(token, self.tree.document)
+
+ def processSpaceCharacters(self, token):
+ return self.parser.phases["inBody"].processSpaceCharacters(token)
+
+ def processCharacters(self, token):
+ self.parser.parseError("expected-eof-but-got-char")
+
+ def startTagHtml(self, token):
+ return self.parser.phases["inBody"].processStartTag(token)
+
+ def startTagNoFrames(self, token):
+ return self.parser.phases["inHead"].processStartTag(token)
+
+ def startTagOther(self, token):
+ self.parser.parseError("expected-eof-but-got-start-tag",
+ {"name": token["name"]})
+
+ def processEndTag(self, token):
+ self.parser.parseError("expected-eof-but-got-end-tag",
+ {"name": token["name"]})
+
+ return {
+ "initial": InitialPhase,
+ "beforeHtml": BeforeHtmlPhase,
+ "beforeHead": BeforeHeadPhase,
+ "inHead": InHeadPhase,
+ # XXX "inHeadNoscript": InHeadNoScriptPhase,
+ "afterHead": AfterHeadPhase,
+ "inBody": InBodyPhase,
+ "text": TextPhase,
+ "inTable": InTablePhase,
+ "inTableText": InTableTextPhase,
+ "inCaption": InCaptionPhase,
+ "inColumnGroup": InColumnGroupPhase,
+ "inTableBody": InTableBodyPhase,
+ "inRow": InRowPhase,
+ "inCell": InCellPhase,
+ "inSelect": InSelectPhase,
+ "inSelectInTable": InSelectInTablePhase,
+ "inForeignContent": InForeignContentPhase,
+ "afterBody": AfterBodyPhase,
+ "inFrameset": InFramesetPhase,
+ "afterFrameset": AfterFramesetPhase,
+ "afterAfterBody": AfterAfterBodyPhase,
+ "afterAfterFrameset": AfterAfterFramesetPhase,
+ # XXX after after frameset
+ }
+
+
+def impliedTagToken(name, type="EndTag", attributes=None,
+ selfClosing=False):
+ if attributes is None:
+ attributes = {}
+ return {"type": tokenTypes[type], "name": name, "data": attributes,
+ "selfClosing": selfClosing}
+
+
+class ParseError(Exception):
+ """Error in parsed document"""
+ pass
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/ihatexml.py b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/ihatexml.py
new file mode 100644
index 00000000000..0fc79308ef4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/ihatexml.py
@@ -0,0 +1,285 @@
+from __future__ import absolute_import, division, unicode_literals
+
+import re
+import warnings
+
+from .constants import DataLossWarning
+
+baseChar = """
+[#x0041-#x005A] | [#x0061-#x007A] | [#x00C0-#x00D6] | [#x00D8-#x00F6] |
+[#x00F8-#x00FF] | [#x0100-#x0131] | [#x0134-#x013E] | [#x0141-#x0148] |
+[#x014A-#x017E] | [#x0180-#x01C3] | [#x01CD-#x01F0] | [#x01F4-#x01F5] |
+[#x01FA-#x0217] | [#x0250-#x02A8] | [#x02BB-#x02C1] | #x0386 |
+[#x0388-#x038A] | #x038C | [#x038E-#x03A1] | [#x03A3-#x03CE] |
+[#x03D0-#x03D6] | #x03DA | #x03DC | #x03DE | #x03E0 | [#x03E2-#x03F3] |
+[#x0401-#x040C] | [#x040E-#x044F] | [#x0451-#x045C] | [#x045E-#x0481] |
+[#x0490-#x04C4] | [#x04C7-#x04C8] | [#x04CB-#x04CC] | [#x04D0-#x04EB] |
+[#x04EE-#x04F5] | [#x04F8-#x04F9] | [#x0531-#x0556] | #x0559 |
+[#x0561-#x0586] | [#x05D0-#x05EA] | [#x05F0-#x05F2] | [#x0621-#x063A] |
+[#x0641-#x064A] | [#x0671-#x06B7] | [#x06BA-#x06BE] | [#x06C0-#x06CE] |
+[#x06D0-#x06D3] | #x06D5 | [#x06E5-#x06E6] | [#x0905-#x0939] | #x093D |
+[#x0958-#x0961] | [#x0985-#x098C] | [#x098F-#x0990] | [#x0993-#x09A8] |
+[#x09AA-#x09B0] | #x09B2 | [#x09B6-#x09B9] | [#x09DC-#x09DD] |
+[#x09DF-#x09E1] | [#x09F0-#x09F1] | [#x0A05-#x0A0A] | [#x0A0F-#x0A10] |
+[#x0A13-#x0A28] | [#x0A2A-#x0A30] | [#x0A32-#x0A33] | [#x0A35-#x0A36] |
+[#x0A38-#x0A39] | [#x0A59-#x0A5C] | #x0A5E | [#x0A72-#x0A74] |
+[#x0A85-#x0A8B] | #x0A8D | [#x0A8F-#x0A91] | [#x0A93-#x0AA8] |
+[#x0AAA-#x0AB0] | [#x0AB2-#x0AB3] | [#x0AB5-#x0AB9] | #x0ABD | #x0AE0 |
+[#x0B05-#x0B0C] | [#x0B0F-#x0B10] | [#x0B13-#x0B28] | [#x0B2A-#x0B30] |
+[#x0B32-#x0B33] | [#x0B36-#x0B39] | #x0B3D | [#x0B5C-#x0B5D] |
+[#x0B5F-#x0B61] | [#x0B85-#x0B8A] | [#x0B8E-#x0B90] | [#x0B92-#x0B95] |
+[#x0B99-#x0B9A] | #x0B9C | [#x0B9E-#x0B9F] | [#x0BA3-#x0BA4] |
+[#x0BA8-#x0BAA] | [#x0BAE-#x0BB5] | [#x0BB7-#x0BB9] | [#x0C05-#x0C0C] |
+[#x0C0E-#x0C10] | [#x0C12-#x0C28] | [#x0C2A-#x0C33] | [#x0C35-#x0C39] |
+[#x0C60-#x0C61] | [#x0C85-#x0C8C] | [#x0C8E-#x0C90] | [#x0C92-#x0CA8] |
+[#x0CAA-#x0CB3] | [#x0CB5-#x0CB9] | #x0CDE | [#x0CE0-#x0CE1] |
+[#x0D05-#x0D0C] | [#x0D0E-#x0D10] | [#x0D12-#x0D28] | [#x0D2A-#x0D39] |
+[#x0D60-#x0D61] | [#x0E01-#x0E2E] | #x0E30 | [#x0E32-#x0E33] |
+[#x0E40-#x0E45] | [#x0E81-#x0E82] | #x0E84 | [#x0E87-#x0E88] | #x0E8A |
+#x0E8D | [#x0E94-#x0E97] | [#x0E99-#x0E9F] | [#x0EA1-#x0EA3] | #x0EA5 |
+#x0EA7 | [#x0EAA-#x0EAB] | [#x0EAD-#x0EAE] | #x0EB0 | [#x0EB2-#x0EB3] |
+#x0EBD | [#x0EC0-#x0EC4] | [#x0F40-#x0F47] | [#x0F49-#x0F69] |
+[#x10A0-#x10C5] | [#x10D0-#x10F6] | #x1100 | [#x1102-#x1103] |
+[#x1105-#x1107] | #x1109 | [#x110B-#x110C] | [#x110E-#x1112] | #x113C |
+#x113E | #x1140 | #x114C | #x114E | #x1150 | [#x1154-#x1155] | #x1159 |
+[#x115F-#x1161] | #x1163 | #x1165 | #x1167 | #x1169 | [#x116D-#x116E] |
+[#x1172-#x1173] | #x1175 | #x119E | #x11A8 | #x11AB | [#x11AE-#x11AF] |
+[#x11B7-#x11B8] | #x11BA | [#x11BC-#x11C2] | #x11EB | #x11F0 | #x11F9 |
+[#x1E00-#x1E9B] | [#x1EA0-#x1EF9] | [#x1F00-#x1F15] | [#x1F18-#x1F1D] |
+[#x1F20-#x1F45] | [#x1F48-#x1F4D] | [#x1F50-#x1F57] | #x1F59 | #x1F5B |
+#x1F5D | [#x1F5F-#x1F7D] | [#x1F80-#x1FB4] | [#x1FB6-#x1FBC] | #x1FBE |
+[#x1FC2-#x1FC4] | [#x1FC6-#x1FCC] | [#x1FD0-#x1FD3] | [#x1FD6-#x1FDB] |
+[#x1FE0-#x1FEC] | [#x1FF2-#x1FF4] | [#x1FF6-#x1FFC] | #x2126 |
+[#x212A-#x212B] | #x212E | [#x2180-#x2182] | [#x3041-#x3094] |
+[#x30A1-#x30FA] | [#x3105-#x312C] | [#xAC00-#xD7A3]"""
+
+ideographic = """[#x4E00-#x9FA5] | #x3007 | [#x3021-#x3029]"""
+
+combiningCharacter = """
+[#x0300-#x0345] | [#x0360-#x0361] | [#x0483-#x0486] | [#x0591-#x05A1] |
+[#x05A3-#x05B9] | [#x05BB-#x05BD] | #x05BF | [#x05C1-#x05C2] | #x05C4 |
+[#x064B-#x0652] | #x0670 | [#x06D6-#x06DC] | [#x06DD-#x06DF] |
+[#x06E0-#x06E4] | [#x06E7-#x06E8] | [#x06EA-#x06ED] | [#x0901-#x0903] |
+#x093C | [#x093E-#x094C] | #x094D | [#x0951-#x0954] | [#x0962-#x0963] |
+[#x0981-#x0983] | #x09BC | #x09BE | #x09BF | [#x09C0-#x09C4] |
+[#x09C7-#x09C8] | [#x09CB-#x09CD] | #x09D7 | [#x09E2-#x09E3] | #x0A02 |
+#x0A3C | #x0A3E | #x0A3F | [#x0A40-#x0A42] | [#x0A47-#x0A48] |
+[#x0A4B-#x0A4D] | [#x0A70-#x0A71] | [#x0A81-#x0A83] | #x0ABC |
+[#x0ABE-#x0AC5] | [#x0AC7-#x0AC9] | [#x0ACB-#x0ACD] | [#x0B01-#x0B03] |
+#x0B3C | [#x0B3E-#x0B43] | [#x0B47-#x0B48] | [#x0B4B-#x0B4D] |
+[#x0B56-#x0B57] | [#x0B82-#x0B83] | [#x0BBE-#x0BC2] | [#x0BC6-#x0BC8] |
+[#x0BCA-#x0BCD] | #x0BD7 | [#x0C01-#x0C03] | [#x0C3E-#x0C44] |
+[#x0C46-#x0C48] | [#x0C4A-#x0C4D] | [#x0C55-#x0C56] | [#x0C82-#x0C83] |
+[#x0CBE-#x0CC4] | [#x0CC6-#x0CC8] | [#x0CCA-#x0CCD] | [#x0CD5-#x0CD6] |
+[#x0D02-#x0D03] | [#x0D3E-#x0D43] | [#x0D46-#x0D48] | [#x0D4A-#x0D4D] |
+#x0D57 | #x0E31 | [#x0E34-#x0E3A] | [#x0E47-#x0E4E] | #x0EB1 |
+[#x0EB4-#x0EB9] | [#x0EBB-#x0EBC] | [#x0EC8-#x0ECD] | [#x0F18-#x0F19] |
+#x0F35 | #x0F37 | #x0F39 | #x0F3E | #x0F3F | [#x0F71-#x0F84] |
+[#x0F86-#x0F8B] | [#x0F90-#x0F95] | #x0F97 | [#x0F99-#x0FAD] |
+[#x0FB1-#x0FB7] | #x0FB9 | [#x20D0-#x20DC] | #x20E1 | [#x302A-#x302F] |
+#x3099 | #x309A"""
+
+digit = """
+[#x0030-#x0039] | [#x0660-#x0669] | [#x06F0-#x06F9] | [#x0966-#x096F] |
+[#x09E6-#x09EF] | [#x0A66-#x0A6F] | [#x0AE6-#x0AEF] | [#x0B66-#x0B6F] |
+[#x0BE7-#x0BEF] | [#x0C66-#x0C6F] | [#x0CE6-#x0CEF] | [#x0D66-#x0D6F] |
+[#x0E50-#x0E59] | [#x0ED0-#x0ED9] | [#x0F20-#x0F29]"""
+
+extender = """
+#x00B7 | #x02D0 | #x02D1 | #x0387 | #x0640 | #x0E46 | #x0EC6 | #x3005 |
+#[#x3031-#x3035] | [#x309D-#x309E] | [#x30FC-#x30FE]"""
+
+letter = " | ".join([baseChar, ideographic])
+
+# Without the
+name = " | ".join([letter, digit, ".", "-", "_", combiningCharacter,
+ extender])
+nameFirst = " | ".join([letter, "_"])
+
+reChar = re.compile(r"#x([\d|A-F]{4,4})")
+reCharRange = re.compile(r"\[#x([\d|A-F]{4,4})-#x([\d|A-F]{4,4})\]")
+
+
+def charStringToList(chars):
+ charRanges = [item.strip() for item in chars.split(" | ")]
+ rv = []
+ for item in charRanges:
+ foundMatch = False
+ for regexp in (reChar, reCharRange):
+ match = regexp.match(item)
+ if match is not None:
+ rv.append([hexToInt(item) for item in match.groups()])
+ if len(rv[-1]) == 1:
+ rv[-1] = rv[-1] * 2
+ foundMatch = True
+ break
+ if not foundMatch:
+ assert len(item) == 1
+
+ rv.append([ord(item)] * 2)
+ rv = normaliseCharList(rv)
+ return rv
+
+
+def normaliseCharList(charList):
+ charList = sorted(charList)
+ for item in charList:
+ assert item[1] >= item[0]
+ rv = []
+ i = 0
+ while i < len(charList):
+ j = 1
+ rv.append(charList[i])
+ while i + j < len(charList) and charList[i + j][0] <= rv[-1][1] + 1:
+ rv[-1][1] = charList[i + j][1]
+ j += 1
+ i += j
+ return rv
+
+# We don't really support characters above the BMP :(
+max_unicode = int("FFFF", 16)
+
+
+def missingRanges(charList):
+ rv = []
+ if charList[0] != 0:
+ rv.append([0, charList[0][0] - 1])
+ for i, item in enumerate(charList[:-1]):
+ rv.append([item[1] + 1, charList[i + 1][0] - 1])
+ if charList[-1][1] != max_unicode:
+ rv.append([charList[-1][1] + 1, max_unicode])
+ return rv
+
+
+def listToRegexpStr(charList):
+ rv = []
+ for item in charList:
+ if item[0] == item[1]:
+ rv.append(escapeRegexp(chr(item[0])))
+ else:
+ rv.append(escapeRegexp(chr(item[0])) + "-" +
+ escapeRegexp(chr(item[1])))
+ return "[%s]" % "".join(rv)
+
+
+def hexToInt(hex_str):
+ return int(hex_str, 16)
+
+
+def escapeRegexp(string):
+ specialCharacters = (".", "^", "$", "*", "+", "?", "{", "}",
+ "[", "]", "|", "(", ")", "-")
+ for char in specialCharacters:
+ string = string.replace(char, "\\" + char)
+
+ return string
+
+# output from the above
+nonXmlNameBMPRegexp = re.compile('[\x00-,/:-@\\[-\\^`\\{-\xb6\xb8-\xbf\xd7\xf7\u0132-\u0133\u013f-\u0140\u0149\u017f\u01c4-\u01cc\u01f1-\u01f3\u01f6-\u01f9\u0218-\u024f\u02a9-\u02ba\u02c2-\u02cf\u02d2-\u02ff\u0346-\u035f\u0362-\u0385\u038b\u038d\u03a2\u03cf\u03d7-\u03d9\u03db\u03dd\u03df\u03e1\u03f4-\u0400\u040d\u0450\u045d\u0482\u0487-\u048f\u04c5-\u04c6\u04c9-\u04ca\u04cd-\u04cf\u04ec-\u04ed\u04f6-\u04f7\u04fa-\u0530\u0557-\u0558\u055a-\u0560\u0587-\u0590\u05a2\u05ba\u05be\u05c0\u05c3\u05c5-\u05cf\u05eb-\u05ef\u05f3-\u0620\u063b-\u063f\u0653-\u065f\u066a-\u066f\u06b8-\u06b9\u06bf\u06cf\u06d4\u06e9\u06ee-\u06ef\u06fa-\u0900\u0904\u093a-\u093b\u094e-\u0950\u0955-\u0957\u0964-\u0965\u0970-\u0980\u0984\u098d-\u098e\u0991-\u0992\u09a9\u09b1\u09b3-\u09b5\u09ba-\u09bb\u09bd\u09c5-\u09c6\u09c9-\u09ca\u09ce-\u09d6\u09d8-\u09db\u09de\u09e4-\u09e5\u09f2-\u0a01\u0a03-\u0a04\u0a0b-\u0a0e\u0a11-\u0a12\u0a29\u0a31\u0a34\u0a37\u0a3a-\u0a3b\u0a3d\u0a43-\u0a46\u0a49-\u0a4a\u0a4e-\u0a58\u0a5d\u0a5f-\u0a65\u0a75-\u0a80\u0a84\u0a8c\u0a8e\u0a92\u0aa9\u0ab1\u0ab4\u0aba-\u0abb\u0ac6\u0aca\u0ace-\u0adf\u0ae1-\u0ae5\u0af0-\u0b00\u0b04\u0b0d-\u0b0e\u0b11-\u0b12\u0b29\u0b31\u0b34-\u0b35\u0b3a-\u0b3b\u0b44-\u0b46\u0b49-\u0b4a\u0b4e-\u0b55\u0b58-\u0b5b\u0b5e\u0b62-\u0b65\u0b70-\u0b81\u0b84\u0b8b-\u0b8d\u0b91\u0b96-\u0b98\u0b9b\u0b9d\u0ba0-\u0ba2\u0ba5-\u0ba7\u0bab-\u0bad\u0bb6\u0bba-\u0bbd\u0bc3-\u0bc5\u0bc9\u0bce-\u0bd6\u0bd8-\u0be6\u0bf0-\u0c00\u0c04\u0c0d\u0c11\u0c29\u0c34\u0c3a-\u0c3d\u0c45\u0c49\u0c4e-\u0c54\u0c57-\u0c5f\u0c62-\u0c65\u0c70-\u0c81\u0c84\u0c8d\u0c91\u0ca9\u0cb4\u0cba-\u0cbd\u0cc5\u0cc9\u0cce-\u0cd4\u0cd7-\u0cdd\u0cdf\u0ce2-\u0ce5\u0cf0-\u0d01\u0d04\u0d0d\u0d11\u0d29\u0d3a-\u0d3d\u0d44-\u0d45\u0d49\u0d4e-\u0d56\u0d58-\u0d5f\u0d62-\u0d65\u0d70-\u0e00\u0e2f\u0e3b-\u0e3f\u0e4f\u0e5a-\u0e80\u0e83\u0e85-\u0e86\u0e89\u0e8b-\u0e8c\u0e8e-\u0e93\u0e98\u0ea0\u0ea4\u0ea6\u0ea8-\u0ea9\u0eac\u0eaf\u0eba\u0ebe-\u0ebf\u0ec5\u0ec7\u0ece-\u0ecf\u0eda-\u0f17\u0f1a-\u0f1f\u0f2a-\u0f34\u0f36\u0f38\u0f3a-\u0f3d\u0f48\u0f6a-\u0f70\u0f85\u0f8c-\u0f8f\u0f96\u0f98\u0fae-\u0fb0\u0fb8\u0fba-\u109f\u10c6-\u10cf\u10f7-\u10ff\u1101\u1104\u1108\u110a\u110d\u1113-\u113b\u113d\u113f\u1141-\u114b\u114d\u114f\u1151-\u1153\u1156-\u1158\u115a-\u115e\u1162\u1164\u1166\u1168\u116a-\u116c\u116f-\u1171\u1174\u1176-\u119d\u119f-\u11a7\u11a9-\u11aa\u11ac-\u11ad\u11b0-\u11b6\u11b9\u11bb\u11c3-\u11ea\u11ec-\u11ef\u11f1-\u11f8\u11fa-\u1dff\u1e9c-\u1e9f\u1efa-\u1eff\u1f16-\u1f17\u1f1e-\u1f1f\u1f46-\u1f47\u1f4e-\u1f4f\u1f58\u1f5a\u1f5c\u1f5e\u1f7e-\u1f7f\u1fb5\u1fbd\u1fbf-\u1fc1\u1fc5\u1fcd-\u1fcf\u1fd4-\u1fd5\u1fdc-\u1fdf\u1fed-\u1ff1\u1ff5\u1ffd-\u20cf\u20dd-\u20e0\u20e2-\u2125\u2127-\u2129\u212c-\u212d\u212f-\u217f\u2183-\u3004\u3006\u3008-\u3020\u3030\u3036-\u3040\u3095-\u3098\u309b-\u309c\u309f-\u30a0\u30fb\u30ff-\u3104\u312d-\u4dff\u9fa6-\uabff\ud7a4-\uffff]')
+
+nonXmlNameFirstBMPRegexp = re.compile('[\x00-@\\[-\\^`\\{-\xbf\xd7\xf7\u0132-\u0133\u013f-\u0140\u0149\u017f\u01c4-\u01cc\u01f1-\u01f3\u01f6-\u01f9\u0218-\u024f\u02a9-\u02ba\u02c2-\u0385\u0387\u038b\u038d\u03a2\u03cf\u03d7-\u03d9\u03db\u03dd\u03df\u03e1\u03f4-\u0400\u040d\u0450\u045d\u0482-\u048f\u04c5-\u04c6\u04c9-\u04ca\u04cd-\u04cf\u04ec-\u04ed\u04f6-\u04f7\u04fa-\u0530\u0557-\u0558\u055a-\u0560\u0587-\u05cf\u05eb-\u05ef\u05f3-\u0620\u063b-\u0640\u064b-\u0670\u06b8-\u06b9\u06bf\u06cf\u06d4\u06d6-\u06e4\u06e7-\u0904\u093a-\u093c\u093e-\u0957\u0962-\u0984\u098d-\u098e\u0991-\u0992\u09a9\u09b1\u09b3-\u09b5\u09ba-\u09db\u09de\u09e2-\u09ef\u09f2-\u0a04\u0a0b-\u0a0e\u0a11-\u0a12\u0a29\u0a31\u0a34\u0a37\u0a3a-\u0a58\u0a5d\u0a5f-\u0a71\u0a75-\u0a84\u0a8c\u0a8e\u0a92\u0aa9\u0ab1\u0ab4\u0aba-\u0abc\u0abe-\u0adf\u0ae1-\u0b04\u0b0d-\u0b0e\u0b11-\u0b12\u0b29\u0b31\u0b34-\u0b35\u0b3a-\u0b3c\u0b3e-\u0b5b\u0b5e\u0b62-\u0b84\u0b8b-\u0b8d\u0b91\u0b96-\u0b98\u0b9b\u0b9d\u0ba0-\u0ba2\u0ba5-\u0ba7\u0bab-\u0bad\u0bb6\u0bba-\u0c04\u0c0d\u0c11\u0c29\u0c34\u0c3a-\u0c5f\u0c62-\u0c84\u0c8d\u0c91\u0ca9\u0cb4\u0cba-\u0cdd\u0cdf\u0ce2-\u0d04\u0d0d\u0d11\u0d29\u0d3a-\u0d5f\u0d62-\u0e00\u0e2f\u0e31\u0e34-\u0e3f\u0e46-\u0e80\u0e83\u0e85-\u0e86\u0e89\u0e8b-\u0e8c\u0e8e-\u0e93\u0e98\u0ea0\u0ea4\u0ea6\u0ea8-\u0ea9\u0eac\u0eaf\u0eb1\u0eb4-\u0ebc\u0ebe-\u0ebf\u0ec5-\u0f3f\u0f48\u0f6a-\u109f\u10c6-\u10cf\u10f7-\u10ff\u1101\u1104\u1108\u110a\u110d\u1113-\u113b\u113d\u113f\u1141-\u114b\u114d\u114f\u1151-\u1153\u1156-\u1158\u115a-\u115e\u1162\u1164\u1166\u1168\u116a-\u116c\u116f-\u1171\u1174\u1176-\u119d\u119f-\u11a7\u11a9-\u11aa\u11ac-\u11ad\u11b0-\u11b6\u11b9\u11bb\u11c3-\u11ea\u11ec-\u11ef\u11f1-\u11f8\u11fa-\u1dff\u1e9c-\u1e9f\u1efa-\u1eff\u1f16-\u1f17\u1f1e-\u1f1f\u1f46-\u1f47\u1f4e-\u1f4f\u1f58\u1f5a\u1f5c\u1f5e\u1f7e-\u1f7f\u1fb5\u1fbd\u1fbf-\u1fc1\u1fc5\u1fcd-\u1fcf\u1fd4-\u1fd5\u1fdc-\u1fdf\u1fed-\u1ff1\u1ff5\u1ffd-\u2125\u2127-\u2129\u212c-\u212d\u212f-\u217f\u2183-\u3006\u3008-\u3020\u302a-\u3040\u3095-\u30a0\u30fb-\u3104\u312d-\u4dff\u9fa6-\uabff\ud7a4-\uffff]')
+
+# Simpler things
+nonPubidCharRegexp = re.compile("[^\x20\x0D\x0Aa-zA-Z0-9\-\'()+,./:=?;!*#@$_%]")
+
+
+class InfosetFilter(object):
+ replacementRegexp = re.compile(r"U[\dA-F]{5,5}")
+
+ def __init__(self, replaceChars=None,
+ dropXmlnsLocalName=False,
+ dropXmlnsAttrNs=False,
+ preventDoubleDashComments=False,
+ preventDashAtCommentEnd=False,
+ replaceFormFeedCharacters=True,
+ preventSingleQuotePubid=False):
+
+ self.dropXmlnsLocalName = dropXmlnsLocalName
+ self.dropXmlnsAttrNs = dropXmlnsAttrNs
+
+ self.preventDoubleDashComments = preventDoubleDashComments
+ self.preventDashAtCommentEnd = preventDashAtCommentEnd
+
+ self.replaceFormFeedCharacters = replaceFormFeedCharacters
+
+ self.preventSingleQuotePubid = preventSingleQuotePubid
+
+ self.replaceCache = {}
+
+ def coerceAttribute(self, name, namespace=None):
+ if self.dropXmlnsLocalName and name.startswith("xmlns:"):
+ warnings.warn("Attributes cannot begin with xmlns", DataLossWarning)
+ return None
+ elif (self.dropXmlnsAttrNs and
+ namespace == "http://www.w3.org/2000/xmlns/"):
+ warnings.warn("Attributes cannot be in the xml namespace", DataLossWarning)
+ return None
+ else:
+ return self.toXmlName(name)
+
+ def coerceElement(self, name, namespace=None):
+ return self.toXmlName(name)
+
+ def coerceComment(self, data):
+ if self.preventDoubleDashComments:
+ while "--" in data:
+ warnings.warn("Comments cannot contain adjacent dashes", DataLossWarning)
+ data = data.replace("--", "- -")
+ return data
+
+ def coerceCharacters(self, data):
+ if self.replaceFormFeedCharacters:
+ for i in range(data.count("\x0C")):
+ warnings.warn("Text cannot contain U+000C", DataLossWarning)
+ data = data.replace("\x0C", " ")
+ # Other non-xml characters
+ return data
+
+ def coercePubid(self, data):
+ dataOutput = data
+ for char in nonPubidCharRegexp.findall(data):
+ warnings.warn("Coercing non-XML pubid", DataLossWarning)
+ replacement = self.getReplacementCharacter(char)
+ dataOutput = dataOutput.replace(char, replacement)
+ if self.preventSingleQuotePubid and dataOutput.find("'") >= 0:
+ warnings.warn("Pubid cannot contain single quote", DataLossWarning)
+ dataOutput = dataOutput.replace("'", self.getReplacementCharacter("'"))
+ return dataOutput
+
+ def toXmlName(self, name):
+ nameFirst = name[0]
+ nameRest = name[1:]
+ m = nonXmlNameFirstBMPRegexp.match(nameFirst)
+ if m:
+ warnings.warn("Coercing non-XML name", DataLossWarning)
+ nameFirstOutput = self.getReplacementCharacter(nameFirst)
+ else:
+ nameFirstOutput = nameFirst
+
+ nameRestOutput = nameRest
+ replaceChars = set(nonXmlNameBMPRegexp.findall(nameRest))
+ for char in replaceChars:
+ warnings.warn("Coercing non-XML name", DataLossWarning)
+ replacement = self.getReplacementCharacter(char)
+ nameRestOutput = nameRestOutput.replace(char, replacement)
+ return nameFirstOutput + nameRestOutput
+
+ def getReplacementCharacter(self, char):
+ if char in self.replaceCache:
+ replacement = self.replaceCache[char]
+ else:
+ replacement = self.escapeChar(char)
+ return replacement
+
+ def fromXmlName(self, name):
+ for item in set(self.replacementRegexp.findall(name)):
+ name = name.replace(item, self.unescapeChar(item))
+ return name
+
+ def escapeChar(self, char):
+ replacement = "U%05X" % ord(char)
+ self.replaceCache[char] = replacement
+ return replacement
+
+ def unescapeChar(self, charcode):
+ return chr(int(charcode[1:], 16))
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/inputstream.py b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/inputstream.py
new file mode 100644
index 00000000000..9e03b9313d7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/inputstream.py
@@ -0,0 +1,886 @@
+from __future__ import absolute_import, division, unicode_literals
+from six import text_type
+from six.moves import http_client
+
+import codecs
+import re
+
+from .constants import EOF, spaceCharacters, asciiLetters, asciiUppercase
+from .constants import encodings, ReparseException
+from . import utils
+
+from io import StringIO
+
+try:
+ from io import BytesIO
+except ImportError:
+ BytesIO = StringIO
+
+try:
+ from io import BufferedIOBase
+except ImportError:
+ class BufferedIOBase(object):
+ pass
+
+# Non-unicode versions of constants for use in the pre-parser
+spaceCharactersBytes = frozenset([item.encode("ascii") for item in spaceCharacters])
+asciiLettersBytes = frozenset([item.encode("ascii") for item in asciiLetters])
+asciiUppercaseBytes = frozenset([item.encode("ascii") for item in asciiUppercase])
+spacesAngleBrackets = spaceCharactersBytes | frozenset([b">", b"<"])
+
+invalid_unicode_re = re.compile("[\u0001-\u0008\u000B\u000E-\u001F\u007F-\u009F\uD800-\uDFFF\uFDD0-\uFDEF\uFFFE\uFFFF\U0001FFFE\U0001FFFF\U0002FFFE\U0002FFFF\U0003FFFE\U0003FFFF\U0004FFFE\U0004FFFF\U0005FFFE\U0005FFFF\U0006FFFE\U0006FFFF\U0007FFFE\U0007FFFF\U0008FFFE\U0008FFFF\U0009FFFE\U0009FFFF\U000AFFFE\U000AFFFF\U000BFFFE\U000BFFFF\U000CFFFE\U000CFFFF\U000DFFFE\U000DFFFF\U000EFFFE\U000EFFFF\U000FFFFE\U000FFFFF\U0010FFFE\U0010FFFF]")
+
+non_bmp_invalid_codepoints = set([0x1FFFE, 0x1FFFF, 0x2FFFE, 0x2FFFF, 0x3FFFE,
+ 0x3FFFF, 0x4FFFE, 0x4FFFF, 0x5FFFE, 0x5FFFF,
+ 0x6FFFE, 0x6FFFF, 0x7FFFE, 0x7FFFF, 0x8FFFE,
+ 0x8FFFF, 0x9FFFE, 0x9FFFF, 0xAFFFE, 0xAFFFF,
+ 0xBFFFE, 0xBFFFF, 0xCFFFE, 0xCFFFF, 0xDFFFE,
+ 0xDFFFF, 0xEFFFE, 0xEFFFF, 0xFFFFE, 0xFFFFF,
+ 0x10FFFE, 0x10FFFF])
+
+ascii_punctuation_re = re.compile("[\u0009-\u000D\u0020-\u002F\u003A-\u0040\u005B-\u0060\u007B-\u007E]")
+
+# Cache for charsUntil()
+charsUntilRegEx = {}
+
+
+class BufferedStream(object):
+ """Buffering for streams that do not have buffering of their own
+
+ The buffer is implemented as a list of chunks on the assumption that
+ joining many strings will be slow since it is O(n**2)
+ """
+
+ def __init__(self, stream):
+ self.stream = stream
+ self.buffer = []
+ self.position = [-1, 0] # chunk number, offset
+
+ def tell(self):
+ pos = 0
+ for chunk in self.buffer[:self.position[0]]:
+ pos += len(chunk)
+ pos += self.position[1]
+ return pos
+
+ def seek(self, pos):
+ assert pos <= self._bufferedBytes()
+ offset = pos
+ i = 0
+ while len(self.buffer[i]) < offset:
+ offset -= len(self.buffer[i])
+ i += 1
+ self.position = [i, offset]
+
+ def read(self, bytes):
+ if not self.buffer:
+ return self._readStream(bytes)
+ elif (self.position[0] == len(self.buffer) and
+ self.position[1] == len(self.buffer[-1])):
+ return self._readStream(bytes)
+ else:
+ return self._readFromBuffer(bytes)
+
+ def _bufferedBytes(self):
+ return sum([len(item) for item in self.buffer])
+
+ def _readStream(self, bytes):
+ data = self.stream.read(bytes)
+ self.buffer.append(data)
+ self.position[0] += 1
+ self.position[1] = len(data)
+ return data
+
+ def _readFromBuffer(self, bytes):
+ remainingBytes = bytes
+ rv = []
+ bufferIndex = self.position[0]
+ bufferOffset = self.position[1]
+ while bufferIndex < len(self.buffer) and remainingBytes != 0:
+ assert remainingBytes > 0
+ bufferedData = self.buffer[bufferIndex]
+
+ if remainingBytes <= len(bufferedData) - bufferOffset:
+ bytesToRead = remainingBytes
+ self.position = [bufferIndex, bufferOffset + bytesToRead]
+ else:
+ bytesToRead = len(bufferedData) - bufferOffset
+ self.position = [bufferIndex, len(bufferedData)]
+ bufferIndex += 1
+ rv.append(bufferedData[bufferOffset:bufferOffset + bytesToRead])
+ remainingBytes -= bytesToRead
+
+ bufferOffset = 0
+
+ if remainingBytes:
+ rv.append(self._readStream(remainingBytes))
+
+ return b"".join(rv)
+
+
+def HTMLInputStream(source, encoding=None, parseMeta=True, chardet=True):
+ if isinstance(source, http_client.HTTPResponse):
+ # Work around Python bug #20007: read(0) closes the connection.
+ # http://bugs.python.org/issue20007
+ isUnicode = False
+ elif hasattr(source, "read"):
+ isUnicode = isinstance(source.read(0), text_type)
+ else:
+ isUnicode = isinstance(source, text_type)
+
+ if isUnicode:
+ if encoding is not None:
+ raise TypeError("Cannot explicitly set an encoding with a unicode string")
+
+ return HTMLUnicodeInputStream(source)
+ else:
+ return HTMLBinaryInputStream(source, encoding, parseMeta, chardet)
+
+
+class HTMLUnicodeInputStream(object):
+ """Provides a unicode stream of characters to the HTMLTokenizer.
+
+ This class takes care of character encoding and removing or replacing
+ incorrect byte-sequences and also provides column and line tracking.
+
+ """
+
+ _defaultChunkSize = 10240
+
+ def __init__(self, source):
+ """Initialises the HTMLInputStream.
+
+ HTMLInputStream(source, [encoding]) -> Normalized stream from source
+ for use by html5lib.
+
+ source can be either a file-object, local filename or a string.
+
+ The optional encoding parameter must be a string that indicates
+ the encoding. If specified, that encoding will be used,
+ regardless of any BOM or later declaration (such as in a meta
+ element)
+
+ parseMeta - Look for a <meta> element containing encoding information
+
+ """
+
+ # Craziness
+ if len("\U0010FFFF") == 1:
+ self.reportCharacterErrors = self.characterErrorsUCS4
+ self.replaceCharactersRegexp = re.compile("[\uD800-\uDFFF]")
+ else:
+ self.reportCharacterErrors = self.characterErrorsUCS2
+ self.replaceCharactersRegexp = re.compile("([\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF])")
+
+ # List of where new lines occur
+ self.newLines = [0]
+
+ self.charEncoding = ("utf-8", "certain")
+ self.dataStream = self.openStream(source)
+
+ self.reset()
+
+ def reset(self):
+ self.chunk = ""
+ self.chunkSize = 0
+ self.chunkOffset = 0
+ self.errors = []
+
+ # number of (complete) lines in previous chunks
+ self.prevNumLines = 0
+ # number of columns in the last line of the previous chunk
+ self.prevNumCols = 0
+
+ # Deal with CR LF and surrogates split over chunk boundaries
+ self._bufferedCharacter = None
+
+ def openStream(self, source):
+ """Produces a file object from source.
+
+ source can be either a file object, local filename or a string.
+
+ """
+ # Already a file object
+ if hasattr(source, 'read'):
+ stream = source
+ else:
+ stream = StringIO(source)
+
+ return stream
+
+ def _position(self, offset):
+ chunk = self.chunk
+ nLines = chunk.count('\n', 0, offset)
+ positionLine = self.prevNumLines + nLines
+ lastLinePos = chunk.rfind('\n', 0, offset)
+ if lastLinePos == -1:
+ positionColumn = self.prevNumCols + offset
+ else:
+ positionColumn = offset - (lastLinePos + 1)
+ return (positionLine, positionColumn)
+
+ def position(self):
+ """Returns (line, col) of the current position in the stream."""
+ line, col = self._position(self.chunkOffset)
+ return (line + 1, col)
+
+ def char(self):
+ """ Read one character from the stream or queue if available. Return
+ EOF when EOF is reached.
+ """
+ # Read a new chunk from the input stream if necessary
+ if self.chunkOffset >= self.chunkSize:
+ if not self.readChunk():
+ return EOF
+
+ chunkOffset = self.chunkOffset
+ char = self.chunk[chunkOffset]
+ self.chunkOffset = chunkOffset + 1
+
+ return char
+
+ def readChunk(self, chunkSize=None):
+ if chunkSize is None:
+ chunkSize = self._defaultChunkSize
+
+ self.prevNumLines, self.prevNumCols = self._position(self.chunkSize)
+
+ self.chunk = ""
+ self.chunkSize = 0
+ self.chunkOffset = 0
+
+ data = self.dataStream.read(chunkSize)
+
+ # Deal with CR LF and surrogates broken across chunks
+ if self._bufferedCharacter:
+ data = self._bufferedCharacter + data
+ self._bufferedCharacter = None
+ elif not data:
+ # We have no more data, bye-bye stream
+ return False
+
+ if len(data) > 1:
+ lastv = ord(data[-1])
+ if lastv == 0x0D or 0xD800 <= lastv <= 0xDBFF:
+ self._bufferedCharacter = data[-1]
+ data = data[:-1]
+
+ self.reportCharacterErrors(data)
+
+ # Replace invalid characters
+ # Note U+0000 is dealt with in the tokenizer
+ data = self.replaceCharactersRegexp.sub("\ufffd", data)
+
+ data = data.replace("\r\n", "\n")
+ data = data.replace("\r", "\n")
+
+ self.chunk = data
+ self.chunkSize = len(data)
+
+ return True
+
+ def characterErrorsUCS4(self, data):
+ for i in range(len(invalid_unicode_re.findall(data))):
+ self.errors.append("invalid-codepoint")
+
+ def characterErrorsUCS2(self, data):
+ # Someone picked the wrong compile option
+ # You lose
+ skip = False
+ for match in invalid_unicode_re.finditer(data):
+ if skip:
+ continue
+ codepoint = ord(match.group())
+ pos = match.start()
+ # Pretty sure there should be endianness issues here
+ if utils.isSurrogatePair(data[pos:pos + 2]):
+ # We have a surrogate pair!
+ char_val = utils.surrogatePairToCodepoint(data[pos:pos + 2])
+ if char_val in non_bmp_invalid_codepoints:
+ self.errors.append("invalid-codepoint")
+ skip = True
+ elif (codepoint >= 0xD800 and codepoint <= 0xDFFF and
+ pos == len(data) - 1):
+ self.errors.append("invalid-codepoint")
+ else:
+ skip = False
+ self.errors.append("invalid-codepoint")
+
+ def charsUntil(self, characters, opposite=False):
+ """ Returns a string of characters from the stream up to but not
+ including any character in 'characters' or EOF. 'characters' must be
+ a container that supports the 'in' method and iteration over its
+ characters.
+ """
+
+ # Use a cache of regexps to find the required characters
+ try:
+ chars = charsUntilRegEx[(characters, opposite)]
+ except KeyError:
+ if __debug__:
+ for c in characters:
+ assert(ord(c) < 128)
+ regex = "".join(["\\x%02x" % ord(c) for c in characters])
+ if not opposite:
+ regex = "^%s" % regex
+ chars = charsUntilRegEx[(characters, opposite)] = re.compile("[%s]+" % regex)
+
+ rv = []
+
+ while True:
+ # Find the longest matching prefix
+ m = chars.match(self.chunk, self.chunkOffset)
+ if m is None:
+ # If nothing matched, and it wasn't because we ran out of chunk,
+ # then stop
+ if self.chunkOffset != self.chunkSize:
+ break
+ else:
+ end = m.end()
+ # If not the whole chunk matched, return everything
+ # up to the part that didn't match
+ if end != self.chunkSize:
+ rv.append(self.chunk[self.chunkOffset:end])
+ self.chunkOffset = end
+ break
+ # If the whole remainder of the chunk matched,
+ # use it all and read the next chunk
+ rv.append(self.chunk[self.chunkOffset:])
+ if not self.readChunk():
+ # Reached EOF
+ break
+
+ r = "".join(rv)
+ return r
+
+ def unget(self, char):
+ # Only one character is allowed to be ungotten at once - it must
+ # be consumed again before any further call to unget
+ if char is not None:
+ if self.chunkOffset == 0:
+ # unget is called quite rarely, so it's a good idea to do
+ # more work here if it saves a bit of work in the frequently
+ # called char and charsUntil.
+ # So, just prepend the ungotten character onto the current
+ # chunk:
+ self.chunk = char + self.chunk
+ self.chunkSize += 1
+ else:
+ self.chunkOffset -= 1
+ assert self.chunk[self.chunkOffset] == char
+
+
+class HTMLBinaryInputStream(HTMLUnicodeInputStream):
+ """Provides a unicode stream of characters to the HTMLTokenizer.
+
+ This class takes care of character encoding and removing or replacing
+ incorrect byte-sequences and also provides column and line tracking.
+
+ """
+
+ def __init__(self, source, encoding=None, parseMeta=True, chardet=True):
+ """Initialises the HTMLInputStream.
+
+ HTMLInputStream(source, [encoding]) -> Normalized stream from source
+ for use by html5lib.
+
+ source can be either a file-object, local filename or a string.
+
+ The optional encoding parameter must be a string that indicates
+ the encoding. If specified, that encoding will be used,
+ regardless of any BOM or later declaration (such as in a meta
+ element)
+
+ parseMeta - Look for a <meta> element containing encoding information
+
+ """
+ # Raw Stream - for unicode objects this will encode to utf-8 and set
+ # self.charEncoding as appropriate
+ self.rawStream = self.openStream(source)
+
+ HTMLUnicodeInputStream.__init__(self, self.rawStream)
+
+ self.charEncoding = (codecName(encoding), "certain")
+
+ # Encoding Information
+ # Number of bytes to use when looking for a meta element with
+ # encoding information
+ self.numBytesMeta = 512
+ # Number of bytes to use when using detecting encoding using chardet
+ self.numBytesChardet = 100
+ # Encoding to use if no other information can be found
+ self.defaultEncoding = "windows-1252"
+
+ # Detect encoding iff no explicit "transport level" encoding is supplied
+ if (self.charEncoding[0] is None):
+ self.charEncoding = self.detectEncoding(parseMeta, chardet)
+
+ # Call superclass
+ self.reset()
+
+ def reset(self):
+ self.dataStream = codecs.getreader(self.charEncoding[0])(self.rawStream,
+ 'replace')
+ HTMLUnicodeInputStream.reset(self)
+
+ def openStream(self, source):
+ """Produces a file object from source.
+
+ source can be either a file object, local filename or a string.
+
+ """
+ # Already a file object
+ if hasattr(source, 'read'):
+ stream = source
+ else:
+ stream = BytesIO(source)
+
+ try:
+ stream.seek(stream.tell())
+ except:
+ stream = BufferedStream(stream)
+
+ return stream
+
+ def detectEncoding(self, parseMeta=True, chardet=True):
+ # First look for a BOM
+ # This will also read past the BOM if present
+ encoding = self.detectBOM()
+ confidence = "certain"
+ # If there is no BOM need to look for meta elements with encoding
+ # information
+ if encoding is None and parseMeta:
+ encoding = self.detectEncodingMeta()
+ confidence = "tentative"
+ # Guess with chardet, if avaliable
+ if encoding is None and chardet:
+ confidence = "tentative"
+ try:
+ try:
+ from charade.universaldetector import UniversalDetector
+ except ImportError:
+ from chardet.universaldetector import UniversalDetector
+ buffers = []
+ detector = UniversalDetector()
+ while not detector.done:
+ buffer = self.rawStream.read(self.numBytesChardet)
+ assert isinstance(buffer, bytes)
+ if not buffer:
+ break
+ buffers.append(buffer)
+ detector.feed(buffer)
+ detector.close()
+ encoding = detector.result['encoding']
+ self.rawStream.seek(0)
+ except ImportError:
+ pass
+ # If all else fails use the default encoding
+ if encoding is None:
+ confidence = "tentative"
+ encoding = self.defaultEncoding
+
+ # Substitute for equivalent encodings:
+ encodingSub = {"iso-8859-1": "windows-1252"}
+
+ if encoding.lower() in encodingSub:
+ encoding = encodingSub[encoding.lower()]
+
+ return encoding, confidence
+
+ def changeEncoding(self, newEncoding):
+ assert self.charEncoding[1] != "certain"
+ newEncoding = codecName(newEncoding)
+ if newEncoding in ("utf-16", "utf-16-be", "utf-16-le"):
+ newEncoding = "utf-8"
+ if newEncoding is None:
+ return
+ elif newEncoding == self.charEncoding[0]:
+ self.charEncoding = (self.charEncoding[0], "certain")
+ else:
+ self.rawStream.seek(0)
+ self.reset()
+ self.charEncoding = (newEncoding, "certain")
+ raise ReparseException("Encoding changed from %s to %s" % (self.charEncoding[0], newEncoding))
+
+ def detectBOM(self):
+ """Attempts to detect at BOM at the start of the stream. If
+ an encoding can be determined from the BOM return the name of the
+ encoding otherwise return None"""
+ bomDict = {
+ codecs.BOM_UTF8: 'utf-8',
+ codecs.BOM_UTF16_LE: 'utf-16-le', codecs.BOM_UTF16_BE: 'utf-16-be',
+ codecs.BOM_UTF32_LE: 'utf-32-le', codecs.BOM_UTF32_BE: 'utf-32-be'
+ }
+
+ # Go to beginning of file and read in 4 bytes
+ string = self.rawStream.read(4)
+ assert isinstance(string, bytes)
+
+ # Try detecting the BOM using bytes from the string
+ encoding = bomDict.get(string[:3]) # UTF-8
+ seek = 3
+ if not encoding:
+ # Need to detect UTF-32 before UTF-16
+ encoding = bomDict.get(string) # UTF-32
+ seek = 4
+ if not encoding:
+ encoding = bomDict.get(string[:2]) # UTF-16
+ seek = 2
+
+ # Set the read position past the BOM if one was found, otherwise
+ # set it to the start of the stream
+ self.rawStream.seek(encoding and seek or 0)
+
+ return encoding
+
+ def detectEncodingMeta(self):
+ """Report the encoding declared by the meta element
+ """
+ buffer = self.rawStream.read(self.numBytesMeta)
+ assert isinstance(buffer, bytes)
+ parser = EncodingParser(buffer)
+ self.rawStream.seek(0)
+ encoding = parser.getEncoding()
+
+ if encoding in ("utf-16", "utf-16-be", "utf-16-le"):
+ encoding = "utf-8"
+
+ return encoding
+
+
+class EncodingBytes(bytes):
+ """String-like object with an associated position and various extra methods
+ If the position is ever greater than the string length then an exception is
+ raised"""
+ def __new__(self, value):
+ assert isinstance(value, bytes)
+ return bytes.__new__(self, value.lower())
+
+ def __init__(self, value):
+ self._position = -1
+
+ def __iter__(self):
+ return self
+
+ def __next__(self):
+ p = self._position = self._position + 1
+ if p >= len(self):
+ raise StopIteration
+ elif p < 0:
+ raise TypeError
+ return self[p:p + 1]
+
+ def next(self):
+ # Py2 compat
+ return self.__next__()
+
+ def previous(self):
+ p = self._position
+ if p >= len(self):
+ raise StopIteration
+ elif p < 0:
+ raise TypeError
+ self._position = p = p - 1
+ return self[p:p + 1]
+
+ def setPosition(self, position):
+ if self._position >= len(self):
+ raise StopIteration
+ self._position = position
+
+ def getPosition(self):
+ if self._position >= len(self):
+ raise StopIteration
+ if self._position >= 0:
+ return self._position
+ else:
+ return None
+
+ position = property(getPosition, setPosition)
+
+ def getCurrentByte(self):
+ return self[self.position:self.position + 1]
+
+ currentByte = property(getCurrentByte)
+
+ def skip(self, chars=spaceCharactersBytes):
+ """Skip past a list of characters"""
+ p = self.position # use property for the error-checking
+ while p < len(self):
+ c = self[p:p + 1]
+ if c not in chars:
+ self._position = p
+ return c
+ p += 1
+ self._position = p
+ return None
+
+ def skipUntil(self, chars):
+ p = self.position
+ while p < len(self):
+ c = self[p:p + 1]
+ if c in chars:
+ self._position = p
+ return c
+ p += 1
+ self._position = p
+ return None
+
+ def matchBytes(self, bytes):
+ """Look for a sequence of bytes at the start of a string. If the bytes
+ are found return True and advance the position to the byte after the
+ match. Otherwise return False and leave the position alone"""
+ p = self.position
+ data = self[p:p + len(bytes)]
+ rv = data.startswith(bytes)
+ if rv:
+ self.position += len(bytes)
+ return rv
+
+ def jumpTo(self, bytes):
+ """Look for the next sequence of bytes matching a given sequence. If
+ a match is found advance the position to the last byte of the match"""
+ newPosition = self[self.position:].find(bytes)
+ if newPosition > -1:
+ # XXX: This is ugly, but I can't see a nicer way to fix this.
+ if self._position == -1:
+ self._position = 0
+ self._position += (newPosition + len(bytes) - 1)
+ return True
+ else:
+ raise StopIteration
+
+
+class EncodingParser(object):
+ """Mini parser for detecting character encoding from meta elements"""
+
+ def __init__(self, data):
+ """string - the data to work on for encoding detection"""
+ self.data = EncodingBytes(data)
+ self.encoding = None
+
+ def getEncoding(self):
+ methodDispatch = (
+ (b"<!--", self.handleComment),
+ (b"<meta", self.handleMeta),
+ (b"</", self.handlePossibleEndTag),
+ (b"<!", self.handleOther),
+ (b"<?", self.handleOther),
+ (b"<", self.handlePossibleStartTag))
+ for byte in self.data:
+ keepParsing = True
+ for key, method in methodDispatch:
+ if self.data.matchBytes(key):
+ try:
+ keepParsing = method()
+ break
+ except StopIteration:
+ keepParsing = False
+ break
+ if not keepParsing:
+ break
+
+ return self.encoding
+
+ def handleComment(self):
+ """Skip over comments"""
+ return self.data.jumpTo(b"-->")
+
+ def handleMeta(self):
+ if self.data.currentByte not in spaceCharactersBytes:
+ # if we have <meta not followed by a space so just keep going
+ return True
+ # We have a valid meta element we want to search for attributes
+ hasPragma = False
+ pendingEncoding = None
+ while True:
+ # Try to find the next attribute after the current position
+ attr = self.getAttribute()
+ if attr is None:
+ return True
+ else:
+ if attr[0] == b"http-equiv":
+ hasPragma = attr[1] == b"content-type"
+ if hasPragma and pendingEncoding is not None:
+ self.encoding = pendingEncoding
+ return False
+ elif attr[0] == b"charset":
+ tentativeEncoding = attr[1]
+ codec = codecName(tentativeEncoding)
+ if codec is not None:
+ self.encoding = codec
+ return False
+ elif attr[0] == b"content":
+ contentParser = ContentAttrParser(EncodingBytes(attr[1]))
+ tentativeEncoding = contentParser.parse()
+ if tentativeEncoding is not None:
+ codec = codecName(tentativeEncoding)
+ if codec is not None:
+ if hasPragma:
+ self.encoding = codec
+ return False
+ else:
+ pendingEncoding = codec
+
+ def handlePossibleStartTag(self):
+ return self.handlePossibleTag(False)
+
+ def handlePossibleEndTag(self):
+ next(self.data)
+ return self.handlePossibleTag(True)
+
+ def handlePossibleTag(self, endTag):
+ data = self.data
+ if data.currentByte not in asciiLettersBytes:
+ # If the next byte is not an ascii letter either ignore this
+ # fragment (possible start tag case) or treat it according to
+ # handleOther
+ if endTag:
+ data.previous()
+ self.handleOther()
+ return True
+
+ c = data.skipUntil(spacesAngleBrackets)
+ if c == b"<":
+ # return to the first step in the overall "two step" algorithm
+ # reprocessing the < byte
+ data.previous()
+ else:
+ # Read all attributes
+ attr = self.getAttribute()
+ while attr is not None:
+ attr = self.getAttribute()
+ return True
+
+ def handleOther(self):
+ return self.data.jumpTo(b">")
+
+ def getAttribute(self):
+ """Return a name,value pair for the next attribute in the stream,
+ if one is found, or None"""
+ data = self.data
+ # Step 1 (skip chars)
+ c = data.skip(spaceCharactersBytes | frozenset([b"/"]))
+ assert c is None or len(c) == 1
+ # Step 2
+ if c in (b">", None):
+ return None
+ # Step 3
+ attrName = []
+ attrValue = []
+ # Step 4 attribute name
+ while True:
+ if c == b"=" and attrName:
+ break
+ elif c in spaceCharactersBytes:
+ # Step 6!
+ c = data.skip()
+ break
+ elif c in (b"/", b">"):
+ return b"".join(attrName), b""
+ elif c in asciiUppercaseBytes:
+ attrName.append(c.lower())
+ elif c is None:
+ return None
+ else:
+ attrName.append(c)
+ # Step 5
+ c = next(data)
+ # Step 7
+ if c != b"=":
+ data.previous()
+ return b"".join(attrName), b""
+ # Step 8
+ next(data)
+ # Step 9
+ c = data.skip()
+ # Step 10
+ if c in (b"'", b'"'):
+ # 10.1
+ quoteChar = c
+ while True:
+ # 10.2
+ c = next(data)
+ # 10.3
+ if c == quoteChar:
+ next(data)
+ return b"".join(attrName), b"".join(attrValue)
+ # 10.4
+ elif c in asciiUppercaseBytes:
+ attrValue.append(c.lower())
+ # 10.5
+ else:
+ attrValue.append(c)
+ elif c == b">":
+ return b"".join(attrName), b""
+ elif c in asciiUppercaseBytes:
+ attrValue.append(c.lower())
+ elif c is None:
+ return None
+ else:
+ attrValue.append(c)
+ # Step 11
+ while True:
+ c = next(data)
+ if c in spacesAngleBrackets:
+ return b"".join(attrName), b"".join(attrValue)
+ elif c in asciiUppercaseBytes:
+ attrValue.append(c.lower())
+ elif c is None:
+ return None
+ else:
+ attrValue.append(c)
+
+
+class ContentAttrParser(object):
+ def __init__(self, data):
+ assert isinstance(data, bytes)
+ self.data = data
+
+ def parse(self):
+ try:
+ # Check if the attr name is charset
+ # otherwise return
+ self.data.jumpTo(b"charset")
+ self.data.position += 1
+ self.data.skip()
+ if not self.data.currentByte == b"=":
+ # If there is no = sign keep looking for attrs
+ return None
+ self.data.position += 1
+ self.data.skip()
+ # Look for an encoding between matching quote marks
+ if self.data.currentByte in (b'"', b"'"):
+ quoteMark = self.data.currentByte
+ self.data.position += 1
+ oldPosition = self.data.position
+ if self.data.jumpTo(quoteMark):
+ return self.data[oldPosition:self.data.position]
+ else:
+ return None
+ else:
+ # Unquoted value
+ oldPosition = self.data.position
+ try:
+ self.data.skipUntil(spaceCharactersBytes)
+ return self.data[oldPosition:self.data.position]
+ except StopIteration:
+ # Return the whole remaining value
+ return self.data[oldPosition:]
+ except StopIteration:
+ return None
+
+
+def codecName(encoding):
+ """Return the python codec name corresponding to an encoding or None if the
+ string doesn't correspond to a valid encoding."""
+ if isinstance(encoding, bytes):
+ try:
+ encoding = encoding.decode("ascii")
+ except UnicodeDecodeError:
+ return None
+ if encoding:
+ canonicalName = ascii_punctuation_re.sub("", encoding).lower()
+ return encodings.get(canonicalName, None)
+ else:
+ return None
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/sanitizer.py b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/sanitizer.py
new file mode 100644
index 00000000000..469d9b40c96
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/sanitizer.py
@@ -0,0 +1,271 @@
+from __future__ import absolute_import, division, unicode_literals
+
+import re
+from xml.sax.saxutils import escape, unescape
+
+from .tokenizer import HTMLTokenizer
+from .constants import tokenTypes
+
+
+class HTMLSanitizerMixin(object):
+ """ sanitization of XHTML+MathML+SVG and of inline style attributes."""
+
+ acceptable_elements = ['a', 'abbr', 'acronym', 'address', 'area',
+ 'article', 'aside', 'audio', 'b', 'big', 'blockquote', 'br', 'button',
+ 'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup',
+ 'command', 'datagrid', 'datalist', 'dd', 'del', 'details', 'dfn',
+ 'dialog', 'dir', 'div', 'dl', 'dt', 'em', 'event-source', 'fieldset',
+ 'figcaption', 'figure', 'footer', 'font', 'form', 'header', 'h1',
+ 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'img', 'input', 'ins',
+ 'keygen', 'kbd', 'label', 'legend', 'li', 'm', 'map', 'menu', 'meter',
+ 'multicol', 'nav', 'nextid', 'ol', 'output', 'optgroup', 'option',
+ 'p', 'pre', 'progress', 'q', 's', 'samp', 'section', 'select',
+ 'small', 'sound', 'source', 'spacer', 'span', 'strike', 'strong',
+ 'sub', 'sup', 'table', 'tbody', 'td', 'textarea', 'time', 'tfoot',
+ 'th', 'thead', 'tr', 'tt', 'u', 'ul', 'var', 'video']
+
+ mathml_elements = ['maction', 'math', 'merror', 'mfrac', 'mi',
+ 'mmultiscripts', 'mn', 'mo', 'mover', 'mpadded', 'mphantom',
+ 'mprescripts', 'mroot', 'mrow', 'mspace', 'msqrt', 'mstyle', 'msub',
+ 'msubsup', 'msup', 'mtable', 'mtd', 'mtext', 'mtr', 'munder',
+ 'munderover', 'none']
+
+ svg_elements = ['a', 'animate', 'animateColor', 'animateMotion',
+ 'animateTransform', 'clipPath', 'circle', 'defs', 'desc', 'ellipse',
+ 'font-face', 'font-face-name', 'font-face-src', 'g', 'glyph', 'hkern',
+ 'linearGradient', 'line', 'marker', 'metadata', 'missing-glyph',
+ 'mpath', 'path', 'polygon', 'polyline', 'radialGradient', 'rect',
+ 'set', 'stop', 'svg', 'switch', 'text', 'title', 'tspan', 'use']
+
+ acceptable_attributes = ['abbr', 'accept', 'accept-charset', 'accesskey',
+ 'action', 'align', 'alt', 'autocomplete', 'autofocus', 'axis',
+ 'background', 'balance', 'bgcolor', 'bgproperties', 'border',
+ 'bordercolor', 'bordercolordark', 'bordercolorlight', 'bottompadding',
+ 'cellpadding', 'cellspacing', 'ch', 'challenge', 'char', 'charoff',
+ 'choff', 'charset', 'checked', 'cite', 'class', 'clear', 'color',
+ 'cols', 'colspan', 'compact', 'contenteditable', 'controls', 'coords',
+ 'data', 'datafld', 'datapagesize', 'datasrc', 'datetime', 'default',
+ 'delay', 'dir', 'disabled', 'draggable', 'dynsrc', 'enctype', 'end',
+ 'face', 'for', 'form', 'frame', 'galleryimg', 'gutter', 'headers',
+ 'height', 'hidefocus', 'hidden', 'high', 'href', 'hreflang', 'hspace',
+ 'icon', 'id', 'inputmode', 'ismap', 'keytype', 'label', 'leftspacing',
+ 'lang', 'list', 'longdesc', 'loop', 'loopcount', 'loopend',
+ 'loopstart', 'low', 'lowsrc', 'max', 'maxlength', 'media', 'method',
+ 'min', 'multiple', 'name', 'nohref', 'noshade', 'nowrap', 'open',
+ 'optimum', 'pattern', 'ping', 'point-size', 'poster', 'pqg', 'preload',
+ 'prompt', 'radiogroup', 'readonly', 'rel', 'repeat-max', 'repeat-min',
+ 'replace', 'required', 'rev', 'rightspacing', 'rows', 'rowspan',
+ 'rules', 'scope', 'selected', 'shape', 'size', 'span', 'src', 'start',
+ 'step', 'style', 'summary', 'suppress', 'tabindex', 'target',
+ 'template', 'title', 'toppadding', 'type', 'unselectable', 'usemap',
+ 'urn', 'valign', 'value', 'variable', 'volume', 'vspace', 'vrml',
+ 'width', 'wrap', 'xml:lang']
+
+ mathml_attributes = ['actiontype', 'align', 'columnalign', 'columnalign',
+ 'columnalign', 'columnlines', 'columnspacing', 'columnspan', 'depth',
+ 'display', 'displaystyle', 'equalcolumns', 'equalrows', 'fence',
+ 'fontstyle', 'fontweight', 'frame', 'height', 'linethickness', 'lspace',
+ 'mathbackground', 'mathcolor', 'mathvariant', 'mathvariant', 'maxsize',
+ 'minsize', 'other', 'rowalign', 'rowalign', 'rowalign', 'rowlines',
+ 'rowspacing', 'rowspan', 'rspace', 'scriptlevel', 'selection',
+ 'separator', 'stretchy', 'width', 'width', 'xlink:href', 'xlink:show',
+ 'xlink:type', 'xmlns', 'xmlns:xlink']
+
+ svg_attributes = ['accent-height', 'accumulate', 'additive', 'alphabetic',
+ 'arabic-form', 'ascent', 'attributeName', 'attributeType',
+ 'baseProfile', 'bbox', 'begin', 'by', 'calcMode', 'cap-height',
+ 'class', 'clip-path', 'color', 'color-rendering', 'content', 'cx',
+ 'cy', 'd', 'dx', 'dy', 'descent', 'display', 'dur', 'end', 'fill',
+ 'fill-opacity', 'fill-rule', 'font-family', 'font-size',
+ 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'from',
+ 'fx', 'fy', 'g1', 'g2', 'glyph-name', 'gradientUnits', 'hanging',
+ 'height', 'horiz-adv-x', 'horiz-origin-x', 'id', 'ideographic', 'k',
+ 'keyPoints', 'keySplines', 'keyTimes', 'lang', 'marker-end',
+ 'marker-mid', 'marker-start', 'markerHeight', 'markerUnits',
+ 'markerWidth', 'mathematical', 'max', 'min', 'name', 'offset',
+ 'opacity', 'orient', 'origin', 'overline-position',
+ 'overline-thickness', 'panose-1', 'path', 'pathLength', 'points',
+ 'preserveAspectRatio', 'r', 'refX', 'refY', 'repeatCount',
+ 'repeatDur', 'requiredExtensions', 'requiredFeatures', 'restart',
+ 'rotate', 'rx', 'ry', 'slope', 'stemh', 'stemv', 'stop-color',
+ 'stop-opacity', 'strikethrough-position', 'strikethrough-thickness',
+ 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap',
+ 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity',
+ 'stroke-width', 'systemLanguage', 'target', 'text-anchor', 'to',
+ 'transform', 'type', 'u1', 'u2', 'underline-position',
+ 'underline-thickness', 'unicode', 'unicode-range', 'units-per-em',
+ 'values', 'version', 'viewBox', 'visibility', 'width', 'widths', 'x',
+ 'x-height', 'x1', 'x2', 'xlink:actuate', 'xlink:arcrole',
+ 'xlink:href', 'xlink:role', 'xlink:show', 'xlink:title', 'xlink:type',
+ 'xml:base', 'xml:lang', 'xml:space', 'xmlns', 'xmlns:xlink', 'y',
+ 'y1', 'y2', 'zoomAndPan']
+
+ attr_val_is_uri = ['href', 'src', 'cite', 'action', 'longdesc', 'poster',
+ 'xlink:href', 'xml:base']
+
+ svg_attr_val_allows_ref = ['clip-path', 'color-profile', 'cursor', 'fill',
+ 'filter', 'marker', 'marker-start', 'marker-mid', 'marker-end',
+ 'mask', 'stroke']
+
+ svg_allow_local_href = ['altGlyph', 'animate', 'animateColor',
+ 'animateMotion', 'animateTransform', 'cursor', 'feImage', 'filter',
+ 'linearGradient', 'pattern', 'radialGradient', 'textpath', 'tref',
+ 'set', 'use']
+
+ acceptable_css_properties = ['azimuth', 'background-color',
+ 'border-bottom-color', 'border-collapse', 'border-color',
+ 'border-left-color', 'border-right-color', 'border-top-color', 'clear',
+ 'color', 'cursor', 'direction', 'display', 'elevation', 'float', 'font',
+ 'font-family', 'font-size', 'font-style', 'font-variant', 'font-weight',
+ 'height', 'letter-spacing', 'line-height', 'overflow', 'pause',
+ 'pause-after', 'pause-before', 'pitch', 'pitch-range', 'richness',
+ 'speak', 'speak-header', 'speak-numeral', 'speak-punctuation',
+ 'speech-rate', 'stress', 'text-align', 'text-decoration', 'text-indent',
+ 'unicode-bidi', 'vertical-align', 'voice-family', 'volume',
+ 'white-space', 'width']
+
+ acceptable_css_keywords = ['auto', 'aqua', 'black', 'block', 'blue',
+ 'bold', 'both', 'bottom', 'brown', 'center', 'collapse', 'dashed',
+ 'dotted', 'fuchsia', 'gray', 'green', '!important', 'italic', 'left',
+ 'lime', 'maroon', 'medium', 'none', 'navy', 'normal', 'nowrap', 'olive',
+ 'pointer', 'purple', 'red', 'right', 'solid', 'silver', 'teal', 'top',
+ 'transparent', 'underline', 'white', 'yellow']
+
+ acceptable_svg_properties = ['fill', 'fill-opacity', 'fill-rule',
+ 'stroke', 'stroke-width', 'stroke-linecap', 'stroke-linejoin',
+ 'stroke-opacity']
+
+ acceptable_protocols = ['ed2k', 'ftp', 'http', 'https', 'irc',
+ 'mailto', 'news', 'gopher', 'nntp', 'telnet', 'webcal',
+ 'xmpp', 'callto', 'feed', 'urn', 'aim', 'rsync', 'tag',
+ 'ssh', 'sftp', 'rtsp', 'afs']
+
+ # subclasses may define their own versions of these constants
+ allowed_elements = acceptable_elements + mathml_elements + svg_elements
+ allowed_attributes = acceptable_attributes + mathml_attributes + svg_attributes
+ allowed_css_properties = acceptable_css_properties
+ allowed_css_keywords = acceptable_css_keywords
+ allowed_svg_properties = acceptable_svg_properties
+ allowed_protocols = acceptable_protocols
+
+ # Sanitize the +html+, escaping all elements not in ALLOWED_ELEMENTS, and
+ # stripping out all # attributes not in ALLOWED_ATTRIBUTES. Style
+ # attributes are parsed, and a restricted set, # specified by
+ # ALLOWED_CSS_PROPERTIES and ALLOWED_CSS_KEYWORDS, are allowed through.
+ # attributes in ATTR_VAL_IS_URI are scanned, and only URI schemes specified
+ # in ALLOWED_PROTOCOLS are allowed.
+ #
+ # sanitize_html('<script> do_nasty_stuff() </script>')
+ # => &lt;script> do_nasty_stuff() &lt;/script>
+ # sanitize_html('<a href="javascript: sucker();">Click here for $100</a>')
+ # => <a>Click here for $100</a>
+ def sanitize_token(self, token):
+
+ # accommodate filters which use token_type differently
+ token_type = token["type"]
+ if token_type in list(tokenTypes.keys()):
+ token_type = tokenTypes[token_type]
+
+ if token_type in (tokenTypes["StartTag"], tokenTypes["EndTag"],
+ tokenTypes["EmptyTag"]):
+ if token["name"] in self.allowed_elements:
+ return self.allowed_token(token, token_type)
+ else:
+ return self.disallowed_token(token, token_type)
+ elif token_type == tokenTypes["Comment"]:
+ pass
+ else:
+ return token
+
+ def allowed_token(self, token, token_type):
+ if "data" in token:
+ attrs = dict([(name, val) for name, val in
+ token["data"][::-1]
+ if name in self.allowed_attributes])
+ for attr in self.attr_val_is_uri:
+ if attr not in attrs:
+ continue
+ val_unescaped = re.sub("[`\000-\040\177-\240\s]+", '',
+ unescape(attrs[attr])).lower()
+ # remove replacement characters from unescaped characters
+ val_unescaped = val_unescaped.replace("\ufffd", "")
+ if (re.match("^[a-z0-9][-+.a-z0-9]*:", val_unescaped) and
+ (val_unescaped.split(':')[0] not in
+ self.allowed_protocols)):
+ del attrs[attr]
+ for attr in self.svg_attr_val_allows_ref:
+ if attr in attrs:
+ attrs[attr] = re.sub(r'url\s*\(\s*[^#\s][^)]+?\)',
+ ' ',
+ unescape(attrs[attr]))
+ if (token["name"] in self.svg_allow_local_href and
+ 'xlink:href' in attrs and re.search('^\s*[^#\s].*',
+ attrs['xlink:href'])):
+ del attrs['xlink:href']
+ if 'style' in attrs:
+ attrs['style'] = self.sanitize_css(attrs['style'])
+ token["data"] = [[name, val] for name, val in list(attrs.items())]
+ return token
+
+ def disallowed_token(self, token, token_type):
+ if token_type == tokenTypes["EndTag"]:
+ token["data"] = "</%s>" % token["name"]
+ elif token["data"]:
+ attrs = ''.join([' %s="%s"' % (k, escape(v)) for k, v in token["data"]])
+ token["data"] = "<%s%s>" % (token["name"], attrs)
+ else:
+ token["data"] = "<%s>" % token["name"]
+ if token.get("selfClosing"):
+ token["data"] = token["data"][:-1] + "/>"
+
+ if token["type"] in list(tokenTypes.keys()):
+ token["type"] = "Characters"
+ else:
+ token["type"] = tokenTypes["Characters"]
+
+ del token["name"]
+ return token
+
+ def sanitize_css(self, style):
+ # disallow urls
+ style = re.compile('url\s*\(\s*[^\s)]+?\s*\)\s*').sub(' ', style)
+
+ # gauntlet
+ if not re.match("""^([:,;#%.\sa-zA-Z0-9!]|\w-\w|'[\s\w]+'|"[\s\w]+"|\([\d,\s]+\))*$""", style):
+ return ''
+ if not re.match("^\s*([-\w]+\s*:[^:;]*(;\s*|$))*$", style):
+ return ''
+
+ clean = []
+ for prop, value in re.findall("([-\w]+)\s*:\s*([^:;]*)", style):
+ if not value:
+ continue
+ if prop.lower() in self.allowed_css_properties:
+ clean.append(prop + ': ' + value + ';')
+ elif prop.split('-')[0].lower() in ['background', 'border', 'margin',
+ 'padding']:
+ for keyword in value.split():
+ if keyword not in self.acceptable_css_keywords and \
+ not re.match("^(#[0-9a-f]+|rgb\(\d+%?,\d*%?,?\d*%?\)?|\d{0,2}\.?\d{0,2}(cm|em|ex|in|mm|pc|pt|px|%|,|\))?)$", keyword):
+ break
+ else:
+ clean.append(prop + ': ' + value + ';')
+ elif prop.lower() in self.allowed_svg_properties:
+ clean.append(prop + ': ' + value + ';')
+
+ return ' '.join(clean)
+
+
+class HTMLSanitizer(HTMLTokenizer, HTMLSanitizerMixin):
+ def __init__(self, stream, encoding=None, parseMeta=True, useChardet=True,
+ lowercaseElementName=False, lowercaseAttrName=False, parser=None):
+ # Change case matching defaults as we only output lowercase html anyway
+ # This solution doesn't seem ideal...
+ HTMLTokenizer.__init__(self, stream, encoding, parseMeta, useChardet,
+ lowercaseElementName, lowercaseAttrName, parser=parser)
+
+ def __iter__(self):
+ for token in HTMLTokenizer.__iter__(self):
+ token = self.sanitize_token(token)
+ if token:
+ yield token
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/serializer/__init__.py b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/serializer/__init__.py
new file mode 100644
index 00000000000..8380839a6d3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/serializer/__init__.py
@@ -0,0 +1,16 @@
+from __future__ import absolute_import, division, unicode_literals
+
+from .. import treewalkers
+
+from .htmlserializer import HTMLSerializer
+
+
+def serialize(input, tree="etree", format="html", encoding=None,
+ **serializer_opts):
+ # XXX: Should we cache this?
+ walker = treewalkers.getTreeWalker(tree)
+ if format == "html":
+ s = HTMLSerializer(**serializer_opts)
+ else:
+ raise ValueError("type must be html")
+ return s.render(walker(input), encoding)
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/serializer/htmlserializer.py b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/serializer/htmlserializer.py
new file mode 100644
index 00000000000..4a891ff56c4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/serializer/htmlserializer.py
@@ -0,0 +1,320 @@
+from __future__ import absolute_import, division, unicode_literals
+from six import text_type
+
+import gettext
+_ = gettext.gettext
+
+try:
+ from functools import reduce
+except ImportError:
+ pass
+
+from ..constants import voidElements, booleanAttributes, spaceCharacters
+from ..constants import rcdataElements, entities, xmlEntities
+from .. import utils
+from xml.sax.saxutils import escape
+
+spaceCharacters = "".join(spaceCharacters)
+
+try:
+ from codecs import register_error, xmlcharrefreplace_errors
+except ImportError:
+ unicode_encode_errors = "strict"
+else:
+ unicode_encode_errors = "htmlentityreplace"
+
+ encode_entity_map = {}
+ is_ucs4 = len("\U0010FFFF") == 1
+ for k, v in list(entities.items()):
+ # skip multi-character entities
+ if ((is_ucs4 and len(v) > 1) or
+ (not is_ucs4 and len(v) > 2)):
+ continue
+ if v != "&":
+ if len(v) == 2:
+ v = utils.surrogatePairToCodepoint(v)
+ else:
+ v = ord(v)
+ if v not in encode_entity_map or k.islower():
+ # prefer &lt; over &LT; and similarly for &amp;, &gt;, etc.
+ encode_entity_map[v] = k
+
+ def htmlentityreplace_errors(exc):
+ if isinstance(exc, (UnicodeEncodeError, UnicodeTranslateError)):
+ res = []
+ codepoints = []
+ skip = False
+ for i, c in enumerate(exc.object[exc.start:exc.end]):
+ if skip:
+ skip = False
+ continue
+ index = i + exc.start
+ if utils.isSurrogatePair(exc.object[index:min([exc.end, index + 2])]):
+ codepoint = utils.surrogatePairToCodepoint(exc.object[index:index + 2])
+ skip = True
+ else:
+ codepoint = ord(c)
+ codepoints.append(codepoint)
+ for cp in codepoints:
+ e = encode_entity_map.get(cp)
+ if e:
+ res.append("&")
+ res.append(e)
+ if not e.endswith(";"):
+ res.append(";")
+ else:
+ res.append("&#x%s;" % (hex(cp)[2:]))
+ return ("".join(res), exc.end)
+ else:
+ return xmlcharrefreplace_errors(exc)
+
+ register_error(unicode_encode_errors, htmlentityreplace_errors)
+
+ del register_error
+
+
+class HTMLSerializer(object):
+
+ # attribute quoting options
+ quote_attr_values = False
+ quote_char = '"'
+ use_best_quote_char = True
+
+ # tag syntax options
+ omit_optional_tags = True
+ minimize_boolean_attributes = True
+ use_trailing_solidus = False
+ space_before_trailing_solidus = True
+
+ # escaping options
+ escape_lt_in_attrs = False
+ escape_rcdata = False
+ resolve_entities = True
+
+ # miscellaneous options
+ alphabetical_attributes = False
+ inject_meta_charset = True
+ strip_whitespace = False
+ sanitize = False
+
+ options = ("quote_attr_values", "quote_char", "use_best_quote_char",
+ "omit_optional_tags", "minimize_boolean_attributes",
+ "use_trailing_solidus", "space_before_trailing_solidus",
+ "escape_lt_in_attrs", "escape_rcdata", "resolve_entities",
+ "alphabetical_attributes", "inject_meta_charset",
+ "strip_whitespace", "sanitize")
+
+ def __init__(self, **kwargs):
+ """Initialize HTMLSerializer.
+
+ Keyword options (default given first unless specified) include:
+
+ inject_meta_charset=True|False
+ Whether it insert a meta element to define the character set of the
+ document.
+ quote_attr_values=True|False
+ Whether to quote attribute values that don't require quoting
+ per HTML5 parsing rules.
+ quote_char=u'"'|u"'"
+ Use given quote character for attribute quoting. Default is to
+ use double quote unless attribute value contains a double quote,
+ in which case single quotes are used instead.
+ escape_lt_in_attrs=False|True
+ Whether to escape < in attribute values.
+ escape_rcdata=False|True
+ Whether to escape characters that need to be escaped within normal
+ elements within rcdata elements such as style.
+ resolve_entities=True|False
+ Whether to resolve named character entities that appear in the
+ source tree. The XML predefined entities &lt; &gt; &amp; &quot; &apos;
+ are unaffected by this setting.
+ strip_whitespace=False|True
+ Whether to remove semantically meaningless whitespace. (This
+ compresses all whitespace to a single space except within pre.)
+ minimize_boolean_attributes=True|False
+ Shortens boolean attributes to give just the attribute value,
+ for example <input disabled="disabled"> becomes <input disabled>.
+ use_trailing_solidus=False|True
+ Includes a close-tag slash at the end of the start tag of void
+ elements (empty elements whose end tag is forbidden). E.g. <hr/>.
+ space_before_trailing_solidus=True|False
+ Places a space immediately before the closing slash in a tag
+ using a trailing solidus. E.g. <hr />. Requires use_trailing_solidus.
+ sanitize=False|True
+ Strip all unsafe or unknown constructs from output.
+ See `html5lib user documentation`_
+ omit_optional_tags=True|False
+ Omit start/end tags that are optional.
+ alphabetical_attributes=False|True
+ Reorder attributes to be in alphabetical order.
+
+ .. _html5lib user documentation: http://code.google.com/p/html5lib/wiki/UserDocumentation
+ """
+ if 'quote_char' in kwargs:
+ self.use_best_quote_char = False
+ for attr in self.options:
+ setattr(self, attr, kwargs.get(attr, getattr(self, attr)))
+ self.errors = []
+ self.strict = False
+
+ def encode(self, string):
+ assert(isinstance(string, text_type))
+ if self.encoding:
+ return string.encode(self.encoding, unicode_encode_errors)
+ else:
+ return string
+
+ def encodeStrict(self, string):
+ assert(isinstance(string, text_type))
+ if self.encoding:
+ return string.encode(self.encoding, "strict")
+ else:
+ return string
+
+ def serialize(self, treewalker, encoding=None):
+ self.encoding = encoding
+ in_cdata = False
+ self.errors = []
+
+ if encoding and self.inject_meta_charset:
+ from ..filters.inject_meta_charset import Filter
+ treewalker = Filter(treewalker, encoding)
+ # WhitespaceFilter should be used before OptionalTagFilter
+ # for maximum efficiently of this latter filter
+ if self.strip_whitespace:
+ from ..filters.whitespace import Filter
+ treewalker = Filter(treewalker)
+ if self.sanitize:
+ from ..filters.sanitizer import Filter
+ treewalker = Filter(treewalker)
+ if self.omit_optional_tags:
+ from ..filters.optionaltags import Filter
+ treewalker = Filter(treewalker)
+ # Alphabetical attributes must be last, as other filters
+ # could add attributes and alter the order
+ if self.alphabetical_attributes:
+ from ..filters.alphabeticalattributes import Filter
+ treewalker = Filter(treewalker)
+
+ for token in treewalker:
+ type = token["type"]
+ if type == "Doctype":
+ doctype = "<!DOCTYPE %s" % token["name"]
+
+ if token["publicId"]:
+ doctype += ' PUBLIC "%s"' % token["publicId"]
+ elif token["systemId"]:
+ doctype += " SYSTEM"
+ if token["systemId"]:
+ if token["systemId"].find('"') >= 0:
+ if token["systemId"].find("'") >= 0:
+ self.serializeError(_("System identifer contains both single and double quote characters"))
+ quote_char = "'"
+ else:
+ quote_char = '"'
+ doctype += " %s%s%s" % (quote_char, token["systemId"], quote_char)
+
+ doctype += ">"
+ yield self.encodeStrict(doctype)
+
+ elif type in ("Characters", "SpaceCharacters"):
+ if type == "SpaceCharacters" or in_cdata:
+ if in_cdata and token["data"].find("</") >= 0:
+ self.serializeError(_("Unexpected </ in CDATA"))
+ yield self.encode(token["data"])
+ else:
+ yield self.encode(escape(token["data"]))
+
+ elif type in ("StartTag", "EmptyTag"):
+ name = token["name"]
+ yield self.encodeStrict("<%s" % name)
+ if name in rcdataElements and not self.escape_rcdata:
+ in_cdata = True
+ elif in_cdata:
+ self.serializeError(_("Unexpected child element of a CDATA element"))
+ for (attr_namespace, attr_name), attr_value in token["data"].items():
+ # TODO: Add namespace support here
+ k = attr_name
+ v = attr_value
+ yield self.encodeStrict(' ')
+
+ yield self.encodeStrict(k)
+ if not self.minimize_boolean_attributes or \
+ (k not in booleanAttributes.get(name, tuple())
+ and k not in booleanAttributes.get("", tuple())):
+ yield self.encodeStrict("=")
+ if self.quote_attr_values or not v:
+ quote_attr = True
+ else:
+ quote_attr = reduce(lambda x, y: x or (y in v),
+ spaceCharacters + ">\"'=", False)
+ v = v.replace("&", "&amp;")
+ if self.escape_lt_in_attrs:
+ v = v.replace("<", "&lt;")
+ if quote_attr:
+ quote_char = self.quote_char
+ if self.use_best_quote_char:
+ if "'" in v and '"' not in v:
+ quote_char = '"'
+ elif '"' in v and "'" not in v:
+ quote_char = "'"
+ if quote_char == "'":
+ v = v.replace("'", "&#39;")
+ else:
+ v = v.replace('"', "&quot;")
+ yield self.encodeStrict(quote_char)
+ yield self.encode(v)
+ yield self.encodeStrict(quote_char)
+ else:
+ yield self.encode(v)
+ if name in voidElements and self.use_trailing_solidus:
+ if self.space_before_trailing_solidus:
+ yield self.encodeStrict(" /")
+ else:
+ yield self.encodeStrict("/")
+ yield self.encode(">")
+
+ elif type == "EndTag":
+ name = token["name"]
+ if name in rcdataElements:
+ in_cdata = False
+ elif in_cdata:
+ self.serializeError(_("Unexpected child element of a CDATA element"))
+ yield self.encodeStrict("</%s>" % name)
+
+ elif type == "Comment":
+ data = token["data"]
+ if data.find("--") >= 0:
+ self.serializeError(_("Comment contains --"))
+ yield self.encodeStrict("<!--%s-->" % token["data"])
+
+ elif type == "Entity":
+ name = token["name"]
+ key = name + ";"
+ if key not in entities:
+ self.serializeError(_("Entity %s not recognized" % name))
+ if self.resolve_entities and key not in xmlEntities:
+ data = entities[key]
+ else:
+ data = "&%s;" % name
+ yield self.encodeStrict(data)
+
+ else:
+ self.serializeError(token["data"])
+
+ def render(self, treewalker, encoding=None):
+ if encoding:
+ return b"".join(list(self.serialize(treewalker, encoding)))
+ else:
+ return "".join(list(self.serialize(treewalker)))
+
+ def serializeError(self, data="XXX ERROR MESSAGE NEEDED"):
+ # XXX The idea is to make data mandatory.
+ self.errors.append(data)
+ if self.strict:
+ raise SerializeError
+
+
+def SerializeError(Exception):
+ """Error in serialized tree"""
+ pass
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/README b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/README
new file mode 100644
index 00000000000..c564b6836e4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/README
@@ -0,0 +1 @@
+Each testcase file can be run through nose (using ``nosetests``). \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/__init__.py b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/__init__.py
new file mode 100644
index 00000000000..b8ce2de32e5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/__init__.py
@@ -0,0 +1 @@
+from __future__ import absolute_import, division, unicode_literals
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/mockParser.py b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/mockParser.py
new file mode 100644
index 00000000000..ef31527e82d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/mockParser.py
@@ -0,0 +1,41 @@
+from __future__ import absolute_import, division, unicode_literals
+
+import sys
+import os
+
+if __name__ == '__main__':
+ # Allow us to import from the src directory
+ os.chdir(os.path.split(os.path.abspath(__file__))[0])
+ sys.path.insert(0, os.path.abspath(os.path.join(os.pardir, "src")))
+
+from html5lib.tokenizer import HTMLTokenizer
+
+
+class HTMLParser(object):
+ """ Fake parser to test tokenizer output """
+ def parse(self, stream, output=True):
+ tokenizer = HTMLTokenizer(stream)
+ for token in tokenizer:
+ if output:
+ print(token)
+
+if __name__ == "__main__":
+ x = HTMLParser()
+ if len(sys.argv) > 1:
+ if len(sys.argv) > 2:
+ import hotshot
+ import hotshot.stats
+ prof = hotshot.Profile('stats.prof')
+ prof.runcall(x.parse, sys.argv[1], False)
+ prof.close()
+ stats = hotshot.stats.load('stats.prof')
+ stats.strip_dirs()
+ stats.sort_stats('time')
+ stats.print_stats()
+ else:
+ x.parse(sys.argv[1])
+ else:
+ print("""Usage: python mockParser.py filename [stats]
+ If stats is specified the hotshots profiler will run and output the
+ stats instead.
+ """)
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/performance/concatenation.py b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/performance/concatenation.py
new file mode 100644
index 00000000000..a1465036e52
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/performance/concatenation.py
@@ -0,0 +1,36 @@
+from __future__ import absolute_import, division, unicode_literals
+
+
+def f1():
+ x = "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ y = "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ z = "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ x += y + z
+
+
+def f2():
+ x = "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ y = "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ z = "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ x = x + y + z
+
+
+def f3():
+ x = "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ y = "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ z = "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ x = "".join((x, y, z))
+
+
+def f4():
+ x = "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ y = "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ z = "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ x = "%s%s%s" % (x, y, z)
+
+import timeit
+for x in range(4):
+ statement = "f%s" % (x + 1)
+ t = timeit.Timer(statement, "from __main__ import " + statement)
+ r = t.repeat(3, 1000000)
+ print(r, min(r))
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/support.py b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/support.py
new file mode 100644
index 00000000000..41f2d2a072d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/support.py
@@ -0,0 +1,177 @@
+from __future__ import absolute_import, division, unicode_literals
+
+import os
+import sys
+import codecs
+import glob
+import xml.sax.handler
+
+base_path = os.path.split(__file__)[0]
+
+test_dir = os.path.join(base_path, 'testdata')
+sys.path.insert(0, os.path.abspath(os.path.join(base_path,
+ os.path.pardir,
+ os.path.pardir)))
+
+from html5lib import treebuilders
+del base_path
+
+# Build a dict of avaliable trees
+treeTypes = {"DOM": treebuilders.getTreeBuilder("dom")}
+
+# Try whatever etree implementations are avaliable from a list that are
+#"supposed" to work
+try:
+ import xml.etree.ElementTree as ElementTree
+ treeTypes['ElementTree'] = treebuilders.getTreeBuilder("etree", ElementTree, fullTree=True)
+except ImportError:
+ try:
+ import elementtree.ElementTree as ElementTree
+ treeTypes['ElementTree'] = treebuilders.getTreeBuilder("etree", ElementTree, fullTree=True)
+ except ImportError:
+ pass
+
+try:
+ import xml.etree.cElementTree as cElementTree
+ treeTypes['cElementTree'] = treebuilders.getTreeBuilder("etree", cElementTree, fullTree=True)
+except ImportError:
+ try:
+ import cElementTree
+ treeTypes['cElementTree'] = treebuilders.getTreeBuilder("etree", cElementTree, fullTree=True)
+ except ImportError:
+ pass
+
+try:
+ import lxml.etree as lxml # flake8: noqa
+except ImportError:
+ pass
+else:
+ treeTypes['lxml'] = treebuilders.getTreeBuilder("lxml")
+
+
+def get_data_files(subdirectory, files='*.dat'):
+ return glob.glob(os.path.join(test_dir, subdirectory, files))
+
+
+class DefaultDict(dict):
+ def __init__(self, default, *args, **kwargs):
+ self.default = default
+ dict.__init__(self, *args, **kwargs)
+
+ def __getitem__(self, key):
+ return dict.get(self, key, self.default)
+
+
+class TestData(object):
+ def __init__(self, filename, newTestHeading="data", encoding="utf8"):
+ if encoding is None:
+ self.f = open(filename, mode="rb")
+ else:
+ self.f = codecs.open(filename, encoding=encoding)
+ self.encoding = encoding
+ self.newTestHeading = newTestHeading
+
+ def __del__(self):
+ self.f.close()
+
+ def __iter__(self):
+ data = DefaultDict(None)
+ key = None
+ for line in self.f:
+ heading = self.isSectionHeading(line)
+ if heading:
+ if data and heading == self.newTestHeading:
+ # Remove trailing newline
+ data[key] = data[key][:-1]
+ yield self.normaliseOutput(data)
+ data = DefaultDict(None)
+ key = heading
+ data[key] = "" if self.encoding else b""
+ elif key is not None:
+ data[key] += line
+ if data:
+ yield self.normaliseOutput(data)
+
+ def isSectionHeading(self, line):
+ """If the current heading is a test section heading return the heading,
+ otherwise return False"""
+ # print(line)
+ if line.startswith("#" if self.encoding else b"#"):
+ return line[1:].strip()
+ else:
+ return False
+
+ def normaliseOutput(self, data):
+ # Remove trailing newlines
+ for key, value in data.items():
+ if value.endswith("\n" if self.encoding else b"\n"):
+ data[key] = value[:-1]
+ return data
+
+
+def convert(stripChars):
+ def convertData(data):
+ """convert the output of str(document) to the format used in the testcases"""
+ data = data.split("\n")
+ rv = []
+ for line in data:
+ if line.startswith("|"):
+ rv.append(line[stripChars:])
+ else:
+ rv.append(line)
+ return "\n".join(rv)
+ return convertData
+
+convertExpected = convert(2)
+
+
+def errorMessage(input, expected, actual):
+ msg = ("Input:\n%s\nExpected:\n%s\nRecieved\n%s\n" %
+ (repr(input), repr(expected), repr(actual)))
+ if sys.version_info.major == 2:
+ msg = msg.encode("ascii", "backslashreplace")
+ return msg
+
+
+class TracingSaxHandler(xml.sax.handler.ContentHandler):
+ def __init__(self):
+ xml.sax.handler.ContentHandler.__init__(self)
+ self.visited = []
+
+ def startDocument(self):
+ self.visited.append('startDocument')
+
+ def endDocument(self):
+ self.visited.append('endDocument')
+
+ def startPrefixMapping(self, prefix, uri):
+ # These are ignored as their order is not guaranteed
+ pass
+
+ def endPrefixMapping(self, prefix):
+ # These are ignored as their order is not guaranteed
+ pass
+
+ def startElement(self, name, attrs):
+ self.visited.append(('startElement', name, attrs))
+
+ def endElement(self, name):
+ self.visited.append(('endElement', name))
+
+ def startElementNS(self, name, qname, attrs):
+ self.visited.append(('startElementNS', name, qname, dict(attrs)))
+
+ def endElementNS(self, name, qname):
+ self.visited.append(('endElementNS', name, qname))
+
+ def characters(self, content):
+ self.visited.append(('characters', content))
+
+ def ignorableWhitespace(self, whitespace):
+ self.visited.append(('ignorableWhitespace', whitespace))
+
+ def processingInstruction(self, target, data):
+ self.visited.append(('processingInstruction', target, data))
+
+ def skippedEntity(self, name):
+ self.visited.append(('skippedEntity', name))
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/test_encoding.py b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/test_encoding.py
new file mode 100644
index 00000000000..d774ce0f600
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/test_encoding.py
@@ -0,0 +1,67 @@
+from __future__ import absolute_import, division, unicode_literals
+
+import os
+import unittest
+
+try:
+ unittest.TestCase.assertEqual
+except AttributeError:
+ unittest.TestCase.assertEqual = unittest.TestCase.assertEquals
+
+from .support import get_data_files, TestData, test_dir, errorMessage
+from html5lib import HTMLParser, inputstream
+
+
+class Html5EncodingTestCase(unittest.TestCase):
+ def test_codec_name_a(self):
+ self.assertEqual(inputstream.codecName("utf-8"), "utf-8")
+
+ def test_codec_name_b(self):
+ self.assertEqual(inputstream.codecName("utf8"), "utf-8")
+
+ def test_codec_name_c(self):
+ self.assertEqual(inputstream.codecName(" utf8 "), "utf-8")
+
+ def test_codec_name_d(self):
+ self.assertEqual(inputstream.codecName("ISO_8859--1"), "windows-1252")
+
+
+def runParserEncodingTest(data, encoding):
+ p = HTMLParser()
+ assert p.documentEncoding is None
+ p.parse(data, useChardet=False)
+ encoding = encoding.lower().decode("ascii")
+
+ assert encoding == p.documentEncoding, errorMessage(data, encoding, p.documentEncoding)
+
+
+def runPreScanEncodingTest(data, encoding):
+ stream = inputstream.HTMLBinaryInputStream(data, chardet=False)
+ encoding = encoding.lower().decode("ascii")
+
+ # Very crude way to ignore irrelevant tests
+ if len(data) > stream.numBytesMeta:
+ return
+
+ assert encoding == stream.charEncoding[0], errorMessage(data, encoding, stream.charEncoding[0])
+
+
+def test_encoding():
+ for filename in get_data_files("encoding"):
+ tests = TestData(filename, b"data", encoding=None)
+ for idx, test in enumerate(tests):
+ yield (runParserEncodingTest, test[b'data'], test[b'encoding'])
+ yield (runPreScanEncodingTest, test[b'data'], test[b'encoding'])
+
+try:
+ try:
+ import charade # flake8: noqa
+ except ImportError:
+ import chardet # flake8: noqa
+except ImportError:
+ print("charade/chardet not found, skipping chardet tests")
+else:
+ def test_chardet():
+ with open(os.path.join(test_dir, "encoding" , "chardet", "test_big5.txt"), "rb") as fp:
+ encoding = inputstream.HTMLInputStream(fp.read()).charEncoding
+ assert encoding[0].lower() == "big5"
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/test_parser.py b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/test_parser.py
new file mode 100644
index 00000000000..230cdb42d59
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/test_parser.py
@@ -0,0 +1,96 @@
+from __future__ import absolute_import, division, unicode_literals
+
+import os
+import sys
+import traceback
+import warnings
+import re
+
+warnings.simplefilter("error")
+
+from .support import get_data_files
+from .support import TestData, convert, convertExpected, treeTypes
+from html5lib import html5parser, constants
+
+# Run the parse error checks
+checkParseErrors = False
+
+# XXX - There should just be one function here but for some reason the testcase
+# format differs from the treedump format by a single space character
+
+
+def convertTreeDump(data):
+ return "\n".join(convert(3)(data).split("\n")[1:])
+
+namespaceExpected = re.compile(r"^(\s*)<(\S+)>", re.M).sub
+
+
+def runParserTest(innerHTML, input, expected, errors, treeClass,
+ namespaceHTMLElements):
+ with warnings.catch_warnings(record=True) as caughtWarnings:
+ warnings.simplefilter("always")
+ p = html5parser.HTMLParser(tree=treeClass,
+ namespaceHTMLElements=namespaceHTMLElements)
+
+ try:
+ if innerHTML:
+ document = p.parseFragment(input, innerHTML)
+ else:
+ document = p.parse(input)
+ except:
+ errorMsg = "\n".join(["\n\nInput:", input, "\nExpected:", expected,
+ "\nTraceback:", traceback.format_exc()])
+ assert False, errorMsg
+
+ otherWarnings = [x for x in caughtWarnings
+ if not issubclass(x.category, constants.DataLossWarning)]
+ assert len(otherWarnings) == 0, [(x.category, x.message) for x in otherWarnings]
+ if len(caughtWarnings):
+ return
+
+ output = convertTreeDump(p.tree.testSerializer(document))
+
+ expected = convertExpected(expected)
+ if namespaceHTMLElements:
+ expected = namespaceExpected(r"\1<html \2>", expected)
+
+ errorMsg = "\n".join(["\n\nInput:", input, "\nExpected:", expected,
+ "\nReceived:", output])
+ assert expected == output, errorMsg
+
+ errStr = []
+ for (line, col), errorcode, datavars in p.errors:
+ assert isinstance(datavars, dict), "%s, %s" % (errorcode, repr(datavars))
+ errStr.append("Line: %i Col: %i %s" % (line, col,
+ constants.E[errorcode] % datavars))
+
+ errorMsg2 = "\n".join(["\n\nInput:", input,
+ "\nExpected errors (" + str(len(errors)) + "):\n" + "\n".join(errors),
+ "\nActual errors (" + str(len(p.errors)) + "):\n" + "\n".join(errStr)])
+ if checkParseErrors:
+ assert len(p.errors) == len(errors), errorMsg2
+
+
+def test_parser():
+ sys.stderr.write('Testing tree builders ' + " ".join(list(treeTypes.keys())) + "\n")
+ files = get_data_files('tree-construction')
+
+ for filename in files:
+ testName = os.path.basename(filename).replace(".dat", "")
+ if testName in ("template",):
+ continue
+
+ tests = TestData(filename, "data")
+
+ for index, test in enumerate(tests):
+ input, errors, innerHTML, expected = [test[key] for key in
+ ('data', 'errors',
+ 'document-fragment',
+ 'document')]
+ if errors:
+ errors = errors.split("\n")
+
+ for treeName, treeCls in treeTypes.items():
+ for namespaceHTMLElements in (True, False):
+ yield (runParserTest, innerHTML, input, expected, errors, treeCls,
+ namespaceHTMLElements)
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/test_parser2.py b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/test_parser2.py
new file mode 100644
index 00000000000..20bbdf3179c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/test_parser2.py
@@ -0,0 +1,64 @@
+from __future__ import absolute_import, division, unicode_literals
+
+import io
+
+from . import support # flake8: noqa
+from html5lib import html5parser
+from html5lib.constants import namespaces
+from html5lib import treebuilders
+
+import unittest
+
+# tests that aren't autogenerated from text files
+
+
+class MoreParserTests(unittest.TestCase):
+
+ def setUp(self):
+ self.dom_tree = treebuilders.getTreeBuilder("dom")
+
+ def test_assertDoctypeCloneable(self):
+ parser = html5parser.HTMLParser(tree=self.dom_tree)
+ doc = parser.parse('<!DOCTYPE HTML>')
+ self.assertTrue(doc.cloneNode(True))
+
+ def test_line_counter(self):
+ # http://groups.google.com/group/html5lib-discuss/browse_frm/thread/f4f00e4a2f26d5c0
+ parser = html5parser.HTMLParser(tree=self.dom_tree)
+ parser.parse("<pre>\nx\n&gt;\n</pre>")
+
+ def test_namespace_html_elements_0_dom(self):
+ parser = html5parser.HTMLParser(tree=self.dom_tree, namespaceHTMLElements=True)
+ doc = parser.parse("<html></html>")
+ self.assertTrue(doc.childNodes[0].namespaceURI == namespaces["html"])
+
+ def test_namespace_html_elements_1_dom(self):
+ parser = html5parser.HTMLParser(tree=self.dom_tree, namespaceHTMLElements=False)
+ doc = parser.parse("<html></html>")
+ self.assertTrue(doc.childNodes[0].namespaceURI is None)
+
+ def test_namespace_html_elements_0_etree(self):
+ parser = html5parser.HTMLParser(namespaceHTMLElements=True)
+ doc = parser.parse("<html></html>")
+ self.assertTrue(list(doc)[0].tag == "{%s}html" % (namespaces["html"],))
+
+ def test_namespace_html_elements_1_etree(self):
+ parser = html5parser.HTMLParser(namespaceHTMLElements=False)
+ doc = parser.parse("<html></html>")
+ self.assertTrue(list(doc)[0].tag == "html")
+
+ def test_unicode_file(self):
+ parser = html5parser.HTMLParser()
+ parser.parse(io.StringIO("a"))
+
+
+def buildTestSuite():
+ return unittest.defaultTestLoader.loadTestsFromName(__name__)
+
+
+def main():
+ buildTestSuite()
+ unittest.main()
+
+if __name__ == '__main__':
+ main()
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/test_sanitizer.py b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/test_sanitizer.py
new file mode 100644
index 00000000000..1cc687dfcad
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/test_sanitizer.py
@@ -0,0 +1,105 @@
+from __future__ import absolute_import, division, unicode_literals
+
+try:
+ import json
+except ImportError:
+ import simplejson as json
+
+from html5lib import html5parser, sanitizer, constants, treebuilders
+
+
+def toxmlFactory():
+ tree = treebuilders.getTreeBuilder("etree")
+
+ def toxml(element):
+ # encode/decode roundtrip required for Python 2.6 compatibility
+ result_bytes = tree.implementation.tostring(element, encoding="utf-8")
+ return result_bytes.decode("utf-8")
+
+ return toxml
+
+
+def runSanitizerTest(name, expected, input, toxml=None):
+ if toxml is None:
+ toxml = toxmlFactory()
+ expected = ''.join([toxml(token) for token in html5parser.HTMLParser().
+ parseFragment(expected)])
+ expected = json.loads(json.dumps(expected))
+ assert expected == sanitize_html(input)
+
+
+def sanitize_html(stream, toxml=None):
+ if toxml is None:
+ toxml = toxmlFactory()
+ return ''.join([toxml(token) for token in
+ html5parser.HTMLParser(tokenizer=sanitizer.HTMLSanitizer).
+ parseFragment(stream)])
+
+
+def test_should_handle_astral_plane_characters():
+ assert '<html:p xmlns:html="http://www.w3.org/1999/xhtml">\U0001d4b5 \U0001d538</html:p>' == sanitize_html("<p>&#x1d4b5; &#x1d538;</p>")
+
+
+def test_sanitizer():
+ toxml = toxmlFactory()
+ for tag_name in sanitizer.HTMLSanitizer.allowed_elements:
+ if tag_name in ['caption', 'col', 'colgroup', 'optgroup', 'option', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr']:
+ continue # TODO
+ if tag_name != tag_name.lower():
+ continue # TODO
+ if tag_name == 'image':
+ yield (runSanitizerTest, "test_should_allow_%s_tag" % tag_name,
+ "<img title=\"1\"/>foo &lt;bad&gt;bar&lt;/bad&gt; baz",
+ "<%s title='1'>foo <bad>bar</bad> baz</%s>" % (tag_name, tag_name),
+ toxml)
+ elif tag_name == 'br':
+ yield (runSanitizerTest, "test_should_allow_%s_tag" % tag_name,
+ "<br title=\"1\"/>foo &lt;bad&gt;bar&lt;/bad&gt; baz<br/>",
+ "<%s title='1'>foo <bad>bar</bad> baz</%s>" % (tag_name, tag_name),
+ toxml)
+ elif tag_name in constants.voidElements:
+ yield (runSanitizerTest, "test_should_allow_%s_tag" % tag_name,
+ "<%s title=\"1\"/>foo &lt;bad&gt;bar&lt;/bad&gt; baz" % tag_name,
+ "<%s title='1'>foo <bad>bar</bad> baz</%s>" % (tag_name, tag_name),
+ toxml)
+ else:
+ yield (runSanitizerTest, "test_should_allow_%s_tag" % tag_name,
+ "<%s title=\"1\">foo &lt;bad&gt;bar&lt;/bad&gt; baz</%s>" % (tag_name, tag_name),
+ "<%s title='1'>foo <bad>bar</bad> baz</%s>" % (tag_name, tag_name),
+ toxml)
+
+ for tag_name in sanitizer.HTMLSanitizer.allowed_elements:
+ tag_name = tag_name.upper()
+ yield (runSanitizerTest, "test_should_forbid_%s_tag" % tag_name,
+ "&lt;%s title=\"1\"&gt;foo &lt;bad&gt;bar&lt;/bad&gt; baz&lt;/%s&gt;" % (tag_name, tag_name),
+ "<%s title='1'>foo <bad>bar</bad> baz</%s>" % (tag_name, tag_name),
+ toxml)
+
+ for attribute_name in sanitizer.HTMLSanitizer.allowed_attributes:
+ if attribute_name != attribute_name.lower():
+ continue # TODO
+ if attribute_name == 'style':
+ continue
+ yield (runSanitizerTest, "test_should_allow_%s_attribute" % attribute_name,
+ "<p %s=\"foo\">foo &lt;bad&gt;bar&lt;/bad&gt; baz</p>" % attribute_name,
+ "<p %s='foo'>foo <bad>bar</bad> baz</p>" % attribute_name,
+ toxml)
+
+ for attribute_name in sanitizer.HTMLSanitizer.allowed_attributes:
+ attribute_name = attribute_name.upper()
+ yield (runSanitizerTest, "test_should_forbid_%s_attribute" % attribute_name,
+ "<p>foo &lt;bad&gt;bar&lt;/bad&gt; baz</p>",
+ "<p %s='display: none;'>foo <bad>bar</bad> baz</p>" % attribute_name,
+ toxml)
+
+ for protocol in sanitizer.HTMLSanitizer.allowed_protocols:
+ yield (runSanitizerTest, "test_should_allow_%s_uris" % protocol,
+ "<a href=\"%s\">foo</a>" % protocol,
+ """<a href="%s">foo</a>""" % protocol,
+ toxml)
+
+ for protocol in sanitizer.HTMLSanitizer.allowed_protocols:
+ yield (runSanitizerTest, "test_should_allow_uppercase_%s_uris" % protocol,
+ "<a href=\"%s\">foo</a>" % protocol,
+ """<a href="%s">foo</a>""" % protocol,
+ toxml)
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/test_serializer.py b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/test_serializer.py
new file mode 100644
index 00000000000..3c37feff70b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/test_serializer.py
@@ -0,0 +1,178 @@
+from __future__ import absolute_import, division, unicode_literals
+
+import json
+import unittest
+
+from .support import get_data_files
+
+try:
+ unittest.TestCase.assertEqual
+except AttributeError:
+ unittest.TestCase.assertEqual = unittest.TestCase.assertEquals
+
+import html5lib
+from html5lib import constants
+from html5lib.serializer import HTMLSerializer, serialize
+from html5lib.treewalkers._base import TreeWalker
+
+optionals_loaded = []
+
+try:
+ from lxml import etree
+ optionals_loaded.append("lxml")
+except ImportError:
+ pass
+
+default_namespace = constants.namespaces["html"]
+
+
+class JsonWalker(TreeWalker):
+ def __iter__(self):
+ for token in self.tree:
+ type = token[0]
+ if type == "StartTag":
+ if len(token) == 4:
+ namespace, name, attrib = token[1:4]
+ else:
+ namespace = default_namespace
+ name, attrib = token[1:3]
+ yield self.startTag(namespace, name, self._convertAttrib(attrib))
+ elif type == "EndTag":
+ if len(token) == 3:
+ namespace, name = token[1:3]
+ else:
+ namespace = default_namespace
+ name = token[1]
+ yield self.endTag(namespace, name)
+ elif type == "EmptyTag":
+ if len(token) == 4:
+ namespace, name, attrib = token[1:]
+ else:
+ namespace = default_namespace
+ name, attrib = token[1:]
+ for token in self.emptyTag(namespace, name, self._convertAttrib(attrib)):
+ yield token
+ elif type == "Comment":
+ yield self.comment(token[1])
+ elif type in ("Characters", "SpaceCharacters"):
+ for token in self.text(token[1]):
+ yield token
+ elif type == "Doctype":
+ if len(token) == 4:
+ yield self.doctype(token[1], token[2], token[3])
+ elif len(token) == 3:
+ yield self.doctype(token[1], token[2])
+ else:
+ yield self.doctype(token[1])
+ else:
+ raise ValueError("Unknown token type: " + type)
+
+ def _convertAttrib(self, attribs):
+ """html5lib tree-walkers use a dict of (namespace, name): value for
+ attributes, but JSON cannot represent this. Convert from the format
+ in the serializer tests (a list of dicts with "namespace", "name",
+ and "value" as keys) to html5lib's tree-walker format."""
+ attrs = {}
+ for attrib in attribs:
+ name = (attrib["namespace"], attrib["name"])
+ assert(name not in attrs)
+ attrs[name] = attrib["value"]
+ return attrs
+
+
+def serialize_html(input, options):
+ options = dict([(str(k), v) for k, v in options.items()])
+ stream = JsonWalker(input)
+ serializer = HTMLSerializer(alphabetical_attributes=True, **options)
+ return serializer.render(stream, options.get("encoding", None))
+
+
+def runSerializerTest(input, expected, options):
+ encoding = options.get("encoding", None)
+
+ if encoding:
+ encode = lambda x: x.encode(encoding)
+ expected = list(map(encode, expected))
+
+ result = serialize_html(input, options)
+ if len(expected) == 1:
+ assert expected[0] == result, "Expected:\n%s\nActual:\n%s\nOptions:\n%s" % (expected[0], result, str(options))
+ elif result not in expected:
+ assert False, "Expected: %s, Received: %s" % (expected, result)
+
+
+class EncodingTestCase(unittest.TestCase):
+ def throwsWithLatin1(self, input):
+ self.assertRaises(UnicodeEncodeError, serialize_html, input, {"encoding": "iso-8859-1"})
+
+ def testDoctypeName(self):
+ self.throwsWithLatin1([["Doctype", "\u0101"]])
+
+ def testDoctypePublicId(self):
+ self.throwsWithLatin1([["Doctype", "potato", "\u0101"]])
+
+ def testDoctypeSystemId(self):
+ self.throwsWithLatin1([["Doctype", "potato", "potato", "\u0101"]])
+
+ def testCdataCharacters(self):
+ runSerializerTest([["StartTag", "http://www.w3.org/1999/xhtml", "style", {}], ["Characters", "\u0101"]],
+ ["<style>&amacr;"], {"encoding": "iso-8859-1"})
+
+ def testCharacters(self):
+ runSerializerTest([["Characters", "\u0101"]],
+ ["&amacr;"], {"encoding": "iso-8859-1"})
+
+ def testStartTagName(self):
+ self.throwsWithLatin1([["StartTag", "http://www.w3.org/1999/xhtml", "\u0101", []]])
+
+ def testEmptyTagName(self):
+ self.throwsWithLatin1([["EmptyTag", "http://www.w3.org/1999/xhtml", "\u0101", []]])
+
+ def testAttributeName(self):
+ self.throwsWithLatin1([["StartTag", "http://www.w3.org/1999/xhtml", "span", [{"namespace": None, "name": "\u0101", "value": "potato"}]]])
+
+ def testAttributeValue(self):
+ runSerializerTest([["StartTag", "http://www.w3.org/1999/xhtml", "span",
+ [{"namespace": None, "name": "potato", "value": "\u0101"}]]],
+ ["<span potato=&amacr;>"], {"encoding": "iso-8859-1"})
+
+ def testEndTagName(self):
+ self.throwsWithLatin1([["EndTag", "http://www.w3.org/1999/xhtml", "\u0101"]])
+
+ def testComment(self):
+ self.throwsWithLatin1([["Comment", "\u0101"]])
+
+
+if "lxml" in optionals_loaded:
+ class LxmlTestCase(unittest.TestCase):
+ def setUp(self):
+ self.parser = etree.XMLParser(resolve_entities=False)
+ self.treewalker = html5lib.getTreeWalker("lxml")
+ self.serializer = HTMLSerializer()
+
+ def testEntityReplacement(self):
+ doc = """<!DOCTYPE html SYSTEM "about:legacy-compat"><html>&beta;</html>"""
+ tree = etree.fromstring(doc, parser=self.parser).getroottree()
+ result = serialize(tree, tree="lxml", omit_optional_tags=False)
+ self.assertEqual("""<!DOCTYPE html SYSTEM "about:legacy-compat"><html>\u03B2</html>""", result)
+
+ def testEntityXML(self):
+ doc = """<!DOCTYPE html SYSTEM "about:legacy-compat"><html>&gt;</html>"""
+ tree = etree.fromstring(doc, parser=self.parser).getroottree()
+ result = serialize(tree, tree="lxml", omit_optional_tags=False)
+ self.assertEqual("""<!DOCTYPE html SYSTEM "about:legacy-compat"><html>&gt;</html>""", result)
+
+ def testEntityNoResolve(self):
+ doc = """<!DOCTYPE html SYSTEM "about:legacy-compat"><html>&beta;</html>"""
+ tree = etree.fromstring(doc, parser=self.parser).getroottree()
+ result = serialize(tree, tree="lxml", omit_optional_tags=False,
+ resolve_entities=False)
+ self.assertEqual("""<!DOCTYPE html SYSTEM "about:legacy-compat"><html>&beta;</html>""", result)
+
+
+def test_serializer():
+ for filename in get_data_files('serializer', '*.test'):
+ with open(filename) as fp:
+ tests = json.load(fp)
+ for index, test in enumerate(tests['tests']):
+ yield runSerializerTest, test["input"], test["expected"], test.get("options", {})
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/test_stream.py b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/test_stream.py
new file mode 100644
index 00000000000..2a876c1dbfd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/test_stream.py
@@ -0,0 +1,183 @@
+from __future__ import absolute_import, division, unicode_literals
+
+from . import support # flake8: noqa
+import unittest
+import codecs
+from io import BytesIO
+
+from six.moves import http_client
+
+from html5lib.inputstream import (BufferedStream, HTMLInputStream,
+ HTMLUnicodeInputStream, HTMLBinaryInputStream)
+
+class BufferedStreamTest(unittest.TestCase):
+ def test_basic(self):
+ s = b"abc"
+ fp = BufferedStream(BytesIO(s))
+ read = fp.read(10)
+ assert read == s
+
+ def test_read_length(self):
+ fp = BufferedStream(BytesIO(b"abcdef"))
+ read1 = fp.read(1)
+ assert read1 == b"a"
+ read2 = fp.read(2)
+ assert read2 == b"bc"
+ read3 = fp.read(3)
+ assert read3 == b"def"
+ read4 = fp.read(4)
+ assert read4 == b""
+
+ def test_tell(self):
+ fp = BufferedStream(BytesIO(b"abcdef"))
+ read1 = fp.read(1)
+ assert fp.tell() == 1
+ read2 = fp.read(2)
+ assert fp.tell() == 3
+ read3 = fp.read(3)
+ assert fp.tell() == 6
+ read4 = fp.read(4)
+ assert fp.tell() == 6
+
+ def test_seek(self):
+ fp = BufferedStream(BytesIO(b"abcdef"))
+ read1 = fp.read(1)
+ assert read1 == b"a"
+ fp.seek(0)
+ read2 = fp.read(1)
+ assert read2 == b"a"
+ read3 = fp.read(2)
+ assert read3 == b"bc"
+ fp.seek(2)
+ read4 = fp.read(2)
+ assert read4 == b"cd"
+ fp.seek(4)
+ read5 = fp.read(2)
+ assert read5 == b"ef"
+
+ def test_seek_tell(self):
+ fp = BufferedStream(BytesIO(b"abcdef"))
+ read1 = fp.read(1)
+ assert fp.tell() == 1
+ fp.seek(0)
+ read2 = fp.read(1)
+ assert fp.tell() == 1
+ read3 = fp.read(2)
+ assert fp.tell() == 3
+ fp.seek(2)
+ read4 = fp.read(2)
+ assert fp.tell() == 4
+ fp.seek(4)
+ read5 = fp.read(2)
+ assert fp.tell() == 6
+
+
+class HTMLUnicodeInputStreamShortChunk(HTMLUnicodeInputStream):
+ _defaultChunkSize = 2
+
+
+class HTMLBinaryInputStreamShortChunk(HTMLBinaryInputStream):
+ _defaultChunkSize = 2
+
+
+class HTMLInputStreamTest(unittest.TestCase):
+
+ def test_char_ascii(self):
+ stream = HTMLInputStream(b"'", encoding='ascii')
+ self.assertEqual(stream.charEncoding[0], 'ascii')
+ self.assertEqual(stream.char(), "'")
+
+ def test_char_utf8(self):
+ stream = HTMLInputStream('\u2018'.encode('utf-8'), encoding='utf-8')
+ self.assertEqual(stream.charEncoding[0], 'utf-8')
+ self.assertEqual(stream.char(), '\u2018')
+
+ def test_char_win1252(self):
+ stream = HTMLInputStream("\xa9\xf1\u2019".encode('windows-1252'))
+ self.assertEqual(stream.charEncoding[0], 'windows-1252')
+ self.assertEqual(stream.char(), "\xa9")
+ self.assertEqual(stream.char(), "\xf1")
+ self.assertEqual(stream.char(), "\u2019")
+
+ def test_bom(self):
+ stream = HTMLInputStream(codecs.BOM_UTF8 + b"'")
+ self.assertEqual(stream.charEncoding[0], 'utf-8')
+ self.assertEqual(stream.char(), "'")
+
+ def test_utf_16(self):
+ stream = HTMLInputStream((' ' * 1025).encode('utf-16'))
+ self.assertTrue(stream.charEncoding[0] in ['utf-16-le', 'utf-16-be'], stream.charEncoding)
+ self.assertEqual(len(stream.charsUntil(' ', True)), 1025)
+
+ def test_newlines(self):
+ stream = HTMLBinaryInputStreamShortChunk(codecs.BOM_UTF8 + b"a\nbb\r\nccc\rddddxe")
+ self.assertEqual(stream.position(), (1, 0))
+ self.assertEqual(stream.charsUntil('c'), "a\nbb\n")
+ self.assertEqual(stream.position(), (3, 0))
+ self.assertEqual(stream.charsUntil('x'), "ccc\ndddd")
+ self.assertEqual(stream.position(), (4, 4))
+ self.assertEqual(stream.charsUntil('e'), "x")
+ self.assertEqual(stream.position(), (4, 5))
+
+ def test_newlines2(self):
+ size = HTMLUnicodeInputStream._defaultChunkSize
+ stream = HTMLInputStream("\r" * size + "\n")
+ self.assertEqual(stream.charsUntil('x'), "\n" * size)
+
+ def test_position(self):
+ stream = HTMLBinaryInputStreamShortChunk(codecs.BOM_UTF8 + b"a\nbb\nccc\nddde\nf\ngh")
+ self.assertEqual(stream.position(), (1, 0))
+ self.assertEqual(stream.charsUntil('c'), "a\nbb\n")
+ self.assertEqual(stream.position(), (3, 0))
+ stream.unget("\n")
+ self.assertEqual(stream.position(), (2, 2))
+ self.assertEqual(stream.charsUntil('c'), "\n")
+ self.assertEqual(stream.position(), (3, 0))
+ stream.unget("\n")
+ self.assertEqual(stream.position(), (2, 2))
+ self.assertEqual(stream.char(), "\n")
+ self.assertEqual(stream.position(), (3, 0))
+ self.assertEqual(stream.charsUntil('e'), "ccc\nddd")
+ self.assertEqual(stream.position(), (4, 3))
+ self.assertEqual(stream.charsUntil('h'), "e\nf\ng")
+ self.assertEqual(stream.position(), (6, 1))
+
+ def test_position2(self):
+ stream = HTMLUnicodeInputStreamShortChunk("abc\nd")
+ self.assertEqual(stream.position(), (1, 0))
+ self.assertEqual(stream.char(), "a")
+ self.assertEqual(stream.position(), (1, 1))
+ self.assertEqual(stream.char(), "b")
+ self.assertEqual(stream.position(), (1, 2))
+ self.assertEqual(stream.char(), "c")
+ self.assertEqual(stream.position(), (1, 3))
+ self.assertEqual(stream.char(), "\n")
+ self.assertEqual(stream.position(), (2, 0))
+ self.assertEqual(stream.char(), "d")
+ self.assertEqual(stream.position(), (2, 1))
+
+ def test_python_issue_20007(self):
+ """
+ Make sure we have a work-around for Python bug #20007
+ http://bugs.python.org/issue20007
+ """
+ class FakeSocket(object):
+ def makefile(self, _mode, _bufsize=None):
+ return BytesIO(b"HTTP/1.1 200 Ok\r\n\r\nText")
+
+ source = http_client.HTTPResponse(FakeSocket())
+ source.begin()
+ stream = HTMLInputStream(source)
+ self.assertEqual(stream.charsUntil(" "), "Text")
+
+
+def buildTestSuite():
+ return unittest.defaultTestLoader.loadTestsFromName(__name__)
+
+
+def main():
+ buildTestSuite()
+ unittest.main()
+
+if __name__ == '__main__':
+ main()
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/test_tokenizer.py b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/test_tokenizer.py
new file mode 100644
index 00000000000..90315ab35d2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/test_tokenizer.py
@@ -0,0 +1,188 @@
+from __future__ import absolute_import, division, unicode_literals
+
+import json
+import warnings
+import re
+
+from .support import get_data_files
+
+from html5lib.tokenizer import HTMLTokenizer
+from html5lib import constants
+
+
+class TokenizerTestParser(object):
+ def __init__(self, initialState, lastStartTag=None):
+ self.tokenizer = HTMLTokenizer
+ self._state = initialState
+ self._lastStartTag = lastStartTag
+
+ def parse(self, stream, encoding=None, innerHTML=False):
+ tokenizer = self.tokenizer(stream, encoding)
+ self.outputTokens = []
+
+ tokenizer.state = getattr(tokenizer, self._state)
+ if self._lastStartTag is not None:
+ tokenizer.currentToken = {"type": "startTag",
+ "name": self._lastStartTag}
+
+ types = dict((v, k) for k, v in constants.tokenTypes.items())
+ for token in tokenizer:
+ getattr(self, 'process%s' % types[token["type"]])(token)
+
+ return self.outputTokens
+
+ def processDoctype(self, token):
+ self.outputTokens.append(["DOCTYPE", token["name"], token["publicId"],
+ token["systemId"], token["correct"]])
+
+ def processStartTag(self, token):
+ self.outputTokens.append(["StartTag", token["name"],
+ dict(token["data"][::-1]), token["selfClosing"]])
+
+ def processEmptyTag(self, token):
+ if token["name"] not in constants.voidElements:
+ self.outputTokens.append("ParseError")
+ self.outputTokens.append(["StartTag", token["name"], dict(token["data"][::-1])])
+
+ def processEndTag(self, token):
+ self.outputTokens.append(["EndTag", token["name"],
+ token["selfClosing"]])
+
+ def processComment(self, token):
+ self.outputTokens.append(["Comment", token["data"]])
+
+ def processSpaceCharacters(self, token):
+ self.outputTokens.append(["Character", token["data"]])
+ self.processSpaceCharacters = self.processCharacters
+
+ def processCharacters(self, token):
+ self.outputTokens.append(["Character", token["data"]])
+
+ def processEOF(self, token):
+ pass
+
+ def processParseError(self, token):
+ self.outputTokens.append(["ParseError", token["data"]])
+
+
+def concatenateCharacterTokens(tokens):
+ outputTokens = []
+ for token in tokens:
+ if "ParseError" not in token and token[0] == "Character":
+ if (outputTokens and "ParseError" not in outputTokens[-1] and
+ outputTokens[-1][0] == "Character"):
+ outputTokens[-1][1] += token[1]
+ else:
+ outputTokens.append(token)
+ else:
+ outputTokens.append(token)
+ return outputTokens
+
+
+def normalizeTokens(tokens):
+ # TODO: convert tests to reflect arrays
+ for i, token in enumerate(tokens):
+ if token[0] == 'ParseError':
+ tokens[i] = token[0]
+ return tokens
+
+
+def tokensMatch(expectedTokens, receivedTokens, ignoreErrorOrder,
+ ignoreErrors=False):
+ """Test whether the test has passed or failed
+
+ If the ignoreErrorOrder flag is set to true we don't test the relative
+ positions of parse errors and non parse errors
+ """
+ checkSelfClosing = False
+ for token in expectedTokens:
+ if (token[0] == "StartTag" and len(token) == 4
+ or token[0] == "EndTag" and len(token) == 3):
+ checkSelfClosing = True
+ break
+
+ if not checkSelfClosing:
+ for token in receivedTokens:
+ if token[0] == "StartTag" or token[0] == "EndTag":
+ token.pop()
+
+ if not ignoreErrorOrder and not ignoreErrors:
+ return expectedTokens == receivedTokens
+ else:
+ # Sort the tokens into two groups; non-parse errors and parse errors
+ tokens = {"expected": [[], []], "received": [[], []]}
+ for tokenType, tokenList in zip(list(tokens.keys()),
+ (expectedTokens, receivedTokens)):
+ for token in tokenList:
+ if token != "ParseError":
+ tokens[tokenType][0].append(token)
+ else:
+ if not ignoreErrors:
+ tokens[tokenType][1].append(token)
+ return tokens["expected"] == tokens["received"]
+
+
+def unescape(test):
+ def decode(inp):
+ return inp.encode("utf-8").decode("unicode-escape")
+
+ test["input"] = decode(test["input"])
+ for token in test["output"]:
+ if token == "ParseError":
+ continue
+ else:
+ token[1] = decode(token[1])
+ if len(token) > 2:
+ for key, value in token[2]:
+ del token[2][key]
+ token[2][decode(key)] = decode(value)
+ return test
+
+
+def runTokenizerTest(test):
+ warnings.resetwarnings()
+ warnings.simplefilter("error")
+
+ expected = concatenateCharacterTokens(test['output'])
+ if 'lastStartTag' not in test:
+ test['lastStartTag'] = None
+ parser = TokenizerTestParser(test['initialState'],
+ test['lastStartTag'])
+ tokens = parser.parse(test['input'])
+ tokens = concatenateCharacterTokens(tokens)
+ received = normalizeTokens(tokens)
+ errorMsg = "\n".join(["\n\nInitial state:",
+ test['initialState'],
+ "\nInput:", test['input'],
+ "\nExpected:", repr(expected),
+ "\nreceived:", repr(tokens)])
+ errorMsg = errorMsg
+ ignoreErrorOrder = test.get('ignoreErrorOrder', False)
+ assert tokensMatch(expected, received, ignoreErrorOrder, True), errorMsg
+
+
+def _doCapitalize(match):
+ return match.group(1).upper()
+
+_capitalizeRe = re.compile(r"\W+(\w)").sub
+
+
+def capitalize(s):
+ s = s.lower()
+ s = _capitalizeRe(_doCapitalize, s)
+ return s
+
+
+def testTokenizer():
+ for filename in get_data_files('tokenizer', '*.test'):
+ with open(filename) as fp:
+ tests = json.load(fp)
+ if 'tests' in tests:
+ for index, test in enumerate(tests['tests']):
+ if 'initialStates' not in test:
+ test["initialStates"] = ["Data state"]
+ if 'doubleEscaped' in test:
+ test = unescape(test)
+ for initialState in test["initialStates"]:
+ test["initialState"] = capitalize(initialState)
+ yield runTokenizerTest, test
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/test_treeadapters.py b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/test_treeadapters.py
new file mode 100644
index 00000000000..5f38b6c33d2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/test_treeadapters.py
@@ -0,0 +1,40 @@
+from __future__ import absolute_import, division, unicode_literals
+
+from . import support # flake8: noqa
+
+import html5lib
+from html5lib.treeadapters import sax
+from html5lib.treewalkers import getTreeWalker
+
+
+def test_to_sax():
+ handler = support.TracingSaxHandler()
+ tree = html5lib.parse("""<html xml:lang="en">
+ <title>Directory Listing</title>
+ <a href="/"><b/></p>
+ """, treebuilder="etree")
+ walker = getTreeWalker("etree")
+ sax.to_sax(walker(tree), handler)
+ expected = [
+ 'startDocument',
+ ('startElementNS', ('http://www.w3.org/1999/xhtml', 'html'),
+ 'html', {(None, 'xml:lang'): 'en'}),
+ ('startElementNS', ('http://www.w3.org/1999/xhtml', 'head'), 'head', {}),
+ ('startElementNS', ('http://www.w3.org/1999/xhtml', 'title'), 'title', {}),
+ ('characters', 'Directory Listing'),
+ ('endElementNS', ('http://www.w3.org/1999/xhtml', 'title'), 'title'),
+ ('characters', '\n '),
+ ('endElementNS', ('http://www.w3.org/1999/xhtml', 'head'), 'head'),
+ ('startElementNS', ('http://www.w3.org/1999/xhtml', 'body'), 'body', {}),
+ ('startElementNS', ('http://www.w3.org/1999/xhtml', 'a'), 'a', {(None, 'href'): '/'}),
+ ('startElementNS', ('http://www.w3.org/1999/xhtml', 'b'), 'b', {}),
+ ('startElementNS', ('http://www.w3.org/1999/xhtml', 'p'), 'p', {}),
+ ('endElementNS', ('http://www.w3.org/1999/xhtml', 'p'), 'p'),
+ ('characters', '\n '),
+ ('endElementNS', ('http://www.w3.org/1999/xhtml', 'b'), 'b'),
+ ('endElementNS', ('http://www.w3.org/1999/xhtml', 'a'), 'a'),
+ ('endElementNS', ('http://www.w3.org/1999/xhtml', 'body'), 'body'),
+ ('endElementNS', ('http://www.w3.org/1999/xhtml', 'html'), 'html'),
+ 'endDocument',
+ ]
+ assert expected == handler.visited
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/test_treewalkers.py b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/test_treewalkers.py
new file mode 100644
index 00000000000..b7756035c26
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/test_treewalkers.py
@@ -0,0 +1,353 @@
+from __future__ import absolute_import, division, unicode_literals
+
+import os
+import sys
+import unittest
+import warnings
+from difflib import unified_diff
+
+try:
+ unittest.TestCase.assertEqual
+except AttributeError:
+ unittest.TestCase.assertEqual = unittest.TestCase.assertEquals
+
+from .support import get_data_files, TestData, convertExpected
+
+from html5lib import html5parser, treewalkers, treebuilders, constants
+
+
+def PullDOMAdapter(node):
+ from xml.dom import Node
+ from xml.dom.pulldom import START_ELEMENT, END_ELEMENT, COMMENT, CHARACTERS
+
+ if node.nodeType in (Node.DOCUMENT_NODE, Node.DOCUMENT_FRAGMENT_NODE):
+ for childNode in node.childNodes:
+ for event in PullDOMAdapter(childNode):
+ yield event
+
+ elif node.nodeType == Node.DOCUMENT_TYPE_NODE:
+ raise NotImplementedError("DOCTYPE nodes are not supported by PullDOM")
+
+ elif node.nodeType == Node.COMMENT_NODE:
+ yield COMMENT, node
+
+ elif node.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE):
+ yield CHARACTERS, node
+
+ elif node.nodeType == Node.ELEMENT_NODE:
+ yield START_ELEMENT, node
+ for childNode in node.childNodes:
+ for event in PullDOMAdapter(childNode):
+ yield event
+ yield END_ELEMENT, node
+
+ else:
+ raise NotImplementedError("Node type not supported: " + str(node.nodeType))
+
+treeTypes = {
+ "DOM": {"builder": treebuilders.getTreeBuilder("dom"),
+ "walker": treewalkers.getTreeWalker("dom")},
+ "PullDOM": {"builder": treebuilders.getTreeBuilder("dom"),
+ "adapter": PullDOMAdapter,
+ "walker": treewalkers.getTreeWalker("pulldom")},
+}
+
+# Try whatever etree implementations are available from a list that are
+#"supposed" to work
+try:
+ import xml.etree.ElementTree as ElementTree
+except ImportError:
+ pass
+else:
+ treeTypes['ElementTree'] = \
+ {"builder": treebuilders.getTreeBuilder("etree", ElementTree),
+ "walker": treewalkers.getTreeWalker("etree", ElementTree)}
+
+try:
+ import xml.etree.cElementTree as ElementTree
+except ImportError:
+ pass
+else:
+ treeTypes['cElementTree'] = \
+ {"builder": treebuilders.getTreeBuilder("etree", ElementTree),
+ "walker": treewalkers.getTreeWalker("etree", ElementTree)}
+
+
+try:
+ import lxml.etree as ElementTree # flake8: noqa
+except ImportError:
+ pass
+else:
+ treeTypes['lxml_native'] = \
+ {"builder": treebuilders.getTreeBuilder("lxml"),
+ "walker": treewalkers.getTreeWalker("lxml")}
+
+
+try:
+ from genshi.core import QName, Attrs
+ from genshi.core import START, END, TEXT, COMMENT, DOCTYPE
+except ImportError:
+ pass
+else:
+ def GenshiAdapter(tree):
+ text = None
+ for token in treewalkers.getTreeWalker("dom")(tree):
+ type = token["type"]
+ if type in ("Characters", "SpaceCharacters"):
+ if text is None:
+ text = token["data"]
+ else:
+ text += token["data"]
+ elif text is not None:
+ yield TEXT, text, (None, -1, -1)
+ text = None
+
+ if type in ("StartTag", "EmptyTag"):
+ if token["namespace"]:
+ name = "{%s}%s" % (token["namespace"], token["name"])
+ else:
+ name = token["name"]
+ attrs = Attrs([(QName("{%s}%s" % attr if attr[0] is not None else attr[1]), value)
+ for attr, value in token["data"].items()])
+ yield (START, (QName(name), attrs), (None, -1, -1))
+ if type == "EmptyTag":
+ type = "EndTag"
+
+ if type == "EndTag":
+ if token["namespace"]:
+ name = "{%s}%s" % (token["namespace"], token["name"])
+ else:
+ name = token["name"]
+
+ yield END, QName(name), (None, -1, -1)
+
+ elif type == "Comment":
+ yield COMMENT, token["data"], (None, -1, -1)
+
+ elif type == "Doctype":
+ yield DOCTYPE, (token["name"], token["publicId"],
+ token["systemId"]), (None, -1, -1)
+
+ else:
+ pass # FIXME: What to do?
+
+ if text is not None:
+ yield TEXT, text, (None, -1, -1)
+
+ treeTypes["genshi"] = \
+ {"builder": treebuilders.getTreeBuilder("dom"),
+ "adapter": GenshiAdapter,
+ "walker": treewalkers.getTreeWalker("genshi")}
+
+
+def concatenateCharacterTokens(tokens):
+ charactersToken = None
+ for token in tokens:
+ type = token["type"]
+ if type in ("Characters", "SpaceCharacters"):
+ if charactersToken is None:
+ charactersToken = {"type": "Characters", "data": token["data"]}
+ else:
+ charactersToken["data"] += token["data"]
+ else:
+ if charactersToken is not None:
+ yield charactersToken
+ charactersToken = None
+ yield token
+ if charactersToken is not None:
+ yield charactersToken
+
+
+def convertTokens(tokens):
+ output = []
+ indent = 0
+ for token in concatenateCharacterTokens(tokens):
+ type = token["type"]
+ if type in ("StartTag", "EmptyTag"):
+ if (token["namespace"] and
+ token["namespace"] != constants.namespaces["html"]):
+ if token["namespace"] in constants.prefixes:
+ name = constants.prefixes[token["namespace"]]
+ else:
+ name = token["namespace"]
+ name += " " + token["name"]
+ else:
+ name = token["name"]
+ output.append("%s<%s>" % (" " * indent, name))
+ indent += 2
+ attrs = token["data"]
+ if attrs:
+ # TODO: Remove this if statement, attrs should always exist
+ for (namespace, name), value in sorted(attrs.items()):
+ if namespace:
+ if namespace in constants.prefixes:
+ outputname = constants.prefixes[namespace]
+ else:
+ outputname = namespace
+ outputname += " " + name
+ else:
+ outputname = name
+ output.append("%s%s=\"%s\"" % (" " * indent, outputname, value))
+ if type == "EmptyTag":
+ indent -= 2
+ elif type == "EndTag":
+ indent -= 2
+ elif type == "Comment":
+ output.append("%s<!-- %s -->" % (" " * indent, token["data"]))
+ elif type == "Doctype":
+ if token["name"]:
+ if token["publicId"]:
+ output.append("""%s<!DOCTYPE %s "%s" "%s">""" %
+ (" " * indent, token["name"],
+ token["publicId"],
+ token["systemId"] and token["systemId"] or ""))
+ elif token["systemId"]:
+ output.append("""%s<!DOCTYPE %s "" "%s">""" %
+ (" " * indent, token["name"],
+ token["systemId"]))
+ else:
+ output.append("%s<!DOCTYPE %s>" % (" " * indent,
+ token["name"]))
+ else:
+ output.append("%s<!DOCTYPE >" % (" " * indent,))
+ elif type in ("Characters", "SpaceCharacters"):
+ output.append("%s\"%s\"" % (" " * indent, token["data"]))
+ else:
+ pass # TODO: what to do with errors?
+ return "\n".join(output)
+
+import re
+attrlist = re.compile(r"^(\s+)\w+=.*(\n\1\w+=.*)+", re.M)
+
+
+def sortattrs(x):
+ lines = x.group(0).split("\n")
+ lines.sort()
+ return "\n".join(lines)
+
+
+class TokenTestCase(unittest.TestCase):
+ def test_all_tokens(self):
+ expected = [
+ {'data': {}, 'type': 'StartTag', 'namespace': 'http://www.w3.org/1999/xhtml', 'name': 'html'},
+ {'data': {}, 'type': 'StartTag', 'namespace': 'http://www.w3.org/1999/xhtml', 'name': 'head'},
+ {'data': {}, 'type': 'EndTag', 'namespace': 'http://www.w3.org/1999/xhtml', 'name': 'head'},
+ {'data': {}, 'type': 'StartTag', 'namespace': 'http://www.w3.org/1999/xhtml', 'name': 'body'},
+ {'data': 'a', 'type': 'Characters'},
+ {'data': {}, 'type': 'StartTag', 'namespace': 'http://www.w3.org/1999/xhtml', 'name': 'div'},
+ {'data': 'b', 'type': 'Characters'},
+ {'data': {}, 'type': 'EndTag', 'namespace': 'http://www.w3.org/1999/xhtml', 'name': 'div'},
+ {'data': 'c', 'type': 'Characters'},
+ {'data': {}, 'type': 'EndTag', 'namespace': 'http://www.w3.org/1999/xhtml', 'name': 'body'},
+ {'data': {}, 'type': 'EndTag', 'namespace': 'http://www.w3.org/1999/xhtml', 'name': 'html'}
+ ]
+ for treeName, treeCls in treeTypes.items():
+ p = html5parser.HTMLParser(tree=treeCls["builder"])
+ document = p.parse("<html><head></head><body>a<div>b</div>c</body></html>")
+ document = treeCls.get("adapter", lambda x: x)(document)
+ output = treeCls["walker"](document)
+ for expectedToken, outputToken in zip(expected, output):
+ self.assertEqual(expectedToken, outputToken)
+
+
+def runTreewalkerTest(innerHTML, input, expected, errors, treeClass):
+ warnings.resetwarnings()
+ warnings.simplefilter("error")
+ try:
+ p = html5parser.HTMLParser(tree=treeClass["builder"])
+ if innerHTML:
+ document = p.parseFragment(input, innerHTML)
+ else:
+ document = p.parse(input)
+ except constants.DataLossWarning:
+ # Ignore testcases we know we don't pass
+ return
+
+ document = treeClass.get("adapter", lambda x: x)(document)
+ try:
+ output = convertTokens(treeClass["walker"](document))
+ output = attrlist.sub(sortattrs, output)
+ expected = attrlist.sub(sortattrs, convertExpected(expected))
+ diff = "".join(unified_diff([line + "\n" for line in expected.splitlines()],
+ [line + "\n" for line in output.splitlines()],
+ "Expected", "Received"))
+ assert expected == output, "\n".join([
+ "", "Input:", input,
+ "", "Expected:", expected,
+ "", "Received:", output,
+ "", "Diff:", diff,
+ ])
+ except NotImplementedError:
+ pass # Amnesty for those that confess...
+
+
+def test_treewalker():
+ sys.stdout.write('Testing tree walkers ' + " ".join(list(treeTypes.keys())) + "\n")
+
+ for treeName, treeCls in treeTypes.items():
+ files = get_data_files('tree-construction')
+ for filename in files:
+ testName = os.path.basename(filename).replace(".dat", "")
+ if testName in ("template",):
+ continue
+
+ tests = TestData(filename, "data")
+
+ for index, test in enumerate(tests):
+ (input, errors,
+ innerHTML, expected) = [test[key] for key in ("data", "errors",
+ "document-fragment",
+ "document")]
+ errors = errors.split("\n")
+ yield runTreewalkerTest, innerHTML, input, expected, errors, treeCls
+
+
+def set_attribute_on_first_child(docfrag, name, value, treeName):
+ """naively sets an attribute on the first child of the document
+ fragment passed in"""
+ setter = {'ElementTree': lambda d: d[0].set,
+ 'DOM': lambda d: d.firstChild.setAttribute}
+ setter['cElementTree'] = setter['ElementTree']
+ try:
+ setter.get(treeName, setter['DOM'])(docfrag)(name, value)
+ except AttributeError:
+ setter['ElementTree'](docfrag)(name, value)
+
+
+def runTreewalkerEditTest(intext, expected, attrs_to_add, tree):
+ """tests what happens when we add attributes to the intext"""
+ treeName, treeClass = tree
+ parser = html5parser.HTMLParser(tree=treeClass["builder"])
+ document = parser.parseFragment(intext)
+ for nom, val in attrs_to_add:
+ set_attribute_on_first_child(document, nom, val, treeName)
+
+ document = treeClass.get("adapter", lambda x: x)(document)
+ output = convertTokens(treeClass["walker"](document))
+ output = attrlist.sub(sortattrs, output)
+ if not output in expected:
+ raise AssertionError("TreewalkerEditTest: %s\nExpected:\n%s\nReceived:\n%s" % (treeName, expected, output))
+
+
+def test_treewalker_six_mix():
+ """Str/Unicode mix. If str attrs added to tree"""
+
+ # On Python 2.x string literals are of type str. Unless, like this
+ # file, the programmer imports unicode_literals from __future__.
+ # In that case, string literals become objects of type unicode.
+
+ # This test simulates a Py2 user, modifying attributes on a document
+ # fragment but not using the u'' syntax nor importing unicode_literals
+ sm_tests = [
+ ('<a href="http://example.com">Example</a>',
+ [(str('class'), str('test123'))],
+ '<a>\n class="test123"\n href="http://example.com"\n "Example"'),
+
+ ('<link href="http://example.com/cow">',
+ [(str('rel'), str('alternate'))],
+ '<link>\n href="http://example.com/cow"\n rel="alternate"\n "Example"')
+ ]
+
+ for tree in treeTypes.items():
+ for intext, attrs, expected in sm_tests:
+ yield runTreewalkerEditTest, intext, expected, attrs, tree
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/test_whitespace_filter.py b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/test_whitespace_filter.py
new file mode 100644
index 00000000000..9ed27fd6ac0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/test_whitespace_filter.py
@@ -0,0 +1,133 @@
+from __future__ import absolute_import, division, unicode_literals
+
+import unittest
+
+from html5lib.filters.whitespace import Filter
+from html5lib.constants import spaceCharacters
+spaceCharacters = "".join(spaceCharacters)
+
+try:
+ unittest.TestCase.assertEqual
+except AttributeError:
+ unittest.TestCase.assertEqual = unittest.TestCase.assertEquals
+
+
+class TestCase(unittest.TestCase):
+ def runTest(self, input, expected):
+ output = list(Filter(input))
+ errorMsg = "\n".join(["\n\nInput:", str(input),
+ "\nExpected:", str(expected),
+ "\nReceived:", str(output)])
+ self.assertEqual(output, expected, errorMsg)
+
+ def runTestUnmodifiedOutput(self, input):
+ self.runTest(input, input)
+
+ def testPhrasingElements(self):
+ self.runTestUnmodifiedOutput(
+ [{"type": "Characters", "data": "This is a "},
+ {"type": "StartTag", "name": "span", "data": []},
+ {"type": "Characters", "data": "phrase"},
+ {"type": "EndTag", "name": "span", "data": []},
+ {"type": "SpaceCharacters", "data": " "},
+ {"type": "Characters", "data": "with"},
+ {"type": "SpaceCharacters", "data": " "},
+ {"type": "StartTag", "name": "em", "data": []},
+ {"type": "Characters", "data": "emphasised text"},
+ {"type": "EndTag", "name": "em", "data": []},
+ {"type": "Characters", "data": " and an "},
+ {"type": "StartTag", "name": "img", "data": [["alt", "image"]]},
+ {"type": "Characters", "data": "."}])
+
+ def testLeadingWhitespace(self):
+ self.runTest(
+ [{"type": "StartTag", "name": "p", "data": []},
+ {"type": "SpaceCharacters", "data": spaceCharacters},
+ {"type": "Characters", "data": "foo"},
+ {"type": "EndTag", "name": "p", "data": []}],
+ [{"type": "StartTag", "name": "p", "data": []},
+ {"type": "SpaceCharacters", "data": " "},
+ {"type": "Characters", "data": "foo"},
+ {"type": "EndTag", "name": "p", "data": []}])
+
+ def testLeadingWhitespaceAsCharacters(self):
+ self.runTest(
+ [{"type": "StartTag", "name": "p", "data": []},
+ {"type": "Characters", "data": spaceCharacters + "foo"},
+ {"type": "EndTag", "name": "p", "data": []}],
+ [{"type": "StartTag", "name": "p", "data": []},
+ {"type": "Characters", "data": " foo"},
+ {"type": "EndTag", "name": "p", "data": []}])
+
+ def testTrailingWhitespace(self):
+ self.runTest(
+ [{"type": "StartTag", "name": "p", "data": []},
+ {"type": "Characters", "data": "foo"},
+ {"type": "SpaceCharacters", "data": spaceCharacters},
+ {"type": "EndTag", "name": "p", "data": []}],
+ [{"type": "StartTag", "name": "p", "data": []},
+ {"type": "Characters", "data": "foo"},
+ {"type": "SpaceCharacters", "data": " "},
+ {"type": "EndTag", "name": "p", "data": []}])
+
+ def testTrailingWhitespaceAsCharacters(self):
+ self.runTest(
+ [{"type": "StartTag", "name": "p", "data": []},
+ {"type": "Characters", "data": "foo" + spaceCharacters},
+ {"type": "EndTag", "name": "p", "data": []}],
+ [{"type": "StartTag", "name": "p", "data": []},
+ {"type": "Characters", "data": "foo "},
+ {"type": "EndTag", "name": "p", "data": []}])
+
+ def testWhitespace(self):
+ self.runTest(
+ [{"type": "StartTag", "name": "p", "data": []},
+ {"type": "Characters", "data": "foo" + spaceCharacters + "bar"},
+ {"type": "EndTag", "name": "p", "data": []}],
+ [{"type": "StartTag", "name": "p", "data": []},
+ {"type": "Characters", "data": "foo bar"},
+ {"type": "EndTag", "name": "p", "data": []}])
+
+ def testLeadingWhitespaceInPre(self):
+ self.runTestUnmodifiedOutput(
+ [{"type": "StartTag", "name": "pre", "data": []},
+ {"type": "SpaceCharacters", "data": spaceCharacters},
+ {"type": "Characters", "data": "foo"},
+ {"type": "EndTag", "name": "pre", "data": []}])
+
+ def testLeadingWhitespaceAsCharactersInPre(self):
+ self.runTestUnmodifiedOutput(
+ [{"type": "StartTag", "name": "pre", "data": []},
+ {"type": "Characters", "data": spaceCharacters + "foo"},
+ {"type": "EndTag", "name": "pre", "data": []}])
+
+ def testTrailingWhitespaceInPre(self):
+ self.runTestUnmodifiedOutput(
+ [{"type": "StartTag", "name": "pre", "data": []},
+ {"type": "Characters", "data": "foo"},
+ {"type": "SpaceCharacters", "data": spaceCharacters},
+ {"type": "EndTag", "name": "pre", "data": []}])
+
+ def testTrailingWhitespaceAsCharactersInPre(self):
+ self.runTestUnmodifiedOutput(
+ [{"type": "StartTag", "name": "pre", "data": []},
+ {"type": "Characters", "data": "foo" + spaceCharacters},
+ {"type": "EndTag", "name": "pre", "data": []}])
+
+ def testWhitespaceInPre(self):
+ self.runTestUnmodifiedOutput(
+ [{"type": "StartTag", "name": "pre", "data": []},
+ {"type": "Characters", "data": "foo" + spaceCharacters + "bar"},
+ {"type": "EndTag", "name": "pre", "data": []}])
+
+
+def buildTestSuite():
+ return unittest.defaultTestLoader.loadTestsFromName(__name__)
+
+
+def main():
+ buildTestSuite()
+ unittest.main()
+
+if __name__ == "__main__":
+ main()
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/AUTHORS.rst b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/AUTHORS.rst
new file mode 100644
index 00000000000..4a7de17ad45
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/AUTHORS.rst
@@ -0,0 +1,34 @@
+Credits
+=======
+
+The ``html5lib`` test data is maintained by:
+
+- James Graham
+- Geoffrey Sneddon
+
+
+Contributors
+------------
+
+- Adam Barth
+- Andi Sidwell
+- Anne van Kesteren
+- David Flanagan
+- Edward Z. Yang
+- Geoffrey Sneddon
+- Henri Sivonen
+- Ian Hickson
+- Jacques Distler
+- James Graham
+- Lachlan Hunt
+- lantis63
+- Mark Pilgrim
+- Mats Palmgren
+- Ms2ger
+- Nolan Waite
+- Philip Taylor
+- Rafael Weinstein
+- Ryan King
+- Sam Ruby
+- Simon Pieters
+- Thomas Broyer
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/LICENSE b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/LICENSE
new file mode 100644
index 00000000000..8812371b41c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/LICENSE
@@ -0,0 +1,21 @@
+Copyright (c) 2006-2013 James Graham, Geoffrey Sneddon, and
+other contributors
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/encoding/chardet/test_big5.txt b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/encoding/chardet/test_big5.txt
new file mode 100644
index 00000000000..91074c98d21
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/encoding/chardet/test_big5.txt
@@ -0,0 +1,51 @@
+ѤlmDwgn Ĥ@~|Q
+
+ѤlDg
+
+Ĥ@
+
+DiDAD`DCWiWAD`WCLAWѦalQAWUC
+G`LAH[䧮F`AH[uC̡APXӲWAPפ
+ȡCȤSȡAC
+
+ĤG
+
+ѤUҪAcoQҪAoCGLۥ͡A
+ۦAuۧΡAU۶ɡAn۩MAeHCOHtHBuL
+vơAuvСCU@jӤAͦӤAӤA\
+ӥ~CҰߥ~AOHhC
+
+ĤT
+
+|AϥQQofAϥsQiAϥߤ
+COHutHvvAߡA両AzӡAj䰩C`ϥLL
+CϤҴ̤]CuLvAhLvC
+
+ĥ|
+
+uDvRAӥΤΤաCWAUvQUAѨɡAM
+APСQ祿ΦsC^֤lHHҤC
+
+
+ѦaAHU쪯QtHAHʩm쪯CѦaAS
+GHӤ}AʦӷUXChƽaApuC
+
+
+AOץȦɡCȦɤAOפѦaڡCYsAΤԡC
+
+ĤC
+
+Ѫa[CѦaҥHB[̡AH䤣ۥ͡AG[COHtH
+ӨA~䨭ӨsCDHLpHGনpC
+
+ĤK
+
+WYCQUӤCBHҴcAGXDC~aAߵ
+WAPAHAFvAƵAʵɡCҰߤAGLסC
+
+ĤE
+
+ӬդApwQӾUAiOCɺAuQIQ
+źAۿSC\EhAѤDC
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/encoding/test-yahoo-jp.dat b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/encoding/test-yahoo-jp.dat
new file mode 100644
index 00000000000..3c25ecb2b1b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/encoding/test-yahoo-jp.dat
@@ -0,0 +1,10 @@
+#data
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=euc-jp">
+<!--京-->
+<title>Yahoo! JAPAN</title>
+<meta name="description" content="日本最大級のポータルサイト。検索、オークション、ニュース、メール、コミュニティ、ショッピング、など80以上のサービスを展開。あなたの生活をより豊かにする「ライフ・エンジン」を目指していきます。">
+<style type="text/css" media="all">
+#encoding
+euc_jp
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/encoding/tests1.dat b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/encoding/tests1.dat
new file mode 100644
index 00000000000..5b585e735f1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/encoding/tests1.dat
@@ -0,0 +1,394 @@
+#data
+<!DOCTYPE HTML>
+<!-- (control test - for the other tests to work, this should pass - you may have to set your defaults appropriately) -->
+#encoding
+Windows-1252
+
+#data
+<!DOCTYPE HTML>
+<meta charset="ISO-8859-1">
+#encoding
+Windows-1252
+
+#data
+<!DOCTYPE HTML>
+<meta charset="iso8859-2">
+#encoding
+iso8859-2
+
+#data
+<!DOCTYPE HTML>
+<meta charset='iso8859-2'>
+#encoding
+iso8859-2
+
+#data
+<!DOCTYPE HTML>
+<meta charset=iso8859-2>
+#encoding
+iso8859-2
+
+#data
+<!DOCTYPE HTML>
+<meta
+charset=iso8859-2>
+#encoding
+iso8859-2
+
+#data
+<!DOCTYPE HTML>
+<metacharset=iso8859-2>
+#encoding
+Windows-1252
+
+#data
+<!DOCTYPE HTML>
+<meta http-equiv="Content-Type" content="text/html; charset=iso8859-2">
+<!-- XXX this is a tough one, not sure how to do this one, unless we explictly do content= processing -->
+#encoding
+iso8859-2
+
+#data
+<!DOCTYPE HTML>
+<meta content="text/html; charset=iso8859-2" http-equiv="Content-Type">
+<!-- XXX this is a tough one, not sure how to do this one, unless we explictly do content= processing -->
+#encoding
+iso8859-2
+
+#data
+<!DOCTYPE HTML>
+<meta http-equiv="Content-Type" content=text/html; charset=iso8859-2>
+#encoding
+iso8859-2
+
+#data
+<!DOCTYPE HTML>
+<meta http-equiv="Content-Type content="text/html; charset=iso8859-2">
+#encoding
+iso8859-2
+
+#data
+<!DOCTYPE HTML>
+<meta http-equiv="Content-Type " content="text/html; charset=iso8859-2">
+#encoding
+Windows-1252
+
+#data
+<!DOCTYPE HTML>
+<meta content="text/html; charset=iso8859-2" http-equiv="Content-Type ">
+#encoding
+Windows-1252
+
+#data
+<!DOCTYPE HTML>
+<meta http-equiv="Content-Type>" content="text/html; charset=iso8859-2">
+#encoding
+Windows-1252
+
+#data
+<!DOCTYPE HTML>
+<meta content="text/html; charset=iso8859-2" http-equiv="Content-Type>">
+#encoding
+Windows-1252
+
+#data
+<!DOCTYPE HTML>
+<meta http-equiv="Content-Style-Type" content="text/html; charset=iso8859-2">
+#encoding
+Windows-1252
+
+#data
+<!DOCTYPE HTML>
+<meta content="text/html; charset=iso8859-2" http-equiv="Content-Style-Type">
+#encoding
+Windows-1252
+
+#data
+<!DOCTYPE HTML>
+<meta name="Content-Style-Type" content="text/html; charset=iso8859-2">
+#encoding
+Windows-1252
+
+#data
+<!DOCTYPE HTML>
+<meta content="text/html; charset=iso8859-2" name="Content-Style-Type">
+#encoding
+Windows-1252
+
+#data
+<!DOCTYPE HTML>
+<meta content="text/html; charset=iso8859-2">
+#encoding
+Windows-1252
+
+#data
+<!DOCTYPE HTML>
+<meta content=" text/html; charset = iso8859-2 ">
+#encoding
+Windows-1252
+
+#data
+<!DOCTYPE HTML>
+<meta content="
+text/html; charset=iso8859-2
+" http-equiv="Content-Type">
+#encoding
+iso8859-2
+
+#data
+<!DOCTYPE HTML>
+<meta charset="
+iso8859-2
+">
+#encoding
+iso8859-2
+
+#data
+<!DOCTYPE HTML>
+<meta charset=
+iso8859-2
+>
+#encoding
+iso8859-2
+
+#data
+<!DOCTYPE HTML>
+<meta charset="iso8859-2>
+<p>"</p>
+#encoding
+Windows-1252
+
+#data
+<!DOCTYPE HTML>
+<meta charset=iso8859-2">
+<p>"</p>
+#encoding
+iso8859-2
+
+#data
+<!DOCTYPE HTML>
+<meta " charset=iso8859-2>
+<p>"</p>
+#encoding
+iso8859-2
+
+#data
+<!DOCTYPE HTML>
+<meta test" charset=iso8859-2>
+<p>"</p>
+#encoding
+iso8859-2
+
+#data
+<!DOCTYPE HTML>
+<meta test=" charset=iso8859-2>
+<p>"</p>
+#encoding
+Windows-1252
+
+#data
+<!DOCTYPE HTML>
+<meta test="' charset=iso8859-2>
+<p>"'</p>
+#encoding
+Windows-1252
+
+#data
+<!DOCTYPE HTML>
+<meta test='" charset=iso8859-2>
+<p>'"</p>
+#encoding
+Windows-1252
+
+#data
+<!DOCTYPE HTML>
+<meta test="" charset=iso8859-2>
+#encoding
+iso8859-2
+
+#data
+<!DOCTYPE HTML>
+<meta test=x" charset=iso8859-2>
+<p>"</p>
+#encoding
+iso8859-2
+
+#data
+<!DOCTYPE HTML>
+<head></head><p title="x>
+<meta test=x" charset=iso8859-2>
+<p>"</p>
+#encoding
+Windows-1252
+
+#data
+<!DOCTYPE HTML>
+<head></head><p title="x>
+<meta test=x charset=iso8859-2>
+<p>"</p>
+#encoding
+Windows-1252
+
+#data
+<!DOCTYPE HTML>
+<head></head><p title="x>
+<meta charset=iso8859-2>
+<p>"</p>
+#encoding
+Windows-1252
+
+#data
+<!DOCTYPE HTML>
+<head></head><p title="x>">
+<meta charset=iso8859-2>
+<p>"</p>
+#encoding
+iso8859-2
+
+#data
+<!DOCTYPE HTML>
+<meta charset="ISO-8859-1">
+<meta charset="iso8859-2">
+#encoding
+Windows-1252
+
+#data
+<!DOCTYPE HTML>
+<meta charset="iso8859-2">
+<meta charset="ISO-8859-1">
+#encoding
+iso8859-2
+
+#data
+<!DOCTYPE HTML>
+<!--<meta charset="ISO-8859-1">-->
+<meta charset="iso8859-2">
+#encoding
+iso8859-2
+
+#data
+<!DOCTYPE HTML>
+<!--<meta charset="iso8859-2">-->
+<meta charset="ISO-8859-1">
+#encoding
+Windows-1252
+
+#data
+<!DOCTYPE HTML>
+<!-- Starts with UTF-8 BOM -->
+#encoding
+UTF-8
+
+#data
+<!DOCTYPE HTML>
+<meta charset="ISO-8859-1">
+<!-- Starts with UTF-8 BOM -->
+#encoding
+UTF-8
+
+#data
+<!-- 511 characters xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-->
+<meta charset="iso8859-2">
+#encoding
+iso8859-2
+
+#data
+<!-- 512 characters xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-->
+<meta charset="iso8859-2">
+#encoding
+iso8859-2
+
+#data
+<!-- 1024 characters xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-->
+<meta charset="iso8859-2">
+#encoding
+iso8859-2
+
+#data
+<!-- 1025 characters xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxz-->
+<meta charset="iso8859-2">
+#encoding
+iso8859-2
+
+#data
+<!-- 2048 characters xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-->
+<meta charset="iso8859-2">
+#encoding
+iso8859-2
+
+#data
+<!-- 2049 characters xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxz-->
+<meta charset="iso8859-2">
+#encoding
+iso8859-2
+
+#data
+<!-- 4096 characters xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-->
+<meta charset="iso8859-2">
+#encoding
+iso8859-2
+
+#data
+<!-- 4097 characters xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxz-->
+<meta charset="iso8859-2">
+#encoding
+iso8859-2
+
+#data
+<!-- 8192 characters xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-->
+<meta charset="iso8859-2">
+#encoding
+iso8859-2
+
+#data
+<!-- 8193 characters xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxz-->
+<meta charset="iso8859-2">
+#encoding
+iso8859-2
+
+#data
+<!-- multi-script test -->
+<script>alert('step 1 of 3 ("")')</script>
+<!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
+<script>alert('step 2 of 3 ("")')</script>
+<meta charset="iso8859-2">
+<script>alert('step 3 of 3 ("")')</script>
+#encoding
+iso8859-2
+
+#data
+<!DOCTYPE HTML>
+<script>document.write('<meta charset="ISO-8859-' + '2">')</script>
+#encoding
+iso8859-2
+
+#data
+<!DOCTYPE HTML>
+<script>document.write('<meta charset="iso8859-2">')</script>
+#encoding
+iso8859-2
+
+#data
+<!DOCTYPE HTML>
+<script type="text/plain"><meta charset="iso8859-2"></script>
+#encoding
+iso8859-2
+
+#data
+<!DOCTYPE HTML>
+<style type="text/plain"><meta charset="iso8859-2"></style>
+#encoding
+iso8859-2
+
+#data
+<!DOCTYPE HTML>
+<p><meta charset="iso8859-2"></p>
+#encoding
+iso8859-2
+
+#data
+<!DOCTYPE HTML>
+<meta charset="bogus">
+<meta charset="iso8859-2">
+#encoding
+iso8859-2
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/encoding/tests2.dat b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/encoding/tests2.dat
new file mode 100644
index 00000000000..eee44984d6b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/encoding/tests2.dat
@@ -0,0 +1,115 @@
+#data
+<meta
+#encoding
+windows-1252
+
+#data
+<
+#encoding
+windows-1252
+
+#data
+<!
+#encoding
+windows-1252
+
+#data
+<meta charset = "
+#encoding
+windows-1252
+
+#data
+<meta charset=euc_jp
+#encoding
+windows-1252
+
+#data
+<meta <meta charset='euc_jp'>
+#encoding
+euc_jp
+
+#data
+<meta charset = 'euc_jp'>
+#encoding
+euc_jp
+
+#data
+<!-- -->
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+#encoding
+utf-8
+
+#data
+<!-- -->
+<meta http-equiv="Content-Type" content="text/html; charset=utf
+#encoding
+windows-1252
+
+#data
+<meta http-equiv="Content-Type<meta charset="utf-8">
+#encoding
+windows-1252
+
+#data
+<meta http-equiv="Content-Type" content="text/html; charset='utf-8'">
+#encoding
+utf-8
+
+#data
+<meta http-equiv="Content-Type" content="text/html; charset='utf-8">
+#encoding
+windows-1252
+
+#data
+<meta
+#encoding
+windows-1252
+
+#data
+<meta charset =
+#encoding
+windows-1252
+
+#data
+<meta charset= utf-8
+>
+#encoding
+utf-8
+
+#data
+<meta content = "text/html;
+#encoding
+windows-1252
+
+#data
+<meta charset="UTF-16">
+#encoding
+utf-8
+
+#data
+<meta charset="UTF-16LE">
+#encoding
+utf-8
+
+#data
+<meta charset="UTF-16BE">
+#encoding
+utf-8
+
+#data
+<html a=ñ>
+<meta charset="utf-8">
+#encoding
+utf-8
+
+#data
+<html ñ>
+<meta charset="utf-8">
+#encoding
+utf-8
+
+#data
+<html>ñ
+<meta charset="utf-8">
+#encoding
+utf-8
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/sanitizer/tests1.dat b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/sanitizer/tests1.dat
new file mode 100644
index 00000000000..c741cb8c6fe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/sanitizer/tests1.dat
@@ -0,0 +1,501 @@
+[
+ {
+ "name": "IE_Comments",
+ "input": "<!--[if gte IE 4]><script>alert('XSS');</script><![endif]-->",
+ "output": ""
+ },
+
+ {
+ "name": "IE_Comments_2",
+ "input": "<![if !IE 5]><script>alert('XSS');</script><![endif]>",
+ "output": "&lt;script&gt;alert('XSS');&lt;/script&gt;",
+ "rexml": "Ill-formed XHTML!"
+ },
+
+ {
+ "name": "allow_colons_in_path_component",
+ "input": "<a href=\"./this:that\">foo</a>",
+ "output": "<a href='./this:that'>foo</a>"
+ },
+
+ {
+ "name": "background_attribute",
+ "input": "<div background=\"javascript:alert('XSS')\"></div>",
+ "output": "<div/>",
+ "xhtml": "<div></div>",
+ "rexml": "<div></div>"
+ },
+
+ {
+ "name": "bgsound",
+ "input": "<bgsound src=\"javascript:alert('XSS');\" />",
+ "output": "&lt;bgsound src=\"javascript:alert('XSS');\"/&gt;",
+ "rexml": "&lt;bgsound src=\"javascript:alert('XSS');\"&gt;&lt;/bgsound&gt;"
+ },
+
+ {
+ "name": "div_background_image_unicode_encoded",
+ "input": "<div style=\"background-image:\u00a5\u00a2\u006C\u0028'\u006a\u0061\u00a6\u0061\u00a3\u0063\u00a2\u0069\u00a0\u00a4\u003a\u0061\u006c\u0065\u00a2\u00a4\u0028.1027\u0058.1053\u0053\u0027\u0029'\u0029\">foo</div>",
+ "output": "<div style=''>foo</div>"
+ },
+
+ {
+ "name": "div_expression",
+ "input": "<div style=\"width: expression(alert('XSS'));\">foo</div>",
+ "output": "<div style=''>foo</div>"
+ },
+
+ {
+ "name": "double_open_angle_brackets",
+ "input": "<img src=http://ha.ckers.org/scriptlet.html <",
+ "output": "<img src='http://ha.ckers.org/scriptlet.html'>",
+ "rexml": "Ill-formed XHTML!"
+ },
+
+ {
+ "name": "double_open_angle_brackets_2",
+ "input": "<script src=http://ha.ckers.org/scriptlet.html <",
+ "output": "&lt;script src=\"http://ha.ckers.org/scriptlet.html\" &lt;=\"\"&gt;",
+ "rexml": "Ill-formed XHTML!"
+ },
+
+ {
+ "name": "grave_accents",
+ "input": "<img src=`javascript:alert('XSS')` />",
+ "output": "<img/>",
+ "rexml": "Ill-formed XHTML!"
+ },
+
+ {
+ "name": "img_dynsrc_lowsrc",
+ "input": "<img dynsrc=\"javascript:alert('XSS')\" />",
+ "output": "<img/>",
+ "rexml": "<img />"
+ },
+
+ {
+ "name": "img_vbscript",
+ "input": "<img src='vbscript:msgbox(\"XSS\")' />",
+ "output": "<img/>",
+ "rexml": "<img />"
+ },
+
+ {
+ "name": "input_image",
+ "input": "<input type=\"image\" src=\"javascript:alert('XSS');\" />",
+ "output": "<input type='image'/>",
+ "rexml": "<input type='image' />"
+ },
+
+ {
+ "name": "link_stylesheets",
+ "input": "<link rel=\"stylesheet\" href=\"javascript:alert('XSS');\" />",
+ "output": "&lt;link rel=\"stylesheet\" href=\"javascript:alert('XSS');\"/&gt;",
+ "rexml": "&lt;link href=\"javascript:alert('XSS');\" rel=\"stylesheet\"/&gt;"
+ },
+
+ {
+ "name": "link_stylesheets_2",
+ "input": "<link rel=\"stylesheet\" href=\"http://ha.ckers.org/xss.css\" />",
+ "output": "&lt;link rel=\"stylesheet\" href=\"http://ha.ckers.org/xss.css\"/&gt;",
+ "rexml": "&lt;link href=\"http://ha.ckers.org/xss.css\" rel=\"stylesheet\"/&gt;"
+ },
+
+ {
+ "name": "list_style_image",
+ "input": "<li style=\"list-style-image: url(javascript:alert('XSS'))\">foo</li>",
+ "output": "<li style=''>foo</li>"
+ },
+
+ {
+ "name": "no_closing_script_tags",
+ "input": "<script src=http://ha.ckers.org/xss.js?<b>",
+ "output": "&lt;script src=\"http://ha.ckers.org/xss.js?&amp;lt;b\"&gt;",
+ "rexml": "Ill-formed XHTML!"
+ },
+
+ {
+ "name": "non_alpha_non_digit",
+ "input": "<script/XSS src=\"http://ha.ckers.org/xss.js\"></script>",
+ "output": "&lt;script XSS=\"\" src=\"http://ha.ckers.org/xss.js\"&gt;&lt;/script&gt;",
+ "rexml": "Ill-formed XHTML!"
+ },
+
+ {
+ "name": "non_alpha_non_digit_2",
+ "input": "<a onclick!\\#$%&()*~+-_.,:;?@[/|\\]^`=alert(\"XSS\")>foo</a>",
+ "output": "<a>foo</a>",
+ "rexml": "Ill-formed XHTML!"
+ },
+
+ {
+ "name": "non_alpha_non_digit_3",
+ "input": "<img/src=\"http://ha.ckers.org/xss.js\"/>",
+ "output": "<img src='http://ha.ckers.org/xss.js'/>",
+ "rexml": "Ill-formed XHTML!"
+ },
+
+ {
+ "name": "non_alpha_non_digit_II",
+ "input": "<a href!\\#$%&()*~+-_.,:;?@[/|]^`=alert('XSS')>foo</a>",
+ "output": "<a>foo</a>",
+ "rexml": "Ill-formed XHTML!"
+ },
+
+ {
+ "name": "non_alpha_non_digit_III",
+ "input": "<a/href=\"javascript:alert('XSS');\">foo</a>",
+ "output": "<a>foo</a>",
+ "rexml": "Ill-formed XHTML!"
+ },
+
+ {
+ "name": "platypus",
+ "input": "<a href=\"http://www.ragingplatypus.com/\" style=\"display:block; position:absolute; left:0; top:0; width:100%; height:100%; z-index:1; background-color:black; background-image:url(http://www.ragingplatypus.com/i/cam-full.jpg); background-x:center; background-y:center; background-repeat:repeat;\">never trust your upstream platypus</a>",
+ "output": "<a href='http://www.ragingplatypus.com/' style='display: block; width: 100%; height: 100%; background-color: black; background-x: center; background-y: center;'>never trust your upstream platypus</a>"
+ },
+
+ {
+ "name": "protocol_resolution_in_script_tag",
+ "input": "<script src=//ha.ckers.org/.j></script>",
+ "output": "&lt;script src=\"//ha.ckers.org/.j\"&gt;&lt;/script&gt;",
+ "rexml": "Ill-formed XHTML!"
+ },
+
+ {
+ "name": "should_allow_anchors",
+ "input": "<a href='foo' onclick='bar'><script>baz</script></a>",
+ "output": "<a href='foo'>&lt;script&gt;baz&lt;/script&gt;</a>"
+ },
+
+ {
+ "name": "should_allow_image_alt_attribute",
+ "input": "<img alt='foo' onclick='bar' />",
+ "output": "<img alt='foo'/>",
+ "rexml": "<img alt='foo' />"
+ },
+
+ {
+ "name": "should_allow_image_height_attribute",
+ "input": "<img height='foo' onclick='bar' />",
+ "output": "<img height='foo'/>",
+ "rexml": "<img height='foo' />"
+ },
+
+ {
+ "name": "should_allow_image_src_attribute",
+ "input": "<img src='foo' onclick='bar' />",
+ "output": "<img src='foo'/>",
+ "rexml": "<img src='foo' />"
+ },
+
+ {
+ "name": "should_allow_image_width_attribute",
+ "input": "<img width='foo' onclick='bar' />",
+ "output": "<img width='foo'/>",
+ "rexml": "<img width='foo' />"
+ },
+
+ {
+ "name": "should_handle_blank_text",
+ "input": "",
+ "output": ""
+ },
+
+ {
+ "name": "should_handle_malformed_image_tags",
+ "input": "<img \"\"\"><script>alert(\"XSS\")</script>\">",
+ "output": "<img/>&lt;script&gt;alert(\"XSS\")&lt;/script&gt;\"&gt;",
+ "rexml": "Ill-formed XHTML!"
+ },
+
+ {
+ "name": "should_handle_non_html",
+ "input": "abc",
+ "output": "abc"
+ },
+
+ {
+ "name": "should_not_fall_for_ridiculous_hack",
+ "input": "<img\nsrc\n=\n\"\nj\na\nv\na\ns\nc\nr\ni\np\nt\n:\na\nl\ne\nr\nt\n(\n'\nX\nS\nS\n'\n)\n\"\n />",
+ "output": "<img/>",
+ "rexml": "<img />"
+ },
+
+ {
+ "name": "should_not_fall_for_xss_image_hack_0",
+ "input": "<img src=\"javascript:alert('XSS');\" />",
+ "output": "<img/>",
+ "rexml": "<img />"
+ },
+
+ {
+ "name": "should_not_fall_for_xss_image_hack_1",
+ "input": "<img src=javascript:alert('XSS') />",
+ "output": "<img/>",
+ "rexml": "Ill-formed XHTML!"
+ },
+
+ {
+ "name": "should_not_fall_for_xss_image_hack_10",
+ "input": "<img src=\"jav&#x0A;ascript:alert('XSS');\" />",
+ "output": "<img/>",
+ "rexml": "<img />"
+ },
+
+ {
+ "name": "should_not_fall_for_xss_image_hack_11",
+ "input": "<img src=\"jav&#x0D;ascript:alert('XSS');\" />",
+ "output": "<img/>",
+ "rexml": "<img />"
+ },
+
+ {
+ "name": "should_not_fall_for_xss_image_hack_12",
+ "input": "<img src=\" &#14; javascript:alert('XSS');\" />",
+ "output": "<img/>",
+ "rexml": "<img />"
+ },
+
+ {
+ "name": "should_not_fall_for_xss_image_hack_13",
+ "input": "<img src=\"&#x20;javascript:alert('XSS');\" />",
+ "output": "<img/>",
+ "rexml": "<img />"
+ },
+
+ {
+ "name": "should_not_fall_for_xss_image_hack_14",
+ "input": "<img src=\"&#xA0;javascript:alert('XSS');\" />",
+ "output": "<img/>",
+ "rexml": "<img />"
+ },
+
+ {
+ "name": "should_not_fall_for_xss_image_hack_2",
+ "input": "<img src=\"JaVaScRiPt:alert('XSS')\" />",
+ "output": "<img/>",
+ "rexml": "<img />"
+ },
+
+ {
+ "name": "should_not_fall_for_xss_image_hack_3",
+ "input": "<img src='javascript:alert(&quot;XSS&quot;)' />",
+ "output": "<img/>",
+ "rexml": "<img />"
+ },
+
+ {
+ "name": "should_not_fall_for_xss_image_hack_4",
+ "input": "<img src='javascript:alert(String.fromCharCode(88,83,83))' />",
+ "output": "<img/>",
+ "rexml": "<img />"
+ },
+
+ {
+ "name": "should_not_fall_for_xss_image_hack_5",
+ "input": "<img src='&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#39;&#88;&#83;&#83;&#39;&#41;' />",
+ "output": "<img/>",
+ "rexml": "<img />"
+ },
+
+ {
+ "name": "should_not_fall_for_xss_image_hack_6",
+ "input": "<img src='&#0000106;&#0000097;&#0000118;&#0000097;&#0000115;&#0000099;&#0000114;&#0000105;&#0000112;&#0000116;&#0000058;&#0000097;&#0000108;&#0000101;&#0000114;&#0000116;&#0000040;&#0000039;&#0000088;&#0000083;&#0000083;&#0000039;&#0000041' />",
+ "output": "<img/>",
+ "rexml": "<img />"
+ },
+
+ {
+ "name": "should_not_fall_for_xss_image_hack_7",
+ "input": "<img src='&#x6A;&#x61;&#x76;&#x61;&#x73;&#x63;&#x72;&#x69;&#x70;&#x74;&#x3A;&#x61;&#x6C;&#x65;&#x72;&#x74;&#x28;&#x27;&#x58;&#x53;&#x53;&#x27;&#x29' />",
+ "output": "<img/>",
+ "rexml": "<img />"
+ },
+
+ {
+ "name": "should_not_fall_for_xss_image_hack_8",
+ "input": "<img src=\"jav\tascript:alert('XSS');\" />",
+ "output": "<img/>",
+ "rexml": "<img />"
+ },
+
+ {
+ "name": "should_not_fall_for_xss_image_hack_9",
+ "input": "<img src=\"jav&#x09;ascript:alert('XSS');\" />",
+ "output": "<img/>",
+ "rexml": "<img />"
+ },
+
+ {
+ "name": "should_sanitize_half_open_scripts",
+ "input": "<img src=\"javascript:alert('XSS')\"",
+ "output": "<img/>",
+ "rexml": "Ill-formed XHTML!"
+ },
+
+ {
+ "name": "should_sanitize_invalid_script_tag",
+ "input": "<script/XSS SRC=\"http://ha.ckers.org/xss.js\"></script>",
+ "output": "&lt;script XSS=\"\" SRC=\"http://ha.ckers.org/xss.js\"&gt;&lt;/script&gt;",
+ "rexml": "Ill-formed XHTML!"
+ },
+
+ {
+ "name": "should_sanitize_script_tag_with_multiple_open_brackets",
+ "input": "<<script>alert(\"XSS\");//<</script>",
+ "output": "&lt;&lt;script&gt;alert(\"XSS\");//&lt;&lt;/script&gt;",
+ "rexml": "Ill-formed XHTML!"
+ },
+
+ {
+ "name": "should_sanitize_script_tag_with_multiple_open_brackets_2",
+ "input": "<iframe src=http://ha.ckers.org/scriptlet.html\n<",
+ "output": "&lt;iframe src=\"http://ha.ckers.org/scriptlet.html\" &lt;=\"\"&gt;",
+ "rexml": "Ill-formed XHTML!"
+ },
+
+ {
+ "name": "should_sanitize_tag_broken_up_by_null",
+ "input": "<scr\u0000ipt>alert(\"XSS\")</scr\u0000ipt>",
+ "output": "&lt;scr\ufffdipt&gt;alert(\"XSS\")&lt;/scr\ufffdipt&gt;",
+ "rexml": "Ill-formed XHTML!"
+ },
+
+ {
+ "name": "should_sanitize_unclosed_script",
+ "input": "<script src=http://ha.ckers.org/xss.js?<b>",
+ "output": "&lt;script src=\"http://ha.ckers.org/xss.js?&amp;lt;b\"&gt;",
+ "rexml": "Ill-formed XHTML!"
+ },
+
+ {
+ "name": "should_strip_href_attribute_in_a_with_bad_protocols",
+ "input": "<a href=\"javascript:XSS\" title=\"1\">boo</a>",
+ "output": "<a title='1'>boo</a>"
+ },
+
+ {
+ "name": "should_strip_href_attribute_in_a_with_bad_protocols_and_whitespace",
+ "input": "<a href=\" javascript:XSS\" title=\"1\">boo</a>",
+ "output": "<a title='1'>boo</a>"
+ },
+
+ {
+ "name": "should_strip_src_attribute_in_img_with_bad_protocols",
+ "input": "<img src=\"javascript:XSS\" title=\"1\">boo</img>",
+ "output": "<img title='1'/>boo",
+ "rexml": "<img title='1' />"
+ },
+
+ {
+ "name": "should_strip_src_attribute_in_img_with_bad_protocols_and_whitespace",
+ "input": "<img src=\" javascript:XSS\" title=\"1\">boo</img>",
+ "output": "<img title='1'/>boo",
+ "rexml": "<img title='1' />"
+ },
+
+ {
+ "name": "xml_base",
+ "input": "<div xml:base=\"javascript:alert('XSS');//\">foo</div>",
+ "output": "<div>foo</div>"
+ },
+
+ {
+ "name": "xul",
+ "input": "<p style=\"-moz-binding:url('http://ha.ckers.org/xssmoz.xml#xss')\">fubar</p>",
+ "output": "<p style=''>fubar</p>"
+ },
+
+ {
+ "name": "quotes_in_attributes",
+ "input": "<img src='foo' title='\"foo\" bar' />",
+ "rexml": "<img src='foo' title='\"foo\" bar' />",
+ "output": "<img title='&quot;foo&quot; bar' src='foo'/>"
+ },
+
+ {
+ "name": "uri_refs_in_svg_attributes",
+ "input": "<rect fill='url(#foo)' />",
+ "rexml": "<rect fill='url(#foo)'></rect>",
+ "xhtml": "<rect fill='url(#foo)'></rect>",
+ "output": "<rect fill='url(#foo)'/>"
+ },
+
+ {
+ "name": "absolute_uri_refs_in_svg_attributes",
+ "input": "<rect fill='url(http://bad.com/) #fff' />",
+ "rexml": "<rect fill=' #fff'></rect>",
+ "xhtml": "<rect fill=' #fff'></rect>",
+ "output": "<rect fill=' #fff'/>"
+ },
+
+ {
+ "name": "uri_ref_with_space_in svg_attribute",
+ "input": "<rect fill='url(\n#foo)' />",
+ "rexml": "<rect fill='url(\n#foo)'></rect>",
+ "xhtml": "<rect fill='url(\n#foo)'></rect>",
+ "output": "<rect fill='url(\n#foo)'/>"
+ },
+
+ {
+ "name": "absolute_uri_ref_with_space_in svg_attribute",
+ "input": "<rect fill=\"url(\nhttp://bad.com/)\" />",
+ "rexml": "<rect fill=' '></rect>",
+ "xhtml": "<rect fill=' '></rect>",
+ "output": "<rect fill=' '/>"
+ },
+
+ {
+ "name": "allow_html5_image_tag",
+ "input": "<image src='foo' />",
+ "rexml": "&lt;image src=\"foo\"&gt;&lt;/image&gt;",
+ "output": "&lt;image src=\"foo\"/&gt;"
+ },
+
+ {
+ "name": "style_attr_end_with_nothing",
+ "input": "<div style=\"color: blue\" />",
+ "output": "<div style='color: blue;'/>",
+ "xhtml": "<div style='color: blue;'></div>",
+ "rexml": "<div style='color: blue;'></div>"
+ },
+
+ {
+ "name": "style_attr_end_with_space",
+ "input": "<div style=\"color: blue \" />",
+ "output": "<div style='color: blue ;'/>",
+ "xhtml": "<div style='color: blue ;'></div>",
+ "rexml": "<div style='color: blue ;'></div>"
+ },
+
+ {
+ "name": "style_attr_end_with_semicolon",
+ "input": "<div style=\"color: blue;\" />",
+ "output": "<div style='color: blue;'/>",
+ "xhtml": "<div style='color: blue;'></div>",
+ "rexml": "<div style='color: blue;'></div>"
+ },
+
+ {
+ "name": "style_attr_end_with_semicolon_space",
+ "input": "<div style=\"color: blue; \" />",
+ "output": "<div style='color: blue;'/>",
+ "xhtml": "<div style='color: blue;'></div>",
+ "rexml": "<div style='color: blue;'></div>"
+ },
+
+ {
+ "name": "attributes_with_embedded_quotes",
+ "input": "<img src=doesntexist.jpg\"'onerror=\"alert(1) />",
+ "output": "<img src='doesntexist.jpg&quot;&apos;onerror=&quot;alert(1)'/>",
+ "rexml": "Ill-formed XHTML!"
+ },
+
+ {
+ "name": "attributes_with_embedded_quotes_II",
+ "input": "<img src=notthere.jpg\"\"onerror=\"alert(2) />",
+ "output": "<img src='notthere.jpg&quot;&quot;onerror=&quot;alert(2)'/>",
+ "rexml": "Ill-formed XHTML!"
+ }
+]
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/serializer/core.test b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/serializer/core.test
new file mode 100644
index 00000000000..c0b4222d2d9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/serializer/core.test
@@ -0,0 +1,125 @@
+{"tests": [
+
+{"description": "proper attribute value escaping",
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "span", [{"namespace": null, "name": "title", "value": "test \"with\" &quot;"}]]],
+ "expected": ["<span title='test \"with\" &amp;quot;'>"]
+},
+
+{"description": "proper attribute value non-quoting",
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "span", [{"namespace": null, "name": "title", "value": "foo"}]]],
+ "expected": ["<span title=foo>"],
+ "xhtml": ["<span title=\"foo\">"]
+},
+
+{"description": "proper attribute value non-quoting (with <)",
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "span", [{"namespace": null, "name": "title", "value": "foo<bar"}]]],
+ "expected": ["<span title=foo<bar>"],
+ "xhtml": ["<span title=\"foo&lt;bar\">"]
+},
+
+{"description": "proper attribute value quoting (with =)",
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "span", [{"namespace": null, "name": "title", "value": "foo=bar"}]]],
+ "expected": ["<span title=\"foo=bar\">"]
+},
+
+{"description": "proper attribute value quoting (with >)",
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "span", [{"namespace": null, "name": "title", "value": "foo>bar"}]]],
+ "expected": ["<span title=\"foo>bar\">"]
+},
+
+{"description": "proper attribute value quoting (with \")",
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "span", [{"namespace": null, "name": "title", "value": "foo\"bar"}]]],
+ "expected": ["<span title='foo\"bar'>"]
+},
+
+{"description": "proper attribute value quoting (with ')",
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "span", [{"namespace": null, "name": "title", "value": "foo'bar"}]]],
+ "expected": ["<span title=\"foo'bar\">"]
+},
+
+{"description": "proper attribute value quoting (with both \" and ')",
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "span", [{"namespace": null, "name": "title", "value": "foo'bar\"baz"}]]],
+ "expected": ["<span title=\"foo'bar&quot;baz\">"]
+},
+
+{"description": "proper attribute value quoting (with space)",
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "span", [{"namespace": null, "name": "title", "value": "foo bar"}]]],
+ "expected": ["<span title=\"foo bar\">"]
+},
+
+{"description": "proper attribute value quoting (with tab)",
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "span", [{"namespace": null, "name": "title", "value": "foo\tbar"}]]],
+ "expected": ["<span title=\"foo\tbar\">"]
+},
+
+{"description": "proper attribute value quoting (with LF)",
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "span", [{"namespace": null, "name": "title", "value": "foo\nbar"}]]],
+ "expected": ["<span title=\"foo\nbar\">"]
+},
+
+{"description": "proper attribute value quoting (with CR)",
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "span", [{"namespace": null, "name": "title", "value": "foo\rbar"}]]],
+ "expected": ["<span title=\"foo\rbar\">"]
+},
+
+{"description": "proper attribute value non-quoting (with linetab)",
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "span", [{"namespace": null, "name": "title", "value": "foo\u000Bbar"}]]],
+ "expected": ["<span title=foo\u000Bbar>"],
+ "xhtml": ["<span title=\"foo\u000Bbar\">"]
+},
+
+{"description": "proper attribute value quoting (with form feed)",
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "span", [{"namespace": null, "name": "title", "value": "foo\u000Cbar"}]]],
+ "expected": ["<span title=\"foo\u000Cbar\">"]
+},
+
+{"description": "void element (as EmptyTag token)",
+ "input": [["EmptyTag", "img", {}]],
+ "expected": ["<img>"],
+ "xhtml": ["<img />"]
+},
+
+{"description": "void element (as StartTag token)",
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "img", {}]],
+ "expected": ["<img>"],
+ "xhtml": ["<img />"]
+},
+
+{"description": "doctype in error",
+ "input": [["Doctype", "foo"]],
+ "expected": ["<!DOCTYPE foo>"]
+},
+
+{"description": "character data",
+ "options": {"encoding":"utf-8"},
+ "input": [["Characters", "a<b>c&d"]],
+ "expected": ["a&lt;b&gt;c&amp;d"]
+},
+
+{"description": "rcdata",
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "script", {}], ["Characters", "a<b>c&d"]],
+ "expected": ["<script>a<b>c&d"],
+ "xhtml": ["<script>a&lt;b&gt;c&amp;d"]
+},
+
+{"description": "doctype",
+ "input": [["Doctype", "HTML"]],
+ "expected": ["<!DOCTYPE HTML>"]
+},
+
+{"description": "HTML 4.01 DOCTYPE",
+ "input": [["Doctype", "HTML", "-//W3C//DTD HTML 4.01//EN", "http://www.w3.org/TR/html4/strict.dtd"]],
+ "expected": ["<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">"]
+},
+
+{"description": "HTML 4.01 DOCTYPE without system identifer",
+ "input": [["Doctype", "HTML", "-//W3C//DTD HTML 4.01//EN"]],
+ "expected": ["<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\">"]
+},
+
+{"description": "IBM DOCTYPE without public identifer",
+ "input": [["Doctype", "html", "", "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd"]],
+ "expected": ["<!DOCTYPE html SYSTEM \"http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd\">"]
+}
+
+]}
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/serializer/injectmeta.test b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/serializer/injectmeta.test
new file mode 100644
index 00000000000..feaaa44f839
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/serializer/injectmeta.test
@@ -0,0 +1,66 @@
+{"tests": [
+
+{"description": "no encoding",
+ "options": {"inject_meta_charset": true},
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "head", {}], ["EndTag", "http://www.w3.org/1999/xhtml", "head"]],
+ "expected": [""],
+ "xhtml": ["<head></head>"]
+},
+
+{"description": "empytag head",
+ "options": {"inject_meta_charset": true, "encoding":"utf-8"},
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "head", {}], ["EndTag", "http://www.w3.org/1999/xhtml", "head"]],
+ "expected": ["<meta charset=utf-8>"],
+ "xhtml": ["<head><meta charset=\"utf-8\" /></head>"]
+},
+
+{"description": "head w/title",
+ "options": {"inject_meta_charset": true, "encoding":"utf-8"},
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "head", {}], ["StartTag", "http://www.w3.org/1999/xhtml","title",{}], ["Characters", "foo"],["EndTag", "http://www.w3.org/1999/xhtml", "title"], ["EndTag", "http://www.w3.org/1999/xhtml", "head"]],
+ "expected": ["<meta charset=utf-8><title>foo</title>"],
+ "xhtml": ["<head><meta charset=\"utf-8\" /><title>foo</title></head>"]
+},
+
+{"description": "head w/meta-charset",
+ "options": {"inject_meta_charset": true, "encoding":"utf-8"},
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "head", {}], ["EmptyTag","meta",[{"namespace": null, "name": "charset", "value": "ascii"}]], ["EndTag", "http://www.w3.org/1999/xhtml", "head"]],
+ "expected": ["<meta charset=utf-8>"],
+ "xhtml": ["<head><meta charset=\"utf-8\" /></head>"]
+},
+
+{"description": "head w/ two meta-charset",
+ "options": {"inject_meta_charset": true, "encoding":"utf-8"},
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "head", {}], ["EmptyTag","meta",[{"namespace": null, "name": "charset", "value": "ascii"}]], ["EmptyTag","meta",[{"namespace": null, "name": "charset", "value": "ascii"}]], ["EndTag", "http://www.w3.org/1999/xhtml", "head"]],
+ "expected": ["<meta charset=utf-8><meta charset=utf-8>", "<head><meta charset=utf-8><meta charset=ascii>"],
+ "xhtml": ["<head><meta charset=\"utf-8\" /><meta charset=\"utf-8\" /></head>", "<head><meta charset=\"utf-8\" /><meta charset=\"ascii\" /></head>"]
+},
+
+{"description": "head w/robots",
+ "options": {"inject_meta_charset": true, "encoding":"utf-8"},
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "head", {}], ["EmptyTag","meta",[{"namespace": null, "name": "name", "value": "robots"},{"namespace": null, "name": "content", "value": "noindex"}]], ["EndTag", "http://www.w3.org/1999/xhtml", "head"]],
+ "expected": ["<meta charset=utf-8><meta content=noindex name=robots>"],
+ "xhtml": ["<head><meta charset=\"utf-8\" /><meta content=\"noindex\" name=\"robots\" /></head>"]
+},
+
+{"description": "head w/robots & charset",
+ "options": {"inject_meta_charset": true, "encoding":"utf-8"},
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "head", {}], ["EmptyTag","meta",[{"namespace": null, "name": "name", "value": "robots"},{"namespace": null, "name": "content", "value": "noindex"}]], ["EmptyTag","meta",[{"namespace": null, "name": "charset", "value": "ascii"}]], ["EndTag", "http://www.w3.org/1999/xhtml", "head"]],
+ "expected": ["<meta content=noindex name=robots><meta charset=utf-8>"],
+ "xhtml": ["<head><meta content=\"noindex\" name=\"robots\" /><meta charset=\"utf-8\" /></head>"]
+},
+
+{"description": "head w/ charset in http-equiv content-type",
+ "options": {"inject_meta_charset": true, "encoding":"utf-8"},
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "head", {}], ["EmptyTag","meta",[{"namespace": null, "name": "http-equiv", "value": "content-type"}, {"namespace": null, "name": "content", "value": "text/html; charset=ascii"}]], ["EndTag", "http://www.w3.org/1999/xhtml", "head"]],
+ "expected": ["<meta content=\"text/html; charset=utf-8\" http-equiv=content-type>"],
+ "xhtml": ["<head><meta content=\"text/html; charset=utf-8\" http-equiv=\"content-type\" /></head>"]
+},
+
+{"description": "head w/robots & charset in http-equiv content-type",
+ "options": {"inject_meta_charset": true, "encoding":"utf-8"},
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "head", {}], ["EmptyTag","meta",[{"namespace": null, "name": "name", "value": "robots"},{"namespace": null, "name": "content", "value": "noindex"}]], ["EmptyTag","meta",[{"namespace": null, "name": "http-equiv", "value": "content-type"}, {"namespace": null, "name": "content", "value": "text/html; charset=ascii"}]], ["EndTag", "http://www.w3.org/1999/xhtml", "head"]],
+ "expected": ["<meta content=noindex name=robots><meta content=\"text/html; charset=utf-8\" http-equiv=content-type>"],
+ "xhtml": ["<head><meta content=\"noindex\" name=\"robots\" /><meta content=\"text/html; charset=utf-8\" http-equiv=\"content-type\" /></head>"]
+}
+
+]}
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/serializer/optionaltags.test b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/serializer/optionaltags.test
new file mode 100644
index 00000000000..80a5edf8968
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/serializer/optionaltags.test
@@ -0,0 +1,965 @@
+{"tests": [
+
+{"description": "html start-tag followed by text, with attributes",
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "html", [{"namespace": null, "name": "lang", "value": "en"}]], ["Characters", "foo"]],
+ "expected": ["<html lang=en>foo"]
+},
+
+
+
+{"description": "html start-tag followed by comment",
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "html", {}], ["Comment", "foo"]],
+ "expected": ["<html><!--foo-->"]
+},
+
+{"description": "html start-tag followed by space character",
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "html", {}], ["Characters", " foo"]],
+ "expected": ["<html> foo"]
+},
+
+{"description": "html start-tag followed by text",
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "html", {}], ["Characters", "foo"]],
+ "expected": ["foo"]
+},
+
+{"description": "html start-tag followed by start-tag",
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "html", {}], ["StartTag", "http://www.w3.org/1999/xhtml", "foo", {}]],
+ "expected": ["<foo>"]
+},
+
+{"description": "html start-tag followed by end-tag",
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "html", {}], ["EndTag", "http://www.w3.org/1999/xhtml", "foo"]],
+ "expected": ["</foo>"]
+},
+
+{"description": "html start-tag at EOF (shouldn't ever happen?!)",
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "html", {}]],
+ "expected": [""]
+},
+
+
+
+{"description": "html end-tag followed by comment",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "html"], ["Comment", "foo"]],
+ "expected": ["</html><!--foo-->"]
+},
+
+{"description": "html end-tag followed by space character",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "html"], ["Characters", " foo"]],
+ "expected": ["</html> foo"]
+},
+
+{"description": "html end-tag followed by text",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "html"], ["Characters", "foo"]],
+ "expected": ["foo"]
+},
+
+{"description": "html end-tag followed by start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "html"], ["StartTag", "http://www.w3.org/1999/xhtml", "foo", {}]],
+ "expected": ["<foo>"]
+},
+
+{"description": "html end-tag followed by end-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "html"], ["EndTag", "http://www.w3.org/1999/xhtml", "foo"]],
+ "expected": ["</foo>"]
+},
+
+{"description": "html end-tag at EOF",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "html"]],
+ "expected": [""]
+},
+
+
+
+
+{"description": "head start-tag followed by comment",
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "head", {}], ["Comment", "foo"]],
+ "expected": ["<head><!--foo-->"]
+},
+
+{"description": "head start-tag followed by space character",
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "head", {}], ["Characters", " foo"]],
+ "expected": ["<head> foo"]
+},
+
+{"description": "head start-tag followed by text",
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "head", {}], ["Characters", "foo"]],
+ "expected": ["<head>foo"]
+},
+
+{"description": "head start-tag followed by start-tag",
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "head", {}], ["StartTag", "http://www.w3.org/1999/xhtml", "foo", {}]],
+ "expected": ["<foo>"]
+},
+
+{"description": "head start-tag followed by end-tag (shouldn't ever happen?!)",
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "head", {}], ["EndTag", "http://www.w3.org/1999/xhtml", "foo"]],
+ "expected": ["<head></foo>", "</foo>"]
+},
+
+{"description": "empty head element",
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "head", {}], ["EndTag", "http://www.w3.org/1999/xhtml", "head"]],
+ "expected": [""]
+},
+
+{"description": "head start-tag followed by empty-tag",
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "head", {}], ["EmptyTag", "foo", {}]],
+ "expected": ["<foo>"]
+},
+
+{"description": "head start-tag at EOF (shouldn't ever happen?!)",
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "head", {}]],
+ "expected": ["<head>", ""]
+},
+
+
+
+{"description": "head end-tag followed by comment",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "head"], ["Comment", "foo"]],
+ "expected": ["</head><!--foo-->"]
+},
+
+{"description": "head end-tag followed by space character",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "head"], ["Characters", " foo"]],
+ "expected": ["</head> foo"]
+},
+
+{"description": "head end-tag followed by text",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "head"], ["Characters", "foo"]],
+ "expected": ["foo"]
+},
+
+{"description": "head end-tag followed by start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "head"], ["StartTag", "http://www.w3.org/1999/xhtml", "foo", {}]],
+ "expected": ["<foo>"]
+},
+
+{"description": "head end-tag followed by end-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "head"], ["EndTag", "http://www.w3.org/1999/xhtml", "foo"]],
+ "expected": ["</foo>"]
+},
+
+{"description": "head end-tag at EOF",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "head"]],
+ "expected": [""]
+},
+
+
+
+
+{"description": "body start-tag followed by comment",
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "body", {}], ["Comment", "foo"]],
+ "expected": ["<body><!--foo-->"]
+},
+
+{"description": "body start-tag followed by space character",
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "body", {}], ["Characters", " foo"]],
+ "expected": ["<body> foo"]
+},
+
+{"description": "body start-tag followed by text",
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "body", {}], ["Characters", "foo"]],
+ "expected": ["foo"]
+},
+
+{"description": "body start-tag followed by start-tag",
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "body", {}], ["StartTag", "http://www.w3.org/1999/xhtml", "foo", {}]],
+ "expected": ["<foo>"]
+},
+
+{"description": "body start-tag followed by end-tag",
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "body", {}], ["EndTag", "http://www.w3.org/1999/xhtml", "foo"]],
+ "expected": ["</foo>"]
+},
+
+{"description": "body start-tag at EOF (shouldn't ever happen?!)",
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "body", {}]],
+ "expected": [""]
+},
+
+
+
+{"description": "body end-tag followed by comment",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "body"], ["Comment", "foo"]],
+ "expected": ["</body><!--foo-->"]
+},
+
+{"description": "body end-tag followed by space character",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "body"], ["Characters", " foo"]],
+ "expected": ["</body> foo"]
+},
+
+{"description": "body end-tag followed by text",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "body"], ["Characters", "foo"]],
+ "expected": ["foo"]
+},
+
+{"description": "body end-tag followed by start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "body"], ["StartTag", "http://www.w3.org/1999/xhtml", "foo", {}]],
+ "expected": ["<foo>"]
+},
+
+{"description": "body end-tag followed by end-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "body"], ["EndTag", "http://www.w3.org/1999/xhtml", "foo"]],
+ "expected": ["</foo>"]
+},
+
+{"description": "body end-tag at EOF",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "body"]],
+ "expected": [""]
+},
+
+
+
+
+{"description": "li end-tag followed by comment",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "li"], ["Comment", "foo"]],
+ "expected": ["</li><!--foo-->"]
+},
+
+{"description": "li end-tag followed by space character",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "li"], ["Characters", " foo"]],
+ "expected": ["</li> foo"]
+},
+
+{"description": "li end-tag followed by text",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "li"], ["Characters", "foo"]],
+ "expected": ["</li>foo"]
+},
+
+{"description": "li end-tag followed by start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "li"], ["StartTag", "http://www.w3.org/1999/xhtml", "foo", {}]],
+ "expected": ["</li><foo>"]
+},
+
+{"description": "li end-tag followed by li start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "li"], ["StartTag", "http://www.w3.org/1999/xhtml", "li", {}]],
+ "expected": ["<li>"]
+},
+
+{"description": "li end-tag followed by end-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "li"], ["EndTag", "http://www.w3.org/1999/xhtml", "foo"]],
+ "expected": ["</foo>"]
+},
+
+{"description": "li end-tag at EOF",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "li"]],
+ "expected": [""]
+},
+
+
+
+
+{"description": "dt end-tag followed by comment",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "dt"], ["Comment", "foo"]],
+ "expected": ["</dt><!--foo-->"]
+},
+
+{"description": "dt end-tag followed by space character",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "dt"], ["Characters", " foo"]],
+ "expected": ["</dt> foo"]
+},
+
+{"description": "dt end-tag followed by text",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "dt"], ["Characters", "foo"]],
+ "expected": ["</dt>foo"]
+},
+
+{"description": "dt end-tag followed by start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "dt"], ["StartTag", "http://www.w3.org/1999/xhtml", "foo", {}]],
+ "expected": ["</dt><foo>"]
+},
+
+{"description": "dt end-tag followed by dt start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "dt"], ["StartTag", "http://www.w3.org/1999/xhtml", "dt", {}]],
+ "expected": ["<dt>"]
+},
+
+{"description": "dt end-tag followed by dd start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "dt"], ["StartTag", "http://www.w3.org/1999/xhtml", "dd", {}]],
+ "expected": ["<dd>"]
+},
+
+{"description": "dt end-tag followed by end-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "dt"], ["EndTag", "http://www.w3.org/1999/xhtml", "foo"]],
+ "expected": ["</dt></foo>"]
+},
+
+{"description": "dt end-tag at EOF",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "dt"]],
+ "expected": ["</dt>"]
+},
+
+
+
+
+{"description": "dd end-tag followed by comment",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "dd"], ["Comment", "foo"]],
+ "expected": ["</dd><!--foo-->"]
+},
+
+{"description": "dd end-tag followed by space character",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "dd"], ["Characters", " foo"]],
+ "expected": ["</dd> foo"]
+},
+
+{"description": "dd end-tag followed by text",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "dd"], ["Characters", "foo"]],
+ "expected": ["</dd>foo"]
+},
+
+{"description": "dd end-tag followed by start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "dd"], ["StartTag", "http://www.w3.org/1999/xhtml", "foo", {}]],
+ "expected": ["</dd><foo>"]
+},
+
+{"description": "dd end-tag followed by dd start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "dd"], ["StartTag", "http://www.w3.org/1999/xhtml", "dd", {}]],
+ "expected": ["<dd>"]
+},
+
+{"description": "dd end-tag followed by dt start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "dd"], ["StartTag", "http://www.w3.org/1999/xhtml", "dt", {}]],
+ "expected": ["<dt>"]
+},
+
+{"description": "dd end-tag followed by end-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "dd"], ["EndTag", "http://www.w3.org/1999/xhtml", "foo"]],
+ "expected": ["</foo>"]
+},
+
+{"description": "dd end-tag at EOF",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "dd"]],
+ "expected": [""]
+},
+
+
+
+
+{"description": "p end-tag followed by comment",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "p"], ["Comment", "foo"]],
+ "expected": ["</p><!--foo-->"]
+},
+
+{"description": "p end-tag followed by space character",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "p"], ["Characters", " foo"]],
+ "expected": ["</p> foo"]
+},
+
+{"description": "p end-tag followed by text",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "p"], ["Characters", "foo"]],
+ "expected": ["</p>foo"]
+},
+
+{"description": "p end-tag followed by start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "p"], ["StartTag", "http://www.w3.org/1999/xhtml", "foo", {}]],
+ "expected": ["</p><foo>"]
+},
+
+{"description": "p end-tag followed by address start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "p"], ["StartTag", "http://www.w3.org/1999/xhtml", "address", {}]],
+ "expected": ["<address>"]
+},
+
+{"description": "p end-tag followed by article start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "p"], ["StartTag", "http://www.w3.org/1999/xhtml", "article", {}]],
+ "expected": ["<article>"]
+},
+
+{"description": "p end-tag followed by aside start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "p"], ["StartTag", "http://www.w3.org/1999/xhtml", "aside", {}]],
+ "expected": ["<aside>"]
+},
+
+{"description": "p end-tag followed by blockquote start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "p"], ["StartTag", "http://www.w3.org/1999/xhtml", "blockquote", {}]],
+ "expected": ["<blockquote>"]
+},
+
+{"description": "p end-tag followed by datagrid start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "p"], ["StartTag", "http://www.w3.org/1999/xhtml", "datagrid", {}]],
+ "expected": ["<datagrid>"]
+},
+
+{"description": "p end-tag followed by dialog start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "p"], ["StartTag", "http://www.w3.org/1999/xhtml", "dialog", {}]],
+ "expected": ["<dialog>"]
+},
+
+{"description": "p end-tag followed by dir start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "p"], ["StartTag", "http://www.w3.org/1999/xhtml", "dir", {}]],
+ "expected": ["<dir>"]
+},
+
+{"description": "p end-tag followed by div start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "p"], ["StartTag", "http://www.w3.org/1999/xhtml", "div", {}]],
+ "expected": ["<div>"]
+},
+
+{"description": "p end-tag followed by dl start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "p"], ["StartTag", "http://www.w3.org/1999/xhtml", "dl", {}]],
+ "expected": ["<dl>"]
+},
+
+{"description": "p end-tag followed by fieldset start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "p"], ["StartTag", "http://www.w3.org/1999/xhtml", "fieldset", {}]],
+ "expected": ["<fieldset>"]
+},
+
+{"description": "p end-tag followed by footer start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "p"], ["StartTag", "http://www.w3.org/1999/xhtml", "footer", {}]],
+ "expected": ["<footer>"]
+},
+
+{"description": "p end-tag followed by form start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "p"], ["StartTag", "http://www.w3.org/1999/xhtml", "form", {}]],
+ "expected": ["<form>"]
+},
+
+{"description": "p end-tag followed by h1 start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "p"], ["StartTag", "http://www.w3.org/1999/xhtml", "h1", {}]],
+ "expected": ["<h1>"]
+},
+
+{"description": "p end-tag followed by h2 start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "p"], ["StartTag", "http://www.w3.org/1999/xhtml", "h2", {}]],
+ "expected": ["<h2>"]
+},
+
+{"description": "p end-tag followed by h3 start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "p"], ["StartTag", "http://www.w3.org/1999/xhtml", "h3", {}]],
+ "expected": ["<h3>"]
+},
+
+{"description": "p end-tag followed by h4 start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "p"], ["StartTag", "http://www.w3.org/1999/xhtml", "h4", {}]],
+ "expected": ["<h4>"]
+},
+
+{"description": "p end-tag followed by h5 start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "p"], ["StartTag", "http://www.w3.org/1999/xhtml", "h5", {}]],
+ "expected": ["<h5>"]
+},
+
+{"description": "p end-tag followed by h6 start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "p"], ["StartTag", "http://www.w3.org/1999/xhtml", "h6", {}]],
+ "expected": ["<h6>"]
+},
+
+{"description": "p end-tag followed by header start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "p"], ["StartTag", "http://www.w3.org/1999/xhtml", "header", {}]],
+ "expected": ["<header>"]
+},
+
+{"description": "p end-tag followed by hr empty-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "p"], ["EmptyTag", "hr", {}]],
+ "expected": ["<hr>"]
+},
+
+{"description": "p end-tag followed by menu start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "p"], ["StartTag", "http://www.w3.org/1999/xhtml", "menu", {}]],
+ "expected": ["<menu>"]
+},
+
+{"description": "p end-tag followed by nav start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "p"], ["StartTag", "http://www.w3.org/1999/xhtml", "nav", {}]],
+ "expected": ["<nav>"]
+},
+
+{"description": "p end-tag followed by ol start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "p"], ["StartTag", "http://www.w3.org/1999/xhtml", "ol", {}]],
+ "expected": ["<ol>"]
+},
+
+{"description": "p end-tag followed by p start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "p"], ["StartTag", "http://www.w3.org/1999/xhtml", "p", {}]],
+ "expected": ["<p>"]
+},
+
+{"description": "p end-tag followed by pre start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "p"], ["StartTag", "http://www.w3.org/1999/xhtml", "pre", {}]],
+ "expected": ["<pre>"]
+},
+
+{"description": "p end-tag followed by section start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "p"], ["StartTag", "http://www.w3.org/1999/xhtml", "section", {}]],
+ "expected": ["<section>"]
+},
+
+{"description": "p end-tag followed by table start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "p"], ["StartTag", "http://www.w3.org/1999/xhtml", "table", {}]],
+ "expected": ["<table>"]
+},
+
+{"description": "p end-tag followed by ul start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "p"], ["StartTag", "http://www.w3.org/1999/xhtml", "ul", {}]],
+ "expected": ["<ul>"]
+},
+
+{"description": "p end-tag followed by end-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "p"], ["EndTag", "http://www.w3.org/1999/xhtml", "foo"]],
+ "expected": ["</foo>"]
+},
+
+{"description": "p end-tag at EOF",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "p"]],
+ "expected": [""]
+},
+
+
+
+
+{"description": "optgroup end-tag followed by comment",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "optgroup"], ["Comment", "foo"]],
+ "expected": ["</optgroup><!--foo-->"]
+},
+
+{"description": "optgroup end-tag followed by space character",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "optgroup"], ["Characters", " foo"]],
+ "expected": ["</optgroup> foo"]
+},
+
+{"description": "optgroup end-tag followed by text",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "optgroup"], ["Characters", "foo"]],
+ "expected": ["</optgroup>foo"]
+},
+
+{"description": "optgroup end-tag followed by start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "optgroup"], ["StartTag", "http://www.w3.org/1999/xhtml", "foo", {}]],
+ "expected": ["</optgroup><foo>"]
+},
+
+{"description": "optgroup end-tag followed by optgroup start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "optgroup"], ["StartTag", "http://www.w3.org/1999/xhtml", "optgroup", {}]],
+ "expected": ["<optgroup>"]
+},
+
+{"description": "optgroup end-tag followed by end-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "optgroup"], ["EndTag", "http://www.w3.org/1999/xhtml", "foo"]],
+ "expected": ["</foo>"]
+},
+
+{"description": "optgroup end-tag at EOF",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "optgroup"]],
+ "expected": [""]
+},
+
+
+
+
+{"description": "option end-tag followed by comment",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "option"], ["Comment", "foo"]],
+ "expected": ["</option><!--foo-->"]
+},
+
+{"description": "option end-tag followed by space character",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "option"], ["Characters", " foo"]],
+ "expected": ["</option> foo"]
+},
+
+{"description": "option end-tag followed by text",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "option"], ["Characters", "foo"]],
+ "expected": ["</option>foo"]
+},
+
+{"description": "option end-tag followed by optgroup start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "option"], ["StartTag", "http://www.w3.org/1999/xhtml", "optgroup", {}]],
+ "expected": ["<optgroup>"]
+},
+
+{"description": "option end-tag followed by start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "option"], ["StartTag", "http://www.w3.org/1999/xhtml", "foo", {}]],
+ "expected": ["</option><foo>"]
+},
+
+{"description": "option end-tag followed by option start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "option"], ["StartTag", "http://www.w3.org/1999/xhtml", "option", {}]],
+ "expected": ["<option>"]
+},
+
+{"description": "option end-tag followed by end-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "option"], ["EndTag", "http://www.w3.org/1999/xhtml", "foo"]],
+ "expected": ["</foo>"]
+},
+
+{"description": "option end-tag at EOF",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "option"]],
+ "expected": [""]
+},
+
+
+
+
+{"description": "colgroup start-tag followed by comment",
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "colgroup", {}], ["Comment", "foo"]],
+ "expected": ["<colgroup><!--foo-->"]
+},
+
+{"description": "colgroup start-tag followed by space character",
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "colgroup", {}], ["Characters", " foo"]],
+ "expected": ["<colgroup> foo"]
+},
+
+{"description": "colgroup start-tag followed by text",
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "colgroup", {}], ["Characters", "foo"]],
+ "expected": ["<colgroup>foo"]
+},
+
+{"description": "colgroup start-tag followed by start-tag",
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "colgroup", {}], ["StartTag", "http://www.w3.org/1999/xhtml", "foo", {}]],
+ "expected": ["<colgroup><foo>"]
+},
+
+{"description": "first colgroup in a table with a col child",
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "table", {}], ["StartTag", "http://www.w3.org/1999/xhtml", "colgroup", {}], ["EmptyTag", "col", {}]],
+ "expected": ["<table><col>"]
+},
+
+{"description": "colgroup with a col child, following another colgroup",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "colgroup"], ["StartTag", "http://www.w3.org/1999/xhtml", "colgroup", {}], ["StartTag", "http://www.w3.org/1999/xhtml", "col", {}]],
+ "expected": ["</colgroup><col>", "<colgroup><col>"]
+},
+
+{"description": "colgroup start-tag followed by end-tag",
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "colgroup", {}], ["EndTag", "http://www.w3.org/1999/xhtml", "foo"]],
+ "expected": ["<colgroup></foo>"]
+},
+
+{"description": "colgroup start-tag at EOF",
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "colgroup", {}]],
+ "expected": ["<colgroup>"]
+},
+
+
+
+{"description": "colgroup end-tag followed by comment",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "colgroup"], ["Comment", "foo"]],
+ "expected": ["</colgroup><!--foo-->"]
+},
+
+{"description": "colgroup end-tag followed by space character",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "colgroup"], ["Characters", " foo"]],
+ "expected": ["</colgroup> foo"]
+},
+
+{"description": "colgroup end-tag followed by text",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "colgroup"], ["Characters", "foo"]],
+ "expected": ["foo"]
+},
+
+{"description": "colgroup end-tag followed by start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "colgroup"], ["StartTag", "http://www.w3.org/1999/xhtml", "foo", {}]],
+ "expected": ["<foo>"]
+},
+
+{"description": "colgroup end-tag followed by end-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "colgroup"], ["EndTag", "http://www.w3.org/1999/xhtml", "foo"]],
+ "expected": ["</foo>"]
+},
+
+{"description": "colgroup end-tag at EOF",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "colgroup"]],
+ "expected": [""]
+},
+
+
+
+
+{"description": "thead end-tag followed by comment",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "thead"], ["Comment", "foo"]],
+ "expected": ["</thead><!--foo-->"]
+},
+
+{"description": "thead end-tag followed by space character",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "thead"], ["Characters", " foo"]],
+ "expected": ["</thead> foo"]
+},
+
+{"description": "thead end-tag followed by text",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "thead"], ["Characters", "foo"]],
+ "expected": ["</thead>foo"]
+},
+
+{"description": "thead end-tag followed by start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "thead"], ["StartTag", "http://www.w3.org/1999/xhtml", "foo", {}]],
+ "expected": ["</thead><foo>"]
+},
+
+{"description": "thead end-tag followed by tbody start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "thead"], ["StartTag", "http://www.w3.org/1999/xhtml", "tbody", {}]],
+ "expected": ["<tbody>"]
+},
+
+{"description": "thead end-tag followed by tfoot start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "thead"], ["StartTag", "http://www.w3.org/1999/xhtml", "tfoot", {}]],
+ "expected": ["<tfoot>"]
+},
+
+{"description": "thead end-tag followed by end-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "thead"], ["EndTag", "http://www.w3.org/1999/xhtml", "foo"]],
+ "expected": ["</thead></foo>"]
+},
+
+{"description": "thead end-tag at EOF",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "thead"]],
+ "expected": ["</thead>"]
+},
+
+
+
+
+{"description": "tbody start-tag followed by comment",
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "tbody", {}], ["Comment", "foo"]],
+ "expected": ["<tbody><!--foo-->"]
+},
+
+{"description": "tbody start-tag followed by space character",
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "tbody", {}], ["Characters", " foo"]],
+ "expected": ["<tbody> foo"]
+},
+
+{"description": "tbody start-tag followed by text",
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "tbody", {}], ["Characters", "foo"]],
+ "expected": ["<tbody>foo"]
+},
+
+{"description": "tbody start-tag followed by start-tag",
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "tbody", {}], ["StartTag", "http://www.w3.org/1999/xhtml", "foo", {}]],
+ "expected": ["<tbody><foo>"]
+},
+
+{"description": "first tbody in a table with a tr child",
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "table", {}], ["StartTag", "http://www.w3.org/1999/xhtml", "tbody", {}], ["StartTag", "http://www.w3.org/1999/xhtml", "tr", {}]],
+ "expected": ["<table><tr>"]
+},
+
+{"description": "tbody with a tr child, following another tbody",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "tbody"], ["StartTag", "http://www.w3.org/1999/xhtml", "tbody", {}], ["StartTag", "http://www.w3.org/1999/xhtml", "tr", {}]],
+ "expected": ["<tbody><tr>", "</tbody><tr>"]
+},
+
+{"description": "tbody with a tr child, following a thead",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "thead"], ["StartTag", "http://www.w3.org/1999/xhtml", "tbody", {}], ["StartTag", "http://www.w3.org/1999/xhtml", "tr", {}]],
+ "expected": ["<tbody><tr>", "</thead><tr>"]
+},
+
+{"description": "tbody with a tr child, following a tfoot",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "tfoot"], ["StartTag", "http://www.w3.org/1999/xhtml", "tbody", {}], ["StartTag", "http://www.w3.org/1999/xhtml", "tr", {}]],
+ "expected": ["<tbody><tr>", "</tfoot><tr>"]
+},
+
+{"description": "tbody start-tag followed by end-tag",
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "tbody", {}], ["EndTag", "http://www.w3.org/1999/xhtml", "foo"]],
+ "expected": ["<tbody></foo>"]
+},
+
+{"description": "tbody start-tag at EOF",
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "tbody", {}]],
+ "expected": ["<tbody>"]
+},
+
+
+
+{"description": "tbody end-tag followed by comment",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "tbody"], ["Comment", "foo"]],
+ "expected": ["</tbody><!--foo-->"]
+},
+
+{"description": "tbody end-tag followed by space character",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "tbody"], ["Characters", " foo"]],
+ "expected": ["</tbody> foo"]
+},
+
+{"description": "tbody end-tag followed by text",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "tbody"], ["Characters", "foo"]],
+ "expected": ["</tbody>foo"]
+},
+
+{"description": "tbody end-tag followed by start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "tbody"], ["StartTag", "http://www.w3.org/1999/xhtml", "foo", {}]],
+ "expected": ["</tbody><foo>"]
+},
+
+{"description": "tbody end-tag followed by tbody start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "tbody"], ["StartTag", "http://www.w3.org/1999/xhtml", "tbody", {}]],
+ "expected": ["<tbody>", "</tbody>"]
+},
+
+{"description": "tbody end-tag followed by tfoot start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "tbody"], ["StartTag", "http://www.w3.org/1999/xhtml", "tfoot", {}]],
+ "expected": ["<tfoot>"]
+},
+
+{"description": "tbody end-tag followed by end-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "tbody"], ["EndTag", "http://www.w3.org/1999/xhtml", "foo"]],
+ "expected": ["</foo>"]
+},
+
+{"description": "tbody end-tag at EOF",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "tbody"]],
+ "expected": [""]
+},
+
+
+
+
+{"description": "tfoot end-tag followed by comment",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "tfoot"], ["Comment", "foo"]],
+ "expected": ["</tfoot><!--foo-->"]
+},
+
+{"description": "tfoot end-tag followed by space character",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "tfoot"], ["Characters", " foo"]],
+ "expected": ["</tfoot> foo"]
+},
+
+{"description": "tfoot end-tag followed by text",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "tfoot"], ["Characters", "foo"]],
+ "expected": ["</tfoot>foo"]
+},
+
+{"description": "tfoot end-tag followed by start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "tfoot"], ["StartTag", "http://www.w3.org/1999/xhtml", "foo", {}]],
+ "expected": ["</tfoot><foo>"]
+},
+
+{"description": "tfoot end-tag followed by tbody start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "tfoot"], ["StartTag", "http://www.w3.org/1999/xhtml", "tbody", {}]],
+ "expected": ["<tbody>", "</tfoot>"]
+},
+
+{"description": "tfoot end-tag followed by end-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "tfoot"], ["EndTag", "http://www.w3.org/1999/xhtml", "foo"]],
+ "expected": ["</foo>"]
+},
+
+{"description": "tfoot end-tag at EOF",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "tfoot"]],
+ "expected": [""]
+},
+
+
+
+
+{"description": "tr end-tag followed by comment",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "tr"], ["Comment", "foo"]],
+ "expected": ["</tr><!--foo-->"]
+},
+
+{"description": "tr end-tag followed by space character",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "tr"], ["Characters", " foo"]],
+ "expected": ["</tr> foo"]
+},
+
+{"description": "tr end-tag followed by text",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "tr"], ["Characters", "foo"]],
+ "expected": ["</tr>foo"]
+},
+
+{"description": "tr end-tag followed by start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "tr"], ["StartTag", "http://www.w3.org/1999/xhtml", "foo", {}]],
+ "expected": ["</tr><foo>"]
+},
+
+{"description": "tr end-tag followed by tr start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "tr"], ["StartTag", "http://www.w3.org/1999/xhtml", "tr", {}]],
+ "expected": ["<tr>", "</tr>"]
+},
+
+{"description": "tr end-tag followed by end-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "tr"], ["EndTag", "http://www.w3.org/1999/xhtml", "foo"]],
+ "expected": ["</foo>"]
+},
+
+{"description": "tr end-tag at EOF",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "tr"]],
+ "expected": [""]
+},
+
+
+
+
+{"description": "td end-tag followed by comment",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "td"], ["Comment", "foo"]],
+ "expected": ["</td><!--foo-->"]
+},
+
+{"description": "td end-tag followed by space character",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "td"], ["Characters", " foo"]],
+ "expected": ["</td> foo"]
+},
+
+{"description": "td end-tag followed by text",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "td"], ["Characters", "foo"]],
+ "expected": ["</td>foo"]
+},
+
+{"description": "td end-tag followed by start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "td"], ["StartTag", "http://www.w3.org/1999/xhtml", "foo", {}]],
+ "expected": ["</td><foo>"]
+},
+
+{"description": "td end-tag followed by td start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "td"], ["StartTag", "http://www.w3.org/1999/xhtml", "td", {}]],
+ "expected": ["<td>", "</td>"]
+},
+
+{"description": "td end-tag followed by th start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "td"], ["StartTag", "http://www.w3.org/1999/xhtml", "th", {}]],
+ "expected": ["<th>", "</td>"]
+},
+
+{"description": "td end-tag followed by end-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "td"], ["EndTag", "http://www.w3.org/1999/xhtml", "foo"]],
+ "expected": ["</foo>"]
+},
+
+{"description": "td end-tag at EOF",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "td"]],
+ "expected": [""]
+},
+
+
+
+
+{"description": "th end-tag followed by comment",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "th"], ["Comment", "foo"]],
+ "expected": ["</th><!--foo-->"]
+},
+
+{"description": "th end-tag followed by space character",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "th"], ["Characters", " foo"]],
+ "expected": ["</th> foo"]
+},
+
+{"description": "th end-tag followed by text",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "th"], ["Characters", "foo"]],
+ "expected": ["</th>foo"]
+},
+
+{"description": "th end-tag followed by start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "th"], ["StartTag", "http://www.w3.org/1999/xhtml", "foo", {}]],
+ "expected": ["</th><foo>"]
+},
+
+{"description": "th end-tag followed by th start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "th"], ["StartTag", "http://www.w3.org/1999/xhtml", "th", {}]],
+ "expected": ["<th>", "</th>"]
+},
+
+{"description": "th end-tag followed by td start-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "th"], ["StartTag", "http://www.w3.org/1999/xhtml", "td", {}]],
+ "expected": ["<td>", "</th>"]
+},
+
+{"description": "th end-tag followed by end-tag",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml", "th"], ["EndTag", "http://www.w3.org/1999/xhtml", "foo"]],
+ "expected": ["</foo>"]
+},
+
+{"description": "th end-tag at EOF",
+ "input": [["EndTag", "http://www.w3.org/1999/xhtml" , "th"]],
+ "expected": [""]
+}
+
+]}
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/serializer/options.test b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/serializer/options.test
new file mode 100644
index 00000000000..6f342dd3f73
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/serializer/options.test
@@ -0,0 +1,60 @@
+{"tests":[
+
+{"description": "quote_char=\"'\"",
+ "options": {"quote_char": "'"},
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "span", [{"namespace": null, "name": "title", "value": "test 'with' quote_char"}]]],
+ "expected": ["<span title='test &#39;with&#39; quote_char'>"]
+},
+
+{"description": "quote_attr_values=true",
+ "options": {"quote_attr_values": true},
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "button", [{"namespace": null, "name": "disabled", "value" :"disabled"}]]],
+ "expected": ["<button disabled>"],
+ "xhtml": ["<button disabled=\"disabled\">"]
+},
+
+{"description": "quote_attr_values=true with irrelevant",
+ "options": {"quote_attr_values": true},
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "div", [{"namespace": null, "name": "irrelevant", "value" :"irrelevant"}]]],
+ "expected": ["<div irrelevant>"],
+ "xhtml": ["<div irrelevant=\"irrelevant\">"]
+},
+
+{"description": "use_trailing_solidus=true with void element",
+ "options": {"use_trailing_solidus": true},
+ "input": [["EmptyTag", "img", {}]],
+ "expected": ["<img />"]
+},
+
+{"description": "use_trailing_solidus=true with non-void element",
+ "options": {"use_trailing_solidus": true},
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "div", {}]],
+ "expected": ["<div>"]
+},
+
+{"description": "minimize_boolean_attributes=false",
+ "options": {"minimize_boolean_attributes": false},
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "div", [{"namespace": null, "name": "irrelevant", "value" :"irrelevant"}]]],
+ "expected": ["<div irrelevant=irrelevant>"],
+ "xhtml": ["<div irrelevant=\"irrelevant\">"]
+},
+
+{"description": "minimize_boolean_attributes=false with empty value",
+ "options": {"minimize_boolean_attributes": false},
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "div", [{"namespace": null, "name": "irrelevant", "value" :""}]]],
+ "expected": ["<div irrelevant=\"\">"]
+},
+
+{"description": "escape less than signs in attribute values",
+ "options": {"escape_lt_in_attrs": true},
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "a", [{"namespace": null, "name": "title", "value": "a<b>c&d"}]]],
+ "expected": ["<a title=\"a&lt;b>c&amp;d\">"]
+},
+
+{"description": "rcdata",
+ "options": {"escape_rcdata": true},
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "script", {}], ["Characters", "a<b>c&d"]],
+ "expected": ["<script>a&lt;b&gt;c&amp;d"]
+}
+
+]}
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/serializer/whitespace.test b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/serializer/whitespace.test
new file mode 100644
index 00000000000..e5d050d3bee
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/serializer/whitespace.test
@@ -0,0 +1,51 @@
+{"tests": [
+
+{"description": "bare text with leading spaces",
+ "options": {"strip_whitespace": true},
+ "input": [["Characters", "\t\r\n\u000C foo"]],
+ "expected": [" foo"]
+},
+
+{"description": "bare text with trailing spaces",
+ "options": {"strip_whitespace": true},
+ "input": [["Characters", "foo \t\r\n\u000C"]],
+ "expected": ["foo "]
+},
+
+{"description": "bare text with inner spaces",
+ "options": {"strip_whitespace": true},
+ "input": [["Characters", "foo \t\r\n\u000C bar"]],
+ "expected": ["foo bar"]
+},
+
+{"description": "text within <pre>",
+ "options": {"strip_whitespace": true},
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "pre", {}], ["Characters", "\t\r\n\u000C foo \t\r\n\u000C bar \t\r\n\u000C"], ["EndTag", "http://www.w3.org/1999/xhtml", "pre"]],
+ "expected": ["<pre>\t\r\n\u000C foo \t\r\n\u000C bar \t\r\n\u000C</pre>"]
+},
+
+{"description": "text within <pre>, with inner markup",
+ "options": {"strip_whitespace": true},
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "pre", {}], ["Characters", "\t\r\n\u000C fo"], ["StartTag", "http://www.w3.org/1999/xhtml", "span", {}], ["Characters", "o \t\r\n\u000C b"], ["EndTag", "http://www.w3.org/1999/xhtml", "span"], ["Characters", "ar \t\r\n\u000C"], ["EndTag", "http://www.w3.org/1999/xhtml", "pre"]],
+ "expected": ["<pre>\t\r\n\u000C fo<span>o \t\r\n\u000C b</span>ar \t\r\n\u000C</pre>"]
+},
+
+{"description": "text within <textarea>",
+ "options": {"strip_whitespace": true},
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "textarea", {}], ["Characters", "\t\r\n\u000C foo \t\r\n\u000C bar \t\r\n\u000C"], ["EndTag", "http://www.w3.org/1999/xhtml", "textarea"]],
+ "expected": ["<textarea>\t\r\n\u000C foo \t\r\n\u000C bar \t\r\n\u000C</textarea>"]
+},
+
+{"description": "text within <script>",
+ "options": {"strip_whitespace": true},
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "script", {}], ["Characters", "\t\r\n\u000C foo \t\r\n\u000C bar \t\r\n\u000C"], ["EndTag", "http://www.w3.org/1999/xhtml", "script"]],
+ "expected": ["<script>\t\r\n\u000C foo \t\r\n\u000C bar \t\r\n\u000C</script>"]
+},
+
+{"description": "text within <style>",
+ "options": {"strip_whitespace": true},
+ "input": [["StartTag", "http://www.w3.org/1999/xhtml", "style", {}], ["Characters", "\t\r\n\u000C foo \t\r\n\u000C bar \t\r\n\u000C"], ["EndTag", "http://www.w3.org/1999/xhtml", "style"]],
+ "expected": ["<style>\t\r\n\u000C foo \t\r\n\u000C bar \t\r\n\u000C</style>"]
+}
+
+]} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/sniffer/htmlOrFeed.json b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/sniffer/htmlOrFeed.json
new file mode 100644
index 00000000000..c1506dbcdde
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/sniffer/htmlOrFeed.json
@@ -0,0 +1,43 @@
+[
+ {"type": "text/html", "input": ""},
+ {"type": "text/html", "input": "<!---->"},
+ {"type": "text/html", "input": "<!--asdfaslkjdf;laksjdf as;dkfjsd-->"},
+ {"type": "text/html", "input": "<!"},
+ {"type": "text/html", "input": "\t"},
+ {"type": "text/html", "input": "<!>"},
+ {"type": "text/html", "input": "<?"},
+ {"type": "text/html", "input": "<??>"},
+ {"type": "application/rss+xml", "input": "<rss"},
+ {"type": "application/atom+xml", "input": "<feed"},
+ {"type": "text/html", "input": "<html"},
+ {"type": "text/html", "input": "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n<html><head>\n<title>302 Found</title>\n</head><body>\n<h1>Found</h1>\n<p>The document has moved <a href=\"http://feeds.feedburner.com/gofug\">here</a>.</p>\n</body></html>\n"},
+ {"type": "text/html", "input": "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">\r\n<HTML><HEAD>\r\n <link rel=\"stylesheet\" type=\"text/css\" href=\"http://cache.blogads.com/289619328/feed.css\" /><link rel=\"stylesheet\" type=\"text/css\" href=\"http://cache.blogads.com/431602649/feed.css\" />\r\n<link rel=\"stylesheet\" type=\"text/css\" href=\"http://cache.blogads.com/382549546/feed.css\" />\r\n<link rel=\"stylesheet\" type=\"text/css\" href=\"http://cache.blogads.com/314618017/feed.css\" /><META http-equiv=\"expires\" content="},
+ {"type": "text/html", "input": "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\r\n<html>\r\n<head>\r\n<title>Xiaxue - Chicken pie blogger.</title><meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\"><style type=\"text/css\">\r\n<style type=\"text/css\">\r\n<!--\r\nbody {\r\n background-color: #FFF2F2;\r\n}\r\n.style1 {font-family: Georgia, \"Times New Roman\", Times, serif}\r\n.style2 {\r\n color: #8a567c;\r\n font-size: 14px;\r\n font-family: Georgia, \"Times New Roman\", Times, serif;\r\n}\r"},
+ {"type": "text/html", "input": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\"><html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\r\n<head> \r\n<title>Google Operating System</title>\r\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\r\n<meta name=\"Description\" content=\"Unofficial news and tips about Google. A blog that watches Google's latest developments and the attempts to move your operating system online.\" />\r\n<meta name=\"generator\" c"},
+ {"type": "text/html", "input": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\"><html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\r\n<head>\r\n <title>Assimilated Press</title> <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\r\n<meta name=\"MSSmartTagsPreventParsing\" content=\"true\" />\r\n<meta name=\"generator\" content=\"Blogger\" />\r\n<link rel=\"alternate\" type=\"application/atom+xml\" title=\"Assimilated Press - Atom\" href=\"http://assimila"},
+ {"type": "text/html", "input": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\"><html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\r\n<head>\r\n <title>PostSecret</title>\r\n<META name=\"keywords\" Content=\"secrets, postcard, secret, postcards, postsecret, postsecrets,online confessional, post secret, post secrets, artomatic, post a secret\"><META name=\"discription\" Content=\"See a Secret...Share a Secret\"> <meta http-equiv=\"Content-Type\" content=\"te"},
+ {"type": "text/html", "input": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n<html xmlns='http://www.w3.org/1999/xhtml' xmlns:b='http://www.google.com/2005/gml/b' xmlns:data='http://www.google.com/2005/gml/data' xmlns:expr='http://www.google.com/2005/gml/expr'>\n <head>\n \n <meta content='text/html; charset=UTF-8' http-equiv='Content-Type'/>\n <meta content='true' name='MSSmartTagsPreventParsing'/>\n <meta content='blogger' name='generator'/>\n <link rel=\"alternate\" typ"},
+ {"type": "text/html", "input": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\" dir=\"ltr\" lang=\"ja\">\n<head profile=\"http://gmpg.org/xfn/11\"> \n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" /> \n<title> CMS Lever</title><link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"http://s.wordpress.com/wp-content/themes/pub/twenty-eight/2813.css\"/>\n<link rel=\"alternate\" type=\"application/rss+xml\" title=\"RSS 2.0\" h"},
+ {"type": "text/html", "input": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\" dir=\"ltr\" lang=\"en\"><head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n<title> Park Avenue Peerage</title>\t<meta name=\"generator\" content=\"WordPress.com\" />\t<!-- feeds -->\n\t<link rel=\"alternate\" type=\"application/rss+xml\" title=\"RSS 2.0\" href=\"http://parkavenuepeerage.wordpress.com/feed/\" />\t<link rel=\"pingback\" href="},
+ {"type": "text/html", "input": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\" dir=\"ltr\" lang=\"ja\"><head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n<title> \u884c\u96f2\u6d41\u6c34 -like a floating clouds and running water-</title>\t<meta name=\"generator\" content=\"WordPress.com\" />\t<!-- feeds -->\n\t<link rel=\"alternate\" type=\"application/rss+xml\" title=\"RSS 2.0\" href=\"http://shw4.wordpress.com/feed/\" />\t<li"},
+ {"type": "text/html", "input": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\"><html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n<meta name=\"generator\" content=\"http://www.typepad.com/\" />\n<title>Go Fug Yourself</title><link rel=\"stylesheet\" href=\"http://gofugyourself.typepad.com/go_fug_yourself/styles.css\" type=\"text/css\" />\n<link rel=\"alternate\" type=\"application/atom+xml\" title=\"Atom\" "},
+ {"type": "text/html", "input": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\" dir=\"ltr\" lang=\"en\"><head profile=\"http://gmpg.org/xfn/11\">\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" /><title> Ladies&#8230;</title><meta name=\"generator\" content=\"WordPress.com\" /> <!-- leave this for stats --><link rel=\"stylesheet\" href=\"http://s.wordpress.com/wp-content/themes/default/style.css?1\" type=\"tex"},
+ {"type": "text/html", "input": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\r\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\r\n<head>\r\n <title>The Sartorialist</title> <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\r\n<meta name=\"MSSmartTagsPreventParsing\" content=\"true\" />\r\n<meta name=\"generator\" content=\"Blogger\" />\r\n<link rel=\"alternate\" type=\"application/atom+xml\" title=\"The Sartorialist - Atom\" href=\"http://thesartorialist.blogspot"},
+ {"type": "text/html", "input": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \n \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\"><html xmlns=\"http://www.w3.org/1999/xhtml\" lang=\"en\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=ISO-8859-1\" />\n<meta name=\"generator\" content=\"http://www.typepad.com/\" />\n<title>Creating Passionate Users</title><link rel=\"stylesheet\" href=\"http://headrush.typepad.com/creating_passionate_users/styles.css\" type=\"text/css\" />\n<link rel=\"alternate\" type"},
+ {"type": "text/html", "input": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n\t\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\" id=\"sixapart-standard\">\n<head>\n\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n\t<meta name=\"generator\" content=\"http://www.typepad.com/\" />\n\t\n\t\n <meta name=\"keywords\" content=\"marketing, blog, seth, ideas, respect, permission\" />\n <meta name=\"description\" content=\"Seth Godin's riffs on marketing, respect, and the "},
+ {"type": "text/html", "input": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n\t\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\" id=\"sixapart-standard\">\n<head>\n\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n\t<meta name=\"generator\" content=\"http://www.typepad.com/\" />\n\t\n\t\n \n <meta name=\"description\" content=\" Western Civilization hangs in the balance. This blog is part of the solution,the cure. Get your heads out of the sand and Fight the G"},
+ {"type": "text/html", "input": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\" dir=\"ltr\" lang=\"en\">\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=pahrefhttpwwwfeedburnercomtarget_blankimgsrchttpwwwfeedburnercomfbimagespubpowered_by_fbgifaltPoweredbyFeedBurnerstyleborder0ap\" />\n<title> From Under the Rotunda</title>\n<link rel=\"stylesheet\" href=\"http://s.wordpress.com/wp-content/themes/pub/andreas04/style.css\" type=\"text/css\""},
+ {"type": "application/atom+xml", "input": "<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href=\"http://www.blogger.com/styles/atom.css\" type=\"text/css\"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/'><id>tag:blogger.com,1999:blog-10861780</id><updated>2007-07-27T12:38:50.888-07:00</updated><title type='text'>Official Google Blog</title><link rel='alternate' type='text/html' href='http://googleblog.blogspot.com/'/><link rel='next' type='application/atom+xml' href='http://googleblog.blogs"},
+ {"type": "application/rss+xml", "input": "<?xml version='1.0' encoding='UTF-8'?><rss xmlns:atom='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' version='2.0'><channel><atom:id>tag:blogger.com,1999:blog-10861780</atom:id><lastBuildDate>Fri, 27 Jul 2007 19:38:50 +0000</lastBuildDate><title>Official Google Blog</title><description/><link>http://googleblog.blogspot.com/</link><managingEditor>Eric Case</managingEditor><generator>Blogger</generator><openSearch:totalResults>729</openSearch:totalResults><openSearc"},
+ {"type": "application/rss+xml", "input": "<?xml version=\"1.0\" encoding=\"pahrefhttpwwwfeedburnercomtarget_blankimgsrchttpwwwfeedburnercomfbimagespubpowered_by_fbgifaltPoweredbyFeedBurnerstyleborder0ap\"?>\n<!-- generator=\"wordpress/MU\" -->\n<rss version=\"2.0\"\n\txmlns:content=\"http://purl.org/rss/1.0/modules/content/\"\n\txmlns:wfw=\"http://wellformedweb.org/CommentAPI/\"\n\txmlns:dc=\"http://purl.org/dc/elements/1.1/\"\n\t><channel>\n\t<title>From Under the Rotunda</title>\n\t<link>http://dannybernardi.wordpress.com</link>\n\t<description>The Monographs of Danny Ber"},
+ {"type": "application/rss+xml", "input": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!-- generator=\"wordpress/MU\" -->\n<rss version=\"2.0\"\n\txmlns:content=\"http://purl.org/rss/1.0/modules/content/\"\n\txmlns:wfw=\"http://wellformedweb.org/CommentAPI/\"\n\txmlns:dc=\"http://purl.org/dc/elements/1.1/\"\n\t><channel>\n\t<title>CMS Lever</title>\n\t<link>http://kanaguri.wordpress.com</link>\n\t<description>CMS\u306e\u6c17\u306b\u306a\u3063\u305f\u3053\u3068</description>\n\t<pubDate>Wed, 18 Jul 2007 21:26:22 +0000</pubDate>\n\t<generator>http://wordpress.org/?v=MU</generator>\n\t<language>ja</languag"},
+ {"type": "application/atom+xml", "input": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<feed xmlns=\"http://www.w3.org/2005/Atom\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:thr=\"http://purl.org/syndication/thread/1.0\">\n <title>Atlas Shrugs</title>\n <link rel=\"self\" type=\"application/atom+xml\" href=\"http://atlasshrugs2000.typepad.com/atlas_shrugs/atom.xml\" />\n <link rel=\"alternate\" type=\"text/html\" href=\"http://atlasshrugs2000.typepad.com/atlas_shrugs/\" />\n <id>tag:typepad.com,2003:weblog-132946</id>\n <updated>2007-08-15T16:07:34-04"},
+ {"type": "application/atom+xml", "input": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<?xml-stylesheet href=\"http://feeds.feedburner.com/~d/styles/atom10full.xsl\" type=\"text/xsl\" media=\"screen\"?><?xml-stylesheet href=\"http://feeds.feedburner.com/~d/styles/itemcontent.css\" type=\"text/css\" media=\"screen\"?><feed xmlns=\"http://www.w3.org/2005/Atom\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:thr=\"http://purl.org/syndication/thread/1.0\" xmlns:feedburner=\"http://rssnamespace.org/feedburner/ext/1.0\">\r\n <title>Creating Passionate Users</title>\r\n "},
+ {"type": "application/atom+xml", "input": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<?xml-stylesheet href=\"http://feeds.feedburner.com/~d/styles/atom10full.xsl\" type=\"text/xsl\" media=\"screen\"?><?xml-stylesheet href=\"http://feeds.feedburner.com/~d/styles/itemcontent.css\" type=\"text/css\" media=\"screen\"?><feed xmlns=\"http://www.w3.org/2005/Atom\" xmlns:feedburner=\"http://rssnamespace.org/feedburner/ext/1.0\">\r\n <title>Seth's Blog</title>\r\n <link rel=\"alternate\" type=\"text/html\" href=\"http://sethgodin.typepad.com/seths_blog/\" />\r\n <link rel=\"s"},
+ {"type": "application/atom+xml", "input": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<?xml-stylesheet href=\"http://feeds.feedburner.com/~d/styles/atom10full.xsl\" type=\"text/xsl\" media=\"screen\"?><?xml-stylesheet href=\"http://feeds.feedburner.com/~d/styles/itemcontent.css\" type=\"text/css\" media=\"screen\"?><feed xmlns=\"http://www.w3.org/2005/Atom\" xmlns:openSearch=\"http://a9.com/-/spec/opensearchrss/1.0/\" xmlns:feedburner=\"http://rssnamespace.org/feedburner/ext/1.0\"><id>tag:blogger.com,1999:blog-32454861</id><updated>2007-07-31T21:44:09.867+02:00</upd"},
+ {"type": "application/atom+xml", "input": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<?xml-stylesheet href=\"http://feeds.feedburner.com/~d/styles/atomfull.xsl\" type=\"text/xsl\" media=\"screen\"?><?xml-stylesheet href=\"http://feeds.feedburner.com/~d/styles/itemcontent.css\" type=\"text/css\" media=\"screen\"?><feed xmlns=\"http://purl.org/atom/ns#\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:feedburner=\"http://rssnamespace.org/feedburner/ext/1.0\" version=\"0.3\">\r\n <title>Go Fug Yourself</title>\r\n <link rel=\"alternate\" type=\"text/html\" href=\"http://go"},
+ {"type": "application/rss+xml", "input": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<?xml-stylesheet href=\"http://feeds.feedburner.com/~d/styles/rss2full.xsl\" type=\"text/xsl\" media=\"screen\"?><?xml-stylesheet href=\"http://feeds.feedburner.com/~d/styles/itemcontent.css\" type=\"text/css\" media=\"screen\"?><rss xmlns:creativeCommons=\"http://backend.userland.com/creativeCommonsRssModule\" xmlns:feedburner=\"http://rssnamespace.org/feedburner/ext/1.0\" version=\"2.0\"><channel><title>Google Operating System</title><link>http://googlesystem.blogspot.com/</link>"},
+ {"type": "application/rss+xml", "input": "<?xml version=\"1.0\" encoding=\"\"?>\n<!-- generator=\"wordpress/MU\" -->\n<rss version=\"2.0\"\n\txmlns:content=\"http://purl.org/rss/1.0/modules/content/\"\n\txmlns:wfw=\"http://wellformedweb.org/CommentAPI/\"\n\txmlns:dc=\"http://purl.org/dc/elements/1.1/\"\n\t><channel>\n\t<title>Nunublog</title>\n\t<link>http://nunubh.wordpress.com</link>\n\t<description>Just Newbie Blog!</description>\n\t<pubDate>Mon, 09 Jul 2007 18:54:09 +0000</pubDate>\n\t<generator>http://wordpress.org/?v=MU</generator>\n\t<language>id</language>\n\t\t\t<item>\n\t\t<ti"},
+ {"type": "text/html", "input": "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\r\n<HEAD>\r\n<TITLE>Design*Sponge</TITLE><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\r\n<meta name=\"MSSmartTagsPreventParsing\" content=\"true\" />\r\n<meta name=\"generator\" content=\"Blogger\" />\r\n<link rel=\"alternate\" type=\"application/atom+xml\" title=\"Design*Sponge - Atom\" href=\"http://designsponge.blogspot.com/feeds/posts/default\" />\r\n<link rel=\"alternate\" type=\"application/rss+xml\" title=\"Design*Sponge - RSS\" href="},
+ {"type": "text/html", "input": "<HTML>\n<HEAD>\n<TITLE>Moved Temporarily</TITLE>\n</HEAD>\n<BODY BGCOLOR=\"#FFFFFF\" TEXT=\"#000000\">\n<H1>Moved Temporarily</H1>\nThe document has moved <A HREF=\"http://feeds.feedburner.com/thesecretdiaryofstevejobs\">here</A>.\n</BODY>\n</HTML>\n"}
+] \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/README.md b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/README.md
new file mode 100644
index 00000000000..4218c26bb0f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/README.md
@@ -0,0 +1,104 @@
+Tokenizer tests
+===============
+
+The test format is [JSON](http://www.json.org/). This has the advantage
+that the syntax allows backward-compatible extensions to the tests and
+the disadvantage that it is relatively verbose.
+
+Basic Structure
+---------------
+
+ {"tests": [
+     {"description": "Test description",
+     "input": "input_string",
+     "output": [expected_output_tokens],
+     "initialStates": [initial_states],
+     "lastStartTag": last_start_tag,
+     "ignoreErrorOrder": ignore_error_order
+     }
+ ]}
+
+Multiple tests per file are allowed simply by adding more objects to the
+"tests" list.
+
+`description`, `input` and `output` are always present. The other values
+are optional.
+
+### Test set-up
+
+`test.input` is a string containing the characters to pass to the
+tokenizer. Specifically, it represents the characters of the **input
+stream**, and so implementations are expected to perform the processing
+described in the spec's **Preprocessing the input stream** section
+before feeding the result to the tokenizer.
+
+If `test.doubleEscaped` is present and `true`, then `test.input` is not
+quite as described above. Instead, it must first be subjected to another
+round of unescaping (i.e., in addition to any unescaping involved in the
+JSON import), and the result of *that* represents the characters of the
+input stream. Currently, the only unescaping required by this option is
+to convert each sequence of the form \\uHHHH (where H is a hex digit)
+into the corresponding Unicode code point. (Note that this option also
+affects the interpretation of `test.output`.)
+
+`test.initialStates` is a list of strings, each being the name of a
+tokenizer state. The test should be run once for each string, using it
+to set the tokenizer's initial state for that run. If
+`test.initialStates` is omitted, it defaults to `["data state"]`.
+
+`test.lastStartTag` is a lowercase string that should be used as "the
+tag name of the last start tag to have been emitted from this
+tokenizer", referenced in the spec's definition of **appropriate end tag
+token**. If it is omitted, it is treated as if "no start tag has been
+emitted from this tokenizer".
+
+### Test results
+
+`test.output` is a list of tokens, ordered with the first produced by
+the tokenizer the first (leftmost) in the list. The list must mach the
+**complete** list of tokens that the tokenizer should produce. Valid
+tokens are:
+
+ ["DOCTYPE", name, public_id, system_id, correctness]
+ ["StartTag", name, {attributes}*, true*]
+ ["StartTag", name, {attributes}]
+ ["EndTag", name]
+ ["Comment", data]
+ ["Character", data]
+ "ParseError"
+
+`public_id` and `system_id` are either strings or `null`. `correctness`
+is either `true` or `false`; `true` corresponds to the force-quirks flag
+being false, and vice-versa.
+
+When the self-closing flag is set, the `StartTag` array has `true` as
+its fourth entry. When the flag is not set, the array has only three
+entries for backwards compatibility.
+
+All adjacent character tokens are coalesced into a single
+`["Character", data]` token.
+
+If `test.doubleEscaped` is present and `true`, then every string within
+`test.output` must be further unescaped (as described above) before
+comparing with the tokenizer's output.
+
+`test.ignoreErrorOrder` is a boolean value indicating that the order of
+`ParseError` tokens relative to other tokens in the output stream is
+unimportant, and implementations should ignore such differences between
+their output and `expected_output_tokens`. (This is used for errors
+emitted by the input stream preprocessing stage, since it is useful to
+test that code but it is undefined when the errors occur). If it is
+omitted, it defaults to `false`.
+
+xmlViolation tests
+------------------
+
+`tokenizer/xmlViolation.test` differs from the above in a couple of
+ways:
+
+- The name of the single member of the top-level JSON object is
+ "xmlViolationTests" instead of "tests".
+- Each test's expected output assumes that implementation is applying
+ the tweaks given in the spec's "Coercing an HTML DOM into an
+ infoset" section.
+
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/contentModelFlags.test b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/contentModelFlags.test
new file mode 100644
index 00000000000..89b8170c6bc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/contentModelFlags.test
@@ -0,0 +1,81 @@
+{"tests": [
+
+{"description":"PLAINTEXT content model flag",
+"initialStates":["PLAINTEXT state"],
+"lastStartTag":"plaintext",
+"input":"<head>&body;",
+"output":[["Character", "<head>&body;"]]},
+
+{"description":"End tag closing RCDATA or RAWTEXT",
+"initialStates":["RCDATA state", "RAWTEXT state"],
+"lastStartTag":"xmp",
+"input":"foo</xmp>",
+"output":[["Character", "foo"], ["EndTag", "xmp"]]},
+
+{"description":"End tag closing RCDATA or RAWTEXT (case-insensitivity)",
+"initialStates":["RCDATA state", "RAWTEXT state"],
+"lastStartTag":"xmp",
+"input":"foo</xMp>",
+"output":[["Character", "foo"], ["EndTag", "xmp"]]},
+
+{"description":"End tag closing RCDATA or RAWTEXT (ending with space)",
+"initialStates":["RCDATA state", "RAWTEXT state"],
+"lastStartTag":"xmp",
+"input":"foo</xmp ",
+"output":[["Character", "foo"], "ParseError"]},
+
+{"description":"End tag closing RCDATA or RAWTEXT (ending with EOF)",
+"initialStates":["RCDATA state", "RAWTEXT state"],
+"lastStartTag":"xmp",
+"input":"foo</xmp",
+"output":[["Character", "foo</xmp"]]},
+
+{"description":"End tag closing RCDATA or RAWTEXT (ending with slash)",
+"initialStates":["RCDATA state", "RAWTEXT state"],
+"lastStartTag":"xmp",
+"input":"foo</xmp/",
+"output":[["Character", "foo"], "ParseError"]},
+
+{"description":"End tag not closing RCDATA or RAWTEXT (ending with left-angle-bracket)",
+"initialStates":["RCDATA state", "RAWTEXT state"],
+"lastStartTag":"xmp",
+"input":"foo</xmp<",
+"output":[["Character", "foo</xmp<"]]},
+
+{"description":"End tag with incorrect name in RCDATA or RAWTEXT",
+"initialStates":["RCDATA state", "RAWTEXT state"],
+"lastStartTag":"xmp",
+"input":"</foo>bar</xmp>",
+"output":[["Character", "</foo>bar"], ["EndTag", "xmp"]]},
+
+{"description":"Partial end tags leading straight into partial end tags",
+"initialStates":["RCDATA state", "RAWTEXT state"],
+"lastStartTag":"xmp",
+"input":"</xmp</xmp</xmp>",
+"output":[["Character", "</xmp</xmp"], ["EndTag", "xmp"]]},
+
+{"description":"End tag with incorrect name in RCDATA or RAWTEXT (starting like correct name)",
+"initialStates":["RCDATA state", "RAWTEXT state"],
+"lastStartTag":"xmp",
+"input":"</foo>bar</xmpaar>",
+"output":[["Character", "</foo>bar</xmpaar>"]]},
+
+{"description":"End tag closing RCDATA or RAWTEXT, switching back to PCDATA",
+"initialStates":["RCDATA state", "RAWTEXT state"],
+"lastStartTag":"xmp",
+"input":"foo</xmp></baz>",
+"output":[["Character", "foo"], ["EndTag", "xmp"], ["EndTag", "baz"]]},
+
+{"description":"RAWTEXT w/ something looking like an entity",
+"initialStates":["RAWTEXT state"],
+"lastStartTag":"xmp",
+"input":"&foo;",
+"output":[["Character", "&foo;"]]},
+
+{"description":"RCDATA w/ an entity",
+"initialStates":["RCDATA state"],
+"lastStartTag":"textarea",
+"input":"&lt;",
+"output":[["Character", "<"]]}
+
+]}
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/domjs.test b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/domjs.test
new file mode 100644
index 00000000000..8f1e42f354f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/domjs.test
@@ -0,0 +1,96 @@
+{
+ "tests": [
+ {
+ "description":"CR in bogus comment state",
+ "input":"<?\u000d",
+ "output":["ParseError", ["Comment", "?\u000a"]]
+ },
+ {
+ "description":"CRLF in bogus comment state",
+ "input":"<?\u000d\u000a",
+ "output":["ParseError", ["Comment", "?\u000a"]]
+ },
+ {
+ "description":"CRLFLF in bogus comment state",
+ "input":"<?\u000d\u000a\u000a",
+ "output":["ParseError", ["Comment", "?\u000a\u000a"]]
+ },
+ {
+ "description":"NUL in RCDATA and RAWTEXT",
+ "doubleEscaped":true,
+ "initialStates":["RCDATA state", "RAWTEXT state"],
+ "input":"\\u0000",
+ "output":["ParseError", ["Character", "\\uFFFD"]]
+ },
+ {
+ "description":"leading U+FEFF must pass through",
+ "doubleEscaped":true,
+ "input":"\\uFEFFfoo\\uFEFFbar",
+ "output":[["Character", "\\uFEFFfoo\\uFEFFbar"]]
+ },
+ {
+ "description":"Non BMP-charref in in RCDATA",
+ "initialStates":["RCDATA state"],
+ "input":"&NotEqualTilde;",
+ "output":[["Character", "\u2242\u0338"]]
+ },
+ {
+ "description":"Bad charref in in RCDATA",
+ "initialStates":["RCDATA state"],
+ "input":"&NotEqualTild;",
+ "output":["ParseError", ["Character", "&NotEqualTild;"]]
+ },
+ {
+ "description":"lowercase endtags in RCDATA and RAWTEXT",
+ "initialStates":["RCDATA state", "RAWTEXT state"],
+ "lastStartTag":"xmp",
+ "input":"</XMP>",
+ "output":[["EndTag","xmp"]]
+ },
+ {
+ "description":"bad endtag in RCDATA and RAWTEXT",
+ "initialStates":["RCDATA state", "RAWTEXT state"],
+ "lastStartTag":"xmp",
+ "input":"</ XMP>",
+ "output":[["Character","</ XMP>"]]
+ },
+ {
+ "description":"bad endtag in RCDATA and RAWTEXT",
+ "initialStates":["RCDATA state", "RAWTEXT state"],
+ "lastStartTag":"xmp",
+ "input":"</xm>",
+ "output":[["Character","</xm>"]]
+ },
+ {
+ "description":"bad endtag in RCDATA and RAWTEXT",
+ "initialStates":["RCDATA state", "RAWTEXT state"],
+ "lastStartTag":"xmp",
+ "input":"</xm ",
+ "output":[["Character","</xm "]]
+ },
+ {
+ "description":"bad endtag in RCDATA and RAWTEXT",
+ "initialStates":["RCDATA state", "RAWTEXT state"],
+ "lastStartTag":"xmp",
+ "input":"</xm/",
+ "output":[["Character","</xm/"]]
+ },
+ {
+ "description":"Non BMP-charref in attribute",
+ "input":"<p id=\"&NotEqualTilde;\">",
+ "output":[["StartTag", "p", {"id":"\u2242\u0338"}]]
+ },
+ {
+ "description":"--!NUL in comment ",
+ "doubleEscaped":true,
+ "input":"<!----!\\u0000-->",
+ "output":["ParseError", "ParseError", ["Comment", "--!\\uFFFD"]]
+ },
+ {
+ "description":"space EOF after doctype ",
+ "input":"<!DOCTYPE html ",
+ "output":["ParseError", ["DOCTYPE", "html", null, null , false]]
+ }
+
+ ]
+}
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/entities.test b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/entities.test
new file mode 100644
index 00000000000..27b85a1cd0b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/entities.test
@@ -0,0 +1,283 @@
+{"tests": [
+
+{"description": "Undefined named entity in attribute value ending in semicolon and whose name starts with a known entity name.",
+"input":"<h a='&noti;'>",
+"output": [["StartTag", "h", {"a": "&noti;"}]]},
+
+{"description": "Entity name followed by the equals sign in an attribute value.",
+"input":"<h a='&lang='>",
+"output": [["StartTag", "h", {"a": "&lang="}]]},
+
+{"description": "CR as numeric entity",
+"input":"&#013;",
+"output": ["ParseError", ["Character", "\r"]]},
+
+{"description": "CR as hexadecimal numeric entity",
+"input":"&#x00D;",
+"output": ["ParseError", ["Character", "\r"]]},
+
+{"description": "Windows-1252 EURO SIGN numeric entity.",
+"input":"&#0128;",
+"output": ["ParseError", ["Character", "\u20AC"]]},
+
+{"description": "Windows-1252 REPLACEMENT CHAR numeric entity.",
+"input":"&#0129;",
+"output": ["ParseError", ["Character", "\u0081"]]},
+
+{"description": "Windows-1252 SINGLE LOW-9 QUOTATION MARK numeric entity.",
+"input":"&#0130;",
+"output": ["ParseError", ["Character", "\u201A"]]},
+
+{"description": "Windows-1252 LATIN SMALL LETTER F WITH HOOK numeric entity.",
+"input":"&#0131;",
+"output": ["ParseError", ["Character", "\u0192"]]},
+
+{"description": "Windows-1252 DOUBLE LOW-9 QUOTATION MARK numeric entity.",
+"input":"&#0132;",
+"output": ["ParseError", ["Character", "\u201E"]]},
+
+{"description": "Windows-1252 HORIZONTAL ELLIPSIS numeric entity.",
+"input":"&#0133;",
+"output": ["ParseError", ["Character", "\u2026"]]},
+
+{"description": "Windows-1252 DAGGER numeric entity.",
+"input":"&#0134;",
+"output": ["ParseError", ["Character", "\u2020"]]},
+
+{"description": "Windows-1252 DOUBLE DAGGER numeric entity.",
+"input":"&#0135;",
+"output": ["ParseError", ["Character", "\u2021"]]},
+
+{"description": "Windows-1252 MODIFIER LETTER CIRCUMFLEX ACCENT numeric entity.",
+"input":"&#0136;",
+"output": ["ParseError", ["Character", "\u02C6"]]},
+
+{"description": "Windows-1252 PER MILLE SIGN numeric entity.",
+"input":"&#0137;",
+"output": ["ParseError", ["Character", "\u2030"]]},
+
+{"description": "Windows-1252 LATIN CAPITAL LETTER S WITH CARON numeric entity.",
+"input":"&#0138;",
+"output": ["ParseError", ["Character", "\u0160"]]},
+
+{"description": "Windows-1252 SINGLE LEFT-POINTING ANGLE QUOTATION MARK numeric entity.",
+"input":"&#0139;",
+"output": ["ParseError", ["Character", "\u2039"]]},
+
+{"description": "Windows-1252 LATIN CAPITAL LIGATURE OE numeric entity.",
+"input":"&#0140;",
+"output": ["ParseError", ["Character", "\u0152"]]},
+
+{"description": "Windows-1252 REPLACEMENT CHAR numeric entity.",
+"input":"&#0141;",
+"output": ["ParseError", ["Character", "\u008D"]]},
+
+{"description": "Windows-1252 LATIN CAPITAL LETTER Z WITH CARON numeric entity.",
+"input":"&#0142;",
+"output": ["ParseError", ["Character", "\u017D"]]},
+
+{"description": "Windows-1252 REPLACEMENT CHAR numeric entity.",
+"input":"&#0143;",
+"output": ["ParseError", ["Character", "\u008F"]]},
+
+{"description": "Windows-1252 REPLACEMENT CHAR numeric entity.",
+"input":"&#0144;",
+"output": ["ParseError", ["Character", "\u0090"]]},
+
+{"description": "Windows-1252 LEFT SINGLE QUOTATION MARK numeric entity.",
+"input":"&#0145;",
+"output": ["ParseError", ["Character", "\u2018"]]},
+
+{"description": "Windows-1252 RIGHT SINGLE QUOTATION MARK numeric entity.",
+"input":"&#0146;",
+"output": ["ParseError", ["Character", "\u2019"]]},
+
+{"description": "Windows-1252 LEFT DOUBLE QUOTATION MARK numeric entity.",
+"input":"&#0147;",
+"output": ["ParseError", ["Character", "\u201C"]]},
+
+{"description": "Windows-1252 RIGHT DOUBLE QUOTATION MARK numeric entity.",
+"input":"&#0148;",
+"output": ["ParseError", ["Character", "\u201D"]]},
+
+{"description": "Windows-1252 BULLET numeric entity.",
+"input":"&#0149;",
+"output": ["ParseError", ["Character", "\u2022"]]},
+
+{"description": "Windows-1252 EN DASH numeric entity.",
+"input":"&#0150;",
+"output": ["ParseError", ["Character", "\u2013"]]},
+
+{"description": "Windows-1252 EM DASH numeric entity.",
+"input":"&#0151;",
+"output": ["ParseError", ["Character", "\u2014"]]},
+
+{"description": "Windows-1252 SMALL TILDE numeric entity.",
+"input":"&#0152;",
+"output": ["ParseError", ["Character", "\u02DC"]]},
+
+{"description": "Windows-1252 TRADE MARK SIGN numeric entity.",
+"input":"&#0153;",
+"output": ["ParseError", ["Character", "\u2122"]]},
+
+{"description": "Windows-1252 LATIN SMALL LETTER S WITH CARON numeric entity.",
+"input":"&#0154;",
+"output": ["ParseError", ["Character", "\u0161"]]},
+
+{"description": "Windows-1252 SINGLE RIGHT-POINTING ANGLE QUOTATION MARK numeric entity.",
+"input":"&#0155;",
+"output": ["ParseError", ["Character", "\u203A"]]},
+
+{"description": "Windows-1252 LATIN SMALL LIGATURE OE numeric entity.",
+"input":"&#0156;",
+"output": ["ParseError", ["Character", "\u0153"]]},
+
+{"description": "Windows-1252 REPLACEMENT CHAR numeric entity.",
+"input":"&#0157;",
+"output": ["ParseError", ["Character", "\u009D"]]},
+
+{"description": "Windows-1252 EURO SIGN hexadecimal numeric entity.",
+"input":"&#x080;",
+"output": ["ParseError", ["Character", "\u20AC"]]},
+
+{"description": "Windows-1252 REPLACEMENT CHAR hexadecimal numeric entity.",
+"input":"&#x081;",
+"output": ["ParseError", ["Character", "\u0081"]]},
+
+{"description": "Windows-1252 SINGLE LOW-9 QUOTATION MARK hexadecimal numeric entity.",
+"input":"&#x082;",
+"output": ["ParseError", ["Character", "\u201A"]]},
+
+{"description": "Windows-1252 LATIN SMALL LETTER F WITH HOOK hexadecimal numeric entity.",
+"input":"&#x083;",
+"output": ["ParseError", ["Character", "\u0192"]]},
+
+{"description": "Windows-1252 DOUBLE LOW-9 QUOTATION MARK hexadecimal numeric entity.",
+"input":"&#x084;",
+"output": ["ParseError", ["Character", "\u201E"]]},
+
+{"description": "Windows-1252 HORIZONTAL ELLIPSIS hexadecimal numeric entity.",
+"input":"&#x085;",
+"output": ["ParseError", ["Character", "\u2026"]]},
+
+{"description": "Windows-1252 DAGGER hexadecimal numeric entity.",
+"input":"&#x086;",
+"output": ["ParseError", ["Character", "\u2020"]]},
+
+{"description": "Windows-1252 DOUBLE DAGGER hexadecimal numeric entity.",
+"input":"&#x087;",
+"output": ["ParseError", ["Character", "\u2021"]]},
+
+{"description": "Windows-1252 MODIFIER LETTER CIRCUMFLEX ACCENT hexadecimal numeric entity.",
+"input":"&#x088;",
+"output": ["ParseError", ["Character", "\u02C6"]]},
+
+{"description": "Windows-1252 PER MILLE SIGN hexadecimal numeric entity.",
+"input":"&#x089;",
+"output": ["ParseError", ["Character", "\u2030"]]},
+
+{"description": "Windows-1252 LATIN CAPITAL LETTER S WITH CARON hexadecimal numeric entity.",
+"input":"&#x08A;",
+"output": ["ParseError", ["Character", "\u0160"]]},
+
+{"description": "Windows-1252 SINGLE LEFT-POINTING ANGLE QUOTATION MARK hexadecimal numeric entity.",
+"input":"&#x08B;",
+"output": ["ParseError", ["Character", "\u2039"]]},
+
+{"description": "Windows-1252 LATIN CAPITAL LIGATURE OE hexadecimal numeric entity.",
+"input":"&#x08C;",
+"output": ["ParseError", ["Character", "\u0152"]]},
+
+{"description": "Windows-1252 REPLACEMENT CHAR hexadecimal numeric entity.",
+"input":"&#x08D;",
+"output": ["ParseError", ["Character", "\u008D"]]},
+
+{"description": "Windows-1252 LATIN CAPITAL LETTER Z WITH CARON hexadecimal numeric entity.",
+"input":"&#x08E;",
+"output": ["ParseError", ["Character", "\u017D"]]},
+
+{"description": "Windows-1252 REPLACEMENT CHAR hexadecimal numeric entity.",
+"input":"&#x08F;",
+"output": ["ParseError", ["Character", "\u008F"]]},
+
+{"description": "Windows-1252 REPLACEMENT CHAR hexadecimal numeric entity.",
+"input":"&#x090;",
+"output": ["ParseError", ["Character", "\u0090"]]},
+
+{"description": "Windows-1252 LEFT SINGLE QUOTATION MARK hexadecimal numeric entity.",
+"input":"&#x091;",
+"output": ["ParseError", ["Character", "\u2018"]]},
+
+{"description": "Windows-1252 RIGHT SINGLE QUOTATION MARK hexadecimal numeric entity.",
+"input":"&#x092;",
+"output": ["ParseError", ["Character", "\u2019"]]},
+
+{"description": "Windows-1252 LEFT DOUBLE QUOTATION MARK hexadecimal numeric entity.",
+"input":"&#x093;",
+"output": ["ParseError", ["Character", "\u201C"]]},
+
+{"description": "Windows-1252 RIGHT DOUBLE QUOTATION MARK hexadecimal numeric entity.",
+"input":"&#x094;",
+"output": ["ParseError", ["Character", "\u201D"]]},
+
+{"description": "Windows-1252 BULLET hexadecimal numeric entity.",
+"input":"&#x095;",
+"output": ["ParseError", ["Character", "\u2022"]]},
+
+{"description": "Windows-1252 EN DASH hexadecimal numeric entity.",
+"input":"&#x096;",
+"output": ["ParseError", ["Character", "\u2013"]]},
+
+{"description": "Windows-1252 EM DASH hexadecimal numeric entity.",
+"input":"&#x097;",
+"output": ["ParseError", ["Character", "\u2014"]]},
+
+{"description": "Windows-1252 SMALL TILDE hexadecimal numeric entity.",
+"input":"&#x098;",
+"output": ["ParseError", ["Character", "\u02DC"]]},
+
+{"description": "Windows-1252 TRADE MARK SIGN hexadecimal numeric entity.",
+"input":"&#x099;",
+"output": ["ParseError", ["Character", "\u2122"]]},
+
+{"description": "Windows-1252 LATIN SMALL LETTER S WITH CARON hexadecimal numeric entity.",
+"input":"&#x09A;",
+"output": ["ParseError", ["Character", "\u0161"]]},
+
+{"description": "Windows-1252 SINGLE RIGHT-POINTING ANGLE QUOTATION MARK hexadecimal numeric entity.",
+"input":"&#x09B;",
+"output": ["ParseError", ["Character", "\u203A"]]},
+
+{"description": "Windows-1252 LATIN SMALL LIGATURE OE hexadecimal numeric entity.",
+"input":"&#x09C;",
+"output": ["ParseError", ["Character", "\u0153"]]},
+
+{"description": "Windows-1252 REPLACEMENT CHAR hexadecimal numeric entity.",
+"input":"&#x09D;",
+"output": ["ParseError", ["Character", "\u009D"]]},
+
+{"description": "Windows-1252 LATIN SMALL LETTER Z WITH CARON hexadecimal numeric entity.",
+"input":"&#x09E;",
+"output": ["ParseError", ["Character", "\u017E"]]},
+
+{"description": "Windows-1252 LATIN CAPITAL LETTER Y WITH DIAERESIS hexadecimal numeric entity.",
+"input":"&#x09F;",
+"output": ["ParseError", ["Character", "\u0178"]]},
+
+{"description": "Decimal numeric entity followed by hex character a.",
+"input":"&#97a",
+"output": ["ParseError", ["Character", "aa"]]},
+
+{"description": "Decimal numeric entity followed by hex character A.",
+"input":"&#97A",
+"output": ["ParseError", ["Character", "aA"]]},
+
+{"description": "Decimal numeric entity followed by hex character f.",
+"input":"&#97f",
+"output": ["ParseError", ["Character", "af"]]},
+
+{"description": "Decimal numeric entity followed by hex character A.",
+"input":"&#97F",
+"output": ["ParseError", ["Character", "aF"]]}
+
+]}
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/escapeFlag.test b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/escapeFlag.test
new file mode 100644
index 00000000000..18cb4309e05
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/escapeFlag.test
@@ -0,0 +1,33 @@
+{"tests": [
+
+{"description":"Commented close tag in RCDATA or RAWTEXT",
+"initialStates":["RCDATA state", "RAWTEXT state"],
+"lastStartTag":"xmp",
+"input":"foo<!--</xmp>--></xmp>",
+"output":[["Character", "foo<!--"], ["EndTag", "xmp"], ["Character", "-->"], ["EndTag", "xmp"]]},
+
+{"description":"Bogus comment in RCDATA or RAWTEXT",
+"initialStates":["RCDATA state", "RAWTEXT state"],
+"lastStartTag":"xmp",
+"input":"foo<!-->baz</xmp>",
+"output":[["Character", "foo<!-->baz"], ["EndTag", "xmp"]]},
+
+{"description":"End tag surrounded by bogus comment in RCDATA or RAWTEXT",
+"initialStates":["RCDATA state", "RAWTEXT state"],
+"lastStartTag":"xmp",
+"input":"foo<!--></xmp><!-->baz</xmp>",
+"output":[["Character", "foo<!-->"], ["EndTag", "xmp"], "ParseError", ["Comment", ""], ["Character", "baz"], ["EndTag", "xmp"]]},
+
+{"description":"Commented entities in RCDATA",
+"initialStates":["RCDATA state"],
+"lastStartTag":"xmp",
+"input":" &amp; <!-- &amp; --> &amp; </xmp>",
+"output":[["Character", " & <!-- & --> & "], ["EndTag", "xmp"]]},
+
+{"description":"Incorrect comment ending sequences in RCDATA or RAWTEXT",
+"initialStates":["RCDATA state", "RAWTEXT state"],
+"lastStartTag":"xmp",
+"input":"foo<!-- x --x>x-- >x--!>x--<></xmp>",
+"output":[["Character", "foo<!-- x --x>x-- >x--!>x--<>"], ["EndTag", "xmp"]]}
+
+]}
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/namedEntities.test b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/namedEntities.test
new file mode 100644
index 00000000000..14db2ede0f1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/namedEntities.test
@@ -0,0 +1,42210 @@
+{
+ "tests": [
+ {
+ "input": "&AElig",
+ "description": "Named entity: AElig without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00c6"
+ ]
+ ]
+ },
+ {
+ "input": "&AElig;",
+ "description": "Named entity: AElig; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00c6"
+ ]
+ ]
+ },
+ {
+ "input": "&AMP",
+ "description": "Named entity: AMP without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "&"
+ ]
+ ]
+ },
+ {
+ "input": "&AMP;",
+ "description": "Named entity: AMP; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&"
+ ]
+ ]
+ },
+ {
+ "input": "&Aacute",
+ "description": "Named entity: Aacute without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00c1"
+ ]
+ ]
+ },
+ {
+ "input": "&Aacute;",
+ "description": "Named entity: Aacute; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00c1"
+ ]
+ ]
+ },
+ {
+ "input": "&Abreve",
+ "description": "Bad named entity: Abreve without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Abreve"
+ ]
+ ]
+ },
+ {
+ "input": "&Abreve;",
+ "description": "Named entity: Abreve; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0102"
+ ]
+ ]
+ },
+ {
+ "input": "&Acirc",
+ "description": "Named entity: Acirc without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00c2"
+ ]
+ ]
+ },
+ {
+ "input": "&Acirc;",
+ "description": "Named entity: Acirc; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00c2"
+ ]
+ ]
+ },
+ {
+ "input": "&Acy",
+ "description": "Bad named entity: Acy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Acy"
+ ]
+ ]
+ },
+ {
+ "input": "&Acy;",
+ "description": "Named entity: Acy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0410"
+ ]
+ ]
+ },
+ {
+ "input": "&Afr",
+ "description": "Bad named entity: Afr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Afr"
+ ]
+ ]
+ },
+ {
+ "input": "&Afr;",
+ "description": "Named entity: Afr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd04"
+ ]
+ ]
+ },
+ {
+ "input": "&Agrave",
+ "description": "Named entity: Agrave without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00c0"
+ ]
+ ]
+ },
+ {
+ "input": "&Agrave;",
+ "description": "Named entity: Agrave; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00c0"
+ ]
+ ]
+ },
+ {
+ "input": "&Alpha",
+ "description": "Bad named entity: Alpha without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Alpha"
+ ]
+ ]
+ },
+ {
+ "input": "&Alpha;",
+ "description": "Named entity: Alpha; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0391"
+ ]
+ ]
+ },
+ {
+ "input": "&Amacr",
+ "description": "Bad named entity: Amacr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Amacr"
+ ]
+ ]
+ },
+ {
+ "input": "&Amacr;",
+ "description": "Named entity: Amacr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0100"
+ ]
+ ]
+ },
+ {
+ "input": "&And",
+ "description": "Bad named entity: And without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&And"
+ ]
+ ]
+ },
+ {
+ "input": "&And;",
+ "description": "Named entity: And; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a53"
+ ]
+ ]
+ },
+ {
+ "input": "&Aogon",
+ "description": "Bad named entity: Aogon without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Aogon"
+ ]
+ ]
+ },
+ {
+ "input": "&Aogon;",
+ "description": "Named entity: Aogon; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0104"
+ ]
+ ]
+ },
+ {
+ "input": "&Aopf",
+ "description": "Bad named entity: Aopf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Aopf"
+ ]
+ ]
+ },
+ {
+ "input": "&Aopf;",
+ "description": "Named entity: Aopf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd38"
+ ]
+ ]
+ },
+ {
+ "input": "&ApplyFunction",
+ "description": "Bad named entity: ApplyFunction without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ApplyFunction"
+ ]
+ ]
+ },
+ {
+ "input": "&ApplyFunction;",
+ "description": "Named entity: ApplyFunction; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2061"
+ ]
+ ]
+ },
+ {
+ "input": "&Aring",
+ "description": "Named entity: Aring without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00c5"
+ ]
+ ]
+ },
+ {
+ "input": "&Aring;",
+ "description": "Named entity: Aring; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00c5"
+ ]
+ ]
+ },
+ {
+ "input": "&Ascr",
+ "description": "Bad named entity: Ascr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Ascr"
+ ]
+ ]
+ },
+ {
+ "input": "&Ascr;",
+ "description": "Named entity: Ascr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udc9c"
+ ]
+ ]
+ },
+ {
+ "input": "&Assign",
+ "description": "Bad named entity: Assign without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Assign"
+ ]
+ ]
+ },
+ {
+ "input": "&Assign;",
+ "description": "Named entity: Assign; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2254"
+ ]
+ ]
+ },
+ {
+ "input": "&Atilde",
+ "description": "Named entity: Atilde without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00c3"
+ ]
+ ]
+ },
+ {
+ "input": "&Atilde;",
+ "description": "Named entity: Atilde; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00c3"
+ ]
+ ]
+ },
+ {
+ "input": "&Auml",
+ "description": "Named entity: Auml without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00c4"
+ ]
+ ]
+ },
+ {
+ "input": "&Auml;",
+ "description": "Named entity: Auml; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00c4"
+ ]
+ ]
+ },
+ {
+ "input": "&Backslash",
+ "description": "Bad named entity: Backslash without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Backslash"
+ ]
+ ]
+ },
+ {
+ "input": "&Backslash;",
+ "description": "Named entity: Backslash; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2216"
+ ]
+ ]
+ },
+ {
+ "input": "&Barv",
+ "description": "Bad named entity: Barv without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Barv"
+ ]
+ ]
+ },
+ {
+ "input": "&Barv;",
+ "description": "Named entity: Barv; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2ae7"
+ ]
+ ]
+ },
+ {
+ "input": "&Barwed",
+ "description": "Bad named entity: Barwed without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Barwed"
+ ]
+ ]
+ },
+ {
+ "input": "&Barwed;",
+ "description": "Named entity: Barwed; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2306"
+ ]
+ ]
+ },
+ {
+ "input": "&Bcy",
+ "description": "Bad named entity: Bcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Bcy"
+ ]
+ ]
+ },
+ {
+ "input": "&Bcy;",
+ "description": "Named entity: Bcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0411"
+ ]
+ ]
+ },
+ {
+ "input": "&Because",
+ "description": "Bad named entity: Because without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Because"
+ ]
+ ]
+ },
+ {
+ "input": "&Because;",
+ "description": "Named entity: Because; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2235"
+ ]
+ ]
+ },
+ {
+ "input": "&Bernoullis",
+ "description": "Bad named entity: Bernoullis without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Bernoullis"
+ ]
+ ]
+ },
+ {
+ "input": "&Bernoullis;",
+ "description": "Named entity: Bernoullis; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u212c"
+ ]
+ ]
+ },
+ {
+ "input": "&Beta",
+ "description": "Bad named entity: Beta without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Beta"
+ ]
+ ]
+ },
+ {
+ "input": "&Beta;",
+ "description": "Named entity: Beta; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0392"
+ ]
+ ]
+ },
+ {
+ "input": "&Bfr",
+ "description": "Bad named entity: Bfr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Bfr"
+ ]
+ ]
+ },
+ {
+ "input": "&Bfr;",
+ "description": "Named entity: Bfr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd05"
+ ]
+ ]
+ },
+ {
+ "input": "&Bopf",
+ "description": "Bad named entity: Bopf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Bopf"
+ ]
+ ]
+ },
+ {
+ "input": "&Bopf;",
+ "description": "Named entity: Bopf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd39"
+ ]
+ ]
+ },
+ {
+ "input": "&Breve",
+ "description": "Bad named entity: Breve without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Breve"
+ ]
+ ]
+ },
+ {
+ "input": "&Breve;",
+ "description": "Named entity: Breve; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u02d8"
+ ]
+ ]
+ },
+ {
+ "input": "&Bscr",
+ "description": "Bad named entity: Bscr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Bscr"
+ ]
+ ]
+ },
+ {
+ "input": "&Bscr;",
+ "description": "Named entity: Bscr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u212c"
+ ]
+ ]
+ },
+ {
+ "input": "&Bumpeq",
+ "description": "Bad named entity: Bumpeq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Bumpeq"
+ ]
+ ]
+ },
+ {
+ "input": "&Bumpeq;",
+ "description": "Named entity: Bumpeq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u224e"
+ ]
+ ]
+ },
+ {
+ "input": "&CHcy",
+ "description": "Bad named entity: CHcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&CHcy"
+ ]
+ ]
+ },
+ {
+ "input": "&CHcy;",
+ "description": "Named entity: CHcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0427"
+ ]
+ ]
+ },
+ {
+ "input": "&COPY",
+ "description": "Named entity: COPY without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00a9"
+ ]
+ ]
+ },
+ {
+ "input": "&COPY;",
+ "description": "Named entity: COPY; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00a9"
+ ]
+ ]
+ },
+ {
+ "input": "&Cacute",
+ "description": "Bad named entity: Cacute without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Cacute"
+ ]
+ ]
+ },
+ {
+ "input": "&Cacute;",
+ "description": "Named entity: Cacute; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0106"
+ ]
+ ]
+ },
+ {
+ "input": "&Cap",
+ "description": "Bad named entity: Cap without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Cap"
+ ]
+ ]
+ },
+ {
+ "input": "&Cap;",
+ "description": "Named entity: Cap; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22d2"
+ ]
+ ]
+ },
+ {
+ "input": "&CapitalDifferentialD",
+ "description": "Bad named entity: CapitalDifferentialD without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&CapitalDifferentialD"
+ ]
+ ]
+ },
+ {
+ "input": "&CapitalDifferentialD;",
+ "description": "Named entity: CapitalDifferentialD; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2145"
+ ]
+ ]
+ },
+ {
+ "input": "&Cayleys",
+ "description": "Bad named entity: Cayleys without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Cayleys"
+ ]
+ ]
+ },
+ {
+ "input": "&Cayleys;",
+ "description": "Named entity: Cayleys; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u212d"
+ ]
+ ]
+ },
+ {
+ "input": "&Ccaron",
+ "description": "Bad named entity: Ccaron without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Ccaron"
+ ]
+ ]
+ },
+ {
+ "input": "&Ccaron;",
+ "description": "Named entity: Ccaron; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u010c"
+ ]
+ ]
+ },
+ {
+ "input": "&Ccedil",
+ "description": "Named entity: Ccedil without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00c7"
+ ]
+ ]
+ },
+ {
+ "input": "&Ccedil;",
+ "description": "Named entity: Ccedil; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00c7"
+ ]
+ ]
+ },
+ {
+ "input": "&Ccirc",
+ "description": "Bad named entity: Ccirc without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Ccirc"
+ ]
+ ]
+ },
+ {
+ "input": "&Ccirc;",
+ "description": "Named entity: Ccirc; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0108"
+ ]
+ ]
+ },
+ {
+ "input": "&Cconint",
+ "description": "Bad named entity: Cconint without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Cconint"
+ ]
+ ]
+ },
+ {
+ "input": "&Cconint;",
+ "description": "Named entity: Cconint; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2230"
+ ]
+ ]
+ },
+ {
+ "input": "&Cdot",
+ "description": "Bad named entity: Cdot without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Cdot"
+ ]
+ ]
+ },
+ {
+ "input": "&Cdot;",
+ "description": "Named entity: Cdot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u010a"
+ ]
+ ]
+ },
+ {
+ "input": "&Cedilla",
+ "description": "Bad named entity: Cedilla without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Cedilla"
+ ]
+ ]
+ },
+ {
+ "input": "&Cedilla;",
+ "description": "Named entity: Cedilla; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00b8"
+ ]
+ ]
+ },
+ {
+ "input": "&CenterDot",
+ "description": "Bad named entity: CenterDot without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&CenterDot"
+ ]
+ ]
+ },
+ {
+ "input": "&CenterDot;",
+ "description": "Named entity: CenterDot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00b7"
+ ]
+ ]
+ },
+ {
+ "input": "&Cfr",
+ "description": "Bad named entity: Cfr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Cfr"
+ ]
+ ]
+ },
+ {
+ "input": "&Cfr;",
+ "description": "Named entity: Cfr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u212d"
+ ]
+ ]
+ },
+ {
+ "input": "&Chi",
+ "description": "Bad named entity: Chi without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Chi"
+ ]
+ ]
+ },
+ {
+ "input": "&Chi;",
+ "description": "Named entity: Chi; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03a7"
+ ]
+ ]
+ },
+ {
+ "input": "&CircleDot",
+ "description": "Bad named entity: CircleDot without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&CircleDot"
+ ]
+ ]
+ },
+ {
+ "input": "&CircleDot;",
+ "description": "Named entity: CircleDot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2299"
+ ]
+ ]
+ },
+ {
+ "input": "&CircleMinus",
+ "description": "Bad named entity: CircleMinus without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&CircleMinus"
+ ]
+ ]
+ },
+ {
+ "input": "&CircleMinus;",
+ "description": "Named entity: CircleMinus; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2296"
+ ]
+ ]
+ },
+ {
+ "input": "&CirclePlus",
+ "description": "Bad named entity: CirclePlus without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&CirclePlus"
+ ]
+ ]
+ },
+ {
+ "input": "&CirclePlus;",
+ "description": "Named entity: CirclePlus; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2295"
+ ]
+ ]
+ },
+ {
+ "input": "&CircleTimes",
+ "description": "Bad named entity: CircleTimes without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&CircleTimes"
+ ]
+ ]
+ },
+ {
+ "input": "&CircleTimes;",
+ "description": "Named entity: CircleTimes; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2297"
+ ]
+ ]
+ },
+ {
+ "input": "&ClockwiseContourIntegral",
+ "description": "Bad named entity: ClockwiseContourIntegral without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ClockwiseContourIntegral"
+ ]
+ ]
+ },
+ {
+ "input": "&ClockwiseContourIntegral;",
+ "description": "Named entity: ClockwiseContourIntegral; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2232"
+ ]
+ ]
+ },
+ {
+ "input": "&CloseCurlyDoubleQuote",
+ "description": "Bad named entity: CloseCurlyDoubleQuote without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&CloseCurlyDoubleQuote"
+ ]
+ ]
+ },
+ {
+ "input": "&CloseCurlyDoubleQuote;",
+ "description": "Named entity: CloseCurlyDoubleQuote; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u201d"
+ ]
+ ]
+ },
+ {
+ "input": "&CloseCurlyQuote",
+ "description": "Bad named entity: CloseCurlyQuote without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&CloseCurlyQuote"
+ ]
+ ]
+ },
+ {
+ "input": "&CloseCurlyQuote;",
+ "description": "Named entity: CloseCurlyQuote; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2019"
+ ]
+ ]
+ },
+ {
+ "input": "&Colon",
+ "description": "Bad named entity: Colon without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Colon"
+ ]
+ ]
+ },
+ {
+ "input": "&Colon;",
+ "description": "Named entity: Colon; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2237"
+ ]
+ ]
+ },
+ {
+ "input": "&Colone",
+ "description": "Bad named entity: Colone without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Colone"
+ ]
+ ]
+ },
+ {
+ "input": "&Colone;",
+ "description": "Named entity: Colone; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a74"
+ ]
+ ]
+ },
+ {
+ "input": "&Congruent",
+ "description": "Bad named entity: Congruent without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Congruent"
+ ]
+ ]
+ },
+ {
+ "input": "&Congruent;",
+ "description": "Named entity: Congruent; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2261"
+ ]
+ ]
+ },
+ {
+ "input": "&Conint",
+ "description": "Bad named entity: Conint without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Conint"
+ ]
+ ]
+ },
+ {
+ "input": "&Conint;",
+ "description": "Named entity: Conint; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u222f"
+ ]
+ ]
+ },
+ {
+ "input": "&ContourIntegral",
+ "description": "Bad named entity: ContourIntegral without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ContourIntegral"
+ ]
+ ]
+ },
+ {
+ "input": "&ContourIntegral;",
+ "description": "Named entity: ContourIntegral; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u222e"
+ ]
+ ]
+ },
+ {
+ "input": "&Copf",
+ "description": "Bad named entity: Copf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Copf"
+ ]
+ ]
+ },
+ {
+ "input": "&Copf;",
+ "description": "Named entity: Copf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2102"
+ ]
+ ]
+ },
+ {
+ "input": "&Coproduct",
+ "description": "Bad named entity: Coproduct without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Coproduct"
+ ]
+ ]
+ },
+ {
+ "input": "&Coproduct;",
+ "description": "Named entity: Coproduct; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2210"
+ ]
+ ]
+ },
+ {
+ "input": "&CounterClockwiseContourIntegral",
+ "description": "Bad named entity: CounterClockwiseContourIntegral without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&CounterClockwiseContourIntegral"
+ ]
+ ]
+ },
+ {
+ "input": "&CounterClockwiseContourIntegral;",
+ "description": "Named entity: CounterClockwiseContourIntegral; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2233"
+ ]
+ ]
+ },
+ {
+ "input": "&Cross",
+ "description": "Bad named entity: Cross without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Cross"
+ ]
+ ]
+ },
+ {
+ "input": "&Cross;",
+ "description": "Named entity: Cross; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a2f"
+ ]
+ ]
+ },
+ {
+ "input": "&Cscr",
+ "description": "Bad named entity: Cscr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Cscr"
+ ]
+ ]
+ },
+ {
+ "input": "&Cscr;",
+ "description": "Named entity: Cscr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udc9e"
+ ]
+ ]
+ },
+ {
+ "input": "&Cup",
+ "description": "Bad named entity: Cup without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Cup"
+ ]
+ ]
+ },
+ {
+ "input": "&Cup;",
+ "description": "Named entity: Cup; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22d3"
+ ]
+ ]
+ },
+ {
+ "input": "&CupCap",
+ "description": "Bad named entity: CupCap without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&CupCap"
+ ]
+ ]
+ },
+ {
+ "input": "&CupCap;",
+ "description": "Named entity: CupCap; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u224d"
+ ]
+ ]
+ },
+ {
+ "input": "&DD",
+ "description": "Bad named entity: DD without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&DD"
+ ]
+ ]
+ },
+ {
+ "input": "&DD;",
+ "description": "Named entity: DD; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2145"
+ ]
+ ]
+ },
+ {
+ "input": "&DDotrahd",
+ "description": "Bad named entity: DDotrahd without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&DDotrahd"
+ ]
+ ]
+ },
+ {
+ "input": "&DDotrahd;",
+ "description": "Named entity: DDotrahd; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2911"
+ ]
+ ]
+ },
+ {
+ "input": "&DJcy",
+ "description": "Bad named entity: DJcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&DJcy"
+ ]
+ ]
+ },
+ {
+ "input": "&DJcy;",
+ "description": "Named entity: DJcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0402"
+ ]
+ ]
+ },
+ {
+ "input": "&DScy",
+ "description": "Bad named entity: DScy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&DScy"
+ ]
+ ]
+ },
+ {
+ "input": "&DScy;",
+ "description": "Named entity: DScy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0405"
+ ]
+ ]
+ },
+ {
+ "input": "&DZcy",
+ "description": "Bad named entity: DZcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&DZcy"
+ ]
+ ]
+ },
+ {
+ "input": "&DZcy;",
+ "description": "Named entity: DZcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u040f"
+ ]
+ ]
+ },
+ {
+ "input": "&Dagger",
+ "description": "Bad named entity: Dagger without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Dagger"
+ ]
+ ]
+ },
+ {
+ "input": "&Dagger;",
+ "description": "Named entity: Dagger; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2021"
+ ]
+ ]
+ },
+ {
+ "input": "&Darr",
+ "description": "Bad named entity: Darr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Darr"
+ ]
+ ]
+ },
+ {
+ "input": "&Darr;",
+ "description": "Named entity: Darr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21a1"
+ ]
+ ]
+ },
+ {
+ "input": "&Dashv",
+ "description": "Bad named entity: Dashv without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Dashv"
+ ]
+ ]
+ },
+ {
+ "input": "&Dashv;",
+ "description": "Named entity: Dashv; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2ae4"
+ ]
+ ]
+ },
+ {
+ "input": "&Dcaron",
+ "description": "Bad named entity: Dcaron without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Dcaron"
+ ]
+ ]
+ },
+ {
+ "input": "&Dcaron;",
+ "description": "Named entity: Dcaron; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u010e"
+ ]
+ ]
+ },
+ {
+ "input": "&Dcy",
+ "description": "Bad named entity: Dcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Dcy"
+ ]
+ ]
+ },
+ {
+ "input": "&Dcy;",
+ "description": "Named entity: Dcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0414"
+ ]
+ ]
+ },
+ {
+ "input": "&Del",
+ "description": "Bad named entity: Del without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Del"
+ ]
+ ]
+ },
+ {
+ "input": "&Del;",
+ "description": "Named entity: Del; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2207"
+ ]
+ ]
+ },
+ {
+ "input": "&Delta",
+ "description": "Bad named entity: Delta without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Delta"
+ ]
+ ]
+ },
+ {
+ "input": "&Delta;",
+ "description": "Named entity: Delta; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0394"
+ ]
+ ]
+ },
+ {
+ "input": "&Dfr",
+ "description": "Bad named entity: Dfr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Dfr"
+ ]
+ ]
+ },
+ {
+ "input": "&Dfr;",
+ "description": "Named entity: Dfr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd07"
+ ]
+ ]
+ },
+ {
+ "input": "&DiacriticalAcute",
+ "description": "Bad named entity: DiacriticalAcute without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&DiacriticalAcute"
+ ]
+ ]
+ },
+ {
+ "input": "&DiacriticalAcute;",
+ "description": "Named entity: DiacriticalAcute; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00b4"
+ ]
+ ]
+ },
+ {
+ "input": "&DiacriticalDot",
+ "description": "Bad named entity: DiacriticalDot without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&DiacriticalDot"
+ ]
+ ]
+ },
+ {
+ "input": "&DiacriticalDot;",
+ "description": "Named entity: DiacriticalDot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u02d9"
+ ]
+ ]
+ },
+ {
+ "input": "&DiacriticalDoubleAcute",
+ "description": "Bad named entity: DiacriticalDoubleAcute without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&DiacriticalDoubleAcute"
+ ]
+ ]
+ },
+ {
+ "input": "&DiacriticalDoubleAcute;",
+ "description": "Named entity: DiacriticalDoubleAcute; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u02dd"
+ ]
+ ]
+ },
+ {
+ "input": "&DiacriticalGrave",
+ "description": "Bad named entity: DiacriticalGrave without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&DiacriticalGrave"
+ ]
+ ]
+ },
+ {
+ "input": "&DiacriticalGrave;",
+ "description": "Named entity: DiacriticalGrave; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "`"
+ ]
+ ]
+ },
+ {
+ "input": "&DiacriticalTilde",
+ "description": "Bad named entity: DiacriticalTilde without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&DiacriticalTilde"
+ ]
+ ]
+ },
+ {
+ "input": "&DiacriticalTilde;",
+ "description": "Named entity: DiacriticalTilde; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u02dc"
+ ]
+ ]
+ },
+ {
+ "input": "&Diamond",
+ "description": "Bad named entity: Diamond without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Diamond"
+ ]
+ ]
+ },
+ {
+ "input": "&Diamond;",
+ "description": "Named entity: Diamond; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22c4"
+ ]
+ ]
+ },
+ {
+ "input": "&DifferentialD",
+ "description": "Bad named entity: DifferentialD without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&DifferentialD"
+ ]
+ ]
+ },
+ {
+ "input": "&DifferentialD;",
+ "description": "Named entity: DifferentialD; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2146"
+ ]
+ ]
+ },
+ {
+ "input": "&Dopf",
+ "description": "Bad named entity: Dopf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Dopf"
+ ]
+ ]
+ },
+ {
+ "input": "&Dopf;",
+ "description": "Named entity: Dopf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd3b"
+ ]
+ ]
+ },
+ {
+ "input": "&Dot",
+ "description": "Bad named entity: Dot without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Dot"
+ ]
+ ]
+ },
+ {
+ "input": "&Dot;",
+ "description": "Named entity: Dot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00a8"
+ ]
+ ]
+ },
+ {
+ "input": "&DotDot",
+ "description": "Bad named entity: DotDot without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&DotDot"
+ ]
+ ]
+ },
+ {
+ "input": "&DotDot;",
+ "description": "Named entity: DotDot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u20dc"
+ ]
+ ]
+ },
+ {
+ "input": "&DotEqual",
+ "description": "Bad named entity: DotEqual without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&DotEqual"
+ ]
+ ]
+ },
+ {
+ "input": "&DotEqual;",
+ "description": "Named entity: DotEqual; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2250"
+ ]
+ ]
+ },
+ {
+ "input": "&DoubleContourIntegral",
+ "description": "Bad named entity: DoubleContourIntegral without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&DoubleContourIntegral"
+ ]
+ ]
+ },
+ {
+ "input": "&DoubleContourIntegral;",
+ "description": "Named entity: DoubleContourIntegral; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u222f"
+ ]
+ ]
+ },
+ {
+ "input": "&DoubleDot",
+ "description": "Bad named entity: DoubleDot without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&DoubleDot"
+ ]
+ ]
+ },
+ {
+ "input": "&DoubleDot;",
+ "description": "Named entity: DoubleDot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00a8"
+ ]
+ ]
+ },
+ {
+ "input": "&DoubleDownArrow",
+ "description": "Bad named entity: DoubleDownArrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&DoubleDownArrow"
+ ]
+ ]
+ },
+ {
+ "input": "&DoubleDownArrow;",
+ "description": "Named entity: DoubleDownArrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21d3"
+ ]
+ ]
+ },
+ {
+ "input": "&DoubleLeftArrow",
+ "description": "Bad named entity: DoubleLeftArrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&DoubleLeftArrow"
+ ]
+ ]
+ },
+ {
+ "input": "&DoubleLeftArrow;",
+ "description": "Named entity: DoubleLeftArrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21d0"
+ ]
+ ]
+ },
+ {
+ "input": "&DoubleLeftRightArrow",
+ "description": "Bad named entity: DoubleLeftRightArrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&DoubleLeftRightArrow"
+ ]
+ ]
+ },
+ {
+ "input": "&DoubleLeftRightArrow;",
+ "description": "Named entity: DoubleLeftRightArrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21d4"
+ ]
+ ]
+ },
+ {
+ "input": "&DoubleLeftTee",
+ "description": "Bad named entity: DoubleLeftTee without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&DoubleLeftTee"
+ ]
+ ]
+ },
+ {
+ "input": "&DoubleLeftTee;",
+ "description": "Named entity: DoubleLeftTee; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2ae4"
+ ]
+ ]
+ },
+ {
+ "input": "&DoubleLongLeftArrow",
+ "description": "Bad named entity: DoubleLongLeftArrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&DoubleLongLeftArrow"
+ ]
+ ]
+ },
+ {
+ "input": "&DoubleLongLeftArrow;",
+ "description": "Named entity: DoubleLongLeftArrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u27f8"
+ ]
+ ]
+ },
+ {
+ "input": "&DoubleLongLeftRightArrow",
+ "description": "Bad named entity: DoubleLongLeftRightArrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&DoubleLongLeftRightArrow"
+ ]
+ ]
+ },
+ {
+ "input": "&DoubleLongLeftRightArrow;",
+ "description": "Named entity: DoubleLongLeftRightArrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u27fa"
+ ]
+ ]
+ },
+ {
+ "input": "&DoubleLongRightArrow",
+ "description": "Bad named entity: DoubleLongRightArrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&DoubleLongRightArrow"
+ ]
+ ]
+ },
+ {
+ "input": "&DoubleLongRightArrow;",
+ "description": "Named entity: DoubleLongRightArrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u27f9"
+ ]
+ ]
+ },
+ {
+ "input": "&DoubleRightArrow",
+ "description": "Bad named entity: DoubleRightArrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&DoubleRightArrow"
+ ]
+ ]
+ },
+ {
+ "input": "&DoubleRightArrow;",
+ "description": "Named entity: DoubleRightArrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21d2"
+ ]
+ ]
+ },
+ {
+ "input": "&DoubleRightTee",
+ "description": "Bad named entity: DoubleRightTee without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&DoubleRightTee"
+ ]
+ ]
+ },
+ {
+ "input": "&DoubleRightTee;",
+ "description": "Named entity: DoubleRightTee; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22a8"
+ ]
+ ]
+ },
+ {
+ "input": "&DoubleUpArrow",
+ "description": "Bad named entity: DoubleUpArrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&DoubleUpArrow"
+ ]
+ ]
+ },
+ {
+ "input": "&DoubleUpArrow;",
+ "description": "Named entity: DoubleUpArrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21d1"
+ ]
+ ]
+ },
+ {
+ "input": "&DoubleUpDownArrow",
+ "description": "Bad named entity: DoubleUpDownArrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&DoubleUpDownArrow"
+ ]
+ ]
+ },
+ {
+ "input": "&DoubleUpDownArrow;",
+ "description": "Named entity: DoubleUpDownArrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21d5"
+ ]
+ ]
+ },
+ {
+ "input": "&DoubleVerticalBar",
+ "description": "Bad named entity: DoubleVerticalBar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&DoubleVerticalBar"
+ ]
+ ]
+ },
+ {
+ "input": "&DoubleVerticalBar;",
+ "description": "Named entity: DoubleVerticalBar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2225"
+ ]
+ ]
+ },
+ {
+ "input": "&DownArrow",
+ "description": "Bad named entity: DownArrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&DownArrow"
+ ]
+ ]
+ },
+ {
+ "input": "&DownArrow;",
+ "description": "Named entity: DownArrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2193"
+ ]
+ ]
+ },
+ {
+ "input": "&DownArrowBar",
+ "description": "Bad named entity: DownArrowBar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&DownArrowBar"
+ ]
+ ]
+ },
+ {
+ "input": "&DownArrowBar;",
+ "description": "Named entity: DownArrowBar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2913"
+ ]
+ ]
+ },
+ {
+ "input": "&DownArrowUpArrow",
+ "description": "Bad named entity: DownArrowUpArrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&DownArrowUpArrow"
+ ]
+ ]
+ },
+ {
+ "input": "&DownArrowUpArrow;",
+ "description": "Named entity: DownArrowUpArrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21f5"
+ ]
+ ]
+ },
+ {
+ "input": "&DownBreve",
+ "description": "Bad named entity: DownBreve without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&DownBreve"
+ ]
+ ]
+ },
+ {
+ "input": "&DownBreve;",
+ "description": "Named entity: DownBreve; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0311"
+ ]
+ ]
+ },
+ {
+ "input": "&DownLeftRightVector",
+ "description": "Bad named entity: DownLeftRightVector without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&DownLeftRightVector"
+ ]
+ ]
+ },
+ {
+ "input": "&DownLeftRightVector;",
+ "description": "Named entity: DownLeftRightVector; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2950"
+ ]
+ ]
+ },
+ {
+ "input": "&DownLeftTeeVector",
+ "description": "Bad named entity: DownLeftTeeVector without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&DownLeftTeeVector"
+ ]
+ ]
+ },
+ {
+ "input": "&DownLeftTeeVector;",
+ "description": "Named entity: DownLeftTeeVector; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u295e"
+ ]
+ ]
+ },
+ {
+ "input": "&DownLeftVector",
+ "description": "Bad named entity: DownLeftVector without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&DownLeftVector"
+ ]
+ ]
+ },
+ {
+ "input": "&DownLeftVector;",
+ "description": "Named entity: DownLeftVector; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21bd"
+ ]
+ ]
+ },
+ {
+ "input": "&DownLeftVectorBar",
+ "description": "Bad named entity: DownLeftVectorBar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&DownLeftVectorBar"
+ ]
+ ]
+ },
+ {
+ "input": "&DownLeftVectorBar;",
+ "description": "Named entity: DownLeftVectorBar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2956"
+ ]
+ ]
+ },
+ {
+ "input": "&DownRightTeeVector",
+ "description": "Bad named entity: DownRightTeeVector without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&DownRightTeeVector"
+ ]
+ ]
+ },
+ {
+ "input": "&DownRightTeeVector;",
+ "description": "Named entity: DownRightTeeVector; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u295f"
+ ]
+ ]
+ },
+ {
+ "input": "&DownRightVector",
+ "description": "Bad named entity: DownRightVector without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&DownRightVector"
+ ]
+ ]
+ },
+ {
+ "input": "&DownRightVector;",
+ "description": "Named entity: DownRightVector; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21c1"
+ ]
+ ]
+ },
+ {
+ "input": "&DownRightVectorBar",
+ "description": "Bad named entity: DownRightVectorBar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&DownRightVectorBar"
+ ]
+ ]
+ },
+ {
+ "input": "&DownRightVectorBar;",
+ "description": "Named entity: DownRightVectorBar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2957"
+ ]
+ ]
+ },
+ {
+ "input": "&DownTee",
+ "description": "Bad named entity: DownTee without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&DownTee"
+ ]
+ ]
+ },
+ {
+ "input": "&DownTee;",
+ "description": "Named entity: DownTee; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22a4"
+ ]
+ ]
+ },
+ {
+ "input": "&DownTeeArrow",
+ "description": "Bad named entity: DownTeeArrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&DownTeeArrow"
+ ]
+ ]
+ },
+ {
+ "input": "&DownTeeArrow;",
+ "description": "Named entity: DownTeeArrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21a7"
+ ]
+ ]
+ },
+ {
+ "input": "&Downarrow",
+ "description": "Bad named entity: Downarrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Downarrow"
+ ]
+ ]
+ },
+ {
+ "input": "&Downarrow;",
+ "description": "Named entity: Downarrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21d3"
+ ]
+ ]
+ },
+ {
+ "input": "&Dscr",
+ "description": "Bad named entity: Dscr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Dscr"
+ ]
+ ]
+ },
+ {
+ "input": "&Dscr;",
+ "description": "Named entity: Dscr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udc9f"
+ ]
+ ]
+ },
+ {
+ "input": "&Dstrok",
+ "description": "Bad named entity: Dstrok without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Dstrok"
+ ]
+ ]
+ },
+ {
+ "input": "&Dstrok;",
+ "description": "Named entity: Dstrok; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0110"
+ ]
+ ]
+ },
+ {
+ "input": "&ENG",
+ "description": "Bad named entity: ENG without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ENG"
+ ]
+ ]
+ },
+ {
+ "input": "&ENG;",
+ "description": "Named entity: ENG; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u014a"
+ ]
+ ]
+ },
+ {
+ "input": "&ETH",
+ "description": "Named entity: ETH without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00d0"
+ ]
+ ]
+ },
+ {
+ "input": "&ETH;",
+ "description": "Named entity: ETH; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00d0"
+ ]
+ ]
+ },
+ {
+ "input": "&Eacute",
+ "description": "Named entity: Eacute without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00c9"
+ ]
+ ]
+ },
+ {
+ "input": "&Eacute;",
+ "description": "Named entity: Eacute; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00c9"
+ ]
+ ]
+ },
+ {
+ "input": "&Ecaron",
+ "description": "Bad named entity: Ecaron without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Ecaron"
+ ]
+ ]
+ },
+ {
+ "input": "&Ecaron;",
+ "description": "Named entity: Ecaron; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u011a"
+ ]
+ ]
+ },
+ {
+ "input": "&Ecirc",
+ "description": "Named entity: Ecirc without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00ca"
+ ]
+ ]
+ },
+ {
+ "input": "&Ecirc;",
+ "description": "Named entity: Ecirc; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00ca"
+ ]
+ ]
+ },
+ {
+ "input": "&Ecy",
+ "description": "Bad named entity: Ecy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Ecy"
+ ]
+ ]
+ },
+ {
+ "input": "&Ecy;",
+ "description": "Named entity: Ecy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u042d"
+ ]
+ ]
+ },
+ {
+ "input": "&Edot",
+ "description": "Bad named entity: Edot without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Edot"
+ ]
+ ]
+ },
+ {
+ "input": "&Edot;",
+ "description": "Named entity: Edot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0116"
+ ]
+ ]
+ },
+ {
+ "input": "&Efr",
+ "description": "Bad named entity: Efr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Efr"
+ ]
+ ]
+ },
+ {
+ "input": "&Efr;",
+ "description": "Named entity: Efr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd08"
+ ]
+ ]
+ },
+ {
+ "input": "&Egrave",
+ "description": "Named entity: Egrave without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00c8"
+ ]
+ ]
+ },
+ {
+ "input": "&Egrave;",
+ "description": "Named entity: Egrave; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00c8"
+ ]
+ ]
+ },
+ {
+ "input": "&Element",
+ "description": "Bad named entity: Element without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Element"
+ ]
+ ]
+ },
+ {
+ "input": "&Element;",
+ "description": "Named entity: Element; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2208"
+ ]
+ ]
+ },
+ {
+ "input": "&Emacr",
+ "description": "Bad named entity: Emacr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Emacr"
+ ]
+ ]
+ },
+ {
+ "input": "&Emacr;",
+ "description": "Named entity: Emacr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0112"
+ ]
+ ]
+ },
+ {
+ "input": "&EmptySmallSquare",
+ "description": "Bad named entity: EmptySmallSquare without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&EmptySmallSquare"
+ ]
+ ]
+ },
+ {
+ "input": "&EmptySmallSquare;",
+ "description": "Named entity: EmptySmallSquare; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u25fb"
+ ]
+ ]
+ },
+ {
+ "input": "&EmptyVerySmallSquare",
+ "description": "Bad named entity: EmptyVerySmallSquare without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&EmptyVerySmallSquare"
+ ]
+ ]
+ },
+ {
+ "input": "&EmptyVerySmallSquare;",
+ "description": "Named entity: EmptyVerySmallSquare; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u25ab"
+ ]
+ ]
+ },
+ {
+ "input": "&Eogon",
+ "description": "Bad named entity: Eogon without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Eogon"
+ ]
+ ]
+ },
+ {
+ "input": "&Eogon;",
+ "description": "Named entity: Eogon; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0118"
+ ]
+ ]
+ },
+ {
+ "input": "&Eopf",
+ "description": "Bad named entity: Eopf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Eopf"
+ ]
+ ]
+ },
+ {
+ "input": "&Eopf;",
+ "description": "Named entity: Eopf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd3c"
+ ]
+ ]
+ },
+ {
+ "input": "&Epsilon",
+ "description": "Bad named entity: Epsilon without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Epsilon"
+ ]
+ ]
+ },
+ {
+ "input": "&Epsilon;",
+ "description": "Named entity: Epsilon; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0395"
+ ]
+ ]
+ },
+ {
+ "input": "&Equal",
+ "description": "Bad named entity: Equal without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Equal"
+ ]
+ ]
+ },
+ {
+ "input": "&Equal;",
+ "description": "Named entity: Equal; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a75"
+ ]
+ ]
+ },
+ {
+ "input": "&EqualTilde",
+ "description": "Bad named entity: EqualTilde without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&EqualTilde"
+ ]
+ ]
+ },
+ {
+ "input": "&EqualTilde;",
+ "description": "Named entity: EqualTilde; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2242"
+ ]
+ ]
+ },
+ {
+ "input": "&Equilibrium",
+ "description": "Bad named entity: Equilibrium without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Equilibrium"
+ ]
+ ]
+ },
+ {
+ "input": "&Equilibrium;",
+ "description": "Named entity: Equilibrium; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21cc"
+ ]
+ ]
+ },
+ {
+ "input": "&Escr",
+ "description": "Bad named entity: Escr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Escr"
+ ]
+ ]
+ },
+ {
+ "input": "&Escr;",
+ "description": "Named entity: Escr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2130"
+ ]
+ ]
+ },
+ {
+ "input": "&Esim",
+ "description": "Bad named entity: Esim without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Esim"
+ ]
+ ]
+ },
+ {
+ "input": "&Esim;",
+ "description": "Named entity: Esim; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a73"
+ ]
+ ]
+ },
+ {
+ "input": "&Eta",
+ "description": "Bad named entity: Eta without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Eta"
+ ]
+ ]
+ },
+ {
+ "input": "&Eta;",
+ "description": "Named entity: Eta; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0397"
+ ]
+ ]
+ },
+ {
+ "input": "&Euml",
+ "description": "Named entity: Euml without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00cb"
+ ]
+ ]
+ },
+ {
+ "input": "&Euml;",
+ "description": "Named entity: Euml; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00cb"
+ ]
+ ]
+ },
+ {
+ "input": "&Exists",
+ "description": "Bad named entity: Exists without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Exists"
+ ]
+ ]
+ },
+ {
+ "input": "&Exists;",
+ "description": "Named entity: Exists; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2203"
+ ]
+ ]
+ },
+ {
+ "input": "&ExponentialE",
+ "description": "Bad named entity: ExponentialE without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ExponentialE"
+ ]
+ ]
+ },
+ {
+ "input": "&ExponentialE;",
+ "description": "Named entity: ExponentialE; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2147"
+ ]
+ ]
+ },
+ {
+ "input": "&Fcy",
+ "description": "Bad named entity: Fcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Fcy"
+ ]
+ ]
+ },
+ {
+ "input": "&Fcy;",
+ "description": "Named entity: Fcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0424"
+ ]
+ ]
+ },
+ {
+ "input": "&Ffr",
+ "description": "Bad named entity: Ffr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Ffr"
+ ]
+ ]
+ },
+ {
+ "input": "&Ffr;",
+ "description": "Named entity: Ffr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd09"
+ ]
+ ]
+ },
+ {
+ "input": "&FilledSmallSquare",
+ "description": "Bad named entity: FilledSmallSquare without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&FilledSmallSquare"
+ ]
+ ]
+ },
+ {
+ "input": "&FilledSmallSquare;",
+ "description": "Named entity: FilledSmallSquare; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u25fc"
+ ]
+ ]
+ },
+ {
+ "input": "&FilledVerySmallSquare",
+ "description": "Bad named entity: FilledVerySmallSquare without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&FilledVerySmallSquare"
+ ]
+ ]
+ },
+ {
+ "input": "&FilledVerySmallSquare;",
+ "description": "Named entity: FilledVerySmallSquare; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u25aa"
+ ]
+ ]
+ },
+ {
+ "input": "&Fopf",
+ "description": "Bad named entity: Fopf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Fopf"
+ ]
+ ]
+ },
+ {
+ "input": "&Fopf;",
+ "description": "Named entity: Fopf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd3d"
+ ]
+ ]
+ },
+ {
+ "input": "&ForAll",
+ "description": "Bad named entity: ForAll without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ForAll"
+ ]
+ ]
+ },
+ {
+ "input": "&ForAll;",
+ "description": "Named entity: ForAll; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2200"
+ ]
+ ]
+ },
+ {
+ "input": "&Fouriertrf",
+ "description": "Bad named entity: Fouriertrf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Fouriertrf"
+ ]
+ ]
+ },
+ {
+ "input": "&Fouriertrf;",
+ "description": "Named entity: Fouriertrf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2131"
+ ]
+ ]
+ },
+ {
+ "input": "&Fscr",
+ "description": "Bad named entity: Fscr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Fscr"
+ ]
+ ]
+ },
+ {
+ "input": "&Fscr;",
+ "description": "Named entity: Fscr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2131"
+ ]
+ ]
+ },
+ {
+ "input": "&GJcy",
+ "description": "Bad named entity: GJcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&GJcy"
+ ]
+ ]
+ },
+ {
+ "input": "&GJcy;",
+ "description": "Named entity: GJcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0403"
+ ]
+ ]
+ },
+ {
+ "input": "&GT",
+ "description": "Named entity: GT without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ ">"
+ ]
+ ]
+ },
+ {
+ "input": "&GT;",
+ "description": "Named entity: GT; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ ">"
+ ]
+ ]
+ },
+ {
+ "input": "&Gamma",
+ "description": "Bad named entity: Gamma without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Gamma"
+ ]
+ ]
+ },
+ {
+ "input": "&Gamma;",
+ "description": "Named entity: Gamma; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0393"
+ ]
+ ]
+ },
+ {
+ "input": "&Gammad",
+ "description": "Bad named entity: Gammad without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Gammad"
+ ]
+ ]
+ },
+ {
+ "input": "&Gammad;",
+ "description": "Named entity: Gammad; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03dc"
+ ]
+ ]
+ },
+ {
+ "input": "&Gbreve",
+ "description": "Bad named entity: Gbreve without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Gbreve"
+ ]
+ ]
+ },
+ {
+ "input": "&Gbreve;",
+ "description": "Named entity: Gbreve; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u011e"
+ ]
+ ]
+ },
+ {
+ "input": "&Gcedil",
+ "description": "Bad named entity: Gcedil without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Gcedil"
+ ]
+ ]
+ },
+ {
+ "input": "&Gcedil;",
+ "description": "Named entity: Gcedil; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0122"
+ ]
+ ]
+ },
+ {
+ "input": "&Gcirc",
+ "description": "Bad named entity: Gcirc without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Gcirc"
+ ]
+ ]
+ },
+ {
+ "input": "&Gcirc;",
+ "description": "Named entity: Gcirc; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u011c"
+ ]
+ ]
+ },
+ {
+ "input": "&Gcy",
+ "description": "Bad named entity: Gcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Gcy"
+ ]
+ ]
+ },
+ {
+ "input": "&Gcy;",
+ "description": "Named entity: Gcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0413"
+ ]
+ ]
+ },
+ {
+ "input": "&Gdot",
+ "description": "Bad named entity: Gdot without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Gdot"
+ ]
+ ]
+ },
+ {
+ "input": "&Gdot;",
+ "description": "Named entity: Gdot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0120"
+ ]
+ ]
+ },
+ {
+ "input": "&Gfr",
+ "description": "Bad named entity: Gfr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Gfr"
+ ]
+ ]
+ },
+ {
+ "input": "&Gfr;",
+ "description": "Named entity: Gfr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd0a"
+ ]
+ ]
+ },
+ {
+ "input": "&Gg",
+ "description": "Bad named entity: Gg without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Gg"
+ ]
+ ]
+ },
+ {
+ "input": "&Gg;",
+ "description": "Named entity: Gg; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22d9"
+ ]
+ ]
+ },
+ {
+ "input": "&Gopf",
+ "description": "Bad named entity: Gopf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Gopf"
+ ]
+ ]
+ },
+ {
+ "input": "&Gopf;",
+ "description": "Named entity: Gopf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd3e"
+ ]
+ ]
+ },
+ {
+ "input": "&GreaterEqual",
+ "description": "Bad named entity: GreaterEqual without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&GreaterEqual"
+ ]
+ ]
+ },
+ {
+ "input": "&GreaterEqual;",
+ "description": "Named entity: GreaterEqual; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2265"
+ ]
+ ]
+ },
+ {
+ "input": "&GreaterEqualLess",
+ "description": "Bad named entity: GreaterEqualLess without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&GreaterEqualLess"
+ ]
+ ]
+ },
+ {
+ "input": "&GreaterEqualLess;",
+ "description": "Named entity: GreaterEqualLess; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22db"
+ ]
+ ]
+ },
+ {
+ "input": "&GreaterFullEqual",
+ "description": "Bad named entity: GreaterFullEqual without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&GreaterFullEqual"
+ ]
+ ]
+ },
+ {
+ "input": "&GreaterFullEqual;",
+ "description": "Named entity: GreaterFullEqual; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2267"
+ ]
+ ]
+ },
+ {
+ "input": "&GreaterGreater",
+ "description": "Bad named entity: GreaterGreater without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&GreaterGreater"
+ ]
+ ]
+ },
+ {
+ "input": "&GreaterGreater;",
+ "description": "Named entity: GreaterGreater; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2aa2"
+ ]
+ ]
+ },
+ {
+ "input": "&GreaterLess",
+ "description": "Bad named entity: GreaterLess without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&GreaterLess"
+ ]
+ ]
+ },
+ {
+ "input": "&GreaterLess;",
+ "description": "Named entity: GreaterLess; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2277"
+ ]
+ ]
+ },
+ {
+ "input": "&GreaterSlantEqual",
+ "description": "Bad named entity: GreaterSlantEqual without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&GreaterSlantEqual"
+ ]
+ ]
+ },
+ {
+ "input": "&GreaterSlantEqual;",
+ "description": "Named entity: GreaterSlantEqual; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a7e"
+ ]
+ ]
+ },
+ {
+ "input": "&GreaterTilde",
+ "description": "Bad named entity: GreaterTilde without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&GreaterTilde"
+ ]
+ ]
+ },
+ {
+ "input": "&GreaterTilde;",
+ "description": "Named entity: GreaterTilde; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2273"
+ ]
+ ]
+ },
+ {
+ "input": "&Gscr",
+ "description": "Bad named entity: Gscr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Gscr"
+ ]
+ ]
+ },
+ {
+ "input": "&Gscr;",
+ "description": "Named entity: Gscr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udca2"
+ ]
+ ]
+ },
+ {
+ "input": "&Gt",
+ "description": "Bad named entity: Gt without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Gt"
+ ]
+ ]
+ },
+ {
+ "input": "&Gt;",
+ "description": "Named entity: Gt; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u226b"
+ ]
+ ]
+ },
+ {
+ "input": "&HARDcy",
+ "description": "Bad named entity: HARDcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&HARDcy"
+ ]
+ ]
+ },
+ {
+ "input": "&HARDcy;",
+ "description": "Named entity: HARDcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u042a"
+ ]
+ ]
+ },
+ {
+ "input": "&Hacek",
+ "description": "Bad named entity: Hacek without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Hacek"
+ ]
+ ]
+ },
+ {
+ "input": "&Hacek;",
+ "description": "Named entity: Hacek; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u02c7"
+ ]
+ ]
+ },
+ {
+ "input": "&Hat",
+ "description": "Bad named entity: Hat without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Hat"
+ ]
+ ]
+ },
+ {
+ "input": "&Hat;",
+ "description": "Named entity: Hat; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "^"
+ ]
+ ]
+ },
+ {
+ "input": "&Hcirc",
+ "description": "Bad named entity: Hcirc without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Hcirc"
+ ]
+ ]
+ },
+ {
+ "input": "&Hcirc;",
+ "description": "Named entity: Hcirc; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0124"
+ ]
+ ]
+ },
+ {
+ "input": "&Hfr",
+ "description": "Bad named entity: Hfr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Hfr"
+ ]
+ ]
+ },
+ {
+ "input": "&Hfr;",
+ "description": "Named entity: Hfr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u210c"
+ ]
+ ]
+ },
+ {
+ "input": "&HilbertSpace",
+ "description": "Bad named entity: HilbertSpace without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&HilbertSpace"
+ ]
+ ]
+ },
+ {
+ "input": "&HilbertSpace;",
+ "description": "Named entity: HilbertSpace; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u210b"
+ ]
+ ]
+ },
+ {
+ "input": "&Hopf",
+ "description": "Bad named entity: Hopf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Hopf"
+ ]
+ ]
+ },
+ {
+ "input": "&Hopf;",
+ "description": "Named entity: Hopf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u210d"
+ ]
+ ]
+ },
+ {
+ "input": "&HorizontalLine",
+ "description": "Bad named entity: HorizontalLine without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&HorizontalLine"
+ ]
+ ]
+ },
+ {
+ "input": "&HorizontalLine;",
+ "description": "Named entity: HorizontalLine; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2500"
+ ]
+ ]
+ },
+ {
+ "input": "&Hscr",
+ "description": "Bad named entity: Hscr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Hscr"
+ ]
+ ]
+ },
+ {
+ "input": "&Hscr;",
+ "description": "Named entity: Hscr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u210b"
+ ]
+ ]
+ },
+ {
+ "input": "&Hstrok",
+ "description": "Bad named entity: Hstrok without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Hstrok"
+ ]
+ ]
+ },
+ {
+ "input": "&Hstrok;",
+ "description": "Named entity: Hstrok; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0126"
+ ]
+ ]
+ },
+ {
+ "input": "&HumpDownHump",
+ "description": "Bad named entity: HumpDownHump without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&HumpDownHump"
+ ]
+ ]
+ },
+ {
+ "input": "&HumpDownHump;",
+ "description": "Named entity: HumpDownHump; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u224e"
+ ]
+ ]
+ },
+ {
+ "input": "&HumpEqual",
+ "description": "Bad named entity: HumpEqual without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&HumpEqual"
+ ]
+ ]
+ },
+ {
+ "input": "&HumpEqual;",
+ "description": "Named entity: HumpEqual; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u224f"
+ ]
+ ]
+ },
+ {
+ "input": "&IEcy",
+ "description": "Bad named entity: IEcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&IEcy"
+ ]
+ ]
+ },
+ {
+ "input": "&IEcy;",
+ "description": "Named entity: IEcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0415"
+ ]
+ ]
+ },
+ {
+ "input": "&IJlig",
+ "description": "Bad named entity: IJlig without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&IJlig"
+ ]
+ ]
+ },
+ {
+ "input": "&IJlig;",
+ "description": "Named entity: IJlig; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0132"
+ ]
+ ]
+ },
+ {
+ "input": "&IOcy",
+ "description": "Bad named entity: IOcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&IOcy"
+ ]
+ ]
+ },
+ {
+ "input": "&IOcy;",
+ "description": "Named entity: IOcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0401"
+ ]
+ ]
+ },
+ {
+ "input": "&Iacute",
+ "description": "Named entity: Iacute without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00cd"
+ ]
+ ]
+ },
+ {
+ "input": "&Iacute;",
+ "description": "Named entity: Iacute; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00cd"
+ ]
+ ]
+ },
+ {
+ "input": "&Icirc",
+ "description": "Named entity: Icirc without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00ce"
+ ]
+ ]
+ },
+ {
+ "input": "&Icirc;",
+ "description": "Named entity: Icirc; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00ce"
+ ]
+ ]
+ },
+ {
+ "input": "&Icy",
+ "description": "Bad named entity: Icy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Icy"
+ ]
+ ]
+ },
+ {
+ "input": "&Icy;",
+ "description": "Named entity: Icy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0418"
+ ]
+ ]
+ },
+ {
+ "input": "&Idot",
+ "description": "Bad named entity: Idot without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Idot"
+ ]
+ ]
+ },
+ {
+ "input": "&Idot;",
+ "description": "Named entity: Idot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0130"
+ ]
+ ]
+ },
+ {
+ "input": "&Ifr",
+ "description": "Bad named entity: Ifr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Ifr"
+ ]
+ ]
+ },
+ {
+ "input": "&Ifr;",
+ "description": "Named entity: Ifr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2111"
+ ]
+ ]
+ },
+ {
+ "input": "&Igrave",
+ "description": "Named entity: Igrave without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00cc"
+ ]
+ ]
+ },
+ {
+ "input": "&Igrave;",
+ "description": "Named entity: Igrave; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00cc"
+ ]
+ ]
+ },
+ {
+ "input": "&Im",
+ "description": "Bad named entity: Im without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Im"
+ ]
+ ]
+ },
+ {
+ "input": "&Im;",
+ "description": "Named entity: Im; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2111"
+ ]
+ ]
+ },
+ {
+ "input": "&Imacr",
+ "description": "Bad named entity: Imacr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Imacr"
+ ]
+ ]
+ },
+ {
+ "input": "&Imacr;",
+ "description": "Named entity: Imacr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u012a"
+ ]
+ ]
+ },
+ {
+ "input": "&ImaginaryI",
+ "description": "Bad named entity: ImaginaryI without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ImaginaryI"
+ ]
+ ]
+ },
+ {
+ "input": "&ImaginaryI;",
+ "description": "Named entity: ImaginaryI; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2148"
+ ]
+ ]
+ },
+ {
+ "input": "&Implies",
+ "description": "Bad named entity: Implies without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Implies"
+ ]
+ ]
+ },
+ {
+ "input": "&Implies;",
+ "description": "Named entity: Implies; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21d2"
+ ]
+ ]
+ },
+ {
+ "input": "&Int",
+ "description": "Bad named entity: Int without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Int"
+ ]
+ ]
+ },
+ {
+ "input": "&Int;",
+ "description": "Named entity: Int; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u222c"
+ ]
+ ]
+ },
+ {
+ "input": "&Integral",
+ "description": "Bad named entity: Integral without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Integral"
+ ]
+ ]
+ },
+ {
+ "input": "&Integral;",
+ "description": "Named entity: Integral; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u222b"
+ ]
+ ]
+ },
+ {
+ "input": "&Intersection",
+ "description": "Bad named entity: Intersection without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Intersection"
+ ]
+ ]
+ },
+ {
+ "input": "&Intersection;",
+ "description": "Named entity: Intersection; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22c2"
+ ]
+ ]
+ },
+ {
+ "input": "&InvisibleComma",
+ "description": "Bad named entity: InvisibleComma without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&InvisibleComma"
+ ]
+ ]
+ },
+ {
+ "input": "&InvisibleComma;",
+ "description": "Named entity: InvisibleComma; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2063"
+ ]
+ ]
+ },
+ {
+ "input": "&InvisibleTimes",
+ "description": "Bad named entity: InvisibleTimes without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&InvisibleTimes"
+ ]
+ ]
+ },
+ {
+ "input": "&InvisibleTimes;",
+ "description": "Named entity: InvisibleTimes; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2062"
+ ]
+ ]
+ },
+ {
+ "input": "&Iogon",
+ "description": "Bad named entity: Iogon without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Iogon"
+ ]
+ ]
+ },
+ {
+ "input": "&Iogon;",
+ "description": "Named entity: Iogon; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u012e"
+ ]
+ ]
+ },
+ {
+ "input": "&Iopf",
+ "description": "Bad named entity: Iopf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Iopf"
+ ]
+ ]
+ },
+ {
+ "input": "&Iopf;",
+ "description": "Named entity: Iopf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd40"
+ ]
+ ]
+ },
+ {
+ "input": "&Iota",
+ "description": "Bad named entity: Iota without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Iota"
+ ]
+ ]
+ },
+ {
+ "input": "&Iota;",
+ "description": "Named entity: Iota; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0399"
+ ]
+ ]
+ },
+ {
+ "input": "&Iscr",
+ "description": "Bad named entity: Iscr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Iscr"
+ ]
+ ]
+ },
+ {
+ "input": "&Iscr;",
+ "description": "Named entity: Iscr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2110"
+ ]
+ ]
+ },
+ {
+ "input": "&Itilde",
+ "description": "Bad named entity: Itilde without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Itilde"
+ ]
+ ]
+ },
+ {
+ "input": "&Itilde;",
+ "description": "Named entity: Itilde; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0128"
+ ]
+ ]
+ },
+ {
+ "input": "&Iukcy",
+ "description": "Bad named entity: Iukcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Iukcy"
+ ]
+ ]
+ },
+ {
+ "input": "&Iukcy;",
+ "description": "Named entity: Iukcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0406"
+ ]
+ ]
+ },
+ {
+ "input": "&Iuml",
+ "description": "Named entity: Iuml without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00cf"
+ ]
+ ]
+ },
+ {
+ "input": "&Iuml;",
+ "description": "Named entity: Iuml; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00cf"
+ ]
+ ]
+ },
+ {
+ "input": "&Jcirc",
+ "description": "Bad named entity: Jcirc without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Jcirc"
+ ]
+ ]
+ },
+ {
+ "input": "&Jcirc;",
+ "description": "Named entity: Jcirc; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0134"
+ ]
+ ]
+ },
+ {
+ "input": "&Jcy",
+ "description": "Bad named entity: Jcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Jcy"
+ ]
+ ]
+ },
+ {
+ "input": "&Jcy;",
+ "description": "Named entity: Jcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0419"
+ ]
+ ]
+ },
+ {
+ "input": "&Jfr",
+ "description": "Bad named entity: Jfr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Jfr"
+ ]
+ ]
+ },
+ {
+ "input": "&Jfr;",
+ "description": "Named entity: Jfr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd0d"
+ ]
+ ]
+ },
+ {
+ "input": "&Jopf",
+ "description": "Bad named entity: Jopf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Jopf"
+ ]
+ ]
+ },
+ {
+ "input": "&Jopf;",
+ "description": "Named entity: Jopf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd41"
+ ]
+ ]
+ },
+ {
+ "input": "&Jscr",
+ "description": "Bad named entity: Jscr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Jscr"
+ ]
+ ]
+ },
+ {
+ "input": "&Jscr;",
+ "description": "Named entity: Jscr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udca5"
+ ]
+ ]
+ },
+ {
+ "input": "&Jsercy",
+ "description": "Bad named entity: Jsercy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Jsercy"
+ ]
+ ]
+ },
+ {
+ "input": "&Jsercy;",
+ "description": "Named entity: Jsercy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0408"
+ ]
+ ]
+ },
+ {
+ "input": "&Jukcy",
+ "description": "Bad named entity: Jukcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Jukcy"
+ ]
+ ]
+ },
+ {
+ "input": "&Jukcy;",
+ "description": "Named entity: Jukcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0404"
+ ]
+ ]
+ },
+ {
+ "input": "&KHcy",
+ "description": "Bad named entity: KHcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&KHcy"
+ ]
+ ]
+ },
+ {
+ "input": "&KHcy;",
+ "description": "Named entity: KHcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0425"
+ ]
+ ]
+ },
+ {
+ "input": "&KJcy",
+ "description": "Bad named entity: KJcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&KJcy"
+ ]
+ ]
+ },
+ {
+ "input": "&KJcy;",
+ "description": "Named entity: KJcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u040c"
+ ]
+ ]
+ },
+ {
+ "input": "&Kappa",
+ "description": "Bad named entity: Kappa without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Kappa"
+ ]
+ ]
+ },
+ {
+ "input": "&Kappa;",
+ "description": "Named entity: Kappa; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u039a"
+ ]
+ ]
+ },
+ {
+ "input": "&Kcedil",
+ "description": "Bad named entity: Kcedil without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Kcedil"
+ ]
+ ]
+ },
+ {
+ "input": "&Kcedil;",
+ "description": "Named entity: Kcedil; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0136"
+ ]
+ ]
+ },
+ {
+ "input": "&Kcy",
+ "description": "Bad named entity: Kcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Kcy"
+ ]
+ ]
+ },
+ {
+ "input": "&Kcy;",
+ "description": "Named entity: Kcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u041a"
+ ]
+ ]
+ },
+ {
+ "input": "&Kfr",
+ "description": "Bad named entity: Kfr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Kfr"
+ ]
+ ]
+ },
+ {
+ "input": "&Kfr;",
+ "description": "Named entity: Kfr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd0e"
+ ]
+ ]
+ },
+ {
+ "input": "&Kopf",
+ "description": "Bad named entity: Kopf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Kopf"
+ ]
+ ]
+ },
+ {
+ "input": "&Kopf;",
+ "description": "Named entity: Kopf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd42"
+ ]
+ ]
+ },
+ {
+ "input": "&Kscr",
+ "description": "Bad named entity: Kscr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Kscr"
+ ]
+ ]
+ },
+ {
+ "input": "&Kscr;",
+ "description": "Named entity: Kscr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udca6"
+ ]
+ ]
+ },
+ {
+ "input": "&LJcy",
+ "description": "Bad named entity: LJcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&LJcy"
+ ]
+ ]
+ },
+ {
+ "input": "&LJcy;",
+ "description": "Named entity: LJcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0409"
+ ]
+ ]
+ },
+ {
+ "input": "&LT",
+ "description": "Named entity: LT without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "<"
+ ]
+ ]
+ },
+ {
+ "input": "&LT;",
+ "description": "Named entity: LT; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "<"
+ ]
+ ]
+ },
+ {
+ "input": "&Lacute",
+ "description": "Bad named entity: Lacute without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Lacute"
+ ]
+ ]
+ },
+ {
+ "input": "&Lacute;",
+ "description": "Named entity: Lacute; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0139"
+ ]
+ ]
+ },
+ {
+ "input": "&Lambda",
+ "description": "Bad named entity: Lambda without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Lambda"
+ ]
+ ]
+ },
+ {
+ "input": "&Lambda;",
+ "description": "Named entity: Lambda; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u039b"
+ ]
+ ]
+ },
+ {
+ "input": "&Lang",
+ "description": "Bad named entity: Lang without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Lang"
+ ]
+ ]
+ },
+ {
+ "input": "&Lang;",
+ "description": "Named entity: Lang; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u27ea"
+ ]
+ ]
+ },
+ {
+ "input": "&Laplacetrf",
+ "description": "Bad named entity: Laplacetrf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Laplacetrf"
+ ]
+ ]
+ },
+ {
+ "input": "&Laplacetrf;",
+ "description": "Named entity: Laplacetrf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2112"
+ ]
+ ]
+ },
+ {
+ "input": "&Larr",
+ "description": "Bad named entity: Larr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Larr"
+ ]
+ ]
+ },
+ {
+ "input": "&Larr;",
+ "description": "Named entity: Larr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u219e"
+ ]
+ ]
+ },
+ {
+ "input": "&Lcaron",
+ "description": "Bad named entity: Lcaron without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Lcaron"
+ ]
+ ]
+ },
+ {
+ "input": "&Lcaron;",
+ "description": "Named entity: Lcaron; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u013d"
+ ]
+ ]
+ },
+ {
+ "input": "&Lcedil",
+ "description": "Bad named entity: Lcedil without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Lcedil"
+ ]
+ ]
+ },
+ {
+ "input": "&Lcedil;",
+ "description": "Named entity: Lcedil; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u013b"
+ ]
+ ]
+ },
+ {
+ "input": "&Lcy",
+ "description": "Bad named entity: Lcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Lcy"
+ ]
+ ]
+ },
+ {
+ "input": "&Lcy;",
+ "description": "Named entity: Lcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u041b"
+ ]
+ ]
+ },
+ {
+ "input": "&LeftAngleBracket",
+ "description": "Bad named entity: LeftAngleBracket without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&LeftAngleBracket"
+ ]
+ ]
+ },
+ {
+ "input": "&LeftAngleBracket;",
+ "description": "Named entity: LeftAngleBracket; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u27e8"
+ ]
+ ]
+ },
+ {
+ "input": "&LeftArrow",
+ "description": "Bad named entity: LeftArrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&LeftArrow"
+ ]
+ ]
+ },
+ {
+ "input": "&LeftArrow;",
+ "description": "Named entity: LeftArrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2190"
+ ]
+ ]
+ },
+ {
+ "input": "&LeftArrowBar",
+ "description": "Bad named entity: LeftArrowBar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&LeftArrowBar"
+ ]
+ ]
+ },
+ {
+ "input": "&LeftArrowBar;",
+ "description": "Named entity: LeftArrowBar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21e4"
+ ]
+ ]
+ },
+ {
+ "input": "&LeftArrowRightArrow",
+ "description": "Bad named entity: LeftArrowRightArrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&LeftArrowRightArrow"
+ ]
+ ]
+ },
+ {
+ "input": "&LeftArrowRightArrow;",
+ "description": "Named entity: LeftArrowRightArrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21c6"
+ ]
+ ]
+ },
+ {
+ "input": "&LeftCeiling",
+ "description": "Bad named entity: LeftCeiling without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&LeftCeiling"
+ ]
+ ]
+ },
+ {
+ "input": "&LeftCeiling;",
+ "description": "Named entity: LeftCeiling; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2308"
+ ]
+ ]
+ },
+ {
+ "input": "&LeftDoubleBracket",
+ "description": "Bad named entity: LeftDoubleBracket without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&LeftDoubleBracket"
+ ]
+ ]
+ },
+ {
+ "input": "&LeftDoubleBracket;",
+ "description": "Named entity: LeftDoubleBracket; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u27e6"
+ ]
+ ]
+ },
+ {
+ "input": "&LeftDownTeeVector",
+ "description": "Bad named entity: LeftDownTeeVector without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&LeftDownTeeVector"
+ ]
+ ]
+ },
+ {
+ "input": "&LeftDownTeeVector;",
+ "description": "Named entity: LeftDownTeeVector; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2961"
+ ]
+ ]
+ },
+ {
+ "input": "&LeftDownVector",
+ "description": "Bad named entity: LeftDownVector without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&LeftDownVector"
+ ]
+ ]
+ },
+ {
+ "input": "&LeftDownVector;",
+ "description": "Named entity: LeftDownVector; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21c3"
+ ]
+ ]
+ },
+ {
+ "input": "&LeftDownVectorBar",
+ "description": "Bad named entity: LeftDownVectorBar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&LeftDownVectorBar"
+ ]
+ ]
+ },
+ {
+ "input": "&LeftDownVectorBar;",
+ "description": "Named entity: LeftDownVectorBar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2959"
+ ]
+ ]
+ },
+ {
+ "input": "&LeftFloor",
+ "description": "Bad named entity: LeftFloor without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&LeftFloor"
+ ]
+ ]
+ },
+ {
+ "input": "&LeftFloor;",
+ "description": "Named entity: LeftFloor; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u230a"
+ ]
+ ]
+ },
+ {
+ "input": "&LeftRightArrow",
+ "description": "Bad named entity: LeftRightArrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&LeftRightArrow"
+ ]
+ ]
+ },
+ {
+ "input": "&LeftRightArrow;",
+ "description": "Named entity: LeftRightArrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2194"
+ ]
+ ]
+ },
+ {
+ "input": "&LeftRightVector",
+ "description": "Bad named entity: LeftRightVector without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&LeftRightVector"
+ ]
+ ]
+ },
+ {
+ "input": "&LeftRightVector;",
+ "description": "Named entity: LeftRightVector; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u294e"
+ ]
+ ]
+ },
+ {
+ "input": "&LeftTee",
+ "description": "Bad named entity: LeftTee without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&LeftTee"
+ ]
+ ]
+ },
+ {
+ "input": "&LeftTee;",
+ "description": "Named entity: LeftTee; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22a3"
+ ]
+ ]
+ },
+ {
+ "input": "&LeftTeeArrow",
+ "description": "Bad named entity: LeftTeeArrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&LeftTeeArrow"
+ ]
+ ]
+ },
+ {
+ "input": "&LeftTeeArrow;",
+ "description": "Named entity: LeftTeeArrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21a4"
+ ]
+ ]
+ },
+ {
+ "input": "&LeftTeeVector",
+ "description": "Bad named entity: LeftTeeVector without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&LeftTeeVector"
+ ]
+ ]
+ },
+ {
+ "input": "&LeftTeeVector;",
+ "description": "Named entity: LeftTeeVector; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u295a"
+ ]
+ ]
+ },
+ {
+ "input": "&LeftTriangle",
+ "description": "Bad named entity: LeftTriangle without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&LeftTriangle"
+ ]
+ ]
+ },
+ {
+ "input": "&LeftTriangle;",
+ "description": "Named entity: LeftTriangle; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22b2"
+ ]
+ ]
+ },
+ {
+ "input": "&LeftTriangleBar",
+ "description": "Bad named entity: LeftTriangleBar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&LeftTriangleBar"
+ ]
+ ]
+ },
+ {
+ "input": "&LeftTriangleBar;",
+ "description": "Named entity: LeftTriangleBar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u29cf"
+ ]
+ ]
+ },
+ {
+ "input": "&LeftTriangleEqual",
+ "description": "Bad named entity: LeftTriangleEqual without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&LeftTriangleEqual"
+ ]
+ ]
+ },
+ {
+ "input": "&LeftTriangleEqual;",
+ "description": "Named entity: LeftTriangleEqual; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22b4"
+ ]
+ ]
+ },
+ {
+ "input": "&LeftUpDownVector",
+ "description": "Bad named entity: LeftUpDownVector without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&LeftUpDownVector"
+ ]
+ ]
+ },
+ {
+ "input": "&LeftUpDownVector;",
+ "description": "Named entity: LeftUpDownVector; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2951"
+ ]
+ ]
+ },
+ {
+ "input": "&LeftUpTeeVector",
+ "description": "Bad named entity: LeftUpTeeVector without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&LeftUpTeeVector"
+ ]
+ ]
+ },
+ {
+ "input": "&LeftUpTeeVector;",
+ "description": "Named entity: LeftUpTeeVector; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2960"
+ ]
+ ]
+ },
+ {
+ "input": "&LeftUpVector",
+ "description": "Bad named entity: LeftUpVector without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&LeftUpVector"
+ ]
+ ]
+ },
+ {
+ "input": "&LeftUpVector;",
+ "description": "Named entity: LeftUpVector; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21bf"
+ ]
+ ]
+ },
+ {
+ "input": "&LeftUpVectorBar",
+ "description": "Bad named entity: LeftUpVectorBar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&LeftUpVectorBar"
+ ]
+ ]
+ },
+ {
+ "input": "&LeftUpVectorBar;",
+ "description": "Named entity: LeftUpVectorBar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2958"
+ ]
+ ]
+ },
+ {
+ "input": "&LeftVector",
+ "description": "Bad named entity: LeftVector without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&LeftVector"
+ ]
+ ]
+ },
+ {
+ "input": "&LeftVector;",
+ "description": "Named entity: LeftVector; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21bc"
+ ]
+ ]
+ },
+ {
+ "input": "&LeftVectorBar",
+ "description": "Bad named entity: LeftVectorBar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&LeftVectorBar"
+ ]
+ ]
+ },
+ {
+ "input": "&LeftVectorBar;",
+ "description": "Named entity: LeftVectorBar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2952"
+ ]
+ ]
+ },
+ {
+ "input": "&Leftarrow",
+ "description": "Bad named entity: Leftarrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Leftarrow"
+ ]
+ ]
+ },
+ {
+ "input": "&Leftarrow;",
+ "description": "Named entity: Leftarrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21d0"
+ ]
+ ]
+ },
+ {
+ "input": "&Leftrightarrow",
+ "description": "Bad named entity: Leftrightarrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Leftrightarrow"
+ ]
+ ]
+ },
+ {
+ "input": "&Leftrightarrow;",
+ "description": "Named entity: Leftrightarrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21d4"
+ ]
+ ]
+ },
+ {
+ "input": "&LessEqualGreater",
+ "description": "Bad named entity: LessEqualGreater without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&LessEqualGreater"
+ ]
+ ]
+ },
+ {
+ "input": "&LessEqualGreater;",
+ "description": "Named entity: LessEqualGreater; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22da"
+ ]
+ ]
+ },
+ {
+ "input": "&LessFullEqual",
+ "description": "Bad named entity: LessFullEqual without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&LessFullEqual"
+ ]
+ ]
+ },
+ {
+ "input": "&LessFullEqual;",
+ "description": "Named entity: LessFullEqual; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2266"
+ ]
+ ]
+ },
+ {
+ "input": "&LessGreater",
+ "description": "Bad named entity: LessGreater without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&LessGreater"
+ ]
+ ]
+ },
+ {
+ "input": "&LessGreater;",
+ "description": "Named entity: LessGreater; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2276"
+ ]
+ ]
+ },
+ {
+ "input": "&LessLess",
+ "description": "Bad named entity: LessLess without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&LessLess"
+ ]
+ ]
+ },
+ {
+ "input": "&LessLess;",
+ "description": "Named entity: LessLess; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2aa1"
+ ]
+ ]
+ },
+ {
+ "input": "&LessSlantEqual",
+ "description": "Bad named entity: LessSlantEqual without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&LessSlantEqual"
+ ]
+ ]
+ },
+ {
+ "input": "&LessSlantEqual;",
+ "description": "Named entity: LessSlantEqual; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a7d"
+ ]
+ ]
+ },
+ {
+ "input": "&LessTilde",
+ "description": "Bad named entity: LessTilde without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&LessTilde"
+ ]
+ ]
+ },
+ {
+ "input": "&LessTilde;",
+ "description": "Named entity: LessTilde; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2272"
+ ]
+ ]
+ },
+ {
+ "input": "&Lfr",
+ "description": "Bad named entity: Lfr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Lfr"
+ ]
+ ]
+ },
+ {
+ "input": "&Lfr;",
+ "description": "Named entity: Lfr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd0f"
+ ]
+ ]
+ },
+ {
+ "input": "&Ll",
+ "description": "Bad named entity: Ll without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Ll"
+ ]
+ ]
+ },
+ {
+ "input": "&Ll;",
+ "description": "Named entity: Ll; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22d8"
+ ]
+ ]
+ },
+ {
+ "input": "&Lleftarrow",
+ "description": "Bad named entity: Lleftarrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Lleftarrow"
+ ]
+ ]
+ },
+ {
+ "input": "&Lleftarrow;",
+ "description": "Named entity: Lleftarrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21da"
+ ]
+ ]
+ },
+ {
+ "input": "&Lmidot",
+ "description": "Bad named entity: Lmidot without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Lmidot"
+ ]
+ ]
+ },
+ {
+ "input": "&Lmidot;",
+ "description": "Named entity: Lmidot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u013f"
+ ]
+ ]
+ },
+ {
+ "input": "&LongLeftArrow",
+ "description": "Bad named entity: LongLeftArrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&LongLeftArrow"
+ ]
+ ]
+ },
+ {
+ "input": "&LongLeftArrow;",
+ "description": "Named entity: LongLeftArrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u27f5"
+ ]
+ ]
+ },
+ {
+ "input": "&LongLeftRightArrow",
+ "description": "Bad named entity: LongLeftRightArrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&LongLeftRightArrow"
+ ]
+ ]
+ },
+ {
+ "input": "&LongLeftRightArrow;",
+ "description": "Named entity: LongLeftRightArrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u27f7"
+ ]
+ ]
+ },
+ {
+ "input": "&LongRightArrow",
+ "description": "Bad named entity: LongRightArrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&LongRightArrow"
+ ]
+ ]
+ },
+ {
+ "input": "&LongRightArrow;",
+ "description": "Named entity: LongRightArrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u27f6"
+ ]
+ ]
+ },
+ {
+ "input": "&Longleftarrow",
+ "description": "Bad named entity: Longleftarrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Longleftarrow"
+ ]
+ ]
+ },
+ {
+ "input": "&Longleftarrow;",
+ "description": "Named entity: Longleftarrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u27f8"
+ ]
+ ]
+ },
+ {
+ "input": "&Longleftrightarrow",
+ "description": "Bad named entity: Longleftrightarrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Longleftrightarrow"
+ ]
+ ]
+ },
+ {
+ "input": "&Longleftrightarrow;",
+ "description": "Named entity: Longleftrightarrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u27fa"
+ ]
+ ]
+ },
+ {
+ "input": "&Longrightarrow",
+ "description": "Bad named entity: Longrightarrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Longrightarrow"
+ ]
+ ]
+ },
+ {
+ "input": "&Longrightarrow;",
+ "description": "Named entity: Longrightarrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u27f9"
+ ]
+ ]
+ },
+ {
+ "input": "&Lopf",
+ "description": "Bad named entity: Lopf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Lopf"
+ ]
+ ]
+ },
+ {
+ "input": "&Lopf;",
+ "description": "Named entity: Lopf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd43"
+ ]
+ ]
+ },
+ {
+ "input": "&LowerLeftArrow",
+ "description": "Bad named entity: LowerLeftArrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&LowerLeftArrow"
+ ]
+ ]
+ },
+ {
+ "input": "&LowerLeftArrow;",
+ "description": "Named entity: LowerLeftArrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2199"
+ ]
+ ]
+ },
+ {
+ "input": "&LowerRightArrow",
+ "description": "Bad named entity: LowerRightArrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&LowerRightArrow"
+ ]
+ ]
+ },
+ {
+ "input": "&LowerRightArrow;",
+ "description": "Named entity: LowerRightArrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2198"
+ ]
+ ]
+ },
+ {
+ "input": "&Lscr",
+ "description": "Bad named entity: Lscr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Lscr"
+ ]
+ ]
+ },
+ {
+ "input": "&Lscr;",
+ "description": "Named entity: Lscr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2112"
+ ]
+ ]
+ },
+ {
+ "input": "&Lsh",
+ "description": "Bad named entity: Lsh without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Lsh"
+ ]
+ ]
+ },
+ {
+ "input": "&Lsh;",
+ "description": "Named entity: Lsh; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21b0"
+ ]
+ ]
+ },
+ {
+ "input": "&Lstrok",
+ "description": "Bad named entity: Lstrok without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Lstrok"
+ ]
+ ]
+ },
+ {
+ "input": "&Lstrok;",
+ "description": "Named entity: Lstrok; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0141"
+ ]
+ ]
+ },
+ {
+ "input": "&Lt",
+ "description": "Bad named entity: Lt without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Lt"
+ ]
+ ]
+ },
+ {
+ "input": "&Lt;",
+ "description": "Named entity: Lt; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u226a"
+ ]
+ ]
+ },
+ {
+ "input": "&Map",
+ "description": "Bad named entity: Map without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Map"
+ ]
+ ]
+ },
+ {
+ "input": "&Map;",
+ "description": "Named entity: Map; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2905"
+ ]
+ ]
+ },
+ {
+ "input": "&Mcy",
+ "description": "Bad named entity: Mcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Mcy"
+ ]
+ ]
+ },
+ {
+ "input": "&Mcy;",
+ "description": "Named entity: Mcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u041c"
+ ]
+ ]
+ },
+ {
+ "input": "&MediumSpace",
+ "description": "Bad named entity: MediumSpace without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&MediumSpace"
+ ]
+ ]
+ },
+ {
+ "input": "&MediumSpace;",
+ "description": "Named entity: MediumSpace; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u205f"
+ ]
+ ]
+ },
+ {
+ "input": "&Mellintrf",
+ "description": "Bad named entity: Mellintrf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Mellintrf"
+ ]
+ ]
+ },
+ {
+ "input": "&Mellintrf;",
+ "description": "Named entity: Mellintrf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2133"
+ ]
+ ]
+ },
+ {
+ "input": "&Mfr",
+ "description": "Bad named entity: Mfr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Mfr"
+ ]
+ ]
+ },
+ {
+ "input": "&Mfr;",
+ "description": "Named entity: Mfr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd10"
+ ]
+ ]
+ },
+ {
+ "input": "&MinusPlus",
+ "description": "Bad named entity: MinusPlus without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&MinusPlus"
+ ]
+ ]
+ },
+ {
+ "input": "&MinusPlus;",
+ "description": "Named entity: MinusPlus; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2213"
+ ]
+ ]
+ },
+ {
+ "input": "&Mopf",
+ "description": "Bad named entity: Mopf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Mopf"
+ ]
+ ]
+ },
+ {
+ "input": "&Mopf;",
+ "description": "Named entity: Mopf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd44"
+ ]
+ ]
+ },
+ {
+ "input": "&Mscr",
+ "description": "Bad named entity: Mscr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Mscr"
+ ]
+ ]
+ },
+ {
+ "input": "&Mscr;",
+ "description": "Named entity: Mscr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2133"
+ ]
+ ]
+ },
+ {
+ "input": "&Mu",
+ "description": "Bad named entity: Mu without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Mu"
+ ]
+ ]
+ },
+ {
+ "input": "&Mu;",
+ "description": "Named entity: Mu; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u039c"
+ ]
+ ]
+ },
+ {
+ "input": "&NJcy",
+ "description": "Bad named entity: NJcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NJcy"
+ ]
+ ]
+ },
+ {
+ "input": "&NJcy;",
+ "description": "Named entity: NJcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u040a"
+ ]
+ ]
+ },
+ {
+ "input": "&Nacute",
+ "description": "Bad named entity: Nacute without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Nacute"
+ ]
+ ]
+ },
+ {
+ "input": "&Nacute;",
+ "description": "Named entity: Nacute; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0143"
+ ]
+ ]
+ },
+ {
+ "input": "&Ncaron",
+ "description": "Bad named entity: Ncaron without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Ncaron"
+ ]
+ ]
+ },
+ {
+ "input": "&Ncaron;",
+ "description": "Named entity: Ncaron; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0147"
+ ]
+ ]
+ },
+ {
+ "input": "&Ncedil",
+ "description": "Bad named entity: Ncedil without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Ncedil"
+ ]
+ ]
+ },
+ {
+ "input": "&Ncedil;",
+ "description": "Named entity: Ncedil; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0145"
+ ]
+ ]
+ },
+ {
+ "input": "&Ncy",
+ "description": "Bad named entity: Ncy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Ncy"
+ ]
+ ]
+ },
+ {
+ "input": "&Ncy;",
+ "description": "Named entity: Ncy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u041d"
+ ]
+ ]
+ },
+ {
+ "input": "&NegativeMediumSpace",
+ "description": "Bad named entity: NegativeMediumSpace without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NegativeMediumSpace"
+ ]
+ ]
+ },
+ {
+ "input": "&NegativeMediumSpace;",
+ "description": "Named entity: NegativeMediumSpace; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u200b"
+ ]
+ ]
+ },
+ {
+ "input": "&NegativeThickSpace",
+ "description": "Bad named entity: NegativeThickSpace without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NegativeThickSpace"
+ ]
+ ]
+ },
+ {
+ "input": "&NegativeThickSpace;",
+ "description": "Named entity: NegativeThickSpace; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u200b"
+ ]
+ ]
+ },
+ {
+ "input": "&NegativeThinSpace",
+ "description": "Bad named entity: NegativeThinSpace without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NegativeThinSpace"
+ ]
+ ]
+ },
+ {
+ "input": "&NegativeThinSpace;",
+ "description": "Named entity: NegativeThinSpace; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u200b"
+ ]
+ ]
+ },
+ {
+ "input": "&NegativeVeryThinSpace",
+ "description": "Bad named entity: NegativeVeryThinSpace without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NegativeVeryThinSpace"
+ ]
+ ]
+ },
+ {
+ "input": "&NegativeVeryThinSpace;",
+ "description": "Named entity: NegativeVeryThinSpace; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u200b"
+ ]
+ ]
+ },
+ {
+ "input": "&NestedGreaterGreater",
+ "description": "Bad named entity: NestedGreaterGreater without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NestedGreaterGreater"
+ ]
+ ]
+ },
+ {
+ "input": "&NestedGreaterGreater;",
+ "description": "Named entity: NestedGreaterGreater; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u226b"
+ ]
+ ]
+ },
+ {
+ "input": "&NestedLessLess",
+ "description": "Bad named entity: NestedLessLess without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NestedLessLess"
+ ]
+ ]
+ },
+ {
+ "input": "&NestedLessLess;",
+ "description": "Named entity: NestedLessLess; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u226a"
+ ]
+ ]
+ },
+ {
+ "input": "&NewLine",
+ "description": "Bad named entity: NewLine without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NewLine"
+ ]
+ ]
+ },
+ {
+ "input": "&NewLine;",
+ "description": "Named entity: NewLine; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\n"
+ ]
+ ]
+ },
+ {
+ "input": "&Nfr",
+ "description": "Bad named entity: Nfr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Nfr"
+ ]
+ ]
+ },
+ {
+ "input": "&Nfr;",
+ "description": "Named entity: Nfr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd11"
+ ]
+ ]
+ },
+ {
+ "input": "&NoBreak",
+ "description": "Bad named entity: NoBreak without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NoBreak"
+ ]
+ ]
+ },
+ {
+ "input": "&NoBreak;",
+ "description": "Named entity: NoBreak; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2060"
+ ]
+ ]
+ },
+ {
+ "input": "&NonBreakingSpace",
+ "description": "Bad named entity: NonBreakingSpace without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NonBreakingSpace"
+ ]
+ ]
+ },
+ {
+ "input": "&NonBreakingSpace;",
+ "description": "Named entity: NonBreakingSpace; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00a0"
+ ]
+ ]
+ },
+ {
+ "input": "&Nopf",
+ "description": "Bad named entity: Nopf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Nopf"
+ ]
+ ]
+ },
+ {
+ "input": "&Nopf;",
+ "description": "Named entity: Nopf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2115"
+ ]
+ ]
+ },
+ {
+ "input": "&Not",
+ "description": "Bad named entity: Not without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Not"
+ ]
+ ]
+ },
+ {
+ "input": "&Not;",
+ "description": "Named entity: Not; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2aec"
+ ]
+ ]
+ },
+ {
+ "input": "&NotCongruent",
+ "description": "Bad named entity: NotCongruent without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NotCongruent"
+ ]
+ ]
+ },
+ {
+ "input": "&NotCongruent;",
+ "description": "Named entity: NotCongruent; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2262"
+ ]
+ ]
+ },
+ {
+ "input": "&NotCupCap",
+ "description": "Bad named entity: NotCupCap without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NotCupCap"
+ ]
+ ]
+ },
+ {
+ "input": "&NotCupCap;",
+ "description": "Named entity: NotCupCap; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u226d"
+ ]
+ ]
+ },
+ {
+ "input": "&NotDoubleVerticalBar",
+ "description": "Bad named entity: NotDoubleVerticalBar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NotDoubleVerticalBar"
+ ]
+ ]
+ },
+ {
+ "input": "&NotDoubleVerticalBar;",
+ "description": "Named entity: NotDoubleVerticalBar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2226"
+ ]
+ ]
+ },
+ {
+ "input": "&NotElement",
+ "description": "Bad named entity: NotElement without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NotElement"
+ ]
+ ]
+ },
+ {
+ "input": "&NotElement;",
+ "description": "Named entity: NotElement; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2209"
+ ]
+ ]
+ },
+ {
+ "input": "&NotEqual",
+ "description": "Bad named entity: NotEqual without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NotEqual"
+ ]
+ ]
+ },
+ {
+ "input": "&NotEqual;",
+ "description": "Named entity: NotEqual; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2260"
+ ]
+ ]
+ },
+ {
+ "input": "&NotEqualTilde",
+ "description": "Bad named entity: NotEqualTilde without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NotEqualTilde"
+ ]
+ ]
+ },
+ {
+ "input": "&NotEqualTilde;",
+ "description": "Named entity: NotEqualTilde; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2242\u0338"
+ ]
+ ]
+ },
+ {
+ "input": "&NotExists",
+ "description": "Bad named entity: NotExists without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NotExists"
+ ]
+ ]
+ },
+ {
+ "input": "&NotExists;",
+ "description": "Named entity: NotExists; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2204"
+ ]
+ ]
+ },
+ {
+ "input": "&NotGreater",
+ "description": "Bad named entity: NotGreater without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NotGreater"
+ ]
+ ]
+ },
+ {
+ "input": "&NotGreater;",
+ "description": "Named entity: NotGreater; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u226f"
+ ]
+ ]
+ },
+ {
+ "input": "&NotGreaterEqual",
+ "description": "Bad named entity: NotGreaterEqual without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NotGreaterEqual"
+ ]
+ ]
+ },
+ {
+ "input": "&NotGreaterEqual;",
+ "description": "Named entity: NotGreaterEqual; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2271"
+ ]
+ ]
+ },
+ {
+ "input": "&NotGreaterFullEqual",
+ "description": "Bad named entity: NotGreaterFullEqual without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NotGreaterFullEqual"
+ ]
+ ]
+ },
+ {
+ "input": "&NotGreaterFullEqual;",
+ "description": "Named entity: NotGreaterFullEqual; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2267\u0338"
+ ]
+ ]
+ },
+ {
+ "input": "&NotGreaterGreater",
+ "description": "Bad named entity: NotGreaterGreater without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NotGreaterGreater"
+ ]
+ ]
+ },
+ {
+ "input": "&NotGreaterGreater;",
+ "description": "Named entity: NotGreaterGreater; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u226b\u0338"
+ ]
+ ]
+ },
+ {
+ "input": "&NotGreaterLess",
+ "description": "Bad named entity: NotGreaterLess without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NotGreaterLess"
+ ]
+ ]
+ },
+ {
+ "input": "&NotGreaterLess;",
+ "description": "Named entity: NotGreaterLess; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2279"
+ ]
+ ]
+ },
+ {
+ "input": "&NotGreaterSlantEqual",
+ "description": "Bad named entity: NotGreaterSlantEqual without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NotGreaterSlantEqual"
+ ]
+ ]
+ },
+ {
+ "input": "&NotGreaterSlantEqual;",
+ "description": "Named entity: NotGreaterSlantEqual; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a7e\u0338"
+ ]
+ ]
+ },
+ {
+ "input": "&NotGreaterTilde",
+ "description": "Bad named entity: NotGreaterTilde without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NotGreaterTilde"
+ ]
+ ]
+ },
+ {
+ "input": "&NotGreaterTilde;",
+ "description": "Named entity: NotGreaterTilde; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2275"
+ ]
+ ]
+ },
+ {
+ "input": "&NotHumpDownHump",
+ "description": "Bad named entity: NotHumpDownHump without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NotHumpDownHump"
+ ]
+ ]
+ },
+ {
+ "input": "&NotHumpDownHump;",
+ "description": "Named entity: NotHumpDownHump; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u224e\u0338"
+ ]
+ ]
+ },
+ {
+ "input": "&NotHumpEqual",
+ "description": "Bad named entity: NotHumpEqual without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NotHumpEqual"
+ ]
+ ]
+ },
+ {
+ "input": "&NotHumpEqual;",
+ "description": "Named entity: NotHumpEqual; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u224f\u0338"
+ ]
+ ]
+ },
+ {
+ "input": "&NotLeftTriangle",
+ "description": "Bad named entity: NotLeftTriangle without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NotLeftTriangle"
+ ]
+ ]
+ },
+ {
+ "input": "&NotLeftTriangle;",
+ "description": "Named entity: NotLeftTriangle; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22ea"
+ ]
+ ]
+ },
+ {
+ "input": "&NotLeftTriangleBar",
+ "description": "Bad named entity: NotLeftTriangleBar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NotLeftTriangleBar"
+ ]
+ ]
+ },
+ {
+ "input": "&NotLeftTriangleBar;",
+ "description": "Named entity: NotLeftTriangleBar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u29cf\u0338"
+ ]
+ ]
+ },
+ {
+ "input": "&NotLeftTriangleEqual",
+ "description": "Bad named entity: NotLeftTriangleEqual without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NotLeftTriangleEqual"
+ ]
+ ]
+ },
+ {
+ "input": "&NotLeftTriangleEqual;",
+ "description": "Named entity: NotLeftTriangleEqual; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22ec"
+ ]
+ ]
+ },
+ {
+ "input": "&NotLess",
+ "description": "Bad named entity: NotLess without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NotLess"
+ ]
+ ]
+ },
+ {
+ "input": "&NotLess;",
+ "description": "Named entity: NotLess; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u226e"
+ ]
+ ]
+ },
+ {
+ "input": "&NotLessEqual",
+ "description": "Bad named entity: NotLessEqual without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NotLessEqual"
+ ]
+ ]
+ },
+ {
+ "input": "&NotLessEqual;",
+ "description": "Named entity: NotLessEqual; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2270"
+ ]
+ ]
+ },
+ {
+ "input": "&NotLessGreater",
+ "description": "Bad named entity: NotLessGreater without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NotLessGreater"
+ ]
+ ]
+ },
+ {
+ "input": "&NotLessGreater;",
+ "description": "Named entity: NotLessGreater; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2278"
+ ]
+ ]
+ },
+ {
+ "input": "&NotLessLess",
+ "description": "Bad named entity: NotLessLess without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NotLessLess"
+ ]
+ ]
+ },
+ {
+ "input": "&NotLessLess;",
+ "description": "Named entity: NotLessLess; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u226a\u0338"
+ ]
+ ]
+ },
+ {
+ "input": "&NotLessSlantEqual",
+ "description": "Bad named entity: NotLessSlantEqual without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NotLessSlantEqual"
+ ]
+ ]
+ },
+ {
+ "input": "&NotLessSlantEqual;",
+ "description": "Named entity: NotLessSlantEqual; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a7d\u0338"
+ ]
+ ]
+ },
+ {
+ "input": "&NotLessTilde",
+ "description": "Bad named entity: NotLessTilde without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NotLessTilde"
+ ]
+ ]
+ },
+ {
+ "input": "&NotLessTilde;",
+ "description": "Named entity: NotLessTilde; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2274"
+ ]
+ ]
+ },
+ {
+ "input": "&NotNestedGreaterGreater",
+ "description": "Bad named entity: NotNestedGreaterGreater without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NotNestedGreaterGreater"
+ ]
+ ]
+ },
+ {
+ "input": "&NotNestedGreaterGreater;",
+ "description": "Named entity: NotNestedGreaterGreater; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2aa2\u0338"
+ ]
+ ]
+ },
+ {
+ "input": "&NotNestedLessLess",
+ "description": "Bad named entity: NotNestedLessLess without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NotNestedLessLess"
+ ]
+ ]
+ },
+ {
+ "input": "&NotNestedLessLess;",
+ "description": "Named entity: NotNestedLessLess; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2aa1\u0338"
+ ]
+ ]
+ },
+ {
+ "input": "&NotPrecedes",
+ "description": "Bad named entity: NotPrecedes without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NotPrecedes"
+ ]
+ ]
+ },
+ {
+ "input": "&NotPrecedes;",
+ "description": "Named entity: NotPrecedes; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2280"
+ ]
+ ]
+ },
+ {
+ "input": "&NotPrecedesEqual",
+ "description": "Bad named entity: NotPrecedesEqual without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NotPrecedesEqual"
+ ]
+ ]
+ },
+ {
+ "input": "&NotPrecedesEqual;",
+ "description": "Named entity: NotPrecedesEqual; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2aaf\u0338"
+ ]
+ ]
+ },
+ {
+ "input": "&NotPrecedesSlantEqual",
+ "description": "Bad named entity: NotPrecedesSlantEqual without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NotPrecedesSlantEqual"
+ ]
+ ]
+ },
+ {
+ "input": "&NotPrecedesSlantEqual;",
+ "description": "Named entity: NotPrecedesSlantEqual; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22e0"
+ ]
+ ]
+ },
+ {
+ "input": "&NotReverseElement",
+ "description": "Bad named entity: NotReverseElement without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NotReverseElement"
+ ]
+ ]
+ },
+ {
+ "input": "&NotReverseElement;",
+ "description": "Named entity: NotReverseElement; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u220c"
+ ]
+ ]
+ },
+ {
+ "input": "&NotRightTriangle",
+ "description": "Bad named entity: NotRightTriangle without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NotRightTriangle"
+ ]
+ ]
+ },
+ {
+ "input": "&NotRightTriangle;",
+ "description": "Named entity: NotRightTriangle; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22eb"
+ ]
+ ]
+ },
+ {
+ "input": "&NotRightTriangleBar",
+ "description": "Bad named entity: NotRightTriangleBar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NotRightTriangleBar"
+ ]
+ ]
+ },
+ {
+ "input": "&NotRightTriangleBar;",
+ "description": "Named entity: NotRightTriangleBar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u29d0\u0338"
+ ]
+ ]
+ },
+ {
+ "input": "&NotRightTriangleEqual",
+ "description": "Bad named entity: NotRightTriangleEqual without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NotRightTriangleEqual"
+ ]
+ ]
+ },
+ {
+ "input": "&NotRightTriangleEqual;",
+ "description": "Named entity: NotRightTriangleEqual; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22ed"
+ ]
+ ]
+ },
+ {
+ "input": "&NotSquareSubset",
+ "description": "Bad named entity: NotSquareSubset without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NotSquareSubset"
+ ]
+ ]
+ },
+ {
+ "input": "&NotSquareSubset;",
+ "description": "Named entity: NotSquareSubset; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u228f\u0338"
+ ]
+ ]
+ },
+ {
+ "input": "&NotSquareSubsetEqual",
+ "description": "Bad named entity: NotSquareSubsetEqual without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NotSquareSubsetEqual"
+ ]
+ ]
+ },
+ {
+ "input": "&NotSquareSubsetEqual;",
+ "description": "Named entity: NotSquareSubsetEqual; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22e2"
+ ]
+ ]
+ },
+ {
+ "input": "&NotSquareSuperset",
+ "description": "Bad named entity: NotSquareSuperset without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NotSquareSuperset"
+ ]
+ ]
+ },
+ {
+ "input": "&NotSquareSuperset;",
+ "description": "Named entity: NotSquareSuperset; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2290\u0338"
+ ]
+ ]
+ },
+ {
+ "input": "&NotSquareSupersetEqual",
+ "description": "Bad named entity: NotSquareSupersetEqual without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NotSquareSupersetEqual"
+ ]
+ ]
+ },
+ {
+ "input": "&NotSquareSupersetEqual;",
+ "description": "Named entity: NotSquareSupersetEqual; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22e3"
+ ]
+ ]
+ },
+ {
+ "input": "&NotSubset",
+ "description": "Bad named entity: NotSubset without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NotSubset"
+ ]
+ ]
+ },
+ {
+ "input": "&NotSubset;",
+ "description": "Named entity: NotSubset; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2282\u20d2"
+ ]
+ ]
+ },
+ {
+ "input": "&NotSubsetEqual",
+ "description": "Bad named entity: NotSubsetEqual without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NotSubsetEqual"
+ ]
+ ]
+ },
+ {
+ "input": "&NotSubsetEqual;",
+ "description": "Named entity: NotSubsetEqual; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2288"
+ ]
+ ]
+ },
+ {
+ "input": "&NotSucceeds",
+ "description": "Bad named entity: NotSucceeds without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NotSucceeds"
+ ]
+ ]
+ },
+ {
+ "input": "&NotSucceeds;",
+ "description": "Named entity: NotSucceeds; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2281"
+ ]
+ ]
+ },
+ {
+ "input": "&NotSucceedsEqual",
+ "description": "Bad named entity: NotSucceedsEqual without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NotSucceedsEqual"
+ ]
+ ]
+ },
+ {
+ "input": "&NotSucceedsEqual;",
+ "description": "Named entity: NotSucceedsEqual; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2ab0\u0338"
+ ]
+ ]
+ },
+ {
+ "input": "&NotSucceedsSlantEqual",
+ "description": "Bad named entity: NotSucceedsSlantEqual without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NotSucceedsSlantEqual"
+ ]
+ ]
+ },
+ {
+ "input": "&NotSucceedsSlantEqual;",
+ "description": "Named entity: NotSucceedsSlantEqual; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22e1"
+ ]
+ ]
+ },
+ {
+ "input": "&NotSucceedsTilde",
+ "description": "Bad named entity: NotSucceedsTilde without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NotSucceedsTilde"
+ ]
+ ]
+ },
+ {
+ "input": "&NotSucceedsTilde;",
+ "description": "Named entity: NotSucceedsTilde; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u227f\u0338"
+ ]
+ ]
+ },
+ {
+ "input": "&NotSuperset",
+ "description": "Bad named entity: NotSuperset without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NotSuperset"
+ ]
+ ]
+ },
+ {
+ "input": "&NotSuperset;",
+ "description": "Named entity: NotSuperset; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2283\u20d2"
+ ]
+ ]
+ },
+ {
+ "input": "&NotSupersetEqual",
+ "description": "Bad named entity: NotSupersetEqual without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NotSupersetEqual"
+ ]
+ ]
+ },
+ {
+ "input": "&NotSupersetEqual;",
+ "description": "Named entity: NotSupersetEqual; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2289"
+ ]
+ ]
+ },
+ {
+ "input": "&NotTilde",
+ "description": "Bad named entity: NotTilde without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NotTilde"
+ ]
+ ]
+ },
+ {
+ "input": "&NotTilde;",
+ "description": "Named entity: NotTilde; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2241"
+ ]
+ ]
+ },
+ {
+ "input": "&NotTildeEqual",
+ "description": "Bad named entity: NotTildeEqual without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NotTildeEqual"
+ ]
+ ]
+ },
+ {
+ "input": "&NotTildeEqual;",
+ "description": "Named entity: NotTildeEqual; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2244"
+ ]
+ ]
+ },
+ {
+ "input": "&NotTildeFullEqual",
+ "description": "Bad named entity: NotTildeFullEqual without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NotTildeFullEqual"
+ ]
+ ]
+ },
+ {
+ "input": "&NotTildeFullEqual;",
+ "description": "Named entity: NotTildeFullEqual; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2247"
+ ]
+ ]
+ },
+ {
+ "input": "&NotTildeTilde",
+ "description": "Bad named entity: NotTildeTilde without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NotTildeTilde"
+ ]
+ ]
+ },
+ {
+ "input": "&NotTildeTilde;",
+ "description": "Named entity: NotTildeTilde; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2249"
+ ]
+ ]
+ },
+ {
+ "input": "&NotVerticalBar",
+ "description": "Bad named entity: NotVerticalBar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&NotVerticalBar"
+ ]
+ ]
+ },
+ {
+ "input": "&NotVerticalBar;",
+ "description": "Named entity: NotVerticalBar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2224"
+ ]
+ ]
+ },
+ {
+ "input": "&Nscr",
+ "description": "Bad named entity: Nscr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Nscr"
+ ]
+ ]
+ },
+ {
+ "input": "&Nscr;",
+ "description": "Named entity: Nscr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udca9"
+ ]
+ ]
+ },
+ {
+ "input": "&Ntilde",
+ "description": "Named entity: Ntilde without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00d1"
+ ]
+ ]
+ },
+ {
+ "input": "&Ntilde;",
+ "description": "Named entity: Ntilde; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00d1"
+ ]
+ ]
+ },
+ {
+ "input": "&Nu",
+ "description": "Bad named entity: Nu without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Nu"
+ ]
+ ]
+ },
+ {
+ "input": "&Nu;",
+ "description": "Named entity: Nu; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u039d"
+ ]
+ ]
+ },
+ {
+ "input": "&OElig",
+ "description": "Bad named entity: OElig without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&OElig"
+ ]
+ ]
+ },
+ {
+ "input": "&OElig;",
+ "description": "Named entity: OElig; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0152"
+ ]
+ ]
+ },
+ {
+ "input": "&Oacute",
+ "description": "Named entity: Oacute without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00d3"
+ ]
+ ]
+ },
+ {
+ "input": "&Oacute;",
+ "description": "Named entity: Oacute; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00d3"
+ ]
+ ]
+ },
+ {
+ "input": "&Ocirc",
+ "description": "Named entity: Ocirc without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00d4"
+ ]
+ ]
+ },
+ {
+ "input": "&Ocirc;",
+ "description": "Named entity: Ocirc; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00d4"
+ ]
+ ]
+ },
+ {
+ "input": "&Ocy",
+ "description": "Bad named entity: Ocy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Ocy"
+ ]
+ ]
+ },
+ {
+ "input": "&Ocy;",
+ "description": "Named entity: Ocy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u041e"
+ ]
+ ]
+ },
+ {
+ "input": "&Odblac",
+ "description": "Bad named entity: Odblac without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Odblac"
+ ]
+ ]
+ },
+ {
+ "input": "&Odblac;",
+ "description": "Named entity: Odblac; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0150"
+ ]
+ ]
+ },
+ {
+ "input": "&Ofr",
+ "description": "Bad named entity: Ofr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Ofr"
+ ]
+ ]
+ },
+ {
+ "input": "&Ofr;",
+ "description": "Named entity: Ofr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd12"
+ ]
+ ]
+ },
+ {
+ "input": "&Ograve",
+ "description": "Named entity: Ograve without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00d2"
+ ]
+ ]
+ },
+ {
+ "input": "&Ograve;",
+ "description": "Named entity: Ograve; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00d2"
+ ]
+ ]
+ },
+ {
+ "input": "&Omacr",
+ "description": "Bad named entity: Omacr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Omacr"
+ ]
+ ]
+ },
+ {
+ "input": "&Omacr;",
+ "description": "Named entity: Omacr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u014c"
+ ]
+ ]
+ },
+ {
+ "input": "&Omega",
+ "description": "Bad named entity: Omega without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Omega"
+ ]
+ ]
+ },
+ {
+ "input": "&Omega;",
+ "description": "Named entity: Omega; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03a9"
+ ]
+ ]
+ },
+ {
+ "input": "&Omicron",
+ "description": "Bad named entity: Omicron without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Omicron"
+ ]
+ ]
+ },
+ {
+ "input": "&Omicron;",
+ "description": "Named entity: Omicron; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u039f"
+ ]
+ ]
+ },
+ {
+ "input": "&Oopf",
+ "description": "Bad named entity: Oopf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Oopf"
+ ]
+ ]
+ },
+ {
+ "input": "&Oopf;",
+ "description": "Named entity: Oopf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd46"
+ ]
+ ]
+ },
+ {
+ "input": "&OpenCurlyDoubleQuote",
+ "description": "Bad named entity: OpenCurlyDoubleQuote without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&OpenCurlyDoubleQuote"
+ ]
+ ]
+ },
+ {
+ "input": "&OpenCurlyDoubleQuote;",
+ "description": "Named entity: OpenCurlyDoubleQuote; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u201c"
+ ]
+ ]
+ },
+ {
+ "input": "&OpenCurlyQuote",
+ "description": "Bad named entity: OpenCurlyQuote without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&OpenCurlyQuote"
+ ]
+ ]
+ },
+ {
+ "input": "&OpenCurlyQuote;",
+ "description": "Named entity: OpenCurlyQuote; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2018"
+ ]
+ ]
+ },
+ {
+ "input": "&Or",
+ "description": "Bad named entity: Or without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Or"
+ ]
+ ]
+ },
+ {
+ "input": "&Or;",
+ "description": "Named entity: Or; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a54"
+ ]
+ ]
+ },
+ {
+ "input": "&Oscr",
+ "description": "Bad named entity: Oscr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Oscr"
+ ]
+ ]
+ },
+ {
+ "input": "&Oscr;",
+ "description": "Named entity: Oscr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udcaa"
+ ]
+ ]
+ },
+ {
+ "input": "&Oslash",
+ "description": "Named entity: Oslash without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00d8"
+ ]
+ ]
+ },
+ {
+ "input": "&Oslash;",
+ "description": "Named entity: Oslash; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00d8"
+ ]
+ ]
+ },
+ {
+ "input": "&Otilde",
+ "description": "Named entity: Otilde without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00d5"
+ ]
+ ]
+ },
+ {
+ "input": "&Otilde;",
+ "description": "Named entity: Otilde; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00d5"
+ ]
+ ]
+ },
+ {
+ "input": "&Otimes",
+ "description": "Bad named entity: Otimes without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Otimes"
+ ]
+ ]
+ },
+ {
+ "input": "&Otimes;",
+ "description": "Named entity: Otimes; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a37"
+ ]
+ ]
+ },
+ {
+ "input": "&Ouml",
+ "description": "Named entity: Ouml without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00d6"
+ ]
+ ]
+ },
+ {
+ "input": "&Ouml;",
+ "description": "Named entity: Ouml; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00d6"
+ ]
+ ]
+ },
+ {
+ "input": "&OverBar",
+ "description": "Bad named entity: OverBar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&OverBar"
+ ]
+ ]
+ },
+ {
+ "input": "&OverBar;",
+ "description": "Named entity: OverBar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u203e"
+ ]
+ ]
+ },
+ {
+ "input": "&OverBrace",
+ "description": "Bad named entity: OverBrace without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&OverBrace"
+ ]
+ ]
+ },
+ {
+ "input": "&OverBrace;",
+ "description": "Named entity: OverBrace; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u23de"
+ ]
+ ]
+ },
+ {
+ "input": "&OverBracket",
+ "description": "Bad named entity: OverBracket without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&OverBracket"
+ ]
+ ]
+ },
+ {
+ "input": "&OverBracket;",
+ "description": "Named entity: OverBracket; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u23b4"
+ ]
+ ]
+ },
+ {
+ "input": "&OverParenthesis",
+ "description": "Bad named entity: OverParenthesis without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&OverParenthesis"
+ ]
+ ]
+ },
+ {
+ "input": "&OverParenthesis;",
+ "description": "Named entity: OverParenthesis; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u23dc"
+ ]
+ ]
+ },
+ {
+ "input": "&PartialD",
+ "description": "Bad named entity: PartialD without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&PartialD"
+ ]
+ ]
+ },
+ {
+ "input": "&PartialD;",
+ "description": "Named entity: PartialD; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2202"
+ ]
+ ]
+ },
+ {
+ "input": "&Pcy",
+ "description": "Bad named entity: Pcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Pcy"
+ ]
+ ]
+ },
+ {
+ "input": "&Pcy;",
+ "description": "Named entity: Pcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u041f"
+ ]
+ ]
+ },
+ {
+ "input": "&Pfr",
+ "description": "Bad named entity: Pfr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Pfr"
+ ]
+ ]
+ },
+ {
+ "input": "&Pfr;",
+ "description": "Named entity: Pfr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd13"
+ ]
+ ]
+ },
+ {
+ "input": "&Phi",
+ "description": "Bad named entity: Phi without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Phi"
+ ]
+ ]
+ },
+ {
+ "input": "&Phi;",
+ "description": "Named entity: Phi; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03a6"
+ ]
+ ]
+ },
+ {
+ "input": "&Pi",
+ "description": "Bad named entity: Pi without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Pi"
+ ]
+ ]
+ },
+ {
+ "input": "&Pi;",
+ "description": "Named entity: Pi; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03a0"
+ ]
+ ]
+ },
+ {
+ "input": "&PlusMinus",
+ "description": "Bad named entity: PlusMinus without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&PlusMinus"
+ ]
+ ]
+ },
+ {
+ "input": "&PlusMinus;",
+ "description": "Named entity: PlusMinus; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00b1"
+ ]
+ ]
+ },
+ {
+ "input": "&Poincareplane",
+ "description": "Bad named entity: Poincareplane without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Poincareplane"
+ ]
+ ]
+ },
+ {
+ "input": "&Poincareplane;",
+ "description": "Named entity: Poincareplane; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u210c"
+ ]
+ ]
+ },
+ {
+ "input": "&Popf",
+ "description": "Bad named entity: Popf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Popf"
+ ]
+ ]
+ },
+ {
+ "input": "&Popf;",
+ "description": "Named entity: Popf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2119"
+ ]
+ ]
+ },
+ {
+ "input": "&Pr",
+ "description": "Bad named entity: Pr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Pr"
+ ]
+ ]
+ },
+ {
+ "input": "&Pr;",
+ "description": "Named entity: Pr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2abb"
+ ]
+ ]
+ },
+ {
+ "input": "&Precedes",
+ "description": "Bad named entity: Precedes without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Precedes"
+ ]
+ ]
+ },
+ {
+ "input": "&Precedes;",
+ "description": "Named entity: Precedes; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u227a"
+ ]
+ ]
+ },
+ {
+ "input": "&PrecedesEqual",
+ "description": "Bad named entity: PrecedesEqual without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&PrecedesEqual"
+ ]
+ ]
+ },
+ {
+ "input": "&PrecedesEqual;",
+ "description": "Named entity: PrecedesEqual; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2aaf"
+ ]
+ ]
+ },
+ {
+ "input": "&PrecedesSlantEqual",
+ "description": "Bad named entity: PrecedesSlantEqual without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&PrecedesSlantEqual"
+ ]
+ ]
+ },
+ {
+ "input": "&PrecedesSlantEqual;",
+ "description": "Named entity: PrecedesSlantEqual; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u227c"
+ ]
+ ]
+ },
+ {
+ "input": "&PrecedesTilde",
+ "description": "Bad named entity: PrecedesTilde without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&PrecedesTilde"
+ ]
+ ]
+ },
+ {
+ "input": "&PrecedesTilde;",
+ "description": "Named entity: PrecedesTilde; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u227e"
+ ]
+ ]
+ },
+ {
+ "input": "&Prime",
+ "description": "Bad named entity: Prime without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Prime"
+ ]
+ ]
+ },
+ {
+ "input": "&Prime;",
+ "description": "Named entity: Prime; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2033"
+ ]
+ ]
+ },
+ {
+ "input": "&Product",
+ "description": "Bad named entity: Product without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Product"
+ ]
+ ]
+ },
+ {
+ "input": "&Product;",
+ "description": "Named entity: Product; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u220f"
+ ]
+ ]
+ },
+ {
+ "input": "&Proportion",
+ "description": "Bad named entity: Proportion without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Proportion"
+ ]
+ ]
+ },
+ {
+ "input": "&Proportion;",
+ "description": "Named entity: Proportion; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2237"
+ ]
+ ]
+ },
+ {
+ "input": "&Proportional",
+ "description": "Bad named entity: Proportional without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Proportional"
+ ]
+ ]
+ },
+ {
+ "input": "&Proportional;",
+ "description": "Named entity: Proportional; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u221d"
+ ]
+ ]
+ },
+ {
+ "input": "&Pscr",
+ "description": "Bad named entity: Pscr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Pscr"
+ ]
+ ]
+ },
+ {
+ "input": "&Pscr;",
+ "description": "Named entity: Pscr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udcab"
+ ]
+ ]
+ },
+ {
+ "input": "&Psi",
+ "description": "Bad named entity: Psi without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Psi"
+ ]
+ ]
+ },
+ {
+ "input": "&Psi;",
+ "description": "Named entity: Psi; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03a8"
+ ]
+ ]
+ },
+ {
+ "input": "&QUOT",
+ "description": "Named entity: QUOT without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\""
+ ]
+ ]
+ },
+ {
+ "input": "&QUOT;",
+ "description": "Named entity: QUOT; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\""
+ ]
+ ]
+ },
+ {
+ "input": "&Qfr",
+ "description": "Bad named entity: Qfr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Qfr"
+ ]
+ ]
+ },
+ {
+ "input": "&Qfr;",
+ "description": "Named entity: Qfr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd14"
+ ]
+ ]
+ },
+ {
+ "input": "&Qopf",
+ "description": "Bad named entity: Qopf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Qopf"
+ ]
+ ]
+ },
+ {
+ "input": "&Qopf;",
+ "description": "Named entity: Qopf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u211a"
+ ]
+ ]
+ },
+ {
+ "input": "&Qscr",
+ "description": "Bad named entity: Qscr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Qscr"
+ ]
+ ]
+ },
+ {
+ "input": "&Qscr;",
+ "description": "Named entity: Qscr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udcac"
+ ]
+ ]
+ },
+ {
+ "input": "&RBarr",
+ "description": "Bad named entity: RBarr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&RBarr"
+ ]
+ ]
+ },
+ {
+ "input": "&RBarr;",
+ "description": "Named entity: RBarr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2910"
+ ]
+ ]
+ },
+ {
+ "input": "&REG",
+ "description": "Named entity: REG without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00ae"
+ ]
+ ]
+ },
+ {
+ "input": "&REG;",
+ "description": "Named entity: REG; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00ae"
+ ]
+ ]
+ },
+ {
+ "input": "&Racute",
+ "description": "Bad named entity: Racute without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Racute"
+ ]
+ ]
+ },
+ {
+ "input": "&Racute;",
+ "description": "Named entity: Racute; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0154"
+ ]
+ ]
+ },
+ {
+ "input": "&Rang",
+ "description": "Bad named entity: Rang without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Rang"
+ ]
+ ]
+ },
+ {
+ "input": "&Rang;",
+ "description": "Named entity: Rang; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u27eb"
+ ]
+ ]
+ },
+ {
+ "input": "&Rarr",
+ "description": "Bad named entity: Rarr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Rarr"
+ ]
+ ]
+ },
+ {
+ "input": "&Rarr;",
+ "description": "Named entity: Rarr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21a0"
+ ]
+ ]
+ },
+ {
+ "input": "&Rarrtl",
+ "description": "Bad named entity: Rarrtl without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Rarrtl"
+ ]
+ ]
+ },
+ {
+ "input": "&Rarrtl;",
+ "description": "Named entity: Rarrtl; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2916"
+ ]
+ ]
+ },
+ {
+ "input": "&Rcaron",
+ "description": "Bad named entity: Rcaron without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Rcaron"
+ ]
+ ]
+ },
+ {
+ "input": "&Rcaron;",
+ "description": "Named entity: Rcaron; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0158"
+ ]
+ ]
+ },
+ {
+ "input": "&Rcedil",
+ "description": "Bad named entity: Rcedil without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Rcedil"
+ ]
+ ]
+ },
+ {
+ "input": "&Rcedil;",
+ "description": "Named entity: Rcedil; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0156"
+ ]
+ ]
+ },
+ {
+ "input": "&Rcy",
+ "description": "Bad named entity: Rcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Rcy"
+ ]
+ ]
+ },
+ {
+ "input": "&Rcy;",
+ "description": "Named entity: Rcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0420"
+ ]
+ ]
+ },
+ {
+ "input": "&Re",
+ "description": "Bad named entity: Re without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Re"
+ ]
+ ]
+ },
+ {
+ "input": "&Re;",
+ "description": "Named entity: Re; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u211c"
+ ]
+ ]
+ },
+ {
+ "input": "&ReverseElement",
+ "description": "Bad named entity: ReverseElement without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ReverseElement"
+ ]
+ ]
+ },
+ {
+ "input": "&ReverseElement;",
+ "description": "Named entity: ReverseElement; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u220b"
+ ]
+ ]
+ },
+ {
+ "input": "&ReverseEquilibrium",
+ "description": "Bad named entity: ReverseEquilibrium without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ReverseEquilibrium"
+ ]
+ ]
+ },
+ {
+ "input": "&ReverseEquilibrium;",
+ "description": "Named entity: ReverseEquilibrium; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21cb"
+ ]
+ ]
+ },
+ {
+ "input": "&ReverseUpEquilibrium",
+ "description": "Bad named entity: ReverseUpEquilibrium without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ReverseUpEquilibrium"
+ ]
+ ]
+ },
+ {
+ "input": "&ReverseUpEquilibrium;",
+ "description": "Named entity: ReverseUpEquilibrium; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u296f"
+ ]
+ ]
+ },
+ {
+ "input": "&Rfr",
+ "description": "Bad named entity: Rfr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Rfr"
+ ]
+ ]
+ },
+ {
+ "input": "&Rfr;",
+ "description": "Named entity: Rfr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u211c"
+ ]
+ ]
+ },
+ {
+ "input": "&Rho",
+ "description": "Bad named entity: Rho without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Rho"
+ ]
+ ]
+ },
+ {
+ "input": "&Rho;",
+ "description": "Named entity: Rho; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03a1"
+ ]
+ ]
+ },
+ {
+ "input": "&RightAngleBracket",
+ "description": "Bad named entity: RightAngleBracket without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&RightAngleBracket"
+ ]
+ ]
+ },
+ {
+ "input": "&RightAngleBracket;",
+ "description": "Named entity: RightAngleBracket; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u27e9"
+ ]
+ ]
+ },
+ {
+ "input": "&RightArrow",
+ "description": "Bad named entity: RightArrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&RightArrow"
+ ]
+ ]
+ },
+ {
+ "input": "&RightArrow;",
+ "description": "Named entity: RightArrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2192"
+ ]
+ ]
+ },
+ {
+ "input": "&RightArrowBar",
+ "description": "Bad named entity: RightArrowBar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&RightArrowBar"
+ ]
+ ]
+ },
+ {
+ "input": "&RightArrowBar;",
+ "description": "Named entity: RightArrowBar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21e5"
+ ]
+ ]
+ },
+ {
+ "input": "&RightArrowLeftArrow",
+ "description": "Bad named entity: RightArrowLeftArrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&RightArrowLeftArrow"
+ ]
+ ]
+ },
+ {
+ "input": "&RightArrowLeftArrow;",
+ "description": "Named entity: RightArrowLeftArrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21c4"
+ ]
+ ]
+ },
+ {
+ "input": "&RightCeiling",
+ "description": "Bad named entity: RightCeiling without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&RightCeiling"
+ ]
+ ]
+ },
+ {
+ "input": "&RightCeiling;",
+ "description": "Named entity: RightCeiling; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2309"
+ ]
+ ]
+ },
+ {
+ "input": "&RightDoubleBracket",
+ "description": "Bad named entity: RightDoubleBracket without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&RightDoubleBracket"
+ ]
+ ]
+ },
+ {
+ "input": "&RightDoubleBracket;",
+ "description": "Named entity: RightDoubleBracket; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u27e7"
+ ]
+ ]
+ },
+ {
+ "input": "&RightDownTeeVector",
+ "description": "Bad named entity: RightDownTeeVector without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&RightDownTeeVector"
+ ]
+ ]
+ },
+ {
+ "input": "&RightDownTeeVector;",
+ "description": "Named entity: RightDownTeeVector; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u295d"
+ ]
+ ]
+ },
+ {
+ "input": "&RightDownVector",
+ "description": "Bad named entity: RightDownVector without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&RightDownVector"
+ ]
+ ]
+ },
+ {
+ "input": "&RightDownVector;",
+ "description": "Named entity: RightDownVector; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21c2"
+ ]
+ ]
+ },
+ {
+ "input": "&RightDownVectorBar",
+ "description": "Bad named entity: RightDownVectorBar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&RightDownVectorBar"
+ ]
+ ]
+ },
+ {
+ "input": "&RightDownVectorBar;",
+ "description": "Named entity: RightDownVectorBar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2955"
+ ]
+ ]
+ },
+ {
+ "input": "&RightFloor",
+ "description": "Bad named entity: RightFloor without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&RightFloor"
+ ]
+ ]
+ },
+ {
+ "input": "&RightFloor;",
+ "description": "Named entity: RightFloor; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u230b"
+ ]
+ ]
+ },
+ {
+ "input": "&RightTee",
+ "description": "Bad named entity: RightTee without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&RightTee"
+ ]
+ ]
+ },
+ {
+ "input": "&RightTee;",
+ "description": "Named entity: RightTee; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22a2"
+ ]
+ ]
+ },
+ {
+ "input": "&RightTeeArrow",
+ "description": "Bad named entity: RightTeeArrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&RightTeeArrow"
+ ]
+ ]
+ },
+ {
+ "input": "&RightTeeArrow;",
+ "description": "Named entity: RightTeeArrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21a6"
+ ]
+ ]
+ },
+ {
+ "input": "&RightTeeVector",
+ "description": "Bad named entity: RightTeeVector without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&RightTeeVector"
+ ]
+ ]
+ },
+ {
+ "input": "&RightTeeVector;",
+ "description": "Named entity: RightTeeVector; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u295b"
+ ]
+ ]
+ },
+ {
+ "input": "&RightTriangle",
+ "description": "Bad named entity: RightTriangle without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&RightTriangle"
+ ]
+ ]
+ },
+ {
+ "input": "&RightTriangle;",
+ "description": "Named entity: RightTriangle; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22b3"
+ ]
+ ]
+ },
+ {
+ "input": "&RightTriangleBar",
+ "description": "Bad named entity: RightTriangleBar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&RightTriangleBar"
+ ]
+ ]
+ },
+ {
+ "input": "&RightTriangleBar;",
+ "description": "Named entity: RightTriangleBar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u29d0"
+ ]
+ ]
+ },
+ {
+ "input": "&RightTriangleEqual",
+ "description": "Bad named entity: RightTriangleEqual without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&RightTriangleEqual"
+ ]
+ ]
+ },
+ {
+ "input": "&RightTriangleEqual;",
+ "description": "Named entity: RightTriangleEqual; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22b5"
+ ]
+ ]
+ },
+ {
+ "input": "&RightUpDownVector",
+ "description": "Bad named entity: RightUpDownVector without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&RightUpDownVector"
+ ]
+ ]
+ },
+ {
+ "input": "&RightUpDownVector;",
+ "description": "Named entity: RightUpDownVector; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u294f"
+ ]
+ ]
+ },
+ {
+ "input": "&RightUpTeeVector",
+ "description": "Bad named entity: RightUpTeeVector without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&RightUpTeeVector"
+ ]
+ ]
+ },
+ {
+ "input": "&RightUpTeeVector;",
+ "description": "Named entity: RightUpTeeVector; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u295c"
+ ]
+ ]
+ },
+ {
+ "input": "&RightUpVector",
+ "description": "Bad named entity: RightUpVector without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&RightUpVector"
+ ]
+ ]
+ },
+ {
+ "input": "&RightUpVector;",
+ "description": "Named entity: RightUpVector; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21be"
+ ]
+ ]
+ },
+ {
+ "input": "&RightUpVectorBar",
+ "description": "Bad named entity: RightUpVectorBar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&RightUpVectorBar"
+ ]
+ ]
+ },
+ {
+ "input": "&RightUpVectorBar;",
+ "description": "Named entity: RightUpVectorBar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2954"
+ ]
+ ]
+ },
+ {
+ "input": "&RightVector",
+ "description": "Bad named entity: RightVector without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&RightVector"
+ ]
+ ]
+ },
+ {
+ "input": "&RightVector;",
+ "description": "Named entity: RightVector; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21c0"
+ ]
+ ]
+ },
+ {
+ "input": "&RightVectorBar",
+ "description": "Bad named entity: RightVectorBar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&RightVectorBar"
+ ]
+ ]
+ },
+ {
+ "input": "&RightVectorBar;",
+ "description": "Named entity: RightVectorBar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2953"
+ ]
+ ]
+ },
+ {
+ "input": "&Rightarrow",
+ "description": "Bad named entity: Rightarrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Rightarrow"
+ ]
+ ]
+ },
+ {
+ "input": "&Rightarrow;",
+ "description": "Named entity: Rightarrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21d2"
+ ]
+ ]
+ },
+ {
+ "input": "&Ropf",
+ "description": "Bad named entity: Ropf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Ropf"
+ ]
+ ]
+ },
+ {
+ "input": "&Ropf;",
+ "description": "Named entity: Ropf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u211d"
+ ]
+ ]
+ },
+ {
+ "input": "&RoundImplies",
+ "description": "Bad named entity: RoundImplies without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&RoundImplies"
+ ]
+ ]
+ },
+ {
+ "input": "&RoundImplies;",
+ "description": "Named entity: RoundImplies; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2970"
+ ]
+ ]
+ },
+ {
+ "input": "&Rrightarrow",
+ "description": "Bad named entity: Rrightarrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Rrightarrow"
+ ]
+ ]
+ },
+ {
+ "input": "&Rrightarrow;",
+ "description": "Named entity: Rrightarrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21db"
+ ]
+ ]
+ },
+ {
+ "input": "&Rscr",
+ "description": "Bad named entity: Rscr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Rscr"
+ ]
+ ]
+ },
+ {
+ "input": "&Rscr;",
+ "description": "Named entity: Rscr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u211b"
+ ]
+ ]
+ },
+ {
+ "input": "&Rsh",
+ "description": "Bad named entity: Rsh without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Rsh"
+ ]
+ ]
+ },
+ {
+ "input": "&Rsh;",
+ "description": "Named entity: Rsh; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21b1"
+ ]
+ ]
+ },
+ {
+ "input": "&RuleDelayed",
+ "description": "Bad named entity: RuleDelayed without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&RuleDelayed"
+ ]
+ ]
+ },
+ {
+ "input": "&RuleDelayed;",
+ "description": "Named entity: RuleDelayed; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u29f4"
+ ]
+ ]
+ },
+ {
+ "input": "&SHCHcy",
+ "description": "Bad named entity: SHCHcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&SHCHcy"
+ ]
+ ]
+ },
+ {
+ "input": "&SHCHcy;",
+ "description": "Named entity: SHCHcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0429"
+ ]
+ ]
+ },
+ {
+ "input": "&SHcy",
+ "description": "Bad named entity: SHcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&SHcy"
+ ]
+ ]
+ },
+ {
+ "input": "&SHcy;",
+ "description": "Named entity: SHcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0428"
+ ]
+ ]
+ },
+ {
+ "input": "&SOFTcy",
+ "description": "Bad named entity: SOFTcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&SOFTcy"
+ ]
+ ]
+ },
+ {
+ "input": "&SOFTcy;",
+ "description": "Named entity: SOFTcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u042c"
+ ]
+ ]
+ },
+ {
+ "input": "&Sacute",
+ "description": "Bad named entity: Sacute without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Sacute"
+ ]
+ ]
+ },
+ {
+ "input": "&Sacute;",
+ "description": "Named entity: Sacute; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u015a"
+ ]
+ ]
+ },
+ {
+ "input": "&Sc",
+ "description": "Bad named entity: Sc without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Sc"
+ ]
+ ]
+ },
+ {
+ "input": "&Sc;",
+ "description": "Named entity: Sc; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2abc"
+ ]
+ ]
+ },
+ {
+ "input": "&Scaron",
+ "description": "Bad named entity: Scaron without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Scaron"
+ ]
+ ]
+ },
+ {
+ "input": "&Scaron;",
+ "description": "Named entity: Scaron; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0160"
+ ]
+ ]
+ },
+ {
+ "input": "&Scedil",
+ "description": "Bad named entity: Scedil without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Scedil"
+ ]
+ ]
+ },
+ {
+ "input": "&Scedil;",
+ "description": "Named entity: Scedil; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u015e"
+ ]
+ ]
+ },
+ {
+ "input": "&Scirc",
+ "description": "Bad named entity: Scirc without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Scirc"
+ ]
+ ]
+ },
+ {
+ "input": "&Scirc;",
+ "description": "Named entity: Scirc; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u015c"
+ ]
+ ]
+ },
+ {
+ "input": "&Scy",
+ "description": "Bad named entity: Scy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Scy"
+ ]
+ ]
+ },
+ {
+ "input": "&Scy;",
+ "description": "Named entity: Scy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0421"
+ ]
+ ]
+ },
+ {
+ "input": "&Sfr",
+ "description": "Bad named entity: Sfr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Sfr"
+ ]
+ ]
+ },
+ {
+ "input": "&Sfr;",
+ "description": "Named entity: Sfr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd16"
+ ]
+ ]
+ },
+ {
+ "input": "&ShortDownArrow",
+ "description": "Bad named entity: ShortDownArrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ShortDownArrow"
+ ]
+ ]
+ },
+ {
+ "input": "&ShortDownArrow;",
+ "description": "Named entity: ShortDownArrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2193"
+ ]
+ ]
+ },
+ {
+ "input": "&ShortLeftArrow",
+ "description": "Bad named entity: ShortLeftArrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ShortLeftArrow"
+ ]
+ ]
+ },
+ {
+ "input": "&ShortLeftArrow;",
+ "description": "Named entity: ShortLeftArrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2190"
+ ]
+ ]
+ },
+ {
+ "input": "&ShortRightArrow",
+ "description": "Bad named entity: ShortRightArrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ShortRightArrow"
+ ]
+ ]
+ },
+ {
+ "input": "&ShortRightArrow;",
+ "description": "Named entity: ShortRightArrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2192"
+ ]
+ ]
+ },
+ {
+ "input": "&ShortUpArrow",
+ "description": "Bad named entity: ShortUpArrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ShortUpArrow"
+ ]
+ ]
+ },
+ {
+ "input": "&ShortUpArrow;",
+ "description": "Named entity: ShortUpArrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2191"
+ ]
+ ]
+ },
+ {
+ "input": "&Sigma",
+ "description": "Bad named entity: Sigma without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Sigma"
+ ]
+ ]
+ },
+ {
+ "input": "&Sigma;",
+ "description": "Named entity: Sigma; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03a3"
+ ]
+ ]
+ },
+ {
+ "input": "&SmallCircle",
+ "description": "Bad named entity: SmallCircle without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&SmallCircle"
+ ]
+ ]
+ },
+ {
+ "input": "&SmallCircle;",
+ "description": "Named entity: SmallCircle; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2218"
+ ]
+ ]
+ },
+ {
+ "input": "&Sopf",
+ "description": "Bad named entity: Sopf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Sopf"
+ ]
+ ]
+ },
+ {
+ "input": "&Sopf;",
+ "description": "Named entity: Sopf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd4a"
+ ]
+ ]
+ },
+ {
+ "input": "&Sqrt",
+ "description": "Bad named entity: Sqrt without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Sqrt"
+ ]
+ ]
+ },
+ {
+ "input": "&Sqrt;",
+ "description": "Named entity: Sqrt; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u221a"
+ ]
+ ]
+ },
+ {
+ "input": "&Square",
+ "description": "Bad named entity: Square without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Square"
+ ]
+ ]
+ },
+ {
+ "input": "&Square;",
+ "description": "Named entity: Square; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u25a1"
+ ]
+ ]
+ },
+ {
+ "input": "&SquareIntersection",
+ "description": "Bad named entity: SquareIntersection without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&SquareIntersection"
+ ]
+ ]
+ },
+ {
+ "input": "&SquareIntersection;",
+ "description": "Named entity: SquareIntersection; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2293"
+ ]
+ ]
+ },
+ {
+ "input": "&SquareSubset",
+ "description": "Bad named entity: SquareSubset without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&SquareSubset"
+ ]
+ ]
+ },
+ {
+ "input": "&SquareSubset;",
+ "description": "Named entity: SquareSubset; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u228f"
+ ]
+ ]
+ },
+ {
+ "input": "&SquareSubsetEqual",
+ "description": "Bad named entity: SquareSubsetEqual without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&SquareSubsetEqual"
+ ]
+ ]
+ },
+ {
+ "input": "&SquareSubsetEqual;",
+ "description": "Named entity: SquareSubsetEqual; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2291"
+ ]
+ ]
+ },
+ {
+ "input": "&SquareSuperset",
+ "description": "Bad named entity: SquareSuperset without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&SquareSuperset"
+ ]
+ ]
+ },
+ {
+ "input": "&SquareSuperset;",
+ "description": "Named entity: SquareSuperset; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2290"
+ ]
+ ]
+ },
+ {
+ "input": "&SquareSupersetEqual",
+ "description": "Bad named entity: SquareSupersetEqual without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&SquareSupersetEqual"
+ ]
+ ]
+ },
+ {
+ "input": "&SquareSupersetEqual;",
+ "description": "Named entity: SquareSupersetEqual; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2292"
+ ]
+ ]
+ },
+ {
+ "input": "&SquareUnion",
+ "description": "Bad named entity: SquareUnion without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&SquareUnion"
+ ]
+ ]
+ },
+ {
+ "input": "&SquareUnion;",
+ "description": "Named entity: SquareUnion; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2294"
+ ]
+ ]
+ },
+ {
+ "input": "&Sscr",
+ "description": "Bad named entity: Sscr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Sscr"
+ ]
+ ]
+ },
+ {
+ "input": "&Sscr;",
+ "description": "Named entity: Sscr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udcae"
+ ]
+ ]
+ },
+ {
+ "input": "&Star",
+ "description": "Bad named entity: Star without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Star"
+ ]
+ ]
+ },
+ {
+ "input": "&Star;",
+ "description": "Named entity: Star; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22c6"
+ ]
+ ]
+ },
+ {
+ "input": "&Sub",
+ "description": "Bad named entity: Sub without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Sub"
+ ]
+ ]
+ },
+ {
+ "input": "&Sub;",
+ "description": "Named entity: Sub; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22d0"
+ ]
+ ]
+ },
+ {
+ "input": "&Subset",
+ "description": "Bad named entity: Subset without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Subset"
+ ]
+ ]
+ },
+ {
+ "input": "&Subset;",
+ "description": "Named entity: Subset; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22d0"
+ ]
+ ]
+ },
+ {
+ "input": "&SubsetEqual",
+ "description": "Bad named entity: SubsetEqual without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&SubsetEqual"
+ ]
+ ]
+ },
+ {
+ "input": "&SubsetEqual;",
+ "description": "Named entity: SubsetEqual; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2286"
+ ]
+ ]
+ },
+ {
+ "input": "&Succeeds",
+ "description": "Bad named entity: Succeeds without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Succeeds"
+ ]
+ ]
+ },
+ {
+ "input": "&Succeeds;",
+ "description": "Named entity: Succeeds; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u227b"
+ ]
+ ]
+ },
+ {
+ "input": "&SucceedsEqual",
+ "description": "Bad named entity: SucceedsEqual without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&SucceedsEqual"
+ ]
+ ]
+ },
+ {
+ "input": "&SucceedsEqual;",
+ "description": "Named entity: SucceedsEqual; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2ab0"
+ ]
+ ]
+ },
+ {
+ "input": "&SucceedsSlantEqual",
+ "description": "Bad named entity: SucceedsSlantEqual without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&SucceedsSlantEqual"
+ ]
+ ]
+ },
+ {
+ "input": "&SucceedsSlantEqual;",
+ "description": "Named entity: SucceedsSlantEqual; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u227d"
+ ]
+ ]
+ },
+ {
+ "input": "&SucceedsTilde",
+ "description": "Bad named entity: SucceedsTilde without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&SucceedsTilde"
+ ]
+ ]
+ },
+ {
+ "input": "&SucceedsTilde;",
+ "description": "Named entity: SucceedsTilde; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u227f"
+ ]
+ ]
+ },
+ {
+ "input": "&SuchThat",
+ "description": "Bad named entity: SuchThat without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&SuchThat"
+ ]
+ ]
+ },
+ {
+ "input": "&SuchThat;",
+ "description": "Named entity: SuchThat; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u220b"
+ ]
+ ]
+ },
+ {
+ "input": "&Sum",
+ "description": "Bad named entity: Sum without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Sum"
+ ]
+ ]
+ },
+ {
+ "input": "&Sum;",
+ "description": "Named entity: Sum; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2211"
+ ]
+ ]
+ },
+ {
+ "input": "&Sup",
+ "description": "Bad named entity: Sup without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Sup"
+ ]
+ ]
+ },
+ {
+ "input": "&Sup;",
+ "description": "Named entity: Sup; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22d1"
+ ]
+ ]
+ },
+ {
+ "input": "&Superset",
+ "description": "Bad named entity: Superset without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Superset"
+ ]
+ ]
+ },
+ {
+ "input": "&Superset;",
+ "description": "Named entity: Superset; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2283"
+ ]
+ ]
+ },
+ {
+ "input": "&SupersetEqual",
+ "description": "Bad named entity: SupersetEqual without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&SupersetEqual"
+ ]
+ ]
+ },
+ {
+ "input": "&SupersetEqual;",
+ "description": "Named entity: SupersetEqual; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2287"
+ ]
+ ]
+ },
+ {
+ "input": "&Supset",
+ "description": "Bad named entity: Supset without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Supset"
+ ]
+ ]
+ },
+ {
+ "input": "&Supset;",
+ "description": "Named entity: Supset; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22d1"
+ ]
+ ]
+ },
+ {
+ "input": "&THORN",
+ "description": "Named entity: THORN without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00de"
+ ]
+ ]
+ },
+ {
+ "input": "&THORN;",
+ "description": "Named entity: THORN; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00de"
+ ]
+ ]
+ },
+ {
+ "input": "&TRADE",
+ "description": "Bad named entity: TRADE without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&TRADE"
+ ]
+ ]
+ },
+ {
+ "input": "&TRADE;",
+ "description": "Named entity: TRADE; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2122"
+ ]
+ ]
+ },
+ {
+ "input": "&TSHcy",
+ "description": "Bad named entity: TSHcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&TSHcy"
+ ]
+ ]
+ },
+ {
+ "input": "&TSHcy;",
+ "description": "Named entity: TSHcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u040b"
+ ]
+ ]
+ },
+ {
+ "input": "&TScy",
+ "description": "Bad named entity: TScy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&TScy"
+ ]
+ ]
+ },
+ {
+ "input": "&TScy;",
+ "description": "Named entity: TScy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0426"
+ ]
+ ]
+ },
+ {
+ "input": "&Tab",
+ "description": "Bad named entity: Tab without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Tab"
+ ]
+ ]
+ },
+ {
+ "input": "&Tab;",
+ "description": "Named entity: Tab; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\t"
+ ]
+ ]
+ },
+ {
+ "input": "&Tau",
+ "description": "Bad named entity: Tau without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Tau"
+ ]
+ ]
+ },
+ {
+ "input": "&Tau;",
+ "description": "Named entity: Tau; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03a4"
+ ]
+ ]
+ },
+ {
+ "input": "&Tcaron",
+ "description": "Bad named entity: Tcaron without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Tcaron"
+ ]
+ ]
+ },
+ {
+ "input": "&Tcaron;",
+ "description": "Named entity: Tcaron; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0164"
+ ]
+ ]
+ },
+ {
+ "input": "&Tcedil",
+ "description": "Bad named entity: Tcedil without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Tcedil"
+ ]
+ ]
+ },
+ {
+ "input": "&Tcedil;",
+ "description": "Named entity: Tcedil; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0162"
+ ]
+ ]
+ },
+ {
+ "input": "&Tcy",
+ "description": "Bad named entity: Tcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Tcy"
+ ]
+ ]
+ },
+ {
+ "input": "&Tcy;",
+ "description": "Named entity: Tcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0422"
+ ]
+ ]
+ },
+ {
+ "input": "&Tfr",
+ "description": "Bad named entity: Tfr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Tfr"
+ ]
+ ]
+ },
+ {
+ "input": "&Tfr;",
+ "description": "Named entity: Tfr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd17"
+ ]
+ ]
+ },
+ {
+ "input": "&Therefore",
+ "description": "Bad named entity: Therefore without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Therefore"
+ ]
+ ]
+ },
+ {
+ "input": "&Therefore;",
+ "description": "Named entity: Therefore; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2234"
+ ]
+ ]
+ },
+ {
+ "input": "&Theta",
+ "description": "Bad named entity: Theta without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Theta"
+ ]
+ ]
+ },
+ {
+ "input": "&Theta;",
+ "description": "Named entity: Theta; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0398"
+ ]
+ ]
+ },
+ {
+ "input": "&ThickSpace",
+ "description": "Bad named entity: ThickSpace without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ThickSpace"
+ ]
+ ]
+ },
+ {
+ "input": "&ThickSpace;",
+ "description": "Named entity: ThickSpace; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u205f\u200a"
+ ]
+ ]
+ },
+ {
+ "input": "&ThinSpace",
+ "description": "Bad named entity: ThinSpace without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ThinSpace"
+ ]
+ ]
+ },
+ {
+ "input": "&ThinSpace;",
+ "description": "Named entity: ThinSpace; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2009"
+ ]
+ ]
+ },
+ {
+ "input": "&Tilde",
+ "description": "Bad named entity: Tilde without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Tilde"
+ ]
+ ]
+ },
+ {
+ "input": "&Tilde;",
+ "description": "Named entity: Tilde; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u223c"
+ ]
+ ]
+ },
+ {
+ "input": "&TildeEqual",
+ "description": "Bad named entity: TildeEqual without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&TildeEqual"
+ ]
+ ]
+ },
+ {
+ "input": "&TildeEqual;",
+ "description": "Named entity: TildeEqual; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2243"
+ ]
+ ]
+ },
+ {
+ "input": "&TildeFullEqual",
+ "description": "Bad named entity: TildeFullEqual without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&TildeFullEqual"
+ ]
+ ]
+ },
+ {
+ "input": "&TildeFullEqual;",
+ "description": "Named entity: TildeFullEqual; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2245"
+ ]
+ ]
+ },
+ {
+ "input": "&TildeTilde",
+ "description": "Bad named entity: TildeTilde without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&TildeTilde"
+ ]
+ ]
+ },
+ {
+ "input": "&TildeTilde;",
+ "description": "Named entity: TildeTilde; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2248"
+ ]
+ ]
+ },
+ {
+ "input": "&Topf",
+ "description": "Bad named entity: Topf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Topf"
+ ]
+ ]
+ },
+ {
+ "input": "&Topf;",
+ "description": "Named entity: Topf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd4b"
+ ]
+ ]
+ },
+ {
+ "input": "&TripleDot",
+ "description": "Bad named entity: TripleDot without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&TripleDot"
+ ]
+ ]
+ },
+ {
+ "input": "&TripleDot;",
+ "description": "Named entity: TripleDot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u20db"
+ ]
+ ]
+ },
+ {
+ "input": "&Tscr",
+ "description": "Bad named entity: Tscr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Tscr"
+ ]
+ ]
+ },
+ {
+ "input": "&Tscr;",
+ "description": "Named entity: Tscr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udcaf"
+ ]
+ ]
+ },
+ {
+ "input": "&Tstrok",
+ "description": "Bad named entity: Tstrok without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Tstrok"
+ ]
+ ]
+ },
+ {
+ "input": "&Tstrok;",
+ "description": "Named entity: Tstrok; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0166"
+ ]
+ ]
+ },
+ {
+ "input": "&Uacute",
+ "description": "Named entity: Uacute without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00da"
+ ]
+ ]
+ },
+ {
+ "input": "&Uacute;",
+ "description": "Named entity: Uacute; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00da"
+ ]
+ ]
+ },
+ {
+ "input": "&Uarr",
+ "description": "Bad named entity: Uarr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Uarr"
+ ]
+ ]
+ },
+ {
+ "input": "&Uarr;",
+ "description": "Named entity: Uarr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u219f"
+ ]
+ ]
+ },
+ {
+ "input": "&Uarrocir",
+ "description": "Bad named entity: Uarrocir without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Uarrocir"
+ ]
+ ]
+ },
+ {
+ "input": "&Uarrocir;",
+ "description": "Named entity: Uarrocir; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2949"
+ ]
+ ]
+ },
+ {
+ "input": "&Ubrcy",
+ "description": "Bad named entity: Ubrcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Ubrcy"
+ ]
+ ]
+ },
+ {
+ "input": "&Ubrcy;",
+ "description": "Named entity: Ubrcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u040e"
+ ]
+ ]
+ },
+ {
+ "input": "&Ubreve",
+ "description": "Bad named entity: Ubreve without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Ubreve"
+ ]
+ ]
+ },
+ {
+ "input": "&Ubreve;",
+ "description": "Named entity: Ubreve; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u016c"
+ ]
+ ]
+ },
+ {
+ "input": "&Ucirc",
+ "description": "Named entity: Ucirc without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00db"
+ ]
+ ]
+ },
+ {
+ "input": "&Ucirc;",
+ "description": "Named entity: Ucirc; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00db"
+ ]
+ ]
+ },
+ {
+ "input": "&Ucy",
+ "description": "Bad named entity: Ucy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Ucy"
+ ]
+ ]
+ },
+ {
+ "input": "&Ucy;",
+ "description": "Named entity: Ucy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0423"
+ ]
+ ]
+ },
+ {
+ "input": "&Udblac",
+ "description": "Bad named entity: Udblac without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Udblac"
+ ]
+ ]
+ },
+ {
+ "input": "&Udblac;",
+ "description": "Named entity: Udblac; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0170"
+ ]
+ ]
+ },
+ {
+ "input": "&Ufr",
+ "description": "Bad named entity: Ufr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Ufr"
+ ]
+ ]
+ },
+ {
+ "input": "&Ufr;",
+ "description": "Named entity: Ufr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd18"
+ ]
+ ]
+ },
+ {
+ "input": "&Ugrave",
+ "description": "Named entity: Ugrave without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00d9"
+ ]
+ ]
+ },
+ {
+ "input": "&Ugrave;",
+ "description": "Named entity: Ugrave; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00d9"
+ ]
+ ]
+ },
+ {
+ "input": "&Umacr",
+ "description": "Bad named entity: Umacr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Umacr"
+ ]
+ ]
+ },
+ {
+ "input": "&Umacr;",
+ "description": "Named entity: Umacr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u016a"
+ ]
+ ]
+ },
+ {
+ "input": "&UnderBar",
+ "description": "Bad named entity: UnderBar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&UnderBar"
+ ]
+ ]
+ },
+ {
+ "input": "&UnderBar;",
+ "description": "Named entity: UnderBar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "_"
+ ]
+ ]
+ },
+ {
+ "input": "&UnderBrace",
+ "description": "Bad named entity: UnderBrace without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&UnderBrace"
+ ]
+ ]
+ },
+ {
+ "input": "&UnderBrace;",
+ "description": "Named entity: UnderBrace; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u23df"
+ ]
+ ]
+ },
+ {
+ "input": "&UnderBracket",
+ "description": "Bad named entity: UnderBracket without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&UnderBracket"
+ ]
+ ]
+ },
+ {
+ "input": "&UnderBracket;",
+ "description": "Named entity: UnderBracket; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u23b5"
+ ]
+ ]
+ },
+ {
+ "input": "&UnderParenthesis",
+ "description": "Bad named entity: UnderParenthesis without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&UnderParenthesis"
+ ]
+ ]
+ },
+ {
+ "input": "&UnderParenthesis;",
+ "description": "Named entity: UnderParenthesis; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u23dd"
+ ]
+ ]
+ },
+ {
+ "input": "&Union",
+ "description": "Bad named entity: Union without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Union"
+ ]
+ ]
+ },
+ {
+ "input": "&Union;",
+ "description": "Named entity: Union; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22c3"
+ ]
+ ]
+ },
+ {
+ "input": "&UnionPlus",
+ "description": "Bad named entity: UnionPlus without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&UnionPlus"
+ ]
+ ]
+ },
+ {
+ "input": "&UnionPlus;",
+ "description": "Named entity: UnionPlus; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u228e"
+ ]
+ ]
+ },
+ {
+ "input": "&Uogon",
+ "description": "Bad named entity: Uogon without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Uogon"
+ ]
+ ]
+ },
+ {
+ "input": "&Uogon;",
+ "description": "Named entity: Uogon; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0172"
+ ]
+ ]
+ },
+ {
+ "input": "&Uopf",
+ "description": "Bad named entity: Uopf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Uopf"
+ ]
+ ]
+ },
+ {
+ "input": "&Uopf;",
+ "description": "Named entity: Uopf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd4c"
+ ]
+ ]
+ },
+ {
+ "input": "&UpArrow",
+ "description": "Bad named entity: UpArrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&UpArrow"
+ ]
+ ]
+ },
+ {
+ "input": "&UpArrow;",
+ "description": "Named entity: UpArrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2191"
+ ]
+ ]
+ },
+ {
+ "input": "&UpArrowBar",
+ "description": "Bad named entity: UpArrowBar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&UpArrowBar"
+ ]
+ ]
+ },
+ {
+ "input": "&UpArrowBar;",
+ "description": "Named entity: UpArrowBar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2912"
+ ]
+ ]
+ },
+ {
+ "input": "&UpArrowDownArrow",
+ "description": "Bad named entity: UpArrowDownArrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&UpArrowDownArrow"
+ ]
+ ]
+ },
+ {
+ "input": "&UpArrowDownArrow;",
+ "description": "Named entity: UpArrowDownArrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21c5"
+ ]
+ ]
+ },
+ {
+ "input": "&UpDownArrow",
+ "description": "Bad named entity: UpDownArrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&UpDownArrow"
+ ]
+ ]
+ },
+ {
+ "input": "&UpDownArrow;",
+ "description": "Named entity: UpDownArrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2195"
+ ]
+ ]
+ },
+ {
+ "input": "&UpEquilibrium",
+ "description": "Bad named entity: UpEquilibrium without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&UpEquilibrium"
+ ]
+ ]
+ },
+ {
+ "input": "&UpEquilibrium;",
+ "description": "Named entity: UpEquilibrium; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u296e"
+ ]
+ ]
+ },
+ {
+ "input": "&UpTee",
+ "description": "Bad named entity: UpTee without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&UpTee"
+ ]
+ ]
+ },
+ {
+ "input": "&UpTee;",
+ "description": "Named entity: UpTee; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22a5"
+ ]
+ ]
+ },
+ {
+ "input": "&UpTeeArrow",
+ "description": "Bad named entity: UpTeeArrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&UpTeeArrow"
+ ]
+ ]
+ },
+ {
+ "input": "&UpTeeArrow;",
+ "description": "Named entity: UpTeeArrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21a5"
+ ]
+ ]
+ },
+ {
+ "input": "&Uparrow",
+ "description": "Bad named entity: Uparrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Uparrow"
+ ]
+ ]
+ },
+ {
+ "input": "&Uparrow;",
+ "description": "Named entity: Uparrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21d1"
+ ]
+ ]
+ },
+ {
+ "input": "&Updownarrow",
+ "description": "Bad named entity: Updownarrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Updownarrow"
+ ]
+ ]
+ },
+ {
+ "input": "&Updownarrow;",
+ "description": "Named entity: Updownarrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21d5"
+ ]
+ ]
+ },
+ {
+ "input": "&UpperLeftArrow",
+ "description": "Bad named entity: UpperLeftArrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&UpperLeftArrow"
+ ]
+ ]
+ },
+ {
+ "input": "&UpperLeftArrow;",
+ "description": "Named entity: UpperLeftArrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2196"
+ ]
+ ]
+ },
+ {
+ "input": "&UpperRightArrow",
+ "description": "Bad named entity: UpperRightArrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&UpperRightArrow"
+ ]
+ ]
+ },
+ {
+ "input": "&UpperRightArrow;",
+ "description": "Named entity: UpperRightArrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2197"
+ ]
+ ]
+ },
+ {
+ "input": "&Upsi",
+ "description": "Bad named entity: Upsi without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Upsi"
+ ]
+ ]
+ },
+ {
+ "input": "&Upsi;",
+ "description": "Named entity: Upsi; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03d2"
+ ]
+ ]
+ },
+ {
+ "input": "&Upsilon",
+ "description": "Bad named entity: Upsilon without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Upsilon"
+ ]
+ ]
+ },
+ {
+ "input": "&Upsilon;",
+ "description": "Named entity: Upsilon; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03a5"
+ ]
+ ]
+ },
+ {
+ "input": "&Uring",
+ "description": "Bad named entity: Uring without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Uring"
+ ]
+ ]
+ },
+ {
+ "input": "&Uring;",
+ "description": "Named entity: Uring; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u016e"
+ ]
+ ]
+ },
+ {
+ "input": "&Uscr",
+ "description": "Bad named entity: Uscr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Uscr"
+ ]
+ ]
+ },
+ {
+ "input": "&Uscr;",
+ "description": "Named entity: Uscr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udcb0"
+ ]
+ ]
+ },
+ {
+ "input": "&Utilde",
+ "description": "Bad named entity: Utilde without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Utilde"
+ ]
+ ]
+ },
+ {
+ "input": "&Utilde;",
+ "description": "Named entity: Utilde; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0168"
+ ]
+ ]
+ },
+ {
+ "input": "&Uuml",
+ "description": "Named entity: Uuml without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00dc"
+ ]
+ ]
+ },
+ {
+ "input": "&Uuml;",
+ "description": "Named entity: Uuml; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00dc"
+ ]
+ ]
+ },
+ {
+ "input": "&VDash",
+ "description": "Bad named entity: VDash without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&VDash"
+ ]
+ ]
+ },
+ {
+ "input": "&VDash;",
+ "description": "Named entity: VDash; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22ab"
+ ]
+ ]
+ },
+ {
+ "input": "&Vbar",
+ "description": "Bad named entity: Vbar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Vbar"
+ ]
+ ]
+ },
+ {
+ "input": "&Vbar;",
+ "description": "Named entity: Vbar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2aeb"
+ ]
+ ]
+ },
+ {
+ "input": "&Vcy",
+ "description": "Bad named entity: Vcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Vcy"
+ ]
+ ]
+ },
+ {
+ "input": "&Vcy;",
+ "description": "Named entity: Vcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0412"
+ ]
+ ]
+ },
+ {
+ "input": "&Vdash",
+ "description": "Bad named entity: Vdash without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Vdash"
+ ]
+ ]
+ },
+ {
+ "input": "&Vdash;",
+ "description": "Named entity: Vdash; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22a9"
+ ]
+ ]
+ },
+ {
+ "input": "&Vdashl",
+ "description": "Bad named entity: Vdashl without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Vdashl"
+ ]
+ ]
+ },
+ {
+ "input": "&Vdashl;",
+ "description": "Named entity: Vdashl; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2ae6"
+ ]
+ ]
+ },
+ {
+ "input": "&Vee",
+ "description": "Bad named entity: Vee without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Vee"
+ ]
+ ]
+ },
+ {
+ "input": "&Vee;",
+ "description": "Named entity: Vee; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22c1"
+ ]
+ ]
+ },
+ {
+ "input": "&Verbar",
+ "description": "Bad named entity: Verbar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Verbar"
+ ]
+ ]
+ },
+ {
+ "input": "&Verbar;",
+ "description": "Named entity: Verbar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2016"
+ ]
+ ]
+ },
+ {
+ "input": "&Vert",
+ "description": "Bad named entity: Vert without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Vert"
+ ]
+ ]
+ },
+ {
+ "input": "&Vert;",
+ "description": "Named entity: Vert; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2016"
+ ]
+ ]
+ },
+ {
+ "input": "&VerticalBar",
+ "description": "Bad named entity: VerticalBar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&VerticalBar"
+ ]
+ ]
+ },
+ {
+ "input": "&VerticalBar;",
+ "description": "Named entity: VerticalBar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2223"
+ ]
+ ]
+ },
+ {
+ "input": "&VerticalLine",
+ "description": "Bad named entity: VerticalLine without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&VerticalLine"
+ ]
+ ]
+ },
+ {
+ "input": "&VerticalLine;",
+ "description": "Named entity: VerticalLine; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "|"
+ ]
+ ]
+ },
+ {
+ "input": "&VerticalSeparator",
+ "description": "Bad named entity: VerticalSeparator without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&VerticalSeparator"
+ ]
+ ]
+ },
+ {
+ "input": "&VerticalSeparator;",
+ "description": "Named entity: VerticalSeparator; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2758"
+ ]
+ ]
+ },
+ {
+ "input": "&VerticalTilde",
+ "description": "Bad named entity: VerticalTilde without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&VerticalTilde"
+ ]
+ ]
+ },
+ {
+ "input": "&VerticalTilde;",
+ "description": "Named entity: VerticalTilde; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2240"
+ ]
+ ]
+ },
+ {
+ "input": "&VeryThinSpace",
+ "description": "Bad named entity: VeryThinSpace without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&VeryThinSpace"
+ ]
+ ]
+ },
+ {
+ "input": "&VeryThinSpace;",
+ "description": "Named entity: VeryThinSpace; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u200a"
+ ]
+ ]
+ },
+ {
+ "input": "&Vfr",
+ "description": "Bad named entity: Vfr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Vfr"
+ ]
+ ]
+ },
+ {
+ "input": "&Vfr;",
+ "description": "Named entity: Vfr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd19"
+ ]
+ ]
+ },
+ {
+ "input": "&Vopf",
+ "description": "Bad named entity: Vopf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Vopf"
+ ]
+ ]
+ },
+ {
+ "input": "&Vopf;",
+ "description": "Named entity: Vopf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd4d"
+ ]
+ ]
+ },
+ {
+ "input": "&Vscr",
+ "description": "Bad named entity: Vscr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Vscr"
+ ]
+ ]
+ },
+ {
+ "input": "&Vscr;",
+ "description": "Named entity: Vscr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udcb1"
+ ]
+ ]
+ },
+ {
+ "input": "&Vvdash",
+ "description": "Bad named entity: Vvdash without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Vvdash"
+ ]
+ ]
+ },
+ {
+ "input": "&Vvdash;",
+ "description": "Named entity: Vvdash; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22aa"
+ ]
+ ]
+ },
+ {
+ "input": "&Wcirc",
+ "description": "Bad named entity: Wcirc without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Wcirc"
+ ]
+ ]
+ },
+ {
+ "input": "&Wcirc;",
+ "description": "Named entity: Wcirc; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0174"
+ ]
+ ]
+ },
+ {
+ "input": "&Wedge",
+ "description": "Bad named entity: Wedge without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Wedge"
+ ]
+ ]
+ },
+ {
+ "input": "&Wedge;",
+ "description": "Named entity: Wedge; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22c0"
+ ]
+ ]
+ },
+ {
+ "input": "&Wfr",
+ "description": "Bad named entity: Wfr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Wfr"
+ ]
+ ]
+ },
+ {
+ "input": "&Wfr;",
+ "description": "Named entity: Wfr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd1a"
+ ]
+ ]
+ },
+ {
+ "input": "&Wopf",
+ "description": "Bad named entity: Wopf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Wopf"
+ ]
+ ]
+ },
+ {
+ "input": "&Wopf;",
+ "description": "Named entity: Wopf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd4e"
+ ]
+ ]
+ },
+ {
+ "input": "&Wscr",
+ "description": "Bad named entity: Wscr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Wscr"
+ ]
+ ]
+ },
+ {
+ "input": "&Wscr;",
+ "description": "Named entity: Wscr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udcb2"
+ ]
+ ]
+ },
+ {
+ "input": "&Xfr",
+ "description": "Bad named entity: Xfr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Xfr"
+ ]
+ ]
+ },
+ {
+ "input": "&Xfr;",
+ "description": "Named entity: Xfr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd1b"
+ ]
+ ]
+ },
+ {
+ "input": "&Xi",
+ "description": "Bad named entity: Xi without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Xi"
+ ]
+ ]
+ },
+ {
+ "input": "&Xi;",
+ "description": "Named entity: Xi; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u039e"
+ ]
+ ]
+ },
+ {
+ "input": "&Xopf",
+ "description": "Bad named entity: Xopf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Xopf"
+ ]
+ ]
+ },
+ {
+ "input": "&Xopf;",
+ "description": "Named entity: Xopf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd4f"
+ ]
+ ]
+ },
+ {
+ "input": "&Xscr",
+ "description": "Bad named entity: Xscr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Xscr"
+ ]
+ ]
+ },
+ {
+ "input": "&Xscr;",
+ "description": "Named entity: Xscr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udcb3"
+ ]
+ ]
+ },
+ {
+ "input": "&YAcy",
+ "description": "Bad named entity: YAcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&YAcy"
+ ]
+ ]
+ },
+ {
+ "input": "&YAcy;",
+ "description": "Named entity: YAcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u042f"
+ ]
+ ]
+ },
+ {
+ "input": "&YIcy",
+ "description": "Bad named entity: YIcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&YIcy"
+ ]
+ ]
+ },
+ {
+ "input": "&YIcy;",
+ "description": "Named entity: YIcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0407"
+ ]
+ ]
+ },
+ {
+ "input": "&YUcy",
+ "description": "Bad named entity: YUcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&YUcy"
+ ]
+ ]
+ },
+ {
+ "input": "&YUcy;",
+ "description": "Named entity: YUcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u042e"
+ ]
+ ]
+ },
+ {
+ "input": "&Yacute",
+ "description": "Named entity: Yacute without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00dd"
+ ]
+ ]
+ },
+ {
+ "input": "&Yacute;",
+ "description": "Named entity: Yacute; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00dd"
+ ]
+ ]
+ },
+ {
+ "input": "&Ycirc",
+ "description": "Bad named entity: Ycirc without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Ycirc"
+ ]
+ ]
+ },
+ {
+ "input": "&Ycirc;",
+ "description": "Named entity: Ycirc; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0176"
+ ]
+ ]
+ },
+ {
+ "input": "&Ycy",
+ "description": "Bad named entity: Ycy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Ycy"
+ ]
+ ]
+ },
+ {
+ "input": "&Ycy;",
+ "description": "Named entity: Ycy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u042b"
+ ]
+ ]
+ },
+ {
+ "input": "&Yfr",
+ "description": "Bad named entity: Yfr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Yfr"
+ ]
+ ]
+ },
+ {
+ "input": "&Yfr;",
+ "description": "Named entity: Yfr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd1c"
+ ]
+ ]
+ },
+ {
+ "input": "&Yopf",
+ "description": "Bad named entity: Yopf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Yopf"
+ ]
+ ]
+ },
+ {
+ "input": "&Yopf;",
+ "description": "Named entity: Yopf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd50"
+ ]
+ ]
+ },
+ {
+ "input": "&Yscr",
+ "description": "Bad named entity: Yscr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Yscr"
+ ]
+ ]
+ },
+ {
+ "input": "&Yscr;",
+ "description": "Named entity: Yscr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udcb4"
+ ]
+ ]
+ },
+ {
+ "input": "&Yuml",
+ "description": "Bad named entity: Yuml without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Yuml"
+ ]
+ ]
+ },
+ {
+ "input": "&Yuml;",
+ "description": "Named entity: Yuml; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0178"
+ ]
+ ]
+ },
+ {
+ "input": "&ZHcy",
+ "description": "Bad named entity: ZHcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ZHcy"
+ ]
+ ]
+ },
+ {
+ "input": "&ZHcy;",
+ "description": "Named entity: ZHcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0416"
+ ]
+ ]
+ },
+ {
+ "input": "&Zacute",
+ "description": "Bad named entity: Zacute without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Zacute"
+ ]
+ ]
+ },
+ {
+ "input": "&Zacute;",
+ "description": "Named entity: Zacute; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0179"
+ ]
+ ]
+ },
+ {
+ "input": "&Zcaron",
+ "description": "Bad named entity: Zcaron without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Zcaron"
+ ]
+ ]
+ },
+ {
+ "input": "&Zcaron;",
+ "description": "Named entity: Zcaron; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u017d"
+ ]
+ ]
+ },
+ {
+ "input": "&Zcy",
+ "description": "Bad named entity: Zcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Zcy"
+ ]
+ ]
+ },
+ {
+ "input": "&Zcy;",
+ "description": "Named entity: Zcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0417"
+ ]
+ ]
+ },
+ {
+ "input": "&Zdot",
+ "description": "Bad named entity: Zdot without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Zdot"
+ ]
+ ]
+ },
+ {
+ "input": "&Zdot;",
+ "description": "Named entity: Zdot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u017b"
+ ]
+ ]
+ },
+ {
+ "input": "&ZeroWidthSpace",
+ "description": "Bad named entity: ZeroWidthSpace without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ZeroWidthSpace"
+ ]
+ ]
+ },
+ {
+ "input": "&ZeroWidthSpace;",
+ "description": "Named entity: ZeroWidthSpace; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u200b"
+ ]
+ ]
+ },
+ {
+ "input": "&Zeta",
+ "description": "Bad named entity: Zeta without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Zeta"
+ ]
+ ]
+ },
+ {
+ "input": "&Zeta;",
+ "description": "Named entity: Zeta; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0396"
+ ]
+ ]
+ },
+ {
+ "input": "&Zfr",
+ "description": "Bad named entity: Zfr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Zfr"
+ ]
+ ]
+ },
+ {
+ "input": "&Zfr;",
+ "description": "Named entity: Zfr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2128"
+ ]
+ ]
+ },
+ {
+ "input": "&Zopf",
+ "description": "Bad named entity: Zopf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Zopf"
+ ]
+ ]
+ },
+ {
+ "input": "&Zopf;",
+ "description": "Named entity: Zopf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2124"
+ ]
+ ]
+ },
+ {
+ "input": "&Zscr",
+ "description": "Bad named entity: Zscr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&Zscr"
+ ]
+ ]
+ },
+ {
+ "input": "&Zscr;",
+ "description": "Named entity: Zscr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udcb5"
+ ]
+ ]
+ },
+ {
+ "input": "&aacute",
+ "description": "Named entity: aacute without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00e1"
+ ]
+ ]
+ },
+ {
+ "input": "&aacute;",
+ "description": "Named entity: aacute; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00e1"
+ ]
+ ]
+ },
+ {
+ "input": "&abreve",
+ "description": "Bad named entity: abreve without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&abreve"
+ ]
+ ]
+ },
+ {
+ "input": "&abreve;",
+ "description": "Named entity: abreve; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0103"
+ ]
+ ]
+ },
+ {
+ "input": "&ac",
+ "description": "Bad named entity: ac without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ac"
+ ]
+ ]
+ },
+ {
+ "input": "&ac;",
+ "description": "Named entity: ac; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u223e"
+ ]
+ ]
+ },
+ {
+ "input": "&acE",
+ "description": "Bad named entity: acE without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&acE"
+ ]
+ ]
+ },
+ {
+ "input": "&acE;",
+ "description": "Named entity: acE; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u223e\u0333"
+ ]
+ ]
+ },
+ {
+ "input": "&acd",
+ "description": "Bad named entity: acd without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&acd"
+ ]
+ ]
+ },
+ {
+ "input": "&acd;",
+ "description": "Named entity: acd; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u223f"
+ ]
+ ]
+ },
+ {
+ "input": "&acirc",
+ "description": "Named entity: acirc without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00e2"
+ ]
+ ]
+ },
+ {
+ "input": "&acirc;",
+ "description": "Named entity: acirc; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00e2"
+ ]
+ ]
+ },
+ {
+ "input": "&acute",
+ "description": "Named entity: acute without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00b4"
+ ]
+ ]
+ },
+ {
+ "input": "&acute;",
+ "description": "Named entity: acute; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00b4"
+ ]
+ ]
+ },
+ {
+ "input": "&acy",
+ "description": "Bad named entity: acy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&acy"
+ ]
+ ]
+ },
+ {
+ "input": "&acy;",
+ "description": "Named entity: acy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0430"
+ ]
+ ]
+ },
+ {
+ "input": "&aelig",
+ "description": "Named entity: aelig without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00e6"
+ ]
+ ]
+ },
+ {
+ "input": "&aelig;",
+ "description": "Named entity: aelig; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00e6"
+ ]
+ ]
+ },
+ {
+ "input": "&af",
+ "description": "Bad named entity: af without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&af"
+ ]
+ ]
+ },
+ {
+ "input": "&af;",
+ "description": "Named entity: af; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2061"
+ ]
+ ]
+ },
+ {
+ "input": "&afr",
+ "description": "Bad named entity: afr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&afr"
+ ]
+ ]
+ },
+ {
+ "input": "&afr;",
+ "description": "Named entity: afr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd1e"
+ ]
+ ]
+ },
+ {
+ "input": "&agrave",
+ "description": "Named entity: agrave without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00e0"
+ ]
+ ]
+ },
+ {
+ "input": "&agrave;",
+ "description": "Named entity: agrave; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00e0"
+ ]
+ ]
+ },
+ {
+ "input": "&alefsym",
+ "description": "Bad named entity: alefsym without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&alefsym"
+ ]
+ ]
+ },
+ {
+ "input": "&alefsym;",
+ "description": "Named entity: alefsym; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2135"
+ ]
+ ]
+ },
+ {
+ "input": "&aleph",
+ "description": "Bad named entity: aleph without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&aleph"
+ ]
+ ]
+ },
+ {
+ "input": "&aleph;",
+ "description": "Named entity: aleph; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2135"
+ ]
+ ]
+ },
+ {
+ "input": "&alpha",
+ "description": "Bad named entity: alpha without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&alpha"
+ ]
+ ]
+ },
+ {
+ "input": "&alpha;",
+ "description": "Named entity: alpha; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03b1"
+ ]
+ ]
+ },
+ {
+ "input": "&amacr",
+ "description": "Bad named entity: amacr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&amacr"
+ ]
+ ]
+ },
+ {
+ "input": "&amacr;",
+ "description": "Named entity: amacr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0101"
+ ]
+ ]
+ },
+ {
+ "input": "&amalg",
+ "description": "Bad named entity: amalg without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&amalg"
+ ]
+ ]
+ },
+ {
+ "input": "&amalg;",
+ "description": "Named entity: amalg; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a3f"
+ ]
+ ]
+ },
+ {
+ "input": "&amp",
+ "description": "Named entity: amp without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "&"
+ ]
+ ]
+ },
+ {
+ "input": "&amp;",
+ "description": "Named entity: amp; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&"
+ ]
+ ]
+ },
+ {
+ "input": "&and",
+ "description": "Bad named entity: and without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&and"
+ ]
+ ]
+ },
+ {
+ "input": "&and;",
+ "description": "Named entity: and; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2227"
+ ]
+ ]
+ },
+ {
+ "input": "&andand",
+ "description": "Bad named entity: andand without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&andand"
+ ]
+ ]
+ },
+ {
+ "input": "&andand;",
+ "description": "Named entity: andand; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a55"
+ ]
+ ]
+ },
+ {
+ "input": "&andd",
+ "description": "Bad named entity: andd without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&andd"
+ ]
+ ]
+ },
+ {
+ "input": "&andd;",
+ "description": "Named entity: andd; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a5c"
+ ]
+ ]
+ },
+ {
+ "input": "&andslope",
+ "description": "Bad named entity: andslope without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&andslope"
+ ]
+ ]
+ },
+ {
+ "input": "&andslope;",
+ "description": "Named entity: andslope; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a58"
+ ]
+ ]
+ },
+ {
+ "input": "&andv",
+ "description": "Bad named entity: andv without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&andv"
+ ]
+ ]
+ },
+ {
+ "input": "&andv;",
+ "description": "Named entity: andv; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a5a"
+ ]
+ ]
+ },
+ {
+ "input": "&ang",
+ "description": "Bad named entity: ang without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ang"
+ ]
+ ]
+ },
+ {
+ "input": "&ang;",
+ "description": "Named entity: ang; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2220"
+ ]
+ ]
+ },
+ {
+ "input": "&ange",
+ "description": "Bad named entity: ange without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ange"
+ ]
+ ]
+ },
+ {
+ "input": "&ange;",
+ "description": "Named entity: ange; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u29a4"
+ ]
+ ]
+ },
+ {
+ "input": "&angle",
+ "description": "Bad named entity: angle without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&angle"
+ ]
+ ]
+ },
+ {
+ "input": "&angle;",
+ "description": "Named entity: angle; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2220"
+ ]
+ ]
+ },
+ {
+ "input": "&angmsd",
+ "description": "Bad named entity: angmsd without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&angmsd"
+ ]
+ ]
+ },
+ {
+ "input": "&angmsd;",
+ "description": "Named entity: angmsd; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2221"
+ ]
+ ]
+ },
+ {
+ "input": "&angmsdaa",
+ "description": "Bad named entity: angmsdaa without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&angmsdaa"
+ ]
+ ]
+ },
+ {
+ "input": "&angmsdaa;",
+ "description": "Named entity: angmsdaa; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u29a8"
+ ]
+ ]
+ },
+ {
+ "input": "&angmsdab",
+ "description": "Bad named entity: angmsdab without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&angmsdab"
+ ]
+ ]
+ },
+ {
+ "input": "&angmsdab;",
+ "description": "Named entity: angmsdab; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u29a9"
+ ]
+ ]
+ },
+ {
+ "input": "&angmsdac",
+ "description": "Bad named entity: angmsdac without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&angmsdac"
+ ]
+ ]
+ },
+ {
+ "input": "&angmsdac;",
+ "description": "Named entity: angmsdac; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u29aa"
+ ]
+ ]
+ },
+ {
+ "input": "&angmsdad",
+ "description": "Bad named entity: angmsdad without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&angmsdad"
+ ]
+ ]
+ },
+ {
+ "input": "&angmsdad;",
+ "description": "Named entity: angmsdad; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u29ab"
+ ]
+ ]
+ },
+ {
+ "input": "&angmsdae",
+ "description": "Bad named entity: angmsdae without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&angmsdae"
+ ]
+ ]
+ },
+ {
+ "input": "&angmsdae;",
+ "description": "Named entity: angmsdae; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u29ac"
+ ]
+ ]
+ },
+ {
+ "input": "&angmsdaf",
+ "description": "Bad named entity: angmsdaf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&angmsdaf"
+ ]
+ ]
+ },
+ {
+ "input": "&angmsdaf;",
+ "description": "Named entity: angmsdaf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u29ad"
+ ]
+ ]
+ },
+ {
+ "input": "&angmsdag",
+ "description": "Bad named entity: angmsdag without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&angmsdag"
+ ]
+ ]
+ },
+ {
+ "input": "&angmsdag;",
+ "description": "Named entity: angmsdag; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u29ae"
+ ]
+ ]
+ },
+ {
+ "input": "&angmsdah",
+ "description": "Bad named entity: angmsdah without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&angmsdah"
+ ]
+ ]
+ },
+ {
+ "input": "&angmsdah;",
+ "description": "Named entity: angmsdah; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u29af"
+ ]
+ ]
+ },
+ {
+ "input": "&angrt",
+ "description": "Bad named entity: angrt without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&angrt"
+ ]
+ ]
+ },
+ {
+ "input": "&angrt;",
+ "description": "Named entity: angrt; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u221f"
+ ]
+ ]
+ },
+ {
+ "input": "&angrtvb",
+ "description": "Bad named entity: angrtvb without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&angrtvb"
+ ]
+ ]
+ },
+ {
+ "input": "&angrtvb;",
+ "description": "Named entity: angrtvb; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22be"
+ ]
+ ]
+ },
+ {
+ "input": "&angrtvbd",
+ "description": "Bad named entity: angrtvbd without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&angrtvbd"
+ ]
+ ]
+ },
+ {
+ "input": "&angrtvbd;",
+ "description": "Named entity: angrtvbd; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u299d"
+ ]
+ ]
+ },
+ {
+ "input": "&angsph",
+ "description": "Bad named entity: angsph without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&angsph"
+ ]
+ ]
+ },
+ {
+ "input": "&angsph;",
+ "description": "Named entity: angsph; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2222"
+ ]
+ ]
+ },
+ {
+ "input": "&angst",
+ "description": "Bad named entity: angst without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&angst"
+ ]
+ ]
+ },
+ {
+ "input": "&angst;",
+ "description": "Named entity: angst; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00c5"
+ ]
+ ]
+ },
+ {
+ "input": "&angzarr",
+ "description": "Bad named entity: angzarr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&angzarr"
+ ]
+ ]
+ },
+ {
+ "input": "&angzarr;",
+ "description": "Named entity: angzarr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u237c"
+ ]
+ ]
+ },
+ {
+ "input": "&aogon",
+ "description": "Bad named entity: aogon without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&aogon"
+ ]
+ ]
+ },
+ {
+ "input": "&aogon;",
+ "description": "Named entity: aogon; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0105"
+ ]
+ ]
+ },
+ {
+ "input": "&aopf",
+ "description": "Bad named entity: aopf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&aopf"
+ ]
+ ]
+ },
+ {
+ "input": "&aopf;",
+ "description": "Named entity: aopf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd52"
+ ]
+ ]
+ },
+ {
+ "input": "&ap",
+ "description": "Bad named entity: ap without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ap"
+ ]
+ ]
+ },
+ {
+ "input": "&ap;",
+ "description": "Named entity: ap; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2248"
+ ]
+ ]
+ },
+ {
+ "input": "&apE",
+ "description": "Bad named entity: apE without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&apE"
+ ]
+ ]
+ },
+ {
+ "input": "&apE;",
+ "description": "Named entity: apE; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a70"
+ ]
+ ]
+ },
+ {
+ "input": "&apacir",
+ "description": "Bad named entity: apacir without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&apacir"
+ ]
+ ]
+ },
+ {
+ "input": "&apacir;",
+ "description": "Named entity: apacir; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a6f"
+ ]
+ ]
+ },
+ {
+ "input": "&ape",
+ "description": "Bad named entity: ape without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ape"
+ ]
+ ]
+ },
+ {
+ "input": "&ape;",
+ "description": "Named entity: ape; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u224a"
+ ]
+ ]
+ },
+ {
+ "input": "&apid",
+ "description": "Bad named entity: apid without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&apid"
+ ]
+ ]
+ },
+ {
+ "input": "&apid;",
+ "description": "Named entity: apid; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u224b"
+ ]
+ ]
+ },
+ {
+ "input": "&apos",
+ "description": "Bad named entity: apos without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&apos"
+ ]
+ ]
+ },
+ {
+ "input": "&apos;",
+ "description": "Named entity: apos; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "'"
+ ]
+ ]
+ },
+ {
+ "input": "&approx",
+ "description": "Bad named entity: approx without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&approx"
+ ]
+ ]
+ },
+ {
+ "input": "&approx;",
+ "description": "Named entity: approx; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2248"
+ ]
+ ]
+ },
+ {
+ "input": "&approxeq",
+ "description": "Bad named entity: approxeq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&approxeq"
+ ]
+ ]
+ },
+ {
+ "input": "&approxeq;",
+ "description": "Named entity: approxeq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u224a"
+ ]
+ ]
+ },
+ {
+ "input": "&aring",
+ "description": "Named entity: aring without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00e5"
+ ]
+ ]
+ },
+ {
+ "input": "&aring;",
+ "description": "Named entity: aring; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00e5"
+ ]
+ ]
+ },
+ {
+ "input": "&ascr",
+ "description": "Bad named entity: ascr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ascr"
+ ]
+ ]
+ },
+ {
+ "input": "&ascr;",
+ "description": "Named entity: ascr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udcb6"
+ ]
+ ]
+ },
+ {
+ "input": "&ast",
+ "description": "Bad named entity: ast without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ast"
+ ]
+ ]
+ },
+ {
+ "input": "&ast;",
+ "description": "Named entity: ast; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "*"
+ ]
+ ]
+ },
+ {
+ "input": "&asymp",
+ "description": "Bad named entity: asymp without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&asymp"
+ ]
+ ]
+ },
+ {
+ "input": "&asymp;",
+ "description": "Named entity: asymp; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2248"
+ ]
+ ]
+ },
+ {
+ "input": "&asympeq",
+ "description": "Bad named entity: asympeq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&asympeq"
+ ]
+ ]
+ },
+ {
+ "input": "&asympeq;",
+ "description": "Named entity: asympeq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u224d"
+ ]
+ ]
+ },
+ {
+ "input": "&atilde",
+ "description": "Named entity: atilde without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00e3"
+ ]
+ ]
+ },
+ {
+ "input": "&atilde;",
+ "description": "Named entity: atilde; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00e3"
+ ]
+ ]
+ },
+ {
+ "input": "&auml",
+ "description": "Named entity: auml without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00e4"
+ ]
+ ]
+ },
+ {
+ "input": "&auml;",
+ "description": "Named entity: auml; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00e4"
+ ]
+ ]
+ },
+ {
+ "input": "&awconint",
+ "description": "Bad named entity: awconint without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&awconint"
+ ]
+ ]
+ },
+ {
+ "input": "&awconint;",
+ "description": "Named entity: awconint; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2233"
+ ]
+ ]
+ },
+ {
+ "input": "&awint",
+ "description": "Bad named entity: awint without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&awint"
+ ]
+ ]
+ },
+ {
+ "input": "&awint;",
+ "description": "Named entity: awint; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a11"
+ ]
+ ]
+ },
+ {
+ "input": "&bNot",
+ "description": "Bad named entity: bNot without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&bNot"
+ ]
+ ]
+ },
+ {
+ "input": "&bNot;",
+ "description": "Named entity: bNot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2aed"
+ ]
+ ]
+ },
+ {
+ "input": "&backcong",
+ "description": "Bad named entity: backcong without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&backcong"
+ ]
+ ]
+ },
+ {
+ "input": "&backcong;",
+ "description": "Named entity: backcong; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u224c"
+ ]
+ ]
+ },
+ {
+ "input": "&backepsilon",
+ "description": "Bad named entity: backepsilon without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&backepsilon"
+ ]
+ ]
+ },
+ {
+ "input": "&backepsilon;",
+ "description": "Named entity: backepsilon; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03f6"
+ ]
+ ]
+ },
+ {
+ "input": "&backprime",
+ "description": "Bad named entity: backprime without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&backprime"
+ ]
+ ]
+ },
+ {
+ "input": "&backprime;",
+ "description": "Named entity: backprime; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2035"
+ ]
+ ]
+ },
+ {
+ "input": "&backsim",
+ "description": "Bad named entity: backsim without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&backsim"
+ ]
+ ]
+ },
+ {
+ "input": "&backsim;",
+ "description": "Named entity: backsim; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u223d"
+ ]
+ ]
+ },
+ {
+ "input": "&backsimeq",
+ "description": "Bad named entity: backsimeq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&backsimeq"
+ ]
+ ]
+ },
+ {
+ "input": "&backsimeq;",
+ "description": "Named entity: backsimeq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22cd"
+ ]
+ ]
+ },
+ {
+ "input": "&barvee",
+ "description": "Bad named entity: barvee without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&barvee"
+ ]
+ ]
+ },
+ {
+ "input": "&barvee;",
+ "description": "Named entity: barvee; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22bd"
+ ]
+ ]
+ },
+ {
+ "input": "&barwed",
+ "description": "Bad named entity: barwed without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&barwed"
+ ]
+ ]
+ },
+ {
+ "input": "&barwed;",
+ "description": "Named entity: barwed; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2305"
+ ]
+ ]
+ },
+ {
+ "input": "&barwedge",
+ "description": "Bad named entity: barwedge without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&barwedge"
+ ]
+ ]
+ },
+ {
+ "input": "&barwedge;",
+ "description": "Named entity: barwedge; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2305"
+ ]
+ ]
+ },
+ {
+ "input": "&bbrk",
+ "description": "Bad named entity: bbrk without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&bbrk"
+ ]
+ ]
+ },
+ {
+ "input": "&bbrk;",
+ "description": "Named entity: bbrk; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u23b5"
+ ]
+ ]
+ },
+ {
+ "input": "&bbrktbrk",
+ "description": "Bad named entity: bbrktbrk without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&bbrktbrk"
+ ]
+ ]
+ },
+ {
+ "input": "&bbrktbrk;",
+ "description": "Named entity: bbrktbrk; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u23b6"
+ ]
+ ]
+ },
+ {
+ "input": "&bcong",
+ "description": "Bad named entity: bcong without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&bcong"
+ ]
+ ]
+ },
+ {
+ "input": "&bcong;",
+ "description": "Named entity: bcong; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u224c"
+ ]
+ ]
+ },
+ {
+ "input": "&bcy",
+ "description": "Bad named entity: bcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&bcy"
+ ]
+ ]
+ },
+ {
+ "input": "&bcy;",
+ "description": "Named entity: bcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0431"
+ ]
+ ]
+ },
+ {
+ "input": "&bdquo",
+ "description": "Bad named entity: bdquo without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&bdquo"
+ ]
+ ]
+ },
+ {
+ "input": "&bdquo;",
+ "description": "Named entity: bdquo; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u201e"
+ ]
+ ]
+ },
+ {
+ "input": "&becaus",
+ "description": "Bad named entity: becaus without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&becaus"
+ ]
+ ]
+ },
+ {
+ "input": "&becaus;",
+ "description": "Named entity: becaus; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2235"
+ ]
+ ]
+ },
+ {
+ "input": "&because",
+ "description": "Bad named entity: because without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&because"
+ ]
+ ]
+ },
+ {
+ "input": "&because;",
+ "description": "Named entity: because; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2235"
+ ]
+ ]
+ },
+ {
+ "input": "&bemptyv",
+ "description": "Bad named entity: bemptyv without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&bemptyv"
+ ]
+ ]
+ },
+ {
+ "input": "&bemptyv;",
+ "description": "Named entity: bemptyv; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u29b0"
+ ]
+ ]
+ },
+ {
+ "input": "&bepsi",
+ "description": "Bad named entity: bepsi without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&bepsi"
+ ]
+ ]
+ },
+ {
+ "input": "&bepsi;",
+ "description": "Named entity: bepsi; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03f6"
+ ]
+ ]
+ },
+ {
+ "input": "&bernou",
+ "description": "Bad named entity: bernou without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&bernou"
+ ]
+ ]
+ },
+ {
+ "input": "&bernou;",
+ "description": "Named entity: bernou; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u212c"
+ ]
+ ]
+ },
+ {
+ "input": "&beta",
+ "description": "Bad named entity: beta without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&beta"
+ ]
+ ]
+ },
+ {
+ "input": "&beta;",
+ "description": "Named entity: beta; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03b2"
+ ]
+ ]
+ },
+ {
+ "input": "&beth",
+ "description": "Bad named entity: beth without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&beth"
+ ]
+ ]
+ },
+ {
+ "input": "&beth;",
+ "description": "Named entity: beth; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2136"
+ ]
+ ]
+ },
+ {
+ "input": "&between",
+ "description": "Bad named entity: between without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&between"
+ ]
+ ]
+ },
+ {
+ "input": "&between;",
+ "description": "Named entity: between; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u226c"
+ ]
+ ]
+ },
+ {
+ "input": "&bfr",
+ "description": "Bad named entity: bfr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&bfr"
+ ]
+ ]
+ },
+ {
+ "input": "&bfr;",
+ "description": "Named entity: bfr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd1f"
+ ]
+ ]
+ },
+ {
+ "input": "&bigcap",
+ "description": "Bad named entity: bigcap without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&bigcap"
+ ]
+ ]
+ },
+ {
+ "input": "&bigcap;",
+ "description": "Named entity: bigcap; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22c2"
+ ]
+ ]
+ },
+ {
+ "input": "&bigcirc",
+ "description": "Bad named entity: bigcirc without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&bigcirc"
+ ]
+ ]
+ },
+ {
+ "input": "&bigcirc;",
+ "description": "Named entity: bigcirc; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u25ef"
+ ]
+ ]
+ },
+ {
+ "input": "&bigcup",
+ "description": "Bad named entity: bigcup without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&bigcup"
+ ]
+ ]
+ },
+ {
+ "input": "&bigcup;",
+ "description": "Named entity: bigcup; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22c3"
+ ]
+ ]
+ },
+ {
+ "input": "&bigodot",
+ "description": "Bad named entity: bigodot without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&bigodot"
+ ]
+ ]
+ },
+ {
+ "input": "&bigodot;",
+ "description": "Named entity: bigodot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a00"
+ ]
+ ]
+ },
+ {
+ "input": "&bigoplus",
+ "description": "Bad named entity: bigoplus without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&bigoplus"
+ ]
+ ]
+ },
+ {
+ "input": "&bigoplus;",
+ "description": "Named entity: bigoplus; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a01"
+ ]
+ ]
+ },
+ {
+ "input": "&bigotimes",
+ "description": "Bad named entity: bigotimes without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&bigotimes"
+ ]
+ ]
+ },
+ {
+ "input": "&bigotimes;",
+ "description": "Named entity: bigotimes; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a02"
+ ]
+ ]
+ },
+ {
+ "input": "&bigsqcup",
+ "description": "Bad named entity: bigsqcup without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&bigsqcup"
+ ]
+ ]
+ },
+ {
+ "input": "&bigsqcup;",
+ "description": "Named entity: bigsqcup; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a06"
+ ]
+ ]
+ },
+ {
+ "input": "&bigstar",
+ "description": "Bad named entity: bigstar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&bigstar"
+ ]
+ ]
+ },
+ {
+ "input": "&bigstar;",
+ "description": "Named entity: bigstar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2605"
+ ]
+ ]
+ },
+ {
+ "input": "&bigtriangledown",
+ "description": "Bad named entity: bigtriangledown without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&bigtriangledown"
+ ]
+ ]
+ },
+ {
+ "input": "&bigtriangledown;",
+ "description": "Named entity: bigtriangledown; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u25bd"
+ ]
+ ]
+ },
+ {
+ "input": "&bigtriangleup",
+ "description": "Bad named entity: bigtriangleup without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&bigtriangleup"
+ ]
+ ]
+ },
+ {
+ "input": "&bigtriangleup;",
+ "description": "Named entity: bigtriangleup; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u25b3"
+ ]
+ ]
+ },
+ {
+ "input": "&biguplus",
+ "description": "Bad named entity: biguplus without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&biguplus"
+ ]
+ ]
+ },
+ {
+ "input": "&biguplus;",
+ "description": "Named entity: biguplus; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a04"
+ ]
+ ]
+ },
+ {
+ "input": "&bigvee",
+ "description": "Bad named entity: bigvee without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&bigvee"
+ ]
+ ]
+ },
+ {
+ "input": "&bigvee;",
+ "description": "Named entity: bigvee; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22c1"
+ ]
+ ]
+ },
+ {
+ "input": "&bigwedge",
+ "description": "Bad named entity: bigwedge without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&bigwedge"
+ ]
+ ]
+ },
+ {
+ "input": "&bigwedge;",
+ "description": "Named entity: bigwedge; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22c0"
+ ]
+ ]
+ },
+ {
+ "input": "&bkarow",
+ "description": "Bad named entity: bkarow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&bkarow"
+ ]
+ ]
+ },
+ {
+ "input": "&bkarow;",
+ "description": "Named entity: bkarow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u290d"
+ ]
+ ]
+ },
+ {
+ "input": "&blacklozenge",
+ "description": "Bad named entity: blacklozenge without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&blacklozenge"
+ ]
+ ]
+ },
+ {
+ "input": "&blacklozenge;",
+ "description": "Named entity: blacklozenge; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u29eb"
+ ]
+ ]
+ },
+ {
+ "input": "&blacksquare",
+ "description": "Bad named entity: blacksquare without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&blacksquare"
+ ]
+ ]
+ },
+ {
+ "input": "&blacksquare;",
+ "description": "Named entity: blacksquare; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u25aa"
+ ]
+ ]
+ },
+ {
+ "input": "&blacktriangle",
+ "description": "Bad named entity: blacktriangle without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&blacktriangle"
+ ]
+ ]
+ },
+ {
+ "input": "&blacktriangle;",
+ "description": "Named entity: blacktriangle; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u25b4"
+ ]
+ ]
+ },
+ {
+ "input": "&blacktriangledown",
+ "description": "Bad named entity: blacktriangledown without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&blacktriangledown"
+ ]
+ ]
+ },
+ {
+ "input": "&blacktriangledown;",
+ "description": "Named entity: blacktriangledown; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u25be"
+ ]
+ ]
+ },
+ {
+ "input": "&blacktriangleleft",
+ "description": "Bad named entity: blacktriangleleft without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&blacktriangleleft"
+ ]
+ ]
+ },
+ {
+ "input": "&blacktriangleleft;",
+ "description": "Named entity: blacktriangleleft; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u25c2"
+ ]
+ ]
+ },
+ {
+ "input": "&blacktriangleright",
+ "description": "Bad named entity: blacktriangleright without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&blacktriangleright"
+ ]
+ ]
+ },
+ {
+ "input": "&blacktriangleright;",
+ "description": "Named entity: blacktriangleright; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u25b8"
+ ]
+ ]
+ },
+ {
+ "input": "&blank",
+ "description": "Bad named entity: blank without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&blank"
+ ]
+ ]
+ },
+ {
+ "input": "&blank;",
+ "description": "Named entity: blank; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2423"
+ ]
+ ]
+ },
+ {
+ "input": "&blk12",
+ "description": "Bad named entity: blk12 without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&blk12"
+ ]
+ ]
+ },
+ {
+ "input": "&blk12;",
+ "description": "Named entity: blk12; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2592"
+ ]
+ ]
+ },
+ {
+ "input": "&blk14",
+ "description": "Bad named entity: blk14 without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&blk14"
+ ]
+ ]
+ },
+ {
+ "input": "&blk14;",
+ "description": "Named entity: blk14; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2591"
+ ]
+ ]
+ },
+ {
+ "input": "&blk34",
+ "description": "Bad named entity: blk34 without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&blk34"
+ ]
+ ]
+ },
+ {
+ "input": "&blk34;",
+ "description": "Named entity: blk34; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2593"
+ ]
+ ]
+ },
+ {
+ "input": "&block",
+ "description": "Bad named entity: block without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&block"
+ ]
+ ]
+ },
+ {
+ "input": "&block;",
+ "description": "Named entity: block; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2588"
+ ]
+ ]
+ },
+ {
+ "input": "&bne",
+ "description": "Bad named entity: bne without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&bne"
+ ]
+ ]
+ },
+ {
+ "input": "&bne;",
+ "description": "Named entity: bne; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "=\u20e5"
+ ]
+ ]
+ },
+ {
+ "input": "&bnequiv",
+ "description": "Bad named entity: bnequiv without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&bnequiv"
+ ]
+ ]
+ },
+ {
+ "input": "&bnequiv;",
+ "description": "Named entity: bnequiv; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2261\u20e5"
+ ]
+ ]
+ },
+ {
+ "input": "&bnot",
+ "description": "Bad named entity: bnot without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&bnot"
+ ]
+ ]
+ },
+ {
+ "input": "&bnot;",
+ "description": "Named entity: bnot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2310"
+ ]
+ ]
+ },
+ {
+ "input": "&bopf",
+ "description": "Bad named entity: bopf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&bopf"
+ ]
+ ]
+ },
+ {
+ "input": "&bopf;",
+ "description": "Named entity: bopf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd53"
+ ]
+ ]
+ },
+ {
+ "input": "&bot",
+ "description": "Bad named entity: bot without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&bot"
+ ]
+ ]
+ },
+ {
+ "input": "&bot;",
+ "description": "Named entity: bot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22a5"
+ ]
+ ]
+ },
+ {
+ "input": "&bottom",
+ "description": "Bad named entity: bottom without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&bottom"
+ ]
+ ]
+ },
+ {
+ "input": "&bottom;",
+ "description": "Named entity: bottom; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22a5"
+ ]
+ ]
+ },
+ {
+ "input": "&bowtie",
+ "description": "Bad named entity: bowtie without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&bowtie"
+ ]
+ ]
+ },
+ {
+ "input": "&bowtie;",
+ "description": "Named entity: bowtie; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22c8"
+ ]
+ ]
+ },
+ {
+ "input": "&boxDL",
+ "description": "Bad named entity: boxDL without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&boxDL"
+ ]
+ ]
+ },
+ {
+ "input": "&boxDL;",
+ "description": "Named entity: boxDL; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2557"
+ ]
+ ]
+ },
+ {
+ "input": "&boxDR",
+ "description": "Bad named entity: boxDR without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&boxDR"
+ ]
+ ]
+ },
+ {
+ "input": "&boxDR;",
+ "description": "Named entity: boxDR; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2554"
+ ]
+ ]
+ },
+ {
+ "input": "&boxDl",
+ "description": "Bad named entity: boxDl without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&boxDl"
+ ]
+ ]
+ },
+ {
+ "input": "&boxDl;",
+ "description": "Named entity: boxDl; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2556"
+ ]
+ ]
+ },
+ {
+ "input": "&boxDr",
+ "description": "Bad named entity: boxDr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&boxDr"
+ ]
+ ]
+ },
+ {
+ "input": "&boxDr;",
+ "description": "Named entity: boxDr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2553"
+ ]
+ ]
+ },
+ {
+ "input": "&boxH",
+ "description": "Bad named entity: boxH without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&boxH"
+ ]
+ ]
+ },
+ {
+ "input": "&boxH;",
+ "description": "Named entity: boxH; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2550"
+ ]
+ ]
+ },
+ {
+ "input": "&boxHD",
+ "description": "Bad named entity: boxHD without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&boxHD"
+ ]
+ ]
+ },
+ {
+ "input": "&boxHD;",
+ "description": "Named entity: boxHD; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2566"
+ ]
+ ]
+ },
+ {
+ "input": "&boxHU",
+ "description": "Bad named entity: boxHU without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&boxHU"
+ ]
+ ]
+ },
+ {
+ "input": "&boxHU;",
+ "description": "Named entity: boxHU; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2569"
+ ]
+ ]
+ },
+ {
+ "input": "&boxHd",
+ "description": "Bad named entity: boxHd without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&boxHd"
+ ]
+ ]
+ },
+ {
+ "input": "&boxHd;",
+ "description": "Named entity: boxHd; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2564"
+ ]
+ ]
+ },
+ {
+ "input": "&boxHu",
+ "description": "Bad named entity: boxHu without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&boxHu"
+ ]
+ ]
+ },
+ {
+ "input": "&boxHu;",
+ "description": "Named entity: boxHu; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2567"
+ ]
+ ]
+ },
+ {
+ "input": "&boxUL",
+ "description": "Bad named entity: boxUL without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&boxUL"
+ ]
+ ]
+ },
+ {
+ "input": "&boxUL;",
+ "description": "Named entity: boxUL; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u255d"
+ ]
+ ]
+ },
+ {
+ "input": "&boxUR",
+ "description": "Bad named entity: boxUR without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&boxUR"
+ ]
+ ]
+ },
+ {
+ "input": "&boxUR;",
+ "description": "Named entity: boxUR; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u255a"
+ ]
+ ]
+ },
+ {
+ "input": "&boxUl",
+ "description": "Bad named entity: boxUl without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&boxUl"
+ ]
+ ]
+ },
+ {
+ "input": "&boxUl;",
+ "description": "Named entity: boxUl; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u255c"
+ ]
+ ]
+ },
+ {
+ "input": "&boxUr",
+ "description": "Bad named entity: boxUr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&boxUr"
+ ]
+ ]
+ },
+ {
+ "input": "&boxUr;",
+ "description": "Named entity: boxUr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2559"
+ ]
+ ]
+ },
+ {
+ "input": "&boxV",
+ "description": "Bad named entity: boxV without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&boxV"
+ ]
+ ]
+ },
+ {
+ "input": "&boxV;",
+ "description": "Named entity: boxV; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2551"
+ ]
+ ]
+ },
+ {
+ "input": "&boxVH",
+ "description": "Bad named entity: boxVH without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&boxVH"
+ ]
+ ]
+ },
+ {
+ "input": "&boxVH;",
+ "description": "Named entity: boxVH; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u256c"
+ ]
+ ]
+ },
+ {
+ "input": "&boxVL",
+ "description": "Bad named entity: boxVL without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&boxVL"
+ ]
+ ]
+ },
+ {
+ "input": "&boxVL;",
+ "description": "Named entity: boxVL; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2563"
+ ]
+ ]
+ },
+ {
+ "input": "&boxVR",
+ "description": "Bad named entity: boxVR without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&boxVR"
+ ]
+ ]
+ },
+ {
+ "input": "&boxVR;",
+ "description": "Named entity: boxVR; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2560"
+ ]
+ ]
+ },
+ {
+ "input": "&boxVh",
+ "description": "Bad named entity: boxVh without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&boxVh"
+ ]
+ ]
+ },
+ {
+ "input": "&boxVh;",
+ "description": "Named entity: boxVh; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u256b"
+ ]
+ ]
+ },
+ {
+ "input": "&boxVl",
+ "description": "Bad named entity: boxVl without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&boxVl"
+ ]
+ ]
+ },
+ {
+ "input": "&boxVl;",
+ "description": "Named entity: boxVl; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2562"
+ ]
+ ]
+ },
+ {
+ "input": "&boxVr",
+ "description": "Bad named entity: boxVr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&boxVr"
+ ]
+ ]
+ },
+ {
+ "input": "&boxVr;",
+ "description": "Named entity: boxVr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u255f"
+ ]
+ ]
+ },
+ {
+ "input": "&boxbox",
+ "description": "Bad named entity: boxbox without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&boxbox"
+ ]
+ ]
+ },
+ {
+ "input": "&boxbox;",
+ "description": "Named entity: boxbox; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u29c9"
+ ]
+ ]
+ },
+ {
+ "input": "&boxdL",
+ "description": "Bad named entity: boxdL without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&boxdL"
+ ]
+ ]
+ },
+ {
+ "input": "&boxdL;",
+ "description": "Named entity: boxdL; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2555"
+ ]
+ ]
+ },
+ {
+ "input": "&boxdR",
+ "description": "Bad named entity: boxdR without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&boxdR"
+ ]
+ ]
+ },
+ {
+ "input": "&boxdR;",
+ "description": "Named entity: boxdR; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2552"
+ ]
+ ]
+ },
+ {
+ "input": "&boxdl",
+ "description": "Bad named entity: boxdl without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&boxdl"
+ ]
+ ]
+ },
+ {
+ "input": "&boxdl;",
+ "description": "Named entity: boxdl; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2510"
+ ]
+ ]
+ },
+ {
+ "input": "&boxdr",
+ "description": "Bad named entity: boxdr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&boxdr"
+ ]
+ ]
+ },
+ {
+ "input": "&boxdr;",
+ "description": "Named entity: boxdr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u250c"
+ ]
+ ]
+ },
+ {
+ "input": "&boxh",
+ "description": "Bad named entity: boxh without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&boxh"
+ ]
+ ]
+ },
+ {
+ "input": "&boxh;",
+ "description": "Named entity: boxh; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2500"
+ ]
+ ]
+ },
+ {
+ "input": "&boxhD",
+ "description": "Bad named entity: boxhD without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&boxhD"
+ ]
+ ]
+ },
+ {
+ "input": "&boxhD;",
+ "description": "Named entity: boxhD; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2565"
+ ]
+ ]
+ },
+ {
+ "input": "&boxhU",
+ "description": "Bad named entity: boxhU without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&boxhU"
+ ]
+ ]
+ },
+ {
+ "input": "&boxhU;",
+ "description": "Named entity: boxhU; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2568"
+ ]
+ ]
+ },
+ {
+ "input": "&boxhd",
+ "description": "Bad named entity: boxhd without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&boxhd"
+ ]
+ ]
+ },
+ {
+ "input": "&boxhd;",
+ "description": "Named entity: boxhd; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u252c"
+ ]
+ ]
+ },
+ {
+ "input": "&boxhu",
+ "description": "Bad named entity: boxhu without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&boxhu"
+ ]
+ ]
+ },
+ {
+ "input": "&boxhu;",
+ "description": "Named entity: boxhu; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2534"
+ ]
+ ]
+ },
+ {
+ "input": "&boxminus",
+ "description": "Bad named entity: boxminus without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&boxminus"
+ ]
+ ]
+ },
+ {
+ "input": "&boxminus;",
+ "description": "Named entity: boxminus; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u229f"
+ ]
+ ]
+ },
+ {
+ "input": "&boxplus",
+ "description": "Bad named entity: boxplus without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&boxplus"
+ ]
+ ]
+ },
+ {
+ "input": "&boxplus;",
+ "description": "Named entity: boxplus; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u229e"
+ ]
+ ]
+ },
+ {
+ "input": "&boxtimes",
+ "description": "Bad named entity: boxtimes without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&boxtimes"
+ ]
+ ]
+ },
+ {
+ "input": "&boxtimes;",
+ "description": "Named entity: boxtimes; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22a0"
+ ]
+ ]
+ },
+ {
+ "input": "&boxuL",
+ "description": "Bad named entity: boxuL without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&boxuL"
+ ]
+ ]
+ },
+ {
+ "input": "&boxuL;",
+ "description": "Named entity: boxuL; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u255b"
+ ]
+ ]
+ },
+ {
+ "input": "&boxuR",
+ "description": "Bad named entity: boxuR without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&boxuR"
+ ]
+ ]
+ },
+ {
+ "input": "&boxuR;",
+ "description": "Named entity: boxuR; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2558"
+ ]
+ ]
+ },
+ {
+ "input": "&boxul",
+ "description": "Bad named entity: boxul without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&boxul"
+ ]
+ ]
+ },
+ {
+ "input": "&boxul;",
+ "description": "Named entity: boxul; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2518"
+ ]
+ ]
+ },
+ {
+ "input": "&boxur",
+ "description": "Bad named entity: boxur without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&boxur"
+ ]
+ ]
+ },
+ {
+ "input": "&boxur;",
+ "description": "Named entity: boxur; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2514"
+ ]
+ ]
+ },
+ {
+ "input": "&boxv",
+ "description": "Bad named entity: boxv without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&boxv"
+ ]
+ ]
+ },
+ {
+ "input": "&boxv;",
+ "description": "Named entity: boxv; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2502"
+ ]
+ ]
+ },
+ {
+ "input": "&boxvH",
+ "description": "Bad named entity: boxvH without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&boxvH"
+ ]
+ ]
+ },
+ {
+ "input": "&boxvH;",
+ "description": "Named entity: boxvH; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u256a"
+ ]
+ ]
+ },
+ {
+ "input": "&boxvL",
+ "description": "Bad named entity: boxvL without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&boxvL"
+ ]
+ ]
+ },
+ {
+ "input": "&boxvL;",
+ "description": "Named entity: boxvL; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2561"
+ ]
+ ]
+ },
+ {
+ "input": "&boxvR",
+ "description": "Bad named entity: boxvR without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&boxvR"
+ ]
+ ]
+ },
+ {
+ "input": "&boxvR;",
+ "description": "Named entity: boxvR; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u255e"
+ ]
+ ]
+ },
+ {
+ "input": "&boxvh",
+ "description": "Bad named entity: boxvh without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&boxvh"
+ ]
+ ]
+ },
+ {
+ "input": "&boxvh;",
+ "description": "Named entity: boxvh; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u253c"
+ ]
+ ]
+ },
+ {
+ "input": "&boxvl",
+ "description": "Bad named entity: boxvl without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&boxvl"
+ ]
+ ]
+ },
+ {
+ "input": "&boxvl;",
+ "description": "Named entity: boxvl; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2524"
+ ]
+ ]
+ },
+ {
+ "input": "&boxvr",
+ "description": "Bad named entity: boxvr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&boxvr"
+ ]
+ ]
+ },
+ {
+ "input": "&boxvr;",
+ "description": "Named entity: boxvr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u251c"
+ ]
+ ]
+ },
+ {
+ "input": "&bprime",
+ "description": "Bad named entity: bprime without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&bprime"
+ ]
+ ]
+ },
+ {
+ "input": "&bprime;",
+ "description": "Named entity: bprime; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2035"
+ ]
+ ]
+ },
+ {
+ "input": "&breve",
+ "description": "Bad named entity: breve without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&breve"
+ ]
+ ]
+ },
+ {
+ "input": "&breve;",
+ "description": "Named entity: breve; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u02d8"
+ ]
+ ]
+ },
+ {
+ "input": "&brvbar",
+ "description": "Named entity: brvbar without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00a6"
+ ]
+ ]
+ },
+ {
+ "input": "&brvbar;",
+ "description": "Named entity: brvbar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00a6"
+ ]
+ ]
+ },
+ {
+ "input": "&bscr",
+ "description": "Bad named entity: bscr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&bscr"
+ ]
+ ]
+ },
+ {
+ "input": "&bscr;",
+ "description": "Named entity: bscr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udcb7"
+ ]
+ ]
+ },
+ {
+ "input": "&bsemi",
+ "description": "Bad named entity: bsemi without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&bsemi"
+ ]
+ ]
+ },
+ {
+ "input": "&bsemi;",
+ "description": "Named entity: bsemi; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u204f"
+ ]
+ ]
+ },
+ {
+ "input": "&bsim",
+ "description": "Bad named entity: bsim without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&bsim"
+ ]
+ ]
+ },
+ {
+ "input": "&bsim;",
+ "description": "Named entity: bsim; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u223d"
+ ]
+ ]
+ },
+ {
+ "input": "&bsime",
+ "description": "Bad named entity: bsime without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&bsime"
+ ]
+ ]
+ },
+ {
+ "input": "&bsime;",
+ "description": "Named entity: bsime; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22cd"
+ ]
+ ]
+ },
+ {
+ "input": "&bsol",
+ "description": "Bad named entity: bsol without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&bsol"
+ ]
+ ]
+ },
+ {
+ "input": "&bsol;",
+ "description": "Named entity: bsol; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\\"
+ ]
+ ]
+ },
+ {
+ "input": "&bsolb",
+ "description": "Bad named entity: bsolb without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&bsolb"
+ ]
+ ]
+ },
+ {
+ "input": "&bsolb;",
+ "description": "Named entity: bsolb; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u29c5"
+ ]
+ ]
+ },
+ {
+ "input": "&bsolhsub",
+ "description": "Bad named entity: bsolhsub without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&bsolhsub"
+ ]
+ ]
+ },
+ {
+ "input": "&bsolhsub;",
+ "description": "Named entity: bsolhsub; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u27c8"
+ ]
+ ]
+ },
+ {
+ "input": "&bull",
+ "description": "Bad named entity: bull without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&bull"
+ ]
+ ]
+ },
+ {
+ "input": "&bull;",
+ "description": "Named entity: bull; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2022"
+ ]
+ ]
+ },
+ {
+ "input": "&bullet",
+ "description": "Bad named entity: bullet without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&bullet"
+ ]
+ ]
+ },
+ {
+ "input": "&bullet;",
+ "description": "Named entity: bullet; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2022"
+ ]
+ ]
+ },
+ {
+ "input": "&bump",
+ "description": "Bad named entity: bump without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&bump"
+ ]
+ ]
+ },
+ {
+ "input": "&bump;",
+ "description": "Named entity: bump; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u224e"
+ ]
+ ]
+ },
+ {
+ "input": "&bumpE",
+ "description": "Bad named entity: bumpE without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&bumpE"
+ ]
+ ]
+ },
+ {
+ "input": "&bumpE;",
+ "description": "Named entity: bumpE; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2aae"
+ ]
+ ]
+ },
+ {
+ "input": "&bumpe",
+ "description": "Bad named entity: bumpe without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&bumpe"
+ ]
+ ]
+ },
+ {
+ "input": "&bumpe;",
+ "description": "Named entity: bumpe; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u224f"
+ ]
+ ]
+ },
+ {
+ "input": "&bumpeq",
+ "description": "Bad named entity: bumpeq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&bumpeq"
+ ]
+ ]
+ },
+ {
+ "input": "&bumpeq;",
+ "description": "Named entity: bumpeq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u224f"
+ ]
+ ]
+ },
+ {
+ "input": "&cacute",
+ "description": "Bad named entity: cacute without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&cacute"
+ ]
+ ]
+ },
+ {
+ "input": "&cacute;",
+ "description": "Named entity: cacute; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0107"
+ ]
+ ]
+ },
+ {
+ "input": "&cap",
+ "description": "Bad named entity: cap without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&cap"
+ ]
+ ]
+ },
+ {
+ "input": "&cap;",
+ "description": "Named entity: cap; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2229"
+ ]
+ ]
+ },
+ {
+ "input": "&capand",
+ "description": "Bad named entity: capand without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&capand"
+ ]
+ ]
+ },
+ {
+ "input": "&capand;",
+ "description": "Named entity: capand; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a44"
+ ]
+ ]
+ },
+ {
+ "input": "&capbrcup",
+ "description": "Bad named entity: capbrcup without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&capbrcup"
+ ]
+ ]
+ },
+ {
+ "input": "&capbrcup;",
+ "description": "Named entity: capbrcup; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a49"
+ ]
+ ]
+ },
+ {
+ "input": "&capcap",
+ "description": "Bad named entity: capcap without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&capcap"
+ ]
+ ]
+ },
+ {
+ "input": "&capcap;",
+ "description": "Named entity: capcap; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a4b"
+ ]
+ ]
+ },
+ {
+ "input": "&capcup",
+ "description": "Bad named entity: capcup without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&capcup"
+ ]
+ ]
+ },
+ {
+ "input": "&capcup;",
+ "description": "Named entity: capcup; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a47"
+ ]
+ ]
+ },
+ {
+ "input": "&capdot",
+ "description": "Bad named entity: capdot without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&capdot"
+ ]
+ ]
+ },
+ {
+ "input": "&capdot;",
+ "description": "Named entity: capdot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a40"
+ ]
+ ]
+ },
+ {
+ "input": "&caps",
+ "description": "Bad named entity: caps without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&caps"
+ ]
+ ]
+ },
+ {
+ "input": "&caps;",
+ "description": "Named entity: caps; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2229\ufe00"
+ ]
+ ]
+ },
+ {
+ "input": "&caret",
+ "description": "Bad named entity: caret without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&caret"
+ ]
+ ]
+ },
+ {
+ "input": "&caret;",
+ "description": "Named entity: caret; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2041"
+ ]
+ ]
+ },
+ {
+ "input": "&caron",
+ "description": "Bad named entity: caron without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&caron"
+ ]
+ ]
+ },
+ {
+ "input": "&caron;",
+ "description": "Named entity: caron; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u02c7"
+ ]
+ ]
+ },
+ {
+ "input": "&ccaps",
+ "description": "Bad named entity: ccaps without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ccaps"
+ ]
+ ]
+ },
+ {
+ "input": "&ccaps;",
+ "description": "Named entity: ccaps; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a4d"
+ ]
+ ]
+ },
+ {
+ "input": "&ccaron",
+ "description": "Bad named entity: ccaron without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ccaron"
+ ]
+ ]
+ },
+ {
+ "input": "&ccaron;",
+ "description": "Named entity: ccaron; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u010d"
+ ]
+ ]
+ },
+ {
+ "input": "&ccedil",
+ "description": "Named entity: ccedil without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00e7"
+ ]
+ ]
+ },
+ {
+ "input": "&ccedil;",
+ "description": "Named entity: ccedil; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00e7"
+ ]
+ ]
+ },
+ {
+ "input": "&ccirc",
+ "description": "Bad named entity: ccirc without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ccirc"
+ ]
+ ]
+ },
+ {
+ "input": "&ccirc;",
+ "description": "Named entity: ccirc; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0109"
+ ]
+ ]
+ },
+ {
+ "input": "&ccups",
+ "description": "Bad named entity: ccups without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ccups"
+ ]
+ ]
+ },
+ {
+ "input": "&ccups;",
+ "description": "Named entity: ccups; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a4c"
+ ]
+ ]
+ },
+ {
+ "input": "&ccupssm",
+ "description": "Bad named entity: ccupssm without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ccupssm"
+ ]
+ ]
+ },
+ {
+ "input": "&ccupssm;",
+ "description": "Named entity: ccupssm; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a50"
+ ]
+ ]
+ },
+ {
+ "input": "&cdot",
+ "description": "Bad named entity: cdot without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&cdot"
+ ]
+ ]
+ },
+ {
+ "input": "&cdot;",
+ "description": "Named entity: cdot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u010b"
+ ]
+ ]
+ },
+ {
+ "input": "&cedil",
+ "description": "Named entity: cedil without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00b8"
+ ]
+ ]
+ },
+ {
+ "input": "&cedil;",
+ "description": "Named entity: cedil; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00b8"
+ ]
+ ]
+ },
+ {
+ "input": "&cemptyv",
+ "description": "Bad named entity: cemptyv without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&cemptyv"
+ ]
+ ]
+ },
+ {
+ "input": "&cemptyv;",
+ "description": "Named entity: cemptyv; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u29b2"
+ ]
+ ]
+ },
+ {
+ "input": "&cent",
+ "description": "Named entity: cent without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00a2"
+ ]
+ ]
+ },
+ {
+ "input": "&cent;",
+ "description": "Named entity: cent; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00a2"
+ ]
+ ]
+ },
+ {
+ "input": "&centerdot;",
+ "description": "Named entity: centerdot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00b7"
+ ]
+ ]
+ },
+ {
+ "input": "&cfr",
+ "description": "Bad named entity: cfr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&cfr"
+ ]
+ ]
+ },
+ {
+ "input": "&cfr;",
+ "description": "Named entity: cfr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd20"
+ ]
+ ]
+ },
+ {
+ "input": "&chcy",
+ "description": "Bad named entity: chcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&chcy"
+ ]
+ ]
+ },
+ {
+ "input": "&chcy;",
+ "description": "Named entity: chcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0447"
+ ]
+ ]
+ },
+ {
+ "input": "&check",
+ "description": "Bad named entity: check without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&check"
+ ]
+ ]
+ },
+ {
+ "input": "&check;",
+ "description": "Named entity: check; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2713"
+ ]
+ ]
+ },
+ {
+ "input": "&checkmark",
+ "description": "Bad named entity: checkmark without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&checkmark"
+ ]
+ ]
+ },
+ {
+ "input": "&checkmark;",
+ "description": "Named entity: checkmark; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2713"
+ ]
+ ]
+ },
+ {
+ "input": "&chi",
+ "description": "Bad named entity: chi without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&chi"
+ ]
+ ]
+ },
+ {
+ "input": "&chi;",
+ "description": "Named entity: chi; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03c7"
+ ]
+ ]
+ },
+ {
+ "input": "&cir",
+ "description": "Bad named entity: cir without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&cir"
+ ]
+ ]
+ },
+ {
+ "input": "&cir;",
+ "description": "Named entity: cir; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u25cb"
+ ]
+ ]
+ },
+ {
+ "input": "&cirE",
+ "description": "Bad named entity: cirE without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&cirE"
+ ]
+ ]
+ },
+ {
+ "input": "&cirE;",
+ "description": "Named entity: cirE; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u29c3"
+ ]
+ ]
+ },
+ {
+ "input": "&circ",
+ "description": "Bad named entity: circ without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&circ"
+ ]
+ ]
+ },
+ {
+ "input": "&circ;",
+ "description": "Named entity: circ; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u02c6"
+ ]
+ ]
+ },
+ {
+ "input": "&circeq",
+ "description": "Bad named entity: circeq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&circeq"
+ ]
+ ]
+ },
+ {
+ "input": "&circeq;",
+ "description": "Named entity: circeq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2257"
+ ]
+ ]
+ },
+ {
+ "input": "&circlearrowleft",
+ "description": "Bad named entity: circlearrowleft without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&circlearrowleft"
+ ]
+ ]
+ },
+ {
+ "input": "&circlearrowleft;",
+ "description": "Named entity: circlearrowleft; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21ba"
+ ]
+ ]
+ },
+ {
+ "input": "&circlearrowright",
+ "description": "Bad named entity: circlearrowright without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&circlearrowright"
+ ]
+ ]
+ },
+ {
+ "input": "&circlearrowright;",
+ "description": "Named entity: circlearrowright; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21bb"
+ ]
+ ]
+ },
+ {
+ "input": "&circledR",
+ "description": "Bad named entity: circledR without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&circledR"
+ ]
+ ]
+ },
+ {
+ "input": "&circledR;",
+ "description": "Named entity: circledR; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00ae"
+ ]
+ ]
+ },
+ {
+ "input": "&circledS",
+ "description": "Bad named entity: circledS without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&circledS"
+ ]
+ ]
+ },
+ {
+ "input": "&circledS;",
+ "description": "Named entity: circledS; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u24c8"
+ ]
+ ]
+ },
+ {
+ "input": "&circledast",
+ "description": "Bad named entity: circledast without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&circledast"
+ ]
+ ]
+ },
+ {
+ "input": "&circledast;",
+ "description": "Named entity: circledast; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u229b"
+ ]
+ ]
+ },
+ {
+ "input": "&circledcirc",
+ "description": "Bad named entity: circledcirc without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&circledcirc"
+ ]
+ ]
+ },
+ {
+ "input": "&circledcirc;",
+ "description": "Named entity: circledcirc; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u229a"
+ ]
+ ]
+ },
+ {
+ "input": "&circleddash",
+ "description": "Bad named entity: circleddash without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&circleddash"
+ ]
+ ]
+ },
+ {
+ "input": "&circleddash;",
+ "description": "Named entity: circleddash; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u229d"
+ ]
+ ]
+ },
+ {
+ "input": "&cire",
+ "description": "Bad named entity: cire without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&cire"
+ ]
+ ]
+ },
+ {
+ "input": "&cire;",
+ "description": "Named entity: cire; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2257"
+ ]
+ ]
+ },
+ {
+ "input": "&cirfnint",
+ "description": "Bad named entity: cirfnint without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&cirfnint"
+ ]
+ ]
+ },
+ {
+ "input": "&cirfnint;",
+ "description": "Named entity: cirfnint; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a10"
+ ]
+ ]
+ },
+ {
+ "input": "&cirmid",
+ "description": "Bad named entity: cirmid without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&cirmid"
+ ]
+ ]
+ },
+ {
+ "input": "&cirmid;",
+ "description": "Named entity: cirmid; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2aef"
+ ]
+ ]
+ },
+ {
+ "input": "&cirscir",
+ "description": "Bad named entity: cirscir without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&cirscir"
+ ]
+ ]
+ },
+ {
+ "input": "&cirscir;",
+ "description": "Named entity: cirscir; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u29c2"
+ ]
+ ]
+ },
+ {
+ "input": "&clubs",
+ "description": "Bad named entity: clubs without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&clubs"
+ ]
+ ]
+ },
+ {
+ "input": "&clubs;",
+ "description": "Named entity: clubs; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2663"
+ ]
+ ]
+ },
+ {
+ "input": "&clubsuit",
+ "description": "Bad named entity: clubsuit without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&clubsuit"
+ ]
+ ]
+ },
+ {
+ "input": "&clubsuit;",
+ "description": "Named entity: clubsuit; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2663"
+ ]
+ ]
+ },
+ {
+ "input": "&colon",
+ "description": "Bad named entity: colon without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&colon"
+ ]
+ ]
+ },
+ {
+ "input": "&colon;",
+ "description": "Named entity: colon; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ ":"
+ ]
+ ]
+ },
+ {
+ "input": "&colone",
+ "description": "Bad named entity: colone without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&colone"
+ ]
+ ]
+ },
+ {
+ "input": "&colone;",
+ "description": "Named entity: colone; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2254"
+ ]
+ ]
+ },
+ {
+ "input": "&coloneq",
+ "description": "Bad named entity: coloneq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&coloneq"
+ ]
+ ]
+ },
+ {
+ "input": "&coloneq;",
+ "description": "Named entity: coloneq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2254"
+ ]
+ ]
+ },
+ {
+ "input": "&comma",
+ "description": "Bad named entity: comma without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&comma"
+ ]
+ ]
+ },
+ {
+ "input": "&comma;",
+ "description": "Named entity: comma; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ ","
+ ]
+ ]
+ },
+ {
+ "input": "&commat",
+ "description": "Bad named entity: commat without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&commat"
+ ]
+ ]
+ },
+ {
+ "input": "&commat;",
+ "description": "Named entity: commat; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "@"
+ ]
+ ]
+ },
+ {
+ "input": "&comp",
+ "description": "Bad named entity: comp without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&comp"
+ ]
+ ]
+ },
+ {
+ "input": "&comp;",
+ "description": "Named entity: comp; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2201"
+ ]
+ ]
+ },
+ {
+ "input": "&compfn",
+ "description": "Bad named entity: compfn without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&compfn"
+ ]
+ ]
+ },
+ {
+ "input": "&compfn;",
+ "description": "Named entity: compfn; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2218"
+ ]
+ ]
+ },
+ {
+ "input": "&complement",
+ "description": "Bad named entity: complement without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&complement"
+ ]
+ ]
+ },
+ {
+ "input": "&complement;",
+ "description": "Named entity: complement; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2201"
+ ]
+ ]
+ },
+ {
+ "input": "&complexes",
+ "description": "Bad named entity: complexes without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&complexes"
+ ]
+ ]
+ },
+ {
+ "input": "&complexes;",
+ "description": "Named entity: complexes; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2102"
+ ]
+ ]
+ },
+ {
+ "input": "&cong",
+ "description": "Bad named entity: cong without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&cong"
+ ]
+ ]
+ },
+ {
+ "input": "&cong;",
+ "description": "Named entity: cong; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2245"
+ ]
+ ]
+ },
+ {
+ "input": "&congdot",
+ "description": "Bad named entity: congdot without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&congdot"
+ ]
+ ]
+ },
+ {
+ "input": "&congdot;",
+ "description": "Named entity: congdot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a6d"
+ ]
+ ]
+ },
+ {
+ "input": "&conint",
+ "description": "Bad named entity: conint without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&conint"
+ ]
+ ]
+ },
+ {
+ "input": "&conint;",
+ "description": "Named entity: conint; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u222e"
+ ]
+ ]
+ },
+ {
+ "input": "&copf",
+ "description": "Bad named entity: copf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&copf"
+ ]
+ ]
+ },
+ {
+ "input": "&copf;",
+ "description": "Named entity: copf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd54"
+ ]
+ ]
+ },
+ {
+ "input": "&coprod",
+ "description": "Bad named entity: coprod without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&coprod"
+ ]
+ ]
+ },
+ {
+ "input": "&coprod;",
+ "description": "Named entity: coprod; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2210"
+ ]
+ ]
+ },
+ {
+ "input": "&copy",
+ "description": "Named entity: copy without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00a9"
+ ]
+ ]
+ },
+ {
+ "input": "&copy;",
+ "description": "Named entity: copy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00a9"
+ ]
+ ]
+ },
+ {
+ "input": "&copysr;",
+ "description": "Named entity: copysr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2117"
+ ]
+ ]
+ },
+ {
+ "input": "&crarr",
+ "description": "Bad named entity: crarr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&crarr"
+ ]
+ ]
+ },
+ {
+ "input": "&crarr;",
+ "description": "Named entity: crarr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21b5"
+ ]
+ ]
+ },
+ {
+ "input": "&cross",
+ "description": "Bad named entity: cross without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&cross"
+ ]
+ ]
+ },
+ {
+ "input": "&cross;",
+ "description": "Named entity: cross; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2717"
+ ]
+ ]
+ },
+ {
+ "input": "&cscr",
+ "description": "Bad named entity: cscr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&cscr"
+ ]
+ ]
+ },
+ {
+ "input": "&cscr;",
+ "description": "Named entity: cscr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udcb8"
+ ]
+ ]
+ },
+ {
+ "input": "&csub",
+ "description": "Bad named entity: csub without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&csub"
+ ]
+ ]
+ },
+ {
+ "input": "&csub;",
+ "description": "Named entity: csub; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2acf"
+ ]
+ ]
+ },
+ {
+ "input": "&csube",
+ "description": "Bad named entity: csube without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&csube"
+ ]
+ ]
+ },
+ {
+ "input": "&csube;",
+ "description": "Named entity: csube; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2ad1"
+ ]
+ ]
+ },
+ {
+ "input": "&csup",
+ "description": "Bad named entity: csup without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&csup"
+ ]
+ ]
+ },
+ {
+ "input": "&csup;",
+ "description": "Named entity: csup; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2ad0"
+ ]
+ ]
+ },
+ {
+ "input": "&csupe",
+ "description": "Bad named entity: csupe without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&csupe"
+ ]
+ ]
+ },
+ {
+ "input": "&csupe;",
+ "description": "Named entity: csupe; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2ad2"
+ ]
+ ]
+ },
+ {
+ "input": "&ctdot",
+ "description": "Bad named entity: ctdot without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ctdot"
+ ]
+ ]
+ },
+ {
+ "input": "&ctdot;",
+ "description": "Named entity: ctdot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22ef"
+ ]
+ ]
+ },
+ {
+ "input": "&cudarrl",
+ "description": "Bad named entity: cudarrl without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&cudarrl"
+ ]
+ ]
+ },
+ {
+ "input": "&cudarrl;",
+ "description": "Named entity: cudarrl; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2938"
+ ]
+ ]
+ },
+ {
+ "input": "&cudarrr",
+ "description": "Bad named entity: cudarrr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&cudarrr"
+ ]
+ ]
+ },
+ {
+ "input": "&cudarrr;",
+ "description": "Named entity: cudarrr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2935"
+ ]
+ ]
+ },
+ {
+ "input": "&cuepr",
+ "description": "Bad named entity: cuepr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&cuepr"
+ ]
+ ]
+ },
+ {
+ "input": "&cuepr;",
+ "description": "Named entity: cuepr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22de"
+ ]
+ ]
+ },
+ {
+ "input": "&cuesc",
+ "description": "Bad named entity: cuesc without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&cuesc"
+ ]
+ ]
+ },
+ {
+ "input": "&cuesc;",
+ "description": "Named entity: cuesc; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22df"
+ ]
+ ]
+ },
+ {
+ "input": "&cularr",
+ "description": "Bad named entity: cularr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&cularr"
+ ]
+ ]
+ },
+ {
+ "input": "&cularr;",
+ "description": "Named entity: cularr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21b6"
+ ]
+ ]
+ },
+ {
+ "input": "&cularrp",
+ "description": "Bad named entity: cularrp without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&cularrp"
+ ]
+ ]
+ },
+ {
+ "input": "&cularrp;",
+ "description": "Named entity: cularrp; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u293d"
+ ]
+ ]
+ },
+ {
+ "input": "&cup",
+ "description": "Bad named entity: cup without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&cup"
+ ]
+ ]
+ },
+ {
+ "input": "&cup;",
+ "description": "Named entity: cup; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u222a"
+ ]
+ ]
+ },
+ {
+ "input": "&cupbrcap",
+ "description": "Bad named entity: cupbrcap without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&cupbrcap"
+ ]
+ ]
+ },
+ {
+ "input": "&cupbrcap;",
+ "description": "Named entity: cupbrcap; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a48"
+ ]
+ ]
+ },
+ {
+ "input": "&cupcap",
+ "description": "Bad named entity: cupcap without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&cupcap"
+ ]
+ ]
+ },
+ {
+ "input": "&cupcap;",
+ "description": "Named entity: cupcap; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a46"
+ ]
+ ]
+ },
+ {
+ "input": "&cupcup",
+ "description": "Bad named entity: cupcup without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&cupcup"
+ ]
+ ]
+ },
+ {
+ "input": "&cupcup;",
+ "description": "Named entity: cupcup; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a4a"
+ ]
+ ]
+ },
+ {
+ "input": "&cupdot",
+ "description": "Bad named entity: cupdot without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&cupdot"
+ ]
+ ]
+ },
+ {
+ "input": "&cupdot;",
+ "description": "Named entity: cupdot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u228d"
+ ]
+ ]
+ },
+ {
+ "input": "&cupor",
+ "description": "Bad named entity: cupor without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&cupor"
+ ]
+ ]
+ },
+ {
+ "input": "&cupor;",
+ "description": "Named entity: cupor; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a45"
+ ]
+ ]
+ },
+ {
+ "input": "&cups",
+ "description": "Bad named entity: cups without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&cups"
+ ]
+ ]
+ },
+ {
+ "input": "&cups;",
+ "description": "Named entity: cups; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u222a\ufe00"
+ ]
+ ]
+ },
+ {
+ "input": "&curarr",
+ "description": "Bad named entity: curarr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&curarr"
+ ]
+ ]
+ },
+ {
+ "input": "&curarr;",
+ "description": "Named entity: curarr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21b7"
+ ]
+ ]
+ },
+ {
+ "input": "&curarrm",
+ "description": "Bad named entity: curarrm without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&curarrm"
+ ]
+ ]
+ },
+ {
+ "input": "&curarrm;",
+ "description": "Named entity: curarrm; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u293c"
+ ]
+ ]
+ },
+ {
+ "input": "&curlyeqprec",
+ "description": "Bad named entity: curlyeqprec without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&curlyeqprec"
+ ]
+ ]
+ },
+ {
+ "input": "&curlyeqprec;",
+ "description": "Named entity: curlyeqprec; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22de"
+ ]
+ ]
+ },
+ {
+ "input": "&curlyeqsucc",
+ "description": "Bad named entity: curlyeqsucc without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&curlyeqsucc"
+ ]
+ ]
+ },
+ {
+ "input": "&curlyeqsucc;",
+ "description": "Named entity: curlyeqsucc; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22df"
+ ]
+ ]
+ },
+ {
+ "input": "&curlyvee",
+ "description": "Bad named entity: curlyvee without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&curlyvee"
+ ]
+ ]
+ },
+ {
+ "input": "&curlyvee;",
+ "description": "Named entity: curlyvee; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22ce"
+ ]
+ ]
+ },
+ {
+ "input": "&curlywedge",
+ "description": "Bad named entity: curlywedge without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&curlywedge"
+ ]
+ ]
+ },
+ {
+ "input": "&curlywedge;",
+ "description": "Named entity: curlywedge; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22cf"
+ ]
+ ]
+ },
+ {
+ "input": "&curren",
+ "description": "Named entity: curren without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00a4"
+ ]
+ ]
+ },
+ {
+ "input": "&curren;",
+ "description": "Named entity: curren; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00a4"
+ ]
+ ]
+ },
+ {
+ "input": "&curvearrowleft",
+ "description": "Bad named entity: curvearrowleft without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&curvearrowleft"
+ ]
+ ]
+ },
+ {
+ "input": "&curvearrowleft;",
+ "description": "Named entity: curvearrowleft; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21b6"
+ ]
+ ]
+ },
+ {
+ "input": "&curvearrowright",
+ "description": "Bad named entity: curvearrowright without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&curvearrowright"
+ ]
+ ]
+ },
+ {
+ "input": "&curvearrowright;",
+ "description": "Named entity: curvearrowright; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21b7"
+ ]
+ ]
+ },
+ {
+ "input": "&cuvee",
+ "description": "Bad named entity: cuvee without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&cuvee"
+ ]
+ ]
+ },
+ {
+ "input": "&cuvee;",
+ "description": "Named entity: cuvee; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22ce"
+ ]
+ ]
+ },
+ {
+ "input": "&cuwed",
+ "description": "Bad named entity: cuwed without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&cuwed"
+ ]
+ ]
+ },
+ {
+ "input": "&cuwed;",
+ "description": "Named entity: cuwed; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22cf"
+ ]
+ ]
+ },
+ {
+ "input": "&cwconint",
+ "description": "Bad named entity: cwconint without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&cwconint"
+ ]
+ ]
+ },
+ {
+ "input": "&cwconint;",
+ "description": "Named entity: cwconint; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2232"
+ ]
+ ]
+ },
+ {
+ "input": "&cwint",
+ "description": "Bad named entity: cwint without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&cwint"
+ ]
+ ]
+ },
+ {
+ "input": "&cwint;",
+ "description": "Named entity: cwint; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2231"
+ ]
+ ]
+ },
+ {
+ "input": "&cylcty",
+ "description": "Bad named entity: cylcty without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&cylcty"
+ ]
+ ]
+ },
+ {
+ "input": "&cylcty;",
+ "description": "Named entity: cylcty; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u232d"
+ ]
+ ]
+ },
+ {
+ "input": "&dArr",
+ "description": "Bad named entity: dArr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&dArr"
+ ]
+ ]
+ },
+ {
+ "input": "&dArr;",
+ "description": "Named entity: dArr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21d3"
+ ]
+ ]
+ },
+ {
+ "input": "&dHar",
+ "description": "Bad named entity: dHar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&dHar"
+ ]
+ ]
+ },
+ {
+ "input": "&dHar;",
+ "description": "Named entity: dHar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2965"
+ ]
+ ]
+ },
+ {
+ "input": "&dagger",
+ "description": "Bad named entity: dagger without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&dagger"
+ ]
+ ]
+ },
+ {
+ "input": "&dagger;",
+ "description": "Named entity: dagger; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2020"
+ ]
+ ]
+ },
+ {
+ "input": "&daleth",
+ "description": "Bad named entity: daleth without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&daleth"
+ ]
+ ]
+ },
+ {
+ "input": "&daleth;",
+ "description": "Named entity: daleth; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2138"
+ ]
+ ]
+ },
+ {
+ "input": "&darr",
+ "description": "Bad named entity: darr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&darr"
+ ]
+ ]
+ },
+ {
+ "input": "&darr;",
+ "description": "Named entity: darr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2193"
+ ]
+ ]
+ },
+ {
+ "input": "&dash",
+ "description": "Bad named entity: dash without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&dash"
+ ]
+ ]
+ },
+ {
+ "input": "&dash;",
+ "description": "Named entity: dash; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2010"
+ ]
+ ]
+ },
+ {
+ "input": "&dashv",
+ "description": "Bad named entity: dashv without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&dashv"
+ ]
+ ]
+ },
+ {
+ "input": "&dashv;",
+ "description": "Named entity: dashv; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22a3"
+ ]
+ ]
+ },
+ {
+ "input": "&dbkarow",
+ "description": "Bad named entity: dbkarow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&dbkarow"
+ ]
+ ]
+ },
+ {
+ "input": "&dbkarow;",
+ "description": "Named entity: dbkarow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u290f"
+ ]
+ ]
+ },
+ {
+ "input": "&dblac",
+ "description": "Bad named entity: dblac without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&dblac"
+ ]
+ ]
+ },
+ {
+ "input": "&dblac;",
+ "description": "Named entity: dblac; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u02dd"
+ ]
+ ]
+ },
+ {
+ "input": "&dcaron",
+ "description": "Bad named entity: dcaron without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&dcaron"
+ ]
+ ]
+ },
+ {
+ "input": "&dcaron;",
+ "description": "Named entity: dcaron; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u010f"
+ ]
+ ]
+ },
+ {
+ "input": "&dcy",
+ "description": "Bad named entity: dcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&dcy"
+ ]
+ ]
+ },
+ {
+ "input": "&dcy;",
+ "description": "Named entity: dcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0434"
+ ]
+ ]
+ },
+ {
+ "input": "&dd",
+ "description": "Bad named entity: dd without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&dd"
+ ]
+ ]
+ },
+ {
+ "input": "&dd;",
+ "description": "Named entity: dd; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2146"
+ ]
+ ]
+ },
+ {
+ "input": "&ddagger",
+ "description": "Bad named entity: ddagger without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ddagger"
+ ]
+ ]
+ },
+ {
+ "input": "&ddagger;",
+ "description": "Named entity: ddagger; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2021"
+ ]
+ ]
+ },
+ {
+ "input": "&ddarr",
+ "description": "Bad named entity: ddarr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ddarr"
+ ]
+ ]
+ },
+ {
+ "input": "&ddarr;",
+ "description": "Named entity: ddarr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21ca"
+ ]
+ ]
+ },
+ {
+ "input": "&ddotseq",
+ "description": "Bad named entity: ddotseq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ddotseq"
+ ]
+ ]
+ },
+ {
+ "input": "&ddotseq;",
+ "description": "Named entity: ddotseq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a77"
+ ]
+ ]
+ },
+ {
+ "input": "&deg",
+ "description": "Named entity: deg without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00b0"
+ ]
+ ]
+ },
+ {
+ "input": "&deg;",
+ "description": "Named entity: deg; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00b0"
+ ]
+ ]
+ },
+ {
+ "input": "&delta",
+ "description": "Bad named entity: delta without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&delta"
+ ]
+ ]
+ },
+ {
+ "input": "&delta;",
+ "description": "Named entity: delta; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03b4"
+ ]
+ ]
+ },
+ {
+ "input": "&demptyv",
+ "description": "Bad named entity: demptyv without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&demptyv"
+ ]
+ ]
+ },
+ {
+ "input": "&demptyv;",
+ "description": "Named entity: demptyv; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u29b1"
+ ]
+ ]
+ },
+ {
+ "input": "&dfisht",
+ "description": "Bad named entity: dfisht without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&dfisht"
+ ]
+ ]
+ },
+ {
+ "input": "&dfisht;",
+ "description": "Named entity: dfisht; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u297f"
+ ]
+ ]
+ },
+ {
+ "input": "&dfr",
+ "description": "Bad named entity: dfr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&dfr"
+ ]
+ ]
+ },
+ {
+ "input": "&dfr;",
+ "description": "Named entity: dfr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd21"
+ ]
+ ]
+ },
+ {
+ "input": "&dharl",
+ "description": "Bad named entity: dharl without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&dharl"
+ ]
+ ]
+ },
+ {
+ "input": "&dharl;",
+ "description": "Named entity: dharl; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21c3"
+ ]
+ ]
+ },
+ {
+ "input": "&dharr",
+ "description": "Bad named entity: dharr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&dharr"
+ ]
+ ]
+ },
+ {
+ "input": "&dharr;",
+ "description": "Named entity: dharr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21c2"
+ ]
+ ]
+ },
+ {
+ "input": "&diam",
+ "description": "Bad named entity: diam without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&diam"
+ ]
+ ]
+ },
+ {
+ "input": "&diam;",
+ "description": "Named entity: diam; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22c4"
+ ]
+ ]
+ },
+ {
+ "input": "&diamond",
+ "description": "Bad named entity: diamond without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&diamond"
+ ]
+ ]
+ },
+ {
+ "input": "&diamond;",
+ "description": "Named entity: diamond; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22c4"
+ ]
+ ]
+ },
+ {
+ "input": "&diamondsuit",
+ "description": "Bad named entity: diamondsuit without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&diamondsuit"
+ ]
+ ]
+ },
+ {
+ "input": "&diamondsuit;",
+ "description": "Named entity: diamondsuit; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2666"
+ ]
+ ]
+ },
+ {
+ "input": "&diams",
+ "description": "Bad named entity: diams without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&diams"
+ ]
+ ]
+ },
+ {
+ "input": "&diams;",
+ "description": "Named entity: diams; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2666"
+ ]
+ ]
+ },
+ {
+ "input": "&die",
+ "description": "Bad named entity: die without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&die"
+ ]
+ ]
+ },
+ {
+ "input": "&die;",
+ "description": "Named entity: die; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00a8"
+ ]
+ ]
+ },
+ {
+ "input": "&digamma",
+ "description": "Bad named entity: digamma without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&digamma"
+ ]
+ ]
+ },
+ {
+ "input": "&digamma;",
+ "description": "Named entity: digamma; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03dd"
+ ]
+ ]
+ },
+ {
+ "input": "&disin",
+ "description": "Bad named entity: disin without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&disin"
+ ]
+ ]
+ },
+ {
+ "input": "&disin;",
+ "description": "Named entity: disin; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22f2"
+ ]
+ ]
+ },
+ {
+ "input": "&div",
+ "description": "Bad named entity: div without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&div"
+ ]
+ ]
+ },
+ {
+ "input": "&div;",
+ "description": "Named entity: div; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00f7"
+ ]
+ ]
+ },
+ {
+ "input": "&divide",
+ "description": "Named entity: divide without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00f7"
+ ]
+ ]
+ },
+ {
+ "input": "&divide;",
+ "description": "Named entity: divide; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00f7"
+ ]
+ ]
+ },
+ {
+ "input": "&divideontimes;",
+ "description": "Named entity: divideontimes; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22c7"
+ ]
+ ]
+ },
+ {
+ "input": "&divonx",
+ "description": "Bad named entity: divonx without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&divonx"
+ ]
+ ]
+ },
+ {
+ "input": "&divonx;",
+ "description": "Named entity: divonx; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22c7"
+ ]
+ ]
+ },
+ {
+ "input": "&djcy",
+ "description": "Bad named entity: djcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&djcy"
+ ]
+ ]
+ },
+ {
+ "input": "&djcy;",
+ "description": "Named entity: djcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0452"
+ ]
+ ]
+ },
+ {
+ "input": "&dlcorn",
+ "description": "Bad named entity: dlcorn without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&dlcorn"
+ ]
+ ]
+ },
+ {
+ "input": "&dlcorn;",
+ "description": "Named entity: dlcorn; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u231e"
+ ]
+ ]
+ },
+ {
+ "input": "&dlcrop",
+ "description": "Bad named entity: dlcrop without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&dlcrop"
+ ]
+ ]
+ },
+ {
+ "input": "&dlcrop;",
+ "description": "Named entity: dlcrop; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u230d"
+ ]
+ ]
+ },
+ {
+ "input": "&dollar",
+ "description": "Bad named entity: dollar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&dollar"
+ ]
+ ]
+ },
+ {
+ "input": "&dollar;",
+ "description": "Named entity: dollar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "$"
+ ]
+ ]
+ },
+ {
+ "input": "&dopf",
+ "description": "Bad named entity: dopf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&dopf"
+ ]
+ ]
+ },
+ {
+ "input": "&dopf;",
+ "description": "Named entity: dopf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd55"
+ ]
+ ]
+ },
+ {
+ "input": "&dot",
+ "description": "Bad named entity: dot without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&dot"
+ ]
+ ]
+ },
+ {
+ "input": "&dot;",
+ "description": "Named entity: dot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u02d9"
+ ]
+ ]
+ },
+ {
+ "input": "&doteq",
+ "description": "Bad named entity: doteq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&doteq"
+ ]
+ ]
+ },
+ {
+ "input": "&doteq;",
+ "description": "Named entity: doteq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2250"
+ ]
+ ]
+ },
+ {
+ "input": "&doteqdot",
+ "description": "Bad named entity: doteqdot without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&doteqdot"
+ ]
+ ]
+ },
+ {
+ "input": "&doteqdot;",
+ "description": "Named entity: doteqdot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2251"
+ ]
+ ]
+ },
+ {
+ "input": "&dotminus",
+ "description": "Bad named entity: dotminus without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&dotminus"
+ ]
+ ]
+ },
+ {
+ "input": "&dotminus;",
+ "description": "Named entity: dotminus; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2238"
+ ]
+ ]
+ },
+ {
+ "input": "&dotplus",
+ "description": "Bad named entity: dotplus without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&dotplus"
+ ]
+ ]
+ },
+ {
+ "input": "&dotplus;",
+ "description": "Named entity: dotplus; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2214"
+ ]
+ ]
+ },
+ {
+ "input": "&dotsquare",
+ "description": "Bad named entity: dotsquare without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&dotsquare"
+ ]
+ ]
+ },
+ {
+ "input": "&dotsquare;",
+ "description": "Named entity: dotsquare; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22a1"
+ ]
+ ]
+ },
+ {
+ "input": "&doublebarwedge",
+ "description": "Bad named entity: doublebarwedge without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&doublebarwedge"
+ ]
+ ]
+ },
+ {
+ "input": "&doublebarwedge;",
+ "description": "Named entity: doublebarwedge; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2306"
+ ]
+ ]
+ },
+ {
+ "input": "&downarrow",
+ "description": "Bad named entity: downarrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&downarrow"
+ ]
+ ]
+ },
+ {
+ "input": "&downarrow;",
+ "description": "Named entity: downarrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2193"
+ ]
+ ]
+ },
+ {
+ "input": "&downdownarrows",
+ "description": "Bad named entity: downdownarrows without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&downdownarrows"
+ ]
+ ]
+ },
+ {
+ "input": "&downdownarrows;",
+ "description": "Named entity: downdownarrows; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21ca"
+ ]
+ ]
+ },
+ {
+ "input": "&downharpoonleft",
+ "description": "Bad named entity: downharpoonleft without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&downharpoonleft"
+ ]
+ ]
+ },
+ {
+ "input": "&downharpoonleft;",
+ "description": "Named entity: downharpoonleft; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21c3"
+ ]
+ ]
+ },
+ {
+ "input": "&downharpoonright",
+ "description": "Bad named entity: downharpoonright without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&downharpoonright"
+ ]
+ ]
+ },
+ {
+ "input": "&downharpoonright;",
+ "description": "Named entity: downharpoonright; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21c2"
+ ]
+ ]
+ },
+ {
+ "input": "&drbkarow",
+ "description": "Bad named entity: drbkarow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&drbkarow"
+ ]
+ ]
+ },
+ {
+ "input": "&drbkarow;",
+ "description": "Named entity: drbkarow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2910"
+ ]
+ ]
+ },
+ {
+ "input": "&drcorn",
+ "description": "Bad named entity: drcorn without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&drcorn"
+ ]
+ ]
+ },
+ {
+ "input": "&drcorn;",
+ "description": "Named entity: drcorn; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u231f"
+ ]
+ ]
+ },
+ {
+ "input": "&drcrop",
+ "description": "Bad named entity: drcrop without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&drcrop"
+ ]
+ ]
+ },
+ {
+ "input": "&drcrop;",
+ "description": "Named entity: drcrop; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u230c"
+ ]
+ ]
+ },
+ {
+ "input": "&dscr",
+ "description": "Bad named entity: dscr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&dscr"
+ ]
+ ]
+ },
+ {
+ "input": "&dscr;",
+ "description": "Named entity: dscr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udcb9"
+ ]
+ ]
+ },
+ {
+ "input": "&dscy",
+ "description": "Bad named entity: dscy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&dscy"
+ ]
+ ]
+ },
+ {
+ "input": "&dscy;",
+ "description": "Named entity: dscy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0455"
+ ]
+ ]
+ },
+ {
+ "input": "&dsol",
+ "description": "Bad named entity: dsol without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&dsol"
+ ]
+ ]
+ },
+ {
+ "input": "&dsol;",
+ "description": "Named entity: dsol; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u29f6"
+ ]
+ ]
+ },
+ {
+ "input": "&dstrok",
+ "description": "Bad named entity: dstrok without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&dstrok"
+ ]
+ ]
+ },
+ {
+ "input": "&dstrok;",
+ "description": "Named entity: dstrok; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0111"
+ ]
+ ]
+ },
+ {
+ "input": "&dtdot",
+ "description": "Bad named entity: dtdot without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&dtdot"
+ ]
+ ]
+ },
+ {
+ "input": "&dtdot;",
+ "description": "Named entity: dtdot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22f1"
+ ]
+ ]
+ },
+ {
+ "input": "&dtri",
+ "description": "Bad named entity: dtri without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&dtri"
+ ]
+ ]
+ },
+ {
+ "input": "&dtri;",
+ "description": "Named entity: dtri; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u25bf"
+ ]
+ ]
+ },
+ {
+ "input": "&dtrif",
+ "description": "Bad named entity: dtrif without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&dtrif"
+ ]
+ ]
+ },
+ {
+ "input": "&dtrif;",
+ "description": "Named entity: dtrif; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u25be"
+ ]
+ ]
+ },
+ {
+ "input": "&duarr",
+ "description": "Bad named entity: duarr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&duarr"
+ ]
+ ]
+ },
+ {
+ "input": "&duarr;",
+ "description": "Named entity: duarr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21f5"
+ ]
+ ]
+ },
+ {
+ "input": "&duhar",
+ "description": "Bad named entity: duhar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&duhar"
+ ]
+ ]
+ },
+ {
+ "input": "&duhar;",
+ "description": "Named entity: duhar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u296f"
+ ]
+ ]
+ },
+ {
+ "input": "&dwangle",
+ "description": "Bad named entity: dwangle without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&dwangle"
+ ]
+ ]
+ },
+ {
+ "input": "&dwangle;",
+ "description": "Named entity: dwangle; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u29a6"
+ ]
+ ]
+ },
+ {
+ "input": "&dzcy",
+ "description": "Bad named entity: dzcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&dzcy"
+ ]
+ ]
+ },
+ {
+ "input": "&dzcy;",
+ "description": "Named entity: dzcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u045f"
+ ]
+ ]
+ },
+ {
+ "input": "&dzigrarr",
+ "description": "Bad named entity: dzigrarr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&dzigrarr"
+ ]
+ ]
+ },
+ {
+ "input": "&dzigrarr;",
+ "description": "Named entity: dzigrarr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u27ff"
+ ]
+ ]
+ },
+ {
+ "input": "&eDDot",
+ "description": "Bad named entity: eDDot without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&eDDot"
+ ]
+ ]
+ },
+ {
+ "input": "&eDDot;",
+ "description": "Named entity: eDDot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a77"
+ ]
+ ]
+ },
+ {
+ "input": "&eDot",
+ "description": "Bad named entity: eDot without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&eDot"
+ ]
+ ]
+ },
+ {
+ "input": "&eDot;",
+ "description": "Named entity: eDot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2251"
+ ]
+ ]
+ },
+ {
+ "input": "&eacute",
+ "description": "Named entity: eacute without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00e9"
+ ]
+ ]
+ },
+ {
+ "input": "&eacute;",
+ "description": "Named entity: eacute; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00e9"
+ ]
+ ]
+ },
+ {
+ "input": "&easter",
+ "description": "Bad named entity: easter without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&easter"
+ ]
+ ]
+ },
+ {
+ "input": "&easter;",
+ "description": "Named entity: easter; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a6e"
+ ]
+ ]
+ },
+ {
+ "input": "&ecaron",
+ "description": "Bad named entity: ecaron without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ecaron"
+ ]
+ ]
+ },
+ {
+ "input": "&ecaron;",
+ "description": "Named entity: ecaron; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u011b"
+ ]
+ ]
+ },
+ {
+ "input": "&ecir",
+ "description": "Bad named entity: ecir without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ecir"
+ ]
+ ]
+ },
+ {
+ "input": "&ecir;",
+ "description": "Named entity: ecir; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2256"
+ ]
+ ]
+ },
+ {
+ "input": "&ecirc",
+ "description": "Named entity: ecirc without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00ea"
+ ]
+ ]
+ },
+ {
+ "input": "&ecirc;",
+ "description": "Named entity: ecirc; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00ea"
+ ]
+ ]
+ },
+ {
+ "input": "&ecolon",
+ "description": "Bad named entity: ecolon without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ecolon"
+ ]
+ ]
+ },
+ {
+ "input": "&ecolon;",
+ "description": "Named entity: ecolon; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2255"
+ ]
+ ]
+ },
+ {
+ "input": "&ecy",
+ "description": "Bad named entity: ecy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ecy"
+ ]
+ ]
+ },
+ {
+ "input": "&ecy;",
+ "description": "Named entity: ecy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u044d"
+ ]
+ ]
+ },
+ {
+ "input": "&edot",
+ "description": "Bad named entity: edot without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&edot"
+ ]
+ ]
+ },
+ {
+ "input": "&edot;",
+ "description": "Named entity: edot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0117"
+ ]
+ ]
+ },
+ {
+ "input": "&ee",
+ "description": "Bad named entity: ee without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ee"
+ ]
+ ]
+ },
+ {
+ "input": "&ee;",
+ "description": "Named entity: ee; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2147"
+ ]
+ ]
+ },
+ {
+ "input": "&efDot",
+ "description": "Bad named entity: efDot without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&efDot"
+ ]
+ ]
+ },
+ {
+ "input": "&efDot;",
+ "description": "Named entity: efDot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2252"
+ ]
+ ]
+ },
+ {
+ "input": "&efr",
+ "description": "Bad named entity: efr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&efr"
+ ]
+ ]
+ },
+ {
+ "input": "&efr;",
+ "description": "Named entity: efr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd22"
+ ]
+ ]
+ },
+ {
+ "input": "&eg",
+ "description": "Bad named entity: eg without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&eg"
+ ]
+ ]
+ },
+ {
+ "input": "&eg;",
+ "description": "Named entity: eg; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a9a"
+ ]
+ ]
+ },
+ {
+ "input": "&egrave",
+ "description": "Named entity: egrave without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00e8"
+ ]
+ ]
+ },
+ {
+ "input": "&egrave;",
+ "description": "Named entity: egrave; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00e8"
+ ]
+ ]
+ },
+ {
+ "input": "&egs",
+ "description": "Bad named entity: egs without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&egs"
+ ]
+ ]
+ },
+ {
+ "input": "&egs;",
+ "description": "Named entity: egs; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a96"
+ ]
+ ]
+ },
+ {
+ "input": "&egsdot",
+ "description": "Bad named entity: egsdot without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&egsdot"
+ ]
+ ]
+ },
+ {
+ "input": "&egsdot;",
+ "description": "Named entity: egsdot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a98"
+ ]
+ ]
+ },
+ {
+ "input": "&el",
+ "description": "Bad named entity: el without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&el"
+ ]
+ ]
+ },
+ {
+ "input": "&el;",
+ "description": "Named entity: el; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a99"
+ ]
+ ]
+ },
+ {
+ "input": "&elinters",
+ "description": "Bad named entity: elinters without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&elinters"
+ ]
+ ]
+ },
+ {
+ "input": "&elinters;",
+ "description": "Named entity: elinters; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u23e7"
+ ]
+ ]
+ },
+ {
+ "input": "&ell",
+ "description": "Bad named entity: ell without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ell"
+ ]
+ ]
+ },
+ {
+ "input": "&ell;",
+ "description": "Named entity: ell; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2113"
+ ]
+ ]
+ },
+ {
+ "input": "&els",
+ "description": "Bad named entity: els without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&els"
+ ]
+ ]
+ },
+ {
+ "input": "&els;",
+ "description": "Named entity: els; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a95"
+ ]
+ ]
+ },
+ {
+ "input": "&elsdot",
+ "description": "Bad named entity: elsdot without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&elsdot"
+ ]
+ ]
+ },
+ {
+ "input": "&elsdot;",
+ "description": "Named entity: elsdot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a97"
+ ]
+ ]
+ },
+ {
+ "input": "&emacr",
+ "description": "Bad named entity: emacr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&emacr"
+ ]
+ ]
+ },
+ {
+ "input": "&emacr;",
+ "description": "Named entity: emacr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0113"
+ ]
+ ]
+ },
+ {
+ "input": "&empty",
+ "description": "Bad named entity: empty without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&empty"
+ ]
+ ]
+ },
+ {
+ "input": "&empty;",
+ "description": "Named entity: empty; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2205"
+ ]
+ ]
+ },
+ {
+ "input": "&emptyset",
+ "description": "Bad named entity: emptyset without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&emptyset"
+ ]
+ ]
+ },
+ {
+ "input": "&emptyset;",
+ "description": "Named entity: emptyset; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2205"
+ ]
+ ]
+ },
+ {
+ "input": "&emptyv",
+ "description": "Bad named entity: emptyv without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&emptyv"
+ ]
+ ]
+ },
+ {
+ "input": "&emptyv;",
+ "description": "Named entity: emptyv; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2205"
+ ]
+ ]
+ },
+ {
+ "input": "&emsp",
+ "description": "Bad named entity: emsp without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&emsp"
+ ]
+ ]
+ },
+ {
+ "input": "&emsp13",
+ "description": "Bad named entity: emsp13 without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&emsp13"
+ ]
+ ]
+ },
+ {
+ "input": "&emsp13;",
+ "description": "Named entity: emsp13; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2004"
+ ]
+ ]
+ },
+ {
+ "input": "&emsp14",
+ "description": "Bad named entity: emsp14 without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&emsp14"
+ ]
+ ]
+ },
+ {
+ "input": "&emsp14;",
+ "description": "Named entity: emsp14; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2005"
+ ]
+ ]
+ },
+ {
+ "input": "&emsp;",
+ "description": "Named entity: emsp; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2003"
+ ]
+ ]
+ },
+ {
+ "input": "&eng",
+ "description": "Bad named entity: eng without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&eng"
+ ]
+ ]
+ },
+ {
+ "input": "&eng;",
+ "description": "Named entity: eng; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u014b"
+ ]
+ ]
+ },
+ {
+ "input": "&ensp",
+ "description": "Bad named entity: ensp without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ensp"
+ ]
+ ]
+ },
+ {
+ "input": "&ensp;",
+ "description": "Named entity: ensp; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2002"
+ ]
+ ]
+ },
+ {
+ "input": "&eogon",
+ "description": "Bad named entity: eogon without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&eogon"
+ ]
+ ]
+ },
+ {
+ "input": "&eogon;",
+ "description": "Named entity: eogon; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0119"
+ ]
+ ]
+ },
+ {
+ "input": "&eopf",
+ "description": "Bad named entity: eopf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&eopf"
+ ]
+ ]
+ },
+ {
+ "input": "&eopf;",
+ "description": "Named entity: eopf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd56"
+ ]
+ ]
+ },
+ {
+ "input": "&epar",
+ "description": "Bad named entity: epar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&epar"
+ ]
+ ]
+ },
+ {
+ "input": "&epar;",
+ "description": "Named entity: epar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22d5"
+ ]
+ ]
+ },
+ {
+ "input": "&eparsl",
+ "description": "Bad named entity: eparsl without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&eparsl"
+ ]
+ ]
+ },
+ {
+ "input": "&eparsl;",
+ "description": "Named entity: eparsl; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u29e3"
+ ]
+ ]
+ },
+ {
+ "input": "&eplus",
+ "description": "Bad named entity: eplus without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&eplus"
+ ]
+ ]
+ },
+ {
+ "input": "&eplus;",
+ "description": "Named entity: eplus; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a71"
+ ]
+ ]
+ },
+ {
+ "input": "&epsi",
+ "description": "Bad named entity: epsi without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&epsi"
+ ]
+ ]
+ },
+ {
+ "input": "&epsi;",
+ "description": "Named entity: epsi; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03b5"
+ ]
+ ]
+ },
+ {
+ "input": "&epsilon",
+ "description": "Bad named entity: epsilon without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&epsilon"
+ ]
+ ]
+ },
+ {
+ "input": "&epsilon;",
+ "description": "Named entity: epsilon; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03b5"
+ ]
+ ]
+ },
+ {
+ "input": "&epsiv",
+ "description": "Bad named entity: epsiv without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&epsiv"
+ ]
+ ]
+ },
+ {
+ "input": "&epsiv;",
+ "description": "Named entity: epsiv; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03f5"
+ ]
+ ]
+ },
+ {
+ "input": "&eqcirc",
+ "description": "Bad named entity: eqcirc without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&eqcirc"
+ ]
+ ]
+ },
+ {
+ "input": "&eqcirc;",
+ "description": "Named entity: eqcirc; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2256"
+ ]
+ ]
+ },
+ {
+ "input": "&eqcolon",
+ "description": "Bad named entity: eqcolon without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&eqcolon"
+ ]
+ ]
+ },
+ {
+ "input": "&eqcolon;",
+ "description": "Named entity: eqcolon; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2255"
+ ]
+ ]
+ },
+ {
+ "input": "&eqsim",
+ "description": "Bad named entity: eqsim without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&eqsim"
+ ]
+ ]
+ },
+ {
+ "input": "&eqsim;",
+ "description": "Named entity: eqsim; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2242"
+ ]
+ ]
+ },
+ {
+ "input": "&eqslantgtr",
+ "description": "Bad named entity: eqslantgtr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&eqslantgtr"
+ ]
+ ]
+ },
+ {
+ "input": "&eqslantgtr;",
+ "description": "Named entity: eqslantgtr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a96"
+ ]
+ ]
+ },
+ {
+ "input": "&eqslantless",
+ "description": "Bad named entity: eqslantless without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&eqslantless"
+ ]
+ ]
+ },
+ {
+ "input": "&eqslantless;",
+ "description": "Named entity: eqslantless; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a95"
+ ]
+ ]
+ },
+ {
+ "input": "&equals",
+ "description": "Bad named entity: equals without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&equals"
+ ]
+ ]
+ },
+ {
+ "input": "&equals;",
+ "description": "Named entity: equals; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "="
+ ]
+ ]
+ },
+ {
+ "input": "&equest",
+ "description": "Bad named entity: equest without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&equest"
+ ]
+ ]
+ },
+ {
+ "input": "&equest;",
+ "description": "Named entity: equest; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u225f"
+ ]
+ ]
+ },
+ {
+ "input": "&equiv",
+ "description": "Bad named entity: equiv without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&equiv"
+ ]
+ ]
+ },
+ {
+ "input": "&equiv;",
+ "description": "Named entity: equiv; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2261"
+ ]
+ ]
+ },
+ {
+ "input": "&equivDD",
+ "description": "Bad named entity: equivDD without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&equivDD"
+ ]
+ ]
+ },
+ {
+ "input": "&equivDD;",
+ "description": "Named entity: equivDD; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a78"
+ ]
+ ]
+ },
+ {
+ "input": "&eqvparsl",
+ "description": "Bad named entity: eqvparsl without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&eqvparsl"
+ ]
+ ]
+ },
+ {
+ "input": "&eqvparsl;",
+ "description": "Named entity: eqvparsl; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u29e5"
+ ]
+ ]
+ },
+ {
+ "input": "&erDot",
+ "description": "Bad named entity: erDot without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&erDot"
+ ]
+ ]
+ },
+ {
+ "input": "&erDot;",
+ "description": "Named entity: erDot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2253"
+ ]
+ ]
+ },
+ {
+ "input": "&erarr",
+ "description": "Bad named entity: erarr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&erarr"
+ ]
+ ]
+ },
+ {
+ "input": "&erarr;",
+ "description": "Named entity: erarr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2971"
+ ]
+ ]
+ },
+ {
+ "input": "&escr",
+ "description": "Bad named entity: escr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&escr"
+ ]
+ ]
+ },
+ {
+ "input": "&escr;",
+ "description": "Named entity: escr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u212f"
+ ]
+ ]
+ },
+ {
+ "input": "&esdot",
+ "description": "Bad named entity: esdot without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&esdot"
+ ]
+ ]
+ },
+ {
+ "input": "&esdot;",
+ "description": "Named entity: esdot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2250"
+ ]
+ ]
+ },
+ {
+ "input": "&esim",
+ "description": "Bad named entity: esim without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&esim"
+ ]
+ ]
+ },
+ {
+ "input": "&esim;",
+ "description": "Named entity: esim; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2242"
+ ]
+ ]
+ },
+ {
+ "input": "&eta",
+ "description": "Bad named entity: eta without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&eta"
+ ]
+ ]
+ },
+ {
+ "input": "&eta;",
+ "description": "Named entity: eta; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03b7"
+ ]
+ ]
+ },
+ {
+ "input": "&eth",
+ "description": "Named entity: eth without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00f0"
+ ]
+ ]
+ },
+ {
+ "input": "&eth;",
+ "description": "Named entity: eth; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00f0"
+ ]
+ ]
+ },
+ {
+ "input": "&euml",
+ "description": "Named entity: euml without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00eb"
+ ]
+ ]
+ },
+ {
+ "input": "&euml;",
+ "description": "Named entity: euml; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00eb"
+ ]
+ ]
+ },
+ {
+ "input": "&euro",
+ "description": "Bad named entity: euro without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&euro"
+ ]
+ ]
+ },
+ {
+ "input": "&euro;",
+ "description": "Named entity: euro; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u20ac"
+ ]
+ ]
+ },
+ {
+ "input": "&excl",
+ "description": "Bad named entity: excl without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&excl"
+ ]
+ ]
+ },
+ {
+ "input": "&excl;",
+ "description": "Named entity: excl; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "!"
+ ]
+ ]
+ },
+ {
+ "input": "&exist",
+ "description": "Bad named entity: exist without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&exist"
+ ]
+ ]
+ },
+ {
+ "input": "&exist;",
+ "description": "Named entity: exist; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2203"
+ ]
+ ]
+ },
+ {
+ "input": "&expectation",
+ "description": "Bad named entity: expectation without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&expectation"
+ ]
+ ]
+ },
+ {
+ "input": "&expectation;",
+ "description": "Named entity: expectation; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2130"
+ ]
+ ]
+ },
+ {
+ "input": "&exponentiale",
+ "description": "Bad named entity: exponentiale without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&exponentiale"
+ ]
+ ]
+ },
+ {
+ "input": "&exponentiale;",
+ "description": "Named entity: exponentiale; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2147"
+ ]
+ ]
+ },
+ {
+ "input": "&fallingdotseq",
+ "description": "Bad named entity: fallingdotseq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&fallingdotseq"
+ ]
+ ]
+ },
+ {
+ "input": "&fallingdotseq;",
+ "description": "Named entity: fallingdotseq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2252"
+ ]
+ ]
+ },
+ {
+ "input": "&fcy",
+ "description": "Bad named entity: fcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&fcy"
+ ]
+ ]
+ },
+ {
+ "input": "&fcy;",
+ "description": "Named entity: fcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0444"
+ ]
+ ]
+ },
+ {
+ "input": "&female",
+ "description": "Bad named entity: female without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&female"
+ ]
+ ]
+ },
+ {
+ "input": "&female;",
+ "description": "Named entity: female; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2640"
+ ]
+ ]
+ },
+ {
+ "input": "&ffilig",
+ "description": "Bad named entity: ffilig without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ffilig"
+ ]
+ ]
+ },
+ {
+ "input": "&ffilig;",
+ "description": "Named entity: ffilig; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ufb03"
+ ]
+ ]
+ },
+ {
+ "input": "&fflig",
+ "description": "Bad named entity: fflig without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&fflig"
+ ]
+ ]
+ },
+ {
+ "input": "&fflig;",
+ "description": "Named entity: fflig; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ufb00"
+ ]
+ ]
+ },
+ {
+ "input": "&ffllig",
+ "description": "Bad named entity: ffllig without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ffllig"
+ ]
+ ]
+ },
+ {
+ "input": "&ffllig;",
+ "description": "Named entity: ffllig; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ufb04"
+ ]
+ ]
+ },
+ {
+ "input": "&ffr",
+ "description": "Bad named entity: ffr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ffr"
+ ]
+ ]
+ },
+ {
+ "input": "&ffr;",
+ "description": "Named entity: ffr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd23"
+ ]
+ ]
+ },
+ {
+ "input": "&filig",
+ "description": "Bad named entity: filig without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&filig"
+ ]
+ ]
+ },
+ {
+ "input": "&filig;",
+ "description": "Named entity: filig; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ufb01"
+ ]
+ ]
+ },
+ {
+ "input": "&fjlig",
+ "description": "Bad named entity: fjlig without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&fjlig"
+ ]
+ ]
+ },
+ {
+ "input": "&fjlig;",
+ "description": "Named entity: fjlig; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "fj"
+ ]
+ ]
+ },
+ {
+ "input": "&flat",
+ "description": "Bad named entity: flat without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&flat"
+ ]
+ ]
+ },
+ {
+ "input": "&flat;",
+ "description": "Named entity: flat; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u266d"
+ ]
+ ]
+ },
+ {
+ "input": "&fllig",
+ "description": "Bad named entity: fllig without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&fllig"
+ ]
+ ]
+ },
+ {
+ "input": "&fllig;",
+ "description": "Named entity: fllig; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ufb02"
+ ]
+ ]
+ },
+ {
+ "input": "&fltns",
+ "description": "Bad named entity: fltns without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&fltns"
+ ]
+ ]
+ },
+ {
+ "input": "&fltns;",
+ "description": "Named entity: fltns; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u25b1"
+ ]
+ ]
+ },
+ {
+ "input": "&fnof",
+ "description": "Bad named entity: fnof without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&fnof"
+ ]
+ ]
+ },
+ {
+ "input": "&fnof;",
+ "description": "Named entity: fnof; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0192"
+ ]
+ ]
+ },
+ {
+ "input": "&fopf",
+ "description": "Bad named entity: fopf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&fopf"
+ ]
+ ]
+ },
+ {
+ "input": "&fopf;",
+ "description": "Named entity: fopf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd57"
+ ]
+ ]
+ },
+ {
+ "input": "&forall",
+ "description": "Bad named entity: forall without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&forall"
+ ]
+ ]
+ },
+ {
+ "input": "&forall;",
+ "description": "Named entity: forall; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2200"
+ ]
+ ]
+ },
+ {
+ "input": "&fork",
+ "description": "Bad named entity: fork without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&fork"
+ ]
+ ]
+ },
+ {
+ "input": "&fork;",
+ "description": "Named entity: fork; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22d4"
+ ]
+ ]
+ },
+ {
+ "input": "&forkv",
+ "description": "Bad named entity: forkv without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&forkv"
+ ]
+ ]
+ },
+ {
+ "input": "&forkv;",
+ "description": "Named entity: forkv; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2ad9"
+ ]
+ ]
+ },
+ {
+ "input": "&fpartint",
+ "description": "Bad named entity: fpartint without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&fpartint"
+ ]
+ ]
+ },
+ {
+ "input": "&fpartint;",
+ "description": "Named entity: fpartint; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a0d"
+ ]
+ ]
+ },
+ {
+ "input": "&frac12",
+ "description": "Named entity: frac12 without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00bd"
+ ]
+ ]
+ },
+ {
+ "input": "&frac12;",
+ "description": "Named entity: frac12; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00bd"
+ ]
+ ]
+ },
+ {
+ "input": "&frac13",
+ "description": "Bad named entity: frac13 without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&frac13"
+ ]
+ ]
+ },
+ {
+ "input": "&frac13;",
+ "description": "Named entity: frac13; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2153"
+ ]
+ ]
+ },
+ {
+ "input": "&frac14",
+ "description": "Named entity: frac14 without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00bc"
+ ]
+ ]
+ },
+ {
+ "input": "&frac14;",
+ "description": "Named entity: frac14; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00bc"
+ ]
+ ]
+ },
+ {
+ "input": "&frac15",
+ "description": "Bad named entity: frac15 without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&frac15"
+ ]
+ ]
+ },
+ {
+ "input": "&frac15;",
+ "description": "Named entity: frac15; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2155"
+ ]
+ ]
+ },
+ {
+ "input": "&frac16",
+ "description": "Bad named entity: frac16 without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&frac16"
+ ]
+ ]
+ },
+ {
+ "input": "&frac16;",
+ "description": "Named entity: frac16; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2159"
+ ]
+ ]
+ },
+ {
+ "input": "&frac18",
+ "description": "Bad named entity: frac18 without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&frac18"
+ ]
+ ]
+ },
+ {
+ "input": "&frac18;",
+ "description": "Named entity: frac18; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u215b"
+ ]
+ ]
+ },
+ {
+ "input": "&frac23",
+ "description": "Bad named entity: frac23 without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&frac23"
+ ]
+ ]
+ },
+ {
+ "input": "&frac23;",
+ "description": "Named entity: frac23; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2154"
+ ]
+ ]
+ },
+ {
+ "input": "&frac25",
+ "description": "Bad named entity: frac25 without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&frac25"
+ ]
+ ]
+ },
+ {
+ "input": "&frac25;",
+ "description": "Named entity: frac25; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2156"
+ ]
+ ]
+ },
+ {
+ "input": "&frac34",
+ "description": "Named entity: frac34 without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00be"
+ ]
+ ]
+ },
+ {
+ "input": "&frac34;",
+ "description": "Named entity: frac34; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00be"
+ ]
+ ]
+ },
+ {
+ "input": "&frac35",
+ "description": "Bad named entity: frac35 without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&frac35"
+ ]
+ ]
+ },
+ {
+ "input": "&frac35;",
+ "description": "Named entity: frac35; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2157"
+ ]
+ ]
+ },
+ {
+ "input": "&frac38",
+ "description": "Bad named entity: frac38 without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&frac38"
+ ]
+ ]
+ },
+ {
+ "input": "&frac38;",
+ "description": "Named entity: frac38; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u215c"
+ ]
+ ]
+ },
+ {
+ "input": "&frac45",
+ "description": "Bad named entity: frac45 without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&frac45"
+ ]
+ ]
+ },
+ {
+ "input": "&frac45;",
+ "description": "Named entity: frac45; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2158"
+ ]
+ ]
+ },
+ {
+ "input": "&frac56",
+ "description": "Bad named entity: frac56 without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&frac56"
+ ]
+ ]
+ },
+ {
+ "input": "&frac56;",
+ "description": "Named entity: frac56; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u215a"
+ ]
+ ]
+ },
+ {
+ "input": "&frac58",
+ "description": "Bad named entity: frac58 without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&frac58"
+ ]
+ ]
+ },
+ {
+ "input": "&frac58;",
+ "description": "Named entity: frac58; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u215d"
+ ]
+ ]
+ },
+ {
+ "input": "&frac78",
+ "description": "Bad named entity: frac78 without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&frac78"
+ ]
+ ]
+ },
+ {
+ "input": "&frac78;",
+ "description": "Named entity: frac78; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u215e"
+ ]
+ ]
+ },
+ {
+ "input": "&frasl",
+ "description": "Bad named entity: frasl without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&frasl"
+ ]
+ ]
+ },
+ {
+ "input": "&frasl;",
+ "description": "Named entity: frasl; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2044"
+ ]
+ ]
+ },
+ {
+ "input": "&frown",
+ "description": "Bad named entity: frown without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&frown"
+ ]
+ ]
+ },
+ {
+ "input": "&frown;",
+ "description": "Named entity: frown; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2322"
+ ]
+ ]
+ },
+ {
+ "input": "&fscr",
+ "description": "Bad named entity: fscr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&fscr"
+ ]
+ ]
+ },
+ {
+ "input": "&fscr;",
+ "description": "Named entity: fscr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udcbb"
+ ]
+ ]
+ },
+ {
+ "input": "&gE",
+ "description": "Bad named entity: gE without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&gE"
+ ]
+ ]
+ },
+ {
+ "input": "&gE;",
+ "description": "Named entity: gE; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2267"
+ ]
+ ]
+ },
+ {
+ "input": "&gEl",
+ "description": "Bad named entity: gEl without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&gEl"
+ ]
+ ]
+ },
+ {
+ "input": "&gEl;",
+ "description": "Named entity: gEl; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a8c"
+ ]
+ ]
+ },
+ {
+ "input": "&gacute",
+ "description": "Bad named entity: gacute without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&gacute"
+ ]
+ ]
+ },
+ {
+ "input": "&gacute;",
+ "description": "Named entity: gacute; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u01f5"
+ ]
+ ]
+ },
+ {
+ "input": "&gamma",
+ "description": "Bad named entity: gamma without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&gamma"
+ ]
+ ]
+ },
+ {
+ "input": "&gamma;",
+ "description": "Named entity: gamma; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03b3"
+ ]
+ ]
+ },
+ {
+ "input": "&gammad",
+ "description": "Bad named entity: gammad without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&gammad"
+ ]
+ ]
+ },
+ {
+ "input": "&gammad;",
+ "description": "Named entity: gammad; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03dd"
+ ]
+ ]
+ },
+ {
+ "input": "&gap",
+ "description": "Bad named entity: gap without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&gap"
+ ]
+ ]
+ },
+ {
+ "input": "&gap;",
+ "description": "Named entity: gap; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a86"
+ ]
+ ]
+ },
+ {
+ "input": "&gbreve",
+ "description": "Bad named entity: gbreve without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&gbreve"
+ ]
+ ]
+ },
+ {
+ "input": "&gbreve;",
+ "description": "Named entity: gbreve; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u011f"
+ ]
+ ]
+ },
+ {
+ "input": "&gcirc",
+ "description": "Bad named entity: gcirc without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&gcirc"
+ ]
+ ]
+ },
+ {
+ "input": "&gcirc;",
+ "description": "Named entity: gcirc; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u011d"
+ ]
+ ]
+ },
+ {
+ "input": "&gcy",
+ "description": "Bad named entity: gcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&gcy"
+ ]
+ ]
+ },
+ {
+ "input": "&gcy;",
+ "description": "Named entity: gcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0433"
+ ]
+ ]
+ },
+ {
+ "input": "&gdot",
+ "description": "Bad named entity: gdot without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&gdot"
+ ]
+ ]
+ },
+ {
+ "input": "&gdot;",
+ "description": "Named entity: gdot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0121"
+ ]
+ ]
+ },
+ {
+ "input": "&ge",
+ "description": "Bad named entity: ge without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ge"
+ ]
+ ]
+ },
+ {
+ "input": "&ge;",
+ "description": "Named entity: ge; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2265"
+ ]
+ ]
+ },
+ {
+ "input": "&gel",
+ "description": "Bad named entity: gel without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&gel"
+ ]
+ ]
+ },
+ {
+ "input": "&gel;",
+ "description": "Named entity: gel; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22db"
+ ]
+ ]
+ },
+ {
+ "input": "&geq",
+ "description": "Bad named entity: geq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&geq"
+ ]
+ ]
+ },
+ {
+ "input": "&geq;",
+ "description": "Named entity: geq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2265"
+ ]
+ ]
+ },
+ {
+ "input": "&geqq",
+ "description": "Bad named entity: geqq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&geqq"
+ ]
+ ]
+ },
+ {
+ "input": "&geqq;",
+ "description": "Named entity: geqq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2267"
+ ]
+ ]
+ },
+ {
+ "input": "&geqslant",
+ "description": "Bad named entity: geqslant without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&geqslant"
+ ]
+ ]
+ },
+ {
+ "input": "&geqslant;",
+ "description": "Named entity: geqslant; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a7e"
+ ]
+ ]
+ },
+ {
+ "input": "&ges",
+ "description": "Bad named entity: ges without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ges"
+ ]
+ ]
+ },
+ {
+ "input": "&ges;",
+ "description": "Named entity: ges; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a7e"
+ ]
+ ]
+ },
+ {
+ "input": "&gescc",
+ "description": "Bad named entity: gescc without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&gescc"
+ ]
+ ]
+ },
+ {
+ "input": "&gescc;",
+ "description": "Named entity: gescc; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2aa9"
+ ]
+ ]
+ },
+ {
+ "input": "&gesdot",
+ "description": "Bad named entity: gesdot without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&gesdot"
+ ]
+ ]
+ },
+ {
+ "input": "&gesdot;",
+ "description": "Named entity: gesdot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a80"
+ ]
+ ]
+ },
+ {
+ "input": "&gesdoto",
+ "description": "Bad named entity: gesdoto without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&gesdoto"
+ ]
+ ]
+ },
+ {
+ "input": "&gesdoto;",
+ "description": "Named entity: gesdoto; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a82"
+ ]
+ ]
+ },
+ {
+ "input": "&gesdotol",
+ "description": "Bad named entity: gesdotol without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&gesdotol"
+ ]
+ ]
+ },
+ {
+ "input": "&gesdotol;",
+ "description": "Named entity: gesdotol; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a84"
+ ]
+ ]
+ },
+ {
+ "input": "&gesl",
+ "description": "Bad named entity: gesl without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&gesl"
+ ]
+ ]
+ },
+ {
+ "input": "&gesl;",
+ "description": "Named entity: gesl; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22db\ufe00"
+ ]
+ ]
+ },
+ {
+ "input": "&gesles",
+ "description": "Bad named entity: gesles without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&gesles"
+ ]
+ ]
+ },
+ {
+ "input": "&gesles;",
+ "description": "Named entity: gesles; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a94"
+ ]
+ ]
+ },
+ {
+ "input": "&gfr",
+ "description": "Bad named entity: gfr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&gfr"
+ ]
+ ]
+ },
+ {
+ "input": "&gfr;",
+ "description": "Named entity: gfr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd24"
+ ]
+ ]
+ },
+ {
+ "input": "&gg",
+ "description": "Bad named entity: gg without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&gg"
+ ]
+ ]
+ },
+ {
+ "input": "&gg;",
+ "description": "Named entity: gg; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u226b"
+ ]
+ ]
+ },
+ {
+ "input": "&ggg",
+ "description": "Bad named entity: ggg without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ggg"
+ ]
+ ]
+ },
+ {
+ "input": "&ggg;",
+ "description": "Named entity: ggg; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22d9"
+ ]
+ ]
+ },
+ {
+ "input": "&gimel",
+ "description": "Bad named entity: gimel without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&gimel"
+ ]
+ ]
+ },
+ {
+ "input": "&gimel;",
+ "description": "Named entity: gimel; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2137"
+ ]
+ ]
+ },
+ {
+ "input": "&gjcy",
+ "description": "Bad named entity: gjcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&gjcy"
+ ]
+ ]
+ },
+ {
+ "input": "&gjcy;",
+ "description": "Named entity: gjcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0453"
+ ]
+ ]
+ },
+ {
+ "input": "&gl",
+ "description": "Bad named entity: gl without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&gl"
+ ]
+ ]
+ },
+ {
+ "input": "&gl;",
+ "description": "Named entity: gl; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2277"
+ ]
+ ]
+ },
+ {
+ "input": "&glE",
+ "description": "Bad named entity: glE without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&glE"
+ ]
+ ]
+ },
+ {
+ "input": "&glE;",
+ "description": "Named entity: glE; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a92"
+ ]
+ ]
+ },
+ {
+ "input": "&gla",
+ "description": "Bad named entity: gla without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&gla"
+ ]
+ ]
+ },
+ {
+ "input": "&gla;",
+ "description": "Named entity: gla; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2aa5"
+ ]
+ ]
+ },
+ {
+ "input": "&glj",
+ "description": "Bad named entity: glj without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&glj"
+ ]
+ ]
+ },
+ {
+ "input": "&glj;",
+ "description": "Named entity: glj; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2aa4"
+ ]
+ ]
+ },
+ {
+ "input": "&gnE",
+ "description": "Bad named entity: gnE without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&gnE"
+ ]
+ ]
+ },
+ {
+ "input": "&gnE;",
+ "description": "Named entity: gnE; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2269"
+ ]
+ ]
+ },
+ {
+ "input": "&gnap",
+ "description": "Bad named entity: gnap without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&gnap"
+ ]
+ ]
+ },
+ {
+ "input": "&gnap;",
+ "description": "Named entity: gnap; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a8a"
+ ]
+ ]
+ },
+ {
+ "input": "&gnapprox",
+ "description": "Bad named entity: gnapprox without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&gnapprox"
+ ]
+ ]
+ },
+ {
+ "input": "&gnapprox;",
+ "description": "Named entity: gnapprox; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a8a"
+ ]
+ ]
+ },
+ {
+ "input": "&gne",
+ "description": "Bad named entity: gne without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&gne"
+ ]
+ ]
+ },
+ {
+ "input": "&gne;",
+ "description": "Named entity: gne; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a88"
+ ]
+ ]
+ },
+ {
+ "input": "&gneq",
+ "description": "Bad named entity: gneq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&gneq"
+ ]
+ ]
+ },
+ {
+ "input": "&gneq;",
+ "description": "Named entity: gneq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a88"
+ ]
+ ]
+ },
+ {
+ "input": "&gneqq",
+ "description": "Bad named entity: gneqq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&gneqq"
+ ]
+ ]
+ },
+ {
+ "input": "&gneqq;",
+ "description": "Named entity: gneqq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2269"
+ ]
+ ]
+ },
+ {
+ "input": "&gnsim",
+ "description": "Bad named entity: gnsim without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&gnsim"
+ ]
+ ]
+ },
+ {
+ "input": "&gnsim;",
+ "description": "Named entity: gnsim; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22e7"
+ ]
+ ]
+ },
+ {
+ "input": "&gopf",
+ "description": "Bad named entity: gopf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&gopf"
+ ]
+ ]
+ },
+ {
+ "input": "&gopf;",
+ "description": "Named entity: gopf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd58"
+ ]
+ ]
+ },
+ {
+ "input": "&grave",
+ "description": "Bad named entity: grave without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&grave"
+ ]
+ ]
+ },
+ {
+ "input": "&grave;",
+ "description": "Named entity: grave; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "`"
+ ]
+ ]
+ },
+ {
+ "input": "&gscr",
+ "description": "Bad named entity: gscr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&gscr"
+ ]
+ ]
+ },
+ {
+ "input": "&gscr;",
+ "description": "Named entity: gscr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u210a"
+ ]
+ ]
+ },
+ {
+ "input": "&gsim",
+ "description": "Bad named entity: gsim without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&gsim"
+ ]
+ ]
+ },
+ {
+ "input": "&gsim;",
+ "description": "Named entity: gsim; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2273"
+ ]
+ ]
+ },
+ {
+ "input": "&gsime",
+ "description": "Bad named entity: gsime without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&gsime"
+ ]
+ ]
+ },
+ {
+ "input": "&gsime;",
+ "description": "Named entity: gsime; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a8e"
+ ]
+ ]
+ },
+ {
+ "input": "&gsiml",
+ "description": "Bad named entity: gsiml without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&gsiml"
+ ]
+ ]
+ },
+ {
+ "input": "&gsiml;",
+ "description": "Named entity: gsiml; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a90"
+ ]
+ ]
+ },
+ {
+ "input": "&gt",
+ "description": "Named entity: gt without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ ">"
+ ]
+ ]
+ },
+ {
+ "input": "&gt;",
+ "description": "Named entity: gt; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ ">"
+ ]
+ ]
+ },
+ {
+ "input": "&gtcc;",
+ "description": "Named entity: gtcc; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2aa7"
+ ]
+ ]
+ },
+ {
+ "input": "&gtcir;",
+ "description": "Named entity: gtcir; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a7a"
+ ]
+ ]
+ },
+ {
+ "input": "&gtdot;",
+ "description": "Named entity: gtdot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22d7"
+ ]
+ ]
+ },
+ {
+ "input": "&gtlPar;",
+ "description": "Named entity: gtlPar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2995"
+ ]
+ ]
+ },
+ {
+ "input": "&gtquest;",
+ "description": "Named entity: gtquest; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a7c"
+ ]
+ ]
+ },
+ {
+ "input": "&gtrapprox;",
+ "description": "Named entity: gtrapprox; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a86"
+ ]
+ ]
+ },
+ {
+ "input": "&gtrarr;",
+ "description": "Named entity: gtrarr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2978"
+ ]
+ ]
+ },
+ {
+ "input": "&gtrdot;",
+ "description": "Named entity: gtrdot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22d7"
+ ]
+ ]
+ },
+ {
+ "input": "&gtreqless;",
+ "description": "Named entity: gtreqless; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22db"
+ ]
+ ]
+ },
+ {
+ "input": "&gtreqqless;",
+ "description": "Named entity: gtreqqless; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a8c"
+ ]
+ ]
+ },
+ {
+ "input": "&gtrless;",
+ "description": "Named entity: gtrless; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2277"
+ ]
+ ]
+ },
+ {
+ "input": "&gtrsim;",
+ "description": "Named entity: gtrsim; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2273"
+ ]
+ ]
+ },
+ {
+ "input": "&gvertneqq",
+ "description": "Bad named entity: gvertneqq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&gvertneqq"
+ ]
+ ]
+ },
+ {
+ "input": "&gvertneqq;",
+ "description": "Named entity: gvertneqq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2269\ufe00"
+ ]
+ ]
+ },
+ {
+ "input": "&gvnE",
+ "description": "Bad named entity: gvnE without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&gvnE"
+ ]
+ ]
+ },
+ {
+ "input": "&gvnE;",
+ "description": "Named entity: gvnE; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2269\ufe00"
+ ]
+ ]
+ },
+ {
+ "input": "&hArr",
+ "description": "Bad named entity: hArr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&hArr"
+ ]
+ ]
+ },
+ {
+ "input": "&hArr;",
+ "description": "Named entity: hArr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21d4"
+ ]
+ ]
+ },
+ {
+ "input": "&hairsp",
+ "description": "Bad named entity: hairsp without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&hairsp"
+ ]
+ ]
+ },
+ {
+ "input": "&hairsp;",
+ "description": "Named entity: hairsp; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u200a"
+ ]
+ ]
+ },
+ {
+ "input": "&half",
+ "description": "Bad named entity: half without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&half"
+ ]
+ ]
+ },
+ {
+ "input": "&half;",
+ "description": "Named entity: half; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00bd"
+ ]
+ ]
+ },
+ {
+ "input": "&hamilt",
+ "description": "Bad named entity: hamilt without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&hamilt"
+ ]
+ ]
+ },
+ {
+ "input": "&hamilt;",
+ "description": "Named entity: hamilt; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u210b"
+ ]
+ ]
+ },
+ {
+ "input": "&hardcy",
+ "description": "Bad named entity: hardcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&hardcy"
+ ]
+ ]
+ },
+ {
+ "input": "&hardcy;",
+ "description": "Named entity: hardcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u044a"
+ ]
+ ]
+ },
+ {
+ "input": "&harr",
+ "description": "Bad named entity: harr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&harr"
+ ]
+ ]
+ },
+ {
+ "input": "&harr;",
+ "description": "Named entity: harr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2194"
+ ]
+ ]
+ },
+ {
+ "input": "&harrcir",
+ "description": "Bad named entity: harrcir without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&harrcir"
+ ]
+ ]
+ },
+ {
+ "input": "&harrcir;",
+ "description": "Named entity: harrcir; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2948"
+ ]
+ ]
+ },
+ {
+ "input": "&harrw",
+ "description": "Bad named entity: harrw without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&harrw"
+ ]
+ ]
+ },
+ {
+ "input": "&harrw;",
+ "description": "Named entity: harrw; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21ad"
+ ]
+ ]
+ },
+ {
+ "input": "&hbar",
+ "description": "Bad named entity: hbar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&hbar"
+ ]
+ ]
+ },
+ {
+ "input": "&hbar;",
+ "description": "Named entity: hbar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u210f"
+ ]
+ ]
+ },
+ {
+ "input": "&hcirc",
+ "description": "Bad named entity: hcirc without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&hcirc"
+ ]
+ ]
+ },
+ {
+ "input": "&hcirc;",
+ "description": "Named entity: hcirc; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0125"
+ ]
+ ]
+ },
+ {
+ "input": "&hearts",
+ "description": "Bad named entity: hearts without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&hearts"
+ ]
+ ]
+ },
+ {
+ "input": "&hearts;",
+ "description": "Named entity: hearts; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2665"
+ ]
+ ]
+ },
+ {
+ "input": "&heartsuit",
+ "description": "Bad named entity: heartsuit without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&heartsuit"
+ ]
+ ]
+ },
+ {
+ "input": "&heartsuit;",
+ "description": "Named entity: heartsuit; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2665"
+ ]
+ ]
+ },
+ {
+ "input": "&hellip",
+ "description": "Bad named entity: hellip without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&hellip"
+ ]
+ ]
+ },
+ {
+ "input": "&hellip;",
+ "description": "Named entity: hellip; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2026"
+ ]
+ ]
+ },
+ {
+ "input": "&hercon",
+ "description": "Bad named entity: hercon without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&hercon"
+ ]
+ ]
+ },
+ {
+ "input": "&hercon;",
+ "description": "Named entity: hercon; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22b9"
+ ]
+ ]
+ },
+ {
+ "input": "&hfr",
+ "description": "Bad named entity: hfr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&hfr"
+ ]
+ ]
+ },
+ {
+ "input": "&hfr;",
+ "description": "Named entity: hfr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd25"
+ ]
+ ]
+ },
+ {
+ "input": "&hksearow",
+ "description": "Bad named entity: hksearow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&hksearow"
+ ]
+ ]
+ },
+ {
+ "input": "&hksearow;",
+ "description": "Named entity: hksearow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2925"
+ ]
+ ]
+ },
+ {
+ "input": "&hkswarow",
+ "description": "Bad named entity: hkswarow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&hkswarow"
+ ]
+ ]
+ },
+ {
+ "input": "&hkswarow;",
+ "description": "Named entity: hkswarow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2926"
+ ]
+ ]
+ },
+ {
+ "input": "&hoarr",
+ "description": "Bad named entity: hoarr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&hoarr"
+ ]
+ ]
+ },
+ {
+ "input": "&hoarr;",
+ "description": "Named entity: hoarr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21ff"
+ ]
+ ]
+ },
+ {
+ "input": "&homtht",
+ "description": "Bad named entity: homtht without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&homtht"
+ ]
+ ]
+ },
+ {
+ "input": "&homtht;",
+ "description": "Named entity: homtht; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u223b"
+ ]
+ ]
+ },
+ {
+ "input": "&hookleftarrow",
+ "description": "Bad named entity: hookleftarrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&hookleftarrow"
+ ]
+ ]
+ },
+ {
+ "input": "&hookleftarrow;",
+ "description": "Named entity: hookleftarrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21a9"
+ ]
+ ]
+ },
+ {
+ "input": "&hookrightarrow",
+ "description": "Bad named entity: hookrightarrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&hookrightarrow"
+ ]
+ ]
+ },
+ {
+ "input": "&hookrightarrow;",
+ "description": "Named entity: hookrightarrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21aa"
+ ]
+ ]
+ },
+ {
+ "input": "&hopf",
+ "description": "Bad named entity: hopf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&hopf"
+ ]
+ ]
+ },
+ {
+ "input": "&hopf;",
+ "description": "Named entity: hopf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd59"
+ ]
+ ]
+ },
+ {
+ "input": "&horbar",
+ "description": "Bad named entity: horbar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&horbar"
+ ]
+ ]
+ },
+ {
+ "input": "&horbar;",
+ "description": "Named entity: horbar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2015"
+ ]
+ ]
+ },
+ {
+ "input": "&hscr",
+ "description": "Bad named entity: hscr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&hscr"
+ ]
+ ]
+ },
+ {
+ "input": "&hscr;",
+ "description": "Named entity: hscr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udcbd"
+ ]
+ ]
+ },
+ {
+ "input": "&hslash",
+ "description": "Bad named entity: hslash without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&hslash"
+ ]
+ ]
+ },
+ {
+ "input": "&hslash;",
+ "description": "Named entity: hslash; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u210f"
+ ]
+ ]
+ },
+ {
+ "input": "&hstrok",
+ "description": "Bad named entity: hstrok without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&hstrok"
+ ]
+ ]
+ },
+ {
+ "input": "&hstrok;",
+ "description": "Named entity: hstrok; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0127"
+ ]
+ ]
+ },
+ {
+ "input": "&hybull",
+ "description": "Bad named entity: hybull without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&hybull"
+ ]
+ ]
+ },
+ {
+ "input": "&hybull;",
+ "description": "Named entity: hybull; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2043"
+ ]
+ ]
+ },
+ {
+ "input": "&hyphen",
+ "description": "Bad named entity: hyphen without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&hyphen"
+ ]
+ ]
+ },
+ {
+ "input": "&hyphen;",
+ "description": "Named entity: hyphen; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2010"
+ ]
+ ]
+ },
+ {
+ "input": "&iacute",
+ "description": "Named entity: iacute without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00ed"
+ ]
+ ]
+ },
+ {
+ "input": "&iacute;",
+ "description": "Named entity: iacute; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00ed"
+ ]
+ ]
+ },
+ {
+ "input": "&ic",
+ "description": "Bad named entity: ic without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ic"
+ ]
+ ]
+ },
+ {
+ "input": "&ic;",
+ "description": "Named entity: ic; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2063"
+ ]
+ ]
+ },
+ {
+ "input": "&icirc",
+ "description": "Named entity: icirc without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00ee"
+ ]
+ ]
+ },
+ {
+ "input": "&icirc;",
+ "description": "Named entity: icirc; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00ee"
+ ]
+ ]
+ },
+ {
+ "input": "&icy",
+ "description": "Bad named entity: icy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&icy"
+ ]
+ ]
+ },
+ {
+ "input": "&icy;",
+ "description": "Named entity: icy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0438"
+ ]
+ ]
+ },
+ {
+ "input": "&iecy",
+ "description": "Bad named entity: iecy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&iecy"
+ ]
+ ]
+ },
+ {
+ "input": "&iecy;",
+ "description": "Named entity: iecy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0435"
+ ]
+ ]
+ },
+ {
+ "input": "&iexcl",
+ "description": "Named entity: iexcl without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00a1"
+ ]
+ ]
+ },
+ {
+ "input": "&iexcl;",
+ "description": "Named entity: iexcl; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00a1"
+ ]
+ ]
+ },
+ {
+ "input": "&iff",
+ "description": "Bad named entity: iff without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&iff"
+ ]
+ ]
+ },
+ {
+ "input": "&iff;",
+ "description": "Named entity: iff; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21d4"
+ ]
+ ]
+ },
+ {
+ "input": "&ifr",
+ "description": "Bad named entity: ifr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ifr"
+ ]
+ ]
+ },
+ {
+ "input": "&ifr;",
+ "description": "Named entity: ifr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd26"
+ ]
+ ]
+ },
+ {
+ "input": "&igrave",
+ "description": "Named entity: igrave without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00ec"
+ ]
+ ]
+ },
+ {
+ "input": "&igrave;",
+ "description": "Named entity: igrave; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00ec"
+ ]
+ ]
+ },
+ {
+ "input": "&ii",
+ "description": "Bad named entity: ii without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ii"
+ ]
+ ]
+ },
+ {
+ "input": "&ii;",
+ "description": "Named entity: ii; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2148"
+ ]
+ ]
+ },
+ {
+ "input": "&iiiint",
+ "description": "Bad named entity: iiiint without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&iiiint"
+ ]
+ ]
+ },
+ {
+ "input": "&iiiint;",
+ "description": "Named entity: iiiint; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a0c"
+ ]
+ ]
+ },
+ {
+ "input": "&iiint",
+ "description": "Bad named entity: iiint without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&iiint"
+ ]
+ ]
+ },
+ {
+ "input": "&iiint;",
+ "description": "Named entity: iiint; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u222d"
+ ]
+ ]
+ },
+ {
+ "input": "&iinfin",
+ "description": "Bad named entity: iinfin without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&iinfin"
+ ]
+ ]
+ },
+ {
+ "input": "&iinfin;",
+ "description": "Named entity: iinfin; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u29dc"
+ ]
+ ]
+ },
+ {
+ "input": "&iiota",
+ "description": "Bad named entity: iiota without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&iiota"
+ ]
+ ]
+ },
+ {
+ "input": "&iiota;",
+ "description": "Named entity: iiota; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2129"
+ ]
+ ]
+ },
+ {
+ "input": "&ijlig",
+ "description": "Bad named entity: ijlig without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ijlig"
+ ]
+ ]
+ },
+ {
+ "input": "&ijlig;",
+ "description": "Named entity: ijlig; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0133"
+ ]
+ ]
+ },
+ {
+ "input": "&imacr",
+ "description": "Bad named entity: imacr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&imacr"
+ ]
+ ]
+ },
+ {
+ "input": "&imacr;",
+ "description": "Named entity: imacr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u012b"
+ ]
+ ]
+ },
+ {
+ "input": "&image",
+ "description": "Bad named entity: image without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&image"
+ ]
+ ]
+ },
+ {
+ "input": "&image;",
+ "description": "Named entity: image; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2111"
+ ]
+ ]
+ },
+ {
+ "input": "&imagline",
+ "description": "Bad named entity: imagline without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&imagline"
+ ]
+ ]
+ },
+ {
+ "input": "&imagline;",
+ "description": "Named entity: imagline; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2110"
+ ]
+ ]
+ },
+ {
+ "input": "&imagpart",
+ "description": "Bad named entity: imagpart without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&imagpart"
+ ]
+ ]
+ },
+ {
+ "input": "&imagpart;",
+ "description": "Named entity: imagpart; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2111"
+ ]
+ ]
+ },
+ {
+ "input": "&imath",
+ "description": "Bad named entity: imath without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&imath"
+ ]
+ ]
+ },
+ {
+ "input": "&imath;",
+ "description": "Named entity: imath; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0131"
+ ]
+ ]
+ },
+ {
+ "input": "&imof",
+ "description": "Bad named entity: imof without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&imof"
+ ]
+ ]
+ },
+ {
+ "input": "&imof;",
+ "description": "Named entity: imof; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22b7"
+ ]
+ ]
+ },
+ {
+ "input": "&imped",
+ "description": "Bad named entity: imped without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&imped"
+ ]
+ ]
+ },
+ {
+ "input": "&imped;",
+ "description": "Named entity: imped; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u01b5"
+ ]
+ ]
+ },
+ {
+ "input": "&in",
+ "description": "Bad named entity: in without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&in"
+ ]
+ ]
+ },
+ {
+ "input": "&in;",
+ "description": "Named entity: in; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2208"
+ ]
+ ]
+ },
+ {
+ "input": "&incare",
+ "description": "Bad named entity: incare without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&incare"
+ ]
+ ]
+ },
+ {
+ "input": "&incare;",
+ "description": "Named entity: incare; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2105"
+ ]
+ ]
+ },
+ {
+ "input": "&infin",
+ "description": "Bad named entity: infin without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&infin"
+ ]
+ ]
+ },
+ {
+ "input": "&infin;",
+ "description": "Named entity: infin; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u221e"
+ ]
+ ]
+ },
+ {
+ "input": "&infintie",
+ "description": "Bad named entity: infintie without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&infintie"
+ ]
+ ]
+ },
+ {
+ "input": "&infintie;",
+ "description": "Named entity: infintie; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u29dd"
+ ]
+ ]
+ },
+ {
+ "input": "&inodot",
+ "description": "Bad named entity: inodot without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&inodot"
+ ]
+ ]
+ },
+ {
+ "input": "&inodot;",
+ "description": "Named entity: inodot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0131"
+ ]
+ ]
+ },
+ {
+ "input": "&int",
+ "description": "Bad named entity: int without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&int"
+ ]
+ ]
+ },
+ {
+ "input": "&int;",
+ "description": "Named entity: int; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u222b"
+ ]
+ ]
+ },
+ {
+ "input": "&intcal",
+ "description": "Bad named entity: intcal without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&intcal"
+ ]
+ ]
+ },
+ {
+ "input": "&intcal;",
+ "description": "Named entity: intcal; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22ba"
+ ]
+ ]
+ },
+ {
+ "input": "&integers",
+ "description": "Bad named entity: integers without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&integers"
+ ]
+ ]
+ },
+ {
+ "input": "&integers;",
+ "description": "Named entity: integers; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2124"
+ ]
+ ]
+ },
+ {
+ "input": "&intercal",
+ "description": "Bad named entity: intercal without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&intercal"
+ ]
+ ]
+ },
+ {
+ "input": "&intercal;",
+ "description": "Named entity: intercal; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22ba"
+ ]
+ ]
+ },
+ {
+ "input": "&intlarhk",
+ "description": "Bad named entity: intlarhk without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&intlarhk"
+ ]
+ ]
+ },
+ {
+ "input": "&intlarhk;",
+ "description": "Named entity: intlarhk; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a17"
+ ]
+ ]
+ },
+ {
+ "input": "&intprod",
+ "description": "Bad named entity: intprod without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&intprod"
+ ]
+ ]
+ },
+ {
+ "input": "&intprod;",
+ "description": "Named entity: intprod; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a3c"
+ ]
+ ]
+ },
+ {
+ "input": "&iocy",
+ "description": "Bad named entity: iocy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&iocy"
+ ]
+ ]
+ },
+ {
+ "input": "&iocy;",
+ "description": "Named entity: iocy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0451"
+ ]
+ ]
+ },
+ {
+ "input": "&iogon",
+ "description": "Bad named entity: iogon without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&iogon"
+ ]
+ ]
+ },
+ {
+ "input": "&iogon;",
+ "description": "Named entity: iogon; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u012f"
+ ]
+ ]
+ },
+ {
+ "input": "&iopf",
+ "description": "Bad named entity: iopf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&iopf"
+ ]
+ ]
+ },
+ {
+ "input": "&iopf;",
+ "description": "Named entity: iopf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd5a"
+ ]
+ ]
+ },
+ {
+ "input": "&iota",
+ "description": "Bad named entity: iota without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&iota"
+ ]
+ ]
+ },
+ {
+ "input": "&iota;",
+ "description": "Named entity: iota; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03b9"
+ ]
+ ]
+ },
+ {
+ "input": "&iprod",
+ "description": "Bad named entity: iprod without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&iprod"
+ ]
+ ]
+ },
+ {
+ "input": "&iprod;",
+ "description": "Named entity: iprod; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a3c"
+ ]
+ ]
+ },
+ {
+ "input": "&iquest",
+ "description": "Named entity: iquest without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00bf"
+ ]
+ ]
+ },
+ {
+ "input": "&iquest;",
+ "description": "Named entity: iquest; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00bf"
+ ]
+ ]
+ },
+ {
+ "input": "&iscr",
+ "description": "Bad named entity: iscr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&iscr"
+ ]
+ ]
+ },
+ {
+ "input": "&iscr;",
+ "description": "Named entity: iscr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udcbe"
+ ]
+ ]
+ },
+ {
+ "input": "&isin",
+ "description": "Bad named entity: isin without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&isin"
+ ]
+ ]
+ },
+ {
+ "input": "&isin;",
+ "description": "Named entity: isin; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2208"
+ ]
+ ]
+ },
+ {
+ "input": "&isinE",
+ "description": "Bad named entity: isinE without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&isinE"
+ ]
+ ]
+ },
+ {
+ "input": "&isinE;",
+ "description": "Named entity: isinE; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22f9"
+ ]
+ ]
+ },
+ {
+ "input": "&isindot",
+ "description": "Bad named entity: isindot without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&isindot"
+ ]
+ ]
+ },
+ {
+ "input": "&isindot;",
+ "description": "Named entity: isindot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22f5"
+ ]
+ ]
+ },
+ {
+ "input": "&isins",
+ "description": "Bad named entity: isins without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&isins"
+ ]
+ ]
+ },
+ {
+ "input": "&isins;",
+ "description": "Named entity: isins; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22f4"
+ ]
+ ]
+ },
+ {
+ "input": "&isinsv",
+ "description": "Bad named entity: isinsv without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&isinsv"
+ ]
+ ]
+ },
+ {
+ "input": "&isinsv;",
+ "description": "Named entity: isinsv; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22f3"
+ ]
+ ]
+ },
+ {
+ "input": "&isinv",
+ "description": "Bad named entity: isinv without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&isinv"
+ ]
+ ]
+ },
+ {
+ "input": "&isinv;",
+ "description": "Named entity: isinv; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2208"
+ ]
+ ]
+ },
+ {
+ "input": "&it",
+ "description": "Bad named entity: it without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&it"
+ ]
+ ]
+ },
+ {
+ "input": "&it;",
+ "description": "Named entity: it; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2062"
+ ]
+ ]
+ },
+ {
+ "input": "&itilde",
+ "description": "Bad named entity: itilde without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&itilde"
+ ]
+ ]
+ },
+ {
+ "input": "&itilde;",
+ "description": "Named entity: itilde; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0129"
+ ]
+ ]
+ },
+ {
+ "input": "&iukcy",
+ "description": "Bad named entity: iukcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&iukcy"
+ ]
+ ]
+ },
+ {
+ "input": "&iukcy;",
+ "description": "Named entity: iukcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0456"
+ ]
+ ]
+ },
+ {
+ "input": "&iuml",
+ "description": "Named entity: iuml without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00ef"
+ ]
+ ]
+ },
+ {
+ "input": "&iuml;",
+ "description": "Named entity: iuml; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00ef"
+ ]
+ ]
+ },
+ {
+ "input": "&jcirc",
+ "description": "Bad named entity: jcirc without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&jcirc"
+ ]
+ ]
+ },
+ {
+ "input": "&jcirc;",
+ "description": "Named entity: jcirc; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0135"
+ ]
+ ]
+ },
+ {
+ "input": "&jcy",
+ "description": "Bad named entity: jcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&jcy"
+ ]
+ ]
+ },
+ {
+ "input": "&jcy;",
+ "description": "Named entity: jcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0439"
+ ]
+ ]
+ },
+ {
+ "input": "&jfr",
+ "description": "Bad named entity: jfr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&jfr"
+ ]
+ ]
+ },
+ {
+ "input": "&jfr;",
+ "description": "Named entity: jfr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd27"
+ ]
+ ]
+ },
+ {
+ "input": "&jmath",
+ "description": "Bad named entity: jmath without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&jmath"
+ ]
+ ]
+ },
+ {
+ "input": "&jmath;",
+ "description": "Named entity: jmath; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0237"
+ ]
+ ]
+ },
+ {
+ "input": "&jopf",
+ "description": "Bad named entity: jopf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&jopf"
+ ]
+ ]
+ },
+ {
+ "input": "&jopf;",
+ "description": "Named entity: jopf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd5b"
+ ]
+ ]
+ },
+ {
+ "input": "&jscr",
+ "description": "Bad named entity: jscr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&jscr"
+ ]
+ ]
+ },
+ {
+ "input": "&jscr;",
+ "description": "Named entity: jscr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udcbf"
+ ]
+ ]
+ },
+ {
+ "input": "&jsercy",
+ "description": "Bad named entity: jsercy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&jsercy"
+ ]
+ ]
+ },
+ {
+ "input": "&jsercy;",
+ "description": "Named entity: jsercy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0458"
+ ]
+ ]
+ },
+ {
+ "input": "&jukcy",
+ "description": "Bad named entity: jukcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&jukcy"
+ ]
+ ]
+ },
+ {
+ "input": "&jukcy;",
+ "description": "Named entity: jukcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0454"
+ ]
+ ]
+ },
+ {
+ "input": "&kappa",
+ "description": "Bad named entity: kappa without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&kappa"
+ ]
+ ]
+ },
+ {
+ "input": "&kappa;",
+ "description": "Named entity: kappa; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03ba"
+ ]
+ ]
+ },
+ {
+ "input": "&kappav",
+ "description": "Bad named entity: kappav without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&kappav"
+ ]
+ ]
+ },
+ {
+ "input": "&kappav;",
+ "description": "Named entity: kappav; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03f0"
+ ]
+ ]
+ },
+ {
+ "input": "&kcedil",
+ "description": "Bad named entity: kcedil without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&kcedil"
+ ]
+ ]
+ },
+ {
+ "input": "&kcedil;",
+ "description": "Named entity: kcedil; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0137"
+ ]
+ ]
+ },
+ {
+ "input": "&kcy",
+ "description": "Bad named entity: kcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&kcy"
+ ]
+ ]
+ },
+ {
+ "input": "&kcy;",
+ "description": "Named entity: kcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u043a"
+ ]
+ ]
+ },
+ {
+ "input": "&kfr",
+ "description": "Bad named entity: kfr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&kfr"
+ ]
+ ]
+ },
+ {
+ "input": "&kfr;",
+ "description": "Named entity: kfr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd28"
+ ]
+ ]
+ },
+ {
+ "input": "&kgreen",
+ "description": "Bad named entity: kgreen without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&kgreen"
+ ]
+ ]
+ },
+ {
+ "input": "&kgreen;",
+ "description": "Named entity: kgreen; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0138"
+ ]
+ ]
+ },
+ {
+ "input": "&khcy",
+ "description": "Bad named entity: khcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&khcy"
+ ]
+ ]
+ },
+ {
+ "input": "&khcy;",
+ "description": "Named entity: khcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0445"
+ ]
+ ]
+ },
+ {
+ "input": "&kjcy",
+ "description": "Bad named entity: kjcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&kjcy"
+ ]
+ ]
+ },
+ {
+ "input": "&kjcy;",
+ "description": "Named entity: kjcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u045c"
+ ]
+ ]
+ },
+ {
+ "input": "&kopf",
+ "description": "Bad named entity: kopf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&kopf"
+ ]
+ ]
+ },
+ {
+ "input": "&kopf;",
+ "description": "Named entity: kopf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd5c"
+ ]
+ ]
+ },
+ {
+ "input": "&kscr",
+ "description": "Bad named entity: kscr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&kscr"
+ ]
+ ]
+ },
+ {
+ "input": "&kscr;",
+ "description": "Named entity: kscr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udcc0"
+ ]
+ ]
+ },
+ {
+ "input": "&lAarr",
+ "description": "Bad named entity: lAarr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lAarr"
+ ]
+ ]
+ },
+ {
+ "input": "&lAarr;",
+ "description": "Named entity: lAarr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21da"
+ ]
+ ]
+ },
+ {
+ "input": "&lArr",
+ "description": "Bad named entity: lArr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lArr"
+ ]
+ ]
+ },
+ {
+ "input": "&lArr;",
+ "description": "Named entity: lArr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21d0"
+ ]
+ ]
+ },
+ {
+ "input": "&lAtail",
+ "description": "Bad named entity: lAtail without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lAtail"
+ ]
+ ]
+ },
+ {
+ "input": "&lAtail;",
+ "description": "Named entity: lAtail; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u291b"
+ ]
+ ]
+ },
+ {
+ "input": "&lBarr",
+ "description": "Bad named entity: lBarr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lBarr"
+ ]
+ ]
+ },
+ {
+ "input": "&lBarr;",
+ "description": "Named entity: lBarr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u290e"
+ ]
+ ]
+ },
+ {
+ "input": "&lE",
+ "description": "Bad named entity: lE without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lE"
+ ]
+ ]
+ },
+ {
+ "input": "&lE;",
+ "description": "Named entity: lE; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2266"
+ ]
+ ]
+ },
+ {
+ "input": "&lEg",
+ "description": "Bad named entity: lEg without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lEg"
+ ]
+ ]
+ },
+ {
+ "input": "&lEg;",
+ "description": "Named entity: lEg; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a8b"
+ ]
+ ]
+ },
+ {
+ "input": "&lHar",
+ "description": "Bad named entity: lHar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lHar"
+ ]
+ ]
+ },
+ {
+ "input": "&lHar;",
+ "description": "Named entity: lHar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2962"
+ ]
+ ]
+ },
+ {
+ "input": "&lacute",
+ "description": "Bad named entity: lacute without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lacute"
+ ]
+ ]
+ },
+ {
+ "input": "&lacute;",
+ "description": "Named entity: lacute; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u013a"
+ ]
+ ]
+ },
+ {
+ "input": "&laemptyv",
+ "description": "Bad named entity: laemptyv without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&laemptyv"
+ ]
+ ]
+ },
+ {
+ "input": "&laemptyv;",
+ "description": "Named entity: laemptyv; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u29b4"
+ ]
+ ]
+ },
+ {
+ "input": "&lagran",
+ "description": "Bad named entity: lagran without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lagran"
+ ]
+ ]
+ },
+ {
+ "input": "&lagran;",
+ "description": "Named entity: lagran; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2112"
+ ]
+ ]
+ },
+ {
+ "input": "&lambda",
+ "description": "Bad named entity: lambda without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lambda"
+ ]
+ ]
+ },
+ {
+ "input": "&lambda;",
+ "description": "Named entity: lambda; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03bb"
+ ]
+ ]
+ },
+ {
+ "input": "&lang",
+ "description": "Bad named entity: lang without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lang"
+ ]
+ ]
+ },
+ {
+ "input": "&lang;",
+ "description": "Named entity: lang; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u27e8"
+ ]
+ ]
+ },
+ {
+ "input": "&langd",
+ "description": "Bad named entity: langd without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&langd"
+ ]
+ ]
+ },
+ {
+ "input": "&langd;",
+ "description": "Named entity: langd; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2991"
+ ]
+ ]
+ },
+ {
+ "input": "&langle",
+ "description": "Bad named entity: langle without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&langle"
+ ]
+ ]
+ },
+ {
+ "input": "&langle;",
+ "description": "Named entity: langle; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u27e8"
+ ]
+ ]
+ },
+ {
+ "input": "&lap",
+ "description": "Bad named entity: lap without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lap"
+ ]
+ ]
+ },
+ {
+ "input": "&lap;",
+ "description": "Named entity: lap; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a85"
+ ]
+ ]
+ },
+ {
+ "input": "&laquo",
+ "description": "Named entity: laquo without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00ab"
+ ]
+ ]
+ },
+ {
+ "input": "&laquo;",
+ "description": "Named entity: laquo; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00ab"
+ ]
+ ]
+ },
+ {
+ "input": "&larr",
+ "description": "Bad named entity: larr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&larr"
+ ]
+ ]
+ },
+ {
+ "input": "&larr;",
+ "description": "Named entity: larr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2190"
+ ]
+ ]
+ },
+ {
+ "input": "&larrb",
+ "description": "Bad named entity: larrb without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&larrb"
+ ]
+ ]
+ },
+ {
+ "input": "&larrb;",
+ "description": "Named entity: larrb; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21e4"
+ ]
+ ]
+ },
+ {
+ "input": "&larrbfs",
+ "description": "Bad named entity: larrbfs without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&larrbfs"
+ ]
+ ]
+ },
+ {
+ "input": "&larrbfs;",
+ "description": "Named entity: larrbfs; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u291f"
+ ]
+ ]
+ },
+ {
+ "input": "&larrfs",
+ "description": "Bad named entity: larrfs without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&larrfs"
+ ]
+ ]
+ },
+ {
+ "input": "&larrfs;",
+ "description": "Named entity: larrfs; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u291d"
+ ]
+ ]
+ },
+ {
+ "input": "&larrhk",
+ "description": "Bad named entity: larrhk without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&larrhk"
+ ]
+ ]
+ },
+ {
+ "input": "&larrhk;",
+ "description": "Named entity: larrhk; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21a9"
+ ]
+ ]
+ },
+ {
+ "input": "&larrlp",
+ "description": "Bad named entity: larrlp without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&larrlp"
+ ]
+ ]
+ },
+ {
+ "input": "&larrlp;",
+ "description": "Named entity: larrlp; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21ab"
+ ]
+ ]
+ },
+ {
+ "input": "&larrpl",
+ "description": "Bad named entity: larrpl without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&larrpl"
+ ]
+ ]
+ },
+ {
+ "input": "&larrpl;",
+ "description": "Named entity: larrpl; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2939"
+ ]
+ ]
+ },
+ {
+ "input": "&larrsim",
+ "description": "Bad named entity: larrsim without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&larrsim"
+ ]
+ ]
+ },
+ {
+ "input": "&larrsim;",
+ "description": "Named entity: larrsim; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2973"
+ ]
+ ]
+ },
+ {
+ "input": "&larrtl",
+ "description": "Bad named entity: larrtl without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&larrtl"
+ ]
+ ]
+ },
+ {
+ "input": "&larrtl;",
+ "description": "Named entity: larrtl; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21a2"
+ ]
+ ]
+ },
+ {
+ "input": "&lat",
+ "description": "Bad named entity: lat without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lat"
+ ]
+ ]
+ },
+ {
+ "input": "&lat;",
+ "description": "Named entity: lat; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2aab"
+ ]
+ ]
+ },
+ {
+ "input": "&latail",
+ "description": "Bad named entity: latail without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&latail"
+ ]
+ ]
+ },
+ {
+ "input": "&latail;",
+ "description": "Named entity: latail; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2919"
+ ]
+ ]
+ },
+ {
+ "input": "&late",
+ "description": "Bad named entity: late without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&late"
+ ]
+ ]
+ },
+ {
+ "input": "&late;",
+ "description": "Named entity: late; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2aad"
+ ]
+ ]
+ },
+ {
+ "input": "&lates",
+ "description": "Bad named entity: lates without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lates"
+ ]
+ ]
+ },
+ {
+ "input": "&lates;",
+ "description": "Named entity: lates; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2aad\ufe00"
+ ]
+ ]
+ },
+ {
+ "input": "&lbarr",
+ "description": "Bad named entity: lbarr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lbarr"
+ ]
+ ]
+ },
+ {
+ "input": "&lbarr;",
+ "description": "Named entity: lbarr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u290c"
+ ]
+ ]
+ },
+ {
+ "input": "&lbbrk",
+ "description": "Bad named entity: lbbrk without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lbbrk"
+ ]
+ ]
+ },
+ {
+ "input": "&lbbrk;",
+ "description": "Named entity: lbbrk; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2772"
+ ]
+ ]
+ },
+ {
+ "input": "&lbrace",
+ "description": "Bad named entity: lbrace without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lbrace"
+ ]
+ ]
+ },
+ {
+ "input": "&lbrace;",
+ "description": "Named entity: lbrace; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "{"
+ ]
+ ]
+ },
+ {
+ "input": "&lbrack",
+ "description": "Bad named entity: lbrack without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lbrack"
+ ]
+ ]
+ },
+ {
+ "input": "&lbrack;",
+ "description": "Named entity: lbrack; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "["
+ ]
+ ]
+ },
+ {
+ "input": "&lbrke",
+ "description": "Bad named entity: lbrke without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lbrke"
+ ]
+ ]
+ },
+ {
+ "input": "&lbrke;",
+ "description": "Named entity: lbrke; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u298b"
+ ]
+ ]
+ },
+ {
+ "input": "&lbrksld",
+ "description": "Bad named entity: lbrksld without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lbrksld"
+ ]
+ ]
+ },
+ {
+ "input": "&lbrksld;",
+ "description": "Named entity: lbrksld; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u298f"
+ ]
+ ]
+ },
+ {
+ "input": "&lbrkslu",
+ "description": "Bad named entity: lbrkslu without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lbrkslu"
+ ]
+ ]
+ },
+ {
+ "input": "&lbrkslu;",
+ "description": "Named entity: lbrkslu; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u298d"
+ ]
+ ]
+ },
+ {
+ "input": "&lcaron",
+ "description": "Bad named entity: lcaron without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lcaron"
+ ]
+ ]
+ },
+ {
+ "input": "&lcaron;",
+ "description": "Named entity: lcaron; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u013e"
+ ]
+ ]
+ },
+ {
+ "input": "&lcedil",
+ "description": "Bad named entity: lcedil without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lcedil"
+ ]
+ ]
+ },
+ {
+ "input": "&lcedil;",
+ "description": "Named entity: lcedil; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u013c"
+ ]
+ ]
+ },
+ {
+ "input": "&lceil",
+ "description": "Bad named entity: lceil without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lceil"
+ ]
+ ]
+ },
+ {
+ "input": "&lceil;",
+ "description": "Named entity: lceil; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2308"
+ ]
+ ]
+ },
+ {
+ "input": "&lcub",
+ "description": "Bad named entity: lcub without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lcub"
+ ]
+ ]
+ },
+ {
+ "input": "&lcub;",
+ "description": "Named entity: lcub; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "{"
+ ]
+ ]
+ },
+ {
+ "input": "&lcy",
+ "description": "Bad named entity: lcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lcy"
+ ]
+ ]
+ },
+ {
+ "input": "&lcy;",
+ "description": "Named entity: lcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u043b"
+ ]
+ ]
+ },
+ {
+ "input": "&ldca",
+ "description": "Bad named entity: ldca without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ldca"
+ ]
+ ]
+ },
+ {
+ "input": "&ldca;",
+ "description": "Named entity: ldca; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2936"
+ ]
+ ]
+ },
+ {
+ "input": "&ldquo",
+ "description": "Bad named entity: ldquo without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ldquo"
+ ]
+ ]
+ },
+ {
+ "input": "&ldquo;",
+ "description": "Named entity: ldquo; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u201c"
+ ]
+ ]
+ },
+ {
+ "input": "&ldquor",
+ "description": "Bad named entity: ldquor without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ldquor"
+ ]
+ ]
+ },
+ {
+ "input": "&ldquor;",
+ "description": "Named entity: ldquor; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u201e"
+ ]
+ ]
+ },
+ {
+ "input": "&ldrdhar",
+ "description": "Bad named entity: ldrdhar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ldrdhar"
+ ]
+ ]
+ },
+ {
+ "input": "&ldrdhar;",
+ "description": "Named entity: ldrdhar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2967"
+ ]
+ ]
+ },
+ {
+ "input": "&ldrushar",
+ "description": "Bad named entity: ldrushar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ldrushar"
+ ]
+ ]
+ },
+ {
+ "input": "&ldrushar;",
+ "description": "Named entity: ldrushar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u294b"
+ ]
+ ]
+ },
+ {
+ "input": "&ldsh",
+ "description": "Bad named entity: ldsh without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ldsh"
+ ]
+ ]
+ },
+ {
+ "input": "&ldsh;",
+ "description": "Named entity: ldsh; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21b2"
+ ]
+ ]
+ },
+ {
+ "input": "&le",
+ "description": "Bad named entity: le without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&le"
+ ]
+ ]
+ },
+ {
+ "input": "&le;",
+ "description": "Named entity: le; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2264"
+ ]
+ ]
+ },
+ {
+ "input": "&leftarrow",
+ "description": "Bad named entity: leftarrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&leftarrow"
+ ]
+ ]
+ },
+ {
+ "input": "&leftarrow;",
+ "description": "Named entity: leftarrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2190"
+ ]
+ ]
+ },
+ {
+ "input": "&leftarrowtail",
+ "description": "Bad named entity: leftarrowtail without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&leftarrowtail"
+ ]
+ ]
+ },
+ {
+ "input": "&leftarrowtail;",
+ "description": "Named entity: leftarrowtail; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21a2"
+ ]
+ ]
+ },
+ {
+ "input": "&leftharpoondown",
+ "description": "Bad named entity: leftharpoondown without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&leftharpoondown"
+ ]
+ ]
+ },
+ {
+ "input": "&leftharpoondown;",
+ "description": "Named entity: leftharpoondown; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21bd"
+ ]
+ ]
+ },
+ {
+ "input": "&leftharpoonup",
+ "description": "Bad named entity: leftharpoonup without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&leftharpoonup"
+ ]
+ ]
+ },
+ {
+ "input": "&leftharpoonup;",
+ "description": "Named entity: leftharpoonup; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21bc"
+ ]
+ ]
+ },
+ {
+ "input": "&leftleftarrows",
+ "description": "Bad named entity: leftleftarrows without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&leftleftarrows"
+ ]
+ ]
+ },
+ {
+ "input": "&leftleftarrows;",
+ "description": "Named entity: leftleftarrows; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21c7"
+ ]
+ ]
+ },
+ {
+ "input": "&leftrightarrow",
+ "description": "Bad named entity: leftrightarrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&leftrightarrow"
+ ]
+ ]
+ },
+ {
+ "input": "&leftrightarrow;",
+ "description": "Named entity: leftrightarrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2194"
+ ]
+ ]
+ },
+ {
+ "input": "&leftrightarrows",
+ "description": "Bad named entity: leftrightarrows without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&leftrightarrows"
+ ]
+ ]
+ },
+ {
+ "input": "&leftrightarrows;",
+ "description": "Named entity: leftrightarrows; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21c6"
+ ]
+ ]
+ },
+ {
+ "input": "&leftrightharpoons",
+ "description": "Bad named entity: leftrightharpoons without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&leftrightharpoons"
+ ]
+ ]
+ },
+ {
+ "input": "&leftrightharpoons;",
+ "description": "Named entity: leftrightharpoons; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21cb"
+ ]
+ ]
+ },
+ {
+ "input": "&leftrightsquigarrow",
+ "description": "Bad named entity: leftrightsquigarrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&leftrightsquigarrow"
+ ]
+ ]
+ },
+ {
+ "input": "&leftrightsquigarrow;",
+ "description": "Named entity: leftrightsquigarrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21ad"
+ ]
+ ]
+ },
+ {
+ "input": "&leftthreetimes",
+ "description": "Bad named entity: leftthreetimes without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&leftthreetimes"
+ ]
+ ]
+ },
+ {
+ "input": "&leftthreetimes;",
+ "description": "Named entity: leftthreetimes; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22cb"
+ ]
+ ]
+ },
+ {
+ "input": "&leg",
+ "description": "Bad named entity: leg without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&leg"
+ ]
+ ]
+ },
+ {
+ "input": "&leg;",
+ "description": "Named entity: leg; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22da"
+ ]
+ ]
+ },
+ {
+ "input": "&leq",
+ "description": "Bad named entity: leq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&leq"
+ ]
+ ]
+ },
+ {
+ "input": "&leq;",
+ "description": "Named entity: leq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2264"
+ ]
+ ]
+ },
+ {
+ "input": "&leqq",
+ "description": "Bad named entity: leqq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&leqq"
+ ]
+ ]
+ },
+ {
+ "input": "&leqq;",
+ "description": "Named entity: leqq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2266"
+ ]
+ ]
+ },
+ {
+ "input": "&leqslant",
+ "description": "Bad named entity: leqslant without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&leqslant"
+ ]
+ ]
+ },
+ {
+ "input": "&leqslant;",
+ "description": "Named entity: leqslant; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a7d"
+ ]
+ ]
+ },
+ {
+ "input": "&les",
+ "description": "Bad named entity: les without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&les"
+ ]
+ ]
+ },
+ {
+ "input": "&les;",
+ "description": "Named entity: les; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a7d"
+ ]
+ ]
+ },
+ {
+ "input": "&lescc",
+ "description": "Bad named entity: lescc without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lescc"
+ ]
+ ]
+ },
+ {
+ "input": "&lescc;",
+ "description": "Named entity: lescc; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2aa8"
+ ]
+ ]
+ },
+ {
+ "input": "&lesdot",
+ "description": "Bad named entity: lesdot without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lesdot"
+ ]
+ ]
+ },
+ {
+ "input": "&lesdot;",
+ "description": "Named entity: lesdot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a7f"
+ ]
+ ]
+ },
+ {
+ "input": "&lesdoto",
+ "description": "Bad named entity: lesdoto without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lesdoto"
+ ]
+ ]
+ },
+ {
+ "input": "&lesdoto;",
+ "description": "Named entity: lesdoto; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a81"
+ ]
+ ]
+ },
+ {
+ "input": "&lesdotor",
+ "description": "Bad named entity: lesdotor without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lesdotor"
+ ]
+ ]
+ },
+ {
+ "input": "&lesdotor;",
+ "description": "Named entity: lesdotor; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a83"
+ ]
+ ]
+ },
+ {
+ "input": "&lesg",
+ "description": "Bad named entity: lesg without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lesg"
+ ]
+ ]
+ },
+ {
+ "input": "&lesg;",
+ "description": "Named entity: lesg; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22da\ufe00"
+ ]
+ ]
+ },
+ {
+ "input": "&lesges",
+ "description": "Bad named entity: lesges without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lesges"
+ ]
+ ]
+ },
+ {
+ "input": "&lesges;",
+ "description": "Named entity: lesges; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a93"
+ ]
+ ]
+ },
+ {
+ "input": "&lessapprox",
+ "description": "Bad named entity: lessapprox without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lessapprox"
+ ]
+ ]
+ },
+ {
+ "input": "&lessapprox;",
+ "description": "Named entity: lessapprox; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a85"
+ ]
+ ]
+ },
+ {
+ "input": "&lessdot",
+ "description": "Bad named entity: lessdot without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lessdot"
+ ]
+ ]
+ },
+ {
+ "input": "&lessdot;",
+ "description": "Named entity: lessdot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22d6"
+ ]
+ ]
+ },
+ {
+ "input": "&lesseqgtr",
+ "description": "Bad named entity: lesseqgtr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lesseqgtr"
+ ]
+ ]
+ },
+ {
+ "input": "&lesseqgtr;",
+ "description": "Named entity: lesseqgtr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22da"
+ ]
+ ]
+ },
+ {
+ "input": "&lesseqqgtr",
+ "description": "Bad named entity: lesseqqgtr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lesseqqgtr"
+ ]
+ ]
+ },
+ {
+ "input": "&lesseqqgtr;",
+ "description": "Named entity: lesseqqgtr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a8b"
+ ]
+ ]
+ },
+ {
+ "input": "&lessgtr",
+ "description": "Bad named entity: lessgtr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lessgtr"
+ ]
+ ]
+ },
+ {
+ "input": "&lessgtr;",
+ "description": "Named entity: lessgtr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2276"
+ ]
+ ]
+ },
+ {
+ "input": "&lesssim",
+ "description": "Bad named entity: lesssim without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lesssim"
+ ]
+ ]
+ },
+ {
+ "input": "&lesssim;",
+ "description": "Named entity: lesssim; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2272"
+ ]
+ ]
+ },
+ {
+ "input": "&lfisht",
+ "description": "Bad named entity: lfisht without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lfisht"
+ ]
+ ]
+ },
+ {
+ "input": "&lfisht;",
+ "description": "Named entity: lfisht; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u297c"
+ ]
+ ]
+ },
+ {
+ "input": "&lfloor",
+ "description": "Bad named entity: lfloor without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lfloor"
+ ]
+ ]
+ },
+ {
+ "input": "&lfloor;",
+ "description": "Named entity: lfloor; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u230a"
+ ]
+ ]
+ },
+ {
+ "input": "&lfr",
+ "description": "Bad named entity: lfr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lfr"
+ ]
+ ]
+ },
+ {
+ "input": "&lfr;",
+ "description": "Named entity: lfr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd29"
+ ]
+ ]
+ },
+ {
+ "input": "&lg",
+ "description": "Bad named entity: lg without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lg"
+ ]
+ ]
+ },
+ {
+ "input": "&lg;",
+ "description": "Named entity: lg; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2276"
+ ]
+ ]
+ },
+ {
+ "input": "&lgE",
+ "description": "Bad named entity: lgE without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lgE"
+ ]
+ ]
+ },
+ {
+ "input": "&lgE;",
+ "description": "Named entity: lgE; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a91"
+ ]
+ ]
+ },
+ {
+ "input": "&lhard",
+ "description": "Bad named entity: lhard without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lhard"
+ ]
+ ]
+ },
+ {
+ "input": "&lhard;",
+ "description": "Named entity: lhard; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21bd"
+ ]
+ ]
+ },
+ {
+ "input": "&lharu",
+ "description": "Bad named entity: lharu without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lharu"
+ ]
+ ]
+ },
+ {
+ "input": "&lharu;",
+ "description": "Named entity: lharu; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21bc"
+ ]
+ ]
+ },
+ {
+ "input": "&lharul",
+ "description": "Bad named entity: lharul without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lharul"
+ ]
+ ]
+ },
+ {
+ "input": "&lharul;",
+ "description": "Named entity: lharul; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u296a"
+ ]
+ ]
+ },
+ {
+ "input": "&lhblk",
+ "description": "Bad named entity: lhblk without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lhblk"
+ ]
+ ]
+ },
+ {
+ "input": "&lhblk;",
+ "description": "Named entity: lhblk; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2584"
+ ]
+ ]
+ },
+ {
+ "input": "&ljcy",
+ "description": "Bad named entity: ljcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ljcy"
+ ]
+ ]
+ },
+ {
+ "input": "&ljcy;",
+ "description": "Named entity: ljcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0459"
+ ]
+ ]
+ },
+ {
+ "input": "&ll",
+ "description": "Bad named entity: ll without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ll"
+ ]
+ ]
+ },
+ {
+ "input": "&ll;",
+ "description": "Named entity: ll; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u226a"
+ ]
+ ]
+ },
+ {
+ "input": "&llarr",
+ "description": "Bad named entity: llarr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&llarr"
+ ]
+ ]
+ },
+ {
+ "input": "&llarr;",
+ "description": "Named entity: llarr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21c7"
+ ]
+ ]
+ },
+ {
+ "input": "&llcorner",
+ "description": "Bad named entity: llcorner without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&llcorner"
+ ]
+ ]
+ },
+ {
+ "input": "&llcorner;",
+ "description": "Named entity: llcorner; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u231e"
+ ]
+ ]
+ },
+ {
+ "input": "&llhard",
+ "description": "Bad named entity: llhard without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&llhard"
+ ]
+ ]
+ },
+ {
+ "input": "&llhard;",
+ "description": "Named entity: llhard; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u296b"
+ ]
+ ]
+ },
+ {
+ "input": "&lltri",
+ "description": "Bad named entity: lltri without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lltri"
+ ]
+ ]
+ },
+ {
+ "input": "&lltri;",
+ "description": "Named entity: lltri; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u25fa"
+ ]
+ ]
+ },
+ {
+ "input": "&lmidot",
+ "description": "Bad named entity: lmidot without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lmidot"
+ ]
+ ]
+ },
+ {
+ "input": "&lmidot;",
+ "description": "Named entity: lmidot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0140"
+ ]
+ ]
+ },
+ {
+ "input": "&lmoust",
+ "description": "Bad named entity: lmoust without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lmoust"
+ ]
+ ]
+ },
+ {
+ "input": "&lmoust;",
+ "description": "Named entity: lmoust; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u23b0"
+ ]
+ ]
+ },
+ {
+ "input": "&lmoustache",
+ "description": "Bad named entity: lmoustache without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lmoustache"
+ ]
+ ]
+ },
+ {
+ "input": "&lmoustache;",
+ "description": "Named entity: lmoustache; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u23b0"
+ ]
+ ]
+ },
+ {
+ "input": "&lnE",
+ "description": "Bad named entity: lnE without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lnE"
+ ]
+ ]
+ },
+ {
+ "input": "&lnE;",
+ "description": "Named entity: lnE; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2268"
+ ]
+ ]
+ },
+ {
+ "input": "&lnap",
+ "description": "Bad named entity: lnap without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lnap"
+ ]
+ ]
+ },
+ {
+ "input": "&lnap;",
+ "description": "Named entity: lnap; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a89"
+ ]
+ ]
+ },
+ {
+ "input": "&lnapprox",
+ "description": "Bad named entity: lnapprox without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lnapprox"
+ ]
+ ]
+ },
+ {
+ "input": "&lnapprox;",
+ "description": "Named entity: lnapprox; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a89"
+ ]
+ ]
+ },
+ {
+ "input": "&lne",
+ "description": "Bad named entity: lne without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lne"
+ ]
+ ]
+ },
+ {
+ "input": "&lne;",
+ "description": "Named entity: lne; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a87"
+ ]
+ ]
+ },
+ {
+ "input": "&lneq",
+ "description": "Bad named entity: lneq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lneq"
+ ]
+ ]
+ },
+ {
+ "input": "&lneq;",
+ "description": "Named entity: lneq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a87"
+ ]
+ ]
+ },
+ {
+ "input": "&lneqq",
+ "description": "Bad named entity: lneqq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lneqq"
+ ]
+ ]
+ },
+ {
+ "input": "&lneqq;",
+ "description": "Named entity: lneqq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2268"
+ ]
+ ]
+ },
+ {
+ "input": "&lnsim",
+ "description": "Bad named entity: lnsim without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lnsim"
+ ]
+ ]
+ },
+ {
+ "input": "&lnsim;",
+ "description": "Named entity: lnsim; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22e6"
+ ]
+ ]
+ },
+ {
+ "input": "&loang",
+ "description": "Bad named entity: loang without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&loang"
+ ]
+ ]
+ },
+ {
+ "input": "&loang;",
+ "description": "Named entity: loang; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u27ec"
+ ]
+ ]
+ },
+ {
+ "input": "&loarr",
+ "description": "Bad named entity: loarr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&loarr"
+ ]
+ ]
+ },
+ {
+ "input": "&loarr;",
+ "description": "Named entity: loarr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21fd"
+ ]
+ ]
+ },
+ {
+ "input": "&lobrk",
+ "description": "Bad named entity: lobrk without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lobrk"
+ ]
+ ]
+ },
+ {
+ "input": "&lobrk;",
+ "description": "Named entity: lobrk; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u27e6"
+ ]
+ ]
+ },
+ {
+ "input": "&longleftarrow",
+ "description": "Bad named entity: longleftarrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&longleftarrow"
+ ]
+ ]
+ },
+ {
+ "input": "&longleftarrow;",
+ "description": "Named entity: longleftarrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u27f5"
+ ]
+ ]
+ },
+ {
+ "input": "&longleftrightarrow",
+ "description": "Bad named entity: longleftrightarrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&longleftrightarrow"
+ ]
+ ]
+ },
+ {
+ "input": "&longleftrightarrow;",
+ "description": "Named entity: longleftrightarrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u27f7"
+ ]
+ ]
+ },
+ {
+ "input": "&longmapsto",
+ "description": "Bad named entity: longmapsto without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&longmapsto"
+ ]
+ ]
+ },
+ {
+ "input": "&longmapsto;",
+ "description": "Named entity: longmapsto; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u27fc"
+ ]
+ ]
+ },
+ {
+ "input": "&longrightarrow",
+ "description": "Bad named entity: longrightarrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&longrightarrow"
+ ]
+ ]
+ },
+ {
+ "input": "&longrightarrow;",
+ "description": "Named entity: longrightarrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u27f6"
+ ]
+ ]
+ },
+ {
+ "input": "&looparrowleft",
+ "description": "Bad named entity: looparrowleft without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&looparrowleft"
+ ]
+ ]
+ },
+ {
+ "input": "&looparrowleft;",
+ "description": "Named entity: looparrowleft; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21ab"
+ ]
+ ]
+ },
+ {
+ "input": "&looparrowright",
+ "description": "Bad named entity: looparrowright without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&looparrowright"
+ ]
+ ]
+ },
+ {
+ "input": "&looparrowright;",
+ "description": "Named entity: looparrowright; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21ac"
+ ]
+ ]
+ },
+ {
+ "input": "&lopar",
+ "description": "Bad named entity: lopar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lopar"
+ ]
+ ]
+ },
+ {
+ "input": "&lopar;",
+ "description": "Named entity: lopar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2985"
+ ]
+ ]
+ },
+ {
+ "input": "&lopf",
+ "description": "Bad named entity: lopf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lopf"
+ ]
+ ]
+ },
+ {
+ "input": "&lopf;",
+ "description": "Named entity: lopf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd5d"
+ ]
+ ]
+ },
+ {
+ "input": "&loplus",
+ "description": "Bad named entity: loplus without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&loplus"
+ ]
+ ]
+ },
+ {
+ "input": "&loplus;",
+ "description": "Named entity: loplus; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a2d"
+ ]
+ ]
+ },
+ {
+ "input": "&lotimes",
+ "description": "Bad named entity: lotimes without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lotimes"
+ ]
+ ]
+ },
+ {
+ "input": "&lotimes;",
+ "description": "Named entity: lotimes; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a34"
+ ]
+ ]
+ },
+ {
+ "input": "&lowast",
+ "description": "Bad named entity: lowast without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lowast"
+ ]
+ ]
+ },
+ {
+ "input": "&lowast;",
+ "description": "Named entity: lowast; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2217"
+ ]
+ ]
+ },
+ {
+ "input": "&lowbar",
+ "description": "Bad named entity: lowbar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lowbar"
+ ]
+ ]
+ },
+ {
+ "input": "&lowbar;",
+ "description": "Named entity: lowbar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "_"
+ ]
+ ]
+ },
+ {
+ "input": "&loz",
+ "description": "Bad named entity: loz without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&loz"
+ ]
+ ]
+ },
+ {
+ "input": "&loz;",
+ "description": "Named entity: loz; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u25ca"
+ ]
+ ]
+ },
+ {
+ "input": "&lozenge",
+ "description": "Bad named entity: lozenge without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lozenge"
+ ]
+ ]
+ },
+ {
+ "input": "&lozenge;",
+ "description": "Named entity: lozenge; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u25ca"
+ ]
+ ]
+ },
+ {
+ "input": "&lozf",
+ "description": "Bad named entity: lozf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lozf"
+ ]
+ ]
+ },
+ {
+ "input": "&lozf;",
+ "description": "Named entity: lozf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u29eb"
+ ]
+ ]
+ },
+ {
+ "input": "&lpar",
+ "description": "Bad named entity: lpar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lpar"
+ ]
+ ]
+ },
+ {
+ "input": "&lpar;",
+ "description": "Named entity: lpar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "("
+ ]
+ ]
+ },
+ {
+ "input": "&lparlt",
+ "description": "Bad named entity: lparlt without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lparlt"
+ ]
+ ]
+ },
+ {
+ "input": "&lparlt;",
+ "description": "Named entity: lparlt; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2993"
+ ]
+ ]
+ },
+ {
+ "input": "&lrarr",
+ "description": "Bad named entity: lrarr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lrarr"
+ ]
+ ]
+ },
+ {
+ "input": "&lrarr;",
+ "description": "Named entity: lrarr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21c6"
+ ]
+ ]
+ },
+ {
+ "input": "&lrcorner",
+ "description": "Bad named entity: lrcorner without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lrcorner"
+ ]
+ ]
+ },
+ {
+ "input": "&lrcorner;",
+ "description": "Named entity: lrcorner; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u231f"
+ ]
+ ]
+ },
+ {
+ "input": "&lrhar",
+ "description": "Bad named entity: lrhar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lrhar"
+ ]
+ ]
+ },
+ {
+ "input": "&lrhar;",
+ "description": "Named entity: lrhar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21cb"
+ ]
+ ]
+ },
+ {
+ "input": "&lrhard",
+ "description": "Bad named entity: lrhard without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lrhard"
+ ]
+ ]
+ },
+ {
+ "input": "&lrhard;",
+ "description": "Named entity: lrhard; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u296d"
+ ]
+ ]
+ },
+ {
+ "input": "&lrm",
+ "description": "Bad named entity: lrm without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lrm"
+ ]
+ ]
+ },
+ {
+ "input": "&lrm;",
+ "description": "Named entity: lrm; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u200e"
+ ]
+ ]
+ },
+ {
+ "input": "&lrtri",
+ "description": "Bad named entity: lrtri without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lrtri"
+ ]
+ ]
+ },
+ {
+ "input": "&lrtri;",
+ "description": "Named entity: lrtri; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22bf"
+ ]
+ ]
+ },
+ {
+ "input": "&lsaquo",
+ "description": "Bad named entity: lsaquo without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lsaquo"
+ ]
+ ]
+ },
+ {
+ "input": "&lsaquo;",
+ "description": "Named entity: lsaquo; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2039"
+ ]
+ ]
+ },
+ {
+ "input": "&lscr",
+ "description": "Bad named entity: lscr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lscr"
+ ]
+ ]
+ },
+ {
+ "input": "&lscr;",
+ "description": "Named entity: lscr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udcc1"
+ ]
+ ]
+ },
+ {
+ "input": "&lsh",
+ "description": "Bad named entity: lsh without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lsh"
+ ]
+ ]
+ },
+ {
+ "input": "&lsh;",
+ "description": "Named entity: lsh; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21b0"
+ ]
+ ]
+ },
+ {
+ "input": "&lsim",
+ "description": "Bad named entity: lsim without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lsim"
+ ]
+ ]
+ },
+ {
+ "input": "&lsim;",
+ "description": "Named entity: lsim; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2272"
+ ]
+ ]
+ },
+ {
+ "input": "&lsime",
+ "description": "Bad named entity: lsime without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lsime"
+ ]
+ ]
+ },
+ {
+ "input": "&lsime;",
+ "description": "Named entity: lsime; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a8d"
+ ]
+ ]
+ },
+ {
+ "input": "&lsimg",
+ "description": "Bad named entity: lsimg without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lsimg"
+ ]
+ ]
+ },
+ {
+ "input": "&lsimg;",
+ "description": "Named entity: lsimg; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a8f"
+ ]
+ ]
+ },
+ {
+ "input": "&lsqb",
+ "description": "Bad named entity: lsqb without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lsqb"
+ ]
+ ]
+ },
+ {
+ "input": "&lsqb;",
+ "description": "Named entity: lsqb; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "["
+ ]
+ ]
+ },
+ {
+ "input": "&lsquo",
+ "description": "Bad named entity: lsquo without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lsquo"
+ ]
+ ]
+ },
+ {
+ "input": "&lsquo;",
+ "description": "Named entity: lsquo; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2018"
+ ]
+ ]
+ },
+ {
+ "input": "&lsquor",
+ "description": "Bad named entity: lsquor without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lsquor"
+ ]
+ ]
+ },
+ {
+ "input": "&lsquor;",
+ "description": "Named entity: lsquor; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u201a"
+ ]
+ ]
+ },
+ {
+ "input": "&lstrok",
+ "description": "Bad named entity: lstrok without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lstrok"
+ ]
+ ]
+ },
+ {
+ "input": "&lstrok;",
+ "description": "Named entity: lstrok; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0142"
+ ]
+ ]
+ },
+ {
+ "input": "&lt",
+ "description": "Named entity: lt without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "<"
+ ]
+ ]
+ },
+ {
+ "input": "&lt;",
+ "description": "Named entity: lt; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "<"
+ ]
+ ]
+ },
+ {
+ "input": "&ltcc;",
+ "description": "Named entity: ltcc; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2aa6"
+ ]
+ ]
+ },
+ {
+ "input": "&ltcir;",
+ "description": "Named entity: ltcir; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a79"
+ ]
+ ]
+ },
+ {
+ "input": "&ltdot;",
+ "description": "Named entity: ltdot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22d6"
+ ]
+ ]
+ },
+ {
+ "input": "&lthree;",
+ "description": "Named entity: lthree; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22cb"
+ ]
+ ]
+ },
+ {
+ "input": "&ltimes;",
+ "description": "Named entity: ltimes; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22c9"
+ ]
+ ]
+ },
+ {
+ "input": "&ltlarr;",
+ "description": "Named entity: ltlarr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2976"
+ ]
+ ]
+ },
+ {
+ "input": "&ltquest;",
+ "description": "Named entity: ltquest; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a7b"
+ ]
+ ]
+ },
+ {
+ "input": "&ltrPar;",
+ "description": "Named entity: ltrPar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2996"
+ ]
+ ]
+ },
+ {
+ "input": "&ltri;",
+ "description": "Named entity: ltri; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u25c3"
+ ]
+ ]
+ },
+ {
+ "input": "&ltrie;",
+ "description": "Named entity: ltrie; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22b4"
+ ]
+ ]
+ },
+ {
+ "input": "&ltrif;",
+ "description": "Named entity: ltrif; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u25c2"
+ ]
+ ]
+ },
+ {
+ "input": "&lurdshar",
+ "description": "Bad named entity: lurdshar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lurdshar"
+ ]
+ ]
+ },
+ {
+ "input": "&lurdshar;",
+ "description": "Named entity: lurdshar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u294a"
+ ]
+ ]
+ },
+ {
+ "input": "&luruhar",
+ "description": "Bad named entity: luruhar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&luruhar"
+ ]
+ ]
+ },
+ {
+ "input": "&luruhar;",
+ "description": "Named entity: luruhar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2966"
+ ]
+ ]
+ },
+ {
+ "input": "&lvertneqq",
+ "description": "Bad named entity: lvertneqq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lvertneqq"
+ ]
+ ]
+ },
+ {
+ "input": "&lvertneqq;",
+ "description": "Named entity: lvertneqq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2268\ufe00"
+ ]
+ ]
+ },
+ {
+ "input": "&lvnE",
+ "description": "Bad named entity: lvnE without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&lvnE"
+ ]
+ ]
+ },
+ {
+ "input": "&lvnE;",
+ "description": "Named entity: lvnE; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2268\ufe00"
+ ]
+ ]
+ },
+ {
+ "input": "&mDDot",
+ "description": "Bad named entity: mDDot without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&mDDot"
+ ]
+ ]
+ },
+ {
+ "input": "&mDDot;",
+ "description": "Named entity: mDDot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u223a"
+ ]
+ ]
+ },
+ {
+ "input": "&macr",
+ "description": "Named entity: macr without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00af"
+ ]
+ ]
+ },
+ {
+ "input": "&macr;",
+ "description": "Named entity: macr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00af"
+ ]
+ ]
+ },
+ {
+ "input": "&male",
+ "description": "Bad named entity: male without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&male"
+ ]
+ ]
+ },
+ {
+ "input": "&male;",
+ "description": "Named entity: male; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2642"
+ ]
+ ]
+ },
+ {
+ "input": "&malt",
+ "description": "Bad named entity: malt without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&malt"
+ ]
+ ]
+ },
+ {
+ "input": "&malt;",
+ "description": "Named entity: malt; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2720"
+ ]
+ ]
+ },
+ {
+ "input": "&maltese",
+ "description": "Bad named entity: maltese without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&maltese"
+ ]
+ ]
+ },
+ {
+ "input": "&maltese;",
+ "description": "Named entity: maltese; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2720"
+ ]
+ ]
+ },
+ {
+ "input": "&map",
+ "description": "Bad named entity: map without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&map"
+ ]
+ ]
+ },
+ {
+ "input": "&map;",
+ "description": "Named entity: map; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21a6"
+ ]
+ ]
+ },
+ {
+ "input": "&mapsto",
+ "description": "Bad named entity: mapsto without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&mapsto"
+ ]
+ ]
+ },
+ {
+ "input": "&mapsto;",
+ "description": "Named entity: mapsto; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21a6"
+ ]
+ ]
+ },
+ {
+ "input": "&mapstodown",
+ "description": "Bad named entity: mapstodown without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&mapstodown"
+ ]
+ ]
+ },
+ {
+ "input": "&mapstodown;",
+ "description": "Named entity: mapstodown; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21a7"
+ ]
+ ]
+ },
+ {
+ "input": "&mapstoleft",
+ "description": "Bad named entity: mapstoleft without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&mapstoleft"
+ ]
+ ]
+ },
+ {
+ "input": "&mapstoleft;",
+ "description": "Named entity: mapstoleft; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21a4"
+ ]
+ ]
+ },
+ {
+ "input": "&mapstoup",
+ "description": "Bad named entity: mapstoup without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&mapstoup"
+ ]
+ ]
+ },
+ {
+ "input": "&mapstoup;",
+ "description": "Named entity: mapstoup; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21a5"
+ ]
+ ]
+ },
+ {
+ "input": "&marker",
+ "description": "Bad named entity: marker without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&marker"
+ ]
+ ]
+ },
+ {
+ "input": "&marker;",
+ "description": "Named entity: marker; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u25ae"
+ ]
+ ]
+ },
+ {
+ "input": "&mcomma",
+ "description": "Bad named entity: mcomma without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&mcomma"
+ ]
+ ]
+ },
+ {
+ "input": "&mcomma;",
+ "description": "Named entity: mcomma; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a29"
+ ]
+ ]
+ },
+ {
+ "input": "&mcy",
+ "description": "Bad named entity: mcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&mcy"
+ ]
+ ]
+ },
+ {
+ "input": "&mcy;",
+ "description": "Named entity: mcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u043c"
+ ]
+ ]
+ },
+ {
+ "input": "&mdash",
+ "description": "Bad named entity: mdash without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&mdash"
+ ]
+ ]
+ },
+ {
+ "input": "&mdash;",
+ "description": "Named entity: mdash; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2014"
+ ]
+ ]
+ },
+ {
+ "input": "&measuredangle",
+ "description": "Bad named entity: measuredangle without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&measuredangle"
+ ]
+ ]
+ },
+ {
+ "input": "&measuredangle;",
+ "description": "Named entity: measuredangle; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2221"
+ ]
+ ]
+ },
+ {
+ "input": "&mfr",
+ "description": "Bad named entity: mfr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&mfr"
+ ]
+ ]
+ },
+ {
+ "input": "&mfr;",
+ "description": "Named entity: mfr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd2a"
+ ]
+ ]
+ },
+ {
+ "input": "&mho",
+ "description": "Bad named entity: mho without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&mho"
+ ]
+ ]
+ },
+ {
+ "input": "&mho;",
+ "description": "Named entity: mho; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2127"
+ ]
+ ]
+ },
+ {
+ "input": "&micro",
+ "description": "Named entity: micro without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00b5"
+ ]
+ ]
+ },
+ {
+ "input": "&micro;",
+ "description": "Named entity: micro; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00b5"
+ ]
+ ]
+ },
+ {
+ "input": "&mid",
+ "description": "Bad named entity: mid without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&mid"
+ ]
+ ]
+ },
+ {
+ "input": "&mid;",
+ "description": "Named entity: mid; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2223"
+ ]
+ ]
+ },
+ {
+ "input": "&midast",
+ "description": "Bad named entity: midast without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&midast"
+ ]
+ ]
+ },
+ {
+ "input": "&midast;",
+ "description": "Named entity: midast; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "*"
+ ]
+ ]
+ },
+ {
+ "input": "&midcir",
+ "description": "Bad named entity: midcir without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&midcir"
+ ]
+ ]
+ },
+ {
+ "input": "&midcir;",
+ "description": "Named entity: midcir; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2af0"
+ ]
+ ]
+ },
+ {
+ "input": "&middot",
+ "description": "Named entity: middot without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00b7"
+ ]
+ ]
+ },
+ {
+ "input": "&middot;",
+ "description": "Named entity: middot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00b7"
+ ]
+ ]
+ },
+ {
+ "input": "&minus",
+ "description": "Bad named entity: minus without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&minus"
+ ]
+ ]
+ },
+ {
+ "input": "&minus;",
+ "description": "Named entity: minus; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2212"
+ ]
+ ]
+ },
+ {
+ "input": "&minusb",
+ "description": "Bad named entity: minusb without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&minusb"
+ ]
+ ]
+ },
+ {
+ "input": "&minusb;",
+ "description": "Named entity: minusb; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u229f"
+ ]
+ ]
+ },
+ {
+ "input": "&minusd",
+ "description": "Bad named entity: minusd without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&minusd"
+ ]
+ ]
+ },
+ {
+ "input": "&minusd;",
+ "description": "Named entity: minusd; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2238"
+ ]
+ ]
+ },
+ {
+ "input": "&minusdu",
+ "description": "Bad named entity: minusdu without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&minusdu"
+ ]
+ ]
+ },
+ {
+ "input": "&minusdu;",
+ "description": "Named entity: minusdu; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a2a"
+ ]
+ ]
+ },
+ {
+ "input": "&mlcp",
+ "description": "Bad named entity: mlcp without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&mlcp"
+ ]
+ ]
+ },
+ {
+ "input": "&mlcp;",
+ "description": "Named entity: mlcp; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2adb"
+ ]
+ ]
+ },
+ {
+ "input": "&mldr",
+ "description": "Bad named entity: mldr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&mldr"
+ ]
+ ]
+ },
+ {
+ "input": "&mldr;",
+ "description": "Named entity: mldr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2026"
+ ]
+ ]
+ },
+ {
+ "input": "&mnplus",
+ "description": "Bad named entity: mnplus without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&mnplus"
+ ]
+ ]
+ },
+ {
+ "input": "&mnplus;",
+ "description": "Named entity: mnplus; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2213"
+ ]
+ ]
+ },
+ {
+ "input": "&models",
+ "description": "Bad named entity: models without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&models"
+ ]
+ ]
+ },
+ {
+ "input": "&models;",
+ "description": "Named entity: models; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22a7"
+ ]
+ ]
+ },
+ {
+ "input": "&mopf",
+ "description": "Bad named entity: mopf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&mopf"
+ ]
+ ]
+ },
+ {
+ "input": "&mopf;",
+ "description": "Named entity: mopf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd5e"
+ ]
+ ]
+ },
+ {
+ "input": "&mp",
+ "description": "Bad named entity: mp without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&mp"
+ ]
+ ]
+ },
+ {
+ "input": "&mp;",
+ "description": "Named entity: mp; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2213"
+ ]
+ ]
+ },
+ {
+ "input": "&mscr",
+ "description": "Bad named entity: mscr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&mscr"
+ ]
+ ]
+ },
+ {
+ "input": "&mscr;",
+ "description": "Named entity: mscr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udcc2"
+ ]
+ ]
+ },
+ {
+ "input": "&mstpos",
+ "description": "Bad named entity: mstpos without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&mstpos"
+ ]
+ ]
+ },
+ {
+ "input": "&mstpos;",
+ "description": "Named entity: mstpos; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u223e"
+ ]
+ ]
+ },
+ {
+ "input": "&mu",
+ "description": "Bad named entity: mu without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&mu"
+ ]
+ ]
+ },
+ {
+ "input": "&mu;",
+ "description": "Named entity: mu; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03bc"
+ ]
+ ]
+ },
+ {
+ "input": "&multimap",
+ "description": "Bad named entity: multimap without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&multimap"
+ ]
+ ]
+ },
+ {
+ "input": "&multimap;",
+ "description": "Named entity: multimap; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22b8"
+ ]
+ ]
+ },
+ {
+ "input": "&mumap",
+ "description": "Bad named entity: mumap without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&mumap"
+ ]
+ ]
+ },
+ {
+ "input": "&mumap;",
+ "description": "Named entity: mumap; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22b8"
+ ]
+ ]
+ },
+ {
+ "input": "&nGg",
+ "description": "Bad named entity: nGg without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nGg"
+ ]
+ ]
+ },
+ {
+ "input": "&nGg;",
+ "description": "Named entity: nGg; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22d9\u0338"
+ ]
+ ]
+ },
+ {
+ "input": "&nGt",
+ "description": "Bad named entity: nGt without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nGt"
+ ]
+ ]
+ },
+ {
+ "input": "&nGt;",
+ "description": "Named entity: nGt; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u226b\u20d2"
+ ]
+ ]
+ },
+ {
+ "input": "&nGtv",
+ "description": "Bad named entity: nGtv without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nGtv"
+ ]
+ ]
+ },
+ {
+ "input": "&nGtv;",
+ "description": "Named entity: nGtv; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u226b\u0338"
+ ]
+ ]
+ },
+ {
+ "input": "&nLeftarrow",
+ "description": "Bad named entity: nLeftarrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nLeftarrow"
+ ]
+ ]
+ },
+ {
+ "input": "&nLeftarrow;",
+ "description": "Named entity: nLeftarrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21cd"
+ ]
+ ]
+ },
+ {
+ "input": "&nLeftrightarrow",
+ "description": "Bad named entity: nLeftrightarrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nLeftrightarrow"
+ ]
+ ]
+ },
+ {
+ "input": "&nLeftrightarrow;",
+ "description": "Named entity: nLeftrightarrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21ce"
+ ]
+ ]
+ },
+ {
+ "input": "&nLl",
+ "description": "Bad named entity: nLl without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nLl"
+ ]
+ ]
+ },
+ {
+ "input": "&nLl;",
+ "description": "Named entity: nLl; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22d8\u0338"
+ ]
+ ]
+ },
+ {
+ "input": "&nLt",
+ "description": "Bad named entity: nLt without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nLt"
+ ]
+ ]
+ },
+ {
+ "input": "&nLt;",
+ "description": "Named entity: nLt; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u226a\u20d2"
+ ]
+ ]
+ },
+ {
+ "input": "&nLtv",
+ "description": "Bad named entity: nLtv without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nLtv"
+ ]
+ ]
+ },
+ {
+ "input": "&nLtv;",
+ "description": "Named entity: nLtv; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u226a\u0338"
+ ]
+ ]
+ },
+ {
+ "input": "&nRightarrow",
+ "description": "Bad named entity: nRightarrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nRightarrow"
+ ]
+ ]
+ },
+ {
+ "input": "&nRightarrow;",
+ "description": "Named entity: nRightarrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21cf"
+ ]
+ ]
+ },
+ {
+ "input": "&nVDash",
+ "description": "Bad named entity: nVDash without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nVDash"
+ ]
+ ]
+ },
+ {
+ "input": "&nVDash;",
+ "description": "Named entity: nVDash; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22af"
+ ]
+ ]
+ },
+ {
+ "input": "&nVdash",
+ "description": "Bad named entity: nVdash without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nVdash"
+ ]
+ ]
+ },
+ {
+ "input": "&nVdash;",
+ "description": "Named entity: nVdash; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22ae"
+ ]
+ ]
+ },
+ {
+ "input": "&nabla",
+ "description": "Bad named entity: nabla without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nabla"
+ ]
+ ]
+ },
+ {
+ "input": "&nabla;",
+ "description": "Named entity: nabla; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2207"
+ ]
+ ]
+ },
+ {
+ "input": "&nacute",
+ "description": "Bad named entity: nacute without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nacute"
+ ]
+ ]
+ },
+ {
+ "input": "&nacute;",
+ "description": "Named entity: nacute; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0144"
+ ]
+ ]
+ },
+ {
+ "input": "&nang",
+ "description": "Bad named entity: nang without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nang"
+ ]
+ ]
+ },
+ {
+ "input": "&nang;",
+ "description": "Named entity: nang; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2220\u20d2"
+ ]
+ ]
+ },
+ {
+ "input": "&nap",
+ "description": "Bad named entity: nap without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nap"
+ ]
+ ]
+ },
+ {
+ "input": "&nap;",
+ "description": "Named entity: nap; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2249"
+ ]
+ ]
+ },
+ {
+ "input": "&napE",
+ "description": "Bad named entity: napE without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&napE"
+ ]
+ ]
+ },
+ {
+ "input": "&napE;",
+ "description": "Named entity: napE; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a70\u0338"
+ ]
+ ]
+ },
+ {
+ "input": "&napid",
+ "description": "Bad named entity: napid without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&napid"
+ ]
+ ]
+ },
+ {
+ "input": "&napid;",
+ "description": "Named entity: napid; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u224b\u0338"
+ ]
+ ]
+ },
+ {
+ "input": "&napos",
+ "description": "Bad named entity: napos without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&napos"
+ ]
+ ]
+ },
+ {
+ "input": "&napos;",
+ "description": "Named entity: napos; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0149"
+ ]
+ ]
+ },
+ {
+ "input": "&napprox",
+ "description": "Bad named entity: napprox without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&napprox"
+ ]
+ ]
+ },
+ {
+ "input": "&napprox;",
+ "description": "Named entity: napprox; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2249"
+ ]
+ ]
+ },
+ {
+ "input": "&natur",
+ "description": "Bad named entity: natur without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&natur"
+ ]
+ ]
+ },
+ {
+ "input": "&natur;",
+ "description": "Named entity: natur; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u266e"
+ ]
+ ]
+ },
+ {
+ "input": "&natural",
+ "description": "Bad named entity: natural without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&natural"
+ ]
+ ]
+ },
+ {
+ "input": "&natural;",
+ "description": "Named entity: natural; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u266e"
+ ]
+ ]
+ },
+ {
+ "input": "&naturals",
+ "description": "Bad named entity: naturals without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&naturals"
+ ]
+ ]
+ },
+ {
+ "input": "&naturals;",
+ "description": "Named entity: naturals; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2115"
+ ]
+ ]
+ },
+ {
+ "input": "&nbsp",
+ "description": "Named entity: nbsp without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00a0"
+ ]
+ ]
+ },
+ {
+ "input": "&nbsp;",
+ "description": "Named entity: nbsp; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00a0"
+ ]
+ ]
+ },
+ {
+ "input": "&nbump",
+ "description": "Bad named entity: nbump without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nbump"
+ ]
+ ]
+ },
+ {
+ "input": "&nbump;",
+ "description": "Named entity: nbump; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u224e\u0338"
+ ]
+ ]
+ },
+ {
+ "input": "&nbumpe",
+ "description": "Bad named entity: nbumpe without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nbumpe"
+ ]
+ ]
+ },
+ {
+ "input": "&nbumpe;",
+ "description": "Named entity: nbumpe; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u224f\u0338"
+ ]
+ ]
+ },
+ {
+ "input": "&ncap",
+ "description": "Bad named entity: ncap without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ncap"
+ ]
+ ]
+ },
+ {
+ "input": "&ncap;",
+ "description": "Named entity: ncap; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a43"
+ ]
+ ]
+ },
+ {
+ "input": "&ncaron",
+ "description": "Bad named entity: ncaron without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ncaron"
+ ]
+ ]
+ },
+ {
+ "input": "&ncaron;",
+ "description": "Named entity: ncaron; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0148"
+ ]
+ ]
+ },
+ {
+ "input": "&ncedil",
+ "description": "Bad named entity: ncedil without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ncedil"
+ ]
+ ]
+ },
+ {
+ "input": "&ncedil;",
+ "description": "Named entity: ncedil; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0146"
+ ]
+ ]
+ },
+ {
+ "input": "&ncong",
+ "description": "Bad named entity: ncong without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ncong"
+ ]
+ ]
+ },
+ {
+ "input": "&ncong;",
+ "description": "Named entity: ncong; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2247"
+ ]
+ ]
+ },
+ {
+ "input": "&ncongdot",
+ "description": "Bad named entity: ncongdot without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ncongdot"
+ ]
+ ]
+ },
+ {
+ "input": "&ncongdot;",
+ "description": "Named entity: ncongdot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a6d\u0338"
+ ]
+ ]
+ },
+ {
+ "input": "&ncup",
+ "description": "Bad named entity: ncup without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ncup"
+ ]
+ ]
+ },
+ {
+ "input": "&ncup;",
+ "description": "Named entity: ncup; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a42"
+ ]
+ ]
+ },
+ {
+ "input": "&ncy",
+ "description": "Bad named entity: ncy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ncy"
+ ]
+ ]
+ },
+ {
+ "input": "&ncy;",
+ "description": "Named entity: ncy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u043d"
+ ]
+ ]
+ },
+ {
+ "input": "&ndash",
+ "description": "Bad named entity: ndash without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ndash"
+ ]
+ ]
+ },
+ {
+ "input": "&ndash;",
+ "description": "Named entity: ndash; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2013"
+ ]
+ ]
+ },
+ {
+ "input": "&ne",
+ "description": "Bad named entity: ne without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ne"
+ ]
+ ]
+ },
+ {
+ "input": "&ne;",
+ "description": "Named entity: ne; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2260"
+ ]
+ ]
+ },
+ {
+ "input": "&neArr",
+ "description": "Bad named entity: neArr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&neArr"
+ ]
+ ]
+ },
+ {
+ "input": "&neArr;",
+ "description": "Named entity: neArr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21d7"
+ ]
+ ]
+ },
+ {
+ "input": "&nearhk",
+ "description": "Bad named entity: nearhk without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nearhk"
+ ]
+ ]
+ },
+ {
+ "input": "&nearhk;",
+ "description": "Named entity: nearhk; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2924"
+ ]
+ ]
+ },
+ {
+ "input": "&nearr",
+ "description": "Bad named entity: nearr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nearr"
+ ]
+ ]
+ },
+ {
+ "input": "&nearr;",
+ "description": "Named entity: nearr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2197"
+ ]
+ ]
+ },
+ {
+ "input": "&nearrow",
+ "description": "Bad named entity: nearrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nearrow"
+ ]
+ ]
+ },
+ {
+ "input": "&nearrow;",
+ "description": "Named entity: nearrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2197"
+ ]
+ ]
+ },
+ {
+ "input": "&nedot",
+ "description": "Bad named entity: nedot without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nedot"
+ ]
+ ]
+ },
+ {
+ "input": "&nedot;",
+ "description": "Named entity: nedot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2250\u0338"
+ ]
+ ]
+ },
+ {
+ "input": "&nequiv",
+ "description": "Bad named entity: nequiv without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nequiv"
+ ]
+ ]
+ },
+ {
+ "input": "&nequiv;",
+ "description": "Named entity: nequiv; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2262"
+ ]
+ ]
+ },
+ {
+ "input": "&nesear",
+ "description": "Bad named entity: nesear without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nesear"
+ ]
+ ]
+ },
+ {
+ "input": "&nesear;",
+ "description": "Named entity: nesear; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2928"
+ ]
+ ]
+ },
+ {
+ "input": "&nesim",
+ "description": "Bad named entity: nesim without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nesim"
+ ]
+ ]
+ },
+ {
+ "input": "&nesim;",
+ "description": "Named entity: nesim; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2242\u0338"
+ ]
+ ]
+ },
+ {
+ "input": "&nexist",
+ "description": "Bad named entity: nexist without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nexist"
+ ]
+ ]
+ },
+ {
+ "input": "&nexist;",
+ "description": "Named entity: nexist; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2204"
+ ]
+ ]
+ },
+ {
+ "input": "&nexists",
+ "description": "Bad named entity: nexists without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nexists"
+ ]
+ ]
+ },
+ {
+ "input": "&nexists;",
+ "description": "Named entity: nexists; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2204"
+ ]
+ ]
+ },
+ {
+ "input": "&nfr",
+ "description": "Bad named entity: nfr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nfr"
+ ]
+ ]
+ },
+ {
+ "input": "&nfr;",
+ "description": "Named entity: nfr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd2b"
+ ]
+ ]
+ },
+ {
+ "input": "&ngE",
+ "description": "Bad named entity: ngE without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ngE"
+ ]
+ ]
+ },
+ {
+ "input": "&ngE;",
+ "description": "Named entity: ngE; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2267\u0338"
+ ]
+ ]
+ },
+ {
+ "input": "&nge",
+ "description": "Bad named entity: nge without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nge"
+ ]
+ ]
+ },
+ {
+ "input": "&nge;",
+ "description": "Named entity: nge; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2271"
+ ]
+ ]
+ },
+ {
+ "input": "&ngeq",
+ "description": "Bad named entity: ngeq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ngeq"
+ ]
+ ]
+ },
+ {
+ "input": "&ngeq;",
+ "description": "Named entity: ngeq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2271"
+ ]
+ ]
+ },
+ {
+ "input": "&ngeqq",
+ "description": "Bad named entity: ngeqq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ngeqq"
+ ]
+ ]
+ },
+ {
+ "input": "&ngeqq;",
+ "description": "Named entity: ngeqq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2267\u0338"
+ ]
+ ]
+ },
+ {
+ "input": "&ngeqslant",
+ "description": "Bad named entity: ngeqslant without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ngeqslant"
+ ]
+ ]
+ },
+ {
+ "input": "&ngeqslant;",
+ "description": "Named entity: ngeqslant; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a7e\u0338"
+ ]
+ ]
+ },
+ {
+ "input": "&nges",
+ "description": "Bad named entity: nges without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nges"
+ ]
+ ]
+ },
+ {
+ "input": "&nges;",
+ "description": "Named entity: nges; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a7e\u0338"
+ ]
+ ]
+ },
+ {
+ "input": "&ngsim",
+ "description": "Bad named entity: ngsim without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ngsim"
+ ]
+ ]
+ },
+ {
+ "input": "&ngsim;",
+ "description": "Named entity: ngsim; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2275"
+ ]
+ ]
+ },
+ {
+ "input": "&ngt",
+ "description": "Bad named entity: ngt without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ngt"
+ ]
+ ]
+ },
+ {
+ "input": "&ngt;",
+ "description": "Named entity: ngt; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u226f"
+ ]
+ ]
+ },
+ {
+ "input": "&ngtr",
+ "description": "Bad named entity: ngtr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ngtr"
+ ]
+ ]
+ },
+ {
+ "input": "&ngtr;",
+ "description": "Named entity: ngtr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u226f"
+ ]
+ ]
+ },
+ {
+ "input": "&nhArr",
+ "description": "Bad named entity: nhArr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nhArr"
+ ]
+ ]
+ },
+ {
+ "input": "&nhArr;",
+ "description": "Named entity: nhArr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21ce"
+ ]
+ ]
+ },
+ {
+ "input": "&nharr",
+ "description": "Bad named entity: nharr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nharr"
+ ]
+ ]
+ },
+ {
+ "input": "&nharr;",
+ "description": "Named entity: nharr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21ae"
+ ]
+ ]
+ },
+ {
+ "input": "&nhpar",
+ "description": "Bad named entity: nhpar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nhpar"
+ ]
+ ]
+ },
+ {
+ "input": "&nhpar;",
+ "description": "Named entity: nhpar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2af2"
+ ]
+ ]
+ },
+ {
+ "input": "&ni",
+ "description": "Bad named entity: ni without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ni"
+ ]
+ ]
+ },
+ {
+ "input": "&ni;",
+ "description": "Named entity: ni; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u220b"
+ ]
+ ]
+ },
+ {
+ "input": "&nis",
+ "description": "Bad named entity: nis without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nis"
+ ]
+ ]
+ },
+ {
+ "input": "&nis;",
+ "description": "Named entity: nis; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22fc"
+ ]
+ ]
+ },
+ {
+ "input": "&nisd",
+ "description": "Bad named entity: nisd without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nisd"
+ ]
+ ]
+ },
+ {
+ "input": "&nisd;",
+ "description": "Named entity: nisd; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22fa"
+ ]
+ ]
+ },
+ {
+ "input": "&niv",
+ "description": "Bad named entity: niv without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&niv"
+ ]
+ ]
+ },
+ {
+ "input": "&niv;",
+ "description": "Named entity: niv; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u220b"
+ ]
+ ]
+ },
+ {
+ "input": "&njcy",
+ "description": "Bad named entity: njcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&njcy"
+ ]
+ ]
+ },
+ {
+ "input": "&njcy;",
+ "description": "Named entity: njcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u045a"
+ ]
+ ]
+ },
+ {
+ "input": "&nlArr",
+ "description": "Bad named entity: nlArr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nlArr"
+ ]
+ ]
+ },
+ {
+ "input": "&nlArr;",
+ "description": "Named entity: nlArr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21cd"
+ ]
+ ]
+ },
+ {
+ "input": "&nlE",
+ "description": "Bad named entity: nlE without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nlE"
+ ]
+ ]
+ },
+ {
+ "input": "&nlE;",
+ "description": "Named entity: nlE; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2266\u0338"
+ ]
+ ]
+ },
+ {
+ "input": "&nlarr",
+ "description": "Bad named entity: nlarr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nlarr"
+ ]
+ ]
+ },
+ {
+ "input": "&nlarr;",
+ "description": "Named entity: nlarr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u219a"
+ ]
+ ]
+ },
+ {
+ "input": "&nldr",
+ "description": "Bad named entity: nldr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nldr"
+ ]
+ ]
+ },
+ {
+ "input": "&nldr;",
+ "description": "Named entity: nldr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2025"
+ ]
+ ]
+ },
+ {
+ "input": "&nle",
+ "description": "Bad named entity: nle without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nle"
+ ]
+ ]
+ },
+ {
+ "input": "&nle;",
+ "description": "Named entity: nle; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2270"
+ ]
+ ]
+ },
+ {
+ "input": "&nleftarrow",
+ "description": "Bad named entity: nleftarrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nleftarrow"
+ ]
+ ]
+ },
+ {
+ "input": "&nleftarrow;",
+ "description": "Named entity: nleftarrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u219a"
+ ]
+ ]
+ },
+ {
+ "input": "&nleftrightarrow",
+ "description": "Bad named entity: nleftrightarrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nleftrightarrow"
+ ]
+ ]
+ },
+ {
+ "input": "&nleftrightarrow;",
+ "description": "Named entity: nleftrightarrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21ae"
+ ]
+ ]
+ },
+ {
+ "input": "&nleq",
+ "description": "Bad named entity: nleq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nleq"
+ ]
+ ]
+ },
+ {
+ "input": "&nleq;",
+ "description": "Named entity: nleq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2270"
+ ]
+ ]
+ },
+ {
+ "input": "&nleqq",
+ "description": "Bad named entity: nleqq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nleqq"
+ ]
+ ]
+ },
+ {
+ "input": "&nleqq;",
+ "description": "Named entity: nleqq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2266\u0338"
+ ]
+ ]
+ },
+ {
+ "input": "&nleqslant",
+ "description": "Bad named entity: nleqslant without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nleqslant"
+ ]
+ ]
+ },
+ {
+ "input": "&nleqslant;",
+ "description": "Named entity: nleqslant; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a7d\u0338"
+ ]
+ ]
+ },
+ {
+ "input": "&nles",
+ "description": "Bad named entity: nles without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nles"
+ ]
+ ]
+ },
+ {
+ "input": "&nles;",
+ "description": "Named entity: nles; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a7d\u0338"
+ ]
+ ]
+ },
+ {
+ "input": "&nless",
+ "description": "Bad named entity: nless without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nless"
+ ]
+ ]
+ },
+ {
+ "input": "&nless;",
+ "description": "Named entity: nless; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u226e"
+ ]
+ ]
+ },
+ {
+ "input": "&nlsim",
+ "description": "Bad named entity: nlsim without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nlsim"
+ ]
+ ]
+ },
+ {
+ "input": "&nlsim;",
+ "description": "Named entity: nlsim; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2274"
+ ]
+ ]
+ },
+ {
+ "input": "&nlt",
+ "description": "Bad named entity: nlt without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nlt"
+ ]
+ ]
+ },
+ {
+ "input": "&nlt;",
+ "description": "Named entity: nlt; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u226e"
+ ]
+ ]
+ },
+ {
+ "input": "&nltri",
+ "description": "Bad named entity: nltri without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nltri"
+ ]
+ ]
+ },
+ {
+ "input": "&nltri;",
+ "description": "Named entity: nltri; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22ea"
+ ]
+ ]
+ },
+ {
+ "input": "&nltrie",
+ "description": "Bad named entity: nltrie without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nltrie"
+ ]
+ ]
+ },
+ {
+ "input": "&nltrie;",
+ "description": "Named entity: nltrie; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22ec"
+ ]
+ ]
+ },
+ {
+ "input": "&nmid",
+ "description": "Bad named entity: nmid without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nmid"
+ ]
+ ]
+ },
+ {
+ "input": "&nmid;",
+ "description": "Named entity: nmid; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2224"
+ ]
+ ]
+ },
+ {
+ "input": "&nopf",
+ "description": "Bad named entity: nopf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nopf"
+ ]
+ ]
+ },
+ {
+ "input": "&nopf;",
+ "description": "Named entity: nopf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd5f"
+ ]
+ ]
+ },
+ {
+ "input": "&not",
+ "description": "Named entity: not without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00ac"
+ ]
+ ]
+ },
+ {
+ "input": "&not;",
+ "description": "Named entity: not; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00ac"
+ ]
+ ]
+ },
+ {
+ "input": "&notin;",
+ "description": "Named entity: notin; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2209"
+ ]
+ ]
+ },
+ {
+ "input": "&notinE;",
+ "description": "Named entity: notinE; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22f9\u0338"
+ ]
+ ]
+ },
+ {
+ "input": "&notindot;",
+ "description": "Named entity: notindot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22f5\u0338"
+ ]
+ ]
+ },
+ {
+ "input": "&notinva;",
+ "description": "Named entity: notinva; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2209"
+ ]
+ ]
+ },
+ {
+ "input": "&notinvb;",
+ "description": "Named entity: notinvb; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22f7"
+ ]
+ ]
+ },
+ {
+ "input": "&notinvc;",
+ "description": "Named entity: notinvc; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22f6"
+ ]
+ ]
+ },
+ {
+ "input": "&notni;",
+ "description": "Named entity: notni; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u220c"
+ ]
+ ]
+ },
+ {
+ "input": "&notniva;",
+ "description": "Named entity: notniva; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u220c"
+ ]
+ ]
+ },
+ {
+ "input": "&notnivb;",
+ "description": "Named entity: notnivb; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22fe"
+ ]
+ ]
+ },
+ {
+ "input": "&notnivc;",
+ "description": "Named entity: notnivc; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22fd"
+ ]
+ ]
+ },
+ {
+ "input": "&npar",
+ "description": "Bad named entity: npar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&npar"
+ ]
+ ]
+ },
+ {
+ "input": "&npar;",
+ "description": "Named entity: npar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2226"
+ ]
+ ]
+ },
+ {
+ "input": "&nparallel",
+ "description": "Bad named entity: nparallel without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nparallel"
+ ]
+ ]
+ },
+ {
+ "input": "&nparallel;",
+ "description": "Named entity: nparallel; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2226"
+ ]
+ ]
+ },
+ {
+ "input": "&nparsl",
+ "description": "Bad named entity: nparsl without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nparsl"
+ ]
+ ]
+ },
+ {
+ "input": "&nparsl;",
+ "description": "Named entity: nparsl; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2afd\u20e5"
+ ]
+ ]
+ },
+ {
+ "input": "&npart",
+ "description": "Bad named entity: npart without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&npart"
+ ]
+ ]
+ },
+ {
+ "input": "&npart;",
+ "description": "Named entity: npart; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2202\u0338"
+ ]
+ ]
+ },
+ {
+ "input": "&npolint",
+ "description": "Bad named entity: npolint without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&npolint"
+ ]
+ ]
+ },
+ {
+ "input": "&npolint;",
+ "description": "Named entity: npolint; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a14"
+ ]
+ ]
+ },
+ {
+ "input": "&npr",
+ "description": "Bad named entity: npr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&npr"
+ ]
+ ]
+ },
+ {
+ "input": "&npr;",
+ "description": "Named entity: npr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2280"
+ ]
+ ]
+ },
+ {
+ "input": "&nprcue",
+ "description": "Bad named entity: nprcue without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nprcue"
+ ]
+ ]
+ },
+ {
+ "input": "&nprcue;",
+ "description": "Named entity: nprcue; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22e0"
+ ]
+ ]
+ },
+ {
+ "input": "&npre",
+ "description": "Bad named entity: npre without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&npre"
+ ]
+ ]
+ },
+ {
+ "input": "&npre;",
+ "description": "Named entity: npre; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2aaf\u0338"
+ ]
+ ]
+ },
+ {
+ "input": "&nprec",
+ "description": "Bad named entity: nprec without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nprec"
+ ]
+ ]
+ },
+ {
+ "input": "&nprec;",
+ "description": "Named entity: nprec; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2280"
+ ]
+ ]
+ },
+ {
+ "input": "&npreceq",
+ "description": "Bad named entity: npreceq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&npreceq"
+ ]
+ ]
+ },
+ {
+ "input": "&npreceq;",
+ "description": "Named entity: npreceq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2aaf\u0338"
+ ]
+ ]
+ },
+ {
+ "input": "&nrArr",
+ "description": "Bad named entity: nrArr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nrArr"
+ ]
+ ]
+ },
+ {
+ "input": "&nrArr;",
+ "description": "Named entity: nrArr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21cf"
+ ]
+ ]
+ },
+ {
+ "input": "&nrarr",
+ "description": "Bad named entity: nrarr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nrarr"
+ ]
+ ]
+ },
+ {
+ "input": "&nrarr;",
+ "description": "Named entity: nrarr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u219b"
+ ]
+ ]
+ },
+ {
+ "input": "&nrarrc",
+ "description": "Bad named entity: nrarrc without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nrarrc"
+ ]
+ ]
+ },
+ {
+ "input": "&nrarrc;",
+ "description": "Named entity: nrarrc; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2933\u0338"
+ ]
+ ]
+ },
+ {
+ "input": "&nrarrw",
+ "description": "Bad named entity: nrarrw without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nrarrw"
+ ]
+ ]
+ },
+ {
+ "input": "&nrarrw;",
+ "description": "Named entity: nrarrw; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u219d\u0338"
+ ]
+ ]
+ },
+ {
+ "input": "&nrightarrow",
+ "description": "Bad named entity: nrightarrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nrightarrow"
+ ]
+ ]
+ },
+ {
+ "input": "&nrightarrow;",
+ "description": "Named entity: nrightarrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u219b"
+ ]
+ ]
+ },
+ {
+ "input": "&nrtri",
+ "description": "Bad named entity: nrtri without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nrtri"
+ ]
+ ]
+ },
+ {
+ "input": "&nrtri;",
+ "description": "Named entity: nrtri; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22eb"
+ ]
+ ]
+ },
+ {
+ "input": "&nrtrie",
+ "description": "Bad named entity: nrtrie without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nrtrie"
+ ]
+ ]
+ },
+ {
+ "input": "&nrtrie;",
+ "description": "Named entity: nrtrie; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22ed"
+ ]
+ ]
+ },
+ {
+ "input": "&nsc",
+ "description": "Bad named entity: nsc without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nsc"
+ ]
+ ]
+ },
+ {
+ "input": "&nsc;",
+ "description": "Named entity: nsc; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2281"
+ ]
+ ]
+ },
+ {
+ "input": "&nsccue",
+ "description": "Bad named entity: nsccue without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nsccue"
+ ]
+ ]
+ },
+ {
+ "input": "&nsccue;",
+ "description": "Named entity: nsccue; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22e1"
+ ]
+ ]
+ },
+ {
+ "input": "&nsce",
+ "description": "Bad named entity: nsce without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nsce"
+ ]
+ ]
+ },
+ {
+ "input": "&nsce;",
+ "description": "Named entity: nsce; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2ab0\u0338"
+ ]
+ ]
+ },
+ {
+ "input": "&nscr",
+ "description": "Bad named entity: nscr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nscr"
+ ]
+ ]
+ },
+ {
+ "input": "&nscr;",
+ "description": "Named entity: nscr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udcc3"
+ ]
+ ]
+ },
+ {
+ "input": "&nshortmid",
+ "description": "Bad named entity: nshortmid without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nshortmid"
+ ]
+ ]
+ },
+ {
+ "input": "&nshortmid;",
+ "description": "Named entity: nshortmid; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2224"
+ ]
+ ]
+ },
+ {
+ "input": "&nshortparallel",
+ "description": "Bad named entity: nshortparallel without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nshortparallel"
+ ]
+ ]
+ },
+ {
+ "input": "&nshortparallel;",
+ "description": "Named entity: nshortparallel; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2226"
+ ]
+ ]
+ },
+ {
+ "input": "&nsim",
+ "description": "Bad named entity: nsim without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nsim"
+ ]
+ ]
+ },
+ {
+ "input": "&nsim;",
+ "description": "Named entity: nsim; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2241"
+ ]
+ ]
+ },
+ {
+ "input": "&nsime",
+ "description": "Bad named entity: nsime without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nsime"
+ ]
+ ]
+ },
+ {
+ "input": "&nsime;",
+ "description": "Named entity: nsime; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2244"
+ ]
+ ]
+ },
+ {
+ "input": "&nsimeq",
+ "description": "Bad named entity: nsimeq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nsimeq"
+ ]
+ ]
+ },
+ {
+ "input": "&nsimeq;",
+ "description": "Named entity: nsimeq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2244"
+ ]
+ ]
+ },
+ {
+ "input": "&nsmid",
+ "description": "Bad named entity: nsmid without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nsmid"
+ ]
+ ]
+ },
+ {
+ "input": "&nsmid;",
+ "description": "Named entity: nsmid; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2224"
+ ]
+ ]
+ },
+ {
+ "input": "&nspar",
+ "description": "Bad named entity: nspar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nspar"
+ ]
+ ]
+ },
+ {
+ "input": "&nspar;",
+ "description": "Named entity: nspar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2226"
+ ]
+ ]
+ },
+ {
+ "input": "&nsqsube",
+ "description": "Bad named entity: nsqsube without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nsqsube"
+ ]
+ ]
+ },
+ {
+ "input": "&nsqsube;",
+ "description": "Named entity: nsqsube; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22e2"
+ ]
+ ]
+ },
+ {
+ "input": "&nsqsupe",
+ "description": "Bad named entity: nsqsupe without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nsqsupe"
+ ]
+ ]
+ },
+ {
+ "input": "&nsqsupe;",
+ "description": "Named entity: nsqsupe; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22e3"
+ ]
+ ]
+ },
+ {
+ "input": "&nsub",
+ "description": "Bad named entity: nsub without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nsub"
+ ]
+ ]
+ },
+ {
+ "input": "&nsub;",
+ "description": "Named entity: nsub; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2284"
+ ]
+ ]
+ },
+ {
+ "input": "&nsubE",
+ "description": "Bad named entity: nsubE without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nsubE"
+ ]
+ ]
+ },
+ {
+ "input": "&nsubE;",
+ "description": "Named entity: nsubE; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2ac5\u0338"
+ ]
+ ]
+ },
+ {
+ "input": "&nsube",
+ "description": "Bad named entity: nsube without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nsube"
+ ]
+ ]
+ },
+ {
+ "input": "&nsube;",
+ "description": "Named entity: nsube; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2288"
+ ]
+ ]
+ },
+ {
+ "input": "&nsubset",
+ "description": "Bad named entity: nsubset without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nsubset"
+ ]
+ ]
+ },
+ {
+ "input": "&nsubset;",
+ "description": "Named entity: nsubset; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2282\u20d2"
+ ]
+ ]
+ },
+ {
+ "input": "&nsubseteq",
+ "description": "Bad named entity: nsubseteq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nsubseteq"
+ ]
+ ]
+ },
+ {
+ "input": "&nsubseteq;",
+ "description": "Named entity: nsubseteq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2288"
+ ]
+ ]
+ },
+ {
+ "input": "&nsubseteqq",
+ "description": "Bad named entity: nsubseteqq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nsubseteqq"
+ ]
+ ]
+ },
+ {
+ "input": "&nsubseteqq;",
+ "description": "Named entity: nsubseteqq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2ac5\u0338"
+ ]
+ ]
+ },
+ {
+ "input": "&nsucc",
+ "description": "Bad named entity: nsucc without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nsucc"
+ ]
+ ]
+ },
+ {
+ "input": "&nsucc;",
+ "description": "Named entity: nsucc; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2281"
+ ]
+ ]
+ },
+ {
+ "input": "&nsucceq",
+ "description": "Bad named entity: nsucceq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nsucceq"
+ ]
+ ]
+ },
+ {
+ "input": "&nsucceq;",
+ "description": "Named entity: nsucceq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2ab0\u0338"
+ ]
+ ]
+ },
+ {
+ "input": "&nsup",
+ "description": "Bad named entity: nsup without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nsup"
+ ]
+ ]
+ },
+ {
+ "input": "&nsup;",
+ "description": "Named entity: nsup; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2285"
+ ]
+ ]
+ },
+ {
+ "input": "&nsupE",
+ "description": "Bad named entity: nsupE without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nsupE"
+ ]
+ ]
+ },
+ {
+ "input": "&nsupE;",
+ "description": "Named entity: nsupE; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2ac6\u0338"
+ ]
+ ]
+ },
+ {
+ "input": "&nsupe",
+ "description": "Bad named entity: nsupe without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nsupe"
+ ]
+ ]
+ },
+ {
+ "input": "&nsupe;",
+ "description": "Named entity: nsupe; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2289"
+ ]
+ ]
+ },
+ {
+ "input": "&nsupset",
+ "description": "Bad named entity: nsupset without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nsupset"
+ ]
+ ]
+ },
+ {
+ "input": "&nsupset;",
+ "description": "Named entity: nsupset; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2283\u20d2"
+ ]
+ ]
+ },
+ {
+ "input": "&nsupseteq",
+ "description": "Bad named entity: nsupseteq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nsupseteq"
+ ]
+ ]
+ },
+ {
+ "input": "&nsupseteq;",
+ "description": "Named entity: nsupseteq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2289"
+ ]
+ ]
+ },
+ {
+ "input": "&nsupseteqq",
+ "description": "Bad named entity: nsupseteqq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nsupseteqq"
+ ]
+ ]
+ },
+ {
+ "input": "&nsupseteqq;",
+ "description": "Named entity: nsupseteqq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2ac6\u0338"
+ ]
+ ]
+ },
+ {
+ "input": "&ntgl",
+ "description": "Bad named entity: ntgl without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ntgl"
+ ]
+ ]
+ },
+ {
+ "input": "&ntgl;",
+ "description": "Named entity: ntgl; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2279"
+ ]
+ ]
+ },
+ {
+ "input": "&ntilde",
+ "description": "Named entity: ntilde without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00f1"
+ ]
+ ]
+ },
+ {
+ "input": "&ntilde;",
+ "description": "Named entity: ntilde; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00f1"
+ ]
+ ]
+ },
+ {
+ "input": "&ntlg",
+ "description": "Bad named entity: ntlg without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ntlg"
+ ]
+ ]
+ },
+ {
+ "input": "&ntlg;",
+ "description": "Named entity: ntlg; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2278"
+ ]
+ ]
+ },
+ {
+ "input": "&ntriangleleft",
+ "description": "Bad named entity: ntriangleleft without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ntriangleleft"
+ ]
+ ]
+ },
+ {
+ "input": "&ntriangleleft;",
+ "description": "Named entity: ntriangleleft; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22ea"
+ ]
+ ]
+ },
+ {
+ "input": "&ntrianglelefteq",
+ "description": "Bad named entity: ntrianglelefteq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ntrianglelefteq"
+ ]
+ ]
+ },
+ {
+ "input": "&ntrianglelefteq;",
+ "description": "Named entity: ntrianglelefteq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22ec"
+ ]
+ ]
+ },
+ {
+ "input": "&ntriangleright",
+ "description": "Bad named entity: ntriangleright without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ntriangleright"
+ ]
+ ]
+ },
+ {
+ "input": "&ntriangleright;",
+ "description": "Named entity: ntriangleright; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22eb"
+ ]
+ ]
+ },
+ {
+ "input": "&ntrianglerighteq",
+ "description": "Bad named entity: ntrianglerighteq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ntrianglerighteq"
+ ]
+ ]
+ },
+ {
+ "input": "&ntrianglerighteq;",
+ "description": "Named entity: ntrianglerighteq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22ed"
+ ]
+ ]
+ },
+ {
+ "input": "&nu",
+ "description": "Bad named entity: nu without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nu"
+ ]
+ ]
+ },
+ {
+ "input": "&nu;",
+ "description": "Named entity: nu; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03bd"
+ ]
+ ]
+ },
+ {
+ "input": "&num",
+ "description": "Bad named entity: num without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&num"
+ ]
+ ]
+ },
+ {
+ "input": "&num;",
+ "description": "Named entity: num; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "#"
+ ]
+ ]
+ },
+ {
+ "input": "&numero",
+ "description": "Bad named entity: numero without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&numero"
+ ]
+ ]
+ },
+ {
+ "input": "&numero;",
+ "description": "Named entity: numero; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2116"
+ ]
+ ]
+ },
+ {
+ "input": "&numsp",
+ "description": "Bad named entity: numsp without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&numsp"
+ ]
+ ]
+ },
+ {
+ "input": "&numsp;",
+ "description": "Named entity: numsp; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2007"
+ ]
+ ]
+ },
+ {
+ "input": "&nvDash",
+ "description": "Bad named entity: nvDash without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nvDash"
+ ]
+ ]
+ },
+ {
+ "input": "&nvDash;",
+ "description": "Named entity: nvDash; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22ad"
+ ]
+ ]
+ },
+ {
+ "input": "&nvHarr",
+ "description": "Bad named entity: nvHarr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nvHarr"
+ ]
+ ]
+ },
+ {
+ "input": "&nvHarr;",
+ "description": "Named entity: nvHarr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2904"
+ ]
+ ]
+ },
+ {
+ "input": "&nvap",
+ "description": "Bad named entity: nvap without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nvap"
+ ]
+ ]
+ },
+ {
+ "input": "&nvap;",
+ "description": "Named entity: nvap; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u224d\u20d2"
+ ]
+ ]
+ },
+ {
+ "input": "&nvdash",
+ "description": "Bad named entity: nvdash without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nvdash"
+ ]
+ ]
+ },
+ {
+ "input": "&nvdash;",
+ "description": "Named entity: nvdash; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22ac"
+ ]
+ ]
+ },
+ {
+ "input": "&nvge",
+ "description": "Bad named entity: nvge without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nvge"
+ ]
+ ]
+ },
+ {
+ "input": "&nvge;",
+ "description": "Named entity: nvge; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2265\u20d2"
+ ]
+ ]
+ },
+ {
+ "input": "&nvgt",
+ "description": "Bad named entity: nvgt without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nvgt"
+ ]
+ ]
+ },
+ {
+ "input": "&nvgt;",
+ "description": "Named entity: nvgt; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ ">\u20d2"
+ ]
+ ]
+ },
+ {
+ "input": "&nvinfin",
+ "description": "Bad named entity: nvinfin without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nvinfin"
+ ]
+ ]
+ },
+ {
+ "input": "&nvinfin;",
+ "description": "Named entity: nvinfin; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u29de"
+ ]
+ ]
+ },
+ {
+ "input": "&nvlArr",
+ "description": "Bad named entity: nvlArr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nvlArr"
+ ]
+ ]
+ },
+ {
+ "input": "&nvlArr;",
+ "description": "Named entity: nvlArr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2902"
+ ]
+ ]
+ },
+ {
+ "input": "&nvle",
+ "description": "Bad named entity: nvle without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nvle"
+ ]
+ ]
+ },
+ {
+ "input": "&nvle;",
+ "description": "Named entity: nvle; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2264\u20d2"
+ ]
+ ]
+ },
+ {
+ "input": "&nvlt",
+ "description": "Bad named entity: nvlt without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nvlt"
+ ]
+ ]
+ },
+ {
+ "input": "&nvlt;",
+ "description": "Named entity: nvlt; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "<\u20d2"
+ ]
+ ]
+ },
+ {
+ "input": "&nvltrie",
+ "description": "Bad named entity: nvltrie without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nvltrie"
+ ]
+ ]
+ },
+ {
+ "input": "&nvltrie;",
+ "description": "Named entity: nvltrie; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22b4\u20d2"
+ ]
+ ]
+ },
+ {
+ "input": "&nvrArr",
+ "description": "Bad named entity: nvrArr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nvrArr"
+ ]
+ ]
+ },
+ {
+ "input": "&nvrArr;",
+ "description": "Named entity: nvrArr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2903"
+ ]
+ ]
+ },
+ {
+ "input": "&nvrtrie",
+ "description": "Bad named entity: nvrtrie without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nvrtrie"
+ ]
+ ]
+ },
+ {
+ "input": "&nvrtrie;",
+ "description": "Named entity: nvrtrie; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22b5\u20d2"
+ ]
+ ]
+ },
+ {
+ "input": "&nvsim",
+ "description": "Bad named entity: nvsim without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nvsim"
+ ]
+ ]
+ },
+ {
+ "input": "&nvsim;",
+ "description": "Named entity: nvsim; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u223c\u20d2"
+ ]
+ ]
+ },
+ {
+ "input": "&nwArr",
+ "description": "Bad named entity: nwArr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nwArr"
+ ]
+ ]
+ },
+ {
+ "input": "&nwArr;",
+ "description": "Named entity: nwArr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21d6"
+ ]
+ ]
+ },
+ {
+ "input": "&nwarhk",
+ "description": "Bad named entity: nwarhk without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nwarhk"
+ ]
+ ]
+ },
+ {
+ "input": "&nwarhk;",
+ "description": "Named entity: nwarhk; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2923"
+ ]
+ ]
+ },
+ {
+ "input": "&nwarr",
+ "description": "Bad named entity: nwarr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nwarr"
+ ]
+ ]
+ },
+ {
+ "input": "&nwarr;",
+ "description": "Named entity: nwarr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2196"
+ ]
+ ]
+ },
+ {
+ "input": "&nwarrow",
+ "description": "Bad named entity: nwarrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nwarrow"
+ ]
+ ]
+ },
+ {
+ "input": "&nwarrow;",
+ "description": "Named entity: nwarrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2196"
+ ]
+ ]
+ },
+ {
+ "input": "&nwnear",
+ "description": "Bad named entity: nwnear without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&nwnear"
+ ]
+ ]
+ },
+ {
+ "input": "&nwnear;",
+ "description": "Named entity: nwnear; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2927"
+ ]
+ ]
+ },
+ {
+ "input": "&oS",
+ "description": "Bad named entity: oS without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&oS"
+ ]
+ ]
+ },
+ {
+ "input": "&oS;",
+ "description": "Named entity: oS; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u24c8"
+ ]
+ ]
+ },
+ {
+ "input": "&oacute",
+ "description": "Named entity: oacute without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00f3"
+ ]
+ ]
+ },
+ {
+ "input": "&oacute;",
+ "description": "Named entity: oacute; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00f3"
+ ]
+ ]
+ },
+ {
+ "input": "&oast",
+ "description": "Bad named entity: oast without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&oast"
+ ]
+ ]
+ },
+ {
+ "input": "&oast;",
+ "description": "Named entity: oast; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u229b"
+ ]
+ ]
+ },
+ {
+ "input": "&ocir",
+ "description": "Bad named entity: ocir without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ocir"
+ ]
+ ]
+ },
+ {
+ "input": "&ocir;",
+ "description": "Named entity: ocir; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u229a"
+ ]
+ ]
+ },
+ {
+ "input": "&ocirc",
+ "description": "Named entity: ocirc without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00f4"
+ ]
+ ]
+ },
+ {
+ "input": "&ocirc;",
+ "description": "Named entity: ocirc; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00f4"
+ ]
+ ]
+ },
+ {
+ "input": "&ocy",
+ "description": "Bad named entity: ocy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ocy"
+ ]
+ ]
+ },
+ {
+ "input": "&ocy;",
+ "description": "Named entity: ocy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u043e"
+ ]
+ ]
+ },
+ {
+ "input": "&odash",
+ "description": "Bad named entity: odash without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&odash"
+ ]
+ ]
+ },
+ {
+ "input": "&odash;",
+ "description": "Named entity: odash; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u229d"
+ ]
+ ]
+ },
+ {
+ "input": "&odblac",
+ "description": "Bad named entity: odblac without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&odblac"
+ ]
+ ]
+ },
+ {
+ "input": "&odblac;",
+ "description": "Named entity: odblac; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0151"
+ ]
+ ]
+ },
+ {
+ "input": "&odiv",
+ "description": "Bad named entity: odiv without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&odiv"
+ ]
+ ]
+ },
+ {
+ "input": "&odiv;",
+ "description": "Named entity: odiv; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a38"
+ ]
+ ]
+ },
+ {
+ "input": "&odot",
+ "description": "Bad named entity: odot without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&odot"
+ ]
+ ]
+ },
+ {
+ "input": "&odot;",
+ "description": "Named entity: odot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2299"
+ ]
+ ]
+ },
+ {
+ "input": "&odsold",
+ "description": "Bad named entity: odsold without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&odsold"
+ ]
+ ]
+ },
+ {
+ "input": "&odsold;",
+ "description": "Named entity: odsold; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u29bc"
+ ]
+ ]
+ },
+ {
+ "input": "&oelig",
+ "description": "Bad named entity: oelig without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&oelig"
+ ]
+ ]
+ },
+ {
+ "input": "&oelig;",
+ "description": "Named entity: oelig; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0153"
+ ]
+ ]
+ },
+ {
+ "input": "&ofcir",
+ "description": "Bad named entity: ofcir without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ofcir"
+ ]
+ ]
+ },
+ {
+ "input": "&ofcir;",
+ "description": "Named entity: ofcir; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u29bf"
+ ]
+ ]
+ },
+ {
+ "input": "&ofr",
+ "description": "Bad named entity: ofr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ofr"
+ ]
+ ]
+ },
+ {
+ "input": "&ofr;",
+ "description": "Named entity: ofr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd2c"
+ ]
+ ]
+ },
+ {
+ "input": "&ogon",
+ "description": "Bad named entity: ogon without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ogon"
+ ]
+ ]
+ },
+ {
+ "input": "&ogon;",
+ "description": "Named entity: ogon; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u02db"
+ ]
+ ]
+ },
+ {
+ "input": "&ograve",
+ "description": "Named entity: ograve without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00f2"
+ ]
+ ]
+ },
+ {
+ "input": "&ograve;",
+ "description": "Named entity: ograve; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00f2"
+ ]
+ ]
+ },
+ {
+ "input": "&ogt",
+ "description": "Bad named entity: ogt without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ogt"
+ ]
+ ]
+ },
+ {
+ "input": "&ogt;",
+ "description": "Named entity: ogt; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u29c1"
+ ]
+ ]
+ },
+ {
+ "input": "&ohbar",
+ "description": "Bad named entity: ohbar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ohbar"
+ ]
+ ]
+ },
+ {
+ "input": "&ohbar;",
+ "description": "Named entity: ohbar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u29b5"
+ ]
+ ]
+ },
+ {
+ "input": "&ohm",
+ "description": "Bad named entity: ohm without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ohm"
+ ]
+ ]
+ },
+ {
+ "input": "&ohm;",
+ "description": "Named entity: ohm; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03a9"
+ ]
+ ]
+ },
+ {
+ "input": "&oint",
+ "description": "Bad named entity: oint without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&oint"
+ ]
+ ]
+ },
+ {
+ "input": "&oint;",
+ "description": "Named entity: oint; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u222e"
+ ]
+ ]
+ },
+ {
+ "input": "&olarr",
+ "description": "Bad named entity: olarr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&olarr"
+ ]
+ ]
+ },
+ {
+ "input": "&olarr;",
+ "description": "Named entity: olarr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21ba"
+ ]
+ ]
+ },
+ {
+ "input": "&olcir",
+ "description": "Bad named entity: olcir without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&olcir"
+ ]
+ ]
+ },
+ {
+ "input": "&olcir;",
+ "description": "Named entity: olcir; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u29be"
+ ]
+ ]
+ },
+ {
+ "input": "&olcross",
+ "description": "Bad named entity: olcross without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&olcross"
+ ]
+ ]
+ },
+ {
+ "input": "&olcross;",
+ "description": "Named entity: olcross; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u29bb"
+ ]
+ ]
+ },
+ {
+ "input": "&oline",
+ "description": "Bad named entity: oline without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&oline"
+ ]
+ ]
+ },
+ {
+ "input": "&oline;",
+ "description": "Named entity: oline; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u203e"
+ ]
+ ]
+ },
+ {
+ "input": "&olt",
+ "description": "Bad named entity: olt without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&olt"
+ ]
+ ]
+ },
+ {
+ "input": "&olt;",
+ "description": "Named entity: olt; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u29c0"
+ ]
+ ]
+ },
+ {
+ "input": "&omacr",
+ "description": "Bad named entity: omacr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&omacr"
+ ]
+ ]
+ },
+ {
+ "input": "&omacr;",
+ "description": "Named entity: omacr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u014d"
+ ]
+ ]
+ },
+ {
+ "input": "&omega",
+ "description": "Bad named entity: omega without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&omega"
+ ]
+ ]
+ },
+ {
+ "input": "&omega;",
+ "description": "Named entity: omega; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03c9"
+ ]
+ ]
+ },
+ {
+ "input": "&omicron",
+ "description": "Bad named entity: omicron without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&omicron"
+ ]
+ ]
+ },
+ {
+ "input": "&omicron;",
+ "description": "Named entity: omicron; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03bf"
+ ]
+ ]
+ },
+ {
+ "input": "&omid",
+ "description": "Bad named entity: omid without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&omid"
+ ]
+ ]
+ },
+ {
+ "input": "&omid;",
+ "description": "Named entity: omid; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u29b6"
+ ]
+ ]
+ },
+ {
+ "input": "&ominus",
+ "description": "Bad named entity: ominus without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ominus"
+ ]
+ ]
+ },
+ {
+ "input": "&ominus;",
+ "description": "Named entity: ominus; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2296"
+ ]
+ ]
+ },
+ {
+ "input": "&oopf",
+ "description": "Bad named entity: oopf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&oopf"
+ ]
+ ]
+ },
+ {
+ "input": "&oopf;",
+ "description": "Named entity: oopf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd60"
+ ]
+ ]
+ },
+ {
+ "input": "&opar",
+ "description": "Bad named entity: opar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&opar"
+ ]
+ ]
+ },
+ {
+ "input": "&opar;",
+ "description": "Named entity: opar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u29b7"
+ ]
+ ]
+ },
+ {
+ "input": "&operp",
+ "description": "Bad named entity: operp without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&operp"
+ ]
+ ]
+ },
+ {
+ "input": "&operp;",
+ "description": "Named entity: operp; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u29b9"
+ ]
+ ]
+ },
+ {
+ "input": "&oplus",
+ "description": "Bad named entity: oplus without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&oplus"
+ ]
+ ]
+ },
+ {
+ "input": "&oplus;",
+ "description": "Named entity: oplus; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2295"
+ ]
+ ]
+ },
+ {
+ "input": "&or",
+ "description": "Bad named entity: or without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&or"
+ ]
+ ]
+ },
+ {
+ "input": "&or;",
+ "description": "Named entity: or; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2228"
+ ]
+ ]
+ },
+ {
+ "input": "&orarr",
+ "description": "Bad named entity: orarr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&orarr"
+ ]
+ ]
+ },
+ {
+ "input": "&orarr;",
+ "description": "Named entity: orarr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21bb"
+ ]
+ ]
+ },
+ {
+ "input": "&ord",
+ "description": "Bad named entity: ord without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ord"
+ ]
+ ]
+ },
+ {
+ "input": "&ord;",
+ "description": "Named entity: ord; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a5d"
+ ]
+ ]
+ },
+ {
+ "input": "&order",
+ "description": "Bad named entity: order without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&order"
+ ]
+ ]
+ },
+ {
+ "input": "&order;",
+ "description": "Named entity: order; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2134"
+ ]
+ ]
+ },
+ {
+ "input": "&orderof",
+ "description": "Bad named entity: orderof without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&orderof"
+ ]
+ ]
+ },
+ {
+ "input": "&orderof;",
+ "description": "Named entity: orderof; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2134"
+ ]
+ ]
+ },
+ {
+ "input": "&ordf",
+ "description": "Named entity: ordf without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00aa"
+ ]
+ ]
+ },
+ {
+ "input": "&ordf;",
+ "description": "Named entity: ordf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00aa"
+ ]
+ ]
+ },
+ {
+ "input": "&ordm",
+ "description": "Named entity: ordm without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00ba"
+ ]
+ ]
+ },
+ {
+ "input": "&ordm;",
+ "description": "Named entity: ordm; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00ba"
+ ]
+ ]
+ },
+ {
+ "input": "&origof",
+ "description": "Bad named entity: origof without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&origof"
+ ]
+ ]
+ },
+ {
+ "input": "&origof;",
+ "description": "Named entity: origof; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22b6"
+ ]
+ ]
+ },
+ {
+ "input": "&oror",
+ "description": "Bad named entity: oror without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&oror"
+ ]
+ ]
+ },
+ {
+ "input": "&oror;",
+ "description": "Named entity: oror; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a56"
+ ]
+ ]
+ },
+ {
+ "input": "&orslope",
+ "description": "Bad named entity: orslope without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&orslope"
+ ]
+ ]
+ },
+ {
+ "input": "&orslope;",
+ "description": "Named entity: orslope; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a57"
+ ]
+ ]
+ },
+ {
+ "input": "&orv",
+ "description": "Bad named entity: orv without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&orv"
+ ]
+ ]
+ },
+ {
+ "input": "&orv;",
+ "description": "Named entity: orv; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a5b"
+ ]
+ ]
+ },
+ {
+ "input": "&oscr",
+ "description": "Bad named entity: oscr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&oscr"
+ ]
+ ]
+ },
+ {
+ "input": "&oscr;",
+ "description": "Named entity: oscr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2134"
+ ]
+ ]
+ },
+ {
+ "input": "&oslash",
+ "description": "Named entity: oslash without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00f8"
+ ]
+ ]
+ },
+ {
+ "input": "&oslash;",
+ "description": "Named entity: oslash; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00f8"
+ ]
+ ]
+ },
+ {
+ "input": "&osol",
+ "description": "Bad named entity: osol without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&osol"
+ ]
+ ]
+ },
+ {
+ "input": "&osol;",
+ "description": "Named entity: osol; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2298"
+ ]
+ ]
+ },
+ {
+ "input": "&otilde",
+ "description": "Named entity: otilde without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00f5"
+ ]
+ ]
+ },
+ {
+ "input": "&otilde;",
+ "description": "Named entity: otilde; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00f5"
+ ]
+ ]
+ },
+ {
+ "input": "&otimes",
+ "description": "Bad named entity: otimes without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&otimes"
+ ]
+ ]
+ },
+ {
+ "input": "&otimes;",
+ "description": "Named entity: otimes; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2297"
+ ]
+ ]
+ },
+ {
+ "input": "&otimesas",
+ "description": "Bad named entity: otimesas without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&otimesas"
+ ]
+ ]
+ },
+ {
+ "input": "&otimesas;",
+ "description": "Named entity: otimesas; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a36"
+ ]
+ ]
+ },
+ {
+ "input": "&ouml",
+ "description": "Named entity: ouml without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00f6"
+ ]
+ ]
+ },
+ {
+ "input": "&ouml;",
+ "description": "Named entity: ouml; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00f6"
+ ]
+ ]
+ },
+ {
+ "input": "&ovbar",
+ "description": "Bad named entity: ovbar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ovbar"
+ ]
+ ]
+ },
+ {
+ "input": "&ovbar;",
+ "description": "Named entity: ovbar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u233d"
+ ]
+ ]
+ },
+ {
+ "input": "&par",
+ "description": "Bad named entity: par without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&par"
+ ]
+ ]
+ },
+ {
+ "input": "&par;",
+ "description": "Named entity: par; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2225"
+ ]
+ ]
+ },
+ {
+ "input": "&para",
+ "description": "Named entity: para without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00b6"
+ ]
+ ]
+ },
+ {
+ "input": "&para;",
+ "description": "Named entity: para; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00b6"
+ ]
+ ]
+ },
+ {
+ "input": "&parallel;",
+ "description": "Named entity: parallel; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2225"
+ ]
+ ]
+ },
+ {
+ "input": "&parsim",
+ "description": "Bad named entity: parsim without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&parsim"
+ ]
+ ]
+ },
+ {
+ "input": "&parsim;",
+ "description": "Named entity: parsim; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2af3"
+ ]
+ ]
+ },
+ {
+ "input": "&parsl",
+ "description": "Bad named entity: parsl without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&parsl"
+ ]
+ ]
+ },
+ {
+ "input": "&parsl;",
+ "description": "Named entity: parsl; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2afd"
+ ]
+ ]
+ },
+ {
+ "input": "&part",
+ "description": "Bad named entity: part without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&part"
+ ]
+ ]
+ },
+ {
+ "input": "&part;",
+ "description": "Named entity: part; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2202"
+ ]
+ ]
+ },
+ {
+ "input": "&pcy",
+ "description": "Bad named entity: pcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&pcy"
+ ]
+ ]
+ },
+ {
+ "input": "&pcy;",
+ "description": "Named entity: pcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u043f"
+ ]
+ ]
+ },
+ {
+ "input": "&percnt",
+ "description": "Bad named entity: percnt without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&percnt"
+ ]
+ ]
+ },
+ {
+ "input": "&percnt;",
+ "description": "Named entity: percnt; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "%"
+ ]
+ ]
+ },
+ {
+ "input": "&period",
+ "description": "Bad named entity: period without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&period"
+ ]
+ ]
+ },
+ {
+ "input": "&period;",
+ "description": "Named entity: period; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "."
+ ]
+ ]
+ },
+ {
+ "input": "&permil",
+ "description": "Bad named entity: permil without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&permil"
+ ]
+ ]
+ },
+ {
+ "input": "&permil;",
+ "description": "Named entity: permil; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2030"
+ ]
+ ]
+ },
+ {
+ "input": "&perp",
+ "description": "Bad named entity: perp without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&perp"
+ ]
+ ]
+ },
+ {
+ "input": "&perp;",
+ "description": "Named entity: perp; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22a5"
+ ]
+ ]
+ },
+ {
+ "input": "&pertenk",
+ "description": "Bad named entity: pertenk without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&pertenk"
+ ]
+ ]
+ },
+ {
+ "input": "&pertenk;",
+ "description": "Named entity: pertenk; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2031"
+ ]
+ ]
+ },
+ {
+ "input": "&pfr",
+ "description": "Bad named entity: pfr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&pfr"
+ ]
+ ]
+ },
+ {
+ "input": "&pfr;",
+ "description": "Named entity: pfr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd2d"
+ ]
+ ]
+ },
+ {
+ "input": "&phi",
+ "description": "Bad named entity: phi without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&phi"
+ ]
+ ]
+ },
+ {
+ "input": "&phi;",
+ "description": "Named entity: phi; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03c6"
+ ]
+ ]
+ },
+ {
+ "input": "&phiv",
+ "description": "Bad named entity: phiv without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&phiv"
+ ]
+ ]
+ },
+ {
+ "input": "&phiv;",
+ "description": "Named entity: phiv; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03d5"
+ ]
+ ]
+ },
+ {
+ "input": "&phmmat",
+ "description": "Bad named entity: phmmat without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&phmmat"
+ ]
+ ]
+ },
+ {
+ "input": "&phmmat;",
+ "description": "Named entity: phmmat; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2133"
+ ]
+ ]
+ },
+ {
+ "input": "&phone",
+ "description": "Bad named entity: phone without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&phone"
+ ]
+ ]
+ },
+ {
+ "input": "&phone;",
+ "description": "Named entity: phone; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u260e"
+ ]
+ ]
+ },
+ {
+ "input": "&pi",
+ "description": "Bad named entity: pi without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&pi"
+ ]
+ ]
+ },
+ {
+ "input": "&pi;",
+ "description": "Named entity: pi; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03c0"
+ ]
+ ]
+ },
+ {
+ "input": "&pitchfork",
+ "description": "Bad named entity: pitchfork without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&pitchfork"
+ ]
+ ]
+ },
+ {
+ "input": "&pitchfork;",
+ "description": "Named entity: pitchfork; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22d4"
+ ]
+ ]
+ },
+ {
+ "input": "&piv",
+ "description": "Bad named entity: piv without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&piv"
+ ]
+ ]
+ },
+ {
+ "input": "&piv;",
+ "description": "Named entity: piv; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03d6"
+ ]
+ ]
+ },
+ {
+ "input": "&planck",
+ "description": "Bad named entity: planck without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&planck"
+ ]
+ ]
+ },
+ {
+ "input": "&planck;",
+ "description": "Named entity: planck; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u210f"
+ ]
+ ]
+ },
+ {
+ "input": "&planckh",
+ "description": "Bad named entity: planckh without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&planckh"
+ ]
+ ]
+ },
+ {
+ "input": "&planckh;",
+ "description": "Named entity: planckh; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u210e"
+ ]
+ ]
+ },
+ {
+ "input": "&plankv",
+ "description": "Bad named entity: plankv without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&plankv"
+ ]
+ ]
+ },
+ {
+ "input": "&plankv;",
+ "description": "Named entity: plankv; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u210f"
+ ]
+ ]
+ },
+ {
+ "input": "&plus",
+ "description": "Bad named entity: plus without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&plus"
+ ]
+ ]
+ },
+ {
+ "input": "&plus;",
+ "description": "Named entity: plus; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "+"
+ ]
+ ]
+ },
+ {
+ "input": "&plusacir",
+ "description": "Bad named entity: plusacir without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&plusacir"
+ ]
+ ]
+ },
+ {
+ "input": "&plusacir;",
+ "description": "Named entity: plusacir; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a23"
+ ]
+ ]
+ },
+ {
+ "input": "&plusb",
+ "description": "Bad named entity: plusb without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&plusb"
+ ]
+ ]
+ },
+ {
+ "input": "&plusb;",
+ "description": "Named entity: plusb; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u229e"
+ ]
+ ]
+ },
+ {
+ "input": "&pluscir",
+ "description": "Bad named entity: pluscir without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&pluscir"
+ ]
+ ]
+ },
+ {
+ "input": "&pluscir;",
+ "description": "Named entity: pluscir; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a22"
+ ]
+ ]
+ },
+ {
+ "input": "&plusdo",
+ "description": "Bad named entity: plusdo without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&plusdo"
+ ]
+ ]
+ },
+ {
+ "input": "&plusdo;",
+ "description": "Named entity: plusdo; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2214"
+ ]
+ ]
+ },
+ {
+ "input": "&plusdu",
+ "description": "Bad named entity: plusdu without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&plusdu"
+ ]
+ ]
+ },
+ {
+ "input": "&plusdu;",
+ "description": "Named entity: plusdu; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a25"
+ ]
+ ]
+ },
+ {
+ "input": "&pluse",
+ "description": "Bad named entity: pluse without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&pluse"
+ ]
+ ]
+ },
+ {
+ "input": "&pluse;",
+ "description": "Named entity: pluse; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a72"
+ ]
+ ]
+ },
+ {
+ "input": "&plusmn",
+ "description": "Named entity: plusmn without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00b1"
+ ]
+ ]
+ },
+ {
+ "input": "&plusmn;",
+ "description": "Named entity: plusmn; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00b1"
+ ]
+ ]
+ },
+ {
+ "input": "&plussim",
+ "description": "Bad named entity: plussim without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&plussim"
+ ]
+ ]
+ },
+ {
+ "input": "&plussim;",
+ "description": "Named entity: plussim; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a26"
+ ]
+ ]
+ },
+ {
+ "input": "&plustwo",
+ "description": "Bad named entity: plustwo without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&plustwo"
+ ]
+ ]
+ },
+ {
+ "input": "&plustwo;",
+ "description": "Named entity: plustwo; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a27"
+ ]
+ ]
+ },
+ {
+ "input": "&pm",
+ "description": "Bad named entity: pm without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&pm"
+ ]
+ ]
+ },
+ {
+ "input": "&pm;",
+ "description": "Named entity: pm; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00b1"
+ ]
+ ]
+ },
+ {
+ "input": "&pointint",
+ "description": "Bad named entity: pointint without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&pointint"
+ ]
+ ]
+ },
+ {
+ "input": "&pointint;",
+ "description": "Named entity: pointint; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a15"
+ ]
+ ]
+ },
+ {
+ "input": "&popf",
+ "description": "Bad named entity: popf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&popf"
+ ]
+ ]
+ },
+ {
+ "input": "&popf;",
+ "description": "Named entity: popf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd61"
+ ]
+ ]
+ },
+ {
+ "input": "&pound",
+ "description": "Named entity: pound without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00a3"
+ ]
+ ]
+ },
+ {
+ "input": "&pound;",
+ "description": "Named entity: pound; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00a3"
+ ]
+ ]
+ },
+ {
+ "input": "&pr",
+ "description": "Bad named entity: pr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&pr"
+ ]
+ ]
+ },
+ {
+ "input": "&pr;",
+ "description": "Named entity: pr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u227a"
+ ]
+ ]
+ },
+ {
+ "input": "&prE",
+ "description": "Bad named entity: prE without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&prE"
+ ]
+ ]
+ },
+ {
+ "input": "&prE;",
+ "description": "Named entity: prE; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2ab3"
+ ]
+ ]
+ },
+ {
+ "input": "&prap",
+ "description": "Bad named entity: prap without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&prap"
+ ]
+ ]
+ },
+ {
+ "input": "&prap;",
+ "description": "Named entity: prap; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2ab7"
+ ]
+ ]
+ },
+ {
+ "input": "&prcue",
+ "description": "Bad named entity: prcue without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&prcue"
+ ]
+ ]
+ },
+ {
+ "input": "&prcue;",
+ "description": "Named entity: prcue; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u227c"
+ ]
+ ]
+ },
+ {
+ "input": "&pre",
+ "description": "Bad named entity: pre without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&pre"
+ ]
+ ]
+ },
+ {
+ "input": "&pre;",
+ "description": "Named entity: pre; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2aaf"
+ ]
+ ]
+ },
+ {
+ "input": "&prec",
+ "description": "Bad named entity: prec without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&prec"
+ ]
+ ]
+ },
+ {
+ "input": "&prec;",
+ "description": "Named entity: prec; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u227a"
+ ]
+ ]
+ },
+ {
+ "input": "&precapprox",
+ "description": "Bad named entity: precapprox without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&precapprox"
+ ]
+ ]
+ },
+ {
+ "input": "&precapprox;",
+ "description": "Named entity: precapprox; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2ab7"
+ ]
+ ]
+ },
+ {
+ "input": "&preccurlyeq",
+ "description": "Bad named entity: preccurlyeq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&preccurlyeq"
+ ]
+ ]
+ },
+ {
+ "input": "&preccurlyeq;",
+ "description": "Named entity: preccurlyeq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u227c"
+ ]
+ ]
+ },
+ {
+ "input": "&preceq",
+ "description": "Bad named entity: preceq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&preceq"
+ ]
+ ]
+ },
+ {
+ "input": "&preceq;",
+ "description": "Named entity: preceq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2aaf"
+ ]
+ ]
+ },
+ {
+ "input": "&precnapprox",
+ "description": "Bad named entity: precnapprox without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&precnapprox"
+ ]
+ ]
+ },
+ {
+ "input": "&precnapprox;",
+ "description": "Named entity: precnapprox; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2ab9"
+ ]
+ ]
+ },
+ {
+ "input": "&precneqq",
+ "description": "Bad named entity: precneqq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&precneqq"
+ ]
+ ]
+ },
+ {
+ "input": "&precneqq;",
+ "description": "Named entity: precneqq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2ab5"
+ ]
+ ]
+ },
+ {
+ "input": "&precnsim",
+ "description": "Bad named entity: precnsim without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&precnsim"
+ ]
+ ]
+ },
+ {
+ "input": "&precnsim;",
+ "description": "Named entity: precnsim; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22e8"
+ ]
+ ]
+ },
+ {
+ "input": "&precsim",
+ "description": "Bad named entity: precsim without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&precsim"
+ ]
+ ]
+ },
+ {
+ "input": "&precsim;",
+ "description": "Named entity: precsim; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u227e"
+ ]
+ ]
+ },
+ {
+ "input": "&prime",
+ "description": "Bad named entity: prime without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&prime"
+ ]
+ ]
+ },
+ {
+ "input": "&prime;",
+ "description": "Named entity: prime; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2032"
+ ]
+ ]
+ },
+ {
+ "input": "&primes",
+ "description": "Bad named entity: primes without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&primes"
+ ]
+ ]
+ },
+ {
+ "input": "&primes;",
+ "description": "Named entity: primes; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2119"
+ ]
+ ]
+ },
+ {
+ "input": "&prnE",
+ "description": "Bad named entity: prnE without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&prnE"
+ ]
+ ]
+ },
+ {
+ "input": "&prnE;",
+ "description": "Named entity: prnE; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2ab5"
+ ]
+ ]
+ },
+ {
+ "input": "&prnap",
+ "description": "Bad named entity: prnap without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&prnap"
+ ]
+ ]
+ },
+ {
+ "input": "&prnap;",
+ "description": "Named entity: prnap; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2ab9"
+ ]
+ ]
+ },
+ {
+ "input": "&prnsim",
+ "description": "Bad named entity: prnsim without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&prnsim"
+ ]
+ ]
+ },
+ {
+ "input": "&prnsim;",
+ "description": "Named entity: prnsim; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22e8"
+ ]
+ ]
+ },
+ {
+ "input": "&prod",
+ "description": "Bad named entity: prod without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&prod"
+ ]
+ ]
+ },
+ {
+ "input": "&prod;",
+ "description": "Named entity: prod; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u220f"
+ ]
+ ]
+ },
+ {
+ "input": "&profalar",
+ "description": "Bad named entity: profalar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&profalar"
+ ]
+ ]
+ },
+ {
+ "input": "&profalar;",
+ "description": "Named entity: profalar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u232e"
+ ]
+ ]
+ },
+ {
+ "input": "&profline",
+ "description": "Bad named entity: profline without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&profline"
+ ]
+ ]
+ },
+ {
+ "input": "&profline;",
+ "description": "Named entity: profline; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2312"
+ ]
+ ]
+ },
+ {
+ "input": "&profsurf",
+ "description": "Bad named entity: profsurf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&profsurf"
+ ]
+ ]
+ },
+ {
+ "input": "&profsurf;",
+ "description": "Named entity: profsurf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2313"
+ ]
+ ]
+ },
+ {
+ "input": "&prop",
+ "description": "Bad named entity: prop without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&prop"
+ ]
+ ]
+ },
+ {
+ "input": "&prop;",
+ "description": "Named entity: prop; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u221d"
+ ]
+ ]
+ },
+ {
+ "input": "&propto",
+ "description": "Bad named entity: propto without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&propto"
+ ]
+ ]
+ },
+ {
+ "input": "&propto;",
+ "description": "Named entity: propto; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u221d"
+ ]
+ ]
+ },
+ {
+ "input": "&prsim",
+ "description": "Bad named entity: prsim without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&prsim"
+ ]
+ ]
+ },
+ {
+ "input": "&prsim;",
+ "description": "Named entity: prsim; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u227e"
+ ]
+ ]
+ },
+ {
+ "input": "&prurel",
+ "description": "Bad named entity: prurel without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&prurel"
+ ]
+ ]
+ },
+ {
+ "input": "&prurel;",
+ "description": "Named entity: prurel; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22b0"
+ ]
+ ]
+ },
+ {
+ "input": "&pscr",
+ "description": "Bad named entity: pscr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&pscr"
+ ]
+ ]
+ },
+ {
+ "input": "&pscr;",
+ "description": "Named entity: pscr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udcc5"
+ ]
+ ]
+ },
+ {
+ "input": "&psi",
+ "description": "Bad named entity: psi without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&psi"
+ ]
+ ]
+ },
+ {
+ "input": "&psi;",
+ "description": "Named entity: psi; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03c8"
+ ]
+ ]
+ },
+ {
+ "input": "&puncsp",
+ "description": "Bad named entity: puncsp without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&puncsp"
+ ]
+ ]
+ },
+ {
+ "input": "&puncsp;",
+ "description": "Named entity: puncsp; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2008"
+ ]
+ ]
+ },
+ {
+ "input": "&qfr",
+ "description": "Bad named entity: qfr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&qfr"
+ ]
+ ]
+ },
+ {
+ "input": "&qfr;",
+ "description": "Named entity: qfr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd2e"
+ ]
+ ]
+ },
+ {
+ "input": "&qint",
+ "description": "Bad named entity: qint without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&qint"
+ ]
+ ]
+ },
+ {
+ "input": "&qint;",
+ "description": "Named entity: qint; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a0c"
+ ]
+ ]
+ },
+ {
+ "input": "&qopf",
+ "description": "Bad named entity: qopf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&qopf"
+ ]
+ ]
+ },
+ {
+ "input": "&qopf;",
+ "description": "Named entity: qopf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd62"
+ ]
+ ]
+ },
+ {
+ "input": "&qprime",
+ "description": "Bad named entity: qprime without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&qprime"
+ ]
+ ]
+ },
+ {
+ "input": "&qprime;",
+ "description": "Named entity: qprime; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2057"
+ ]
+ ]
+ },
+ {
+ "input": "&qscr",
+ "description": "Bad named entity: qscr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&qscr"
+ ]
+ ]
+ },
+ {
+ "input": "&qscr;",
+ "description": "Named entity: qscr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udcc6"
+ ]
+ ]
+ },
+ {
+ "input": "&quaternions",
+ "description": "Bad named entity: quaternions without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&quaternions"
+ ]
+ ]
+ },
+ {
+ "input": "&quaternions;",
+ "description": "Named entity: quaternions; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u210d"
+ ]
+ ]
+ },
+ {
+ "input": "&quatint",
+ "description": "Bad named entity: quatint without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&quatint"
+ ]
+ ]
+ },
+ {
+ "input": "&quatint;",
+ "description": "Named entity: quatint; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a16"
+ ]
+ ]
+ },
+ {
+ "input": "&quest",
+ "description": "Bad named entity: quest without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&quest"
+ ]
+ ]
+ },
+ {
+ "input": "&quest;",
+ "description": "Named entity: quest; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "?"
+ ]
+ ]
+ },
+ {
+ "input": "&questeq",
+ "description": "Bad named entity: questeq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&questeq"
+ ]
+ ]
+ },
+ {
+ "input": "&questeq;",
+ "description": "Named entity: questeq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u225f"
+ ]
+ ]
+ },
+ {
+ "input": "&quot",
+ "description": "Named entity: quot without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\""
+ ]
+ ]
+ },
+ {
+ "input": "&quot;",
+ "description": "Named entity: quot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\""
+ ]
+ ]
+ },
+ {
+ "input": "&rAarr",
+ "description": "Bad named entity: rAarr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rAarr"
+ ]
+ ]
+ },
+ {
+ "input": "&rAarr;",
+ "description": "Named entity: rAarr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21db"
+ ]
+ ]
+ },
+ {
+ "input": "&rArr",
+ "description": "Bad named entity: rArr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rArr"
+ ]
+ ]
+ },
+ {
+ "input": "&rArr;",
+ "description": "Named entity: rArr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21d2"
+ ]
+ ]
+ },
+ {
+ "input": "&rAtail",
+ "description": "Bad named entity: rAtail without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rAtail"
+ ]
+ ]
+ },
+ {
+ "input": "&rAtail;",
+ "description": "Named entity: rAtail; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u291c"
+ ]
+ ]
+ },
+ {
+ "input": "&rBarr",
+ "description": "Bad named entity: rBarr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rBarr"
+ ]
+ ]
+ },
+ {
+ "input": "&rBarr;",
+ "description": "Named entity: rBarr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u290f"
+ ]
+ ]
+ },
+ {
+ "input": "&rHar",
+ "description": "Bad named entity: rHar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rHar"
+ ]
+ ]
+ },
+ {
+ "input": "&rHar;",
+ "description": "Named entity: rHar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2964"
+ ]
+ ]
+ },
+ {
+ "input": "&race",
+ "description": "Bad named entity: race without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&race"
+ ]
+ ]
+ },
+ {
+ "input": "&race;",
+ "description": "Named entity: race; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u223d\u0331"
+ ]
+ ]
+ },
+ {
+ "input": "&racute",
+ "description": "Bad named entity: racute without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&racute"
+ ]
+ ]
+ },
+ {
+ "input": "&racute;",
+ "description": "Named entity: racute; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0155"
+ ]
+ ]
+ },
+ {
+ "input": "&radic",
+ "description": "Bad named entity: radic without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&radic"
+ ]
+ ]
+ },
+ {
+ "input": "&radic;",
+ "description": "Named entity: radic; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u221a"
+ ]
+ ]
+ },
+ {
+ "input": "&raemptyv",
+ "description": "Bad named entity: raemptyv without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&raemptyv"
+ ]
+ ]
+ },
+ {
+ "input": "&raemptyv;",
+ "description": "Named entity: raemptyv; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u29b3"
+ ]
+ ]
+ },
+ {
+ "input": "&rang",
+ "description": "Bad named entity: rang without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rang"
+ ]
+ ]
+ },
+ {
+ "input": "&rang;",
+ "description": "Named entity: rang; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u27e9"
+ ]
+ ]
+ },
+ {
+ "input": "&rangd",
+ "description": "Bad named entity: rangd without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rangd"
+ ]
+ ]
+ },
+ {
+ "input": "&rangd;",
+ "description": "Named entity: rangd; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2992"
+ ]
+ ]
+ },
+ {
+ "input": "&range",
+ "description": "Bad named entity: range without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&range"
+ ]
+ ]
+ },
+ {
+ "input": "&range;",
+ "description": "Named entity: range; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u29a5"
+ ]
+ ]
+ },
+ {
+ "input": "&rangle",
+ "description": "Bad named entity: rangle without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rangle"
+ ]
+ ]
+ },
+ {
+ "input": "&rangle;",
+ "description": "Named entity: rangle; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u27e9"
+ ]
+ ]
+ },
+ {
+ "input": "&raquo",
+ "description": "Named entity: raquo without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00bb"
+ ]
+ ]
+ },
+ {
+ "input": "&raquo;",
+ "description": "Named entity: raquo; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00bb"
+ ]
+ ]
+ },
+ {
+ "input": "&rarr",
+ "description": "Bad named entity: rarr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rarr"
+ ]
+ ]
+ },
+ {
+ "input": "&rarr;",
+ "description": "Named entity: rarr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2192"
+ ]
+ ]
+ },
+ {
+ "input": "&rarrap",
+ "description": "Bad named entity: rarrap without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rarrap"
+ ]
+ ]
+ },
+ {
+ "input": "&rarrap;",
+ "description": "Named entity: rarrap; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2975"
+ ]
+ ]
+ },
+ {
+ "input": "&rarrb",
+ "description": "Bad named entity: rarrb without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rarrb"
+ ]
+ ]
+ },
+ {
+ "input": "&rarrb;",
+ "description": "Named entity: rarrb; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21e5"
+ ]
+ ]
+ },
+ {
+ "input": "&rarrbfs",
+ "description": "Bad named entity: rarrbfs without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rarrbfs"
+ ]
+ ]
+ },
+ {
+ "input": "&rarrbfs;",
+ "description": "Named entity: rarrbfs; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2920"
+ ]
+ ]
+ },
+ {
+ "input": "&rarrc",
+ "description": "Bad named entity: rarrc without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rarrc"
+ ]
+ ]
+ },
+ {
+ "input": "&rarrc;",
+ "description": "Named entity: rarrc; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2933"
+ ]
+ ]
+ },
+ {
+ "input": "&rarrfs",
+ "description": "Bad named entity: rarrfs without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rarrfs"
+ ]
+ ]
+ },
+ {
+ "input": "&rarrfs;",
+ "description": "Named entity: rarrfs; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u291e"
+ ]
+ ]
+ },
+ {
+ "input": "&rarrhk",
+ "description": "Bad named entity: rarrhk without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rarrhk"
+ ]
+ ]
+ },
+ {
+ "input": "&rarrhk;",
+ "description": "Named entity: rarrhk; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21aa"
+ ]
+ ]
+ },
+ {
+ "input": "&rarrlp",
+ "description": "Bad named entity: rarrlp without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rarrlp"
+ ]
+ ]
+ },
+ {
+ "input": "&rarrlp;",
+ "description": "Named entity: rarrlp; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21ac"
+ ]
+ ]
+ },
+ {
+ "input": "&rarrpl",
+ "description": "Bad named entity: rarrpl without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rarrpl"
+ ]
+ ]
+ },
+ {
+ "input": "&rarrpl;",
+ "description": "Named entity: rarrpl; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2945"
+ ]
+ ]
+ },
+ {
+ "input": "&rarrsim",
+ "description": "Bad named entity: rarrsim without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rarrsim"
+ ]
+ ]
+ },
+ {
+ "input": "&rarrsim;",
+ "description": "Named entity: rarrsim; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2974"
+ ]
+ ]
+ },
+ {
+ "input": "&rarrtl",
+ "description": "Bad named entity: rarrtl without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rarrtl"
+ ]
+ ]
+ },
+ {
+ "input": "&rarrtl;",
+ "description": "Named entity: rarrtl; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21a3"
+ ]
+ ]
+ },
+ {
+ "input": "&rarrw",
+ "description": "Bad named entity: rarrw without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rarrw"
+ ]
+ ]
+ },
+ {
+ "input": "&rarrw;",
+ "description": "Named entity: rarrw; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u219d"
+ ]
+ ]
+ },
+ {
+ "input": "&ratail",
+ "description": "Bad named entity: ratail without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ratail"
+ ]
+ ]
+ },
+ {
+ "input": "&ratail;",
+ "description": "Named entity: ratail; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u291a"
+ ]
+ ]
+ },
+ {
+ "input": "&ratio",
+ "description": "Bad named entity: ratio without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ratio"
+ ]
+ ]
+ },
+ {
+ "input": "&ratio;",
+ "description": "Named entity: ratio; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2236"
+ ]
+ ]
+ },
+ {
+ "input": "&rationals",
+ "description": "Bad named entity: rationals without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rationals"
+ ]
+ ]
+ },
+ {
+ "input": "&rationals;",
+ "description": "Named entity: rationals; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u211a"
+ ]
+ ]
+ },
+ {
+ "input": "&rbarr",
+ "description": "Bad named entity: rbarr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rbarr"
+ ]
+ ]
+ },
+ {
+ "input": "&rbarr;",
+ "description": "Named entity: rbarr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u290d"
+ ]
+ ]
+ },
+ {
+ "input": "&rbbrk",
+ "description": "Bad named entity: rbbrk without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rbbrk"
+ ]
+ ]
+ },
+ {
+ "input": "&rbbrk;",
+ "description": "Named entity: rbbrk; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2773"
+ ]
+ ]
+ },
+ {
+ "input": "&rbrace",
+ "description": "Bad named entity: rbrace without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rbrace"
+ ]
+ ]
+ },
+ {
+ "input": "&rbrace;",
+ "description": "Named entity: rbrace; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "}"
+ ]
+ ]
+ },
+ {
+ "input": "&rbrack",
+ "description": "Bad named entity: rbrack without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rbrack"
+ ]
+ ]
+ },
+ {
+ "input": "&rbrack;",
+ "description": "Named entity: rbrack; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "]"
+ ]
+ ]
+ },
+ {
+ "input": "&rbrke",
+ "description": "Bad named entity: rbrke without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rbrke"
+ ]
+ ]
+ },
+ {
+ "input": "&rbrke;",
+ "description": "Named entity: rbrke; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u298c"
+ ]
+ ]
+ },
+ {
+ "input": "&rbrksld",
+ "description": "Bad named entity: rbrksld without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rbrksld"
+ ]
+ ]
+ },
+ {
+ "input": "&rbrksld;",
+ "description": "Named entity: rbrksld; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u298e"
+ ]
+ ]
+ },
+ {
+ "input": "&rbrkslu",
+ "description": "Bad named entity: rbrkslu without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rbrkslu"
+ ]
+ ]
+ },
+ {
+ "input": "&rbrkslu;",
+ "description": "Named entity: rbrkslu; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2990"
+ ]
+ ]
+ },
+ {
+ "input": "&rcaron",
+ "description": "Bad named entity: rcaron without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rcaron"
+ ]
+ ]
+ },
+ {
+ "input": "&rcaron;",
+ "description": "Named entity: rcaron; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0159"
+ ]
+ ]
+ },
+ {
+ "input": "&rcedil",
+ "description": "Bad named entity: rcedil without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rcedil"
+ ]
+ ]
+ },
+ {
+ "input": "&rcedil;",
+ "description": "Named entity: rcedil; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0157"
+ ]
+ ]
+ },
+ {
+ "input": "&rceil",
+ "description": "Bad named entity: rceil without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rceil"
+ ]
+ ]
+ },
+ {
+ "input": "&rceil;",
+ "description": "Named entity: rceil; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2309"
+ ]
+ ]
+ },
+ {
+ "input": "&rcub",
+ "description": "Bad named entity: rcub without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rcub"
+ ]
+ ]
+ },
+ {
+ "input": "&rcub;",
+ "description": "Named entity: rcub; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "}"
+ ]
+ ]
+ },
+ {
+ "input": "&rcy",
+ "description": "Bad named entity: rcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rcy"
+ ]
+ ]
+ },
+ {
+ "input": "&rcy;",
+ "description": "Named entity: rcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0440"
+ ]
+ ]
+ },
+ {
+ "input": "&rdca",
+ "description": "Bad named entity: rdca without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rdca"
+ ]
+ ]
+ },
+ {
+ "input": "&rdca;",
+ "description": "Named entity: rdca; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2937"
+ ]
+ ]
+ },
+ {
+ "input": "&rdldhar",
+ "description": "Bad named entity: rdldhar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rdldhar"
+ ]
+ ]
+ },
+ {
+ "input": "&rdldhar;",
+ "description": "Named entity: rdldhar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2969"
+ ]
+ ]
+ },
+ {
+ "input": "&rdquo",
+ "description": "Bad named entity: rdquo without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rdquo"
+ ]
+ ]
+ },
+ {
+ "input": "&rdquo;",
+ "description": "Named entity: rdquo; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u201d"
+ ]
+ ]
+ },
+ {
+ "input": "&rdquor",
+ "description": "Bad named entity: rdquor without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rdquor"
+ ]
+ ]
+ },
+ {
+ "input": "&rdquor;",
+ "description": "Named entity: rdquor; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u201d"
+ ]
+ ]
+ },
+ {
+ "input": "&rdsh",
+ "description": "Bad named entity: rdsh without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rdsh"
+ ]
+ ]
+ },
+ {
+ "input": "&rdsh;",
+ "description": "Named entity: rdsh; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21b3"
+ ]
+ ]
+ },
+ {
+ "input": "&real",
+ "description": "Bad named entity: real without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&real"
+ ]
+ ]
+ },
+ {
+ "input": "&real;",
+ "description": "Named entity: real; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u211c"
+ ]
+ ]
+ },
+ {
+ "input": "&realine",
+ "description": "Bad named entity: realine without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&realine"
+ ]
+ ]
+ },
+ {
+ "input": "&realine;",
+ "description": "Named entity: realine; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u211b"
+ ]
+ ]
+ },
+ {
+ "input": "&realpart",
+ "description": "Bad named entity: realpart without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&realpart"
+ ]
+ ]
+ },
+ {
+ "input": "&realpart;",
+ "description": "Named entity: realpart; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u211c"
+ ]
+ ]
+ },
+ {
+ "input": "&reals",
+ "description": "Bad named entity: reals without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&reals"
+ ]
+ ]
+ },
+ {
+ "input": "&reals;",
+ "description": "Named entity: reals; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u211d"
+ ]
+ ]
+ },
+ {
+ "input": "&rect",
+ "description": "Bad named entity: rect without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rect"
+ ]
+ ]
+ },
+ {
+ "input": "&rect;",
+ "description": "Named entity: rect; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u25ad"
+ ]
+ ]
+ },
+ {
+ "input": "&reg",
+ "description": "Named entity: reg without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00ae"
+ ]
+ ]
+ },
+ {
+ "input": "&reg;",
+ "description": "Named entity: reg; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00ae"
+ ]
+ ]
+ },
+ {
+ "input": "&rfisht",
+ "description": "Bad named entity: rfisht without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rfisht"
+ ]
+ ]
+ },
+ {
+ "input": "&rfisht;",
+ "description": "Named entity: rfisht; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u297d"
+ ]
+ ]
+ },
+ {
+ "input": "&rfloor",
+ "description": "Bad named entity: rfloor without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rfloor"
+ ]
+ ]
+ },
+ {
+ "input": "&rfloor;",
+ "description": "Named entity: rfloor; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u230b"
+ ]
+ ]
+ },
+ {
+ "input": "&rfr",
+ "description": "Bad named entity: rfr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rfr"
+ ]
+ ]
+ },
+ {
+ "input": "&rfr;",
+ "description": "Named entity: rfr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd2f"
+ ]
+ ]
+ },
+ {
+ "input": "&rhard",
+ "description": "Bad named entity: rhard without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rhard"
+ ]
+ ]
+ },
+ {
+ "input": "&rhard;",
+ "description": "Named entity: rhard; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21c1"
+ ]
+ ]
+ },
+ {
+ "input": "&rharu",
+ "description": "Bad named entity: rharu without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rharu"
+ ]
+ ]
+ },
+ {
+ "input": "&rharu;",
+ "description": "Named entity: rharu; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21c0"
+ ]
+ ]
+ },
+ {
+ "input": "&rharul",
+ "description": "Bad named entity: rharul without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rharul"
+ ]
+ ]
+ },
+ {
+ "input": "&rharul;",
+ "description": "Named entity: rharul; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u296c"
+ ]
+ ]
+ },
+ {
+ "input": "&rho",
+ "description": "Bad named entity: rho without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rho"
+ ]
+ ]
+ },
+ {
+ "input": "&rho;",
+ "description": "Named entity: rho; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03c1"
+ ]
+ ]
+ },
+ {
+ "input": "&rhov",
+ "description": "Bad named entity: rhov without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rhov"
+ ]
+ ]
+ },
+ {
+ "input": "&rhov;",
+ "description": "Named entity: rhov; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03f1"
+ ]
+ ]
+ },
+ {
+ "input": "&rightarrow",
+ "description": "Bad named entity: rightarrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rightarrow"
+ ]
+ ]
+ },
+ {
+ "input": "&rightarrow;",
+ "description": "Named entity: rightarrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2192"
+ ]
+ ]
+ },
+ {
+ "input": "&rightarrowtail",
+ "description": "Bad named entity: rightarrowtail without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rightarrowtail"
+ ]
+ ]
+ },
+ {
+ "input": "&rightarrowtail;",
+ "description": "Named entity: rightarrowtail; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21a3"
+ ]
+ ]
+ },
+ {
+ "input": "&rightharpoondown",
+ "description": "Bad named entity: rightharpoondown without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rightharpoondown"
+ ]
+ ]
+ },
+ {
+ "input": "&rightharpoondown;",
+ "description": "Named entity: rightharpoondown; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21c1"
+ ]
+ ]
+ },
+ {
+ "input": "&rightharpoonup",
+ "description": "Bad named entity: rightharpoonup without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rightharpoonup"
+ ]
+ ]
+ },
+ {
+ "input": "&rightharpoonup;",
+ "description": "Named entity: rightharpoonup; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21c0"
+ ]
+ ]
+ },
+ {
+ "input": "&rightleftarrows",
+ "description": "Bad named entity: rightleftarrows without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rightleftarrows"
+ ]
+ ]
+ },
+ {
+ "input": "&rightleftarrows;",
+ "description": "Named entity: rightleftarrows; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21c4"
+ ]
+ ]
+ },
+ {
+ "input": "&rightleftharpoons",
+ "description": "Bad named entity: rightleftharpoons without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rightleftharpoons"
+ ]
+ ]
+ },
+ {
+ "input": "&rightleftharpoons;",
+ "description": "Named entity: rightleftharpoons; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21cc"
+ ]
+ ]
+ },
+ {
+ "input": "&rightrightarrows",
+ "description": "Bad named entity: rightrightarrows without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rightrightarrows"
+ ]
+ ]
+ },
+ {
+ "input": "&rightrightarrows;",
+ "description": "Named entity: rightrightarrows; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21c9"
+ ]
+ ]
+ },
+ {
+ "input": "&rightsquigarrow",
+ "description": "Bad named entity: rightsquigarrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rightsquigarrow"
+ ]
+ ]
+ },
+ {
+ "input": "&rightsquigarrow;",
+ "description": "Named entity: rightsquigarrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u219d"
+ ]
+ ]
+ },
+ {
+ "input": "&rightthreetimes",
+ "description": "Bad named entity: rightthreetimes without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rightthreetimes"
+ ]
+ ]
+ },
+ {
+ "input": "&rightthreetimes;",
+ "description": "Named entity: rightthreetimes; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22cc"
+ ]
+ ]
+ },
+ {
+ "input": "&ring",
+ "description": "Bad named entity: ring without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ring"
+ ]
+ ]
+ },
+ {
+ "input": "&ring;",
+ "description": "Named entity: ring; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u02da"
+ ]
+ ]
+ },
+ {
+ "input": "&risingdotseq",
+ "description": "Bad named entity: risingdotseq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&risingdotseq"
+ ]
+ ]
+ },
+ {
+ "input": "&risingdotseq;",
+ "description": "Named entity: risingdotseq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2253"
+ ]
+ ]
+ },
+ {
+ "input": "&rlarr",
+ "description": "Bad named entity: rlarr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rlarr"
+ ]
+ ]
+ },
+ {
+ "input": "&rlarr;",
+ "description": "Named entity: rlarr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21c4"
+ ]
+ ]
+ },
+ {
+ "input": "&rlhar",
+ "description": "Bad named entity: rlhar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rlhar"
+ ]
+ ]
+ },
+ {
+ "input": "&rlhar;",
+ "description": "Named entity: rlhar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21cc"
+ ]
+ ]
+ },
+ {
+ "input": "&rlm",
+ "description": "Bad named entity: rlm without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rlm"
+ ]
+ ]
+ },
+ {
+ "input": "&rlm;",
+ "description": "Named entity: rlm; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u200f"
+ ]
+ ]
+ },
+ {
+ "input": "&rmoust",
+ "description": "Bad named entity: rmoust without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rmoust"
+ ]
+ ]
+ },
+ {
+ "input": "&rmoust;",
+ "description": "Named entity: rmoust; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u23b1"
+ ]
+ ]
+ },
+ {
+ "input": "&rmoustache",
+ "description": "Bad named entity: rmoustache without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rmoustache"
+ ]
+ ]
+ },
+ {
+ "input": "&rmoustache;",
+ "description": "Named entity: rmoustache; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u23b1"
+ ]
+ ]
+ },
+ {
+ "input": "&rnmid",
+ "description": "Bad named entity: rnmid without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rnmid"
+ ]
+ ]
+ },
+ {
+ "input": "&rnmid;",
+ "description": "Named entity: rnmid; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2aee"
+ ]
+ ]
+ },
+ {
+ "input": "&roang",
+ "description": "Bad named entity: roang without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&roang"
+ ]
+ ]
+ },
+ {
+ "input": "&roang;",
+ "description": "Named entity: roang; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u27ed"
+ ]
+ ]
+ },
+ {
+ "input": "&roarr",
+ "description": "Bad named entity: roarr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&roarr"
+ ]
+ ]
+ },
+ {
+ "input": "&roarr;",
+ "description": "Named entity: roarr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21fe"
+ ]
+ ]
+ },
+ {
+ "input": "&robrk",
+ "description": "Bad named entity: robrk without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&robrk"
+ ]
+ ]
+ },
+ {
+ "input": "&robrk;",
+ "description": "Named entity: robrk; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u27e7"
+ ]
+ ]
+ },
+ {
+ "input": "&ropar",
+ "description": "Bad named entity: ropar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ropar"
+ ]
+ ]
+ },
+ {
+ "input": "&ropar;",
+ "description": "Named entity: ropar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2986"
+ ]
+ ]
+ },
+ {
+ "input": "&ropf",
+ "description": "Bad named entity: ropf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ropf"
+ ]
+ ]
+ },
+ {
+ "input": "&ropf;",
+ "description": "Named entity: ropf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd63"
+ ]
+ ]
+ },
+ {
+ "input": "&roplus",
+ "description": "Bad named entity: roplus without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&roplus"
+ ]
+ ]
+ },
+ {
+ "input": "&roplus;",
+ "description": "Named entity: roplus; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a2e"
+ ]
+ ]
+ },
+ {
+ "input": "&rotimes",
+ "description": "Bad named entity: rotimes without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rotimes"
+ ]
+ ]
+ },
+ {
+ "input": "&rotimes;",
+ "description": "Named entity: rotimes; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a35"
+ ]
+ ]
+ },
+ {
+ "input": "&rpar",
+ "description": "Bad named entity: rpar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rpar"
+ ]
+ ]
+ },
+ {
+ "input": "&rpar;",
+ "description": "Named entity: rpar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ ")"
+ ]
+ ]
+ },
+ {
+ "input": "&rpargt",
+ "description": "Bad named entity: rpargt without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rpargt"
+ ]
+ ]
+ },
+ {
+ "input": "&rpargt;",
+ "description": "Named entity: rpargt; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2994"
+ ]
+ ]
+ },
+ {
+ "input": "&rppolint",
+ "description": "Bad named entity: rppolint without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rppolint"
+ ]
+ ]
+ },
+ {
+ "input": "&rppolint;",
+ "description": "Named entity: rppolint; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a12"
+ ]
+ ]
+ },
+ {
+ "input": "&rrarr",
+ "description": "Bad named entity: rrarr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rrarr"
+ ]
+ ]
+ },
+ {
+ "input": "&rrarr;",
+ "description": "Named entity: rrarr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21c9"
+ ]
+ ]
+ },
+ {
+ "input": "&rsaquo",
+ "description": "Bad named entity: rsaquo without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rsaquo"
+ ]
+ ]
+ },
+ {
+ "input": "&rsaquo;",
+ "description": "Named entity: rsaquo; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u203a"
+ ]
+ ]
+ },
+ {
+ "input": "&rscr",
+ "description": "Bad named entity: rscr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rscr"
+ ]
+ ]
+ },
+ {
+ "input": "&rscr;",
+ "description": "Named entity: rscr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udcc7"
+ ]
+ ]
+ },
+ {
+ "input": "&rsh",
+ "description": "Bad named entity: rsh without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rsh"
+ ]
+ ]
+ },
+ {
+ "input": "&rsh;",
+ "description": "Named entity: rsh; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21b1"
+ ]
+ ]
+ },
+ {
+ "input": "&rsqb",
+ "description": "Bad named entity: rsqb without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rsqb"
+ ]
+ ]
+ },
+ {
+ "input": "&rsqb;",
+ "description": "Named entity: rsqb; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "]"
+ ]
+ ]
+ },
+ {
+ "input": "&rsquo",
+ "description": "Bad named entity: rsquo without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rsquo"
+ ]
+ ]
+ },
+ {
+ "input": "&rsquo;",
+ "description": "Named entity: rsquo; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2019"
+ ]
+ ]
+ },
+ {
+ "input": "&rsquor",
+ "description": "Bad named entity: rsquor without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rsquor"
+ ]
+ ]
+ },
+ {
+ "input": "&rsquor;",
+ "description": "Named entity: rsquor; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2019"
+ ]
+ ]
+ },
+ {
+ "input": "&rthree",
+ "description": "Bad named entity: rthree without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rthree"
+ ]
+ ]
+ },
+ {
+ "input": "&rthree;",
+ "description": "Named entity: rthree; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22cc"
+ ]
+ ]
+ },
+ {
+ "input": "&rtimes",
+ "description": "Bad named entity: rtimes without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rtimes"
+ ]
+ ]
+ },
+ {
+ "input": "&rtimes;",
+ "description": "Named entity: rtimes; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22ca"
+ ]
+ ]
+ },
+ {
+ "input": "&rtri",
+ "description": "Bad named entity: rtri without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rtri"
+ ]
+ ]
+ },
+ {
+ "input": "&rtri;",
+ "description": "Named entity: rtri; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u25b9"
+ ]
+ ]
+ },
+ {
+ "input": "&rtrie",
+ "description": "Bad named entity: rtrie without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rtrie"
+ ]
+ ]
+ },
+ {
+ "input": "&rtrie;",
+ "description": "Named entity: rtrie; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22b5"
+ ]
+ ]
+ },
+ {
+ "input": "&rtrif",
+ "description": "Bad named entity: rtrif without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rtrif"
+ ]
+ ]
+ },
+ {
+ "input": "&rtrif;",
+ "description": "Named entity: rtrif; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u25b8"
+ ]
+ ]
+ },
+ {
+ "input": "&rtriltri",
+ "description": "Bad named entity: rtriltri without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rtriltri"
+ ]
+ ]
+ },
+ {
+ "input": "&rtriltri;",
+ "description": "Named entity: rtriltri; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u29ce"
+ ]
+ ]
+ },
+ {
+ "input": "&ruluhar",
+ "description": "Bad named entity: ruluhar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ruluhar"
+ ]
+ ]
+ },
+ {
+ "input": "&ruluhar;",
+ "description": "Named entity: ruluhar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2968"
+ ]
+ ]
+ },
+ {
+ "input": "&rx",
+ "description": "Bad named entity: rx without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&rx"
+ ]
+ ]
+ },
+ {
+ "input": "&rx;",
+ "description": "Named entity: rx; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u211e"
+ ]
+ ]
+ },
+ {
+ "input": "&sacute",
+ "description": "Bad named entity: sacute without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&sacute"
+ ]
+ ]
+ },
+ {
+ "input": "&sacute;",
+ "description": "Named entity: sacute; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u015b"
+ ]
+ ]
+ },
+ {
+ "input": "&sbquo",
+ "description": "Bad named entity: sbquo without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&sbquo"
+ ]
+ ]
+ },
+ {
+ "input": "&sbquo;",
+ "description": "Named entity: sbquo; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u201a"
+ ]
+ ]
+ },
+ {
+ "input": "&sc",
+ "description": "Bad named entity: sc without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&sc"
+ ]
+ ]
+ },
+ {
+ "input": "&sc;",
+ "description": "Named entity: sc; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u227b"
+ ]
+ ]
+ },
+ {
+ "input": "&scE",
+ "description": "Bad named entity: scE without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&scE"
+ ]
+ ]
+ },
+ {
+ "input": "&scE;",
+ "description": "Named entity: scE; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2ab4"
+ ]
+ ]
+ },
+ {
+ "input": "&scap",
+ "description": "Bad named entity: scap without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&scap"
+ ]
+ ]
+ },
+ {
+ "input": "&scap;",
+ "description": "Named entity: scap; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2ab8"
+ ]
+ ]
+ },
+ {
+ "input": "&scaron",
+ "description": "Bad named entity: scaron without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&scaron"
+ ]
+ ]
+ },
+ {
+ "input": "&scaron;",
+ "description": "Named entity: scaron; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0161"
+ ]
+ ]
+ },
+ {
+ "input": "&sccue",
+ "description": "Bad named entity: sccue without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&sccue"
+ ]
+ ]
+ },
+ {
+ "input": "&sccue;",
+ "description": "Named entity: sccue; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u227d"
+ ]
+ ]
+ },
+ {
+ "input": "&sce",
+ "description": "Bad named entity: sce without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&sce"
+ ]
+ ]
+ },
+ {
+ "input": "&sce;",
+ "description": "Named entity: sce; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2ab0"
+ ]
+ ]
+ },
+ {
+ "input": "&scedil",
+ "description": "Bad named entity: scedil without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&scedil"
+ ]
+ ]
+ },
+ {
+ "input": "&scedil;",
+ "description": "Named entity: scedil; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u015f"
+ ]
+ ]
+ },
+ {
+ "input": "&scirc",
+ "description": "Bad named entity: scirc without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&scirc"
+ ]
+ ]
+ },
+ {
+ "input": "&scirc;",
+ "description": "Named entity: scirc; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u015d"
+ ]
+ ]
+ },
+ {
+ "input": "&scnE",
+ "description": "Bad named entity: scnE without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&scnE"
+ ]
+ ]
+ },
+ {
+ "input": "&scnE;",
+ "description": "Named entity: scnE; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2ab6"
+ ]
+ ]
+ },
+ {
+ "input": "&scnap",
+ "description": "Bad named entity: scnap without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&scnap"
+ ]
+ ]
+ },
+ {
+ "input": "&scnap;",
+ "description": "Named entity: scnap; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2aba"
+ ]
+ ]
+ },
+ {
+ "input": "&scnsim",
+ "description": "Bad named entity: scnsim without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&scnsim"
+ ]
+ ]
+ },
+ {
+ "input": "&scnsim;",
+ "description": "Named entity: scnsim; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22e9"
+ ]
+ ]
+ },
+ {
+ "input": "&scpolint",
+ "description": "Bad named entity: scpolint without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&scpolint"
+ ]
+ ]
+ },
+ {
+ "input": "&scpolint;",
+ "description": "Named entity: scpolint; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a13"
+ ]
+ ]
+ },
+ {
+ "input": "&scsim",
+ "description": "Bad named entity: scsim without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&scsim"
+ ]
+ ]
+ },
+ {
+ "input": "&scsim;",
+ "description": "Named entity: scsim; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u227f"
+ ]
+ ]
+ },
+ {
+ "input": "&scy",
+ "description": "Bad named entity: scy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&scy"
+ ]
+ ]
+ },
+ {
+ "input": "&scy;",
+ "description": "Named entity: scy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0441"
+ ]
+ ]
+ },
+ {
+ "input": "&sdot",
+ "description": "Bad named entity: sdot without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&sdot"
+ ]
+ ]
+ },
+ {
+ "input": "&sdot;",
+ "description": "Named entity: sdot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22c5"
+ ]
+ ]
+ },
+ {
+ "input": "&sdotb",
+ "description": "Bad named entity: sdotb without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&sdotb"
+ ]
+ ]
+ },
+ {
+ "input": "&sdotb;",
+ "description": "Named entity: sdotb; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22a1"
+ ]
+ ]
+ },
+ {
+ "input": "&sdote",
+ "description": "Bad named entity: sdote without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&sdote"
+ ]
+ ]
+ },
+ {
+ "input": "&sdote;",
+ "description": "Named entity: sdote; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a66"
+ ]
+ ]
+ },
+ {
+ "input": "&seArr",
+ "description": "Bad named entity: seArr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&seArr"
+ ]
+ ]
+ },
+ {
+ "input": "&seArr;",
+ "description": "Named entity: seArr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21d8"
+ ]
+ ]
+ },
+ {
+ "input": "&searhk",
+ "description": "Bad named entity: searhk without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&searhk"
+ ]
+ ]
+ },
+ {
+ "input": "&searhk;",
+ "description": "Named entity: searhk; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2925"
+ ]
+ ]
+ },
+ {
+ "input": "&searr",
+ "description": "Bad named entity: searr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&searr"
+ ]
+ ]
+ },
+ {
+ "input": "&searr;",
+ "description": "Named entity: searr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2198"
+ ]
+ ]
+ },
+ {
+ "input": "&searrow",
+ "description": "Bad named entity: searrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&searrow"
+ ]
+ ]
+ },
+ {
+ "input": "&searrow;",
+ "description": "Named entity: searrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2198"
+ ]
+ ]
+ },
+ {
+ "input": "&sect",
+ "description": "Named entity: sect without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00a7"
+ ]
+ ]
+ },
+ {
+ "input": "&sect;",
+ "description": "Named entity: sect; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00a7"
+ ]
+ ]
+ },
+ {
+ "input": "&semi",
+ "description": "Bad named entity: semi without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&semi"
+ ]
+ ]
+ },
+ {
+ "input": "&semi;",
+ "description": "Named entity: semi; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ ";"
+ ]
+ ]
+ },
+ {
+ "input": "&seswar",
+ "description": "Bad named entity: seswar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&seswar"
+ ]
+ ]
+ },
+ {
+ "input": "&seswar;",
+ "description": "Named entity: seswar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2929"
+ ]
+ ]
+ },
+ {
+ "input": "&setminus",
+ "description": "Bad named entity: setminus without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&setminus"
+ ]
+ ]
+ },
+ {
+ "input": "&setminus;",
+ "description": "Named entity: setminus; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2216"
+ ]
+ ]
+ },
+ {
+ "input": "&setmn",
+ "description": "Bad named entity: setmn without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&setmn"
+ ]
+ ]
+ },
+ {
+ "input": "&setmn;",
+ "description": "Named entity: setmn; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2216"
+ ]
+ ]
+ },
+ {
+ "input": "&sext",
+ "description": "Bad named entity: sext without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&sext"
+ ]
+ ]
+ },
+ {
+ "input": "&sext;",
+ "description": "Named entity: sext; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2736"
+ ]
+ ]
+ },
+ {
+ "input": "&sfr",
+ "description": "Bad named entity: sfr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&sfr"
+ ]
+ ]
+ },
+ {
+ "input": "&sfr;",
+ "description": "Named entity: sfr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd30"
+ ]
+ ]
+ },
+ {
+ "input": "&sfrown",
+ "description": "Bad named entity: sfrown without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&sfrown"
+ ]
+ ]
+ },
+ {
+ "input": "&sfrown;",
+ "description": "Named entity: sfrown; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2322"
+ ]
+ ]
+ },
+ {
+ "input": "&sharp",
+ "description": "Bad named entity: sharp without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&sharp"
+ ]
+ ]
+ },
+ {
+ "input": "&sharp;",
+ "description": "Named entity: sharp; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u266f"
+ ]
+ ]
+ },
+ {
+ "input": "&shchcy",
+ "description": "Bad named entity: shchcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&shchcy"
+ ]
+ ]
+ },
+ {
+ "input": "&shchcy;",
+ "description": "Named entity: shchcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0449"
+ ]
+ ]
+ },
+ {
+ "input": "&shcy",
+ "description": "Bad named entity: shcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&shcy"
+ ]
+ ]
+ },
+ {
+ "input": "&shcy;",
+ "description": "Named entity: shcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0448"
+ ]
+ ]
+ },
+ {
+ "input": "&shortmid",
+ "description": "Bad named entity: shortmid without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&shortmid"
+ ]
+ ]
+ },
+ {
+ "input": "&shortmid;",
+ "description": "Named entity: shortmid; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2223"
+ ]
+ ]
+ },
+ {
+ "input": "&shortparallel",
+ "description": "Bad named entity: shortparallel without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&shortparallel"
+ ]
+ ]
+ },
+ {
+ "input": "&shortparallel;",
+ "description": "Named entity: shortparallel; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2225"
+ ]
+ ]
+ },
+ {
+ "input": "&shy",
+ "description": "Named entity: shy without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00ad"
+ ]
+ ]
+ },
+ {
+ "input": "&shy;",
+ "description": "Named entity: shy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00ad"
+ ]
+ ]
+ },
+ {
+ "input": "&sigma",
+ "description": "Bad named entity: sigma without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&sigma"
+ ]
+ ]
+ },
+ {
+ "input": "&sigma;",
+ "description": "Named entity: sigma; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03c3"
+ ]
+ ]
+ },
+ {
+ "input": "&sigmaf",
+ "description": "Bad named entity: sigmaf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&sigmaf"
+ ]
+ ]
+ },
+ {
+ "input": "&sigmaf;",
+ "description": "Named entity: sigmaf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03c2"
+ ]
+ ]
+ },
+ {
+ "input": "&sigmav",
+ "description": "Bad named entity: sigmav without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&sigmav"
+ ]
+ ]
+ },
+ {
+ "input": "&sigmav;",
+ "description": "Named entity: sigmav; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03c2"
+ ]
+ ]
+ },
+ {
+ "input": "&sim",
+ "description": "Bad named entity: sim without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&sim"
+ ]
+ ]
+ },
+ {
+ "input": "&sim;",
+ "description": "Named entity: sim; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u223c"
+ ]
+ ]
+ },
+ {
+ "input": "&simdot",
+ "description": "Bad named entity: simdot without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&simdot"
+ ]
+ ]
+ },
+ {
+ "input": "&simdot;",
+ "description": "Named entity: simdot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a6a"
+ ]
+ ]
+ },
+ {
+ "input": "&sime",
+ "description": "Bad named entity: sime without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&sime"
+ ]
+ ]
+ },
+ {
+ "input": "&sime;",
+ "description": "Named entity: sime; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2243"
+ ]
+ ]
+ },
+ {
+ "input": "&simeq",
+ "description": "Bad named entity: simeq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&simeq"
+ ]
+ ]
+ },
+ {
+ "input": "&simeq;",
+ "description": "Named entity: simeq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2243"
+ ]
+ ]
+ },
+ {
+ "input": "&simg",
+ "description": "Bad named entity: simg without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&simg"
+ ]
+ ]
+ },
+ {
+ "input": "&simg;",
+ "description": "Named entity: simg; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a9e"
+ ]
+ ]
+ },
+ {
+ "input": "&simgE",
+ "description": "Bad named entity: simgE without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&simgE"
+ ]
+ ]
+ },
+ {
+ "input": "&simgE;",
+ "description": "Named entity: simgE; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2aa0"
+ ]
+ ]
+ },
+ {
+ "input": "&siml",
+ "description": "Bad named entity: siml without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&siml"
+ ]
+ ]
+ },
+ {
+ "input": "&siml;",
+ "description": "Named entity: siml; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a9d"
+ ]
+ ]
+ },
+ {
+ "input": "&simlE",
+ "description": "Bad named entity: simlE without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&simlE"
+ ]
+ ]
+ },
+ {
+ "input": "&simlE;",
+ "description": "Named entity: simlE; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a9f"
+ ]
+ ]
+ },
+ {
+ "input": "&simne",
+ "description": "Bad named entity: simne without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&simne"
+ ]
+ ]
+ },
+ {
+ "input": "&simne;",
+ "description": "Named entity: simne; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2246"
+ ]
+ ]
+ },
+ {
+ "input": "&simplus",
+ "description": "Bad named entity: simplus without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&simplus"
+ ]
+ ]
+ },
+ {
+ "input": "&simplus;",
+ "description": "Named entity: simplus; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a24"
+ ]
+ ]
+ },
+ {
+ "input": "&simrarr",
+ "description": "Bad named entity: simrarr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&simrarr"
+ ]
+ ]
+ },
+ {
+ "input": "&simrarr;",
+ "description": "Named entity: simrarr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2972"
+ ]
+ ]
+ },
+ {
+ "input": "&slarr",
+ "description": "Bad named entity: slarr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&slarr"
+ ]
+ ]
+ },
+ {
+ "input": "&slarr;",
+ "description": "Named entity: slarr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2190"
+ ]
+ ]
+ },
+ {
+ "input": "&smallsetminus",
+ "description": "Bad named entity: smallsetminus without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&smallsetminus"
+ ]
+ ]
+ },
+ {
+ "input": "&smallsetminus;",
+ "description": "Named entity: smallsetminus; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2216"
+ ]
+ ]
+ },
+ {
+ "input": "&smashp",
+ "description": "Bad named entity: smashp without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&smashp"
+ ]
+ ]
+ },
+ {
+ "input": "&smashp;",
+ "description": "Named entity: smashp; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a33"
+ ]
+ ]
+ },
+ {
+ "input": "&smeparsl",
+ "description": "Bad named entity: smeparsl without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&smeparsl"
+ ]
+ ]
+ },
+ {
+ "input": "&smeparsl;",
+ "description": "Named entity: smeparsl; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u29e4"
+ ]
+ ]
+ },
+ {
+ "input": "&smid",
+ "description": "Bad named entity: smid without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&smid"
+ ]
+ ]
+ },
+ {
+ "input": "&smid;",
+ "description": "Named entity: smid; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2223"
+ ]
+ ]
+ },
+ {
+ "input": "&smile",
+ "description": "Bad named entity: smile without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&smile"
+ ]
+ ]
+ },
+ {
+ "input": "&smile;",
+ "description": "Named entity: smile; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2323"
+ ]
+ ]
+ },
+ {
+ "input": "&smt",
+ "description": "Bad named entity: smt without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&smt"
+ ]
+ ]
+ },
+ {
+ "input": "&smt;",
+ "description": "Named entity: smt; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2aaa"
+ ]
+ ]
+ },
+ {
+ "input": "&smte",
+ "description": "Bad named entity: smte without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&smte"
+ ]
+ ]
+ },
+ {
+ "input": "&smte;",
+ "description": "Named entity: smte; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2aac"
+ ]
+ ]
+ },
+ {
+ "input": "&smtes",
+ "description": "Bad named entity: smtes without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&smtes"
+ ]
+ ]
+ },
+ {
+ "input": "&smtes;",
+ "description": "Named entity: smtes; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2aac\ufe00"
+ ]
+ ]
+ },
+ {
+ "input": "&softcy",
+ "description": "Bad named entity: softcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&softcy"
+ ]
+ ]
+ },
+ {
+ "input": "&softcy;",
+ "description": "Named entity: softcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u044c"
+ ]
+ ]
+ },
+ {
+ "input": "&sol",
+ "description": "Bad named entity: sol without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&sol"
+ ]
+ ]
+ },
+ {
+ "input": "&sol;",
+ "description": "Named entity: sol; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "/"
+ ]
+ ]
+ },
+ {
+ "input": "&solb",
+ "description": "Bad named entity: solb without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&solb"
+ ]
+ ]
+ },
+ {
+ "input": "&solb;",
+ "description": "Named entity: solb; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u29c4"
+ ]
+ ]
+ },
+ {
+ "input": "&solbar",
+ "description": "Bad named entity: solbar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&solbar"
+ ]
+ ]
+ },
+ {
+ "input": "&solbar;",
+ "description": "Named entity: solbar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u233f"
+ ]
+ ]
+ },
+ {
+ "input": "&sopf",
+ "description": "Bad named entity: sopf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&sopf"
+ ]
+ ]
+ },
+ {
+ "input": "&sopf;",
+ "description": "Named entity: sopf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd64"
+ ]
+ ]
+ },
+ {
+ "input": "&spades",
+ "description": "Bad named entity: spades without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&spades"
+ ]
+ ]
+ },
+ {
+ "input": "&spades;",
+ "description": "Named entity: spades; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2660"
+ ]
+ ]
+ },
+ {
+ "input": "&spadesuit",
+ "description": "Bad named entity: spadesuit without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&spadesuit"
+ ]
+ ]
+ },
+ {
+ "input": "&spadesuit;",
+ "description": "Named entity: spadesuit; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2660"
+ ]
+ ]
+ },
+ {
+ "input": "&spar",
+ "description": "Bad named entity: spar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&spar"
+ ]
+ ]
+ },
+ {
+ "input": "&spar;",
+ "description": "Named entity: spar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2225"
+ ]
+ ]
+ },
+ {
+ "input": "&sqcap",
+ "description": "Bad named entity: sqcap without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&sqcap"
+ ]
+ ]
+ },
+ {
+ "input": "&sqcap;",
+ "description": "Named entity: sqcap; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2293"
+ ]
+ ]
+ },
+ {
+ "input": "&sqcaps",
+ "description": "Bad named entity: sqcaps without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&sqcaps"
+ ]
+ ]
+ },
+ {
+ "input": "&sqcaps;",
+ "description": "Named entity: sqcaps; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2293\ufe00"
+ ]
+ ]
+ },
+ {
+ "input": "&sqcup",
+ "description": "Bad named entity: sqcup without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&sqcup"
+ ]
+ ]
+ },
+ {
+ "input": "&sqcup;",
+ "description": "Named entity: sqcup; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2294"
+ ]
+ ]
+ },
+ {
+ "input": "&sqcups",
+ "description": "Bad named entity: sqcups without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&sqcups"
+ ]
+ ]
+ },
+ {
+ "input": "&sqcups;",
+ "description": "Named entity: sqcups; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2294\ufe00"
+ ]
+ ]
+ },
+ {
+ "input": "&sqsub",
+ "description": "Bad named entity: sqsub without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&sqsub"
+ ]
+ ]
+ },
+ {
+ "input": "&sqsub;",
+ "description": "Named entity: sqsub; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u228f"
+ ]
+ ]
+ },
+ {
+ "input": "&sqsube",
+ "description": "Bad named entity: sqsube without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&sqsube"
+ ]
+ ]
+ },
+ {
+ "input": "&sqsube;",
+ "description": "Named entity: sqsube; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2291"
+ ]
+ ]
+ },
+ {
+ "input": "&sqsubset",
+ "description": "Bad named entity: sqsubset without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&sqsubset"
+ ]
+ ]
+ },
+ {
+ "input": "&sqsubset;",
+ "description": "Named entity: sqsubset; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u228f"
+ ]
+ ]
+ },
+ {
+ "input": "&sqsubseteq",
+ "description": "Bad named entity: sqsubseteq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&sqsubseteq"
+ ]
+ ]
+ },
+ {
+ "input": "&sqsubseteq;",
+ "description": "Named entity: sqsubseteq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2291"
+ ]
+ ]
+ },
+ {
+ "input": "&sqsup",
+ "description": "Bad named entity: sqsup without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&sqsup"
+ ]
+ ]
+ },
+ {
+ "input": "&sqsup;",
+ "description": "Named entity: sqsup; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2290"
+ ]
+ ]
+ },
+ {
+ "input": "&sqsupe",
+ "description": "Bad named entity: sqsupe without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&sqsupe"
+ ]
+ ]
+ },
+ {
+ "input": "&sqsupe;",
+ "description": "Named entity: sqsupe; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2292"
+ ]
+ ]
+ },
+ {
+ "input": "&sqsupset",
+ "description": "Bad named entity: sqsupset without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&sqsupset"
+ ]
+ ]
+ },
+ {
+ "input": "&sqsupset;",
+ "description": "Named entity: sqsupset; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2290"
+ ]
+ ]
+ },
+ {
+ "input": "&sqsupseteq",
+ "description": "Bad named entity: sqsupseteq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&sqsupseteq"
+ ]
+ ]
+ },
+ {
+ "input": "&sqsupseteq;",
+ "description": "Named entity: sqsupseteq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2292"
+ ]
+ ]
+ },
+ {
+ "input": "&squ",
+ "description": "Bad named entity: squ without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&squ"
+ ]
+ ]
+ },
+ {
+ "input": "&squ;",
+ "description": "Named entity: squ; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u25a1"
+ ]
+ ]
+ },
+ {
+ "input": "&square",
+ "description": "Bad named entity: square without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&square"
+ ]
+ ]
+ },
+ {
+ "input": "&square;",
+ "description": "Named entity: square; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u25a1"
+ ]
+ ]
+ },
+ {
+ "input": "&squarf",
+ "description": "Bad named entity: squarf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&squarf"
+ ]
+ ]
+ },
+ {
+ "input": "&squarf;",
+ "description": "Named entity: squarf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u25aa"
+ ]
+ ]
+ },
+ {
+ "input": "&squf",
+ "description": "Bad named entity: squf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&squf"
+ ]
+ ]
+ },
+ {
+ "input": "&squf;",
+ "description": "Named entity: squf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u25aa"
+ ]
+ ]
+ },
+ {
+ "input": "&srarr",
+ "description": "Bad named entity: srarr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&srarr"
+ ]
+ ]
+ },
+ {
+ "input": "&srarr;",
+ "description": "Named entity: srarr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2192"
+ ]
+ ]
+ },
+ {
+ "input": "&sscr",
+ "description": "Bad named entity: sscr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&sscr"
+ ]
+ ]
+ },
+ {
+ "input": "&sscr;",
+ "description": "Named entity: sscr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udcc8"
+ ]
+ ]
+ },
+ {
+ "input": "&ssetmn",
+ "description": "Bad named entity: ssetmn without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ssetmn"
+ ]
+ ]
+ },
+ {
+ "input": "&ssetmn;",
+ "description": "Named entity: ssetmn; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2216"
+ ]
+ ]
+ },
+ {
+ "input": "&ssmile",
+ "description": "Bad named entity: ssmile without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ssmile"
+ ]
+ ]
+ },
+ {
+ "input": "&ssmile;",
+ "description": "Named entity: ssmile; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2323"
+ ]
+ ]
+ },
+ {
+ "input": "&sstarf",
+ "description": "Bad named entity: sstarf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&sstarf"
+ ]
+ ]
+ },
+ {
+ "input": "&sstarf;",
+ "description": "Named entity: sstarf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22c6"
+ ]
+ ]
+ },
+ {
+ "input": "&star",
+ "description": "Bad named entity: star without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&star"
+ ]
+ ]
+ },
+ {
+ "input": "&star;",
+ "description": "Named entity: star; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2606"
+ ]
+ ]
+ },
+ {
+ "input": "&starf",
+ "description": "Bad named entity: starf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&starf"
+ ]
+ ]
+ },
+ {
+ "input": "&starf;",
+ "description": "Named entity: starf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2605"
+ ]
+ ]
+ },
+ {
+ "input": "&straightepsilon",
+ "description": "Bad named entity: straightepsilon without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&straightepsilon"
+ ]
+ ]
+ },
+ {
+ "input": "&straightepsilon;",
+ "description": "Named entity: straightepsilon; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03f5"
+ ]
+ ]
+ },
+ {
+ "input": "&straightphi",
+ "description": "Bad named entity: straightphi without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&straightphi"
+ ]
+ ]
+ },
+ {
+ "input": "&straightphi;",
+ "description": "Named entity: straightphi; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03d5"
+ ]
+ ]
+ },
+ {
+ "input": "&strns",
+ "description": "Bad named entity: strns without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&strns"
+ ]
+ ]
+ },
+ {
+ "input": "&strns;",
+ "description": "Named entity: strns; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00af"
+ ]
+ ]
+ },
+ {
+ "input": "&sub",
+ "description": "Bad named entity: sub without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&sub"
+ ]
+ ]
+ },
+ {
+ "input": "&sub;",
+ "description": "Named entity: sub; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2282"
+ ]
+ ]
+ },
+ {
+ "input": "&subE",
+ "description": "Bad named entity: subE without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&subE"
+ ]
+ ]
+ },
+ {
+ "input": "&subE;",
+ "description": "Named entity: subE; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2ac5"
+ ]
+ ]
+ },
+ {
+ "input": "&subdot",
+ "description": "Bad named entity: subdot without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&subdot"
+ ]
+ ]
+ },
+ {
+ "input": "&subdot;",
+ "description": "Named entity: subdot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2abd"
+ ]
+ ]
+ },
+ {
+ "input": "&sube",
+ "description": "Bad named entity: sube without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&sube"
+ ]
+ ]
+ },
+ {
+ "input": "&sube;",
+ "description": "Named entity: sube; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2286"
+ ]
+ ]
+ },
+ {
+ "input": "&subedot",
+ "description": "Bad named entity: subedot without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&subedot"
+ ]
+ ]
+ },
+ {
+ "input": "&subedot;",
+ "description": "Named entity: subedot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2ac3"
+ ]
+ ]
+ },
+ {
+ "input": "&submult",
+ "description": "Bad named entity: submult without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&submult"
+ ]
+ ]
+ },
+ {
+ "input": "&submult;",
+ "description": "Named entity: submult; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2ac1"
+ ]
+ ]
+ },
+ {
+ "input": "&subnE",
+ "description": "Bad named entity: subnE without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&subnE"
+ ]
+ ]
+ },
+ {
+ "input": "&subnE;",
+ "description": "Named entity: subnE; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2acb"
+ ]
+ ]
+ },
+ {
+ "input": "&subne",
+ "description": "Bad named entity: subne without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&subne"
+ ]
+ ]
+ },
+ {
+ "input": "&subne;",
+ "description": "Named entity: subne; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u228a"
+ ]
+ ]
+ },
+ {
+ "input": "&subplus",
+ "description": "Bad named entity: subplus without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&subplus"
+ ]
+ ]
+ },
+ {
+ "input": "&subplus;",
+ "description": "Named entity: subplus; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2abf"
+ ]
+ ]
+ },
+ {
+ "input": "&subrarr",
+ "description": "Bad named entity: subrarr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&subrarr"
+ ]
+ ]
+ },
+ {
+ "input": "&subrarr;",
+ "description": "Named entity: subrarr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2979"
+ ]
+ ]
+ },
+ {
+ "input": "&subset",
+ "description": "Bad named entity: subset without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&subset"
+ ]
+ ]
+ },
+ {
+ "input": "&subset;",
+ "description": "Named entity: subset; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2282"
+ ]
+ ]
+ },
+ {
+ "input": "&subseteq",
+ "description": "Bad named entity: subseteq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&subseteq"
+ ]
+ ]
+ },
+ {
+ "input": "&subseteq;",
+ "description": "Named entity: subseteq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2286"
+ ]
+ ]
+ },
+ {
+ "input": "&subseteqq",
+ "description": "Bad named entity: subseteqq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&subseteqq"
+ ]
+ ]
+ },
+ {
+ "input": "&subseteqq;",
+ "description": "Named entity: subseteqq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2ac5"
+ ]
+ ]
+ },
+ {
+ "input": "&subsetneq",
+ "description": "Bad named entity: subsetneq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&subsetneq"
+ ]
+ ]
+ },
+ {
+ "input": "&subsetneq;",
+ "description": "Named entity: subsetneq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u228a"
+ ]
+ ]
+ },
+ {
+ "input": "&subsetneqq",
+ "description": "Bad named entity: subsetneqq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&subsetneqq"
+ ]
+ ]
+ },
+ {
+ "input": "&subsetneqq;",
+ "description": "Named entity: subsetneqq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2acb"
+ ]
+ ]
+ },
+ {
+ "input": "&subsim",
+ "description": "Bad named entity: subsim without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&subsim"
+ ]
+ ]
+ },
+ {
+ "input": "&subsim;",
+ "description": "Named entity: subsim; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2ac7"
+ ]
+ ]
+ },
+ {
+ "input": "&subsub",
+ "description": "Bad named entity: subsub without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&subsub"
+ ]
+ ]
+ },
+ {
+ "input": "&subsub;",
+ "description": "Named entity: subsub; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2ad5"
+ ]
+ ]
+ },
+ {
+ "input": "&subsup",
+ "description": "Bad named entity: subsup without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&subsup"
+ ]
+ ]
+ },
+ {
+ "input": "&subsup;",
+ "description": "Named entity: subsup; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2ad3"
+ ]
+ ]
+ },
+ {
+ "input": "&succ",
+ "description": "Bad named entity: succ without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&succ"
+ ]
+ ]
+ },
+ {
+ "input": "&succ;",
+ "description": "Named entity: succ; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u227b"
+ ]
+ ]
+ },
+ {
+ "input": "&succapprox",
+ "description": "Bad named entity: succapprox without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&succapprox"
+ ]
+ ]
+ },
+ {
+ "input": "&succapprox;",
+ "description": "Named entity: succapprox; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2ab8"
+ ]
+ ]
+ },
+ {
+ "input": "&succcurlyeq",
+ "description": "Bad named entity: succcurlyeq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&succcurlyeq"
+ ]
+ ]
+ },
+ {
+ "input": "&succcurlyeq;",
+ "description": "Named entity: succcurlyeq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u227d"
+ ]
+ ]
+ },
+ {
+ "input": "&succeq",
+ "description": "Bad named entity: succeq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&succeq"
+ ]
+ ]
+ },
+ {
+ "input": "&succeq;",
+ "description": "Named entity: succeq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2ab0"
+ ]
+ ]
+ },
+ {
+ "input": "&succnapprox",
+ "description": "Bad named entity: succnapprox without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&succnapprox"
+ ]
+ ]
+ },
+ {
+ "input": "&succnapprox;",
+ "description": "Named entity: succnapprox; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2aba"
+ ]
+ ]
+ },
+ {
+ "input": "&succneqq",
+ "description": "Bad named entity: succneqq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&succneqq"
+ ]
+ ]
+ },
+ {
+ "input": "&succneqq;",
+ "description": "Named entity: succneqq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2ab6"
+ ]
+ ]
+ },
+ {
+ "input": "&succnsim",
+ "description": "Bad named entity: succnsim without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&succnsim"
+ ]
+ ]
+ },
+ {
+ "input": "&succnsim;",
+ "description": "Named entity: succnsim; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22e9"
+ ]
+ ]
+ },
+ {
+ "input": "&succsim",
+ "description": "Bad named entity: succsim without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&succsim"
+ ]
+ ]
+ },
+ {
+ "input": "&succsim;",
+ "description": "Named entity: succsim; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u227f"
+ ]
+ ]
+ },
+ {
+ "input": "&sum",
+ "description": "Bad named entity: sum without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&sum"
+ ]
+ ]
+ },
+ {
+ "input": "&sum;",
+ "description": "Named entity: sum; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2211"
+ ]
+ ]
+ },
+ {
+ "input": "&sung",
+ "description": "Bad named entity: sung without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&sung"
+ ]
+ ]
+ },
+ {
+ "input": "&sung;",
+ "description": "Named entity: sung; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u266a"
+ ]
+ ]
+ },
+ {
+ "input": "&sup",
+ "description": "Bad named entity: sup without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&sup"
+ ]
+ ]
+ },
+ {
+ "input": "&sup1",
+ "description": "Named entity: sup1 without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00b9"
+ ]
+ ]
+ },
+ {
+ "input": "&sup1;",
+ "description": "Named entity: sup1; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00b9"
+ ]
+ ]
+ },
+ {
+ "input": "&sup2",
+ "description": "Named entity: sup2 without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00b2"
+ ]
+ ]
+ },
+ {
+ "input": "&sup2;",
+ "description": "Named entity: sup2; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00b2"
+ ]
+ ]
+ },
+ {
+ "input": "&sup3",
+ "description": "Named entity: sup3 without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00b3"
+ ]
+ ]
+ },
+ {
+ "input": "&sup3;",
+ "description": "Named entity: sup3; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00b3"
+ ]
+ ]
+ },
+ {
+ "input": "&sup;",
+ "description": "Named entity: sup; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2283"
+ ]
+ ]
+ },
+ {
+ "input": "&supE",
+ "description": "Bad named entity: supE without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&supE"
+ ]
+ ]
+ },
+ {
+ "input": "&supE;",
+ "description": "Named entity: supE; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2ac6"
+ ]
+ ]
+ },
+ {
+ "input": "&supdot",
+ "description": "Bad named entity: supdot without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&supdot"
+ ]
+ ]
+ },
+ {
+ "input": "&supdot;",
+ "description": "Named entity: supdot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2abe"
+ ]
+ ]
+ },
+ {
+ "input": "&supdsub",
+ "description": "Bad named entity: supdsub without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&supdsub"
+ ]
+ ]
+ },
+ {
+ "input": "&supdsub;",
+ "description": "Named entity: supdsub; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2ad8"
+ ]
+ ]
+ },
+ {
+ "input": "&supe",
+ "description": "Bad named entity: supe without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&supe"
+ ]
+ ]
+ },
+ {
+ "input": "&supe;",
+ "description": "Named entity: supe; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2287"
+ ]
+ ]
+ },
+ {
+ "input": "&supedot",
+ "description": "Bad named entity: supedot without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&supedot"
+ ]
+ ]
+ },
+ {
+ "input": "&supedot;",
+ "description": "Named entity: supedot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2ac4"
+ ]
+ ]
+ },
+ {
+ "input": "&suphsol",
+ "description": "Bad named entity: suphsol without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&suphsol"
+ ]
+ ]
+ },
+ {
+ "input": "&suphsol;",
+ "description": "Named entity: suphsol; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u27c9"
+ ]
+ ]
+ },
+ {
+ "input": "&suphsub",
+ "description": "Bad named entity: suphsub without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&suphsub"
+ ]
+ ]
+ },
+ {
+ "input": "&suphsub;",
+ "description": "Named entity: suphsub; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2ad7"
+ ]
+ ]
+ },
+ {
+ "input": "&suplarr",
+ "description": "Bad named entity: suplarr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&suplarr"
+ ]
+ ]
+ },
+ {
+ "input": "&suplarr;",
+ "description": "Named entity: suplarr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u297b"
+ ]
+ ]
+ },
+ {
+ "input": "&supmult",
+ "description": "Bad named entity: supmult without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&supmult"
+ ]
+ ]
+ },
+ {
+ "input": "&supmult;",
+ "description": "Named entity: supmult; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2ac2"
+ ]
+ ]
+ },
+ {
+ "input": "&supnE",
+ "description": "Bad named entity: supnE without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&supnE"
+ ]
+ ]
+ },
+ {
+ "input": "&supnE;",
+ "description": "Named entity: supnE; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2acc"
+ ]
+ ]
+ },
+ {
+ "input": "&supne",
+ "description": "Bad named entity: supne without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&supne"
+ ]
+ ]
+ },
+ {
+ "input": "&supne;",
+ "description": "Named entity: supne; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u228b"
+ ]
+ ]
+ },
+ {
+ "input": "&supplus",
+ "description": "Bad named entity: supplus without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&supplus"
+ ]
+ ]
+ },
+ {
+ "input": "&supplus;",
+ "description": "Named entity: supplus; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2ac0"
+ ]
+ ]
+ },
+ {
+ "input": "&supset",
+ "description": "Bad named entity: supset without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&supset"
+ ]
+ ]
+ },
+ {
+ "input": "&supset;",
+ "description": "Named entity: supset; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2283"
+ ]
+ ]
+ },
+ {
+ "input": "&supseteq",
+ "description": "Bad named entity: supseteq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&supseteq"
+ ]
+ ]
+ },
+ {
+ "input": "&supseteq;",
+ "description": "Named entity: supseteq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2287"
+ ]
+ ]
+ },
+ {
+ "input": "&supseteqq",
+ "description": "Bad named entity: supseteqq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&supseteqq"
+ ]
+ ]
+ },
+ {
+ "input": "&supseteqq;",
+ "description": "Named entity: supseteqq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2ac6"
+ ]
+ ]
+ },
+ {
+ "input": "&supsetneq",
+ "description": "Bad named entity: supsetneq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&supsetneq"
+ ]
+ ]
+ },
+ {
+ "input": "&supsetneq;",
+ "description": "Named entity: supsetneq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u228b"
+ ]
+ ]
+ },
+ {
+ "input": "&supsetneqq",
+ "description": "Bad named entity: supsetneqq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&supsetneqq"
+ ]
+ ]
+ },
+ {
+ "input": "&supsetneqq;",
+ "description": "Named entity: supsetneqq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2acc"
+ ]
+ ]
+ },
+ {
+ "input": "&supsim",
+ "description": "Bad named entity: supsim without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&supsim"
+ ]
+ ]
+ },
+ {
+ "input": "&supsim;",
+ "description": "Named entity: supsim; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2ac8"
+ ]
+ ]
+ },
+ {
+ "input": "&supsub",
+ "description": "Bad named entity: supsub without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&supsub"
+ ]
+ ]
+ },
+ {
+ "input": "&supsub;",
+ "description": "Named entity: supsub; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2ad4"
+ ]
+ ]
+ },
+ {
+ "input": "&supsup",
+ "description": "Bad named entity: supsup without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&supsup"
+ ]
+ ]
+ },
+ {
+ "input": "&supsup;",
+ "description": "Named entity: supsup; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2ad6"
+ ]
+ ]
+ },
+ {
+ "input": "&swArr",
+ "description": "Bad named entity: swArr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&swArr"
+ ]
+ ]
+ },
+ {
+ "input": "&swArr;",
+ "description": "Named entity: swArr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21d9"
+ ]
+ ]
+ },
+ {
+ "input": "&swarhk",
+ "description": "Bad named entity: swarhk without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&swarhk"
+ ]
+ ]
+ },
+ {
+ "input": "&swarhk;",
+ "description": "Named entity: swarhk; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2926"
+ ]
+ ]
+ },
+ {
+ "input": "&swarr",
+ "description": "Bad named entity: swarr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&swarr"
+ ]
+ ]
+ },
+ {
+ "input": "&swarr;",
+ "description": "Named entity: swarr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2199"
+ ]
+ ]
+ },
+ {
+ "input": "&swarrow",
+ "description": "Bad named entity: swarrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&swarrow"
+ ]
+ ]
+ },
+ {
+ "input": "&swarrow;",
+ "description": "Named entity: swarrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2199"
+ ]
+ ]
+ },
+ {
+ "input": "&swnwar",
+ "description": "Bad named entity: swnwar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&swnwar"
+ ]
+ ]
+ },
+ {
+ "input": "&swnwar;",
+ "description": "Named entity: swnwar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u292a"
+ ]
+ ]
+ },
+ {
+ "input": "&szlig",
+ "description": "Named entity: szlig without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00df"
+ ]
+ ]
+ },
+ {
+ "input": "&szlig;",
+ "description": "Named entity: szlig; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00df"
+ ]
+ ]
+ },
+ {
+ "input": "&target",
+ "description": "Bad named entity: target without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&target"
+ ]
+ ]
+ },
+ {
+ "input": "&target;",
+ "description": "Named entity: target; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2316"
+ ]
+ ]
+ },
+ {
+ "input": "&tau",
+ "description": "Bad named entity: tau without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&tau"
+ ]
+ ]
+ },
+ {
+ "input": "&tau;",
+ "description": "Named entity: tau; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03c4"
+ ]
+ ]
+ },
+ {
+ "input": "&tbrk",
+ "description": "Bad named entity: tbrk without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&tbrk"
+ ]
+ ]
+ },
+ {
+ "input": "&tbrk;",
+ "description": "Named entity: tbrk; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u23b4"
+ ]
+ ]
+ },
+ {
+ "input": "&tcaron",
+ "description": "Bad named entity: tcaron without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&tcaron"
+ ]
+ ]
+ },
+ {
+ "input": "&tcaron;",
+ "description": "Named entity: tcaron; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0165"
+ ]
+ ]
+ },
+ {
+ "input": "&tcedil",
+ "description": "Bad named entity: tcedil without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&tcedil"
+ ]
+ ]
+ },
+ {
+ "input": "&tcedil;",
+ "description": "Named entity: tcedil; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0163"
+ ]
+ ]
+ },
+ {
+ "input": "&tcy",
+ "description": "Bad named entity: tcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&tcy"
+ ]
+ ]
+ },
+ {
+ "input": "&tcy;",
+ "description": "Named entity: tcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0442"
+ ]
+ ]
+ },
+ {
+ "input": "&tdot",
+ "description": "Bad named entity: tdot without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&tdot"
+ ]
+ ]
+ },
+ {
+ "input": "&tdot;",
+ "description": "Named entity: tdot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u20db"
+ ]
+ ]
+ },
+ {
+ "input": "&telrec",
+ "description": "Bad named entity: telrec without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&telrec"
+ ]
+ ]
+ },
+ {
+ "input": "&telrec;",
+ "description": "Named entity: telrec; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2315"
+ ]
+ ]
+ },
+ {
+ "input": "&tfr",
+ "description": "Bad named entity: tfr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&tfr"
+ ]
+ ]
+ },
+ {
+ "input": "&tfr;",
+ "description": "Named entity: tfr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd31"
+ ]
+ ]
+ },
+ {
+ "input": "&there4",
+ "description": "Bad named entity: there4 without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&there4"
+ ]
+ ]
+ },
+ {
+ "input": "&there4;",
+ "description": "Named entity: there4; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2234"
+ ]
+ ]
+ },
+ {
+ "input": "&therefore",
+ "description": "Bad named entity: therefore without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&therefore"
+ ]
+ ]
+ },
+ {
+ "input": "&therefore;",
+ "description": "Named entity: therefore; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2234"
+ ]
+ ]
+ },
+ {
+ "input": "&theta",
+ "description": "Bad named entity: theta without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&theta"
+ ]
+ ]
+ },
+ {
+ "input": "&theta;",
+ "description": "Named entity: theta; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03b8"
+ ]
+ ]
+ },
+ {
+ "input": "&thetasym",
+ "description": "Bad named entity: thetasym without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&thetasym"
+ ]
+ ]
+ },
+ {
+ "input": "&thetasym;",
+ "description": "Named entity: thetasym; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03d1"
+ ]
+ ]
+ },
+ {
+ "input": "&thetav",
+ "description": "Bad named entity: thetav without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&thetav"
+ ]
+ ]
+ },
+ {
+ "input": "&thetav;",
+ "description": "Named entity: thetav; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03d1"
+ ]
+ ]
+ },
+ {
+ "input": "&thickapprox",
+ "description": "Bad named entity: thickapprox without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&thickapprox"
+ ]
+ ]
+ },
+ {
+ "input": "&thickapprox;",
+ "description": "Named entity: thickapprox; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2248"
+ ]
+ ]
+ },
+ {
+ "input": "&thicksim",
+ "description": "Bad named entity: thicksim without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&thicksim"
+ ]
+ ]
+ },
+ {
+ "input": "&thicksim;",
+ "description": "Named entity: thicksim; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u223c"
+ ]
+ ]
+ },
+ {
+ "input": "&thinsp",
+ "description": "Bad named entity: thinsp without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&thinsp"
+ ]
+ ]
+ },
+ {
+ "input": "&thinsp;",
+ "description": "Named entity: thinsp; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2009"
+ ]
+ ]
+ },
+ {
+ "input": "&thkap",
+ "description": "Bad named entity: thkap without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&thkap"
+ ]
+ ]
+ },
+ {
+ "input": "&thkap;",
+ "description": "Named entity: thkap; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2248"
+ ]
+ ]
+ },
+ {
+ "input": "&thksim",
+ "description": "Bad named entity: thksim without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&thksim"
+ ]
+ ]
+ },
+ {
+ "input": "&thksim;",
+ "description": "Named entity: thksim; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u223c"
+ ]
+ ]
+ },
+ {
+ "input": "&thorn",
+ "description": "Named entity: thorn without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00fe"
+ ]
+ ]
+ },
+ {
+ "input": "&thorn;",
+ "description": "Named entity: thorn; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00fe"
+ ]
+ ]
+ },
+ {
+ "input": "&tilde",
+ "description": "Bad named entity: tilde without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&tilde"
+ ]
+ ]
+ },
+ {
+ "input": "&tilde;",
+ "description": "Named entity: tilde; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u02dc"
+ ]
+ ]
+ },
+ {
+ "input": "&times",
+ "description": "Named entity: times without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00d7"
+ ]
+ ]
+ },
+ {
+ "input": "&times;",
+ "description": "Named entity: times; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00d7"
+ ]
+ ]
+ },
+ {
+ "input": "&timesb;",
+ "description": "Named entity: timesb; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22a0"
+ ]
+ ]
+ },
+ {
+ "input": "&timesbar;",
+ "description": "Named entity: timesbar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a31"
+ ]
+ ]
+ },
+ {
+ "input": "&timesd;",
+ "description": "Named entity: timesd; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a30"
+ ]
+ ]
+ },
+ {
+ "input": "&tint",
+ "description": "Bad named entity: tint without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&tint"
+ ]
+ ]
+ },
+ {
+ "input": "&tint;",
+ "description": "Named entity: tint; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u222d"
+ ]
+ ]
+ },
+ {
+ "input": "&toea",
+ "description": "Bad named entity: toea without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&toea"
+ ]
+ ]
+ },
+ {
+ "input": "&toea;",
+ "description": "Named entity: toea; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2928"
+ ]
+ ]
+ },
+ {
+ "input": "&top",
+ "description": "Bad named entity: top without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&top"
+ ]
+ ]
+ },
+ {
+ "input": "&top;",
+ "description": "Named entity: top; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22a4"
+ ]
+ ]
+ },
+ {
+ "input": "&topbot",
+ "description": "Bad named entity: topbot without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&topbot"
+ ]
+ ]
+ },
+ {
+ "input": "&topbot;",
+ "description": "Named entity: topbot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2336"
+ ]
+ ]
+ },
+ {
+ "input": "&topcir",
+ "description": "Bad named entity: topcir without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&topcir"
+ ]
+ ]
+ },
+ {
+ "input": "&topcir;",
+ "description": "Named entity: topcir; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2af1"
+ ]
+ ]
+ },
+ {
+ "input": "&topf",
+ "description": "Bad named entity: topf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&topf"
+ ]
+ ]
+ },
+ {
+ "input": "&topf;",
+ "description": "Named entity: topf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd65"
+ ]
+ ]
+ },
+ {
+ "input": "&topfork",
+ "description": "Bad named entity: topfork without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&topfork"
+ ]
+ ]
+ },
+ {
+ "input": "&topfork;",
+ "description": "Named entity: topfork; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2ada"
+ ]
+ ]
+ },
+ {
+ "input": "&tosa",
+ "description": "Bad named entity: tosa without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&tosa"
+ ]
+ ]
+ },
+ {
+ "input": "&tosa;",
+ "description": "Named entity: tosa; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2929"
+ ]
+ ]
+ },
+ {
+ "input": "&tprime",
+ "description": "Bad named entity: tprime without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&tprime"
+ ]
+ ]
+ },
+ {
+ "input": "&tprime;",
+ "description": "Named entity: tprime; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2034"
+ ]
+ ]
+ },
+ {
+ "input": "&trade",
+ "description": "Bad named entity: trade without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&trade"
+ ]
+ ]
+ },
+ {
+ "input": "&trade;",
+ "description": "Named entity: trade; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2122"
+ ]
+ ]
+ },
+ {
+ "input": "&triangle",
+ "description": "Bad named entity: triangle without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&triangle"
+ ]
+ ]
+ },
+ {
+ "input": "&triangle;",
+ "description": "Named entity: triangle; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u25b5"
+ ]
+ ]
+ },
+ {
+ "input": "&triangledown",
+ "description": "Bad named entity: triangledown without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&triangledown"
+ ]
+ ]
+ },
+ {
+ "input": "&triangledown;",
+ "description": "Named entity: triangledown; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u25bf"
+ ]
+ ]
+ },
+ {
+ "input": "&triangleleft",
+ "description": "Bad named entity: triangleleft without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&triangleleft"
+ ]
+ ]
+ },
+ {
+ "input": "&triangleleft;",
+ "description": "Named entity: triangleleft; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u25c3"
+ ]
+ ]
+ },
+ {
+ "input": "&trianglelefteq",
+ "description": "Bad named entity: trianglelefteq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&trianglelefteq"
+ ]
+ ]
+ },
+ {
+ "input": "&trianglelefteq;",
+ "description": "Named entity: trianglelefteq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22b4"
+ ]
+ ]
+ },
+ {
+ "input": "&triangleq",
+ "description": "Bad named entity: triangleq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&triangleq"
+ ]
+ ]
+ },
+ {
+ "input": "&triangleq;",
+ "description": "Named entity: triangleq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u225c"
+ ]
+ ]
+ },
+ {
+ "input": "&triangleright",
+ "description": "Bad named entity: triangleright without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&triangleright"
+ ]
+ ]
+ },
+ {
+ "input": "&triangleright;",
+ "description": "Named entity: triangleright; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u25b9"
+ ]
+ ]
+ },
+ {
+ "input": "&trianglerighteq",
+ "description": "Bad named entity: trianglerighteq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&trianglerighteq"
+ ]
+ ]
+ },
+ {
+ "input": "&trianglerighteq;",
+ "description": "Named entity: trianglerighteq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22b5"
+ ]
+ ]
+ },
+ {
+ "input": "&tridot",
+ "description": "Bad named entity: tridot without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&tridot"
+ ]
+ ]
+ },
+ {
+ "input": "&tridot;",
+ "description": "Named entity: tridot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u25ec"
+ ]
+ ]
+ },
+ {
+ "input": "&trie",
+ "description": "Bad named entity: trie without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&trie"
+ ]
+ ]
+ },
+ {
+ "input": "&trie;",
+ "description": "Named entity: trie; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u225c"
+ ]
+ ]
+ },
+ {
+ "input": "&triminus",
+ "description": "Bad named entity: triminus without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&triminus"
+ ]
+ ]
+ },
+ {
+ "input": "&triminus;",
+ "description": "Named entity: triminus; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a3a"
+ ]
+ ]
+ },
+ {
+ "input": "&triplus",
+ "description": "Bad named entity: triplus without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&triplus"
+ ]
+ ]
+ },
+ {
+ "input": "&triplus;",
+ "description": "Named entity: triplus; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a39"
+ ]
+ ]
+ },
+ {
+ "input": "&trisb",
+ "description": "Bad named entity: trisb without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&trisb"
+ ]
+ ]
+ },
+ {
+ "input": "&trisb;",
+ "description": "Named entity: trisb; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u29cd"
+ ]
+ ]
+ },
+ {
+ "input": "&tritime",
+ "description": "Bad named entity: tritime without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&tritime"
+ ]
+ ]
+ },
+ {
+ "input": "&tritime;",
+ "description": "Named entity: tritime; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a3b"
+ ]
+ ]
+ },
+ {
+ "input": "&trpezium",
+ "description": "Bad named entity: trpezium without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&trpezium"
+ ]
+ ]
+ },
+ {
+ "input": "&trpezium;",
+ "description": "Named entity: trpezium; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u23e2"
+ ]
+ ]
+ },
+ {
+ "input": "&tscr",
+ "description": "Bad named entity: tscr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&tscr"
+ ]
+ ]
+ },
+ {
+ "input": "&tscr;",
+ "description": "Named entity: tscr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udcc9"
+ ]
+ ]
+ },
+ {
+ "input": "&tscy",
+ "description": "Bad named entity: tscy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&tscy"
+ ]
+ ]
+ },
+ {
+ "input": "&tscy;",
+ "description": "Named entity: tscy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0446"
+ ]
+ ]
+ },
+ {
+ "input": "&tshcy",
+ "description": "Bad named entity: tshcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&tshcy"
+ ]
+ ]
+ },
+ {
+ "input": "&tshcy;",
+ "description": "Named entity: tshcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u045b"
+ ]
+ ]
+ },
+ {
+ "input": "&tstrok",
+ "description": "Bad named entity: tstrok without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&tstrok"
+ ]
+ ]
+ },
+ {
+ "input": "&tstrok;",
+ "description": "Named entity: tstrok; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0167"
+ ]
+ ]
+ },
+ {
+ "input": "&twixt",
+ "description": "Bad named entity: twixt without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&twixt"
+ ]
+ ]
+ },
+ {
+ "input": "&twixt;",
+ "description": "Named entity: twixt; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u226c"
+ ]
+ ]
+ },
+ {
+ "input": "&twoheadleftarrow",
+ "description": "Bad named entity: twoheadleftarrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&twoheadleftarrow"
+ ]
+ ]
+ },
+ {
+ "input": "&twoheadleftarrow;",
+ "description": "Named entity: twoheadleftarrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u219e"
+ ]
+ ]
+ },
+ {
+ "input": "&twoheadrightarrow",
+ "description": "Bad named entity: twoheadrightarrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&twoheadrightarrow"
+ ]
+ ]
+ },
+ {
+ "input": "&twoheadrightarrow;",
+ "description": "Named entity: twoheadrightarrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21a0"
+ ]
+ ]
+ },
+ {
+ "input": "&uArr",
+ "description": "Bad named entity: uArr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&uArr"
+ ]
+ ]
+ },
+ {
+ "input": "&uArr;",
+ "description": "Named entity: uArr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21d1"
+ ]
+ ]
+ },
+ {
+ "input": "&uHar",
+ "description": "Bad named entity: uHar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&uHar"
+ ]
+ ]
+ },
+ {
+ "input": "&uHar;",
+ "description": "Named entity: uHar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2963"
+ ]
+ ]
+ },
+ {
+ "input": "&uacute",
+ "description": "Named entity: uacute without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00fa"
+ ]
+ ]
+ },
+ {
+ "input": "&uacute;",
+ "description": "Named entity: uacute; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00fa"
+ ]
+ ]
+ },
+ {
+ "input": "&uarr",
+ "description": "Bad named entity: uarr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&uarr"
+ ]
+ ]
+ },
+ {
+ "input": "&uarr;",
+ "description": "Named entity: uarr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2191"
+ ]
+ ]
+ },
+ {
+ "input": "&ubrcy",
+ "description": "Bad named entity: ubrcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ubrcy"
+ ]
+ ]
+ },
+ {
+ "input": "&ubrcy;",
+ "description": "Named entity: ubrcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u045e"
+ ]
+ ]
+ },
+ {
+ "input": "&ubreve",
+ "description": "Bad named entity: ubreve without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ubreve"
+ ]
+ ]
+ },
+ {
+ "input": "&ubreve;",
+ "description": "Named entity: ubreve; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u016d"
+ ]
+ ]
+ },
+ {
+ "input": "&ucirc",
+ "description": "Named entity: ucirc without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00fb"
+ ]
+ ]
+ },
+ {
+ "input": "&ucirc;",
+ "description": "Named entity: ucirc; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00fb"
+ ]
+ ]
+ },
+ {
+ "input": "&ucy",
+ "description": "Bad named entity: ucy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ucy"
+ ]
+ ]
+ },
+ {
+ "input": "&ucy;",
+ "description": "Named entity: ucy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0443"
+ ]
+ ]
+ },
+ {
+ "input": "&udarr",
+ "description": "Bad named entity: udarr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&udarr"
+ ]
+ ]
+ },
+ {
+ "input": "&udarr;",
+ "description": "Named entity: udarr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21c5"
+ ]
+ ]
+ },
+ {
+ "input": "&udblac",
+ "description": "Bad named entity: udblac without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&udblac"
+ ]
+ ]
+ },
+ {
+ "input": "&udblac;",
+ "description": "Named entity: udblac; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0171"
+ ]
+ ]
+ },
+ {
+ "input": "&udhar",
+ "description": "Bad named entity: udhar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&udhar"
+ ]
+ ]
+ },
+ {
+ "input": "&udhar;",
+ "description": "Named entity: udhar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u296e"
+ ]
+ ]
+ },
+ {
+ "input": "&ufisht",
+ "description": "Bad named entity: ufisht without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ufisht"
+ ]
+ ]
+ },
+ {
+ "input": "&ufisht;",
+ "description": "Named entity: ufisht; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u297e"
+ ]
+ ]
+ },
+ {
+ "input": "&ufr",
+ "description": "Bad named entity: ufr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ufr"
+ ]
+ ]
+ },
+ {
+ "input": "&ufr;",
+ "description": "Named entity: ufr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd32"
+ ]
+ ]
+ },
+ {
+ "input": "&ugrave",
+ "description": "Named entity: ugrave without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00f9"
+ ]
+ ]
+ },
+ {
+ "input": "&ugrave;",
+ "description": "Named entity: ugrave; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00f9"
+ ]
+ ]
+ },
+ {
+ "input": "&uharl",
+ "description": "Bad named entity: uharl without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&uharl"
+ ]
+ ]
+ },
+ {
+ "input": "&uharl;",
+ "description": "Named entity: uharl; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21bf"
+ ]
+ ]
+ },
+ {
+ "input": "&uharr",
+ "description": "Bad named entity: uharr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&uharr"
+ ]
+ ]
+ },
+ {
+ "input": "&uharr;",
+ "description": "Named entity: uharr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21be"
+ ]
+ ]
+ },
+ {
+ "input": "&uhblk",
+ "description": "Bad named entity: uhblk without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&uhblk"
+ ]
+ ]
+ },
+ {
+ "input": "&uhblk;",
+ "description": "Named entity: uhblk; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2580"
+ ]
+ ]
+ },
+ {
+ "input": "&ulcorn",
+ "description": "Bad named entity: ulcorn without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ulcorn"
+ ]
+ ]
+ },
+ {
+ "input": "&ulcorn;",
+ "description": "Named entity: ulcorn; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u231c"
+ ]
+ ]
+ },
+ {
+ "input": "&ulcorner",
+ "description": "Bad named entity: ulcorner without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ulcorner"
+ ]
+ ]
+ },
+ {
+ "input": "&ulcorner;",
+ "description": "Named entity: ulcorner; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u231c"
+ ]
+ ]
+ },
+ {
+ "input": "&ulcrop",
+ "description": "Bad named entity: ulcrop without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ulcrop"
+ ]
+ ]
+ },
+ {
+ "input": "&ulcrop;",
+ "description": "Named entity: ulcrop; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u230f"
+ ]
+ ]
+ },
+ {
+ "input": "&ultri",
+ "description": "Bad named entity: ultri without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ultri"
+ ]
+ ]
+ },
+ {
+ "input": "&ultri;",
+ "description": "Named entity: ultri; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u25f8"
+ ]
+ ]
+ },
+ {
+ "input": "&umacr",
+ "description": "Bad named entity: umacr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&umacr"
+ ]
+ ]
+ },
+ {
+ "input": "&umacr;",
+ "description": "Named entity: umacr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u016b"
+ ]
+ ]
+ },
+ {
+ "input": "&uml",
+ "description": "Named entity: uml without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00a8"
+ ]
+ ]
+ },
+ {
+ "input": "&uml;",
+ "description": "Named entity: uml; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00a8"
+ ]
+ ]
+ },
+ {
+ "input": "&uogon",
+ "description": "Bad named entity: uogon without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&uogon"
+ ]
+ ]
+ },
+ {
+ "input": "&uogon;",
+ "description": "Named entity: uogon; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0173"
+ ]
+ ]
+ },
+ {
+ "input": "&uopf",
+ "description": "Bad named entity: uopf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&uopf"
+ ]
+ ]
+ },
+ {
+ "input": "&uopf;",
+ "description": "Named entity: uopf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd66"
+ ]
+ ]
+ },
+ {
+ "input": "&uparrow",
+ "description": "Bad named entity: uparrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&uparrow"
+ ]
+ ]
+ },
+ {
+ "input": "&uparrow;",
+ "description": "Named entity: uparrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2191"
+ ]
+ ]
+ },
+ {
+ "input": "&updownarrow",
+ "description": "Bad named entity: updownarrow without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&updownarrow"
+ ]
+ ]
+ },
+ {
+ "input": "&updownarrow;",
+ "description": "Named entity: updownarrow; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2195"
+ ]
+ ]
+ },
+ {
+ "input": "&upharpoonleft",
+ "description": "Bad named entity: upharpoonleft without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&upharpoonleft"
+ ]
+ ]
+ },
+ {
+ "input": "&upharpoonleft;",
+ "description": "Named entity: upharpoonleft; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21bf"
+ ]
+ ]
+ },
+ {
+ "input": "&upharpoonright",
+ "description": "Bad named entity: upharpoonright without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&upharpoonright"
+ ]
+ ]
+ },
+ {
+ "input": "&upharpoonright;",
+ "description": "Named entity: upharpoonright; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21be"
+ ]
+ ]
+ },
+ {
+ "input": "&uplus",
+ "description": "Bad named entity: uplus without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&uplus"
+ ]
+ ]
+ },
+ {
+ "input": "&uplus;",
+ "description": "Named entity: uplus; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u228e"
+ ]
+ ]
+ },
+ {
+ "input": "&upsi",
+ "description": "Bad named entity: upsi without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&upsi"
+ ]
+ ]
+ },
+ {
+ "input": "&upsi;",
+ "description": "Named entity: upsi; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03c5"
+ ]
+ ]
+ },
+ {
+ "input": "&upsih",
+ "description": "Bad named entity: upsih without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&upsih"
+ ]
+ ]
+ },
+ {
+ "input": "&upsih;",
+ "description": "Named entity: upsih; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03d2"
+ ]
+ ]
+ },
+ {
+ "input": "&upsilon",
+ "description": "Bad named entity: upsilon without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&upsilon"
+ ]
+ ]
+ },
+ {
+ "input": "&upsilon;",
+ "description": "Named entity: upsilon; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03c5"
+ ]
+ ]
+ },
+ {
+ "input": "&upuparrows",
+ "description": "Bad named entity: upuparrows without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&upuparrows"
+ ]
+ ]
+ },
+ {
+ "input": "&upuparrows;",
+ "description": "Named entity: upuparrows; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21c8"
+ ]
+ ]
+ },
+ {
+ "input": "&urcorn",
+ "description": "Bad named entity: urcorn without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&urcorn"
+ ]
+ ]
+ },
+ {
+ "input": "&urcorn;",
+ "description": "Named entity: urcorn; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u231d"
+ ]
+ ]
+ },
+ {
+ "input": "&urcorner",
+ "description": "Bad named entity: urcorner without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&urcorner"
+ ]
+ ]
+ },
+ {
+ "input": "&urcorner;",
+ "description": "Named entity: urcorner; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u231d"
+ ]
+ ]
+ },
+ {
+ "input": "&urcrop",
+ "description": "Bad named entity: urcrop without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&urcrop"
+ ]
+ ]
+ },
+ {
+ "input": "&urcrop;",
+ "description": "Named entity: urcrop; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u230e"
+ ]
+ ]
+ },
+ {
+ "input": "&uring",
+ "description": "Bad named entity: uring without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&uring"
+ ]
+ ]
+ },
+ {
+ "input": "&uring;",
+ "description": "Named entity: uring; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u016f"
+ ]
+ ]
+ },
+ {
+ "input": "&urtri",
+ "description": "Bad named entity: urtri without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&urtri"
+ ]
+ ]
+ },
+ {
+ "input": "&urtri;",
+ "description": "Named entity: urtri; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u25f9"
+ ]
+ ]
+ },
+ {
+ "input": "&uscr",
+ "description": "Bad named entity: uscr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&uscr"
+ ]
+ ]
+ },
+ {
+ "input": "&uscr;",
+ "description": "Named entity: uscr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udcca"
+ ]
+ ]
+ },
+ {
+ "input": "&utdot",
+ "description": "Bad named entity: utdot without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&utdot"
+ ]
+ ]
+ },
+ {
+ "input": "&utdot;",
+ "description": "Named entity: utdot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22f0"
+ ]
+ ]
+ },
+ {
+ "input": "&utilde",
+ "description": "Bad named entity: utilde without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&utilde"
+ ]
+ ]
+ },
+ {
+ "input": "&utilde;",
+ "description": "Named entity: utilde; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0169"
+ ]
+ ]
+ },
+ {
+ "input": "&utri",
+ "description": "Bad named entity: utri without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&utri"
+ ]
+ ]
+ },
+ {
+ "input": "&utri;",
+ "description": "Named entity: utri; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u25b5"
+ ]
+ ]
+ },
+ {
+ "input": "&utrif",
+ "description": "Bad named entity: utrif without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&utrif"
+ ]
+ ]
+ },
+ {
+ "input": "&utrif;",
+ "description": "Named entity: utrif; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u25b4"
+ ]
+ ]
+ },
+ {
+ "input": "&uuarr",
+ "description": "Bad named entity: uuarr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&uuarr"
+ ]
+ ]
+ },
+ {
+ "input": "&uuarr;",
+ "description": "Named entity: uuarr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21c8"
+ ]
+ ]
+ },
+ {
+ "input": "&uuml",
+ "description": "Named entity: uuml without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00fc"
+ ]
+ ]
+ },
+ {
+ "input": "&uuml;",
+ "description": "Named entity: uuml; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00fc"
+ ]
+ ]
+ },
+ {
+ "input": "&uwangle",
+ "description": "Bad named entity: uwangle without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&uwangle"
+ ]
+ ]
+ },
+ {
+ "input": "&uwangle;",
+ "description": "Named entity: uwangle; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u29a7"
+ ]
+ ]
+ },
+ {
+ "input": "&vArr",
+ "description": "Bad named entity: vArr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&vArr"
+ ]
+ ]
+ },
+ {
+ "input": "&vArr;",
+ "description": "Named entity: vArr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21d5"
+ ]
+ ]
+ },
+ {
+ "input": "&vBar",
+ "description": "Bad named entity: vBar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&vBar"
+ ]
+ ]
+ },
+ {
+ "input": "&vBar;",
+ "description": "Named entity: vBar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2ae8"
+ ]
+ ]
+ },
+ {
+ "input": "&vBarv",
+ "description": "Bad named entity: vBarv without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&vBarv"
+ ]
+ ]
+ },
+ {
+ "input": "&vBarv;",
+ "description": "Named entity: vBarv; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2ae9"
+ ]
+ ]
+ },
+ {
+ "input": "&vDash",
+ "description": "Bad named entity: vDash without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&vDash"
+ ]
+ ]
+ },
+ {
+ "input": "&vDash;",
+ "description": "Named entity: vDash; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22a8"
+ ]
+ ]
+ },
+ {
+ "input": "&vangrt",
+ "description": "Bad named entity: vangrt without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&vangrt"
+ ]
+ ]
+ },
+ {
+ "input": "&vangrt;",
+ "description": "Named entity: vangrt; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u299c"
+ ]
+ ]
+ },
+ {
+ "input": "&varepsilon",
+ "description": "Bad named entity: varepsilon without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&varepsilon"
+ ]
+ ]
+ },
+ {
+ "input": "&varepsilon;",
+ "description": "Named entity: varepsilon; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03f5"
+ ]
+ ]
+ },
+ {
+ "input": "&varkappa",
+ "description": "Bad named entity: varkappa without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&varkappa"
+ ]
+ ]
+ },
+ {
+ "input": "&varkappa;",
+ "description": "Named entity: varkappa; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03f0"
+ ]
+ ]
+ },
+ {
+ "input": "&varnothing",
+ "description": "Bad named entity: varnothing without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&varnothing"
+ ]
+ ]
+ },
+ {
+ "input": "&varnothing;",
+ "description": "Named entity: varnothing; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2205"
+ ]
+ ]
+ },
+ {
+ "input": "&varphi",
+ "description": "Bad named entity: varphi without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&varphi"
+ ]
+ ]
+ },
+ {
+ "input": "&varphi;",
+ "description": "Named entity: varphi; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03d5"
+ ]
+ ]
+ },
+ {
+ "input": "&varpi",
+ "description": "Bad named entity: varpi without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&varpi"
+ ]
+ ]
+ },
+ {
+ "input": "&varpi;",
+ "description": "Named entity: varpi; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03d6"
+ ]
+ ]
+ },
+ {
+ "input": "&varpropto",
+ "description": "Bad named entity: varpropto without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&varpropto"
+ ]
+ ]
+ },
+ {
+ "input": "&varpropto;",
+ "description": "Named entity: varpropto; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u221d"
+ ]
+ ]
+ },
+ {
+ "input": "&varr",
+ "description": "Bad named entity: varr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&varr"
+ ]
+ ]
+ },
+ {
+ "input": "&varr;",
+ "description": "Named entity: varr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2195"
+ ]
+ ]
+ },
+ {
+ "input": "&varrho",
+ "description": "Bad named entity: varrho without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&varrho"
+ ]
+ ]
+ },
+ {
+ "input": "&varrho;",
+ "description": "Named entity: varrho; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03f1"
+ ]
+ ]
+ },
+ {
+ "input": "&varsigma",
+ "description": "Bad named entity: varsigma without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&varsigma"
+ ]
+ ]
+ },
+ {
+ "input": "&varsigma;",
+ "description": "Named entity: varsigma; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03c2"
+ ]
+ ]
+ },
+ {
+ "input": "&varsubsetneq",
+ "description": "Bad named entity: varsubsetneq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&varsubsetneq"
+ ]
+ ]
+ },
+ {
+ "input": "&varsubsetneq;",
+ "description": "Named entity: varsubsetneq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u228a\ufe00"
+ ]
+ ]
+ },
+ {
+ "input": "&varsubsetneqq",
+ "description": "Bad named entity: varsubsetneqq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&varsubsetneqq"
+ ]
+ ]
+ },
+ {
+ "input": "&varsubsetneqq;",
+ "description": "Named entity: varsubsetneqq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2acb\ufe00"
+ ]
+ ]
+ },
+ {
+ "input": "&varsupsetneq",
+ "description": "Bad named entity: varsupsetneq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&varsupsetneq"
+ ]
+ ]
+ },
+ {
+ "input": "&varsupsetneq;",
+ "description": "Named entity: varsupsetneq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u228b\ufe00"
+ ]
+ ]
+ },
+ {
+ "input": "&varsupsetneqq",
+ "description": "Bad named entity: varsupsetneqq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&varsupsetneqq"
+ ]
+ ]
+ },
+ {
+ "input": "&varsupsetneqq;",
+ "description": "Named entity: varsupsetneqq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2acc\ufe00"
+ ]
+ ]
+ },
+ {
+ "input": "&vartheta",
+ "description": "Bad named entity: vartheta without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&vartheta"
+ ]
+ ]
+ },
+ {
+ "input": "&vartheta;",
+ "description": "Named entity: vartheta; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03d1"
+ ]
+ ]
+ },
+ {
+ "input": "&vartriangleleft",
+ "description": "Bad named entity: vartriangleleft without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&vartriangleleft"
+ ]
+ ]
+ },
+ {
+ "input": "&vartriangleleft;",
+ "description": "Named entity: vartriangleleft; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22b2"
+ ]
+ ]
+ },
+ {
+ "input": "&vartriangleright",
+ "description": "Bad named entity: vartriangleright without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&vartriangleright"
+ ]
+ ]
+ },
+ {
+ "input": "&vartriangleright;",
+ "description": "Named entity: vartriangleright; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22b3"
+ ]
+ ]
+ },
+ {
+ "input": "&vcy",
+ "description": "Bad named entity: vcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&vcy"
+ ]
+ ]
+ },
+ {
+ "input": "&vcy;",
+ "description": "Named entity: vcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0432"
+ ]
+ ]
+ },
+ {
+ "input": "&vdash",
+ "description": "Bad named entity: vdash without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&vdash"
+ ]
+ ]
+ },
+ {
+ "input": "&vdash;",
+ "description": "Named entity: vdash; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22a2"
+ ]
+ ]
+ },
+ {
+ "input": "&vee",
+ "description": "Bad named entity: vee without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&vee"
+ ]
+ ]
+ },
+ {
+ "input": "&vee;",
+ "description": "Named entity: vee; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2228"
+ ]
+ ]
+ },
+ {
+ "input": "&veebar",
+ "description": "Bad named entity: veebar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&veebar"
+ ]
+ ]
+ },
+ {
+ "input": "&veebar;",
+ "description": "Named entity: veebar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22bb"
+ ]
+ ]
+ },
+ {
+ "input": "&veeeq",
+ "description": "Bad named entity: veeeq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&veeeq"
+ ]
+ ]
+ },
+ {
+ "input": "&veeeq;",
+ "description": "Named entity: veeeq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u225a"
+ ]
+ ]
+ },
+ {
+ "input": "&vellip",
+ "description": "Bad named entity: vellip without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&vellip"
+ ]
+ ]
+ },
+ {
+ "input": "&vellip;",
+ "description": "Named entity: vellip; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22ee"
+ ]
+ ]
+ },
+ {
+ "input": "&verbar",
+ "description": "Bad named entity: verbar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&verbar"
+ ]
+ ]
+ },
+ {
+ "input": "&verbar;",
+ "description": "Named entity: verbar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "|"
+ ]
+ ]
+ },
+ {
+ "input": "&vert",
+ "description": "Bad named entity: vert without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&vert"
+ ]
+ ]
+ },
+ {
+ "input": "&vert;",
+ "description": "Named entity: vert; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "|"
+ ]
+ ]
+ },
+ {
+ "input": "&vfr",
+ "description": "Bad named entity: vfr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&vfr"
+ ]
+ ]
+ },
+ {
+ "input": "&vfr;",
+ "description": "Named entity: vfr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd33"
+ ]
+ ]
+ },
+ {
+ "input": "&vltri",
+ "description": "Bad named entity: vltri without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&vltri"
+ ]
+ ]
+ },
+ {
+ "input": "&vltri;",
+ "description": "Named entity: vltri; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22b2"
+ ]
+ ]
+ },
+ {
+ "input": "&vnsub",
+ "description": "Bad named entity: vnsub without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&vnsub"
+ ]
+ ]
+ },
+ {
+ "input": "&vnsub;",
+ "description": "Named entity: vnsub; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2282\u20d2"
+ ]
+ ]
+ },
+ {
+ "input": "&vnsup",
+ "description": "Bad named entity: vnsup without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&vnsup"
+ ]
+ ]
+ },
+ {
+ "input": "&vnsup;",
+ "description": "Named entity: vnsup; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2283\u20d2"
+ ]
+ ]
+ },
+ {
+ "input": "&vopf",
+ "description": "Bad named entity: vopf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&vopf"
+ ]
+ ]
+ },
+ {
+ "input": "&vopf;",
+ "description": "Named entity: vopf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd67"
+ ]
+ ]
+ },
+ {
+ "input": "&vprop",
+ "description": "Bad named entity: vprop without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&vprop"
+ ]
+ ]
+ },
+ {
+ "input": "&vprop;",
+ "description": "Named entity: vprop; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u221d"
+ ]
+ ]
+ },
+ {
+ "input": "&vrtri",
+ "description": "Bad named entity: vrtri without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&vrtri"
+ ]
+ ]
+ },
+ {
+ "input": "&vrtri;",
+ "description": "Named entity: vrtri; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22b3"
+ ]
+ ]
+ },
+ {
+ "input": "&vscr",
+ "description": "Bad named entity: vscr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&vscr"
+ ]
+ ]
+ },
+ {
+ "input": "&vscr;",
+ "description": "Named entity: vscr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udccb"
+ ]
+ ]
+ },
+ {
+ "input": "&vsubnE",
+ "description": "Bad named entity: vsubnE without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&vsubnE"
+ ]
+ ]
+ },
+ {
+ "input": "&vsubnE;",
+ "description": "Named entity: vsubnE; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2acb\ufe00"
+ ]
+ ]
+ },
+ {
+ "input": "&vsubne",
+ "description": "Bad named entity: vsubne without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&vsubne"
+ ]
+ ]
+ },
+ {
+ "input": "&vsubne;",
+ "description": "Named entity: vsubne; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u228a\ufe00"
+ ]
+ ]
+ },
+ {
+ "input": "&vsupnE",
+ "description": "Bad named entity: vsupnE without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&vsupnE"
+ ]
+ ]
+ },
+ {
+ "input": "&vsupnE;",
+ "description": "Named entity: vsupnE; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2acc\ufe00"
+ ]
+ ]
+ },
+ {
+ "input": "&vsupne",
+ "description": "Bad named entity: vsupne without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&vsupne"
+ ]
+ ]
+ },
+ {
+ "input": "&vsupne;",
+ "description": "Named entity: vsupne; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u228b\ufe00"
+ ]
+ ]
+ },
+ {
+ "input": "&vzigzag",
+ "description": "Bad named entity: vzigzag without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&vzigzag"
+ ]
+ ]
+ },
+ {
+ "input": "&vzigzag;",
+ "description": "Named entity: vzigzag; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u299a"
+ ]
+ ]
+ },
+ {
+ "input": "&wcirc",
+ "description": "Bad named entity: wcirc without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&wcirc"
+ ]
+ ]
+ },
+ {
+ "input": "&wcirc;",
+ "description": "Named entity: wcirc; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0175"
+ ]
+ ]
+ },
+ {
+ "input": "&wedbar",
+ "description": "Bad named entity: wedbar without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&wedbar"
+ ]
+ ]
+ },
+ {
+ "input": "&wedbar;",
+ "description": "Named entity: wedbar; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a5f"
+ ]
+ ]
+ },
+ {
+ "input": "&wedge",
+ "description": "Bad named entity: wedge without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&wedge"
+ ]
+ ]
+ },
+ {
+ "input": "&wedge;",
+ "description": "Named entity: wedge; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2227"
+ ]
+ ]
+ },
+ {
+ "input": "&wedgeq",
+ "description": "Bad named entity: wedgeq without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&wedgeq"
+ ]
+ ]
+ },
+ {
+ "input": "&wedgeq;",
+ "description": "Named entity: wedgeq; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2259"
+ ]
+ ]
+ },
+ {
+ "input": "&weierp",
+ "description": "Bad named entity: weierp without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&weierp"
+ ]
+ ]
+ },
+ {
+ "input": "&weierp;",
+ "description": "Named entity: weierp; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2118"
+ ]
+ ]
+ },
+ {
+ "input": "&wfr",
+ "description": "Bad named entity: wfr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&wfr"
+ ]
+ ]
+ },
+ {
+ "input": "&wfr;",
+ "description": "Named entity: wfr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd34"
+ ]
+ ]
+ },
+ {
+ "input": "&wopf",
+ "description": "Bad named entity: wopf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&wopf"
+ ]
+ ]
+ },
+ {
+ "input": "&wopf;",
+ "description": "Named entity: wopf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd68"
+ ]
+ ]
+ },
+ {
+ "input": "&wp",
+ "description": "Bad named entity: wp without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&wp"
+ ]
+ ]
+ },
+ {
+ "input": "&wp;",
+ "description": "Named entity: wp; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2118"
+ ]
+ ]
+ },
+ {
+ "input": "&wr",
+ "description": "Bad named entity: wr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&wr"
+ ]
+ ]
+ },
+ {
+ "input": "&wr;",
+ "description": "Named entity: wr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2240"
+ ]
+ ]
+ },
+ {
+ "input": "&wreath",
+ "description": "Bad named entity: wreath without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&wreath"
+ ]
+ ]
+ },
+ {
+ "input": "&wreath;",
+ "description": "Named entity: wreath; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2240"
+ ]
+ ]
+ },
+ {
+ "input": "&wscr",
+ "description": "Bad named entity: wscr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&wscr"
+ ]
+ ]
+ },
+ {
+ "input": "&wscr;",
+ "description": "Named entity: wscr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udccc"
+ ]
+ ]
+ },
+ {
+ "input": "&xcap",
+ "description": "Bad named entity: xcap without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&xcap"
+ ]
+ ]
+ },
+ {
+ "input": "&xcap;",
+ "description": "Named entity: xcap; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22c2"
+ ]
+ ]
+ },
+ {
+ "input": "&xcirc",
+ "description": "Bad named entity: xcirc without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&xcirc"
+ ]
+ ]
+ },
+ {
+ "input": "&xcirc;",
+ "description": "Named entity: xcirc; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u25ef"
+ ]
+ ]
+ },
+ {
+ "input": "&xcup",
+ "description": "Bad named entity: xcup without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&xcup"
+ ]
+ ]
+ },
+ {
+ "input": "&xcup;",
+ "description": "Named entity: xcup; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22c3"
+ ]
+ ]
+ },
+ {
+ "input": "&xdtri",
+ "description": "Bad named entity: xdtri without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&xdtri"
+ ]
+ ]
+ },
+ {
+ "input": "&xdtri;",
+ "description": "Named entity: xdtri; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u25bd"
+ ]
+ ]
+ },
+ {
+ "input": "&xfr",
+ "description": "Bad named entity: xfr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&xfr"
+ ]
+ ]
+ },
+ {
+ "input": "&xfr;",
+ "description": "Named entity: xfr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd35"
+ ]
+ ]
+ },
+ {
+ "input": "&xhArr",
+ "description": "Bad named entity: xhArr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&xhArr"
+ ]
+ ]
+ },
+ {
+ "input": "&xhArr;",
+ "description": "Named entity: xhArr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u27fa"
+ ]
+ ]
+ },
+ {
+ "input": "&xharr",
+ "description": "Bad named entity: xharr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&xharr"
+ ]
+ ]
+ },
+ {
+ "input": "&xharr;",
+ "description": "Named entity: xharr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u27f7"
+ ]
+ ]
+ },
+ {
+ "input": "&xi",
+ "description": "Bad named entity: xi without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&xi"
+ ]
+ ]
+ },
+ {
+ "input": "&xi;",
+ "description": "Named entity: xi; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03be"
+ ]
+ ]
+ },
+ {
+ "input": "&xlArr",
+ "description": "Bad named entity: xlArr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&xlArr"
+ ]
+ ]
+ },
+ {
+ "input": "&xlArr;",
+ "description": "Named entity: xlArr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u27f8"
+ ]
+ ]
+ },
+ {
+ "input": "&xlarr",
+ "description": "Bad named entity: xlarr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&xlarr"
+ ]
+ ]
+ },
+ {
+ "input": "&xlarr;",
+ "description": "Named entity: xlarr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u27f5"
+ ]
+ ]
+ },
+ {
+ "input": "&xmap",
+ "description": "Bad named entity: xmap without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&xmap"
+ ]
+ ]
+ },
+ {
+ "input": "&xmap;",
+ "description": "Named entity: xmap; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u27fc"
+ ]
+ ]
+ },
+ {
+ "input": "&xnis",
+ "description": "Bad named entity: xnis without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&xnis"
+ ]
+ ]
+ },
+ {
+ "input": "&xnis;",
+ "description": "Named entity: xnis; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22fb"
+ ]
+ ]
+ },
+ {
+ "input": "&xodot",
+ "description": "Bad named entity: xodot without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&xodot"
+ ]
+ ]
+ },
+ {
+ "input": "&xodot;",
+ "description": "Named entity: xodot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a00"
+ ]
+ ]
+ },
+ {
+ "input": "&xopf",
+ "description": "Bad named entity: xopf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&xopf"
+ ]
+ ]
+ },
+ {
+ "input": "&xopf;",
+ "description": "Named entity: xopf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd69"
+ ]
+ ]
+ },
+ {
+ "input": "&xoplus",
+ "description": "Bad named entity: xoplus without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&xoplus"
+ ]
+ ]
+ },
+ {
+ "input": "&xoplus;",
+ "description": "Named entity: xoplus; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a01"
+ ]
+ ]
+ },
+ {
+ "input": "&xotime",
+ "description": "Bad named entity: xotime without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&xotime"
+ ]
+ ]
+ },
+ {
+ "input": "&xotime;",
+ "description": "Named entity: xotime; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a02"
+ ]
+ ]
+ },
+ {
+ "input": "&xrArr",
+ "description": "Bad named entity: xrArr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&xrArr"
+ ]
+ ]
+ },
+ {
+ "input": "&xrArr;",
+ "description": "Named entity: xrArr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u27f9"
+ ]
+ ]
+ },
+ {
+ "input": "&xrarr",
+ "description": "Bad named entity: xrarr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&xrarr"
+ ]
+ ]
+ },
+ {
+ "input": "&xrarr;",
+ "description": "Named entity: xrarr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u27f6"
+ ]
+ ]
+ },
+ {
+ "input": "&xscr",
+ "description": "Bad named entity: xscr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&xscr"
+ ]
+ ]
+ },
+ {
+ "input": "&xscr;",
+ "description": "Named entity: xscr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udccd"
+ ]
+ ]
+ },
+ {
+ "input": "&xsqcup",
+ "description": "Bad named entity: xsqcup without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&xsqcup"
+ ]
+ ]
+ },
+ {
+ "input": "&xsqcup;",
+ "description": "Named entity: xsqcup; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a06"
+ ]
+ ]
+ },
+ {
+ "input": "&xuplus",
+ "description": "Bad named entity: xuplus without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&xuplus"
+ ]
+ ]
+ },
+ {
+ "input": "&xuplus;",
+ "description": "Named entity: xuplus; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2a04"
+ ]
+ ]
+ },
+ {
+ "input": "&xutri",
+ "description": "Bad named entity: xutri without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&xutri"
+ ]
+ ]
+ },
+ {
+ "input": "&xutri;",
+ "description": "Named entity: xutri; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u25b3"
+ ]
+ ]
+ },
+ {
+ "input": "&xvee",
+ "description": "Bad named entity: xvee without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&xvee"
+ ]
+ ]
+ },
+ {
+ "input": "&xvee;",
+ "description": "Named entity: xvee; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22c1"
+ ]
+ ]
+ },
+ {
+ "input": "&xwedge",
+ "description": "Bad named entity: xwedge without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&xwedge"
+ ]
+ ]
+ },
+ {
+ "input": "&xwedge;",
+ "description": "Named entity: xwedge; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u22c0"
+ ]
+ ]
+ },
+ {
+ "input": "&yacute",
+ "description": "Named entity: yacute without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00fd"
+ ]
+ ]
+ },
+ {
+ "input": "&yacute;",
+ "description": "Named entity: yacute; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00fd"
+ ]
+ ]
+ },
+ {
+ "input": "&yacy",
+ "description": "Bad named entity: yacy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&yacy"
+ ]
+ ]
+ },
+ {
+ "input": "&yacy;",
+ "description": "Named entity: yacy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u044f"
+ ]
+ ]
+ },
+ {
+ "input": "&ycirc",
+ "description": "Bad named entity: ycirc without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ycirc"
+ ]
+ ]
+ },
+ {
+ "input": "&ycirc;",
+ "description": "Named entity: ycirc; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0177"
+ ]
+ ]
+ },
+ {
+ "input": "&ycy",
+ "description": "Bad named entity: ycy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&ycy"
+ ]
+ ]
+ },
+ {
+ "input": "&ycy;",
+ "description": "Named entity: ycy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u044b"
+ ]
+ ]
+ },
+ {
+ "input": "&yen",
+ "description": "Named entity: yen without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00a5"
+ ]
+ ]
+ },
+ {
+ "input": "&yen;",
+ "description": "Named entity: yen; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00a5"
+ ]
+ ]
+ },
+ {
+ "input": "&yfr",
+ "description": "Bad named entity: yfr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&yfr"
+ ]
+ ]
+ },
+ {
+ "input": "&yfr;",
+ "description": "Named entity: yfr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd36"
+ ]
+ ]
+ },
+ {
+ "input": "&yicy",
+ "description": "Bad named entity: yicy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&yicy"
+ ]
+ ]
+ },
+ {
+ "input": "&yicy;",
+ "description": "Named entity: yicy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0457"
+ ]
+ ]
+ },
+ {
+ "input": "&yopf",
+ "description": "Bad named entity: yopf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&yopf"
+ ]
+ ]
+ },
+ {
+ "input": "&yopf;",
+ "description": "Named entity: yopf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd6a"
+ ]
+ ]
+ },
+ {
+ "input": "&yscr",
+ "description": "Bad named entity: yscr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&yscr"
+ ]
+ ]
+ },
+ {
+ "input": "&yscr;",
+ "description": "Named entity: yscr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udcce"
+ ]
+ ]
+ },
+ {
+ "input": "&yucy",
+ "description": "Bad named entity: yucy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&yucy"
+ ]
+ ]
+ },
+ {
+ "input": "&yucy;",
+ "description": "Named entity: yucy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u044e"
+ ]
+ ]
+ },
+ {
+ "input": "&yuml",
+ "description": "Named entity: yuml without a semi-colon",
+ "output": [
+ "ParseError",
+ [
+ "Character",
+ "\u00ff"
+ ]
+ ]
+ },
+ {
+ "input": "&yuml;",
+ "description": "Named entity: yuml; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u00ff"
+ ]
+ ]
+ },
+ {
+ "input": "&zacute",
+ "description": "Bad named entity: zacute without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&zacute"
+ ]
+ ]
+ },
+ {
+ "input": "&zacute;",
+ "description": "Named entity: zacute; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u017a"
+ ]
+ ]
+ },
+ {
+ "input": "&zcaron",
+ "description": "Bad named entity: zcaron without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&zcaron"
+ ]
+ ]
+ },
+ {
+ "input": "&zcaron;",
+ "description": "Named entity: zcaron; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u017e"
+ ]
+ ]
+ },
+ {
+ "input": "&zcy",
+ "description": "Bad named entity: zcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&zcy"
+ ]
+ ]
+ },
+ {
+ "input": "&zcy;",
+ "description": "Named entity: zcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0437"
+ ]
+ ]
+ },
+ {
+ "input": "&zdot",
+ "description": "Bad named entity: zdot without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&zdot"
+ ]
+ ]
+ },
+ {
+ "input": "&zdot;",
+ "description": "Named entity: zdot; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u017c"
+ ]
+ ]
+ },
+ {
+ "input": "&zeetrf",
+ "description": "Bad named entity: zeetrf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&zeetrf"
+ ]
+ ]
+ },
+ {
+ "input": "&zeetrf;",
+ "description": "Named entity: zeetrf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u2128"
+ ]
+ ]
+ },
+ {
+ "input": "&zeta",
+ "description": "Bad named entity: zeta without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&zeta"
+ ]
+ ]
+ },
+ {
+ "input": "&zeta;",
+ "description": "Named entity: zeta; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u03b6"
+ ]
+ ]
+ },
+ {
+ "input": "&zfr",
+ "description": "Bad named entity: zfr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&zfr"
+ ]
+ ]
+ },
+ {
+ "input": "&zfr;",
+ "description": "Named entity: zfr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd37"
+ ]
+ ]
+ },
+ {
+ "input": "&zhcy",
+ "description": "Bad named entity: zhcy without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&zhcy"
+ ]
+ ]
+ },
+ {
+ "input": "&zhcy;",
+ "description": "Named entity: zhcy; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u0436"
+ ]
+ ]
+ },
+ {
+ "input": "&zigrarr",
+ "description": "Bad named entity: zigrarr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&zigrarr"
+ ]
+ ]
+ },
+ {
+ "input": "&zigrarr;",
+ "description": "Named entity: zigrarr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u21dd"
+ ]
+ ]
+ },
+ {
+ "input": "&zopf",
+ "description": "Bad named entity: zopf without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&zopf"
+ ]
+ ]
+ },
+ {
+ "input": "&zopf;",
+ "description": "Named entity: zopf; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udd6b"
+ ]
+ ]
+ },
+ {
+ "input": "&zscr",
+ "description": "Bad named entity: zscr without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&zscr"
+ ]
+ ]
+ },
+ {
+ "input": "&zscr;",
+ "description": "Named entity: zscr; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\ud835\udccf"
+ ]
+ ]
+ },
+ {
+ "input": "&zwj",
+ "description": "Bad named entity: zwj without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&zwj"
+ ]
+ ]
+ },
+ {
+ "input": "&zwj;",
+ "description": "Named entity: zwj; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u200d"
+ ]
+ ]
+ },
+ {
+ "input": "&zwnj",
+ "description": "Bad named entity: zwnj without a semi-colon",
+ "output": [
+ [
+ "Character",
+ "&zwnj"
+ ]
+ ]
+ },
+ {
+ "input": "&zwnj;",
+ "description": "Named entity: zwnj; with a semi-colon",
+ "output": [
+ [
+ "Character",
+ "\u200c"
+ ]
+ ]
+ }
+ ]
+} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/numericEntities.test b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/numericEntities.test
new file mode 100644
index 00000000000..36c82281cd9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/numericEntities.test
@@ -0,0 +1,1313 @@
+{"tests": [
+
+{"description": "Invalid numeric entity character U+0000",
+"input": "&#x0000;",
+"output": ["ParseError", ["Character", "\uFFFD"]]},
+
+{"description": "Invalid numeric entity character U+0001",
+"input": "&#x0001;",
+"output": ["ParseError", ["Character", "\u0001"]]},
+
+{"description": "Invalid numeric entity character U+0002",
+"input": "&#x0002;",
+"output": ["ParseError", ["Character", "\u0002"]]},
+
+{"description": "Invalid numeric entity character U+0003",
+"input": "&#x0003;",
+"output": ["ParseError", ["Character", "\u0003"]]},
+
+{"description": "Invalid numeric entity character U+0004",
+"input": "&#x0004;",
+"output": ["ParseError", ["Character", "\u0004"]]},
+
+{"description": "Invalid numeric entity character U+0005",
+"input": "&#x0005;",
+"output": ["ParseError", ["Character", "\u0005"]]},
+
+{"description": "Invalid numeric entity character U+0006",
+"input": "&#x0006;",
+"output": ["ParseError", ["Character", "\u0006"]]},
+
+{"description": "Invalid numeric entity character U+0007",
+"input": "&#x0007;",
+"output": ["ParseError", ["Character", "\u0007"]]},
+
+{"description": "Invalid numeric entity character U+0008",
+"input": "&#x0008;",
+"output": ["ParseError", ["Character", "\u0008"]]},
+
+{"description": "Invalid numeric entity character U+000B",
+"input": "&#x000b;",
+"output": ["ParseError", ["Character", "\u000b"]]},
+
+{"description": "Invalid numeric entity character U+000E",
+"input": "&#x000e;",
+"output": ["ParseError", ["Character", "\u000e"]]},
+
+{"description": "Invalid numeric entity character U+000F",
+"input": "&#x000f;",
+"output": ["ParseError", ["Character", "\u000f"]]},
+
+{"description": "Invalid numeric entity character U+0010",
+"input": "&#x0010;",
+"output": ["ParseError", ["Character", "\u0010"]]},
+
+{"description": "Invalid numeric entity character U+0011",
+"input": "&#x0011;",
+"output": ["ParseError", ["Character", "\u0011"]]},
+
+{"description": "Invalid numeric entity character U+0012",
+"input": "&#x0012;",
+"output": ["ParseError", ["Character", "\u0012"]]},
+
+{"description": "Invalid numeric entity character U+0013",
+"input": "&#x0013;",
+"output": ["ParseError", ["Character", "\u0013"]]},
+
+{"description": "Invalid numeric entity character U+0014",
+"input": "&#x0014;",
+"output": ["ParseError", ["Character", "\u0014"]]},
+
+{"description": "Invalid numeric entity character U+0015",
+"input": "&#x0015;",
+"output": ["ParseError", ["Character", "\u0015"]]},
+
+{"description": "Invalid numeric entity character U+0016",
+"input": "&#x0016;",
+"output": ["ParseError", ["Character", "\u0016"]]},
+
+{"description": "Invalid numeric entity character U+0017",
+"input": "&#x0017;",
+"output": ["ParseError", ["Character", "\u0017"]]},
+
+{"description": "Invalid numeric entity character U+0018",
+"input": "&#x0018;",
+"output": ["ParseError", ["Character", "\u0018"]]},
+
+{"description": "Invalid numeric entity character U+0019",
+"input": "&#x0019;",
+"output": ["ParseError", ["Character", "\u0019"]]},
+
+{"description": "Invalid numeric entity character U+001A",
+"input": "&#x001a;",
+"output": ["ParseError", ["Character", "\u001a"]]},
+
+{"description": "Invalid numeric entity character U+001B",
+"input": "&#x001b;",
+"output": ["ParseError", ["Character", "\u001b"]]},
+
+{"description": "Invalid numeric entity character U+001C",
+"input": "&#x001c;",
+"output": ["ParseError", ["Character", "\u001c"]]},
+
+{"description": "Invalid numeric entity character U+001D",
+"input": "&#x001d;",
+"output": ["ParseError", ["Character", "\u001d"]]},
+
+{"description": "Invalid numeric entity character U+001E",
+"input": "&#x001e;",
+"output": ["ParseError", ["Character", "\u001e"]]},
+
+{"description": "Invalid numeric entity character U+001F",
+"input": "&#x001f;",
+"output": ["ParseError", ["Character", "\u001f"]]},
+
+{"description": "Invalid numeric entity character U+007F",
+"input": "&#x007f;",
+"output": ["ParseError", ["Character", "\u007f"]]},
+
+{"description": "Invalid numeric entity character U+D800",
+"input": "&#xd800;",
+"output": ["ParseError", ["Character", "\uFFFD"]]},
+
+{"description": "Invalid numeric entity character U+DFFF",
+"input": "&#xdfff;",
+"output": ["ParseError", ["Character", "\uFFFD"]]},
+
+{"description": "Invalid numeric entity character U+FDD0",
+"input": "&#xfdd0;",
+"output": ["ParseError", ["Character", "\ufdd0"]]},
+
+{"description": "Invalid numeric entity character U+FDD1",
+"input": "&#xfdd1;",
+"output": ["ParseError", ["Character", "\ufdd1"]]},
+
+{"description": "Invalid numeric entity character U+FDD2",
+"input": "&#xfdd2;",
+"output": ["ParseError", ["Character", "\ufdd2"]]},
+
+{"description": "Invalid numeric entity character U+FDD3",
+"input": "&#xfdd3;",
+"output": ["ParseError", ["Character", "\ufdd3"]]},
+
+{"description": "Invalid numeric entity character U+FDD4",
+"input": "&#xfdd4;",
+"output": ["ParseError", ["Character", "\ufdd4"]]},
+
+{"description": "Invalid numeric entity character U+FDD5",
+"input": "&#xfdd5;",
+"output": ["ParseError", ["Character", "\ufdd5"]]},
+
+{"description": "Invalid numeric entity character U+FDD6",
+"input": "&#xfdd6;",
+"output": ["ParseError", ["Character", "\ufdd6"]]},
+
+{"description": "Invalid numeric entity character U+FDD7",
+"input": "&#xfdd7;",
+"output": ["ParseError", ["Character", "\ufdd7"]]},
+
+{"description": "Invalid numeric entity character U+FDD8",
+"input": "&#xfdd8;",
+"output": ["ParseError", ["Character", "\ufdd8"]]},
+
+{"description": "Invalid numeric entity character U+FDD9",
+"input": "&#xfdd9;",
+"output": ["ParseError", ["Character", "\ufdd9"]]},
+
+{"description": "Invalid numeric entity character U+FDDA",
+"input": "&#xfdda;",
+"output": ["ParseError", ["Character", "\ufdda"]]},
+
+{"description": "Invalid numeric entity character U+FDDB",
+"input": "&#xfddb;",
+"output": ["ParseError", ["Character", "\ufddb"]]},
+
+{"description": "Invalid numeric entity character U+FDDC",
+"input": "&#xfddc;",
+"output": ["ParseError", ["Character", "\ufddc"]]},
+
+{"description": "Invalid numeric entity character U+FDDD",
+"input": "&#xfddd;",
+"output": ["ParseError", ["Character", "\ufddd"]]},
+
+{"description": "Invalid numeric entity character U+FDDE",
+"input": "&#xfdde;",
+"output": ["ParseError", ["Character", "\ufdde"]]},
+
+{"description": "Invalid numeric entity character U+FDDF",
+"input": "&#xfddf;",
+"output": ["ParseError", ["Character", "\ufddf"]]},
+
+{"description": "Invalid numeric entity character U+FDE0",
+"input": "&#xfde0;",
+"output": ["ParseError", ["Character", "\ufde0"]]},
+
+{"description": "Invalid numeric entity character U+FDE1",
+"input": "&#xfde1;",
+"output": ["ParseError", ["Character", "\ufde1"]]},
+
+{"description": "Invalid numeric entity character U+FDE2",
+"input": "&#xfde2;",
+"output": ["ParseError", ["Character", "\ufde2"]]},
+
+{"description": "Invalid numeric entity character U+FDE3",
+"input": "&#xfde3;",
+"output": ["ParseError", ["Character", "\ufde3"]]},
+
+{"description": "Invalid numeric entity character U+FDE4",
+"input": "&#xfde4;",
+"output": ["ParseError", ["Character", "\ufde4"]]},
+
+{"description": "Invalid numeric entity character U+FDE5",
+"input": "&#xfde5;",
+"output": ["ParseError", ["Character", "\ufde5"]]},
+
+{"description": "Invalid numeric entity character U+FDE6",
+"input": "&#xfde6;",
+"output": ["ParseError", ["Character", "\ufde6"]]},
+
+{"description": "Invalid numeric entity character U+FDE7",
+"input": "&#xfde7;",
+"output": ["ParseError", ["Character", "\ufde7"]]},
+
+{"description": "Invalid numeric entity character U+FDE8",
+"input": "&#xfde8;",
+"output": ["ParseError", ["Character", "\ufde8"]]},
+
+{"description": "Invalid numeric entity character U+FDE9",
+"input": "&#xfde9;",
+"output": ["ParseError", ["Character", "\ufde9"]]},
+
+{"description": "Invalid numeric entity character U+FDEA",
+"input": "&#xfdea;",
+"output": ["ParseError", ["Character", "\ufdea"]]},
+
+{"description": "Invalid numeric entity character U+FDEB",
+"input": "&#xfdeb;",
+"output": ["ParseError", ["Character", "\ufdeb"]]},
+
+{"description": "Invalid numeric entity character U+FDEC",
+"input": "&#xfdec;",
+"output": ["ParseError", ["Character", "\ufdec"]]},
+
+{"description": "Invalid numeric entity character U+FDED",
+"input": "&#xfded;",
+"output": ["ParseError", ["Character", "\ufded"]]},
+
+{"description": "Invalid numeric entity character U+FDEE",
+"input": "&#xfdee;",
+"output": ["ParseError", ["Character", "\ufdee"]]},
+
+{"description": "Invalid numeric entity character U+FDEF",
+"input": "&#xfdef;",
+"output": ["ParseError", ["Character", "\ufdef"]]},
+
+{"description": "Invalid numeric entity character U+FFFE",
+"input": "&#xfffe;",
+"output": ["ParseError", ["Character", "\ufffe"]]},
+
+{"description": "Invalid numeric entity character U+FFFF",
+"input": "&#xffff;",
+"output": ["ParseError", ["Character", "\uffff"]]},
+
+{"description": "Invalid numeric entity character U+1FFFE",
+"input": "&#x1fffe;",
+"output": ["ParseError", ["Character", "\uD83F\uDFFE"]]},
+
+{"description": "Invalid numeric entity character U+1FFFF",
+"input": "&#x1ffff;",
+"output": ["ParseError", ["Character", "\uD83F\uDFFF"]]},
+
+{"description": "Invalid numeric entity character U+2FFFE",
+"input": "&#x2fffe;",
+"output": ["ParseError", ["Character", "\uD87F\uDFFE"]]},
+
+{"description": "Invalid numeric entity character U+2FFFF",
+"input": "&#x2ffff;",
+"output": ["ParseError", ["Character", "\uD87F\uDFFF"]]},
+
+{"description": "Invalid numeric entity character U+3FFFE",
+"input": "&#x3fffe;",
+"output": ["ParseError", ["Character", "\uD8BF\uDFFE"]]},
+
+{"description": "Invalid numeric entity character U+3FFFF",
+"input": "&#x3ffff;",
+"output": ["ParseError", ["Character", "\uD8BF\uDFFF"]]},
+
+{"description": "Invalid numeric entity character U+4FFFE",
+"input": "&#x4fffe;",
+"output": ["ParseError", ["Character", "\uD8FF\uDFFE"]]},
+
+{"description": "Invalid numeric entity character U+4FFFF",
+"input": "&#x4ffff;",
+"output": ["ParseError", ["Character", "\uD8FF\uDFFF"]]},
+
+{"description": "Invalid numeric entity character U+5FFFE",
+"input": "&#x5fffe;",
+"output": ["ParseError", ["Character", "\uD93F\uDFFE"]]},
+
+{"description": "Invalid numeric entity character U+5FFFF",
+"input": "&#x5ffff;",
+"output": ["ParseError", ["Character", "\uD93F\uDFFF"]]},
+
+{"description": "Invalid numeric entity character U+6FFFE",
+"input": "&#x6fffe;",
+"output": ["ParseError", ["Character", "\uD97F\uDFFE"]]},
+
+{"description": "Invalid numeric entity character U+6FFFF",
+"input": "&#x6ffff;",
+"output": ["ParseError", ["Character", "\uD97F\uDFFF"]]},
+
+{"description": "Invalid numeric entity character U+7FFFE",
+"input": "&#x7fffe;",
+"output": ["ParseError", ["Character", "\uD9BF\uDFFE"]]},
+
+{"description": "Invalid numeric entity character U+7FFFF",
+"input": "&#x7ffff;",
+"output": ["ParseError", ["Character", "\uD9BF\uDFFF"]]},
+
+{"description": "Invalid numeric entity character U+8FFFE",
+"input": "&#x8fffe;",
+"output": ["ParseError", ["Character", "\uD9FF\uDFFE"]]},
+
+{"description": "Invalid numeric entity character U+8FFFF",
+"input": "&#x8ffff;",
+"output": ["ParseError", ["Character", "\uD9FF\uDFFF"]]},
+
+{"description": "Invalid numeric entity character U+9FFFE",
+"input": "&#x9fffe;",
+"output": ["ParseError", ["Character", "\uDA3F\uDFFE"]]},
+
+{"description": "Invalid numeric entity character U+9FFFF",
+"input": "&#x9ffff;",
+"output": ["ParseError", ["Character", "\uDA3F\uDFFF"]]},
+
+{"description": "Invalid numeric entity character U+AFFFE",
+"input": "&#xafffe;",
+"output": ["ParseError", ["Character", "\uDA7F\uDFFE"]]},
+
+{"description": "Invalid numeric entity character U+AFFFF",
+"input": "&#xaffff;",
+"output": ["ParseError", ["Character", "\uDA7F\uDFFF"]]},
+
+{"description": "Invalid numeric entity character U+BFFFE",
+"input": "&#xbfffe;",
+"output": ["ParseError", ["Character", "\uDABF\uDFFE"]]},
+
+{"description": "Invalid numeric entity character U+BFFFF",
+"input": "&#xbffff;",
+"output": ["ParseError", ["Character", "\uDABF\uDFFF"]]},
+
+{"description": "Invalid numeric entity character U+CFFFE",
+"input": "&#xcfffe;",
+"output": ["ParseError", ["Character", "\uDAFF\uDFFE"]]},
+
+{"description": "Invalid numeric entity character U+CFFFF",
+"input": "&#xcffff;",
+"output": ["ParseError", ["Character", "\uDAFF\uDFFF"]]},
+
+{"description": "Invalid numeric entity character U+DFFFE",
+"input": "&#xdfffe;",
+"output": ["ParseError", ["Character", "\uDB3F\uDFFE"]]},
+
+{"description": "Invalid numeric entity character U+DFFFF",
+"input": "&#xdffff;",
+"output": ["ParseError", ["Character", "\uDB3F\uDFFF"]]},
+
+{"description": "Invalid numeric entity character U+EFFFE",
+"input": "&#xefffe;",
+"output": ["ParseError", ["Character", "\uDB7F\uDFFE"]]},
+
+{"description": "Invalid numeric entity character U+EFFFF",
+"input": "&#xeffff;",
+"output": ["ParseError", ["Character", "\uDB7F\uDFFF"]]},
+
+{"description": "Invalid numeric entity character U+FFFFE",
+"input": "&#xffffe;",
+"output": ["ParseError", ["Character", "\uDBBF\uDFFE"]]},
+
+{"description": "Invalid numeric entity character U+FFFFF",
+"input": "&#xfffff;",
+"output": ["ParseError", ["Character", "\uDBBF\uDFFF"]]},
+
+{"description": "Invalid numeric entity character U+10FFFE",
+"input": "&#x10fffe;",
+"output": ["ParseError", ["Character", "\uDBFF\uDFFE"]]},
+
+{"description": "Invalid numeric entity character U+10FFFF",
+"input": "&#x10ffff;",
+"output": ["ParseError", ["Character", "\uDBFF\uDFFF"]]},
+
+{"description": "Valid numeric entity character U+0009",
+"input": "&#x0009;",
+"output": [["Character", "\u0009"]]},
+
+{"description": "Valid numeric entity character U+000A",
+"input": "&#x000a;",
+"output": [["Character", "\u000A"]]},
+
+{"description": "Valid numeric entity character U+0020",
+"input": "&#x0020;",
+"output": [["Character", "\u0020"]]},
+
+{"description": "Valid numeric entity character U+0021",
+"input": "&#x0021;",
+"output": [["Character", "\u0021"]]},
+
+{"description": "Valid numeric entity character U+0022",
+"input": "&#x0022;",
+"output": [["Character", "\u0022"]]},
+
+{"description": "Valid numeric entity character U+0023",
+"input": "&#x0023;",
+"output": [["Character", "\u0023"]]},
+
+{"description": "Valid numeric entity character U+0024",
+"input": "&#x0024;",
+"output": [["Character", "\u0024"]]},
+
+{"description": "Valid numeric entity character U+0025",
+"input": "&#x0025;",
+"output": [["Character", "\u0025"]]},
+
+{"description": "Valid numeric entity character U+0026",
+"input": "&#x0026;",
+"output": [["Character", "\u0026"]]},
+
+{"description": "Valid numeric entity character U+0027",
+"input": "&#x0027;",
+"output": [["Character", "\u0027"]]},
+
+{"description": "Valid numeric entity character U+0028",
+"input": "&#x0028;",
+"output": [["Character", "\u0028"]]},
+
+{"description": "Valid numeric entity character U+0029",
+"input": "&#x0029;",
+"output": [["Character", "\u0029"]]},
+
+{"description": "Valid numeric entity character U+002A",
+"input": "&#x002a;",
+"output": [["Character", "\u002A"]]},
+
+{"description": "Valid numeric entity character U+002B",
+"input": "&#x002b;",
+"output": [["Character", "\u002B"]]},
+
+{"description": "Valid numeric entity character U+002C",
+"input": "&#x002c;",
+"output": [["Character", "\u002C"]]},
+
+{"description": "Valid numeric entity character U+002D",
+"input": "&#x002d;",
+"output": [["Character", "\u002D"]]},
+
+{"description": "Valid numeric entity character U+002E",
+"input": "&#x002e;",
+"output": [["Character", "\u002E"]]},
+
+{"description": "Valid numeric entity character U+002F",
+"input": "&#x002f;",
+"output": [["Character", "\u002F"]]},
+
+{"description": "Valid numeric entity character U+0030",
+"input": "&#x0030;",
+"output": [["Character", "\u0030"]]},
+
+{"description": "Valid numeric entity character U+0031",
+"input": "&#x0031;",
+"output": [["Character", "\u0031"]]},
+
+{"description": "Valid numeric entity character U+0032",
+"input": "&#x0032;",
+"output": [["Character", "\u0032"]]},
+
+{"description": "Valid numeric entity character U+0033",
+"input": "&#x0033;",
+"output": [["Character", "\u0033"]]},
+
+{"description": "Valid numeric entity character U+0034",
+"input": "&#x0034;",
+"output": [["Character", "\u0034"]]},
+
+{"description": "Valid numeric entity character U+0035",
+"input": "&#x0035;",
+"output": [["Character", "\u0035"]]},
+
+{"description": "Valid numeric entity character U+0036",
+"input": "&#x0036;",
+"output": [["Character", "\u0036"]]},
+
+{"description": "Valid numeric entity character U+0037",
+"input": "&#x0037;",
+"output": [["Character", "\u0037"]]},
+
+{"description": "Valid numeric entity character U+0038",
+"input": "&#x0038;",
+"output": [["Character", "\u0038"]]},
+
+{"description": "Valid numeric entity character U+0039",
+"input": "&#x0039;",
+"output": [["Character", "\u0039"]]},
+
+{"description": "Valid numeric entity character U+003A",
+"input": "&#x003a;",
+"output": [["Character", "\u003A"]]},
+
+{"description": "Valid numeric entity character U+003B",
+"input": "&#x003b;",
+"output": [["Character", "\u003B"]]},
+
+{"description": "Valid numeric entity character U+003C",
+"input": "&#x003c;",
+"output": [["Character", "\u003C"]]},
+
+{"description": "Valid numeric entity character U+003D",
+"input": "&#x003d;",
+"output": [["Character", "\u003D"]]},
+
+{"description": "Valid numeric entity character U+003E",
+"input": "&#x003e;",
+"output": [["Character", "\u003E"]]},
+
+{"description": "Valid numeric entity character U+003F",
+"input": "&#x003f;",
+"output": [["Character", "\u003F"]]},
+
+{"description": "Valid numeric entity character U+0040",
+"input": "&#x0040;",
+"output": [["Character", "\u0040"]]},
+
+{"description": "Valid numeric entity character U+0041",
+"input": "&#x0041;",
+"output": [["Character", "\u0041"]]},
+
+{"description": "Valid numeric entity character U+0042",
+"input": "&#x0042;",
+"output": [["Character", "\u0042"]]},
+
+{"description": "Valid numeric entity character U+0043",
+"input": "&#x0043;",
+"output": [["Character", "\u0043"]]},
+
+{"description": "Valid numeric entity character U+0044",
+"input": "&#x0044;",
+"output": [["Character", "\u0044"]]},
+
+{"description": "Valid numeric entity character U+0045",
+"input": "&#x0045;",
+"output": [["Character", "\u0045"]]},
+
+{"description": "Valid numeric entity character U+0046",
+"input": "&#x0046;",
+"output": [["Character", "\u0046"]]},
+
+{"description": "Valid numeric entity character U+0047",
+"input": "&#x0047;",
+"output": [["Character", "\u0047"]]},
+
+{"description": "Valid numeric entity character U+0048",
+"input": "&#x0048;",
+"output": [["Character", "\u0048"]]},
+
+{"description": "Valid numeric entity character U+0049",
+"input": "&#x0049;",
+"output": [["Character", "\u0049"]]},
+
+{"description": "Valid numeric entity character U+004A",
+"input": "&#x004a;",
+"output": [["Character", "\u004A"]]},
+
+{"description": "Valid numeric entity character U+004B",
+"input": "&#x004b;",
+"output": [["Character", "\u004B"]]},
+
+{"description": "Valid numeric entity character U+004C",
+"input": "&#x004c;",
+"output": [["Character", "\u004C"]]},
+
+{"description": "Valid numeric entity character U+004D",
+"input": "&#x004d;",
+"output": [["Character", "\u004D"]]},
+
+{"description": "Valid numeric entity character U+004E",
+"input": "&#x004e;",
+"output": [["Character", "\u004E"]]},
+
+{"description": "Valid numeric entity character U+004F",
+"input": "&#x004f;",
+"output": [["Character", "\u004F"]]},
+
+{"description": "Valid numeric entity character U+0050",
+"input": "&#x0050;",
+"output": [["Character", "\u0050"]]},
+
+{"description": "Valid numeric entity character U+0051",
+"input": "&#x0051;",
+"output": [["Character", "\u0051"]]},
+
+{"description": "Valid numeric entity character U+0052",
+"input": "&#x0052;",
+"output": [["Character", "\u0052"]]},
+
+{"description": "Valid numeric entity character U+0053",
+"input": "&#x0053;",
+"output": [["Character", "\u0053"]]},
+
+{"description": "Valid numeric entity character U+0054",
+"input": "&#x0054;",
+"output": [["Character", "\u0054"]]},
+
+{"description": "Valid numeric entity character U+0055",
+"input": "&#x0055;",
+"output": [["Character", "\u0055"]]},
+
+{"description": "Valid numeric entity character U+0056",
+"input": "&#x0056;",
+"output": [["Character", "\u0056"]]},
+
+{"description": "Valid numeric entity character U+0057",
+"input": "&#x0057;",
+"output": [["Character", "\u0057"]]},
+
+{"description": "Valid numeric entity character U+0058",
+"input": "&#x0058;",
+"output": [["Character", "\u0058"]]},
+
+{"description": "Valid numeric entity character U+0059",
+"input": "&#x0059;",
+"output": [["Character", "\u0059"]]},
+
+{"description": "Valid numeric entity character U+005A",
+"input": "&#x005a;",
+"output": [["Character", "\u005A"]]},
+
+{"description": "Valid numeric entity character U+005B",
+"input": "&#x005b;",
+"output": [["Character", "\u005B"]]},
+
+{"description": "Valid numeric entity character U+005C",
+"input": "&#x005c;",
+"output": [["Character", "\u005C"]]},
+
+{"description": "Valid numeric entity character U+005D",
+"input": "&#x005d;",
+"output": [["Character", "\u005D"]]},
+
+{"description": "Valid numeric entity character U+005E",
+"input": "&#x005e;",
+"output": [["Character", "\u005E"]]},
+
+{"description": "Valid numeric entity character U+005F",
+"input": "&#x005f;",
+"output": [["Character", "\u005F"]]},
+
+{"description": "Valid numeric entity character U+0060",
+"input": "&#x0060;",
+"output": [["Character", "\u0060"]]},
+
+{"description": "Valid numeric entity character U+0061",
+"input": "&#x0061;",
+"output": [["Character", "\u0061"]]},
+
+{"description": "Valid numeric entity character U+0062",
+"input": "&#x0062;",
+"output": [["Character", "\u0062"]]},
+
+{"description": "Valid numeric entity character U+0063",
+"input": "&#x0063;",
+"output": [["Character", "\u0063"]]},
+
+{"description": "Valid numeric entity character U+0064",
+"input": "&#x0064;",
+"output": [["Character", "\u0064"]]},
+
+{"description": "Valid numeric entity character U+0065",
+"input": "&#x0065;",
+"output": [["Character", "\u0065"]]},
+
+{"description": "Valid numeric entity character U+0066",
+"input": "&#x0066;",
+"output": [["Character", "\u0066"]]},
+
+{"description": "Valid numeric entity character U+0067",
+"input": "&#x0067;",
+"output": [["Character", "\u0067"]]},
+
+{"description": "Valid numeric entity character U+0068",
+"input": "&#x0068;",
+"output": [["Character", "\u0068"]]},
+
+{"description": "Valid numeric entity character U+0069",
+"input": "&#x0069;",
+"output": [["Character", "\u0069"]]},
+
+{"description": "Valid numeric entity character U+006A",
+"input": "&#x006a;",
+"output": [["Character", "\u006A"]]},
+
+{"description": "Valid numeric entity character U+006B",
+"input": "&#x006b;",
+"output": [["Character", "\u006B"]]},
+
+{"description": "Valid numeric entity character U+006C",
+"input": "&#x006c;",
+"output": [["Character", "\u006C"]]},
+
+{"description": "Valid numeric entity character U+006D",
+"input": "&#x006d;",
+"output": [["Character", "\u006D"]]},
+
+{"description": "Valid numeric entity character U+006E",
+"input": "&#x006e;",
+"output": [["Character", "\u006E"]]},
+
+{"description": "Valid numeric entity character U+006F",
+"input": "&#x006f;",
+"output": [["Character", "\u006F"]]},
+
+{"description": "Valid numeric entity character U+0070",
+"input": "&#x0070;",
+"output": [["Character", "\u0070"]]},
+
+{"description": "Valid numeric entity character U+0071",
+"input": "&#x0071;",
+"output": [["Character", "\u0071"]]},
+
+{"description": "Valid numeric entity character U+0072",
+"input": "&#x0072;",
+"output": [["Character", "\u0072"]]},
+
+{"description": "Valid numeric entity character U+0073",
+"input": "&#x0073;",
+"output": [["Character", "\u0073"]]},
+
+{"description": "Valid numeric entity character U+0074",
+"input": "&#x0074;",
+"output": [["Character", "\u0074"]]},
+
+{"description": "Valid numeric entity character U+0075",
+"input": "&#x0075;",
+"output": [["Character", "\u0075"]]},
+
+{"description": "Valid numeric entity character U+0076",
+"input": "&#x0076;",
+"output": [["Character", "\u0076"]]},
+
+{"description": "Valid numeric entity character U+0077",
+"input": "&#x0077;",
+"output": [["Character", "\u0077"]]},
+
+{"description": "Valid numeric entity character U+0078",
+"input": "&#x0078;",
+"output": [["Character", "\u0078"]]},
+
+{"description": "Valid numeric entity character U+0079",
+"input": "&#x0079;",
+"output": [["Character", "\u0079"]]},
+
+{"description": "Valid numeric entity character U+007A",
+"input": "&#x007a;",
+"output": [["Character", "\u007A"]]},
+
+{"description": "Valid numeric entity character U+007B",
+"input": "&#x007b;",
+"output": [["Character", "\u007B"]]},
+
+{"description": "Valid numeric entity character U+007C",
+"input": "&#x007c;",
+"output": [["Character", "\u007C"]]},
+
+{"description": "Valid numeric entity character U+007D",
+"input": "&#x007d;",
+"output": [["Character", "\u007D"]]},
+
+{"description": "Valid numeric entity character U+007E",
+"input": "&#x007e;",
+"output": [["Character", "\u007E"]]},
+
+{"description": "Valid numeric entity character U+00A0",
+"input": "&#x00a0;",
+"output": [["Character", "\u00A0"]]},
+
+{"description": "Valid numeric entity character U+00A1",
+"input": "&#x00a1;",
+"output": [["Character", "\u00A1"]]},
+
+{"description": "Valid numeric entity character U+00A2",
+"input": "&#x00a2;",
+"output": [["Character", "\u00A2"]]},
+
+{"description": "Valid numeric entity character U+00A3",
+"input": "&#x00a3;",
+"output": [["Character", "\u00A3"]]},
+
+{"description": "Valid numeric entity character U+00A4",
+"input": "&#x00a4;",
+"output": [["Character", "\u00A4"]]},
+
+{"description": "Valid numeric entity character U+00A5",
+"input": "&#x00a5;",
+"output": [["Character", "\u00A5"]]},
+
+{"description": "Valid numeric entity character U+00A6",
+"input": "&#x00a6;",
+"output": [["Character", "\u00A6"]]},
+
+{"description": "Valid numeric entity character U+00A7",
+"input": "&#x00a7;",
+"output": [["Character", "\u00A7"]]},
+
+{"description": "Valid numeric entity character U+00A8",
+"input": "&#x00a8;",
+"output": [["Character", "\u00A8"]]},
+
+{"description": "Valid numeric entity character U+00A9",
+"input": "&#x00a9;",
+"output": [["Character", "\u00A9"]]},
+
+{"description": "Valid numeric entity character U+00AA",
+"input": "&#x00aa;",
+"output": [["Character", "\u00AA"]]},
+
+{"description": "Valid numeric entity character U+00AB",
+"input": "&#x00ab;",
+"output": [["Character", "\u00AB"]]},
+
+{"description": "Valid numeric entity character U+00AC",
+"input": "&#x00ac;",
+"output": [["Character", "\u00AC"]]},
+
+{"description": "Valid numeric entity character U+00AD",
+"input": "&#x00ad;",
+"output": [["Character", "\u00AD"]]},
+
+{"description": "Valid numeric entity character U+00AE",
+"input": "&#x00ae;",
+"output": [["Character", "\u00AE"]]},
+
+{"description": "Valid numeric entity character U+00AF",
+"input": "&#x00af;",
+"output": [["Character", "\u00AF"]]},
+
+{"description": "Valid numeric entity character U+00B0",
+"input": "&#x00b0;",
+"output": [["Character", "\u00B0"]]},
+
+{"description": "Valid numeric entity character U+00B1",
+"input": "&#x00b1;",
+"output": [["Character", "\u00B1"]]},
+
+{"description": "Valid numeric entity character U+00B2",
+"input": "&#x00b2;",
+"output": [["Character", "\u00B2"]]},
+
+{"description": "Valid numeric entity character U+00B3",
+"input": "&#x00b3;",
+"output": [["Character", "\u00B3"]]},
+
+{"description": "Valid numeric entity character U+00B4",
+"input": "&#x00b4;",
+"output": [["Character", "\u00B4"]]},
+
+{"description": "Valid numeric entity character U+00B5",
+"input": "&#x00b5;",
+"output": [["Character", "\u00B5"]]},
+
+{"description": "Valid numeric entity character U+00B6",
+"input": "&#x00b6;",
+"output": [["Character", "\u00B6"]]},
+
+{"description": "Valid numeric entity character U+00B7",
+"input": "&#x00b7;",
+"output": [["Character", "\u00B7"]]},
+
+{"description": "Valid numeric entity character U+00B8",
+"input": "&#x00b8;",
+"output": [["Character", "\u00B8"]]},
+
+{"description": "Valid numeric entity character U+00B9",
+"input": "&#x00b9;",
+"output": [["Character", "\u00B9"]]},
+
+{"description": "Valid numeric entity character U+00BA",
+"input": "&#x00ba;",
+"output": [["Character", "\u00BA"]]},
+
+{"description": "Valid numeric entity character U+00BB",
+"input": "&#x00bb;",
+"output": [["Character", "\u00BB"]]},
+
+{"description": "Valid numeric entity character U+00BC",
+"input": "&#x00bc;",
+"output": [["Character", "\u00BC"]]},
+
+{"description": "Valid numeric entity character U+00BD",
+"input": "&#x00bd;",
+"output": [["Character", "\u00BD"]]},
+
+{"description": "Valid numeric entity character U+00BE",
+"input": "&#x00be;",
+"output": [["Character", "\u00BE"]]},
+
+{"description": "Valid numeric entity character U+00BF",
+"input": "&#x00bf;",
+"output": [["Character", "\u00BF"]]},
+
+{"description": "Valid numeric entity character U+00C0",
+"input": "&#x00c0;",
+"output": [["Character", "\u00C0"]]},
+
+{"description": "Valid numeric entity character U+00C1",
+"input": "&#x00c1;",
+"output": [["Character", "\u00C1"]]},
+
+{"description": "Valid numeric entity character U+00C2",
+"input": "&#x00c2;",
+"output": [["Character", "\u00C2"]]},
+
+{"description": "Valid numeric entity character U+00C3",
+"input": "&#x00c3;",
+"output": [["Character", "\u00C3"]]},
+
+{"description": "Valid numeric entity character U+00C4",
+"input": "&#x00c4;",
+"output": [["Character", "\u00C4"]]},
+
+{"description": "Valid numeric entity character U+00C5",
+"input": "&#x00c5;",
+"output": [["Character", "\u00C5"]]},
+
+{"description": "Valid numeric entity character U+00C6",
+"input": "&#x00c6;",
+"output": [["Character", "\u00C6"]]},
+
+{"description": "Valid numeric entity character U+00C7",
+"input": "&#x00c7;",
+"output": [["Character", "\u00C7"]]},
+
+{"description": "Valid numeric entity character U+00C8",
+"input": "&#x00c8;",
+"output": [["Character", "\u00C8"]]},
+
+{"description": "Valid numeric entity character U+00C9",
+"input": "&#x00c9;",
+"output": [["Character", "\u00C9"]]},
+
+{"description": "Valid numeric entity character U+00CA",
+"input": "&#x00ca;",
+"output": [["Character", "\u00CA"]]},
+
+{"description": "Valid numeric entity character U+00CB",
+"input": "&#x00cb;",
+"output": [["Character", "\u00CB"]]},
+
+{"description": "Valid numeric entity character U+00CC",
+"input": "&#x00cc;",
+"output": [["Character", "\u00CC"]]},
+
+{"description": "Valid numeric entity character U+00CD",
+"input": "&#x00cd;",
+"output": [["Character", "\u00CD"]]},
+
+{"description": "Valid numeric entity character U+00CE",
+"input": "&#x00ce;",
+"output": [["Character", "\u00CE"]]},
+
+{"description": "Valid numeric entity character U+00CF",
+"input": "&#x00cf;",
+"output": [["Character", "\u00CF"]]},
+
+{"description": "Valid numeric entity character U+00D0",
+"input": "&#x00d0;",
+"output": [["Character", "\u00D0"]]},
+
+{"description": "Valid numeric entity character U+00D1",
+"input": "&#x00d1;",
+"output": [["Character", "\u00D1"]]},
+
+{"description": "Valid numeric entity character U+00D2",
+"input": "&#x00d2;",
+"output": [["Character", "\u00D2"]]},
+
+{"description": "Valid numeric entity character U+00D3",
+"input": "&#x00d3;",
+"output": [["Character", "\u00D3"]]},
+
+{"description": "Valid numeric entity character U+00D4",
+"input": "&#x00d4;",
+"output": [["Character", "\u00D4"]]},
+
+{"description": "Valid numeric entity character U+00D5",
+"input": "&#x00d5;",
+"output": [["Character", "\u00D5"]]},
+
+{"description": "Valid numeric entity character U+00D6",
+"input": "&#x00d6;",
+"output": [["Character", "\u00D6"]]},
+
+{"description": "Valid numeric entity character U+00D7",
+"input": "&#x00d7;",
+"output": [["Character", "\u00D7"]]},
+
+{"description": "Valid numeric entity character U+00D8",
+"input": "&#x00d8;",
+"output": [["Character", "\u00D8"]]},
+
+{"description": "Valid numeric entity character U+00D9",
+"input": "&#x00d9;",
+"output": [["Character", "\u00D9"]]},
+
+{"description": "Valid numeric entity character U+00DA",
+"input": "&#x00da;",
+"output": [["Character", "\u00DA"]]},
+
+{"description": "Valid numeric entity character U+00DB",
+"input": "&#x00db;",
+"output": [["Character", "\u00DB"]]},
+
+{"description": "Valid numeric entity character U+00DC",
+"input": "&#x00dc;",
+"output": [["Character", "\u00DC"]]},
+
+{"description": "Valid numeric entity character U+00DD",
+"input": "&#x00dd;",
+"output": [["Character", "\u00DD"]]},
+
+{"description": "Valid numeric entity character U+00DE",
+"input": "&#x00de;",
+"output": [["Character", "\u00DE"]]},
+
+{"description": "Valid numeric entity character U+00DF",
+"input": "&#x00df;",
+"output": [["Character", "\u00DF"]]},
+
+{"description": "Valid numeric entity character U+00E0",
+"input": "&#x00e0;",
+"output": [["Character", "\u00E0"]]},
+
+{"description": "Valid numeric entity character U+00E1",
+"input": "&#x00e1;",
+"output": [["Character", "\u00E1"]]},
+
+{"description": "Valid numeric entity character U+00E2",
+"input": "&#x00e2;",
+"output": [["Character", "\u00E2"]]},
+
+{"description": "Valid numeric entity character U+00E3",
+"input": "&#x00e3;",
+"output": [["Character", "\u00E3"]]},
+
+{"description": "Valid numeric entity character U+00E4",
+"input": "&#x00e4;",
+"output": [["Character", "\u00E4"]]},
+
+{"description": "Valid numeric entity character U+00E5",
+"input": "&#x00e5;",
+"output": [["Character", "\u00E5"]]},
+
+{"description": "Valid numeric entity character U+00E6",
+"input": "&#x00e6;",
+"output": [["Character", "\u00E6"]]},
+
+{"description": "Valid numeric entity character U+00E7",
+"input": "&#x00e7;",
+"output": [["Character", "\u00E7"]]},
+
+{"description": "Valid numeric entity character U+00E8",
+"input": "&#x00e8;",
+"output": [["Character", "\u00E8"]]},
+
+{"description": "Valid numeric entity character U+00E9",
+"input": "&#x00e9;",
+"output": [["Character", "\u00E9"]]},
+
+{"description": "Valid numeric entity character U+00EA",
+"input": "&#x00ea;",
+"output": [["Character", "\u00EA"]]},
+
+{"description": "Valid numeric entity character U+00EB",
+"input": "&#x00eb;",
+"output": [["Character", "\u00EB"]]},
+
+{"description": "Valid numeric entity character U+00EC",
+"input": "&#x00ec;",
+"output": [["Character", "\u00EC"]]},
+
+{"description": "Valid numeric entity character U+00ED",
+"input": "&#x00ed;",
+"output": [["Character", "\u00ED"]]},
+
+{"description": "Valid numeric entity character U+00EE",
+"input": "&#x00ee;",
+"output": [["Character", "\u00EE"]]},
+
+{"description": "Valid numeric entity character U+00EF",
+"input": "&#x00ef;",
+"output": [["Character", "\u00EF"]]},
+
+{"description": "Valid numeric entity character U+00F0",
+"input": "&#x00f0;",
+"output": [["Character", "\u00F0"]]},
+
+{"description": "Valid numeric entity character U+00F1",
+"input": "&#x00f1;",
+"output": [["Character", "\u00F1"]]},
+
+{"description": "Valid numeric entity character U+00F2",
+"input": "&#x00f2;",
+"output": [["Character", "\u00F2"]]},
+
+{"description": "Valid numeric entity character U+00F3",
+"input": "&#x00f3;",
+"output": [["Character", "\u00F3"]]},
+
+{"description": "Valid numeric entity character U+00F4",
+"input": "&#x00f4;",
+"output": [["Character", "\u00F4"]]},
+
+{"description": "Valid numeric entity character U+00F5",
+"input": "&#x00f5;",
+"output": [["Character", "\u00F5"]]},
+
+{"description": "Valid numeric entity character U+00F6",
+"input": "&#x00f6;",
+"output": [["Character", "\u00F6"]]},
+
+{"description": "Valid numeric entity character U+00F7",
+"input": "&#x00f7;",
+"output": [["Character", "\u00F7"]]},
+
+{"description": "Valid numeric entity character U+00F8",
+"input": "&#x00f8;",
+"output": [["Character", "\u00F8"]]},
+
+{"description": "Valid numeric entity character U+00F9",
+"input": "&#x00f9;",
+"output": [["Character", "\u00F9"]]},
+
+{"description": "Valid numeric entity character U+00FA",
+"input": "&#x00fa;",
+"output": [["Character", "\u00FA"]]},
+
+{"description": "Valid numeric entity character U+00FB",
+"input": "&#x00fb;",
+"output": [["Character", "\u00FB"]]},
+
+{"description": "Valid numeric entity character U+00FC",
+"input": "&#x00fc;",
+"output": [["Character", "\u00FC"]]},
+
+{"description": "Valid numeric entity character U+00FD",
+"input": "&#x00fd;",
+"output": [["Character", "\u00FD"]]},
+
+{"description": "Valid numeric entity character U+00FE",
+"input": "&#x00fe;",
+"output": [["Character", "\u00FE"]]},
+
+{"description": "Valid numeric entity character U+00FF",
+"input": "&#x00ff;",
+"output": [["Character", "\u00FF"]]},
+
+{"description": "Valid numeric entity character U+D7FF",
+"input": "&#xd7ff;",
+"output": [["Character", "\uD7FF"]]},
+
+{"description": "Valid numeric entity character U+E000",
+"input": "&#xe000;",
+"output": [["Character", "\uE000"]]},
+
+{"description": "Valid numeric entity character U+FDCF",
+"input": "&#xfdcf;",
+"output": [["Character", "\uFDCF"]]},
+
+{"description": "Valid numeric entity character U+FDF0",
+"input": "&#xfdf0;",
+"output": [["Character", "\uFDF0"]]},
+
+{"description": "Valid numeric entity character U+FFFD",
+"input": "&#xfffd;",
+"output": [["Character", "\uFFFD"]]},
+
+{"description": "Valid numeric entity character U+10000",
+"input": "&#x10000;",
+"output": [["Character", "\uD800\uDC00"]]},
+
+{"description": "Valid numeric entity character U+1FFFD",
+"input": "&#x1fffd;",
+"output": [["Character", "\uD83F\uDFFD"]]},
+
+{"description": "Valid numeric entity character U+20000",
+"input": "&#x20000;",
+"output": [["Character", "\uD840\uDC00"]]},
+
+{"description": "Valid numeric entity character U+2FFFD",
+"input": "&#x2fffd;",
+"output": [["Character", "\uD87F\uDFFD"]]},
+
+{"description": "Valid numeric entity character U+30000",
+"input": "&#x30000;",
+"output": [["Character", "\uD880\uDC00"]]},
+
+{"description": "Valid numeric entity character U+3FFFD",
+"input": "&#x3fffd;",
+"output": [["Character", "\uD8BF\uDFFD"]]},
+
+{"description": "Valid numeric entity character U+40000",
+"input": "&#x40000;",
+"output": [["Character", "\uD8C0\uDC00"]]},
+
+{"description": "Valid numeric entity character U+4FFFD",
+"input": "&#x4fffd;",
+"output": [["Character", "\uD8FF\uDFFD"]]},
+
+{"description": "Valid numeric entity character U+50000",
+"input": "&#x50000;",
+"output": [["Character", "\uD900\uDC00"]]},
+
+{"description": "Valid numeric entity character U+5FFFD",
+"input": "&#x5fffd;",
+"output": [["Character", "\uD93F\uDFFD"]]},
+
+{"description": "Valid numeric entity character U+60000",
+"input": "&#x60000;",
+"output": [["Character", "\uD940\uDC00"]]},
+
+{"description": "Valid numeric entity character U+6FFFD",
+"input": "&#x6fffd;",
+"output": [["Character", "\uD97F\uDFFD"]]},
+
+{"description": "Valid numeric entity character U+70000",
+"input": "&#x70000;",
+"output": [["Character", "\uD980\uDC00"]]},
+
+{"description": "Valid numeric entity character U+7FFFD",
+"input": "&#x7fffd;",
+"output": [["Character", "\uD9BF\uDFFD"]]},
+
+{"description": "Valid numeric entity character U+80000",
+"input": "&#x80000;",
+"output": [["Character", "\uD9C0\uDC00"]]},
+
+{"description": "Valid numeric entity character U+8FFFD",
+"input": "&#x8fffd;",
+"output": [["Character", "\uD9FF\uDFFD"]]},
+
+{"description": "Valid numeric entity character U+90000",
+"input": "&#x90000;",
+"output": [["Character", "\uDA00\uDC00"]]},
+
+{"description": "Valid numeric entity character U+9FFFD",
+"input": "&#x9fffd;",
+"output": [["Character", "\uDA3F\uDFFD"]]},
+
+{"description": "Valid numeric entity character U+A0000",
+"input": "&#xa0000;",
+"output": [["Character", "\uDA40\uDC00"]]},
+
+{"description": "Valid numeric entity character U+AFFFD",
+"input": "&#xafffd;",
+"output": [["Character", "\uDA7F\uDFFD"]]},
+
+{"description": "Valid numeric entity character U+B0000",
+"input": "&#xb0000;",
+"output": [["Character", "\uDA80\uDC00"]]},
+
+{"description": "Valid numeric entity character U+BFFFD",
+"input": "&#xbfffd;",
+"output": [["Character", "\uDABF\uDFFD"]]},
+
+{"description": "Valid numeric entity character U+C0000",
+"input": "&#xc0000;",
+"output": [["Character", "\uDAC0\uDC00"]]},
+
+{"description": "Valid numeric entity character U+CFFFD",
+"input": "&#xcfffd;",
+"output": [["Character", "\uDAFF\uDFFD"]]},
+
+{"description": "Valid numeric entity character U+D0000",
+"input": "&#xd0000;",
+"output": [["Character", "\uDB00\uDC00"]]},
+
+{"description": "Valid numeric entity character U+DFFFD",
+"input": "&#xdfffd;",
+"output": [["Character", "\uDB3F\uDFFD"]]},
+
+{"description": "Valid numeric entity character U+E0000",
+"input": "&#xe0000;",
+"output": [["Character", "\uDB40\uDC00"]]},
+
+{"description": "Valid numeric entity character U+EFFFD",
+"input": "&#xefffd;",
+"output": [["Character", "\uDB7F\uDFFD"]]},
+
+{"description": "Valid numeric entity character U+F0000",
+"input": "&#xf0000;",
+"output": [["Character", "\uDB80\uDC00"]]},
+
+{"description": "Valid numeric entity character U+FFFFD",
+"input": "&#xffffd;",
+"output": [["Character", "\uDBBF\uDFFD"]]},
+
+{"description": "Valid numeric entity character U+100000",
+"input": "&#x100000;",
+"output": [["Character", "\uDBC0\uDC00"]]},
+
+{"description": "Valid numeric entity character U+10FFFD",
+"input": "&#x10fffd;",
+"output": [["Character", "\uDBFF\uDFFD"]]}
+
+]}
+
+
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/pendingSpecChanges.test b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/pendingSpecChanges.test
new file mode 100644
index 00000000000..1b7dc3c7228
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/pendingSpecChanges.test
@@ -0,0 +1,7 @@
+{"tests": [
+
+{"description":"<!---- >",
+"input":"<!---- >",
+"output":["ParseError", "ParseError", ["Comment","-- >"]]}
+
+]}
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/test1.test b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/test1.test
new file mode 100644
index 00000000000..b97b2cbecf9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/test1.test
@@ -0,0 +1,196 @@
+{"tests": [
+
+{"description":"Correct Doctype lowercase",
+"input":"<!DOCTYPE html>",
+"output":[["DOCTYPE", "html", null, null, true]]},
+
+{"description":"Correct Doctype uppercase",
+"input":"<!DOCTYPE HTML>",
+"output":[["DOCTYPE", "html", null, null, true]]},
+
+{"description":"Correct Doctype mixed case",
+"input":"<!DOCTYPE HtMl>",
+"output":[["DOCTYPE", "html", null, null, true]]},
+
+{"description":"Correct Doctype case with EOF",
+"input":"<!DOCTYPE HtMl",
+"output":["ParseError", ["DOCTYPE", "html", null, null, false]]},
+
+{"description":"Truncated doctype start",
+"input":"<!DOC>",
+"output":["ParseError", ["Comment", "DOC"]]},
+
+{"description":"Doctype in error",
+"input":"<!DOCTYPE foo>",
+"output":[["DOCTYPE", "foo", null, null, true]]},
+
+{"description":"Single Start Tag",
+"input":"<h>",
+"output":[["StartTag", "h", {}]]},
+
+{"description":"Empty end tag",
+"input":"</>",
+"output":["ParseError"]},
+
+{"description":"Empty start tag",
+"input":"<>",
+"output":["ParseError", ["Character", "<>"]]},
+
+{"description":"Start Tag w/attribute",
+"input":"<h a='b'>",
+"output":[["StartTag", "h", {"a":"b"}]]},
+
+{"description":"Start Tag w/attribute no quotes",
+"input":"<h a=b>",
+"output":[["StartTag", "h", {"a":"b"}]]},
+
+{"description":"Start/End Tag",
+"input":"<h></h>",
+"output":[["StartTag", "h", {}], ["EndTag", "h"]]},
+
+{"description":"Two unclosed start tags",
+"input":"<p>One<p>Two",
+"output":[["StartTag", "p", {}], ["Character", "One"], ["StartTag", "p", {}], ["Character", "Two"]]},
+
+{"description":"End Tag w/attribute",
+"input":"<h></h a='b'>",
+"output":[["StartTag", "h", {}], "ParseError", ["EndTag", "h"]]},
+
+{"description":"Multiple atts",
+"input":"<h a='b' c='d'>",
+"output":[["StartTag", "h", {"a":"b", "c":"d"}]]},
+
+{"description":"Multiple atts no space",
+"input":"<h a='b'c='d'>",
+"output":["ParseError", ["StartTag", "h", {"a":"b", "c":"d"}]]},
+
+{"description":"Repeated attr",
+ "input":"<h a='b' a='d'>",
+ "output":["ParseError", ["StartTag", "h", {"a":"b"}]]},
+
+{"description":"Simple comment",
+ "input":"<!--comment-->",
+ "output":[["Comment", "comment"]]},
+
+{"description":"Comment, Central dash no space",
+ "input":"<!----->",
+ "output":["ParseError", ["Comment", "-"]]},
+
+{"description":"Comment, two central dashes",
+"input":"<!-- --comment -->",
+"output":["ParseError", ["Comment", " --comment "]]},
+
+{"description":"Unfinished comment",
+"input":"<!--comment",
+"output":["ParseError", ["Comment", "comment"]]},
+
+{"description":"Start of a comment",
+"input":"<!-",
+"output":["ParseError", ["Comment", "-"]]},
+
+{"description":"Short comment",
+ "input":"<!-->",
+ "output":["ParseError", ["Comment", ""]]},
+
+{"description":"Short comment two",
+ "input":"<!--->",
+ "output":["ParseError", ["Comment", ""]]},
+
+{"description":"Short comment three",
+ "input":"<!---->",
+ "output":[["Comment", ""]]},
+
+
+{"description":"Ampersand EOF",
+"input":"&",
+"output":[["Character", "&"]]},
+
+{"description":"Ampersand ampersand EOF",
+"input":"&&",
+"output":[["Character", "&&"]]},
+
+{"description":"Ampersand space EOF",
+"input":"& ",
+"output":[["Character", "& "]]},
+
+{"description":"Unfinished entity",
+"input":"&f",
+"output":[["Character", "&f"]]},
+
+{"description":"Ampersand, number sign",
+"input":"&#",
+"output":["ParseError", ["Character", "&#"]]},
+
+{"description":"Unfinished numeric entity",
+"input":"&#x",
+"output":["ParseError", ["Character", "&#x"]]},
+
+{"description":"Entity with trailing semicolon (1)",
+"input":"I'm &not;it",
+"output":[["Character","I'm \u00ACit"]]},
+
+{"description":"Entity with trailing semicolon (2)",
+"input":"I'm &notin;",
+"output":[["Character","I'm \u2209"]]},
+
+{"description":"Entity without trailing semicolon (1)",
+"input":"I'm &notit",
+"output":[["Character","I'm "], "ParseError", ["Character", "\u00ACit"]]},
+
+{"description":"Entity without trailing semicolon (2)",
+"input":"I'm &notin",
+"output":[["Character","I'm "], "ParseError", ["Character", "\u00ACin"]]},
+
+{"description":"Partial entity match at end of file",
+"input":"I'm &no",
+"output":[["Character","I'm &no"]]},
+
+{"description":"Non-ASCII character reference name",
+"input":"&\u00AC;",
+"output":[["Character", "&\u00AC;"]]},
+
+{"description":"ASCII decimal entity",
+"input":"&#0036;",
+"output":[["Character","$"]]},
+
+{"description":"ASCII hexadecimal entity",
+"input":"&#x3f;",
+"output":[["Character","?"]]},
+
+{"description":"Hexadecimal entity in attribute",
+"input":"<h a='&#x3f;'></h>",
+"output":[["StartTag", "h", {"a":"?"}], ["EndTag", "h"]]},
+
+{"description":"Entity in attribute without semicolon ending in x",
+"input":"<h a='&notx'>",
+"output":[["StartTag", "h", {"a":"&notx"}]]},
+
+{"description":"Entity in attribute without semicolon ending in 1",
+"input":"<h a='&not1'>",
+"output":[["StartTag", "h", {"a":"&not1"}]]},
+
+{"description":"Entity in attribute without semicolon ending in i",
+"input":"<h a='&noti'>",
+"output":[["StartTag", "h", {"a":"&noti"}]]},
+
+{"description":"Entity in attribute without semicolon",
+"input":"<h a='&COPY'>",
+"output":["ParseError", ["StartTag", "h", {"a":"\u00A9"}]]},
+
+{"description":"Unquoted attribute ending in ampersand",
+"input":"<s o=& t>",
+"output":[["StartTag","s",{"o":"&","t":""}]]},
+
+{"description":"Unquoted attribute at end of tag with final character of &, with tag followed by characters",
+"input":"<a a=a&>foo",
+"output":[["StartTag", "a", {"a":"a&"}], ["Character", "foo"]]},
+
+{"description":"plaintext element",
+ "input":"<plaintext>foobar",
+ "output":[["StartTag","plaintext",{}], ["Character","foobar"]]},
+
+{"description":"Open angled bracket in unquoted attribute value state",
+ "input":"<a a=f<>",
+ "output":["ParseError", ["StartTag", "a", {"a":"f<"}]]}
+
+]}
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/test2.test b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/test2.test
new file mode 100644
index 00000000000..87a8eba3465
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/test2.test
@@ -0,0 +1,179 @@
+{"tests": [
+
+{"description":"DOCTYPE without name",
+"input":"<!DOCTYPE>",
+"output":["ParseError", "ParseError", ["DOCTYPE", null, null, null, false]]},
+
+{"description":"DOCTYPE without space before name",
+"input":"<!DOCTYPEhtml>",
+"output":["ParseError", ["DOCTYPE", "html", null, null, true]]},
+
+{"description":"Incorrect DOCTYPE without a space before name",
+"input":"<!DOCTYPEfoo>",
+"output":["ParseError", ["DOCTYPE", "foo", null, null, true]]},
+
+{"description":"DOCTYPE with publicId",
+"input":"<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML Transitional 4.01//EN\">",
+"output":[["DOCTYPE", "html", "-//W3C//DTD HTML Transitional 4.01//EN", null, true]]},
+
+{"description":"DOCTYPE with EOF after PUBLIC",
+"input":"<!DOCTYPE html PUBLIC",
+"output":["ParseError", ["DOCTYPE", "html", null, null, false]]},
+
+{"description":"DOCTYPE with EOF after PUBLIC '",
+"input":"<!DOCTYPE html PUBLIC '",
+"output":["ParseError", ["DOCTYPE", "html", "", null, false]]},
+
+{"description":"DOCTYPE with EOF after PUBLIC 'x",
+"input":"<!DOCTYPE html PUBLIC 'x",
+"output":["ParseError", ["DOCTYPE", "html", "x", null, false]]},
+
+{"description":"DOCTYPE with systemId",
+"input":"<!DOCTYPE html SYSTEM \"-//W3C//DTD HTML Transitional 4.01//EN\">",
+"output":[["DOCTYPE", "html", null, "-//W3C//DTD HTML Transitional 4.01//EN", true]]},
+
+{"description":"DOCTYPE with publicId and systemId",
+"input":"<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML Transitional 4.01//EN\" \"-//W3C//DTD HTML Transitional 4.01//EN\">",
+"output":[["DOCTYPE", "html", "-//W3C//DTD HTML Transitional 4.01//EN", "-//W3C//DTD HTML Transitional 4.01//EN", true]]},
+
+{"description":"DOCTYPE with > in double-quoted publicId",
+"input":"<!DOCTYPE html PUBLIC \">x",
+"output":["ParseError", ["DOCTYPE", "html", "", null, false], ["Character", "x"]]},
+
+{"description":"DOCTYPE with > in single-quoted publicId",
+"input":"<!DOCTYPE html PUBLIC '>x",
+"output":["ParseError", ["DOCTYPE", "html", "", null, false], ["Character", "x"]]},
+
+{"description":"DOCTYPE with > in double-quoted systemId",
+"input":"<!DOCTYPE html PUBLIC \"foo\" \">x",
+"output":["ParseError", ["DOCTYPE", "html", "foo", "", false], ["Character", "x"]]},
+
+{"description":"DOCTYPE with > in single-quoted systemId",
+"input":"<!DOCTYPE html PUBLIC 'foo' '>x",
+"output":["ParseError", ["DOCTYPE", "html", "foo", "", false], ["Character", "x"]]},
+
+{"description":"Incomplete doctype",
+"input":"<!DOCTYPE html ",
+"output":["ParseError", ["DOCTYPE", "html", null, null, false]]},
+
+{"description":"Numeric entity representing the NUL character",
+"input":"&#0000;",
+"output":["ParseError", ["Character", "\uFFFD"]]},
+
+{"description":"Hexadecimal entity representing the NUL character",
+"input":"&#x0000;",
+"output":["ParseError", ["Character", "\uFFFD"]]},
+
+{"description":"Numeric entity representing a codepoint after 1114111 (U+10FFFF)",
+"input":"&#2225222;",
+"output":["ParseError", ["Character", "\uFFFD"]]},
+
+{"description":"Hexadecimal entity representing a codepoint after 1114111 (U+10FFFF)",
+"input":"&#x1010FFFF;",
+"output":["ParseError", ["Character", "\uFFFD"]]},
+
+{"description":"Hexadecimal entity pair representing a surrogate pair",
+"input":"&#xD869;&#xDED6;",
+"output":["ParseError", ["Character", "\uFFFD"], "ParseError", ["Character", "\uFFFD"]]},
+
+{"description":"Hexadecimal entity with mixed uppercase and lowercase",
+"input":"&#xaBcD;",
+"output":[["Character", "\uABCD"]]},
+
+{"description":"Entity without a name",
+"input":"&;",
+"output":[["Character", "&;"]]},
+
+{"description":"Unescaped ampersand in attribute value",
+"input":"<h a='&'>",
+"output":[["StartTag", "h", { "a":"&" }]]},
+
+{"description":"StartTag containing <",
+"input":"<a<b>",
+"output":[["StartTag", "a<b", { }]]},
+
+{"description":"Non-void element containing trailing /",
+"input":"<h/>",
+"output":[["StartTag","h",{},true]]},
+
+{"description":"Void element with permitted slash",
+"input":"<br/>",
+"output":[["StartTag","br",{},true]]},
+
+{"description":"Void element with permitted slash (with attribute)",
+"input":"<br foo='bar'/>",
+"output":[["StartTag","br",{"foo":"bar"},true]]},
+
+{"description":"StartTag containing /",
+"input":"<h/a='b'>",
+"output":["ParseError", ["StartTag", "h", { "a":"b" }]]},
+
+{"description":"Double-quoted attribute value",
+"input":"<h a=\"b\">",
+"output":[["StartTag", "h", { "a":"b" }]]},
+
+{"description":"Unescaped </",
+"input":"</",
+"output":["ParseError", ["Character", "</"]]},
+
+{"description":"Illegal end tag name",
+"input":"</1>",
+"output":["ParseError", ["Comment", "1"]]},
+
+{"description":"Simili processing instruction",
+"input":"<?namespace>",
+"output":["ParseError", ["Comment", "?namespace"]]},
+
+{"description":"A bogus comment stops at >, even if preceeded by two dashes",
+"input":"<?foo-->",
+"output":["ParseError", ["Comment", "?foo--"]]},
+
+{"description":"Unescaped <",
+"input":"foo < bar",
+"output":[["Character", "foo "], "ParseError", ["Character", "< bar"]]},
+
+{"description":"Null Byte Replacement",
+"input":"\u0000",
+"output":["ParseError", ["Character", "\u0000"]]},
+
+{"description":"Comment with dash",
+"input":"<!---x",
+"output":["ParseError", ["Comment", "-x"]]},
+
+{"description":"Entity + newline",
+"input":"\nx\n&gt;\n",
+"output":[["Character","\nx\n>\n"]]},
+
+{"description":"Start tag with no attributes but space before the greater-than sign",
+"input":"<h >",
+"output":[["StartTag", "h", {}]]},
+
+{"description":"Empty attribute followed by uppercase attribute",
+"input":"<h a B=''>",
+"output":[["StartTag", "h", {"a":"", "b":""}]]},
+
+{"description":"Double-quote after attribute name",
+"input":"<h a \">",
+"output":["ParseError", ["StartTag", "h", {"a":"", "\"":""}]]},
+
+{"description":"Single-quote after attribute name",
+"input":"<h a '>",
+"output":["ParseError", ["StartTag", "h", {"a":"", "'":""}]]},
+
+{"description":"Empty end tag with following characters",
+"input":"a</>bc",
+"output":[["Character", "a"], "ParseError", ["Character", "bc"]]},
+
+{"description":"Empty end tag with following tag",
+"input":"a</><b>c",
+"output":[["Character", "a"], "ParseError", ["StartTag", "b", {}], ["Character", "c"]]},
+
+{"description":"Empty end tag with following comment",
+"input":"a</><!--b-->c",
+"output":[["Character", "a"], "ParseError", ["Comment", "b"], ["Character", "c"]]},
+
+{"description":"Empty end tag with following end tag",
+"input":"a</></b>c",
+"output":[["Character", "a"], "ParseError", ["EndTag", "b"], ["Character", "c"]]}
+
+]}
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/test3.test b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/test3.test
new file mode 100644
index 00000000000..8fc529a2ba4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/test3.test
@@ -0,0 +1,6047 @@
+{"tests": [
+
+{"description":"",
+"input":"",
+"output":[]},
+
+{"description":"\\u0009",
+"input":"\u0009",
+"output":[["Character", "\u0009"]]},
+
+{"description":"\\u000A",
+"input":"\u000A",
+"output":[["Character", "\u000A"]]},
+
+{"description":"\\u000B",
+"input":"\u000B",
+"output":["ParseError", ["Character", "\u000B"]]},
+
+{"description":"\\u000C",
+"input":"\u000C",
+"output":[["Character", "\u000C"]]},
+
+{"description":" ",
+"input":" ",
+"output":[["Character", " "]]},
+
+{"description":"!",
+"input":"!",
+"output":[["Character", "!"]]},
+
+{"description":"\"",
+"input":"\"",
+"output":[["Character", "\""]]},
+
+{"description":"%",
+"input":"%",
+"output":[["Character", "%"]]},
+
+{"description":"&",
+"input":"&",
+"output":[["Character", "&"]]},
+
+{"description":"'",
+"input":"'",
+"output":[["Character", "'"]]},
+
+{"description":",",
+"input":",",
+"output":[["Character", ","]]},
+
+{"description":"-",
+"input":"-",
+"output":[["Character", "-"]]},
+
+{"description":".",
+"input":".",
+"output":[["Character", "."]]},
+
+{"description":"/",
+"input":"/",
+"output":[["Character", "/"]]},
+
+{"description":"0",
+"input":"0",
+"output":[["Character", "0"]]},
+
+{"description":"1",
+"input":"1",
+"output":[["Character", "1"]]},
+
+{"description":"9",
+"input":"9",
+"output":[["Character", "9"]]},
+
+{"description":";",
+"input":";",
+"output":[["Character", ";"]]},
+
+{"description":"<",
+"input":"<",
+"output":["ParseError", ["Character", "<"]]},
+
+{"description":"<\\u0000",
+"input":"<\u0000",
+"output":["ParseError", ["Character", "<"], "ParseError", ["Character", "\u0000"]]},
+
+{"description":"<\\u0009",
+"input":"<\u0009",
+"output":["ParseError", ["Character", "<\u0009"]]},
+
+{"description":"<\\u000A",
+"input":"<\u000A",
+"output":["ParseError", ["Character", "<\u000A"]]},
+
+{"description":"<\\u000B",
+"input":"<\u000B",
+"output":["ParseError", "ParseError", ["Character", "<\u000B"]]},
+
+{"description":"<\\u000C",
+"input":"<\u000C",
+"output":["ParseError", ["Character", "<\u000C"]]},
+
+{"description":"< ",
+"input":"< ",
+"output":["ParseError", ["Character", "< "]]},
+
+{"description":"<!",
+"input":"<!",
+"output":["ParseError", ["Comment", ""]]},
+
+{"description":"<!\\u0000",
+"input":"<!\u0000",
+"output":["ParseError", ["Comment", "\uFFFD"]]},
+
+{"description":"<!\\u0009",
+"input":"<!\u0009",
+"output":["ParseError", ["Comment", "\u0009"]]},
+
+{"description":"<!\\u000A",
+"input":"<!\u000A",
+"output":["ParseError", ["Comment", "\u000A"]]},
+
+{"description":"<!\\u000B",
+"input":"<!\u000B",
+"output":["ParseError", "ParseError", ["Comment", "\u000B"]]},
+
+{"description":"<!\\u000C",
+"input":"<!\u000C",
+"output":["ParseError", ["Comment", "\u000C"]]},
+
+{"description":"<! ",
+"input":"<! ",
+"output":["ParseError", ["Comment", " "]]},
+
+{"description":"<!!",
+"input":"<!!",
+"output":["ParseError", ["Comment", "!"]]},
+
+{"description":"<!\"",
+"input":"<!\"",
+"output":["ParseError", ["Comment", "\""]]},
+
+{"description":"<!&",
+"input":"<!&",
+"output":["ParseError", ["Comment", "&"]]},
+
+{"description":"<!'",
+"input":"<!'",
+"output":["ParseError", ["Comment", "'"]]},
+
+{"description":"<!-",
+"input":"<!-",
+"output":["ParseError", ["Comment", "-"]]},
+
+{"description":"<!--",
+"input":"<!--",
+"output":["ParseError", ["Comment", ""]]},
+
+{"description":"<!--\\u0000",
+"input":"<!--\u0000",
+"output":["ParseError", "ParseError", ["Comment", "\uFFFD"]]},
+
+{"description":"<!--\\u0009",
+"input":"<!--\u0009",
+"output":["ParseError", ["Comment", "\u0009"]]},
+
+{"description":"<!--\\u000A",
+"input":"<!--\u000A",
+"output":["ParseError", ["Comment", "\u000A"]]},
+
+{"description":"<!--\\u000B",
+"input":"<!--\u000B",
+"output":["ParseError", "ParseError", ["Comment", "\u000B"]]},
+
+{"description":"<!--\\u000C",
+"input":"<!--\u000C",
+"output":["ParseError", ["Comment", "\u000C"]]},
+
+{"description":"<!-- ",
+"input":"<!-- ",
+"output":["ParseError", ["Comment", " "]]},
+
+{"description":"<!-- \\u0000",
+"input":"<!-- \u0000",
+"output":["ParseError", "ParseError", ["Comment", " \uFFFD"]]},
+
+{"description":"<!-- \\u0009",
+"input":"<!-- \u0009",
+"output":["ParseError", ["Comment", " \u0009"]]},
+
+{"description":"<!-- \\u000A",
+"input":"<!-- \u000A",
+"output":["ParseError", ["Comment", " \u000A"]]},
+
+{"description":"<!-- \\u000B",
+"input":"<!-- \u000B",
+"output":["ParseError", "ParseError", ["Comment", " \u000B"]]},
+
+{"description":"<!-- \\u000C",
+"input":"<!-- \u000C",
+"output":["ParseError", ["Comment", " \u000C"]]},
+
+{"description":"<!-- ",
+"input":"<!-- ",
+"output":["ParseError", ["Comment", " "]]},
+
+{"description":"<!-- !",
+"input":"<!-- !",
+"output":["ParseError", ["Comment", " !"]]},
+
+{"description":"<!-- \"",
+"input":"<!-- \"",
+"output":["ParseError", ["Comment", " \""]]},
+
+{"description":"<!-- &",
+"input":"<!-- &",
+"output":["ParseError", ["Comment", " &"]]},
+
+{"description":"<!-- '",
+"input":"<!-- '",
+"output":["ParseError", ["Comment", " '"]]},
+
+{"description":"<!-- ,",
+"input":"<!-- ,",
+"output":["ParseError", ["Comment", " ,"]]},
+
+{"description":"<!-- -",
+"input":"<!-- -",
+"output":["ParseError", ["Comment", " "]]},
+
+{"description":"<!-- -\\u0000",
+"input":"<!-- -\u0000",
+"output":["ParseError", "ParseError", ["Comment", " -\uFFFD"]]},
+
+{"description":"<!-- -\\u0009",
+"input":"<!-- -\u0009",
+"output":["ParseError", ["Comment", " -\u0009"]]},
+
+{"description":"<!-- -\\u000A",
+"input":"<!-- -\u000A",
+"output":["ParseError", ["Comment", " -\u000A"]]},
+
+{"description":"<!-- -\\u000B",
+"input":"<!-- -\u000B",
+"output":["ParseError", "ParseError", ["Comment", " -\u000B"]]},
+
+{"description":"<!-- -\\u000C",
+"input":"<!-- -\u000C",
+"output":["ParseError", ["Comment", " -\u000C"]]},
+
+{"description":"<!-- - ",
+"input":"<!-- - ",
+"output":["ParseError", ["Comment", " - "]]},
+
+{"description":"<!-- -!",
+"input":"<!-- -!",
+"output":["ParseError", ["Comment", " -!"]]},
+
+{"description":"<!-- -\"",
+"input":"<!-- -\"",
+"output":["ParseError", ["Comment", " -\""]]},
+
+{"description":"<!-- -&",
+"input":"<!-- -&",
+"output":["ParseError", ["Comment", " -&"]]},
+
+{"description":"<!-- -'",
+"input":"<!-- -'",
+"output":["ParseError", ["Comment", " -'"]]},
+
+{"description":"<!-- -,",
+"input":"<!-- -,",
+"output":["ParseError", ["Comment", " -,"]]},
+
+{"description":"<!-- --",
+"input":"<!-- --",
+"output":["ParseError", ["Comment", " "]]},
+
+{"description":"<!-- -.",
+"input":"<!-- -.",
+"output":["ParseError", ["Comment", " -."]]},
+
+{"description":"<!-- -/",
+"input":"<!-- -/",
+"output":["ParseError", ["Comment", " -/"]]},
+
+{"description":"<!-- -0",
+"input":"<!-- -0",
+"output":["ParseError", ["Comment", " -0"]]},
+
+{"description":"<!-- -1",
+"input":"<!-- -1",
+"output":["ParseError", ["Comment", " -1"]]},
+
+{"description":"<!-- -9",
+"input":"<!-- -9",
+"output":["ParseError", ["Comment", " -9"]]},
+
+{"description":"<!-- -<",
+"input":"<!-- -<",
+"output":["ParseError", ["Comment", " -<"]]},
+
+{"description":"<!-- -=",
+"input":"<!-- -=",
+"output":["ParseError", ["Comment", " -="]]},
+
+{"description":"<!-- ->",
+"input":"<!-- ->",
+"output":["ParseError", ["Comment", " ->"]]},
+
+{"description":"<!-- -?",
+"input":"<!-- -?",
+"output":["ParseError", ["Comment", " -?"]]},
+
+{"description":"<!-- -@",
+"input":"<!-- -@",
+"output":["ParseError", ["Comment", " -@"]]},
+
+{"description":"<!-- -A",
+"input":"<!-- -A",
+"output":["ParseError", ["Comment", " -A"]]},
+
+{"description":"<!-- -B",
+"input":"<!-- -B",
+"output":["ParseError", ["Comment", " -B"]]},
+
+{"description":"<!-- -Y",
+"input":"<!-- -Y",
+"output":["ParseError", ["Comment", " -Y"]]},
+
+{"description":"<!-- -Z",
+"input":"<!-- -Z",
+"output":["ParseError", ["Comment", " -Z"]]},
+
+{"description":"<!-- -`",
+"input":"<!-- -`",
+"output":["ParseError", ["Comment", " -`"]]},
+
+{"description":"<!-- -a",
+"input":"<!-- -a",
+"output":["ParseError", ["Comment", " -a"]]},
+
+{"description":"<!-- -b",
+"input":"<!-- -b",
+"output":["ParseError", ["Comment", " -b"]]},
+
+{"description":"<!-- -y",
+"input":"<!-- -y",
+"output":["ParseError", ["Comment", " -y"]]},
+
+{"description":"<!-- -z",
+"input":"<!-- -z",
+"output":["ParseError", ["Comment", " -z"]]},
+
+{"description":"<!-- -{",
+"input":"<!-- -{",
+"output":["ParseError", ["Comment", " -{"]]},
+
+{"description":"<!-- -\\uDBC0\\uDC00",
+"input":"<!-- -\uDBC0\uDC00",
+"output":["ParseError", ["Comment", " -\uDBC0\uDC00"]]},
+
+{"description":"<!-- .",
+"input":"<!-- .",
+"output":["ParseError", ["Comment", " ."]]},
+
+{"description":"<!-- /",
+"input":"<!-- /",
+"output":["ParseError", ["Comment", " /"]]},
+
+{"description":"<!-- 0",
+"input":"<!-- 0",
+"output":["ParseError", ["Comment", " 0"]]},
+
+{"description":"<!-- 1",
+"input":"<!-- 1",
+"output":["ParseError", ["Comment", " 1"]]},
+
+{"description":"<!-- 9",
+"input":"<!-- 9",
+"output":["ParseError", ["Comment", " 9"]]},
+
+{"description":"<!-- <",
+"input":"<!-- <",
+"output":["ParseError", ["Comment", " <"]]},
+
+{"description":"<!-- =",
+"input":"<!-- =",
+"output":["ParseError", ["Comment", " ="]]},
+
+{"description":"<!-- >",
+"input":"<!-- >",
+"output":["ParseError", ["Comment", " >"]]},
+
+{"description":"<!-- ?",
+"input":"<!-- ?",
+"output":["ParseError", ["Comment", " ?"]]},
+
+{"description":"<!-- @",
+"input":"<!-- @",
+"output":["ParseError", ["Comment", " @"]]},
+
+{"description":"<!-- A",
+"input":"<!-- A",
+"output":["ParseError", ["Comment", " A"]]},
+
+{"description":"<!-- B",
+"input":"<!-- B",
+"output":["ParseError", ["Comment", " B"]]},
+
+{"description":"<!-- Y",
+"input":"<!-- Y",
+"output":["ParseError", ["Comment", " Y"]]},
+
+{"description":"<!-- Z",
+"input":"<!-- Z",
+"output":["ParseError", ["Comment", " Z"]]},
+
+{"description":"<!-- `",
+"input":"<!-- `",
+"output":["ParseError", ["Comment", " `"]]},
+
+{"description":"<!-- a",
+"input":"<!-- a",
+"output":["ParseError", ["Comment", " a"]]},
+
+{"description":"<!-- b",
+"input":"<!-- b",
+"output":["ParseError", ["Comment", " b"]]},
+
+{"description":"<!-- y",
+"input":"<!-- y",
+"output":["ParseError", ["Comment", " y"]]},
+
+{"description":"<!-- z",
+"input":"<!-- z",
+"output":["ParseError", ["Comment", " z"]]},
+
+{"description":"<!-- {",
+"input":"<!-- {",
+"output":["ParseError", ["Comment", " {"]]},
+
+{"description":"<!-- \\uDBC0\\uDC00",
+"input":"<!-- \uDBC0\uDC00",
+"output":["ParseError", ["Comment", " \uDBC0\uDC00"]]},
+
+{"description":"<!--!",
+"input":"<!--!",
+"output":["ParseError", ["Comment", "!"]]},
+
+{"description":"<!--\"",
+"input":"<!--\"",
+"output":["ParseError", ["Comment", "\""]]},
+
+{"description":"<!--&",
+"input":"<!--&",
+"output":["ParseError", ["Comment", "&"]]},
+
+{"description":"<!--'",
+"input":"<!--'",
+"output":["ParseError", ["Comment", "'"]]},
+
+{"description":"<!--,",
+"input":"<!--,",
+"output":["ParseError", ["Comment", ","]]},
+
+{"description":"<!---",
+"input":"<!---",
+"output":["ParseError", ["Comment", ""]]},
+
+{"description":"<!---\\u0000",
+"input":"<!---\u0000",
+"output":["ParseError", "ParseError", ["Comment", "-\uFFFD"]]},
+
+{"description":"<!---\\u0009",
+"input":"<!---\u0009",
+"output":["ParseError", ["Comment", "-\u0009"]]},
+
+{"description":"<!---\\u000A",
+"input":"<!---\u000A",
+"output":["ParseError", ["Comment", "-\u000A"]]},
+
+{"description":"<!---\\u000B",
+"input":"<!---\u000B",
+"output":["ParseError", "ParseError", ["Comment", "-\u000B"]]},
+
+{"description":"<!---\\u000C",
+"input":"<!---\u000C",
+"output":["ParseError", ["Comment", "-\u000C"]]},
+
+{"description":"<!--- ",
+"input":"<!--- ",
+"output":["ParseError", ["Comment", "- "]]},
+
+{"description":"<!---!",
+"input":"<!---!",
+"output":["ParseError", ["Comment", "-!"]]},
+
+{"description":"<!---\"",
+"input":"<!---\"",
+"output":["ParseError", ["Comment", "-\""]]},
+
+{"description":"<!---&",
+"input":"<!---&",
+"output":["ParseError", ["Comment", "-&"]]},
+
+{"description":"<!---'",
+"input":"<!---'",
+"output":["ParseError", ["Comment", "-'"]]},
+
+{"description":"<!---,",
+"input":"<!---,",
+"output":["ParseError", ["Comment", "-,"]]},
+
+{"description":"<!----",
+"input":"<!----",
+"output":["ParseError", ["Comment", ""]]},
+
+{"description":"<!----\\u0000",
+"input":"<!----\u0000",
+"output":["ParseError", "ParseError", ["Comment", "--\uFFFD"]]},
+
+{"description":"<!----\\u0009",
+"input":"<!----\u0009",
+"output":["ParseError", "ParseError", ["Comment", "--\u0009"]]},
+
+{"description":"<!----\\u000A",
+"input":"<!----\u000A",
+"output":["ParseError", "ParseError", ["Comment", "--\u000A"]]},
+
+{"description":"<!----\\u000B",
+"input":"<!----\u000B",
+"output":["ParseError", "ParseError", "ParseError", ["Comment", "--\u000B"]]},
+
+{"description":"<!----\\u000C",
+"input":"<!----\u000C",
+"output":["ParseError", "ParseError", ["Comment", "--\u000C"]]},
+
+{"description":"<!---- ",
+"input":"<!---- ",
+"output":["ParseError", "ParseError", ["Comment", "-- "]]},
+
+{"description":"<!---- -",
+"input":"<!---- -",
+"output":["ParseError", "ParseError", ["Comment", "-- "]]},
+
+{"description":"<!---- --",
+"input":"<!---- --",
+"output":["ParseError", "ParseError", ["Comment", "-- "]]},
+
+{"description":"<!---- -->",
+"input":"<!---- -->",
+"output":["ParseError", ["Comment", "-- "]]},
+
+{"description":"<!---- -->",
+"input":"<!---- -->",
+"output":["ParseError", ["Comment", "-- "]]},
+
+{"description":"<!---- a-->",
+"input":"<!---- a-->",
+"output":["ParseError", ["Comment", "-- a"]]},
+
+{"description":"<!----!",
+"input":"<!----!",
+"output":["ParseError", "ParseError", ["Comment", ""]]},
+
+{"description":"<!----!>",
+"input":"<!----!>",
+"output":["ParseError", ["Comment", ""]]},
+
+{"description":"<!----!a",
+"input":"<!----!a",
+"output":["ParseError", "ParseError", ["Comment", "--!a"]]},
+
+{"description":"<!----!a-",
+"input":"<!----!a-",
+"output":["ParseError", "ParseError", ["Comment", "--!a"]]},
+
+{"description":"<!----!a--",
+"input":"<!----!a--",
+"output":["ParseError", "ParseError", ["Comment", "--!a"]]},
+
+{"description":"<!----!a-->",
+"input":"<!----!a-->",
+"output":["ParseError", ["Comment", "--!a"]]},
+
+{"description":"<!----!-",
+"input":"<!----!-",
+"output":["ParseError", "ParseError", ["Comment", "--!"]]},
+
+{"description":"<!----!--",
+"input":"<!----!--",
+"output":["ParseError", "ParseError", ["Comment", "--!"]]},
+
+{"description":"<!----!-->",
+"input":"<!----!-->",
+"output":["ParseError", ["Comment", "--!"]]},
+
+{"description":"<!----\"",
+"input":"<!----\"",
+"output":["ParseError", "ParseError", ["Comment", "--\""]]},
+
+{"description":"<!----&",
+"input":"<!----&",
+"output":["ParseError", "ParseError", ["Comment", "--&"]]},
+
+{"description":"<!----'",
+"input":"<!----'",
+"output":["ParseError", "ParseError", ["Comment", "--'"]]},
+
+{"description":"<!----,",
+"input":"<!----,",
+"output":["ParseError", "ParseError", ["Comment", "--,"]]},
+
+{"description":"<!-----",
+"input":"<!-----",
+"output":["ParseError", "ParseError", ["Comment", "-"]]},
+
+{"description":"<!----.",
+"input":"<!----.",
+"output":["ParseError", "ParseError", ["Comment", "--."]]},
+
+{"description":"<!----/",
+"input":"<!----/",
+"output":["ParseError", "ParseError", ["Comment", "--/"]]},
+
+{"description":"<!----0",
+"input":"<!----0",
+"output":["ParseError", "ParseError", ["Comment", "--0"]]},
+
+{"description":"<!----1",
+"input":"<!----1",
+"output":["ParseError", "ParseError", ["Comment", "--1"]]},
+
+{"description":"<!----9",
+"input":"<!----9",
+"output":["ParseError", "ParseError", ["Comment", "--9"]]},
+
+{"description":"<!----<",
+"input":"<!----<",
+"output":["ParseError", "ParseError", ["Comment", "--<"]]},
+
+{"description":"<!----=",
+"input":"<!----=",
+"output":["ParseError", "ParseError", ["Comment", "--="]]},
+
+{"description":"<!---->",
+"input":"<!---->",
+"output":[["Comment", ""]]},
+
+{"description":"<!----?",
+"input":"<!----?",
+"output":["ParseError", "ParseError", ["Comment", "--?"]]},
+
+{"description":"<!----@",
+"input":"<!----@",
+"output":["ParseError", "ParseError", ["Comment", "--@"]]},
+
+{"description":"<!----A",
+"input":"<!----A",
+"output":["ParseError", "ParseError", ["Comment", "--A"]]},
+
+{"description":"<!----B",
+"input":"<!----B",
+"output":["ParseError", "ParseError", ["Comment", "--B"]]},
+
+{"description":"<!----Y",
+"input":"<!----Y",
+"output":["ParseError", "ParseError", ["Comment", "--Y"]]},
+
+{"description":"<!----Z",
+"input":"<!----Z",
+"output":["ParseError", "ParseError", ["Comment", "--Z"]]},
+
+{"description":"<!----`",
+"input":"<!----`",
+"output":["ParseError", "ParseError", ["Comment", "--`"]]},
+
+{"description":"<!----a",
+"input":"<!----a",
+"output":["ParseError", "ParseError", ["Comment", "--a"]]},
+
+{"description":"<!----b",
+"input":"<!----b",
+"output":["ParseError", "ParseError", ["Comment", "--b"]]},
+
+{"description":"<!----y",
+"input":"<!----y",
+"output":["ParseError", "ParseError", ["Comment", "--y"]]},
+
+{"description":"<!----z",
+"input":"<!----z",
+"output":["ParseError", "ParseError", ["Comment", "--z"]]},
+
+{"description":"<!----{",
+"input":"<!----{",
+"output":["ParseError", "ParseError", ["Comment", "--{"]]},
+
+{"description":"<!----\\uDBC0\\uDC00",
+"input":"<!----\uDBC0\uDC00",
+"output":["ParseError", "ParseError", ["Comment", "--\uDBC0\uDC00"]]},
+
+{"description":"<!---.",
+"input":"<!---.",
+"output":["ParseError", ["Comment", "-."]]},
+
+{"description":"<!---/",
+"input":"<!---/",
+"output":["ParseError", ["Comment", "-/"]]},
+
+{"description":"<!---0",
+"input":"<!---0",
+"output":["ParseError", ["Comment", "-0"]]},
+
+{"description":"<!---1",
+"input":"<!---1",
+"output":["ParseError", ["Comment", "-1"]]},
+
+{"description":"<!---9",
+"input":"<!---9",
+"output":["ParseError", ["Comment", "-9"]]},
+
+{"description":"<!---<",
+"input":"<!---<",
+"output":["ParseError", ["Comment", "-<"]]},
+
+{"description":"<!---=",
+"input":"<!---=",
+"output":["ParseError", ["Comment", "-="]]},
+
+{"description":"<!--->",
+"input":"<!--->",
+"output":["ParseError", ["Comment", ""]]},
+
+{"description":"<!---?",
+"input":"<!---?",
+"output":["ParseError", ["Comment", "-?"]]},
+
+{"description":"<!---@",
+"input":"<!---@",
+"output":["ParseError", ["Comment", "-@"]]},
+
+{"description":"<!---A",
+"input":"<!---A",
+"output":["ParseError", ["Comment", "-A"]]},
+
+{"description":"<!---B",
+"input":"<!---B",
+"output":["ParseError", ["Comment", "-B"]]},
+
+{"description":"<!---Y",
+"input":"<!---Y",
+"output":["ParseError", ["Comment", "-Y"]]},
+
+{"description":"<!---Z",
+"input":"<!---Z",
+"output":["ParseError", ["Comment", "-Z"]]},
+
+{"description":"<!---`",
+"input":"<!---`",
+"output":["ParseError", ["Comment", "-`"]]},
+
+{"description":"<!---a",
+"input":"<!---a",
+"output":["ParseError", ["Comment", "-a"]]},
+
+{"description":"<!---b",
+"input":"<!---b",
+"output":["ParseError", ["Comment", "-b"]]},
+
+{"description":"<!---y",
+"input":"<!---y",
+"output":["ParseError", ["Comment", "-y"]]},
+
+{"description":"<!---z",
+"input":"<!---z",
+"output":["ParseError", ["Comment", "-z"]]},
+
+{"description":"<!---{",
+"input":"<!---{",
+"output":["ParseError", ["Comment", "-{"]]},
+
+{"description":"<!---\\uDBC0\\uDC00",
+"input":"<!---\uDBC0\uDC00",
+"output":["ParseError", ["Comment", "-\uDBC0\uDC00"]]},
+
+{"description":"<!--.",
+"input":"<!--.",
+"output":["ParseError", ["Comment", "."]]},
+
+{"description":"<!--/",
+"input":"<!--/",
+"output":["ParseError", ["Comment", "/"]]},
+
+{"description":"<!--0",
+"input":"<!--0",
+"output":["ParseError", ["Comment", "0"]]},
+
+{"description":"<!--1",
+"input":"<!--1",
+"output":["ParseError", ["Comment", "1"]]},
+
+{"description":"<!--9",
+"input":"<!--9",
+"output":["ParseError", ["Comment", "9"]]},
+
+{"description":"<!--<",
+"input":"<!--<",
+"output":["ParseError", ["Comment", "<"]]},
+
+{"description":"<!--=",
+"input":"<!--=",
+"output":["ParseError", ["Comment", "="]]},
+
+{"description":"<!-->",
+"input":"<!-->",
+"output":["ParseError", ["Comment", ""]]},
+
+{"description":"<!--?",
+"input":"<!--?",
+"output":["ParseError", ["Comment", "?"]]},
+
+{"description":"<!--@",
+"input":"<!--@",
+"output":["ParseError", ["Comment", "@"]]},
+
+{"description":"<!--A",
+"input":"<!--A",
+"output":["ParseError", ["Comment", "A"]]},
+
+{"description":"<!--B",
+"input":"<!--B",
+"output":["ParseError", ["Comment", "B"]]},
+
+{"description":"<!--Y",
+"input":"<!--Y",
+"output":["ParseError", ["Comment", "Y"]]},
+
+{"description":"<!--Z",
+"input":"<!--Z",
+"output":["ParseError", ["Comment", "Z"]]},
+
+{"description":"<!--`",
+"input":"<!--`",
+"output":["ParseError", ["Comment", "`"]]},
+
+{"description":"<!--a",
+"input":"<!--a",
+"output":["ParseError", ["Comment", "a"]]},
+
+{"description":"<!--b",
+"input":"<!--b",
+"output":["ParseError", ["Comment", "b"]]},
+
+{"description":"<!--y",
+"input":"<!--y",
+"output":["ParseError", ["Comment", "y"]]},
+
+{"description":"<!--z",
+"input":"<!--z",
+"output":["ParseError", ["Comment", "z"]]},
+
+{"description":"<!--{",
+"input":"<!--{",
+"output":["ParseError", ["Comment", "{"]]},
+
+{"description":"<!--\\uDBC0\\uDC00",
+"input":"<!--\uDBC0\uDC00",
+"output":["ParseError", ["Comment", "\uDBC0\uDC00"]]},
+
+{"description":"<!/",
+"input":"<!/",
+"output":["ParseError", ["Comment", "/"]]},
+
+{"description":"<!0",
+"input":"<!0",
+"output":["ParseError", ["Comment", "0"]]},
+
+{"description":"<!1",
+"input":"<!1",
+"output":["ParseError", ["Comment", "1"]]},
+
+{"description":"<!9",
+"input":"<!9",
+"output":["ParseError", ["Comment", "9"]]},
+
+{"description":"<!<",
+"input":"<!<",
+"output":["ParseError", ["Comment", "<"]]},
+
+{"description":"<!=",
+"input":"<!=",
+"output":["ParseError", ["Comment", "="]]},
+
+{"description":"<!>",
+"input":"<!>",
+"output":["ParseError", ["Comment", ""]]},
+
+{"description":"<!?",
+"input":"<!?",
+"output":["ParseError", ["Comment", "?"]]},
+
+{"description":"<!@",
+"input":"<!@",
+"output":["ParseError", ["Comment", "@"]]},
+
+{"description":"<!A",
+"input":"<!A",
+"output":["ParseError", ["Comment", "A"]]},
+
+{"description":"<!B",
+"input":"<!B",
+"output":["ParseError", ["Comment", "B"]]},
+
+{"description":"<!DOCTYPE",
+"input":"<!DOCTYPE",
+"output":["ParseError", ["DOCTYPE", null, null, null, false]]},
+
+{"description":"<!DOCTYPE\\u0000",
+"input":"<!DOCTYPE\u0000",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "\uFFFD", null, null, false]]},
+
+{"description":"<!DOCTYPE\\u0008",
+"input":"<!DOCTYPE\u0008",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "\u0008", null, null, false]]},
+
+{"description":"<!DOCTYPE\\u0009",
+"input":"<!DOCTYPE\u0009",
+"output":["ParseError", ["DOCTYPE", null, null, null, false]]},
+
+{"description":"<!DOCTYPE\\u000A",
+"input":"<!DOCTYPE\u000A",
+"output":["ParseError", ["DOCTYPE", null, null, null, false]]},
+
+{"description":"<!DOCTYPE\\u000B",
+"input":"<!DOCTYPE\u000B",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "\u000B", null, null, false]]},
+
+{"description":"<!DOCTYPE\\u000C",
+"input":"<!DOCTYPE\u000C",
+"output":["ParseError", ["DOCTYPE", null, null, null, false]]},
+
+{"description":"<!DOCTYPE\\u000D",
+"input":"<!DOCTYPE\u000D",
+"output":["ParseError", ["DOCTYPE", null, null, null, false]]},
+
+{"description":"<!DOCTYPE\\u001F",
+"input":"<!DOCTYPE\u001F",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "\u001F", null, null, false]]},
+
+{"description":"<!DOCTYPE ",
+"input":"<!DOCTYPE ",
+"output":["ParseError", ["DOCTYPE", null, null, null, false]]},
+
+{"description":"<!DOCTYPE \\u0000",
+"input":"<!DOCTYPE \u0000",
+"output":["ParseError", "ParseError", ["DOCTYPE", "\uFFFD", null, null, false]]},
+
+{"description":"<!DOCTYPE \\u0008",
+"input":"<!DOCTYPE \u0008",
+"output":["ParseError", "ParseError", ["DOCTYPE", "\u0008", null, null, false]]},
+
+{"description":"<!DOCTYPE \\u0009",
+"input":"<!DOCTYPE \u0009",
+"output":["ParseError", ["DOCTYPE", null, null, null, false]]},
+
+{"description":"<!DOCTYPE \\u000A",
+"input":"<!DOCTYPE \u000A",
+"output":["ParseError", ["DOCTYPE", null, null, null, false]]},
+
+{"description":"<!DOCTYPE \\u000B",
+"input":"<!DOCTYPE \u000B",
+"output":["ParseError", "ParseError", ["DOCTYPE", "\u000B", null, null, false]]},
+
+{"description":"<!DOCTYPE \\u000C",
+"input":"<!DOCTYPE \u000C",
+"output":["ParseError", ["DOCTYPE", null, null, null, false]]},
+
+{"description":"<!DOCTYPE \\u000D",
+"input":"<!DOCTYPE \u000D",
+"output":["ParseError", ["DOCTYPE", null, null, null, false]]},
+
+{"description":"<!DOCTYPE \\u001F",
+"input":"<!DOCTYPE \u001F",
+"output":["ParseError", "ParseError", ["DOCTYPE", "\u001F", null, null, false]]},
+
+{"description":"<!DOCTYPE ",
+"input":"<!DOCTYPE ",
+"output":["ParseError", ["DOCTYPE", null, null, null, false]]},
+
+{"description":"<!DOCTYPE !",
+"input":"<!DOCTYPE !",
+"output":["ParseError", ["DOCTYPE", "!", null, null, false]]},
+
+{"description":"<!DOCTYPE \"",
+"input":"<!DOCTYPE \"",
+"output":["ParseError", ["DOCTYPE", "\"", null, null, false]]},
+
+{"description":"<!DOCTYPE &",
+"input":"<!DOCTYPE &",
+"output":["ParseError", ["DOCTYPE", "&", null, null, false]]},
+
+{"description":"<!DOCTYPE '",
+"input":"<!DOCTYPE '",
+"output":["ParseError", ["DOCTYPE", "'", null, null, false]]},
+
+{"description":"<!DOCTYPE -",
+"input":"<!DOCTYPE -",
+"output":["ParseError", ["DOCTYPE", "-", null, null, false]]},
+
+{"description":"<!DOCTYPE /",
+"input":"<!DOCTYPE /",
+"output":["ParseError", ["DOCTYPE", "/", null, null, false]]},
+
+{"description":"<!DOCTYPE 0",
+"input":"<!DOCTYPE 0",
+"output":["ParseError", ["DOCTYPE", "0", null, null, false]]},
+
+{"description":"<!DOCTYPE 1",
+"input":"<!DOCTYPE 1",
+"output":["ParseError", ["DOCTYPE", "1", null, null, false]]},
+
+{"description":"<!DOCTYPE 9",
+"input":"<!DOCTYPE 9",
+"output":["ParseError", ["DOCTYPE", "9", null, null, false]]},
+
+{"description":"<!DOCTYPE <",
+"input":"<!DOCTYPE <",
+"output":["ParseError", ["DOCTYPE", "<", null, null, false]]},
+
+{"description":"<!DOCTYPE =",
+"input":"<!DOCTYPE =",
+"output":["ParseError", ["DOCTYPE", "=", null, null, false]]},
+
+{"description":"<!DOCTYPE >",
+"input":"<!DOCTYPE >",
+"output":["ParseError", ["DOCTYPE", null, null, null, false]]},
+
+{"description":"<!DOCTYPE ?",
+"input":"<!DOCTYPE ?",
+"output":["ParseError", ["DOCTYPE", "?", null, null, false]]},
+
+{"description":"<!DOCTYPE @",
+"input":"<!DOCTYPE @",
+"output":["ParseError", ["DOCTYPE", "@", null, null, false]]},
+
+{"description":"<!DOCTYPE A",
+"input":"<!DOCTYPE A",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE B",
+"input":"<!DOCTYPE B",
+"output":["ParseError", ["DOCTYPE", "b", null, null, false]]},
+
+{"description":"<!DOCTYPE Y",
+"input":"<!DOCTYPE Y",
+"output":["ParseError", ["DOCTYPE", "y", null, null, false]]},
+
+{"description":"<!DOCTYPE Z",
+"input":"<!DOCTYPE Z",
+"output":["ParseError", ["DOCTYPE", "z", null, null, false]]},
+
+{"description":"<!DOCTYPE [",
+"input":"<!DOCTYPE [",
+"output":["ParseError", ["DOCTYPE", "[", null, null, false]]},
+
+{"description":"<!DOCTYPE `",
+"input":"<!DOCTYPE `",
+"output":["ParseError", ["DOCTYPE", "`", null, null, false]]},
+
+{"description":"<!DOCTYPE a",
+"input":"<!DOCTYPE a",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a\\u0000",
+"input":"<!DOCTYPE a\u0000",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a\uFFFD", null, null, false]]},
+
+{"description":"<!DOCTYPE a\\u0008",
+"input":"<!DOCTYPE a\u0008",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a\u0008", null, null, false]]},
+
+{"description":"<!DOCTYPE a\\u0009",
+"input":"<!DOCTYPE a\u0009",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a\\u000A",
+"input":"<!DOCTYPE a\u000A",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a\\u000B",
+"input":"<!DOCTYPE a\u000B",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a\u000B", null, null, false]]},
+
+{"description":"<!DOCTYPE a\\u000C",
+"input":"<!DOCTYPE a\u000C",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a\\u000D",
+"input":"<!DOCTYPE a\u000D",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a\\u001F",
+"input":"<!DOCTYPE a\u001F",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a\u001F", null, null, false]]},
+
+{"description":"<!DOCTYPE a ",
+"input":"<!DOCTYPE a ",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a \\u0000",
+"input":"<!DOCTYPE a \u0000",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a \\u0008",
+"input":"<!DOCTYPE a \u0008",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a \\u0009",
+"input":"<!DOCTYPE a \u0009",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a \\u000A",
+"input":"<!DOCTYPE a \u000A",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a \\u000B",
+"input":"<!DOCTYPE a \u000B",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a \\u000C",
+"input":"<!DOCTYPE a \u000C",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a \\u000D",
+"input":"<!DOCTYPE a \u000D",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a \\u001F",
+"input":"<!DOCTYPE a \u001F",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a ",
+"input":"<!DOCTYPE a ",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a !",
+"input":"<!DOCTYPE a !",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a \"",
+"input":"<!DOCTYPE a \"",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a &",
+"input":"<!DOCTYPE a &",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a '",
+"input":"<!DOCTYPE a '",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a -",
+"input":"<!DOCTYPE a -",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a /",
+"input":"<!DOCTYPE a /",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a 0",
+"input":"<!DOCTYPE a 0",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a 1",
+"input":"<!DOCTYPE a 1",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a 9",
+"input":"<!DOCTYPE a 9",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a <",
+"input":"<!DOCTYPE a <",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a =",
+"input":"<!DOCTYPE a =",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a >",
+"input":"<!DOCTYPE a >",
+"output":[["DOCTYPE", "a", null, null, true]]},
+
+{"description":"<!DOCTYPE a ?",
+"input":"<!DOCTYPE a ?",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a @",
+"input":"<!DOCTYPE a @",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a A",
+"input":"<!DOCTYPE a A",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a B",
+"input":"<!DOCTYPE a B",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC",
+"input":"<!DOCTYPE a PUBLIC",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC\\u0000",
+"input":"<!DOCTYPE a PUBLIC\u0000",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC\\u0008",
+"input":"<!DOCTYPE a PUBLIC\u0008",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC\\u0009",
+"input":"<!DOCTYPE a PUBLIC\u0009",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC\\u000A",
+"input":"<!DOCTYPE a PUBLIC\u000A",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC\\u000B",
+"input":"<!DOCTYPE a PUBLIC\u000B",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC\\u000C",
+"input":"<!DOCTYPE a PUBLIC\u000C",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC\\u000D",
+"input":"<!DOCTYPE a PUBLIC\u000D",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC\\u001F",
+"input":"<!DOCTYPE a PUBLIC\u001F",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC ",
+"input":"<!DOCTYPE a PUBLIC ",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC!",
+"input":"<!DOCTYPE a PUBLIC!",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC\"",
+"input":"<!DOCTYPE a PUBLIC\"",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC\"\\u0000",
+"input":"<!DOCTYPE a PUBLIC\"\u0000",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "\uFFFD", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC\"\\u0009",
+"input":"<!DOCTYPE a PUBLIC\"\u0009",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "\u0009", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC\"\\u000A",
+"input":"<!DOCTYPE a PUBLIC\"\u000A",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "\u000A", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC\"\\u000B",
+"input":"<!DOCTYPE a PUBLIC\"\u000B",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "\u000B", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC\"\\u000C",
+"input":"<!DOCTYPE a PUBLIC\"\u000C",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "\u000C", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC\" ",
+"input":"<!DOCTYPE a PUBLIC\" ",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", " ", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC\"!",
+"input":"<!DOCTYPE a PUBLIC\"!",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "!", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC\"\"",
+"input":"<!DOCTYPE a PUBLIC\"\"",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC\"#",
+"input":"<!DOCTYPE a PUBLIC\"#",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "#", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC\"&",
+"input":"<!DOCTYPE a PUBLIC\"&",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "&", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC\"'",
+"input":"<!DOCTYPE a PUBLIC\"'",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "'", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC\"-",
+"input":"<!DOCTYPE a PUBLIC\"-",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "-", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC\"/",
+"input":"<!DOCTYPE a PUBLIC\"/",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "/", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC\"0",
+"input":"<!DOCTYPE a PUBLIC\"0",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "0", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC\"1",
+"input":"<!DOCTYPE a PUBLIC\"1",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "1", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC\"9",
+"input":"<!DOCTYPE a PUBLIC\"9",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "9", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC\"<",
+"input":"<!DOCTYPE a PUBLIC\"<",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "<", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC\"=",
+"input":"<!DOCTYPE a PUBLIC\"=",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "=", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC\">",
+"input":"<!DOCTYPE a PUBLIC\">",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC\"?",
+"input":"<!DOCTYPE a PUBLIC\"?",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "?", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC\"@",
+"input":"<!DOCTYPE a PUBLIC\"@",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "@", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC\"A",
+"input":"<!DOCTYPE a PUBLIC\"A",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "A", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC\"B",
+"input":"<!DOCTYPE a PUBLIC\"B",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "B", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC\"Y",
+"input":"<!DOCTYPE a PUBLIC\"Y",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "Y", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC\"Z",
+"input":"<!DOCTYPE a PUBLIC\"Z",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "Z", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC\"`",
+"input":"<!DOCTYPE a PUBLIC\"`",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "`", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC\"a",
+"input":"<!DOCTYPE a PUBLIC\"a",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "a", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC\"b",
+"input":"<!DOCTYPE a PUBLIC\"b",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "b", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC\"y",
+"input":"<!DOCTYPE a PUBLIC\"y",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "y", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC\"z",
+"input":"<!DOCTYPE a PUBLIC\"z",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "z", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC\"{",
+"input":"<!DOCTYPE a PUBLIC\"{",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "{", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC\"\\uDBC0\\uDC00",
+"input":"<!DOCTYPE a PUBLIC\"\uDBC0\uDC00",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "\uDBC0\uDC00", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC#",
+"input":"<!DOCTYPE a PUBLIC#",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC&",
+"input":"<!DOCTYPE a PUBLIC&",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC'",
+"input":"<!DOCTYPE a PUBLIC'",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC'\\u0000",
+"input":"<!DOCTYPE a PUBLIC'\u0000",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "\uFFFD", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC'\\u0009",
+"input":"<!DOCTYPE a PUBLIC'\u0009",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "\u0009", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC'\\u000A",
+"input":"<!DOCTYPE a PUBLIC'\u000A",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "\u000A", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC'\\u000B",
+"input":"<!DOCTYPE a PUBLIC'\u000B",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "\u000B", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC'\\u000C",
+"input":"<!DOCTYPE a PUBLIC'\u000C",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "\u000C", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC' ",
+"input":"<!DOCTYPE a PUBLIC' ",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", " ", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC'!",
+"input":"<!DOCTYPE a PUBLIC'!",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "!", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC'\"",
+"input":"<!DOCTYPE a PUBLIC'\"",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "\"", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC'&",
+"input":"<!DOCTYPE a PUBLIC'&",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "&", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC''",
+"input":"<!DOCTYPE a PUBLIC''",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC''\\u0000",
+"input":"<!DOCTYPE a PUBLIC''\u0000",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC''\\u0008",
+"input":"<!DOCTYPE a PUBLIC''\u0008",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC''\\u0009",
+"input":"<!DOCTYPE a PUBLIC''\u0009",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC''\\u000A",
+"input":"<!DOCTYPE a PUBLIC''\u000A",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC''\\u000B",
+"input":"<!DOCTYPE a PUBLIC''\u000B",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC''\\u000C",
+"input":"<!DOCTYPE a PUBLIC''\u000C",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC''\\u000D",
+"input":"<!DOCTYPE a PUBLIC''\u000D",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC''\\u001F",
+"input":"<!DOCTYPE a PUBLIC''\u001F",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC'' ",
+"input":"<!DOCTYPE a PUBLIC'' ",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC''!",
+"input":"<!DOCTYPE a PUBLIC''!",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC''\"",
+"input":"<!DOCTYPE a PUBLIC''\"",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", "", false]]},
+
+{"description":"<!DOCTYPE a PUBLIC''#",
+"input":"<!DOCTYPE a PUBLIC''#",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC''&",
+"input":"<!DOCTYPE a PUBLIC''&",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC'''",
+"input":"<!DOCTYPE a PUBLIC'''",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", "", false]]},
+
+{"description":"<!DOCTYPE a PUBLIC''(",
+"input":"<!DOCTYPE a PUBLIC''(",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC''-",
+"input":"<!DOCTYPE a PUBLIC''-",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC''/",
+"input":"<!DOCTYPE a PUBLIC''/",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC''0",
+"input":"<!DOCTYPE a PUBLIC''0",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC''1",
+"input":"<!DOCTYPE a PUBLIC''1",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC''9",
+"input":"<!DOCTYPE a PUBLIC''9",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC''<",
+"input":"<!DOCTYPE a PUBLIC''<",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC''=",
+"input":"<!DOCTYPE a PUBLIC''=",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC''>",
+"input":"<!DOCTYPE a PUBLIC''>",
+"output":["ParseError", ["DOCTYPE", "a", "", null, true]]},
+
+{"description":"<!DOCTYPE a PUBLIC''?",
+"input":"<!DOCTYPE a PUBLIC''?",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC''@",
+"input":"<!DOCTYPE a PUBLIC''@",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC''A",
+"input":"<!DOCTYPE a PUBLIC''A",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC''B",
+"input":"<!DOCTYPE a PUBLIC''B",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC''Y",
+"input":"<!DOCTYPE a PUBLIC''Y",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC''Z",
+"input":"<!DOCTYPE a PUBLIC''Z",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC''`",
+"input":"<!DOCTYPE a PUBLIC''`",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC''a",
+"input":"<!DOCTYPE a PUBLIC''a",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC''b",
+"input":"<!DOCTYPE a PUBLIC''b",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC''y",
+"input":"<!DOCTYPE a PUBLIC''y",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC''z",
+"input":"<!DOCTYPE a PUBLIC''z",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC''{",
+"input":"<!DOCTYPE a PUBLIC''{",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC''\\uDBC0\\uDC00",
+"input":"<!DOCTYPE a PUBLIC''\uDBC0\uDC00",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC'(",
+"input":"<!DOCTYPE a PUBLIC'(",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "(", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC'-",
+"input":"<!DOCTYPE a PUBLIC'-",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "-", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC'/",
+"input":"<!DOCTYPE a PUBLIC'/",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "/", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC'0",
+"input":"<!DOCTYPE a PUBLIC'0",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "0", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC'1",
+"input":"<!DOCTYPE a PUBLIC'1",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "1", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC'9",
+"input":"<!DOCTYPE a PUBLIC'9",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "9", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC'<",
+"input":"<!DOCTYPE a PUBLIC'<",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "<", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC'=",
+"input":"<!DOCTYPE a PUBLIC'=",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "=", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC'>",
+"input":"<!DOCTYPE a PUBLIC'>",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC'?",
+"input":"<!DOCTYPE a PUBLIC'?",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "?", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC'@",
+"input":"<!DOCTYPE a PUBLIC'@",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "@", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC'A",
+"input":"<!DOCTYPE a PUBLIC'A",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "A", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC'B",
+"input":"<!DOCTYPE a PUBLIC'B",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "B", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC'Y",
+"input":"<!DOCTYPE a PUBLIC'Y",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "Y", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC'Z",
+"input":"<!DOCTYPE a PUBLIC'Z",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "Z", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC'`",
+"input":"<!DOCTYPE a PUBLIC'`",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "`", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC'a",
+"input":"<!DOCTYPE a PUBLIC'a",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "a", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC'b",
+"input":"<!DOCTYPE a PUBLIC'b",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "b", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC'y",
+"input":"<!DOCTYPE a PUBLIC'y",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "y", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC'z",
+"input":"<!DOCTYPE a PUBLIC'z",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "z", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC'{",
+"input":"<!DOCTYPE a PUBLIC'{",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "{", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC'\\uDBC0\\uDC00",
+"input":"<!DOCTYPE a PUBLIC'\uDBC0\uDC00",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "\uDBC0\uDC00", null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC(",
+"input":"<!DOCTYPE a PUBLIC(",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC-",
+"input":"<!DOCTYPE a PUBLIC-",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC/",
+"input":"<!DOCTYPE a PUBLIC/",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC0",
+"input":"<!DOCTYPE a PUBLIC0",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC1",
+"input":"<!DOCTYPE a PUBLIC1",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC9",
+"input":"<!DOCTYPE a PUBLIC9",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC<",
+"input":"<!DOCTYPE a PUBLIC<",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC=",
+"input":"<!DOCTYPE a PUBLIC=",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC>",
+"input":"<!DOCTYPE a PUBLIC>",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC?",
+"input":"<!DOCTYPE a PUBLIC?",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC@",
+"input":"<!DOCTYPE a PUBLIC@",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a PUBLICA",
+"input":"<!DOCTYPE a PUBLICA",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a PUBLICB",
+"input":"<!DOCTYPE a PUBLICB",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a PUBLICY",
+"input":"<!DOCTYPE a PUBLICY",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a PUBLICZ",
+"input":"<!DOCTYPE a PUBLICZ",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC`",
+"input":"<!DOCTYPE a PUBLIC`",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a PUBLICa",
+"input":"<!DOCTYPE a PUBLICa",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a PUBLICb",
+"input":"<!DOCTYPE a PUBLICb",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a PUBLICy",
+"input":"<!DOCTYPE a PUBLICy",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a PUBLICz",
+"input":"<!DOCTYPE a PUBLICz",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC{",
+"input":"<!DOCTYPE a PUBLIC{",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a PUBLIC\\uDBC0\\uDC00",
+"input":"<!DOCTYPE a PUBLIC\uDBC0\uDC00",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a SYSTEM",
+"input":"<!DOCTYPE a SYSTEM",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a SYSTEM\\u0000",
+"input":"<!DOCTYPE a SYSTEM\u0000",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a SYSTEM\\u0008",
+"input":"<!DOCTYPE a SYSTEM\u0008",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a SYSTEM\\u0009",
+"input":"<!DOCTYPE a SYSTEM\u0009",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a SYSTEM\\u000A",
+"input":"<!DOCTYPE a SYSTEM\u000A",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a SYSTEM\\u000B",
+"input":"<!DOCTYPE a SYSTEM\u000B",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a SYSTEM\\u000C",
+"input":"<!DOCTYPE a SYSTEM\u000C",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a SYSTEM\\u000D",
+"input":"<!DOCTYPE a SYSTEM\u000D",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a SYSTEM\\u001F",
+"input":"<!DOCTYPE a SYSTEM\u001F",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a SYSTEM ",
+"input":"<!DOCTYPE a SYSTEM ",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a SYSTEM!",
+"input":"<!DOCTYPE a SYSTEM!",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a SYSTEM\"",
+"input":"<!DOCTYPE a SYSTEM\"",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM\"\\u0000",
+"input":"<!DOCTYPE a SYSTEM\"\u0000",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "\uFFFD", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM\"\\u0009",
+"input":"<!DOCTYPE a SYSTEM\"\u0009",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "\u0009", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM\"\\u000A",
+"input":"<!DOCTYPE a SYSTEM\"\u000A",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "\u000A", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM\"\\u000B",
+"input":"<!DOCTYPE a SYSTEM\"\u000B",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "\u000B", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM\"\\u000C",
+"input":"<!DOCTYPE a SYSTEM\"\u000C",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "\u000C", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM\" ",
+"input":"<!DOCTYPE a SYSTEM\" ",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, " ", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM\"!",
+"input":"<!DOCTYPE a SYSTEM\"!",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "!", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM\"\"",
+"input":"<!DOCTYPE a SYSTEM\"\"",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM\"#",
+"input":"<!DOCTYPE a SYSTEM\"#",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "#", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM\"&",
+"input":"<!DOCTYPE a SYSTEM\"&",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "&", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM\"'",
+"input":"<!DOCTYPE a SYSTEM\"'",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "'", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM\"-",
+"input":"<!DOCTYPE a SYSTEM\"-",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "-", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM\"/",
+"input":"<!DOCTYPE a SYSTEM\"/",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "/", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM\"0",
+"input":"<!DOCTYPE a SYSTEM\"0",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "0", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM\"1",
+"input":"<!DOCTYPE a SYSTEM\"1",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "1", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM\"9",
+"input":"<!DOCTYPE a SYSTEM\"9",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "9", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM\"<",
+"input":"<!DOCTYPE a SYSTEM\"<",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "<", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM\"=",
+"input":"<!DOCTYPE a SYSTEM\"=",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "=", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM\">",
+"input":"<!DOCTYPE a SYSTEM\">",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM\"?",
+"input":"<!DOCTYPE a SYSTEM\"?",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "?", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM\"@",
+"input":"<!DOCTYPE a SYSTEM\"@",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "@", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM\"A",
+"input":"<!DOCTYPE a SYSTEM\"A",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "A", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM\"B",
+"input":"<!DOCTYPE a SYSTEM\"B",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "B", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM\"Y",
+"input":"<!DOCTYPE a SYSTEM\"Y",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "Y", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM\"Z",
+"input":"<!DOCTYPE a SYSTEM\"Z",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "Z", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM\"`",
+"input":"<!DOCTYPE a SYSTEM\"`",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "`", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM\"a",
+"input":"<!DOCTYPE a SYSTEM\"a",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "a", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM\"b",
+"input":"<!DOCTYPE a SYSTEM\"b",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "b", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM\"y",
+"input":"<!DOCTYPE a SYSTEM\"y",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "y", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM\"z",
+"input":"<!DOCTYPE a SYSTEM\"z",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "z", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM\"{",
+"input":"<!DOCTYPE a SYSTEM\"{",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "{", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM\"\\uDBC0\\uDC00",
+"input":"<!DOCTYPE a SYSTEM\"\uDBC0\uDC00",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "\uDBC0\uDC00", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM#",
+"input":"<!DOCTYPE a SYSTEM#",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a SYSTEM&",
+"input":"<!DOCTYPE a SYSTEM&",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a SYSTEM'",
+"input":"<!DOCTYPE a SYSTEM'",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM'\\u0000",
+"input":"<!DOCTYPE a SYSTEM'\u0000",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "\uFFFD", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM'\\u0009",
+"input":"<!DOCTYPE a SYSTEM'\u0009",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "\u0009", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM'\\u000A",
+"input":"<!DOCTYPE a SYSTEM'\u000A",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "\u000A", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM'\\u000B",
+"input":"<!DOCTYPE a SYSTEM'\u000B",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "\u000B", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM'\\u000C",
+"input":"<!DOCTYPE a SYSTEM'\u000C",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "\u000C", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM' ",
+"input":"<!DOCTYPE a SYSTEM' ",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, " ", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM'!",
+"input":"<!DOCTYPE a SYSTEM'!",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "!", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM'\"",
+"input":"<!DOCTYPE a SYSTEM'\"",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "\"", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM'&",
+"input":"<!DOCTYPE a SYSTEM'&",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "&", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM''",
+"input":"<!DOCTYPE a SYSTEM''",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM''\\u0000",
+"input":"<!DOCTYPE a SYSTEM''\u0000",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPE a SYSTEM''\\u0008",
+"input":"<!DOCTYPE a SYSTEM''\u0008",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPE a SYSTEM''\\u0009",
+"input":"<!DOCTYPE a SYSTEM''\u0009",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM''\\u000A",
+"input":"<!DOCTYPE a SYSTEM''\u000A",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM''\\u000B",
+"input":"<!DOCTYPE a SYSTEM''\u000B",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPE a SYSTEM''\\u000C",
+"input":"<!DOCTYPE a SYSTEM''\u000C",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM''\\u000D",
+"input":"<!DOCTYPE a SYSTEM''\u000D",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM''\\u001F",
+"input":"<!DOCTYPE a SYSTEM''\u001F",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPE a SYSTEM'' ",
+"input":"<!DOCTYPE a SYSTEM'' ",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM''!",
+"input":"<!DOCTYPE a SYSTEM''!",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPE a SYSTEM''\"",
+"input":"<!DOCTYPE a SYSTEM''\"",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPE a SYSTEM''&",
+"input":"<!DOCTYPE a SYSTEM''&",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPE a SYSTEM'''",
+"input":"<!DOCTYPE a SYSTEM'''",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPE a SYSTEM''-",
+"input":"<!DOCTYPE a SYSTEM''-",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPE a SYSTEM''/",
+"input":"<!DOCTYPE a SYSTEM''/",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPE a SYSTEM''0",
+"input":"<!DOCTYPE a SYSTEM''0",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPE a SYSTEM''1",
+"input":"<!DOCTYPE a SYSTEM''1",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPE a SYSTEM''9",
+"input":"<!DOCTYPE a SYSTEM''9",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPE a SYSTEM''<",
+"input":"<!DOCTYPE a SYSTEM''<",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPE a SYSTEM''=",
+"input":"<!DOCTYPE a SYSTEM''=",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPE a SYSTEM''>",
+"input":"<!DOCTYPE a SYSTEM''>",
+"output":["ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPE a SYSTEM''?",
+"input":"<!DOCTYPE a SYSTEM''?",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPE a SYSTEM''@",
+"input":"<!DOCTYPE a SYSTEM''@",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPE a SYSTEM''A",
+"input":"<!DOCTYPE a SYSTEM''A",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPE a SYSTEM''B",
+"input":"<!DOCTYPE a SYSTEM''B",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPE a SYSTEM''Y",
+"input":"<!DOCTYPE a SYSTEM''Y",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPE a SYSTEM''Z",
+"input":"<!DOCTYPE a SYSTEM''Z",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPE a SYSTEM''`",
+"input":"<!DOCTYPE a SYSTEM''`",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPE a SYSTEM''a",
+"input":"<!DOCTYPE a SYSTEM''a",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPE a SYSTEM''b",
+"input":"<!DOCTYPE a SYSTEM''b",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPE a SYSTEM''y",
+"input":"<!DOCTYPE a SYSTEM''y",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPE a SYSTEM''z",
+"input":"<!DOCTYPE a SYSTEM''z",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPE a SYSTEM''{",
+"input":"<!DOCTYPE a SYSTEM''{",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPE a SYSTEM''\\uDBC0\\uDC00",
+"input":"<!DOCTYPE a SYSTEM''\uDBC0\uDC00",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPE a SYSTEM'(",
+"input":"<!DOCTYPE a SYSTEM'(",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "(", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM'-",
+"input":"<!DOCTYPE a SYSTEM'-",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "-", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM'/",
+"input":"<!DOCTYPE a SYSTEM'/",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "/", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM'0",
+"input":"<!DOCTYPE a SYSTEM'0",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "0", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM'1",
+"input":"<!DOCTYPE a SYSTEM'1",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "1", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM'9",
+"input":"<!DOCTYPE a SYSTEM'9",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "9", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM'<",
+"input":"<!DOCTYPE a SYSTEM'<",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "<", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM'=",
+"input":"<!DOCTYPE a SYSTEM'=",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "=", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM'>",
+"input":"<!DOCTYPE a SYSTEM'>",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM'?",
+"input":"<!DOCTYPE a SYSTEM'?",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "?", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM'@",
+"input":"<!DOCTYPE a SYSTEM'@",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "@", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM'A",
+"input":"<!DOCTYPE a SYSTEM'A",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "A", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM'B",
+"input":"<!DOCTYPE a SYSTEM'B",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "B", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM'Y",
+"input":"<!DOCTYPE a SYSTEM'Y",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "Y", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM'Z",
+"input":"<!DOCTYPE a SYSTEM'Z",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "Z", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM'`",
+"input":"<!DOCTYPE a SYSTEM'`",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "`", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM'a",
+"input":"<!DOCTYPE a SYSTEM'a",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "a", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM'b",
+"input":"<!DOCTYPE a SYSTEM'b",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "b", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM'y",
+"input":"<!DOCTYPE a SYSTEM'y",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "y", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM'z",
+"input":"<!DOCTYPE a SYSTEM'z",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "z", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM'{",
+"input":"<!DOCTYPE a SYSTEM'{",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "{", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM'\\uDBC0\\uDC00",
+"input":"<!DOCTYPE a SYSTEM'\uDBC0\uDC00",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "\uDBC0\uDC00", false]]},
+
+{"description":"<!DOCTYPE a SYSTEM(",
+"input":"<!DOCTYPE a SYSTEM(",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a SYSTEM-",
+"input":"<!DOCTYPE a SYSTEM-",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a SYSTEM/",
+"input":"<!DOCTYPE a SYSTEM/",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a SYSTEM0",
+"input":"<!DOCTYPE a SYSTEM0",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a SYSTEM1",
+"input":"<!DOCTYPE a SYSTEM1",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a SYSTEM9",
+"input":"<!DOCTYPE a SYSTEM9",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a SYSTEM<",
+"input":"<!DOCTYPE a SYSTEM<",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a SYSTEM=",
+"input":"<!DOCTYPE a SYSTEM=",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a SYSTEM>",
+"input":"<!DOCTYPE a SYSTEM>",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a SYSTEM?",
+"input":"<!DOCTYPE a SYSTEM?",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a SYSTEM@",
+"input":"<!DOCTYPE a SYSTEM@",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a SYSTEMA",
+"input":"<!DOCTYPE a SYSTEMA",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a SYSTEMB",
+"input":"<!DOCTYPE a SYSTEMB",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a SYSTEMY",
+"input":"<!DOCTYPE a SYSTEMY",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a SYSTEMZ",
+"input":"<!DOCTYPE a SYSTEMZ",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a SYSTEM`",
+"input":"<!DOCTYPE a SYSTEM`",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a SYSTEMa",
+"input":"<!DOCTYPE a SYSTEMa",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a SYSTEMb",
+"input":"<!DOCTYPE a SYSTEMb",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a SYSTEMy",
+"input":"<!DOCTYPE a SYSTEMy",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a SYSTEMz",
+"input":"<!DOCTYPE a SYSTEMz",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a SYSTEM{",
+"input":"<!DOCTYPE a SYSTEM{",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a SYSTEM\\uDBC0\\uDC00",
+"input":"<!DOCTYPE a SYSTEM\uDBC0\uDC00",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a Y",
+"input":"<!DOCTYPE a Y",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a Z",
+"input":"<!DOCTYPE a Z",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a `",
+"input":"<!DOCTYPE a `",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a a",
+"input":"<!DOCTYPE a a",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a a\\u0000",
+"input":"<!DOCTYPE a a\u0000",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a a\\u0009",
+"input":"<!DOCTYPE a a\u0009",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a a\\u000A",
+"input":"<!DOCTYPE a a\u000A",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a a\\u000B",
+"input":"<!DOCTYPE a a\u000B",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a a\\u000C",
+"input":"<!DOCTYPE a a\u000C",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a a ",
+"input":"<!DOCTYPE a a ",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a a!",
+"input":"<!DOCTYPE a a!",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a a\"",
+"input":"<!DOCTYPE a a\"",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a a&",
+"input":"<!DOCTYPE a a&",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a a'",
+"input":"<!DOCTYPE a a'",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a a-",
+"input":"<!DOCTYPE a a-",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a a/",
+"input":"<!DOCTYPE a a/",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a a0",
+"input":"<!DOCTYPE a a0",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a a1",
+"input":"<!DOCTYPE a a1",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a a9",
+"input":"<!DOCTYPE a a9",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a a<",
+"input":"<!DOCTYPE a a<",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a a=",
+"input":"<!DOCTYPE a a=",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a a>",
+"input":"<!DOCTYPE a a>",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a a?",
+"input":"<!DOCTYPE a a?",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a a@",
+"input":"<!DOCTYPE a a@",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a aA",
+"input":"<!DOCTYPE a aA",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a aB",
+"input":"<!DOCTYPE a aB",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a aY",
+"input":"<!DOCTYPE a aY",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a aZ",
+"input":"<!DOCTYPE a aZ",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a a`",
+"input":"<!DOCTYPE a a`",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a aa",
+"input":"<!DOCTYPE a aa",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a ab",
+"input":"<!DOCTYPE a ab",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a ay",
+"input":"<!DOCTYPE a ay",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a az",
+"input":"<!DOCTYPE a az",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a a{",
+"input":"<!DOCTYPE a a{",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a a\\uDBC0\\uDC00",
+"input":"<!DOCTYPE a a\uDBC0\uDC00",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a b",
+"input":"<!DOCTYPE a b",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a y",
+"input":"<!DOCTYPE a y",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a z",
+"input":"<!DOCTYPE a z",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a {",
+"input":"<!DOCTYPE a {",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a \\uDBC0\\uDC00",
+"input":"<!DOCTYPE a \uDBC0\uDC00",
+"output":["ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPE a!",
+"input":"<!DOCTYPE a!",
+"output":["ParseError", ["DOCTYPE", "a!", null, null, false]]},
+
+{"description":"<!DOCTYPE a\"",
+"input":"<!DOCTYPE a\"",
+"output":["ParseError", ["DOCTYPE", "a\"", null, null, false]]},
+
+{"description":"<!DOCTYPE a&",
+"input":"<!DOCTYPE a&",
+"output":["ParseError", ["DOCTYPE", "a&", null, null, false]]},
+
+{"description":"<!DOCTYPE a'",
+"input":"<!DOCTYPE a'",
+"output":["ParseError", ["DOCTYPE", "a'", null, null, false]]},
+
+{"description":"<!DOCTYPE a-",
+"input":"<!DOCTYPE a-",
+"output":["ParseError", ["DOCTYPE", "a-", null, null, false]]},
+
+{"description":"<!DOCTYPE a/",
+"input":"<!DOCTYPE a/",
+"output":["ParseError", ["DOCTYPE", "a/", null, null, false]]},
+
+{"description":"<!DOCTYPE a0",
+"input":"<!DOCTYPE a0",
+"output":["ParseError", ["DOCTYPE", "a0", null, null, false]]},
+
+{"description":"<!DOCTYPE a1",
+"input":"<!DOCTYPE a1",
+"output":["ParseError", ["DOCTYPE", "a1", null, null, false]]},
+
+{"description":"<!DOCTYPE a9",
+"input":"<!DOCTYPE a9",
+"output":["ParseError", ["DOCTYPE", "a9", null, null, false]]},
+
+{"description":"<!DOCTYPE a<",
+"input":"<!DOCTYPE a<",
+"output":["ParseError", ["DOCTYPE", "a<", null, null, false]]},
+
+{"description":"<!DOCTYPE a=",
+"input":"<!DOCTYPE a=",
+"output":["ParseError", ["DOCTYPE", "a=", null, null, false]]},
+
+{"description":"<!DOCTYPE a>",
+"input":"<!DOCTYPE a>",
+"output":[["DOCTYPE", "a", null, null, true]]},
+
+{"description":"<!DOCTYPE a?",
+"input":"<!DOCTYPE a?",
+"output":["ParseError", ["DOCTYPE", "a?", null, null, false]]},
+
+{"description":"<!DOCTYPE a@",
+"input":"<!DOCTYPE a@",
+"output":["ParseError", ["DOCTYPE", "a@", null, null, false]]},
+
+{"description":"<!DOCTYPE aA",
+"input":"<!DOCTYPE aA",
+"output":["ParseError", ["DOCTYPE", "aa", null, null, false]]},
+
+{"description":"<!DOCTYPE aB",
+"input":"<!DOCTYPE aB",
+"output":["ParseError", ["DOCTYPE", "ab", null, null, false]]},
+
+{"description":"<!DOCTYPE aY",
+"input":"<!DOCTYPE aY",
+"output":["ParseError", ["DOCTYPE", "ay", null, null, false]]},
+
+{"description":"<!DOCTYPE aZ",
+"input":"<!DOCTYPE aZ",
+"output":["ParseError", ["DOCTYPE", "az", null, null, false]]},
+
+{"description":"<!DOCTYPE a[",
+"input":"<!DOCTYPE a[",
+"output":["ParseError", ["DOCTYPE", "a[", null, null, false]]},
+
+{"description":"<!DOCTYPE a`",
+"input":"<!DOCTYPE a`",
+"output":["ParseError", ["DOCTYPE", "a`", null, null, false]]},
+
+{"description":"<!DOCTYPE aa",
+"input":"<!DOCTYPE aa",
+"output":["ParseError", ["DOCTYPE", "aa", null, null, false]]},
+
+{"description":"<!DOCTYPE ab",
+"input":"<!DOCTYPE ab",
+"output":["ParseError", ["DOCTYPE", "ab", null, null, false]]},
+
+{"description":"<!DOCTYPE ay",
+"input":"<!DOCTYPE ay",
+"output":["ParseError", ["DOCTYPE", "ay", null, null, false]]},
+
+{"description":"<!DOCTYPE az",
+"input":"<!DOCTYPE az",
+"output":["ParseError", ["DOCTYPE", "az", null, null, false]]},
+
+{"description":"<!DOCTYPE a{",
+"input":"<!DOCTYPE a{",
+"output":["ParseError", ["DOCTYPE", "a{", null, null, false]]},
+
+{"description":"<!DOCTYPE a\\uDBC0\\uDC00",
+"input":"<!DOCTYPE a\uDBC0\uDC00",
+"output":["ParseError", ["DOCTYPE", "a\uDBC0\uDC00", null, null, false]]},
+
+{"description":"<!DOCTYPE b",
+"input":"<!DOCTYPE b",
+"output":["ParseError", ["DOCTYPE", "b", null, null, false]]},
+
+{"description":"<!DOCTYPE y",
+"input":"<!DOCTYPE y",
+"output":["ParseError", ["DOCTYPE", "y", null, null, false]]},
+
+{"description":"<!DOCTYPE z",
+"input":"<!DOCTYPE z",
+"output":["ParseError", ["DOCTYPE", "z", null, null, false]]},
+
+{"description":"<!DOCTYPE {",
+"input":"<!DOCTYPE {",
+"output":["ParseError", ["DOCTYPE", "{", null, null, false]]},
+
+{"description":"<!DOCTYPE \\uDBC0\\uDC00",
+"input":"<!DOCTYPE \uDBC0\uDC00",
+"output":["ParseError", ["DOCTYPE", "\uDBC0\uDC00", null, null, false]]},
+
+{"description":"<!DOCTYPE!",
+"input":"<!DOCTYPE!",
+"output":["ParseError", "ParseError", ["DOCTYPE", "!", null, null, false]]},
+
+{"description":"<!DOCTYPE\"",
+"input":"<!DOCTYPE\"",
+"output":["ParseError", "ParseError", ["DOCTYPE", "\"", null, null, false]]},
+
+{"description":"<!DOCTYPE&",
+"input":"<!DOCTYPE&",
+"output":["ParseError", "ParseError", ["DOCTYPE", "&", null, null, false]]},
+
+{"description":"<!DOCTYPE'",
+"input":"<!DOCTYPE'",
+"output":["ParseError", "ParseError", ["DOCTYPE", "'", null, null, false]]},
+
+{"description":"<!DOCTYPE-",
+"input":"<!DOCTYPE-",
+"output":["ParseError", "ParseError", ["DOCTYPE", "-", null, null, false]]},
+
+{"description":"<!DOCTYPE/",
+"input":"<!DOCTYPE/",
+"output":["ParseError", "ParseError", ["DOCTYPE", "/", null, null, false]]},
+
+{"description":"<!DOCTYPE0",
+"input":"<!DOCTYPE0",
+"output":["ParseError", "ParseError", ["DOCTYPE", "0", null, null, false]]},
+
+{"description":"<!DOCTYPE1",
+"input":"<!DOCTYPE1",
+"output":["ParseError", "ParseError", ["DOCTYPE", "1", null, null, false]]},
+
+{"description":"<!DOCTYPE9",
+"input":"<!DOCTYPE9",
+"output":["ParseError", "ParseError", ["DOCTYPE", "9", null, null, false]]},
+
+{"description":"<!DOCTYPE<",
+"input":"<!DOCTYPE<",
+"output":["ParseError", "ParseError", ["DOCTYPE", "<", null, null, false]]},
+
+{"description":"<!DOCTYPE=",
+"input":"<!DOCTYPE=",
+"output":["ParseError", "ParseError", ["DOCTYPE", "=", null, null, false]]},
+
+{"description":"<!DOCTYPE>",
+"input":"<!DOCTYPE>",
+"output":["ParseError", "ParseError", ["DOCTYPE", null, null, null, false]]},
+
+{"description":"<!DOCTYPE?",
+"input":"<!DOCTYPE?",
+"output":["ParseError", "ParseError", ["DOCTYPE", "?", null, null, false]]},
+
+{"description":"<!DOCTYPE@",
+"input":"<!DOCTYPE@",
+"output":["ParseError", "ParseError", ["DOCTYPE", "@", null, null, false]]},
+
+{"description":"<!DOCTYPEA",
+"input":"<!DOCTYPEA",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEB",
+"input":"<!DOCTYPEB",
+"output":["ParseError", "ParseError", ["DOCTYPE", "b", null, null, false]]},
+
+{"description":"<!DOCTYPEY",
+"input":"<!DOCTYPEY",
+"output":["ParseError", "ParseError", ["DOCTYPE", "y", null, null, false]]},
+
+{"description":"<!DOCTYPEZ",
+"input":"<!DOCTYPEZ",
+"output":["ParseError", "ParseError", ["DOCTYPE", "z", null, null, false]]},
+
+{"description":"<!DOCTYPE`",
+"input":"<!DOCTYPE`",
+"output":["ParseError", "ParseError", ["DOCTYPE", "`", null, null, false]]},
+
+{"description":"<!DOCTYPEa",
+"input":"<!DOCTYPEa",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa\\u0000",
+"input":"<!DOCTYPEa\u0000",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a\uFFFD", null, null, false]]},
+
+{"description":"<!DOCTYPEa\\u0008",
+"input":"<!DOCTYPEa\u0008",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a\u0008", null, null, false]]},
+
+{"description":"<!DOCTYPEa\\u0009",
+"input":"<!DOCTYPEa\u0009",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa\\u000A",
+"input":"<!DOCTYPEa\u000A",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa\\u000B",
+"input":"<!DOCTYPEa\u000B",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a\u000B", null, null, false]]},
+
+{"description":"<!DOCTYPEa\\u000C",
+"input":"<!DOCTYPEa\u000C",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa\\u000D",
+"input":"<!DOCTYPEa\u000D",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa\\u001F",
+"input":"<!DOCTYPEa\u001F",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a\u001F", null, null, false]]},
+
+{"description":"<!DOCTYPEa ",
+"input":"<!DOCTYPEa ",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa \\u0000",
+"input":"<!DOCTYPEa \u0000",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa \\u0008",
+"input":"<!DOCTYPEa \u0008",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa \\u0009",
+"input":"<!DOCTYPEa \u0009",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa \\u000A",
+"input":"<!DOCTYPEa \u000A",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa \\u000B",
+"input":"<!DOCTYPEa \u000B",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa \\u000C",
+"input":"<!DOCTYPEa \u000C",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa \\u000D",
+"input":"<!DOCTYPEa \u000D",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa \\u001F",
+"input":"<!DOCTYPEa \u001F",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa ",
+"input":"<!DOCTYPEa ",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa !",
+"input":"<!DOCTYPEa !",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa \"",
+"input":"<!DOCTYPEa \"",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa &",
+"input":"<!DOCTYPEa &",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa '",
+"input":"<!DOCTYPEa '",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa -",
+"input":"<!DOCTYPEa -",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa /",
+"input":"<!DOCTYPEa /",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa 0",
+"input":"<!DOCTYPEa 0",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa 1",
+"input":"<!DOCTYPEa 1",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa 9",
+"input":"<!DOCTYPEa 9",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa <",
+"input":"<!DOCTYPEa <",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa =",
+"input":"<!DOCTYPEa =",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa >",
+"input":"<!DOCTYPEa >",
+"output":["ParseError", ["DOCTYPE", "a", null, null, true]]},
+
+{"description":"<!DOCTYPEa ?",
+"input":"<!DOCTYPEa ?",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa @",
+"input":"<!DOCTYPEa @",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa A",
+"input":"<!DOCTYPEa A",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa B",
+"input":"<!DOCTYPEa B",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC",
+"input":"<!DOCTYPEa PUBLIC",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC\\u0000",
+"input":"<!DOCTYPEa PUBLIC\u0000",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC\\u0008",
+"input":"<!DOCTYPEa PUBLIC\u0008",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC\\u0009",
+"input":"<!DOCTYPEa PUBLIC\u0009",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC\\u000A",
+"input":"<!DOCTYPEa PUBLIC\u000A",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC\\u000B",
+"input":"<!DOCTYPEa PUBLIC\u000B",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC\\u000C",
+"input":"<!DOCTYPEa PUBLIC\u000C",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC\\u000D",
+"input":"<!DOCTYPEa PUBLIC\u000D",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC\\u001F",
+"input":"<!DOCTYPEa PUBLIC\u001F",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC ",
+"input":"<!DOCTYPEa PUBLIC ",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC!",
+"input":"<!DOCTYPEa PUBLIC!",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC\"",
+"input":"<!DOCTYPEa PUBLIC\"",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC\"\\u0000",
+"input":"<!DOCTYPEa PUBLIC\"\u0000",
+"output":["ParseError", "ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "\uFFFD", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC\"\\u0009",
+"input":"<!DOCTYPEa PUBLIC\"\u0009",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "\u0009", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC\"\\u000A",
+"input":"<!DOCTYPEa PUBLIC\"\u000A",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "\u000A", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC\"\\u000B",
+"input":"<!DOCTYPEa PUBLIC\"\u000B",
+"output":["ParseError", "ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "\u000B", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC\"\\u000C",
+"input":"<!DOCTYPEa PUBLIC\"\u000C",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "\u000C", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC\" ",
+"input":"<!DOCTYPEa PUBLIC\" ",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", " ", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC\"!",
+"input":"<!DOCTYPEa PUBLIC\"!",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "!", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC\"\"",
+"input":"<!DOCTYPEa PUBLIC\"\"",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC\"#",
+"input":"<!DOCTYPEa PUBLIC\"#",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "#", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC\"&",
+"input":"<!DOCTYPEa PUBLIC\"&",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "&", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC\"'",
+"input":"<!DOCTYPEa PUBLIC\"'",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "'", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC\"-",
+"input":"<!DOCTYPEa PUBLIC\"-",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "-", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC\"/",
+"input":"<!DOCTYPEa PUBLIC\"/",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "/", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC\"0",
+"input":"<!DOCTYPEa PUBLIC\"0",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "0", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC\"1",
+"input":"<!DOCTYPEa PUBLIC\"1",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "1", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC\"9",
+"input":"<!DOCTYPEa PUBLIC\"9",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "9", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC\"<",
+"input":"<!DOCTYPEa PUBLIC\"<",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "<", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC\"=",
+"input":"<!DOCTYPEa PUBLIC\"=",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "=", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC\">",
+"input":"<!DOCTYPEa PUBLIC\">",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC\"?",
+"input":"<!DOCTYPEa PUBLIC\"?",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "?", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC\"@",
+"input":"<!DOCTYPEa PUBLIC\"@",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "@", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC\"A",
+"input":"<!DOCTYPEa PUBLIC\"A",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "A", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC\"B",
+"input":"<!DOCTYPEa PUBLIC\"B",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "B", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC\"Y",
+"input":"<!DOCTYPEa PUBLIC\"Y",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "Y", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC\"Z",
+"input":"<!DOCTYPEa PUBLIC\"Z",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "Z", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC\"`",
+"input":"<!DOCTYPEa PUBLIC\"`",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "`", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC\"a",
+"input":"<!DOCTYPEa PUBLIC\"a",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "a", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC\"b",
+"input":"<!DOCTYPEa PUBLIC\"b",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "b", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC\"y",
+"input":"<!DOCTYPEa PUBLIC\"y",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "y", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC\"z",
+"input":"<!DOCTYPEa PUBLIC\"z",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "z", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC\"{",
+"input":"<!DOCTYPEa PUBLIC\"{",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "{", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC\"\\uDBC0\\uDC00",
+"input":"<!DOCTYPEa PUBLIC\"\uDBC0\uDC00",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "\uDBC0\uDC00", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC#",
+"input":"<!DOCTYPEa PUBLIC#",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC&",
+"input":"<!DOCTYPEa PUBLIC&",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC'",
+"input":"<!DOCTYPEa PUBLIC'",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC'\\u0000",
+"input":"<!DOCTYPEa PUBLIC'\u0000",
+"output":["ParseError", "ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "\uFFFD", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC'\\u0009",
+"input":"<!DOCTYPEa PUBLIC'\u0009",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "\u0009", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC'\\u000A",
+"input":"<!DOCTYPEa PUBLIC'\u000A",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "\u000A", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC'\\u000B",
+"input":"<!DOCTYPEa PUBLIC'\u000B",
+"output":["ParseError", "ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "\u000B", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC'\\u000C",
+"input":"<!DOCTYPEa PUBLIC'\u000C",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "\u000C", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC' ",
+"input":"<!DOCTYPEa PUBLIC' ",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", " ", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC'!",
+"input":"<!DOCTYPEa PUBLIC'!",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "!", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC'\"",
+"input":"<!DOCTYPEa PUBLIC'\"",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "\"", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC'&",
+"input":"<!DOCTYPEa PUBLIC'&",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "&", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC''",
+"input":"<!DOCTYPEa PUBLIC''",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC''\\u0000",
+"input":"<!DOCTYPEa PUBLIC''\u0000",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC''\\u0008",
+"input":"<!DOCTYPEa PUBLIC''\u0008",
+"output":["ParseError", "ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC''\\u0009",
+"input":"<!DOCTYPEa PUBLIC''\u0009",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC''\\u000A",
+"input":"<!DOCTYPEa PUBLIC''\u000A",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC''\\u000B",
+"input":"<!DOCTYPEa PUBLIC''\u000B",
+"output":["ParseError", "ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC''\\u000C",
+"input":"<!DOCTYPEa PUBLIC''\u000C",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC''\\u000D",
+"input":"<!DOCTYPEa PUBLIC''\u000D",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC''\\u001F",
+"input":"<!DOCTYPEa PUBLIC''\u001F",
+"output":["ParseError", "ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC'' ",
+"input":"<!DOCTYPEa PUBLIC'' ",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC''!",
+"input":"<!DOCTYPEa PUBLIC''!",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC''\"",
+"input":"<!DOCTYPEa PUBLIC''\"",
+"output":["ParseError", "ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", "", false]]},
+
+{"description":"<!DOCTYPEa PUBLIC''#",
+"input":"<!DOCTYPEa PUBLIC''#",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC''&",
+"input":"<!DOCTYPEa PUBLIC''&",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC'''",
+"input":"<!DOCTYPEa PUBLIC'''",
+"output":["ParseError", "ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", "", false]]},
+
+{"description":"<!DOCTYPEa PUBLIC''(",
+"input":"<!DOCTYPEa PUBLIC''(",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC''-",
+"input":"<!DOCTYPEa PUBLIC''-",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC''/",
+"input":"<!DOCTYPEa PUBLIC''/",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC''0",
+"input":"<!DOCTYPEa PUBLIC''0",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC''1",
+"input":"<!DOCTYPEa PUBLIC''1",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC''9",
+"input":"<!DOCTYPEa PUBLIC''9",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC''<",
+"input":"<!DOCTYPEa PUBLIC''<",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC''=",
+"input":"<!DOCTYPEa PUBLIC''=",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC''>",
+"input":"<!DOCTYPEa PUBLIC''>",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, true]]},
+
+{"description":"<!DOCTYPEa PUBLIC''?",
+"input":"<!DOCTYPEa PUBLIC''?",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC''@",
+"input":"<!DOCTYPEa PUBLIC''@",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC''A",
+"input":"<!DOCTYPEa PUBLIC''A",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC''B",
+"input":"<!DOCTYPEa PUBLIC''B",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC''Y",
+"input":"<!DOCTYPEa PUBLIC''Y",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC''Z",
+"input":"<!DOCTYPEa PUBLIC''Z",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC''`",
+"input":"<!DOCTYPEa PUBLIC''`",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC''a",
+"input":"<!DOCTYPEa PUBLIC''a",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC''b",
+"input":"<!DOCTYPEa PUBLIC''b",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC''y",
+"input":"<!DOCTYPEa PUBLIC''y",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC''z",
+"input":"<!DOCTYPEa PUBLIC''z",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC''{",
+"input":"<!DOCTYPEa PUBLIC''{",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC''\\uDBC0\\uDC00",
+"input":"<!DOCTYPEa PUBLIC''\uDBC0\uDC00",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC'(",
+"input":"<!DOCTYPEa PUBLIC'(",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "(", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC'-",
+"input":"<!DOCTYPEa PUBLIC'-",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "-", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC'/",
+"input":"<!DOCTYPEa PUBLIC'/",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "/", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC'0",
+"input":"<!DOCTYPEa PUBLIC'0",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "0", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC'1",
+"input":"<!DOCTYPEa PUBLIC'1",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "1", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC'9",
+"input":"<!DOCTYPEa PUBLIC'9",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "9", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC'<",
+"input":"<!DOCTYPEa PUBLIC'<",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "<", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC'=",
+"input":"<!DOCTYPEa PUBLIC'=",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "=", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC'>",
+"input":"<!DOCTYPEa PUBLIC'>",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC'?",
+"input":"<!DOCTYPEa PUBLIC'?",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "?", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC'@",
+"input":"<!DOCTYPEa PUBLIC'@",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "@", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC'A",
+"input":"<!DOCTYPEa PUBLIC'A",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "A", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC'B",
+"input":"<!DOCTYPEa PUBLIC'B",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "B", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC'Y",
+"input":"<!DOCTYPEa PUBLIC'Y",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "Y", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC'Z",
+"input":"<!DOCTYPEa PUBLIC'Z",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "Z", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC'`",
+"input":"<!DOCTYPEa PUBLIC'`",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "`", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC'a",
+"input":"<!DOCTYPEa PUBLIC'a",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "a", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC'b",
+"input":"<!DOCTYPEa PUBLIC'b",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "b", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC'y",
+"input":"<!DOCTYPEa PUBLIC'y",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "y", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC'z",
+"input":"<!DOCTYPEa PUBLIC'z",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "z", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC'{",
+"input":"<!DOCTYPEa PUBLIC'{",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "{", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC'\\uDBC0\\uDC00",
+"input":"<!DOCTYPEa PUBLIC'\uDBC0\uDC00",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "\uDBC0\uDC00", null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC(",
+"input":"<!DOCTYPEa PUBLIC(",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC-",
+"input":"<!DOCTYPEa PUBLIC-",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC/",
+"input":"<!DOCTYPEa PUBLIC/",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC0",
+"input":"<!DOCTYPEa PUBLIC0",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC1",
+"input":"<!DOCTYPEa PUBLIC1",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC9",
+"input":"<!DOCTYPEa PUBLIC9",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC<",
+"input":"<!DOCTYPEa PUBLIC<",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC=",
+"input":"<!DOCTYPEa PUBLIC=",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC>",
+"input":"<!DOCTYPEa PUBLIC>",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC?",
+"input":"<!DOCTYPEa PUBLIC?",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC@",
+"input":"<!DOCTYPEa PUBLIC@",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa PUBLICA",
+"input":"<!DOCTYPEa PUBLICA",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa PUBLICB",
+"input":"<!DOCTYPEa PUBLICB",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa PUBLICY",
+"input":"<!DOCTYPEa PUBLICY",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa PUBLICZ",
+"input":"<!DOCTYPEa PUBLICZ",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC`",
+"input":"<!DOCTYPEa PUBLIC`",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa PUBLICa",
+"input":"<!DOCTYPEa PUBLICa",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa PUBLICb",
+"input":"<!DOCTYPEa PUBLICb",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa PUBLICy",
+"input":"<!DOCTYPEa PUBLICy",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa PUBLICz",
+"input":"<!DOCTYPEa PUBLICz",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC{",
+"input":"<!DOCTYPEa PUBLIC{",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa PUBLIC\\uDBC0\\uDC00",
+"input":"<!DOCTYPEa PUBLIC\uDBC0\uDC00",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa SYSTEM",
+"input":"<!DOCTYPEa SYSTEM",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa SYSTEM\\u0000",
+"input":"<!DOCTYPEa SYSTEM\u0000",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa SYSTEM\\u0008",
+"input":"<!DOCTYPEa SYSTEM\u0008",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa SYSTEM\\u0009",
+"input":"<!DOCTYPEa SYSTEM\u0009",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa SYSTEM\\u000A",
+"input":"<!DOCTYPEa SYSTEM\u000A",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa SYSTEM\\u000B",
+"input":"<!DOCTYPEa SYSTEM\u000B",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa SYSTEM\\u000C",
+"input":"<!DOCTYPEa SYSTEM\u000C",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa SYSTEM\\u000D",
+"input":"<!DOCTYPEa SYSTEM\u000D",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa SYSTEM\\u001F",
+"input":"<!DOCTYPEa SYSTEM\u001F",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa SYSTEM ",
+"input":"<!DOCTYPEa SYSTEM ",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa SYSTEM!",
+"input":"<!DOCTYPEa SYSTEM!",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa SYSTEM\"",
+"input":"<!DOCTYPEa SYSTEM\"",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM\"\\u0000",
+"input":"<!DOCTYPEa SYSTEM\"\u0000",
+"output":["ParseError", "ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "\uFFFD", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM\"\\u0009",
+"input":"<!DOCTYPEa SYSTEM\"\u0009",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "\u0009", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM\"\\u000A",
+"input":"<!DOCTYPEa SYSTEM\"\u000A",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "\u000A", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM\"\\u000B",
+"input":"<!DOCTYPEa SYSTEM\"\u000B",
+"output":["ParseError", "ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "\u000B", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM\"\\u000C",
+"input":"<!DOCTYPEa SYSTEM\"\u000C",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "\u000C", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM\" ",
+"input":"<!DOCTYPEa SYSTEM\" ",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, " ", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM\"!",
+"input":"<!DOCTYPEa SYSTEM\"!",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "!", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM\"\"",
+"input":"<!DOCTYPEa SYSTEM\"\"",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM\"#",
+"input":"<!DOCTYPEa SYSTEM\"#",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "#", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM\"&",
+"input":"<!DOCTYPEa SYSTEM\"&",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "&", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM\"'",
+"input":"<!DOCTYPEa SYSTEM\"'",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "'", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM\"-",
+"input":"<!DOCTYPEa SYSTEM\"-",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "-", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM\"/",
+"input":"<!DOCTYPEa SYSTEM\"/",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "/", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM\"0",
+"input":"<!DOCTYPEa SYSTEM\"0",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "0", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM\"1",
+"input":"<!DOCTYPEa SYSTEM\"1",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "1", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM\"9",
+"input":"<!DOCTYPEa SYSTEM\"9",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "9", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM\"<",
+"input":"<!DOCTYPEa SYSTEM\"<",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "<", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM\"=",
+"input":"<!DOCTYPEa SYSTEM\"=",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "=", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM\">",
+"input":"<!DOCTYPEa SYSTEM\">",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM\"?",
+"input":"<!DOCTYPEa SYSTEM\"?",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "?", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM\"@",
+"input":"<!DOCTYPEa SYSTEM\"@",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "@", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM\"A",
+"input":"<!DOCTYPEa SYSTEM\"A",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "A", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM\"B",
+"input":"<!DOCTYPEa SYSTEM\"B",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "B", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM\"Y",
+"input":"<!DOCTYPEa SYSTEM\"Y",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "Y", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM\"Z",
+"input":"<!DOCTYPEa SYSTEM\"Z",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "Z", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM\"`",
+"input":"<!DOCTYPEa SYSTEM\"`",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "`", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM\"a",
+"input":"<!DOCTYPEa SYSTEM\"a",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "a", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM\"b",
+"input":"<!DOCTYPEa SYSTEM\"b",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "b", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM\"y",
+"input":"<!DOCTYPEa SYSTEM\"y",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "y", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM\"z",
+"input":"<!DOCTYPEa SYSTEM\"z",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "z", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM\"{",
+"input":"<!DOCTYPEa SYSTEM\"{",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "{", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM\"\\uDBC0\\uDC00",
+"input":"<!DOCTYPEa SYSTEM\"\uDBC0\uDC00",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "\uDBC0\uDC00", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM#",
+"input":"<!DOCTYPEa SYSTEM#",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa SYSTEM&",
+"input":"<!DOCTYPEa SYSTEM&",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa SYSTEM'",
+"input":"<!DOCTYPEa SYSTEM'",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM'\\u0000",
+"input":"<!DOCTYPEa SYSTEM'\u0000",
+"output":["ParseError", "ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "\uFFFD", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM'\\u0009",
+"input":"<!DOCTYPEa SYSTEM'\u0009",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "\u0009", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM'\\u000A",
+"input":"<!DOCTYPEa SYSTEM'\u000A",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "\u000A", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM'\\u000B",
+"input":"<!DOCTYPEa SYSTEM'\u000B",
+"output":["ParseError", "ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "\u000B", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM'\\u000C",
+"input":"<!DOCTYPEa SYSTEM'\u000C",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "\u000C", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM' ",
+"input":"<!DOCTYPEa SYSTEM' ",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, " ", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM'!",
+"input":"<!DOCTYPEa SYSTEM'!",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "!", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM'\"",
+"input":"<!DOCTYPEa SYSTEM'\"",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "\"", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM'&",
+"input":"<!DOCTYPEa SYSTEM'&",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "&", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM''",
+"input":"<!DOCTYPEa SYSTEM''",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM''\\u0000",
+"input":"<!DOCTYPEa SYSTEM''\u0000",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPEa SYSTEM''\\u0008",
+"input":"<!DOCTYPEa SYSTEM''\u0008",
+"output":["ParseError", "ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPEa SYSTEM''\\u0009",
+"input":"<!DOCTYPEa SYSTEM''\u0009",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM''\\u000A",
+"input":"<!DOCTYPEa SYSTEM''\u000A",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM''\\u000B",
+"input":"<!DOCTYPEa SYSTEM''\u000B",
+"output":["ParseError", "ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPEa SYSTEM''\\u000C",
+"input":"<!DOCTYPEa SYSTEM''\u000C",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM''\\u000D",
+"input":"<!DOCTYPEa SYSTEM''\u000D",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM''\\u001F",
+"input":"<!DOCTYPEa SYSTEM''\u001F",
+"output":["ParseError", "ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPEa SYSTEM'' ",
+"input":"<!DOCTYPEa SYSTEM'' ",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM''!",
+"input":"<!DOCTYPEa SYSTEM''!",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPEa SYSTEM''\"",
+"input":"<!DOCTYPEa SYSTEM''\"",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPEa SYSTEM''&",
+"input":"<!DOCTYPEa SYSTEM''&",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPEa SYSTEM'''",
+"input":"<!DOCTYPEa SYSTEM'''",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPEa SYSTEM''-",
+"input":"<!DOCTYPEa SYSTEM''-",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPEa SYSTEM''/",
+"input":"<!DOCTYPEa SYSTEM''/",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPEa SYSTEM''0",
+"input":"<!DOCTYPEa SYSTEM''0",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPEa SYSTEM''1",
+"input":"<!DOCTYPEa SYSTEM''1",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPEa SYSTEM''9",
+"input":"<!DOCTYPEa SYSTEM''9",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPEa SYSTEM''<",
+"input":"<!DOCTYPEa SYSTEM''<",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPEa SYSTEM''=",
+"input":"<!DOCTYPEa SYSTEM''=",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPEa SYSTEM''>",
+"input":"<!DOCTYPEa SYSTEM''>",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPEa SYSTEM''?",
+"input":"<!DOCTYPEa SYSTEM''?",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPEa SYSTEM''@",
+"input":"<!DOCTYPEa SYSTEM''@",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPEa SYSTEM''A",
+"input":"<!DOCTYPEa SYSTEM''A",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPEa SYSTEM''B",
+"input":"<!DOCTYPEa SYSTEM''B",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPEa SYSTEM''Y",
+"input":"<!DOCTYPEa SYSTEM''Y",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPEa SYSTEM''Z",
+"input":"<!DOCTYPEa SYSTEM''Z",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPEa SYSTEM''`",
+"input":"<!DOCTYPEa SYSTEM''`",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPEa SYSTEM''a",
+"input":"<!DOCTYPEa SYSTEM''a",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPEa SYSTEM''b",
+"input":"<!DOCTYPEa SYSTEM''b",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPEa SYSTEM''y",
+"input":"<!DOCTYPEa SYSTEM''y",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPEa SYSTEM''z",
+"input":"<!DOCTYPEa SYSTEM''z",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPEa SYSTEM''{",
+"input":"<!DOCTYPEa SYSTEM''{",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPEa SYSTEM''\\uDBC0\\uDC00",
+"input":"<!DOCTYPEa SYSTEM''\uDBC0\uDC00",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]},
+
+{"description":"<!DOCTYPEa SYSTEM'(",
+"input":"<!DOCTYPEa SYSTEM'(",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "(", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM'-",
+"input":"<!DOCTYPEa SYSTEM'-",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "-", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM'/",
+"input":"<!DOCTYPEa SYSTEM'/",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "/", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM'0",
+"input":"<!DOCTYPEa SYSTEM'0",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "0", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM'1",
+"input":"<!DOCTYPEa SYSTEM'1",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "1", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM'9",
+"input":"<!DOCTYPEa SYSTEM'9",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "9", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM'<",
+"input":"<!DOCTYPEa SYSTEM'<",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "<", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM'=",
+"input":"<!DOCTYPEa SYSTEM'=",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "=", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM'>",
+"input":"<!DOCTYPEa SYSTEM'>",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM'?",
+"input":"<!DOCTYPEa SYSTEM'?",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "?", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM'@",
+"input":"<!DOCTYPEa SYSTEM'@",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "@", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM'A",
+"input":"<!DOCTYPEa SYSTEM'A",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "A", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM'B",
+"input":"<!DOCTYPEa SYSTEM'B",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "B", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM'Y",
+"input":"<!DOCTYPEa SYSTEM'Y",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "Y", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM'Z",
+"input":"<!DOCTYPEa SYSTEM'Z",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "Z", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM'`",
+"input":"<!DOCTYPEa SYSTEM'`",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "`", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM'a",
+"input":"<!DOCTYPEa SYSTEM'a",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "a", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM'b",
+"input":"<!DOCTYPEa SYSTEM'b",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "b", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM'y",
+"input":"<!DOCTYPEa SYSTEM'y",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "y", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM'z",
+"input":"<!DOCTYPEa SYSTEM'z",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "z", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM'{",
+"input":"<!DOCTYPEa SYSTEM'{",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "{", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM'\\uDBC0\\uDC00",
+"input":"<!DOCTYPEa SYSTEM'\uDBC0\uDC00",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "\uDBC0\uDC00", false]]},
+
+{"description":"<!DOCTYPEa SYSTEM(",
+"input":"<!DOCTYPEa SYSTEM(",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa SYSTEM-",
+"input":"<!DOCTYPEa SYSTEM-",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa SYSTEM/",
+"input":"<!DOCTYPEa SYSTEM/",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa SYSTEM0",
+"input":"<!DOCTYPEa SYSTEM0",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa SYSTEM1",
+"input":"<!DOCTYPEa SYSTEM1",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa SYSTEM9",
+"input":"<!DOCTYPEa SYSTEM9",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa SYSTEM<",
+"input":"<!DOCTYPEa SYSTEM<",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa SYSTEM=",
+"input":"<!DOCTYPEa SYSTEM=",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa SYSTEM>",
+"input":"<!DOCTYPEa SYSTEM>",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa SYSTEM?",
+"input":"<!DOCTYPEa SYSTEM?",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa SYSTEM@",
+"input":"<!DOCTYPEa SYSTEM@",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa SYSTEMA",
+"input":"<!DOCTYPEa SYSTEMA",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa SYSTEMB",
+"input":"<!DOCTYPEa SYSTEMB",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa SYSTEMY",
+"input":"<!DOCTYPEa SYSTEMY",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa SYSTEMZ",
+"input":"<!DOCTYPEa SYSTEMZ",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa SYSTEM`",
+"input":"<!DOCTYPEa SYSTEM`",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa SYSTEMa",
+"input":"<!DOCTYPEa SYSTEMa",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa SYSTEMb",
+"input":"<!DOCTYPEa SYSTEMb",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa SYSTEMy",
+"input":"<!DOCTYPEa SYSTEMy",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa SYSTEMz",
+"input":"<!DOCTYPEa SYSTEMz",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa SYSTEM{",
+"input":"<!DOCTYPEa SYSTEM{",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa SYSTEM\\uDBC0\\uDC00",
+"input":"<!DOCTYPEa SYSTEM\uDBC0\uDC00",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa Y",
+"input":"<!DOCTYPEa Y",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa Z",
+"input":"<!DOCTYPEa Z",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa `",
+"input":"<!DOCTYPEa `",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa a",
+"input":"<!DOCTYPEa a",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa a\\u0000",
+"input":"<!DOCTYPEa a\u0000",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa a\\u0009",
+"input":"<!DOCTYPEa a\u0009",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa a\\u000A",
+"input":"<!DOCTYPEa a\u000A",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa a\\u000B",
+"input":"<!DOCTYPEa a\u000B",
+"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa a\\u000C",
+"input":"<!DOCTYPEa a\u000C",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa a ",
+"input":"<!DOCTYPEa a ",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa a!",
+"input":"<!DOCTYPEa a!",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa a\"",
+"input":"<!DOCTYPEa a\"",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa a&",
+"input":"<!DOCTYPEa a&",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa a'",
+"input":"<!DOCTYPEa a'",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa a-",
+"input":"<!DOCTYPEa a-",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa a/",
+"input":"<!DOCTYPEa a/",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa a0",
+"input":"<!DOCTYPEa a0",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa a1",
+"input":"<!DOCTYPEa a1",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa a9",
+"input":"<!DOCTYPEa a9",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa a<",
+"input":"<!DOCTYPEa a<",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa a=",
+"input":"<!DOCTYPEa a=",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa a>",
+"input":"<!DOCTYPEa a>",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa a?",
+"input":"<!DOCTYPEa a?",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa a@",
+"input":"<!DOCTYPEa a@",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa aA",
+"input":"<!DOCTYPEa aA",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa aB",
+"input":"<!DOCTYPEa aB",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa aY",
+"input":"<!DOCTYPEa aY",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa aZ",
+"input":"<!DOCTYPEa aZ",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa a`",
+"input":"<!DOCTYPEa a`",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa aa",
+"input":"<!DOCTYPEa aa",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa ab",
+"input":"<!DOCTYPEa ab",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa ay",
+"input":"<!DOCTYPEa ay",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa az",
+"input":"<!DOCTYPEa az",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa a{",
+"input":"<!DOCTYPEa a{",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa a\\uDBC0\\uDC00",
+"input":"<!DOCTYPEa a\uDBC0\uDC00",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa b",
+"input":"<!DOCTYPEa b",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa y",
+"input":"<!DOCTYPEa y",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa z",
+"input":"<!DOCTYPEa z",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa {",
+"input":"<!DOCTYPEa {",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa \\uDBC0\\uDC00",
+"input":"<!DOCTYPEa \uDBC0\uDC00",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]},
+
+{"description":"<!DOCTYPEa!",
+"input":"<!DOCTYPEa!",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a!", null, null, false]]},
+
+{"description":"<!DOCTYPEa\"",
+"input":"<!DOCTYPEa\"",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a\"", null, null, false]]},
+
+{"description":"<!DOCTYPEa&",
+"input":"<!DOCTYPEa&",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a&", null, null, false]]},
+
+{"description":"<!DOCTYPEa'",
+"input":"<!DOCTYPEa'",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a'", null, null, false]]},
+
+{"description":"<!DOCTYPEa-",
+"input":"<!DOCTYPEa-",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a-", null, null, false]]},
+
+{"description":"<!DOCTYPEa/",
+"input":"<!DOCTYPEa/",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a/", null, null, false]]},
+
+{"description":"<!DOCTYPEa0",
+"input":"<!DOCTYPEa0",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a0", null, null, false]]},
+
+{"description":"<!DOCTYPEa1",
+"input":"<!DOCTYPEa1",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a1", null, null, false]]},
+
+{"description":"<!DOCTYPEa9",
+"input":"<!DOCTYPEa9",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a9", null, null, false]]},
+
+{"description":"<!DOCTYPEa<",
+"input":"<!DOCTYPEa<",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a<", null, null, false]]},
+
+{"description":"<!DOCTYPEa=",
+"input":"<!DOCTYPEa=",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a=", null, null, false]]},
+
+{"description":"<!DOCTYPEa>",
+"input":"<!DOCTYPEa>",
+"output":["ParseError", ["DOCTYPE", "a", null, null, true]]},
+
+{"description":"<!DOCTYPEa?",
+"input":"<!DOCTYPEa?",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a?", null, null, false]]},
+
+{"description":"<!DOCTYPEa@",
+"input":"<!DOCTYPEa@",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a@", null, null, false]]},
+
+{"description":"<!DOCTYPEaA",
+"input":"<!DOCTYPEaA",
+"output":["ParseError", "ParseError", ["DOCTYPE", "aa", null, null, false]]},
+
+{"description":"<!DOCTYPEaB",
+"input":"<!DOCTYPEaB",
+"output":["ParseError", "ParseError", ["DOCTYPE", "ab", null, null, false]]},
+
+{"description":"<!DOCTYPEaY",
+"input":"<!DOCTYPEaY",
+"output":["ParseError", "ParseError", ["DOCTYPE", "ay", null, null, false]]},
+
+{"description":"<!DOCTYPEaZ",
+"input":"<!DOCTYPEaZ",
+"output":["ParseError", "ParseError", ["DOCTYPE", "az", null, null, false]]},
+
+{"description":"<!DOCTYPEa[",
+"input":"<!DOCTYPEa[",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a[", null, null, false]]},
+
+{"description":"<!DOCTYPEa`",
+"input":"<!DOCTYPEa`",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a`", null, null, false]]},
+
+{"description":"<!DOCTYPEaa",
+"input":"<!DOCTYPEaa",
+"output":["ParseError", "ParseError", ["DOCTYPE", "aa", null, null, false]]},
+
+{"description":"<!DOCTYPEab",
+"input":"<!DOCTYPEab",
+"output":["ParseError", "ParseError", ["DOCTYPE", "ab", null, null, false]]},
+
+{"description":"<!DOCTYPEay",
+"input":"<!DOCTYPEay",
+"output":["ParseError", "ParseError", ["DOCTYPE", "ay", null, null, false]]},
+
+{"description":"<!DOCTYPEaz",
+"input":"<!DOCTYPEaz",
+"output":["ParseError", "ParseError", ["DOCTYPE", "az", null, null, false]]},
+
+{"description":"<!DOCTYPEa{",
+"input":"<!DOCTYPEa{",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a{", null, null, false]]},
+
+{"description":"<!DOCTYPEa\\uDBC0\\uDC00",
+"input":"<!DOCTYPEa\uDBC0\uDC00",
+"output":["ParseError", "ParseError", ["DOCTYPE", "a\uDBC0\uDC00", null, null, false]]},
+
+{"description":"<!DOCTYPEb",
+"input":"<!DOCTYPEb",
+"output":["ParseError", "ParseError", ["DOCTYPE", "b", null, null, false]]},
+
+{"description":"<!DOCTYPEy",
+"input":"<!DOCTYPEy",
+"output":["ParseError", "ParseError", ["DOCTYPE", "y", null, null, false]]},
+
+{"description":"<!DOCTYPEz",
+"input":"<!DOCTYPEz",
+"output":["ParseError", "ParseError", ["DOCTYPE", "z", null, null, false]]},
+
+{"description":"<!DOCTYPE{",
+"input":"<!DOCTYPE{",
+"output":["ParseError", "ParseError", ["DOCTYPE", "{", null, null, false]]},
+
+{"description":"<!DOCTYPE\\uDBC0\\uDC00",
+"input":"<!DOCTYPE\uDBC0\uDC00",
+"output":["ParseError", "ParseError", ["DOCTYPE", "\uDBC0\uDC00", null, null, false]]},
+
+{"description":"<!Y",
+"input":"<!Y",
+"output":["ParseError", ["Comment", "Y"]]},
+
+{"description":"<!Z",
+"input":"<!Z",
+"output":["ParseError", ["Comment", "Z"]]},
+
+{"description":"<!`",
+"input":"<!`",
+"output":["ParseError", ["Comment", "`"]]},
+
+{"description":"<!a",
+"input":"<!a",
+"output":["ParseError", ["Comment", "a"]]},
+
+{"description":"<!b",
+"input":"<!b",
+"output":["ParseError", ["Comment", "b"]]},
+
+{"description":"<!y",
+"input":"<!y",
+"output":["ParseError", ["Comment", "y"]]},
+
+{"description":"<!z",
+"input":"<!z",
+"output":["ParseError", ["Comment", "z"]]},
+
+{"description":"<!{",
+"input":"<!{",
+"output":["ParseError", ["Comment", "{"]]},
+
+{"description":"<!\\uDBC0\\uDC00",
+"input":"<!\uDBC0\uDC00",
+"output":["ParseError", ["Comment", "\uDBC0\uDC00"]]},
+
+{"description":"<\"",
+"input":"<\"",
+"output":["ParseError", ["Character", "<\""]]},
+
+{"description":"<&",
+"input":"<&",
+"output":["ParseError", ["Character", "<&"]]},
+
+{"description":"<'",
+"input":"<'",
+"output":["ParseError", ["Character", "<'"]]},
+
+{"description":"<-",
+"input":"<-",
+"output":["ParseError", ["Character", "<-"]]},
+
+{"description":"<.",
+"input":"<.",
+"output":["ParseError", ["Character", "<."]]},
+
+{"description":"</",
+"input":"</",
+"output":["ParseError", ["Character", "</"]]},
+
+{"description":"</\\u0000",
+"input":"</\u0000",
+"output":["ParseError", ["Comment", "\uFFFD"]]},
+
+{"description":"</\\u0009",
+"input":"</\u0009",
+"output":["ParseError", ["Comment", "\u0009"]]},
+
+{"description":"</\\u000A",
+"input":"</\u000A",
+"output":["ParseError", ["Comment", "\u000A"]]},
+
+{"description":"</\\u000B",
+"input":"</\u000B",
+"output":["ParseError", "ParseError", ["Comment", "\u000B"]]},
+
+{"description":"</\\u000C",
+"input":"</\u000C",
+"output":["ParseError", ["Comment", "\u000C"]]},
+
+{"description":"</ ",
+"input":"</ ",
+"output":["ParseError", ["Comment", " "]]},
+
+{"description":"</!",
+"input":"</!",
+"output":["ParseError", ["Comment", "!"]]},
+
+{"description":"</\"",
+"input":"</\"",
+"output":["ParseError", ["Comment", "\""]]},
+
+{"description":"</&",
+"input":"</&",
+"output":["ParseError", ["Comment", "&"]]},
+
+{"description":"</'",
+"input":"</'",
+"output":["ParseError", ["Comment", "'"]]},
+
+{"description":"</-",
+"input":"</-",
+"output":["ParseError", ["Comment", "-"]]},
+
+{"description":"<//",
+"input":"<//",
+"output":["ParseError", ["Comment", "/"]]},
+
+{"description":"</0",
+"input":"</0",
+"output":["ParseError", ["Comment", "0"]]},
+
+{"description":"</1",
+"input":"</1",
+"output":["ParseError", ["Comment", "1"]]},
+
+{"description":"</9",
+"input":"</9",
+"output":["ParseError", ["Comment", "9"]]},
+
+{"description":"</<",
+"input":"</<",
+"output":["ParseError", ["Comment", "<"]]},
+
+{"description":"</=",
+"input":"</=",
+"output":["ParseError", ["Comment", "="]]},
+
+{"description":"</>",
+"input":"</>",
+"output":["ParseError"]},
+
+{"description":"</?",
+"input":"</?",
+"output":["ParseError", ["Comment", "?"]]},
+
+{"description":"</@",
+"input":"</@",
+"output":["ParseError", ["Comment", "@"]]},
+
+{"description":"</A>",
+"input":"</A>",
+"output":[["EndTag", "a"]]},
+
+{"description":"</B>",
+"input":"</B>",
+"output":[["EndTag", "b"]]},
+
+{"description":"</Y>",
+"input":"</Y>",
+"output":[["EndTag", "y"]]},
+
+{"description":"</Z>",
+"input":"</Z>",
+"output":[["EndTag", "z"]]},
+
+{"description":"</[",
+"input":"</[",
+"output":["ParseError", ["Comment", "["]]},
+
+{"description":"</`",
+"input":"</`",
+"output":["ParseError", ["Comment", "`"]]},
+
+{"description":"</a>",
+"input":"</a>",
+"output":[["EndTag", "a"]]},
+
+{"description":"</b>",
+"input":"</b>",
+"output":[["EndTag", "b"]]},
+
+{"description":"</y>",
+"input":"</y>",
+"output":[["EndTag", "y"]]},
+
+{"description":"</z>",
+"input":"</z>",
+"output":[["EndTag", "z"]]},
+
+{"description":"</{",
+"input":"</{",
+"output":["ParseError", ["Comment", "{"]]},
+
+{"description":"</\\uDBC0\\uDC00",
+"input":"</\uDBC0\uDC00",
+"output":["ParseError", ["Comment", "\uDBC0\uDC00"]]},
+
+{"description":"<0",
+"input":"<0",
+"output":["ParseError", ["Character", "<0"]]},
+
+{"description":"<1",
+"input":"<1",
+"output":["ParseError", ["Character", "<1"]]},
+
+{"description":"<9",
+"input":"<9",
+"output":["ParseError", ["Character", "<9"]]},
+
+{"description":"<<",
+"input":"<<",
+"output":["ParseError", ["Character", "<"], "ParseError", ["Character", "<"]]},
+
+{"description":"<=",
+"input":"<=",
+"output":["ParseError", ["Character", "<="]]},
+
+{"description":"<>",
+"input":"<>",
+"output":["ParseError", ["Character", "<>"]]},
+
+{"description":"<?",
+"input":"<?",
+"output":["ParseError", ["Comment", "?"]]},
+
+{"description":"<?\\u0000",
+"input":"<?\u0000",
+"output":["ParseError", ["Comment", "?\uFFFD"]]},
+
+{"description":"<?\\u0009",
+"input":"<?\u0009",
+"output":["ParseError", ["Comment", "?\u0009"]]},
+
+{"description":"<?\\u000A",
+"input":"<?\u000A",
+"output":["ParseError", ["Comment", "?\u000A"]]},
+
+{"description":"<?\\u000B",
+"input":"<?\u000B",
+"output":["ParseError", "ParseError", ["Comment", "?\u000B"]]},
+
+{"description":"<?\\u000C",
+"input":"<?\u000C",
+"output":["ParseError", ["Comment", "?\u000C"]]},
+
+{"description":"<? ",
+"input":"<? ",
+"output":["ParseError", ["Comment", "? "]]},
+
+{"description":"<?!",
+"input":"<?!",
+"output":["ParseError", ["Comment", "?!"]]},
+
+{"description":"<?\"",
+"input":"<?\"",
+"output":["ParseError", ["Comment", "?\""]]},
+
+{"description":"<?&",
+"input":"<?&",
+"output":["ParseError", ["Comment", "?&"]]},
+
+{"description":"<?'",
+"input":"<?'",
+"output":["ParseError", ["Comment", "?'"]]},
+
+{"description":"<?-",
+"input":"<?-",
+"output":["ParseError", ["Comment", "?-"]]},
+
+{"description":"<?/",
+"input":"<?/",
+"output":["ParseError", ["Comment", "?/"]]},
+
+{"description":"<?0",
+"input":"<?0",
+"output":["ParseError", ["Comment", "?0"]]},
+
+{"description":"<?1",
+"input":"<?1",
+"output":["ParseError", ["Comment", "?1"]]},
+
+{"description":"<?9",
+"input":"<?9",
+"output":["ParseError", ["Comment", "?9"]]},
+
+{"description":"<?<",
+"input":"<?<",
+"output":["ParseError", ["Comment", "?<"]]},
+
+{"description":"<?=",
+"input":"<?=",
+"output":["ParseError", ["Comment", "?="]]},
+
+{"description":"<?>",
+"input":"<?>",
+"output":["ParseError", ["Comment", "?"]]},
+
+{"description":"<??",
+"input":"<??",
+"output":["ParseError", ["Comment", "??"]]},
+
+{"description":"<?@",
+"input":"<?@",
+"output":["ParseError", ["Comment", "?@"]]},
+
+{"description":"<?A",
+"input":"<?A",
+"output":["ParseError", ["Comment", "?A"]]},
+
+{"description":"<?B",
+"input":"<?B",
+"output":["ParseError", ["Comment", "?B"]]},
+
+{"description":"<?Y",
+"input":"<?Y",
+"output":["ParseError", ["Comment", "?Y"]]},
+
+{"description":"<?Z",
+"input":"<?Z",
+"output":["ParseError", ["Comment", "?Z"]]},
+
+{"description":"<?`",
+"input":"<?`",
+"output":["ParseError", ["Comment", "?`"]]},
+
+{"description":"<?a",
+"input":"<?a",
+"output":["ParseError", ["Comment", "?a"]]},
+
+{"description":"<?b",
+"input":"<?b",
+"output":["ParseError", ["Comment", "?b"]]},
+
+{"description":"<?y",
+"input":"<?y",
+"output":["ParseError", ["Comment", "?y"]]},
+
+{"description":"<?z",
+"input":"<?z",
+"output":["ParseError", ["Comment", "?z"]]},
+
+{"description":"<?{",
+"input":"<?{",
+"output":["ParseError", ["Comment", "?{"]]},
+
+{"description":"<?\\uDBC0\\uDC00",
+"input":"<?\uDBC0\uDC00",
+"output":["ParseError", ["Comment", "?\uDBC0\uDC00"]]},
+
+{"description":"<@",
+"input":"<@",
+"output":["ParseError", ["Character", "<@"]]},
+
+{"description":"<A>",
+"input":"<A>",
+"output":[["StartTag", "a", {}]]},
+
+{"description":"<B>",
+"input":"<B>",
+"output":[["StartTag", "b", {}]]},
+
+{"description":"<Y>",
+"input":"<Y>",
+"output":[["StartTag", "y", {}]]},
+
+{"description":"<Z>",
+"input":"<Z>",
+"output":[["StartTag", "z", {}]]},
+
+{"description":"<[",
+"input":"<[",
+"output":["ParseError", ["Character", "<["]]},
+
+{"description":"<`",
+"input":"<`",
+"output":["ParseError", ["Character", "<`"]]},
+
+{"description":"<a>",
+"input":"<a>",
+"output":[["StartTag", "a", {}]]},
+
+{"description":"<a\\u0000>",
+"input":"<a\u0000>",
+"output":["ParseError", ["StartTag", "a\uFFFD", {}]]},
+
+{"description":"<a\\u0008>",
+"input":"<a\u0008>",
+"output":["ParseError", ["StartTag", "a\u0008", {}]]},
+
+{"description":"<a\\u0009>",
+"input":"<a\u0009>",
+"output":[["StartTag", "a", {}]]},
+
+{"description":"<a\\u000A>",
+"input":"<a\u000A>",
+"output":[["StartTag", "a", {}]]},
+
+{"description":"<a\\u000B>",
+"input":"<a\u000B>",
+"output":["ParseError", ["StartTag", "a\u000B", {}]]},
+
+{"description":"<a\\u000C>",
+"input":"<a\u000C>",
+"output":[["StartTag", "a", {}]]},
+
+{"description":"<a\\u000D>",
+"input":"<a\u000D>",
+"output":[["StartTag", "a", {}]]},
+
+{"description":"<a\\u001F>",
+"input":"<a\u001F>",
+"output":["ParseError", ["StartTag", "a\u001F", {}]]},
+
+{"description":"<a >",
+"input":"<a >",
+"output":[["StartTag", "a", {}]]},
+
+{"description":"<a \\u0000>",
+"input":"<a \u0000>",
+"output":["ParseError", ["StartTag", "a", {"\uFFFD":""}]]},
+
+{"description":"<a \\u0008>",
+"input":"<a \u0008>",
+"output":["ParseError", ["StartTag", "a", {"\u0008":""}]]},
+
+{"description":"<a \\u0009>",
+"input":"<a \u0009>",
+"output":[["StartTag", "a", {}]]},
+
+{"description":"<a \\u000A>",
+"input":"<a \u000A>",
+"output":[["StartTag", "a", {}]]},
+
+{"description":"<a \\u000B>",
+"input":"<a \u000B>",
+"output":["ParseError", ["StartTag", "a", {"\u000B":""}]]},
+
+{"description":"<a \\u000C>",
+"input":"<a \u000C>",
+"output":[["StartTag", "a", {}]]},
+
+{"description":"<a \\u000D>",
+"input":"<a \u000D>",
+"output":[["StartTag", "a", {}]]},
+
+{"description":"<a \\u001F>",
+"input":"<a \u001F>",
+"output":["ParseError", ["StartTag", "a", {"\u001F":""}]]},
+
+{"description":"<a >",
+"input":"<a >",
+"output":[["StartTag", "a", {}]]},
+
+{"description":"<a !>",
+"input":"<a !>",
+"output":[["StartTag", "a", {"!":""}]]},
+
+{"description":"<a \">",
+"input":"<a \">",
+"output":["ParseError", ["StartTag", "a", {"\"":""}]]},
+
+{"description":"<a #>",
+"input":"<a #>",
+"output":[["StartTag", "a", {"#":""}]]},
+
+{"description":"<a &>",
+"input":"<a &>",
+"output":[["StartTag", "a", {"&":""}]]},
+
+{"description":"<a '>",
+"input":"<a '>",
+"output":["ParseError", ["StartTag", "a", {"'":""}]]},
+
+{"description":"<a (>",
+"input":"<a (>",
+"output":[["StartTag", "a", {"(":""}]]},
+
+{"description":"<a ->",
+"input":"<a ->",
+"output":[["StartTag", "a", {"-":""}]]},
+
+{"description":"<a .>",
+"input":"<a .>",
+"output":[["StartTag", "a", {".":""}]]},
+
+{"description":"<a />",
+"input":"<a />",
+"output":[["StartTag", "a", {}, true]]},
+
+{"description":"<a 0>",
+"input":"<a 0>",
+"output":[["StartTag", "a", {"0":""}]]},
+
+{"description":"<a 1>",
+"input":"<a 1>",
+"output":[["StartTag", "a", {"1":""}]]},
+
+{"description":"<a 9>",
+"input":"<a 9>",
+"output":[["StartTag", "a", {"9":""}]]},
+
+{"description":"<a <>",
+"input":"<a <>",
+"output":["ParseError", ["StartTag", "a", {"<":""}]]},
+
+{"description":"<a =>",
+"input":"<a =>",
+"output":["ParseError", ["StartTag", "a", {"=":""}]]},
+
+{"description":"<a >",
+"input":"<a >",
+"output":[["StartTag", "a", {}]]},
+
+{"description":"<a ?>",
+"input":"<a ?>",
+"output":[["StartTag", "a", {"?":""}]]},
+
+{"description":"<a @>",
+"input":"<a @>",
+"output":[["StartTag", "a", {"@":""}]]},
+
+{"description":"<a A>",
+"input":"<a A>",
+"output":[["StartTag", "a", {"a":""}]]},
+
+{"description":"<a B>",
+"input":"<a B>",
+"output":[["StartTag", "a", {"b":""}]]},
+
+{"description":"<a Y>",
+"input":"<a Y>",
+"output":[["StartTag", "a", {"y":""}]]},
+
+{"description":"<a Z>",
+"input":"<a Z>",
+"output":[["StartTag", "a", {"z":""}]]},
+
+{"description":"<a [>",
+"input":"<a [>",
+"output":[["StartTag", "a", {"[":""}]]},
+
+{"description":"<a `>",
+"input":"<a `>",
+"output":[["StartTag", "a", {"`":""}]]},
+
+{"description":"<a a>",
+"input":"<a a>",
+"output":[["StartTag", "a", {"a":""}]]},
+
+{"description":"<a a\\u0000>",
+"input":"<a a\u0000>",
+"output":["ParseError", ["StartTag", "a", {"a\uFFFD":""}]]},
+
+{"description":"<a a\\u0008>",
+"input":"<a a\u0008>",
+"output":["ParseError", ["StartTag", "a", {"a\u0008":""}]]},
+
+{"description":"<a a\\u0009>",
+"input":"<a a\u0009>",
+"output":[["StartTag", "a", {"a":""}]]},
+
+{"description":"<a a\\u000A>",
+"input":"<a a\u000A>",
+"output":[["StartTag", "a", {"a":""}]]},
+
+{"description":"<a a\\u000B>",
+"input":"<a a\u000B>",
+"output":["ParseError", ["StartTag", "a", {"a\u000B":""}]]},
+
+{"description":"<a a\\u000C>",
+"input":"<a a\u000C>",
+"output":[["StartTag", "a", {"a":""}]]},
+
+{"description":"<a a\\u000D>",
+"input":"<a a\u000D>",
+"output":[["StartTag", "a", {"a":""}]]},
+
+{"description":"<a a\\u001F>",
+"input":"<a a\u001F>",
+"output":["ParseError", ["StartTag", "a", {"a\u001F":""}]]},
+
+{"description":"<a a >",
+"input":"<a a >",
+"output":[["StartTag", "a", {"a":""}]]},
+
+{"description":"<a a \\u0000>",
+"input":"<a a \u0000>",
+"output":["ParseError", ["StartTag", "a", {"a":"", "\uFFFD":""}]]},
+
+{"description":"<a a \\u0008>",
+"input":"<a a \u0008>",
+"output":["ParseError", ["StartTag", "a", {"a":"", "\u0008":""}]]},
+
+{"description":"<a a \\u0009>",
+"input":"<a a \u0009>",
+"output":[["StartTag", "a", {"a":""}]]},
+
+{"description":"<a a \\u000A>",
+"input":"<a a \u000A>",
+"output":[["StartTag", "a", {"a":""}]]},
+
+{"description":"<a a \\u000B>",
+"input":"<a a \u000B>",
+"output":["ParseError", ["StartTag", "a", {"a":"", "\u000B":""}]]},
+
+{"description":"<a a \\u000C>",
+"input":"<a a \u000C>",
+"output":[["StartTag", "a", {"a":""}]]},
+
+{"description":"<a a \\u000D>",
+"input":"<a a \u000D>",
+"output":[["StartTag", "a", {"a":""}]]},
+
+{"description":"<a a \\u001F>",
+"input":"<a a \u001F>",
+"output":["ParseError", ["StartTag", "a", {"a":"", "\u001F":""}]]},
+
+{"description":"<a a >",
+"input":"<a a >",
+"output":[["StartTag", "a", {"a":""}]]},
+
+{"description":"<a a !>",
+"input":"<a a !>",
+"output":[["StartTag", "a", {"a":"", "!":""}]]},
+
+{"description":"<a a \">",
+"input":"<a a \">",
+"output":["ParseError", ["StartTag", "a", {"a":"", "\"":""}]]},
+
+{"description":"<a a #>",
+"input":"<a a #>",
+"output":[["StartTag", "a", {"a":"", "#":""}]]},
+
+{"description":"<a a &>",
+"input":"<a a &>",
+"output":[["StartTag", "a", {"a":"", "&":""}]]},
+
+{"description":"<a a '>",
+"input":"<a a '>",
+"output":["ParseError", ["StartTag", "a", {"a":"", "'":""}]]},
+
+{"description":"<a a (>",
+"input":"<a a (>",
+"output":[["StartTag", "a", {"a":"", "(":""}]]},
+
+{"description":"<a a ->",
+"input":"<a a ->",
+"output":[["StartTag", "a", {"a":"", "-":""}]]},
+
+{"description":"<a a .>",
+"input":"<a a .>",
+"output":[["StartTag", "a", {"a":"", ".":""}]]},
+
+{"description":"<a a />",
+"input":"<a a />",
+"output":[["StartTag", "a", {"a":""}, true]]},
+
+{"description":"<a a 0>",
+"input":"<a a 0>",
+"output":[["StartTag", "a", {"a":"", "0":""}]]},
+
+{"description":"<a a 1>",
+"input":"<a a 1>",
+"output":[["StartTag", "a", {"a":"", "1":""}]]},
+
+{"description":"<a a 9>",
+"input":"<a a 9>",
+"output":[["StartTag", "a", {"a":"", "9":""}]]},
+
+{"description":"<a a <>",
+"input":"<a a <>",
+"output":["ParseError", ["StartTag", "a", {"a":"", "<":""}]]},
+
+{"description":"<a a =>",
+"input":"<a a =>",
+"output":["ParseError", ["StartTag", "a", {"a":""}]]},
+
+{"description":"<a a >",
+"input":"<a a >",
+"output":[["StartTag", "a", {"a":""}]]},
+
+{"description":"<a a ?>",
+"input":"<a a ?>",
+"output":[["StartTag", "a", {"a":"", "?":""}]]},
+
+{"description":"<a a @>",
+"input":"<a a @>",
+"output":[["StartTag", "a", {"a":"", "@":""}]]},
+
+{"description":"<a a A>",
+"input":"<a a A>",
+"output":["ParseError", ["StartTag", "a", {"a":""}]]},
+
+{"description":"<a a B>",
+"input":"<a a B>",
+"output":[["StartTag", "a", {"a":"", "b":""}]]},
+
+{"description":"<a a Y>",
+"input":"<a a Y>",
+"output":[["StartTag", "a", {"a":"", "y":""}]]},
+
+{"description":"<a a Z>",
+"input":"<a a Z>",
+"output":[["StartTag", "a", {"a":"", "z":""}]]},
+
+{"description":"<a a [>",
+"input":"<a a [>",
+"output":[["StartTag", "a", {"a":"", "[":""}]]},
+
+{"description":"<a a `>",
+"input":"<a a `>",
+"output":[["StartTag", "a", {"a":"", "`":""}]]},
+
+{"description":"<a a a>",
+"input":"<a a a>",
+"output":["ParseError", ["StartTag", "a", {"a":""}]]},
+
+{"description":"<a a b>",
+"input":"<a a b>",
+"output":[["StartTag", "a", {"a":"", "b":""}]]},
+
+{"description":"<a a y>",
+"input":"<a a y>",
+"output":[["StartTag", "a", {"a":"", "y":""}]]},
+
+{"description":"<a a z>",
+"input":"<a a z>",
+"output":[["StartTag", "a", {"a":"", "z":""}]]},
+
+{"description":"<a a {>",
+"input":"<a a {>",
+"output":[["StartTag", "a", {"a":"", "{":""}]]},
+
+{"description":"<a a \\uDBC0\\uDC00>",
+"input":"<a a \uDBC0\uDC00>",
+"output":[["StartTag", "a", {"a":"", "\uDBC0\uDC00":""}]]},
+
+{"description":"<a a!>",
+"input":"<a a!>",
+"output":[["StartTag", "a", {"a!":""}]]},
+
+{"description":"<a a\">",
+"input":"<a a\">",
+"output":["ParseError", ["StartTag", "a", {"a\"":""}]]},
+
+{"description":"<a a#>",
+"input":"<a a#>",
+"output":[["StartTag", "a", {"a#":""}]]},
+
+{"description":"<a a&>",
+"input":"<a a&>",
+"output":[["StartTag", "a", {"a&":""}]]},
+
+{"description":"<a a'>",
+"input":"<a a'>",
+"output":["ParseError", ["StartTag", "a", {"a'":""}]]},
+
+{"description":"<a a(>",
+"input":"<a a(>",
+"output":[["StartTag", "a", {"a(":""}]]},
+
+{"description":"<a a->",
+"input":"<a a->",
+"output":[["StartTag", "a", {"a-":""}]]},
+
+{"description":"<a a.>",
+"input":"<a a.>",
+"output":[["StartTag", "a", {"a.":""}]]},
+
+{"description":"<a a/>",
+"input":"<a a/>",
+"output":[["StartTag", "a", {"a":""}, true]]},
+
+{"description":"<a a0>",
+"input":"<a a0>",
+"output":[["StartTag", "a", {"a0":""}]]},
+
+{"description":"<a a1>",
+"input":"<a a1>",
+"output":[["StartTag", "a", {"a1":""}]]},
+
+{"description":"<a a9>",
+"input":"<a a9>",
+"output":[["StartTag", "a", {"a9":""}]]},
+
+{"description":"<a a<>",
+"input":"<a a<>",
+"output":["ParseError", ["StartTag", "a", {"a<":""}]]},
+
+{"description":"<a a=>",
+"input":"<a a=>",
+"output":["ParseError", ["StartTag", "a", {"a":""}]]},
+
+{"description":"<a a=\\u0000>",
+"input":"<a a=\u0000>",
+"output":["ParseError", ["StartTag", "a", {"a":"\uFFFD"}]]},
+
+{"description":"<a a=\\u0008>",
+"input":"<a a=\u0008>",
+"output":["ParseError", ["StartTag", "a", {"a":"\u0008"}]]},
+
+{"description":"<a a=\\u0009>",
+"input":"<a a=\u0009>",
+"output":["ParseError", ["StartTag", "a", {"a":""}]]},
+
+{"description":"<a a=\\u000A>",
+"input":"<a a=\u000A>",
+"output":["ParseError", ["StartTag", "a", {"a":""}]]},
+
+{"description":"<a a=\\u000B>",
+"input":"<a a=\u000B>",
+"output":["ParseError", ["StartTag", "a", {"a":"\u000B"}]]},
+
+{"description":"<a a=\\u000C>",
+"input":"<a a=\u000C>",
+"output":["ParseError", ["StartTag", "a", {"a":""}]]},
+
+{"description":"<a a=\\u000D>",
+"input":"<a a=\u000D>",
+"output":["ParseError", ["StartTag", "a", {"a":""}]]},
+
+{"description":"<a a=\\u001F>",
+"input":"<a a=\u001F>",
+"output":["ParseError", ["StartTag", "a", {"a":"\u001F"}]]},
+
+{"description":"<a a= >",
+"input":"<a a= >",
+"output":["ParseError", ["StartTag", "a", {"a":""}]]},
+
+{"description":"<a a=!>",
+"input":"<a a=!>",
+"output":[["StartTag", "a", {"a":"!"}]]},
+
+{"description":"<a a=\"\">",
+"input":"<a a=\"\">",
+"output":[["StartTag", "a", {"a":""}]]},
+
+{"description":"<a a=\"\\u0000\">",
+"input":"<a a=\"\u0000\">",
+"output":["ParseError", ["StartTag", "a", {"a":"\uFFFD"}]]},
+
+{"description":"<a a=\"\\u0009\">",
+"input":"<a a=\"\u0009\">",
+"output":[["StartTag", "a", {"a":"\u0009"}]]},
+
+{"description":"<a a=\"\\u000A\">",
+"input":"<a a=\"\u000A\">",
+"output":[["StartTag", "a", {"a":"\u000A"}]]},
+
+{"description":"<a a=\"\\u000B\">",
+"input":"<a a=\"\u000B\">",
+"output":["ParseError", ["StartTag", "a", {"a":"\u000B"}]]},
+
+{"description":"<a a=\"\\u000C\">",
+"input":"<a a=\"\u000C\">",
+"output":[["StartTag", "a", {"a":"\u000C"}]]},
+
+{"description":"<a a=\" \">",
+"input":"<a a=\" \">",
+"output":[["StartTag", "a", {"a":" "}]]},
+
+{"description":"<a a=\"!\">",
+"input":"<a a=\"!\">",
+"output":[["StartTag", "a", {"a":"!"}]]},
+
+{"description":"<a a=\"\">",
+"input":"<a a=\"\">",
+"output":[["StartTag", "a", {"a":""}]]},
+
+{"description":"<a a=\"#\">",
+"input":"<a a=\"#\">",
+"output":[["StartTag", "a", {"a":"#"}]]},
+
+{"description":"<a a=\"%\">",
+"input":"<a a=\"%\">",
+"output":[["StartTag", "a", {"a":"%"}]]},
+
+{"description":"<a a=\"&\">",
+"input":"<a a=\"&\">",
+"output":[["StartTag", "a", {"a":"&"}]]},
+
+{"description":"<a a=\"'\">",
+"input":"<a a=\"'\">",
+"output":[["StartTag", "a", {"a":"'"}]]},
+
+{"description":"<a a=\"-\">",
+"input":"<a a=\"-\">",
+"output":[["StartTag", "a", {"a":"-"}]]},
+
+{"description":"<a a=\"/\">",
+"input":"<a a=\"/\">",
+"output":[["StartTag", "a", {"a":"/"}]]},
+
+{"description":"<a a=\"0\">",
+"input":"<a a=\"0\">",
+"output":[["StartTag", "a", {"a":"0"}]]},
+
+{"description":"<a a=\"1\">",
+"input":"<a a=\"1\">",
+"output":[["StartTag", "a", {"a":"1"}]]},
+
+{"description":"<a a=\"9\">",
+"input":"<a a=\"9\">",
+"output":[["StartTag", "a", {"a":"9"}]]},
+
+{"description":"<a a=\"<\">",
+"input":"<a a=\"<\">",
+"output":[["StartTag", "a", {"a":"<"}]]},
+
+{"description":"<a a=\"=\">",
+"input":"<a a=\"=\">",
+"output":[["StartTag", "a", {"a":"="}]]},
+
+{"description":"<a a=\">\">",
+"input":"<a a=\">\">",
+"output":[["StartTag", "a", {"a":">"}]]},
+
+{"description":"<a a=\"?\">",
+"input":"<a a=\"?\">",
+"output":[["StartTag", "a", {"a":"?"}]]},
+
+{"description":"<a a=\"@\">",
+"input":"<a a=\"@\">",
+"output":[["StartTag", "a", {"a":"@"}]]},
+
+{"description":"<a a=\"A\">",
+"input":"<a a=\"A\">",
+"output":[["StartTag", "a", {"a":"A"}]]},
+
+{"description":"<a a=\"B\">",
+"input":"<a a=\"B\">",
+"output":[["StartTag", "a", {"a":"B"}]]},
+
+{"description":"<a a=\"Y\">",
+"input":"<a a=\"Y\">",
+"output":[["StartTag", "a", {"a":"Y"}]]},
+
+{"description":"<a a=\"Z\">",
+"input":"<a a=\"Z\">",
+"output":[["StartTag", "a", {"a":"Z"}]]},
+
+{"description":"<a a=\"`\">",
+"input":"<a a=\"`\">",
+"output":[["StartTag", "a", {"a":"`"}]]},
+
+{"description":"<a a=\"a\">",
+"input":"<a a=\"a\">",
+"output":[["StartTag", "a", {"a":"a"}]]},
+
+{"description":"<a a=\"b\">",
+"input":"<a a=\"b\">",
+"output":[["StartTag", "a", {"a":"b"}]]},
+
+{"description":"<a a=\"y\">",
+"input":"<a a=\"y\">",
+"output":[["StartTag", "a", {"a":"y"}]]},
+
+{"description":"<a a=\"z\">",
+"input":"<a a=\"z\">",
+"output":[["StartTag", "a", {"a":"z"}]]},
+
+{"description":"<a a=\"{\">",
+"input":"<a a=\"{\">",
+"output":[["StartTag", "a", {"a":"{"}]]},
+
+{"description":"<a a=\"\\uDBC0\\uDC00\">",
+"input":"<a a=\"\uDBC0\uDC00\">",
+"output":[["StartTag", "a", {"a":"\uDBC0\uDC00"}]]},
+
+{"description":"<a a=#>",
+"input":"<a a=#>",
+"output":[["StartTag", "a", {"a":"#"}]]},
+
+{"description":"<a a=%>",
+"input":"<a a=%>",
+"output":[["StartTag", "a", {"a":"%"}]]},
+
+{"description":"<a a=&>",
+"input":"<a a=&>",
+"output":[["StartTag", "a", {"a":"&"}]]},
+
+{"description":"<a a=''>",
+"input":"<a a=''>",
+"output":[["StartTag", "a", {"a":""}]]},
+
+{"description":"<a a='\\u0000'>",
+"input":"<a a='\u0000'>",
+"output":["ParseError", ["StartTag", "a", {"a":"\uFFFD"}]]},
+
+{"description":"<a a='\\u0009'>",
+"input":"<a a='\u0009'>",
+"output":[["StartTag", "a", {"a":"\u0009"}]]},
+
+{"description":"<a a='\\u000A'>",
+"input":"<a a='\u000A'>",
+"output":[["StartTag", "a", {"a":"\u000A"}]]},
+
+{"description":"<a a='\\u000B'>",
+"input":"<a a='\u000B'>",
+"output":["ParseError", ["StartTag", "a", {"a":"\u000B"}]]},
+
+{"description":"<a a='\\u000C'>",
+"input":"<a a='\u000C'>",
+"output":[["StartTag", "a", {"a":"\u000C"}]]},
+
+{"description":"<a a=' '>",
+"input":"<a a=' '>",
+"output":[["StartTag", "a", {"a":" "}]]},
+
+{"description":"<a a='!'>",
+"input":"<a a='!'>",
+"output":[["StartTag", "a", {"a":"!"}]]},
+
+{"description":"<a a='\"'>",
+"input":"<a a='\"'>",
+"output":[["StartTag", "a", {"a":"\""}]]},
+
+{"description":"<a a='%'>",
+"input":"<a a='%'>",
+"output":[["StartTag", "a", {"a":"%"}]]},
+
+{"description":"<a a='&'>",
+"input":"<a a='&'>",
+"output":[["StartTag", "a", {"a":"&"}]]},
+
+{"description":"<a a=''>",
+"input":"<a a=''>",
+"output":[["StartTag", "a", {"a":""}]]},
+
+{"description":"<a a=''\\u0000>",
+"input":"<a a=''\u0000>",
+"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"", "\uFFFD":""}]]},
+
+{"description":"<a a=''\\u0008>",
+"input":"<a a=''\u0008>",
+"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"", "\u0008":""}]]},
+
+{"description":"<a a=''\\u0009>",
+"input":"<a a=''\u0009>",
+"output":[["StartTag", "a", {"a":""}]]},
+
+{"description":"<a a=''\\u000A>",
+"input":"<a a=''\u000A>",
+"output":[["StartTag", "a", {"a":""}]]},
+
+{"description":"<a a=''\\u000B>",
+"input":"<a a=''\u000B>",
+"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"", "\u000B":""}]]},
+
+{"description":"<a a=''\\u000C>",
+"input":"<a a=''\u000C>",
+"output":[["StartTag", "a", {"a":""}]]},
+
+{"description":"<a a=''\\u000D>",
+"input":"<a a=''\u000D>",
+"output":[["StartTag", "a", {"a":""}]]},
+
+{"description":"<a a=''\\u001F>",
+"input":"<a a=''\u001F>",
+"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"", "\u001F":""}]]},
+
+{"description":"<a a='' >",
+"input":"<a a='' >",
+"output":[["StartTag", "a", {"a":""}]]},
+
+{"description":"<a a=''!>",
+"input":"<a a=''!>",
+"output":["ParseError", ["StartTag", "a", {"a":"", "!":""}]]},
+
+{"description":"<a a=''\">",
+"input":"<a a=''\">",
+"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"", "\"":""}]]},
+
+{"description":"<a a=''&>",
+"input":"<a a=''&>",
+"output":["ParseError", ["StartTag", "a", {"a":"", "&":""}]]},
+
+{"description":"<a a='''>",
+"input":"<a a='''>",
+"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"", "'":""}]]},
+
+{"description":"<a a=''->",
+"input":"<a a=''->",
+"output":["ParseError", ["StartTag", "a", {"a":"", "-":""}]]},
+
+{"description":"<a a=''.>",
+"input":"<a a=''.>",
+"output":["ParseError", ["StartTag", "a", {"a":"", ".":""}]]},
+
+{"description":"<a a=''/>",
+"input":"<a a=''/>",
+"output":[["StartTag", "a", {"a":""}, true]]},
+
+{"description":"<a a=''0>",
+"input":"<a a=''0>",
+"output":["ParseError", ["StartTag", "a", {"a":"", "0":""}]]},
+
+{"description":"<a a=''1>",
+"input":"<a a=''1>",
+"output":["ParseError", ["StartTag", "a", {"a":"", "1":""}]]},
+
+{"description":"<a a=''9>",
+"input":"<a a=''9>",
+"output":["ParseError", ["StartTag", "a", {"a":"", "9":""}]]},
+
+{"description":"<a a=''<>",
+"input":"<a a=''<>",
+"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"", "<":""}]]},
+
+{"description":"<a a=''=>",
+"input":"<a a=''=>",
+"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"", "=":""}]]},
+
+{"description":"<a a=''>",
+"input":"<a a=''>",
+"output":[["StartTag", "a", {"a":""}]]},
+
+{"description":"<a a=''?>",
+"input":"<a a=''?>",
+"output":["ParseError", ["StartTag", "a", {"a":"", "?":""}]]},
+
+{"description":"<a a=''@>",
+"input":"<a a=''@>",
+"output":["ParseError", ["StartTag", "a", {"a":"", "@":""}]]},
+
+{"description":"<a a=''A>",
+"input":"<a a=''A>",
+"output":["ParseError", "ParseError", ["StartTag", "a", {"a":""}]]},
+
+{"description":"<a a=''B>",
+"input":"<a a=''B>",
+"output":["ParseError", ["StartTag", "a", {"a":"", "b":""}]]},
+
+{"description":"<a a=''Y>",
+"input":"<a a=''Y>",
+"output":["ParseError", ["StartTag", "a", {"a":"", "y":""}]]},
+
+{"description":"<a a=''Z>",
+"input":"<a a=''Z>",
+"output":["ParseError", ["StartTag", "a", {"a":"", "z":""}]]},
+
+{"description":"<a a=''`>",
+"input":"<a a=''`>",
+"output":["ParseError", ["StartTag", "a", {"a":"", "`":""}]]},
+
+{"description":"<a a=''a>",
+"input":"<a a=''a>",
+"output":["ParseError", "ParseError", ["StartTag", "a", {"a":""}]]},
+
+{"description":"<a a=''b>",
+"input":"<a a=''b>",
+"output":["ParseError", ["StartTag", "a", {"a":"", "b":""}]]},
+
+{"description":"<a a=''y>",
+"input":"<a a=''y>",
+"output":["ParseError", ["StartTag", "a", {"a":"", "y":""}]]},
+
+{"description":"<a a=''z>",
+"input":"<a a=''z>",
+"output":["ParseError", ["StartTag", "a", {"a":"", "z":""}]]},
+
+{"description":"<a a=''{>",
+"input":"<a a=''{>",
+"output":["ParseError", ["StartTag", "a", {"a":"", "{":""}]]},
+
+{"description":"<a a=''\\uDBC0\\uDC00>",
+"input":"<a a=''\uDBC0\uDC00>",
+"output":["ParseError", ["StartTag", "a", {"a":"", "\uDBC0\uDC00":""}]]},
+
+{"description":"<a a='('>",
+"input":"<a a='('>",
+"output":[["StartTag", "a", {"a":"("}]]},
+
+{"description":"<a a='-'>",
+"input":"<a a='-'>",
+"output":[["StartTag", "a", {"a":"-"}]]},
+
+{"description":"<a a='/'>",
+"input":"<a a='/'>",
+"output":[["StartTag", "a", {"a":"/"}]]},
+
+{"description":"<a a='0'>",
+"input":"<a a='0'>",
+"output":[["StartTag", "a", {"a":"0"}]]},
+
+{"description":"<a a='1'>",
+"input":"<a a='1'>",
+"output":[["StartTag", "a", {"a":"1"}]]},
+
+{"description":"<a a='9'>",
+"input":"<a a='9'>",
+"output":[["StartTag", "a", {"a":"9"}]]},
+
+{"description":"<a a='<'>",
+"input":"<a a='<'>",
+"output":[["StartTag", "a", {"a":"<"}]]},
+
+{"description":"<a a='='>",
+"input":"<a a='='>",
+"output":[["StartTag", "a", {"a":"="}]]},
+
+{"description":"<a a='>'>",
+"input":"<a a='>'>",
+"output":[["StartTag", "a", {"a":">"}]]},
+
+{"description":"<a a='?'>",
+"input":"<a a='?'>",
+"output":[["StartTag", "a", {"a":"?"}]]},
+
+{"description":"<a a='@'>",
+"input":"<a a='@'>",
+"output":[["StartTag", "a", {"a":"@"}]]},
+
+{"description":"<a a='A'>",
+"input":"<a a='A'>",
+"output":[["StartTag", "a", {"a":"A"}]]},
+
+{"description":"<a a='B'>",
+"input":"<a a='B'>",
+"output":[["StartTag", "a", {"a":"B"}]]},
+
+{"description":"<a a='Y'>",
+"input":"<a a='Y'>",
+"output":[["StartTag", "a", {"a":"Y"}]]},
+
+{"description":"<a a='Z'>",
+"input":"<a a='Z'>",
+"output":[["StartTag", "a", {"a":"Z"}]]},
+
+{"description":"<a a='`'>",
+"input":"<a a='`'>",
+"output":[["StartTag", "a", {"a":"`"}]]},
+
+{"description":"<a a='a'>",
+"input":"<a a='a'>",
+"output":[["StartTag", "a", {"a":"a"}]]},
+
+{"description":"<a a='b'>",
+"input":"<a a='b'>",
+"output":[["StartTag", "a", {"a":"b"}]]},
+
+{"description":"<a a='y'>",
+"input":"<a a='y'>",
+"output":[["StartTag", "a", {"a":"y"}]]},
+
+{"description":"<a a='z'>",
+"input":"<a a='z'>",
+"output":[["StartTag", "a", {"a":"z"}]]},
+
+{"description":"<a a='{'>",
+"input":"<a a='{'>",
+"output":[["StartTag", "a", {"a":"{"}]]},
+
+{"description":"<a a='\\uDBC0\\uDC00'>",
+"input":"<a a='\uDBC0\uDC00'>",
+"output":[["StartTag", "a", {"a":"\uDBC0\uDC00"}]]},
+
+{"description":"<a a=(>",
+"input":"<a a=(>",
+"output":[["StartTag", "a", {"a":"("}]]},
+
+{"description":"<a a=->",
+"input":"<a a=->",
+"output":[["StartTag", "a", {"a":"-"}]]},
+
+{"description":"<a a=/>",
+"input":"<a a=/>",
+"output":[["StartTag", "a", {"a":"/"}]]},
+
+{"description":"<a a=0>",
+"input":"<a a=0>",
+"output":[["StartTag", "a", {"a":"0"}]]},
+
+{"description":"<a a=1>",
+"input":"<a a=1>",
+"output":[["StartTag", "a", {"a":"1"}]]},
+
+{"description":"<a a=9>",
+"input":"<a a=9>",
+"output":[["StartTag", "a", {"a":"9"}]]},
+
+{"description":"<a a=<>",
+"input":"<a a=<>",
+"output":["ParseError", ["StartTag", "a", {"a":"<"}]]},
+
+{"description":"<a a==>",
+"input":"<a a==>",
+"output":["ParseError", ["StartTag", "a", {"a":"="}]]},
+
+{"description":"<a a=>",
+"input":"<a a=>",
+"output":["ParseError", ["StartTag", "a", {"a":""}]]},
+
+{"description":"<a a=?>",
+"input":"<a a=?>",
+"output":[["StartTag", "a", {"a":"?"}]]},
+
+{"description":"<a a=@>",
+"input":"<a a=@>",
+"output":[["StartTag", "a", {"a":"@"}]]},
+
+{"description":"<a a=A>",
+"input":"<a a=A>",
+"output":[["StartTag", "a", {"a":"A"}]]},
+
+{"description":"<a a=B>",
+"input":"<a a=B>",
+"output":[["StartTag", "a", {"a":"B"}]]},
+
+{"description":"<a a=Y>",
+"input":"<a a=Y>",
+"output":[["StartTag", "a", {"a":"Y"}]]},
+
+{"description":"<a a=Z>",
+"input":"<a a=Z>",
+"output":[["StartTag", "a", {"a":"Z"}]]},
+
+{"description":"<a a=`>",
+"input":"<a a=`>",
+"output":["ParseError", ["StartTag", "a", {"a":"`"}]]},
+
+{"description":"<a a=a>",
+"input":"<a a=a>",
+"output":[["StartTag", "a", {"a":"a"}]]},
+
+{"description":"<a a=a\\u0000>",
+"input":"<a a=a\u0000>",
+"output":["ParseError", ["StartTag", "a", {"a":"a\uFFFD"}]]},
+
+{"description":"<a a=a\\u0008>",
+"input":"<a a=a\u0008>",
+"output":["ParseError", ["StartTag", "a", {"a":"a\u0008"}]]},
+
+{"description":"<a a=a\\u0009>",
+"input":"<a a=a\u0009>",
+"output":[["StartTag", "a", {"a":"a"}]]},
+
+{"description":"<a a=a\\u000A>",
+"input":"<a a=a\u000A>",
+"output":[["StartTag", "a", {"a":"a"}]]},
+
+{"description":"<a a=a\\u000B>",
+"input":"<a a=a\u000B>",
+"output":["ParseError", ["StartTag", "a", {"a":"a\u000B"}]]},
+
+{"description":"<a a=a\\u000C>",
+"input":"<a a=a\u000C>",
+"output":[["StartTag", "a", {"a":"a"}]]},
+
+{"description":"<a a=a\\u000D>",
+"input":"<a a=a\u000D>",
+"output":[["StartTag", "a", {"a":"a"}]]},
+
+{"description":"<a a=a\\u001F>",
+"input":"<a a=a\u001F>",
+"output":["ParseError", ["StartTag", "a", {"a":"a\u001F"}]]},
+
+{"description":"<a a=a >",
+"input":"<a a=a >",
+"output":[["StartTag", "a", {"a":"a"}]]},
+
+{"description":"<a a=a!>",
+"input":"<a a=a!>",
+"output":[["StartTag", "a", {"a":"a!"}]]},
+
+{"description":"<a a=a\">",
+"input":"<a a=a\">",
+"output":["ParseError", ["StartTag", "a", {"a":"a\""}]]},
+
+{"description":"<a a=a#>",
+"input":"<a a=a#>",
+"output":[["StartTag", "a", {"a":"a#"}]]},
+
+{"description":"<a a=a%>",
+"input":"<a a=a%>",
+"output":[["StartTag", "a", {"a":"a%"}]]},
+
+{"description":"<a a=a&>",
+"input":"<a a=a&>",
+"output":[["StartTag", "a", {"a":"a&"}]]},
+
+{"description":"<a a=a'>",
+"input":"<a a=a'>",
+"output":["ParseError", ["StartTag", "a", {"a":"a'"}]]},
+
+{"description":"<a a=a(>",
+"input":"<a a=a(>",
+"output":[["StartTag", "a", {"a":"a("}]]},
+
+{"description":"<a a=a->",
+"input":"<a a=a->",
+"output":[["StartTag", "a", {"a":"a-"}]]},
+
+{"description":"<a a=a/>",
+"input":"<a a=a/>",
+"output":[["StartTag", "a", {"a":"a/"}]]},
+
+{"description":"<a a=a0>",
+"input":"<a a=a0>",
+"output":[["StartTag", "a", {"a":"a0"}]]},
+
+{"description":"<a a=a1>",
+"input":"<a a=a1>",
+"output":[["StartTag", "a", {"a":"a1"}]]},
+
+{"description":"<a a=a9>",
+"input":"<a a=a9>",
+"output":[["StartTag", "a", {"a":"a9"}]]},
+
+{"description":"<a a=a<>",
+"input":"<a a=a<>",
+"output":["ParseError", ["StartTag", "a", {"a":"a<"}]]},
+
+{"description":"<a a=a=>",
+"input":"<a a=a=>",
+"output":["ParseError", ["StartTag", "a", {"a":"a="}]]},
+
+{"description":"<a a=a>",
+"input":"<a a=a>",
+"output":[["StartTag", "a", {"a":"a"}]]},
+
+{"description":"<a a=a?>",
+"input":"<a a=a?>",
+"output":[["StartTag", "a", {"a":"a?"}]]},
+
+{"description":"<a a=a@>",
+"input":"<a a=a@>",
+"output":[["StartTag", "a", {"a":"a@"}]]},
+
+{"description":"<a a=aA>",
+"input":"<a a=aA>",
+"output":[["StartTag", "a", {"a":"aA"}]]},
+
+{"description":"<a a=aB>",
+"input":"<a a=aB>",
+"output":[["StartTag", "a", {"a":"aB"}]]},
+
+{"description":"<a a=aY>",
+"input":"<a a=aY>",
+"output":[["StartTag", "a", {"a":"aY"}]]},
+
+{"description":"<a a=aZ>",
+"input":"<a a=aZ>",
+"output":[["StartTag", "a", {"a":"aZ"}]]},
+
+{"description":"<a a=a`>",
+"input":"<a a=a`>",
+"output":["ParseError", ["StartTag", "a", {"a":"a`"}]]},
+
+{"description":"<a a=aa>",
+"input":"<a a=aa>",
+"output":[["StartTag", "a", {"a":"aa"}]]},
+
+{"description":"<a a=ab>",
+"input":"<a a=ab>",
+"output":[["StartTag", "a", {"a":"ab"}]]},
+
+{"description":"<a a=ay>",
+"input":"<a a=ay>",
+"output":[["StartTag", "a", {"a":"ay"}]]},
+
+{"description":"<a a=az>",
+"input":"<a a=az>",
+"output":[["StartTag", "a", {"a":"az"}]]},
+
+{"description":"<a a=a{>",
+"input":"<a a=a{>",
+"output":[["StartTag", "a", {"a":"a{"}]]},
+
+{"description":"<a a=a\\uDBC0\\uDC00>",
+"input":"<a a=a\uDBC0\uDC00>",
+"output":[["StartTag", "a", {"a":"a\uDBC0\uDC00"}]]},
+
+{"description":"<a a=b>",
+"input":"<a a=b>",
+"output":[["StartTag", "a", {"a":"b"}]]},
+
+{"description":"<a a=y>",
+"input":"<a a=y>",
+"output":[["StartTag", "a", {"a":"y"}]]},
+
+{"description":"<a a=z>",
+"input":"<a a=z>",
+"output":[["StartTag", "a", {"a":"z"}]]},
+
+{"description":"<a a={>",
+"input":"<a a={>",
+"output":[["StartTag", "a", {"a":"{"}]]},
+
+{"description":"<a a=\\uDBC0\\uDC00>",
+"input":"<a a=\uDBC0\uDC00>",
+"output":[["StartTag", "a", {"a":"\uDBC0\uDC00"}]]},
+
+{"description":"<a a>",
+"input":"<a a>",
+"output":[["StartTag", "a", {"a":""}]]},
+
+{"description":"<a a?>",
+"input":"<a a?>",
+"output":[["StartTag", "a", {"a?":""}]]},
+
+{"description":"<a a@>",
+"input":"<a a@>",
+"output":[["StartTag", "a", {"a@":""}]]},
+
+{"description":"<a aA>",
+"input":"<a aA>",
+"output":[["StartTag", "a", {"aa":""}]]},
+
+{"description":"<a aB>",
+"input":"<a aB>",
+"output":[["StartTag", "a", {"ab":""}]]},
+
+{"description":"<a aY>",
+"input":"<a aY>",
+"output":[["StartTag", "a", {"ay":""}]]},
+
+{"description":"<a aZ>",
+"input":"<a aZ>",
+"output":[["StartTag", "a", {"az":""}]]},
+
+{"description":"<a a[>",
+"input":"<a a[>",
+"output":[["StartTag", "a", {"a[":""}]]},
+
+{"description":"<a a`>",
+"input":"<a a`>",
+"output":[["StartTag", "a", {"a`":""}]]},
+
+{"description":"<a aa>",
+"input":"<a aa>",
+"output":[["StartTag", "a", {"aa":""}]]},
+
+{"description":"<a ab>",
+"input":"<a ab>",
+"output":[["StartTag", "a", {"ab":""}]]},
+
+{"description":"<a ay>",
+"input":"<a ay>",
+"output":[["StartTag", "a", {"ay":""}]]},
+
+{"description":"<a az>",
+"input":"<a az>",
+"output":[["StartTag", "a", {"az":""}]]},
+
+{"description":"<a a{>",
+"input":"<a a{>",
+"output":[["StartTag", "a", {"a{":""}]]},
+
+{"description":"<a a\\uDBC0\\uDC00>",
+"input":"<a a\uDBC0\uDC00>",
+"output":[["StartTag", "a", {"a\uDBC0\uDC00":""}]]},
+
+{"description":"<a b>",
+"input":"<a b>",
+"output":[["StartTag", "a", {"b":""}]]},
+
+{"description":"<a y>",
+"input":"<a y>",
+"output":[["StartTag", "a", {"y":""}]]},
+
+{"description":"<a z>",
+"input":"<a z>",
+"output":[["StartTag", "a", {"z":""}]]},
+
+{"description":"<a {>",
+"input":"<a {>",
+"output":[["StartTag", "a", {"{":""}]]},
+
+{"description":"<a \\uDBC0\\uDC00>",
+"input":"<a \uDBC0\uDC00>",
+"output":[["StartTag", "a", {"\uDBC0\uDC00":""}]]},
+
+{"description":"<a!>",
+"input":"<a!>",
+"output":[["StartTag", "a!", {}]]},
+
+{"description":"<a\">",
+"input":"<a\">",
+"output":[["StartTag", "a\"", {}]]},
+
+{"description":"<a&>",
+"input":"<a&>",
+"output":[["StartTag", "a&", {}]]},
+
+{"description":"<a'>",
+"input":"<a'>",
+"output":[["StartTag", "a'", {}]]},
+
+{"description":"<a->",
+"input":"<a->",
+"output":[["StartTag", "a-", {}]]},
+
+{"description":"<a.>",
+"input":"<a.>",
+"output":[["StartTag", "a.", {}]]},
+
+{"description":"<a/>",
+"input":"<a/>",
+"output":[["StartTag", "a", {}, true]]},
+
+{"description":"<a/\\u0000>",
+"input":"<a/\u0000>",
+"output":["ParseError", "ParseError", ["StartTag", "a", {"\uFFFD":""}]]},
+
+{"description":"<a/\\u0009>",
+"input":"<a/\u0009>",
+"output":["ParseError", ["StartTag", "a", {}]]},
+
+{"description":"<a/\\u000A>",
+"input":"<a/\u000A>",
+"output":["ParseError", ["StartTag", "a", {}]]},
+
+{"description":"<a/\\u000B>",
+"input":"<a/\u000B>",
+"output":["ParseError", "ParseError", ["StartTag", "a", {"\u000B":""}]]},
+
+{"description":"<a/\\u000C>",
+"input":"<a/\u000C>",
+"output":["ParseError", ["StartTag", "a", {}]]},
+
+{"description":"<a/ >",
+"input":"<a/ >",
+"output":["ParseError", ["StartTag", "a", {}]]},
+
+{"description":"<a/!>",
+"input":"<a/!>",
+"output":["ParseError", ["StartTag", "a", {"!":""}]]},
+
+{"description":"<a/\">",
+"input":"<a/\">",
+"output":["ParseError", "ParseError", ["StartTag", "a", {"\"":""}]]},
+
+{"description":"<a/&>",
+"input":"<a/&>",
+"output":["ParseError", ["StartTag", "a", {"&":""}]]},
+
+{"description":"<a/'>",
+"input":"<a/'>",
+"output":["ParseError", "ParseError", ["StartTag", "a", {"'":""}]]},
+
+{"description":"<a/->",
+"input":"<a/->",
+"output":["ParseError", ["StartTag", "a", {"-":""}]]},
+
+{"description":"<a//>",
+"input":"<a//>",
+"output":["ParseError", ["StartTag", "a", {}, true]]},
+
+{"description":"<a/0>",
+"input":"<a/0>",
+"output":["ParseError", ["StartTag", "a", {"0":""}]]},
+
+{"description":"<a/1>",
+"input":"<a/1>",
+"output":["ParseError", ["StartTag", "a", {"1":""}]]},
+
+{"description":"<a/9>",
+"input":"<a/9>",
+"output":["ParseError", ["StartTag", "a", {"9":""}]]},
+
+{"description":"<a/<>",
+"input":"<a/<>",
+"output":["ParseError", "ParseError", ["StartTag", "a", {"<":""}]]},
+
+{"description":"<a/=>",
+"input":"<a/=>",
+"output":["ParseError", "ParseError", ["StartTag", "a", {"=":""}]]},
+
+{"description":"<a/>",
+"input":"<a/>",
+"output":[["StartTag", "a", {}, true]]},
+
+{"description":"<a/?>",
+"input":"<a/?>",
+"output":["ParseError", ["StartTag", "a", {"?":""}]]},
+
+{"description":"<a/@>",
+"input":"<a/@>",
+"output":["ParseError", ["StartTag", "a", {"@":""}]]},
+
+{"description":"<a/A>",
+"input":"<a/A>",
+"output":["ParseError", ["StartTag", "a", {"a":""}]]},
+
+{"description":"<a/B>",
+"input":"<a/B>",
+"output":["ParseError", ["StartTag", "a", {"b":""}]]},
+
+{"description":"<a/Y>",
+"input":"<a/Y>",
+"output":["ParseError", ["StartTag", "a", {"y":""}]]},
+
+{"description":"<a/Z>",
+"input":"<a/Z>",
+"output":["ParseError", ["StartTag", "a", {"z":""}]]},
+
+{"description":"<a/`>",
+"input":"<a/`>",
+"output":["ParseError", ["StartTag", "a", {"`":""}]]},
+
+{"description":"<a/a>",
+"input":"<a/a>",
+"output":["ParseError", ["StartTag", "a", {"a":""}]]},
+
+{"description":"<a/b>",
+"input":"<a/b>",
+"output":["ParseError", ["StartTag", "a", {"b":""}]]},
+
+{"description":"<a/y>",
+"input":"<a/y>",
+"output":["ParseError", ["StartTag", "a", {"y":""}]]},
+
+{"description":"<a/z>",
+"input":"<a/z>",
+"output":["ParseError", ["StartTag", "a", {"z":""}]]},
+
+{"description":"<a/{>",
+"input":"<a/{>",
+"output":["ParseError", ["StartTag", "a", {"{":""}]]},
+
+{"description":"<a/\\uDBC0\\uDC00>",
+"input":"<a/\uDBC0\uDC00>",
+"output":["ParseError", ["StartTag", "a", {"\uDBC0\uDC00":""}]]},
+
+{"description":"<a0>",
+"input":"<a0>",
+"output":[["StartTag", "a0", {}]]},
+
+{"description":"<a1>",
+"input":"<a1>",
+"output":[["StartTag", "a1", {}]]},
+
+{"description":"<a9>",
+"input":"<a9>",
+"output":[["StartTag", "a9", {}]]},
+
+{"description":"<a<>",
+"input":"<a<>",
+"output":[["StartTag", "a<", {}]]},
+
+{"description":"<a=>",
+"input":"<a=>",
+"output":[["StartTag", "a=", {}]]},
+
+{"description":"<a>",
+"input":"<a>",
+"output":[["StartTag", "a", {}]]},
+
+{"description":"<a?>",
+"input":"<a?>",
+"output":[["StartTag", "a?", {}]]},
+
+{"description":"<a@>",
+"input":"<a@>",
+"output":[["StartTag", "a@", {}]]},
+
+{"description":"<aA>",
+"input":"<aA>",
+"output":[["StartTag", "aa", {}]]},
+
+{"description":"<aB>",
+"input":"<aB>",
+"output":[["StartTag", "ab", {}]]},
+
+{"description":"<aY>",
+"input":"<aY>",
+"output":[["StartTag", "ay", {}]]},
+
+{"description":"<aZ>",
+"input":"<aZ>",
+"output":[["StartTag", "az", {}]]},
+
+{"description":"<a[>",
+"input":"<a[>",
+"output":[["StartTag", "a[", {}]]},
+
+{"description":"<a`>",
+"input":"<a`>",
+"output":[["StartTag", "a`", {}]]},
+
+{"description":"<aa>",
+"input":"<aa>",
+"output":[["StartTag", "aa", {}]]},
+
+{"description":"<ab>",
+"input":"<ab>",
+"output":[["StartTag", "ab", {}]]},
+
+{"description":"<ay>",
+"input":"<ay>",
+"output":[["StartTag", "ay", {}]]},
+
+{"description":"<az>",
+"input":"<az>",
+"output":[["StartTag", "az", {}]]},
+
+{"description":"<a{>",
+"input":"<a{>",
+"output":[["StartTag", "a{", {}]]},
+
+{"description":"<a\\uDBC0\\uDC00>",
+"input":"<a\uDBC0\uDC00>",
+"output":[["StartTag", "a\uDBC0\uDC00", {}]]},
+
+{"description":"<b>",
+"input":"<b>",
+"output":[["StartTag", "b", {}]]},
+
+{"description":"<y>",
+"input":"<y>",
+"output":[["StartTag", "y", {}]]},
+
+{"description":"<z>",
+"input":"<z>",
+"output":[["StartTag", "z", {}]]},
+
+{"description":"<{",
+"input":"<{",
+"output":["ParseError", ["Character", "<{"]]},
+
+{"description":"<\\uDBC0\\uDC00",
+"input":"<\uDBC0\uDC00",
+"output":["ParseError", ["Character", "<\uDBC0\uDC00"]]},
+
+{"description":"=",
+"input":"=",
+"output":[["Character", "="]]},
+
+{"description":">",
+"input":">",
+"output":[["Character", ">"]]},
+
+{"description":"?",
+"input":"?",
+"output":[["Character", "?"]]},
+
+{"description":"@",
+"input":"@",
+"output":[["Character", "@"]]},
+
+{"description":"A",
+"input":"A",
+"output":[["Character", "A"]]},
+
+{"description":"B",
+"input":"B",
+"output":[["Character", "B"]]},
+
+{"description":"Y",
+"input":"Y",
+"output":[["Character", "Y"]]},
+
+{"description":"Z",
+"input":"Z",
+"output":[["Character", "Z"]]},
+
+{"description":"`",
+"input":"`",
+"output":[["Character", "`"]]},
+
+{"description":"a",
+"input":"a",
+"output":[["Character", "a"]]},
+
+{"description":"b",
+"input":"b",
+"output":[["Character", "b"]]},
+
+{"description":"y",
+"input":"y",
+"output":[["Character", "y"]]},
+
+{"description":"z",
+"input":"z",
+"output":[["Character", "z"]]},
+
+{"description":"{",
+"input":"{",
+"output":[["Character", "{"]]},
+
+{"description":"\\uDBC0\\uDC00",
+"input":"\uDBC0\uDC00",
+"output":[["Character", "\uDBC0\uDC00"]]}
+
+]}
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/test4.test b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/test4.test
new file mode 100644
index 00000000000..4be94b0c7e4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/test4.test
@@ -0,0 +1,344 @@
+{"tests": [
+
+{"description":"< in attribute name",
+"input":"<z/0 <>",
+"output":["ParseError", "ParseError", ["StartTag", "z", {"0": "", "<": ""}]]},
+
+{"description":"< in attribute value",
+"input":"<z x=<>",
+"output":["ParseError", ["StartTag", "z", {"x": "<"}]]},
+
+{"description":"= in unquoted attribute value",
+"input":"<z z=z=z>",
+"output":["ParseError", ["StartTag", "z", {"z": "z=z"}]]},
+
+{"description":"= attribute",
+"input":"<z =>",
+"output":["ParseError", ["StartTag", "z", {"=": ""}]]},
+
+{"description":"== attribute",
+"input":"<z ==>",
+"output":["ParseError", "ParseError", ["StartTag", "z", {"=": ""}]]},
+
+{"description":"=== attribute",
+"input":"<z ===>",
+"output":["ParseError", "ParseError", ["StartTag", "z", {"=": "="}]]},
+
+{"description":"==== attribute",
+"input":"<z ====>",
+"output":["ParseError", "ParseError", "ParseError", ["StartTag", "z", {"=": "=="}]]},
+
+{"description":"\" after ampersand in double-quoted attribute value",
+"input":"<z z=\"&\">",
+"output":[["StartTag", "z", {"z": "&"}]]},
+
+{"description":"' after ampersand in double-quoted attribute value",
+"input":"<z z=\"&'\">",
+"output":[["StartTag", "z", {"z": "&'"}]]},
+
+{"description":"' after ampersand in single-quoted attribute value",
+"input":"<z z='&'>",
+"output":[["StartTag", "z", {"z": "&"}]]},
+
+{"description":"\" after ampersand in single-quoted attribute value",
+"input":"<z z='&\"'>",
+"output":[["StartTag", "z", {"z": "&\""}]]},
+
+{"description":"Text after bogus character reference",
+"input":"<z z='&xlink_xmlns;'>bar<z>",
+"output":[["StartTag","z",{"z":"&xlink_xmlns;"}],["Character","bar"],["StartTag","z",{}]]},
+
+{"description":"Text after hex character reference",
+"input":"<z z='&#x0020; foo'>bar<z>",
+"output":[["StartTag","z",{"z":" foo"}],["Character","bar"],["StartTag","z",{}]]},
+
+{"description":"Attribute name starting with \"",
+"input":"<foo \"='bar'>",
+"output":["ParseError", ["StartTag", "foo", {"\"": "bar"}]]},
+
+{"description":"Attribute name starting with '",
+"input":"<foo '='bar'>",
+"output":["ParseError", ["StartTag", "foo", {"'": "bar"}]]},
+
+{"description":"Attribute name containing \"",
+"input":"<foo a\"b='bar'>",
+"output":["ParseError", ["StartTag", "foo", {"a\"b": "bar"}]]},
+
+{"description":"Attribute name containing '",
+"input":"<foo a'b='bar'>",
+"output":["ParseError", ["StartTag", "foo", {"a'b": "bar"}]]},
+
+{"description":"Unquoted attribute value containing '",
+"input":"<foo a=b'c>",
+"output":["ParseError", ["StartTag", "foo", {"a": "b'c"}]]},
+
+{"description":"Unquoted attribute value containing \"",
+"input":"<foo a=b\"c>",
+"output":["ParseError", ["StartTag", "foo", {"a": "b\"c"}]]},
+
+{"description":"Double-quoted attribute value not followed by whitespace",
+"input":"<foo a=\"b\"c>",
+"output":["ParseError", ["StartTag", "foo", {"a": "b", "c": ""}]]},
+
+{"description":"Single-quoted attribute value not followed by whitespace",
+"input":"<foo a='b'c>",
+"output":["ParseError", ["StartTag", "foo", {"a": "b", "c": ""}]]},
+
+{"description":"Quoted attribute followed by permitted /",
+"input":"<br a='b'/>",
+"output":[["StartTag","br",{"a":"b"},true]]},
+
+{"description":"Quoted attribute followed by non-permitted /",
+"input":"<bar a='b'/>",
+"output":[["StartTag","bar",{"a":"b"},true]]},
+
+{"description":"CR EOF after doctype name",
+"input":"<!doctype html \r",
+"output":["ParseError", ["DOCTYPE", "html", null, null, false]]},
+
+{"description":"CR EOF in tag name",
+"input":"<z\r",
+"output":["ParseError"]},
+
+{"description":"Slash EOF in tag name",
+"input":"<z/",
+"output":["ParseError"]},
+
+{"description":"Zero hex numeric entity",
+"input":"&#x0",
+"output":["ParseError", "ParseError", ["Character", "\uFFFD"]]},
+
+{"description":"Zero decimal numeric entity",
+"input":"&#0",
+"output":["ParseError", "ParseError", ["Character", "\uFFFD"]]},
+
+{"description":"Zero-prefixed hex numeric entity",
+"input":"&#x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041;",
+"output":[["Character", "A"]]},
+
+{"description":"Zero-prefixed decimal numeric entity",
+"input":"&#000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000065;",
+"output":[["Character", "A"]]},
+
+{"description":"Empty hex numeric entities",
+"input":"&#x &#X ",
+"output":["ParseError", ["Character", "&#x "], "ParseError", ["Character", "&#X "]]},
+
+{"description":"Empty decimal numeric entities",
+"input":"&# &#; ",
+"output":["ParseError", ["Character", "&# "], "ParseError", ["Character", "&#; "]]},
+
+{"description":"Non-BMP numeric entity",
+"input":"&#x10000;",
+"output":[["Character", "\uD800\uDC00"]]},
+
+{"description":"Maximum non-BMP numeric entity",
+"input":"&#X10FFFF;",
+"output":["ParseError", ["Character", "\uDBFF\uDFFF"]]},
+
+{"description":"Above maximum numeric entity",
+"input":"&#x110000;",
+"output":["ParseError", ["Character", "\uFFFD"]]},
+
+{"description":"32-bit hex numeric entity",
+"input":"&#x80000041;",
+"output":["ParseError", ["Character", "\uFFFD"]]},
+
+{"description":"33-bit hex numeric entity",
+"input":"&#x100000041;",
+"output":["ParseError", ["Character", "\uFFFD"]]},
+
+{"description":"33-bit decimal numeric entity",
+"input":"&#4294967361;",
+"output":["ParseError", ["Character", "\uFFFD"]]},
+
+{"description":"65-bit hex numeric entity",
+"input":"&#x10000000000000041;",
+"output":["ParseError", ["Character", "\uFFFD"]]},
+
+{"description":"65-bit decimal numeric entity",
+"input":"&#18446744073709551681;",
+"output":["ParseError", ["Character", "\uFFFD"]]},
+
+{"description":"Surrogate code point edge cases",
+"input":"&#xD7FF;&#xD800;&#xD801;&#xDFFE;&#xDFFF;&#xE000;",
+"output":[["Character", "\uD7FF"], "ParseError", ["Character", "\uFFFD"], "ParseError", ["Character", "\uFFFD"], "ParseError", ["Character", "\uFFFD"], "ParseError", ["Character", "\uFFFD\uE000"]]},
+
+{"description":"Uppercase start tag name",
+"input":"<X>",
+"output":[["StartTag", "x", {}]]},
+
+{"description":"Uppercase end tag name",
+"input":"</X>",
+"output":[["EndTag", "x"]]},
+
+{"description":"Uppercase attribute name",
+"input":"<x X>",
+"output":[["StartTag", "x", { "x":"" }]]},
+
+{"description":"Tag/attribute name case edge values",
+"input":"<x@AZ[`az{ @AZ[`az{>",
+"output":[["StartTag", "x@az[`az{", { "@az[`az{":"" }]]},
+
+{"description":"Duplicate different-case attributes",
+"input":"<x x=1 x=2 X=3>",
+"output":["ParseError", "ParseError", ["StartTag", "x", { "x":"1" }]]},
+
+{"description":"Uppercase close tag attributes",
+"input":"</x X>",
+"output":["ParseError", ["EndTag", "x"]]},
+
+{"description":"Duplicate close tag attributes",
+"input":"</x x x>",
+"output":["ParseError", "ParseError", ["EndTag", "x"]]},
+
+{"description":"Permitted slash",
+"input":"<br/>",
+"output":[["StartTag","br",{},true]]},
+
+{"description":"Non-permitted slash",
+"input":"<xr/>",
+"output":[["StartTag","xr",{},true]]},
+
+{"description":"Permitted slash but in close tag",
+"input":"</br/>",
+"output":["ParseError", ["EndTag", "br"]]},
+
+{"description":"Doctype public case-sensitivity (1)",
+"input":"<!DoCtYpE HtMl PuBlIc \"AbC\" \"XyZ\">",
+"output":[["DOCTYPE", "html", "AbC", "XyZ", true]]},
+
+{"description":"Doctype public case-sensitivity (2)",
+"input":"<!dOcTyPe hTmL pUbLiC \"aBc\" \"xYz\">",
+"output":[["DOCTYPE", "html", "aBc", "xYz", true]]},
+
+{"description":"Doctype system case-sensitivity (1)",
+"input":"<!DoCtYpE HtMl SyStEm \"XyZ\">",
+"output":[["DOCTYPE", "html", null, "XyZ", true]]},
+
+{"description":"Doctype system case-sensitivity (2)",
+"input":"<!dOcTyPe hTmL sYsTeM \"xYz\">",
+"output":[["DOCTYPE", "html", null, "xYz", true]]},
+
+{"description":"U+0000 in lookahead region after non-matching character",
+"input":"<!doc>\u0000",
+"output":["ParseError", ["Comment", "doc"], "ParseError", ["Character", "\u0000"]],
+"ignoreErrorOrder":true},
+
+{"description":"U+0000 in lookahead region",
+"input":"<!doc\u0000",
+"output":["ParseError", ["Comment", "doc\uFFFD"]],
+"ignoreErrorOrder":true},
+
+{"description":"U+0080 in lookahead region",
+"input":"<!doc\u0080",
+"output":["ParseError", "ParseError", ["Comment", "doc\u0080"]],
+"ignoreErrorOrder":true},
+
+{"description":"U+FDD1 in lookahead region",
+"input":"<!doc\uFDD1",
+"output":["ParseError", "ParseError", ["Comment", "doc\uFDD1"]],
+"ignoreErrorOrder":true},
+
+{"description":"U+1FFFF in lookahead region",
+"input":"<!doc\uD83F\uDFFF",
+"output":["ParseError", "ParseError", ["Comment", "doc\uD83F\uDFFF"]],
+"ignoreErrorOrder":true},
+
+{"description":"CR followed by non-LF",
+"input":"\r?",
+"output":[["Character", "\n?"]]},
+
+{"description":"CR at EOF",
+"input":"\r",
+"output":[["Character", "\n"]]},
+
+{"description":"LF at EOF",
+"input":"\n",
+"output":[["Character", "\n"]]},
+
+{"description":"CR LF",
+"input":"\r\n",
+"output":[["Character", "\n"]]},
+
+{"description":"CR CR",
+"input":"\r\r",
+"output":[["Character", "\n\n"]]},
+
+{"description":"LF LF",
+"input":"\n\n",
+"output":[["Character", "\n\n"]]},
+
+{"description":"LF CR",
+"input":"\n\r",
+"output":[["Character", "\n\n"]]},
+
+{"description":"text CR CR CR text",
+"input":"text\r\r\rtext",
+"output":[["Character", "text\n\n\ntext"]]},
+
+{"description":"Doctype publik",
+"input":"<!DOCTYPE html PUBLIK \"AbC\" \"XyZ\">",
+"output":["ParseError", ["DOCTYPE", "html", null, null, false]]},
+
+{"description":"Doctype publi",
+"input":"<!DOCTYPE html PUBLI",
+"output":["ParseError", ["DOCTYPE", "html", null, null, false]]},
+
+{"description":"Doctype sistem",
+"input":"<!DOCTYPE html SISTEM \"AbC\">",
+"output":["ParseError", ["DOCTYPE", "html", null, null, false]]},
+
+{"description":"Doctype sys",
+"input":"<!DOCTYPE html SYS",
+"output":["ParseError", ["DOCTYPE", "html", null, null, false]]},
+
+{"description":"Doctype html x>text",
+"input":"<!DOCTYPE html x>text",
+"output":["ParseError", ["DOCTYPE", "html", null, null, false], ["Character", "text"]]},
+
+{"description":"Grave accent in unquoted attribute",
+"input":"<a a=aa`>",
+"output":["ParseError", ["StartTag", "a", {"a":"aa`"}]]},
+
+{"description":"EOF in tag name state ",
+"input":"<a",
+"output":["ParseError"]},
+
+{"description":"EOF in tag name state",
+"input":"<a",
+"output":["ParseError"]},
+
+{"description":"EOF in before attribute name state",
+"input":"<a ",
+"output":["ParseError"]},
+
+{"description":"EOF in attribute name state",
+"input":"<a a",
+"output":["ParseError"]},
+
+{"description":"EOF in after attribute name state",
+"input":"<a a ",
+"output":["ParseError"]},
+
+{"description":"EOF in before attribute value state",
+"input":"<a a =",
+"output":["ParseError"]},
+
+{"description":"EOF in attribute value (double quoted) state",
+"input":"<a a =\"a",
+"output":["ParseError"]},
+
+{"description":"EOF in attribute value (single quoted) state",
+"input":"<a a ='a",
+"output":["ParseError"]},
+
+{"description":"EOF in attribute value (unquoted) state",
+"input":"<a a =a",
+"output":["ParseError"]},
+
+{"description":"EOF in after attribute value state",
+"input":"<a a ='a'",
+"output":["ParseError"]}
+
+]}
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/unicodeChars.test b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/unicodeChars.test
new file mode 100644
index 00000000000..c7786682cbd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/unicodeChars.test
@@ -0,0 +1,1295 @@
+{"tests": [
+
+{"description": "Invalid Unicode character U+0001",
+"input": "\u0001",
+"output": ["ParseError", ["Character", "\u0001"]]},
+
+{"description": "Invalid Unicode character U+0002",
+"input": "\u0002",
+"output": ["ParseError", ["Character", "\u0002"]]},
+
+{"description": "Invalid Unicode character U+0003",
+"input": "\u0003",
+"output": ["ParseError", ["Character", "\u0003"]]},
+
+{"description": "Invalid Unicode character U+0004",
+"input": "\u0004",
+"output": ["ParseError", ["Character", "\u0004"]]},
+
+{"description": "Invalid Unicode character U+0005",
+"input": "\u0005",
+"output": ["ParseError", ["Character", "\u0005"]]},
+
+{"description": "Invalid Unicode character U+0006",
+"input": "\u0006",
+"output": ["ParseError", ["Character", "\u0006"]]},
+
+{"description": "Invalid Unicode character U+0007",
+"input": "\u0007",
+"output": ["ParseError", ["Character", "\u0007"]]},
+
+{"description": "Invalid Unicode character U+0008",
+"input": "\u0008",
+"output": ["ParseError", ["Character", "\u0008"]]},
+
+{"description": "Invalid Unicode character U+000B",
+"input": "\u000B",
+"output": ["ParseError", ["Character", "\u000B"]]},
+
+{"description": "Invalid Unicode character U+000E",
+"input": "\u000E",
+"output": ["ParseError", ["Character", "\u000E"]]},
+
+{"description": "Invalid Unicode character U+000F",
+"input": "\u000F",
+"output": ["ParseError", ["Character", "\u000F"]]},
+
+{"description": "Invalid Unicode character U+0010",
+"input": "\u0010",
+"output": ["ParseError", ["Character", "\u0010"]]},
+
+{"description": "Invalid Unicode character U+0011",
+"input": "\u0011",
+"output": ["ParseError", ["Character", "\u0011"]]},
+
+{"description": "Invalid Unicode character U+0012",
+"input": "\u0012",
+"output": ["ParseError", ["Character", "\u0012"]]},
+
+{"description": "Invalid Unicode character U+0013",
+"input": "\u0013",
+"output": ["ParseError", ["Character", "\u0013"]]},
+
+{"description": "Invalid Unicode character U+0014",
+"input": "\u0014",
+"output": ["ParseError", ["Character", "\u0014"]]},
+
+{"description": "Invalid Unicode character U+0015",
+"input": "\u0015",
+"output": ["ParseError", ["Character", "\u0015"]]},
+
+{"description": "Invalid Unicode character U+0016",
+"input": "\u0016",
+"output": ["ParseError", ["Character", "\u0016"]]},
+
+{"description": "Invalid Unicode character U+0017",
+"input": "\u0017",
+"output": ["ParseError", ["Character", "\u0017"]]},
+
+{"description": "Invalid Unicode character U+0018",
+"input": "\u0018",
+"output": ["ParseError", ["Character", "\u0018"]]},
+
+{"description": "Invalid Unicode character U+0019",
+"input": "\u0019",
+"output": ["ParseError", ["Character", "\u0019"]]},
+
+{"description": "Invalid Unicode character U+001A",
+"input": "\u001A",
+"output": ["ParseError", ["Character", "\u001A"]]},
+
+{"description": "Invalid Unicode character U+001B",
+"input": "\u001B",
+"output": ["ParseError", ["Character", "\u001B"]]},
+
+{"description": "Invalid Unicode character U+001C",
+"input": "\u001C",
+"output": ["ParseError", ["Character", "\u001C"]]},
+
+{"description": "Invalid Unicode character U+001D",
+"input": "\u001D",
+"output": ["ParseError", ["Character", "\u001D"]]},
+
+{"description": "Invalid Unicode character U+001E",
+"input": "\u001E",
+"output": ["ParseError", ["Character", "\u001E"]]},
+
+{"description": "Invalid Unicode character U+001F",
+"input": "\u001F",
+"output": ["ParseError", ["Character", "\u001F"]]},
+
+{"description": "Invalid Unicode character U+007F",
+"input": "\u007F",
+"output": ["ParseError", ["Character", "\u007F"]]},
+
+{"description": "Invalid Unicode character U+FDD0",
+"input": "\uFDD0",
+"output": ["ParseError", ["Character", "\uFDD0"]]},
+
+{"description": "Invalid Unicode character U+FDD1",
+"input": "\uFDD1",
+"output": ["ParseError", ["Character", "\uFDD1"]]},
+
+{"description": "Invalid Unicode character U+FDD2",
+"input": "\uFDD2",
+"output": ["ParseError", ["Character", "\uFDD2"]]},
+
+{"description": "Invalid Unicode character U+FDD3",
+"input": "\uFDD3",
+"output": ["ParseError", ["Character", "\uFDD3"]]},
+
+{"description": "Invalid Unicode character U+FDD4",
+"input": "\uFDD4",
+"output": ["ParseError", ["Character", "\uFDD4"]]},
+
+{"description": "Invalid Unicode character U+FDD5",
+"input": "\uFDD5",
+"output": ["ParseError", ["Character", "\uFDD5"]]},
+
+{"description": "Invalid Unicode character U+FDD6",
+"input": "\uFDD6",
+"output": ["ParseError", ["Character", "\uFDD6"]]},
+
+{"description": "Invalid Unicode character U+FDD7",
+"input": "\uFDD7",
+"output": ["ParseError", ["Character", "\uFDD7"]]},
+
+{"description": "Invalid Unicode character U+FDD8",
+"input": "\uFDD8",
+"output": ["ParseError", ["Character", "\uFDD8"]]},
+
+{"description": "Invalid Unicode character U+FDD9",
+"input": "\uFDD9",
+"output": ["ParseError", ["Character", "\uFDD9"]]},
+
+{"description": "Invalid Unicode character U+FDDA",
+"input": "\uFDDA",
+"output": ["ParseError", ["Character", "\uFDDA"]]},
+
+{"description": "Invalid Unicode character U+FDDB",
+"input": "\uFDDB",
+"output": ["ParseError", ["Character", "\uFDDB"]]},
+
+{"description": "Invalid Unicode character U+FDDC",
+"input": "\uFDDC",
+"output": ["ParseError", ["Character", "\uFDDC"]]},
+
+{"description": "Invalid Unicode character U+FDDD",
+"input": "\uFDDD",
+"output": ["ParseError", ["Character", "\uFDDD"]]},
+
+{"description": "Invalid Unicode character U+FDDE",
+"input": "\uFDDE",
+"output": ["ParseError", ["Character", "\uFDDE"]]},
+
+{"description": "Invalid Unicode character U+FDDF",
+"input": "\uFDDF",
+"output": ["ParseError", ["Character", "\uFDDF"]]},
+
+{"description": "Invalid Unicode character U+FDE0",
+"input": "\uFDE0",
+"output": ["ParseError", ["Character", "\uFDE0"]]},
+
+{"description": "Invalid Unicode character U+FDE1",
+"input": "\uFDE1",
+"output": ["ParseError", ["Character", "\uFDE1"]]},
+
+{"description": "Invalid Unicode character U+FDE2",
+"input": "\uFDE2",
+"output": ["ParseError", ["Character", "\uFDE2"]]},
+
+{"description": "Invalid Unicode character U+FDE3",
+"input": "\uFDE3",
+"output": ["ParseError", ["Character", "\uFDE3"]]},
+
+{"description": "Invalid Unicode character U+FDE4",
+"input": "\uFDE4",
+"output": ["ParseError", ["Character", "\uFDE4"]]},
+
+{"description": "Invalid Unicode character U+FDE5",
+"input": "\uFDE5",
+"output": ["ParseError", ["Character", "\uFDE5"]]},
+
+{"description": "Invalid Unicode character U+FDE6",
+"input": "\uFDE6",
+"output": ["ParseError", ["Character", "\uFDE6"]]},
+
+{"description": "Invalid Unicode character U+FDE7",
+"input": "\uFDE7",
+"output": ["ParseError", ["Character", "\uFDE7"]]},
+
+{"description": "Invalid Unicode character U+FDE8",
+"input": "\uFDE8",
+"output": ["ParseError", ["Character", "\uFDE8"]]},
+
+{"description": "Invalid Unicode character U+FDE9",
+"input": "\uFDE9",
+"output": ["ParseError", ["Character", "\uFDE9"]]},
+
+{"description": "Invalid Unicode character U+FDEA",
+"input": "\uFDEA",
+"output": ["ParseError", ["Character", "\uFDEA"]]},
+
+{"description": "Invalid Unicode character U+FDEB",
+"input": "\uFDEB",
+"output": ["ParseError", ["Character", "\uFDEB"]]},
+
+{"description": "Invalid Unicode character U+FDEC",
+"input": "\uFDEC",
+"output": ["ParseError", ["Character", "\uFDEC"]]},
+
+{"description": "Invalid Unicode character U+FDED",
+"input": "\uFDED",
+"output": ["ParseError", ["Character", "\uFDED"]]},
+
+{"description": "Invalid Unicode character U+FDEE",
+"input": "\uFDEE",
+"output": ["ParseError", ["Character", "\uFDEE"]]},
+
+{"description": "Invalid Unicode character U+FDEF",
+"input": "\uFDEF",
+"output": ["ParseError", ["Character", "\uFDEF"]]},
+
+{"description": "Invalid Unicode character U+FFFE",
+"input": "\uFFFE",
+"output": ["ParseError", ["Character", "\uFFFE"]]},
+
+{"description": "Invalid Unicode character U+FFFF",
+"input": "\uFFFF",
+"output": ["ParseError", ["Character", "\uFFFF"]]},
+
+{"description": "Invalid Unicode character U+1FFFE",
+"input": "\uD83F\uDFFE",
+"output": ["ParseError", ["Character", "\uD83F\uDFFE"]]},
+
+{"description": "Invalid Unicode character U+1FFFF",
+"input": "\uD83F\uDFFF",
+"output": ["ParseError", ["Character", "\uD83F\uDFFF"]]},
+
+{"description": "Invalid Unicode character U+2FFFE",
+"input": "\uD87F\uDFFE",
+"output": ["ParseError", ["Character", "\uD87F\uDFFE"]]},
+
+{"description": "Invalid Unicode character U+2FFFF",
+"input": "\uD87F\uDFFF",
+"output": ["ParseError", ["Character", "\uD87F\uDFFF"]]},
+
+{"description": "Invalid Unicode character U+3FFFE",
+"input": "\uD8BF\uDFFE",
+"output": ["ParseError", ["Character", "\uD8BF\uDFFE"]]},
+
+{"description": "Invalid Unicode character U+3FFFF",
+"input": "\uD8BF\uDFFF",
+"output": ["ParseError", ["Character", "\uD8BF\uDFFF"]]},
+
+{"description": "Invalid Unicode character U+4FFFE",
+"input": "\uD8FF\uDFFE",
+"output": ["ParseError", ["Character", "\uD8FF\uDFFE"]]},
+
+{"description": "Invalid Unicode character U+4FFFF",
+"input": "\uD8FF\uDFFF",
+"output": ["ParseError", ["Character", "\uD8FF\uDFFF"]]},
+
+{"description": "Invalid Unicode character U+5FFFE",
+"input": "\uD93F\uDFFE",
+"output": ["ParseError", ["Character", "\uD93F\uDFFE"]]},
+
+{"description": "Invalid Unicode character U+5FFFF",
+"input": "\uD93F\uDFFF",
+"output": ["ParseError", ["Character", "\uD93F\uDFFF"]]},
+
+{"description": "Invalid Unicode character U+6FFFE",
+"input": "\uD97F\uDFFE",
+"output": ["ParseError", ["Character", "\uD97F\uDFFE"]]},
+
+{"description": "Invalid Unicode character U+6FFFF",
+"input": "\uD97F\uDFFF",
+"output": ["ParseError", ["Character", "\uD97F\uDFFF"]]},
+
+{"description": "Invalid Unicode character U+7FFFE",
+"input": "\uD9BF\uDFFE",
+"output": ["ParseError", ["Character", "\uD9BF\uDFFE"]]},
+
+{"description": "Invalid Unicode character U+7FFFF",
+"input": "\uD9BF\uDFFF",
+"output": ["ParseError", ["Character", "\uD9BF\uDFFF"]]},
+
+{"description": "Invalid Unicode character U+8FFFE",
+"input": "\uD9FF\uDFFE",
+"output": ["ParseError", ["Character", "\uD9FF\uDFFE"]]},
+
+{"description": "Invalid Unicode character U+8FFFF",
+"input": "\uD9FF\uDFFF",
+"output": ["ParseError", ["Character", "\uD9FF\uDFFF"]]},
+
+{"description": "Invalid Unicode character U+9FFFE",
+"input": "\uDA3F\uDFFE",
+"output": ["ParseError", ["Character", "\uDA3F\uDFFE"]]},
+
+{"description": "Invalid Unicode character U+9FFFF",
+"input": "\uDA3F\uDFFF",
+"output": ["ParseError", ["Character", "\uDA3F\uDFFF"]]},
+
+{"description": "Invalid Unicode character U+AFFFE",
+"input": "\uDA7F\uDFFE",
+"output": ["ParseError", ["Character", "\uDA7F\uDFFE"]]},
+
+{"description": "Invalid Unicode character U+AFFFF",
+"input": "\uDA7F\uDFFF",
+"output": ["ParseError", ["Character", "\uDA7F\uDFFF"]]},
+
+{"description": "Invalid Unicode character U+BFFFE",
+"input": "\uDABF\uDFFE",
+"output": ["ParseError", ["Character", "\uDABF\uDFFE"]]},
+
+{"description": "Invalid Unicode character U+BFFFF",
+"input": "\uDABF\uDFFF",
+"output": ["ParseError", ["Character", "\uDABF\uDFFF"]]},
+
+{"description": "Invalid Unicode character U+CFFFE",
+"input": "\uDAFF\uDFFE",
+"output": ["ParseError", ["Character", "\uDAFF\uDFFE"]]},
+
+{"description": "Invalid Unicode character U+CFFFF",
+"input": "\uDAFF\uDFFF",
+"output": ["ParseError", ["Character", "\uDAFF\uDFFF"]]},
+
+{"description": "Invalid Unicode character U+DFFFE",
+"input": "\uDB3F\uDFFE",
+"output": ["ParseError", ["Character", "\uDB3F\uDFFE"]]},
+
+{"description": "Invalid Unicode character U+DFFFF",
+"input": "\uDB3F\uDFFF",
+"output": ["ParseError", ["Character", "\uDB3F\uDFFF"]]},
+
+{"description": "Invalid Unicode character U+EFFFE",
+"input": "\uDB7F\uDFFE",
+"output": ["ParseError", ["Character", "\uDB7F\uDFFE"]]},
+
+{"description": "Invalid Unicode character U+EFFFF",
+"input": "\uDB7F\uDFFF",
+"output": ["ParseError", ["Character", "\uDB7F\uDFFF"]]},
+
+{"description": "Invalid Unicode character U+FFFFE",
+"input": "\uDBBF\uDFFE",
+"output": ["ParseError", ["Character", "\uDBBF\uDFFE"]]},
+
+{"description": "Invalid Unicode character U+FFFFF",
+"input": "\uDBBF\uDFFF",
+"output": ["ParseError", ["Character", "\uDBBF\uDFFF"]]},
+
+{"description": "Invalid Unicode character U+10FFFE",
+"input": "\uDBFF\uDFFE",
+"output": ["ParseError", ["Character", "\uDBFF\uDFFE"]]},
+
+{"description": "Invalid Unicode character U+10FFFF",
+"input": "\uDBFF\uDFFF",
+"output": ["ParseError", ["Character", "\uDBFF\uDFFF"]]},
+
+{"description": "Valid Unicode character U+0009",
+"input": "\u0009",
+"output": [["Character", "\u0009"]]},
+
+{"description": "Valid Unicode character U+000A",
+"input": "\u000A",
+"output": [["Character", "\u000A"]]},
+
+{"description": "Valid Unicode character U+0020",
+"input": "\u0020",
+"output": [["Character", "\u0020"]]},
+
+{"description": "Valid Unicode character U+0021",
+"input": "\u0021",
+"output": [["Character", "\u0021"]]},
+
+{"description": "Valid Unicode character U+0022",
+"input": "\u0022",
+"output": [["Character", "\u0022"]]},
+
+{"description": "Valid Unicode character U+0023",
+"input": "\u0023",
+"output": [["Character", "\u0023"]]},
+
+{"description": "Valid Unicode character U+0024",
+"input": "\u0024",
+"output": [["Character", "\u0024"]]},
+
+{"description": "Valid Unicode character U+0025",
+"input": "\u0025",
+"output": [["Character", "\u0025"]]},
+
+{"description": "Valid Unicode character U+0026",
+"input": "\u0026",
+"output": [["Character", "\u0026"]]},
+
+{"description": "Valid Unicode character U+0027",
+"input": "\u0027",
+"output": [["Character", "\u0027"]]},
+
+{"description": "Valid Unicode character U+0028",
+"input": "\u0028",
+"output": [["Character", "\u0028"]]},
+
+{"description": "Valid Unicode character U+0029",
+"input": "\u0029",
+"output": [["Character", "\u0029"]]},
+
+{"description": "Valid Unicode character U+002A",
+"input": "\u002A",
+"output": [["Character", "\u002A"]]},
+
+{"description": "Valid Unicode character U+002B",
+"input": "\u002B",
+"output": [["Character", "\u002B"]]},
+
+{"description": "Valid Unicode character U+002C",
+"input": "\u002C",
+"output": [["Character", "\u002C"]]},
+
+{"description": "Valid Unicode character U+002D",
+"input": "\u002D",
+"output": [["Character", "\u002D"]]},
+
+{"description": "Valid Unicode character U+002E",
+"input": "\u002E",
+"output": [["Character", "\u002E"]]},
+
+{"description": "Valid Unicode character U+002F",
+"input": "\u002F",
+"output": [["Character", "\u002F"]]},
+
+{"description": "Valid Unicode character U+0030",
+"input": "\u0030",
+"output": [["Character", "\u0030"]]},
+
+{"description": "Valid Unicode character U+0031",
+"input": "\u0031",
+"output": [["Character", "\u0031"]]},
+
+{"description": "Valid Unicode character U+0032",
+"input": "\u0032",
+"output": [["Character", "\u0032"]]},
+
+{"description": "Valid Unicode character U+0033",
+"input": "\u0033",
+"output": [["Character", "\u0033"]]},
+
+{"description": "Valid Unicode character U+0034",
+"input": "\u0034",
+"output": [["Character", "\u0034"]]},
+
+{"description": "Valid Unicode character U+0035",
+"input": "\u0035",
+"output": [["Character", "\u0035"]]},
+
+{"description": "Valid Unicode character U+0036",
+"input": "\u0036",
+"output": [["Character", "\u0036"]]},
+
+{"description": "Valid Unicode character U+0037",
+"input": "\u0037",
+"output": [["Character", "\u0037"]]},
+
+{"description": "Valid Unicode character U+0038",
+"input": "\u0038",
+"output": [["Character", "\u0038"]]},
+
+{"description": "Valid Unicode character U+0039",
+"input": "\u0039",
+"output": [["Character", "\u0039"]]},
+
+{"description": "Valid Unicode character U+003A",
+"input": "\u003A",
+"output": [["Character", "\u003A"]]},
+
+{"description": "Valid Unicode character U+003B",
+"input": "\u003B",
+"output": [["Character", "\u003B"]]},
+
+{"description": "Valid Unicode character U+003D",
+"input": "\u003D",
+"output": [["Character", "\u003D"]]},
+
+{"description": "Valid Unicode character U+003E",
+"input": "\u003E",
+"output": [["Character", "\u003E"]]},
+
+{"description": "Valid Unicode character U+003F",
+"input": "\u003F",
+"output": [["Character", "\u003F"]]},
+
+{"description": "Valid Unicode character U+0040",
+"input": "\u0040",
+"output": [["Character", "\u0040"]]},
+
+{"description": "Valid Unicode character U+0041",
+"input": "\u0041",
+"output": [["Character", "\u0041"]]},
+
+{"description": "Valid Unicode character U+0042",
+"input": "\u0042",
+"output": [["Character", "\u0042"]]},
+
+{"description": "Valid Unicode character U+0043",
+"input": "\u0043",
+"output": [["Character", "\u0043"]]},
+
+{"description": "Valid Unicode character U+0044",
+"input": "\u0044",
+"output": [["Character", "\u0044"]]},
+
+{"description": "Valid Unicode character U+0045",
+"input": "\u0045",
+"output": [["Character", "\u0045"]]},
+
+{"description": "Valid Unicode character U+0046",
+"input": "\u0046",
+"output": [["Character", "\u0046"]]},
+
+{"description": "Valid Unicode character U+0047",
+"input": "\u0047",
+"output": [["Character", "\u0047"]]},
+
+{"description": "Valid Unicode character U+0048",
+"input": "\u0048",
+"output": [["Character", "\u0048"]]},
+
+{"description": "Valid Unicode character U+0049",
+"input": "\u0049",
+"output": [["Character", "\u0049"]]},
+
+{"description": "Valid Unicode character U+004A",
+"input": "\u004A",
+"output": [["Character", "\u004A"]]},
+
+{"description": "Valid Unicode character U+004B",
+"input": "\u004B",
+"output": [["Character", "\u004B"]]},
+
+{"description": "Valid Unicode character U+004C",
+"input": "\u004C",
+"output": [["Character", "\u004C"]]},
+
+{"description": "Valid Unicode character U+004D",
+"input": "\u004D",
+"output": [["Character", "\u004D"]]},
+
+{"description": "Valid Unicode character U+004E",
+"input": "\u004E",
+"output": [["Character", "\u004E"]]},
+
+{"description": "Valid Unicode character U+004F",
+"input": "\u004F",
+"output": [["Character", "\u004F"]]},
+
+{"description": "Valid Unicode character U+0050",
+"input": "\u0050",
+"output": [["Character", "\u0050"]]},
+
+{"description": "Valid Unicode character U+0051",
+"input": "\u0051",
+"output": [["Character", "\u0051"]]},
+
+{"description": "Valid Unicode character U+0052",
+"input": "\u0052",
+"output": [["Character", "\u0052"]]},
+
+{"description": "Valid Unicode character U+0053",
+"input": "\u0053",
+"output": [["Character", "\u0053"]]},
+
+{"description": "Valid Unicode character U+0054",
+"input": "\u0054",
+"output": [["Character", "\u0054"]]},
+
+{"description": "Valid Unicode character U+0055",
+"input": "\u0055",
+"output": [["Character", "\u0055"]]},
+
+{"description": "Valid Unicode character U+0056",
+"input": "\u0056",
+"output": [["Character", "\u0056"]]},
+
+{"description": "Valid Unicode character U+0057",
+"input": "\u0057",
+"output": [["Character", "\u0057"]]},
+
+{"description": "Valid Unicode character U+0058",
+"input": "\u0058",
+"output": [["Character", "\u0058"]]},
+
+{"description": "Valid Unicode character U+0059",
+"input": "\u0059",
+"output": [["Character", "\u0059"]]},
+
+{"description": "Valid Unicode character U+005A",
+"input": "\u005A",
+"output": [["Character", "\u005A"]]},
+
+{"description": "Valid Unicode character U+005B",
+"input": "\u005B",
+"output": [["Character", "\u005B"]]},
+
+{"description": "Valid Unicode character U+005C",
+"input": "\u005C",
+"output": [["Character", "\u005C"]]},
+
+{"description": "Valid Unicode character U+005D",
+"input": "\u005D",
+"output": [["Character", "\u005D"]]},
+
+{"description": "Valid Unicode character U+005E",
+"input": "\u005E",
+"output": [["Character", "\u005E"]]},
+
+{"description": "Valid Unicode character U+005F",
+"input": "\u005F",
+"output": [["Character", "\u005F"]]},
+
+{"description": "Valid Unicode character U+0060",
+"input": "\u0060",
+"output": [["Character", "\u0060"]]},
+
+{"description": "Valid Unicode character U+0061",
+"input": "\u0061",
+"output": [["Character", "\u0061"]]},
+
+{"description": "Valid Unicode character U+0062",
+"input": "\u0062",
+"output": [["Character", "\u0062"]]},
+
+{"description": "Valid Unicode character U+0063",
+"input": "\u0063",
+"output": [["Character", "\u0063"]]},
+
+{"description": "Valid Unicode character U+0064",
+"input": "\u0064",
+"output": [["Character", "\u0064"]]},
+
+{"description": "Valid Unicode character U+0065",
+"input": "\u0065",
+"output": [["Character", "\u0065"]]},
+
+{"description": "Valid Unicode character U+0066",
+"input": "\u0066",
+"output": [["Character", "\u0066"]]},
+
+{"description": "Valid Unicode character U+0067",
+"input": "\u0067",
+"output": [["Character", "\u0067"]]},
+
+{"description": "Valid Unicode character U+0068",
+"input": "\u0068",
+"output": [["Character", "\u0068"]]},
+
+{"description": "Valid Unicode character U+0069",
+"input": "\u0069",
+"output": [["Character", "\u0069"]]},
+
+{"description": "Valid Unicode character U+006A",
+"input": "\u006A",
+"output": [["Character", "\u006A"]]},
+
+{"description": "Valid Unicode character U+006B",
+"input": "\u006B",
+"output": [["Character", "\u006B"]]},
+
+{"description": "Valid Unicode character U+006C",
+"input": "\u006C",
+"output": [["Character", "\u006C"]]},
+
+{"description": "Valid Unicode character U+006D",
+"input": "\u006D",
+"output": [["Character", "\u006D"]]},
+
+{"description": "Valid Unicode character U+006E",
+"input": "\u006E",
+"output": [["Character", "\u006E"]]},
+
+{"description": "Valid Unicode character U+006F",
+"input": "\u006F",
+"output": [["Character", "\u006F"]]},
+
+{"description": "Valid Unicode character U+0070",
+"input": "\u0070",
+"output": [["Character", "\u0070"]]},
+
+{"description": "Valid Unicode character U+0071",
+"input": "\u0071",
+"output": [["Character", "\u0071"]]},
+
+{"description": "Valid Unicode character U+0072",
+"input": "\u0072",
+"output": [["Character", "\u0072"]]},
+
+{"description": "Valid Unicode character U+0073",
+"input": "\u0073",
+"output": [["Character", "\u0073"]]},
+
+{"description": "Valid Unicode character U+0074",
+"input": "\u0074",
+"output": [["Character", "\u0074"]]},
+
+{"description": "Valid Unicode character U+0075",
+"input": "\u0075",
+"output": [["Character", "\u0075"]]},
+
+{"description": "Valid Unicode character U+0076",
+"input": "\u0076",
+"output": [["Character", "\u0076"]]},
+
+{"description": "Valid Unicode character U+0077",
+"input": "\u0077",
+"output": [["Character", "\u0077"]]},
+
+{"description": "Valid Unicode character U+0078",
+"input": "\u0078",
+"output": [["Character", "\u0078"]]},
+
+{"description": "Valid Unicode character U+0079",
+"input": "\u0079",
+"output": [["Character", "\u0079"]]},
+
+{"description": "Valid Unicode character U+007A",
+"input": "\u007A",
+"output": [["Character", "\u007A"]]},
+
+{"description": "Valid Unicode character U+007B",
+"input": "\u007B",
+"output": [["Character", "\u007B"]]},
+
+{"description": "Valid Unicode character U+007C",
+"input": "\u007C",
+"output": [["Character", "\u007C"]]},
+
+{"description": "Valid Unicode character U+007D",
+"input": "\u007D",
+"output": [["Character", "\u007D"]]},
+
+{"description": "Valid Unicode character U+007E",
+"input": "\u007E",
+"output": [["Character", "\u007E"]]},
+
+{"description": "Valid Unicode character U+00A0",
+"input": "\u00A0",
+"output": [["Character", "\u00A0"]]},
+
+{"description": "Valid Unicode character U+00A1",
+"input": "\u00A1",
+"output": [["Character", "\u00A1"]]},
+
+{"description": "Valid Unicode character U+00A2",
+"input": "\u00A2",
+"output": [["Character", "\u00A2"]]},
+
+{"description": "Valid Unicode character U+00A3",
+"input": "\u00A3",
+"output": [["Character", "\u00A3"]]},
+
+{"description": "Valid Unicode character U+00A4",
+"input": "\u00A4",
+"output": [["Character", "\u00A4"]]},
+
+{"description": "Valid Unicode character U+00A5",
+"input": "\u00A5",
+"output": [["Character", "\u00A5"]]},
+
+{"description": "Valid Unicode character U+00A6",
+"input": "\u00A6",
+"output": [["Character", "\u00A6"]]},
+
+{"description": "Valid Unicode character U+00A7",
+"input": "\u00A7",
+"output": [["Character", "\u00A7"]]},
+
+{"description": "Valid Unicode character U+00A8",
+"input": "\u00A8",
+"output": [["Character", "\u00A8"]]},
+
+{"description": "Valid Unicode character U+00A9",
+"input": "\u00A9",
+"output": [["Character", "\u00A9"]]},
+
+{"description": "Valid Unicode character U+00AA",
+"input": "\u00AA",
+"output": [["Character", "\u00AA"]]},
+
+{"description": "Valid Unicode character U+00AB",
+"input": "\u00AB",
+"output": [["Character", "\u00AB"]]},
+
+{"description": "Valid Unicode character U+00AC",
+"input": "\u00AC",
+"output": [["Character", "\u00AC"]]},
+
+{"description": "Valid Unicode character U+00AD",
+"input": "\u00AD",
+"output": [["Character", "\u00AD"]]},
+
+{"description": "Valid Unicode character U+00AE",
+"input": "\u00AE",
+"output": [["Character", "\u00AE"]]},
+
+{"description": "Valid Unicode character U+00AF",
+"input": "\u00AF",
+"output": [["Character", "\u00AF"]]},
+
+{"description": "Valid Unicode character U+00B0",
+"input": "\u00B0",
+"output": [["Character", "\u00B0"]]},
+
+{"description": "Valid Unicode character U+00B1",
+"input": "\u00B1",
+"output": [["Character", "\u00B1"]]},
+
+{"description": "Valid Unicode character U+00B2",
+"input": "\u00B2",
+"output": [["Character", "\u00B2"]]},
+
+{"description": "Valid Unicode character U+00B3",
+"input": "\u00B3",
+"output": [["Character", "\u00B3"]]},
+
+{"description": "Valid Unicode character U+00B4",
+"input": "\u00B4",
+"output": [["Character", "\u00B4"]]},
+
+{"description": "Valid Unicode character U+00B5",
+"input": "\u00B5",
+"output": [["Character", "\u00B5"]]},
+
+{"description": "Valid Unicode character U+00B6",
+"input": "\u00B6",
+"output": [["Character", "\u00B6"]]},
+
+{"description": "Valid Unicode character U+00B7",
+"input": "\u00B7",
+"output": [["Character", "\u00B7"]]},
+
+{"description": "Valid Unicode character U+00B8",
+"input": "\u00B8",
+"output": [["Character", "\u00B8"]]},
+
+{"description": "Valid Unicode character U+00B9",
+"input": "\u00B9",
+"output": [["Character", "\u00B9"]]},
+
+{"description": "Valid Unicode character U+00BA",
+"input": "\u00BA",
+"output": [["Character", "\u00BA"]]},
+
+{"description": "Valid Unicode character U+00BB",
+"input": "\u00BB",
+"output": [["Character", "\u00BB"]]},
+
+{"description": "Valid Unicode character U+00BC",
+"input": "\u00BC",
+"output": [["Character", "\u00BC"]]},
+
+{"description": "Valid Unicode character U+00BD",
+"input": "\u00BD",
+"output": [["Character", "\u00BD"]]},
+
+{"description": "Valid Unicode character U+00BE",
+"input": "\u00BE",
+"output": [["Character", "\u00BE"]]},
+
+{"description": "Valid Unicode character U+00BF",
+"input": "\u00BF",
+"output": [["Character", "\u00BF"]]},
+
+{"description": "Valid Unicode character U+00C0",
+"input": "\u00C0",
+"output": [["Character", "\u00C0"]]},
+
+{"description": "Valid Unicode character U+00C1",
+"input": "\u00C1",
+"output": [["Character", "\u00C1"]]},
+
+{"description": "Valid Unicode character U+00C2",
+"input": "\u00C2",
+"output": [["Character", "\u00C2"]]},
+
+{"description": "Valid Unicode character U+00C3",
+"input": "\u00C3",
+"output": [["Character", "\u00C3"]]},
+
+{"description": "Valid Unicode character U+00C4",
+"input": "\u00C4",
+"output": [["Character", "\u00C4"]]},
+
+{"description": "Valid Unicode character U+00C5",
+"input": "\u00C5",
+"output": [["Character", "\u00C5"]]},
+
+{"description": "Valid Unicode character U+00C6",
+"input": "\u00C6",
+"output": [["Character", "\u00C6"]]},
+
+{"description": "Valid Unicode character U+00C7",
+"input": "\u00C7",
+"output": [["Character", "\u00C7"]]},
+
+{"description": "Valid Unicode character U+00C8",
+"input": "\u00C8",
+"output": [["Character", "\u00C8"]]},
+
+{"description": "Valid Unicode character U+00C9",
+"input": "\u00C9",
+"output": [["Character", "\u00C9"]]},
+
+{"description": "Valid Unicode character U+00CA",
+"input": "\u00CA",
+"output": [["Character", "\u00CA"]]},
+
+{"description": "Valid Unicode character U+00CB",
+"input": "\u00CB",
+"output": [["Character", "\u00CB"]]},
+
+{"description": "Valid Unicode character U+00CC",
+"input": "\u00CC",
+"output": [["Character", "\u00CC"]]},
+
+{"description": "Valid Unicode character U+00CD",
+"input": "\u00CD",
+"output": [["Character", "\u00CD"]]},
+
+{"description": "Valid Unicode character U+00CE",
+"input": "\u00CE",
+"output": [["Character", "\u00CE"]]},
+
+{"description": "Valid Unicode character U+00CF",
+"input": "\u00CF",
+"output": [["Character", "\u00CF"]]},
+
+{"description": "Valid Unicode character U+00D0",
+"input": "\u00D0",
+"output": [["Character", "\u00D0"]]},
+
+{"description": "Valid Unicode character U+00D1",
+"input": "\u00D1",
+"output": [["Character", "\u00D1"]]},
+
+{"description": "Valid Unicode character U+00D2",
+"input": "\u00D2",
+"output": [["Character", "\u00D2"]]},
+
+{"description": "Valid Unicode character U+00D3",
+"input": "\u00D3",
+"output": [["Character", "\u00D3"]]},
+
+{"description": "Valid Unicode character U+00D4",
+"input": "\u00D4",
+"output": [["Character", "\u00D4"]]},
+
+{"description": "Valid Unicode character U+00D5",
+"input": "\u00D5",
+"output": [["Character", "\u00D5"]]},
+
+{"description": "Valid Unicode character U+00D6",
+"input": "\u00D6",
+"output": [["Character", "\u00D6"]]},
+
+{"description": "Valid Unicode character U+00D7",
+"input": "\u00D7",
+"output": [["Character", "\u00D7"]]},
+
+{"description": "Valid Unicode character U+00D8",
+"input": "\u00D8",
+"output": [["Character", "\u00D8"]]},
+
+{"description": "Valid Unicode character U+00D9",
+"input": "\u00D9",
+"output": [["Character", "\u00D9"]]},
+
+{"description": "Valid Unicode character U+00DA",
+"input": "\u00DA",
+"output": [["Character", "\u00DA"]]},
+
+{"description": "Valid Unicode character U+00DB",
+"input": "\u00DB",
+"output": [["Character", "\u00DB"]]},
+
+{"description": "Valid Unicode character U+00DC",
+"input": "\u00DC",
+"output": [["Character", "\u00DC"]]},
+
+{"description": "Valid Unicode character U+00DD",
+"input": "\u00DD",
+"output": [["Character", "\u00DD"]]},
+
+{"description": "Valid Unicode character U+00DE",
+"input": "\u00DE",
+"output": [["Character", "\u00DE"]]},
+
+{"description": "Valid Unicode character U+00DF",
+"input": "\u00DF",
+"output": [["Character", "\u00DF"]]},
+
+{"description": "Valid Unicode character U+00E0",
+"input": "\u00E0",
+"output": [["Character", "\u00E0"]]},
+
+{"description": "Valid Unicode character U+00E1",
+"input": "\u00E1",
+"output": [["Character", "\u00E1"]]},
+
+{"description": "Valid Unicode character U+00E2",
+"input": "\u00E2",
+"output": [["Character", "\u00E2"]]},
+
+{"description": "Valid Unicode character U+00E3",
+"input": "\u00E3",
+"output": [["Character", "\u00E3"]]},
+
+{"description": "Valid Unicode character U+00E4",
+"input": "\u00E4",
+"output": [["Character", "\u00E4"]]},
+
+{"description": "Valid Unicode character U+00E5",
+"input": "\u00E5",
+"output": [["Character", "\u00E5"]]},
+
+{"description": "Valid Unicode character U+00E6",
+"input": "\u00E6",
+"output": [["Character", "\u00E6"]]},
+
+{"description": "Valid Unicode character U+00E7",
+"input": "\u00E7",
+"output": [["Character", "\u00E7"]]},
+
+{"description": "Valid Unicode character U+00E8",
+"input": "\u00E8",
+"output": [["Character", "\u00E8"]]},
+
+{"description": "Valid Unicode character U+00E9",
+"input": "\u00E9",
+"output": [["Character", "\u00E9"]]},
+
+{"description": "Valid Unicode character U+00EA",
+"input": "\u00EA",
+"output": [["Character", "\u00EA"]]},
+
+{"description": "Valid Unicode character U+00EB",
+"input": "\u00EB",
+"output": [["Character", "\u00EB"]]},
+
+{"description": "Valid Unicode character U+00EC",
+"input": "\u00EC",
+"output": [["Character", "\u00EC"]]},
+
+{"description": "Valid Unicode character U+00ED",
+"input": "\u00ED",
+"output": [["Character", "\u00ED"]]},
+
+{"description": "Valid Unicode character U+00EE",
+"input": "\u00EE",
+"output": [["Character", "\u00EE"]]},
+
+{"description": "Valid Unicode character U+00EF",
+"input": "\u00EF",
+"output": [["Character", "\u00EF"]]},
+
+{"description": "Valid Unicode character U+00F0",
+"input": "\u00F0",
+"output": [["Character", "\u00F0"]]},
+
+{"description": "Valid Unicode character U+00F1",
+"input": "\u00F1",
+"output": [["Character", "\u00F1"]]},
+
+{"description": "Valid Unicode character U+00F2",
+"input": "\u00F2",
+"output": [["Character", "\u00F2"]]},
+
+{"description": "Valid Unicode character U+00F3",
+"input": "\u00F3",
+"output": [["Character", "\u00F3"]]},
+
+{"description": "Valid Unicode character U+00F4",
+"input": "\u00F4",
+"output": [["Character", "\u00F4"]]},
+
+{"description": "Valid Unicode character U+00F5",
+"input": "\u00F5",
+"output": [["Character", "\u00F5"]]},
+
+{"description": "Valid Unicode character U+00F6",
+"input": "\u00F6",
+"output": [["Character", "\u00F6"]]},
+
+{"description": "Valid Unicode character U+00F7",
+"input": "\u00F7",
+"output": [["Character", "\u00F7"]]},
+
+{"description": "Valid Unicode character U+00F8",
+"input": "\u00F8",
+"output": [["Character", "\u00F8"]]},
+
+{"description": "Valid Unicode character U+00F9",
+"input": "\u00F9",
+"output": [["Character", "\u00F9"]]},
+
+{"description": "Valid Unicode character U+00FA",
+"input": "\u00FA",
+"output": [["Character", "\u00FA"]]},
+
+{"description": "Valid Unicode character U+00FB",
+"input": "\u00FB",
+"output": [["Character", "\u00FB"]]},
+
+{"description": "Valid Unicode character U+00FC",
+"input": "\u00FC",
+"output": [["Character", "\u00FC"]]},
+
+{"description": "Valid Unicode character U+00FD",
+"input": "\u00FD",
+"output": [["Character", "\u00FD"]]},
+
+{"description": "Valid Unicode character U+00FE",
+"input": "\u00FE",
+"output": [["Character", "\u00FE"]]},
+
+{"description": "Valid Unicode character U+00FF",
+"input": "\u00FF",
+"output": [["Character", "\u00FF"]]},
+
+{"description": "Valid Unicode character U+D7FF",
+"input": "\uD7FF",
+"output": [["Character", "\uD7FF"]]},
+
+{"description": "Valid Unicode character U+E000",
+"input": "\uE000",
+"output": [["Character", "\uE000"]]},
+
+{"description": "Valid Unicode character U+FDCF",
+"input": "\uFDCF",
+"output": [["Character", "\uFDCF"]]},
+
+{"description": "Valid Unicode character U+FDF0",
+"input": "\uFDF0",
+"output": [["Character", "\uFDF0"]]},
+
+{"description": "Valid Unicode character U+FFFD",
+"input": "\uFFFD",
+"output": [["Character", "\uFFFD"]]},
+
+{"description": "Valid Unicode character U+10000",
+"input": "\uD800\uDC00",
+"output": [["Character", "\uD800\uDC00"]]},
+
+{"description": "Valid Unicode character U+1FFFD",
+"input": "\uD83F\uDFFD",
+"output": [["Character", "\uD83F\uDFFD"]]},
+
+{"description": "Valid Unicode character U+20000",
+"input": "\uD840\uDC00",
+"output": [["Character", "\uD840\uDC00"]]},
+
+{"description": "Valid Unicode character U+2FFFD",
+"input": "\uD87F\uDFFD",
+"output": [["Character", "\uD87F\uDFFD"]]},
+
+{"description": "Valid Unicode character U+30000",
+"input": "\uD880\uDC00",
+"output": [["Character", "\uD880\uDC00"]]},
+
+{"description": "Valid Unicode character U+3FFFD",
+"input": "\uD8BF\uDFFD",
+"output": [["Character", "\uD8BF\uDFFD"]]},
+
+{"description": "Valid Unicode character U+40000",
+"input": "\uD8C0\uDC00",
+"output": [["Character", "\uD8C0\uDC00"]]},
+
+{"description": "Valid Unicode character U+4FFFD",
+"input": "\uD8FF\uDFFD",
+"output": [["Character", "\uD8FF\uDFFD"]]},
+
+{"description": "Valid Unicode character U+50000",
+"input": "\uD900\uDC00",
+"output": [["Character", "\uD900\uDC00"]]},
+
+{"description": "Valid Unicode character U+5FFFD",
+"input": "\uD93F\uDFFD",
+"output": [["Character", "\uD93F\uDFFD"]]},
+
+{"description": "Valid Unicode character U+60000",
+"input": "\uD940\uDC00",
+"output": [["Character", "\uD940\uDC00"]]},
+
+{"description": "Valid Unicode character U+6FFFD",
+"input": "\uD97F\uDFFD",
+"output": [["Character", "\uD97F\uDFFD"]]},
+
+{"description": "Valid Unicode character U+70000",
+"input": "\uD980\uDC00",
+"output": [["Character", "\uD980\uDC00"]]},
+
+{"description": "Valid Unicode character U+7FFFD",
+"input": "\uD9BF\uDFFD",
+"output": [["Character", "\uD9BF\uDFFD"]]},
+
+{"description": "Valid Unicode character U+80000",
+"input": "\uD9C0\uDC00",
+"output": [["Character", "\uD9C0\uDC00"]]},
+
+{"description": "Valid Unicode character U+8FFFD",
+"input": "\uD9FF\uDFFD",
+"output": [["Character", "\uD9FF\uDFFD"]]},
+
+{"description": "Valid Unicode character U+90000",
+"input": "\uDA00\uDC00",
+"output": [["Character", "\uDA00\uDC00"]]},
+
+{"description": "Valid Unicode character U+9FFFD",
+"input": "\uDA3F\uDFFD",
+"output": [["Character", "\uDA3F\uDFFD"]]},
+
+{"description": "Valid Unicode character U+A0000",
+"input": "\uDA40\uDC00",
+"output": [["Character", "\uDA40\uDC00"]]},
+
+{"description": "Valid Unicode character U+AFFFD",
+"input": "\uDA7F\uDFFD",
+"output": [["Character", "\uDA7F\uDFFD"]]},
+
+{"description": "Valid Unicode character U+B0000",
+"input": "\uDA80\uDC00",
+"output": [["Character", "\uDA80\uDC00"]]},
+
+{"description": "Valid Unicode character U+BFFFD",
+"input": "\uDABF\uDFFD",
+"output": [["Character", "\uDABF\uDFFD"]]},
+
+{"description": "Valid Unicode character U+C0000",
+"input": "\uDAC0\uDC00",
+"output": [["Character", "\uDAC0\uDC00"]]},
+
+{"description": "Valid Unicode character U+CFFFD",
+"input": "\uDAFF\uDFFD",
+"output": [["Character", "\uDAFF\uDFFD"]]},
+
+{"description": "Valid Unicode character U+D0000",
+"input": "\uDB00\uDC00",
+"output": [["Character", "\uDB00\uDC00"]]},
+
+{"description": "Valid Unicode character U+DFFFD",
+"input": "\uDB3F\uDFFD",
+"output": [["Character", "\uDB3F\uDFFD"]]},
+
+{"description": "Valid Unicode character U+E0000",
+"input": "\uDB40\uDC00",
+"output": [["Character", "\uDB40\uDC00"]]},
+
+{"description": "Valid Unicode character U+EFFFD",
+"input": "\uDB7F\uDFFD",
+"output": [["Character", "\uDB7F\uDFFD"]]},
+
+{"description": "Valid Unicode character U+F0000",
+"input": "\uDB80\uDC00",
+"output": [["Character", "\uDB80\uDC00"]]},
+
+{"description": "Valid Unicode character U+FFFFD",
+"input": "\uDBBF\uDFFD",
+"output": [["Character", "\uDBBF\uDFFD"]]},
+
+{"description": "Valid Unicode character U+100000",
+"input": "\uDBC0\uDC00",
+"output": [["Character", "\uDBC0\uDC00"]]},
+
+{"description": "Valid Unicode character U+10FFFD",
+"input": "\uDBFF\uDFFD",
+"output": [["Character", "\uDBFF\uDFFD"]]}
+
+]}
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/unicodeCharsProblematic.test b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/unicodeCharsProblematic.test
new file mode 100644
index 00000000000..8fb54c411f7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/unicodeCharsProblematic.test
@@ -0,0 +1,27 @@
+{"tests" : [
+{"description": "Invalid Unicode character U+DFFF",
+"doubleEscaped":true,
+"input": "\\uDFFF",
+"output":["ParseError", ["Character", "\\uDFFF"]]},
+
+{"description": "Invalid Unicode character U+D800",
+"doubleEscaped":true,
+"input": "\\uD800",
+"output":["ParseError", ["Character", "\\uD800"]]},
+
+{"description": "Invalid Unicode character U+DFFF with valid preceding character",
+"doubleEscaped":true,
+"input": "a\\uDFFF",
+"output":[["Character", "a"], "ParseError", ["Character", "\\uDFFF"]]},
+
+{"description": "Invalid Unicode character U+D800 with valid following character",
+"doubleEscaped":true,
+"input": "\\uD800a",
+"output":["ParseError", ["Character", "\\uD800a"]]},
+
+{"description":"CR followed by U+0000",
+"input":"\r\u0000",
+"output":[["Character", "\n"], "ParseError", ["Character", "\u0000"]],
+"ignoreErrorOrder":true}
+]
+} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/xmlViolation.test b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/xmlViolation.test
new file mode 100644
index 00000000000..137d964295d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tokenizer/xmlViolation.test
@@ -0,0 +1,22 @@
+{"xmlViolationTests": [
+
+{"description":"Non-XML character",
+"input":"a\uFFFFb",
+"ignoreErrorOrder":true,
+"output":["ParseError",["Character","a\uFFFDb"]]},
+
+{"description":"Non-XML space",
+"input":"a\u000Cb",
+"ignoreErrorOrder":true,
+"output":[["Character","a b"]]},
+
+{"description":"Double hyphen in comment",
+"input":"<!-- foo -- bar -->",
+"output":["ParseError",["Comment"," foo - - bar "]]},
+
+{"description":"FF between attributes",
+"input":"<a b=''\u000Cc=''>",
+"output":[["StartTag","a",{"b":"","c":""}]]}
+]}
+
+
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/README.md b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/README.md
new file mode 100644
index 00000000000..2aba4bf860a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/README.md
@@ -0,0 +1,98 @@
+Tree Construction Tests
+=======================
+
+Each file containing tree construction tests consists of any number of
+tests separated by two newlines (LF) and a single newline before the end
+of the file. For instance:
+
+ [TEST]LF
+ LF
+ [TEST]LF
+ LF
+ [TEST]LF
+
+Where [TEST] is the following format:
+
+Each test must begin with a string "\#data" followed by a newline (LF).
+All subsequent lines until a line that says "\#errors" are the test data
+and must be passed to the system being tested unchanged, except with the
+final newline (on the last line) removed.
+
+Then there must be a line that says "\#errors". It must be followed by
+one line per parse error that a conformant checker would return. It
+doesn't matter what those lines are, although they can't be
+"\#document-fragment", "\#document", "\#script-off", "\#script-on", or
+empty, the only thing that matters is that there be the right number
+of parse errors.
+
+Then there \*may\* be a line that says "\#document-fragment", which must
+be followed by a newline (LF), followed by a string of characters that
+indicates the context element, followed by a newline (LF). If this line
+is present the "\#data" must be parsed using the HTML fragment parsing
+algorithm with the context element as context.
+
+Then there \*may\* be a line that says "\#script-off" or
+"\#script-in". If a line that says "\#script-off" is present, the
+parser must set the scripting flag to disabled. If a line that says
+"\#script-on" is present, it must set it to enabled. Otherwise, the
+test should be run in both modes.
+
+Then there must be a line that says "\#document", which must be followed
+by a dump of the tree of the parsed DOM. Each node must be represented
+by a single line. Each line must start with "| ", followed by two spaces
+per parent node that the node has before the root document node.
+
+- Element nodes must be represented by a "`<`" then the *tag name
+ string* "`>`", and all the attributes must be given, sorted
+ lexicographically by UTF-16 code unit according to their *attribute
+ name string*, on subsequent lines, as if they were children of the
+ element node.
+- Attribute nodes must have the *attribute name string*, then an "="
+ sign, then the attribute value in double quotes (").
+- Text nodes must be the string, in double quotes. Newlines aren't
+ escaped.
+- Comments must be "`<`" then "`!-- `" then the data then "` -->`".
+- DOCTYPEs must be "`<!DOCTYPE `" then the name then if either of the
+ system id or public id is non-empty a space, public id in
+ double-quotes, another space an the system id in double-quotes, and
+ then in any case "`>`".
+- Processing instructions must be "`<?`", then the target, then a
+ space, then the data and then "`>`". (The HTML parser cannot emit
+ processing instructions, but scripts can, and the WebVTT to DOM
+ rules can emit them.)
+- Template contents are represented by the string "content" with the
+ children below it.
+
+The *tag name string* is the local name prefixed by a namespace
+designator. For the HTML namespace, the namespace designator is the
+empty string, i.e. there's no prefix. For the SVG namespace, the
+namespace designator is "svg ". For the MathML namespace, the namespace
+designator is "math ".
+
+The *attribute name string* is the local name prefixed by a namespace
+designator. For no namespace, the namespace designator is the empty
+string, i.e. there's no prefix. For the XLink namespace, the namespace
+designator is "xlink ". For the XML namespace, the namespace designator
+is "xml ". For the XMLNS namespace, the namespace designator is "xmlns
+". Note the difference between "xlink:href" which is an attribute in no
+namespace with the local name "xlink:href" and "xlink href" which is an
+attribute in the xlink namespace with the local name "href".
+
+If there is also a "\#document-fragment" the bit following "\#document"
+must be a representation of the HTML fragment serialization for the
+context element given by "\#document-fragment".
+
+For example:
+
+ #data
+ <p>One<p>Two
+ #errors
+ 3: Missing document type declaration
+ #document
+ | <html>
+ | <head>
+ | <body>
+ | <p>
+ | "One"
+ | <p>
+ | "Two"
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/adoption01.dat b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/adoption01.dat
new file mode 100644
index 00000000000..2e1127e5178
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/adoption01.dat
@@ -0,0 +1,337 @@
+#data
+<a><p></a></p>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,10): adoption-agency-1.3
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| <p>
+| <a>
+
+#data
+<a>1<p>2</a>3</p>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,12): adoption-agency-1.3
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| "1"
+| <p>
+| <a>
+| "2"
+| "3"
+
+#data
+<a>1<button>2</a>3</button>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,17): adoption-agency-1.3
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| "1"
+| <button>
+| <a>
+| "2"
+| "3"
+
+#data
+<a>1<b>2</a>3</b>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,12): adoption-agency-1.3
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| "1"
+| <b>
+| "2"
+| <b>
+| "3"
+
+#data
+<a>1<div>2<div>3</a>4</div>5</div>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,20): adoption-agency-1.3
+(1,20): adoption-agency-1.3
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| "1"
+| <div>
+| <a>
+| "2"
+| <div>
+| <a>
+| "3"
+| "4"
+| "5"
+
+#data
+<table><a>1<p>2</a>3</p>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,10): unexpected-start-tag-implies-table-voodoo
+(1,11): unexpected-character-implies-table-voodoo
+(1,14): unexpected-start-tag-implies-table-voodoo
+(1,15): unexpected-character-implies-table-voodoo
+(1,19): unexpected-end-tag-implies-table-voodoo
+(1,19): adoption-agency-1.3
+(1,20): unexpected-character-implies-table-voodoo
+(1,24): unexpected-end-tag-implies-table-voodoo
+(1,24): eof-in-table
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| "1"
+| <p>
+| <a>
+| "2"
+| "3"
+| <table>
+
+#data
+<b><b><a><p></a>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,16): adoption-agency-1.3
+(1,16): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| <b>
+| <a>
+| <p>
+| <a>
+
+#data
+<b><a><b><p></a>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,16): adoption-agency-1.3
+(1,16): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| <a>
+| <b>
+| <b>
+| <p>
+| <a>
+
+#data
+<a><b><b><p></a>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,16): adoption-agency-1.3
+(1,16): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| <b>
+| <b>
+| <b>
+| <b>
+| <p>
+| <a>
+
+#data
+<p>1<s id="A">2<b id="B">3</p>4</s>5</b>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,30): unexpected-end-tag
+(1,35): adoption-agency-1.3
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| "1"
+| <s>
+| id="A"
+| "2"
+| <b>
+| id="B"
+| "3"
+| <s>
+| id="A"
+| <b>
+| id="B"
+| "4"
+| <b>
+| id="B"
+| "5"
+
+#data
+<table><a>1<td>2</td>3</table>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,10): unexpected-start-tag-implies-table-voodoo
+(1,11): unexpected-character-implies-table-voodoo
+(1,15): unexpected-cell-in-table-body
+(1,30): unexpected-implied-end-tag-in-table-view
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| "1"
+| <a>
+| "3"
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| "2"
+
+#data
+<table>A<td>B</td>C</table>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,8): unexpected-character-implies-table-voodoo
+(1,12): unexpected-cell-in-table-body
+(1,22): unexpected-character-implies-table-voodoo
+#document
+| <html>
+| <head>
+| <body>
+| "AC"
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| "B"
+
+#data
+<a><svg><tr><input></a>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,23): unexpected-end-tag
+(1,23): adoption-agency-1.3
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| <svg svg>
+| <svg tr>
+| <svg input>
+
+#data
+<div><a><b><div><div><div><div><div><div><div><div><div><div></a>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,65): adoption-agency-1.3
+(1,65): adoption-agency-1.3
+(1,65): adoption-agency-1.3
+(1,65): adoption-agency-1.3
+(1,65): adoption-agency-1.3
+(1,65): adoption-agency-1.3
+(1,65): adoption-agency-1.3
+(1,65): adoption-agency-1.3
+(1,65): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| <a>
+| <b>
+| <b>
+| <div>
+| <a>
+| <div>
+| <a>
+| <div>
+| <a>
+| <div>
+| <a>
+| <div>
+| <a>
+| <div>
+| <a>
+| <div>
+| <a>
+| <div>
+| <a>
+| <div>
+| <div>
+
+#data
+<div><a><b><u><i><code><div></a>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,32): adoption-agency-1.3
+(1,32): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| <a>
+| <b>
+| <u>
+| <i>
+| <code>
+| <u>
+| <i>
+| <code>
+| <div>
+| <a>
+
+#data
+<b><b><b><b>x</b></b></b></b>y
+#errors
+(1,3): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| <b>
+| <b>
+| <b>
+| "x"
+| "y"
+
+#data
+<p><b><b><b><b><p>x
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,18): unexpected-end-tag
+(1,19): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| <b>
+| <b>
+| <b>
+| <b>
+| <p>
+| <b>
+| <b>
+| <b>
+| "x"
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/adoption02.dat b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/adoption02.dat
new file mode 100644
index 00000000000..e54d8033bac
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/adoption02.dat
@@ -0,0 +1,39 @@
+#data
+<b>1<i>2<p>3</b>4
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,16): adoption-agency-1.3
+(1,17): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| "1"
+| <i>
+| "2"
+| <i>
+| <p>
+| <b>
+| "3"
+| "4"
+
+#data
+<a><div><style></style><address><a>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,35): unexpected-start-tag-implies-end-tag
+(1,35): adoption-agency-1.3
+(1,35): adoption-agency-1.3
+(1,35): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| <div>
+| <a>
+| <style>
+| <address>
+| <a>
+| <a>
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/comments01.dat b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/comments01.dat
new file mode 100644
index 00000000000..35ec6cced63
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/comments01.dat
@@ -0,0 +1,178 @@
+#data
+FOO<!-- BAR -->BAZ
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <!-- BAR -->
+| "BAZ"
+
+#data
+FOO<!-- BAR --!>BAZ
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,15): unexpected-bang-after-double-dash-in-comment
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <!-- BAR -->
+| "BAZ"
+
+#data
+FOO<!-- BAR -- >BAZ
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,15): unexpected-char-in-comment
+(1,21): eof-in-comment
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <!-- BAR -- >BAZ -->
+
+#data
+FOO<!-- BAR -- <QUX> -- MUX -->BAZ
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,15): unexpected-char-in-comment
+(1,24): unexpected-char-in-comment
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <!-- BAR -- <QUX> -- MUX -->
+| "BAZ"
+
+#data
+FOO<!-- BAR -- <QUX> -- MUX --!>BAZ
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,15): unexpected-char-in-comment
+(1,24): unexpected-char-in-comment
+(1,31): unexpected-bang-after-double-dash-in-comment
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <!-- BAR -- <QUX> -- MUX -->
+| "BAZ"
+
+#data
+FOO<!-- BAR -- <QUX> -- MUX -- >BAZ
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,15): unexpected-char-in-comment
+(1,24): unexpected-char-in-comment
+(1,31): unexpected-char-in-comment
+(1,35): eof-in-comment
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <!-- BAR -- <QUX> -- MUX -- >BAZ -->
+
+#data
+FOO<!---->BAZ
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <!-- -->
+| "BAZ"
+
+#data
+FOO<!--->BAZ
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,9): incorrect-comment
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <!-- -->
+| "BAZ"
+
+#data
+FOO<!-->BAZ
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,8): incorrect-comment
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <!-- -->
+| "BAZ"
+
+#data
+<?xml version="1.0">Hi
+#errors
+(1,1): expected-tag-name-but-got-question-mark
+(1,22): expected-doctype-but-got-chars
+#document
+| <!-- ?xml version="1.0" -->
+| <html>
+| <head>
+| <body>
+| "Hi"
+
+#data
+<?xml version="1.0">
+#errors
+(1,1): expected-tag-name-but-got-question-mark
+(1,20): expected-doctype-but-got-eof
+#document
+| <!-- ?xml version="1.0" -->
+| <html>
+| <head>
+| <body>
+
+#data
+<?xml version
+#errors
+(1,1): expected-tag-name-but-got-question-mark
+(1,13): expected-doctype-but-got-eof
+#document
+| <!-- ?xml version -->
+| <html>
+| <head>
+| <body>
+
+#data
+FOO<!----->BAZ
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,10): unexpected-dash-after-double-dash-in-comment
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <!-- - -->
+| "BAZ"
+
+#data
+<html><!-- comment --><title>Comment before head</title>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <!-- comment -->
+| <head>
+| <title>
+| "Comment before head"
+| <body>
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/doctype01.dat b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/doctype01.dat
new file mode 100644
index 00000000000..cec66389710
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/doctype01.dat
@@ -0,0 +1,424 @@
+#data
+<!DOCTYPE html>Hello
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!dOctYpE HtMl>Hello
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPEhtml>Hello
+#errors
+(1,9): need-space-after-doctype
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE>Hello
+#errors
+(1,9): need-space-after-doctype
+(1,10): expected-doctype-name-but-got-right-bracket
+(1,10): unknown-doctype
+#document
+| <!DOCTYPE >
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE >Hello
+#errors
+(1,11): expected-doctype-name-but-got-right-bracket
+(1,11): unknown-doctype
+#document
+| <!DOCTYPE >
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato>Hello
+#errors
+(1,17): unknown-doctype
+#document
+| <!DOCTYPE potato>
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato >Hello
+#errors
+(1,18): unknown-doctype
+#document
+| <!DOCTYPE potato>
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato taco>Hello
+#errors
+(1,17): expected-space-or-right-bracket-in-doctype
+(1,22): unknown-doctype
+#document
+| <!DOCTYPE potato>
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato taco "ddd>Hello
+#errors
+(1,17): expected-space-or-right-bracket-in-doctype
+(1,27): unknown-doctype
+#document
+| <!DOCTYPE potato>
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato sYstEM>Hello
+#errors
+(1,24): unexpected-char-in-doctype
+(1,24): unknown-doctype
+#document
+| <!DOCTYPE potato>
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato sYstEM >Hello
+#errors
+(1,28): unexpected-char-in-doctype
+(1,28): unknown-doctype
+#document
+| <!DOCTYPE potato>
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato sYstEM ggg>Hello
+#errors
+(1,34): unexpected-char-in-doctype
+(1,37): unknown-doctype
+#document
+| <!DOCTYPE potato>
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato SYSTEM taco >Hello
+#errors
+(1,25): unexpected-char-in-doctype
+(1,31): unknown-doctype
+#document
+| <!DOCTYPE potato>
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato SYSTEM 'taco"'>Hello
+#errors
+(1,32): unknown-doctype
+#document
+| <!DOCTYPE potato "" "taco"">
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato SYSTEM "taco">Hello
+#errors
+(1,31): unknown-doctype
+#document
+| <!DOCTYPE potato "" "taco">
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato SYSTEM "tai'co">Hello
+#errors
+(1,33): unknown-doctype
+#document
+| <!DOCTYPE potato "" "tai'co">
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato SYSTEMtaco "ddd">Hello
+#errors
+(1,24): unexpected-char-in-doctype
+(1,34): unknown-doctype
+#document
+| <!DOCTYPE potato>
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato grass SYSTEM taco>Hello
+#errors
+(1,17): expected-space-or-right-bracket-in-doctype
+(1,35): unknown-doctype
+#document
+| <!DOCTYPE potato>
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato pUbLIc>Hello
+#errors
+(1,24): unexpected-end-of-doctype
+(1,24): unknown-doctype
+#document
+| <!DOCTYPE potato>
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato pUbLIc >Hello
+#errors
+(1,25): unexpected-end-of-doctype
+(1,25): unknown-doctype
+#document
+| <!DOCTYPE potato>
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato pUbLIcgoof>Hello
+#errors
+(1,24): unexpected-char-in-doctype
+(1,28): unknown-doctype
+#document
+| <!DOCTYPE potato>
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato PUBLIC goof>Hello
+#errors
+(1,25): unexpected-char-in-doctype
+(1,29): unknown-doctype
+#document
+| <!DOCTYPE potato>
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato PUBLIC "go'of">Hello
+#errors
+(1,32): unknown-doctype
+#document
+| <!DOCTYPE potato "go'of" "">
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato PUBLIC 'go'of'>Hello
+#errors
+(1,29): unexpected-char-in-doctype
+(1,32): unknown-doctype
+#document
+| <!DOCTYPE potato "go" "">
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato PUBLIC 'go:hh of' >Hello
+#errors
+(1,38): unknown-doctype
+#document
+| <!DOCTYPE potato "go:hh of" "">
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE potato PUBLIC "W3C-//dfdf" SYSTEM ggg>Hello
+#errors
+(1,38): unexpected-char-in-doctype
+(1,48): unknown-doctype
+#document
+| <!DOCTYPE potato "W3C-//dfdf" "">
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">Hello
+#errors
+#document
+| <!DOCTYPE html "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE ...>Hello
+#errors
+(1,14): unknown-doctype
+#document
+| <!DOCTYPE ...>
+| <html>
+| <head>
+| <body>
+| "Hello"
+
+#data
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+#errors
+(2,58): unknown-doctype
+#document
+| <!DOCTYPE html "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+| <html>
+| <head>
+| <body>
+
+#data
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
+#errors
+(2,54): unknown-doctype
+#document
+| <!DOCTYPE html "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
+| <html>
+| <head>
+| <body>
+
+#data
+<!DOCTYPE root-element [SYSTEM OR PUBLIC FPI] "uri" [
+<!-- internal declarations -->
+]>
+#errors
+(1,23): expected-space-or-right-bracket-in-doctype
+(2,30): unknown-doctype
+#document
+| <!DOCTYPE root-element>
+| <html>
+| <head>
+| <body>
+| "]>"
+
+#data
+<!DOCTYPE html PUBLIC
+ "-//WAPFORUM//DTD XHTML Mobile 1.0//EN"
+ "http://www.wapforum.org/DTD/xhtml-mobile10.dtd">
+#errors
+(3,53): unknown-doctype
+#document
+| <!DOCTYPE html "-//WAPFORUM//DTD XHTML Mobile 1.0//EN" "http://www.wapforum.org/DTD/xhtml-mobile10.dtd">
+| <html>
+| <head>
+| <body>
+
+#data
+<!DOCTYPE HTML SYSTEM "http://www.w3.org/DTD/HTML4-strict.dtd"><body><b>Mine!</b></body>
+#errors
+(1,63): unknown-doctype
+#document
+| <!DOCTYPE html "" "http://www.w3.org/DTD/HTML4-strict.dtd">
+| <html>
+| <head>
+| <body>
+| <b>
+| "Mine!"
+
+#data
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN""http://www.w3.org/TR/html4/strict.dtd">
+#errors
+(1,50): unexpected-char-in-doctype
+#document
+| <!DOCTYPE html "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+| <html>
+| <head>
+| <body>
+
+#data
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"'http://www.w3.org/TR/html4/strict.dtd'>
+#errors
+(1,50): unexpected-char-in-doctype
+#document
+| <!DOCTYPE html "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+| <html>
+| <head>
+| <body>
+
+#data
+<!DOCTYPE HTML PUBLIC"-//W3C//DTD HTML 4.01//EN"'http://www.w3.org/TR/html4/strict.dtd'>
+#errors
+(1,21): unexpected-char-in-doctype
+(1,49): unexpected-char-in-doctype
+#document
+| <!DOCTYPE html "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+| <html>
+| <head>
+| <body>
+
+#data
+<!DOCTYPE HTML PUBLIC'-//W3C//DTD HTML 4.01//EN''http://www.w3.org/TR/html4/strict.dtd'>
+#errors
+(1,21): unexpected-char-in-doctype
+(1,49): unexpected-char-in-doctype
+#document
+| <!DOCTYPE html "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+| <html>
+| <head>
+| <body>
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/domjs-unsafe.dat b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/domjs-unsafe.dat
new file mode 100644
index 00000000000..34b4e62716e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/domjs-unsafe.dat
Binary files differ
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/entities01.dat b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/entities01.dat
new file mode 100644
index 00000000000..20d53a0fd5a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/entities01.dat
@@ -0,0 +1,723 @@
+#data
+FOO&gt;BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOO>BAR"
+
+#data
+FOO&gtBAR
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,6): named-entity-without-semicolon
+#document
+| <html>
+| <head>
+| <body>
+| "FOO>BAR"
+
+#data
+FOO&gt BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,6): named-entity-without-semicolon
+#document
+| <html>
+| <head>
+| <body>
+| "FOO> BAR"
+
+#data
+FOO&gt;;;BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOO>;;BAR"
+
+#data
+I'm &notit; I tell you
+#errors
+(1,4): expected-doctype-but-got-chars
+(1,9): named-entity-without-semicolon
+#document
+| <html>
+| <head>
+| <body>
+| "I'm ¬it; I tell you"
+
+#data
+I'm &notin; I tell you
+#errors
+(1,4): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "I'm ∉ I tell you"
+
+#data
+FOO& BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOO& BAR"
+
+#data
+FOO&<BAR>
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,9): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| "FOO&"
+| <bar>
+
+#data
+FOO&&&&gt;BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOO&&&>BAR"
+
+#data
+FOO&#41;BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOO)BAR"
+
+#data
+FOO&#x41;BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOOABAR"
+
+#data
+FOO&#X41;BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOOABAR"
+
+#data
+FOO&#BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,5): expected-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO&#BAR"
+
+#data
+FOO&#ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,5): expected-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO&#ZOO"
+
+#data
+FOO&#xBAR
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,7): expected-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOOºR"
+
+#data
+FOO&#xZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,6): expected-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO&#xZOO"
+
+#data
+FOO&#XZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,6): expected-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO&#XZOO"
+
+#data
+FOO&#41BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,7): numeric-entity-without-semicolon
+#document
+| <html>
+| <head>
+| <body>
+| "FOO)BAR"
+
+#data
+FOO&#x41BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,10): numeric-entity-without-semicolon
+#document
+| <html>
+| <head>
+| <body>
+| "FOO䆺R"
+
+#data
+FOO&#x41ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,8): numeric-entity-without-semicolon
+#document
+| <html>
+| <head>
+| <body>
+| "FOOAZOO"
+
+#data
+FOO&#x0000;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO�ZOO"
+
+#data
+FOO&#x0078;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOOxZOO"
+
+#data
+FOO&#x0079;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOOyZOO"
+
+#data
+FOO&#x0080;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO€ZOO"
+
+#data
+FOO&#x0081;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOOZOO"
+
+#data
+FOO&#x0082;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO‚ZOO"
+
+#data
+FOO&#x0083;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOOƒZOO"
+
+#data
+FOO&#x0084;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO„ZOO"
+
+#data
+FOO&#x0085;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO…ZOO"
+
+#data
+FOO&#x0086;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO†ZOO"
+
+#data
+FOO&#x0087;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO‡ZOO"
+
+#data
+FOO&#x0088;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOOˆZOO"
+
+#data
+FOO&#x0089;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO‰ZOO"
+
+#data
+FOO&#x008A;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOOŠZOO"
+
+#data
+FOO&#x008B;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO‹ZOO"
+
+#data
+FOO&#x008C;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOOŒZOO"
+
+#data
+FOO&#x008D;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOOZOO"
+
+#data
+FOO&#x008E;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOOŽZOO"
+
+#data
+FOO&#x008F;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOOZOO"
+
+#data
+FOO&#x0090;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOOZOO"
+
+#data
+FOO&#x0091;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO‘ZOO"
+
+#data
+FOO&#x0092;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO’ZOO"
+
+#data
+FOO&#x0093;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO“ZOO"
+
+#data
+FOO&#x0094;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO”ZOO"
+
+#data
+FOO&#x0095;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO•ZOO"
+
+#data
+FOO&#x0096;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO–ZOO"
+
+#data
+FOO&#x0097;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO—ZOO"
+
+#data
+FOO&#x0098;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO˜ZOO"
+
+#data
+FOO&#x0099;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO™ZOO"
+
+#data
+FOO&#x009A;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOOšZOO"
+
+#data
+FOO&#x009B;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO›ZOO"
+
+#data
+FOO&#x009C;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOOœZOO"
+
+#data
+FOO&#x009D;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOOZOO"
+
+#data
+FOO&#x009E;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOOžZOO"
+
+#data
+FOO&#x009F;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOOŸZOO"
+
+#data
+FOO&#x00A0;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOO ZOO"
+
+#data
+FOO&#xD7FF;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOO퟿ZOO"
+
+#data
+FOO&#xD800;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO�ZOO"
+
+#data
+FOO&#xD801;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO�ZOO"
+
+#data
+FOO&#xDFFE;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO�ZOO"
+
+#data
+FOO&#xDFFF;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,11): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO�ZOO"
+
+#data
+FOO&#xE000;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOOZOO"
+
+#data
+FOO&#x10FFFE;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,13): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO􏿾ZOO"
+
+#data
+FOO&#x1087D4;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOO􈟔ZOO"
+
+#data
+FOO&#x10FFFF;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,13): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO􏿿ZOO"
+
+#data
+FOO&#x110000;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,13): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO�ZOO"
+
+#data
+FOO&#xFFFFFF;ZOO
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,13): illegal-codepoint-for-numeric-entity
+#document
+| <html>
+| <head>
+| <body>
+| "FOO�ZOO"
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/entities02.dat b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/entities02.dat
new file mode 100644
index 00000000000..f117f068a01
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/entities02.dat
@@ -0,0 +1,283 @@
+#data
+<div bar="ZZ&gt;YY"></div>
+#errors
+(1,20): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZ>YY"
+
+#data
+<div bar="ZZ&"></div>
+#errors
+(1,15): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZ&"
+
+#data
+<div bar='ZZ&'></div>
+#errors
+(1,15): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZ&"
+
+#data
+<div bar=ZZ&></div>
+#errors
+(1,13): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZ&"
+
+#data
+<div bar="ZZ&gt=YY"></div>
+#errors
+(1,15): named-entity-without-semicolon
+(1,20): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZ&gt=YY"
+
+#data
+<div bar="ZZ&gt0YY"></div>
+#errors
+(1,20): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZ&gt0YY"
+
+#data
+<div bar="ZZ&gt9YY"></div>
+#errors
+(1,20): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZ&gt9YY"
+
+#data
+<div bar="ZZ&gtaYY"></div>
+#errors
+(1,20): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZ&gtaYY"
+
+#data
+<div bar="ZZ&gtZYY"></div>
+#errors
+(1,20): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZ&gtZYY"
+
+#data
+<div bar="ZZ&gt YY"></div>
+#errors
+(1,15): named-entity-without-semicolon
+(1,20): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZ> YY"
+
+#data
+<div bar="ZZ&gt"></div>
+#errors
+(1,15): named-entity-without-semicolon
+(1,17): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZ>"
+
+#data
+<div bar='ZZ&gt'></div>
+#errors
+(1,15): named-entity-without-semicolon
+(1,17): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZ>"
+
+#data
+<div bar=ZZ&gt></div>
+#errors
+(1,14): named-entity-without-semicolon
+(1,15): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZ>"
+
+#data
+<div bar="ZZ&pound_id=23"></div>
+#errors
+(1,18): named-entity-without-semicolon
+(1,26): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZ£_id=23"
+
+#data
+<div bar="ZZ&prod_id=23"></div>
+#errors
+(1,25): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZ&prod_id=23"
+
+#data
+<div bar="ZZ&pound;_id=23"></div>
+#errors
+(1,27): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZ£_id=23"
+
+#data
+<div bar="ZZ&prod;_id=23"></div>
+#errors
+(1,26): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZ∏_id=23"
+
+#data
+<div bar="ZZ&pound=23"></div>
+#errors
+(1,18): named-entity-without-semicolon
+(1,23): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZ&pound=23"
+
+#data
+<div bar="ZZ&prod=23"></div>
+#errors
+(1,22): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| bar="ZZ&prod=23"
+
+#data
+<div>ZZ&pound_id=23</div>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,13): named-entity-without-semicolon
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| "ZZ£_id=23"
+
+#data
+<div>ZZ&prod_id=23</div>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| "ZZ&prod_id=23"
+
+#data
+<div>ZZ&pound;_id=23</div>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| "ZZ£_id=23"
+
+#data
+<div>ZZ&prod;_id=23</div>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| "ZZ∏_id=23"
+
+#data
+<div>ZZ&pound=23</div>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,13): named-entity-without-semicolon
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| "ZZ£=23"
+
+#data
+<div>ZZ&prod=23</div>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| "ZZ&prod=23"
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/html5test-com.dat b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/html5test-com.dat
new file mode 100644
index 00000000000..8c6ec40cd74
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/html5test-com.dat
@@ -0,0 +1,291 @@
+#data
+<div<div>
+#errors
+(1,9): expected-doctype-but-got-start-tag
+(1,9): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div<div>
+
+#data
+<div foo<bar=''>
+#errors
+(1,9): invalid-character-in-attribute-name
+(1,16): expected-doctype-but-got-start-tag
+(1,16): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| foo<bar=""
+
+#data
+<div foo=`bar`>
+#errors
+(1,10): equals-in-unquoted-attribute-value
+(1,14): unexpected-character-in-unquoted-attribute-value
+(1,15): expected-doctype-but-got-start-tag
+(1,15): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| foo="`bar`"
+
+#data
+<div \"foo=''>
+#errors
+(1,7): invalid-character-in-attribute-name
+(1,14): expected-doctype-but-got-start-tag
+(1,14): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| \"foo=""
+
+#data
+<a href='\nbar'></a>
+#errors
+(1,16): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| href="\nbar"
+
+#data
+<!DOCTYPE html>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+
+#data
+&lang;&rang;
+#errors
+(1,6): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "⟨⟩"
+
+#data
+&apos;
+#errors
+(1,6): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "'"
+
+#data
+&ImaginaryI;
+#errors
+(1,12): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "ⅈ"
+
+#data
+&Kopf;
+#errors
+(1,6): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "𝕂"
+
+#data
+&notinva;
+#errors
+(1,9): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "∉"
+
+#data
+<?import namespace="foo" implementation="#bar">
+#errors
+(1,1): expected-tag-name-but-got-question-mark
+(1,47): expected-doctype-but-got-eof
+#document
+| <!-- ?import namespace="foo" implementation="#bar" -->
+| <html>
+| <head>
+| <body>
+
+#data
+<!--foo--bar-->
+#errors
+(1,10): unexpected-char-in-comment
+(1,15): expected-doctype-but-got-eof
+#document
+| <!-- foo--bar -->
+| <html>
+| <head>
+| <body>
+
+#data
+<![CDATA[x]]>
+#errors
+(1,2): expected-dashes-or-doctype
+(1,13): expected-doctype-but-got-eof
+#document
+| <!-- [CDATA[x]] -->
+| <html>
+| <head>
+| <body>
+
+#data
+<textarea><!--</textarea>--></textarea>
+#errors
+(1,10): expected-doctype-but-got-start-tag
+(1,39): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <body>
+| <textarea>
+| "<!--"
+| "-->"
+
+#data
+<textarea><!--</textarea>-->
+#errors
+(1,10): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <textarea>
+| "<!--"
+| "-->"
+
+#data
+<style><!--</style>--></style>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,30): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <style>
+| "<!--"
+| <body>
+| "-->"
+
+#data
+<style><!--</style>-->
+#errors
+(1,7): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <style>
+| "<!--"
+| <body>
+| "-->"
+
+#data
+<ul><li>A </li> <li>B</li></ul>
+#errors
+(1,4): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <ul>
+| <li>
+| "A "
+| " "
+| <li>
+| "B"
+
+#data
+<table><form><input type=hidden><input></form><div></div></table>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,13): unexpected-form-in-table
+(1,32): unexpected-hidden-input-in-table
+(1,39): unexpected-start-tag-implies-table-voodoo
+(1,46): unexpected-end-tag-implies-table-voodoo
+(1,46): unexpected-end-tag
+(1,51): unexpected-start-tag-implies-table-voodoo
+(1,57): unexpected-end-tag-implies-table-voodoo
+#document
+| <html>
+| <head>
+| <body>
+| <input>
+| <div>
+| <table>
+| <form>
+| <input>
+| type="hidden"
+
+#data
+<i>A<b>B<p></i>C</b>D
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,15): adoption-agency-1.3
+(1,20): adoption-agency-1.3
+#document
+| <html>
+| <head>
+| <body>
+| <i>
+| "A"
+| <b>
+| "B"
+| <b>
+| <p>
+| <b>
+| <i>
+| "C"
+| "D"
+
+#data
+<div></div>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+
+#data
+<svg></svg>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+
+#data
+<math></math>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/inbody01.dat b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/inbody01.dat
new file mode 100644
index 00000000000..10f6520f6fe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/inbody01.dat
@@ -0,0 +1,54 @@
+#data
+<button>1</foo>
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,15): unexpected-end-tag
+(1,15): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <button>
+| "1"
+
+#data
+<foo>1<p>2</foo>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,16): unexpected-end-tag
+(1,16): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <foo>
+| "1"
+| <p>
+| "2"
+
+#data
+<dd>1</foo>
+#errors
+(1,4): expected-doctype-but-got-start-tag
+(1,11): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <body>
+| <dd>
+| "1"
+
+#data
+<foo>1<dd>2</foo>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,17): unexpected-end-tag
+(1,17): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <foo>
+| "1"
+| <dd>
+| "2"
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/isindex.dat b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/isindex.dat
new file mode 100644
index 00000000000..42ef997f7ff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/isindex.dat
@@ -0,0 +1,47 @@
+#data
+<isindex>
+#errors
+(1,9): expected-doctype-but-got-start-tag
+(1,9): deprecated-tag
+#document
+| <html>
+| <head>
+| <body>
+| <form>
+| <hr>
+| <label>
+| "This is a searchable index. Enter search keywords: "
+| <input>
+| name="isindex"
+| <hr>
+
+#data
+<isindex name="A" action="B" prompt="C" foo="D">
+#errors
+(1,48): expected-doctype-but-got-start-tag
+(1,48): deprecated-tag
+#document
+| <html>
+| <head>
+| <body>
+| <form>
+| action="B"
+| <hr>
+| <label>
+| "C"
+| <input>
+| foo="D"
+| name="isindex"
+| <hr>
+
+#data
+<form><isindex>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,15): deprecated-tag
+(1,15): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <form>
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/main-element.dat b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/main-element.dat
new file mode 100644
index 00000000000..4b103bb0fa3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/main-element.dat
@@ -0,0 +1,46 @@
+#data
+<!doctype html><p>foo<main>bar<p>baz
+#errors
+(1,36): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| "foo"
+| <main>
+| "bar"
+| <p>
+| "baz"
+
+#data
+<!doctype html><main><p>foo</main>bar
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <main>
+| <p>
+| "foo"
+| "bar"
+
+#data
+<!DOCTYPE html>xxx<svg><x><g><a><main><b>
+#errors
+ * (1,42) unexpected HTML-like start tag token in foreign content
+ * (1,42) unexpected end of file
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "xxx"
+| <svg svg>
+| <svg x>
+| <svg g>
+| <svg a>
+| <svg main>
+| <b>
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/pending-spec-changes-plain-text-unsafe.dat b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/pending-spec-changes-plain-text-unsafe.dat
new file mode 100644
index 00000000000..3ee8cec904f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/pending-spec-changes-plain-text-unsafe.dat
Binary files differ
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/pending-spec-changes.dat b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/pending-spec-changes.dat
new file mode 100644
index 00000000000..1647d7f23a9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/pending-spec-changes.dat
@@ -0,0 +1,46 @@
+#data
+<input type="hidden"><frameset>
+#errors
+(1,21): expected-doctype-but-got-start-tag
+(1,31): unexpected-start-tag
+(1,31): eof-in-frameset
+#document
+| <html>
+| <head>
+| <frameset>
+
+#data
+<!DOCTYPE html><table><caption><svg>foo</table>bar
+#errors
+(1,47): unexpected-end-tag
+(1,47): end-table-tag-in-caption
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <caption>
+| <svg svg>
+| "foo"
+| "bar"
+
+#data
+<table><tr><td><svg><desc><td></desc><circle>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,30): unexpected-cell-end-tag
+(1,37): unexpected-end-tag
+(1,45): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <svg svg>
+| <svg desc>
+| <td>
+| <circle>
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/plain-text-unsafe.dat b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/plain-text-unsafe.dat
new file mode 100644
index 00000000000..f40dd57607a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/plain-text-unsafe.dat
Binary files differ
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/ruby.dat b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/ruby.dat
new file mode 100644
index 00000000000..80d0c53313c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/ruby.dat
@@ -0,0 +1,298 @@
+#data
+<html><ruby>a<rb>b<rb></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <ruby>
+| "a"
+| <rb>
+| "b"
+| <rb>
+
+#data
+<html><ruby>a<rb>b<rt></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <ruby>
+| "a"
+| <rb>
+| "b"
+| <rt>
+
+#data
+<html><ruby>a<rb>b<rtc></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <ruby>
+| "a"
+| <rb>
+| "b"
+| <rtc>
+
+#data
+<html><ruby>a<rb>b<rp></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <ruby>
+| "a"
+| <rb>
+| "b"
+| <rp>
+
+#data
+<html><ruby>a<rb>b<span></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <ruby>
+| "a"
+| <rb>
+| "b"
+| <span>
+
+#data
+<html><ruby>a<rt>b<rb></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <ruby>
+| "a"
+| <rt>
+| "b"
+| <rb>
+
+#data
+<html><ruby>a<rt>b<rt></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <ruby>
+| "a"
+| <rt>
+| "b"
+| <rt>
+
+#data
+<html><ruby>a<rt>b<rtc></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <ruby>
+| "a"
+| <rt>
+| "b"
+| <rtc>
+
+#data
+<html><ruby>a<rt>b<rp></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <ruby>
+| "a"
+| <rt>
+| "b"
+| <rp>
+
+#data
+<html><ruby>a<rt>b<span></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <ruby>
+| "a"
+| <rt>
+| "b"
+| <span>
+
+#data
+<html><ruby>a<rtc>b<rb></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <ruby>
+| "a"
+| <rtc>
+| "b"
+| <rb>
+
+#data
+<html><ruby>a<rtc>b<rt>c<rt>d</ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <ruby>
+| "a"
+| <rtc>
+| "b"
+| <rt>
+| "c"
+| <rt>
+| "d"
+
+#data
+<html><ruby>a<rtc>b<rtc></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <ruby>
+| "a"
+| <rtc>
+| "b"
+| <rtc>
+
+#data
+<html><ruby>a<rtc>b<rp></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <ruby>
+| "a"
+| <rtc>
+| "b"
+| <rp>
+
+#data
+<html><ruby>a<rtc>b<span></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <ruby>
+| "a"
+| <rtc>
+| "b"
+| <span>
+
+#data
+<html><ruby>a<rp>b<rb></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <ruby>
+| "a"
+| <rp>
+| "b"
+| <rb>
+
+#data
+<html><ruby>a<rp>b<rt></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <ruby>
+| "a"
+| <rp>
+| "b"
+| <rt>
+
+#data
+<html><ruby>a<rp>b<rtc></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <ruby>
+| "a"
+| <rp>
+| "b"
+| <rtc>
+
+#data
+<html><ruby>a<rp>b<rp></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <ruby>
+| "a"
+| <rp>
+| "b"
+| <rp>
+
+#data
+<html><ruby>a<rp>b<span></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <ruby>
+| "a"
+| <rp>
+| "b"
+| <span>
+
+#data
+<html><ruby><rtc><ruby>a<rb>b<rt></ruby></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <ruby>
+| <rtc>
+| <ruby>
+| "a"
+| <rb>
+| "b"
+| <rt>
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/scriptdata01.dat b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/scriptdata01.dat
new file mode 100644
index 00000000000..ac698d282ff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/scriptdata01.dat
@@ -0,0 +1,365 @@
+#data
+FOO<script>'Hello'</script>BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| "'Hello'"
+| "BAR"
+
+#data
+FOO<script></script>BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| "BAR"
+
+#data
+FOO<script></script >BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| "BAR"
+
+#data
+FOO<script></script/>BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,21): self-closing-flag-on-end-tag
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| "BAR"
+
+#data
+FOO<script></script/ >BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,20): unexpected-character-after-solidus-in-tag
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| "BAR"
+
+#data
+FOO<script type="text/plain"></scriptx>BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,42): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| type="text/plain"
+| "</scriptx>BAR"
+
+#data
+FOO<script></script foo=">" dd>BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,31): attributes-in-end-tag
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| "BAR"
+
+#data
+FOO<script>'<'</script>BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| "'<'"
+| "BAR"
+
+#data
+FOO<script>'<!'</script>BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| "'<!'"
+| "BAR"
+
+#data
+FOO<script>'<!-'</script>BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| "'<!-'"
+| "BAR"
+
+#data
+FOO<script>'<!--'</script>BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| "'<!--'"
+| "BAR"
+
+#data
+FOO<script>'<!---'</script>BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| "'<!---'"
+| "BAR"
+
+#data
+FOO<script>'<!-->'</script>BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| "'<!-->'"
+| "BAR"
+
+#data
+FOO<script>'<!-->'</script>BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| "'<!-->'"
+| "BAR"
+
+#data
+FOO<script>'<!-- potato'</script>BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| "'<!-- potato'"
+| "BAR"
+
+#data
+FOO<script>'<!-- <sCrIpt'</script>BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| "'<!-- <sCrIpt'"
+| "BAR"
+
+#data
+FOO<script type="text/plain">'<!-- <sCrIpt>'</script>BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,56): expected-script-data-but-got-eof
+(1,56): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| type="text/plain"
+| "'<!-- <sCrIpt>'</script>BAR"
+
+#data
+FOO<script type="text/plain">'<!-- <sCrIpt> -'</script>BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,58): expected-script-data-but-got-eof
+(1,58): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| type="text/plain"
+| "'<!-- <sCrIpt> -'</script>BAR"
+
+#data
+FOO<script type="text/plain">'<!-- <sCrIpt> --'</script>BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,59): expected-script-data-but-got-eof
+(1,59): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| type="text/plain"
+| "'<!-- <sCrIpt> --'</script>BAR"
+
+#data
+FOO<script>'<!-- <sCrIpt> -->'</script>BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| "'<!-- <sCrIpt> -->'"
+| "BAR"
+
+#data
+FOO<script type="text/plain">'<!-- <sCrIpt> --!>'</script>BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,61): expected-script-data-but-got-eof
+(1,61): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| type="text/plain"
+| "'<!-- <sCrIpt> --!>'</script>BAR"
+
+#data
+FOO<script type="text/plain">'<!-- <sCrIpt> -- >'</script>BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,61): expected-script-data-but-got-eof
+(1,61): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| type="text/plain"
+| "'<!-- <sCrIpt> -- >'</script>BAR"
+
+#data
+FOO<script type="text/plain">'<!-- <sCrIpt '</script>BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,56): expected-script-data-but-got-eof
+(1,56): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| type="text/plain"
+| "'<!-- <sCrIpt '</script>BAR"
+
+#data
+FOO<script type="text/plain">'<!-- <sCrIpt/'</script>BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+(1,56): expected-script-data-but-got-eof
+(1,56): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| type="text/plain"
+| "'<!-- <sCrIpt/'</script>BAR"
+
+#data
+FOO<script type="text/plain">'<!-- <sCrIpt\'</script>BAR
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| type="text/plain"
+| "'<!-- <sCrIpt\'"
+| "BAR"
+
+#data
+FOO<script type="text/plain">'<!-- <sCrIpt/'</script>BAR</script>QUX
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| type="text/plain"
+| "'<!-- <sCrIpt/'</script>BAR"
+| "QUX"
+
+#data
+FOO<script><!--<script>-></script>--></script>QUX
+#errors
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "FOO"
+| <script>
+| "<!--<script>-></script>-->"
+| "QUX"
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/scripted/adoption01.dat b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/scripted/adoption01.dat
new file mode 100644
index 00000000000..4e08d0e84a0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/scripted/adoption01.dat
@@ -0,0 +1,15 @@
+#data
+<p><b id="A"><script>document.getElementById("A").id = "B"</script></p>TEXT</b>
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| <b>
+| id="B"
+| <script>
+| "document.getElementById("A").id = "B""
+| <b>
+| id="A"
+| "TEXT"
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/scripted/ark.dat b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/scripted/ark.dat
new file mode 100644
index 00000000000..acbac41df16
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/scripted/ark.dat
@@ -0,0 +1,26 @@
+#data
+<p><font size=4><font size=4><font size=4><script>document.getElementsByTagName("font")[2].setAttribute("size", "5");</script><font size=4><p>X
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| <font>
+| size="4"
+| <font>
+| size="4"
+| <font>
+| size="5"
+| <script>
+| "document.getElementsByTagName("font")[2].setAttribute("size", "5");"
+| <font>
+| size="4"
+| <p>
+| <font>
+| size="4"
+| <font>
+| size="4"
+| <font>
+| size="4"
+| "X"
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/scripted/webkit01.dat b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/scripted/webkit01.dat
new file mode 100644
index 00000000000..ef4a41ca00b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/scripted/webkit01.dat
@@ -0,0 +1,28 @@
+#data
+1<script>document.write("2")</script>3
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "1"
+| <script>
+| "document.write("2")"
+| "23"
+
+#data
+1<script>document.write("<script>document.write('2')</scr"+ "ipt><script>document.write('3')</scr" + "ipt>")</script>4
+#errors
+#document
+| <html>
+| <head>
+| <body>
+| "1"
+| <script>
+| "document.write("<script>document.write('2')</scr"+ "ipt><script>document.write('3')</scr" + "ipt>")"
+| <script>
+| "document.write('2')"
+| "2"
+| <script>
+| "document.write('3')"
+| "34"
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tables01.dat b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tables01.dat
new file mode 100644
index 00000000000..f0caaa3c5fc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tables01.dat
@@ -0,0 +1,286 @@
+#data
+<table><th>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,11): unexpected-cell-in-table-body
+(1,11): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <th>
+
+#data
+<table><td>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,11): unexpected-cell-in-table-body
+(1,11): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+
+#data
+<table><col foo='bar'>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,22): eof-in-table
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <colgroup>
+| <col>
+| foo="bar"
+
+#data
+<table><colgroup></html>foo
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,24): unexpected-end-tag
+(1,27): foster-parenting-character-in-table
+(1,27): foster-parenting-character-in-table
+(1,27): foster-parenting-character-in-table
+(1,27): eof-in-table
+#document
+| <html>
+| <head>
+| <body>
+| "foo"
+| <table>
+| <colgroup>
+
+#data
+<table></table><p>foo
+#errors
+(1,7): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <p>
+| "foo"
+
+#data
+<table></body></caption></col></colgroup></html></tbody></td></tfoot></th></thead></tr><td>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,14): unexpected-end-tag
+(1,24): unexpected-end-tag
+(1,30): unexpected-end-tag
+(1,41): unexpected-end-tag
+(1,48): unexpected-end-tag
+(1,56): unexpected-end-tag
+(1,61): unexpected-end-tag
+(1,69): unexpected-end-tag
+(1,74): unexpected-end-tag
+(1,82): unexpected-end-tag
+(1,87): unexpected-end-tag
+(1,91): unexpected-cell-in-table-body
+(1,91): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+
+#data
+<table><select><option>3</select></table>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,15): unexpected-start-tag-implies-table-voodoo
+#document
+| <html>
+| <head>
+| <body>
+| <select>
+| <option>
+| "3"
+| <table>
+
+#data
+<table><select><table></table></select></table>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,15): unexpected-start-tag-implies-table-voodoo
+(1,22): unexpected-table-element-start-tag-in-select-in-table
+(1,22): unexpected-start-tag-implies-end-tag
+(1,39): unexpected-end-tag
+(1,47): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <body>
+| <select>
+| <table>
+| <table>
+
+#data
+<table><select></table>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,15): unexpected-start-tag-implies-table-voodoo
+(1,23): unexpected-table-element-end-tag-in-select-in-table
+#document
+| <html>
+| <head>
+| <body>
+| <select>
+| <table>
+
+#data
+<table><select><option>A<tr><td>B</td></tr></table>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,15): unexpected-start-tag-implies-table-voodoo
+(1,28): unexpected-table-element-start-tag-in-select-in-table
+#document
+| <html>
+| <head>
+| <body>
+| <select>
+| <option>
+| "A"
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| "B"
+
+#data
+<table><td></body></caption></col></colgroup></html>foo
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,11): unexpected-cell-in-table-body
+(1,18): unexpected-end-tag
+(1,28): unexpected-end-tag
+(1,34): unexpected-end-tag
+(1,45): unexpected-end-tag
+(1,52): unexpected-end-tag
+(1,55): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| "foo"
+
+#data
+<table><td>A</table>B
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,11): unexpected-cell-in-table-body
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| "A"
+| "B"
+
+#data
+<table><tr><caption>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,20): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <caption>
+
+#data
+<table><tr></body></caption></col></colgroup></html></td></th><td>foo
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,18): unexpected-end-tag-in-table-row
+(1,28): unexpected-end-tag-in-table-row
+(1,34): unexpected-end-tag-in-table-row
+(1,45): unexpected-end-tag-in-table-row
+(1,52): unexpected-end-tag-in-table-row
+(1,57): unexpected-end-tag-in-table-row
+(1,62): unexpected-end-tag-in-table-row
+(1,69): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| "foo"
+
+#data
+<table><td><tr>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,11): unexpected-cell-in-table-body
+(1,15): eof-in-table
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <tr>
+
+#data
+<table><td><button><td>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,11): unexpected-cell-in-table-body
+(1,23): unexpected-cell-end-tag
+(1,23): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <button>
+| <td>
+
+#data
+<table><tr><td><svg><desc><td>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,30): unexpected-cell-end-tag
+(1,30): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <svg svg>
+| <svg desc>
+| <td>
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/template.dat b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/template.dat
new file mode 100644
index 00000000000..f370cc18607
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/template.dat
@@ -0,0 +1,1591 @@
+#data
+<body><template>Hello</template>
+#errors
+no doctype
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| "Hello"
+
+#data
+<template>Hello</template>
+#errors
+no doctype
+#document
+| <html>
+| <head>
+| <template>
+| content
+| "Hello"
+| <body>
+
+#data
+<template></template><div></div>
+#errors
+no doctype
+#document
+| <html>
+| <head>
+| <template>
+| content
+| <body>
+| <div>
+
+#data
+<html><template>Hello</template>
+#errors
+no doctype
+#document
+| <html>
+| <head>
+| <template>
+| content
+| "Hello"
+| <body>
+
+#data
+<head><template><div></div></template></head>
+#errors
+no doctype
+#document
+| <html>
+| <head>
+| <template>
+| content
+| <div>
+| <body>
+
+#data
+<div><template><div><span></template><b>
+#errors
+ * (1,6) missing DOCTYPE
+ * (1,38) mismatched template end tag
+ * (1,41) unexpected end of file
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| <template>
+| content
+| <div>
+| <span>
+| <b>
+
+#data
+<div><template></div>Hello
+#errors
+ * (1,6) missing DOCTYPE
+ * (1,22) unexpected token in template
+ * (1,27) unexpected end of file in template
+ * (1,27) unexpected end of file
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| <template>
+| content
+| "Hello"
+
+#data
+<div></template></div>
+#errors
+ * (1,6) missing DOCTYPE
+ * (1,17) unexpected template end tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+
+#data
+<table><template></template></table>
+#errors
+no doctype
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <template>
+| content
+
+#data
+<table><template></template></div>
+#errors
+ * (1,8) missing DOCTYPE
+ * (1,35) unexpected token in table - foster parenting
+ * (1,35) unexpected end tag
+ * (1,35) unexpected end of file
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <template>
+| content
+
+#data
+<table><div><template></template></div>
+#errors
+ * (1,8) missing DOCTYPE
+ * (1,13) unexpected token in table - foster parenting
+ * (1,40) unexpected token in table - foster parenting
+ * (1,40) unexpected end of file
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| <template>
+| content
+| <table>
+
+#data
+<table><template></template><div></div>
+#errors
+no doctype
+bad div in table
+bad /div in table
+eof in table
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| <table>
+| <template>
+| content
+
+#data
+<table> <template></template></table>
+#errors
+no doctype
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| " "
+| <template>
+| content
+
+#data
+<table><tbody><template></template></tbody>
+#errors
+no doctype
+eof in table
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <template>
+| content
+
+#data
+<table><tbody><template></tbody></template>
+#errors
+no doctype
+bad /tbody
+eof in table
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <template>
+| content
+
+#data
+<table><tbody><template></template></tbody></table>
+#errors
+no doctype
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <template>
+| content
+
+#data
+<table><thead><template></template></thead>
+#errors
+no doctype
+eof in table
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <thead>
+| <template>
+| content
+
+#data
+<table><tfoot><template></template></tfoot>
+#errors
+no doctype
+eof in table
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tfoot>
+| <template>
+| content
+
+#data
+<select><template></template></select>
+#errors
+no doctype
+#document
+| <html>
+| <head>
+| <body>
+| <select>
+| <template>
+| content
+
+#data
+<select><template><option></option></template></select>
+#errors
+no doctype
+#document
+| <html>
+| <head>
+| <body>
+| <select>
+| <template>
+| content
+| <option>
+
+#data
+<template><option></option></select><option></option></template>
+#errors
+no doctype
+bad /select
+#document
+| <html>
+| <head>
+| <template>
+| content
+| <option>
+| <option>
+| <body>
+
+#data
+<select><template></template><option></select>
+#errors
+no doctype
+#document
+| <html>
+| <head>
+| <body>
+| <select>
+| <template>
+| content
+| <option>
+
+#data
+<select><option><template></template></select>
+#errors
+no doctype
+#document
+| <html>
+| <head>
+| <body>
+| <select>
+| <option>
+| <template>
+| content
+
+#data
+<select><template>
+#errors
+no doctype
+eof in template
+eof in select
+#document
+| <html>
+| <head>
+| <body>
+| <select>
+| <template>
+| content
+
+#data
+<select><option></option><template>
+#errors
+no doctype
+eof in template
+eof in select
+#document
+| <html>
+| <head>
+| <body>
+| <select>
+| <option>
+| <template>
+| content
+
+#data
+<select><option></option><template><option>
+#errors
+no doctype
+eof in template
+eof in select
+#document
+| <html>
+| <head>
+| <body>
+| <select>
+| <option>
+| <template>
+| content
+| <option>
+
+#data
+<table><thead><template><td></template></table>
+#errors
+ * (1,8) missing DOCTYPE
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <thead>
+| <template>
+| content
+| <td>
+
+#data
+<table><template><thead></template></table>
+#errors
+no doctype
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <template>
+| content
+| <thead>
+
+#data
+<body><table><template><td></tr><div></template></table>
+#errors
+no doctype
+bad </tr>
+missing </div>
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <template>
+| content
+| <td>
+| <div>
+
+#data
+<table><template><thead></template></thead></table>
+#errors
+no doctype
+bad /thead after /template
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <template>
+| content
+| <thead>
+
+#data
+<table><thead><template><tr></template></table>
+#errors
+no doctype
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <thead>
+| <template>
+| content
+| <tr>
+
+#data
+<table><template><tr></template></table>
+#errors
+no doctype
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <template>
+| content
+| <tr>
+
+#data
+<table><tr><template><td>
+#errors
+no doctype
+eof in template
+eof in table
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <template>
+| content
+| <td>
+
+#data
+<table><template><tr><template><td></template></tr></template></table>
+#errors
+no doctype
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <template>
+| content
+| <tr>
+| <template>
+| content
+| <td>
+
+#data
+<table><template><tr><template><td></td></template></tr></template></table>
+#errors
+no doctype
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <template>
+| content
+| <tr>
+| <template>
+| content
+| <td>
+
+#data
+<table><template><td></template>
+#errors
+no doctype
+eof in table
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <template>
+| content
+| <td>
+
+#data
+<body><template><td></td></template>
+#errors
+no doctype
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <td>
+
+#data
+<body><template><template><tr></tr></template><td></td></template>
+#errors
+no doctype
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <template>
+| content
+| <tr>
+| <td>
+
+#data
+<table><colgroup><template><col>
+#errors
+no doctype
+eof in template
+eof in table
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <colgroup>
+| <template>
+| content
+| <col>
+
+#data
+<frameset><template><frame></frame></template></frameset>
+#errors
+ * (1,11) missing DOCTYPE
+ * (1,21) unexpected start tag token
+ * (1,36) unexpected end tag token
+ * (1,47) unexpected end tag token
+#document
+| <html>
+| <head>
+| <frameset>
+| <frame>
+
+#data
+<template><frame></frame></frameset><frame></frame></template>
+#errors
+ * (1,11) missing DOCTYPE
+ * (1,18) unexpected start tag
+ * (1,26) unexpected end tag
+ * (1,37) unexpected end tag
+ * (1,44) unexpected start tag
+ * (1,52) unexpected end tag
+#document
+| <html>
+| <head>
+| <template>
+| content
+| <body>
+
+#data
+<template><div><frameset><span></span></div><span></span></template>
+#errors
+no doctype
+bad frameset
+#document
+| <html>
+| <head>
+| <template>
+| content
+| <div>
+| <span>
+| <span>
+| <body>
+
+#data
+<body><template><div><frameset><span></span></div><span></span></template></body>
+#errors
+no doctype
+bad frameset
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <div>
+| <span>
+| <span>
+
+#data
+<body><template><script>var i = 1;</script><td></td></template>
+#errors
+no doctype
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <script>
+| "var i = 1;"
+| <td>
+
+#data
+<body><template><tr><div></div></tr></template>
+#errors
+no doctype
+foster-parented div
+foster-parented /div
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <tr>
+| <div>
+
+#data
+<body><template><tr></tr><td></td></template>
+#errors
+no doctype
+unexpected <td>
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <tr>
+| <tr>
+| <td>
+
+#data
+<body><template><td></td></tr><td></td></template>
+#errors
+no doctype
+bad </tr>
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <td>
+| <td>
+
+#data
+<body><template><td></td><tbody><td></td></template>
+#errors
+no doctype
+bad <tbody>
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <td>
+| <td>
+
+#data
+<body><template><td></td><caption></caption><td></td></template>
+#errors
+ * (1,7) missing DOCTYPE
+ * (1,35) unexpected start tag in table row
+ * (1,45) unexpected end tag in table row
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <td>
+| <td>
+
+#data
+<body><template><td></td><colgroup></caption><td></td></template>
+#errors
+ * (1,7) missing DOCTYPE
+ * (1,36) unexpected start tag in table row
+ * (1,46) unexpected end tag in table row
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <td>
+| <td>
+
+#data
+<body><template><td></td></table><td></td></template>
+#errors
+no doctype
+bad </table>
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <td>
+| <td>
+
+#data
+<body><template><tr></tr><tbody><tr></tr></template>
+#errors
+no doctype
+bad <tbody>
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <tr>
+| <tr>
+
+#data
+<body><template><tr></tr><caption><tr></tr></template>
+#errors
+no doctype
+bad <caption>
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <tr>
+| <tr>
+
+#data
+<body><template><tr></tr></table><tr></tr></template>
+#errors
+no doctype
+bad </table>
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <tr>
+| <tr>
+
+#data
+<body><template><thead></thead><caption></caption><tbody></tbody></template>
+#errors
+no doctype
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <thead>
+| <caption>
+| <tbody>
+
+#data
+<body><template><thead></thead></table><tbody></tbody></template></body>
+#errors
+no doctype
+bad </table>
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <thead>
+| <tbody>
+
+#data
+<body><template><div><tr></tr></div></template>
+#errors
+no doctype
+bad tr
+bad /tr
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <div>
+
+#data
+<body><template><em>Hello</em></template>
+#errors
+no doctype
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <em>
+| "Hello"
+
+#data
+<body><template><!--comment--></template>
+#errors
+no doctype
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <!-- comment -->
+
+#data
+<body><template><style></style><td></td></template>
+#errors
+no doctype
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <style>
+| <td>
+
+#data
+<body><template><meta><td></td></template>
+#errors
+no doctype
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <meta>
+| <td>
+
+#data
+<body><template><link><td></td></template>
+#errors
+no doctype
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <link>
+| <td>
+
+#data
+<body><template><template><tr></tr></template><td></td></template>
+#errors
+no doctype
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <template>
+| content
+| <tr>
+| <td>
+
+#data
+<body><table><colgroup><template><col></col></template></colgroup></table></body>
+#errors
+no doctype
+bad /col
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <colgroup>
+| <template>
+| content
+| <col>
+
+#data
+<body a=b><template><div></div><body c=d><div></div></body></template></body>
+#errors
+no doctype
+bad <body>
+bad </body>
+#document
+| <html>
+| <head>
+| <body>
+| a="b"
+| <template>
+| content
+| <div>
+| <div>
+
+#data
+<html a=b><template><div><html b=c><span></template>
+#errors
+no doctype
+bad <html>
+missing end tags in template
+#document
+| <html>
+| a="b"
+| <head>
+| <template>
+| content
+| <div>
+| <span>
+| <body>
+
+#data
+<html a=b><template><col></col><html b=c><col></col></template>
+#errors
+no doctype
+bad /col
+bad html
+bad /col
+#document
+| <html>
+| a="b"
+| <head>
+| <template>
+| content
+| <col>
+| <col>
+| <body>
+
+#data
+<html a=b><template><frame></frame><html b=c><frame></frame></template>
+#errors
+no doctype
+bad frame
+bad /frame
+bad html
+bad frame
+bad /frame
+#document
+| <html>
+| a="b"
+| <head>
+| <template>
+| content
+| <body>
+
+#data
+<body><template><tr></tr><template></template><td></td></template>
+#errors
+no doctype
+unexpected <td>
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <tr>
+| <template>
+| content
+| <tr>
+| <td>
+
+#data
+<body><template><thead></thead><template><tr></tr></template><tr></tr><tfoot></tfoot></template>
+#errors
+no doctype
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <thead>
+| <template>
+| content
+| <tr>
+| <tbody>
+| <tr>
+| <tfoot>
+
+#data
+<body><template><template><b><template></template></template>text</template>
+#errors
+no doctype
+missing </b>
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <template>
+| content
+| <b>
+| <template>
+| content
+| "text"
+
+#data
+<body><template><col><colgroup>
+#errors
+no doctype
+bad colgroup
+eof in template
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <col>
+
+#data
+<body><template><col></colgroup>
+#errors
+no doctype
+bogus /colgroup
+eof in template
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <col>
+
+#data
+<body><template><col><colgroup></template></body>
+#errors
+no doctype
+bad colgroup
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <col>
+
+#data
+<body><template><col><div>
+#errors
+ * (1,7) missing DOCTYPE
+ * (1,27) unexpected token
+ * (1,27) unexpected end of file in template
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <col>
+
+#data
+<body><template><col></div>
+#errors
+no doctype
+bad /div
+eof in template
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <col>
+
+#data
+<body><template><col>Hello
+#errors
+no doctype
+unexpected text
+eof in template
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <col>
+
+#data
+<body><template><i><menu>Foo</i>
+#errors
+no doctype
+mising /menu
+eof in template
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <i>
+| <menu>
+| <i>
+| "Foo"
+
+#data
+<body><template></div><div>Foo</div><template></template><tr></tr>
+#errors
+no doctype
+bogus /div
+bogus tr
+bogus /tr
+eof in template
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+| <div>
+| "Foo"
+| <template>
+| content
+
+#data
+<body><div><template></div><tr><td>Foo</td></tr></template>
+#errors
+ * (1,7) missing DOCTYPE
+ * (1,28) unexpected token in template
+ * (1,60) unexpected end of file
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| <template>
+| content
+| <tr>
+| <td>
+| "Foo"
+
+#data
+<template></figcaption><sub><table></table>
+#errors
+no doctype
+bad /figcaption
+eof in template
+#document
+| <html>
+| <head>
+| <template>
+| content
+| <sub>
+| <table>
+| <body>
+
+#data
+<template><template>
+#errors
+no doctype
+eof in template
+eof in template
+#document
+| <html>
+| <head>
+| <template>
+| content
+| <template>
+| content
+| <body>
+
+#data
+<template><div>
+#errors
+no doctype
+eof in template
+#document
+| <html>
+| <head>
+| <template>
+| content
+| <div>
+| <body>
+
+#data
+<template><template><div>
+#errors
+no doctype
+eof in template
+eof in template
+#document
+| <html>
+| <head>
+| <template>
+| content
+| <template>
+| content
+| <div>
+| <body>
+
+#data
+<template><template><table>
+#errors
+no doctype
+eof in template
+eof in template
+#document
+| <html>
+| <head>
+| <template>
+| content
+| <template>
+| content
+| <table>
+| <body>
+
+#data
+<template><template><tbody>
+#errors
+no doctype
+eof in template
+eof in template
+#document
+| <html>
+| <head>
+| <template>
+| content
+| <template>
+| content
+| <tbody>
+| <body>
+
+#data
+<template><template><tr>
+#errors
+no doctype
+eof in template
+eof in template
+#document
+| <html>
+| <head>
+| <template>
+| content
+| <template>
+| content
+| <tr>
+| <body>
+
+#data
+<template><template><td>
+#errors
+no doctype
+eof in template
+eof in template
+#document
+| <html>
+| <head>
+| <template>
+| content
+| <template>
+| content
+| <td>
+| <body>
+
+#data
+<template><template><caption>
+#errors
+no doctype
+eof in template
+eof in template
+#document
+| <html>
+| <head>
+| <template>
+| content
+| <template>
+| content
+| <caption>
+| <body>
+
+#data
+<template><template><colgroup>
+#errors
+no doctype
+eof in template
+eof in template
+#document
+| <html>
+| <head>
+| <template>
+| content
+| <template>
+| content
+| <colgroup>
+| <body>
+
+#data
+<template><template><col>
+#errors
+no doctype
+eof in template
+eof in template
+#document
+| <html>
+| <head>
+| <template>
+| content
+| <template>
+| content
+| <col>
+| <body>
+
+#data
+<template><template><tbody><select>
+#errors
+ * (1,11) missing DOCTYPE
+ * (1,36) unexpected token in table - foster parenting
+ * (1,36) unexpected end of file in template
+ * (1,36) unexpected end of file in template
+#document
+| <html>
+| <head>
+| <template>
+| content
+| <template>
+| content
+| <tbody>
+| <select>
+| <body>
+
+#data
+<template><template><table>Foo
+#errors
+no doctype
+foster-parenting text F
+foster-parenting text o
+foster-parenting text o
+eof
+eof
+#document
+| <html>
+| <head>
+| <template>
+| content
+| <template>
+| content
+| "Foo"
+| <table>
+| <body>
+
+#data
+<template><template><frame>
+#errors
+no doctype
+bad tag
+eof
+eof
+#document
+| <html>
+| <head>
+| <template>
+| content
+| <template>
+| content
+| <body>
+
+#data
+<template><template><script>var i
+#errors
+no doctype
+eof in script
+eof in template
+eof in template
+#document
+| <html>
+| <head>
+| <template>
+| content
+| <template>
+| content
+| <script>
+| "var i"
+| <body>
+
+#data
+<template><template><style>var i
+#errors
+no doctype
+eof in style
+eof in template
+eof in template
+#document
+| <html>
+| <head>
+| <template>
+| content
+| <template>
+| content
+| <style>
+| "var i"
+| <body>
+
+#data
+<template><table></template><body><span>Foo
+#errors
+no doctype
+missing /table
+bad eof
+#document
+| <html>
+| <head>
+| <template>
+| content
+| <table>
+| <body>
+| <span>
+| "Foo"
+
+#data
+<template><td></template><body><span>Foo
+#errors
+no doctype
+bad eof
+#document
+| <html>
+| <head>
+| <template>
+| content
+| <td>
+| <body>
+| <span>
+| "Foo"
+
+#data
+<template><object></template><body><span>Foo
+#errors
+no doctype
+missing /object
+bad eof
+#document
+| <html>
+| <head>
+| <template>
+| content
+| <object>
+| <body>
+| <span>
+| "Foo"
+
+#data
+<template><svg><template>
+#errors
+no doctype
+eof in template
+#document
+| <html>
+| <head>
+| <template>
+| content
+| <svg svg>
+| <svg template>
+| <body>
+
+#data
+<template><svg><foo><template><foreignObject><div></template><div>
+#errors
+no doctype
+ugly template closure
+bad eof
+#document
+| <html>
+| <head>
+| <template>
+| content
+| <svg svg>
+| <svg foo>
+| <svg template>
+| <svg foreignObject>
+| <div>
+| <body>
+| <div>
+
+#data
+<dummy><template><span></dummy>
+#errors
+no doctype
+bad end tag </dummy>
+eof in template
+eof in dummy
+#document
+| <html>
+| <head>
+| <body>
+| <dummy>
+| <template>
+| content
+| <span>
+
+#data
+<body><table><tr><td><select><template>Foo</template><caption>A</table>
+#errors
+no doctype
+(1,62): unexpected-caption-in-select-in-table
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <select>
+| <template>
+| content
+| "Foo"
+| <caption>
+| "A"
+
+#data
+<body></body><template>
+#errors
+no doctype
+(1,23): template-after-body
+(1,24): eof-in-template
+#document
+| <html>
+| <head>
+| <body>
+| <template>
+| content
+
+#data
+<head></head><template>
+#errors
+no doctype
+(1,23): template-after-head
+(1,24): eof-in-template
+#document
+| <html>
+| <head>
+| <template>
+| content
+| <body>
+
+#data
+<head></head><template>Foo</template>
+#errors
+no doctype
+(1,23): template-after-head
+#document
+| <html>
+| <head>
+| <template>
+| content
+| "Foo"
+| <body>
+
+#data
+<!DOCTYPE HTML><dummy><table><template><table><template><table><script>
+#errors
+eof script
+eof template
+eof template
+eof table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <dummy>
+| <table>
+| <template>
+| content
+| <table>
+| <template>
+| content
+| <table>
+| <script>
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests1.dat b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests1.dat
new file mode 100644
index 00000000000..d6726e305ce
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests1.dat
@@ -0,0 +1,1959 @@
+#data
+Test
+#errors
+(1,0): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "Test"
+
+#data
+<p>One<p>Two
+#errors
+(1,3): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| "One"
+| <p>
+| "Two"
+
+#data
+Line1<br>Line2<br>Line3<br>Line4
+#errors
+(1,0): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "Line1"
+| <br>
+| "Line2"
+| <br>
+| "Line3"
+| <br>
+| "Line4"
+
+#data
+<html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+<head>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+<body>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+<html><head>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+<html><head></head>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+<html><head></head><body>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+<html><head></head><body></body>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+<html><head><body></body></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+<html><head></body></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+<html><head><body></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+<html><body></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+<body></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+<head></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+</head>
+#errors
+(1,7): expected-doctype-but-got-end-tag
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+</body>
+#errors
+(1,7): expected-doctype-but-got-end-tag element.
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+</html>
+#errors
+(1,7): expected-doctype-but-got-end-tag element.
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+<b><table><td><i></table>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,14): unexpected-cell-in-table-body
+(1,25): unexpected-cell-end-tag
+(1,25): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <i>
+
+#data
+<b><table><td></b><i></table>X
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,14): unexpected-cell-in-table-body
+(1,18): unexpected-end-tag
+(1,29): unexpected-cell-end-tag
+(1,30): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <i>
+| "X"
+
+#data
+<h1>Hello<h2>World
+#errors
+(1,4): expected-doctype-but-got-start-tag
+(1,13): unexpected-start-tag
+(1,18): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <h1>
+| "Hello"
+| <h2>
+| "World"
+
+#data
+<a><p>X<a>Y</a>Z</p></a>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,10): unexpected-start-tag-implies-end-tag
+(1,10): adoption-agency-1.3
+(1,24): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| <p>
+| <a>
+| "X"
+| <a>
+| "Y"
+| "Z"
+
+#data
+<b><button>foo</b>bar
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,18): adoption-agency-1.3
+(1,21): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| <button>
+| <b>
+| "foo"
+| "bar"
+
+#data
+<!DOCTYPE html><span><button>foo</span>bar
+#errors
+(1,39): unexpected-end-tag
+(1,42): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <span>
+| <button>
+| "foobar"
+
+#data
+<p><b><div><marquee></p></b></div>X
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,11): unexpected-end-tag
+(1,24): unexpected-end-tag
+(1,28): unexpected-end-tag
+(1,34): end-tag-too-early
+(1,35): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| <b>
+| <div>
+| <b>
+| <marquee>
+| <p>
+| "X"
+
+#data
+<script><div></script></div><title><p></title><p><p>
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,28): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <script>
+| "<div>"
+| <title>
+| "<p>"
+| <body>
+| <p>
+| <p>
+
+#data
+<!--><div>--<!-->
+#errors
+(1,5): incorrect-comment
+(1,10): expected-doctype-but-got-start-tag
+(1,17): incorrect-comment
+(1,17): expected-closing-tag-but-got-eof
+#document
+| <!-- -->
+| <html>
+| <head>
+| <body>
+| <div>
+| "--"
+| <!-- -->
+
+#data
+<p><hr></p>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,11): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| <hr>
+| <p>
+
+#data
+<select><b><option><select><option></b></select>X
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,11): unexpected-start-tag-in-select
+(1,27): unexpected-select-in-select
+(1,39): unexpected-end-tag
+(1,48): unexpected-end-tag
+(1,49): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <select>
+| <option>
+| <option>
+| "X"
+
+#data
+<a><table><td><a><table></table><a></tr><a></table><b>X</b>C<a>Y
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,14): unexpected-cell-in-table-body
+(1,35): unexpected-start-tag-implies-end-tag
+(1,40): unexpected-cell-end-tag
+(1,43): unexpected-start-tag-implies-table-voodoo
+(1,43): unexpected-start-tag-implies-end-tag
+(1,43): unexpected-end-tag
+(1,63): unexpected-start-tag-implies-end-tag
+(1,64): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| <a>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <a>
+| <table>
+| <a>
+| <a>
+| <b>
+| "X"
+| "C"
+| <a>
+| "Y"
+
+#data
+<a X>0<b>1<a Y>2
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,15): unexpected-start-tag-implies-end-tag
+(1,15): adoption-agency-1.3
+(1,16): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| x=""
+| "0"
+| <b>
+| "1"
+| <b>
+| <a>
+| y=""
+| "2"
+
+#data
+<!-----><font><div>hello<table>excite!<b>me!<th><i>please!</tr><!--X-->
+#errors
+(1,7): unexpected-dash-after-double-dash-in-comment
+(1,14): expected-doctype-but-got-start-tag
+(1,41): unexpected-start-tag-implies-table-voodoo
+(1,48): foster-parenting-character-in-table
+(1,48): foster-parenting-character-in-table
+(1,48): foster-parenting-character-in-table
+(1,48): foster-parenting-character-in-table
+(1,48): foster-parenting-character-in-table
+(1,48): foster-parenting-character-in-table
+(1,48): foster-parenting-character-in-table
+(1,48): foster-parenting-character-in-table
+(1,48): foster-parenting-character-in-table
+(1,48): foster-parenting-character-in-table
+(1,48): unexpected-cell-in-table-body
+(1,63): unexpected-cell-end-tag
+(1,71): eof-in-table
+#document
+| <!-- - -->
+| <html>
+| <head>
+| <body>
+| <font>
+| <div>
+| "helloexcite!"
+| <b>
+| "me!"
+| <table>
+| <tbody>
+| <tr>
+| <th>
+| <i>
+| "please!"
+| <!-- X -->
+
+#data
+<!DOCTYPE html><li>hello<li>world<ul>how<li>do</ul>you</body><!--do-->
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <li>
+| "hello"
+| <li>
+| "world"
+| <ul>
+| "how"
+| <li>
+| "do"
+| "you"
+| <!-- do -->
+
+#data
+<!DOCTYPE html>A<option>B<optgroup>C<select>D</option>E
+#errors
+(1,54): unexpected-end-tag-in-select
+(1,55): eof-in-select
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "A"
+| <option>
+| "B"
+| <optgroup>
+| "C"
+| <select>
+| "DE"
+
+#data
+<
+#errors
+(1,1): expected-tag-name
+(1,1): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "<"
+
+#data
+<#
+#errors
+(1,1): expected-tag-name
+(1,1): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "<#"
+
+#data
+</
+#errors
+(1,2): expected-closing-tag-but-got-eof
+(1,2): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "</"
+
+#data
+</#
+#errors
+(1,2): expected-closing-tag-but-got-char
+(1,3): expected-doctype-but-got-eof
+#document
+| <!-- # -->
+| <html>
+| <head>
+| <body>
+
+#data
+<?
+#errors
+(1,1): expected-tag-name-but-got-question-mark
+(1,2): expected-doctype-but-got-eof
+#document
+| <!-- ? -->
+| <html>
+| <head>
+| <body>
+
+#data
+<?#
+#errors
+(1,1): expected-tag-name-but-got-question-mark
+(1,3): expected-doctype-but-got-eof
+#document
+| <!-- ?# -->
+| <html>
+| <head>
+| <body>
+
+#data
+<!
+#errors
+(1,2): expected-dashes-or-doctype
+(1,2): expected-doctype-but-got-eof
+#document
+| <!-- -->
+| <html>
+| <head>
+| <body>
+
+#data
+<!#
+#errors
+(1,2): expected-dashes-or-doctype
+(1,3): expected-doctype-but-got-eof
+#document
+| <!-- # -->
+| <html>
+| <head>
+| <body>
+
+#data
+<?COMMENT?>
+#errors
+(1,1): expected-tag-name-but-got-question-mark
+(1,11): expected-doctype-but-got-eof
+#document
+| <!-- ?COMMENT? -->
+| <html>
+| <head>
+| <body>
+
+#data
+<!COMMENT>
+#errors
+(1,2): expected-dashes-or-doctype
+(1,10): expected-doctype-but-got-eof
+#document
+| <!-- COMMENT -->
+| <html>
+| <head>
+| <body>
+
+#data
+</ COMMENT >
+#errors
+(1,2): expected-closing-tag-but-got-char
+(1,12): expected-doctype-but-got-eof
+#document
+| <!-- COMMENT -->
+| <html>
+| <head>
+| <body>
+
+#data
+<?COM--MENT?>
+#errors
+(1,1): expected-tag-name-but-got-question-mark
+(1,13): expected-doctype-but-got-eof
+#document
+| <!-- ?COM--MENT? -->
+| <html>
+| <head>
+| <body>
+
+#data
+<!COM--MENT>
+#errors
+(1,2): expected-dashes-or-doctype
+(1,12): expected-doctype-but-got-eof
+#document
+| <!-- COM--MENT -->
+| <html>
+| <head>
+| <body>
+
+#data
+</ COM--MENT >
+#errors
+(1,2): expected-closing-tag-but-got-char
+(1,14): expected-doctype-but-got-eof
+#document
+| <!-- COM--MENT -->
+| <html>
+| <head>
+| <body>
+
+#data
+<!DOCTYPE html><style> EOF
+#errors
+(1,26): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <style>
+| " EOF"
+| <body>
+
+#data
+<!DOCTYPE html><script> <!-- </script> --> </script> EOF
+#errors
+(1,52): unexpected-end-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| " <!-- "
+| " "
+| <body>
+| "--> EOF"
+
+#data
+<b><p></b>TEST
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,10): adoption-agency-1.3
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| <p>
+| <b>
+| "TEST"
+
+#data
+<p id=a><b><p id=b></b>TEST
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,19): unexpected-end-tag
+(1,23): adoption-agency-1.2
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| id="a"
+| <b>
+| <p>
+| id="b"
+| "TEST"
+
+#data
+<b id=a><p><b id=b></p></b>TEST
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,23): unexpected-end-tag
+(1,27): adoption-agency-1.2
+(1,31): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| id="a"
+| <p>
+| <b>
+| id="b"
+| "TEST"
+
+#data
+<!DOCTYPE html><title>U-test</title><body><div><p>Test<u></p></div></body>
+#errors
+(1,61): unexpected-end-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <title>
+| "U-test"
+| <body>
+| <div>
+| <p>
+| "Test"
+| <u>
+
+#data
+<!DOCTYPE html><font><table></font></table></font>
+#errors
+(1,35): unexpected-end-tag-implies-table-voodoo
+(1,35): unexpected-end-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <font>
+| <table>
+
+#data
+<font><p>hello<b>cruel</font>world
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,29): adoption-agency-1.3
+(1,29): adoption-agency-1.3
+(1,34): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <font>
+| <p>
+| <font>
+| "hello"
+| <b>
+| "cruel"
+| <b>
+| "world"
+
+#data
+<b>Test</i>Test
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,11): unexpected-end-tag
+(1,15): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| "TestTest"
+
+#data
+<b>A<cite>B<div>C
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,17): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| "A"
+| <cite>
+| "B"
+| <div>
+| "C"
+
+#data
+<b>A<cite>B<div>C</cite>D
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,24): unexpected-end-tag
+(1,25): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| "A"
+| <cite>
+| "B"
+| <div>
+| "CD"
+
+#data
+<b>A<cite>B<div>C</b>D
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,21): adoption-agency-1.3
+(1,22): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| "A"
+| <cite>
+| "B"
+| <div>
+| <b>
+| "C"
+| "D"
+
+#data
+
+#errors
+(1,0): expected-doctype-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+<DIV>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,5): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+
+#data
+<DIV> abc
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,9): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| " abc"
+
+#data
+<DIV> abc <B>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,13): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| " abc "
+| <b>
+
+#data
+<DIV> abc <B> def
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,17): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| " abc "
+| <b>
+| " def"
+
+#data
+<DIV> abc <B> def <I>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,21): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| " abc "
+| <b>
+| " def "
+| <i>
+
+#data
+<DIV> abc <B> def <I> ghi
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,25): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| " abc "
+| <b>
+| " def "
+| <i>
+| " ghi"
+
+#data
+<DIV> abc <B> def <I> ghi <P>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,29): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| " abc "
+| <b>
+| " def "
+| <i>
+| " ghi "
+| <p>
+
+#data
+<DIV> abc <B> def <I> ghi <P> jkl
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,33): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| " abc "
+| <b>
+| " def "
+| <i>
+| " ghi "
+| <p>
+| " jkl"
+
+#data
+<DIV> abc <B> def <I> ghi <P> jkl </B>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,38): adoption-agency-1.3
+(1,38): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| " abc "
+| <b>
+| " def "
+| <i>
+| " ghi "
+| <i>
+| <p>
+| <b>
+| " jkl "
+
+#data
+<DIV> abc <B> def <I> ghi <P> jkl </B> mno
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,38): adoption-agency-1.3
+(1,42): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| " abc "
+| <b>
+| " def "
+| <i>
+| " ghi "
+| <i>
+| <p>
+| <b>
+| " jkl "
+| " mno"
+
+#data
+<DIV> abc <B> def <I> ghi <P> jkl </B> mno </I>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,38): adoption-agency-1.3
+(1,47): adoption-agency-1.3
+(1,47): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| " abc "
+| <b>
+| " def "
+| <i>
+| " ghi "
+| <i>
+| <p>
+| <i>
+| <b>
+| " jkl "
+| " mno "
+
+#data
+<DIV> abc <B> def <I> ghi <P> jkl </B> mno </I> pqr
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,38): adoption-agency-1.3
+(1,47): adoption-agency-1.3
+(1,51): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| " abc "
+| <b>
+| " def "
+| <i>
+| " ghi "
+| <i>
+| <p>
+| <i>
+| <b>
+| " jkl "
+| " mno "
+| " pqr"
+
+#data
+<DIV> abc <B> def <I> ghi <P> jkl </B> mno </I> pqr </P>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,38): adoption-agency-1.3
+(1,47): adoption-agency-1.3
+(1,56): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| " abc "
+| <b>
+| " def "
+| <i>
+| " ghi "
+| <i>
+| <p>
+| <i>
+| <b>
+| " jkl "
+| " mno "
+| " pqr "
+
+#data
+<DIV> abc <B> def <I> ghi <P> jkl </B> mno </I> pqr </P> stu
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,38): adoption-agency-1.3
+(1,47): adoption-agency-1.3
+(1,60): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| " abc "
+| <b>
+| " def "
+| <i>
+| " ghi "
+| <i>
+| <p>
+| <i>
+| <b>
+| " jkl "
+| " mno "
+| " pqr "
+| " stu"
+
+#data
+<test attribute---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------->
+#errors
+(1,1040): expected-doctype-but-got-start-tag
+(1,1040): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <test>
+| attribute----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------=""
+
+#data
+<a href="blah">aba<table><a href="foo">br<tr><td></td></tr>x</table>aoe
+#errors
+(1,15): expected-doctype-but-got-start-tag
+(1,39): unexpected-start-tag-implies-table-voodoo
+(1,39): unexpected-start-tag-implies-end-tag
+(1,39): unexpected-end-tag
+(1,45): foster-parenting-character-in-table
+(1,45): foster-parenting-character-in-table
+(1,68): foster-parenting-character-in-table
+(1,71): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| href="blah"
+| "aba"
+| <a>
+| href="foo"
+| "br"
+| <a>
+| href="foo"
+| "x"
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <a>
+| href="foo"
+| "aoe"
+
+#data
+<a href="blah">aba<table><tr><td><a href="foo">br</td></tr>x</table>aoe
+#errors
+(1,15): expected-doctype-but-got-start-tag
+(1,54): unexpected-cell-end-tag
+(1,68): unexpected text in table
+(1,71): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| href="blah"
+| "abax"
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <a>
+| href="foo"
+| "br"
+| "aoe"
+
+#data
+<table><a href="blah">aba<tr><td><a href="foo">br</td></tr>x</table>aoe
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,22): unexpected-start-tag-implies-table-voodoo
+(1,29): foster-parenting-character-in-table
+(1,29): foster-parenting-character-in-table
+(1,29): foster-parenting-character-in-table
+(1,54): unexpected-cell-end-tag
+(1,68): foster-parenting-character-in-table
+(1,71): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| href="blah"
+| "aba"
+| <a>
+| href="blah"
+| "x"
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <a>
+| href="foo"
+| "br"
+| <a>
+| href="blah"
+| "aoe"
+
+#data
+<a href=a>aa<marquee>aa<a href=b>bb</marquee>aa
+#errors
+(1,10): expected-doctype-but-got-start-tag
+(1,45): end-tag-too-early
+(1,47): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| href="a"
+| "aa"
+| <marquee>
+| "aa"
+| <a>
+| href="b"
+| "bb"
+| "aa"
+
+#data
+<wbr><strike><code></strike><code><strike></code>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,28): adoption-agency-1.3
+(1,49): adoption-agency-1.3
+(1,49): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <wbr>
+| <strike>
+| <code>
+| <code>
+| <code>
+| <strike>
+
+#data
+<!DOCTYPE html><spacer>foo
+#errors
+(1,26): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <spacer>
+| "foo"
+
+#data
+<title><meta></title><link><title><meta></title>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <title>
+| "<meta>"
+| <link>
+| <title>
+| "<meta>"
+| <body>
+
+#data
+<style><!--</style><meta><script>--><link></script>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <style>
+| "<!--"
+| <meta>
+| <script>
+| "--><link>"
+| <body>
+
+#data
+<head><meta></head><link>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,25): unexpected-start-tag-out-of-my-head
+#document
+| <html>
+| <head>
+| <meta>
+| <link>
+| <body>
+
+#data
+<table><tr><tr><td><td><span><th><span>X</table>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,33): unexpected-cell-end-tag
+(1,48): unexpected-cell-end-tag
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <tr>
+| <td>
+| <td>
+| <span>
+| <th>
+| <span>
+| "X"
+
+#data
+<body><body><base><link><meta><title><p></title><body><p></body>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,12): unexpected-start-tag
+(1,54): unexpected-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <base>
+| <link>
+| <meta>
+| <title>
+| "<p>"
+| <p>
+
+#data
+<textarea><p></textarea>
+#errors
+(1,10): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <textarea>
+| "<p>"
+
+#data
+<p><image></p>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,10): unexpected-start-tag-treated-as
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| <img>
+
+#data
+<a><table><a></table><p><a><div><a>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,13): unexpected-start-tag-implies-table-voodoo
+(1,13): unexpected-start-tag-implies-end-tag
+(1,13): adoption-agency-1.3
+(1,27): unexpected-start-tag-implies-end-tag
+(1,27): adoption-agency-1.2
+(1,32): unexpected-end-tag
+(1,35): unexpected-start-tag-implies-end-tag
+(1,35): adoption-agency-1.2
+(1,35): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| <a>
+| <table>
+| <p>
+| <a>
+| <div>
+| <a>
+
+#data
+<head></p><meta><p>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,10): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <meta>
+| <body>
+| <p>
+
+#data
+<head></html><meta><p>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,19): expected-eof-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <meta>
+| <p>
+
+#data
+<b><table><td><i></table>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,14): unexpected-cell-in-table-body
+(1,25): unexpected-cell-end-tag
+(1,25): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <i>
+
+#data
+<b><table><td></b><i></table>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,14): unexpected-cell-in-table-body
+(1,18): unexpected-end-tag
+(1,29): unexpected-cell-end-tag
+(1,29): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <i>
+
+#data
+<h1><h2>
+#errors
+(1,4): expected-doctype-but-got-start-tag
+(1,8): unexpected-start-tag
+(1,8): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <h1>
+| <h2>
+
+#data
+<a><p><a></a></p></a>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,9): unexpected-start-tag-implies-end-tag
+(1,9): adoption-agency-1.3
+(1,21): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| <p>
+| <a>
+| <a>
+
+#data
+<b><button></b></button></b>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,15): adoption-agency-1.3
+(1,28): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| <button>
+| <b>
+
+#data
+<p><b><div><marquee></p></b></div>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,11): unexpected-end-tag
+(1,24): unexpected-end-tag
+(1,28): unexpected-end-tag
+(1,34): end-tag-too-early
+(1,34): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| <b>
+| <div>
+| <b>
+| <marquee>
+| <p>
+
+#data
+<script></script></div><title></title><p><p>
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,23): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <script>
+| <title>
+| <body>
+| <p>
+| <p>
+
+#data
+<p><hr></p>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,11): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| <hr>
+| <p>
+
+#data
+<select><b><option><select><option></b></select>
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,11): unexpected-start-tag-in-select
+(1,27): unexpected-select-in-select
+(1,39): unexpected-end-tag
+(1,48): unexpected-end-tag
+(1,48): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <select>
+| <option>
+| <option>
+
+#data
+<html><head><title></title><body></body></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <title>
+| <body>
+
+#data
+<a><table><td><a><table></table><a></tr><a></table><a>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,14): unexpected-cell-in-table-body
+(1,35): unexpected-start-tag-implies-end-tag
+(1,40): unexpected-cell-end-tag
+(1,43): unexpected-start-tag-implies-table-voodoo
+(1,43): unexpected-start-tag-implies-end-tag
+(1,43): unexpected-end-tag
+(1,54): unexpected-start-tag-implies-end-tag
+(1,54): adoption-agency-1.2
+(1,54): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| <a>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <a>
+| <table>
+| <a>
+| <a>
+
+#data
+<ul><li></li><div><li></div><li><li><div><li><address><li><b><em></b><li></ul>
+#errors
+(1,4): expected-doctype-but-got-start-tag
+(1,45): end-tag-too-early
+(1,58): end-tag-too-early
+(1,69): adoption-agency-1.3
+#document
+| <html>
+| <head>
+| <body>
+| <ul>
+| <li>
+| <div>
+| <li>
+| <li>
+| <li>
+| <div>
+| <li>
+| <address>
+| <li>
+| <b>
+| <em>
+| <li>
+
+#data
+<ul><li><ul></li><li>a</li></ul></li></ul>
+#errors
+(1,4): expected-doctype-but-got-start-tag
+(1,17): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <body>
+| <ul>
+| <li>
+| <ul>
+| <li>
+| "a"
+
+#data
+<frameset><frame><frameset><frame></frameset><noframes></noframes></frameset>
+#errors
+(1,10): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <frameset>
+| <frame>
+| <frameset>
+| <frame>
+| <noframes>
+
+#data
+<h1><table><td><h3></table><h3></h1>
+#errors
+(1,4): expected-doctype-but-got-start-tag
+(1,15): unexpected-cell-in-table-body
+(1,27): unexpected-cell-end-tag
+(1,31): unexpected-start-tag
+(1,36): end-tag-too-early
+#document
+| <html>
+| <head>
+| <body>
+| <h1>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <h3>
+| <h3>
+
+#data
+<table><colgroup><col><colgroup><col><col><col><colgroup><col><col><thead><tr><td></table>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <colgroup>
+| <col>
+| <colgroup>
+| <col>
+| <col>
+| <col>
+| <colgroup>
+| <col>
+| <col>
+| <thead>
+| <tr>
+| <td>
+
+#data
+<table><col><tbody><col><tr><col><td><col></table><col>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,37): unexpected-cell-in-table-body
+(1,55): unexpected-start-tag-ignored
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <colgroup>
+| <col>
+| <tbody>
+| <colgroup>
+| <col>
+| <tbody>
+| <tr>
+| <colgroup>
+| <col>
+| <tbody>
+| <tr>
+| <td>
+| <colgroup>
+| <col>
+
+#data
+<table><colgroup><tbody><colgroup><tr><colgroup><td><colgroup></table><colgroup>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,52): unexpected-cell-in-table-body
+(1,80): unexpected-start-tag-ignored
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <colgroup>
+| <tbody>
+| <colgroup>
+| <tbody>
+| <tr>
+| <colgroup>
+| <tbody>
+| <tr>
+| <td>
+| <colgroup>
+
+#data
+</strong></b></em></i></u></strike></s></blink></tt></pre></big></small></font></select></h1></h2></h3></h4></h5></h6></body></br></a></img></title></span></style></script></table></th></td></tr></frame></area></link></param></hr></input></col></base></meta></basefont></bgsound></embed></spacer></p></dd></dt></caption></colgroup></tbody></tfoot></thead></address></blockquote></center></dir></div></dl></fieldset></listing></menu></ol></ul></li></nobr></wbr></form></button></marquee></object></html></frameset></head></iframe></image></isindex></noembed></noframes></noscript></optgroup></option></plaintext></textarea>
+#errors
+(1,9): expected-doctype-but-got-end-tag
+(1,9): unexpected-end-tag-before-html
+(1,13): unexpected-end-tag-before-html
+(1,18): unexpected-end-tag-before-html
+(1,22): unexpected-end-tag-before-html
+(1,26): unexpected-end-tag-before-html
+(1,35): unexpected-end-tag-before-html
+(1,39): unexpected-end-tag-before-html
+(1,47): unexpected-end-tag-before-html
+(1,52): unexpected-end-tag-before-html
+(1,58): unexpected-end-tag-before-html
+(1,64): unexpected-end-tag-before-html
+(1,72): unexpected-end-tag-before-html
+(1,79): unexpected-end-tag-before-html
+(1,88): unexpected-end-tag-before-html
+(1,93): unexpected-end-tag-before-html
+(1,98): unexpected-end-tag-before-html
+(1,103): unexpected-end-tag-before-html
+(1,108): unexpected-end-tag-before-html
+(1,113): unexpected-end-tag-before-html
+(1,118): unexpected-end-tag-before-html
+(1,130): unexpected-end-tag-after-body
+(1,130): unexpected-end-tag-treated-as
+(1,134): unexpected-end-tag
+(1,140): unexpected-end-tag
+(1,148): unexpected-end-tag
+(1,155): unexpected-end-tag
+(1,163): unexpected-end-tag
+(1,172): unexpected-end-tag
+(1,180): unexpected-end-tag
+(1,185): unexpected-end-tag
+(1,190): unexpected-end-tag
+(1,195): unexpected-end-tag
+(1,203): unexpected-end-tag
+(1,210): unexpected-end-tag
+(1,217): unexpected-end-tag
+(1,225): unexpected-end-tag
+(1,230): unexpected-end-tag
+(1,238): unexpected-end-tag
+(1,244): unexpected-end-tag
+(1,251): unexpected-end-tag
+(1,258): unexpected-end-tag
+(1,269): unexpected-end-tag
+(1,279): unexpected-end-tag
+(1,287): unexpected-end-tag
+(1,296): unexpected-end-tag
+(1,300): unexpected-end-tag
+(1,305): unexpected-end-tag
+(1,310): unexpected-end-tag
+(1,320): unexpected-end-tag
+(1,331): unexpected-end-tag
+(1,339): unexpected-end-tag
+(1,347): unexpected-end-tag
+(1,355): unexpected-end-tag
+(1,365): end-tag-too-early
+(1,378): end-tag-too-early
+(1,387): end-tag-too-early
+(1,393): end-tag-too-early
+(1,399): end-tag-too-early
+(1,404): end-tag-too-early
+(1,415): end-tag-too-early
+(1,425): end-tag-too-early
+(1,432): end-tag-too-early
+(1,437): end-tag-too-early
+(1,442): end-tag-too-early
+(1,447): unexpected-end-tag
+(1,454): unexpected-end-tag
+(1,460): unexpected-end-tag
+(1,467): unexpected-end-tag
+(1,476): end-tag-too-early
+(1,486): end-tag-too-early
+(1,495): end-tag-too-early
+(1,513): expected-eof-but-got-end-tag
+(1,513): unexpected-end-tag
+(1,520): unexpected-end-tag
+(1,529): unexpected-end-tag
+(1,537): unexpected-end-tag
+(1,547): unexpected-end-tag
+(1,557): unexpected-end-tag
+(1,568): unexpected-end-tag
+(1,579): unexpected-end-tag
+(1,590): unexpected-end-tag
+(1,599): unexpected-end-tag
+(1,611): unexpected-end-tag
+(1,622): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <body>
+| <br>
+| <p>
+
+#data
+<table><tr></strong></b></em></i></u></strike></s></blink></tt></pre></big></small></font></select></h1></h2></h3></h4></h5></h6></body></br></a></img></title></span></style></script></table></th></td></tr></frame></area></link></param></hr></input></col></base></meta></basefont></bgsound></embed></spacer></p></dd></dt></caption></colgroup></tbody></tfoot></thead></address></blockquote></center></dir></div></dl></fieldset></listing></menu></ol></ul></li></nobr></wbr></form></button></marquee></object></html></frameset></head></iframe></image></isindex></noembed></noframes></noscript></optgroup></option></plaintext></textarea>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,20): unexpected-end-tag-implies-table-voodoo
+(1,20): unexpected-end-tag
+(1,24): unexpected-end-tag-implies-table-voodoo
+(1,24): unexpected-end-tag
+(1,29): unexpected-end-tag-implies-table-voodoo
+(1,29): unexpected-end-tag
+(1,33): unexpected-end-tag-implies-table-voodoo
+(1,33): unexpected-end-tag
+(1,37): unexpected-end-tag-implies-table-voodoo
+(1,37): unexpected-end-tag
+(1,46): unexpected-end-tag-implies-table-voodoo
+(1,46): unexpected-end-tag
+(1,50): unexpected-end-tag-implies-table-voodoo
+(1,50): unexpected-end-tag
+(1,58): unexpected-end-tag-implies-table-voodoo
+(1,58): unexpected-end-tag
+(1,63): unexpected-end-tag-implies-table-voodoo
+(1,63): unexpected-end-tag
+(1,69): unexpected-end-tag-implies-table-voodoo
+(1,69): end-tag-too-early
+(1,75): unexpected-end-tag-implies-table-voodoo
+(1,75): unexpected-end-tag
+(1,83): unexpected-end-tag-implies-table-voodoo
+(1,83): unexpected-end-tag
+(1,90): unexpected-end-tag-implies-table-voodoo
+(1,90): unexpected-end-tag
+(1,99): unexpected-end-tag-implies-table-voodoo
+(1,99): unexpected-end-tag
+(1,104): unexpected-end-tag-implies-table-voodoo
+(1,104): end-tag-too-early
+(1,109): unexpected-end-tag-implies-table-voodoo
+(1,109): end-tag-too-early
+(1,114): unexpected-end-tag-implies-table-voodoo
+(1,114): end-tag-too-early
+(1,119): unexpected-end-tag-implies-table-voodoo
+(1,119): end-tag-too-early
+(1,124): unexpected-end-tag-implies-table-voodoo
+(1,124): end-tag-too-early
+(1,129): unexpected-end-tag-implies-table-voodoo
+(1,129): end-tag-too-early
+(1,136): unexpected-end-tag-in-table-row
+(1,141): unexpected-end-tag-implies-table-voodoo
+(1,141): unexpected-end-tag-treated-as
+(1,145): unexpected-end-tag-implies-table-voodoo
+(1,145): unexpected-end-tag
+(1,151): unexpected-end-tag-implies-table-voodoo
+(1,151): unexpected-end-tag
+(1,159): unexpected-end-tag-implies-table-voodoo
+(1,159): unexpected-end-tag
+(1,166): unexpected-end-tag-implies-table-voodoo
+(1,166): unexpected-end-tag
+(1,174): unexpected-end-tag-implies-table-voodoo
+(1,174): unexpected-end-tag
+(1,183): unexpected-end-tag-implies-table-voodoo
+(1,183): unexpected-end-tag
+(1,196): unexpected-end-tag
+(1,201): unexpected-end-tag
+(1,206): unexpected-end-tag
+(1,214): unexpected-end-tag
+(1,221): unexpected-end-tag
+(1,228): unexpected-end-tag
+(1,236): unexpected-end-tag
+(1,241): unexpected-end-tag
+(1,249): unexpected-end-tag
+(1,255): unexpected-end-tag
+(1,262): unexpected-end-tag
+(1,269): unexpected-end-tag
+(1,280): unexpected-end-tag
+(1,290): unexpected-end-tag
+(1,298): unexpected-end-tag
+(1,307): unexpected-end-tag
+(1,311): unexpected-end-tag
+(1,316): unexpected-end-tag
+(1,321): unexpected-end-tag
+(1,331): unexpected-end-tag
+(1,342): unexpected-end-tag
+(1,350): unexpected-end-tag
+(1,358): unexpected-end-tag
+(1,366): unexpected-end-tag
+(1,376): end-tag-too-early
+(1,389): end-tag-too-early
+(1,398): end-tag-too-early
+(1,404): end-tag-too-early
+(1,410): end-tag-too-early
+(1,415): end-tag-too-early
+(1,426): end-tag-too-early
+(1,436): end-tag-too-early
+(1,443): end-tag-too-early
+(1,448): end-tag-too-early
+(1,453): end-tag-too-early
+(1,458): unexpected-end-tag
+(1,465): unexpected-end-tag
+(1,471): unexpected-end-tag
+(1,478): unexpected-end-tag
+(1,487): end-tag-too-early
+(1,497): end-tag-too-early
+(1,506): end-tag-too-early
+(1,524): expected-eof-but-got-end-tag
+(1,524): unexpected-end-tag
+(1,531): unexpected-end-tag
+(1,540): unexpected-end-tag
+(1,548): unexpected-end-tag
+(1,558): unexpected-end-tag
+(1,568): unexpected-end-tag
+(1,579): unexpected-end-tag
+(1,590): unexpected-end-tag
+(1,601): unexpected-end-tag
+(1,610): unexpected-end-tag
+(1,622): unexpected-end-tag
+(1,633): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <body>
+| <br>
+| <table>
+| <tbody>
+| <tr>
+| <p>
+
+#data
+<frameset>
+#errors
+(1,10): expected-doctype-but-got-start-tag
+(1,10): eof-in-frameset
+#document
+| <html>
+| <head>
+| <frameset>
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests10.dat b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests10.dat
new file mode 100644
index 00000000000..3e9a9f19b9c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests10.dat
@@ -0,0 +1,847 @@
+#data
+<!DOCTYPE html><svg></svg>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+
+#data
+<!DOCTYPE html><svg></svg><![CDATA[a]]>
+#errors
+(1,28) expected-dashes-or-doctype
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <!-- [CDATA[a]] -->
+
+#data
+<!DOCTYPE html><body><svg></svg>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+
+#data
+<!DOCTYPE html><body><select><svg></svg></select>
+#errors
+(1,34) unexpected-start-tag-in-select
+(1,40) unexpected-end-tag-in-select
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+
+#data
+<!DOCTYPE html><body><select><option><svg></svg></option></select>
+#errors
+(1,42) unexpected-start-tag-in-select
+(1,48) unexpected-end-tag-in-select
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| <option>
+
+#data
+<!DOCTYPE html><body><table><svg></svg></table>
+#errors
+(1,33) foster-parenting-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <table>
+
+#data
+<!DOCTYPE html><body><table><svg><g>foo</g></svg></table>
+#errors
+(1,33) foster-parenting-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg g>
+| "foo"
+| <table>
+
+#data
+<!DOCTYPE html><body><table><svg><g>foo</g><g>bar</g></svg></table>
+#errors
+(1,33) foster-parenting-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg g>
+| "foo"
+| <svg g>
+| "bar"
+| <table>
+
+#data
+<!DOCTYPE html><body><table><tbody><svg><g>foo</g><g>bar</g></svg></tbody></table>
+#errors
+(1,40) foster-parenting-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg g>
+| "foo"
+| <svg g>
+| "bar"
+| <table>
+| <tbody>
+
+#data
+<!DOCTYPE html><body><table><tbody><tr><svg><g>foo</g><g>bar</g></svg></tr></tbody></table>
+#errors
+(1,44) foster-parenting-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg g>
+| "foo"
+| <svg g>
+| "bar"
+| <table>
+| <tbody>
+| <tr>
+
+#data
+<!DOCTYPE html><body><table><tbody><tr><td><svg><g>foo</g><g>bar</g></svg></td></tr></tbody></table>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <svg svg>
+| <svg g>
+| "foo"
+| <svg g>
+| "bar"
+
+#data
+<!DOCTYPE html><body><table><tbody><tr><td><svg><g>foo</g><g>bar</g></svg><p>baz</td></tr></tbody></table>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <svg svg>
+| <svg g>
+| "foo"
+| <svg g>
+| "bar"
+| <p>
+| "baz"
+
+#data
+<!DOCTYPE html><body><table><caption><svg><g>foo</g><g>bar</g></svg><p>baz</caption></table>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <caption>
+| <svg svg>
+| <svg g>
+| "foo"
+| <svg g>
+| "bar"
+| <p>
+| "baz"
+
+#data
+<!DOCTYPE html><body><table><caption><svg><g>foo</g><g>bar</g><p>baz</table><p>quux
+#errors
+(1,65) unexpected-html-element-in-foreign-content
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <caption>
+| <svg svg>
+| <svg g>
+| "foo"
+| <svg g>
+| "bar"
+| <p>
+| "baz"
+| <p>
+| "quux"
+
+#data
+<!DOCTYPE html><body><table><caption><svg><g>foo</g><g>bar</g>baz</table><p>quux
+#errors
+(1,73) unexpected-end-tag
+(1,73) expected-one-end-tag-but-got-another
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <caption>
+| <svg svg>
+| <svg g>
+| "foo"
+| <svg g>
+| "bar"
+| "baz"
+| <p>
+| "quux"
+
+#data
+<!DOCTYPE html><body><table><colgroup><svg><g>foo</g><g>bar</g><p>baz</table><p>quux
+#errors
+(1,43) foster-parenting-start-tag svg
+(1,66) unexpected HTML-like start tag token in foreign content
+(1,66) foster-parenting-start-tag
+(1,67) foster-parenting-character
+(1,68) foster-parenting-character
+(1,69) foster-parenting-character
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg g>
+| "foo"
+| <svg g>
+| "bar"
+| <p>
+| "baz"
+| <table>
+| <colgroup>
+| <p>
+| "quux"
+
+#data
+<!DOCTYPE html><body><table><tr><td><select><svg><g>foo</g><g>bar</g><p>baz</table><p>quux
+#errors
+(1,49) unexpected-start-tag-in-select
+(1,52) unexpected-start-tag-in-select
+(1,59) unexpected-end-tag-in-select
+(1,62) unexpected-start-tag-in-select
+(1,69) unexpected-end-tag-in-select
+(1,72) unexpected-start-tag-in-select
+(1,83) unexpected-table-element-end-tag-in-select-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <select>
+| "foobarbaz"
+| <p>
+| "quux"
+
+#data
+<!DOCTYPE html><body><table><select><svg><g>foo</g><g>bar</g><p>baz</table><p>quux
+#errors
+(1,36) unexpected-start-tag-implies-table-voodoo
+(1,41) unexpected-start-tag-in-select
+(1,44) unexpected-start-tag-in-select
+(1,51) unexpected-end-tag-in-select
+(1,54) unexpected-start-tag-in-select
+(1,61) unexpected-end-tag-in-select
+(1,64) unexpected-start-tag-in-select
+(1,75) unexpected-table-element-end-tag-in-select-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| "foobarbaz"
+| <table>
+| <p>
+| "quux"
+
+#data
+<!DOCTYPE html><body></body></html><svg><g>foo</g><g>bar</g><p>baz
+#errors
+(1,40) expected-eof-but-got-start-tag
+(1,63) unexpected-html-element-in-foreign-content
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg g>
+| "foo"
+| <svg g>
+| "bar"
+| <p>
+| "baz"
+
+#data
+<!DOCTYPE html><body></body><svg><g>foo</g><g>bar</g><p>baz
+#errors
+(1,33) unexpected-start-tag-after-body
+(1,56) unexpected-html-element-in-foreign-content
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg g>
+| "foo"
+| <svg g>
+| "bar"
+| <p>
+| "baz"
+
+#data
+<!DOCTYPE html><frameset><svg><g></g><g></g><p><span>
+#errors
+(1,30) unexpected-start-tag-in-frameset
+(1,33) unexpected-start-tag-in-frameset
+(1,37) unexpected-end-tag-in-frameset
+(1,40) unexpected-start-tag-in-frameset
+(1,44) unexpected-end-tag-in-frameset
+(1,47) unexpected-start-tag-in-frameset
+(1,53) unexpected-start-tag-in-frameset
+(1,53) eof-in-frameset
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+
+#data
+<!DOCTYPE html><frameset></frameset><svg><g></g><g></g><p><span>
+#errors
+(1,41) unexpected-start-tag-after-frameset
+(1,44) unexpected-start-tag-after-frameset
+(1,48) unexpected-end-tag-after-frameset
+(1,51) unexpected-start-tag-after-frameset
+(1,55) unexpected-end-tag-after-frameset
+(1,58) unexpected-start-tag-after-frameset
+(1,64) unexpected-start-tag-after-frameset
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+
+#data
+<!DOCTYPE html><body xlink:href=foo><svg xlink:href=foo></svg>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| xlink:href="foo"
+| <svg svg>
+| xlink href="foo"
+
+#data
+<!DOCTYPE html><body xlink:href=foo xml:lang=en><svg><g xml:lang=en xlink:href=foo></g></svg>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| xlink:href="foo"
+| xml:lang="en"
+| <svg svg>
+| <svg g>
+| xlink href="foo"
+| xml lang="en"
+
+#data
+<!DOCTYPE html><body xlink:href=foo xml:lang=en><svg><g xml:lang=en xlink:href=foo /></svg>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| xlink:href="foo"
+| xml:lang="en"
+| <svg svg>
+| <svg g>
+| xlink href="foo"
+| xml lang="en"
+
+#data
+<!DOCTYPE html><body xlink:href=foo xml:lang=en><svg><g xml:lang=en xlink:href=foo />bar</svg>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| xlink:href="foo"
+| xml:lang="en"
+| <svg svg>
+| <svg g>
+| xlink href="foo"
+| xml lang="en"
+| "bar"
+
+#data
+<svg></path>
+#errors
+(1,5) expected-doctype-but-got-start-tag
+(1,12) unexpected-end-tag
+(1,12) unexpected-end-tag
+(1,12) expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+
+#data
+<div><svg></div>a
+#errors
+(1,5) expected-doctype-but-got-start-tag
+(1,16) unexpected-end-tag
+(1,16) end-tag-too-early
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| <svg svg>
+| "a"
+
+#data
+<div><svg><path></div>a
+#errors
+(1,5) expected-doctype-but-got-start-tag
+(1,22) unexpected-end-tag
+(1,22) end-tag-too-early
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| <svg svg>
+| <svg path>
+| "a"
+
+#data
+<div><svg><path></svg><path>
+#errors
+(1,5) expected-doctype-but-got-start-tag
+(1,22) unexpected-end-tag
+(1,28) expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| <svg svg>
+| <svg path>
+| <path>
+
+#data
+<div><svg><path><foreignObject><math></div>a
+#errors
+(1,5) expected-doctype-but-got-start-tag
+(1,43) unexpected-end-tag
+(1,43) end-tag-too-early
+(1,44) expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| <svg svg>
+| <svg path>
+| <svg foreignObject>
+| <math math>
+| "a"
+
+#data
+<div><svg><path><foreignObject><p></div>a
+#errors
+(1,5) expected-doctype-but-got-start-tag
+(1,40) end-tag-too-early
+(1,41) expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| <svg svg>
+| <svg path>
+| <svg foreignObject>
+| <p>
+| "a"
+
+#data
+<!DOCTYPE html><svg><desc><div><svg><ul>a
+#errors
+(1,40) unexpected-html-element-in-foreign-content
+(1,41) expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg desc>
+| <div>
+| <svg svg>
+| <ul>
+| "a"
+
+#data
+<!DOCTYPE html><svg><desc><svg><ul>a
+#errors
+(1,35) unexpected-html-element-in-foreign-content
+(1,36) expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg desc>
+| <svg svg>
+| <ul>
+| "a"
+
+#data
+<!DOCTYPE html><p><svg><desc><p>
+#errors
+(1,32) expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <svg svg>
+| <svg desc>
+| <p>
+
+#data
+<!DOCTYPE html><p><svg><title><p>
+#errors
+(1,33) expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <svg svg>
+| <svg title>
+| <p>
+
+#data
+<div><svg><path><foreignObject><p></foreignObject><p>
+#errors
+(1,5) expected-doctype-but-got-start-tag
+(1,50) unexpected-end-tag
+(1,53) expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| <svg svg>
+| <svg path>
+| <svg foreignObject>
+| <p>
+| <p>
+
+#data
+<math><mi><div><object><div><span></span></div></object></div></mi><mi>
+#errors
+(1,6) expected-doctype-but-got-start-tag
+(1,71) expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mi>
+| <div>
+| <object>
+| <div>
+| <span>
+| <math mi>
+
+#data
+<math><mi><svg><foreignObject><div><div></div></div></foreignObject></svg></mi><mi>
+#errors
+(1,6) expected-doctype-but-got-start-tag
+(1,83) expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mi>
+| <svg svg>
+| <svg foreignObject>
+| <div>
+| <div>
+| <math mi>
+
+#data
+<svg><script></script><path>
+#errors
+(1,5) expected-doctype-but-got-start-tag
+(1,28) expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg script>
+| <svg path>
+
+#data
+<table><svg></svg><tr>
+#errors
+(1,7) expected-doctype-but-got-start-tag
+(1,12) unexpected-start-tag-implies-table-voodoo
+(1,22) eof-in-table
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <table>
+| <tbody>
+| <tr>
+
+#data
+<math><mi><mglyph>
+#errors
+(1,6) expected-doctype-but-got-start-tag
+(1,18) expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mi>
+| <math mglyph>
+
+#data
+<math><mi><malignmark>
+#errors
+(1,6) expected-doctype-but-got-start-tag
+(1,22) expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mi>
+| <math malignmark>
+
+#data
+<math><mo><mglyph>
+#errors
+(1,6) expected-doctype-but-got-start-tag
+(1,18) expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mo>
+| <math mglyph>
+
+#data
+<math><mo><malignmark>
+#errors
+(1,6) expected-doctype-but-got-start-tag
+(1,22) expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mo>
+| <math malignmark>
+
+#data
+<math><mn><mglyph>
+#errors
+(1,6) expected-doctype-but-got-start-tag
+(1,18) expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mn>
+| <math mglyph>
+
+#data
+<math><mn><malignmark>
+#errors
+(1,6) expected-doctype-but-got-start-tag
+(1,22) expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mn>
+| <math malignmark>
+
+#data
+<math><ms><mglyph>
+#errors
+(1,6) expected-doctype-but-got-start-tag
+(1,18) expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math ms>
+| <math mglyph>
+
+#data
+<math><ms><malignmark>
+#errors
+(1,6) expected-doctype-but-got-start-tag
+(1,22) expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math ms>
+| <math malignmark>
+
+#data
+<math><mtext><mglyph>
+#errors
+(1,6) expected-doctype-but-got-start-tag
+(1,21) expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mtext>
+| <math mglyph>
+
+#data
+<math><mtext><malignmark>
+#errors
+(1,6) expected-doctype-but-got-start-tag
+(1,25) expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mtext>
+| <math malignmark>
+
+#data
+<math><annotation-xml><svg></svg></annotation-xml><mi>
+#errors
+(1,6) expected-doctype-but-got-start-tag
+(1,54) expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math annotation-xml>
+| <svg svg>
+| <math mi>
+
+#data
+<math><annotation-xml><svg><foreignObject><div><math><mi></mi></math><span></span></div></foreignObject><path></path></svg></annotation-xml><mi>
+#errors
+(1,6) expected-doctype-but-got-start-tag
+(1,144) expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math annotation-xml>
+| <svg svg>
+| <svg foreignObject>
+| <div>
+| <math math>
+| <math mi>
+| <span>
+| <svg path>
+| <math mi>
+
+#data
+<math><annotation-xml><svg><foreignObject><math><mi><svg></svg></mi><mo></mo></math><span></span></foreignObject><path></path></svg></annotation-xml><mi>
+#errors
+(1,6) expected-doctype-but-got-start-tag
+(1,153) expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math annotation-xml>
+| <svg svg>
+| <svg foreignObject>
+| <math math>
+| <math mi>
+| <svg svg>
+| <math mo>
+| <span>
+| <svg path>
+| <math mi>
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests11.dat b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests11.dat
new file mode 100644
index 00000000000..ad62cdf659b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests11.dat
@@ -0,0 +1,482 @@
+#data
+<!DOCTYPE html><body><svg attributeName='' attributeType='' baseFrequency='' baseProfile='' calcMode='' clipPathUnits='' contentScriptType='' contentStyleType='' diffuseConstant='' edgeMode='' externalResourcesRequired='' filterRes='' filterUnits='' glyphRef='' gradientTransform='' gradientUnits='' kernelMatrix='' kernelUnitLength='' keyPoints='' keySplines='' keyTimes='' lengthAdjust='' limitingConeAngle='' markerHeight='' markerUnits='' markerWidth='' maskContentUnits='' maskUnits='' numOctaves='' pathLength='' patternContentUnits='' patternTransform='' patternUnits='' pointsAtX='' pointsAtY='' pointsAtZ='' preserveAlpha='' preserveAspectRatio='' primitiveUnits='' refX='' refY='' repeatCount='' repeatDur='' requiredExtensions='' requiredFeatures='' specularConstant='' specularExponent='' spreadMethod='' startOffset='' stdDeviation='' stitchTiles='' surfaceScale='' systemLanguage='' tableValues='' targetX='' targetY='' textLength='' viewBox='' viewTarget='' xChannelSelector='' yChannelSelector='' zoomAndPan=''></svg>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| attributeName=""
+| attributeType=""
+| baseFrequency=""
+| baseProfile=""
+| calcMode=""
+| clipPathUnits=""
+| contentscripttype=""
+| contentstyletype=""
+| diffuseConstant=""
+| edgeMode=""
+| externalresourcesrequired=""
+| filterUnits=""
+| filterres=""
+| glyphRef=""
+| gradientTransform=""
+| gradientUnits=""
+| kernelMatrix=""
+| kernelUnitLength=""
+| keyPoints=""
+| keySplines=""
+| keyTimes=""
+| lengthAdjust=""
+| limitingConeAngle=""
+| markerHeight=""
+| markerUnits=""
+| markerWidth=""
+| maskContentUnits=""
+| maskUnits=""
+| numOctaves=""
+| pathLength=""
+| patternContentUnits=""
+| patternTransform=""
+| patternUnits=""
+| pointsAtX=""
+| pointsAtY=""
+| pointsAtZ=""
+| preserveAlpha=""
+| preserveAspectRatio=""
+| primitiveUnits=""
+| refX=""
+| refY=""
+| repeatCount=""
+| repeatDur=""
+| requiredExtensions=""
+| requiredFeatures=""
+| specularConstant=""
+| specularExponent=""
+| spreadMethod=""
+| startOffset=""
+| stdDeviation=""
+| stitchTiles=""
+| surfaceScale=""
+| systemLanguage=""
+| tableValues=""
+| targetX=""
+| targetY=""
+| textLength=""
+| viewBox=""
+| viewTarget=""
+| xChannelSelector=""
+| yChannelSelector=""
+| zoomAndPan=""
+
+#data
+<!DOCTYPE html><BODY><SVG ATTRIBUTENAME='' ATTRIBUTETYPE='' BASEFREQUENCY='' BASEPROFILE='' CALCMODE='' CLIPPATHUNITS='' CONTENTSCRIPTTYPE='' CONTENTSTYLETYPE='' DIFFUSECONSTANT='' EDGEMODE='' EXTERNALRESOURCESREQUIRED='' FILTERRES='' FILTERUNITS='' GLYPHREF='' GRADIENTTRANSFORM='' GRADIENTUNITS='' KERNELMATRIX='' KERNELUNITLENGTH='' KEYPOINTS='' KEYSPLINES='' KEYTIMES='' LENGTHADJUST='' LIMITINGCONEANGLE='' MARKERHEIGHT='' MARKERUNITS='' MARKERWIDTH='' MASKCONTENTUNITS='' MASKUNITS='' NUMOCTAVES='' PATHLENGTH='' PATTERNCONTENTUNITS='' PATTERNTRANSFORM='' PATTERNUNITS='' POINTSATX='' POINTSATY='' POINTSATZ='' PRESERVEALPHA='' PRESERVEASPECTRATIO='' PRIMITIVEUNITS='' REFX='' REFY='' REPEATCOUNT='' REPEATDUR='' REQUIREDEXTENSIONS='' REQUIREDFEATURES='' SPECULARCONSTANT='' SPECULAREXPONENT='' SPREADMETHOD='' STARTOFFSET='' STDDEVIATION='' STITCHTILES='' SURFACESCALE='' SYSTEMLANGUAGE='' TABLEVALUES='' TARGETX='' TARGETY='' TEXTLENGTH='' VIEWBOX='' VIEWTARGET='' XCHANNELSELECTOR='' YCHANNELSELECTOR='' ZOOMANDPAN=''></SVG>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| attributeName=""
+| attributeType=""
+| baseFrequency=""
+| baseProfile=""
+| calcMode=""
+| clipPathUnits=""
+| contentscripttype=""
+| contentstyletype=""
+| diffuseConstant=""
+| edgeMode=""
+| externalresourcesrequired=""
+| filterUnits=""
+| filterres=""
+| glyphRef=""
+| gradientTransform=""
+| gradientUnits=""
+| kernelMatrix=""
+| kernelUnitLength=""
+| keyPoints=""
+| keySplines=""
+| keyTimes=""
+| lengthAdjust=""
+| limitingConeAngle=""
+| markerHeight=""
+| markerUnits=""
+| markerWidth=""
+| maskContentUnits=""
+| maskUnits=""
+| numOctaves=""
+| pathLength=""
+| patternContentUnits=""
+| patternTransform=""
+| patternUnits=""
+| pointsAtX=""
+| pointsAtY=""
+| pointsAtZ=""
+| preserveAlpha=""
+| preserveAspectRatio=""
+| primitiveUnits=""
+| refX=""
+| refY=""
+| repeatCount=""
+| repeatDur=""
+| requiredExtensions=""
+| requiredFeatures=""
+| specularConstant=""
+| specularExponent=""
+| spreadMethod=""
+| startOffset=""
+| stdDeviation=""
+| stitchTiles=""
+| surfaceScale=""
+| systemLanguage=""
+| tableValues=""
+| targetX=""
+| targetY=""
+| textLength=""
+| viewBox=""
+| viewTarget=""
+| xChannelSelector=""
+| yChannelSelector=""
+| zoomAndPan=""
+
+#data
+<!DOCTYPE html><body><svg attributename='' attributetype='' basefrequency='' baseprofile='' calcmode='' clippathunits='' contentscripttype='' contentstyletype='' diffuseconstant='' edgemode='' externalresourcesrequired='' filterres='' filterunits='' glyphref='' gradienttransform='' gradientunits='' kernelmatrix='' kernelunitlength='' keypoints='' keysplines='' keytimes='' lengthadjust='' limitingconeangle='' markerheight='' markerunits='' markerwidth='' maskcontentunits='' maskunits='' numoctaves='' pathlength='' patterncontentunits='' patterntransform='' patternunits='' pointsatx='' pointsaty='' pointsatz='' preservealpha='' preserveaspectratio='' primitiveunits='' refx='' refy='' repeatcount='' repeatdur='' requiredextensions='' requiredfeatures='' specularconstant='' specularexponent='' spreadmethod='' startoffset='' stddeviation='' stitchtiles='' surfacescale='' systemlanguage='' tablevalues='' targetx='' targety='' textlength='' viewbox='' viewtarget='' xchannelselector='' ychannelselector='' zoomandpan=''></svg>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| attributeName=""
+| attributeType=""
+| baseFrequency=""
+| baseProfile=""
+| calcMode=""
+| clipPathUnits=""
+| contentscripttype=""
+| contentstyletype=""
+| diffuseConstant=""
+| edgeMode=""
+| externalresourcesrequired=""
+| filterUnits=""
+| filterres=""
+| glyphRef=""
+| gradientTransform=""
+| gradientUnits=""
+| kernelMatrix=""
+| kernelUnitLength=""
+| keyPoints=""
+| keySplines=""
+| keyTimes=""
+| lengthAdjust=""
+| limitingConeAngle=""
+| markerHeight=""
+| markerUnits=""
+| markerWidth=""
+| maskContentUnits=""
+| maskUnits=""
+| numOctaves=""
+| pathLength=""
+| patternContentUnits=""
+| patternTransform=""
+| patternUnits=""
+| pointsAtX=""
+| pointsAtY=""
+| pointsAtZ=""
+| preserveAlpha=""
+| preserveAspectRatio=""
+| primitiveUnits=""
+| refX=""
+| refY=""
+| repeatCount=""
+| repeatDur=""
+| requiredExtensions=""
+| requiredFeatures=""
+| specularConstant=""
+| specularExponent=""
+| spreadMethod=""
+| startOffset=""
+| stdDeviation=""
+| stitchTiles=""
+| surfaceScale=""
+| systemLanguage=""
+| tableValues=""
+| targetX=""
+| targetY=""
+| textLength=""
+| viewBox=""
+| viewTarget=""
+| xChannelSelector=""
+| yChannelSelector=""
+| zoomAndPan=""
+
+#data
+<!DOCTYPE html><body><math attributeName='' attributeType='' baseFrequency='' baseProfile='' calcMode='' clipPathUnits='' contentScriptType='' contentStyleType='' diffuseConstant='' edgeMode='' externalResourcesRequired='' filterRes='' filterUnits='' glyphRef='' gradientTransform='' gradientUnits='' kernelMatrix='' kernelUnitLength='' keyPoints='' keySplines='' keyTimes='' lengthAdjust='' limitingConeAngle='' markerHeight='' markerUnits='' markerWidth='' maskContentUnits='' maskUnits='' numOctaves='' pathLength='' patternContentUnits='' patternTransform='' patternUnits='' pointsAtX='' pointsAtY='' pointsAtZ='' preserveAlpha='' preserveAspectRatio='' primitiveUnits='' refX='' refY='' repeatCount='' repeatDur='' requiredExtensions='' requiredFeatures='' specularConstant='' specularExponent='' spreadMethod='' startOffset='' stdDeviation='' stitchTiles='' surfaceScale='' systemLanguage='' tableValues='' targetX='' targetY='' textLength='' viewBox='' viewTarget='' xChannelSelector='' yChannelSelector='' zoomAndPan=''></math>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <math math>
+| attributename=""
+| attributetype=""
+| basefrequency=""
+| baseprofile=""
+| calcmode=""
+| clippathunits=""
+| contentscripttype=""
+| contentstyletype=""
+| diffuseconstant=""
+| edgemode=""
+| externalresourcesrequired=""
+| filterres=""
+| filterunits=""
+| glyphref=""
+| gradienttransform=""
+| gradientunits=""
+| kernelmatrix=""
+| kernelunitlength=""
+| keypoints=""
+| keysplines=""
+| keytimes=""
+| lengthadjust=""
+| limitingconeangle=""
+| markerheight=""
+| markerunits=""
+| markerwidth=""
+| maskcontentunits=""
+| maskunits=""
+| numoctaves=""
+| pathlength=""
+| patterncontentunits=""
+| patterntransform=""
+| patternunits=""
+| pointsatx=""
+| pointsaty=""
+| pointsatz=""
+| preservealpha=""
+| preserveaspectratio=""
+| primitiveunits=""
+| refx=""
+| refy=""
+| repeatcount=""
+| repeatdur=""
+| requiredextensions=""
+| requiredfeatures=""
+| specularconstant=""
+| specularexponent=""
+| spreadmethod=""
+| startoffset=""
+| stddeviation=""
+| stitchtiles=""
+| surfacescale=""
+| systemlanguage=""
+| tablevalues=""
+| targetx=""
+| targety=""
+| textlength=""
+| viewbox=""
+| viewtarget=""
+| xchannelselector=""
+| ychannelselector=""
+| zoomandpan=""
+
+#data
+<!DOCTYPE html><body><svg><altGlyph /><altGlyphDef /><altGlyphItem /><animateColor /><animateMotion /><animateTransform /><clipPath /><feBlend /><feColorMatrix /><feComponentTransfer /><feComposite /><feConvolveMatrix /><feDiffuseLighting /><feDisplacementMap /><feDistantLight /><feFlood /><feFuncA /><feFuncB /><feFuncG /><feFuncR /><feGaussianBlur /><feImage /><feMerge /><feMergeNode /><feMorphology /><feOffset /><fePointLight /><feSpecularLighting /><feSpotLight /><feTile /><feTurbulence /><foreignObject /><glyphRef /><linearGradient /><radialGradient /><textPath /></svg>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg altGlyph>
+| <svg altGlyphDef>
+| <svg altGlyphItem>
+| <svg animateColor>
+| <svg animateMotion>
+| <svg animateTransform>
+| <svg clipPath>
+| <svg feBlend>
+| <svg feColorMatrix>
+| <svg feComponentTransfer>
+| <svg feComposite>
+| <svg feConvolveMatrix>
+| <svg feDiffuseLighting>
+| <svg feDisplacementMap>
+| <svg feDistantLight>
+| <svg feFlood>
+| <svg feFuncA>
+| <svg feFuncB>
+| <svg feFuncG>
+| <svg feFuncR>
+| <svg feGaussianBlur>
+| <svg feImage>
+| <svg feMerge>
+| <svg feMergeNode>
+| <svg feMorphology>
+| <svg feOffset>
+| <svg fePointLight>
+| <svg feSpecularLighting>
+| <svg feSpotLight>
+| <svg feTile>
+| <svg feTurbulence>
+| <svg foreignObject>
+| <svg glyphRef>
+| <svg linearGradient>
+| <svg radialGradient>
+| <svg textPath>
+
+#data
+<!DOCTYPE html><body><svg><altglyph /><altglyphdef /><altglyphitem /><animatecolor /><animatemotion /><animatetransform /><clippath /><feblend /><fecolormatrix /><fecomponenttransfer /><fecomposite /><feconvolvematrix /><fediffuselighting /><fedisplacementmap /><fedistantlight /><feflood /><fefunca /><fefuncb /><fefuncg /><fefuncr /><fegaussianblur /><feimage /><femerge /><femergenode /><femorphology /><feoffset /><fepointlight /><fespecularlighting /><fespotlight /><fetile /><feturbulence /><foreignobject /><glyphref /><lineargradient /><radialgradient /><textpath /></svg>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg altGlyph>
+| <svg altGlyphDef>
+| <svg altGlyphItem>
+| <svg animateColor>
+| <svg animateMotion>
+| <svg animateTransform>
+| <svg clipPath>
+| <svg feBlend>
+| <svg feColorMatrix>
+| <svg feComponentTransfer>
+| <svg feComposite>
+| <svg feConvolveMatrix>
+| <svg feDiffuseLighting>
+| <svg feDisplacementMap>
+| <svg feDistantLight>
+| <svg feFlood>
+| <svg feFuncA>
+| <svg feFuncB>
+| <svg feFuncG>
+| <svg feFuncR>
+| <svg feGaussianBlur>
+| <svg feImage>
+| <svg feMerge>
+| <svg feMergeNode>
+| <svg feMorphology>
+| <svg feOffset>
+| <svg fePointLight>
+| <svg feSpecularLighting>
+| <svg feSpotLight>
+| <svg feTile>
+| <svg feTurbulence>
+| <svg foreignObject>
+| <svg glyphRef>
+| <svg linearGradient>
+| <svg radialGradient>
+| <svg textPath>
+
+#data
+<!DOCTYPE html><BODY><SVG><ALTGLYPH /><ALTGLYPHDEF /><ALTGLYPHITEM /><ANIMATECOLOR /><ANIMATEMOTION /><ANIMATETRANSFORM /><CLIPPATH /><FEBLEND /><FECOLORMATRIX /><FECOMPONENTTRANSFER /><FECOMPOSITE /><FECONVOLVEMATRIX /><FEDIFFUSELIGHTING /><FEDISPLACEMENTMAP /><FEDISTANTLIGHT /><FEFLOOD /><FEFUNCA /><FEFUNCB /><FEFUNCG /><FEFUNCR /><FEGAUSSIANBLUR /><FEIMAGE /><FEMERGE /><FEMERGENODE /><FEMORPHOLOGY /><FEOFFSET /><FEPOINTLIGHT /><FESPECULARLIGHTING /><FESPOTLIGHT /><FETILE /><FETURBULENCE /><FOREIGNOBJECT /><GLYPHREF /><LINEARGRADIENT /><RADIALGRADIENT /><TEXTPATH /></SVG>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg altGlyph>
+| <svg altGlyphDef>
+| <svg altGlyphItem>
+| <svg animateColor>
+| <svg animateMotion>
+| <svg animateTransform>
+| <svg clipPath>
+| <svg feBlend>
+| <svg feColorMatrix>
+| <svg feComponentTransfer>
+| <svg feComposite>
+| <svg feConvolveMatrix>
+| <svg feDiffuseLighting>
+| <svg feDisplacementMap>
+| <svg feDistantLight>
+| <svg feFlood>
+| <svg feFuncA>
+| <svg feFuncB>
+| <svg feFuncG>
+| <svg feFuncR>
+| <svg feGaussianBlur>
+| <svg feImage>
+| <svg feMerge>
+| <svg feMergeNode>
+| <svg feMorphology>
+| <svg feOffset>
+| <svg fePointLight>
+| <svg feSpecularLighting>
+| <svg feSpotLight>
+| <svg feTile>
+| <svg feTurbulence>
+| <svg foreignObject>
+| <svg glyphRef>
+| <svg linearGradient>
+| <svg radialGradient>
+| <svg textPath>
+
+#data
+<!DOCTYPE html><body><math><altGlyph /><altGlyphDef /><altGlyphItem /><animateColor /><animateMotion /><animateTransform /><clipPath /><feBlend /><feColorMatrix /><feComponentTransfer /><feComposite /><feConvolveMatrix /><feDiffuseLighting /><feDisplacementMap /><feDistantLight /><feFlood /><feFuncA /><feFuncB /><feFuncG /><feFuncR /><feGaussianBlur /><feImage /><feMerge /><feMergeNode /><feMorphology /><feOffset /><fePointLight /><feSpecularLighting /><feSpotLight /><feTile /><feTurbulence /><foreignObject /><glyphRef /><linearGradient /><radialGradient /><textPath /></math>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math altglyph>
+| <math altglyphdef>
+| <math altglyphitem>
+| <math animatecolor>
+| <math animatemotion>
+| <math animatetransform>
+| <math clippath>
+| <math feblend>
+| <math fecolormatrix>
+| <math fecomponenttransfer>
+| <math fecomposite>
+| <math feconvolvematrix>
+| <math fediffuselighting>
+| <math fedisplacementmap>
+| <math fedistantlight>
+| <math feflood>
+| <math fefunca>
+| <math fefuncb>
+| <math fefuncg>
+| <math fefuncr>
+| <math fegaussianblur>
+| <math feimage>
+| <math femerge>
+| <math femergenode>
+| <math femorphology>
+| <math feoffset>
+| <math fepointlight>
+| <math fespecularlighting>
+| <math fespotlight>
+| <math fetile>
+| <math feturbulence>
+| <math foreignobject>
+| <math glyphref>
+| <math lineargradient>
+| <math radialgradient>
+| <math textpath>
+
+#data
+<!DOCTYPE html><body><svg><solidColor /></svg>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg solidcolor>
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests12.dat b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests12.dat
new file mode 100644
index 00000000000..63107d277b6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests12.dat
@@ -0,0 +1,62 @@
+#data
+<!DOCTYPE html><body><p>foo<math><mtext><i>baz</i></mtext><annotation-xml><svg><desc><b>eggs</b></desc><g><foreignObject><P>spam<TABLE><tr><td><img></td></table></foreignObject></g><g>quux</g></svg></annotation-xml></math>bar
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| "foo"
+| <math math>
+| <math mtext>
+| <i>
+| "baz"
+| <math annotation-xml>
+| <svg svg>
+| <svg desc>
+| <b>
+| "eggs"
+| <svg g>
+| <svg foreignObject>
+| <p>
+| "spam"
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <img>
+| <svg g>
+| "quux"
+| "bar"
+
+#data
+<!DOCTYPE html><body>foo<math><mtext><i>baz</i></mtext><annotation-xml><svg><desc><b>eggs</b></desc><g><foreignObject><P>spam<TABLE><tr><td><img></td></table></foreignObject></g><g>quux</g></svg></annotation-xml></math>bar
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "foo"
+| <math math>
+| <math mtext>
+| <i>
+| "baz"
+| <math annotation-xml>
+| <svg svg>
+| <svg desc>
+| <b>
+| "eggs"
+| <svg g>
+| <svg foreignObject>
+| <p>
+| "spam"
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <img>
+| <svg g>
+| "quux"
+| "bar"
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests14.dat b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests14.dat
new file mode 100644
index 00000000000..a08b7649eba
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests14.dat
@@ -0,0 +1,75 @@
+#data
+<!DOCTYPE html><html><body><xyz:abc></xyz:abc>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <xyz:abc>
+
+#data
+<!DOCTYPE html><html><body><xyz:abc></xyz:abc><span></span>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <xyz:abc>
+| <span>
+
+#data
+<!DOCTYPE html><html><html abc:def=gh><xyz:abc></xyz:abc>
+#errors
+(1,38): non-html-root
+#document
+| <!DOCTYPE html>
+| <html>
+| abc:def="gh"
+| <head>
+| <body>
+| <xyz:abc>
+
+#data
+<!DOCTYPE html><html xml:lang=bar><html xml:lang=foo>
+#errors
+(1,53): non-html-root
+#document
+| <!DOCTYPE html>
+| <html>
+| xml:lang="bar"
+| <head>
+| <body>
+
+#data
+<!DOCTYPE html><html 123=456>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| 123="456"
+| <head>
+| <body>
+
+#data
+<!DOCTYPE html><html 123=456><html 789=012>
+#errors
+(1,43): non-html-root
+#document
+| <!DOCTYPE html>
+| <html>
+| 123="456"
+| 789="012"
+| <head>
+| <body>
+
+#data
+<!DOCTYPE html><html><body 789=012>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| 789="012"
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests15.dat b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests15.dat
new file mode 100644
index 00000000000..93d06a87170
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests15.dat
@@ -0,0 +1,216 @@
+#data
+<!DOCTYPE html><p><b><i><u></p> <p>X
+#errors
+(1,31): unexpected-end-tag
+(1,36): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <b>
+| <i>
+| <u>
+| <b>
+| <i>
+| <u>
+| " "
+| <p>
+| "X"
+
+#data
+<p><b><i><u></p>
+<p>X
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,16): unexpected-end-tag
+(2,4): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| <b>
+| <i>
+| <u>
+| <b>
+| <i>
+| <u>
+| "
+"
+| <p>
+| "X"
+
+#data
+<!doctype html></html> <head>
+#errors
+(1,29): expected-eof-but-got-start-tag
+(1,29): unexpected-start-tag-ignored
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| " "
+
+#data
+<!doctype html></body><meta>
+#errors
+(1,28): unexpected-start-tag-after-body
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <meta>
+
+#data
+<html></html><!-- foo -->
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <!-- foo -->
+
+#data
+<!doctype html></body><title>X</title>
+#errors
+(1,29): unexpected-start-tag-after-body
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <title>
+| "X"
+
+#data
+<!doctype html><table> X<meta></table>
+#errors
+(1,23): foster-parenting-character
+(1,24): foster-parenting-character
+(1,30): foster-parenting-start-character
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| " X"
+| <meta>
+| <table>
+
+#data
+<!doctype html><table> x</table>
+#errors
+(1,23): foster-parenting-character
+(1,24): foster-parenting-character
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| " x"
+| <table>
+
+#data
+<!doctype html><table> x </table>
+#errors
+(1,23): foster-parenting-character
+(1,24): foster-parenting-character
+(1,25): foster-parenting-character
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| " x "
+| <table>
+
+#data
+<!doctype html><table><tr> x</table>
+#errors
+(1,27): foster-parenting-character
+(1,28): foster-parenting-character
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| " x"
+| <table>
+| <tbody>
+| <tr>
+
+#data
+<!doctype html><table>X<style> <tr>x </style> </table>
+#errors
+(1,23): foster-parenting-character
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "X"
+| <table>
+| <style>
+| " <tr>x "
+| " "
+
+#data
+<!doctype html><div><table><a>foo</a> <tr><td>bar</td> </tr></table></div>
+#errors
+(1,30): foster-parenting-start-tag
+(1,31): foster-parenting-character
+(1,32): foster-parenting-character
+(1,33): foster-parenting-character
+(1,37): foster-parenting-end-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <div>
+| <a>
+| "foo"
+| <table>
+| " "
+| <tbody>
+| <tr>
+| <td>
+| "bar"
+| " "
+
+#data
+<frame></frame></frame><frameset><frame><frameset><frame></frameset><noframes></frameset><noframes>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,7): unexpected-start-tag-ignored
+(1,15): unexpected-end-tag
+(1,23): unexpected-end-tag
+(1,33): unexpected-start-tag
+(1,99): expected-named-closing-tag-but-got-eof
+(1,99): eof-in-frameset
+#document
+| <html>
+| <head>
+| <frameset>
+| <frame>
+| <frameset>
+| <frame>
+| <noframes>
+| "</frameset><noframes>"
+
+#data
+<!DOCTYPE html><object></html>
+#errors
+(1,30): expected-body-in-scope
+(1,30): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <object>
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests16.dat b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests16.dat
new file mode 100644
index 00000000000..12191577761
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests16.dat
@@ -0,0 +1,2458 @@
+#data
+<!doctype html><script>
+#errors
+(1,23): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| <body>
+
+#data
+<!doctype html><script>a
+#errors
+(1,24): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "a"
+| <body>
+
+#data
+<!doctype html><script><
+#errors
+(1,24): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<"
+| <body>
+
+#data
+<!doctype html><script></
+#errors
+(1,25): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "</"
+| <body>
+
+#data
+<!doctype html><script></S
+#errors
+(1,26): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "</S"
+| <body>
+
+#data
+<!doctype html><script></SC
+#errors
+(1,27): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "</SC"
+| <body>
+
+#data
+<!doctype html><script></SCR
+#errors
+(1,28): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "</SCR"
+| <body>
+
+#data
+<!doctype html><script></SCRI
+#errors
+(1,29): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "</SCRI"
+| <body>
+
+#data
+<!doctype html><script></SCRIP
+#errors
+(1,30): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "</SCRIP"
+| <body>
+
+#data
+<!doctype html><script></SCRIPT
+#errors
+(1,31): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "</SCRIPT"
+| <body>
+
+#data
+<!doctype html><script></SCRIPT
+#errors
+(1,32): expected-attribute-name-but-got-eof
+(1,32): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| <body>
+
+#data
+<!doctype html><script></s
+#errors
+(1,26): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "</s"
+| <body>
+
+#data
+<!doctype html><script></sc
+#errors
+(1,27): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "</sc"
+| <body>
+
+#data
+<!doctype html><script></scr
+#errors
+(1,28): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "</scr"
+| <body>
+
+#data
+<!doctype html><script></scri
+#errors
+(1,29): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "</scri"
+| <body>
+
+#data
+<!doctype html><script></scrip
+#errors
+(1,30): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "</scrip"
+| <body>
+
+#data
+<!doctype html><script></script
+#errors
+(1,31): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "</script"
+| <body>
+
+#data
+<!doctype html><script></script
+#errors
+(1,32): expected-attribute-name-but-got-eof
+(1,32): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| <body>
+
+#data
+<!doctype html><script><!
+#errors
+(1,25): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!"
+| <body>
+
+#data
+<!doctype html><script><!a
+#errors
+(1,26): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!a"
+| <body>
+
+#data
+<!doctype html><script><!-
+#errors
+(1,26): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!-"
+| <body>
+
+#data
+<!doctype html><script><!-a
+#errors
+(1,27): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!-a"
+| <body>
+
+#data
+<!doctype html><script><!--
+#errors
+(1,27): expected-named-closing-tag-but-got-eof
+(1,27): unexpected-eof-in-text-mode
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--"
+| <body>
+
+#data
+<!doctype html><script><!--a
+#errors
+(1,28): expected-named-closing-tag-but-got-eof
+(1,28): unexpected-eof-in-text-mode
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--a"
+| <body>
+
+#data
+<!doctype html><script><!--<
+#errors
+(1,28): expected-named-closing-tag-but-got-eof
+(1,28): unexpected-eof-in-text-mode
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<"
+| <body>
+
+#data
+<!doctype html><script><!--<a
+#errors
+(1,29): expected-named-closing-tag-but-got-eof
+(1,29): unexpected-eof-in-text-mode
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<a"
+| <body>
+
+#data
+<!doctype html><script><!--</
+#errors
+(1,29): expected-named-closing-tag-but-got-eof
+(1,29): unexpected-eof-in-text-mode
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--</"
+| <body>
+
+#data
+<!doctype html><script><!--</script
+#errors
+(1,35): expected-named-closing-tag-but-got-eof
+(1,35): unexpected-eof-in-text-mode
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--</script"
+| <body>
+
+#data
+<!doctype html><script><!--</script
+#errors
+(1,36): expected-attribute-name-but-got-eof
+(1,36): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--"
+| <body>
+
+#data
+<!doctype html><script><!--<s
+#errors
+(1,29): expected-named-closing-tag-but-got-eof
+(1,29): unexpected-eof-in-text-mode
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<s"
+| <body>
+
+#data
+<!doctype html><script><!--<script
+#errors
+(1,34): expected-named-closing-tag-but-got-eof
+(1,34): unexpected-eof-in-text-mode
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script"
+| <body>
+
+#data
+<!doctype html><script><!--<script
+#errors
+(1,35): eof-in-script-in-script
+(1,35): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script "
+| <body>
+
+#data
+<!doctype html><script><!--<script <
+#errors
+(1,36): eof-in-script-in-script
+(1,36): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script <"
+| <body>
+
+#data
+<!doctype html><script><!--<script <a
+#errors
+(1,37): eof-in-script-in-script
+(1,37): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script <a"
+| <body>
+
+#data
+<!doctype html><script><!--<script </
+#errors
+(1,37): eof-in-script-in-script
+(1,37): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script </"
+| <body>
+
+#data
+<!doctype html><script><!--<script </s
+#errors
+(1,38): eof-in-script-in-script
+(1,38): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script </s"
+| <body>
+
+#data
+<!doctype html><script><!--<script </script
+#errors
+(1,43): eof-in-script-in-script
+(1,43): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script </script"
+| <body>
+
+#data
+<!doctype html><script><!--<script </scripta
+#errors
+(1,44): eof-in-script-in-script
+(1,44): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script </scripta"
+| <body>
+
+#data
+<!doctype html><script><!--<script </script
+#errors
+(1,44): expected-named-closing-tag-but-got-eof
+(1,44): unexpected-eof-in-text-mode
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script </script "
+| <body>
+
+#data
+<!doctype html><script><!--<script </script>
+#errors
+(1,44): expected-named-closing-tag-but-got-eof
+(1,44): unexpected-eof-in-text-mode
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script </script>"
+| <body>
+
+#data
+<!doctype html><script><!--<script </script/
+#errors
+(1,44): expected-named-closing-tag-but-got-eof
+(1,44): unexpected-eof-in-text-mode
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script </script/"
+| <body>
+
+#data
+<!doctype html><script><!--<script </script <
+#errors
+(1,45): expected-named-closing-tag-but-got-eof
+(1,45): unexpected-eof-in-text-mode
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script </script <"
+| <body>
+
+#data
+<!doctype html><script><!--<script </script <a
+#errors
+(1,46): expected-named-closing-tag-but-got-eof
+(1,46): unexpected-eof-in-text-mode
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script </script <a"
+| <body>
+
+#data
+<!doctype html><script><!--<script </script </
+#errors
+(1,46): expected-named-closing-tag-but-got-eof
+(1,46): unexpected-eof-in-text-mode
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script </script </"
+| <body>
+
+#data
+<!doctype html><script><!--<script </script </script
+#errors
+(1,52): expected-named-closing-tag-but-got-eof
+(1,52): unexpected-eof-in-text-mode
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script </script </script"
+| <body>
+
+#data
+<!doctype html><script><!--<script </script </script
+#errors
+(1,53): expected-attribute-name-but-got-eof
+(1,53): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script </script "
+| <body>
+
+#data
+<!doctype html><script><!--<script </script </script/
+#errors
+(1,53): unexpected-EOF-after-solidus-in-tag
+(1,53): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script </script "
+| <body>
+
+#data
+<!doctype html><script><!--<script </script </script>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script </script "
+| <body>
+
+#data
+<!doctype html><script><!--<script -
+#errors
+(1,36): eof-in-script-in-script
+(1,36): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script -"
+| <body>
+
+#data
+<!doctype html><script><!--<script -a
+#errors
+(1,37): eof-in-script-in-script
+(1,37): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script -a"
+| <body>
+
+#data
+<!doctype html><script><!--<script -<
+#errors
+(1,37): eof-in-script-in-script
+(1,37): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script -<"
+| <body>
+
+#data
+<!doctype html><script><!--<script --
+#errors
+(1,37): eof-in-script-in-script
+(1,37): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script --"
+| <body>
+
+#data
+<!doctype html><script><!--<script --a
+#errors
+(1,38): eof-in-script-in-script
+(1,38): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script --a"
+| <body>
+
+#data
+<!doctype html><script><!--<script --<
+#errors
+(1,38): eof-in-script-in-script
+(1,38): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script --<"
+| <body>
+
+#data
+<!doctype html><script><!--<script -->
+#errors
+(1,38): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script -->"
+| <body>
+
+#data
+<!doctype html><script><!--<script --><
+#errors
+(1,39): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script --><"
+| <body>
+
+#data
+<!doctype html><script><!--<script --></
+#errors
+(1,40): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script --></"
+| <body>
+
+#data
+<!doctype html><script><!--<script --></script
+#errors
+(1,46): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script --></script"
+| <body>
+
+#data
+<!doctype html><script><!--<script --></script
+#errors
+(1,47): expected-attribute-name-but-got-eof
+(1,47): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script -->"
+| <body>
+
+#data
+<!doctype html><script><!--<script --></script/
+#errors
+(1,47): unexpected-EOF-after-solidus-in-tag
+(1,47): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script -->"
+| <body>
+
+#data
+<!doctype html><script><!--<script --></script>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script -->"
+| <body>
+
+#data
+<!doctype html><script><!--<script><\/script>--></script>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script><\/script>-->"
+| <body>
+
+#data
+<!doctype html><script><!--<script></scr'+'ipt>--></script>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script></scr'+'ipt>-->"
+| <body>
+
+#data
+<!doctype html><script><!--<script></script><script></script></script>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script></script><script></script>"
+| <body>
+
+#data
+<!doctype html><script><!--<script></script><script></script>--><!--</script>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script></script><script></script>--><!--"
+| <body>
+
+#data
+<!doctype html><script><!--<script></script><script></script>-- ></script>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script></script><script></script>-- >"
+| <body>
+
+#data
+<!doctype html><script><!--<script></script><script></script>- -></script>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script></script><script></script>- ->"
+| <body>
+
+#data
+<!doctype html><script><!--<script></script><script></script>- - ></script>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script></script><script></script>- - >"
+| <body>
+
+#data
+<!doctype html><script><!--<script></script><script></script>-></script>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script></script><script></script>->"
+| <body>
+
+#data
+<!doctype html><script><!--<script>--!></script>X
+#errors
+(1,49): expected-named-closing-tag-but-got-eof
+(1,49): unexpected-EOF-in-text-mode
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script>--!></script>X"
+| <body>
+
+#data
+<!doctype html><script><!--<scr'+'ipt></script>--></script>
+#errors
+(1,59): unexpected-end-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<scr'+'ipt>"
+| <body>
+| "-->"
+
+#data
+<!doctype html><script><!--<script></scr'+'ipt></script>X
+#errors
+(1,57): expected-named-closing-tag-but-got-eof
+(1,57): unexpected-eof-in-text-mode
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "<!--<script></scr'+'ipt></script>X"
+| <body>
+
+#data
+<!doctype html><style><!--<style></style>--></style>
+#errors
+(1,52): unexpected-end-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <style>
+| "<!--<style>"
+| <body>
+| "-->"
+
+#data
+<!doctype html><style><!--</style>X
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <style>
+| "<!--"
+| <body>
+| "X"
+
+#data
+<!doctype html><style><!--...</style>...--></style>
+#errors
+(1,51): unexpected-end-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <style>
+| "<!--..."
+| <body>
+| "...-->"
+
+#data
+<!doctype html><style><!--<br><html xmlns:v="urn:schemas-microsoft-com:vml"><!--[if !mso]><style></style>X
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <style>
+| "<!--<br><html xmlns:v="urn:schemas-microsoft-com:vml"><!--[if !mso]><style>"
+| <body>
+| "X"
+
+#data
+<!doctype html><style><!--...<style><!--...--!></style>--></style>
+#errors
+(1,66): unexpected-end-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <style>
+| "<!--...<style><!--...--!>"
+| <body>
+| "-->"
+
+#data
+<!doctype html><style><!--...</style><!-- --><style>@import ...</style>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <style>
+| "<!--..."
+| <!-- -->
+| <style>
+| "@import ..."
+| <body>
+
+#data
+<!doctype html><style>...<style><!--...</style><!-- --></style>
+#errors
+(1,63): unexpected-end-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <style>
+| "...<style><!--..."
+| <!-- -->
+| <body>
+
+#data
+<!doctype html><style>...<!--[if IE]><style>...</style>X
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <style>
+| "...<!--[if IE]><style>..."
+| <body>
+| "X"
+
+#data
+<!doctype html><title><!--<title></title>--></title>
+#errors
+(1,52): unexpected-end-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <title>
+| "<!--<title>"
+| <body>
+| "-->"
+
+#data
+<!doctype html><title>&lt;/title></title>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <title>
+| "</title>"
+| <body>
+
+#data
+<!doctype html><title>foo/title><link></head><body>X
+#errors
+(1,52): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <title>
+| "foo/title><link></head><body>X"
+| <body>
+
+#data
+<!doctype html><noscript><!--<noscript></noscript>--></noscript>
+#errors
+(1,64): unexpected-end-tag
+#script-on
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <noscript>
+| "<!--<noscript>"
+| <body>
+| "-->"
+
+#data
+<!doctype html><noscript><!--<noscript></noscript>--></noscript>
+#errors
+#script-off
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <noscript>
+| <!-- <noscript></noscript> -->
+| <body>
+
+#data
+<!doctype html><noscript><!--</noscript>X<noscript>--></noscript>
+#errors
+#script-on
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <noscript>
+| "<!--"
+| <body>
+| "X"
+| <noscript>
+| "-->"
+
+#data
+<!doctype html><noscript><!--</noscript>X<noscript>--></noscript>
+#errors
+#script-off
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <noscript>
+| <!-- </noscript>X<noscript> -->
+| <body>
+
+#data
+<!doctype html><noscript><iframe></noscript>X
+#errors
+#script-on
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <noscript>
+| "<iframe>"
+| <body>
+| "X"
+
+#data
+<!doctype html><noscript><iframe></noscript>X
+#errors
+ * (1,34) unexpected token in head noscript
+ * (1,46) unexpected EOF
+#script-off
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <noscript>
+| <body>
+| <iframe>
+| "</noscript>X"
+
+#data
+<!doctype html><noframes><!--<noframes></noframes>--></noframes>
+#errors
+(1,64): unexpected-end-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <noframes>
+| "<!--<noframes>"
+| <body>
+| "-->"
+
+#data
+<!doctype html><noframes><body><script><!--...</script></body></noframes></html>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <noframes>
+| "<body><script><!--...</script></body>"
+| <body>
+
+#data
+<!doctype html><textarea><!--<textarea></textarea>--></textarea>
+#errors
+(1,64): unexpected-end-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <textarea>
+| "<!--<textarea>"
+| "-->"
+
+#data
+<!doctype html><textarea>&lt;/textarea></textarea>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <textarea>
+| "</textarea>"
+
+#data
+<!doctype html><textarea>&lt;</textarea>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <textarea>
+| "<"
+
+#data
+<!doctype html><textarea>a&lt;b</textarea>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <textarea>
+| "a<b"
+
+#data
+<!doctype html><iframe><!--<iframe></iframe>--></iframe>
+#errors
+(1,56): unexpected-end-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <iframe>
+| "<!--<iframe>"
+| "-->"
+
+#data
+<!doctype html><iframe>...<!--X->...<!--/X->...</iframe>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <iframe>
+| "...<!--X->...<!--/X->..."
+
+#data
+<!doctype html><xmp><!--<xmp></xmp>--></xmp>
+#errors
+(1,44): unexpected-end-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <xmp>
+| "<!--<xmp>"
+| "-->"
+
+#data
+<!doctype html><noembed><!--<noembed></noembed>--></noembed>
+#errors
+(1,60): unexpected-end-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <noembed>
+| "<!--<noembed>"
+| "-->"
+
+#data
+<script>
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,8): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| <body>
+
+#data
+<script>a
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,9): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "a"
+| <body>
+
+#data
+<script><
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,9): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "<"
+| <body>
+
+#data
+<script></
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,10): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "</"
+| <body>
+
+#data
+<script></S
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,11): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "</S"
+| <body>
+
+#data
+<script></SC
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,12): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "</SC"
+| <body>
+
+#data
+<script></SCR
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,13): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "</SCR"
+| <body>
+
+#data
+<script></SCRI
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,14): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "</SCRI"
+| <body>
+
+#data
+<script></SCRIP
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,15): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "</SCRIP"
+| <body>
+
+#data
+<script></SCRIPT
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,16): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "</SCRIPT"
+| <body>
+
+#data
+<script></SCRIPT
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,17): expected-attribute-name-but-got-eof
+(1,17): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| <body>
+
+#data
+<script></s
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,11): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "</s"
+| <body>
+
+#data
+<script></sc
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,12): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "</sc"
+| <body>
+
+#data
+<script></scr
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,13): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "</scr"
+| <body>
+
+#data
+<script></scri
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,14): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "</scri"
+| <body>
+
+#data
+<script></scrip
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,15): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "</scrip"
+| <body>
+
+#data
+<script></script
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,16): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "</script"
+| <body>
+
+#data
+<script></script
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,17): expected-attribute-name-but-got-eof
+(1,17): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| <body>
+
+#data
+<script><!
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,10): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "<!"
+| <body>
+
+#data
+<script><!a
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,11): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "<!a"
+| <body>
+
+#data
+<script><!-
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,11): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "<!-"
+| <body>
+
+#data
+<script><!-a
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,12): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "<!-a"
+| <body>
+
+#data
+<script><!--
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,12): expected-named-closing-tag-but-got-eof
+(1,12): unexpected-eof-in-text-mode
+#document
+| <html>
+| <head>
+| <script>
+| "<!--"
+| <body>
+
+#data
+<script><!--a
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,13): expected-named-closing-tag-but-got-eof
+(1,13): unexpected-eof-in-text-mode
+#document
+| <html>
+| <head>
+| <script>
+| "<!--a"
+| <body>
+
+#data
+<script><!--<
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,13): expected-named-closing-tag-but-got-eof
+(1,13): unexpected-eof-in-text-mode
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<"
+| <body>
+
+#data
+<script><!--<a
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,14): expected-named-closing-tag-but-got-eof
+(1,14): unexpected-eof-in-text-mode
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<a"
+| <body>
+
+#data
+<script><!--</
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,14): expected-named-closing-tag-but-got-eof
+(1,14): unexpected-eof-in-text-mode
+#document
+| <html>
+| <head>
+| <script>
+| "<!--</"
+| <body>
+
+#data
+<script><!--</script
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,20): expected-named-closing-tag-but-got-eof
+(1,20): unexpected-eof-in-text-mode
+#document
+| <html>
+| <head>
+| <script>
+| "<!--</script"
+| <body>
+
+#data
+<script><!--</script
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,21): expected-attribute-name-but-got-eof
+(1,21): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "<!--"
+| <body>
+
+#data
+<script><!--<s
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,14): expected-named-closing-tag-but-got-eof
+(1,14): unexpected-eof-in-text-mode
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<s"
+| <body>
+
+#data
+<script><!--<script
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,19): expected-named-closing-tag-but-got-eof
+(1,19): unexpected-eof-in-text-mode
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script"
+| <body>
+
+#data
+<script><!--<script
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,20): eof-in-script-in-script
+(1,20): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script "
+| <body>
+
+#data
+<script><!--<script <
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,21): eof-in-script-in-script
+(1,21): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script <"
+| <body>
+
+#data
+<script><!--<script <a
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,22): eof-in-script-in-script
+(1,22): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script <a"
+| <body>
+
+#data
+<script><!--<script </
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,22): eof-in-script-in-script
+(1,22): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script </"
+| <body>
+
+#data
+<script><!--<script </s
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,23): eof-in-script-in-script
+(1,23): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script </s"
+| <body>
+
+#data
+<script><!--<script </script
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,28): eof-in-script-in-script
+(1,28): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script </script"
+| <body>
+
+#data
+<script><!--<script </scripta
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,29): eof-in-script-in-script
+(1,29): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script </scripta"
+| <body>
+
+#data
+<script><!--<script </script
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,29): expected-named-closing-tag-but-got-eof
+(1,29): unexpected-eof-in-text-mode
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script </script "
+| <body>
+
+#data
+<script><!--<script </script>
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,29): expected-named-closing-tag-but-got-eof
+(1,29): unexpected-eof-in-text-mode
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script </script>"
+| <body>
+
+#data
+<script><!--<script </script/
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,29): expected-named-closing-tag-but-got-eof
+(1,29): unexpected-eof-in-text-mode
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script </script/"
+| <body>
+
+#data
+<script><!--<script </script <
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,30): expected-named-closing-tag-but-got-eof
+(1,30): unexpected-eof-in-text-mode
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script </script <"
+| <body>
+
+#data
+<script><!--<script </script <a
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,31): expected-named-closing-tag-but-got-eof
+(1,31): unexpected-eof-in-text-mode
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script </script <a"
+| <body>
+
+#data
+<script><!--<script </script </
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,31): expected-named-closing-tag-but-got-eof
+(1,31): unexpected-eof-in-text-mode
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script </script </"
+| <body>
+
+#data
+<script><!--<script </script </script
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,37): expected-named-closing-tag-but-got-eof
+(1,37): unexpected-eof-in-text-mode
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script </script </script"
+| <body>
+
+#data
+<script><!--<script </script </script
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,38): expected-attribute-name-but-got-eof
+(1,38): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script </script "
+| <body>
+
+#data
+<script><!--<script </script </script/
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,38): unexpected-EOF-after-solidus-in-tag
+(1,38): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script </script "
+| <body>
+
+#data
+<script><!--<script </script </script>
+#errors
+(1,8): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script </script "
+| <body>
+
+#data
+<script><!--<script -
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,21): eof-in-script-in-script
+(1,21): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script -"
+| <body>
+
+#data
+<script><!--<script -a
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,22): eof-in-script-in-script
+(1,22): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script -a"
+| <body>
+
+#data
+<script><!--<script --
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,22): eof-in-script-in-script
+(1,22): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script --"
+| <body>
+
+#data
+<script><!--<script --a
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,23): eof-in-script-in-script
+(1,23): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script --a"
+| <body>
+
+#data
+<script><!--<script -->
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,23): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script -->"
+| <body>
+
+#data
+<script><!--<script --><
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,24): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script --><"
+| <body>
+
+#data
+<script><!--<script --></
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,25): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script --></"
+| <body>
+
+#data
+<script><!--<script --></script
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,31): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script --></script"
+| <body>
+
+#data
+<script><!--<script --></script
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,32): expected-attribute-name-but-got-eof
+(1,32): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script -->"
+| <body>
+
+#data
+<script><!--<script --></script/
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,32): unexpected-EOF-after-solidus-in-tag
+(1,32): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script -->"
+| <body>
+
+#data
+<script><!--<script --></script>
+#errors
+(1,8): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script -->"
+| <body>
+
+#data
+<script><!--<script><\/script>--></script>
+#errors
+(1,8): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script><\/script>-->"
+| <body>
+
+#data
+<script><!--<script></scr'+'ipt>--></script>
+#errors
+(1,8): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script></scr'+'ipt>-->"
+| <body>
+
+#data
+<script><!--<script></script><script></script></script>
+#errors
+(1,8): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script></script><script></script>"
+| <body>
+
+#data
+<script><!--<script></script><script></script>--><!--</script>
+#errors
+(1,8): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script></script><script></script>--><!--"
+| <body>
+
+#data
+<script><!--<script></script><script></script>-- ></script>
+#errors
+(1,8): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script></script><script></script>-- >"
+| <body>
+
+#data
+<script><!--<script></script><script></script>- -></script>
+#errors
+(1,8): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script></script><script></script>- ->"
+| <body>
+
+#data
+<script><!--<script></script><script></script>- - ></script>
+#errors
+(1,8): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script></script><script></script>- - >"
+| <body>
+
+#data
+<script><!--<script></script><script></script>-></script>
+#errors
+(1,8): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script></script><script></script>->"
+| <body>
+
+#data
+<script><!--<script>--!></script>X
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,34): expected-named-closing-tag-but-got-eof
+(1,34): unexpected-eof-in-text-mode
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script>--!></script>X"
+| <body>
+
+#data
+<script><!--<scr'+'ipt></script>--></script>
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,44): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<scr'+'ipt>"
+| <body>
+| "-->"
+
+#data
+<script><!--<script></scr'+'ipt></script>X
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,42): expected-named-closing-tag-but-got-eof
+(1,42): unexpected-eof-in-text-mode
+#document
+| <html>
+| <head>
+| <script>
+| "<!--<script></scr'+'ipt></script>X"
+| <body>
+
+#data
+<style><!--<style></style>--></style>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,37): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <style>
+| "<!--<style>"
+| <body>
+| "-->"
+
+#data
+<style><!--</style>X
+#errors
+(1,7): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <style>
+| "<!--"
+| <body>
+| "X"
+
+#data
+<style><!--...</style>...--></style>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,36): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <style>
+| "<!--..."
+| <body>
+| "...-->"
+
+#data
+<style><!--<br><html xmlns:v="urn:schemas-microsoft-com:vml"><!--[if !mso]><style></style>X
+#errors
+(1,7): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <style>
+| "<!--<br><html xmlns:v="urn:schemas-microsoft-com:vml"><!--[if !mso]><style>"
+| <body>
+| "X"
+
+#data
+<style><!--...<style><!--...--!></style>--></style>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,51): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <style>
+| "<!--...<style><!--...--!>"
+| <body>
+| "-->"
+
+#data
+<style><!--...</style><!-- --><style>@import ...</style>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <style>
+| "<!--..."
+| <!-- -->
+| <style>
+| "@import ..."
+| <body>
+
+#data
+<style>...<style><!--...</style><!-- --></style>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,48): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <style>
+| "...<style><!--..."
+| <!-- -->
+| <body>
+
+#data
+<style>...<!--[if IE]><style>...</style>X
+#errors
+(1,7): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <style>
+| "...<!--[if IE]><style>..."
+| <body>
+| "X"
+
+#data
+<title><!--<title></title>--></title>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,37): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <title>
+| "<!--<title>"
+| <body>
+| "-->"
+
+#data
+<title>&lt;/title></title>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <title>
+| "</title>"
+| <body>
+
+#data
+<title>foo/title><link></head><body>X
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,37): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <title>
+| "foo/title><link></head><body>X"
+| <body>
+
+#data
+<noscript><!--<noscript></noscript>--></noscript>
+#errors
+(1,10): expected-doctype-but-got-start-tag
+(1,49): unexpected-end-tag
+#script-on
+#document
+| <html>
+| <head>
+| <noscript>
+| "<!--<noscript>"
+| <body>
+| "-->"
+
+#data
+<noscript><!--<noscript></noscript>--></noscript>
+#errors
+ * (1,11) missing DOCTYPE
+#script-off
+#document
+| <html>
+| <head>
+| <noscript>
+| <!-- <noscript></noscript> -->
+| <body>
+
+#data
+<noscript><!--</noscript>X<noscript>--></noscript>
+#errors
+(1,10): expected-doctype-but-got-start-tag
+#script-on
+#document
+| <html>
+| <head>
+| <noscript>
+| "<!--"
+| <body>
+| "X"
+| <noscript>
+| "-->"
+
+#data
+<noscript><!--</noscript>X<noscript>--></noscript>
+#errors
+(1,10): expected-doctype-but-got-start-tag
+#script-off
+#document
+| <html>
+| <head>
+| <noscript>
+| <!-- </noscript>X<noscript> -->
+| <body>
+
+#data
+<noscript><iframe></noscript>X
+#errors
+(1,10): expected-doctype-but-got-start-tag
+#script-on
+#document
+| <html>
+| <head>
+| <noscript>
+| "<iframe>"
+| <body>
+| "X"
+
+#data
+<noscript><iframe></noscript>X
+#errors
+ * (1,11) missing DOCTYPE
+ * (1,19) unexpected token in head noscript
+ * (1,31) unexpected EOF
+#script-off
+#document
+| <html>
+| <head>
+| <noscript>
+| <body>
+| <iframe>
+| "</noscript>X"
+
+#data
+<noframes><!--<noframes></noframes>--></noframes>
+#errors
+(1,10): expected-doctype-but-got-start-tag
+(1,49): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <noframes>
+| "<!--<noframes>"
+| <body>
+| "-->"
+
+#data
+<noframes><body><script><!--...</script></body></noframes></html>
+#errors
+(1,10): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <noframes>
+| "<body><script><!--...</script></body>"
+| <body>
+
+#data
+<textarea><!--<textarea></textarea>--></textarea>
+#errors
+(1,10): expected-doctype-but-got-start-tag
+(1,49): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <body>
+| <textarea>
+| "<!--<textarea>"
+| "-->"
+
+#data
+<textarea>&lt;/textarea></textarea>
+#errors
+(1,10): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <textarea>
+| "</textarea>"
+
+#data
+<iframe><!--<iframe></iframe>--></iframe>
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,41): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <body>
+| <iframe>
+| "<!--<iframe>"
+| "-->"
+
+#data
+<iframe>...<!--X->...<!--/X->...</iframe>
+#errors
+(1,8): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <iframe>
+| "...<!--X->...<!--/X->..."
+
+#data
+<xmp><!--<xmp></xmp>--></xmp>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,29): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <body>
+| <xmp>
+| "<!--<xmp>"
+| "-->"
+
+#data
+<noembed><!--<noembed></noembed>--></noembed>
+#errors
+(1,9): expected-doctype-but-got-start-tag
+(1,45): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <body>
+| <noembed>
+| "<!--<noembed>"
+| "-->"
+
+#data
+<!doctype html><table>
+
+#errors
+(2,0): eof-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| "
+"
+
+#data
+<!doctype html><table><td><span><font></span><span>
+#errors
+(1,26): unexpected-cell-in-table-body
+(1,45): unexpected-end-tag
+(1,51): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <span>
+| <font>
+| <font>
+| <span>
+
+#data
+<!doctype html><form><table></form><form></table></form>
+#errors
+(1,35): unexpected-end-tag-implies-table-voodoo
+(1,35): unexpected-end-tag
+(1,41): unexpected-form-in-table
+(1,56): unexpected-end-tag
+(1,56): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <form>
+| <table>
+| <form>
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests17.dat b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests17.dat
new file mode 100644
index 00000000000..e49bcf03142
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests17.dat
@@ -0,0 +1,179 @@
+#data
+<!doctype html><table><tbody><select><tr>
+#errors
+(1,37): unexpected-start-tag-implies-table-voodoo
+(1,41): unexpected-table-element-start-tag-in-select-in-table
+(1,41): eof-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| <table>
+| <tbody>
+| <tr>
+
+#data
+<!doctype html><table><tr><select><td>
+#errors
+(1,34): unexpected-start-tag-implies-table-voodoo
+(1,38): unexpected-table-element-start-tag-in-select-in-table
+(1,38): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+
+#data
+<!doctype html><table><tr><td><select><td>
+#errors
+(1,42): unexpected-table-element-start-tag-in-select-in-table
+(1,42): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <select>
+| <td>
+
+#data
+<!doctype html><table><tr><th><select><td>
+#errors
+(1,42): unexpected-table-element-start-tag-in-select-in-table
+(1,42): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <th>
+| <select>
+| <td>
+
+#data
+<!doctype html><table><caption><select><tr>
+#errors
+(1,43): unexpected-table-element-start-tag-in-select-in-table
+(1,43): eof-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <caption>
+| <select>
+| <tbody>
+| <tr>
+
+#data
+<!doctype html><select><tr>
+#errors
+(1,27): unexpected-start-tag-in-select
+(1,27): eof-in-select
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+
+#data
+<!doctype html><select><td>
+#errors
+(1,27): unexpected-start-tag-in-select
+(1,27): eof-in-select
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+
+#data
+<!doctype html><select><th>
+#errors
+(1,27): unexpected-start-tag-in-select
+(1,27): eof-in-select
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+
+#data
+<!doctype html><select><tbody>
+#errors
+(1,30): unexpected-start-tag-in-select
+(1,30): eof-in-select
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+
+#data
+<!doctype html><select><thead>
+#errors
+(1,30): unexpected-start-tag-in-select
+(1,30): eof-in-select
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+
+#data
+<!doctype html><select><tfoot>
+#errors
+(1,30): unexpected-start-tag-in-select
+(1,30): eof-in-select
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+
+#data
+<!doctype html><select><caption>
+#errors
+(1,32): unexpected-start-tag-in-select
+(1,32): eof-in-select
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+
+#data
+<!doctype html><table><tr></table>a
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| "a"
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests18.dat b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests18.dat
new file mode 100644
index 00000000000..926bccb3875
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests18.dat
@@ -0,0 +1,322 @@
+#data
+<!doctype html><plaintext></plaintext>
+#errors
+(1,38): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <plaintext>
+| "</plaintext>"
+
+#data
+<!doctype html><table><plaintext></plaintext>
+#errors
+(1,33): foster-parenting-start-tag
+(1,34): foster-parenting-character
+(1,35): foster-parenting-character
+(1,36): foster-parenting-character
+(1,37): foster-parenting-character
+(1,38): foster-parenting-character
+(1,39): foster-parenting-character
+(1,40): foster-parenting-character
+(1,41): foster-parenting-character
+(1,42): foster-parenting-character
+(1,43): foster-parenting-character
+(1,44): foster-parenting-character
+(1,45): foster-parenting-character
+(1,45): eof-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <plaintext>
+| "</plaintext>"
+| <table>
+
+#data
+<!doctype html><table><tbody><plaintext></plaintext>
+#errors
+(1,40): foster-parenting-start-tag
+(1,41): foster-parenting-character
+(1,41): foster-parenting-character
+(1,41): foster-parenting-character
+(1,41): foster-parenting-character
+(1,41): foster-parenting-character
+(1,41): foster-parenting-character
+(1,41): foster-parenting-character
+(1,41): foster-parenting-character
+(1,41): foster-parenting-character
+(1,41): foster-parenting-character
+(1,41): foster-parenting-character
+(1,41): foster-parenting-character
+(1,52): eof-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <plaintext>
+| "</plaintext>"
+| <table>
+| <tbody>
+
+#data
+<!doctype html><table><tbody><tr><plaintext></plaintext>
+#errors
+(1,44): foster-parenting-start-tag
+(1,45): foster-parenting-character
+(1,46): foster-parenting-character
+(1,47): foster-parenting-character
+(1,48): foster-parenting-character
+(1,49): foster-parenting-character
+(1,50): foster-parenting-character
+(1,51): foster-parenting-character
+(1,52): foster-parenting-character
+(1,53): foster-parenting-character
+(1,54): foster-parenting-character
+(1,55): foster-parenting-character
+(1,56): foster-parenting-character
+(1,56): eof-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <plaintext>
+| "</plaintext>"
+| <table>
+| <tbody>
+| <tr>
+
+#data
+<!doctype html><table><td><plaintext></plaintext>
+#errors
+(1,26): unexpected-cell-in-table-body
+(1,49): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <plaintext>
+| "</plaintext>"
+
+#data
+<!doctype html><table><caption><plaintext></plaintext>
+#errors
+(1,54): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <caption>
+| <plaintext>
+| "</plaintext>"
+
+#data
+<!doctype html><table><tr><style></script></style>abc
+#errors
+(1,51): foster-parenting-character
+(1,52): foster-parenting-character
+(1,53): foster-parenting-character
+(1,53): eof-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "abc"
+| <table>
+| <tbody>
+| <tr>
+| <style>
+| "</script>"
+
+#data
+<!doctype html><table><tr><script></style></script>abc
+#errors
+(1,52): foster-parenting-character
+(1,53): foster-parenting-character
+(1,54): foster-parenting-character
+(1,54): eof-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "abc"
+| <table>
+| <tbody>
+| <tr>
+| <script>
+| "</style>"
+
+#data
+<!doctype html><table><caption><style></script></style>abc
+#errors
+(1,58): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <caption>
+| <style>
+| "</script>"
+| "abc"
+
+#data
+<!doctype html><table><td><style></script></style>abc
+#errors
+(1,26): unexpected-cell-in-table-body
+(1,53): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <style>
+| "</script>"
+| "abc"
+
+#data
+<!doctype html><select><script></style></script>abc
+#errors
+(1,51): eof-in-select
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| <script>
+| "</style>"
+| "abc"
+
+#data
+<!doctype html><table><select><script></style></script>abc
+#errors
+(1,30): unexpected-start-tag-implies-table-voodoo
+(1,58): eof-in-select
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| <script>
+| "</style>"
+| "abc"
+| <table>
+
+#data
+<!doctype html><table><tr><select><script></style></script>abc
+#errors
+(1,34): unexpected-start-tag-implies-table-voodoo
+(1,62): eof-in-select
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| <script>
+| "</style>"
+| "abc"
+| <table>
+| <tbody>
+| <tr>
+
+#data
+<!doctype html><frameset></frameset><noframes>abc
+#errors
+(1,49): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+| <noframes>
+| "abc"
+
+#data
+<!doctype html><frameset></frameset><noframes>abc</noframes><!--abc-->
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+| <noframes>
+| "abc"
+| <!-- abc -->
+
+#data
+<!doctype html><frameset></frameset></html><noframes>abc
+#errors
+(1,56): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+| <noframes>
+| "abc"
+
+#data
+<!doctype html><frameset></frameset></html><noframes>abc</noframes><!--abc-->
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+| <noframes>
+| "abc"
+| <!-- abc -->
+
+#data
+<!doctype html><table><tr></tbody><tfoot>
+#errors
+(1,41): eof-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <tfoot>
+
+#data
+<!doctype html><table><td><svg></svg>abc<td>
+#errors
+(1,26): unexpected-cell-in-table-body
+(1,44): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <svg svg>
+| "abc"
+| <td>
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests19.dat b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests19.dat
new file mode 100644
index 00000000000..02158c8bba8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests19.dat
@@ -0,0 +1,1524 @@
+#data
+<!doctype html><math><mn DefinitionUrl="foo">
+#errors
+(1,45): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mn>
+| definitionURL="foo"
+
+#data
+<!doctype html><html></p><!--foo-->
+#errors
+(1,25): end-tag-after-implied-root
+#document
+| <!DOCTYPE html>
+| <html>
+| <!-- foo -->
+| <head>
+| <body>
+
+#data
+<!doctype html><head></head></p><!--foo-->
+#errors
+(1,32): unexpected-end-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <!-- foo -->
+| <body>
+
+#data
+<!doctype html><body><p><pre>
+#errors
+(1,29): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <pre>
+
+#data
+<!doctype html><body><p><listing>
+#errors
+(1,33): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <listing>
+
+#data
+<!doctype html><p><plaintext>
+#errors
+(1,29): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <plaintext>
+
+#data
+<!doctype html><p><h1>
+#errors
+(1,22): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <h1>
+
+#data
+<!doctype html><form><isindex>
+#errors
+(1,30): deprecated-tag
+(1,30): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <form>
+
+#data
+<!doctype html><isindex action="POST">
+#errors
+(1,38): deprecated-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <form>
+| action="POST"
+| <hr>
+| <label>
+| "This is a searchable index. Enter search keywords: "
+| <input>
+| name="isindex"
+| <hr>
+
+#data
+<!doctype html><isindex prompt="this is isindex">
+#errors
+(1,49): deprecated-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <form>
+| <hr>
+| <label>
+| "this is isindex"
+| <input>
+| name="isindex"
+| <hr>
+
+#data
+<!doctype html><isindex type="hidden">
+#errors
+(1,38): deprecated-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <form>
+| <hr>
+| <label>
+| "This is a searchable index. Enter search keywords: "
+| <input>
+| name="isindex"
+| type="hidden"
+| <hr>
+
+#data
+<!doctype html><isindex name="foo">
+#errors
+(1,35): deprecated-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <form>
+| <hr>
+| <label>
+| "This is a searchable index. Enter search keywords: "
+| <input>
+| name="isindex"
+| <hr>
+
+#data
+<!doctype html><ruby><p><rp>
+#errors
+(1,28): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <ruby>
+| <p>
+| <rp>
+
+#data
+<!doctype html><ruby><div><span><rp>
+#errors
+(1,36): XXX-undefined-error
+(1,36): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <ruby>
+| <div>
+| <span>
+| <rp>
+
+#data
+<!doctype html><ruby><div><p><rp>
+#errors
+(1,33): XXX-undefined-error
+(1,33): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <ruby>
+| <div>
+| <p>
+| <rp>
+
+#data
+<!doctype html><ruby><p><rt>
+#errors
+(1,28): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <ruby>
+| <p>
+| <rt>
+
+#data
+<!doctype html><ruby><div><span><rt>
+#errors
+(1,36): XXX-undefined-error
+(1,36): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <ruby>
+| <div>
+| <span>
+| <rt>
+
+#data
+<!doctype html><ruby><div><p><rt>
+#errors
+(1,33): XXX-undefined-error
+(1,33): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <ruby>
+| <div>
+| <p>
+| <rt>
+
+#data
+<html><ruby>a<rb>b<rt></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <ruby>
+| "a"
+| <rb>
+| "b"
+| <rt>
+
+#data
+<html><ruby>a<rp>b<rt></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <ruby>
+| "a"
+| <rp>
+| "b"
+| <rt>
+
+#data
+<html><ruby>a<rt>b<rt></ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <ruby>
+| "a"
+| <rt>
+| "b"
+| <rt>
+
+#data
+<html><ruby>a<rtc>b<rt>c<rb>d</ruby></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <ruby>
+| "a"
+| <rtc>
+| "b"
+| <rt>
+| "c"
+| <rb>
+| "d"
+
+#data
+<!doctype html><math/><foo>
+#errors
+(1,27): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <math math>
+| <foo>
+
+#data
+<!doctype html><svg/><foo>
+#errors
+(1,26): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <foo>
+
+#data
+<!doctype html><div></body><!--foo-->
+#errors
+(1,27): expected-one-end-tag-but-got-another
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <div>
+| <!-- foo -->
+
+#data
+<!doctype html><h1><div><h3><span></h1>foo
+#errors
+(1,39): end-tag-too-early
+(1,42): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <h1>
+| <div>
+| <h3>
+| <span>
+| "foo"
+
+#data
+<!doctype html><p></h3>foo
+#errors
+(1,23): end-tag-too-early
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| "foo"
+
+#data
+<!doctype html><h3><li>abc</h2>foo
+#errors
+(1,31): end-tag-too-early
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <h3>
+| <li>
+| "abc"
+| "foo"
+
+#data
+<!doctype html><table>abc<!--foo-->
+#errors
+(1,23): foster-parenting-character
+(1,24): foster-parenting-character
+(1,25): foster-parenting-character
+(1,35): eof-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "abc"
+| <table>
+| <!-- foo -->
+
+#data
+<!doctype html><table> <!--foo-->
+#errors
+(1,34): eof-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| " "
+| <!-- foo -->
+
+#data
+<!doctype html><table> b <!--foo-->
+#errors
+(1,23): foster-parenting-character
+(1,24): foster-parenting-character
+(1,25): foster-parenting-character
+(1,35): eof-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| " b "
+| <table>
+| <!-- foo -->
+
+#data
+<!doctype html><select><option><option>
+#errors
+(1,39): eof-in-select
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| <option>
+| <option>
+
+#data
+<!doctype html><select><option></optgroup>
+#errors
+(1,42): unexpected-end-tag-in-select
+(1,42): eof-in-select
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| <option>
+
+#data
+<!doctype html><select><option></optgroup>
+#errors
+(1,42): unexpected-end-tag-in-select
+(1,42): eof-in-select
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| <option>
+
+#data
+<!doctype html><dd><optgroup><dd>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <dd>
+| <optgroup>
+| <dd>
+
+#data
+<!doctype html><p><math><mi><p><h1>
+#errors
+(1,35): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <math math>
+| <math mi>
+| <p>
+| <h1>
+
+#data
+<!doctype html><p><math><mo><p><h1>
+#errors
+(1,35): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <math math>
+| <math mo>
+| <p>
+| <h1>
+
+#data
+<!doctype html><p><math><mn><p><h1>
+#errors
+(1,35): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <math math>
+| <math mn>
+| <p>
+| <h1>
+
+#data
+<!doctype html><p><math><ms><p><h1>
+#errors
+(1,35): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <math math>
+| <math ms>
+| <p>
+| <h1>
+
+#data
+<!doctype html><p><math><mtext><p><h1>
+#errors
+(1,38): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <math math>
+| <math mtext>
+| <p>
+| <h1>
+
+#data
+<!doctype html><frameset></noframes>
+#errors
+(1,36): unexpected-end-tag-in-frameset
+(1,36): eof-in-frameset
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+
+#data
+<!doctype html><html c=d><body></html><html a=b>
+#errors
+(1,48): non-html-root
+#document
+| <!DOCTYPE html>
+| <html>
+| a="b"
+| c="d"
+| <head>
+| <body>
+
+#data
+<!doctype html><html c=d><frameset></frameset></html><html a=b>
+#errors
+(1,63): non-html-root
+#document
+| <!DOCTYPE html>
+| <html>
+| a="b"
+| c="d"
+| <head>
+| <frameset>
+
+#data
+<!doctype html><html><frameset></frameset></html><!--foo-->
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+| <!-- foo -->
+
+#data
+<!doctype html><html><frameset></frameset></html>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+| " "
+
+#data
+<!doctype html><html><frameset></frameset></html>abc
+#errors
+(1,50): expected-eof-but-got-char
+(1,51): expected-eof-but-got-char
+(1,52): expected-eof-but-got-char
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+
+#data
+<!doctype html><html><frameset></frameset></html><p>
+#errors
+(1,52): expected-eof-but-got-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+
+#data
+<!doctype html><html><frameset></frameset></html></p>
+#errors
+(1,53): expected-eof-but-got-end-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+
+#data
+<html><frameset></frameset></html><!doctype html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,49): unexpected-doctype
+#document
+| <html>
+| <head>
+| <frameset>
+
+#data
+<!doctype html><body><frameset>
+#errors
+(1,31): unexpected-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+
+#data
+<!doctype html><p><frameset><frame>
+#errors
+(1,28): unexpected-start-tag
+(1,35): eof-in-frameset
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+| <frame>
+
+#data
+<!doctype html><p>a<frameset>
+#errors
+(1,29): unexpected-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| "a"
+
+#data
+<!doctype html><p> <frameset><frame>
+#errors
+(1,29): unexpected-start-tag
+(1,36): eof-in-frameset
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+| <frame>
+
+#data
+<!doctype html><pre><frameset>
+#errors
+(1,30): unexpected-start-tag
+(1,30): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <pre>
+
+#data
+<!doctype html><listing><frameset>
+#errors
+(1,34): unexpected-start-tag
+(1,34): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <listing>
+
+#data
+<!doctype html><li><frameset>
+#errors
+(1,29): unexpected-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <li>
+
+#data
+<!doctype html><dd><frameset>
+#errors
+(1,29): unexpected-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <dd>
+
+#data
+<!doctype html><dt><frameset>
+#errors
+(1,29): unexpected-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <dt>
+
+#data
+<!doctype html><button><frameset>
+#errors
+(1,33): unexpected-start-tag
+(1,33): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <button>
+
+#data
+<!doctype html><applet><frameset>
+#errors
+(1,33): unexpected-start-tag
+(1,33): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <applet>
+
+#data
+<!doctype html><marquee><frameset>
+#errors
+(1,34): unexpected-start-tag
+(1,34): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <marquee>
+
+#data
+<!doctype html><object><frameset>
+#errors
+(1,33): unexpected-start-tag
+(1,33): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <object>
+
+#data
+<!doctype html><table><frameset>
+#errors
+(1,32): unexpected-start-tag-implies-table-voodoo
+(1,32): unexpected-start-tag
+(1,32): eof-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+
+#data
+<!doctype html><area><frameset>
+#errors
+(1,31): unexpected-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <area>
+
+#data
+<!doctype html><basefont><frameset>
+#errors
+(1,35): eof-in-frameset
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <basefont>
+| <frameset>
+
+#data
+<!doctype html><bgsound><frameset>
+#errors
+(1,34): eof-in-frameset
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <bgsound>
+| <frameset>
+
+#data
+<!doctype html><br><frameset>
+#errors
+(1,29): unexpected-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <br>
+
+#data
+<!doctype html><embed><frameset>
+#errors
+(1,32): unexpected-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <embed>
+
+#data
+<!doctype html><img><frameset>
+#errors
+(1,30): unexpected-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <img>
+
+#data
+<!doctype html><input><frameset>
+#errors
+(1,32): unexpected-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <input>
+
+#data
+<!doctype html><keygen><frameset>
+#errors
+(1,33): unexpected-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <keygen>
+
+#data
+<!doctype html><wbr><frameset>
+#errors
+(1,30): unexpected-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <wbr>
+
+#data
+<!doctype html><hr><frameset>
+#errors
+(1,29): unexpected-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <hr>
+
+#data
+<!doctype html><textarea></textarea><frameset>
+#errors
+(1,46): unexpected-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <textarea>
+
+#data
+<!doctype html><xmp></xmp><frameset>
+#errors
+(1,36): unexpected-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <xmp>
+
+#data
+<!doctype html><iframe></iframe><frameset>
+#errors
+(1,42): unexpected-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <iframe>
+
+#data
+<!doctype html><select></select><frameset>
+#errors
+(1,42): unexpected-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+
+#data
+<!doctype html><svg></svg><frameset><frame>
+#errors
+(1,36): unexpected-start-tag
+(1,43): eof-in-frameset
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+| <frame>
+
+#data
+<!doctype html><math></math><frameset><frame>
+#errors
+(1,38): unexpected-start-tag
+(1,45): eof-in-frameset
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+| <frame>
+
+#data
+<!doctype html><svg><foreignObject><div> <frameset><frame>
+#errors
+(1,51): unexpected-start-tag
+(1,58): eof-in-frameset
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+| <frame>
+
+#data
+<!doctype html><svg>a</svg><frameset><frame>
+#errors
+(1,37): unexpected-start-tag
+(1,44): unexpected-start-tag-ignored
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "a"
+
+#data
+<!doctype html><svg> </svg><frameset><frame>
+#errors
+(1,37): unexpected-start-tag
+(1,44): eof-in-frameset
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+| <frame>
+
+#data
+<html>aaa<frameset></frameset>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,19): unexpected-start-tag
+(1,30): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <body>
+| "aaa"
+
+#data
+<html> a <frameset></frameset>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,19): unexpected-start-tag
+(1,30): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <body>
+| "a "
+
+#data
+<!doctype html><div><frameset>
+#errors
+(1,30): unexpected-start-tag
+(1,30): eof-in-frameset
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+
+#data
+<!doctype html><div><body><frameset>
+#errors
+(1,26): unexpected-start-tag
+(1,36): unexpected-start-tag
+(1,36): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <div>
+
+#data
+<!doctype html><p><math></p>a
+#errors
+(1,28): unexpected-end-tag
+(1,28): unexpected-end-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <math math>
+| "a"
+
+#data
+<!doctype html><p><math><mn><span></p>a
+#errors
+(1,38): unexpected-end-tag
+(1,39): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <math math>
+| <math mn>
+| <span>
+| <p>
+| "a"
+
+#data
+<!doctype html><math></html>
+#errors
+(1,28): unexpected-end-tag
+(1,28): expected-one-end-tag-but-got-another
+(1,28): unexpected-end-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <math math>
+
+#data
+<!doctype html><meta charset="ascii">
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <meta>
+| charset="ascii"
+| <body>
+
+#data
+<!doctype html><meta http-equiv="content-type" content="text/html;charset=ascii">
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <meta>
+| content="text/html;charset=ascii"
+| http-equiv="content-type"
+| <body>
+
+#data
+<!doctype html><head><!--aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa--><meta charset="utf8">
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <!-- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -->
+| <meta>
+| charset="utf8"
+| <body>
+
+#data
+<!doctype html><html a=b><head></head><html c=d>
+#errors
+(1,48): non-html-root
+#document
+| <!DOCTYPE html>
+| <html>
+| a="b"
+| c="d"
+| <head>
+| <body>
+
+#data
+<!doctype html><image/>
+#errors
+(1,23): image-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <img>
+
+#data
+<!doctype html>a<i>b<table>c<b>d</i>e</b>f
+#errors
+(1,28): foster-parenting-character
+(1,31): foster-parenting-start-tag
+(1,32): foster-parenting-character
+(1,36): foster-parenting-end-tag
+(1,36): adoption-agency-1.3
+(1,37): foster-parenting-character
+(1,41): foster-parenting-end-tag
+(1,42): foster-parenting-character
+(1,42): eof-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "a"
+| <i>
+| "bc"
+| <b>
+| "de"
+| "f"
+| <table>
+
+#data
+<!doctype html><table><i>a<b>b<div>c<a>d</i>e</b>f
+#errors
+(1,25): foster-parenting-start-tag
+(1,26): foster-parenting-character
+(1,29): foster-parenting-start-tag
+(1,30): foster-parenting-character
+(1,35): foster-parenting-start-tag
+(1,36): foster-parenting-character
+(1,39): foster-parenting-start-tag
+(1,40): foster-parenting-character
+(1,44): foster-parenting-end-tag
+(1,44): adoption-agency-1.3
+(1,44): adoption-agency-1.3
+(1,45): foster-parenting-character
+(1,49): foster-parenting-end-tag
+(1,49): adoption-agency-1.3
+(1,49): adoption-agency-1.3
+(1,50): foster-parenting-character
+(1,50): eof-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <i>
+| "a"
+| <b>
+| "b"
+| <b>
+| <div>
+| <b>
+| <i>
+| "c"
+| <a>
+| "d"
+| <a>
+| "e"
+| <a>
+| "f"
+| <table>
+
+#data
+<!doctype html><i>a<b>b<div>c<a>d</i>e</b>f
+#errors
+(1,37): adoption-agency-1.3
+(1,37): adoption-agency-1.3
+(1,42): adoption-agency-1.3
+(1,42): adoption-agency-1.3
+(1,43): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <i>
+| "a"
+| <b>
+| "b"
+| <b>
+| <div>
+| <b>
+| <i>
+| "c"
+| <a>
+| "d"
+| <a>
+| "e"
+| <a>
+| "f"
+
+#data
+<!doctype html><table><i>a<b>b<div>c</i>
+#errors
+(1,25): foster-parenting-start-tag
+(1,26): foster-parenting-character
+(1,29): foster-parenting-start-tag
+(1,30): foster-parenting-character
+(1,35): foster-parenting-start-tag
+(1,36): foster-parenting-character
+(1,40): foster-parenting-end-tag
+(1,40): adoption-agency-1.3
+(1,40): eof-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <i>
+| "a"
+| <b>
+| "b"
+| <b>
+| <div>
+| <i>
+| "c"
+| <table>
+
+#data
+<!doctype html><table><i>a<b>b<div>c<a>d</i>e</b>f
+#errors
+(1,25): foster-parenting-start-tag
+(1,26): foster-parenting-character
+(1,29): foster-parenting-start-tag
+(1,30): foster-parenting-character
+(1,35): foster-parenting-start-tag
+(1,36): foster-parenting-character
+(1,39): foster-parenting-start-tag
+(1,40): foster-parenting-character
+(1,44): foster-parenting-end-tag
+(1,44): adoption-agency-1.3
+(1,44): adoption-agency-1.3
+(1,45): foster-parenting-character
+(1,49): foster-parenting-end-tag
+(1,44): adoption-agency-1.3
+(1,44): adoption-agency-1.3
+(1,50): foster-parenting-character
+(1,50): eof-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <i>
+| "a"
+| <b>
+| "b"
+| <b>
+| <div>
+| <b>
+| <i>
+| "c"
+| <a>
+| "d"
+| <a>
+| "e"
+| <a>
+| "f"
+| <table>
+
+#data
+<!doctype html><table><i>a<div>b<tr>c<b>d</i>e
+#errors
+(1,25): foster-parenting-start-tag
+(1,26): foster-parenting-character
+(1,31): foster-parenting-start-tag
+(1,32): foster-parenting-character
+(1,37): foster-parenting-character
+(1,40): foster-parenting-start-tag
+(1,41): foster-parenting-character
+(1,45): foster-parenting-end-tag
+(1,45): adoption-agency-1.3
+(1,46): foster-parenting-character
+(1,46): eof-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <i>
+| "a"
+| <div>
+| "b"
+| <i>
+| "c"
+| <b>
+| "d"
+| <b>
+| "e"
+| <table>
+| <tbody>
+| <tr>
+
+#data
+<!doctype html><table><td><table><i>a<div>b<b>c</i>d
+#errors
+(1,26): unexpected-cell-in-table-body
+(1,36): foster-parenting-start-tag
+(1,37): foster-parenting-character
+(1,42): foster-parenting-start-tag
+(1,43): foster-parenting-character
+(1,46): foster-parenting-start-tag
+(1,47): foster-parenting-character
+(1,51): foster-parenting-end-tag
+(1,51): adoption-agency-1.3
+(1,51): adoption-agency-1.3
+(1,52): foster-parenting-character
+(1,52): eof-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <i>
+| "a"
+| <div>
+| <i>
+| "b"
+| <b>
+| "c"
+| <b>
+| "d"
+| <table>
+
+#data
+<!doctype html><body><bgsound>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <bgsound>
+
+#data
+<!doctype html><body><basefont>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <basefont>
+
+#data
+<!doctype html><a><b></a><basefont>
+#errors
+(1,25): adoption-agency-1.3
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <a>
+| <b>
+| <basefont>
+
+#data
+<!doctype html><a><b></a><bgsound>
+#errors
+(1,25): adoption-agency-1.3
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <a>
+| <b>
+| <bgsound>
+
+#data
+<!doctype html><figcaption><article></figcaption>a
+#errors
+(1,49): end-tag-too-early
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <figcaption>
+| <article>
+| "a"
+
+#data
+<!doctype html><summary><article></summary>a
+#errors
+(1,43): end-tag-too-early
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <summary>
+| <article>
+| "a"
+
+#data
+<!doctype html><p><a><plaintext>b
+#errors
+(1,32): unexpected-end-tag
+(1,33): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <a>
+| <plaintext>
+| <a>
+| "b"
+
+#data
+<!DOCTYPE html><div>a<a></div>b<p>c</p>d
+#errors
+(1,30): end-tag-too-early
+(1,40): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <div>
+| "a"
+| <a>
+| <a>
+| "b"
+| <p>
+| "c"
+| "d"
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests2.dat b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests2.dat
new file mode 100644
index 00000000000..41953160f00
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests2.dat
@@ -0,0 +1,799 @@
+#data
+<!DOCTYPE html>Test
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "Test"
+
+#data
+<textarea>test</div>test
+#errors
+(1,10): expected-doctype-but-got-start-tag
+(1,24): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <textarea>
+| "test</div>test"
+
+#data
+<table><td>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,11): unexpected-cell-in-table-body
+(1,11): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+
+#data
+<table><td>test</tbody></table>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,11): unexpected-cell-in-table-body
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| "test"
+
+#data
+<frame>test
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,7): unexpected-start-tag-ignored
+#document
+| <html>
+| <head>
+| <body>
+| "test"
+
+#data
+<!DOCTYPE html><frameset>test
+#errors
+(1,29): unexpected-char-in-frameset
+(1,29): unexpected-char-in-frameset
+(1,29): unexpected-char-in-frameset
+(1,29): unexpected-char-in-frameset
+(1,29): eof-in-frameset
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+
+#data
+<!DOCTYPE html><frameset> te st
+#errors
+(1,29): unexpected-char-in-frameset
+(1,29): unexpected-char-in-frameset
+(1,29): unexpected-char-in-frameset
+(1,29): unexpected-char-in-frameset
+(1,29): eof-in-frameset
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+| " "
+
+#data
+<!DOCTYPE html><frameset></frameset> te st
+#errors
+(1,29): unexpected-char-after-frameset
+(1,29): unexpected-char-after-frameset
+(1,29): unexpected-char-after-frameset
+(1,29): unexpected-char-after-frameset
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+| " "
+
+#data
+<!DOCTYPE html><frameset><!DOCTYPE html>
+#errors
+(1,40): unexpected-doctype
+(1,40): eof-in-frameset
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+
+#data
+<!DOCTYPE html><font><p><b>test</font>
+#errors
+(1,38): adoption-agency-1.3
+(1,38): adoption-agency-1.3
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <font>
+| <p>
+| <font>
+| <b>
+| "test"
+
+#data
+<!DOCTYPE html><dt><div><dd>
+#errors
+(1,28): end-tag-too-early
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <dt>
+| <div>
+| <dd>
+
+#data
+<script></x
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,11): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <script>
+| "</x"
+| <body>
+
+#data
+<table><plaintext><td>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,18): unexpected-start-tag-implies-table-voodoo
+(1,22): foster-parenting-character-in-table
+(1,22): foster-parenting-character-in-table
+(1,22): foster-parenting-character-in-table
+(1,22): foster-parenting-character-in-table
+(1,22): eof-in-table
+#document
+| <html>
+| <head>
+| <body>
+| <plaintext>
+| "<td>"
+| <table>
+
+#data
+<plaintext></plaintext>
+#errors
+(1,11): expected-doctype-but-got-start-tag
+(1,23): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <plaintext>
+| "</plaintext>"
+
+#data
+<!DOCTYPE html><table><tr>TEST
+#errors
+(1,30): foster-parenting-character-in-table
+(1,30): foster-parenting-character-in-table
+(1,30): foster-parenting-character-in-table
+(1,30): foster-parenting-character-in-table
+(1,30): eof-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "TEST"
+| <table>
+| <tbody>
+| <tr>
+
+#data
+<!DOCTYPE html><body t1=1><body t2=2><body t3=3 t4=4>
+#errors
+(1,37): unexpected-start-tag
+(1,53): unexpected-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| t1="1"
+| t2="2"
+| t3="3"
+| t4="4"
+
+#data
+</b test
+#errors
+(1,8): eof-in-attribute-name
+(1,8): expected-doctype-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+<!DOCTYPE html></b test<b &=&amp>X
+#errors
+(1,24): invalid-character-in-attribute-name
+(1,32): named-entity-without-semicolon
+(1,33): attributes-in-end-tag
+(1,33): unexpected-end-tag-before-html
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "X"
+
+#data
+<!doctypehtml><scrIPt type=text/x-foobar;baz>X</SCRipt
+#errors
+(1,9): need-space-after-doctype
+(1,54): expected-named-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| type="text/x-foobar;baz"
+| "X</SCRipt"
+| <body>
+
+#data
+&
+#errors
+(1,1): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "&"
+
+#data
+&#
+#errors
+(1,2): expected-numeric-entity
+(1,2): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "&#"
+
+#data
+&#X
+#errors
+(1,3): expected-numeric-entity
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "&#X"
+
+#data
+&#x
+#errors
+(1,3): expected-numeric-entity
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "&#x"
+
+#data
+&#45
+#errors
+(1,4): numeric-entity-without-semicolon
+(1,4): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "-"
+
+#data
+&x-test
+#errors
+(1,2): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "&x-test"
+
+#data
+<!doctypehtml><p><li>
+#errors
+(1,9): need-space-after-doctype
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <li>
+
+#data
+<!doctypehtml><p><dt>
+#errors
+(1,9): need-space-after-doctype
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <dt>
+
+#data
+<!doctypehtml><p><dd>
+#errors
+(1,9): need-space-after-doctype
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <dd>
+
+#data
+<!doctypehtml><p><form>
+#errors
+(1,9): need-space-after-doctype
+(1,23): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <form>
+
+#data
+<!DOCTYPE html><p></P>X
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| "X"
+
+#data
+&AMP
+#errors
+(1,4): named-entity-without-semicolon
+(1,4): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "&"
+
+#data
+&AMp;
+#errors
+(1,3): expected-named-entity
+(1,3): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "&AMp;"
+
+#data
+<!DOCTYPE html><html><head></head><body><thisISasillyTESTelementNameToMakeSureCrazyTagNamesArePARSEDcorrectLY>
+#errors
+(1,110): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <thisisasillytestelementnametomakesurecrazytagnamesareparsedcorrectly>
+
+#data
+<!DOCTYPE html>X</body>X
+#errors
+(1,24): unexpected-char-after-body
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "XX"
+
+#data
+<!DOCTYPE html><!-- X
+#errors
+(1,21): eof-in-comment
+#document
+| <!DOCTYPE html>
+| <!-- X -->
+| <html>
+| <head>
+| <body>
+
+#data
+<!DOCTYPE html><table><caption>test TEST</caption><td>test
+#errors
+(1,54): unexpected-cell-in-table-body
+(1,58): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <caption>
+| "test TEST"
+| <tbody>
+| <tr>
+| <td>
+| "test"
+
+#data
+<!DOCTYPE html><select><option><optgroup>
+#errors
+(1,41): eof-in-select
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| <option>
+| <optgroup>
+
+#data
+<!DOCTYPE html><select><optgroup><option></optgroup><option><select><option>
+#errors
+(1,68): unexpected-select-in-select
+(1,76): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| <optgroup>
+| <option>
+| <option>
+| <option>
+
+#data
+<!DOCTYPE html><select><optgroup><option><optgroup>
+#errors
+(1,51): eof-in-select
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| <optgroup>
+| <option>
+| <optgroup>
+
+#data
+<!DOCTYPE html><datalist><option>foo</datalist>bar
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <datalist>
+| <option>
+| "foo"
+| "bar"
+
+#data
+<!DOCTYPE html><font><input><input></font>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <font>
+| <input>
+| <input>
+
+#data
+<!DOCTYPE html><!-- XXX - XXX -->
+#errors
+#document
+| <!DOCTYPE html>
+| <!-- XXX - XXX -->
+| <html>
+| <head>
+| <body>
+
+#data
+<!DOCTYPE html><!-- XXX - XXX
+#errors
+(1,29): eof-in-comment
+#document
+| <!DOCTYPE html>
+| <!-- XXX - XXX -->
+| <html>
+| <head>
+| <body>
+
+#data
+<!DOCTYPE html><!-- XXX - XXX - XXX -->
+#errors
+#document
+| <!DOCTYPE html>
+| <!-- XXX - XXX - XXX -->
+| <html>
+| <head>
+| <body>
+
+#data
+<isindex test=x name=x>
+#errors
+(1,23): expected-doctype-but-got-start-tag
+(1,23): deprecated-tag
+#document
+| <html>
+| <head>
+| <body>
+| <form>
+| <hr>
+| <label>
+| "This is a searchable index. Enter search keywords: "
+| <input>
+| name="isindex"
+| test="x"
+| <hr>
+
+#data
+test
+test
+#errors
+(2,4): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "test
+test"
+
+#data
+<!DOCTYPE html><body><title>test</body></title>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <title>
+| "test</body>"
+
+#data
+<!DOCTYPE html><body><title>X</title><meta name=z><link rel=foo><style>
+x { content:"</style" } </style>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <title>
+| "X"
+| <meta>
+| name="z"
+| <link>
+| rel="foo"
+| <style>
+| "
+x { content:"</style" } "
+
+#data
+<!DOCTYPE html><select><optgroup></optgroup></select>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| <optgroup>
+
+#data
+
+
+#errors
+(2,1): expected-doctype-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+<!DOCTYPE html> <html>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+
+#data
+<!DOCTYPE html><script>
+</script> <title>x</title> </head>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <script>
+| "
+"
+| " "
+| <title>
+| "x"
+| " "
+| <body>
+
+#data
+<!DOCTYPE html><html><body><html id=x>
+#errors
+(1,38): non-html-root
+#document
+| <!DOCTYPE html>
+| <html>
+| id="x"
+| <head>
+| <body>
+
+#data
+<!DOCTYPE html>X</body><html id="x">
+#errors
+(1,36): non-html-root
+#document
+| <!DOCTYPE html>
+| <html>
+| id="x"
+| <head>
+| <body>
+| "X"
+
+#data
+<!DOCTYPE html><head><html id=x>
+#errors
+(1,32): non-html-root
+#document
+| <!DOCTYPE html>
+| <html>
+| id="x"
+| <head>
+| <body>
+
+#data
+<!DOCTYPE html>X</html>X
+#errors
+(1,24): expected-eof-but-got-char
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "XX"
+
+#data
+<!DOCTYPE html>X</html>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "X "
+
+#data
+<!DOCTYPE html>X</html><p>X
+#errors
+(1,26): expected-eof-but-got-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "X"
+| <p>
+| "X"
+
+#data
+<!DOCTYPE html>X<p/x/y/z>
+#errors
+(1,19): unexpected-character-after-solidus-in-tag
+(1,21): unexpected-character-after-solidus-in-tag
+(1,23): unexpected-character-after-solidus-in-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "X"
+| <p>
+| x=""
+| y=""
+| z=""
+
+#data
+<!DOCTYPE html><!--x--
+#errors
+(1,22): eof-in-comment-double-dash
+#document
+| <!DOCTYPE html>
+| <!-- x -->
+| <html>
+| <head>
+| <body>
+
+#data
+<!DOCTYPE html><table><tr><td></p></table>
+#errors
+(1,34): unexpected-end-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <p>
+
+#data
+<!DOCTYPE <!DOCTYPE HTML>><!--<!--x-->-->
+#errors
+(1,20): expected-space-or-right-bracket-in-doctype
+(1,25): unknown-doctype
+(1,35): unexpected-char-in-comment
+#document
+| <!DOCTYPE <!doctype>
+| <html>
+| <head>
+| <body>
+| ">"
+| <!-- <!--x -->
+| "-->"
+
+#data
+<!doctype html><div><form></form><div></div></div>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <div>
+| <form>
+| <div>
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests20.dat b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests20.dat
new file mode 100644
index 00000000000..52c5acdc6e6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests20.dat
@@ -0,0 +1,516 @@
+#data
+<!doctype html><p><button><button>
+#errors
+(1,34): unexpected-start-tag-implies-end-tag
+(1,34): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <button>
+
+#data
+<!doctype html><p><button><address>
+#errors
+(1,35): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <address>
+
+#data
+<!doctype html><p><button><blockquote>
+#errors
+(1,38): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <blockquote>
+
+#data
+<!doctype html><p><button><menu>
+#errors
+(1,32): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <menu>
+
+#data
+<!doctype html><p><button><p>
+#errors
+(1,29): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <p>
+
+#data
+<!doctype html><p><button><ul>
+#errors
+(1,30): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <ul>
+
+#data
+<!doctype html><p><button><h1>
+#errors
+(1,30): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <h1>
+
+#data
+<!doctype html><p><button><h6>
+#errors
+(1,30): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <h6>
+
+#data
+<!doctype html><p><button><listing>
+#errors
+(1,35): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <listing>
+
+#data
+<!doctype html><p><button><pre>
+#errors
+(1,31): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <pre>
+
+#data
+<!doctype html><p><button><form>
+#errors
+(1,32): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <form>
+
+#data
+<!doctype html><p><button><li>
+#errors
+(1,30): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <li>
+
+#data
+<!doctype html><p><button><dd>
+#errors
+(1,30): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <dd>
+
+#data
+<!doctype html><p><button><dt>
+#errors
+(1,30): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <dt>
+
+#data
+<!doctype html><p><button><plaintext>
+#errors
+(1,37): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <plaintext>
+
+#data
+<!doctype html><p><button><table>
+#errors
+(1,33): eof-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <table>
+
+#data
+<!doctype html><p><button><hr>
+#errors
+(1,30): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <hr>
+
+#data
+<!doctype html><p><button><xmp>
+#errors
+(1,31): expected-named-closing-tag-but-got-eof
+(1,31): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <xmp>
+
+#data
+<!doctype html><p><button></p>
+#errors
+(1,30): unexpected-end-tag
+(1,30): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <button>
+| <p>
+
+#data
+<!doctype html><address><button></address>a
+#errors
+(1,42): end-tag-too-early
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <address>
+| <button>
+| "a"
+
+#data
+<!doctype html><address><button></address>a
+#errors
+(1,42): end-tag-too-early
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <address>
+| <button>
+| "a"
+
+#data
+<p><table></p>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,14): unexpected-end-tag-implies-table-voodoo
+(1,14): unexpected-end-tag
+(1,14): eof-in-table
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| <p>
+| <table>
+
+#data
+<!doctype html><svg>
+#errors
+(1,20): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+
+#data
+<!doctype html><p><figcaption>
+#errors
+(1,30): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <figcaption>
+
+#data
+<!doctype html><p><summary>
+#errors
+(1,27): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <summary>
+
+#data
+<!doctype html><form><table><form>
+#errors
+(1,34): unexpected-form-in-table
+(1,34): eof-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <form>
+| <table>
+
+#data
+<!doctype html><table><form><form>
+#errors
+(1,28): unexpected-form-in-table
+(1,34): unexpected-form-in-table
+(1,34): eof-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <form>
+
+#data
+<!doctype html><table><form></table><form>
+#errors
+(1,28): unexpected-form-in-table
+(1,42): unexpected-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <form>
+
+#data
+<!doctype html><svg><foreignObject><p>
+#errors
+(1,38): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg foreignObject>
+| <p>
+
+#data
+<!doctype html><svg><title>abc
+#errors
+(1,30): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg title>
+| "abc"
+
+#data
+<option><span><option>
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,22): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <option>
+| <span>
+| <option>
+
+#data
+<option><option>
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,16): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <option>
+| <option>
+
+#data
+<math><annotation-xml><div>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,27): unexpected-html-element-in-foreign-content
+(1,27): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math annotation-xml>
+| <div>
+
+#data
+<math><annotation-xml encoding="application/svg+xml"><div>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,58): unexpected-html-element-in-foreign-content
+(1,58): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math annotation-xml>
+| encoding="application/svg+xml"
+| <div>
+
+#data
+<math><annotation-xml encoding="application/xhtml+xml"><div>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,60): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math annotation-xml>
+| encoding="application/xhtml+xml"
+| <div>
+
+#data
+<math><annotation-xml encoding="aPPlication/xhtmL+xMl"><div>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,60): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math annotation-xml>
+| encoding="aPPlication/xhtmL+xMl"
+| <div>
+
+#data
+<math><annotation-xml encoding="text/html"><div>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,48): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math annotation-xml>
+| encoding="text/html"
+| <div>
+
+#data
+<math><annotation-xml encoding="Text/htmL"><div>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,48): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math annotation-xml>
+| encoding="Text/htmL"
+| <div>
+
+#data
+<math><annotation-xml encoding=" text/html "><div>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,50): unexpected-html-element-in-foreign-content
+(1,50): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math annotation-xml>
+| encoding=" text/html "
+| <div>
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests21.dat b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests21.dat
new file mode 100644
index 00000000000..d384a55564c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests21.dat
@@ -0,0 +1,305 @@
+#data
+<svg><![CDATA[foo]]>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,20): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "foo"
+
+#data
+<math><![CDATA[foo]]>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,21): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| "foo"
+
+#data
+<div><![CDATA[foo]]>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,7): expected-dashes-or-doctype
+(1,20): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| <!-- [CDATA[foo]] -->
+
+#data
+<svg><![CDATA[foo
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,17): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "foo"
+
+#data
+<svg><![CDATA[foo
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,17): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "foo"
+
+#data
+<svg><![CDATA[
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,14): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+
+#data
+<svg><![CDATA[]]>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,17): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+
+#data
+<svg><![CDATA[]] >]]>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,21): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "]] >"
+
+#data
+<svg><![CDATA[]] >]]>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,21): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "]] >"
+
+#data
+<svg><![CDATA[]]
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,16): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "]]"
+
+#data
+<svg><![CDATA[]
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,15): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "]"
+
+#data
+<svg><![CDATA[]>a
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,17): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "]>a"
+
+#data
+<!DOCTYPE html><svg><![CDATA[foo]]]>
+#errors
+(1,36): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "foo]"
+
+#data
+<!DOCTYPE html><svg><![CDATA[foo]]]]>
+#errors
+(1,37): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "foo]]"
+
+#data
+<!DOCTYPE html><svg><![CDATA[foo]]]]]>
+#errors
+(1,38): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "foo]]]"
+
+#data
+<svg><foreignObject><div><![CDATA[foo]]>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,27): expected-dashes-or-doctype
+(1,40): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg foreignObject>
+| <div>
+| <!-- [CDATA[foo]] -->
+
+#data
+<svg><![CDATA[<svg>]]>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,22): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "<svg>"
+
+#data
+<svg><![CDATA[</svg>a]]>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,24): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "</svg>a"
+
+#data
+<svg><![CDATA[<svg>a
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,20): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "<svg>a"
+
+#data
+<svg><![CDATA[</svg>a
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,21): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "</svg>a"
+
+#data
+<svg><![CDATA[<svg>]]><path>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,28): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "<svg>"
+| <svg path>
+
+#data
+<svg><![CDATA[<svg>]]></path>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,29): unexpected-end-tag
+(1,29): unexpected-end-tag
+(1,29): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "<svg>"
+
+#data
+<svg><![CDATA[<svg>]]><!--path-->
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,33): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "<svg>"
+| <!-- path -->
+
+#data
+<svg><![CDATA[<svg>]]>path
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,26): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "<svg>path"
+
+#data
+<svg><![CDATA[<!--svg-->]]>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,27): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| "<!--svg-->"
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests22.dat b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests22.dat
new file mode 100644
index 00000000000..31e6d9e3310
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests22.dat
@@ -0,0 +1,190 @@
+#data
+<a><b><big><em><strong><div>X</a>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,33): adoption-agency-1.3
+(1,33): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| <b>
+| <big>
+| <em>
+| <strong>
+| <big>
+| <em>
+| <strong>
+| <div>
+| <a>
+| "X"
+
+#data
+<a><b><div id=1><div id=2><div id=3><div id=4><div id=5><div id=6><div id=7><div id=8>A</a>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,91): adoption-agency-1.3
+(1,91): adoption-agency-1.3
+(1,91): adoption-agency-1.3
+(1,91): adoption-agency-1.3
+(1,91): adoption-agency-1.3
+(1,91): adoption-agency-1.3
+(1,91): adoption-agency-1.3
+(1,91): adoption-agency-1.3
+(1,91): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| <b>
+| <b>
+| <div>
+| id="1"
+| <a>
+| <div>
+| id="2"
+| <a>
+| <div>
+| id="3"
+| <a>
+| <div>
+| id="4"
+| <a>
+| <div>
+| id="5"
+| <a>
+| <div>
+| id="6"
+| <a>
+| <div>
+| id="7"
+| <a>
+| <div>
+| id="8"
+| <a>
+| "A"
+
+#data
+<a><b><div id=1><div id=2><div id=3><div id=4><div id=5><div id=6><div id=7><div id=8><div id=9>A</a>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,101): adoption-agency-1.3
+(1,101): adoption-agency-1.3
+(1,101): adoption-agency-1.3
+(1,101): adoption-agency-1.3
+(1,101): adoption-agency-1.3
+(1,101): adoption-agency-1.3
+(1,101): adoption-agency-1.3
+(1,101): adoption-agency-1.3
+(1,101): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| <b>
+| <b>
+| <div>
+| id="1"
+| <a>
+| <div>
+| id="2"
+| <a>
+| <div>
+| id="3"
+| <a>
+| <div>
+| id="4"
+| <a>
+| <div>
+| id="5"
+| <a>
+| <div>
+| id="6"
+| <a>
+| <div>
+| id="7"
+| <a>
+| <div>
+| id="8"
+| <a>
+| <div>
+| id="9"
+| "A"
+
+#data
+<a><b><div id=1><div id=2><div id=3><div id=4><div id=5><div id=6><div id=7><div id=8><div id=9><div id=10>A</a>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,112): adoption-agency-1.3
+(1,112): adoption-agency-1.3
+(1,112): adoption-agency-1.3
+(1,112): adoption-agency-1.3
+(1,112): adoption-agency-1.3
+(1,112): adoption-agency-1.3
+(1,112): adoption-agency-1.3
+(1,112): adoption-agency-1.3
+(1,112): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| <b>
+| <b>
+| <div>
+| id="1"
+| <a>
+| <div>
+| id="2"
+| <a>
+| <div>
+| id="3"
+| <a>
+| <div>
+| id="4"
+| <a>
+| <div>
+| id="5"
+| <a>
+| <div>
+| id="6"
+| <a>
+| <div>
+| id="7"
+| <a>
+| <div>
+| id="8"
+| <a>
+| <div>
+| id="9"
+| <div>
+| id="10"
+| "A"
+
+#data
+<cite><b><cite><i><cite><i><cite><i><div>X</b>TEST
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,46): adoption-agency-1.3
+(1,50): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <cite>
+| <b>
+| <cite>
+| <i>
+| <cite>
+| <i>
+| <cite>
+| <i>
+| <i>
+| <i>
+| <div>
+| <b>
+| "X"
+| "TEST"
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests23.dat b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests23.dat
new file mode 100644
index 00000000000..49e4a4ace58
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests23.dat
@@ -0,0 +1,168 @@
+#data
+<p><font size=4><font color=red><font size=4><font size=4><font size=4><font size=4><font size=4><font color=red><p>X
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,116): unexpected-end-tag
+(1,117): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| <font>
+| size="4"
+| <font>
+| color="red"
+| <font>
+| size="4"
+| <font>
+| size="4"
+| <font>
+| size="4"
+| <font>
+| size="4"
+| <font>
+| size="4"
+| <font>
+| color="red"
+| <p>
+| <font>
+| color="red"
+| <font>
+| size="4"
+| <font>
+| size="4"
+| <font>
+| size="4"
+| <font>
+| color="red"
+| "X"
+
+#data
+<p><font size=4><font size=4><font size=4><font size=4><p>X
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,58): unexpected-end-tag
+(1,59): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| <font>
+| size="4"
+| <font>
+| size="4"
+| <font>
+| size="4"
+| <font>
+| size="4"
+| <p>
+| <font>
+| size="4"
+| <font>
+| size="4"
+| <font>
+| size="4"
+| "X"
+
+#data
+<p><font size=4><font size=4><font size=4><font size="5"><font size=4><p>X
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,73): unexpected-end-tag
+(1,74): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| <font>
+| size="4"
+| <font>
+| size="4"
+| <font>
+| size="4"
+| <font>
+| size="5"
+| <font>
+| size="4"
+| <p>
+| <font>
+| size="4"
+| <font>
+| size="4"
+| <font>
+| size="5"
+| <font>
+| size="4"
+| "X"
+
+#data
+<p><font size=4 id=a><font size=4 id=b><font size=4><font size=4><p>X
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,68): unexpected-end-tag
+(1,69): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| <font>
+| id="a"
+| size="4"
+| <font>
+| id="b"
+| size="4"
+| <font>
+| size="4"
+| <font>
+| size="4"
+| <p>
+| <font>
+| id="a"
+| size="4"
+| <font>
+| id="b"
+| size="4"
+| <font>
+| size="4"
+| <font>
+| size="4"
+| "X"
+
+#data
+<p><b id=a><b id=a><b id=a><b><object><b id=a><b id=a>X</object><p>Y
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,64): end-tag-too-early
+(1,67): unexpected-end-tag
+(1,68): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| <b>
+| id="a"
+| <b>
+| id="a"
+| <b>
+| id="a"
+| <b>
+| <object>
+| <b>
+| id="a"
+| <b>
+| id="a"
+| "X"
+| <p>
+| <b>
+| id="a"
+| <b>
+| id="a"
+| <b>
+| id="a"
+| <b>
+| "Y"
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests24.dat b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests24.dat
new file mode 100644
index 00000000000..f6dc7eb48a5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests24.dat
@@ -0,0 +1,79 @@
+#data
+<!DOCTYPE html>&NotEqualTilde;
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "≂̸"
+
+#data
+<!DOCTYPE html>&NotEqualTilde;A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "≂̸A"
+
+#data
+<!DOCTYPE html>&ThickSpace;
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "  "
+
+#data
+<!DOCTYPE html>&ThickSpace;A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "  A"
+
+#data
+<!DOCTYPE html>&NotSubset;
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "⊂⃒"
+
+#data
+<!DOCTYPE html>&NotSubset;A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "⊂⃒A"
+
+#data
+<!DOCTYPE html>&Gopf;
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "𝔾"
+
+#data
+<!DOCTYPE html>&Gopf;A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "𝔾A"
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests25.dat b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests25.dat
new file mode 100644
index 00000000000..103574ee4b7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests25.dat
@@ -0,0 +1,232 @@
+#data
+<!DOCTYPE html><body><foo>A
+#errors
+(1,27): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <foo>
+| "A"
+
+#data
+<!DOCTYPE html><body><area>A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <area>
+| "A"
+
+#data
+<!DOCTYPE html><body><base>A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <base>
+| "A"
+
+#data
+<!DOCTYPE html><body><basefont>A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <basefont>
+| "A"
+
+#data
+<!DOCTYPE html><body><bgsound>A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <bgsound>
+| "A"
+
+#data
+<!DOCTYPE html><body><br>A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <br>
+| "A"
+
+#data
+<!DOCTYPE html><body><col>A
+#errors
+(1,26): unexpected-start-tag-ignored
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "A"
+
+#data
+<!DOCTYPE html><body><command>A
+#errors
+eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <command>
+| "A"
+
+#data
+<!DOCTYPE html><body><menuitem>A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <menuitem>
+| "A"
+
+#data
+<!DOCTYPE html><body><embed>A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <embed>
+| "A"
+
+#data
+<!DOCTYPE html><body><frame>A
+#errors
+(1,28): unexpected-start-tag-ignored
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "A"
+
+#data
+<!DOCTYPE html><body><hr>A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <hr>
+| "A"
+
+#data
+<!DOCTYPE html><body><img>A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <img>
+| "A"
+
+#data
+<!DOCTYPE html><body><input>A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <input>
+| "A"
+
+#data
+<!DOCTYPE html><body><keygen>A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <keygen>
+| "A"
+
+#data
+<!DOCTYPE html><body><link>A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <link>
+| "A"
+
+#data
+<!DOCTYPE html><body><meta>A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <meta>
+| "A"
+
+#data
+<!DOCTYPE html><body><param>A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <param>
+| "A"
+
+#data
+<!DOCTYPE html><body><source>A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <source>
+| "A"
+
+#data
+<!DOCTYPE html><body><track>A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <track>
+| "A"
+
+#data
+<!DOCTYPE html><body><wbr>A
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <wbr>
+| "A"
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests26.dat b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests26.dat
new file mode 100644
index 00000000000..8964624a4f3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests26.dat
@@ -0,0 +1,388 @@
+#data
+<!DOCTYPE html><body><a href='#1'><nobr>1<nobr></a><br><a href='#2'><nobr>2<nobr></a><br><a href='#3'><nobr>3<nobr></a>
+#errors
+(1,47): unexpected-start-tag-implies-end-tag
+(1,51): adoption-agency-1.3
+(1,74): unexpected-start-tag-implies-end-tag
+(1,74): adoption-agency-1.3
+(1,81): unexpected-start-tag-implies-end-tag
+(1,85): adoption-agency-1.3
+(1,108): unexpected-start-tag-implies-end-tag
+(1,108): adoption-agency-1.3
+(1,115): unexpected-start-tag-implies-end-tag
+(1,119): adoption-agency-1.3
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <a>
+| href="#1"
+| <nobr>
+| "1"
+| <nobr>
+| <nobr>
+| <br>
+| <a>
+| href="#2"
+| <a>
+| href="#2"
+| <nobr>
+| "2"
+| <nobr>
+| <nobr>
+| <br>
+| <a>
+| href="#3"
+| <a>
+| href="#3"
+| <nobr>
+| "3"
+| <nobr>
+
+#data
+<!DOCTYPE html><body><b><nobr>1<nobr></b><i><nobr>2<nobr></i>3
+#errors
+(1,37): unexpected-start-tag-implies-end-tag
+(1,41): adoption-agency-1.3
+(1,50): unexpected-start-tag-implies-end-tag
+(1,50): adoption-agency-1.3
+(1,57): unexpected-start-tag-implies-end-tag
+(1,61): adoption-agency-1.3
+(1,62): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <b>
+| <nobr>
+| "1"
+| <nobr>
+| <nobr>
+| <i>
+| <i>
+| <nobr>
+| "2"
+| <nobr>
+| <nobr>
+| "3"
+
+#data
+<!DOCTYPE html><body><b><nobr>1<table><nobr></b><i><nobr>2<nobr></i>3
+#errors
+(1,44): foster-parenting-start-tag
+(1,48): foster-parenting-end-tag
+(1,48): adoption-agency-1.3
+(1,51): foster-parenting-start-tag
+(1,57): foster-parenting-start-tag
+(1,57): nobr-already-in-scope
+(1,57): adoption-agency-1.2
+(1,58): foster-parenting-character
+(1,64): foster-parenting-start-tag
+(1,64): nobr-already-in-scope
+(1,68): foster-parenting-end-tag
+(1,68): adoption-agency-1.2
+(1,69): foster-parenting-character
+(1,69): eof-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <b>
+| <nobr>
+| "1"
+| <nobr>
+| <i>
+| <i>
+| <nobr>
+| "2"
+| <nobr>
+| <nobr>
+| "3"
+| <table>
+
+#data
+<!DOCTYPE html><body><b><nobr>1<table><tr><td><nobr></b><i><nobr>2<nobr></i>3
+#errors
+(1,56): unexpected-end-tag
+(1,65): unexpected-start-tag-implies-end-tag
+(1,65): adoption-agency-1.3
+(1,72): unexpected-start-tag-implies-end-tag
+(1,76): adoption-agency-1.3
+(1,77): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <b>
+| <nobr>
+| "1"
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <nobr>
+| <i>
+| <i>
+| <nobr>
+| "2"
+| <nobr>
+| <nobr>
+| "3"
+
+#data
+<!DOCTYPE html><body><b><nobr>1<div><nobr></b><i><nobr>2<nobr></i>3
+#errors
+(1,42): unexpected-start-tag-implies-end-tag
+(1,42): adoption-agency-1.3
+(1,46): adoption-agency-1.3
+(1,46): adoption-agency-1.3
+(1,55): unexpected-start-tag-implies-end-tag
+(1,55): adoption-agency-1.3
+(1,62): unexpected-start-tag-implies-end-tag
+(1,66): adoption-agency-1.3
+(1,67): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <b>
+| <nobr>
+| "1"
+| <div>
+| <b>
+| <nobr>
+| <nobr>
+| <nobr>
+| <i>
+| <i>
+| <nobr>
+| "2"
+| <nobr>
+| <nobr>
+| "3"
+
+#data
+<!DOCTYPE html><body><b><nobr>1<nobr></b><div><i><nobr>2<nobr></i>3
+#errors
+(1,37): unexpected-start-tag-implies-end-tag
+(1,41): adoption-agency-1.3
+(1,55): unexpected-start-tag-implies-end-tag
+(1,55): adoption-agency-1.3
+(1,62): unexpected-start-tag-implies-end-tag
+(1,66): adoption-agency-1.3
+(1,67): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <b>
+| <nobr>
+| "1"
+| <nobr>
+| <div>
+| <nobr>
+| <i>
+| <i>
+| <nobr>
+| "2"
+| <nobr>
+| <nobr>
+| "3"
+
+#data
+<!DOCTYPE html><body><b><nobr>1<nobr><ins></b><i><nobr>
+#errors
+(1,37): unexpected-start-tag-implies-end-tag
+(1,46): adoption-agency-1.3
+(1,55): unexpected-start-tag-implies-end-tag
+(1,55): adoption-agency-1.3
+(1,55): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <b>
+| <nobr>
+| "1"
+| <nobr>
+| <ins>
+| <nobr>
+| <i>
+| <i>
+| <nobr>
+
+#data
+<!DOCTYPE html><body><b><nobr>1<ins><nobr></b><i>2
+#errors
+(1,42): unexpected-start-tag-implies-end-tag
+(1,42): adoption-agency-1.3
+(1,46): adoption-agency-1.3
+(1,50): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <b>
+| <nobr>
+| "1"
+| <ins>
+| <nobr>
+| <nobr>
+| <i>
+| "2"
+
+#data
+<!DOCTYPE html><body><b>1<nobr></b><i><nobr>2</i>
+#errors
+(1,35): adoption-agency-1.3
+(1,44): unexpected-start-tag-implies-end-tag
+(1,44): adoption-agency-1.3
+(1,49): adoption-agency-1.3
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <b>
+| "1"
+| <nobr>
+| <nobr>
+| <i>
+| <i>
+| <nobr>
+| "2"
+
+#data
+<p><code x</code></p>
+
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,11): invalid-character-in-attribute-name
+(1,12): unexpected-character-after-solidus-in-tag
+(1,21): unexpected-end-tag
+(2,0): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| <code>
+| code=""
+| x<=""
+| <code>
+| code=""
+| x<=""
+| "
+"
+
+#data
+<!DOCTYPE html><svg><foreignObject><p><i></p>a
+#errors
+(1,45): unexpected-end-tag
+(1,46): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg foreignObject>
+| <p>
+| <i>
+| <i>
+| "a"
+
+#data
+<!DOCTYPE html><table><tr><td><svg><foreignObject><p><i></p>a
+#errors
+(1,60): unexpected-end-tag
+(1,61): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <svg svg>
+| <svg foreignObject>
+| <p>
+| <i>
+| <i>
+| "a"
+
+#data
+<!DOCTYPE html><math><mtext><p><i></p>a
+#errors
+(1,38): unexpected-end-tag
+(1,39): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mtext>
+| <p>
+| <i>
+| <i>
+| "a"
+
+#data
+<!DOCTYPE html><table><tr><td><math><mtext><p><i></p>a
+#errors
+(1,53): unexpected-end-tag
+(1,54): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <math math>
+| <math mtext>
+| <p>
+| <i>
+| <i>
+| "a"
+
+#data
+<!DOCTYPE html><body><div><!/div>a
+#errors
+(1,28): expected-dashes-or-doctype
+(1,34): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <div>
+| <!-- /div -->
+| "a"
+
+#data
+<button><p><button>
+#errors
+Line 1 Col 8 Unexpected start tag (button). Expected DOCTYPE.
+Line 1 Col 19 Unexpected start tag (button) implies end tag (button).
+Line 1 Col 19 Expected closing tag. Unexpected end of file.
+#document
+| <html>
+| <head>
+| <body>
+| <button>
+| <p>
+| <button>
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests3.dat b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests3.dat
new file mode 100644
index 00000000000..c7583d99e8b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests3.dat
@@ -0,0 +1,305 @@
+#data
+<head></head><style></style>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,20): unexpected-start-tag-out-of-my-head
+#document
+| <html>
+| <head>
+| <style>
+| <body>
+
+#data
+<head></head><script></script>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,21): unexpected-start-tag-out-of-my-head
+#document
+| <html>
+| <head>
+| <script>
+| <body>
+
+#data
+<head></head><!-- --><style></style><!-- --><script></script>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,28): unexpected-start-tag-out-of-my-head
+(1,52): unexpected-start-tag-out-of-my-head
+#document
+| <html>
+| <head>
+| <style>
+| <script>
+| <!-- -->
+| <!-- -->
+| <body>
+
+#data
+<head></head><!-- -->x<style></style><!-- --><script></script>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <!-- -->
+| <body>
+| "x"
+| <style>
+| <!-- -->
+| <script>
+
+#data
+<!DOCTYPE html><html><head></head><body><pre>
+</pre></body></html>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <pre>
+
+#data
+<!DOCTYPE html><html><head></head><body><pre>
+foo</pre></body></html>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <pre>
+| "foo"
+
+#data
+<!DOCTYPE html><html><head></head><body><pre>
+
+foo</pre></body></html>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <pre>
+| "
+foo"
+
+#data
+<!DOCTYPE html><html><head></head><body><pre>
+foo
+</pre></body></html>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <pre>
+| "foo
+"
+
+#data
+<!DOCTYPE html><html><head></head><body><pre>x</pre><span>
+</span></body></html>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <pre>
+| "x"
+| <span>
+| "
+"
+
+#data
+<!DOCTYPE html><html><head></head><body><pre>x
+y</pre></body></html>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <pre>
+| "x
+y"
+
+#data
+<!DOCTYPE html><html><head></head><body><pre>x<div>
+y</pre></body></html>
+#errors
+(2,7): end-tag-too-early
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <pre>
+| "x"
+| <div>
+| "
+y"
+
+#data
+<!DOCTYPE html><pre>&#x0a;&#x0a;A</pre>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <pre>
+| "
+A"
+
+#data
+<!DOCTYPE html><HTML><META><HEAD></HEAD></HTML>
+#errors
+(1,33): two-heads-are-not-better-than-one
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <meta>
+| <body>
+
+#data
+<!DOCTYPE html><HTML><HEAD><head></HEAD></HTML>
+#errors
+(1,33): two-heads-are-not-better-than-one
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+
+#data
+<textarea>foo<span>bar</span><i>baz
+#errors
+(1,10): expected-doctype-but-got-start-tag
+(1,35): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <textarea>
+| "foo<span>bar</span><i>baz"
+
+#data
+<title>foo<span>bar</em><i>baz
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,30): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <title>
+| "foo<span>bar</em><i>baz"
+| <body>
+
+#data
+<!DOCTYPE html><textarea>
+</textarea>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <textarea>
+
+#data
+<!DOCTYPE html><textarea>
+foo</textarea>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <textarea>
+| "foo"
+
+#data
+<!DOCTYPE html><textarea>
+
+foo</textarea>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <textarea>
+| "
+foo"
+
+#data
+<!DOCTYPE html><html><head></head><body><ul><li><div><p><li></ul></body></html>
+#errors
+(1,60): end-tag-too-early
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <ul>
+| <li>
+| <div>
+| <p>
+| <li>
+
+#data
+<!doctype html><nobr><nobr><nobr>
+#errors
+(1,27): unexpected-start-tag-implies-end-tag
+(1,33): unexpected-start-tag-implies-end-tag
+(1,33): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <nobr>
+| <nobr>
+| <nobr>
+
+#data
+<!doctype html><nobr><nobr></nobr><nobr>
+#errors
+(1,27): unexpected-start-tag-implies-end-tag
+(1,40): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <nobr>
+| <nobr>
+| <nobr>
+
+#data
+<!doctype html><html><body><p><table></table></body></html>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <table>
+
+#data
+<p><table></table>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| <table>
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests4.dat b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests4.dat
new file mode 100644
index 00000000000..0a6174c36c0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests4.dat
@@ -0,0 +1,58 @@
+#data
+direct div content
+#errors
+#document-fragment
+div
+#document
+| "direct div content"
+
+#data
+direct textarea content
+#errors
+#document-fragment
+textarea
+#document
+| "direct textarea content"
+
+#data
+textarea content with <em>pseudo</em> <foo>markup
+#errors
+#document-fragment
+textarea
+#document
+| "textarea content with <em>pseudo</em> <foo>markup"
+
+#data
+this is &#x0043;DATA inside a <style> element
+#errors
+#document-fragment
+style
+#document
+| "this is &#x0043;DATA inside a <style> element"
+
+#data
+</plaintext>
+#errors
+#document-fragment
+plaintext
+#document
+| "</plaintext>"
+
+#data
+setting html's innerHTML
+#errors
+#document-fragment
+html
+#document
+| <head>
+| <body>
+| "setting html's innerHTML"
+
+#data
+<title>setting head's innerHTML</title>
+#errors
+#document-fragment
+head
+#document
+| <title>
+| "setting head's innerHTML"
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests5.dat b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests5.dat
new file mode 100644
index 00000000000..1ef8cae4213
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests5.dat
@@ -0,0 +1,210 @@
+#data
+<style> <!-- </style>x
+#errors
+(1,7): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <style>
+| " <!-- "
+| <body>
+| "x"
+
+#data
+<style> <!-- </style> --> </style>x
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,34): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <style>
+| " <!-- "
+| " "
+| <body>
+| "--> x"
+
+#data
+<style> <!--> </style>x
+#errors
+(1,7): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <style>
+| " <!--> "
+| <body>
+| "x"
+
+#data
+<style> <!---> </style>x
+#errors
+(1,7): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <style>
+| " <!---> "
+| <body>
+| "x"
+
+#data
+<iframe> <!---> </iframe>x
+#errors
+(1,8): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <iframe>
+| " <!---> "
+| "x"
+
+#data
+<iframe> <!--- </iframe>->x</iframe> --> </iframe>x
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,36): unexpected-end-tag
+(1,50): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <body>
+| <iframe>
+| " <!--- "
+| "->x --> x"
+
+#data
+<script> <!-- </script> --> </script>x
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,37): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <script>
+| " <!-- "
+| " "
+| <body>
+| "--> x"
+
+#data
+<title> <!-- </title> --> </title>x
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,34): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <title>
+| " <!-- "
+| " "
+| <body>
+| "--> x"
+
+#data
+<textarea> <!--- </textarea>->x</textarea> --> </textarea>x
+#errors
+(1,10): expected-doctype-but-got-start-tag
+(1,42): unexpected-end-tag
+(1,58): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <body>
+| <textarea>
+| " <!--- "
+| "->x --> x"
+
+#data
+<style> <!</-- </style>x
+#errors
+(1,7): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <style>
+| " <!</-- "
+| <body>
+| "x"
+
+#data
+<p><xmp></xmp>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| <xmp>
+
+#data
+<xmp> <!-- > --> </xmp>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <xmp>
+| " <!-- > --> "
+
+#data
+<title>&amp;</title>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <title>
+| "&"
+| <body>
+
+#data
+<title><!--&amp;--></title>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <title>
+| "<!--&-->"
+| <body>
+
+#data
+<title><!--</title>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <title>
+| "<!--"
+| <body>
+
+#data
+<noscript><!--</noscript>--></noscript>
+#errors
+(1,10): expected-doctype-but-got-start-tag
+(1,39): unexpected-end-tag
+#script-on
+#document
+| <html>
+| <head>
+| <noscript>
+| "<!--"
+| <body>
+| "-->"
+
+#data
+<noscript><!--</noscript>--></noscript>
+#errors
+(1,10): expected-doctype-but-got-start-tag
+#script-off
+#document
+| <html>
+| <head>
+| <noscript>
+| <!-- </noscript> -->
+| <body>
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests6.dat b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests6.dat
new file mode 100644
index 00000000000..d774fc234a9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests6.dat
@@ -0,0 +1,659 @@
+#data
+<!doctype html></head> <head>
+#errors
+(1,29): unexpected-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| " "
+| <body>
+
+#data
+<!doctype html><form><div></form><div>
+#errors
+(1,33): end-tag-too-early-ignored
+(1,38): expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <form>
+| <div>
+| <div>
+
+#data
+<!doctype html><title>&amp;</title>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <title>
+| "&"
+| <body>
+
+#data
+<!doctype html><title><!--&amp;--></title>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <title>
+| "<!--&-->"
+| <body>
+
+#data
+<!doctype>
+#errors
+(1,9): need-space-after-doctype
+(1,10): expected-doctype-name-but-got-right-bracket
+(1,10): unknown-doctype
+#document
+| <!DOCTYPE >
+| <html>
+| <head>
+| <body>
+
+#data
+<!---x
+#errors
+(1,6): eof-in-comment
+(1,6): expected-doctype-but-got-eof
+#document
+| <!-- -x -->
+| <html>
+| <head>
+| <body>
+
+#data
+<body>
+<div>
+#errors
+(1,6): unexpected-start-tag
+(2,5): expected-closing-tag-but-got-eof
+#document-fragment
+div
+#document
+| "
+"
+| <div>
+
+#data
+<frameset></frameset>
+foo
+#errors
+(1,10): expected-doctype-but-got-start-tag
+(2,1): unexpected-char-after-frameset
+(2,2): unexpected-char-after-frameset
+(2,3): unexpected-char-after-frameset
+#document
+| <html>
+| <head>
+| <frameset>
+| "
+"
+
+#data
+<frameset></frameset>
+<noframes>
+#errors
+(1,10): expected-doctype-but-got-start-tag
+(2,10): expected-named-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <frameset>
+| "
+"
+| <noframes>
+
+#data
+<frameset></frameset>
+<div>
+#errors
+(1,10): expected-doctype-but-got-start-tag
+(2,5): unexpected-start-tag-after-frameset
+#document
+| <html>
+| <head>
+| <frameset>
+| "
+"
+
+#data
+<frameset></frameset>
+</html>
+#errors
+(1,10): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <frameset>
+| "
+"
+
+#data
+<frameset></frameset>
+</div>
+#errors
+(1,10): expected-doctype-but-got-start-tag
+(2,6): unexpected-end-tag-after-frameset
+#document
+| <html>
+| <head>
+| <frameset>
+| "
+"
+
+#data
+<form><form>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,12): unexpected-start-tag
+(1,12): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <form>
+
+#data
+<button><button>
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,16): unexpected-start-tag-implies-end-tag
+(1,16): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <button>
+| <button>
+
+#data
+<table><tr><td></th>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,20): unexpected-end-tag
+(1,20): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+
+#data
+<table><caption><td>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,20): unexpected-cell-in-table-body
+(1,20): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <caption>
+| <tbody>
+| <tr>
+| <td>
+
+#data
+<table><caption><div>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,21): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <caption>
+| <div>
+
+#data
+</caption><div>
+#errors
+(1,10): XXX-undefined-error
+(1,15): expected-closing-tag-but-got-eof
+#document-fragment
+caption
+#document
+| <div>
+
+#data
+<table><caption><div></caption>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,31): expected-one-end-tag-but-got-another
+(1,31): eof-in-table
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <caption>
+| <div>
+
+#data
+<table><caption></table>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <caption>
+
+#data
+</table><div>
+#errors
+(1,8): unexpected-end-tag
+(1,13): expected-closing-tag-but-got-eof
+#document-fragment
+caption
+#document
+| <div>
+
+#data
+<table><caption></body></col></colgroup></html></tbody></td></tfoot></th></thead></tr>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,23): unexpected-end-tag
+(1,29): unexpected-end-tag
+(1,40): unexpected-end-tag
+(1,47): unexpected-end-tag
+(1,55): unexpected-end-tag
+(1,60): unexpected-end-tag
+(1,68): unexpected-end-tag
+(1,73): unexpected-end-tag
+(1,81): unexpected-end-tag
+(1,86): unexpected-end-tag
+(1,86): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <caption>
+
+#data
+<table><caption><div></div>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,27): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <caption>
+| <div>
+
+#data
+<table><tr><td></body></caption></col></colgroup></html>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,22): unexpected-end-tag
+(1,32): unexpected-end-tag
+(1,38): unexpected-end-tag
+(1,49): unexpected-end-tag
+(1,56): unexpected-end-tag
+(1,56): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+
+#data
+</table></tbody></tfoot></thead></tr><div>
+#errors
+(1,8): unexpected-end-tag
+(1,16): unexpected-end-tag
+(1,24): unexpected-end-tag
+(1,32): unexpected-end-tag
+(1,37): unexpected-end-tag
+(1,42): expected-closing-tag-but-got-eof
+#document-fragment
+td
+#document
+| <div>
+
+#data
+<table><colgroup>foo
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,18): foster-parenting-character-in-table
+(1,19): foster-parenting-character-in-table
+(1,20): foster-parenting-character-in-table
+(1,20): eof-in-table
+#document
+| <html>
+| <head>
+| <body>
+| "foo"
+| <table>
+| <colgroup>
+
+#data
+foo<col>
+#errors
+(1,1): unexpected-character-in-colgroup
+(1,2): unexpected-character-in-colgroup
+(1,3): unexpected-character-in-colgroup
+#document-fragment
+colgroup
+#document
+| <col>
+
+#data
+<table><colgroup></col>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,23): no-end-tag
+(1,23): eof-in-table
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <colgroup>
+
+#data
+<frameset><div>
+#errors
+(1,10): expected-doctype-but-got-start-tag
+(1,15): unexpected-start-tag-in-frameset
+(1,15): eof-in-frameset
+#document
+| <html>
+| <head>
+| <frameset>
+
+#data
+</frameset><frame>
+#errors
+(1,11): unexpected-frameset-in-frameset-innerhtml
+#document-fragment
+frameset
+#document
+| <frame>
+
+#data
+<frameset></div>
+#errors
+(1,10): expected-doctype-but-got-start-tag
+(1,16): unexpected-end-tag-in-frameset
+(1,16): eof-in-frameset
+#document
+| <html>
+| <head>
+| <frameset>
+
+#data
+</body><div>
+#errors
+(1,7): unexpected-close-tag
+(1,12): expected-closing-tag-but-got-eof
+#document-fragment
+body
+#document
+| <div>
+
+#data
+<table><tr><div>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,16): unexpected-start-tag-implies-table-voodoo
+(1,16): eof-in-table
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| <table>
+| <tbody>
+| <tr>
+
+#data
+</tr><td>
+#errors
+(1,5): unexpected-end-tag
+#document-fragment
+tr
+#document
+| <td>
+
+#data
+</tbody></tfoot></thead><td>
+#errors
+(1,8): unexpected-end-tag
+(1,16): unexpected-end-tag
+(1,24): unexpected-end-tag
+#document-fragment
+tr
+#document
+| <td>
+
+#data
+<table><tr><div><td>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,16): foster-parenting-start-tag
+(1,20): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+
+#data
+<caption><col><colgroup><tbody><tfoot><thead><tr>
+#errors
+(1,9): unexpected-start-tag
+(1,14): unexpected-start-tag
+(1,24): unexpected-start-tag
+(1,31): unexpected-start-tag
+(1,38): unexpected-start-tag
+(1,45): unexpected-start-tag
+#document-fragment
+tbody
+#document
+| <tr>
+
+#data
+<table><tbody></thead>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,22): unexpected-end-tag-in-table-body
+(1,22): eof-in-table
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+
+#data
+</table><tr>
+#errors
+(1,8): unexpected-end-tag
+#document-fragment
+tbody
+#document
+| <tr>
+
+#data
+<table><tbody></body></caption></col></colgroup></html></td></th></tr>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,21): unexpected-end-tag-in-table-body
+(1,31): unexpected-end-tag-in-table-body
+(1,37): unexpected-end-tag-in-table-body
+(1,48): unexpected-end-tag-in-table-body
+(1,55): unexpected-end-tag-in-table-body
+(1,60): unexpected-end-tag-in-table-body
+(1,65): unexpected-end-tag-in-table-body
+(1,70): unexpected-end-tag-in-table-body
+(1,70): eof-in-table
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+
+#data
+<table><tbody></div>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,20): unexpected-end-tag-implies-table-voodoo
+(1,20): end-tag-too-early
+(1,20): eof-in-table
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+
+#data
+<table><table>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,14): unexpected-start-tag-implies-end-tag
+(1,14): eof-in-table
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <table>
+
+#data
+<table></body></caption></col></colgroup></html></tbody></td></tfoot></th></thead></tr>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,14): unexpected-end-tag
+(1,24): unexpected-end-tag
+(1,30): unexpected-end-tag
+(1,41): unexpected-end-tag
+(1,48): unexpected-end-tag
+(1,56): unexpected-end-tag
+(1,61): unexpected-end-tag
+(1,69): unexpected-end-tag
+(1,74): unexpected-end-tag
+(1,82): unexpected-end-tag
+(1,87): unexpected-end-tag
+(1,87): eof-in-table
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+
+#data
+</table><tr>
+#errors
+(1,8): unexpected-end-tag
+#document-fragment
+table
+#document
+| <tbody>
+| <tr>
+
+#data
+<body></body></html>
+#errors
+(1,20): unexpected-end-tag-after-body-innerhtml
+#document-fragment
+html
+#document
+| <head>
+| <body>
+
+#data
+<html><frameset></frameset></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <frameset>
+| " "
+
+#data
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"><html></html>
+#errors
+#document
+| <!DOCTYPE html "-//W3C//DTD HTML 4.01//EN" "">
+| <html>
+| <head>
+| <body>
+
+#data
+<param><frameset></frameset>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,17): unexpected-start-tag
+#document
+| <html>
+| <head>
+| <frameset>
+
+#data
+<source><frameset></frameset>
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,18): unexpected-start-tag
+#document
+| <html>
+| <head>
+| <frameset>
+
+#data
+<track><frameset></frameset>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,17): unexpected-start-tag
+#document
+| <html>
+| <head>
+| <frameset>
+
+#data
+</html><frameset></frameset>
+#errors
+(1,7): expected-doctype-but-got-end-tag
+(1,17): expected-eof-but-got-start-tag
+(1,17): unexpected-start-tag
+#document
+| <html>
+| <head>
+| <frameset>
+
+#data
+</body><frameset></frameset>
+#errors
+(1,7): expected-doctype-but-got-end-tag
+(1,17): unexpected-start-tag-after-body
+(1,17): unexpected-start-tag
+#document
+| <html>
+| <head>
+| <frameset>
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests7.dat b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests7.dat
new file mode 100644
index 00000000000..d941d3d70be
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests7.dat
@@ -0,0 +1,403 @@
+#data
+<!doctype html><body><title>X</title>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <title>
+| "X"
+
+#data
+<!doctype html><table><title>X</title></table>
+#errors
+(1,29): unexpected-start-tag-implies-table-voodoo
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <title>
+| "X"
+| <table>
+
+#data
+<!doctype html><head></head><title>X</title>
+#errors
+(1,35): unexpected-start-tag-out-of-my-head
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <title>
+| "X"
+| <body>
+
+#data
+<!doctype html></head><title>X</title>
+#errors
+(1,29): unexpected-start-tag-out-of-my-head
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <title>
+| "X"
+| <body>
+
+#data
+<!doctype html><table><meta></table>
+#errors
+(1,28): unexpected-start-tag-implies-table-voodoo
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <meta>
+| <table>
+
+#data
+<!doctype html><table>X<tr><td><table> <meta></table></table>
+#errors
+unexpected text in table
+(1,45): unexpected-start-tag-implies-table-voodoo
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "X"
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <meta>
+| <table>
+| " "
+
+#data
+<!doctype html><html> <head>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+
+#data
+<!doctype html> <head>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+
+#data
+<!doctype html><table><style> <tr>x </style> </table>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <style>
+| " <tr>x "
+| " "
+
+#data
+<!doctype html><table><TBODY><script> <tr>x </script> </table>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <script>
+| " <tr>x "
+| " "
+
+#data
+<!doctype html><p><applet><p>X</p></applet>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <p>
+| <applet>
+| <p>
+| "X"
+
+#data
+<!doctype html><listing>
+X</listing>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <listing>
+| "X"
+
+#data
+<!doctype html><select><input>X
+#errors
+(1,30): unexpected-input-in-select
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| <input>
+| "X"
+
+#data
+<!doctype html><select><select>X
+#errors
+(1,31): unexpected-select-in-select
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| "X"
+
+#data
+<!doctype html><table><input type=hidDEN></table>
+#errors
+(1,41): unexpected-hidden-input-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <input>
+| type="hidDEN"
+
+#data
+<!doctype html><table>X<input type=hidDEN></table>
+#errors
+(1,23): foster-parenting-character
+(1,42): unexpected-hidden-input-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| "X"
+| <table>
+| <input>
+| type="hidDEN"
+
+#data
+<!doctype html><table> <input type=hidDEN></table>
+#errors
+(1,43): unexpected-hidden-input-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| " "
+| <input>
+| type="hidDEN"
+
+#data
+<!doctype html><table> <input type='hidDEN'></table>
+#errors
+(1,45): unexpected-hidden-input-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| " "
+| <input>
+| type="hidDEN"
+
+#data
+<!doctype html><table><input type=" hidden"><input type=hidDEN></table>
+#errors
+(1,44): unexpected-start-tag-implies-table-voodoo
+(1,63): unexpected-hidden-input-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <input>
+| type=" hidden"
+| <table>
+| <input>
+| type="hidDEN"
+
+#data
+<!doctype html><table><select>X<tr>
+#errors
+(1,30): unexpected-start-tag-implies-table-voodoo
+(1,35): unexpected-table-element-start-tag-in-select-in-table
+(1,35): eof-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| "X"
+| <table>
+| <tbody>
+| <tr>
+
+#data
+<!doctype html><select>X</select>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| "X"
+
+#data
+<!DOCTYPE hTmL><html></html>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+
+#data
+<!DOCTYPE HTML><html></html>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+
+#data
+<body>X</body></body>
+#errors
+(1,21): unexpected-end-tag-after-body
+#document-fragment
+html
+#document
+| <head>
+| <body>
+| "X"
+
+#data
+<div><p>a</x> b
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,13): unexpected-end-tag
+(1,15): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| <p>
+| "a b"
+
+#data
+<table><tr><td><code></code> </table>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <code>
+| " "
+
+#data
+<table><b><tr><td>aaa</td></tr>bbb</table>ccc
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,10): foster-parenting-start-tag
+(1,32): foster-parenting-character
+(1,33): foster-parenting-character
+(1,34): foster-parenting-character
+(1,45): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| <b>
+| "bbb"
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| "aaa"
+| <b>
+| "ccc"
+
+#data
+A<table><tr> B</tr> B</table>
+#errors
+(1,1): expected-doctype-but-got-chars
+(1,13): foster-parenting-character
+(1,14): foster-parenting-character
+(1,20): foster-parenting-character
+(1,21): foster-parenting-character
+#document
+| <html>
+| <head>
+| <body>
+| "A B B"
+| <table>
+| <tbody>
+| <tr>
+
+#data
+A<table><tr> B</tr> </em>C</table>
+#errors
+(1,1): expected-doctype-but-got-chars
+(1,13): foster-parenting-character
+(1,14): foster-parenting-character
+(1,20): foster-parenting-character
+(1,25): unexpected-end-tag
+(1,26): foster-parenting-character
+#document
+| <html>
+| <head>
+| <body>
+| "A BC"
+| <table>
+| <tbody>
+| <tr>
+| " "
+
+#data
+<select><keygen>
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,16): unexpected-input-in-select
+#document
+| <html>
+| <head>
+| <body>
+| <select>
+| <keygen>
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests8.dat b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests8.dat
new file mode 100644
index 00000000000..33dd96d3320
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests8.dat
@@ -0,0 +1,151 @@
+#data
+<div>
+<div></div>
+</span>x
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(3,7): unexpected-end-tag
+(3,8): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| "
+"
+| <div>
+| "
+x"
+
+#data
+<div>x<div></div>
+</span>x
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(2,7): unexpected-end-tag
+(2,8): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| "x"
+| <div>
+| "
+x"
+
+#data
+<div>x<div></div>x</span>x
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,25): unexpected-end-tag
+(1,26): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| "x"
+| <div>
+| "xx"
+
+#data
+<div>x<div></div>y</span>z
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,25): unexpected-end-tag
+(1,26): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| "x"
+| <div>
+| "yz"
+
+#data
+<table><div>x<div></div>x</span>x
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,12): foster-parenting-start-tag
+(1,13): foster-parenting-character
+(1,18): foster-parenting-start-tag
+(1,24): foster-parenting-end-tag
+(1,25): foster-parenting-start-tag
+(1,32): foster-parenting-end-tag
+(1,32): unexpected-end-tag
+(1,33): foster-parenting-character
+(1,33): eof-in-table
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| "x"
+| <div>
+| "xx"
+| <table>
+
+#data
+x<table>x
+#errors
+(1,1): expected-doctype-but-got-chars
+(1,9): foster-parenting-character
+(1,9): eof-in-table
+#document
+| <html>
+| <head>
+| <body>
+| "xx"
+| <table>
+
+#data
+x<table><table>x
+#errors
+(1,1): expected-doctype-but-got-chars
+(1,15): unexpected-start-tag-implies-end-tag
+(1,16): foster-parenting-character
+(1,16): eof-in-table
+#document
+| <html>
+| <head>
+| <body>
+| "x"
+| <table>
+| "x"
+| <table>
+
+#data
+<b>a<div></div><div></b>y
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,24): adoption-agency-1.3
+(1,25): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| "a"
+| <div>
+| <div>
+| <b>
+| "y"
+
+#data
+<a><div><p></a>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,15): adoption-agency-1.3
+(1,15): adoption-agency-1.3
+(1,15): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| <div>
+| <a>
+| <p>
+| <a>
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests9.dat b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests9.dat
new file mode 100644
index 00000000000..f8d04b23bc0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests9.dat
@@ -0,0 +1,472 @@
+#data
+<!DOCTYPE html><math></math>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <math math>
+
+#data
+<!DOCTYPE html><body><math></math>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <math math>
+
+#data
+<!DOCTYPE html><math><mi>
+#errors
+(1,25) expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mi>
+
+#data
+<!DOCTYPE html><math><annotation-xml><svg><u>
+#errors
+(1,45) unexpected-html-element-in-foreign-content
+(1,45) expected-closing-tag-but-got-eof
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math annotation-xml>
+| <svg svg>
+| <u>
+
+#data
+<!DOCTYPE html><body><select><math></math></select>
+#errors
+(1,35) unexpected-start-tag-in-select
+(1,42) unexpected-end-tag-in-select
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+
+#data
+<!DOCTYPE html><body><select><option><math></math></option></select>
+#errors
+(1,43) unexpected-start-tag-in-select
+(1,50) unexpected-end-tag-in-select
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| <option>
+
+#data
+<!DOCTYPE html><body><table><math></math></table>
+#errors
+(1,34) unexpected-start-tag-implies-table-voodoo
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <math math>
+| <table>
+
+#data
+<!DOCTYPE html><body><table><math><mi>foo</mi></math></table>
+#errors
+(1,34) foster-parenting-start-token
+(1,39) foster-parenting-character
+(1,40) foster-parenting-character
+(1,41) foster-parenting-character
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mi>
+| "foo"
+| <table>
+
+#data
+<!DOCTYPE html><body><table><math><mi>foo</mi><mi>bar</mi></math></table>
+#errors
+(1,34) foster-parenting-start-tag
+(1,39) foster-parenting-character
+(1,40) foster-parenting-character
+(1,41) foster-parenting-character
+(1,51) foster-parenting-character
+(1,52) foster-parenting-character
+(1,53) foster-parenting-character
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mi>
+| "foo"
+| <math mi>
+| "bar"
+| <table>
+
+#data
+<!DOCTYPE html><body><table><tbody><math><mi>foo</mi><mi>bar</mi></math></tbody></table>
+#errors
+(1,41) foster-parenting-start-tag
+(1,46) foster-parenting-character
+(1,47) foster-parenting-character
+(1,48) foster-parenting-character
+(1,58) foster-parenting-character
+(1,59) foster-parenting-character
+(1,60) foster-parenting-character
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mi>
+| "foo"
+| <math mi>
+| "bar"
+| <table>
+| <tbody>
+
+#data
+<!DOCTYPE html><body><table><tbody><tr><math><mi>foo</mi><mi>bar</mi></math></tr></tbody></table>
+#errors
+(1,45) foster-parenting-start-tag
+(1,50) foster-parenting-character
+(1,51) foster-parenting-character
+(1,52) foster-parenting-character
+(1,62) foster-parenting-character
+(1,63) foster-parenting-character
+(1,64) foster-parenting-character
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mi>
+| "foo"
+| <math mi>
+| "bar"
+| <table>
+| <tbody>
+| <tr>
+
+#data
+<!DOCTYPE html><body><table><tbody><tr><td><math><mi>foo</mi><mi>bar</mi></math></td></tr></tbody></table>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <math math>
+| <math mi>
+| "foo"
+| <math mi>
+| "bar"
+
+#data
+<!DOCTYPE html><body><table><tbody><tr><td><math><mi>foo</mi><mi>bar</mi></math><p>baz</td></tr></tbody></table>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <math math>
+| <math mi>
+| "foo"
+| <math mi>
+| "bar"
+| <p>
+| "baz"
+
+#data
+<!DOCTYPE html><body><table><caption><math><mi>foo</mi><mi>bar</mi></math><p>baz</caption></table>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <caption>
+| <math math>
+| <math mi>
+| "foo"
+| <math mi>
+| "bar"
+| <p>
+| "baz"
+
+#data
+<!DOCTYPE html><body><table><caption><math><mi>foo</mi><mi>bar</mi><p>baz</table><p>quux
+#errors
+(1,70) unexpected-html-element-in-foreign-content
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <caption>
+| <math math>
+| <math mi>
+| "foo"
+| <math mi>
+| "bar"
+| <p>
+| "baz"
+| <p>
+| "quux"
+
+#data
+<!DOCTYPE html><body><table><caption><math><mi>foo</mi><mi>bar</mi>baz</table><p>quux
+#errors
+(1,78) unexpected-end-tag
+(1,78) expected-one-end-tag-but-got-another
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <caption>
+| <math math>
+| <math mi>
+| "foo"
+| <math mi>
+| "bar"
+| "baz"
+| <p>
+| "quux"
+
+#data
+<!DOCTYPE html><body><table><colgroup><math><mi>foo</mi><mi>bar</mi><p>baz</table><p>quux
+#errors
+(1,44) foster-parenting-start-tag
+(1,49) foster-parenting-character
+(1,50) foster-parenting-character
+(1,51) foster-parenting-character
+(1,61) foster-parenting-character
+(1,62) foster-parenting-character
+(1,63) foster-parenting-character
+(1,71) unexpected-html-element-in-foreign-content
+(1,71) foster-parenting-start-tag
+(1,63) foster-parenting-character
+(1,63) foster-parenting-character
+(1,63) foster-parenting-character
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mi>
+| "foo"
+| <math mi>
+| "bar"
+| <p>
+| "baz"
+| <table>
+| <colgroup>
+| <p>
+| "quux"
+
+#data
+<!DOCTYPE html><body><table><tr><td><select><math><mi>foo</mi><mi>bar</mi><p>baz</table><p>quux
+#errors
+(1,50) unexpected-start-tag-in-select
+(1,54) unexpected-start-tag-in-select
+(1,62) unexpected-end-tag-in-select
+(1,66) unexpected-start-tag-in-select
+(1,74) unexpected-end-tag-in-select
+(1,77) unexpected-start-tag-in-select
+(1,88) unexpected-table-element-end-tag-in-select-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <select>
+| "foobarbaz"
+| <p>
+| "quux"
+
+#data
+<!DOCTYPE html><body><table><select><math><mi>foo</mi><mi>bar</mi><p>baz</table><p>quux
+#errors
+(1,36) unexpected-start-tag-implies-table-voodoo
+(1,42) unexpected-start-tag-in-select
+(1,46) unexpected-start-tag-in-select
+(1,54) unexpected-end-tag-in-select
+(1,58) unexpected-start-tag-in-select
+(1,66) unexpected-end-tag-in-select
+(1,69) unexpected-start-tag-in-select
+(1,80) unexpected-table-element-end-tag-in-select-in-table
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <select>
+| "foobarbaz"
+| <table>
+| <p>
+| "quux"
+
+#data
+<!DOCTYPE html><body></body></html><math><mi>foo</mi><mi>bar</mi><p>baz
+#errors
+(1,41) expected-eof-but-got-start-tag
+(1,68) unexpected-html-element-in-foreign-content
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mi>
+| "foo"
+| <math mi>
+| "bar"
+| <p>
+| "baz"
+
+#data
+<!DOCTYPE html><body></body><math><mi>foo</mi><mi>bar</mi><p>baz
+#errors
+(1,34) unexpected-start-tag-after-body
+(1,61) unexpected-html-element-in-foreign-content
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mi>
+| "foo"
+| <math mi>
+| "bar"
+| <p>
+| "baz"
+
+#data
+<!DOCTYPE html><frameset><math><mi></mi><mi></mi><p><span>
+#errors
+(1,31) unexpected-start-tag-in-frameset
+(1,35) unexpected-start-tag-in-frameset
+(1,40) unexpected-end-tag-in-frameset
+(1,44) unexpected-start-tag-in-frameset
+(1,49) unexpected-end-tag-in-frameset
+(1,52) unexpected-start-tag-in-frameset
+(1,58) unexpected-start-tag-in-frameset
+(1,58) eof-in-frameset
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+
+#data
+<!DOCTYPE html><frameset></frameset><math><mi></mi><mi></mi><p><span>
+#errors
+(1,42) unexpected-start-tag-after-frameset
+(1,46) unexpected-start-tag-after-frameset
+(1,51) unexpected-end-tag-after-frameset
+(1,55) unexpected-start-tag-after-frameset
+(1,60) unexpected-end-tag-after-frameset
+(1,63) unexpected-start-tag-after-frameset
+(1,69) unexpected-start-tag-after-frameset
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+
+#data
+<!DOCTYPE html><body xlink:href=foo><math xlink:href=foo></math>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| xlink:href="foo"
+| <math math>
+| xlink href="foo"
+
+#data
+<!DOCTYPE html><body xlink:href=foo xml:lang=en><math><mi xml:lang=en xlink:href=foo></mi></math>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| xlink:href="foo"
+| xml:lang="en"
+| <math math>
+| <math mi>
+| xlink href="foo"
+| xml lang="en"
+
+#data
+<!DOCTYPE html><body xlink:href=foo xml:lang=en><math><mi xml:lang=en xlink:href=foo /></math>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| xlink:href="foo"
+| xml:lang="en"
+| <math math>
+| <math mi>
+| xlink href="foo"
+| xml lang="en"
+
+#data
+<!DOCTYPE html><body xlink:href=foo xml:lang=en><math><mi xml:lang=en xlink:href=foo />bar</math>
+#errors
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| xlink:href="foo"
+| xml:lang="en"
+| <math math>
+| <math mi>
+| xlink href="foo"
+| xml lang="en"
+| "bar"
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests_innerHTML_1.dat b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests_innerHTML_1.dat
new file mode 100644
index 00000000000..9c5c18220d9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tests_innerHTML_1.dat
@@ -0,0 +1,891 @@
+#data
+<body><span>
+#errors
+(1,6): unexpected-start-tag
+(1,12): expected-closing-tag-but-got-eof
+#document-fragment
+body
+#document
+| <span>
+
+#data
+<span><body>
+#errors
+(1,12): unexpected-start-tag
+(1,12): expected-closing-tag-but-got-eof
+#document-fragment
+body
+#document
+| <span>
+
+#data
+<span><body>
+#errors
+(1,12): unexpected-start-tag
+(1,12): expected-closing-tag-but-got-eof
+#document-fragment
+div
+#document
+| <span>
+
+#data
+<body><span>
+#errors
+(1,12): expected-closing-tag-but-got-eof
+#document-fragment
+html
+#document
+| <head>
+| <body>
+| <span>
+
+#data
+<frameset><span>
+#errors
+(1,10): unexpected-start-tag
+(1,16): expected-closing-tag-but-got-eof
+#document-fragment
+body
+#document
+| <span>
+
+#data
+<span><frameset>
+#errors
+(1,16): unexpected-start-tag
+(1,16): expected-closing-tag-but-got-eof
+#document-fragment
+body
+#document
+| <span>
+
+#data
+<span><frameset>
+#errors
+(1,16): unexpected-start-tag
+(1,16): expected-closing-tag-but-got-eof
+#document-fragment
+div
+#document
+| <span>
+
+#data
+<frameset><span>
+#errors
+(1,16): unexpected-start-tag-in-frameset
+(1,16): eof-in-frameset
+#document-fragment
+html
+#document
+| <head>
+| <frameset>
+
+#data
+<table><tr>
+#errors
+(1,7): unexpected-start-tag
+#document-fragment
+table
+#document
+| <tbody>
+| <tr>
+
+#data
+</table><tr>
+#errors
+(1,8): unexpected-end-tag
+#document-fragment
+table
+#document
+| <tbody>
+| <tr>
+
+#data
+<a>
+#errors
+(1,3): unexpected-start-tag-implies-table-voodoo
+(1,3): eof-in-table
+#document-fragment
+table
+#document
+| <a>
+
+#data
+<a>
+#errors
+(1,3): unexpected-start-tag-implies-table-voodoo
+(1,3): eof-in-table
+#document-fragment
+table
+#document
+| <a>
+
+#data
+<a><caption>a
+#errors
+(1,3): unexpected-start-tag-implies-table-voodoo
+(1,13): expected-closing-tag-but-got-eof
+#document-fragment
+table
+#document
+| <a>
+| <caption>
+| "a"
+
+#data
+<a><colgroup><col>
+#errors
+(1,3): foster-parenting-start-token
+(1,18): expected-closing-tag-but-got-eof
+#document-fragment
+table
+#document
+| <a>
+| <colgroup>
+| <col>
+
+#data
+<a><tbody><tr>
+#errors
+(1,3): foster-parenting-start-tag
+#document-fragment
+table
+#document
+| <a>
+| <tbody>
+| <tr>
+
+#data
+<a><tfoot><tr>
+#errors
+(1,3): foster-parenting-start-tag
+#document-fragment
+table
+#document
+| <a>
+| <tfoot>
+| <tr>
+
+#data
+<a><thead><tr>
+#errors
+(1,3): foster-parenting-start-tag
+#document-fragment
+table
+#document
+| <a>
+| <thead>
+| <tr>
+
+#data
+<a><tr>
+#errors
+(1,3): foster-parenting-start-tag
+#document-fragment
+table
+#document
+| <a>
+| <tbody>
+| <tr>
+
+#data
+<a><th>
+#errors
+(1,3): unexpected-start-tag-implies-table-voodoo
+(1,7): unexpected-cell-in-table-body
+#document-fragment
+table
+#document
+| <a>
+| <tbody>
+| <tr>
+| <th>
+
+#data
+<a><td>
+#errors
+(1,3): unexpected-start-tag-implies-table-voodoo
+(1,7): unexpected-cell-in-table-body
+#document-fragment
+table
+#document
+| <a>
+| <tbody>
+| <tr>
+| <td>
+
+#data
+<table></table><tbody>
+#errors
+(1,22): unexpected-start-tag
+#document-fragment
+caption
+#document
+| <table>
+
+#data
+</table><span>
+#errors
+(1,8): unexpected-end-tag
+(1,14): expected-closing-tag-but-got-eof
+#document-fragment
+caption
+#document
+| <span>
+
+#data
+<span></table>
+#errors
+(1,14): unexpected-end-tag
+(1,14): expected-closing-tag-but-got-eof
+#document-fragment
+caption
+#document
+| <span>
+
+#data
+</caption><span>
+#errors
+(1,10): XXX-undefined-error
+(1,16): expected-closing-tag-but-got-eof
+#document-fragment
+caption
+#document
+| <span>
+
+#data
+<span></caption><span>
+#errors
+(1,16): XXX-undefined-error
+(1,22): expected-closing-tag-but-got-eof
+#document-fragment
+caption
+#document
+| <span>
+| <span>
+
+#data
+<span><caption><span>
+#errors
+(1,15): unexpected-start-tag
+(1,21): expected-closing-tag-but-got-eof
+#document-fragment
+caption
+#document
+| <span>
+| <span>
+
+#data
+<span><col><span>
+#errors
+(1,11): unexpected-start-tag
+(1,17): expected-closing-tag-but-got-eof
+#document-fragment
+caption
+#document
+| <span>
+| <span>
+
+#data
+<span><colgroup><span>
+#errors
+(1,16): unexpected-start-tag
+(1,22): expected-closing-tag-but-got-eof
+#document-fragment
+caption
+#document
+| <span>
+| <span>
+
+#data
+<span><html><span>
+#errors
+(1,12): non-html-root
+(1,18): expected-closing-tag-but-got-eof
+#document-fragment
+caption
+#document
+| <span>
+| <span>
+
+#data
+<span><tbody><span>
+#errors
+(1,13): unexpected-start-tag
+(1,19): expected-closing-tag-but-got-eof
+#document-fragment
+caption
+#document
+| <span>
+| <span>
+
+#data
+<span><td><span>
+#errors
+(1,10): unexpected-start-tag
+(1,16): expected-closing-tag-but-got-eof
+#document-fragment
+caption
+#document
+| <span>
+| <span>
+
+#data
+<span><tfoot><span>
+#errors
+(1,13): unexpected-start-tag
+(1,19): expected-closing-tag-but-got-eof
+#document-fragment
+caption
+#document
+| <span>
+| <span>
+
+#data
+<span><thead><span>
+#errors
+(1,13): unexpected-start-tag
+(1,19): expected-closing-tag-but-got-eof
+#document-fragment
+caption
+#document
+| <span>
+| <span>
+
+#data
+<span><th><span>
+#errors
+(1,10): unexpected-start-tag
+(1,16): expected-closing-tag-but-got-eof
+#document-fragment
+caption
+#document
+| <span>
+| <span>
+
+#data
+<span><tr><span>
+#errors
+(1,10): unexpected-start-tag
+(1,16): expected-closing-tag-but-got-eof
+#document-fragment
+caption
+#document
+| <span>
+| <span>
+
+#data
+<span></table><span>
+#errors
+(1,14): unexpected-end-tag
+(1,20): expected-closing-tag-but-got-eof
+#document-fragment
+caption
+#document
+| <span>
+| <span>
+
+#data
+</colgroup><col>
+#errors
+(1,11): XXX-undefined-error
+#document-fragment
+colgroup
+#document
+| <col>
+
+#data
+<a><col>
+#errors
+(1,3): XXX-undefined-error
+#document-fragment
+colgroup
+#document
+| <col>
+
+#data
+<caption><a>
+#errors
+(1,9): XXX-undefined-error
+(1,12): unexpected-start-tag-implies-table-voodoo
+(1,12): eof-in-table
+#document-fragment
+tbody
+#document
+| <a>
+
+#data
+<col><a>
+#errors
+(1,5): XXX-undefined-error
+(1,8): unexpected-start-tag-implies-table-voodoo
+(1,8): eof-in-table
+#document-fragment
+tbody
+#document
+| <a>
+
+#data
+<colgroup><a>
+#errors
+(1,10): XXX-undefined-error
+(1,13): unexpected-start-tag-implies-table-voodoo
+(1,13): eof-in-table
+#document-fragment
+tbody
+#document
+| <a>
+
+#data
+<tbody><a>
+#errors
+(1,7): XXX-undefined-error
+(1,10): unexpected-start-tag-implies-table-voodoo
+(1,10): eof-in-table
+#document-fragment
+tbody
+#document
+| <a>
+
+#data
+<tfoot><a>
+#errors
+(1,7): XXX-undefined-error
+(1,10): unexpected-start-tag-implies-table-voodoo
+(1,10): eof-in-table
+#document-fragment
+tbody
+#document
+| <a>
+
+#data
+<thead><a>
+#errors
+(1,7): XXX-undefined-error
+(1,10): unexpected-start-tag-implies-table-voodoo
+(1,10): eof-in-table
+#document-fragment
+tbody
+#document
+| <a>
+
+#data
+</table><a>
+#errors
+(1,8): XXX-undefined-error
+(1,11): unexpected-start-tag-implies-table-voodoo
+(1,11): eof-in-table
+#document-fragment
+tbody
+#document
+| <a>
+
+#data
+<a><tr>
+#errors
+(1,3): unexpected-start-tag-implies-table-voodoo
+#document-fragment
+tbody
+#document
+| <a>
+| <tr>
+
+#data
+<a><td>
+#errors
+(1,3): unexpected-start-tag-implies-table-voodoo
+(1,7): unexpected-cell-in-table-body
+#document-fragment
+tbody
+#document
+| <a>
+| <tr>
+| <td>
+
+#data
+<a><td>
+#errors
+(1,3): unexpected-start-tag-implies-table-voodoo
+(1,7): unexpected-cell-in-table-body
+#document-fragment
+tbody
+#document
+| <a>
+| <tr>
+| <td>
+
+#data
+<a><td>
+#errors
+(1,3): unexpected-start-tag-implies-table-voodoo
+(1,7): unexpected-cell-in-table-body
+#document-fragment
+tbody
+#document
+| <a>
+| <tr>
+| <td>
+
+#data
+<td><table><tbody><a><tr>
+#errors
+(1,4): unexpected-cell-in-table-body
+(1,21): unexpected-start-tag-implies-table-voodoo
+(1,25): eof-in-table
+#document-fragment
+tbody
+#document
+| <tr>
+| <td>
+| <a>
+| <table>
+| <tbody>
+| <tr>
+
+#data
+</tr><td>
+#errors
+(1,5): XXX-undefined-error
+#document-fragment
+tr
+#document
+| <td>
+
+#data
+<td><table><a><tr></tr><tr>
+#errors
+(1,14): unexpected-start-tag-implies-table-voodoo
+(1,27): eof-in-table
+#document-fragment
+tr
+#document
+| <td>
+| <a>
+| <table>
+| <tbody>
+| <tr>
+| <tr>
+
+#data
+<caption><td>
+#errors
+(1,9): XXX-undefined-error
+#document-fragment
+tr
+#document
+| <td>
+
+#data
+<col><td>
+#errors
+(1,5): XXX-undefined-error
+#document-fragment
+tr
+#document
+| <td>
+
+#data
+<colgroup><td>
+#errors
+(1,10): XXX-undefined-error
+#document-fragment
+tr
+#document
+| <td>
+
+#data
+<tbody><td>
+#errors
+(1,7): XXX-undefined-error
+#document-fragment
+tr
+#document
+| <td>
+
+#data
+<tfoot><td>
+#errors
+(1,7): XXX-undefined-error
+#document-fragment
+tr
+#document
+| <td>
+
+#data
+<thead><td>
+#errors
+(1,7): XXX-undefined-error
+#document-fragment
+tr
+#document
+| <td>
+
+#data
+<tr><td>
+#errors
+(1,4): XXX-undefined-error
+#document-fragment
+tr
+#document
+| <td>
+
+#data
+</table><td>
+#errors
+(1,8): XXX-undefined-error
+#document-fragment
+tr
+#document
+| <td>
+
+#data
+<td><table></table><td>
+#errors
+#document-fragment
+tr
+#document
+| <td>
+| <table>
+| <td>
+
+#data
+<td><table></table><td>
+#errors
+#document-fragment
+tr
+#document
+| <td>
+| <table>
+| <td>
+
+#data
+<caption><a>
+#errors
+(1,9): XXX-undefined-error
+(1,12): expected-closing-tag-but-got-eof
+#document-fragment
+td
+#document
+| <a>
+
+#data
+<col><a>
+#errors
+(1,5): XXX-undefined-error
+(1,8): expected-closing-tag-but-got-eof
+#document-fragment
+td
+#document
+| <a>
+
+#data
+<colgroup><a>
+#errors
+(1,10): XXX-undefined-error
+(1,13): expected-closing-tag-but-got-eof
+#document-fragment
+td
+#document
+| <a>
+
+#data
+<tbody><a>
+#errors
+(1,7): XXX-undefined-error
+(1,10): expected-closing-tag-but-got-eof
+#document-fragment
+td
+#document
+| <a>
+
+#data
+<tfoot><a>
+#errors
+(1,7): XXX-undefined-error
+(1,10): expected-closing-tag-but-got-eof
+#document-fragment
+td
+#document
+| <a>
+
+#data
+<th><a>
+#errors
+(1,4): XXX-undefined-error
+(1,7): expected-closing-tag-but-got-eof
+#document-fragment
+td
+#document
+| <a>
+
+#data
+<thead><a>
+#errors
+(1,7): XXX-undefined-error
+(1,10): expected-closing-tag-but-got-eof
+#document-fragment
+td
+#document
+| <a>
+
+#data
+<tr><a>
+#errors
+(1,4): XXX-undefined-error
+(1,7): expected-closing-tag-but-got-eof
+#document-fragment
+td
+#document
+| <a>
+
+#data
+</table><a>
+#errors
+(1,8): XXX-undefined-error
+(1,11): expected-closing-tag-but-got-eof
+#document-fragment
+td
+#document
+| <a>
+
+#data
+</tbody><a>
+#errors
+(1,8): XXX-undefined-error
+(1,11): expected-closing-tag-but-got-eof
+#document-fragment
+td
+#document
+| <a>
+
+#data
+</td><a>
+#errors
+(1,5): unexpected-end-tag
+(1,8): expected-closing-tag-but-got-eof
+#document-fragment
+td
+#document
+| <a>
+
+#data
+</tfoot><a>
+#errors
+(1,8): XXX-undefined-error
+(1,11): expected-closing-tag-but-got-eof
+#document-fragment
+td
+#document
+| <a>
+
+#data
+</thead><a>
+#errors
+(1,8): XXX-undefined-error
+(1,11): expected-closing-tag-but-got-eof
+#document-fragment
+td
+#document
+| <a>
+
+#data
+</th><a>
+#errors
+(1,5): unexpected-end-tag
+(1,8): expected-closing-tag-but-got-eof
+#document-fragment
+td
+#document
+| <a>
+
+#data
+</tr><a>
+#errors
+(1,5): XXX-undefined-error
+(1,8): expected-closing-tag-but-got-eof
+#document-fragment
+td
+#document
+| <a>
+
+#data
+<table><td><td>
+#errors
+(1,11): unexpected-cell-in-table-body
+(1,15): expected-closing-tag-but-got-eof
+#document-fragment
+td
+#document
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| <td>
+
+#data
+</select><option>
+#errors
+(1,9): XXX-undefined-error
+(1,17): eof-in-select
+#document-fragment
+select
+#document
+| <option>
+
+#data
+<input><option>
+#errors
+(1,7): unexpected-input-in-select
+(1,15): eof-in-select
+#document-fragment
+select
+#document
+| <option>
+
+#data
+<keygen><option>
+#errors
+(1,8): unexpected-input-in-select
+(1,16): eof-in-select
+#document-fragment
+select
+#document
+| <option>
+
+#data
+<textarea><option>
+#errors
+(1,10): unexpected-input-in-select
+(1,18): eof-in-select
+#document-fragment
+select
+#document
+| <option>
+
+#data
+</html><!--abc-->
+#errors
+(1,7): unexpected-end-tag-after-body-innerhtml
+#document-fragment
+html
+#document
+| <head>
+| <body>
+| <!-- abc -->
+
+#data
+</frameset><frame>
+#errors
+(1,11): unexpected-frameset-in-frameset-innerhtml
+#document-fragment
+frameset
+#document
+| <frame>
+
+#data
+#errors
+#document-fragment
+html
+#document
+| <head>
+| <body>
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tricky01.dat b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tricky01.dat
new file mode 100644
index 00000000000..753502a2619
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/tricky01.dat
@@ -0,0 +1,336 @@
+#data
+<b><p>Bold </b> Not bold</p>
+Also not bold.
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,15): adoption-agency-1.3
+#document
+| <html>
+| <head>
+| <body>
+| <b>
+| <p>
+| <b>
+| "Bold "
+| " Not bold"
+| "
+Also not bold."
+
+#data
+<html>
+<font color=red><i>Italic and Red<p>Italic and Red </font> Just italic.</p> Italic only.</i> Plain
+<p>I should not be red. <font color=red>Red. <i>Italic and red.</p>
+<p>Italic and red. </i> Red.</font> I should not be red.</p>
+<b>Bold <i>Bold and italic</b> Only Italic </i> Plain
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(2,58): adoption-agency-1.3
+(3,67): unexpected-end-tag
+(4,23): adoption-agency-1.3
+(4,35): adoption-agency-1.3
+(5,30): adoption-agency-1.3
+#document
+| <html>
+| <head>
+| <body>
+| <font>
+| color="red"
+| <i>
+| "Italic and Red"
+| <i>
+| <p>
+| <font>
+| color="red"
+| "Italic and Red "
+| " Just italic."
+| " Italic only."
+| " Plain
+"
+| <p>
+| "I should not be red. "
+| <font>
+| color="red"
+| "Red. "
+| <i>
+| "Italic and red."
+| <font>
+| color="red"
+| <i>
+| "
+"
+| <p>
+| <font>
+| color="red"
+| <i>
+| "Italic and red. "
+| " Red."
+| " I should not be red."
+| "
+"
+| <b>
+| "Bold "
+| <i>
+| "Bold and italic"
+| <i>
+| " Only Italic "
+| " Plain"
+
+#data
+<html><body>
+<p><font size="7">First paragraph.</p>
+<p>Second paragraph.</p></font>
+<b><p><i>Bold and Italic</b> Italic</p>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(2,38): unexpected-end-tag
+(4,28): adoption-agency-1.3
+(4,28): adoption-agency-1.3
+(4,39): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <body>
+| "
+"
+| <p>
+| <font>
+| size="7"
+| "First paragraph."
+| <font>
+| size="7"
+| "
+"
+| <p>
+| "Second paragraph."
+| "
+"
+| <b>
+| <p>
+| <b>
+| <i>
+| "Bold and Italic"
+| <i>
+| " Italic"
+
+#data
+<html>
+<dl>
+<dt><b>Boo
+<dd>Goo?
+</dl>
+</html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(4,4): end-tag-too-early
+(5,5): end-tag-too-early
+(6,7): expected-one-end-tag-but-got-another
+#document
+| <html>
+| <head>
+| <body>
+| <dl>
+| "
+"
+| <dt>
+| <b>
+| "Boo
+"
+| <dd>
+| <b>
+| "Goo?
+"
+| <b>
+| "
+"
+
+#data
+<html><body>
+<label><a><div>Hello<div>World</div></a></label>
+</body></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(2,40): adoption-agency-1.3
+(2,48): unexpected-end-tag
+(3,7): expected-one-end-tag-but-got-another
+#document
+| <html>
+| <head>
+| <body>
+| "
+"
+| <label>
+| <a>
+| <div>
+| <a>
+| "Hello"
+| <div>
+| "World"
+| "
+"
+
+#data
+<table><center> <font>a</center> <img> <tr><td> </td> </tr> </table>
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,15): foster-parenting-start-tag
+(1,16): foster-parenting-character
+(1,22): foster-parenting-start-tag
+(1,23): foster-parenting-character
+(1,32): foster-parenting-end-tag
+(1,32): end-tag-too-early
+(1,33): foster-parenting-character
+(1,38): foster-parenting-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <center>
+| " "
+| <font>
+| "a"
+| <font>
+| <img>
+| " "
+| <table>
+| " "
+| <tbody>
+| <tr>
+| <td>
+| " "
+| " "
+| " "
+
+#data
+<table><tr><p><a><p>You should see this text.
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,14): unexpected-start-tag-implies-table-voodoo
+(1,17): unexpected-start-tag-implies-table-voodoo
+(1,20): unexpected-start-tag-implies-table-voodoo
+(1,20): closing-non-current-p-element
+(1,21): foster-parenting-character
+(1,22): foster-parenting-character
+(1,23): foster-parenting-character
+(1,24): foster-parenting-character
+(1,25): foster-parenting-character
+(1,26): foster-parenting-character
+(1,27): foster-parenting-character
+(1,28): foster-parenting-character
+(1,29): foster-parenting-character
+(1,30): foster-parenting-character
+(1,31): foster-parenting-character
+(1,32): foster-parenting-character
+(1,33): foster-parenting-character
+(1,34): foster-parenting-character
+(1,35): foster-parenting-character
+(1,36): foster-parenting-character
+(1,37): foster-parenting-character
+(1,38): foster-parenting-character
+(1,39): foster-parenting-character
+(1,40): foster-parenting-character
+(1,41): foster-parenting-character
+(1,42): foster-parenting-character
+(1,43): foster-parenting-character
+(1,44): foster-parenting-character
+(1,45): foster-parenting-character
+(1,45): eof-in-table
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| <a>
+| <p>
+| <a>
+| "You should see this text."
+| <table>
+| <tbody>
+| <tr>
+
+#data
+<TABLE>
+<TR>
+<CENTER><CENTER><TD></TD></TR><TR>
+<FONT>
+<TABLE><tr></tr></TABLE>
+</P>
+<a></font><font></a>
+This page contains an insanely badly-nested tag sequence.
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(3,8): unexpected-start-tag-implies-table-voodoo
+(3,16): unexpected-start-tag-implies-table-voodoo
+(4,6): unexpected-start-tag-implies-table-voodoo
+(4,6): unexpected character token in table (the newline)
+(5,7): unexpected-start-tag-implies-end-tag
+(6,4): unexpected p end tag
+(7,10): adoption-agency-1.3
+(7,20): adoption-agency-1.3
+(8,57): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <center>
+| <center>
+| <font>
+| "
+"
+| <table>
+| "
+"
+| <tbody>
+| <tr>
+| "
+"
+| <td>
+| <tr>
+| "
+"
+| <table>
+| <tbody>
+| <tr>
+| <font>
+| "
+"
+| <p>
+| "
+"
+| <a>
+| <a>
+| <font>
+| <font>
+| "
+This page contains an insanely badly-nested tag sequence."
+
+#data
+<html>
+<body>
+<b><nobr><div>This text is in a div inside a nobr</nobr>More text that should not be in the nobr, i.e., the
+nobr should have closed the div inside it implicitly. </b><pre>A pre tag outside everything else.</pre>
+</body>
+</html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(3,56): adoption-agency-1.3
+(4,58): adoption-agency-1.3
+(5,7): expected-one-end-tag-but-got-another
+#document
+| <html>
+| <head>
+| <body>
+| "
+"
+| <b>
+| <nobr>
+| <div>
+| <b>
+| <nobr>
+| "This text is in a div inside a nobr"
+| "More text that should not be in the nobr, i.e., the
+nobr should have closed the div inside it implicitly. "
+| <pre>
+| "A pre tag outside everything else."
+| "
+
+"
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/webkit01.dat b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/webkit01.dat
new file mode 100644
index 00000000000..c480accd95a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/webkit01.dat
@@ -0,0 +1,705 @@
+#data
+Test
+#errors
+(1,4): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "Test"
+
+#data
+<div></div>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+
+#data
+<div>Test</div>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| "Test"
+
+#data
+<di
+#errors
+(1,3): eof-in-tag-name
+(1,3): expected-doctype-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+<div>Hello</div>
+<script>
+console.log("PASS");
+</script>
+<div>Bye</div>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| "Hello"
+| "
+"
+| <script>
+| "
+console.log("PASS");
+"
+| "
+"
+| <div>
+| "Bye"
+
+#data
+<div foo="bar">Hello</div>
+#errors
+(1,15): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| foo="bar"
+| "Hello"
+
+#data
+<div>Hello</div>
+<script>
+console.log("FOO<span>BAR</span>BAZ");
+</script>
+<div>Bye</div>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| "Hello"
+| "
+"
+| <script>
+| "
+console.log("FOO<span>BAR</span>BAZ");
+"
+| "
+"
+| <div>
+| "Bye"
+
+#data
+<foo bar="baz"></foo><potato quack="duck"></potato>
+#errors
+(1,15): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <foo>
+| bar="baz"
+| <potato>
+| quack="duck"
+
+#data
+<foo bar="baz"><potato quack="duck"></potato></foo>
+#errors
+(1,15): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <foo>
+| bar="baz"
+| <potato>
+| quack="duck"
+
+#data
+<foo></foo bar="baz"><potato></potato quack="duck">
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,21): attributes-in-end-tag
+(1,51): attributes-in-end-tag
+#document
+| <html>
+| <head>
+| <body>
+| <foo>
+| <potato>
+
+#data
+</ tttt>
+#errors
+(1,2): expected-closing-tag-but-got-char
+(1,8): expected-doctype-but-got-eof
+#document
+| <!-- tttt -->
+| <html>
+| <head>
+| <body>
+
+#data
+<div FOO ><img><img></div>
+#errors
+(1,10): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| foo=""
+| <img>
+| <img>
+
+#data
+<p>Test</p<p>Test2</p>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,13): unexpected-end-tag
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| "TestTest2"
+
+#data
+<rdar://problem/6869687>
+#errors
+(1,7): unexpected-character-after-solidus-in-tag
+(1,8): unexpected-character-after-solidus-in-tag
+(1,16): unexpected-character-after-solidus-in-tag
+(1,24): expected-doctype-but-got-start-tag
+(1,24): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <rdar:>
+| 6869687=""
+| problem=""
+
+#data
+<A>test< /A>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,8): expected-tag-name
+(1,12): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| "test< /A>"
+
+#data
+&lt;
+#errors
+(1,4): expected-doctype-but-got-chars
+#document
+| <html>
+| <head>
+| <body>
+| "<"
+
+#data
+<body foo='bar'><body foo='baz' yo='mama'>
+#errors
+(1,16): expected-doctype-but-got-start-tag
+(1,42): unexpected-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| foo="bar"
+| yo="mama"
+
+#data
+<body></br foo="bar"></body>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,21): attributes-in-end-tag
+(1,21): unexpected-end-tag-treated-as
+#document
+| <html>
+| <head>
+| <body>
+| <br>
+
+#data
+<bdy><br foo="bar"></body>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,26): expected-one-end-tag-but-got-another
+#document
+| <html>
+| <head>
+| <body>
+| <bdy>
+| <br>
+| foo="bar"
+
+#data
+<body></body></br foo="bar">
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,28): attributes-in-end-tag
+(1,28): unexpected-end-tag-after-body
+(1,28): unexpected-end-tag-treated-as
+#document
+| <html>
+| <head>
+| <body>
+| <br>
+
+#data
+<bdy></body><br foo="bar">
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,12): expected-one-end-tag-but-got-another
+(1,26): unexpected-start-tag-after-body
+(1,26): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <bdy>
+| <br>
+| foo="bar"
+
+#data
+<html><body></body></html><!-- Hi there -->
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <!-- Hi there -->
+
+#data
+<html><body></body></html>x<!-- Hi there -->
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,27): expected-eof-but-got-char
+#document
+| <html>
+| <head>
+| <body>
+| "x"
+| <!-- Hi there -->
+
+#data
+<html><body></body></html>x<!-- Hi there --></html><!-- Again -->
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,27): expected-eof-but-got-char
+#document
+| <html>
+| <head>
+| <body>
+| "x"
+| <!-- Hi there -->
+| <!-- Again -->
+
+#data
+<html><body></body></html>x<!-- Hi there --></body></html><!-- Again -->
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,27): expected-eof-but-got-char
+#document
+| <html>
+| <head>
+| <body>
+| "x"
+| <!-- Hi there -->
+| <!-- Again -->
+
+#data
+<html><body><ruby><div><rp>xx</rp></div></ruby></body></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,27): XXX-undefined-error
+#document
+| <html>
+| <head>
+| <body>
+| <ruby>
+| <div>
+| <rp>
+| "xx"
+
+#data
+<html><body><ruby><div><rt>xx</rt></div></ruby></body></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,27): XXX-undefined-error
+#document
+| <html>
+| <head>
+| <body>
+| <ruby>
+| <div>
+| <rt>
+| "xx"
+
+#data
+<html><frameset><!--1--><noframes>A</noframes><!--2--></frameset><!--3--><noframes>B</noframes><!--4--></html><!--5--><noframes>C</noframes><!--6-->
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <frameset>
+| <!-- 1 -->
+| <noframes>
+| "A"
+| <!-- 2 -->
+| <!-- 3 -->
+| <noframes>
+| "B"
+| <!-- 4 -->
+| <noframes>
+| "C"
+| <!-- 5 -->
+| <!-- 6 -->
+
+#data
+<select><option>A<select><option>B<select><option>C<select><option>D<select><option>E<select><option>F<select><option>G<select>
+#errors
+(1,8): expected-doctype-but-got-start-tag
+(1,25): unexpected-select-in-select
+(1,59): unexpected-select-in-select
+(1,93): unexpected-select-in-select
+(1,127): unexpected-select-in-select
+(1,127): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <select>
+| <option>
+| "A"
+| <option>
+| "B"
+| <select>
+| <option>
+| "C"
+| <option>
+| "D"
+| <select>
+| <option>
+| "E"
+| <option>
+| "F"
+| <select>
+| <option>
+| "G"
+
+#data
+<dd><dd><dt><dt><dd><li><li>
+#errors
+(1,4): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <dd>
+| <dd>
+| <dt>
+| <dt>
+| <dd>
+| <li>
+| <li>
+
+#data
+<div><b></div><div><nobr>a<nobr>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,14): end-tag-too-early
+(1,32): unexpected-start-tag-implies-end-tag
+(1,32): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| <b>
+| <div>
+| <b>
+| <nobr>
+| "a"
+| <nobr>
+
+#data
+<head></head>
+<body></body>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| "
+"
+| <body>
+
+#data
+<head></head> <style></style>ddd
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,21): unexpected-start-tag-out-of-my-head
+#document
+| <html>
+| <head>
+| <style>
+| " "
+| <body>
+| "ddd"
+
+#data
+<kbd><table></kbd><col><select><tr>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,18): unexpected-end-tag-implies-table-voodoo
+(1,18): unexpected-end-tag
+(1,31): unexpected-start-tag-implies-table-voodoo
+(1,35): unexpected-table-element-start-tag-in-select-in-table
+(1,35): eof-in-table
+#document
+| <html>
+| <head>
+| <body>
+| <kbd>
+| <select>
+| <table>
+| <colgroup>
+| <col>
+| <tbody>
+| <tr>
+
+#data
+<kbd><table></kbd><col><select><tr></table><div>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,18): unexpected-end-tag-implies-table-voodoo
+(1,18): unexpected-end-tag
+(1,31): unexpected-start-tag-implies-table-voodoo
+(1,35): unexpected-table-element-start-tag-in-select-in-table
+(1,48): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <kbd>
+| <select>
+| <table>
+| <colgroup>
+| <col>
+| <tbody>
+| <tr>
+| <div>
+
+#data
+<a><li><style></style><title></title></a>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,41): adoption-agency-1.3
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| <li>
+| <a>
+| <style>
+| <title>
+
+#data
+<font></p><p><meta><title></title></font>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,10): unexpected-end-tag
+(1,41): adoption-agency-1.3
+#document
+| <html>
+| <head>
+| <body>
+| <font>
+| <p>
+| <p>
+| <font>
+| <meta>
+| <title>
+
+#data
+<a><center><title></title><a>
+#errors
+(1,3): expected-doctype-but-got-start-tag
+(1,29): unexpected-start-tag-implies-end-tag
+(1,29): adoption-agency-1.3
+(1,29): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <a>
+| <center>
+| <a>
+| <title>
+| <a>
+
+#data
+<svg><title><div>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,17): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg title>
+| <div>
+
+#data
+<svg><title><rect><div>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,23): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg title>
+| <rect>
+| <div>
+
+#data
+<svg><title><svg><div>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,22): unexpected-html-element-in-foreign-content
+(1,22): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg title>
+| <svg svg>
+| <div>
+
+#data
+<img <="" FAIL>
+#errors
+(1,6): invalid-character-in-attribute-name
+(1,15): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <img>
+| <=""
+| fail=""
+
+#data
+<ul><li><div id='foo'/>A</li><li>B<div>C</div></li></ul>
+#errors
+(1,4): expected-doctype-but-got-start-tag
+(1,23): non-void-element-with-trailing-solidus
+(1,29): end-tag-too-early
+#document
+| <html>
+| <head>
+| <body>
+| <ul>
+| <li>
+| <div>
+| id="foo"
+| "A"
+| <li>
+| "B"
+| <div>
+| "C"
+
+#data
+<svg><em><desc></em>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,9): unexpected-html-element-in-foreign-content
+(1,20): adoption-agency-1.3
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <em>
+| <desc>
+
+#data
+<svg><tfoot></mi><td>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+(1,17): unexpected-end-tag
+(1,17): unexpected-end-tag
+(1,21): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <svg svg>
+| <svg tfoot>
+| <svg td>
+
+#data
+<math><mrow><mrow><mn>1</mn></mrow><mi>a</mi></mrow></math>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <math math>
+| <math mrow>
+| <math mrow>
+| <math mn>
+| "1"
+| <math mi>
+| "a"
+
+#data
+<!doctype html><input type="hidden"><frameset>
+#errors
+(1,46): unexpected-start-tag
+(1,46): eof-in-frameset
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <frameset>
+
+#data
+<!doctype html><input type="button"><frameset>
+#errors
+(1,46): unexpected-start-tag
+#document
+| <!DOCTYPE html>
+| <html>
+| <head>
+| <body>
+| <input>
+| type="button"
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/webkit02.dat b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/webkit02.dat
new file mode 100644
index 00000000000..1ce90dfe13d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/tree-construction/webkit02.dat
@@ -0,0 +1,134 @@
+#data
+<foo bar=qux/>
+#errors
+(1,14): expected-doctype-but-got-start-tag
+(1,14): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <foo>
+| bar="qux/"
+
+#data
+<p id="status"><noscript><strong>A</strong></noscript><span>B</span></p>
+#errors
+(1,15): expected-doctype-but-got-start-tag
+#script-on
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| id="status"
+| <noscript>
+| "<strong>A</strong>"
+| <span>
+| "B"
+
+#data
+<p id="status"><noscript><strong>A</strong></noscript><span>B</span></p>
+#errors
+(1,15): expected-doctype-but-got-start-tag
+#script-off
+#document
+| <html>
+| <head>
+| <body>
+| <p>
+| id="status"
+| <noscript>
+| <strong>
+| "A"
+| <span>
+| "B"
+
+#data
+<div><sarcasm><div></div></sarcasm></div>
+#errors
+(1,5): expected-doctype-but-got-start-tag
+#document
+| <html>
+| <head>
+| <body>
+| <div>
+| <sarcasm>
+| <div>
+
+#data
+<html><body><img src="" border="0" alt="><div>A</div></body></html>
+#errors
+(1,6): expected-doctype-but-got-start-tag
+(1,67): eof-in-attribute-value-double-quote
+#document
+| <html>
+| <head>
+| <body>
+
+#data
+<table><td></tbody>A
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,11): unexpected-cell-in-table-body
+(1,20): foster-parenting-character
+(1,20): eof-in-table
+#document
+| <html>
+| <head>
+| <body>
+| "A"
+| <table>
+| <tbody>
+| <tr>
+| <td>
+
+#data
+<table><td></thead>A
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,11): unexpected-cell-in-table-body
+(1,19): XXX-undefined-error
+(1,20): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| "A"
+
+#data
+<table><td></tfoot>A
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,11): unexpected-cell-in-table-body
+(1,19): XXX-undefined-error
+(1,20): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <tbody>
+| <tr>
+| <td>
+| "A"
+
+#data
+<table><thead><td></tbody>A
+#errors
+(1,7): expected-doctype-but-got-start-tag
+(1,18): unexpected-cell-in-table-body
+(1,26): XXX-undefined-error
+(1,27): expected-closing-tag-but-got-eof
+#document
+| <html>
+| <head>
+| <body>
+| <table>
+| <thead>
+| <tr>
+| <td>
+| "A"
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/attributes.test b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/attributes.test
new file mode 100755
index 00000000000..2815976bff8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/attributes.test
@@ -0,0 +1,1035 @@
+{"tests": [
+
+{"description": "allowed 'class' attribute on <span>",
+"input": "<span class>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'contenteditable' attribute on <span>",
+"input": "<span contenteditable>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'contextmenu' attribute on <span>",
+"input": "<span contextmenu>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'dir' attribute on <span>",
+"input": "<span dir>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'draggable' attribute on <span>",
+"input": "<span draggable>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'id' attribute on <span>",
+"input": "<span id>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'irrelevant' attribute on <span>",
+"input": "<span irrelevant>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'lang' attribute on <span>",
+"input": "<span lang>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'ref' attribute on <span>",
+"input": "<span ref>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'tabindex' attribute on <span>",
+"input": "<span tabindex>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'template' attribute on <span>",
+"input": "<span template>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'title' attribute on <span>",
+"input": "<span title>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'onabort' attribute on <span>",
+"input": "<span onabort>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'onbeforeunload' attribute on <span>",
+"input": "<span onbeforeunload>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'onblur' attribute on <span>",
+"input": "<span onblur>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'onchange' attribute on <span>",
+"input": "<span onchange>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'onclick' attribute on <span>",
+"input": "<span onclick>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'oncontextmenu' attribute on <span>",
+"input": "<span oncontextmenu>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'ondblclick' attribute on <span>",
+"input": "<span ondblclick>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'ondrag' attribute on <span>",
+"input": "<span ondrag>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'ondragend' attribute on <span>",
+"input": "<span ondragend>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'ondragenter' attribute on <span>",
+"input": "<span ondragenter>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'ondragleave' attribute on <span>",
+"input": "<span ondragleave>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'ondragover' attribute on <span>",
+"input": "<span ondragover>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'ondragstart' attribute on <span>",
+"input": "<span ondragstart>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'ondrop' attribute on <span>",
+"input": "<span ondrop>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'onerror' attribute on <span>",
+"input": "<span onerror>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'onfocus' attribute on <span>",
+"input": "<span onfocus>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'onkeydown' attribute on <span>",
+"input": "<span onkeydown>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'onkeypress' attribute on <span>",
+"input": "<span onkeypress>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'onkeyup' attribute on <span>",
+"input": "<span onkeyup>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'onload' attribute on <span>",
+"input": "<span onload>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'onmessage' attribute on <span>",
+"input": "<span onmessage>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'onmousedown' attribute on <span>",
+"input": "<span onmousedown>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'onmousemove' attribute on <span>",
+"input": "<span onmousemove>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'onmouseout' attribute on <span>",
+"input": "<span onmouseout>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'onmouseover' attribute on <span>",
+"input": "<span onmouseover>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'onmouseup' attribute on <span>",
+"input": "<span onmouseup>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'onmousewheel' attribute on <span>",
+"input": "<span onmousewheel>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'onresize' attribute on <span>",
+"input": "<span onresize>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'onscroll' attribute on <span>",
+"input": "<span onscroll>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'onselect' attribute on <span>",
+"input": "<span onselect>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'onsubmit' attribute on <span>",
+"input": "<span onsubmit>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'onunload' attribute on <span>",
+"input": "<span onunload>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'type' attribute on <command>",
+"input": "<command type>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'label' attribute on <command>",
+"input": "<command label>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'icon' attribute on <command>",
+"input": "<command icon>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'hidden' attribute on <command>",
+"input": "<command hidden>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'disabled' attribute on <command>",
+"input": "<command disabled>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'checked' attribute on <command>",
+"input": "<command checked>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'radiogroup' attribute on <command>",
+"input": "<command radiogroup>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'default' attribute on <command>",
+"input": "<command default>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'value' attribute on <meter>",
+"input": "<meter value>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'min' attribute on <meter>",
+"input": "<meter min>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'low' attribute on <meter>",
+"input": "<meter low>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'high' attribute on <meter>",
+"input": "<meter high>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'max' attribute on <meter>",
+"input": "<meter max>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'optimum' attribute on <meter>",
+"input": "<meter optimum>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'cite' attribute on <ins>",
+"input": "<ins cite>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'datetime' attribute on <ins>",
+"input": "<ins datetime>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'multiple' attribute on <datagrid>",
+"input": "<datagrid multiple>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'disabled' attribute on <datagrid>",
+"input": "<datagrid disabled>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'name' attribute on <meta>",
+"input": "<meta name>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'http-equiv' attribute on <meta>",
+"input": "<meta http-equiv>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'content' attribute on <meta>",
+"input": "<meta content>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'charset' attribute on <meta>",
+"input": "<meta charset>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'src' attribute on <video>",
+"input": "<video src>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'autoplay' attribute on <video>",
+"input": "<video autoplay>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'start' attribute on <video>",
+"input": "<video start>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'loopstart' attribute on <video>",
+"input": "<video loopstart>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'loopend' attribute on <video>",
+"input": "<video loopend>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'end' attribute on <video>",
+"input": "<video end>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'loopcount' attribute on <video>",
+"input": "<video loopcount>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'controls' attribute on <video>",
+"input": "<video controls>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'style' attribute on <font>",
+"input": "<font style>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'media' attribute on <style>",
+"input": "<style media>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'type' attribute on <style>",
+"input": "<style type>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'scoped' attribute on <style>",
+"input": "<style scoped>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'alt' attribute on <img>",
+"input": "<img alt>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'src' attribute on <img>",
+"input": "<img src>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'usemap' attribute on <img>",
+"input": "<img usemap>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'ismap' attribute on <img>",
+"input": "<img ismap>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'height' attribute on <img>",
+"input": "<img height>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'width' attribute on <img>",
+"input": "<img width>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'alt' attribute on <area>",
+"input": "<area alt>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'coords' attribute on <area>",
+"input": "<area coords>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'shape' attribute on <area>",
+"input": "<area shape>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'href' attribute on <area>",
+"input": "<area href>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'target' attribute on <area>",
+"input": "<area target>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'ping' attribute on <area>",
+"input": "<area ping>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'rel' attribute on <area>",
+"input": "<area rel>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'media' attribute on <area>",
+"input": "<area media>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'hreflang' attribute on <area>",
+"input": "<area hreflang>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'type' attribute on <area>",
+"input": "<area type>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'type' attribute on <menu>",
+"input": "<menu type>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'label' attribute on <menu>",
+"input": "<menu label>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'autosubmit' attribute on <menu>",
+"input": "<menu autosubmit>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'name' attribute on <param>",
+"input": "<param name>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'value' attribute on <param>",
+"input": "<param value>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'value' attribute on <li>",
+"input": "<li value>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'src' attribute on <source>",
+"input": "<source src>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'type' attribute on <source>",
+"input": "<source type>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'media' attribute on <source>",
+"input": "<source media>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'xmlns' attribute on <html>",
+"input": "<html xmlns>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'open' attribute on <details>",
+"input": "<details open>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'colspan' attribute on <th>",
+"input": "<th colspan>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'rowspan' attribute on <th>",
+"input": "<th rowspan>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'scope' attribute on <th>",
+"input": "<th scope>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'value' attribute on <progress>",
+"input": "<progress value>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'max' attribute on <progress>",
+"input": "<progress max>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'colspan' attribute on <td>",
+"input": "<td colspan>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'rowspan' attribute on <td>",
+"input": "<td rowspan>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'cite' attribute on <blockquote>",
+"input": "<blockquote cite>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'data' attribute on <object>",
+"input": "<object data>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'type' attribute on <object>",
+"input": "<object type>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'usemap' attribute on <object>",
+"input": "<object usemap>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'height' attribute on <object>",
+"input": "<object height>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'width' attribute on <object>",
+"input": "<object width>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'height' attribute on <canvas>",
+"input": "<canvas height>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'width' attribute on <canvas>",
+"input": "<canvas width>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'href' attribute on <base>",
+"input": "<base href>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'target' attribute on <base>",
+"input": "<base target>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'href' attribute on <link>",
+"input": "<link href>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'rel' attribute on <link>",
+"input": "<link rel>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'media' attribute on <link>",
+"input": "<link media>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'hreflang' attribute on <link>",
+"input": "<link hreflang>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'type' attribute on <link>",
+"input": "<link type>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'href' attribute on <a>",
+"input": "<a href>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'target' attribute on <a>",
+"input": "<a target>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'ping' attribute on <a>",
+"input": "<a ping>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'rel' attribute on <a>",
+"input": "<a rel>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'media' attribute on <a>",
+"input": "<a media>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'hreflang' attribute on <a>",
+"input": "<a hreflang>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'type' attribute on <a>",
+"input": "<a type>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'src' attribute on <event-source>",
+"input": "<event-source src>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'start' attribute on <ol>",
+"input": "<ol start>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'span' attribute on <colgroup>",
+"input": "<colgroup span>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'src' attribute on <script>",
+"input": "<script src>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'defer' attribute on <script>",
+"input": "<script defer>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'async' attribute on <script>",
+"input": "<script async>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'type' attribute on <script>",
+"input": "<script type>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'cite' attribute on <q>",
+"input": "<q cite>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'cite' attribute on <del>",
+"input": "<del cite>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'datetime' attribute on <del>",
+"input": "<del datetime>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'src' attribute on <iframe>",
+"input": "<iframe src>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'datetime' attribute on <time>",
+"input": "<time datetime>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'src' attribute on <audio>",
+"input": "<audio src>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'autoplay' attribute on <audio>",
+"input": "<audio autoplay>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'start' attribute on <audio>",
+"input": "<audio start>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'loopstart' attribute on <audio>",
+"input": "<audio loopstart>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'loopend' attribute on <audio>",
+"input": "<audio loopend>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'end' attribute on <audio>",
+"input": "<audio end>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'loopcount' attribute on <audio>",
+"input": "<audio loopcount>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'controls' attribute on <audio>",
+"input": "<audio controls>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'span' attribute on <col>",
+"input": "<col span>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'disabled' attribute on <fieldset>",
+"input": "<fieldset disabled>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'form' attribute on <fieldset>",
+"input": "<fieldset form>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'onsubmit' attribute on <form>",
+"input": "<form onsubmit>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'name' attribute on <form>",
+"input": "<form name>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'onreset' attribute on <form>",
+"input": "<form onreset>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'accept' attribute on <form>",
+"input": "<form accept>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'replace' attribute on <form>",
+"input": "<form replace>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'accept-charset' attribute on <form>",
+"input": "<form accept-charset>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'action' attribute on <form>",
+"input": "<form action>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'data' attribute on <form>",
+"input": "<form data>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'method' attribute on <form>",
+"input": "<form method>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'enctype' attribute on <form>",
+"input": "<form enctype>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'rows' attribute on <textarea>",
+"input": "<textarea rows>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'name' attribute on <textarea>",
+"input": "<textarea name>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'form' attribute on <textarea>",
+"input": "<textarea form>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'required' attribute on <textarea>",
+"input": "<textarea required>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'cols' attribute on <textarea>",
+"input": "<textarea cols>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'accept' attribute on <textarea>",
+"input": "<textarea accept>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'disabled' attribute on <textarea>",
+"input": "<textarea disabled>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'readonly' attribute on <textarea>",
+"input": "<textarea readonly>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'wrap' attribute on <textarea>",
+"input": "<textarea wrap>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'autofocus' attribute on <textarea>",
+"input": "<textarea autofocus>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'maxlength' attribute on <textarea>",
+"input": "<textarea maxlength>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'a' attribute on <datalist>",
+"input": "<datalist a>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "allowed 'd' attribute on <datalist>",
+"input": "<datalist d>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "allowed 't' attribute on <datalist>",
+"input": "<datalist t>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "allowed 'action' attribute on <button>",
+"input": "<button action>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'enctype' attribute on <button>",
+"input": "<button enctype>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'method' attribute on <button>",
+"input": "<button method>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'replace' attribute on <button>",
+"input": "<button replace>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'template' attribute on <button>",
+"input": "<button template>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'name' attribute on <button>",
+"input": "<button name>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'form' attribute on <button>",
+"input": "<button form>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'value' attribute on <button>",
+"input": "<button value>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'disabled' attribute on <button>",
+"input": "<button disabled>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'autofocus' attribute on <button>",
+"input": "<button autofocus>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'type' attribute on <button>",
+"input": "<button type>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'accesskey' attribute on <label>",
+"input": "<label accesskey>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'form' attribute on <label>",
+"input": "<label form>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'for' attribute on <label>",
+"input": "<label for>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'disabled' attribute on <optgroup>",
+"input": "<optgroup disabled>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'label' attribute on <optgroup>",
+"input": "<optgroup label>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'onforminput' attribute on <output>",
+"input": "<output onforminput>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'onformchange' attribute on <output>",
+"input": "<output onformchange>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'name' attribute on <output>",
+"input": "<output name>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'form' attribute on <output>",
+"input": "<output form>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'for' attribute on <output>",
+"input": "<output for>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'multiple' attribute on <select>",
+"input": "<select multiple>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'name' attribute on <select>",
+"input": "<select name>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'form' attribute on <select>",
+"input": "<select form>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'accesskey' attribute on <select>",
+"input": "<select accesskey>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'disabled' attribute on <select>",
+"input": "<select disabled>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'autofocus' attribute on <select>",
+"input": "<select autofocus>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'data' attribute on <select>",
+"input": "<select data>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'size' attribute on <select>",
+"input": "<select size>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'selected' attribute on <option>",
+"input": "<option selected>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'value' attribute on <option>",
+"input": "<option value>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'label' attribute on <option>",
+"input": "<option label>",
+"fail-if": "unknown-attribute"},
+
+{"description": "allowed 'disabled' attribute on <option>",
+"input": "<option disabled>",
+"fail-if": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <command>",
+"input": "<command foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <meter>",
+"input": "<meter foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <ins>",
+"input": "<ins foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <datagrid>",
+"input": "<datagrid foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <meta>",
+"input": "<meta foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <video>",
+"input": "<video foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <font>",
+"input": "<font foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <style>",
+"input": "<style foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <img>",
+"input": "<img foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <area>",
+"input": "<area foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <menu>",
+"input": "<menu foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <param>",
+"input": "<param foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <li>",
+"input": "<li foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <source>",
+"input": "<source foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <html>",
+"input": "<html foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <details>",
+"input": "<details foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <th>",
+"input": "<th foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <progress>",
+"input": "<progress foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <td>",
+"input": "<td foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <blockquote>",
+"input": "<blockquote foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <object>",
+"input": "<object foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <canvas>",
+"input": "<canvas foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <base>",
+"input": "<base foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <link>",
+"input": "<link foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <a>",
+"input": "<a foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <event-source>",
+"input": "<event-source foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <ol>",
+"input": "<ol foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <colgroup>",
+"input": "<colgroup foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <script>",
+"input": "<script foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <q>",
+"input": "<q foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <del>",
+"input": "<del foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <iframe>",
+"input": "<iframe foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <time>",
+"input": "<time foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <audio>",
+"input": "<audio foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <col>",
+"input": "<col foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "missing required 'href' attribute on <link>",
+"input": "<link rel>",
+"fail-unless": "missing-required-attribute"},
+
+{"description": "missing required 'rel' attribute on <link>",
+"input": "<link href>",
+"fail-unless": "missing-required-attribute"},
+
+{"description": "missing required 'dir' attribute on <bdo>",
+"input": "<bdo>",
+"fail-unless": "missing-required-attribute"},
+
+{"description": "missing required 'src' attribute on <img>",
+"input": "<img>",
+"fail-unless": "missing-required-attribute"},
+
+{"description": "missing required 'src' attribute on <embed>",
+"input": "<embed>",
+"fail-unless": "missing-required-attribute"},
+
+{"description": "missing required 'name' attribute on <param>",
+"input": "<param value>",
+"fail-unless": "missing-required-attribute"},
+
+{"description": "missing required 'value' attribute on <param>",
+"input": "<param name>",
+"fail-unless": "missing-required-attribute"},
+
+{"description": "missing required 'src' attribute on <source>",
+"input": "<source>",
+"fail-unless": "missing-required-attribute"},
+
+{"description": "missing required 'id' attribute on <map>",
+"input": "<map>",
+"fail-unless": "missing-required-attribute"}
+
+]}
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/base-href-attribute.test b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/base-href-attribute.test
new file mode 100755
index 00000000000..83a626a79a3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/base-href-attribute.test
@@ -0,0 +1,787 @@
+{"tests": [
+
+{"description": "base href contains invalid URI due to leading space",
+"input": "<base href=' http://www.example.com/'",
+"fail-unless": "invalid-uri-char"},
+
+{"description": "base href contains invalid URI due to trailing space",
+"input": "<base href='http://www.example.com/ '",
+"fail-unless": "invalid-uri-char"},
+
+{"description": "base href contains invalid URI due to space in scheme",
+"input": "<base href='ht tp://www.example.com/'",
+"fail-unless": "invalid-uri-char"},
+
+{"description": "base href contains invalid URI due to space in domain",
+"input": "<base href='http://www.example. com/'",
+"fail-unless": "invalid-uri-char"},
+
+{"description": "base href contains invalid URI due to space in path",
+"input": "<base href='http://www.example.com/a b'",
+"fail-unless": "invalid-uri-char"},
+
+{"description": "base href contains invalid URI due to space in fragment",
+"input": "<base href='http://www.example.com/a#b c'",
+"fail-unless": "invalid-uri-char"},
+
+{"description": "base href contains invalid URI due to space in query",
+"input": "<base href='http://www.example.com/a?b c'",
+"fail-unless": "invalid-uri-char"},
+
+{"description": "base href contains invalid URI due to leading tab",
+"input": "<base href='\thttp://www.example.com/'",
+"fail-unless": "invalid-uri-char"},
+
+{"description": "base href contains invalid URI due to trailing tab",
+"input": "<base href='http://www.example.com/\t'",
+"fail-unless": "invalid-uri-char"},
+
+{"description": "base href contains invalid URI due to tab in scheme",
+"input": "<base href='ht\ttp://www.example.com/'",
+"fail-unless": "invalid-uri-char"},
+
+{"description": "base href contains invalid URI due to tab in domain",
+"input": "<base href='http://www.example.\tcom/'",
+"fail-unless": "invalid-uri-char"},
+
+{"description": "base href contains invalid URI due to tab in path",
+"input": "<base href='http://www.example.com/a\tb'",
+"fail-unless": "invalid-uri-char"},
+
+{"description": "base href contains invalid URI due to tab in fragment",
+"input": "<base href='http://www.example.com/a#b\tc'",
+"fail-unless": "invalid-uri-char"},
+
+{"description": "base href contains invalid URI due to tab in query",
+"input": "<base href='http://www.example.com/a?b\tc'",
+"fail-unless": "invalid-uri-char"},
+
+{"description": "base href contains invalid URI due to leading LF",
+"input": "<base href='\nhttp://www.example.com/'",
+"fail-unless": "invalid-uri-char"},
+
+{"description": "base href contains invalid URI due to LF in scheme",
+"input": "<base href='ht\ntp://www.example.com/'",
+"fail-unless": "invalid-uri-char"},
+
+{"description": "base href contains invalid URI due to LF in domain",
+"input": "<base href='http://www.example.\ncom/'",
+"fail-unless": "invalid-uri-char"},
+
+{"description": "base href contains invalid URI due to LF in path",
+"input": "<base href='http://www.example.com/a\nb'",
+"fail-unless": "invalid-uri-char"},
+
+{"description": "base href contains invalid URI due to LF in fragment",
+"input": "<base href='http://www.example.com/a#b\nc'",
+"fail-unless": "invalid-uri-char"},
+
+{"description": "base href contains invalid URI due to LF in query",
+"input": "<base href='http://www.example.com/a?b\nc'",
+"fail-unless": "invalid-uri-char"},
+
+{"description": "base href contains invalid URI due to leading LT",
+"input": "<base href='\u000Bhttp://www.example.com/'",
+"fail-unless": "invalid-uri-char"},
+
+{"description": "base href contains invalid URI due to trailing LT",
+"input": "<base href='http://www.example.com/\u000B'",
+"fail-unless": "invalid-uri-char"},
+
+{"description": "base href contains invalid URI due to LT in scheme",
+"input": "<base href='ht\u000Btp://www.example.com/'",
+"fail-unless": "invalid-uri-char"},
+
+{"description": "base href contains invalid URI due to LT in domain",
+"input": "<base href='http://www.example.\u000Bcom/'",
+"fail-unless": "invalid-uri-char"},
+
+{"description": "base href contains invalid URI due to LT in path",
+"input": "<base href='http://www.example.com/a\u000Bb'",
+"fail-unless": "invalid-uri-char"},
+
+{"description": "base href contains invalid URI due to LT in fragment",
+"input": "<base href='http://www.example.com/a#b\u000Bc'",
+"fail-unless": "invalid-uri-char"},
+
+{"description": "base href contains invalid URI due to LT in query",
+"input": "<base href='http://www.example.com/a?b\u000Bc'",
+"fail-unless": "invalid-uri-char"},
+
+{"description": "base href contains invalid URI due to leading FF",
+"input": "<base href='\u000Chttp://www.example.com/'",
+"fail-unless": "invalid-uri-char"},
+
+{"description": "base href contains invalid URI due to trailing FF",
+"input": "<base href='http://www.example.com/\u000C'",
+"fail-unless": "invalid-uri-char"},
+
+{"description": "base href contains invalid URI due to FF in scheme",
+"input": "<base href='ht\u000Ctp://www.example.com/'",
+"fail-unless": "invalid-uri-char"},
+
+{"description": "base href contains invalid URI due to FF in domain",
+"input": "<base href='http://www.example.\u000Ccom/'",
+"fail-unless": "invalid-uri-char"},
+
+{"description": "base href contains invalid URI due to FF in path",
+"input": "<base href='http://www.example.com/a\u000Cb'",
+"fail-unless": "invalid-uri-char"},
+
+{"description": "base href contains invalid URI due to FF in fragment",
+"input": "<base href='http://www.example.com/a#b\u000Cc'",
+"fail-unless": "invalid-uri-char"},
+
+{"description": "base href contains invalid URI due to FF in query",
+"input": "<base href='http://www.example.com/a?b\u000Cc'",
+"fail-unless": "invalid-uri-char"},
+
+{"description": "base href contains invalid URI due to leading CR",
+"input": "<base href='\rhttp://www.example.com/'",
+"fail-unless": "invalid-uri-char"},
+
+{"description": "base href contains invalid URI due to CR in scheme",
+"input": "<base href='ht\rtp://www.example.com/'",
+"fail-unless": "invalid-uri-char"},
+
+{"description": "base href contains invalid URI due to CR in domain",
+"input": "<base href='http://www.example.\rcom/'",
+"fail-unless": "invalid-uri-char"},
+
+{"description": "base href contains invalid URI due to CR in path",
+"input": "<base href='http://www.example.com/a\rb'",
+"fail-unless": "invalid-uri-char"},
+
+{"description": "base href contains invalid URI due to CR in fragment",
+"input": "<base href='http://www.example.com/a#b\rc'",
+"fail-unless": "invalid-uri-char"},
+
+{"description": "base href contains invalid URI due to CR in query",
+"input": "<base href='http://www.example.com/a?b\rc'",
+"fail-unless": "invalid-uri-char"},
+
+{"description": "base href contains valid URI scheme 'ftp'",
+"input": "<base href='ftp://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'http'",
+"input": "<base href='http://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'gopher'",
+"input": "<base href='gopher://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'mailto'",
+"input": "<base href='mailto://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'news'",
+"input": "<base href='news://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'nntp'",
+"input": "<base href='nntp://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'telnet'",
+"input": "<base href='telnet://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'wais'",
+"input": "<base href='wais://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'file'",
+"input": "<base href='file://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'prospero'",
+"input": "<base href='prospero://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'z39.50s'",
+"input": "<base href='z39.50s://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'z39.50r'",
+"input": "<base href='z39.50r://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'cid'",
+"input": "<base href='cid://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'mid'",
+"input": "<base href='mid://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'vemmi'",
+"input": "<base href='vemmi://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'service'",
+"input": "<base href='service://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'imap'",
+"input": "<base href='imap://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'nfs'",
+"input": "<base href='nfs://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'acap'",
+"input": "<base href='acap://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'rtsp'",
+"input": "<base href='rtsp://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'tip'",
+"input": "<base href='tip://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'pop'",
+"input": "<base href='pop://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'data'",
+"input": "<base href='data://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'dav'",
+"input": "<base href='dav://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'opaquelocktoken'",
+"input": "<base href='opaquelocktoken://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'sip'",
+"input": "<base href='sip://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'sips'",
+"input": "<base href='sips://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'tel'",
+"input": "<base href='tel://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'fax'",
+"input": "<base href='fax://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'modem'",
+"input": "<base href='modem://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'ldap'",
+"input": "<base href='ldap://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'https'",
+"input": "<base href='https://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'soap.beep'",
+"input": "<base href='soap.beep://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'soap.beeps'",
+"input": "<base href='soap.beeps://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'xmlrpc.beep'",
+"input": "<base href='xmlrpc.beep://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'xmlrpc.beeps'",
+"input": "<base href='xmlrpc.beeps://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'urn'",
+"input": "<base href='urn://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'go'",
+"input": "<base href='go://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'h323'",
+"input": "<base href='h323://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'ipp'",
+"input": "<base href='ipp://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'tftp'",
+"input": "<base href='tftp://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'mupdate'",
+"input": "<base href='mupdate://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'pres'",
+"input": "<base href='pres://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'im'",
+"input": "<base href='im://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'mtqp'",
+"input": "<base href='mtqp://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'iris.beep'",
+"input": "<base href='iris.beep://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'dict'",
+"input": "<base href='dict://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'snmp'",
+"input": "<base href='snmp://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'crid'",
+"input": "<base href='crid://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'tag'",
+"input": "<base href='tag://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'dns'",
+"input": "<base href='dns://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'info'",
+"input": "<base href='info://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'javascript'",
+"input": "<base href='javascript:foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'FTP'",
+"input": "<base href='FTP://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'HTTP'",
+"input": "<base href='HTTP://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'GOPHER'",
+"input": "<base href='GOPHER://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'MAILTO'",
+"input": "<base href='MAILTO://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'NEWS'",
+"input": "<base href='NEWS://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'NNTP'",
+"input": "<base href='NNTP://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'TELNET'",
+"input": "<base href='TELNET://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'WAIS'",
+"input": "<base href='WAIS://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'FILE'",
+"input": "<base href='FILE://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'PROSPERO'",
+"input": "<base href='PROSPERO://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'Z39.50S'",
+"input": "<base href='Z39.50S://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'Z39.50R'",
+"input": "<base href='Z39.50R://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'CID'",
+"input": "<base href='CID://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'MID'",
+"input": "<base href='MID://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'VEMMI'",
+"input": "<base href='VEMMI://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'SERVICE'",
+"input": "<base href='SERVICE://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'IMAP'",
+"input": "<base href='IMAP://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'NFS'",
+"input": "<base href='NFS://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'ACAP'",
+"input": "<base href='ACAP://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'RTSP'",
+"input": "<base href='RTSP://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'TIP'",
+"input": "<base href='TIP://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'POP'",
+"input": "<base href='POP://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'DATA'",
+"input": "<base href='DATA://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'DAV'",
+"input": "<base href='DAV://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'OPAQUELOCKTOKEN'",
+"input": "<base href='OPAQUELOCKTOKEN://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'SIP'",
+"input": "<base href='SIP://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'SIPS'",
+"input": "<base href='SIPS://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'TEL'",
+"input": "<base href='TEL://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'FAX'",
+"input": "<base href='FAX://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'MODEM'",
+"input": "<base href='MODEM://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'LDAP'",
+"input": "<base href='LDAP://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'HTTPS'",
+"input": "<base href='HTTPS://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'SOAP.BEEP'",
+"input": "<base href='SOAP.BEEP://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'SOAP.BEEPS'",
+"input": "<base href='SOAP.BEEPS://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'XMLRPC.BEEP'",
+"input": "<base href='XMLRPC.BEEP://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'XMLRPC.BEEPS'",
+"input": "<base href='XMLRPC.BEEPS://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'URN'",
+"input": "<base href='URN://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'GO'",
+"input": "<base href='GO://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'H323'",
+"input": "<base href='H323://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'IPP'",
+"input": "<base href='IPP://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'TFTP'",
+"input": "<base href='TFTP://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'MUPDATE'",
+"input": "<base href='MUPDATE://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'PRES'",
+"input": "<base href='PRES://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'IM'",
+"input": "<base href='IM://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'MTQP'",
+"input": "<base href='MTQP://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'IRIS.BEEP'",
+"input": "<base href='IRIS.BEEP://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'DICT'",
+"input": "<base href='DICT://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'SNMP'",
+"input": "<base href='SNMP://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'CRID'",
+"input": "<base href='CRID://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'TAG'",
+"input": "<base href='TAG://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'DNS'",
+"input": "<base href='DNS://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'INFO'",
+"input": "<base href='INFO://foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'JAVASCRIPT'",
+"input": "<base href='JAVASCRIPT:foo'",
+"fail-if": "invalid-scheme"},
+
+{"description": "base href contains valid URI scheme 'foo'",
+"input": "<base href='foo:bar'",
+"fail-unless": "invalid-scheme"},
+
+{"description": "base href contains valid URI 'g'",
+"input": "<base href='g'",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "base href contains valid URI './g'",
+"input": "<base href='./g'",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "base href contains valid URI 'g/'",
+"input": "<base href='g/'",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "base href contains valid URI '/g'",
+"input": "<base href='/g'",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "base href contains valid URI '//g'",
+"input": "<base href='//g'",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "base href contains valid URI '?y'",
+"input": "<base href='?y'",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "base href contains valid URI 'g?y'",
+"input": "<base href='g?y'",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "base href contains valid URI '#s'",
+"input": "<base href='#s'",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "base href contains valid URI 'g#s'",
+"input": "<base href='g#s'",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "base href contains valid URI 'g?y#s'",
+"input": "<base href='g?y#s'",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "base href contains valid URI ';x'",
+"input": "<base href=';x'",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "base href contains valid URI 'g;x'",
+"input": "<base href='g;x'",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "base href contains valid URI 'g;x?y#s'",
+"input": "<base href='g;x?y#s'",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "base href contains valid URI '.'",
+"input": "<base href='.'",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "base href contains valid URI './'",
+"input": "<base href='./'",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "base href contains valid URI '..'",
+"input": "<base href='..'",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "base href contains valid URI '../'",
+"input": "<base href='../'",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "base href contains valid URI '../g'",
+"input": "<base href='../g'",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "base href contains valid URI '../..'",
+"input": "<base href='../..'",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "base href contains valid URI '../../'",
+"input": "<base href='../../'",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "base href contains valid URI '../../g'",
+"input": "<base href='../../g'",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "base href contains valid URI '../../../g'",
+"input": "<base href='../../../g'",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "base href contains valid URI '../../../../g'",
+"input": "<base href='../../../../g'",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "base href contains valid URI '/./g'",
+"input": "<base href='/./g'",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "base href contains valid URI '/../g'",
+"input": "<base href='/../g'",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "base href contains valid URI 'g.'",
+"input": "<base href='g.'",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "base href contains valid URI '.g'",
+"input": "<base href='.g'",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "base href contains valid URI 'g..'",
+"input": "<base href='g..'",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "base href contains valid URI '..g'",
+"input": "<base href='..g'",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "base href contains valid URI './../g'",
+"input": "<base href='./../g'",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "base href contains valid URI './g/.'",
+"input": "<base href='./g/.'",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "base href contains valid URI 'g/./h'",
+"input": "<base href='g/./h'",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "base href contains valid URI 'g/../h'",
+"input": "<base href='g/../h'",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "base href contains valid URI 'g;x=1/./y'",
+"input": "<base href='g;x=1/./y'",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "base href contains valid URI 'g;x=1/../y'",
+"input": "<base href='g;x=1/../y'",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "base href contains valid URI 'g?y/./x'",
+"input": "<base href='g?y/./x'",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "base href contains valid URI 'g?y/../x'",
+"input": "<base href='g?y/../x'",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "base href contains valid URI 'g#s/./x'",
+"input": "<base href='g#s/./x'",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "base href contains valid URI 'g#s/../x'",
+"input": "<base href='g#s/../x'",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "base href contains valid URI './g:h'",
+"input": "<base href='./g:h'",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "base href contains valid URI 'http://www.w%33.org'",
+"input": "<base href='http://www.w%33.org'",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "base href contains valid URI 'http://r%C3%A4ksm%C3%B6rg%C3%A5s.josefsson.org'",
+"input": "<base href='http://r%C3%A4ksm%C3%B6rg%C3%A5s.josefsson.org'",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "base href contains valid URI 'http://xn--rksmrgs-5wao1o.josefsson.org'",
+"input": "<base href='http://xn--rksmrgs-5wao1o.josefsson.org'",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "base href contains valid URI 'http://%E7%B4%8D%E8%B1%86.w3.mag.keio.ac.jp'",
+"input": "<base href='http://%E7%B4%8D%E8%B1%86.w3.mag.keio.ac.jp'",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "base href contains valid URI 'http://xn--99zt52a.w3.mag.keio.ac.jp'",
+"input": "<base href='http://xn--99zt52a.w3.mag.keio.ac.jp'",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "base href contains valid URI 'http://www.%E3%81%BB%E3%82%93%E3%81%A8%E3%81%86%E3%81%AB%E3%81%AA%E3%81%8C%E3%81%84%E3%82%8F%E3%81%91%E3%81%AE%E3%82%8F%E3%81%8B%E3%82%89%E3%81%AA%E3%81%84%E3%81%A9%E3%82%81%E3%81%84%E3%82%93%E3%82%81%E3%81%84%E3%81%AE%E3%82%89%E3%81%B9%E3%82%8B%E3%81%BE%E3%81%A0%E3%81%AA%E3%81%8C%E3%81%8F%E3%81%97%E3%81%AA%E3%81%84%E3%81%A8%E3%81%9F%E3%82%8A%E3%81%AA%E3%81%84.w3.mag.keio.ac.jp/'",
+"input": "<base href='http://www.%E3%81%BB%E3%82%93%E3%81%A8%E3%81%86%E3%81%AB%E3%81%AA%E3%81%8C%E3%81%84%E3%82%8F%E3%81%91%E3%81%AE%E3%82%8F%E3%81%8B%E3%82%89%E3%81%AA%E3%81%84%E3%81%A9%E3%82%81%E3%81%84%E3%82%93%E3%82%81%E3%81%84%E3%81%AE%E3%82%89%E3%81%B9%E3%82%8B%E3%81%BE%E3%81%A0%E3%81%AA%E3%81%8C%E3%81%8F%E3%81%97%E3%81%AA%E3%81%84%E3%81%A8%E3%81%9F%E3%82%8A%E3%81%AA%E3%81%84.w3.mag.keio.ac.jp/'",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "base href contains valid URI 'http://www.xn--n8jaaaaai5bhf7as8fsfk3jnknefdde3fg11amb5gzdb4wi9bya3kc6lra.w3.mag.keio.ac.jp/'",
+"input": "<base href='http://www.xn--n8jaaaaai5bhf7as8fsfk3jnknefdde3fg11amb5gzdb4wi9bya3kc6lra.w3.mag.keio.ac.jp/'",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "base href contains valid URI 'http://%E3%81%BB%E3%82%93%E3%81%A8%E3%81%86%E3%81%AB%E3%81%AA%E3%81%8C%E3%81%84%E3%82%8F%E3%81%91%E3%81%AE%E3%82%8F%E3%81%8B%E3%82%89%E3%81%AA%E3%81%84%E3%81%A9%E3%82%81%E3%81%84%E3%82%93%E3%82%81%E3%81%84%E3%81%AE%E3%82%89%E3%81%B9%E3%82%8B%E3%81%BE%E3%81%A0%E3%81%AA%E3%81%8C%E3%81%8F%E3%81%97%E3%81%AA%E3%81%84%E3%81%A8%E3%81%9F%E3%82%8A%E3%81%AA%E3%81%84.%E3%81%BB%E3%82%93%E3%81%A8%E3%81%86%E3%81%AB%E3%81%AA%E3%81%8C%E3%81%84%E3%82%8F%E3%81%91%E3%81%AE%E3%82%8F%E3%81%8B%E3%82%89%E3%81%AA%E3%81%84%E3%81%A9%E3%82%81%E3%81%84%E3%82%93%E3%82%81%E3%81%84%E3%81%AE%E3%82%89%E3%81%B9%E3%82%8B%E3%81%BE%E3%81%A0%E3%81%AA%E3%81%8C%E3%81%8F%E3%81%97%E3%81%AA%E3%81%84%E3%81%A8%E3%81%9F%E3%82%8A%E3%81%AA%E3%81%84.%E3%81%BB%E3%82%93%E3%81%A8%E3%81%86%E3%81%AB%E3%81%AA%E3%81%8C%E3%81%84%E3%82%8F%E3%81%91%E3%81%AE%E3%82%8F%E3%81%8B%E3%82%89%E3%81%AA%E3%81%84%E3%81%A9%E3%82%81%E3%81%84%E3%82%93%E3%82%81%E3%81%84%E3%81%AE%E3%82%89%E3%81%B9%E3%82%8B%E3%81%BE%E3%81%A0%E3%81%AA%E3%81%8C%E3%81%8F%E3%81%97%E3%81%AA%E3%81%84%E3%81%A8%E3%81%9F%E3%82%8A%E3%81%AA%E3%81%84.w3.mag.keio.ac.jp/'",
+"input": "<base href='http://%E3%81%BB%E3%82%93%E3%81%A8%E3%81%86%E3%81%AB%E3%81%AA%E3%81%8C%E3%81%84%E3%82%8F%E3%81%91%E3%81%AE%E3%82%8F%E3%81%8B%E3%82%89%E3%81%AA%E3%81%84%E3%81%A9%E3%82%81%E3%81%84%E3%82%93%E3%82%81%E3%81%84%E3%81%AE%E3%82%89%E3%81%B9%E3%82%8B%E3%81%BE%E3%81%A0%E3%81%AA%E3%81%8C%E3%81%8F%E3%81%97%E3%81%AA%E3%81%84%E3%81%A8%E3%81%9F%E3%82%8A%E3%81%AA%E3%81%84.%E3%81%BB%E3%82%93%E3%81%A8%E3%81%86%E3%81%AB%E3%81%AA%E3%81%8C%E3%81%84%E3%82%8F%E3%81%91%E3%81%AE%E3%82%8F%E3%81%8B%E3%82%89%E3%81%AA%E3%81%84%E3%81%A9%E3%82%81%E3%81%84%E3%82%93%E3%82%81%E3%81%84%E3%81%AE%E3%82%89%E3%81%B9%E3%82%8B%E3%81%BE%E3%81%A0%E3%81%AA%E3%81%8C%E3%81%8F%E3%81%97%E3%81%AA%E3%81%84%E3%81%A8%E3%81%9F%E3%82%8A%E3%81%AA%E3%81%84.%E3%81%BB%E3%82%93%E3%81%A8%E3%81%86%E3%81%AB%E3%81%AA%E3%81%8C%E3%81%84%E3%82%8F%E3%81%91%E3%81%AE%E3%82%8F%E3%81%8B%E3%82%89%E3%81%AA%E3%81%84%E3%81%A9%E3%82%81%E3%81%84%E3%82%93%E3%82%81%E3%81%84%E3%81%AE%E3%82%89%E3%81%B9%E3%82%8B%E3%81%BE%E3%81%A0%E3%81%AA%E3%81%8C%E3%81%8F%E3%81%97%E3%81%AA%E3%81%84%E3%81%A8%E3%81%9F%E3%82%8A%E3%81%AA%E3%81%84.w3.mag.keio.ac.jp/'",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "base href contains valid URI 'http://xn--n8jaaaaai5bhf7as8fsfk3jnknefdde3fg11amb5gzdb4wi9bya3kc6lra.xn--n8jaaaaai5bhf7as8fsfk3jnknefdde3fg11amb5gzdb4wi9bya3kc6lra.xn--n8jaaaaai5bhf7as8fsfk3jnknefdde3fg11amb5gzdb4wi9bya3kc6lra.w3.mag.keio.ac.jp/'",
+"input": "<base href='http://xn--n8jaaaaai5bhf7as8fsfk3jnknefdde3fg11amb5gzdb4wi9bya3kc6lra.xn--n8jaaaaai5bhf7as8fsfk3jnknefdde3fg11amb5gzdb4wi9bya3kc6lra.xn--n8jaaaaai5bhf7as8fsfk3jnknefdde3fg11amb5gzdb4wi9bya3kc6lra.w3.mag.keio.ac.jp/'",
+"fail-if": "invalid-attribute-value"}
+
+]}
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/base-target-attribute.test b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/base-target-attribute.test
new file mode 100755
index 00000000000..6d4db20b2a0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/base-target-attribute.test
@@ -0,0 +1,35 @@
+{"tests": [
+
+{"description": "valid base target attribute '_self'",
+"input": "<base target=_self>",
+"fail-if": "invalid-browsing-context"},
+
+{"description": "valid base target attribute '_parent'",
+"input": "<base target=_parent>",
+"fail-if": "invalid-browsing-context"},
+
+{"description": "valid base target attribute '_top'",
+"input": "<base target=_top>",
+"fail-if": "invalid-browsing-context"},
+
+{"description": "valid base target attribute '_blank'",
+"input": "<base target=_blank>",
+"fail-if": "invalid-browsing-context"},
+
+{"description": "valid base target attribute 'foo'",
+"input": "<base target=foo>",
+"fail-if": "invalid-browsing-context"},
+
+{"description": "base target attribute may be blank",
+"input": "<base target>",
+"fail-if": "invalid-browsing-context"},
+
+{"description": "invalid base target attribute '_'",
+"input": "<base target=_>",
+"fail-unless": "invalid-browsing-context"},
+
+{"description": "invalid base target attribute '_foo'",
+"input": "<base target=_foo>",
+"fail-unless": "invalid-browsing-context"}
+
+]} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/blockquote-cite-attribute.test b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/blockquote-cite-attribute.test
new file mode 100755
index 00000000000..153c6e6af1d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/blockquote-cite-attribute.test
@@ -0,0 +1,7 @@
+{"tests": [
+
+{"description": "blockquote cite contains invalid URI due to space in domain",
+"input": "<blockquote cite='http://www.example. com/'",
+"fail-unless": "invalid-uri-char"}
+
+]} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/classattribute.test b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/classattribute.test
new file mode 100755
index 00000000000..0fe703fcddc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/classattribute.test
@@ -0,0 +1,152 @@
+{"tests": [
+
+{"description": "valid single class attribute value",
+"input": "<span class=a>",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "valid single class attribute value with leading space",
+"input": "<span class=' a'>",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "valid single class attribute value with trailing space",
+"input": "<span class='a '>",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "valid single class attribute value with leading and trailing space",
+"input": "<span class=' a '>",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "valid single class attribute value with leading tab",
+"input": "<span class='\ta'>",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "valid single class attribute value with trailing tab",
+"input": "<span class='a\t'>",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "valid single class attribute value with leading and trailing tab",
+"input": "<span class='\ta\t'>",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "valid single class attribute value with leading LF",
+"input": "<span class='\na'>",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "valid single class attribute value with trailing LF",
+"input": "<span class='a\n'>",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "valid single class attribute value with leading and trailing LF",
+"input": "<span class='\na\n'>",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "valid single class attribute value with leading LT",
+"input": "<span class='\u000Ba'>",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "valid single class attribute value with trailing LT",
+"input": "<span class='a\u000B'>",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "valid single class attribute value with leading and trailing LT",
+"input": "<span class='\u000Ba\u000B'>",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "valid single class attribute value with leading FF",
+"input": "<span class='\u000Ca'>",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "valid single class attribute value with trailing FF",
+"input": "<span class='a\u000C'>",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "valid single class attribute value with leading and trailing FF",
+"input": "<span class='\u000Ca\u000C'>",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "valid single class attribute value with leading CR",
+"input": "<span class='\ra'>",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "valid single class attribute value with trailing CR",
+"input": "<span class='a\r'>",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "valid single class attribute value with leading and trailing CR",
+"input": "<span class='\ra\r'>",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "valid double class attribute value separated by space",
+"input": "<span class='a b'>",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "valid double class attribute value separated by tab",
+"input": "<span class='a\tb'>",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "valid double class attribute value separated by LF",
+"input": "<span class='a\nb'>",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "valid double class attribute value separated by LT",
+"input": "<span class='a\u000Bb'>",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "valid double class attribute value separated by FF",
+"input": "<span class='a\u000Cb'>",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "valid double class attribute value separated by CR",
+"input": "<span class='a\rb'>",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "invalid duplicated class attribute value separated by space",
+"input": "<span class='a a'>",
+"fail-unless": "invalid-attribute-value"},
+
+{"description": "invalid duplicated class attribute value separated by tab",
+"input": "<span class='a\ta'>",
+"fail-unless": "invalid-attribute-value"},
+
+{"description": "invalid duplicated class attribute value separated by LF",
+"input": "<span class='a\na'>",
+"fail-unless": "invalid-attribute-value"},
+
+{"description": "invalid duplicated class attribute value separated by LT",
+"input": "<span class='a\u000Ba'>",
+"fail-unless": "invalid-attribute-value"},
+
+{"description": "invalid duplicated class attribute value separated by FF",
+"input": "<span class='a\u000Ca'>",
+"fail-unless": "invalid-attribute-value"},
+
+{"description": "invalid duplicated class attribute value separated by CR",
+"input": "<span class='a\ra'>",
+"fail-unless": "duplicate-value-in-token-list"},
+
+{"description": "invalid duplicated class attribute value separated by space",
+"input": "<span class='a a'>",
+"fail-unless": "duplicate-value-in-token-list"},
+
+{"description": "invalid duplicated class attribute value separated by tab",
+"input": "<span class='a\ta'>",
+"fail-unless": "duplicate-value-in-token-list"},
+
+{"description": "invalid duplicated class attribute value separated by LF",
+"input": "<span class='a\na'>",
+"fail-unless": "duplicate-value-in-token-list"},
+
+{"description": "invalid duplicated class attribute value separated by LT",
+"input": "<span class='a\u000Ba'>",
+"fail-unless": "duplicate-value-in-token-list"},
+
+{"description": "invalid duplicated class attribute value separated by FF",
+"input": "<span class='a\u000Ca'>",
+"fail-unless": "duplicate-value-in-token-list"},
+
+{"description": "invalid duplicated class attribute value separated by CR",
+"input": "<span class='a\ra'>",
+"fail-unless": "duplicate-value-in-token-list"}
+
+]}
+
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/contenteditableattribute.test b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/contenteditableattribute.test
new file mode 100755
index 00000000000..b6ae1d27e7e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/contenteditableattribute.test
@@ -0,0 +1,59 @@
+{"tests": [
+
+{"description": "valid contenteditable attribute value 'true'",
+"input": "<span contenteditable=true>",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "valid contenteditable attribute value 'TRUE'",
+"input": "<span contenteditable=TRUE>",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "valid contenteditable attribute value 'TrUe'",
+"input": "<span contenteditable=TrUe>",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "valid contenteditable attribute value 'false'",
+"input": "<span contenteditable=false>",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "valid contenteditable attribute value 'FALSE'",
+"input": "<span contenteditable=FALSE>",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "valid contenteditable attribute value 'FalSe'",
+"input": "<span contenteditable=FalSe>",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "valid contenteditable attribute value ''",
+"input": "<span contenteditable=''>",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "valid contenteditable attribute value (not specified)",
+"input": "<span contenteditable>",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "invalid contenteditable attribute value 'foo'",
+"input": "<span contenteditable=foo>",
+"fail-unless": "invalid-enumerated-value"},
+
+{"description": "invalid contenteditable attribute value '0'",
+"input": "<span contenteditable=0>",
+"fail-unless": "invalid-enumerated-value"},
+
+{"description": "invalid contenteditable attribute value '1'",
+"input": "<span contenteditable=1>",
+"fail-unless": "invalid-enumerated-value"},
+
+{"description": "invalid contenteditable attribute value 'yes'",
+"input": "<span contenteditable=yes>",
+"fail-unless": "invalid-enumerated-value"},
+
+{"description": "invalid contenteditable attribute value 'no'",
+"input": "<span contenteditable=no>",
+"fail-unless": "invalid-enumerated-value"},
+
+{"description": "invalid contenteditable attribute value 'inherit'",
+"input": "<span contenteditable=inherit>",
+"fail-unless": "invalid-enumerated-value"}
+
+]} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/contextmenuattribute.test b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/contextmenuattribute.test
new file mode 100755
index 00000000000..59e4397c911
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/contextmenuattribute.test
@@ -0,0 +1,115 @@
+{"tests": [
+
+{"description": "contextmenu points to valid ID earlier",
+"input": "<menu id=a><span contextmenu=a>",
+"fail-if": "id-does-not-exist"},
+
+{"description": "contextmenu points to valid ID later",
+"input": "<span contextmenu=a><menu id=a>",
+"fail-if": "id-does-not-exist"},
+
+{"description": "contextmenu points to non-existent ID",
+"input": "<span contextmenu=a>",
+"fail-unless": "id-does-not-exist"},
+
+{"description": "contextmenu points to ID on non-menu element",
+"input": "<span id=a><span contextmenu=a>",
+"fail-unless": "contextmenu-must-point-to-menu"},
+
+{"description": "uppercase contextmenu points to ID on non-menu element",
+"input": "<span id=a><span CONTEXTMENU=a>",
+"fail-unless": "contextmenu-must-point-to-menu"},
+
+{"description": "valid ID 'a'",
+"input": "<span contextmenu=a>",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "valid ID '1'",
+"input": "<span contextmenu=1>",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "wacky but valid ID",
+"input": "<span contextmenu='<html><head><title>a</title></head><body><p>b</p></body></html>'>",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "invalid blank ID",
+"input": "<span id>",
+"fail-unless": "attribute-value-can-not-be-blank"},
+
+{"description": "invalid blank ID with quotes",
+"input": "<span contextmenu=''>",
+"fail-unless": "attribute-value-can-not-be-blank"},
+
+{"description": "invalid ID because of leading space",
+"input": "<span contextmenu=' a'>",
+"fail-unless": "space-in-id"},
+
+{"description": "invalid ID because of trailing space",
+"input": "<span contextmenu='a '>",
+"fail-unless": "space-in-id"},
+
+{"description": "invalid ID because of space in value",
+"input": "<span contextmenu='a b'>",
+"fail-unless": "space-in-id"},
+
+{"description": "invalid ID because of leading tab",
+"input": "<span contextmenu='\ta'>",
+"fail-unless": "space-in-id"},
+
+{"description": "invalid ID because of trailing tab",
+"input": "<span contextmenu='a\t'>",
+"fail-unless": "space-in-id"},
+
+{"description": "invalid ID because of tab in value",
+"input": "<span contextmenu='a\tb'>",
+"fail-unless": "space-in-id"},
+
+{"description": "invalid ID because of leading LF",
+"input": "<span contextmenu='\na'>",
+"fail-unless": "space-in-id"},
+
+{"description": "invalid ID because of trailing LF",
+"input": "<span contextmenu='a\n'>",
+"fail-unless": "space-in-id"},
+
+{"description": "invalid ID because of LF in value",
+"input": "<span contextmenu='a\nb'>",
+"fail-unless": "space-in-id"},
+
+{"description": "invalid ID because of leading LT",
+"input": "<span contextmenu='\u000Ba'>",
+"fail-unless": "space-in-id"},
+
+{"description": "invalid ID because of trailing LT",
+"input": "<span contextmenu='a\u000B'>",
+"fail-unless": "space-in-id"},
+
+{"description": "invalid ID because of LT in value",
+"input": "<span contextmenu='a\u000Bb'>",
+"fail-unless": "space-in-id"},
+
+{"description": "invalid ID because of leading FF",
+"input": "<span contextmenu='\u000Ca'>",
+"fail-unless": "space-in-id"},
+
+{"description": "invalid ID because of trailing FF",
+"input": "<span contextmenu='a\u000C'>",
+"fail-unless": "space-in-id"},
+
+{"description": "invalid ID because of FF in value",
+"input": "<span contextmenu='a\u000Cb'>",
+"fail-unless": "space-in-id"},
+
+{"description": "invalid ID because of leading CR",
+"input": "<span contextmenu='\ra'>",
+"fail-unless": "space-in-id"},
+
+{"description": "invalid ID because of trailing CR",
+"input": "<span contextmenu='a\r'>",
+"fail-unless": "space-in-id"},
+
+{"description": "invalid ID because of CR in value",
+"input": "<span contextmenu='a\rb'>",
+"fail-unless": "space-in-id"}
+
+]}
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/dirattribute.test b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/dirattribute.test
new file mode 100755
index 00000000000..71883dc1c34
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/dirattribute.test
@@ -0,0 +1,59 @@
+{"tests": [
+
+{"description": "valid dir attribute value 'ltr'",
+"input": "<span dir=ltr>",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "valid dir attribute value 'LTR'",
+"input": "<span dir=LTR>",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "valid dir attribute value 'LtR'",
+"input": "<span dir=LtR>",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "valid dir attribute value 'rtl'",
+"input": "<span dir=rtl>",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "valid dir attribute value 'RTL'",
+"input": "<span dir=RTL>",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "valid dir attribute value 'RtL'",
+"input": "<span dir=RtL>",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "invalid dir attribute value due to leading space",
+"input": "<span dir=' ltr'>",
+"fail-unless": "invalid-enumerated-value"},
+
+{"description": "dir attribute value can not be blank",
+"input": "<span dir>",
+"fail-unless": "attribute-value-can-not-be-blank"},
+
+{"description": "dir attribute value can not be blank (with quotes)",
+"input": "<span dir=''>",
+"fail-unless": "attribute-value-can-not-be-blank"},
+
+{"description": "invalid dir attribute value 'left'",
+"input": "<span dir=left>",
+"fail-unless": "invalid-enumerated-value"},
+
+{"description": "invalid dir attribute value 'right'",
+"input": "<span dir=right>",
+"fail-unless": "invalid-enumerated-value"},
+
+{"description": "invalid dir attribute value 'lefttoright'",
+"input": "<span dir=lefttoright>",
+"fail-unless": "invalid-enumerated-value"},
+
+{"description": "invalid dir attribute value 'righttoleft'",
+"input": "<span dir=righttoleft>",
+"fail-unless": "invalid-enumerated-value"},
+
+{"description": "invalid dir attribute value 'inherit'",
+"input": "<span dir=inherit>",
+"fail-unless": "invalid-enumerated-value"}
+
+]} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/draggableattribute.test b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/draggableattribute.test
new file mode 100755
index 00000000000..49e692d988f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/draggableattribute.test
@@ -0,0 +1,63 @@
+{"tests": [
+
+{"description": "valid draggable attribute value 'true'",
+"input": "<span draggable=true>",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "valid draggable attribute value 'TRUE'",
+"input": "<span draggable=TRUE>",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "valid draggable attribute value 'TrUe'",
+"input": "<span draggable=TrUe>",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "valid draggable attribute value 'false'",
+"input": "<span draggable=false>",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "valid draggable attribute value 'FALSE'",
+"input": "<span draggable=FALSE>",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "valid draggable attribute value 'FalSe'",
+"input": "<span draggable=FalSe>",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "invalid draggable attribute value ''",
+"input": "<span draggable=''>",
+"fail-unless": "attribute-value-can-not-be-blank"},
+
+{"description": "valid draggable attribute value (not specified)",
+"input": "<span draggable>",
+"fail-unless": "attribute-value-can-not-be-blank"},
+
+{"description": "invalid draggable attribute value 'foo'",
+"input": "<span draggable=foo>",
+"fail-unless": "invalid-enumerated-value"},
+
+{"description": "invalid draggable attribute value '0'",
+"input": "<span draggable=0>",
+"fail-unless": "invalid-enumerated-value"},
+
+{"description": "invalid draggable attribute value '1'",
+"input": "<span draggable=1>",
+"fail-unless": "invalid-enumerated-value"},
+
+{"description": "invalid draggable attribute value 'yes'",
+"input": "<span draggable=yes>",
+"fail-unless": "invalid-enumerated-value"},
+
+{"description": "invalid draggable attribute value 'no'",
+"input": "<span draggable=no>",
+"fail-unless": "invalid-enumerated-value"},
+
+{"description": "invalid draggable attribute value 'auto'",
+"input": "<span draggable=auto>",
+"fail-unless": "invalid-enumerated-value"},
+
+{"description": "invalid draggable attribute value 'inherit'",
+"input": "<span draggable=inherit>",
+"fail-unless": "invalid-enumerated-value"}
+
+]} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/html-xmlns-attribute.test b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/html-xmlns-attribute.test
new file mode 100755
index 00000000000..2ebd19eba88
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/html-xmlns-attribute.test
@@ -0,0 +1,23 @@
+{"tests": [
+
+{"description": "valid html xmlns attribute",
+"input": "<html xmlns=http://www.w3.org/1999/xhtml>",
+"fail-if": "invalid-root-namespace"},
+
+{"description": "invalid html xmlns attribute due to leading space",
+"input": "<html xmlns=' http://www.w3.org/1999/xhtml'>",
+"fail-unless": "invalid-root-namespace"},
+
+{"description": "invalid html xmlns attribute due to trailing space",
+"input": "<html xmlns='http://www.w3.org/1999/xhtml '>",
+"fail-unless": "invalid-root-namespace"},
+
+{"description": "invalid html xmlns attribute due to uppercase",
+"input": "<html xmlns=HTTP://WWW.W3.ORG/1999/XHTML>",
+"fail-unless": "invalid-root-namespace"},
+
+{"description": "invalid xmlns attribute on non-html element",
+"input": "<body xmlns=http://www.w3.org/1999/xhtml>",
+"fail-unless": "unknown-attribute"}
+
+]} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/idattribute.test b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/idattribute.test
new file mode 100755
index 00000000000..4058d5219a3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/idattribute.test
@@ -0,0 +1,115 @@
+{"tests": [
+
+{"description": "valid ID 'a'",
+"input": "<span id=a>",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "valid ID '1'",
+"input": "<span id=1>",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "wacky but valid ID",
+"input": "<span id='<html><head><title>a</title></head><body><p>b</p></body></html>'>",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "invalid blank ID",
+"input": "<span id>",
+"fail-unless": "attribute-value-can-not-be-blank"},
+
+{"description": "invalid blank ID with quotes",
+"input": "<span id=''>",
+"fail-unless": "attribute-value-can-not-be-blank"},
+
+{"description": "invalid ID because of leading space",
+"input": "<span id=' a'>",
+"fail-unless": "space-in-id"},
+
+{"description": "invalid ID because of trailing space",
+"input": "<span id='a '>",
+"fail-unless": "space-in-id"},
+
+{"description": "invalid ID because of space in value",
+"input": "<span id='a b'>",
+"fail-unless": "space-in-id"},
+
+{"description": "invalid ID because of leading tab",
+"input": "<span id='\ta'>",
+"fail-unless": "space-in-id"},
+
+{"description": "invalid ID because of trailing tab",
+"input": "<span id='a\t'>",
+"fail-unless": "space-in-id"},
+
+{"description": "invalid ID because of tab in value",
+"input": "<span id='a\tb'>",
+"fail-unless": "space-in-id"},
+
+{"description": "invalid ID because of leading LF",
+"input": "<span id='\na'>",
+"fail-unless": "space-in-id"},
+
+{"description": "invalid ID because of trailing LF",
+"input": "<span id='a\n'>",
+"fail-unless": "space-in-id"},
+
+{"description": "invalid ID because of LF in value",
+"input": "<span id='a\nb'>",
+"fail-unless": "space-in-id"},
+
+{"description": "invalid ID because of leading LT",
+"input": "<span id='\u000Ba'>",
+"fail-unless": "space-in-id"},
+
+{"description": "invalid ID because of trailing LT",
+"input": "<span id='a\u000B'>",
+"fail-unless": "space-in-id"},
+
+{"description": "invalid ID because of LT in value",
+"input": "<span id='a\u000Bb'>",
+"fail-unless": "space-in-id"},
+
+{"description": "invalid ID because of leading FF",
+"input": "<span id='\u000Ca'>",
+"fail-unless": "space-in-id"},
+
+{"description": "invalid ID because of trailing FF",
+"input": "<span id='a\u000C'>",
+"fail-unless": "space-in-id"},
+
+{"description": "invalid ID because of FF in value",
+"input": "<span id='a\u000Cb'>",
+"fail-unless": "space-in-id"},
+
+{"description": "invalid ID because of leading CR",
+"input": "<span id='\ra'>",
+"fail-unless": "space-in-id"},
+
+{"description": "invalid ID because of trailing CR",
+"input": "<span id='a\r'>",
+"fail-unless": "space-in-id"},
+
+{"description": "invalid ID because of CR in value",
+"input": "<span id='a\rb'>",
+"fail-unless": "space-in-id"},
+
+{"description": "duplicate ID values",
+"input": "<span id=a><span id=a>",
+"fail-unless": "duplicate-id"},
+
+{"description": "duplicate ID values with spaces (weird but true)",
+"input": "<span id='a '><span id='a '>",
+"fail-unless": "duplicate-id"},
+
+{"description": "not duplicate ID values because spaces don't match",
+"input": "<span id=a><span id='a '>",
+"fail-if": "duplicate-id"},
+
+{"description": "not duplicate ID values because spaces don't match",
+"input": "<span id=' a'><span id='a '>",
+"fail-if": "duplicate-id"},
+
+{"description": "not duplicate ID values because case doesn't match",
+"input": "<span id=a><span id=A>",
+"fail-if": "duplicate-id"}
+
+]}
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/inputattributes.test b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/inputattributes.test
new file mode 100755
index 00000000000..acdc50e7bfe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/inputattributes.test
@@ -0,0 +1,2795 @@
+{"tests": [
+
+{"description": "'size' attribute deprecated on <input type='text'>",
+"input": "<input type=text size>",
+"fail-unless": "deprecated-attribute"},
+
+{"description": "'size' attribute deprecated on <input type='password'>",
+"input": "<input type=password size>",
+"fail-unless": "deprecated-attribute"},
+
+{"description": "allowed 'accesskey' attribute on <input type='checkbox'>",
+"input": "<input type=checkbox accesskey>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'accept' attribute not allowed on <input type='checkbox'>",
+"input": "<input type=checkbox accept>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'replace' attribute not allowed on <input type='checkbox'>",
+"input": "<input type=checkbox replace>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'disabled' attribute on <input type='checkbox'>",
+"input": "<input type=checkbox disabled>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'alt' attribute not allowed on <input type='checkbox'>",
+"input": "<input type=checkbox alt>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'size' attribute not allowed on <input type='checkbox'>",
+"input": "<input type=checkbox size>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'checked' attribute on <input type='checkbox'>",
+"input": "<input type=checkbox checked>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'min' attribute not allowed on <input type='checkbox'>",
+"input": "<input type=checkbox min>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'pattern' attribute not allowed on <input type='checkbox'>",
+"input": "<input type=checkbox pattern>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'readonly' attribute not allowed on <input type='checkbox'>",
+"input": "<input type=checkbox readonly>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'template' attribute not allowed on <input type='checkbox'>",
+"input": "<input type=checkbox template>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'autofocus' attribute on <input type='checkbox'>",
+"input": "<input type=checkbox autofocus>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'target' attribute not allowed on <input type='checkbox'>",
+"input": "<input type=checkbox target>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'method' attribute not allowed on <input type='checkbox'>",
+"input": "<input type=checkbox method>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'form' attribute on <input type='checkbox'>",
+"input": "<input type=checkbox form>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'max' attribute not allowed on <input type='checkbox'>",
+"input": "<input type=checkbox max>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'step' attribute not allowed on <input type='checkbox'>",
+"input": "<input type=checkbox step>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'enctype' attribute not allowed on <input type='checkbox'>",
+"input": "<input type=checkbox enctype>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'src' attribute not allowed on <input type='checkbox'>",
+"input": "<input type=checkbox src>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'name' attribute on <input type='checkbox'>",
+"input": "<input type=checkbox name>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'required' attribute on <input type='checkbox'>",
+"input": "<input type=checkbox required>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'list' attribute not allowed on <input type='checkbox'>",
+"input": "<input type=checkbox list>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'value' attribute on <input type='checkbox'>",
+"input": "<input type=checkbox value>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'autocomplete' attribute not allowed on <input type='checkbox'>",
+"input": "<input type=checkbox autocomplete>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'inputmode' attribute not allowed on <input type='checkbox'>",
+"input": "<input type=checkbox inputmode>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'maxlength' attribute not allowed on <input type='checkbox'>",
+"input": "<input type=checkbox maxlength>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'action' attribute not allowed on <input type='checkbox'>",
+"input": "<input type=checkbox action>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'tabindex' attribute on <input type='checkbox'>",
+"input": "<input type=checkbox tabindex>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'accesskey' attribute on <input type='text'>",
+"input": "<input type=text accesskey>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'accept' attribute not allowed on <input type='text'>",
+"input": "<input type=text accept>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'replace' attribute not allowed on <input type='text'>",
+"input": "<input type=text replace>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'disabled' attribute on <input type='text'>",
+"input": "<input type=text disabled>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'alt' attribute not allowed on <input type='text'>",
+"input": "<input type=text alt>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'size' attribute on <input type='text'>",
+"input": "<input type=text size>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'checked' attribute not allowed on <input type='text'>",
+"input": "<input type=text checked>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'min' attribute not allowed on <input type='text'>",
+"input": "<input type=text min>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'pattern' attribute on <input type='text'>",
+"input": "<input type=text pattern>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'readonly' attribute on <input type='text'>",
+"input": "<input type=text readonly>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'template' attribute not allowed on <input type='text'>",
+"input": "<input type=text template>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'autofocus' attribute on <input type='text'>",
+"input": "<input type=text autofocus>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'target' attribute not allowed on <input type='text'>",
+"input": "<input type=text target>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'method' attribute not allowed on <input type='text'>",
+"input": "<input type=text method>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'form' attribute on <input type='text'>",
+"input": "<input type=text form>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'max' attribute not allowed on <input type='text'>",
+"input": "<input type=text max>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'step' attribute not allowed on <input type='text'>",
+"input": "<input type=text step>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'enctype' attribute not allowed on <input type='text'>",
+"input": "<input type=text enctype>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'src' attribute not allowed on <input type='text'>",
+"input": "<input type=text src>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'name' attribute on <input type='text'>",
+"input": "<input type=text name>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'required' attribute on <input type='text'>",
+"input": "<input type=text required>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'list' attribute on <input type='text'>",
+"input": "<input type=text list>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'value' attribute on <input type='text'>",
+"input": "<input type=text value>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'autocomplete' attribute on <input type='text'>",
+"input": "<input type=text autocomplete>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'inputmode' attribute on <input type='text'>",
+"input": "<input type=text inputmode>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'maxlength' attribute on <input type='text'>",
+"input": "<input type=text maxlength>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'action' attribute not allowed on <input type='text'>",
+"input": "<input type=text action>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'tabindex' attribute on <input type='text'>",
+"input": "<input type=text tabindex>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'accesskey' attribute on <input type='image'>",
+"input": "<input type=image accesskey>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'accept' attribute not allowed on <input type='image'>",
+"input": "<input type=image accept>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'replace' attribute on <input type='image'>",
+"input": "<input type=image replace>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'disabled' attribute on <input type='image'>",
+"input": "<input type=image disabled>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'alt' attribute on <input type='image'>",
+"input": "<input type=image alt>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'size' attribute not allowed on <input type='image'>",
+"input": "<input type=image size>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'checked' attribute not allowed on <input type='image'>",
+"input": "<input type=image checked>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'min' attribute not allowed on <input type='image'>",
+"input": "<input type=image min>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'pattern' attribute not allowed on <input type='image'>",
+"input": "<input type=image pattern>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'readonly' attribute not allowed on <input type='image'>",
+"input": "<input type=image readonly>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'template' attribute not allowed on <input type='image'>",
+"input": "<input type=image template>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'autofocus' attribute on <input type='image'>",
+"input": "<input type=image autofocus>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'target' attribute on <input type='image'>",
+"input": "<input type=image target>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'method' attribute on <input type='image'>",
+"input": "<input type=image method>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'form' attribute on <input type='image'>",
+"input": "<input type=image form>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'max' attribute not allowed on <input type='image'>",
+"input": "<input type=image max>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'step' attribute not allowed on <input type='image'>",
+"input": "<input type=image step>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'enctype' attribute on <input type='image'>",
+"input": "<input type=image enctype>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'src' attribute on <input type='image'>",
+"input": "<input type=image src>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'name' attribute on <input type='image'>",
+"input": "<input type=image name>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'required' attribute not allowed on <input type='image'>",
+"input": "<input type=image required>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'list' attribute not allowed on <input type='image'>",
+"input": "<input type=image list>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'value' attribute not allowed on <input type='image'>",
+"input": "<input type=image value>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'autocomplete' attribute not allowed on <input type='image'>",
+"input": "<input type=image autocomplete>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'inputmode' attribute not allowed on <input type='image'>",
+"input": "<input type=image inputmode>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'maxlength' attribute not allowed on <input type='image'>",
+"input": "<input type=image maxlength>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'action' attribute on <input type='image'>",
+"input": "<input type=image action>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'tabindex' attribute on <input type='image'>",
+"input": "<input type=image tabindex>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'accesskey' attribute on <input type='number'>",
+"input": "<input type=number accesskey>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'accept' attribute not allowed on <input type='number'>",
+"input": "<input type=number accept>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'replace' attribute not allowed on <input type='number'>",
+"input": "<input type=number replace>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'disabled' attribute on <input type='number'>",
+"input": "<input type=number disabled>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'alt' attribute not allowed on <input type='number'>",
+"input": "<input type=number alt>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'size' attribute not allowed on <input type='number'>",
+"input": "<input type=number size>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'checked' attribute not allowed on <input type='number'>",
+"input": "<input type=number checked>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'min' attribute on <input type='number'>",
+"input": "<input type=number min>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'pattern' attribute not allowed on <input type='number'>",
+"input": "<input type=number pattern>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'readonly' attribute on <input type='number'>",
+"input": "<input type=number readonly>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'template' attribute not allowed on <input type='number'>",
+"input": "<input type=number template>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'autofocus' attribute on <input type='number'>",
+"input": "<input type=number autofocus>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'target' attribute not allowed on <input type='number'>",
+"input": "<input type=number target>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'method' attribute not allowed on <input type='number'>",
+"input": "<input type=number method>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'form' attribute on <input type='number'>",
+"input": "<input type=number form>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'max' attribute on <input type='number'>",
+"input": "<input type=number max>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'step' attribute on <input type='number'>",
+"input": "<input type=number step>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'enctype' attribute not allowed on <input type='number'>",
+"input": "<input type=number enctype>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'src' attribute not allowed on <input type='number'>",
+"input": "<input type=number src>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'name' attribute on <input type='number'>",
+"input": "<input type=number name>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'required' attribute on <input type='number'>",
+"input": "<input type=number required>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'list' attribute on <input type='number'>",
+"input": "<input type=number list>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'value' attribute on <input type='number'>",
+"input": "<input type=number value>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'autocomplete' attribute on <input type='number'>",
+"input": "<input type=number autocomplete>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'inputmode' attribute not allowed on <input type='number'>",
+"input": "<input type=number inputmode>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'maxlength' attribute not allowed on <input type='number'>",
+"input": "<input type=number maxlength>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'action' attribute not allowed on <input type='number'>",
+"input": "<input type=number action>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'tabindex' attribute on <input type='number'>",
+"input": "<input type=number tabindex>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'accesskey' attribute on <input type='month'>",
+"input": "<input type=month accesskey>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'accept' attribute not allowed on <input type='month'>",
+"input": "<input type=month accept>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'replace' attribute not allowed on <input type='month'>",
+"input": "<input type=month replace>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'disabled' attribute on <input type='month'>",
+"input": "<input type=month disabled>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'alt' attribute not allowed on <input type='month'>",
+"input": "<input type=month alt>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'size' attribute not allowed on <input type='month'>",
+"input": "<input type=month size>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'checked' attribute not allowed on <input type='month'>",
+"input": "<input type=month checked>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'min' attribute on <input type='month'>",
+"input": "<input type=month min>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'pattern' attribute not allowed on <input type='month'>",
+"input": "<input type=month pattern>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'readonly' attribute on <input type='month'>",
+"input": "<input type=month readonly>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'template' attribute not allowed on <input type='month'>",
+"input": "<input type=month template>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'autofocus' attribute on <input type='month'>",
+"input": "<input type=month autofocus>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'target' attribute not allowed on <input type='month'>",
+"input": "<input type=month target>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'method' attribute not allowed on <input type='month'>",
+"input": "<input type=month method>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'form' attribute on <input type='month'>",
+"input": "<input type=month form>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'max' attribute on <input type='month'>",
+"input": "<input type=month max>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'step' attribute on <input type='month'>",
+"input": "<input type=month step>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'enctype' attribute not allowed on <input type='month'>",
+"input": "<input type=month enctype>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'src' attribute not allowed on <input type='month'>",
+"input": "<input type=month src>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'name' attribute on <input type='month'>",
+"input": "<input type=month name>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'required' attribute on <input type='month'>",
+"input": "<input type=month required>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'list' attribute on <input type='month'>",
+"input": "<input type=month list>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'value' attribute on <input type='month'>",
+"input": "<input type=month value>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'autocomplete' attribute on <input type='month'>",
+"input": "<input type=month autocomplete>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'inputmode' attribute not allowed on <input type='month'>",
+"input": "<input type=month inputmode>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'maxlength' attribute not allowed on <input type='month'>",
+"input": "<input type=month maxlength>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'action' attribute not allowed on <input type='month'>",
+"input": "<input type=month action>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'tabindex' attribute on <input type='month'>",
+"input": "<input type=month tabindex>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'accesskey' attribute on <input type='radio'>",
+"input": "<input type=radio accesskey>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'accept' attribute not allowed on <input type='radio'>",
+"input": "<input type=radio accept>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'replace' attribute not allowed on <input type='radio'>",
+"input": "<input type=radio replace>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'disabled' attribute on <input type='radio'>",
+"input": "<input type=radio disabled>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'alt' attribute not allowed on <input type='radio'>",
+"input": "<input type=radio alt>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'size' attribute not allowed on <input type='radio'>",
+"input": "<input type=radio size>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'checked' attribute on <input type='radio'>",
+"input": "<input type=radio checked>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'min' attribute not allowed on <input type='radio'>",
+"input": "<input type=radio min>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'pattern' attribute not allowed on <input type='radio'>",
+"input": "<input type=radio pattern>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'readonly' attribute not allowed on <input type='radio'>",
+"input": "<input type=radio readonly>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'template' attribute not allowed on <input type='radio'>",
+"input": "<input type=radio template>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'autofocus' attribute on <input type='radio'>",
+"input": "<input type=radio autofocus>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'target' attribute not allowed on <input type='radio'>",
+"input": "<input type=radio target>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'method' attribute not allowed on <input type='radio'>",
+"input": "<input type=radio method>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'form' attribute on <input type='radio'>",
+"input": "<input type=radio form>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'max' attribute not allowed on <input type='radio'>",
+"input": "<input type=radio max>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'step' attribute not allowed on <input type='radio'>",
+"input": "<input type=radio step>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'enctype' attribute not allowed on <input type='radio'>",
+"input": "<input type=radio enctype>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'src' attribute not allowed on <input type='radio'>",
+"input": "<input type=radio src>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'name' attribute on <input type='radio'>",
+"input": "<input type=radio name>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'required' attribute on <input type='radio'>",
+"input": "<input type=radio required>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'list' attribute not allowed on <input type='radio'>",
+"input": "<input type=radio list>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'value' attribute on <input type='radio'>",
+"input": "<input type=radio value>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'autocomplete' attribute not allowed on <input type='radio'>",
+"input": "<input type=radio autocomplete>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'inputmode' attribute not allowed on <input type='radio'>",
+"input": "<input type=radio inputmode>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'maxlength' attribute not allowed on <input type='radio'>",
+"input": "<input type=radio maxlength>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'action' attribute not allowed on <input type='radio'>",
+"input": "<input type=radio action>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'tabindex' attribute on <input type='radio'>",
+"input": "<input type=radio tabindex>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'accesskey' attribute on <input type='file'>",
+"input": "<input type=file accesskey>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'accept' attribute on <input type='file'>",
+"input": "<input type=file accept>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'replace' attribute not allowed on <input type='file'>",
+"input": "<input type=file replace>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'disabled' attribute on <input type='file'>",
+"input": "<input type=file disabled>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'alt' attribute not allowed on <input type='file'>",
+"input": "<input type=file alt>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'size' attribute not allowed on <input type='file'>",
+"input": "<input type=file size>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'checked' attribute not allowed on <input type='file'>",
+"input": "<input type=file checked>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'min' attribute on <input type='file'>",
+"input": "<input type=file min>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'pattern' attribute not allowed on <input type='file'>",
+"input": "<input type=file pattern>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'readonly' attribute not allowed on <input type='file'>",
+"input": "<input type=file readonly>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'template' attribute not allowed on <input type='file'>",
+"input": "<input type=file template>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'autofocus' attribute on <input type='file'>",
+"input": "<input type=file autofocus>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'target' attribute not allowed on <input type='file'>",
+"input": "<input type=file target>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'method' attribute not allowed on <input type='file'>",
+"input": "<input type=file method>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'form' attribute on <input type='file'>",
+"input": "<input type=file form>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'max' attribute on <input type='file'>",
+"input": "<input type=file max>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'step' attribute not allowed on <input type='file'>",
+"input": "<input type=file step>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'enctype' attribute not allowed on <input type='file'>",
+"input": "<input type=file enctype>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'src' attribute not allowed on <input type='file'>",
+"input": "<input type=file src>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'name' attribute on <input type='file'>",
+"input": "<input type=file name>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'required' attribute on <input type='file'>",
+"input": "<input type=file required>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'list' attribute not allowed on <input type='file'>",
+"input": "<input type=file list>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'value' attribute not allowed on <input type='file'>",
+"input": "<input type=file value>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'autocomplete' attribute not allowed on <input type='file'>",
+"input": "<input type=file autocomplete>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'inputmode' attribute not allowed on <input type='file'>",
+"input": "<input type=file inputmode>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'maxlength' attribute not allowed on <input type='file'>",
+"input": "<input type=file maxlength>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'action' attribute not allowed on <input type='file'>",
+"input": "<input type=file action>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'tabindex' attribute on <input type='file'>",
+"input": "<input type=file tabindex>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'accesskey' attribute on <input type='password'>",
+"input": "<input type=password accesskey>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'accept' attribute not allowed on <input type='password'>",
+"input": "<input type=password accept>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'replace' attribute not allowed on <input type='password'>",
+"input": "<input type=password replace>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'disabled' attribute on <input type='password'>",
+"input": "<input type=password disabled>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'alt' attribute not allowed on <input type='password'>",
+"input": "<input type=password alt>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'size' attribute on <input type='password'>",
+"input": "<input type=password size>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'checked' attribute not allowed on <input type='password'>",
+"input": "<input type=password checked>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'min' attribute not allowed on <input type='password'>",
+"input": "<input type=password min>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'pattern' attribute on <input type='password'>",
+"input": "<input type=password pattern>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'readonly' attribute on <input type='password'>",
+"input": "<input type=password readonly>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'template' attribute not allowed on <input type='password'>",
+"input": "<input type=password template>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'autofocus' attribute on <input type='password'>",
+"input": "<input type=password autofocus>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'target' attribute not allowed on <input type='password'>",
+"input": "<input type=password target>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'method' attribute not allowed on <input type='password'>",
+"input": "<input type=password method>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'form' attribute on <input type='password'>",
+"input": "<input type=password form>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'max' attribute not allowed on <input type='password'>",
+"input": "<input type=password max>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'step' attribute not allowed on <input type='password'>",
+"input": "<input type=password step>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'enctype' attribute not allowed on <input type='password'>",
+"input": "<input type=password enctype>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'src' attribute not allowed on <input type='password'>",
+"input": "<input type=password src>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'name' attribute on <input type='password'>",
+"input": "<input type=password name>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'required' attribute on <input type='password'>",
+"input": "<input type=password required>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'list' attribute not allowed on <input type='password'>",
+"input": "<input type=password list>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'value' attribute on <input type='password'>",
+"input": "<input type=password value>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'autocomplete' attribute on <input type='password'>",
+"input": "<input type=password autocomplete>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'inputmode' attribute on <input type='password'>",
+"input": "<input type=password inputmode>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'maxlength' attribute on <input type='password'>",
+"input": "<input type=password maxlength>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'action' attribute not allowed on <input type='password'>",
+"input": "<input type=password action>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'tabindex' attribute on <input type='password'>",
+"input": "<input type=password tabindex>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'accesskey' attribute on <input type='move-up'>",
+"input": "<input type=move-up accesskey>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'accept' attribute not allowed on <input type='move-up'>",
+"input": "<input type=move-up accept>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'replace' attribute not allowed on <input type='move-up'>",
+"input": "<input type=move-up replace>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'disabled' attribute on <input type='move-up'>",
+"input": "<input type=move-up disabled>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'alt' attribute not allowed on <input type='move-up'>",
+"input": "<input type=move-up alt>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'size' attribute not allowed on <input type='move-up'>",
+"input": "<input type=move-up size>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'checked' attribute not allowed on <input type='move-up'>",
+"input": "<input type=move-up checked>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'min' attribute not allowed on <input type='move-up'>",
+"input": "<input type=move-up min>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'pattern' attribute not allowed on <input type='move-up'>",
+"input": "<input type=move-up pattern>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'readonly' attribute not allowed on <input type='move-up'>",
+"input": "<input type=move-up readonly>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'template' attribute not allowed on <input type='move-up'>",
+"input": "<input type=move-up template>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'autofocus' attribute on <input type='move-up'>",
+"input": "<input type=move-up autofocus>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'target' attribute not allowed on <input type='move-up'>",
+"input": "<input type=move-up target>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'method' attribute not allowed on <input type='move-up'>",
+"input": "<input type=move-up method>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'form' attribute on <input type='move-up'>",
+"input": "<input type=move-up form>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'max' attribute not allowed on <input type='move-up'>",
+"input": "<input type=move-up max>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'step' attribute not allowed on <input type='move-up'>",
+"input": "<input type=move-up step>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'enctype' attribute not allowed on <input type='move-up'>",
+"input": "<input type=move-up enctype>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'src' attribute not allowed on <input type='move-up'>",
+"input": "<input type=move-up src>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'name' attribute on <input type='move-up'>",
+"input": "<input type=move-up name>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'required' attribute not allowed on <input type='move-up'>",
+"input": "<input type=move-up required>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'list' attribute not allowed on <input type='move-up'>",
+"input": "<input type=move-up list>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'value' attribute on <input type='move-up'>",
+"input": "<input type=move-up value>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'autocomplete' attribute not allowed on <input type='move-up'>",
+"input": "<input type=move-up autocomplete>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'inputmode' attribute not allowed on <input type='move-up'>",
+"input": "<input type=move-up inputmode>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'maxlength' attribute not allowed on <input type='move-up'>",
+"input": "<input type=move-up maxlength>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'action' attribute not allowed on <input type='move-up'>",
+"input": "<input type=move-up action>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'tabindex' attribute on <input type='move-up'>",
+"input": "<input type=move-up tabindex>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'accesskey' attribute on <input type='submit'>",
+"input": "<input type=submit accesskey>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'accept' attribute not allowed on <input type='submit'>",
+"input": "<input type=submit accept>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'replace' attribute on <input type='submit'>",
+"input": "<input type=submit replace>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'disabled' attribute on <input type='submit'>",
+"input": "<input type=submit disabled>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'alt' attribute not allowed on <input type='submit'>",
+"input": "<input type=submit alt>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'size' attribute not allowed on <input type='submit'>",
+"input": "<input type=submit size>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'checked' attribute not allowed on <input type='submit'>",
+"input": "<input type=submit checked>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'min' attribute not allowed on <input type='submit'>",
+"input": "<input type=submit min>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'pattern' attribute not allowed on <input type='submit'>",
+"input": "<input type=submit pattern>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'readonly' attribute not allowed on <input type='submit'>",
+"input": "<input type=submit readonly>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'template' attribute not allowed on <input type='submit'>",
+"input": "<input type=submit template>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'autofocus' attribute on <input type='submit'>",
+"input": "<input type=submit autofocus>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'target' attribute on <input type='submit'>",
+"input": "<input type=submit target>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'method' attribute on <input type='submit'>",
+"input": "<input type=submit method>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'form' attribute on <input type='submit'>",
+"input": "<input type=submit form>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'max' attribute not allowed on <input type='submit'>",
+"input": "<input type=submit max>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'step' attribute not allowed on <input type='submit'>",
+"input": "<input type=submit step>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'enctype' attribute on <input type='submit'>",
+"input": "<input type=submit enctype>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'src' attribute not allowed on <input type='submit'>",
+"input": "<input type=submit src>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'name' attribute on <input type='submit'>",
+"input": "<input type=submit name>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'required' attribute not allowed on <input type='submit'>",
+"input": "<input type=submit required>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'list' attribute not allowed on <input type='submit'>",
+"input": "<input type=submit list>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'value' attribute on <input type='submit'>",
+"input": "<input type=submit value>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'autocomplete' attribute not allowed on <input type='submit'>",
+"input": "<input type=submit autocomplete>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'inputmode' attribute not allowed on <input type='submit'>",
+"input": "<input type=submit inputmode>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'maxlength' attribute not allowed on <input type='submit'>",
+"input": "<input type=submit maxlength>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'action' attribute on <input type='submit'>",
+"input": "<input type=submit action>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'tabindex' attribute on <input type='submit'>",
+"input": "<input type=submit tabindex>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'accesskey' attribute on <input type='add'>",
+"input": "<input type=add accesskey>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'accept' attribute not allowed on <input type='add'>",
+"input": "<input type=add accept>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'replace' attribute not allowed on <input type='add'>",
+"input": "<input type=add replace>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'disabled' attribute on <input type='add'>",
+"input": "<input type=add disabled>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'alt' attribute not allowed on <input type='add'>",
+"input": "<input type=add alt>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'size' attribute not allowed on <input type='add'>",
+"input": "<input type=add size>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'checked' attribute not allowed on <input type='add'>",
+"input": "<input type=add checked>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'min' attribute not allowed on <input type='add'>",
+"input": "<input type=add min>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'pattern' attribute not allowed on <input type='add'>",
+"input": "<input type=add pattern>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'readonly' attribute not allowed on <input type='add'>",
+"input": "<input type=add readonly>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'template' attribute on <input type='add'>",
+"input": "<input type=add template>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'autofocus' attribute on <input type='add'>",
+"input": "<input type=add autofocus>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'target' attribute not allowed on <input type='add'>",
+"input": "<input type=add target>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'method' attribute not allowed on <input type='add'>",
+"input": "<input type=add method>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'form' attribute on <input type='add'>",
+"input": "<input type=add form>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'max' attribute not allowed on <input type='add'>",
+"input": "<input type=add max>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'step' attribute not allowed on <input type='add'>",
+"input": "<input type=add step>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'enctype' attribute not allowed on <input type='add'>",
+"input": "<input type=add enctype>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'src' attribute not allowed on <input type='add'>",
+"input": "<input type=add src>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'name' attribute on <input type='add'>",
+"input": "<input type=add name>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'required' attribute not allowed on <input type='add'>",
+"input": "<input type=add required>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'list' attribute not allowed on <input type='add'>",
+"input": "<input type=add list>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'value' attribute on <input type='add'>",
+"input": "<input type=add value>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'autocomplete' attribute not allowed on <input type='add'>",
+"input": "<input type=add autocomplete>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'inputmode' attribute not allowed on <input type='add'>",
+"input": "<input type=add inputmode>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'maxlength' attribute not allowed on <input type='add'>",
+"input": "<input type=add maxlength>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'action' attribute not allowed on <input type='add'>",
+"input": "<input type=add action>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'tabindex' attribute on <input type='add'>",
+"input": "<input type=add tabindex>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'accesskey' attribute not allowed on <input type='hidden'>",
+"input": "<input type=hidden accesskey>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'accept' attribute not allowed on <input type='hidden'>",
+"input": "<input type=hidden accept>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'replace' attribute not allowed on <input type='hidden'>",
+"input": "<input type=hidden replace>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'disabled' attribute on <input type='hidden'>",
+"input": "<input type=hidden disabled>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'alt' attribute not allowed on <input type='hidden'>",
+"input": "<input type=hidden alt>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'size' attribute not allowed on <input type='hidden'>",
+"input": "<input type=hidden size>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'checked' attribute not allowed on <input type='hidden'>",
+"input": "<input type=hidden checked>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'min' attribute not allowed on <input type='hidden'>",
+"input": "<input type=hidden min>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'pattern' attribute not allowed on <input type='hidden'>",
+"input": "<input type=hidden pattern>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'readonly' attribute not allowed on <input type='hidden'>",
+"input": "<input type=hidden readonly>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'template' attribute not allowed on <input type='hidden'>",
+"input": "<input type=hidden template>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'autofocus' attribute not allowed on <input type='hidden'>",
+"input": "<input type=hidden autofocus>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'target' attribute not allowed on <input type='hidden'>",
+"input": "<input type=hidden target>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'method' attribute not allowed on <input type='hidden'>",
+"input": "<input type=hidden method>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'form' attribute on <input type='hidden'>",
+"input": "<input type=hidden form>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'max' attribute not allowed on <input type='hidden'>",
+"input": "<input type=hidden max>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'step' attribute not allowed on <input type='hidden'>",
+"input": "<input type=hidden step>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'enctype' attribute not allowed on <input type='hidden'>",
+"input": "<input type=hidden enctype>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'src' attribute not allowed on <input type='hidden'>",
+"input": "<input type=hidden src>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'name' attribute on <input type='hidden'>",
+"input": "<input type=hidden name>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'required' attribute not allowed on <input type='hidden'>",
+"input": "<input type=hidden required>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'list' attribute not allowed on <input type='hidden'>",
+"input": "<input type=hidden list>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'value' attribute on <input type='hidden'>",
+"input": "<input type=hidden value>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'autocomplete' attribute not allowed on <input type='hidden'>",
+"input": "<input type=hidden autocomplete>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'inputmode' attribute not allowed on <input type='hidden'>",
+"input": "<input type=hidden inputmode>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'maxlength' attribute not allowed on <input type='hidden'>",
+"input": "<input type=hidden maxlength>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'action' attribute not allowed on <input type='hidden'>",
+"input": "<input type=hidden action>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'tabindex' attribute not allowed on <input type='hidden'>",
+"input": "<input type=hidden tabindex>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'accesskey' attribute on <input type='email'>",
+"input": "<input type=email accesskey>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'accept' attribute not allowed on <input type='email'>",
+"input": "<input type=email accept>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'replace' attribute not allowed on <input type='email'>",
+"input": "<input type=email replace>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'disabled' attribute on <input type='email'>",
+"input": "<input type=email disabled>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'alt' attribute not allowed on <input type='email'>",
+"input": "<input type=email alt>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'size' attribute not allowed on <input type='email'>",
+"input": "<input type=email size>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'checked' attribute not allowed on <input type='email'>",
+"input": "<input type=email checked>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'min' attribute not allowed on <input type='email'>",
+"input": "<input type=email min>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'pattern' attribute on <input type='email'>",
+"input": "<input type=email pattern>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'readonly' attribute on <input type='email'>",
+"input": "<input type=email readonly>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'template' attribute not allowed on <input type='email'>",
+"input": "<input type=email template>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'autofocus' attribute on <input type='email'>",
+"input": "<input type=email autofocus>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'target' attribute not allowed on <input type='email'>",
+"input": "<input type=email target>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'method' attribute not allowed on <input type='email'>",
+"input": "<input type=email method>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'form' attribute on <input type='email'>",
+"input": "<input type=email form>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'max' attribute not allowed on <input type='email'>",
+"input": "<input type=email max>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'step' attribute not allowed on <input type='email'>",
+"input": "<input type=email step>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'enctype' attribute not allowed on <input type='email'>",
+"input": "<input type=email enctype>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'src' attribute not allowed on <input type='email'>",
+"input": "<input type=email src>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'name' attribute on <input type='email'>",
+"input": "<input type=email name>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'required' attribute on <input type='email'>",
+"input": "<input type=email required>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'list' attribute on <input type='email'>",
+"input": "<input type=email list>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'value' attribute on <input type='email'>",
+"input": "<input type=email value>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'autocomplete' attribute on <input type='email'>",
+"input": "<input type=email autocomplete>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'inputmode' attribute on <input type='email'>",
+"input": "<input type=email inputmode>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'maxlength' attribute on <input type='email'>",
+"input": "<input type=email maxlength>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'action' attribute not allowed on <input type='email'>",
+"input": "<input type=email action>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'tabindex' attribute on <input type='email'>",
+"input": "<input type=email tabindex>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'accesskey' attribute on <input type='week'>",
+"input": "<input type=week accesskey>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'accept' attribute not allowed on <input type='week'>",
+"input": "<input type=week accept>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'replace' attribute not allowed on <input type='week'>",
+"input": "<input type=week replace>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'disabled' attribute on <input type='week'>",
+"input": "<input type=week disabled>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'alt' attribute not allowed on <input type='week'>",
+"input": "<input type=week alt>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'size' attribute not allowed on <input type='week'>",
+"input": "<input type=week size>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'checked' attribute not allowed on <input type='week'>",
+"input": "<input type=week checked>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'min' attribute on <input type='week'>",
+"input": "<input type=week min>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'pattern' attribute not allowed on <input type='week'>",
+"input": "<input type=week pattern>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'readonly' attribute on <input type='week'>",
+"input": "<input type=week readonly>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'template' attribute not allowed on <input type='week'>",
+"input": "<input type=week template>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'autofocus' attribute on <input type='week'>",
+"input": "<input type=week autofocus>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'target' attribute not allowed on <input type='week'>",
+"input": "<input type=week target>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'method' attribute not allowed on <input type='week'>",
+"input": "<input type=week method>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'form' attribute on <input type='week'>",
+"input": "<input type=week form>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'max' attribute on <input type='week'>",
+"input": "<input type=week max>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'step' attribute on <input type='week'>",
+"input": "<input type=week step>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'enctype' attribute not allowed on <input type='week'>",
+"input": "<input type=week enctype>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'src' attribute not allowed on <input type='week'>",
+"input": "<input type=week src>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'name' attribute on <input type='week'>",
+"input": "<input type=week name>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'required' attribute on <input type='week'>",
+"input": "<input type=week required>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'list' attribute on <input type='week'>",
+"input": "<input type=week list>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'value' attribute on <input type='week'>",
+"input": "<input type=week value>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'autocomplete' attribute on <input type='week'>",
+"input": "<input type=week autocomplete>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'inputmode' attribute not allowed on <input type='week'>",
+"input": "<input type=week inputmode>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'maxlength' attribute not allowed on <input type='week'>",
+"input": "<input type=week maxlength>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'action' attribute not allowed on <input type='week'>",
+"input": "<input type=week action>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'tabindex' attribute on <input type='week'>",
+"input": "<input type=week tabindex>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'accesskey' attribute on <input type='date'>",
+"input": "<input type=date accesskey>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'accept' attribute not allowed on <input type='date'>",
+"input": "<input type=date accept>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'replace' attribute not allowed on <input type='date'>",
+"input": "<input type=date replace>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'disabled' attribute on <input type='date'>",
+"input": "<input type=date disabled>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'alt' attribute not allowed on <input type='date'>",
+"input": "<input type=date alt>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'size' attribute not allowed on <input type='date'>",
+"input": "<input type=date size>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'checked' attribute not allowed on <input type='date'>",
+"input": "<input type=date checked>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'min' attribute on <input type='date'>",
+"input": "<input type=date min>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'pattern' attribute not allowed on <input type='date'>",
+"input": "<input type=date pattern>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'readonly' attribute on <input type='date'>",
+"input": "<input type=date readonly>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'template' attribute not allowed on <input type='date'>",
+"input": "<input type=date template>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'autofocus' attribute on <input type='date'>",
+"input": "<input type=date autofocus>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'target' attribute not allowed on <input type='date'>",
+"input": "<input type=date target>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'method' attribute not allowed on <input type='date'>",
+"input": "<input type=date method>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'form' attribute on <input type='date'>",
+"input": "<input type=date form>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'max' attribute on <input type='date'>",
+"input": "<input type=date max>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'step' attribute on <input type='date'>",
+"input": "<input type=date step>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'enctype' attribute not allowed on <input type='date'>",
+"input": "<input type=date enctype>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'src' attribute not allowed on <input type='date'>",
+"input": "<input type=date src>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'name' attribute on <input type='date'>",
+"input": "<input type=date name>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'required' attribute on <input type='date'>",
+"input": "<input type=date required>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'list' attribute on <input type='date'>",
+"input": "<input type=date list>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'value' attribute on <input type='date'>",
+"input": "<input type=date value>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'autocomplete' attribute on <input type='date'>",
+"input": "<input type=date autocomplete>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'inputmode' attribute not allowed on <input type='date'>",
+"input": "<input type=date inputmode>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'maxlength' attribute not allowed on <input type='date'>",
+"input": "<input type=date maxlength>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'action' attribute not allowed on <input type='date'>",
+"input": "<input type=date action>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'tabindex' attribute on <input type='date'>",
+"input": "<input type=date tabindex>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'accesskey' attribute on <input type='datetime'>",
+"input": "<input type=datetime accesskey>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'accept' attribute not allowed on <input type='datetime'>",
+"input": "<input type=datetime accept>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'replace' attribute not allowed on <input type='datetime'>",
+"input": "<input type=datetime replace>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'disabled' attribute on <input type='datetime'>",
+"input": "<input type=datetime disabled>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'alt' attribute not allowed on <input type='datetime'>",
+"input": "<input type=datetime alt>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'size' attribute not allowed on <input type='datetime'>",
+"input": "<input type=datetime size>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'checked' attribute not allowed on <input type='datetime'>",
+"input": "<input type=datetime checked>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'min' attribute on <input type='datetime'>",
+"input": "<input type=datetime min>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'pattern' attribute not allowed on <input type='datetime'>",
+"input": "<input type=datetime pattern>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'readonly' attribute on <input type='datetime'>",
+"input": "<input type=datetime readonly>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'template' attribute not allowed on <input type='datetime'>",
+"input": "<input type=datetime template>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'autofocus' attribute on <input type='datetime'>",
+"input": "<input type=datetime autofocus>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'target' attribute not allowed on <input type='datetime'>",
+"input": "<input type=datetime target>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'method' attribute not allowed on <input type='datetime'>",
+"input": "<input type=datetime method>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'form' attribute on <input type='datetime'>",
+"input": "<input type=datetime form>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'max' attribute on <input type='datetime'>",
+"input": "<input type=datetime max>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'step' attribute on <input type='datetime'>",
+"input": "<input type=datetime step>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'enctype' attribute not allowed on <input type='datetime'>",
+"input": "<input type=datetime enctype>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'src' attribute not allowed on <input type='datetime'>",
+"input": "<input type=datetime src>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'name' attribute on <input type='datetime'>",
+"input": "<input type=datetime name>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'required' attribute on <input type='datetime'>",
+"input": "<input type=datetime required>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'list' attribute on <input type='datetime'>",
+"input": "<input type=datetime list>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'value' attribute on <input type='datetime'>",
+"input": "<input type=datetime value>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'autocomplete' attribute on <input type='datetime'>",
+"input": "<input type=datetime autocomplete>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'inputmode' attribute not allowed on <input type='datetime'>",
+"input": "<input type=datetime inputmode>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'maxlength' attribute not allowed on <input type='datetime'>",
+"input": "<input type=datetime maxlength>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'action' attribute not allowed on <input type='datetime'>",
+"input": "<input type=datetime action>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'tabindex' attribute on <input type='datetime'>",
+"input": "<input type=datetime tabindex>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'accesskey' attribute on <input type='move-down'>",
+"input": "<input type=move-down accesskey>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'accept' attribute not allowed on <input type='move-down'>",
+"input": "<input type=move-down accept>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'replace' attribute not allowed on <input type='move-down'>",
+"input": "<input type=move-down replace>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'disabled' attribute on <input type='move-down'>",
+"input": "<input type=move-down disabled>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'alt' attribute not allowed on <input type='move-down'>",
+"input": "<input type=move-down alt>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'size' attribute not allowed on <input type='move-down'>",
+"input": "<input type=move-down size>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'checked' attribute not allowed on <input type='move-down'>",
+"input": "<input type=move-down checked>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'min' attribute not allowed on <input type='move-down'>",
+"input": "<input type=move-down min>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'pattern' attribute not allowed on <input type='move-down'>",
+"input": "<input type=move-down pattern>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'readonly' attribute not allowed on <input type='move-down'>",
+"input": "<input type=move-down readonly>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'template' attribute not allowed on <input type='move-down'>",
+"input": "<input type=move-down template>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'autofocus' attribute on <input type='move-down'>",
+"input": "<input type=move-down autofocus>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'target' attribute not allowed on <input type='move-down'>",
+"input": "<input type=move-down target>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'method' attribute not allowed on <input type='move-down'>",
+"input": "<input type=move-down method>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'form' attribute on <input type='move-down'>",
+"input": "<input type=move-down form>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'max' attribute not allowed on <input type='move-down'>",
+"input": "<input type=move-down max>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'step' attribute not allowed on <input type='move-down'>",
+"input": "<input type=move-down step>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'enctype' attribute not allowed on <input type='move-down'>",
+"input": "<input type=move-down enctype>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'src' attribute not allowed on <input type='move-down'>",
+"input": "<input type=move-down src>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'name' attribute on <input type='move-down'>",
+"input": "<input type=move-down name>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'required' attribute not allowed on <input type='move-down'>",
+"input": "<input type=move-down required>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'list' attribute not allowed on <input type='move-down'>",
+"input": "<input type=move-down list>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'value' attribute on <input type='move-down'>",
+"input": "<input type=move-down value>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'autocomplete' attribute not allowed on <input type='move-down'>",
+"input": "<input type=move-down autocomplete>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'inputmode' attribute not allowed on <input type='move-down'>",
+"input": "<input type=move-down inputmode>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'maxlength' attribute not allowed on <input type='move-down'>",
+"input": "<input type=move-down maxlength>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'action' attribute not allowed on <input type='move-down'>",
+"input": "<input type=move-down action>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'tabindex' attribute on <input type='move-down'>",
+"input": "<input type=move-down tabindex>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'accesskey' attribute on <input type='datetime-local'>",
+"input": "<input type=datetime-local accesskey>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'accept' attribute not allowed on <input type='datetime-local'>",
+"input": "<input type=datetime-local accept>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'replace' attribute not allowed on <input type='datetime-local'>",
+"input": "<input type=datetime-local replace>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'disabled' attribute on <input type='datetime-local'>",
+"input": "<input type=datetime-local disabled>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'alt' attribute not allowed on <input type='datetime-local'>",
+"input": "<input type=datetime-local alt>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'size' attribute not allowed on <input type='datetime-local'>",
+"input": "<input type=datetime-local size>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'checked' attribute not allowed on <input type='datetime-local'>",
+"input": "<input type=datetime-local checked>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'min' attribute on <input type='datetime-local'>",
+"input": "<input type=datetime-local min>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'pattern' attribute not allowed on <input type='datetime-local'>",
+"input": "<input type=datetime-local pattern>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'readonly' attribute on <input type='datetime-local'>",
+"input": "<input type=datetime-local readonly>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'template' attribute not allowed on <input type='datetime-local'>",
+"input": "<input type=datetime-local template>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'autofocus' attribute on <input type='datetime-local'>",
+"input": "<input type=datetime-local autofocus>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'target' attribute not allowed on <input type='datetime-local'>",
+"input": "<input type=datetime-local target>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'method' attribute not allowed on <input type='datetime-local'>",
+"input": "<input type=datetime-local method>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'form' attribute on <input type='datetime-local'>",
+"input": "<input type=datetime-local form>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'max' attribute on <input type='datetime-local'>",
+"input": "<input type=datetime-local max>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'step' attribute on <input type='datetime-local'>",
+"input": "<input type=datetime-local step>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'enctype' attribute not allowed on <input type='datetime-local'>",
+"input": "<input type=datetime-local enctype>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'src' attribute not allowed on <input type='datetime-local'>",
+"input": "<input type=datetime-local src>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'name' attribute on <input type='datetime-local'>",
+"input": "<input type=datetime-local name>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'required' attribute on <input type='datetime-local'>",
+"input": "<input type=datetime-local required>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'list' attribute on <input type='datetime-local'>",
+"input": "<input type=datetime-local list>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'value' attribute on <input type='datetime-local'>",
+"input": "<input type=datetime-local value>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'autocomplete' attribute on <input type='datetime-local'>",
+"input": "<input type=datetime-local autocomplete>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'inputmode' attribute not allowed on <input type='datetime-local'>",
+"input": "<input type=datetime-local inputmode>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'maxlength' attribute not allowed on <input type='datetime-local'>",
+"input": "<input type=datetime-local maxlength>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'action' attribute not allowed on <input type='datetime-local'>",
+"input": "<input type=datetime-local action>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'tabindex' attribute on <input type='datetime-local'>",
+"input": "<input type=datetime-local tabindex>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'accesskey' attribute on <input type='reset'>",
+"input": "<input type=reset accesskey>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'accept' attribute not allowed on <input type='reset'>",
+"input": "<input type=reset accept>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'replace' attribute not allowed on <input type='reset'>",
+"input": "<input type=reset replace>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'disabled' attribute on <input type='reset'>",
+"input": "<input type=reset disabled>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'alt' attribute not allowed on <input type='reset'>",
+"input": "<input type=reset alt>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'size' attribute not allowed on <input type='reset'>",
+"input": "<input type=reset size>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'checked' attribute not allowed on <input type='reset'>",
+"input": "<input type=reset checked>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'min' attribute not allowed on <input type='reset'>",
+"input": "<input type=reset min>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'pattern' attribute not allowed on <input type='reset'>",
+"input": "<input type=reset pattern>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'readonly' attribute not allowed on <input type='reset'>",
+"input": "<input type=reset readonly>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'template' attribute not allowed on <input type='reset'>",
+"input": "<input type=reset template>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'autofocus' attribute on <input type='reset'>",
+"input": "<input type=reset autofocus>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'target' attribute not allowed on <input type='reset'>",
+"input": "<input type=reset target>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'method' attribute not allowed on <input type='reset'>",
+"input": "<input type=reset method>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'form' attribute on <input type='reset'>",
+"input": "<input type=reset form>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'max' attribute not allowed on <input type='reset'>",
+"input": "<input type=reset max>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'step' attribute not allowed on <input type='reset'>",
+"input": "<input type=reset step>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'enctype' attribute not allowed on <input type='reset'>",
+"input": "<input type=reset enctype>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'src' attribute not allowed on <input type='reset'>",
+"input": "<input type=reset src>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'name' attribute on <input type='reset'>",
+"input": "<input type=reset name>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'required' attribute not allowed on <input type='reset'>",
+"input": "<input type=reset required>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'list' attribute not allowed on <input type='reset'>",
+"input": "<input type=reset list>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'value' attribute on <input type='reset'>",
+"input": "<input type=reset value>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'autocomplete' attribute not allowed on <input type='reset'>",
+"input": "<input type=reset autocomplete>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'inputmode' attribute not allowed on <input type='reset'>",
+"input": "<input type=reset inputmode>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'maxlength' attribute not allowed on <input type='reset'>",
+"input": "<input type=reset maxlength>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'action' attribute not allowed on <input type='reset'>",
+"input": "<input type=reset action>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'tabindex' attribute on <input type='reset'>",
+"input": "<input type=reset tabindex>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'accesskey' attribute on <input type='url'>",
+"input": "<input type=url accesskey>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'accept' attribute not allowed on <input type='url'>",
+"input": "<input type=url accept>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'replace' attribute not allowed on <input type='url'>",
+"input": "<input type=url replace>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'disabled' attribute on <input type='url'>",
+"input": "<input type=url disabled>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'alt' attribute not allowed on <input type='url'>",
+"input": "<input type=url alt>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'size' attribute not allowed on <input type='url'>",
+"input": "<input type=url size>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'checked' attribute not allowed on <input type='url'>",
+"input": "<input type=url checked>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'min' attribute not allowed on <input type='url'>",
+"input": "<input type=url min>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'pattern' attribute on <input type='url'>",
+"input": "<input type=url pattern>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'readonly' attribute on <input type='url'>",
+"input": "<input type=url readonly>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'template' attribute not allowed on <input type='url'>",
+"input": "<input type=url template>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'autofocus' attribute on <input type='url'>",
+"input": "<input type=url autofocus>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'target' attribute not allowed on <input type='url'>",
+"input": "<input type=url target>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'method' attribute not allowed on <input type='url'>",
+"input": "<input type=url method>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'form' attribute on <input type='url'>",
+"input": "<input type=url form>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'max' attribute not allowed on <input type='url'>",
+"input": "<input type=url max>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'step' attribute not allowed on <input type='url'>",
+"input": "<input type=url step>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'enctype' attribute not allowed on <input type='url'>",
+"input": "<input type=url enctype>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'src' attribute not allowed on <input type='url'>",
+"input": "<input type=url src>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'name' attribute on <input type='url'>",
+"input": "<input type=url name>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'required' attribute on <input type='url'>",
+"input": "<input type=url required>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'list' attribute on <input type='url'>",
+"input": "<input type=url list>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'value' attribute on <input type='url'>",
+"input": "<input type=url value>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'autocomplete' attribute on <input type='url'>",
+"input": "<input type=url autocomplete>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'inputmode' attribute on <input type='url'>",
+"input": "<input type=url inputmode>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'maxlength' attribute on <input type='url'>",
+"input": "<input type=url maxlength>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'action' attribute not allowed on <input type='url'>",
+"input": "<input type=url action>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'tabindex' attribute on <input type='url'>",
+"input": "<input type=url tabindex>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'accesskey' attribute on <input type='button'>",
+"input": "<input type=button accesskey>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'accept' attribute not allowed on <input type='button'>",
+"input": "<input type=button accept>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'replace' attribute not allowed on <input type='button'>",
+"input": "<input type=button replace>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'disabled' attribute on <input type='button'>",
+"input": "<input type=button disabled>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'alt' attribute not allowed on <input type='button'>",
+"input": "<input type=button alt>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'size' attribute not allowed on <input type='button'>",
+"input": "<input type=button size>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'checked' attribute not allowed on <input type='button'>",
+"input": "<input type=button checked>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'min' attribute not allowed on <input type='button'>",
+"input": "<input type=button min>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'pattern' attribute not allowed on <input type='button'>",
+"input": "<input type=button pattern>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'readonly' attribute not allowed on <input type='button'>",
+"input": "<input type=button readonly>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'template' attribute not allowed on <input type='button'>",
+"input": "<input type=button template>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'autofocus' attribute on <input type='button'>",
+"input": "<input type=button autofocus>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'target' attribute not allowed on <input type='button'>",
+"input": "<input type=button target>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'method' attribute not allowed on <input type='button'>",
+"input": "<input type=button method>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'form' attribute on <input type='button'>",
+"input": "<input type=button form>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'max' attribute not allowed on <input type='button'>",
+"input": "<input type=button max>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'step' attribute not allowed on <input type='button'>",
+"input": "<input type=button step>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'enctype' attribute not allowed on <input type='button'>",
+"input": "<input type=button enctype>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'src' attribute not allowed on <input type='button'>",
+"input": "<input type=button src>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'name' attribute on <input type='button'>",
+"input": "<input type=button name>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'required' attribute not allowed on <input type='button'>",
+"input": "<input type=button required>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'list' attribute not allowed on <input type='button'>",
+"input": "<input type=button list>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'value' attribute on <input type='button'>",
+"input": "<input type=button value>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'autocomplete' attribute not allowed on <input type='button'>",
+"input": "<input type=button autocomplete>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'inputmode' attribute not allowed on <input type='button'>",
+"input": "<input type=button inputmode>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'maxlength' attribute not allowed on <input type='button'>",
+"input": "<input type=button maxlength>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'action' attribute not allowed on <input type='button'>",
+"input": "<input type=button action>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'tabindex' attribute on <input type='button'>",
+"input": "<input type=button tabindex>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'accesskey' attribute on <input type='remove'>",
+"input": "<input type=remove accesskey>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'accept' attribute not allowed on <input type='remove'>",
+"input": "<input type=remove accept>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'replace' attribute not allowed on <input type='remove'>",
+"input": "<input type=remove replace>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'disabled' attribute on <input type='remove'>",
+"input": "<input type=remove disabled>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'alt' attribute not allowed on <input type='remove'>",
+"input": "<input type=remove alt>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'size' attribute not allowed on <input type='remove'>",
+"input": "<input type=remove size>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'checked' attribute not allowed on <input type='remove'>",
+"input": "<input type=remove checked>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'min' attribute not allowed on <input type='remove'>",
+"input": "<input type=remove min>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'pattern' attribute not allowed on <input type='remove'>",
+"input": "<input type=remove pattern>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'readonly' attribute not allowed on <input type='remove'>",
+"input": "<input type=remove readonly>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'template' attribute not allowed on <input type='remove'>",
+"input": "<input type=remove template>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'autofocus' attribute on <input type='remove'>",
+"input": "<input type=remove autofocus>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'target' attribute not allowed on <input type='remove'>",
+"input": "<input type=remove target>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'method' attribute not allowed on <input type='remove'>",
+"input": "<input type=remove method>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'form' attribute on <input type='remove'>",
+"input": "<input type=remove form>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'max' attribute not allowed on <input type='remove'>",
+"input": "<input type=remove max>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'step' attribute not allowed on <input type='remove'>",
+"input": "<input type=remove step>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'enctype' attribute not allowed on <input type='remove'>",
+"input": "<input type=remove enctype>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'src' attribute not allowed on <input type='remove'>",
+"input": "<input type=remove src>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'name' attribute on <input type='remove'>",
+"input": "<input type=remove name>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'required' attribute not allowed on <input type='remove'>",
+"input": "<input type=remove required>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'list' attribute not allowed on <input type='remove'>",
+"input": "<input type=remove list>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'value' attribute on <input type='remove'>",
+"input": "<input type=remove value>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'autocomplete' attribute not allowed on <input type='remove'>",
+"input": "<input type=remove autocomplete>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'inputmode' attribute not allowed on <input type='remove'>",
+"input": "<input type=remove inputmode>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'maxlength' attribute not allowed on <input type='remove'>",
+"input": "<input type=remove maxlength>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'action' attribute not allowed on <input type='remove'>",
+"input": "<input type=remove action>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'tabindex' attribute on <input type='remove'>",
+"input": "<input type=remove tabindex>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'accesskey' attribute on <input type='range'>",
+"input": "<input type=range accesskey>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'accept' attribute not allowed on <input type='range'>",
+"input": "<input type=range accept>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'replace' attribute not allowed on <input type='range'>",
+"input": "<input type=range replace>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'disabled' attribute on <input type='range'>",
+"input": "<input type=range disabled>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'alt' attribute not allowed on <input type='range'>",
+"input": "<input type=range alt>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'size' attribute not allowed on <input type='range'>",
+"input": "<input type=range size>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'checked' attribute not allowed on <input type='range'>",
+"input": "<input type=range checked>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'min' attribute on <input type='range'>",
+"input": "<input type=range min>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'pattern' attribute not allowed on <input type='range'>",
+"input": "<input type=range pattern>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'readonly' attribute on <input type='range'>",
+"input": "<input type=range readonly>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'template' attribute not allowed on <input type='range'>",
+"input": "<input type=range template>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'autofocus' attribute on <input type='range'>",
+"input": "<input type=range autofocus>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'target' attribute not allowed on <input type='range'>",
+"input": "<input type=range target>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'method' attribute not allowed on <input type='range'>",
+"input": "<input type=range method>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'form' attribute on <input type='range'>",
+"input": "<input type=range form>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'max' attribute on <input type='range'>",
+"input": "<input type=range max>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'step' attribute on <input type='range'>",
+"input": "<input type=range step>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'enctype' attribute not allowed on <input type='range'>",
+"input": "<input type=range enctype>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'src' attribute not allowed on <input type='range'>",
+"input": "<input type=range src>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'name' attribute on <input type='range'>",
+"input": "<input type=range name>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'required' attribute on <input type='range'>",
+"input": "<input type=range required>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'list' attribute on <input type='range'>",
+"input": "<input type=range list>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'value' attribute on <input type='range'>",
+"input": "<input type=range value>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'autocomplete' attribute on <input type='range'>",
+"input": "<input type=range autocomplete>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'inputmode' attribute not allowed on <input type='range'>",
+"input": "<input type=range inputmode>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'maxlength' attribute not allowed on <input type='range'>",
+"input": "<input type=range maxlength>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'action' attribute not allowed on <input type='range'>",
+"input": "<input type=range action>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'tabindex' attribute on <input type='range'>",
+"input": "<input type=range tabindex>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'accesskey' attribute on <input type='time'>",
+"input": "<input type=time accesskey>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'accept' attribute not allowed on <input type='time'>",
+"input": "<input type=time accept>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'replace' attribute not allowed on <input type='time'>",
+"input": "<input type=time replace>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'disabled' attribute on <input type='time'>",
+"input": "<input type=time disabled>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'alt' attribute not allowed on <input type='time'>",
+"input": "<input type=time alt>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'size' attribute not allowed on <input type='time'>",
+"input": "<input type=time size>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'checked' attribute not allowed on <input type='time'>",
+"input": "<input type=time checked>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'min' attribute on <input type='time'>",
+"input": "<input type=time min>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'pattern' attribute not allowed on <input type='time'>",
+"input": "<input type=time pattern>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'readonly' attribute on <input type='time'>",
+"input": "<input type=time readonly>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'template' attribute not allowed on <input type='time'>",
+"input": "<input type=time template>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'autofocus' attribute on <input type='time'>",
+"input": "<input type=time autofocus>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'target' attribute not allowed on <input type='time'>",
+"input": "<input type=time target>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'method' attribute not allowed on <input type='time'>",
+"input": "<input type=time method>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'form' attribute on <input type='time'>",
+"input": "<input type=time form>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'max' attribute on <input type='time'>",
+"input": "<input type=time max>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'step' attribute on <input type='time'>",
+"input": "<input type=time step>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'enctype' attribute not allowed on <input type='time'>",
+"input": "<input type=time enctype>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'src' attribute not allowed on <input type='time'>",
+"input": "<input type=time src>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'name' attribute on <input type='time'>",
+"input": "<input type=time name>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'required' attribute on <input type='time'>",
+"input": "<input type=time required>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'list' attribute on <input type='time'>",
+"input": "<input type=time list>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'value' attribute on <input type='time'>",
+"input": "<input type=time value>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'autocomplete' attribute on <input type='time'>",
+"input": "<input type=time autocomplete>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'inputmode' attribute not allowed on <input type='time'>",
+"input": "<input type=time inputmode>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'maxlength' attribute not allowed on <input type='time'>",
+"input": "<input type=time maxlength>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "'action' attribute not allowed on <input type='time'>",
+"input": "<input type=time action>",
+"fail-unless": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "allowed 'tabindex' attribute on <input type='time'>",
+"input": "<input type=time tabindex>",
+"fail-if": "attribute-not-allowed-on-this-input-type"},
+
+{"description": "unknown 'foo' attribute on <input type='checkbox'>",
+"input": "<input type=checkbox foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <input type='text'>",
+"input": "<input type=text foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <input type='image'>",
+"input": "<input type=image foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <input type='number'>",
+"input": "<input type=number foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <input type='month'>",
+"input": "<input type=month foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <input type='radio'>",
+"input": "<input type=radio foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <input type='file'>",
+"input": "<input type=file foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <input type='password'>",
+"input": "<input type=password foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <input type='move-up'>",
+"input": "<input type=move-up foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <input type='submit'>",
+"input": "<input type=submit foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <input type='add'>",
+"input": "<input type=add foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <input type='hidden'>",
+"input": "<input type=hidden foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <input type='email'>",
+"input": "<input type=email foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <input type='week'>",
+"input": "<input type=week foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <input type='date'>",
+"input": "<input type=date foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <input type='datetime'>",
+"input": "<input type=datetime foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <input type='move-down'>",
+"input": "<input type=move-down foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <input type='datetime-local'>",
+"input": "<input type=datetime-local foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <input type='reset'>",
+"input": "<input type=reset foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <input type='url'>",
+"input": "<input type=url foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <input type='button'>",
+"input": "<input type=button foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <input type='remove'>",
+"input": "<input type=remove foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <input type='range'>",
+"input": "<input type=range foo>",
+"fail-unless": "unknown-attribute"},
+
+{"description": "unknown 'foo' attribute on <input type='time'>",
+"input": "<input type=time foo>",
+"fail-unless": "unknown-attribute"}
+
+]}
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/irrelevantattribute.test b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/irrelevantattribute.test
new file mode 100755
index 00000000000..fa4061300cd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/irrelevantattribute.test
@@ -0,0 +1,63 @@
+{"tests": [
+
+{"description": "valid irrelevant attribute value 'irrelevant'",
+"input": "<span irrelevant=irrelevant>",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "valid irrelevant attribute value ''",
+"input": "<span irrelevant=''>",
+"fail-if": "invalid-attribute-value"},
+
+{"description": "invalid irrelevant attribute value due to uppercase",
+"input": "<span irrelevant=IRRELEVANT>",
+"fail-unless": "invalid-boolean-value"},
+
+{"description": "invalid irrelevant attribute value due to mixed case",
+"input": "<span irrelevant=IrReLeVaNt>",
+"fail-unless": "invalid-boolean-value"},
+
+{"description": "invalid irrelevant attribute value due to leading space",
+"input": "<span irrelevant=' irrelevant'>",
+"fail-unless": "invalid-boolean-value"},
+
+{"description": "invalid irrelevant attribute value due to trailing space",
+"input": "<span irrelevant='irrelevant '>",
+"fail-unless": "invalid-boolean-value"},
+
+{"description": "invalid irrelevant attribute value 'foo'",
+"input": "<span irrelevant=foo>",
+"fail-unless": "invalid-boolean-value"},
+
+{"description": "invalid irrelevant attribute value '0'",
+"input": "<span irrelevant=0>",
+"fail-unless": "invalid-boolean-value"},
+
+{"description": "invalid irrelevant attribute value '1'",
+"input": "<span irrelevant=1>",
+"fail-unless": "invalid-boolean-value"},
+
+{"description": "invalid irrelevant attribute value 'yes'",
+"input": "<span irrelevant=yes>",
+"fail-unless": "invalid-boolean-value"},
+
+{"description": "invalid irrelevant attribute value 'no'",
+"input": "<span irrelevant=no>",
+"fail-unless": "invalid-boolean-value"},
+
+{"description": "invalid irrelevant attribute value 'true'",
+"input": "<span irrelevant=true>",
+"fail-unless": "invalid-boolean-value"},
+
+{"description": "invalid irrelevant attribute value 'false'",
+"input": "<span irrelevant=false>",
+"fail-unless": "invalid-boolean-value"},
+
+{"description": "invalid irrelevant attribute value 'auto'",
+"input": "<span irrelevant=auto>",
+"fail-unless": "invalid-boolean-value"},
+
+{"description": "invalid irrelevant attribute value 'inherit'",
+"input": "<span irrelevant=inherit>",
+"fail-unless": "invalid-boolean-value"}
+
+]} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/langattribute.test b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/langattribute.test
new file mode 100755
index 00000000000..6c831a179d8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/langattribute.test
@@ -0,0 +1,5579 @@
+{"tests": [
+
+{"description": "valid lang attribute 'roh'",
+"input": "<span lang=roh>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'gv'",
+"input": "<span lang=gv>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'gu'",
+"input": "<span lang=gu>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'scn'",
+"input": "<span lang=scn>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'rom'",
+"input": "<span lang=rom>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ron'",
+"input": "<span lang=ron>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'alg'",
+"input": "<span lang=alg>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'oss'",
+"input": "<span lang=oss>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ale'",
+"input": "<span lang=ale>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'alb'",
+"input": "<span lang=alb>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sco'",
+"input": "<span lang=sco>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'scc'",
+"input": "<span lang=scc>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mni'",
+"input": "<span lang=mni>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'gd'",
+"input": "<span lang=gd>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'per'",
+"input": "<span lang=per>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ga'",
+"input": "<span lang=ga>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nwc'",
+"input": "<span lang=nwc>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'osa'",
+"input": "<span lang=osa>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'gn'",
+"input": "<span lang=gn>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'alt'",
+"input": "<span lang=alt>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'gl'",
+"input": "<span lang=gl>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'scr'",
+"input": "<span lang=scr>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mwr'",
+"input": "<span lang=mwr>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ty'",
+"input": "<span lang=ty>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tw'",
+"input": "<span lang=tw>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tt'",
+"input": "<span lang=tt>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tr'",
+"input": "<span lang=tr>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ts'",
+"input": "<span lang=ts>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tn'",
+"input": "<span lang=tn>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'to'",
+"input": "<span lang=to>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tl'",
+"input": "<span lang=tl>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tk'",
+"input": "<span lang=tk>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'th'",
+"input": "<span lang=th>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ti'",
+"input": "<span lang=ti>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ven'",
+"input": "<span lang=ven>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tg'",
+"input": "<span lang=tg>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'te'",
+"input": "<span lang=te>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'uga'",
+"input": "<span lang=uga>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ta'",
+"input": "<span lang=ta>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'fas'",
+"input": "<span lang=fas>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'fat'",
+"input": "<span lang=fat>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'fan'",
+"input": "<span lang=fan>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'fao'",
+"input": "<span lang=fao>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'got'",
+"input": "<span lang=got>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sme'",
+"input": "<span lang=sme>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'din'",
+"input": "<span lang=din>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'hye'",
+"input": "<span lang=hye>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'guj'",
+"input": "<span lang=guj>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'cmc'",
+"input": "<span lang=cmc>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'srd'",
+"input": "<span lang=srd>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mdr'",
+"input": "<span lang=mdr>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ml'",
+"input": "<span lang=ml>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'div'",
+"input": "<span lang=div>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'zh'",
+"input": "<span lang=zh>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tem'",
+"input": "<span lang=tem>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'xho'",
+"input": "<span lang=xho>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mno'",
+"input": "<span lang=mno>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'roa'",
+"input": "<span lang=roa>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'za'",
+"input": "<span lang=za>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'deu'",
+"input": "<span lang=deu>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mk'",
+"input": "<span lang=mk>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nbl'",
+"input": "<span lang=nbl>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'zu'",
+"input": "<span lang=zu>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ter'",
+"input": "<span lang=ter>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tet'",
+"input": "<span lang=tet>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mnc'",
+"input": "<span lang=mnc>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sun'",
+"input": "<span lang=sun>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'abk'",
+"input": "<span lang=abk>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'suk'",
+"input": "<span lang=suk>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kur'",
+"input": "<span lang=kur>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kum'",
+"input": "<span lang=kum>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'slo'",
+"input": "<span lang=slo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sus'",
+"input": "<span lang=sus>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'new'",
+"input": "<span lang=new>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kua'",
+"input": "<span lang=kua>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sux'",
+"input": "<span lang=sux>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'den'",
+"input": "<span lang=den>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mr'",
+"input": "<span lang=mr>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mul'",
+"input": "<span lang=mul>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'lez'",
+"input": "<span lang=lez>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'gla'",
+"input": "<span lang=gla>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bos'",
+"input": "<span lang=bos>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'gle'",
+"input": "<span lang=gle>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'eka'",
+"input": "<span lang=eka>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'glg'",
+"input": "<span lang=glg>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'akk'",
+"input": "<span lang=akk>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'dra'",
+"input": "<span lang=dra>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'aka'",
+"input": "<span lang=aka>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bod'",
+"input": "<span lang=bod>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'glv'",
+"input": "<span lang=glv>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'jrb'",
+"input": "<span lang=jrb>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'vie'",
+"input": "<span lang=vie>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ipk'",
+"input": "<span lang=ipk>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'uzb'",
+"input": "<span lang=uzb>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sgn'",
+"input": "<span lang=sgn>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sga'",
+"input": "<span lang=sga>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bre'",
+"input": "<span lang=bre>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'apa'",
+"input": "<span lang=apa>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bra'",
+"input": "<span lang=bra>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'aym'",
+"input": "<span lang=aym>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'cha'",
+"input": "<span lang=cha>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'chb'",
+"input": "<span lang=chb>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'che'",
+"input": "<span lang=che>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'chg'",
+"input": "<span lang=chg>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'chi'",
+"input": "<span lang=chi>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'chk'",
+"input": "<span lang=chk>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'aus'",
+"input": "<span lang=aus>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'chn'",
+"input": "<span lang=chn>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'cho'",
+"input": "<span lang=cho>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'chp'",
+"input": "<span lang=chp>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'chr'",
+"input": "<span lang=chr>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'chu'",
+"input": "<span lang=chu>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'chv'",
+"input": "<span lang=chv>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'chy'",
+"input": "<span lang=chy>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'msa'",
+"input": "<span lang=msa>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'iii'",
+"input": "<span lang=iii>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'vot'",
+"input": "<span lang=vot>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mg'",
+"input": "<span lang=mg>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ndo'",
+"input": "<span lang=ndo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ibo'",
+"input": "<span lang=ibo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'car'",
+"input": "<span lang=car>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mo'",
+"input": "<span lang=mo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mn'",
+"input": "<span lang=mn>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mi'",
+"input": "<span lang=mi>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mh'",
+"input": "<span lang=mh>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'cau'",
+"input": "<span lang=cau>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'cat'",
+"input": "<span lang=cat>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bur'",
+"input": "<span lang=bur>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mt'",
+"input": "<span lang=mt>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'cai'",
+"input": "<span lang=cai>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'del'",
+"input": "<span lang=del>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ms'",
+"input": "<span lang=ms>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'byn'",
+"input": "<span lang=byn>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mwl'",
+"input": "<span lang=mwl>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'my'",
+"input": "<span lang=my>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'cad'",
+"input": "<span lang=cad>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tat'",
+"input": "<span lang=tat>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nde'",
+"input": "<span lang=nde>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tam'",
+"input": "<span lang=tam>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'spa'",
+"input": "<span lang=spa>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tah'",
+"input": "<span lang=tah>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tai'",
+"input": "<span lang=tai>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'cze'",
+"input": "<span lang=cze>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'afh'",
+"input": "<span lang=afh>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'eng'",
+"input": "<span lang=eng>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'afa'",
+"input": "<span lang=afa>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'id'",
+"input": "<span lang=id>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nyn'",
+"input": "<span lang=nyn>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nyo'",
+"input": "<span lang=nyo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'gez'",
+"input": "<span lang=gez>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nya'",
+"input": "<span lang=nya>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sio'",
+"input": "<span lang=sio>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sin'",
+"input": "<span lang=sin>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'afr'",
+"input": "<span lang=afr>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'map'",
+"input": "<span lang=map>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'fr'",
+"input": "<span lang=fr>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'lao'",
+"input": "<span lang=lao>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'lah'",
+"input": "<span lang=lah>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nym'",
+"input": "<span lang=nym>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sna'",
+"input": "<span lang=sna>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'lad'",
+"input": "<span lang=lad>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'fy'",
+"input": "<span lang=fy>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'snk'",
+"input": "<span lang=snk>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'fa'",
+"input": "<span lang=fa>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mac'",
+"input": "<span lang=mac>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mad'",
+"input": "<span lang=mad>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ff'",
+"input": "<span lang=ff>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'lat'",
+"input": "<span lang=lat>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'fi'",
+"input": "<span lang=fi>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'fj'",
+"input": "<span lang=fj>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mal'",
+"input": "<span lang=mal>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mao'",
+"input": "<span lang=mao>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'fo'",
+"input": "<span lang=fo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mak'",
+"input": "<span lang=mak>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'egy'",
+"input": "<span lang=egy>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'znd'",
+"input": "<span lang=znd>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ss'",
+"input": "<span lang=ss>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sr'",
+"input": "<span lang=sr>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sq'",
+"input": "<span lang=sq>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sit'",
+"input": "<span lang=sit>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sw'",
+"input": "<span lang=sw>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sv'",
+"input": "<span lang=sv>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'su'",
+"input": "<span lang=su>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'st'",
+"input": "<span lang=st>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sk'",
+"input": "<span lang=sk>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'si'",
+"input": "<span lang=si>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sh'",
+"input": "<span lang=sh>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'so'",
+"input": "<span lang=so>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sn'",
+"input": "<span lang=sn>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sm'",
+"input": "<span lang=sm>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sl'",
+"input": "<span lang=sl>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sc'",
+"input": "<span lang=sc>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sa'",
+"input": "<span lang=sa>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sg'",
+"input": "<span lang=sg>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'se'",
+"input": "<span lang=se>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sd'",
+"input": "<span lang=sd>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'zen'",
+"input": "<span lang=zen>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kbd'",
+"input": "<span lang=kbd>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'enm'",
+"input": "<span lang=enm>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'iro'",
+"input": "<span lang=iro>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'vai'",
+"input": "<span lang=vai>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'csb'",
+"input": "<span lang=csb>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tsn'",
+"input": "<span lang=tsn>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'lg'",
+"input": "<span lang=lg>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'lb'",
+"input": "<span lang=lb>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'la'",
+"input": "<span lang=la>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ln'",
+"input": "<span lang=ln>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'lo'",
+"input": "<span lang=lo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'li'",
+"input": "<span lang=li>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'lv'",
+"input": "<span lang=lv>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'lt'",
+"input": "<span lang=lt>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'lu'",
+"input": "<span lang=lu>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'hin'",
+"input": "<span lang=hin>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'fij'",
+"input": "<span lang=fij>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'fin'",
+"input": "<span lang=fin>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'eus'",
+"input": "<span lang=eus>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'yi'",
+"input": "<span lang=yi>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'non'",
+"input": "<span lang=non>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ceb'",
+"input": "<span lang=ceb>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'yo'",
+"input": "<span lang=yo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'dan'",
+"input": "<span lang=dan>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'cel'",
+"input": "<span lang=cel>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bat'",
+"input": "<span lang=bat>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nob'",
+"input": "<span lang=nob>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'dak'",
+"input": "<span lang=dak>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ces'",
+"input": "<span lang=ces>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'dar'",
+"input": "<span lang=dar>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'son'",
+"input": "<span lang=son>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'day'",
+"input": "<span lang=day>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nor'",
+"input": "<span lang=nor>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'gba'",
+"input": "<span lang=gba>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ssa'",
+"input": "<span lang=ssa>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'hil'",
+"input": "<span lang=hil>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kpe'",
+"input": "<span lang=kpe>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'man'",
+"input": "<span lang=man>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'wel'",
+"input": "<span lang=wel>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'el'",
+"input": "<span lang=el>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'eo'",
+"input": "<span lang=eo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'en'",
+"input": "<span lang=en>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'lam'",
+"input": "<span lang=lam>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ee'",
+"input": "<span lang=ee>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tpi'",
+"input": "<span lang=tpi>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mdf'",
+"input": "<span lang=mdf>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mas'",
+"input": "<span lang=mas>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mar'",
+"input": "<span lang=mar>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'eu'",
+"input": "<span lang=eu>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'et'",
+"input": "<span lang=et>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'es'",
+"input": "<span lang=es>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ru'",
+"input": "<span lang=ru>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'rw'",
+"input": "<span lang=rw>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'goh'",
+"input": "<span lang=goh>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sms'",
+"input": "<span lang=sms>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'smo'",
+"input": "<span lang=smo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'smn'",
+"input": "<span lang=smn>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'smj'",
+"input": "<span lang=smj>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'smi'",
+"input": "<span lang=smi>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nic'",
+"input": "<span lang=nic>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'rm'",
+"input": "<span lang=rm>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'rn'",
+"input": "<span lang=rn>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ro'",
+"input": "<span lang=ro>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'dsb'",
+"input": "<span lang=dsb>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sma'",
+"input": "<span lang=sma>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'gor'",
+"input": "<span lang=gor>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ast'",
+"input": "<span lang=ast>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'orm'",
+"input": "<span lang=orm>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'que'",
+"input": "<span lang=que>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ori'",
+"input": "<span lang=ori>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'crh'",
+"input": "<span lang=crh>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'asm'",
+"input": "<span lang=asm>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'pus'",
+"input": "<span lang=pus>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kik'",
+"input": "<span lang=kik>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ltz'",
+"input": "<span lang=ltz>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ath'",
+"input": "<span lang=ath>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'wln'",
+"input": "<span lang=wln>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'isl'",
+"input": "<span lang=isl>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'xh'",
+"input": "<span lang=xh>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mag'",
+"input": "<span lang=mag>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mai'",
+"input": "<span lang=mai>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'xx'",
+"input": "<span lang=xx>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mah'",
+"input": "<span lang=mah>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tel'",
+"input": "<span lang=tel>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'lav'",
+"input": "<span lang=lav>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'zap'",
+"input": "<span lang=zap>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'yid'",
+"input": "<span lang=yid>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kok'",
+"input": "<span lang=kok>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kom'",
+"input": "<span lang=kom>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kon'",
+"input": "<span lang=kon>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ukr'",
+"input": "<span lang=ukr>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ton'",
+"input": "<span lang=ton>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kos'",
+"input": "<span lang=kos>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kor'",
+"input": "<span lang=kor>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tog'",
+"input": "<span lang=tog>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'hun'",
+"input": "<span lang=hun>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'hup'",
+"input": "<span lang=hup>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'cym'",
+"input": "<span lang=cym>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'udm'",
+"input": "<span lang=udm>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bej'",
+"input": "<span lang=bej>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ben'",
+"input": "<span lang=ben>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bel'",
+"input": "<span lang=bel>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bem'",
+"input": "<span lang=bem>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tsi'",
+"input": "<span lang=tsi>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'aar'",
+"input": "<span lang=aar>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ber'",
+"input": "<span lang=ber>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nzi'",
+"input": "<span lang=nzi>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sai'",
+"input": "<span lang=sai>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ang'",
+"input": "<span lang=ang>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'pra'",
+"input": "<span lang=pra>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'san'",
+"input": "<span lang=san>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bho'",
+"input": "<span lang=bho>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sal'",
+"input": "<span lang=sal>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'pro'",
+"input": "<span lang=pro>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'raj'",
+"input": "<span lang=raj>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sad'",
+"input": "<span lang=sad>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'anp'",
+"input": "<span lang=anp>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'rap'",
+"input": "<span lang=rap>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sas'",
+"input": "<span lang=sas>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'iba'",
+"input": "<span lang=iba>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'myn'",
+"input": "<span lang=myn>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'min'",
+"input": "<span lang=min>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'lim'",
+"input": "<span lang=lim>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'lin'",
+"input": "<span lang=lin>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nah'",
+"input": "<span lang=nah>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'lit'",
+"input": "<span lang=lit>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'efi'",
+"input": "<span lang=efi>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'srn'",
+"input": "<span lang=srn>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'arn'",
+"input": "<span lang=arn>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ypk'",
+"input": "<span lang=ypk>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mis'",
+"input": "<span lang=mis>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kac'",
+"input": "<span lang=kac>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kab'",
+"input": "<span lang=kab>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kaa'",
+"input": "<span lang=kaa>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kan'",
+"input": "<span lang=kan>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kam'",
+"input": "<span lang=kam>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kal'",
+"input": "<span lang=kal>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kas'",
+"input": "<span lang=kas>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kar'",
+"input": "<span lang=kar>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kaw'",
+"input": "<span lang=kaw>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kau'",
+"input": "<span lang=kau>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kat'",
+"input": "<span lang=kat>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kaz'",
+"input": "<span lang=kaz>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tyv'",
+"input": "<span lang=tyv>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'awa'",
+"input": "<span lang=awa>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'urd'",
+"input": "<span lang=urd>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ka'",
+"input": "<span lang=ka>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'doi'",
+"input": "<span lang=doi>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kg'",
+"input": "<span lang=kg>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kk'",
+"input": "<span lang=kk>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kj'",
+"input": "<span lang=kj>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ki'",
+"input": "<span lang=ki>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ko'",
+"input": "<span lang=ko>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kn'",
+"input": "<span lang=kn>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'km'",
+"input": "<span lang=km>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kl'",
+"input": "<span lang=kl>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ks'",
+"input": "<span lang=ks>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kr'",
+"input": "<span lang=kr>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kw'",
+"input": "<span lang=kw>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kv'",
+"input": "<span lang=kv>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ku'",
+"input": "<span lang=ku>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ky'",
+"input": "<span lang=ky>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ota'",
+"input": "<span lang=ota>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kut'",
+"input": "<span lang=kut>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tkl'",
+"input": "<span lang=tkl>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nld'",
+"input": "<span lang=nld>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'oji'",
+"input": "<span lang=oji>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'oci'",
+"input": "<span lang=oci>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ha'",
+"input": "<span lang=ha>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'wol'",
+"input": "<span lang=wol>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'jav'",
+"input": "<span lang=jav>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'hrv'",
+"input": "<span lang=hrv>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ger'",
+"input": "<span lang=ger>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mga'",
+"input": "<span lang=mga>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'hit'",
+"input": "<span lang=hit>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'dyu'",
+"input": "<span lang=dyu>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ssw'",
+"input": "<span lang=ssw>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'de'",
+"input": "<span lang=de>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'da'",
+"input": "<span lang=da>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'dz'",
+"input": "<span lang=dz>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'lui'",
+"input": "<span lang=lui>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'dv'",
+"input": "<span lang=dv>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ita'",
+"input": "<span lang=ita>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'geo'",
+"input": "<span lang=geo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'him'",
+"input": "<span lang=him>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'gem'",
+"input": "<span lang=gem>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'crp'",
+"input": "<span lang=crp>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'qu'",
+"input": "<span lang=qu>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bas'",
+"input": "<span lang=bas>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'baq'",
+"input": "<span lang=baq>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bad'",
+"input": "<span lang=bad>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nep'",
+"input": "<span lang=nep>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'cre'",
+"input": "<span lang=cre>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ban'",
+"input": "<span lang=ban>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'x'",
+"input": "<span lang=x>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bal'",
+"input": "<span lang=bal>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bam'",
+"input": "<span lang=bam>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bak'",
+"input": "<span lang=bak>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'shn'",
+"input": "<span lang=shn>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bai'",
+"input": "<span lang=bai>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'arp'",
+"input": "<span lang=arp>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'art'",
+"input": "<span lang=art>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'arw'",
+"input": "<span lang=arw>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'qtz'",
+"input": "<span lang=qtz>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ara'",
+"input": "<span lang=ara>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'arc'",
+"input": "<span lang=arc>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'arg'",
+"input": "<span lang=arg>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sem'",
+"input": "<span lang=sem>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sel'",
+"input": "<span lang=sel>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nub'",
+"input": "<span lang=nub>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'arm'",
+"input": "<span lang=arm>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'btk'",
+"input": "<span lang=btk>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'lus'",
+"input": "<span lang=lus>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'iku'",
+"input": "<span lang=iku>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mus'",
+"input": "<span lang=mus>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'lua'",
+"input": "<span lang=lua>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'lub'",
+"input": "<span lang=lub>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'lug'",
+"input": "<span lang=lug>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ira'",
+"input": "<span lang=ira>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mun'",
+"input": "<span lang=mun>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tur'",
+"input": "<span lang=tur>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'lun'",
+"input": "<span lang=lun>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'luo'",
+"input": "<span lang=luo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'men'",
+"input": "<span lang=men>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'wa'",
+"input": "<span lang=wa>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tso'",
+"input": "<span lang=tso>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'wo'",
+"input": "<span lang=wo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'jv'",
+"input": "<span lang=jv>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tut'",
+"input": "<span lang=tut>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ind'",
+"input": "<span lang=ind>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tuk'",
+"input": "<span lang=tuk>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tum'",
+"input": "<span lang=tum>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ja'",
+"input": "<span lang=ja>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'cop'",
+"input": "<span lang=cop>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'cos'",
+"input": "<span lang=cos>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'cor'",
+"input": "<span lang=cor>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ilo'",
+"input": "<span lang=ilo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'fiu'",
+"input": "<span lang=fiu>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'gwi'",
+"input": "<span lang=gwi>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'und'",
+"input": "<span lang=und>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'gws'",
+"input": "<span lang=gws>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tli'",
+"input": "<span lang=tli>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tlh'",
+"input": "<span lang=tlh>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nno'",
+"input": "<span lang=nno>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ch'",
+"input": "<span lang=ch>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'co'",
+"input": "<span lang=co>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ca'",
+"input": "<span lang=ca>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'por'",
+"input": "<span lang=por>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ce'",
+"input": "<span lang=ce>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'pon'",
+"input": "<span lang=pon>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'cy'",
+"input": "<span lang=cy>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sah'",
+"input": "<span lang=sah>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'cs'",
+"input": "<span lang=cs>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'cr'",
+"input": "<span lang=cr>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ady'",
+"input": "<span lang=ady>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'cv'",
+"input": "<span lang=cv>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'cu'",
+"input": "<span lang=cu>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ps'",
+"input": "<span lang=ps>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'fra'",
+"input": "<span lang=fra>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'dum'",
+"input": "<span lang=dum>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'pt'",
+"input": "<span lang=pt>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'swa'",
+"input": "<span lang=swa>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'dua'",
+"input": "<span lang=dua>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'fro'",
+"input": "<span lang=fro>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'yap'",
+"input": "<span lang=yap>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'frm'",
+"input": "<span lang=frm>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tiv'",
+"input": "<span lang=tiv>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'frs'",
+"input": "<span lang=frs>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'frr'",
+"input": "<span lang=frr>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'yao'",
+"input": "<span lang=yao>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'pa'",
+"input": "<span lang=pa>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'xal'",
+"input": "<span lang=xal>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'fry'",
+"input": "<span lang=fry>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'pi'",
+"input": "<span lang=pi>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'dut'",
+"input": "<span lang=dut>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'pl'",
+"input": "<span lang=pl>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'gay'",
+"input": "<span lang=gay>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'oto'",
+"input": "<span lang=oto>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sag'",
+"input": "<span lang=sag>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'hmn'",
+"input": "<span lang=hmn>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'hmo'",
+"input": "<span lang=hmo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'an'",
+"input": "<span lang=an>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'gaa'",
+"input": "<span lang=gaa>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'fur'",
+"input": "<span lang=fur>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mlg'",
+"input": "<span lang=mlg>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'slv'",
+"input": "<span lang=slv>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ain'",
+"input": "<span lang=ain>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'fil'",
+"input": "<span lang=fil>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mlt'",
+"input": "<span lang=mlt>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'slk'",
+"input": "<span lang=slk>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'rar'",
+"input": "<span lang=rar>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ful'",
+"input": "<span lang=ful>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sla'",
+"input": "<span lang=sla>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 've'",
+"input": "<span lang=ve>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'jpn'",
+"input": "<span lang=jpn>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'vol'",
+"input": "<span lang=vol>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'vi'",
+"input": "<span lang=vi>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'is'",
+"input": "<span lang=is>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kho'",
+"input": "<span lang=kho>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'iu'",
+"input": "<span lang=iu>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'it'",
+"input": "<span lang=it>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'vo'",
+"input": "<span lang=vo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ii'",
+"input": "<span lang=ii>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ay'",
+"input": "<span lang=ay>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ik'",
+"input": "<span lang=ik>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'io'",
+"input": "<span lang=io>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kha'",
+"input": "<span lang=kha>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ia'",
+"input": "<span lang=ia>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ave'",
+"input": "<span lang=ave>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'jpr'",
+"input": "<span lang=jpr>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ie'",
+"input": "<span lang=ie>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ava'",
+"input": "<span lang=ava>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ig'",
+"input": "<span lang=ig>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'pap'",
+"input": "<span lang=pap>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ewo'",
+"input": "<span lang=ewo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'pau'",
+"input": "<span lang=pau>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ewe'",
+"input": "<span lang=ewe>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'paa'",
+"input": "<span lang=paa>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'qaa'",
+"input": "<span lang=qaa>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'pag'",
+"input": "<span lang=pag>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sat'",
+"input": "<span lang=sat>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'pal'",
+"input": "<span lang=pal>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'pam'",
+"input": "<span lang=pam>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'pan'",
+"input": "<span lang=pan>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'phi'",
+"input": "<span lang=phi>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nog'",
+"input": "<span lang=nog>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'phn'",
+"input": "<span lang=phn>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kir'",
+"input": "<span lang=kir>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nia'",
+"input": "<span lang=nia>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'dgr'",
+"input": "<span lang=dgr>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'syr'",
+"input": "<span lang=syr>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kin'",
+"input": "<span lang=kin>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tup'",
+"input": "<span lang=tup>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'niu'",
+"input": "<span lang=niu>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'gsw'",
+"input": "<span lang=gsw>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'epo'",
+"input": "<span lang=epo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'jbo'",
+"input": "<span lang=jbo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mic'",
+"input": "<span lang=mic>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tha'",
+"input": "<span lang=tha>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sam'",
+"input": "<span lang=sam>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'hai'",
+"input": "<span lang=hai>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'gmh'",
+"input": "<span lang=gmh>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'cus'",
+"input": "<span lang=cus>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ell'",
+"input": "<span lang=ell>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'wen'",
+"input": "<span lang=wen>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bnt'",
+"input": "<span lang=bnt>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'fre'",
+"input": "<span lang=fre>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'elx'",
+"input": "<span lang=elx>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ada'",
+"input": "<span lang=ada>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nav'",
+"input": "<span lang=nav>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'hat'",
+"input": "<span lang=hat>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'hau'",
+"input": "<span lang=hau>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'haw'",
+"input": "<span lang=haw>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bin'",
+"input": "<span lang=bin>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'amh'",
+"input": "<span lang=amh>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bik'",
+"input": "<span lang=bik>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bih'",
+"input": "<span lang=bih>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mos'",
+"input": "<span lang=mos>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'moh'",
+"input": "<span lang=moh>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mon'",
+"input": "<span lang=mon>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mol'",
+"input": "<span lang=mol>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bis'",
+"input": "<span lang=bis>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bla'",
+"input": "<span lang=bla>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'pol'",
+"input": "<span lang=pol>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tib'",
+"input": "<span lang=tib>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tvl'",
+"input": "<span lang=tvl>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tgk'",
+"input": "<span lang=tgk>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ijo'",
+"input": "<span lang=ijo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'est'",
+"input": "<span lang=est>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kmb'",
+"input": "<span lang=kmb>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ice'",
+"input": "<span lang=ice>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'peo'",
+"input": "<span lang=peo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tgl'",
+"input": "<span lang=tgl>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'umb'",
+"input": "<span lang=umb>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tmh'",
+"input": "<span lang=tmh>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'fon'",
+"input": "<span lang=fon>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'hsb'",
+"input": "<span lang=hsb>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'be'",
+"input": "<span lang=be>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bg'",
+"input": "<span lang=bg>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'run'",
+"input": "<span lang=run>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ba'",
+"input": "<span lang=ba>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'rum'",
+"input": "<span lang=rum>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bm'",
+"input": "<span lang=bm>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bn'",
+"input": "<span lang=bn>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bo'",
+"input": "<span lang=bo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bh'",
+"input": "<span lang=bh>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bi'",
+"input": "<span lang=bi>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'br'",
+"input": "<span lang=br>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bs'",
+"input": "<span lang=bs>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'rus'",
+"input": "<span lang=rus>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'rup'",
+"input": "<span lang=rup>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'pli'",
+"input": "<span lang=pli>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'om'",
+"input": "<span lang=om>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'oj'",
+"input": "<span lang=oj>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ace'",
+"input": "<span lang=ace>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ach'",
+"input": "<span lang=ach>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'oc'",
+"input": "<span lang=oc>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'dzo'",
+"input": "<span lang=dzo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kru'",
+"input": "<span lang=kru>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'srr'",
+"input": "<span lang=srr>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ido'",
+"input": "<span lang=ido>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'srp'",
+"input": "<span lang=srp>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kro'",
+"input": "<span lang=kro>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'krl'",
+"input": "<span lang=krl>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'krc'",
+"input": "<span lang=krc>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nds'",
+"input": "<span lang=nds>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'os'",
+"input": "<span lang=os>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'or'",
+"input": "<span lang=or>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'zul'",
+"input": "<span lang=zul>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'twi'",
+"input": "<span lang=twi>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sog'",
+"input": "<span lang=sog>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nso'",
+"input": "<span lang=nso>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'swe'",
+"input": "<span lang=swe>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'som'",
+"input": "<span lang=som>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'chm'",
+"input": "<span lang=chm>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'snd'",
+"input": "<span lang=snd>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sot'",
+"input": "<span lang=sot>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mkd'",
+"input": "<span lang=mkd>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'wak'",
+"input": "<span lang=wak>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'her'",
+"input": "<span lang=her>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'lol'",
+"input": "<span lang=lol>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mkh'",
+"input": "<span lang=mkh>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'heb'",
+"input": "<span lang=heb>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'loz'",
+"input": "<span lang=loz>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'gil'",
+"input": "<span lang=gil>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'was'",
+"input": "<span lang=was>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'war'",
+"input": "<span lang=war>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'hz'",
+"input": "<span lang=hz>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'hy'",
+"input": "<span lang=hy>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sid'",
+"input": "<span lang=sid>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'hr'",
+"input": "<span lang=hr>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ht'",
+"input": "<span lang=ht>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'hu'",
+"input": "<span lang=hu>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'hi'",
+"input": "<span lang=hi>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ho'",
+"input": "<span lang=ho>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bul'",
+"input": "<span lang=bul>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'wal'",
+"input": "<span lang=wal>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bua'",
+"input": "<span lang=bua>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bug'",
+"input": "<span lang=bug>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'he'",
+"input": "<span lang=he>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'uz'",
+"input": "<span lang=uz>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'aze'",
+"input": "<span lang=aze>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ur'",
+"input": "<span lang=ur>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'zha'",
+"input": "<span lang=zha>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'uk'",
+"input": "<span lang=uk>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ug'",
+"input": "<span lang=ug>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'zho'",
+"input": "<span lang=zho>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'aa'",
+"input": "<span lang=aa>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ab'",
+"input": "<span lang=ab>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ae'",
+"input": "<span lang=ae>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'uig'",
+"input": "<span lang=uig>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'af'",
+"input": "<span lang=af>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ak'",
+"input": "<span lang=ak>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'am'",
+"input": "<span lang=am>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'myv'",
+"input": "<span lang=myv>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'khi'",
+"input": "<span lang=khi>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'as'",
+"input": "<span lang=as>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ar'",
+"input": "<span lang=ar>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'inh'",
+"input": "<span lang=inh>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'khm'",
+"input": "<span lang=khm>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'av'",
+"input": "<span lang=av>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mya'",
+"input": "<span lang=mya>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ine'",
+"input": "<span lang=ine>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'az'",
+"input": "<span lang=az>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ina'",
+"input": "<span lang=ina>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'inc'",
+"input": "<span lang=inc>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nl'",
+"input": "<span lang=nl>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nn'",
+"input": "<span lang=nn>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'no'",
+"input": "<span lang=no>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'na'",
+"input": "<span lang=na>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nb'",
+"input": "<span lang=nb>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nai'",
+"input": "<span lang=nai>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nd'",
+"input": "<span lang=nd>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ne'",
+"input": "<span lang=ne>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tir'",
+"input": "<span lang=tir>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ng'",
+"input": "<span lang=ng>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ny'",
+"input": "<span lang=ny>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nap'",
+"input": "<span lang=nap>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'gre'",
+"input": "<span lang=gre>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'grb'",
+"input": "<span lang=grb>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'grc'",
+"input": "<span lang=grc>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nau'",
+"input": "<span lang=nau>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'grn'",
+"input": "<span lang=grn>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nr'",
+"input": "<span lang=nr>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tig'",
+"input": "<span lang=tig>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'yor'",
+"input": "<span lang=yor>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nv'",
+"input": "<span lang=nv>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mri'",
+"input": "<span lang=mri>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'may'",
+"input": "<span lang=may>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'zun'",
+"input": "<span lang=zun>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ile'",
+"input": "<span lang=ile>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sqi'",
+"input": "<span lang=sqi>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'gon'",
+"input": "<span lang=gon>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'cpe'",
+"input": "<span lang=cpe>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'cpf'",
+"input": "<span lang=cpf>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'cpp'",
+"input": "<span lang=cpp>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'roh-foo'",
+"input": "<span lang=roh-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'gv-foo'",
+"input": "<span lang=gv-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'gu-foo'",
+"input": "<span lang=gu-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'scn-foo'",
+"input": "<span lang=scn-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'rom-foo'",
+"input": "<span lang=rom-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ron-foo'",
+"input": "<span lang=ron-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'alg-foo'",
+"input": "<span lang=alg-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'oss-foo'",
+"input": "<span lang=oss-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ale-foo'",
+"input": "<span lang=ale-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'alb-foo'",
+"input": "<span lang=alb-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sco-foo'",
+"input": "<span lang=sco-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'scc-foo'",
+"input": "<span lang=scc-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mni-foo'",
+"input": "<span lang=mni-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'gd-foo'",
+"input": "<span lang=gd-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'per-foo'",
+"input": "<span lang=per-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ga-foo'",
+"input": "<span lang=ga-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nwc-foo'",
+"input": "<span lang=nwc-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'osa-foo'",
+"input": "<span lang=osa-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'gn-foo'",
+"input": "<span lang=gn-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'alt-foo'",
+"input": "<span lang=alt-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'gl-foo'",
+"input": "<span lang=gl-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'scr-foo'",
+"input": "<span lang=scr-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mwr-foo'",
+"input": "<span lang=mwr-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ty-foo'",
+"input": "<span lang=ty-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tw-foo'",
+"input": "<span lang=tw-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tt-foo'",
+"input": "<span lang=tt-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tr-foo'",
+"input": "<span lang=tr-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ts-foo'",
+"input": "<span lang=ts-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tn-foo'",
+"input": "<span lang=tn-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'to-foo'",
+"input": "<span lang=to-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tl-foo'",
+"input": "<span lang=tl-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tk-foo'",
+"input": "<span lang=tk-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'th-foo'",
+"input": "<span lang=th-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ti-foo'",
+"input": "<span lang=ti-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ven-foo'",
+"input": "<span lang=ven-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tg-foo'",
+"input": "<span lang=tg-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'te-foo'",
+"input": "<span lang=te-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'uga-foo'",
+"input": "<span lang=uga-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ta-foo'",
+"input": "<span lang=ta-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'fas-foo'",
+"input": "<span lang=fas-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'fat-foo'",
+"input": "<span lang=fat-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'fan-foo'",
+"input": "<span lang=fan-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'fao-foo'",
+"input": "<span lang=fao-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'got-foo'",
+"input": "<span lang=got-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sme-foo'",
+"input": "<span lang=sme-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'din-foo'",
+"input": "<span lang=din-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'hye-foo'",
+"input": "<span lang=hye-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'guj-foo'",
+"input": "<span lang=guj-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'cmc-foo'",
+"input": "<span lang=cmc-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'srd-foo'",
+"input": "<span lang=srd-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mdr-foo'",
+"input": "<span lang=mdr-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ml-foo'",
+"input": "<span lang=ml-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'div-foo'",
+"input": "<span lang=div-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'zh-foo'",
+"input": "<span lang=zh-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tem-foo'",
+"input": "<span lang=tem-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'xho-foo'",
+"input": "<span lang=xho-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mno-foo'",
+"input": "<span lang=mno-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'roa-foo'",
+"input": "<span lang=roa-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'za-foo'",
+"input": "<span lang=za-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'deu-foo'",
+"input": "<span lang=deu-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mk-foo'",
+"input": "<span lang=mk-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nbl-foo'",
+"input": "<span lang=nbl-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'zu-foo'",
+"input": "<span lang=zu-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ter-foo'",
+"input": "<span lang=ter-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tet-foo'",
+"input": "<span lang=tet-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mnc-foo'",
+"input": "<span lang=mnc-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sun-foo'",
+"input": "<span lang=sun-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'abk-foo'",
+"input": "<span lang=abk-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'suk-foo'",
+"input": "<span lang=suk-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kur-foo'",
+"input": "<span lang=kur-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kum-foo'",
+"input": "<span lang=kum-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'slo-foo'",
+"input": "<span lang=slo-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sus-foo'",
+"input": "<span lang=sus-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'new-foo'",
+"input": "<span lang=new-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kua-foo'",
+"input": "<span lang=kua-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sux-foo'",
+"input": "<span lang=sux-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'den-foo'",
+"input": "<span lang=den-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mr-foo'",
+"input": "<span lang=mr-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mul-foo'",
+"input": "<span lang=mul-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'lez-foo'",
+"input": "<span lang=lez-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'gla-foo'",
+"input": "<span lang=gla-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bos-foo'",
+"input": "<span lang=bos-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'gle-foo'",
+"input": "<span lang=gle-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'eka-foo'",
+"input": "<span lang=eka-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'glg-foo'",
+"input": "<span lang=glg-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'akk-foo'",
+"input": "<span lang=akk-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'dra-foo'",
+"input": "<span lang=dra-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'aka-foo'",
+"input": "<span lang=aka-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bod-foo'",
+"input": "<span lang=bod-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'glv-foo'",
+"input": "<span lang=glv-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'jrb-foo'",
+"input": "<span lang=jrb-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'vie-foo'",
+"input": "<span lang=vie-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ipk-foo'",
+"input": "<span lang=ipk-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'uzb-foo'",
+"input": "<span lang=uzb-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sgn-foo'",
+"input": "<span lang=sgn-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sga-foo'",
+"input": "<span lang=sga-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bre-foo'",
+"input": "<span lang=bre-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'apa-foo'",
+"input": "<span lang=apa-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bra-foo'",
+"input": "<span lang=bra-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'aym-foo'",
+"input": "<span lang=aym-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'cha-foo'",
+"input": "<span lang=cha-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'chb-foo'",
+"input": "<span lang=chb-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'che-foo'",
+"input": "<span lang=che-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'chg-foo'",
+"input": "<span lang=chg-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'chi-foo'",
+"input": "<span lang=chi-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'chk-foo'",
+"input": "<span lang=chk-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'aus-foo'",
+"input": "<span lang=aus-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'chn-foo'",
+"input": "<span lang=chn-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'cho-foo'",
+"input": "<span lang=cho-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'chp-foo'",
+"input": "<span lang=chp-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'chr-foo'",
+"input": "<span lang=chr-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'chu-foo'",
+"input": "<span lang=chu-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'chv-foo'",
+"input": "<span lang=chv-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'chy-foo'",
+"input": "<span lang=chy-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'msa-foo'",
+"input": "<span lang=msa-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'iii-foo'",
+"input": "<span lang=iii-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'vot-foo'",
+"input": "<span lang=vot-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mg-foo'",
+"input": "<span lang=mg-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ndo-foo'",
+"input": "<span lang=ndo-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ibo-foo'",
+"input": "<span lang=ibo-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'car-foo'",
+"input": "<span lang=car-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mo-foo'",
+"input": "<span lang=mo-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mn-foo'",
+"input": "<span lang=mn-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mi-foo'",
+"input": "<span lang=mi-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mh-foo'",
+"input": "<span lang=mh-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'cau-foo'",
+"input": "<span lang=cau-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'cat-foo'",
+"input": "<span lang=cat-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bur-foo'",
+"input": "<span lang=bur-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mt-foo'",
+"input": "<span lang=mt-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'cai-foo'",
+"input": "<span lang=cai-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'del-foo'",
+"input": "<span lang=del-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ms-foo'",
+"input": "<span lang=ms-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'byn-foo'",
+"input": "<span lang=byn-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mwl-foo'",
+"input": "<span lang=mwl-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'my-foo'",
+"input": "<span lang=my-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'cad-foo'",
+"input": "<span lang=cad-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tat-foo'",
+"input": "<span lang=tat-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nde-foo'",
+"input": "<span lang=nde-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tam-foo'",
+"input": "<span lang=tam-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'spa-foo'",
+"input": "<span lang=spa-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tah-foo'",
+"input": "<span lang=tah-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tai-foo'",
+"input": "<span lang=tai-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'cze-foo'",
+"input": "<span lang=cze-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'afh-foo'",
+"input": "<span lang=afh-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'eng-foo'",
+"input": "<span lang=eng-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'afa-foo'",
+"input": "<span lang=afa-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'id-foo'",
+"input": "<span lang=id-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nyn-foo'",
+"input": "<span lang=nyn-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nyo-foo'",
+"input": "<span lang=nyo-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'gez-foo'",
+"input": "<span lang=gez-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nya-foo'",
+"input": "<span lang=nya-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sio-foo'",
+"input": "<span lang=sio-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sin-foo'",
+"input": "<span lang=sin-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'afr-foo'",
+"input": "<span lang=afr-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'map-foo'",
+"input": "<span lang=map-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'fr-foo'",
+"input": "<span lang=fr-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'lao-foo'",
+"input": "<span lang=lao-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'lah-foo'",
+"input": "<span lang=lah-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nym-foo'",
+"input": "<span lang=nym-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sna-foo'",
+"input": "<span lang=sna-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'lad-foo'",
+"input": "<span lang=lad-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'fy-foo'",
+"input": "<span lang=fy-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'snk-foo'",
+"input": "<span lang=snk-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'fa-foo'",
+"input": "<span lang=fa-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mac-foo'",
+"input": "<span lang=mac-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mad-foo'",
+"input": "<span lang=mad-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ff-foo'",
+"input": "<span lang=ff-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'lat-foo'",
+"input": "<span lang=lat-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'fi-foo'",
+"input": "<span lang=fi-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'fj-foo'",
+"input": "<span lang=fj-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mal-foo'",
+"input": "<span lang=mal-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mao-foo'",
+"input": "<span lang=mao-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'fo-foo'",
+"input": "<span lang=fo-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mak-foo'",
+"input": "<span lang=mak-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'egy-foo'",
+"input": "<span lang=egy-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'znd-foo'",
+"input": "<span lang=znd-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ss-foo'",
+"input": "<span lang=ss-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sr-foo'",
+"input": "<span lang=sr-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sq-foo'",
+"input": "<span lang=sq-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sit-foo'",
+"input": "<span lang=sit-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sw-foo'",
+"input": "<span lang=sw-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sv-foo'",
+"input": "<span lang=sv-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'su-foo'",
+"input": "<span lang=su-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'st-foo'",
+"input": "<span lang=st-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sk-foo'",
+"input": "<span lang=sk-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'si-foo'",
+"input": "<span lang=si-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sh-foo'",
+"input": "<span lang=sh-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'so-foo'",
+"input": "<span lang=so-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sn-foo'",
+"input": "<span lang=sn-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sm-foo'",
+"input": "<span lang=sm-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sl-foo'",
+"input": "<span lang=sl-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sc-foo'",
+"input": "<span lang=sc-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sa-foo'",
+"input": "<span lang=sa-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sg-foo'",
+"input": "<span lang=sg-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'se-foo'",
+"input": "<span lang=se-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sd-foo'",
+"input": "<span lang=sd-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'zen-foo'",
+"input": "<span lang=zen-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kbd-foo'",
+"input": "<span lang=kbd-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'enm-foo'",
+"input": "<span lang=enm-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'iro-foo'",
+"input": "<span lang=iro-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'vai-foo'",
+"input": "<span lang=vai-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'csb-foo'",
+"input": "<span lang=csb-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tsn-foo'",
+"input": "<span lang=tsn-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'lg-foo'",
+"input": "<span lang=lg-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'lb-foo'",
+"input": "<span lang=lb-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'la-foo'",
+"input": "<span lang=la-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ln-foo'",
+"input": "<span lang=ln-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'lo-foo'",
+"input": "<span lang=lo-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'li-foo'",
+"input": "<span lang=li-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'lv-foo'",
+"input": "<span lang=lv-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'lt-foo'",
+"input": "<span lang=lt-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'lu-foo'",
+"input": "<span lang=lu-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'hin-foo'",
+"input": "<span lang=hin-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'fij-foo'",
+"input": "<span lang=fij-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'fin-foo'",
+"input": "<span lang=fin-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'eus-foo'",
+"input": "<span lang=eus-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'yi-foo'",
+"input": "<span lang=yi-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'non-foo'",
+"input": "<span lang=non-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ceb-foo'",
+"input": "<span lang=ceb-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'yo-foo'",
+"input": "<span lang=yo-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'dan-foo'",
+"input": "<span lang=dan-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'cel-foo'",
+"input": "<span lang=cel-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bat-foo'",
+"input": "<span lang=bat-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nob-foo'",
+"input": "<span lang=nob-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'dak-foo'",
+"input": "<span lang=dak-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ces-foo'",
+"input": "<span lang=ces-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'dar-foo'",
+"input": "<span lang=dar-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'son-foo'",
+"input": "<span lang=son-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'day-foo'",
+"input": "<span lang=day-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nor-foo'",
+"input": "<span lang=nor-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'gba-foo'",
+"input": "<span lang=gba-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ssa-foo'",
+"input": "<span lang=ssa-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'hil-foo'",
+"input": "<span lang=hil-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kpe-foo'",
+"input": "<span lang=kpe-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'man-foo'",
+"input": "<span lang=man-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'wel-foo'",
+"input": "<span lang=wel-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'el-foo'",
+"input": "<span lang=el-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'eo-foo'",
+"input": "<span lang=eo-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'en-foo'",
+"input": "<span lang=en-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'lam-foo'",
+"input": "<span lang=lam-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ee-foo'",
+"input": "<span lang=ee-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tpi-foo'",
+"input": "<span lang=tpi-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mdf-foo'",
+"input": "<span lang=mdf-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mas-foo'",
+"input": "<span lang=mas-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mar-foo'",
+"input": "<span lang=mar-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'eu-foo'",
+"input": "<span lang=eu-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'et-foo'",
+"input": "<span lang=et-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'es-foo'",
+"input": "<span lang=es-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ru-foo'",
+"input": "<span lang=ru-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'rw-foo'",
+"input": "<span lang=rw-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'goh-foo'",
+"input": "<span lang=goh-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sms-foo'",
+"input": "<span lang=sms-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'smo-foo'",
+"input": "<span lang=smo-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'smn-foo'",
+"input": "<span lang=smn-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'smj-foo'",
+"input": "<span lang=smj-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'smi-foo'",
+"input": "<span lang=smi-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nic-foo'",
+"input": "<span lang=nic-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'rm-foo'",
+"input": "<span lang=rm-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'rn-foo'",
+"input": "<span lang=rn-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ro-foo'",
+"input": "<span lang=ro-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'dsb-foo'",
+"input": "<span lang=dsb-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sma-foo'",
+"input": "<span lang=sma-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'gor-foo'",
+"input": "<span lang=gor-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ast-foo'",
+"input": "<span lang=ast-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'orm-foo'",
+"input": "<span lang=orm-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'que-foo'",
+"input": "<span lang=que-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ori-foo'",
+"input": "<span lang=ori-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'crh-foo'",
+"input": "<span lang=crh-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'asm-foo'",
+"input": "<span lang=asm-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'pus-foo'",
+"input": "<span lang=pus-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kik-foo'",
+"input": "<span lang=kik-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ltz-foo'",
+"input": "<span lang=ltz-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ath-foo'",
+"input": "<span lang=ath-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'wln-foo'",
+"input": "<span lang=wln-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'isl-foo'",
+"input": "<span lang=isl-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'xh-foo'",
+"input": "<span lang=xh-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mag-foo'",
+"input": "<span lang=mag-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mai-foo'",
+"input": "<span lang=mai-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'xx-foo'",
+"input": "<span lang=xx-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mah-foo'",
+"input": "<span lang=mah-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tel-foo'",
+"input": "<span lang=tel-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'lav-foo'",
+"input": "<span lang=lav-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'zap-foo'",
+"input": "<span lang=zap-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'yid-foo'",
+"input": "<span lang=yid-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kok-foo'",
+"input": "<span lang=kok-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kom-foo'",
+"input": "<span lang=kom-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kon-foo'",
+"input": "<span lang=kon-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ukr-foo'",
+"input": "<span lang=ukr-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ton-foo'",
+"input": "<span lang=ton-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kos-foo'",
+"input": "<span lang=kos-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kor-foo'",
+"input": "<span lang=kor-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tog-foo'",
+"input": "<span lang=tog-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'hun-foo'",
+"input": "<span lang=hun-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'hup-foo'",
+"input": "<span lang=hup-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'cym-foo'",
+"input": "<span lang=cym-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'udm-foo'",
+"input": "<span lang=udm-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bej-foo'",
+"input": "<span lang=bej-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ben-foo'",
+"input": "<span lang=ben-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bel-foo'",
+"input": "<span lang=bel-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bem-foo'",
+"input": "<span lang=bem-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tsi-foo'",
+"input": "<span lang=tsi-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'aar-foo'",
+"input": "<span lang=aar-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ber-foo'",
+"input": "<span lang=ber-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nzi-foo'",
+"input": "<span lang=nzi-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sai-foo'",
+"input": "<span lang=sai-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ang-foo'",
+"input": "<span lang=ang-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'pra-foo'",
+"input": "<span lang=pra-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'san-foo'",
+"input": "<span lang=san-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bho-foo'",
+"input": "<span lang=bho-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sal-foo'",
+"input": "<span lang=sal-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'pro-foo'",
+"input": "<span lang=pro-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'raj-foo'",
+"input": "<span lang=raj-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sad-foo'",
+"input": "<span lang=sad-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'anp-foo'",
+"input": "<span lang=anp-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'rap-foo'",
+"input": "<span lang=rap-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sas-foo'",
+"input": "<span lang=sas-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'iba-foo'",
+"input": "<span lang=iba-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'myn-foo'",
+"input": "<span lang=myn-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'min-foo'",
+"input": "<span lang=min-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'lim-foo'",
+"input": "<span lang=lim-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'lin-foo'",
+"input": "<span lang=lin-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nah-foo'",
+"input": "<span lang=nah-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'lit-foo'",
+"input": "<span lang=lit-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'efi-foo'",
+"input": "<span lang=efi-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'srn-foo'",
+"input": "<span lang=srn-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'arn-foo'",
+"input": "<span lang=arn-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ypk-foo'",
+"input": "<span lang=ypk-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mis-foo'",
+"input": "<span lang=mis-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kac-foo'",
+"input": "<span lang=kac-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kab-foo'",
+"input": "<span lang=kab-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kaa-foo'",
+"input": "<span lang=kaa-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kan-foo'",
+"input": "<span lang=kan-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kam-foo'",
+"input": "<span lang=kam-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kal-foo'",
+"input": "<span lang=kal-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kas-foo'",
+"input": "<span lang=kas-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kar-foo'",
+"input": "<span lang=kar-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kaw-foo'",
+"input": "<span lang=kaw-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kau-foo'",
+"input": "<span lang=kau-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kat-foo'",
+"input": "<span lang=kat-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kaz-foo'",
+"input": "<span lang=kaz-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tyv-foo'",
+"input": "<span lang=tyv-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'awa-foo'",
+"input": "<span lang=awa-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'urd-foo'",
+"input": "<span lang=urd-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ka-foo'",
+"input": "<span lang=ka-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'doi-foo'",
+"input": "<span lang=doi-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kg-foo'",
+"input": "<span lang=kg-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kk-foo'",
+"input": "<span lang=kk-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kj-foo'",
+"input": "<span lang=kj-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ki-foo'",
+"input": "<span lang=ki-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ko-foo'",
+"input": "<span lang=ko-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kn-foo'",
+"input": "<span lang=kn-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'km-foo'",
+"input": "<span lang=km-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kl-foo'",
+"input": "<span lang=kl-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ks-foo'",
+"input": "<span lang=ks-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kr-foo'",
+"input": "<span lang=kr-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kw-foo'",
+"input": "<span lang=kw-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kv-foo'",
+"input": "<span lang=kv-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ku-foo'",
+"input": "<span lang=ku-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ky-foo'",
+"input": "<span lang=ky-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ota-foo'",
+"input": "<span lang=ota-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kut-foo'",
+"input": "<span lang=kut-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tkl-foo'",
+"input": "<span lang=tkl-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nld-foo'",
+"input": "<span lang=nld-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'oji-foo'",
+"input": "<span lang=oji-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'oci-foo'",
+"input": "<span lang=oci-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ha-foo'",
+"input": "<span lang=ha-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'wol-foo'",
+"input": "<span lang=wol-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'jav-foo'",
+"input": "<span lang=jav-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'hrv-foo'",
+"input": "<span lang=hrv-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ger-foo'",
+"input": "<span lang=ger-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mga-foo'",
+"input": "<span lang=mga-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'hit-foo'",
+"input": "<span lang=hit-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'dyu-foo'",
+"input": "<span lang=dyu-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ssw-foo'",
+"input": "<span lang=ssw-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'de-foo'",
+"input": "<span lang=de-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'da-foo'",
+"input": "<span lang=da-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'dz-foo'",
+"input": "<span lang=dz-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'lui-foo'",
+"input": "<span lang=lui-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'dv-foo'",
+"input": "<span lang=dv-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ita-foo'",
+"input": "<span lang=ita-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'geo-foo'",
+"input": "<span lang=geo-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'him-foo'",
+"input": "<span lang=him-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'gem-foo'",
+"input": "<span lang=gem-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'crp-foo'",
+"input": "<span lang=crp-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'qu-foo'",
+"input": "<span lang=qu-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bas-foo'",
+"input": "<span lang=bas-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'baq-foo'",
+"input": "<span lang=baq-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bad-foo'",
+"input": "<span lang=bad-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nep-foo'",
+"input": "<span lang=nep-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'cre-foo'",
+"input": "<span lang=cre-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ban-foo'",
+"input": "<span lang=ban-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'x-foo'",
+"input": "<span lang=x-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bal-foo'",
+"input": "<span lang=bal-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bam-foo'",
+"input": "<span lang=bam-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bak-foo'",
+"input": "<span lang=bak-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'shn-foo'",
+"input": "<span lang=shn-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bai-foo'",
+"input": "<span lang=bai-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'arp-foo'",
+"input": "<span lang=arp-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'art-foo'",
+"input": "<span lang=art-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'arw-foo'",
+"input": "<span lang=arw-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'qtz-foo'",
+"input": "<span lang=qtz-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ara-foo'",
+"input": "<span lang=ara-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'arc-foo'",
+"input": "<span lang=arc-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'arg-foo'",
+"input": "<span lang=arg-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sem-foo'",
+"input": "<span lang=sem-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sel-foo'",
+"input": "<span lang=sel-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nub-foo'",
+"input": "<span lang=nub-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'arm-foo'",
+"input": "<span lang=arm-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'btk-foo'",
+"input": "<span lang=btk-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'lus-foo'",
+"input": "<span lang=lus-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'iku-foo'",
+"input": "<span lang=iku-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mus-foo'",
+"input": "<span lang=mus-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'lua-foo'",
+"input": "<span lang=lua-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'lub-foo'",
+"input": "<span lang=lub-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'lug-foo'",
+"input": "<span lang=lug-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ira-foo'",
+"input": "<span lang=ira-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mun-foo'",
+"input": "<span lang=mun-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tur-foo'",
+"input": "<span lang=tur-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'lun-foo'",
+"input": "<span lang=lun-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'luo-foo'",
+"input": "<span lang=luo-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'men-foo'",
+"input": "<span lang=men-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'wa-foo'",
+"input": "<span lang=wa-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tso-foo'",
+"input": "<span lang=tso-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'wo-foo'",
+"input": "<span lang=wo-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'jv-foo'",
+"input": "<span lang=jv-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tut-foo'",
+"input": "<span lang=tut-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ind-foo'",
+"input": "<span lang=ind-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tuk-foo'",
+"input": "<span lang=tuk-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tum-foo'",
+"input": "<span lang=tum-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ja-foo'",
+"input": "<span lang=ja-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'cop-foo'",
+"input": "<span lang=cop-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'cos-foo'",
+"input": "<span lang=cos-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'cor-foo'",
+"input": "<span lang=cor-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ilo-foo'",
+"input": "<span lang=ilo-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'fiu-foo'",
+"input": "<span lang=fiu-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'gwi-foo'",
+"input": "<span lang=gwi-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'und-foo'",
+"input": "<span lang=und-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'gws-foo'",
+"input": "<span lang=gws-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tli-foo'",
+"input": "<span lang=tli-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tlh-foo'",
+"input": "<span lang=tlh-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nno-foo'",
+"input": "<span lang=nno-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ch-foo'",
+"input": "<span lang=ch-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'co-foo'",
+"input": "<span lang=co-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ca-foo'",
+"input": "<span lang=ca-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'por-foo'",
+"input": "<span lang=por-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ce-foo'",
+"input": "<span lang=ce-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'pon-foo'",
+"input": "<span lang=pon-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'cy-foo'",
+"input": "<span lang=cy-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sah-foo'",
+"input": "<span lang=sah-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'cs-foo'",
+"input": "<span lang=cs-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'cr-foo'",
+"input": "<span lang=cr-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ady-foo'",
+"input": "<span lang=ady-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'cv-foo'",
+"input": "<span lang=cv-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'cu-foo'",
+"input": "<span lang=cu-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ps-foo'",
+"input": "<span lang=ps-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'fra-foo'",
+"input": "<span lang=fra-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'dum-foo'",
+"input": "<span lang=dum-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'pt-foo'",
+"input": "<span lang=pt-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'swa-foo'",
+"input": "<span lang=swa-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'dua-foo'",
+"input": "<span lang=dua-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'fro-foo'",
+"input": "<span lang=fro-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'yap-foo'",
+"input": "<span lang=yap-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'frm-foo'",
+"input": "<span lang=frm-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tiv-foo'",
+"input": "<span lang=tiv-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'frs-foo'",
+"input": "<span lang=frs-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'frr-foo'",
+"input": "<span lang=frr-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'yao-foo'",
+"input": "<span lang=yao-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'pa-foo'",
+"input": "<span lang=pa-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'xal-foo'",
+"input": "<span lang=xal-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'fry-foo'",
+"input": "<span lang=fry-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'pi-foo'",
+"input": "<span lang=pi-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'dut-foo'",
+"input": "<span lang=dut-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'pl-foo'",
+"input": "<span lang=pl-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'gay-foo'",
+"input": "<span lang=gay-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'oto-foo'",
+"input": "<span lang=oto-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sag-foo'",
+"input": "<span lang=sag-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'hmn-foo'",
+"input": "<span lang=hmn-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'hmo-foo'",
+"input": "<span lang=hmo-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'an-foo'",
+"input": "<span lang=an-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'gaa-foo'",
+"input": "<span lang=gaa-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'fur-foo'",
+"input": "<span lang=fur-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mlg-foo'",
+"input": "<span lang=mlg-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'slv-foo'",
+"input": "<span lang=slv-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ain-foo'",
+"input": "<span lang=ain-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'fil-foo'",
+"input": "<span lang=fil-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mlt-foo'",
+"input": "<span lang=mlt-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'slk-foo'",
+"input": "<span lang=slk-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'rar-foo'",
+"input": "<span lang=rar-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ful-foo'",
+"input": "<span lang=ful-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sla-foo'",
+"input": "<span lang=sla-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 've-foo'",
+"input": "<span lang=ve-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'jpn-foo'",
+"input": "<span lang=jpn-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'vol-foo'",
+"input": "<span lang=vol-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'vi-foo'",
+"input": "<span lang=vi-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'is-foo'",
+"input": "<span lang=is-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kho-foo'",
+"input": "<span lang=kho-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'iu-foo'",
+"input": "<span lang=iu-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'it-foo'",
+"input": "<span lang=it-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'vo-foo'",
+"input": "<span lang=vo-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ii-foo'",
+"input": "<span lang=ii-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ay-foo'",
+"input": "<span lang=ay-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ik-foo'",
+"input": "<span lang=ik-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'io-foo'",
+"input": "<span lang=io-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kha-foo'",
+"input": "<span lang=kha-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ia-foo'",
+"input": "<span lang=ia-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ave-foo'",
+"input": "<span lang=ave-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'jpr-foo'",
+"input": "<span lang=jpr-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ie-foo'",
+"input": "<span lang=ie-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ava-foo'",
+"input": "<span lang=ava-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ig-foo'",
+"input": "<span lang=ig-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'pap-foo'",
+"input": "<span lang=pap-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ewo-foo'",
+"input": "<span lang=ewo-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'pau-foo'",
+"input": "<span lang=pau-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ewe-foo'",
+"input": "<span lang=ewe-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'paa-foo'",
+"input": "<span lang=paa-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'qaa-foo'",
+"input": "<span lang=qaa-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'pag-foo'",
+"input": "<span lang=pag-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sat-foo'",
+"input": "<span lang=sat-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'pal-foo'",
+"input": "<span lang=pal-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'pam-foo'",
+"input": "<span lang=pam-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'pan-foo'",
+"input": "<span lang=pan-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'phi-foo'",
+"input": "<span lang=phi-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nog-foo'",
+"input": "<span lang=nog-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'phn-foo'",
+"input": "<span lang=phn-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kir-foo'",
+"input": "<span lang=kir-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nia-foo'",
+"input": "<span lang=nia-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'dgr-foo'",
+"input": "<span lang=dgr-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'syr-foo'",
+"input": "<span lang=syr-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kin-foo'",
+"input": "<span lang=kin-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tup-foo'",
+"input": "<span lang=tup-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'niu-foo'",
+"input": "<span lang=niu-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'gsw-foo'",
+"input": "<span lang=gsw-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'epo-foo'",
+"input": "<span lang=epo-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'jbo-foo'",
+"input": "<span lang=jbo-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mic-foo'",
+"input": "<span lang=mic-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tha-foo'",
+"input": "<span lang=tha-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sam-foo'",
+"input": "<span lang=sam-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'hai-foo'",
+"input": "<span lang=hai-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'gmh-foo'",
+"input": "<span lang=gmh-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'cus-foo'",
+"input": "<span lang=cus-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ell-foo'",
+"input": "<span lang=ell-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'wen-foo'",
+"input": "<span lang=wen-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bnt-foo'",
+"input": "<span lang=bnt-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'fre-foo'",
+"input": "<span lang=fre-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'elx-foo'",
+"input": "<span lang=elx-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ada-foo'",
+"input": "<span lang=ada-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nav-foo'",
+"input": "<span lang=nav-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'hat-foo'",
+"input": "<span lang=hat-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'hau-foo'",
+"input": "<span lang=hau-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'haw-foo'",
+"input": "<span lang=haw-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bin-foo'",
+"input": "<span lang=bin-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'amh-foo'",
+"input": "<span lang=amh-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bik-foo'",
+"input": "<span lang=bik-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bih-foo'",
+"input": "<span lang=bih-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mos-foo'",
+"input": "<span lang=mos-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'moh-foo'",
+"input": "<span lang=moh-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mon-foo'",
+"input": "<span lang=mon-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mol-foo'",
+"input": "<span lang=mol-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bis-foo'",
+"input": "<span lang=bis-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bla-foo'",
+"input": "<span lang=bla-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'pol-foo'",
+"input": "<span lang=pol-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tib-foo'",
+"input": "<span lang=tib-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tvl-foo'",
+"input": "<span lang=tvl-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tgk-foo'",
+"input": "<span lang=tgk-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ijo-foo'",
+"input": "<span lang=ijo-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'est-foo'",
+"input": "<span lang=est-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kmb-foo'",
+"input": "<span lang=kmb-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ice-foo'",
+"input": "<span lang=ice-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'peo-foo'",
+"input": "<span lang=peo-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tgl-foo'",
+"input": "<span lang=tgl-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'umb-foo'",
+"input": "<span lang=umb-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tmh-foo'",
+"input": "<span lang=tmh-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'fon-foo'",
+"input": "<span lang=fon-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'hsb-foo'",
+"input": "<span lang=hsb-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'be-foo'",
+"input": "<span lang=be-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bg-foo'",
+"input": "<span lang=bg-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'run-foo'",
+"input": "<span lang=run-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ba-foo'",
+"input": "<span lang=ba-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'rum-foo'",
+"input": "<span lang=rum-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bm-foo'",
+"input": "<span lang=bm-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bn-foo'",
+"input": "<span lang=bn-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bo-foo'",
+"input": "<span lang=bo-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bh-foo'",
+"input": "<span lang=bh-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bi-foo'",
+"input": "<span lang=bi-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'br-foo'",
+"input": "<span lang=br-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bs-foo'",
+"input": "<span lang=bs-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'rus-foo'",
+"input": "<span lang=rus-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'rup-foo'",
+"input": "<span lang=rup-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'pli-foo'",
+"input": "<span lang=pli-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'om-foo'",
+"input": "<span lang=om-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'oj-foo'",
+"input": "<span lang=oj-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ace-foo'",
+"input": "<span lang=ace-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ach-foo'",
+"input": "<span lang=ach-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'oc-foo'",
+"input": "<span lang=oc-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'dzo-foo'",
+"input": "<span lang=dzo-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kru-foo'",
+"input": "<span lang=kru-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'srr-foo'",
+"input": "<span lang=srr-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ido-foo'",
+"input": "<span lang=ido-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'srp-foo'",
+"input": "<span lang=srp-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'kro-foo'",
+"input": "<span lang=kro-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'krl-foo'",
+"input": "<span lang=krl-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'krc-foo'",
+"input": "<span lang=krc-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nds-foo'",
+"input": "<span lang=nds-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'os-foo'",
+"input": "<span lang=os-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'or-foo'",
+"input": "<span lang=or-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'zul-foo'",
+"input": "<span lang=zul-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'twi-foo'",
+"input": "<span lang=twi-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sog-foo'",
+"input": "<span lang=sog-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nso-foo'",
+"input": "<span lang=nso-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'swe-foo'",
+"input": "<span lang=swe-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'som-foo'",
+"input": "<span lang=som-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'chm-foo'",
+"input": "<span lang=chm-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'snd-foo'",
+"input": "<span lang=snd-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sot-foo'",
+"input": "<span lang=sot-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mkd-foo'",
+"input": "<span lang=mkd-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'wak-foo'",
+"input": "<span lang=wak-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'her-foo'",
+"input": "<span lang=her-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'lol-foo'",
+"input": "<span lang=lol-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mkh-foo'",
+"input": "<span lang=mkh-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'heb-foo'",
+"input": "<span lang=heb-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'loz-foo'",
+"input": "<span lang=loz-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'gil-foo'",
+"input": "<span lang=gil-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'was-foo'",
+"input": "<span lang=was-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'war-foo'",
+"input": "<span lang=war-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'hz-foo'",
+"input": "<span lang=hz-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'hy-foo'",
+"input": "<span lang=hy-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sid-foo'",
+"input": "<span lang=sid-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'hr-foo'",
+"input": "<span lang=hr-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ht-foo'",
+"input": "<span lang=ht-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'hu-foo'",
+"input": "<span lang=hu-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'hi-foo'",
+"input": "<span lang=hi-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ho-foo'",
+"input": "<span lang=ho-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bul-foo'",
+"input": "<span lang=bul-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'wal-foo'",
+"input": "<span lang=wal-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bua-foo'",
+"input": "<span lang=bua-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'bug-foo'",
+"input": "<span lang=bug-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'he-foo'",
+"input": "<span lang=he-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'uz-foo'",
+"input": "<span lang=uz-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'aze-foo'",
+"input": "<span lang=aze-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ur-foo'",
+"input": "<span lang=ur-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'zha-foo'",
+"input": "<span lang=zha-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'uk-foo'",
+"input": "<span lang=uk-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ug-foo'",
+"input": "<span lang=ug-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'zho-foo'",
+"input": "<span lang=zho-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'aa-foo'",
+"input": "<span lang=aa-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ab-foo'",
+"input": "<span lang=ab-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ae-foo'",
+"input": "<span lang=ae-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'uig-foo'",
+"input": "<span lang=uig-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'af-foo'",
+"input": "<span lang=af-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ak-foo'",
+"input": "<span lang=ak-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'am-foo'",
+"input": "<span lang=am-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'myv-foo'",
+"input": "<span lang=myv-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'khi-foo'",
+"input": "<span lang=khi-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'as-foo'",
+"input": "<span lang=as-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ar-foo'",
+"input": "<span lang=ar-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'inh-foo'",
+"input": "<span lang=inh-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'khm-foo'",
+"input": "<span lang=khm-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'av-foo'",
+"input": "<span lang=av-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mya-foo'",
+"input": "<span lang=mya-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ine-foo'",
+"input": "<span lang=ine-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'az-foo'",
+"input": "<span lang=az-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ina-foo'",
+"input": "<span lang=ina-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'inc-foo'",
+"input": "<span lang=inc-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nl-foo'",
+"input": "<span lang=nl-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nn-foo'",
+"input": "<span lang=nn-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'no-foo'",
+"input": "<span lang=no-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'na-foo'",
+"input": "<span lang=na-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nb-foo'",
+"input": "<span lang=nb-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nai-foo'",
+"input": "<span lang=nai-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nd-foo'",
+"input": "<span lang=nd-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ne-foo'",
+"input": "<span lang=ne-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tir-foo'",
+"input": "<span lang=tir-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ng-foo'",
+"input": "<span lang=ng-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ny-foo'",
+"input": "<span lang=ny-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nap-foo'",
+"input": "<span lang=nap-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'gre-foo'",
+"input": "<span lang=gre-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'grb-foo'",
+"input": "<span lang=grb-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'grc-foo'",
+"input": "<span lang=grc-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nau-foo'",
+"input": "<span lang=nau-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'grn-foo'",
+"input": "<span lang=grn-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nr-foo'",
+"input": "<span lang=nr-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'tig-foo'",
+"input": "<span lang=tig-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'yor-foo'",
+"input": "<span lang=yor-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'nv-foo'",
+"input": "<span lang=nv-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'mri-foo'",
+"input": "<span lang=mri-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'may-foo'",
+"input": "<span lang=may-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'zun-foo'",
+"input": "<span lang=zun-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'ile-foo'",
+"input": "<span lang=ile-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'sqi-foo'",
+"input": "<span lang=sqi-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'gon-foo'",
+"input": "<span lang=gon-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'cpe-foo'",
+"input": "<span lang=cpe-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'cpf-foo'",
+"input": "<span lang=cpf-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'cpp-foo'",
+"input": "<span lang=cpp-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "invalid lang attribute 'foo'",
+"input": "<span lang=foo>",
+"fail-unless": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'EN'",
+"input": "<span lang=EN>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "valid lang attribute 'EN-foo'",
+"input": "<span lang=EN-foo>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "lang attribute can be blank",
+"input": "<span lang>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "lang attribute can be blank (with quotes)",
+"input": "<span lang=''>",
+"fail-if": "invalid-lang-code"},
+
+{"description": "lang attribute can not be just space characters",
+"input": "<span lang=' '>",
+"fail-unless": "invalid-lang-code"},
+
+{"description": "lang attribute can not contain leading spaces",
+"input": "<span lang=' en'>",
+"fail-unless": "invalid-lang-code"},
+
+{"description": "lang attribute can not contain trailing spaces",
+"input": "<span lang='en '>",
+"fail-unless": "invalid-lang-code"}
+
+]} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/li-value-attribute.test b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/li-value-attribute.test
new file mode 100755
index 00000000000..9ef9dcc562f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/li-value-attribute.test
@@ -0,0 +1,7 @@
+{"tests": [
+
+{"description": "invalid li value attribute value due to leading junk",
+"input": "<li value=a1>",
+"fail-unless": "invalid-integer-value"}
+
+]} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/link-href-attribute.test b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/link-href-attribute.test
new file mode 100755
index 00000000000..950c3786fa2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/link-href-attribute.test
@@ -0,0 +1,7 @@
+{"tests": [
+
+{"description": "link href contains invalid URI due to space in domain",
+"input": "<link href='http://www.example. com/'",
+"fail-unless": "invalid-uri-char"}
+
+]} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/link-hreflang-attribute.test b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/link-hreflang-attribute.test
new file mode 100755
index 00000000000..de39d4da066
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/link-hreflang-attribute.test
@@ -0,0 +1,7 @@
+{"tests": [
+
+{"description": "invalid lang attribute 'foo'",
+"input": "<link hreflang=foo>",
+"fail-unless": "invalid-lang-code"}
+
+]} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/link-rel-attribute.test b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/link-rel-attribute.test
new file mode 100755
index 00000000000..a436751da69
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/link-rel-attribute.test
@@ -0,0 +1,271 @@
+{"tests": [
+
+{"description": "invalid link rel value 'foo'",
+"input": "<link rel=foo>",
+"fail-unless": "invalid-rel"},
+
+{"description": "valid link rel value 'alternate stylesheet'",
+"input": "<link rel='alternate stylesheet'>",
+"fail-if": "invalid-rel"},
+
+{"description": "valid single link rel value with leading space",
+"input": "<link rel=' stylesheet'>",
+"fail-if": "invalid-rel"},
+
+{"description": "valid single link rel value with trailing space",
+"input": "<link rel='stylesheet '>",
+"fail-if": "invalid-rel"},
+
+{"description": "valid single link rel value with leading and trailing space",
+"input": "<link rel=' stylesheet '>",
+"fail-if": "invalid-rel"},
+
+{"description": "valid single link rel value with leading tab",
+"input": "<link rel='\tstylesheet'>",
+"fail-if": "invalid-rel"},
+
+{"description": "valid single link rel value with trailing tab",
+"input": "<link rel='stylesheet\t'>",
+"fail-if": "invalid-rel"},
+
+{"description": "valid single link rel value with leading and trailing tab",
+"input": "<link rel='\tstylesheet\t'>",
+"fail-if": "invalid-rel"},
+
+{"description": "valid single link rel value with leading LF",
+"input": "<link rel='\nstylesheet'>",
+"fail-if": "invalid-rel"},
+
+{"description": "valid single link rel value with trailing LF",
+"input": "<link rel='stylesheet\n'>",
+"fail-if": "invalid-rel"},
+
+{"description": "valid single link rel value with leading and trailing LF",
+"input": "<link rel='\nstylesheet\n'>",
+"fail-if": "invalid-rel"},
+
+{"description": "valid single link rel value with leading LT",
+"input": "<link rel='\u000Bstylesheet'>",
+"fail-if": "invalid-rel"},
+
+{"description": "valid single link rel value with trailing LT",
+"input": "<link rel='stylesheet\u000B'>",
+"fail-if": "invalid-rel"},
+
+{"description": "valid single link rel value with leading and trailing LT",
+"input": "<link rel='\u000Bstylesheet\u000B'>",
+"fail-if": "invalid-rel"},
+
+{"description": "valid single link rel value with leading FF",
+"input": "<link rel='\u000Cstylesheet'>",
+"fail-if": "invalid-rel"},
+
+{"description": "valid single link rel value with trailing FF",
+"input": "<link rel='stylesheet\u000C'>",
+"fail-if": "invalid-rel"},
+
+{"description": "valid single link rel value with leading and trailing FF",
+"input": "<link rel='\u000Cstylesheet\u000C'>",
+"fail-if": "invalid-rel"},
+
+{"description": "valid single link rel value with leading CR",
+"input": "<link rel='\rstylesheet'>",
+"fail-if": "invalid-rel"},
+
+{"description": "valid single link rel value with trailing CR",
+"input": "<link rel='stylesheet\r'>",
+"fail-if": "invalid-rel"},
+
+{"description": "valid single link rel value with leading and trailing CR",
+"input": "<link rel='\rstylesheet\r'>",
+"fail-if": "invalid-rel"},
+
+{"description": "valid double link rel value separated by space",
+"input": "<link rel='stylesheet alternate'>",
+"fail-if": "invalid-rel"},
+
+{"description": "valid double link rel value separated by tab",
+"input": "<link rel='stylesheet\talternate'>",
+"fail-if": "invalid-rel"},
+
+{"description": "valid double link rel value separated by LF",
+"input": "<link rel='stylesheet\nalternate'>",
+"fail-if": "invalid-rel"},
+
+{"description": "valid double link rel value separated by LT",
+"input": "<link rel='stylesheet\u000Balternate'>",
+"fail-if": "invalid-rel"},
+
+{"description": "valid double link rel value separated by FF",
+"input": "<link rel='stylesheet\u000Calternate'>",
+"fail-if": "invalid-rel"},
+
+{"description": "valid double link rel value separated by CR",
+"input": "<link rel='stylesheet\ralternate'>",
+"fail-if": "invalid-rel"},
+
+{"description": "invalid duplicated link rel value separated by space",
+"input": "<link rel='stylesheet stylesheet'>",
+"fail-unless": "duplicate-value-in-token-list"},
+
+{"description": "invalid duplicated link rel value separated by tab",
+"input": "<link rel='stylesheet\tstylesheet'>",
+"fail-unless": "duplicate-value-in-token-list"},
+
+{"description": "invalid duplicated link rel value separated by LF",
+"input": "<link rel='stylesheet\nstylesheet'>",
+"fail-unless": "duplicate-value-in-token-list"},
+
+{"description": "invalid duplicated link rel value separated by LT",
+"input": "<link rel='stylesheet\u000Bstylesheet'>",
+"fail-unless": "duplicate-value-in-token-list"},
+
+{"description": "invalid duplicated link rel value separated by FF",
+"input": "<link rel='stylesheet\u000Cstylesheet'>",
+"fail-unless": "duplicate-value-in-token-list"},
+
+{"description": "invalid duplicated link rel value separated by CR",
+"input": "<link rel='stylesheet\rstylesheet'>",
+"fail-unless": "duplicate-value-in-token-list"},
+
+{"description": "invalid duplicated link rel value separated by space",
+"input": "<link rel='stylesheet stylesheet'>",
+"fail-unless": "duplicate-value-in-token-list"},
+
+{"description": "invalid duplicated link rel value separated by tab",
+"input": "<link rel='stylesheet\tstylesheet'>",
+"fail-unless": "duplicate-value-in-token-list"},
+
+{"description": "invalid duplicated link rel value separated by LF",
+"input": "<link rel='stylesheet\nstylesheet'>",
+"fail-unless": "duplicate-value-in-token-list"},
+
+{"description": "invalid duplicated link rel value separated by LT",
+"input": "<link rel='stylesheet\u000Bstylesheet'>",
+"fail-unless": "duplicate-value-in-token-list"},
+
+{"description": "invalid duplicated link rel value separated by FF",
+"input": "<link rel='stylesheet\u000Cstylesheet'>",
+"fail-unless": "duplicate-value-in-token-list"},
+
+{"description": "invalid duplicated link rel value separated by CR",
+"input": "<link rel='stylesheet\rstylesheet'>",
+"fail-unless": "duplicate-value-in-token-list"},
+
+{"description": "valid link rel value 'feed'",
+"input": "<link rel=feed>",
+"fail-if": "invalid-rel"},
+
+{"description": "valid link rel value 'help'",
+"input": "<link rel=help>",
+"fail-if": "invalid-rel"},
+
+{"description": "valid link rel value 'tag'",
+"input": "<link rel=tag>",
+"fail-if": "invalid-rel"},
+
+{"description": "valid link rel value 'sidebar'",
+"input": "<link rel=sidebar>",
+"fail-if": "invalid-rel"},
+
+{"description": "valid link rel value 'archive'",
+"input": "<link rel=archive>",
+"fail-if": "invalid-rel"},
+
+{"description": "valid link rel value 'contents'",
+"input": "<link rel=contents>",
+"fail-if": "invalid-rel"},
+
+{"description": "valid link rel value 'previous'",
+"input": "<link rel=previous>",
+"fail-if": "invalid-rel"},
+
+{"description": "valid link rel value 'index'",
+"input": "<link rel=index>",
+"fail-if": "invalid-rel"},
+
+{"description": "valid link rel value 'end'",
+"input": "<link rel=end>",
+"fail-if": "invalid-rel"},
+
+{"description": "valid link rel value 'copyright'",
+"input": "<link rel=copyright>",
+"fail-if": "invalid-rel"},
+
+{"description": "valid link rel value 'author'",
+"input": "<link rel=author>",
+"fail-if": "invalid-rel"},
+
+{"description": "valid link rel value 'top'",
+"input": "<link rel=top>",
+"fail-if": "invalid-rel"},
+
+{"description": "valid link rel value 'alternate'",
+"input": "<link rel=alternate>",
+"fail-if": "invalid-rel"},
+
+{"description": "valid link rel value 'next'",
+"input": "<link rel=next>",
+"fail-if": "invalid-rel"},
+
+{"description": "valid link rel value 'start'",
+"input": "<link rel=start>",
+"fail-if": "invalid-rel"},
+
+{"description": "valid link rel value 'stylesheet'",
+"input": "<link rel=stylesheet>",
+"fail-if": "invalid-rel"},
+
+{"description": "valid link rel value 'archives'",
+"input": "<link rel=archives>",
+"fail-if": "invalid-rel"},
+
+{"description": "valid link rel value 'toc'",
+"input": "<link rel=toc>",
+"fail-if": "invalid-rel"},
+
+{"description": "valid link rel value 'prev'",
+"input": "<link rel=prev>",
+"fail-if": "invalid-rel"},
+
+{"description": "valid link rel value 'begin'",
+"input": "<link rel=begin>",
+"fail-if": "invalid-rel"},
+
+{"description": "valid link rel value 'icon'",
+"input": "<link rel=icon>",
+"fail-if": "invalid-rel"},
+
+{"description": "valid link rel value 'search'",
+"input": "<link rel=search>",
+"fail-if": "invalid-rel"},
+
+{"description": "valid link rel value 'last'",
+"input": "<link rel=last>",
+"fail-if": "invalid-rel"},
+
+{"description": "valid link rel value 'license'",
+"input": "<link rel=license>",
+"fail-if": "invalid-rel"},
+
+{"description": "valid link rel value 'pingback'",
+"input": "<link rel=pingback>",
+"fail-if": "invalid-rel"},
+
+{"description": "valid link rel value 'up'",
+"input": "<link rel=up>",
+"fail-if": "invalid-rel"},
+
+{"description": "valid link rel value 'contact'",
+"input": "<link rel=contact>",
+"fail-if": "invalid-rel"},
+
+{"description": "valid link rel value 'prefetch'",
+"input": "<link rel=prefetch>",
+"fail-if": "invalid-rel"},
+
+{"description": "valid link rel value 'first'",
+"input": "<link rel=first>",
+"fail-if": "invalid-rel"}
+
+]}
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/ol-start-attribute.test b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/ol-start-attribute.test
new file mode 100755
index 00000000000..5e18cbef41a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/ol-start-attribute.test
@@ -0,0 +1,7 @@
+{"tests": [
+
+{"description": "invalid ol start attribute value due to leading junk",
+"input": "<ol start=a1>",
+"fail-unless": "invalid-integer-value"}
+
+]} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/starttags.test b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/starttags.test
new file mode 100755
index 00000000000..0aa5b4d001e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/starttags.test
@@ -0,0 +1,375 @@
+{"tests": [
+
+{"description": "unknown start tag <foo>",
+"input": "<foo>",
+"fail-unless": "unknown-start-tag"},
+
+{"description": "allowed start tag <code>",
+"input": "<code>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <kbd>",
+"input": "<kbd>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <aside>",
+"input": "<aside>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <datagrid>",
+"input": "<datagrid>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <font>",
+"input": "<font>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <noscript>",
+"input": "<noscript>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <style>",
+"input": "<style>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <img>",
+"input": "<img>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <title>",
+"input": "<title>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <menu>",
+"input": "<menu>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <tr>",
+"input": "<tr>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <param>",
+"input": "<param>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <li>",
+"input": "<li>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <source>",
+"input": "<source>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <tfoot>",
+"input": "<tfoot>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <th>",
+"input": "<th>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <td>",
+"input": "<td>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <dl>",
+"input": "<dl>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <blockquote>",
+"input": "<blockquote>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <dd>",
+"input": "<dd>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <abbr>",
+"input": "<abbr>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <dt>",
+"input": "<dt>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <noembed>",
+"input": "<noembed>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <p>",
+"input": "<p>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <small>",
+"input": "<small>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <meter>",
+"input": "<meter>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <em>",
+"input": "<em>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <meta>",
+"input": "<meta>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <video>",
+"input": "<video>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <div>",
+"input": "<div>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <canvas>",
+"input": "<canvas>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <sub>",
+"input": "<sub>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <section>",
+"input": "<section>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <sup>",
+"input": "<sup>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <progress>",
+"input": "<progress>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <body>",
+"input": "<body>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <base>",
+"input": "<base>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <br>",
+"input": "<br>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <address>",
+"input": "<address>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <article>",
+"input": "<article>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <strong>",
+"input": "<strong>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <legend>",
+"input": "<legend>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <event-source>",
+"input": "<event-source>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <ol>",
+"input": "<ol>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <script>",
+"input": "<script>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <caption>",
+"input": "<caption>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <dialog>",
+"input": "<dialog>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <col>",
+"input": "<col>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <h2>",
+"input": "<h2>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <h3>",
+"input": "<h3>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <h1>",
+"input": "<h1>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <h6>",
+"input": "<h6>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <h4>",
+"input": "<h4>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <h5>",
+"input": "<h5>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <header>",
+"input": "<header>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <table>",
+"input": "<table>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <span>",
+"input": "<span>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <area>",
+"input": "<area>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <dfn>",
+"input": "<dfn>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <var>",
+"input": "<var>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <cite>",
+"input": "<cite>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <thead>",
+"input": "<thead>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <head>",
+"input": "<head>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <hr>",
+"input": "<hr>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <link>",
+"input": "<link>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <datatemplate>",
+"input": "<datatemplate>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <b>",
+"input": "<b>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <colgroup>",
+"input": "<colgroup>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <ul>",
+"input": "<ul>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <del>",
+"input": "<del>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <iframe>",
+"input": "<iframe>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <pre>",
+"input": "<pre>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <figure>",
+"input": "<figure>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <ins>",
+"input": "<ins>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <tbody>",
+"input": "<tbody>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <html>",
+"input": "<html>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <nav>",
+"input": "<nav>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <details>",
+"input": "<details>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <samp>",
+"input": "<samp>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <map>",
+"input": "<map>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <nest>",
+"input": "<nest>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <object>",
+"input": "<object>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <a>",
+"input": "<a>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <footer>",
+"input": "<footer>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <i>",
+"input": "<i>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <m>",
+"input": "<m>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <rule>",
+"input": "<rule>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <q>",
+"input": "<q>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <command>",
+"input": "<command>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <time>",
+"input": "<time>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <audio>",
+"input": "<audio>",
+"fail-if": "unknown-start-tag"},
+
+{"description": "allowed start tag <bdo>",
+"input": "<bdo>",
+"fail-if": "unknown-start-tag"}
+
+]}
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/style-scoped-attribute.test b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/style-scoped-attribute.test
new file mode 100755
index 00000000000..f47795a2178
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/style-scoped-attribute.test
@@ -0,0 +1,7 @@
+{"tests": [
+
+{"description": "invalid style scoped attribute value 'inherit'",
+"input": "<style scoped=inherit>",
+"fail-unless": "invalid-boolean-value"}
+
+]} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/tabindexattribute.test b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/tabindexattribute.test
new file mode 100755
index 00000000000..02066957b28
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/testdata/validator/tabindexattribute.test
@@ -0,0 +1,79 @@
+{"tests": [
+
+{"description": "valid tabindex attribute value '-1'",
+"input": "<span tabindex=-1>",
+"fail-if": "invalid-integer-value"},
+
+{"description": "valid tabindex attribute value '0'",
+"input": "<span tabindex=0>",
+"fail-if": "invalid-integer-value"},
+
+{"description": "valid tabindex attribute value '1'",
+"input": "<span tabindex=1>",
+"fail-if": "invalid-integer-value"},
+
+{"description": "valid tabindex attribute value '32768'",
+"input": "<span tabindex=32768>",
+"fail-if": "invalid-integer-value"},
+
+{"description": "valid tabindex attribute value '-32768'",
+"input": "<span tabindex=-32768>",
+"fail-if": "invalid-integer-value"},
+
+{"description": "valid tabindex attribute value with leading spaces",
+"input": "<span tabindex=' -32768'>",
+"fail-if": "invalid-integer-value"},
+
+{"description": "valid tabindex attribute value with trailing spaces",
+"input": "<span tabindex='-32768 '>",
+"fail-if": "invalid-integer-value"},
+
+{"description": "valid tabindex attribute value with trailing junk",
+"input": "<span tabindex='32768a'>",
+"fail-if": "invalid-integer-value"},
+
+{"description": "valid tabindex attribute value with trailing junk and whitespace",
+"input": "<span tabindex='32768a '>",
+"fail-if": "invalid-integer-value"},
+
+{"description": "valid tabindex attribute value with trailing whitespace and junk",
+"input": "<span tabindex='32768 a'>",
+"fail-if": "invalid-integer-value"},
+
+{"description": "valid tabindex attribute value with leading spaces",
+"input": "<span tabindex=' 32768'>",
+"fail-if": "invalid-integer-value"},
+
+{"description": "valid tabindex attribute value with leading spaces (with sign)",
+"input": "<span tabindex=' -32768'>",
+"fail-if": "invalid-integer-value"},
+
+{"description": "invalid tabindex attribute value (blank)",
+"input": "<span tabindex>",
+"fail-unless": "attribute-value-can-not-be-blank"},
+
+{"description": "invalid tabindex attribute value due to leading junk",
+"input": "<span tabindex=a1>",
+"fail-unless": "invalid-integer-value"},
+
+{"description": "invalid tabindex attribute value due to two hyphens",
+"input": "<span tabindex=--1>",
+"fail-unless": "invalid-integer-value"},
+
+{"description": "invalid tabindex attribute value due to non-numeric",
+"input": "<span tabindex=foo>",
+"fail-unless": "invalid-integer-value"},
+
+{"description": "invalid tabindex attribute value due to positive sign",
+"input": "<span tabindex=+1>",
+"fail-unless": "invalid-integer-value"},
+
+{"description": "invalid tabindex attribute value due to decimal point",
+"input": "<span tabindex=.1>",
+"fail-unless": "invalid-integer-value"},
+
+{"description": "valid tabindex attribute value with trailing decimal point",
+"input": "<span tabindex=1.0>",
+"fail-if": "invalid-integer-value"}
+
+]} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/tokenizertotree.py b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/tokenizertotree.py
new file mode 100644
index 00000000000..b841c76ce41
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/tokenizertotree.py
@@ -0,0 +1,68 @@
+from __future__ import absolute_import, division, unicode_literals
+
+import sys
+import os
+import json
+import re
+
+import html5lib
+from . import support
+from . import test_tokenizer
+
+p = html5lib.HTMLParser()
+
+unnamespaceExpected = re.compile(r"^(\|\s*)<html ([^>]+)>", re.M).sub
+
+
+def main(out_path):
+ if not os.path.exists(out_path):
+ sys.stderr.write("Path %s does not exist" % out_path)
+ sys.exit(1)
+
+ for filename in support.get_data_files('tokenizer', '*.test'):
+ run_file(filename, out_path)
+
+
+def run_file(filename, out_path):
+ try:
+ tests_data = json.load(open(filename, "r"))
+ except ValueError:
+ sys.stderr.write("Failed to load %s\n" % filename)
+ return
+ name = os.path.splitext(os.path.split(filename)[1])[0]
+ output_file = open(os.path.join(out_path, "tokenizer_%s.dat" % name), "w")
+
+ if 'tests' in tests_data:
+ for test_data in tests_data['tests']:
+ if 'initialStates' not in test_data:
+ test_data["initialStates"] = ["Data state"]
+
+ for initial_state in test_data["initialStates"]:
+ if initial_state != "Data state":
+ # don't support this yet
+ continue
+ test = make_test(test_data)
+ output_file.write(test)
+
+ output_file.close()
+
+
+def make_test(test_data):
+ if 'doubleEscaped' in test_data:
+ test_data = test_tokenizer.unescape_test(test_data)
+
+ rv = []
+ rv.append("#data")
+ rv.append(test_data["input"].encode("utf8"))
+ rv.append("#errors")
+ tree = p.parse(test_data["input"])
+ output = p.tree.testSerializer(tree)
+ output = "\n".join(("| " + line[3:]) if line.startswith("| ") else line
+ for line in output.split("\n"))
+ output = unnamespaceExpected(r"\1<\2>", output)
+ rv.append(output.encode("utf8"))
+ rv.append("")
+ return "\n".join(rv)
+
+if __name__ == "__main__":
+ main(sys.argv[1])
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/us-ascii.html b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/us-ascii.html
new file mode 100644
index 00000000000..728cb6baf98
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/us-ascii.html
@@ -0,0 +1,3 @@
+<!doctype html>
+<title>Test</title>
+<p>Hello World! \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/utf-8-bom.html b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/utf-8-bom.html
new file mode 100644
index 00000000000..6ac5efcedf1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tests/utf-8-bom.html
@@ -0,0 +1,3 @@
+<!doctype html>
+<title>Test</title>
+<p>Hello World! © \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tokenizer.py b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tokenizer.py
new file mode 100644
index 00000000000..797745787a4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/tokenizer.py
@@ -0,0 +1,1731 @@
+from __future__ import absolute_import, division, unicode_literals
+
+try:
+ chr = unichr # flake8: noqa
+except NameError:
+ pass
+
+from collections import deque
+
+from .constants import spaceCharacters
+from .constants import entities
+from .constants import asciiLetters, asciiUpper2Lower
+from .constants import digits, hexDigits, EOF
+from .constants import tokenTypes, tagTokenTypes
+from .constants import replacementCharacters
+
+from .inputstream import HTMLInputStream
+
+from .trie import Trie
+
+entitiesTrie = Trie(entities)
+
+
+class HTMLTokenizer(object):
+ """ This class takes care of tokenizing HTML.
+
+ * self.currentToken
+ Holds the token that is currently being processed.
+
+ * self.state
+ Holds a reference to the method to be invoked... XXX
+
+ * self.stream
+ Points to HTMLInputStream object.
+ """
+
+ def __init__(self, stream, encoding=None, parseMeta=True, useChardet=True,
+ lowercaseElementName=True, lowercaseAttrName=True, parser=None):
+
+ self.stream = HTMLInputStream(stream, encoding, parseMeta, useChardet)
+ self.parser = parser
+
+ # Perform case conversions?
+ self.lowercaseElementName = lowercaseElementName
+ self.lowercaseAttrName = lowercaseAttrName
+
+ # Setup the initial tokenizer state
+ self.escapeFlag = False
+ self.lastFourChars = []
+ self.state = self.dataState
+ self.escape = False
+
+ # The current token being created
+ self.currentToken = None
+ super(HTMLTokenizer, self).__init__()
+
+ def __iter__(self):
+ """ This is where the magic happens.
+
+ We do our usually processing through the states and when we have a token
+ to return we yield the token which pauses processing until the next token
+ is requested.
+ """
+ self.tokenQueue = deque([])
+ # Start processing. When EOF is reached self.state will return False
+ # instead of True and the loop will terminate.
+ while self.state():
+ while self.stream.errors:
+ yield {"type": tokenTypes["ParseError"], "data": self.stream.errors.pop(0)}
+ while self.tokenQueue:
+ yield self.tokenQueue.popleft()
+
+ def consumeNumberEntity(self, isHex):
+ """This function returns either U+FFFD or the character based on the
+ decimal or hexadecimal representation. It also discards ";" if present.
+ If not present self.tokenQueue.append({"type": tokenTypes["ParseError"]}) is invoked.
+ """
+
+ allowed = digits
+ radix = 10
+ if isHex:
+ allowed = hexDigits
+ radix = 16
+
+ charStack = []
+
+ # Consume all the characters that are in range while making sure we
+ # don't hit an EOF.
+ c = self.stream.char()
+ while c in allowed and c is not EOF:
+ charStack.append(c)
+ c = self.stream.char()
+
+ # Convert the set of characters consumed to an int.
+ charAsInt = int("".join(charStack), radix)
+
+ # Certain characters get replaced with others
+ if charAsInt in replacementCharacters:
+ char = replacementCharacters[charAsInt]
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "illegal-codepoint-for-numeric-entity",
+ "datavars": {"charAsInt": charAsInt}})
+ elif ((0xD800 <= charAsInt <= 0xDFFF) or
+ (charAsInt > 0x10FFFF)):
+ char = "\uFFFD"
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "illegal-codepoint-for-numeric-entity",
+ "datavars": {"charAsInt": charAsInt}})
+ else:
+ # Should speed up this check somehow (e.g. move the set to a constant)
+ if ((0x0001 <= charAsInt <= 0x0008) or
+ (0x000E <= charAsInt <= 0x001F) or
+ (0x007F <= charAsInt <= 0x009F) or
+ (0xFDD0 <= charAsInt <= 0xFDEF) or
+ charAsInt in frozenset([0x000B, 0xFFFE, 0xFFFF, 0x1FFFE,
+ 0x1FFFF, 0x2FFFE, 0x2FFFF, 0x3FFFE,
+ 0x3FFFF, 0x4FFFE, 0x4FFFF, 0x5FFFE,
+ 0x5FFFF, 0x6FFFE, 0x6FFFF, 0x7FFFE,
+ 0x7FFFF, 0x8FFFE, 0x8FFFF, 0x9FFFE,
+ 0x9FFFF, 0xAFFFE, 0xAFFFF, 0xBFFFE,
+ 0xBFFFF, 0xCFFFE, 0xCFFFF, 0xDFFFE,
+ 0xDFFFF, 0xEFFFE, 0xEFFFF, 0xFFFFE,
+ 0xFFFFF, 0x10FFFE, 0x10FFFF])):
+ self.tokenQueue.append({"type": tokenTypes["ParseError"],
+ "data":
+ "illegal-codepoint-for-numeric-entity",
+ "datavars": {"charAsInt": charAsInt}})
+ try:
+ # Try/except needed as UCS-2 Python builds' unichar only works
+ # within the BMP.
+ char = chr(charAsInt)
+ except ValueError:
+ v = charAsInt - 0x10000
+ char = chr(0xD800 | (v >> 10)) + chr(0xDC00 | (v & 0x3FF))
+
+ # Discard the ; if present. Otherwise, put it back on the queue and
+ # invoke parseError on parser.
+ if c != ";":
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "numeric-entity-without-semicolon"})
+ self.stream.unget(c)
+
+ return char
+
+ def consumeEntity(self, allowedChar=None, fromAttribute=False):
+ # Initialise to the default output for when no entity is matched
+ output = "&"
+
+ charStack = [self.stream.char()]
+ if (charStack[0] in spaceCharacters or charStack[0] in (EOF, "<", "&")
+ or (allowedChar is not None and allowedChar == charStack[0])):
+ self.stream.unget(charStack[0])
+
+ elif charStack[0] == "#":
+ # Read the next character to see if it's hex or decimal
+ hex = False
+ charStack.append(self.stream.char())
+ if charStack[-1] in ("x", "X"):
+ hex = True
+ charStack.append(self.stream.char())
+
+ # charStack[-1] should be the first digit
+ if (hex and charStack[-1] in hexDigits) \
+ or (not hex and charStack[-1] in digits):
+ # At least one digit found, so consume the whole number
+ self.stream.unget(charStack[-1])
+ output = self.consumeNumberEntity(hex)
+ else:
+ # No digits found
+ self.tokenQueue.append({"type": tokenTypes["ParseError"],
+ "data": "expected-numeric-entity"})
+ self.stream.unget(charStack.pop())
+ output = "&" + "".join(charStack)
+
+ else:
+ # At this point in the process might have named entity. Entities
+ # are stored in the global variable "entities".
+ #
+ # Consume characters and compare to these to a substring of the
+ # entity names in the list until the substring no longer matches.
+ while (charStack[-1] is not EOF):
+ if not entitiesTrie.has_keys_with_prefix("".join(charStack)):
+ break
+ charStack.append(self.stream.char())
+
+ # At this point we have a string that starts with some characters
+ # that may match an entity
+ # Try to find the longest entity the string will match to take care
+ # of &noti for instance.
+ try:
+ entityName = entitiesTrie.longest_prefix("".join(charStack[:-1]))
+ entityLength = len(entityName)
+ except KeyError:
+ entityName = None
+
+ if entityName is not None:
+ if entityName[-1] != ";":
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "named-entity-without-semicolon"})
+ if (entityName[-1] != ";" and fromAttribute and
+ (charStack[entityLength] in asciiLetters or
+ charStack[entityLength] in digits or
+ charStack[entityLength] == "=")):
+ self.stream.unget(charStack.pop())
+ output = "&" + "".join(charStack)
+ else:
+ output = entities[entityName]
+ self.stream.unget(charStack.pop())
+ output += "".join(charStack[entityLength:])
+ else:
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "expected-named-entity"})
+ self.stream.unget(charStack.pop())
+ output = "&" + "".join(charStack)
+
+ if fromAttribute:
+ self.currentToken["data"][-1][1] += output
+ else:
+ if output in spaceCharacters:
+ tokenType = "SpaceCharacters"
+ else:
+ tokenType = "Characters"
+ self.tokenQueue.append({"type": tokenTypes[tokenType], "data": output})
+
+ def processEntityInAttribute(self, allowedChar):
+ """This method replaces the need for "entityInAttributeValueState".
+ """
+ self.consumeEntity(allowedChar=allowedChar, fromAttribute=True)
+
+ def emitCurrentToken(self):
+ """This method is a generic handler for emitting the tags. It also sets
+ the state to "data" because that's what's needed after a token has been
+ emitted.
+ """
+ token = self.currentToken
+ # Add token to the queue to be yielded
+ if (token["type"] in tagTokenTypes):
+ if self.lowercaseElementName:
+ token["name"] = token["name"].translate(asciiUpper2Lower)
+ if token["type"] == tokenTypes["EndTag"]:
+ if token["data"]:
+ self.tokenQueue.append({"type": tokenTypes["ParseError"],
+ "data": "attributes-in-end-tag"})
+ if token["selfClosing"]:
+ self.tokenQueue.append({"type": tokenTypes["ParseError"],
+ "data": "self-closing-flag-on-end-tag"})
+ self.tokenQueue.append(token)
+ self.state = self.dataState
+
+ # Below are the various tokenizer states worked out.
+ def dataState(self):
+ data = self.stream.char()
+ if data == "&":
+ self.state = self.entityDataState
+ elif data == "<":
+ self.state = self.tagOpenState
+ elif data == "\u0000":
+ self.tokenQueue.append({"type": tokenTypes["ParseError"],
+ "data": "invalid-codepoint"})
+ self.tokenQueue.append({"type": tokenTypes["Characters"],
+ "data": "\u0000"})
+ elif data is EOF:
+ # Tokenization ends.
+ return False
+ elif data in spaceCharacters:
+ # Directly after emitting a token you switch back to the "data
+ # state". At that point spaceCharacters are important so they are
+ # emitted separately.
+ self.tokenQueue.append({"type": tokenTypes["SpaceCharacters"], "data":
+ data + self.stream.charsUntil(spaceCharacters, True)})
+ # No need to update lastFourChars here, since the first space will
+ # have already been appended to lastFourChars and will have broken
+ # any <!-- or --> sequences
+ else:
+ chars = self.stream.charsUntil(("&", "<", "\u0000"))
+ self.tokenQueue.append({"type": tokenTypes["Characters"], "data":
+ data + chars})
+ return True
+
+ def entityDataState(self):
+ self.consumeEntity()
+ self.state = self.dataState
+ return True
+
+ def rcdataState(self):
+ data = self.stream.char()
+ if data == "&":
+ self.state = self.characterReferenceInRcdata
+ elif data == "<":
+ self.state = self.rcdataLessThanSignState
+ elif data == EOF:
+ # Tokenization ends.
+ return False
+ elif data == "\u0000":
+ self.tokenQueue.append({"type": tokenTypes["ParseError"],
+ "data": "invalid-codepoint"})
+ self.tokenQueue.append({"type": tokenTypes["Characters"],
+ "data": "\uFFFD"})
+ elif data in spaceCharacters:
+ # Directly after emitting a token you switch back to the "data
+ # state". At that point spaceCharacters are important so they are
+ # emitted separately.
+ self.tokenQueue.append({"type": tokenTypes["SpaceCharacters"], "data":
+ data + self.stream.charsUntil(spaceCharacters, True)})
+ # No need to update lastFourChars here, since the first space will
+ # have already been appended to lastFourChars and will have broken
+ # any <!-- or --> sequences
+ else:
+ chars = self.stream.charsUntil(("&", "<", "\u0000"))
+ self.tokenQueue.append({"type": tokenTypes["Characters"], "data":
+ data + chars})
+ return True
+
+ def characterReferenceInRcdata(self):
+ self.consumeEntity()
+ self.state = self.rcdataState
+ return True
+
+ def rawtextState(self):
+ data = self.stream.char()
+ if data == "<":
+ self.state = self.rawtextLessThanSignState
+ elif data == "\u0000":
+ self.tokenQueue.append({"type": tokenTypes["ParseError"],
+ "data": "invalid-codepoint"})
+ self.tokenQueue.append({"type": tokenTypes["Characters"],
+ "data": "\uFFFD"})
+ elif data == EOF:
+ # Tokenization ends.
+ return False
+ else:
+ chars = self.stream.charsUntil(("<", "\u0000"))
+ self.tokenQueue.append({"type": tokenTypes["Characters"], "data":
+ data + chars})
+ return True
+
+ def scriptDataState(self):
+ data = self.stream.char()
+ if data == "<":
+ self.state = self.scriptDataLessThanSignState
+ elif data == "\u0000":
+ self.tokenQueue.append({"type": tokenTypes["ParseError"],
+ "data": "invalid-codepoint"})
+ self.tokenQueue.append({"type": tokenTypes["Characters"],
+ "data": "\uFFFD"})
+ elif data == EOF:
+ # Tokenization ends.
+ return False
+ else:
+ chars = self.stream.charsUntil(("<", "\u0000"))
+ self.tokenQueue.append({"type": tokenTypes["Characters"], "data":
+ data + chars})
+ return True
+
+ def plaintextState(self):
+ data = self.stream.char()
+ if data == EOF:
+ # Tokenization ends.
+ return False
+ elif data == "\u0000":
+ self.tokenQueue.append({"type": tokenTypes["ParseError"],
+ "data": "invalid-codepoint"})
+ self.tokenQueue.append({"type": tokenTypes["Characters"],
+ "data": "\uFFFD"})
+ else:
+ self.tokenQueue.append({"type": tokenTypes["Characters"], "data":
+ data + self.stream.charsUntil("\u0000")})
+ return True
+
+ def tagOpenState(self):
+ data = self.stream.char()
+ if data == "!":
+ self.state = self.markupDeclarationOpenState
+ elif data == "/":
+ self.state = self.closeTagOpenState
+ elif data in asciiLetters:
+ self.currentToken = {"type": tokenTypes["StartTag"],
+ "name": data, "data": [],
+ "selfClosing": False,
+ "selfClosingAcknowledged": False}
+ self.state = self.tagNameState
+ elif data == ">":
+ # XXX In theory it could be something besides a tag name. But
+ # do we really care?
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "expected-tag-name-but-got-right-bracket"})
+ self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<>"})
+ self.state = self.dataState
+ elif data == "?":
+ # XXX In theory it could be something besides a tag name. But
+ # do we really care?
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "expected-tag-name-but-got-question-mark"})
+ self.stream.unget(data)
+ self.state = self.bogusCommentState
+ else:
+ # XXX
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "expected-tag-name"})
+ self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<"})
+ self.stream.unget(data)
+ self.state = self.dataState
+ return True
+
+ def closeTagOpenState(self):
+ data = self.stream.char()
+ if data in asciiLetters:
+ self.currentToken = {"type": tokenTypes["EndTag"], "name": data,
+ "data": [], "selfClosing": False}
+ self.state = self.tagNameState
+ elif data == ">":
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "expected-closing-tag-but-got-right-bracket"})
+ self.state = self.dataState
+ elif data is EOF:
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "expected-closing-tag-but-got-eof"})
+ self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "</"})
+ self.state = self.dataState
+ else:
+ # XXX data can be _'_...
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "expected-closing-tag-but-got-char",
+ "datavars": {"data": data}})
+ self.stream.unget(data)
+ self.state = self.bogusCommentState
+ return True
+
+ def tagNameState(self):
+ data = self.stream.char()
+ if data in spaceCharacters:
+ self.state = self.beforeAttributeNameState
+ elif data == ">":
+ self.emitCurrentToken()
+ elif data is EOF:
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "eof-in-tag-name"})
+ self.state = self.dataState
+ elif data == "/":
+ self.state = self.selfClosingStartTagState
+ elif data == "\u0000":
+ self.tokenQueue.append({"type": tokenTypes["ParseError"],
+ "data": "invalid-codepoint"})
+ self.currentToken["name"] += "\uFFFD"
+ else:
+ self.currentToken["name"] += data
+ # (Don't use charsUntil here, because tag names are
+ # very short and it's faster to not do anything fancy)
+ return True
+
+ def rcdataLessThanSignState(self):
+ data = self.stream.char()
+ if data == "/":
+ self.temporaryBuffer = ""
+ self.state = self.rcdataEndTagOpenState
+ else:
+ self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<"})
+ self.stream.unget(data)
+ self.state = self.rcdataState
+ return True
+
+ def rcdataEndTagOpenState(self):
+ data = self.stream.char()
+ if data in asciiLetters:
+ self.temporaryBuffer += data
+ self.state = self.rcdataEndTagNameState
+ else:
+ self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "</"})
+ self.stream.unget(data)
+ self.state = self.rcdataState
+ return True
+
+ def rcdataEndTagNameState(self):
+ appropriate = self.currentToken and self.currentToken["name"].lower() == self.temporaryBuffer.lower()
+ data = self.stream.char()
+ if data in spaceCharacters and appropriate:
+ self.currentToken = {"type": tokenTypes["EndTag"],
+ "name": self.temporaryBuffer,
+ "data": [], "selfClosing": False}
+ self.state = self.beforeAttributeNameState
+ elif data == "/" and appropriate:
+ self.currentToken = {"type": tokenTypes["EndTag"],
+ "name": self.temporaryBuffer,
+ "data": [], "selfClosing": False}
+ self.state = self.selfClosingStartTagState
+ elif data == ">" and appropriate:
+ self.currentToken = {"type": tokenTypes["EndTag"],
+ "name": self.temporaryBuffer,
+ "data": [], "selfClosing": False}
+ self.emitCurrentToken()
+ self.state = self.dataState
+ elif data in asciiLetters:
+ self.temporaryBuffer += data
+ else:
+ self.tokenQueue.append({"type": tokenTypes["Characters"],
+ "data": "</" + self.temporaryBuffer})
+ self.stream.unget(data)
+ self.state = self.rcdataState
+ return True
+
+ def rawtextLessThanSignState(self):
+ data = self.stream.char()
+ if data == "/":
+ self.temporaryBuffer = ""
+ self.state = self.rawtextEndTagOpenState
+ else:
+ self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<"})
+ self.stream.unget(data)
+ self.state = self.rawtextState
+ return True
+
+ def rawtextEndTagOpenState(self):
+ data = self.stream.char()
+ if data in asciiLetters:
+ self.temporaryBuffer += data
+ self.state = self.rawtextEndTagNameState
+ else:
+ self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "</"})
+ self.stream.unget(data)
+ self.state = self.rawtextState
+ return True
+
+ def rawtextEndTagNameState(self):
+ appropriate = self.currentToken and self.currentToken["name"].lower() == self.temporaryBuffer.lower()
+ data = self.stream.char()
+ if data in spaceCharacters and appropriate:
+ self.currentToken = {"type": tokenTypes["EndTag"],
+ "name": self.temporaryBuffer,
+ "data": [], "selfClosing": False}
+ self.state = self.beforeAttributeNameState
+ elif data == "/" and appropriate:
+ self.currentToken = {"type": tokenTypes["EndTag"],
+ "name": self.temporaryBuffer,
+ "data": [], "selfClosing": False}
+ self.state = self.selfClosingStartTagState
+ elif data == ">" and appropriate:
+ self.currentToken = {"type": tokenTypes["EndTag"],
+ "name": self.temporaryBuffer,
+ "data": [], "selfClosing": False}
+ self.emitCurrentToken()
+ self.state = self.dataState
+ elif data in asciiLetters:
+ self.temporaryBuffer += data
+ else:
+ self.tokenQueue.append({"type": tokenTypes["Characters"],
+ "data": "</" + self.temporaryBuffer})
+ self.stream.unget(data)
+ self.state = self.rawtextState
+ return True
+
+ def scriptDataLessThanSignState(self):
+ data = self.stream.char()
+ if data == "/":
+ self.temporaryBuffer = ""
+ self.state = self.scriptDataEndTagOpenState
+ elif data == "!":
+ self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<!"})
+ self.state = self.scriptDataEscapeStartState
+ else:
+ self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<"})
+ self.stream.unget(data)
+ self.state = self.scriptDataState
+ return True
+
+ def scriptDataEndTagOpenState(self):
+ data = self.stream.char()
+ if data in asciiLetters:
+ self.temporaryBuffer += data
+ self.state = self.scriptDataEndTagNameState
+ else:
+ self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "</"})
+ self.stream.unget(data)
+ self.state = self.scriptDataState
+ return True
+
+ def scriptDataEndTagNameState(self):
+ appropriate = self.currentToken and self.currentToken["name"].lower() == self.temporaryBuffer.lower()
+ data = self.stream.char()
+ if data in spaceCharacters and appropriate:
+ self.currentToken = {"type": tokenTypes["EndTag"],
+ "name": self.temporaryBuffer,
+ "data": [], "selfClosing": False}
+ self.state = self.beforeAttributeNameState
+ elif data == "/" and appropriate:
+ self.currentToken = {"type": tokenTypes["EndTag"],
+ "name": self.temporaryBuffer,
+ "data": [], "selfClosing": False}
+ self.state = self.selfClosingStartTagState
+ elif data == ">" and appropriate:
+ self.currentToken = {"type": tokenTypes["EndTag"],
+ "name": self.temporaryBuffer,
+ "data": [], "selfClosing": False}
+ self.emitCurrentToken()
+ self.state = self.dataState
+ elif data in asciiLetters:
+ self.temporaryBuffer += data
+ else:
+ self.tokenQueue.append({"type": tokenTypes["Characters"],
+ "data": "</" + self.temporaryBuffer})
+ self.stream.unget(data)
+ self.state = self.scriptDataState
+ return True
+
+ def scriptDataEscapeStartState(self):
+ data = self.stream.char()
+ if data == "-":
+ self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "-"})
+ self.state = self.scriptDataEscapeStartDashState
+ else:
+ self.stream.unget(data)
+ self.state = self.scriptDataState
+ return True
+
+ def scriptDataEscapeStartDashState(self):
+ data = self.stream.char()
+ if data == "-":
+ self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "-"})
+ self.state = self.scriptDataEscapedDashDashState
+ else:
+ self.stream.unget(data)
+ self.state = self.scriptDataState
+ return True
+
+ def scriptDataEscapedState(self):
+ data = self.stream.char()
+ if data == "-":
+ self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "-"})
+ self.state = self.scriptDataEscapedDashState
+ elif data == "<":
+ self.state = self.scriptDataEscapedLessThanSignState
+ elif data == "\u0000":
+ self.tokenQueue.append({"type": tokenTypes["ParseError"],
+ "data": "invalid-codepoint"})
+ self.tokenQueue.append({"type": tokenTypes["Characters"],
+ "data": "\uFFFD"})
+ elif data == EOF:
+ self.state = self.dataState
+ else:
+ chars = self.stream.charsUntil(("<", "-", "\u0000"))
+ self.tokenQueue.append({"type": tokenTypes["Characters"], "data":
+ data + chars})
+ return True
+
+ def scriptDataEscapedDashState(self):
+ data = self.stream.char()
+ if data == "-":
+ self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "-"})
+ self.state = self.scriptDataEscapedDashDashState
+ elif data == "<":
+ self.state = self.scriptDataEscapedLessThanSignState
+ elif data == "\u0000":
+ self.tokenQueue.append({"type": tokenTypes["ParseError"],
+ "data": "invalid-codepoint"})
+ self.tokenQueue.append({"type": tokenTypes["Characters"],
+ "data": "\uFFFD"})
+ self.state = self.scriptDataEscapedState
+ elif data == EOF:
+ self.state = self.dataState
+ else:
+ self.tokenQueue.append({"type": tokenTypes["Characters"], "data": data})
+ self.state = self.scriptDataEscapedState
+ return True
+
+ def scriptDataEscapedDashDashState(self):
+ data = self.stream.char()
+ if data == "-":
+ self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "-"})
+ elif data == "<":
+ self.state = self.scriptDataEscapedLessThanSignState
+ elif data == ">":
+ self.tokenQueue.append({"type": tokenTypes["Characters"], "data": ">"})
+ self.state = self.scriptDataState
+ elif data == "\u0000":
+ self.tokenQueue.append({"type": tokenTypes["ParseError"],
+ "data": "invalid-codepoint"})
+ self.tokenQueue.append({"type": tokenTypes["Characters"],
+ "data": "\uFFFD"})
+ self.state = self.scriptDataEscapedState
+ elif data == EOF:
+ self.state = self.dataState
+ else:
+ self.tokenQueue.append({"type": tokenTypes["Characters"], "data": data})
+ self.state = self.scriptDataEscapedState
+ return True
+
+ def scriptDataEscapedLessThanSignState(self):
+ data = self.stream.char()
+ if data == "/":
+ self.temporaryBuffer = ""
+ self.state = self.scriptDataEscapedEndTagOpenState
+ elif data in asciiLetters:
+ self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<" + data})
+ self.temporaryBuffer = data
+ self.state = self.scriptDataDoubleEscapeStartState
+ else:
+ self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<"})
+ self.stream.unget(data)
+ self.state = self.scriptDataEscapedState
+ return True
+
+ def scriptDataEscapedEndTagOpenState(self):
+ data = self.stream.char()
+ if data in asciiLetters:
+ self.temporaryBuffer = data
+ self.state = self.scriptDataEscapedEndTagNameState
+ else:
+ self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "</"})
+ self.stream.unget(data)
+ self.state = self.scriptDataEscapedState
+ return True
+
+ def scriptDataEscapedEndTagNameState(self):
+ appropriate = self.currentToken and self.currentToken["name"].lower() == self.temporaryBuffer.lower()
+ data = self.stream.char()
+ if data in spaceCharacters and appropriate:
+ self.currentToken = {"type": tokenTypes["EndTag"],
+ "name": self.temporaryBuffer,
+ "data": [], "selfClosing": False}
+ self.state = self.beforeAttributeNameState
+ elif data == "/" and appropriate:
+ self.currentToken = {"type": tokenTypes["EndTag"],
+ "name": self.temporaryBuffer,
+ "data": [], "selfClosing": False}
+ self.state = self.selfClosingStartTagState
+ elif data == ">" and appropriate:
+ self.currentToken = {"type": tokenTypes["EndTag"],
+ "name": self.temporaryBuffer,
+ "data": [], "selfClosing": False}
+ self.emitCurrentToken()
+ self.state = self.dataState
+ elif data in asciiLetters:
+ self.temporaryBuffer += data
+ else:
+ self.tokenQueue.append({"type": tokenTypes["Characters"],
+ "data": "</" + self.temporaryBuffer})
+ self.stream.unget(data)
+ self.state = self.scriptDataEscapedState
+ return True
+
+ def scriptDataDoubleEscapeStartState(self):
+ data = self.stream.char()
+ if data in (spaceCharacters | frozenset(("/", ">"))):
+ self.tokenQueue.append({"type": tokenTypes["Characters"], "data": data})
+ if self.temporaryBuffer.lower() == "script":
+ self.state = self.scriptDataDoubleEscapedState
+ else:
+ self.state = self.scriptDataEscapedState
+ elif data in asciiLetters:
+ self.tokenQueue.append({"type": tokenTypes["Characters"], "data": data})
+ self.temporaryBuffer += data
+ else:
+ self.stream.unget(data)
+ self.state = self.scriptDataEscapedState
+ return True
+
+ def scriptDataDoubleEscapedState(self):
+ data = self.stream.char()
+ if data == "-":
+ self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "-"})
+ self.state = self.scriptDataDoubleEscapedDashState
+ elif data == "<":
+ self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<"})
+ self.state = self.scriptDataDoubleEscapedLessThanSignState
+ elif data == "\u0000":
+ self.tokenQueue.append({"type": tokenTypes["ParseError"],
+ "data": "invalid-codepoint"})
+ self.tokenQueue.append({"type": tokenTypes["Characters"],
+ "data": "\uFFFD"})
+ elif data == EOF:
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "eof-in-script-in-script"})
+ self.state = self.dataState
+ else:
+ self.tokenQueue.append({"type": tokenTypes["Characters"], "data": data})
+ return True
+
+ def scriptDataDoubleEscapedDashState(self):
+ data = self.stream.char()
+ if data == "-":
+ self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "-"})
+ self.state = self.scriptDataDoubleEscapedDashDashState
+ elif data == "<":
+ self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<"})
+ self.state = self.scriptDataDoubleEscapedLessThanSignState
+ elif data == "\u0000":
+ self.tokenQueue.append({"type": tokenTypes["ParseError"],
+ "data": "invalid-codepoint"})
+ self.tokenQueue.append({"type": tokenTypes["Characters"],
+ "data": "\uFFFD"})
+ self.state = self.scriptDataDoubleEscapedState
+ elif data == EOF:
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "eof-in-script-in-script"})
+ self.state = self.dataState
+ else:
+ self.tokenQueue.append({"type": tokenTypes["Characters"], "data": data})
+ self.state = self.scriptDataDoubleEscapedState
+ return True
+
+ def scriptDataDoubleEscapedDashDashState(self):
+ data = self.stream.char()
+ if data == "-":
+ self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "-"})
+ elif data == "<":
+ self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<"})
+ self.state = self.scriptDataDoubleEscapedLessThanSignState
+ elif data == ">":
+ self.tokenQueue.append({"type": tokenTypes["Characters"], "data": ">"})
+ self.state = self.scriptDataState
+ elif data == "\u0000":
+ self.tokenQueue.append({"type": tokenTypes["ParseError"],
+ "data": "invalid-codepoint"})
+ self.tokenQueue.append({"type": tokenTypes["Characters"],
+ "data": "\uFFFD"})
+ self.state = self.scriptDataDoubleEscapedState
+ elif data == EOF:
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "eof-in-script-in-script"})
+ self.state = self.dataState
+ else:
+ self.tokenQueue.append({"type": tokenTypes["Characters"], "data": data})
+ self.state = self.scriptDataDoubleEscapedState
+ return True
+
+ def scriptDataDoubleEscapedLessThanSignState(self):
+ data = self.stream.char()
+ if data == "/":
+ self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "/"})
+ self.temporaryBuffer = ""
+ self.state = self.scriptDataDoubleEscapeEndState
+ else:
+ self.stream.unget(data)
+ self.state = self.scriptDataDoubleEscapedState
+ return True
+
+ def scriptDataDoubleEscapeEndState(self):
+ data = self.stream.char()
+ if data in (spaceCharacters | frozenset(("/", ">"))):
+ self.tokenQueue.append({"type": tokenTypes["Characters"], "data": data})
+ if self.temporaryBuffer.lower() == "script":
+ self.state = self.scriptDataEscapedState
+ else:
+ self.state = self.scriptDataDoubleEscapedState
+ elif data in asciiLetters:
+ self.tokenQueue.append({"type": tokenTypes["Characters"], "data": data})
+ self.temporaryBuffer += data
+ else:
+ self.stream.unget(data)
+ self.state = self.scriptDataDoubleEscapedState
+ return True
+
+ def beforeAttributeNameState(self):
+ data = self.stream.char()
+ if data in spaceCharacters:
+ self.stream.charsUntil(spaceCharacters, True)
+ elif data in asciiLetters:
+ self.currentToken["data"].append([data, ""])
+ self.state = self.attributeNameState
+ elif data == ">":
+ self.emitCurrentToken()
+ elif data == "/":
+ self.state = self.selfClosingStartTagState
+ elif data in ("'", '"', "=", "<"):
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "invalid-character-in-attribute-name"})
+ self.currentToken["data"].append([data, ""])
+ self.state = self.attributeNameState
+ elif data == "\u0000":
+ self.tokenQueue.append({"type": tokenTypes["ParseError"],
+ "data": "invalid-codepoint"})
+ self.currentToken["data"].append(["\uFFFD", ""])
+ self.state = self.attributeNameState
+ elif data is EOF:
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "expected-attribute-name-but-got-eof"})
+ self.state = self.dataState
+ else:
+ self.currentToken["data"].append([data, ""])
+ self.state = self.attributeNameState
+ return True
+
+ def attributeNameState(self):
+ data = self.stream.char()
+ leavingThisState = True
+ emitToken = False
+ if data == "=":
+ self.state = self.beforeAttributeValueState
+ elif data in asciiLetters:
+ self.currentToken["data"][-1][0] += data +\
+ self.stream.charsUntil(asciiLetters, True)
+ leavingThisState = False
+ elif data == ">":
+ # XXX If we emit here the attributes are converted to a dict
+ # without being checked and when the code below runs we error
+ # because data is a dict not a list
+ emitToken = True
+ elif data in spaceCharacters:
+ self.state = self.afterAttributeNameState
+ elif data == "/":
+ self.state = self.selfClosingStartTagState
+ elif data == "\u0000":
+ self.tokenQueue.append({"type": tokenTypes["ParseError"],
+ "data": "invalid-codepoint"})
+ self.currentToken["data"][-1][0] += "\uFFFD"
+ leavingThisState = False
+ elif data in ("'", '"', "<"):
+ self.tokenQueue.append({"type": tokenTypes["ParseError"],
+ "data":
+ "invalid-character-in-attribute-name"})
+ self.currentToken["data"][-1][0] += data
+ leavingThisState = False
+ elif data is EOF:
+ self.tokenQueue.append({"type": tokenTypes["ParseError"],
+ "data": "eof-in-attribute-name"})
+ self.state = self.dataState
+ else:
+ self.currentToken["data"][-1][0] += data
+ leavingThisState = False
+
+ if leavingThisState:
+ # Attributes are not dropped at this stage. That happens when the
+ # start tag token is emitted so values can still be safely appended
+ # to attributes, but we do want to report the parse error in time.
+ if self.lowercaseAttrName:
+ self.currentToken["data"][-1][0] = (
+ self.currentToken["data"][-1][0].translate(asciiUpper2Lower))
+ for name, value in self.currentToken["data"][:-1]:
+ if self.currentToken["data"][-1][0] == name:
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "duplicate-attribute"})
+ break
+ # XXX Fix for above XXX
+ if emitToken:
+ self.emitCurrentToken()
+ return True
+
+ def afterAttributeNameState(self):
+ data = self.stream.char()
+ if data in spaceCharacters:
+ self.stream.charsUntil(spaceCharacters, True)
+ elif data == "=":
+ self.state = self.beforeAttributeValueState
+ elif data == ">":
+ self.emitCurrentToken()
+ elif data in asciiLetters:
+ self.currentToken["data"].append([data, ""])
+ self.state = self.attributeNameState
+ elif data == "/":
+ self.state = self.selfClosingStartTagState
+ elif data == "\u0000":
+ self.tokenQueue.append({"type": tokenTypes["ParseError"],
+ "data": "invalid-codepoint"})
+ self.currentToken["data"].append(["\uFFFD", ""])
+ self.state = self.attributeNameState
+ elif data in ("'", '"', "<"):
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "invalid-character-after-attribute-name"})
+ self.currentToken["data"].append([data, ""])
+ self.state = self.attributeNameState
+ elif data is EOF:
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "expected-end-of-tag-but-got-eof"})
+ self.state = self.dataState
+ else:
+ self.currentToken["data"].append([data, ""])
+ self.state = self.attributeNameState
+ return True
+
+ def beforeAttributeValueState(self):
+ data = self.stream.char()
+ if data in spaceCharacters:
+ self.stream.charsUntil(spaceCharacters, True)
+ elif data == "\"":
+ self.state = self.attributeValueDoubleQuotedState
+ elif data == "&":
+ self.state = self.attributeValueUnQuotedState
+ self.stream.unget(data)
+ elif data == "'":
+ self.state = self.attributeValueSingleQuotedState
+ elif data == ">":
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "expected-attribute-value-but-got-right-bracket"})
+ self.emitCurrentToken()
+ elif data == "\u0000":
+ self.tokenQueue.append({"type": tokenTypes["ParseError"],
+ "data": "invalid-codepoint"})
+ self.currentToken["data"][-1][1] += "\uFFFD"
+ self.state = self.attributeValueUnQuotedState
+ elif data in ("=", "<", "`"):
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "equals-in-unquoted-attribute-value"})
+ self.currentToken["data"][-1][1] += data
+ self.state = self.attributeValueUnQuotedState
+ elif data is EOF:
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "expected-attribute-value-but-got-eof"})
+ self.state = self.dataState
+ else:
+ self.currentToken["data"][-1][1] += data
+ self.state = self.attributeValueUnQuotedState
+ return True
+
+ def attributeValueDoubleQuotedState(self):
+ data = self.stream.char()
+ if data == "\"":
+ self.state = self.afterAttributeValueState
+ elif data == "&":
+ self.processEntityInAttribute('"')
+ elif data == "\u0000":
+ self.tokenQueue.append({"type": tokenTypes["ParseError"],
+ "data": "invalid-codepoint"})
+ self.currentToken["data"][-1][1] += "\uFFFD"
+ elif data is EOF:
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "eof-in-attribute-value-double-quote"})
+ self.state = self.dataState
+ else:
+ self.currentToken["data"][-1][1] += data +\
+ self.stream.charsUntil(("\"", "&", "\u0000"))
+ return True
+
+ def attributeValueSingleQuotedState(self):
+ data = self.stream.char()
+ if data == "'":
+ self.state = self.afterAttributeValueState
+ elif data == "&":
+ self.processEntityInAttribute("'")
+ elif data == "\u0000":
+ self.tokenQueue.append({"type": tokenTypes["ParseError"],
+ "data": "invalid-codepoint"})
+ self.currentToken["data"][-1][1] += "\uFFFD"
+ elif data is EOF:
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "eof-in-attribute-value-single-quote"})
+ self.state = self.dataState
+ else:
+ self.currentToken["data"][-1][1] += data +\
+ self.stream.charsUntil(("'", "&", "\u0000"))
+ return True
+
+ def attributeValueUnQuotedState(self):
+ data = self.stream.char()
+ if data in spaceCharacters:
+ self.state = self.beforeAttributeNameState
+ elif data == "&":
+ self.processEntityInAttribute(">")
+ elif data == ">":
+ self.emitCurrentToken()
+ elif data in ('"', "'", "=", "<", "`"):
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "unexpected-character-in-unquoted-attribute-value"})
+ self.currentToken["data"][-1][1] += data
+ elif data == "\u0000":
+ self.tokenQueue.append({"type": tokenTypes["ParseError"],
+ "data": "invalid-codepoint"})
+ self.currentToken["data"][-1][1] += "\uFFFD"
+ elif data is EOF:
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "eof-in-attribute-value-no-quotes"})
+ self.state = self.dataState
+ else:
+ self.currentToken["data"][-1][1] += data + self.stream.charsUntil(
+ frozenset(("&", ">", '"', "'", "=", "<", "`", "\u0000")) | spaceCharacters)
+ return True
+
+ def afterAttributeValueState(self):
+ data = self.stream.char()
+ if data in spaceCharacters:
+ self.state = self.beforeAttributeNameState
+ elif data == ">":
+ self.emitCurrentToken()
+ elif data == "/":
+ self.state = self.selfClosingStartTagState
+ elif data is EOF:
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "unexpected-EOF-after-attribute-value"})
+ self.stream.unget(data)
+ self.state = self.dataState
+ else:
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "unexpected-character-after-attribute-value"})
+ self.stream.unget(data)
+ self.state = self.beforeAttributeNameState
+ return True
+
+ def selfClosingStartTagState(self):
+ data = self.stream.char()
+ if data == ">":
+ self.currentToken["selfClosing"] = True
+ self.emitCurrentToken()
+ elif data is EOF:
+ self.tokenQueue.append({"type": tokenTypes["ParseError"],
+ "data":
+ "unexpected-EOF-after-solidus-in-tag"})
+ self.stream.unget(data)
+ self.state = self.dataState
+ else:
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "unexpected-character-after-solidus-in-tag"})
+ self.stream.unget(data)
+ self.state = self.beforeAttributeNameState
+ return True
+
+ def bogusCommentState(self):
+ # Make a new comment token and give it as value all the characters
+ # until the first > or EOF (charsUntil checks for EOF automatically)
+ # and emit it.
+ data = self.stream.charsUntil(">")
+ data = data.replace("\u0000", "\uFFFD")
+ self.tokenQueue.append(
+ {"type": tokenTypes["Comment"], "data": data})
+
+ # Eat the character directly after the bogus comment which is either a
+ # ">" or an EOF.
+ self.stream.char()
+ self.state = self.dataState
+ return True
+
+ def markupDeclarationOpenState(self):
+ charStack = [self.stream.char()]
+ if charStack[-1] == "-":
+ charStack.append(self.stream.char())
+ if charStack[-1] == "-":
+ self.currentToken = {"type": tokenTypes["Comment"], "data": ""}
+ self.state = self.commentStartState
+ return True
+ elif charStack[-1] in ('d', 'D'):
+ matched = True
+ for expected in (('o', 'O'), ('c', 'C'), ('t', 'T'),
+ ('y', 'Y'), ('p', 'P'), ('e', 'E')):
+ charStack.append(self.stream.char())
+ if charStack[-1] not in expected:
+ matched = False
+ break
+ if matched:
+ self.currentToken = {"type": tokenTypes["Doctype"],
+ "name": "",
+ "publicId": None, "systemId": None,
+ "correct": True}
+ self.state = self.doctypeState
+ return True
+ elif (charStack[-1] == "[" and
+ self.parser is not None and
+ self.parser.tree.openElements and
+ self.parser.tree.openElements[-1].namespace != self.parser.tree.defaultNamespace):
+ matched = True
+ for expected in ["C", "D", "A", "T", "A", "["]:
+ charStack.append(self.stream.char())
+ if charStack[-1] != expected:
+ matched = False
+ break
+ if matched:
+ self.state = self.cdataSectionState
+ return True
+
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "expected-dashes-or-doctype"})
+
+ while charStack:
+ self.stream.unget(charStack.pop())
+ self.state = self.bogusCommentState
+ return True
+
+ def commentStartState(self):
+ data = self.stream.char()
+ if data == "-":
+ self.state = self.commentStartDashState
+ elif data == "\u0000":
+ self.tokenQueue.append({"type": tokenTypes["ParseError"],
+ "data": "invalid-codepoint"})
+ self.currentToken["data"] += "\uFFFD"
+ elif data == ">":
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "incorrect-comment"})
+ self.tokenQueue.append(self.currentToken)
+ self.state = self.dataState
+ elif data is EOF:
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "eof-in-comment"})
+ self.tokenQueue.append(self.currentToken)
+ self.state = self.dataState
+ else:
+ self.currentToken["data"] += data
+ self.state = self.commentState
+ return True
+
+ def commentStartDashState(self):
+ data = self.stream.char()
+ if data == "-":
+ self.state = self.commentEndState
+ elif data == "\u0000":
+ self.tokenQueue.append({"type": tokenTypes["ParseError"],
+ "data": "invalid-codepoint"})
+ self.currentToken["data"] += "-\uFFFD"
+ elif data == ">":
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "incorrect-comment"})
+ self.tokenQueue.append(self.currentToken)
+ self.state = self.dataState
+ elif data is EOF:
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "eof-in-comment"})
+ self.tokenQueue.append(self.currentToken)
+ self.state = self.dataState
+ else:
+ self.currentToken["data"] += "-" + data
+ self.state = self.commentState
+ return True
+
+ def commentState(self):
+ data = self.stream.char()
+ if data == "-":
+ self.state = self.commentEndDashState
+ elif data == "\u0000":
+ self.tokenQueue.append({"type": tokenTypes["ParseError"],
+ "data": "invalid-codepoint"})
+ self.currentToken["data"] += "\uFFFD"
+ elif data is EOF:
+ self.tokenQueue.append({"type": tokenTypes["ParseError"],
+ "data": "eof-in-comment"})
+ self.tokenQueue.append(self.currentToken)
+ self.state = self.dataState
+ else:
+ self.currentToken["data"] += data + \
+ self.stream.charsUntil(("-", "\u0000"))
+ return True
+
+ def commentEndDashState(self):
+ data = self.stream.char()
+ if data == "-":
+ self.state = self.commentEndState
+ elif data == "\u0000":
+ self.tokenQueue.append({"type": tokenTypes["ParseError"],
+ "data": "invalid-codepoint"})
+ self.currentToken["data"] += "-\uFFFD"
+ self.state = self.commentState
+ elif data is EOF:
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "eof-in-comment-end-dash"})
+ self.tokenQueue.append(self.currentToken)
+ self.state = self.dataState
+ else:
+ self.currentToken["data"] += "-" + data
+ self.state = self.commentState
+ return True
+
+ def commentEndState(self):
+ data = self.stream.char()
+ if data == ">":
+ self.tokenQueue.append(self.currentToken)
+ self.state = self.dataState
+ elif data == "\u0000":
+ self.tokenQueue.append({"type": tokenTypes["ParseError"],
+ "data": "invalid-codepoint"})
+ self.currentToken["data"] += "--\uFFFD"
+ self.state = self.commentState
+ elif data == "!":
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "unexpected-bang-after-double-dash-in-comment"})
+ self.state = self.commentEndBangState
+ elif data == "-":
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "unexpected-dash-after-double-dash-in-comment"})
+ self.currentToken["data"] += data
+ elif data is EOF:
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "eof-in-comment-double-dash"})
+ self.tokenQueue.append(self.currentToken)
+ self.state = self.dataState
+ else:
+ # XXX
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "unexpected-char-in-comment"})
+ self.currentToken["data"] += "--" + data
+ self.state = self.commentState
+ return True
+
+ def commentEndBangState(self):
+ data = self.stream.char()
+ if data == ">":
+ self.tokenQueue.append(self.currentToken)
+ self.state = self.dataState
+ elif data == "-":
+ self.currentToken["data"] += "--!"
+ self.state = self.commentEndDashState
+ elif data == "\u0000":
+ self.tokenQueue.append({"type": tokenTypes["ParseError"],
+ "data": "invalid-codepoint"})
+ self.currentToken["data"] += "--!\uFFFD"
+ self.state = self.commentState
+ elif data is EOF:
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "eof-in-comment-end-bang-state"})
+ self.tokenQueue.append(self.currentToken)
+ self.state = self.dataState
+ else:
+ self.currentToken["data"] += "--!" + data
+ self.state = self.commentState
+ return True
+
+ def doctypeState(self):
+ data = self.stream.char()
+ if data in spaceCharacters:
+ self.state = self.beforeDoctypeNameState
+ elif data is EOF:
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "expected-doctype-name-but-got-eof"})
+ self.currentToken["correct"] = False
+ self.tokenQueue.append(self.currentToken)
+ self.state = self.dataState
+ else:
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "need-space-after-doctype"})
+ self.stream.unget(data)
+ self.state = self.beforeDoctypeNameState
+ return True
+
+ def beforeDoctypeNameState(self):
+ data = self.stream.char()
+ if data in spaceCharacters:
+ pass
+ elif data == ">":
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "expected-doctype-name-but-got-right-bracket"})
+ self.currentToken["correct"] = False
+ self.tokenQueue.append(self.currentToken)
+ self.state = self.dataState
+ elif data == "\u0000":
+ self.tokenQueue.append({"type": tokenTypes["ParseError"],
+ "data": "invalid-codepoint"})
+ self.currentToken["name"] = "\uFFFD"
+ self.state = self.doctypeNameState
+ elif data is EOF:
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "expected-doctype-name-but-got-eof"})
+ self.currentToken["correct"] = False
+ self.tokenQueue.append(self.currentToken)
+ self.state = self.dataState
+ else:
+ self.currentToken["name"] = data
+ self.state = self.doctypeNameState
+ return True
+
+ def doctypeNameState(self):
+ data = self.stream.char()
+ if data in spaceCharacters:
+ self.currentToken["name"] = self.currentToken["name"].translate(asciiUpper2Lower)
+ self.state = self.afterDoctypeNameState
+ elif data == ">":
+ self.currentToken["name"] = self.currentToken["name"].translate(asciiUpper2Lower)
+ self.tokenQueue.append(self.currentToken)
+ self.state = self.dataState
+ elif data == "\u0000":
+ self.tokenQueue.append({"type": tokenTypes["ParseError"],
+ "data": "invalid-codepoint"})
+ self.currentToken["name"] += "\uFFFD"
+ self.state = self.doctypeNameState
+ elif data is EOF:
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "eof-in-doctype-name"})
+ self.currentToken["correct"] = False
+ self.currentToken["name"] = self.currentToken["name"].translate(asciiUpper2Lower)
+ self.tokenQueue.append(self.currentToken)
+ self.state = self.dataState
+ else:
+ self.currentToken["name"] += data
+ return True
+
+ def afterDoctypeNameState(self):
+ data = self.stream.char()
+ if data in spaceCharacters:
+ pass
+ elif data == ">":
+ self.tokenQueue.append(self.currentToken)
+ self.state = self.dataState
+ elif data is EOF:
+ self.currentToken["correct"] = False
+ self.stream.unget(data)
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "eof-in-doctype"})
+ self.tokenQueue.append(self.currentToken)
+ self.state = self.dataState
+ else:
+ if data in ("p", "P"):
+ matched = True
+ for expected in (("u", "U"), ("b", "B"), ("l", "L"),
+ ("i", "I"), ("c", "C")):
+ data = self.stream.char()
+ if data not in expected:
+ matched = False
+ break
+ if matched:
+ self.state = self.afterDoctypePublicKeywordState
+ return True
+ elif data in ("s", "S"):
+ matched = True
+ for expected in (("y", "Y"), ("s", "S"), ("t", "T"),
+ ("e", "E"), ("m", "M")):
+ data = self.stream.char()
+ if data not in expected:
+ matched = False
+ break
+ if matched:
+ self.state = self.afterDoctypeSystemKeywordState
+ return True
+
+ # All the characters read before the current 'data' will be
+ # [a-zA-Z], so they're garbage in the bogus doctype and can be
+ # discarded; only the latest character might be '>' or EOF
+ # and needs to be ungetted
+ self.stream.unget(data)
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "expected-space-or-right-bracket-in-doctype", "datavars":
+ {"data": data}})
+ self.currentToken["correct"] = False
+ self.state = self.bogusDoctypeState
+
+ return True
+
+ def afterDoctypePublicKeywordState(self):
+ data = self.stream.char()
+ if data in spaceCharacters:
+ self.state = self.beforeDoctypePublicIdentifierState
+ elif data in ("'", '"'):
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "unexpected-char-in-doctype"})
+ self.stream.unget(data)
+ self.state = self.beforeDoctypePublicIdentifierState
+ elif data is EOF:
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "eof-in-doctype"})
+ self.currentToken["correct"] = False
+ self.tokenQueue.append(self.currentToken)
+ self.state = self.dataState
+ else:
+ self.stream.unget(data)
+ self.state = self.beforeDoctypePublicIdentifierState
+ return True
+
+ def beforeDoctypePublicIdentifierState(self):
+ data = self.stream.char()
+ if data in spaceCharacters:
+ pass
+ elif data == "\"":
+ self.currentToken["publicId"] = ""
+ self.state = self.doctypePublicIdentifierDoubleQuotedState
+ elif data == "'":
+ self.currentToken["publicId"] = ""
+ self.state = self.doctypePublicIdentifierSingleQuotedState
+ elif data == ">":
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "unexpected-end-of-doctype"})
+ self.currentToken["correct"] = False
+ self.tokenQueue.append(self.currentToken)
+ self.state = self.dataState
+ elif data is EOF:
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "eof-in-doctype"})
+ self.currentToken["correct"] = False
+ self.tokenQueue.append(self.currentToken)
+ self.state = self.dataState
+ else:
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "unexpected-char-in-doctype"})
+ self.currentToken["correct"] = False
+ self.state = self.bogusDoctypeState
+ return True
+
+ def doctypePublicIdentifierDoubleQuotedState(self):
+ data = self.stream.char()
+ if data == "\"":
+ self.state = self.afterDoctypePublicIdentifierState
+ elif data == "\u0000":
+ self.tokenQueue.append({"type": tokenTypes["ParseError"],
+ "data": "invalid-codepoint"})
+ self.currentToken["publicId"] += "\uFFFD"
+ elif data == ">":
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "unexpected-end-of-doctype"})
+ self.currentToken["correct"] = False
+ self.tokenQueue.append(self.currentToken)
+ self.state = self.dataState
+ elif data is EOF:
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "eof-in-doctype"})
+ self.currentToken["correct"] = False
+ self.tokenQueue.append(self.currentToken)
+ self.state = self.dataState
+ else:
+ self.currentToken["publicId"] += data
+ return True
+
+ def doctypePublicIdentifierSingleQuotedState(self):
+ data = self.stream.char()
+ if data == "'":
+ self.state = self.afterDoctypePublicIdentifierState
+ elif data == "\u0000":
+ self.tokenQueue.append({"type": tokenTypes["ParseError"],
+ "data": "invalid-codepoint"})
+ self.currentToken["publicId"] += "\uFFFD"
+ elif data == ">":
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "unexpected-end-of-doctype"})
+ self.currentToken["correct"] = False
+ self.tokenQueue.append(self.currentToken)
+ self.state = self.dataState
+ elif data is EOF:
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "eof-in-doctype"})
+ self.currentToken["correct"] = False
+ self.tokenQueue.append(self.currentToken)
+ self.state = self.dataState
+ else:
+ self.currentToken["publicId"] += data
+ return True
+
+ def afterDoctypePublicIdentifierState(self):
+ data = self.stream.char()
+ if data in spaceCharacters:
+ self.state = self.betweenDoctypePublicAndSystemIdentifiersState
+ elif data == ">":
+ self.tokenQueue.append(self.currentToken)
+ self.state = self.dataState
+ elif data == '"':
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "unexpected-char-in-doctype"})
+ self.currentToken["systemId"] = ""
+ self.state = self.doctypeSystemIdentifierDoubleQuotedState
+ elif data == "'":
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "unexpected-char-in-doctype"})
+ self.currentToken["systemId"] = ""
+ self.state = self.doctypeSystemIdentifierSingleQuotedState
+ elif data is EOF:
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "eof-in-doctype"})
+ self.currentToken["correct"] = False
+ self.tokenQueue.append(self.currentToken)
+ self.state = self.dataState
+ else:
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "unexpected-char-in-doctype"})
+ self.currentToken["correct"] = False
+ self.state = self.bogusDoctypeState
+ return True
+
+ def betweenDoctypePublicAndSystemIdentifiersState(self):
+ data = self.stream.char()
+ if data in spaceCharacters:
+ pass
+ elif data == ">":
+ self.tokenQueue.append(self.currentToken)
+ self.state = self.dataState
+ elif data == '"':
+ self.currentToken["systemId"] = ""
+ self.state = self.doctypeSystemIdentifierDoubleQuotedState
+ elif data == "'":
+ self.currentToken["systemId"] = ""
+ self.state = self.doctypeSystemIdentifierSingleQuotedState
+ elif data == EOF:
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "eof-in-doctype"})
+ self.currentToken["correct"] = False
+ self.tokenQueue.append(self.currentToken)
+ self.state = self.dataState
+ else:
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "unexpected-char-in-doctype"})
+ self.currentToken["correct"] = False
+ self.state = self.bogusDoctypeState
+ return True
+
+ def afterDoctypeSystemKeywordState(self):
+ data = self.stream.char()
+ if data in spaceCharacters:
+ self.state = self.beforeDoctypeSystemIdentifierState
+ elif data in ("'", '"'):
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "unexpected-char-in-doctype"})
+ self.stream.unget(data)
+ self.state = self.beforeDoctypeSystemIdentifierState
+ elif data is EOF:
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "eof-in-doctype"})
+ self.currentToken["correct"] = False
+ self.tokenQueue.append(self.currentToken)
+ self.state = self.dataState
+ else:
+ self.stream.unget(data)
+ self.state = self.beforeDoctypeSystemIdentifierState
+ return True
+
+ def beforeDoctypeSystemIdentifierState(self):
+ data = self.stream.char()
+ if data in spaceCharacters:
+ pass
+ elif data == "\"":
+ self.currentToken["systemId"] = ""
+ self.state = self.doctypeSystemIdentifierDoubleQuotedState
+ elif data == "'":
+ self.currentToken["systemId"] = ""
+ self.state = self.doctypeSystemIdentifierSingleQuotedState
+ elif data == ">":
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "unexpected-char-in-doctype"})
+ self.currentToken["correct"] = False
+ self.tokenQueue.append(self.currentToken)
+ self.state = self.dataState
+ elif data is EOF:
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "eof-in-doctype"})
+ self.currentToken["correct"] = False
+ self.tokenQueue.append(self.currentToken)
+ self.state = self.dataState
+ else:
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "unexpected-char-in-doctype"})
+ self.currentToken["correct"] = False
+ self.state = self.bogusDoctypeState
+ return True
+
+ def doctypeSystemIdentifierDoubleQuotedState(self):
+ data = self.stream.char()
+ if data == "\"":
+ self.state = self.afterDoctypeSystemIdentifierState
+ elif data == "\u0000":
+ self.tokenQueue.append({"type": tokenTypes["ParseError"],
+ "data": "invalid-codepoint"})
+ self.currentToken["systemId"] += "\uFFFD"
+ elif data == ">":
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "unexpected-end-of-doctype"})
+ self.currentToken["correct"] = False
+ self.tokenQueue.append(self.currentToken)
+ self.state = self.dataState
+ elif data is EOF:
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "eof-in-doctype"})
+ self.currentToken["correct"] = False
+ self.tokenQueue.append(self.currentToken)
+ self.state = self.dataState
+ else:
+ self.currentToken["systemId"] += data
+ return True
+
+ def doctypeSystemIdentifierSingleQuotedState(self):
+ data = self.stream.char()
+ if data == "'":
+ self.state = self.afterDoctypeSystemIdentifierState
+ elif data == "\u0000":
+ self.tokenQueue.append({"type": tokenTypes["ParseError"],
+ "data": "invalid-codepoint"})
+ self.currentToken["systemId"] += "\uFFFD"
+ elif data == ">":
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "unexpected-end-of-doctype"})
+ self.currentToken["correct"] = False
+ self.tokenQueue.append(self.currentToken)
+ self.state = self.dataState
+ elif data is EOF:
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "eof-in-doctype"})
+ self.currentToken["correct"] = False
+ self.tokenQueue.append(self.currentToken)
+ self.state = self.dataState
+ else:
+ self.currentToken["systemId"] += data
+ return True
+
+ def afterDoctypeSystemIdentifierState(self):
+ data = self.stream.char()
+ if data in spaceCharacters:
+ pass
+ elif data == ">":
+ self.tokenQueue.append(self.currentToken)
+ self.state = self.dataState
+ elif data is EOF:
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "eof-in-doctype"})
+ self.currentToken["correct"] = False
+ self.tokenQueue.append(self.currentToken)
+ self.state = self.dataState
+ else:
+ self.tokenQueue.append({"type": tokenTypes["ParseError"], "data":
+ "unexpected-char-in-doctype"})
+ self.state = self.bogusDoctypeState
+ return True
+
+ def bogusDoctypeState(self):
+ data = self.stream.char()
+ if data == ">":
+ self.tokenQueue.append(self.currentToken)
+ self.state = self.dataState
+ elif data is EOF:
+ # XXX EMIT
+ self.stream.unget(data)
+ self.tokenQueue.append(self.currentToken)
+ self.state = self.dataState
+ else:
+ pass
+ return True
+
+ def cdataSectionState(self):
+ data = []
+ while True:
+ data.append(self.stream.charsUntil("]"))
+ data.append(self.stream.charsUntil(">"))
+ char = self.stream.char()
+ if char == EOF:
+ break
+ else:
+ assert char == ">"
+ if data[-1][-2:] == "]]":
+ data[-1] = data[-1][:-2]
+ break
+ else:
+ data.append(char)
+
+ data = "".join(data)
+ # Deal with null here rather than in the parser
+ nullCount = data.count("\u0000")
+ if nullCount > 0:
+ for i in range(nullCount):
+ self.tokenQueue.append({"type": tokenTypes["ParseError"],
+ "data": "invalid-codepoint"})
+ data = data.replace("\u0000", "\uFFFD")
+ if data:
+ self.tokenQueue.append({"type": tokenTypes["Characters"],
+ "data": data})
+ self.state = self.dataState
+ return True
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/treeadapters/__init__.py b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/treeadapters/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/treeadapters/__init__.py
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/treeadapters/sax.py b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/treeadapters/sax.py
new file mode 100644
index 00000000000..ad47df95648
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/treeadapters/sax.py
@@ -0,0 +1,44 @@
+from __future__ import absolute_import, division, unicode_literals
+
+from xml.sax.xmlreader import AttributesNSImpl
+
+from ..constants import adjustForeignAttributes, unadjustForeignAttributes
+
+prefix_mapping = {}
+for prefix, localName, namespace in adjustForeignAttributes.values():
+ if prefix is not None:
+ prefix_mapping[prefix] = namespace
+
+
+def to_sax(walker, handler):
+ """Call SAX-like content handler based on treewalker walker"""
+ handler.startDocument()
+ for prefix, namespace in prefix_mapping.items():
+ handler.startPrefixMapping(prefix, namespace)
+
+ for token in walker:
+ type = token["type"]
+ if type == "Doctype":
+ continue
+ elif type in ("StartTag", "EmptyTag"):
+ attrs = AttributesNSImpl(token["data"],
+ unadjustForeignAttributes)
+ handler.startElementNS((token["namespace"], token["name"]),
+ token["name"],
+ attrs)
+ if type == "EmptyTag":
+ handler.endElementNS((token["namespace"], token["name"]),
+ token["name"])
+ elif type == "EndTag":
+ handler.endElementNS((token["namespace"], token["name"]),
+ token["name"])
+ elif type in ("Characters", "SpaceCharacters"):
+ handler.characters(token["data"])
+ elif type == "Comment":
+ pass
+ else:
+ assert False, "Unknown token type"
+
+ for prefix, namespace in prefix_mapping.items():
+ handler.endPrefixMapping(prefix)
+ handler.endDocument()
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/treebuilders/__init__.py b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/treebuilders/__init__.py
new file mode 100644
index 00000000000..6a6b2a4c45c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/treebuilders/__init__.py
@@ -0,0 +1,76 @@
+"""A collection of modules for building different kinds of tree from
+HTML documents.
+
+To create a treebuilder for a new type of tree, you need to do
+implement several things:
+
+1) A set of classes for various types of elements: Document, Doctype,
+Comment, Element. These must implement the interface of
+_base.treebuilders.Node (although comment nodes have a different
+signature for their constructor, see treebuilders.etree.Comment)
+Textual content may also be implemented as another node type, or not, as
+your tree implementation requires.
+
+2) A treebuilder object (called TreeBuilder by convention) that
+inherits from treebuilders._base.TreeBuilder. This has 4 required attributes:
+documentClass - the class to use for the bottommost node of a document
+elementClass - the class to use for HTML Elements
+commentClass - the class to use for comments
+doctypeClass - the class to use for doctypes
+It also has one required method:
+getDocument - Returns the root node of the complete document tree
+
+3) If you wish to run the unit tests, you must also create a
+testSerializer method on your treebuilder which accepts a node and
+returns a string containing Node and its children serialized according
+to the format used in the unittests
+"""
+
+from __future__ import absolute_import, division, unicode_literals
+
+from ..utils import default_etree
+
+treeBuilderCache = {}
+
+
+def getTreeBuilder(treeType, implementation=None, **kwargs):
+ """Get a TreeBuilder class for various types of tree with built-in support
+
+ treeType - the name of the tree type required (case-insensitive). Supported
+ values are:
+
+ "dom" - A generic builder for DOM implementations, defaulting to
+ a xml.dom.minidom based implementation.
+ "etree" - A generic builder for tree implementations exposing an
+ ElementTree-like interface, defaulting to
+ xml.etree.cElementTree if available and
+ xml.etree.ElementTree if not.
+ "lxml" - A etree-based builder for lxml.etree, handling
+ limitations of lxml's implementation.
+
+ implementation - (Currently applies to the "etree" and "dom" tree types). A
+ module implementing the tree type e.g.
+ xml.etree.ElementTree or xml.etree.cElementTree."""
+
+ treeType = treeType.lower()
+ if treeType not in treeBuilderCache:
+ if treeType == "dom":
+ from . import dom
+ # Come up with a sane default (pref. from the stdlib)
+ if implementation is None:
+ from xml.dom import minidom
+ implementation = minidom
+ # NEVER cache here, caching is done in the dom submodule
+ return dom.getDomModule(implementation, **kwargs).TreeBuilder
+ elif treeType == "lxml":
+ from . import etree_lxml
+ treeBuilderCache[treeType] = etree_lxml.TreeBuilder
+ elif treeType == "etree":
+ from . import etree
+ if implementation is None:
+ implementation = default_etree
+ # NEVER cache here, caching is done in the etree submodule
+ return etree.getETreeModule(implementation, **kwargs).TreeBuilder
+ else:
+ raise ValueError("""Unrecognised treebuilder "%s" """ % treeType)
+ return treeBuilderCache.get(treeType)
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/treebuilders/_base.py b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/treebuilders/_base.py
new file mode 100644
index 00000000000..8b97cc11a21
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/treebuilders/_base.py
@@ -0,0 +1,377 @@
+from __future__ import absolute_import, division, unicode_literals
+from six import text_type
+
+from ..constants import scopingElements, tableInsertModeElements, namespaces
+
+# The scope markers are inserted when entering object elements,
+# marquees, table cells, and table captions, and are used to prevent formatting
+# from "leaking" into tables, object elements, and marquees.
+Marker = None
+
+listElementsMap = {
+ None: (frozenset(scopingElements), False),
+ "button": (frozenset(scopingElements | set([(namespaces["html"], "button")])), False),
+ "list": (frozenset(scopingElements | set([(namespaces["html"], "ol"),
+ (namespaces["html"], "ul")])), False),
+ "table": (frozenset([(namespaces["html"], "html"),
+ (namespaces["html"], "table")]), False),
+ "select": (frozenset([(namespaces["html"], "optgroup"),
+ (namespaces["html"], "option")]), True)
+}
+
+
+class Node(object):
+ def __init__(self, name):
+ """Node representing an item in the tree.
+ name - The tag name associated with the node
+ parent - The parent of the current node (or None for the document node)
+ value - The value of the current node (applies to text nodes and
+ comments
+ attributes - a dict holding name, value pairs for attributes of the node
+ childNodes - a list of child nodes of the current node. This must
+ include all elements but not necessarily other node types
+ _flags - A list of miscellaneous flags that can be set on the node
+ """
+ self.name = name
+ self.parent = None
+ self.value = None
+ self.attributes = {}
+ self.childNodes = []
+ self._flags = []
+
+ def __str__(self):
+ attributesStr = " ".join(["%s=\"%s\"" % (name, value)
+ for name, value in
+ self.attributes.items()])
+ if attributesStr:
+ return "<%s %s>" % (self.name, attributesStr)
+ else:
+ return "<%s>" % (self.name)
+
+ def __repr__(self):
+ return "<%s>" % (self.name)
+
+ def appendChild(self, node):
+ """Insert node as a child of the current node
+ """
+ raise NotImplementedError
+
+ def insertText(self, data, insertBefore=None):
+ """Insert data as text in the current node, positioned before the
+ start of node insertBefore or to the end of the node's text.
+ """
+ raise NotImplementedError
+
+ def insertBefore(self, node, refNode):
+ """Insert node as a child of the current node, before refNode in the
+ list of child nodes. Raises ValueError if refNode is not a child of
+ the current node"""
+ raise NotImplementedError
+
+ def removeChild(self, node):
+ """Remove node from the children of the current node
+ """
+ raise NotImplementedError
+
+ def reparentChildren(self, newParent):
+ """Move all the children of the current node to newParent.
+ This is needed so that trees that don't store text as nodes move the
+ text in the correct way
+ """
+ # XXX - should this method be made more general?
+ for child in self.childNodes:
+ newParent.appendChild(child)
+ self.childNodes = []
+
+ def cloneNode(self):
+ """Return a shallow copy of the current node i.e. a node with the same
+ name and attributes but with no parent or child nodes
+ """
+ raise NotImplementedError
+
+ def hasContent(self):
+ """Return true if the node has children or text, false otherwise
+ """
+ raise NotImplementedError
+
+
+class ActiveFormattingElements(list):
+ def append(self, node):
+ equalCount = 0
+ if node != Marker:
+ for element in self[::-1]:
+ if element == Marker:
+ break
+ if self.nodesEqual(element, node):
+ equalCount += 1
+ if equalCount == 3:
+ self.remove(element)
+ break
+ list.append(self, node)
+
+ def nodesEqual(self, node1, node2):
+ if not node1.nameTuple == node2.nameTuple:
+ return False
+
+ if not node1.attributes == node2.attributes:
+ return False
+
+ return True
+
+
+class TreeBuilder(object):
+ """Base treebuilder implementation
+ documentClass - the class to use for the bottommost node of a document
+ elementClass - the class to use for HTML Elements
+ commentClass - the class to use for comments
+ doctypeClass - the class to use for doctypes
+ """
+
+ # Document class
+ documentClass = None
+
+ # The class to use for creating a node
+ elementClass = None
+
+ # The class to use for creating comments
+ commentClass = None
+
+ # The class to use for creating doctypes
+ doctypeClass = None
+
+ # Fragment class
+ fragmentClass = None
+
+ def __init__(self, namespaceHTMLElements):
+ if namespaceHTMLElements:
+ self.defaultNamespace = "http://www.w3.org/1999/xhtml"
+ else:
+ self.defaultNamespace = None
+ self.reset()
+
+ def reset(self):
+ self.openElements = []
+ self.activeFormattingElements = ActiveFormattingElements()
+
+ # XXX - rename these to headElement, formElement
+ self.headPointer = None
+ self.formPointer = None
+
+ self.insertFromTable = False
+
+ self.document = self.documentClass()
+
+ def elementInScope(self, target, variant=None):
+
+ # If we pass a node in we match that. if we pass a string
+ # match any node with that name
+ exactNode = hasattr(target, "nameTuple")
+
+ listElements, invert = listElementsMap[variant]
+
+ for node in reversed(self.openElements):
+ if (node.name == target and not exactNode or
+ node == target and exactNode):
+ return True
+ elif (invert ^ (node.nameTuple in listElements)):
+ return False
+
+ assert False # We should never reach this point
+
+ def reconstructActiveFormattingElements(self):
+ # Within this algorithm the order of steps described in the
+ # specification is not quite the same as the order of steps in the
+ # code. It should still do the same though.
+
+ # Step 1: stop the algorithm when there's nothing to do.
+ if not self.activeFormattingElements:
+ return
+
+ # Step 2 and step 3: we start with the last element. So i is -1.
+ i = len(self.activeFormattingElements) - 1
+ entry = self.activeFormattingElements[i]
+ if entry == Marker or entry in self.openElements:
+ return
+
+ # Step 6
+ while entry != Marker and entry not in self.openElements:
+ if i == 0:
+ # This will be reset to 0 below
+ i = -1
+ break
+ i -= 1
+ # Step 5: let entry be one earlier in the list.
+ entry = self.activeFormattingElements[i]
+
+ while True:
+ # Step 7
+ i += 1
+
+ # Step 8
+ entry = self.activeFormattingElements[i]
+ clone = entry.cloneNode() # Mainly to get a new copy of the attributes
+
+ # Step 9
+ element = self.insertElement({"type": "StartTag",
+ "name": clone.name,
+ "namespace": clone.namespace,
+ "data": clone.attributes})
+
+ # Step 10
+ self.activeFormattingElements[i] = element
+
+ # Step 11
+ if element == self.activeFormattingElements[-1]:
+ break
+
+ def clearActiveFormattingElements(self):
+ entry = self.activeFormattingElements.pop()
+ while self.activeFormattingElements and entry != Marker:
+ entry = self.activeFormattingElements.pop()
+
+ def elementInActiveFormattingElements(self, name):
+ """Check if an element exists between the end of the active
+ formatting elements and the last marker. If it does, return it, else
+ return false"""
+
+ for item in self.activeFormattingElements[::-1]:
+ # Check for Marker first because if it's a Marker it doesn't have a
+ # name attribute.
+ if item == Marker:
+ break
+ elif item.name == name:
+ return item
+ return False
+
+ def insertRoot(self, token):
+ element = self.createElement(token)
+ self.openElements.append(element)
+ self.document.appendChild(element)
+
+ def insertDoctype(self, token):
+ name = token["name"]
+ publicId = token["publicId"]
+ systemId = token["systemId"]
+
+ doctype = self.doctypeClass(name, publicId, systemId)
+ self.document.appendChild(doctype)
+
+ def insertComment(self, token, parent=None):
+ if parent is None:
+ parent = self.openElements[-1]
+ parent.appendChild(self.commentClass(token["data"]))
+
+ def createElement(self, token):
+ """Create an element but don't insert it anywhere"""
+ name = token["name"]
+ namespace = token.get("namespace", self.defaultNamespace)
+ element = self.elementClass(name, namespace)
+ element.attributes = token["data"]
+ return element
+
+ def _getInsertFromTable(self):
+ return self._insertFromTable
+
+ def _setInsertFromTable(self, value):
+ """Switch the function used to insert an element from the
+ normal one to the misnested table one and back again"""
+ self._insertFromTable = value
+ if value:
+ self.insertElement = self.insertElementTable
+ else:
+ self.insertElement = self.insertElementNormal
+
+ insertFromTable = property(_getInsertFromTable, _setInsertFromTable)
+
+ def insertElementNormal(self, token):
+ name = token["name"]
+ assert isinstance(name, text_type), "Element %s not unicode" % name
+ namespace = token.get("namespace", self.defaultNamespace)
+ element = self.elementClass(name, namespace)
+ element.attributes = token["data"]
+ self.openElements[-1].appendChild(element)
+ self.openElements.append(element)
+ return element
+
+ def insertElementTable(self, token):
+ """Create an element and insert it into the tree"""
+ element = self.createElement(token)
+ if self.openElements[-1].name not in tableInsertModeElements:
+ return self.insertElementNormal(token)
+ else:
+ # We should be in the InTable mode. This means we want to do
+ # special magic element rearranging
+ parent, insertBefore = self.getTableMisnestedNodePosition()
+ if insertBefore is None:
+ parent.appendChild(element)
+ else:
+ parent.insertBefore(element, insertBefore)
+ self.openElements.append(element)
+ return element
+
+ def insertText(self, data, parent=None):
+ """Insert text data."""
+ if parent is None:
+ parent = self.openElements[-1]
+
+ if (not self.insertFromTable or (self.insertFromTable and
+ self.openElements[-1].name
+ not in tableInsertModeElements)):
+ parent.insertText(data)
+ else:
+ # We should be in the InTable mode. This means we want to do
+ # special magic element rearranging
+ parent, insertBefore = self.getTableMisnestedNodePosition()
+ parent.insertText(data, insertBefore)
+
+ def getTableMisnestedNodePosition(self):
+ """Get the foster parent element, and sibling to insert before
+ (or None) when inserting a misnested table node"""
+ # The foster parent element is the one which comes before the most
+ # recently opened table element
+ # XXX - this is really inelegant
+ lastTable = None
+ fosterParent = None
+ insertBefore = None
+ for elm in self.openElements[::-1]:
+ if elm.name == "table":
+ lastTable = elm
+ break
+ if lastTable:
+ # XXX - we should really check that this parent is actually a
+ # node here
+ if lastTable.parent:
+ fosterParent = lastTable.parent
+ insertBefore = lastTable
+ else:
+ fosterParent = self.openElements[
+ self.openElements.index(lastTable) - 1]
+ else:
+ fosterParent = self.openElements[0]
+ return fosterParent, insertBefore
+
+ def generateImpliedEndTags(self, exclude=None):
+ name = self.openElements[-1].name
+ # XXX td, th and tr are not actually needed
+ if (name in frozenset(("dd", "dt", "li", "option", "optgroup", "p", "rp", "rt"))
+ and name != exclude):
+ self.openElements.pop()
+ # XXX This is not entirely what the specification says. We should
+ # investigate it more closely.
+ self.generateImpliedEndTags(exclude)
+
+ def getDocument(self):
+ "Return the final tree"
+ return self.document
+
+ def getFragment(self):
+ "Return the final fragment"
+ # assert self.innerHTML
+ fragment = self.fragmentClass()
+ self.openElements[0].reparentChildren(fragment)
+ return fragment
+
+ def testSerializer(self, node):
+ """Serialize the subtree of node in the format required by unit tests
+ node - the node from which to start serializing"""
+ raise NotImplementedError
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/treebuilders/dom.py b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/treebuilders/dom.py
new file mode 100644
index 00000000000..234233b7932
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/treebuilders/dom.py
@@ -0,0 +1,227 @@
+from __future__ import absolute_import, division, unicode_literals
+
+
+from xml.dom import minidom, Node
+import weakref
+
+from . import _base
+from .. import constants
+from ..constants import namespaces
+from ..utils import moduleFactoryFactory
+
+
+def getDomBuilder(DomImplementation):
+ Dom = DomImplementation
+
+ class AttrList(object):
+ def __init__(self, element):
+ self.element = element
+
+ def __iter__(self):
+ return list(self.element.attributes.items()).__iter__()
+
+ def __setitem__(self, name, value):
+ self.element.setAttribute(name, value)
+
+ def __len__(self):
+ return len(list(self.element.attributes.items()))
+
+ def items(self):
+ return [(item[0], item[1]) for item in
+ list(self.element.attributes.items())]
+
+ def keys(self):
+ return list(self.element.attributes.keys())
+
+ def __getitem__(self, name):
+ return self.element.getAttribute(name)
+
+ def __contains__(self, name):
+ if isinstance(name, tuple):
+ raise NotImplementedError
+ else:
+ return self.element.hasAttribute(name)
+
+ class NodeBuilder(_base.Node):
+ def __init__(self, element):
+ _base.Node.__init__(self, element.nodeName)
+ self.element = element
+
+ namespace = property(lambda self: hasattr(self.element, "namespaceURI")
+ and self.element.namespaceURI or None)
+
+ def appendChild(self, node):
+ node.parent = self
+ self.element.appendChild(node.element)
+
+ def insertText(self, data, insertBefore=None):
+ text = self.element.ownerDocument.createTextNode(data)
+ if insertBefore:
+ self.element.insertBefore(text, insertBefore.element)
+ else:
+ self.element.appendChild(text)
+
+ def insertBefore(self, node, refNode):
+ self.element.insertBefore(node.element, refNode.element)
+ node.parent = self
+
+ def removeChild(self, node):
+ if node.element.parentNode == self.element:
+ self.element.removeChild(node.element)
+ node.parent = None
+
+ def reparentChildren(self, newParent):
+ while self.element.hasChildNodes():
+ child = self.element.firstChild
+ self.element.removeChild(child)
+ newParent.element.appendChild(child)
+ self.childNodes = []
+
+ def getAttributes(self):
+ return AttrList(self.element)
+
+ def setAttributes(self, attributes):
+ if attributes:
+ for name, value in list(attributes.items()):
+ if isinstance(name, tuple):
+ if name[0] is not None:
+ qualifiedName = (name[0] + ":" + name[1])
+ else:
+ qualifiedName = name[1]
+ self.element.setAttributeNS(name[2], qualifiedName,
+ value)
+ else:
+ self.element.setAttribute(
+ name, value)
+ attributes = property(getAttributes, setAttributes)
+
+ def cloneNode(self):
+ return NodeBuilder(self.element.cloneNode(False))
+
+ def hasContent(self):
+ return self.element.hasChildNodes()
+
+ def getNameTuple(self):
+ if self.namespace is None:
+ return namespaces["html"], self.name
+ else:
+ return self.namespace, self.name
+
+ nameTuple = property(getNameTuple)
+
+ class TreeBuilder(_base.TreeBuilder):
+ def documentClass(self):
+ self.dom = Dom.getDOMImplementation().createDocument(None, None, None)
+ return weakref.proxy(self)
+
+ def insertDoctype(self, token):
+ name = token["name"]
+ publicId = token["publicId"]
+ systemId = token["systemId"]
+
+ domimpl = Dom.getDOMImplementation()
+ doctype = domimpl.createDocumentType(name, publicId, systemId)
+ self.document.appendChild(NodeBuilder(doctype))
+ if Dom == minidom:
+ doctype.ownerDocument = self.dom
+
+ def elementClass(self, name, namespace=None):
+ if namespace is None and self.defaultNamespace is None:
+ node = self.dom.createElement(name)
+ else:
+ node = self.dom.createElementNS(namespace, name)
+
+ return NodeBuilder(node)
+
+ def commentClass(self, data):
+ return NodeBuilder(self.dom.createComment(data))
+
+ def fragmentClass(self):
+ return NodeBuilder(self.dom.createDocumentFragment())
+
+ def appendChild(self, node):
+ self.dom.appendChild(node.element)
+
+ def testSerializer(self, element):
+ return testSerializer(element)
+
+ def getDocument(self):
+ return self.dom
+
+ def getFragment(self):
+ return _base.TreeBuilder.getFragment(self).element
+
+ def insertText(self, data, parent=None):
+ data = data
+ if parent != self:
+ _base.TreeBuilder.insertText(self, data, parent)
+ else:
+ # HACK: allow text nodes as children of the document node
+ if hasattr(self.dom, '_child_node_types'):
+ if Node.TEXT_NODE not in self.dom._child_node_types:
+ self.dom._child_node_types = list(self.dom._child_node_types)
+ self.dom._child_node_types.append(Node.TEXT_NODE)
+ self.dom.appendChild(self.dom.createTextNode(data))
+
+ implementation = DomImplementation
+ name = None
+
+ def testSerializer(element):
+ element.normalize()
+ rv = []
+
+ def serializeElement(element, indent=0):
+ if element.nodeType == Node.DOCUMENT_TYPE_NODE:
+ if element.name:
+ if element.publicId or element.systemId:
+ publicId = element.publicId or ""
+ systemId = element.systemId or ""
+ rv.append("""|%s<!DOCTYPE %s "%s" "%s">""" %
+ (' ' * indent, element.name, publicId, systemId))
+ else:
+ rv.append("|%s<!DOCTYPE %s>" % (' ' * indent, element.name))
+ else:
+ rv.append("|%s<!DOCTYPE >" % (' ' * indent,))
+ elif element.nodeType == Node.DOCUMENT_NODE:
+ rv.append("#document")
+ elif element.nodeType == Node.DOCUMENT_FRAGMENT_NODE:
+ rv.append("#document-fragment")
+ elif element.nodeType == Node.COMMENT_NODE:
+ rv.append("|%s<!-- %s -->" % (' ' * indent, element.nodeValue))
+ elif element.nodeType == Node.TEXT_NODE:
+ rv.append("|%s\"%s\"" % (' ' * indent, element.nodeValue))
+ else:
+ if (hasattr(element, "namespaceURI") and
+ element.namespaceURI is not None):
+ name = "%s %s" % (constants.prefixes[element.namespaceURI],
+ element.nodeName)
+ else:
+ name = element.nodeName
+ rv.append("|%s<%s>" % (' ' * indent, name))
+ if element.hasAttributes():
+ attributes = []
+ for i in range(len(element.attributes)):
+ attr = element.attributes.item(i)
+ name = attr.nodeName
+ value = attr.value
+ ns = attr.namespaceURI
+ if ns:
+ name = "%s %s" % (constants.prefixes[ns], attr.localName)
+ else:
+ name = attr.nodeName
+ attributes.append((name, value))
+
+ for name, value in sorted(attributes):
+ rv.append('|%s%s="%s"' % (' ' * (indent + 2), name, value))
+ indent += 2
+ for child in element.childNodes:
+ serializeElement(child, indent)
+ serializeElement(element, 0)
+
+ return "\n".join(rv)
+
+ return locals()
+
+
+# The actual means to get a module!
+getDomModule = moduleFactoryFactory(getDomBuilder)
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/treebuilders/etree.py b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/treebuilders/etree.py
new file mode 100644
index 00000000000..2c8ed19f8fe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/treebuilders/etree.py
@@ -0,0 +1,337 @@
+from __future__ import absolute_import, division, unicode_literals
+from six import text_type
+
+import re
+
+from . import _base
+from .. import ihatexml
+from .. import constants
+from ..constants import namespaces
+from ..utils import moduleFactoryFactory
+
+tag_regexp = re.compile("{([^}]*)}(.*)")
+
+
+def getETreeBuilder(ElementTreeImplementation, fullTree=False):
+ ElementTree = ElementTreeImplementation
+ ElementTreeCommentType = ElementTree.Comment("asd").tag
+
+ class Element(_base.Node):
+ def __init__(self, name, namespace=None):
+ self._name = name
+ self._namespace = namespace
+ self._element = ElementTree.Element(self._getETreeTag(name,
+ namespace))
+ if namespace is None:
+ self.nameTuple = namespaces["html"], self._name
+ else:
+ self.nameTuple = self._namespace, self._name
+ self.parent = None
+ self._childNodes = []
+ self._flags = []
+
+ def _getETreeTag(self, name, namespace):
+ if namespace is None:
+ etree_tag = name
+ else:
+ etree_tag = "{%s}%s" % (namespace, name)
+ return etree_tag
+
+ def _setName(self, name):
+ self._name = name
+ self._element.tag = self._getETreeTag(self._name, self._namespace)
+
+ def _getName(self):
+ return self._name
+
+ name = property(_getName, _setName)
+
+ def _setNamespace(self, namespace):
+ self._namespace = namespace
+ self._element.tag = self._getETreeTag(self._name, self._namespace)
+
+ def _getNamespace(self):
+ return self._namespace
+
+ namespace = property(_getNamespace, _setNamespace)
+
+ def _getAttributes(self):
+ return self._element.attrib
+
+ def _setAttributes(self, attributes):
+ # Delete existing attributes first
+ # XXX - there may be a better way to do this...
+ for key in list(self._element.attrib.keys()):
+ del self._element.attrib[key]
+ for key, value in attributes.items():
+ if isinstance(key, tuple):
+ name = "{%s}%s" % (key[2], key[1])
+ else:
+ name = key
+ self._element.set(name, value)
+
+ attributes = property(_getAttributes, _setAttributes)
+
+ def _getChildNodes(self):
+ return self._childNodes
+
+ def _setChildNodes(self, value):
+ del self._element[:]
+ self._childNodes = []
+ for element in value:
+ self.insertChild(element)
+
+ childNodes = property(_getChildNodes, _setChildNodes)
+
+ def hasContent(self):
+ """Return true if the node has children or text"""
+ return bool(self._element.text or len(self._element))
+
+ def appendChild(self, node):
+ self._childNodes.append(node)
+ self._element.append(node._element)
+ node.parent = self
+
+ def insertBefore(self, node, refNode):
+ index = list(self._element).index(refNode._element)
+ self._element.insert(index, node._element)
+ node.parent = self
+
+ def removeChild(self, node):
+ self._element.remove(node._element)
+ node.parent = None
+
+ def insertText(self, data, insertBefore=None):
+ if not(len(self._element)):
+ if not self._element.text:
+ self._element.text = ""
+ self._element.text += data
+ elif insertBefore is None:
+ # Insert the text as the tail of the last child element
+ if not self._element[-1].tail:
+ self._element[-1].tail = ""
+ self._element[-1].tail += data
+ else:
+ # Insert the text before the specified node
+ children = list(self._element)
+ index = children.index(insertBefore._element)
+ if index > 0:
+ if not self._element[index - 1].tail:
+ self._element[index - 1].tail = ""
+ self._element[index - 1].tail += data
+ else:
+ if not self._element.text:
+ self._element.text = ""
+ self._element.text += data
+
+ def cloneNode(self):
+ element = type(self)(self.name, self.namespace)
+ for name, value in self.attributes.items():
+ element.attributes[name] = value
+ return element
+
+ def reparentChildren(self, newParent):
+ if newParent.childNodes:
+ newParent.childNodes[-1]._element.tail += self._element.text
+ else:
+ if not newParent._element.text:
+ newParent._element.text = ""
+ if self._element.text is not None:
+ newParent._element.text += self._element.text
+ self._element.text = ""
+ _base.Node.reparentChildren(self, newParent)
+
+ class Comment(Element):
+ def __init__(self, data):
+ # Use the superclass constructor to set all properties on the
+ # wrapper element
+ self._element = ElementTree.Comment(data)
+ self.parent = None
+ self._childNodes = []
+ self._flags = []
+
+ def _getData(self):
+ return self._element.text
+
+ def _setData(self, value):
+ self._element.text = value
+
+ data = property(_getData, _setData)
+
+ class DocumentType(Element):
+ def __init__(self, name, publicId, systemId):
+ Element.__init__(self, "<!DOCTYPE>")
+ self._element.text = name
+ self.publicId = publicId
+ self.systemId = systemId
+
+ def _getPublicId(self):
+ return self._element.get("publicId", "")
+
+ def _setPublicId(self, value):
+ if value is not None:
+ self._element.set("publicId", value)
+
+ publicId = property(_getPublicId, _setPublicId)
+
+ def _getSystemId(self):
+ return self._element.get("systemId", "")
+
+ def _setSystemId(self, value):
+ if value is not None:
+ self._element.set("systemId", value)
+
+ systemId = property(_getSystemId, _setSystemId)
+
+ class Document(Element):
+ def __init__(self):
+ Element.__init__(self, "DOCUMENT_ROOT")
+
+ class DocumentFragment(Element):
+ def __init__(self):
+ Element.__init__(self, "DOCUMENT_FRAGMENT")
+
+ def testSerializer(element):
+ rv = []
+
+ def serializeElement(element, indent=0):
+ if not(hasattr(element, "tag")):
+ element = element.getroot()
+ if element.tag == "<!DOCTYPE>":
+ if element.get("publicId") or element.get("systemId"):
+ publicId = element.get("publicId") or ""
+ systemId = element.get("systemId") or ""
+ rv.append("""<!DOCTYPE %s "%s" "%s">""" %
+ (element.text, publicId, systemId))
+ else:
+ rv.append("<!DOCTYPE %s>" % (element.text,))
+ elif element.tag == "DOCUMENT_ROOT":
+ rv.append("#document")
+ if element.text is not None:
+ rv.append("|%s\"%s\"" % (' ' * (indent + 2), element.text))
+ if element.tail is not None:
+ raise TypeError("Document node cannot have tail")
+ if hasattr(element, "attrib") and len(element.attrib):
+ raise TypeError("Document node cannot have attributes")
+ elif element.tag == ElementTreeCommentType:
+ rv.append("|%s<!-- %s -->" % (' ' * indent, element.text))
+ else:
+ assert isinstance(element.tag, text_type), \
+ "Expected unicode, got %s, %s" % (type(element.tag), element.tag)
+ nsmatch = tag_regexp.match(element.tag)
+
+ if nsmatch is None:
+ name = element.tag
+ else:
+ ns, name = nsmatch.groups()
+ prefix = constants.prefixes[ns]
+ name = "%s %s" % (prefix, name)
+ rv.append("|%s<%s>" % (' ' * indent, name))
+
+ if hasattr(element, "attrib"):
+ attributes = []
+ for name, value in element.attrib.items():
+ nsmatch = tag_regexp.match(name)
+ if nsmatch is not None:
+ ns, name = nsmatch.groups()
+ prefix = constants.prefixes[ns]
+ attr_string = "%s %s" % (prefix, name)
+ else:
+ attr_string = name
+ attributes.append((attr_string, value))
+
+ for name, value in sorted(attributes):
+ rv.append('|%s%s="%s"' % (' ' * (indent + 2), name, value))
+ if element.text:
+ rv.append("|%s\"%s\"" % (' ' * (indent + 2), element.text))
+ indent += 2
+ for child in element:
+ serializeElement(child, indent)
+ if element.tail:
+ rv.append("|%s\"%s\"" % (' ' * (indent - 2), element.tail))
+ serializeElement(element, 0)
+
+ return "\n".join(rv)
+
+ def tostring(element):
+ """Serialize an element and its child nodes to a string"""
+ rv = []
+ filter = ihatexml.InfosetFilter()
+
+ def serializeElement(element):
+ if isinstance(element, ElementTree.ElementTree):
+ element = element.getroot()
+
+ if element.tag == "<!DOCTYPE>":
+ if element.get("publicId") or element.get("systemId"):
+ publicId = element.get("publicId") or ""
+ systemId = element.get("systemId") or ""
+ rv.append("""<!DOCTYPE %s PUBLIC "%s" "%s">""" %
+ (element.text, publicId, systemId))
+ else:
+ rv.append("<!DOCTYPE %s>" % (element.text,))
+ elif element.tag == "DOCUMENT_ROOT":
+ if element.text is not None:
+ rv.append(element.text)
+ if element.tail is not None:
+ raise TypeError("Document node cannot have tail")
+ if hasattr(element, "attrib") and len(element.attrib):
+ raise TypeError("Document node cannot have attributes")
+
+ for child in element:
+ serializeElement(child)
+
+ elif element.tag == ElementTreeCommentType:
+ rv.append("<!--%s-->" % (element.text,))
+ else:
+ # This is assumed to be an ordinary element
+ if not element.attrib:
+ rv.append("<%s>" % (filter.fromXmlName(element.tag),))
+ else:
+ attr = " ".join(["%s=\"%s\"" % (
+ filter.fromXmlName(name), value)
+ for name, value in element.attrib.items()])
+ rv.append("<%s %s>" % (element.tag, attr))
+ if element.text:
+ rv.append(element.text)
+
+ for child in element:
+ serializeElement(child)
+
+ rv.append("</%s>" % (element.tag,))
+
+ if element.tail:
+ rv.append(element.tail)
+
+ serializeElement(element)
+
+ return "".join(rv)
+
+ class TreeBuilder(_base.TreeBuilder):
+ documentClass = Document
+ doctypeClass = DocumentType
+ elementClass = Element
+ commentClass = Comment
+ fragmentClass = DocumentFragment
+ implementation = ElementTreeImplementation
+
+ def testSerializer(self, element):
+ return testSerializer(element)
+
+ def getDocument(self):
+ if fullTree:
+ return self.document._element
+ else:
+ if self.defaultNamespace is not None:
+ return self.document._element.find(
+ "{%s}html" % self.defaultNamespace)
+ else:
+ return self.document._element.find("html")
+
+ def getFragment(self):
+ return _base.TreeBuilder.getFragment(self)._element
+
+ return locals()
+
+
+getETreeModule = moduleFactoryFactory(getETreeBuilder)
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/treebuilders/etree_lxml.py b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/treebuilders/etree_lxml.py
new file mode 100644
index 00000000000..35d08efaa61
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/treebuilders/etree_lxml.py
@@ -0,0 +1,369 @@
+"""Module for supporting the lxml.etree library. The idea here is to use as much
+of the native library as possible, without using fragile hacks like custom element
+names that break between releases. The downside of this is that we cannot represent
+all possible trees; specifically the following are known to cause problems:
+
+Text or comments as siblings of the root element
+Docypes with no name
+
+When any of these things occur, we emit a DataLossWarning
+"""
+
+from __future__ import absolute_import, division, unicode_literals
+
+import warnings
+import re
+import sys
+
+from . import _base
+from ..constants import DataLossWarning
+from .. import constants
+from . import etree as etree_builders
+from .. import ihatexml
+
+import lxml.etree as etree
+
+
+fullTree = True
+tag_regexp = re.compile("{([^}]*)}(.*)")
+
+comment_type = etree.Comment("asd").tag
+
+
+class DocumentType(object):
+ def __init__(self, name, publicId, systemId):
+ self.name = name
+ self.publicId = publicId
+ self.systemId = systemId
+
+
+class Document(object):
+ def __init__(self):
+ self._elementTree = None
+ self._childNodes = []
+
+ def appendChild(self, element):
+ self._elementTree.getroot().addnext(element._element)
+
+ def _getChildNodes(self):
+ return self._childNodes
+
+ childNodes = property(_getChildNodes)
+
+
+def testSerializer(element):
+ rv = []
+ finalText = None
+ infosetFilter = ihatexml.InfosetFilter()
+
+ def serializeElement(element, indent=0):
+ if not hasattr(element, "tag"):
+ if hasattr(element, "getroot"):
+ # Full tree case
+ rv.append("#document")
+ if element.docinfo.internalDTD:
+ if not (element.docinfo.public_id or
+ element.docinfo.system_url):
+ dtd_str = "<!DOCTYPE %s>" % element.docinfo.root_name
+ else:
+ dtd_str = """<!DOCTYPE %s "%s" "%s">""" % (
+ element.docinfo.root_name,
+ element.docinfo.public_id,
+ element.docinfo.system_url)
+ rv.append("|%s%s" % (' ' * (indent + 2), dtd_str))
+ next_element = element.getroot()
+ while next_element.getprevious() is not None:
+ next_element = next_element.getprevious()
+ while next_element is not None:
+ serializeElement(next_element, indent + 2)
+ next_element = next_element.getnext()
+ elif isinstance(element, str) or isinstance(element, bytes):
+ # Text in a fragment
+ assert isinstance(element, str) or sys.version_info.major == 2
+ rv.append("|%s\"%s\"" % (' ' * indent, element))
+ else:
+ # Fragment case
+ rv.append("#document-fragment")
+ for next_element in element:
+ serializeElement(next_element, indent + 2)
+ elif element.tag == comment_type:
+ rv.append("|%s<!-- %s -->" % (' ' * indent, element.text))
+ if hasattr(element, "tail") and element.tail:
+ rv.append("|%s\"%s\"" % (' ' * indent, element.tail))
+ else:
+ assert isinstance(element, etree._Element)
+ nsmatch = etree_builders.tag_regexp.match(element.tag)
+ if nsmatch is not None:
+ ns = nsmatch.group(1)
+ tag = nsmatch.group(2)
+ prefix = constants.prefixes[ns]
+ rv.append("|%s<%s %s>" % (' ' * indent, prefix,
+ infosetFilter.fromXmlName(tag)))
+ else:
+ rv.append("|%s<%s>" % (' ' * indent,
+ infosetFilter.fromXmlName(element.tag)))
+
+ if hasattr(element, "attrib"):
+ attributes = []
+ for name, value in element.attrib.items():
+ nsmatch = tag_regexp.match(name)
+ if nsmatch is not None:
+ ns, name = nsmatch.groups()
+ name = infosetFilter.fromXmlName(name)
+ prefix = constants.prefixes[ns]
+ attr_string = "%s %s" % (prefix, name)
+ else:
+ attr_string = infosetFilter.fromXmlName(name)
+ attributes.append((attr_string, value))
+
+ for name, value in sorted(attributes):
+ rv.append('|%s%s="%s"' % (' ' * (indent + 2), name, value))
+
+ if element.text:
+ rv.append("|%s\"%s\"" % (' ' * (indent + 2), element.text))
+ indent += 2
+ for child in element:
+ serializeElement(child, indent)
+ if hasattr(element, "tail") and element.tail:
+ rv.append("|%s\"%s\"" % (' ' * (indent - 2), element.tail))
+ serializeElement(element, 0)
+
+ if finalText is not None:
+ rv.append("|%s\"%s\"" % (' ' * 2, finalText))
+
+ return "\n".join(rv)
+
+
+def tostring(element):
+ """Serialize an element and its child nodes to a string"""
+ rv = []
+ finalText = None
+
+ def serializeElement(element):
+ if not hasattr(element, "tag"):
+ if element.docinfo.internalDTD:
+ if element.docinfo.doctype:
+ dtd_str = element.docinfo.doctype
+ else:
+ dtd_str = "<!DOCTYPE %s>" % element.docinfo.root_name
+ rv.append(dtd_str)
+ serializeElement(element.getroot())
+
+ elif element.tag == comment_type:
+ rv.append("<!--%s-->" % (element.text,))
+
+ else:
+ # This is assumed to be an ordinary element
+ if not element.attrib:
+ rv.append("<%s>" % (element.tag,))
+ else:
+ attr = " ".join(["%s=\"%s\"" % (name, value)
+ for name, value in element.attrib.items()])
+ rv.append("<%s %s>" % (element.tag, attr))
+ if element.text:
+ rv.append(element.text)
+
+ for child in element:
+ serializeElement(child)
+
+ rv.append("</%s>" % (element.tag,))
+
+ if hasattr(element, "tail") and element.tail:
+ rv.append(element.tail)
+
+ serializeElement(element)
+
+ if finalText is not None:
+ rv.append("%s\"" % (' ' * 2, finalText))
+
+ return "".join(rv)
+
+
+class TreeBuilder(_base.TreeBuilder):
+ documentClass = Document
+ doctypeClass = DocumentType
+ elementClass = None
+ commentClass = None
+ fragmentClass = Document
+ implementation = etree
+
+ def __init__(self, namespaceHTMLElements, fullTree=False):
+ builder = etree_builders.getETreeModule(etree, fullTree=fullTree)
+ infosetFilter = self.infosetFilter = ihatexml.InfosetFilter()
+ self.namespaceHTMLElements = namespaceHTMLElements
+
+ class Attributes(dict):
+ def __init__(self, element, value={}):
+ self._element = element
+ dict.__init__(self, value)
+ for key, value in self.items():
+ if isinstance(key, tuple):
+ name = "{%s}%s" % (key[2], infosetFilter.coerceAttribute(key[1]))
+ else:
+ name = infosetFilter.coerceAttribute(key)
+ self._element._element.attrib[name] = value
+
+ def __setitem__(self, key, value):
+ dict.__setitem__(self, key, value)
+ if isinstance(key, tuple):
+ name = "{%s}%s" % (key[2], infosetFilter.coerceAttribute(key[1]))
+ else:
+ name = infosetFilter.coerceAttribute(key)
+ self._element._element.attrib[name] = value
+
+ class Element(builder.Element):
+ def __init__(self, name, namespace):
+ name = infosetFilter.coerceElement(name)
+ builder.Element.__init__(self, name, namespace=namespace)
+ self._attributes = Attributes(self)
+
+ def _setName(self, name):
+ self._name = infosetFilter.coerceElement(name)
+ self._element.tag = self._getETreeTag(
+ self._name, self._namespace)
+
+ def _getName(self):
+ return infosetFilter.fromXmlName(self._name)
+
+ name = property(_getName, _setName)
+
+ def _getAttributes(self):
+ return self._attributes
+
+ def _setAttributes(self, attributes):
+ self._attributes = Attributes(self, attributes)
+
+ attributes = property(_getAttributes, _setAttributes)
+
+ def insertText(self, data, insertBefore=None):
+ data = infosetFilter.coerceCharacters(data)
+ builder.Element.insertText(self, data, insertBefore)
+
+ def appendChild(self, child):
+ builder.Element.appendChild(self, child)
+
+ class Comment(builder.Comment):
+ def __init__(self, data):
+ data = infosetFilter.coerceComment(data)
+ builder.Comment.__init__(self, data)
+
+ def _setData(self, data):
+ data = infosetFilter.coerceComment(data)
+ self._element.text = data
+
+ def _getData(self):
+ return self._element.text
+
+ data = property(_getData, _setData)
+
+ self.elementClass = Element
+ self.commentClass = builder.Comment
+ # self.fragmentClass = builder.DocumentFragment
+ _base.TreeBuilder.__init__(self, namespaceHTMLElements)
+
+ def reset(self):
+ _base.TreeBuilder.reset(self)
+ self.insertComment = self.insertCommentInitial
+ self.initial_comments = []
+ self.doctype = None
+
+ def testSerializer(self, element):
+ return testSerializer(element)
+
+ def getDocument(self):
+ if fullTree:
+ return self.document._elementTree
+ else:
+ return self.document._elementTree.getroot()
+
+ def getFragment(self):
+ fragment = []
+ element = self.openElements[0]._element
+ if element.text:
+ fragment.append(element.text)
+ fragment.extend(list(element))
+ if element.tail:
+ fragment.append(element.tail)
+ return fragment
+
+ def insertDoctype(self, token):
+ name = token["name"]
+ publicId = token["publicId"]
+ systemId = token["systemId"]
+
+ if not name:
+ warnings.warn("lxml cannot represent empty doctype", DataLossWarning)
+ self.doctype = None
+ else:
+ coercedName = self.infosetFilter.coerceElement(name)
+ if coercedName != name:
+ warnings.warn("lxml cannot represent non-xml doctype", DataLossWarning)
+
+ doctype = self.doctypeClass(coercedName, publicId, systemId)
+ self.doctype = doctype
+
+ def insertCommentInitial(self, data, parent=None):
+ self.initial_comments.append(data)
+
+ def insertCommentMain(self, data, parent=None):
+ if (parent == self.document and
+ self.document._elementTree.getroot()[-1].tag == comment_type):
+ warnings.warn("lxml cannot represent adjacent comments beyond the root elements", DataLossWarning)
+ super(TreeBuilder, self).insertComment(data, parent)
+
+ def insertRoot(self, token):
+ """Create the document root"""
+ # Because of the way libxml2 works, it doesn't seem to be possible to
+ # alter information like the doctype after the tree has been parsed.
+ # Therefore we need to use the built-in parser to create our iniial
+ # tree, after which we can add elements like normal
+ docStr = ""
+ if self.doctype:
+ assert self.doctype.name
+ docStr += "<!DOCTYPE %s" % self.doctype.name
+ if (self.doctype.publicId is not None or
+ self.doctype.systemId is not None):
+ docStr += (' PUBLIC "%s" ' %
+ (self.infosetFilter.coercePubid(self.doctype.publicId or "")))
+ if self.doctype.systemId:
+ sysid = self.doctype.systemId
+ if sysid.find("'") >= 0 and sysid.find('"') >= 0:
+ warnings.warn("DOCTYPE system cannot contain single and double quotes", DataLossWarning)
+ sysid = sysid.replace("'", 'U00027')
+ if sysid.find("'") >= 0:
+ docStr += '"%s"' % sysid
+ else:
+ docStr += "'%s'" % sysid
+ else:
+ docStr += "''"
+ docStr += ">"
+ if self.doctype.name != token["name"]:
+ warnings.warn("lxml cannot represent doctype with a different name to the root element", DataLossWarning)
+ docStr += "<THIS_SHOULD_NEVER_APPEAR_PUBLICLY/>"
+ root = etree.fromstring(docStr)
+
+ # Append the initial comments:
+ for comment_token in self.initial_comments:
+ root.addprevious(etree.Comment(comment_token["data"]))
+
+ # Create the root document and add the ElementTree to it
+ self.document = self.documentClass()
+ self.document._elementTree = root.getroottree()
+
+ # Give the root element the right name
+ name = token["name"]
+ namespace = token.get("namespace", self.defaultNamespace)
+ if namespace is None:
+ etree_tag = name
+ else:
+ etree_tag = "{%s}%s" % (namespace, name)
+ root.tag = etree_tag
+
+ # Add the root element to the internal child/open data structures
+ root_element = self.elementClass(name, namespace)
+ root_element._element = root
+ self.document._childNodes.append(root_element)
+ self.openElements.append(root_element)
+
+ # Reset to the default insert comment function
+ self.insertComment = self.insertCommentMain
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/treewalkers/__init__.py b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/treewalkers/__init__.py
new file mode 100644
index 00000000000..18124e75f3b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/treewalkers/__init__.py
@@ -0,0 +1,57 @@
+"""A collection of modules for iterating through different kinds of
+tree, generating tokens identical to those produced by the tokenizer
+module.
+
+To create a tree walker for a new type of tree, you need to do
+implement a tree walker object (called TreeWalker by convention) that
+implements a 'serialize' method taking a tree as sole argument and
+returning an iterator generating tokens.
+"""
+
+from __future__ import absolute_import, division, unicode_literals
+
+import sys
+
+from ..utils import default_etree
+
+treeWalkerCache = {}
+
+
+def getTreeWalker(treeType, implementation=None, **kwargs):
+ """Get a TreeWalker class for various types of tree with built-in support
+
+ treeType - the name of the tree type required (case-insensitive). Supported
+ values are:
+
+ "dom" - The xml.dom.minidom DOM implementation
+ "pulldom" - The xml.dom.pulldom event stream
+ "etree" - A generic walker for tree implementations exposing an
+ elementtree-like interface (known to work with
+ ElementTree, cElementTree and lxml.etree).
+ "lxml" - Optimized walker for lxml.etree
+ "genshi" - a Genshi stream
+
+ implementation - (Currently applies to the "etree" tree type only). A module
+ implementing the tree type e.g. xml.etree.ElementTree or
+ cElementTree."""
+
+ treeType = treeType.lower()
+ if treeType not in treeWalkerCache:
+ if treeType in ("dom", "pulldom"):
+ name = "%s.%s" % (__name__, treeType)
+ __import__(name)
+ mod = sys.modules[name]
+ treeWalkerCache[treeType] = mod.TreeWalker
+ elif treeType == "genshi":
+ from . import genshistream
+ treeWalkerCache[treeType] = genshistream.TreeWalker
+ elif treeType == "lxml":
+ from . import lxmletree
+ treeWalkerCache[treeType] = lxmletree.TreeWalker
+ elif treeType == "etree":
+ from . import etree
+ if implementation is None:
+ implementation = default_etree
+ # XXX: NEVER cache here, caching is done in the etree submodule
+ return etree.getETreeModule(implementation, **kwargs).TreeWalker
+ return treeWalkerCache.get(treeType)
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/treewalkers/_base.py b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/treewalkers/_base.py
new file mode 100644
index 00000000000..34252e50c0e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/treewalkers/_base.py
@@ -0,0 +1,200 @@
+from __future__ import absolute_import, division, unicode_literals
+from six import text_type, string_types
+
+import gettext
+_ = gettext.gettext
+
+from xml.dom import Node
+
+DOCUMENT = Node.DOCUMENT_NODE
+DOCTYPE = Node.DOCUMENT_TYPE_NODE
+TEXT = Node.TEXT_NODE
+ELEMENT = Node.ELEMENT_NODE
+COMMENT = Node.COMMENT_NODE
+ENTITY = Node.ENTITY_NODE
+UNKNOWN = "<#UNKNOWN#>"
+
+from ..constants import voidElements, spaceCharacters
+spaceCharacters = "".join(spaceCharacters)
+
+
+def to_text(s, blank_if_none=True):
+ """Wrapper around six.text_type to convert None to empty string"""
+ if s is None:
+ if blank_if_none:
+ return ""
+ else:
+ return None
+ elif isinstance(s, text_type):
+ return s
+ else:
+ return text_type(s)
+
+
+def is_text_or_none(string):
+ """Wrapper around isinstance(string_types) or is None"""
+ return string is None or isinstance(string, string_types)
+
+
+class TreeWalker(object):
+ def __init__(self, tree):
+ self.tree = tree
+
+ def __iter__(self):
+ raise NotImplementedError
+
+ def error(self, msg):
+ return {"type": "SerializeError", "data": msg}
+
+ def emptyTag(self, namespace, name, attrs, hasChildren=False):
+ assert namespace is None or isinstance(namespace, string_types), type(namespace)
+ assert isinstance(name, string_types), type(name)
+ assert all((namespace is None or isinstance(namespace, string_types)) and
+ isinstance(name, string_types) and
+ isinstance(value, string_types)
+ for (namespace, name), value in attrs.items())
+
+ yield {"type": "EmptyTag", "name": to_text(name, False),
+ "namespace": to_text(namespace),
+ "data": attrs}
+ if hasChildren:
+ yield self.error(_("Void element has children"))
+
+ def startTag(self, namespace, name, attrs):
+ assert namespace is None or isinstance(namespace, string_types), type(namespace)
+ assert isinstance(name, string_types), type(name)
+ assert all((namespace is None or isinstance(namespace, string_types)) and
+ isinstance(name, string_types) and
+ isinstance(value, string_types)
+ for (namespace, name), value in attrs.items())
+
+ return {"type": "StartTag",
+ "name": text_type(name),
+ "namespace": to_text(namespace),
+ "data": dict(((to_text(namespace, False), to_text(name)),
+ to_text(value, False))
+ for (namespace, name), value in attrs.items())}
+
+ def endTag(self, namespace, name):
+ assert namespace is None or isinstance(namespace, string_types), type(namespace)
+ assert isinstance(name, string_types), type(namespace)
+
+ return {"type": "EndTag",
+ "name": to_text(name, False),
+ "namespace": to_text(namespace),
+ "data": {}}
+
+ def text(self, data):
+ assert isinstance(data, string_types), type(data)
+
+ data = to_text(data)
+ middle = data.lstrip(spaceCharacters)
+ left = data[:len(data) - len(middle)]
+ if left:
+ yield {"type": "SpaceCharacters", "data": left}
+ data = middle
+ middle = data.rstrip(spaceCharacters)
+ right = data[len(middle):]
+ if middle:
+ yield {"type": "Characters", "data": middle}
+ if right:
+ yield {"type": "SpaceCharacters", "data": right}
+
+ def comment(self, data):
+ assert isinstance(data, string_types), type(data)
+
+ return {"type": "Comment", "data": text_type(data)}
+
+ def doctype(self, name, publicId=None, systemId=None, correct=True):
+ assert is_text_or_none(name), type(name)
+ assert is_text_or_none(publicId), type(publicId)
+ assert is_text_or_none(systemId), type(systemId)
+
+ return {"type": "Doctype",
+ "name": to_text(name),
+ "publicId": to_text(publicId),
+ "systemId": to_text(systemId),
+ "correct": to_text(correct)}
+
+ def entity(self, name):
+ assert isinstance(name, string_types), type(name)
+
+ return {"type": "Entity", "name": text_type(name)}
+
+ def unknown(self, nodeType):
+ return self.error(_("Unknown node type: ") + nodeType)
+
+
+class NonRecursiveTreeWalker(TreeWalker):
+ def getNodeDetails(self, node):
+ raise NotImplementedError
+
+ def getFirstChild(self, node):
+ raise NotImplementedError
+
+ def getNextSibling(self, node):
+ raise NotImplementedError
+
+ def getParentNode(self, node):
+ raise NotImplementedError
+
+ def __iter__(self):
+ currentNode = self.tree
+ while currentNode is not None:
+ details = self.getNodeDetails(currentNode)
+ type, details = details[0], details[1:]
+ hasChildren = False
+
+ if type == DOCTYPE:
+ yield self.doctype(*details)
+
+ elif type == TEXT:
+ for token in self.text(*details):
+ yield token
+
+ elif type == ELEMENT:
+ namespace, name, attributes, hasChildren = details
+ if name in voidElements:
+ for token in self.emptyTag(namespace, name, attributes,
+ hasChildren):
+ yield token
+ hasChildren = False
+ else:
+ yield self.startTag(namespace, name, attributes)
+
+ elif type == COMMENT:
+ yield self.comment(details[0])
+
+ elif type == ENTITY:
+ yield self.entity(details[0])
+
+ elif type == DOCUMENT:
+ hasChildren = True
+
+ else:
+ yield self.unknown(details[0])
+
+ if hasChildren:
+ firstChild = self.getFirstChild(currentNode)
+ else:
+ firstChild = None
+
+ if firstChild is not None:
+ currentNode = firstChild
+ else:
+ while currentNode is not None:
+ details = self.getNodeDetails(currentNode)
+ type, details = details[0], details[1:]
+ if type == ELEMENT:
+ namespace, name, attributes, hasChildren = details
+ if name not in voidElements:
+ yield self.endTag(namespace, name)
+ if self.tree is currentNode:
+ currentNode = None
+ break
+ nextSibling = self.getNextSibling(currentNode)
+ if nextSibling is not None:
+ currentNode = nextSibling
+ break
+ else:
+ currentNode = self.getParentNode(currentNode)
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/treewalkers/dom.py b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/treewalkers/dom.py
new file mode 100644
index 00000000000..a01287a9448
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/treewalkers/dom.py
@@ -0,0 +1,46 @@
+from __future__ import absolute_import, division, unicode_literals
+
+from xml.dom import Node
+
+import gettext
+_ = gettext.gettext
+
+from . import _base
+
+
+class TreeWalker(_base.NonRecursiveTreeWalker):
+ def getNodeDetails(self, node):
+ if node.nodeType == Node.DOCUMENT_TYPE_NODE:
+ return _base.DOCTYPE, node.name, node.publicId, node.systemId
+
+ elif node.nodeType in (Node.TEXT_NODE, Node.CDATA_SECTION_NODE):
+ return _base.TEXT, node.nodeValue
+
+ elif node.nodeType == Node.ELEMENT_NODE:
+ attrs = {}
+ for attr in list(node.attributes.keys()):
+ attr = node.getAttributeNode(attr)
+ if attr.namespaceURI:
+ attrs[(attr.namespaceURI, attr.localName)] = attr.value
+ else:
+ attrs[(None, attr.name)] = attr.value
+ return (_base.ELEMENT, node.namespaceURI, node.nodeName,
+ attrs, node.hasChildNodes())
+
+ elif node.nodeType == Node.COMMENT_NODE:
+ return _base.COMMENT, node.nodeValue
+
+ elif node.nodeType in (Node.DOCUMENT_NODE, Node.DOCUMENT_FRAGMENT_NODE):
+ return (_base.DOCUMENT,)
+
+ else:
+ return _base.UNKNOWN, node.nodeType
+
+ def getFirstChild(self, node):
+ return node.firstChild
+
+ def getNextSibling(self, node):
+ return node.nextSibling
+
+ def getParentNode(self, node):
+ return node.parentNode
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/treewalkers/etree.py b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/treewalkers/etree.py
new file mode 100644
index 00000000000..fd8a9cc9b52
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/treewalkers/etree.py
@@ -0,0 +1,138 @@
+from __future__ import absolute_import, division, unicode_literals
+
+try:
+ from collections import OrderedDict
+except ImportError:
+ try:
+ from ordereddict import OrderedDict
+ except ImportError:
+ OrderedDict = dict
+import gettext
+_ = gettext.gettext
+
+import re
+
+from six import text_type
+
+from . import _base
+from ..utils import moduleFactoryFactory
+
+tag_regexp = re.compile("{([^}]*)}(.*)")
+
+
+def getETreeBuilder(ElementTreeImplementation):
+ ElementTree = ElementTreeImplementation
+ ElementTreeCommentType = ElementTree.Comment("asd").tag
+
+ class TreeWalker(_base.NonRecursiveTreeWalker):
+ """Given the particular ElementTree representation, this implementation,
+ to avoid using recursion, returns "nodes" as tuples with the following
+ content:
+
+ 1. The current element
+
+ 2. The index of the element relative to its parent
+
+ 3. A stack of ancestor elements
+
+ 4. A flag "text", "tail" or None to indicate if the current node is a
+ text node; either the text or tail of the current element (1)
+ """
+ def getNodeDetails(self, node):
+ if isinstance(node, tuple): # It might be the root Element
+ elt, key, parents, flag = node
+ if flag in ("text", "tail"):
+ return _base.TEXT, getattr(elt, flag)
+ else:
+ node = elt
+
+ if not(hasattr(node, "tag")):
+ node = node.getroot()
+
+ if node.tag in ("DOCUMENT_ROOT", "DOCUMENT_FRAGMENT"):
+ return (_base.DOCUMENT,)
+
+ elif node.tag == "<!DOCTYPE>":
+ return (_base.DOCTYPE, node.text,
+ node.get("publicId"), node.get("systemId"))
+
+ elif node.tag == ElementTreeCommentType:
+ return _base.COMMENT, node.text
+
+ else:
+ assert type(node.tag) == text_type, type(node.tag)
+ # This is assumed to be an ordinary element
+ match = tag_regexp.match(node.tag)
+ if match:
+ namespace, tag = match.groups()
+ else:
+ namespace = None
+ tag = node.tag
+ attrs = OrderedDict()
+ for name, value in list(node.attrib.items()):
+ match = tag_regexp.match(name)
+ if match:
+ attrs[(match.group(1), match.group(2))] = value
+ else:
+ attrs[(None, name)] = value
+ return (_base.ELEMENT, namespace, tag,
+ attrs, len(node) or node.text)
+
+ def getFirstChild(self, node):
+ if isinstance(node, tuple):
+ element, key, parents, flag = node
+ else:
+ element, key, parents, flag = node, None, [], None
+
+ if flag in ("text", "tail"):
+ return None
+ else:
+ if element.text:
+ return element, key, parents, "text"
+ elif len(element):
+ parents.append(element)
+ return element[0], 0, parents, None
+ else:
+ return None
+
+ def getNextSibling(self, node):
+ if isinstance(node, tuple):
+ element, key, parents, flag = node
+ else:
+ return None
+
+ if flag == "text":
+ if len(element):
+ parents.append(element)
+ return element[0], 0, parents, None
+ else:
+ return None
+ else:
+ if element.tail and flag != "tail":
+ return element, key, parents, "tail"
+ elif key < len(parents[-1]) - 1:
+ return parents[-1][key + 1], key + 1, parents, None
+ else:
+ return None
+
+ def getParentNode(self, node):
+ if isinstance(node, tuple):
+ element, key, parents, flag = node
+ else:
+ return None
+
+ if flag == "text":
+ if not parents:
+ return element
+ else:
+ return element, key, parents, None
+ else:
+ parent = parents.pop()
+ if not parents:
+ return parent
+ else:
+ return parent, list(parents[-1]).index(parent), parents, None
+
+ return locals()
+
+getETreeModule = moduleFactoryFactory(getETreeBuilder)
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/treewalkers/genshistream.py b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/treewalkers/genshistream.py
new file mode 100644
index 00000000000..f559c45d044
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/treewalkers/genshistream.py
@@ -0,0 +1,69 @@
+from __future__ import absolute_import, division, unicode_literals
+
+from genshi.core import QName
+from genshi.core import START, END, XML_NAMESPACE, DOCTYPE, TEXT
+from genshi.core import START_NS, END_NS, START_CDATA, END_CDATA, PI, COMMENT
+
+from . import _base
+
+from ..constants import voidElements, namespaces
+
+
+class TreeWalker(_base.TreeWalker):
+ def __iter__(self):
+ # Buffer the events so we can pass in the following one
+ previous = None
+ for event in self.tree:
+ if previous is not None:
+ for token in self.tokens(previous, event):
+ yield token
+ previous = event
+
+ # Don't forget the final event!
+ if previous is not None:
+ for token in self.tokens(previous, None):
+ yield token
+
+ def tokens(self, event, next):
+ kind, data, pos = event
+ if kind == START:
+ tag, attribs = data
+ name = tag.localname
+ namespace = tag.namespace
+ converted_attribs = {}
+ for k, v in attribs:
+ if isinstance(k, QName):
+ converted_attribs[(k.namespace, k.localname)] = v
+ else:
+ converted_attribs[(None, k)] = v
+
+ if namespace == namespaces["html"] and name in voidElements:
+ for token in self.emptyTag(namespace, name, converted_attribs,
+ not next or next[0] != END
+ or next[1] != tag):
+ yield token
+ else:
+ yield self.startTag(namespace, name, converted_attribs)
+
+ elif kind == END:
+ name = data.localname
+ namespace = data.namespace
+ if name not in voidElements:
+ yield self.endTag(namespace, name)
+
+ elif kind == COMMENT:
+ yield self.comment(data)
+
+ elif kind == TEXT:
+ for token in self.text(data):
+ yield token
+
+ elif kind == DOCTYPE:
+ yield self.doctype(*data)
+
+ elif kind in (XML_NAMESPACE, DOCTYPE, START_NS, END_NS,
+ START_CDATA, END_CDATA, PI):
+ pass
+
+ else:
+ yield self.unknown(kind)
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/treewalkers/lxmletree.py b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/treewalkers/lxmletree.py
new file mode 100644
index 00000000000..bc934ac05a9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/treewalkers/lxmletree.py
@@ -0,0 +1,204 @@
+from __future__ import absolute_import, division, unicode_literals
+from six import text_type
+
+from lxml import etree
+from ..treebuilders.etree import tag_regexp
+
+from gettext import gettext
+_ = gettext
+
+from . import _base
+
+from .. import ihatexml
+
+
+def ensure_str(s):
+ if s is None:
+ return None
+ elif isinstance(s, text_type):
+ return s
+ else:
+ return s.decode("utf-8", "strict")
+
+
+class Root(object):
+ def __init__(self, et):
+ self.elementtree = et
+ self.children = []
+ if et.docinfo.internalDTD:
+ self.children.append(Doctype(self,
+ ensure_str(et.docinfo.root_name),
+ ensure_str(et.docinfo.public_id),
+ ensure_str(et.docinfo.system_url)))
+ root = et.getroot()
+ node = root
+
+ while node.getprevious() is not None:
+ node = node.getprevious()
+ while node is not None:
+ self.children.append(node)
+ node = node.getnext()
+
+ self.text = None
+ self.tail = None
+
+ def __getitem__(self, key):
+ return self.children[key]
+
+ def getnext(self):
+ return None
+
+ def __len__(self):
+ return 1
+
+
+class Doctype(object):
+ def __init__(self, root_node, name, public_id, system_id):
+ self.root_node = root_node
+ self.name = name
+ self.public_id = public_id
+ self.system_id = system_id
+
+ self.text = None
+ self.tail = None
+
+ def getnext(self):
+ return self.root_node.children[1]
+
+
+class FragmentRoot(Root):
+ def __init__(self, children):
+ self.children = [FragmentWrapper(self, child) for child in children]
+ self.text = self.tail = None
+
+ def getnext(self):
+ return None
+
+
+class FragmentWrapper(object):
+ def __init__(self, fragment_root, obj):
+ self.root_node = fragment_root
+ self.obj = obj
+ if hasattr(self.obj, 'text'):
+ self.text = ensure_str(self.obj.text)
+ else:
+ self.text = None
+ if hasattr(self.obj, 'tail'):
+ self.tail = ensure_str(self.obj.tail)
+ else:
+ self.tail = None
+
+ def __getattr__(self, name):
+ return getattr(self.obj, name)
+
+ def getnext(self):
+ siblings = self.root_node.children
+ idx = siblings.index(self)
+ if idx < len(siblings) - 1:
+ return siblings[idx + 1]
+ else:
+ return None
+
+ def __getitem__(self, key):
+ return self.obj[key]
+
+ def __bool__(self):
+ return bool(self.obj)
+
+ def getparent(self):
+ return None
+
+ def __str__(self):
+ return str(self.obj)
+
+ def __unicode__(self):
+ return str(self.obj)
+
+ def __len__(self):
+ return len(self.obj)
+
+
+class TreeWalker(_base.NonRecursiveTreeWalker):
+ def __init__(self, tree):
+ if hasattr(tree, "getroot"):
+ tree = Root(tree)
+ elif isinstance(tree, list):
+ tree = FragmentRoot(tree)
+ _base.NonRecursiveTreeWalker.__init__(self, tree)
+ self.filter = ihatexml.InfosetFilter()
+
+ def getNodeDetails(self, node):
+ if isinstance(node, tuple): # Text node
+ node, key = node
+ assert key in ("text", "tail"), _("Text nodes are text or tail, found %s") % key
+ return _base.TEXT, ensure_str(getattr(node, key))
+
+ elif isinstance(node, Root):
+ return (_base.DOCUMENT,)
+
+ elif isinstance(node, Doctype):
+ return _base.DOCTYPE, node.name, node.public_id, node.system_id
+
+ elif isinstance(node, FragmentWrapper) and not hasattr(node, "tag"):
+ return _base.TEXT, node.obj
+
+ elif node.tag == etree.Comment:
+ return _base.COMMENT, ensure_str(node.text)
+
+ elif node.tag == etree.Entity:
+ return _base.ENTITY, ensure_str(node.text)[1:-1] # strip &;
+
+ else:
+ # This is assumed to be an ordinary element
+ match = tag_regexp.match(ensure_str(node.tag))
+ if match:
+ namespace, tag = match.groups()
+ else:
+ namespace = None
+ tag = ensure_str(node.tag)
+ attrs = {}
+ for name, value in list(node.attrib.items()):
+ name = ensure_str(name)
+ value = ensure_str(value)
+ match = tag_regexp.match(name)
+ if match:
+ attrs[(match.group(1), match.group(2))] = value
+ else:
+ attrs[(None, name)] = value
+ return (_base.ELEMENT, namespace, self.filter.fromXmlName(tag),
+ attrs, len(node) > 0 or node.text)
+
+ def getFirstChild(self, node):
+ assert not isinstance(node, tuple), _("Text nodes have no children")
+
+ assert len(node) or node.text, "Node has no children"
+ if node.text:
+ return (node, "text")
+ else:
+ return node[0]
+
+ def getNextSibling(self, node):
+ if isinstance(node, tuple): # Text node
+ node, key = node
+ assert key in ("text", "tail"), _("Text nodes are text or tail, found %s") % key
+ if key == "text":
+ # XXX: we cannot use a "bool(node) and node[0] or None" construct here
+ # because node[0] might evaluate to False if it has no child element
+ if len(node):
+ return node[0]
+ else:
+ return None
+ else: # tail
+ return node.getnext()
+
+ return (node, "tail") if node.tail else node.getnext()
+
+ def getParentNode(self, node):
+ if isinstance(node, tuple): # Text node
+ node, key = node
+ assert key in ("text", "tail"), _("Text nodes are text or tail, found %s") % key
+ if key == "text":
+ return node
+ # else: fallback to "normal" processing
+
+ return node.getparent()
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/treewalkers/pulldom.py b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/treewalkers/pulldom.py
new file mode 100644
index 00000000000..0b0f515fec7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/treewalkers/pulldom.py
@@ -0,0 +1,63 @@
+from __future__ import absolute_import, division, unicode_literals
+
+from xml.dom.pulldom import START_ELEMENT, END_ELEMENT, \
+ COMMENT, IGNORABLE_WHITESPACE, CHARACTERS
+
+from . import _base
+
+from ..constants import voidElements
+
+
+class TreeWalker(_base.TreeWalker):
+ def __iter__(self):
+ ignore_until = None
+ previous = None
+ for event in self.tree:
+ if previous is not None and \
+ (ignore_until is None or previous[1] is ignore_until):
+ if previous[1] is ignore_until:
+ ignore_until = None
+ for token in self.tokens(previous, event):
+ yield token
+ if token["type"] == "EmptyTag":
+ ignore_until = previous[1]
+ previous = event
+ if ignore_until is None or previous[1] is ignore_until:
+ for token in self.tokens(previous, None):
+ yield token
+ elif ignore_until is not None:
+ raise ValueError("Illformed DOM event stream: void element without END_ELEMENT")
+
+ def tokens(self, event, next):
+ type, node = event
+ if type == START_ELEMENT:
+ name = node.nodeName
+ namespace = node.namespaceURI
+ attrs = {}
+ for attr in list(node.attributes.keys()):
+ attr = node.getAttributeNode(attr)
+ attrs[(attr.namespaceURI, attr.localName)] = attr.value
+ if name in voidElements:
+ for token in self.emptyTag(namespace,
+ name,
+ attrs,
+ not next or next[1] is not node):
+ yield token
+ else:
+ yield self.startTag(namespace, name, attrs)
+
+ elif type == END_ELEMENT:
+ name = node.nodeName
+ namespace = node.namespaceURI
+ if name not in voidElements:
+ yield self.endTag(namespace, name)
+
+ elif type == COMMENT:
+ yield self.comment(node.nodeValue)
+
+ elif type in (IGNORABLE_WHITESPACE, CHARACTERS):
+ for token in self.text(node.nodeValue):
+ yield token
+
+ else:
+ yield self.unknown(type)
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/trie/__init__.py b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/trie/__init__.py
new file mode 100644
index 00000000000..a8cca8a9acf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/trie/__init__.py
@@ -0,0 +1,12 @@
+from __future__ import absolute_import, division, unicode_literals
+
+from .py import Trie as PyTrie
+
+Trie = PyTrie
+
+try:
+ from .datrie import Trie as DATrie
+except ImportError:
+ pass
+else:
+ Trie = DATrie
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/trie/_base.py b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/trie/_base.py
new file mode 100644
index 00000000000..724486b16eb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/trie/_base.py
@@ -0,0 +1,37 @@
+from __future__ import absolute_import, division, unicode_literals
+
+from collections import Mapping
+
+
+class Trie(Mapping):
+ """Abstract base class for tries"""
+
+ def keys(self, prefix=None):
+ keys = super().keys()
+
+ if prefix is None:
+ return set(keys)
+
+ # Python 2.6: no set comprehensions
+ return set([x for x in keys if x.startswith(prefix)])
+
+ def has_keys_with_prefix(self, prefix):
+ for key in self.keys():
+ if key.startswith(prefix):
+ return True
+
+ return False
+
+ def longest_prefix(self, prefix):
+ if prefix in self:
+ return prefix
+
+ for i in range(1, len(prefix) + 1):
+ if prefix[:-i] in self:
+ return prefix[:-i]
+
+ raise KeyError(prefix)
+
+ def longest_prefix_item(self, prefix):
+ lprefix = self.longest_prefix(prefix)
+ return (lprefix, self[lprefix])
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/trie/datrie.py b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/trie/datrie.py
new file mode 100644
index 00000000000..51f3d046a74
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/trie/datrie.py
@@ -0,0 +1,44 @@
+from __future__ import absolute_import, division, unicode_literals
+
+from datrie import Trie as DATrie
+from six import text_type
+
+from ._base import Trie as ABCTrie
+
+
+class Trie(ABCTrie):
+ def __init__(self, data):
+ chars = set()
+ for key in data.keys():
+ if not isinstance(key, text_type):
+ raise TypeError("All keys must be strings")
+ for char in key:
+ chars.add(char)
+
+ self._data = DATrie("".join(chars))
+ for key, value in data.items():
+ self._data[key] = value
+
+ def __contains__(self, key):
+ return key in self._data
+
+ def __len__(self):
+ return len(self._data)
+
+ def __iter__(self):
+ raise NotImplementedError()
+
+ def __getitem__(self, key):
+ return self._data[key]
+
+ def keys(self, prefix=None):
+ return self._data.keys(prefix)
+
+ def has_keys_with_prefix(self, prefix):
+ return self._data.has_keys_with_prefix(prefix)
+
+ def longest_prefix(self, prefix):
+ return self._data.longest_prefix(prefix)
+
+ def longest_prefix_item(self, prefix):
+ return self._data.longest_prefix_item(prefix)
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/trie/py.py b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/trie/py.py
new file mode 100644
index 00000000000..c2ba3da7576
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/trie/py.py
@@ -0,0 +1,67 @@
+from __future__ import absolute_import, division, unicode_literals
+from six import text_type
+
+from bisect import bisect_left
+
+from ._base import Trie as ABCTrie
+
+
+class Trie(ABCTrie):
+ def __init__(self, data):
+ if not all(isinstance(x, text_type) for x in data.keys()):
+ raise TypeError("All keys must be strings")
+
+ self._data = data
+ self._keys = sorted(data.keys())
+ self._cachestr = ""
+ self._cachepoints = (0, len(data))
+
+ def __contains__(self, key):
+ return key in self._data
+
+ def __len__(self):
+ return len(self._data)
+
+ def __iter__(self):
+ return iter(self._data)
+
+ def __getitem__(self, key):
+ return self._data[key]
+
+ def keys(self, prefix=None):
+ if prefix is None or prefix == "" or not self._keys:
+ return set(self._keys)
+
+ if prefix.startswith(self._cachestr):
+ lo, hi = self._cachepoints
+ start = i = bisect_left(self._keys, prefix, lo, hi)
+ else:
+ start = i = bisect_left(self._keys, prefix)
+
+ keys = set()
+ if start == len(self._keys):
+ return keys
+
+ while self._keys[i].startswith(prefix):
+ keys.add(self._keys[i])
+ i += 1
+
+ self._cachestr = prefix
+ self._cachepoints = (start, i)
+
+ return keys
+
+ def has_keys_with_prefix(self, prefix):
+ if prefix in self._data:
+ return True
+
+ if prefix.startswith(self._cachestr):
+ lo, hi = self._cachepoints
+ i = bisect_left(self._keys, prefix, lo, hi)
+ else:
+ i = bisect_left(self._keys, prefix)
+
+ if i == len(self._keys):
+ return False
+
+ return self._keys[i].startswith(prefix)
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/html5lib/utils.py b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/utils.py
new file mode 100644
index 00000000000..2f41f4dfa60
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/html5lib/utils.py
@@ -0,0 +1,82 @@
+from __future__ import absolute_import, division, unicode_literals
+
+from types import ModuleType
+
+try:
+ import xml.etree.cElementTree as default_etree
+except ImportError:
+ import xml.etree.ElementTree as default_etree
+
+
+__all__ = ["default_etree", "MethodDispatcher", "isSurrogatePair",
+ "surrogatePairToCodepoint", "moduleFactoryFactory"]
+
+
+class MethodDispatcher(dict):
+ """Dict with 2 special properties:
+
+ On initiation, keys that are lists, sets or tuples are converted to
+ multiple keys so accessing any one of the items in the original
+ list-like object returns the matching value
+
+ md = MethodDispatcher({("foo", "bar"):"baz"})
+ md["foo"] == "baz"
+
+ A default value which can be set through the default attribute.
+ """
+
+ def __init__(self, items=()):
+ # Using _dictEntries instead of directly assigning to self is about
+ # twice as fast. Please do careful performance testing before changing
+ # anything here.
+ _dictEntries = []
+ for name, value in items:
+ if type(name) in (list, tuple, frozenset, set):
+ for item in name:
+ _dictEntries.append((item, value))
+ else:
+ _dictEntries.append((name, value))
+ dict.__init__(self, _dictEntries)
+ self.default = None
+
+ def __getitem__(self, key):
+ return dict.get(self, key, self.default)
+
+
+# Some utility functions to dal with weirdness around UCS2 vs UCS4
+# python builds
+
+def isSurrogatePair(data):
+ return (len(data) == 2 and
+ ord(data[0]) >= 0xD800 and ord(data[0]) <= 0xDBFF and
+ ord(data[1]) >= 0xDC00 and ord(data[1]) <= 0xDFFF)
+
+
+def surrogatePairToCodepoint(data):
+ char_val = (0x10000 + (ord(data[0]) - 0xD800) * 0x400 +
+ (ord(data[1]) - 0xDC00))
+ return char_val
+
+# Module Factory Factory (no, this isn't Java, I know)
+# Here to stop this being duplicated all over the place.
+
+
+def moduleFactoryFactory(factory):
+ moduleCache = {}
+
+ def moduleFactory(baseModule, *args, **kwargs):
+ if isinstance(ModuleType.__name__, type("")):
+ name = "_%s_factory" % baseModule.__name__
+ else:
+ name = b"_%s_factory" % baseModule.__name__
+
+ if name in moduleCache:
+ return moduleCache[name]
+ else:
+ mod = ModuleType(name)
+ objs = factory(baseModule, *args, **kwargs)
+ mod.__dict__.update(objs)
+ moduleCache[name] = mod
+ return mod
+
+ return moduleFactory
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/parse.py b/tests/wpt/web-platform-tests/tools/html5lib/parse.py
new file mode 100755
index 00000000000..9cbf3b8d1cc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/parse.py
@@ -0,0 +1,233 @@
+#!/usr/bin/env python
+"""usage: %prog [options] filename
+
+Parse a document to a tree, with optional profiling
+"""
+
+import sys
+import os
+import traceback
+from optparse import OptionParser
+
+from html5lib import html5parser, sanitizer
+from html5lib.tokenizer import HTMLTokenizer
+from html5lib import treebuilders, serializer, treewalkers
+from html5lib import constants
+
+def parse():
+ optParser = getOptParser()
+ opts,args = optParser.parse_args()
+ encoding = "utf8"
+
+ try:
+ f = args[-1]
+ # Try opening from the internet
+ if f.startswith('http://'):
+ try:
+ import urllib.request, urllib.parse, urllib.error, cgi
+ f = urllib.request.urlopen(f)
+ contentType = f.headers.get('content-type')
+ if contentType:
+ (mediaType, params) = cgi.parse_header(contentType)
+ encoding = params.get('charset')
+ except:
+ pass
+ elif f == '-':
+ f = sys.stdin
+ if sys.version_info[0] >= 3:
+ encoding = None
+ else:
+ try:
+ # Try opening from file system
+ f = open(f, "rb")
+ except IOError as e:
+ sys.stderr.write("Unable to open file: %s\n" % e)
+ sys.exit(1)
+ except IndexError:
+ sys.stderr.write("No filename provided. Use -h for help\n")
+ sys.exit(1)
+
+ treebuilder = treebuilders.getTreeBuilder(opts.treebuilder)
+
+ if opts.sanitize:
+ tokenizer = sanitizer.HTMLSanitizer
+ else:
+ tokenizer = HTMLTokenizer
+
+ p = html5parser.HTMLParser(tree=treebuilder, tokenizer=tokenizer, debug=opts.log)
+
+ if opts.fragment:
+ parseMethod = p.parseFragment
+ else:
+ parseMethod = p.parse
+
+ if opts.profile:
+ import cProfile
+ import pstats
+ cProfile.runctx("run(parseMethod, f, encoding)", None,
+ {"run": run,
+ "parseMethod": parseMethod,
+ "f": f,
+ "encoding": encoding},
+ "stats.prof")
+ # XXX - We should use a temp file here
+ stats = pstats.Stats('stats.prof')
+ stats.strip_dirs()
+ stats.sort_stats('time')
+ stats.print_stats()
+ elif opts.time:
+ import time
+ t0 = time.time()
+ document = run(parseMethod, f, encoding)
+ t1 = time.time()
+ if document:
+ printOutput(p, document, opts)
+ t2 = time.time()
+ sys.stderr.write("\n\nRun took: %fs (plus %fs to print the output)"%(t1-t0, t2-t1))
+ else:
+ sys.stderr.write("\n\nRun took: %fs"%(t1-t0))
+ else:
+ document = run(parseMethod, f, encoding)
+ if document:
+ printOutput(p, document, opts)
+
+def run(parseMethod, f, encoding):
+ try:
+ document = parseMethod(f, encoding=encoding)
+ except:
+ document = None
+ traceback.print_exc()
+ return document
+
+def printOutput(parser, document, opts):
+ if opts.encoding:
+ print("Encoding:", parser.tokenizer.stream.charEncoding)
+
+ for item in parser.log:
+ print(item)
+
+ if document is not None:
+ if opts.xml:
+ sys.stdout.write(document.toxml("utf-8"))
+ elif opts.tree:
+ if not hasattr(document,'__getitem__'):
+ document = [document]
+ for fragment in document:
+ print(parser.tree.testSerializer(fragment))
+ elif opts.hilite:
+ sys.stdout.write(document.hilite("utf-8"))
+ elif opts.html:
+ kwargs = {}
+ for opt in serializer.HTMLSerializer.options:
+ try:
+ kwargs[opt] = getattr(opts,opt)
+ except:
+ pass
+ if not kwargs['quote_char']:
+ del kwargs['quote_char']
+
+ tokens = treewalkers.getTreeWalker(opts.treebuilder)(document)
+ if sys.version_info[0] >= 3:
+ encoding = None
+ else:
+ encoding = "utf-8"
+ for text in serializer.HTMLSerializer(**kwargs).serialize(tokens, encoding=encoding):
+ sys.stdout.write(text)
+ if not text.endswith('\n'): sys.stdout.write('\n')
+ if opts.error:
+ errList=[]
+ for pos, errorcode, datavars in parser.errors:
+ errList.append("Line %i Col %i"%pos + " " + constants.E.get(errorcode, 'Unknown error "%s"' % errorcode) % datavars)
+ sys.stdout.write("\nParse errors:\n" + "\n".join(errList)+"\n")
+
+def getOptParser():
+ parser = OptionParser(usage=__doc__)
+
+ parser.add_option("-p", "--profile", action="store_true", default=False,
+ dest="profile", help="Use the hotshot profiler to "
+ "produce a detailed log of the run")
+
+ parser.add_option("-t", "--time",
+ action="store_true", default=False, dest="time",
+ help="Time the run using time.time (may not be accurate on all platforms, especially for short runs)")
+
+ parser.add_option("-b", "--treebuilder", action="store", type="string",
+ dest="treebuilder", default="simpleTree")
+
+ parser.add_option("-e", "--error", action="store_true", default=False,
+ dest="error", help="Print a list of parse errors")
+
+ parser.add_option("-f", "--fragment", action="store_true", default=False,
+ dest="fragment", help="Parse as a fragment")
+
+ parser.add_option("", "--tree", action="store_true", default=False,
+ dest="tree", help="Output as debug tree")
+
+ parser.add_option("-x", "--xml", action="store_true", default=False,
+ dest="xml", help="Output as xml")
+
+ parser.add_option("", "--no-html", action="store_false", default=True,
+ dest="html", help="Don't output html")
+
+ parser.add_option("", "--hilite", action="store_true", default=False,
+ dest="hilite", help="Output as formatted highlighted code.")
+
+ parser.add_option("-c", "--encoding", action="store_true", default=False,
+ dest="encoding", help="Print character encoding used")
+
+ parser.add_option("", "--inject-meta-charset", action="store_true",
+ default=False, dest="inject_meta_charset",
+ help="inject <meta charset>")
+
+ parser.add_option("", "--strip-whitespace", action="store_true",
+ default=False, dest="strip_whitespace",
+ help="strip whitespace")
+
+ parser.add_option("", "--omit-optional-tags", action="store_true",
+ default=False, dest="omit_optional_tags",
+ help="omit optional tags")
+
+ parser.add_option("", "--quote-attr-values", action="store_true",
+ default=False, dest="quote_attr_values",
+ help="quote attribute values")
+
+ parser.add_option("", "--use-best-quote-char", action="store_true",
+ default=False, dest="use_best_quote_char",
+ help="use best quote character")
+
+ parser.add_option("", "--quote-char", action="store",
+ default=None, dest="quote_char",
+ help="quote character")
+
+ parser.add_option("", "--no-minimize-boolean-attributes",
+ action="store_false", default=True,
+ dest="minimize_boolean_attributes",
+ help="minimize boolean attributes")
+
+ parser.add_option("", "--use-trailing-solidus", action="store_true",
+ default=False, dest="use_trailing_solidus",
+ help="use trailing solidus")
+
+ parser.add_option("", "--space-before-trailing-solidus",
+ action="store_true", default=False,
+ dest="space_before_trailing_solidus",
+ help="add space before trailing solidus")
+
+ parser.add_option("", "--escape-lt-in-attrs", action="store_true",
+ default=False, dest="escape_lt_in_attrs",
+ help="escape less than signs in attribute values")
+
+ parser.add_option("", "--escape-rcdata", action="store_true",
+ default=False, dest="escape_rcdata",
+ help="escape rcdata element values")
+
+ parser.add_option("", "--sanitize", action="store_true", default=False,
+ dest="sanitize", help="sanitize")
+
+ parser.add_option("-l", "--log", action="store_true", default=False,
+ dest="log", help="log state transitions")
+
+ return parser
+
+if __name__ == "__main__":
+ parse()
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/requirements-install.sh b/tests/wpt/web-platform-tests/tools/html5lib/requirements-install.sh
new file mode 100755
index 00000000000..5f8ba50645f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/requirements-install.sh
@@ -0,0 +1,16 @@
+#!/bin/bash -e
+
+if [[ $USE_OPTIONAL != "true" && $USE_OPTIONAL != "false" ]]; then
+ echo "fatal: \$USE_OPTIONAL not set to true or false. Exiting."
+ exit 1
+fi
+
+pip install -r requirements-test.txt
+
+if [[ $USE_OPTIONAL == "true" && $TRAVIS_PYTHON_VERSION != "pypy" ]]; then
+ if [[ $TRAVIS_PYTHON_VERSION == "2.6" ]]; then
+ pip install --allow-external Genshi --allow-insecure Genshi -r requirements-optional-2.6.txt
+ else
+ pip install --allow-external Genshi --allow-insecure Genshi -r requirements-optional-cpython.txt
+ fi
+fi
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/requirements-optional-2.6.txt b/tests/wpt/web-platform-tests/tools/html5lib/requirements-optional-2.6.txt
new file mode 100644
index 00000000000..37557ac403d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/requirements-optional-2.6.txt
@@ -0,0 +1,5 @@
+-r requirements-optional-cpython.txt
+
+# Can be used to force attributes to be serialized in alphabetical
+# order.
+ordereddict
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/requirements-optional-cpython.txt b/tests/wpt/web-platform-tests/tools/html5lib/requirements-optional-cpython.txt
new file mode 100644
index 00000000000..35ed3529c2c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/requirements-optional-cpython.txt
@@ -0,0 +1,5 @@
+-r requirements-optional.txt
+
+# lxml is supported with its own treebuilder ("lxml") and otherwise
+# uses the standard ElementTree support
+lxml
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/requirements-optional.txt b/tests/wpt/web-platform-tests/tools/html5lib/requirements-optional.txt
new file mode 100644
index 00000000000..c6355270127
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/requirements-optional.txt
@@ -0,0 +1,13 @@
+-r requirements.txt
+
+# We support a Genshi treewalker that can be used to serialize Genshi
+# streams.
+genshi
+
+# DATrie can be used in place of our Python trie implementation for
+# slightly better parsing performance.
+datrie
+
+# charade can be used as a fallback in case we are unable to determine
+# the encoding of a document.
+charade
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/requirements-test.txt b/tests/wpt/web-platform-tests/tools/html5lib/requirements-test.txt
new file mode 100644
index 00000000000..d5f8088c1c1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/requirements-test.txt
@@ -0,0 +1,5 @@
+-r requirements.txt
+
+flake8
+nose
+ordereddict # Python 2.6
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/requirements.txt b/tests/wpt/web-platform-tests/tools/html5lib/requirements.txt
new file mode 100644
index 00000000000..ffe2fce4989
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/requirements.txt
@@ -0,0 +1 @@
+six
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/setup.py b/tests/wpt/web-platform-tests/tools/html5lib/setup.py
new file mode 100644
index 00000000000..f75910eaf21
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/setup.py
@@ -0,0 +1,44 @@
+from distutils.core import setup
+import os
+import codecs
+
+classifiers=[
+ 'Development Status :: 5 - Production/Stable',
+ 'Intended Audience :: Developers',
+ 'License :: OSI Approved :: MIT License',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python',
+ 'Programming Language :: Python :: 2',
+ 'Programming Language :: Python :: 2.6',
+ 'Programming Language :: Python :: 2.7',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.2',
+ 'Programming Language :: Python :: 3.3',
+ 'Topic :: Software Development :: Libraries :: Python Modules',
+ 'Topic :: Text Processing :: Markup :: HTML'
+ ]
+
+packages = ['html5lib'] + ['html5lib.'+name
+ for name in os.listdir(os.path.join('html5lib'))
+ if os.path.isdir(os.path.join('html5lib', name)) and
+ not name.startswith('.') and name != 'tests']
+
+current_dir = os.path.dirname(__file__)
+with codecs.open(os.path.join(current_dir, 'README.rst'), 'r', 'utf8') as readme_file:
+ with codecs.open(os.path.join(current_dir, 'CHANGES.rst'), 'r', 'utf8') as changes_file:
+ long_description = readme_file.read() + '\n' + changes_file.read()
+
+setup(name='html5lib',
+ version='0.9999-dev',
+ url='https://github.com/html5lib/html5lib-python',
+ license="MIT License",
+ description='HTML parser based on the WHATWG HTML specifcation',
+ long_description=long_description,
+ classifiers=classifiers,
+ maintainer='James Graham',
+ maintainer_email='james@hoppipolla.co.uk',
+ packages=packages,
+ install_requires=[
+ 'six',
+ ],
+ )
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/tox.ini b/tests/wpt/web-platform-tests/tools/html5lib/tox.ini
new file mode 100644
index 00000000000..479f9e1f732
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/tox.ini
@@ -0,0 +1,30 @@
+[tox]
+envlist = py26,py27,py32,py33,py34,pypy
+
+[testenv]
+deps =
+ -r{toxinidir}/requirements-optional-cpython.txt
+ flake8
+ nose
+commands =
+ {envbindir}/nosetests -q
+ {toxinidir}/flake8-run.sh
+install_command =
+ pip install {opts} {packages}
+
+[testenv:pypy]
+# lxml doesn't work and datrie doesn't make sense
+# (it's slower than the pure-python version)
+deps =
+ charade
+ flake8
+ Genshi
+ nose
+ six
+
+[testenv:py26]
+basepython = python2.6
+deps =
+ -r{toxinidir}/requirements-optional-2.6.txt
+ flake8
+ nose
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/utils/entities.py b/tests/wpt/web-platform-tests/tools/html5lib/utils/entities.py
new file mode 100644
index 00000000000..116a27cbc9b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/utils/entities.py
@@ -0,0 +1,88 @@
+import json
+
+import html5lib
+
+def parse(path="html5ents.xml"):
+ return html5lib.parse(open(path), treebuilder="lxml")
+
+def entity_table(tree):
+ return dict((entity_name("".join(tr[0].xpath(".//text()"))),
+ entity_characters(tr[1].text))
+ for tr in tree.xpath("//h:tbody/h:tr",
+ namespaces={"h":"http://www.w3.org/1999/xhtml"}))
+
+def entity_name(inp):
+ return inp.strip()
+
+def entity_characters(inp):
+ return "".join(codepoint_to_character(item)
+ for item in inp.split()
+ if item)
+
+def codepoint_to_character(inp):
+ return ("\U000"+inp[2:]).decode("unicode-escape")
+
+def make_tests_json(entities):
+ test_list = make_test_list(entities)
+ tests_json = {"tests":
+ [make_test(*item) for item in test_list]
+ }
+ return tests_json
+
+def make_test(name, characters, good):
+ return {
+ "description":test_description(name, good),
+ "input":"&%s"%name,
+ "output":test_expected(name, characters, good)
+ }
+
+def test_description(name, good):
+ with_semicolon = name.endswith(";")
+ semicolon_text = {True:"with a semi-colon",
+ False:"without a semi-colon"}[with_semicolon]
+ if good:
+ text = "Named entity: %s %s"%(name, semicolon_text)
+ else:
+ text = "Bad named entity: %s %s"%(name, semicolon_text)
+ return text
+
+def test_expected(name, characters, good):
+ rv = []
+ if not good or not name.endswith(";"):
+ rv.append("ParseError")
+ rv.append(["Character", characters])
+ return rv
+
+def make_test_list(entities):
+ tests = []
+ for entity_name, characters in entities.items():
+ if entity_name.endswith(";") and not subentity_exists(entity_name, entities):
+ tests.append((entity_name[:-1], "&" + entity_name[:-1], False))
+ tests.append((entity_name, characters, True))
+ return sorted(tests)
+
+def subentity_exists(entity_name, entities):
+ for i in range(1, len(entity_name)):
+ if entity_name[:-i] in entities:
+ return True
+ return False
+
+def make_entities_code(entities):
+ entities_text = "\n".join(" \"%s\": u\"%s\","%(
+ name, entities[name].encode(
+ "unicode-escape").replace("\"", "\\\""))
+ for name in sorted(entities.keys()))
+ return """entities = {
+%s
+}"""%entities_text
+
+def main():
+ entities = entity_table(parse())
+ tests_json = make_tests_json(entities)
+ json.dump(tests_json, open("namedEntities.test", "w"), indent=4)
+ code = make_entities_code(entities)
+ open("entities_constants.py", "w").write(code)
+
+if __name__ == "__main__":
+ main()
+
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/utils/iana_parse.py b/tests/wpt/web-platform-tests/tools/html5lib/utils/iana_parse.py
new file mode 100644
index 00000000000..6dde94c2829
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/utils/iana_parse.py
@@ -0,0 +1,24 @@
+#!/usr/bin/env python
+import sys
+import urllib.request, urllib.error, urllib.parse
+import codecs
+
+def main():
+ encodings = []
+ f = urllib.request.urlopen(sys.argv[1])
+ for line in f:
+ if line.startswith("Name: ") or line.startswith("Alias: "):
+ enc = line.split()[1]
+ try:
+ codecs.lookup(enc)
+ if enc.lower not in encodings:
+ encodings.append(enc.lower())
+ except LookupError:
+ pass
+ sys.stdout.write("encodings = frozenset((\n")
+ for enc in encodings:
+ sys.stdout.write(' "%s",\n'%enc)
+ sys.stdout.write(' ))')
+
+if __name__ == "__main__":
+ main() \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/tools/html5lib/utils/spider.py b/tests/wpt/web-platform-tests/tools/html5lib/utils/spider.py
new file mode 100644
index 00000000000..a7b8031974b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/html5lib/utils/spider.py
@@ -0,0 +1,122 @@
+#!/usr/bin/env python
+"""Spider to try and find bugs in the parser. Requires httplib2 and elementtree
+
+usage:
+import spider
+s = spider.Spider()
+s.spider("http://www.google.com", maxURLs=100)
+"""
+
+import urllib.request, urllib.error, urllib.parse
+import urllib.robotparser
+import md5
+
+import httplib2
+
+import html5lib
+from html5lib.treebuilders import etree
+
+class Spider(object):
+ def __init__(self):
+ self.unvisitedURLs = set()
+ self.visitedURLs = set()
+ self.buggyURLs=set()
+ self.robotParser = urllib.robotparser.RobotFileParser()
+ self.contentDigest = {}
+ self.http = httplib2.Http(".cache")
+
+ def run(self, initialURL, maxURLs=1000):
+ urlNumber = 0
+ self.visitedURLs.add(initialURL)
+ content = self.loadURL(initialURL)
+ while maxURLs is None or urlNumber < maxURLs:
+ if content is not None:
+ self.parse(content)
+ urlNumber += 1
+ if not self.unvisitedURLs:
+ break
+ content = self.loadURL(self.unvisitedURLs.pop())
+
+ def parse(self, content):
+ failed = False
+ p = html5lib.HTMLParser(tree=etree.TreeBuilder)
+ try:
+ tree = p.parse(content)
+ except:
+ self.buggyURLs.add(self.currentURL)
+ failed = True
+ print("BUGGY:", self.currentURL)
+ self.visitedURLs.add(self.currentURL)
+ if not failed:
+ self.updateURLs(tree)
+
+ def loadURL(self, url):
+ resp, content = self.http.request(url, "GET")
+ self.currentURL = url
+ digest = md5.md5(content).hexdigest()
+ if digest in self.contentDigest:
+ content = None
+ self.visitedURLs.add(url)
+ else:
+ self.contentDigest[digest] = url
+
+ if resp['status'] != "200":
+ content = None
+
+ return content
+
+ def updateURLs(self, tree):
+ """Take all the links in the current document, extract the URLs and
+ update the list of visited and unvisited URLs according to whether we
+ have seen them before or not"""
+ urls = set()
+ #Remove all links we have already visited
+ for link in tree.findall(".//a"):
+ try:
+ url = urllib.parse.urldefrag(link.attrib['href'])[0]
+ if (url and url not in self.unvisitedURLs and url
+ not in self.visitedURLs):
+ urls.add(url)
+ except KeyError:
+ pass
+
+ #Remove all non-http URLs and a dd a sutiable base URL where that is
+ #missing
+ newUrls = set()
+ for url in urls:
+ splitURL = list(urllib.parse.urlsplit(url))
+ if splitURL[0] != "http":
+ continue
+ if splitURL[1] == "":
+ splitURL[1] = urllib.parse.urlsplit(self.currentURL)[1]
+ newUrls.add(urllib.parse.urlunsplit(splitURL))
+ urls = newUrls
+
+ responseHeaders = {}
+ #Now we want to find the content types of the links we haven't visited
+ for url in urls:
+ try:
+ resp, content = self.http.request(url, "HEAD")
+ responseHeaders[url] = resp
+ except AttributeError as KeyError:
+ #Don't know why this happens
+ pass
+
+
+ #Remove links not of content-type html or pages not found
+ #XXX - need to deal with other status codes?
+ toVisit = set([url for url in urls if url in responseHeaders and
+ "html" in responseHeaders[url]['content-type'] and
+ responseHeaders[url]['status'] == "200"])
+
+ #Now check we are allowed to spider the page
+ for url in toVisit:
+ robotURL = list(urllib.parse.urlsplit(url)[:2])
+ robotURL.extend(["robots.txt", "", ""])
+ robotURL = urllib.parse.urlunsplit(robotURL)
+ self.robotParser.set_url(robotURL)
+ if not self.robotParser.can_fetch("*", url):
+ toVisit.remove(url)
+
+ self.visitedURLs.update(urls)
+ self.unvisitedURLs.update(toVisit)
diff --git a/tests/wpt/web-platform-tests/tools/lint/__init__.py b/tests/wpt/web-platform-tests/tools/lint/__init__.py
new file mode 100644
index 00000000000..1595338cd6d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/lint/__init__.py
@@ -0,0 +1 @@
+import lint
diff --git a/tests/wpt/web-platform-tests/tools/lint/lint.py b/tests/wpt/web-platform-tests/tools/lint/lint.py
new file mode 100644
index 00000000000..e33cc6ef03a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/lint/lint.py
@@ -0,0 +1,259 @@
+import os
+import subprocess
+import re
+import sys
+import fnmatch
+
+from collections import defaultdict
+
+from .. import localpaths
+from manifest.sourcefile import SourceFile
+
+here = os.path.abspath(os.path.split(__file__)[0])
+repo_root = localpaths.repo_root
+
+def git(command, *args):
+ args = list(args)
+
+ proc_kwargs = {"cwd": repo_root}
+
+ command_line = ["git", command] + args
+
+ try:
+ return subprocess.check_output(command_line, **proc_kwargs)
+ except subprocess.CalledProcessError:
+ raise
+
+
+def iter_files():
+ for item in git("ls-tree", "-r", "--name-only", "HEAD").split("\n"):
+ yield item
+
+
+def check_path_length(path):
+ if len(path) + 1 > 150:
+ return [("PATH LENGTH", "/%s longer than maximum path length (%d > 150)" % (path, len(path) + 1), None)]
+ return []
+
+def set_type(error_type, errors):
+ return [(error_type,) + error for error in errors]
+
+def parse_whitelist_file(filename):
+ data = defaultdict(lambda:defaultdict(set))
+
+ with open(filename) as f:
+ for line in f:
+ line = line.strip()
+ if not line or line.startswith("#"):
+ continue
+ parts = [item.strip() for item in line.split(":")]
+ if len(parts) == 2:
+ parts.append(None)
+ else:
+ parts[-1] = int(parts[-1])
+
+ error_type, file_match, line_number = parts
+ data[file_match][error_type].add(line_number)
+
+ def inner(path, errors):
+ whitelisted = [False for item in xrange(len(errors))]
+
+ for file_match, whitelist_errors in data.iteritems():
+ if fnmatch.fnmatch(path, file_match):
+ for i, (error_type, msg, line) in enumerate(errors):
+ if "*" in whitelist_errors:
+ whitelisted[i] = True
+ elif error_type in whitelist_errors:
+ allowed_lines = whitelist_errors[error_type]
+ if None in allowed_lines or line in allowed_lines:
+ whitelisted[i] = True
+
+ return [item for i, item in enumerate(errors) if not whitelisted[i]]
+ return inner
+
+_whitelist_fn = None
+def whitelist_errors(path, errors):
+ global _whitelist_fn
+
+ if _whitelist_fn is None:
+ _whitelist_fn = parse_whitelist_file(os.path.join(here, "lint.whitelist"))
+ return _whitelist_fn(path, errors)
+
+class Regexp(object):
+ pattern = None
+ file_extensions = None
+ error = None
+ _re = None
+
+ def __init__(self):
+ self._re = re.compile(self.pattern)
+
+ def applies(self, path):
+ return (self.file_extensions is None or
+ os.path.splitext(path)[1] in self.file_extensions)
+
+ def search(self, line):
+ return self._re.search(line)
+
+class TrailingWhitespaceRegexp(Regexp):
+ pattern = "[ \t\f\v]$"
+ error = "TRAILING WHITESPACE"
+
+class TabsRegexp(Regexp):
+ pattern = "^\t"
+ error = "INDENT TABS"
+
+class CRRegexp(Regexp):
+ pattern = "\r$"
+ error = "CR AT EOL"
+
+class W3CTestOrgRegexp(Regexp):
+ pattern = "w3c\-test\.org"
+ error = "W3C-TEST.ORG"
+
+class PrintRegexp(Regexp):
+ pattern = "print(?:\s|\s*\()"
+ error = "PRINT STATEMENT"
+ file_extensions = [".py"]
+
+regexps = [item() for item in
+ [TrailingWhitespaceRegexp,
+ TabsRegexp,
+ CRRegexp,
+ W3CTestOrgRegexp,
+ PrintRegexp]]
+
+def check_regexp_line(path, f):
+ errors = []
+
+ applicable_regexps = [regexp for regexp in regexps if regexp.applies(path)]
+
+ for i, line in enumerate(f):
+ for regexp in applicable_regexps:
+ if regexp.search(line):
+ errors.append((regexp.error, "%s line %i" % (path, i+1), i+1))
+
+ return errors
+
+def check_parsed(path, f):
+ source_file = SourceFile(repo_root, path, "/")
+
+ errors = []
+
+ if source_file.name_is_non_test or source_file.name_is_manual:
+ return []
+
+ if source_file.markup_type is None:
+ return []
+
+ if source_file.root is None:
+ return [("PARSE-FAILED", "Unable to parse file %s" % path, None)]
+
+ if len(source_file.timeout_nodes) > 1:
+ errors.append(("MULTIPLE-TIMEOUT", "%s more than one meta name='timeout'" % path, None))
+
+ for timeout_node in source_file.timeout_nodes:
+ timeout_value = timeout_node.attrib.get("content", "").lower()
+ if timeout_value != "long":
+ errors.append(("INVALID-TIMEOUT", "%s invalid timeout value %s" % (path, timeout_value), None))
+
+ if source_file.testharness_nodes:
+ if len(source_file.testharness_nodes) > 1:
+ errors.append(("MULTIPLE-TESTHARNESS",
+ "%s more than one <script src='/resources/testharness.js>'" % path, None))
+
+ testharnessreport_nodes = source_file.root.findall(".//{http://www.w3.org/1999/xhtml}script[@src='/resources/testharnessreport.js']")
+ if not testharnessreport_nodes:
+ errors.append(("MISSING-TESTHARNESSREPORT",
+ "%s missing <script src='/resources/testharnessreport.js>'" % path, None))
+ else:
+ if len(testharnessreport_nodes) > 1:
+ errors.append(("MULTIPLE-TESTHARNESSREPORT",
+ "%s more than one <script src='/resources/testharnessreport.js>'" % path, None))
+
+ for element in source_file.variant_nodes:
+ if "content" not in element.attrib:
+ errors.append(("VARIANT-MISSING",
+ "%s has <meta name=variant> missing 'content' attribute" % path, None))
+ else:
+ variant = element.attrib["content"]
+ if variant != "" and variant[0] not in ("?", "#"):
+ errors.append(("MALFORMED-VARIANT",
+ "%s <meta name=variant> 'content' attribute must be the empty string or start with '?' or '#'" % path, None))
+
+ seen_elements = {"timeout": False,
+ "testharness": False,
+ "testharnessreport": False}
+ required_elements = [key for key, value in {"testharness": True,
+ "testharnessreport": len(testharnessreport_nodes) > 0,
+ "timeout": len(source_file.timeout_nodes) > 0}.iteritems()
+ if value]
+
+ for elem in source_file.root.iter():
+ if source_file.timeout_nodes and elem == source_file.timeout_nodes[0]:
+ seen_elements["timeout"] = True
+ if seen_elements["testharness"]:
+ errors.append(("LATE-TIMEOUT",
+ "%s <meta name=timeout> seen after testharness.js script" % path, None))
+
+ elif elem == source_file.testharness_nodes[0]:
+ seen_elements["testharness"] = True
+
+ elif testharnessreport_nodes and elem == testharnessreport_nodes[0]:
+ seen_elements["testharnessreport"] = True
+ if not seen_elements["testharness"]:
+ errors.append(("EARLY-TESTHARNESSREPORT",
+ "%s testharnessreport.js script seen before testharness.js script" % path, None))
+
+ if all(seen_elements[name] for name in required_elements):
+ break
+
+ return errors
+
+def output_errors(errors):
+ for error_type, error, line_number in errors:
+ print "%s: %s" % (error_type, error)
+
+def output_error_count(error_count):
+ if not error_count:
+ return
+
+ by_type = " ".join("%s: %d" % item for item in error_count.iteritems())
+ count = sum(error_count.values())
+ if count == 1:
+ print "There was 1 error (%s)" % (by_type,)
+ else:
+ print "There were %d errors (%s)" % (count, by_type)
+
+def main():
+ error_count = defaultdict(int)
+
+ def run_lint(path, fn, *args):
+ errors = whitelist_errors(path, fn(path, *args))
+ output_errors(errors)
+ for error_type, error, line in errors:
+ error_count[error_type] += 1
+
+ for path in iter_files():
+ abs_path = os.path.join(repo_root, path)
+ if not os.path.exists(path):
+ continue
+ for path_fn in path_lints:
+ run_lint(path, path_fn)
+
+ if not os.path.isdir(abs_path):
+ with open(abs_path) as f:
+ for file_fn in file_lints:
+ run_lint(path, file_fn, f)
+ f.seek(0)
+
+ output_error_count(error_count)
+ return sum(error_count.itervalues())
+
+path_lints = [check_path_length]
+file_lints = [check_regexp_line, check_parsed]
+
+if __name__ == "__main__":
+ error_count = main()
+ if error_count > 0:
+ sys.exit(1)
diff --git a/tests/wpt/web-platform-tests/tools/lint/lint.whitelist b/tests/wpt/web-platform-tests/tools/lint/lint.whitelist
new file mode 100644
index 00000000000..c683aa04235
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/lint/lint.whitelist
@@ -0,0 +1,104 @@
+# File containing whiteslist for lint errors
+# Format is:
+# ERROR TYPE:file/name/pattern[:line number]
+# e.g.
+# TRAILING WHITESPACE:example/file.html:128
+# to allow trailing whitespace on example/file.html line 128
+
+## Whitespace rules that we can't enforce yet ##
+
+INDENT TABS: .gitmodules
+INDENT TABS: app-uri/*
+INDENT TABS: conformance-checkers/*
+INDENT TABS: content-security-policy/*
+INDENT TABS: custom-elements/*
+INDENT TABS: DOMEvents/*
+INDENT TABS: eventsource/*
+INDENT TABS: html/editing/dnd/*
+INDENT TABS: html/semantics/*
+INDENT TABS: html/syntax/*
+INDENT TABS: html/webappapis/*
+INDENT TABS: media-source/*
+INDENT TABS: old-tests/*
+INDENT TABS: pointerlock/*
+INDENT TABS: shadow-dom/*
+INDENT TABS: tools/*
+INDENT TABS: touch-events/*
+INDENT TABS: web-animations/*
+INDENT TABS: webaudio/*
+INDENT TABS: webdriver/*
+INDENT TABS: webvtt/*
+INDENT TABS: XMLHttpRequest/*
+
+TRAILING WHITESPACE: app-uri/*
+TRAILING WHITESPACE: battery-status/*
+TRAILING WHITESPACE: conformance-checkers/*
+TRAILING WHITESPACE: content-security-policy/*
+TRAILING WHITESPACE: custom-elements/*
+TRAILING WHITESPACE: DOMEvents/*
+TRAILING WHITESPACE: html-longdesc/*
+TRAILING WHITESPACE: media-source/*
+TRAILING WHITESPACE: microdata/*
+TRAILING WHITESPACE: old-tests/*
+TRAILING WHITESPACE: pointerevents/*
+TRAILING WHITESPACE: progress-events/*
+TRAILING WHITESPACE: shadow-dom/*
+TRAILING WHITESPACE: tools/*
+TRAILING WHITESPACE: webaudio/*
+TRAILING WHITESPACE: webdriver/*
+TRAILING WHITESPACE: WebIDL/*
+TRAILING WHITESPACE: webvtt/*
+TRAILING WHITESPACE: XMLHttpRequest/*
+
+## File types that should never be checked ##
+
+*:*.pdf
+*:*.jpg
+*:*.png
+*:*.gif
+*:*.pdf
+*:*.wav
+*:*.mp3
+*:*.m4a
+*:*.oga
+*:*.ogv
+*:*.webm
+*:*.mp4
+*:*.m4v
+*:*.ttf
+*:*.woff
+*:*.eot
+*:*.sfd
+*:*.swf
+
+## Documentation ##
+
+W3C-TEST.ORG:README.md
+W3C-TEST.ORG:*/README.md
+W3C-TEST.ORG:docs/*
+
+## Helper scripts ##
+
+W3C-TEST.ORG:tools/*
+PRINT STATEMENT:tools/*
+W3C-TEST.ORG:*/tools/*
+PRINT STATEMENT:*/tools/*
+
+### Test exclusions ##
+
+CR AT EOL:WebIDL/valid/idl/documentation-dos.widl
+CR AT EOL:cors/resources/cors-headers.asis
+CR AT EOL:html/semantics/embedded-content/the-canvas-element/size.attributes.parse.whitespace.html
+CR AT EOL:webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/newlines.vtt
+PARSE-FAILED:dom/nodes/Document-createElement-namespace-tests/empty.svg
+PARSE-FAILED:dom/nodes/Document-createElement-namespace-tests/empty.xhtml
+PARSE-FAILED:dom/nodes/Document-createElement-namespace-tests/minimal_html.svg
+PARSE-FAILED:dom/nodes/Document-createElement-namespace-tests/minimal_html.xhtml
+
+# These have undefined entities; should probably find a way to define them
+PARSE-FAILED:ext-xhtml-pubid/the-xhtml-syntax/parsing-xhtml-documents/xhtml-pubid-1.xhtml
+PARSE-FAILED:ext-xhtml-pubid/the-xhtml-syntax/parsing-xhtml-documents/xhtml-pubid-2.xhtml
+PARSE-FAILED:ext-xhtml-pubid/the-xhtml-syntax/parsing-xhtml-documents/xhtml-pubid-3.xhtml
+
+# Test generation files containing print statements
+PRINT STATEMENT:dom/nodes/Document-createElement-namespace-tests/generate.py
diff --git a/tests/wpt/web-platform-tests/tools/localpaths.py b/tests/wpt/web-platform-tests/tools/localpaths.py
new file mode 100644
index 00000000000..dcd19c35b33
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/localpaths.py
@@ -0,0 +1,11 @@
+import os
+import sys
+
+here = os.path.abspath(os.path.split(__file__)[0])
+repo_root = os.path.abspath(os.path.join(here, os.pardir))
+
+sys.path.insert(0, os.path.join(repo_root, "tools"))
+sys.path.insert(0, os.path.join(repo_root, "tools", "six"))
+sys.path.insert(0, os.path.join(repo_root, "tools", "html5lib"))
+sys.path.insert(0, os.path.join(repo_root, "tools", "wptserve"))
+sys.path.insert(0, os.path.join(repo_root, "tools", "pywebsocket", "src"))
diff --git a/tests/wpt/web-platform-tests/tools/manifest/__init__.py b/tests/wpt/web-platform-tests/tools/manifest/__init__.py
new file mode 100644
index 00000000000..9c259c89529
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/manifest/__init__.py
@@ -0,0 +1,5 @@
+import item
+import manifest
+import sourcefile
+import tree
+import update
diff --git a/tests/wpt/web-platform-tests/tools/manifest/item.py b/tests/wpt/web-platform-tests/tools/manifest/item.py
new file mode 100644
index 00000000000..702682cd70e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/manifest/item.py
@@ -0,0 +1,175 @@
+import urlparse
+from abc import ABCMeta, abstractmethod, abstractproperty
+
+item_types = ["testharness", "reftest", "manual", "stub", "wdspec"]
+
+def get_source_file(source_files, tests_root, manifest, path):
+ def make_new():
+ from sourcefile import SourceFile
+
+ return SourceFile(tests_root, path, manifest.url_base)
+
+ if source_files is None:
+ return make_new()
+
+ if path not in source_files:
+ source_files[path] = make_new()
+
+ return source_files[path]
+
+class ManifestItem(object):
+ __metaclass__ = ABCMeta
+
+ item_type = None
+
+ def __init__(self, source_file, manifest=None):
+ self.manifest = manifest
+ self.source_file = source_file
+
+ @abstractproperty
+ def id(self):
+ """The test's id (usually its url)"""
+ pass
+
+ @property
+ def path(self):
+ """The test path relative to the test_root"""
+ return self.source_file.rel_path
+
+ @property
+ def https(self):
+ return "https" in self.source_file.meta_flags
+
+ def key(self):
+ """A unique identifier for the test"""
+ return (self.item_type, self.id)
+
+ def meta_key(self):
+ """Extra metadata that doesn't form part of the test identity, but for
+ which changes mean regenerating the manifest (e.g. the test timeout."""
+ return ()
+
+ def __eq__(self, other):
+ if not hasattr(other, "key"):
+ return False
+ return self.key() == other.key()
+
+ def __hash__(self):
+ return hash(self.key() + self.meta_key())
+
+ def to_json(self):
+ return {"path": self.path}
+
+ @classmethod
+ def from_json(self, manifest, tests_root, obj, source_files=None):
+ raise NotImplementedError
+
+
+class URLManifestItem(ManifestItem):
+ def __init__(self, source_file, url, url_base="/", manifest=None):
+ ManifestItem.__init__(self, source_file, manifest=manifest)
+ self._url = url
+ self.url_base = url_base
+
+ @property
+ def id(self):
+ return self.url
+
+ @property
+ def url(self):
+ return urlparse.urljoin(self.url_base, self._url)
+
+ def to_json(self):
+ rv = ManifestItem.to_json(self)
+ rv["url"] = self._url
+ return rv
+
+ @classmethod
+ def from_json(cls, manifest, tests_root, obj, source_files=None):
+ source_file = get_source_file(source_files, tests_root, manifest, obj["path"])
+ return cls(source_file,
+ obj["url"],
+ url_base=manifest.url_base,
+ manifest=manifest)
+
+
+class TestharnessTest(URLManifestItem):
+ item_type = "testharness"
+
+ def __init__(self, source_file, url, url_base="/", timeout=None, manifest=None):
+ URLManifestItem.__init__(self, source_file, url, url_base=url_base, manifest=manifest)
+ self.timeout = timeout
+
+ def meta_key(self):
+ return (self.timeout,)
+
+ def to_json(self):
+ rv = URLManifestItem.to_json(self)
+ if self.timeout is not None:
+ rv["timeout"] = self.timeout
+ return rv
+
+ @classmethod
+ def from_json(cls, manifest, tests_root, obj, source_files=None):
+ source_file = get_source_file(source_files, tests_root, manifest, obj["path"])
+ return cls(source_file,
+ obj["url"],
+ url_base=manifest.url_base,
+ timeout=obj.get("timeout"),
+ manifest=manifest)
+
+
+class RefTest(URLManifestItem):
+ item_type = "reftest"
+
+ def __init__(self, source_file, url, references, url_base="/", timeout=None,
+ manifest=None):
+ URLManifestItem.__init__(self, source_file, url, url_base=url_base, manifest=manifest)
+ for _, ref_type in references:
+ if ref_type not in ["==", "!="]:
+ raise ValueError, "Unrecognised ref_type %s" % ref_type
+ self.references = tuple(references)
+ self.timeout = timeout
+
+ @property
+ def is_reference(self):
+ return self.source_file.name_is_reference
+
+ def meta_key(self):
+ return (self.timeout,)
+
+ def to_json(self):
+ rv = URLManifestItem.to_json(self)
+ rv["references"] = self.references
+ if self.timeout is not None:
+ rv["timeout"] = self.timeout
+ return rv
+
+ @classmethod
+ def from_json(cls, manifest, tests_root, obj, source_files=None):
+ source_file = get_source_file(source_files, tests_root, manifest, obj["path"])
+ return cls(source_file,
+ obj["url"],
+ obj["references"],
+ url_base=manifest.url_base,
+ timeout=obj.get("timeout"),
+ manifest=manifest)
+
+
+class ManualTest(URLManifestItem):
+ item_type = "manual"
+
+class Stub(URLManifestItem):
+ item_type = "stub"
+
+class WebdriverSpecTest(ManifestItem):
+ item_type = "wdspec"
+
+ @property
+ def id(self):
+ return self.path
+
+ @classmethod
+ def from_json(cls, manifest, tests_root, obj, source_files=None):
+ source_file = get_source_file(source_files, tests_root, manifest, obj["path"])
+ return cls(source_file, manifest=manifest)
diff --git a/tests/wpt/web-platform-tests/tools/manifest/log.py b/tests/wpt/web-platform-tests/tools/manifest/log.py
new file mode 100644
index 00000000000..6aea9ce0802
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/manifest/log.py
@@ -0,0 +1,8 @@
+import logging
+
+logging.basicConfig()
+logger = logging.getLogger("manifest")
+logger.setLevel(logging.DEBUG)
+
+def get_logger():
+ return logger
diff --git a/tests/wpt/web-platform-tests/tools/manifest/manifest.py b/tests/wpt/web-platform-tests/tools/manifest/manifest.py
new file mode 100644
index 00000000000..8a0ea4d34f0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/manifest/manifest.py
@@ -0,0 +1,374 @@
+import json
+import os
+from collections import defaultdict
+
+from item import item_types, ManualTest, WebdriverSpecTest, Stub, RefTest, TestharnessTest
+from log import get_logger
+from sourcefile import SourceFile
+
+
+CURRENT_VERSION = 2
+
+
+class ManifestError(Exception):
+ pass
+
+
+class ManifestVersionMismatch(ManifestError):
+ pass
+
+class Manifest(object):
+ def __init__(self, git_rev=None, url_base="/"):
+ # Dict of item_type: {path: set(manifest_items)}
+ self._data = dict((item_type, defaultdict(set))
+ for item_type in item_types)
+ self.rev = git_rev
+ self.url_base = url_base
+ self.local_changes = LocalChanges(self)
+ # reftest nodes arranged as {path: set(manifest_items)}
+ self.reftest_nodes = defaultdict(set)
+ self.reftest_nodes_by_url = {}
+
+ def _included_items(self, include_types=None):
+ if include_types is None:
+ include_types = item_types
+
+ for item_type in include_types:
+ paths = self._data[item_type].copy()
+ for local_types, local_paths in self.local_changes.itertypes(item_type):
+ for path, items in local_paths.iteritems():
+ paths[path] = items
+ for path in self.local_changes.iterdeleted():
+ if path in paths:
+ del paths[path]
+
+ yield item_type, paths
+
+ def contains_path(self, path):
+ return any(path in paths for _, paths in self._included_items())
+
+ def add(self, item):
+ if item is None:
+ return
+
+ is_reference = False
+ if isinstance(item, RefTest):
+ self.reftest_nodes[item.path].add(item)
+ self.reftest_nodes_by_url[item.url] = item
+ is_reference = item.is_reference
+
+ if not is_reference:
+ self._add(item)
+
+ item.manifest = self
+
+ def _add(self, item):
+ self._data[item.item_type][item.path].add(item)
+
+ def extend(self, items):
+ for item in items:
+ self.add(item)
+
+ def remove_path(self, path):
+ for item_type in item_types:
+ if path in self._data[item_type]:
+ del self._data[item_type][path]
+
+ def itertypes(self, *types):
+ if not types:
+ types = None
+ for item_type, items in self._included_items(types):
+ for item in sorted(items.items()):
+ yield item
+
+ def __iter__(self):
+ for item in self.itertypes():
+ yield item
+
+ def __getitem__(self, path):
+ for _, paths in self._included_items():
+ if path in paths:
+ return paths[path]
+ raise KeyError
+
+ def get_reference(self, url):
+ if url in self.local_changes.reftest_nodes_by_url:
+ return self.local_changes.reftest_nodes_by_url[url]
+
+ if url in self.reftest_nodes_by_url:
+ return self.reftest_nodes_by_url[url]
+
+ return None
+
+ def _committed_with_path(self, rel_path):
+ rv = set()
+
+ for paths_items in self._data.itervalues():
+ rv |= paths_items.get(rel_path, set())
+
+ if rel_path in self.reftest_nodes:
+ rv |= self.reftest_nodes[rel_path]
+
+ return rv
+
+ def _committed_paths(self):
+ rv = set()
+ for paths_items in self._data.itervalues():
+ rv |= set(paths_items.keys())
+ return rv
+
+ def update(self,
+ tests_root,
+ url_base,
+ new_rev,
+ committed_changes=None,
+ local_changes=None,
+ remove_missing_local=False):
+
+ if local_changes is None:
+ local_changes = {}
+
+ if committed_changes is not None:
+ for rel_path, status in committed_changes:
+ self.remove_path(rel_path)
+ if status == "modified":
+ use_committed = rel_path in local_changes
+ source_file = SourceFile(tests_root,
+ rel_path,
+ url_base,
+ use_committed=use_committed)
+ self.extend(source_file.manifest_items())
+
+ self.local_changes = LocalChanges(self)
+
+ local_paths = set()
+ for rel_path, status in local_changes.iteritems():
+ local_paths.add(rel_path)
+
+ if status == "modified":
+ existing_items = self._committed_with_path(rel_path)
+ source_file = SourceFile(tests_root,
+ rel_path,
+ url_base,
+ use_committed=False)
+ local_items = set(source_file.manifest_items())
+
+ updated_items = local_items - existing_items
+ self.local_changes.extend(updated_items)
+ else:
+ self.local_changes.add_deleted(rel_path)
+
+ if remove_missing_local:
+ for path in self._committed_paths() - local_paths:
+ self.local_changes.add_deleted(path)
+
+ self.update_reftests()
+
+ if new_rev is not None:
+ self.rev = new_rev
+ self.url_base = url_base
+
+ def update_reftests(self):
+ reftest_nodes = self.reftest_nodes.copy()
+ for path, items in self.local_changes.reftest_nodes.iteritems():
+ reftest_nodes[path] |= items
+
+ #TODO: remove locally deleted files
+ tests = set()
+ for items in reftest_nodes.values():
+ tests |= set(item for item in items if not item.is_reference)
+
+ has_inbound = set()
+ for path, items in reftest_nodes.iteritems():
+ for item in items:
+ for ref_url, ref_type in item.references:
+ has_inbound.add(ref_url)
+
+ if self.local_changes.reftest_nodes:
+ target = self.local_changes
+ else:
+ target = self
+
+ #TODO: Warn if there exist unreachable reftest nodes
+
+ for path, items in reftest_nodes.iteritems():
+ for item in items:
+ if item.url in has_inbound:
+ continue
+ target._data["reftest"][path].add(item)
+
+ def to_json(self):
+ out_items = {
+ item_type: sorted(
+ test.to_json()
+ for _, tests in items.iteritems()
+ for test in tests
+ )
+ for item_type, items in self._data.iteritems()
+ }
+
+ reftest_nodes = {key:[v.to_json() for v in value]
+ for key, value in self.reftest_nodes.iteritems()}
+
+ rv = {"url_base": self.url_base,
+ "rev": self.rev,
+ "local_changes": self.local_changes.to_json(),
+ "items": out_items,
+ "reftest_nodes": reftest_nodes,
+ "version": CURRENT_VERSION}
+ return rv
+
+ @classmethod
+ def from_json(cls, tests_root, obj):
+ version = obj.get("version")
+ if version != CURRENT_VERSION:
+ raise ManifestVersionMismatch
+
+ self = cls(git_rev=obj["rev"],
+ url_base=obj.get("url_base", "/"))
+ if not hasattr(obj, "iteritems"):
+ raise ManifestError
+
+ item_classes = {"testharness": TestharnessTest,
+ "reftest": RefTest,
+ "manual": ManualTest,
+ "stub": Stub,
+ "wdspec": WebdriverSpecTest}
+
+ source_files = {}
+
+ for k, values in obj["items"].iteritems():
+ if k not in item_types:
+ raise ManifestError
+ for v in values:
+ manifest_item = item_classes[k].from_json(self, tests_root, v,
+ source_files=source_files)
+ self._add(manifest_item)
+
+ for path, values in obj["reftest_nodes"].iteritems():
+ for v in values:
+ item = RefTest.from_json(self, tests_root, v,
+ source_files=source_files)
+ self.reftest_nodes[path].add(item)
+ self.reftest_nodes_by_url[v["url"]] = item
+
+ self.local_changes = LocalChanges.from_json(self,
+ tests_root,
+ obj["local_changes"],
+ source_files=source_files)
+ return self
+
+class LocalChanges(object):
+ def __init__(self, manifest):
+ self.manifest = manifest
+ self._data = dict((item_type, defaultdict(set)) for item_type in item_types)
+ self._deleted = set()
+ self.reftest_nodes = defaultdict(set)
+ self.reftest_nodes_by_url = {}
+
+ def add(self, item):
+ if item is None:
+ return
+
+ is_reference = False
+ if isinstance(item, RefTest):
+ self.reftest_nodes[item.path].add(item)
+ self.reftest_nodes_by_url[item.url] = item
+ is_reference = item.is_reference
+
+ if not is_reference:
+ self._add(item)
+
+ item.manifest = self.manifest
+
+ def _add(self, item):
+ self._data[item.item_type][item.path].add(item)
+
+ def extend(self, items):
+ for item in items:
+ self.add(item)
+
+ def add_deleted(self, path):
+ self._deleted.add(path)
+
+ def is_deleted(self, path):
+ return path in self._deleted
+
+ def itertypes(self, *types):
+ for item_type in types:
+ yield item_type, self._data[item_type]
+
+ def iterdeleted(self):
+ for item in self._deleted:
+ yield item
+
+ def __getitem__(self, item_type):
+ return self._data[item_type]
+
+ def to_json(self):
+ reftest_nodes = {key:[v.to_json() for v in value]
+ for key, value in self.reftest_nodes.iteritems()}
+
+ rv = {"items": defaultdict(dict),
+ "reftest_nodes": reftest_nodes,
+ "deleted": []}
+
+ rv["deleted"].extend(self._deleted)
+
+ for test_type, paths in self._data.iteritems():
+ for path, tests in paths.iteritems():
+ rv["items"][test_type][path] = [test.to_json() for test in tests]
+
+ return rv
+
+ @classmethod
+ def from_json(cls, manifest, tests_root, obj, source_files=None):
+ self = cls(manifest)
+ if not hasattr(obj, "iteritems"):
+ raise ManifestError
+
+ item_classes = {"testharness": TestharnessTest,
+ "reftest": RefTest,
+ "manual": ManualTest,
+ "stub": Stub,
+ "wdspec": WebdriverSpecTest}
+
+ for test_type, paths in obj["items"].iteritems():
+ for path, tests in paths.iteritems():
+ for test in tests:
+ manifest_item = item_classes[test_type].from_json(manifest,
+ tests_root,
+ test,
+ source_files=source_files)
+ self.add(manifest_item)
+
+ for path, values in obj["reftest_nodes"].iteritems():
+ for v in values:
+ item = RefTest.from_json(self.manifest, tests_root, v,
+ source_files=source_files)
+ self.reftest_nodes[path].add(item)
+ self.reftest_nodes_by_url[item.url] = item
+
+ for item in obj["deleted"]:
+ self.add_deleted(item)
+
+ return self
+
+def load(tests_root, manifest_path):
+ logger = get_logger()
+
+ if os.path.exists(manifest_path):
+ logger.debug("Opening manifest at %s" % manifest_path)
+ else:
+ logger.debug("Creating new manifest at %s" % manifest_path)
+ try:
+ with open(manifest_path) as f:
+ manifest = Manifest.from_json(tests_root, json.load(f))
+ except IOError:
+ manifest = Manifest(None)
+
+ return manifest
+
+def write(manifest, manifest_path):
+ with open(manifest_path, "w") as f:
+ json.dump(manifest.to_json(), f, sort_keys=True, indent=2, separators=(',', ': '))
diff --git a/tests/wpt/web-platform-tests/tools/manifest/sourcefile.py b/tests/wpt/web-platform-tests/tools/manifest/sourcefile.py
new file mode 100644
index 00000000000..914f7736419
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/manifest/sourcefile.py
@@ -0,0 +1,268 @@
+import os
+import urlparse
+from fnmatch import fnmatch
+try:
+ from xml.etree import cElementTree as ElementTree
+except ImportError:
+ from xml.etree import ElementTree
+
+import html5lib
+
+import vcs
+from item import Stub, ManualTest, WebdriverSpecTest, RefTest, TestharnessTest
+from utils import rel_path_to_url, is_blacklisted, ContextManagerStringIO, cached_property
+
+wd_pattern = "*.py"
+
+class SourceFile(object):
+ parsers = {"html":lambda x:html5lib.parse(x, treebuilder="etree"),
+ "xhtml":ElementTree.parse,
+ "svg":ElementTree.parse}
+
+ def __init__(self, tests_root, rel_path, url_base, use_committed=False):
+ """Object representing a file in a source tree.
+
+ :param tests_root: Path to the root of the source tree
+ :param rel_path: File path relative to tests_root
+ :param url_base: Base URL used when converting file paths to urls
+ :param use_committed: Work with the last committed version of the file
+ rather than the on-disk version.
+ """
+
+ self.tests_root = tests_root
+ self.rel_path = rel_path
+ self.url_base = url_base
+ self.use_committed = use_committed
+
+ self.url = rel_path_to_url(rel_path, url_base)
+ self.path = os.path.join(tests_root, rel_path)
+
+ self.dir_path, self.filename = os.path.split(self.path)
+ self.name, self.ext = os.path.splitext(self.filename)
+
+ self.type_flag = None
+ if "-" in self.name:
+ self.type_flag = self.name.rsplit("-", 1)[1]
+
+ self.meta_flags = self.name.split(".")[1:]
+
+ def name_prefix(self, prefix):
+ """Check if the filename starts with a given prefix
+
+ :param prefix: The prefix to check"""
+ return self.name.startswith(prefix)
+
+ def open(self):
+ """Return a File object opened for reading the file contents,
+ or the contents of the file when last committed, if
+ use_comitted is true."""
+
+ if self.use_committed:
+ git = vcs.get_git_func(os.path.dirname(__file__))
+ blob = git("show", "HEAD:%s" % self.rel_path)
+ file_obj = ContextManagerStringIO(blob)
+ else:
+ file_obj = open(self.path)
+ return file_obj
+
+ @property
+ def name_is_non_test(self):
+ """Check if the file name matches the conditions for the file to
+ be a non-test file"""
+ return (os.path.isdir(self.rel_path) or
+ self.name_prefix("MANIFEST") or
+ self.filename.startswith(".") or
+ is_blacklisted(self.url))
+
+ @property
+ def name_is_stub(self):
+ """Check if the file name matches the conditions for the file to
+ be a stub file"""
+ return self.name_prefix("stub-")
+
+ @property
+ def name_is_manual(self):
+ """Check if the file name matches the conditions for the file to
+ be a manual test file"""
+ return self.type_flag == "manual"
+
+ @property
+ def name_is_worker(self):
+ """Check if the file name matches the conditions for the file to
+ be a worker js test file"""
+ return "worker" in self.meta_flags and self.ext == ".js"
+
+ @property
+ def name_is_webdriver(self):
+ """Check if the file name matches the conditions for the file to
+ be a webdriver spec test file"""
+ # wdspec tests are in subdirectories of /webdriver excluding __init__.py
+ # files.
+ rel_dir_tree = self.rel_path.split(os.path.sep)
+ return (rel_dir_tree[0] == "webdriver" and
+ len(rel_dir_tree) > 2 and
+ self.filename != "__init__.py" and
+ fnmatch(self.filename, wd_pattern))
+
+ @property
+ def name_is_reference(self):
+ """Check if the file name matches the conditions for the file to
+ be a reference file (not a reftest)"""
+ return self.type_flag in ("ref", "notref")
+
+ @property
+ def markup_type(self):
+ """Return the type of markup contained in a file, based on its extension,
+ or None if it doesn't contain markup"""
+ ext = self.ext
+
+ if not ext:
+ return None
+ if ext[0] == ".":
+ ext = ext[1:]
+ if ext in ["html", "htm"]:
+ return "html"
+ if ext in ["xhtml", "xht"]:
+ return "xhtml"
+ if ext == "svg":
+ return "svg"
+ return None
+
+ @cached_property
+ def root(self):
+ """Return an ElementTree Element for the root node of the file if it contains
+ markup, or None if it does not"""
+ if not self.markup_type:
+ return None
+
+ parser = self.parsers[self.markup_type]
+
+ with self.open() as f:
+ try:
+ tree = parser(f)
+ except Exception:
+ return None
+
+ if hasattr(tree, "getroot"):
+ root = tree.getroot()
+ else:
+ root = tree
+
+ return root
+
+ @cached_property
+ def timeout_nodes(self):
+ """List of ElementTree Elements corresponding to nodes in a test that
+ specify timeouts"""
+ return self.root.findall(".//{http://www.w3.org/1999/xhtml}meta[@name='timeout']")
+
+ @cached_property
+ def timeout(self):
+ """The timeout of a test or reference file. "long" if the file has an extended timeout
+ or None otherwise"""
+ if not self.root:
+ return
+
+ if self.timeout_nodes:
+ timeout_str = self.timeout_nodes[0].attrib.get("content", None)
+ if timeout_str and timeout_str.lower() == "long":
+ return timeout_str
+
+ @cached_property
+ def testharness_nodes(self):
+ """List of ElementTree Elements corresponding to nodes representing a
+ testharness.js script"""
+ return self.root.findall(".//{http://www.w3.org/1999/xhtml}script[@src='/resources/testharness.js']")
+
+ @cached_property
+ def content_is_testharness(self):
+ """Boolean indicating whether the file content represents a
+ testharness.js test"""
+ if not self.root:
+ return None
+ return bool(self.testharness_nodes)
+
+ @cached_property
+ def variant_nodes(self):
+ """List of ElementTree Elements corresponding to nodes representing a
+ test variant"""
+ return self.root.findall(".//{http://www.w3.org/1999/xhtml}meta[@name='variant']")
+
+ @cached_property
+ def test_variants(self):
+ rv = []
+ for element in self.variant_nodes:
+ if "content" in element.attrib:
+ variant = element.attrib["content"]
+ assert variant == "" or variant[0] in ["#", "?"]
+ rv.append(variant)
+
+ if not rv:
+ rv = [""]
+
+ return rv
+
+ @cached_property
+ def reftest_nodes(self):
+ """List of ElementTree Elements corresponding to nodes representing a
+ to a reftest <link>"""
+ if not self.root:
+ return []
+
+ match_links = self.root.findall(".//{http://www.w3.org/1999/xhtml}link[@rel='match']")
+ mismatch_links = self.root.findall(".//{http://www.w3.org/1999/xhtml}link[@rel='mismatch']")
+ return match_links + mismatch_links
+
+ @cached_property
+ def references(self):
+ """List of (ref_url, relation) tuples for any reftest references specified in
+ the file"""
+ rv = []
+ rel_map = {"match": "==", "mismatch": "!="}
+ for item in self.reftest_nodes:
+ if "href" in item.attrib:
+ ref_url = urlparse.urljoin(self.url, item.attrib["href"])
+ ref_type = rel_map[item.attrib["rel"]]
+ rv.append((ref_url, ref_type))
+ return rv
+
+ @cached_property
+ def content_is_ref_node(self):
+ """Boolean indicating whether the file is a non-leaf node in a reftest
+ graph (i.e. if it contains any <link rel=[mis]match>"""
+ return bool(self.references)
+
+ def manifest_items(self):
+ """List of manifest items corresponding to the file. There is typically one
+ per test, but in the case of reftests a node may have corresponding manifest
+ items without being a test itself."""
+
+ if self.name_is_non_test:
+ rv = []
+
+ elif self.name_is_stub:
+ rv = [Stub(self, self.url)]
+
+ elif self.name_is_manual:
+ rv = [ManualTest(self, self.url)]
+
+ elif self.name_is_worker:
+ rv = [TestharnessTest(self, self.url[:-3])]
+
+ elif self.name_is_webdriver:
+ rv = [WebdriverSpecTest(self)]
+
+ elif self.content_is_testharness:
+ rv = []
+ for variant in self.test_variants:
+ url = self.url + variant
+ rv.append(TestharnessTest(self, url, timeout=self.timeout))
+
+ elif self.content_is_ref_node:
+ rv = [RefTest(self, self.url, self.references, timeout=self.timeout)]
+
+ else:
+ # If nothing else it's a helper file, which we don't have a specific type for
+ rv = []
+
+ return rv
diff --git a/tests/wpt/web-platform-tests/tools/manifest/tree.py b/tests/wpt/web-platform-tests/tools/manifest/tree.py
new file mode 100644
index 00000000000..e4ef6562b25
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/manifest/tree.py
@@ -0,0 +1,166 @@
+import os
+from cStringIO import StringIO
+from fnmatch import fnmatch
+
+import vcs
+from log import get_logger
+from utils import is_blacklisted, rel_path_to_url
+
+def chunks(data, n):
+ for i in range(0, len(data) - 1, n):
+ yield data[i:i+n]
+
+class TestTree(object):
+ def __init__(self, tests_root, url_base):
+ self.tests_root = tests_root
+ self.url_base = url_base
+ self.logger = get_logger()
+
+ def current_rev(self):
+ pass
+
+ def local_changes(self):
+ pass
+
+ def committed_changes(self, base_rev=None):
+ pass
+
+
+class GitTree(TestTree):
+ def __init__(self, tests_root, url_base):
+ TestTree.__init__(self, tests_root, url_base)
+ self.git = self.setup_git()
+
+ def setup_git(self):
+ assert vcs.is_git_repo(self.tests_root)
+ return vcs.get_git_func(self.tests_root)
+
+ def current_rev(self):
+ return self.git("rev-parse", "HEAD").strip()
+
+ def local_changes(self, path=None):
+ # -z is stable like --porcelain; see the git status documentation for details
+ cmd = ["status", "-z", "--ignore-submodules=all"]
+ if path is not None:
+ cmd.extend(["--", path])
+
+ rv = {}
+
+ data = self.git(*cmd)
+ if data == "":
+ return rv
+
+ assert data[-1] == "\0"
+ f = StringIO(data)
+
+ while f.tell() < len(data):
+ # First two bytes are the status in the stage (index) and working tree, respectively
+ staged = f.read(1)
+ worktree = f.read(1)
+ assert f.read(1) == " "
+
+ if staged == "R":
+ # When a file is renamed, there are two files, the source and the destination
+ files = 2
+ else:
+ files = 1
+
+ filenames = []
+
+ for i in range(files):
+ filenames.append("")
+ char = f.read(1)
+ while char != "\0":
+ filenames[-1] += char
+ char = f.read(1)
+
+ if not is_blacklisted(rel_path_to_url(filenames[0], self.url_base)):
+ rv.update(self.local_status(staged, worktree, filenames))
+
+ return rv
+
+ def committed_changes(self, base_rev=None):
+ if base_rev is None:
+ self.logger.debug("Adding all changesets to the manifest")
+ return [(item, "modified") for item in self.paths()]
+
+ self.logger.debug("Updating the manifest from %s to %s" % (base_rev, self.current_rev()))
+ rv = []
+ data = self.git("diff", "-z", "--name-status", base_rev + "..HEAD")
+ items = data.split("\0")
+ for status, filename in chunks(items, 2):
+ if is_blacklisted(rel_path_to_url(filename, self.url_base)):
+ continue
+ if status == "D":
+ rv.append((filename, "deleted"))
+ else:
+ rv.append((filename, "modified"))
+ return rv
+
+ def paths(self):
+ data = self.git("ls-tree", "--name-only", "--full-tree", "-r", "HEAD")
+ return [item for item in data.split("\n") if not item.endswith(os.path.sep)]
+
+ def local_status(self, staged, worktree, filenames):
+ # Convert the complex range of statuses that git can have to two values
+ # we care about; "modified" and "deleted" and return a dictionary mapping
+ # filenames to statuses
+
+ rv = {}
+
+ if (staged, worktree) in [("D", "D"), ("A", "U"), ("U", "D"), ("U", "A"),
+ ("D", "U"), ("A", "A"), ("U", "U")]:
+ raise Exception("Can't operate on tree containing unmerged paths")
+
+ if staged == "R":
+ assert len(filenames) == 2
+ dest, src = filenames
+ rv[dest] = "modified"
+ rv[src] = "deleted"
+ else:
+ assert len(filenames) == 1
+
+ filename = filenames[0]
+
+ if staged == "D" or worktree == "D":
+ # Actually if something is deleted in the index but present in the worktree
+ # it will get included by having a status of both "D " and "??".
+ # It isn't clear whether that's a bug
+ rv[filename] = "deleted"
+ elif staged == "?" and worktree == "?":
+ # A new file. If it's a directory, recurse into it
+ if os.path.isdir(os.path.join(self.tests_root, filename)):
+ rv.update(self.local_changes(filename))
+ else:
+ rv[filename] = "modified"
+ else:
+ rv[filename] = "modified"
+
+ return rv
+
+class NoVCSTree(TestTree):
+ """Subclass that doesn't depend on git"""
+
+ ignore = ["*.py[c|0]", "*~", "#*"]
+
+ def current_rev(self):
+ return None
+
+ def local_changes(self):
+ # Put all files into local_changes and rely on Manifest.update to de-dupe
+ # changes that in fact committed at the base rev.
+
+ rv = []
+ for dir_path, dir_names, filenames in os.walk(self.tests_root):
+ for filename in filenames:
+ if any(fnmatch(filename, pattern) for pattern in self.ignore):
+ continue
+ rel_path = os.path.relpath(os.path.join(dir_path, filename),
+ self.tests_root)
+ if is_blacklisted(rel_path_to_url(rel_path, self.url_base)):
+ continue
+ rv.append((rel_path, "modified"))
+ return dict(rv)
+
+ def committed_changes(self, base_rev=None):
+ return None
diff --git a/tests/wpt/web-platform-tests/tools/manifest/update.py b/tests/wpt/web-platform-tests/tools/manifest/update.py
new file mode 100644
index 00000000000..054e9ce7ab2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/manifest/update.py
@@ -0,0 +1,98 @@
+#!/usr/bin/env python
+import argparse
+import imp
+import os
+
+import manifest
+import vcs
+from log import get_logger
+from tree import GitTree, NoVCSTree
+
+here = os.path.dirname(__file__)
+localpaths = imp.load_source("localpaths", os.path.abspath(os.path.join(here, os.pardir, "localpaths.py")))
+
+def update(tests_root, url_base, manifest, ignore_local=False):
+ if vcs.is_git_repo(tests_root):
+ tests_tree = GitTree(tests_root, url_base)
+ remove_missing_local = False
+ else:
+ tests_tree = NoVCSTree(tests_root, url_base)
+ remove_missing_local = not ignore_local
+
+ if not ignore_local:
+ local_changes = tests_tree.local_changes()
+ else:
+ local_changes = None
+
+ manifest.update(tests_root,
+ url_base,
+ tests_tree.current_rev(),
+ tests_tree.committed_changes(manifest.rev),
+ local_changes,
+ remove_missing_local=remove_missing_local)
+
+
+def update_from_cli(**kwargs):
+ tests_root = kwargs["tests_root"]
+ path = kwargs["path"]
+ assert tests_root is not None
+
+ m = None
+ logger = get_logger()
+
+ if not kwargs.get("rebuild", False):
+ try:
+ m = manifest.load(tests_root, path)
+ except manifest.ManifestVersionMismatch:
+ logger.info("Manifest version changed, rebuilding")
+ m = None
+ else:
+ logger.info("Updating manifest")
+
+ if m is None:
+ m = manifest.Manifest(None)
+
+
+ update(tests_root,
+ kwargs["url_base"],
+ m,
+ ignore_local=kwargs.get("ignore_local", False))
+ manifest.write(m, path)
+
+
+def abs_path(path):
+ return os.path.abspath(os.path.expanduser(path))
+
+
+def create_parser():
+ parser = argparse.ArgumentParser()
+ parser.add_argument(
+ "-p", "--path", type=abs_path, help="Path to manifest file.")
+ parser.add_argument(
+ "--tests-root", type=abs_path, help="Path to root of tests.")
+ parser.add_argument(
+ "-r", "--rebuild", action="store_true", default=False,
+ help="Force a full rebuild of the manifest.")
+ parser.add_argument(
+ "--ignore-local", action="store_true", default=False,
+ help="Don't include uncommitted local changes in the manifest.")
+ parser.add_argument(
+ "--url-base", action="store", default="/",
+ help="Base url to use as the mount point for tests in this manifest.")
+ return parser
+
+
+def main():
+ opts = create_parser().parse_args()
+
+ if opts.tests_root is None:
+ opts.tests_root = vcs.get_repo_root()
+
+ if opts.path is None:
+ opts.path = os.path.join(opts.tests_root, "MANIFEST.json")
+
+ update_from_cli(**vars(opts))
+
+
+if __name__ == "__main__":
+ main()
diff --git a/tests/wpt/web-platform-tests/tools/manifest/utils.py b/tests/wpt/web-platform-tests/tools/manifest/utils.py
new file mode 100644
index 00000000000..cdd274c9b47
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/manifest/utils.py
@@ -0,0 +1,43 @@
+import os
+import urlparse
+from StringIO import StringIO
+
+blacklist = ["/", "/tools/", "/resources/", "/common/", "/conformance-checkers/", "_certs"]
+
+def rel_path_to_url(rel_path, url_base="/"):
+ assert not os.path.isabs(rel_path)
+ if url_base[0] != "/":
+ url_base = "/" + url_base
+ if url_base[-1] != "/":
+ url_base += "/"
+ return url_base + rel_path.replace(os.sep, "/")
+
+def is_blacklisted(url):
+ for item in blacklist:
+ if item == "/":
+ if "/" not in url[1:]:
+ return True
+ elif url.startswith(item):
+ return True
+ return False
+
+class ContextManagerStringIO(StringIO):
+ def __enter__(self):
+ return self
+
+ def __exit__(self, *args, **kwargs):
+ self.close()
+
+class cached_property(object):
+ def __init__(self, func):
+ self.func = func
+ self.__doc__ = getattr(func, "__doc__")
+ self.name = func.__name__
+
+ def __get__(self, obj, cls=None):
+ if obj is None:
+ return self
+
+ if self.name not in obj.__dict__:
+ obj.__dict__[self.name] = self.func(obj)
+ return obj.__dict__[self.name]
diff --git a/tests/wpt/web-platform-tests/tools/manifest/vcs.py b/tests/wpt/web-platform-tests/tools/manifest/vcs.py
new file mode 100644
index 00000000000..7bf37949208
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/manifest/vcs.py
@@ -0,0 +1,21 @@
+import os
+import subprocess
+
+def get_git_func(repo_path):
+ def git(cmd, *args):
+ full_cmd = ["git", cmd] + list(args)
+ return subprocess.check_output(full_cmd, cwd=repo_path, stderr=subprocess.STDOUT)
+ return git
+
+
+def is_git_repo(tests_root):
+ return os.path.exists(os.path.join(tests_root, ".git"))
+
+
+_repo_root = None
+def get_repo_root():
+ global _repo_root
+ if _repo_root is None:
+ git = get_git_func(os.path.dirname(__file__))
+ _repo_root = git("rev-parse", "--show-toplevel").rstrip()
+ return _repo_root
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/COPYING b/tests/wpt/web-platform-tests/tools/pywebsocket/src/COPYING
new file mode 100644
index 00000000000..989d02e4cd0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/COPYING
@@ -0,0 +1,28 @@
+Copyright 2012, Google Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/MANIFEST.in b/tests/wpt/web-platform-tests/tools/pywebsocket/src/MANIFEST.in
new file mode 100644
index 00000000000..19256882c56
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/MANIFEST.in
@@ -0,0 +1,6 @@
+include COPYING
+include MANIFEST.in
+include README
+recursive-include example *.py
+recursive-include mod_pywebsocket *.py
+recursive-include test *.py
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/README b/tests/wpt/web-platform-tests/tools/pywebsocket/src/README
new file mode 100644
index 00000000000..c8c758f5eef
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/README
@@ -0,0 +1,17 @@
+INSTALL
+
+To install this package to the system, run this:
+$ python setup.py build
+$ sudo python setup.py install
+
+To install this package as a normal user, run this instead:
+$ python setup.py build
+$ python setup.py install --user
+
+LAUNCH
+
+To use pywebsocket as Apache module, run this to read the document:
+$ pydoc mod_pywebsocket
+
+To use pywebsocket as standalone server, run this to read the document:
+$ pydoc mod_pywebsocket.standalone
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/abort_handshake_wsh.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/abort_handshake_wsh.py
new file mode 100644
index 00000000000..008023a1fe9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/abort_handshake_wsh.py
@@ -0,0 +1,43 @@
+# Copyright 2012, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+from mod_pywebsocket import handshake
+
+
+def web_socket_do_extra_handshake(request):
+ raise handshake.AbortedByUserException(
+ "Aborted in web_socket_do_extra_handshake")
+
+
+def web_socket_transfer_data(request):
+ pass
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/abort_wsh.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/abort_wsh.py
new file mode 100644
index 00000000000..2bbf005f6a3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/abort_wsh.py
@@ -0,0 +1,43 @@
+# Copyright 2012, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+from mod_pywebsocket import handshake
+
+
+def web_socket_do_extra_handshake(request):
+ pass
+
+
+def web_socket_transfer_data(request):
+ raise handshake.AbortedByUserException(
+ "Aborted in web_socket_transfer_data")
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/arraybuffer_benchmark.html b/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/arraybuffer_benchmark.html
new file mode 100644
index 00000000000..869cd7e1ee6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/arraybuffer_benchmark.html
@@ -0,0 +1,134 @@
+<!--
+Copyright 2013, Google Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+
+<html>
+<head>
+<title>ArrayBuffer benchmark</title>
+<script src="util.js"></script>
+<script>
+var PRINT_SIZE = true;
+
+// Initial size of arrays.
+var START_SIZE = 10 * 1024;
+// Stops benchmark when the size of an array exceeds this threshold.
+var STOP_THRESHOLD = 100000 * 1024;
+// If the size of each array is small, write/read the array multiple times
+// until the sum of sizes reaches this threshold.
+var MIN_TOTAL = 100000 * 1024;
+var MULTIPLIERS = [5, 2];
+
+// Repeat benchmark for several times to measure performance of optimized
+// (such as JIT) run.
+var REPEAT_FOR_WARMUP = 3;
+
+function writeBenchmark(size, minTotal) {
+ var totalSize = 0;
+ while (totalSize < minTotal) {
+ var arrayBuffer = new ArrayBuffer(size);
+
+ // Write 'a's.
+ fillArrayBuffer(arrayBuffer, 0x61);
+
+ totalSize += size;
+ }
+ return totalSize;
+}
+
+function readBenchmark(size, minTotal) {
+ var totalSize = 0;
+ while (totalSize < minTotal) {
+ var arrayBuffer = new ArrayBuffer(size);
+
+ if (!verifyArrayBuffer(arrayBuffer, 0x00)) {
+ queueLog('Verification failed');
+ return -1;
+ }
+
+ totalSize += size;
+ }
+ return totalSize;
+}
+
+function runBenchmark(benchmarkFunction,
+ size,
+ stopThreshold,
+ minTotal,
+ multipliers,
+ multiplierIndex) {
+ while (size <= stopThreshold) {
+ var maxSpeed = 0;
+
+ for (var i = 0; i < REPEAT_FOR_WARMUP; ++i) {
+ var startTimeInMs = getTimeStamp();
+
+ var totalSize = benchmarkFunction(size, minTotal);
+
+ maxSpeed = Math.max(maxSpeed,
+ calculateSpeedInKB(totalSize, startTimeInMs));
+ }
+ queueLog(formatResultInKiB(size, maxSpeed, PRINT_SIZE));
+
+ size *= multipliers[multiplierIndex];
+ multiplierIndex = (multiplierIndex + 1) % multipliers.length;
+ }
+}
+
+function runBenchmarks() {
+ queueLog('Message size in KiB, Speed in kB/s');
+
+ queueLog('Write benchmark');
+ runBenchmark(
+ writeBenchmark, START_SIZE, STOP_THRESHOLD, MIN_TOTAL, MULTIPLIERS, 0);
+ queueLog('Finished');
+
+ queueLog('Read benchmark');
+ runBenchmark(
+ readBenchmark, START_SIZE, STOP_THRESHOLD, MIN_TOTAL, MULTIPLIERS, 0);
+ addToLog('Finished');
+}
+
+function init() {
+ logBox = document.getElementById('log');
+
+ queueLog(window.navigator.userAgent.toLowerCase());
+
+ addToLog('Started...');
+
+ setTimeout(runBenchmarks, 0);
+}
+
+</script>
+</head>
+<body onload="init()">
+<textarea
+ id="log" rows="50" style="width: 100%" readonly></textarea>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/bench_wsh.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/bench_wsh.py
new file mode 100644
index 00000000000..5067ca7d895
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/bench_wsh.py
@@ -0,0 +1,60 @@
+# Copyright 2011, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+"""A simple load tester for WebSocket clients.
+
+A client program sends a message formatted as "<time> <count> <message>" to
+this handler. This handler starts sending total <count> WebSocket messages
+containing <message> every <time> seconds. <time> can be a floating point
+value. <count> must be an integer value.
+"""
+
+
+import time
+
+
+def web_socket_do_extra_handshake(request):
+ pass # Always accept.
+
+
+def web_socket_transfer_data(request):
+ line = request.ws_stream.receive_message()
+ parts = line.split(' ')
+ if len(parts) != 3:
+ raise ValueError('Bad parameter format')
+ wait = float(parts[0])
+ count = int(parts[1])
+ message = parts[2]
+ for i in xrange(count):
+ request.ws_stream.send_message(message)
+ time.sleep(wait)
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/benchmark.html b/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/benchmark.html
new file mode 100644
index 00000000000..3a218173a0f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/benchmark.html
@@ -0,0 +1,203 @@
+<!--
+Copyright 2013, Google Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+
+<html>
+<head>
+<title>WebSocket benchmark</title>
+<script src="util_main.js"></script>
+<script src="util.js"></script>
+<script src="benchmark.js"></script>
+<script>
+var addressBox = null;
+
+function getConfig() {
+ return {
+ prefixUrl: addressBox.value,
+ printSize: getBoolFromCheckBox('printsize'),
+ numSockets: getIntFromInput('numsockets'),
+ // Initial size of messages.
+ numIterations: getIntFromInput('numiterations'),
+ numWarmUpIterations: getIntFromInput('numwarmupiterations'),
+ startSize: getIntFromInput('startsize'),
+ // Stops benchmark when the size of message exceeds this threshold.
+ stopThreshold: getIntFromInput('stopthreshold'),
+ // If the size of each message is small, send/receive multiple messages
+ // until the sum of sizes reaches this threshold.
+ minTotal: getIntFromInput('mintotal'),
+ multipliers: getIntArrayFromInput('multipliers'),
+ verifyData: getBoolFromCheckBox('verifydata')
+ };
+}
+
+var worker = new Worker('benchmark.js');
+worker.onmessage = onMessage;
+
+function onSendBenchmark() {
+ var config = getConfig();
+
+ if (getBoolFromCheckBox('worker')) {
+ worker.postMessage({type: 'sendBenchmark', config: config});
+ } else {
+ config.addToLog = addToLog;
+ config.addToSummary = addToSummary;
+ config.measureValue = measureValue;
+ sendBenchmark(config);
+ }
+}
+
+function onReceiveBenchmark() {
+ var config = getConfig();
+
+ if (getBoolFromCheckBox('worker')) {
+ worker.postMessage({type: 'receiveBenchmark', config: config});
+ } else {
+ config.addToLog = addToLog;
+ config.addToSummary = addToSummary;
+ config.measureValue = measureValue;
+ receiveBenchmark(config);
+ }
+}
+
+function onBatchBenchmark() {
+ var config = getConfig();
+
+ if (getBoolFromCheckBox('worker')) {
+ worker.postMessage({type: 'batchBenchmark', config: config});
+ } else {
+ config.addToLog = addToLog;
+ config.addToSummary = addToSummary;
+ config.measureValue = measureValue;
+ batchBenchmark(config);
+ }
+}
+
+function onStop() {
+ var config = getConfig();
+
+ if (getBoolFromCheckBox('worker')) {
+ worker.postMessage({type: 'stop', config: config});
+ } else {
+ config.addToLog = addToLog;
+ config.addToSummary = addToSummary;
+ config.measureValue = measureValue;
+ stop(config);
+ }
+}
+function init() {
+ addressBox = document.getElementById('address');
+ logBox = document.getElementById('log');
+
+ summaryBox = document.getElementById('summary');
+
+ var scheme = window.location.protocol == 'https:' ? 'wss://' : 'ws://';
+ var defaultAddress = scheme + window.location.host + '/benchmark_helper';
+
+ addressBox.value = defaultAddress;
+
+ addToLog(window.navigator.userAgent.toLowerCase());
+ addToSummary(window.navigator.userAgent.toLowerCase());
+
+ if (!('WebSocket' in window)) {
+ addToLog('WebSocket is not available');
+ }
+}
+</script>
+</head>
+<body onload="init()">
+
+<div id="benchmark_div">
+ url <input type="text" id="address" size="40">
+ <input type="button" value="send" onclick="onSendBenchmark()">
+ <input type="button" value="receive" onclick="onReceiveBenchmark()">
+ <input type="button" value="batch" onclick="onBatchBenchmark()">
+ <input type="button" value="stop" onclick="onStop()">
+
+ <br/>
+
+ <input type="checkbox" id="printsize" checked>
+ <label for="printsize">Print size and time per message</label>
+ <input type="checkbox" id="verifydata" checked>
+ <label for="verifydata">Verify data</label>
+ <input type="checkbox" id="worker">
+ <label for="worker">Run on worker</label>
+
+ <br/>
+
+ Parameters:
+
+ <br/>
+
+ <table>
+ <tr>
+ <td>Num sockets</td>
+ <td><input type="text" id="numsockets" value="1"></td>
+ </tr>
+ <tr>
+ <td>Number of iterations</td>
+ <td><input type="text" id="numiterations" value="1"></td>
+ </tr>
+ <tr>
+ <td>Number of warm-up iterations</td>
+ <td><input type="text" id="numwarmupiterations" value="0"></td>
+ </tr>
+ <tr>
+ <td>Start size</td>
+ <td><input type="text" id="startsize" value="10240"></td>
+ </tr>
+ <tr>
+ <td>Stop threshold</td>
+ <td><input type="text" id="stopthreshold" value="102400000"></td>
+ </tr>
+ <tr>
+ <td>Minimum total</td>
+ <td><input type="text" id="mintotal" value="102400000"></td>
+ </tr>
+ <tr>
+ <td>Multipliers</td>
+ <td><input type="text" id="multipliers" value="5, 2"></td>
+ </tr>
+ </table>
+</div>
+
+<div id="log_div">
+ <textarea
+ id="log" rows="20" style="width: 100%" readonly></textarea>
+</div>
+<div id="summary_div">
+ Summary
+ <textarea
+ id="summary" rows="20" style="width: 100%" readonly></textarea>
+</div>
+
+Note: Effect of RTT is not eliminated.
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/benchmark.js b/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/benchmark.js
new file mode 100644
index 00000000000..d347ae9e13d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/benchmark.js
@@ -0,0 +1,309 @@
+// Copyright 2014 Google Inc. All rights reserved.
+//
+// Use of this source code is governed by a BSD-style
+// license that can be found in the COPYING file or at
+// https://developers.google.com/open-source/licenses/bsd
+
+if (typeof importScripts !== "undefined") {
+ // Running on a worker
+ importScripts('util.js', 'util_worker.js');
+}
+
+// Namespace for holding globals.
+var benchmark = {startTimeInMs: 0};
+
+var sockets = [];
+var numEstablishedSockets = 0;
+
+var timerID = null;
+
+function destroySocket(socket) {
+ socket.onopen = null;
+ socket.onmessage = null;
+ socket.onerror = null;
+ socket.onclose = null;
+ socket.close();
+}
+
+function destroyAllSockets() {
+ for (var i = 0; i < sockets.length; ++i) {
+ destroySocket(sockets[i]);
+ }
+ sockets = [];
+}
+
+function sendBenchmarkStep(size, config) {
+ timerID = null;
+
+ var totalSize = 0;
+ var totalReplied = 0;
+
+ var onMessageHandler = function(event) {
+ if (!verifyAcknowledgement(config, event.data, size)) {
+ destroyAllSockets();
+ return;
+ }
+
+ totalReplied += size;
+
+ if (totalReplied < totalSize) {
+ return;
+ }
+
+ calculateAndLogResult(config, size, benchmark.startTimeInMs, totalSize);
+
+ runNextTask(config);
+ };
+
+ for (var i = 0; i < sockets.length; ++i) {
+ var socket = sockets[i];
+ socket.onmessage = onMessageHandler;
+ }
+
+ var dataArray = [];
+
+ while (totalSize < config.minTotal) {
+ var buffer = new ArrayBuffer(size);
+
+ fillArrayBuffer(buffer, 0x61);
+
+ dataArray.push(buffer);
+ totalSize += size;
+ }
+
+ benchmark.startTimeInMs = getTimeStamp();
+
+ totalSize = 0;
+
+ var socketIndex = 0;
+ var dataIndex = 0;
+ while (totalSize < config.minTotal) {
+ var command = ['send'];
+ command.push(config.verifyData ? '1' : '0');
+ sockets[socketIndex].send(command.join(' '));
+ sockets[socketIndex].send(dataArray[dataIndex]);
+ socketIndex = (socketIndex + 1) % sockets.length;
+
+ totalSize += size;
+ ++dataIndex;
+ }
+}
+
+function receiveBenchmarkStep(size, config) {
+ timerID = null;
+
+ var totalSize = 0;
+ var totalReplied = 0;
+
+ var onMessageHandler = function(event) {
+ var bytesReceived = event.data.byteLength;
+ if (bytesReceived != size) {
+ config.addToLog('Expected ' + size + 'B but received ' +
+ bytesReceived + 'B');
+ destroyAllSockets();
+ return;
+ }
+
+ if (config.verifyData && !verifyArrayBuffer(event.data, 0x61)) {
+ config.addToLog('Response verification failed');
+ destroyAllSockets();
+ return;
+ }
+
+ totalReplied += bytesReceived;
+
+ if (totalReplied < totalSize) {
+ return;
+ }
+
+ calculateAndLogResult(config, size, benchmark.startTimeInMs, totalSize);
+
+ runNextTask(config);
+ };
+
+ for (var i = 0; i < sockets.length; ++i) {
+ var socket = sockets[i];
+ socket.binaryType = 'arraybuffer';
+ socket.onmessage = onMessageHandler;
+ }
+
+ benchmark.startTimeInMs = getTimeStamp();
+
+ var socketIndex = 0;
+ while (totalSize < config.minTotal) {
+ sockets[socketIndex].send('receive ' + size);
+ socketIndex = (socketIndex + 1) % sockets.length;
+
+ totalSize += size;
+ }
+}
+
+function createSocket(config) {
+ // TODO(tyoshino): Add TCP warm up.
+ var url = config.prefixUrl;
+
+ config.addToLog('Connect ' + url);
+
+ var socket = new WebSocket(url);
+ socket.onmessage = function(event) {
+ config.addToLog('Unexpected message received. Aborting.');
+ };
+ socket.onerror = function() {
+ config.addToLog('Error');
+ };
+ socket.onclose = function(event) {
+ config.addToLog('Closed');
+ };
+ return socket;
+}
+
+var tasks = [];
+
+function startBenchmark(config) {
+ clearTimeout(timerID);
+ destroyAllSockets();
+
+ numEstablishedSockets = 0;
+
+ for (var i = 0; i < config.numSockets; ++i) {
+ var socket = createSocket(config);
+ socket.onopen = function() {
+ config.addToLog('Opened');
+
+ ++numEstablishedSockets;
+
+ if (numEstablishedSockets == sockets.length) {
+ runNextTask(config);
+ }
+ };
+ sockets.push(socket);
+ }
+}
+
+function runNextTask(config) {
+ var task = tasks.shift();
+ if (task == undefined) {
+ config.addToLog('Finished');
+ destroyAllSockets();
+ return;
+ }
+ timerID = setTimeout(task, 0);
+}
+
+function buildLegendString(config) {
+ var legend = ''
+ if (config.printSize)
+ legend = 'Message size in KiB, Time/message in ms, ';
+ legend += 'Speed in kB/s';
+ return legend;
+}
+
+function getConfigString(config) {
+ return '(WebSocket' +
+ ', ' + (typeof importScripts !== "undefined" ? 'Worker' : 'Main') +
+ ', numSockets=' + config.numSockets +
+ ', numIterations=' + config.numIterations +
+ ', verifyData=' + config.verifyData +
+ ', minTotal=' + config.minTotal +
+ ', numWarmUpIterations=' + config.numWarmUpIterations +
+ ')';
+}
+
+function addTasks(config, stepFunc) {
+ for (var i = 0;
+ i < config.numWarmUpIterations + config.numIterations; ++i) {
+ // Ignore the first |config.numWarmUpIterations| iterations.
+ if (i == config.numWarmUpIterations)
+ addResultClearingTask(config);
+
+ var multiplierIndex = 0;
+ for (var size = config.startSize;
+ size <= config.stopThreshold;
+ ++multiplierIndex) {
+ var task = stepFunc.bind(
+ null,
+ size,
+ config);
+ tasks.push(task);
+ size *= config.multipliers[
+ multiplierIndex % config.multipliers.length];
+ }
+ }
+}
+
+function addResultReportingTask(config, title) {
+ tasks.push(function(){
+ timerID = null;
+ config.addToSummary(title);
+ reportAverageData(config);
+ clearAverageData();
+ runNextTask(config);
+ });
+}
+
+function addResultClearingTask(config) {
+ tasks.push(function(){
+ timerID = null;
+ clearAverageData();
+ runNextTask(config);
+ });
+}
+
+function sendBenchmark(config) {
+ config.addToLog('Send benchmark');
+ config.addToLog(buildLegendString(config));
+
+ tasks = [];
+ clearAverageData();
+ addTasks(config, sendBenchmarkStep);
+ addResultReportingTask(config, 'Send Benchmark ' + getConfigString(config));
+ startBenchmark(config);
+}
+
+function receiveBenchmark(config) {
+ config.addToLog('Receive benchmark');
+ config.addToLog(buildLegendString(config));
+
+ tasks = [];
+ clearAverageData();
+ addTasks(config, receiveBenchmarkStep);
+ addResultReportingTask(config,
+ 'Receive Benchmark ' + getConfigString(config));
+ startBenchmark(config);
+}
+
+function batchBenchmark(config) {
+ config.addToLog('Batch benchmark');
+ config.addToLog(buildLegendString(config));
+
+ tasks = [];
+ clearAverageData();
+ addTasks(config, sendBenchmarkStep);
+ addResultReportingTask(config, 'Send Benchmark ' + getConfigString(config));
+ addTasks(config, receiveBenchmarkStep);
+ addResultReportingTask(config, 'Receive Benchmark ' +
+ getConfigString(config));
+ startBenchmark(config);
+}
+
+function stop(config) {
+ clearTimeout(timerID);
+ timerID = null;
+ config.addToLog('Stopped');
+ destroyAllSockets();
+}
+
+onmessage = function (message) {
+ var config = message.data.config;
+ config.addToLog = workerAddToLog;
+ config.addToSummary = workerAddToSummary;
+ config.measureValue = workerMeasureValue;
+ if (message.data.type === 'sendBenchmark')
+ sendBenchmark(config);
+ else if (message.data.type === 'receiveBenchmark')
+ receiveBenchmark(config);
+ else if (message.data.type === 'batchBenchmark')
+ batchBenchmark(config);
+ else if (message.data.type === 'stop')
+ stop(config);
+};
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/benchmark_helper_wsh.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/benchmark_helper_wsh.py
new file mode 100644
index 00000000000..44ad0bfeefc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/benchmark_helper_wsh.py
@@ -0,0 +1,85 @@
+# Copyright 2013, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+"""Handler for benchmark.html."""
+
+
+def web_socket_do_extra_handshake(request):
+ # Turn off compression.
+ request.ws_extension_processors = []
+
+
+def web_socket_transfer_data(request):
+ data = ''
+
+ while True:
+ command = request.ws_stream.receive_message()
+ if command is None:
+ return
+
+ if not isinstance(command, unicode):
+ raise ValueError('Invalid command data:' + command)
+ commands = command.split(' ')
+ if len(commands) == 0:
+ raise ValueError('Invalid command data: ' + command)
+
+ if commands[0] == 'receive':
+ if len(commands) != 2:
+ raise ValueError(
+ 'Illegal number of arguments for send command' +
+ command)
+ size = int(commands[1])
+
+ # Reuse data if possible.
+ if len(data) != size:
+ data = 'a' * size
+ request.ws_stream.send_message(data, binary=True)
+ elif commands[0] == 'send':
+ if len(commands) != 2:
+ raise ValueError(
+ 'Illegal number of arguments for receive command' +
+ command)
+ verify_data = commands[1] == '1'
+
+ data = request.ws_stream.receive_message()
+ if data is None:
+ raise ValueError('Payload not received')
+ size = len(data)
+
+ if verify_data:
+ if data != 'a' * size:
+ raise ValueError('Payload verification failed')
+
+ request.ws_stream.send_message(str(size))
+ else:
+ raise ValueError('Invalid command: ' + commands[0])
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/close_wsh.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/close_wsh.py
new file mode 100644
index 00000000000..26b08384081
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/close_wsh.py
@@ -0,0 +1,69 @@
+# Copyright 2012, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import struct
+
+from mod_pywebsocket import common
+from mod_pywebsocket import stream
+
+
+def web_socket_do_extra_handshake(request):
+ pass
+
+
+def web_socket_transfer_data(request):
+ while True:
+ line = request.ws_stream.receive_message()
+ if line is None:
+ return
+ code, reason = line.split(' ', 1)
+ if code is None or reason is None:
+ return
+ request.ws_stream.close_connection(int(code), reason)
+ # close_connection() initiates closing handshake. It validates code
+ # and reason. If you want to send a broken close frame for a test,
+ # following code will be useful.
+ # > data = struct.pack('!H', int(code)) + reason.encode('UTF-8')
+ # > request.connection.write(stream.create_close_frame(data))
+ # > # Suppress to re-respond client responding close frame.
+ # > raise Exception("customized server initiated closing handshake")
+
+
+def web_socket_passive_closing_handshake(request):
+ # Simply echo a close status code
+ code, reason = request.ws_close_code, request.ws_close_reason
+
+ # pywebsocket sets pseudo code for receiving an empty body close frame.
+ if code == common.STATUS_NO_STATUS_RECEIVED:
+ code = None
+ reason = ''
+ return code, reason
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/console.html b/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/console.html
new file mode 100644
index 00000000000..ccd6d8f8067
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/console.html
@@ -0,0 +1,317 @@
+<!--
+Copyright 2011, Google Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+
+<!--
+A simple console for testing WebSocket server.
+
+Type an address into the top text input and click connect to establish
+WebSocket. Then, type some message into the bottom text input and click send
+to send the message. Received/sent messages and connection state will be shown
+on the middle textarea.
+-->
+
+<html>
+<head>
+<title>WebSocket console</title>
+<script>
+var socket = null;
+
+var showTimeStamp = false;
+
+var addressBox = null;
+var protocolsBox = null;
+var logBox = null;
+var messageBox = null;
+var fileBox = null;
+var codeBox = null;
+var reasonBox = null;
+
+function getTimeStamp() {
+ return new Date().getTime();
+}
+
+function addToLog(log) {
+ if (showTimeStamp) {
+ logBox.value += '[' + getTimeStamp() + '] ';
+ }
+ logBox.value += log + '\n'
+ // Large enough to keep showing the latest message.
+ logBox.scrollTop = 1000000;
+}
+
+function setbinarytype(binaryType) {
+ if (!socket) {
+ addToLog('Not connected');
+ return;
+ }
+
+ socket.binaryType = binaryType;
+ addToLog('Set binaryType to ' + binaryType);
+}
+
+function send() {
+ if (!socket) {
+ addToLog('Not connected');
+ return;
+ }
+
+ socket.send(messageBox.value);
+ addToLog('> ' + messageBox.value);
+ messageBox.value = '';
+}
+
+function sendfile() {
+ if (!socket) {
+ addToLog('Not connected');
+ return;
+ }
+
+ var files = fileBox.files;
+
+ if (files.length == 0) {
+ addToLog('File not selected');
+ return;
+ }
+
+ socket.send(files[0]);
+ addToLog('> Send ' + files[0].name);
+}
+
+function parseProtocols(protocolsText) {
+ var protocols = protocolsText.split(',');
+ for (var i = 0; i < protocols.length; ++i) {
+ protocols[i] = protocols[i].trim();
+ }
+
+ if (protocols.length == 0) {
+ // Don't pass.
+ protocols = null;
+ } else if (protocols.length == 1) {
+ if (protocols[0].length == 0) {
+ // Don't pass.
+ protocols = null;
+ } else {
+ // Pass as a string.
+ protocols = protocols[0];
+ }
+ }
+
+ return protocols;
+}
+
+function connect() {
+ var url = addressBox.value;
+ var protocols = parseProtocols(protocolsBox.value);
+
+ if ('WebSocket' in window) {
+ if (protocols) {
+ socket = new WebSocket(url, protocols);
+ } else {
+ socket = new WebSocket(url);
+ }
+ } else {
+ return;
+ }
+
+ socket.onopen = function () {
+ var extraInfo = [];
+ if (('protocol' in socket) && socket.protocol) {
+ extraInfo.push('protocol = ' + socket.protocol);
+ }
+ if (('extensions' in socket) && socket.extensions) {
+ extraInfo.push('extensions = ' + socket.extensions);
+ }
+
+ var logMessage = 'Opened';
+ if (extraInfo.length > 0) {
+ logMessage += ' (' + extraInfo.join(', ') + ')';
+ }
+ addToLog(logMessage);
+ };
+ socket.onmessage = function (event) {
+ if (('ArrayBuffer' in window) && (event.data instanceof ArrayBuffer)) {
+ addToLog('< Received an ArrayBuffer of ' + event.data.byteLength +
+ ' bytes')
+ } else if (('Blob' in window) && (event.data instanceof Blob)) {
+ addToLog('< Received a Blob of ' + event.data.size + ' bytes')
+ } else {
+ addToLog('< ' + event.data);
+ }
+ };
+ socket.onerror = function () {
+ addToLog('Error');
+ };
+ socket.onclose = function (event) {
+ var logMessage = 'Closed (';
+ if ((arguments.length == 1) && ('CloseEvent' in window) &&
+ (event instanceof CloseEvent)) {
+ logMessage += 'wasClean = ' + event.wasClean;
+ // code and reason are present only for
+ // draft-ietf-hybi-thewebsocketprotocol-06 and later
+ if ('code' in event) {
+ logMessage += ', code = ' + event.code;
+ }
+ if ('reason' in event) {
+ logMessage += ', reason = ' + event.reason;
+ }
+ } else {
+ logMessage += 'CloseEvent is not available';
+ }
+ addToLog(logMessage + ')');
+ };
+
+ if (protocols) {
+ addToLog('Connect ' + url + ' (protocols = ' + protocols + ')');
+ } else {
+ addToLog('Connect ' + url);
+ }
+}
+
+function closeSocket() {
+ if (!socket) {
+ addToLog('Not connected');
+ return;
+ }
+
+ if (codeBox.value || reasonBox.value) {
+ socket.close(codeBox.value, reasonBox.value);
+ } else {
+ socket.close();
+ }
+}
+
+function printState() {
+ if (!socket) {
+ addToLog('Not connected');
+ return;
+ }
+
+ addToLog(
+ 'url = ' + socket.url +
+ ', readyState = ' + socket.readyState +
+ ', bufferedAmount = ' + socket.bufferedAmount);
+}
+
+function init() {
+ var scheme = window.location.protocol == 'https:' ? 'wss://' : 'ws://';
+ var defaultAddress = scheme + window.location.host + '/echo';
+
+ addressBox = document.getElementById('address');
+ protocolsBox = document.getElementById('protocols');
+ logBox = document.getElementById('log');
+ messageBox = document.getElementById('message');
+ fileBox = document.getElementById('file');
+ codeBox = document.getElementById('code');
+ reasonBox = document.getElementById('reason');
+
+ addressBox.value = defaultAddress;
+
+ if (!('WebSocket' in window)) {
+ addToLog('WebSocket is not available');
+ }
+}
+</script>
+<style type="text/css">
+form {
+ margin: 0px;
+}
+
+#connect_div, #log_div, #send_div, #sendfile_div, #close_div, #printstate_div {
+ padding: 5px;
+ margin: 5px;
+ border-width: 0px 0px 0px 10px;
+ border-style: solid;
+ border-color: silver;
+}
+</style>
+</head>
+<body onload="init()">
+
+<div>
+
+<div id="connect_div">
+ <form action="#" onsubmit="connect(); return false;">
+ url <input type="text" id="address" size="40">
+ <input type="submit" value="connect">
+ <br/>
+ protocols <input type="text" id="protocols" size="20">
+ </form>
+</div>
+
+<div id="log_div">
+ <textarea id="log" rows="10" cols="40" readonly></textarea>
+ <br/>
+ <input type="checkbox"
+ name="showtimestamp"
+ value="showtimestamp"
+ onclick="showTimeStamp = this.checked">Show time stamp
+</div>
+
+<div id="send_div">
+ <form action="#" onsubmit="send(); return false;">
+ data <input type="text" id="message" size="40">
+ <input type="submit" value="send">
+ </form>
+</div>
+
+<div id="sendfile_div">
+ <form action="#" onsubmit="sendfile(); return false;">
+ <input type="file" id="file" size="40">
+ <input type="submit" value="send file">
+ </form>
+
+ Set binaryType
+ <input type="radio"
+ name="binarytype"
+ value="blob"
+ onclick="setbinarytype('blob')" checked>blob
+ <input type="radio"
+ name="binarytype"
+ value="arraybuffer"
+ onclick="setbinarytype('arraybuffer')">arraybuffer
+</div>
+
+<div id="close_div">
+ <form action="#" onsubmit="closeSocket(); return false;">
+ code <input type="text" id="code" size="10">
+ reason <input type="text" id="reason" size="20">
+ <input type="submit" value="close">
+ </form>
+</div>
+
+<div id="printstate_div">
+ <input type="button" value="print state" onclick="printState();">
+</div>
+
+</div>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/cookie_wsh.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/cookie_wsh.py
new file mode 100644
index 00000000000..8b327152e70
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/cookie_wsh.py
@@ -0,0 +1,32 @@
+# Copyright 2014 Google Inc. All rights reserved.
+#
+# Use of this source code is governed by a BSD-style
+# license that can be found in the COPYING file or at
+# https://developers.google.com/open-source/licenses/bsd
+
+
+import urlparse
+
+
+def _add_set_cookie(request, value):
+ request.extra_headers.append(('Set-Cookie', value))
+
+
+def web_socket_do_extra_handshake(request):
+ components = urlparse.urlparse(request.uri)
+ command = components[4]
+
+ ONE_DAY_LIFE = 'Max-Age=86400'
+
+ if command == 'set':
+ _add_set_cookie(request, '; '.join(['foo=bar', ONE_DAY_LIFE]))
+ elif command == 'set_httponly':
+ _add_set_cookie(request,
+ '; '.join(['httpOnlyFoo=bar', ONE_DAY_LIFE, 'httpOnly']))
+ elif command == 'clear':
+ _add_set_cookie(request, 'foo=0; Max-Age=0')
+ _add_set_cookie(request, 'httpOnlyFoo=0; Max-Age=0')
+
+
+def web_socket_transfer_data(request):
+ pass
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/echo_client.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/echo_client.py
new file mode 100755
index 00000000000..943ce64e8b8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/echo_client.py
@@ -0,0 +1,1128 @@
+#!/usr/bin/env python
+#
+# Copyright 2011, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+"""Simple WebSocket client named echo_client just because of historical reason.
+
+mod_pywebsocket directory must be in PYTHONPATH.
+
+Example Usage:
+
+# server setup
+ % cd $pywebsocket
+ % PYTHONPATH=$cwd/src python ./mod_pywebsocket/standalone.py -p 8880 \
+ -d $cwd/src/example
+
+# run client
+ % PYTHONPATH=$cwd/src python ./src/example/echo_client.py -p 8880 \
+ -s localhost \
+ -o http://localhost -r /echo -m test
+
+or
+
+# run echo client to test IETF HyBi 00 protocol
+ run with --protocol-version=hybi00
+"""
+
+
+import base64
+import codecs
+import logging
+from optparse import OptionParser
+import os
+import random
+import re
+import socket
+import struct
+import sys
+
+from mod_pywebsocket import common
+from mod_pywebsocket.extensions import DeflateFrameExtensionProcessor
+from mod_pywebsocket.extensions import PerMessageDeflateExtensionProcessor
+from mod_pywebsocket.extensions import _PerMessageDeflateFramer
+from mod_pywebsocket.extensions import _parse_window_bits
+from mod_pywebsocket.stream import Stream
+from mod_pywebsocket.stream import StreamHixie75
+from mod_pywebsocket.stream import StreamOptions
+from mod_pywebsocket import util
+
+
+_TIMEOUT_SEC = 10
+_UNDEFINED_PORT = -1
+
+_UPGRADE_HEADER = 'Upgrade: websocket\r\n'
+_UPGRADE_HEADER_HIXIE75 = 'Upgrade: WebSocket\r\n'
+_CONNECTION_HEADER = 'Connection: Upgrade\r\n'
+
+# Special message that tells the echo server to start closing handshake
+_GOODBYE_MESSAGE = 'Goodbye'
+
+_PROTOCOL_VERSION_HYBI13 = 'hybi13'
+_PROTOCOL_VERSION_HYBI08 = 'hybi08'
+_PROTOCOL_VERSION_HYBI00 = 'hybi00'
+_PROTOCOL_VERSION_HIXIE75 = 'hixie75'
+
+# Constants for the --tls_module flag.
+_TLS_BY_STANDARD_MODULE = 'ssl'
+_TLS_BY_PYOPENSSL = 'pyopenssl'
+
+# Values used by the --tls-version flag.
+_TLS_VERSION_SSL23 = 'ssl23'
+_TLS_VERSION_SSL3 = 'ssl3'
+_TLS_VERSION_TLS1 = 'tls1'
+
+
+class ClientHandshakeError(Exception):
+ pass
+
+
+def _build_method_line(resource):
+ return 'GET %s HTTP/1.1\r\n' % resource
+
+
+def _origin_header(header, origin):
+ # 4.1 13. concatenation of the string "Origin:", a U+0020 SPACE character,
+ # and the /origin/ value, converted to ASCII lowercase, to /fields/.
+ return '%s: %s\r\n' % (header, origin.lower())
+
+
+def _format_host_header(host, port, secure):
+ # 4.1 9. Let /hostport/ be an empty string.
+ # 4.1 10. Append the /host/ value, converted to ASCII lowercase, to
+ # /hostport/
+ hostport = host.lower()
+ # 4.1 11. If /secure/ is false, and /port/ is not 80, or if /secure/
+ # is true, and /port/ is not 443, then append a U+003A COLON character
+ # (:) followed by the value of /port/, expressed as a base-ten integer,
+ # to /hostport/
+ if ((not secure and port != common.DEFAULT_WEB_SOCKET_PORT) or
+ (secure and port != common.DEFAULT_WEB_SOCKET_SECURE_PORT)):
+ hostport += ':' + str(port)
+ # 4.1 12. concatenation of the string "Host:", a U+0020 SPACE
+ # character, and /hostport/, to /fields/.
+ return '%s: %s\r\n' % (common.HOST_HEADER, hostport)
+
+
+def _receive_bytes(socket, length):
+ bytes = []
+ remaining = length
+ while remaining > 0:
+ received_bytes = socket.recv(remaining)
+ if not received_bytes:
+ raise IOError(
+ 'Connection closed before receiving requested length '
+ '(requested %d bytes but received only %d bytes)' %
+ (length, length - remaining))
+ bytes.append(received_bytes)
+ remaining -= len(received_bytes)
+ return ''.join(bytes)
+
+
+def _get_mandatory_header(fields, name):
+ """Gets the value of the header specified by name from fields.
+
+ This function expects that there's only one header with the specified name
+ in fields. Otherwise, raises an ClientHandshakeError.
+ """
+
+ values = fields.get(name.lower())
+ if values is None or len(values) == 0:
+ raise ClientHandshakeError(
+ '%s header not found: %r' % (name, values))
+ if len(values) > 1:
+ raise ClientHandshakeError(
+ 'Multiple %s headers found: %r' % (name, values))
+ return values[0]
+
+
+def _validate_mandatory_header(fields, name,
+ expected_value, case_sensitive=False):
+ """Gets and validates the value of the header specified by name from
+ fields.
+
+ If expected_value is specified, compares expected value and actual value
+ and raises an ClientHandshakeError on failure. You can specify case
+ sensitiveness in this comparison by case_sensitive parameter. This function
+ expects that there's only one header with the specified name in fields.
+ Otherwise, raises an ClientHandshakeError.
+ """
+
+ value = _get_mandatory_header(fields, name)
+
+ if ((case_sensitive and value != expected_value) or
+ (not case_sensitive and value.lower() != expected_value.lower())):
+ raise ClientHandshakeError(
+ 'Illegal value for header %s: %r (expected) vs %r (actual)' %
+ (name, expected_value, value))
+
+
+class _TLSSocket(object):
+ """Wrapper for a TLS connection."""
+
+ def __init__(self,
+ raw_socket, tls_module, tls_version, disable_tls_compression):
+ self._logger = util.get_class_logger(self)
+
+ if tls_module == _TLS_BY_STANDARD_MODULE:
+ if tls_version == _TLS_VERSION_SSL23:
+ version = ssl.PROTOCOL_SSLv23
+ elif tls_version == _TLS_VERSION_SSL3:
+ version = ssl.PROTOCOL_SSLv3
+ elif tls_version == _TLS_VERSION_TLS1:
+ version = ssl.PROTOCOL_TLSv1
+ else:
+ raise ValueError(
+ 'Invalid --tls-version flag: %r' % tls_version)
+
+ if disable_tls_compression:
+ raise ValueError(
+ '--disable-tls-compression is not available for ssl '
+ 'module')
+
+ self._tls_socket = ssl.wrap_socket(raw_socket, ssl_version=version)
+
+ # Print cipher in use. Handshake is done on wrap_socket call.
+ self._logger.info("Cipher: %s", self._tls_socket.cipher())
+ elif tls_module == _TLS_BY_PYOPENSSL:
+ if tls_version == _TLS_VERSION_SSL23:
+ version = OpenSSL.SSL.SSLv23_METHOD
+ elif tls_version == _TLS_VERSION_SSL3:
+ version = OpenSSL.SSL.SSLv3_METHOD
+ elif tls_version == _TLS_VERSION_TLS1:
+ version = OpenSSL.SSL.TLSv1_METHOD
+ else:
+ raise ValueError(
+ 'Invalid --tls-version flag: %r' % tls_version)
+
+ context = OpenSSL.SSL.Context(version)
+
+ if disable_tls_compression:
+ # OP_NO_COMPRESSION is not defined in OpenSSL module.
+ context.set_options(0x00020000)
+
+ self._tls_socket = OpenSSL.SSL.Connection(context, raw_socket)
+ # Client mode.
+ self._tls_socket.set_connect_state()
+ self._tls_socket.setblocking(True)
+
+ # Do handshake now (not necessary).
+ self._tls_socket.do_handshake()
+ else:
+ raise ValueError('No TLS support module is available')
+
+ def send(self, data):
+ return self._tls_socket.write(data)
+
+ def sendall(self, data):
+ return self._tls_socket.sendall(data)
+
+ def recv(self, size=-1):
+ return self._tls_socket.read(size)
+
+ def close(self):
+ return self._tls_socket.close()
+
+ def getpeername(self):
+ return self._tls_socket.getpeername()
+
+
+class ClientHandshakeBase(object):
+ """A base class for WebSocket opening handshake processors for each
+ protocol version.
+ """
+
+ def __init__(self):
+ self._logger = util.get_class_logger(self)
+
+ def _read_fields(self):
+ # 4.1 32. let /fields/ be a list of name-value pairs, initially empty.
+ fields = {}
+ while True: # "Field"
+ # 4.1 33. let /name/ and /value/ be empty byte arrays
+ name = ''
+ value = ''
+ # 4.1 34. read /name/
+ name = self._read_name()
+ if name is None:
+ break
+ # 4.1 35. read spaces
+ # TODO(tyoshino): Skip only one space as described in the spec.
+ ch = self._skip_spaces()
+ # 4.1 36. read /value/
+ value = self._read_value(ch)
+ # 4.1 37. read a byte from the server
+ ch = _receive_bytes(self._socket, 1)
+ if ch != '\n': # 0x0A
+ raise ClientHandshakeError(
+ 'Expected LF but found %r while reading value %r for '
+ 'header %r' % (ch, value, name))
+ self._logger.debug('Received %r header', name)
+ # 4.1 38. append an entry to the /fields/ list that has the name
+ # given by the string obtained by interpreting the /name/ byte
+ # array as a UTF-8 stream and the value given by the string
+ # obtained by interpreting the /value/ byte array as a UTF-8 byte
+ # stream.
+ fields.setdefault(name, []).append(value)
+ # 4.1 39. return to the "Field" step above
+ return fields
+
+ def _read_name(self):
+ # 4.1 33. let /name/ be empty byte arrays
+ name = ''
+ while True:
+ # 4.1 34. read a byte from the server
+ ch = _receive_bytes(self._socket, 1)
+ if ch == '\r': # 0x0D
+ return None
+ elif ch == '\n': # 0x0A
+ raise ClientHandshakeError(
+ 'Unexpected LF when reading header name %r' % name)
+ elif ch == ':': # 0x3A
+ return name
+ elif ch >= 'A' and ch <= 'Z': # Range 0x31 to 0x5A
+ ch = chr(ord(ch) + 0x20)
+ name += ch
+ else:
+ name += ch
+
+ def _skip_spaces(self):
+ # 4.1 35. read a byte from the server
+ while True:
+ ch = _receive_bytes(self._socket, 1)
+ if ch == ' ': # 0x20
+ continue
+ return ch
+
+ def _read_value(self, ch):
+ # 4.1 33. let /value/ be empty byte arrays
+ value = ''
+ # 4.1 36. read a byte from server.
+ while True:
+ if ch == '\r': # 0x0D
+ return value
+ elif ch == '\n': # 0x0A
+ raise ClientHandshakeError(
+ 'Unexpected LF when reading header value %r' % value)
+ else:
+ value += ch
+ ch = _receive_bytes(self._socket, 1)
+
+
+def _get_permessage_deflate_framer(extension_response):
+ """Validate the response and return a framer object using the parameters in
+ the response. This method doesn't accept the server_.* parameters.
+ """
+
+ client_max_window_bits = None
+ client_no_context_takeover = None
+
+ client_max_window_bits_name = (
+ PerMessageDeflateExtensionProcessor.
+ _CLIENT_MAX_WINDOW_BITS_PARAM)
+ client_no_context_takeover_name = (
+ PerMessageDeflateExtensionProcessor.
+ _CLIENT_NO_CONTEXT_TAKEOVER_PARAM)
+
+ # We didn't send any server_.* parameter.
+ # Handle those parameters as invalid if found in the response.
+
+ for param_name, param_value in extension_response.get_parameters():
+ if param_name == client_max_window_bits_name:
+ if client_max_window_bits is not None:
+ raise ClientHandshakeError(
+ 'Multiple %s found' % client_max_window_bits_name)
+
+ parsed_value = _parse_window_bits(param_value)
+ if parsed_value is None:
+ raise ClientHandshakeError(
+ 'Bad %s: %r' %
+ (client_max_window_bits_name, param_value))
+ client_max_window_bits = parsed_value
+ elif param_name == client_no_context_takeover_name:
+ if client_no_context_takeover is not None:
+ raise ClientHandshakeError(
+ 'Multiple %s found' % client_no_context_takeover_name)
+
+ if param_value is not None:
+ raise ClientHandshakeError(
+ 'Bad %s: Has value %r' %
+ (client_no_context_takeover_name, param_value))
+ client_no_context_takeover = True
+
+ if client_no_context_takeover is None:
+ client_no_context_takeover = False
+
+ return _PerMessageDeflateFramer(client_max_window_bits,
+ client_no_context_takeover)
+
+
+class ClientHandshakeProcessor(ClientHandshakeBase):
+ """WebSocket opening handshake processor for
+ draft-ietf-hybi-thewebsocketprotocol-06 and later.
+ """
+
+ def __init__(self, socket, options):
+ super(ClientHandshakeProcessor, self).__init__()
+
+ self._socket = socket
+ self._options = options
+
+ self._logger = util.get_class_logger(self)
+
+ def handshake(self):
+ """Performs opening handshake on the specified socket.
+
+ Raises:
+ ClientHandshakeError: handshake failed.
+ """
+
+ request_line = _build_method_line(self._options.resource)
+ self._logger.debug('Client\'s opening handshake Request-Line: %r',
+ request_line)
+ self._socket.sendall(request_line)
+
+ fields = []
+ fields.append(_format_host_header(
+ self._options.server_host,
+ self._options.server_port,
+ self._options.use_tls))
+ fields.append(_UPGRADE_HEADER)
+ fields.append(_CONNECTION_HEADER)
+ if self._options.origin is not None:
+ if self._options.protocol_version == _PROTOCOL_VERSION_HYBI08:
+ fields.append(_origin_header(
+ common.SEC_WEBSOCKET_ORIGIN_HEADER,
+ self._options.origin))
+ else:
+ fields.append(_origin_header(common.ORIGIN_HEADER,
+ self._options.origin))
+
+ original_key = os.urandom(16)
+ self._key = base64.b64encode(original_key)
+ self._logger.debug(
+ '%s: %r (%s)',
+ common.SEC_WEBSOCKET_KEY_HEADER,
+ self._key,
+ util.hexify(original_key))
+ fields.append(
+ '%s: %s\r\n' % (common.SEC_WEBSOCKET_KEY_HEADER, self._key))
+
+ if self._options.version_header > 0:
+ fields.append('%s: %d\r\n' % (common.SEC_WEBSOCKET_VERSION_HEADER,
+ self._options.version_header))
+ elif self._options.protocol_version == _PROTOCOL_VERSION_HYBI08:
+ fields.append('%s: %d\r\n' % (common.SEC_WEBSOCKET_VERSION_HEADER,
+ common.VERSION_HYBI08))
+ else:
+ fields.append('%s: %d\r\n' % (common.SEC_WEBSOCKET_VERSION_HEADER,
+ common.VERSION_HYBI_LATEST))
+
+ extensions_to_request = []
+
+ if self._options.deflate_frame:
+ extensions_to_request.append(
+ common.ExtensionParameter(common.DEFLATE_FRAME_EXTENSION))
+
+ if self._options.use_permessage_deflate:
+ extension = common.ExtensionParameter(
+ common.PERMESSAGE_DEFLATE_EXTENSION)
+ # Accept the client_max_window_bits extension parameter by default.
+ extension.add_parameter(
+ PerMessageDeflateExtensionProcessor.
+ _CLIENT_MAX_WINDOW_BITS_PARAM,
+ None)
+ extensions_to_request.append(extension)
+
+ if len(extensions_to_request) != 0:
+ fields.append(
+ '%s: %s\r\n' %
+ (common.SEC_WEBSOCKET_EXTENSIONS_HEADER,
+ common.format_extensions(extensions_to_request)))
+
+ for field in fields:
+ self._socket.sendall(field)
+
+ self._socket.sendall('\r\n')
+
+ self._logger.debug('Sent client\'s opening handshake headers: %r',
+ fields)
+ self._logger.debug('Start reading Status-Line')
+
+ status_line = ''
+ while True:
+ ch = _receive_bytes(self._socket, 1)
+ status_line += ch
+ if ch == '\n':
+ break
+
+ m = re.match('HTTP/\\d+\.\\d+ (\\d\\d\\d) .*\r\n', status_line)
+ if m is None:
+ raise ClientHandshakeError(
+ 'Wrong status line format: %r' % status_line)
+ status_code = m.group(1)
+ if status_code != '101':
+ self._logger.debug('Unexpected status code %s with following '
+ 'headers: %r', status_code, self._read_fields())
+ raise ClientHandshakeError(
+ 'Expected HTTP status code 101 but found %r' % status_code)
+
+ self._logger.debug('Received valid Status-Line')
+ self._logger.debug('Start reading headers until we see an empty line')
+
+ fields = self._read_fields()
+
+ ch = _receive_bytes(self._socket, 1)
+ if ch != '\n': # 0x0A
+ raise ClientHandshakeError(
+ 'Expected LF but found %r while reading value %r for header '
+ 'name %r' % (ch, value, name))
+
+ self._logger.debug('Received an empty line')
+ self._logger.debug('Server\'s opening handshake headers: %r', fields)
+
+ _validate_mandatory_header(
+ fields,
+ common.UPGRADE_HEADER,
+ common.WEBSOCKET_UPGRADE_TYPE,
+ False)
+
+ _validate_mandatory_header(
+ fields,
+ common.CONNECTION_HEADER,
+ common.UPGRADE_CONNECTION_TYPE,
+ False)
+
+ accept = _get_mandatory_header(
+ fields, common.SEC_WEBSOCKET_ACCEPT_HEADER)
+
+ # Validate
+ try:
+ binary_accept = base64.b64decode(accept)
+ except TypeError, e:
+ raise HandshakeError(
+ 'Illegal value for header %s: %r' %
+ (common.SEC_WEBSOCKET_ACCEPT_HEADER, accept))
+
+ if len(binary_accept) != 20:
+ raise ClientHandshakeError(
+ 'Decoded value of %s is not 20-byte long' %
+ common.SEC_WEBSOCKET_ACCEPT_HEADER)
+
+ self._logger.debug(
+ 'Response for challenge : %r (%s)',
+ accept, util.hexify(binary_accept))
+
+ binary_expected_accept = util.sha1_hash(
+ self._key + common.WEBSOCKET_ACCEPT_UUID).digest()
+ expected_accept = base64.b64encode(binary_expected_accept)
+
+ self._logger.debug(
+ 'Expected response for challenge: %r (%s)',
+ expected_accept, util.hexify(binary_expected_accept))
+
+ if accept != expected_accept:
+ raise ClientHandshakeError(
+ 'Invalid %s header: %r (expected: %s)' %
+ (common.SEC_WEBSOCKET_ACCEPT_HEADER, accept, expected_accept))
+
+ deflate_frame_accepted = False
+ permessage_deflate_accepted = False
+
+ extensions_header = fields.get(
+ common.SEC_WEBSOCKET_EXTENSIONS_HEADER.lower())
+ accepted_extensions = []
+ if extensions_header is not None and len(extensions_header) != 0:
+ accepted_extensions = common.parse_extensions(extensions_header[0])
+
+ # TODO(bashi): Support the new style perframe compression extension.
+ for extension in accepted_extensions:
+ extension_name = extension.name()
+ if (extension_name == common.DEFLATE_FRAME_EXTENSION and
+ self._options.deflate_frame):
+ deflate_frame_accepted = True
+ processor = DeflateFrameExtensionProcessor(extension)
+ unused_extension_response = processor.get_extension_response()
+ self._options.deflate_frame = processor
+ continue
+ elif (extension_name == common.PERMESSAGE_DEFLATE_EXTENSION and
+ self._options.use_permessage_deflate):
+ permessage_deflate_accepted = True
+
+ framer = _get_permessage_deflate_framer(extension)
+ framer.set_compress_outgoing_enabled(True)
+ self._options.use_permessage_deflate = framer
+ continue
+
+ raise ClientHandshakeError(
+ 'Unexpected extension %r' % extension_name)
+
+ if (self._options.deflate_frame and not deflate_frame_accepted):
+ raise ClientHandshakeError(
+ 'Requested %s, but the server rejected it' %
+ common.DEFLATE_FRAME_EXTENSION)
+
+ if (self._options.use_permessage_deflate and
+ not permessage_deflate_accepted):
+ raise ClientHandshakeError(
+ 'Requested %s, but the server rejected it' %
+ common.PERMESSAGE_DEFLATE_EXTENSION)
+
+ # TODO(tyoshino): Handle Sec-WebSocket-Protocol
+ # TODO(tyoshino): Handle Cookie, etc.
+
+
+class ClientHandshakeProcessorHybi00(ClientHandshakeBase):
+ """WebSocket opening handshake processor for
+ draft-ietf-hybi-thewebsocketprotocol-00 (equivalent to
+ draft-hixie-thewebsocketprotocol-76).
+ """
+
+ def __init__(self, socket, options):
+ super(ClientHandshakeProcessorHybi00, self).__init__()
+
+ self._socket = socket
+ self._options = options
+
+ self._logger = util.get_class_logger(self)
+
+ if (self._options.deflate_frame or
+ self._options.use_permessage_deflate):
+ logging.critical('HyBi 00 doesn\'t support extensions.')
+ sys.exit(1)
+
+ def handshake(self):
+ """Performs opening handshake on the specified socket.
+
+ Raises:
+ ClientHandshakeError: handshake failed.
+ """
+
+ # 4.1 5. send request line.
+ self._socket.sendall(_build_method_line(self._options.resource))
+ # 4.1 6. Let /fields/ be an empty list of strings.
+ fields = []
+ # 4.1 7. Add the string "Upgrade: WebSocket" to /fields/.
+ fields.append(_UPGRADE_HEADER_HIXIE75)
+ # 4.1 8. Add the string "Connection: Upgrade" to /fields/.
+ fields.append(_CONNECTION_HEADER)
+ # 4.1 9-12. Add Host: field to /fields/.
+ fields.append(_format_host_header(
+ self._options.server_host,
+ self._options.server_port,
+ self._options.use_tls))
+ # 4.1 13. Add Origin: field to /fields/.
+ if not self._options.origin:
+ raise ClientHandshakeError(
+ 'Specify the origin of the connection by --origin flag')
+ fields.append(_origin_header(common.ORIGIN_HEADER,
+ self._options.origin))
+ # TODO: 4.1 14 Add Sec-WebSocket-Protocol: field to /fields/.
+ # TODO: 4.1 15 Add cookie headers to /fields/.
+
+ # 4.1 16-23. Add Sec-WebSocket-Key<n> to /fields/.
+ self._number1, key1 = self._generate_sec_websocket_key()
+ self._logger.debug('Number1: %d', self._number1)
+ fields.append('%s: %s\r\n' % (common.SEC_WEBSOCKET_KEY1_HEADER, key1))
+ self._number2, key2 = self._generate_sec_websocket_key()
+ self._logger.debug('Number2: %d', self._number2)
+ fields.append('%s: %s\r\n' % (common.SEC_WEBSOCKET_KEY2_HEADER, key2))
+
+ fields.append('%s: 0\r\n' % common.SEC_WEBSOCKET_DRAFT_HEADER)
+
+ # 4.1 24. For each string in /fields/, in a random order: send the
+ # string, encoded as UTF-8, followed by a UTF-8 encoded U+000D CARRIAGE
+ # RETURN U+000A LINE FEED character pair (CRLF).
+ random.shuffle(fields)
+ for field in fields:
+ self._socket.sendall(field)
+ # 4.1 25. send a UTF-8-encoded U+000D CARRIAGE RETURN U+000A LINE FEED
+ # character pair (CRLF).
+ self._socket.sendall('\r\n')
+ # 4.1 26. let /key3/ be a string consisting of eight random bytes (or
+ # equivalently, a random 64 bit integer encoded in a big-endian order).
+ self._key3 = self._generate_key3()
+ # 4.1 27. send /key3/ to the server.
+ self._socket.sendall(self._key3)
+ self._logger.debug(
+ 'Key3: %r (%s)', self._key3, util.hexify(self._key3))
+
+ self._logger.info('Sent handshake')
+
+ # 4.1 28. Read bytes from the server until either the connection
+ # closes, or a 0x0A byte is read. let /field/ be these bytes, including
+ # the 0x0A bytes.
+ field = ''
+ while True:
+ ch = _receive_bytes(self._socket, 1)
+ field += ch
+ if ch == '\n':
+ break
+ # if /field/ is not at least seven bytes long, or if the last
+ # two bytes aren't 0x0D and 0x0A respectively, or if it does not
+ # contain at least two 0x20 bytes, then fail the WebSocket connection
+ # and abort these steps.
+ if len(field) < 7 or not field.endswith('\r\n'):
+ raise ClientHandshakeError('Wrong status line: %r' % field)
+ m = re.match('[^ ]* ([^ ]*) .*', field)
+ if m is None:
+ raise ClientHandshakeError(
+ 'No HTTP status code found in status line: %r' % field)
+ # 4.1 29. let /code/ be the substring of /field/ that starts from the
+ # byte after the first 0x20 byte, and ends with the byte before the
+ # second 0x20 byte.
+ code = m.group(1)
+ # 4.1 30. if /code/ is not three bytes long, or if any of the bytes in
+ # /code/ are not in the range 0x30 to 0x90, then fail the WebSocket
+ # connection and abort these steps.
+ if not re.match('[0-9][0-9][0-9]', code):
+ raise ClientHandshakeError(
+ 'HTTP status code %r is not three digit in status line: %r' %
+ (code, field))
+ # 4.1 31. if /code/, interpreted as UTF-8, is "101", then move to the
+ # next step.
+ if code != '101':
+ raise ClientHandshakeError(
+ 'Expected HTTP status code 101 but found %r in status line: '
+ '%r' % (code, field))
+ # 4.1 32-39. read fields into /fields/
+ fields = self._read_fields()
+ # 4.1 40. _Fields processing_
+ # read a byte from server
+ ch = _receive_bytes(self._socket, 1)
+ if ch != '\n': # 0x0A
+ raise ClientHandshakeError('Expected LF but found %r' % ch)
+ # 4.1 41. check /fields/
+ # TODO(ukai): protocol
+ # if the entry's name is "upgrade"
+ # if the value is not exactly equal to the string "WebSocket",
+ # then fail the WebSocket connection and abort these steps.
+ _validate_mandatory_header(
+ fields,
+ common.UPGRADE_HEADER,
+ common.WEBSOCKET_UPGRADE_TYPE_HIXIE75,
+ True)
+ # if the entry's name is "connection"
+ # if the value, converted to ASCII lowercase, is not exactly equal
+ # to the string "upgrade", then fail the WebSocket connection and
+ # abort these steps.
+ _validate_mandatory_header(
+ fields,
+ common.CONNECTION_HEADER,
+ common.UPGRADE_CONNECTION_TYPE,
+ False)
+
+ origin = _get_mandatory_header(
+ fields, common.SEC_WEBSOCKET_ORIGIN_HEADER)
+
+ location = _get_mandatory_header(
+ fields, common.SEC_WEBSOCKET_LOCATION_HEADER)
+
+ # TODO(ukai): check origin, location, cookie, ..
+
+ # 4.1 42. let /challenge/ be the concatenation of /number_1/,
+ # expressed as a big endian 32 bit integer, /number_2/, expressed
+ # as big endian 32 bit integer, and the eight bytes of /key_3/ in the
+ # order they were sent on the wire.
+ challenge = struct.pack('!I', self._number1)
+ challenge += struct.pack('!I', self._number2)
+ challenge += self._key3
+
+ self._logger.debug(
+ 'Challenge: %r (%s)', challenge, util.hexify(challenge))
+
+ # 4.1 43. let /expected/ be the MD5 fingerprint of /challenge/ as a
+ # big-endian 128 bit string.
+ expected = util.md5_hash(challenge).digest()
+ self._logger.debug(
+ 'Expected challenge response: %r (%s)',
+ expected, util.hexify(expected))
+
+ # 4.1 44. read sixteen bytes from the server.
+ # let /reply/ be those bytes.
+ reply = _receive_bytes(self._socket, 16)
+ self._logger.debug(
+ 'Actual challenge response: %r (%s)', reply, util.hexify(reply))
+
+ # 4.1 45. if /reply/ does not exactly equal /expected/, then fail
+ # the WebSocket connection and abort these steps.
+ if expected != reply:
+ raise ClientHandshakeError(
+ 'Bad challenge response: %r (expected) != %r (actual)' %
+ (expected, reply))
+ # 4.1 46. The *WebSocket connection is established*.
+
+ def _generate_sec_websocket_key(self):
+ # 4.1 16. let /spaces_n/ be a random integer from 1 to 12 inclusive.
+ spaces = random.randint(1, 12)
+ # 4.1 17. let /max_n/ be the largest integer not greater than
+ # 4,294,967,295 divided by /spaces_n/.
+ maxnum = 4294967295 / spaces
+ # 4.1 18. let /number_n/ be a random integer from 0 to /max_n/
+ # inclusive.
+ number = random.randint(0, maxnum)
+ # 4.1 19. let /product_n/ be the result of multiplying /number_n/ and
+ # /spaces_n/ together.
+ product = number * spaces
+ # 4.1 20. let /key_n/ be a string consisting of /product_n/, expressed
+ # in base ten using the numerals in the range U+0030 DIGIT ZERO (0) to
+ # U+0039 DIGIT NINE (9).
+ key = str(product)
+ # 4.1 21. insert between one and twelve random characters from the
+ # range U+0021 to U+002F and U+003A to U+007E into /key_n/ at random
+ # positions.
+ available_chars = range(0x21, 0x2f + 1) + range(0x3a, 0x7e + 1)
+ n = random.randint(1, 12)
+ for _ in xrange(n):
+ ch = random.choice(available_chars)
+ pos = random.randint(0, len(key))
+ key = key[0:pos] + chr(ch) + key[pos:]
+ # 4.1 22. insert /spaces_n/ U+0020 SPACE characters into /key_n/ at
+ # random positions other than start or end of the string.
+ for _ in xrange(spaces):
+ pos = random.randint(1, len(key) - 1)
+ key = key[0:pos] + ' ' + key[pos:]
+ return number, key
+
+ def _generate_key3(self):
+ # 4.1 26. let /key3/ be a string consisting of eight random bytes (or
+ # equivalently, a random 64 bit integer encoded in a big-endian order).
+ return ''.join([chr(random.randint(0, 255)) for _ in xrange(8)])
+
+
+class ClientConnection(object):
+ """A wrapper for socket object to provide the mp_conn interface.
+ mod_pywebsocket library is designed to be working on Apache mod_python's
+ mp_conn object.
+ """
+
+ def __init__(self, socket):
+ self._socket = socket
+
+ def write(self, data):
+ self._socket.sendall(data)
+
+ def read(self, n):
+ return self._socket.recv(n)
+
+ def get_remote_addr(self):
+ return self._socket.getpeername()
+ remote_addr = property(get_remote_addr)
+
+
+class ClientRequest(object):
+ """A wrapper class just to make it able to pass a socket object to
+ functions that expect a mp_request object.
+ """
+
+ def __init__(self, socket):
+ self._logger = util.get_class_logger(self)
+
+ self._socket = socket
+ self.connection = ClientConnection(socket)
+
+
+def _import_ssl():
+ global ssl
+ try:
+ import ssl
+ return True
+ except ImportError:
+ return False
+
+
+def _import_pyopenssl():
+ global OpenSSL
+ try:
+ import OpenSSL.SSL
+ return True
+ except ImportError:
+ return False
+
+
+class EchoClient(object):
+ """WebSocket echo client."""
+
+ def __init__(self, options):
+ self._options = options
+ self._socket = None
+
+ self._logger = util.get_class_logger(self)
+
+ def run(self):
+ """Run the client.
+
+ Shake hands and then repeat sending message and receiving its echo.
+ """
+
+ self._socket = socket.socket()
+ self._socket.settimeout(self._options.socket_timeout)
+ try:
+ self._socket.connect((self._options.server_host,
+ self._options.server_port))
+ if self._options.use_tls:
+ self._socket = _TLSSocket(
+ self._socket,
+ self._options.tls_module,
+ self._options.tls_version,
+ self._options.disable_tls_compression)
+
+ version = self._options.protocol_version
+
+ if (version == _PROTOCOL_VERSION_HYBI08 or
+ version == _PROTOCOL_VERSION_HYBI13):
+ self._handshake = ClientHandshakeProcessor(
+ self._socket, self._options)
+ elif version == _PROTOCOL_VERSION_HYBI00:
+ self._handshake = ClientHandshakeProcessorHybi00(
+ self._socket, self._options)
+ else:
+ raise ValueError(
+ 'Invalid --protocol-version flag: %r' % version)
+
+ self._handshake.handshake()
+
+ self._logger.info('Connection established')
+
+ request = ClientRequest(self._socket)
+
+ version_map = {
+ _PROTOCOL_VERSION_HYBI08: common.VERSION_HYBI08,
+ _PROTOCOL_VERSION_HYBI13: common.VERSION_HYBI13,
+ _PROTOCOL_VERSION_HYBI00: common.VERSION_HYBI00}
+ request.ws_version = version_map[version]
+
+ if (version == _PROTOCOL_VERSION_HYBI08 or
+ version == _PROTOCOL_VERSION_HYBI13):
+ stream_option = StreamOptions()
+ stream_option.mask_send = True
+ stream_option.unmask_receive = False
+
+ if self._options.deflate_frame is not False:
+ processor = self._options.deflate_frame
+ processor.setup_stream_options(stream_option)
+
+ if self._options.use_permessage_deflate is not False:
+ framer = self._options.use_permessage_deflate
+ framer.setup_stream_options(stream_option)
+
+ self._stream = Stream(request, stream_option)
+ elif version == _PROTOCOL_VERSION_HYBI00:
+ self._stream = StreamHixie75(request, True)
+
+ for line in self._options.message.split(','):
+ self._stream.send_message(line)
+ if self._options.verbose:
+ print 'Send: %s' % line
+ try:
+ received = self._stream.receive_message()
+
+ if self._options.verbose:
+ print 'Recv: %s' % received
+ except Exception, e:
+ if self._options.verbose:
+ print 'Error: %s' % e
+ raise
+
+ self._do_closing_handshake()
+ finally:
+ self._socket.close()
+
+ def _do_closing_handshake(self):
+ """Perform closing handshake using the specified closing frame."""
+
+ if self._options.message.split(',')[-1] == _GOODBYE_MESSAGE:
+ # requested server initiated closing handshake, so
+ # expecting closing handshake message from server.
+ self._logger.info('Wait for server-initiated closing handshake')
+ message = self._stream.receive_message()
+ if message is None:
+ print 'Recv close'
+ print 'Send ack'
+ self._logger.info(
+ 'Received closing handshake and sent ack')
+ return
+ print 'Send close'
+ self._stream.close_connection()
+ self._logger.info('Sent closing handshake')
+ print 'Recv ack'
+ self._logger.info('Received ack')
+
+
+def main():
+ sys.stdout = codecs.getwriter('utf-8')(sys.stdout)
+
+ parser = OptionParser()
+ # We accept --command_line_flag style flags which is the same as Google
+ # gflags in addition to common --command-line-flag style flags.
+ parser.add_option('-s', '--server-host', '--server_host',
+ dest='server_host', type='string',
+ default='localhost', help='server host')
+ parser.add_option('-p', '--server-port', '--server_port',
+ dest='server_port', type='int',
+ default=_UNDEFINED_PORT, help='server port')
+ parser.add_option('-o', '--origin', dest='origin', type='string',
+ default=None, help='origin')
+ parser.add_option('-r', '--resource', dest='resource', type='string',
+ default='/echo', help='resource path')
+ parser.add_option('-m', '--message', dest='message', type='string',
+ help=('comma-separated messages to send. '
+ '%s will force close the connection from server.' %
+ _GOODBYE_MESSAGE))
+ parser.add_option('-q', '--quiet', dest='verbose', action='store_false',
+ default=True, help='suppress messages')
+ parser.add_option('-t', '--tls', dest='use_tls', action='store_true',
+ default=False, help='use TLS (wss://). By default, '
+ 'it looks for ssl and pyOpenSSL module and uses found '
+ 'one. Use --tls-module option to specify which module '
+ 'to use')
+ parser.add_option('--tls-module', '--tls_module', dest='tls_module',
+ type='choice',
+ choices=[_TLS_BY_STANDARD_MODULE, _TLS_BY_PYOPENSSL],
+ help='Use ssl module if "%s" is specified. '
+ 'Use pyOpenSSL module if "%s" is specified' %
+ (_TLS_BY_STANDARD_MODULE, _TLS_BY_PYOPENSSL))
+ parser.add_option('--tls-version', '--tls_version',
+ dest='tls_version',
+ type='string', default=_TLS_VERSION_SSL23,
+ help='TLS/SSL version to use. One of \'' +
+ _TLS_VERSION_SSL23 + '\' (SSL version 2 or 3), \'' +
+ _TLS_VERSION_SSL3 + '\' (SSL version 3), \'' +
+ _TLS_VERSION_TLS1 + '\' (TLS version 1)')
+ parser.add_option('--disable-tls-compression', '--disable_tls_compression',
+ dest='disable_tls_compression',
+ action='store_true', default=False,
+ help='Disable TLS compression. Available only when '
+ 'pyOpenSSL module is used.')
+ parser.add_option('-k', '--socket-timeout', '--socket_timeout',
+ dest='socket_timeout', type='int', default=_TIMEOUT_SEC,
+ help='Timeout(sec) for sockets')
+ parser.add_option('--draft75', dest='draft75',
+ action='store_true', default=False,
+ help='Obsolete option. Don\'t use this.')
+ parser.add_option('--protocol-version', '--protocol_version',
+ dest='protocol_version',
+ type='string', default=_PROTOCOL_VERSION_HYBI13,
+ help='WebSocket protocol version to use. One of \'' +
+ _PROTOCOL_VERSION_HYBI13 + '\', \'' +
+ _PROTOCOL_VERSION_HYBI08 + '\', \'' +
+ _PROTOCOL_VERSION_HYBI00 + '\'')
+ parser.add_option('--version-header', '--version_header',
+ dest='version_header',
+ type='int', default=-1,
+ help='Specify Sec-WebSocket-Version header value')
+ parser.add_option('--deflate-frame', '--deflate_frame',
+ dest='deflate_frame',
+ action='store_true', default=False,
+ help='Use the deflate-frame extension.')
+ parser.add_option('--use-permessage-deflate', '--use_permessage_deflate',
+ dest='use_permessage_deflate',
+ action='store_true', default=False,
+ help='Use the permessage-deflate extension.')
+ parser.add_option('--log-level', '--log_level', type='choice',
+ dest='log_level', default='warn',
+ choices=['debug', 'info', 'warn', 'error', 'critical'],
+ help='Log level.')
+
+ (options, unused_args) = parser.parse_args()
+
+ logging.basicConfig(level=logging.getLevelName(options.log_level.upper()))
+
+ if options.draft75:
+ logging.critical('--draft75 option is obsolete.')
+ sys.exit(1)
+
+ if options.protocol_version == _PROTOCOL_VERSION_HIXIE75:
+ logging.critical(
+ 'Value %s is obsolete for --protocol_version options' %
+ _PROTOCOL_VERSION_HIXIE75)
+ sys.exit(1)
+
+ if options.use_tls:
+ if options.tls_module is None:
+ if _import_ssl():
+ options.tls_module = _TLS_BY_STANDARD_MODULE
+ logging.debug('Using ssl module')
+ elif _import_pyopenssl():
+ options.tls_module = _TLS_BY_PYOPENSSL
+ logging.debug('Using pyOpenSSL module')
+ else:
+ logging.critical(
+ 'TLS support requires ssl or pyOpenSSL module.')
+ sys.exit(1)
+ elif options.tls_module == _TLS_BY_STANDARD_MODULE:
+ if not _import_ssl():
+ logging.critical('ssl module is not available')
+ sys.exit(1)
+ elif options.tls_module == _TLS_BY_PYOPENSSL:
+ if not _import_pyopenssl():
+ logging.critical('pyOpenSSL module is not available')
+ sys.exit(1)
+ else:
+ logging.critical('Invalid --tls-module option: %r',
+ options.tls_module)
+ sys.exit(1)
+
+ if (options.disable_tls_compression and
+ options.tls_module != _TLS_BY_PYOPENSSL):
+ logging.critical('You can disable TLS compression only when '
+ 'pyOpenSSL module is used.')
+ sys.exit(1)
+ else:
+ if options.tls_module is not None:
+ logging.critical('Use --tls-module option only together with '
+ '--use-tls option.')
+ sys.exit(1)
+
+ if options.disable_tls_compression:
+ logging.critical('Use --disable-tls-compression only together '
+ 'with --use-tls option.')
+ sys.exit(1)
+
+ # Default port number depends on whether TLS is used.
+ if options.server_port == _UNDEFINED_PORT:
+ if options.use_tls:
+ options.server_port = common.DEFAULT_WEB_SOCKET_SECURE_PORT
+ else:
+ options.server_port = common.DEFAULT_WEB_SOCKET_PORT
+
+ # optparse doesn't seem to handle non-ascii default values.
+ # Set default message here.
+ if not options.message:
+ options.message = u'Hello,\u65e5\u672c' # "Japan" in Japanese
+
+ EchoClient(options).run()
+
+
+if __name__ == '__main__':
+ main()
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/echo_noext_wsh.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/echo_noext_wsh.py
new file mode 100644
index 00000000000..1df51512271
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/echo_noext_wsh.py
@@ -0,0 +1,61 @@
+# Copyright 2013, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+_GOODBYE_MESSAGE = u'Goodbye'
+
+
+def web_socket_do_extra_handshake(request):
+ """Received Sec-WebSocket-Extensions header value is parsed into
+ request.ws_requested_extensions. pywebsocket creates extension
+ processors using it before do_extra_handshake call and never looks at it
+ after the call.
+
+ To reject requested extensions, clear the processor list.
+ """
+
+ request.ws_extension_processors = []
+
+
+def web_socket_transfer_data(request):
+ """Echo. Same as echo_wsh.py."""
+
+ while True:
+ line = request.ws_stream.receive_message()
+ if line is None:
+ return
+ if isinstance(line, unicode):
+ request.ws_stream.send_message(line, binary=False)
+ if line == _GOODBYE_MESSAGE:
+ return
+ else:
+ request.ws_stream.send_message(line, binary=True)
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/echo_wsh.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/echo_wsh.py
new file mode 100644
index 00000000000..38646c32ceb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/echo_wsh.py
@@ -0,0 +1,54 @@
+# Copyright 2011, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+_GOODBYE_MESSAGE = u'Goodbye'
+
+
+def web_socket_do_extra_handshake(request):
+ # This example handler accepts any request. See origin_check_wsh.py for how
+ # to reject access from untrusted scripts based on origin value.
+
+ pass # Always accept.
+
+
+def web_socket_transfer_data(request):
+ while True:
+ line = request.ws_stream.receive_message()
+ if line is None:
+ return
+ if isinstance(line, unicode):
+ request.ws_stream.send_message(line, binary=False)
+ if line == _GOODBYE_MESSAGE:
+ return
+ else:
+ request.ws_stream.send_message(line, binary=True)
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/eventsource.cgi b/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/eventsource.cgi
new file mode 100755
index 00000000000..adddf237cf7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/eventsource.cgi
@@ -0,0 +1,54 @@
+#!/usr/bin/python
+
+# Copyright 2013, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+"""This CGI script generates text/event-stream type data stream for testing
+the Server-Sent Events.
+
+It will only work correctly with HTTP servers that do not buffer the output of
+CGI scripts.
+"""
+
+
+import sys
+import time
+
+sys.stdout.write('Content-type: text/event-stream\r\n\r\n')
+
+id = 0
+
+while True:
+ sys.stdout.write('data: Hello\r\nid: %d\r\n\r\n' % id)
+ sys.stdout.flush()
+
+ id = id + 1
+
+ time.sleep(1)
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/eventsource.html b/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/eventsource.html
new file mode 100644
index 00000000000..1598a8807d1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/eventsource.html
@@ -0,0 +1,74 @@
+<!--
+Copyright 2013, Google Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+
+<!--
+Simple example of the Server-Sent Events
+http://dev.w3.org/html5/eventsource/
+
+For comparison with the WebSocket Protocol & API.
+
+Run the pywebsocket with the --cgi_path parameter.
+-->
+
+<html>
+<head>
+<title>Server-Sent Events Example</title>
+<script>
+var eventSource = null;
+
+function addToLog(data) {
+ logBox.value += data + '\n';
+ logBox.scrollTop = 1000000;
+}
+
+function init() {
+ logBox = document.getElementById('log');
+
+ eventSource = new EventSource('/eventsource.cgi');
+ eventSource.onopen = function() {
+ addToLog('onopen (readyState = ' + eventSource.readyState + ')');
+ }
+ eventSource.onmessage = function(event) {
+ addToLog(event.data);
+ }
+ eventSource.onerror = function(event) {
+ addToLog('onerror (readyState = ' + eventSource.readyState + ')');
+ }
+}
+</script>
+</head>
+<body onload="init()">
+<textarea id="log" rows="10" cols="40" readonly></textarea>
+<p style="font-size: small">
+ Make sure that pywebsocket is run with --cgi_path parameter.
+</p>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/handler_map.txt b/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/handler_map.txt
new file mode 100644
index 00000000000..21c4c09aa00
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/handler_map.txt
@@ -0,0 +1,11 @@
+# websocket handler map file, used by standalone.py -m option.
+# A line starting with '#' is a comment line.
+# Each line consists of 'alias_resource_path' and 'existing_resource_path'
+# separated by spaces.
+# Aliasing is processed from the top to the bottom of the line, and
+# 'existing_resource_path' must exist before it is aliased.
+# For example,
+# / /echo
+# means that a request to '/' will be handled by handlers for '/echo'.
+/ /echo
+
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/hsts_wsh.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/hsts_wsh.py
new file mode 100644
index 00000000000..e861946921a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/hsts_wsh.py
@@ -0,0 +1,40 @@
+# Copyright 2013, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+def web_socket_do_extra_handshake(request):
+ request.extra_headers.append(
+ ('Strict-Transport-Security', 'max-age=86400'))
+
+
+def web_socket_transfer_data(request):
+ request.ws_stream.send_message('Hello', binary=False)
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/internal_error_wsh.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/internal_error_wsh.py
new file mode 100644
index 00000000000..fe581b54a64
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/internal_error_wsh.py
@@ -0,0 +1,42 @@
+# Copyright 2012, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+from mod_pywebsocket import msgutil
+
+
+def web_socket_do_extra_handshake(request):
+ pass
+
+
+def web_socket_transfer_data(request):
+ raise msgutil.BadOperationException('Intentional')
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/origin_check_wsh.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/origin_check_wsh.py
new file mode 100644
index 00000000000..e05767ab932
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/origin_check_wsh.py
@@ -0,0 +1,44 @@
+# Copyright 2011, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# This example is derived from test/testdata/handlers/origin_check_wsh.py.
+
+
+def web_socket_do_extra_handshake(request):
+ if request.ws_origin == 'http://example.com':
+ return
+ raise ValueError('Unacceptable origin: %r' % request.ws_origin)
+
+
+def web_socket_transfer_data(request):
+ request.connection.write('origin_check_wsh.py is called for %s, %s' %
+ (request.ws_resource, request.ws_protocol))
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/pywebsocket.conf b/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/pywebsocket.conf
new file mode 100644
index 00000000000..335d130a5c8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/pywebsocket.conf
@@ -0,0 +1,42 @@
+# Copyright 2011, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#
+# Sample configuration file for apache2
+#
+LogLevel debug
+<IfModule python_module>
+ PythonPath "sys.path+['/mod_pywebsocket']"
+ PythonOption mod_pywebsocket.handler_root /var/www
+ PythonOption mod_pywebsocket.handler_scan /var/www/ws
+ #PythonOption mod_pywebsocket.allow_draft75 On
+ <Location /ws>
+ PythonHeaderParserHandler mod_pywebsocket.headerparserhandler
+ </Location>
+</IfModule>
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/special_headers.cgi b/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/special_headers.cgi
new file mode 100755
index 00000000000..ea5080f1f1a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/special_headers.cgi
@@ -0,0 +1,28 @@
+#!/usr/bin/python
+
+# Copyright 2014 Google Inc. All rights reserved.
+#
+# Use of this source code is governed by a BSD-style
+# license that can be found in the COPYING file or at
+# https://developers.google.com/open-source/licenses/bsd
+
+"""CGI script sample for testing effect of HTTP headers on the origin page.
+
+Note that CGI scripts don't work on the standalone pywebsocket running in TLS
+mode.
+"""
+
+
+print """Content-type: text/html
+Content-Security-Policy: connect-src self
+
+<html>
+<head>
+<title></title>
+</head>
+<body>
+<script>
+var socket = new WebSocket("ws://example.com");
+</script>
+</body>
+</html>"""
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/util.js b/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/util.js
new file mode 100644
index 00000000000..a1cad4975ee
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/util.js
@@ -0,0 +1,177 @@
+// Copyright 2013, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+// Utilities for example applications (for both main and worker thread).
+
+var results = {};
+
+function getTimeStamp() {
+ return Date.now();
+}
+
+function formatResultInKiB(size, timePerMessageInMs, stddevTimePerMessageInMs,
+ speed, printSize) {
+ if (printSize) {
+ return (size / 1024) +
+ '\t' + timePerMessageInMs.toFixed(3) +
+ (stddevTimePerMessageInMs == -1 ?
+ '' :
+ '\t' + stddevTimePerMessageInMs.toFixed(3)) +
+ '\t' + speed.toFixed(3);
+ } else {
+ return speed.toString();
+ }
+}
+
+function clearAverageData() {
+ results = {};
+}
+
+function reportAverageData(config) {
+ config.addToSummary(
+ 'Size[KiB]\tAverage time[ms]\tStddev time[ms]\tSpeed[KB/s]');
+ for (var size in results) {
+ var averageTimePerMessageInMs = results[size].sum_t / results[size].n;
+ var speed = calculateSpeedInKB(size, averageTimePerMessageInMs);
+ // Calculate sample standard deviation
+ var stddevTimePerMessageInMs = Math.sqrt(
+ (results[size].sum_t2 / results[size].n -
+ averageTimePerMessageInMs * averageTimePerMessageInMs) *
+ results[size].n /
+ (results[size].n - 1));
+ config.addToSummary(formatResultInKiB(
+ size, averageTimePerMessageInMs, stddevTimePerMessageInMs, speed,
+ true));
+ }
+}
+
+function calculateSpeedInKB(size, timeSpentInMs) {
+ return Math.round(size / timeSpentInMs * 1000) / 1000;
+}
+
+function calculateAndLogResult(config, size, startTimeInMs, totalSize) {
+ var timeSpentInMs = getTimeStamp() - startTimeInMs;
+ var speed = calculateSpeedInKB(totalSize, timeSpentInMs);
+ var timePerMessageInMs = timeSpentInMs / (totalSize / size);
+ if (!results[size]) {
+ results[size] = {n: 0, sum_t: 0, sum_t2: 0};
+ }
+ config.measureValue(timePerMessageInMs);
+ results[size].n ++;
+ results[size].sum_t += timePerMessageInMs;
+ results[size].sum_t2 += timePerMessageInMs * timePerMessageInMs;
+ config.addToLog(formatResultInKiB(size, timePerMessageInMs, -1, speed,
+ config.printSize));
+}
+
+function fillArrayBuffer(buffer, c) {
+ var i;
+
+ var u32Content = c * 0x01010101;
+
+ var u32Blocks = Math.floor(buffer.byteLength / 4);
+ var u32View = new Uint32Array(buffer, 0, u32Blocks);
+ // length attribute is slow on Chrome. Don't use it for loop condition.
+ for (i = 0; i < u32Blocks; ++i) {
+ u32View[i] = u32Content;
+ }
+
+ // Fraction
+ var u8Blocks = buffer.byteLength - u32Blocks * 4;
+ var u8View = new Uint8Array(buffer, u32Blocks * 4, u8Blocks);
+ for (i = 0; i < u8Blocks; ++i) {
+ u8View[i] = c;
+ }
+}
+
+function verifyArrayBuffer(buffer, expectedChar) {
+ var i;
+
+ var expectedU32Value = expectedChar * 0x01010101;
+
+ var u32Blocks = Math.floor(buffer.byteLength / 4);
+ var u32View = new Uint32Array(buffer, 0, u32Blocks);
+ for (i = 0; i < u32Blocks; ++i) {
+ if (u32View[i] != expectedU32Value) {
+ return false;
+ }
+ }
+
+ var u8Blocks = buffer.byteLength - u32Blocks * 4;
+ var u8View = new Uint8Array(buffer, u32Blocks * 4, u8Blocks);
+ for (i = 0; i < u8Blocks; ++i) {
+ if (u8View[i] != expectedChar) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+function verifyBlob(config, blob, expectedChar, doneCallback) {
+ var reader = new FileReader(blob);
+ reader.onerror = function() {
+ config.addToLog('FileReader Error: ' + reader.error.message);
+ doneCallback(blob.size, false);
+ }
+ reader.onloadend = function() {
+ var result = verifyArrayBuffer(reader.result, expectedChar);
+ doneCallback(blob.size, result);
+ }
+ reader.readAsArrayBuffer(blob);
+}
+
+function verifyAcknowledgement(config, message, size) {
+ if (typeof message != 'string') {
+ config.addToLog('Invalid ack type: ' + typeof message);
+ return false;
+ }
+ var parsedAck = parseInt(message);
+ if (isNaN(parsedAck)) {
+ config.addToLog('Invalid ack value: ' + message);
+ return false;
+ }
+ if (parsedAck != size) {
+ config.addToLog(
+ 'Expected ack for ' + size + 'B but received one for ' + parsedAck +
+ 'B');
+ return false;
+ }
+
+ return true;
+}
+
+function cloneConfig(obj) {
+ var newObj = {};
+ for (key in obj) {
+ newObj[key] = obj[key];
+ }
+ return newObj;
+}
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/util_main.js b/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/util_main.js
new file mode 100644
index 00000000000..b03d1c2bdc4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/util_main.js
@@ -0,0 +1,63 @@
+// Copyright 2014 Google Inc. All rights reserved.
+//
+// Use of this source code is governed by a BSD-style
+// license that can be found in the COPYING file or at
+// https://developers.google.com/open-source/licenses/bsd
+
+// Utilities for example applications (for the main thread only).
+
+var logBox = null;
+var queuedLog = '';
+
+var summaryBox = null;
+
+function queueLog(log) {
+ queuedLog += log + '\n';
+}
+
+function addToLog(log) {
+ logBox.value += queuedLog;
+ queuedLog = '';
+ logBox.value += log + '\n';
+ logBox.scrollTop = 1000000;
+}
+
+function addToSummary(log) {
+ summaryBox.value += log + '\n';
+ summaryBox.scrollTop = 1000000;
+}
+
+// value: execution time in milliseconds.
+// config.measureValue is intended to be used in Performance Tests.
+// Do nothing here in non-PerformanceTest.
+function measureValue(value) {
+}
+
+function getIntFromInput(id) {
+ return parseInt(document.getElementById(id).value);
+}
+
+function getStringFromRadioBox(name) {
+ var list = document.getElementById('benchmark_form')[name];
+ for (var i = 0; i < list.length; ++i)
+ if (list.item(i).checked)
+ return list.item(i).value;
+ return undefined;
+}
+function getBoolFromCheckBox(id) {
+ return document.getElementById(id).checked;
+}
+
+function getIntArrayFromInput(id) {
+ var strArray = document.getElementById(id).value.split(',');
+ return strArray.map(function(str) { return parseInt(str, 10); });
+}
+
+function onMessage(message) {
+ if (message.data.type === 'addToLog')
+ addToLog(message.data.data);
+ else if (message.data.type === 'addToSummary')
+ addToSummary(message.data.data);
+ else if (message.data.type === 'measureValue')
+ measureValue(message.data.data);
+}
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/util_worker.js b/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/util_worker.js
new file mode 100644
index 00000000000..b64f7829d52
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/util_worker.js
@@ -0,0 +1,19 @@
+// Copyright 2014 Google Inc. All rights reserved.
+//
+// Use of this source code is governed by a BSD-style
+// license that can be found in the COPYING file or at
+// https://developers.google.com/open-source/licenses/bsd
+
+// Utilities for example applications (for the worker threads only).
+
+function workerAddToLog(text) {
+ postMessage({type: 'addToLog', data: text});
+}
+
+function workerAddToSummary(text) {
+ postMessage({type: 'addToSummary', data: text});
+}
+
+function workerMeasureValue(value) {
+ postMessage({type: 'measureValue', data: value});
+}
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/xhr_benchmark.html b/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/xhr_benchmark.html
new file mode 100644
index 00000000000..186229775f5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/xhr_benchmark.html
@@ -0,0 +1,222 @@
+<!--
+Copyright 2013, Google Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+
+<html>
+<head>
+<title>XMLHttpRequest benchmark</title>
+<script src="util_main.js"></script>
+<script src="util.js"></script>
+<script src="xhr_benchmark.js"></script>
+<script>
+var addressBox = null;
+
+function getConfig() {
+ return {
+ prefixUrl: addressBox.value,
+ printSize: getBoolFromCheckBox('printsize'),
+ numXHRs: getIntFromInput('numXHRs'),
+ async: getBoolFromCheckBox('async'),
+ // Initial size of messages.
+ numIterations: getIntFromInput('numiterations'),
+ numWarmUpIterations: getIntFromInput('numwarmupiterations'),
+ startSize: getIntFromInput('startsize'),
+ // Stops benchmark when the size of message exceeds this threshold.
+ stopThreshold: getIntFromInput('stopthreshold'),
+ // If the size of each message is small, send/receive multiple messages
+ // until the sum of sizes reaches this threshold.
+ // minTotal: getIntFromInput('mintotal'),
+ // minTotal is not yet implemented on XHR benchmark
+ multipliers: getIntArrayFromInput('multipliers'),
+ verifyData: getBoolFromCheckBox('verifydata')
+ };
+}
+
+var worker = new Worker('xhr_benchmark.js');
+worker.onmessage = onMessage;
+
+function onSendBenchmark() {
+ var config = getConfig();
+ config.dataType = getStringFromRadioBox('datatyperadio');
+
+ if (getBoolFromCheckBox('worker')) {
+ worker.postMessage({type: 'sendBenchmark', config: config});
+ } else {
+ config.addToLog = addToLog;
+ config.addToSummary = addToSummary;
+ config.measureValue = measureValue;
+ sendBenchmark(config);
+ }
+}
+
+function onReceiveBenchmark() {
+ var config = getConfig();
+ config.dataType = getStringFromRadioBox('datatyperadio');
+
+ if (getBoolFromCheckBox('worker')) {
+ worker.postMessage({type: 'receiveBenchmark', config: config});
+ } else {
+ config.addToLog = addToLog;
+ config.addToSummary = addToSummary;
+ config.measureValue = measureValue;
+ receiveBenchmark(config);
+ }
+}
+
+function onBatchBenchmark() {
+ var config = getConfig();
+
+ if (getBoolFromCheckBox('worker')) {
+ worker.postMessage({type: 'batchBenchmark', config: config});
+ } else {
+ config.addToLog = addToLog;
+ config.addToSummary = addToSummary;
+ config.measureValue = measureValue;
+ batchBenchmark(config);
+ }
+}
+
+function onStop() {
+ var config = getConfig();
+
+ if (getBoolFromCheckBox('worker')) {
+ worker.postMessage({type: 'stop', config: config});
+ } else {
+ config.addToLog = addToLog;
+ config.addToSummary = addToSummary;
+ config.measureValue = measureValue;
+ stop(config);
+ }
+}
+
+function init() {
+ addressBox = document.getElementById('address');
+ logBox = document.getElementById('log');
+
+ summaryBox = document.getElementById('summary');
+
+ // Special address of pywebsocket for XHR benchmark.
+ addressBox.value = '/073be001e10950692ccbf3a2ad21c245';
+
+ addToLog(window.navigator.userAgent.toLowerCase());
+ addToSummary(window.navigator.userAgent.toLowerCase());
+}
+</script>
+</head>
+<body onload="init()">
+
+<form id="benchmark_form">
+ url prefix <input type="text" id="address" size="40">
+ <input type="button" value="send" onclick="onSendBenchmark()">
+ <input type="button" value="receive" onclick="onReceiveBenchmark()">
+ <input type="button" value="batch" onclick="onBatchBenchmark()">
+ <input type="button" value="stop" onclick="onStop()">
+
+ <br/>
+
+ <input type="checkbox" id="printsize" checked>
+ <label for="printsize">Print size and time per message</label>
+ <input type="checkbox" id="verifydata" checked>
+ <label for="verifydata">Verify data</label>
+ <input type="checkbox" id="worker">
+ <label for="worker">Run on worker</label>
+ <input type="checkbox" id="async" checked>
+ <label for="async">Async</label><br>
+ (Receive &amp;&amp; Non-Worker &amp;&amp; Sync is not supported by spec)
+
+ <br/>
+
+ Parameters:
+
+ <br/>
+
+ <table>
+ <tr>
+ <td>Num XHRs</td>
+ <td><input type="text" id="numXHRs" value="1"></td>
+ </tr>
+ <tr>
+ <td>Number of iterations</td>
+ <td><input type="text" id="numiterations" value="1"></td>
+ </tr>
+ <tr>
+ <td>Number of warm-up iterations</td>
+ <td><input type="text" id="numwarmupiterations" value="0"></td>
+ </tr>
+ <tr>
+ <td>Start size</td>
+ <td><input type="text" id="startsize" value="10240"></td>
+ </tr>
+ <tr>
+ <td>Stop threshold</td>
+ <td><input type="text" id="stopthreshold" value="102400000"></td>
+ </tr>
+ <tr>
+ <td>Minimum total</td>
+ <td><input type="text" id="mintotal" value="102400000"></td>
+ </tr>
+ <tr>
+ <td>Multipliers</td>
+ <td><input type="text" id="multipliers" value="5, 2"></td>
+ </tr>
+ </table>
+
+ Set data type
+ <input type="radio"
+ name="datatyperadio"
+ id="datatyperadiotext"
+ value="text"
+ checked><label for="datatyperadiotext">text</label>
+ <input type="radio"
+ name="datatyperadio"
+ id="datatyperadioblob"
+ value="blob"
+ ><label for="datatyperadioblob">blob</label>
+ <input type="radio"
+ name="datatyperadio"
+ id="datatyperadioarraybuffer"
+ value="arraybuffer"
+ ><label for="datatyperadioarraybuffer">arraybuffer</label>
+</form>
+
+<div id="log_div">
+ <textarea
+ id="log" rows="20" style="width: 100%" readonly></textarea>
+</div>
+<div id="summary_div">
+ Summary
+ <textarea
+ id="summary" rows="20" style="width: 100%" readonly></textarea>
+</div>
+
+Note: Effect of RTT and time spent for ArrayBuffer creation in receive benchmarks are not eliminated.
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/xhr_benchmark.js b/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/xhr_benchmark.js
new file mode 100644
index 00000000000..233c7cb38c4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/xhr_benchmark.js
@@ -0,0 +1,389 @@
+// Copyright 2014 Google Inc. All rights reserved.
+//
+// Use of this source code is governed by a BSD-style
+// license that can be found in the COPYING file or at
+// https://developers.google.com/open-source/licenses/bsd
+
+var isWorker = typeof importScripts !== "undefined";
+
+if (isWorker) {
+ // Running on a worker
+ importScripts('util.js', 'util_worker.js');
+}
+
+// Namespace for holding globals.
+var benchmark = {};
+benchmark.startTimeInMs = 0;
+
+var xhrs = [];
+
+var timerID = null;
+
+function destroyAllXHRs() {
+ for (var i = 0; i < xhrs.length; ++i) {
+ xhrs[i].onreadystatechange = null;
+ // Abort XHRs if they are not yet DONE state.
+ // Calling abort() here (i.e. in onreadystatechange handler)
+ // causes "NetworkError" messages in DevTools in sync mode,
+ // even if it is after transition to DONE state.
+ if (xhrs[i].readyState != XMLHttpRequest.DONE)
+ xhrs[i].abort();
+ }
+ xhrs = [];
+ // gc() might be needed for Chrome/Blob
+}
+
+function repeatString(str, count) {
+ var data = '';
+ var expChunk = str;
+ var remain = count;
+ while (true) {
+ if (remain % 2) {
+ data += expChunk;
+ remain = (remain - 1) / 2;
+ } else {
+ remain /= 2;
+ }
+
+ if (remain == 0)
+ break;
+
+ expChunk = expChunk + expChunk;
+ }
+ return data;
+}
+
+function sendBenchmarkStep(size, config) {
+ timerID = null;
+
+ benchmark.startTimeInMs = null;
+ var totalSize = 0;
+ var totalReplied = 0;
+
+ var onReadyStateChangeHandler = function () {
+ if (this.readyState != this.DONE) {
+ return;
+ }
+
+ if (this.status != 200) {
+ config.addToLog('Failed (status=' + this.status + ')');
+ destroyAllXHRs();
+ return;
+ }
+
+ if (config.verifyData &&
+ !verifyAcknowledgement(config, this.response, size)) {
+ destroyAllXHRs();
+ return;
+ }
+
+ totalReplied += size;
+
+ if (totalReplied < totalSize) {
+ return;
+ }
+
+ if (benchmark.startTimeInMs == null) {
+ config.addToLog('startTimeInMs not set');
+ destroyAllXHRs();
+ return;
+ }
+
+ calculateAndLogResult(config, size, benchmark.startTimeInMs, totalSize);
+
+ destroyAllXHRs();
+
+ runNextTask(config);
+ };
+
+ for (var i = 0; i < config.numXHRs; ++i) {
+ var xhr = new XMLHttpRequest();
+ xhr.onreadystatechange = onReadyStateChangeHandler;
+ xhrs.push(xhr);
+ }
+
+ var dataArray = [];
+
+ for (var i = 0; i < xhrs.length; ++i) {
+ var data = null;
+ if (config.dataType == 'arraybuffer' ||
+ config.dataType == 'blob') {
+ data = new ArrayBuffer(size);
+
+ fillArrayBuffer(data, 0x61);
+
+ if (config.dataType == 'blob') {
+ data = new Blob([data]);
+ }
+ } else {
+ data = repeatString('a', size);
+ }
+
+ dataArray.push(data);
+ }
+
+
+ benchmark.startTimeInMs = getTimeStamp();
+ totalSize = size * xhrs.length;
+
+ for (var i = 0; i < xhrs.length; ++i) {
+ var data = dataArray[i];
+ var xhr = xhrs[i];
+ xhr.open('POST', config.prefixUrl + '_send', config.async);
+ xhr.send(data);
+ }
+}
+
+function receiveBenchmarkStep(size, config) {
+ timerID = null;
+
+ benchmark.startTimeInMs = null;
+ var totalSize = 0;
+ var totalReplied = 0;
+
+ var checkResultAndContinue = function (bytesReceived, verificationResult) {
+ if (!verificationResult) {
+ config.addToLog('Response verification failed');
+ destroyAllXHRs();
+ return;
+ }
+
+ totalReplied += bytesReceived;
+
+ if (totalReplied < totalSize) {
+ return;
+ }
+
+ if (benchmark.startTimeInMs == null) {
+ config.addToLog('startTimeInMs not set');
+ destroyAllXHRs();
+ return;
+ }
+
+ calculateAndLogResult(config, size, benchmark.startTimeInMs, totalSize);
+
+ destroyAllXHRs();
+
+ runNextTask(config);
+ }
+
+ var onReadyStateChangeHandler = function () {
+ if (this.readyState != this.DONE) {
+ return;
+ }
+
+ if (this.status != 200) {
+ config.addToLog('Failed (status=' + this.status + ')');
+ destroyAllXHRs();
+ return;
+ }
+
+ var bytesReceived = -1;
+ if (this.responseType == 'arraybuffer') {
+ bytesReceived = this.response.byteLength;
+ } else if (this.responseType == 'blob') {
+ bytesReceived = this.response.size;
+ } else {
+ bytesReceived = this.response.length;
+ }
+ if (bytesReceived != size) {
+ config.addToLog('Expected ' + size +
+ 'B but received ' + bytesReceived + 'B');
+ destroyAllXHRs();
+ return;
+ }
+
+ if (this.responseType == 'arraybuffer') {
+ checkResultAndContinue(bytesReceived,
+ !config.verifyData || verifyArrayBuffer(this.response, 0x61));
+ } else if (this.responseType == 'blob') {
+ if (config.verifyData)
+ verifyBlob(config, this.response, 0x61, checkResultAndContinue);
+ else
+ checkResultAndContinue(bytesReceived, true);
+ } else {
+ checkResultAndContinue(
+ bytesReceived,
+ !config.verifyData ||
+ this.response == repeatString('a', this.response.length));
+ }
+ };
+
+ for (var i = 0; i < config.numXHRs; ++i) {
+ var xhr = new XMLHttpRequest();
+ xhr.onreadystatechange = onReadyStateChangeHandler;
+ xhrs.push(xhr);
+ }
+
+ benchmark.startTimeInMs = getTimeStamp();
+ totalSize = size * xhrs.length;
+
+ for (var i = 0; i < xhrs.length; ++i) {
+ var xhr = xhrs[i];
+ xhr.open('POST', config.prefixUrl + '_receive', config.async);
+ xhr.responseType = config.dataType;
+ xhr.send(size + ' none');
+ }
+}
+
+
+function getConfigString(config) {
+ return '(' + config.dataType +
+ ', verifyData=' + config.verifyData +
+ ', ' + (isWorker ? 'Worker' : 'Main') +
+ ', ' + (config.async ? 'Async' : 'Sync') +
+ ', numXHRs=' + config.numXHRs +
+ ', numIterations=' + config.numIterations +
+ ', numWarmUpIterations=' + config.numWarmUpIterations +
+ ')';
+}
+
+function startBenchmark(config) {
+ clearTimeout(timerID);
+ destroyAllXHRs();
+
+ runNextTask(config);
+}
+
+// TODO(hiroshige): the following code is the same as benchmark.html
+// and some of them should be merged into e.g. util.js
+
+var tasks = [];
+
+function runNextTask(config) {
+ var task = tasks.shift();
+ if (task == undefined) {
+ config.addToLog('Finished');
+ destroyAllXHRs();
+ return;
+ }
+ timerID = setTimeout(task, 0);
+}
+
+function buildLegendString(config) {
+ var legend = ''
+ if (config.printSize)
+ legend = 'Message size in KiB, Time/message in ms, ';
+ legend += 'Speed in kB/s';
+ return legend;
+}
+
+function addTasks(config, stepFunc) {
+ for (var i = 0;
+ i < config.numWarmUpIterations + config.numIterations; ++i) {
+ // Ignore the first |config.numWarmUpIterations| iterations.
+ if (i == config.numWarmUpIterations)
+ addResultClearingTask(config);
+
+ var multiplierIndex = 0;
+ for (var size = config.startSize;
+ size <= config.stopThreshold;
+ ++multiplierIndex) {
+ var task = stepFunc.bind(
+ null,
+ size,
+ config);
+ tasks.push(task);
+ size *= config.multipliers[
+ multiplierIndex % config.multipliers.length];
+ }
+ }
+}
+
+function addResultReportingTask(config, title) {
+ tasks.push(function(){
+ timerID = null;
+ config.addToSummary(title);
+ reportAverageData(config);
+ clearAverageData();
+ runNextTask(config);
+ });
+}
+
+function addResultClearingTask(config) {
+ tasks.push(function(){
+ timerID = null;
+ clearAverageData();
+ runNextTask(config);
+ });
+}
+
+// --------------------------------
+
+function sendBenchmark(config) {
+ config.addToLog('Send benchmark');
+ config.addToLog(buildLegendString(config));
+
+ tasks = [];
+ clearAverageData();
+ addTasks(config, sendBenchmarkStep);
+ addResultReportingTask(config, 'Send Benchmark ' + getConfigString(config));
+ startBenchmark(config);
+}
+
+function receiveBenchmark(config) {
+ config.addToLog('Receive benchmark');
+ config.addToLog(buildLegendString(config));
+
+ tasks = [];
+ clearAverageData();
+ addTasks(config, receiveBenchmarkStep);
+ addResultReportingTask(config,
+ 'Receive Benchmark ' + getConfigString(config));
+ startBenchmark(config);
+}
+
+function batchBenchmark(originalConfig) {
+ originalConfig.addToLog('Batch benchmark');
+
+ tasks = [];
+ clearAverageData();
+
+ var dataTypes = ['text', 'blob', 'arraybuffer'];
+ var stepFuncs = [sendBenchmarkStep, receiveBenchmarkStep];
+ var names = ['Send', 'Receive'];
+ var async = [true, false];
+ for (var i = 0; i < stepFuncs.length; ++i) {
+ for (var j = 0; j < dataTypes.length; ++j) {
+ for (var k = 0; k < async.length; ++k) {
+ var config = cloneConfig(originalConfig);
+ config.dataType = dataTypes[j];
+ config.async = async[k];
+
+ // Receive && Non-Worker && Sync is not supported by the spec
+ if (stepFuncs[i] === receiveBenchmarkStep && !isWorker &&
+ !config.async)
+ continue;
+
+ addTasks(config, stepFuncs[i]);
+ addResultReportingTask(config,
+ names[i] + ' benchmark ' + getConfigString(config));
+ }
+ }
+ }
+
+ startBenchmark(config);
+}
+
+
+function stop(config) {
+ destroyAllXHRs();
+ clearTimeout(timerID);
+ timerID = null;
+ config.addToLog('Stopped');
+}
+
+onmessage = function (message) {
+ var config = message.data.config;
+ config.addToLog = workerAddToLog;
+ config.addToSummary = workerAddToSummary;
+ config.measureValue = workerMeasureValue;
+ if (message.data.type === 'sendBenchmark')
+ sendBenchmark(config);
+ else if (message.data.type === 'receiveBenchmark')
+ receiveBenchmark(config);
+ else if (message.data.type === 'batchBenchmark')
+ batchBenchmark(config);
+ else if (message.data.type === 'stop')
+ stop(config);
+};
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/xhr_event_logger.html b/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/xhr_event_logger.html
new file mode 100644
index 00000000000..6983553b8ac
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/example/xhr_event_logger.html
@@ -0,0 +1,110 @@
+<!--
+Copyright 2014 Google Inc. All rights reserved.
+
+Use of this source code is governed by a BSD-style
+license that can be found in the COPYING file or at
+https://developers.google.com/open-source/licenses/bsd
+-->
+
+<html>
+<head>
+<title>XHR event logger</title>
+<script src="util_main.js"></script>
+<script>
+var events = [];
+
+function run() {
+ events = [];
+
+ function pushToLog(type) {
+ if (events.length != 0 && type === events[events.length - 1].type) {
+ events[events.length - 1].count += 1;
+ } else {
+ events.push({type: type, count: 1});
+ }
+ }
+
+ var xhr = new XMLHttpRequest();
+
+ function getProgressEventDump(e) {
+ return '(' + e.lengthComputable + ', ' + e.loaded + ', ' + e.total + ')';
+ }
+
+ var dumpProgressEvent = getBoolFromCheckBox('dumpprogressevent');
+
+ function log(e) {
+ var type = e.type;
+ if (type === 'readystatechange') {
+ type += e.target.readyState;
+ }
+ if (dumpProgressEvent && (e instanceof ProgressEvent)) {
+ type += getProgressEventDump(e);
+ }
+ pushToLog(type);
+ };
+
+ function logUpload(e) {
+ var type = e.type;
+ if (dumpProgressEvent && (e instanceof ProgressEvent)) {
+ type += getProgressEventDump(e);
+ }
+ pushToLog('upload' + type);
+ }
+
+ if (getBoolFromCheckBox('upload')) {
+ var upload = xhr.upload;
+ upload.onloadstart = logUpload;
+ upload.onprogress = logUpload;
+ upload.onabort = logUpload;
+ upload.onerror = logUpload;
+ upload.onload = logUpload;
+ upload.ontimeout = logUpload;
+ upload.onloadend = logUpload;
+ }
+
+ xhr.onreadystatechange = log;
+ xhr.onloadstart = log;
+ xhr.onprogress = log;
+ xhr.onabort = log;
+ xhr.onerror = log;
+ xhr.onload = log;
+ xhr.ontimeout = log;
+ xhr.onloadend = log;
+
+ xhr.open('POST', '/073be001e10950692ccbf3a2ad21c245_receive',
+ getBoolFromCheckBox('async'));
+ var size = getIntFromInput('size');
+ var chunkedMode = 'none';
+ if (getBoolFromCheckBox('chunkedresponse')) {
+ chunkedMode = 'chunked';
+ }
+ xhr.send(size + ' ' + chunkedMode);
+}
+
+function print() {
+ var result = '';
+ for (var i = 0; i < events.length; ++i) {
+ var event = events[i];
+ result += event.type + ' * ' + event.count + '\n';
+ }
+ document.getElementById('log').value = result;
+}
+</script>
+
+<body>
+ <textarea id="log" rows="10" cols="40" readonly></textarea>
+ <br/>
+ Size: <input type="text" id="size" value="65536"><br/>
+ <input type="checkbox" id="chunkedresponse">
+ <label for="chunkedresponse">Use Chunked T-E for response</label><br/>
+ <input type="checkbox" id="upload">
+ <label for="upload">Upload progress</label><br/>
+ <input type="checkbox" id="dumpprogressevent">
+ <label for="dumpprogressevent">
+ Dump lengthComputable/loaded/total</label><br/>
+ <input type="checkbox" id="async" checked>
+ <label for="async">Async</label><br/>
+ <input type="button" onclick="run()" value="Run XHR">
+ <input type="button" onclick="print()" value="Print log">
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/__init__.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/__init__.py
new file mode 100644
index 00000000000..70933a22045
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/__init__.py
@@ -0,0 +1,224 @@
+# Copyright 2011, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+"""WebSocket extension for Apache HTTP Server.
+
+mod_pywebsocket is a WebSocket extension for Apache HTTP Server
+intended for testing or experimental purposes. mod_python is required.
+
+
+Installation
+============
+
+0. Prepare an Apache HTTP Server for which mod_python is enabled.
+
+1. Specify the following Apache HTTP Server directives to suit your
+ configuration.
+
+ If mod_pywebsocket is not in the Python path, specify the following.
+ <websock_lib> is the directory where mod_pywebsocket is installed.
+
+ PythonPath "sys.path+['<websock_lib>']"
+
+ Always specify the following. <websock_handlers> is the directory where
+ user-written WebSocket handlers are placed.
+
+ PythonOption mod_pywebsocket.handler_root <websock_handlers>
+ PythonHeaderParserHandler mod_pywebsocket.headerparserhandler
+
+ To limit the search for WebSocket handlers to a directory <scan_dir>
+ under <websock_handlers>, configure as follows:
+
+ PythonOption mod_pywebsocket.handler_scan <scan_dir>
+
+ <scan_dir> is useful in saving scan time when <websock_handlers>
+ contains many non-WebSocket handler files.
+
+ If you want to allow handlers whose canonical path is not under the root
+ directory (i.e. symbolic link is in root directory but its target is not),
+ configure as follows:
+
+ PythonOption mod_pywebsocket.allow_handlers_outside_root_dir On
+
+ Example snippet of httpd.conf:
+ (mod_pywebsocket is in /websock_lib, WebSocket handlers are in
+ /websock_handlers, port is 80 for ws, 443 for wss.)
+
+ <IfModule python_module>
+ PythonPath "sys.path+['/websock_lib']"
+ PythonOption mod_pywebsocket.handler_root /websock_handlers
+ PythonHeaderParserHandler mod_pywebsocket.headerparserhandler
+ </IfModule>
+
+2. Tune Apache parameters for serving WebSocket. We'd like to note that at
+ least TimeOut directive from core features and RequestReadTimeout
+ directive from mod_reqtimeout should be modified not to kill connections
+ in only a few seconds of idle time.
+
+3. Verify installation. You can use example/console.html to poke the server.
+
+
+Writing WebSocket handlers
+==========================
+
+When a WebSocket request comes in, the resource name
+specified in the handshake is considered as if it is a file path under
+<websock_handlers> and the handler defined in
+<websock_handlers>/<resource_name>_wsh.py is invoked.
+
+For example, if the resource name is /example/chat, the handler defined in
+<websock_handlers>/example/chat_wsh.py is invoked.
+
+A WebSocket handler is composed of the following three functions:
+
+ web_socket_do_extra_handshake(request)
+ web_socket_transfer_data(request)
+ web_socket_passive_closing_handshake(request)
+
+where:
+ request: mod_python request.
+
+web_socket_do_extra_handshake is called during the handshake after the
+headers are successfully parsed and WebSocket properties (ws_location,
+ws_origin, and ws_resource) are added to request. A handler
+can reject the request by raising an exception.
+
+A request object has the following properties that you can use during the
+extra handshake (web_socket_do_extra_handshake):
+- ws_resource
+- ws_origin
+- ws_version
+- ws_location (HyBi 00 only)
+- ws_extensions (HyBi 06 and later)
+- ws_deflate (HyBi 06 and later)
+- ws_protocol
+- ws_requested_protocols (HyBi 06 and later)
+
+The last two are a bit tricky. See the next subsection.
+
+
+Subprotocol Negotiation
+-----------------------
+
+For HyBi 06 and later, ws_protocol is always set to None when
+web_socket_do_extra_handshake is called. If ws_requested_protocols is not
+None, you must choose one subprotocol from this list and set it to
+ws_protocol.
+
+For HyBi 00, when web_socket_do_extra_handshake is called,
+ws_protocol is set to the value given by the client in
+Sec-WebSocket-Protocol header or None if
+such header was not found in the opening handshake request. Finish extra
+handshake with ws_protocol untouched to accept the request subprotocol.
+Then, Sec-WebSocket-Protocol header will be sent to
+the client in response with the same value as requested. Raise an exception
+in web_socket_do_extra_handshake to reject the requested subprotocol.
+
+
+Data Transfer
+-------------
+
+web_socket_transfer_data is called after the handshake completed
+successfully. A handler can receive/send messages from/to the client
+using request. mod_pywebsocket.msgutil module provides utilities
+for data transfer.
+
+You can receive a message by the following statement.
+
+ message = request.ws_stream.receive_message()
+
+This call blocks until any complete text frame arrives, and the payload data
+of the incoming frame will be stored into message. When you're using IETF
+HyBi 00 or later protocol, receive_message() will return None on receiving
+client-initiated closing handshake. When any error occurs, receive_message()
+will raise some exception.
+
+You can send a message by the following statement.
+
+ request.ws_stream.send_message(message)
+
+
+Closing Connection
+------------------
+
+Executing the following statement or just return-ing from
+web_socket_transfer_data cause connection close.
+
+ request.ws_stream.close_connection()
+
+close_connection will wait
+for closing handshake acknowledgement coming from the client. When it
+couldn't receive a valid acknowledgement, raises an exception.
+
+web_socket_passive_closing_handshake is called after the server receives
+incoming closing frame from the client peer immediately. You can specify
+code and reason by return values. They are sent as a outgoing closing frame
+from the server. A request object has the following properties that you can
+use in web_socket_passive_closing_handshake.
+- ws_close_code
+- ws_close_reason
+
+
+Threading
+---------
+
+A WebSocket handler must be thread-safe if the server (Apache or
+standalone.py) is configured to use threads.
+
+
+Configuring WebSocket Extension Processors
+------------------------------------------
+
+See extensions.py for supported WebSocket extensions. Note that they are
+unstable and their APIs are subject to change substantially.
+
+A request object has these extension processing related attributes.
+
+- ws_requested_extensions:
+
+ A list of common.ExtensionParameter instances representing extension
+ parameters received from the client in the client's opening handshake.
+ You shouldn't modify it manually.
+
+- ws_extensions:
+
+ A list of common.ExtensionParameter instances representing extension
+ parameters to send back to the client in the server's opening handshake.
+ You shouldn't touch it directly. Instead, call methods on extension
+ processors.
+
+- ws_extension_processors:
+
+ A list of loaded extension processors. Find the processor for the
+ extension you want to configure from it, and call its methods.
+"""
+
+
+# vi:sts=4 sw=4 et tw=72
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/_stream_base.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/_stream_base.py
new file mode 100644
index 00000000000..8235666bbb1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/_stream_base.py
@@ -0,0 +1,181 @@
+# Copyright 2011, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+"""Base stream class.
+"""
+
+
+# Note: request.connection.write/read are used in this module, even though
+# mod_python document says that they should be used only in connection
+# handlers. Unfortunately, we have no other options. For example,
+# request.write/read are not suitable because they don't allow direct raw bytes
+# writing/reading.
+
+
+import socket
+
+from mod_pywebsocket import util
+
+
+# Exceptions
+
+
+class ConnectionTerminatedException(Exception):
+ """This exception will be raised when a connection is terminated
+ unexpectedly.
+ """
+
+ pass
+
+
+class InvalidFrameException(ConnectionTerminatedException):
+ """This exception will be raised when we received an invalid frame we
+ cannot parse.
+ """
+
+ pass
+
+
+class BadOperationException(Exception):
+ """This exception will be raised when send_message() is called on
+ server-terminated connection or receive_message() is called on
+ client-terminated connection.
+ """
+
+ pass
+
+
+class UnsupportedFrameException(Exception):
+ """This exception will be raised when we receive a frame with flag, opcode
+ we cannot handle. Handlers can just catch and ignore this exception and
+ call receive_message() again to continue processing the next frame.
+ """
+
+ pass
+
+
+class InvalidUTF8Exception(Exception):
+ """This exception will be raised when we receive a text frame which
+ contains invalid UTF-8 strings.
+ """
+
+ pass
+
+
+class StreamBase(object):
+ """Base stream class."""
+
+ def __init__(self, request):
+ """Construct an instance.
+
+ Args:
+ request: mod_python request.
+ """
+
+ self._logger = util.get_class_logger(self)
+
+ self._request = request
+
+ def _read(self, length):
+ """Reads length bytes from connection. In case we catch any exception,
+ prepends remote address to the exception message and raise again.
+
+ Raises:
+ ConnectionTerminatedException: when read returns empty string.
+ """
+
+ try:
+ read_bytes = self._request.connection.read(length)
+ if not read_bytes:
+ raise ConnectionTerminatedException(
+ 'Receiving %d byte failed. Peer (%r) closed connection' %
+ (length, (self._request.connection.remote_addr,)))
+ return read_bytes
+ except socket.error, e:
+ # Catch a socket.error. Because it's not a child class of the
+ # IOError prior to Python 2.6, we cannot omit this except clause.
+ # Use %s rather than %r for the exception to use human friendly
+ # format.
+ raise ConnectionTerminatedException(
+ 'Receiving %d byte failed. socket.error (%s) occurred' %
+ (length, e))
+ except IOError, e:
+ # Also catch an IOError because mod_python throws it.
+ raise ConnectionTerminatedException(
+ 'Receiving %d byte failed. IOError (%s) occurred' %
+ (length, e))
+
+ def _write(self, bytes_to_write):
+ """Writes given bytes to connection. In case we catch any exception,
+ prepends remote address to the exception message and raise again.
+ """
+
+ try:
+ self._request.connection.write(bytes_to_write)
+ except Exception, e:
+ util.prepend_message_to_exception(
+ 'Failed to send message to %r: ' %
+ (self._request.connection.remote_addr,),
+ e)
+ raise
+
+ def receive_bytes(self, length):
+ """Receives multiple bytes. Retries read when we couldn't receive the
+ specified amount.
+
+ Raises:
+ ConnectionTerminatedException: when read returns empty string.
+ """
+
+ read_bytes = []
+ while length > 0:
+ new_read_bytes = self._read(length)
+ read_bytes.append(new_read_bytes)
+ length -= len(new_read_bytes)
+ return ''.join(read_bytes)
+
+ def _read_until(self, delim_char):
+ """Reads bytes until we encounter delim_char. The result will not
+ contain delim_char.
+
+ Raises:
+ ConnectionTerminatedException: when read returns empty string.
+ """
+
+ read_bytes = []
+ while True:
+ ch = self._read(1)
+ if ch == delim_char:
+ break
+ read_bytes.append(ch)
+ return ''.join(read_bytes)
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/_stream_hixie75.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/_stream_hixie75.py
new file mode 100644
index 00000000000..94cf5b31ba0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/_stream_hixie75.py
@@ -0,0 +1,229 @@
+# Copyright 2011, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+"""This file provides a class for parsing/building frames of the WebSocket
+protocol version HyBi 00 and Hixie 75.
+
+Specification:
+- HyBi 00 http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-00
+- Hixie 75 http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-75
+"""
+
+
+from mod_pywebsocket import common
+from mod_pywebsocket._stream_base import BadOperationException
+from mod_pywebsocket._stream_base import ConnectionTerminatedException
+from mod_pywebsocket._stream_base import InvalidFrameException
+from mod_pywebsocket._stream_base import StreamBase
+from mod_pywebsocket._stream_base import UnsupportedFrameException
+from mod_pywebsocket import util
+
+
+class StreamHixie75(StreamBase):
+ """A class for parsing/building frames of the WebSocket protocol version
+ HyBi 00 and Hixie 75.
+ """
+
+ def __init__(self, request, enable_closing_handshake=False):
+ """Construct an instance.
+
+ Args:
+ request: mod_python request.
+ enable_closing_handshake: to let StreamHixie75 perform closing
+ handshake as specified in HyBi 00, set
+ this option to True.
+ """
+
+ StreamBase.__init__(self, request)
+
+ self._logger = util.get_class_logger(self)
+
+ self._enable_closing_handshake = enable_closing_handshake
+
+ self._request.client_terminated = False
+ self._request.server_terminated = False
+
+ def send_message(self, message, end=True, binary=False):
+ """Send message.
+
+ Args:
+ message: unicode string to send.
+ binary: not used in hixie75.
+
+ Raises:
+ BadOperationException: when called on a server-terminated
+ connection.
+ """
+
+ if not end:
+ raise BadOperationException(
+ 'StreamHixie75 doesn\'t support send_message with end=False')
+
+ if binary:
+ raise BadOperationException(
+ 'StreamHixie75 doesn\'t support send_message with binary=True')
+
+ if self._request.server_terminated:
+ raise BadOperationException(
+ 'Requested send_message after sending out a closing handshake')
+
+ self._write(''.join(['\x00', message.encode('utf-8'), '\xff']))
+
+ def _read_payload_length_hixie75(self):
+ """Reads a length header in a Hixie75 version frame with length.
+
+ Raises:
+ ConnectionTerminatedException: when read returns empty string.
+ """
+
+ length = 0
+ while True:
+ b_str = self._read(1)
+ b = ord(b_str)
+ length = length * 128 + (b & 0x7f)
+ if (b & 0x80) == 0:
+ break
+ return length
+
+ def receive_message(self):
+ """Receive a WebSocket frame and return its payload an unicode string.
+
+ Returns:
+ payload unicode string in a WebSocket frame.
+
+ Raises:
+ ConnectionTerminatedException: when read returns empty
+ string.
+ BadOperationException: when called on a client-terminated
+ connection.
+ """
+
+ if self._request.client_terminated:
+ raise BadOperationException(
+ 'Requested receive_message after receiving a closing '
+ 'handshake')
+
+ while True:
+ # Read 1 byte.
+ # mp_conn.read will block if no bytes are available.
+ # Timeout is controlled by TimeOut directive of Apache.
+ frame_type_str = self.receive_bytes(1)
+ frame_type = ord(frame_type_str)
+ if (frame_type & 0x80) == 0x80:
+ # The payload length is specified in the frame.
+ # Read and discard.
+ length = self._read_payload_length_hixie75()
+ if length > 0:
+ _ = self.receive_bytes(length)
+ # 5.3 3. 12. if /type/ is 0xFF and /length/ is 0, then set the
+ # /client terminated/ flag and abort these steps.
+ if not self._enable_closing_handshake:
+ continue
+
+ if frame_type == 0xFF and length == 0:
+ self._request.client_terminated = True
+
+ if self._request.server_terminated:
+ self._logger.debug(
+ 'Received ack for server-initiated closing '
+ 'handshake')
+ return None
+
+ self._logger.debug(
+ 'Received client-initiated closing handshake')
+
+ self._send_closing_handshake()
+ self._logger.debug(
+ 'Sent ack for client-initiated closing handshake')
+ return None
+ else:
+ # The payload is delimited with \xff.
+ bytes = self._read_until('\xff')
+ # The WebSocket protocol section 4.4 specifies that invalid
+ # characters must be replaced with U+fffd REPLACEMENT
+ # CHARACTER.
+ message = bytes.decode('utf-8', 'replace')
+ if frame_type == 0x00:
+ return message
+ # Discard data of other types.
+
+ def _send_closing_handshake(self):
+ if not self._enable_closing_handshake:
+ raise BadOperationException(
+ 'Closing handshake is not supported in Hixie 75 protocol')
+
+ self._request.server_terminated = True
+
+ # 5.3 the server may decide to terminate the WebSocket connection by
+ # running through the following steps:
+ # 1. send a 0xFF byte and a 0x00 byte to the client to indicate the
+ # start of the closing handshake.
+ self._write('\xff\x00')
+
+ def close_connection(self, unused_code='', unused_reason=''):
+ """Closes a WebSocket connection.
+
+ Raises:
+ ConnectionTerminatedException: when closing handshake was
+ not successfull.
+ """
+
+ if self._request.server_terminated:
+ self._logger.debug(
+ 'Requested close_connection but server is already terminated')
+ return
+
+ if not self._enable_closing_handshake:
+ self._request.server_terminated = True
+ self._logger.debug('Connection closed')
+ return
+
+ self._send_closing_handshake()
+ self._logger.debug('Sent server-initiated closing handshake')
+
+ # TODO(ukai): 2. wait until the /client terminated/ flag has been set,
+ # or until a server-defined timeout expires.
+ #
+ # For now, we expect receiving closing handshake right after sending
+ # out closing handshake, and if we couldn't receive non-handshake
+ # frame, we take it as ConnectionTerminatedException.
+ message = self.receive_message()
+ if message is not None:
+ raise ConnectionTerminatedException(
+ 'Didn\'t receive valid ack for closing handshake')
+ # TODO: 3. close the WebSocket connection.
+ # note: mod_python Connection (mp_conn) doesn't have close method.
+
+ def send_ping(self, body):
+ raise BadOperationException(
+ 'StreamHixie75 doesn\'t support send_ping')
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/_stream_hybi.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/_stream_hybi.py
new file mode 100644
index 00000000000..a8a49e3c3dc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/_stream_hybi.py
@@ -0,0 +1,887 @@
+# Copyright 2012, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+"""This file provides classes and helper functions for parsing/building frames
+of the WebSocket protocol (RFC 6455).
+
+Specification:
+http://tools.ietf.org/html/rfc6455
+"""
+
+
+from collections import deque
+import logging
+import os
+import struct
+import time
+
+from mod_pywebsocket import common
+from mod_pywebsocket import util
+from mod_pywebsocket._stream_base import BadOperationException
+from mod_pywebsocket._stream_base import ConnectionTerminatedException
+from mod_pywebsocket._stream_base import InvalidFrameException
+from mod_pywebsocket._stream_base import InvalidUTF8Exception
+from mod_pywebsocket._stream_base import StreamBase
+from mod_pywebsocket._stream_base import UnsupportedFrameException
+
+
+_NOOP_MASKER = util.NoopMasker()
+
+
+class Frame(object):
+
+ def __init__(self, fin=1, rsv1=0, rsv2=0, rsv3=0,
+ opcode=None, payload=''):
+ self.fin = fin
+ self.rsv1 = rsv1
+ self.rsv2 = rsv2
+ self.rsv3 = rsv3
+ self.opcode = opcode
+ self.payload = payload
+
+
+# Helper functions made public to be used for writing unittests for WebSocket
+# clients.
+
+
+def create_length_header(length, mask):
+ """Creates a length header.
+
+ Args:
+ length: Frame length. Must be less than 2^63.
+ mask: Mask bit. Must be boolean.
+
+ Raises:
+ ValueError: when bad data is given.
+ """
+
+ if mask:
+ mask_bit = 1 << 7
+ else:
+ mask_bit = 0
+
+ if length < 0:
+ raise ValueError('length must be non negative integer')
+ elif length <= 125:
+ return chr(mask_bit | length)
+ elif length < (1 << 16):
+ return chr(mask_bit | 126) + struct.pack('!H', length)
+ elif length < (1 << 63):
+ return chr(mask_bit | 127) + struct.pack('!Q', length)
+ else:
+ raise ValueError('Payload is too big for one frame')
+
+
+def create_header(opcode, payload_length, fin, rsv1, rsv2, rsv3, mask):
+ """Creates a frame header.
+
+ Raises:
+ Exception: when bad data is given.
+ """
+
+ if opcode < 0 or 0xf < opcode:
+ raise ValueError('Opcode out of range')
+
+ if payload_length < 0 or (1 << 63) <= payload_length:
+ raise ValueError('payload_length out of range')
+
+ if (fin | rsv1 | rsv2 | rsv3) & ~1:
+ raise ValueError('FIN bit and Reserved bit parameter must be 0 or 1')
+
+ header = ''
+
+ first_byte = ((fin << 7)
+ | (rsv1 << 6) | (rsv2 << 5) | (rsv3 << 4)
+ | opcode)
+ header += chr(first_byte)
+ header += create_length_header(payload_length, mask)
+
+ return header
+
+
+def _build_frame(header, body, mask):
+ if not mask:
+ return header + body
+
+ masking_nonce = os.urandom(4)
+ masker = util.RepeatedXorMasker(masking_nonce)
+
+ return header + masking_nonce + masker.mask(body)
+
+
+def _filter_and_format_frame_object(frame, mask, frame_filters):
+ for frame_filter in frame_filters:
+ frame_filter.filter(frame)
+
+ header = create_header(
+ frame.opcode, len(frame.payload), frame.fin,
+ frame.rsv1, frame.rsv2, frame.rsv3, mask)
+ return _build_frame(header, frame.payload, mask)
+
+
+def create_binary_frame(
+ message, opcode=common.OPCODE_BINARY, fin=1, mask=False, frame_filters=[]):
+ """Creates a simple binary frame with no extension, reserved bit."""
+
+ frame = Frame(fin=fin, opcode=opcode, payload=message)
+ return _filter_and_format_frame_object(frame, mask, frame_filters)
+
+
+def create_text_frame(
+ message, opcode=common.OPCODE_TEXT, fin=1, mask=False, frame_filters=[]):
+ """Creates a simple text frame with no extension, reserved bit."""
+
+ encoded_message = message.encode('utf-8')
+ return create_binary_frame(encoded_message, opcode, fin, mask,
+ frame_filters)
+
+
+def parse_frame(receive_bytes, logger=None,
+ ws_version=common.VERSION_HYBI_LATEST,
+ unmask_receive=True):
+ """Parses a frame. Returns a tuple containing each header field and
+ payload.
+
+ Args:
+ receive_bytes: a function that reads frame data from a stream or
+ something similar. The function takes length of the bytes to be
+ read. The function must raise ConnectionTerminatedException if
+ there is not enough data to be read.
+ logger: a logging object.
+ ws_version: the version of WebSocket protocol.
+ unmask_receive: unmask received frames. When received unmasked
+ frame, raises InvalidFrameException.
+
+ Raises:
+ ConnectionTerminatedException: when receive_bytes raises it.
+ InvalidFrameException: when the frame contains invalid data.
+ """
+
+ if not logger:
+ logger = logging.getLogger()
+
+ logger.log(common.LOGLEVEL_FINE, 'Receive the first 2 octets of a frame')
+
+ received = receive_bytes(2)
+
+ first_byte = ord(received[0])
+ fin = (first_byte >> 7) & 1
+ rsv1 = (first_byte >> 6) & 1
+ rsv2 = (first_byte >> 5) & 1
+ rsv3 = (first_byte >> 4) & 1
+ opcode = first_byte & 0xf
+
+ second_byte = ord(received[1])
+ mask = (second_byte >> 7) & 1
+ payload_length = second_byte & 0x7f
+
+ logger.log(common.LOGLEVEL_FINE,
+ 'FIN=%s, RSV1=%s, RSV2=%s, RSV3=%s, opcode=%s, '
+ 'Mask=%s, Payload_length=%s',
+ fin, rsv1, rsv2, rsv3, opcode, mask, payload_length)
+
+ if (mask == 1) != unmask_receive:
+ raise InvalidFrameException(
+ 'Mask bit on the received frame did\'nt match masking '
+ 'configuration for received frames')
+
+ # The HyBi and later specs disallow putting a value in 0x0-0xFFFF
+ # into the 8-octet extended payload length field (or 0x0-0xFD in
+ # 2-octet field).
+ valid_length_encoding = True
+ length_encoding_bytes = 1
+ if payload_length == 127:
+ logger.log(common.LOGLEVEL_FINE,
+ 'Receive 8-octet extended payload length')
+
+ extended_payload_length = receive_bytes(8)
+ payload_length = struct.unpack(
+ '!Q', extended_payload_length)[0]
+ if payload_length > 0x7FFFFFFFFFFFFFFF:
+ raise InvalidFrameException(
+ 'Extended payload length >= 2^63')
+ if ws_version >= 13 and payload_length < 0x10000:
+ valid_length_encoding = False
+ length_encoding_bytes = 8
+
+ logger.log(common.LOGLEVEL_FINE,
+ 'Decoded_payload_length=%s', payload_length)
+ elif payload_length == 126:
+ logger.log(common.LOGLEVEL_FINE,
+ 'Receive 2-octet extended payload length')
+
+ extended_payload_length = receive_bytes(2)
+ payload_length = struct.unpack(
+ '!H', extended_payload_length)[0]
+ if ws_version >= 13 and payload_length < 126:
+ valid_length_encoding = False
+ length_encoding_bytes = 2
+
+ logger.log(common.LOGLEVEL_FINE,
+ 'Decoded_payload_length=%s', payload_length)
+
+ if not valid_length_encoding:
+ logger.warning(
+ 'Payload length is not encoded using the minimal number of '
+ 'bytes (%d is encoded using %d bytes)',
+ payload_length,
+ length_encoding_bytes)
+
+ if mask == 1:
+ logger.log(common.LOGLEVEL_FINE, 'Receive mask')
+
+ masking_nonce = receive_bytes(4)
+ masker = util.RepeatedXorMasker(masking_nonce)
+
+ logger.log(common.LOGLEVEL_FINE, 'Mask=%r', masking_nonce)
+ else:
+ masker = _NOOP_MASKER
+
+ logger.log(common.LOGLEVEL_FINE, 'Receive payload data')
+ if logger.isEnabledFor(common.LOGLEVEL_FINE):
+ receive_start = time.time()
+
+ raw_payload_bytes = receive_bytes(payload_length)
+
+ if logger.isEnabledFor(common.LOGLEVEL_FINE):
+ logger.log(
+ common.LOGLEVEL_FINE,
+ 'Done receiving payload data at %s MB/s',
+ payload_length / (time.time() - receive_start) / 1000 / 1000)
+ logger.log(common.LOGLEVEL_FINE, 'Unmask payload data')
+
+ if logger.isEnabledFor(common.LOGLEVEL_FINE):
+ unmask_start = time.time()
+
+ unmasked_bytes = masker.mask(raw_payload_bytes)
+
+ if logger.isEnabledFor(common.LOGLEVEL_FINE):
+ logger.log(
+ common.LOGLEVEL_FINE,
+ 'Done unmasking payload data at %s MB/s',
+ payload_length / (time.time() - unmask_start) / 1000 / 1000)
+
+ return opcode, unmasked_bytes, fin, rsv1, rsv2, rsv3
+
+
+class FragmentedFrameBuilder(object):
+ """A stateful class to send a message as fragments."""
+
+ def __init__(self, mask, frame_filters=[], encode_utf8=True):
+ """Constructs an instance."""
+
+ self._mask = mask
+ self._frame_filters = frame_filters
+ # This is for skipping UTF-8 encoding when building text type frames
+ # from compressed data.
+ self._encode_utf8 = encode_utf8
+
+ self._started = False
+
+ # Hold opcode of the first frame in messages to verify types of other
+ # frames in the message are all the same.
+ self._opcode = common.OPCODE_TEXT
+
+ def build(self, payload_data, end, binary):
+ if binary:
+ frame_type = common.OPCODE_BINARY
+ else:
+ frame_type = common.OPCODE_TEXT
+ if self._started:
+ if self._opcode != frame_type:
+ raise ValueError('Message types are different in frames for '
+ 'the same message')
+ opcode = common.OPCODE_CONTINUATION
+ else:
+ opcode = frame_type
+ self._opcode = frame_type
+
+ if end:
+ self._started = False
+ fin = 1
+ else:
+ self._started = True
+ fin = 0
+
+ if binary or not self._encode_utf8:
+ return create_binary_frame(
+ payload_data, opcode, fin, self._mask, self._frame_filters)
+ else:
+ return create_text_frame(
+ payload_data, opcode, fin, self._mask, self._frame_filters)
+
+
+def _create_control_frame(opcode, body, mask, frame_filters):
+ frame = Frame(opcode=opcode, payload=body)
+
+ for frame_filter in frame_filters:
+ frame_filter.filter(frame)
+
+ if len(frame.payload) > 125:
+ raise BadOperationException(
+ 'Payload data size of control frames must be 125 bytes or less')
+
+ header = create_header(
+ frame.opcode, len(frame.payload), frame.fin,
+ frame.rsv1, frame.rsv2, frame.rsv3, mask)
+ return _build_frame(header, frame.payload, mask)
+
+
+def create_ping_frame(body, mask=False, frame_filters=[]):
+ return _create_control_frame(common.OPCODE_PING, body, mask, frame_filters)
+
+
+def create_pong_frame(body, mask=False, frame_filters=[]):
+ return _create_control_frame(common.OPCODE_PONG, body, mask, frame_filters)
+
+
+def create_close_frame(body, mask=False, frame_filters=[]):
+ return _create_control_frame(
+ common.OPCODE_CLOSE, body, mask, frame_filters)
+
+
+def create_closing_handshake_body(code, reason):
+ body = ''
+ if code is not None:
+ if (code > common.STATUS_USER_PRIVATE_MAX or
+ code < common.STATUS_NORMAL_CLOSURE):
+ raise BadOperationException('Status code is out of range')
+ if (code == common.STATUS_NO_STATUS_RECEIVED or
+ code == common.STATUS_ABNORMAL_CLOSURE or
+ code == common.STATUS_TLS_HANDSHAKE):
+ raise BadOperationException('Status code is reserved pseudo '
+ 'code')
+ encoded_reason = reason.encode('utf-8')
+ body = struct.pack('!H', code) + encoded_reason
+ return body
+
+
+class StreamOptions(object):
+ """Holds option values to configure Stream objects."""
+
+ def __init__(self):
+ """Constructs StreamOptions."""
+
+ # Filters applied to frames.
+ self.outgoing_frame_filters = []
+ self.incoming_frame_filters = []
+
+ # Filters applied to messages. Control frames are not affected by them.
+ self.outgoing_message_filters = []
+ self.incoming_message_filters = []
+
+ self.encode_text_message_to_utf8 = True
+ self.mask_send = False
+ self.unmask_receive = True
+
+
+class Stream(StreamBase):
+ """A class for parsing/building frames of the WebSocket protocol
+ (RFC 6455).
+ """
+
+ def __init__(self, request, options):
+ """Constructs an instance.
+
+ Args:
+ request: mod_python request.
+ """
+
+ StreamBase.__init__(self, request)
+
+ self._logger = util.get_class_logger(self)
+
+ self._options = options
+
+ self._request.client_terminated = False
+ self._request.server_terminated = False
+
+ # Holds body of received fragments.
+ self._received_fragments = []
+ # Holds the opcode of the first fragment.
+ self._original_opcode = None
+
+ self._writer = FragmentedFrameBuilder(
+ self._options.mask_send, self._options.outgoing_frame_filters,
+ self._options.encode_text_message_to_utf8)
+
+ self._ping_queue = deque()
+
+ def _receive_frame(self):
+ """Receives a frame and return data in the frame as a tuple containing
+ each header field and payload separately.
+
+ Raises:
+ ConnectionTerminatedException: when read returns empty
+ string.
+ InvalidFrameException: when the frame contains invalid data.
+ """
+
+ def _receive_bytes(length):
+ return self.receive_bytes(length)
+
+ return parse_frame(receive_bytes=_receive_bytes,
+ logger=self._logger,
+ ws_version=self._request.ws_version,
+ unmask_receive=self._options.unmask_receive)
+
+ def _receive_frame_as_frame_object(self):
+ opcode, unmasked_bytes, fin, rsv1, rsv2, rsv3 = self._receive_frame()
+
+ return Frame(fin=fin, rsv1=rsv1, rsv2=rsv2, rsv3=rsv3,
+ opcode=opcode, payload=unmasked_bytes)
+
+ def receive_filtered_frame(self):
+ """Receives a frame and applies frame filters and message filters.
+ The frame to be received must satisfy following conditions:
+ - The frame is not fragmented.
+ - The opcode of the frame is TEXT or BINARY.
+
+ DO NOT USE this method except for testing purpose.
+ """
+
+ frame = self._receive_frame_as_frame_object()
+ if not frame.fin:
+ raise InvalidFrameException(
+ 'Segmented frames must not be received via '
+ 'receive_filtered_frame()')
+ if (frame.opcode != common.OPCODE_TEXT and
+ frame.opcode != common.OPCODE_BINARY):
+ raise InvalidFrameException(
+ 'Control frames must not be received via '
+ 'receive_filtered_frame()')
+
+ for frame_filter in self._options.incoming_frame_filters:
+ frame_filter.filter(frame)
+ for message_filter in self._options.incoming_message_filters:
+ frame.payload = message_filter.filter(frame.payload)
+ return frame
+
+ def send_message(self, message, end=True, binary=False):
+ """Send message.
+
+ Args:
+ message: text in unicode or binary in str to send.
+ binary: send message as binary frame.
+
+ Raises:
+ BadOperationException: when called on a server-terminated
+ connection or called with inconsistent message type or
+ binary parameter.
+ """
+
+ if self._request.server_terminated:
+ raise BadOperationException(
+ 'Requested send_message after sending out a closing handshake')
+
+ if binary and isinstance(message, unicode):
+ raise BadOperationException(
+ 'Message for binary frame must be instance of str')
+
+ for message_filter in self._options.outgoing_message_filters:
+ message = message_filter.filter(message, end, binary)
+
+ try:
+ # Set this to any positive integer to limit maximum size of data in
+ # payload data of each frame.
+ MAX_PAYLOAD_DATA_SIZE = -1
+
+ if MAX_PAYLOAD_DATA_SIZE <= 0:
+ self._write(self._writer.build(message, end, binary))
+ return
+
+ bytes_written = 0
+ while True:
+ end_for_this_frame = end
+ bytes_to_write = len(message) - bytes_written
+ if (MAX_PAYLOAD_DATA_SIZE > 0 and
+ bytes_to_write > MAX_PAYLOAD_DATA_SIZE):
+ end_for_this_frame = False
+ bytes_to_write = MAX_PAYLOAD_DATA_SIZE
+
+ frame = self._writer.build(
+ message[bytes_written:bytes_written + bytes_to_write],
+ end_for_this_frame,
+ binary)
+ self._write(frame)
+
+ bytes_written += bytes_to_write
+
+ # This if must be placed here (the end of while block) so that
+ # at least one frame is sent.
+ if len(message) <= bytes_written:
+ break
+ except ValueError, e:
+ raise BadOperationException(e)
+
+ def _get_message_from_frame(self, frame):
+ """Gets a message from frame. If the message is composed of fragmented
+ frames and the frame is not the last fragmented frame, this method
+ returns None. The whole message will be returned when the last
+ fragmented frame is passed to this method.
+
+ Raises:
+ InvalidFrameException: when the frame doesn't match defragmentation
+ context, or the frame contains invalid data.
+ """
+
+ if frame.opcode == common.OPCODE_CONTINUATION:
+ if not self._received_fragments:
+ if frame.fin:
+ raise InvalidFrameException(
+ 'Received a termination frame but fragmentation '
+ 'not started')
+ else:
+ raise InvalidFrameException(
+ 'Received an intermediate frame but '
+ 'fragmentation not started')
+
+ if frame.fin:
+ # End of fragmentation frame
+ self._received_fragments.append(frame.payload)
+ message = ''.join(self._received_fragments)
+ self._received_fragments = []
+ return message
+ else:
+ # Intermediate frame
+ self._received_fragments.append(frame.payload)
+ return None
+ else:
+ if self._received_fragments:
+ if frame.fin:
+ raise InvalidFrameException(
+ 'Received an unfragmented frame without '
+ 'terminating existing fragmentation')
+ else:
+ raise InvalidFrameException(
+ 'New fragmentation started without terminating '
+ 'existing fragmentation')
+
+ if frame.fin:
+ # Unfragmented frame
+
+ self._original_opcode = frame.opcode
+ return frame.payload
+ else:
+ # Start of fragmentation frame
+
+ if common.is_control_opcode(frame.opcode):
+ raise InvalidFrameException(
+ 'Control frames must not be fragmented')
+
+ self._original_opcode = frame.opcode
+ self._received_fragments.append(frame.payload)
+ return None
+
+ def _process_close_message(self, message):
+ """Processes close message.
+
+ Args:
+ message: close message.
+
+ Raises:
+ InvalidFrameException: when the message is invalid.
+ """
+
+ self._request.client_terminated = True
+
+ # Status code is optional. We can have status reason only if we
+ # have status code. Status reason can be empty string. So,
+ # allowed cases are
+ # - no application data: no code no reason
+ # - 2 octet of application data: has code but no reason
+ # - 3 or more octet of application data: both code and reason
+ if len(message) == 0:
+ self._logger.debug('Received close frame (empty body)')
+ self._request.ws_close_code = (
+ common.STATUS_NO_STATUS_RECEIVED)
+ elif len(message) == 1:
+ raise InvalidFrameException(
+ 'If a close frame has status code, the length of '
+ 'status code must be 2 octet')
+ elif len(message) >= 2:
+ self._request.ws_close_code = struct.unpack(
+ '!H', message[0:2])[0]
+ self._request.ws_close_reason = message[2:].decode(
+ 'utf-8', 'replace')
+ self._logger.debug(
+ 'Received close frame (code=%d, reason=%r)',
+ self._request.ws_close_code,
+ self._request.ws_close_reason)
+
+ # As we've received a close frame, no more data is coming over the
+ # socket. We can now safely close the socket without worrying about
+ # RST sending.
+
+ if self._request.server_terminated:
+ self._logger.debug(
+ 'Received ack for server-initiated closing handshake')
+ return
+
+ self._logger.debug(
+ 'Received client-initiated closing handshake')
+
+ code = common.STATUS_NORMAL_CLOSURE
+ reason = ''
+ if hasattr(self._request, '_dispatcher'):
+ dispatcher = self._request._dispatcher
+ code, reason = dispatcher.passive_closing_handshake(
+ self._request)
+ if code is None and reason is not None and len(reason) > 0:
+ self._logger.warning(
+ 'Handler specified reason despite code being None')
+ reason = ''
+ if reason is None:
+ reason = ''
+ self._send_closing_handshake(code, reason)
+ self._logger.debug(
+ 'Acknowledged closing handshake initiated by the peer '
+ '(code=%r, reason=%r)', code, reason)
+
+ def _process_ping_message(self, message):
+ """Processes ping message.
+
+ Args:
+ message: ping message.
+ """
+
+ try:
+ handler = self._request.on_ping_handler
+ if handler:
+ handler(self._request, message)
+ return
+ except AttributeError, e:
+ pass
+ self._send_pong(message)
+
+ def _process_pong_message(self, message):
+ """Processes pong message.
+
+ Args:
+ message: pong message.
+ """
+
+ # TODO(tyoshino): Add ping timeout handling.
+
+ inflight_pings = deque()
+
+ while True:
+ try:
+ expected_body = self._ping_queue.popleft()
+ if expected_body == message:
+ # inflight_pings contains pings ignored by the
+ # other peer. Just forget them.
+ self._logger.debug(
+ 'Ping %r is acked (%d pings were ignored)',
+ expected_body, len(inflight_pings))
+ break
+ else:
+ inflight_pings.append(expected_body)
+ except IndexError, e:
+ # The received pong was unsolicited pong. Keep the
+ # ping queue as is.
+ self._ping_queue = inflight_pings
+ self._logger.debug('Received a unsolicited pong')
+ break
+
+ try:
+ handler = self._request.on_pong_handler
+ if handler:
+ handler(self._request, message)
+ except AttributeError, e:
+ pass
+
+ def receive_message(self):
+ """Receive a WebSocket frame and return its payload as a text in
+ unicode or a binary in str.
+
+ Returns:
+ payload data of the frame
+ - as unicode instance if received text frame
+ - as str instance if received binary frame
+ or None iff received closing handshake.
+ Raises:
+ BadOperationException: when called on a client-terminated
+ connection.
+ ConnectionTerminatedException: when read returns empty
+ string.
+ InvalidFrameException: when the frame contains invalid
+ data.
+ UnsupportedFrameException: when the received frame has
+ flags, opcode we cannot handle. You can ignore this
+ exception and continue receiving the next frame.
+ """
+
+ if self._request.client_terminated:
+ raise BadOperationException(
+ 'Requested receive_message after receiving a closing '
+ 'handshake')
+
+ while True:
+ # mp_conn.read will block if no bytes are available.
+ # Timeout is controlled by TimeOut directive of Apache.
+
+ frame = self._receive_frame_as_frame_object()
+
+ # Check the constraint on the payload size for control frames
+ # before extension processes the frame.
+ # See also http://tools.ietf.org/html/rfc6455#section-5.5
+ if (common.is_control_opcode(frame.opcode) and
+ len(frame.payload) > 125):
+ raise InvalidFrameException(
+ 'Payload data size of control frames must be 125 bytes or '
+ 'less')
+
+ for frame_filter in self._options.incoming_frame_filters:
+ frame_filter.filter(frame)
+
+ if frame.rsv1 or frame.rsv2 or frame.rsv3:
+ raise UnsupportedFrameException(
+ 'Unsupported flag is set (rsv = %d%d%d)' %
+ (frame.rsv1, frame.rsv2, frame.rsv3))
+
+ message = self._get_message_from_frame(frame)
+ if message is None:
+ continue
+
+ for message_filter in self._options.incoming_message_filters:
+ message = message_filter.filter(message)
+
+ if self._original_opcode == common.OPCODE_TEXT:
+ # The WebSocket protocol section 4.4 specifies that invalid
+ # characters must be replaced with U+fffd REPLACEMENT
+ # CHARACTER.
+ try:
+ return message.decode('utf-8')
+ except UnicodeDecodeError, e:
+ raise InvalidUTF8Exception(e)
+ elif self._original_opcode == common.OPCODE_BINARY:
+ return message
+ elif self._original_opcode == common.OPCODE_CLOSE:
+ self._process_close_message(message)
+ return None
+ elif self._original_opcode == common.OPCODE_PING:
+ self._process_ping_message(message)
+ elif self._original_opcode == common.OPCODE_PONG:
+ self._process_pong_message(message)
+ else:
+ raise UnsupportedFrameException(
+ 'Opcode %d is not supported' % self._original_opcode)
+
+ def _send_closing_handshake(self, code, reason):
+ body = create_closing_handshake_body(code, reason)
+ frame = create_close_frame(
+ body, mask=self._options.mask_send,
+ frame_filters=self._options.outgoing_frame_filters)
+
+ self._request.server_terminated = True
+
+ self._write(frame)
+
+ def close_connection(self, code=common.STATUS_NORMAL_CLOSURE, reason='',
+ wait_response=True):
+ """Closes a WebSocket connection.
+
+ Args:
+ code: Status code for close frame. If code is None, a close
+ frame with empty body will be sent.
+ reason: string representing close reason.
+ wait_response: True when caller want to wait the response.
+ Raises:
+ BadOperationException: when reason is specified with code None
+ or reason is not an instance of both str and unicode.
+ """
+
+ if self._request.server_terminated:
+ self._logger.debug(
+ 'Requested close_connection but server is already terminated')
+ return
+
+ if code is None:
+ if reason is not None and len(reason) > 0:
+ raise BadOperationException(
+ 'close reason must not be specified if code is None')
+ reason = ''
+ else:
+ if not isinstance(reason, str) and not isinstance(reason, unicode):
+ raise BadOperationException(
+ 'close reason must be an instance of str or unicode')
+
+ self._send_closing_handshake(code, reason)
+ self._logger.debug(
+ 'Initiated closing handshake (code=%r, reason=%r)',
+ code, reason)
+
+ if (code == common.STATUS_GOING_AWAY or
+ code == common.STATUS_PROTOCOL_ERROR) or not wait_response:
+ # It doesn't make sense to wait for a close frame if the reason is
+ # protocol error or that the server is going away. For some of
+ # other reasons, it might not make sense to wait for a close frame,
+ # but it's not clear, yet.
+ return
+
+ # TODO(ukai): 2. wait until the /client terminated/ flag has been set,
+ # or until a server-defined timeout expires.
+ #
+ # For now, we expect receiving closing handshake right after sending
+ # out closing handshake.
+ message = self.receive_message()
+ if message is not None:
+ raise ConnectionTerminatedException(
+ 'Didn\'t receive valid ack for closing handshake')
+ # TODO: 3. close the WebSocket connection.
+ # note: mod_python Connection (mp_conn) doesn't have close method.
+
+ def send_ping(self, body=''):
+ frame = create_ping_frame(
+ body,
+ self._options.mask_send,
+ self._options.outgoing_frame_filters)
+ self._write(frame)
+
+ self._ping_queue.append(body)
+
+ def _send_pong(self, body):
+ frame = create_pong_frame(
+ body,
+ self._options.mask_send,
+ self._options.outgoing_frame_filters)
+ self._write(frame)
+
+ def get_last_received_opcode(self):
+ """Returns the opcode of the WebSocket message which the last received
+ frame belongs to. The return value is valid iff immediately after
+ receive_message call.
+ """
+
+ return self._original_opcode
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/common.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/common.py
new file mode 100644
index 00000000000..2fc2ead6481
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/common.py
@@ -0,0 +1,303 @@
+# Copyright 2012, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+"""This file must not depend on any module specific to the WebSocket protocol.
+"""
+
+
+from mod_pywebsocket import http_header_util
+
+
+# Additional log level definitions.
+LOGLEVEL_FINE = 9
+
+# Constants indicating WebSocket protocol version.
+VERSION_HIXIE75 = -1
+VERSION_HYBI00 = 0
+VERSION_HYBI01 = 1
+VERSION_HYBI02 = 2
+VERSION_HYBI03 = 2
+VERSION_HYBI04 = 4
+VERSION_HYBI05 = 5
+VERSION_HYBI06 = 6
+VERSION_HYBI07 = 7
+VERSION_HYBI08 = 8
+VERSION_HYBI09 = 8
+VERSION_HYBI10 = 8
+VERSION_HYBI11 = 8
+VERSION_HYBI12 = 8
+VERSION_HYBI13 = 13
+VERSION_HYBI14 = 13
+VERSION_HYBI15 = 13
+VERSION_HYBI16 = 13
+VERSION_HYBI17 = 13
+
+# Constants indicating WebSocket protocol latest version.
+VERSION_HYBI_LATEST = VERSION_HYBI13
+
+# Port numbers
+DEFAULT_WEB_SOCKET_PORT = 80
+DEFAULT_WEB_SOCKET_SECURE_PORT = 443
+
+# Schemes
+WEB_SOCKET_SCHEME = 'ws'
+WEB_SOCKET_SECURE_SCHEME = 'wss'
+
+# Frame opcodes defined in the spec.
+OPCODE_CONTINUATION = 0x0
+OPCODE_TEXT = 0x1
+OPCODE_BINARY = 0x2
+OPCODE_CLOSE = 0x8
+OPCODE_PING = 0x9
+OPCODE_PONG = 0xa
+
+# UUIDs used by HyBi 04 and later opening handshake and frame masking.
+WEBSOCKET_ACCEPT_UUID = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
+
+# Opening handshake header names and expected values.
+UPGRADE_HEADER = 'Upgrade'
+WEBSOCKET_UPGRADE_TYPE = 'websocket'
+WEBSOCKET_UPGRADE_TYPE_HIXIE75 = 'WebSocket'
+CONNECTION_HEADER = 'Connection'
+UPGRADE_CONNECTION_TYPE = 'Upgrade'
+HOST_HEADER = 'Host'
+ORIGIN_HEADER = 'Origin'
+SEC_WEBSOCKET_ORIGIN_HEADER = 'Sec-WebSocket-Origin'
+SEC_WEBSOCKET_KEY_HEADER = 'Sec-WebSocket-Key'
+SEC_WEBSOCKET_ACCEPT_HEADER = 'Sec-WebSocket-Accept'
+SEC_WEBSOCKET_VERSION_HEADER = 'Sec-WebSocket-Version'
+SEC_WEBSOCKET_PROTOCOL_HEADER = 'Sec-WebSocket-Protocol'
+SEC_WEBSOCKET_EXTENSIONS_HEADER = 'Sec-WebSocket-Extensions'
+SEC_WEBSOCKET_DRAFT_HEADER = 'Sec-WebSocket-Draft'
+SEC_WEBSOCKET_KEY1_HEADER = 'Sec-WebSocket-Key1'
+SEC_WEBSOCKET_KEY2_HEADER = 'Sec-WebSocket-Key2'
+SEC_WEBSOCKET_LOCATION_HEADER = 'Sec-WebSocket-Location'
+
+# Extensions
+DEFLATE_FRAME_EXTENSION = 'deflate-frame'
+PERMESSAGE_COMPRESSION_EXTENSION = 'permessage-compress'
+PERMESSAGE_DEFLATE_EXTENSION = 'permessage-deflate'
+X_WEBKIT_DEFLATE_FRAME_EXTENSION = 'x-webkit-deflate-frame'
+X_WEBKIT_PERMESSAGE_COMPRESSION_EXTENSION = 'x-webkit-permessage-compress'
+MUX_EXTENSION = 'mux_DO_NOT_USE'
+
+# Status codes
+# Code STATUS_NO_STATUS_RECEIVED, STATUS_ABNORMAL_CLOSURE, and
+# STATUS_TLS_HANDSHAKE are pseudo codes to indicate specific error cases.
+# Could not be used for codes in actual closing frames.
+# Application level errors must use codes in the range
+# STATUS_USER_REGISTERED_BASE to STATUS_USER_PRIVATE_MAX. The codes in the
+# range STATUS_USER_REGISTERED_BASE to STATUS_USER_REGISTERED_MAX are managed
+# by IANA. Usually application must define user protocol level errors in the
+# range STATUS_USER_PRIVATE_BASE to STATUS_USER_PRIVATE_MAX.
+STATUS_NORMAL_CLOSURE = 1000
+STATUS_GOING_AWAY = 1001
+STATUS_PROTOCOL_ERROR = 1002
+STATUS_UNSUPPORTED_DATA = 1003
+STATUS_NO_STATUS_RECEIVED = 1005
+STATUS_ABNORMAL_CLOSURE = 1006
+STATUS_INVALID_FRAME_PAYLOAD_DATA = 1007
+STATUS_POLICY_VIOLATION = 1008
+STATUS_MESSAGE_TOO_BIG = 1009
+STATUS_MANDATORY_EXTENSION = 1010
+STATUS_INTERNAL_ENDPOINT_ERROR = 1011
+STATUS_TLS_HANDSHAKE = 1015
+STATUS_USER_REGISTERED_BASE = 3000
+STATUS_USER_REGISTERED_MAX = 3999
+STATUS_USER_PRIVATE_BASE = 4000
+STATUS_USER_PRIVATE_MAX = 4999
+# Following definitions are aliases to keep compatibility. Applications must
+# not use these obsoleted definitions anymore.
+STATUS_NORMAL = STATUS_NORMAL_CLOSURE
+STATUS_UNSUPPORTED = STATUS_UNSUPPORTED_DATA
+STATUS_CODE_NOT_AVAILABLE = STATUS_NO_STATUS_RECEIVED
+STATUS_ABNORMAL_CLOSE = STATUS_ABNORMAL_CLOSURE
+STATUS_INVALID_FRAME_PAYLOAD = STATUS_INVALID_FRAME_PAYLOAD_DATA
+STATUS_MANDATORY_EXT = STATUS_MANDATORY_EXTENSION
+
+# HTTP status codes
+HTTP_STATUS_BAD_REQUEST = 400
+HTTP_STATUS_FORBIDDEN = 403
+HTTP_STATUS_NOT_FOUND = 404
+
+
+def is_control_opcode(opcode):
+ return (opcode >> 3) == 1
+
+
+class ExtensionParameter(object):
+ """Holds information about an extension which is exchanged on extension
+ negotiation in opening handshake.
+ """
+
+ def __init__(self, name):
+ self._name = name
+ # TODO(tyoshino): Change the data structure to more efficient one such
+ # as dict when the spec changes to say like
+ # - Parameter names must be unique
+ # - The order of parameters is not significant
+ self._parameters = []
+
+ def name(self):
+ return self._name
+
+ def add_parameter(self, name, value):
+ self._parameters.append((name, value))
+
+ def get_parameters(self):
+ return self._parameters
+
+ def get_parameter_names(self):
+ return [name for name, unused_value in self._parameters]
+
+ def has_parameter(self, name):
+ for param_name, param_value in self._parameters:
+ if param_name == name:
+ return True
+ return False
+
+ def get_parameter_value(self, name):
+ for param_name, param_value in self._parameters:
+ if param_name == name:
+ return param_value
+
+
+class ExtensionParsingException(Exception):
+ def __init__(self, name):
+ super(ExtensionParsingException, self).__init__(name)
+
+
+def _parse_extension_param(state, definition):
+ param_name = http_header_util.consume_token(state)
+
+ if param_name is None:
+ raise ExtensionParsingException('No valid parameter name found')
+
+ http_header_util.consume_lwses(state)
+
+ if not http_header_util.consume_string(state, '='):
+ definition.add_parameter(param_name, None)
+ return
+
+ http_header_util.consume_lwses(state)
+
+ # TODO(tyoshino): Add code to validate that parsed param_value is token
+ param_value = http_header_util.consume_token_or_quoted_string(state)
+ if param_value is None:
+ raise ExtensionParsingException(
+ 'No valid parameter value found on the right-hand side of '
+ 'parameter %r' % param_name)
+
+ definition.add_parameter(param_name, param_value)
+
+
+def _parse_extension(state):
+ extension_token = http_header_util.consume_token(state)
+ if extension_token is None:
+ return None
+
+ extension = ExtensionParameter(extension_token)
+
+ while True:
+ http_header_util.consume_lwses(state)
+
+ if not http_header_util.consume_string(state, ';'):
+ break
+
+ http_header_util.consume_lwses(state)
+
+ try:
+ _parse_extension_param(state, extension)
+ except ExtensionParsingException, e:
+ raise ExtensionParsingException(
+ 'Failed to parse parameter for %r (%r)' %
+ (extension_token, e))
+
+ return extension
+
+
+def parse_extensions(data):
+ """Parses Sec-WebSocket-Extensions header value returns a list of
+ ExtensionParameter objects.
+
+ Leading LWSes must be trimmed.
+ """
+
+ state = http_header_util.ParsingState(data)
+
+ extension_list = []
+ while True:
+ extension = _parse_extension(state)
+ if extension is not None:
+ extension_list.append(extension)
+
+ http_header_util.consume_lwses(state)
+
+ if http_header_util.peek(state) is None:
+ break
+
+ if not http_header_util.consume_string(state, ','):
+ raise ExtensionParsingException(
+ 'Failed to parse Sec-WebSocket-Extensions header: '
+ 'Expected a comma but found %r' %
+ http_header_util.peek(state))
+
+ http_header_util.consume_lwses(state)
+
+ if len(extension_list) == 0:
+ raise ExtensionParsingException(
+ 'No valid extension entry found')
+
+ return extension_list
+
+
+def format_extension(extension):
+ """Formats an ExtensionParameter object."""
+
+ formatted_params = [extension.name()]
+ for param_name, param_value in extension.get_parameters():
+ if param_value is None:
+ formatted_params.append(param_name)
+ else:
+ quoted_value = http_header_util.quote_if_necessary(param_value)
+ formatted_params.append('%s=%s' % (param_name, quoted_value))
+ return '; '.join(formatted_params)
+
+
+def format_extensions(extension_list):
+ """Formats a list of ExtensionParameter objects."""
+
+ formatted_extension_list = []
+ for extension in extension_list:
+ formatted_extension_list.append(format_extension(extension))
+ return ', '.join(formatted_extension_list)
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/dispatch.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/dispatch.py
new file mode 100644
index 00000000000..96c91e0c90e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/dispatch.py
@@ -0,0 +1,393 @@
+# Copyright 2012, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+"""Dispatch WebSocket request.
+"""
+
+
+import logging
+import os
+import re
+
+from mod_pywebsocket import common
+from mod_pywebsocket import handshake
+from mod_pywebsocket import msgutil
+from mod_pywebsocket import mux
+from mod_pywebsocket import stream
+from mod_pywebsocket import util
+
+
+_SOURCE_PATH_PATTERN = re.compile(r'(?i)_wsh\.py$')
+_SOURCE_SUFFIX = '_wsh.py'
+_DO_EXTRA_HANDSHAKE_HANDLER_NAME = 'web_socket_do_extra_handshake'
+_TRANSFER_DATA_HANDLER_NAME = 'web_socket_transfer_data'
+_PASSIVE_CLOSING_HANDSHAKE_HANDLER_NAME = (
+ 'web_socket_passive_closing_handshake')
+
+
+class DispatchException(Exception):
+ """Exception in dispatching WebSocket request."""
+
+ def __init__(self, name, status=common.HTTP_STATUS_NOT_FOUND):
+ super(DispatchException, self).__init__(name)
+ self.status = status
+
+
+def _default_passive_closing_handshake_handler(request):
+ """Default web_socket_passive_closing_handshake handler."""
+
+ return common.STATUS_NORMAL_CLOSURE, ''
+
+
+def _normalize_path(path):
+ """Normalize path.
+
+ Args:
+ path: the path to normalize.
+
+ Path is converted to the absolute path.
+ The input path can use either '\\' or '/' as the separator.
+ The normalized path always uses '/' regardless of the platform.
+ """
+
+ path = path.replace('\\', os.path.sep)
+ path = os.path.realpath(path)
+ path = path.replace('\\', '/')
+ return path
+
+
+def _create_path_to_resource_converter(base_dir):
+ """Returns a function that converts the path of a WebSocket handler source
+ file to a resource string by removing the path to the base directory from
+ its head, removing _SOURCE_SUFFIX from its tail, and replacing path
+ separators in it with '/'.
+
+ Args:
+ base_dir: the path to the base directory.
+ """
+
+ base_dir = _normalize_path(base_dir)
+
+ base_len = len(base_dir)
+ suffix_len = len(_SOURCE_SUFFIX)
+
+ def converter(path):
+ if not path.endswith(_SOURCE_SUFFIX):
+ return None
+ # _normalize_path must not be used because resolving symlink breaks
+ # following path check.
+ path = path.replace('\\', '/')
+ if not path.startswith(base_dir):
+ return None
+ return path[base_len:-suffix_len]
+
+ return converter
+
+
+def _enumerate_handler_file_paths(directory):
+ """Returns a generator that enumerates WebSocket Handler source file names
+ in the given directory.
+ """
+
+ for root, unused_dirs, files in os.walk(directory):
+ for base in files:
+ path = os.path.join(root, base)
+ if _SOURCE_PATH_PATTERN.search(path):
+ yield path
+
+
+class _HandlerSuite(object):
+ """A handler suite holder class."""
+
+ def __init__(self, do_extra_handshake, transfer_data,
+ passive_closing_handshake):
+ self.do_extra_handshake = do_extra_handshake
+ self.transfer_data = transfer_data
+ self.passive_closing_handshake = passive_closing_handshake
+
+
+def _source_handler_file(handler_definition):
+ """Source a handler definition string.
+
+ Args:
+ handler_definition: a string containing Python statements that define
+ handler functions.
+ """
+
+ global_dic = {}
+ try:
+ exec handler_definition in global_dic
+ except Exception:
+ raise DispatchException('Error in sourcing handler:' +
+ util.get_stack_trace())
+ passive_closing_handshake_handler = None
+ try:
+ passive_closing_handshake_handler = _extract_handler(
+ global_dic, _PASSIVE_CLOSING_HANDSHAKE_HANDLER_NAME)
+ except Exception:
+ passive_closing_handshake_handler = (
+ _default_passive_closing_handshake_handler)
+ return _HandlerSuite(
+ _extract_handler(global_dic, _DO_EXTRA_HANDSHAKE_HANDLER_NAME),
+ _extract_handler(global_dic, _TRANSFER_DATA_HANDLER_NAME),
+ passive_closing_handshake_handler)
+
+
+def _extract_handler(dic, name):
+ """Extracts a callable with the specified name from the given dictionary
+ dic.
+ """
+
+ if name not in dic:
+ raise DispatchException('%s is not defined.' % name)
+ handler = dic[name]
+ if not callable(handler):
+ raise DispatchException('%s is not callable.' % name)
+ return handler
+
+
+class Dispatcher(object):
+ """Dispatches WebSocket requests.
+
+ This class maintains a map from resource name to handlers.
+ """
+
+ def __init__(
+ self, root_dir, scan_dir=None,
+ allow_handlers_outside_root_dir=True):
+ """Construct an instance.
+
+ Args:
+ root_dir: The directory where handler definition files are
+ placed.
+ scan_dir: The directory where handler definition files are
+ searched. scan_dir must be a directory under root_dir,
+ including root_dir itself. If scan_dir is None,
+ root_dir is used as scan_dir. scan_dir can be useful
+ in saving scan time when root_dir contains many
+ subdirectories.
+ allow_handlers_outside_root_dir: Scans handler files even if their
+ canonical path is not under root_dir.
+ """
+
+ self._logger = util.get_class_logger(self)
+
+ self._handler_suite_map = {}
+ self._source_warnings = []
+ if scan_dir is None:
+ scan_dir = root_dir
+ if not os.path.realpath(scan_dir).startswith(
+ os.path.realpath(root_dir)):
+ raise DispatchException('scan_dir:%s must be a directory under '
+ 'root_dir:%s.' % (scan_dir, root_dir))
+ self._source_handler_files_in_dir(
+ root_dir, scan_dir, allow_handlers_outside_root_dir)
+
+ def add_resource_path_alias(self,
+ alias_resource_path, existing_resource_path):
+ """Add resource path alias.
+
+ Once added, request to alias_resource_path would be handled by
+ handler registered for existing_resource_path.
+
+ Args:
+ alias_resource_path: alias resource path
+ existing_resource_path: existing resource path
+ """
+ try:
+ handler_suite = self._handler_suite_map[existing_resource_path]
+ self._handler_suite_map[alias_resource_path] = handler_suite
+ except KeyError:
+ raise DispatchException('No handler for: %r' %
+ existing_resource_path)
+
+ def source_warnings(self):
+ """Return warnings in sourcing handlers."""
+
+ return self._source_warnings
+
+ def do_extra_handshake(self, request):
+ """Do extra checking in WebSocket handshake.
+
+ Select a handler based on request.uri and call its
+ web_socket_do_extra_handshake function.
+
+ Args:
+ request: mod_python request.
+
+ Raises:
+ DispatchException: when handler was not found
+ AbortedByUserException: when user handler abort connection
+ HandshakeException: when opening handshake failed
+ """
+
+ handler_suite = self.get_handler_suite(request.ws_resource)
+ if handler_suite is None:
+ raise DispatchException('No handler for: %r' % request.ws_resource)
+ do_extra_handshake_ = handler_suite.do_extra_handshake
+ try:
+ do_extra_handshake_(request)
+ except handshake.AbortedByUserException, e:
+ # Re-raise to tell the caller of this function to finish this
+ # connection without sending any error.
+ self._logger.debug('%s', util.get_stack_trace())
+ raise
+ except Exception, e:
+ util.prepend_message_to_exception(
+ '%s raised exception for %s: ' % (
+ _DO_EXTRA_HANDSHAKE_HANDLER_NAME,
+ request.ws_resource),
+ e)
+ raise handshake.HandshakeException(e, common.HTTP_STATUS_FORBIDDEN)
+
+ def transfer_data(self, request):
+ """Let a handler transfer_data with a WebSocket client.
+
+ Select a handler based on request.ws_resource and call its
+ web_socket_transfer_data function.
+
+ Args:
+ request: mod_python request.
+
+ Raises:
+ DispatchException: when handler was not found
+ AbortedByUserException: when user handler abort connection
+ """
+
+ # TODO(tyoshino): Terminate underlying TCP connection if possible.
+ try:
+ if mux.use_mux(request):
+ mux.start(request, self)
+ else:
+ handler_suite = self.get_handler_suite(request.ws_resource)
+ if handler_suite is None:
+ raise DispatchException('No handler for: %r' %
+ request.ws_resource)
+ transfer_data_ = handler_suite.transfer_data
+ transfer_data_(request)
+
+ if not request.server_terminated:
+ request.ws_stream.close_connection()
+ # Catch non-critical exceptions the handler didn't handle.
+ except handshake.AbortedByUserException, e:
+ self._logger.debug('%s', util.get_stack_trace())
+ raise
+ except msgutil.BadOperationException, e:
+ self._logger.debug('%s', e)
+ request.ws_stream.close_connection(
+ common.STATUS_INTERNAL_ENDPOINT_ERROR)
+ except msgutil.InvalidFrameException, e:
+ # InvalidFrameException must be caught before
+ # ConnectionTerminatedException that catches InvalidFrameException.
+ self._logger.debug('%s', e)
+ request.ws_stream.close_connection(common.STATUS_PROTOCOL_ERROR)
+ except msgutil.UnsupportedFrameException, e:
+ self._logger.debug('%s', e)
+ request.ws_stream.close_connection(common.STATUS_UNSUPPORTED_DATA)
+ except stream.InvalidUTF8Exception, e:
+ self._logger.debug('%s', e)
+ request.ws_stream.close_connection(
+ common.STATUS_INVALID_FRAME_PAYLOAD_DATA)
+ except msgutil.ConnectionTerminatedException, e:
+ self._logger.debug('%s', e)
+ except Exception, e:
+ # Any other exceptions are forwarded to the caller of this
+ # function.
+ util.prepend_message_to_exception(
+ '%s raised exception for %s: ' % (
+ _TRANSFER_DATA_HANDLER_NAME, request.ws_resource),
+ e)
+ raise
+
+ def passive_closing_handshake(self, request):
+ """Prepare code and reason for responding client initiated closing
+ handshake.
+ """
+
+ handler_suite = self.get_handler_suite(request.ws_resource)
+ if handler_suite is None:
+ return _default_passive_closing_handshake_handler(request)
+ return handler_suite.passive_closing_handshake(request)
+
+ def get_handler_suite(self, resource):
+ """Retrieves two handlers (one for extra handshake processing, and one
+ for data transfer) for the given request as a HandlerSuite object.
+ """
+
+ fragment = None
+ if '#' in resource:
+ resource, fragment = resource.split('#', 1)
+ if '?' in resource:
+ resource = resource.split('?', 1)[0]
+ handler_suite = self._handler_suite_map.get(resource)
+ if handler_suite and fragment:
+ raise DispatchException('Fragment identifiers MUST NOT be used on '
+ 'WebSocket URIs',
+ common.HTTP_STATUS_BAD_REQUEST)
+ return handler_suite
+
+ def _source_handler_files_in_dir(
+ self, root_dir, scan_dir, allow_handlers_outside_root_dir):
+ """Source all the handler source files in the scan_dir directory.
+
+ The resource path is determined relative to root_dir.
+ """
+
+ # We build a map from resource to handler code assuming that there's
+ # only one path from root_dir to scan_dir and it can be obtained by
+ # comparing realpath of them.
+
+ # Here we cannot use abspath. See
+ # https://bugs.webkit.org/show_bug.cgi?id=31603
+
+ convert = _create_path_to_resource_converter(root_dir)
+ scan_realpath = os.path.realpath(scan_dir)
+ root_realpath = os.path.realpath(root_dir)
+ for path in _enumerate_handler_file_paths(scan_realpath):
+ if (not allow_handlers_outside_root_dir and
+ (not os.path.realpath(path).startswith(root_realpath))):
+ self._logger.debug(
+ 'Canonical path of %s is not under root directory' %
+ path)
+ continue
+ try:
+ handler_suite = _source_handler_file(open(path).read())
+ except DispatchException, e:
+ self._source_warnings.append('%s: %s' % (path, e))
+ continue
+ resource = convert(path)
+ if resource is None:
+ self._logger.debug(
+ 'Path to resource conversion on %s failed' % path)
+ else:
+ self._handler_suite_map[convert(path)] = handler_suite
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/extensions.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/extensions.py
new file mode 100644
index 00000000000..49a9fdcf947
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/extensions.py
@@ -0,0 +1,885 @@
+# Copyright 2012, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+from mod_pywebsocket import common
+from mod_pywebsocket import util
+from mod_pywebsocket.http_header_util import quote_if_necessary
+
+
+# The list of available server side extension processor classes.
+_available_processors = {}
+_compression_extension_names = []
+
+
+class ExtensionProcessorInterface(object):
+
+ def __init__(self, request):
+ self._logger = util.get_class_logger(self)
+
+ self._request = request
+ self._active = True
+
+ def request(self):
+ return self._request
+
+ def name(self):
+ return None
+
+ def check_consistency_with_other_processors(self, processors):
+ pass
+
+ def set_active(self, active):
+ self._active = active
+
+ def is_active(self):
+ return self._active
+
+ def _get_extension_response_internal(self):
+ return None
+
+ def get_extension_response(self):
+ if not self._active:
+ self._logger.debug('Extension %s is deactivated', self.name())
+ return None
+
+ response = self._get_extension_response_internal()
+ if response is None:
+ self._active = False
+ return response
+
+ def _setup_stream_options_internal(self, stream_options):
+ pass
+
+ def setup_stream_options(self, stream_options):
+ if self._active:
+ self._setup_stream_options_internal(stream_options)
+
+
+def _log_outgoing_compression_ratio(
+ logger, original_bytes, filtered_bytes, average_ratio):
+ # Print inf when ratio is not available.
+ ratio = float('inf')
+ if original_bytes != 0:
+ ratio = float(filtered_bytes) / original_bytes
+
+ logger.debug('Outgoing compression ratio: %f (average: %f)' %
+ (ratio, average_ratio))
+
+
+def _log_incoming_compression_ratio(
+ logger, received_bytes, filtered_bytes, average_ratio):
+ # Print inf when ratio is not available.
+ ratio = float('inf')
+ if filtered_bytes != 0:
+ ratio = float(received_bytes) / filtered_bytes
+
+ logger.debug('Incoming compression ratio: %f (average: %f)' %
+ (ratio, average_ratio))
+
+
+def _parse_window_bits(bits):
+ """Return parsed integer value iff the given string conforms to the
+ grammar of the window bits extension parameters.
+ """
+
+ if bits is None:
+ raise ValueError('Value is required')
+
+ # For non integer values such as "10.0", ValueError will be raised.
+ int_bits = int(bits)
+
+ # First condition is to drop leading zero case e.g. "08".
+ if bits != str(int_bits) or int_bits < 8 or int_bits > 15:
+ raise ValueError('Invalid value: %r' % bits)
+
+ return int_bits
+
+
+class _AverageRatioCalculator(object):
+ """Stores total bytes of original and result data, and calculates average
+ result / original ratio.
+ """
+
+ def __init__(self):
+ self._total_original_bytes = 0
+ self._total_result_bytes = 0
+
+ def add_original_bytes(self, value):
+ self._total_original_bytes += value
+
+ def add_result_bytes(self, value):
+ self._total_result_bytes += value
+
+ def get_average_ratio(self):
+ if self._total_original_bytes != 0:
+ return (float(self._total_result_bytes) /
+ self._total_original_bytes)
+ else:
+ return float('inf')
+
+
+class DeflateFrameExtensionProcessor(ExtensionProcessorInterface):
+ """deflate-frame extension processor.
+
+ Specification:
+ http://tools.ietf.org/html/draft-tyoshino-hybi-websocket-perframe-deflate
+ """
+
+ _WINDOW_BITS_PARAM = 'max_window_bits'
+ _NO_CONTEXT_TAKEOVER_PARAM = 'no_context_takeover'
+
+ def __init__(self, request):
+ ExtensionProcessorInterface.__init__(self, request)
+ self._logger = util.get_class_logger(self)
+
+ self._response_window_bits = None
+ self._response_no_context_takeover = False
+ self._bfinal = False
+
+ # Calculates
+ # (Total outgoing bytes supplied to this filter) /
+ # (Total bytes sent to the network after applying this filter)
+ self._outgoing_average_ratio_calculator = _AverageRatioCalculator()
+
+ # Calculates
+ # (Total bytes received from the network) /
+ # (Total incoming bytes obtained after applying this filter)
+ self._incoming_average_ratio_calculator = _AverageRatioCalculator()
+
+ def name(self):
+ return common.DEFLATE_FRAME_EXTENSION
+
+ def _get_extension_response_internal(self):
+ # Any unknown parameter will be just ignored.
+
+ window_bits = None
+ if self._request.has_parameter(self._WINDOW_BITS_PARAM):
+ window_bits = self._request.get_parameter_value(
+ self._WINDOW_BITS_PARAM)
+ try:
+ window_bits = _parse_window_bits(window_bits)
+ except ValueError, e:
+ return None
+
+ no_context_takeover = self._request.has_parameter(
+ self._NO_CONTEXT_TAKEOVER_PARAM)
+ if (no_context_takeover and
+ self._request.get_parameter_value(
+ self._NO_CONTEXT_TAKEOVER_PARAM) is not None):
+ return None
+
+ self._rfc1979_deflater = util._RFC1979Deflater(
+ window_bits, no_context_takeover)
+
+ self._rfc1979_inflater = util._RFC1979Inflater()
+
+ self._compress_outgoing = True
+
+ response = common.ExtensionParameter(self._request.name())
+
+ if self._response_window_bits is not None:
+ response.add_parameter(
+ self._WINDOW_BITS_PARAM, str(self._response_window_bits))
+ if self._response_no_context_takeover:
+ response.add_parameter(
+ self._NO_CONTEXT_TAKEOVER_PARAM, None)
+
+ self._logger.debug(
+ 'Enable %s extension ('
+ 'request: window_bits=%s; no_context_takeover=%r, '
+ 'response: window_wbits=%s; no_context_takeover=%r)' %
+ (self._request.name(),
+ window_bits,
+ no_context_takeover,
+ self._response_window_bits,
+ self._response_no_context_takeover))
+
+ return response
+
+ def _setup_stream_options_internal(self, stream_options):
+
+ class _OutgoingFilter(object):
+
+ def __init__(self, parent):
+ self._parent = parent
+
+ def filter(self, frame):
+ self._parent._outgoing_filter(frame)
+
+ class _IncomingFilter(object):
+
+ def __init__(self, parent):
+ self._parent = parent
+
+ def filter(self, frame):
+ self._parent._incoming_filter(frame)
+
+ stream_options.outgoing_frame_filters.append(
+ _OutgoingFilter(self))
+ stream_options.incoming_frame_filters.insert(
+ 0, _IncomingFilter(self))
+
+ def set_response_window_bits(self, value):
+ self._response_window_bits = value
+
+ def set_response_no_context_takeover(self, value):
+ self._response_no_context_takeover = value
+
+ def set_bfinal(self, value):
+ self._bfinal = value
+
+ def enable_outgoing_compression(self):
+ self._compress_outgoing = True
+
+ def disable_outgoing_compression(self):
+ self._compress_outgoing = False
+
+ def _outgoing_filter(self, frame):
+ """Transform outgoing frames. This method is called only by
+ an _OutgoingFilter instance.
+ """
+
+ original_payload_size = len(frame.payload)
+ self._outgoing_average_ratio_calculator.add_original_bytes(
+ original_payload_size)
+
+ if (not self._compress_outgoing or
+ common.is_control_opcode(frame.opcode)):
+ self._outgoing_average_ratio_calculator.add_result_bytes(
+ original_payload_size)
+ return
+
+ frame.payload = self._rfc1979_deflater.filter(
+ frame.payload, bfinal=self._bfinal)
+ frame.rsv1 = 1
+
+ filtered_payload_size = len(frame.payload)
+ self._outgoing_average_ratio_calculator.add_result_bytes(
+ filtered_payload_size)
+
+ _log_outgoing_compression_ratio(
+ self._logger,
+ original_payload_size,
+ filtered_payload_size,
+ self._outgoing_average_ratio_calculator.get_average_ratio())
+
+ def _incoming_filter(self, frame):
+ """Transform incoming frames. This method is called only by
+ an _IncomingFilter instance.
+ """
+
+ received_payload_size = len(frame.payload)
+ self._incoming_average_ratio_calculator.add_result_bytes(
+ received_payload_size)
+
+ if frame.rsv1 != 1 or common.is_control_opcode(frame.opcode):
+ self._incoming_average_ratio_calculator.add_original_bytes(
+ received_payload_size)
+ return
+
+ frame.payload = self._rfc1979_inflater.filter(frame.payload)
+ frame.rsv1 = 0
+
+ filtered_payload_size = len(frame.payload)
+ self._incoming_average_ratio_calculator.add_original_bytes(
+ filtered_payload_size)
+
+ _log_incoming_compression_ratio(
+ self._logger,
+ received_payload_size,
+ filtered_payload_size,
+ self._incoming_average_ratio_calculator.get_average_ratio())
+
+
+_available_processors[common.DEFLATE_FRAME_EXTENSION] = (
+ DeflateFrameExtensionProcessor)
+_compression_extension_names.append(common.DEFLATE_FRAME_EXTENSION)
+
+_available_processors[common.X_WEBKIT_DEFLATE_FRAME_EXTENSION] = (
+ DeflateFrameExtensionProcessor)
+_compression_extension_names.append(common.X_WEBKIT_DEFLATE_FRAME_EXTENSION)
+
+
+def _parse_compression_method(data):
+ """Parses the value of "method" extension parameter."""
+
+ return common.parse_extensions(data)
+
+
+def _create_accepted_method_desc(method_name, method_params):
+ """Creates accepted-method-desc from given method name and parameters"""
+
+ extension = common.ExtensionParameter(method_name)
+ for name, value in method_params:
+ extension.add_parameter(name, value)
+ return common.format_extension(extension)
+
+
+class CompressionExtensionProcessorBase(ExtensionProcessorInterface):
+ """Base class for perframe-compress and permessage-compress extension."""
+
+ _METHOD_PARAM = 'method'
+
+ def __init__(self, request):
+ ExtensionProcessorInterface.__init__(self, request)
+ self._logger = util.get_class_logger(self)
+ self._compression_method_name = None
+ self._compression_processor = None
+ self._compression_processor_hook = None
+
+ def name(self):
+ return ''
+
+ def _lookup_compression_processor(self, method_desc):
+ return None
+
+ def _get_compression_processor_response(self):
+ """Looks up the compression processor based on the self._request and
+ returns the compression processor's response.
+ """
+
+ method_list = self._request.get_parameter_value(self._METHOD_PARAM)
+ if method_list is None:
+ return None
+ methods = _parse_compression_method(method_list)
+ if methods is None:
+ return None
+ comression_processor = None
+ # The current implementation tries only the first method that matches
+ # supported algorithm. Following methods aren't tried even if the
+ # first one is rejected.
+ # TODO(bashi): Need to clarify this behavior.
+ for method_desc in methods:
+ compression_processor = self._lookup_compression_processor(
+ method_desc)
+ if compression_processor is not None:
+ self._compression_method_name = method_desc.name()
+ break
+ if compression_processor is None:
+ return None
+
+ if self._compression_processor_hook:
+ self._compression_processor_hook(compression_processor)
+
+ processor_response = compression_processor.get_extension_response()
+ if processor_response is None:
+ return None
+ self._compression_processor = compression_processor
+ return processor_response
+
+ def _get_extension_response_internal(self):
+ processor_response = self._get_compression_processor_response()
+ if processor_response is None:
+ return None
+
+ response = common.ExtensionParameter(self._request.name())
+ accepted_method_desc = _create_accepted_method_desc(
+ self._compression_method_name,
+ processor_response.get_parameters())
+ response.add_parameter(self._METHOD_PARAM, accepted_method_desc)
+ self._logger.debug(
+ 'Enable %s extension (method: %s)' %
+ (self._request.name(), self._compression_method_name))
+ return response
+
+ def _setup_stream_options_internal(self, stream_options):
+ if self._compression_processor is None:
+ return
+ self._compression_processor.setup_stream_options(stream_options)
+
+ def set_compression_processor_hook(self, hook):
+ self._compression_processor_hook = hook
+
+ def get_compression_processor(self):
+ return self._compression_processor
+
+
+class PerMessageDeflateExtensionProcessor(ExtensionProcessorInterface):
+ """permessage-deflate extension processor. It's also used for
+ permessage-compress extension when the deflate method is chosen.
+
+ Specification:
+ http://tools.ietf.org/html/draft-ietf-hybi-permessage-compression-08
+ """
+
+ _SERVER_MAX_WINDOW_BITS_PARAM = 'server_max_window_bits'
+ _SERVER_NO_CONTEXT_TAKEOVER_PARAM = 'server_no_context_takeover'
+ _CLIENT_MAX_WINDOW_BITS_PARAM = 'client_max_window_bits'
+ _CLIENT_NO_CONTEXT_TAKEOVER_PARAM = 'client_no_context_takeover'
+
+ def __init__(self, request, draft08=True):
+ """Construct PerMessageDeflateExtensionProcessor
+
+ Args:
+ draft08: Follow the constraints on the parameters that were not
+ specified for permessage-compress but are specified for
+ permessage-deflate as on
+ draft-ietf-hybi-permessage-compression-08.
+ """
+
+ ExtensionProcessorInterface.__init__(self, request)
+ self._logger = util.get_class_logger(self)
+
+ self._preferred_client_max_window_bits = None
+ self._client_no_context_takeover = False
+
+ self._draft08 = draft08
+
+ def name(self):
+ return 'deflate'
+
+ def _get_extension_response_internal(self):
+ if self._draft08:
+ for name in self._request.get_parameter_names():
+ if name not in [self._SERVER_MAX_WINDOW_BITS_PARAM,
+ self._SERVER_NO_CONTEXT_TAKEOVER_PARAM,
+ self._CLIENT_MAX_WINDOW_BITS_PARAM]:
+ self._logger.debug('Unknown parameter: %r', name)
+ return None
+ else:
+ # Any unknown parameter will be just ignored.
+ pass
+
+ server_max_window_bits = None
+ if self._request.has_parameter(self._SERVER_MAX_WINDOW_BITS_PARAM):
+ server_max_window_bits = self._request.get_parameter_value(
+ self._SERVER_MAX_WINDOW_BITS_PARAM)
+ try:
+ server_max_window_bits = _parse_window_bits(
+ server_max_window_bits)
+ except ValueError, e:
+ self._logger.debug('Bad %s parameter: %r',
+ self._SERVER_MAX_WINDOW_BITS_PARAM,
+ e)
+ return None
+
+ server_no_context_takeover = self._request.has_parameter(
+ self._SERVER_NO_CONTEXT_TAKEOVER_PARAM)
+ if (server_no_context_takeover and
+ self._request.get_parameter_value(
+ self._SERVER_NO_CONTEXT_TAKEOVER_PARAM) is not None):
+ self._logger.debug('%s parameter must not have a value: %r',
+ self._SERVER_NO_CONTEXT_TAKEOVER_PARAM,
+ server_no_context_takeover)
+ return None
+
+ # client_max_window_bits from a client indicates whether the client can
+ # accept client_max_window_bits from a server or not.
+ client_client_max_window_bits = self._request.has_parameter(
+ self._CLIENT_MAX_WINDOW_BITS_PARAM)
+ if (self._draft08 and
+ client_client_max_window_bits and
+ self._request.get_parameter_value(
+ self._CLIENT_MAX_WINDOW_BITS_PARAM) is not None):
+ self._logger.debug('%s parameter must not have a value in a '
+ 'client\'s opening handshake: %r',
+ self._CLIENT_MAX_WINDOW_BITS_PARAM,
+ client_client_max_window_bits)
+ return None
+
+ self._rfc1979_deflater = util._RFC1979Deflater(
+ server_max_window_bits, server_no_context_takeover)
+
+ # Note that we prepare for incoming messages compressed with window
+ # bits upto 15 regardless of the client_max_window_bits value to be
+ # sent to the client.
+ self._rfc1979_inflater = util._RFC1979Inflater()
+
+ self._framer = _PerMessageDeflateFramer(
+ server_max_window_bits, server_no_context_takeover)
+ self._framer.set_bfinal(False)
+ self._framer.set_compress_outgoing_enabled(True)
+
+ response = common.ExtensionParameter(self._request.name())
+
+ if server_max_window_bits is not None:
+ response.add_parameter(
+ self._SERVER_MAX_WINDOW_BITS_PARAM,
+ str(server_max_window_bits))
+
+ if server_no_context_takeover:
+ response.add_parameter(
+ self._SERVER_NO_CONTEXT_TAKEOVER_PARAM, None)
+
+ if self._preferred_client_max_window_bits is not None:
+ if self._draft08 and not client_client_max_window_bits:
+ self._logger.debug('Processor is configured to use %s but '
+ 'the client cannot accept it',
+ self._CLIENT_MAX_WINDOW_BITS_PARAM)
+ return None
+ response.add_parameter(
+ self._CLIENT_MAX_WINDOW_BITS_PARAM,
+ str(self._preferred_client_max_window_bits))
+
+ if self._client_no_context_takeover:
+ response.add_parameter(
+ self._CLIENT_NO_CONTEXT_TAKEOVER_PARAM, None)
+
+ self._logger.debug(
+ 'Enable %s extension ('
+ 'request: server_max_window_bits=%s; '
+ 'server_no_context_takeover=%r, '
+ 'response: client_max_window_bits=%s; '
+ 'client_no_context_takeover=%r)' %
+ (self._request.name(),
+ server_max_window_bits,
+ server_no_context_takeover,
+ self._preferred_client_max_window_bits,
+ self._client_no_context_takeover))
+
+ return response
+
+ def _setup_stream_options_internal(self, stream_options):
+ self._framer.setup_stream_options(stream_options)
+
+ def set_client_max_window_bits(self, value):
+ """If this option is specified, this class adds the
+ client_max_window_bits extension parameter to the handshake response,
+ but doesn't reduce the LZ77 sliding window size of its inflater.
+ I.e., you can use this for testing client implementation but cannot
+ reduce memory usage of this class.
+
+ If this method has been called with True and an offer without the
+ client_max_window_bits extension parameter is received,
+ - (When processing the permessage-deflate extension) this processor
+ declines the request.
+ - (When processing the permessage-compress extension) this processor
+ accepts the request.
+ """
+
+ self._preferred_client_max_window_bits = value
+
+ def set_client_no_context_takeover(self, value):
+ """If this option is specified, this class adds the
+ client_no_context_takeover extension parameter to the handshake
+ response, but doesn't reset inflater for each message. I.e., you can
+ use this for testing client implementation but cannot reduce memory
+ usage of this class.
+ """
+
+ self._client_no_context_takeover = value
+
+ def set_bfinal(self, value):
+ self._framer.set_bfinal(value)
+
+ def enable_outgoing_compression(self):
+ self._framer.set_compress_outgoing_enabled(True)
+
+ def disable_outgoing_compression(self):
+ self._framer.set_compress_outgoing_enabled(False)
+
+
+class _PerMessageDeflateFramer(object):
+ """A framer for extensions with per-message DEFLATE feature."""
+
+ def __init__(self, deflate_max_window_bits, deflate_no_context_takeover):
+ self._logger = util.get_class_logger(self)
+
+ self._rfc1979_deflater = util._RFC1979Deflater(
+ deflate_max_window_bits, deflate_no_context_takeover)
+
+ self._rfc1979_inflater = util._RFC1979Inflater()
+
+ self._bfinal = False
+
+ self._compress_outgoing_enabled = False
+
+ # True if a message is fragmented and compression is ongoing.
+ self._compress_ongoing = False
+
+ # Calculates
+ # (Total outgoing bytes supplied to this filter) /
+ # (Total bytes sent to the network after applying this filter)
+ self._outgoing_average_ratio_calculator = _AverageRatioCalculator()
+
+ # Calculates
+ # (Total bytes received from the network) /
+ # (Total incoming bytes obtained after applying this filter)
+ self._incoming_average_ratio_calculator = _AverageRatioCalculator()
+
+ def set_bfinal(self, value):
+ self._bfinal = value
+
+ def set_compress_outgoing_enabled(self, value):
+ self._compress_outgoing_enabled = value
+
+ def _process_incoming_message(self, message, decompress):
+ if not decompress:
+ return message
+
+ received_payload_size = len(message)
+ self._incoming_average_ratio_calculator.add_result_bytes(
+ received_payload_size)
+
+ message = self._rfc1979_inflater.filter(message)
+
+ filtered_payload_size = len(message)
+ self._incoming_average_ratio_calculator.add_original_bytes(
+ filtered_payload_size)
+
+ _log_incoming_compression_ratio(
+ self._logger,
+ received_payload_size,
+ filtered_payload_size,
+ self._incoming_average_ratio_calculator.get_average_ratio())
+
+ return message
+
+ def _process_outgoing_message(self, message, end, binary):
+ if not binary:
+ message = message.encode('utf-8')
+
+ if not self._compress_outgoing_enabled:
+ return message
+
+ original_payload_size = len(message)
+ self._outgoing_average_ratio_calculator.add_original_bytes(
+ original_payload_size)
+
+ message = self._rfc1979_deflater.filter(
+ message, end=end, bfinal=self._bfinal)
+
+ filtered_payload_size = len(message)
+ self._outgoing_average_ratio_calculator.add_result_bytes(
+ filtered_payload_size)
+
+ _log_outgoing_compression_ratio(
+ self._logger,
+ original_payload_size,
+ filtered_payload_size,
+ self._outgoing_average_ratio_calculator.get_average_ratio())
+
+ if not self._compress_ongoing:
+ self._outgoing_frame_filter.set_compression_bit()
+ self._compress_ongoing = not end
+ return message
+
+ def _process_incoming_frame(self, frame):
+ if frame.rsv1 == 1 and not common.is_control_opcode(frame.opcode):
+ self._incoming_message_filter.decompress_next_message()
+ frame.rsv1 = 0
+
+ def _process_outgoing_frame(self, frame, compression_bit):
+ if (not compression_bit or
+ common.is_control_opcode(frame.opcode)):
+ return
+
+ frame.rsv1 = 1
+
+ def setup_stream_options(self, stream_options):
+ """Creates filters and sets them to the StreamOptions."""
+
+ class _OutgoingMessageFilter(object):
+
+ def __init__(self, parent):
+ self._parent = parent
+
+ def filter(self, message, end=True, binary=False):
+ return self._parent._process_outgoing_message(
+ message, end, binary)
+
+ class _IncomingMessageFilter(object):
+
+ def __init__(self, parent):
+ self._parent = parent
+ self._decompress_next_message = False
+
+ def decompress_next_message(self):
+ self._decompress_next_message = True
+
+ def filter(self, message):
+ message = self._parent._process_incoming_message(
+ message, self._decompress_next_message)
+ self._decompress_next_message = False
+ return message
+
+ self._outgoing_message_filter = _OutgoingMessageFilter(self)
+ self._incoming_message_filter = _IncomingMessageFilter(self)
+ stream_options.outgoing_message_filters.append(
+ self._outgoing_message_filter)
+ stream_options.incoming_message_filters.append(
+ self._incoming_message_filter)
+
+ class _OutgoingFrameFilter(object):
+
+ def __init__(self, parent):
+ self._parent = parent
+ self._set_compression_bit = False
+
+ def set_compression_bit(self):
+ self._set_compression_bit = True
+
+ def filter(self, frame):
+ self._parent._process_outgoing_frame(
+ frame, self._set_compression_bit)
+ self._set_compression_bit = False
+
+ class _IncomingFrameFilter(object):
+
+ def __init__(self, parent):
+ self._parent = parent
+
+ def filter(self, frame):
+ self._parent._process_incoming_frame(frame)
+
+ self._outgoing_frame_filter = _OutgoingFrameFilter(self)
+ self._incoming_frame_filter = _IncomingFrameFilter(self)
+ stream_options.outgoing_frame_filters.append(
+ self._outgoing_frame_filter)
+ stream_options.incoming_frame_filters.append(
+ self._incoming_frame_filter)
+
+ stream_options.encode_text_message_to_utf8 = False
+
+
+_available_processors[common.PERMESSAGE_DEFLATE_EXTENSION] = (
+ PerMessageDeflateExtensionProcessor)
+# TODO(tyoshino): Reorganize class names.
+_compression_extension_names.append('deflate')
+
+
+class PerMessageCompressExtensionProcessor(
+ CompressionExtensionProcessorBase):
+ """permessage-compress extension processor.
+
+ Specification:
+ http://tools.ietf.org/html/draft-ietf-hybi-permessage-compression
+ """
+
+ _DEFLATE_METHOD = 'deflate'
+
+ def __init__(self, request):
+ CompressionExtensionProcessorBase.__init__(self, request)
+
+ def name(self):
+ return common.PERMESSAGE_COMPRESSION_EXTENSION
+
+ def _lookup_compression_processor(self, method_desc):
+ if method_desc.name() == self._DEFLATE_METHOD:
+ return PerMessageDeflateExtensionProcessor(method_desc, False)
+ return None
+
+
+_available_processors[common.PERMESSAGE_COMPRESSION_EXTENSION] = (
+ PerMessageCompressExtensionProcessor)
+_compression_extension_names.append(common.PERMESSAGE_COMPRESSION_EXTENSION)
+
+
+class MuxExtensionProcessor(ExtensionProcessorInterface):
+ """WebSocket multiplexing extension processor."""
+
+ _QUOTA_PARAM = 'quota'
+
+ def __init__(self, request):
+ ExtensionProcessorInterface.__init__(self, request)
+ self._quota = 0
+ self._extensions = []
+
+ def name(self):
+ return common.MUX_EXTENSION
+
+ def check_consistency_with_other_processors(self, processors):
+ before_mux = True
+ for processor in processors:
+ name = processor.name()
+ if name == self.name():
+ before_mux = False
+ continue
+ if not processor.is_active():
+ continue
+ if before_mux:
+ # Mux extension cannot be used after extensions
+ # that depend on frame boundary, extension data field, or any
+ # reserved bits which are attributed to each frame.
+ if (name == common.DEFLATE_FRAME_EXTENSION or
+ name == common.X_WEBKIT_DEFLATE_FRAME_EXTENSION):
+ self.set_active(False)
+ return
+ else:
+ # Mux extension should not be applied before any history-based
+ # compression extension.
+ if (name == common.DEFLATE_FRAME_EXTENSION or
+ name == common.X_WEBKIT_DEFLATE_FRAME_EXTENSION or
+ name == common.PERMESSAGE_COMPRESSION_EXTENSION or
+ name == common.X_WEBKIT_PERMESSAGE_COMPRESSION_EXTENSION):
+ self.set_active(False)
+ return
+
+ def _get_extension_response_internal(self):
+ self._active = False
+ quota = self._request.get_parameter_value(self._QUOTA_PARAM)
+ if quota is not None:
+ try:
+ quota = int(quota)
+ except ValueError, e:
+ return None
+ if quota < 0 or quota >= 2 ** 32:
+ return None
+ self._quota = quota
+
+ self._active = True
+ return common.ExtensionParameter(common.MUX_EXTENSION)
+
+ def _setup_stream_options_internal(self, stream_options):
+ pass
+
+ def set_quota(self, quota):
+ self._quota = quota
+
+ def quota(self):
+ return self._quota
+
+ def set_extensions(self, extensions):
+ self._extensions = extensions
+
+ def extensions(self):
+ return self._extensions
+
+
+_available_processors[common.MUX_EXTENSION] = MuxExtensionProcessor
+
+
+def get_extension_processor(extension_request):
+ """Given an ExtensionParameter representing an extension offer received
+ from a client, configures and returns an instance of the corresponding
+ extension processor class.
+ """
+
+ processor_class = _available_processors.get(extension_request.name())
+ if processor_class is None:
+ return None
+ return processor_class(extension_request)
+
+
+def is_compression_extension(extension_name):
+ return extension_name in _compression_extension_names
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/fast_masking.i b/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/fast_masking.i
new file mode 100644
index 00000000000..ddaad27f53c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/fast_masking.i
@@ -0,0 +1,98 @@
+// Copyright 2013, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+%module fast_masking
+
+%include "cstring.i"
+
+%{
+#include <cstring>
+
+#ifdef __SSE2__
+#include <emmintrin.h>
+#endif
+%}
+
+%apply (char *STRING, int LENGTH) {
+ (const char* payload, int payload_length),
+ (const char* masking_key, int masking_key_length) };
+%cstring_output_allocate_size(
+ char** result, int* result_length, delete [] *$1);
+
+%inline %{
+
+void mask(
+ const char* payload, int payload_length,
+ const char* masking_key, int masking_key_length,
+ int masking_key_index,
+ char** result, int* result_length) {
+ *result = new char[payload_length];
+ *result_length = payload_length;
+ memcpy(*result, payload, payload_length);
+
+ char* cursor = *result;
+ char* cursor_end = *result + *result_length;
+
+#ifdef __SSE2__
+ while ((cursor < cursor_end) &&
+ (reinterpret_cast<size_t>(cursor) & 0xf)) {
+ *cursor ^= masking_key[masking_key_index];
+ ++cursor;
+ masking_key_index = (masking_key_index + 1) % masking_key_length;
+ }
+ if (cursor == cursor_end) {
+ return;
+ }
+
+ const int kBlockSize = 16;
+ __m128i masking_key_block;
+ for (int i = 0; i < kBlockSize; ++i) {
+ *(reinterpret_cast<char*>(&masking_key_block) + i) =
+ masking_key[masking_key_index];
+ masking_key_index = (masking_key_index + 1) % masking_key_length;
+ }
+
+ while (cursor + kBlockSize <= cursor_end) {
+ __m128i payload_block =
+ _mm_load_si128(reinterpret_cast<__m128i*>(cursor));
+ _mm_stream_si128(reinterpret_cast<__m128i*>(cursor),
+ _mm_xor_si128(payload_block, masking_key_block));
+ cursor += kBlockSize;
+ }
+#endif
+
+ while (cursor < cursor_end) {
+ *cursor ^= masking_key[masking_key_index];
+ ++cursor;
+ masking_key_index = (masking_key_index + 1) % masking_key_length;
+ }
+}
+
+%}
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/handshake/__init__.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/handshake/__init__.py
new file mode 100644
index 00000000000..194f6b395ae
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/handshake/__init__.py
@@ -0,0 +1,110 @@
+# Copyright 2011, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+"""WebSocket opening handshake processor. This class try to apply available
+opening handshake processors for each protocol version until a connection is
+successfully established.
+"""
+
+
+import logging
+
+from mod_pywebsocket import common
+from mod_pywebsocket.handshake import hybi00
+from mod_pywebsocket.handshake import hybi
+# Export AbortedByUserException, HandshakeException, and VersionException
+# symbol from this module.
+from mod_pywebsocket.handshake._base import AbortedByUserException
+from mod_pywebsocket.handshake._base import HandshakeException
+from mod_pywebsocket.handshake._base import VersionException
+
+
+_LOGGER = logging.getLogger(__name__)
+
+
+def do_handshake(request, dispatcher, allowDraft75=False, strict=False):
+ """Performs WebSocket handshake.
+
+ Args:
+ request: mod_python request.
+ dispatcher: Dispatcher (dispatch.Dispatcher).
+ allowDraft75: obsolete argument. ignored.
+ strict: obsolete argument. ignored.
+
+ Handshaker will add attributes such as ws_resource in performing
+ handshake.
+ """
+
+ _LOGGER.debug('Client\'s opening handshake resource: %r', request.uri)
+ # To print mimetools.Message as escaped one-line string, we converts
+ # headers_in to dict object. Without conversion, if we use %r, it just
+ # prints the type and address, and if we use %s, it prints the original
+ # header string as multiple lines.
+ #
+ # Both mimetools.Message and MpTable_Type of mod_python can be
+ # converted to dict.
+ #
+ # mimetools.Message.__str__ returns the original header string.
+ # dict(mimetools.Message object) returns the map from header names to
+ # header values. While MpTable_Type doesn't have such __str__ but just
+ # __repr__ which formats itself as well as dictionary object.
+ _LOGGER.debug(
+ 'Client\'s opening handshake headers: %r', dict(request.headers_in))
+
+ handshakers = []
+ handshakers.append(
+ ('RFC 6455', hybi.Handshaker(request, dispatcher)))
+ handshakers.append(
+ ('HyBi 00', hybi00.Handshaker(request, dispatcher)))
+
+ for name, handshaker in handshakers:
+ _LOGGER.debug('Trying protocol version %s', name)
+ try:
+ handshaker.do_handshake()
+ _LOGGER.info('Established (%s protocol)', name)
+ return
+ except HandshakeException, e:
+ _LOGGER.debug(
+ 'Failed to complete opening handshake as %s protocol: %r',
+ name, e)
+ if e.status:
+ raise e
+ except AbortedByUserException, e:
+ raise
+ except VersionException, e:
+ raise
+
+ # TODO(toyoshim): Add a test to cover the case all handshakers fail.
+ raise HandshakeException(
+ 'Failed to complete opening handshake for all available protocols',
+ status=common.HTTP_STATUS_BAD_REQUEST)
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/handshake/_base.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/handshake/_base.py
new file mode 100644
index 00000000000..c993a584b7b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/handshake/_base.py
@@ -0,0 +1,182 @@
+# Copyright 2012, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+"""Common functions and exceptions used by WebSocket opening handshake
+processors.
+"""
+
+
+from mod_pywebsocket import common
+from mod_pywebsocket import http_header_util
+
+
+class AbortedByUserException(Exception):
+ """Exception for aborting a connection intentionally.
+
+ If this exception is raised in do_extra_handshake handler, the connection
+ will be abandoned. No other WebSocket or HTTP(S) handler will be invoked.
+
+ If this exception is raised in transfer_data_handler, the connection will
+ be closed without closing handshake. No other WebSocket or HTTP(S) handler
+ will be invoked.
+ """
+
+ pass
+
+
+class HandshakeException(Exception):
+ """This exception will be raised when an error occurred while processing
+ WebSocket initial handshake.
+ """
+
+ def __init__(self, name, status=None):
+ super(HandshakeException, self).__init__(name)
+ self.status = status
+
+
+class VersionException(Exception):
+ """This exception will be raised when a version of client request does not
+ match with version the server supports.
+ """
+
+ def __init__(self, name, supported_versions=''):
+ """Construct an instance.
+
+ Args:
+ supported_version: a str object to show supported hybi versions.
+ (e.g. '8, 13')
+ """
+ super(VersionException, self).__init__(name)
+ self.supported_versions = supported_versions
+
+
+def get_default_port(is_secure):
+ if is_secure:
+ return common.DEFAULT_WEB_SOCKET_SECURE_PORT
+ else:
+ return common.DEFAULT_WEB_SOCKET_PORT
+
+
+def validate_subprotocol(subprotocol):
+ """Validate a value in the Sec-WebSocket-Protocol field.
+
+ See the Section 4.1., 4.2.2., and 4.3. of RFC 6455.
+ """
+
+ if not subprotocol:
+ raise HandshakeException('Invalid subprotocol name: empty')
+
+ # Parameter should be encoded HTTP token.
+ state = http_header_util.ParsingState(subprotocol)
+ token = http_header_util.consume_token(state)
+ rest = http_header_util.peek(state)
+ # If |rest| is not None, |subprotocol| is not one token or invalid. If
+ # |rest| is None, |token| must not be None because |subprotocol| is
+ # concatenation of |token| and |rest| and is not None.
+ if rest is not None:
+ raise HandshakeException('Invalid non-token string in subprotocol '
+ 'name: %r' % rest)
+
+
+def parse_host_header(request):
+ fields = request.headers_in[common.HOST_HEADER].split(':', 1)
+ if len(fields) == 1:
+ return fields[0], get_default_port(request.is_https())
+ try:
+ return fields[0], int(fields[1])
+ except ValueError, e:
+ raise HandshakeException('Invalid port number format: %r' % e)
+
+
+def format_header(name, value):
+ return '%s: %s\r\n' % (name, value)
+
+
+def get_mandatory_header(request, key):
+ value = request.headers_in.get(key)
+ if value is None:
+ raise HandshakeException('Header %s is not defined' % key)
+ return value
+
+
+def validate_mandatory_header(request, key, expected_value, fail_status=None):
+ value = get_mandatory_header(request, key)
+
+ if value.lower() != expected_value.lower():
+ raise HandshakeException(
+ 'Expected %r for header %s but found %r (case-insensitive)' %
+ (expected_value, key, value), status=fail_status)
+
+
+def check_request_line(request):
+ # 5.1 1. The three character UTF-8 string "GET".
+ # 5.1 2. A UTF-8-encoded U+0020 SPACE character (0x20 byte).
+ if request.method != 'GET':
+ raise HandshakeException('Method is not GET: %r' % request.method)
+
+ if request.protocol != 'HTTP/1.1':
+ raise HandshakeException('Version is not HTTP/1.1: %r' %
+ request.protocol)
+
+
+def parse_token_list(data):
+ """Parses a header value which follows 1#token and returns parsed elements
+ as a list of strings.
+
+ Leading LWSes must be trimmed.
+ """
+
+ state = http_header_util.ParsingState(data)
+
+ token_list = []
+
+ while True:
+ token = http_header_util.consume_token(state)
+ if token is not None:
+ token_list.append(token)
+
+ http_header_util.consume_lwses(state)
+
+ if http_header_util.peek(state) is None:
+ break
+
+ if not http_header_util.consume_string(state, ','):
+ raise HandshakeException(
+ 'Expected a comma but found %r' % http_header_util.peek(state))
+
+ http_header_util.consume_lwses(state)
+
+ if len(token_list) == 0:
+ raise HandshakeException('No valid token found')
+
+ return token_list
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/handshake/hybi.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/handshake/hybi.py
new file mode 100644
index 00000000000..1ad10ea3728
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/handshake/hybi.py
@@ -0,0 +1,420 @@
+# Copyright 2012, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+"""This file provides the opening handshake processor for the WebSocket
+protocol (RFC 6455).
+
+Specification:
+http://tools.ietf.org/html/rfc6455
+"""
+
+
+# Note: request.connection.write is used in this module, even though mod_python
+# document says that it should be used only in connection handlers.
+# Unfortunately, we have no other options. For example, request.write is not
+# suitable because it doesn't allow direct raw bytes writing.
+
+
+import base64
+import logging
+import os
+import re
+
+from mod_pywebsocket import common
+from mod_pywebsocket.extensions import get_extension_processor
+from mod_pywebsocket.extensions import is_compression_extension
+from mod_pywebsocket.handshake._base import check_request_line
+from mod_pywebsocket.handshake._base import format_header
+from mod_pywebsocket.handshake._base import get_mandatory_header
+from mod_pywebsocket.handshake._base import HandshakeException
+from mod_pywebsocket.handshake._base import parse_token_list
+from mod_pywebsocket.handshake._base import validate_mandatory_header
+from mod_pywebsocket.handshake._base import validate_subprotocol
+from mod_pywebsocket.handshake._base import VersionException
+from mod_pywebsocket.stream import Stream
+from mod_pywebsocket.stream import StreamOptions
+from mod_pywebsocket import util
+
+
+# Used to validate the value in the Sec-WebSocket-Key header strictly. RFC 4648
+# disallows non-zero padding, so the character right before == must be any of
+# A, Q, g and w.
+_SEC_WEBSOCKET_KEY_REGEX = re.compile('^[+/0-9A-Za-z]{21}[AQgw]==$')
+
+# Defining aliases for values used frequently.
+_VERSION_LATEST = common.VERSION_HYBI_LATEST
+_VERSION_LATEST_STRING = str(_VERSION_LATEST)
+_SUPPORTED_VERSIONS = [
+ _VERSION_LATEST,
+]
+
+
+def compute_accept(key):
+ """Computes value for the Sec-WebSocket-Accept header from value of the
+ Sec-WebSocket-Key header.
+ """
+
+ accept_binary = util.sha1_hash(
+ key + common.WEBSOCKET_ACCEPT_UUID).digest()
+ accept = base64.b64encode(accept_binary)
+
+ return (accept, accept_binary)
+
+
+class Handshaker(object):
+ """Opening handshake processor for the WebSocket protocol (RFC 6455)."""
+
+ def __init__(self, request, dispatcher):
+ """Construct an instance.
+
+ Args:
+ request: mod_python request.
+ dispatcher: Dispatcher (dispatch.Dispatcher).
+
+ Handshaker will add attributes such as ws_resource during handshake.
+ """
+
+ self._logger = util.get_class_logger(self)
+
+ self._request = request
+ self._dispatcher = dispatcher
+
+ def _validate_connection_header(self):
+ connection = get_mandatory_header(
+ self._request, common.CONNECTION_HEADER)
+
+ try:
+ connection_tokens = parse_token_list(connection)
+ except HandshakeException, e:
+ raise HandshakeException(
+ 'Failed to parse %s: %s' % (common.CONNECTION_HEADER, e))
+
+ connection_is_valid = False
+ for token in connection_tokens:
+ if token.lower() == common.UPGRADE_CONNECTION_TYPE.lower():
+ connection_is_valid = True
+ break
+ if not connection_is_valid:
+ raise HandshakeException(
+ '%s header doesn\'t contain "%s"' %
+ (common.CONNECTION_HEADER, common.UPGRADE_CONNECTION_TYPE))
+
+ def do_handshake(self):
+ self._request.ws_close_code = None
+ self._request.ws_close_reason = None
+
+ # Parsing.
+
+ check_request_line(self._request)
+
+ validate_mandatory_header(
+ self._request,
+ common.UPGRADE_HEADER,
+ common.WEBSOCKET_UPGRADE_TYPE)
+
+ self._validate_connection_header()
+
+ self._request.ws_resource = self._request.uri
+
+ unused_host = get_mandatory_header(self._request, common.HOST_HEADER)
+
+ self._request.ws_version = self._check_version()
+
+ try:
+ self._get_origin()
+ self._set_protocol()
+ self._parse_extensions()
+
+ # Key validation, response generation.
+
+ key = self._get_key()
+ (accept, accept_binary) = compute_accept(key)
+ self._logger.debug(
+ '%s: %r (%s)',
+ common.SEC_WEBSOCKET_ACCEPT_HEADER,
+ accept,
+ util.hexify(accept_binary))
+
+ self._logger.debug('Protocol version is RFC 6455')
+
+ # Setup extension processors.
+
+ processors = []
+ if self._request.ws_requested_extensions is not None:
+ for extension_request in self._request.ws_requested_extensions:
+ processor = get_extension_processor(extension_request)
+ # Unknown extension requests are just ignored.
+ if processor is not None:
+ processors.append(processor)
+ self._request.ws_extension_processors = processors
+
+ # List of extra headers. The extra handshake handler may add header
+ # data as name/value pairs to this list and pywebsocket appends
+ # them to the WebSocket handshake.
+ self._request.extra_headers = []
+
+ # Extra handshake handler may modify/remove processors.
+ self._dispatcher.do_extra_handshake(self._request)
+ processors = filter(lambda processor: processor is not None,
+ self._request.ws_extension_processors)
+
+ # Ask each processor if there are extensions on the request which
+ # cannot co-exist. When processor decided other processors cannot
+ # co-exist with it, the processor marks them (or itself) as
+ # "inactive". The first extension processor has the right to
+ # make the final call.
+ for processor in reversed(processors):
+ if processor.is_active():
+ processor.check_consistency_with_other_processors(
+ processors)
+ processors = filter(lambda processor: processor.is_active(),
+ processors)
+
+ accepted_extensions = []
+
+ # We need to take into account of mux extension here.
+ # If mux extension exists:
+ # - Remove processors of extensions for logical channel,
+ # which are processors located before the mux processor
+ # - Pass extension requests for logical channel to mux processor
+ # - Attach the mux processor to the request. It will be referred
+ # by dispatcher to see whether the dispatcher should use mux
+ # handler or not.
+ mux_index = -1
+ for i, processor in enumerate(processors):
+ if processor.name() == common.MUX_EXTENSION:
+ mux_index = i
+ break
+ if mux_index >= 0:
+ logical_channel_extensions = []
+ for processor in processors[:mux_index]:
+ logical_channel_extensions.append(processor.request())
+ processor.set_active(False)
+ self._request.mux_processor = processors[mux_index]
+ self._request.mux_processor.set_extensions(
+ logical_channel_extensions)
+ processors = filter(lambda processor: processor.is_active(),
+ processors)
+
+ stream_options = StreamOptions()
+
+ for index, processor in enumerate(processors):
+ if not processor.is_active():
+ continue
+
+ extension_response = processor.get_extension_response()
+ if extension_response is None:
+ # Rejected.
+ continue
+
+ accepted_extensions.append(extension_response)
+
+ processor.setup_stream_options(stream_options)
+
+ if not is_compression_extension(processor.name()):
+ continue
+
+ # Inactivate all of the following compression extensions.
+ for j in xrange(index + 1, len(processors)):
+ if is_compression_extension(processors[j].name()):
+ processors[j].set_active(False)
+
+ if len(accepted_extensions) > 0:
+ self._request.ws_extensions = accepted_extensions
+ self._logger.debug(
+ 'Extensions accepted: %r',
+ map(common.ExtensionParameter.name, accepted_extensions))
+ else:
+ self._request.ws_extensions = None
+
+ self._request.ws_stream = self._create_stream(stream_options)
+
+ if self._request.ws_requested_protocols is not None:
+ if self._request.ws_protocol is None:
+ raise HandshakeException(
+ 'do_extra_handshake must choose one subprotocol from '
+ 'ws_requested_protocols and set it to ws_protocol')
+ validate_subprotocol(self._request.ws_protocol)
+
+ self._logger.debug(
+ 'Subprotocol accepted: %r',
+ self._request.ws_protocol)
+ else:
+ if self._request.ws_protocol is not None:
+ raise HandshakeException(
+ 'ws_protocol must be None when the client didn\'t '
+ 'request any subprotocol')
+
+ self._send_handshake(accept)
+ except HandshakeException, e:
+ if not e.status:
+ # Fallback to 400 bad request by default.
+ e.status = common.HTTP_STATUS_BAD_REQUEST
+ raise e
+
+ def _get_origin(self):
+ origin_header = common.ORIGIN_HEADER
+ origin = self._request.headers_in.get(origin_header)
+ if origin is None:
+ self._logger.debug('Client request does not have origin header')
+ self._request.ws_origin = origin
+
+ def _check_version(self):
+ version = get_mandatory_header(self._request,
+ common.SEC_WEBSOCKET_VERSION_HEADER)
+ if version == _VERSION_LATEST_STRING:
+ return _VERSION_LATEST
+
+ if version.find(',') >= 0:
+ raise HandshakeException(
+ 'Multiple versions (%r) are not allowed for header %s' %
+ (version, common.SEC_WEBSOCKET_VERSION_HEADER),
+ status=common.HTTP_STATUS_BAD_REQUEST)
+ raise VersionException(
+ 'Unsupported version %r for header %s' %
+ (version, common.SEC_WEBSOCKET_VERSION_HEADER),
+ supported_versions=', '.join(map(str, _SUPPORTED_VERSIONS)))
+
+ def _set_protocol(self):
+ self._request.ws_protocol = None
+
+ protocol_header = self._request.headers_in.get(
+ common.SEC_WEBSOCKET_PROTOCOL_HEADER)
+
+ if protocol_header is None:
+ self._request.ws_requested_protocols = None
+ return
+
+ self._request.ws_requested_protocols = parse_token_list(
+ protocol_header)
+ self._logger.debug('Subprotocols requested: %r',
+ self._request.ws_requested_protocols)
+
+ def _parse_extensions(self):
+ extensions_header = self._request.headers_in.get(
+ common.SEC_WEBSOCKET_EXTENSIONS_HEADER)
+ if not extensions_header:
+ self._request.ws_requested_extensions = None
+ return
+
+ try:
+ self._request.ws_requested_extensions = common.parse_extensions(
+ extensions_header)
+ except common.ExtensionParsingException, e:
+ raise HandshakeException(
+ 'Failed to parse Sec-WebSocket-Extensions header: %r' % e)
+
+ self._logger.debug(
+ 'Extensions requested: %r',
+ map(common.ExtensionParameter.name,
+ self._request.ws_requested_extensions))
+
+ def _validate_key(self, key):
+ if key.find(',') >= 0:
+ raise HandshakeException('Request has multiple %s header lines or '
+ 'contains illegal character \',\': %r' %
+ (common.SEC_WEBSOCKET_KEY_HEADER, key))
+
+ # Validate
+ key_is_valid = False
+ try:
+ # Validate key by quick regex match before parsing by base64
+ # module. Because base64 module skips invalid characters, we have
+ # to do this in advance to make this server strictly reject illegal
+ # keys.
+ if _SEC_WEBSOCKET_KEY_REGEX.match(key):
+ decoded_key = base64.b64decode(key)
+ if len(decoded_key) == 16:
+ key_is_valid = True
+ except TypeError, e:
+ pass
+
+ if not key_is_valid:
+ raise HandshakeException(
+ 'Illegal value for header %s: %r' %
+ (common.SEC_WEBSOCKET_KEY_HEADER, key))
+
+ return decoded_key
+
+ def _get_key(self):
+ key = get_mandatory_header(
+ self._request, common.SEC_WEBSOCKET_KEY_HEADER)
+
+ decoded_key = self._validate_key(key)
+
+ self._logger.debug(
+ '%s: %r (%s)',
+ common.SEC_WEBSOCKET_KEY_HEADER,
+ key,
+ util.hexify(decoded_key))
+
+ return key
+
+ def _create_stream(self, stream_options):
+ return Stream(self._request, stream_options)
+
+ def _create_handshake_response(self, accept):
+ response = []
+
+ response.append('HTTP/1.1 101 Switching Protocols\r\n')
+
+ # WebSocket headers
+ response.append(format_header(
+ common.UPGRADE_HEADER, common.WEBSOCKET_UPGRADE_TYPE))
+ response.append(format_header(
+ common.CONNECTION_HEADER, common.UPGRADE_CONNECTION_TYPE))
+ response.append(format_header(
+ common.SEC_WEBSOCKET_ACCEPT_HEADER, accept))
+ if self._request.ws_protocol is not None:
+ response.append(format_header(
+ common.SEC_WEBSOCKET_PROTOCOL_HEADER,
+ self._request.ws_protocol))
+ if (self._request.ws_extensions is not None and
+ len(self._request.ws_extensions) != 0):
+ response.append(format_header(
+ common.SEC_WEBSOCKET_EXTENSIONS_HEADER,
+ common.format_extensions(self._request.ws_extensions)))
+
+ # Headers not specific for WebSocket
+ for name, value in self._request.extra_headers:
+ response.append(format_header(name, value))
+
+ response.append('\r\n')
+
+ return ''.join(response)
+
+ def _send_handshake(self, accept):
+ raw_response = self._create_handshake_response(accept)
+ self._request.connection.write(raw_response)
+ self._logger.debug('Sent server\'s opening handshake: %r',
+ raw_response)
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/handshake/hybi00.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/handshake/hybi00.py
new file mode 100644
index 00000000000..8757717a639
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/handshake/hybi00.py
@@ -0,0 +1,293 @@
+# Copyright 2011, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+"""This file provides the opening handshake processor for the WebSocket
+protocol version HyBi 00.
+
+Specification:
+http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-00
+"""
+
+
+# Note: request.connection.write/read are used in this module, even though
+# mod_python document says that they should be used only in connection
+# handlers. Unfortunately, we have no other options. For example,
+# request.write/read are not suitable because they don't allow direct raw bytes
+# writing/reading.
+
+
+import logging
+import re
+import struct
+
+from mod_pywebsocket import common
+from mod_pywebsocket.stream import StreamHixie75
+from mod_pywebsocket import util
+from mod_pywebsocket.handshake._base import HandshakeException
+from mod_pywebsocket.handshake._base import check_request_line
+from mod_pywebsocket.handshake._base import format_header
+from mod_pywebsocket.handshake._base import get_default_port
+from mod_pywebsocket.handshake._base import get_mandatory_header
+from mod_pywebsocket.handshake._base import parse_host_header
+from mod_pywebsocket.handshake._base import validate_mandatory_header
+
+
+_MANDATORY_HEADERS = [
+ # key, expected value or None
+ [common.UPGRADE_HEADER, common.WEBSOCKET_UPGRADE_TYPE_HIXIE75],
+ [common.CONNECTION_HEADER, common.UPGRADE_CONNECTION_TYPE],
+]
+
+
+def _validate_subprotocol(subprotocol):
+ """Checks if characters in subprotocol are in range between U+0020 and
+ U+007E. A value in the Sec-WebSocket-Protocol field need to satisfy this
+ requirement.
+
+ See the Section 4.1. Opening handshake of the spec.
+ """
+
+ if not subprotocol:
+ raise HandshakeException('Invalid subprotocol name: empty')
+
+ # Parameter should be in the range U+0020 to U+007E.
+ for c in subprotocol:
+ if not 0x20 <= ord(c) <= 0x7e:
+ raise HandshakeException(
+ 'Illegal character in subprotocol name: %r' % c)
+
+
+def _check_header_lines(request, mandatory_headers):
+ check_request_line(request)
+
+ # The expected field names, and the meaning of their corresponding
+ # values, are as follows.
+ # |Upgrade| and |Connection|
+ for key, expected_value in mandatory_headers:
+ validate_mandatory_header(request, key, expected_value)
+
+
+def _build_location(request):
+ """Build WebSocket location for request."""
+
+ location_parts = []
+ if request.is_https():
+ location_parts.append(common.WEB_SOCKET_SECURE_SCHEME)
+ else:
+ location_parts.append(common.WEB_SOCKET_SCHEME)
+ location_parts.append('://')
+ host, port = parse_host_header(request)
+ connection_port = request.connection.local_addr[1]
+ if port != connection_port:
+ raise HandshakeException('Header/connection port mismatch: %d/%d' %
+ (port, connection_port))
+ location_parts.append(host)
+ if (port != get_default_port(request.is_https())):
+ location_parts.append(':')
+ location_parts.append(str(port))
+ location_parts.append(request.unparsed_uri)
+ return ''.join(location_parts)
+
+
+class Handshaker(object):
+ """Opening handshake processor for the WebSocket protocol version HyBi 00.
+ """
+
+ def __init__(self, request, dispatcher):
+ """Construct an instance.
+
+ Args:
+ request: mod_python request.
+ dispatcher: Dispatcher (dispatch.Dispatcher).
+
+ Handshaker will add attributes such as ws_resource in performing
+ handshake.
+ """
+
+ self._logger = util.get_class_logger(self)
+
+ self._request = request
+ self._dispatcher = dispatcher
+
+ def do_handshake(self):
+ """Perform WebSocket Handshake.
+
+ On _request, we set
+ ws_resource, ws_protocol, ws_location, ws_origin, ws_challenge,
+ ws_challenge_md5: WebSocket handshake information.
+ ws_stream: Frame generation/parsing class.
+ ws_version: Protocol version.
+
+ Raises:
+ HandshakeException: when any error happened in parsing the opening
+ handshake request.
+ """
+
+ # 5.1 Reading the client's opening handshake.
+ # dispatcher sets it in self._request.
+ _check_header_lines(self._request, _MANDATORY_HEADERS)
+ self._set_resource()
+ self._set_subprotocol()
+ self._set_location()
+ self._set_origin()
+ self._set_challenge_response()
+ self._set_protocol_version()
+
+ self._dispatcher.do_extra_handshake(self._request)
+
+ self._send_handshake()
+
+ def _set_resource(self):
+ self._request.ws_resource = self._request.uri
+
+ def _set_subprotocol(self):
+ # |Sec-WebSocket-Protocol|
+ subprotocol = self._request.headers_in.get(
+ common.SEC_WEBSOCKET_PROTOCOL_HEADER)
+ if subprotocol is not None:
+ _validate_subprotocol(subprotocol)
+ self._request.ws_protocol = subprotocol
+
+ def _set_location(self):
+ # |Host|
+ host = self._request.headers_in.get(common.HOST_HEADER)
+ if host is not None:
+ self._request.ws_location = _build_location(self._request)
+ # TODO(ukai): check host is this host.
+
+ def _set_origin(self):
+ # |Origin|
+ origin = self._request.headers_in.get(common.ORIGIN_HEADER)
+ if origin is not None:
+ self._request.ws_origin = origin
+
+ def _set_protocol_version(self):
+ # |Sec-WebSocket-Draft|
+ draft = self._request.headers_in.get(common.SEC_WEBSOCKET_DRAFT_HEADER)
+ if draft is not None and draft != '0':
+ raise HandshakeException('Illegal value for %s: %s' %
+ (common.SEC_WEBSOCKET_DRAFT_HEADER,
+ draft))
+
+ self._logger.debug('Protocol version is HyBi 00')
+ self._request.ws_version = common.VERSION_HYBI00
+ self._request.ws_stream = StreamHixie75(self._request, True)
+
+ def _set_challenge_response(self):
+ # 5.2 4-8.
+ self._request.ws_challenge = self._get_challenge()
+ # 5.2 9. let /response/ be the MD5 finterprint of /challenge/
+ self._request.ws_challenge_md5 = util.md5_hash(
+ self._request.ws_challenge).digest()
+ self._logger.debug(
+ 'Challenge: %r (%s)',
+ self._request.ws_challenge,
+ util.hexify(self._request.ws_challenge))
+ self._logger.debug(
+ 'Challenge response: %r (%s)',
+ self._request.ws_challenge_md5,
+ util.hexify(self._request.ws_challenge_md5))
+
+ def _get_key_value(self, key_field):
+ key_value = get_mandatory_header(self._request, key_field)
+
+ self._logger.debug('%s: %r', key_field, key_value)
+
+ # 5.2 4. let /key-number_n/ be the digits (characters in the range
+ # U+0030 DIGIT ZERO (0) to U+0039 DIGIT NINE (9)) in /key_n/,
+ # interpreted as a base ten integer, ignoring all other characters
+ # in /key_n/.
+ try:
+ key_number = int(re.sub("\\D", "", key_value))
+ except:
+ raise HandshakeException('%s field contains no digit' % key_field)
+ # 5.2 5. let /spaces_n/ be the number of U+0020 SPACE characters
+ # in /key_n/.
+ spaces = re.subn(" ", "", key_value)[1]
+ if spaces == 0:
+ raise HandshakeException('%s field contains no space' % key_field)
+
+ self._logger.debug(
+ '%s: Key-number is %d and number of spaces is %d',
+ key_field, key_number, spaces)
+
+ # 5.2 6. if /key-number_n/ is not an integral multiple of /spaces_n/
+ # then abort the WebSocket connection.
+ if key_number % spaces != 0:
+ raise HandshakeException(
+ '%s: Key-number (%d) is not an integral multiple of spaces '
+ '(%d)' % (key_field, key_number, spaces))
+ # 5.2 7. let /part_n/ be /key-number_n/ divided by /spaces_n/.
+ part = key_number / spaces
+ self._logger.debug('%s: Part is %d', key_field, part)
+ return part
+
+ def _get_challenge(self):
+ # 5.2 4-7.
+ key1 = self._get_key_value(common.SEC_WEBSOCKET_KEY1_HEADER)
+ key2 = self._get_key_value(common.SEC_WEBSOCKET_KEY2_HEADER)
+ # 5.2 8. let /challenge/ be the concatenation of /part_1/,
+ challenge = ''
+ challenge += struct.pack('!I', key1) # network byteorder int
+ challenge += struct.pack('!I', key2) # network byteorder int
+ challenge += self._request.connection.read(8)
+ return challenge
+
+ def _send_handshake(self):
+ response = []
+
+ # 5.2 10. send the following line.
+ response.append('HTTP/1.1 101 WebSocket Protocol Handshake\r\n')
+
+ # 5.2 11. send the following fields to the client.
+ response.append(format_header(
+ common.UPGRADE_HEADER, common.WEBSOCKET_UPGRADE_TYPE_HIXIE75))
+ response.append(format_header(
+ common.CONNECTION_HEADER, common.UPGRADE_CONNECTION_TYPE))
+ response.append(format_header(
+ common.SEC_WEBSOCKET_LOCATION_HEADER, self._request.ws_location))
+ response.append(format_header(
+ common.SEC_WEBSOCKET_ORIGIN_HEADER, self._request.ws_origin))
+ if self._request.ws_protocol:
+ response.append(format_header(
+ common.SEC_WEBSOCKET_PROTOCOL_HEADER,
+ self._request.ws_protocol))
+ # 5.2 12. send two bytes 0x0D 0x0A.
+ response.append('\r\n')
+ # 5.2 13. send /response/
+ response.append(self._request.ws_challenge_md5)
+
+ raw_response = ''.join(response)
+ self._request.connection.write(raw_response)
+ self._logger.debug('Sent server\'s opening handshake: %r',
+ raw_response)
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/headerparserhandler.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/headerparserhandler.py
new file mode 100644
index 00000000000..c244421cf79
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/headerparserhandler.py
@@ -0,0 +1,254 @@
+# Copyright 2011, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+"""PythonHeaderParserHandler for mod_pywebsocket.
+
+Apache HTTP Server and mod_python must be configured such that this
+function is called to handle WebSocket request.
+"""
+
+
+import logging
+
+from mod_python import apache
+
+from mod_pywebsocket import common
+from mod_pywebsocket import dispatch
+from mod_pywebsocket import handshake
+from mod_pywebsocket import util
+
+
+# PythonOption to specify the handler root directory.
+_PYOPT_HANDLER_ROOT = 'mod_pywebsocket.handler_root'
+
+# PythonOption to specify the handler scan directory.
+# This must be a directory under the root directory.
+# The default is the root directory.
+_PYOPT_HANDLER_SCAN = 'mod_pywebsocket.handler_scan'
+
+# PythonOption to allow handlers whose canonical path is
+# not under the root directory. It's disallowed by default.
+# Set this option with value of 'yes' to allow.
+_PYOPT_ALLOW_HANDLERS_OUTSIDE_ROOT = (
+ 'mod_pywebsocket.allow_handlers_outside_root_dir')
+# Map from values to their meanings. 'Yes' and 'No' are allowed just for
+# compatibility.
+_PYOPT_ALLOW_HANDLERS_OUTSIDE_ROOT_DEFINITION = {
+ 'off': False, 'no': False, 'on': True, 'yes': True}
+
+# (Obsolete option. Ignored.)
+# PythonOption to specify to allow handshake defined in Hixie 75 version
+# protocol. The default is None (Off)
+_PYOPT_ALLOW_DRAFT75 = 'mod_pywebsocket.allow_draft75'
+# Map from values to their meanings.
+_PYOPT_ALLOW_DRAFT75_DEFINITION = {'off': False, 'on': True}
+
+
+class ApacheLogHandler(logging.Handler):
+ """Wrapper logging.Handler to emit log message to apache's error.log."""
+
+ _LEVELS = {
+ logging.DEBUG: apache.APLOG_DEBUG,
+ logging.INFO: apache.APLOG_INFO,
+ logging.WARNING: apache.APLOG_WARNING,
+ logging.ERROR: apache.APLOG_ERR,
+ logging.CRITICAL: apache.APLOG_CRIT,
+ }
+
+ def __init__(self, request=None):
+ logging.Handler.__init__(self)
+ self._log_error = apache.log_error
+ if request is not None:
+ self._log_error = request.log_error
+
+ # Time and level will be printed by Apache.
+ self._formatter = logging.Formatter('%(name)s: %(message)s')
+
+ def emit(self, record):
+ apache_level = apache.APLOG_DEBUG
+ if record.levelno in ApacheLogHandler._LEVELS:
+ apache_level = ApacheLogHandler._LEVELS[record.levelno]
+
+ msg = self._formatter.format(record)
+
+ # "server" parameter must be passed to have "level" parameter work.
+ # If only "level" parameter is passed, nothing shows up on Apache's
+ # log. However, at this point, we cannot get the server object of the
+ # virtual host which will process WebSocket requests. The only server
+ # object we can get here is apache.main_server. But Wherever (server
+ # configuration context or virtual host context) we put
+ # PythonHeaderParserHandler directive, apache.main_server just points
+ # the main server instance (not any of virtual server instance). Then,
+ # Apache follows LogLevel directive in the server configuration context
+ # to filter logs. So, we need to specify LogLevel in the server
+ # configuration context. Even if we specify "LogLevel debug" in the
+ # virtual host context which actually handles WebSocket connections,
+ # DEBUG level logs never show up unless "LogLevel debug" is specified
+ # in the server configuration context.
+ #
+ # TODO(tyoshino): Provide logging methods on request object. When
+ # request is mp_request object (when used together with Apache), the
+ # methods call request.log_error indirectly. When request is
+ # _StandaloneRequest, the methods call Python's logging facility which
+ # we create in standalone.py.
+ self._log_error(msg, apache_level, apache.main_server)
+
+
+def _configure_logging():
+ logger = logging.getLogger()
+ # Logs are filtered by Apache based on LogLevel directive in Apache
+ # configuration file. We must just pass logs for all levels to
+ # ApacheLogHandler.
+ logger.setLevel(logging.DEBUG)
+ logger.addHandler(ApacheLogHandler())
+
+
+_configure_logging()
+
+_LOGGER = logging.getLogger(__name__)
+
+
+def _parse_option(name, value, definition):
+ if value is None:
+ return False
+
+ meaning = definition.get(value.lower())
+ if meaning is None:
+ raise Exception('Invalid value for PythonOption %s: %r' %
+ (name, value))
+ return meaning
+
+
+def _create_dispatcher():
+ _LOGGER.info('Initializing Dispatcher')
+
+ options = apache.main_server.get_options()
+
+ handler_root = options.get(_PYOPT_HANDLER_ROOT, None)
+ if not handler_root:
+ raise Exception('PythonOption %s is not defined' % _PYOPT_HANDLER_ROOT,
+ apache.APLOG_ERR)
+
+ handler_scan = options.get(_PYOPT_HANDLER_SCAN, handler_root)
+
+ allow_handlers_outside_root = _parse_option(
+ _PYOPT_ALLOW_HANDLERS_OUTSIDE_ROOT,
+ options.get(_PYOPT_ALLOW_HANDLERS_OUTSIDE_ROOT),
+ _PYOPT_ALLOW_HANDLERS_OUTSIDE_ROOT_DEFINITION)
+
+ dispatcher = dispatch.Dispatcher(
+ handler_root, handler_scan, allow_handlers_outside_root)
+
+ for warning in dispatcher.source_warnings():
+ apache.log_error(
+ 'mod_pywebsocket: Warning in source loading: %s' % warning,
+ apache.APLOG_WARNING)
+
+ return dispatcher
+
+
+# Initialize
+_dispatcher = _create_dispatcher()
+
+
+def headerparserhandler(request):
+ """Handle request.
+
+ Args:
+ request: mod_python request.
+
+ This function is named headerparserhandler because it is the default
+ name for a PythonHeaderParserHandler.
+ """
+
+ handshake_is_done = False
+ try:
+ # Fallback to default http handler for request paths for which
+ # we don't have request handlers.
+ if not _dispatcher.get_handler_suite(request.uri):
+ request.log_error(
+ 'mod_pywebsocket: No handler for resource: %r' % request.uri,
+ apache.APLOG_INFO)
+ request.log_error(
+ 'mod_pywebsocket: Fallback to Apache', apache.APLOG_INFO)
+ return apache.DECLINED
+ except dispatch.DispatchException, e:
+ request.log_error(
+ 'mod_pywebsocket: Dispatch failed for error: %s' % e,
+ apache.APLOG_INFO)
+ if not handshake_is_done:
+ return e.status
+
+ try:
+ allow_draft75 = _parse_option(
+ _PYOPT_ALLOW_DRAFT75,
+ apache.main_server.get_options().get(_PYOPT_ALLOW_DRAFT75),
+ _PYOPT_ALLOW_DRAFT75_DEFINITION)
+
+ try:
+ handshake.do_handshake(
+ request, _dispatcher, allowDraft75=allow_draft75)
+ except handshake.VersionException, e:
+ request.log_error(
+ 'mod_pywebsocket: Handshake failed for version error: %s' % e,
+ apache.APLOG_INFO)
+ request.err_headers_out.add(common.SEC_WEBSOCKET_VERSION_HEADER,
+ e.supported_versions)
+ return apache.HTTP_BAD_REQUEST
+ except handshake.HandshakeException, e:
+ # Handshake for ws/wss failed.
+ # Send http response with error status.
+ request.log_error(
+ 'mod_pywebsocket: Handshake failed for error: %s' % e,
+ apache.APLOG_INFO)
+ return e.status
+
+ handshake_is_done = True
+ request._dispatcher = _dispatcher
+ _dispatcher.transfer_data(request)
+ except handshake.AbortedByUserException, e:
+ request.log_error('mod_pywebsocket: Aborted: %s' % e, apache.APLOG_INFO)
+ except Exception, e:
+ # DispatchException can also be thrown if something is wrong in
+ # pywebsocket code. It's caught here, then.
+
+ request.log_error('mod_pywebsocket: Exception occurred: %s\n%s' %
+ (e, util.get_stack_trace()),
+ apache.APLOG_ERR)
+ # Unknown exceptions before handshake mean Apache must handle its
+ # request with another handler.
+ if not handshake_is_done:
+ return apache.DECLINED
+ # Set assbackwards to suppress response header generation by Apache.
+ request.assbackwards = 1
+ return apache.DONE # Return DONE such that no other handlers are invoked.
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/http_header_util.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/http_header_util.py
new file mode 100644
index 00000000000..b7746539328
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/http_header_util.py
@@ -0,0 +1,263 @@
+# Copyright 2011, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+"""Utilities for parsing and formatting headers that follow the grammar defined
+in HTTP RFC http://www.ietf.org/rfc/rfc2616.txt.
+"""
+
+
+import urlparse
+
+
+_SEPARATORS = '()<>@,;:\\"/[]?={} \t'
+
+
+def _is_char(c):
+ """Returns true iff c is in CHAR as specified in HTTP RFC."""
+
+ return ord(c) <= 127
+
+
+def _is_ctl(c):
+ """Returns true iff c is in CTL as specified in HTTP RFC."""
+
+ return ord(c) <= 31 or ord(c) == 127
+
+
+class ParsingState(object):
+
+ def __init__(self, data):
+ self.data = data
+ self.head = 0
+
+
+def peek(state, pos=0):
+ """Peeks the character at pos from the head of data."""
+
+ if state.head + pos >= len(state.data):
+ return None
+
+ return state.data[state.head + pos]
+
+
+def consume(state, amount=1):
+ """Consumes specified amount of bytes from the head and returns the
+ consumed bytes. If there's not enough bytes to consume, returns None.
+ """
+
+ if state.head + amount > len(state.data):
+ return None
+
+ result = state.data[state.head:state.head + amount]
+ state.head = state.head + amount
+ return result
+
+
+def consume_string(state, expected):
+ """Given a parsing state and a expected string, consumes the string from
+ the head. Returns True if consumed successfully. Otherwise, returns
+ False.
+ """
+
+ pos = 0
+
+ for c in expected:
+ if c != peek(state, pos):
+ return False
+ pos += 1
+
+ consume(state, pos)
+ return True
+
+
+def consume_lws(state):
+ """Consumes a LWS from the head. Returns True if any LWS is consumed.
+ Otherwise, returns False.
+
+ LWS = [CRLF] 1*( SP | HT )
+ """
+
+ original_head = state.head
+
+ consume_string(state, '\r\n')
+
+ pos = 0
+
+ while True:
+ c = peek(state, pos)
+ if c == ' ' or c == '\t':
+ pos += 1
+ else:
+ if pos == 0:
+ state.head = original_head
+ return False
+ else:
+ consume(state, pos)
+ return True
+
+
+def consume_lwses(state):
+ """Consumes *LWS from the head."""
+
+ while consume_lws(state):
+ pass
+
+
+def consume_token(state):
+ """Consumes a token from the head. Returns the token or None if no token
+ was found.
+ """
+
+ pos = 0
+
+ while True:
+ c = peek(state, pos)
+ if c is None or c in _SEPARATORS or _is_ctl(c) or not _is_char(c):
+ if pos == 0:
+ return None
+
+ return consume(state, pos)
+ else:
+ pos += 1
+
+
+def consume_token_or_quoted_string(state):
+ """Consumes a token or a quoted-string, and returns the token or unquoted
+ string. If no token or quoted-string was found, returns None.
+ """
+
+ original_head = state.head
+
+ if not consume_string(state, '"'):
+ return consume_token(state)
+
+ result = []
+
+ expect_quoted_pair = False
+
+ while True:
+ if not expect_quoted_pair and consume_lws(state):
+ result.append(' ')
+ continue
+
+ c = consume(state)
+ if c is None:
+ # quoted-string is not enclosed with double quotation
+ state.head = original_head
+ return None
+ elif expect_quoted_pair:
+ expect_quoted_pair = False
+ if _is_char(c):
+ result.append(c)
+ else:
+ # Non CHAR character found in quoted-pair
+ state.head = original_head
+ return None
+ elif c == '\\':
+ expect_quoted_pair = True
+ elif c == '"':
+ return ''.join(result)
+ elif _is_ctl(c):
+ # Invalid character %r found in qdtext
+ state.head = original_head
+ return None
+ else:
+ result.append(c)
+
+
+def quote_if_necessary(s):
+ """Quotes arbitrary string into quoted-string."""
+
+ quote = False
+ if s == '':
+ return '""'
+
+ result = []
+ for c in s:
+ if c == '"' or c in _SEPARATORS or _is_ctl(c) or not _is_char(c):
+ quote = True
+
+ if c == '"' or _is_ctl(c):
+ result.append('\\' + c)
+ else:
+ result.append(c)
+
+ if quote:
+ return '"' + ''.join(result) + '"'
+ else:
+ return ''.join(result)
+
+
+def parse_uri(uri):
+ """Parse absolute URI then return host, port and resource."""
+
+ parsed = urlparse.urlsplit(uri)
+ if parsed.scheme != 'wss' and parsed.scheme != 'ws':
+ # |uri| must be a relative URI.
+ # TODO(toyoshim): Should validate |uri|.
+ return None, None, uri
+
+ if parsed.hostname is None:
+ return None, None, None
+
+ port = None
+ try:
+ port = parsed.port
+ except ValueError, e:
+ # port property cause ValueError on invalid null port description like
+ # 'ws://host:/path'.
+ return None, None, None
+
+ if port is None:
+ if parsed.scheme == 'ws':
+ port = 80
+ else:
+ port = 443
+
+ path = parsed.path
+ if not path:
+ path += '/'
+ if parsed.query:
+ path += '?' + parsed.query
+ if parsed.fragment:
+ path += '#' + parsed.fragment
+
+ return parsed.hostname, port, path
+
+
+try:
+ urlparse.uses_netloc.index('ws')
+except ValueError, e:
+ # urlparse in Python2.5.1 doesn't have 'ws' and 'wss' entries.
+ urlparse.uses_netloc.append('ws')
+ urlparse.uses_netloc.append('wss')
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/memorizingfile.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/memorizingfile.py
new file mode 100644
index 00000000000..4d4cd958595
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/memorizingfile.py
@@ -0,0 +1,99 @@
+#!/usr/bin/env python
+#
+# Copyright 2011, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+"""Memorizing file.
+
+A memorizing file wraps a file and memorizes lines read by readline.
+"""
+
+
+import sys
+
+
+class MemorizingFile(object):
+ """MemorizingFile wraps a file and memorizes lines read by readline.
+
+ Note that data read by other methods are not memorized. This behavior
+ is good enough for memorizing lines SimpleHTTPServer reads before
+ the control reaches WebSocketRequestHandler.
+ """
+
+ def __init__(self, file_, max_memorized_lines=sys.maxint):
+ """Construct an instance.
+
+ Args:
+ file_: the file object to wrap.
+ max_memorized_lines: the maximum number of lines to memorize.
+ Only the first max_memorized_lines are memorized.
+ Default: sys.maxint.
+ """
+
+ self._file = file_
+ self._memorized_lines = []
+ self._max_memorized_lines = max_memorized_lines
+ self._buffered = False
+ self._buffered_line = None
+
+ def __getattribute__(self, name):
+ if name in ('_file', '_memorized_lines', '_max_memorized_lines',
+ '_buffered', '_buffered_line', 'readline',
+ 'get_memorized_lines'):
+ return object.__getattribute__(self, name)
+ return self._file.__getattribute__(name)
+
+ def readline(self, size=-1):
+ """Override file.readline and memorize the line read.
+
+ Note that even if size is specified and smaller than actual size,
+ the whole line will be read out from underlying file object by
+ subsequent readline calls.
+ """
+
+ if self._buffered:
+ line = self._buffered_line
+ self._buffered = False
+ else:
+ line = self._file.readline()
+ if line and len(self._memorized_lines) < self._max_memorized_lines:
+ self._memorized_lines.append(line)
+ if size >= 0 and size < len(line):
+ self._buffered = True
+ self._buffered_line = line[size:]
+ return line[:size]
+ return line
+
+ def get_memorized_lines(self):
+ """Get lines memorized so far."""
+ return self._memorized_lines
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/msgutil.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/msgutil.py
new file mode 100644
index 00000000000..4c1a0114b4b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/msgutil.py
@@ -0,0 +1,219 @@
+# Copyright 2011, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+"""Message related utilities.
+
+Note: request.connection.write/read are used in this module, even though
+mod_python document says that they should be used only in connection
+handlers. Unfortunately, we have no other options. For example,
+request.write/read are not suitable because they don't allow direct raw
+bytes writing/reading.
+"""
+
+
+import Queue
+import threading
+
+
+# Export Exception symbols from msgutil for backward compatibility
+from mod_pywebsocket._stream_base import ConnectionTerminatedException
+from mod_pywebsocket._stream_base import InvalidFrameException
+from mod_pywebsocket._stream_base import BadOperationException
+from mod_pywebsocket._stream_base import UnsupportedFrameException
+
+
+# An API for handler to send/receive WebSocket messages.
+def close_connection(request):
+ """Close connection.
+
+ Args:
+ request: mod_python request.
+ """
+ request.ws_stream.close_connection()
+
+
+def send_message(request, payload_data, end=True, binary=False):
+ """Send a message (or part of a message).
+
+ Args:
+ request: mod_python request.
+ payload_data: unicode text or str binary to send.
+ end: True to terminate a message.
+ False to send payload_data as part of a message that is to be
+ terminated by next or later send_message call with end=True.
+ binary: send payload_data as binary frame(s).
+ Raises:
+ BadOperationException: when server already terminated.
+ """
+ request.ws_stream.send_message(payload_data, end, binary)
+
+
+def receive_message(request):
+ """Receive a WebSocket frame and return its payload as a text in
+ unicode or a binary in str.
+
+ Args:
+ request: mod_python request.
+ Raises:
+ InvalidFrameException: when client send invalid frame.
+ UnsupportedFrameException: when client send unsupported frame e.g. some
+ of reserved bit is set but no extension can
+ recognize it.
+ InvalidUTF8Exception: when client send a text frame containing any
+ invalid UTF-8 string.
+ ConnectionTerminatedException: when the connection is closed
+ unexpectedly.
+ BadOperationException: when client already terminated.
+ """
+ return request.ws_stream.receive_message()
+
+
+def send_ping(request, body=''):
+ request.ws_stream.send_ping(body)
+
+
+class MessageReceiver(threading.Thread):
+ """This class receives messages from the client.
+
+ This class provides three ways to receive messages: blocking,
+ non-blocking, and via callback. Callback has the highest precedence.
+
+ Note: This class should not be used with the standalone server for wss
+ because pyOpenSSL used by the server raises a fatal error if the socket
+ is accessed from multiple threads.
+ """
+
+ def __init__(self, request, onmessage=None):
+ """Construct an instance.
+
+ Args:
+ request: mod_python request.
+ onmessage: a function to be called when a message is received.
+ May be None. If not None, the function is called on
+ another thread. In that case, MessageReceiver.receive
+ and MessageReceiver.receive_nowait are useless
+ because they will never return any messages.
+ """
+
+ threading.Thread.__init__(self)
+ self._request = request
+ self._queue = Queue.Queue()
+ self._onmessage = onmessage
+ self._stop_requested = False
+ self.setDaemon(True)
+ self.start()
+
+ def run(self):
+ try:
+ while not self._stop_requested:
+ message = receive_message(self._request)
+ if self._onmessage:
+ self._onmessage(message)
+ else:
+ self._queue.put(message)
+ finally:
+ close_connection(self._request)
+
+ def receive(self):
+ """ Receive a message from the channel, blocking.
+
+ Returns:
+ message as a unicode string.
+ """
+ return self._queue.get()
+
+ def receive_nowait(self):
+ """ Receive a message from the channel, non-blocking.
+
+ Returns:
+ message as a unicode string if available. None otherwise.
+ """
+ try:
+ message = self._queue.get_nowait()
+ except Queue.Empty:
+ message = None
+ return message
+
+ def stop(self):
+ """Request to stop this instance.
+
+ The instance will be stopped after receiving the next message.
+ This method may not be very useful, but there is no clean way
+ in Python to forcefully stop a running thread.
+ """
+ self._stop_requested = True
+
+
+class MessageSender(threading.Thread):
+ """This class sends messages to the client.
+
+ This class provides both synchronous and asynchronous ways to send
+ messages.
+
+ Note: This class should not be used with the standalone server for wss
+ because pyOpenSSL used by the server raises a fatal error if the socket
+ is accessed from multiple threads.
+ """
+
+ def __init__(self, request):
+ """Construct an instance.
+
+ Args:
+ request: mod_python request.
+ """
+ threading.Thread.__init__(self)
+ self._request = request
+ self._queue = Queue.Queue()
+ self.setDaemon(True)
+ self.start()
+
+ def run(self):
+ while True:
+ message, condition = self._queue.get()
+ condition.acquire()
+ send_message(self._request, message)
+ condition.notify()
+ condition.release()
+
+ def send(self, message):
+ """Send a message, blocking."""
+
+ condition = threading.Condition()
+ condition.acquire()
+ self._queue.put((message, condition))
+ condition.wait()
+
+ def send_nowait(self, message):
+ """Send a message, non-blocking."""
+
+ self._queue.put((message, threading.Condition()))
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/mux.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/mux.py
new file mode 100644
index 00000000000..76334685b31
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/mux.py
@@ -0,0 +1,1889 @@
+# Copyright 2012, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+"""This file provides classes and helper functions for multiplexing extension.
+
+Specification:
+http://tools.ietf.org/html/draft-ietf-hybi-websocket-multiplexing-06
+"""
+
+
+import collections
+import copy
+import email
+import email.parser
+import logging
+import math
+import struct
+import threading
+import traceback
+
+from mod_pywebsocket import common
+from mod_pywebsocket import handshake
+from mod_pywebsocket import util
+from mod_pywebsocket._stream_base import BadOperationException
+from mod_pywebsocket._stream_base import ConnectionTerminatedException
+from mod_pywebsocket._stream_base import InvalidFrameException
+from mod_pywebsocket._stream_hybi import Frame
+from mod_pywebsocket._stream_hybi import Stream
+from mod_pywebsocket._stream_hybi import StreamOptions
+from mod_pywebsocket._stream_hybi import create_binary_frame
+from mod_pywebsocket._stream_hybi import create_closing_handshake_body
+from mod_pywebsocket._stream_hybi import create_header
+from mod_pywebsocket._stream_hybi import create_length_header
+from mod_pywebsocket._stream_hybi import parse_frame
+from mod_pywebsocket.handshake import hybi
+
+
+_CONTROL_CHANNEL_ID = 0
+_DEFAULT_CHANNEL_ID = 1
+
+_MUX_OPCODE_ADD_CHANNEL_REQUEST = 0
+_MUX_OPCODE_ADD_CHANNEL_RESPONSE = 1
+_MUX_OPCODE_FLOW_CONTROL = 2
+_MUX_OPCODE_DROP_CHANNEL = 3
+_MUX_OPCODE_NEW_CHANNEL_SLOT = 4
+
+_MAX_CHANNEL_ID = 2 ** 29 - 1
+
+_INITIAL_NUMBER_OF_CHANNEL_SLOTS = 64
+_INITIAL_QUOTA_FOR_CLIENT = 8 * 1024
+
+_HANDSHAKE_ENCODING_IDENTITY = 0
+_HANDSHAKE_ENCODING_DELTA = 1
+
+# We need only these status code for now.
+_HTTP_BAD_RESPONSE_MESSAGES = {
+ common.HTTP_STATUS_BAD_REQUEST: 'Bad Request',
+}
+
+# DropChannel reason code
+# TODO(bashi): Define all reason code defined in -05 draft.
+_DROP_CODE_NORMAL_CLOSURE = 1000
+
+_DROP_CODE_INVALID_ENCAPSULATING_MESSAGE = 2001
+_DROP_CODE_CHANNEL_ID_TRUNCATED = 2002
+_DROP_CODE_ENCAPSULATED_FRAME_IS_TRUNCATED = 2003
+_DROP_CODE_UNKNOWN_MUX_OPCODE = 2004
+_DROP_CODE_INVALID_MUX_CONTROL_BLOCK = 2005
+_DROP_CODE_CHANNEL_ALREADY_EXISTS = 2006
+_DROP_CODE_NEW_CHANNEL_SLOT_VIOLATION = 2007
+_DROP_CODE_UNKNOWN_REQUEST_ENCODING = 2010
+
+_DROP_CODE_SEND_QUOTA_VIOLATION = 3005
+_DROP_CODE_SEND_QUOTA_OVERFLOW = 3006
+_DROP_CODE_ACKNOWLEDGED = 3008
+_DROP_CODE_BAD_FRAGMENTATION = 3009
+
+
+class MuxUnexpectedException(Exception):
+ """Exception in handling multiplexing extension."""
+ pass
+
+
+# Temporary
+class MuxNotImplementedException(Exception):
+ """Raised when a flow enters unimplemented code path."""
+ pass
+
+
+class LogicalConnectionClosedException(Exception):
+ """Raised when logical connection is gracefully closed."""
+ pass
+
+
+class PhysicalConnectionError(Exception):
+ """Raised when there is a physical connection error."""
+ def __init__(self, drop_code, message=''):
+ super(PhysicalConnectionError, self).__init__(
+ 'code=%d, message=%r' % (drop_code, message))
+ self.drop_code = drop_code
+ self.message = message
+
+
+class LogicalChannelError(Exception):
+ """Raised when there is a logical channel error."""
+ def __init__(self, channel_id, drop_code, message=''):
+ super(LogicalChannelError, self).__init__(
+ 'channel_id=%d, code=%d, message=%r' % (
+ channel_id, drop_code, message))
+ self.channel_id = channel_id
+ self.drop_code = drop_code
+ self.message = message
+
+
+def _encode_channel_id(channel_id):
+ if channel_id < 0:
+ raise ValueError('Channel id %d must not be negative' % channel_id)
+
+ if channel_id < 2 ** 7:
+ return chr(channel_id)
+ if channel_id < 2 ** 14:
+ return struct.pack('!H', 0x8000 + channel_id)
+ if channel_id < 2 ** 21:
+ first = chr(0xc0 + (channel_id >> 16))
+ return first + struct.pack('!H', channel_id & 0xffff)
+ if channel_id < 2 ** 29:
+ return struct.pack('!L', 0xe0000000 + channel_id)
+
+ raise ValueError('Channel id %d is too large' % channel_id)
+
+
+def _encode_number(number):
+ return create_length_header(number, False)
+
+
+def _create_add_channel_response(channel_id, encoded_handshake,
+ encoding=0, rejected=False):
+ if encoding != 0 and encoding != 1:
+ raise ValueError('Invalid encoding %d' % encoding)
+
+ first_byte = ((_MUX_OPCODE_ADD_CHANNEL_RESPONSE << 5) |
+ (rejected << 4) | encoding)
+ block = (chr(first_byte) +
+ _encode_channel_id(channel_id) +
+ _encode_number(len(encoded_handshake)) +
+ encoded_handshake)
+ return block
+
+
+def _create_drop_channel(channel_id, code=None, message=''):
+ if len(message) > 0 and code is None:
+ raise ValueError('Code must be specified if message is specified')
+
+ first_byte = _MUX_OPCODE_DROP_CHANNEL << 5
+ block = chr(first_byte) + _encode_channel_id(channel_id)
+ if code is None:
+ block += _encode_number(0) # Reason size
+ else:
+ reason = struct.pack('!H', code) + message
+ reason_size = _encode_number(len(reason))
+ block += reason_size + reason
+
+ return block
+
+
+def _create_flow_control(channel_id, replenished_quota):
+ first_byte = _MUX_OPCODE_FLOW_CONTROL << 5
+ block = (chr(first_byte) +
+ _encode_channel_id(channel_id) +
+ _encode_number(replenished_quota))
+ return block
+
+
+def _create_new_channel_slot(slots, send_quota):
+ if slots < 0 or send_quota < 0:
+ raise ValueError('slots and send_quota must be non-negative.')
+ first_byte = _MUX_OPCODE_NEW_CHANNEL_SLOT << 5
+ block = (chr(first_byte) +
+ _encode_number(slots) +
+ _encode_number(send_quota))
+ return block
+
+
+def _create_fallback_new_channel_slot():
+ first_byte = (_MUX_OPCODE_NEW_CHANNEL_SLOT << 5) | 1 # Set the F flag
+ block = (chr(first_byte) + _encode_number(0) + _encode_number(0))
+ return block
+
+
+def _parse_request_text(request_text):
+ request_line, header_lines = request_text.split('\r\n', 1)
+
+ words = request_line.split(' ')
+ if len(words) != 3:
+ raise ValueError('Bad Request-Line syntax %r' % request_line)
+ [command, path, version] = words
+ if version != 'HTTP/1.1':
+ raise ValueError('Bad request version %r' % version)
+
+ # email.parser.Parser() parses RFC 2822 (RFC 822) style headers.
+ # RFC 6455 refers RFC 2616 for handshake parsing, and RFC 2616 refers
+ # RFC 822.
+ headers = email.parser.Parser().parsestr(header_lines)
+ return command, path, version, headers
+
+
+class _ControlBlock(object):
+ """A structure that holds parsing result of multiplexing control block.
+ Control block specific attributes will be added by _MuxFramePayloadParser.
+ (e.g. encoded_handshake will be added for AddChannelRequest and
+ AddChannelResponse)
+ """
+
+ def __init__(self, opcode):
+ self.opcode = opcode
+
+
+class _MuxFramePayloadParser(object):
+ """A class that parses multiplexed frame payload."""
+
+ def __init__(self, payload):
+ self._data = payload
+ self._read_position = 0
+ self._logger = util.get_class_logger(self)
+
+ def read_channel_id(self):
+ """Reads channel id.
+
+ Raises:
+ ValueError: when the payload doesn't contain
+ valid channel id.
+ """
+
+ remaining_length = len(self._data) - self._read_position
+ pos = self._read_position
+ if remaining_length == 0:
+ raise ValueError('Invalid channel id format')
+
+ channel_id = ord(self._data[pos])
+ channel_id_length = 1
+ if channel_id & 0xe0 == 0xe0:
+ if remaining_length < 4:
+ raise ValueError('Invalid channel id format')
+ channel_id = struct.unpack('!L',
+ self._data[pos:pos+4])[0] & 0x1fffffff
+ channel_id_length = 4
+ elif channel_id & 0xc0 == 0xc0:
+ if remaining_length < 3:
+ raise ValueError('Invalid channel id format')
+ channel_id = (((channel_id & 0x1f) << 16) +
+ struct.unpack('!H', self._data[pos+1:pos+3])[0])
+ channel_id_length = 3
+ elif channel_id & 0x80 == 0x80:
+ if remaining_length < 2:
+ raise ValueError('Invalid channel id format')
+ channel_id = struct.unpack('!H',
+ self._data[pos:pos+2])[0] & 0x3fff
+ channel_id_length = 2
+ self._read_position += channel_id_length
+
+ return channel_id
+
+ def read_inner_frame(self):
+ """Reads an inner frame.
+
+ Raises:
+ PhysicalConnectionError: when the inner frame is invalid.
+ """
+
+ if len(self._data) == self._read_position:
+ raise PhysicalConnectionError(
+ _DROP_CODE_ENCAPSULATED_FRAME_IS_TRUNCATED)
+
+ bits = ord(self._data[self._read_position])
+ self._read_position += 1
+ fin = (bits & 0x80) == 0x80
+ rsv1 = (bits & 0x40) == 0x40
+ rsv2 = (bits & 0x20) == 0x20
+ rsv3 = (bits & 0x10) == 0x10
+ opcode = bits & 0xf
+ payload = self.remaining_data()
+ # Consume rest of the message which is payload data of the original
+ # frame.
+ self._read_position = len(self._data)
+ return fin, rsv1, rsv2, rsv3, opcode, payload
+
+ def _read_number(self):
+ if self._read_position + 1 > len(self._data):
+ raise ValueError(
+ 'Cannot read the first byte of number field')
+
+ number = ord(self._data[self._read_position])
+ if number & 0x80 == 0x80:
+ raise ValueError(
+ 'The most significant bit of the first byte of number should '
+ 'be unset')
+ self._read_position += 1
+ pos = self._read_position
+ if number == 127:
+ if pos + 8 > len(self._data):
+ raise ValueError('Invalid number field')
+ self._read_position += 8
+ number = struct.unpack('!Q', self._data[pos:pos+8])[0]
+ if number > 0x7FFFFFFFFFFFFFFF:
+ raise ValueError('Encoded number(%d) >= 2^63' % number)
+ if number <= 0xFFFF:
+ raise ValueError(
+ '%d should not be encoded by 9 bytes encoding' % number)
+ return number
+ if number == 126:
+ if pos + 2 > len(self._data):
+ raise ValueError('Invalid number field')
+ self._read_position += 2
+ number = struct.unpack('!H', self._data[pos:pos+2])[0]
+ if number <= 125:
+ raise ValueError(
+ '%d should not be encoded by 3 bytes encoding' % number)
+ return number
+
+ def _read_size_and_contents(self):
+ """Reads data that consists of followings:
+ - the size of the contents encoded the same way as payload length
+ of the WebSocket Protocol with 1 bit padding at the head.
+ - the contents.
+ """
+
+ try:
+ size = self._read_number()
+ except ValueError, e:
+ raise PhysicalConnectionError(_DROP_CODE_INVALID_MUX_CONTROL_BLOCK,
+ str(e))
+ pos = self._read_position
+ if pos + size > len(self._data):
+ raise PhysicalConnectionError(
+ _DROP_CODE_INVALID_MUX_CONTROL_BLOCK,
+ 'Cannot read %d bytes data' % size)
+
+ self._read_position += size
+ return self._data[pos:pos+size]
+
+ def _read_add_channel_request(self, first_byte, control_block):
+ reserved = (first_byte >> 2) & 0x7
+ if reserved != 0:
+ raise PhysicalConnectionError(
+ _DROP_CODE_INVALID_MUX_CONTROL_BLOCK,
+ 'Reserved bits must be unset')
+
+ # Invalid encoding will be handled by MuxHandler.
+ encoding = first_byte & 0x3
+ try:
+ control_block.channel_id = self.read_channel_id()
+ except ValueError, e:
+ raise PhysicalConnectionError(_DROP_CODE_INVALID_MUX_CONTROL_BLOCK)
+ control_block.encoding = encoding
+ encoded_handshake = self._read_size_and_contents()
+ control_block.encoded_handshake = encoded_handshake
+ return control_block
+
+ def _read_add_channel_response(self, first_byte, control_block):
+ reserved = (first_byte >> 2) & 0x3
+ if reserved != 0:
+ raise PhysicalConnectionError(
+ _DROP_CODE_INVALID_MUX_CONTROL_BLOCK,
+ 'Reserved bits must be unset')
+
+ control_block.accepted = (first_byte >> 4) & 1
+ control_block.encoding = first_byte & 0x3
+ try:
+ control_block.channel_id = self.read_channel_id()
+ except ValueError, e:
+ raise PhysicalConnectionError(_DROP_CODE_INVALID_MUX_CONTROL_BLOCK)
+ control_block.encoded_handshake = self._read_size_and_contents()
+ return control_block
+
+ def _read_flow_control(self, first_byte, control_block):
+ reserved = first_byte & 0x1f
+ if reserved != 0:
+ raise PhysicalConnectionError(
+ _DROP_CODE_INVALID_MUX_CONTROL_BLOCK,
+ 'Reserved bits must be unset')
+
+ try:
+ control_block.channel_id = self.read_channel_id()
+ control_block.send_quota = self._read_number()
+ except ValueError, e:
+ raise PhysicalConnectionError(_DROP_CODE_INVALID_MUX_CONTROL_BLOCK,
+ str(e))
+
+ return control_block
+
+ def _read_drop_channel(self, first_byte, control_block):
+ reserved = first_byte & 0x1f
+ if reserved != 0:
+ raise PhysicalConnectionError(
+ _DROP_CODE_INVALID_MUX_CONTROL_BLOCK,
+ 'Reserved bits must be unset')
+
+ try:
+ control_block.channel_id = self.read_channel_id()
+ except ValueError, e:
+ raise PhysicalConnectionError(_DROP_CODE_INVALID_MUX_CONTROL_BLOCK)
+ reason = self._read_size_and_contents()
+ if len(reason) == 0:
+ control_block.drop_code = None
+ control_block.drop_message = ''
+ elif len(reason) >= 2:
+ control_block.drop_code = struct.unpack('!H', reason[:2])[0]
+ control_block.drop_message = reason[2:]
+ else:
+ raise PhysicalConnectionError(
+ _DROP_CODE_INVALID_MUX_CONTROL_BLOCK,
+ 'Received DropChannel that conains only 1-byte reason')
+ return control_block
+
+ def _read_new_channel_slot(self, first_byte, control_block):
+ reserved = first_byte & 0x1e
+ if reserved != 0:
+ raise PhysicalConnectionError(
+ _DROP_CODE_INVALID_MUX_CONTROL_BLOCK,
+ 'Reserved bits must be unset')
+ control_block.fallback = first_byte & 1
+ try:
+ control_block.slots = self._read_number()
+ control_block.send_quota = self._read_number()
+ except ValueError, e:
+ raise PhysicalConnectionError(_DROP_CODE_INVALID_MUX_CONTROL_BLOCK,
+ str(e))
+ return control_block
+
+ def read_control_blocks(self):
+ """Reads control block(s).
+
+ Raises:
+ PhysicalConnectionError: when the payload contains invalid control
+ block(s).
+ StopIteration: when no control blocks left.
+ """
+
+ while self._read_position < len(self._data):
+ first_byte = ord(self._data[self._read_position])
+ self._read_position += 1
+ opcode = (first_byte >> 5) & 0x7
+ control_block = _ControlBlock(opcode=opcode)
+ if opcode == _MUX_OPCODE_ADD_CHANNEL_REQUEST:
+ yield self._read_add_channel_request(first_byte, control_block)
+ elif opcode == _MUX_OPCODE_ADD_CHANNEL_RESPONSE:
+ yield self._read_add_channel_response(
+ first_byte, control_block)
+ elif opcode == _MUX_OPCODE_FLOW_CONTROL:
+ yield self._read_flow_control(first_byte, control_block)
+ elif opcode == _MUX_OPCODE_DROP_CHANNEL:
+ yield self._read_drop_channel(first_byte, control_block)
+ elif opcode == _MUX_OPCODE_NEW_CHANNEL_SLOT:
+ yield self._read_new_channel_slot(first_byte, control_block)
+ else:
+ raise PhysicalConnectionError(
+ _DROP_CODE_UNKNOWN_MUX_OPCODE,
+ 'Invalid opcode %d' % opcode)
+
+ assert self._read_position == len(self._data)
+ raise StopIteration
+
+ def remaining_data(self):
+ """Returns remaining data."""
+
+ return self._data[self._read_position:]
+
+
+class _LogicalRequest(object):
+ """Mimics mod_python request."""
+
+ def __init__(self, channel_id, command, path, protocol, headers,
+ connection):
+ """Constructs an instance.
+
+ Args:
+ channel_id: the channel id of the logical channel.
+ command: HTTP request command.
+ path: HTTP request path.
+ headers: HTTP headers.
+ connection: _LogicalConnection instance.
+ """
+
+ self.channel_id = channel_id
+ self.method = command
+ self.uri = path
+ self.protocol = protocol
+ self.headers_in = headers
+ self.connection = connection
+ self.server_terminated = False
+ self.client_terminated = False
+
+ def is_https(self):
+ """Mimics request.is_https(). Returns False because this method is
+ used only by old protocols (hixie and hybi00).
+ """
+
+ return False
+
+
+class _LogicalConnection(object):
+ """Mimics mod_python mp_conn."""
+
+ # For details, see the comment of set_read_state().
+ STATE_ACTIVE = 1
+ STATE_GRACEFULLY_CLOSED = 2
+ STATE_TERMINATED = 3
+
+ def __init__(self, mux_handler, channel_id):
+ """Constructs an instance.
+
+ Args:
+ mux_handler: _MuxHandler instance.
+ channel_id: channel id of this connection.
+ """
+
+ self._mux_handler = mux_handler
+ self._channel_id = channel_id
+ self._incoming_data = ''
+
+ # - Protects _waiting_write_completion
+ # - Signals the thread waiting for completion of write by mux handler
+ self._write_condition = threading.Condition()
+ self._waiting_write_completion = False
+
+ self._read_condition = threading.Condition()
+ self._read_state = self.STATE_ACTIVE
+
+ def get_local_addr(self):
+ """Getter to mimic mp_conn.local_addr."""
+
+ return self._mux_handler.physical_connection.get_local_addr()
+ local_addr = property(get_local_addr)
+
+ def get_remote_addr(self):
+ """Getter to mimic mp_conn.remote_addr."""
+
+ return self._mux_handler.physical_connection.get_remote_addr()
+ remote_addr = property(get_remote_addr)
+
+ def get_memorized_lines(self):
+ """Gets memorized lines. Not supported."""
+
+ raise MuxUnexpectedException('_LogicalConnection does not support '
+ 'get_memorized_lines')
+
+ def write(self, data):
+ """Writes data. mux_handler sends data asynchronously. The caller will
+ be suspended until write done.
+
+ Args:
+ data: data to be written.
+
+ Raises:
+ MuxUnexpectedException: when called before finishing the previous
+ write.
+ """
+
+ try:
+ self._write_condition.acquire()
+ if self._waiting_write_completion:
+ raise MuxUnexpectedException(
+ 'Logical connection %d is already waiting the completion '
+ 'of write' % self._channel_id)
+
+ self._waiting_write_completion = True
+ self._mux_handler.send_data(self._channel_id, data)
+ self._write_condition.wait()
+ # TODO(tyoshino): Raise an exception if woke up by on_writer_done.
+ finally:
+ self._write_condition.release()
+
+ def write_control_data(self, data):
+ """Writes data via the control channel. Don't wait finishing write
+ because this method can be called by mux dispatcher.
+
+ Args:
+ data: data to be written.
+ """
+
+ self._mux_handler.send_control_data(data)
+
+ def on_write_data_done(self):
+ """Called when sending data is completed."""
+
+ try:
+ self._write_condition.acquire()
+ if not self._waiting_write_completion:
+ raise MuxUnexpectedException(
+ 'Invalid call of on_write_data_done for logical '
+ 'connection %d' % self._channel_id)
+ self._waiting_write_completion = False
+ self._write_condition.notify()
+ finally:
+ self._write_condition.release()
+
+ def on_writer_done(self):
+ """Called by the mux handler when the writer thread has finished."""
+
+ try:
+ self._write_condition.acquire()
+ self._waiting_write_completion = False
+ self._write_condition.notify()
+ finally:
+ self._write_condition.release()
+
+
+ def append_frame_data(self, frame_data):
+ """Appends incoming frame data. Called when mux_handler dispatches
+ frame data to the corresponding application.
+
+ Args:
+ frame_data: incoming frame data.
+ """
+
+ self._read_condition.acquire()
+ self._incoming_data += frame_data
+ self._read_condition.notify()
+ self._read_condition.release()
+
+ def read(self, length):
+ """Reads data. Blocks until enough data has arrived via physical
+ connection.
+
+ Args:
+ length: length of data to be read.
+ Raises:
+ LogicalConnectionClosedException: when closing handshake for this
+ logical channel has been received.
+ ConnectionTerminatedException: when the physical connection has
+ closed, or an error is caused on the reader thread.
+ """
+
+ self._read_condition.acquire()
+ while (self._read_state == self.STATE_ACTIVE and
+ len(self._incoming_data) < length):
+ self._read_condition.wait()
+
+ try:
+ if self._read_state == self.STATE_GRACEFULLY_CLOSED:
+ raise LogicalConnectionClosedException(
+ 'Logical channel %d has closed.' % self._channel_id)
+ elif self._read_state == self.STATE_TERMINATED:
+ raise ConnectionTerminatedException(
+ 'Receiving %d byte failed. Logical channel (%d) closed' %
+ (length, self._channel_id))
+
+ value = self._incoming_data[:length]
+ self._incoming_data = self._incoming_data[length:]
+ finally:
+ self._read_condition.release()
+
+ return value
+
+ def set_read_state(self, new_state):
+ """Sets the state of this connection. Called when an event for this
+ connection has occurred.
+
+ Args:
+ new_state: state to be set. new_state must be one of followings:
+ - STATE_GRACEFULLY_CLOSED: when closing handshake for this
+ connection has been received.
+ - STATE_TERMINATED: when the physical connection has closed or
+ DropChannel of this connection has received.
+ """
+
+ self._read_condition.acquire()
+ self._read_state = new_state
+ self._read_condition.notify()
+ self._read_condition.release()
+
+
+class _InnerMessage(object):
+ """Holds the result of _InnerMessageBuilder.build().
+ """
+
+ def __init__(self, opcode, payload):
+ self.opcode = opcode
+ self.payload = payload
+
+
+class _InnerMessageBuilder(object):
+ """A class that holds the context of inner message fragmentation and
+ builds a message from fragmented inner frame(s).
+ """
+
+ def __init__(self):
+ self._control_opcode = None
+ self._pending_control_fragments = []
+ self._message_opcode = None
+ self._pending_message_fragments = []
+ self._frame_handler = self._handle_first
+
+ def _handle_first(self, frame):
+ if frame.opcode == common.OPCODE_CONTINUATION:
+ raise InvalidFrameException('Sending invalid continuation opcode')
+
+ if common.is_control_opcode(frame.opcode):
+ return self._process_first_fragmented_control(frame)
+ else:
+ return self._process_first_fragmented_message(frame)
+
+ def _process_first_fragmented_control(self, frame):
+ self._control_opcode = frame.opcode
+ self._pending_control_fragments.append(frame.payload)
+ if not frame.fin:
+ self._frame_handler = self._handle_fragmented_control
+ return None
+ return self._reassemble_fragmented_control()
+
+ def _process_first_fragmented_message(self, frame):
+ self._message_opcode = frame.opcode
+ self._pending_message_fragments.append(frame.payload)
+ if not frame.fin:
+ self._frame_handler = self._handle_fragmented_message
+ return None
+ return self._reassemble_fragmented_message()
+
+ def _handle_fragmented_control(self, frame):
+ if frame.opcode != common.OPCODE_CONTINUATION:
+ raise InvalidFrameException(
+ 'Sending invalid opcode %d while sending fragmented control '
+ 'message' % frame.opcode)
+ self._pending_control_fragments.append(frame.payload)
+ if not frame.fin:
+ return None
+ return self._reassemble_fragmented_control()
+
+ def _reassemble_fragmented_control(self):
+ opcode = self._control_opcode
+ payload = ''.join(self._pending_control_fragments)
+ self._control_opcode = None
+ self._pending_control_fragments = []
+ if self._message_opcode is not None:
+ self._frame_handler = self._handle_fragmented_message
+ else:
+ self._frame_handler = self._handle_first
+ return _InnerMessage(opcode, payload)
+
+ def _handle_fragmented_message(self, frame):
+ # Sender can interleave a control message while sending fragmented
+ # messages.
+ if common.is_control_opcode(frame.opcode):
+ if self._control_opcode is not None:
+ raise MuxUnexpectedException(
+ 'Should not reach here(Bug in builder)')
+ return self._process_first_fragmented_control(frame)
+
+ if frame.opcode != common.OPCODE_CONTINUATION:
+ raise InvalidFrameException(
+ 'Sending invalid opcode %d while sending fragmented message' %
+ frame.opcode)
+ self._pending_message_fragments.append(frame.payload)
+ if not frame.fin:
+ return None
+ return self._reassemble_fragmented_message()
+
+ def _reassemble_fragmented_message(self):
+ opcode = self._message_opcode
+ payload = ''.join(self._pending_message_fragments)
+ self._message_opcode = None
+ self._pending_message_fragments = []
+ self._frame_handler = self._handle_first
+ return _InnerMessage(opcode, payload)
+
+ def build(self, frame):
+ """Build an inner message. Returns an _InnerMessage instance when
+ the given frame is the last fragmented frame. Returns None otherwise.
+
+ Args:
+ frame: an inner frame.
+ Raises:
+ InvalidFrameException: when received invalid opcode. (e.g.
+ receiving non continuation data opcode but the fin flag of
+ the previous inner frame was not set.)
+ """
+
+ return self._frame_handler(frame)
+
+
+class _LogicalStream(Stream):
+ """Mimics the Stream class. This class interprets multiplexed WebSocket
+ frames.
+ """
+
+ def __init__(self, request, stream_options, send_quota, receive_quota):
+ """Constructs an instance.
+
+ Args:
+ request: _LogicalRequest instance.
+ stream_options: StreamOptions instance.
+ send_quota: Initial send quota.
+ receive_quota: Initial receive quota.
+ """
+
+ # Physical stream is responsible for masking.
+ stream_options.unmask_receive = False
+ Stream.__init__(self, request, stream_options)
+
+ self._send_closed = False
+ self._send_quota = send_quota
+ # - Protects _send_closed and _send_quota
+ # - Signals the thread waiting for send quota replenished
+ self._send_condition = threading.Condition()
+
+ # The opcode of the first frame in messages.
+ self._message_opcode = common.OPCODE_TEXT
+ # True when the last message was fragmented.
+ self._last_message_was_fragmented = False
+
+ self._receive_quota = receive_quota
+ self._write_inner_frame_semaphore = threading.Semaphore()
+
+ self._inner_message_builder = _InnerMessageBuilder()
+
+ def _create_inner_frame(self, opcode, payload, end=True):
+ frame = Frame(fin=end, opcode=opcode, payload=payload)
+ for frame_filter in self._options.outgoing_frame_filters:
+ frame_filter.filter(frame)
+
+ if len(payload) != len(frame.payload):
+ raise MuxUnexpectedException(
+ 'Mux extension must not be used after extensions which change '
+ ' frame boundary')
+
+ first_byte = ((frame.fin << 7) | (frame.rsv1 << 6) |
+ (frame.rsv2 << 5) | (frame.rsv3 << 4) | frame.opcode)
+ return chr(first_byte) + frame.payload
+
+ def _write_inner_frame(self, opcode, payload, end=True):
+ payload_length = len(payload)
+ write_position = 0
+
+ try:
+ # An inner frame will be fragmented if there is no enough send
+ # quota. This semaphore ensures that fragmented inner frames are
+ # sent in order on the logical channel.
+ # Note that frames that come from other logical channels or
+ # multiplexing control blocks can be inserted between fragmented
+ # inner frames on the physical channel.
+ self._write_inner_frame_semaphore.acquire()
+
+ # Consume an octet quota when this is the first fragmented frame.
+ if opcode != common.OPCODE_CONTINUATION:
+ try:
+ self._send_condition.acquire()
+ while (not self._send_closed) and self._send_quota == 0:
+ self._send_condition.wait()
+
+ if self._send_closed:
+ raise BadOperationException(
+ 'Logical connection %d is closed' %
+ self._request.channel_id)
+
+ self._send_quota -= 1
+ finally:
+ self._send_condition.release()
+
+ while write_position < payload_length:
+ try:
+ self._send_condition.acquire()
+ while (not self._send_closed) and self._send_quota == 0:
+ self._logger.debug(
+ 'No quota. Waiting FlowControl message for %d.' %
+ self._request.channel_id)
+ self._send_condition.wait()
+
+ if self._send_closed:
+ raise BadOperationException(
+ 'Logical connection %d is closed' %
+ self.request._channel_id)
+
+ remaining = payload_length - write_position
+ write_length = min(self._send_quota, remaining)
+ inner_frame_end = (
+ end and
+ (write_position + write_length == payload_length))
+
+ inner_frame = self._create_inner_frame(
+ opcode,
+ payload[write_position:write_position+write_length],
+ inner_frame_end)
+ self._send_quota -= write_length
+ self._logger.debug('Consumed quota=%d, remaining=%d' %
+ (write_length, self._send_quota))
+ finally:
+ self._send_condition.release()
+
+ # Writing data will block the worker so we need to release
+ # _send_condition before writing.
+ self._logger.debug('Sending inner frame: %r' % inner_frame)
+ self._request.connection.write(inner_frame)
+ write_position += write_length
+
+ opcode = common.OPCODE_CONTINUATION
+
+ except ValueError, e:
+ raise BadOperationException(e)
+ finally:
+ self._write_inner_frame_semaphore.release()
+
+ def replenish_send_quota(self, send_quota):
+ """Replenish send quota."""
+
+ try:
+ self._send_condition.acquire()
+ if self._send_quota + send_quota > 0x7FFFFFFFFFFFFFFF:
+ self._send_quota = 0
+ raise LogicalChannelError(
+ self._request.channel_id, _DROP_CODE_SEND_QUOTA_OVERFLOW)
+ self._send_quota += send_quota
+ self._logger.debug('Replenished send quota for channel id %d: %d' %
+ (self._request.channel_id, self._send_quota))
+ finally:
+ self._send_condition.notify()
+ self._send_condition.release()
+
+ def consume_receive_quota(self, amount):
+ """Consumes receive quota. Returns False on failure."""
+
+ if self._receive_quota < amount:
+ self._logger.debug('Violate quota on channel id %d: %d < %d' %
+ (self._request.channel_id,
+ self._receive_quota, amount))
+ return False
+ self._receive_quota -= amount
+ return True
+
+ def send_message(self, message, end=True, binary=False):
+ """Override Stream.send_message."""
+
+ if self._request.server_terminated:
+ raise BadOperationException(
+ 'Requested send_message after sending out a closing handshake')
+
+ if binary and isinstance(message, unicode):
+ raise BadOperationException(
+ 'Message for binary frame must be instance of str')
+
+ if binary:
+ opcode = common.OPCODE_BINARY
+ else:
+ opcode = common.OPCODE_TEXT
+ message = message.encode('utf-8')
+
+ for message_filter in self._options.outgoing_message_filters:
+ message = message_filter.filter(message, end, binary)
+
+ if self._last_message_was_fragmented:
+ if opcode != self._message_opcode:
+ raise BadOperationException('Message types are different in '
+ 'frames for the same message')
+ opcode = common.OPCODE_CONTINUATION
+ else:
+ self._message_opcode = opcode
+
+ self._write_inner_frame(opcode, message, end)
+ self._last_message_was_fragmented = not end
+
+ def _receive_frame(self):
+ """Overrides Stream._receive_frame.
+
+ In addition to call Stream._receive_frame, this method adds the amount
+ of payload to receiving quota and sends FlowControl to the client.
+ We need to do it here because Stream.receive_message() handles
+ control frames internally.
+ """
+
+ opcode, payload, fin, rsv1, rsv2, rsv3 = Stream._receive_frame(self)
+ amount = len(payload)
+ # Replenish extra one octet when receiving the first fragmented frame.
+ if opcode != common.OPCODE_CONTINUATION:
+ amount += 1
+ self._receive_quota += amount
+ frame_data = _create_flow_control(self._request.channel_id,
+ amount)
+ self._logger.debug('Sending flow control for %d, replenished=%d' %
+ (self._request.channel_id, amount))
+ self._request.connection.write_control_data(frame_data)
+ return opcode, payload, fin, rsv1, rsv2, rsv3
+
+ def _get_message_from_frame(self, frame):
+ """Overrides Stream._get_message_from_frame.
+ """
+
+ try:
+ inner_message = self._inner_message_builder.build(frame)
+ except InvalidFrameException:
+ raise LogicalChannelError(
+ self._request.channel_id, _DROP_CODE_BAD_FRAGMENTATION)
+
+ if inner_message is None:
+ return None
+ self._original_opcode = inner_message.opcode
+ return inner_message.payload
+
+ def receive_message(self):
+ """Overrides Stream.receive_message."""
+
+ # Just call Stream.receive_message(), but catch
+ # LogicalConnectionClosedException, which is raised when the logical
+ # connection has closed gracefully.
+ try:
+ return Stream.receive_message(self)
+ except LogicalConnectionClosedException, e:
+ self._logger.debug('%s', e)
+ return None
+
+ def _send_closing_handshake(self, code, reason):
+ """Overrides Stream._send_closing_handshake."""
+
+ body = create_closing_handshake_body(code, reason)
+ self._logger.debug('Sending closing handshake for %d: (%r, %r)' %
+ (self._request.channel_id, code, reason))
+ self._write_inner_frame(common.OPCODE_CLOSE, body, end=True)
+
+ self._request.server_terminated = True
+
+ def send_ping(self, body=''):
+ """Overrides Stream.send_ping"""
+
+ self._logger.debug('Sending ping on logical channel %d: %r' %
+ (self._request.channel_id, body))
+ self._write_inner_frame(common.OPCODE_PING, body, end=True)
+
+ self._ping_queue.append(body)
+
+ def _send_pong(self, body):
+ """Overrides Stream._send_pong"""
+
+ self._logger.debug('Sending pong on logical channel %d: %r' %
+ (self._request.channel_id, body))
+ self._write_inner_frame(common.OPCODE_PONG, body, end=True)
+
+ def close_connection(self, code=common.STATUS_NORMAL_CLOSURE, reason=''):
+ """Overrides Stream.close_connection."""
+
+ # TODO(bashi): Implement
+ self._logger.debug('Closing logical connection %d' %
+ self._request.channel_id)
+ self._request.server_terminated = True
+
+ def stop_sending(self):
+ """Stops accepting new send operation (_write_inner_frame)."""
+
+ self._send_condition.acquire()
+ self._send_closed = True
+ self._send_condition.notify()
+ self._send_condition.release()
+
+
+class _OutgoingData(object):
+ """A structure that holds data to be sent via physical connection and
+ origin of the data.
+ """
+
+ def __init__(self, channel_id, data):
+ self.channel_id = channel_id
+ self.data = data
+
+
+class _PhysicalConnectionWriter(threading.Thread):
+ """A thread that is responsible for writing data to physical connection.
+
+ TODO(bashi): Make sure there is no thread-safety problem when the reader
+ thread reads data from the same socket at a time.
+ """
+
+ def __init__(self, mux_handler):
+ """Constructs an instance.
+
+ Args:
+ mux_handler: _MuxHandler instance.
+ """
+
+ threading.Thread.__init__(self)
+ self._logger = util.get_class_logger(self)
+ self._mux_handler = mux_handler
+ self.setDaemon(True)
+
+ # When set, make this thread stop accepting new data, flush pending
+ # data and exit.
+ self._stop_requested = False
+ # The close code of the physical connection.
+ self._close_code = common.STATUS_NORMAL_CLOSURE
+ # Deque for passing write data. It's protected by _deque_condition
+ # until _stop_requested is set.
+ self._deque = collections.deque()
+ # - Protects _deque, _stop_requested and _close_code
+ # - Signals threads waiting for them to be available
+ self._deque_condition = threading.Condition()
+
+ def put_outgoing_data(self, data):
+ """Puts outgoing data.
+
+ Args:
+ data: _OutgoingData instance.
+
+ Raises:
+ BadOperationException: when the thread has been requested to
+ terminate.
+ """
+
+ try:
+ self._deque_condition.acquire()
+ if self._stop_requested:
+ raise BadOperationException('Cannot write data anymore')
+
+ self._deque.append(data)
+ self._deque_condition.notify()
+ finally:
+ self._deque_condition.release()
+
+ def _write_data(self, outgoing_data):
+ message = (_encode_channel_id(outgoing_data.channel_id) +
+ outgoing_data.data)
+ try:
+ self._mux_handler.physical_stream.send_message(
+ message=message, end=True, binary=True)
+ except Exception, e:
+ util.prepend_message_to_exception(
+ 'Failed to send message to %r: ' %
+ (self._mux_handler.physical_connection.remote_addr,), e)
+ raise
+
+ # TODO(bashi): It would be better to block the thread that sends
+ # control data as well.
+ if outgoing_data.channel_id != _CONTROL_CHANNEL_ID:
+ self._mux_handler.notify_write_data_done(outgoing_data.channel_id)
+
+ def run(self):
+ try:
+ self._deque_condition.acquire()
+ while not self._stop_requested:
+ if len(self._deque) == 0:
+ self._deque_condition.wait()
+ continue
+
+ outgoing_data = self._deque.popleft()
+
+ self._deque_condition.release()
+ self._write_data(outgoing_data)
+ self._deque_condition.acquire()
+
+ # Flush deque.
+ #
+ # At this point, self._deque_condition is always acquired.
+ try:
+ while len(self._deque) > 0:
+ outgoing_data = self._deque.popleft()
+ self._write_data(outgoing_data)
+ finally:
+ self._deque_condition.release()
+
+ # Close physical connection.
+ try:
+ # Don't wait the response here. The response will be read
+ # by the reader thread.
+ self._mux_handler.physical_stream.close_connection(
+ self._close_code, wait_response=False)
+ except Exception, e:
+ util.prepend_message_to_exception(
+ 'Failed to close the physical connection: %r' % e)
+ raise
+ finally:
+ self._mux_handler.notify_writer_done()
+
+ def stop(self, close_code=common.STATUS_NORMAL_CLOSURE):
+ """Stops the writer thread."""
+
+ self._deque_condition.acquire()
+ self._stop_requested = True
+ self._close_code = close_code
+ self._deque_condition.notify()
+ self._deque_condition.release()
+
+
+class _PhysicalConnectionReader(threading.Thread):
+ """A thread that is responsible for reading data from physical connection.
+ """
+
+ def __init__(self, mux_handler):
+ """Constructs an instance.
+
+ Args:
+ mux_handler: _MuxHandler instance.
+ """
+
+ threading.Thread.__init__(self)
+ self._logger = util.get_class_logger(self)
+ self._mux_handler = mux_handler
+ self.setDaemon(True)
+
+ def run(self):
+ while True:
+ try:
+ physical_stream = self._mux_handler.physical_stream
+ message = physical_stream.receive_message()
+ if message is None:
+ break
+ # Below happens only when a data message is received.
+ opcode = physical_stream.get_last_received_opcode()
+ if opcode != common.OPCODE_BINARY:
+ self._mux_handler.fail_physical_connection(
+ _DROP_CODE_INVALID_ENCAPSULATING_MESSAGE,
+ 'Received a text message on physical connection')
+ break
+
+ except ConnectionTerminatedException, e:
+ self._logger.debug('%s', e)
+ break
+
+ try:
+ self._mux_handler.dispatch_message(message)
+ except PhysicalConnectionError, e:
+ self._mux_handler.fail_physical_connection(
+ e.drop_code, e.message)
+ break
+ except LogicalChannelError, e:
+ self._mux_handler.fail_logical_channel(
+ e.channel_id, e.drop_code, e.message)
+ except Exception, e:
+ self._logger.debug(traceback.format_exc())
+ break
+
+ self._mux_handler.notify_reader_done()
+
+
+class _Worker(threading.Thread):
+ """A thread that is responsible for running the corresponding application
+ handler.
+ """
+
+ def __init__(self, mux_handler, request):
+ """Constructs an instance.
+
+ Args:
+ mux_handler: _MuxHandler instance.
+ request: _LogicalRequest instance.
+ """
+
+ threading.Thread.__init__(self)
+ self._logger = util.get_class_logger(self)
+ self._mux_handler = mux_handler
+ self._request = request
+ self.setDaemon(True)
+
+ def run(self):
+ self._logger.debug('Logical channel worker started. (id=%d)' %
+ self._request.channel_id)
+ try:
+ # Non-critical exceptions will be handled by dispatcher.
+ self._mux_handler.dispatcher.transfer_data(self._request)
+ except LogicalChannelError, e:
+ self._mux_handler.fail_logical_channel(
+ e.channel_id, e.drop_code, e.message)
+ finally:
+ self._mux_handler.notify_worker_done(self._request.channel_id)
+
+
+class _MuxHandshaker(hybi.Handshaker):
+ """Opening handshake processor for multiplexing."""
+
+ _DUMMY_WEBSOCKET_KEY = 'dGhlIHNhbXBsZSBub25jZQ=='
+
+ def __init__(self, request, dispatcher, send_quota, receive_quota):
+ """Constructs an instance.
+ Args:
+ request: _LogicalRequest instance.
+ dispatcher: Dispatcher instance (dispatch.Dispatcher).
+ send_quota: Initial send quota.
+ receive_quota: Initial receive quota.
+ """
+
+ hybi.Handshaker.__init__(self, request, dispatcher)
+ self._send_quota = send_quota
+ self._receive_quota = receive_quota
+
+ # Append headers which should not be included in handshake field of
+ # AddChannelRequest.
+ # TODO(bashi): Make sure whether we should raise exception when
+ # these headers are included already.
+ request.headers_in[common.UPGRADE_HEADER] = (
+ common.WEBSOCKET_UPGRADE_TYPE)
+ request.headers_in[common.SEC_WEBSOCKET_VERSION_HEADER] = (
+ str(common.VERSION_HYBI_LATEST))
+ request.headers_in[common.SEC_WEBSOCKET_KEY_HEADER] = (
+ self._DUMMY_WEBSOCKET_KEY)
+
+ def _create_stream(self, stream_options):
+ """Override hybi.Handshaker._create_stream."""
+
+ self._logger.debug('Creating logical stream for %d' %
+ self._request.channel_id)
+ return _LogicalStream(
+ self._request, stream_options, self._send_quota,
+ self._receive_quota)
+
+ def _create_handshake_response(self, accept):
+ """Override hybi._create_handshake_response."""
+
+ response = []
+
+ response.append('HTTP/1.1 101 Switching Protocols\r\n')
+
+ # Upgrade and Sec-WebSocket-Accept should be excluded.
+ response.append('%s: %s\r\n' % (
+ common.CONNECTION_HEADER, common.UPGRADE_CONNECTION_TYPE))
+ if self._request.ws_protocol is not None:
+ response.append('%s: %s\r\n' % (
+ common.SEC_WEBSOCKET_PROTOCOL_HEADER,
+ self._request.ws_protocol))
+ if (self._request.ws_extensions is not None and
+ len(self._request.ws_extensions) != 0):
+ response.append('%s: %s\r\n' % (
+ common.SEC_WEBSOCKET_EXTENSIONS_HEADER,
+ common.format_extensions(self._request.ws_extensions)))
+ response.append('\r\n')
+
+ return ''.join(response)
+
+ def _send_handshake(self, accept):
+ """Override hybi.Handshaker._send_handshake."""
+
+ # Don't send handshake response for the default channel
+ if self._request.channel_id == _DEFAULT_CHANNEL_ID:
+ return
+
+ handshake_response = self._create_handshake_response(accept)
+ frame_data = _create_add_channel_response(
+ self._request.channel_id,
+ handshake_response)
+ self._logger.debug('Sending handshake response for %d: %r' %
+ (self._request.channel_id, frame_data))
+ self._request.connection.write_control_data(frame_data)
+
+
+class _LogicalChannelData(object):
+ """A structure that holds information about logical channel.
+ """
+
+ def __init__(self, request, worker):
+ self.request = request
+ self.worker = worker
+ self.drop_code = _DROP_CODE_NORMAL_CLOSURE
+ self.drop_message = ''
+
+
+class _HandshakeDeltaBase(object):
+ """A class that holds information for delta-encoded handshake."""
+
+ def __init__(self, headers):
+ self._headers = headers
+
+ def create_headers(self, delta=None):
+ """Creates request headers for an AddChannelRequest that has
+ delta-encoded handshake.
+
+ Args:
+ delta: headers should be overridden.
+ """
+
+ headers = copy.copy(self._headers)
+ if delta:
+ for key, value in delta.items():
+ # The spec requires that a header with an empty value is
+ # removed from the delta base.
+ if len(value) == 0 and headers.has_key(key):
+ del headers[key]
+ else:
+ headers[key] = value
+ return headers
+
+
+class _MuxHandler(object):
+ """Multiplexing handler. When a handler starts, it launches three
+ threads; the reader thread, the writer thread, and a worker thread.
+
+ The reader thread reads data from the physical stream, i.e., the
+ ws_stream object of the underlying websocket connection. The reader
+ thread interprets multiplexed frames and dispatches them to logical
+ channels. Methods of this class are mostly called by the reader thread.
+
+ The writer thread sends multiplexed frames which are created by
+ logical channels via the physical connection.
+
+ The worker thread launched at the starting point handles the
+ "Implicitly Opened Connection". If multiplexing handler receives
+ an AddChannelRequest and accepts it, the handler will launch a new worker
+ thread and dispatch the request to it.
+ """
+
+ def __init__(self, request, dispatcher):
+ """Constructs an instance.
+
+ Args:
+ request: mod_python request of the physical connection.
+ dispatcher: Dispatcher instance (dispatch.Dispatcher).
+ """
+
+ self.original_request = request
+ self.dispatcher = dispatcher
+ self.physical_connection = request.connection
+ self.physical_stream = request.ws_stream
+ self._logger = util.get_class_logger(self)
+ self._logical_channels = {}
+ self._logical_channels_condition = threading.Condition()
+ # Holds client's initial quota
+ self._channel_slots = collections.deque()
+ self._handshake_base = None
+ self._worker_done_notify_received = False
+ self._reader = None
+ self._writer = None
+
+ def start(self):
+ """Starts the handler.
+
+ Raises:
+ MuxUnexpectedException: when the handler already started, or when
+ opening handshake of the default channel fails.
+ """
+
+ if self._reader or self._writer:
+ raise MuxUnexpectedException('MuxHandler already started')
+
+ self._reader = _PhysicalConnectionReader(self)
+ self._writer = _PhysicalConnectionWriter(self)
+ self._reader.start()
+ self._writer.start()
+
+ # Create "Implicitly Opened Connection".
+ logical_connection = _LogicalConnection(self, _DEFAULT_CHANNEL_ID)
+ headers = copy.copy(self.original_request.headers_in)
+ # Add extensions for logical channel.
+ headers[common.SEC_WEBSOCKET_EXTENSIONS_HEADER] = (
+ common.format_extensions(
+ self.original_request.mux_processor.extensions()))
+ self._handshake_base = _HandshakeDeltaBase(headers)
+ logical_request = _LogicalRequest(
+ _DEFAULT_CHANNEL_ID,
+ self.original_request.method,
+ self.original_request.uri,
+ self.original_request.protocol,
+ self._handshake_base.create_headers(),
+ logical_connection)
+ # Client's send quota for the implicitly opened connection is zero,
+ # but we will send FlowControl later so set the initial quota to
+ # _INITIAL_QUOTA_FOR_CLIENT.
+ self._channel_slots.append(_INITIAL_QUOTA_FOR_CLIENT)
+ send_quota = self.original_request.mux_processor.quota()
+ if not self._do_handshake_for_logical_request(
+ logical_request, send_quota=send_quota):
+ raise MuxUnexpectedException(
+ 'Failed handshake on the default channel id')
+ self._add_logical_channel(logical_request)
+
+ # Send FlowControl for the implicitly opened connection.
+ frame_data = _create_flow_control(_DEFAULT_CHANNEL_ID,
+ _INITIAL_QUOTA_FOR_CLIENT)
+ logical_request.connection.write_control_data(frame_data)
+
+ def add_channel_slots(self, slots, send_quota):
+ """Adds channel slots.
+
+ Args:
+ slots: number of slots to be added.
+ send_quota: initial send quota for slots.
+ """
+
+ self._channel_slots.extend([send_quota] * slots)
+ # Send NewChannelSlot to client.
+ frame_data = _create_new_channel_slot(slots, send_quota)
+ self.send_control_data(frame_data)
+
+ def wait_until_done(self, timeout=None):
+ """Waits until all workers are done. Returns False when timeout has
+ occurred. Returns True on success.
+
+ Args:
+ timeout: timeout in sec.
+ """
+
+ self._logical_channels_condition.acquire()
+ try:
+ while len(self._logical_channels) > 0:
+ self._logger.debug('Waiting workers(%d)...' %
+ len(self._logical_channels))
+ self._worker_done_notify_received = False
+ self._logical_channels_condition.wait(timeout)
+ if not self._worker_done_notify_received:
+ self._logger.debug('Waiting worker(s) timed out')
+ return False
+ finally:
+ self._logical_channels_condition.release()
+
+ # Flush pending outgoing data
+ self._writer.stop()
+ self._writer.join()
+
+ return True
+
+ def notify_write_data_done(self, channel_id):
+ """Called by the writer thread when a write operation has done.
+
+ Args:
+ channel_id: objective channel id.
+ """
+
+ try:
+ self._logical_channels_condition.acquire()
+ if channel_id in self._logical_channels:
+ channel_data = self._logical_channels[channel_id]
+ channel_data.request.connection.on_write_data_done()
+ else:
+ self._logger.debug('Seems that logical channel for %d has gone'
+ % channel_id)
+ finally:
+ self._logical_channels_condition.release()
+
+ def send_control_data(self, data):
+ """Sends data via the control channel.
+
+ Args:
+ data: data to be sent.
+ """
+
+ self._writer.put_outgoing_data(_OutgoingData(
+ channel_id=_CONTROL_CHANNEL_ID, data=data))
+
+ def send_data(self, channel_id, data):
+ """Sends data via given logical channel. This method is called by
+ worker threads.
+
+ Args:
+ channel_id: objective channel id.
+ data: data to be sent.
+ """
+
+ self._writer.put_outgoing_data(_OutgoingData(
+ channel_id=channel_id, data=data))
+
+ def _send_drop_channel(self, channel_id, code=None, message=''):
+ frame_data = _create_drop_channel(channel_id, code, message)
+ self._logger.debug(
+ 'Sending drop channel for channel id %d' % channel_id)
+ self.send_control_data(frame_data)
+
+ def _send_error_add_channel_response(self, channel_id, status=None):
+ if status is None:
+ status = common.HTTP_STATUS_BAD_REQUEST
+
+ if status in _HTTP_BAD_RESPONSE_MESSAGES:
+ message = _HTTP_BAD_RESPONSE_MESSAGES[status]
+ else:
+ self._logger.debug('Response message for %d is not found' % status)
+ message = '???'
+
+ response = 'HTTP/1.1 %d %s\r\n\r\n' % (status, message)
+ frame_data = _create_add_channel_response(channel_id,
+ encoded_handshake=response,
+ encoding=0, rejected=True)
+ self.send_control_data(frame_data)
+
+ def _create_logical_request(self, block):
+ if block.channel_id == _CONTROL_CHANNEL_ID:
+ # TODO(bashi): Raise PhysicalConnectionError with code 2006
+ # instead of MuxUnexpectedException.
+ raise MuxUnexpectedException(
+ 'Received the control channel id (0) as objective channel '
+ 'id for AddChannel')
+
+ if block.encoding > _HANDSHAKE_ENCODING_DELTA:
+ raise PhysicalConnectionError(
+ _DROP_CODE_UNKNOWN_REQUEST_ENCODING)
+
+ method, path, version, headers = _parse_request_text(
+ block.encoded_handshake)
+ if block.encoding == _HANDSHAKE_ENCODING_DELTA:
+ headers = self._handshake_base.create_headers(headers)
+
+ connection = _LogicalConnection(self, block.channel_id)
+ request = _LogicalRequest(block.channel_id, method, path, version,
+ headers, connection)
+ return request
+
+ def _do_handshake_for_logical_request(self, request, send_quota=0):
+ try:
+ receive_quota = self._channel_slots.popleft()
+ except IndexError:
+ raise LogicalChannelError(
+ request.channel_id, _DROP_CODE_NEW_CHANNEL_SLOT_VIOLATION)
+
+ handshaker = _MuxHandshaker(request, self.dispatcher,
+ send_quota, receive_quota)
+ try:
+ handshaker.do_handshake()
+ except handshake.VersionException, e:
+ self._logger.info('%s', e)
+ self._send_error_add_channel_response(
+ request.channel_id, status=common.HTTP_STATUS_BAD_REQUEST)
+ return False
+ except handshake.HandshakeException, e:
+ # TODO(bashi): Should we _Fail the Logical Channel_ with 3001
+ # instead?
+ self._logger.info('%s', e)
+ self._send_error_add_channel_response(request.channel_id,
+ status=e.status)
+ return False
+ except handshake.AbortedByUserException, e:
+ self._logger.info('%s', e)
+ self._send_error_add_channel_response(request.channel_id)
+ return False
+
+ return True
+
+ def _add_logical_channel(self, logical_request):
+ try:
+ self._logical_channels_condition.acquire()
+ if logical_request.channel_id in self._logical_channels:
+ self._logger.debug('Channel id %d already exists' %
+ logical_request.channel_id)
+ raise PhysicalConnectionError(
+ _DROP_CODE_CHANNEL_ALREADY_EXISTS,
+ 'Channel id %d already exists' %
+ logical_request.channel_id)
+ worker = _Worker(self, logical_request)
+ channel_data = _LogicalChannelData(logical_request, worker)
+ self._logical_channels[logical_request.channel_id] = channel_data
+ worker.start()
+ finally:
+ self._logical_channels_condition.release()
+
+ def _process_add_channel_request(self, block):
+ try:
+ logical_request = self._create_logical_request(block)
+ except ValueError, e:
+ self._logger.debug('Failed to create logical request: %r' % e)
+ self._send_error_add_channel_response(
+ block.channel_id, status=common.HTTP_STATUS_BAD_REQUEST)
+ return
+ if self._do_handshake_for_logical_request(logical_request):
+ if block.encoding == _HANDSHAKE_ENCODING_IDENTITY:
+ # Update handshake base.
+ # TODO(bashi): Make sure this is the right place to update
+ # handshake base.
+ self._handshake_base = _HandshakeDeltaBase(
+ logical_request.headers_in)
+ self._add_logical_channel(logical_request)
+ else:
+ self._send_error_add_channel_response(
+ block.channel_id, status=common.HTTP_STATUS_BAD_REQUEST)
+
+ def _process_flow_control(self, block):
+ try:
+ self._logical_channels_condition.acquire()
+ if not block.channel_id in self._logical_channels:
+ return
+ channel_data = self._logical_channels[block.channel_id]
+ channel_data.request.ws_stream.replenish_send_quota(
+ block.send_quota)
+ finally:
+ self._logical_channels_condition.release()
+
+ def _process_drop_channel(self, block):
+ self._logger.debug(
+ 'DropChannel received for %d: code=%r, reason=%r' %
+ (block.channel_id, block.drop_code, block.drop_message))
+ try:
+ self._logical_channels_condition.acquire()
+ if not block.channel_id in self._logical_channels:
+ return
+ channel_data = self._logical_channels[block.channel_id]
+ channel_data.drop_code = _DROP_CODE_ACKNOWLEDGED
+
+ # Close the logical channel
+ channel_data.request.connection.set_read_state(
+ _LogicalConnection.STATE_TERMINATED)
+ channel_data.request.ws_stream.stop_sending()
+ finally:
+ self._logical_channels_condition.release()
+
+ def _process_control_blocks(self, parser):
+ for control_block in parser.read_control_blocks():
+ opcode = control_block.opcode
+ self._logger.debug('control block received, opcode: %d' % opcode)
+ if opcode == _MUX_OPCODE_ADD_CHANNEL_REQUEST:
+ self._process_add_channel_request(control_block)
+ elif opcode == _MUX_OPCODE_ADD_CHANNEL_RESPONSE:
+ raise PhysicalConnectionError(
+ _DROP_CODE_INVALID_MUX_CONTROL_BLOCK,
+ 'Received AddChannelResponse')
+ elif opcode == _MUX_OPCODE_FLOW_CONTROL:
+ self._process_flow_control(control_block)
+ elif opcode == _MUX_OPCODE_DROP_CHANNEL:
+ self._process_drop_channel(control_block)
+ elif opcode == _MUX_OPCODE_NEW_CHANNEL_SLOT:
+ raise PhysicalConnectionError(
+ _DROP_CODE_INVALID_MUX_CONTROL_BLOCK,
+ 'Received NewChannelSlot')
+ else:
+ raise MuxUnexpectedException(
+ 'Unexpected opcode %r' % opcode)
+
+ def _process_logical_frame(self, channel_id, parser):
+ self._logger.debug('Received a frame. channel id=%d' % channel_id)
+ try:
+ self._logical_channels_condition.acquire()
+ if not channel_id in self._logical_channels:
+ # We must ignore the message for an inactive channel.
+ return
+ channel_data = self._logical_channels[channel_id]
+ fin, rsv1, rsv2, rsv3, opcode, payload = parser.read_inner_frame()
+ consuming_byte = len(payload)
+ if opcode != common.OPCODE_CONTINUATION:
+ consuming_byte += 1
+ if not channel_data.request.ws_stream.consume_receive_quota(
+ consuming_byte):
+ # The client violates quota. Close logical channel.
+ raise LogicalChannelError(
+ channel_id, _DROP_CODE_SEND_QUOTA_VIOLATION)
+ header = create_header(opcode, len(payload), fin, rsv1, rsv2, rsv3,
+ mask=False)
+ frame_data = header + payload
+ channel_data.request.connection.append_frame_data(frame_data)
+ finally:
+ self._logical_channels_condition.release()
+
+ def dispatch_message(self, message):
+ """Dispatches message. The reader thread calls this method.
+
+ Args:
+ message: a message that contains encapsulated frame.
+ Raises:
+ PhysicalConnectionError: if the message contains physical
+ connection level errors.
+ LogicalChannelError: if the message contains logical channel
+ level errors.
+ """
+
+ parser = _MuxFramePayloadParser(message)
+ try:
+ channel_id = parser.read_channel_id()
+ except ValueError, e:
+ raise PhysicalConnectionError(_DROP_CODE_CHANNEL_ID_TRUNCATED)
+ if channel_id == _CONTROL_CHANNEL_ID:
+ self._process_control_blocks(parser)
+ else:
+ self._process_logical_frame(channel_id, parser)
+
+ def notify_worker_done(self, channel_id):
+ """Called when a worker has finished.
+
+ Args:
+ channel_id: channel id corresponded with the worker.
+ """
+
+ self._logger.debug('Worker for channel id %d terminated' % channel_id)
+ try:
+ self._logical_channels_condition.acquire()
+ if not channel_id in self._logical_channels:
+ raise MuxUnexpectedException(
+ 'Channel id %d not found' % channel_id)
+ channel_data = self._logical_channels.pop(channel_id)
+ finally:
+ self._worker_done_notify_received = True
+ self._logical_channels_condition.notify()
+ self._logical_channels_condition.release()
+
+ if not channel_data.request.server_terminated:
+ self._send_drop_channel(
+ channel_id, code=channel_data.drop_code,
+ message=channel_data.drop_message)
+
+ def notify_reader_done(self):
+ """This method is called by the reader thread when the reader has
+ finished.
+ """
+
+ self._logger.debug(
+ 'Termiating all logical connections waiting for incoming data '
+ '...')
+ self._logical_channels_condition.acquire()
+ for channel_data in self._logical_channels.values():
+ try:
+ channel_data.request.connection.set_read_state(
+ _LogicalConnection.STATE_TERMINATED)
+ except Exception:
+ self._logger.debug(traceback.format_exc())
+ self._logical_channels_condition.release()
+
+ def notify_writer_done(self):
+ """This method is called by the writer thread when the writer has
+ finished.
+ """
+
+ self._logger.debug(
+ 'Termiating all logical connections waiting for write '
+ 'completion ...')
+ self._logical_channels_condition.acquire()
+ for channel_data in self._logical_channels.values():
+ try:
+ channel_data.request.connection.on_writer_done()
+ except Exception:
+ self._logger.debug(traceback.format_exc())
+ self._logical_channels_condition.release()
+
+ def fail_physical_connection(self, code, message):
+ """Fail the physical connection.
+
+ Args:
+ code: drop reason code.
+ message: drop message.
+ """
+
+ self._logger.debug('Failing the physical connection...')
+ self._send_drop_channel(_CONTROL_CHANNEL_ID, code, message)
+ self._writer.stop(common.STATUS_INTERNAL_ENDPOINT_ERROR)
+
+ def fail_logical_channel(self, channel_id, code, message):
+ """Fail a logical channel.
+
+ Args:
+ channel_id: channel id.
+ code: drop reason code.
+ message: drop message.
+ """
+
+ self._logger.debug('Failing logical channel %d...' % channel_id)
+ try:
+ self._logical_channels_condition.acquire()
+ if channel_id in self._logical_channels:
+ channel_data = self._logical_channels[channel_id]
+ # Close the logical channel. notify_worker_done() will be
+ # called later and it will send DropChannel.
+ channel_data.drop_code = code
+ channel_data.drop_message = message
+
+ channel_data.request.connection.set_read_state(
+ _LogicalConnection.STATE_TERMINATED)
+ channel_data.request.ws_stream.stop_sending()
+ else:
+ self._send_drop_channel(channel_id, code, message)
+ finally:
+ self._logical_channels_condition.release()
+
+
+def use_mux(request):
+ return hasattr(request, 'mux_processor') and (
+ request.mux_processor.is_active())
+
+
+def start(request, dispatcher):
+ mux_handler = _MuxHandler(request, dispatcher)
+ mux_handler.start()
+
+ mux_handler.add_channel_slots(_INITIAL_NUMBER_OF_CHANNEL_SLOTS,
+ _INITIAL_QUOTA_FOR_CLIENT)
+
+ mux_handler.wait_until_done()
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/standalone.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/standalone.py
new file mode 100755
index 00000000000..24c299eaf3d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/standalone.py
@@ -0,0 +1,1193 @@
+#!/usr/bin/env python
+#
+# Copyright 2012, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+"""Standalone WebSocket server.
+
+Use this file to launch pywebsocket without Apache HTTP Server.
+
+
+BASIC USAGE
+===========
+
+Go to the src directory and run
+
+ $ python mod_pywebsocket/standalone.py [-p <ws_port>]
+ [-w <websock_handlers>]
+ [-d <document_root>]
+
+<ws_port> is the port number to use for ws:// connection.
+
+<document_root> is the path to the root directory of HTML files.
+
+<websock_handlers> is the path to the root directory of WebSocket handlers.
+If not specified, <document_root> will be used. See __init__.py (or
+run $ pydoc mod_pywebsocket) for how to write WebSocket handlers.
+
+For more detail and other options, run
+
+ $ python mod_pywebsocket/standalone.py --help
+
+or see _build_option_parser method below.
+
+For trouble shooting, adding "--log_level debug" might help you.
+
+
+TRY DEMO
+========
+
+Go to the src directory and run standalone.py with -d option to set the
+document root to the directory containing example HTMLs and handlers like this:
+
+ $ cd src
+ $ PYTHONPATH=. python mod_pywebsocket/standalone.py -d example
+
+to launch pywebsocket with the sample handler and html on port 80. Open
+http://localhost/console.html, click the connect button, type something into
+the text box next to the send button and click the send button. If everything
+is working, you'll see the message you typed echoed by the server.
+
+
+USING TLS
+=========
+
+To run the standalone server with TLS support, run it with -t, -k, and -c
+options. When TLS is enabled, the standalone server accepts only TLS connection.
+
+Note that when ssl module is used and the key/cert location is incorrect,
+TLS connection silently fails while pyOpenSSL fails on startup.
+
+Example:
+
+ $ PYTHONPATH=. python mod_pywebsocket/standalone.py \
+ -d example \
+ -p 10443 \
+ -t \
+ -c ../test/cert/cert.pem \
+ -k ../test/cert/key.pem \
+
+Note that when passing a relative path to -c and -k option, it will be resolved
+using the document root directory as the base.
+
+
+USING CLIENT AUTHENTICATION
+===========================
+
+To run the standalone server with TLS client authentication support, run it with
+--tls-client-auth and --tls-client-ca options in addition to ones required for
+TLS support.
+
+Example:
+
+ $ PYTHONPATH=. python mod_pywebsocket/standalone.py -d example -p 10443 -t \
+ -c ../test/cert/cert.pem -k ../test/cert/key.pem \
+ --tls-client-auth \
+ --tls-client-ca=../test/cert/cacert.pem
+
+Note that when passing a relative path to --tls-client-ca option, it will be
+resolved using the document root directory as the base.
+
+
+CONFIGURATION FILE
+==================
+
+You can also write a configuration file and use it by specifying the path to
+the configuration file by --config option. Please write a configuration file
+following the documentation of the Python ConfigParser library. Name of each
+entry must be the long version argument name. E.g. to set log level to debug,
+add the following line:
+
+log_level=debug
+
+For options which doesn't take value, please add some fake value. E.g. for
+--tls option, add the following line:
+
+tls=True
+
+Note that tls will be enabled even if you write tls=False as the value part is
+fake.
+
+When both a command line argument and a configuration file entry are set for
+the same configuration item, the command line value will override one in the
+configuration file.
+
+
+THREADING
+=========
+
+This server is derived from SocketServer.ThreadingMixIn. Hence a thread is
+used for each request.
+
+
+SECURITY WARNING
+================
+
+This uses CGIHTTPServer and CGIHTTPServer is not secure.
+It may execute arbitrary Python code or external programs. It should not be
+used outside a firewall.
+"""
+
+import BaseHTTPServer
+import CGIHTTPServer
+import SimpleHTTPServer
+import SocketServer
+import ConfigParser
+import base64
+import httplib
+import logging
+import logging.handlers
+import optparse
+import os
+import re
+import select
+import socket
+import sys
+import threading
+import time
+
+from mod_pywebsocket import common
+from mod_pywebsocket import dispatch
+from mod_pywebsocket import handshake
+from mod_pywebsocket import http_header_util
+from mod_pywebsocket import memorizingfile
+from mod_pywebsocket import util
+from mod_pywebsocket.xhr_benchmark_handler import XHRBenchmarkHandler
+
+
+_DEFAULT_LOG_MAX_BYTES = 1024 * 256
+_DEFAULT_LOG_BACKUP_COUNT = 5
+
+_DEFAULT_REQUEST_QUEUE_SIZE = 128
+
+# 1024 is practically large enough to contain WebSocket handshake lines.
+_MAX_MEMORIZED_LINES = 1024
+
+# Constants for the --tls_module flag.
+_TLS_BY_STANDARD_MODULE = 'ssl'
+_TLS_BY_PYOPENSSL = 'pyopenssl'
+
+
+class _StandaloneConnection(object):
+ """Mimic mod_python mp_conn."""
+
+ def __init__(self, request_handler):
+ """Construct an instance.
+
+ Args:
+ request_handler: A WebSocketRequestHandler instance.
+ """
+
+ self._request_handler = request_handler
+
+ def get_local_addr(self):
+ """Getter to mimic mp_conn.local_addr."""
+
+ return (self._request_handler.server.server_name,
+ self._request_handler.server.server_port)
+ local_addr = property(get_local_addr)
+
+ def get_remote_addr(self):
+ """Getter to mimic mp_conn.remote_addr.
+
+ Setting the property in __init__ won't work because the request
+ handler is not initialized yet there."""
+
+ return self._request_handler.client_address
+ remote_addr = property(get_remote_addr)
+
+ def write(self, data):
+ """Mimic mp_conn.write()."""
+
+ return self._request_handler.wfile.write(data)
+
+ def read(self, length):
+ """Mimic mp_conn.read()."""
+
+ return self._request_handler.rfile.read(length)
+
+ def get_memorized_lines(self):
+ """Get memorized lines."""
+
+ return self._request_handler.rfile.get_memorized_lines()
+
+
+class _StandaloneRequest(object):
+ """Mimic mod_python request."""
+
+ def __init__(self, request_handler, use_tls):
+ """Construct an instance.
+
+ Args:
+ request_handler: A WebSocketRequestHandler instance.
+ """
+
+ self._logger = util.get_class_logger(self)
+
+ self._request_handler = request_handler
+ self.connection = _StandaloneConnection(request_handler)
+ self._use_tls = use_tls
+ self.headers_in = request_handler.headers
+
+ def get_uri(self):
+ """Getter to mimic request.uri.
+
+ This method returns the raw data at the Request-URI part of the
+ Request-Line, while the uri method on the request object of mod_python
+ returns the path portion after parsing the raw data. This behavior is
+ kept for compatibility.
+ """
+
+ return self._request_handler.path
+ uri = property(get_uri)
+
+ def get_unparsed_uri(self):
+ """Getter to mimic request.unparsed_uri."""
+
+ return self._request_handler.path
+ unparsed_uri = property(get_unparsed_uri)
+
+ def get_method(self):
+ """Getter to mimic request.method."""
+
+ return self._request_handler.command
+ method = property(get_method)
+
+ def get_protocol(self):
+ """Getter to mimic request.protocol."""
+
+ return self._request_handler.request_version
+ protocol = property(get_protocol)
+
+ def is_https(self):
+ """Mimic request.is_https()."""
+
+ return self._use_tls
+
+
+def _import_ssl():
+ global ssl
+ try:
+ import ssl
+ return True
+ except ImportError:
+ return False
+
+
+def _import_pyopenssl():
+ global OpenSSL
+ try:
+ import OpenSSL.SSL
+ return True
+ except ImportError:
+ return False
+
+
+class _StandaloneSSLConnection(object):
+ """A wrapper class for OpenSSL.SSL.Connection to
+ - provide makefile method which is not supported by the class
+ - tweak shutdown method since OpenSSL.SSL.Connection.shutdown doesn't
+ accept the "how" argument.
+ - convert SysCallError exceptions that its recv method may raise into a
+ return value of '', meaning EOF. We cannot overwrite the recv method on
+ self._connection since it's immutable.
+ """
+
+ _OVERRIDDEN_ATTRIBUTES = ['_connection', 'makefile', 'shutdown', 'recv']
+
+ def __init__(self, connection):
+ self._connection = connection
+
+ def __getattribute__(self, name):
+ if name in _StandaloneSSLConnection._OVERRIDDEN_ATTRIBUTES:
+ return object.__getattribute__(self, name)
+ return self._connection.__getattribute__(name)
+
+ def __setattr__(self, name, value):
+ if name in _StandaloneSSLConnection._OVERRIDDEN_ATTRIBUTES:
+ return object.__setattr__(self, name, value)
+ return self._connection.__setattr__(name, value)
+
+ def makefile(self, mode='r', bufsize=-1):
+ return socket._fileobject(self, mode, bufsize)
+
+ def shutdown(self, unused_how):
+ self._connection.shutdown()
+
+ def recv(self, bufsize, flags=0):
+ if flags != 0:
+ raise ValueError('Non-zero flags not allowed')
+
+ try:
+ return self._connection.recv(bufsize)
+ except OpenSSL.SSL.SysCallError, (err, message):
+ if err == -1:
+ # Suppress "unexpected EOF" exception. See the OpenSSL document
+ # for SSL_get_error.
+ return ''
+ raise
+
+
+def _alias_handlers(dispatcher, websock_handlers_map_file):
+ """Set aliases specified in websock_handler_map_file in dispatcher.
+
+ Args:
+ dispatcher: dispatch.Dispatcher instance
+ websock_handler_map_file: alias map file
+ """
+
+ fp = open(websock_handlers_map_file)
+ try:
+ for line in fp:
+ if line[0] == '#' or line.isspace():
+ continue
+ m = re.match('(\S+)\s+(\S+)', line)
+ if not m:
+ logging.warning('Wrong format in map file:' + line)
+ continue
+ try:
+ dispatcher.add_resource_path_alias(
+ m.group(1), m.group(2))
+ except dispatch.DispatchException, e:
+ logging.error(str(e))
+ finally:
+ fp.close()
+
+
+class WebSocketServer(SocketServer.ThreadingMixIn, BaseHTTPServer.HTTPServer):
+ """HTTPServer specialized for WebSocket."""
+
+ # Overrides SocketServer.ThreadingMixIn.daemon_threads
+ daemon_threads = True
+ # Overrides BaseHTTPServer.HTTPServer.allow_reuse_address
+ allow_reuse_address = True
+
+ def __init__(self, options):
+ """Override SocketServer.TCPServer.__init__ to set SSL enabled
+ socket object to self.socket before server_bind and server_activate,
+ if necessary.
+ """
+
+ # Share a Dispatcher among request handlers to save time for
+ # instantiation. Dispatcher can be shared because it is thread-safe.
+ options.dispatcher = dispatch.Dispatcher(
+ options.websock_handlers,
+ options.scan_dir,
+ options.allow_handlers_outside_root_dir)
+ if options.websock_handlers_map_file:
+ _alias_handlers(options.dispatcher,
+ options.websock_handlers_map_file)
+ warnings = options.dispatcher.source_warnings()
+ if warnings:
+ for warning in warnings:
+ logging.warning('Warning in source loading: %s' % warning)
+
+ self._logger = util.get_class_logger(self)
+
+ self.request_queue_size = options.request_queue_size
+ self.__ws_is_shut_down = threading.Event()
+ self.__ws_serving = False
+
+ SocketServer.BaseServer.__init__(
+ self, (options.server_host, options.port), WebSocketRequestHandler)
+
+ # Expose the options object to allow handler objects access it. We name
+ # it with websocket_ prefix to avoid conflict.
+ self.websocket_server_options = options
+
+ self._create_sockets()
+ self.server_bind()
+ self.server_activate()
+
+ def _create_sockets(self):
+ self.server_name, self.server_port = self.server_address
+ self._sockets = []
+ if not self.server_name:
+ # On platforms that doesn't support IPv6, the first bind fails.
+ # On platforms that supports IPv6
+ # - If it binds both IPv4 and IPv6 on call with AF_INET6, the
+ # first bind succeeds and the second fails (we'll see 'Address
+ # already in use' error).
+ # - If it binds only IPv6 on call with AF_INET6, both call are
+ # expected to succeed to listen both protocol.
+ addrinfo_array = [
+ (socket.AF_INET6, socket.SOCK_STREAM, '', '', ''),
+ (socket.AF_INET, socket.SOCK_STREAM, '', '', '')]
+ else:
+ addrinfo_array = socket.getaddrinfo(self.server_name,
+ self.server_port,
+ socket.AF_UNSPEC,
+ socket.SOCK_STREAM,
+ socket.IPPROTO_TCP)
+ for addrinfo in addrinfo_array:
+ self._logger.info('Create socket on: %r', addrinfo)
+ family, socktype, proto, canonname, sockaddr = addrinfo
+ try:
+ socket_ = socket.socket(family, socktype)
+ except Exception, e:
+ self._logger.info('Skip by failure: %r', e)
+ continue
+ server_options = self.websocket_server_options
+ if server_options.use_tls:
+ # For the case of _HAS_OPEN_SSL, we do wrapper setup after
+ # accept.
+ if server_options.tls_module == _TLS_BY_STANDARD_MODULE:
+ if server_options.tls_client_auth:
+ if server_options.tls_client_cert_optional:
+ client_cert_ = ssl.CERT_OPTIONAL
+ else:
+ client_cert_ = ssl.CERT_REQUIRED
+ else:
+ client_cert_ = ssl.CERT_NONE
+ socket_ = ssl.wrap_socket(socket_,
+ keyfile=server_options.private_key,
+ certfile=server_options.certificate,
+ ssl_version=ssl.PROTOCOL_SSLv23,
+ ca_certs=server_options.tls_client_ca,
+ cert_reqs=client_cert_,
+ do_handshake_on_connect=False)
+ self._sockets.append((socket_, addrinfo))
+
+ def server_bind(self):
+ """Override SocketServer.TCPServer.server_bind to enable multiple
+ sockets bind.
+ """
+
+ failed_sockets = []
+
+ for socketinfo in self._sockets:
+ socket_, addrinfo = socketinfo
+ self._logger.info('Bind on: %r', addrinfo)
+ if self.allow_reuse_address:
+ socket_.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ try:
+ socket_.bind(self.server_address)
+ except Exception, e:
+ self._logger.info('Skip by failure: %r', e)
+ socket_.close()
+ failed_sockets.append(socketinfo)
+ if self.server_address[1] == 0:
+ # The operating system assigns the actual port number for port
+ # number 0. This case, the second and later sockets should use
+ # the same port number. Also self.server_port is rewritten
+ # because it is exported, and will be used by external code.
+ self.server_address = (
+ self.server_name, socket_.getsockname()[1])
+ self.server_port = self.server_address[1]
+ self._logger.info('Port %r is assigned', self.server_port)
+
+ for socketinfo in failed_sockets:
+ self._sockets.remove(socketinfo)
+
+ def server_activate(self):
+ """Override SocketServer.TCPServer.server_activate to enable multiple
+ sockets listen.
+ """
+
+ failed_sockets = []
+
+ for socketinfo in self._sockets:
+ socket_, addrinfo = socketinfo
+ self._logger.info('Listen on: %r', addrinfo)
+ try:
+ socket_.listen(self.request_queue_size)
+ except Exception, e:
+ self._logger.info('Skip by failure: %r', e)
+ socket_.close()
+ failed_sockets.append(socketinfo)
+
+ for socketinfo in failed_sockets:
+ self._sockets.remove(socketinfo)
+
+ if len(self._sockets) == 0:
+ self._logger.critical(
+ 'No sockets activated. Use info log level to see the reason.')
+
+ def server_close(self):
+ """Override SocketServer.TCPServer.server_close to enable multiple
+ sockets close.
+ """
+
+ for socketinfo in self._sockets:
+ socket_, addrinfo = socketinfo
+ self._logger.info('Close on: %r', addrinfo)
+ socket_.close()
+
+ def fileno(self):
+ """Override SocketServer.TCPServer.fileno."""
+
+ self._logger.critical('Not supported: fileno')
+ return self._sockets[0][0].fileno()
+
+ def handle_error(self, request, client_address):
+ """Override SocketServer.handle_error."""
+
+ self._logger.error(
+ 'Exception in processing request from: %r\n%s',
+ client_address,
+ util.get_stack_trace())
+ # Note: client_address is a tuple.
+
+ def get_request(self):
+ """Override TCPServer.get_request to wrap OpenSSL.SSL.Connection
+ object with _StandaloneSSLConnection to provide makefile method. We
+ cannot substitute OpenSSL.SSL.Connection.makefile since it's readonly
+ attribute.
+ """
+
+ accepted_socket, client_address = self.socket.accept()
+
+ server_options = self.websocket_server_options
+ if server_options.use_tls:
+ if server_options.tls_module == _TLS_BY_STANDARD_MODULE:
+ try:
+ accepted_socket.do_handshake()
+ except ssl.SSLError, e:
+ self._logger.debug('%r', e)
+ raise
+
+ # Print cipher in use. Handshake is done on accept.
+ self._logger.debug('Cipher: %s', accepted_socket.cipher())
+ self._logger.debug('Client cert: %r',
+ accepted_socket.getpeercert())
+ elif server_options.tls_module == _TLS_BY_PYOPENSSL:
+ # We cannot print the cipher in use. pyOpenSSL doesn't provide
+ # any method to fetch that.
+
+ ctx = OpenSSL.SSL.Context(OpenSSL.SSL.SSLv23_METHOD)
+ ctx.use_privatekey_file(server_options.private_key)
+ ctx.use_certificate_file(server_options.certificate)
+
+ def default_callback(conn, cert, errnum, errdepth, ok):
+ return ok == 1
+
+ # See the OpenSSL document for SSL_CTX_set_verify.
+ if server_options.tls_client_auth:
+ verify_mode = OpenSSL.SSL.VERIFY_PEER
+ if not server_options.tls_client_cert_optional:
+ verify_mode |= OpenSSL.SSL.VERIFY_FAIL_IF_NO_PEER_CERT
+ ctx.set_verify(verify_mode, default_callback)
+ ctx.load_verify_locations(server_options.tls_client_ca,
+ None)
+ else:
+ ctx.set_verify(OpenSSL.SSL.VERIFY_NONE, default_callback)
+
+ accepted_socket = OpenSSL.SSL.Connection(ctx, accepted_socket)
+ accepted_socket.set_accept_state()
+
+ # Convert SSL related error into socket.error so that
+ # SocketServer ignores them and keeps running.
+ #
+ # TODO(tyoshino): Convert all kinds of errors.
+ try:
+ accepted_socket.do_handshake()
+ except OpenSSL.SSL.Error, e:
+ # Set errno part to 1 (SSL_ERROR_SSL) like the ssl module
+ # does.
+ self._logger.debug('%r', e)
+ raise socket.error(1, '%r' % e)
+ cert = accepted_socket.get_peer_certificate()
+ if cert is not None:
+ self._logger.debug('Client cert subject: %r',
+ cert.get_subject().get_components())
+ accepted_socket = _StandaloneSSLConnection(accepted_socket)
+ else:
+ raise ValueError('No TLS support module is available')
+
+ return accepted_socket, client_address
+
+ def serve_forever(self, poll_interval=0.5):
+ """Override SocketServer.BaseServer.serve_forever."""
+
+ self.__ws_serving = True
+ self.__ws_is_shut_down.clear()
+ handle_request = self.handle_request
+ if hasattr(self, '_handle_request_noblock'):
+ handle_request = self._handle_request_noblock
+ else:
+ self._logger.warning('Fallback to blocking request handler')
+ try:
+ while self.__ws_serving:
+ r, w, e = select.select(
+ [socket_[0] for socket_ in self._sockets],
+ [], [], poll_interval)
+ for socket_ in r:
+ self.socket = socket_
+ handle_request()
+ self.socket = None
+ finally:
+ self.__ws_is_shut_down.set()
+
+ def shutdown(self):
+ """Override SocketServer.BaseServer.shutdown."""
+
+ self.__ws_serving = False
+ self.__ws_is_shut_down.wait()
+
+
+class WebSocketRequestHandler(CGIHTTPServer.CGIHTTPRequestHandler):
+ """CGIHTTPRequestHandler specialized for WebSocket."""
+
+ # Use httplib.HTTPMessage instead of mimetools.Message.
+ MessageClass = httplib.HTTPMessage
+
+ protocol_version = "HTTP/1.1"
+
+ def setup(self):
+ """Override SocketServer.StreamRequestHandler.setup to wrap rfile
+ with MemorizingFile.
+
+ This method will be called by BaseRequestHandler's constructor
+ before calling BaseHTTPRequestHandler.handle.
+ BaseHTTPRequestHandler.handle will call
+ BaseHTTPRequestHandler.handle_one_request and it will call
+ WebSocketRequestHandler.parse_request.
+ """
+
+ # Call superclass's setup to prepare rfile, wfile, etc. See setup
+ # definition on the root class SocketServer.StreamRequestHandler to
+ # understand what this does.
+ CGIHTTPServer.CGIHTTPRequestHandler.setup(self)
+
+ self.rfile = memorizingfile.MemorizingFile(
+ self.rfile,
+ max_memorized_lines=_MAX_MEMORIZED_LINES)
+
+ def __init__(self, request, client_address, server):
+ self._logger = util.get_class_logger(self)
+
+ self._options = server.websocket_server_options
+
+ # Overrides CGIHTTPServerRequestHandler.cgi_directories.
+ self.cgi_directories = self._options.cgi_directories
+ # Replace CGIHTTPRequestHandler.is_executable method.
+ if self._options.is_executable_method is not None:
+ self.is_executable = self._options.is_executable_method
+
+ # This actually calls BaseRequestHandler.__init__.
+ CGIHTTPServer.CGIHTTPRequestHandler.__init__(
+ self, request, client_address, server)
+
+ def parse_request(self):
+ """Override BaseHTTPServer.BaseHTTPRequestHandler.parse_request.
+
+ Return True to continue processing for HTTP(S), False otherwise.
+
+ See BaseHTTPRequestHandler.handle_one_request method which calls
+ this method to understand how the return value will be handled.
+ """
+
+ # We hook parse_request method, but also call the original
+ # CGIHTTPRequestHandler.parse_request since when we return False,
+ # CGIHTTPRequestHandler.handle_one_request continues processing and
+ # it needs variables set by CGIHTTPRequestHandler.parse_request.
+ #
+ # Variables set by this method will be also used by WebSocket request
+ # handling (self.path, self.command, self.requestline, etc. See also
+ # how _StandaloneRequest's members are implemented using these
+ # attributes).
+ if not CGIHTTPServer.CGIHTTPRequestHandler.parse_request(self):
+ return False
+
+ if self.command == "CONNECT":
+ self.send_response(200, "Connected")
+ self.send_header("Connection", "keep-alive")
+ self.end_headers()
+ return False
+
+ if self._options.use_basic_auth:
+ auth = self.headers.getheader('Authorization')
+ if auth != self._options.basic_auth_credential:
+ self.send_response(401)
+ self.send_header('WWW-Authenticate',
+ 'Basic realm="Pywebsocket"')
+ self.end_headers()
+ self._logger.info('Request basic authentication')
+ return False
+
+ host, port, resource = http_header_util.parse_uri(self.path)
+
+ # Special paths for XMLHttpRequest benchmark
+ xhr_benchmark_helper_prefix = '/073be001e10950692ccbf3a2ad21c245'
+ if resource == (xhr_benchmark_helper_prefix + '_send'):
+ xhr_benchmark_handler = XHRBenchmarkHandler(
+ self.headers, self.rfile, self.wfile)
+ xhr_benchmark_handler.do_send()
+ return False
+ if resource == (xhr_benchmark_helper_prefix + '_receive'):
+ xhr_benchmark_handler = XHRBenchmarkHandler(
+ self.headers, self.rfile, self.wfile)
+ xhr_benchmark_handler.do_receive()
+ return False
+
+ if resource is None:
+ self._logger.info('Invalid URI: %r', self.path)
+ self._logger.info('Fallback to CGIHTTPRequestHandler')
+ return True
+ server_options = self.server.websocket_server_options
+ if host is not None:
+ validation_host = server_options.validation_host
+ if validation_host is not None and host != validation_host:
+ self._logger.info('Invalid host: %r (expected: %r)',
+ host,
+ validation_host)
+ self._logger.info('Fallback to CGIHTTPRequestHandler')
+ return True
+ if port is not None:
+ validation_port = server_options.validation_port
+ if validation_port is not None and port != validation_port:
+ self._logger.info('Invalid port: %r (expected: %r)',
+ port,
+ validation_port)
+ self._logger.info('Fallback to CGIHTTPRequestHandler')
+ return True
+ self.path = resource
+
+ request = _StandaloneRequest(self, self._options.use_tls)
+
+ try:
+ # Fallback to default http handler for request paths for which
+ # we don't have request handlers.
+ if not self._options.dispatcher.get_handler_suite(self.path):
+ self._logger.info('No handler for resource: %r',
+ self.path)
+ self._logger.info('Fallback to CGIHTTPRequestHandler')
+ return True
+ except dispatch.DispatchException, e:
+ self._logger.info('Dispatch failed for error: %s', e)
+ self.send_error(e.status)
+ return False
+
+ # If any Exceptions without except clause setup (including
+ # DispatchException) is raised below this point, it will be caught
+ # and logged by WebSocketServer.
+
+ try:
+ try:
+ handshake.do_handshake(
+ request,
+ self._options.dispatcher,
+ allowDraft75=self._options.allow_draft75,
+ strict=self._options.strict)
+ except handshake.VersionException, e:
+ self._logger.info('Handshake failed for version error: %s', e)
+ self.send_response(common.HTTP_STATUS_BAD_REQUEST)
+ self.send_header(common.SEC_WEBSOCKET_VERSION_HEADER,
+ e.supported_versions)
+ self.end_headers()
+ return False
+ except handshake.HandshakeException, e:
+ # Handshake for ws(s) failed.
+ self._logger.info('Handshake failed for error: %s', e)
+ self.send_error(e.status)
+ return False
+
+ request._dispatcher = self._options.dispatcher
+ self._options.dispatcher.transfer_data(request)
+ except handshake.AbortedByUserException, e:
+ self._logger.info('Aborted: %s', e)
+ return False
+
+ def log_request(self, code='-', size='-'):
+ """Override BaseHTTPServer.log_request."""
+
+ self._logger.info('"%s" %s %s',
+ self.requestline, str(code), str(size))
+
+ def log_error(self, *args):
+ """Override BaseHTTPServer.log_error."""
+
+ # Despite the name, this method is for warnings than for errors.
+ # For example, HTTP status code is logged by this method.
+ self._logger.warning('%s - %s',
+ self.address_string(),
+ args[0] % args[1:])
+
+ def is_cgi(self):
+ """Test whether self.path corresponds to a CGI script.
+
+ Add extra check that self.path doesn't contains ..
+ Also check if the file is a executable file or not.
+ If the file is not executable, it is handled as static file or dir
+ rather than a CGI script.
+ """
+
+ if CGIHTTPServer.CGIHTTPRequestHandler.is_cgi(self):
+ if '..' in self.path:
+ return False
+ # strip query parameter from request path
+ resource_name = self.path.split('?', 2)[0]
+ # convert resource_name into real path name in filesystem.
+ scriptfile = self.translate_path(resource_name)
+ if not os.path.isfile(scriptfile):
+ return False
+ if not self.is_executable(scriptfile):
+ return False
+ return True
+ return False
+
+
+def _get_logger_from_class(c):
+ return logging.getLogger('%s.%s' % (c.__module__, c.__name__))
+
+
+def _configure_logging(options):
+ logging.addLevelName(common.LOGLEVEL_FINE, 'FINE')
+
+ logger = logging.getLogger()
+ logger.setLevel(logging.getLevelName(options.log_level.upper()))
+ if options.log_file:
+ handler = logging.handlers.RotatingFileHandler(
+ options.log_file, 'a', options.log_max, options.log_count)
+ else:
+ handler = logging.StreamHandler()
+ formatter = logging.Formatter(
+ '[%(asctime)s] [%(levelname)s] %(name)s: %(message)s')
+ handler.setFormatter(formatter)
+ logger.addHandler(handler)
+
+ deflate_log_level_name = logging.getLevelName(
+ options.deflate_log_level.upper())
+ _get_logger_from_class(util._Deflater).setLevel(
+ deflate_log_level_name)
+ _get_logger_from_class(util._Inflater).setLevel(
+ deflate_log_level_name)
+
+
+def _build_option_parser():
+ parser = optparse.OptionParser()
+
+ parser.add_option('--config', dest='config_file', type='string',
+ default=None,
+ help=('Path to configuration file. See the file comment '
+ 'at the top of this file for the configuration '
+ 'file format'))
+ parser.add_option('-H', '--server-host', '--server_host',
+ dest='server_host',
+ default='',
+ help='server hostname to listen to')
+ parser.add_option('-V', '--validation-host', '--validation_host',
+ dest='validation_host',
+ default=None,
+ help='server hostname to validate in absolute path.')
+ parser.add_option('-p', '--port', dest='port', type='int',
+ default=common.DEFAULT_WEB_SOCKET_PORT,
+ help='port to listen to')
+ parser.add_option('-P', '--validation-port', '--validation_port',
+ dest='validation_port', type='int',
+ default=None,
+ help='server port to validate in absolute path.')
+ parser.add_option('-w', '--websock-handlers', '--websock_handlers',
+ dest='websock_handlers',
+ default='.',
+ help=('The root directory of WebSocket handler files. '
+ 'If the path is relative, --document-root is used '
+ 'as the base.'))
+ parser.add_option('-m', '--websock-handlers-map-file',
+ '--websock_handlers_map_file',
+ dest='websock_handlers_map_file',
+ default=None,
+ help=('WebSocket handlers map file. '
+ 'Each line consists of alias_resource_path and '
+ 'existing_resource_path, separated by spaces.'))
+ parser.add_option('-s', '--scan-dir', '--scan_dir', dest='scan_dir',
+ default=None,
+ help=('Must be a directory under --websock-handlers. '
+ 'Only handlers under this directory are scanned '
+ 'and registered to the server. '
+ 'Useful for saving scan time when the handler '
+ 'root directory contains lots of files that are '
+ 'not handler file or are handler files but you '
+ 'don\'t want them to be registered. '))
+ parser.add_option('--allow-handlers-outside-root-dir',
+ '--allow_handlers_outside_root_dir',
+ dest='allow_handlers_outside_root_dir',
+ action='store_true',
+ default=False,
+ help=('Scans WebSocket handlers even if their canonical '
+ 'path is not under --websock-handlers.'))
+ parser.add_option('-d', '--document-root', '--document_root',
+ dest='document_root', default='.',
+ help='Document root directory.')
+ parser.add_option('-x', '--cgi-paths', '--cgi_paths', dest='cgi_paths',
+ default=None,
+ help=('CGI paths relative to document_root.'
+ 'Comma-separated. (e.g -x /cgi,/htbin) '
+ 'Files under document_root/cgi_path are handled '
+ 'as CGI programs. Must be executable.'))
+ parser.add_option('-t', '--tls', dest='use_tls', action='store_true',
+ default=False, help='use TLS (wss://)')
+ parser.add_option('--tls-module', '--tls_module', dest='tls_module',
+ type='choice',
+ choices = [_TLS_BY_STANDARD_MODULE, _TLS_BY_PYOPENSSL],
+ help='Use ssl module if "%s" is specified. '
+ 'Use pyOpenSSL module if "%s" is specified' %
+ (_TLS_BY_STANDARD_MODULE, _TLS_BY_PYOPENSSL))
+ parser.add_option('-k', '--private-key', '--private_key',
+ dest='private_key',
+ default='', help='TLS private key file.')
+ parser.add_option('-c', '--certificate', dest='certificate',
+ default='', help='TLS certificate file.')
+ parser.add_option('--tls-client-auth', dest='tls_client_auth',
+ action='store_true', default=False,
+ help='Requests TLS client auth on every connection.')
+ parser.add_option('--tls-client-cert-optional',
+ dest='tls_client_cert_optional',
+ action='store_true', default=False,
+ help=('Makes client certificate optional even though '
+ 'TLS client auth is enabled.'))
+ parser.add_option('--tls-client-ca', dest='tls_client_ca', default='',
+ help=('Specifies a pem file which contains a set of '
+ 'concatenated CA certificates which are used to '
+ 'validate certificates passed from clients'))
+ parser.add_option('--basic-auth', dest='use_basic_auth',
+ action='store_true', default=False,
+ help='Requires Basic authentication.')
+ parser.add_option('--basic-auth-credential',
+ dest='basic_auth_credential', default='test:test',
+ help='Specifies the credential of basic authentication '
+ 'by username:password pair (e.g. test:test).')
+ parser.add_option('-l', '--log-file', '--log_file', dest='log_file',
+ default='', help='Log file.')
+ # Custom log level:
+ # - FINE: Prints status of each frame processing step
+ parser.add_option('--log-level', '--log_level', type='choice',
+ dest='log_level', default='warn',
+ choices=['fine',
+ 'debug', 'info', 'warning', 'warn', 'error',
+ 'critical'],
+ help='Log level.')
+ parser.add_option('--deflate-log-level', '--deflate_log_level',
+ type='choice',
+ dest='deflate_log_level', default='warn',
+ choices=['debug', 'info', 'warning', 'warn', 'error',
+ 'critical'],
+ help='Log level for _Deflater and _Inflater.')
+ parser.add_option('--thread-monitor-interval-in-sec',
+ '--thread_monitor_interval_in_sec',
+ dest='thread_monitor_interval_in_sec',
+ type='int', default=-1,
+ help=('If positive integer is specified, run a thread '
+ 'monitor to show the status of server threads '
+ 'periodically in the specified inteval in '
+ 'second. If non-positive integer is specified, '
+ 'disable the thread monitor.'))
+ parser.add_option('--log-max', '--log_max', dest='log_max', type='int',
+ default=_DEFAULT_LOG_MAX_BYTES,
+ help='Log maximum bytes')
+ parser.add_option('--log-count', '--log_count', dest='log_count',
+ type='int', default=_DEFAULT_LOG_BACKUP_COUNT,
+ help='Log backup count')
+ parser.add_option('--allow-draft75', dest='allow_draft75',
+ action='store_true', default=False,
+ help='Obsolete option. Ignored.')
+ parser.add_option('--strict', dest='strict', action='store_true',
+ default=False, help='Obsolete option. Ignored.')
+ parser.add_option('-q', '--queue', dest='request_queue_size', type='int',
+ default=_DEFAULT_REQUEST_QUEUE_SIZE,
+ help='request queue size')
+
+ return parser
+
+
+class ThreadMonitor(threading.Thread):
+ daemon = True
+
+ def __init__(self, interval_in_sec):
+ threading.Thread.__init__(self, name='ThreadMonitor')
+
+ self._logger = util.get_class_logger(self)
+
+ self._interval_in_sec = interval_in_sec
+
+ def run(self):
+ while True:
+ thread_name_list = []
+ for thread in threading.enumerate():
+ thread_name_list.append(thread.name)
+ self._logger.info(
+ "%d active threads: %s",
+ threading.active_count(),
+ ', '.join(thread_name_list))
+ time.sleep(self._interval_in_sec)
+
+
+def _parse_args_and_config(args):
+ parser = _build_option_parser()
+
+ # First, parse options without configuration file.
+ temporary_options, temporary_args = parser.parse_args(args=args)
+ if temporary_args:
+ logging.critical(
+ 'Unrecognized positional arguments: %r', temporary_args)
+ sys.exit(1)
+
+ if temporary_options.config_file:
+ try:
+ config_fp = open(temporary_options.config_file, 'r')
+ except IOError, e:
+ logging.critical(
+ 'Failed to open configuration file %r: %r',
+ temporary_options.config_file,
+ e)
+ sys.exit(1)
+
+ config_parser = ConfigParser.SafeConfigParser()
+ config_parser.readfp(config_fp)
+ config_fp.close()
+
+ args_from_config = []
+ for name, value in config_parser.items('pywebsocket'):
+ args_from_config.append('--' + name)
+ args_from_config.append(value)
+ if args is None:
+ args = args_from_config
+ else:
+ args = args_from_config + args
+ return parser.parse_args(args=args)
+ else:
+ return temporary_options, temporary_args
+
+
+def _main(args=None):
+ """You can call this function from your own program, but please note that
+ this function has some side-effects that might affect your program. For
+ example, util.wrap_popen3_for_win use in this method replaces implementation
+ of os.popen3.
+ """
+
+ options, args = _parse_args_and_config(args=args)
+
+ os.chdir(options.document_root)
+
+ _configure_logging(options)
+
+ if options.allow_draft75:
+ logging.warning('--allow_draft75 option is obsolete.')
+
+ if options.strict:
+ logging.warning('--strict option is obsolete.')
+
+ # TODO(tyoshino): Clean up initialization of CGI related values. Move some
+ # of code here to WebSocketRequestHandler class if it's better.
+ options.cgi_directories = []
+ options.is_executable_method = None
+ if options.cgi_paths:
+ options.cgi_directories = options.cgi_paths.split(',')
+ if sys.platform in ('cygwin', 'win32'):
+ cygwin_path = None
+ # For Win32 Python, it is expected that CYGWIN_PATH
+ # is set to a directory of cygwin binaries.
+ # For example, websocket_server.py in Chromium sets CYGWIN_PATH to
+ # full path of third_party/cygwin/bin.
+ if 'CYGWIN_PATH' in os.environ:
+ cygwin_path = os.environ['CYGWIN_PATH']
+ util.wrap_popen3_for_win(cygwin_path)
+
+ def __check_script(scriptpath):
+ return util.get_script_interp(scriptpath, cygwin_path)
+
+ options.is_executable_method = __check_script
+
+ if options.use_tls:
+ if options.tls_module is None:
+ if _import_ssl():
+ options.tls_module = _TLS_BY_STANDARD_MODULE
+ logging.debug('Using ssl module')
+ elif _import_pyopenssl():
+ options.tls_module = _TLS_BY_PYOPENSSL
+ logging.debug('Using pyOpenSSL module')
+ else:
+ logging.critical(
+ 'TLS support requires ssl or pyOpenSSL module.')
+ sys.exit(1)
+ elif options.tls_module == _TLS_BY_STANDARD_MODULE:
+ if not _import_ssl():
+ logging.critical('ssl module is not available')
+ sys.exit(1)
+ elif options.tls_module == _TLS_BY_PYOPENSSL:
+ if not _import_pyopenssl():
+ logging.critical('pyOpenSSL module is not available')
+ sys.exit(1)
+ else:
+ logging.critical('Invalid --tls-module option: %r',
+ options.tls_module)
+ sys.exit(1)
+
+ if not options.private_key or not options.certificate:
+ logging.critical(
+ 'To use TLS, specify private_key and certificate.')
+ sys.exit(1)
+
+ if (options.tls_client_cert_optional and
+ not options.tls_client_auth):
+ logging.critical('Client authentication must be enabled to '
+ 'specify tls_client_cert_optional')
+ sys.exit(1)
+ else:
+ if options.tls_module is not None:
+ logging.critical('Use --tls-module option only together with '
+ '--use-tls option.')
+ sys.exit(1)
+
+ if options.tls_client_auth:
+ logging.critical('TLS must be enabled for client authentication.')
+ sys.exit(1)
+
+ if options.tls_client_cert_optional:
+ logging.critical('TLS must be enabled for client authentication.')
+ sys.exit(1)
+
+ if not options.scan_dir:
+ options.scan_dir = options.websock_handlers
+
+ if options.use_basic_auth:
+ options.basic_auth_credential = 'Basic ' + base64.b64encode(
+ options.basic_auth_credential)
+
+ try:
+ if options.thread_monitor_interval_in_sec > 0:
+ # Run a thread monitor to show the status of server threads for
+ # debugging.
+ ThreadMonitor(options.thread_monitor_interval_in_sec).start()
+
+ server = WebSocketServer(options)
+ server.serve_forever()
+ except Exception, e:
+ logging.critical('mod_pywebsocket: %s' % e)
+ logging.critical('mod_pywebsocket: %s' % util.get_stack_trace())
+ sys.exit(1)
+
+
+if __name__ == '__main__':
+ _main(sys.argv[1:])
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/stream.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/stream.py
new file mode 100644
index 00000000000..edc53327974
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/stream.py
@@ -0,0 +1,57 @@
+# Copyright 2011, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+"""This file exports public symbols.
+"""
+
+
+from mod_pywebsocket._stream_base import BadOperationException
+from mod_pywebsocket._stream_base import ConnectionTerminatedException
+from mod_pywebsocket._stream_base import InvalidFrameException
+from mod_pywebsocket._stream_base import InvalidUTF8Exception
+from mod_pywebsocket._stream_base import UnsupportedFrameException
+from mod_pywebsocket._stream_hixie75 import StreamHixie75
+from mod_pywebsocket._stream_hybi import Frame
+from mod_pywebsocket._stream_hybi import Stream
+from mod_pywebsocket._stream_hybi import StreamOptions
+
+# These methods are intended to be used by WebSocket client developers to have
+# their implementations receive broken data in tests.
+from mod_pywebsocket._stream_hybi import create_close_frame
+from mod_pywebsocket._stream_hybi import create_header
+from mod_pywebsocket._stream_hybi import create_length_header
+from mod_pywebsocket._stream_hybi import create_ping_frame
+from mod_pywebsocket._stream_hybi import create_pong_frame
+from mod_pywebsocket._stream_hybi import create_binary_frame
+from mod_pywebsocket._stream_hybi import create_text_frame
+from mod_pywebsocket._stream_hybi import create_closing_handshake_body
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/util.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/util.py
new file mode 100644
index 00000000000..d224ae3942d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/util.py
@@ -0,0 +1,416 @@
+# Copyright 2011, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+"""WebSocket utilities.
+"""
+
+
+import array
+import errno
+
+# Import hash classes from a module available and recommended for each Python
+# version and re-export those symbol. Use sha and md5 module in Python 2.4, and
+# hashlib module in Python 2.6.
+try:
+ import hashlib
+ md5_hash = hashlib.md5
+ sha1_hash = hashlib.sha1
+except ImportError:
+ import md5
+ import sha
+ md5_hash = md5.md5
+ sha1_hash = sha.sha
+
+import StringIO
+import logging
+import os
+import re
+import socket
+import traceback
+import zlib
+
+try:
+ from mod_pywebsocket import fast_masking
+except ImportError:
+ pass
+
+
+def get_stack_trace():
+ """Get the current stack trace as string.
+
+ This is needed to support Python 2.3.
+ TODO: Remove this when we only support Python 2.4 and above.
+ Use traceback.format_exc instead.
+ """
+
+ out = StringIO.StringIO()
+ traceback.print_exc(file=out)
+ return out.getvalue()
+
+
+def prepend_message_to_exception(message, exc):
+ """Prepend message to the exception."""
+
+ exc.args = (message + str(exc),)
+ return
+
+
+def __translate_interp(interp, cygwin_path):
+ """Translate interp program path for Win32 python to run cygwin program
+ (e.g. perl). Note that it doesn't support path that contains space,
+ which is typically true for Unix, where #!-script is written.
+ For Win32 python, cygwin_path is a directory of cygwin binaries.
+
+ Args:
+ interp: interp command line
+ cygwin_path: directory name of cygwin binary, or None
+ Returns:
+ translated interp command line.
+ """
+ if not cygwin_path:
+ return interp
+ m = re.match('^[^ ]*/([^ ]+)( .*)?', interp)
+ if m:
+ cmd = os.path.join(cygwin_path, m.group(1))
+ return cmd + m.group(2)
+ return interp
+
+
+def get_script_interp(script_path, cygwin_path=None):
+ """Gets #!-interpreter command line from the script.
+
+ It also fixes command path. When Cygwin Python is used, e.g. in WebKit,
+ it could run "/usr/bin/perl -wT hello.pl".
+ When Win32 Python is used, e.g. in Chromium, it couldn't. So, fix
+ "/usr/bin/perl" to "<cygwin_path>\perl.exe".
+
+ Args:
+ script_path: pathname of the script
+ cygwin_path: directory name of cygwin binary, or None
+ Returns:
+ #!-interpreter command line, or None if it is not #!-script.
+ """
+ fp = open(script_path)
+ line = fp.readline()
+ fp.close()
+ m = re.match('^#!(.*)', line)
+ if m:
+ return __translate_interp(m.group(1), cygwin_path)
+ return None
+
+
+def wrap_popen3_for_win(cygwin_path):
+ """Wrap popen3 to support #!-script on Windows.
+
+ Args:
+ cygwin_path: path for cygwin binary if command path is needed to be
+ translated. None if no translation required.
+ """
+
+ __orig_popen3 = os.popen3
+
+ def __wrap_popen3(cmd, mode='t', bufsize=-1):
+ cmdline = cmd.split(' ')
+ interp = get_script_interp(cmdline[0], cygwin_path)
+ if interp:
+ cmd = interp + ' ' + cmd
+ return __orig_popen3(cmd, mode, bufsize)
+
+ os.popen3 = __wrap_popen3
+
+
+def hexify(s):
+ return ' '.join(map(lambda x: '%02x' % ord(x), s))
+
+
+def get_class_logger(o):
+ return logging.getLogger(
+ '%s.%s' % (o.__class__.__module__, o.__class__.__name__))
+
+
+class NoopMasker(object):
+ """A masking object that has the same interface as RepeatedXorMasker but
+ just returns the string passed in without making any change.
+ """
+
+ def __init__(self):
+ pass
+
+ def mask(self, s):
+ return s
+
+
+class RepeatedXorMasker(object):
+ """A masking object that applies XOR on the string given to mask method
+ with the masking bytes given to the constructor repeatedly. This object
+ remembers the position in the masking bytes the last mask method call
+ ended and resumes from that point on the next mask method call.
+ """
+
+ def __init__(self, masking_key):
+ self._masking_key = masking_key
+ self._masking_key_index = 0
+
+ def _mask_using_swig(self, s):
+ masked_data = fast_masking.mask(
+ s, self._masking_key, self._masking_key_index)
+ self._masking_key_index = (
+ (self._masking_key_index + len(s)) % len(self._masking_key))
+ return masked_data
+
+ def _mask_using_array(self, s):
+ result = array.array('B')
+ result.fromstring(s)
+
+ # Use temporary local variables to eliminate the cost to access
+ # attributes
+ masking_key = map(ord, self._masking_key)
+ masking_key_size = len(masking_key)
+ masking_key_index = self._masking_key_index
+
+ for i in xrange(len(result)):
+ result[i] ^= masking_key[masking_key_index]
+ masking_key_index = (masking_key_index + 1) % masking_key_size
+
+ self._masking_key_index = masking_key_index
+
+ return result.tostring()
+
+ if 'fast_masking' in globals():
+ mask = _mask_using_swig
+ else:
+ mask = _mask_using_array
+
+
+# By making wbits option negative, we can suppress CMF/FLG (2 octet) and
+# ADLER32 (4 octet) fields of zlib so that we can use zlib module just as
+# deflate library. DICTID won't be added as far as we don't set dictionary.
+# LZ77 window of 32K will be used for both compression and decompression.
+# For decompression, we can just use 32K to cover any windows size. For
+# compression, we use 32K so receivers must use 32K.
+#
+# Compression level is Z_DEFAULT_COMPRESSION. We don't have to match level
+# to decode.
+#
+# See zconf.h, deflate.cc, inflate.cc of zlib library, and zlibmodule.c of
+# Python. See also RFC1950 (ZLIB 3.3).
+
+
+class _Deflater(object):
+
+ def __init__(self, window_bits):
+ self._logger = get_class_logger(self)
+
+ self._compress = zlib.compressobj(
+ zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -window_bits)
+
+ def compress(self, bytes):
+ compressed_bytes = self._compress.compress(bytes)
+ self._logger.debug('Compress input %r', bytes)
+ self._logger.debug('Compress result %r', compressed_bytes)
+ return compressed_bytes
+
+ def compress_and_flush(self, bytes):
+ compressed_bytes = self._compress.compress(bytes)
+ compressed_bytes += self._compress.flush(zlib.Z_SYNC_FLUSH)
+ self._logger.debug('Compress input %r', bytes)
+ self._logger.debug('Compress result %r', compressed_bytes)
+ return compressed_bytes
+
+ def compress_and_finish(self, bytes):
+ compressed_bytes = self._compress.compress(bytes)
+ compressed_bytes += self._compress.flush(zlib.Z_FINISH)
+ self._logger.debug('Compress input %r', bytes)
+ self._logger.debug('Compress result %r', compressed_bytes)
+ return compressed_bytes
+
+
+class _Inflater(object):
+
+ def __init__(self, window_bits):
+ self._logger = get_class_logger(self)
+ self._window_bits = window_bits
+
+ self._unconsumed = ''
+
+ self.reset()
+
+ def decompress(self, size):
+ if not (size == -1 or size > 0):
+ raise Exception('size must be -1 or positive')
+
+ data = ''
+
+ while True:
+ if size == -1:
+ data += self._decompress.decompress(self._unconsumed)
+ # See Python bug http://bugs.python.org/issue12050 to
+ # understand why the same code cannot be used for updating
+ # self._unconsumed for here and else block.
+ self._unconsumed = ''
+ else:
+ data += self._decompress.decompress(
+ self._unconsumed, size - len(data))
+ self._unconsumed = self._decompress.unconsumed_tail
+ if self._decompress.unused_data:
+ # Encountered a last block (i.e. a block with BFINAL = 1) and
+ # found a new stream (unused_data). We cannot use the same
+ # zlib.Decompress object for the new stream. Create a new
+ # Decompress object to decompress the new one.
+ #
+ # It's fine to ignore unconsumed_tail if unused_data is not
+ # empty.
+ self._unconsumed = self._decompress.unused_data
+ self.reset()
+ if size >= 0 and len(data) == size:
+ # data is filled. Don't call decompress again.
+ break
+ else:
+ # Re-invoke Decompress.decompress to try to decompress all
+ # available bytes before invoking read which blocks until
+ # any new byte is available.
+ continue
+ else:
+ # Here, since unused_data is empty, even if unconsumed_tail is
+ # not empty, bytes of requested length are already in data. We
+ # don't have to "continue" here.
+ break
+
+ if data:
+ self._logger.debug('Decompressed %r', data)
+ return data
+
+ def append(self, data):
+ self._logger.debug('Appended %r', data)
+ self._unconsumed += data
+
+ def reset(self):
+ self._logger.debug('Reset')
+ self._decompress = zlib.decompressobj(-self._window_bits)
+
+
+# Compresses/decompresses given octets using the method introduced in RFC1979.
+
+
+class _RFC1979Deflater(object):
+ """A compressor class that applies DEFLATE to given byte sequence and
+ flushes using the algorithm described in the RFC1979 section 2.1.
+ """
+
+ def __init__(self, window_bits, no_context_takeover):
+ self._deflater = None
+ if window_bits is None:
+ window_bits = zlib.MAX_WBITS
+ self._window_bits = window_bits
+ self._no_context_takeover = no_context_takeover
+
+ def filter(self, bytes, end=True, bfinal=False):
+ if self._deflater is None:
+ self._deflater = _Deflater(self._window_bits)
+
+ if bfinal:
+ result = self._deflater.compress_and_finish(bytes)
+ # Add a padding block with BFINAL = 0 and BTYPE = 0.
+ result = result + chr(0)
+ self._deflater = None
+ return result
+
+ result = self._deflater.compress_and_flush(bytes)
+ if end:
+ # Strip last 4 octets which is LEN and NLEN field of a
+ # non-compressed block added for Z_SYNC_FLUSH.
+ result = result[:-4]
+
+ if self._no_context_takeover and end:
+ self._deflater = None
+
+ return result
+
+
+class _RFC1979Inflater(object):
+ """A decompressor class for byte sequence compressed and flushed following
+ the algorithm described in the RFC1979 section 2.1.
+ """
+
+ def __init__(self, window_bits=zlib.MAX_WBITS):
+ self._inflater = _Inflater(window_bits)
+
+ def filter(self, bytes):
+ # Restore stripped LEN and NLEN field of a non-compressed block added
+ # for Z_SYNC_FLUSH.
+ self._inflater.append(bytes + '\x00\x00\xff\xff')
+ return self._inflater.decompress(-1)
+
+
+class DeflateSocket(object):
+ """A wrapper class for socket object to intercept send and recv to perform
+ deflate compression and decompression transparently.
+ """
+
+ # Size of the buffer passed to recv to receive compressed data.
+ _RECV_SIZE = 4096
+
+ def __init__(self, socket):
+ self._socket = socket
+
+ self._logger = get_class_logger(self)
+
+ self._deflater = _Deflater(zlib.MAX_WBITS)
+ self._inflater = _Inflater(zlib.MAX_WBITS)
+
+ def recv(self, size):
+ """Receives data from the socket specified on the construction up
+ to the specified size. Once any data is available, returns it even
+ if it's smaller than the specified size.
+ """
+
+ # TODO(tyoshino): Allow call with size=0. It should block until any
+ # decompressed data is available.
+ if size <= 0:
+ raise Exception('Non-positive size passed')
+ while True:
+ data = self._inflater.decompress(size)
+ if len(data) != 0:
+ return data
+
+ read_data = self._socket.recv(DeflateSocket._RECV_SIZE)
+ if not read_data:
+ return ''
+ self._inflater.append(read_data)
+
+ def sendall(self, bytes):
+ self.send(bytes)
+
+ def send(self, bytes):
+ self._socket.sendall(self._deflater.compress_and_flush(bytes))
+ return len(bytes)
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/xhr_benchmark_handler.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/xhr_benchmark_handler.py
new file mode 100644
index 00000000000..6735c7e2a3d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/mod_pywebsocket/xhr_benchmark_handler.py
@@ -0,0 +1,109 @@
+# Copyright 2014 Google Inc. All rights reserved.
+#
+# Use of this source code is governed by a BSD-style
+# license that can be found in the COPYING file or at
+# https://developers.google.com/open-source/licenses/bsd
+
+
+from mod_pywebsocket import util
+
+
+class XHRBenchmarkHandler(object):
+ def __init__(self, headers, rfile, wfile):
+ self._logger = util.get_class_logger(self)
+
+ self.headers = headers
+ self.rfile = rfile
+ self.wfile = wfile
+
+ def do_send(self):
+ content_length = int(self.headers.getheader('Content-Length'))
+
+ self._logger.debug('Requested to receive %s bytes', content_length)
+
+ RECEIVE_BLOCK_SIZE = 1024 * 1024
+
+ bytes_to_receive = content_length
+ while bytes_to_receive > 0:
+ bytes_to_receive_in_this_loop = bytes_to_receive
+ if bytes_to_receive_in_this_loop > RECEIVE_BLOCK_SIZE:
+ bytes_to_receive_in_this_loop = RECEIVE_BLOCK_SIZE
+ received_data = self.rfile.read(bytes_to_receive_in_this_loop)
+ if received_data != ('a' * bytes_to_receive_in_this_loop):
+ self._logger.debug('Request body verification failed')
+ return
+ bytes_to_receive -= len(received_data)
+ if bytes_to_receive < 0:
+ self._logger.debug('Received %d more bytes than expected' %
+ (-bytes_to_receive))
+ return
+
+ # Return the number of received bytes back to the client.
+ response_body = '%d' % content_length
+ self.wfile.write(
+ 'HTTP/1.1 200 OK\r\n'
+ 'Content-Type: text/html\r\n'
+ 'Content-Length: %d\r\n'
+ '\r\n%s' % (len(response_body), response_body))
+ self.wfile.flush()
+
+ def do_receive(self):
+ content_length = int(self.headers.getheader('Content-Length'))
+ request_body = self.rfile.read(content_length)
+
+ request_array = request_body.split(' ')
+ if len(request_array) < 2:
+ self._logger.debug('Malformed request body: %r', request_body)
+ return
+
+ # Parse the size parameter.
+ bytes_to_send = request_array[0]
+ try:
+ bytes_to_send = int(bytes_to_send)
+ except ValueError, e:
+ self._logger.debug('Malformed size parameter: %r', bytes_to_send)
+ return
+ self._logger.debug('Requested to send %s bytes', bytes_to_send)
+
+ # Parse the transfer encoding parameter.
+ chunked_mode = False
+ mode_parameter = request_array[1]
+ if mode_parameter == 'chunked':
+ self._logger.debug('Requested chunked transfer encoding')
+ chunked_mode = True
+ elif mode_parameter != 'none':
+ self._logger.debug('Invalid mode parameter: %r', mode_parameter)
+ return
+
+ # Write a header
+ response_header = (
+ 'HTTP/1.1 200 OK\r\n'
+ 'Content-Type: application/octet-stream\r\n')
+ if chunked_mode:
+ response_header += 'Transfer-Encoding: chunked\r\n\r\n'
+ else:
+ response_header += (
+ 'Content-Length: %d\r\n\r\n' % bytes_to_send)
+ self.wfile.write(response_header)
+ self.wfile.flush()
+
+ # Write a body
+ SEND_BLOCK_SIZE = 1024 * 1024
+
+ while bytes_to_send > 0:
+ bytes_to_send_in_this_loop = bytes_to_send
+ if bytes_to_send_in_this_loop > SEND_BLOCK_SIZE:
+ bytes_to_send_in_this_loop = SEND_BLOCK_SIZE
+
+ if chunked_mode:
+ self.wfile.write('%x\r\n' % bytes_to_send_in_this_loop)
+ self.wfile.write('a' * bytes_to_send_in_this_loop)
+ if chunked_mode:
+ self.wfile.write('\r\n')
+ self.wfile.flush()
+
+ bytes_to_send -= bytes_to_send_in_this_loop
+
+ if chunked_mode:
+ self.wfile.write('0\r\n\r\n')
+ self.wfile.flush()
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/setup.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/setup.py
new file mode 100755
index 00000000000..ada8db3e111
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/setup.py
@@ -0,0 +1,74 @@
+#!/usr/bin/env python
+#
+# Copyright 2012, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+"""Set up script for mod_pywebsocket.
+"""
+
+
+from distutils.core import setup, Extension
+import sys
+
+
+_PACKAGE_NAME = 'mod_pywebsocket'
+
+# Build and use a C++ extension for faster masking. SWIG is required.
+_USE_FAST_MASKING = False
+
+if sys.version < '2.3':
+ print >> sys.stderr, '%s requires Python 2.3 or later.' % _PACKAGE_NAME
+ sys.exit(1)
+
+if _USE_FAST_MASKING:
+ setup(ext_modules=[
+ Extension(
+ 'mod_pywebsocket/_fast_masking',
+ ['mod_pywebsocket/fast_masking.i'],
+ swig_opts=['-c++'])])
+
+setup(author='Yuzo Fujishima',
+ author_email='yuzo@chromium.org',
+ description='WebSocket extension for Apache HTTP Server.',
+ long_description=(
+ 'mod_pywebsocket is an Apache HTTP Server extension for '
+ 'the WebSocket Protocol (RFC 6455). '
+ 'See mod_pywebsocket/__init__.py for more detail.'),
+ license='See COPYING',
+ name=_PACKAGE_NAME,
+ packages=[_PACKAGE_NAME, _PACKAGE_NAME + '.handshake'],
+ url='http://code.google.com/p/pywebsocket/',
+ # See the source of distutils.version, distutils.versionpredicate and
+ # distutils.dist to understand how to name version numbers.
+ version='0.7.9',
+ )
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/__init__.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/__init__.py
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/cert/cacert.pem b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/cert/cacert.pem
new file mode 100644
index 00000000000..4dadae121bd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/cert/cacert.pem
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICvDCCAiWgAwIBAgIJAKqVghkGF1rSMA0GCSqGSIb3DQEBBQUAMEkxCzAJBgNV
+BAYTAkpQMQ4wDAYDVQQIEwVUb2t5bzEUMBIGA1UEChMLcHl3ZWJzb2NrZXQxFDAS
+BgNVBAMTC3B5d2Vic29ja2V0MB4XDTEyMDYwNjA3MjQzM1oXDTM5MTAyMzA3MjQz
+M1owSTELMAkGA1UEBhMCSlAxDjAMBgNVBAgTBVRva3lvMRQwEgYDVQQKEwtweXdl
+YnNvY2tldDEUMBIGA1UEAxMLcHl3ZWJzb2NrZXQwgZ8wDQYJKoZIhvcNAQEBBQAD
+gY0AMIGJAoGBAKoSEW2biQxVrMMKdn/8PJzDYiSXDPR9WQbLRRQ1Gm5jkCYiahXW
+u2CbTThfPPfi2NHA3I+HlT7gO9yR7RVUvN6ISUzGwXDEq4f4UNqtQOhQaqqK+CZ9
+LO/BhO/YYfNrbSPlYzHUKaT9ese7xO9VzVKLW+qUf2Mjh4/+SzxBDNP7AgMBAAGj
+gaswgagwHQYDVR0OBBYEFOsWdxCSuyhwaZeab6BoTho3++bzMHkGA1UdIwRyMHCA
+FOsWdxCSuyhwaZeab6BoTho3++bzoU2kSzBJMQswCQYDVQQGEwJKUDEOMAwGA1UE
+CBMFVG9reW8xFDASBgNVBAoTC3B5d2Vic29ja2V0MRQwEgYDVQQDEwtweXdlYnNv
+Y2tldIIJAKqVghkGF1rSMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEA
+gsMI1WEYqNw/jhUIdrTBcCxJ0X6hJvA9ziKANVm1Rs+4P3YDArkQ8bCr6xY+Kw7s
+Zp0yE7dM8GMdi+DU6hL3t3E5eMkTS1yZr9WCK4f2RLo+et98selZydpHemF3DJJ3
+gAj8Sx4LBaG8Cb/WnEMPv3MxG3fBE5favF6V4jU07hQ=
+-----END CERTIFICATE-----
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/cert/cert.pem b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/cert/cert.pem
new file mode 100644
index 00000000000..25379a72b0d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/cert/cert.pem
@@ -0,0 +1,61 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 1 (0x1)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=JP, ST=Tokyo, O=pywebsocket, CN=pywebsocket
+ Validity
+ Not Before: Jun 6 07:25:08 2012 GMT
+ Not After : Oct 23 07:25:08 2039 GMT
+ Subject: C=JP, ST=Tokyo, O=pywebsocket, CN=pywebsocket
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:de:10:ce:3a:5a:04:a4:1c:29:93:5c:23:82:1a:
+ f2:06:01:e6:2b:a4:0f:dd:77:49:76:89:03:a2:21:
+ de:04:75:c6:e2:dd:fb:35:27:3a:a2:92:8e:12:62:
+ 2b:3e:1f:f4:78:df:b6:94:cb:27:d6:cb:d6:37:d7:
+ 5c:08:f0:09:3e:c9:ce:24:2d:00:c9:df:4a:e0:99:
+ e5:fb:23:a9:e2:d6:c9:3d:96:fa:01:88:de:5a:89:
+ b0:cf:03:67:6f:04:86:1d:ef:62:1c:55:a9:07:9a:
+ 2e:66:2a:73:5b:4c:62:03:f9:82:83:db:68:bf:b8:
+ 4b:0b:8b:93:11:b8:54:73:7b
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:FALSE
+ Netscape Cert Type:
+ SSL Server
+ Netscape Comment:
+ OpenSSL Generated Certificate
+ X509v3 Subject Key Identifier:
+ 82:A1:73:8B:16:0C:7C:E4:D3:46:95:13:95:1A:32:C1:84:E9:06:00
+ X509v3 Authority Key Identifier:
+ keyid:EB:16:77:10:92:BB:28:70:69:97:9A:6F:A0:68:4E:1A:37:FB:E6:F3
+
+ Signature Algorithm: sha1WithRSAEncryption
+ 6b:b3:46:29:02:df:b0:c8:8e:c4:d7:7f:a0:1e:0d:1a:eb:2f:
+ df:d1:48:57:36:5f:95:8c:1b:f0:51:d6:52:e7:8d:84:3b:9f:
+ d8:ed:22:9c:aa:bd:ee:9b:90:1d:84:a3:4c:0b:cb:eb:64:73:
+ ba:f7:15:ce:da:5f:db:8b:15:07:a6:28:7f:b9:8c:11:9b:64:
+ d3:f1:be:52:4f:c3:d8:58:fe:de:56:63:63:3b:51:ed:a7:81:
+ f9:05:51:70:63:32:09:0e:94:7e:05:fe:a1:56:18:34:98:d5:
+ 99:1e:4e:27:38:89:90:6a:e5:ce:60:35:01:f5:de:34:60:b1:
+ cb:ae
+-----BEGIN CERTIFICATE-----
+MIICmDCCAgGgAwIBAgIBATANBgkqhkiG9w0BAQUFADBJMQswCQYDVQQGEwJKUDEO
+MAwGA1UECBMFVG9reW8xFDASBgNVBAoTC3B5d2Vic29ja2V0MRQwEgYDVQQDEwtw
+eXdlYnNvY2tldDAeFw0xMjA2MDYwNzI1MDhaFw0zOTEwMjMwNzI1MDhaMEkxCzAJ
+BgNVBAYTAkpQMQ4wDAYDVQQIEwVUb2t5bzEUMBIGA1UEChMLcHl3ZWJzb2NrZXQx
+FDASBgNVBAMTC3B5d2Vic29ja2V0MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
+gQDeEM46WgSkHCmTXCOCGvIGAeYrpA/dd0l2iQOiId4Edcbi3fs1Jzqiko4SYis+
+H/R437aUyyfWy9Y311wI8Ak+yc4kLQDJ30rgmeX7I6ni1sk9lvoBiN5aibDPA2dv
+BIYd72IcVakHmi5mKnNbTGID+YKD22i/uEsLi5MRuFRzewIDAQABo4GPMIGMMAkG
+A1UdEwQCMAAwEQYJYIZIAYb4QgEBBAQDAgZAMCwGCWCGSAGG+EIBDQQfFh1PcGVu
+U1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUgqFzixYMfOTTRpUT
+lRoywYTpBgAwHwYDVR0jBBgwFoAU6xZ3EJK7KHBpl5pvoGhOGjf75vMwDQYJKoZI
+hvcNAQEFBQADgYEAa7NGKQLfsMiOxNd/oB4NGusv39FIVzZflYwb8FHWUueNhDuf
+2O0inKq97puQHYSjTAvL62RzuvcVztpf24sVB6Yof7mMEZtk0/G+Uk/D2Fj+3lZj
+YztR7aeB+QVRcGMyCQ6UfgX+oVYYNJjVmR5OJziJkGrlzmA1AfXeNGCxy64=
+-----END CERTIFICATE-----
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/cert/client_cert.p12 b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/cert/client_cert.p12
new file mode 100644
index 00000000000..14e13992798
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/cert/client_cert.p12
Binary files differ
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/cert/key.pem b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/cert/key.pem
new file mode 100644
index 00000000000..fae858318f2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/cert/key.pem
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXgIBAAKBgQDeEM46WgSkHCmTXCOCGvIGAeYrpA/dd0l2iQOiId4Edcbi3fs1
+Jzqiko4SYis+H/R437aUyyfWy9Y311wI8Ak+yc4kLQDJ30rgmeX7I6ni1sk9lvoB
+iN5aibDPA2dvBIYd72IcVakHmi5mKnNbTGID+YKD22i/uEsLi5MRuFRzewIDAQAB
+AoGBAIuCuV1Vcnb7rm8CwtgZP5XgmY8vSjxTldafa6XvawEYUTP0S77v/1llg1Yv
+UIV+I+PQgG9oVoYOl22LoimHS/Z3e1fsot5tDYszGe8/Gkst4oaReSoxvBUa6WXp
+QSo7YFCajuHtE+W/gzF+UHbdzzXIDjQZ314LNF5t+4UnsEPBAkEA+girImqWoM2t
+3UR8f8oekERwsmEMf9DH5YpH4cvUnvI+kwesC/r2U8Sho++fyEMUNm7aIXGqNLga
+ogAM+4NX4QJBAONdSxSay22egTGNoIhLndljWkuOt/9FWj2klf/4QxD4blMJQ5Oq
+QdOGAh7nVQjpPLQ5D7CBVAKpGM2CD+QJBtsCQEP2kz35pxPylG3urcC2mfQxBkkW
+ZCViBNP58GwJ0bOauTOSBEwFXWuLqTw8aDwxL49UNmqc0N0fpe2fAehj3UECQQCm
+FH/DjU8Lw7ybddjNtm6XXPuYNagxz3cbkB4B3FchDleIUDwMoVF0MW9bI5/54mV1
+QDk1tUKortxvQZJaAD4BAkEAhGOHQqPd6bBBoFBvpaLzPJMxwLKrB+Wtkq/QlC72
+ClRiMn2g8SALiIL3BDgGXKcKE/Wy7jo/af/JCzQ/cPqt/A==
+-----END RSA PRIVATE KEY-----
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/client_for_testing.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/client_for_testing.py
new file mode 100644
index 00000000000..c7f805ee94e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/client_for_testing.py
@@ -0,0 +1,1100 @@
+#!/usr/bin/env python
+#
+# Copyright 2012, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+"""WebSocket client utility for testing.
+
+This module contains helper methods for performing handshake, frame
+sending/receiving as a WebSocket client.
+
+This is code for testing mod_pywebsocket. Keep this code independent from
+mod_pywebsocket. Don't import e.g. Stream class for generating frame for
+testing. Using util.hexify, etc. that are not related to protocol processing
+is allowed.
+
+Note:
+This code is far from robust, e.g., we cut corners in handshake.
+"""
+
+
+import base64
+import errno
+import logging
+import os
+import random
+import re
+import socket
+import struct
+import time
+
+from mod_pywebsocket import common
+from mod_pywebsocket import util
+
+
+DEFAULT_PORT = 80
+DEFAULT_SECURE_PORT = 443
+
+# Opcodes introduced in IETF HyBi 01 for the new framing format
+OPCODE_CONTINUATION = 0x0
+OPCODE_CLOSE = 0x8
+OPCODE_PING = 0x9
+OPCODE_PONG = 0xa
+OPCODE_TEXT = 0x1
+OPCODE_BINARY = 0x2
+
+# Strings used for handshake
+_UPGRADE_HEADER = 'Upgrade: websocket\r\n'
+_UPGRADE_HEADER_HIXIE75 = 'Upgrade: WebSocket\r\n'
+_CONNECTION_HEADER = 'Connection: Upgrade\r\n'
+
+WEBSOCKET_ACCEPT_UUID = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
+
+# Status codes
+STATUS_NORMAL_CLOSURE = 1000
+STATUS_GOING_AWAY = 1001
+STATUS_PROTOCOL_ERROR = 1002
+STATUS_UNSUPPORTED_DATA = 1003
+STATUS_NO_STATUS_RECEIVED = 1005
+STATUS_ABNORMAL_CLOSURE = 1006
+STATUS_INVALID_FRAME_PAYLOAD_DATA = 1007
+STATUS_POLICY_VIOLATION = 1008
+STATUS_MESSAGE_TOO_BIG = 1009
+STATUS_MANDATORY_EXT = 1010
+STATUS_INTERNAL_ENDPOINT_ERROR = 1011
+STATUS_TLS_HANDSHAKE = 1015
+
+# Extension tokens
+_DEFLATE_FRAME_EXTENSION = 'deflate-frame'
+# TODO(bashi): Update after mux implementation finished.
+_MUX_EXTENSION = 'mux_DO_NOT_USE'
+_PERMESSAGE_DEFLATE_EXTENSION = 'permessage-deflate'
+
+def _method_line(resource):
+ return 'GET %s HTTP/1.1\r\n' % resource
+
+
+def _sec_origin_header(origin):
+ return 'Sec-WebSocket-Origin: %s\r\n' % origin.lower()
+
+
+def _origin_header(origin):
+ # 4.1 13. concatenation of the string "Origin:", a U+0020 SPACE character,
+ # and the /origin/ value, converted to ASCII lowercase, to /fields/.
+ return 'Origin: %s\r\n' % origin.lower()
+
+
+def _format_host_header(host, port, secure):
+ # 4.1 9. Let /hostport/ be an empty string.
+ # 4.1 10. Append the /host/ value, converted to ASCII lowercase, to
+ # /hostport/
+ hostport = host.lower()
+ # 4.1 11. If /secure/ is false, and /port/ is not 80, or if /secure/
+ # is true, and /port/ is not 443, then append a U+003A COLON character
+ # (:) followed by the value of /port/, expressed as a base-ten integer,
+ # to /hostport/
+ if ((not secure and port != DEFAULT_PORT) or
+ (secure and port != DEFAULT_SECURE_PORT)):
+ hostport += ':' + str(port)
+ # 4.1 12. concatenation of the string "Host:", a U+0020 SPACE
+ # character, and /hostport/, to /fields/.
+ return 'Host: %s\r\n' % hostport
+
+
+# TODO(tyoshino): Define a base class and move these shared methods to that.
+
+
+def receive_bytes(socket, length):
+ received_bytes = []
+ remaining = length
+ while remaining > 0:
+ new_received_bytes = socket.recv(remaining)
+ if not new_received_bytes:
+ raise Exception(
+ 'Connection closed before receiving requested length '
+ '(requested %d bytes but received only %d bytes)' %
+ (length, length - remaining))
+ received_bytes.append(new_received_bytes)
+ remaining -= len(new_received_bytes)
+ return ''.join(received_bytes)
+
+
+# TODO(tyoshino): Now the WebSocketHandshake class diverts these methods. We
+# should move to HTTP parser as specified in RFC 6455. For HyBi 00 and
+# Hixie 75, pack these methods as some parser class.
+
+
+def _read_fields(socket):
+ # 4.1 32. let /fields/ be a list of name-value pairs, initially empty.
+ fields = {}
+ while True:
+ # 4.1 33. let /name/ and /value/ be empty byte arrays
+ name = ''
+ value = ''
+ # 4.1 34. read /name/
+ name = _read_name(socket)
+ if name is None:
+ break
+ # 4.1 35. read spaces
+ # TODO(tyoshino): Skip only one space as described in the spec.
+ ch = _skip_spaces(socket)
+ # 4.1 36. read /value/
+ value = _read_value(socket, ch)
+ # 4.1 37. read a byte from the server
+ ch = receive_bytes(socket, 1)
+ if ch != '\n': # 0x0A
+ raise Exception(
+ 'Expected LF but found %r while reading value %r for header '
+ '%r' % (ch, name, value))
+ # 4.1 38. append an entry to the /fields/ list that has the name
+ # given by the string obtained by interpreting the /name/ byte
+ # array as a UTF-8 stream and the value given by the string
+ # obtained by interpreting the /value/ byte array as a UTF-8 byte
+ # stream.
+ fields.setdefault(name, []).append(value)
+ # 4.1 39. return to the "Field" step above
+ return fields
+
+
+def _read_name(socket):
+ # 4.1 33. let /name/ be empty byte arrays
+ name = ''
+ while True:
+ # 4.1 34. read a byte from the server
+ ch = receive_bytes(socket, 1)
+ if ch == '\r': # 0x0D
+ return None
+ elif ch == '\n': # 0x0A
+ raise Exception(
+ 'Unexpected LF when reading header name %r' % name)
+ elif ch == ':': # 0x3A
+ return name
+ elif ch >= 'A' and ch <= 'Z': # range 0x31 to 0x5A
+ ch = chr(ord(ch) + 0x20)
+ name += ch
+ else:
+ name += ch
+
+
+def _skip_spaces(socket):
+ # 4.1 35. read a byte from the server
+ while True:
+ ch = receive_bytes(socket, 1)
+ if ch == ' ': # 0x20
+ continue
+ return ch
+
+
+def _read_value(socket, ch):
+ # 4.1 33. let /value/ be empty byte arrays
+ value = ''
+ # 4.1 36. read a byte from server.
+ while True:
+ if ch == '\r': # 0x0D
+ return value
+ elif ch == '\n': # 0x0A
+ raise Exception(
+ 'Unexpected LF when reading header value %r' % value)
+ else:
+ value += ch
+ ch = receive_bytes(socket, 1)
+
+
+def read_frame_header(socket):
+ received = receive_bytes(socket, 2)
+
+ first_byte = ord(received[0])
+ fin = (first_byte >> 7) & 1
+ rsv1 = (first_byte >> 6) & 1
+ rsv2 = (first_byte >> 5) & 1
+ rsv3 = (first_byte >> 4) & 1
+ opcode = first_byte & 0xf
+
+ second_byte = ord(received[1])
+ mask = (second_byte >> 7) & 1
+ payload_length = second_byte & 0x7f
+
+ if mask != 0:
+ raise Exception(
+ 'Mask bit must be 0 for frames coming from server')
+
+ if payload_length == 127:
+ extended_payload_length = receive_bytes(socket, 8)
+ payload_length = struct.unpack(
+ '!Q', extended_payload_length)[0]
+ if payload_length > 0x7FFFFFFFFFFFFFFF:
+ raise Exception('Extended payload length >= 2^63')
+ elif payload_length == 126:
+ extended_payload_length = receive_bytes(socket, 2)
+ payload_length = struct.unpack(
+ '!H', extended_payload_length)[0]
+
+ return fin, rsv1, rsv2, rsv3, opcode, payload_length
+
+
+class _TLSSocket(object):
+ """Wrapper for a TLS connection."""
+
+ def __init__(self, raw_socket):
+ self._ssl = socket.ssl(raw_socket)
+
+ def send(self, bytes):
+ return self._ssl.write(bytes)
+
+ def recv(self, size=-1):
+ return self._ssl.read(size)
+
+ def close(self):
+ # Nothing to do.
+ pass
+
+
+class HttpStatusException(Exception):
+ """This exception will be raised when unexpected http status code was
+ received as a result of handshake.
+ """
+
+ def __init__(self, name, status):
+ super(HttpStatusException, self).__init__(name)
+ self.status = status
+
+
+class WebSocketHandshake(object):
+ """Opening handshake processor for the WebSocket protocol (RFC 6455)."""
+
+ def __init__(self, options):
+ self._logger = util.get_class_logger(self)
+
+ self._options = options
+
+ def handshake(self, socket):
+ """Handshake WebSocket.
+
+ Raises:
+ Exception: handshake failed.
+ """
+
+ self._socket = socket
+
+ request_line = _method_line(self._options.resource)
+ self._logger.debug('Opening handshake Request-Line: %r', request_line)
+ self._socket.sendall(request_line)
+
+ fields = []
+ fields.append(_UPGRADE_HEADER)
+ fields.append(_CONNECTION_HEADER)
+
+ fields.append(_format_host_header(
+ self._options.server_host,
+ self._options.server_port,
+ self._options.use_tls))
+
+ if self._options.version is 8:
+ fields.append(_sec_origin_header(self._options.origin))
+ else:
+ fields.append(_origin_header(self._options.origin))
+
+ original_key = os.urandom(16)
+ key = base64.b64encode(original_key)
+ self._logger.debug(
+ 'Sec-WebSocket-Key: %s (%s)', key, util.hexify(original_key))
+ fields.append('Sec-WebSocket-Key: %s\r\n' % key)
+
+ fields.append('Sec-WebSocket-Version: %d\r\n' % self._options.version)
+
+ # Setting up extensions.
+ if len(self._options.extensions) > 0:
+ fields.append('Sec-WebSocket-Extensions: %s\r\n' %
+ ', '.join(self._options.extensions))
+
+ self._logger.debug('Opening handshake request headers: %r', fields)
+
+ for field in fields:
+ self._socket.sendall(field)
+ self._socket.sendall('\r\n')
+
+ self._logger.info('Sent opening handshake request')
+
+ field = ''
+ while True:
+ ch = receive_bytes(self._socket, 1)
+ field += ch
+ if ch == '\n':
+ break
+
+ self._logger.debug('Opening handshake Response-Line: %r', field)
+
+ if len(field) < 7 or not field.endswith('\r\n'):
+ raise Exception('Wrong status line: %r' % field)
+ m = re.match('[^ ]* ([^ ]*) .*', field)
+ if m is None:
+ raise Exception(
+ 'No HTTP status code found in status line: %r' % field)
+ code = m.group(1)
+ if not re.match('[0-9][0-9][0-9]', code):
+ raise Exception(
+ 'HTTP status code %r is not three digit in status line: %r' %
+ (code, field))
+ if code != '101':
+ raise HttpStatusException(
+ 'Expected HTTP status code 101 but found %r in status line: '
+ '%r' % (code, field), int(code))
+ fields = _read_fields(self._socket)
+ ch = receive_bytes(self._socket, 1)
+ if ch != '\n': # 0x0A
+ raise Exception('Expected LF but found: %r' % ch)
+
+ self._logger.debug('Opening handshake response headers: %r', fields)
+
+ # Check /fields/
+ if len(fields['upgrade']) != 1:
+ raise Exception(
+ 'Multiple Upgrade headers found: %s' % fields['upgrade'])
+ if len(fields['connection']) != 1:
+ raise Exception(
+ 'Multiple Connection headers found: %s' % fields['connection'])
+ if fields['upgrade'][0] != 'websocket':
+ raise Exception(
+ 'Unexpected Upgrade header value: %s' % fields['upgrade'][0])
+ if fields['connection'][0].lower() != 'upgrade':
+ raise Exception(
+ 'Unexpected Connection header value: %s' %
+ fields['connection'][0])
+
+ if len(fields['sec-websocket-accept']) != 1:
+ raise Exception(
+ 'Multiple Sec-WebSocket-Accept headers found: %s' %
+ fields['sec-websocket-accept'])
+
+ accept = fields['sec-websocket-accept'][0]
+
+ # Validate
+ try:
+ decoded_accept = base64.b64decode(accept)
+ except TypeError, e:
+ raise HandshakeException(
+ 'Illegal value for header Sec-WebSocket-Accept: ' + accept)
+
+ if len(decoded_accept) != 20:
+ raise HandshakeException(
+ 'Decoded value of Sec-WebSocket-Accept is not 20-byte long')
+
+ self._logger.debug('Actual Sec-WebSocket-Accept: %r (%s)',
+ accept, util.hexify(decoded_accept))
+
+ original_expected_accept = util.sha1_hash(
+ key + WEBSOCKET_ACCEPT_UUID).digest()
+ expected_accept = base64.b64encode(original_expected_accept)
+
+ self._logger.debug('Expected Sec-WebSocket-Accept: %r (%s)',
+ expected_accept,
+ util.hexify(original_expected_accept))
+
+ if accept != expected_accept:
+ raise Exception(
+ 'Invalid Sec-WebSocket-Accept header: %r (expected) != %r '
+ '(actual)' % (accept, expected_accept))
+
+ server_extensions_header = fields.get('sec-websocket-extensions')
+ accepted_extensions = []
+ if server_extensions_header is not None:
+ accepted_extensions = common.parse_extensions(
+ ', '.join(server_extensions_header))
+
+ # Scan accepted extension list to check if there is any unrecognized
+ # extensions or extensions we didn't request in it. Then, for
+ # extensions we request, parse them and store parameters. They will be
+ # used later by each extension.
+ deflate_frame_accepted = False
+ mux_accepted = False
+ for extension in accepted_extensions:
+ if extension.name() == _DEFLATE_FRAME_EXTENSION:
+ if self._options.use_deflate_frame:
+ deflate_frame_accepted = True
+ continue
+ if extension.name() == _MUX_EXTENSION:
+ if self._options.use_mux:
+ mux_accepted = True
+ continue
+ if extension.name() == _PERMESSAGE_DEFLATE_EXTENSION:
+ checker = self._options.check_permessage_deflate
+ if checker:
+ checker(extension)
+ continue
+
+ raise Exception(
+ 'Received unrecognized extension: %s' % extension.name())
+
+ # Let all extensions check the response for extension request.
+
+ if (self._options.use_deflate_frame and
+ not deflate_frame_accepted):
+ raise Exception('%s extension not accepted' %
+ _DEFLATE_FRAME_EXTENSION)
+
+ if self._options.use_mux and not mux_accepted:
+ raise Exception('%s extension not accepted' % _MUX_EXTENSION)
+
+
+class WebSocketHybi00Handshake(object):
+ """Opening handshake processor for the WebSocket protocol version HyBi 00.
+ """
+
+ def __init__(self, options, draft_field):
+ self._logger = util.get_class_logger(self)
+
+ self._options = options
+ self._draft_field = draft_field
+
+ def handshake(self, socket):
+ """Handshake WebSocket.
+
+ Raises:
+ Exception: handshake failed.
+ """
+
+ self._socket = socket
+
+ # 4.1 5. send request line.
+ request_line = _method_line(self._options.resource)
+ self._logger.debug('Opening handshake Request-Line: %r', request_line)
+ self._socket.sendall(request_line)
+ # 4.1 6. Let /fields/ be an empty list of strings.
+ fields = []
+ # 4.1 7. Add the string "Upgrade: WebSocket" to /fields/.
+ fields.append(_UPGRADE_HEADER_HIXIE75)
+ # 4.1 8. Add the string "Connection: Upgrade" to /fields/.
+ fields.append(_CONNECTION_HEADER)
+ # 4.1 9-12. Add Host: field to /fields/.
+ fields.append(_format_host_header(
+ self._options.server_host,
+ self._options.server_port,
+ self._options.use_tls))
+ # 4.1 13. Add Origin: field to /fields/.
+ fields.append(_origin_header(self._options.origin))
+ # TODO: 4.1 14 Add Sec-WebSocket-Protocol: field to /fields/.
+ # TODO: 4.1 15 Add cookie headers to /fields/.
+
+ # 4.1 16-23. Add Sec-WebSocket-Key<n> to /fields/.
+ self._number1, key1 = self._generate_sec_websocket_key()
+ self._logger.debug('Number1: %d', self._number1)
+ fields.append('Sec-WebSocket-Key1: %s\r\n' % key1)
+ self._number2, key2 = self._generate_sec_websocket_key()
+ self._logger.debug('Number2: %d', self._number1)
+ fields.append('Sec-WebSocket-Key2: %s\r\n' % key2)
+
+ fields.append('Sec-WebSocket-Draft: %s\r\n' % self._draft_field)
+
+ # 4.1 24. For each string in /fields/, in a random order: send the
+ # string, encoded as UTF-8, followed by a UTF-8 encoded U+000D CARRIAGE
+ # RETURN U+000A LINE FEED character pair (CRLF).
+ random.shuffle(fields)
+
+ self._logger.debug('Opening handshake request headers: %r', fields)
+ for field in fields:
+ self._socket.sendall(field)
+
+ # 4.1 25. send a UTF-8-encoded U+000D CARRIAGE RETURN U+000A LINE FEED
+ # character pair (CRLF).
+ self._socket.sendall('\r\n')
+ # 4.1 26. let /key3/ be a string consisting of eight random bytes (or
+ # equivalently, a random 64 bit integer encoded in a big-endian order).
+ self._key3 = self._generate_key3()
+ # 4.1 27. send /key3/ to the server.
+ self._socket.sendall(self._key3)
+ self._logger.debug(
+ 'Key3: %r (%s)', self._key3, util.hexify(self._key3))
+
+ self._logger.info('Sent opening handshake request')
+
+ # 4.1 28. Read bytes from the server until either the connection
+ # closes, or a 0x0A byte is read. let /field/ be these bytes, including
+ # the 0x0A bytes.
+ field = ''
+ while True:
+ ch = receive_bytes(self._socket, 1)
+ field += ch
+ if ch == '\n':
+ break
+
+ self._logger.debug('Opening handshake Response-Line: %r', field)
+
+ # if /field/ is not at least seven bytes long, or if the last
+ # two bytes aren't 0x0D and 0x0A respectively, or if it does not
+ # contain at least two 0x20 bytes, then fail the WebSocket connection
+ # and abort these steps.
+ if len(field) < 7 or not field.endswith('\r\n'):
+ raise Exception('Wrong status line: %r' % field)
+ m = re.match('[^ ]* ([^ ]*) .*', field)
+ if m is None:
+ raise Exception('No code found in status line: %r' % field)
+ # 4.1 29. let /code/ be the substring of /field/ that starts from the
+ # byte after the first 0x20 byte, and ends with the byte before the
+ # second 0x20 byte.
+ code = m.group(1)
+ # 4.1 30. if /code/ is not three bytes long, or if any of the bytes in
+ # /code/ are not in the range 0x30 to 0x90, then fail the WebSocket
+ # connection and abort these steps.
+ if not re.match('[0-9][0-9][0-9]', code):
+ raise Exception(
+ 'HTTP status code %r is not three digit in status line: %r' %
+ (code, field))
+ # 4.1 31. if /code/, interpreted as UTF-8, is "101", then move to the
+ # next step.
+ if code != '101':
+ raise HttpStatusException(
+ 'Expected HTTP status code 101 but found %r in status line: '
+ '%r' % (code, field), int(code))
+ # 4.1 32-39. read fields into /fields/
+ fields = _read_fields(self._socket)
+
+ self._logger.debug('Opening handshake response headers: %r', fields)
+
+ # 4.1 40. _Fields processing_
+ # read a byte from server
+ ch = receive_bytes(self._socket, 1)
+ if ch != '\n': # 0x0A
+ raise Exception('Expected LF but found %r' % ch)
+ # 4.1 41. check /fields/
+ if len(fields['upgrade']) != 1:
+ raise Exception(
+ 'Multiple Upgrade headers found: %s' % fields['upgrade'])
+ if len(fields['connection']) != 1:
+ raise Exception(
+ 'Multiple Connection headers found: %s' % fields['connection'])
+ if len(fields['sec-websocket-origin']) != 1:
+ raise Exception(
+ 'Multiple Sec-WebSocket-Origin headers found: %s' %
+ fields['sec-sebsocket-origin'])
+ if len(fields['sec-websocket-location']) != 1:
+ raise Exception(
+ 'Multiple Sec-WebSocket-Location headers found: %s' %
+ fields['sec-sebsocket-location'])
+ # TODO(ukai): protocol
+ # if the entry's name is "upgrade"
+ # if the value is not exactly equal to the string "WebSocket",
+ # then fail the WebSocket connection and abort these steps.
+ if fields['upgrade'][0] != 'WebSocket':
+ raise Exception(
+ 'Unexpected Upgrade header value: %s' % fields['upgrade'][0])
+ # if the entry's name is "connection"
+ # if the value, converted to ASCII lowercase, is not exactly equal
+ # to the string "upgrade", then fail the WebSocket connection and
+ # abort these steps.
+ if fields['connection'][0].lower() != 'upgrade':
+ raise Exception(
+ 'Unexpected Connection header value: %s' %
+ fields['connection'][0])
+ # TODO(ukai): check origin, location, cookie, ..
+
+ # 4.1 42. let /challenge/ be the concatenation of /number_1/,
+ # expressed as a big endian 32 bit integer, /number_2/, expressed
+ # as big endian 32 bit integer, and the eight bytes of /key_3/ in the
+ # order they were sent on the wire.
+ challenge = struct.pack('!I', self._number1)
+ challenge += struct.pack('!I', self._number2)
+ challenge += self._key3
+
+ self._logger.debug(
+ 'Challenge: %r (%s)', challenge, util.hexify(challenge))
+
+ # 4.1 43. let /expected/ be the MD5 fingerprint of /challenge/ as a
+ # big-endian 128 bit string.
+ expected = util.md5_hash(challenge).digest()
+ self._logger.debug(
+ 'Expected challenge response: %r (%s)',
+ expected, util.hexify(expected))
+
+ # 4.1 44. read sixteen bytes from the server.
+ # let /reply/ be those bytes.
+ reply = receive_bytes(self._socket, 16)
+ self._logger.debug(
+ 'Actual challenge response: %r (%s)', reply, util.hexify(reply))
+
+ # 4.1 45. if /reply/ does not exactly equal /expected/, then fail
+ # the WebSocket connection and abort these steps.
+ if expected != reply:
+ raise Exception(
+ 'Bad challenge response: %r (expected) != %r (actual)' %
+ (expected, reply))
+ # 4.1 46. The *WebSocket connection is established*.
+
+ def _generate_sec_websocket_key(self):
+ # 4.1 16. let /spaces_n/ be a random integer from 1 to 12 inclusive.
+ spaces = random.randint(1, 12)
+ # 4.1 17. let /max_n/ be the largest integer not greater than
+ # 4,294,967,295 divided by /spaces_n/.
+ maxnum = 4294967295 / spaces
+ # 4.1 18. let /number_n/ be a random integer from 0 to /max_n/
+ # inclusive.
+ number = random.randint(0, maxnum)
+ # 4.1 19. let /product_n/ be the result of multiplying /number_n/ and
+ # /spaces_n/ together.
+ product = number * spaces
+ # 4.1 20. let /key_n/ be a string consisting of /product_n/, expressed
+ # in base ten using the numerals in the range U+0030 DIGIT ZERO (0) to
+ # U+0039 DIGIT NINE (9).
+ key = str(product)
+ # 4.1 21. insert between one and twelve random characters from the
+ # range U+0021 to U+002F and U+003A to U+007E into /key_n/ at random
+ # positions.
+ available_chars = range(0x21, 0x2f + 1) + range(0x3a, 0x7e + 1)
+ n = random.randint(1, 12)
+ for _ in xrange(n):
+ ch = random.choice(available_chars)
+ pos = random.randint(0, len(key))
+ key = key[0:pos] + chr(ch) + key[pos:]
+ # 4.1 22. insert /spaces_n/ U+0020 SPACE characters into /key_n/ at
+ # random positions other than start or end of the string.
+ for _ in xrange(spaces):
+ pos = random.randint(1, len(key) - 1)
+ key = key[0:pos] + ' ' + key[pos:]
+ return number, key
+
+ def _generate_key3(self):
+ # 4.1 26. let /key3/ be a string consisting of eight random bytes (or
+ # equivalently, a random 64 bit integer encoded in a big-endian order).
+ return ''.join([chr(random.randint(0, 255)) for _ in xrange(8)])
+
+
+class WebSocketHixie75Handshake(object):
+ """WebSocket handshake processor for IETF Hixie 75."""
+
+ _EXPECTED_RESPONSE = (
+ 'HTTP/1.1 101 Web Socket Protocol Handshake\r\n' +
+ _UPGRADE_HEADER_HIXIE75 +
+ _CONNECTION_HEADER)
+
+ def __init__(self, options):
+ self._logger = util.get_class_logger(self)
+
+ self._options = options
+
+ def _skip_headers(self):
+ terminator = '\r\n\r\n'
+ pos = 0
+ while pos < len(terminator):
+ received = receive_bytes(self._socket, 1)
+ if received == terminator[pos]:
+ pos += 1
+ elif received == terminator[0]:
+ pos = 1
+ else:
+ pos = 0
+
+ def handshake(self, socket):
+ self._socket = socket
+
+ request_line = _method_line(self._options.resource)
+ self._logger.debug('Opening handshake Request-Line: %r', request_line)
+ self._socket.sendall(request_line)
+
+ headers = _UPGRADE_HEADER_HIXIE75 + _CONNECTION_HEADER
+ headers += _format_host_header(
+ self._options.server_host,
+ self._options.server_port,
+ self._options.use_tls)
+ headers += _origin_header(self._options.origin)
+ self._logger.debug('Opening handshake request headers: %r', headers)
+ self._socket.sendall(headers)
+
+ self._socket.sendall('\r\n')
+
+ self._logger.info('Sent opening handshake request')
+
+ for expected_char in WebSocketHixie75Handshake._EXPECTED_RESPONSE:
+ received = receive_bytes(self._socket, 1)
+ if expected_char != received:
+ raise Exception('Handshake failure')
+ # We cut corners and skip other headers.
+ self._skip_headers()
+
+
+class WebSocketStream(object):
+ """Frame processor for the WebSocket protocol (RFC 6455)."""
+
+ def __init__(self, socket, handshake):
+ self._handshake = handshake
+ self._socket = socket
+
+ # Filters applied to application data part of data frames.
+ self._outgoing_frame_filter = None
+ self._incoming_frame_filter = None
+
+ if self._handshake._options.use_deflate_frame:
+ self._outgoing_frame_filter = (
+ util._RFC1979Deflater(None, False))
+ self._incoming_frame_filter = util._RFC1979Inflater()
+
+ self._fragmented = False
+
+ def _mask_hybi(self, s):
+ # TODO(tyoshino): os.urandom does open/read/close for every call. If
+ # performance matters, change this to some library call that generates
+ # cryptographically secure pseudo random number sequence.
+ masking_nonce = os.urandom(4)
+ result = [masking_nonce]
+ count = 0
+ for c in s:
+ result.append(chr(ord(c) ^ ord(masking_nonce[count])))
+ count = (count + 1) % len(masking_nonce)
+ return ''.join(result)
+
+ def send_frame_of_arbitrary_bytes(self, header, body):
+ self._socket.sendall(header + self._mask_hybi(body))
+
+ def send_data(self, payload, frame_type, end=True, mask=True,
+ rsv1=0, rsv2=0, rsv3=0):
+ if self._outgoing_frame_filter is not None:
+ payload = self._outgoing_frame_filter.filter(payload)
+
+ if self._fragmented:
+ opcode = OPCODE_CONTINUATION
+ else:
+ opcode = frame_type
+
+ if end:
+ self._fragmented = False
+ fin = 1
+ else:
+ self._fragmented = True
+ fin = 0
+
+ if self._handshake._options.use_deflate_frame:
+ rsv1 = 1
+
+ if mask:
+ mask_bit = 1 << 7
+ else:
+ mask_bit = 0
+
+ header = chr(fin << 7 | rsv1 << 6 | rsv2 << 5 | rsv3 << 4 | opcode)
+ payload_length = len(payload)
+ if payload_length <= 125:
+ header += chr(mask_bit | payload_length)
+ elif payload_length < 1 << 16:
+ header += chr(mask_bit | 126) + struct.pack('!H', payload_length)
+ elif payload_length < 1 << 63:
+ header += chr(mask_bit | 127) + struct.pack('!Q', payload_length)
+ else:
+ raise Exception('Too long payload (%d byte)' % payload_length)
+ if mask:
+ payload = self._mask_hybi(payload)
+ self._socket.sendall(header + payload)
+
+ def send_binary(self, payload, end=True, mask=True):
+ self.send_data(payload, OPCODE_BINARY, end, mask)
+
+ def send_text(self, payload, end=True, mask=True):
+ self.send_data(payload.encode('utf-8'), OPCODE_TEXT, end, mask)
+
+ def _assert_receive_data(self, payload, opcode, fin, rsv1, rsv2, rsv3):
+ (actual_fin, actual_rsv1, actual_rsv2, actual_rsv3, actual_opcode,
+ payload_length) = read_frame_header(self._socket)
+
+ if actual_opcode != opcode:
+ raise Exception(
+ 'Unexpected opcode: %d (expected) vs %d (actual)' %
+ (opcode, actual_opcode))
+
+ if actual_fin != fin:
+ raise Exception(
+ 'Unexpected fin: %d (expected) vs %d (actual)' %
+ (fin, actual_fin))
+
+ if rsv1 is None:
+ rsv1 = 0
+ if self._handshake._options.use_deflate_frame:
+ rsv1 = 1
+
+ if rsv2 is None:
+ rsv2 = 0
+
+ if rsv3 is None:
+ rsv3 = 0
+
+ if actual_rsv1 != rsv1:
+ raise Exception(
+ 'Unexpected rsv1: %r (expected) vs %r (actual)' %
+ (rsv1, actual_rsv1))
+
+ if actual_rsv2 != rsv2:
+ raise Exception(
+ 'Unexpected rsv2: %r (expected) vs %r (actual)' %
+ (rsv2, actual_rsv2))
+
+ if actual_rsv3 != rsv3:
+ raise Exception(
+ 'Unexpected rsv3: %r (expected) vs %r (actual)' %
+ (rsv3, actual_rsv3))
+
+ received = receive_bytes(self._socket, payload_length)
+
+ if self._incoming_frame_filter is not None:
+ received = self._incoming_frame_filter.filter(received)
+
+ if len(received) != len(payload):
+ raise Exception(
+ 'Unexpected payload length: %d (expected) vs %d (actual)' %
+ (len(payload), len(received)))
+
+ if payload != received:
+ raise Exception(
+ 'Unexpected payload: %r (expected) vs %r (actual)' %
+ (payload, received))
+
+ def assert_receive_binary(self, payload, opcode=OPCODE_BINARY, fin=1,
+ rsv1=None, rsv2=None, rsv3=None):
+ self._assert_receive_data(payload, opcode, fin, rsv1, rsv2, rsv3)
+
+ def assert_receive_text(self, payload, opcode=OPCODE_TEXT, fin=1,
+ rsv1=None, rsv2=None, rsv3=None):
+ self._assert_receive_data(payload.encode('utf-8'), opcode, fin, rsv1,
+ rsv2, rsv3)
+
+ def _build_close_frame(self, code, reason, mask):
+ frame = chr(1 << 7 | OPCODE_CLOSE)
+
+ if code is not None:
+ body = struct.pack('!H', code) + reason.encode('utf-8')
+ else:
+ body = ''
+ if mask:
+ frame += chr(1 << 7 | len(body)) + self._mask_hybi(body)
+ else:
+ frame += chr(len(body)) + body
+ return frame
+
+ def send_close(self, code, reason):
+ self._socket.sendall(
+ self._build_close_frame(code, reason, True))
+
+ def assert_receive_close(self, code, reason):
+ expected_frame = self._build_close_frame(code, reason, False)
+ actual_frame = receive_bytes(self._socket, len(expected_frame))
+ if actual_frame != expected_frame:
+ raise Exception(
+ 'Unexpected close frame: %r (expected) vs %r (actual)' %
+ (expected_frame, actual_frame))
+
+
+class WebSocketStreamHixie75(object):
+ """Frame processor for the WebSocket protocol version Hixie 75 and HyBi 00.
+ """
+
+ _CLOSE_FRAME = '\xff\x00'
+
+ def __init__(self, socket, unused_handshake):
+ self._socket = socket
+
+ def send_frame_of_arbitrary_bytes(self, header, body):
+ self._socket.sendall(header + body)
+
+ def send_data(self, payload, unused_frame_typem, unused_end, unused_mask):
+ frame = ''.join(['\x00', payload, '\xff'])
+ self._socket.sendall(frame)
+
+ def send_binary(self, unused_payload, unused_end, unused_mask):
+ pass
+
+ def send_text(self, payload, unused_end, unused_mask):
+ encoded_payload = payload.encode('utf-8')
+ frame = ''.join(['\x00', encoded_payload, '\xff'])
+ self._socket.sendall(frame)
+
+ def assert_receive_binary(self, payload, opcode=OPCODE_BINARY, fin=1,
+ rsv1=0, rsv2=0, rsv3=0):
+ raise Exception('Binary frame is not supported in hixie75')
+
+ def assert_receive_text(self, payload):
+ received = receive_bytes(self._socket, 1)
+
+ if received != '\x00':
+ raise Exception(
+ 'Unexpected frame type: %d (expected) vs %d (actual)' %
+ (0, ord(received)))
+
+ received = receive_bytes(self._socket, len(payload) + 1)
+ if received[-1] != '\xff':
+ raise Exception(
+ 'Termination expected: 0xff (expected) vs %r (actual)' %
+ received)
+
+ if received[0:-1] != payload:
+ raise Exception(
+ 'Unexpected payload: %r (expected) vs %r (actual)' %
+ (payload, received[0:-1]))
+
+ def send_close(self, code, reason):
+ self._socket.sendall(self._CLOSE_FRAME)
+
+ def assert_receive_close(self, unused_code, unused_reason):
+ closing = receive_bytes(self._socket, len(self._CLOSE_FRAME))
+ if closing != self._CLOSE_FRAME:
+ raise Exception('Didn\'t receive closing handshake')
+
+
+class ClientOptions(object):
+ """Holds option values to configure the Client object."""
+
+ def __init__(self):
+ self.version = 13
+ self.server_host = ''
+ self.origin = ''
+ self.resource = ''
+ self.server_port = -1
+ self.socket_timeout = 1000
+ self.use_tls = False
+ self.extensions = []
+ # Enable deflate-application-data.
+ self.use_deflate_frame = False
+ # Enable mux
+ self.use_mux = False
+
+ def enable_deflate_frame(self):
+ self.use_deflate_frame = True
+ self.extensions.append(_DEFLATE_FRAME_EXTENSION)
+
+ def enable_mux(self):
+ self.use_mux = True
+ self.extensions.append(_MUX_EXTENSION)
+
+
+def connect_socket_with_retry(host, port, timeout, use_tls,
+ retry=10, sleep_sec=0.1):
+ retry_count = 0
+ while retry_count < retry:
+ try:
+ s = socket.socket()
+ s.settimeout(timeout)
+ s.connect((host, port))
+ if use_tls:
+ return _TLSSocket(s)
+ return s
+ except socket.error, e:
+ if e.errno != errno.ECONNREFUSED:
+ raise
+ else:
+ retry_count = retry_count + 1
+ time.sleep(sleep_sec)
+
+ return None
+
+
+class Client(object):
+ """WebSocket client."""
+
+ def __init__(self, options, handshake, stream_class):
+ self._logger = util.get_class_logger(self)
+
+ self._options = options
+ self._socket = None
+
+ self._handshake = handshake
+ self._stream_class = stream_class
+
+ def connect(self):
+ self._socket = connect_socket_with_retry(
+ self._options.server_host,
+ self._options.server_port,
+ self._options.socket_timeout,
+ self._options.use_tls)
+
+ self._handshake.handshake(self._socket)
+
+ self._stream = self._stream_class(self._socket, self._handshake)
+
+ self._logger.info('Connection established')
+
+ def send_frame_of_arbitrary_bytes(self, header, body):
+ self._stream.send_frame_of_arbitrary_bytes(header, body)
+
+ def send_message(self, message, end=True, binary=False, raw=False,
+ mask=True):
+ if binary:
+ self._stream.send_binary(message, end, mask)
+ elif raw:
+ self._stream.send_data(message, OPCODE_TEXT, end, mask)
+ else:
+ self._stream.send_text(message, end, mask)
+
+ def assert_receive(self, payload, binary=False):
+ if binary:
+ self._stream.assert_receive_binary(payload)
+ else:
+ self._stream.assert_receive_text(payload)
+
+ def send_close(self, code=STATUS_NORMAL_CLOSURE, reason=''):
+ self._stream.send_close(code, reason)
+
+ def assert_receive_close(self, code=STATUS_NORMAL_CLOSURE, reason=''):
+ self._stream.assert_receive_close(code, reason)
+
+ def close_socket(self):
+ self._socket.close()
+
+ def assert_connection_closed(self):
+ try:
+ read_data = receive_bytes(self._socket, 1)
+ except Exception, e:
+ if str(e).find(
+ 'Connection closed before receiving requested length ') == 0:
+ return
+ try:
+ error_number, message = e
+ for error_name in ['ECONNRESET', 'WSAECONNRESET']:
+ if (error_name in dir(errno) and
+ error_number == getattr(errno, error_name)):
+ return
+ except:
+ raise e
+ raise e
+
+ raise Exception('Connection is not closed (Read: %r)' % read_data)
+
+
+def create_client(options):
+ return Client(
+ options, WebSocketHandshake(options), WebSocketStream)
+
+
+def create_client_hybi00(options):
+ return Client(
+ options,
+ WebSocketHybi00Handshake(options, '0'),
+ WebSocketStreamHixie75)
+
+
+def create_client_hixie75(options):
+ return Client(
+ options, WebSocketHixie75Handshake(options), WebSocketStreamHixie75)
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/endtoend_with_external_server.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/endtoend_with_external_server.py
new file mode 100755
index 00000000000..47f86fdb416
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/endtoend_with_external_server.py
@@ -0,0 +1,67 @@
+#!/usr/bin/env python
+#
+# Copyright 2011, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+"""Test for end-to-end with external server.
+
+This test is not run by run_all.py because it requires some preparations.
+If you would like to run this test correctly, launch Apache with mod_python
+and mod_pywebsocket manually. In addition, you should pass allow_draft75 option
+and example path as handler_scan option and Apache's DocumentRoot.
+"""
+
+
+import optparse
+import sys
+import test.test_endtoend
+import unittest
+
+
+_DEFAULT_WEB_SOCKET_PORT = 80
+
+
+class EndToEndTestWithExternalServer(test.test_endtoend.EndToEndTest):
+ pass
+
+if __name__ == '__main__':
+ parser = optparse.OptionParser()
+ parser.add_option('-p', '--port', dest='port', type='int',
+ default=_DEFAULT_WEB_SOCKET_PORT,
+ help='external test server port.')
+ (options, args) = parser.parse_args()
+
+ test.test_endtoend._use_external_server = True
+ test.test_endtoend._external_server_port = options.port
+
+ unittest.main(argv=[sys.argv[0]])
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/mock.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/mock.py
new file mode 100644
index 00000000000..6bffcac48dc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/mock.py
@@ -0,0 +1,221 @@
+# Copyright 2011, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+"""Mocks for testing.
+"""
+
+
+import Queue
+import threading
+
+from mod_pywebsocket import common
+from mod_pywebsocket.stream import StreamHixie75
+
+
+class _MockConnBase(object):
+ """Base class of mocks for mod_python.apache.mp_conn.
+
+ This enables tests to check what is written to a (mock) mp_conn.
+ """
+
+ def __init__(self):
+ self._write_data = []
+ self.remote_addr = 'fake_address'
+
+ def write(self, data):
+ """Override mod_python.apache.mp_conn.write."""
+
+ self._write_data.append(data)
+
+ def written_data(self):
+ """Get bytes written to this mock."""
+
+ return ''.join(self._write_data)
+
+
+class MockConn(_MockConnBase):
+ """Mock for mod_python.apache.mp_conn.
+
+ This enables tests to specify what should be read from a (mock) mp_conn as
+ well as to check what is written to it.
+ """
+
+ def __init__(self, read_data):
+ """Constructs an instance.
+
+ Args:
+ read_data: bytes that should be returned when read* methods are
+ called.
+ """
+
+ _MockConnBase.__init__(self)
+ self._read_data = read_data
+ self._read_pos = 0
+
+ def readline(self):
+ """Override mod_python.apache.mp_conn.readline."""
+
+ if self._read_pos >= len(self._read_data):
+ return ''
+ end_index = self._read_data.find('\n', self._read_pos) + 1
+ if not end_index:
+ end_index = len(self._read_data)
+ return self._read_up_to(end_index)
+
+ def read(self, length):
+ """Override mod_python.apache.mp_conn.read."""
+
+ if self._read_pos >= len(self._read_data):
+ return ''
+ end_index = min(len(self._read_data), self._read_pos + length)
+ return self._read_up_to(end_index)
+
+ def _read_up_to(self, end_index):
+ line = self._read_data[self._read_pos:end_index]
+ self._read_pos = end_index
+ return line
+
+
+class MockBlockingConn(_MockConnBase):
+ """Blocking mock for mod_python.apache.mp_conn.
+
+ This enables tests to specify what should be read from a (mock) mp_conn as
+ well as to check what is written to it.
+ Callers of read* methods will block if there is no bytes available.
+ """
+
+ def __init__(self):
+ _MockConnBase.__init__(self)
+ self._queue = Queue.Queue()
+
+ def readline(self):
+ """Override mod_python.apache.mp_conn.readline."""
+ line = ''
+ while True:
+ c = self._queue.get()
+ line += c
+ if c == '\n':
+ return line
+
+ def read(self, length):
+ """Override mod_python.apache.mp_conn.read."""
+
+ data = ''
+ for unused in range(length):
+ data += self._queue.get()
+ return data
+
+ def put_bytes(self, bytes):
+ """Put bytes to be read from this mock.
+
+ Args:
+ bytes: bytes to be read.
+ """
+
+ for byte in bytes:
+ self._queue.put(byte)
+
+
+class MockTable(dict):
+ """Mock table.
+
+ This mimics mod_python mp_table. Note that only the methods used by
+ tests are overridden.
+ """
+
+ def __init__(self, copy_from={}):
+ if isinstance(copy_from, dict):
+ copy_from = copy_from.items()
+ for key, value in copy_from:
+ self.__setitem__(key, value)
+
+ def __getitem__(self, key):
+ return super(MockTable, self).__getitem__(key.lower())
+
+ def __setitem__(self, key, value):
+ super(MockTable, self).__setitem__(key.lower(), value)
+
+ def get(self, key, def_value=None):
+ return super(MockTable, self).get(key.lower(), def_value)
+
+
+class MockRequest(object):
+ """Mock request.
+
+ This mimics mod_python request.
+ """
+
+ def __init__(self, uri=None, headers_in={}, connection=None, method='GET',
+ protocol='HTTP/1.1', is_https=False):
+ """Construct an instance.
+
+ Arguments:
+ uri: URI of the request.
+ headers_in: Request headers.
+ connection: Connection used for the request.
+ method: request method.
+ is_https: Whether this request is over SSL.
+
+ See the document of mod_python Request for details.
+ """
+ self.uri = uri
+ self.unparsed_uri = uri
+ self.connection = connection
+ self.method = method
+ self.protocol = protocol
+ self.headers_in = MockTable(headers_in)
+ # self.is_https_ needs to be accessible from tests. To avoid name
+ # conflict with self.is_https(), it is named as such.
+ self.is_https_ = is_https
+ self.ws_stream = StreamHixie75(self, True)
+ self.ws_close_code = None
+ self.ws_close_reason = None
+ self.ws_version = common.VERSION_HYBI00
+ self.ws_deflate = False
+
+ def is_https(self):
+ """Return whether this request is over SSL."""
+ return self.is_https_
+
+
+class MockDispatcher(object):
+ """Mock for dispatch.Dispatcher."""
+
+ def __init__(self):
+ self.do_extra_handshake_called = False
+
+ def do_extra_handshake(self, conn_context):
+ self.do_extra_handshake_called = True
+
+ def transfer_data(self, conn_context):
+ pass
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/mux_client_for_testing.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/mux_client_for_testing.py
new file mode 100644
index 00000000000..dd5435a8cc0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/mux_client_for_testing.py
@@ -0,0 +1,690 @@
+#!/usr/bin/env python
+#
+# Copyright 2012, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+"""WebSocket client utility for testing mux extension.
+
+This code should be independent from mod_pywebsocket. See the comment of
+client_for_testing.py.
+
+NOTE: This code is far from robust like client_for_testing.py.
+"""
+
+
+
+import Queue
+import base64
+import collections
+import email
+import email.parser
+import logging
+import math
+import os
+import random
+import socket
+import struct
+import threading
+
+from mod_pywebsocket import util
+
+from test import client_for_testing
+
+
+_CONTROL_CHANNEL_ID = 0
+_DEFAULT_CHANNEL_ID = 1
+
+_MUX_OPCODE_ADD_CHANNEL_REQUEST = 0
+_MUX_OPCODE_ADD_CHANNEL_RESPONSE = 1
+_MUX_OPCODE_FLOW_CONTROL = 2
+_MUX_OPCODE_DROP_CHANNEL = 3
+_MUX_OPCODE_NEW_CHANNEL_SLOT = 4
+
+
+class _ControlBlock:
+ def __init__(self, opcode):
+ self.opcode = opcode
+
+
+def _parse_handshake_response(response):
+ status_line, header_lines = response.split('\r\n', 1)
+
+ words = status_line.split(' ')
+ if len(words) < 3:
+ raise ValueError('Bad Status-Line syntax %r' % status_line)
+ [version, response_code] = words[:2]
+ if version != 'HTTP/1.1':
+ raise ValueError('Bad response version %r' % version)
+
+ if response_code != '101':
+ raise ValueError('Bad response code %r ' % response_code)
+ headers = email.parser.Parser().parsestr(header_lines)
+ return headers
+
+
+def _parse_channel_id(data, offset=0):
+ length = len(data)
+ remaining = length - offset
+
+ if remaining <= 0:
+ raise Exception('No channel id found')
+
+ channel_id = ord(data[offset])
+ channel_id_length = 1
+ if channel_id & 0xe0 == 0xe0:
+ if remaining < 4:
+ raise Exception('Invalid channel id format')
+ channel_id = struct.unpack('!L',
+ data[offset:offset+4])[0] & 0x1fffffff
+ channel_id_length = 4
+ elif channel_id & 0xc0 == 0xc0:
+ if remaining < 3:
+ raise Exception('Invalid channel id format')
+ channel_id = (((channel_id & 0x1f) << 16) +
+ struct.unpack('!H', data[offset+1:offset+3])[0])
+ channel_id_length = 3
+ elif channel_id & 0x80 == 0x80:
+ if remaining < 2:
+ raise Exception('Invalid channel id format')
+ channel_id = struct.unpack('!H', data[offset:offset+2])[0] & 0x3fff
+ channel_id_length = 2
+
+ return channel_id, channel_id_length
+
+
+def _parse_number(data, offset=0):
+ first_byte = ord(data[offset])
+ if (first_byte & 0x80) != 0:
+ raise Exception('The MSB of number field must be unset')
+ first_byte = first_byte & 0x7f
+ if first_byte == 127:
+ if offset + 9 > len(data):
+ raise Exception('Invalid number')
+ return struct.unpack('!Q', data[offset+1:offset+9])[0], 9
+ if first_byte == 126:
+ if offset + 3 > len(data):
+ raise Exception('Invalid number')
+ return struct.unpack('!H', data[offset+1:offset+3])[0], 3
+ return first_byte, 1
+
+
+def _parse_size_and_contents(data, offset=0):
+ size, advance = _parse_number(data, offset)
+ start_position = offset + advance
+ end_position = start_position + size
+ if len(data) < end_position:
+ raise Exception('Invalid size of control block (%d < %d)' % (
+ len(data), end_position))
+ return data[start_position:end_position], size + advance
+
+
+def _parse_control_blocks(data):
+ blocks = []
+ length = len(data)
+ pos = 0
+
+ while pos < length:
+ first_byte = ord(data[pos])
+ pos += 1
+ opcode = (first_byte >> 5) & 0x7
+ block = _ControlBlock(opcode)
+
+ # TODO(bashi): Support more opcode
+ if opcode == _MUX_OPCODE_ADD_CHANNEL_RESPONSE:
+ block.encode = first_byte & 3
+ block.rejected = (first_byte >> 4) & 1
+
+ channel_id, advance = _parse_channel_id(data, pos)
+ block.channel_id = channel_id
+ pos += advance
+
+ encoded_handshake, advance = _parse_size_and_contents(data, pos)
+ block.encoded_handshake = encoded_handshake
+ pos += advance
+ blocks.append(block)
+ elif opcode == _MUX_OPCODE_DROP_CHANNEL:
+ block.mux_error = (first_byte >> 4) & 1
+
+ channel_id, advance = _parse_channel_id(data, pos)
+ block.channel_id = channel_id
+ pos += advance
+
+ reason, advance = _parse_size_and_contents(data, pos)
+ if len(reason) == 0:
+ block.drop_code = None
+ block.drop_message = ''
+ elif len(reason) >= 2:
+ block.drop_code = struct.unpack('!H', reason[:2])[0]
+ block.drop_message = reason[2:]
+ else:
+ raise Exception('Invalid DropChannel')
+ pos += advance
+ blocks.append(block)
+ elif opcode == _MUX_OPCODE_FLOW_CONTROL:
+ channel_id, advance = _parse_channel_id(data, pos)
+ block.channel_id = channel_id
+ pos += advance
+ send_quota, advance = _parse_number(data, pos)
+ block.send_quota = send_quota
+ pos += advance
+ blocks.append(block)
+ elif opcode == _MUX_OPCODE_NEW_CHANNEL_SLOT:
+ fallback = first_byte & 1
+ slots, advance = _parse_number(data, pos)
+ pos += advance
+ send_quota, advance = _parse_number(data, pos)
+ pos += advance
+ if fallback == 1 and (slots != 0 or send_quota != 0):
+ raise Exception('slots and send_quota must be zero if F bit '
+ 'is set')
+ block.fallback = fallback
+ block.slots = slots
+ block.send_quota = send_quota
+ blocks.append(block)
+ else:
+ raise Exception(
+ 'Unsupported mux opcode %d received' % opcode)
+
+ return blocks
+
+
+def _encode_channel_id(channel_id):
+ if channel_id < 0:
+ raise ValueError('Channel id %d must not be negative' % channel_id)
+
+ if channel_id < 2 ** 7:
+ return chr(channel_id)
+ if channel_id < 2 ** 14:
+ return struct.pack('!H', 0x8000 + channel_id)
+ if channel_id < 2 ** 21:
+ first = chr(0xc0 + (channel_id >> 16))
+ return first + struct.pack('!H', channel_id & 0xffff)
+ if channel_id < 2 ** 29:
+ return struct.pack('!L', 0xe0000000 + channel_id)
+
+ raise ValueError('Channel id %d is too large' % channel_id)
+
+
+def _encode_number(number):
+ if number <= 125:
+ return chr(number)
+ elif number < (1 << 16):
+ return chr(0x7e) + struct.pack('!H', number)
+ elif number < (1 << 63):
+ return chr(0x7f) + struct.pack('!Q', number)
+ else:
+ raise Exception('Invalid number')
+
+
+def _create_add_channel_request(channel_id, encoded_handshake,
+ encoding=0):
+ length = len(encoded_handshake)
+ handshake_length = _encode_number(length)
+
+ first_byte = (_MUX_OPCODE_ADD_CHANNEL_REQUEST << 5) | encoding
+ return (chr(first_byte) + _encode_channel_id(channel_id) +
+ handshake_length + encoded_handshake)
+
+
+def _create_flow_control(channel_id, replenished_quota):
+ first_byte = (_MUX_OPCODE_FLOW_CONTROL << 5)
+ return (chr(first_byte) + _encode_channel_id(channel_id) +
+ _encode_number(replenished_quota))
+
+
+class _MuxReaderThread(threading.Thread):
+ """Mux reader thread.
+
+ Reads frames and passes them to the mux client. This thread accesses
+ private functions/variables of the mux client.
+ """
+
+ def __init__(self, mux):
+ threading.Thread.__init__(self)
+ self.setDaemon(True)
+ self._mux = mux
+ self._stop_requested = False
+
+ def _receive_message(self):
+ first_opcode = None
+ pending_payload = []
+ while not self._stop_requested:
+ fin, rsv1, rsv2, rsv3, opcode, payload_length = (
+ client_for_testing.read_frame_header(self._mux._socket))
+
+ if not first_opcode:
+ if opcode == client_for_testing.OPCODE_TEXT:
+ raise Exception('Received a text message on physical '
+ 'connection')
+ if opcode == client_for_testing.OPCODE_CONTINUATION:
+ raise Exception('Received an intermediate frame but '
+ 'fragmentation was not started')
+ if (opcode == client_for_testing.OPCODE_BINARY or
+ opcode == client_for_testing.OPCODE_PONG or
+ opcode == client_for_testing.OPCODE_PONG or
+ opcode == client_for_testing.OPCODE_CLOSE):
+ first_opcode = opcode
+ else:
+ raise Exception('Received an undefined opcode frame: %d' %
+ opcode)
+
+ elif opcode != client_for_testing.OPCODE_CONTINUATION:
+ raise Exception('Received a new opcode before '
+ 'terminating fragmentation')
+
+ payload = client_for_testing.receive_bytes(
+ self._mux._socket, payload_length)
+
+ if self._mux._incoming_frame_filter is not None:
+ payload = self._mux._incoming_frame_filter.filter(payload)
+
+ pending_payload.append(payload)
+
+ if fin:
+ break
+
+ if self._stop_requested:
+ return None, None
+
+ message = ''.join(pending_payload)
+ return first_opcode, message
+
+ def request_stop(self):
+ self._stop_requested = True
+
+ def run(self):
+ try:
+ while not self._stop_requested:
+ # opcode is OPCODE_BINARY or control opcodes when a message
+ # is succesfully received.
+ opcode, message = self._receive_message()
+ if not opcode:
+ return
+ if opcode == client_for_testing.OPCODE_BINARY:
+ channel_id, advance = _parse_channel_id(message)
+ self._mux._dispatch_frame(channel_id, message[advance:])
+ else:
+ self._mux._process_control_message(opcode, message)
+ finally:
+ self._mux._notify_reader_done()
+
+
+class _InnerFrame(object):
+ def __init__(self, fin, rsv1, rsv2, rsv3, opcode, payload):
+ self.fin = fin
+ self.rsv1 = rsv1
+ self.rsv2 = rsv2
+ self.rsv3 = rsv3
+ self.opcode = opcode
+ self.payload = payload
+
+
+class _LogicalChannelData(object):
+ def __init__(self):
+ self.queue = Queue.Queue()
+ self.send_quota = 0
+ self.receive_quota = 0
+
+
+class MuxClient(object):
+ """WebSocket mux client.
+
+ Note that this class is NOT thread-safe. Do not access an instance of this
+ class from multiple threads at a same time.
+ """
+
+ def __init__(self, options):
+ self._logger = util.get_class_logger(self)
+
+ self._options = options
+ self._options.enable_mux()
+ self._stream = None
+ self._socket = None
+ self._handshake = client_for_testing.WebSocketHandshake(self._options)
+ self._incoming_frame_filter = None
+ self._outgoing_frame_filter = None
+
+ self._is_active = False
+ self._read_thread = None
+ self._control_blocks_condition = threading.Condition()
+ self._control_blocks = []
+ self._channel_slots = collections.deque()
+ self._logical_channels_condition = threading.Condition();
+ self._logical_channels = {}
+ self._timeout = 2
+ self._physical_connection_close_event = None
+ self._physical_connection_close_message = None
+
+ def _parse_inner_frame(self, data):
+ if len(data) == 0:
+ raise Exception('Invalid encapsulated frame received')
+
+ first_byte = ord(data[0])
+ fin = (first_byte << 7) & 1
+ rsv1 = (first_byte << 6) & 1
+ rsv2 = (first_byte << 5) & 1
+ rsv3 = (first_byte << 4) & 1
+ opcode = first_byte & 0xf
+
+ if self._outgoing_frame_filter:
+ payload = self._outgoing_frame_filter.filter(
+ data[1:])
+ else:
+ payload = data[1:]
+
+ return _InnerFrame(fin, rsv1, rsv2, rsv3, opcode, payload)
+
+ def _process_mux_control_blocks(self):
+ for block in self._control_blocks:
+ if block.opcode == _MUX_OPCODE_ADD_CHANNEL_RESPONSE:
+ # AddChannelResponse will be handled in add_channel().
+ continue
+ elif block.opcode == _MUX_OPCODE_FLOW_CONTROL:
+ try:
+ self._logical_channels_condition.acquire()
+ if not block.channel_id in self._logical_channels:
+ raise Exception('Invalid flow control received for '
+ 'channel id %d' % block.channel_id)
+ self._logical_channels[block.channel_id].send_quota += (
+ block.send_quota)
+ self._logical_channels_condition.notify()
+ finally:
+ self._logical_channels_condition.release()
+ elif block.opcode == _MUX_OPCODE_NEW_CHANNEL_SLOT:
+ self._channel_slots.extend([block.send_quota] * block.slots)
+
+ def _dispatch_frame(self, channel_id, payload):
+ if channel_id == _CONTROL_CHANNEL_ID:
+ try:
+ self._control_blocks_condition.acquire()
+ self._control_blocks += _parse_control_blocks(payload)
+ self._process_mux_control_blocks()
+ self._control_blocks_condition.notify()
+ finally:
+ self._control_blocks_condition.release()
+ else:
+ try:
+ self._logical_channels_condition.acquire()
+ if not channel_id in self._logical_channels:
+ raise Exception('Received logical frame on channel id '
+ '%d, which is not established' %
+ channel_id)
+
+ inner_frame = self._parse_inner_frame(payload)
+ self._logical_channels[channel_id].receive_quota -= (
+ len(inner_frame.payload))
+ if self._logical_channels[channel_id].receive_quota < 0:
+ raise Exception('The server violates quota on '
+ 'channel id %d' % channel_id)
+ finally:
+ self._logical_channels_condition.release()
+ self._logical_channels[channel_id].queue.put(inner_frame)
+
+ def _process_control_message(self, opcode, message):
+ # Ping/Pong are not supported.
+ if opcode == client_for_testing.OPCODE_CLOSE:
+ self._physical_connection_close_message = message
+ if self._is_active:
+ self._stream.send_close(
+ code=client_for_testing.STATUS_NORMAL_CLOSURE, reason='')
+ self._read_thread.request_stop()
+
+ if self._physical_connection_close_event:
+ self._physical_connection_close_event.set()
+
+ def _notify_reader_done(self):
+ self._logger.debug('Read thread terminated.')
+ self.close_socket()
+
+ def _assert_channel_slot_available(self):
+ try:
+ self._control_blocks_condition.acquire()
+ if len(self._channel_slots) == 0:
+ # Wait once
+ self._control_blocks_condition.wait(timeout=self._timeout)
+ finally:
+ self._control_blocks_condition.release()
+
+ if len(self._channel_slots) == 0:
+ raise Exception('Failed to receive NewChannelSlot')
+
+ def _assert_send_quota_available(self, channel_id):
+ try:
+ self._logical_channels_condition.acquire()
+ if self._logical_channels[channel_id].send_quota == 0:
+ # Wait once
+ self._logical_channels_condition.wait(timeout=self._timeout)
+ finally:
+ self._logical_channels_condition.release()
+
+ if self._logical_channels[channel_id].send_quota == 0:
+ raise Exception('Failed to receive FlowControl for channel id %d' %
+ channel_id)
+
+ def connect(self):
+ self._socket = client_for_testing.connect_socket_with_retry(
+ self._options.server_host,
+ self._options.server_port,
+ self._options.socket_timeout,
+ self._options.use_tls)
+
+ self._handshake.handshake(self._socket)
+ self._stream = client_for_testing.WebSocketStream(
+ self._socket, self._handshake)
+
+ self._logical_channels[_DEFAULT_CHANNEL_ID] = _LogicalChannelData()
+
+ self._read_thread = _MuxReaderThread(self)
+ self._read_thread.start()
+
+ self._assert_channel_slot_available()
+ self._assert_send_quota_available(_DEFAULT_CHANNEL_ID)
+
+ self._is_active = True
+ self._logger.info('Connection established')
+
+ def add_channel(self, channel_id, options):
+ if not self._is_active:
+ raise Exception('Mux client is not active')
+
+ if channel_id in self._logical_channels:
+ raise Exception('Channel id %d already exists' % channel_id)
+
+ try:
+ send_quota = self._channel_slots.popleft()
+ except IndexError, e:
+ raise Exception('No channel slots: %r' % e)
+
+ # Create AddChannel request
+ request_line = 'GET %s HTTP/1.1\r\n' % options.resource
+ fields = []
+ if options.server_port == client_for_testing.DEFAULT_PORT:
+ fields.append('Host: %s\r\n' % options.server_host.lower())
+ else:
+ fields.append('Host: %s:%d\r\n' % (options.server_host.lower(),
+ options.server_port))
+ fields.append('Origin: %s\r\n' % options.origin.lower())
+ fields.append('Connection: Upgrade\r\n')
+
+ if len(options.extensions) > 0:
+ fields.append('Sec-WebSocket-Extensions: %s\r\n' %
+ ', '.join(options.extensions))
+
+ handshake = request_line + ''.join(fields) + '\r\n'
+ add_channel_request = _create_add_channel_request(
+ channel_id, handshake)
+ payload = _encode_channel_id(_CONTROL_CHANNEL_ID) + add_channel_request
+ self._stream.send_binary(payload)
+
+ # Wait AddChannelResponse
+ self._logger.debug('Waiting AddChannelResponse for the request...')
+ response = None
+ try:
+ self._control_blocks_condition.acquire()
+ while True:
+ for block in self._control_blocks:
+ if block.opcode != _MUX_OPCODE_ADD_CHANNEL_RESPONSE:
+ continue
+ if block.channel_id == channel_id:
+ response = block
+ self._control_blocks.remove(response)
+ break
+ if response:
+ break
+ self._control_blocks_condition.wait(self._timeout)
+ if not self._is_active:
+ raise Exception('AddChannelRequest timed out')
+ finally:
+ self._control_blocks_condition.release()
+
+ # Validate AddChannelResponse
+ if response.rejected:
+ raise Exception('The server rejected AddChannelRequest')
+
+ fields = _parse_handshake_response(response.encoded_handshake)
+
+ # Should we reject when Upgrade, Connection, or Sec-WebSocket-Accept
+ # headers exist?
+
+ self._logical_channels_condition.acquire()
+ self._logical_channels[channel_id] = _LogicalChannelData()
+ self._logical_channels[channel_id].send_quota = send_quota
+ self._logical_channels_condition.release()
+
+ self._logger.debug('Logical channel %d established' % channel_id)
+
+ def _check_logical_channel_is_opened(self, channel_id):
+ if not self._is_active:
+ raise Exception('Mux client is not active')
+
+ if not channel_id in self._logical_channels:
+ raise Exception('Logical channel %d is not established.')
+
+ def drop_channel(self, channel_id):
+ # TODO(bashi): Implement
+ pass
+
+ def send_flow_control(self, channel_id, replenished_quota):
+ self._check_logical_channel_is_opened(channel_id)
+ flow_control = _create_flow_control(channel_id, replenished_quota)
+ payload = _encode_channel_id(_CONTROL_CHANNEL_ID) + flow_control
+ # Replenish receive quota
+ try:
+ self._logical_channels_condition.acquire()
+ self._logical_channels[channel_id].receive_quota += (
+ replenished_quota)
+ finally:
+ self._logical_channels_condition.release()
+ self._stream.send_binary(payload)
+
+ def send_message(self, channel_id, message, end=True, binary=False):
+ self._check_logical_channel_is_opened(channel_id)
+
+ if binary:
+ first_byte = (end << 7) | client_for_testing.OPCODE_BINARY
+ else:
+ first_byte = (end << 7) | client_for_testing.OPCODE_TEXT
+ message = message.encode('utf-8')
+
+ try:
+ self._logical_channels_condition.acquire()
+ if self._logical_channels[channel_id].send_quota < len(message):
+ raise Exception('Send quota violation: %d < %d' % (
+ self._logical_channels[channel_id].send_quota,
+ len(message)))
+
+ self._logical_channels[channel_id].send_quota -= len(message)
+ finally:
+ self._logical_channels_condition.release()
+ payload = _encode_channel_id(channel_id) + chr(first_byte) + message
+ self._stream.send_binary(payload)
+
+ def assert_receive(self, channel_id, payload, binary=False):
+ self._check_logical_channel_is_opened(channel_id)
+
+ try:
+ inner_frame = self._logical_channels[channel_id].queue.get(
+ timeout=self._timeout)
+ except Queue.Empty, e:
+ raise Exception('Cannot receive message from channel id %d' %
+ channel_id)
+
+ if binary:
+ opcode = client_for_testing.OPCODE_BINARY
+ else:
+ opcode = client_for_testing.OPCODE_TEXT
+
+ if inner_frame.opcode != opcode:
+ raise Exception('Unexpected opcode received (%r != %r)' %
+ (expected_opcode, inner_frame.opcode))
+
+ if inner_frame.payload != payload:
+ raise Exception('Unexpected payload received')
+
+ def send_close(self, channel_id, code=None, reason=''):
+ self._check_logical_channel_is_opened(channel_id)
+
+ if code is not None:
+ body = struct.pack('!H', code) + reason.encode('utf-8')
+ else:
+ body = ''
+
+ first_byte = (1 << 7) | client_for_testing.OPCODE_CLOSE
+ payload = _encode_channel_id(channel_id) + chr(first_byte) + body
+ self._stream.send_binary(payload)
+
+ def assert_receive_close(self, channel_id):
+ self._check_logical_channel_is_opened(channel_id)
+
+ try:
+ inner_frame = self._logical_channels[channel_id].queue.get(
+ timeout=self._timeout)
+ except Queue.Empty, e:
+ raise Exception('Cannot receive message from channel id %d' %
+ channel_id)
+ if inner_frame.opcode != client_for_testing.OPCODE_CLOSE:
+ raise Exception('Didn\'t receive close frame')
+
+ def send_physical_connection_close(self, code=None, reason=''):
+ self._physical_connection_close_event = threading.Event()
+ self._stream.send_close(code, reason)
+
+ # This method can be used only after calling
+ # send_physical_connection_close().
+ def assert_physical_connection_receive_close(
+ self, code=client_for_testing.STATUS_NORMAL_CLOSURE, reason=''):
+ self._physical_connection_close_event.wait(timeout=self._timeout)
+ if (not self._physical_connection_close_event.isSet() or
+ not self._physical_connection_close_message):
+ raise Exception('Didn\'t receive closing handshake')
+
+ def close_socket(self):
+ self._is_active = False
+ self._socket.close()
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/run_all.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/run_all.py
new file mode 100755
index 00000000000..80a5d87d838
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/run_all.py
@@ -0,0 +1,89 @@
+#!/usr/bin/env python
+#
+# Copyright 2011, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+"""Run all tests in the same directory.
+
+This suite is expected to be run under pywebsocket's src directory, i.e. the
+directory containing mod_pywebsocket, test, etc.
+
+To change loggin level, please specify --log-level option.
+ python test/run_test.py --log-level debug
+
+To pass any option to unittest module, please specify options after '--'. For
+example, run this for making the test runner verbose.
+ python test/run_test.py --log-level debug -- -v
+"""
+
+
+import logging
+import optparse
+import os
+import re
+import sys
+import unittest
+
+
+_TEST_MODULE_PATTERN = re.compile(r'^(test_.+)\.py$')
+
+
+def _list_test_modules(directory):
+ module_names = []
+ for filename in os.listdir(directory):
+ match = _TEST_MODULE_PATTERN.search(filename)
+ if match:
+ module_names.append(match.group(1))
+ return module_names
+
+
+def _suite():
+ loader = unittest.TestLoader()
+ return loader.loadTestsFromNames(
+ _list_test_modules(os.path.join(os.path.split(__file__)[0], '.')))
+
+
+if __name__ == '__main__':
+ parser = optparse.OptionParser()
+ parser.add_option('--log-level', '--log_level', type='choice',
+ dest='log_level', default='warning',
+ choices=['debug', 'info', 'warning', 'warn', 'error',
+ 'critical'])
+ options, args = parser.parse_args()
+ logging.basicConfig(
+ level=logging.getLevelName(options.log_level.upper()),
+ format='%(levelname)s %(asctime)s '
+ '%(filename)s:%(lineno)d] '
+ '%(message)s',
+ datefmt='%H:%M:%S')
+ unittest.main(defaultTest='_suite', argv=[sys.argv[0]] + args)
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/set_sys_path.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/set_sys_path.py
new file mode 100644
index 00000000000..e3c6db9ea4d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/set_sys_path.py
@@ -0,0 +1,45 @@
+# Copyright 2009, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+"""Configuration for testing.
+
+Test files should import this module before mod_pywebsocket.
+"""
+
+
+import os
+import sys
+
+
+# Add the parent directory to sys.path to enable importing mod_pywebsocket.
+sys.path.insert(0, os.path.join(os.path.split(__file__)[0], '..'))
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/test_dispatch.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/test_dispatch.py
new file mode 100755
index 00000000000..9ca3d4f3ae1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/test_dispatch.py
@@ -0,0 +1,288 @@
+#!/usr/bin/env python
+#
+# Copyright 2011, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+"""Tests for dispatch module."""
+
+
+import os
+import unittest
+
+import set_sys_path # Update sys.path to locate mod_pywebsocket module.
+
+from mod_pywebsocket import dispatch
+from mod_pywebsocket import handshake
+from test import mock
+
+
+_TEST_HANDLERS_DIR = os.path.join(
+ os.path.split(__file__)[0], 'testdata', 'handlers')
+
+_TEST_HANDLERS_SUB_DIR = os.path.join(_TEST_HANDLERS_DIR, 'sub')
+
+
+class DispatcherTest(unittest.TestCase):
+ """A unittest for dispatch module."""
+
+ def test_normalize_path(self):
+ self.assertEqual(os.path.abspath('/a/b').replace('\\', '/'),
+ dispatch._normalize_path('/a/b'))
+ self.assertEqual(os.path.abspath('/a/b').replace('\\', '/'),
+ dispatch._normalize_path('\\a\\b'))
+ self.assertEqual(os.path.abspath('/a/b').replace('\\', '/'),
+ dispatch._normalize_path('/a/c/../b'))
+ self.assertEqual(os.path.abspath('abc').replace('\\', '/'),
+ dispatch._normalize_path('abc'))
+
+ def test_converter(self):
+ converter = dispatch._create_path_to_resource_converter('/a/b')
+ # Python built by MSC inserts a drive name like 'C:\' via realpath().
+ # Converter Generator expands provided path using realpath() and uses
+ # the path including a drive name to verify the prefix.
+ os_root = os.path.realpath('/')
+ self.assertEqual('/h', converter(os_root + 'a/b/h_wsh.py'))
+ self.assertEqual('/c/h', converter(os_root + 'a/b/c/h_wsh.py'))
+ self.assertEqual(None, converter(os_root + 'a/b/h.py'))
+ self.assertEqual(None, converter('a/b/h_wsh.py'))
+
+ converter = dispatch._create_path_to_resource_converter('a/b')
+ self.assertEqual('/h', converter(dispatch._normalize_path(
+ 'a/b/h_wsh.py')))
+
+ converter = dispatch._create_path_to_resource_converter('/a/b///')
+ self.assertEqual('/h', converter(os_root + 'a/b/h_wsh.py'))
+ self.assertEqual('/h', converter(dispatch._normalize_path(
+ '/a/b/../b/h_wsh.py')))
+
+ converter = dispatch._create_path_to_resource_converter(
+ '/a/../a/b/../b/')
+ self.assertEqual('/h', converter(os_root + 'a/b/h_wsh.py'))
+
+ converter = dispatch._create_path_to_resource_converter(r'\a\b')
+ self.assertEqual('/h', converter(os_root + r'a\b\h_wsh.py'))
+ self.assertEqual('/h', converter(os_root + r'a/b/h_wsh.py'))
+
+ def test_enumerate_handler_file_paths(self):
+ paths = list(
+ dispatch._enumerate_handler_file_paths(_TEST_HANDLERS_DIR))
+ paths.sort()
+ self.assertEqual(8, len(paths))
+ expected_paths = [
+ os.path.join(_TEST_HANDLERS_DIR, 'abort_by_user_wsh.py'),
+ os.path.join(_TEST_HANDLERS_DIR, 'blank_wsh.py'),
+ os.path.join(_TEST_HANDLERS_DIR, 'origin_check_wsh.py'),
+ os.path.join(_TEST_HANDLERS_DIR, 'sub',
+ 'exception_in_transfer_wsh.py'),
+ os.path.join(_TEST_HANDLERS_DIR, 'sub', 'non_callable_wsh.py'),
+ os.path.join(_TEST_HANDLERS_DIR, 'sub', 'plain_wsh.py'),
+ os.path.join(_TEST_HANDLERS_DIR, 'sub',
+ 'wrong_handshake_sig_wsh.py'),
+ os.path.join(_TEST_HANDLERS_DIR, 'sub',
+ 'wrong_transfer_sig_wsh.py'),
+ ]
+ for expected, actual in zip(expected_paths, paths):
+ self.assertEqual(expected, actual)
+
+ def test_source_handler_file(self):
+ self.assertRaises(
+ dispatch.DispatchException, dispatch._source_handler_file, '')
+ self.assertRaises(
+ dispatch.DispatchException, dispatch._source_handler_file, 'def')
+ self.assertRaises(
+ dispatch.DispatchException, dispatch._source_handler_file, '1/0')
+ self.failUnless(dispatch._source_handler_file(
+ 'def web_socket_do_extra_handshake(request):pass\n'
+ 'def web_socket_transfer_data(request):pass\n'))
+
+ def test_source_warnings(self):
+ dispatcher = dispatch.Dispatcher(_TEST_HANDLERS_DIR, None)
+ warnings = dispatcher.source_warnings()
+ warnings.sort()
+ expected_warnings = [
+ (os.path.realpath(os.path.join(
+ _TEST_HANDLERS_DIR, 'blank_wsh.py')) +
+ ': web_socket_do_extra_handshake is not defined.'),
+ (os.path.realpath(os.path.join(
+ _TEST_HANDLERS_DIR, 'sub', 'non_callable_wsh.py')) +
+ ': web_socket_do_extra_handshake is not callable.'),
+ (os.path.realpath(os.path.join(
+ _TEST_HANDLERS_DIR, 'sub', 'wrong_handshake_sig_wsh.py')) +
+ ': web_socket_do_extra_handshake is not defined.'),
+ (os.path.realpath(os.path.join(
+ _TEST_HANDLERS_DIR, 'sub', 'wrong_transfer_sig_wsh.py')) +
+ ': web_socket_transfer_data is not defined.'),
+ ]
+ self.assertEquals(4, len(warnings))
+ for expected, actual in zip(expected_warnings, warnings):
+ self.assertEquals(expected, actual)
+
+ def test_do_extra_handshake(self):
+ dispatcher = dispatch.Dispatcher(_TEST_HANDLERS_DIR, None)
+ request = mock.MockRequest()
+ request.ws_resource = '/origin_check'
+ request.ws_origin = 'http://example.com'
+ dispatcher.do_extra_handshake(request) # Must not raise exception.
+
+ request.ws_origin = 'http://bad.example.com'
+ try:
+ dispatcher.do_extra_handshake(request)
+ self.fail('Could not catch HandshakeException with 403 status')
+ except handshake.HandshakeException, e:
+ self.assertEquals(403, e.status)
+ except Exception, e:
+ self.fail('Unexpected exception: %r' % e)
+
+ def test_abort_extra_handshake(self):
+ dispatcher = dispatch.Dispatcher(_TEST_HANDLERS_DIR, None)
+ request = mock.MockRequest()
+ request.ws_resource = '/abort_by_user'
+ self.assertRaises(handshake.AbortedByUserException,
+ dispatcher.do_extra_handshake, request)
+
+ def test_transfer_data(self):
+ dispatcher = dispatch.Dispatcher(_TEST_HANDLERS_DIR, None)
+
+ request = mock.MockRequest(connection=mock.MockConn('\xff\x00'))
+ request.ws_resource = '/origin_check'
+ request.ws_protocol = 'p1'
+ dispatcher.transfer_data(request)
+ self.assertEqual('origin_check_wsh.py is called for /origin_check, p1'
+ '\xff\x00',
+ request.connection.written_data())
+
+ request = mock.MockRequest(connection=mock.MockConn('\xff\x00'))
+ request.ws_resource = '/sub/plain'
+ request.ws_protocol = None
+ dispatcher.transfer_data(request)
+ self.assertEqual('sub/plain_wsh.py is called for /sub/plain, None'
+ '\xff\x00',
+ request.connection.written_data())
+
+ request = mock.MockRequest(connection=mock.MockConn('\xff\x00'))
+ request.ws_resource = '/sub/plain?'
+ request.ws_protocol = None
+ dispatcher.transfer_data(request)
+ self.assertEqual('sub/plain_wsh.py is called for /sub/plain?, None'
+ '\xff\x00',
+ request.connection.written_data())
+
+ request = mock.MockRequest(connection=mock.MockConn('\xff\x00'))
+ request.ws_resource = '/sub/plain?q=v'
+ request.ws_protocol = None
+ dispatcher.transfer_data(request)
+ self.assertEqual('sub/plain_wsh.py is called for /sub/plain?q=v, None'
+ '\xff\x00',
+ request.connection.written_data())
+
+ def test_transfer_data_no_handler(self):
+ dispatcher = dispatch.Dispatcher(_TEST_HANDLERS_DIR, None)
+ for resource in ['/blank', '/sub/non_callable',
+ '/sub/no_wsh_at_the_end', '/does/not/exist']:
+ request = mock.MockRequest(connection=mock.MockConn(''))
+ request.ws_resource = resource
+ request.ws_protocol = 'p2'
+ try:
+ dispatcher.transfer_data(request)
+ self.fail()
+ except dispatch.DispatchException, e:
+ self.failUnless(str(e).find('No handler') != -1)
+ except Exception:
+ self.fail()
+
+ def test_transfer_data_handler_exception(self):
+ dispatcher = dispatch.Dispatcher(_TEST_HANDLERS_DIR, None)
+ request = mock.MockRequest(connection=mock.MockConn(''))
+ request.ws_resource = '/sub/exception_in_transfer'
+ request.ws_protocol = 'p3'
+ try:
+ dispatcher.transfer_data(request)
+ self.fail()
+ except Exception, e:
+ self.failUnless(str(e).find('Intentional') != -1,
+ 'Unexpected exception: %s' % e)
+
+ def test_abort_transfer_data(self):
+ dispatcher = dispatch.Dispatcher(_TEST_HANDLERS_DIR, None)
+ request = mock.MockRequest()
+ request.ws_resource = '/abort_by_user'
+ self.assertRaises(handshake.AbortedByUserException,
+ dispatcher.transfer_data, request)
+
+ def test_scan_dir(self):
+ disp = dispatch.Dispatcher(_TEST_HANDLERS_DIR, None)
+ self.assertEqual(4, len(disp._handler_suite_map))
+ self.failUnless('/origin_check' in disp._handler_suite_map)
+ self.failUnless(
+ '/sub/exception_in_transfer' in disp._handler_suite_map)
+ self.failUnless('/sub/plain' in disp._handler_suite_map)
+
+ def test_scan_sub_dir(self):
+ disp = dispatch.Dispatcher(_TEST_HANDLERS_DIR, _TEST_HANDLERS_SUB_DIR)
+ self.assertEqual(2, len(disp._handler_suite_map))
+ self.failIf('/origin_check' in disp._handler_suite_map)
+ self.failUnless(
+ '/sub/exception_in_transfer' in disp._handler_suite_map)
+ self.failUnless('/sub/plain' in disp._handler_suite_map)
+
+ def test_scan_sub_dir_as_root(self):
+ disp = dispatch.Dispatcher(_TEST_HANDLERS_SUB_DIR,
+ _TEST_HANDLERS_SUB_DIR)
+ self.assertEqual(2, len(disp._handler_suite_map))
+ self.failIf('/origin_check' in disp._handler_suite_map)
+ self.failIf('/sub/exception_in_transfer' in disp._handler_suite_map)
+ self.failIf('/sub/plain' in disp._handler_suite_map)
+ self.failUnless('/exception_in_transfer' in disp._handler_suite_map)
+ self.failUnless('/plain' in disp._handler_suite_map)
+
+ def test_scan_dir_must_under_root(self):
+ dispatch.Dispatcher('a/b', 'a/b/c') # OK
+ dispatch.Dispatcher('a/b///', 'a/b') # OK
+ self.assertRaises(dispatch.DispatchException,
+ dispatch.Dispatcher, 'a/b/c', 'a/b')
+
+ def test_resource_path_alias(self):
+ disp = dispatch.Dispatcher(_TEST_HANDLERS_DIR, None)
+ disp.add_resource_path_alias('/', '/origin_check')
+ self.assertEqual(5, len(disp._handler_suite_map))
+ self.failUnless('/origin_check' in disp._handler_suite_map)
+ self.failUnless(
+ '/sub/exception_in_transfer' in disp._handler_suite_map)
+ self.failUnless('/sub/plain' in disp._handler_suite_map)
+ self.failUnless('/' in disp._handler_suite_map)
+ self.assertRaises(dispatch.DispatchException,
+ disp.add_resource_path_alias, '/alias', '/not-exist')
+
+
+if __name__ == '__main__':
+ unittest.main()
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/test_endtoend.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/test_endtoend.py
new file mode 100755
index 00000000000..5e5cf615739
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/test_endtoend.py
@@ -0,0 +1,753 @@
+#!/usr/bin/env python
+#
+# Copyright 2012, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+"""End-to-end tests for pywebsocket. Tests standalone.py by default. You
+can also test mod_pywebsocket hosted on an Apache server by setting
+_use_external_server to True and modifying _external_server_port to point to
+the port on which the Apache server is running.
+"""
+
+
+import logging
+import os
+import signal
+import socket
+import subprocess
+import sys
+import time
+import unittest
+
+import set_sys_path # Update sys.path to locate mod_pywebsocket module.
+
+from test import client_for_testing
+from test import mux_client_for_testing
+
+
+# Special message that tells the echo server to start closing handshake
+_GOODBYE_MESSAGE = 'Goodbye'
+
+_SERVER_WARMUP_IN_SEC = 0.2
+
+# If you want to use external server to run end to end tests, set following
+# parameters correctly.
+_use_external_server = False
+_external_server_port = 0
+
+
+# Test body functions
+def _echo_check_procedure(client):
+ client.connect()
+
+ client.send_message('test')
+ client.assert_receive('test')
+ client.send_message('helloworld')
+ client.assert_receive('helloworld')
+
+ client.send_close()
+ client.assert_receive_close()
+
+ client.assert_connection_closed()
+
+
+def _echo_check_procedure_with_binary(client):
+ client.connect()
+
+ client.send_message('binary', binary=True)
+ client.assert_receive('binary', binary=True)
+ client.send_message('\x00\x80\xfe\xff\x00\x80', binary=True)
+ client.assert_receive('\x00\x80\xfe\xff\x00\x80', binary=True)
+
+ client.send_close()
+ client.assert_receive_close()
+
+ client.assert_connection_closed()
+
+
+def _echo_check_procedure_with_goodbye(client):
+ client.connect()
+
+ client.send_message('test')
+ client.assert_receive('test')
+
+ client.send_message(_GOODBYE_MESSAGE)
+ client.assert_receive(_GOODBYE_MESSAGE)
+
+ client.assert_receive_close()
+ client.send_close()
+
+ client.assert_connection_closed()
+
+
+def _echo_check_procedure_with_code_and_reason(client, code, reason):
+ client.connect()
+
+ client.send_close(code, reason)
+ client.assert_receive_close(code, reason)
+
+ client.assert_connection_closed()
+
+
+def _unmasked_frame_check_procedure(client):
+ client.connect()
+
+ client.send_message('test', mask=False)
+ client.assert_receive_close(client_for_testing.STATUS_PROTOCOL_ERROR, '')
+
+ client.assert_connection_closed()
+
+
+def _mux_echo_check_procedure(mux_client):
+ mux_client.connect()
+ mux_client.send_flow_control(1, 1024)
+
+ logical_channel_options = client_for_testing.ClientOptions()
+ logical_channel_options.server_host = 'localhost'
+ logical_channel_options.server_port = 80
+ logical_channel_options.origin = 'http://localhost'
+ logical_channel_options.resource = '/echo'
+ mux_client.add_channel(2, logical_channel_options)
+ mux_client.send_flow_control(2, 1024)
+
+ mux_client.send_message(2, 'test')
+ mux_client.assert_receive(2, 'test')
+
+ mux_client.add_channel(3, logical_channel_options)
+ mux_client.send_flow_control(3, 1024)
+
+ mux_client.send_message(2, 'hello')
+ mux_client.send_message(3, 'world')
+ mux_client.assert_receive(2, 'hello')
+ mux_client.assert_receive(3, 'world')
+
+ # Don't send close message on channel id 1 so that server-initiated
+ # closing handshake won't occur.
+ mux_client.send_close(2)
+ mux_client.send_close(3)
+ mux_client.assert_receive_close(2)
+ mux_client.assert_receive_close(3)
+
+ mux_client.send_physical_connection_close()
+ mux_client.assert_physical_connection_receive_close()
+
+
+class EndToEndTestBase(unittest.TestCase):
+ """Base class for end-to-end tests that launch pywebsocket standalone
+ server as a separate process, connect to it using the client_for_testing
+ module, and check if the server behaves correctly by exchanging opening
+ handshake and frames over a TCP connection.
+ """
+
+ def setUp(self):
+ self.server_stderr = None
+ self.top_dir = os.path.join(os.path.split(__file__)[0], '..')
+ os.putenv('PYTHONPATH', os.path.pathsep.join(sys.path))
+ self.standalone_command = os.path.join(
+ self.top_dir, 'mod_pywebsocket', 'standalone.py')
+ self.document_root = os.path.join(self.top_dir, 'example')
+ s = socket.socket()
+ s.bind(('localhost', 0))
+ (_, self.test_port) = s.getsockname()
+ s.close()
+
+ self._options = client_for_testing.ClientOptions()
+ self._options.server_host = 'localhost'
+ self._options.origin = 'http://localhost'
+ self._options.resource = '/echo'
+
+ # TODO(toyoshim): Eliminate launching a standalone server on using
+ # external server.
+
+ if _use_external_server:
+ self._options.server_port = _external_server_port
+ else:
+ self._options.server_port = self.test_port
+
+ # TODO(tyoshino): Use tearDown to kill the server.
+
+ def _run_python_command(self, commandline, stdout=None, stderr=None):
+ return subprocess.Popen([sys.executable] + commandline, close_fds=True,
+ stdout=stdout, stderr=stderr)
+
+ def _run_server(self):
+ args = [self.standalone_command,
+ '-H', 'localhost',
+ '-V', 'localhost',
+ '-p', str(self.test_port),
+ '-P', str(self.test_port),
+ '-d', self.document_root]
+
+ # Inherit the level set to the root logger by test runner.
+ root_logger = logging.getLogger()
+ log_level = root_logger.getEffectiveLevel()
+ if log_level != logging.NOTSET:
+ args.append('--log-level')
+ args.append(logging.getLevelName(log_level).lower())
+
+ return self._run_python_command(args,
+ stderr=self.server_stderr)
+
+ def _kill_process(self, pid):
+ if sys.platform in ('win32', 'cygwin'):
+ subprocess.call(
+ ('taskkill.exe', '/f', '/pid', str(pid)), close_fds=True)
+ else:
+ os.kill(pid, signal.SIGKILL)
+
+
+class EndToEndHyBiTest(EndToEndTestBase):
+ def setUp(self):
+ EndToEndTestBase.setUp(self)
+
+ def _run_test_with_client_options(self, test_function, options):
+ server = self._run_server()
+ try:
+ # TODO(tyoshino): add some logic to poll the server until it
+ # becomes ready
+ time.sleep(_SERVER_WARMUP_IN_SEC)
+
+ client = client_for_testing.create_client(options)
+ try:
+ test_function(client)
+ finally:
+ client.close_socket()
+ finally:
+ self._kill_process(server.pid)
+
+ def _run_test(self, test_function):
+ self._run_test_with_client_options(test_function, self._options)
+
+ def _run_deflate_frame_test(self, test_function):
+ server = self._run_server()
+ try:
+ time.sleep(_SERVER_WARMUP_IN_SEC)
+
+ self._options.enable_deflate_frame()
+ client = client_for_testing.create_client(self._options)
+ try:
+ test_function(client)
+ finally:
+ client.close_socket()
+ finally:
+ self._kill_process(server.pid)
+
+ def _run_permessage_deflate_test(
+ self, offer, response_checker, test_function):
+ server = self._run_server()
+ try:
+ time.sleep(_SERVER_WARMUP_IN_SEC)
+
+ self._options.extensions += offer
+ self._options.check_permessage_deflate = response_checker
+ client = client_for_testing.create_client(self._options)
+
+ try:
+ client.connect()
+
+ if test_function is not None:
+ test_function(client)
+
+ client.assert_connection_closed()
+ finally:
+ client.close_socket()
+ finally:
+ self._kill_process(server.pid)
+
+ def _run_close_with_code_and_reason_test(self, test_function, code,
+ reason):
+ server = self._run_server()
+ try:
+ time.sleep(_SERVER_WARMUP_IN_SEC)
+
+ client = client_for_testing.create_client(self._options)
+ try:
+ test_function(client, code, reason)
+ finally:
+ client.close_socket()
+ finally:
+ self._kill_process(server.pid)
+
+ def _run_http_fallback_test(self, options, status):
+ server = self._run_server()
+ try:
+ time.sleep(_SERVER_WARMUP_IN_SEC)
+
+ client = client_for_testing.create_client(options)
+ try:
+ client.connect()
+ self.fail('Could not catch HttpStatusException')
+ except client_for_testing.HttpStatusException, e:
+ self.assertEqual(status, e.status)
+ except Exception, e:
+ self.fail('Catch unexpected exception')
+ finally:
+ client.close_socket()
+ finally:
+ self._kill_process(server.pid)
+
+ def _run_mux_test(self, test_function):
+ server = self._run_server()
+ try:
+ time.sleep(_SERVER_WARMUP_IN_SEC)
+
+ client = mux_client_for_testing.MuxClient(self._options)
+ try:
+ test_function(client)
+ finally:
+ client.close_socket()
+ finally:
+ self._kill_process(server.pid)
+
+ def test_echo(self):
+ self._run_test(_echo_check_procedure)
+
+ def test_echo_binary(self):
+ self._run_test(_echo_check_procedure_with_binary)
+
+ def test_echo_server_close(self):
+ self._run_test(_echo_check_procedure_with_goodbye)
+
+ def test_unmasked_frame(self):
+ self._run_test(_unmasked_frame_check_procedure)
+
+ def test_echo_deflate_frame(self):
+ self._run_deflate_frame_test(_echo_check_procedure)
+
+ def test_echo_deflate_frame_server_close(self):
+ self._run_deflate_frame_test(
+ _echo_check_procedure_with_goodbye)
+
+ def test_echo_permessage_deflate(self):
+ def test_function(client):
+ # From the examples in the spec.
+ compressed_hello = '\xf2\x48\xcd\xc9\xc9\x07\x00'
+ client._stream.send_data(
+ compressed_hello,
+ client_for_testing.OPCODE_TEXT,
+ rsv1=1)
+ client._stream.assert_receive_binary(
+ compressed_hello,
+ opcode=client_for_testing.OPCODE_TEXT,
+ rsv1=1)
+
+ client.send_close()
+ client.assert_receive_close()
+
+ def response_checker(parameter):
+ self.assertEquals('permessage-deflate', parameter.name())
+ self.assertEquals([], parameter.get_parameters())
+
+ self._run_permessage_deflate_test(
+ ['permessage-deflate'],
+ response_checker,
+ test_function)
+
+ def test_echo_permessage_deflate_two_frames(self):
+ def test_function(client):
+ # From the examples in the spec.
+ client._stream.send_data(
+ '\xf2\x48\xcd',
+ client_for_testing.OPCODE_TEXT,
+ end=False,
+ rsv1=1)
+ client._stream.send_data(
+ '\xc9\xc9\x07\x00',
+ client_for_testing.OPCODE_TEXT)
+ client._stream.assert_receive_binary(
+ '\xf2\x48\xcd\xc9\xc9\x07\x00',
+ opcode=client_for_testing.OPCODE_TEXT,
+ rsv1=1)
+
+ client.send_close()
+ client.assert_receive_close()
+
+ def response_checker(parameter):
+ self.assertEquals('permessage-deflate', parameter.name())
+ self.assertEquals([], parameter.get_parameters())
+
+ self._run_permessage_deflate_test(
+ ['permessage-deflate'],
+ response_checker,
+ test_function)
+
+ def test_echo_permessage_deflate_two_messages(self):
+ def test_function(client):
+ # From the examples in the spec.
+ client._stream.send_data(
+ '\xf2\x48\xcd\xc9\xc9\x07\x00',
+ client_for_testing.OPCODE_TEXT,
+ rsv1=1)
+ client._stream.send_data(
+ '\xf2\x00\x11\x00\x00',
+ client_for_testing.OPCODE_TEXT,
+ rsv1=1)
+ client._stream.assert_receive_binary(
+ '\xf2\x48\xcd\xc9\xc9\x07\x00',
+ opcode=client_for_testing.OPCODE_TEXT,
+ rsv1=1)
+ client._stream.assert_receive_binary(
+ '\xf2\x00\x11\x00\x00',
+ opcode=client_for_testing.OPCODE_TEXT,
+ rsv1=1)
+
+ client.send_close()
+ client.assert_receive_close()
+
+ def response_checker(parameter):
+ self.assertEquals('permessage-deflate', parameter.name())
+ self.assertEquals([], parameter.get_parameters())
+
+ self._run_permessage_deflate_test(
+ ['permessage-deflate'],
+ response_checker,
+ test_function)
+
+ def test_echo_permessage_deflate_two_msgs_server_no_context_takeover(self):
+ def test_function(client):
+ # From the examples in the spec.
+ client._stream.send_data(
+ '\xf2\x48\xcd\xc9\xc9\x07\x00',
+ client_for_testing.OPCODE_TEXT,
+ rsv1=1)
+ client._stream.send_data(
+ '\xf2\x00\x11\x00\x00',
+ client_for_testing.OPCODE_TEXT,
+ rsv1=1)
+ client._stream.assert_receive_binary(
+ '\xf2\x48\xcd\xc9\xc9\x07\x00',
+ opcode=client_for_testing.OPCODE_TEXT,
+ rsv1=1)
+ client._stream.assert_receive_binary(
+ '\xf2\x48\xcd\xc9\xc9\x07\x00',
+ opcode=client_for_testing.OPCODE_TEXT,
+ rsv1=1)
+
+ client.send_close()
+ client.assert_receive_close()
+
+ def response_checker(parameter):
+ self.assertEquals('permessage-deflate', parameter.name())
+ self.assertEquals([('server_no_context_takeover', None)],
+ parameter.get_parameters())
+
+ self._run_permessage_deflate_test(
+ ['permessage-deflate; server_no_context_takeover'],
+ response_checker,
+ test_function)
+
+ def test_echo_permessage_deflate_preference(self):
+ def test_function(client):
+ # From the examples in the spec.
+ compressed_hello = '\xf2\x48\xcd\xc9\xc9\x07\x00'
+ client._stream.send_data(
+ compressed_hello,
+ client_for_testing.OPCODE_TEXT,
+ rsv1=1)
+ client._stream.assert_receive_binary(
+ compressed_hello,
+ opcode=client_for_testing.OPCODE_TEXT,
+ rsv1=1)
+
+ client.send_close()
+ client.assert_receive_close()
+
+ def response_checker(parameter):
+ self.assertEquals('permessage-deflate', parameter.name())
+ self.assertEquals([], parameter.get_parameters())
+
+ self._run_permessage_deflate_test(
+ ['permessage-deflate', 'deflate-frame'],
+ response_checker,
+ test_function)
+
+ def test_echo_permessage_deflate_with_parameters(self):
+ def test_function(client):
+ # From the examples in the spec.
+ compressed_hello = '\xf2\x48\xcd\xc9\xc9\x07\x00'
+ client._stream.send_data(
+ compressed_hello,
+ client_for_testing.OPCODE_TEXT,
+ rsv1=1)
+ client._stream.assert_receive_binary(
+ compressed_hello,
+ opcode=client_for_testing.OPCODE_TEXT,
+ rsv1=1)
+
+ client.send_close()
+ client.assert_receive_close()
+
+ def response_checker(parameter):
+ self.assertEquals('permessage-deflate', parameter.name())
+ self.assertEquals([('server_max_window_bits', '10'),
+ ('server_no_context_takeover', None)],
+ parameter.get_parameters())
+
+ self._run_permessage_deflate_test(
+ ['permessage-deflate; server_max_window_bits=10; '
+ 'server_no_context_takeover'],
+ response_checker,
+ test_function)
+
+ def test_echo_permessage_deflate_with_bad_server_max_window_bits(self):
+ def test_function(client):
+ client.send_close()
+ client.assert_receive_close()
+
+ def response_checker(parameter):
+ raise Exception('Unexpected acceptance of permessage-deflate')
+
+ self._run_permessage_deflate_test(
+ ['permessage-deflate; server_max_window_bits=3000000'],
+ response_checker,
+ test_function)
+
+ def test_echo_permessage_deflate_with_bad_server_max_window_bits(self):
+ def test_function(client):
+ client.send_close()
+ client.assert_receive_close()
+
+ def response_checker(parameter):
+ raise Exception('Unexpected acceptance of permessage-deflate')
+
+ self._run_permessage_deflate_test(
+ ['permessage-deflate; server_max_window_bits=3000000'],
+ response_checker,
+ test_function)
+
+ def test_echo_permessage_deflate_with_undefined_parameter(self):
+ def test_function(client):
+ client.send_close()
+ client.assert_receive_close()
+
+ def response_checker(parameter):
+ raise Exception('Unexpected acceptance of permessage-deflate')
+
+ self._run_permessage_deflate_test(
+ ['permessage-deflate; foo=bar'],
+ response_checker,
+ test_function)
+
+ def test_echo_close_with_code_and_reason(self):
+ self._options.resource = '/close'
+ self._run_close_with_code_and_reason_test(
+ _echo_check_procedure_with_code_and_reason, 3333, 'sunsunsunsun')
+
+ def test_echo_close_with_empty_body(self):
+ self._options.resource = '/close'
+ self._run_close_with_code_and_reason_test(
+ _echo_check_procedure_with_code_and_reason, None, '')
+
+ def test_mux_echo(self):
+ self._run_mux_test(_mux_echo_check_procedure)
+
+ def test_close_on_protocol_error(self):
+ """Tests that the server sends a close frame with protocol error status
+ code when the client sends data with some protocol error.
+ """
+
+ def test_function(client):
+ client.connect()
+
+ # Intermediate frame without any preceding start of fragmentation
+ # frame.
+ client.send_frame_of_arbitrary_bytes('\x80\x80', '')
+ client.assert_receive_close(
+ client_for_testing.STATUS_PROTOCOL_ERROR)
+
+ self._run_test(test_function)
+
+ def test_close_on_unsupported_frame(self):
+ """Tests that the server sends a close frame with unsupported operation
+ status code when the client sends data asking some operation that is
+ not supported by the server.
+ """
+
+ def test_function(client):
+ client.connect()
+
+ # Text frame with RSV3 bit raised.
+ client.send_frame_of_arbitrary_bytes('\x91\x80', '')
+ client.assert_receive_close(
+ client_for_testing.STATUS_UNSUPPORTED_DATA)
+
+ self._run_test(test_function)
+
+ def test_close_on_invalid_frame(self):
+ """Tests that the server sends a close frame with invalid frame payload
+ data status code when the client sends an invalid frame like containing
+ invalid UTF-8 character.
+ """
+
+ def test_function(client):
+ client.connect()
+
+ # Text frame with invalid UTF-8 string.
+ client.send_message('\x80', raw=True)
+ client.assert_receive_close(
+ client_for_testing.STATUS_INVALID_FRAME_PAYLOAD_DATA)
+
+ self._run_test(test_function)
+
+ def test_close_on_internal_endpoint_error(self):
+ """Tests that the server sends a close frame with internal endpoint
+ error status code when the handler does bad operation.
+ """
+
+ self._options.resource = '/internal_error'
+
+ def test_function(client):
+ client.connect()
+ client.assert_receive_close(
+ client_for_testing.STATUS_INTERNAL_ENDPOINT_ERROR)
+
+ self._run_test(test_function)
+
+ # TODO(toyoshim): Add tests to verify invalid absolute uri handling like
+ # host unmatch, port unmatch and invalid port description (':' without port
+ # number).
+
+ def test_absolute_uri(self):
+ """Tests absolute uri request."""
+
+ options = self._options
+ options.resource = 'ws://localhost:%d/echo' % options.server_port
+ self._run_test_with_client_options(_echo_check_procedure, options)
+
+ def test_origin_check(self):
+ """Tests http fallback on origin check fail."""
+
+ options = self._options
+ options.resource = '/origin_check'
+ # Server shows warning message for http 403 fallback. This warning
+ # message is confusing. Following pipe disposes warning messages.
+ self.server_stderr = subprocess.PIPE
+ self._run_http_fallback_test(options, 403)
+
+ def test_version_check(self):
+ """Tests http fallback on version check fail."""
+
+ options = self._options
+ options.version = 99
+ self._run_http_fallback_test(options, 400)
+
+
+class EndToEndHyBi00Test(EndToEndTestBase):
+ def setUp(self):
+ EndToEndTestBase.setUp(self)
+
+ def _run_test(self, test_function):
+ server = self._run_server()
+ try:
+ time.sleep(_SERVER_WARMUP_IN_SEC)
+
+ client = client_for_testing.create_client_hybi00(self._options)
+ try:
+ test_function(client)
+ finally:
+ client.close_socket()
+ finally:
+ self._kill_process(server.pid)
+
+ def test_echo(self):
+ self._run_test(_echo_check_procedure)
+
+ def test_echo_server_close(self):
+ self._run_test(_echo_check_procedure_with_goodbye)
+
+
+class EndToEndTestWithEchoClient(EndToEndTestBase):
+ def setUp(self):
+ EndToEndTestBase.setUp(self)
+
+ def _check_example_echo_client_result(
+ self, expected, stdoutdata, stderrdata):
+ actual = stdoutdata.decode("utf-8")
+ if actual != expected:
+ raise Exception('Unexpected result on example echo client: '
+ '%r (expected) vs %r (actual)' %
+ (expected, actual))
+ if stderrdata is not None:
+ raise Exception('Unexpected error message on example echo '
+ 'client: %r' % stderrdata)
+
+ def test_example_echo_client(self):
+ """Tests that the echo_client.py example can talk with the server."""
+
+ server = self._run_server()
+ try:
+ time.sleep(_SERVER_WARMUP_IN_SEC)
+
+ client_command = os.path.join(
+ self.top_dir, 'example', 'echo_client.py')
+
+ # Expected output for the default messages.
+ default_expectation = ('Send: Hello\n' 'Recv: Hello\n'
+ u'Send: \u65e5\u672c\n' u'Recv: \u65e5\u672c\n'
+ 'Send close\n' 'Recv ack\n')
+
+ args = [client_command,
+ '-p', str(self._options.server_port)]
+ client = self._run_python_command(args, stdout=subprocess.PIPE)
+ stdoutdata, stderrdata = client.communicate()
+ self._check_example_echo_client_result(
+ default_expectation, stdoutdata, stderrdata)
+
+ # Process a big message for which extended payload length is used.
+ # To handle extended payload length, ws_version attribute will be
+ # accessed. This test checks that ws_version is correctly set.
+ big_message = 'a' * 1024
+ args = [client_command,
+ '-p', str(self._options.server_port),
+ '-m', big_message]
+ client = self._run_python_command(args, stdout=subprocess.PIPE)
+ stdoutdata, stderrdata = client.communicate()
+ expected = ('Send: %s\nRecv: %s\nSend close\nRecv ack\n' %
+ (big_message, big_message))
+ self._check_example_echo_client_result(
+ expected, stdoutdata, stderrdata)
+
+ # Test the permessage-deflate extension.
+ args = [client_command,
+ '-p', str(self._options.server_port),
+ '--use_permessage_deflate']
+ client = self._run_python_command(args, stdout=subprocess.PIPE)
+ stdoutdata, stderrdata = client.communicate()
+ self._check_example_echo_client_result(
+ default_expectation, stdoutdata, stderrdata)
+ finally:
+ self._kill_process(server.pid)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/test_extensions.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/test_extensions.py
new file mode 100755
index 00000000000..6c8b1262d89
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/test_extensions.py
@@ -0,0 +1,360 @@
+#!/usr/bin/env python
+#
+# Copyright 2012, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+"""Tests for extensions module."""
+
+
+import unittest
+import zlib
+
+import set_sys_path # Update sys.path to locate mod_pywebsocket module.
+
+from mod_pywebsocket import common
+from mod_pywebsocket import extensions
+
+
+class ExtensionsTest(unittest.TestCase):
+ """A unittest for non-class methods in extensions.py"""
+
+ def test_parse_window_bits(self):
+ self.assertRaises(ValueError, extensions._parse_window_bits, None)
+ self.assertRaises(ValueError, extensions._parse_window_bits, 'foobar')
+ self.assertRaises(ValueError, extensions._parse_window_bits, ' 8 ')
+ self.assertRaises(ValueError, extensions._parse_window_bits, 'a8a')
+ self.assertRaises(ValueError, extensions._parse_window_bits, '00000')
+ self.assertRaises(ValueError, extensions._parse_window_bits, '00008')
+ self.assertRaises(ValueError, extensions._parse_window_bits, '0x8')
+
+ self.assertRaises(ValueError, extensions._parse_window_bits, '9.5')
+ self.assertRaises(ValueError, extensions._parse_window_bits, '8.0')
+
+ self.assertTrue(extensions._parse_window_bits, '8')
+ self.assertTrue(extensions._parse_window_bits, '15')
+
+ self.assertRaises(ValueError, extensions._parse_window_bits, '-8')
+ self.assertRaises(ValueError, extensions._parse_window_bits, '0')
+ self.assertRaises(ValueError, extensions._parse_window_bits, '7')
+
+ self.assertRaises(ValueError, extensions._parse_window_bits, '16')
+ self.assertRaises(
+ ValueError, extensions._parse_window_bits, '10000000')
+
+
+class CompressionMethodParameterParserTest(unittest.TestCase):
+ """A unittest for _parse_compression_method which parses the compression
+ method description used by perframe-compression and permessage-compression
+ extension in their "method" extension parameter.
+ """
+
+ def test_parse_method_simple(self):
+ method_list = extensions._parse_compression_method('foo')
+ self.assertEqual(1, len(method_list))
+ method = method_list[0]
+ self.assertEqual('foo', method.name())
+ self.assertEqual(0, len(method.get_parameters()))
+
+ def test_parse_method_with_parameter(self):
+ method_list = extensions._parse_compression_method('foo; x; y=10')
+ self.assertEqual(1, len(method_list))
+ method = method_list[0]
+ self.assertEqual('foo', method.name())
+ self.assertEqual(2, len(method.get_parameters()))
+ self.assertTrue(method.has_parameter('x'))
+ self.assertEqual(None, method.get_parameter_value('x'))
+ self.assertTrue(method.has_parameter('y'))
+ self.assertEqual('10', method.get_parameter_value('y'))
+
+ def test_parse_method_with_quoted_parameter(self):
+ method_list = extensions._parse_compression_method(
+ 'foo; x="Hello World"; y=10')
+ self.assertEqual(1, len(method_list))
+ method = method_list[0]
+ self.assertEqual('foo', method.name())
+ self.assertEqual(2, len(method.get_parameters()))
+ self.assertTrue(method.has_parameter('x'))
+ self.assertEqual('Hello World', method.get_parameter_value('x'))
+ self.assertTrue(method.has_parameter('y'))
+ self.assertEqual('10', method.get_parameter_value('y'))
+
+ def test_parse_method_multiple(self):
+ method_list = extensions._parse_compression_method('foo, bar')
+ self.assertEqual(2, len(method_list))
+ self.assertEqual('foo', method_list[0].name())
+ self.assertEqual(0, len(method_list[0].get_parameters()))
+ self.assertEqual('bar', method_list[1].name())
+ self.assertEqual(0, len(method_list[1].get_parameters()))
+
+ def test_parse_method_multiple_methods_with_quoted_parameter(self):
+ method_list = extensions._parse_compression_method(
+ 'foo; x="Hello World", bar; y=10')
+ self.assertEqual(2, len(method_list))
+ self.assertEqual('foo', method_list[0].name())
+ self.assertEqual(1, len(method_list[0].get_parameters()))
+ self.assertTrue(method_list[0].has_parameter('x'))
+ self.assertEqual('Hello World',
+ method_list[0].get_parameter_value('x'))
+ self.assertEqual('bar', method_list[1].name())
+ self.assertEqual(1, len(method_list[1].get_parameters()))
+ self.assertTrue(method_list[1].has_parameter('y'))
+ self.assertEqual('10', method_list[1].get_parameter_value('y'))
+
+ def test_create_method_desc_simple(self):
+ params = common.ExtensionParameter('foo')
+ desc = extensions._create_accepted_method_desc('foo',
+ params.get_parameters())
+ self.assertEqual('foo', desc)
+
+ def test_create_method_desc_with_parameters(self):
+ params = common.ExtensionParameter('foo')
+ params.add_parameter('x', 'Hello, World')
+ params.add_parameter('y', '10')
+ desc = extensions._create_accepted_method_desc('foo',
+ params.get_parameters())
+ self.assertEqual('foo; x="Hello, World"; y=10', desc)
+
+
+class DeflateFrameExtensionProcessorParsingTest(unittest.TestCase):
+ """A unittest for checking that DeflateFrameExtensionProcessor parses given
+ extension parameter correctly.
+ """
+
+ def test_registry(self):
+ processor = extensions.get_extension_processor(
+ common.ExtensionParameter('deflate-frame'))
+ self.assertIsInstance(processor,
+ extensions.DeflateFrameExtensionProcessor)
+
+ processor = extensions.get_extension_processor(
+ common.ExtensionParameter('x-webkit-deflate-frame'))
+ self.assertIsInstance(processor,
+ extensions.DeflateFrameExtensionProcessor)
+
+ def test_minimal_offer(self):
+ processor = extensions.DeflateFrameExtensionProcessor(
+ common.ExtensionParameter('perframe-deflate'))
+
+ response = processor.get_extension_response()
+ self.assertEqual('perframe-deflate', response.name())
+ self.assertEqual(0, len(response.get_parameters()))
+
+ self.assertEqual(zlib.MAX_WBITS,
+ processor._rfc1979_deflater._window_bits)
+ self.assertFalse(processor._rfc1979_deflater._no_context_takeover)
+
+ def test_offer_with_max_window_bits(self):
+ parameter = common.ExtensionParameter('perframe-deflate')
+ parameter.add_parameter('max_window_bits', '10')
+ processor = extensions.DeflateFrameExtensionProcessor(parameter)
+
+ response = processor.get_extension_response()
+ self.assertEqual('perframe-deflate', response.name())
+ self.assertEqual(0, len(response.get_parameters()))
+
+ self.assertEqual(10, processor._rfc1979_deflater._window_bits)
+
+ def test_offer_with_out_of_range_max_window_bits(self):
+ parameter = common.ExtensionParameter('perframe-deflate')
+ parameter.add_parameter('max_window_bits', '0')
+ processor = extensions.DeflateFrameExtensionProcessor(parameter)
+
+ self.assertIsNone(processor.get_extension_response())
+
+ def test_offer_with_max_window_bits_without_value(self):
+ parameter = common.ExtensionParameter('perframe-deflate')
+ parameter.add_parameter('max_window_bits', None)
+ processor = extensions.DeflateFrameExtensionProcessor(parameter)
+
+ self.assertIsNone(processor.get_extension_response())
+
+ def test_offer_with_no_context_takeover(self):
+ parameter = common.ExtensionParameter('perframe-deflate')
+ parameter.add_parameter('no_context_takeover', None)
+ processor = extensions.DeflateFrameExtensionProcessor(parameter)
+
+ response = processor.get_extension_response()
+ self.assertEqual('perframe-deflate', response.name())
+ self.assertEqual(0, len(response.get_parameters()))
+
+ self.assertTrue(processor._rfc1979_deflater._no_context_takeover)
+
+ def test_offer_with_no_context_takeover_with_value(self):
+ parameter = common.ExtensionParameter('perframe-deflate')
+ parameter.add_parameter('no_context_takeover', 'foobar')
+ processor = extensions.DeflateFrameExtensionProcessor(parameter)
+
+ self.assertIsNone(processor.get_extension_response())
+
+ def test_offer_with_unknown_parameter(self):
+ parameter = common.ExtensionParameter('perframe-deflate')
+ parameter.add_parameter('foo', 'bar')
+ processor = extensions.DeflateFrameExtensionProcessor(parameter)
+
+ response = processor.get_extension_response()
+ self.assertEqual('perframe-deflate', response.name())
+ self.assertEqual(0, len(response.get_parameters()))
+
+
+class PerMessageDeflateExtensionProcessorParsingTest(unittest.TestCase):
+ """A unittest for checking that PerMessageDeflateExtensionProcessor parses
+ given extension parameter correctly.
+ """
+
+ def test_registry(self):
+ processor = extensions.get_extension_processor(
+ common.ExtensionParameter('permessage-deflate'))
+ self.assertIsInstance(processor,
+ extensions.PerMessageDeflateExtensionProcessor)
+
+ def test_minimal_offer(self):
+ processor = extensions.PerMessageDeflateExtensionProcessor(
+ common.ExtensionParameter('permessage-deflate'))
+
+ response = processor.get_extension_response()
+ self.assertEqual('permessage-deflate', response.name())
+ self.assertEqual(0, len(response.get_parameters()))
+
+ self.assertEqual(zlib.MAX_WBITS,
+ processor._rfc1979_deflater._window_bits)
+ self.assertFalse(processor._rfc1979_deflater._no_context_takeover)
+
+ def test_offer_with_max_window_bits(self):
+ parameter = common.ExtensionParameter('permessage-deflate')
+ parameter.add_parameter('server_max_window_bits', '10')
+ processor = extensions.PerMessageDeflateExtensionProcessor(parameter)
+
+ response = processor.get_extension_response()
+ self.assertEqual('permessage-deflate', response.name())
+ self.assertEqual([('server_max_window_bits', '10')],
+ response.get_parameters())
+
+ self.assertEqual(10, processor._rfc1979_deflater._window_bits)
+
+ def test_offer_with_out_of_range_max_window_bits(self):
+ parameter = common.ExtensionParameter('permessage-deflate')
+ parameter.add_parameter('server_max_window_bits', '0')
+ processor = extensions.PerMessageDeflateExtensionProcessor(parameter)
+
+ self.assertIsNone(processor.get_extension_response())
+
+ def test_offer_with_max_window_bits_without_value(self):
+ parameter = common.ExtensionParameter('permessage-deflate')
+ parameter.add_parameter('server_max_window_bits', None)
+ processor = extensions.PerMessageDeflateExtensionProcessor(parameter)
+
+ self.assertIsNone(processor.get_extension_response())
+
+ def test_offer_with_no_context_takeover(self):
+ parameter = common.ExtensionParameter('permessage-deflate')
+ parameter.add_parameter('server_no_context_takeover', None)
+ processor = extensions.PerMessageDeflateExtensionProcessor(parameter)
+
+ response = processor.get_extension_response()
+ self.assertEqual('permessage-deflate', response.name())
+ self.assertEqual([('server_no_context_takeover', None)],
+ response.get_parameters())
+
+ self.assertTrue(processor._rfc1979_deflater._no_context_takeover)
+
+ def test_offer_with_no_context_takeover_with_value(self):
+ parameter = common.ExtensionParameter('permessage-deflate')
+ parameter.add_parameter('server_no_context_takeover', 'foobar')
+ processor = extensions.PerMessageDeflateExtensionProcessor(parameter)
+
+ self.assertIsNone(processor.get_extension_response())
+
+ def test_offer_with_unknown_parameter(self):
+ parameter = common.ExtensionParameter('permessage-deflate')
+ parameter.add_parameter('foo', 'bar')
+ processor = extensions.PerMessageDeflateExtensionProcessor(parameter)
+
+ self.assertIsNone(processor.get_extension_response())
+
+
+class PerMessageDeflateExtensionProcessorBuildingTest(unittest.TestCase):
+ """A unittest for checking that PerMessageDeflateExtensionProcessor builds
+ a response based on specified options correctly.
+ """
+
+ def test_response_with_max_window_bits(self):
+ parameter = common.ExtensionParameter('permessage-deflate')
+ parameter.add_parameter('client_max_window_bits', None)
+ processor = extensions.PerMessageDeflateExtensionProcessor(parameter)
+ processor.set_client_max_window_bits(10)
+
+ response = processor.get_extension_response()
+ self.assertEqual('permessage-deflate', response.name())
+ self.assertEqual([('client_max_window_bits', '10')],
+ response.get_parameters())
+
+ def test_response_with_max_window_bits_without_client_permission(self):
+ processor = extensions.PerMessageDeflateExtensionProcessor(
+ common.ExtensionParameter('permessage-deflate'))
+ processor.set_client_max_window_bits(10)
+
+ response = processor.get_extension_response()
+ self.assertIsNone(response)
+
+ def test_response_with_true_for_no_context_takeover(self):
+ processor = extensions.PerMessageDeflateExtensionProcessor(
+ common.ExtensionParameter('permessage-deflate'))
+
+ processor.set_client_no_context_takeover(True)
+
+ response = processor.get_extension_response()
+ self.assertEqual('permessage-deflate', response.name())
+ self.assertEqual([('client_no_context_takeover', None)],
+ response.get_parameters())
+
+ def test_response_with_false_for_no_context_takeover(self):
+ processor = extensions.PerMessageDeflateExtensionProcessor(
+ common.ExtensionParameter('permessage-deflate'))
+
+ processor.set_client_no_context_takeover(False)
+
+ response = processor.get_extension_response()
+ self.assertEqual('permessage-deflate', response.name())
+ self.assertEqual(0, len(response.get_parameters()))
+
+
+class PerMessageCompressExtensionProcessorTest(unittest.TestCase):
+ def test_registry(self):
+ processor = extensions.get_extension_processor(
+ common.ExtensionParameter('permessage-compress'))
+ self.assertIsInstance(processor,
+ extensions.PerMessageCompressExtensionProcessor)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/test_handshake.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/test_handshake.py
new file mode 100755
index 00000000000..aa78ac05e58
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/test_handshake.py
@@ -0,0 +1,188 @@
+#!/usr/bin/env python
+#
+# Copyright 2012, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+"""Tests for handshake._base module."""
+
+
+import unittest
+
+import set_sys_path # Update sys.path to locate mod_pywebsocket module.
+
+from mod_pywebsocket.common import ExtensionParameter
+from mod_pywebsocket.common import ExtensionParsingException
+from mod_pywebsocket.common import format_extensions
+from mod_pywebsocket.common import parse_extensions
+from mod_pywebsocket.handshake._base import HandshakeException
+from mod_pywebsocket.handshake._base import validate_subprotocol
+
+
+class ValidateSubprotocolTest(unittest.TestCase):
+ """A unittest for validate_subprotocol method."""
+
+ def test_validate_subprotocol(self):
+ # Should succeed.
+ validate_subprotocol('sample')
+ validate_subprotocol('Sample')
+ validate_subprotocol('sample\x7eprotocol')
+
+ # Should fail.
+ self.assertRaises(HandshakeException,
+ validate_subprotocol,
+ '')
+ self.assertRaises(HandshakeException,
+ validate_subprotocol,
+ 'sample\x09protocol')
+ self.assertRaises(HandshakeException,
+ validate_subprotocol,
+ 'sample\x19protocol')
+ self.assertRaises(HandshakeException,
+ validate_subprotocol,
+ 'sample\x20protocol')
+ self.assertRaises(HandshakeException,
+ validate_subprotocol,
+ 'sample\x7fprotocol')
+ self.assertRaises(HandshakeException,
+ validate_subprotocol,
+ # "Japan" in Japanese
+ u'\u65e5\u672c')
+
+
+_TEST_TOKEN_EXTENSION_DATA = [
+ ('foo', [('foo', [])]),
+ ('foo; bar', [('foo', [('bar', None)])]),
+ ('foo; bar=baz', [('foo', [('bar', 'baz')])]),
+ ('foo; bar=baz; car=cdr', [('foo', [('bar', 'baz'), ('car', 'cdr')])]),
+ ('foo; bar=baz, car; cdr',
+ [('foo', [('bar', 'baz')]), ('car', [('cdr', None)])]),
+ ('a, b, c, d',
+ [('a', []), ('b', []), ('c', []), ('d', [])]),
+ ]
+
+
+_TEST_QUOTED_EXTENSION_DATA = [
+ ('foo; bar=""', [('foo', [('bar', '')])]),
+ ('foo; bar=" baz "', [('foo', [('bar', ' baz ')])]),
+ ('foo; bar=",baz;"', [('foo', [('bar', ',baz;')])]),
+ ('foo; bar="\\\r\\\nbaz"', [('foo', [('bar', '\r\nbaz')])]),
+ ('foo; bar="\\"baz"', [('foo', [('bar', '"baz')])]),
+ ('foo; bar="\xbbbaz"', [('foo', [('bar', '\xbbbaz')])]),
+ ]
+
+
+_TEST_REDUNDANT_TOKEN_EXTENSION_DATA = [
+ ('foo \t ', [('foo', [])]),
+ ('foo; \r\n bar', [('foo', [('bar', None)])]),
+ ('foo; bar=\r\n \r\n baz', [('foo', [('bar', 'baz')])]),
+ ('foo ;bar = baz ', [('foo', [('bar', 'baz')])]),
+ ('foo,bar,,baz', [('foo', []), ('bar', []), ('baz', [])]),
+ ]
+
+
+_TEST_REDUNDANT_QUOTED_EXTENSION_DATA = [
+ ('foo; bar="\r\n \r\n baz"', [('foo', [('bar', ' baz')])]),
+ ]
+
+
+class ExtensionsParserTest(unittest.TestCase):
+
+ def _verify_extension_list(self, expected_list, actual_list):
+ """Verifies that ExtensionParameter objects in actual_list have the
+ same members as extension definitions in expected_list. Extension
+ definition used in this test is a pair of an extension name and a
+ parameter dictionary.
+ """
+
+ self.assertEqual(len(expected_list), len(actual_list))
+ for expected, actual in zip(expected_list, actual_list):
+ (name, parameters) = expected
+ self.assertEqual(name, actual._name)
+ self.assertEqual(parameters, actual._parameters)
+
+ def test_parse(self):
+ for formatted_string, definition in _TEST_TOKEN_EXTENSION_DATA:
+ self._verify_extension_list(
+ definition, parse_extensions(formatted_string))
+
+ def test_parse_quoted_data(self):
+ for formatted_string, definition in _TEST_QUOTED_EXTENSION_DATA:
+ self._verify_extension_list(
+ definition, parse_extensions(formatted_string))
+
+ def test_parse_redundant_data(self):
+ for (formatted_string,
+ definition) in _TEST_REDUNDANT_TOKEN_EXTENSION_DATA:
+ self._verify_extension_list(
+ definition, parse_extensions(formatted_string))
+
+ def test_parse_redundant_quoted_data(self):
+ for (formatted_string,
+ definition) in _TEST_REDUNDANT_QUOTED_EXTENSION_DATA:
+ self._verify_extension_list(
+ definition, parse_extensions(formatted_string))
+
+ def test_parse_bad_data(self):
+ _TEST_BAD_EXTENSION_DATA = [
+ ('foo; ; '),
+ ('foo; a a'),
+ ('foo foo'),
+ (',,,'),
+ ('foo; bar='),
+ ('foo; bar="hoge'),
+ ('foo; bar="a\r"'),
+ ('foo; bar="\\\xff"'),
+ ('foo; bar=\ra'),
+ ]
+
+ for formatted_string in _TEST_BAD_EXTENSION_DATA:
+ self.assertRaises(
+ ExtensionParsingException, parse_extensions, formatted_string)
+
+
+class FormatExtensionsTest(unittest.TestCase):
+
+ def test_format_extensions(self):
+ for formatted_string, definitions in _TEST_TOKEN_EXTENSION_DATA:
+ extensions = []
+ for definition in definitions:
+ (name, parameters) = definition
+ extension = ExtensionParameter(name)
+ extension._parameters = parameters
+ extensions.append(extension)
+ self.assertEqual(
+ formatted_string, format_extensions(extensions))
+
+
+if __name__ == '__main__':
+ unittest.main()
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/test_handshake_hybi.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/test_handshake_hybi.py
new file mode 100755
index 00000000000..6c87138230b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/test_handshake_hybi.py
@@ -0,0 +1,534 @@
+#!/usr/bin/env python
+#
+# Copyright 2011, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+"""Tests for handshake module."""
+
+
+import unittest
+
+import set_sys_path # Update sys.path to locate mod_pywebsocket module.
+from mod_pywebsocket import common
+from mod_pywebsocket.handshake._base import AbortedByUserException
+from mod_pywebsocket.handshake._base import HandshakeException
+from mod_pywebsocket.handshake._base import VersionException
+from mod_pywebsocket.handshake.hybi import Handshaker
+
+import mock
+
+
+class RequestDefinition(object):
+ """A class for holding data for constructing opening handshake strings for
+ testing the opening handshake processor.
+ """
+
+ def __init__(self, method, uri, headers):
+ self.method = method
+ self.uri = uri
+ self.headers = headers
+
+
+def _create_good_request_def():
+ return RequestDefinition(
+ 'GET', '/demo',
+ {'Host': 'server.example.com',
+ 'Upgrade': 'websocket',
+ 'Connection': 'Upgrade',
+ 'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==',
+ 'Sec-WebSocket-Version': '13',
+ 'Origin': 'http://example.com'})
+
+
+def _create_request(request_def):
+ conn = mock.MockConn('')
+ return mock.MockRequest(
+ method=request_def.method,
+ uri=request_def.uri,
+ headers_in=request_def.headers,
+ connection=conn)
+
+
+def _create_handshaker(request):
+ handshaker = Handshaker(request, mock.MockDispatcher())
+ return handshaker
+
+
+class SubprotocolChoosingDispatcher(object):
+ """A dispatcher for testing. This dispatcher sets the i-th subprotocol
+ of requested ones to ws_protocol where i is given on construction as index
+ argument. If index is negative, default_value will be set to ws_protocol.
+ """
+
+ def __init__(self, index, default_value=None):
+ self.index = index
+ self.default_value = default_value
+
+ def do_extra_handshake(self, conn_context):
+ if self.index >= 0:
+ conn_context.ws_protocol = conn_context.ws_requested_protocols[
+ self.index]
+ else:
+ conn_context.ws_protocol = self.default_value
+
+ def transfer_data(self, conn_context):
+ pass
+
+
+class HandshakeAbortedException(Exception):
+ pass
+
+
+class AbortingDispatcher(object):
+ """A dispatcher for testing. This dispatcher raises an exception in
+ do_extra_handshake to reject the request.
+ """
+
+ def do_extra_handshake(self, conn_context):
+ raise HandshakeAbortedException('An exception to reject the request')
+
+ def transfer_data(self, conn_context):
+ pass
+
+
+class AbortedByUserDispatcher(object):
+ """A dispatcher for testing. This dispatcher raises an
+ AbortedByUserException in do_extra_handshake to reject the request.
+ """
+
+ def do_extra_handshake(self, conn_context):
+ raise AbortedByUserException('An AbortedByUserException to reject the '
+ 'request')
+
+ def transfer_data(self, conn_context):
+ pass
+
+
+_EXPECTED_RESPONSE = (
+ 'HTTP/1.1 101 Switching Protocols\r\n'
+ 'Upgrade: websocket\r\n'
+ 'Connection: Upgrade\r\n'
+ 'Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n')
+
+
+class HandshakerTest(unittest.TestCase):
+ """A unittest for draft-ietf-hybi-thewebsocketprotocol-06 and later
+ handshake processor.
+ """
+
+ def test_do_handshake(self):
+ request = _create_request(_create_good_request_def())
+ dispatcher = mock.MockDispatcher()
+ handshaker = Handshaker(request, dispatcher)
+ handshaker.do_handshake()
+
+ self.assertTrue(dispatcher.do_extra_handshake_called)
+
+ self.assertEqual(
+ _EXPECTED_RESPONSE, request.connection.written_data())
+ self.assertEqual('/demo', request.ws_resource)
+ self.assertEqual('http://example.com', request.ws_origin)
+ self.assertEqual(None, request.ws_protocol)
+ self.assertEqual(None, request.ws_extensions)
+ self.assertEqual(common.VERSION_HYBI_LATEST, request.ws_version)
+
+ def test_do_handshake_with_extra_headers(self):
+ request_def = _create_good_request_def()
+ # Add headers not related to WebSocket opening handshake.
+ request_def.headers['FooKey'] = 'BarValue'
+ request_def.headers['EmptyKey'] = ''
+
+ request = _create_request(request_def)
+ handshaker = _create_handshaker(request)
+ handshaker.do_handshake()
+ self.assertEqual(
+ _EXPECTED_RESPONSE, request.connection.written_data())
+
+ def test_do_handshake_with_capitalized_value(self):
+ request_def = _create_good_request_def()
+ request_def.headers['upgrade'] = 'WEBSOCKET'
+
+ request = _create_request(request_def)
+ handshaker = _create_handshaker(request)
+ handshaker.do_handshake()
+ self.assertEqual(
+ _EXPECTED_RESPONSE, request.connection.written_data())
+
+ request_def = _create_good_request_def()
+ request_def.headers['Connection'] = 'UPGRADE'
+
+ request = _create_request(request_def)
+ handshaker = _create_handshaker(request)
+ handshaker.do_handshake()
+ self.assertEqual(
+ _EXPECTED_RESPONSE, request.connection.written_data())
+
+ def test_do_handshake_with_multiple_connection_values(self):
+ request_def = _create_good_request_def()
+ request_def.headers['Connection'] = 'Upgrade, keep-alive, , '
+
+ request = _create_request(request_def)
+ handshaker = _create_handshaker(request)
+ handshaker.do_handshake()
+ self.assertEqual(
+ _EXPECTED_RESPONSE, request.connection.written_data())
+
+ def test_aborting_handshake(self):
+ handshaker = Handshaker(
+ _create_request(_create_good_request_def()),
+ AbortingDispatcher())
+ # do_extra_handshake raises an exception. Check that it's not caught by
+ # do_handshake.
+ self.assertRaises(HandshakeAbortedException, handshaker.do_handshake)
+
+ def test_do_handshake_with_protocol(self):
+ request_def = _create_good_request_def()
+ request_def.headers['Sec-WebSocket-Protocol'] = 'chat, superchat'
+
+ request = _create_request(request_def)
+ handshaker = Handshaker(request, SubprotocolChoosingDispatcher(0))
+ handshaker.do_handshake()
+
+ EXPECTED_RESPONSE = (
+ 'HTTP/1.1 101 Switching Protocols\r\n'
+ 'Upgrade: websocket\r\n'
+ 'Connection: Upgrade\r\n'
+ 'Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n'
+ 'Sec-WebSocket-Protocol: chat\r\n\r\n')
+
+ self.assertEqual(EXPECTED_RESPONSE, request.connection.written_data())
+ self.assertEqual('chat', request.ws_protocol)
+
+ def test_do_handshake_protocol_not_in_request_but_in_response(self):
+ request_def = _create_good_request_def()
+ request = _create_request(request_def)
+ handshaker = Handshaker(
+ request, SubprotocolChoosingDispatcher(-1, 'foobar'))
+ # No request has been made but ws_protocol is set. HandshakeException
+ # must be raised.
+ self.assertRaises(HandshakeException, handshaker.do_handshake)
+
+ def test_do_handshake_with_protocol_no_protocol_selection(self):
+ request_def = _create_good_request_def()
+ request_def.headers['Sec-WebSocket-Protocol'] = 'chat, superchat'
+
+ request = _create_request(request_def)
+ handshaker = _create_handshaker(request)
+ # ws_protocol is not set. HandshakeException must be raised.
+ self.assertRaises(HandshakeException, handshaker.do_handshake)
+
+ def test_do_handshake_with_extensions(self):
+ request_def = _create_good_request_def()
+ request_def.headers['Sec-WebSocket-Extensions'] = (
+ 'permessage-compress; method=deflate, unknown')
+
+ EXPECTED_RESPONSE = (
+ 'HTTP/1.1 101 Switching Protocols\r\n'
+ 'Upgrade: websocket\r\n'
+ 'Connection: Upgrade\r\n'
+ 'Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n'
+ 'Sec-WebSocket-Extensions: permessage-compress; method=deflate\r\n'
+ '\r\n')
+
+ request = _create_request(request_def)
+ handshaker = _create_handshaker(request)
+ handshaker.do_handshake()
+ self.assertEqual(EXPECTED_RESPONSE, request.connection.written_data())
+ self.assertEqual(1, len(request.ws_extensions))
+ extension = request.ws_extensions[0]
+ self.assertEqual(common.PERMESSAGE_COMPRESSION_EXTENSION,
+ extension.name())
+ self.assertEqual(['method'], extension.get_parameter_names())
+ self.assertEqual('deflate', extension.get_parameter_value('method'))
+ self.assertEqual(1, len(request.ws_extension_processors))
+ self.assertEqual(common.PERMESSAGE_COMPRESSION_EXTENSION,
+ request.ws_extension_processors[0].name())
+
+ def test_do_handshake_with_permessage_compress(self):
+ request_def = _create_good_request_def()
+ request_def.headers['Sec-WebSocket-Extensions'] = (
+ 'permessage-compress; method=deflate')
+ request = _create_request(request_def)
+ handshaker = _create_handshaker(request)
+ handshaker.do_handshake()
+ self.assertEqual(1, len(request.ws_extensions))
+ self.assertEqual(common.PERMESSAGE_COMPRESSION_EXTENSION,
+ request.ws_extensions[0].name())
+ self.assertEqual(1, len(request.ws_extension_processors))
+ self.assertEqual(common.PERMESSAGE_COMPRESSION_EXTENSION,
+ request.ws_extension_processors[0].name())
+
+ def test_do_handshake_with_quoted_extensions(self):
+ request_def = _create_good_request_def()
+ request_def.headers['Sec-WebSocket-Extensions'] = (
+ 'permessage-compress; method=deflate, , '
+ 'unknown; e = "mc^2"; ma="\r\n \\\rf "; pv=nrt')
+
+ request = _create_request(request_def)
+ handshaker = _create_handshaker(request)
+ handshaker.do_handshake()
+ self.assertEqual(2, len(request.ws_requested_extensions))
+ first_extension = request.ws_requested_extensions[0]
+ self.assertEqual('permessage-compress', first_extension.name())
+ self.assertEqual(['method'], first_extension.get_parameter_names())
+ self.assertEqual('deflate',
+ first_extension.get_parameter_value('method'))
+ second_extension = request.ws_requested_extensions[1]
+ self.assertEqual('unknown', second_extension.name())
+ self.assertEqual(
+ ['e', 'ma', 'pv'], second_extension.get_parameter_names())
+ self.assertEqual('mc^2', second_extension.get_parameter_value('e'))
+ self.assertEqual(' \rf ', second_extension.get_parameter_value('ma'))
+ self.assertEqual('nrt', second_extension.get_parameter_value('pv'))
+
+ def test_do_handshake_with_optional_headers(self):
+ request_def = _create_good_request_def()
+ request_def.headers['EmptyValue'] = ''
+ request_def.headers['AKey'] = 'AValue'
+
+ request = _create_request(request_def)
+ handshaker = _create_handshaker(request)
+ handshaker.do_handshake()
+ self.assertEqual(
+ 'AValue', request.headers_in['AKey'])
+ self.assertEqual(
+ '', request.headers_in['EmptyValue'])
+
+ def test_abort_extra_handshake(self):
+ handshaker = Handshaker(
+ _create_request(_create_good_request_def()),
+ AbortedByUserDispatcher())
+ # do_extra_handshake raises an AbortedByUserException. Check that it's
+ # not caught by do_handshake.
+ self.assertRaises(AbortedByUserException, handshaker.do_handshake)
+
+ def test_do_handshake_with_mux_and_deflate_frame(self):
+ request_def = _create_good_request_def()
+ request_def.headers['Sec-WebSocket-Extensions'] = ('%s, %s' % (
+ common.MUX_EXTENSION,
+ common.DEFLATE_FRAME_EXTENSION))
+ request = _create_request(request_def)
+ handshaker = _create_handshaker(request)
+ handshaker.do_handshake()
+ # mux should be rejected.
+ self.assertEqual(1, len(request.ws_extensions))
+ self.assertEqual(common.DEFLATE_FRAME_EXTENSION,
+ request.ws_extensions[0].name())
+ self.assertEqual(2, len(request.ws_extension_processors))
+ self.assertEqual(common.MUX_EXTENSION,
+ request.ws_extension_processors[0].name())
+ self.assertEqual(common.DEFLATE_FRAME_EXTENSION,
+ request.ws_extension_processors[1].name())
+ self.assertFalse(hasattr(request, 'mux_processor'))
+
+ def test_do_handshake_with_deflate_frame_and_mux(self):
+ request_def = _create_good_request_def()
+ request_def.headers['Sec-WebSocket-Extensions'] = ('%s, %s' % (
+ common.DEFLATE_FRAME_EXTENSION,
+ common.MUX_EXTENSION))
+ request = _create_request(request_def)
+ handshaker = _create_handshaker(request)
+ handshaker.do_handshake()
+ # mux should be rejected.
+ self.assertEqual(1, len(request.ws_extensions))
+ first_extension = request.ws_extensions[0]
+ self.assertEqual(common.DEFLATE_FRAME_EXTENSION,
+ first_extension.name())
+ self.assertEqual(2, len(request.ws_extension_processors))
+ self.assertEqual(common.DEFLATE_FRAME_EXTENSION,
+ request.ws_extension_processors[0].name())
+ self.assertEqual(common.MUX_EXTENSION,
+ request.ws_extension_processors[1].name())
+ self.assertFalse(hasattr(request, 'mux'))
+
+ def test_do_handshake_with_permessage_compress_and_mux(self):
+ request_def = _create_good_request_def()
+ request_def.headers['Sec-WebSocket-Extensions'] = (
+ '%s; method=deflate, %s' % (
+ common.PERMESSAGE_COMPRESSION_EXTENSION,
+ common.MUX_EXTENSION))
+ request = _create_request(request_def)
+ handshaker = _create_handshaker(request)
+ handshaker.do_handshake()
+
+ self.assertEqual(1, len(request.ws_extensions))
+ self.assertEqual(common.MUX_EXTENSION,
+ request.ws_extensions[0].name())
+ self.assertEqual(2, len(request.ws_extension_processors))
+ self.assertEqual(common.PERMESSAGE_COMPRESSION_EXTENSION,
+ request.ws_extension_processors[0].name())
+ self.assertEqual(common.MUX_EXTENSION,
+ request.ws_extension_processors[1].name())
+ self.assertTrue(hasattr(request, 'mux_processor'))
+ self.assertTrue(request.mux_processor.is_active())
+ mux_extensions = request.mux_processor.extensions()
+ self.assertEqual(1, len(mux_extensions))
+ self.assertEqual(common.PERMESSAGE_COMPRESSION_EXTENSION,
+ mux_extensions[0].name())
+
+ def test_do_handshake_with_mux_and_permessage_compress(self):
+ request_def = _create_good_request_def()
+ request_def.headers['Sec-WebSocket-Extensions'] = (
+ '%s, %s; method=deflate' % (
+ common.MUX_EXTENSION,
+ common.PERMESSAGE_COMPRESSION_EXTENSION))
+ request = _create_request(request_def)
+ handshaker = _create_handshaker(request)
+ handshaker.do_handshake()
+ # mux should be rejected.
+ self.assertEqual(1, len(request.ws_extensions))
+ first_extension = request.ws_extensions[0]
+ self.assertEqual(common.PERMESSAGE_COMPRESSION_EXTENSION,
+ first_extension.name())
+ self.assertEqual(2, len(request.ws_extension_processors))
+ self.assertEqual(common.MUX_EXTENSION,
+ request.ws_extension_processors[0].name())
+ self.assertEqual(common.PERMESSAGE_COMPRESSION_EXTENSION,
+ request.ws_extension_processors[1].name())
+ self.assertFalse(hasattr(request, 'mux_processor'))
+
+ def test_bad_requests(self):
+ bad_cases = [
+ ('HTTP request',
+ RequestDefinition(
+ 'GET', '/demo',
+ {'Host': 'www.google.com',
+ 'User-Agent':
+ 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5;'
+ ' en-US; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3'
+ ' GTB6 GTBA',
+ 'Accept':
+ 'text/html,application/xhtml+xml,application/xml;q=0.9,'
+ '*/*;q=0.8',
+ 'Accept-Language': 'en-us,en;q=0.5',
+ 'Accept-Encoding': 'gzip,deflate',
+ 'Accept-Charset': 'ISO-8859-1,utf-8;q=0.7,*;q=0.7',
+ 'Keep-Alive': '300',
+ 'Connection': 'keep-alive'}), None, True)]
+
+ request_def = _create_good_request_def()
+ request_def.method = 'POST'
+ bad_cases.append(('Wrong method', request_def, None, True))
+
+ request_def = _create_good_request_def()
+ del request_def.headers['Host']
+ bad_cases.append(('Missing Host', request_def, None, True))
+
+ request_def = _create_good_request_def()
+ del request_def.headers['Upgrade']
+ bad_cases.append(('Missing Upgrade', request_def, None, True))
+
+ request_def = _create_good_request_def()
+ request_def.headers['Upgrade'] = 'nonwebsocket'
+ bad_cases.append(('Wrong Upgrade', request_def, None, True))
+
+ request_def = _create_good_request_def()
+ del request_def.headers['Connection']
+ bad_cases.append(('Missing Connection', request_def, None, True))
+
+ request_def = _create_good_request_def()
+ request_def.headers['Connection'] = 'Downgrade'
+ bad_cases.append(('Wrong Connection', request_def, None, True))
+
+ request_def = _create_good_request_def()
+ del request_def.headers['Sec-WebSocket-Key']
+ bad_cases.append(('Missing Sec-WebSocket-Key', request_def, 400, True))
+
+ request_def = _create_good_request_def()
+ request_def.headers['Sec-WebSocket-Key'] = (
+ 'dGhlIHNhbXBsZSBub25jZQ==garbage')
+ bad_cases.append(('Wrong Sec-WebSocket-Key (with garbage on the tail)',
+ request_def, 400, True))
+
+ request_def = _create_good_request_def()
+ request_def.headers['Sec-WebSocket-Key'] = 'YQ==' # BASE64 of 'a'
+ bad_cases.append(
+ ('Wrong Sec-WebSocket-Key (decoded value is not 16 octets long)',
+ request_def, 400, True))
+
+ request_def = _create_good_request_def()
+ # The last character right before == must be any of A, Q, w and g.
+ request_def.headers['Sec-WebSocket-Key'] = (
+ 'AQIDBAUGBwgJCgsMDQ4PEC==')
+ bad_cases.append(
+ ('Wrong Sec-WebSocket-Key (padding bits are not zero)',
+ request_def, 400, True))
+
+ request_def = _create_good_request_def()
+ request_def.headers['Sec-WebSocket-Key'] = (
+ 'dGhlIHNhbXBsZSBub25jZQ==,dGhlIHNhbXBsZSBub25jZQ==')
+ bad_cases.append(
+ ('Wrong Sec-WebSocket-Key (multiple values)',
+ request_def, 400, True))
+
+ request_def = _create_good_request_def()
+ del request_def.headers['Sec-WebSocket-Version']
+ bad_cases.append(('Missing Sec-WebSocket-Version', request_def, None,
+ True))
+
+ request_def = _create_good_request_def()
+ request_def.headers['Sec-WebSocket-Version'] = '3'
+ bad_cases.append(('Wrong Sec-WebSocket-Version', request_def, None,
+ False))
+
+ request_def = _create_good_request_def()
+ request_def.headers['Sec-WebSocket-Version'] = '13, 13'
+ bad_cases.append(('Wrong Sec-WebSocket-Version (multiple values)',
+ request_def, 400, True))
+
+ request_def = _create_good_request_def()
+ request_def.headers['Sec-WebSocket-Protocol'] = 'illegal\x09protocol'
+ bad_cases.append(('Illegal Sec-WebSocket-Protocol',
+ request_def, 400, True))
+
+ request_def = _create_good_request_def()
+ request_def.headers['Sec-WebSocket-Protocol'] = ''
+ bad_cases.append(('Empty Sec-WebSocket-Protocol',
+ request_def, 400, True))
+
+ for (case_name, request_def, expected_status,
+ expect_handshake_exception) in bad_cases:
+ request = _create_request(request_def)
+ handshaker = Handshaker(request, mock.MockDispatcher())
+ try:
+ handshaker.do_handshake()
+ self.fail('No exception thrown for \'%s\' case' % case_name)
+ except HandshakeException, e:
+ self.assertTrue(expect_handshake_exception)
+ self.assertEqual(expected_status, e.status)
+ except VersionException, e:
+ self.assertFalse(expect_handshake_exception)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/test_handshake_hybi00.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/test_handshake_hybi00.py
new file mode 100755
index 00000000000..73f9f27ca2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/test_handshake_hybi00.py
@@ -0,0 +1,516 @@
+#!/usr/bin/env python
+#
+# Copyright 2011, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+"""Tests for handshake.hybi00 module."""
+
+
+import unittest
+
+import set_sys_path # Update sys.path to locate mod_pywebsocket module.
+
+from mod_pywebsocket.handshake._base import HandshakeException
+from mod_pywebsocket.handshake.hybi00 import Handshaker
+from mod_pywebsocket.handshake.hybi00 import _validate_subprotocol
+from test import mock
+
+
+_TEST_KEY1 = '4 @1 46546xW%0l 1 5'
+_TEST_KEY2 = '12998 5 Y3 1 .P00'
+_TEST_KEY3 = '^n:ds[4U'
+_TEST_CHALLENGE_RESPONSE = '8jKS\'y:G*Co,Wxa-'
+
+
+_GOOD_REQUEST = (
+ 80,
+ 'GET',
+ '/demo',
+ {
+ 'Host': 'example.com',
+ 'Connection': 'Upgrade',
+ 'Sec-WebSocket-Key2': _TEST_KEY2,
+ 'Sec-WebSocket-Protocol': 'sample',
+ 'Upgrade': 'WebSocket',
+ 'Sec-WebSocket-Key1': _TEST_KEY1,
+ 'Origin': 'http://example.com',
+ },
+ _TEST_KEY3)
+
+_GOOD_REQUEST_CAPITALIZED_HEADER_VALUES = (
+ 80,
+ 'GET',
+ '/demo',
+ {
+ 'Host': 'example.com',
+ 'Connection': 'UPGRADE',
+ 'Sec-WebSocket-Key2': _TEST_KEY2,
+ 'Sec-WebSocket-Protocol': 'sample',
+ 'Upgrade': 'WEBSOCKET',
+ 'Sec-WebSocket-Key1': _TEST_KEY1,
+ 'Origin': 'http://example.com',
+ },
+ _TEST_KEY3)
+
+_GOOD_REQUEST_CASE_MIXED_HEADER_NAMES = (
+ 80,
+ 'GET',
+ '/demo',
+ {
+ 'hOsT': 'example.com',
+ 'cOnNeCtIoN': 'Upgrade',
+ 'sEc-wEbsOcKeT-kEy2': _TEST_KEY2,
+ 'sEc-wEbsOcKeT-pRoToCoL': 'sample',
+ 'uPgRaDe': 'WebSocket',
+ 'sEc-wEbsOcKeT-kEy1': _TEST_KEY1,
+ 'oRiGiN': 'http://example.com',
+ },
+ _TEST_KEY3)
+
+_GOOD_RESPONSE_DEFAULT_PORT = (
+ 'HTTP/1.1 101 WebSocket Protocol Handshake\r\n'
+ 'Upgrade: WebSocket\r\n'
+ 'Connection: Upgrade\r\n'
+ 'Sec-WebSocket-Location: ws://example.com/demo\r\n'
+ 'Sec-WebSocket-Origin: http://example.com\r\n'
+ 'Sec-WebSocket-Protocol: sample\r\n'
+ '\r\n' +
+ _TEST_CHALLENGE_RESPONSE)
+
+_GOOD_RESPONSE_SECURE = (
+ 'HTTP/1.1 101 WebSocket Protocol Handshake\r\n'
+ 'Upgrade: WebSocket\r\n'
+ 'Connection: Upgrade\r\n'
+ 'Sec-WebSocket-Location: wss://example.com/demo\r\n'
+ 'Sec-WebSocket-Origin: http://example.com\r\n'
+ 'Sec-WebSocket-Protocol: sample\r\n'
+ '\r\n' +
+ _TEST_CHALLENGE_RESPONSE)
+
+_GOOD_REQUEST_NONDEFAULT_PORT = (
+ 8081,
+ 'GET',
+ '/demo',
+ {
+ 'Host': 'example.com:8081',
+ 'Connection': 'Upgrade',
+ 'Sec-WebSocket-Key2': _TEST_KEY2,
+ 'Sec-WebSocket-Protocol': 'sample',
+ 'Upgrade': 'WebSocket',
+ 'Sec-WebSocket-Key1': _TEST_KEY1,
+ 'Origin': 'http://example.com',
+ },
+ _TEST_KEY3)
+
+_GOOD_RESPONSE_NONDEFAULT_PORT = (
+ 'HTTP/1.1 101 WebSocket Protocol Handshake\r\n'
+ 'Upgrade: WebSocket\r\n'
+ 'Connection: Upgrade\r\n'
+ 'Sec-WebSocket-Location: ws://example.com:8081/demo\r\n'
+ 'Sec-WebSocket-Origin: http://example.com\r\n'
+ 'Sec-WebSocket-Protocol: sample\r\n'
+ '\r\n' +
+ _TEST_CHALLENGE_RESPONSE)
+
+_GOOD_RESPONSE_SECURE_NONDEF = (
+ 'HTTP/1.1 101 WebSocket Protocol Handshake\r\n'
+ 'Upgrade: WebSocket\r\n'
+ 'Connection: Upgrade\r\n'
+ 'Sec-WebSocket-Location: wss://example.com:8081/demo\r\n'
+ 'Sec-WebSocket-Origin: http://example.com\r\n'
+ 'Sec-WebSocket-Protocol: sample\r\n'
+ '\r\n' +
+ _TEST_CHALLENGE_RESPONSE)
+
+_GOOD_REQUEST_NO_PROTOCOL = (
+ 80,
+ 'GET',
+ '/demo',
+ {
+ 'Host': 'example.com',
+ 'Connection': 'Upgrade',
+ 'Sec-WebSocket-Key2': _TEST_KEY2,
+ 'Upgrade': 'WebSocket',
+ 'Sec-WebSocket-Key1': _TEST_KEY1,
+ 'Origin': 'http://example.com',
+ },
+ _TEST_KEY3)
+
+_GOOD_RESPONSE_NO_PROTOCOL = (
+ 'HTTP/1.1 101 WebSocket Protocol Handshake\r\n'
+ 'Upgrade: WebSocket\r\n'
+ 'Connection: Upgrade\r\n'
+ 'Sec-WebSocket-Location: ws://example.com/demo\r\n'
+ 'Sec-WebSocket-Origin: http://example.com\r\n'
+ '\r\n' +
+ _TEST_CHALLENGE_RESPONSE)
+
+_GOOD_REQUEST_WITH_OPTIONAL_HEADERS = (
+ 80,
+ 'GET',
+ '/demo',
+ {
+ 'Host': 'example.com',
+ 'Connection': 'Upgrade',
+ 'Sec-WebSocket-Key2': _TEST_KEY2,
+ 'EmptyValue': '',
+ 'Sec-WebSocket-Protocol': 'sample',
+ 'AKey': 'AValue',
+ 'Upgrade': 'WebSocket',
+ 'Sec-WebSocket-Key1': _TEST_KEY1,
+ 'Origin': 'http://example.com',
+ },
+ _TEST_KEY3)
+
+# TODO(tyoshino): Include \r \n in key3, challenge response.
+
+_GOOD_REQUEST_WITH_NONPRINTABLE_KEY = (
+ 80,
+ 'GET',
+ '/demo',
+ {
+ 'Host': 'example.com',
+ 'Connection': 'Upgrade',
+ 'Sec-WebSocket-Key2': 'y R2 48 Q1O4 e|BV3 i5 1 u- 65',
+ 'Sec-WebSocket-Protocol': 'sample',
+ 'Upgrade': 'WebSocket',
+ 'Sec-WebSocket-Key1': '36 7 74 i 92 2\'m 9 0G',
+ 'Origin': 'http://example.com',
+ },
+ ''.join(map(chr, [0x01, 0xd1, 0xdd, 0x3b, 0xd1, 0x56, 0x63, 0xff])))
+
+_GOOD_RESPONSE_WITH_NONPRINTABLE_KEY = (
+ 'HTTP/1.1 101 WebSocket Protocol Handshake\r\n'
+ 'Upgrade: WebSocket\r\n'
+ 'Connection: Upgrade\r\n'
+ 'Sec-WebSocket-Location: ws://example.com/demo\r\n'
+ 'Sec-WebSocket-Origin: http://example.com\r\n'
+ 'Sec-WebSocket-Protocol: sample\r\n'
+ '\r\n' +
+ ''.join(map(chr, [0x0b, 0x99, 0xfa, 0x55, 0xbd, 0x01, 0x23, 0x7b,
+ 0x45, 0xa2, 0xf1, 0xd0, 0x87, 0x8a, 0xee, 0xeb])))
+
+_GOOD_REQUEST_WITH_QUERY_PART = (
+ 80,
+ 'GET',
+ '/demo?e=mc2',
+ {
+ 'Host': 'example.com',
+ 'Connection': 'Upgrade',
+ 'Sec-WebSocket-Key2': _TEST_KEY2,
+ 'Sec-WebSocket-Protocol': 'sample',
+ 'Upgrade': 'WebSocket',
+ 'Sec-WebSocket-Key1': _TEST_KEY1,
+ 'Origin': 'http://example.com',
+ },
+ _TEST_KEY3)
+
+_GOOD_RESPONSE_WITH_QUERY_PART = (
+ 'HTTP/1.1 101 WebSocket Protocol Handshake\r\n'
+ 'Upgrade: WebSocket\r\n'
+ 'Connection: Upgrade\r\n'
+ 'Sec-WebSocket-Location: ws://example.com/demo?e=mc2\r\n'
+ 'Sec-WebSocket-Origin: http://example.com\r\n'
+ 'Sec-WebSocket-Protocol: sample\r\n'
+ '\r\n' +
+ _TEST_CHALLENGE_RESPONSE)
+
+_BAD_REQUESTS = (
+ ( # HTTP request
+ 80,
+ 'GET',
+ '/demo',
+ {
+ 'Host': 'www.google.com',
+ 'User-Agent': 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5;'
+ ' en-US; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3'
+ ' GTB6 GTBA',
+ 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,'
+ '*/*;q=0.8',
+ 'Accept-Language': 'en-us,en;q=0.5',
+ 'Accept-Encoding': 'gzip,deflate',
+ 'Accept-Charset': 'ISO-8859-1,utf-8;q=0.7,*;q=0.7',
+ 'Keep-Alive': '300',
+ 'Connection': 'keep-alive',
+ }),
+ ( # Wrong method
+ 80,
+ 'POST',
+ '/demo',
+ {
+ 'Host': 'example.com',
+ 'Connection': 'Upgrade',
+ 'Sec-WebSocket-Key2': _TEST_KEY2,
+ 'Sec-WebSocket-Protocol': 'sample',
+ 'Upgrade': 'WebSocket',
+ 'Sec-WebSocket-Key1': _TEST_KEY1,
+ 'Origin': 'http://example.com',
+ },
+ _TEST_KEY3),
+ ( # Missing Upgrade
+ 80,
+ 'GET',
+ '/demo',
+ {
+ 'Host': 'example.com',
+ 'Connection': 'Upgrade',
+ 'Sec-WebSocket-Key2': _TEST_KEY2,
+ 'Sec-WebSocket-Protocol': 'sample',
+ 'Sec-WebSocket-Key1': _TEST_KEY1,
+ 'Origin': 'http://example.com',
+ },
+ _TEST_KEY3),
+ ( # Wrong Upgrade
+ 80,
+ 'GET',
+ '/demo',
+ {
+ 'Host': 'example.com',
+ 'Connection': 'Upgrade',
+ 'Sec-WebSocket-Key2': _TEST_KEY2,
+ 'Sec-WebSocket-Protocol': 'sample',
+ 'Upgrade': 'NonWebSocket',
+ 'Sec-WebSocket-Key1': _TEST_KEY1,
+ 'Origin': 'http://example.com',
+ },
+ _TEST_KEY3),
+ ( # Empty WebSocket-Protocol
+ 80,
+ 'GET',
+ '/demo',
+ {
+ 'Host': 'example.com',
+ 'Connection': 'Upgrade',
+ 'Sec-WebSocket-Key2': _TEST_KEY2,
+ 'Sec-WebSocket-Protocol': '',
+ 'Upgrade': 'WebSocket',
+ 'Sec-WebSocket-Key1': _TEST_KEY1,
+ 'Origin': 'http://example.com',
+ },
+ _TEST_KEY3),
+ ( # Wrong port number format
+ 80,
+ 'GET',
+ '/demo',
+ {
+ 'Host': 'example.com:0x50',
+ 'Connection': 'Upgrade',
+ 'Sec-WebSocket-Key2': _TEST_KEY2,
+ 'Sec-WebSocket-Protocol': 'sample',
+ 'Upgrade': 'WebSocket',
+ 'Sec-WebSocket-Key1': _TEST_KEY1,
+ 'Origin': 'http://example.com',
+ },
+ _TEST_KEY3),
+ ( # Header/connection port mismatch
+ 8080,
+ 'GET',
+ '/demo',
+ {
+ 'Host': 'example.com',
+ 'Connection': 'Upgrade',
+ 'Sec-WebSocket-Key2': _TEST_KEY2,
+ 'Sec-WebSocket-Protocol': 'sample',
+ 'Upgrade': 'WebSocket',
+ 'Sec-WebSocket-Key1': _TEST_KEY1,
+ 'Origin': 'http://example.com',
+ },
+ _TEST_KEY3),
+ ( # Illegal WebSocket-Protocol
+ 80,
+ 'GET',
+ '/demo',
+ {
+ 'Host': 'example.com',
+ 'Connection': 'Upgrade',
+ 'Sec-WebSocket-Key2': _TEST_KEY2,
+ 'Sec-WebSocket-Protocol': 'illegal\x09protocol',
+ 'Upgrade': 'WebSocket',
+ 'Sec-WebSocket-Key1': _TEST_KEY1,
+ 'Origin': 'http://example.com',
+ },
+ _TEST_KEY3),
+)
+
+
+def _create_request(request_def):
+ data = ''
+ if len(request_def) > 4:
+ data = request_def[4]
+ conn = mock.MockConn(data)
+ conn.local_addr = ('0.0.0.0', request_def[0])
+ return mock.MockRequest(
+ method=request_def[1],
+ uri=request_def[2],
+ headers_in=request_def[3],
+ connection=conn)
+
+
+def _create_get_memorized_lines(lines):
+ """Creates a function that returns the given string."""
+
+ def get_memorized_lines():
+ return lines
+ return get_memorized_lines
+
+
+def _create_requests_with_lines(request_lines_set):
+ requests = []
+ for lines in request_lines_set:
+ request = _create_request(_GOOD_REQUEST)
+ request.connection.get_memorized_lines = _create_get_memorized_lines(
+ lines)
+ requests.append(request)
+ return requests
+
+
+class HyBi00HandshakerTest(unittest.TestCase):
+
+ def test_good_request_default_port(self):
+ request = _create_request(_GOOD_REQUEST)
+ handshaker = Handshaker(request, mock.MockDispatcher())
+ handshaker.do_handshake()
+ self.assertEqual(_GOOD_RESPONSE_DEFAULT_PORT,
+ request.connection.written_data())
+ self.assertEqual('/demo', request.ws_resource)
+ self.assertEqual('http://example.com', request.ws_origin)
+ self.assertEqual('ws://example.com/demo', request.ws_location)
+ self.assertEqual('sample', request.ws_protocol)
+
+ def test_good_request_capitalized_header_values(self):
+ request = _create_request(_GOOD_REQUEST_CAPITALIZED_HEADER_VALUES)
+ handshaker = Handshaker(request, mock.MockDispatcher())
+ handshaker.do_handshake()
+ self.assertEqual(_GOOD_RESPONSE_DEFAULT_PORT,
+ request.connection.written_data())
+
+ def test_good_request_case_mixed_header_names(self):
+ request = _create_request(_GOOD_REQUEST_CASE_MIXED_HEADER_NAMES)
+ handshaker = Handshaker(request, mock.MockDispatcher())
+ handshaker.do_handshake()
+ self.assertEqual(_GOOD_RESPONSE_DEFAULT_PORT,
+ request.connection.written_data())
+
+ def test_good_request_secure_default_port(self):
+ request = _create_request(_GOOD_REQUEST)
+ request.connection.local_addr = ('0.0.0.0', 443)
+ request.is_https_ = True
+ handshaker = Handshaker(request, mock.MockDispatcher())
+ handshaker.do_handshake()
+ self.assertEqual(_GOOD_RESPONSE_SECURE,
+ request.connection.written_data())
+ self.assertEqual('sample', request.ws_protocol)
+
+ def test_good_request_nondefault_port(self):
+ request = _create_request(_GOOD_REQUEST_NONDEFAULT_PORT)
+ handshaker = Handshaker(request,
+ mock.MockDispatcher())
+ handshaker.do_handshake()
+ self.assertEqual(_GOOD_RESPONSE_NONDEFAULT_PORT,
+ request.connection.written_data())
+ self.assertEqual('sample', request.ws_protocol)
+
+ def test_good_request_secure_non_default_port(self):
+ request = _create_request(_GOOD_REQUEST_NONDEFAULT_PORT)
+ request.is_https_ = True
+ handshaker = Handshaker(request, mock.MockDispatcher())
+ handshaker.do_handshake()
+ self.assertEqual(_GOOD_RESPONSE_SECURE_NONDEF,
+ request.connection.written_data())
+ self.assertEqual('sample', request.ws_protocol)
+
+ def test_good_request_default_no_protocol(self):
+ request = _create_request(_GOOD_REQUEST_NO_PROTOCOL)
+ handshaker = Handshaker(request, mock.MockDispatcher())
+ handshaker.do_handshake()
+ self.assertEqual(_GOOD_RESPONSE_NO_PROTOCOL,
+ request.connection.written_data())
+ self.assertEqual(None, request.ws_protocol)
+
+ def test_good_request_optional_headers(self):
+ request = _create_request(_GOOD_REQUEST_WITH_OPTIONAL_HEADERS)
+ handshaker = Handshaker(request, mock.MockDispatcher())
+ handshaker.do_handshake()
+ self.assertEqual('AValue',
+ request.headers_in['AKey'])
+ self.assertEqual('',
+ request.headers_in['EmptyValue'])
+
+ def test_good_request_with_nonprintable_key(self):
+ request = _create_request(_GOOD_REQUEST_WITH_NONPRINTABLE_KEY)
+ handshaker = Handshaker(request, mock.MockDispatcher())
+ handshaker.do_handshake()
+ self.assertEqual(_GOOD_RESPONSE_WITH_NONPRINTABLE_KEY,
+ request.connection.written_data())
+ self.assertEqual('sample', request.ws_protocol)
+
+ def test_good_request_with_query_part(self):
+ request = _create_request(_GOOD_REQUEST_WITH_QUERY_PART)
+ handshaker = Handshaker(request, mock.MockDispatcher())
+ handshaker.do_handshake()
+ self.assertEqual(_GOOD_RESPONSE_WITH_QUERY_PART,
+ request.connection.written_data())
+ self.assertEqual('ws://example.com/demo?e=mc2', request.ws_location)
+
+ def test_bad_requests(self):
+ for request in map(_create_request, _BAD_REQUESTS):
+ handshaker = Handshaker(request, mock.MockDispatcher())
+ self.assertRaises(HandshakeException, handshaker.do_handshake)
+
+
+class HyBi00ValidateSubprotocolTest(unittest.TestCase):
+ def test_validate_subprotocol(self):
+ # should succeed.
+ _validate_subprotocol('sample')
+ _validate_subprotocol('Sample')
+ _validate_subprotocol('sample\x7eprotocol')
+ _validate_subprotocol('sample\x20protocol')
+
+ # should fail.
+ self.assertRaises(HandshakeException,
+ _validate_subprotocol,
+ '')
+ self.assertRaises(HandshakeException,
+ _validate_subprotocol,
+ 'sample\x19protocol')
+ self.assertRaises(HandshakeException,
+ _validate_subprotocol,
+ 'sample\x7fprotocol')
+ self.assertRaises(HandshakeException,
+ _validate_subprotocol,
+ # "Japan" in Japanese
+ u'\u65e5\u672c')
+
+
+if __name__ == '__main__':
+ unittest.main()
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/test_http_header_util.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/test_http_header_util.py
new file mode 100755
index 00000000000..436dc57c373
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/test_http_header_util.py
@@ -0,0 +1,90 @@
+#!/usr/bin/env python
+#
+# Copyright 2011, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+"""Tests for http_header_util module."""
+
+
+import unittest
+
+from mod_pywebsocket import http_header_util
+
+
+class UnitTest(unittest.TestCase):
+ """A unittest for http_header_util module."""
+
+ def test_parse_relative_uri(self):
+ host, port, resource = http_header_util.parse_uri('/ws/test')
+ self.assertEqual(None, host)
+ self.assertEqual(None, port)
+ self.assertEqual('/ws/test', resource)
+
+ def test_parse_absolute_uri(self):
+ host, port, resource = http_header_util.parse_uri(
+ 'ws://localhost:10080/ws/test')
+ self.assertEqual('localhost', host)
+ self.assertEqual(10080, port)
+ self.assertEqual('/ws/test', resource)
+
+ host, port, resource = http_header_util.parse_uri(
+ 'ws://example.com/ws/test')
+ self.assertEqual('example.com', host)
+ self.assertEqual(80, port)
+ self.assertEqual('/ws/test', resource)
+
+ host, port, resource = http_header_util.parse_uri(
+ 'wss://example.com/')
+ self.assertEqual('example.com', host)
+ self.assertEqual(443, port)
+ self.assertEqual('/', resource)
+
+ host, port, resource = http_header_util.parse_uri(
+ 'ws://example.com:8080')
+ self.assertEqual('example.com', host)
+ self.assertEqual(8080, port)
+ self.assertEqual('/', resource)
+
+ def test_parse_invalid_uri(self):
+ host, port, resource = http_header_util.parse_uri('ws:///')
+ self.assertEqual(None, resource)
+
+ host, port, resource = http_header_util.parse_uri('ws://localhost:')
+ self.assertEqual(None, resource)
+
+ host, port, resource = http_header_util.parse_uri('ws://localhost:/ws')
+ self.assertEqual(None, resource)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/test_memorizingfile.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/test_memorizingfile.py
new file mode 100755
index 00000000000..8f1b8eef433
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/test_memorizingfile.py
@@ -0,0 +1,104 @@
+#!/usr/bin/env python
+#
+# Copyright 2011, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+"""Tests for memorizingfile module."""
+
+
+import StringIO
+import unittest
+
+import set_sys_path # Update sys.path to locate mod_pywebsocket module.
+
+from mod_pywebsocket import memorizingfile
+
+
+class UtilTest(unittest.TestCase):
+ """A unittest for memorizingfile module."""
+
+ def check(self, memorizing_file, num_read, expected_list):
+ for unused in range(num_read):
+ memorizing_file.readline()
+ actual_list = memorizing_file.get_memorized_lines()
+ self.assertEqual(len(expected_list), len(actual_list))
+ for expected, actual in zip(expected_list, actual_list):
+ self.assertEqual(expected, actual)
+
+ def check_with_size(self, memorizing_file, read_size, expected_list):
+ read_list = []
+ read_line = ''
+ while True:
+ line = memorizing_file.readline(read_size)
+ line_length = len(line)
+ self.assertTrue(line_length <= read_size)
+ if line_length == 0:
+ if read_line != '':
+ read_list.append(read_line)
+ break
+ read_line += line
+ if line[line_length - 1] == '\n':
+ read_list.append(read_line)
+ read_line = ''
+ actual_list = memorizing_file.get_memorized_lines()
+ self.assertEqual(len(expected_list), len(actual_list))
+ self.assertEqual(len(expected_list), len(read_list))
+ for expected, actual, read in zip(expected_list, actual_list,
+ read_list):
+ self.assertEqual(expected, actual)
+ self.assertEqual(expected, read)
+
+ def test_get_memorized_lines(self):
+ memorizing_file = memorizingfile.MemorizingFile(StringIO.StringIO(
+ 'Hello\nWorld\nWelcome'))
+ self.check(memorizing_file, 3, ['Hello\n', 'World\n', 'Welcome'])
+
+ def test_get_memorized_lines_limit_memorized_lines(self):
+ memorizing_file = memorizingfile.MemorizingFile(StringIO.StringIO(
+ 'Hello\nWorld\nWelcome'), 2)
+ self.check(memorizing_file, 3, ['Hello\n', 'World\n'])
+
+ def test_get_memorized_lines_empty_file(self):
+ memorizing_file = memorizingfile.MemorizingFile(StringIO.StringIO(
+ ''))
+ self.check(memorizing_file, 10, [])
+
+ def test_get_memorized_lines_with_size(self):
+ for size in range(1, 10):
+ memorizing_file = memorizingfile.MemorizingFile(StringIO.StringIO(
+ 'Hello\nWorld\nWelcome'))
+ self.check_with_size(memorizing_file, size,
+ ['Hello\n', 'World\n', 'Welcome'])
+
+if __name__ == '__main__':
+ unittest.main()
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/test_mock.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/test_mock.py
new file mode 100755
index 00000000000..7dc23a73d8f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/test_mock.py
@@ -0,0 +1,145 @@
+#!/usr/bin/env python
+#
+# Copyright 2011, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+"""Tests for mock module."""
+
+
+import Queue
+import threading
+import unittest
+
+import set_sys_path # Update sys.path to locate mod_pywebsocket module.
+
+from test import mock
+
+
+class MockConnTest(unittest.TestCase):
+ """A unittest for MockConn class."""
+
+ def setUp(self):
+ self._conn = mock.MockConn('ABC\r\nDEFG\r\n\r\nHIJK')
+
+ def test_readline(self):
+ self.assertEqual('ABC\r\n', self._conn.readline())
+ self.assertEqual('DEFG\r\n', self._conn.readline())
+ self.assertEqual('\r\n', self._conn.readline())
+ self.assertEqual('HIJK', self._conn.readline())
+ self.assertEqual('', self._conn.readline())
+
+ def test_read(self):
+ self.assertEqual('ABC\r\nD', self._conn.read(6))
+ self.assertEqual('EFG\r\n\r\nHI', self._conn.read(9))
+ self.assertEqual('JK', self._conn.read(10))
+ self.assertEqual('', self._conn.read(10))
+
+ def test_read_and_readline(self):
+ self.assertEqual('ABC\r\nD', self._conn.read(6))
+ self.assertEqual('EFG\r\n', self._conn.readline())
+ self.assertEqual('\r\nHIJK', self._conn.read(9))
+ self.assertEqual('', self._conn.readline())
+
+ def test_write(self):
+ self._conn.write('Hello\r\n')
+ self._conn.write('World\r\n')
+ self.assertEqual('Hello\r\nWorld\r\n', self._conn.written_data())
+
+
+class MockBlockingConnTest(unittest.TestCase):
+ """A unittest for MockBlockingConn class."""
+
+ def test_read(self):
+ """Tests that data put to MockBlockingConn by put_bytes method can be
+ read from it.
+ """
+
+ class LineReader(threading.Thread):
+ """A test class that launches a thread, calls readline on the
+ specified conn repeatedly and puts the read data to the specified
+ queue.
+ """
+
+ def __init__(self, conn, queue):
+ threading.Thread.__init__(self)
+ self._queue = queue
+ self._conn = conn
+ self.setDaemon(True)
+ self.start()
+
+ def run(self):
+ while True:
+ data = self._conn.readline()
+ self._queue.put(data)
+
+ conn = mock.MockBlockingConn()
+ queue = Queue.Queue()
+ reader = LineReader(conn, queue)
+ self.failUnless(queue.empty())
+ conn.put_bytes('Foo bar\r\n')
+ read = queue.get()
+ self.assertEqual('Foo bar\r\n', read)
+
+
+class MockTableTest(unittest.TestCase):
+ """A unittest for MockTable class."""
+
+ def test_create_from_dict(self):
+ table = mock.MockTable({'Key': 'Value'})
+ self.assertEqual('Value', table.get('KEY'))
+ self.assertEqual('Value', table['key'])
+
+ def test_create_from_list(self):
+ table = mock.MockTable([('Key', 'Value')])
+ self.assertEqual('Value', table.get('KEY'))
+ self.assertEqual('Value', table['key'])
+
+ def test_create_from_tuple(self):
+ table = mock.MockTable((('Key', 'Value'),))
+ self.assertEqual('Value', table.get('KEY'))
+ self.assertEqual('Value', table['key'])
+
+ def test_set_and_get(self):
+ table = mock.MockTable()
+ self.assertEqual(None, table.get('Key'))
+ table['Key'] = 'Value'
+ self.assertEqual('Value', table.get('Key'))
+ self.assertEqual('Value', table.get('key'))
+ self.assertEqual('Value', table.get('KEY'))
+ self.assertEqual('Value', table['Key'])
+ self.assertEqual('Value', table['key'])
+ self.assertEqual('Value', table['KEY'])
+
+
+if __name__ == '__main__':
+ unittest.main()
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/test_msgutil.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/test_msgutil.py
new file mode 100755
index 00000000000..5fedcf92f61
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/test_msgutil.py
@@ -0,0 +1,1356 @@
+#!/usr/bin/env python
+#
+# Copyright 2012, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+"""Tests for msgutil module."""
+
+
+import array
+import Queue
+import random
+import struct
+import unittest
+import zlib
+
+import set_sys_path # Update sys.path to locate mod_pywebsocket module.
+
+from mod_pywebsocket import common
+from mod_pywebsocket.extensions import DeflateFrameExtensionProcessor
+from mod_pywebsocket.extensions import PerMessageCompressExtensionProcessor
+from mod_pywebsocket.extensions import PerMessageDeflateExtensionProcessor
+from mod_pywebsocket import msgutil
+from mod_pywebsocket.stream import InvalidUTF8Exception
+from mod_pywebsocket.stream import Stream
+from mod_pywebsocket.stream import StreamHixie75
+from mod_pywebsocket.stream import StreamOptions
+from mod_pywebsocket import util
+from test import mock
+
+
+# We use one fixed nonce for testing instead of cryptographically secure PRNG.
+_MASKING_NONCE = 'ABCD'
+
+
+def _mask_hybi(frame):
+ frame_key = map(ord, _MASKING_NONCE)
+ frame_key_len = len(frame_key)
+ result = array.array('B')
+ result.fromstring(frame)
+ count = 0
+ for i in xrange(len(result)):
+ result[i] ^= frame_key[count]
+ count = (count + 1) % frame_key_len
+ return _MASKING_NONCE + result.tostring()
+
+
+def _install_extension_processor(processor, request, stream_options):
+ response = processor.get_extension_response()
+ if response is not None:
+ processor.setup_stream_options(stream_options)
+ request.ws_extension_processors.append(processor)
+
+
+def _create_request_from_rawdata(
+ read_data,
+ deflate_frame_request=None,
+ permessage_compression_request=None,
+ permessage_deflate_request=None):
+ req = mock.MockRequest(connection=mock.MockConn(''.join(read_data)))
+ req.ws_version = common.VERSION_HYBI_LATEST
+ req.ws_extension_processors = []
+
+ processor = None
+ if deflate_frame_request is not None:
+ processor = DeflateFrameExtensionProcessor(deflate_frame_request)
+ elif permessage_compression_request is not None:
+ processor = PerMessageCompressExtensionProcessor(
+ permessage_compression_request)
+ elif permessage_deflate_request is not None:
+ processor = PerMessageDeflateExtensionProcessor(
+ permessage_deflate_request)
+
+ stream_options = StreamOptions()
+ if processor is not None:
+ _install_extension_processor(processor, req, stream_options)
+ req.ws_stream = Stream(req, stream_options)
+
+ return req
+
+
+def _create_request(*frames):
+ """Creates MockRequest using data given as frames.
+
+ frames will be returned on calling request.connection.read() where request
+ is MockRequest returned by this function.
+ """
+
+ read_data = []
+ for (header, body) in frames:
+ read_data.append(header + _mask_hybi(body))
+
+ return _create_request_from_rawdata(read_data)
+
+
+def _create_blocking_request():
+ """Creates MockRequest.
+
+ Data written to a MockRequest can be read out by calling
+ request.connection.written_data().
+ """
+
+ req = mock.MockRequest(connection=mock.MockBlockingConn())
+ req.ws_version = common.VERSION_HYBI_LATEST
+ stream_options = StreamOptions()
+ req.ws_stream = Stream(req, stream_options)
+ return req
+
+
+def _create_request_hixie75(read_data=''):
+ req = mock.MockRequest(connection=mock.MockConn(read_data))
+ req.ws_stream = StreamHixie75(req)
+ return req
+
+
+def _create_blocking_request_hixie75():
+ req = mock.MockRequest(connection=mock.MockBlockingConn())
+ req.ws_stream = StreamHixie75(req)
+ return req
+
+
+class BasicMessageTest(unittest.TestCase):
+ """Basic tests for Stream."""
+
+ def test_send_message(self):
+ request = _create_request()
+ msgutil.send_message(request, 'Hello')
+ self.assertEqual('\x81\x05Hello', request.connection.written_data())
+
+ payload = 'a' * 125
+ request = _create_request()
+ msgutil.send_message(request, payload)
+ self.assertEqual('\x81\x7d' + payload,
+ request.connection.written_data())
+
+ def test_send_medium_message(self):
+ payload = 'a' * 126
+ request = _create_request()
+ msgutil.send_message(request, payload)
+ self.assertEqual('\x81\x7e\x00\x7e' + payload,
+ request.connection.written_data())
+
+ payload = 'a' * ((1 << 16) - 1)
+ request = _create_request()
+ msgutil.send_message(request, payload)
+ self.assertEqual('\x81\x7e\xff\xff' + payload,
+ request.connection.written_data())
+
+ def test_send_large_message(self):
+ payload = 'a' * (1 << 16)
+ request = _create_request()
+ msgutil.send_message(request, payload)
+ self.assertEqual('\x81\x7f\x00\x00\x00\x00\x00\x01\x00\x00' + payload,
+ request.connection.written_data())
+
+ def test_send_message_unicode(self):
+ request = _create_request()
+ msgutil.send_message(request, u'\u65e5')
+ # U+65e5 is encoded as e6,97,a5 in UTF-8
+ self.assertEqual('\x81\x03\xe6\x97\xa5',
+ request.connection.written_data())
+
+ def test_send_message_fragments(self):
+ request = _create_request()
+ msgutil.send_message(request, 'Hello', False)
+ msgutil.send_message(request, ' ', False)
+ msgutil.send_message(request, 'World', False)
+ msgutil.send_message(request, '!', True)
+ self.assertEqual('\x01\x05Hello\x00\x01 \x00\x05World\x80\x01!',
+ request.connection.written_data())
+
+ def test_send_fragments_immediate_zero_termination(self):
+ request = _create_request()
+ msgutil.send_message(request, 'Hello World!', False)
+ msgutil.send_message(request, '', True)
+ self.assertEqual('\x01\x0cHello World!\x80\x00',
+ request.connection.written_data())
+
+ def test_receive_message(self):
+ request = _create_request(
+ ('\x81\x85', 'Hello'), ('\x81\x86', 'World!'))
+ self.assertEqual('Hello', msgutil.receive_message(request))
+ self.assertEqual('World!', msgutil.receive_message(request))
+
+ payload = 'a' * 125
+ request = _create_request(('\x81\xfd', payload))
+ self.assertEqual(payload, msgutil.receive_message(request))
+
+ def test_receive_medium_message(self):
+ payload = 'a' * 126
+ request = _create_request(('\x81\xfe\x00\x7e', payload))
+ self.assertEqual(payload, msgutil.receive_message(request))
+
+ payload = 'a' * ((1 << 16) - 1)
+ request = _create_request(('\x81\xfe\xff\xff', payload))
+ self.assertEqual(payload, msgutil.receive_message(request))
+
+ def test_receive_large_message(self):
+ payload = 'a' * (1 << 16)
+ request = _create_request(
+ ('\x81\xff\x00\x00\x00\x00\x00\x01\x00\x00', payload))
+ self.assertEqual(payload, msgutil.receive_message(request))
+
+ def test_receive_length_not_encoded_using_minimal_number_of_bytes(self):
+ # Log warning on receiving bad payload length field that doesn't use
+ # minimal number of bytes but continue processing.
+
+ payload = 'a'
+ # 1 byte can be represented without extended payload length field.
+ request = _create_request(
+ ('\x81\xff\x00\x00\x00\x00\x00\x00\x00\x01', payload))
+ self.assertEqual(payload, msgutil.receive_message(request))
+
+ def test_receive_message_unicode(self):
+ request = _create_request(('\x81\x83', '\xe6\x9c\xac'))
+ # U+672c is encoded as e6,9c,ac in UTF-8
+ self.assertEqual(u'\u672c', msgutil.receive_message(request))
+
+ def test_receive_message_erroneous_unicode(self):
+ # \x80 and \x81 are invalid as UTF-8.
+ request = _create_request(('\x81\x82', '\x80\x81'))
+ # Invalid characters should raise InvalidUTF8Exception
+ self.assertRaises(InvalidUTF8Exception,
+ msgutil.receive_message,
+ request)
+
+ def test_receive_fragments(self):
+ request = _create_request(
+ ('\x01\x85', 'Hello'),
+ ('\x00\x81', ' '),
+ ('\x00\x85', 'World'),
+ ('\x80\x81', '!'))
+ self.assertEqual('Hello World!', msgutil.receive_message(request))
+
+ def test_receive_fragments_unicode(self):
+ # UTF-8 encodes U+6f22 into e6bca2 and U+5b57 into e5ad97.
+ request = _create_request(
+ ('\x01\x82', '\xe6\xbc'),
+ ('\x00\x82', '\xa2\xe5'),
+ ('\x80\x82', '\xad\x97'))
+ self.assertEqual(u'\u6f22\u5b57', msgutil.receive_message(request))
+
+ def test_receive_fragments_immediate_zero_termination(self):
+ request = _create_request(
+ ('\x01\x8c', 'Hello World!'), ('\x80\x80', ''))
+ self.assertEqual('Hello World!', msgutil.receive_message(request))
+
+ def test_receive_fragments_duplicate_start(self):
+ request = _create_request(
+ ('\x01\x85', 'Hello'), ('\x01\x85', 'World'))
+ self.assertRaises(msgutil.InvalidFrameException,
+ msgutil.receive_message,
+ request)
+
+ def test_receive_fragments_intermediate_but_not_started(self):
+ request = _create_request(('\x00\x85', 'Hello'))
+ self.assertRaises(msgutil.InvalidFrameException,
+ msgutil.receive_message,
+ request)
+
+ def test_receive_fragments_end_but_not_started(self):
+ request = _create_request(('\x80\x85', 'Hello'))
+ self.assertRaises(msgutil.InvalidFrameException,
+ msgutil.receive_message,
+ request)
+
+ def test_receive_message_discard(self):
+ request = _create_request(
+ ('\x8f\x86', 'IGNORE'), ('\x81\x85', 'Hello'),
+ ('\x8f\x89', 'DISREGARD'), ('\x81\x86', 'World!'))
+ self.assertRaises(msgutil.UnsupportedFrameException,
+ msgutil.receive_message, request)
+ self.assertEqual('Hello', msgutil.receive_message(request))
+ self.assertRaises(msgutil.UnsupportedFrameException,
+ msgutil.receive_message, request)
+ self.assertEqual('World!', msgutil.receive_message(request))
+
+ def test_receive_close(self):
+ request = _create_request(
+ ('\x88\x8a', struct.pack('!H', 1000) + 'Good bye'))
+ self.assertEqual(None, msgutil.receive_message(request))
+ self.assertEqual(1000, request.ws_close_code)
+ self.assertEqual('Good bye', request.ws_close_reason)
+
+ def test_send_longest_close(self):
+ reason = 'a' * 123
+ request = _create_request(
+ ('\x88\xfd',
+ struct.pack('!H', common.STATUS_NORMAL_CLOSURE) + reason))
+ request.ws_stream.close_connection(common.STATUS_NORMAL_CLOSURE,
+ reason)
+ self.assertEqual(request.ws_close_code, common.STATUS_NORMAL_CLOSURE)
+ self.assertEqual(request.ws_close_reason, reason)
+
+ def test_send_close_too_long(self):
+ request = _create_request()
+ self.assertRaises(msgutil.BadOperationException,
+ Stream.close_connection,
+ request.ws_stream,
+ common.STATUS_NORMAL_CLOSURE,
+ 'a' * 124)
+
+ def test_send_close_inconsistent_code_and_reason(self):
+ request = _create_request()
+ # reason parameter must not be specified when code is None.
+ self.assertRaises(msgutil.BadOperationException,
+ Stream.close_connection,
+ request.ws_stream,
+ None,
+ 'a')
+
+ def test_send_ping(self):
+ request = _create_request()
+ msgutil.send_ping(request, 'Hello World!')
+ self.assertEqual('\x89\x0cHello World!',
+ request.connection.written_data())
+
+ def test_send_longest_ping(self):
+ request = _create_request()
+ msgutil.send_ping(request, 'a' * 125)
+ self.assertEqual('\x89\x7d' + 'a' * 125,
+ request.connection.written_data())
+
+ def test_send_ping_too_long(self):
+ request = _create_request()
+ self.assertRaises(msgutil.BadOperationException,
+ msgutil.send_ping,
+ request,
+ 'a' * 126)
+
+ def test_receive_ping(self):
+ """Tests receiving a ping control frame."""
+
+ def handler(request, message):
+ request.called = True
+
+ # Stream automatically respond to ping with pong without any action
+ # by application layer.
+ request = _create_request(
+ ('\x89\x85', 'Hello'), ('\x81\x85', 'World'))
+ self.assertEqual('World', msgutil.receive_message(request))
+ self.assertEqual('\x8a\x05Hello',
+ request.connection.written_data())
+
+ request = _create_request(
+ ('\x89\x85', 'Hello'), ('\x81\x85', 'World'))
+ request.on_ping_handler = handler
+ self.assertEqual('World', msgutil.receive_message(request))
+ self.assertTrue(request.called)
+
+ def test_receive_longest_ping(self):
+ request = _create_request(
+ ('\x89\xfd', 'a' * 125), ('\x81\x85', 'World'))
+ self.assertEqual('World', msgutil.receive_message(request))
+ self.assertEqual('\x8a\x7d' + 'a' * 125,
+ request.connection.written_data())
+
+ def test_receive_ping_too_long(self):
+ request = _create_request(('\x89\xfe\x00\x7e', 'a' * 126))
+ self.assertRaises(msgutil.InvalidFrameException,
+ msgutil.receive_message,
+ request)
+
+ def test_receive_pong(self):
+ """Tests receiving a pong control frame."""
+
+ def handler(request, message):
+ request.called = True
+
+ request = _create_request(
+ ('\x8a\x85', 'Hello'), ('\x81\x85', 'World'))
+ request.on_pong_handler = handler
+ msgutil.send_ping(request, 'Hello')
+ self.assertEqual('\x89\x05Hello',
+ request.connection.written_data())
+ # Valid pong is received, but receive_message won't return for it.
+ self.assertEqual('World', msgutil.receive_message(request))
+ # Check that nothing was written after receive_message call.
+ self.assertEqual('\x89\x05Hello',
+ request.connection.written_data())
+
+ self.assertTrue(request.called)
+
+ def test_receive_unsolicited_pong(self):
+ # Unsolicited pong is allowed from HyBi 07.
+ request = _create_request(
+ ('\x8a\x85', 'Hello'), ('\x81\x85', 'World'))
+ msgutil.receive_message(request)
+
+ request = _create_request(
+ ('\x8a\x85', 'Hello'), ('\x81\x85', 'World'))
+ msgutil.send_ping(request, 'Jumbo')
+ # Body mismatch.
+ msgutil.receive_message(request)
+
+ def test_ping_cannot_be_fragmented(self):
+ request = _create_request(('\x09\x85', 'Hello'))
+ self.assertRaises(msgutil.InvalidFrameException,
+ msgutil.receive_message,
+ request)
+
+ def test_ping_with_too_long_payload(self):
+ request = _create_request(('\x89\xfe\x01\x00', 'a' * 256))
+ self.assertRaises(msgutil.InvalidFrameException,
+ msgutil.receive_message,
+ request)
+
+
+class DeflateFrameTest(unittest.TestCase):
+ """Tests for checking deflate-frame extension."""
+
+ def test_send_message(self):
+ compress = zlib.compressobj(
+ zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -zlib.MAX_WBITS)
+
+ extension = common.ExtensionParameter(common.DEFLATE_FRAME_EXTENSION)
+ request = _create_request_from_rawdata(
+ '', deflate_frame_request=extension)
+ msgutil.send_message(request, 'Hello')
+ msgutil.send_message(request, 'World')
+
+ expected = ''
+
+ compressed_hello = compress.compress('Hello')
+ compressed_hello += compress.flush(zlib.Z_SYNC_FLUSH)
+ compressed_hello = compressed_hello[:-4]
+ expected += '\xc1%c' % len(compressed_hello)
+ expected += compressed_hello
+
+ compressed_world = compress.compress('World')
+ compressed_world += compress.flush(zlib.Z_SYNC_FLUSH)
+ compressed_world = compressed_world[:-4]
+ expected += '\xc1%c' % len(compressed_world)
+ expected += compressed_world
+
+ self.assertEqual(expected, request.connection.written_data())
+
+ def test_send_message_bfinal(self):
+ extension = common.ExtensionParameter(common.DEFLATE_FRAME_EXTENSION)
+ request = _create_request_from_rawdata(
+ '', deflate_frame_request=extension)
+ self.assertEquals(1, len(request.ws_extension_processors))
+ deflate_frame_processor = request.ws_extension_processors[0]
+ deflate_frame_processor.set_bfinal(True)
+ msgutil.send_message(request, 'Hello')
+ msgutil.send_message(request, 'World')
+
+ expected = ''
+
+ compress = zlib.compressobj(
+ zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -zlib.MAX_WBITS)
+ compressed_hello = compress.compress('Hello')
+ compressed_hello += compress.flush(zlib.Z_FINISH)
+ compressed_hello = compressed_hello + chr(0)
+ expected += '\xc1%c' % len(compressed_hello)
+ expected += compressed_hello
+
+ compress = zlib.compressobj(
+ zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -zlib.MAX_WBITS)
+ compressed_world = compress.compress('World')
+ compressed_world += compress.flush(zlib.Z_FINISH)
+ compressed_world = compressed_world + chr(0)
+ expected += '\xc1%c' % len(compressed_world)
+ expected += compressed_world
+
+ self.assertEqual(expected, request.connection.written_data())
+
+ def test_send_message_comp_bit(self):
+ compress = zlib.compressobj(
+ zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -zlib.MAX_WBITS)
+
+ extension = common.ExtensionParameter(common.DEFLATE_FRAME_EXTENSION)
+ request = _create_request_from_rawdata(
+ '', deflate_frame_request=extension)
+ self.assertEquals(1, len(request.ws_extension_processors))
+ deflate_frame_processor = request.ws_extension_processors[0]
+ msgutil.send_message(request, 'Hello')
+ deflate_frame_processor.disable_outgoing_compression()
+ msgutil.send_message(request, 'Hello')
+ deflate_frame_processor.enable_outgoing_compression()
+ msgutil.send_message(request, 'Hello')
+
+ expected = ''
+
+ compressed_hello = compress.compress('Hello')
+ compressed_hello += compress.flush(zlib.Z_SYNC_FLUSH)
+ compressed_hello = compressed_hello[:-4]
+ expected += '\xc1%c' % len(compressed_hello)
+ expected += compressed_hello
+
+ expected += '\x81\x05Hello'
+
+ compressed_2nd_hello = compress.compress('Hello')
+ compressed_2nd_hello += compress.flush(zlib.Z_SYNC_FLUSH)
+ compressed_2nd_hello = compressed_2nd_hello[:-4]
+ expected += '\xc1%c' % len(compressed_2nd_hello)
+ expected += compressed_2nd_hello
+
+ self.assertEqual(expected, request.connection.written_data())
+
+ def test_send_message_no_context_takeover_parameter(self):
+ compress = zlib.compressobj(
+ zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -zlib.MAX_WBITS)
+
+ extension = common.ExtensionParameter(common.DEFLATE_FRAME_EXTENSION)
+ extension.add_parameter('no_context_takeover', None)
+ request = _create_request_from_rawdata(
+ '', deflate_frame_request=extension)
+ for i in xrange(3):
+ msgutil.send_message(request, 'Hello')
+
+ compressed_message = compress.compress('Hello')
+ compressed_message += compress.flush(zlib.Z_SYNC_FLUSH)
+ compressed_message = compressed_message[:-4]
+ expected = '\xc1%c' % len(compressed_message)
+ expected += compressed_message
+
+ self.assertEqual(
+ expected + expected + expected, request.connection.written_data())
+
+ def test_bad_request_parameters(self):
+ """Tests that if there's anything wrong with deflate-frame extension
+ request, deflate-frame is rejected.
+ """
+
+ extension = common.ExtensionParameter(common.DEFLATE_FRAME_EXTENSION)
+ # max_window_bits less than 8 is illegal.
+ extension.add_parameter('max_window_bits', '7')
+ processor = DeflateFrameExtensionProcessor(extension)
+ self.assertEqual(None, processor.get_extension_response())
+
+ extension = common.ExtensionParameter(common.DEFLATE_FRAME_EXTENSION)
+ # max_window_bits greater than 15 is illegal.
+ extension.add_parameter('max_window_bits', '16')
+ processor = DeflateFrameExtensionProcessor(extension)
+ self.assertEqual(None, processor.get_extension_response())
+
+ extension = common.ExtensionParameter(common.DEFLATE_FRAME_EXTENSION)
+ # Non integer max_window_bits is illegal.
+ extension.add_parameter('max_window_bits', 'foobar')
+ processor = DeflateFrameExtensionProcessor(extension)
+ self.assertEqual(None, processor.get_extension_response())
+
+ extension = common.ExtensionParameter(common.DEFLATE_FRAME_EXTENSION)
+ # no_context_takeover must not have any value.
+ extension.add_parameter('no_context_takeover', 'foobar')
+ processor = DeflateFrameExtensionProcessor(extension)
+ self.assertEqual(None, processor.get_extension_response())
+
+ def test_response_parameters(self):
+ extension = common.ExtensionParameter(common.DEFLATE_FRAME_EXTENSION)
+ processor = DeflateFrameExtensionProcessor(extension)
+ processor.set_response_window_bits(8)
+ response = processor.get_extension_response()
+ self.assertTrue(response.has_parameter('max_window_bits'))
+ self.assertEqual('8', response.get_parameter_value('max_window_bits'))
+
+ extension = common.ExtensionParameter(common.DEFLATE_FRAME_EXTENSION)
+ processor = DeflateFrameExtensionProcessor(extension)
+ processor.set_response_no_context_takeover(True)
+ response = processor.get_extension_response()
+ self.assertTrue(response.has_parameter('no_context_takeover'))
+ self.assertTrue(
+ response.get_parameter_value('no_context_takeover') is None)
+
+ def test_receive_message(self):
+ compress = zlib.compressobj(
+ zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -zlib.MAX_WBITS)
+
+ data = ''
+
+ compressed_hello = compress.compress('Hello')
+ compressed_hello += compress.flush(zlib.Z_SYNC_FLUSH)
+ compressed_hello = compressed_hello[:-4]
+ data += '\xc1%c' % (len(compressed_hello) | 0x80)
+ data += _mask_hybi(compressed_hello)
+
+ compressed_websocket = compress.compress('WebSocket')
+ compressed_websocket += compress.flush(zlib.Z_FINISH)
+ compressed_websocket += '\x00'
+ data += '\xc1%c' % (len(compressed_websocket) | 0x80)
+ data += _mask_hybi(compressed_websocket)
+
+ compress = zlib.compressobj(
+ zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -zlib.MAX_WBITS)
+
+ compressed_world = compress.compress('World')
+ compressed_world += compress.flush(zlib.Z_SYNC_FLUSH)
+ compressed_world = compressed_world[:-4]
+ data += '\xc1%c' % (len(compressed_world) | 0x80)
+ data += _mask_hybi(compressed_world)
+
+ # Close frame
+ data += '\x88\x8a' + _mask_hybi(struct.pack('!H', 1000) + 'Good bye')
+
+ extension = common.ExtensionParameter(common.DEFLATE_FRAME_EXTENSION)
+ request = _create_request_from_rawdata(
+ data, deflate_frame_request=extension)
+ self.assertEqual('Hello', msgutil.receive_message(request))
+ self.assertEqual('WebSocket', msgutil.receive_message(request))
+ self.assertEqual('World', msgutil.receive_message(request))
+
+ self.assertEqual(None, msgutil.receive_message(request))
+
+ def test_receive_message_client_using_smaller_window(self):
+ """Test that frames coming from a client which is using smaller window
+ size that the server are correctly received.
+ """
+
+ # Using the smallest window bits of 8 for generating input frames.
+ compress = zlib.compressobj(
+ zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -8)
+
+ data = ''
+
+ # Use a frame whose content is bigger than the clients' DEFLATE window
+ # size before compression. The content mainly consists of 'a' but
+ # repetition of 'b' is put at the head and tail so that if the window
+ # size is big, the head is back-referenced but if small, not.
+ payload = 'b' * 64 + 'a' * 1024 + 'b' * 64
+ compressed_hello = compress.compress(payload)
+ compressed_hello += compress.flush(zlib.Z_SYNC_FLUSH)
+ compressed_hello = compressed_hello[:-4]
+ data += '\xc1%c' % (len(compressed_hello) | 0x80)
+ data += _mask_hybi(compressed_hello)
+
+ # Close frame
+ data += '\x88\x8a' + _mask_hybi(struct.pack('!H', 1000) + 'Good bye')
+
+ extension = common.ExtensionParameter(common.DEFLATE_FRAME_EXTENSION)
+ request = _create_request_from_rawdata(
+ data, deflate_frame_request=extension)
+ self.assertEqual(payload, msgutil.receive_message(request))
+
+ self.assertEqual(None, msgutil.receive_message(request))
+
+ def test_receive_message_comp_bit(self):
+ compress = zlib.compressobj(
+ zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -zlib.MAX_WBITS)
+
+ data = ''
+
+ compressed_hello = compress.compress('Hello')
+ compressed_hello += compress.flush(zlib.Z_SYNC_FLUSH)
+ compressed_hello = compressed_hello[:-4]
+ data += '\xc1%c' % (len(compressed_hello) | 0x80)
+ data += _mask_hybi(compressed_hello)
+
+ data += '\x81\x85' + _mask_hybi('Hello')
+
+ compress = zlib.compressobj(
+ zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -zlib.MAX_WBITS)
+
+ compressed_2nd_hello = compress.compress('Hello')
+ compressed_2nd_hello += compress.flush(zlib.Z_SYNC_FLUSH)
+ compressed_2nd_hello = compressed_2nd_hello[:-4]
+ data += '\xc1%c' % (len(compressed_2nd_hello) | 0x80)
+ data += _mask_hybi(compressed_2nd_hello)
+
+ extension = common.ExtensionParameter(common.DEFLATE_FRAME_EXTENSION)
+ request = _create_request_from_rawdata(
+ data, deflate_frame_request=extension)
+ for i in xrange(3):
+ self.assertEqual('Hello', msgutil.receive_message(request))
+
+ def test_receive_message_various_btype(self):
+ compress = zlib.compressobj(
+ zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -zlib.MAX_WBITS)
+
+ data = ''
+
+ compressed_hello = compress.compress('Hello')
+ compressed_hello += compress.flush(zlib.Z_SYNC_FLUSH)
+ compressed_hello = compressed_hello[:-4]
+ data += '\xc1%c' % (len(compressed_hello) | 0x80)
+ data += _mask_hybi(compressed_hello)
+
+ compressed_websocket = compress.compress('WebSocket')
+ compressed_websocket += compress.flush(zlib.Z_FINISH)
+ compressed_websocket += '\x00'
+ data += '\xc1%c' % (len(compressed_websocket) | 0x80)
+ data += _mask_hybi(compressed_websocket)
+
+ compress = zlib.compressobj(
+ zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -zlib.MAX_WBITS)
+
+ compressed_world = compress.compress('World')
+ compressed_world += compress.flush(zlib.Z_SYNC_FLUSH)
+ compressed_world = compressed_world[:-4]
+ data += '\xc1%c' % (len(compressed_world) | 0x80)
+ data += _mask_hybi(compressed_world)
+
+ # Close frame
+ data += '\x88\x8a' + _mask_hybi(struct.pack('!H', 1000) + 'Good bye')
+
+ extension = common.ExtensionParameter(common.DEFLATE_FRAME_EXTENSION)
+ request = _create_request_from_rawdata(
+ data, deflate_frame_request=extension)
+ self.assertEqual('Hello', msgutil.receive_message(request))
+ self.assertEqual('WebSocket', msgutil.receive_message(request))
+ self.assertEqual('World', msgutil.receive_message(request))
+
+ self.assertEqual(None, msgutil.receive_message(request))
+
+
+class PerMessageDeflateTest(unittest.TestCase):
+ """Tests for permessage-deflate extension."""
+
+ def test_send_message(self):
+ extension = common.ExtensionParameter(
+ common.PERMESSAGE_DEFLATE_EXTENSION)
+ request = _create_request_from_rawdata(
+ '', permessage_deflate_request=extension)
+ msgutil.send_message(request, 'Hello')
+
+ compress = zlib.compressobj(
+ zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -zlib.MAX_WBITS)
+ compressed_hello = compress.compress('Hello')
+ compressed_hello += compress.flush(zlib.Z_SYNC_FLUSH)
+ compressed_hello = compressed_hello[:-4]
+ expected = '\xc1%c' % len(compressed_hello)
+ expected += compressed_hello
+ self.assertEqual(expected, request.connection.written_data())
+
+ def test_send_empty_message(self):
+ """Test that an empty message is compressed correctly."""
+
+ extension = common.ExtensionParameter(
+ common.PERMESSAGE_DEFLATE_EXTENSION)
+ request = _create_request_from_rawdata(
+ '', permessage_deflate_request=extension)
+
+ msgutil.send_message(request, '')
+
+ # Payload in binary: 0b00000010 0b00000000
+ # From LSB,
+ # - 1 bit of BFINAL (0)
+ # - 2 bits of BTYPE (01 that means fixed Huffman)
+ # - 7 bits of the first code (0000000 that is the code for the
+ # end-of-block)
+ # - 1 bit of BFINAL (0)
+ # - 2 bits of BTYPE (no compression)
+ # - 3 bits of padding
+ self.assertEqual('\xc1\x02\x02\x00',
+ request.connection.written_data())
+
+ def test_send_message_with_null_character(self):
+ """Test that a simple payload (one null) is framed correctly."""
+
+ extension = common.ExtensionParameter(
+ common.PERMESSAGE_DEFLATE_EXTENSION)
+ request = _create_request_from_rawdata(
+ '', permessage_deflate_request=extension)
+
+ msgutil.send_message(request, '\x00')
+
+ # Payload in binary: 0b01100010 0b00000000 0b00000000
+ # From LSB,
+ # - 1 bit of BFINAL (0)
+ # - 2 bits of BTYPE (01 that means fixed Huffman)
+ # - 8 bits of the first code (00110000 that is the code for the literal
+ # alphabet 0x00)
+ # - 7 bits of the second code (0000000 that is the code for the
+ # end-of-block)
+ # - 1 bit of BFINAL (0)
+ # - 2 bits of BTYPE (no compression)
+ # - 2 bits of padding
+ self.assertEqual('\xc1\x03\x62\x00\x00',
+ request.connection.written_data())
+
+ def test_send_two_messages(self):
+ extension = common.ExtensionParameter(
+ common.PERMESSAGE_DEFLATE_EXTENSION)
+ request = _create_request_from_rawdata(
+ '', permessage_deflate_request=extension)
+ msgutil.send_message(request, 'Hello')
+ msgutil.send_message(request, 'World')
+
+ compress = zlib.compressobj(
+ zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -zlib.MAX_WBITS)
+
+ expected = ''
+
+ compressed_hello = compress.compress('Hello')
+ compressed_hello += compress.flush(zlib.Z_SYNC_FLUSH)
+ compressed_hello = compressed_hello[:-4]
+ expected += '\xc1%c' % len(compressed_hello)
+ expected += compressed_hello
+
+ compressed_world = compress.compress('World')
+ compressed_world += compress.flush(zlib.Z_SYNC_FLUSH)
+ compressed_world = compressed_world[:-4]
+ expected += '\xc1%c' % len(compressed_world)
+ expected += compressed_world
+
+ self.assertEqual(expected, request.connection.written_data())
+
+ def test_send_message_fragmented(self):
+ extension = common.ExtensionParameter(
+ common.PERMESSAGE_DEFLATE_EXTENSION)
+ request = _create_request_from_rawdata(
+ '', permessage_deflate_request=extension)
+ msgutil.send_message(request, 'Hello', end=False)
+ msgutil.send_message(request, 'Goodbye', end=False)
+ msgutil.send_message(request, 'World')
+
+ compress = zlib.compressobj(
+ zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -zlib.MAX_WBITS)
+ compressed_hello = compress.compress('Hello')
+ compressed_hello += compress.flush(zlib.Z_SYNC_FLUSH)
+ expected = '\x41%c' % len(compressed_hello)
+ expected += compressed_hello
+ compressed_goodbye = compress.compress('Goodbye')
+ compressed_goodbye += compress.flush(zlib.Z_SYNC_FLUSH)
+ expected += '\x00%c' % len(compressed_goodbye)
+ expected += compressed_goodbye
+ compressed_world = compress.compress('World')
+ compressed_world += compress.flush(zlib.Z_SYNC_FLUSH)
+ compressed_world = compressed_world[:-4]
+ expected += '\x80%c' % len(compressed_world)
+ expected += compressed_world
+ self.assertEqual(expected, request.connection.written_data())
+
+ def test_send_message_fragmented_empty_first_frame(self):
+ extension = common.ExtensionParameter(
+ common.PERMESSAGE_DEFLATE_EXTENSION)
+ request = _create_request_from_rawdata(
+ '', permessage_deflate_request=extension)
+ msgutil.send_message(request, '', end=False)
+ msgutil.send_message(request, 'Hello')
+
+ compress = zlib.compressobj(
+ zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -zlib.MAX_WBITS)
+ compressed_hello = compress.compress('')
+ compressed_hello += compress.flush(zlib.Z_SYNC_FLUSH)
+ expected = '\x41%c' % len(compressed_hello)
+ expected += compressed_hello
+ compressed_empty = compress.compress('Hello')
+ compressed_empty += compress.flush(zlib.Z_SYNC_FLUSH)
+ compressed_empty = compressed_empty[:-4]
+ expected += '\x80%c' % len(compressed_empty)
+ expected += compressed_empty
+ print '%r' % expected
+ self.assertEqual(expected, request.connection.written_data())
+
+ def test_send_message_fragmented_empty_last_frame(self):
+ extension = common.ExtensionParameter(
+ common.PERMESSAGE_DEFLATE_EXTENSION)
+ request = _create_request_from_rawdata(
+ '', permessage_deflate_request=extension)
+ msgutil.send_message(request, 'Hello', end=False)
+ msgutil.send_message(request, '')
+
+ compress = zlib.compressobj(
+ zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -zlib.MAX_WBITS)
+ compressed_hello = compress.compress('Hello')
+ compressed_hello += compress.flush(zlib.Z_SYNC_FLUSH)
+ expected = '\x41%c' % len(compressed_hello)
+ expected += compressed_hello
+ compressed_empty = compress.compress('')
+ compressed_empty += compress.flush(zlib.Z_SYNC_FLUSH)
+ compressed_empty = compressed_empty[:-4]
+ expected += '\x80%c' % len(compressed_empty)
+ expected += compressed_empty
+ self.assertEqual(expected, request.connection.written_data())
+
+ def test_send_message_using_small_window(self):
+ common_part = 'abcdefghijklmnopqrstuvwxyz'
+ test_message = common_part + '-' * 30000 + common_part
+
+ extension = common.ExtensionParameter(
+ common.PERMESSAGE_DEFLATE_EXTENSION)
+ extension.add_parameter('server_max_window_bits', '8')
+ request = _create_request_from_rawdata(
+ '', permessage_deflate_request=extension)
+ msgutil.send_message(request, test_message)
+
+ expected_websocket_header_size = 2
+ expected_websocket_payload_size = 91
+
+ actual_frame = request.connection.written_data()
+ self.assertEqual(expected_websocket_header_size +
+ expected_websocket_payload_size,
+ len(actual_frame))
+ actual_header = actual_frame[0:expected_websocket_header_size]
+ actual_payload = actual_frame[expected_websocket_header_size:]
+
+ self.assertEqual(
+ '\xc1%c' % expected_websocket_payload_size, actual_header)
+ decompress = zlib.decompressobj(-8)
+ decompressed_message = decompress.decompress(
+ actual_payload + '\x00\x00\xff\xff')
+ decompressed_message += decompress.flush()
+ self.assertEqual(test_message, decompressed_message)
+ self.assertEqual(0, len(decompress.unused_data))
+ self.assertEqual(0, len(decompress.unconsumed_tail))
+
+ def test_send_message_no_context_takeover_parameter(self):
+ extension = common.ExtensionParameter(
+ common.PERMESSAGE_DEFLATE_EXTENSION)
+ extension.add_parameter('server_no_context_takeover', None)
+ request = _create_request_from_rawdata(
+ '', permessage_deflate_request=extension)
+ for i in xrange(3):
+ msgutil.send_message(request, 'Hello', end=False)
+ msgutil.send_message(request, 'Hello', end=True)
+
+ compress = zlib.compressobj(
+ zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -zlib.MAX_WBITS)
+
+ first_hello = compress.compress('Hello')
+ first_hello += compress.flush(zlib.Z_SYNC_FLUSH)
+ expected = '\x41%c' % len(first_hello)
+ expected += first_hello
+ second_hello = compress.compress('Hello')
+ second_hello += compress.flush(zlib.Z_SYNC_FLUSH)
+ second_hello = second_hello[:-4]
+ expected += '\x80%c' % len(second_hello)
+ expected += second_hello
+
+ self.assertEqual(
+ expected + expected + expected,
+ request.connection.written_data())
+
+ def test_send_message_fragmented_bfinal(self):
+ extension = common.ExtensionParameter(
+ common.PERMESSAGE_DEFLATE_EXTENSION)
+ request = _create_request_from_rawdata(
+ '', permessage_deflate_request=extension)
+ self.assertEquals(1, len(request.ws_extension_processors))
+ request.ws_extension_processors[0].set_bfinal(True)
+ msgutil.send_message(request, 'Hello', end=False)
+ msgutil.send_message(request, 'World', end=True)
+
+ expected = ''
+
+ compress = zlib.compressobj(
+ zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -zlib.MAX_WBITS)
+ compressed_hello = compress.compress('Hello')
+ compressed_hello += compress.flush(zlib.Z_FINISH)
+ compressed_hello = compressed_hello + chr(0)
+ expected += '\x41%c' % len(compressed_hello)
+ expected += compressed_hello
+
+ compress = zlib.compressobj(
+ zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -zlib.MAX_WBITS)
+ compressed_world = compress.compress('World')
+ compressed_world += compress.flush(zlib.Z_FINISH)
+ compressed_world = compressed_world + chr(0)
+ expected += '\x80%c' % len(compressed_world)
+ expected += compressed_world
+
+ self.assertEqual(expected, request.connection.written_data())
+
+ def test_receive_message_deflate(self):
+ compress = zlib.compressobj(
+ zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -zlib.MAX_WBITS)
+
+ compressed_hello = compress.compress('Hello')
+ compressed_hello += compress.flush(zlib.Z_SYNC_FLUSH)
+ compressed_hello = compressed_hello[:-4]
+ data = '\xc1%c' % (len(compressed_hello) | 0x80)
+ data += _mask_hybi(compressed_hello)
+
+ # Close frame
+ data += '\x88\x8a' + _mask_hybi(struct.pack('!H', 1000) + 'Good bye')
+
+ extension = common.ExtensionParameter(
+ common.PERMESSAGE_DEFLATE_EXTENSION)
+ request = _create_request_from_rawdata(
+ data, permessage_deflate_request=extension)
+ self.assertEqual('Hello', msgutil.receive_message(request))
+
+ self.assertEqual(None, msgutil.receive_message(request))
+
+ def test_receive_message_random_section(self):
+ """Test that a compressed message fragmented into lots of chunks is
+ correctly received.
+ """
+
+ random.seed(a=0)
+ payload = ''.join(
+ [chr(random.randint(0, 255)) for i in xrange(1000)])
+
+ compress = zlib.compressobj(
+ zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -zlib.MAX_WBITS)
+ compressed_payload = compress.compress(payload)
+ compressed_payload += compress.flush(zlib.Z_SYNC_FLUSH)
+ compressed_payload = compressed_payload[:-4]
+
+ # Fragment the compressed payload into lots of frames.
+ bytes_chunked = 0
+ data = ''
+ frame_count = 0
+
+ chunk_sizes = []
+
+ while bytes_chunked < len(compressed_payload):
+ # Make sure that
+ # - the length of chunks are equal or less than 125 so that we can
+ # use 1 octet length header format for all frames.
+ # - at least 10 chunks are created.
+ chunk_size = random.randint(
+ 1, min(125,
+ len(compressed_payload) / 10,
+ len(compressed_payload) - bytes_chunked))
+ chunk_sizes.append(chunk_size)
+ chunk = compressed_payload[
+ bytes_chunked:bytes_chunked + chunk_size]
+ bytes_chunked += chunk_size
+
+ first_octet = 0x00
+ if len(data) == 0:
+ first_octet = first_octet | 0x42
+ if bytes_chunked == len(compressed_payload):
+ first_octet = first_octet | 0x80
+
+ data += '%c%c' % (first_octet, chunk_size | 0x80)
+ data += _mask_hybi(chunk)
+
+ frame_count += 1
+
+ print "Chunk sizes: %r" % chunk_sizes
+ self.assertTrue(len(chunk_sizes) > 10)
+
+ # Close frame
+ data += '\x88\x8a' + _mask_hybi(struct.pack('!H', 1000) + 'Good bye')
+
+ extension = common.ExtensionParameter(
+ common.PERMESSAGE_DEFLATE_EXTENSION)
+ request = _create_request_from_rawdata(
+ data, permessage_deflate_request=extension)
+ self.assertEqual(payload, msgutil.receive_message(request))
+
+ self.assertEqual(None, msgutil.receive_message(request))
+
+ def test_receive_two_messages(self):
+ compress = zlib.compressobj(
+ zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -zlib.MAX_WBITS)
+
+ data = ''
+
+ compressed_hello = compress.compress('HelloWebSocket')
+ compressed_hello += compress.flush(zlib.Z_SYNC_FLUSH)
+ compressed_hello = compressed_hello[:-4]
+ split_position = len(compressed_hello) / 2
+ data += '\x41%c' % (split_position | 0x80)
+ data += _mask_hybi(compressed_hello[:split_position])
+
+ data += '\x80%c' % ((len(compressed_hello) - split_position) | 0x80)
+ data += _mask_hybi(compressed_hello[split_position:])
+
+ compress = zlib.compressobj(
+ zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -zlib.MAX_WBITS)
+
+ compressed_world = compress.compress('World')
+ compressed_world += compress.flush(zlib.Z_SYNC_FLUSH)
+ compressed_world = compressed_world[:-4]
+ data += '\xc1%c' % (len(compressed_world) | 0x80)
+ data += _mask_hybi(compressed_world)
+
+ # Close frame
+ data += '\x88\x8a' + _mask_hybi(struct.pack('!H', 1000) + 'Good bye')
+
+ extension = common.ExtensionParameter(
+ common.PERMESSAGE_DEFLATE_EXTENSION)
+ request = _create_request_from_rawdata(
+ data, permessage_deflate_request=extension)
+ self.assertEqual('HelloWebSocket', msgutil.receive_message(request))
+ self.assertEqual('World', msgutil.receive_message(request))
+
+ self.assertEqual(None, msgutil.receive_message(request))
+
+ def test_receive_message_mixed_btype(self):
+ """Test that a message compressed using lots of DEFLATE blocks with
+ various flush mode is correctly received.
+ """
+
+ random.seed(a=0)
+ payload = ''.join(
+ [chr(random.randint(0, 255)) for i in xrange(1000)])
+
+ compress = None
+
+ # Fragment the compressed payload into lots of frames.
+ bytes_chunked = 0
+ compressed_payload = ''
+
+ chunk_sizes = []
+ methods = []
+ sync_used = False
+ finish_used = False
+
+ while bytes_chunked < len(payload):
+ # Make sure at least 10 chunks are created.
+ chunk_size = random.randint(
+ 1, min(100, len(payload) - bytes_chunked))
+ chunk_sizes.append(chunk_size)
+ chunk = payload[bytes_chunked:bytes_chunked + chunk_size]
+
+ bytes_chunked += chunk_size
+
+ if compress is None:
+ compress = zlib.compressobj(
+ zlib.Z_DEFAULT_COMPRESSION,
+ zlib.DEFLATED,
+ -zlib.MAX_WBITS)
+
+ if bytes_chunked == len(payload):
+ compressed_payload += compress.compress(chunk)
+ compressed_payload += compress.flush(zlib.Z_SYNC_FLUSH)
+ compressed_payload = compressed_payload[:-4]
+ else:
+ method = random.randint(0, 1)
+ methods.append(method)
+ if method == 0:
+ compressed_payload += compress.compress(chunk)
+ compressed_payload += compress.flush(zlib.Z_SYNC_FLUSH)
+ sync_used = True
+ else:
+ compressed_payload += compress.compress(chunk)
+ compressed_payload += compress.flush(zlib.Z_FINISH)
+ compress = None
+ finish_used = True
+
+ print "Chunk sizes: %r" % chunk_sizes
+ self.assertTrue(len(chunk_sizes) > 10)
+ print "Methods: %r" % methods
+ self.assertTrue(sync_used)
+ self.assertTrue(finish_used)
+
+ self.assertTrue(125 < len(compressed_payload))
+ self.assertTrue(len(compressed_payload) < 65536)
+ data = '\xc2\xfe' + struct.pack('!H', len(compressed_payload))
+ data += _mask_hybi(compressed_payload)
+
+ # Close frame
+ data += '\x88\x8a' + _mask_hybi(struct.pack('!H', 1000) + 'Good bye')
+
+ extension = common.ExtensionParameter(
+ common.PERMESSAGE_DEFLATE_EXTENSION)
+ request = _create_request_from_rawdata(
+ data, permessage_deflate_request=extension)
+ self.assertEqual(payload, msgutil.receive_message(request))
+
+ self.assertEqual(None, msgutil.receive_message(request))
+
+
+class PerMessageCompressTest(unittest.TestCase):
+ """Tests for checking permessage-compression extension."""
+
+ def test_deflate_response_parameters(self):
+ extension = common.ExtensionParameter(
+ common.PERMESSAGE_COMPRESSION_EXTENSION)
+ extension.add_parameter('method', 'deflate')
+ processor = PerMessageCompressExtensionProcessor(extension)
+ response = processor.get_extension_response()
+ self.assertEqual('deflate',
+ response.get_parameter_value('method'))
+
+ extension = common.ExtensionParameter(
+ common.PERMESSAGE_COMPRESSION_EXTENSION)
+ extension.add_parameter('method', 'deflate')
+ processor = PerMessageCompressExtensionProcessor(extension)
+
+ def _compression_processor_hook(compression_processor):
+ compression_processor.set_client_max_window_bits(8)
+ compression_processor.set_client_no_context_takeover(True)
+ processor.set_compression_processor_hook(
+ _compression_processor_hook)
+ response = processor.get_extension_response()
+ self.assertEqual(
+ 'deflate; client_max_window_bits=8; client_no_context_takeover',
+ response.get_parameter_value('method'))
+
+
+class MessageTestHixie75(unittest.TestCase):
+ """Tests for draft-hixie-thewebsocketprotocol-76 stream class."""
+
+ def test_send_message(self):
+ request = _create_request_hixie75()
+ msgutil.send_message(request, 'Hello')
+ self.assertEqual('\x00Hello\xff', request.connection.written_data())
+
+ def test_send_message_unicode(self):
+ request = _create_request_hixie75()
+ msgutil.send_message(request, u'\u65e5')
+ # U+65e5 is encoded as e6,97,a5 in UTF-8
+ self.assertEqual('\x00\xe6\x97\xa5\xff',
+ request.connection.written_data())
+
+ def test_receive_message(self):
+ request = _create_request_hixie75('\x00Hello\xff\x00World!\xff')
+ self.assertEqual('Hello', msgutil.receive_message(request))
+ self.assertEqual('World!', msgutil.receive_message(request))
+
+ def test_receive_message_unicode(self):
+ request = _create_request_hixie75('\x00\xe6\x9c\xac\xff')
+ # U+672c is encoded as e6,9c,ac in UTF-8
+ self.assertEqual(u'\u672c', msgutil.receive_message(request))
+
+ def test_receive_message_erroneous_unicode(self):
+ # \x80 and \x81 are invalid as UTF-8.
+ request = _create_request_hixie75('\x00\x80\x81\xff')
+ # Invalid characters should be replaced with
+ # U+fffd REPLACEMENT CHARACTER
+ self.assertEqual(u'\ufffd\ufffd', msgutil.receive_message(request))
+
+ def test_receive_message_discard(self):
+ request = _create_request_hixie75('\x80\x06IGNORE\x00Hello\xff'
+ '\x01DISREGARD\xff\x00World!\xff')
+ self.assertEqual('Hello', msgutil.receive_message(request))
+ self.assertEqual('World!', msgutil.receive_message(request))
+
+
+class MessageReceiverTest(unittest.TestCase):
+ """Tests the Stream class using MessageReceiver."""
+
+ def test_queue(self):
+ request = _create_blocking_request()
+ receiver = msgutil.MessageReceiver(request)
+
+ self.assertEqual(None, receiver.receive_nowait())
+
+ request.connection.put_bytes('\x81\x86' + _mask_hybi('Hello!'))
+ self.assertEqual('Hello!', receiver.receive())
+
+ def test_onmessage(self):
+ onmessage_queue = Queue.Queue()
+
+ def onmessage_handler(message):
+ onmessage_queue.put(message)
+
+ request = _create_blocking_request()
+ receiver = msgutil.MessageReceiver(request, onmessage_handler)
+
+ request.connection.put_bytes('\x81\x86' + _mask_hybi('Hello!'))
+ self.assertEqual('Hello!', onmessage_queue.get())
+
+
+class MessageReceiverHixie75Test(unittest.TestCase):
+ """Tests the StreamHixie75 class using MessageReceiver."""
+
+ def test_queue(self):
+ request = _create_blocking_request_hixie75()
+ receiver = msgutil.MessageReceiver(request)
+
+ self.assertEqual(None, receiver.receive_nowait())
+
+ request.connection.put_bytes('\x00Hello!\xff')
+ self.assertEqual('Hello!', receiver.receive())
+
+ def test_onmessage(self):
+ onmessage_queue = Queue.Queue()
+
+ def onmessage_handler(message):
+ onmessage_queue.put(message)
+
+ request = _create_blocking_request_hixie75()
+ receiver = msgutil.MessageReceiver(request, onmessage_handler)
+
+ request.connection.put_bytes('\x00Hello!\xff')
+ self.assertEqual('Hello!', onmessage_queue.get())
+
+
+class MessageSenderTest(unittest.TestCase):
+ """Tests the Stream class using MessageSender."""
+
+ def test_send(self):
+ request = _create_blocking_request()
+ sender = msgutil.MessageSender(request)
+
+ sender.send('World')
+ self.assertEqual('\x81\x05World', request.connection.written_data())
+
+ def test_send_nowait(self):
+ # Use a queue to check the bytes written by MessageSender.
+ # request.connection.written_data() cannot be used here because
+ # MessageSender runs in a separate thread.
+ send_queue = Queue.Queue()
+
+ def write(bytes):
+ send_queue.put(bytes)
+
+ request = _create_blocking_request()
+ request.connection.write = write
+
+ sender = msgutil.MessageSender(request)
+
+ sender.send_nowait('Hello')
+ sender.send_nowait('World')
+ self.assertEqual('\x81\x05Hello', send_queue.get())
+ self.assertEqual('\x81\x05World', send_queue.get())
+
+
+class MessageSenderHixie75Test(unittest.TestCase):
+ """Tests the StreamHixie75 class using MessageSender."""
+
+ def test_send(self):
+ request = _create_blocking_request_hixie75()
+ sender = msgutil.MessageSender(request)
+
+ sender.send('World')
+ self.assertEqual('\x00World\xff', request.connection.written_data())
+
+ def test_send_nowait(self):
+ # Use a queue to check the bytes written by MessageSender.
+ # request.connection.written_data() cannot be used here because
+ # MessageSender runs in a separate thread.
+ send_queue = Queue.Queue()
+
+ def write(bytes):
+ send_queue.put(bytes)
+
+ request = _create_blocking_request_hixie75()
+ request.connection.write = write
+
+ sender = msgutil.MessageSender(request)
+
+ sender.send_nowait('Hello')
+ sender.send_nowait('World')
+ self.assertEqual('\x00Hello\xff', send_queue.get())
+ self.assertEqual('\x00World\xff', send_queue.get())
+
+
+if __name__ == '__main__':
+ unittest.main()
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/test_mux.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/test_mux.py
new file mode 100644
index 00000000000..d4598944e08
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/test_mux.py
@@ -0,0 +1,2089 @@
+#!/usr/bin/env python
+#
+# Copyright 2012, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+"""Tests for mux module."""
+
+import Queue
+import copy
+import logging
+import optparse
+import struct
+import sys
+import unittest
+import time
+import zlib
+
+import set_sys_path # Update sys.path to locate mod_pywebsocket module.
+
+from mod_pywebsocket import common
+from mod_pywebsocket import mux
+from mod_pywebsocket._stream_base import ConnectionTerminatedException
+from mod_pywebsocket._stream_base import UnsupportedFrameException
+from mod_pywebsocket._stream_hybi import Frame
+from mod_pywebsocket._stream_hybi import Stream
+from mod_pywebsocket._stream_hybi import StreamOptions
+from mod_pywebsocket._stream_hybi import create_binary_frame
+from mod_pywebsocket._stream_hybi import create_close_frame
+from mod_pywebsocket._stream_hybi import create_closing_handshake_body
+from mod_pywebsocket._stream_hybi import parse_frame
+from mod_pywebsocket.extensions import MuxExtensionProcessor
+
+
+import mock
+
+
+_TEST_HEADERS = {'Host': 'server.example.com',
+ 'Upgrade': 'websocket',
+ 'Connection': 'Upgrade',
+ 'Sec-WebSocket-Key': 'dGhlIHNhbXBsZSBub25jZQ==',
+ 'Sec-WebSocket-Version': '13',
+ 'Origin': 'http://example.com'}
+
+
+class _OutgoingChannelData(object):
+ def __init__(self):
+ self.messages = []
+ self.control_messages = []
+
+ self.builder = mux._InnerMessageBuilder()
+
+class _MockMuxConnection(mock.MockBlockingConn):
+ """Mock class of mod_python connection for mux."""
+
+ def __init__(self):
+ mock.MockBlockingConn.__init__(self)
+ self._control_blocks = []
+ self._channel_data = {}
+
+ self._current_opcode = None
+ self._pending_fragments = []
+
+ self.server_close_code = None
+
+ def write(self, data):
+ """Override MockBlockingConn.write."""
+
+ self._current_data = data
+ self._position = 0
+
+ def _receive_bytes(length):
+ if self._position + length > len(self._current_data):
+ raise ConnectionTerminatedException(
+ 'Failed to receive %d bytes from encapsulated '
+ 'frame' % length)
+ data = self._current_data[self._position:self._position+length]
+ self._position += length
+ return data
+
+ # Parse physical frames and assemble a message if the message is
+ # fragmented.
+ opcode, payload, fin, rsv1, rsv2, rsv3 = (
+ parse_frame(_receive_bytes, unmask_receive=False))
+
+ self._pending_fragments.append(payload)
+
+ if self._current_opcode is None:
+ if opcode == common.OPCODE_CONTINUATION:
+ raise Exception('Sending invalid continuation opcode')
+ self._current_opcode = opcode
+ else:
+ if opcode != common.OPCODE_CONTINUATION:
+ raise Exception('Sending invalid opcode %d' % opcode)
+ if not fin:
+ return
+
+ inner_frame_data = ''.join(self._pending_fragments)
+ self._pending_fragments = []
+ self._current_opcode = None
+
+ # Handle a control message on the physical channel.
+ # TODO(bashi): Support other opcodes if needed.
+ if opcode == common.OPCODE_CLOSE:
+ if len(payload) >= 2:
+ self.server_close_code = struct.unpack('!H', payload[:2])[0]
+ close_body = create_closing_handshake_body(
+ common.STATUS_NORMAL_CLOSURE, '')
+ close_frame = create_close_frame(close_body, mask=True)
+ self.put_bytes(close_frame)
+ return
+
+ # Parse the payload of the message on physical channel.
+ parser = mux._MuxFramePayloadParser(inner_frame_data)
+ channel_id = parser.read_channel_id()
+ if channel_id == mux._CONTROL_CHANNEL_ID:
+ self._control_blocks.extend(list(parser.read_control_blocks()))
+ return
+
+ if not channel_id in self._channel_data:
+ self._channel_data[channel_id] = _OutgoingChannelData()
+ channel_data = self._channel_data[channel_id]
+
+ # Parse logical frames and assemble an inner (logical) message.
+ (inner_fin, inner_rsv1, inner_rsv2, inner_rsv3, inner_opcode,
+ inner_payload) = parser.read_inner_frame()
+ inner_frame = Frame(inner_fin, inner_rsv1, inner_rsv2, inner_rsv3,
+ inner_opcode, inner_payload)
+ message = channel_data.builder.build(inner_frame)
+ if message is None:
+ return
+
+ if (message.opcode == common.OPCODE_TEXT or
+ message.opcode == common.OPCODE_BINARY):
+ channel_data.messages.append(message.payload)
+
+ self.on_data_message(message.payload)
+ else:
+ channel_data.control_messages.append(
+ {'opcode': message.opcode,
+ 'message': message.payload})
+
+ def on_data_message(self, message):
+ pass
+
+ def get_written_control_blocks(self):
+ return self._control_blocks
+
+ def get_written_messages(self, channel_id):
+ return self._channel_data[channel_id].messages
+
+ def get_written_control_messages(self, channel_id):
+ return self._channel_data[channel_id].control_messages
+
+
+class _FailOnWriteConnection(_MockMuxConnection):
+ """Specicialized version of _MockMuxConnection. Its write() method raises
+ an exception for testing when a data message is written.
+ """
+
+ def on_data_message(self, message):
+ """Override to raise an exception."""
+
+ raise Exception('Intentional failure')
+
+
+class _ChannelEvent(object):
+ """A structure that records channel events."""
+
+ def __init__(self):
+ self.request = None
+ self.messages = []
+ self.exception = None
+ self.client_initiated_closing = False
+
+
+class _MuxMockDispatcher(object):
+ """Mock class of dispatch.Dispatcher for mux."""
+
+ def __init__(self):
+ self.channel_events = {}
+
+ def do_extra_handshake(self, request):
+ if request.ws_requested_protocols is not None:
+ request.ws_protocol = request.ws_requested_protocols[0]
+
+ def _do_echo(self, request, channel_events):
+ while True:
+ message = request.ws_stream.receive_message()
+ if message == None:
+ channel_events.client_initiated_closing = True
+ return
+ if message == 'Goodbye':
+ return
+ channel_events.messages.append(message)
+ # echo back
+ request.ws_stream.send_message(message)
+
+ def _do_ping(self, request, channel_events):
+ request.ws_stream.send_ping('Ping!')
+
+ def _do_ping_while_hello_world(self, request, channel_events):
+ request.ws_stream.send_message('Hello ', end=False)
+ request.ws_stream.send_ping('Ping!')
+ request.ws_stream.send_message('World!', end=True)
+
+ def _do_two_ping_while_hello_world(self, request, channel_events):
+ request.ws_stream.send_message('Hello ', end=False)
+ request.ws_stream.send_ping('Ping!')
+ request.ws_stream.send_ping('Pong!')
+ request.ws_stream.send_message('World!', end=True)
+
+ def transfer_data(self, request):
+ self.channel_events[request.channel_id] = _ChannelEvent()
+ self.channel_events[request.channel_id].request = request
+
+ try:
+ # Note: more handler will be added.
+ if request.uri.endswith('echo'):
+ self._do_echo(request,
+ self.channel_events[request.channel_id])
+ elif request.uri.endswith('ping'):
+ self._do_ping(request,
+ self.channel_events[request.channel_id])
+ elif request.uri.endswith('two_ping_while_hello_world'):
+ self._do_two_ping_while_hello_world(
+ request, self.channel_events[request.channel_id])
+ elif request.uri.endswith('ping_while_hello_world'):
+ self._do_ping_while_hello_world(
+ request, self.channel_events[request.channel_id])
+ else:
+ raise ValueError('Cannot handle path %r' % request.path)
+ if not request.server_terminated:
+ request.ws_stream.close_connection()
+ except ConnectionTerminatedException, e:
+ self.channel_events[request.channel_id].exception = e
+ except Exception, e:
+ self.channel_events[request.channel_id].exception = e
+ raise
+
+
+def _create_mock_request(connection=None, logical_channel_extensions=None):
+ if connection is None:
+ connection = _MockMuxConnection()
+
+ request = mock.MockRequest(uri='/echo',
+ headers_in=_TEST_HEADERS,
+ connection=connection)
+ request.ws_stream = Stream(request, options=StreamOptions())
+ request.mux_processor = MuxExtensionProcessor(
+ common.ExtensionParameter(common.MUX_EXTENSION))
+ if logical_channel_extensions is not None:
+ request.mux_processor.set_extensions(logical_channel_extensions)
+ request.mux_processor.set_quota(8 * 1024)
+ return request
+
+
+def _create_add_channel_request_frame(channel_id, encoding, encoded_handshake):
+ # Allow invalid encoding for testing.
+ first_byte = ((mux._MUX_OPCODE_ADD_CHANNEL_REQUEST << 5) | encoding)
+ payload = (chr(first_byte) +
+ mux._encode_channel_id(channel_id) +
+ mux._encode_number(len(encoded_handshake)) +
+ encoded_handshake)
+ return create_binary_frame(
+ (mux._encode_channel_id(mux._CONTROL_CHANNEL_ID) + payload), mask=True)
+
+
+def _create_drop_channel_frame(channel_id, code=None, message=''):
+ payload = mux._create_drop_channel(channel_id, code, message)
+ return create_binary_frame(
+ (mux._encode_channel_id(mux._CONTROL_CHANNEL_ID) + payload), mask=True)
+
+
+def _create_flow_control_frame(channel_id, replenished_quota):
+ payload = mux._create_flow_control(channel_id, replenished_quota)
+ return create_binary_frame(
+ (mux._encode_channel_id(mux._CONTROL_CHANNEL_ID) + payload), mask=True)
+
+
+def _create_logical_frame(channel_id, message, opcode=common.OPCODE_BINARY,
+ fin=True, rsv1=False, rsv2=False, rsv3=False,
+ mask=True):
+ bits = chr((fin << 7) | (rsv1 << 6) | (rsv2 << 5) | (rsv3 << 4) | opcode)
+ payload = mux._encode_channel_id(channel_id) + bits + message
+ return create_binary_frame(payload, mask=True)
+
+
+def _create_request_header(path='/echo', extensions=None):
+ headers = (
+ 'GET %s HTTP/1.1\r\n'
+ 'Host: server.example.com\r\n'
+ 'Connection: Upgrade\r\n'
+ 'Origin: http://example.com\r\n') % path
+ if extensions:
+ headers += '%s: %s' % (
+ common.SEC_WEBSOCKET_EXTENSIONS_HEADER, extensions)
+ return headers
+
+
+class MuxTest(unittest.TestCase):
+ """A unittest for mux module."""
+
+ def test_channel_id_decode(self):
+ data = '\x00\x01\xbf\xff\xdf\xff\xff\xff\xff\xff\xff'
+ parser = mux._MuxFramePayloadParser(data)
+ channel_id = parser.read_channel_id()
+ self.assertEqual(0, channel_id)
+ channel_id = parser.read_channel_id()
+ self.assertEqual(1, channel_id)
+ channel_id = parser.read_channel_id()
+ self.assertEqual(2 ** 14 - 1, channel_id)
+ channel_id = parser.read_channel_id()
+ self.assertEqual(2 ** 21 - 1, channel_id)
+ channel_id = parser.read_channel_id()
+ self.assertEqual(2 ** 29 - 1, channel_id)
+ self.assertEqual(len(data), parser._read_position)
+
+ def test_channel_id_encode(self):
+ encoded = mux._encode_channel_id(0)
+ self.assertEqual('\x00', encoded)
+ encoded = mux._encode_channel_id(2 ** 14 - 1)
+ self.assertEqual('\xbf\xff', encoded)
+ encoded = mux._encode_channel_id(2 ** 14)
+ self.assertEqual('\xc0@\x00', encoded)
+ encoded = mux._encode_channel_id(2 ** 21 - 1)
+ self.assertEqual('\xdf\xff\xff', encoded)
+ encoded = mux._encode_channel_id(2 ** 21)
+ self.assertEqual('\xe0 \x00\x00', encoded)
+ encoded = mux._encode_channel_id(2 ** 29 - 1)
+ self.assertEqual('\xff\xff\xff\xff', encoded)
+ # channel_id is too large
+ self.assertRaises(ValueError,
+ mux._encode_channel_id,
+ 2 ** 29)
+
+ def test_read_multiple_control_blocks(self):
+ # Use AddChannelRequest because it can contain arbitrary length of data
+ data = ('\x00\x01\x01a'
+ '\x00\x02\x7d%s'
+ '\x00\x03\x7e\xff\xff%s'
+ '\x00\x04\x7f\x00\x00\x00\x00\x00\x01\x00\x00%s') % (
+ 'a' * 0x7d, 'b' * 0xffff, 'c' * 0x10000)
+ parser = mux._MuxFramePayloadParser(data)
+ blocks = list(parser.read_control_blocks())
+ self.assertEqual(4, len(blocks))
+
+ self.assertEqual(mux._MUX_OPCODE_ADD_CHANNEL_REQUEST, blocks[0].opcode)
+ self.assertEqual(1, blocks[0].channel_id)
+ self.assertEqual(1, len(blocks[0].encoded_handshake))
+
+ self.assertEqual(mux._MUX_OPCODE_ADD_CHANNEL_REQUEST, blocks[1].opcode)
+ self.assertEqual(2, blocks[1].channel_id)
+ self.assertEqual(0x7d, len(blocks[1].encoded_handshake))
+
+ self.assertEqual(mux._MUX_OPCODE_ADD_CHANNEL_REQUEST, blocks[2].opcode)
+ self.assertEqual(3, blocks[2].channel_id)
+ self.assertEqual(0xffff, len(blocks[2].encoded_handshake))
+
+ self.assertEqual(mux._MUX_OPCODE_ADD_CHANNEL_REQUEST, blocks[3].opcode)
+ self.assertEqual(4, blocks[3].channel_id)
+ self.assertEqual(0x10000, len(blocks[3].encoded_handshake))
+
+ self.assertEqual(len(data), parser._read_position)
+
+ def test_read_add_channel_request(self):
+ data = '\x00\x01\x01a'
+ parser = mux._MuxFramePayloadParser(data)
+ blocks = list(parser.read_control_blocks())
+ self.assertEqual(mux._MUX_OPCODE_ADD_CHANNEL_REQUEST, blocks[0].opcode)
+ self.assertEqual(1, blocks[0].channel_id)
+ self.assertEqual(1, len(blocks[0].encoded_handshake))
+
+ def test_read_drop_channel(self):
+ data = '\x60\x01\x00'
+ parser = mux._MuxFramePayloadParser(data)
+ blocks = list(parser.read_control_blocks())
+ self.assertEqual(1, len(blocks))
+ self.assertEqual(1, blocks[0].channel_id)
+ self.assertEqual(mux._MUX_OPCODE_DROP_CHANNEL, blocks[0].opcode)
+ self.assertEqual(None, blocks[0].drop_code)
+ self.assertEqual(0, len(blocks[0].drop_message))
+
+ data = '\x60\x02\x09\x03\xe8Success'
+ parser = mux._MuxFramePayloadParser(data)
+ blocks = list(parser.read_control_blocks())
+ self.assertEqual(1, len(blocks))
+ self.assertEqual(2, blocks[0].channel_id)
+ self.assertEqual(mux._MUX_OPCODE_DROP_CHANNEL, blocks[0].opcode)
+ self.assertEqual(1000, blocks[0].drop_code)
+ self.assertEqual('Success', blocks[0].drop_message)
+
+ # Reason is too short.
+ data = '\x60\x01\x01\x00'
+ parser = mux._MuxFramePayloadParser(data)
+ self.assertRaises(mux.PhysicalConnectionError,
+ lambda: list(parser.read_control_blocks()))
+
+ def test_read_flow_control(self):
+ data = '\x40\x01\x02'
+ parser = mux._MuxFramePayloadParser(data)
+ blocks = list(parser.read_control_blocks())
+ self.assertEqual(1, len(blocks))
+ self.assertEqual(1, blocks[0].channel_id)
+ self.assertEqual(mux._MUX_OPCODE_FLOW_CONTROL, blocks[0].opcode)
+ self.assertEqual(2, blocks[0].send_quota)
+
+ def test_read_new_channel_slot(self):
+ data = '\x80\x01\x02\x02\x03'
+ parser = mux._MuxFramePayloadParser(data)
+ # TODO(bashi): Implement
+ self.assertRaises(mux.PhysicalConnectionError,
+ lambda: list(parser.read_control_blocks()))
+
+ def test_read_invalid_number_field_in_control_block(self):
+ # No number field.
+ data = ''
+ parser = mux._MuxFramePayloadParser(data)
+ self.assertRaises(ValueError, parser._read_number)
+
+ # The last two bytes are missing.
+ data = '\x7e'
+ parser = mux._MuxFramePayloadParser(data)
+ self.assertRaises(ValueError, parser._read_number)
+
+ # Missing the last one byte.
+ data = '\x7f\x00\x00\x00\x00\x00\x01\x00'
+ parser = mux._MuxFramePayloadParser(data)
+ self.assertRaises(ValueError, parser._read_number)
+
+ # The length of number field is too large.
+ data = '\x7f\xff\xff\xff\xff\xff\xff\xff\xff'
+ parser = mux._MuxFramePayloadParser(data)
+ self.assertRaises(ValueError, parser._read_number)
+
+ # The msb of the first byte is set.
+ data = '\x80'
+ parser = mux._MuxFramePayloadParser(data)
+ self.assertRaises(ValueError, parser._read_number)
+
+ # Using 3 bytes encoding for 125.
+ data = '\x7e\x00\x7d'
+ parser = mux._MuxFramePayloadParser(data)
+ self.assertRaises(ValueError, parser._read_number)
+
+ # Using 9 bytes encoding for 0xffff
+ data = '\x7f\x00\x00\x00\x00\x00\x00\xff\xff'
+ parser = mux._MuxFramePayloadParser(data)
+ self.assertRaises(ValueError, parser._read_number)
+
+ def test_read_invalid_size_and_contents(self):
+ # Only contain number field.
+ data = '\x01'
+ parser = mux._MuxFramePayloadParser(data)
+ self.assertRaises(mux.PhysicalConnectionError,
+ parser._read_size_and_contents)
+
+ def test_create_add_channel_response(self):
+ data = mux._create_add_channel_response(channel_id=1,
+ encoded_handshake='FooBar',
+ encoding=0,
+ rejected=False)
+ self.assertEqual('\x20\x01\x06FooBar', data)
+
+ data = mux._create_add_channel_response(channel_id=2,
+ encoded_handshake='Hello',
+ encoding=1,
+ rejected=True)
+ self.assertEqual('\x31\x02\x05Hello', data)
+
+ def test_create_drop_channel(self):
+ data = mux._create_drop_channel(channel_id=1)
+ self.assertEqual('\x60\x01\x00', data)
+
+ data = mux._create_drop_channel(channel_id=1,
+ code=2000,
+ message='error')
+ self.assertEqual('\x60\x01\x07\x07\xd0error', data)
+
+ # reason must be empty if code is None
+ self.assertRaises(ValueError,
+ mux._create_drop_channel,
+ 1, None, 'FooBar')
+
+ def test_parse_request_text(self):
+ request_text = _create_request_header()
+ command, path, version, headers = mux._parse_request_text(request_text)
+ self.assertEqual('GET', command)
+ self.assertEqual('/echo', path)
+ self.assertEqual('HTTP/1.1', version)
+ self.assertEqual(3, len(headers))
+ self.assertEqual('server.example.com', headers['Host'])
+ self.assertEqual('http://example.com', headers['Origin'])
+
+
+class MuxHandlerTest(unittest.TestCase):
+
+ def test_add_channel(self):
+ request = _create_mock_request()
+ dispatcher = _MuxMockDispatcher()
+ mux_handler = mux._MuxHandler(request, dispatcher)
+ mux_handler.start()
+ mux_handler.add_channel_slots(mux._INITIAL_NUMBER_OF_CHANNEL_SLOTS,
+ mux._INITIAL_QUOTA_FOR_CLIENT)
+
+ encoded_handshake = _create_request_header(path='/echo')
+ add_channel_request = _create_add_channel_request_frame(
+ channel_id=2, encoding=0,
+ encoded_handshake=encoded_handshake)
+ request.connection.put_bytes(add_channel_request)
+
+ flow_control = _create_flow_control_frame(channel_id=2,
+ replenished_quota=6)
+ request.connection.put_bytes(flow_control)
+
+ encoded_handshake = _create_request_header(path='/echo')
+ add_channel_request = _create_add_channel_request_frame(
+ channel_id=3, encoding=0,
+ encoded_handshake=encoded_handshake)
+ request.connection.put_bytes(add_channel_request)
+
+ flow_control = _create_flow_control_frame(channel_id=3,
+ replenished_quota=6)
+ request.connection.put_bytes(flow_control)
+
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=2, message='Hello'))
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=3, message='World'))
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=1, message='Goodbye'))
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=2, message='Goodbye'))
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=3, message='Goodbye'))
+
+ self.assertTrue(mux_handler.wait_until_done(timeout=2))
+
+ self.assertEqual([], dispatcher.channel_events[1].messages)
+ self.assertEqual(['Hello'], dispatcher.channel_events[2].messages)
+ self.assertEqual(['World'], dispatcher.channel_events[3].messages)
+ # Channel 2
+ messages = request.connection.get_written_messages(2)
+ self.assertEqual(1, len(messages))
+ self.assertEqual('Hello', messages[0])
+ # Channel 3
+ messages = request.connection.get_written_messages(3)
+ self.assertEqual(1, len(messages))
+ self.assertEqual('World', messages[0])
+ control_blocks = request.connection.get_written_control_blocks()
+ # There should be 8 control blocks:
+ # - 1 NewChannelSlot
+ # - 2 AddChannelResponses for channel id 2 and 3
+ # - 6 FlowControls for channel id 1 (initialize), 'Hello', 'World',
+ # and 3 'Goodbye's
+ self.assertEqual(9, len(control_blocks))
+
+ def test_physical_connection_write_failure(self):
+ # Use _FailOnWriteConnection.
+ request = _create_mock_request(connection=_FailOnWriteConnection())
+
+ dispatcher = _MuxMockDispatcher()
+ mux_handler = mux._MuxHandler(request, dispatcher)
+ mux_handler.start()
+
+ # Let the worker echo back 'Hello'. It causes _FailOnWriteConnection
+ # raising an exception.
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=1, message='Hello'))
+
+ # Let the worker exit. This will be unnecessary when
+ # _LogicalConnection.write() is changed to throw an exception if
+ # woke up by on_writer_done.
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=1, message='Goodbye'))
+
+ # All threads should be done.
+ self.assertTrue(mux_handler.wait_until_done(timeout=2))
+
+ def test_send_blocked(self):
+ request = _create_mock_request()
+ dispatcher = _MuxMockDispatcher()
+ mux_handler = mux._MuxHandler(request, dispatcher)
+ mux_handler.start()
+
+ mux_handler.add_channel_slots(mux._INITIAL_NUMBER_OF_CHANNEL_SLOTS,
+ mux._INITIAL_QUOTA_FOR_CLIENT)
+
+ encoded_handshake = _create_request_header(path='/echo')
+ add_channel_request = _create_add_channel_request_frame(
+ channel_id=2, encoding=0,
+ encoded_handshake=encoded_handshake)
+ request.connection.put_bytes(add_channel_request)
+
+ # On receiving this 'Hello', the server tries to echo back 'Hello',
+ # but it will be blocked since there's no send quota available for the
+ # channel 2.
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=2, message='Hello'))
+
+ # Wait until the worker is blocked due to send quota shortage.
+ time.sleep(1)
+
+ # Close the channel 2. The worker should be notified of the end of
+ # writer thread and stop waiting for send quota to be replenished.
+ drop_channel = _create_drop_channel_frame(channel_id=2)
+
+ request.connection.put_bytes(drop_channel)
+
+ # Make sure the channel 1 is also closed.
+ drop_channel = _create_drop_channel_frame(channel_id=1)
+ request.connection.put_bytes(drop_channel)
+
+ # All threads should be done.
+ self.assertTrue(mux_handler.wait_until_done(timeout=2))
+
+ def test_add_channel_delta_encoding(self):
+ request = _create_mock_request()
+ dispatcher = _MuxMockDispatcher()
+ mux_handler = mux._MuxHandler(request, dispatcher)
+ mux_handler.start()
+ mux_handler.add_channel_slots(mux._INITIAL_NUMBER_OF_CHANNEL_SLOTS,
+ mux._INITIAL_QUOTA_FOR_CLIENT)
+
+ delta = 'GET /echo HTTP/1.1\r\n\r\n'
+ add_channel_request = _create_add_channel_request_frame(
+ channel_id=2, encoding=1, encoded_handshake=delta)
+ request.connection.put_bytes(add_channel_request)
+
+ flow_control = _create_flow_control_frame(channel_id=2,
+ replenished_quota=6)
+ request.connection.put_bytes(flow_control)
+
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=2, message='Hello'))
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=1, message='Goodbye'))
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=2, message='Goodbye'))
+
+ self.assertTrue(mux_handler.wait_until_done(timeout=2))
+
+ self.assertEqual(['Hello'], dispatcher.channel_events[2].messages)
+ messages = request.connection.get_written_messages(2)
+ self.assertEqual(1, len(messages))
+ self.assertEqual('Hello', messages[0])
+
+ def test_add_channel_delta_encoding_override(self):
+ request = _create_mock_request()
+ dispatcher = _MuxMockDispatcher()
+ mux_handler = mux._MuxHandler(request, dispatcher)
+ mux_handler.start()
+ mux_handler.add_channel_slots(mux._INITIAL_NUMBER_OF_CHANNEL_SLOTS,
+ mux._INITIAL_QUOTA_FOR_CLIENT)
+
+ # Override Sec-WebSocket-Protocol.
+ delta = ('GET /echo HTTP/1.1\r\n'
+ 'Sec-WebSocket-Protocol: x-foo\r\n'
+ '\r\n')
+ add_channel_request = _create_add_channel_request_frame(
+ channel_id=2, encoding=1, encoded_handshake=delta)
+ request.connection.put_bytes(add_channel_request)
+
+ flow_control = _create_flow_control_frame(channel_id=2,
+ replenished_quota=6)
+ request.connection.put_bytes(flow_control)
+
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=2, message='Hello'))
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=1, message='Goodbye'))
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=2, message='Goodbye'))
+
+ self.assertTrue(mux_handler.wait_until_done(timeout=2))
+
+ self.assertEqual(['Hello'], dispatcher.channel_events[2].messages)
+ messages = request.connection.get_written_messages(2)
+ self.assertEqual(1, len(messages))
+ self.assertEqual('Hello', messages[0])
+ self.assertEqual('x-foo',
+ dispatcher.channel_events[2].request.ws_protocol)
+
+ def test_add_channel_delta_after_identity(self):
+ request = _create_mock_request()
+ dispatcher = _MuxMockDispatcher()
+ mux_handler = mux._MuxHandler(request, dispatcher)
+ mux_handler.start()
+ mux_handler.add_channel_slots(mux._INITIAL_NUMBER_OF_CHANNEL_SLOTS,
+ mux._INITIAL_QUOTA_FOR_CLIENT)
+ # Sec-WebSocket-Protocol is different from client's opening handshake
+ # of the physical connection.
+ # TODO(bashi): Remove Upgrade, Connection, Sec-WebSocket-Key and
+ # Sec-WebSocket-Version.
+ encoded_handshake = (
+ 'GET /echo HTTP/1.1\r\n'
+ 'Host: server.example.com\r\n'
+ 'Sec-WebSocket-Protocol: x-foo\r\n'
+ 'Connection: Upgrade\r\n'
+ 'Origin: http://example.com\r\n'
+ '\r\n')
+ add_channel_request = _create_add_channel_request_frame(
+ channel_id=2, encoding=0,
+ encoded_handshake=encoded_handshake)
+ request.connection.put_bytes(add_channel_request)
+
+ flow_control = _create_flow_control_frame(channel_id=2,
+ replenished_quota=6)
+ request.connection.put_bytes(flow_control)
+
+ delta = 'GET /echo HTTP/1.1\r\n\r\n'
+ add_channel_request = _create_add_channel_request_frame(
+ channel_id=3, encoding=1, encoded_handshake=delta)
+ request.connection.put_bytes(add_channel_request)
+
+ flow_control = _create_flow_control_frame(channel_id=3,
+ replenished_quota=6)
+ request.connection.put_bytes(flow_control)
+
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=2, message='Hello'))
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=3, message='World'))
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=1, message='Goodbye'))
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=2, message='Goodbye'))
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=3, message='Goodbye'))
+
+ self.assertTrue(mux_handler.wait_until_done(timeout=2))
+
+ self.assertEqual([], dispatcher.channel_events[1].messages)
+ self.assertEqual(['Hello'], dispatcher.channel_events[2].messages)
+ self.assertEqual(['World'], dispatcher.channel_events[3].messages)
+ # Channel 2
+ messages = request.connection.get_written_messages(2)
+ self.assertEqual(1, len(messages))
+ self.assertEqual('Hello', messages[0])
+ # Channel 3
+ messages = request.connection.get_written_messages(3)
+ self.assertEqual(1, len(messages))
+ self.assertEqual('World', messages[0])
+ # Handshake base should be updated.
+ self.assertEqual(
+ 'x-foo',
+ mux_handler._handshake_base._headers['Sec-WebSocket-Protocol'])
+
+ def test_add_channel_delta_remove_header(self):
+ request = _create_mock_request()
+ dispatcher = _MuxMockDispatcher()
+ mux_handler = mux._MuxHandler(request, dispatcher)
+ mux_handler.start()
+ mux_handler.add_channel_slots(mux._INITIAL_NUMBER_OF_CHANNEL_SLOTS,
+ mux._INITIAL_QUOTA_FOR_CLIENT)
+ # Override handshake delta base.
+ encoded_handshake = (
+ 'GET /echo HTTP/1.1\r\n'
+ 'Host: server.example.com\r\n'
+ 'Sec-WebSocket-Protocol: x-foo\r\n'
+ 'Connection: Upgrade\r\n'
+ 'Origin: http://example.com\r\n'
+ '\r\n')
+ add_channel_request = _create_add_channel_request_frame(
+ channel_id=2, encoding=0,
+ encoded_handshake=encoded_handshake)
+ request.connection.put_bytes(add_channel_request)
+
+ flow_control = _create_flow_control_frame(channel_id=2,
+ replenished_quota=6)
+ request.connection.put_bytes(flow_control)
+
+ # Remove Sec-WebSocket-Protocol header.
+ delta = ('GET /echo HTTP/1.1\r\n'
+ 'Sec-WebSocket-Protocol:'
+ '\r\n')
+ add_channel_request = _create_add_channel_request_frame(
+ channel_id=3, encoding=1, encoded_handshake=delta)
+ request.connection.put_bytes(add_channel_request)
+
+ flow_control = _create_flow_control_frame(channel_id=3,
+ replenished_quota=6)
+ request.connection.put_bytes(flow_control)
+
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=2, message='Hello'))
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=3, message='World'))
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=1, message='Goodbye'))
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=2, message='Goodbye'))
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=3, message='Goodbye'))
+
+ self.assertTrue(mux_handler.wait_until_done(timeout=2))
+
+ self.assertEqual([], dispatcher.channel_events[1].messages)
+ self.assertEqual(['Hello'], dispatcher.channel_events[2].messages)
+ self.assertEqual(['World'], dispatcher.channel_events[3].messages)
+ # Channel 2
+ messages = request.connection.get_written_messages(2)
+ self.assertEqual(1, len(messages))
+ self.assertEqual('Hello', messages[0])
+ # Channel 3
+ messages = request.connection.get_written_messages(3)
+ self.assertEqual(1, len(messages))
+ self.assertEqual('World', messages[0])
+ self.assertEqual(
+ 'x-foo',
+ dispatcher.channel_events[2].request.ws_protocol)
+ self.assertEqual(
+ None,
+ dispatcher.channel_events[3].request.ws_protocol)
+
+ def test_add_channel_delta_encoding_permessage_compress(self):
+ # Enable permessage compress extension on the implicitly opened channel.
+ extensions = common.parse_extensions(
+ '%s; method=deflate' % common.PERMESSAGE_COMPRESSION_EXTENSION)
+ request = _create_mock_request(
+ logical_channel_extensions=extensions)
+ dispatcher = _MuxMockDispatcher()
+ mux_handler = mux._MuxHandler(request, dispatcher)
+ mux_handler.start()
+ mux_handler.add_channel_slots(mux._INITIAL_NUMBER_OF_CHANNEL_SLOTS,
+ mux._INITIAL_QUOTA_FOR_CLIENT)
+
+ delta = 'GET /echo HTTP/1.1\r\n\r\n'
+ add_channel_request = _create_add_channel_request_frame(
+ channel_id=2, encoding=1, encoded_handshake=delta)
+ request.connection.put_bytes(add_channel_request)
+
+ flow_control = _create_flow_control_frame(channel_id=2,
+ replenished_quota=20)
+ request.connection.put_bytes(flow_control)
+
+ # Send compressed 'Hello' on logical channel 1 and 2.
+ compress = zlib.compressobj(
+ zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -zlib.MAX_WBITS)
+ compressed_hello = compress.compress('Hello')
+ compressed_hello += compress.flush(zlib.Z_SYNC_FLUSH)
+ compressed_hello = compressed_hello[:-4]
+
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=1, message=compressed_hello,
+ rsv1=True))
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=2, message=compressed_hello,
+ rsv1=True))
+
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=1, message='Goodbye'))
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=2, message='Goodbye'))
+
+ self.assertTrue(mux_handler.wait_until_done(timeout=2))
+
+ self.assertEqual(['Hello'], dispatcher.channel_events[1].messages)
+ self.assertEqual(['Hello'], dispatcher.channel_events[2].messages)
+ # Written 'Hello's should be compressed.
+ messages = request.connection.get_written_messages(1)
+ self.assertEqual(1, len(messages))
+ self.assertEqual(compressed_hello, messages[0])
+ messages = request.connection.get_written_messages(2)
+ self.assertEqual(1, len(messages))
+ self.assertEqual(compressed_hello, messages[0])
+
+ def test_add_channel_delta_encoding_remove_extensions(self):
+ # Enable permessage compress extension on the implicitly opened channel.
+ extensions = common.parse_extensions(
+ '%s; method=deflate' % common.PERMESSAGE_COMPRESSION_EXTENSION)
+ request = _create_mock_request(
+ logical_channel_extensions=extensions)
+ dispatcher = _MuxMockDispatcher()
+ mux_handler = mux._MuxHandler(request, dispatcher)
+ mux_handler.start()
+ mux_handler.add_channel_slots(mux._INITIAL_NUMBER_OF_CHANNEL_SLOTS,
+ mux._INITIAL_QUOTA_FOR_CLIENT)
+
+ # Remove permessage compress extension.
+ delta = ('GET /echo HTTP/1.1\r\n'
+ 'Sec-WebSocket-Extensions:\r\n'
+ '\r\n')
+ add_channel_request = _create_add_channel_request_frame(
+ channel_id=2, encoding=1, encoded_handshake=delta)
+ request.connection.put_bytes(add_channel_request)
+
+ flow_control = _create_flow_control_frame(channel_id=2,
+ replenished_quota=20)
+ request.connection.put_bytes(flow_control)
+
+ # Send compressed message on logical channel 2. The message should
+ # be rejected (since rsv1 is set).
+ compress = zlib.compressobj(
+ zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -zlib.MAX_WBITS)
+ compressed_hello = compress.compress('Hello')
+ compressed_hello += compress.flush(zlib.Z_SYNC_FLUSH)
+ compressed_hello = compressed_hello[:-4]
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=2, message=compressed_hello,
+ rsv1=True))
+
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=1, message='Goodbye'))
+
+ self.assertTrue(mux_handler.wait_until_done(timeout=2))
+
+ drop_channel = next(
+ b for b in request.connection.get_written_control_blocks()
+ if b.opcode == mux._MUX_OPCODE_DROP_CHANNEL)
+ self.assertEqual(mux._DROP_CODE_NORMAL_CLOSURE, drop_channel.drop_code)
+ self.assertEqual(2, drop_channel.channel_id)
+ # UnsupportedFrameException should be raised on logical channel 2.
+ self.assertTrue(isinstance(dispatcher.channel_events[2].exception,
+ UnsupportedFrameException))
+
+ def test_add_channel_invalid_encoding(self):
+ request = _create_mock_request()
+ dispatcher = _MuxMockDispatcher()
+ mux_handler = mux._MuxHandler(request, dispatcher)
+ mux_handler.start()
+ mux_handler.add_channel_slots(mux._INITIAL_NUMBER_OF_CHANNEL_SLOTS,
+ mux._INITIAL_QUOTA_FOR_CLIENT)
+
+ encoded_handshake = _create_request_header(path='/echo')
+ add_channel_request = _create_add_channel_request_frame(
+ channel_id=2, encoding=3,
+ encoded_handshake=encoded_handshake)
+ request.connection.put_bytes(add_channel_request)
+
+ self.assertTrue(mux_handler.wait_until_done(timeout=2))
+
+ drop_channel = next(
+ b for b in request.connection.get_written_control_blocks()
+ if b.opcode == mux._MUX_OPCODE_DROP_CHANNEL)
+ self.assertEqual(mux._DROP_CODE_UNKNOWN_REQUEST_ENCODING,
+ drop_channel.drop_code)
+ self.assertEqual(common.STATUS_INTERNAL_ENDPOINT_ERROR,
+ request.connection.server_close_code)
+
+ def test_add_channel_incomplete_handshake(self):
+ request = _create_mock_request()
+ dispatcher = _MuxMockDispatcher()
+ mux_handler = mux._MuxHandler(request, dispatcher)
+ mux_handler.start()
+ mux_handler.add_channel_slots(mux._INITIAL_NUMBER_OF_CHANNEL_SLOTS,
+ mux._INITIAL_QUOTA_FOR_CLIENT)
+
+ incomplete_encoded_handshake = 'GET /echo HTTP/1.1'
+ add_channel_request = _create_add_channel_request_frame(
+ channel_id=2, encoding=0,
+ encoded_handshake=incomplete_encoded_handshake)
+ request.connection.put_bytes(add_channel_request)
+
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=1, message='Goodbye'))
+
+ self.assertTrue(mux_handler.wait_until_done(timeout=2))
+
+ self.assertTrue(1 in dispatcher.channel_events)
+ self.assertTrue(not 2 in dispatcher.channel_events)
+
+ def test_add_channel_duplicate_channel_id(self):
+ request = _create_mock_request()
+ dispatcher = _MuxMockDispatcher()
+ mux_handler = mux._MuxHandler(request, dispatcher)
+ mux_handler.start()
+ mux_handler.add_channel_slots(mux._INITIAL_NUMBER_OF_CHANNEL_SLOTS,
+ mux._INITIAL_QUOTA_FOR_CLIENT)
+
+ encoded_handshake = _create_request_header(path='/echo')
+ add_channel_request = _create_add_channel_request_frame(
+ channel_id=2, encoding=0,
+ encoded_handshake=encoded_handshake)
+ request.connection.put_bytes(add_channel_request)
+
+ encoded_handshake = _create_request_header(path='/echo')
+ add_channel_request = _create_add_channel_request_frame(
+ channel_id=2, encoding=0,
+ encoded_handshake=encoded_handshake)
+ request.connection.put_bytes(add_channel_request)
+
+ self.assertTrue(mux_handler.wait_until_done(timeout=2))
+
+ drop_channel = next(
+ b for b in request.connection.get_written_control_blocks()
+ if b.opcode == mux._MUX_OPCODE_DROP_CHANNEL)
+ self.assertEqual(mux._DROP_CODE_CHANNEL_ALREADY_EXISTS,
+ drop_channel.drop_code)
+ self.assertEqual(common.STATUS_INTERNAL_ENDPOINT_ERROR,
+ request.connection.server_close_code)
+
+ def test_receive_drop_channel(self):
+ request = _create_mock_request()
+ dispatcher = _MuxMockDispatcher()
+ mux_handler = mux._MuxHandler(request, dispatcher)
+ mux_handler.start()
+ mux_handler.add_channel_slots(mux._INITIAL_NUMBER_OF_CHANNEL_SLOTS,
+ mux._INITIAL_QUOTA_FOR_CLIENT)
+
+ encoded_handshake = _create_request_header(path='/echo')
+ add_channel_request = _create_add_channel_request_frame(
+ channel_id=2, encoding=0,
+ encoded_handshake=encoded_handshake)
+ request.connection.put_bytes(add_channel_request)
+
+ drop_channel = _create_drop_channel_frame(channel_id=2)
+ request.connection.put_bytes(drop_channel)
+
+ # Terminate implicitly opened channel.
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=1, message='Goodbye'))
+
+ self.assertTrue(mux_handler.wait_until_done(timeout=2))
+
+ exception = dispatcher.channel_events[2].exception
+ self.assertTrue(exception.__class__ == ConnectionTerminatedException)
+
+ def test_receive_ping_frame(self):
+ request = _create_mock_request()
+ dispatcher = _MuxMockDispatcher()
+ mux_handler = mux._MuxHandler(request, dispatcher)
+ mux_handler.start()
+ mux_handler.add_channel_slots(mux._INITIAL_NUMBER_OF_CHANNEL_SLOTS,
+ mux._INITIAL_QUOTA_FOR_CLIENT)
+
+ encoded_handshake = _create_request_header(path='/echo')
+ add_channel_request = _create_add_channel_request_frame(
+ channel_id=2, encoding=0,
+ encoded_handshake=encoded_handshake)
+ request.connection.put_bytes(add_channel_request)
+
+ flow_control = _create_flow_control_frame(channel_id=2,
+ replenished_quota=13)
+ request.connection.put_bytes(flow_control)
+
+ ping_frame = _create_logical_frame(channel_id=2,
+ message='Hello World!',
+ opcode=common.OPCODE_PING)
+ request.connection.put_bytes(ping_frame)
+
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=1, message='Goodbye'))
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=2, message='Goodbye'))
+
+ self.assertTrue(mux_handler.wait_until_done(timeout=2))
+
+ messages = request.connection.get_written_control_messages(2)
+ self.assertEqual(common.OPCODE_PONG, messages[0]['opcode'])
+ self.assertEqual('Hello World!', messages[0]['message'])
+
+ def test_receive_fragmented_ping(self):
+ request = _create_mock_request()
+ dispatcher = _MuxMockDispatcher()
+ mux_handler = mux._MuxHandler(request, dispatcher)
+ mux_handler.start()
+ mux_handler.add_channel_slots(mux._INITIAL_NUMBER_OF_CHANNEL_SLOTS,
+ mux._INITIAL_QUOTA_FOR_CLIENT)
+
+ encoded_handshake = _create_request_header(path='/echo')
+ add_channel_request = _create_add_channel_request_frame(
+ channel_id=2, encoding=0,
+ encoded_handshake=encoded_handshake)
+ request.connection.put_bytes(add_channel_request)
+
+ flow_control = _create_flow_control_frame(channel_id=2,
+ replenished_quota=13)
+ request.connection.put_bytes(flow_control)
+
+ # Send a ping with message 'Hello world!' in two fragmented frames.
+ ping_frame1 = _create_logical_frame(channel_id=2,
+ message='Hello ',
+ fin=False,
+ opcode=common.OPCODE_PING)
+ request.connection.put_bytes(ping_frame1)
+ ping_frame2 = _create_logical_frame(channel_id=2,
+ message='World!',
+ fin=True,
+ opcode=common.OPCODE_CONTINUATION)
+ request.connection.put_bytes(ping_frame2)
+
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=1, message='Goodbye'))
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=2, message='Goodbye'))
+
+ self.assertTrue(mux_handler.wait_until_done(timeout=2))
+
+ messages = request.connection.get_written_control_messages(2)
+ self.assertEqual(common.OPCODE_PONG, messages[0]['opcode'])
+ self.assertEqual('Hello World!', messages[0]['message'])
+
+ def test_receive_fragmented_ping_while_receiving_fragmented_message(self):
+ request = _create_mock_request()
+ dispatcher = _MuxMockDispatcher()
+ mux_handler = mux._MuxHandler(request, dispatcher)
+ mux_handler.start()
+ mux_handler.add_channel_slots(mux._INITIAL_NUMBER_OF_CHANNEL_SLOTS,
+ mux._INITIAL_QUOTA_FOR_CLIENT)
+
+ encoded_handshake = _create_request_header(path='/echo')
+ add_channel_request = _create_add_channel_request_frame(
+ channel_id=2, encoding=0,
+ encoded_handshake=encoded_handshake)
+ request.connection.put_bytes(add_channel_request)
+
+ flow_control = _create_flow_control_frame(channel_id=2,
+ replenished_quota=19)
+ request.connection.put_bytes(flow_control)
+
+ # Send a fragmented frame of message 'Hello '.
+ hello = _create_logical_frame(channel_id=2,
+ message='Hello ',
+ fin=False)
+ request.connection.put_bytes(hello)
+
+ # Before sending the last fragmented frame of the message, send a
+ # fragmented ping.
+ ping1 = _create_logical_frame(channel_id=2,
+ message='Pi',
+ fin=False,
+ opcode=common.OPCODE_PING)
+ request.connection.put_bytes(ping1)
+ ping2 = _create_logical_frame(channel_id=2,
+ message='ng!',
+ fin=True,
+ opcode=common.OPCODE_CONTINUATION)
+ request.connection.put_bytes(ping2)
+
+ # Send the last fragmented frame of the message.
+ world = _create_logical_frame(channel_id=2,
+ message='World!',
+ fin=True,
+ opcode=common.OPCODE_CONTINUATION)
+ request.connection.put_bytes(world)
+
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=1, message='Goodbye'))
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=2, message='Goodbye'))
+
+ self.assertTrue(mux_handler.wait_until_done(timeout=2))
+
+ messages = request.connection.get_written_messages(2)
+ self.assertEqual(['Hello World!'], messages)
+ control_messages = request.connection.get_written_control_messages(2)
+ self.assertEqual(common.OPCODE_PONG, control_messages[0]['opcode'])
+ self.assertEqual('Ping!', control_messages[0]['message'])
+
+ def test_receive_two_ping_while_receiving_fragmented_message(self):
+ request = _create_mock_request()
+ dispatcher = _MuxMockDispatcher()
+ mux_handler = mux._MuxHandler(request, dispatcher)
+ mux_handler.start()
+ mux_handler.add_channel_slots(mux._INITIAL_NUMBER_OF_CHANNEL_SLOTS,
+ mux._INITIAL_QUOTA_FOR_CLIENT)
+
+ encoded_handshake = _create_request_header(path='/echo')
+ add_channel_request = _create_add_channel_request_frame(
+ channel_id=2, encoding=0,
+ encoded_handshake=encoded_handshake)
+ request.connection.put_bytes(add_channel_request)
+
+ flow_control = _create_flow_control_frame(channel_id=2,
+ replenished_quota=25)
+ request.connection.put_bytes(flow_control)
+
+ # Send a fragmented frame of message 'Hello '.
+ hello = _create_logical_frame(channel_id=2,
+ message='Hello ',
+ fin=False)
+ request.connection.put_bytes(hello)
+
+ # Before sending the last fragmented frame of the message, send a
+ # fragmented ping and a non-fragmented ping.
+ ping1 = _create_logical_frame(channel_id=2,
+ message='Pi',
+ fin=False,
+ opcode=common.OPCODE_PING)
+ request.connection.put_bytes(ping1)
+ ping2 = _create_logical_frame(channel_id=2,
+ message='ng!',
+ fin=True,
+ opcode=common.OPCODE_CONTINUATION)
+ request.connection.put_bytes(ping2)
+ ping3 = _create_logical_frame(channel_id=2,
+ message='Pong!',
+ fin=True,
+ opcode=common.OPCODE_PING)
+ request.connection.put_bytes(ping3)
+
+ # Send the last fragmented frame of the message.
+ world = _create_logical_frame(channel_id=2,
+ message='World!',
+ fin=True,
+ opcode=common.OPCODE_CONTINUATION)
+ request.connection.put_bytes(world)
+
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=1, message='Goodbye'))
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=2, message='Goodbye'))
+
+ self.assertTrue(mux_handler.wait_until_done(timeout=2))
+
+ messages = request.connection.get_written_messages(2)
+ self.assertEqual(['Hello World!'], messages)
+ control_messages = request.connection.get_written_control_messages(2)
+ self.assertEqual(common.OPCODE_PONG, control_messages[0]['opcode'])
+ self.assertEqual('Ping!', control_messages[0]['message'])
+ self.assertEqual(common.OPCODE_PONG, control_messages[1]['opcode'])
+ self.assertEqual('Pong!', control_messages[1]['message'])
+
+ def test_receive_message_while_receiving_fragmented_ping(self):
+ request = _create_mock_request()
+ dispatcher = _MuxMockDispatcher()
+ mux_handler = mux._MuxHandler(request, dispatcher)
+ mux_handler.start()
+ mux_handler.add_channel_slots(mux._INITIAL_NUMBER_OF_CHANNEL_SLOTS,
+ mux._INITIAL_QUOTA_FOR_CLIENT)
+
+ encoded_handshake = _create_request_header(path='/echo')
+ add_channel_request = _create_add_channel_request_frame(
+ channel_id=2, encoding=0,
+ encoded_handshake=encoded_handshake)
+ request.connection.put_bytes(add_channel_request)
+
+ flow_control = _create_flow_control_frame(channel_id=2,
+ replenished_quota=19)
+ request.connection.put_bytes(flow_control)
+
+ # Send a fragmented ping.
+ ping1 = _create_logical_frame(channel_id=2,
+ message='Pi',
+ fin=False,
+ opcode=common.OPCODE_PING)
+ request.connection.put_bytes(ping1)
+
+ # Before sending the last fragmented ping, send a message.
+ # The logical channel (2) should be dropped.
+ message = _create_logical_frame(channel_id=2,
+ message='Hello world!',
+ fin=True)
+ request.connection.put_bytes(message)
+
+ # Send the last fragmented frame of the message.
+ ping2 = _create_logical_frame(channel_id=2,
+ message='ng!',
+ fin=True,
+ opcode=common.OPCODE_CONTINUATION)
+ request.connection.put_bytes(ping2)
+
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=1, message='Goodbye'))
+
+ self.assertTrue(mux_handler.wait_until_done(timeout=2))
+
+ drop_channel = next(
+ b for b in request.connection.get_written_control_blocks()
+ if b.opcode == mux._MUX_OPCODE_DROP_CHANNEL)
+ self.assertEqual(2, drop_channel.channel_id)
+ # No message should be sent on channel 2.
+ self.assertRaises(KeyError,
+ request.connection.get_written_messages,
+ 2)
+ self.assertRaises(KeyError,
+ request.connection.get_written_control_messages,
+ 2)
+
+ def test_send_ping(self):
+ request = _create_mock_request()
+ dispatcher = _MuxMockDispatcher()
+ mux_handler = mux._MuxHandler(request, dispatcher)
+ mux_handler.start()
+ mux_handler.add_channel_slots(mux._INITIAL_NUMBER_OF_CHANNEL_SLOTS,
+ mux._INITIAL_QUOTA_FOR_CLIENT)
+
+ encoded_handshake = _create_request_header(path='/ping')
+ add_channel_request = _create_add_channel_request_frame(
+ channel_id=2, encoding=0,
+ encoded_handshake=encoded_handshake)
+ request.connection.put_bytes(add_channel_request)
+
+ flow_control = _create_flow_control_frame(channel_id=2,
+ replenished_quota=6)
+ request.connection.put_bytes(flow_control)
+
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=1, message='Goodbye'))
+
+ self.assertTrue(mux_handler.wait_until_done(timeout=2))
+
+ messages = request.connection.get_written_control_messages(2)
+ self.assertEqual(common.OPCODE_PING, messages[0]['opcode'])
+ self.assertEqual('Ping!', messages[0]['message'])
+
+ def test_send_fragmented_ping(self):
+ request = _create_mock_request()
+ dispatcher = _MuxMockDispatcher()
+ mux_handler = mux._MuxHandler(request, dispatcher)
+ mux_handler.start()
+ mux_handler.add_channel_slots(mux._INITIAL_NUMBER_OF_CHANNEL_SLOTS,
+ mux._INITIAL_QUOTA_FOR_CLIENT)
+
+ encoded_handshake = _create_request_header(path='/ping')
+ add_channel_request = _create_add_channel_request_frame(
+ channel_id=2, encoding=0,
+ encoded_handshake=encoded_handshake)
+ request.connection.put_bytes(add_channel_request)
+
+ # Replenish 3 bytes. This isn't enough to send the whole ping frame
+ # because the frame will have 5 bytes message('Ping!'). The frame
+ # should be fragmented.
+ flow_control = _create_flow_control_frame(channel_id=2,
+ replenished_quota=3)
+ request.connection.put_bytes(flow_control)
+
+ # Wait until the worker is blocked due to send quota shortage.
+ time.sleep(1)
+
+ # Replenish remaining 2 + 1 bytes (including extra cost).
+ flow_control = _create_flow_control_frame(channel_id=2,
+ replenished_quota=3)
+ request.connection.put_bytes(flow_control)
+
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=1, message='Goodbye'))
+
+ self.assertTrue(mux_handler.wait_until_done(timeout=2))
+
+ messages = request.connection.get_written_control_messages(2)
+ self.assertEqual(common.OPCODE_PING, messages[0]['opcode'])
+ self.assertEqual('Ping!', messages[0]['message'])
+
+ def test_send_fragmented_ping_while_sending_fragmented_message(self):
+ request = _create_mock_request()
+ dispatcher = _MuxMockDispatcher()
+ mux_handler = mux._MuxHandler(request, dispatcher)
+ mux_handler.start()
+ mux_handler.add_channel_slots(mux._INITIAL_NUMBER_OF_CHANNEL_SLOTS,
+ mux._INITIAL_QUOTA_FOR_CLIENT)
+
+ encoded_handshake = _create_request_header(
+ path='/ping_while_hello_world')
+ add_channel_request = _create_add_channel_request_frame(
+ channel_id=2, encoding=0,
+ encoded_handshake=encoded_handshake)
+ request.connection.put_bytes(add_channel_request)
+
+ # Application will send:
+ # - text message 'Hello ' with fin=0
+ # - ping with 'Ping!' message
+ # - text message 'World!' with fin=1
+ # Replenish (6 + 1) + (2 + 1) bytes so that the ping will be
+ # fragmented on the logical channel.
+ flow_control = _create_flow_control_frame(channel_id=2,
+ replenished_quota=10)
+ request.connection.put_bytes(flow_control)
+
+ time.sleep(1)
+
+ # Replenish remaining 3 + 6 bytes.
+ flow_control = _create_flow_control_frame(channel_id=2,
+ replenished_quota=9)
+ request.connection.put_bytes(flow_control)
+
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=1, message='Goodbye'))
+
+ self.assertTrue(mux_handler.wait_until_done(timeout=2))
+
+ messages = request.connection.get_written_messages(2)
+ self.assertEqual(['Hello World!'], messages)
+ control_messages = request.connection.get_written_control_messages(2)
+ self.assertEqual(common.OPCODE_PING, control_messages[0]['opcode'])
+ self.assertEqual('Ping!', control_messages[0]['message'])
+
+ def test_send_fragmented_two_ping_while_sending_fragmented_message(self):
+ request = _create_mock_request()
+ dispatcher = _MuxMockDispatcher()
+ mux_handler = mux._MuxHandler(request, dispatcher)
+ mux_handler.start()
+ mux_handler.add_channel_slots(mux._INITIAL_NUMBER_OF_CHANNEL_SLOTS,
+ mux._INITIAL_QUOTA_FOR_CLIENT)
+
+ encoded_handshake = _create_request_header(
+ path='/two_ping_while_hello_world')
+ add_channel_request = _create_add_channel_request_frame(
+ channel_id=2, encoding=0,
+ encoded_handshake=encoded_handshake)
+ request.connection.put_bytes(add_channel_request)
+
+ # Application will send:
+ # - text message 'Hello ' with fin=0
+ # - ping with 'Ping!' message
+ # - ping with 'Pong!' message
+ # - text message 'World!' with fin=1
+ # Replenish (6 + 1) + (2 + 1) bytes so that the first ping will be
+ # fragmented on the logical channel.
+ flow_control = _create_flow_control_frame(channel_id=2,
+ replenished_quota=10)
+ request.connection.put_bytes(flow_control)
+
+ time.sleep(1)
+
+ # Replenish remaining 3 + (5 + 1) + 6 bytes. The second ping won't
+ # be fragmented on the logical channel.
+ flow_control = _create_flow_control_frame(channel_id=2,
+ replenished_quota=15)
+ request.connection.put_bytes(flow_control)
+
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=1, message='Goodbye'))
+
+ self.assertTrue(mux_handler.wait_until_done(timeout=2))
+
+ messages = request.connection.get_written_messages(2)
+ self.assertEqual(['Hello World!'], messages)
+ control_messages = request.connection.get_written_control_messages(2)
+ self.assertEqual(common.OPCODE_PING, control_messages[0]['opcode'])
+ self.assertEqual('Ping!', control_messages[0]['message'])
+ self.assertEqual(common.OPCODE_PING, control_messages[1]['opcode'])
+ self.assertEqual('Pong!', control_messages[1]['message'])
+
+ def test_send_drop_channel(self):
+ request = _create_mock_request()
+ dispatcher = _MuxMockDispatcher()
+ mux_handler = mux._MuxHandler(request, dispatcher)
+ mux_handler.start()
+
+ # DropChannel for channel id 1 which doesn't have reason.
+ frame = create_binary_frame('\x00\x60\x01\x00', mask=True)
+ request.connection.put_bytes(frame)
+
+ self.assertTrue(mux_handler.wait_until_done(timeout=2))
+
+ drop_channel = next(
+ b for b in request.connection.get_written_control_blocks()
+ if b.opcode == mux._MUX_OPCODE_DROP_CHANNEL)
+ self.assertEqual(mux._DROP_CODE_ACKNOWLEDGED,
+ drop_channel.drop_code)
+ self.assertEqual(1, drop_channel.channel_id)
+
+ def test_two_flow_control(self):
+ request = _create_mock_request()
+ dispatcher = _MuxMockDispatcher()
+ mux_handler = mux._MuxHandler(request, dispatcher)
+ mux_handler.start()
+ mux_handler.add_channel_slots(mux._INITIAL_NUMBER_OF_CHANNEL_SLOTS,
+ mux._INITIAL_QUOTA_FOR_CLIENT)
+
+ encoded_handshake = _create_request_header(path='/echo')
+ add_channel_request = _create_add_channel_request_frame(
+ channel_id=2, encoding=0,
+ encoded_handshake=encoded_handshake)
+ request.connection.put_bytes(add_channel_request)
+
+ # Replenish 5 bytes.
+ flow_control = _create_flow_control_frame(channel_id=2,
+ replenished_quota=5)
+ request.connection.put_bytes(flow_control)
+
+ # Send 10 bytes. The server will try echo back 10 bytes.
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=2, message='HelloWorld'))
+
+ # Replenish 5 + 1 (per-message extra cost) bytes.
+ flow_control = _create_flow_control_frame(channel_id=2,
+ replenished_quota=6)
+ request.connection.put_bytes(flow_control)
+
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=1, message='Goodbye'))
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=2, message='Goodbye'))
+
+ self.assertTrue(mux_handler.wait_until_done(timeout=2))
+
+ messages = request.connection.get_written_messages(2)
+ self.assertEqual(['HelloWorld'], messages)
+ received_flow_controls = [
+ b for b in request.connection.get_written_control_blocks()
+ if b.opcode == mux._MUX_OPCODE_FLOW_CONTROL and b.channel_id == 2]
+ # Replenishment for 'HelloWorld' + 1
+ self.assertEqual(11, received_flow_controls[0].send_quota)
+ # Replenishment for 'Goodbye' + 1
+ self.assertEqual(8, received_flow_controls[1].send_quota)
+
+ def test_no_send_quota_on_server(self):
+ request = _create_mock_request()
+ dispatcher = _MuxMockDispatcher()
+ mux_handler = mux._MuxHandler(request, dispatcher)
+ mux_handler.start()
+ mux_handler.add_channel_slots(mux._INITIAL_NUMBER_OF_CHANNEL_SLOTS,
+ mux._INITIAL_QUOTA_FOR_CLIENT)
+
+ encoded_handshake = _create_request_header(path='/echo')
+ add_channel_request = _create_add_channel_request_frame(
+ channel_id=2, encoding=0,
+ encoded_handshake=encoded_handshake)
+ request.connection.put_bytes(add_channel_request)
+
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=2, message='HelloWorld'))
+
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=1, message='Goodbye'))
+
+ # Just wait for 1 sec so that the server attempts to echo back
+ # 'HelloWorld'.
+ self.assertFalse(mux_handler.wait_until_done(timeout=1))
+
+ # No message should be sent on channel 2.
+ self.assertRaises(KeyError,
+ request.connection.get_written_messages,
+ 2)
+
+ def test_no_send_quota_on_server_for_permessage_extra_cost(self):
+ request = _create_mock_request()
+ dispatcher = _MuxMockDispatcher()
+ mux_handler = mux._MuxHandler(request, dispatcher)
+ mux_handler.start()
+ mux_handler.add_channel_slots(mux._INITIAL_NUMBER_OF_CHANNEL_SLOTS,
+ mux._INITIAL_QUOTA_FOR_CLIENT)
+
+ encoded_handshake = _create_request_header(path='/echo')
+ add_channel_request = _create_add_channel_request_frame(
+ channel_id=2, encoding=0,
+ encoded_handshake=encoded_handshake)
+ request.connection.put_bytes(add_channel_request)
+
+ flow_control = _create_flow_control_frame(channel_id=2,
+ replenished_quota=6)
+ request.connection.put_bytes(flow_control)
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=2, message='Hello'))
+ # Replenish only len('World') bytes.
+ flow_control = _create_flow_control_frame(channel_id=2,
+ replenished_quota=5)
+ request.connection.put_bytes(flow_control)
+ # Server should not callback for this message.
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=2, message='World'))
+
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=1, message='Goodbye'))
+
+ # Just wait for 1 sec so that the server attempts to echo back
+ # 'World'.
+ self.assertFalse(mux_handler.wait_until_done(timeout=1))
+
+ # Only one message should be sent on channel 2.
+ messages = request.connection.get_written_messages(2)
+ self.assertEqual(['Hello'], messages)
+
+ def test_quota_violation_by_client(self):
+ request = _create_mock_request()
+ dispatcher = _MuxMockDispatcher()
+ mux_handler = mux._MuxHandler(request, dispatcher)
+ mux_handler.start()
+ mux_handler.add_channel_slots(mux._INITIAL_NUMBER_OF_CHANNEL_SLOTS, 0)
+
+ encoded_handshake = _create_request_header(path='/echo')
+ add_channel_request = _create_add_channel_request_frame(
+ channel_id=2, encoding=0,
+ encoded_handshake=encoded_handshake)
+ request.connection.put_bytes(add_channel_request)
+
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=2, message='HelloWorld'))
+
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=1, message='Goodbye'))
+
+ self.assertTrue(mux_handler.wait_until_done(timeout=2))
+
+ control_blocks = request.connection.get_written_control_blocks()
+ self.assertEqual(5, len(control_blocks))
+ drop_channel = next(
+ b for b in control_blocks
+ if b.opcode == mux._MUX_OPCODE_DROP_CHANNEL)
+ self.assertEqual(mux._DROP_CODE_SEND_QUOTA_VIOLATION,
+ drop_channel.drop_code)
+
+ def test_consume_quota_empty_message(self):
+ request = _create_mock_request()
+ dispatcher = _MuxMockDispatcher()
+ mux_handler = mux._MuxHandler(request, dispatcher)
+ mux_handler.start()
+ # Client has 1 byte quota.
+ mux_handler.add_channel_slots(mux._INITIAL_NUMBER_OF_CHANNEL_SLOTS, 1)
+
+ encoded_handshake = _create_request_header(path='/echo')
+ add_channel_request = _create_add_channel_request_frame(
+ channel_id=2, encoding=0,
+ encoded_handshake=encoded_handshake)
+ request.connection.put_bytes(add_channel_request)
+
+ flow_control = _create_flow_control_frame(channel_id=2,
+ replenished_quota=2)
+ request.connection.put_bytes(flow_control)
+ # Send an empty message. Pywebsocket always replenishes 1 byte quota
+ # for empty message
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=2, message=''))
+
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=1, message='Goodbye'))
+ # This message violates quota on channel id 2.
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=2, message='Goodbye'))
+
+ self.assertTrue(mux_handler.wait_until_done(timeout=2))
+
+ self.assertEqual(1, len(dispatcher.channel_events[2].messages))
+ self.assertEqual('', dispatcher.channel_events[2].messages[0])
+
+ received_flow_controls = [
+ b for b in request.connection.get_written_control_blocks()
+ if b.opcode == mux._MUX_OPCODE_FLOW_CONTROL and b.channel_id == 2]
+ self.assertEqual(1, len(received_flow_controls))
+ self.assertEqual(1, received_flow_controls[0].send_quota)
+
+ drop_channel = next(
+ b for b in request.connection.get_written_control_blocks()
+ if b.opcode == mux._MUX_OPCODE_DROP_CHANNEL)
+ self.assertEqual(2, drop_channel.channel_id)
+ self.assertEqual(mux._DROP_CODE_SEND_QUOTA_VIOLATION,
+ drop_channel.drop_code)
+
+ def test_consume_quota_fragmented_message(self):
+ request = _create_mock_request()
+ dispatcher = _MuxMockDispatcher()
+ mux_handler = mux._MuxHandler(request, dispatcher)
+ mux_handler.start()
+ # Client has len('Hello') + len('Goodbye') + 2 bytes quota.
+ mux_handler.add_channel_slots(mux._INITIAL_NUMBER_OF_CHANNEL_SLOTS, 14)
+
+ encoded_handshake = _create_request_header(path='/echo')
+ add_channel_request = _create_add_channel_request_frame(
+ channel_id=2, encoding=0,
+ encoded_handshake=encoded_handshake)
+ request.connection.put_bytes(add_channel_request)
+
+ flow_control = _create_flow_control_frame(channel_id=2,
+ replenished_quota=6)
+ request.connection.put_bytes(flow_control)
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=2, message='He', fin=False,
+ opcode=common.OPCODE_TEXT))
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=2, message='llo', fin=True,
+ opcode=common.OPCODE_CONTINUATION))
+
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=1, message='Goodbye'))
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=2, message='Goodbye'))
+
+ self.assertTrue(mux_handler.wait_until_done(timeout=2))
+
+ messages = request.connection.get_written_messages(2)
+ self.assertEqual(['Hello'], messages)
+
+ def test_fragmented_control_message(self):
+ request = _create_mock_request()
+ dispatcher = _MuxMockDispatcher()
+ mux_handler = mux._MuxHandler(request, dispatcher)
+ mux_handler.start()
+ mux_handler.add_channel_slots(mux._INITIAL_NUMBER_OF_CHANNEL_SLOTS,
+ mux._INITIAL_QUOTA_FOR_CLIENT)
+
+ encoded_handshake = _create_request_header(path='/ping')
+ add_channel_request = _create_add_channel_request_frame(
+ channel_id=2, encoding=0,
+ encoded_handshake=encoded_handshake)
+ request.connection.put_bytes(add_channel_request)
+
+ # Replenish total 6 bytes in 3 FlowControls.
+ flow_control = _create_flow_control_frame(channel_id=2,
+ replenished_quota=1)
+ request.connection.put_bytes(flow_control)
+
+ flow_control = _create_flow_control_frame(channel_id=2,
+ replenished_quota=2)
+ request.connection.put_bytes(flow_control)
+
+ flow_control = _create_flow_control_frame(channel_id=2,
+ replenished_quota=3)
+ request.connection.put_bytes(flow_control)
+
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=1, message='Goodbye'))
+
+ self.assertTrue(mux_handler.wait_until_done(timeout=2))
+
+ messages = request.connection.get_written_control_messages(2)
+ self.assertEqual(common.OPCODE_PING, messages[0]['opcode'])
+ self.assertEqual('Ping!', messages[0]['message'])
+
+ def test_channel_slot_violation_by_client(self):
+ request = _create_mock_request()
+ dispatcher = _MuxMockDispatcher()
+ mux_handler = mux._MuxHandler(request, dispatcher)
+ mux_handler.start()
+ mux_handler.add_channel_slots(slots=1,
+ send_quota=mux._INITIAL_QUOTA_FOR_CLIENT)
+
+ encoded_handshake = _create_request_header(path='/echo')
+ add_channel_request = _create_add_channel_request_frame(
+ channel_id=2, encoding=0,
+ encoded_handshake=encoded_handshake)
+ request.connection.put_bytes(add_channel_request)
+ flow_control = _create_flow_control_frame(channel_id=2,
+ replenished_quota=6)
+ request.connection.put_bytes(flow_control)
+
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=2, message='Hello'))
+
+ # This request should be rejected.
+ encoded_handshake = _create_request_header(path='/echo')
+ add_channel_request = _create_add_channel_request_frame(
+ channel_id=3, encoding=0,
+ encoded_handshake=encoded_handshake)
+ request.connection.put_bytes(add_channel_request)
+ flow_control = _create_flow_control_frame(channel_id=3,
+ replenished_quota=6)
+ request.connection.put_bytes(flow_control)
+
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=3, message='Hello'))
+
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=1, message='Goodbye'))
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=2, message='Goodbye'))
+
+ self.assertTrue(mux_handler.wait_until_done(timeout=2))
+
+ self.assertEqual([], dispatcher.channel_events[1].messages)
+ self.assertEqual(['Hello'], dispatcher.channel_events[2].messages)
+ self.assertFalse(dispatcher.channel_events.has_key(3))
+ drop_channel = next(
+ b for b in request.connection.get_written_control_blocks()
+ if b.opcode == mux._MUX_OPCODE_DROP_CHANNEL)
+ self.assertEqual(3, drop_channel.channel_id)
+ self.assertEqual(mux._DROP_CODE_NEW_CHANNEL_SLOT_VIOLATION,
+ drop_channel.drop_code)
+
+ def test_quota_overflow_by_client(self):
+ request = _create_mock_request()
+ dispatcher = _MuxMockDispatcher()
+ mux_handler = mux._MuxHandler(request, dispatcher)
+ mux_handler.start()
+ mux_handler.add_channel_slots(slots=1,
+ send_quota=mux._INITIAL_QUOTA_FOR_CLIENT)
+
+ encoded_handshake = _create_request_header(path='/echo')
+ add_channel_request = _create_add_channel_request_frame(
+ channel_id=2, encoding=0,
+ encoded_handshake=encoded_handshake)
+ request.connection.put_bytes(add_channel_request)
+ # Replenish 0x7FFFFFFFFFFFFFFF bytes twice.
+ flow_control = _create_flow_control_frame(
+ channel_id=2,
+ replenished_quota=0x7FFFFFFFFFFFFFFF)
+ request.connection.put_bytes(flow_control)
+ request.connection.put_bytes(flow_control)
+
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=1, message='Goodbye'))
+
+ self.assertTrue(mux_handler.wait_until_done(timeout=2))
+
+ drop_channel = next(
+ b for b in request.connection.get_written_control_blocks()
+ if b.opcode == mux._MUX_OPCODE_DROP_CHANNEL)
+ self.assertEqual(2, drop_channel.channel_id)
+ self.assertEqual(mux._DROP_CODE_SEND_QUOTA_OVERFLOW,
+ drop_channel.drop_code)
+
+ def test_invalid_encapsulated_message(self):
+ request = _create_mock_request()
+ dispatcher = _MuxMockDispatcher()
+ mux_handler = mux._MuxHandler(request, dispatcher)
+ mux_handler.start()
+
+ first_byte = (mux._MUX_OPCODE_ADD_CHANNEL_REQUEST << 5)
+ block = (chr(first_byte) +
+ mux._encode_channel_id(1) +
+ mux._encode_number(0))
+ payload = mux._encode_channel_id(mux._CONTROL_CHANNEL_ID) + block
+ text_frame = create_binary_frame(payload, opcode=common.OPCODE_TEXT,
+ mask=True)
+ request.connection.put_bytes(text_frame)
+
+ self.assertTrue(mux_handler.wait_until_done(timeout=2))
+
+ drop_channel = next(
+ b for b in request.connection.get_written_control_blocks()
+ if b.opcode == mux._MUX_OPCODE_DROP_CHANNEL)
+ self.assertEqual(mux._DROP_CODE_INVALID_ENCAPSULATING_MESSAGE,
+ drop_channel.drop_code)
+ self.assertEqual(common.STATUS_INTERNAL_ENDPOINT_ERROR,
+ request.connection.server_close_code)
+
+ def test_channel_id_truncated(self):
+ request = _create_mock_request()
+ dispatcher = _MuxMockDispatcher()
+ mux_handler = mux._MuxHandler(request, dispatcher)
+ mux_handler.start()
+
+ # The last byte of the channel id is missing.
+ frame = create_binary_frame('\x80', mask=True)
+ request.connection.put_bytes(frame)
+
+ self.assertTrue(mux_handler.wait_until_done(timeout=2))
+
+ drop_channel = next(
+ b for b in request.connection.get_written_control_blocks()
+ if b.opcode == mux._MUX_OPCODE_DROP_CHANNEL)
+ self.assertEqual(mux._DROP_CODE_CHANNEL_ID_TRUNCATED,
+ drop_channel.drop_code)
+ self.assertEqual(common.STATUS_INTERNAL_ENDPOINT_ERROR,
+ request.connection.server_close_code)
+
+ def test_inner_frame_truncated(self):
+ request = _create_mock_request()
+ dispatcher = _MuxMockDispatcher()
+ mux_handler = mux._MuxHandler(request, dispatcher)
+ mux_handler.start()
+
+ # Just contain channel id 1.
+ frame = create_binary_frame('\x01', mask=True)
+ request.connection.put_bytes(frame)
+
+ self.assertTrue(mux_handler.wait_until_done(timeout=2))
+
+ drop_channel = next(
+ b for b in request.connection.get_written_control_blocks()
+ if b.opcode == mux._MUX_OPCODE_DROP_CHANNEL)
+ self.assertEqual(mux._DROP_CODE_ENCAPSULATED_FRAME_IS_TRUNCATED,
+ drop_channel.drop_code)
+ self.assertEqual(common.STATUS_INTERNAL_ENDPOINT_ERROR,
+ request.connection.server_close_code)
+
+ def test_unknown_mux_opcode(self):
+ request = _create_mock_request()
+ dispatcher = _MuxMockDispatcher()
+ mux_handler = mux._MuxHandler(request, dispatcher)
+ mux_handler.start()
+
+ # Undefined opcode 5
+ frame = create_binary_frame('\x00\xa0', mask=True)
+ request.connection.put_bytes(frame)
+
+ self.assertTrue(mux_handler.wait_until_done(timeout=2))
+
+ drop_channel = next(
+ b for b in request.connection.get_written_control_blocks()
+ if b.opcode == mux._MUX_OPCODE_DROP_CHANNEL)
+ self.assertEqual(mux._DROP_CODE_UNKNOWN_MUX_OPCODE,
+ drop_channel.drop_code)
+ self.assertEqual(common.STATUS_INTERNAL_ENDPOINT_ERROR,
+ request.connection.server_close_code)
+
+ def test_invalid_mux_control_block(self):
+ request = _create_mock_request()
+ dispatcher = _MuxMockDispatcher()
+ mux_handler = mux._MuxHandler(request, dispatcher)
+ mux_handler.start()
+
+ # DropChannel contains 1 byte reason
+ frame = create_binary_frame('\x00\x60\x00\x01\x00', mask=True)
+ request.connection.put_bytes(frame)
+
+ self.assertTrue(mux_handler.wait_until_done(timeout=2))
+
+ drop_channel = next(
+ b for b in request.connection.get_written_control_blocks()
+ if b.opcode == mux._MUX_OPCODE_DROP_CHANNEL)
+ self.assertEqual(mux._DROP_CODE_INVALID_MUX_CONTROL_BLOCK,
+ drop_channel.drop_code)
+ self.assertEqual(common.STATUS_INTERNAL_ENDPOINT_ERROR,
+ request.connection.server_close_code)
+
+ def test_permessage_compress(self):
+ request = _create_mock_request()
+ dispatcher = _MuxMockDispatcher()
+ mux_handler = mux._MuxHandler(request, dispatcher)
+ mux_handler.start()
+ mux_handler.add_channel_slots(mux._INITIAL_NUMBER_OF_CHANNEL_SLOTS,
+ mux._INITIAL_QUOTA_FOR_CLIENT)
+
+ # Enable permessage compress extension on logical channel 2.
+ extensions = '%s; method=deflate' % (
+ common.PERMESSAGE_COMPRESSION_EXTENSION)
+ encoded_handshake = _create_request_header(path='/echo',
+ extensions=extensions)
+ add_channel_request = _create_add_channel_request_frame(
+ channel_id=2, encoding=0,
+ encoded_handshake=encoded_handshake)
+ request.connection.put_bytes(add_channel_request)
+
+ flow_control = _create_flow_control_frame(channel_id=2,
+ replenished_quota=20)
+ request.connection.put_bytes(flow_control)
+
+ # Send compressed 'Hello' twice.
+ compress = zlib.compressobj(
+ zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -zlib.MAX_WBITS)
+ compressed_hello1 = compress.compress('Hello')
+ compressed_hello1 += compress.flush(zlib.Z_SYNC_FLUSH)
+ compressed_hello1 = compressed_hello1[:-4]
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=2, message=compressed_hello1,
+ rsv1=True))
+ compressed_hello2 = compress.compress('Hello')
+ compressed_hello2 += compress.flush(zlib.Z_SYNC_FLUSH)
+ compressed_hello2 = compressed_hello2[:-4]
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=2, message=compressed_hello2,
+ rsv1=True))
+
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=1, message='Goodbye'))
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=2, message='Goodbye'))
+
+ self.assertTrue(mux_handler.wait_until_done(timeout=2))
+
+ self.assertEqual(['Hello', 'Hello'],
+ dispatcher.channel_events[2].messages)
+ # Written 'Hello's should be compressed.
+ messages = request.connection.get_written_messages(2)
+ self.assertEqual(2, len(messages))
+ self.assertEqual(compressed_hello1, messages[0])
+ self.assertEqual(compressed_hello2, messages[1])
+
+
+ def test_permessage_compress_fragmented_message(self):
+ extensions = common.parse_extensions(
+ '%s; method=deflate' % common.PERMESSAGE_COMPRESSION_EXTENSION)
+ request = _create_mock_request(
+ logical_channel_extensions=extensions)
+ dispatcher = _MuxMockDispatcher()
+ mux_handler = mux._MuxHandler(request, dispatcher)
+ mux_handler.start()
+ mux_handler.add_channel_slots(mux._INITIAL_NUMBER_OF_CHANNEL_SLOTS,
+ mux._INITIAL_QUOTA_FOR_CLIENT)
+
+ # Send compressed 'HelloHelloHello' as fragmented message.
+ compress = zlib.compressobj(
+ zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -zlib.MAX_WBITS)
+ compressed_hello = compress.compress('HelloHelloHello')
+ compressed_hello += compress.flush(zlib.Z_SYNC_FLUSH)
+ compressed_hello = compressed_hello[:-4]
+
+ m = len(compressed_hello) / 2
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=1,
+ message=compressed_hello[:m],
+ fin=False, rsv1=True,
+ opcode=common.OPCODE_TEXT))
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=1,
+ message=compressed_hello[m:],
+ fin=True, rsv1=False,
+ opcode=common.OPCODE_CONTINUATION))
+
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=1, message='Goodbye'))
+
+ self.assertTrue(mux_handler.wait_until_done(timeout=2))
+
+ self.assertEqual(['HelloHelloHello'],
+ dispatcher.channel_events[1].messages)
+ messages = request.connection.get_written_messages(1)
+ self.assertEqual(1, len(messages))
+ self.assertEqual(compressed_hello, messages[0])
+
+ def test_receive_bad_fragmented_message(self):
+ request = _create_mock_request()
+ dispatcher = _MuxMockDispatcher()
+ mux_handler = mux._MuxHandler(request, dispatcher)
+ mux_handler.start()
+ mux_handler.add_channel_slots(mux._INITIAL_NUMBER_OF_CHANNEL_SLOTS,
+ mux._INITIAL_QUOTA_FOR_CLIENT)
+
+ encoded_handshake = _create_request_header(path='/echo')
+ add_channel_request = _create_add_channel_request_frame(
+ channel_id=2, encoding=0,
+ encoded_handshake=encoded_handshake)
+ request.connection.put_bytes(add_channel_request)
+
+ # Send a frame with fin=False, and then send a frame with
+ # opcode=TEXT (not CONTINUATION). Logical channel 2 should be dropped.
+ frame1 = _create_logical_frame(channel_id=2,
+ message='Hello ',
+ fin=False,
+ opcode=common.OPCODE_TEXT)
+ request.connection.put_bytes(frame1)
+ frame2 = _create_logical_frame(channel_id=2,
+ message='World!',
+ fin=True,
+ opcode=common.OPCODE_TEXT)
+ request.connection.put_bytes(frame2)
+
+ encoded_handshake = _create_request_header(path='/echo')
+ add_channel_request = _create_add_channel_request_frame(
+ channel_id=3, encoding=0,
+ encoded_handshake=encoded_handshake)
+ request.connection.put_bytes(add_channel_request)
+
+ # Send a frame with opcode=CONTINUATION without a preceding frame
+ # the fin of which is not set. Logical channel 3 should be dropped.
+ frame3 = _create_logical_frame(channel_id=3,
+ message='Hello',
+ fin=True,
+ opcode=common.OPCODE_CONTINUATION)
+ request.connection.put_bytes(frame3)
+
+ encoded_handshake = _create_request_header(path='/echo')
+ add_channel_request = _create_add_channel_request_frame(
+ channel_id=4, encoding=0,
+ encoded_handshake=encoded_handshake)
+ request.connection.put_bytes(add_channel_request)
+
+ # Send a frame with opcode=PING and fin=False, and then send a frame
+ # with opcode=TEXT (not CONTINUATION). Logical channel 4 should be
+ # dropped.
+ frame4 = _create_logical_frame(channel_id=4,
+ message='Ping',
+ fin=False,
+ opcode=common.OPCODE_PING)
+ request.connection.put_bytes(frame4)
+ frame5 = _create_logical_frame(channel_id=4,
+ message='Hello',
+ fin=True,
+ opcode=common.OPCODE_TEXT)
+ request.connection.put_bytes(frame5)
+
+ request.connection.put_bytes(
+ _create_logical_frame(channel_id=1, message='Goodbye'))
+
+ self.assertTrue(mux_handler.wait_until_done(timeout=2))
+
+ drop_channels = [
+ b for b in request.connection.get_written_control_blocks()
+ if b.opcode == mux._MUX_OPCODE_DROP_CHANNEL]
+ self.assertEqual(3, len(drop_channels))
+ for d in drop_channels:
+ self.assertEqual(mux._DROP_CODE_BAD_FRAGMENTATION,
+ d.drop_code)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/test_stream.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/test_stream.py
new file mode 100755
index 00000000000..81acfeb048d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/test_stream.py
@@ -0,0 +1,77 @@
+#!/usr/bin/env python
+#
+# Copyright 2011, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+"""Tests for stream module."""
+
+
+import unittest
+
+import set_sys_path # Update sys.path to locate mod_pywebsocket module.
+
+from mod_pywebsocket import common
+from mod_pywebsocket import stream
+
+
+class StreamTest(unittest.TestCase):
+ """A unittest for stream module."""
+
+ def test_create_header(self):
+ # more, rsv1, ..., rsv4 are all true
+ header = stream.create_header(common.OPCODE_TEXT, 1, 1, 1, 1, 1, 1)
+ self.assertEqual('\xf1\x81', header)
+
+ # Maximum payload size
+ header = stream.create_header(
+ common.OPCODE_TEXT, (1 << 63) - 1, 0, 0, 0, 0, 0)
+ self.assertEqual('\x01\x7f\x7f\xff\xff\xff\xff\xff\xff\xff', header)
+
+ # Invalid opcode 0x10
+ self.assertRaises(ValueError,
+ stream.create_header,
+ 0x10, 0, 0, 0, 0, 0, 0)
+
+ # Invalid value 0xf passed to more parameter
+ self.assertRaises(ValueError,
+ stream.create_header,
+ common.OPCODE_TEXT, 0, 0xf, 0, 0, 0, 0)
+
+ # Too long payload_length
+ self.assertRaises(ValueError,
+ stream.create_header,
+ common.OPCODE_TEXT, 1 << 63, 0, 0, 0, 0, 0)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/test_stream_hixie75.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/test_stream_hixie75.py
new file mode 100755
index 00000000000..ca9ac7130b7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/test_stream_hixie75.py
@@ -0,0 +1,59 @@
+#!/usr/bin/env python
+#
+# Copyright 2011, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+"""Tests for stream module."""
+
+
+import unittest
+
+import set_sys_path # Update sys.path to locate mod_pywebsocket module.
+
+from mod_pywebsocket.stream import StreamHixie75
+from test.test_msgutil import _create_request_hixie75
+
+
+class StreamHixie75Test(unittest.TestCase):
+ """A unittest for StreamHixie75 class."""
+
+ def test_payload_length(self):
+ for length, bytes in ((0, '\x00'), (0x7f, '\x7f'), (0x80, '\x81\x00'),
+ (0x1234, '\x80\xa4\x34')):
+ test_stream = StreamHixie75(_create_request_hixie75(bytes))
+ self.assertEqual(
+ length, test_stream._read_payload_length_hixie75())
+
+
+if __name__ == '__main__':
+ unittest.main()
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/test_util.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/test_util.py
new file mode 100755
index 00000000000..20f4ab05965
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/test_util.py
@@ -0,0 +1,200 @@
+#!/usr/bin/env python
+#
+# Copyright 2011, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+"""Tests for util module."""
+
+
+import os
+import random
+import sys
+import unittest
+
+import set_sys_path # Update sys.path to locate mod_pywebsocket module.
+
+from mod_pywebsocket import util
+
+
+_TEST_DATA_DIR = os.path.join(os.path.split(__file__)[0], 'testdata')
+
+
+class UtilTest(unittest.TestCase):
+ """A unittest for util module."""
+
+ def test_get_stack_trace(self):
+ self.assertEqual('None\n', util.get_stack_trace())
+ try:
+ a = 1 / 0 # Intentionally raise exception.
+ except Exception:
+ trace = util.get_stack_trace()
+ self.failUnless(trace.startswith('Traceback'))
+ self.failUnless(trace.find('ZeroDivisionError') != -1)
+
+ def test_prepend_message_to_exception(self):
+ exc = Exception('World')
+ self.assertEqual('World', str(exc))
+ util.prepend_message_to_exception('Hello ', exc)
+ self.assertEqual('Hello World', str(exc))
+
+ def test_get_script_interp(self):
+ cygwin_path = 'c:\\cygwin\\bin'
+ cygwin_perl = os.path.join(cygwin_path, 'perl')
+ self.assertEqual(None, util.get_script_interp(
+ os.path.join(_TEST_DATA_DIR, 'README')))
+ self.assertEqual(None, util.get_script_interp(
+ os.path.join(_TEST_DATA_DIR, 'README'), cygwin_path))
+ self.assertEqual('/usr/bin/perl -wT', util.get_script_interp(
+ os.path.join(_TEST_DATA_DIR, 'hello.pl')))
+ self.assertEqual(cygwin_perl + ' -wT', util.get_script_interp(
+ os.path.join(_TEST_DATA_DIR, 'hello.pl'), cygwin_path))
+
+ def test_hexify(self):
+ self.assertEqual('61 7a 41 5a 30 39 20 09 0d 0a 00 ff',
+ util.hexify('azAZ09 \t\r\n\x00\xff'))
+
+
+class RepeatedXorMaskerTest(unittest.TestCase):
+ """A unittest for RepeatedXorMasker class."""
+
+ def test_mask(self):
+ # Sample input e6,97,a5 is U+65e5 in UTF-8
+ masker = util.RepeatedXorMasker('\xff\xff\xff\xff')
+ result = masker.mask('\xe6\x97\xa5')
+ self.assertEqual('\x19\x68\x5a', result)
+
+ masker = util.RepeatedXorMasker('\x00\x00\x00\x00')
+ result = masker.mask('\xe6\x97\xa5')
+ self.assertEqual('\xe6\x97\xa5', result)
+
+ masker = util.RepeatedXorMasker('\xe6\x97\xa5\x20')
+ result = masker.mask('\xe6\x97\xa5')
+ self.assertEqual('\x00\x00\x00', result)
+
+ def test_mask_twice(self):
+ masker = util.RepeatedXorMasker('\x00\x7f\xff\x20')
+ # mask[0], mask[1], ... will be used.
+ result = masker.mask('\x00\x00\x00\x00\x00')
+ self.assertEqual('\x00\x7f\xff\x20\x00', result)
+ # mask[2], mask[0], ... will be used for the next call.
+ result = masker.mask('\x00\x00\x00\x00\x00')
+ self.assertEqual('\x7f\xff\x20\x00\x7f', result)
+
+ def test_mask_large_data(self):
+ masker = util.RepeatedXorMasker('mASk')
+ original = ''.join([chr(i % 256) for i in xrange(1000)])
+ result = masker.mask(original)
+ expected = ''.join(
+ [chr((i % 256) ^ ord('mASk'[i % 4])) for i in xrange(1000)])
+ self.assertEqual(expected, result)
+
+ masker = util.RepeatedXorMasker('MaSk')
+ first_part = 'The WebSocket Protocol enables two-way communication.'
+ result = masker.mask(first_part)
+ self.assertEqual(
+ '\x19\t6K\x1a\x0418"\x028\x0e9A\x03\x19"\x15<\x08"\rs\x0e#'
+ '\x001\x07(\x12s\x1f:\x0e~\x1c,\x18s\x08"\x0c>\x1e#\x080\n9'
+ '\x08<\x05c',
+ result)
+ second_part = 'It has two parts: a handshake and the data transfer.'
+ result = masker.mask(second_part)
+ self.assertEqual(
+ "('K%\x00 K9\x16<K=\x00!\x1f>[s\nm\t2\x05)\x12;\n&\x04s\n#"
+ "\x05s\x1f%\x04s\x0f,\x152K9\x132\x05>\x076\x19c",
+ result)
+
+
+def get_random_section(source, min_num_chunks):
+ chunks = []
+ bytes_chunked = 0
+
+ while bytes_chunked < len(source):
+ chunk_size = random.randint(
+ 1,
+ min(len(source) / min_num_chunks, len(source) - bytes_chunked))
+ chunk = source[bytes_chunked:bytes_chunked + chunk_size]
+ chunks.append(chunk)
+ bytes_chunked += chunk_size
+
+ return chunks
+
+
+class InflaterDeflaterTest(unittest.TestCase):
+ """A unittest for _Inflater and _Deflater class."""
+
+ def test_inflate_deflate_default(self):
+ input = b'hello' + '-' * 30000 + b'hello'
+ inflater15 = util._Inflater(15)
+ deflater15 = util._Deflater(15)
+ inflater8 = util._Inflater(8)
+ deflater8 = util._Deflater(8)
+
+ compressed15 = deflater15.compress_and_finish(input)
+ compressed8 = deflater8.compress_and_finish(input)
+
+ inflater15.append(compressed15)
+ inflater8.append(compressed8)
+
+ self.assertNotEqual(compressed15, compressed8)
+ self.assertEqual(input, inflater15.decompress(-1))
+ self.assertEqual(input, inflater8.decompress(-1))
+
+ def test_random_section(self):
+ random.seed(a=0)
+ source = ''.join(
+ [chr(random.randint(0, 255)) for i in xrange(100 * 1024)])
+
+ chunked_input = get_random_section(source, 10)
+ print "Input chunk sizes: %r" % [len(c) for c in chunked_input]
+
+ deflater = util._Deflater(15)
+ compressed = []
+ for chunk in chunked_input:
+ compressed.append(deflater.compress(chunk))
+ compressed.append(deflater.compress_and_finish(''))
+
+ chunked_expectation = get_random_section(source, 10)
+ print ("Expectation chunk sizes: %r" %
+ [len(c) for c in chunked_expectation])
+
+ inflater = util._Inflater(15)
+ inflater.append(''.join(compressed))
+ for chunk in chunked_expectation:
+ decompressed = inflater.decompress(len(chunk))
+ self.assertEqual(chunk, decompressed)
+
+ self.assertEqual('', inflater.decompress(-1))
+
+
+if __name__ == '__main__':
+ unittest.main()
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/testdata/README b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/testdata/README
new file mode 100644
index 00000000000..c001aa5595c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/testdata/README
@@ -0,0 +1 @@
+Test data directory
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/testdata/handlers/abort_by_user_wsh.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/testdata/handlers/abort_by_user_wsh.py
new file mode 100644
index 00000000000..367f9930f78
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/testdata/handlers/abort_by_user_wsh.py
@@ -0,0 +1,42 @@
+# Copyright 2011, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+from mod_pywebsocket import handshake
+
+
+def web_socket_do_extra_handshake(request):
+ raise handshake.AbortedByUserException("abort for test")
+
+
+def web_socket_transfer_data(request):
+ raise handshake.AbortedByUserException("abort for test")
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/testdata/handlers/blank_wsh.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/testdata/handlers/blank_wsh.py
new file mode 100644
index 00000000000..7f87c6af23d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/testdata/handlers/blank_wsh.py
@@ -0,0 +1,31 @@
+# Copyright 2009, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+# intentionally left blank
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/testdata/handlers/origin_check_wsh.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/testdata/handlers/origin_check_wsh.py
new file mode 100644
index 00000000000..2c139fa176c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/testdata/handlers/origin_check_wsh.py
@@ -0,0 +1,42 @@
+# Copyright 2009, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+def web_socket_do_extra_handshake(request):
+ if request.ws_origin == 'http://example.com':
+ return
+ raise ValueError('Unacceptable origin: %r' % request.ws_origin)
+
+
+def web_socket_transfer_data(request):
+ request.connection.write('origin_check_wsh.py is called for %s, %s' %
+ (request.ws_resource, request.ws_protocol))
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/testdata/handlers/sub/exception_in_transfer_wsh.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/testdata/handlers/sub/exception_in_transfer_wsh.py
new file mode 100644
index 00000000000..b982d0231ef
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/testdata/handlers/sub/exception_in_transfer_wsh.py
@@ -0,0 +1,44 @@
+# Copyright 2009, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+"""Exception in web_socket_transfer_data().
+"""
+
+
+def web_socket_do_extra_handshake(request):
+ pass
+
+
+def web_socket_transfer_data(request):
+ raise Exception('Intentional Exception for %s, %s' %
+ (request.ws_resource, request.ws_protocol))
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/testdata/handlers/sub/no_wsh_at_the_end.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/testdata/handlers/sub/no_wsh_at_the_end.py
new file mode 100644
index 00000000000..17e7be1802e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/testdata/handlers/sub/no_wsh_at_the_end.py
@@ -0,0 +1,45 @@
+# Copyright 2009, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+"""Correct signatures, wrong file name.
+"""
+
+
+def web_socket_do_extra_handshake(request):
+ pass
+
+
+def web_socket_transfer_data(request):
+ request.connection.write(
+ 'sub/no_wsh_at_the_end.py is called for %s, %s' %
+ (request.ws_resource, request.ws_protocol))
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/testdata/handlers/sub/non_callable_wsh.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/testdata/handlers/sub/non_callable_wsh.py
new file mode 100644
index 00000000000..26352eb4ca2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/testdata/handlers/sub/non_callable_wsh.py
@@ -0,0 +1,39 @@
+# Copyright 2009, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+"""Non-callable handlers.
+"""
+
+
+web_socket_do_extra_handshake = True
+web_socket_transfer_data = 1
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/testdata/handlers/sub/plain_wsh.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/testdata/handlers/sub/plain_wsh.py
new file mode 100644
index 00000000000..db3ff693025
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/testdata/handlers/sub/plain_wsh.py
@@ -0,0 +1,40 @@
+# Copyright 2009, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+def web_socket_do_extra_handshake(request):
+ pass
+
+
+def web_socket_transfer_data(request):
+ request.connection.write('sub/plain_wsh.py is called for %s, %s' %
+ (request.ws_resource, request.ws_protocol))
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/testdata/handlers/sub/wrong_handshake_sig_wsh.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/testdata/handlers/sub/wrong_handshake_sig_wsh.py
new file mode 100644
index 00000000000..6bf659bc9af
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/testdata/handlers/sub/wrong_handshake_sig_wsh.py
@@ -0,0 +1,45 @@
+# Copyright 2009, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+"""Wrong web_socket_do_extra_handshake signature.
+"""
+
+
+def no_web_socket_do_extra_handshake(request):
+ pass
+
+
+def web_socket_transfer_data(request):
+ request.connection.write(
+ 'sub/wrong_handshake_sig_wsh.py is called for %s, %s' %
+ (request.ws_resource, request.ws_protocol))
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/testdata/handlers/sub/wrong_transfer_sig_wsh.py b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/testdata/handlers/sub/wrong_transfer_sig_wsh.py
new file mode 100644
index 00000000000..e0e2e550794
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/testdata/handlers/sub/wrong_transfer_sig_wsh.py
@@ -0,0 +1,45 @@
+# Copyright 2009, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+"""Wrong web_socket_transfer_data() signature.
+"""
+
+
+def web_socket_do_extra_handshake(request):
+ pass
+
+
+def no_web_socket_transfer_data(request):
+ request.connection.write(
+ 'sub/wrong_transfer_sig_wsh.py is called for %s, %s' %
+ (request.ws_resource, request.ws_protocol))
+
+
+# vi:sts=4 sw=4 et
diff --git a/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/testdata/hello.pl b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/testdata/hello.pl
new file mode 100644
index 00000000000..882ef5a1006
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/pywebsocket/src/test/testdata/hello.pl
@@ -0,0 +1,32 @@
+#!/usr/bin/perl -wT
+#
+# Copyright 2012, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+print "Hello\n";
diff --git a/tests/wpt/web-platform-tests/tools/runner/css/bootstrap-theme.min.css b/tests/wpt/web-platform-tests/tools/runner/css/bootstrap-theme.min.css
new file mode 100644
index 00000000000..8dee0720934
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/runner/css/bootstrap-theme.min.css
@@ -0,0 +1,7 @@
+/*!
+ * Bootstrap v3.1.1 (http://getbootstrap.com)
+ * Copyright 2011-2014 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */
+
+.btn-default,.btn-primary,.btn-success,.btn-info,.btn-warning,.btn-danger{text-shadow:0 -1px 0 rgba(0,0,0,0.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 1px rgba(0,0,0,0.075)}.btn-default:active,.btn-primary:active,.btn-success:active,.btn-info:active,.btn-warning:active,.btn-danger:active,.btn-default.active,.btn-primary.active,.btn-success.active,.btn-info.active,.btn-warning.active,.btn-danger.active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn:active,.btn.active{background-image:none}.btn-default{background-image:-webkit-linear-gradient(top, #fff 0, #e0e0e0 100%);background-image:linear-gradient(to bottom, #fff 0, #e0e0e0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background-repeat:repeat-x;border-color:#dbdbdb;text-shadow:0 1px 0 #fff;border-color:#ccc}.btn-default:hover,.btn-default:focus{background-color:#e0e0e0;background-position:0 -15px}.btn-default:active,.btn-default.active{background-color:#e0e0e0;border-color:#dbdbdb}.btn-primary{background-image:-webkit-linear-gradient(top, #428bca 0, #2d6ca2 100%);background-image:linear-gradient(to bottom, #428bca 0, #2d6ca2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff2d6ca2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background-repeat:repeat-x;border-color:#2b669a}.btn-primary:hover,.btn-primary:focus{background-color:#2d6ca2;background-position:0 -15px}.btn-primary:active,.btn-primary.active{background-color:#2d6ca2;border-color:#2b669a}.btn-success{background-image:-webkit-linear-gradient(top, #5cb85c 0, #419641 100%);background-image:linear-gradient(to bottom, #5cb85c 0, #419641 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background-repeat:repeat-x;border-color:#3e8f3e}.btn-success:hover,.btn-success:focus{background-color:#419641;background-position:0 -15px}.btn-success:active,.btn-success.active{background-color:#419641;border-color:#3e8f3e}.btn-info{background-image:-webkit-linear-gradient(top, #5bc0de 0, #2aabd2 100%);background-image:linear-gradient(to bottom, #5bc0de 0, #2aabd2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background-repeat:repeat-x;border-color:#28a4c9}.btn-info:hover,.btn-info:focus{background-color:#2aabd2;background-position:0 -15px}.btn-info:active,.btn-info.active{background-color:#2aabd2;border-color:#28a4c9}.btn-warning{background-image:-webkit-linear-gradient(top, #f0ad4e 0, #eb9316 100%);background-image:linear-gradient(to bottom, #f0ad4e 0, #eb9316 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background-repeat:repeat-x;border-color:#e38d13}.btn-warning:hover,.btn-warning:focus{background-color:#eb9316;background-position:0 -15px}.btn-warning:active,.btn-warning.active{background-color:#eb9316;border-color:#e38d13}.btn-danger{background-image:-webkit-linear-gradient(top, #d9534f 0, #c12e2a 100%);background-image:linear-gradient(to bottom, #d9534f 0, #c12e2a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);background-repeat:repeat-x;border-color:#b92c28}.btn-danger:hover,.btn-danger:focus{background-color:#c12e2a;background-position:0 -15px}.btn-danger:active,.btn-danger.active{background-color:#c12e2a;border-color:#b92c28}.thumbnail,.img-thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.075);box-shadow:0 1px 2px rgba(0,0,0,0.075)}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{background-image:-webkit-linear-gradient(top, #f5f5f5 0, #e8e8e8 100%);background-image:linear-gradient(to bottom, #f5f5f5 0, #e8e8e8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-color:#e8e8e8}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{background-image:-webkit-linear-gradient(top, #428bca 0, #357ebd 100%);background-image:linear-gradient(to bottom, #428bca 0, #357ebd 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);background-color:#357ebd}.navbar-default{background-image:-webkit-linear-gradient(top, #fff 0, #f8f8f8 100%);background-image:linear-gradient(to bottom, #fff 0, #f8f8f8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 5px rgba(0,0,0,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 5px rgba(0,0,0,0.075)}.navbar-default .navbar-nav>.active>a{background-image:-webkit-linear-gradient(top, #ebebeb 0, #f3f3f3 100%);background-image:linear-gradient(to bottom, #ebebeb 0, #f3f3f3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff3f3f3', GradientType=0);-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,0.075);box-shadow:inset 0 3px 9px rgba(0,0,0,0.075)}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,0.25)}.navbar-inverse{background-image:-webkit-linear-gradient(top, #3c3c3c 0, #222 100%);background-image:linear-gradient(to bottom, #3c3c3c 0, #222 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled = false)}.navbar-inverse .navbar-nav>.active>a{background-image:-webkit-linear-gradient(top, #222 0, #282828 100%);background-image:linear-gradient(to bottom, #222 0, #282828 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff282828', GradientType=0);-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,0.25);box-shadow:inset 0 3px 9px rgba(0,0,0,0.25)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.navbar-static-top,.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}.alert{text-shadow:0 1px 0 rgba(255,255,255,0.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.25),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 1px 0 rgba(255,255,255,0.25),0 1px 2px rgba(0,0,0,0.05)}.alert-success{background-image:-webkit-linear-gradient(top, #dff0d8 0, #c8e5bc 100%);background-image:linear-gradient(to bottom, #dff0d8 0, #c8e5bc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);border-color:#b2dba1}.alert-info{background-image:-webkit-linear-gradient(top, #d9edf7 0, #b9def0 100%);background-image:linear-gradient(to bottom, #d9edf7 0, #b9def0 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);border-color:#9acfea}.alert-warning{background-image:-webkit-linear-gradient(top, #fcf8e3 0, #f8efc0 100%);background-image:linear-gradient(to bottom, #fcf8e3 0, #f8efc0 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);border-color:#f5e79e}.alert-danger{background-image:-webkit-linear-gradient(top, #f2dede 0, #e7c3c3 100%);background-image:linear-gradient(to bottom, #f2dede 0, #e7c3c3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);border-color:#dca7a7}.progress{background-image:-webkit-linear-gradient(top, #ebebeb 0, #f5f5f5 100%);background-image:linear-gradient(to bottom, #ebebeb 0, #f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0)}.progress-bar{background-image:-webkit-linear-gradient(top, #428bca 0, #3071a9 100%);background-image:linear-gradient(to bottom, #428bca 0, #3071a9 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0)}.progress-bar-success{background-image:-webkit-linear-gradient(top, #5cb85c 0, #449d44 100%);background-image:linear-gradient(to bottom, #5cb85c 0, #449d44 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0)}.progress-bar-info{background-image:-webkit-linear-gradient(top, #5bc0de 0, #31b0d5 100%);background-image:linear-gradient(to bottom, #5bc0de 0, #31b0d5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0)}.progress-bar-warning{background-image:-webkit-linear-gradient(top, #f0ad4e 0, #ec971f 100%);background-image:linear-gradient(to bottom, #f0ad4e 0, #ec971f 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0)}.progress-bar-danger{background-image:-webkit-linear-gradient(top, #d9534f 0, #c9302c 100%);background-image:linear-gradient(to bottom, #d9534f 0, #c9302c 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.075);box-shadow:0 1px 2px rgba(0,0,0,0.075)}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{text-shadow:0 -1px 0 #3071a9;background-image:-webkit-linear-gradient(top, #428bca 0, #3278b3 100%);background-image:linear-gradient(to bottom, #428bca 0, #3278b3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0);border-color:#3278b3}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.05);box-shadow:0 1px 2px rgba(0,0,0,0.05)}.panel-default>.panel-heading{background-image:-webkit-linear-gradient(top, #f5f5f5 0, #e8e8e8 100%);background-image:linear-gradient(to bottom, #f5f5f5 0, #e8e8e8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0)}.panel-primary>.panel-heading{background-image:-webkit-linear-gradient(top, #428bca 0, #357ebd 100%);background-image:linear-gradient(to bottom, #428bca 0, #357ebd 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0)}.panel-success>.panel-heading{background-image:-webkit-linear-gradient(top, #dff0d8 0, #d0e9c6 100%);background-image:linear-gradient(to bottom, #dff0d8 0, #d0e9c6 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0)}.panel-info>.panel-heading{background-image:-webkit-linear-gradient(top, #d9edf7 0, #c4e3f3 100%);background-image:linear-gradient(to bottom, #d9edf7 0, #c4e3f3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0)}.panel-warning>.panel-heading{background-image:-webkit-linear-gradient(top, #fcf8e3 0, #faf2cc 100%);background-image:linear-gradient(to bottom, #fcf8e3 0, #faf2cc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0)}.panel-danger>.panel-heading{background-image:-webkit-linear-gradient(top, #f2dede 0, #ebcccc 100%);background-image:linear-gradient(to bottom, #f2dede 0, #ebcccc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0)}.well{background-image:-webkit-linear-gradient(top, #e8e8e8 0, #f5f5f5 100%);background-image:linear-gradient(to bottom, #e8e8e8 0, #f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);border-color:#dcdcdc;-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,0.05),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 3px rgba(0,0,0,0.05),0 1px 0 rgba(255,255,255,0.1)} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/tools/runner/css/bootstrap.min.css b/tests/wpt/web-platform-tests/tools/runner/css/bootstrap.min.css
new file mode 100644
index 00000000000..de697fd7820
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/runner/css/bootstrap.min.css
@@ -0,0 +1,7 @@
+/*!
+ * Bootstrap v3.1.1 (http://getbootstrap.com)
+ * Copyright 2011-2014 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */
+
+/*! normalize.css v3.0.0 | MIT License | git.io/normalize */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:0.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace, monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:0.35em 0.625em 0.75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}@media print{*{text-shadow:none !important;color:#000 !important;background:transparent !important;box-shadow:none !important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}select{background:#fff !important}.navbar{display:none}.table td,.table th{background-color:#fff !important}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000 !important}.label{border:1px solid #000}.table{border-collapse:collapse !important}.table-bordered th,.table-bordered td{border:1px solid #ddd !important}}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}*:before,*:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:62.5%;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#428bca;text-decoration:none}a:hover,a:focus{color:#2a6496;text-decoration:underline}a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.img-responsive{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 .small,h2 .small,h3 .small,h4 .small,h5 .small,h6 .small,.h1 .small,.h2 .small,.h3 .small,.h4 .small,.h5 .small,.h6 .small{font-weight:normal;line-height:1;color:#999}h1,.h1,h2,.h2,h3,.h3{margin-top:20px;margin-bottom:10px}h1 small,.h1 small,h2 small,.h2 small,h3 small,.h3 small,h1 .small,.h1 .small,h2 .small,.h2 .small,h3 .small,.h3 .small{font-size:65%}h4,.h4,h5,.h5,h6,.h6{margin-top:10px;margin-bottom:10px}h4 small,.h4 small,h5 small,.h5 small,h6 small,.h6 small,h4 .small,.h4 .small,h5 .small,.h5 .small,h6 .small,.h6 .small{font-size:75%}h1,.h1{font-size:36px}h2,.h2{font-size:30px}h3,.h3{font-size:24px}h4,.h4{font-size:18px}h5,.h5{font-size:14px}h6,.h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:200;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}small,.small{font-size:85%}cite{font-style:normal}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-muted{color:#999}.text-primary{color:#428bca}a.text-primary:hover{color:#3071a9}.text-success{color:#3c763d}a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#428bca}a.bg-primary:hover{background-color:#3071a9}.bg-success{background-color:#dff0d8}a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ul,ol{margin-top:0;margin-bottom:10px}ul ul,ol ul,ul ol,ol ol{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none;margin-left:-5px}.list-inline>li{display:inline-block;padding-left:5px;padding-right:5px}dl{margin-top:0;margin-bottom:20px}dt,dd{line-height:1.42857143}dt{font-weight:bold}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote p:last-child,blockquote ul:last-child,blockquote ol:last-child{margin-bottom:0}blockquote footer,blockquote small,blockquote .small{display:block;font-size:80%;line-height:1.42857143;color:#999}blockquote footer:before,blockquote small:before,blockquote .small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0;text-align:right}.blockquote-reverse footer:before,blockquote.pull-right footer:before,.blockquote-reverse small:before,blockquote.pull-right small:before,.blockquote-reverse .small:before,blockquote.pull-right .small:before{content:''}.blockquote-reverse footer:after,blockquote.pull-right footer:after,.blockquote-reverse small:after,blockquote.pull-right small:after,.blockquote-reverse .small:after,blockquote.pull-right .small:after{content:'\00A0 \2014'}blockquote:before,blockquote:after{content:""}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;white-space:nowrap;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;box-shadow:inset 0 -1px 0 rgba(0,0,0,0.25)}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;word-break:break-all;word-wrap:break-word;color:#333;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}.row{margin-left:-15px;margin-right:-15px}.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12{position:relative;min-height:1px;padding-left:15px;padding-right:15px}.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:0}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:0}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:0}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:0}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:0}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:0}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:0}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:0}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{max-width:100%;background-color:transparent}th{text-align:left}.table{width:100%;margin-bottom:20px}.table>thead>tr>th,.table>tbody>tr>th,.table>tfoot>tr>th,.table>thead>tr>td,.table>tbody>tr>td,.table>tfoot>tr>td{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>th,.table>caption+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>td,.table>thead:first-child>tr:first-child>td{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>thead>tr>th,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>tbody>tr>td,.table-condensed>tfoot>tr>td{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px}.table-striped>tbody>tr:nth-child(odd)>td,.table-striped>tbody>tr:nth-child(odd)>th{background-color:#f9f9f9}.table-hover>tbody>tr:hover>td,.table-hover>tbody>tr:hover>th{background-color:#f5f5f5}table col[class*="col-"]{position:static;float:none;display:table-column}table td[class*="col-"],table th[class*="col-"]{position:static;float:none;display:table-cell}.table>thead>tr>td.active,.table>tbody>tr>td.active,.table>tfoot>tr>td.active,.table>thead>tr>th.active,.table>tbody>tr>th.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>tbody>tr.active>td,.table>tfoot>tr.active>td,.table>thead>tr.active>th,.table>tbody>tr.active>th,.table>tfoot>tr.active>th{background-color:#f5f5f5}.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover,.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th{background-color:#e8e8e8}.table>thead>tr>td.success,.table>tbody>tr>td.success,.table>tfoot>tr>td.success,.table>thead>tr>th.success,.table>tbody>tr>th.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>tbody>tr.success>td,.table>tfoot>tr.success>td,.table>thead>tr.success>th,.table>tbody>tr.success>th,.table>tfoot>tr.success>th{background-color:#dff0d8}.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover,.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th{background-color:#d0e9c6}.table>thead>tr>td.info,.table>tbody>tr>td.info,.table>tfoot>tr>td.info,.table>thead>tr>th.info,.table>tbody>tr>th.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>tbody>tr.info>td,.table>tfoot>tr.info>td,.table>thead>tr.info>th,.table>tbody>tr.info>th,.table>tfoot>tr.info>th{background-color:#d9edf7}.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover,.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th{background-color:#c4e3f3}.table>thead>tr>td.warning,.table>tbody>tr>td.warning,.table>tfoot>tr>td.warning,.table>thead>tr>th.warning,.table>tbody>tr>th.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>tbody>tr.warning>td,.table>tfoot>tr.warning>td,.table>thead>tr.warning>th,.table>tbody>tr.warning>th,.table>tfoot>tr.warning>th{background-color:#fcf8e3}.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover,.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th{background-color:#faf2cc}.table>thead>tr>td.danger,.table>tbody>tr>td.danger,.table>tfoot>tr>td.danger,.table>thead>tr>th.danger,.table>tbody>tr>th.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>tbody>tr.danger>td,.table>tfoot>tr.danger>td,.table>thead>tr.danger>th,.table>tbody>tr.danger>th,.table>tfoot>tr.danger>th{background-color:#f2dede}.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover,.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th{background-color:#ebcccc}@media (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;overflow-x:scroll;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd;-webkit-overflow-scrolling:touch}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>thead>tr>th,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tfoot>tr>td{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>thead>tr>th:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.table-responsive>.table-bordered>thead>tr>th:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>th,.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}}fieldset{padding:0;margin:0;border:0;min-width:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;margin-bottom:5px;font-weight:bold}input[type="search"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;line-height:normal}input[type="file"]{display:block}input[type="range"]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{cursor:not-allowed;background-color:#eee;opacity:1}textarea.form-control{height:auto}input[type="search"]{-webkit-appearance:none}input[type="date"]{line-height:34px}.form-group{margin-bottom:15px}.radio,.checkbox{display:block;min-height:20px;margin-top:10px;margin-bottom:10px;padding-left:20px}.radio label,.checkbox label{display:inline;font-weight:normal;cursor:pointer}.radio input[type="radio"],.radio-inline input[type="radio"],.checkbox input[type="checkbox"],.checkbox-inline input[type="checkbox"]{float:left;margin-left:-20px}.radio+.radio,.checkbox+.checkbox{margin-top:-5px}.radio-inline,.checkbox-inline{display:inline-block;padding-left:20px;margin-bottom:0;vertical-align:middle;font-weight:normal;cursor:pointer}.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px}input[type="radio"][disabled],input[type="checkbox"][disabled],.radio[disabled],.radio-inline[disabled],.checkbox[disabled],.checkbox-inline[disabled],fieldset[disabled] input[type="radio"],fieldset[disabled] input[type="checkbox"],fieldset[disabled] .radio,fieldset[disabled] .radio-inline,fieldset[disabled] .checkbox,fieldset[disabled] .checkbox-inline{cursor:not-allowed}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}textarea.input-sm,select[multiple].input-sm{height:auto}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-lg{height:46px;line-height:46px}textarea.input-lg,select[multiple].input-lg{height:auto}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.has-feedback .form-control-feedback{position:absolute;top:25px;right:0;display:block;width:34px;height:34px;line-height:34px;text-align:center}.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;border-color:#3c763d;background-color:#dff0d8}.has-success .form-control-feedback{color:#3c763d}.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;border-color:#8a6d3b;background-color:#fcf8e3}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-inline,.has-error .checkbox-inline{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;border-color:#a94442;background-color:#f2dede}.has-error .form-control-feedback{color:#a94442}.form-control-static{margin-bottom:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .radio,.form-inline .checkbox{display:inline-block;margin-top:0;margin-bottom:0;padding-left:0;vertical-align:middle}.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{float:none;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .control-label,.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{margin-top:0;margin-bottom:0;padding-top:7px}.form-horizontal .radio,.form-horizontal .checkbox{min-height:27px}.form-horizontal .form-group{margin-left:-15px;margin-right:-15px}.form-horizontal .form-control-static{padding-top:7px}@media (min-width:768px){.form-horizontal .control-label{text-align:right}}.form-horizontal .has-feedback .form-control-feedback{top:0;right:15px}.btn{display:inline-block;margin-bottom:0;font-weight:normal;text-align:center;vertical-align:middle;cursor:pointer;background-image:none;border:1px solid transparent;white-space:nowrap;padding:6px 12px;font-size:14px;line-height:1.42857143;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.btn:focus,.btn:active:focus,.btn.active:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:hover,.btn:focus{color:#333;text-decoration:none}.btn:active,.btn.active{outline:0;background-image:none;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;pointer-events:none;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default:hover,.btn-default:focus,.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{color:#333;background-color:#ebebeb;border-color:#adadad}.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{background-image:none}.btn-default.disabled,.btn-default[disabled],fieldset[disabled] .btn-default,.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled:active,.btn-default[disabled]:active,fieldset[disabled] .btn-default:active,.btn-default.disabled.active,.btn-default[disabled].active,fieldset[disabled] .btn-default.active{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#428bca;border-color:#357ebd}.btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{color:#fff;background-color:#3276b1;border-color:#285e8e}.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled,.btn-primary[disabled],fieldset[disabled] .btn-primary,.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled:active,.btn-primary[disabled]:active,fieldset[disabled] .btn-primary:active,.btn-primary.disabled.active,.btn-primary[disabled].active,fieldset[disabled] .btn-primary.active{background-color:#428bca;border-color:#357ebd}.btn-primary .badge{color:#428bca;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success:hover,.btn-success:focus,.btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success{color:#fff;background-color:#47a447;border-color:#398439}.btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success{background-image:none}.btn-success.disabled,.btn-success[disabled],fieldset[disabled] .btn-success,.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled:active,.btn-success[disabled]:active,fieldset[disabled] .btn-success:active,.btn-success.disabled.active,.btn-success[disabled].active,fieldset[disabled] .btn-success.active{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info:hover,.btn-info:focus,.btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info{color:#fff;background-color:#39b3d7;border-color:#269abc}.btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info{background-image:none}.btn-info.disabled,.btn-info[disabled],fieldset[disabled] .btn-info,.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled:active,.btn-info[disabled]:active,fieldset[disabled] .btn-info:active,.btn-info.disabled.active,.btn-info[disabled].active,fieldset[disabled] .btn-info.active{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning:hover,.btn-warning:focus,.btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning{color:#fff;background-color:#ed9c28;border-color:#d58512}.btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-warning,.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled:active,.btn-warning[disabled]:active,fieldset[disabled] .btn-warning:active,.btn-warning.disabled.active,.btn-warning[disabled].active,fieldset[disabled] .btn-warning.active{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger:hover,.btn-danger:focus,.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{color:#fff;background-color:#d2322d;border-color:#ac2925}.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled,.btn-danger[disabled],fieldset[disabled] .btn-danger,.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled:active,.btn-danger[disabled]:active,fieldset[disabled] .btn-danger:active,.btn-danger.disabled.active,.btn-danger[disabled].active,fieldset[disabled] .btn-danger.active{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{color:#428bca;font-weight:normal;cursor:pointer;border-radius:0}.btn-link,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent}.btn-link:hover,.btn-link:focus{color:#2a6496;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#999;text-decoration:none}.btn-lg,.btn-group-lg>.btn{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.btn-sm,.btn-group-sm>.btn{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-xs,.btn-group-xs>.btn{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%;padding-left:0;padding-right:0}.btn-block+.btn-block{margin-top:5px}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}@font-face{font-family:'Glyphicons Halflings';src:url('../fonts/glyphicons-halflings-regular.eot');src:url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'),url('../fonts/glyphicons-halflings-regular.woff') format('woff'),url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'),url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:normal;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\2a"}.glyphicon-plus:before{content:"\2b"}.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;float:left}.btn-group>.btn:hover,.btn-group-vertical>.btn:hover,.btn-group>.btn:focus,.btn-group-vertical>.btn:focus,.btn-group>.btn:active,.btn-group-vertical>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn.active{z-index:2}.btn-group>.btn:focus,.btn-group-vertical>.btn:focus{outline:none}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child>.btn:last-child,.btn-group>.btn-group:first-child>.dropdown-toggle{border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn-group:last-child>.btn:first-child{border-bottom-left-radius:0;border-top-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-left:8px;padding-right:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-left:12px;padding-right:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-bottom-left-radius:4px;border-top-right-radius:0;border-top-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-right-radius:0;border-top-left-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{float:none;display:table-cell;width:1%}.btn-group-justified>.btn-group .btn{width:100%}[data-toggle="buttons"]>.btn>input[type="radio"],[data-toggle="buttons"]>.btn>input[type="checkbox"]{display:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*="col-"]{float:none;padding-left:0;padding-right:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn,select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn,select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn{height:auto}.input-group-addon,.input-group-btn,.input-group .form-control{display:table-cell}.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child),.input-group .form-control:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:normal;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type="radio"],.input-group-addon input[type="checkbox"]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group-btn:last-child>.btn-group:not(:last-child)>.btn{border-bottom-right-radius:0;border-top-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:first-child>.btn-group:not(:first-child)>.btn{border-bottom-left-radius:0;border-top-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:hover,.input-group-btn>.btn:focus,.input-group-btn>.btn:active{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{margin-left:-1px}.nav{margin-bottom:0;padding-left:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#999}.nav>li.disabled>a:hover,.nav>li.disabled>a:focus{color:#999;text-decoration:none;background-color:transparent;cursor:not-allowed}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{background-color:#eee;border-color:#428bca}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{color:#555;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent;cursor:default}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:hover,.nav-pills>li.active>a:focus{color:#fff;background-color:#428bca}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-right-radius:0;border-top-left-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{max-height:340px;overflow-x:visible;padding-right:15px;padding-left:15px;border-top:1px solid transparent;box-shadow:inset 0 1px 0 rgba(255,255,255,0.1);-webkit-overflow-scrolling:touch}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;box-shadow:none}.navbar-collapse.collapse{display:block !important;height:auto !important;padding-bottom:0;overflow:visible !important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{padding-left:0;padding-right:0}}.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;padding:15px 15px;font-size:18px;line-height:20px;height:50px}.navbar-brand:hover,.navbar-brand:focus{text-decoration:none}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;margin-right:15px;padding:9px 10px;margin-top:8px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:none}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;box-shadow:none}.navbar-nav .open .dropdown-menu>li>a,.navbar-nav .open .dropdown-menu .dropdown-header{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:hover,.navbar-nav .open .dropdown-menu>li>a:focus{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}.navbar-nav.navbar-right:last-child{margin-right:-15px}}@media (min-width:768px){.navbar-left{float:left !important}.navbar-right{float:right !important}}.navbar-form{margin-left:-15px;margin-right:-15px;padding:10px 15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);margin-top:8px;margin-bottom:8px}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .radio,.navbar-form .checkbox{display:inline-block;margin-top:0;margin-bottom:0;padding-left:0;vertical-align:middle}.navbar-form .radio input[type="radio"],.navbar-form .checkbox input[type="checkbox"]{float:none;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}}@media (min-width:768px){.navbar-form{width:auto;border:0;margin-left:0;margin-right:0;padding-top:0;padding-bottom:0;-webkit-box-shadow:none;box-shadow:none}.navbar-form.navbar-right:last-child{margin-right:-15px}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-right-radius:0;border-top-left-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-left:15px;margin-right:15px}.navbar-text.navbar-right:last-child{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:hover,.navbar-default .navbar-brand:focus{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:hover,.navbar-default .navbar-nav>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:hover,.navbar-default .navbar-nav>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:hover,.navbar-default .navbar-nav>.disabled>a:focus{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:hover,.navbar-default .navbar-toggle:focus{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:hover,.navbar-default .navbar-nav>.open>a:focus{background-color:#e7e7e7;color:#555}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#999}.navbar-inverse .navbar-brand:hover,.navbar-inverse .navbar-brand:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#999}.navbar-inverse .navbar-nav>li>a{color:#999}.navbar-inverse .navbar-nav>li>a:hover,.navbar-inverse .navbar-nav>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:hover,.navbar-inverse .navbar-nav>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:hover,.navbar-inverse .navbar-nav>.disabled>a:focus{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:hover,.navbar-inverse .navbar-toggle:focus{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:hover,.navbar-inverse .navbar-nav>.open>a:focus{background-color:#080808;color:#fff}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#999}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#999}.navbar-inverse .navbar-link:hover{color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:bold;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}.label[href]:hover,.label[href]:focus{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#999}.label-default[href]:hover,.label-default[href]:focus{background-color:#808080}.label-primary{background-color:#428bca}.label-primary[href]:hover,.label-primary[href]:focus{background-color:#3071a9}.label-success{background-color:#5cb85c}.label-success[href]:hover,.label-success[href]:focus{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:hover,.label-info[href]:focus{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:hover,.label-warning[href]:focus{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:hover,.label-danger[href]:focus{background-color:#c9302c}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:bold}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable{padding-right:35px}.alert-dismissable .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{background-color:#dff0d8;border-color:#d6e9c6;color:#3c763d}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{background-color:#d9edf7;border-color:#bce8f1;color:#31708f}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{background-color:#fcf8e3;border-color:#faebcc;color:#8a6d3b}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{background-color:#f2dede;border-color:#ebccd1;color:#a94442}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{overflow:hidden;height:20px;margin-bottom:20px;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1)}.progress-bar{float:left;width:0%;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#428bca;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-transition:width .6s ease;transition:width .6s ease}.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-size:40px 40px}.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.list-group{margin-bottom:20px;padding-left:0}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-right-radius:4px;border-top-left-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}a.list-group-item{color:#555}a.list-group-item .list-group-item-heading{color:#333}a.list-group-item:hover,a.list-group-item:focus{text-decoration:none;background-color:#f5f5f5}a.list-group-item.active,a.list-group-item.active:hover,a.list-group-item.active:focus{z-index:2;color:#fff;background-color:#428bca;border-color:#428bca}a.list-group-item.active .list-group-item-heading,a.list-group-item.active:hover .list-group-item-heading,a.list-group-item.active:focus .list-group-item-heading{color:inherit}a.list-group-item.active .list-group-item-text,a.list-group-item.active:hover .list-group-item-text,a.list-group-item.active:focus .list-group-item-text{color:#e1edf7}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:hover,a.list-group-item-success:focus{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:hover,a.list-group-item-success.active:focus{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:hover,a.list-group-item-info:focus{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:hover,a.list-group-item-info.active:focus{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:hover,a.list-group-item-warning:focus{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:hover,a.list-group-item-warning.active:focus{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:hover,a.list-group-item-danger:focus{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:hover,a.list-group-item-danger.active:focus{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,0.05);box-shadow:0 1px 1px rgba(0,0,0,0.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-right-radius:3px;border-top-left-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group{margin-bottom:0}.panel>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-right-radius:3px;border-top-left-radius:3px}.panel>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.table:first-child,.panel>.table-responsive:first-child>.table:first-child{border-top-right-radius:3px;border-top-left-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table:last-child,.panel>.table-responsive:last-child>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child th,.panel>.table>tbody:first-child>tr:first-child td{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{border:0;margin-bottom:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px;overflow:hidden}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse .panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse .panel-body{border-top-color:#ddd}.panel-default>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#428bca}.panel-primary>.panel-heading{color:#fff;background-color:#428bca;border-color:#428bca}.panel-primary>.panel-heading+.panel-collapse .panel-body{border-top-color:#428bca}.panel-primary>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#428bca}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse .panel-body{border-top-color:#d6e9c6}.panel-success>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse .panel-body{border-top-color:#bce8f1}.panel-info>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse .panel-body{border-top-color:#faebcc}.panel-warning>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse .panel-body{border-top-color:#ebccd1}.panel-danger>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#ebccd1}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);box-shadow:inset 0 1px 1px rgba(0,0,0,0.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,0.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:bold;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:hover,.close:focus{color:#000;text-decoration:none;cursor:pointer;opacity:.5;filter:alpha(opacity=50)}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.clearfix:before,.clearfix:after,.container:before,.container:after,.container-fluid:before,.container-fluid:after,.row:before,.row:after,.form-horizontal .form-group:before,.form-horizontal .form-group:after,.btn-toolbar:before,.btn-toolbar:after,.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after,.nav:before,.nav:after,.navbar:before,.navbar:after,.navbar-header:before,.navbar-header:after,.navbar-collapse:before,.navbar-collapse:after,.panel-body:before,.panel-body:after{content:" ";display:table}.clearfix:after,.container:after,.container-fluid:after,.row:after,.form-horizontal .form-group:after,.btn-toolbar:after,.btn-group-vertical>.btn-group:after,.nav:after,.navbar:after,.navbar-header:after,.navbar-collapse:after,.panel-body:after{clear:both}.center-block{display:block;margin-left:auto;margin-right:auto}.pull-right{float:right !important}.pull-left{float:left !important}.hide{display:none !important}.show{display:block !important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none !important;visibility:hidden !important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-xs,.visible-sm,.visible-md,.visible-lg{display:none !important}@media (max-width:767px){.visible-xs{display:block !important}table.visible-xs{display:table}tr.visible-xs{display:table-row !important}th.visible-xs,td.visible-xs{display:table-cell !important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block !important}table.visible-sm{display:table}tr.visible-sm{display:table-row !important}th.visible-sm,td.visible-sm{display:table-cell !important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block !important}table.visible-md{display:table}tr.visible-md{display:table-row !important}th.visible-md,td.visible-md{display:table-cell !important}}@media (min-width:1200px){.visible-lg{display:block !important}table.visible-lg{display:table}tr.visible-lg{display:table-row !important}th.visible-lg,td.visible-lg{display:table-cell !important}}@media (max-width:767px){.hidden-xs{display:none !important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none !important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none !important}}@media (min-width:1200px){.hidden-lg{display:none !important}}.visible-print{display:none !important}@media print{.visible-print{display:block !important}table.visible-print{display:table}tr.visible-print{display:table-row !important}th.visible-print,td.visible-print{display:table-cell !important}}@media print{.hidden-print{display:none !important}} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/tools/runner/fonts/glyphicons-halflings-regular.eot b/tests/wpt/web-platform-tests/tools/runner/fonts/glyphicons-halflings-regular.eot
new file mode 100644
index 00000000000..4a4ca865d67
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/runner/fonts/glyphicons-halflings-regular.eot
Binary files differ
diff --git a/tests/wpt/web-platform-tests/tools/runner/fonts/glyphicons-halflings-regular.svg b/tests/wpt/web-platform-tests/tools/runner/fonts/glyphicons-halflings-regular.svg
new file mode 100644
index 00000000000..e3e2dc739dd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/runner/fonts/glyphicons-halflings-regular.svg
@@ -0,0 +1,229 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
+<svg xmlns="http://www.w3.org/2000/svg">
+<metadata></metadata>
+<defs>
+<font id="glyphicons_halflingsregular" horiz-adv-x="1200" >
+<font-face units-per-em="1200" ascent="960" descent="-240" />
+<missing-glyph horiz-adv-x="500" />
+<glyph />
+<glyph />
+<glyph unicode="&#xd;" />
+<glyph unicode=" " />
+<glyph unicode="*" d="M100 500v200h259l-183 183l141 141l183 -183v259h200v-259l183 183l141 -141l-183 -183h259v-200h-259l183 -183l-141 -141l-183 183v-259h-200v259l-183 -183l-141 141l183 183h-259z" />
+<glyph unicode="+" d="M0 400v300h400v400h300v-400h400v-300h-400v-400h-300v400h-400z" />
+<glyph unicode="&#xa0;" />
+<glyph unicode="&#x2000;" horiz-adv-x="652" />
+<glyph unicode="&#x2001;" horiz-adv-x="1304" />
+<glyph unicode="&#x2002;" horiz-adv-x="652" />
+<glyph unicode="&#x2003;" horiz-adv-x="1304" />
+<glyph unicode="&#x2004;" horiz-adv-x="434" />
+<glyph unicode="&#x2005;" horiz-adv-x="326" />
+<glyph unicode="&#x2006;" horiz-adv-x="217" />
+<glyph unicode="&#x2007;" horiz-adv-x="217" />
+<glyph unicode="&#x2008;" horiz-adv-x="163" />
+<glyph unicode="&#x2009;" horiz-adv-x="260" />
+<glyph unicode="&#x200a;" horiz-adv-x="72" />
+<glyph unicode="&#x202f;" horiz-adv-x="260" />
+<glyph unicode="&#x205f;" horiz-adv-x="326" />
+<glyph unicode="&#x20ac;" d="M100 500l100 100h113q0 47 5 100h-218l100 100h135q37 167 112 257q117 141 297 141q242 0 354 -189q60 -103 66 -209h-181q0 55 -25.5 99t-63.5 68t-75 36.5t-67 12.5q-24 0 -52.5 -10t-62.5 -32t-65.5 -67t-50.5 -107h379l-100 -100h-300q-6 -46 -6 -100h406l-100 -100 h-300q9 -74 33 -132t52.5 -91t62 -54.5t59 -29t46.5 -7.5q29 0 66 13t75 37t63.5 67.5t25.5 96.5h174q-31 -172 -128 -278q-107 -117 -274 -117q-205 0 -324 158q-36 46 -69 131.5t-45 205.5h-217z" />
+<glyph unicode="&#x2212;" d="M200 400h900v300h-900v-300z" />
+<glyph unicode="&#x25fc;" horiz-adv-x="500" d="M0 0z" />
+<glyph unicode="&#x2601;" d="M-14 494q0 -80 56.5 -137t135.5 -57h750q120 0 205 86.5t85 207.5t-85 207t-205 86q-46 0 -90 -14q-44 97 -134.5 156.5t-200.5 59.5q-152 0 -260 -107.5t-108 -260.5q0 -25 2 -37q-66 -14 -108.5 -67.5t-42.5 -122.5z" />
+<glyph unicode="&#x2709;" d="M0 100l400 400l200 -200l200 200l400 -400h-1200zM0 300v600l300 -300zM0 1100l600 -603l600 603h-1200zM900 600l300 300v-600z" />
+<glyph unicode="&#x270f;" d="M-13 -13l333 112l-223 223zM187 403l214 -214l614 614l-214 214zM887 1103l214 -214l99 92q13 13 13 32.5t-13 33.5l-153 153q-15 13 -33 13t-33 -13z" />
+<glyph unicode="&#xe001;" d="M0 1200h1200l-500 -550v-550h300v-100h-800v100h300v550z" />
+<glyph unicode="&#xe002;" d="M14 84q18 -55 86 -75.5t147 5.5q65 21 109 69t44 90v606l600 155v-521q-64 16 -138 -7q-79 -26 -122.5 -83t-25.5 -111q18 -55 86 -75.5t147 4.5q70 23 111.5 63.5t41.5 95.5v881q0 10 -7 15.5t-17 2.5l-752 -193q-10 -3 -17 -12.5t-7 -19.5v-689q-64 17 -138 -7 q-79 -25 -122.5 -82t-25.5 -112z" />
+<glyph unicode="&#xe003;" d="M23 693q0 200 142 342t342 142t342 -142t142 -342q0 -142 -78 -261l300 -300q7 -8 7 -18t-7 -18l-109 -109q-8 -7 -18 -7t-18 7l-300 300q-119 -78 -261 -78q-200 0 -342 142t-142 342zM176 693q0 -136 97 -233t234 -97t233.5 96.5t96.5 233.5t-96.5 233.5t-233.5 96.5 t-234 -97t-97 -233z" />
+<glyph unicode="&#xe005;" d="M100 784q0 64 28 123t73 100.5t104.5 64t119 20.5t120 -38.5t104.5 -104.5q48 69 109.5 105t121.5 38t118.5 -20.5t102.5 -64t71 -100.5t27 -123q0 -57 -33.5 -117.5t-94 -124.5t-126.5 -127.5t-150 -152.5t-146 -174q-62 85 -145.5 174t-149.5 152.5t-126.5 127.5 t-94 124.5t-33.5 117.5z" />
+<glyph unicode="&#xe006;" d="M-72 800h479l146 400h2l146 -400h472l-382 -278l145 -449l-384 275l-382 -275l146 447zM168 71l2 1z" />
+<glyph unicode="&#xe007;" d="M-72 800h479l146 400h2l146 -400h472l-382 -278l145 -449l-384 275l-382 -275l146 447zM168 71l2 1zM237 700l196 -142l-73 -226l192 140l195 -141l-74 229l193 140h-235l-77 211l-78 -211h-239z" />
+<glyph unicode="&#xe008;" d="M0 0v143l400 257v100q-37 0 -68.5 74.5t-31.5 125.5v200q0 124 88 212t212 88t212 -88t88 -212v-200q0 -51 -31.5 -125.5t-68.5 -74.5v-100l400 -257v-143h-1200z" />
+<glyph unicode="&#xe009;" d="M0 0v1100h1200v-1100h-1200zM100 100h100v100h-100v-100zM100 300h100v100h-100v-100zM100 500h100v100h-100v-100zM100 700h100v100h-100v-100zM100 900h100v100h-100v-100zM300 100h600v400h-600v-400zM300 600h600v400h-600v-400zM1000 100h100v100h-100v-100z M1000 300h100v100h-100v-100zM1000 500h100v100h-100v-100zM1000 700h100v100h-100v-100zM1000 900h100v100h-100v-100z" />
+<glyph unicode="&#xe010;" d="M0 50v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5zM0 650v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400 q-21 0 -35.5 14.5t-14.5 35.5zM600 50v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5zM600 650v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-400 q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5z" />
+<glyph unicode="&#xe011;" d="M0 50v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM0 450v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200 q-21 0 -35.5 14.5t-14.5 35.5zM0 850v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM400 50v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5 t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM400 450v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM400 850v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5 v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM800 50v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM800 450v200q0 21 14.5 35.5t35.5 14.5h200 q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM800 850v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5z" />
+<glyph unicode="&#xe012;" d="M0 50v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM0 450q0 -21 14.5 -35.5t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5v200q0 21 -14.5 35.5t-35.5 14.5h-200q-21 0 -35.5 -14.5 t-14.5 -35.5v-200zM0 850v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM400 50v200q0 21 14.5 35.5t35.5 14.5h700q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5 t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5zM400 450v200q0 21 14.5 35.5t35.5 14.5h700q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5zM400 850v200q0 21 14.5 35.5t35.5 14.5h700q21 0 35.5 -14.5t14.5 -35.5 v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5z" />
+<glyph unicode="&#xe013;" d="M29 454l419 -420l818 820l-212 212l-607 -607l-206 207z" />
+<glyph unicode="&#xe014;" d="M106 318l282 282l-282 282l212 212l282 -282l282 282l212 -212l-282 -282l282 -282l-212 -212l-282 282l-282 -282z" />
+<glyph unicode="&#xe015;" d="M23 693q0 200 142 342t342 142t342 -142t142 -342q0 -142 -78 -261l300 -300q7 -8 7 -18t-7 -18l-109 -109q-8 -7 -18 -7t-18 7l-300 300q-119 -78 -261 -78q-200 0 -342 142t-142 342zM176 693q0 -136 97 -233t234 -97t233.5 96.5t96.5 233.5t-96.5 233.5t-233.5 96.5 t-234 -97t-97 -233zM300 600v200h100v100h200v-100h100v-200h-100v-100h-200v100h-100z" />
+<glyph unicode="&#xe016;" d="M23 694q0 200 142 342t342 142t342 -142t142 -342q0 -141 -78 -262l300 -299q7 -7 7 -18t-7 -18l-109 -109q-8 -8 -18 -8t-18 8l-300 300q-119 -78 -261 -78q-200 0 -342 142t-142 342zM176 694q0 -136 97 -233t234 -97t233.5 97t96.5 233t-96.5 233t-233.5 97t-234 -97 t-97 -233zM300 601h400v200h-400v-200z" />
+<glyph unicode="&#xe017;" d="M23 600q0 183 105 331t272 210v-166q-103 -55 -165 -155t-62 -220q0 -177 125 -302t302 -125t302 125t125 302q0 120 -62 220t-165 155v166q167 -62 272 -210t105 -331q0 -118 -45.5 -224.5t-123 -184t-184 -123t-224.5 -45.5t-224.5 45.5t-184 123t-123 184t-45.5 224.5 zM500 750q0 -21 14.5 -35.5t35.5 -14.5h100q21 0 35.5 14.5t14.5 35.5v400q0 21 -14.5 35.5t-35.5 14.5h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-400z" />
+<glyph unicode="&#xe018;" d="M100 1h200v300h-200v-300zM400 1v500h200v-500h-200zM700 1v800h200v-800h-200zM1000 1v1200h200v-1200h-200z" />
+<glyph unicode="&#xe019;" d="M26 601q0 -33 6 -74l151 -38l2 -6q14 -49 38 -93l3 -5l-80 -134q45 -59 105 -105l133 81l5 -3q45 -26 94 -39l5 -2l38 -151q40 -5 74 -5q27 0 74 5l38 151l6 2q46 13 93 39l5 3l134 -81q56 44 104 105l-80 134l3 5q24 44 39 93l1 6l152 38q5 40 5 74q0 28 -5 73l-152 38 l-1 6q-16 51 -39 93l-3 5l80 134q-44 58 -104 105l-134 -81l-5 3q-45 25 -93 39l-6 1l-38 152q-40 5 -74 5q-27 0 -74 -5l-38 -152l-5 -1q-50 -14 -94 -39l-5 -3l-133 81q-59 -47 -105 -105l80 -134l-3 -5q-25 -47 -38 -93l-2 -6l-151 -38q-6 -48 -6 -73zM385 601 q0 88 63 151t152 63t152 -63t63 -151q0 -89 -63 -152t-152 -63t-152 63t-63 152z" />
+<glyph unicode="&#xe020;" d="M100 1025v50q0 10 7.5 17.5t17.5 7.5h275v100q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5v-100h275q10 0 17.5 -7.5t7.5 -17.5v-50q0 -11 -7 -18t-18 -7h-1050q-11 0 -18 7t-7 18zM200 100v800h900v-800q0 -41 -29.5 -71t-70.5 -30h-700q-41 0 -70.5 30 t-29.5 71zM300 100h100v700h-100v-700zM500 100h100v700h-100v-700zM500 1100h300v100h-300v-100zM700 100h100v700h-100v-700zM900 100h100v700h-100v-700z" />
+<glyph unicode="&#xe021;" d="M1 601l656 644l644 -644h-200v-600h-300v400h-300v-400h-300v600h-200z" />
+<glyph unicode="&#xe022;" d="M100 25v1150q0 11 7 18t18 7h475v-500h400v-675q0 -11 -7 -18t-18 -7h-850q-11 0 -18 7t-7 18zM700 800v300l300 -300h-300z" />
+<glyph unicode="&#xe023;" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM500 500v400h100 v-300h200v-100h-300z" />
+<glyph unicode="&#xe024;" d="M-100 0l431 1200h209l-21 -300h162l-20 300h208l431 -1200h-538l-41 400h-242l-40 -400h-539zM488 500h224l-27 300h-170z" />
+<glyph unicode="&#xe025;" d="M0 0v400h490l-290 300h200v500h300v-500h200l-290 -300h490v-400h-1100zM813 200h175v100h-175v-100z" />
+<glyph unicode="&#xe026;" d="M1 600q0 122 47.5 233t127.5 191t191 127.5t233 47.5t233 -47.5t191 -127.5t127.5 -191t47.5 -233t-47.5 -233t-127.5 -191t-191 -127.5t-233 -47.5t-233 47.5t-191 127.5t-127.5 191t-47.5 233zM188 600q0 -170 121 -291t291 -121t291 121t121 291t-121 291t-291 121 t-291 -121t-121 -291zM350 600h150v300h200v-300h150l-250 -300z" />
+<glyph unicode="&#xe027;" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM350 600l250 300 l250 -300h-150v-300h-200v300h-150z" />
+<glyph unicode="&#xe028;" d="M0 25v475l200 700h800l199 -700l1 -475q0 -11 -7 -18t-18 -7h-1150q-11 0 -18 7t-7 18zM200 500h200l50 -200h300l50 200h200l-97 500h-606z" />
+<glyph unicode="&#xe029;" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -172 121.5 -293t292.5 -121t292.5 121t121.5 293q0 171 -121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM500 397v401 l297 -200z" />
+<glyph unicode="&#xe030;" d="M23 600q0 -118 45.5 -224.5t123 -184t184 -123t224.5 -45.5t224.5 45.5t184 123t123 184t45.5 224.5h-150q0 -177 -125 -302t-302 -125t-302 125t-125 302t125 302t302 125q136 0 246 -81l-146 -146h400v400l-145 -145q-157 122 -355 122q-118 0 -224.5 -45.5t-184 -123 t-123 -184t-45.5 -224.5z" />
+<glyph unicode="&#xe031;" d="M23 600q0 118 45.5 224.5t123 184t184 123t224.5 45.5q198 0 355 -122l145 145v-400h-400l147 147q-112 80 -247 80q-177 0 -302 -125t-125 -302h-150zM100 0v400h400l-147 -147q112 -80 247 -80q177 0 302 125t125 302h150q0 -118 -45.5 -224.5t-123 -184t-184 -123 t-224.5 -45.5q-198 0 -355 122z" />
+<glyph unicode="&#xe032;" d="M100 0h1100v1200h-1100v-1200zM200 100v900h900v-900h-900zM300 200v100h100v-100h-100zM300 400v100h100v-100h-100zM300 600v100h100v-100h-100zM300 800v100h100v-100h-100zM500 200h500v100h-500v-100zM500 400v100h500v-100h-500zM500 600v100h500v-100h-500z M500 800v100h500v-100h-500z" />
+<glyph unicode="&#xe033;" d="M0 100v600q0 41 29.5 70.5t70.5 29.5h100v200q0 82 59 141t141 59h300q82 0 141 -59t59 -141v-200h100q41 0 70.5 -29.5t29.5 -70.5v-600q0 -41 -29.5 -70.5t-70.5 -29.5h-900q-41 0 -70.5 29.5t-29.5 70.5zM400 800h300v150q0 21 -14.5 35.5t-35.5 14.5h-200 q-21 0 -35.5 -14.5t-14.5 -35.5v-150z" />
+<glyph unicode="&#xe034;" d="M100 0v1100h100v-1100h-100zM300 400q60 60 127.5 84t127.5 17.5t122 -23t119 -30t110 -11t103 42t91 120.5v500q-40 -81 -101.5 -115.5t-127.5 -29.5t-138 25t-139.5 40t-125.5 25t-103 -29.5t-65 -115.5v-500z" />
+<glyph unicode="&#xe035;" d="M0 275q0 -11 7 -18t18 -7h50q11 0 18 7t7 18v300q0 127 70.5 231.5t184.5 161.5t245 57t245 -57t184.5 -161.5t70.5 -231.5v-300q0 -11 7 -18t18 -7h50q11 0 18 7t7 18v300q0 116 -49.5 227t-131 192.5t-192.5 131t-227 49.5t-227 -49.5t-192.5 -131t-131 -192.5 t-49.5 -227v-300zM200 20v460q0 8 6 14t14 6h160q8 0 14 -6t6 -14v-460q0 -8 -6 -14t-14 -6h-160q-8 0 -14 6t-6 14zM800 20v460q0 8 6 14t14 6h160q8 0 14 -6t6 -14v-460q0 -8 -6 -14t-14 -6h-160q-8 0 -14 6t-6 14z" />
+<glyph unicode="&#xe036;" d="M0 400h300l300 -200v800l-300 -200h-300v-400zM688 459l141 141l-141 141l71 71l141 -141l141 141l71 -71l-141 -141l141 -141l-71 -71l-141 141l-141 -141z" />
+<glyph unicode="&#xe037;" d="M0 400h300l300 -200v800l-300 -200h-300v-400zM700 857l69 53q111 -135 111 -310q0 -169 -106 -302l-67 54q86 110 86 248q0 146 -93 257z" />
+<glyph unicode="&#xe038;" d="M0 401v400h300l300 200v-800l-300 200h-300zM702 858l69 53q111 -135 111 -310q0 -170 -106 -303l-67 55q86 110 86 248q0 145 -93 257zM889 951l7 -8q123 -151 123 -344q0 -189 -119 -339l-7 -8l81 -66l6 8q142 178 142 405q0 230 -144 408l-6 8z" />
+<glyph unicode="&#xe039;" d="M0 0h500v500h-200v100h-100v-100h-200v-500zM0 600h100v100h400v100h100v100h-100v300h-500v-600zM100 100v300h300v-300h-300zM100 800v300h300v-300h-300zM200 200v100h100v-100h-100zM200 900h100v100h-100v-100zM500 500v100h300v-300h200v-100h-100v-100h-200v100 h-100v100h100v200h-200zM600 0v100h100v-100h-100zM600 1000h100v-300h200v-300h300v200h-200v100h200v500h-600v-200zM800 800v300h300v-300h-300zM900 0v100h300v-100h-300zM900 900v100h100v-100h-100zM1100 200v100h100v-100h-100z" />
+<glyph unicode="&#xe040;" d="M0 200h100v1000h-100v-1000zM100 0v100h300v-100h-300zM200 200v1000h100v-1000h-100zM500 0v91h100v-91h-100zM500 200v1000h200v-1000h-200zM700 0v91h100v-91h-100zM800 200v1000h100v-1000h-100zM900 0v91h200v-91h-200zM1000 200v1000h200v-1000h-200z" />
+<glyph unicode="&#xe041;" d="M0 700l1 475q0 10 7.5 17.5t17.5 7.5h474l700 -700l-500 -500zM148 953q0 -42 29 -71q30 -30 71.5 -30t71.5 30q29 29 29 71t-29 71q-30 30 -71.5 30t-71.5 -30q-29 -29 -29 -71z" />
+<glyph unicode="&#xe042;" d="M1 700l1 475q0 11 7 18t18 7h474l700 -700l-500 -500zM148 953q0 -42 30 -71q29 -30 71 -30t71 30q30 29 30 71t-30 71q-29 30 -71 30t-71 -30q-30 -29 -30 -71zM701 1200h100l700 -700l-500 -500l-50 50l450 450z" />
+<glyph unicode="&#xe043;" d="M100 0v1025l175 175h925v-1000l-100 -100v1000h-750l-100 -100h750v-1000h-900z" />
+<glyph unicode="&#xe044;" d="M200 0l450 444l450 -443v1150q0 20 -14.5 35t-35.5 15h-800q-21 0 -35.5 -15t-14.5 -35v-1151z" />
+<glyph unicode="&#xe045;" d="M0 100v700h200l100 -200h600l100 200h200v-700h-200v200h-800v-200h-200zM253 829l40 -124h592l62 124l-94 346q-2 11 -10 18t-18 7h-450q-10 0 -18 -7t-10 -18zM281 24l38 152q2 10 11.5 17t19.5 7h500q10 0 19.5 -7t11.5 -17l38 -152q2 -10 -3.5 -17t-15.5 -7h-600 q-10 0 -15.5 7t-3.5 17z" />
+<glyph unicode="&#xe046;" d="M0 200q0 -41 29.5 -70.5t70.5 -29.5h1000q41 0 70.5 29.5t29.5 70.5v600q0 41 -29.5 70.5t-70.5 29.5h-150q-4 8 -11.5 21.5t-33 48t-53 61t-69 48t-83.5 21.5h-200q-41 0 -82 -20.5t-70 -50t-52 -59t-34 -50.5l-12 -20h-150q-41 0 -70.5 -29.5t-29.5 -70.5v-600z M356 500q0 100 72 172t172 72t172 -72t72 -172t-72 -172t-172 -72t-172 72t-72 172zM494 500q0 -44 31 -75t75 -31t75 31t31 75t-31 75t-75 31t-75 -31t-31 -75zM900 700v100h100v-100h-100z" />
+<glyph unicode="&#xe047;" d="M53 0h365v66q-41 0 -72 11t-49 38t1 71l92 234h391l82 -222q16 -45 -5.5 -88.5t-74.5 -43.5v-66h417v66q-34 1 -74 43q-18 19 -33 42t-21 37l-6 13l-385 998h-93l-399 -1006q-24 -48 -52 -75q-12 -12 -33 -25t-36 -20l-15 -7v-66zM416 521l178 457l46 -140l116 -317h-340 z" />
+<glyph unicode="&#xe048;" d="M100 0v89q41 7 70.5 32.5t29.5 65.5v827q0 28 -1 39.5t-5.5 26t-15.5 21t-29 14t-49 14.5v71l471 -1q120 0 213 -88t93 -228q0 -55 -11.5 -101.5t-28 -74t-33.5 -47.5t-28 -28l-12 -7q8 -3 21.5 -9t48 -31.5t60.5 -58t47.5 -91.5t21.5 -129q0 -84 -59 -156.5t-142 -111 t-162 -38.5h-500zM400 200h161q89 0 153 48.5t64 132.5q0 90 -62.5 154.5t-156.5 64.5h-159v-400zM400 700h139q76 0 130 61.5t54 138.5q0 82 -84 130.5t-239 48.5v-379z" />
+<glyph unicode="&#xe049;" d="M200 0v57q77 7 134.5 40.5t65.5 80.5l173 849q10 56 -10 74t-91 37q-6 1 -10.5 2.5t-9.5 2.5v57h425l2 -57q-33 -8 -62 -25.5t-46 -37t-29.5 -38t-17.5 -30.5l-5 -12l-128 -825q-10 -52 14 -82t95 -36v-57h-500z" />
+<glyph unicode="&#xe050;" d="M-75 200h75v800h-75l125 167l125 -167h-75v-800h75l-125 -167zM300 900v300h150h700h150v-300h-50q0 29 -8 48.5t-18.5 30t-33.5 15t-39.5 5.5t-50.5 1h-200v-850l100 -50v-100h-400v100l100 50v850h-200q-34 0 -50.5 -1t-40 -5.5t-33.5 -15t-18.5 -30t-8.5 -48.5h-49z " />
+<glyph unicode="&#xe051;" d="M33 51l167 125v-75h800v75l167 -125l-167 -125v75h-800v-75zM100 901v300h150h700h150v-300h-50q0 29 -8 48.5t-18 30t-33.5 15t-40 5.5t-50.5 1h-200v-650l100 -50v-100h-400v100l100 50v650h-200q-34 0 -50.5 -1t-39.5 -5.5t-33.5 -15t-18.5 -30t-8 -48.5h-50z" />
+<glyph unicode="&#xe052;" d="M0 50q0 -20 14.5 -35t35.5 -15h1100q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM0 350q0 -20 14.5 -35t35.5 -15h800q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-800q-21 0 -35.5 -14.5t-14.5 -35.5 v-100zM0 650q0 -20 14.5 -35t35.5 -15h1000q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-1000q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM0 950q0 -20 14.5 -35t35.5 -15h600q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-600q-21 0 -35.5 -14.5 t-14.5 -35.5v-100z" />
+<glyph unicode="&#xe053;" d="M0 50q0 -20 14.5 -35t35.5 -15h1100q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM0 650q0 -20 14.5 -35t35.5 -15h1100q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5 v-100zM200 350q0 -20 14.5 -35t35.5 -15h700q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-700q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM200 950q0 -20 14.5 -35t35.5 -15h700q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-700q-21 0 -35.5 -14.5 t-14.5 -35.5v-100z" />
+<glyph unicode="&#xe054;" d="M0 50v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15t-14.5 35zM100 650v100q0 21 14.5 35.5t35.5 14.5h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1000q-21 0 -35.5 15 t-14.5 35zM300 350v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800q-21 0 -35.5 15t-14.5 35zM500 950v100q0 21 14.5 35.5t35.5 14.5h600q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-600 q-21 0 -35.5 15t-14.5 35z" />
+<glyph unicode="&#xe055;" d="M0 50v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15t-14.5 35zM0 350v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15 t-14.5 35zM0 650v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15t-14.5 35zM0 950v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100 q-21 0 -35.5 15t-14.5 35z" />
+<glyph unicode="&#xe056;" d="M0 50v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15t-14.5 35zM0 350v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15 t-14.5 35zM0 650v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15t-14.5 35zM0 950v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15 t-14.5 35zM300 50v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800q-21 0 -35.5 15t-14.5 35zM300 350v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800 q-21 0 -35.5 15t-14.5 35zM300 650v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800q-21 0 -35.5 15t-14.5 35zM300 950v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15 h-800q-21 0 -35.5 15t-14.5 35z" />
+<glyph unicode="&#xe057;" d="M-101 500v100h201v75l166 -125l-166 -125v75h-201zM300 0h100v1100h-100v-1100zM500 50q0 -20 14.5 -35t35.5 -15h600q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-600q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM500 350q0 -20 14.5 -35t35.5 -15h300q20 0 35 15t15 35 v100q0 21 -15 35.5t-35 14.5h-300q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM500 650q0 -20 14.5 -35t35.5 -15h500q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-500q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM500 950q0 -20 14.5 -35t35.5 -15h100q20 0 35 15t15 35v100 q0 21 -15 35.5t-35 14.5h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-100z" />
+<glyph unicode="&#xe058;" d="M1 50q0 -20 14.5 -35t35.5 -15h600q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-600q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM1 350q0 -20 14.5 -35t35.5 -15h300q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-300q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM1 650 q0 -20 14.5 -35t35.5 -15h500q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-500q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM1 950q0 -20 14.5 -35t35.5 -15h100q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM801 0v1100h100v-1100 h-100zM934 550l167 -125v75h200v100h-200v75z" />
+<glyph unicode="&#xe059;" d="M0 275v650q0 31 22 53t53 22h750q31 0 53 -22t22 -53v-650q0 -31 -22 -53t-53 -22h-750q-31 0 -53 22t-22 53zM900 600l300 300v-600z" />
+<glyph unicode="&#xe060;" d="M0 44v1012q0 18 13 31t31 13h1112q19 0 31.5 -13t12.5 -31v-1012q0 -18 -12.5 -31t-31.5 -13h-1112q-18 0 -31 13t-13 31zM100 263l247 182l298 -131l-74 156l293 318l236 -288v500h-1000v-737zM208 750q0 56 39 95t95 39t95 -39t39 -95t-39 -95t-95 -39t-95 39t-39 95z " />
+<glyph unicode="&#xe062;" d="M148 745q0 124 60.5 231.5t165 172t226.5 64.5q123 0 227 -63t164.5 -169.5t60.5 -229.5t-73 -272q-73 -114 -166.5 -237t-150.5 -189l-57 -66q-10 9 -27 26t-66.5 70.5t-96 109t-104 135.5t-100.5 155q-63 139 -63 262zM342 772q0 -107 75.5 -182.5t181.5 -75.5 q107 0 182.5 75.5t75.5 182.5t-75.5 182t-182.5 75t-182 -75.5t-75 -181.5z" />
+<glyph unicode="&#xe063;" d="M1 600q0 122 47.5 233t127.5 191t191 127.5t233 47.5t233 -47.5t191 -127.5t127.5 -191t47.5 -233t-47.5 -233t-127.5 -191t-191 -127.5t-233 -47.5t-233 47.5t-191 127.5t-127.5 191t-47.5 233zM173 600q0 -177 125.5 -302t301.5 -125v854q-176 0 -301.5 -125 t-125.5 -302z" />
+<glyph unicode="&#xe064;" d="M117 406q0 94 34 186t88.5 172.5t112 159t115 177t87.5 194.5q21 -71 57.5 -142.5t76 -130.5t83 -118.5t82 -117t70 -116t50 -125.5t18.5 -136q0 -89 -39 -165.5t-102 -126.5t-140 -79.5t-156 -33.5q-114 6 -211.5 53t-161.5 139t-64 210zM243 414q14 -82 59.5 -136 t136.5 -80l16 98q-7 6 -18 17t-34 48t-33 77q-15 73 -14 143.5t10 122.5l9 51q-92 -110 -119.5 -185t-12.5 -156z" />
+<glyph unicode="&#xe065;" d="M0 400v300q0 165 117.5 282.5t282.5 117.5q366 -6 397 -14l-186 -186h-311q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v125l200 200v-225q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5 t-117.5 282.5zM436 341l161 50l412 412l-114 113l-405 -405zM995 1015l113 -113l113 113l-21 85l-92 28z" />
+<glyph unicode="&#xe066;" d="M0 400v300q0 165 117.5 282.5t282.5 117.5h261l2 -80q-133 -32 -218 -120h-145q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5l200 153v-53q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5t-117.5 282.5 zM423 524q30 38 81.5 64t103 35.5t99 14t77.5 3.5l29 -1v-209l360 324l-359 318v-216q-7 0 -19 -1t-48 -8t-69.5 -18.5t-76.5 -37t-76.5 -59t-62 -88t-39.5 -121.5z" />
+<glyph unicode="&#xe067;" d="M0 400v300q0 165 117.5 282.5t282.5 117.5h300q61 0 127 -23l-178 -177h-349q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v69l200 200v-169q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5 t-117.5 282.5zM342 632l283 -284l567 567l-137 137l-430 -431l-146 147z" />
+<glyph unicode="&#xe068;" d="M0 603l300 296v-198h200v200h-200l300 300l295 -300h-195v-200h200v198l300 -296l-300 -300v198h-200v-200h195l-295 -300l-300 300h200v200h-200v-198z" />
+<glyph unicode="&#xe069;" d="M200 50v1000q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-437l500 487v-1100l-500 488v-438q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5z" />
+<glyph unicode="&#xe070;" d="M0 50v1000q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-437l500 487v-487l500 487v-1100l-500 488v-488l-500 488v-438q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5z" />
+<glyph unicode="&#xe071;" d="M136 550l564 550v-487l500 487v-1100l-500 488v-488z" />
+<glyph unicode="&#xe072;" d="M200 0l900 550l-900 550v-1100z" />
+<glyph unicode="&#xe073;" d="M200 150q0 -21 14.5 -35.5t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5v800q0 21 -14.5 35.5t-35.5 14.5h-200q-21 0 -35.5 -14.5t-14.5 -35.5v-800zM600 150q0 -21 14.5 -35.5t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5v800q0 21 -14.5 35.5t-35.5 14.5h-200 q-21 0 -35.5 -14.5t-14.5 -35.5v-800z" />
+<glyph unicode="&#xe074;" d="M200 150q0 -20 14.5 -35t35.5 -15h800q21 0 35.5 15t14.5 35v800q0 21 -14.5 35.5t-35.5 14.5h-800q-21 0 -35.5 -14.5t-14.5 -35.5v-800z" />
+<glyph unicode="&#xe075;" d="M0 0v1100l500 -487v487l564 -550l-564 -550v488z" />
+<glyph unicode="&#xe076;" d="M0 0v1100l500 -487v487l500 -487v437q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-1000q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v438l-500 -488v488z" />
+<glyph unicode="&#xe077;" d="M300 0v1100l500 -487v437q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-1000q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v438z" />
+<glyph unicode="&#xe078;" d="M100 250v100q0 21 14.5 35.5t35.5 14.5h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5zM100 500h1100l-550 564z" />
+<glyph unicode="&#xe079;" d="M185 599l592 -592l240 240l-353 353l353 353l-240 240z" />
+<glyph unicode="&#xe080;" d="M272 194l353 353l-353 353l241 240l572 -571l21 -22l-1 -1v-1l-592 -591z" />
+<glyph unicode="&#xe081;" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM300 500h200v-200h200v200h200v200h-200v200h-200v-200h-200v-200z" />
+<glyph unicode="&#xe082;" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM300 500h600v200h-600v-200z" />
+<glyph unicode="&#xe083;" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM246 459l213 -213l141 142l141 -142l213 213l-142 141l142 141l-213 212l-141 -141l-141 142l-212 -213l141 -141 z" />
+<glyph unicode="&#xe084;" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM270 551l276 -277l411 411l-175 174l-236 -236l-102 102z" />
+<glyph unicode="&#xe085;" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM364 700h143q4 0 11.5 -1t11 -1t6.5 3t3 9t1 11t3.5 8.5t3.5 6t5.5 4t6.5 2.5t9 1.5t9 0.5h11.5h12.5 q19 0 30 -10t11 -26q0 -22 -4 -28t-27 -22q-5 -1 -12.5 -3t-27 -13.5t-34 -27t-26.5 -46t-11 -68.5h200q5 3 14 8t31.5 25.5t39.5 45.5t31 69t14 94q0 51 -17.5 89t-42 58t-58.5 32t-58.5 15t-51.5 3q-50 0 -90.5 -12t-75 -38.5t-53.5 -74.5t-19 -114zM500 300h200v100h-200 v-100z" />
+<glyph unicode="&#xe086;" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM400 300h400v100h-100v300h-300v-100h100v-200h-100v-100zM500 800h200v100h-200v-100z" />
+<glyph unicode="&#xe087;" d="M0 500v200h195q31 125 98.5 199.5t206.5 100.5v200h200v-200q54 -20 113 -60t112.5 -105.5t71.5 -134.5h203v-200h-203q-25 -102 -116.5 -186t-180.5 -117v-197h-200v197q-140 27 -208 102.5t-98 200.5h-194zM290 500q24 -73 79.5 -127.5t130.5 -78.5v206h200v-206 q149 48 201 206h-201v200h200q-25 74 -75.5 127t-124.5 77v-204h-200v203q-75 -23 -130 -77t-79 -126h209v-200h-210z" />
+<glyph unicode="&#xe088;" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM356 465l135 135 l-135 135l109 109l135 -135l135 135l109 -109l-135 -135l135 -135l-109 -109l-135 135l-135 -135z" />
+<glyph unicode="&#xe089;" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM322 537l141 141 l87 -87l204 205l142 -142l-346 -345z" />
+<glyph unicode="&#xe090;" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -115 62 -215l568 567q-100 62 -216 62q-171 0 -292.5 -121.5t-121.5 -292.5zM391 245q97 -59 209 -59q171 0 292.5 121.5t121.5 292.5 q0 112 -59 209z" />
+<glyph unicode="&#xe091;" d="M0 547l600 453v-300h600v-300h-600v-301z" />
+<glyph unicode="&#xe092;" d="M0 400v300h600v300l600 -453l-600 -448v301h-600z" />
+<glyph unicode="&#xe093;" d="M204 600l450 600l444 -600h-298v-600h-300v600h-296z" />
+<glyph unicode="&#xe094;" d="M104 600h296v600h300v-600h298l-449 -600z" />
+<glyph unicode="&#xe095;" d="M0 200q6 132 41 238.5t103.5 193t184 138t271.5 59.5v271l600 -453l-600 -448v301q-95 -2 -183 -20t-170 -52t-147 -92.5t-100 -135.5z" />
+<glyph unicode="&#xe096;" d="M0 0v400l129 -129l294 294l142 -142l-294 -294l129 -129h-400zM635 777l142 -142l294 294l129 -129v400h-400l129 -129z" />
+<glyph unicode="&#xe097;" d="M34 176l295 295l-129 129h400v-400l-129 130l-295 -295zM600 600v400l129 -129l295 295l142 -141l-295 -295l129 -130h-400z" />
+<glyph unicode="&#xe101;" d="M23 600q0 118 45.5 224.5t123 184t184 123t224.5 45.5t224.5 -45.5t184 -123t123 -184t45.5 -224.5t-45.5 -224.5t-123 -184t-184 -123t-224.5 -45.5t-224.5 45.5t-184 123t-123 184t-45.5 224.5zM456 851l58 -302q4 -20 21.5 -34.5t37.5 -14.5h54q20 0 37.5 14.5 t21.5 34.5l58 302q4 20 -8 34.5t-32 14.5h-207q-21 0 -33 -14.5t-8 -34.5zM500 300h200v100h-200v-100z" />
+<glyph unicode="&#xe102;" d="M0 800h100v-200h400v300h200v-300h400v200h100v100h-111q1 1 1 6.5t-1.5 15t-3.5 17.5l-34 172q-11 39 -41.5 63t-69.5 24q-32 0 -61 -17l-239 -144q-22 -13 -40 -35q-19 24 -40 36l-238 144q-33 18 -62 18q-39 0 -69.5 -23t-40.5 -61l-35 -177q-2 -8 -3 -18t-1 -15v-6 h-111v-100zM100 0h400v400h-400v-400zM200 900q-3 0 14 48t36 96l18 47l213 -191h-281zM700 0v400h400v-400h-400zM731 900l202 197q5 -12 12 -32.5t23 -64t25 -72t7 -28.5h-269z" />
+<glyph unicode="&#xe103;" d="M0 -22v143l216 193q-9 53 -13 83t-5.5 94t9 113t38.5 114t74 124q47 60 99.5 102.5t103 68t127.5 48t145.5 37.5t184.5 43.5t220 58.5q0 -189 -22 -343t-59 -258t-89 -181.5t-108.5 -120t-122 -68t-125.5 -30t-121.5 -1.5t-107.5 12.5t-87.5 17t-56.5 7.5l-99 -55z M238.5 300.5q19.5 -6.5 86.5 76.5q55 66 367 234q70 38 118.5 69.5t102 79t99 111.5t86.5 148q22 50 24 60t-6 19q-7 5 -17 5t-26.5 -14.5t-33.5 -39.5q-35 -51 -113.5 -108.5t-139.5 -89.5l-61 -32q-369 -197 -458 -401q-48 -111 -28.5 -117.5z" />
+<glyph unicode="&#xe104;" d="M111 408q0 -33 5 -63q9 -56 44 -119.5t105 -108.5q31 -21 64 -16t62 23.5t57 49.5t48 61.5t35 60.5q32 66 39 184.5t-13 157.5q79 -80 122 -164t26 -184q-5 -33 -20.5 -69.5t-37.5 -80.5q-10 -19 -14.5 -29t-12 -26t-9 -23.5t-3 -19t2.5 -15.5t11 -9.5t19.5 -5t30.5 2.5 t42 8q57 20 91 34t87.5 44.5t87 64t65.5 88.5t47 122q38 172 -44.5 341.5t-246.5 278.5q22 -44 43 -129q39 -159 -32 -154q-15 2 -33 9q-79 33 -120.5 100t-44 175.5t48.5 257.5q-13 -8 -34 -23.5t-72.5 -66.5t-88.5 -105.5t-60 -138t-8 -166.5q2 -12 8 -41.5t8 -43t6 -39.5 t3.5 -39.5t-1 -33.5t-6 -31.5t-13.5 -24t-21 -20.5t-31 -12q-38 -10 -67 13t-40.5 61.5t-15 81.5t10.5 75q-52 -46 -83.5 -101t-39 -107t-7.5 -85z" />
+<glyph unicode="&#xe105;" d="M-61 600l26 40q6 10 20 30t49 63.5t74.5 85.5t97 90t116.5 83.5t132.5 59t145.5 23.5t145.5 -23.5t132.5 -59t116.5 -83.5t97 -90t74.5 -85.5t49 -63.5t20 -30l26 -40l-26 -40q-6 -10 -20 -30t-49 -63.5t-74.5 -85.5t-97 -90t-116.5 -83.5t-132.5 -59t-145.5 -23.5 t-145.5 23.5t-132.5 59t-116.5 83.5t-97 90t-74.5 85.5t-49 63.5t-20 30zM120 600q7 -10 40.5 -58t56 -78.5t68 -77.5t87.5 -75t103 -49.5t125 -21.5t123.5 20t100.5 45.5t85.5 71.5t66.5 75.5t58 81.5t47 66q-1 1 -28.5 37.5t-42 55t-43.5 53t-57.5 63.5t-58.5 54 q49 -74 49 -163q0 -124 -88 -212t-212 -88t-212 88t-88 212q0 85 46 158q-102 -87 -226 -258zM377 656q49 -124 154 -191l105 105q-37 24 -75 72t-57 84l-20 36z" />
+<glyph unicode="&#xe106;" d="M-61 600l26 40q6 10 20 30t49 63.5t74.5 85.5t97 90t116.5 83.5t132.5 59t145.5 23.5q61 0 121 -17l37 142h148l-314 -1200h-148l37 143q-82 21 -165 71.5t-140 102t-109.5 112t-72 88.5t-29.5 43zM120 600q210 -282 393 -336l37 141q-107 18 -178.5 101.5t-71.5 193.5 q0 85 46 158q-102 -87 -226 -258zM377 656q49 -124 154 -191l47 47l23 87q-30 28 -59 69t-44 68l-14 26zM780 161l38 145q22 15 44.5 34t46 44t40.5 44t41 50.5t33.5 43.5t33 44t24.5 34q-97 127 -140 175l39 146q67 -54 131.5 -125.5t87.5 -103.5t36 -52l26 -40l-26 -40 q-7 -12 -25.5 -38t-63.5 -79.5t-95.5 -102.5t-124 -100t-146.5 -79z" />
+<glyph unicode="&#xe107;" d="M-97.5 34q13.5 -34 50.5 -34h1294q37 0 50.5 35.5t-7.5 67.5l-642 1056q-20 34 -48 36.5t-48 -29.5l-642 -1066q-21 -32 -7.5 -66zM155 200l445 723l445 -723h-345v100h-200v-100h-345zM500 600l100 -300l100 300v100h-200v-100z" />
+<glyph unicode="&#xe108;" d="M100 262v41q0 20 11 44.5t26 38.5l363 325v339q0 62 44 106t106 44t106 -44t44 -106v-339l363 -325q15 -14 26 -38.5t11 -44.5v-41q0 -20 -12 -26.5t-29 5.5l-359 249v-263q100 -91 100 -113v-64q0 -20 -13 -28.5t-32 0.5l-94 78h-222l-94 -78q-19 -9 -32 -0.5t-13 28.5 v64q0 22 100 113v263l-359 -249q-17 -12 -29 -5.5t-12 26.5z" />
+<glyph unicode="&#xe109;" d="M0 50q0 -20 14.5 -35t35.5 -15h1000q21 0 35.5 15t14.5 35v750h-1100v-750zM0 900h1100v150q0 21 -14.5 35.5t-35.5 14.5h-150v100h-100v-100h-500v100h-100v-100h-150q-21 0 -35.5 -14.5t-14.5 -35.5v-150zM100 100v100h100v-100h-100zM100 300v100h100v-100h-100z M100 500v100h100v-100h-100zM300 100v100h100v-100h-100zM300 300v100h100v-100h-100zM300 500v100h100v-100h-100zM500 100v100h100v-100h-100zM500 300v100h100v-100h-100zM500 500v100h100v-100h-100zM700 100v100h100v-100h-100zM700 300v100h100v-100h-100zM700 500 v100h100v-100h-100zM900 100v100h100v-100h-100zM900 300v100h100v-100h-100zM900 500v100h100v-100h-100z" />
+<glyph unicode="&#xe110;" d="M0 200v200h259l600 600h241v198l300 -295l-300 -300v197h-159l-600 -600h-341zM0 800h259l122 -122l141 142l-181 180h-341v-200zM678 381l141 142l122 -123h159v198l300 -295l-300 -300v197h-241z" />
+<glyph unicode="&#xe111;" d="M0 400v600q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-600q0 -41 -29.5 -70.5t-70.5 -29.5h-596l-304 -300v300h-100q-41 0 -70.5 29.5t-29.5 70.5z" />
+<glyph unicode="&#xe112;" d="M100 600v200h300v-250q0 -113 6 -145q17 -92 102 -117q39 -11 92 -11q37 0 66.5 5.5t50 15.5t36 24t24 31.5t14 37.5t7 42t2.5 45t0 47v25v250h300v-200q0 -42 -3 -83t-15 -104t-31.5 -116t-58 -109.5t-89 -96.5t-129 -65.5t-174.5 -25.5t-174.5 25.5t-129 65.5t-89 96.5 t-58 109.5t-31.5 116t-15 104t-3 83zM100 900v300h300v-300h-300zM800 900v300h300v-300h-300z" />
+<glyph unicode="&#xe113;" d="M-30 411l227 -227l352 353l353 -353l226 227l-578 579z" />
+<glyph unicode="&#xe114;" d="M70 797l580 -579l578 579l-226 227l-353 -353l-352 353z" />
+<glyph unicode="&#xe115;" d="M-198 700l299 283l300 -283h-203v-400h385l215 -200h-800v600h-196zM402 1000l215 -200h381v-400h-198l299 -283l299 283h-200v600h-796z" />
+<glyph unicode="&#xe116;" d="M18 939q-5 24 10 42q14 19 39 19h896l38 162q5 17 18.5 27.5t30.5 10.5h94q20 0 35 -14.5t15 -35.5t-15 -35.5t-35 -14.5h-54l-201 -961q-2 -4 -6 -10.5t-19 -17.5t-33 -11h-31v-50q0 -20 -14.5 -35t-35.5 -15t-35.5 15t-14.5 35v50h-300v-50q0 -20 -14.5 -35t-35.5 -15 t-35.5 15t-14.5 35v50h-50q-21 0 -35.5 15t-14.5 35q0 21 14.5 35.5t35.5 14.5h535l48 200h-633q-32 0 -54.5 21t-27.5 43z" />
+<glyph unicode="&#xe117;" d="M0 0v800h1200v-800h-1200zM0 900v100h200q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5h500v-100h-1200z" />
+<glyph unicode="&#xe118;" d="M1 0l300 700h1200l-300 -700h-1200zM1 400v600h200q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5h500v-200h-1000z" />
+<glyph unicode="&#xe119;" d="M302 300h198v600h-198l298 300l298 -300h-198v-600h198l-298 -300z" />
+<glyph unicode="&#xe120;" d="M0 600l300 298v-198h600v198l300 -298l-300 -297v197h-600v-197z" />
+<glyph unicode="&#xe121;" d="M0 100v100q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5zM31 400l172 739q5 22 23 41.5t38 19.5h672q19 0 37.5 -22.5t23.5 -45.5l172 -732h-1138zM800 100h100v100h-100v-100z M1000 100h100v100h-100v-100z" />
+<glyph unicode="&#xe122;" d="M-101 600v50q0 24 25 49t50 38l25 13v-250l-11 5.5t-24 14t-30 21.5t-24 27.5t-11 31.5zM100 500v250v8v8v7t0.5 7t1.5 5.5t2 5t3 4t4.5 3.5t6 1.5t7.5 0.5h200l675 250v-850l-675 200h-38l47 -276q2 -12 -3 -17.5t-11 -6t-21 -0.5h-8h-83q-20 0 -34.5 14t-18.5 35 q-55 337 -55 351zM1100 200v850q0 21 14.5 35.5t35.5 14.5q20 0 35 -14.5t15 -35.5v-850q0 -20 -15 -35t-35 -15q-21 0 -35.5 15t-14.5 35z" />
+<glyph unicode="&#xe123;" d="M74 350q0 21 13.5 35.5t33.5 14.5h18l117 173l63 327q15 77 76 140t144 83l-18 32q-6 19 3 32t29 13h94q20 0 29 -10.5t3 -29.5q-18 -36 -18 -37q83 -19 144 -82.5t76 -140.5l63 -327l118 -173h17q20 0 33.5 -14.5t13.5 -35.5q0 -20 -13 -40t-31 -27q-8 -3 -23 -8.5 t-65 -20t-103 -25t-132.5 -19.5t-158.5 -9q-125 0 -245.5 20.5t-178.5 40.5l-58 20q-18 7 -31 27.5t-13 40.5zM497 110q12 -49 40 -79.5t63 -30.5t63 30.5t39 79.5q-48 -6 -102 -6t-103 6z" />
+<glyph unicode="&#xe124;" d="M21 445l233 -45l-78 -224l224 78l45 -233l155 179l155 -179l45 233l224 -78l-78 224l234 45l-180 155l180 156l-234 44l78 225l-224 -78l-45 233l-155 -180l-155 180l-45 -233l-224 78l78 -225l-233 -44l179 -156z" />
+<glyph unicode="&#xe125;" d="M0 200h200v600h-200v-600zM300 275q0 -75 100 -75h61q124 -100 139 -100h250q46 0 83 57l238 344q29 31 29 74v100q0 44 -30.5 84.5t-69.5 40.5h-328q28 118 28 125v150q0 44 -30.5 84.5t-69.5 40.5h-50q-27 0 -51 -20t-38 -48l-96 -198l-145 -196q-20 -26 -20 -63v-400z M400 300v375l150 213l100 212h50v-175l-50 -225h450v-125l-250 -375h-214l-136 100h-100z" />
+<glyph unicode="&#xe126;" d="M0 400v600h200v-600h-200zM300 525v400q0 75 100 75h61q124 100 139 100h250q46 0 83 -57l238 -344q29 -31 29 -74v-100q0 -44 -30.5 -84.5t-69.5 -40.5h-328q28 -118 28 -125v-150q0 -44 -30.5 -84.5t-69.5 -40.5h-50q-27 0 -51 20t-38 48l-96 198l-145 196 q-20 26 -20 63zM400 525l150 -212l100 -213h50v175l-50 225h450v125l-250 375h-214l-136 -100h-100v-375z" />
+<glyph unicode="&#xe127;" d="M8 200v600h200v-600h-200zM308 275v525q0 17 14 35.5t28 28.5l14 9l362 230q14 6 25 6q17 0 29 -12l109 -112q14 -14 14 -34q0 -18 -11 -32l-85 -121h302q85 0 138.5 -38t53.5 -110t-54.5 -111t-138.5 -39h-107l-130 -339q-7 -22 -20.5 -41.5t-28.5 -19.5h-341 q-7 0 -90 81t-83 94zM408 289l100 -89h293l131 339q6 21 19.5 41t28.5 20h203q16 0 25 15t9 36q0 20 -9 34.5t-25 14.5h-457h-6.5h-7.5t-6.5 0.5t-6 1t-5 1.5t-5.5 2.5t-4 4t-4 5.5q-5 12 -5 20q0 14 10 27l147 183l-86 83l-339 -236v-503z" />
+<glyph unicode="&#xe128;" d="M-101 651q0 72 54 110t139 38l302 -1l-85 121q-11 16 -11 32q0 21 14 34l109 113q13 12 29 12q11 0 25 -6l365 -230q7 -4 17 -10.5t26.5 -26t16.5 -36.5v-526q0 -13 -86 -93.5t-94 -80.5h-341q-16 0 -29.5 20t-19.5 41l-130 339h-107q-84 0 -139 39t-55 111zM-1 601h222 q15 0 28.5 -20.5t19.5 -40.5l131 -339h293l107 89v502l-343 237l-87 -83l145 -184q10 -11 10 -26q0 -11 -5 -20q-1 -3 -3.5 -5.5l-4 -4t-5 -2.5t-5.5 -1.5t-6.5 -1t-6.5 -0.5h-7.5h-6.5h-476v-100zM1000 201v600h200v-600h-200z" />
+<glyph unicode="&#xe129;" d="M97 719l230 -363q4 -6 10.5 -15.5t26 -25t36.5 -15.5h525q13 0 94 83t81 90v342q0 15 -20 28.5t-41 19.5l-339 131v106q0 84 -39 139t-111 55t-110 -53.5t-38 -138.5v-302l-121 84q-15 12 -33.5 11.5t-32.5 -13.5l-112 -110q-22 -22 -6 -53zM172 739l83 86l183 -146 q22 -18 47 -5q3 1 5.5 3.5l4 4t2.5 5t1.5 5.5t1 6.5t0.5 6.5v7.5v6.5v456q0 22 25 31t50 -0.5t25 -30.5v-202q0 -16 20 -29.5t41 -19.5l339 -130v-294l-89 -100h-503zM400 0v200h600v-200h-600z" />
+<glyph unicode="&#xe130;" d="M2 585q-16 -31 6 -53l112 -110q13 -13 32 -13.5t34 10.5l121 85q0 -51 -0.5 -153.5t-0.5 -148.5q0 -84 38.5 -138t110.5 -54t111 55t39 139v106l339 131q20 6 40.5 19.5t20.5 28.5v342q0 7 -81 90t-94 83h-525q-17 0 -35.5 -14t-28.5 -28l-10 -15zM77 565l236 339h503 l89 -100v-294l-340 -130q-20 -6 -40 -20t-20 -29v-202q0 -22 -25 -31t-50 0t-25 31v456v14.5t-1.5 11.5t-5 12t-9.5 7q-24 13 -46 -5l-184 -146zM305 1104v200h600v-200h-600z" />
+<glyph unicode="&#xe131;" d="M5 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5q162 0 299.5 -80t217.5 -218t80 -300t-80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5zM298 701l2 -201h300l-2 -194l402 294l-402 298v-197h-300z" />
+<glyph unicode="&#xe132;" d="M0 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t231.5 47.5q122 0 232.5 -47.5t190.5 -127.5t127.5 -190.5t47.5 -232.5q0 -162 -80 -299.5t-218 -217.5t-300 -80t-299.5 80t-217.5 217.5t-80 299.5zM200 600l402 -294l-2 194h300l2 201h-300v197z" />
+<glyph unicode="&#xe133;" d="M5 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5q162 0 299.5 -80t217.5 -218t80 -300t-80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5zM300 600h200v-300h200v300h200l-300 400z" />
+<glyph unicode="&#xe134;" d="M5 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5q162 0 299.5 -80t217.5 -218t80 -300t-80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5zM300 600l300 -400l300 400h-200v300h-200v-300h-200z" />
+<glyph unicode="&#xe135;" d="M5 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5q121 0 231.5 -47.5t190.5 -127.5t127.5 -190.5t47.5 -232.5q0 -162 -80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5zM254 780q-8 -33 5.5 -92.5t7.5 -87.5q0 -9 17 -44t16 -60 q12 0 23 -5.5t23 -15t20 -13.5q24 -12 108 -42q22 -8 53 -31.5t59.5 -38.5t57.5 -11q8 -18 -15 -55t-20 -57q42 -71 87 -80q0 -6 -3 -15.5t-3.5 -14.5t4.5 -17q104 -3 221 112q30 29 47 47t34.5 49t20.5 62q-14 9 -37 9.5t-36 7.5q-14 7 -49 15t-52 19q-9 0 -39.5 -0.5 t-46.5 -1.5t-39 -6.5t-39 -16.5q-50 -35 -66 -12q-4 2 -3.5 25.5t0.5 25.5q-6 13 -26.5 17t-24.5 7q2 22 -2 41t-16.5 28t-38.5 -20q-23 -25 -42 4q-19 28 -8 58q6 16 22 22q6 -1 26 -1.5t33.5 -4t19.5 -13.5q12 -19 32 -37.5t34 -27.5l14 -8q0 3 9.5 39.5t5.5 57.5 q-4 23 14.5 44.5t22.5 31.5q5 14 10 35t8.5 31t15.5 22.5t34 21.5q-6 18 10 37q8 0 23.5 -1.5t24.5 -1.5t20.5 4.5t20.5 15.5q-10 23 -30.5 42.5t-38 30t-49 26.5t-43.5 23q11 39 2 44q31 -13 58 -14.5t39 3.5l11 4q7 36 -16.5 53.5t-64.5 28.5t-56 23q-19 -3 -37 0 q-15 -12 -36.5 -21t-34.5 -12t-44 -8t-39 -6q-15 -3 -45.5 0.5t-45.5 -2.5q-21 -7 -52 -26.5t-34 -34.5q-3 -11 6.5 -22.5t8.5 -18.5q-3 -34 -27.5 -90.5t-29.5 -79.5zM518 916q3 12 16 30t16 25q10 -10 18.5 -10t14 6t14.5 14.5t16 12.5q0 -24 17 -66.5t17 -43.5 q-9 2 -31 5t-36 5t-32 8t-30 14zM692 1003h1h-1z" />
+<glyph unicode="&#xe136;" d="M0 164.5q0 21.5 15 37.5l600 599q-33 101 6 201.5t135 154.5q164 92 306 -9l-259 -138l145 -232l251 126q13 -175 -151 -267q-123 -70 -253 -23l-596 -596q-15 -16 -36.5 -16t-36.5 16l-111 110q-15 15 -15 36.5z" />
+<glyph unicode="&#xe137;" horiz-adv-x="1220" d="M0 196v100q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5zM0 596v100q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000 q-41 0 -70.5 29.5t-29.5 70.5zM0 996v100q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5zM600 596h500v100h-500v-100zM800 196h300v100h-300v-100zM900 996h200v100h-200v-100z" />
+<glyph unicode="&#xe138;" d="M100 1100v100h1000v-100h-1000zM150 1000h900l-350 -500v-300l-200 -200v500z" />
+<glyph unicode="&#xe139;" d="M0 200v200h1200v-200q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5zM0 500v400q0 41 29.5 70.5t70.5 29.5h300v100q0 41 29.5 70.5t70.5 29.5h200q41 0 70.5 -29.5t29.5 -70.5v-100h300q41 0 70.5 -29.5t29.5 -70.5v-400h-500v100h-200v-100h-500z M500 1000h200v100h-200v-100z" />
+<glyph unicode="&#xe140;" d="M0 0v400l129 -129l200 200l142 -142l-200 -200l129 -129h-400zM0 800l129 129l200 -200l142 142l-200 200l129 129h-400v-400zM729 329l142 142l200 -200l129 129v-400h-400l129 129zM729 871l200 200l-129 129h400v-400l-129 129l-200 -200z" />
+<glyph unicode="&#xe141;" d="M0 596q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM182 596q0 -172 121.5 -293t292.5 -121t292.5 121t121.5 293q0 171 -121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM291 655 q0 23 15.5 38.5t38.5 15.5t39 -16t16 -38q0 -23 -16 -39t-39 -16q-22 0 -38 16t-16 39zM400 850q0 22 16 38.5t39 16.5q22 0 38 -16t16 -39t-16 -39t-38 -16q-23 0 -39 16.5t-16 38.5zM514 609q0 32 20.5 56.5t51.5 29.5l122 126l1 1q-9 14 -9 28q0 22 16 38.5t39 16.5 q22 0 38 -16t16 -39t-16 -39t-38 -16q-14 0 -29 10l-55 -145q17 -22 17 -51q0 -36 -25.5 -61.5t-61.5 -25.5t-61.5 25.5t-25.5 61.5zM800 655q0 22 16 38t39 16t38.5 -15.5t15.5 -38.5t-16 -39t-38 -16q-23 0 -39 16t-16 39z" />
+<glyph unicode="&#xe142;" d="M-40 375q-13 -95 35 -173q35 -57 94 -89t129 -32q63 0 119 28q33 16 65 40.5t52.5 45.5t59.5 64q40 44 57 61l394 394q35 35 47 84t-3 96q-27 87 -117 104q-20 2 -29 2q-46 0 -78.5 -16.5t-67.5 -51.5l-389 -396l-7 -7l69 -67l377 373q20 22 39 38q23 23 50 23 q38 0 53 -36q16 -39 -20 -75l-547 -547q-52 -52 -125 -52q-55 0 -100 33t-54 96q-5 35 2.5 66t31.5 63t42 50t56 54q24 21 44 41l348 348q52 52 82.5 79.5t84 54t107.5 26.5q25 0 48 -4q95 -17 154 -94.5t51 -175.5q-7 -101 -98 -192l-252 -249l-253 -256l7 -7l69 -60 l517 511q67 67 95 157t11 183q-16 87 -67 154t-130 103q-69 33 -152 33q-107 0 -197 -55q-40 -24 -111 -95l-512 -512q-68 -68 -81 -163z" />
+<glyph unicode="&#xe143;" d="M80 784q0 131 98.5 229.5t230.5 98.5q143 0 241 -129q103 129 246 129q129 0 226 -98.5t97 -229.5q0 -46 -17.5 -91t-61 -99t-77 -89.5t-104.5 -105.5q-197 -191 -293 -322l-17 -23l-16 23q-43 58 -100 122.5t-92 99.5t-101 100q-71 70 -104.5 105.5t-77 89.5t-61 99 t-17.5 91zM250 784q0 -27 30.5 -70t61.5 -75.5t95 -94.5l22 -22q93 -90 190 -201q82 92 195 203l12 12q64 62 97.5 97t64.5 79t31 72q0 71 -48 119.5t-105 48.5q-74 0 -132 -83l-118 -171l-114 174q-51 80 -123 80q-60 0 -109.5 -49.5t-49.5 -118.5z" />
+<glyph unicode="&#xe144;" d="M57 353q0 -95 66 -159l141 -142q68 -66 159 -66q93 0 159 66l283 283q66 66 66 159t-66 159l-141 141q-8 9 -19 17l-105 -105l212 -212l-389 -389l-247 248l95 95l-18 18q-46 45 -75 101l-55 -55q-66 -66 -66 -159zM269 706q0 -93 66 -159l141 -141q7 -7 19 -17l105 105 l-212 212l389 389l247 -247l-95 -96l18 -17q47 -49 77 -100l29 29q35 35 62.5 88t27.5 96q0 93 -66 159l-141 141q-66 66 -159 66q-95 0 -159 -66l-283 -283q-66 -64 -66 -159z" />
+<glyph unicode="&#xe145;" d="M200 100v953q0 21 30 46t81 48t129 38t163 15t162 -15t127 -38t79 -48t29 -46v-953q0 -41 -29.5 -70.5t-70.5 -29.5h-600q-41 0 -70.5 29.5t-29.5 70.5zM300 300h600v700h-600v-700zM496 150q0 -43 30.5 -73.5t73.5 -30.5t73.5 30.5t30.5 73.5t-30.5 73.5t-73.5 30.5 t-73.5 -30.5t-30.5 -73.5z" />
+<glyph unicode="&#xe146;" d="M0 0l303 380l207 208l-210 212h300l267 279l-35 36q-15 14 -15 35t15 35q14 15 35 15t35 -15l283 -282q15 -15 15 -36t-15 -35q-14 -15 -35 -15t-35 15l-36 35l-279 -267v-300l-212 210l-208 -207z" />
+<glyph unicode="&#xe148;" d="M295 433h139q5 -77 48.5 -126.5t117.5 -64.5v335q-6 1 -15.5 4t-11.5 3q-46 14 -79 26.5t-72 36t-62.5 52t-40 72.5t-16.5 99q0 92 44 159.5t109 101t144 40.5v78h100v-79q38 -4 72.5 -13.5t75.5 -31.5t71 -53.5t51.5 -84t24.5 -118.5h-159q-8 72 -35 109.5t-101 50.5 v-307l64 -14q34 -7 64 -16.5t70 -31.5t67.5 -52t47.5 -80.5t20 -112.5q0 -139 -89 -224t-244 -96v-77h-100v78q-152 17 -237 104q-40 40 -52.5 93.5t-15.5 139.5zM466 889q0 -29 8 -51t16.5 -34t29.5 -22.5t31 -13.5t38 -10q7 -2 11 -3v274q-61 -8 -97.5 -37.5t-36.5 -102.5 zM700 237q170 18 170 151q0 64 -44 99.5t-126 60.5v-311z" />
+<glyph unicode="&#xe149;" d="M100 600v100h166q-24 49 -44 104q-10 26 -14.5 55.5t-3 72.5t25 90t68.5 87q97 88 263 88q129 0 230 -89t101 -208h-153q0 52 -34 89.5t-74 51.5t-76 14q-37 0 -79 -14.5t-62 -35.5q-41 -44 -41 -101q0 -28 16.5 -69.5t28 -62.5t41.5 -72h241v-100h-197q8 -50 -2.5 -115 t-31.5 -94q-41 -59 -99 -113q35 11 84 18t70 7q33 1 103 -16t103 -17q76 0 136 30l50 -147q-41 -25 -80.5 -36.5t-59 -13t-61.5 -1.5q-23 0 -128 33t-155 29q-39 -4 -82 -17t-66 -25l-24 -11l-55 145l16.5 11t15.5 10t13.5 9.5t14.5 12t14.5 14t17.5 18.5q48 55 54 126.5 t-30 142.5h-221z" />
+<glyph unicode="&#xe150;" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM602 900l298 300l298 -300h-198v-900h-200v900h-198z" />
+<glyph unicode="&#xe151;" d="M2 300h198v900h200v-900h198l-298 -300zM700 0v200h100v-100h200v-100h-300zM700 400v100h300v-200h-99v-100h-100v100h99v100h-200zM700 700v500h300v-500h-100v100h-100v-100h-100zM801 900h100v200h-100v-200z" />
+<glyph unicode="&#xe152;" d="M2 300h198v900h200v-900h198l-298 -300zM700 0v500h300v-500h-100v100h-100v-100h-100zM700 700v200h100v-100h200v-100h-300zM700 1100v100h300v-200h-99v-100h-100v100h99v100h-200zM801 200h100v200h-100v-200z" />
+<glyph unicode="&#xe153;" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM800 100v400h300v-500h-100v100h-200zM800 1100v100h200v-500h-100v400h-100zM901 200h100v200h-100v-200z" />
+<glyph unicode="&#xe154;" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM800 400v100h200v-500h-100v400h-100zM800 800v400h300v-500h-100v100h-200zM901 900h100v200h-100v-200z" />
+<glyph unicode="&#xe155;" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM700 100v200h500v-200h-500zM700 400v200h400v-200h-400zM700 700v200h300v-200h-300zM700 1000v200h200v-200h-200z" />
+<glyph unicode="&#xe156;" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM700 100v200h200v-200h-200zM700 400v200h300v-200h-300zM700 700v200h400v-200h-400zM700 1000v200h500v-200h-500z" />
+<glyph unicode="&#xe157;" d="M0 400v300q0 165 117.5 282.5t282.5 117.5h300q162 0 281 -118.5t119 -281.5v-300q0 -165 -118.5 -282.5t-281.5 -117.5h-300q-165 0 -282.5 117.5t-117.5 282.5zM200 300q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5 h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500z" />
+<glyph unicode="&#xe158;" d="M0 400v300q0 163 119 281.5t281 118.5h300q165 0 282.5 -117.5t117.5 -282.5v-300q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-163 0 -281.5 117.5t-118.5 282.5zM200 300q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5 h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500zM400 300l333 250l-333 250v-500z" />
+<glyph unicode="&#xe159;" d="M0 400v300q0 163 117.5 281.5t282.5 118.5h300q163 0 281.5 -119t118.5 -281v-300q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5t-117.5 282.5zM200 300q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5 h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500zM300 700l250 -333l250 333h-500z" />
+<glyph unicode="&#xe160;" d="M0 400v300q0 165 117.5 282.5t282.5 117.5h300q165 0 282.5 -117.5t117.5 -282.5v-300q0 -162 -118.5 -281t-281.5 -119h-300q-165 0 -282.5 118.5t-117.5 281.5zM200 300q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5 h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500zM300 400h500l-250 333z" />
+<glyph unicode="&#xe161;" d="M0 400v300h300v200l400 -350l-400 -350v200h-300zM500 0v200h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5h-500v200h400q165 0 282.5 -117.5t117.5 -282.5v-300q0 -165 -117.5 -282.5t-282.5 -117.5h-400z" />
+<glyph unicode="&#xe162;" d="M217 519q8 -19 31 -19h302q-155 -438 -160 -458q-5 -21 4 -32l9 -8h9q14 0 26 15q11 13 274.5 321.5t264.5 308.5q14 19 5 36q-8 17 -31 17l-301 -1q1 4 78 219.5t79 227.5q2 15 -5 27l-9 9h-9q-15 0 -25 -16q-4 -6 -98 -111.5t-228.5 -257t-209.5 -237.5q-16 -19 -6 -41 z" />
+<glyph unicode="&#xe163;" d="M0 400q0 -165 117.5 -282.5t282.5 -117.5h300q47 0 100 15v185h-500q-41 0 -70.5 29.5t-29.5 70.5v500q0 41 29.5 70.5t70.5 29.5h500v185q-14 4 -114 7.5t-193 5.5l-93 2q-165 0 -282.5 -117.5t-117.5 -282.5v-300zM600 400v300h300v200l400 -350l-400 -350v200h-300z " />
+<glyph unicode="&#xe164;" d="M0 400q0 -165 117.5 -282.5t282.5 -117.5h300q163 0 281.5 117.5t118.5 282.5v98l-78 73l-122 -123v-148q0 -41 -29.5 -70.5t-70.5 -29.5h-500q-41 0 -70.5 29.5t-29.5 70.5v500q0 41 29.5 70.5t70.5 29.5h156l118 122l-74 78h-100q-165 0 -282.5 -117.5t-117.5 -282.5 v-300zM496 709l353 342l-149 149h500v-500l-149 149l-342 -353z" />
+<glyph unicode="&#xe165;" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM406 600 q0 80 57 137t137 57t137 -57t57 -137t-57 -137t-137 -57t-137 57t-57 137z" />
+<glyph unicode="&#xe166;" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM100 800l445 -500l450 500h-295v400h-300v-400h-300zM900 150h100v50h-100v-50z" />
+<glyph unicode="&#xe167;" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM100 700h300v-300h300v300h295l-445 500zM900 150h100v50h-100v-50z" />
+<glyph unicode="&#xe168;" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM100 705l305 -305l596 596l-154 155l-442 -442l-150 151zM900 150h100v50h-100v-50z" />
+<glyph unicode="&#xe169;" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM100 988l97 -98l212 213l-97 97zM200 400l697 1l3 699l-250 -239l-149 149l-212 -212l149 -149zM900 150h100v50h-100v-50z" />
+<glyph unicode="&#xe170;" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM200 612l212 -212l98 97l-213 212zM300 1200l239 -250l-149 -149l212 -212l149 148l249 -237l-1 697zM900 150h100v50h-100v-50z" />
+<glyph unicode="&#xe171;" d="M23 415l1177 784v-1079l-475 272l-310 -393v416h-392zM494 210l672 938l-672 -712v-226z" />
+<glyph unicode="&#xe172;" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-850q0 -21 -15 -35.5t-35 -14.5h-150v400h-700v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM600 1000h100v200h-100v-200z" />
+<glyph unicode="&#xe173;" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-218l-276 -275l-120 120l-126 -127h-378v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM581 306l123 123l120 -120l353 352l123 -123l-475 -476zM600 1000h100v200h-100v-200z" />
+<glyph unicode="&#xe174;" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-269l-103 -103l-170 170l-298 -298h-329v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM600 1000h100v200h-100v-200zM700 133l170 170l-170 170l127 127l170 -170l170 170l127 -128l-170 -169l170 -170 l-127 -127l-170 170l-170 -170z" />
+<glyph unicode="&#xe175;" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-300h-400v-200h-500v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM600 300l300 -300l300 300h-200v300h-200v-300h-200zM600 1000v200h100v-200h-100z" />
+<glyph unicode="&#xe176;" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-402l-200 200l-298 -298h-402v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM600 300h200v-300h200v300h200l-300 300zM600 1000v200h100v-200h-100z" />
+<glyph unicode="&#xe177;" d="M0 250q0 -21 14.5 -35.5t35.5 -14.5h1100q21 0 35.5 14.5t14.5 35.5v550h-1200v-550zM0 900h1200v150q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5v-150zM100 300v200h400v-200h-400z" />
+<glyph unicode="&#xe178;" d="M0 400l300 298v-198h400v-200h-400v-198zM100 800v200h100v-200h-100zM300 800v200h100v-200h-100zM500 800v200h400v198l300 -298l-300 -298v198h-400zM800 300v200h100v-200h-100zM1000 300h100v200h-100v-200z" />
+<glyph unicode="&#xe179;" d="M100 700v400l50 100l50 -100v-300h100v300l50 100l50 -100v-300h100v300l50 100l50 -100v-400l-100 -203v-447q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v447zM800 597q0 -29 10.5 -55.5t25 -43t29 -28.5t25.5 -18l10 -5v-397q0 -21 14.5 -35.5 t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5v1106q0 31 -18 40.5t-44 -7.5l-276 -116q-25 -17 -43.5 -51.5t-18.5 -65.5v-359z" />
+<glyph unicode="&#xe180;" d="M100 0h400v56q-75 0 -87.5 6t-12.5 44v394h500v-394q0 -38 -12.5 -44t-87.5 -6v-56h400v56q-4 0 -11 0.5t-24 3t-30 7t-24 15t-11 24.5v888q0 22 25 34.5t50 13.5l25 2v56h-400v-56q75 0 87.5 -6t12.5 -44v-394h-500v394q0 38 12.5 44t87.5 6v56h-400v-56q4 0 11 -0.5 t24 -3t30 -7t24 -15t11 -24.5v-888q0 -22 -25 -34.5t-50 -13.5l-25 -2v-56z" />
+<glyph unicode="&#xe181;" d="M0 300q0 -41 29.5 -70.5t70.5 -29.5h300q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5h-300q-41 0 -70.5 -29.5t-29.5 -70.5v-500zM100 100h400l200 200h105l295 98v-298h-425l-100 -100h-375zM100 300v200h300v-200h-300zM100 600v200h300v-200h-300z M100 1000h400l200 -200v-98l295 98h105v200h-425l-100 100h-375zM700 402v163l400 133v-163z" />
+<glyph unicode="&#xe182;" d="M16.5 974.5q0.5 -21.5 16 -90t46.5 -140t104 -177.5t175 -208q103 -103 207.5 -176t180 -103.5t137 -47t92.5 -16.5l31 1l163 162q17 18 13.5 41t-22.5 37l-192 136q-19 14 -45 12t-42 -19l-118 -118q-142 101 -268 227t-227 268l118 118q17 17 20 41.5t-11 44.5 l-139 194q-14 19 -36.5 22t-40.5 -14l-162 -162q-1 -11 -0.5 -32.5z" />
+<glyph unicode="&#xe183;" d="M0 50v212q0 20 10.5 45.5t24.5 39.5l365 303v50q0 4 1 10.5t12 22.5t30 28.5t60 23t97 10.5t97 -10t60 -23.5t30 -27.5t12 -24l1 -10v-50l365 -303q14 -14 24.5 -39.5t10.5 -45.5v-212q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-20 0 -35 14.5t-15 35.5zM0 712 q0 -21 14.5 -33.5t34.5 -8.5l202 33q20 4 34.5 21t14.5 38v146q141 24 300 24t300 -24v-146q0 -21 14.5 -38t34.5 -21l202 -33q20 -4 34.5 8.5t14.5 33.5v200q-6 8 -19 20.5t-63 45t-112 57t-171 45t-235 20.5q-92 0 -175 -10.5t-141.5 -27t-108.5 -36.5t-81.5 -40 t-53.5 -36.5t-31 -27.5l-9 -10v-200z" />
+<glyph unicode="&#xe184;" d="M100 0v100h1100v-100h-1100zM175 200h950l-125 150v250l100 100v400h-100v-200h-100v200h-200v-200h-100v200h-200v-200h-100v200h-100v-400l100 -100v-250z" />
+<glyph unicode="&#xe185;" d="M100 0h300v400q0 41 -29.5 70.5t-70.5 29.5h-100q-41 0 -70.5 -29.5t-29.5 -70.5v-400zM500 0v1000q0 41 29.5 70.5t70.5 29.5h100q41 0 70.5 -29.5t29.5 -70.5v-1000h-300zM900 0v700q0 41 29.5 70.5t70.5 29.5h100q41 0 70.5 -29.5t29.5 -70.5v-700h-300z" />
+<glyph unicode="&#xe186;" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h300v300h-200v100h200v100h-300v-300h200v-100h-200v-100zM600 300h200v100h100v300h-100v100h-200v-500 zM700 400v300h100v-300h-100z" />
+<glyph unicode="&#xe187;" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h100v200h100v-200h100v500h-100v-200h-100v200h-100v-500zM600 300h200v100h100v300h-100v100h-200v-500 zM700 400v300h100v-300h-100z" />
+<glyph unicode="&#xe188;" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h300v100h-200v300h200v100h-300v-500zM600 300h300v100h-200v300h200v100h-300v-500z" />
+<glyph unicode="&#xe189;" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 550l300 -150v300zM600 400l300 150l-300 150v-300z" />
+<glyph unicode="&#xe190;" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300v500h700v-500h-700zM300 400h130q41 0 68 42t27 107t-28.5 108t-66.5 43h-130v-300zM575 549 q0 -65 27 -107t68 -42h130v300h-130q-38 0 -66.5 -43t-28.5 -108z" />
+<glyph unicode="&#xe191;" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h300v300h-200v100h200v100h-300v-300h200v-100h-200v-100zM601 300h100v100h-100v-100zM700 700h100 v-400h100v500h-200v-100z" />
+<glyph unicode="&#xe192;" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h300v400h-200v100h-100v-500zM301 400v200h100v-200h-100zM601 300h100v100h-100v-100zM700 700h100 v-400h100v500h-200v-100z" />
+<glyph unicode="&#xe193;" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 700v100h300v-300h-99v-100h-100v100h99v200h-200zM201 300v100h100v-100h-100zM601 300v100h100v-100h-100z M700 700v100h200v-500h-100v400h-100z" />
+<glyph unicode="&#xe194;" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM400 500v200 l100 100h300v-100h-300v-200h300v-100h-300z" />
+<glyph unicode="&#xe195;" d="M0 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM182 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM400 400v400h300 l100 -100v-100h-100v100h-200v-100h200v-100h-200v-100h-100zM700 400v100h100v-100h-100z" />
+<glyph unicode="&#xe197;" d="M-14 494q0 -80 56.5 -137t135.5 -57h222v300h400v-300h128q120 0 205 86.5t85 207.5t-85 207t-205 86q-46 0 -90 -14q-44 97 -134.5 156.5t-200.5 59.5q-152 0 -260 -107.5t-108 -260.5q0 -25 2 -37q-66 -14 -108.5 -67.5t-42.5 -122.5zM300 200h200v300h200v-300h200 l-300 -300z" />
+<glyph unicode="&#xe198;" d="M-14 494q0 -80 56.5 -137t135.5 -57h8l414 414l403 -403q94 26 154.5 104.5t60.5 178.5q0 120 -85 206.5t-205 86.5q-46 0 -90 -14q-44 97 -134.5 156.5t-200.5 59.5q-152 0 -260 -107.5t-108 -260.5q0 -25 2 -37q-66 -14 -108.5 -67.5t-42.5 -122.5zM300 200l300 300 l300 -300h-200v-300h-200v300h-200z" />
+<glyph unicode="&#xe199;" d="M100 200h400v-155l-75 -45h350l-75 45v155h400l-270 300h170l-270 300h170l-300 333l-300 -333h170l-270 -300h170z" />
+<glyph unicode="&#xe200;" d="M121 700q0 -53 28.5 -97t75.5 -65q-4 -16 -4 -38q0 -74 52.5 -126.5t126.5 -52.5q56 0 100 30v-306l-75 -45h350l-75 45v306q46 -30 100 -30q74 0 126.5 52.5t52.5 126.5q0 24 -9 55q50 32 79.5 83t29.5 112q0 90 -61.5 155.5t-150.5 71.5q-26 89 -99.5 145.5 t-167.5 56.5q-116 0 -197.5 -81.5t-81.5 -197.5q0 -4 1 -11.5t1 -11.5q-14 2 -23 2q-74 0 -126.5 -52.5t-52.5 -126.5z" />
+</font>
+</defs></svg> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/tools/runner/fonts/glyphicons-halflings-regular.ttf b/tests/wpt/web-platform-tests/tools/runner/fonts/glyphicons-halflings-regular.ttf
new file mode 100644
index 00000000000..67fa00bf838
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/runner/fonts/glyphicons-halflings-regular.ttf
Binary files differ
diff --git a/tests/wpt/web-platform-tests/tools/runner/fonts/glyphicons-halflings-regular.woff b/tests/wpt/web-platform-tests/tools/runner/fonts/glyphicons-halflings-regular.woff
new file mode 100644
index 00000000000..8c54182aa5d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/runner/fonts/glyphicons-halflings-regular.woff
Binary files differ
diff --git a/tests/wpt/web-platform-tests/tools/runner/index.html b/tests/wpt/web-platform-tests/tools/runner/index.html
new file mode 100644
index 00000000000..45ae38c7edf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/runner/index.html
@@ -0,0 +1,178 @@
+<!DOCTYPE html>
+<html lang=en>
+<meta charset=UTF-8>
+<title>Web tests</title>
+<link rel='stylesheet' href='css/bootstrap.min.css'>
+<link rel='stylesheet' href='css/bootstrap-theme.min.css'>
+<link rel=stylesheet href=runner.css>
+<script src=runner.js></script>
+
+
+<header class="navbar navbar-inverse navbar-fixed-top">
+ <div class="container">
+ <div class="navbar-header">
+ <a class="navbar-brand" href="#">
+ <img src='logo.svg' width='50' height='50' alt='Logo for the WPT Runner'>
+ Web Platform Tests Runner
+ </a>
+ </div>
+ </div>
+</header>
+
+<div class="container">
+ <div id="testControl" class="panel panel-default">
+ <div class="panel-body">
+ <form id='options' class='horizontal-form' onsubmit='return false;'>
+
+ <div class="form-group">
+ <label class="col-sm-3 control-label">Test types to include</label>
+ <div class="col-sm-9">
+ <label>
+ <input type=checkbox checked value="testharness" id='th' class='test-type'>
+ JavaScript tests
+ </label>
+ <label>
+ <input type=checkbox checked value="reftest" id='ref' class='test-type'>
+ Reftests
+ </label>
+ <label>
+ <input type=checkbox checked value="manual" id='man' class='test-type'>
+ Manual tests
+ </label>
+ </div>
+ </div>
+
+ <div class="form-group">
+ <label for="path" class="col-sm-3 control-label">Run tests under path</label>
+ <div class="col-sm-9">
+ <input value="/" id='path' class='path form-control' disabled>
+ </div>
+ </div>
+
+ <div class="form-group">
+ <label for="timeout_multiplier" class="col-sm-3 control-label">Timeout multiplier</label>
+ <div class="col-sm-9">
+ <input type=number value="1" id='timeout_multiplier' class='timeout_multiplier form-control'>
+ </div>
+ </div>
+
+ <div class="form-group">
+ <label class="col-sm-3 control-label">Debug options</label>
+ <div class="col-sm-9">
+ <label>
+ <input type=checkbox id='render' value='render' class='render'>
+ Show output
+ </label>
+ <label>
+ <input type=checkbox id='dumpit'>
+ Dump JSON
+ </label>
+ </div>
+ </div>
+
+ <div class="form-group">
+ <div class="col-sm-offset-3 col-sm-9">
+ <button type="submit" class="btn btn-success toggleStart" disabled>Start</button>
+ <button type='submit' class="btn btn-info togglePause" disabled>Pause</button>
+ </div>
+ </div>
+ </form>
+ </div>
+ </div>
+
+ <div class="instructions">
+ <p>
+ To run a set of
+ <a href="https://github.com/w3c/web-platform-tests/blob/master/README.md">web-platform-tests</a>
+ tests, specify a path value in the <b>Run tests under path</b> field above. Example paths:
+ <ul>
+ <li><code>/</code> - runs all of the tests from the root down</li>
+ <li><code>/websockets</code> - runs all of the
+ <a href="http://w3c-test.org/websockets/">websockets</a> tests</li>
+ <li><code>/websockets/constructor</code> - runs all of the
+ <a href="http://w3c-test.org/websockets/constructor/">websockets/constructor</a> tests</li>
+ <li><code>/html/syntax/parsing</code> - runs all of the
+ <a href="http://w3c-test.org/html/syntax/parsing/">html/syntax/parsing</a> tests</li>
+ </ul>
+ <p>
+ If the test runner is run online, the set of tests available to run can be found in the
+ <a href="http://w3c-test.org/">w3c-test.org</a> test repository.
+ <p>
+ Tests will run in a new window. For reftests and manual tests it’s best
+ to put that window side-by-side with this one.
+ </div>
+
+ <div id="output">
+ <div class="summary clearfix">
+ <h4>Progress
+ <span id="manifest">updating and loading test manifest; this may take several minutes</span>
+ </h4>
+ <div class="progress">
+ <div class="progress-bar" role="progressbar"
+ aria-valuenow="0" aria-valuemin="0" aria-valuemax="0" style="width: 0">
+ 0%
+ </div>
+ </div>
+ <div id='test_url'></div>
+ <table class='table'>
+ <thead>
+ <tr>
+ <th>Passed
+ <th>Failed
+ <th>Timeouts
+ <th>Errors
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td class='PASS'>0
+ <td class='FAIL'>0
+ <td class='TIMEOUT'>0
+ <td class='ERROR'>0
+ </tr>
+ </tbody>
+ </table>
+ <a class="jsonResults btn btn-primary pull-right">Download JSON results</a>
+ </div>
+
+ <div class="results">
+ <div id="manualUI">
+ <div class='panel panel-primary'>
+ <div class='panel-heading'>
+ <h4 class='panel-title'>Manual Testing</h4>
+ </div>
+ <div class="panel-body reftestUI">
+ <p>
+ The current test requires manual result marking.
+ Test and ref should compare <strong class="refType text-primary"></strong>
+ </p>
+ <p>
+ <button class="btn btn-info test">Show Test</button>
+ <button class="btn btn-info ref">Show Reference</button>
+ </p>
+ </div>
+ <div class="panel-footer">
+ The test has:
+ <button class="btn btn-success pass">Passed</button>
+ <button class="btn btn-danger fail">Failed</button>
+ </div>
+ </div>
+ </div>
+
+ <hr>
+ <h4>Details</h4>
+ <table class='table'>
+ <thead>
+ <tr>
+ <th>Test
+ <th>Status
+ <th>Message
+ <th>Subtest Pass Rate
+ </tr>
+ </thead>
+ <tbody></tbody>
+ </table>
+ </div>
+ </div>
+
+</div>
diff --git a/tests/wpt/web-platform-tests/tools/runner/logo.svg b/tests/wpt/web-platform-tests/tools/runner/logo.svg
new file mode 100644
index 00000000000..8a25776b6f4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/runner/logo.svg
@@ -0,0 +1,8 @@
+<svg width="453px" height="453px" viewBox="0 0 453 453" xmlns="http://www.w3.org/2000/svg">
+ <circle stroke="#ed5565" stroke-width="20" fill="#fff" cx="226.5" cy="226.5" r="213.5"></circle>
+ <g transform="translate(160 250)">
+ <g transform="matrix(2.25 0 0 -2.25 0 0)">
+ <path d="m0 0c0.252-0.333 0.508-0.659 0.766-0.974-1.269-3.764-2.368-7.749-3.447-11.383-0.166-0.053-0.329-0.116-0.486-0.194-8.572 8.211-2.056 11.364 3.167 12.551m59.809 45.57c2.899 20.118-10.084 38.635-29 41.362-18.915 2.726-36.601-11.371-39.5-31.489-2.418-16.774 6.212-32.427 20.112-38.75l-0.05 0.014-0.323-2.242c0.219-0.049 0.427-0.09 0.64-0.134-0.122-0.027-0.245-0.053-0.365-0.086l-0.004 0.013s-0.042-0.017-0.106-0.042c-0.465-0.137-0.915-0.319-1.349-0.544-3.502-1.424-12.285-5.095-14.287-6.867 0 0 0.927-1.665 2.254-3.704-17.335-2.421-6.522-15.63-3.176-19.26-0.015-0.296 0.004-0.592 0.039-0.888-2.562-1.677-5.772-4.195-7.772-7.29 0 0 0.552-0.182 1.458-0.536v-0.001l0.016-0.005c1.182-0.463 2.96-1.219 4.914-2.248-3.004-13.557-7.542-9.677-10.589-4.683 0.745 2.232 0.741 4.23-0.202 5.393-0.66 0.811-1.681 1.101-2.889 0.931-0.087 0.222-0.135 0.349-0.135 0.349l-0.108-0.397c-0.057-0.01-0.115-0.021-0.173-0.034 0.005 0.003 0.008 0.005 0.013 0.008 0 0-0.032-0.008-0.078-0.021-0.508-0.116-1.042-0.306-1.593-0.566-2.759-1.158-8.023-4.248-8.639-11.088-0.208-1.056-0.212-2.015 0.002-2.812 0.001-0.014 0.001-0.026 0.003-0.04 0 0 0.527-4.561 4.288-1.894l-0.002 0.003c1.861 0.536 4.034 2.003 5.989 4.226 0.664 0.755 1.256 1.545 1.768 2.343 8.537-16.768 14.974 3.409 15.81 6.23 2.309-1.538 4.528-3.425 6.019-5.64 0 0 1.182 3.458 3.942 6.312 5.984-8.956 13.374-10.465 13.374-10.465l3.802 6.152c11.328-5.569 7.382-10.385 2.713-13.253-1.757 1.198-3.428 1.485-4.537 0.55-0.775-0.653-1.166-1.807-1.2-3.246-0.199-0.069-0.312-0.106-0.312-0.106l0.316-0.185c0.001-0.069 0.002-0.139 0.004-0.21-0.002 0.006-0.004 0.012-0.006 0.019 0 0 0.003-0.044 0.007-0.112 0.024-0.604 0.104-1.247 0.239-1.92 0.564-3.395 2.378-10.019 8.013-11.741 0.851-0.396 1.652-0.542 2.349-0.407 0.012 0 0.023-0.003 0.035-0.003 0 0 3.891-0.048 2.21 4.745l-0.004-0.004c-0.176 2.258-1.086 5.015-2.659 7.628-0.535 0.888-1.109 1.695-1.701 2.413 16.374 8.095-3.15 19.567-3.156 19.57l2.062 3.336-4.584 1.028c-0.516 0.116-1.446 0.458-2.639 0.949 0.61-0.116 1.218-0.225 1.821-0.322 0.221 0.615 0.432 1.249 0.631 1.918 1.715 5.766 2.34 12.577 1.803 18.76l1.544-3.601s0.655 0.404 1.612 0.827l-0.088-0.167c3.832-26.906 14.631-10.666 17.407-5.924 1.445 0.125 2.819 1.27 3.448 3.074 0.864 2.475 0.002 5.242-1.926 6.183-1.927 0.942-4.188-0.301-5.05-2.774-0.533-1.524-0.406-3.158 0.218-4.41-6.67-13.044-10.36-1.016-11.647 4.81 0.669 0.143 1.355 0.21 1.998 0.135 0 0-4.185 11.234-11.743 15.618-0.097 0.136-0.192 0.275-0.291 0.405-0.056-0.017-0.116-0.029-0.174-0.044l0.345 2.832c0.567 0.046 0.871 0.099 0.871 0.099l0.021 0.146-0.65 0.181c18.572-2.158 35.744 11.797 38.597 31.593" fill="#ed5565"/>
+ </g>
+ </g>
+</svg>
diff --git a/tests/wpt/web-platform-tests/tools/runner/report.css b/tests/wpt/web-platform-tests/tools/runner/report.css
new file mode 100644
index 00000000000..bc25f9e1bdb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/runner/report.css
@@ -0,0 +1,43 @@
+table {
+ border-collapse: collapse;
+}
+
+tbody {
+ border-top: thin solid;
+ border-bottom: thin solid;
+}
+
+.status {
+ font-variant:small-caps;
+ color:white;
+ text-align:center;
+ font-variant:small-caps;
+}
+
+.PASS, .OK {
+ background-color:green;
+}
+
+.FAIL {
+ background-color:red;
+}
+
+.ERROR, .NOTRUN, .NONE {
+ background-color:black;
+}
+
+.TIMEOUT {
+ background-color:blue;
+}
+
+td {
+ padding:0.25em;
+}
+
+tr.test {
+ background-color:#ddd;
+}
+
+tr.subtest {
+ background-color:#eee;
+}
diff --git a/tests/wpt/web-platform-tests/tools/runner/report.py b/tests/wpt/web-platform-tests/tools/runner/report.py
new file mode 100644
index 00000000000..60a0cef8510
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/runner/report.py
@@ -0,0 +1,310 @@
+import argparse
+import json
+import sys
+from cgi import escape
+from collections import defaultdict
+
+import types
+
+
+def html_escape(item, escape_quote=False):
+ if isinstance(item, types.StringTypes):
+ rv = escape(item)
+ if escape_quote:
+ rv = rv.replace('"', "&quot;")
+ return rv
+ else:
+ return item
+
+
+class Raw(object):
+ """Simple wrapper around a string to stop it being escaped by html_escape"""
+ def __init__(self, value):
+ self.value = value
+
+ def __unicode__(self):
+ return unicode(self.value)
+
+
+class Node(object):
+ """Node structure used when building HTML"""
+ def __init__(self, name, attrs, children):
+ #Need list of void elements
+ self.name = name
+ self.attrs = attrs
+ self.children = children
+
+ def __unicode__(self):
+ if self.attrs:
+ #Need to escape
+ attrs_unicode = " " + " ".join("%s=\"%s\"" % (html_escape(key),
+ html_escape(value,
+ escape_quote=True))
+ for key, value in self.attrs.iteritems())
+ else:
+ attrs_unicode = ""
+ return "<%s%s>%s</%s>\n" % (self.name,
+ attrs_unicode,
+ "".join(unicode(html_escape(item))
+ for item in self.children),
+ self.name)
+
+ def __str__(self):
+ return unicode(self).encode("utf8")
+
+
+class RootNode(object):
+ """Special Node representing the document root"""
+ def __init__(self, *children):
+ self.children = ["<!DOCTYPE html>"] + list(children)
+
+ def __unicode__(self):
+ return "".join(unicode(item) for item in self.children)
+
+ def __str__(self):
+ return unicode(self).encode("utf8")
+
+
+def flatten(iterable):
+ """Flatten a list of lists by one level so that
+ [1,["abc"], "def",[2, [3]]]
+ becomes
+ [1, "abc", "def", 2, [3]]"""
+ rv = []
+ for item in iterable:
+ if hasattr(item, "__iter__") and not isinstance(item, types.StringTypes):
+ rv.extend(item)
+ else:
+ rv.append(item)
+ return rv
+
+
+class HTML(object):
+ """Simple HTML templating system. An instance of this class can create
+ element nodes by calling methods with the same name as the element,
+ passing in children as positional arguments or as a list, and attributes
+ as keyword arguments, with _ replacing - and trailing _ for python keywords
+
+ e.g.
+
+ h = HTML()
+ print h.html(
+ html.head(),
+ html.body([html.h1("Hello World!")], class_="body-class")
+ )
+ Would give
+ <!DOCTYPE html><html><head></head><body class="body-class"><h1>Hello World!</h1></body></html>"""
+ def __getattr__(self, name):
+ def make_html(self, *content, **attrs):
+ for attr_name in attrs.keys():
+ if "_" in attr_name:
+ new_name = attr_name.replace("_", "-")
+ if new_name.endswith("-"):
+ new_name = new_name[:-1]
+ attrs[new_name] = attrs.pop(attr_name)
+ return Node(name, attrs, flatten(content))
+
+ method = types.MethodType(make_html, self, HTML)
+ setattr(self, name, method)
+ return method
+
+ def __call__(self, *children):
+ return RootNode(*flatten(children))
+
+
+h = HTML()
+
+
+class TestResult(object):
+ """Simple holder for the results of a single test in a single UA"""
+ def __init__(self, test):
+ self.test = test
+ self.results = {}
+
+ def __cmp__(self, other):
+ return self.test == other.test
+
+ def __hash__(self):
+ return hash(self.test)
+
+
+def load_data(args):
+ """Load data treating args as a list of UA name, filename pairs"""
+ pairs = []
+ for i in xrange(0, len(args), 2):
+ pairs.append(args[i:i+2])
+
+ rv = {}
+ for UA, filename in pairs:
+ with open(filename) as f:
+ rv[UA] = json.load(f)
+
+ return rv
+
+
+def test_id(id):
+ """Convert a test id in JSON into an immutable object that
+ can be used as a dictionary key"""
+ if isinstance(id, list):
+ return tuple(id)
+ else:
+ return id
+
+
+def all_tests(data):
+ tests = defaultdict(set)
+ for UA, results in data.iteritems():
+ for result in results["results"]:
+ id = test_id(result["test"])
+ tests[id] |= set(subtest["name"] for subtest in result["subtests"])
+ return tests
+
+
+def group_results(data):
+ """Produce a list of UAs and a dictionary mapping specific tests to their
+ status in all UAs e.g.
+ ["UA1", "UA2"], {"test_id":{"harness":{"UA1": (status1, message1),
+ "UA2": (status2, message2)},
+ "subtests":{"subtest1": "UA1": (status1-1, message1-1),
+ "UA2": (status2-1, message2-1)}}}
+ Status and message are None if the test didn't run in a particular UA.
+ Message is None if the test didn't produce a message"""
+ tests = all_tests(data)
+
+ UAs = data.keys()
+
+ def result():
+ return {
+ "harness": dict((UA, (None, None)) for UA in UAs),
+ "subtests": None # init this later
+ }
+
+ results_by_test = defaultdict(result)
+
+ for UA, results in data.iteritems():
+ for test_data in results["results"]:
+ id = test_id(test_data["test"])
+ result = results_by_test[id]
+
+ if result["subtests"] is None:
+ result["subtests"] = dict(
+ (name, dict((UA, (None, None)) for UA in UAs)) for name in tests[id]
+ )
+
+ result["harness"][UA] = (test_data["status"], test_data["message"])
+ for subtest in test_data["subtests"]:
+ result["subtests"][subtest["name"]][UA] = (subtest["status"],
+ subtest["message"])
+
+ return UAs, results_by_test
+
+
+def status_cell(status, message=None):
+ """Produce a table cell showing the status of a test"""
+ status = status if status is not None else "NONE"
+ kwargs = {}
+ if message:
+ kwargs["title"] = message
+ status_text = status.title()
+ return h.td(status_text, class_="status " + status,
+ **kwargs)
+
+
+def test_link(test_id, subtest=None):
+ """Produce an <a> element linking to a test"""
+ if isinstance(test_id, types.StringTypes):
+ rv = [h.a(test_id, href=test_id)]
+ else:
+ rv = [h.a(test_id[0], href=test_id[0]),
+ " %s " % test_id[1],
+ h.a(test_id[2], href=test_id[2])]
+ if subtest is not None:
+ rv.append(" [%s]" % subtest)
+ return rv
+
+
+def summary(UAs, results_by_test):
+ """Render the implementation report summary"""
+ not_passing = []
+ for test, results in results_by_test.iteritems():
+ if not any(item[0] in ("PASS", "OK") for item in results["harness"].values()):
+ not_passing.append((test, None))
+ for subtest_name, subtest_results in results["subtests"].iteritems():
+ if not any(item[0] == "PASS" for item in subtest_results.values()):
+ not_passing.append((test, subtest_name))
+ if not_passing:
+ rv = [
+ h.p("The following tests failed to pass in all UAs:"),
+ h.ul([h.li(test_link(test, subtest))
+ for test, subtest in not_passing])
+ ]
+ else:
+ rv = "All tests passed in at least one UA"
+ return rv
+
+
+def result_rows(UAs, test, result):
+ """Render the results for each test run"""
+ yield h.tr(
+ h.td(
+ test_link(test),
+ rowspan=(1 + len(result["subtests"]))
+ ),
+ h.td(),
+ [status_cell(status, message)
+ for UA, (status, message) in sorted(result["harness"].items())],
+ class_="test"
+ )
+
+ for name, subtest_result in sorted(result["subtests"].iteritems()):
+ yield h.tr(
+ h.td(name),
+ [status_cell(status, message)
+ for UA, (status, message) in sorted(subtest_result.items())],
+ class_="subtest"
+ )
+
+
+def result_bodies(UAs, results_by_test):
+ return [h.tbody(result_rows(UAs, test, result))
+ for test, result in sorted(results_by_test.iteritems())]
+
+
+def generate_html(UAs, results_by_test):
+ """Generate all the HTML output"""
+ doc = h(h.html([
+ h.head(h.meta(charset="utf8"),
+ h.title("Implementation Report"),
+ h.link(href="report.css", rel="stylesheet")),
+ h.body(h.h1("Implementation Report"),
+ h.h2("Summary"),
+ summary(UAs, results_by_test),
+ h.h2("Full Results"),
+ h.table(
+ h.thead(
+ h.tr(
+ h.th("Test"),
+ h.th("Subtest"),
+ [h.th(UA) for UA in sorted(UAs)]
+ )
+ ),
+ result_bodies(UAs, results_by_test)
+ )
+ )
+ ]))
+
+ return doc
+
+
+def main(filenames):
+ data = load_data(filenames)
+ UAs, results_by_test = group_results(data)
+ return generate_html(UAs, results_by_test)
+
+
+if __name__ == "__main__":
+ if not sys.argv[1:]:
+ print """Please supply a list of UA name, filename pairs e.g.
+
+python report.py Firefox firefox.json Chrome chrome.json IE internet_explorer.json"""
+ print main(sys.argv[1:])
diff --git a/tests/wpt/web-platform-tests/tools/runner/runner.css b/tests/wpt/web-platform-tests/tools/runner/runner.css
new file mode 100644
index 00000000000..b24c8bd4232
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/runner/runner.css
@@ -0,0 +1,193 @@
+
+html {
+ margin: 0 8px;
+}
+
+body {
+ margin: 0;
+}
+
+html.done {
+ border: 2px solid #32cd32;
+ margin: 3px;
+ padding: 3px;
+}
+
+html:not(.done) {
+ height: 100%;
+}
+
+html:not(.done) body {
+ height: 100%;
+}
+
+html:not(.done) #wrapper {
+ height: 100%;
+ margin-top: -1.5em;
+ padding-top: 1.5em;
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+}
+
+section {
+ display: block;
+ border: thin solid black;
+ padding: 0.5em 0;
+}
+
+section h1 {
+ margin: 0;
+ font-size: 1em;
+}
+
+html.done section h1 {
+ text-align: center;
+}
+
+section ol {
+ padding: 0;
+ margin: 0;
+ list-style-position: inside;
+}
+
+html.done section ol {
+ -moz-column-count: 3;
+ -webkit-column-count: 3;
+ column-count: 3;
+}
+
+section li {
+ padding: 0.1em 0.5em;
+}
+
+section li.pass:nth-child(odd) {
+ background: #e5ffe5;
+}
+section li.pass:nth-child(even) {
+ background: #def8de;
+}
+
+section li.fail:nth-child(odd) {
+ background: #ffe5e5;
+}
+
+section li.fail:nth-child(even) {
+ background: #f8dede;
+}
+
+section p {
+ margin: 0;
+}
+
+html:not(.done) section {
+ border-top: none;
+}
+
+html.done section + section {
+ border-top: none;
+}
+
+#manualUI {
+ position: fixed;
+ top: 100px;
+ left: 0;
+ right: 0;
+ display: block;
+ padding: 40px;
+ background: rgba(255, 200, 0, 0.5);
+}
+
+#manualUI .panel {
+ max-width: 800px;
+ margin: auto;
+ box-shadow: 2px 2px 10px #666;
+}
+
+body > p {
+ text-align: center;
+}
+
+body > p > textarea {
+ width: 90%;
+ height: 20em;
+}
+
+body {
+ padding-top: 70px;
+}
+
+.container {
+ max-width: 800px;
+}
+
+.navbar-inverse .navbar-brand {
+ color: #fff;
+}
+
+.form-group {
+ clear:both;
+}
+
+.horizontal-form .form-group {
+ padding: 6px;
+}
+
+header.navbar-inverse {
+ background: linear-gradient(to bottom, rgb(7, 62, 128) 0px, rgb(0, 45, 80) 100%);
+}
+
+ul.error, ul.warning {
+ padding: 0;
+}
+
+td.PASS {
+ color: #48cfad;
+}
+
+td.FAIL {
+ color: #ed5565;
+}
+
+td.TIMEOUT {
+ color: #f6bb42;
+}
+
+td.ERROR {
+ color: #da4453;
+ font-weight: bold;
+}
+.stopped {
+ background-image: linear-gradient(to bottom, #fc0000 0, #770000 100%);
+}
+
+.col-sm-9 label {
+ margin-right: 20px;
+}
+
+.instructions {
+ padding-left: 8px;
+ padding-right: 8px;
+}
+
+@keyframes alert_updating {
+ from {
+ background-color: inherit;
+ }
+ to {
+ background-color: #ffc;
+ }
+}
+
+#manifest {
+ padding-left: 6px;
+ padding-right: 6px;
+ font-size: 80%;
+ font-weight: normal;
+ font-style: italic;
+ color: #999;
+ animation-duration: 1.5s;
+ animation-name: alert_updating;
+ animation-iteration-count: infinite;
+ animation-direction: alternate;
+}
diff --git a/tests/wpt/web-platform-tests/tools/runner/runner.js b/tests/wpt/web-platform-tests/tools/runner/runner.js
new file mode 100644
index 00000000000..80dc5d5cef7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/runner/runner.js
@@ -0,0 +1,729 @@
+/*jshint nonew: false */
+(function() {
+"use strict";
+var runner;
+var testharness_properties = {output:false,
+ timeout_multiplier:1};
+
+function Manifest(path) {
+ this.data = null;
+ this.path = path;
+ this.num_tests = null;
+}
+
+Manifest.prototype = {
+ load: function(loaded_callback) {
+ this.generate(loaded_callback);
+ },
+
+ do_load: function(loaded_callback) {
+ var xhr = new XMLHttpRequest();
+ xhr.onreadystatechange = function() {
+ if (xhr.readyState !== 4) {
+ return;
+ }
+ if (!(xhr.status === 200 || xhr.status === 0)) {
+ throw new Error("Manifest " + this.path + " failed to load");
+ }
+ this.data = JSON.parse(xhr.responseText);
+ loaded_callback();
+ }.bind(this);
+ xhr.open("GET", this.path);
+ xhr.send(null);
+ },
+
+ generate: function(loaded_callback) {
+ var xhr = new XMLHttpRequest();
+ xhr.onreadystatechange = function() {
+ if (xhr.readyState !== 4) {
+ return;
+ }
+ if (!(xhr.status === 200 || xhr.status === 0)) {
+ throw new Error("Manifest generation failed");
+ }
+ this.do_load(loaded_callback);
+ }.bind(this);
+ xhr.open("POST", "update_manifest.py");
+ xhr.send(null);
+ },
+
+ by_type:function(type) {
+ if (this.data.items.hasOwnProperty(type)) {
+ return this.data.items[type];
+ } else {
+ return [];
+ }
+ }
+};
+
+function ManifestIterator(manifest, path, test_types) {
+ this.manifest = manifest;
+ this.path = path;
+ this.test_types = test_types;
+ this.test_types_index = -1;
+ this.test_list = null;
+ this.test_index = null;
+}
+
+ManifestIterator.prototype = {
+ next: function() {
+ var manifest_item = null;
+
+ if (this.test_types.length === 0) {
+ return null;
+ }
+
+ while (!manifest_item) {
+ while (this.test_list === null || this.test_index >= this.test_list.length) {
+ this.test_types_index++;
+ if (this.test_types_index >= this.test_types.length) {
+ return null;
+ }
+ this.test_index = 0;
+ this.test_list = this.manifest.by_type(this.test_types[this.test_types_index]);
+ }
+
+ manifest_item = this.test_list[this.test_index++];
+ while (manifest_item && !this.matches(manifest_item)) {
+ manifest_item = this.test_list[this.test_index++];
+ }
+ if (manifest_item) {
+ return this.to_test(manifest_item);
+ }
+ }
+ },
+
+ matches: function(manifest_item) {
+ return manifest_item.url.indexOf(this.path) === 0;
+ },
+
+ to_test: function(manifest_item) {
+ var test = {
+ type: this.test_types[this.test_types_index],
+ url: manifest_item.url
+ };
+ if (manifest_item.hasOwnProperty("ref_url")) {
+ test.ref_type = manifest_item.ref_type;
+ test.ref_url = manifest_item.ref_url;
+ }
+ return test;
+ },
+
+ count: function() {
+ return this.test_types.reduce(function(prev, current) {
+ var matches = this.manifest.by_type(current).filter(function(x) {
+ return this.matches(x);
+ }.bind(this));
+ return prev + matches.length;
+ }.bind(this), 0);
+ }
+};
+
+function VisualOutput(elem, runner) {
+ this.elem = elem;
+ this.runner = runner;
+ this.results_table = null;
+ this.section_wrapper = null;
+ this.results_table = this.elem.querySelector(".results > table");
+ this.section = null;
+ this.manifest_status = this.elem.querySelector("#manifest");
+ this.progress = this.elem.querySelector(".summary .progress");
+ this.meter = this.progress.querySelector(".progress-bar");
+ this.result_count = null;
+ this.json_results_area = this.elem.querySelector("textarea");
+ this.instructions = document.querySelector(".instructions");
+
+ this.elem.style.display = "none";
+ this.runner.manifest_wait_callbacks.push(this.on_manifest_wait.bind(this));
+ this.runner.start_callbacks.push(this.on_start.bind(this));
+ this.runner.result_callbacks.push(this.on_result.bind(this));
+ this.runner.done_callbacks.push(this.on_done.bind(this));
+}
+
+VisualOutput.prototype = {
+ clear: function() {
+ this.result_count = {"PASS":0,
+ "FAIL":0,
+ "ERROR":0,
+ "TIMEOUT":0};
+ for (var p in this.result_count) {
+ if (this.result_count.hasOwnProperty(p)) {
+ this.elem.querySelector("td." + p).textContent = 0;
+ }
+ }
+ if (this.json_results_area) {
+ this.json_results_area.parentNode.removeChild(this.json_results_area);
+ }
+ this.meter.style.width = '0px';
+ this.meter.textContent = '0%';
+ this.manifest_status.style.display = "none";
+ this.elem.querySelector(".jsonResults").style.display = "none";
+ this.results_table.removeChild(this.results_table.tBodies[0]);
+ this.results_table.appendChild(document.createElement("tbody"));
+ },
+
+ on_manifest_wait: function() {
+ this.clear();
+ this.instructions.style.display = "none";
+ this.elem.style.display = "block";
+ this.manifest_status.style.display = "inline";
+ },
+
+ on_start: function() {
+ this.clear();
+ this.instructions.style.display = "none";
+ this.elem.style.display = "block";
+ this.meter.classList.remove("stopped");
+ this.meter.classList.add("progress-striped", "active");
+ },
+
+ on_result: function(test, status, message, subtests) {
+ var row = document.createElement("tr");
+
+ var subtest_pass_count = subtests.reduce(function(prev, current) {
+ return (current.status === "PASS") ? prev + 1 : prev;
+ }, 0);
+ var subtests_count = subtests.length;
+
+ var test_status;
+ if (subtest_pass_count === subtests_count &&
+ (status == "OK" || status == "PASS")) {
+ test_status = "PASS";
+ } else if (subtests_count > 0 && status === "OK") {
+ test_status = "FAIL";
+ } else {
+ test_status = status;
+ }
+
+ subtests.forEach(function(subtest) {
+ if (this.result_count.hasOwnProperty(subtest.status)) {
+ this.result_count[subtest.status] += 1;
+ }
+ }.bind(this));
+ if (this.result_count.hasOwnProperty(status)) {
+ this.result_count[status] += 1;
+ }
+
+ var name_node = row.appendChild(document.createElement("td"));
+ name_node.appendChild(this.test_name_node(test));
+
+ var status_node = row.appendChild(document.createElement("td"));
+ status_node.textContent = test_status;
+ status_node.className = test_status;
+
+ var message_node = row.appendChild(document.createElement("td"));
+ message_node.textContent = message || "";
+
+ var subtests_node = row.appendChild(document.createElement("td"));
+ if (subtests_count) {
+ subtests_node.textContent = subtest_pass_count + "/" + subtests_count;
+ } else {
+ if (status == "PASS") {
+ subtests_node.textContent = "1/1";
+ } else {
+ subtests_node.textContent = "0/1";
+ }
+ }
+
+ var status_arr = ["PASS", "FAIL", "ERROR", "TIMEOUT"];
+ for (var i = 0; i < status_arr.length; i++) {
+ this.elem.querySelector("td." + status_arr[i]).textContent = this.result_count[status_arr[i]];
+ }
+
+ this.results_table.tBodies[0].appendChild(row);
+ this.update_meter(this.runner.progress(), this.runner.results.count(), this.runner.test_count());
+ },
+
+ on_done: function() {
+ this.meter.setAttribute("aria-valuenow", this.meter.getAttribute("aria-valuemax"));
+ this.meter.style.width = "100%";
+ if (this.runner.stop_flag) {
+ this.meter.textContent = "Stopped";
+ this.meter.classList.add("stopped");
+ } else {
+ this.meter.textContent = "Done!";
+ }
+ this.meter.classList.remove("progress-striped", "active");
+ this.runner.test_div.textContent = "";
+ //add the json serialization of the results
+ var a = this.elem.querySelector(".jsonResults");
+ var json = this.runner.results.to_json();
+
+ if (document.getElementById("dumpit").checked) {
+ this.json_results_area = document.createElement("textarea");
+ this.json_results_area.style.width = "100%";
+ this.json_results_area.setAttribute("rows", "50");
+ this.elem.appendChild(this.json_results_area);
+ this.json_results_area.textContent = json;
+ }
+ var blob = new Blob([json], { type: "application/json" });
+ a.href = window.URL.createObjectURL(blob);
+ a.download = "runner-results.json";
+ a.textContent = "Download JSON results";
+ if (!a.getAttribute("download")) a.textContent += " (right-click and save as to download)";
+ a.style.display = "inline";
+ },
+
+ test_name_node: function(test) {
+ if (!test.hasOwnProperty("ref_url")) {
+ return this.link(test.url);
+ } else {
+ var wrapper = document.createElement("span");
+ wrapper.appendChild(this.link(test.url));
+ wrapper.appendChild(document.createTextNode(" " + test.ref_type + " "));
+ wrapper.appendChild(this.link(test.ref_url));
+ return wrapper;
+ }
+ },
+
+ link: function(href) {
+ var link = document.createElement("a");
+ link.href = this.runner.server + href;
+ link.textContent = href;
+ return link;
+ },
+
+ update_meter: function(progress, count, total) {
+ this.meter.setAttribute("aria-valuenow", count);
+ this.meter.setAttribute("aria-valuemax", total);
+ this.meter.textContent = this.meter.style.width = (progress * 100).toFixed(1) + "%";
+ }
+
+};
+
+function ManualUI(elem, runner) {
+ this.elem = elem;
+ this.runner = runner;
+ this.pass_button = this.elem.querySelector("button.pass");
+ this.fail_button = this.elem.querySelector("button.fail");
+ this.ref_buttons = this.elem.querySelector(".reftestUI");
+ this.ref_type = this.ref_buttons.querySelector(".refType");
+ this.test_button = this.ref_buttons.querySelector("button.test");
+ this.ref_button = this.ref_buttons.querySelector("button.ref");
+
+ this.hide();
+
+ this.runner.test_start_callbacks.push(this.on_test_start.bind(this));
+ this.runner.test_pause_callbacks.push(this.hide.bind(this));
+ this.runner.done_callbacks.push(this.on_done.bind(this));
+
+ this.pass_button.onclick = function() {
+ this.disable_buttons();
+ this.runner.on_result("PASS", "", []);
+ }.bind(this);
+
+ this.fail_button.onclick = function() {
+ this.disable_buttons();
+ this.runner.on_result("FAIL", "", []);
+ }.bind(this);
+}
+
+ManualUI.prototype = {
+ show: function() {
+ this.elem.style.display = "block";
+ setTimeout(this.enable_buttons.bind(this), 200);
+ },
+
+ hide: function() {
+ this.elem.style.display = "none";
+ },
+
+ show_ref: function() {
+ this.ref_buttons.style.display = "block";
+ this.test_button.onclick = function() {
+ this.runner.load(this.runner.current_test.url);
+ }.bind(this);
+ this.ref_button.onclick = function() {
+ this.runner.load(this.runner.current_test.ref_url);
+ }.bind(this);
+ },
+
+ hide_ref: function() {
+ this.ref_buttons.style.display = "none";
+ },
+
+ disable_buttons: function() {
+ this.pass_button.disabled = true;
+ this.fail_button.disabled = true;
+ },
+
+ enable_buttons: function() {
+ this.pass_button.disabled = false;
+ this.fail_button.disabled = false;
+ },
+
+ on_test_start: function(test) {
+ if (test.type == "manual" || test.type == "reftest") {
+ this.show();
+ } else {
+ this.hide();
+ }
+ if (test.type == "reftest") {
+ this.show_ref();
+ this.ref_type.textContent = test.ref_type === "==" ? "equal" : "unequal";
+ } else {
+ this.hide_ref();
+ }
+ },
+
+ on_done: function() {
+ this.hide();
+ }
+};
+
+function TestControl(elem, runner) {
+ this.elem = elem;
+ this.path_input = this.elem.querySelector(".path");
+ this.pause_button = this.elem.querySelector("button.togglePause");
+ this.start_button = this.elem.querySelector("button.toggleStart");
+ this.type_checkboxes = Array.prototype.slice.call(
+ this.elem.querySelectorAll("input[type=checkbox].test-type"));
+ this.type_checkboxes.forEach(function(elem) {
+ elem.addEventListener("click", function() {
+ this.start_button.disabled = this.get_test_types().length < 1;
+ }.bind(this),
+ false);
+ }.bind(this));
+ this.timeout_input = this.elem.querySelector(".timeout_multiplier");
+ this.render_checkbox = this.elem.querySelector(".render");
+ this.runner = runner;
+ this.runner.done_callbacks.push(this.on_done.bind(this));
+ this.set_start();
+}
+
+TestControl.prototype = {
+ set_start: function() {
+ this.start_button.disabled = this.get_test_types().length < 1;
+ this.pause_button.disabled = true;
+ this.start_button.textContent = "Start";
+ this.path_input.disabled = false;
+ this.type_checkboxes.forEach(function(elem) {
+ elem.disabled = false;
+ });
+ this.start_button.onclick = function() {
+ var path = this.get_path();
+ var test_types = this.get_test_types();
+ var settings = this.get_testharness_settings();
+ this.runner.start(path, test_types, settings);
+ this.set_stop();
+ this.set_pause();
+ }.bind(this);
+ },
+
+ set_stop: function() {
+ clearTimeout(this.runner.timeout);
+ this.pause_button.disabled = false;
+ this.start_button.textContent = "Stop";
+ this.path_input.disabled = true;
+ this.type_checkboxes.forEach(function(elem) {
+ elem.disabled = true;
+ });
+ this.start_button.onclick = function() {
+ this.runner.stop_flag = true;
+ this.runner.done();
+ }.bind(this);
+ },
+
+ set_pause: function() {
+ this.pause_button.textContent = "Pause";
+ this.pause_button.onclick = function() {
+ this.runner.pause();
+ this.set_resume();
+ }.bind(this);
+ },
+
+ set_resume: function() {
+ this.pause_button.textContent = "Resume";
+ this.pause_button.onclick = function() {
+ this.runner.unpause();
+ this.set_pause();
+ }.bind(this);
+
+ },
+
+ get_path: function() {
+ return this.path_input.value;
+ },
+
+ get_test_types: function() {
+ return this.type_checkboxes.filter(function(elem) {
+ return elem.checked;
+ }).map(function(elem) {
+ return elem.value;
+ });
+ },
+
+ get_testharness_settings: function() {
+ return {timeout_multiplier: parseFloat(this.timeout_input.value),
+ output: this.render_checkbox.checked};
+ },
+
+ on_done: function() {
+ this.set_pause();
+ this.set_start();
+ }
+};
+
+function Results(runner) {
+ this.test_results = null;
+ this.runner = runner;
+
+ this.runner.start_callbacks.push(this.on_start.bind(this));
+}
+
+Results.prototype = {
+ on_start: function() {
+ this.test_results = [];
+ },
+
+ set: function(test, status, message, subtests) {
+ this.test_results.push({"test":test,
+ "subtests":subtests,
+ "status":status,
+ "message":message});
+ },
+
+ count: function() {
+ return this.test_results.length;
+ },
+
+ to_json: function() {
+ var data = {
+ "results": this.test_results.map(function(result) {
+ var rv = {"test":(result.test.hasOwnProperty("ref_url") ?
+ [result.test.url, result.test.ref_type, result.test.ref_url] :
+ result.test.url),
+ "subtests":result.subtests,
+ "status":result.status,
+ "message":result.message};
+ return rv;
+ })
+ };
+ return JSON.stringify(data, null, 2);
+ }
+};
+
+function Runner(manifest_path) {
+ this.server = location.protocol + "//" + location.host;
+ this.manifest = new Manifest(manifest_path);
+ this.path = null;
+ this.test_types = null;
+ this.manifest_iterator = null;
+
+ this.test_window = null;
+ this.test_div = document.getElementById('test_url');
+ this.current_test = null;
+ this.timeout = null;
+ this.num_tests = null;
+ this.pause_flag = false;
+ this.stop_flag = false;
+ this.done_flag = false;
+
+ this.manifest_wait_callbacks = [];
+ this.start_callbacks = [];
+ this.test_start_callbacks = [];
+ this.test_pause_callbacks = [];
+ this.result_callbacks = [];
+ this.done_callbacks = [];
+
+ this.results = new Results(this);
+
+ this.start_after_manifest_load = false;
+ this.manifest.load(this.manifest_loaded.bind(this));
+}
+
+Runner.prototype = {
+ test_timeout: 20000, //ms
+
+ currentTest: function() {
+ return this.manifest[this.mTestCount];
+ },
+
+ open_test_window: function() {
+ this.test_window = window.open("about:blank", 800, 600);
+ },
+
+ manifest_loaded: function() {
+ if (this.start_after_manifest_load) {
+ this.do_start();
+ }
+ },
+
+ start: function(path, test_types, testharness_settings) {
+ this.pause_flag = false;
+ this.stop_flag = false;
+ this.done_flag = false;
+ this.path = path;
+ this.test_types = test_types;
+ window.testharness_properties = testharness_settings;
+ this.manifest_iterator = new ManifestIterator(this.manifest, this.path, this.test_types);
+ this.num_tests = null;
+
+ if (this.manifest.data === null) {
+ this.wait_for_manifest();
+ } else {
+ this.do_start();
+ }
+ },
+
+ wait_for_manifest: function() {
+ this.start_after_manifest_load = true;
+ this.manifest_wait_callbacks.forEach(function(callback) {
+ callback();
+ });
+ },
+
+ do_start: function() {
+ if (this.manifest_iterator.count() > 0) {
+ this.open_test_window();
+ this.start_callbacks.forEach(function(callback) {
+ callback();
+ });
+ this.run_next_test();
+ } else {
+ var tests = "tests";
+ if (this.test_types.length < 3) {
+ tests = this.test_types.join(" tests or ") + " tests";
+ }
+ var message = "No " + tests + " found in this path."
+ document.querySelector(".path").setCustomValidity(message);
+ this.done();
+ }
+ },
+
+ pause: function() {
+ this.pause_flag = true;
+ this.test_pause_callbacks.forEach(function(callback) {
+ callback(this.current_test);
+ }.bind(this));
+ },
+
+ unpause: function() {
+ this.pause_flag = false;
+ this.run_next_test();
+ },
+
+ on_result: function(status, message, subtests) {
+ clearTimeout(this.timeout);
+ this.results.set(this.current_test, status, message, subtests);
+ this.result_callbacks.forEach(function(callback) {
+ callback(this.current_test, status, message, subtests);
+ }.bind(this));
+ this.run_next_test();
+ },
+
+ on_timeout: function() {
+ this.on_result("TIMEOUT", "", []);
+ },
+
+ done: function() {
+ this.done_flag = true;
+ if (this.test_window) {
+ this.test_window.close();
+ }
+ this.done_callbacks.forEach(function(callback) {
+ callback();
+ });
+ },
+
+ run_next_test: function() {
+ if (this.pause_flag) {
+ return;
+ }
+ var next_test = this.manifest_iterator.next();
+ if (next_test === null||this.done_flag) {
+ this.done();
+ return;
+ }
+
+ this.current_test = next_test;
+
+ if (next_test.type === "testharness") {
+ this.timeout = setTimeout(this.on_timeout.bind(this),
+ this.test_timeout * window.testharness_properties.timeout_multiplier);
+ }
+ this.test_div.textContent = this.current_test.url;
+ this.load(this.current_test.url);
+
+ this.test_start_callbacks.forEach(function(callback) {
+ callback(this.current_test);
+ }.bind(this));
+ },
+
+ load: function(path) {
+ if (this.test_window.location === null) {
+ this.open_test_window();
+ }
+ this.test_window.location.href = this.server + path;
+ },
+
+ progress: function() {
+ return this.results.count() / this.test_count();
+ },
+
+ test_count: function() {
+ if (this.num_tests === null) {
+ this.num_tests = this.manifest_iterator.count();
+ }
+ return this.num_tests;
+ }
+
+};
+
+
+function parseOptions() {
+ var options = {
+ test_types: ["testharness", "reftest", "manual"]
+ };
+
+ var optionstrings = location.search.substring(1).split("&");
+ for (var i = 0, il = optionstrings.length; i < il; ++i) {
+ var opt = optionstrings[i];
+ //TODO: fix this for complex-valued options
+ options[opt.substring(0, opt.indexOf("="))] =
+ opt.substring(opt.indexOf("=") + 1);
+ }
+ return options;
+}
+
+function setup() {
+ var options = parseOptions();
+
+ if (options.path) {
+ document.getElementById('path').value = options.path;
+ }
+
+ runner = new Runner("/MANIFEST.json", options);
+ var test_control = new TestControl(document.getElementById("testControl"), runner);
+ new ManualUI(document.getElementById("manualUI"), runner);
+ new VisualOutput(document.getElementById("output"), runner);
+
+ if (options.autorun === "1") {
+ runner.start(test_control.get_path(),
+ test_control.get_test_types(),
+ test_control.get_testharness_settings());
+ return;
+ }
+}
+
+window.completion_callback = function(tests, status) {
+ var harness_status_map = {0:"OK", 1:"ERROR", 2:"TIMEOUT"};
+ var subtest_status_map = {0:"PASS", 1:"FAIL", 2:"TIMEOUT", 3:"NOTRUN"};
+
+ // this ugly hack is because IE really insists on holding on to the objects it creates in
+ // other windows, and on losing track of them when the window gets closed
+ var subtest_results = JSON.parse(JSON.stringify(
+ tests.map(function (test) {
+ return {name: test.name,
+ status: subtest_status_map[test.status],
+ message: test.message};
+ })
+ ));
+
+ runner.on_result(harness_status_map[status.status],
+ status.message,
+ subtest_results);
+};
+
+window.addEventListener("DOMContentLoaded", setup, false);
+})();
diff --git a/tests/wpt/web-platform-tests/tools/runner/update_manifest.py b/tests/wpt/web-platform-tests/tools/runner/update_manifest.py
new file mode 100644
index 00000000000..cf6d1093b27
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/runner/update_manifest.py
@@ -0,0 +1,19 @@
+import imp
+import json
+import os
+import sys
+
+here = os.path.dirname(__file__)
+localpaths = imp.load_source("localpaths", os.path.abspath(os.path.join(here, os.pardir, "localpaths.py")))
+
+root = localpaths.repo_root
+
+import manifest
+
+def main(request, response):
+ path = os.path.join(root, "MANIFEST.json")
+ manifest_file = manifest.manifest.load(root, path)
+ manifest.update.update(root, "/", manifest_file)
+ manifest.manifest.write(manifest_file, path)
+
+ return [("Content-Type", "application/json")], json.dumps({"url": "/MANIFEST.json"})
diff --git a/tests/wpt/web-platform-tests/tools/scripts/id2path.js b/tests/wpt/web-platform-tests/tools/scripts/id2path.js
new file mode 100644
index 00000000000..39b8d644bc5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/scripts/id2path.js
@@ -0,0 +1,12 @@
+
+var fs = require("fs")
+, pth = require("path")
+, id = process.argv[2]
+;
+
+if (!id) {
+ console.log("Missing ID");
+ process.exit(1);
+}
+
+console.log(JSON.parse(fs.readFileSync(pth.join(__dirname, "id2path.json"), "utf8"))[id]);
diff --git a/tests/wpt/web-platform-tests/tools/scripts/id2path.json b/tests/wpt/web-platform-tests/tools/scripts/id2path.json
new file mode 100644
index 00000000000..491bd8694c5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/scripts/id2path.json
@@ -0,0 +1,822 @@
+{
+ "introduction": "microdata/introduction",
+ "background": "html/introduction/background",
+ "audience": "html/introduction/audience",
+ "scope": "html/introduction/scope",
+ "history-0": "html/introduction/history-0",
+ "design-notes": "html/introduction/design-notes",
+ "serializability-of-script-execution": "html/introduction/design-notes/serializability-of-script-execution",
+ "compliance-with-other-specifications": "html/introduction/design-notes/compliance-with-other-specifications",
+ "html-vs-xhtml": "html/introduction/html-vs-xhtml",
+ "structure-of-this-specification": "html/introduction/structure-of-this-specification",
+ "how-to-read-this-specification": "html/introduction/structure-of-this-specification/how-to-read-this-specification",
+ "typographic-conventions": "html/introduction/structure-of-this-specification/typographic-conventions",
+ "fingerprint": "html/introduction/fingerprint",
+ "a-quick-introduction-to-html": "html/introduction/a-quick-introduction-to-html",
+ "writing-secure-applications-with-html": "html/introduction/a-quick-introduction-to-html/writing-secure-applications-with-html",
+ "common-pitfalls-to-avoid-when-using-the-scripting-apis": "html/introduction/a-quick-introduction-to-html/common-pitfalls-to-avoid-when-using-the-scripting-apis",
+ "conformance-requirements-for-authors": "html/introduction/conformance-requirements-for-authors",
+ "presentational-markup": "html/introduction/conformance-requirements-for-authors/presentational-markup",
+ "syntax-errors": "html/introduction/conformance-requirements-for-authors/syntax-errors",
+ "restrictions-on-content-models-and-on-attribute-values": "html/introduction/conformance-requirements-for-authors/restrictions-on-content-models-and-on-attribute-values",
+ "suggested-reading": "html/introduction/suggested-reading",
+ "infrastructure": "html/infrastructure",
+ "terminology": "microdata/terminology",
+ "resources": "html/infrastructure/terminology/resources",
+ "xml": "html/infrastructure/terminology/xml",
+ "dom-trees": "html/infrastructure/terminology/dom-trees",
+ "scripting-0": "html/infrastructure/terminology/scripting-0",
+ "plugins": "html/infrastructure/terminology/plugins",
+ "character-encodings": "html/infrastructure/terminology/character-encodings",
+ "conformance-requirements": "microdata/conformance-requirements",
+ "conformance-classes": "html/infrastructure/conformance-requirements/conformance-classes",
+ "dependencies": "microdata/dependencies",
+ "extensibility": "html/infrastructure/conformance-requirements/extensibility",
+ "case-sensitivity-and-string-comparison": "html/infrastructure/case-sensitivity-and-string-comparison",
+ "utf-8": "html/infrastructure/utf-8",
+ "common-microsyntaxes": "html/infrastructure/common-microsyntaxes",
+ "common-parser-idioms": "html/infrastructure/common-microsyntaxes/common-parser-idioms",
+ "boolean-attributes": "html/infrastructure/common-microsyntaxes/boolean-attributes",
+ "keywords-and-enumerated-attributes": "html/infrastructure/common-microsyntaxes/keywords-and-enumerated-attributes",
+ "numbers": "html/infrastructure/common-microsyntaxes/numbers",
+ "signed-integers": "html/infrastructure/common-microsyntaxes/numbers",
+ "non-negative-integers": "html/infrastructure/common-microsyntaxes/numbers",
+ "floating-point-numbers": "html/infrastructure/common-microsyntaxes/numbers",
+ "percentages-and-dimensions": "html/infrastructure/common-microsyntaxes/numbers",
+ "lists-of-integers": "html/infrastructure/common-microsyntaxes/numbers",
+ "lists-of-dimensions": "html/infrastructure/common-microsyntaxes/numbers",
+ "dates-and-times": "html/infrastructure/common-microsyntaxes/dates-and-times",
+ "months": "html/infrastructure/common-microsyntaxes/dates-and-times",
+ "dates": "html/infrastructure/common-microsyntaxes/dates-and-times",
+ "yearless-dates": "html/infrastructure/common-microsyntaxes/dates-and-times",
+ "times": "html/infrastructure/common-microsyntaxes/dates-and-times",
+ "local-dates-and-times": "html/infrastructure/common-microsyntaxes/dates-and-times",
+ "time-zones": "html/infrastructure/common-microsyntaxes/dates-and-times",
+ "global-dates-and-times": "html/infrastructure/common-microsyntaxes/dates-and-times",
+ "weeks": "html/infrastructure/common-microsyntaxes/dates-and-times",
+ "durations": "html/infrastructure/common-microsyntaxes/dates-and-times",
+ "vaguer-moments-in-time": "html/infrastructure/common-microsyntaxes/dates-and-times",
+ "colors": "html/infrastructure/common-microsyntaxes/colors",
+ "space-separated-tokens": "html/infrastructure/common-microsyntaxes/space-separated-tokens",
+ "comma-separated-tokens": "html/infrastructure/common-microsyntaxes/comma-separated-tokens",
+ "syntax-references": "html/infrastructure/common-microsyntaxes/syntax-references",
+ "mq": "html/infrastructure/common-microsyntaxes/mq",
+ "urls": "html/infrastructure/urls",
+ "terminology-0": "html/infrastructure/urls/terminology-0",
+ "parsing-urls": "html/infrastructure/urls/parsing-urls",
+ "base-urls": "html/infrastructure/urls/base-urls",
+ "resolving-urls": "html/infrastructure/urls/resolving-urls",
+ "url-manipulation-and-creation": "html/infrastructure/urls/url-manipulation-and-creation",
+ "dynamic-changes-to-base-urls": "html/infrastructure/urls/dynamic-changes-to-base-urls",
+ "interfaces-for-url-manipulation": "html/infrastructure/urls/interfaces-for-url-manipulation",
+ "fetching-resources": "html/infrastructure/fetching-resources",
+ "terminology-1": "html/infrastructure/fetching-resources/terminology-1",
+ "processing-model": "html/infrastructure/fetching-resources/processing-model",
+ "encrypted-http-and-related-security-concerns": "html/infrastructure/fetching-resources/encrypted-http-and-related-security-concerns",
+ "content-type-sniffing": "html/infrastructure/fetching-resources/content-type-sniffing",
+ "extracting-character-encodings-from-meta-elements": "html/infrastructure/fetching-resources/extracting-character-encodings-from-meta-elements",
+ "cors-settings-attributes": "html/infrastructure/fetching-resources/cors-settings-attributes",
+ "cors-enabled-fetch": "html/infrastructure/fetching-resources/cors-enabled-fetch",
+ "common-dom-interfaces": "html/infrastructure/common-dom-interfaces",
+ "reflecting-content-attributes-in-idl-attributes": "html/infrastructure/common-dom-interfaces/reflecting-content-attributes-in-idl-attributes",
+ "collections": "html/infrastructure/common-dom-interfaces/collections",
+ "htmlallcollection": "html/infrastructure/common-dom-interfaces/collections",
+ "htmlformcontrolscollection": "html/infrastructure/common-dom-interfaces/collections",
+ "htmloptionscollection": "html/infrastructure/common-dom-interfaces/collections",
+ "domstringmap": "html/infrastructure/common-dom-interfaces/domstringmap",
+ "transferable-objects": "html/infrastructure/common-dom-interfaces/transferable-objects",
+ "safe-passing-of-structured-data": "html/infrastructure/common-dom-interfaces/safe-passing-of-structured-data",
+ "garbage-collection": "html/infrastructure/common-dom-interfaces/garbage-collection",
+ "namespaces": "html/infrastructure/namespaces",
+ "dom": "html/dom",
+ "documents": "html/dom/documents",
+ "the-document-object": "html/dom/documents/the-document-object",
+ "security-document": "html/dom/documents/security-document",
+ "resource-metadata-management": "html/dom/documents/resource-metadata-management",
+ "dom-tree-accessors": "html/dom/documents/dom-tree-accessors",
+ "loading-xml-documents": "html/dom/documents/loading-xml-documents",
+ "elements": "html/dom/elements",
+ "semantics-0": "html/dom/elements/semantics-0",
+ "elements-in-the-dom": "html/dom/elements/elements-in-the-dom",
+ "global-attributes": "html/dom/elements/global-attributes",
+ "the-id-attribute": "html/dom/elements/global-attributes",
+ "the-title-attribute": "html/dom/elements/global-attributes",
+ "the-lang-and-xml:lang-attributes": "html/dom/elements/global-attributes",
+ "the-translate-attribute": "html/dom/elements/global-attributes",
+ "the-xml:base-attribute-(xml-only)": "html/dom/elements/global-attributes",
+ "the-dir-attribute": "html/dom/elements/global-attributes",
+ "classes": "html/dom/elements/global-attributes",
+ "the-style-attribute": "html/dom/elements/global-attributes",
+ "embedding-custom-non-visible-data-with-the-data-*-attributes": "html/dom/elements/global-attributes",
+ "element-definitions": "html/dom/elements/element-definitions",
+ "attributes": "html/dom/elements/element-definitions",
+ "content-models": "html/dom/elements/content-models",
+ "kinds-of-content": "html/dom/elements/content-models",
+ "metadata-content": "html/dom/elements/content-models",
+ "flow-content": "html/dom/elements/content-models",
+ "sectioning-content": "html/dom/elements/content-models",
+ "heading-content": "html/dom/elements/content-models",
+ "phrasing-content": "html/dom/elements/content-models",
+ "embedded-content": "html/dom/elements/content-models",
+ "interactive-content": "html/dom/elements/content-models",
+ "palpable-content": "html/dom/elements/content-models",
+ "transparent-content-models": "html/dom/elements/content-models",
+ "paragraphs": "html/dom/elements/content-models",
+ "requirements-relating-to-bidirectional-algorithm-formatting-characters": "html/dom/elements/requirements-relating-to-bidirectional-algorithm-formatting-characters",
+ "wai-aria": "html/dom/elements/wai-aria",
+ "aria-role-attribute": "html/dom/elements/wai-aria",
+ "state-and-property-attributes": "html/dom/elements/wai-aria",
+ "sec-strong-native-semantics": "html/dom/elements/wai-aria",
+ "sec-implicit-aria-semantics": "html/dom/elements/wai-aria",
+ "interactions-with-xpath-and-xslt": "html/dom/interactions-with-xpath-and-xslt",
+ "dynamic-markup-insertion": "html/dom/dynamic-markup-insertion",
+ "opening-the-input-stream": "html/dom/dynamic-markup-insertion/opening-the-input-stream",
+ "closing-the-input-stream": "html/dom/dynamic-markup-insertion/closing-the-input-stream",
+ "document.write()": "html/dom/dynamic-markup-insertion/document-write",
+ "document.writeln()": "html/dom/dynamic-markup-insertion/document-writeln",
+ "semantics": "html/semantics",
+ "the-root-element": "html/semantics/the-root-element",
+ "the-html-element": "html/semantics/the-root-element/the-html-element",
+ "document-metadata": "html/semantics/document-metadata",
+ "the-head-element": "html/semantics/document-metadata/the-head-element",
+ "the-title-element": "html/semantics/document-metadata/the-title-element",
+ "the-base-element": "html/semantics/document-metadata/the-base-element",
+ "the-link-element": "html/semantics/document-metadata/the-link-element",
+ "the-meta-element": "html/semantics/document-metadata/the-meta-element",
+ "standard-metadata-names": "html/semantics/document-metadata/the-meta-element",
+ "other-metadata-names": "html/semantics/document-metadata/the-meta-element",
+ "pragma-directives": "html/semantics/document-metadata/the-meta-element",
+ "other-pragma-directives": "html/semantics/document-metadata/the-meta-element",
+ "charset": "html/semantics/document-metadata/the-meta-element",
+ "the-style-element": "html/semantics/document-metadata/the-style-element",
+ "styling": "html/semantics/document-metadata/styling",
+ "scripting-1": "html/semantics/scripting-1",
+ "the-script-element": "html/semantics/scripting-1/the-script-element",
+ "scriptingLanguages": "html/semantics/scripting-1/the-script-element",
+ "restrictions-for-contents-of-script-elements": "html/semantics/scripting-1/the-script-element",
+ "inline-documentation-for-external-scripts": "html/semantics/scripting-1/the-script-element",
+ "scriptTagXSLT": "html/semantics/scripting-1/the-script-element",
+ "the-noscript-element": "html/semantics/scripting-1/the-noscript-element",
+ "sections": "html/semantics/sections",
+ "the-body-element": "html/semantics/sections/the-body-element",
+ "the-article-element": "html/semantics/sections/the-article-element",
+ "the-section-element": "html/semantics/sections/the-section-element",
+ "the-nav-element": "html/semantics/sections/the-nav-element",
+ "the-aside-element": "html/semantics/sections/the-aside-element",
+ "the-h1,-h2,-h3,-h4,-h5,-and-h6-elements": "html/semantics/sections/the-h1-h2-h3-h4-h5-and-h6-elements",
+ "the-hgroup-element": "html/semantics/sections/the-hgroup-element",
+ "the-header-element": "html/semantics/sections/the-header-element",
+ "the-footer-element": "html/semantics/sections/the-footer-element",
+ "the-address-element": "html/semantics/sections/the-address-element",
+ "headings-and-sections": "html/semantics/sections/headings-and-sections",
+ "outlines": "html/semantics/sections/headings-and-sections",
+ "usage-summary-0": "html/semantics/sections/usage-summary-0",
+ "grouping-content": "html/semantics/grouping-content",
+ "the-p-element": "html/semantics/grouping-content/the-p-element",
+ "the-hr-element": "html/semantics/grouping-content/the-hr-element",
+ "the-pre-element": "html/semantics/grouping-content/the-pre-element",
+ "the-blockquote-element": "html/semantics/grouping-content/the-blockquote-element",
+ "the-ol-element": "html/semantics/grouping-content/the-ol-element",
+ "the-ul-element": "html/semantics/grouping-content/the-ul-element",
+ "the-li-element": "html/semantics/grouping-content/the-li-element",
+ "the-dl-element": "html/semantics/grouping-content/the-dl-element",
+ "the-dt-element": "html/semantics/grouping-content/the-dt-element",
+ "the-dd-element": "html/semantics/grouping-content/the-dd-element",
+ "the-figure-element": "html/semantics/grouping-content/the-figure-element",
+ "the-figcaption-element": "html/semantics/grouping-content/the-figcaption-element",
+ "the-div-element": "html/semantics/grouping-content/the-div-element",
+ "text-level-semantics": "html/semantics/text-level-semantics",
+ "the-a-element": "html/semantics/text-level-semantics/the-a-element",
+ "the-em-element": "html/semantics/text-level-semantics/the-em-element",
+ "the-strong-element": "html/semantics/text-level-semantics/the-strong-element",
+ "the-small-element": "html/semantics/text-level-semantics/the-small-element",
+ "the-s-element": "html/semantics/text-level-semantics/the-s-element",
+ "the-cite-element": "html/semantics/text-level-semantics/the-cite-element",
+ "the-q-element": "html/semantics/text-level-semantics/the-q-element",
+ "the-dfn-element": "html/semantics/text-level-semantics/the-dfn-element",
+ "the-abbr-element": "html/semantics/text-level-semantics/the-abbr-element",
+ "the-time-element": "html/semantics/text-level-semantics/the-time-element",
+ "the-code-element": "html/semantics/text-level-semantics/the-code-element",
+ "the-var-element": "html/semantics/text-level-semantics/the-var-element",
+ "the-samp-element": "html/semantics/text-level-semantics/the-samp-element",
+ "the-kbd-element": "html/semantics/text-level-semantics/the-kbd-element",
+ "the-sub-and-sup-elements": "html/semantics/text-level-semantics/the-sub-and-sup-elements",
+ "the-i-element": "html/semantics/text-level-semantics/the-i-element",
+ "the-b-element": "html/semantics/text-level-semantics/the-b-element",
+ "the-u-element": "html/semantics/text-level-semantics/the-u-element",
+ "the-mark-element": "html/semantics/text-level-semantics/the-mark-element",
+ "the-ruby-element": "html/semantics/text-level-semantics/the-ruby-element",
+ "the-rt-element": "html/semantics/text-level-semantics/the-rt-element",
+ "the-rp-element": "html/semantics/text-level-semantics/the-rp-element",
+ "the-bdi-element": "html/semantics/text-level-semantics/the-bdi-element",
+ "the-bdo-element": "html/semantics/text-level-semantics/the-bdo-element",
+ "the-span-element": "html/semantics/text-level-semantics/the-span-element",
+ "the-br-element": "html/semantics/text-level-semantics/the-br-element",
+ "the-wbr-element": "html/semantics/text-level-semantics/the-wbr-element",
+ "usage-summary": "html/semantics/text-level-semantics/usage-summary",
+ "edits": "html/semantics/edits",
+ "the-ins-element": "html/semantics/edits/the-ins-element",
+ "the-del-element": "html/semantics/edits/the-del-element",
+ "attributes-common-to-ins-and-del-elements": "html/semantics/edits/attributes-common-to-ins-and-del-elements",
+ "edits-and-paragraphs": "html/semantics/edits/edits-and-paragraphs",
+ "edits-and-lists": "html/semantics/edits/edits-and-lists",
+ "edits-and-tables": "html/semantics/edits/edits-and-tables",
+ "embedded-content-0": "html/semantics/embedded-content-0",
+ "the-img-element": "html/semantics/embedded-content-0/the-img-element",
+ "alt": "html/semantics/embedded-content-0/the-img-element",
+ "general-guidelines": "html/semantics/embedded-content-0/the-img-element",
+ "a-link-or-button-containing-nothing-but-the-image": "html/semantics/embedded-content-0/the-img-element",
+ "a-phrase-or-paragraph-with-an-alternative-graphical-representation:-charts,-diagrams,-graphs,-maps,-illustrations": "html/semantics/embedded-content-0/the-img-element",
+ "a-short-phrase-or-label-with-an-alternative-graphical-representation:-icons,-logos": "html/semantics/embedded-content-0/the-img-element",
+ "text-that-has-been-rendered-to-a-graphic-for-typographical-effect": "html/semantics/embedded-content-0/the-img-element",
+ "a-graphical-representation-of-some-of-the-surrounding-text": "html/semantics/embedded-content-0/the-img-element",
+ "a-purely-decorative-image-that-doesn't-add-any-information": "html/semantics/embedded-content-0/the-img-element",
+ "a-group-of-images-that-form-a-single-larger-picture-with-no-links": "html/semantics/embedded-content-0/the-img-element",
+ "a-group-of-images-that-form-a-single-larger-picture-with-links": "html/semantics/embedded-content-0/the-img-element",
+ "a-key-part-of-the-content": "html/semantics/embedded-content-0/the-img-element",
+ "an-image-not-intended-for-the-user": "html/semantics/embedded-content-0/the-img-element",
+ "guidance-for-markup-generators": "html/semantics/embedded-content-0/the-img-element",
+ "guidance-for-conformance-checkers": "html/semantics/embedded-content-0/the-img-element",
+ "the-iframe-element": "html/semantics/embedded-content-0/the-iframe-element",
+ "the-embed-element": "html/semantics/embedded-content-0/the-embed-element",
+ "the-object-element": "html/semantics/embedded-content-0/the-object-element",
+ "the-param-element": "html/semantics/embedded-content-0/the-param-element",
+ "the-video-element": "html/semantics/embedded-content-0/the-video-element",
+ "the-audio-element": "html/semantics/embedded-content-0/the-audio-element",
+ "the-source-element": "html/semantics/embedded-content-0/the-source-element",
+ "the-track-element": "html/semantics/embedded-content-0/the-track-element",
+ "media-elements": "html/semantics/embedded-content-0/media-elements",
+ "error-codes": "html/semantics/embedded-content-0/media-elements",
+ "location-of-the-media-resource": "html/semantics/embedded-content-0/media-elements",
+ "mime-types": "html/semantics/embedded-content-0/media-elements",
+ "network-states": "html/semantics/embedded-content-0/media-elements",
+ "loading-the-media-resource": "html/semantics/embedded-content-0/media-elements",
+ "offsets-into-the-media-resource": "html/semantics/embedded-content-0/media-elements",
+ "ready-states": "html/semantics/embedded-content-0/media-elements",
+ "playing-the-media-resource": "html/semantics/embedded-content-0/media-elements",
+ "seeking": "html/semantics/embedded-content-0/media-elements",
+ "media-resources-with-multiple-media-tracks": "html/semantics/embedded-content-0/media-elements",
+ "audiotracklist-and-videotracklist-objects": "html/semantics/embedded-content-0/media-elements",
+ "selecting-specific-audio-and-video-tracks-declaratively": "html/semantics/embedded-content-0/media-elements",
+ "synchronising-multiple-media-elements": "html/semantics/embedded-content-0/media-elements",
+ "introduction-0": "html/semantics/embedded-content-0/media-elements",
+ "media-controllers": "html/semantics/embedded-content-0/media-elements",
+ "assigning-a-media-controller-declaratively": "html/semantics/embedded-content-0/media-elements",
+ "timed-text-tracks": "html/semantics/embedded-content-0/media-elements",
+ "text-track-model": "html/semantics/embedded-content-0/media-elements",
+ "sourcing-in-band-text-tracks": "html/semantics/embedded-content-0/media-elements",
+ "sourcing-out-of-band-text-tracks": "html/semantics/embedded-content-0/media-elements",
+ "guidelines-for-exposing-cues-in-various-formats-as-text-track-cues": "html/semantics/embedded-content-0/media-elements",
+ "text-track-api": "html/semantics/embedded-content-0/media-elements",
+ "text-tracks-describing-chapters": "html/semantics/embedded-content-0/media-elements",
+ "cue-events": "html/semantics/embedded-content-0/media-elements",
+ "user-interface": "html/semantics/embedded-content-0/media-elements",
+ "time-ranges": "html/semantics/embedded-content-0/media-elements",
+ "event-definitions": "html/semantics/embedded-content-0/media-elements",
+ "mediaevents": "html/semantics/embedded-content-0/media-elements",
+ "security-and-privacy-considerations": "html/semantics/embedded-content-0/media-elements",
+ "best-practices-for-authors-using-media-elements": "html/semantics/embedded-content-0/media-elements",
+ "best-practices-for-implementors-of-media-elements": "html/semantics/embedded-content-0/media-elements",
+ "the-canvas-element": "html/semantics/embedded-content-0/the-canvas-element",
+ "color-spaces-and-color-correction": "html/semantics/embedded-content-0/the-canvas-element",
+ "security-with-canvas-elements": "html/semantics/embedded-content-0/the-canvas-element",
+ "the-map-element": "html/semantics/embedded-content-0/the-map-element",
+ "the-area-element": "html/semantics/embedded-content-0/the-area-element",
+ "image-maps": "html/semantics/embedded-content-0/image-maps",
+ "authoring": "html/semantics/embedded-content-0/image-maps",
+ "processing-model-0": "html/semantics/embedded-content-0/image-maps",
+ "mathml": "html/semantics/embedded-content-0/mathml",
+ "svg": "html/semantics/embedded-content-0/svg",
+ "dimension-attributes": "html/semantics/embedded-content-0/dimension-attributes",
+ "tabular-data": "html/semantics/tabular-data",
+ "the-table-element": "html/semantics/tabular-data/the-table-element",
+ "table-descriptions-techniques": "html/semantics/tabular-data/the-table-element",
+ "table-layout-techniques": "html/semantics/tabular-data/the-table-element",
+ "the-caption-element": "html/semantics/tabular-data/the-caption-element",
+ "the-colgroup-element": "html/semantics/tabular-data/the-colgroup-element",
+ "the-col-element": "html/semantics/tabular-data/the-col-element",
+ "the-tbody-element": "html/semantics/tabular-data/the-tbody-element",
+ "the-thead-element": "html/semantics/tabular-data/the-thead-element",
+ "the-tfoot-element": "html/semantics/tabular-data/the-tfoot-element",
+ "the-tr-element": "html/semantics/tabular-data/the-tr-element",
+ "the-td-element": "html/semantics/tabular-data/the-td-element",
+ "the-th-element": "html/semantics/tabular-data/the-th-element",
+ "attributes-common-to-td-and-th-elements": "html/semantics/tabular-data/attributes-common-to-td-and-th-elements",
+ "processing-model-1": "html/semantics/tabular-data/processing-model-1",
+ "forming-a-table": "html/semantics/tabular-data/processing-model-1",
+ "header-and-data-cell-semantics": "html/semantics/tabular-data/processing-model-1",
+ "examples": "canvas2d/examples",
+ "forms": "html/semantics/forms",
+ "introduction-1": "html/semantics/forms/introduction-1",
+ "writing-a-form's-user-interface": "html/semantics/forms/introduction-1",
+ "implementing-the-server-side-processing-for-a-form": "html/semantics/forms/introduction-1",
+ "configuring-a-form-to-communicate-with-a-server": "html/semantics/forms/introduction-1",
+ "client-side-form-validation": "html/semantics/forms/introduction-1",
+ "enabling-client-side-automatic-filling-of-form-controls": "html/semantics/forms/introduction-1",
+ "improving-the-user-experience-on-mobile-devices": "html/semantics/forms/introduction-1",
+ "the-difference-between-the-field-type,-the-autofill-field-name,-and-the-input-modality": "html/semantics/forms/introduction-1",
+ "input-author-notes": "html/semantics/forms/introduction-1",
+ "categories": "html/semantics/forms/categories",
+ "the-form-element": "html/semantics/forms/the-form-element",
+ "the-fieldset-element": "html/semantics/forms/the-fieldset-element",
+ "the-legend-element": "html/semantics/forms/the-legend-element",
+ "the-label-element": "html/semantics/forms/the-label-element",
+ "the-input-element": "html/semantics/forms/the-input-element",
+ "states-of-the-type-attribute": "html/semantics/forms/the-input-element",
+ "hidden-state-(type=hidden)": "html/semantics/forms/the-input-element",
+ "text-(type=text)-state-and-search-state-(type=search)": "html/semantics/forms/the-input-element",
+ "telephone-state-(type=tel)": "html/semantics/forms/the-input-element",
+ "url-state-(type=url)": "html/semantics/forms/the-input-element",
+ "e-mail-state-(type=email)": "html/semantics/forms/the-input-element",
+ "password-state-(type=password)": "html/semantics/forms/the-input-element",
+ "date-and-time-state-(type=datetime)": "html/semantics/forms/the-input-element",
+ "date-state-(type=date)": "html/semantics/forms/the-input-element",
+ "month-state-(type=month)": "html/semantics/forms/the-input-element",
+ "week-state-(type=week)": "html/semantics/forms/the-input-element",
+ "time-state-(type=time)": "html/semantics/forms/the-input-element",
+ "local-date-and-time-state-(type=datetime-local)": "html/semantics/forms/the-input-element",
+ "number-state-(type=number)": "html/semantics/forms/the-input-element",
+ "range-state-(type=range)": "html/semantics/forms/the-input-element",
+ "color-state-(type=color)": "html/semantics/forms/the-input-element",
+ "checkbox-state-(type=checkbox)": "html/semantics/forms/the-input-element",
+ "radio-button-state-(type=radio)": "html/semantics/forms/the-input-element",
+ "file-upload-state-(type=file)": "html/semantics/forms/the-input-element",
+ "submit-button-state-(type=submit)": "html/semantics/forms/the-input-element",
+ "image-button-state-(type=image)": "html/semantics/forms/the-input-element",
+ "reset-button-state-(type=reset)": "html/semantics/forms/the-input-element",
+ "button-state-(type=button)": "html/semantics/forms/the-input-element",
+ "input-impl-notes": "html/semantics/forms/the-input-element",
+ "common-input-element-attributes": "html/semantics/forms/the-input-element",
+ "the-maxlength-attribute": "html/semantics/forms/the-input-element",
+ "the-size-attribute": "html/semantics/forms/the-input-element",
+ "the-readonly-attribute": "html/semantics/forms/the-input-element",
+ "the-required-attribute": "html/semantics/forms/the-input-element",
+ "the-multiple-attribute": "html/semantics/forms/the-input-element",
+ "the-pattern-attribute": "html/semantics/forms/the-input-element",
+ "the-min-and-max-attributes": "html/semantics/forms/the-input-element",
+ "the-step-attribute": "html/semantics/forms/the-input-element",
+ "the-list-attribute": "html/semantics/forms/the-input-element",
+ "the-placeholder-attribute": "html/semantics/forms/the-input-element",
+ "common-input-element-apis": "html/semantics/forms/the-input-element",
+ "common-event-behaviors": "html/semantics/forms/the-input-element",
+ "the-button-element": "html/semantics/forms/the-button-element",
+ "the-select-element": "html/semantics/forms/the-select-element",
+ "the-datalist-element": "html/semantics/forms/the-datalist-element",
+ "the-optgroup-element": "html/semantics/forms/the-optgroup-element",
+ "the-option-element": "html/semantics/forms/the-option-element",
+ "the-textarea-element": "html/semantics/forms/the-textarea-element",
+ "the-keygen-element": "html/semantics/forms/the-keygen-element",
+ "the-output-element": "html/semantics/forms/the-output-element",
+ "the-progress-element": "html/semantics/forms/the-progress-element",
+ "the-meter-element": "html/semantics/forms/the-meter-element",
+ "form-control-infrastructure": "html/semantics/forms/form-control-infrastructure",
+ "a-form-control's-value": "html/semantics/forms/form-control-infrastructure",
+ "mutability": "html/semantics/forms/form-control-infrastructure",
+ "association-of-controls-and-forms": "html/semantics/forms/form-control-infrastructure",
+ "attributes-common-to-form-controls": "html/semantics/forms/attributes-common-to-form-controls",
+ "naming-form-controls:-the-name-attribute": "html/semantics/forms/attributes-common-to-form-controls",
+ "submitting-element-directionality:-the-dirname-attribute": "html/semantics/forms/attributes-common-to-form-controls",
+ "limiting-user-input-length:-the-maxlength-attribute": "html/semantics/forms/attributes-common-to-form-controls",
+ "enabling-and-disabling-form-controls:-the-disabled-attribute": "html/semantics/forms/attributes-common-to-form-controls",
+ "form-submission": "html/semantics/forms/attributes-common-to-form-controls",
+ "autofocusing-a-form-control:-the-autofocus-attribute": "html/semantics/forms/attributes-common-to-form-controls",
+ "input-modalities:-the-inputmode-attribute": "html/semantics/forms/attributes-common-to-form-controls",
+ "autofilling-form-controls:-the-autocomplete-attribute": "html/semantics/forms/attributes-common-to-form-controls",
+ "textFieldSelection": "html/semantics/forms/textfieldselection",
+ "constraints": "html/semantics/forms/constraints",
+ "definitions": "html/semantics/forms/constraints",
+ "constraint-validation": "html/semantics/forms/constraints",
+ "the-constraint-validation-api": "html/semantics/forms/constraints",
+ "security-forms": "html/semantics/forms/constraints",
+ "form-submission-0": "html/semantics/forms/form-submission-0",
+ "introduction-2": "html/semantics/forms/form-submission-0",
+ "implicit-submission": "html/semantics/forms/form-submission-0",
+ "form-submission-algorithm": "html/semantics/forms/form-submission-0",
+ "constructing-form-data-set": "html/semantics/forms/form-submission-0",
+ "url-encoded-form-data": "html/semantics/forms/form-submission-0",
+ "multipart-form-data": "html/semantics/forms/form-submission-0",
+ "plain-text-form-data": "html/semantics/forms/form-submission-0",
+ "resetting-a-form": "html/semantics/forms/resetting-a-form",
+ "interactive-elements": "html/semantics/interactive-elements",
+ "the-details-element": "html/semantics/interactive-elements/the-details-element",
+ "the-summary-element": "html/semantics/interactive-elements/the-summary-element",
+ "the-command-element": "html/semantics/interactive-elements/the-command-element",
+ "the-menu-element": "html/semantics/interactive-elements/the-menu-element",
+ "menus-intro": "html/semantics/interactive-elements/the-menu-element",
+ "building-menus-and-toolbars": "html/semantics/interactive-elements/the-menu-element",
+ "context-menus": "html/semantics/interactive-elements/the-menu-element",
+ "toolbars": "html/semantics/interactive-elements/the-menu-element",
+ "commands": "html/semantics/interactive-elements/commands",
+ "using-the-a-element-to-define-a-command": "html/semantics/interactive-elements/commands",
+ "using-the-button-element-to-define-a-command": "html/semantics/interactive-elements/commands",
+ "using-the-input-element-to-define-a-command": "html/semantics/interactive-elements/commands",
+ "using-the-option-element-to-define-a-command": "html/semantics/interactive-elements/commands",
+ "using-the-command-element-to-define-a-command": "html/semantics/interactive-elements/commands",
+ "using-the-command-attribute-on-command-elements-to-define-a-command-indirectly": "html/semantics/interactive-elements/commands",
+ "using-the-accesskey-attribute-on-a-label-element-to-define-a-command": "html/semantics/interactive-elements/commands",
+ "using-the-accesskey-attribute-on-a-legend-element-to-define-a-command": "html/semantics/interactive-elements/commands",
+ "using-the-accesskey-attribute-to-define-a-command-on-other-elements": "html/semantics/interactive-elements/commands",
+ "the-dialog-element": "html/semantics/interactive-elements/the-dialog-element",
+ "anchor-points": "html/semantics/interactive-elements/the-dialog-element",
+ "links": "html/semantics/links",
+ "introduction-3": "html/semantics/links/introduction-3",
+ "links-created-by-a-and-area-elements": "html/semantics/links/links-created-by-a-and-area-elements",
+ "following-hyperlinks": "html/semantics/links/following-hyperlinks",
+ "downloading-resources": "html/semantics/links/downloading-resources",
+ "hyperlink-auditing": "html/semantics/links/downloading-resources",
+ "linkTypes": "html/semantics/links/linktypes",
+ "rel-alternate": "html/semantics/links/linktypes",
+ "link-type-author": "html/semantics/links/linktypes",
+ "link-type-bookmark": "html/semantics/links/linktypes",
+ "link-type-help": "html/semantics/links/linktypes",
+ "rel-icon": "html/semantics/links/linktypes",
+ "link-type-license": "html/semantics/links/linktypes",
+ "link-type-nofollow": "html/semantics/links/linktypes",
+ "link-type-noreferrer": "html/semantics/links/linktypes",
+ "link-type-prefetch": "html/semantics/links/linktypes",
+ "link-type-search": "html/semantics/links/linktypes",
+ "link-type-stylesheet": "html/semantics/links/linktypes",
+ "link-type-tag": "html/semantics/links/linktypes",
+ "sequential-link-types": "html/semantics/links/linktypes",
+ "link-type-next": "html/semantics/links/linktypes",
+ "link-type-prev": "html/semantics/links/linktypes",
+ "other-link-types": "html/semantics/links/linktypes",
+ "common-idioms": "html/semantics/common-idioms",
+ "the-main-part-of-the-content": "html/semantics/common-idioms/the-main-part-of-the-content",
+ "rel-up": "html/semantics/common-idioms/rel-up",
+ "tag-clouds": "html/semantics/common-idioms/tag-clouds",
+ "conversations": "html/semantics/common-idioms/conversations",
+ "footnotes": "html/semantics/common-idioms/footnotes",
+ "disabled-elements": "html/semantics/disabled-elements",
+ "selectors": "html/semantics/selectors",
+ "case-sensitivity": "html/semantics/selectors/case-sensitivity",
+ "pseudo-classes": "html/semantics/selectors/pseudo-classes",
+ "browsers": "html/browsers",
+ "windows": "html/browsers/windows",
+ "nested-browsing-contexts": "html/browsers/windows/nested-browsing-contexts",
+ "navigating-nested-browsing-contexts-in-the-dom": "html/browsers/windows/nested-browsing-contexts",
+ "auxiliary-browsing-contexts": "html/browsers/windows/auxiliary-browsing-contexts",
+ "navigating-auxiliary-browsing-contexts-in-the-dom": "html/browsers/windows/auxiliary-browsing-contexts",
+ "secondary-browsing-contexts": "html/browsers/windows/secondary-browsing-contexts",
+ "security-nav": "html/browsers/windows/security-nav",
+ "groupings-of-browsing-contexts": "html/browsers/windows/groupings-of-browsing-contexts",
+ "browsing-context-names": "html/browsers/windows/browsing-context-names",
+ "the-window-object": "html/browsers/the-window-object",
+ "security-window": "html/browsers/the-window-object/security-window",
+ "apis-for-creating-and-navigating-browsing-contexts-by-name": "html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name",
+ "accessing-other-browsing-contexts": "html/browsers/the-window-object/accessing-other-browsing-contexts",
+ "named-access-on-the-window-object": "html/browsers/the-window-object/named-access-on-the-window-object",
+ "garbage-collection-and-browsing-contexts": "html/browsers/the-window-object/garbage-collection-and-browsing-contexts",
+ "closing-browsing-contexts": "html/browsers/the-window-object/closing-browsing-contexts",
+ "browser-interface-elements": "html/browsers/the-window-object/browser-interface-elements",
+ "the-windowproxy-object": "html/browsers/the-window-object/the-windowproxy-object",
+ "origin": "html/browsers/origin",
+ "relaxing-the-same-origin-restriction": "html/browsers/origin/relaxing-the-same-origin-restriction",
+ "sandboxing": "html/browsers/sandboxing",
+ "history": "html/browsers/history",
+ "the-session-history-of-browsing-contexts": "html/browsers/history/the-session-history-of-browsing-contexts",
+ "the-history-interface": "html/browsers/history/the-history-interface",
+ "the-location-interface": "html/browsers/history/the-location-interface",
+ "security-location": "html/browsers/history/the-location-interface",
+ "history-notes": "html/browsers/history/history-notes",
+ "browsing-the-web": "html/browsers/browsing-the-web",
+ "navigating-across-documents": "html/browsers/browsing-the-web/navigating-across-documents",
+ "read-html": "html/browsers/browsing-the-web/read-html",
+ "read-xml": "html/browsers/browsing-the-web/read-xml",
+ "read-text": "html/browsers/browsing-the-web/read-text",
+ "read-multipart-x-mixed-replace": "html/browsers/browsing-the-web/read-multipart-x-mixed-replace",
+ "read-media": "html/browsers/browsing-the-web/read-media",
+ "read-plugin": "html/browsers/browsing-the-web/read-plugin",
+ "read-ua-inline": "html/browsers/browsing-the-web/read-ua-inline",
+ "scroll-to-fragid": "html/browsers/browsing-the-web/scroll-to-fragid",
+ "history-traversal": "html/browsers/browsing-the-web/history-traversal",
+ "event-definitions-0": "html/browsers/browsing-the-web/history-traversal",
+ "unloading-documents": "html/browsers/browsing-the-web/unloading-documents",
+ "event-definition": "html/browsers/browsing-the-web/unloading-documents",
+ "aborting-a-document-load": "html/browsers/browsing-the-web/aborting-a-document-load",
+ "offline": "html/browsers/offline",
+ "introduction-4": "html/browsers/offline/introduction-4",
+ "supporting-offline-caching-for-legacy-applications": "html/browsers/offline/introduction-4",
+ "appcacheevents": "html/browsers/offline/introduction-4",
+ "appcache": "html/browsers/offline/appcache",
+ "manifests": "html/browsers/offline/manifests",
+ "some-sample-manifests": "html/browsers/offline/manifests",
+ "writing-cache-manifests": "html/browsers/offline/manifests",
+ "parsing-cache-manifests": "html/browsers/offline/manifests",
+ "downloading-or-updating-an-application-cache": "html/browsers/offline/downloading-or-updating-an-application-cache",
+ "the-application-cache-selection-algorithm": "html/browsers/offline/the-application-cache-selection-algorithm",
+ "changesToNetworkingModel": "html/browsers/offline/changestonetworkingmodel",
+ "expiring-application-caches": "html/browsers/offline/expiring-application-caches",
+ "disk-space": "html/browsers/offline/disk-space",
+ "application-cache-api": "html/browsers/offline/application-cache-api",
+ "browser-state": "html/browsers/offline/browser-state",
+ "webappapis": "html/webappapis",
+ "scripting": "html/webappapis/scripting",
+ "introduction-5": "html/webappapis/scripting/introduction-5",
+ "enabling-and-disabling-scripting": "html/webappapis/scripting/enabling-and-disabling-scripting",
+ "processing-model-2": "html/webappapis/scripting/processing-model-2",
+ "definitions-0": "html/webappapis/scripting/processing-model-2",
+ "calling-scripts": "html/webappapis/scripting/processing-model-2",
+ "creating-scripts": "html/webappapis/scripting/processing-model-2",
+ "killing-scripts": "html/webappapis/scripting/processing-model-2",
+ "runtime-script-errors": "html/webappapis/scripting/processing-model-2",
+ "runtime-script-errors-in-documents": "html/webappapis/scripting/processing-model-2",
+ "event-loops": "html/webappapis/scripting/event-loops",
+ "definitions-1": "html/webappapis/scripting/event-loops",
+ "processing-model-3": "html/webappapis/scripting/event-loops",
+ "generic-task-sources": "html/webappapis/scripting/event-loops",
+ "javascript-protocol": "html/webappapis/scripting/javascript-protocol",
+ "events": "html/webappapis/scripting/events",
+ "event-handler-attributes": "html/webappapis/scripting/events",
+ "event-handlers-on-elements,-document-objects,-and-window-objects": "html/webappapis/scripting/events",
+ "event-firing": "html/webappapis/scripting/events",
+ "events-and-the-window-object": "html/webappapis/scripting/events",
+ "atob": "html/webappapis/atob",
+ "timers": "html/webappapis/timers",
+ "user-prompts": "html/webappapis/user-prompts",
+ "simple-dialogs": "html/webappapis/user-prompts/simple-dialogs",
+ "printing": "html/webappapis/user-prompts/printing",
+ "dialogs-implemented-using-separate-documents": "html/webappapis/user-prompts/dialogs-implemented-using-separate-documents",
+ "system-state-and-capabilities": "html/webappapis/system-state-and-capabilities",
+ "the-navigator-object": "html/webappapis/system-state-and-capabilities/the-navigator-object",
+ "client-identification": "html/webappapis/system-state-and-capabilities/the-navigator-object",
+ "custom-handlers": "html/webappapis/system-state-and-capabilities/the-navigator-object",
+ "security-and-privacy": "html/webappapis/system-state-and-capabilities/the-navigator-object",
+ "sample-handler-impl": "html/webappapis/system-state-and-capabilities/the-navigator-object",
+ "manually-releasing-the-storage-mutex": "html/webappapis/system-state-and-capabilities/the-navigator-object",
+ "the-external-interface": "html/webappapis/system-state-and-capabilities/the-external-interface",
+ "editing": "html/editing",
+ "the-hidden-attribute": "html/editing/the-hidden-attribute",
+ "inert-subtrees": "html/editing/inert-subtrees",
+ "the-inert-attribute": "html/editing/inert-subtrees/the-inert-attribute",
+ "activation": "html/editing/activation",
+ "focus": "html/editing/focus",
+ "sequential-focus-navigation-and-the-tabindex-attribute": "html/editing/focus/sequential-focus-navigation-and-the-tabindex-attribute",
+ "focus-management": "html/editing/focus/focus-management",
+ "document-level-focus-apis": "html/editing/focus/document-level-focus-apis",
+ "element-level-focus-apis": "html/editing/focus/element-level-focus-apis",
+ "assigning-keyboard-shortcuts": "html/editing/assigning-keyboard-shortcuts",
+ "introduction-6": "html/editing/assigning-keyboard-shortcuts/introduction-6",
+ "the-accesskey-attribute": "html/editing/assigning-keyboard-shortcuts/the-accesskey-attribute",
+ "processing-model-4": "html/editing/assigning-keyboard-shortcuts/processing-model-4",
+ "editing-0": "html/editing/editing-0",
+ "contenteditable": "html/editing/editing-0/contenteditable",
+ "making-entire-documents-editable:-the-designmode-idl-attribute": "html/editing/editing-0/making-entire-documents-editable-the-designmode-idl-attribute",
+ "best-practices-for-in-page-editors": "html/editing/editing-0/best-practices-for-in-page-editors",
+ "editing-apis": "html/editing/editing-0/editing-apis",
+ "spelling-and-grammar-checking": "html/editing/editing-0/spelling-and-grammar-checking",
+ "dnd": "html/editing/dnd",
+ "introduction-7": "html/editing/dnd/introduction-7",
+ "the-drag-data-store": "html/editing/dnd/the-drag-data-store",
+ "the-datatransfer-interface": "html/editing/dnd/the-datatransfer-interface",
+ "the-datatransferitemlist-interface": "html/editing/dnd/the-datatransfer-interface",
+ "the-datatransferitem-interface": "html/editing/dnd/the-datatransfer-interface",
+ "the-dragevent-interface": "html/editing/dnd/the-dragevent-interface",
+ "drag-and-drop-processing-model": "html/editing/dnd/drag-and-drop-processing-model",
+ "dndevents": "html/editing/dnd/dndevents",
+ "the-draggable-attribute": "html/editing/dnd/the-draggable-attribute",
+ "the-dropzone-attribute": "html/editing/dnd/the-dropzone-attribute",
+ "security-risks-in-the-drag-and-drop-model": "html/editing/dnd/security-risks-in-the-drag-and-drop-model",
+ "syntax": "html/syntax",
+ "writing": "html/syntax/writing",
+ "the-doctype": "html/syntax/writing/the-doctype",
+ "elements-0": "html/syntax/writing/elements-0",
+ "start-tags": "html/syntax/writing/elements-0",
+ "end-tags": "html/syntax/writing/elements-0",
+ "attributes-0": "html/syntax/writing/elements-0",
+ "optional-tags": "html/syntax/writing/elements-0",
+ "element-restrictions": "html/syntax/writing/elements-0",
+ "cdata-rcdata-restrictions": "html/syntax/writing/elements-0",
+ "text": "html/syntax/writing/text",
+ "newlines": "html/syntax/writing/text",
+ "character-references": "html/syntax/writing/character-references",
+ "cdata-sections": "html/syntax/writing/cdata-sections",
+ "comments": "html/syntax/writing/comments",
+ "parsing": "html/syntax/parsing",
+ "overview-of-the-parsing-model": "html/syntax/parsing",
+ "the-input-byte-stream": "html/syntax/parsing",
+ "determining-the-character-encoding": "html/syntax/parsing",
+ "character-encodings-0": "html/syntax/parsing",
+ "changing-the-encoding-while-parsing": "html/syntax/parsing",
+ "preprocessing-the-input-stream": "html/syntax/parsing",
+ "parse-state": "html/syntax/parsing",
+ "the-insertion-mode": "html/syntax/parsing",
+ "the-stack-of-open-elements": "html/syntax/parsing",
+ "the-list-of-active-formatting-elements": "html/syntax/parsing",
+ "the-element-pointers": "html/syntax/parsing",
+ "other-parsing-state-flags": "html/syntax/parsing",
+ "tokenization": "html/syntax/parsing",
+ "data-state": "html/syntax/parsing",
+ "character-reference-in-data-state": "html/syntax/parsing",
+ "rcdata-state": "html/syntax/parsing",
+ "character-reference-in-rcdata-state": "html/syntax/parsing",
+ "rawtext-state": "html/syntax/parsing",
+ "script-data-state": "html/syntax/parsing",
+ "plaintext-state": "html/syntax/parsing",
+ "tag-open-state": "html/syntax/parsing",
+ "end-tag-open-state": "html/syntax/parsing",
+ "tag-name-state": "html/syntax/parsing",
+ "rcdata-less-than-sign-state": "html/syntax/parsing",
+ "rcdata-end-tag-open-state": "html/syntax/parsing",
+ "rcdata-end-tag-name-state": "html/syntax/parsing",
+ "rawtext-less-than-sign-state": "html/syntax/parsing",
+ "rawtext-end-tag-open-state": "html/syntax/parsing",
+ "rawtext-end-tag-name-state": "html/syntax/parsing",
+ "script-data-less-than-sign-state": "html/syntax/parsing",
+ "script-data-end-tag-open-state": "html/syntax/parsing",
+ "script-data-end-tag-name-state": "html/syntax/parsing",
+ "script-data-escape-start-state": "html/syntax/parsing",
+ "script-data-escape-start-dash-state": "html/syntax/parsing",
+ "script-data-escaped-state": "html/syntax/parsing",
+ "script-data-escaped-dash-state": "html/syntax/parsing",
+ "script-data-escaped-dash-dash-state": "html/syntax/parsing",
+ "script-data-escaped-less-than-sign-state": "html/syntax/parsing",
+ "script-data-escaped-end-tag-open-state": "html/syntax/parsing",
+ "script-data-escaped-end-tag-name-state": "html/syntax/parsing",
+ "script-data-double-escape-start-state": "html/syntax/parsing",
+ "script-data-double-escaped-state": "html/syntax/parsing",
+ "script-data-double-escaped-dash-state": "html/syntax/parsing",
+ "script-data-double-escaped-dash-dash-state": "html/syntax/parsing",
+ "script-data-double-escaped-less-than-sign-state": "html/syntax/parsing",
+ "script-data-double-escape-end-state": "html/syntax/parsing",
+ "before-attribute-name-state": "html/syntax/parsing",
+ "attribute-name-state": "html/syntax/parsing",
+ "after-attribute-name-state": "html/syntax/parsing",
+ "before-attribute-value-state": "html/syntax/parsing",
+ "attribute-value-(double-quoted)-state": "html/syntax/parsing",
+ "attribute-value-(single-quoted)-state": "html/syntax/parsing",
+ "attribute-value-(unquoted)-state": "html/syntax/parsing",
+ "character-reference-in-attribute-value-state": "html/syntax/parsing",
+ "after-attribute-value-(quoted)-state": "html/syntax/parsing",
+ "self-closing-start-tag-state": "html/syntax/parsing",
+ "bogus-comment-state": "html/syntax/parsing",
+ "markup-declaration-open-state": "html/syntax/parsing",
+ "comment-start-state": "html/syntax/parsing",
+ "comment-start-dash-state": "html/syntax/parsing",
+ "comment-state": "html/syntax/parsing",
+ "comment-end-dash-state": "html/syntax/parsing",
+ "comment-end-state": "html/syntax/parsing",
+ "comment-end-bang-state": "html/syntax/parsing",
+ "doctype-state": "html/syntax/parsing",
+ "before-doctype-name-state": "html/syntax/parsing",
+ "doctype-name-state": "html/syntax/parsing",
+ "after-doctype-name-state": "html/syntax/parsing",
+ "after-doctype-public-keyword-state": "html/syntax/parsing",
+ "before-doctype-public-identifier-state": "html/syntax/parsing",
+ "doctype-public-identifier-(double-quoted)-state": "html/syntax/parsing",
+ "doctype-public-identifier-(single-quoted)-state": "html/syntax/parsing",
+ "after-doctype-public-identifier-state": "html/syntax/parsing",
+ "between-doctype-public-and-system-identifiers-state": "html/syntax/parsing",
+ "after-doctype-system-keyword-state": "html/syntax/parsing",
+ "before-doctype-system-identifier-state": "html/syntax/parsing",
+ "doctype-system-identifier-(double-quoted)-state": "html/syntax/parsing",
+ "doctype-system-identifier-(single-quoted)-state": "html/syntax/parsing",
+ "after-doctype-system-identifier-state": "html/syntax/parsing",
+ "bogus-doctype-state": "html/syntax/parsing",
+ "cdata-section-state": "html/syntax/parsing",
+ "tokenizing-character-references": "html/syntax/parsing",
+ "tree-construction": "html/syntax/parsing",
+ "creating-and-inserting-elements": "html/syntax/parsing",
+ "closing-elements-that-have-implied-end-tags": "html/syntax/parsing",
+ "foster-parenting": "html/syntax/parsing",
+ "parsing-main-inhtml": "html/syntax/parsing",
+ "the-initial-insertion-mode": "html/syntax/parsing",
+ "the-before-html-insertion-mode": "html/syntax/parsing",
+ "the-before-head-insertion-mode": "html/syntax/parsing",
+ "parsing-main-inhead": "html/syntax/parsing",
+ "parsing-main-inheadnoscript": "html/syntax/parsing",
+ "the-after-head-insertion-mode": "html/syntax/parsing",
+ "parsing-main-inbody": "html/syntax/parsing",
+ "parsing-main-incdata": "html/syntax/parsing",
+ "parsing-main-intable": "html/syntax/parsing",
+ "parsing-main-intabletext": "html/syntax/parsing",
+ "parsing-main-incaption": "html/syntax/parsing",
+ "parsing-main-incolgroup": "html/syntax/parsing",
+ "parsing-main-intbody": "html/syntax/parsing",
+ "parsing-main-intr": "html/syntax/parsing",
+ "parsing-main-intd": "html/syntax/parsing",
+ "parsing-main-inselect": "html/syntax/parsing",
+ "parsing-main-inselectintable": "html/syntax/parsing",
+ "parsing-main-afterbody": "html/syntax/parsing",
+ "parsing-main-inframeset": "html/syntax/parsing",
+ "parsing-main-afterframeset": "html/syntax/parsing",
+ "the-after-after-body-insertion-mode": "html/syntax/parsing",
+ "the-after-after-frameset-insertion-mode": "html/syntax/parsing",
+ "parsing-main-inforeign": "html/syntax/parsing",
+ "the-end": "html/syntax/parsing",
+ "coercing-an-html-dom-into-an-infoset": "html/syntax/parsing",
+ "an-introduction-to-error-handling-and-strange-cases-in-the-parser": "html/syntax/parsing",
+ "misnested-tags:-b-i-/b-/i": "html/syntax/parsing",
+ "misnested-tags:-b-p-/b-/p": "html/syntax/parsing",
+ "unexpected-markup-in-tables": "html/syntax/parsing",
+ "scripts-that-modify-the-page-as-it-is-being-parsed": "html/syntax/parsing",
+ "the-execution-of-scripts-that-are-moving-across-multiple-documents": "html/syntax/parsing",
+ "unclosed-formatting-elements": "html/syntax/parsing",
+ "serializing-html-fragments": "html/syntax/serializing-html-fragments",
+ "parsing-html-fragments": "html/syntax/parsing-html-fragments",
+ "named-character-references": "html/syntax/named-character-references",
+ "the-xhtml-syntax": "html/the-xhtml-syntax",
+ "writing-xhtml-documents": "html/the-xhtml-syntax/writing-xhtml-documents",
+ "parsing-xhtml-documents": "html/the-xhtml-syntax/parsing-xhtml-documents",
+ "serializing-xhtml-fragments": "html/the-xhtml-syntax/serializing-xhtml-fragments",
+ "parsing-xhtml-fragments": "html/the-xhtml-syntax/parsing-xhtml-fragments",
+ "rendering": "html/rendering",
+ "introduction-8": "html/rendering/introduction-8",
+ "the-css-user-agent-style-sheet-and-presentational-hints": "html/rendering/the-css-user-agent-style-sheet-and-presentational-hints",
+ "non-replaced-elements": "html/rendering/non-replaced-elements",
+ "hidden-elements": "html/rendering/non-replaced-elements/hidden-elements",
+ "the-page": "html/rendering/non-replaced-elements/the-page",
+ "flow-content-0": "html/rendering/non-replaced-elements/flow-content-0",
+ "phrasing-content-0": "html/rendering/non-replaced-elements/phrasing-content-0",
+ "bidirectional-text": "html/rendering/non-replaced-elements/bidirectional-text",
+ "quotes": "html/rendering/non-replaced-elements/quotes",
+ "sections-and-headings": "html/rendering/non-replaced-elements/sections-and-headings",
+ "lists": "html/rendering/non-replaced-elements/lists",
+ "tables": "html/rendering/non-replaced-elements/tables",
+ "form-controls": "html/rendering/non-replaced-elements/form-controls",
+ "the-hr-element-0": "html/rendering/non-replaced-elements/the-hr-element-0",
+ "the-fieldset-element-0": "html/rendering/non-replaced-elements/the-fieldset-element-0",
+ "replaced-elements": "html/rendering/replaced-elements",
+ "embedded-content-1": "html/rendering/replaced-elements/embedded-content-1",
+ "images": "html/rendering/replaced-elements/images",
+ "attributes-for-embedded-content-and-images": "html/rendering/replaced-elements/attributes-for-embedded-content-and-images",
+ "image-maps-0": "html/rendering/replaced-elements/image-maps-0",
+ "toolbars-0": "html/rendering/replaced-elements/toolbars-0",
+ "bindings": "html/rendering/bindings",
+ "introduction-9": "html/rendering/bindings/introduction-9",
+ "the-button-element-0": "html/rendering/bindings/the-button-element-0",
+ "the-details-element-0": "html/rendering/bindings/the-details-element-0",
+ "the-input-element-as-a-text-entry-widget": "html/rendering/bindings/the-input-element-as-a-text-entry-widget",
+ "the-input-element-as-domain-specific-widgets": "html/rendering/bindings/the-input-element-as-domain-specific-widgets",
+ "the-input-element-as-a-range-control": "html/rendering/bindings/the-input-element-as-a-range-control",
+ "the-input-element-as-a-color-well": "html/rendering/bindings/the-input-element-as-a-color-well",
+ "the-input-element-as-a-checkbox-and-radio-button-widgets": "html/rendering/bindings/the-input-element-as-a-checkbox-and-radio-button-widgets",
+ "the-input-element-as-a-file-upload-control": "html/rendering/bindings/the-input-element-as-a-file-upload-control",
+ "the-input-element-as-a-button": "html/rendering/bindings/the-input-element-as-a-button",
+ "the-marquee-element": "html/rendering/bindings/the-marquee-element",
+ "the-meter-element-0": "html/rendering/bindings/the-meter-element-0",
+ "the-progress-element-0": "html/rendering/bindings/the-progress-element-0",
+ "the-select-element-0": "html/rendering/bindings/the-select-element-0",
+ "the-textarea-element-0": "html/rendering/bindings/the-textarea-element-0",
+ "the-keygen-element-0": "html/rendering/bindings/the-keygen-element-0",
+ "frames-and-framesets": "html/rendering/frames-and-framesets",
+ "interactive-media": "html/rendering/interactive-media",
+ "links,-forms,-and-navigation": "html/rendering/interactive-media/links-forms-and-navigation",
+ "the-title-attribute-0": "html/rendering/interactive-media/the-title-attribute-0",
+ "editing-hosts": "html/rendering/interactive-media/editing-hosts",
+ "text-rendered-in-native-user-interfaces": "html/rendering/interactive-media/text-rendered-in-native-user-interfaces",
+ "print-media": "html/rendering/print-media",
+ "unstyled-xml-documents": "html/rendering/unstyled-xml-documents",
+ "obsolete": "html/obsolete",
+ "obsolete-but-conforming-features": "html/obsolete/obsolete-but-conforming-features",
+ "warnings-for-obsolete-but-conforming-features": "html/obsolete/obsolete-but-conforming-features/warnings-for-obsolete-but-conforming-features",
+ "non-conforming-features": "html/obsolete/non-conforming-features",
+ "requirements-for-implementations": "html/obsolete/requirements-for-implementations",
+ "the-applet-element": "html/obsolete/requirements-for-implementations/the-applet-element",
+ "the-marquee-element-0": "html/obsolete/requirements-for-implementations/the-marquee-element-0",
+ "frames": "html/obsolete/requirements-for-implementations/frames",
+ "other-elements,-attributes-and-apis": "html/obsolete/requirements-for-implementations/other-elements-attributes-and-apis",
+ "iana": "microdata/iana",
+ "text/html": "html/iana/text-html",
+ "multipart/x-mixed-replace": "html/iana/multipart-x-mixed-replace",
+ "application/xhtml+xml": "html/iana/application-xhtml-xml",
+ "application/x-www-form-urlencoded": "html/iana/application-x-www-form-urlencoded",
+ "text/cache-manifest": "html/iana/text-cache-manifest",
+ "ping-to": "html/iana/ping-to",
+ "web+-scheme-prefix": "html/iana/web-scheme-prefix",
+ "the-canvas-state": "canvas2d/the-canvas-state",
+ "drawingstyle-objects": "canvas2d/drawingstyle-objects",
+ "line-styles": "canvas2d/line-styles",
+ "text-styles": "canvas2d/text-styles",
+ "building-paths": "canvas2d/building-paths",
+ "path-objects": "canvas2d/path-objects",
+ "transformations": "canvas2d/transformations",
+ "fill-and-stroke-styles": "canvas2d/fill-and-stroke-styles",
+ "drawing-rectangles-to-the-canvas": "canvas2d/drawing-rectangles-to-the-canvas",
+ "drawing-text-to-the-canvas": "canvas2d/drawing-text-to-the-canvas",
+ "drawing-paths-to-the-canvas": "canvas2d/drawing-paths-to-the-canvas",
+ "drawing-images-to-the-canvas": "canvas2d/drawing-images-to-the-canvas",
+ "hit-regions": "canvas2d/hit-regions",
+ "pixel-manipulation": "canvas2d/pixel-manipulation",
+ "compositing": "canvas2d/compositing",
+ "shadows": "canvas2d/shadows",
+ "drawing-model": "canvas2d/drawing-model",
+ "best-practices": "canvas2d/best-practices",
+ "overview": "microdata/introduction/overview",
+ "the-basic-syntax": "microdata/introduction/the-basic-syntax",
+ "typed-items": "microdata/introduction/typed-items",
+ "global-identifiers-for-items": "microdata/introduction/global-identifiers-for-items",
+ "selecting-names-when-defining-vocabularies": "microdata/introduction/selecting-names-when-defining-vocabularies",
+ "using-the-microdata-dom-api": "microdata/introduction/using-the-microdata-dom-api",
+ "encoding-microdata": "microdata/encoding-microdata",
+ "the-microdata-model": "microdata/encoding-microdata/the-microdata-model",
+ "items": "microdata/encoding-microdata/items",
+ "names:-the-itemprop-attribute": "microdata/encoding-microdata/names-the-itemprop-attribute",
+ "values": "microdata/encoding-microdata/values",
+ "associating-names-with-items": "microdata/encoding-microdata/associating-names-with-items",
+ "microdata-and-other-namespaces": "microdata/encoding-microdata/microdata-and-other-namespaces",
+ "microdata-dom-api": "microdata/microdata-dom-api",
+ "htmlpropertiescollection": "microdata/microdata-dom-api/htmlpropertiescollection",
+ "converting-html-to-other-formats": "microdata/converting-html-to-other-formats",
+ "json": "microdata/converting-html-to-other-formats/json"
+} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/tools/scripts/manifest.js b/tests/wpt/web-platform-tests/tools/scripts/manifest.js
new file mode 100644
index 00000000000..fbd55682590
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/scripts/manifest.js
@@ -0,0 +1,140 @@
+// grab test metadata from a test file
+function __result_handler() {
+
+ function __get_metadata() {
+ var obj = new Object();
+ var author = [];
+ var assert = [];
+ var help = [];
+ var match = [];
+ var mismatch = [];
+ var flags = [];
+ var nodes;
+
+ nodes = document.querySelectorAll('link[rel="author"]');
+ for (var i = 0; i < nodes.length; i++) {
+ var href = nodes[i].getAttribute("href");
+ var title = nodes[i].getAttribute("title");
+ var s = title;
+ if (href != null) {
+ s += " <" + href + ">";
+ }
+ author.push(s);
+ }
+ if (nodes.length > 0) obj.author = author;
+ nodes = document.querySelectorAll('meta[name="assert"]');
+ for (var i = 0; i < nodes.length; i++) {
+ assert.push(nodes[i].getAttribute("content"));
+ }
+ if (nodes.length > 0) obj.assert = assert;
+ nodes = document.querySelectorAll('link[rel="help"]');
+ for (var i = 0; i < nodes.length; i++) {
+ help.push(nodes[i].getAttribute("href"));
+ }
+ if (nodes.length > 0) obj.help = help;
+ nodes = document.querySelectorAll('link[rel="match"]');
+ for (var i = 0; i < nodes.length; i++) {
+ match.push(nodes[i].getAttribute("href"));
+ }
+ if (nodes.length > 0) obj.match = match;
+ nodes = document.querySelectorAll('link[rel="mismatch"]');
+ for (var i = 0; i < nodes.length; i++) {
+ mismatch.push(nodes[i].getAttribute("href"));
+ }
+ if (nodes.length > 0) obj.match = mismatch;
+ nodes = document.querySelectorAll('meta[name="flags"]');
+ for (var i = 0; i < nodes.length; i++) {
+ flags.push(nodes[i].getAttribute("content"));
+ }
+ if (nodes.length > 0) obj.flags = flags;
+
+ return obj;
+ }
+
+ var meta = __get_metadata();
+ var nodes;
+
+ function copy(obj, prop, arr) {
+ if (typeof arr !== "undefined") {
+ var a = [];
+ for (var i = 0; i<arr.length;i++) {
+ a[i] = arr[i];
+ }
+ obj[prop] = a;
+ }
+ }
+
+
+ var ret = new Object();
+ ret.location = document.location.href;
+ ret.type = "manual";
+ ret.tests = new Object();
+
+ var node = document.querySelector('script[src$="/resources/testharness.js"]');
+ if (node !== null) {
+ ret.type = "script";
+ }
+
+ if (ret.type === "script") {
+ if (typeof metadata_generator === "undefined"
+ || Object.keys(metadata_generator.currentMetadata).length === 0)
+ return "WRAPPER:TRY_AGAIN";
+ else {
+ for (var key in metadata_generator.currentMetadata) {
+ var obj = metadata_generator.currentMetadata[key];
+ var newtest = new Object();
+ ret.tests[key]= newtest;
+ if (typeof obj.help === "undefined") {
+ copy(newtest, "help", meta.help);
+ } else if (typeof obj.help === "string") {
+ newtest.help = [ obj.help ];
+ }
+ if (typeof obj.author === "undefined") {
+ copy(newtest, "author", meta.author);
+ } else if (typeof obj.author === "string") {
+ newtest.author = [ obj.author ];
+ }
+ if (typeof obj.assert === "undefined") {
+ copy(newtest, "assert", meta.assert);
+ } else if (typeof obj.assert === "string") {
+ newtest.assert = [ obj.assert ];
+ }
+ copy(newtest, "match", meta.match);
+ copy(newtest, "mismatch", meta.mismatch);
+ copy(newtest, "flags", meta.flags);
+ }
+ return ret;
+ }
+ } else {
+ var newtest = meta;
+ ret.tests[document.title]= newtest;
+
+ if (typeof newtest.match !== "undefined"
+ || typeof newtest.mismatch !== "undefined") {
+ ret.type = "reftest";
+ }
+
+ return ret;
+ }
+
+}
+
+function __give_up() {
+ var ret = new Object();
+ ret.location = document.location.href;
+ ret.type = "manual";
+ ret.tests = new Object();
+
+ var node = document.querySelector('script[src$="/resources/testharness.js"]');
+ if (node !== null) {
+ ret.type = "script";
+ } else if (typeof newtest.match !== "undefined"
+ || typeof newtest.mismatch !== "undefined") {
+ ret.type = "reftest";
+ }
+
+ var newtest = __get_metadata();
+ ret.tests[document.title]= newtest;
+
+ return ret;
+}
diff --git a/tests/wpt/web-platform-tests/tools/scripts/package.json b/tests/wpt/web-platform-tests/tools/scripts/package.json
new file mode 100644
index 00000000000..5618f6691f5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/scripts/package.json
@@ -0,0 +1,11 @@
+{
+ "name": "convert"
+, "version": "0.0.1"
+, "private": true
+, "dependencies": {
+ "mkdirp": "*"
+ , "wrench": "*"
+ , "underscore": "*"
+ , "jsdom": "*"
+ }
+}
diff --git a/tests/wpt/web-platform-tests/tools/scripts/toc.js b/tests/wpt/web-platform-tests/tools/scripts/toc.js
new file mode 100644
index 00000000000..120d4be039f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/scripts/toc.js
@@ -0,0 +1,107 @@
+// grab the table of contents filled with all the anchors
+function __result_handler() {
+ function getMap() {
+ var toc_element = document.getElementById("contents").nextElementSibling;
+
+ function getSection() {
+ function getIds(node) {
+ var a = [];
+
+ var nodes = node.querySelectorAll('*[id]');
+ for (var i = 0; i < nodes.length; i++) {
+ a.push(nodes[i].getAttribute("id"));
+ }
+ return a;
+ }
+
+ function getTOCIds() {
+ var a = [];
+
+ var nodes = toc_element.querySelectorAll('li');
+ for (var i = 0; i < nodes.length; i++) {
+ var href = nodes[i].firstElementChild.getAttribute("href");
+ a.push(href.substring(1));
+ }
+ return a;
+ }
+
+ var obj = new Object();
+ var ids = getIds(document);
+ var toc = getTOCIds();
+
+ for (var i = 1; i < toc.length; i++) {
+ var key1 = toc[i-1];
+ var key2 = toc[i];
+ var map = [];
+
+ var index1 = ids.indexOf(key1);
+ var index2 = ids.indexOf(key2);
+
+ if ((index2-index1) > 1) {
+ for (var j = index1+1; j < index2;j++) {
+ map.push(ids[j]);
+ }
+ }
+
+ obj[key1] = map;
+ }
+ {
+ var key = toc[toc.length-1];
+ var index = ids.indexOf(key);
+ var map = [];
+
+ for (var j = index+1; j < ids.length;j++) {
+ map.push(ids[j]);
+ }
+ obj[key] = map;
+ }
+
+ return obj;
+ }
+
+ function section(id) {
+ this.id = id;
+ }
+ function addSubSection(section, sub) {
+ if (typeof section.sections === "undefined") {
+ section.sections = [];
+ }
+ section.sections.push(sub);
+ }
+
+ function li(el, map) {
+ var obj = new section(el.firstElementChild.getAttribute("href").substring(1));
+ obj.title = el.firstElementChild.textContent;
+ var child = el.firstElementChild;
+
+ var m = map[obj.id];
+ for (var i = 0; i < m.length; i++) {
+ var sub = new section(m[i]);
+ addSubSection(obj, sub);
+ }
+ while (child !== null) {
+ if (child.nodeName === "OL") ol(child, obj, map);
+ child = child.nextElementSibling;
+ }
+ return obj;
+ }
+
+ function ol(el, section, map) {
+ var child = el.firstElementChild;
+ while (child !== null) {
+ addSubSection(section, li(child, map));
+ child = child.nextElementSibling;
+ }
+ }
+
+ var map = getSection();
+ var main = new section("___main___");
+ main.title = document.title;
+
+ ol(toc_element, main, map);
+
+ return main;
+ }
+
+ return getMap();
+}
diff --git a/tests/wpt/web-platform-tests/tools/scripts/update-directory-structure.js b/tests/wpt/web-platform-tests/tools/scripts/update-directory-structure.js
new file mode 100644
index 00000000000..7d73d93ac96
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/scripts/update-directory-structure.js
@@ -0,0 +1,106 @@
+
+// convert from old-style test structure to new style
+
+var fs = require("fs")
+, pth = require("path")
+, jsdom = require("jsdom")
+, mkdirp = require("mkdirp").sync
+, testDir = pth.join(__dirname, "../..")
+, MAX_DEPTH = 3
+, id2path = {}
+, limitDepth = {
+ parsing: true
+ }
+;
+
+var sections = {
+ html: "http://www.w3.org/html/wg/drafts/html/master/Overview.html"
+, canvas2d: "http://www.w3.org/html/wg/drafts/2dcontext/html5_canvas/Overview.html"
+, microdata: "http://www.w3.org/html/wg/drafts/microdata/master/Overview.html"
+};
+
+function walkTree ($, $el, list) {
+ $el.find("> li").each(function () {
+ var $li = $(this)
+ , $a = $li.find("> a").first()
+ ;
+ // skip sections that don't have a number
+ if (!/^\s*\d+/.test($a.text())) return;
+ var href = $a.attr("href").replace(/^.*#/, "")
+ , def = {
+ id: href.toLowerCase()
+ .replace(/[^a-z0-9\-]/g, "-")
+ .replace(/\-{2,}/g, "-")
+ .replace(/(?:^\-|\-$)/g, "")
+ , original_id: href
+ }
+ , $ol = $li.find("> ol").first()
+ ;
+ if ($ol.length) {
+ def.children = [];
+ walkTree($, $ol, def.children);
+ }
+ list.push(def);
+ });
+}
+
+function extractSections (sec, secDir, spec, cb) {
+ jsdom.env(
+ spec
+ , function (err, window) {
+ if (err) return cb(err);
+ jsdom.jQueryify(window, "https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js", function (window, $) {
+ if (!$) return cb("$ was not defined");
+ var $root = $("body > ol.toc").first()
+ , tree = []
+ ;
+ walkTree($, $root, tree);
+ cb(null, tree, sec, secDir);
+ }
+ );
+ });
+}
+
+function makeID2Path (base, tree) {
+ for (var i = 0, n = tree.length; i < n; i++) {
+ var sec = tree[i];
+ id2path[sec.original_id] = base;
+ if (sec.children && sec.children.length) makeID2Path(base, sec.children);
+ }
+}
+
+function makeDirs (base, tree, depth) {
+ console.log("Making " + base + " at depth " + depth);
+ for (var i = 0, n = tree.length; i < n; i++) {
+ var sec = tree[i]
+ , path = pth.join(base, sec.id)
+ ;
+ mkdirp(path);
+ fs.writeFileSync(pth.join(path, ".gitkeep"), "", "utf8");
+ id2path[sec.original_id] = path;
+ if (sec.id !== sec.original_id) {
+ fs.writeFileSync(pth.join(path, "original-id.json"), JSON.stringify({ original_id: sec.original_id}), "utf8");
+ }
+ if (sec.children && sec.children.length) {
+ if (depth === MAX_DEPTH || limitDepth[sec.id]) {
+ fs.writeFileSync(pth.join(path, "contains.json"), JSON.stringify(sec.children, null, 4), "utf8");
+ makeID2Path(path, sec.children);
+ }
+ else {
+ makeDirs(path, sec.children, depth + 1);
+ }
+ }
+ }
+}
+
+for (var sec in sections) {
+ var secDir = pth.join(testDir, sec);
+ mkdirp(secDir);
+ console.log("Launching extraction for " + sec);
+ extractSections(sec, secDir, sections[sec], function (err, toc, sec, secDir) {
+ if (err) return console.log("ERROR: " + err);
+ makeDirs(secDir, toc, 1);
+ for (var k in id2path) id2path[k] = id2path[k].replace(testDir + "/", "");
+ fs.writeFileSync(pth.join(__dirname, "id2path.json"), JSON.stringify(id2path, null, 4), "utf8");
+ });
+}
diff --git a/tests/wpt/web-platform-tests/tools/serve/__init__.py b/tests/wpt/web-platform-tests/tools/serve/__init__.py
new file mode 100644
index 00000000000..fc2f2f0fdd0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/serve/__init__.py
@@ -0,0 +1 @@
+import serve
diff --git a/tests/wpt/web-platform-tests/tools/serve/serve.py b/tests/wpt/web-platform-tests/tools/serve/serve.py
new file mode 100644
index 00000000000..bec8257e564
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/serve/serve.py
@@ -0,0 +1,456 @@
+ # -*- coding: utf-8 -*-
+import argparse
+import json
+import os
+import signal
+import socket
+import sys
+import threading
+import time
+import traceback
+import urllib2
+import uuid
+from collections import defaultdict
+from multiprocessing import Process, Event
+
+from .. import localpaths
+
+import sslutils
+from wptserve import server as wptserve, handlers
+from wptserve.logger import set_logger
+from mod_pywebsocket import standalone as pywebsocket
+
+repo_root = localpaths.repo_root
+
+class WorkersHandler(object):
+ def __init__(self):
+ self.handler = handlers.handler(self.handle_request)
+
+ def __call__(self, request, response):
+ return self.handler(request, response)
+
+ def handle_request(self, request, response):
+ worker_path = request.url_parts.path.replace(".worker", ".worker.js")
+ return """<!doctype html>
+<meta charset=utf-8>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+fetch_tests_from_worker(new Worker("%s"));
+</script>
+""" % (worker_path,)
+
+rewrites = [("GET", "/resources/WebIDLParser.js", "/resources/webidl2/lib/webidl2.js")]
+
+subdomains = [u"www",
+ u"www1",
+ u"www2",
+ u"天気の良い日",
+ u"élève"]
+
+def default_routes():
+ return [("GET", "/tools/runner/*", handlers.file_handler),
+ ("POST", "/tools/runner/update_manifest.py", handlers.python_script_handler),
+ ("*", "/_certs/*", handlers.ErrorHandler(404)),
+ ("*", "/tools/*", handlers.ErrorHandler(404)),
+ ("*", "{spec}/tools/*", handlers.ErrorHandler(404)),
+ ("*", "/serve.py", handlers.ErrorHandler(404)),
+ ("*", "*.py", handlers.python_script_handler),
+ ("GET", "*.asis", handlers.as_is_handler),
+ ("GET", "*.worker", WorkersHandler()),
+ ("GET", "*", handlers.file_handler),]
+
+def setup_logger(level):
+ import logging
+ global logger
+ logger = logging.getLogger("web-platform-tests")
+ logging.basicConfig(level=getattr(logging, level.upper()))
+ set_logger(logger)
+
+
+def open_socket(port):
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ if port != 0:
+ sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ sock.bind(('127.0.0.1', port))
+ sock.listen(5)
+ return sock
+
+
+def get_port():
+ free_socket = open_socket(0)
+ port = free_socket.getsockname()[1]
+ logger.debug("Going to use port %s" % port)
+ free_socket.close()
+ return port
+
+
+class ServerProc(object):
+ def __init__(self):
+ self.proc = None
+ self.daemon = None
+ self.stop = Event()
+
+ def start(self, init_func, host, port, paths, routes, bind_hostname, external_config,
+ ssl_config, **kwargs):
+ self.proc = Process(target=self.create_daemon,
+ args=(init_func, host, port, paths, routes, bind_hostname,
+ external_config, ssl_config))
+ self.proc.daemon = True
+ self.proc.start()
+
+ def create_daemon(self, init_func, host, port, paths, routes, bind_hostname,
+ external_config, ssl_config, **kwargs):
+ try:
+ self.daemon = init_func(host, port, paths, routes, bind_hostname, external_config,
+ ssl_config, **kwargs)
+ except socket.error:
+ print >> sys.stderr, "Socket error on port %s" % port
+ raise
+ except:
+ print >> sys.stderr, traceback.format_exc()
+ raise
+
+ if self.daemon:
+ try:
+ self.daemon.start(block=False)
+ try:
+ self.stop.wait()
+ except KeyboardInterrupt:
+ pass
+ except:
+ print >> sys.stderr, traceback.format_exc()
+ raise
+
+ def wait(self):
+ self.stop.set()
+ self.proc.join()
+
+ def kill(self):
+ self.stop.set()
+ self.proc.terminate()
+ self.proc.join()
+
+ def is_alive(self):
+ return self.proc.is_alive()
+
+
+def check_subdomains(host, paths, bind_hostname, ssl_config):
+ port = get_port()
+ subdomains = get_subdomains(host)
+
+ wrapper = ServerProc()
+ wrapper.start(start_http_server, host, port, paths, default_routes(), bind_hostname,
+ None, ssl_config)
+
+ connected = False
+ for i in range(10):
+ try:
+ urllib2.urlopen("http://%s:%d/" % (host, port))
+ connected = True
+ break
+ except urllib2.URLError:
+ time.sleep(1)
+
+ if not connected:
+ logger.critical("Failed to connect to test server on http://%s:%s You may need to edit /etc/hosts or similar" % (host, port))
+ sys.exit(1)
+
+ for subdomain, (punycode, host) in subdomains.iteritems():
+ domain = "%s.%s" % (punycode, host)
+ try:
+ urllib2.urlopen("http://%s:%d/" % (domain, port))
+ except Exception as e:
+ logger.critical("Failed probing domain %s. You may need to edit /etc/hosts or similar." % domain)
+ sys.exit(1)
+
+ wrapper.wait()
+
+
+def get_subdomains(host):
+ #This assumes that the tld is ascii-only or already in punycode
+ return {subdomain: (subdomain.encode("idna"), host)
+ for subdomain in subdomains}
+
+
+def start_servers(host, ports, paths, routes, bind_hostname, external_config, ssl_config,
+ **kwargs):
+ servers = defaultdict(list)
+ for scheme, ports in ports.iteritems():
+ assert len(ports) == {"http":2}.get(scheme, 1)
+
+ for port in ports:
+ if port is None:
+ continue
+ init_func = {"http":start_http_server,
+ "https":start_https_server,
+ "ws":start_ws_server,
+ "wss":start_wss_server}[scheme]
+
+ server_proc = ServerProc()
+ server_proc.start(init_func, host, port, paths, routes, bind_hostname,
+ external_config, ssl_config, **kwargs)
+ servers[scheme].append((port, server_proc))
+
+ return servers
+
+
+def start_http_server(host, port, paths, routes, bind_hostname, external_config, ssl_config,
+ **kwargs):
+ return wptserve.WebTestHttpd(host=host,
+ port=port,
+ doc_root=paths["doc_root"],
+ routes=routes,
+ rewrites=rewrites,
+ bind_hostname=bind_hostname,
+ config=external_config,
+ use_ssl=False,
+ key_file=None,
+ certificate=None,
+ latency=kwargs.get("latency"))
+
+
+def start_https_server(host, port, paths, routes, bind_hostname, external_config, ssl_config,
+ **kwargs):
+ return wptserve.WebTestHttpd(host=host,
+ port=port,
+ doc_root=paths["doc_root"],
+ routes=routes,
+ rewrites=rewrites,
+ bind_hostname=bind_hostname,
+ config=external_config,
+ use_ssl=True,
+ key_file=ssl_config["key_path"],
+ certificate=ssl_config["cert_path"],
+ encrypt_after_connect=ssl_config["encrypt_after_connect"],
+ latency=kwargs.get("latency"))
+
+
+class WebSocketDaemon(object):
+ def __init__(self, host, port, doc_root, handlers_root, log_level, bind_hostname,
+ ssl_config):
+ self.host = host
+ cmd_args = ["-p", port,
+ "-d", doc_root,
+ "-w", handlers_root,
+ "--log-level", log_level]
+ if (bind_hostname):
+ cmd_args = ["-H", host] + cmd_args
+ opts, args = pywebsocket._parse_args_and_config(cmd_args)
+ opts.cgi_directories = []
+ opts.is_executable_method = None
+ self.server = pywebsocket.WebSocketServer(opts)
+ ports = [item[0].getsockname()[1] for item in self.server._sockets]
+ assert all(item == ports[0] for item in ports)
+ self.port = ports[0]
+ self.started = False
+ self.server_thread = None
+
+ def start(self, block=False):
+ self.started = True
+ if block:
+ self.server.serve_forever()
+ else:
+ self.server_thread = threading.Thread(target=self.server.serve_forever)
+ self.server_thread.setDaemon(True) # don't hang on exit
+ self.server_thread.start()
+
+ def stop(self):
+ """
+ Stops the server.
+
+ If the server is not running, this method has no effect.
+ """
+ if self.started:
+ try:
+ self.server.shutdown()
+ self.server.server_close()
+ self.server_thread.join()
+ self.server_thread = None
+ except AttributeError:
+ pass
+ self.started = False
+ self.server = None
+
+
+def start_ws_server(host, port, paths, routes, bind_hostname, external_config, ssl_config,
+ **kwargs):
+ return WebSocketDaemon(host,
+ str(port),
+ repo_root,
+ paths["ws_doc_root"],
+ "debug",
+ bind_hostname,
+ ssl_config)
+
+
+def start_wss_server(host, port, path, routes, bind_hostname, external_config, ssl_config,
+ **kwargs):
+ return
+
+
+def get_ports(config, ssl_enabled):
+ rv = defaultdict(list)
+ for scheme, ports in config["ports"].iteritems():
+ for i, port in enumerate(ports):
+ if scheme in ["http", "https"] and not ssl_enabled:
+ port = None
+ if port == "auto":
+ port = get_port()
+ else:
+ port = port
+ rv[scheme].append(port)
+ return rv
+
+
+
+def normalise_config(config, ports):
+ host = config["external_host"] if config["external_host"] else config["host"]
+ domains = get_subdomains(host)
+ ports_ = {}
+ for scheme, ports_used in ports.iteritems():
+ ports_[scheme] = ports_used
+
+ for key, value in domains.iteritems():
+ domains[key] = ".".join(value)
+
+ domains[""] = host
+
+ ports_ = {}
+ for scheme, ports_used in ports.iteritems():
+ ports_[scheme] = ports_used
+
+ return {"host": host,
+ "domains": domains,
+ "ports": ports_}
+
+
+def get_ssl_config(config, external_domains, ssl_environment):
+ key_path, cert_path = ssl_environment.host_cert_path(external_domains)
+ return {"key_path": key_path,
+ "cert_path": cert_path,
+ "encrypt_after_connect": config["ssl"]["encrypt_after_connect"]}
+
+
+def start(config, ssl_environment, routes, **kwargs):
+ host = config["host"]
+ domains = get_subdomains(host)
+ ports = get_ports(config, ssl_environment)
+ bind_hostname = config["bind_hostname"]
+
+ paths = {"doc_root": config["doc_root"],
+ "ws_doc_root": config["ws_doc_root"]}
+
+ external_config = normalise_config(config, ports)
+
+ ssl_config = get_ssl_config(config, external_config["domains"].values(), ssl_environment)
+
+ if config["check_subdomains"]:
+ check_subdomains(host, paths, bind_hostname, ssl_config)
+
+ servers = start_servers(host, ports, paths, routes, bind_hostname, external_config,
+ ssl_config, **kwargs)
+
+ return external_config, servers
+
+
+def iter_procs(servers):
+ for servers in servers.values():
+ for port, server in servers:
+ yield server.proc
+
+
+def value_set(config, key):
+ return key in config and config[key] is not None
+
+
+def set_computed_defaults(config):
+ if not value_set(config, "ws_doc_root"):
+ if value_set(config, "doc_root"):
+ root = config["doc_root"]
+ else:
+ root = repo_root
+ config["ws_doc_root"] = os.path.join(repo_root, "websockets", "handlers")
+
+ if not value_set(config, "doc_root"):
+ config["doc_root"] = repo_root
+
+
+def merge_json(base_obj, override_obj):
+ rv = {}
+ for key, value in base_obj.iteritems():
+ if key not in override_obj:
+ rv[key] = value
+ else:
+ if isinstance(value, dict):
+ rv[key] = merge_json(value, override_obj[key])
+ else:
+ rv[key] = override_obj[key]
+ return rv
+
+
+def get_ssl_environment(config):
+ implementation_type = config["ssl"]["type"]
+ cls = sslutils.environments[implementation_type]
+ try:
+ kwargs = config["ssl"][implementation_type].copy()
+ except KeyError:
+ raise ValueError("%s is not a vaid ssl type." % implementation_type)
+ return cls(logger, **kwargs)
+
+
+def load_config(default_path, override_path=None, **kwargs):
+ if os.path.exists(default_path):
+ with open(default_path) as f:
+ base_obj = json.load(f)
+ else:
+ raise ValueError("Config path %s does not exist" % default_path)
+
+ if os.path.exists(override_path):
+ with open(override_path) as f:
+ override_obj = json.load(f)
+ else:
+ override_obj = {}
+ rv = merge_json(base_obj, override_obj)
+
+ if kwargs.get("config_path"):
+ other_path = os.path.abspath(os.path.expanduser(kwargs.get("config_path")))
+ if os.path.exists(other_path):
+ base_obj = rv
+ with open(other_path) as f:
+ override_obj = json.load(f)
+ rv = merge_json(base_obj, override_obj)
+ else:
+ raise ValueError("Config path %s does not exist" % other_path)
+
+ set_computed_defaults(rv)
+ return rv
+
+
+def get_parser():
+ parser = argparse.ArgumentParser()
+ parser.add_argument("--latency", type=int,
+ help="Artificial latency to add before sending http responses, in ms")
+ parser.add_argument("--config", action="store", dest="config_path",
+ help="Path to external config file")
+ return parser
+
+
+def main():
+ kwargs = vars(get_parser().parse_args())
+ config = load_config("config.default.json",
+ "config.json",
+ **kwargs)
+
+ setup_logger(config["log_level"])
+
+ with get_ssl_environment(config) as ssl_env:
+ config_, servers = start(config, ssl_env, default_routes(), **kwargs)
+
+ try:
+ while any(item.is_alive() for item in iter_procs(servers)):
+ for item in iter_procs(servers):
+ item.join(1)
+ except KeyboardInterrupt:
+ logger.info("Shutting down")
diff --git a/tests/wpt/web-platform-tests/tools/six/.gitignore b/tests/wpt/web-platform-tests/tools/six/.gitignore
new file mode 100644
index 00000000000..809b2e84eef
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/six/.gitignore
@@ -0,0 +1,9 @@
+*#
+*.py[co]
+*.sw[po]
+*~
+MANIFEST
+documentation/_build
+\#*
+.tox
+six.egg-info
diff --git a/tests/wpt/web-platform-tests/tools/six/.hgignore b/tests/wpt/web-platform-tests/tools/six/.hgignore
new file mode 100644
index 00000000000..37232e73382
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/six/.hgignore
@@ -0,0 +1,8 @@
+syntax: glob
+*.pyc
+dist
+MANIFEST
+documentation/_build
+.tox
+.gitignore
+six.egg-info
diff --git a/tests/wpt/web-platform-tests/tools/six/CHANGES b/tests/wpt/web-platform-tests/tools/six/CHANGES
new file mode 100644
index 00000000000..25930bd9aa1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/six/CHANGES
@@ -0,0 +1,246 @@
+Changelog for six
+=================
+
+This file lists the changes in each six version.
+
+Development version
+-------------------
+
+- Issue #105 and pull request #58: Ensure `six.wraps` respects the *updated* and
+ *assigned* arguments.
+
+- Issue #102: Add `raise_from` to abstract out Python 3's raise from syntax.
+
+- Issue #97: Optimize `six.iterbytes` on Python 2.
+
+- Issue #98: Fix `six.moves` race condition in multi-threaded code.
+
+- Pull request #51: Add `six.view(keys|values|itmes)`, which provide dictionary
+ views on Python 2.7+.
+
+1.8.0
+-----
+
+- Issue #90: Add `six.moves.shlex_quote`.
+
+- Issue #59: Add `six.moves.intern`.
+
+- Add `six.urllib.parse.uses_(fragment|netloc|params|query|relative)`.
+
+- Issue #88: Fix add_metaclass when the class has `__slots__` containing
+ `__weakref__` or `__dict__`.
+
+- Issue #89: Make six use absolute imports.
+
+- Issue #85: Always accept *updated* and *assigned* arguments for `wraps()`.
+
+- Issue #86: In `reraise()`, instantiate the exception if the second argument is
+ `None`.
+
+- Pull request #45: Add `six.moves.email_mime_nonmultipart`.
+
+- Issue #81: Add `six.urllib.request.splittag` mapping.
+
+- Issue #80: Add `six.urllib.request.splituser` mapping.
+
+1.7.3
+-----
+
+- Issue #77: Fix import six on Python 3.4 with a custom loader.
+
+- Issue #74: `six.moves.xmlrpc_server` should map to `SimpleXMLRPCServer` on Python
+ 2 as documented not `xmlrpclib`.
+
+1.7.2
+-----
+
+- Issue #72: Fix installing on Python 2.
+
+1.7.1
+-----
+
+- Issue #71: Make the six.moves meta path importer handle reloading of the six
+ module gracefully.
+
+1.7.0
+-----
+
+- Pull request #30: Implement six.moves with a PEP 302 meta path hook.
+
+- Pull request #32: Add six.wraps, which is like functools.wraps but always sets
+ the __wrapped__ attribute.
+
+- Pull request #35: Improve add_metaclass, so that it doesn't end up inserting
+ another class into the hierarchy.
+
+- Pull request #34: Add import mappings for dummy_thread.
+
+- Pull request #33: Add import mappings for UserDict and UserList.
+
+- Pull request #31: Select the implementations of dictionary iterator routines
+ at import time for a 20% speed boost.
+
+1.6.1
+-----
+
+- Raise an AttributeError for six.moves.X when X is a module not available in
+ the current interpreter.
+
+1.6.0
+-----
+
+- Raise an AttributeError for every attribute of unimportable modules.
+
+- Issue #56: Make the fake modules six.moves puts into sys.modules appear not to
+ have a __path__ unless they are loaded.
+
+- Pull request #28: Add support for SplitResult.
+
+- Issue #55: Add move mapping for xmlrpc.server.
+
+- Pull request #29: Add move for urllib.parse.splitquery.
+
+1.5.2
+-----
+
+- Issue #53: Make the fake modules six.moves puts into sys.modules appear not to
+ have a __name__ unless they are loaded.
+
+1.5.1
+-----
+
+- Issue #51: Hack around the Django autoreloader after recent six.moves changes.
+
+1.5.0
+-----
+
+- Removed support for Python 2.4. This is because py.test no longer supports
+ 2.4.
+
+- Fix various import problems including issues #19 and #41. six.moves modules
+ are now lazy wrappers over the underlying modules instead of the actual
+ modules themselves.
+
+- Issue #49: Add six.moves mapping for tkinter.ttk.
+
+- Pull request #24: Add __dir__ special method to six.moves modules.
+
+- Issue #47: Fix add_metaclass on classes with a string for the __slots__
+ variable.
+
+- Issue #44: Fix interpretation of backslashes on Python 2 in the u() function.
+
+- Pull request #21: Add import mapping for urllib's proxy_bypass function.
+
+- Issue #43: Add import mapping for the Python 2 xmlrpclib module.
+
+- Issue #39: Add import mapping for the Python 2 thread module.
+
+- Issue #40: Add import mapping for the Python 2 gdbm module.
+
+- Issue #35: On Python versions less than 2.7, print_ now encodes unicode
+ strings when outputing to standard streams. (Python 2.7 handles this
+ automatically.)
+
+1.4.1
+-----
+
+- Issue #32: urllib module wrappings don't work when six is not a toplevel file.
+
+1.4.0
+-----
+
+- Issue #31: Add six.moves mapping for UserString.
+
+- Pull request #12: Add six.add_metaclass, a decorator for adding a metaclass to
+ a class.
+
+- Add six.moves.zip_longest and six.moves.filterfalse, which correspond
+ respectively to itertools.izip_longest and itertools.ifilterfalse on Python 2
+ and itertools.zip_longest and itertools.filterfalse on Python 3.
+
+- Issue #25: Add the unichr function, which returns a string for a Unicode
+ codepoint.
+
+- Issue #26: Add byte2int function, which complements int2byte.
+
+- Add a PY2 constant with obvious semantics.
+
+- Add helpers for indexing and iterating over bytes: iterbytes and indexbytes.
+
+- Add create_bound_method() wrapper.
+
+- Issue #23: Allow multiple base classes to be passed to with_metaclass.
+
+- Issue #24: Add six.moves.range alias. This exactly the same as the current
+ xrange alias.
+
+- Pull request #5: Create six.moves.urllib, which contains abstractions for a
+ bunch of things which are in urllib in Python 3 and spread out across urllib,
+ urllib2, and urlparse in Python 2.
+
+1.3.0
+-----
+
+- Issue #21: Add methods to access the closure and globals of a function.
+
+- In six.iter(items/keys/values/lists), passed keyword arguments through to the
+ underlying method.
+
+- Add six.iterlists().
+
+- Issue #20: Fix tests if tkinter is not available.
+
+- Issue #17: Define callable to be builtin callable when it is available again
+ in Python 3.2+.
+
+- Issue #16: Rename Python 2 exec_'s arguments, so casually calling exec_ with
+ keyword arguments will raise.
+
+- Issue #14: Put the six.moves package in sys.modules based on the name six is
+ imported under.
+
+- Fix Jython detection.
+
+- Pull request #4: Add email_mime_multipart, email_mime_text, and
+ email_mime_base to six.moves.
+
+1.2.0
+-----
+
+- Issue #13: Make iterkeys/itervalues/iteritems return iterators on Python 3
+ instead of iterables.
+
+- Issue #11: Fix maxsize support on Jython.
+
+- Add six.next() as an alias for six.advance_iterator().
+
+- Use the builtin next() function for advance_iterator() where is available
+ (2.6+), not just Python 3.
+
+- Add the Iterator class for writing portable iterators.
+
+1.1.0
+-----
+
+- Add the int2byte function.
+
+- Add compatibility mappings for iterators over the keys, values, and items of a
+ dictionary.
+
+- Fix six.MAXSIZE on platforms where sizeof(long) != sizeof(Py_ssize_t).
+
+- Issue #3: Add six.moves mappings for filter, map, and zip.
+
+1.0.0
+-----
+
+- Issue #2: u() on Python 2.x now resolves unicode escapes.
+
+- Expose an API for adding mappings to six.moves.
+
+1.0 beta 1
+----------
+
+- Reworked six into one .py file. This breaks imports. Please tell me if you
+ are interested in an import compatibility layer.
diff --git a/tests/wpt/web-platform-tests/tools/six/CONTRIBUTORS b/tests/wpt/web-platform-tests/tools/six/CONTRIBUTORS
new file mode 100644
index 00000000000..0cbd0a4026e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/six/CONTRIBUTORS
@@ -0,0 +1,22 @@
+The primary author and maintainer of six is Benjamin Peterson. He would like to
+acknowledge the following people who submitted bug reports, pull requests, and
+otherwise worked to improve six:
+
+Marc Abramowitz
+Alexander Artemenko
+Aymeric Augustin
+Ned Batchelder
+Jason R. Coombs
+Julien Danjou
+Ben Darnell
+Ben Davis
+Joshua Harlow
+Anselm Kruis
+Alexander Lukanin
+James Mills
+Sridhar Ratnakumar
+Erik Rose
+Peter Ruibal
+Miroslav Shubernetskiy
+
+If you think you belong on this list, please let me know! --Benjamin
diff --git a/tests/wpt/web-platform-tests/tools/six/LICENSE b/tests/wpt/web-platform-tests/tools/six/LICENSE
new file mode 100644
index 00000000000..d76e024263c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/six/LICENSE
@@ -0,0 +1,18 @@
+Copyright (c) 2010-2014 Benjamin Peterson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/tests/wpt/web-platform-tests/tools/six/MANIFEST.in b/tests/wpt/web-platform-tests/tools/six/MANIFEST.in
new file mode 100644
index 00000000000..b924e068eee
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/six/MANIFEST.in
@@ -0,0 +1,6 @@
+include CHANGES
+include LICENSE
+include test_six.py
+
+recursive-include documentation *
+prune documentation/_build
diff --git a/tests/wpt/web-platform-tests/tools/six/README b/tests/wpt/web-platform-tests/tools/six/README
new file mode 100644
index 00000000000..32bab7ceecf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/six/README
@@ -0,0 +1,16 @@
+Six is a Python 2 and 3 compatibility library. It provides utility functions
+for smoothing over the differences between the Python versions with the goal of
+writing Python code that is compatible on both Python versions. See the
+documentation for more information on what is provided.
+
+Six supports every Python version since 2.5. It is contained in only one Python
+file, so it can be easily copied into your project. (The copyright and license
+notice must be retained.)
+
+Online documentation is at http://pythonhosted.org/six/.
+
+Bugs can be reported to https://bitbucket.org/gutworth/six. The code can also
+be found there.
+
+For questions about six or porting in general, email the python-porting mailing
+list: http://mail.python.org/mailman/listinfo/python-porting
diff --git a/tests/wpt/web-platform-tests/tools/six/documentation/Makefile b/tests/wpt/web-platform-tests/tools/six/documentation/Makefile
new file mode 100644
index 00000000000..eebafcd6d60
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/six/documentation/Makefile
@@ -0,0 +1,130 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS =
+SPHINXBUILD = sphinx-build
+PAPER =
+BUILDDIR = _build
+
+# Internal variables.
+PAPEROPT_a4 = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest
+
+help:
+ @echo "Please use \`make <target>' where <target> is one of"
+ @echo " html to make standalone HTML files"
+ @echo " dirhtml to make HTML files named index.html in directories"
+ @echo " singlehtml to make a single large HTML file"
+ @echo " pickle to make pickle files"
+ @echo " json to make JSON files"
+ @echo " htmlhelp to make HTML files and a HTML help project"
+ @echo " qthelp to make HTML files and a qthelp project"
+ @echo " devhelp to make HTML files and a Devhelp project"
+ @echo " epub to make an epub"
+ @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+ @echo " latexpdf to make LaTeX files and run them through pdflatex"
+ @echo " text to make text files"
+ @echo " man to make manual pages"
+ @echo " changes to make an overview of all changed/added/deprecated items"
+ @echo " linkcheck to check all external links for integrity"
+ @echo " doctest to run all doctests embedded in the documentation (if enabled)"
+
+clean:
+ -rm -rf $(BUILDDIR)/*
+
+html:
+ $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+dirhtml:
+ $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
+
+singlehtml:
+ $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
+ @echo
+ @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
+
+pickle:
+ $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
+ @echo
+ @echo "Build finished; now you can process the pickle files."
+
+json:
+ $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
+ @echo
+ @echo "Build finished; now you can process the JSON files."
+
+htmlhelp:
+ $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
+ @echo
+ @echo "Build finished; now you can run HTML Help Workshop with the" \
+ ".hhp project file in $(BUILDDIR)/htmlhelp."
+
+qthelp:
+ $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
+ @echo
+ @echo "Build finished; now you can run "qcollectiongenerator" with the" \
+ ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
+ @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/six.qhcp"
+ @echo "To view the help file:"
+ @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/six.qhc"
+
+devhelp:
+ $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
+ @echo
+ @echo "Build finished."
+ @echo "To view the help file:"
+ @echo "# mkdir -p $$HOME/.local/share/devhelp/six"
+ @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/six"
+ @echo "# devhelp"
+
+epub:
+ $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
+ @echo
+ @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
+
+latex:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo
+ @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
+ @echo "Run \`make' in that directory to run these through (pdf)latex" \
+ "(use \`make latexpdf' here to do that automatically)."
+
+latexpdf:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo "Running LaTeX files through pdflatex..."
+ make -C $(BUILDDIR)/latex all-pdf
+ @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+text:
+ $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
+ @echo
+ @echo "Build finished. The text files are in $(BUILDDIR)/text."
+
+man:
+ $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
+ @echo
+ @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
+
+changes:
+ $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
+ @echo
+ @echo "The overview file is in $(BUILDDIR)/changes."
+
+linkcheck:
+ $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
+ @echo
+ @echo "Link check complete; look for any errors in the above output " \
+ "or in $(BUILDDIR)/linkcheck/output.txt."
+
+doctest:
+ $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
+ @echo "Testing of doctests in the sources finished, look at the " \
+ "results in $(BUILDDIR)/doctest/output.txt."
diff --git a/tests/wpt/web-platform-tests/tools/six/documentation/conf.py b/tests/wpt/web-platform-tests/tools/six/documentation/conf.py
new file mode 100644
index 00000000000..7e54287a69e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/six/documentation/conf.py
@@ -0,0 +1,217 @@
+# -*- coding: utf-8 -*-
+#
+# six documentation build configuration file
+
+import os
+import sys
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#sys.path.append(os.path.abspath('.'))
+
+# -- General configuration -----------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+needs_sphinx = "1.0"
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = ["sphinx.ext.intersphinx"]
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ["_templates"]
+
+# The suffix of source filenames.
+source_suffix = ".rst"
+
+# The encoding of source files.
+#source_encoding = "utf-8-sig"
+
+# The master toctree document.
+master_doc = "index"
+
+# General information about the project.
+project = u"six"
+copyright = u"2010-2014, Benjamin Peterson"
+
+sys.path.append(os.path.abspath(os.path.join(".", "..")))
+from six import __version__ as six_version
+sys.path.pop()
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+version = six_version[:-2]
+# The full version, including alpha/beta/rc tags.
+release = six_version
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = ["_build"]
+
+# The reST default role (used for this markup: `text`) to use for all documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = "sphinx"
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+
+# -- Options for HTML output ---------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages. See the documentation for
+# a list of builtin themes.
+html_theme = "default"
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further. For a list of options available for each theme, see the
+# documentation.
+#html_theme_options = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+#html_theme_path = []
+
+# The name for this set of Sphinx documents. If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# A shorter title for the navigation bar. Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ["_static"]
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_domain_indices = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+#html_show_sourcelink = True
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+#html_show_sphinx = True
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+#html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it. The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = ''
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'sixdoc'
+
+
+# -- Options for LaTeX output --------------------------------------------------
+
+# The paper size ('letter' or 'a4').
+#latex_paper_size = 'letter'
+
+# The font size ('10pt', '11pt' or '12pt').
+#latex_font_size = '10pt'
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, documentclass [howto/manual]).
+latex_documents = [
+ ("index", "six.tex", u"six Documentation",
+ u"Benjamin Peterson", "manual"),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# If true, show page references after internal links.
+#latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+#latex_show_urls = False
+
+# Additional stuff for the LaTeX preamble.
+#latex_preamble = ''
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_domain_indices = True
+
+
+# -- Options for manual page output --------------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+ ("index", "six", u"six Documentation",
+ [u"Benjamin Peterson"], 1)
+]
+
+# -- Intersphinx ---------------------------------------------------------------
+
+intersphinx_mapping = {"py2" : ("https://docs.python.org/2/", None),
+ "py3" : ("https://docs.python.org/3/", None)}
diff --git a/tests/wpt/web-platform-tests/tools/six/documentation/index.rst b/tests/wpt/web-platform-tests/tools/six/documentation/index.rst
new file mode 100644
index 00000000000..7851421a90e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/six/documentation/index.rst
@@ -0,0 +1,785 @@
+Six: Python 2 and 3 Compatibility Library
+=========================================
+
+.. module:: six
+ :synopsis: Python 2 and 3 compatibility
+
+.. moduleauthor:: Benjamin Peterson <benjamin@python.org>
+.. sectionauthor:: Benjamin Peterson <benjamin@python.org>
+
+
+Six provides simple utilities for wrapping over differences between Python 2 and
+Python 3. It is intended to support codebases that work on both Python 2 and 3
+without modification. six consists of only one Python file, so it is painless
+to copy into a project.
+
+Six can be downloaded on `PyPi <http://pypi.python.org/pypi/six/>`_. Its bug
+tracker and code hosting is on `BitBucket <http://bitbucket.org/gutworth/six>`_.
+
+The name, "six", comes from the fact that 2*3 equals 6. Why not addition?
+Multiplication is more powerful, and, anyway, "five" has already been snatched
+away by the Zope Five project.
+
+
+Indices and tables
+------------------
+
+* :ref:`genindex`
+* :ref:`search`
+
+
+Package contents
+----------------
+
+.. data:: PY2
+
+ A boolean indicating if the code is running on Python 2.
+
+.. data:: PY3
+
+ A boolean indicating if the code is running on Python 3.
+
+
+Constants
+>>>>>>>>>
+
+Six provides constants that may differ between Python versions. Ones ending
+``_types`` are mostly useful as the second argument to ``isinstance`` or
+``issubclass``.
+
+
+.. data:: class_types
+
+ Possible class types. In Python 2, this encompasses old-style and new-style
+ classes. In Python 3, this is just new-styles.
+
+
+.. data:: integer_types
+
+ Possible integer types. In Python 2, this is :func:`py2:long` and
+ :func:`py2:int`, and in Python 3, just :func:`py3:int`.
+
+
+.. data:: string_types
+
+ Possible types for text data. This is :func:`py2:basestring` in Python 2 and
+ :func:`py3:str` in Python 3.
+
+
+.. data:: text_type
+
+ Type for representing (Unicode) textual data. This is :func:`py2:unicode` in
+ Python 2 and :func:`py3:str` in Python 3.
+
+
+.. data:: binary_type
+
+ Type for representing binary data. This is :func:`py2:str` in Python 2 and
+ :func:`py3:bytes` in Python 3.
+
+
+.. data:: MAXSIZE
+
+ The maximum size of a container like :func:`py3:list` or :func:`py3:dict`.
+ This is equivalent to :data:`py3:sys.maxsize` in Python 2.6 and later
+ (including 3.x). Note, this is temptingly similar to, but not the same as
+ :data:`py2:sys.maxint` in Python 2. There is no direct equivalent to
+ :data:`py2:sys.maxint` in Python 3 because its integer type has no limits
+ aside from memory.
+
+
+Here's example usage of the module::
+
+ import six
+
+ def dispatch_types(value):
+ if isinstance(value, six.integer_types):
+ handle_integer(value)
+ elif isinstance(value, six.class_types):
+ handle_class(value)
+ elif isinstance(value, six.string_types):
+ handle_string(value)
+
+
+Object model compatibility
+>>>>>>>>>>>>>>>>>>>>>>>>>>
+
+Python 3 renamed the attributes of several intepreter data structures. The
+following accessors are available. Note that the recommended way to inspect
+functions and methods is the stdlib :mod:`py3:inspect` module.
+
+
+.. function:: get_unbound_function(meth)
+
+ Get the function out of unbound method *meth*. In Python 3, unbound methods
+ don't exist, so this function just returns *meth* unchanged. Example
+ usage::
+
+ from six import get_unbound_function
+
+ class X(object):
+ def method(self):
+ pass
+ method_function = get_unbound_function(X.method)
+
+
+.. function:: get_method_function(meth)
+
+ Get the function out of method object *meth*.
+
+
+.. function:: get_method_self(meth)
+
+ Get the ``self`` of bound method *meth*.
+
+
+.. function:: get_function_closure(func)
+
+ Get the closure (list of cells) associated with *func*. This is equivalent
+ to ``func.__closure__`` on Python 2.6+ and ``func.func_closure`` on Python
+ 2.5.
+
+
+.. function:: get_function_code(func)
+
+ Get the code object associated with *func*. This is equivalent to
+ ``func.__code__`` on Python 2.6+ and ``func.func_code`` on Python 2.5.
+
+
+.. function:: get_function_defaults(func)
+
+ Get the defaults tuple associated with *func*. This is equivalent to
+ ``func.__defaults__`` on Python 2.6+ and ``func.func_defaults`` on Python
+ 2.5.
+
+
+.. function:: get_function_globals(func)
+
+ Get the globals of *func*. This is equivalent to ``func.__globals__`` on
+ Python 2.6+ and ``func.func_globals`` on Python 2.5.
+
+
+.. function:: next(it)
+ advance_iterator(it)
+
+ Get the next item of iterator *it*. :exc:`py3:StopIteration` is raised if
+ the iterator is exhausted. This is a replacement for calling ``it.next()``
+ in Python 2 and ``next(it)`` in Python 3.
+
+
+.. function:: callable(obj)
+
+ Check if *obj* can be called. Note ``callable`` has returned in Python 3.2,
+ so using six's version is only necessary when supporting Python 3.0 or 3.1.
+
+
+.. function:: iterkeys(dictionary, **kwargs)
+
+ Returns an iterator over *dictionary*\'s keys. This replaces
+ ``dictionary.iterkeys()`` on Python 2 and ``dictionary.keys()`` on
+ Python 3. *kwargs* are passed through to the underlying method.
+
+
+.. function:: itervalues(dictionary, **kwargs)
+
+ Returns an iterator over *dictionary*\'s values. This replaces
+ ``dictionary.itervalues()`` on Python 2 and ``dictionary.values()`` on
+ Python 3. *kwargs* are passed through to the underlying method.
+
+
+.. function:: iteritems(dictionary, **kwargs)
+
+ Returns an iterator over *dictionary*\'s items. This replaces
+ ``dictionary.iteritems()`` on Python 2 and ``dictionary.items()`` on
+ Python 3. *kwargs* are passed through to the underlying method.
+
+
+.. function:: iterlists(dictionary, **kwargs)
+
+ Calls ``dictionary.iterlists()`` on Python 2 and ``dictionary.lists()`` on
+ Python 3. No builtin Python mapping type has such a method; this method is
+ intended for use with multi-valued dictionaries like `Werkzeug's
+ <http://werkzeug.pocoo.org/docs/datastructures/#werkzeug.datastructures.MultiDict>`_.
+ *kwargs* are passed through to the underlying method.
+
+
+.. function:: viewkeys(dictionary)
+
+ Return a view over *dictionary*\'s keys. This replaces
+ :meth:`py2:dict.viewkeys` on Python 2.7 and :meth:`py3:dict.keys` on
+ Python 3.
+
+
+.. function:: viewvalues(dictionary)
+
+ Return a view over *dictionary*\'s values. This replaces
+ :meth:`py2:dict.viewvalues` on Python 2.7 and :meth:`py3:dict.values` on
+ Python 3.
+
+
+.. function:: viewitems(dictionary)
+
+ Return a view over *dictionary*\'s items. This replaces
+ :meth:`py2:dict.viewitems` on Python 2.7 and :meth:`py3:dict.items` on
+ Python 3.
+
+
+.. function:: create_bound_method(func, obj)
+
+ Return a method object wrapping *func* and bound to *obj*. On both Python 2
+ and 3, this will return a :func:`py3:types.MethodType` object. The reason
+ this wrapper exists is that on Python 2, the ``MethodType`` constructor
+ requires the *obj*'s class to be passed.
+
+
+.. class:: Iterator
+
+ A class for making portable iterators. The intention is that it be subclassed
+ and subclasses provide a ``__next__`` method. In Python 2, :class:`Iterator`
+ has one method: ``next``. It simply delegates to ``__next__``. An alternate
+ way to do this would be to simply alias ``next`` to ``__next__``. However,
+ this interacts badly with subclasses that override
+ ``__next__``. :class:`Iterator` is empty on Python 3. (In fact, it is just
+ aliased to :class:`py3:object`.)
+
+
+.. function:: wraps(wrapped, assigned=functools.WRAPPER_ASSIGNMENTS, updated=functools.WRAPPER_UPDATES)
+
+ This is exactly the :func:`py3:functools.wraps` decorator, but it sets the
+ ``__wrapped__`` attribute on what it decorates as :func:`py3:functools.wraps`
+ does on Python versions after 3.2.
+
+
+Syntax compatibility
+>>>>>>>>>>>>>>>>>>>>
+
+These functions smooth over operations which have different syntaxes between
+Python 2 and 3.
+
+
+.. function:: exec_(code, globals=None, locals=None)
+
+ Execute *code* in the scope of *globals* and *locals*. *code* can be a
+ string or a code object. If *globals* or *locals* are not given, they will
+ default to the scope of the caller. If just *globals* is given, it will also
+ be used as *locals*.
+
+ .. note::
+
+ Python 3's :func:`py3:exec` doesn't take keyword arguments, so calling
+ :func:`exec` with them should be avoided.
+
+
+.. function:: print_(*args, *, file=sys.stdout, end="\\n", sep=" ")
+
+ Print *args* into *file*. Each argument will be separated with *sep* and
+ *end* will be written to the file after the last argument is printed.
+
+ .. note::
+
+ In Python 2, this function imitates Python 3's :func:`py3:print` by not
+ having softspace support. If you don't know what that is, you're probably
+ ok. :)
+
+
+.. function:: raise_from(exc_value, exc_value_from)
+
+ Raise an exception from a context. On Python 3, this is equivalent to
+ ``raise exc_value from exc_value_from``. On Python 2, which does not support
+ exception chaining, it is equivalent to ``raise exc_value``.
+
+
+.. function:: reraise(exc_type, exc_value, exc_traceback=None)
+
+ Reraise an exception, possibly with a different traceback. In the simple
+ case, ``reraise(*sys.exc_info())`` with an active exception (in an except
+ block) reraises the current exception with the last traceback. A different
+ traceback can be specified with the *exc_traceback* parameter. Note that
+ since the exception reraising is done within the :func:`reraise` function,
+ Python will attach the call frame of :func:`reraise` to whatever traceback is
+ raised.
+
+
+.. function:: with_metaclass(metaclass, *bases)
+
+ Create a new class with base classes *bases* and metaclass *metaclass*. This
+ is designed to be used in class declarations like this: ::
+
+ from six import with_metaclass
+
+ class Meta(type):
+ pass
+
+ class Base(object):
+ pass
+
+ class MyClass(with_metaclass(Meta, Base)):
+ pass
+
+ Another way to set a metaclass on a class is with the :func:`add_metaclass`
+ decorator.
+
+
+.. function:: add_metaclass(metaclass)
+
+ Class decorator that replaces a normally-constructed class with a
+ metaclass-constructed one. Example usage: ::
+
+ @add_metaclass(Meta)
+ class MyClass(object):
+ pass
+
+ That code produces a class equivalent to ::
+
+ class MyClass(object, metaclass=Meta):
+ pass
+
+ on Python 3 or ::
+
+ class MyClass(object):
+ __metaclass__ = MyMeta
+
+ on Python 2.
+
+ Note that class decorators require Python 2.6. However, the effect of the
+ decorator can be emulated on Python 2.5 like so::
+
+ class MyClass(object):
+ pass
+ MyClass = add_metaclass(Meta)(MyClass)
+
+
+Binary and text data
+>>>>>>>>>>>>>>>>>>>>
+
+Python 3 enforces the distinction between byte strings and text strings far more
+rigoriously than Python 2 does; binary data cannot be automatically coerced to
+or from text data. six provides several functions to assist in classifying
+string data in all Python versions.
+
+
+.. function:: b(data)
+
+ A "fake" bytes literal. *data* should always be a normal string literal. In
+ Python 2, :func:`b` returns a 8-bit string. In Python 3, *data* is encoded
+ with the latin-1 encoding to bytes.
+
+
+ .. note::
+
+ Since all Python versions 2.6 and after support the ``b`` prefix,
+ :func:`b`, code without 2.5 support doesn't need :func:`b`.
+
+
+.. function:: u(text)
+
+ A "fake" unicode literal. *text* should always be a normal string literal.
+ In Python 2, :func:`u` returns unicode, and in Python 3, a string. Also, in
+ Python 2, the string is decoded with the ``unicode-escape`` codec, which
+ allows unicode escapes to be used in it.
+
+
+ .. note::
+
+ In Python 3.3, the ``u`` prefix has been reintroduced. Code that only
+ supports Python 3 versions greater than 3.3 thus does not need
+ :func:`u`.
+
+ .. note::
+
+ On Python 2, :func:`u` doesn't know what the encoding of the literal
+ is. Each byte is converted directly to the unicode codepoint of the same
+ value. Because of this, it's only safe to use :func:`u` with strings of
+ ASCII data.
+
+
+.. function:: unichr(c)
+
+ Return the (Unicode) string representing the codepoint *c*. This is
+ equivalent to :func:`py2:unichr` on Python 2 and :func:`py3:chr` on Python 3.
+
+
+.. function:: int2byte(i)
+
+ Converts *i* to a byte. *i* must be in ``range(0, 256)``. This is
+ equivalent to :func:`py2:chr` in Python 2 and ``bytes((i,))`` in Python 3.
+
+
+.. function:: byte2int(bs)
+
+ Converts the first byte of *bs* to an integer. This is equivalent to
+ ``ord(bs[0])`` on Python 2 and ``bs[0]`` on Python 3.
+
+
+.. function:: indexbytes(buf, i)
+
+ Return the byte at index *i* of *buf* as an integer. This is equivalent to
+ indexing a bytes object in Python 3.
+
+
+.. function:: iterbytes(buf)
+
+ Return an iterator over bytes in *buf* as integers. This is equivalent to
+ a bytes object iterator in Python 3.
+
+
+.. data:: StringIO
+
+ This is an fake file object for textual data. It's an alias for
+ :class:`py2:StringIO.StringIO` in Python 2 and :class:`py3:io.StringIO` in
+ Python 3.
+
+
+.. data:: BytesIO
+
+ This is a fake file object for binary data. In Python 2, it's an alias for
+ :class:`py2:StringIO.StringIO`, but in Python 3, it's an alias for
+ :class:`py3:io.BytesIO`.
+
+
+Renamed modules and attributes compatibility
+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+
+.. module:: six.moves
+ :synopsis: Renamed modules and attributes compatibility
+
+Python 3 reorganized the standard library and moved several functions to
+different modules. Six provides a consistent interface to them through the fake
+:mod:`six.moves` module. For example, to load the module for parsing HTML on
+Python 2 or 3, write::
+
+ from six.moves import html_parser
+
+Similarly, to get the function to reload modules, which was moved from the
+builtin module to the ``imp`` module, use::
+
+ from six.moves import reload_module
+
+For the most part, :mod:`six.moves` aliases are the names of the modules in
+Python 3. When the new Python 3 name is a package, the components of the name
+are separated by underscores. For example, ``html.parser`` becomes
+``html_parser``. In some cases where several modules have been combined, the
+Python 2 name is retained. This is so the appropiate modules can be found when
+running on Python 2. For example, ``BaseHTTPServer`` which is in
+``http.server`` in Python 3 is aliased as ``BaseHTTPServer``.
+
+Some modules which had two implementations have been merged in Python 3. For
+example, ``cPickle`` no longer exists in Python 3; it was merged with
+``pickle``. In these cases, fetching the fast version will load the fast one on
+Python 2 and the merged module in Python 3.
+
+The :mod:`py2:urllib`, :mod:`py2:urllib2`, and :mod:`py2:urlparse` modules have
+been combined in the :mod:`py3:urllib` package in Python 3. The
+:mod:`six.moves.urllib` package is a version-independent location for this
+functionality; its structure mimics the structure of the Python 3
+:mod:`py3:urllib` package.
+
+.. note::
+
+ In order to make imports of the form::
+
+ from six.moves.cPickle import loads
+
+ work, six places special proxy objects in in :data:`py3:sys.modules`. These
+ proxies lazily load the underlying module when an attribute is fetched. This
+ will fail if the underlying module is not available in the Python
+ interpreter. For example, ``sys.modules["six.moves.winreg"].LoadKey`` would
+ fail on any non-Windows platform. Unfortunately, some applications try to
+ load attributes on every module in :data:`py3:sys.modules`. six mitigates
+ this problem for some applications by pretending attributes on unimportable
+ modules don't exist. This hack doesn't work in every case, though. If you are
+ encountering problems with the lazy modules and don't use any from imports
+ directly from ``six.moves`` modules, you can workaround the issue by removing
+ the six proxy modules::
+
+ d = [name for name in sys.modules if name.startswith("six.moves.")]
+ for name in d:
+ del sys.modules[name]
+
+Supported renames:
+
++------------------------------+-------------------------------------+-------------------------------------+
+| Name | Python 2 name | Python 3 name |
++==============================+=====================================+=====================================+
+| ``builtins`` | :mod:`py2:__builtin__` | :mod:`py3:builtins` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``configparser`` | :mod:`py2:ConfigParser` | :mod:`py3:configparser` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``copyreg`` | :mod:`py2:copy_reg` | :mod:`py3:copyreg` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``cPickle`` | :mod:`py2:cPickle` | :mod:`py3:pickle` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``cStringIO`` | :func:`py2:cStringIO.StringIO` | :class:`py3:io.StringIO` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``dbm_gnu`` | :func:`py2:gdbm` | :class:`py3:dbm.gnu` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``_dummy_thread`` | :mod:`py2:dummy_thread` | :mod:`py3:_dummy_thread` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``email_mime_multipart`` | :mod:`py2:email.MIMEMultipart` | :mod:`py3:email.mime.multipart` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``email_mime_nonmultipart`` | :mod:`py2:email.MIMENonMultipart` | :mod:`py3:email.mime.nonmultipart` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``email_mime_text`` | :mod:`py2:email.MIMEText` | :mod:`py3:email.mime.text` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``email_mime_base`` | :mod:`py2:email.MIMEBase` | :mod:`py3:email.mime.base` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``filter`` | :func:`py2:itertools.ifilter` | :func:`py3:filter` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``filterfalse`` | :func:`py2:itertools.ifilterfalse` | :func:`py3:itertools.filterfalse` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``http_cookiejar`` | :mod:`py2:cookielib` | :mod:`py3:http.cookiejar` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``http_cookies`` | :mod:`py2:Cookie` | :mod:`py3:http.cookies` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``html_entities`` | :mod:`py2:htmlentitydefs` | :mod:`py3:html.entities` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``html_parser`` | :mod:`py2:HTMLParser` | :mod:`py3:html.parser` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``http_client`` | :mod:`py2:httplib` | :mod:`py3:http.client` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``BaseHTTPServer`` | :mod:`py2:BaseHTTPServer` | :mod:`py3:http.server` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``CGIHTTPServer`` | :mod:`py2:CGIHTTPServer` | :mod:`py3:http.server` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``SimpleHTTPServer`` | :mod:`py2:SimpleHTTPServer` | :mod:`py3:http.server` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``input`` | :func:`py2:raw_input` | :func:`py3:input` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``intern`` | :func:`py2:intern` | :func:`py3:sys.intern` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``map`` | :func:`py2:itertools.imap` | :func:`py3:map` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``queue`` | :mod:`py2:Queue` | :mod:`py3:queue` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``range`` | :func:`py2:xrange` | :func:`py3:range` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``reduce`` | :func:`py2:reduce` | :func:`py3:functools.reduce` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``reload_module`` | :func:`py2:reload` | :func:`py3:imp.reload` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``reprlib`` | :mod:`py2:repr` | :mod:`py3:reprlib` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``shlex_quote`` | :mod:`py2:pipes.quote` | :mod:`py3:shlex.quote` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``socketserver`` | :mod:`py2:SocketServer` | :mod:`py3:socketserver` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``_thread`` | :mod:`py2:thread` | :mod:`py3:_thread` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``tkinter`` | :mod:`py2:Tkinter` | :mod:`py3:tkinter` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``tkinter_dialog`` | :mod:`py2:Dialog` | :mod:`py3:tkinter.dialog` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``tkinter_filedialog`` | :mod:`py2:FileDialog` | :mod:`py3:tkinter.FileDialog` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``tkinter_scrolledtext`` | :mod:`py2:ScrolledText` | :mod:`py3:tkinter.scrolledtext` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``tkinter_simpledialog`` | :mod:`py2:SimpleDialog` | :mod:`py3:tkinter.simpledialog` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``tkinter_ttk`` | :mod:`py2:ttk` | :mod:`py3:tkinter.ttk` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``tkinter_tix`` | :mod:`py2:Tix` | :mod:`py3:tkinter.tix` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``tkinter_constants`` | :mod:`py2:Tkconstants` | :mod:`py3:tkinter.constants` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``tkinter_dnd`` | :mod:`py2:Tkdnd` | :mod:`py3:tkinter.dnd` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``tkinter_colorchooser`` | :mod:`py2:tkColorChooser` | :mod:`py3:tkinter.colorchooser` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``tkinter_commondialog`` | :mod:`py2:tkCommonDialog` | :mod:`py3:tkinter.commondialog` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``tkinter_tkfiledialog`` | :mod:`py2:tkFileDialog` | :mod:`py3:tkinter.filedialog` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``tkinter_font`` | :mod:`py2:tkFont` | :mod:`py3:tkinter.font` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``tkinter_messagebox`` | :mod:`py2:tkMessageBox` | :mod:`py3:tkinter.messagebox` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``tkinter_tksimpledialog`` | :mod:`py2:tkSimpleDialog` | :mod:`py3:tkinter.simpledialog` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``urllib.parse`` | See :mod:`six.moves.urllib.parse` | :mod:`py3:urllib.parse` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``urllib.error`` | See :mod:`six.moves.urllib.error` | :mod:`py3:urllib.error` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``urllib.request`` | See :mod:`six.moves.urllib.request` | :mod:`py3:urllib.request` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``urllib.response`` | See :mod:`six.moves.urllib.response`| :mod:`py3:urllib.response` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``urllib.robotparser`` | :mod:`py2:robotparser` | :mod:`py3:urllib.robotparser` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``urllib_robotparser`` | :mod:`py2:robotparser` | :mod:`py3:urllib.robotparser` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``UserDict`` | :class:`py2:UserDict.UserDict` | :class:`py3:collections.UserDict` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``UserList`` | :class:`py2:UserList.UserList` | :class:`py3:collections.UserList` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``UserString`` | :class:`py2:UserString.UserString` | :class:`py3:collections.UserString` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``winreg`` | :mod:`py2:_winreg` | :mod:`py3:winreg` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``xmlrpc_client`` | :mod:`py2:xmlrpclib` | :mod:`py3:xmlrpc.client` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``xmlrpc_server`` | :mod:`py2:SimpleXMLRPCServer` | :mod:`py3:xmlrpc.server` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``xrange`` | :func:`py2:xrange` | :func:`py3:range` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``zip`` | :func:`py2:itertools.izip` | :func:`py3:zip` |
++------------------------------+-------------------------------------+-------------------------------------+
+| ``zip_longest`` | :func:`py2:itertools.izip_longest` | :func:`py3:itertools.zip_longest` |
++------------------------------+-------------------------------------+-------------------------------------+
+
+urllib parse
+<<<<<<<<<<<<
+
+.. module:: six.moves.urllib.parse
+ :synopsis: Stuff from :mod:`py2:urlparse` and :mod:`py2:urllib` in Python 2 and :mod:`py3:urllib.parse` in Python 3
+
+Contains functions from Python 3's :mod:`py3:urllib.parse` and Python 2's:
+
+:mod:`py2:urlparse`:
+
+* :func:`py2:urlparse.ParseResult`
+* :func:`py2:urlparse.SplitResult`
+* :func:`py2:urlparse.urlparse`
+* :func:`py2:urlparse.urlunparse`
+* :func:`py2:urlparse.parse_qs`
+* :func:`py2:urlparse.parse_qsl`
+* :func:`py2:urlparse.urljoin`
+* :func:`py2:urlparse.urldefrag`
+* :func:`py2:urlparse.urlsplit`
+* :func:`py2:urlparse.urlunsplit`
+* :func:`py2:urlparse.splitquery`
+* :func:`py2:urlparse.uses_fragment`
+* :func:`py2:urlparse.uses_netloc`
+* :func:`py2:urlparse.uses_params`
+* :func:`py2:urlparse.uses_query`
+* :func:`py2:urlparse.uses_relative`
+
+and :mod:`py2:urllib`:
+
+* :func:`py2:urllib.quote`
+* :func:`py2:urllib.quote_plus`
+* :func:`py2:urllib.splittag`
+* :func:`py2:urllib.splituser`
+* :func:`py2:urllib.unquote`
+* :func:`py2:urllib.unquote_plus`
+* :func:`py2:urllib.urlencode`
+
+
+urllib error
+<<<<<<<<<<<<
+
+.. module:: six.moves.urllib.error
+ :synopsis: Stuff from :mod:`py2:urllib` and :mod:`py2:urllib2` in Python 2 and :mod:`py3:urllib.error` in Python 3
+
+Contains exceptions from Python 3's :mod:`py3:urllib.error` and Python 2's:
+
+:mod:`py2:urllib`:
+
+* :exc:`py2:urllib.ContentTooShortError`
+
+and :mod:`py2:urllib2`:
+
+* :exc:`py2:urllib2.URLError`
+* :exc:`py2:urllib2.HTTPError`
+
+
+urllib request
+<<<<<<<<<<<<<<
+
+.. module:: six.moves.urllib.request
+ :synopsis: Stuff from :mod:`py2:urllib` and :mod:`py2:urllib2` in Python 2 and :mod:`py3:urllib.request` in Python 3
+
+Contains items from Python 3's :mod:`py3:urllib.request` and Python 2's:
+
+:mod:`py2:urllib`:
+
+* :func:`py2:urllib.pathname2url`
+* :func:`py2:urllib.url2pathname`
+* :func:`py2:urllib.getproxies`
+* :func:`py2:urllib.urlretrieve`
+* :func:`py2:urllib.urlcleanup`
+* :class:`py2:urllib.URLopener`
+* :class:`py2:urllib.FancyURLopener`
+* :func:`py2:urllib.proxy_bypass`
+
+and :mod:`py2:urllib2`:
+
+* :func:`py2:urllib2.urlopen`
+* :func:`py2:urllib2.install_opener`
+* :func:`py2:urllib2.build_opener`
+* :class:`py2:urllib2.Request`
+* :class:`py2:urllib2.OpenerDirector`
+* :class:`py2:urllib2.HTTPDefaultErrorHandler`
+* :class:`py2:urllib2.HTTPRedirectHandler`
+* :class:`py2:urllib2.HTTPCookieProcessor`
+* :class:`py2:urllib2.ProxyHandler`
+* :class:`py2:urllib2.BaseHandler`
+* :class:`py2:urllib2.HTTPPasswordMgr`
+* :class:`py2:urllib2.HTTPPasswordMgrWithDefaultRealm`
+* :class:`py2:urllib2.AbstractBasicAuthHandler`
+* :class:`py2:urllib2.HTTPBasicAuthHandler`
+* :class:`py2:urllib2.ProxyBasicAuthHandler`
+* :class:`py2:urllib2.AbstractDigestAuthHandler`
+* :class:`py2:urllib2.HTTPDigestAuthHandler`
+* :class:`py2:urllib2.ProxyDigestAuthHandler`
+* :class:`py2:urllib2.HTTPHandler`
+* :class:`py2:urllib2.HTTPSHandler`
+* :class:`py2:urllib2.FileHandler`
+* :class:`py2:urllib2.FTPHandler`
+* :class:`py2:urllib2.CacheFTPHandler`
+* :class:`py2:urllib2.UnknownHandler`
+* :class:`py2:urllib2.HTTPErrorProcessor`
+
+
+urllib response
+<<<<<<<<<<<<<<<
+
+.. module:: six.moves.urllib.response
+ :synopsis: Stuff from :mod:`py2:urllib` in Python 2 and :mod:`py3:urllib.response` in Python 3
+
+Contains classes from Python 3's :mod:`py3:urllib.response` and Python 2's:
+
+:mod:`py2:urllib`:
+
+* :class:`py2:urllib.addbase`
+* :class:`py2:urllib.addclosehook`
+* :class:`py2:urllib.addinfo`
+* :class:`py2:urllib.addinfourl`
+
+
+Advanced - Customizing renames
+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+
+.. currentmodule:: six
+
+It is possible to add additional names to the :mod:`six.moves` namespace.
+
+
+.. function:: add_move(item)
+
+ Add *item* to the :mod:`six.moves` mapping. *item* should be a
+ :class:`MovedAttribute` or :class:`MovedModule` instance.
+
+
+.. function:: remove_move(name)
+
+ Remove the :mod:`six.moves` mapping called *name*. *name* should be a
+ string.
+
+
+Instances of the following classes can be passed to :func:`add_move`. Neither
+have any public members.
+
+
+.. class:: MovedModule(name, old_mod, new_mod)
+
+ Create a mapping for :mod:`six.moves` called *name* that references different
+ modules in Python 2 and 3. *old_mod* is the name of the Python 2 module.
+ *new_mod* is the name of the Python 3 module.
+
+
+.. class:: MovedAttribute(name, old_mod, new_mod, old_attr=None, new_attr=None)
+
+ Create a mapping for :mod:`six.moves` called *name* that references different
+ attributes in Python 2 and 3. *old_mod* is the name of the Python 2 module.
+ *new_mod* is the name of the Python 3 module. If *new_attr* is not given, it
+ defaults to *old_attr*. If neither is given, they both default to *name*.
diff --git a/tests/wpt/web-platform-tests/tools/six/setup.cfg b/tests/wpt/web-platform-tests/tools/six/setup.cfg
new file mode 100644
index 00000000000..5e4090017a9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/six/setup.cfg
@@ -0,0 +1,2 @@
+[wheel]
+universal = 1
diff --git a/tests/wpt/web-platform-tests/tools/six/setup.py b/tests/wpt/web-platform-tests/tools/six/setup.py
new file mode 100644
index 00000000000..b0cca52d4a8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/six/setup.py
@@ -0,0 +1,32 @@
+from __future__ import with_statement
+
+try:
+ from setuptools import setup
+except ImportError:
+ from distutils.core import setup
+
+import six
+
+six_classifiers = [
+ "Programming Language :: Python :: 2",
+ "Programming Language :: Python :: 3",
+ "Intended Audience :: Developers",
+ "License :: OSI Approved :: MIT License",
+ "Topic :: Software Development :: Libraries",
+ "Topic :: Utilities",
+]
+
+with open("README", "r") as fp:
+ six_long_description = fp.read()
+
+setup(name="six",
+ version=six.__version__,
+ author="Benjamin Peterson",
+ author_email="benjamin@python.org",
+ url="http://pypi.python.org/pypi/six/",
+ py_modules=["six"],
+ description="Python 2 and 3 compatibility utilities",
+ long_description=six_long_description,
+ license="MIT",
+ classifiers=six_classifiers
+ )
diff --git a/tests/wpt/web-platform-tests/tools/six/six.py b/tests/wpt/web-platform-tests/tools/six/six.py
new file mode 100644
index 00000000000..686c20a15a6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/six/six.py
@@ -0,0 +1,787 @@
+"""Utilities for writing code that runs on Python 2 and 3"""
+
+# Copyright (c) 2010-2014 Benjamin Peterson
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+from __future__ import absolute_import
+
+import functools
+import itertools
+import operator
+import sys
+import types
+
+__author__ = "Benjamin Peterson <benjamin@python.org>"
+__version__ = "1.8.0"
+
+
+# Useful for very coarse version differentiation.
+PY2 = sys.version_info[0] == 2
+PY3 = sys.version_info[0] == 3
+
+if PY3:
+ string_types = str,
+ integer_types = int,
+ class_types = type,
+ text_type = str
+ binary_type = bytes
+
+ MAXSIZE = sys.maxsize
+else:
+ string_types = basestring,
+ integer_types = (int, long)
+ class_types = (type, types.ClassType)
+ text_type = unicode
+ binary_type = str
+
+ if sys.platform.startswith("java"):
+ # Jython always uses 32 bits.
+ MAXSIZE = int((1 << 31) - 1)
+ else:
+ # It's possible to have sizeof(long) != sizeof(Py_ssize_t).
+ class X(object):
+ def __len__(self):
+ return 1 << 31
+ try:
+ len(X())
+ except OverflowError:
+ # 32-bit
+ MAXSIZE = int((1 << 31) - 1)
+ else:
+ # 64-bit
+ MAXSIZE = int((1 << 63) - 1)
+ del X
+
+
+def _add_doc(func, doc):
+ """Add documentation to a function."""
+ func.__doc__ = doc
+
+
+def _import_module(name):
+ """Import module, returning the module after the last dot."""
+ __import__(name)
+ return sys.modules[name]
+
+
+class _LazyDescr(object):
+
+ def __init__(self, name):
+ self.name = name
+
+ def __get__(self, obj, tp):
+ result = self._resolve()
+ setattr(obj, self.name, result) # Invokes __set__.
+ try:
+ # This is a bit ugly, but it avoids running this again by
+ # removing this descriptor.
+ delattr(obj.__class__, self.name)
+ except AttributeError:
+ pass
+ return result
+
+
+class MovedModule(_LazyDescr):
+
+ def __init__(self, name, old, new=None):
+ super(MovedModule, self).__init__(name)
+ if PY3:
+ if new is None:
+ new = name
+ self.mod = new
+ else:
+ self.mod = old
+
+ def _resolve(self):
+ return _import_module(self.mod)
+
+ def __getattr__(self, attr):
+ _module = self._resolve()
+ value = getattr(_module, attr)
+ setattr(self, attr, value)
+ return value
+
+
+class _LazyModule(types.ModuleType):
+
+ def __init__(self, name):
+ super(_LazyModule, self).__init__(name)
+ self.__doc__ = self.__class__.__doc__
+
+ def __dir__(self):
+ attrs = ["__doc__", "__name__"]
+ attrs += [attr.name for attr in self._moved_attributes]
+ return attrs
+
+ # Subclasses should override this
+ _moved_attributes = []
+
+
+class MovedAttribute(_LazyDescr):
+
+ def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None):
+ super(MovedAttribute, self).__init__(name)
+ if PY3:
+ if new_mod is None:
+ new_mod = name
+ self.mod = new_mod
+ if new_attr is None:
+ if old_attr is None:
+ new_attr = name
+ else:
+ new_attr = old_attr
+ self.attr = new_attr
+ else:
+ self.mod = old_mod
+ if old_attr is None:
+ old_attr = name
+ self.attr = old_attr
+
+ def _resolve(self):
+ module = _import_module(self.mod)
+ return getattr(module, self.attr)
+
+
+class _SixMetaPathImporter(object):
+ """
+ A meta path importer to import six.moves and its submodules.
+
+ This class implements a PEP302 finder and loader. It should be compatible
+ with Python 2.5 and all existing versions of Python3
+ """
+ def __init__(self, six_module_name):
+ self.name = six_module_name
+ self.known_modules = {}
+
+ def _add_module(self, mod, *fullnames):
+ for fullname in fullnames:
+ self.known_modules[self.name + "." + fullname] = mod
+
+ def _get_module(self, fullname):
+ return self.known_modules[self.name + "." + fullname]
+
+ def find_module(self, fullname, path=None):
+ if fullname in self.known_modules:
+ return self
+ return None
+
+ def __get_module(self, fullname):
+ try:
+ return self.known_modules[fullname]
+ except KeyError:
+ raise ImportError("This loader does not know module " + fullname)
+
+ def load_module(self, fullname):
+ try:
+ # in case of a reload
+ return sys.modules[fullname]
+ except KeyError:
+ pass
+ mod = self.__get_module(fullname)
+ if isinstance(mod, MovedModule):
+ mod = mod._resolve()
+ else:
+ mod.__loader__ = self
+ sys.modules[fullname] = mod
+ return mod
+
+ def is_package(self, fullname):
+ """
+ Return true, if the named module is a package.
+
+ We need this method to get correct spec objects with
+ Python 3.4 (see PEP451)
+ """
+ return hasattr(self.__get_module(fullname), "__path__")
+
+ def get_code(self, fullname):
+ """Return None
+
+ Required, if is_package is implemented"""
+ self.__get_module(fullname) # eventually raises ImportError
+ return None
+ get_source = get_code # same as get_code
+
+_importer = _SixMetaPathImporter(__name__)
+
+
+class _MovedItems(_LazyModule):
+ """Lazy loading of moved objects"""
+ __path__ = [] # mark as package
+
+
+_moved_attributes = [
+ MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"),
+ MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"),
+ MovedAttribute("filterfalse", "itertools", "itertools", "ifilterfalse", "filterfalse"),
+ MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"),
+ MovedAttribute("intern", "__builtin__", "sys"),
+ MovedAttribute("map", "itertools", "builtins", "imap", "map"),
+ MovedAttribute("range", "__builtin__", "builtins", "xrange", "range"),
+ MovedAttribute("reload_module", "__builtin__", "imp", "reload"),
+ MovedAttribute("reduce", "__builtin__", "functools"),
+ MovedAttribute("shlex_quote", "pipes", "shlex", "quote"),
+ MovedAttribute("StringIO", "StringIO", "io"),
+ MovedAttribute("UserDict", "UserDict", "collections"),
+ MovedAttribute("UserList", "UserList", "collections"),
+ MovedAttribute("UserString", "UserString", "collections"),
+ MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"),
+ MovedAttribute("zip", "itertools", "builtins", "izip", "zip"),
+ MovedAttribute("zip_longest", "itertools", "itertools", "izip_longest", "zip_longest"),
+
+ MovedModule("builtins", "__builtin__"),
+ MovedModule("configparser", "ConfigParser"),
+ MovedModule("copyreg", "copy_reg"),
+ MovedModule("dbm_gnu", "gdbm", "dbm.gnu"),
+ MovedModule("_dummy_thread", "dummy_thread", "_dummy_thread"),
+ MovedModule("http_cookiejar", "cookielib", "http.cookiejar"),
+ MovedModule("http_cookies", "Cookie", "http.cookies"),
+ MovedModule("html_entities", "htmlentitydefs", "html.entities"),
+ MovedModule("html_parser", "HTMLParser", "html.parser"),
+ MovedModule("http_client", "httplib", "http.client"),
+ MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"),
+ MovedModule("email_mime_nonmultipart", "email.MIMENonMultipart", "email.mime.nonmultipart"),
+ MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"),
+ MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"),
+ MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"),
+ MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"),
+ MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"),
+ MovedModule("cPickle", "cPickle", "pickle"),
+ MovedModule("queue", "Queue"),
+ MovedModule("reprlib", "repr"),
+ MovedModule("socketserver", "SocketServer"),
+ MovedModule("_thread", "thread", "_thread"),
+ MovedModule("tkinter", "Tkinter"),
+ MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"),
+ MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"),
+ MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"),
+ MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"),
+ MovedModule("tkinter_tix", "Tix", "tkinter.tix"),
+ MovedModule("tkinter_ttk", "ttk", "tkinter.ttk"),
+ MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"),
+ MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"),
+ MovedModule("tkinter_colorchooser", "tkColorChooser",
+ "tkinter.colorchooser"),
+ MovedModule("tkinter_commondialog", "tkCommonDialog",
+ "tkinter.commondialog"),
+ MovedModule("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"),
+ MovedModule("tkinter_font", "tkFont", "tkinter.font"),
+ MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"),
+ MovedModule("tkinter_tksimpledialog", "tkSimpleDialog",
+ "tkinter.simpledialog"),
+ MovedModule("urllib_parse", __name__ + ".moves.urllib_parse", "urllib.parse"),
+ MovedModule("urllib_error", __name__ + ".moves.urllib_error", "urllib.error"),
+ MovedModule("urllib", __name__ + ".moves.urllib", __name__ + ".moves.urllib"),
+ MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"),
+ MovedModule("xmlrpc_client", "xmlrpclib", "xmlrpc.client"),
+ MovedModule("xmlrpc_server", "SimpleXMLRPCServer", "xmlrpc.server"),
+ MovedModule("winreg", "_winreg"),
+]
+for attr in _moved_attributes:
+ setattr(_MovedItems, attr.name, attr)
+ if isinstance(attr, MovedModule):
+ _importer._add_module(attr, "moves." + attr.name)
+del attr
+
+_MovedItems._moved_attributes = _moved_attributes
+
+moves = _MovedItems(__name__ + ".moves")
+_importer._add_module(moves, "moves")
+
+
+class Module_six_moves_urllib_parse(_LazyModule):
+ """Lazy loading of moved objects in six.moves.urllib_parse"""
+
+
+_urllib_parse_moved_attributes = [
+ MovedAttribute("ParseResult", "urlparse", "urllib.parse"),
+ MovedAttribute("SplitResult", "urlparse", "urllib.parse"),
+ MovedAttribute("parse_qs", "urlparse", "urllib.parse"),
+ MovedAttribute("parse_qsl", "urlparse", "urllib.parse"),
+ MovedAttribute("urldefrag", "urlparse", "urllib.parse"),
+ MovedAttribute("urljoin", "urlparse", "urllib.parse"),
+ MovedAttribute("urlparse", "urlparse", "urllib.parse"),
+ MovedAttribute("urlsplit", "urlparse", "urllib.parse"),
+ MovedAttribute("urlunparse", "urlparse", "urllib.parse"),
+ MovedAttribute("urlunsplit", "urlparse", "urllib.parse"),
+ MovedAttribute("quote", "urllib", "urllib.parse"),
+ MovedAttribute("quote_plus", "urllib", "urllib.parse"),
+ MovedAttribute("unquote", "urllib", "urllib.parse"),
+ MovedAttribute("unquote_plus", "urllib", "urllib.parse"),
+ MovedAttribute("urlencode", "urllib", "urllib.parse"),
+ MovedAttribute("splitquery", "urllib", "urllib.parse"),
+ MovedAttribute("splittag", "urllib", "urllib.parse"),
+ MovedAttribute("splituser", "urllib", "urllib.parse"),
+ MovedAttribute("uses_fragment", "urlparse", "urllib.parse"),
+ MovedAttribute("uses_netloc", "urlparse", "urllib.parse"),
+ MovedAttribute("uses_params", "urlparse", "urllib.parse"),
+ MovedAttribute("uses_query", "urlparse", "urllib.parse"),
+ MovedAttribute("uses_relative", "urlparse", "urllib.parse"),
+]
+for attr in _urllib_parse_moved_attributes:
+ setattr(Module_six_moves_urllib_parse, attr.name, attr)
+del attr
+
+Module_six_moves_urllib_parse._moved_attributes = _urllib_parse_moved_attributes
+
+_importer._add_module(Module_six_moves_urllib_parse(__name__ + ".moves.urllib_parse"),
+ "moves.urllib_parse", "moves.urllib.parse")
+
+
+class Module_six_moves_urllib_error(_LazyModule):
+ """Lazy loading of moved objects in six.moves.urllib_error"""
+
+
+_urllib_error_moved_attributes = [
+ MovedAttribute("URLError", "urllib2", "urllib.error"),
+ MovedAttribute("HTTPError", "urllib2", "urllib.error"),
+ MovedAttribute("ContentTooShortError", "urllib", "urllib.error"),
+]
+for attr in _urllib_error_moved_attributes:
+ setattr(Module_six_moves_urllib_error, attr.name, attr)
+del attr
+
+Module_six_moves_urllib_error._moved_attributes = _urllib_error_moved_attributes
+
+_importer._add_module(Module_six_moves_urllib_error(__name__ + ".moves.urllib.error"),
+ "moves.urllib_error", "moves.urllib.error")
+
+
+class Module_six_moves_urllib_request(_LazyModule):
+ """Lazy loading of moved objects in six.moves.urllib_request"""
+
+
+_urllib_request_moved_attributes = [
+ MovedAttribute("urlopen", "urllib2", "urllib.request"),
+ MovedAttribute("install_opener", "urllib2", "urllib.request"),
+ MovedAttribute("build_opener", "urllib2", "urllib.request"),
+ MovedAttribute("pathname2url", "urllib", "urllib.request"),
+ MovedAttribute("url2pathname", "urllib", "urllib.request"),
+ MovedAttribute("getproxies", "urllib", "urllib.request"),
+ MovedAttribute("Request", "urllib2", "urllib.request"),
+ MovedAttribute("OpenerDirector", "urllib2", "urllib.request"),
+ MovedAttribute("HTTPDefaultErrorHandler", "urllib2", "urllib.request"),
+ MovedAttribute("HTTPRedirectHandler", "urllib2", "urllib.request"),
+ MovedAttribute("HTTPCookieProcessor", "urllib2", "urllib.request"),
+ MovedAttribute("ProxyHandler", "urllib2", "urllib.request"),
+ MovedAttribute("BaseHandler", "urllib2", "urllib.request"),
+ MovedAttribute("HTTPPasswordMgr", "urllib2", "urllib.request"),
+ MovedAttribute("HTTPPasswordMgrWithDefaultRealm", "urllib2", "urllib.request"),
+ MovedAttribute("AbstractBasicAuthHandler", "urllib2", "urllib.request"),
+ MovedAttribute("HTTPBasicAuthHandler", "urllib2", "urllib.request"),
+ MovedAttribute("ProxyBasicAuthHandler", "urllib2", "urllib.request"),
+ MovedAttribute("AbstractDigestAuthHandler", "urllib2", "urllib.request"),
+ MovedAttribute("HTTPDigestAuthHandler", "urllib2", "urllib.request"),
+ MovedAttribute("ProxyDigestAuthHandler", "urllib2", "urllib.request"),
+ MovedAttribute("HTTPHandler", "urllib2", "urllib.request"),
+ MovedAttribute("HTTPSHandler", "urllib2", "urllib.request"),
+ MovedAttribute("FileHandler", "urllib2", "urllib.request"),
+ MovedAttribute("FTPHandler", "urllib2", "urllib.request"),
+ MovedAttribute("CacheFTPHandler", "urllib2", "urllib.request"),
+ MovedAttribute("UnknownHandler", "urllib2", "urllib.request"),
+ MovedAttribute("HTTPErrorProcessor", "urllib2", "urllib.request"),
+ MovedAttribute("urlretrieve", "urllib", "urllib.request"),
+ MovedAttribute("urlcleanup", "urllib", "urllib.request"),
+ MovedAttribute("URLopener", "urllib", "urllib.request"),
+ MovedAttribute("FancyURLopener", "urllib", "urllib.request"),
+ MovedAttribute("proxy_bypass", "urllib", "urllib.request"),
+]
+for attr in _urllib_request_moved_attributes:
+ setattr(Module_six_moves_urllib_request, attr.name, attr)
+del attr
+
+Module_six_moves_urllib_request._moved_attributes = _urllib_request_moved_attributes
+
+_importer._add_module(Module_six_moves_urllib_request(__name__ + ".moves.urllib.request"),
+ "moves.urllib_request", "moves.urllib.request")
+
+
+class Module_six_moves_urllib_response(_LazyModule):
+ """Lazy loading of moved objects in six.moves.urllib_response"""
+
+
+_urllib_response_moved_attributes = [
+ MovedAttribute("addbase", "urllib", "urllib.response"),
+ MovedAttribute("addclosehook", "urllib", "urllib.response"),
+ MovedAttribute("addinfo", "urllib", "urllib.response"),
+ MovedAttribute("addinfourl", "urllib", "urllib.response"),
+]
+for attr in _urllib_response_moved_attributes:
+ setattr(Module_six_moves_urllib_response, attr.name, attr)
+del attr
+
+Module_six_moves_urllib_response._moved_attributes = _urllib_response_moved_attributes
+
+_importer._add_module(Module_six_moves_urllib_response(__name__ + ".moves.urllib.response"),
+ "moves.urllib_response", "moves.urllib.response")
+
+
+class Module_six_moves_urllib_robotparser(_LazyModule):
+ """Lazy loading of moved objects in six.moves.urllib_robotparser"""
+
+
+_urllib_robotparser_moved_attributes = [
+ MovedAttribute("RobotFileParser", "robotparser", "urllib.robotparser"),
+]
+for attr in _urllib_robotparser_moved_attributes:
+ setattr(Module_six_moves_urllib_robotparser, attr.name, attr)
+del attr
+
+Module_six_moves_urllib_robotparser._moved_attributes = _urllib_robotparser_moved_attributes
+
+_importer._add_module(Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib.robotparser"),
+ "moves.urllib_robotparser", "moves.urllib.robotparser")
+
+
+class Module_six_moves_urllib(types.ModuleType):
+ """Create a six.moves.urllib namespace that resembles the Python 3 namespace"""
+ __path__ = [] # mark as package
+ parse = _importer._get_module("moves.urllib_parse")
+ error = _importer._get_module("moves.urllib_error")
+ request = _importer._get_module("moves.urllib_request")
+ response = _importer._get_module("moves.urllib_response")
+ robotparser = _importer._get_module("moves.urllib_robotparser")
+
+ def __dir__(self):
+ return ['parse', 'error', 'request', 'response', 'robotparser']
+
+_importer._add_module(Module_six_moves_urllib(__name__ + ".moves.urllib"),
+ "moves.urllib")
+
+
+def add_move(move):
+ """Add an item to six.moves."""
+ setattr(_MovedItems, move.name, move)
+
+
+def remove_move(name):
+ """Remove item from six.moves."""
+ try:
+ delattr(_MovedItems, name)
+ except AttributeError:
+ try:
+ del moves.__dict__[name]
+ except KeyError:
+ raise AttributeError("no such move, %r" % (name,))
+
+
+if PY3:
+ _meth_func = "__func__"
+ _meth_self = "__self__"
+
+ _func_closure = "__closure__"
+ _func_code = "__code__"
+ _func_defaults = "__defaults__"
+ _func_globals = "__globals__"
+else:
+ _meth_func = "im_func"
+ _meth_self = "im_self"
+
+ _func_closure = "func_closure"
+ _func_code = "func_code"
+ _func_defaults = "func_defaults"
+ _func_globals = "func_globals"
+
+
+try:
+ advance_iterator = next
+except NameError:
+ def advance_iterator(it):
+ return it.next()
+next = advance_iterator
+
+
+try:
+ callable = callable
+except NameError:
+ def callable(obj):
+ return any("__call__" in klass.__dict__ for klass in type(obj).__mro__)
+
+
+if PY3:
+ def get_unbound_function(unbound):
+ return unbound
+
+ create_bound_method = types.MethodType
+
+ Iterator = object
+else:
+ def get_unbound_function(unbound):
+ return unbound.im_func
+
+ def create_bound_method(func, obj):
+ return types.MethodType(func, obj, obj.__class__)
+
+ class Iterator(object):
+
+ def next(self):
+ return type(self).__next__(self)
+
+ callable = callable
+_add_doc(get_unbound_function,
+ """Get the function out of a possibly unbound function""")
+
+
+get_method_function = operator.attrgetter(_meth_func)
+get_method_self = operator.attrgetter(_meth_self)
+get_function_closure = operator.attrgetter(_func_closure)
+get_function_code = operator.attrgetter(_func_code)
+get_function_defaults = operator.attrgetter(_func_defaults)
+get_function_globals = operator.attrgetter(_func_globals)
+
+
+if PY3:
+ def iterkeys(d, **kw):
+ return iter(d.keys(**kw))
+
+ def itervalues(d, **kw):
+ return iter(d.values(**kw))
+
+ def iteritems(d, **kw):
+ return iter(d.items(**kw))
+
+ def iterlists(d, **kw):
+ return iter(d.lists(**kw))
+
+ viewkeys = operator.methodcaller("keys")
+
+ viewvalues = operator.methodcaller("values")
+
+ viewitems = operator.methodcaller("items")
+else:
+ def iterkeys(d, **kw):
+ return iter(d.iterkeys(**kw))
+
+ def itervalues(d, **kw):
+ return iter(d.itervalues(**kw))
+
+ def iteritems(d, **kw):
+ return iter(d.iteritems(**kw))
+
+ def iterlists(d, **kw):
+ return iter(d.iterlists(**kw))
+
+ viewkeys = operator.methodcaller("viewkeys")
+
+ viewvalues = operator.methodcaller("viewvalues")
+
+ viewitems = operator.methodcaller("viewitems")
+
+_add_doc(iterkeys, "Return an iterator over the keys of a dictionary.")
+_add_doc(itervalues, "Return an iterator over the values of a dictionary.")
+_add_doc(iteritems,
+ "Return an iterator over the (key, value) pairs of a dictionary.")
+_add_doc(iterlists,
+ "Return an iterator over the (key, [values]) pairs of a dictionary.")
+
+
+if PY3:
+ def b(s):
+ return s.encode("latin-1")
+ def u(s):
+ return s
+ unichr = chr
+ if sys.version_info[1] <= 1:
+ def int2byte(i):
+ return bytes((i,))
+ else:
+ # This is about 2x faster than the implementation above on 3.2+
+ int2byte = operator.methodcaller("to_bytes", 1, "big")
+ byte2int = operator.itemgetter(0)
+ indexbytes = operator.getitem
+ iterbytes = iter
+ import io
+ StringIO = io.StringIO
+ BytesIO = io.BytesIO
+else:
+ def b(s):
+ return s
+ # Workaround for standalone backslash
+ def u(s):
+ return unicode(s.replace(r'\\', r'\\\\'), "unicode_escape")
+ unichr = unichr
+ int2byte = chr
+ def byte2int(bs):
+ return ord(bs[0])
+ def indexbytes(buf, i):
+ return ord(buf[i])
+ iterbytes = functools.partial(itertools.imap, ord)
+ import StringIO
+ StringIO = BytesIO = StringIO.StringIO
+_add_doc(b, """Byte literal""")
+_add_doc(u, """Text literal""")
+
+
+if PY3:
+ exec_ = getattr(moves.builtins, "exec")
+
+
+ def reraise(tp, value, tb=None):
+ if value is None:
+ value = tp()
+ if value.__traceback__ is not tb:
+ raise value.with_traceback(tb)
+ raise value
+
+else:
+ def exec_(_code_, _globs_=None, _locs_=None):
+ """Execute code in a namespace."""
+ if _globs_ is None:
+ frame = sys._getframe(1)
+ _globs_ = frame.f_globals
+ if _locs_ is None:
+ _locs_ = frame.f_locals
+ del frame
+ elif _locs_ is None:
+ _locs_ = _globs_
+ exec("""exec _code_ in _globs_, _locs_""")
+
+
+ exec_("""def reraise(tp, value, tb=None):
+ raise tp, value, tb
+""")
+
+
+if sys.version_info > (3, 2):
+ exec_("""def raise_from(value, from_value):
+ raise value from from_value
+""")
+else:
+ def raise_from(value, from_value):
+ raise value
+
+
+print_ = getattr(moves.builtins, "print", None)
+if print_ is None:
+ def print_(*args, **kwargs):
+ """The new-style print function for Python 2.4 and 2.5."""
+ fp = kwargs.pop("file", sys.stdout)
+ if fp is None:
+ return
+ def write(data):
+ if not isinstance(data, basestring):
+ data = str(data)
+ # If the file has an encoding, encode unicode with it.
+ if (isinstance(fp, file) and
+ isinstance(data, unicode) and
+ fp.encoding is not None):
+ errors = getattr(fp, "errors", None)
+ if errors is None:
+ errors = "strict"
+ data = data.encode(fp.encoding, errors)
+ fp.write(data)
+ want_unicode = False
+ sep = kwargs.pop("sep", None)
+ if sep is not None:
+ if isinstance(sep, unicode):
+ want_unicode = True
+ elif not isinstance(sep, str):
+ raise TypeError("sep must be None or a string")
+ end = kwargs.pop("end", None)
+ if end is not None:
+ if isinstance(end, unicode):
+ want_unicode = True
+ elif not isinstance(end, str):
+ raise TypeError("end must be None or a string")
+ if kwargs:
+ raise TypeError("invalid keyword arguments to print()")
+ if not want_unicode:
+ for arg in args:
+ if isinstance(arg, unicode):
+ want_unicode = True
+ break
+ if want_unicode:
+ newline = unicode("\n")
+ space = unicode(" ")
+ else:
+ newline = "\n"
+ space = " "
+ if sep is None:
+ sep = space
+ if end is None:
+ end = newline
+ for i, arg in enumerate(args):
+ if i:
+ write(sep)
+ write(arg)
+ write(end)
+
+_add_doc(reraise, """Reraise an exception.""")
+
+if sys.version_info[0:2] < (3, 4):
+ def wraps(wrapped, assigned=functools.WRAPPER_ASSIGNMENTS,
+ updated=functools.WRAPPER_UPDATES):
+ def wrapper(f):
+ f = functools.wraps(wrapped, assigned, updated)(f)
+ f.__wrapped__ = wrapped
+ return f
+ return wrapper
+else:
+ wraps = functools.wraps
+
+def with_metaclass(meta, *bases):
+ """Create a base class with a metaclass."""
+ # This requires a bit of explanation: the basic idea is to make a dummy
+ # metaclass for one level of class instantiation that replaces itself with
+ # the actual metaclass.
+ class metaclass(meta):
+ def __new__(cls, name, this_bases, d):
+ return meta(name, bases, d)
+ return type.__new__(metaclass, 'temporary_class', (), {})
+
+
+def add_metaclass(metaclass):
+ """Class decorator for creating a class with a metaclass."""
+ def wrapper(cls):
+ orig_vars = cls.__dict__.copy()
+ slots = orig_vars.get('__slots__')
+ if slots is not None:
+ if isinstance(slots, str):
+ slots = [slots]
+ for slots_var in slots:
+ orig_vars.pop(slots_var)
+ orig_vars.pop('__dict__', None)
+ orig_vars.pop('__weakref__', None)
+ return metaclass(cls.__name__, cls.__bases__, orig_vars)
+ return wrapper
+
+# Complete the moves implementation.
+# This code is at the end of this module to speed up module loading.
+# Turn this module into a package.
+__path__ = [] # required for PEP 302 and PEP 451
+__package__ = __name__ # see PEP 366 @ReservedAssignment
+if globals().get("__spec__") is not None:
+ __spec__.submodule_search_locations = [] # PEP 451 @UndefinedVariable
+# Remove other six meta path importers, since they cause problems. This can
+# happen if six is removed from sys.modules and then reloaded. (Setuptools does
+# this for some reason.)
+if sys.meta_path:
+ for i, importer in enumerate(sys.meta_path):
+ # Here's some real nastiness: Another "instance" of the six module might
+ # be floating around. Therefore, we can't use isinstance() to check for
+ # the six meta path importer, since the other six instance will have
+ # inserted an importer with different class.
+ if (type(importer).__name__ == "_SixMetaPathImporter" and
+ importer.name == __name__):
+ del sys.meta_path[i]
+ break
+ del i, importer
+# Finally, add the importer to the meta path import hook.
+sys.meta_path.append(_importer)
diff --git a/tests/wpt/web-platform-tests/tools/six/test_six.py b/tests/wpt/web-platform-tests/tools/six/test_six.py
new file mode 100644
index 00000000000..d5555e8ac3c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/six/test_six.py
@@ -0,0 +1,787 @@
+import operator
+import sys
+import types
+
+import py
+
+import six
+
+
+def test_add_doc():
+ def f():
+ """Icky doc"""
+ pass
+ six._add_doc(f, """New doc""")
+ assert f.__doc__ == "New doc"
+
+
+def test_import_module():
+ from logging import handlers
+ m = six._import_module("logging.handlers")
+ assert m is handlers
+
+
+def test_integer_types():
+ assert isinstance(1, six.integer_types)
+ assert isinstance(-1, six.integer_types)
+ assert isinstance(six.MAXSIZE + 23, six.integer_types)
+ assert not isinstance(.1, six.integer_types)
+
+
+def test_string_types():
+ assert isinstance("hi", six.string_types)
+ assert isinstance(six.u("hi"), six.string_types)
+ assert issubclass(six.text_type, six.string_types)
+
+
+def test_class_types():
+ class X:
+ pass
+ class Y(object):
+ pass
+ assert isinstance(X, six.class_types)
+ assert isinstance(Y, six.class_types)
+ assert not isinstance(X(), six.class_types)
+
+
+def test_text_type():
+ assert type(six.u("hi")) is six.text_type
+
+
+def test_binary_type():
+ assert type(six.b("hi")) is six.binary_type
+
+
+def test_MAXSIZE():
+ try:
+ # This shouldn't raise an overflow error.
+ six.MAXSIZE.__index__()
+ except AttributeError:
+ # Before Python 2.6.
+ pass
+ py.test.raises(
+ (ValueError, OverflowError),
+ operator.mul, [None], six.MAXSIZE + 1)
+
+
+def test_lazy():
+ if six.PY3:
+ html_name = "html.parser"
+ else:
+ html_name = "HTMLParser"
+ assert html_name not in sys.modules
+ mod = six.moves.html_parser
+ assert sys.modules[html_name] is mod
+ assert "htmlparser" not in six._MovedItems.__dict__
+
+
+try:
+ import _tkinter
+except ImportError:
+ have_tkinter = False
+else:
+ have_tkinter = True
+
+have_gdbm = True
+try:
+ import gdbm
+except ImportError:
+ try:
+ import dbm.gnu
+ except ImportError:
+ have_gdbm = False
+
+@py.test.mark.parametrize("item_name",
+ [item.name for item in six._moved_attributes])
+def test_move_items(item_name):
+ """Ensure that everything loads correctly."""
+ try:
+ item = getattr(six.moves, item_name)
+ if isinstance(item, types.ModuleType):
+ __import__("six.moves." + item_name)
+ except AttributeError:
+ if item_name == "zip_longest" and sys.version_info < (2, 6):
+ py.test.skip("zip_longest only available on 2.6+")
+ except ImportError:
+ if item_name == "winreg" and not sys.platform.startswith("win"):
+ py.test.skip("Windows only module")
+ if item_name.startswith("tkinter"):
+ if not have_tkinter:
+ py.test.skip("requires tkinter")
+ if item_name == "tkinter_ttk" and sys.version_info[:2] <= (2, 6):
+ py.test.skip("ttk only available on 2.7+")
+ if item_name.startswith("dbm_gnu") and not have_gdbm:
+ py.test.skip("requires gdbm")
+ raise
+ if sys.version_info[:2] >= (2, 6):
+ assert item_name in dir(six.moves)
+
+
+@py.test.mark.parametrize("item_name",
+ [item.name for item in six._urllib_parse_moved_attributes])
+def test_move_items_urllib_parse(item_name):
+ """Ensure that everything loads correctly."""
+ if item_name == "ParseResult" and sys.version_info < (2, 5):
+ py.test.skip("ParseResult is only found on 2.5+")
+ if item_name in ("parse_qs", "parse_qsl") and sys.version_info < (2, 6):
+ py.test.skip("parse_qs[l] is new in 2.6")
+ if sys.version_info[:2] >= (2, 6):
+ assert item_name in dir(six.moves.urllib.parse)
+ getattr(six.moves.urllib.parse, item_name)
+
+
+@py.test.mark.parametrize("item_name",
+ [item.name for item in six._urllib_error_moved_attributes])
+def test_move_items_urllib_error(item_name):
+ """Ensure that everything loads correctly."""
+ if sys.version_info[:2] >= (2, 6):
+ assert item_name in dir(six.moves.urllib.error)
+ getattr(six.moves.urllib.error, item_name)
+
+
+@py.test.mark.parametrize("item_name",
+ [item.name for item in six._urllib_request_moved_attributes])
+def test_move_items_urllib_request(item_name):
+ """Ensure that everything loads correctly."""
+ if sys.version_info[:2] >= (2, 6):
+ assert item_name in dir(six.moves.urllib.request)
+ getattr(six.moves.urllib.request, item_name)
+
+
+@py.test.mark.parametrize("item_name",
+ [item.name for item in six._urllib_response_moved_attributes])
+def test_move_items_urllib_response(item_name):
+ """Ensure that everything loads correctly."""
+ if sys.version_info[:2] >= (2, 6):
+ assert item_name in dir(six.moves.urllib.response)
+ getattr(six.moves.urllib.response, item_name)
+
+
+@py.test.mark.parametrize("item_name",
+ [item.name for item in six._urllib_robotparser_moved_attributes])
+def test_move_items_urllib_robotparser(item_name):
+ """Ensure that everything loads correctly."""
+ if sys.version_info[:2] >= (2, 6):
+ assert item_name in dir(six.moves.urllib.robotparser)
+ getattr(six.moves.urllib.robotparser, item_name)
+
+
+def test_import_moves_error_1():
+ from six.moves.urllib.parse import urljoin
+ from six import moves
+ # In 1.4.1: AttributeError: 'Module_six_moves_urllib_parse' object has no attribute 'urljoin'
+ assert moves.urllib.parse.urljoin
+
+
+def test_import_moves_error_2():
+ from six import moves
+ assert moves.urllib.parse.urljoin
+ # In 1.4.1: ImportError: cannot import name urljoin
+ from six.moves.urllib.parse import urljoin
+
+
+def test_import_moves_error_3():
+ from six.moves.urllib.parse import urljoin
+ # In 1.4.1: ImportError: cannot import name urljoin
+ from six.moves.urllib_parse import urljoin
+
+
+def test_from_imports():
+ from six.moves.queue import Queue
+ assert isinstance(Queue, six.class_types)
+ from six.moves.configparser import ConfigParser
+ assert isinstance(ConfigParser, six.class_types)
+
+
+def test_filter():
+ from six.moves import filter
+ f = filter(lambda x: x % 2, range(10))
+ assert six.advance_iterator(f) == 1
+
+
+def test_filter_false():
+ from six.moves import filterfalse
+ f = filterfalse(lambda x: x % 3, range(10))
+ assert six.advance_iterator(f) == 0
+ assert six.advance_iterator(f) == 3
+ assert six.advance_iterator(f) == 6
+
+def test_map():
+ from six.moves import map
+ assert six.advance_iterator(map(lambda x: x + 1, range(2))) == 1
+
+
+def test_zip():
+ from six.moves import zip
+ assert six.advance_iterator(zip(range(2), range(2))) == (0, 0)
+
+
+@py.test.mark.skipif("sys.version_info < (2, 6)")
+def test_zip_longest():
+ from six.moves import zip_longest
+ it = zip_longest(range(2), range(1))
+
+ assert six.advance_iterator(it) == (0, 0)
+ assert six.advance_iterator(it) == (1, None)
+
+
+class TestCustomizedMoves:
+
+ def teardown_method(self, meth):
+ try:
+ del six._MovedItems.spam
+ except AttributeError:
+ pass
+ try:
+ del six.moves.__dict__["spam"]
+ except KeyError:
+ pass
+
+
+ def test_moved_attribute(self):
+ attr = six.MovedAttribute("spam", "foo", "bar")
+ if six.PY3:
+ assert attr.mod == "bar"
+ else:
+ assert attr.mod == "foo"
+ assert attr.attr == "spam"
+ attr = six.MovedAttribute("spam", "foo", "bar", "lemma")
+ assert attr.attr == "lemma"
+ attr = six.MovedAttribute("spam", "foo", "bar", "lemma", "theorm")
+ if six.PY3:
+ assert attr.attr == "theorm"
+ else:
+ assert attr.attr == "lemma"
+
+
+ def test_moved_module(self):
+ attr = six.MovedModule("spam", "foo")
+ if six.PY3:
+ assert attr.mod == "spam"
+ else:
+ assert attr.mod == "foo"
+ attr = six.MovedModule("spam", "foo", "bar")
+ if six.PY3:
+ assert attr.mod == "bar"
+ else:
+ assert attr.mod == "foo"
+
+
+ def test_custom_move_module(self):
+ attr = six.MovedModule("spam", "six", "six")
+ six.add_move(attr)
+ six.remove_move("spam")
+ assert not hasattr(six.moves, "spam")
+ attr = six.MovedModule("spam", "six", "six")
+ six.add_move(attr)
+ from six.moves import spam
+ assert spam is six
+ six.remove_move("spam")
+ assert not hasattr(six.moves, "spam")
+
+
+ def test_custom_move_attribute(self):
+ attr = six.MovedAttribute("spam", "six", "six", "u", "u")
+ six.add_move(attr)
+ six.remove_move("spam")
+ assert not hasattr(six.moves, "spam")
+ attr = six.MovedAttribute("spam", "six", "six", "u", "u")
+ six.add_move(attr)
+ from six.moves import spam
+ assert spam is six.u
+ six.remove_move("spam")
+ assert not hasattr(six.moves, "spam")
+
+
+ def test_empty_remove(self):
+ py.test.raises(AttributeError, six.remove_move, "eggs")
+
+
+def test_get_unbound_function():
+ class X(object):
+ def m(self):
+ pass
+ assert six.get_unbound_function(X.m) is X.__dict__["m"]
+
+
+def test_get_method_self():
+ class X(object):
+ def m(self):
+ pass
+ x = X()
+ assert six.get_method_self(x.m) is x
+ py.test.raises(AttributeError, six.get_method_self, 42)
+
+
+def test_get_method_function():
+ class X(object):
+ def m(self):
+ pass
+ x = X()
+ assert six.get_method_function(x.m) is X.__dict__["m"]
+ py.test.raises(AttributeError, six.get_method_function, hasattr)
+
+
+def test_get_function_closure():
+ def f():
+ x = 42
+ def g():
+ return x
+ return g
+ cell = six.get_function_closure(f())[0]
+ assert type(cell).__name__ == "cell"
+
+
+def test_get_function_code():
+ def f():
+ pass
+ assert isinstance(six.get_function_code(f), types.CodeType)
+ if not hasattr(sys, "pypy_version_info"):
+ py.test.raises(AttributeError, six.get_function_code, hasattr)
+
+
+def test_get_function_defaults():
+ def f(x, y=3, b=4):
+ pass
+ assert six.get_function_defaults(f) == (3, 4)
+
+
+def test_get_function_globals():
+ def f():
+ pass
+ assert six.get_function_globals(f) is globals()
+
+
+def test_dictionary_iterators(monkeypatch):
+ def stock_method_name(iterwhat):
+ """Given a method suffix like "lists" or "values", return the name
+ of the dict method that delivers those on the version of Python
+ we're running in."""
+ if six.PY3:
+ return iterwhat
+ return 'iter' + iterwhat
+
+ class MyDict(dict):
+ if not six.PY3:
+ def lists(self, **kw):
+ return [1, 2, 3]
+ def iterlists(self, **kw):
+ return iter([1, 2, 3])
+ f = MyDict.iterlists
+ del MyDict.iterlists
+ setattr(MyDict, stock_method_name('lists'), f)
+
+ d = MyDict(zip(range(10), reversed(range(10))))
+ for name in "keys", "values", "items", "lists":
+ meth = getattr(six, "iter" + name)
+ it = meth(d)
+ assert not isinstance(it, list)
+ assert list(it) == list(getattr(d, name)())
+ py.test.raises(StopIteration, six.advance_iterator, it)
+ record = []
+ def with_kw(*args, **kw):
+ record.append(kw["kw"])
+ return old(*args)
+ old = getattr(MyDict, stock_method_name(name))
+ monkeypatch.setattr(MyDict, stock_method_name(name), with_kw)
+ meth(d, kw=42)
+ assert record == [42]
+ monkeypatch.undo()
+
+
+@py.test.mark.skipif(sys.version_info[:2] < (2, 7),
+ reason="view methods on dictionaries only available on 2.7+")
+def test_dictionary_views():
+ def stock_method_name(viewwhat):
+ """Given a method suffix like "keys" or "values", return the name
+ of the dict method that delivers those on the version of Python
+ we're running in."""
+ if six.PY3:
+ return viewwhat
+ return 'view' + viewwhat
+
+ d = dict(zip(range(10), (range(11, 20))))
+ for name in "keys", "values", "items":
+ meth = getattr(six, "view" + name)
+ view = meth(d)
+ assert set(view) == set(getattr(d, name)())
+
+
+def test_advance_iterator():
+ assert six.next is six.advance_iterator
+ l = [1, 2]
+ it = iter(l)
+ assert six.next(it) == 1
+ assert six.next(it) == 2
+ py.test.raises(StopIteration, six.next, it)
+ py.test.raises(StopIteration, six.next, it)
+
+
+def test_iterator():
+ class myiter(six.Iterator):
+ def __next__(self):
+ return 13
+ assert six.advance_iterator(myiter()) == 13
+ class myitersub(myiter):
+ def __next__(self):
+ return 14
+ assert six.advance_iterator(myitersub()) == 14
+
+
+def test_callable():
+ class X:
+ def __call__(self):
+ pass
+ def method(self):
+ pass
+ assert six.callable(X)
+ assert six.callable(X())
+ assert six.callable(test_callable)
+ assert six.callable(hasattr)
+ assert six.callable(X.method)
+ assert six.callable(X().method)
+ assert not six.callable(4)
+ assert not six.callable("string")
+
+
+def test_create_bound_method():
+ class X(object):
+ pass
+ def f(self):
+ return self
+ x = X()
+ b = six.create_bound_method(f, x)
+ assert isinstance(b, types.MethodType)
+ assert b() is x
+
+
+if six.PY3:
+
+ def test_b():
+ data = six.b("\xff")
+ assert isinstance(data, bytes)
+ assert len(data) == 1
+ assert data == bytes([255])
+
+
+ def test_u():
+ s = six.u("hi \u0439 \U00000439 \\ \\\\ \n")
+ assert isinstance(s, str)
+ assert s == "hi \u0439 \U00000439 \\ \\\\ \n"
+
+else:
+
+ def test_b():
+ data = six.b("\xff")
+ assert isinstance(data, str)
+ assert len(data) == 1
+ assert data == "\xff"
+
+
+ def test_u():
+ s = six.u("hi \u0439 \U00000439 \\ \\\\ \n")
+ assert isinstance(s, unicode)
+ assert s == "hi \xd0\xb9 \xd0\xb9 \\ \\\\ \n".decode("utf8")
+
+
+def test_u_escapes():
+ s = six.u("\u1234")
+ assert len(s) == 1
+
+
+def test_unichr():
+ assert six.u("\u1234") == six.unichr(0x1234)
+ assert type(six.u("\u1234")) is type(six.unichr(0x1234))
+
+
+def test_int2byte():
+ assert six.int2byte(3) == six.b("\x03")
+ py.test.raises((OverflowError, ValueError), six.int2byte, 256)
+
+
+def test_byte2int():
+ assert six.byte2int(six.b("\x03")) == 3
+ assert six.byte2int(six.b("\x03\x04")) == 3
+ py.test.raises(IndexError, six.byte2int, six.b(""))
+
+
+def test_bytesindex():
+ assert six.indexbytes(six.b("hello"), 3) == ord("l")
+
+
+def test_bytesiter():
+ it = six.iterbytes(six.b("hi"))
+ assert six.next(it) == ord("h")
+ assert six.next(it) == ord("i")
+ py.test.raises(StopIteration, six.next, it)
+
+
+def test_StringIO():
+ fp = six.StringIO()
+ fp.write(six.u("hello"))
+ assert fp.getvalue() == six.u("hello")
+
+
+def test_BytesIO():
+ fp = six.BytesIO()
+ fp.write(six.b("hello"))
+ assert fp.getvalue() == six.b("hello")
+
+
+def test_exec_():
+ def f():
+ l = []
+ six.exec_("l.append(1)")
+ assert l == [1]
+ f()
+ ns = {}
+ six.exec_("x = 42", ns)
+ assert ns["x"] == 42
+ glob = {}
+ loc = {}
+ six.exec_("global y; y = 42; x = 12", glob, loc)
+ assert glob["y"] == 42
+ assert "x" not in glob
+ assert loc["x"] == 12
+ assert "y" not in loc
+
+
+def test_reraise():
+ def get_next(tb):
+ if six.PY3:
+ return tb.tb_next.tb_next
+ else:
+ return tb.tb_next
+ e = Exception("blah")
+ try:
+ raise e
+ except Exception:
+ tp, val, tb = sys.exc_info()
+ try:
+ six.reraise(tp, val, tb)
+ except Exception:
+ tp2, value2, tb2 = sys.exc_info()
+ assert tp2 is Exception
+ assert value2 is e
+ assert tb is get_next(tb2)
+ try:
+ six.reraise(tp, val)
+ except Exception:
+ tp2, value2, tb2 = sys.exc_info()
+ assert tp2 is Exception
+ assert value2 is e
+ assert tb2 is not tb
+ try:
+ six.reraise(tp, val, tb2)
+ except Exception:
+ tp2, value2, tb3 = sys.exc_info()
+ assert tp2 is Exception
+ assert value2 is e
+ assert get_next(tb3) is tb2
+ try:
+ six.reraise(tp, None, tb)
+ except Exception:
+ tp2, value2, tb2 = sys.exc_info()
+ assert tp2 is Exception
+ assert value2 is not val
+ assert isinstance(value2, Exception)
+ assert tb is get_next(tb2)
+
+
+def test_raise_from():
+ try:
+ try:
+ raise Exception("blah")
+ except Exception:
+ ctx = sys.exc_info()[1]
+ f = Exception("foo")
+ six.raise_from(f, None)
+ except Exception:
+ tp, val, tb = sys.exc_info()
+ if sys.version_info[:2] > (3, 0):
+ # We should have done a raise f from None equivalent.
+ assert val.__cause__ is None
+ assert val.__context__ is ctx
+ if sys.version_info[:2] >= (3, 3):
+ # And that should suppress the context on the exception.
+ assert val.__suppress_context__
+ # For all versions the outer exception should have raised successfully.
+ assert str(val) == "foo"
+
+
+def test_print_():
+ save = sys.stdout
+ out = sys.stdout = six.moves.StringIO()
+ try:
+ six.print_("Hello,", "person!")
+ finally:
+ sys.stdout = save
+ assert out.getvalue() == "Hello, person!\n"
+ out = six.StringIO()
+ six.print_("Hello,", "person!", file=out)
+ assert out.getvalue() == "Hello, person!\n"
+ out = six.StringIO()
+ six.print_("Hello,", "person!", file=out, end="")
+ assert out.getvalue() == "Hello, person!"
+ out = six.StringIO()
+ six.print_("Hello,", "person!", file=out, sep="X")
+ assert out.getvalue() == "Hello,Xperson!\n"
+ out = six.StringIO()
+ six.print_(six.u("Hello,"), six.u("person!"), file=out)
+ result = out.getvalue()
+ assert isinstance(result, six.text_type)
+ assert result == six.u("Hello, person!\n")
+ six.print_("Hello", file=None) # This works.
+ out = six.StringIO()
+ six.print_(None, file=out)
+ assert out.getvalue() == "None\n"
+
+
+@py.test.mark.skipif("sys.version_info[:2] >= (2, 6)")
+def test_print_encoding(monkeypatch):
+ # Fool the type checking in print_.
+ monkeypatch.setattr(six, "file", six.BytesIO, raising=False)
+ out = six.BytesIO()
+ out.encoding = "utf-8"
+ out.errors = None
+ six.print_(six.u("\u053c"), end="", file=out)
+ assert out.getvalue() == six.b("\xd4\xbc")
+ out = six.BytesIO()
+ out.encoding = "ascii"
+ out.errors = "strict"
+ py.test.raises(UnicodeEncodeError, six.print_, six.u("\u053c"), file=out)
+ out.errors = "backslashreplace"
+ six.print_(six.u("\u053c"), end="", file=out)
+ assert out.getvalue() == six.b("\\u053c")
+
+
+def test_print_exceptions():
+ py.test.raises(TypeError, six.print_, x=3)
+ py.test.raises(TypeError, six.print_, end=3)
+ py.test.raises(TypeError, six.print_, sep=42)
+
+
+def test_with_metaclass():
+ class Meta(type):
+ pass
+ class X(six.with_metaclass(Meta)):
+ pass
+ assert type(X) is Meta
+ assert issubclass(X, object)
+ class Base(object):
+ pass
+ class X(six.with_metaclass(Meta, Base)):
+ pass
+ assert type(X) is Meta
+ assert issubclass(X, Base)
+ class Base2(object):
+ pass
+ class X(six.with_metaclass(Meta, Base, Base2)):
+ pass
+ assert type(X) is Meta
+ assert issubclass(X, Base)
+ assert issubclass(X, Base2)
+ assert X.__mro__ == (X, Base, Base2, object)
+
+
+def test_wraps():
+ def f(g):
+ @six.wraps(g)
+ def w():
+ return 42
+ return w
+ def k():
+ pass
+ original_k = k
+ k = f(f(k))
+ assert hasattr(k, '__wrapped__')
+ k = k.__wrapped__
+ assert hasattr(k, '__wrapped__')
+ k = k.__wrapped__
+ assert k is original_k
+ assert not hasattr(k, '__wrapped__')
+
+ def f(g, assign, update):
+ def w():
+ return 42
+ w.glue = {"foo" : "bar"}
+ return six.wraps(g, assign, update)(w)
+ k.glue = {"melon" : "egg"}
+ k.turnip = 43
+ k = f(k, ["turnip"], ["glue"])
+ assert k.__name__ == "w"
+ assert k.turnip == 43
+ assert k.glue == {"melon" : "egg", "foo" : "bar"}
+
+
+def test_add_metaclass():
+ class Meta(type):
+ pass
+ class X:
+ "success"
+ X = six.add_metaclass(Meta)(X)
+ assert type(X) is Meta
+ assert issubclass(X, object)
+ assert X.__module__ == __name__
+ assert X.__doc__ == "success"
+ class Base(object):
+ pass
+ class X(Base):
+ pass
+ X = six.add_metaclass(Meta)(X)
+ assert type(X) is Meta
+ assert issubclass(X, Base)
+ class Base2(object):
+ pass
+ class X(Base, Base2):
+ pass
+ X = six.add_metaclass(Meta)(X)
+ assert type(X) is Meta
+ assert issubclass(X, Base)
+ assert issubclass(X, Base2)
+
+ # Test a second-generation subclass of a type.
+ class Meta1(type):
+ m1 = "m1"
+ class Meta2(Meta1):
+ m2 = "m2"
+ class Base:
+ b = "b"
+ Base = six.add_metaclass(Meta1)(Base)
+ class X(Base):
+ x = "x"
+ X = six.add_metaclass(Meta2)(X)
+ assert type(X) is Meta2
+ assert issubclass(X, Base)
+ assert type(Base) is Meta1
+ assert "__dict__" not in vars(X)
+ instance = X()
+ instance.attr = "test"
+ assert vars(instance) == {"attr": "test"}
+ assert instance.b == Base.b
+ assert instance.x == X.x
+
+ # Test a class with slots.
+ class MySlots(object):
+ __slots__ = ["a", "b"]
+ MySlots = six.add_metaclass(Meta1)(MySlots)
+
+ assert MySlots.__slots__ == ["a", "b"]
+ instance = MySlots()
+ instance.a = "foo"
+ py.test.raises(AttributeError, setattr, instance, "c", "baz")
+
+ # Test a class with string for slots.
+ class MyStringSlots(object):
+ __slots__ = "ab"
+ MyStringSlots = six.add_metaclass(Meta1)(MyStringSlots)
+ assert MyStringSlots.__slots__ == "ab"
+ instance = MyStringSlots()
+ instance.ab = "foo"
+ py.test.raises(AttributeError, setattr, instance, "a", "baz")
+ py.test.raises(AttributeError, setattr, instance, "b", "baz")
+
+ class MySlotsWeakref(object):
+ __slots__ = "__weakref__",
+ MySlotsWeakref = six.add_metaclass(Meta)(MySlotsWeakref)
+ assert type(MySlotsWeakref) is Meta
diff --git a/tests/wpt/web-platform-tests/tools/six/tox.ini b/tests/wpt/web-platform-tests/tools/six/tox.ini
new file mode 100644
index 00000000000..b29b31a69e9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/six/tox.ini
@@ -0,0 +1,12 @@
+[tox]
+envlist=py25,py26,py27,py31,py32,py33,py34,pypy
+indexserver=
+ default = http://pypi.python.org/simple
+ testrun = http://pypi.testrun.org
+
+[testenv]
+deps=pytest
+commands= py.test -rfsxX {posargs}
+
+[pytest]
+minversion=2.2.0
diff --git a/tests/wpt/web-platform-tests/tools/sslutils/__init__.py b/tests/wpt/web-platform-tests/tools/sslutils/__init__.py
new file mode 100644
index 00000000000..e46be851d64
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/sslutils/__init__.py
@@ -0,0 +1,9 @@
+import openssl
+import pregenerated
+from base import NoSSLEnvironment
+from openssl import OpenSSLEnvironment
+from pregenerated import PregeneratedSSLEnvironment
+
+environments = {"none": NoSSLEnvironment,
+ "openssl": OpenSSLEnvironment,
+ "pregenerated": PregeneratedSSLEnvironment}
diff --git a/tests/wpt/web-platform-tests/tools/sslutils/base.py b/tests/wpt/web-platform-tests/tools/sslutils/base.py
new file mode 100644
index 00000000000..e78e1385c7b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/sslutils/base.py
@@ -0,0 +1,23 @@
+def get_logger(name="ssl"):
+ logger = structured.get_default_logger(name)
+ if logger is None:
+ logger = structured.structuredlog.StructuredLogger(name)
+ return logger
+
+class NoSSLEnvironment(object):
+ ssl_enabled = False
+
+ def __init__(self, *args, **kwargs):
+ pass
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, *args, **kwargs):
+ pass
+
+ def host_cert_path(self, host):
+ return None, None
+
+ def ca_cert_path(self):
+ return None
diff --git a/tests/wpt/web-platform-tests/tools/sslutils/openssl.py b/tests/wpt/web-platform-tests/tools/sslutils/openssl.py
new file mode 100644
index 00000000000..eef41f14306
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/sslutils/openssl.py
@@ -0,0 +1,386 @@
+import functools
+import os
+import shutil
+import subprocess
+import tempfile
+from datetime import datetime
+
+class OpenSSL(object):
+ def __init__(self, logger, binary, base_path, conf_path, hosts, duration):
+ """Context manager for interacting with OpenSSL.
+ Creates a config file for the duration of the context.
+
+ :param logger: stdlib logger or python structured logger
+ :param binary: path to openssl binary
+ :param base_path: path to directory for storing certificates
+ :param conf_path: path for configuration file storing configuration data
+ :param hosts: list of hosts to include in configuration (or None if not
+ generating host certificates)
+ :param duration: Certificate duration in days"""
+
+ self.base_path = base_path
+ self.binary = binary
+ self.conf_path = conf_path
+ self.logger = logger
+ self.proc = None
+ self.cmd = []
+ self.hosts = hosts
+ self.duration = duration
+
+ def __enter__(self):
+ with open(self.conf_path, "w") as f:
+ f.write(get_config(self.base_path, self.hosts, self.duration))
+ return self
+
+ def __exit__(self, *args, **kwargs):
+ os.unlink(self.conf_path)
+
+ def log(self, line):
+ if hasattr(self.logger, "process_output"):
+ self.logger.process_output(self.proc.pid if self.proc is not None else None,
+ line.decode("utf8", "replace"),
+ command=" ".join(self.cmd))
+ else:
+ self.logger.debug(line)
+
+ def __call__(self, cmd, *args, **kwargs):
+ """Run a command using OpenSSL in the current context.
+
+ :param cmd: The openssl subcommand to run
+ :param *args: Additional arguments to pass to the command
+ """
+ self.cmd = [self.binary, cmd]
+ if cmd != "x509":
+ self.cmd += ["-config", self.conf_path]
+ self.cmd += list(args)
+ self.proc = subprocess.Popen(self.cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ stdout, stderr = self.proc.communicate()
+ self.log(stdout)
+ if self.proc.returncode != 0:
+ raise subprocess.CalledProcessError(self.proc.returncode, self.cmd,
+ output=stdout)
+
+ self.cmd = []
+ self.proc = None
+ return stdout
+
+
+def make_subject(common_name,
+ country=None,
+ state=None,
+ locality=None,
+ organization=None,
+ organization_unit=None):
+ args = [("country", "C"),
+ ("state", "ST"),
+ ("locality", "L"),
+ ("organization", "O"),
+ ("organization_unit", "OU"),
+ ("common_name", "CN")]
+
+ rv = []
+
+ for var, key in args:
+ value = locals()[var]
+ if value is not None:
+ rv.append("/%s=%s" % (key, value.replace("/", "\\/")))
+
+ return "".join(rv)
+
+def make_alt_names(hosts):
+ rv = []
+ for name in hosts:
+ rv.append("DNS:%s" % name)
+ return ",".join(rv)
+
+def get_config(root_dir, hosts, duration=30):
+ if hosts is None:
+ san_line = ""
+ else:
+ san_line = "subjectAltName = %s" % make_alt_names(hosts)
+
+ rv = """[ ca ]
+default_ca = CA_default
+
+[ CA_default ]
+dir = %(root_dir)s
+certs = $dir
+new_certs_dir = $certs
+crl_dir = $dir/crl
+database = $dir/index.txt
+private_key = $dir/cakey.pem
+certificate = $dir/cacert.pem
+serial = $dir/serial
+crldir = $dir/crl
+crlnumber = $dir/crlnumber
+crl = $crldir/crl.pem
+RANDFILE = $dir/private/.rand
+x509_extensions = usr_cert
+name_opt = ca_default
+cert_opt = ca_default
+default_days = %(duration)d
+default_crl_days = %(duration)d
+default_md = sha256
+preserve = no
+policy = policy_anything
+copy_extensions = copy
+
+[ policy_anything ]
+countryName = optional
+stateOrProvinceName = optional
+localityName = optional
+organizationName = optional
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+[ req ]
+default_bits = 2048
+default_keyfile = privkey.pem
+distinguished_name = req_distinguished_name
+attributes = req_attributes
+x509_extensions = v3_ca
+
+# Passwords for private keys if not present they will be prompted for
+# input_password = secret
+# output_password = secret
+string_mask = utf8only
+req_extensions = v3_req
+
+[ req_distinguished_name ]
+countryName = Country Name (2 letter code)
+countryName_default = AU
+countryName_min = 2
+countryName_max = 2
+stateOrProvinceName = State or Province Name (full name)
+stateOrProvinceName_default =
+localityName = Locality Name (eg, city)
+0.organizationName = Organization Name
+0.organizationName_default = Web Platform Tests
+organizationalUnitName = Organizational Unit Name (eg, section)
+#organizationalUnitName_default =
+commonName = Common Name (e.g. server FQDN or YOUR name)
+commonName_max = 64
+emailAddress = Email Address
+emailAddress_max = 64
+
+[ req_attributes ]
+
+[ usr_cert ]
+basicConstraints=CA:false
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer
+
+[ v3_req ]
+basicConstraints = CA:FALSE
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+extendedKeyUsage = serverAuth
+%(san_line)s
+
+[ v3_ca ]
+basicConstraints = CA:true
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid:always,issuer:always
+keyUsage = keyCertSign
+""" % {"root_dir": root_dir,
+ "san_line": san_line,
+ "duration": duration}
+
+ return rv
+
+class OpenSSLEnvironment(object):
+ ssl_enabled = True
+
+ def __init__(self, logger, openssl_binary="openssl", base_path=None,
+ password="web-platform-tests", force_regenerate=False,
+ duration=30):
+ """SSL environment that creates a local CA and host certificate using OpenSSL.
+
+ By default this will look in base_path for existing certificates that are still
+ valid and only create new certificates if there aren't any. This behaviour can
+ be adjusted using the force_regenerate option.
+
+ :param logger: a stdlib logging compatible logger or mozlog structured logger
+ :param openssl_binary: Path to the OpenSSL binary
+ :param base_path: Path in which certificates will be stored. If None, a temporary
+ directory will be used and removed when the server shuts down
+ :param password: Password to use
+ :param force_regenerate: Always create a new certificate even if one already exists.
+ """
+ self.logger = logger
+
+ self.temporary = False
+ if base_path is None:
+ base_path = tempfile.mkdtemp()
+ self.temporary = True
+
+ self.base_path = os.path.abspath(base_path)
+ self.password = password
+ self.force_regenerate = force_regenerate
+ self.duration = duration
+
+ self.path = None
+ self.binary = openssl_binary
+ self.openssl = None
+
+ self._ca_cert_path = None
+ self._ca_key_path = None
+ self.host_certificates = {}
+
+ def __enter__(self):
+ if not os.path.exists(self.base_path):
+ os.makedirs(self.base_path)
+
+ path = functools.partial(os.path.join, self.base_path)
+
+ with open(path("index.txt"), "w"):
+ pass
+ with open(path("serial"), "w") as f:
+ f.write("01")
+
+ self.path = path
+
+ return self
+
+ def __exit__(self, *args, **kwargs):
+ if self.temporary:
+ shutil.rmtree(self.base_path)
+
+ def _config_openssl(self, hosts):
+ conf_path = self.path("openssl.cfg")
+ return OpenSSL(self.logger, self.binary, self.base_path, conf_path, hosts,
+ self.duration)
+
+ def ca_cert_path(self):
+ """Get the path to the CA certificate file, generating a
+ new one if needed"""
+ if self._ca_cert_path is None and not self.force_regenerate:
+ self._load_ca_cert()
+ if self._ca_cert_path is None:
+ self._generate_ca()
+ return self._ca_cert_path
+
+ def _load_ca_cert(self):
+ key_path = self.path("cakey.pem")
+ cert_path = self.path("cacert.pem")
+
+ if self.check_key_cert(key_path, cert_path, None):
+ self.logger.info("Using existing CA cert")
+ self._ca_key_path, self._ca_cert_path = key_path, cert_path
+
+ def check_key_cert(self, key_path, cert_path, hosts):
+ """Check that a key and cert file exist and are valid"""
+ if not os.path.exists(key_path) or not os.path.exists(cert_path):
+ return False
+
+ with self._config_openssl(hosts) as openssl:
+ end_date_str = openssl("x509",
+ "-noout",
+ "-enddate",
+ "-in", cert_path).split("=", 1)[1].strip()
+ # Not sure if this works in other locales
+ end_date = datetime.strptime(end_date_str, "%b %d %H:%M:%S %Y %Z")
+ # Should have some buffer here e.g. 1 hr
+ if end_date < datetime.now():
+ return False
+
+ #TODO: check the key actually signed the cert.
+ return True
+
+ def _generate_ca(self):
+ path = self.path
+ self.logger.info("Generating new CA in %s" % self.base_path)
+
+ key_path = path("cakey.pem")
+ req_path = path("careq.pem")
+ cert_path = path("cacert.pem")
+
+ with self._config_openssl(None) as openssl:
+ openssl("req",
+ "-batch",
+ "-new",
+ "-newkey", "rsa:2048",
+ "-keyout", key_path,
+ "-out", req_path,
+ "-subj", make_subject("web-platform-tests"),
+ "-passout", "pass:%s" % self.password)
+
+ openssl("ca",
+ "-batch",
+ "-create_serial",
+ "-keyfile", key_path,
+ "-passin", "pass:%s" % self.password,
+ "-selfsign",
+ "-extensions", "v3_ca",
+ "-in", req_path,
+ "-out", cert_path)
+
+ os.unlink(req_path)
+
+ self._ca_key_path, self._ca_cert_path = key_path, cert_path
+
+ def host_cert_path(self, hosts):
+ """Get a tuple of (private key path, certificate path) for a host,
+ generating new ones if necessary.
+
+ hosts must be a list of all hosts to appear on the certificate, with
+ the primary hostname first."""
+ hosts = tuple(hosts)
+ if hosts not in self.host_certificates:
+ if not self.force_regenerate:
+ key_cert = self._load_host_cert(hosts)
+ else:
+ key_cert = None
+ if key_cert is None:
+ key, cert = self._generate_host_cert(hosts)
+ else:
+ key, cert = key_cert
+ self.host_certificates[hosts] = key, cert
+
+ return self.host_certificates[hosts]
+
+ def _load_host_cert(self, hosts):
+ host = hosts[0]
+ key_path = self.path("%s.key" % host)
+ cert_path = self.path("%s.pem" % host)
+
+ # TODO: check that this cert was signed by the CA cert
+ if self.check_key_cert(key_path, cert_path, hosts):
+ self.logger.info("Using existing host cert")
+ return key_path, cert_path
+
+ def _generate_host_cert(self, hosts):
+ host = hosts[0]
+ if self._ca_key_path is None:
+ self._generate_ca()
+ ca_key_path = self._ca_key_path
+
+ assert os.path.exists(ca_key_path)
+
+ path = self.path
+
+ req_path = path("wpt.req")
+ cert_path = path("%s.pem" % host)
+ key_path = path("%s.key" % host)
+
+ self.logger.info("Generating new host cert")
+
+ with self._config_openssl(hosts) as openssl:
+ openssl("req",
+ "-batch",
+ "-newkey", "rsa:2048",
+ "-keyout", key_path,
+ "-in", ca_key_path,
+ "-nodes",
+ "-out", req_path)
+
+ openssl("ca",
+ "-batch",
+ "-in", req_path,
+ "-passin", "pass:%s" % self.password,
+ "-subj", make_subject(host),
+ "-out", cert_path)
+
+ os.unlink(req_path)
+
+ return key_path, cert_path
diff --git a/tests/wpt/web-platform-tests/tools/sslutils/pregenerated.py b/tests/wpt/web-platform-tests/tools/sslutils/pregenerated.py
new file mode 100644
index 00000000000..fc487df3add
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/sslutils/pregenerated.py
@@ -0,0 +1,26 @@
+class PregeneratedSSLEnvironment(object):
+ """SSL environment to use with existing key/certificate files
+ e.g. when running on a server with a public domain name
+ """
+ ssl_enabled = True
+
+ def __init__(self, logger, host_key_path, host_cert_path,
+ ca_cert_path=None):
+ self._ca_cert_path = ca_cert_path
+ self._host_key_path = host_key_path
+ self._host_cert_path = host_cert_path
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, *args, **kwargs):
+ pass
+
+ def host_cert_path(self, hosts):
+ """Return the key and certificate paths for the host"""
+ return self._host_key_path, self._host_cert_path
+
+ def ca_cert_path(self):
+ """Return the certificate path of the CA that signed the
+ host certificates, or None if that isn't known"""
+ return self._ca_cert_path
diff --git a/tests/wpt/web-platform-tests/tools/webdriver/webdriver/__init__.py b/tests/wpt/web-platform-tests/tools/webdriver/webdriver/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/webdriver/webdriver/__init__.py
diff --git a/tests/wpt/web-platform-tests/tools/webdriver/webdriver/alert.py b/tests/wpt/web-platform-tests/tools/webdriver/webdriver/alert.py
new file mode 100644
index 00000000000..0dee3127d29
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/webdriver/webdriver/alert.py
@@ -0,0 +1,26 @@
+"""WebDriver alert handling."""
+
+class Alert(object):
+ """Class that provides access to the WebDriver alert handling functions."""
+
+ def __init__(self, driver):
+ self._driver = driver
+
+ def _execute(self, method, path, name, body=None):
+ return self._driver.execute(method, path, name, body)
+
+ def dismiss(self):
+ """Dismiss the alert."""
+ self._execute('POST', '/dismiss_alert', 'dismiss')
+
+ def accept(self):
+ """Accept the alert."""
+ self._execute('POST', '/accept_alert', 'accept')
+
+ def get_text(self):
+ """Get the text displayed in the alert."""
+ return self._execute('GET', '/alert_text', 'getText')
+
+ def send_keys(self, keys):
+ """Type into the text input of the alert if available."""
+ self._execute('POST', '/alert_text', 'sendKeys', { 'text': keys })
diff --git a/tests/wpt/web-platform-tests/tools/webdriver/webdriver/capabilities.py b/tests/wpt/web-platform-tests/tools/webdriver/webdriver/capabilities.py
new file mode 100644
index 00000000000..44bb1fd647d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/webdriver/webdriver/capabilities.py
@@ -0,0 +1,30 @@
+"""Definition of various capability-related constants."""
+
+class Capability:
+ """Standard capability names."""
+ BROWSER_NAME = 'browserName'
+ BROWSER_VERSION = 'browserVersion'
+ PAGE_LOADING_STRATEGY = 'pageLoadingStrategy'
+ PLATFORM_NAME = 'platformName'
+ PLATFORM_VERSION = 'platformVersion'
+ SECURE_SSL = 'secureSsl'
+ TAKES_SCREENSHOT = 'takesScreenshot'
+ TAKE_ELEMENT_SCREENSHOT = 'takeElementScreenshot'
+ TOUCH_ENABLED = 'touchEnabled'
+
+class Platform:
+ """Standard OS names."""
+ ANY = 'any'
+ ANDROID = 'android'
+ IOS = 'ios'
+ LINUX = 'linux'
+ MAC = 'mac'
+ UNIX = 'unix'
+ WINDOW = 'windows'
+
+class PageLoadingStrategy:
+ """Standard page loading strategies."""
+ CONSERVATIVE = 'conservative'
+ NORMAL = 'normal'
+ EAGER = 'eager'
+ NONE = 'none'
diff --git a/tests/wpt/web-platform-tests/tools/webdriver/webdriver/command.py b/tests/wpt/web-platform-tests/tools/webdriver/webdriver/command.py
new file mode 100644
index 00000000000..4ea162fea12
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/webdriver/webdriver/command.py
@@ -0,0 +1,111 @@
+"""Dispatches requests to remote WebDriver endpoint."""
+
+import exceptions
+
+import httplib
+import json
+import urlparse
+import webelement
+
+class CommandExecutor(object):
+ """Dispatches requests to remote WebDriver endpoint."""
+
+ _HEADERS = {
+ "User-Agent": "Python WebDriver Local End",
+ "Content-Type": "application/json;charset=\"UTF-8\"",
+ "Accept": "application/json",
+ "Accept-Charset": "utf-8",
+ "Accept-Encoding": "identity",
+ "Connection": "close",
+ }
+
+ def __init__(self, url, mode='strict'):
+ self._parsed_url = urlparse.urlparse(url)
+ self._conn = httplib.HTTPConnection(self._parsed_url.hostname,
+ self._parsed_url.port)
+ self._mode = mode
+
+ def execute(self,
+ method,
+ path,
+ session_id,
+ name,
+ parameters=None,
+ object_hook=None):
+ """Execute a command against the WebDriver endpoint.
+
+ Arguments:
+ method -- one of GET, POST, DELETE
+ path -- the path of the url endpoint (needs to include
+ session/<sessionId> if needed)
+ session_id -- the sessionId to include in the JSON body
+ name -- name of the command that is being executed to include in
+ the JSON body
+ parameters -- the JSON body to send with the command. Only used if
+ method is POST
+ object_hook -- function used by json.loads to properly deserialize
+ objects in the request
+ """
+ if self._mode == 'strict':
+ return self._execute_strict(
+ method, path, session_id, name, parameters, object_hook)
+ elif self._mode == 'compatibility':
+ return self._execute_compatibility(
+ method, path, session_id, name, parameters, object_hook)
+ else:
+ raise Exception("Unknown mode: " + self._mode)
+
+ def _execute_compatibility(self,
+ method,
+ path,
+ session_id,
+ name,
+ parameters,
+ object_hook):
+ body = {'sessionId': session_id, 'name': name }
+ if parameters:
+ body.update(parameters)
+
+ self._conn.request(
+ method,
+ self._parsed_url.path + path,
+ json.dumps(body, default = self._json_encode).encode('utf-8'),
+ self._HEADERS)
+ resp = self._conn.getresponse()
+ data = resp.read().decode('utf-8')
+ if data:
+ data = json.loads(data, object_hook = object_hook)
+ if data['status'] != 0:
+ raise exceptions.create_webdriver_exception_compatibility(
+ data['status'], data['value']['message'])
+ return data
+ if resp.status < 200 or resp.status > 299:
+ raise exceptions.create_webdriver_exception_compatibility(
+ resp.status, resp.reason)
+
+ def _execute_strict(self,
+ method,
+ path,
+ session_id,
+ name,
+ parameters,
+ object_hook):
+ body = {
+ 'sessionId': session_id,
+ 'name': name,
+ 'parameters': parameters }
+ self._conn.request(
+ method,
+ self._parsed_url.path + path,
+ json.dumps(body, default = self._json_encode).encode('utf-8'),
+ self._HEADERS)
+ resp = self._conn.getresponse()
+ data = json.loads(
+ resp.read().decode('utf-8'), object_hook = object_hook)
+ if data['status'] != 'success':
+ raise exceptions.create_webdriver_exception_strict(
+ data['status'], data['value'])
+ return data
+
+ def _json_encode(self, obj):
+ return obj.to_json()
diff --git a/tests/wpt/web-platform-tests/tools/webdriver/webdriver/driver.py b/tests/wpt/web-platform-tests/tools/webdriver/webdriver/driver.py
new file mode 100644
index 00000000000..f76881367ef
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/webdriver/webdriver/driver.py
@@ -0,0 +1,199 @@
+"""Entry point for WebDriver."""
+
+import alert
+import command
+import searchcontext
+import webelement
+
+import base64
+
+
+class WebDriver(searchcontext.SearchContext):
+ """Controls a web browser."""
+
+ def __init__(self, host, required, desired, mode='strict'):
+ args = { 'desiredCapabilities': desired }
+ if required:
+ args['requiredCapabilities'] = required
+
+ self._executor = command.CommandExecutor(host, mode)
+
+ resp = self._executor.execute(
+ 'POST', '/session', None, 'newSession', args)
+ self.capabilities = resp['value']
+ self._session_id = resp['sessionId']
+ self.mode = mode
+
+ def execute(self, method, path, name, parameters= None):
+ """Execute a command against the current WebDriver session."""
+ data = self._executor.execute(
+ method,
+ '/session/' + self._session_id + path,
+ self._session_id,
+ name,
+ parameters,
+ self._object_hook)
+ if data:
+ return data['value']
+
+ def get(self, url):
+ """Navigate to url."""
+ self.execute('POST', '/url', 'get', { 'url': url })
+
+ def get_current_url(self):
+ """Get the current value of the location bar."""
+ return self.execute('GET', '/url', 'getCurrentUrl')
+
+ def go_back(self):
+ """Hit the browser back button."""
+ self.execute('POST', '/back', 'goBack')
+
+ def go_forward(self):
+ """Hit the browser forward button."""
+ self.execute('POST', '/forward', 'goForward')
+
+ def refresh(self):
+ """Refresh the current page in the browser."""
+ self.execute('POST', '/refresh', 'refresh')
+
+ def quit(self):
+ """Shutdown the current WebDriver session."""
+ self.execute('DELETE', '', 'quit')
+
+ def get_window_handle(self):
+ """Get the handle for the browser window/tab currently accepting
+ commands.
+ """
+ return self.execute('GET', '/window_handle', 'getWindowHandle')
+
+ def get_window_handles(self):
+ """Get handles for all open windows/tabs."""
+ return self.execute('GET', '/window_handles', 'getWindowHandles')
+
+ def close(self):
+ """Close the current tab or window.
+
+ If this is the last tab or window, then this is the same as
+ calling quit.
+ """
+ self.execute('DELETE', '/window', 'close')
+
+ def maximize_window(self):
+ """Maximize the current window."""
+ return self._window_command('POST', '/maximize', 'maximize')
+
+ def get_window_size(self):
+ """Get the dimensions of the current window."""
+ result = self._window_command('GET', '/size', 'getWindowSize')
+ return { 'height': result[height], 'width': result[width] }
+
+ def set_window_size(self, height, width):
+ """Set the size of the current window."""
+ self._window_command(
+ 'POST',
+ '/size',
+ 'setWindowSize',
+ { 'height': height, 'width': width})
+
+ def fullscreen_window(self):
+ """Make the current window fullscreen."""
+ pass # implement when end point is defined
+
+ def switch_to_window(self, name):
+ """Switch to the window with the given handle or name."""
+ self.execute('POST', '/window', 'switchToWindow', { 'name': name })
+
+ def switch_to_frame(self, id):
+ """Switch to a frame.
+
+ id can be either a WebElement or an integer.
+ """
+ self.execute('POST', '/frame', 'switchToFrame', { 'id': id})
+
+ def switch_to_parent_frame(self):
+ """Move to the browsing context containing the currently selected frame.
+
+ If in the top-level browsing context, this is a no-op.
+ """
+ self.execute('POST', '/frame/parent', 'switchToParentFrame')
+
+ def switch_to_alert(self):
+ """Return an Alert object to interact with a modal dialog."""
+ alert_ = alert.Alert(self)
+ alert_.get_text()
+ return alert_
+
+ def execute_script(self, script, args=[]):
+ """Execute a Javascript script in the current browsing context."""
+ return self.execute(
+ 'POST',
+ '/execute',
+ 'executeScript',
+ { 'script': script, 'args': args })
+
+ def execute_script_async(self, script, args=[]):
+ """Execute a Javascript script in the current browsing context."""
+ return self.execute(
+ 'POST',
+ '/execute_async',
+ 'executeScriptAsync',
+ { 'script': script, 'args': args })
+
+ def take_screenshot(self, element=None):
+ """Take a screenshot.
+
+ If element is not provided, the screenshot should be of the
+ current page, otherwise the screenshot should be of the given element.
+ """
+ if self.mode == 'strict':
+ pass # implement when endpoint is defined
+ elif self.mode == 'compatibility':
+ if element:
+ pass # element screenshots are unsupported in compatibility
+ else:
+ return base64.standard_b64decode(
+ self.execute('GET', '/screenshot', 'takeScreenshot'))
+
+ def add_cookie(self, cookie):
+ """Add a cookie to the browser."""
+ self.execute('POST', '/cookie', 'addCookie', { 'cookie': cookie })
+
+ def get_cookie(self, name = None):
+ """Get the cookies accessible from the current page."""
+ if self.mode == 'compatibility':
+ cookies = self.execute('GET', '/cookie', 'getCookie')
+ if name:
+ cookies_ = []
+ for cookie in cookies:
+ if cookie['name'] == name:
+ cookies_.append(cookie)
+ return cookies_
+ return cookies
+ elif self.mode == 'strict':
+ pass # implement when wire protocol for this has been defined
+
+ def set_implicit_timeout(self, ms):
+ self._set_timeout('implicit', ms)
+
+ def set_page_load_timeout(self, ms):
+ self._set_timeout('page load', ms)
+
+ def set_script_timeout(self, ms):
+ self._set_timeout('script', ms)
+
+ def _set_timeout(self, type, ms):
+ params = { 'type': type, 'ms': ms }
+ self.execute('POST', '/timeouts', 'timeouts', params)
+
+ def _window_command(self, method, path, name, parameters = None):
+ if self.mode == 'compatibility':
+ return self.execute(
+ method, '/window/current' + path, name, parameters)
+ elif self.mode == 'strict':
+ pass # implement this when end-points are defined in doc
+
+ def _object_hook(self, obj):
+ if 'ELEMENT' in obj:
+ return webelement.WebElement(self, obj['ELEMENT'])
+ return obj
+
diff --git a/tests/wpt/web-platform-tests/tools/webdriver/webdriver/exceptions.py b/tests/wpt/web-platform-tests/tools/webdriver/webdriver/exceptions.py
new file mode 100644
index 00000000000..33f63ea5811
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/webdriver/webdriver/exceptions.py
@@ -0,0 +1,166 @@
+"""Definition of WebDriverException classes."""
+
+def create_webdriver_exception_strict(status_code, message):
+ """Create the appropriate WebDriverException given the status_code."""
+ if status_code in _exceptions_strict:
+ return _exceptions_strict[status_code](message)
+ return UnknownStatusCodeException("[%s] %s" % (status_code, message))
+
+def create_webdriver_exception_compatibility(status_code, message):
+ """Create the appropriate WebDriverException given the status_code."""
+ if status_code in _exceptions_compatibility:
+ return _exceptions_compatibility[status_code](message)
+ return UnknownStatusCodeException("[%s] %s" % (status_code, message))
+
+class WebDriverException(Exception):
+ """Base class for all WebDriverExceptions."""
+
+class UnableToSetCookieException(WebDriverException):
+ """A request to set a cookie's value could not be satisfied."""
+
+class InvalidElementStateException(WebDriverException):
+ """An element command could not be completed because the element is
+ in an invalid state (e.g. attempting to click an element that is no
+ longer attached to the DOM).
+ """
+
+class NoSuchElementException(WebDriverException):
+ """An element could not be located on the page using the given
+ search parameters.
+ """
+
+class TimeoutException(WebDriverException):
+ """An operation did not complete before its timeout expired."""
+
+class ElementNotSelectableException(InvalidElementStateException):
+ """An attempt was made to select an element that cannot be selected."""
+
+class ElementNotVisibleException(InvalidElementStateException):
+ """An element command could not be completed because the element is
+ not visible on the page.
+ """
+
+class ImeEngineActivationFailedException(WebDriverException):
+ """An IME engine could not be started."""
+
+class ImeNotAvailableException(ImeEngineActivationFailedException):
+ """IME was not available."""
+
+class InvalidCookieDomainException(UnableToSetCookieException):
+ """An illegal attempt was made to set a cookie under a different
+ domain than the current page.
+ """
+
+class InvalidElementCoordinatesException(WebDriverException):
+ """The coordinates provided to an interactions operation are invalid."""
+
+class InvalidSelectorException(NoSuchElementException):
+ """Argument was an invalid selector (e.g. XPath/CSS)."""
+
+class JavascriptErrorException(WebDriverException):
+ """An error occurred while executing user supplied JavaScript."""
+
+class MoveTargetOutOfBoundsException(InvalidElementStateException):
+ """The target for mouse interaction is not in the browser's viewport
+ and cannot be brought into that viewport.
+ """
+
+class NoSuchAlertException(WebDriverException):
+ """An attempt was made to operate on a modal dialog when one was not open."""
+
+class NoSuchFrameException(WebDriverException):
+ """A request to switch to a frame could not be satisfied because
+ the frame could not be found."""
+
+class NoSuchWindowException(WebDriverException):
+ """A request to switch to a different window could not be satisfied
+ because the window could not be found.
+ """
+
+class ScriptTimeoutException(TimeoutException):
+ """A script did not complete before its timeout expired."""
+
+class SessionNotCreatedException(WebDriverException):
+ """A new session could not be created."""
+
+class StaleElementReferenceException(InvalidElementStateException):
+ """An element command failed because the referenced element is no
+ longer attached to the DOM.
+ """
+
+class UnexpectedAlertOpenException(WebDriverException):
+ """A modal dialog was open, blocking this operation."""
+
+class UnknownCommandException(WebDriverException):
+ """A command could not be executed because the remote end is not
+ aware of it.
+ """
+
+class UnknownErrorException(WebDriverException):
+ """An unknown error occurred in the remote end while processing
+ the command.
+ """
+
+class UnsupportedOperationException(WebDriverException):
+ """Indicates that a command that should have executed properly
+ cannot be supported for some reason.
+ """
+
+class UnknownStatusCodeException(WebDriverException):
+ """Exception for all other status codes."""
+
+_exceptions_strict = {
+ "element not selectable": ElementNotSelectableException,
+ "element not visible": ElementNotVisibleException,
+ "ime engine activation failed": ImeEngineActivationFailedException,
+ "ime not available": ImeNotAvailableException,
+ "invalid cookie domain": InvalidCookieDomainException,
+ "invalid element coordinates": InvalidElementCoordinatesException,
+ "invalid element state": InvalidElementStateException,
+ "invalid selector": InvalidSelectorException,
+ "javascript error": JavascriptErrorException,
+ "move target out of bounds": MoveTargetOutOfBoundsException,
+ "no such alert": NoSuchAlertException,
+ "no such element": NoSuchElementException,
+ "no such frame": NoSuchFrameException,
+ "no such window": NoSuchWindowException,
+ "script timeout": ScriptTimeoutException,
+ "session not created": SessionNotCreatedException,
+ "stale element reference": StaleElementReferenceException,
+ "success": None,
+ "timeout": TimeoutException,
+ "unable to set cookie": UnableToSetCookieException,
+ "unexpected alert open": UnexpectedAlertOpenException,
+ "unknown command": UnknownCommandException,
+ "unknown error": UnknownErrorException,
+ "unsupported operation": UnsupportedOperationException,
+}
+
+_exceptions_compatibility = {
+ 15: ElementNotSelectableException,
+ 11: ElementNotVisibleException,
+ 31: ImeEngineActivationFailedException,
+ 30: ImeNotAvailableException,
+ 24: InvalidCookieDomainException,
+ 29: InvalidElementCoordinatesException,
+ 12: InvalidElementStateException,
+ 19: InvalidSelectorException,
+ 32: InvalidSelectorException,
+ 17: JavascriptErrorException,
+ 34: MoveTargetOutOfBoundsException,
+ 27: NoSuchAlertException,
+ 7: NoSuchElementException,
+ 8: NoSuchFrameException,
+ 23: NoSuchWindowException,
+ 28: ScriptTimeoutException,
+ 6: SessionNotCreatedException,
+ 33: SessionNotCreatedException,
+ 10: StaleElementReferenceException,
+ 0: None, # success
+ 21: TimeoutException,
+ 25: UnableToSetCookieException,
+ 26: UnexpectedAlertOpenException,
+ 9: UnknownCommandException,
+ 13: UnknownErrorException,
+ # "unsupported operation": UnsupportedOperationException
+}
diff --git a/tests/wpt/web-platform-tests/tools/webdriver/webdriver/keys.py b/tests/wpt/web-platform-tests/tools/webdriver/webdriver/keys.py
new file mode 100644
index 00000000000..9c6d93df821
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/webdriver/webdriver/keys.py
@@ -0,0 +1,68 @@
+"""Constants for special keys."""
+
+class Keys:
+ """Constants for special keys."""
+ NULL = '\uE000'
+ CANCEL = '\uE001'
+ HELP = '\uE002'
+ BACK_SPACE = '\uE003'
+ TAB = '\uE004'
+ CLEAR = '\uE005'
+ RETURN = '\uE006'
+ ENTER = '\uE007'
+ SHIFT = '\uE008'
+ LEFT_SHIFT = '\uE008'
+ CONTROL = '\uE009'
+ LEFT_CONTROL = '\uE009'
+ ALT = '\uE00A'
+ LEFT_ALT = '\uE00A'
+ PAUSE = '\uE00B'
+ ESCAPE = '\uE00C'
+ SPACE = '\uE00D'
+ PAGE_UP = '\uE00E'
+ PAGE_DOWN = '\uE00F'
+ END = '\uE010'
+ HOME = '\uE011'
+ LEFT = '\uE012'
+ ARROW_LEFT = '\uE012'
+ UP = '\uE013'
+ ARROW_UP = '\uE013'
+ RIGHT = '\uE014'
+ ARROW_RIGHT = '\uE014'
+ DOWN = '\uE015'
+ ARROW_DOWN = '\uE015'
+ INSERT = '\uE016'
+ DELETE = '\uE017'
+ SEMICOLON = '\uE018'
+ EQUALS = '\uE019'
+ NUMPAD0 = '\uE01A'
+ NUMPAD1 = '\uE01B'
+ NUMPAD2 = '\uE01C'
+ NUMPAD3 = '\uE01D'
+ NUMPAD4 = '\uE01E'
+ NUMPAD5 = '\uE01F'
+ NUMPAD6 = '\uE020'
+ NUMPAD7 = '\uE021'
+ NUMPAD8 = '\uE022'
+ NUMPAD9 = '\uE023'
+ MULTIPLY = '\uE024'
+ ADD = '\uE025'
+ SEPARATOR = '\uE026'
+ SUBTRACT = '\uE027'
+ DECIMAL = '\uE028'
+ DIVIDE = '\uE029'
+ F1 = '\uE031'
+ F2 = '\uE032'
+ F3 = '\uE033'
+ F4 = '\uE034'
+ F5 = '\uE035'
+ F6 = '\uE036'
+ F7 = '\uE037'
+ F8 = '\uE038'
+ F9 = '\uE039'
+ F10 = '\uE03A'
+ F11 = '\uE03B'
+ F12 = '\uE03C'
+ META = '\uE03D'
+ COMMAND = '\uE03D'
+ ZENKAKU_HANKAKU = '\uE040'
diff --git a/tests/wpt/web-platform-tests/tools/webdriver/webdriver/searchcontext.py b/tests/wpt/web-platform-tests/tools/webdriver/webdriver/searchcontext.py
new file mode 100644
index 00000000000..061fa027db1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/webdriver/webdriver/searchcontext.py
@@ -0,0 +1,54 @@
+"""WebDriver element location functionality."""
+
+class SearchContext(object):
+ """Abstract class that provides the core element location functionality."""
+
+ def find_element_by_css(self, selector):
+ """Find the first element matching a css selector."""
+ return self._find_element('css selector', selector)
+
+ def find_elements_by_css(self, selector):
+ """Find all elements matching a css selector."""
+ return self._find_elements('css selector', selector)
+
+ def find_element_by_link_text(self, text):
+ """Find the first link with the given text."""
+ return self._find_element('link text', text)
+
+ def find_elements_by_link_text(self, text):
+ """Find all links with the given text."""
+ return self._find_elements('link text', text)
+
+ def find_element_by_partial_link_text(self, text):
+ """Find the first link containing the given text."""
+ return self._find_element('partial link text', text)
+
+ def find_elements_by_partial_link_text(self, text):
+ """Find all links containing the given text."""
+ return self._find_elements('partial link text', text)
+
+ def find_element_by_xpath(self, xpath):
+ """Find the first element matching the xpath."""
+ return self._find_element('xpath', xpath)
+
+ def find_elements_by_xpath(self, xpath):
+ """Find all elements matching the xpath."""
+ return self._find_elements('xpath', xpath)
+
+ def _find_element(self, strategy, value):
+ return self.execute('POST',
+ '/element',
+ 'findElement',
+ self._get_locator(strategy, value))
+
+ def _find_elements(self, strategy, value):
+ return self.execute('POST',
+ '/elements',
+ 'findElements',
+ self._get_locator(strategy, value))
+
+ def _get_locator(self, strategy, value):
+ if self.mode == 'strict':
+ return {'strategy': strategy, 'value': value}
+ elif self.mode == 'compatibility':
+ return {'using': strategy, 'value': value}
diff --git a/tests/wpt/web-platform-tests/tools/webdriver/webdriver/wait.py b/tests/wpt/web-platform-tests/tools/webdriver/webdriver/wait.py
new file mode 100644
index 00000000000..e93c42d1d72
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/webdriver/webdriver/wait.py
@@ -0,0 +1,87 @@
+# Copyright 2011 Software Freedom Conservancy.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Waiting functionality."""
+
+import time
+from exceptions import NoSuchElementException
+from exceptions import TimeoutException
+
+POLL_FREQUENCY = 0.5 # How long to sleep inbetween calls to the method
+IGNORED_EXCEPTIONS = [NoSuchElementException] # list of exceptions ignored during calls to the method
+
+class WebDriverWait(object):
+
+ def __init__(self, driver, timeout, poll_frequency=POLL_FREQUENCY, ignored_exceptions=None):
+ """Constructor, takes a WebDriver instance and timeout in seconds.
+
+ :Args:
+ - driver - Instance of WebDriver (Ie, Firefox, Chrome or Remote)
+ - timeout - Number of seconds before timing out
+ - poll_frequency - sleep interval between calls
+ By default, it is 0.5 second.
+ - ignored_exceptions - iterable structure of exception classes ignored during calls.
+ By default, it contains NoSuchElementException only.
+
+ Example:
+ from selenium.webdriver.support.ui import WebDriverWait \n
+ element = WebDriverWait(driver, 10).until(lambda x: x.find_element_by_id("someId")) \n
+ is_disappeared = WebDriverWait(driver, 30, 1, (ElementNotVisibleException)).\ \n
+ until_not(lambda x: x.find_element_by_id("someId").is_displayed())
+ """
+ self._driver = driver
+ self._timeout = timeout
+ self._poll = poll_frequency
+ # avoid the divide by zero
+ if self._poll == 0:
+ self._poll = POLL_FREQUENCY
+ exceptions = IGNORED_EXCEPTIONS
+ if ignored_exceptions is not None:
+ try:
+ exceptions.extend(iter(ignored_exceptions))
+ except TypeError: # ignored_exceptions is not iterable
+ exceptions.append(ignored_exceptions)
+ self._ignored_exceptions = tuple(exceptions)
+
+ def until(self, method, message=''):
+ """Calls the method provided with the driver as an argument until the \
+ return value is not False."""
+ end_time = time.time() + self._timeout
+ while(True):
+ try:
+ value = method(self._driver)
+ if value:
+ return value
+ except self._ignored_exceptions:
+ pass
+ time.sleep(self._poll)
+ if(time.time() > end_time):
+ break
+ raise TimeoutException(message)
+
+ def until_not(self, method, message=''):
+ """Calls the method provided with the driver as an argument until the \
+ return value is False."""
+ end_time = time.time() + self._timeout
+ while(True):
+ try:
+ value = method(self._driver)
+ if not value:
+ return value
+ except self._ignored_exceptions:
+ return True
+ time.sleep(self._poll)
+ if(time.time() > end_time):
+ break
+ raise TimeoutException(message)
diff --git a/tests/wpt/web-platform-tests/tools/webdriver/webdriver/webelement.py b/tests/wpt/web-platform-tests/tools/webdriver/webdriver/webelement.py
new file mode 100644
index 00000000000..83e27f23116
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/webdriver/webdriver/webelement.py
@@ -0,0 +1,56 @@
+"""Element-level WebDriver operations."""
+
+import searchcontext
+
+class WebElement(searchcontext.SearchContext):
+ """Corresponds to a DOM element in the current page."""
+
+ def __init__(self, driver, id):
+ self._driver = driver
+ self._id = id
+ # Set value of mode used by SearchContext
+ self.mode = driver.mode
+
+ def execute(self, method, path, name, body=None):
+ """Execute a command against this WebElement."""
+ return self._driver.execute(
+ method, '/element/%s%s' % (self._id, path), name, body)
+
+ def is_displayed(self):
+ """Is this element displayed?"""
+ return self.execute('GET', '/displayed', 'isDisplayed')
+
+ def is_selected(self):
+ """Is this checkbox, radio button, or option selected?"""
+ return self.execute('GET', '/selected', 'isSelected')
+
+ def get_attribute(self, name):
+ """Get the value of an element property or attribute."""
+ return self.execute('GET', '/attribute/%s' % name, 'getElementAttribute')
+
+ @property
+ def text(self):
+ """Get the visible text for this element."""
+ return self.execute('GET', '/text', 'text')
+
+ @property
+ def tag_name(self):
+ """Get the tag name for this element"""
+ return self.execute('GET', '/name', 'getElementTagName')
+
+ def click(self):
+ """Click on this element."""
+ return self.execute('POST', '/click', 'click')
+
+ def clear(self):
+ """Clear the contents of the this text input."""
+ self.execute('POST', '/clear', 'clear')
+
+ def send_keys(self, keys):
+ """Send keys to this text input or body element."""
+ if isinstance(keys, str):
+ keys = [keys]
+ self.execute('POST', '/value', 'sendKeys', {'value': keys})
+
+ def to_json(self):
+ return {'ELEMENT': self.id}
diff --git a/tests/wpt/web-platform-tests/tools/wptserve/.gitignore b/tests/wpt/web-platform-tests/tools/wptserve/.gitignore
new file mode 100644
index 00000000000..8e87d388488
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/wptserve/.gitignore
@@ -0,0 +1,40 @@
+*.py[cod]
+*~
+\#*
+
+docs/_build/
+
+# C extensions
+*.so
+
+# Packages
+*.egg
+*.egg-info
+dist
+build
+eggs
+parts
+bin
+var
+sdist
+develop-eggs
+.installed.cfg
+lib
+lib64
+
+# Installer logs
+pip-log.txt
+
+# Unit test / coverage reports
+.coverage
+.tox
+nosetests.xml
+tests/functional/html/*
+
+# Translations
+*.mo
+
+# Mr Developer
+.mr.developer.cfg
+.project
+.pydevproject
diff --git a/tests/wpt/web-platform-tests/tools/wptserve/MANIFEST.in b/tests/wpt/web-platform-tests/tools/wptserve/MANIFEST.in
new file mode 100644
index 00000000000..4bf44835220
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/wptserve/MANIFEST.in
@@ -0,0 +1 @@
+include README.md \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/tools/wptserve/README.md b/tests/wpt/web-platform-tests/tools/wptserve/README.md
new file mode 100644
index 00000000000..c0c88e2c36c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/wptserve/README.md
@@ -0,0 +1,4 @@
+wptserve
+========
+
+Web server designed for use with web-platform-tests
diff --git a/tests/wpt/web-platform-tests/tools/wptserve/docs/Makefile b/tests/wpt/web-platform-tests/tools/wptserve/docs/Makefile
new file mode 100644
index 00000000000..250b6c8647f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/wptserve/docs/Makefile
@@ -0,0 +1,153 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS =
+SPHINXBUILD = sphinx-build
+PAPER =
+BUILDDIR = _build
+
+# Internal variables.
+PAPEROPT_a4 = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+# the i18n builder cannot share the environment and doctrees with the others
+I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
+
+help:
+ @echo "Please use \`make <target>' where <target> is one of"
+ @echo " html to make standalone HTML files"
+ @echo " dirhtml to make HTML files named index.html in directories"
+ @echo " singlehtml to make a single large HTML file"
+ @echo " pickle to make pickle files"
+ @echo " json to make JSON files"
+ @echo " htmlhelp to make HTML files and a HTML help project"
+ @echo " qthelp to make HTML files and a qthelp project"
+ @echo " devhelp to make HTML files and a Devhelp project"
+ @echo " epub to make an epub"
+ @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+ @echo " latexpdf to make LaTeX files and run them through pdflatex"
+ @echo " text to make text files"
+ @echo " man to make manual pages"
+ @echo " texinfo to make Texinfo files"
+ @echo " info to make Texinfo files and run them through makeinfo"
+ @echo " gettext to make PO message catalogs"
+ @echo " changes to make an overview of all changed/added/deprecated items"
+ @echo " linkcheck to check all external links for integrity"
+ @echo " doctest to run all doctests embedded in the documentation (if enabled)"
+
+clean:
+ -rm -rf $(BUILDDIR)/*
+
+html:
+ $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+dirhtml:
+ $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
+
+singlehtml:
+ $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
+ @echo
+ @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
+
+pickle:
+ $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
+ @echo
+ @echo "Build finished; now you can process the pickle files."
+
+json:
+ $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
+ @echo
+ @echo "Build finished; now you can process the JSON files."
+
+htmlhelp:
+ $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
+ @echo
+ @echo "Build finished; now you can run HTML Help Workshop with the" \
+ ".hhp project file in $(BUILDDIR)/htmlhelp."
+
+qthelp:
+ $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
+ @echo
+ @echo "Build finished; now you can run "qcollectiongenerator" with the" \
+ ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
+ @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/wptserve.qhcp"
+ @echo "To view the help file:"
+ @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/wptserve.qhc"
+
+devhelp:
+ $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
+ @echo
+ @echo "Build finished."
+ @echo "To view the help file:"
+ @echo "# mkdir -p $$HOME/.local/share/devhelp/wptserve"
+ @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/wptserve"
+ @echo "# devhelp"
+
+epub:
+ $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
+ @echo
+ @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
+
+latex:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo
+ @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
+ @echo "Run \`make' in that directory to run these through (pdf)latex" \
+ "(use \`make latexpdf' here to do that automatically)."
+
+latexpdf:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo "Running LaTeX files through pdflatex..."
+ $(MAKE) -C $(BUILDDIR)/latex all-pdf
+ @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+text:
+ $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
+ @echo
+ @echo "Build finished. The text files are in $(BUILDDIR)/text."
+
+man:
+ $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
+ @echo
+ @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
+
+texinfo:
+ $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+ @echo
+ @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
+ @echo "Run \`make' in that directory to run these through makeinfo" \
+ "(use \`make info' here to do that automatically)."
+
+info:
+ $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+ @echo "Running Texinfo files through makeinfo..."
+ make -C $(BUILDDIR)/texinfo info
+ @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
+
+gettext:
+ $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
+ @echo
+ @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
+
+changes:
+ $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
+ @echo
+ @echo "The overview file is in $(BUILDDIR)/changes."
+
+linkcheck:
+ $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
+ @echo
+ @echo "Link check complete; look for any errors in the above output " \
+ "or in $(BUILDDIR)/linkcheck/output.txt."
+
+doctest:
+ $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
+ @echo "Testing of doctests in the sources finished, look at the " \
+ "results in $(BUILDDIR)/doctest/output.txt."
diff --git a/tests/wpt/web-platform-tests/tools/wptserve/docs/conf.py b/tests/wpt/web-platform-tests/tools/wptserve/docs/conf.py
new file mode 100644
index 00000000000..eae1c20cce5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/wptserve/docs/conf.py
@@ -0,0 +1,243 @@
+# -*- coding: utf-8 -*-
+#
+# wptserve documentation build configuration file, created by
+# sphinx-quickstart on Wed Aug 14 17:23:24 2013.
+#
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys, os
+sys.path.insert(0, os.path.abspath(".."))
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#sys.path.insert(0, os.path.abspath('.'))
+
+# -- General configuration -----------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode']
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = u'wptserve'
+copyright = u'2013, Mozilla Foundation and other wptserve contributers'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+version = '0.1'
+# The full version, including alpha/beta/rc tags.
+release = '0.1'
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = ['_build']
+
+# The reST default role (used for this markup: `text`) to use for all documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+
+# -- Options for HTML output ---------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages. See the documentation for
+# a list of builtin themes.
+html_theme = 'default'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further. For a list of options available for each theme, see the
+# documentation.
+#html_theme_options = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+#html_theme_path = []
+
+# The name for this set of Sphinx documents. If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# A shorter title for the navigation bar. Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_domain_indices = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+#html_show_sourcelink = True
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+#html_show_sphinx = True
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+#html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it. The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# This is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = None
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'wptservedoc'
+
+
+# -- Options for LaTeX output --------------------------------------------------
+
+latex_elements = {
+# The paper size ('letterpaper' or 'a4paper').
+#'papersize': 'letterpaper',
+
+# The font size ('10pt', '11pt' or '12pt').
+#'pointsize': '10pt',
+
+# Additional stuff for the LaTeX preamble.
+#'preamble': '',
+}
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, documentclass [howto/manual]).
+latex_documents = [
+ ('index', 'wptserve.tex', u'wptserve Documentation',
+ u'James Graham', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# If true, show page references after internal links.
+#latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+#latex_show_urls = False
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_domain_indices = True
+
+
+# -- Options for manual page output --------------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+ ('index', 'wptserve', u'wptserve Documentation',
+ [u'James Graham'], 1)
+]
+
+# If true, show URL addresses after external links.
+#man_show_urls = False
+
+
+# -- Options for Texinfo output ------------------------------------------------
+
+# Grouping the document tree into Texinfo files. List of tuples
+# (source start file, target name, title, author,
+# dir menu entry, description, category)
+texinfo_documents = [
+ ('index', 'wptserve', u'wptserve Documentation',
+ u'James Graham', 'wptserve', 'One line description of project.',
+ 'Miscellaneous'),
+]
+
+# Documents to append as an appendix to all manuals.
+#texinfo_appendices = []
+
+# If false, no module index is generated.
+#texinfo_domain_indices = True
+
+# How to display URL addresses: 'footnote', 'no', or 'inline'.
+#texinfo_show_urls = 'footnote'
diff --git a/tests/wpt/web-platform-tests/tools/wptserve/docs/handlers.rst b/tests/wpt/web-platform-tests/tools/wptserve/docs/handlers.rst
new file mode 100644
index 00000000000..c15aab635d9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/wptserve/docs/handlers.rst
@@ -0,0 +1,111 @@
+Handlers
+========
+
+Handlers are functions that have the general signature::
+
+ handler(request, response)
+
+It is expected that the handler will use information from
+the request (e.g. the path) either to populate the response
+object with the data to send, or to directly write to the
+output stream via the ResponseWriter instance associated with
+the request. If a handler writes to the output stream then the
+server will not attempt additional writes, i.e. the choice to write
+directly in the handler or not is all-or-nothing.
+
+A number of general-purpose handler functions are provided by default:
+
+.. _handlers.Python:
+
+Python Handlers
+---------------
+
+Python handlers are functions which provide a higher-level API over
+manually updating the response object, by causing the return value of
+the function to provide (part of) the response. There are three
+possible sets of values that may be returned::
+
+
+ (status, headers, content)
+ (headers, content)
+ content
+
+Here `status` is either a tuple (status code, message) or simply a
+integer status code, `headers` is a list of (field name, value) pairs,
+and `content` is a string or an iterable returning strings. Such a
+function may also update the response manually. For example one may
+use `response.headers.set` to set a response header, and only return
+the content. One may even use this kind of handler, but manipulate
+the output socket directly, in which case the return value of the
+function, and the properties of the response object, will be ignored.
+
+The most common way to make a user function into a python handler is
+to use the provided `wptserve.handlers.handler` decorator::
+
+ from wptserve.handlers import handler
+
+ @handler
+ def test(request, response):
+ return [("X-Test": "PASS"), ("Content-Type", "text/plain")], "test"
+
+ #Later, assuming we have a Router object called 'router'
+
+ router.register("GET", "/test", test)
+
+JSON Handlers
+-------------
+
+This is a specialisation of the python handler type specifically
+designed to facilitate providing JSON responses. The API is largely
+the same as for a normal python handler, but the `content` part of the
+return value is JSON encoded, and a default Content-Type header of
+`application/json` is added. Again this handler is usually used as a
+decorator::
+
+ from wptserve.handlers import json_handler
+
+ @json_handler
+ def test(request, response):
+ return {"test": "PASS"}
+
+Python File Handlers
+--------------------
+
+Python file handlers are designed to provide a vaguely PHP-like interface
+where each resource corresponds to a particular python file on the
+filesystem. Typically this is hooked up to a route like ``("*",
+"*.py", python_file_handler)``, meaning that any .py file will be
+treated as a handler file (note that this makes python files unsafe in
+much the same way that .php files are when using PHP).
+
+Unlike PHP, the python files don't work by outputting text to stdout
+from the global scope. Instead they must define a single function
+`main` with the signature::
+
+ main(request, response)
+
+This function then behaves just like those described in
+:ref:`handlers.Python` above.
+
+asis Handlers
+-------------
+
+These are used to serve files as literal byte streams including the
+HTTP status line, headers and body. In the default configuration this
+handler is invoked for all files with a .asis extension.
+
+File Handlers
+-------------
+
+File handlers are used to serve static files. By default the content
+type of these files is set by examining the file extension. However
+this can be overridden, or additional headers supplied, by providing a
+file with the same name as the file being served but an additional
+.headers suffix, i.e. test.html has its headers set from
+test.html.headers. The format of the .headers file is plaintext, with
+each line containing::
+
+ Header-Name: header_value
+
+In addition headers can be set for a whole directory of files (but not
+subdirectories), using a file called `__dir__.headers`.
diff --git a/tests/wpt/web-platform-tests/tools/wptserve/docs/index.rst b/tests/wpt/web-platform-tests/tools/wptserve/docs/index.rst
new file mode 100644
index 00000000000..a9f630c760f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/wptserve/docs/index.rst
@@ -0,0 +1,35 @@
+.. wptserve documentation master file, created by
+ sphinx-quickstart on Wed Aug 14 17:23:24 2013.
+ You can adapt this file completely to your liking, but it should at least
+ contain the root `toctree` directive.
+
+Web Platform Test Server
+========================
+
+A python-based HTTP server specifically targeted at being used for
+testing the web platform. This means that extreme flexibility —
+including the possibility of HTTP non-conformance — in the response is
+supported.
+
+Contents:
+
+.. toctree::
+ :maxdepth: 2
+
+ introduction
+ server
+ router
+ request
+ response
+ stash
+ handlers
+ pipes
+
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
+
diff --git a/tests/wpt/web-platform-tests/tools/wptserve/docs/introduction.rst b/tests/wpt/web-platform-tests/tools/wptserve/docs/introduction.rst
new file mode 100644
index 00000000000..b585a983a2e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/wptserve/docs/introduction.rst
@@ -0,0 +1,51 @@
+Introduction
+============
+
+wptserve has been designed with the specific goal of making a server
+that is suitable for writing tests for the web platform. This means
+that it cannot use common abstractions over HTTP such as WSGI, since
+these assume that the goal is to generate a well-formed HTTP
+response. Testcases, however, often require precise control of the
+exact bytes sent over the wire and their timing. The full list of
+design goals for the server are:
+
+* Suitable to run on individual test machines and over the public internet.
+
+* Support plain TCP and SSL servers.
+
+* Serve static files with the minimum of configuration.
+
+* Allow headers to be overwritten on a per-file and per-directory
+ basis.
+
+* Full customisation of headers sent (e.g. altering or omitting
+ "mandatory" headers).
+
+* Simple per-client state.
+
+* Complex logic in tests, up to precise control over the individual
+ bytes sent and the timing of sending them.
+
+Request Handling
+----------------
+
+At the high level, the design of the server is based around similar
+concepts to those found in common web frameworks like Django, Pyramid
+or Flask. In particular the lifecycle of a typical request will be
+familiar to users of these systems. Incoming requests are parsed and a
+:doc:`Request <request>` object is constructed. This object is passed
+to a :ref:`Router <router.Interface>` instance, which is
+responsible for mapping the request method and path to a handler
+function. This handler is passed two arguments; the request object and
+a :doc:`Response <response>` object. In cases where only simple
+responses are required, the handler function may fill in the
+properties of the response object and the server will take care of
+constructing the response. However each Response also contains a
+:ref:`ResponseWriter <response.Interface>` which can be
+used to directly control the TCP socket.
+
+By default there are several built-in handler functions that provide a
+higher level API than direct manipulation of the Response
+object. These are documented in :doc:`handlers`.
+
+
diff --git a/tests/wpt/web-platform-tests/tools/wptserve/docs/make.bat b/tests/wpt/web-platform-tests/tools/wptserve/docs/make.bat
new file mode 100644
index 00000000000..40c71ff5ddd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/wptserve/docs/make.bat
@@ -0,0 +1,190 @@
+@ECHO OFF
+
+REM Command file for Sphinx documentation
+
+if "%SPHINXBUILD%" == "" (
+ set SPHINXBUILD=sphinx-build
+)
+set BUILDDIR=_build
+set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
+set I18NSPHINXOPTS=%SPHINXOPTS% .
+if NOT "%PAPER%" == "" (
+ set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
+ set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
+)
+
+if "%1" == "" goto help
+
+if "%1" == "help" (
+ :help
+ echo.Please use `make ^<target^>` where ^<target^> is one of
+ echo. html to make standalone HTML files
+ echo. dirhtml to make HTML files named index.html in directories
+ echo. singlehtml to make a single large HTML file
+ echo. pickle to make pickle files
+ echo. json to make JSON files
+ echo. htmlhelp to make HTML files and a HTML help project
+ echo. qthelp to make HTML files and a qthelp project
+ echo. devhelp to make HTML files and a Devhelp project
+ echo. epub to make an epub
+ echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
+ echo. text to make text files
+ echo. man to make manual pages
+ echo. texinfo to make Texinfo files
+ echo. gettext to make PO message catalogs
+ echo. changes to make an overview over all changed/added/deprecated items
+ echo. linkcheck to check all external links for integrity
+ echo. doctest to run all doctests embedded in the documentation if enabled
+ goto end
+)
+
+if "%1" == "clean" (
+ for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
+ del /q /s %BUILDDIR%\*
+ goto end
+)
+
+if "%1" == "html" (
+ %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The HTML pages are in %BUILDDIR%/html.
+ goto end
+)
+
+if "%1" == "dirhtml" (
+ %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
+ goto end
+)
+
+if "%1" == "singlehtml" (
+ %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
+ goto end
+)
+
+if "%1" == "pickle" (
+ %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can process the pickle files.
+ goto end
+)
+
+if "%1" == "json" (
+ %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can process the JSON files.
+ goto end
+)
+
+if "%1" == "htmlhelp" (
+ %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can run HTML Help Workshop with the ^
+.hhp project file in %BUILDDIR%/htmlhelp.
+ goto end
+)
+
+if "%1" == "qthelp" (
+ %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can run "qcollectiongenerator" with the ^
+.qhcp project file in %BUILDDIR%/qthelp, like this:
+ echo.^> qcollectiongenerator %BUILDDIR%\qthelp\wptserve.qhcp
+ echo.To view the help file:
+ echo.^> assistant -collectionFile %BUILDDIR%\qthelp\wptserve.ghc
+ goto end
+)
+
+if "%1" == "devhelp" (
+ %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished.
+ goto end
+)
+
+if "%1" == "epub" (
+ %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The epub file is in %BUILDDIR%/epub.
+ goto end
+)
+
+if "%1" == "latex" (
+ %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
+ goto end
+)
+
+if "%1" == "text" (
+ %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The text files are in %BUILDDIR%/text.
+ goto end
+)
+
+if "%1" == "man" (
+ %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The manual pages are in %BUILDDIR%/man.
+ goto end
+)
+
+if "%1" == "texinfo" (
+ %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
+ goto end
+)
+
+if "%1" == "gettext" (
+ %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
+ goto end
+)
+
+if "%1" == "changes" (
+ %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.The overview file is in %BUILDDIR%/changes.
+ goto end
+)
+
+if "%1" == "linkcheck" (
+ %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Link check complete; look for any errors in the above output ^
+or in %BUILDDIR%/linkcheck/output.txt.
+ goto end
+)
+
+if "%1" == "doctest" (
+ %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Testing of doctests in the sources finished, look at the ^
+results in %BUILDDIR%/doctest/output.txt.
+ goto end
+)
+
+:end
diff --git a/tests/wpt/web-platform-tests/tools/wptserve/docs/pipes.rst b/tests/wpt/web-platform-tests/tools/wptserve/docs/pipes.rst
new file mode 100644
index 00000000000..c606140d474
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/wptserve/docs/pipes.rst
@@ -0,0 +1,157 @@
+Pipes
+======
+
+Pipes are functions that may be used when serving files to alter parts
+of the response. These are invoked by adding a pipe= query parameter
+taking a | separated list of pipe functions and parameters. The pipe
+functions are applied to the response from left to right. For example::
+
+ GET /sample.txt?pipe=slice(1,200)|status(404).
+
+This would serve bytes 1 to 199, inclusive, of foo.txt with the HTTP status
+code 404.
+
+There are several built-in pipe functions, and it is possible to add
+more using the `@pipe` decorator on a function, if required.
+
+.. note::
+ Because of the way pipes compose, using some pipe functions prevents the
+ content-length of the response from being known in advance. In these cases
+ the server will close the connection to indicate the end of the response,
+ preventing the use of HTTP 1.1 keepalive.
+
+Built-In Pipes
+--------------
+
+sub
+~~~
+
+Used to substitute variables from the server environment, or from the
+request into the response.
+
+Substitutions are marked in a file using a block delimited by `{{`
+and `}}`. Inside the block the following variables are available:
+
+ `{{host}}`
+ The host name of the server excluding any subdomain part.
+
+ `{{domains[]}}`
+ The domain name of a particular subdomain
+ e.g. `{{domains[www]}}` for the `www` subdomain.
+
+ `{{ports[][]}}`
+ The port number of servers, by protocol
+ e.g. `{{ports[http][0]}}` for the first (and, depending on setup,
+ possibly only) http server
+
+ `{{headers[]}}`
+ The HTTP headers in the request
+ e.g. `{{headers[X-Test]}}` for a hypothetical `X-Test` header.
+
+ `{{GET[]}}`
+ The query parameters for the request
+ e.g. `{{GET[id]}}` for an id parameter sent with the request.
+
+So, for example, to write a javascript file called `xhr.js` that
+depends on the host name of the server, without hardcoding, one might
+write::
+
+ var server_url = http://{{host}}:{{ports[http][0]}}/path/to/resource;
+ //Create the actual XHR and so on
+
+The file would then be included as:
+
+ <script src="xhr.js?pipe=sub"></script>
+
+This pipe can also be enabled by using a filename `*.sub.ext`, e.g. the file above could be called `xhr.sub.js`.
+
+status
+~~~~~~
+
+Used to set the HTTP status of the response, for example::
+
+ example.js?pipe=status(410)
+
+headers
+~~~~~~~
+
+Used to add or replace http headers in the response. Takes two or
+three arguments; the header name, the header value and whether to
+append the header rather than replace an existing header (default:
+False). So, for example, a request for::
+
+ example.html?pipe=header(Content-Type,text/plain)
+
+causes example.html to be returned with a text/plain content type
+whereas::
+
+ example.html?pipe=header(Content-Type,text/plain,True)
+
+Will cause example.html to be returned with both text/html and
+text/plain content-type headers.
+
+slice
+~~~~~
+
+Used to send only part of a response body. Takes the start and,
+optionally, end bytes as arguments, although either can be null to
+indicate the start or end of the file, respectively. So for example::
+
+ example.txt?pipe=slice(10,20)
+
+Would result in a response with a body containing 10 bytes of
+example.txt including byte 10 but excluding byte 20.
+
+::
+
+ example.txt?pipe=slice(10)
+
+Would cause all bytes from byte 10 of example.txt to be sent, but::
+
+ example.txt?pipe=slice(null,20)
+
+Would send the first 20 bytes of example.txt.
+
+trickle
+~~~~~~~
+
+.. note::
+ Using this function will force a connection close.
+
+Used to send the body of a response in chunks with delays. Takes a
+single argument that is a microsyntax consisting of colon-separated
+commands. There are three types of commands:
+
+* Bare numbers represent a number of bytes to send
+
+* Numbers prefixed `d` indicate a delay in seconds
+
+* Numbers prefixed `r` must only appear at the end of the command, and
+ indicate that the preceding N items must be repeated until there is
+ no more content to send. The number of items to repeat must be even.
+
+In the absence of a repetition command, the entire remainder of the content is
+sent at once when the command list is exhausted. So for example::
+
+ example.txt?pipe=trickle(d1)
+
+causes a 1s delay before sending the entirety of example.txt.
+
+::
+
+ example.txt?pipe=trickle(100:d1)
+
+causes 100 bytes of example.txt to be sent, followed by a 1s delay,
+and then the remainder of the file to be sent. On the other hand::
+
+ example.txt?pipe=trickle(100:d1:r2)
+
+Will cause the file to be sent in 100 byte chunks separated by a 1s
+delay until the whole content has been sent.
+
+
+:mod:`Interface <pipes>`
+------------------------
+
+.. automodule:: wptserve.pipes
+ :members:
diff --git a/tests/wpt/web-platform-tests/tools/wptserve/docs/request.rst b/tests/wpt/web-platform-tests/tools/wptserve/docs/request.rst
new file mode 100644
index 00000000000..790e4f0bb02
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/wptserve/docs/request.rst
@@ -0,0 +1,10 @@
+Request
+=======
+
+Request object.
+
+:mod:`Interface <request>`
+--------------------------
+
+.. automodule:: wptserve.request
+ :members:
diff --git a/tests/wpt/web-platform-tests/tools/wptserve/docs/response.rst b/tests/wpt/web-platform-tests/tools/wptserve/docs/response.rst
new file mode 100644
index 00000000000..23075dfb3d9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/wptserve/docs/response.rst
@@ -0,0 +1,41 @@
+Response
+========
+
+Response object. This object is used to control the response that will
+be sent to the HTTP client. A handler function will take the response
+object and fill in various parts of the response. For example, a plain
+text response with the body 'Some example content' could be produced as::
+
+ def handler(request, response):
+ response.headers.set("Content-Type", "text/plain")
+ response.content = "Some example content"
+
+The response object also gives access to a ResponseWriter, which
+allows direct access to the response socket. For example, one could
+write a similar response but with more explicit control as follows::
+
+ import time
+
+ def handler(request, response):
+ response.add_required_headers = False # Don't implicitly add HTTP headers
+ response.writer.write_status(200)
+ response.writer.write_header("Content-Type", "text/plain")
+ response.writer.write_header("Content-Length", len("Some example content"))
+ response.writer.end_headers()
+ response.writer.write("Some ")
+ time.sleep(1)
+ response.writer.write("example content")
+
+Note that when writing the response directly like this it is always
+necessary to either set the Content-Length header or set
+`response.close_connection = True`. Without one of these, the client
+will not be able to determine where the response body ends and will
+continue to load indefinitely.
+
+.. _response.Interface:
+
+:mod:`Interface <response>`
+---------------------------
+
+.. automodule:: wptserve.response
+ :members:
diff --git a/tests/wpt/web-platform-tests/tools/wptserve/docs/router.rst b/tests/wpt/web-platform-tests/tools/wptserve/docs/router.rst
new file mode 100644
index 00000000000..21d67d22268
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/wptserve/docs/router.rst
@@ -0,0 +1,78 @@
+Router
+======
+
+The router is used to match incoming requests to request handler
+functions. Typically users don't interact with the router directly,
+but instead send a list of routes to register when starting the
+server. However it is also possible to add routes after starting the
+server by calling the `register` method on the server's `router`
+property.
+
+Routes are represented by a three item tuple::
+
+ (methods, path_match, handler)
+
+`methods` is either a string or a list of strings indicating the HTTP
+methods to match. In cases where all methods should match there is a
+special sentinel value `any_method` provided as a property of the
+`router` module that can be used.
+
+`path_match` is an expression that will be evaluated against the
+request path to decide if the handler should match. These expressions
+follow a custom syntax intended to make matching URLs straightforward
+and, in particular, to be easier to use than raw regexp for URL
+matching. There are three possible components of a match expression:
+
+* Literals. These match any character. The special characters \*, \{
+ and \} must be escaped by prefixing them with a \\.
+
+* Match groups. These match any character other than / and save the
+ result as a named group. They are delimited by curly braces; for
+ example::
+
+ {abc}
+
+ would create a match group with the name `abc`.
+
+* Stars. These are denoted with a `*` and match any character
+ including /. There can be at most one star
+ per pattern and it must follow any match groups.
+
+Path expressions always match the entire request path and a leading /
+in the expression is implied even if it is not explicitly
+provided. This means that `/foo` and `foo` are equivalent.
+
+For example, the following pattern matches all requests for resources with the
+extension `.py`::
+
+ *.py
+
+The following expression matches anything directly under `/resources`
+with a `.html` extension, and places the "filename" in the `name`
+group::
+
+ /resources/{name}.html
+
+The groups, including anything that matches a `*` are available in the
+request object through the `route_match` property. This is a
+dictionary mapping the group names, and any match for `*` to the
+matching part of the route. For example, given a route::
+
+ /api/{sub_api}/*
+
+and the request path `/api/test/html/test.html`, `route_match` would
+be::
+
+ {"sub_api": "html", "*": "html/test.html"}
+
+`handler` is a function taking a request and a response object that is
+responsible for constructing the response to the HTTP request. See
+:doc:`handlers` for more details on handler functions.
+
+.. _router.Interface:
+
+:mod:`Interface <wptserve>`
+---------------------------
+
+.. automodule:: wptserve.router
+ :members:
diff --git a/tests/wpt/web-platform-tests/tools/wptserve/docs/server.rst b/tests/wpt/web-platform-tests/tools/wptserve/docs/server.rst
new file mode 100644
index 00000000000..732f9fdc78a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/wptserve/docs/server.rst
@@ -0,0 +1,20 @@
+Server
+======
+
+Basic server classes and router.
+
+The following example creates a server that serves static files from
+the `files` subdirectory of the current directory and causes it to
+run on port 8080 until it is killed::
+
+ from wptserve import server, handlers
+
+ httpd = server.WebTestHttpd(port=8080, doc_root="./files/",
+ routes=[("GET", "*", handlers.file_handler)])
+ httpd.start(block=True)
+
+:mod:`Interface <wptserve>`
+---------------------------
+
+.. automodule:: wptserve.server
+ :members:
diff --git a/tests/wpt/web-platform-tests/tools/wptserve/docs/stash.rst b/tests/wpt/web-platform-tests/tools/wptserve/docs/stash.rst
new file mode 100644
index 00000000000..821c2d34455
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/wptserve/docs/stash.rst
@@ -0,0 +1,31 @@
+Stash
+=====
+
+Object for storing cross-request state. This is unusual in that keys
+must be UUIDs, in order to prevent different clients setting the same
+key, and values are write-once, read-once to minimise the chances of
+state persisting indefinitely. The stash defines two operations;
+`put`, to add state and `take` to remove state. Furthermore, the view
+of the stash is path-specific; by default a request will only see the
+part of the stash corresponding to its own path.
+
+A typical example of using a stash to store state might be::
+
+ @handler
+ def handler(request, response):
+ # We assume this is a string representing a UUID
+ key = request.GET.first("id")
+
+ if request.method == "POST":
+ request.server.stash.put(key, "Some sample value")
+ return "Added value to stash"
+ else:
+ value = request.server.stash.take(key)
+ assert request.server.stash.take(key) is None
+ return key
+
+:mod:`Interface <stash>`
+------------------------
+
+.. automodule:: wptserve.stash
+ :members:
diff --git a/tests/wpt/web-platform-tests/tools/wptserve/setup.py b/tests/wpt/web-platform-tests/tools/wptserve/setup.py
new file mode 100644
index 00000000000..020fc20d224
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/wptserve/setup.py
@@ -0,0 +1,23 @@
+from setuptools import setup
+
+PACKAGE_VERSION = '1.2.1'
+deps = []
+
+setup(name='wptserve',
+ version=PACKAGE_VERSION,
+ description="Python webserver intended for in web browser testing",
+ long_description=open("README.md").read(),
+ # Get strings from http://pypi.python.org/pypi?%3Aaction=list_classifiers
+ classifiers=["Development Status :: 5 - Production/Stable",
+ "License :: OSI Approved :: BSD License",
+ "Topic :: Internet :: WWW/HTTP :: HTTP Servers"],
+ keywords='',
+ author='James Graham',
+ author_email='james@hoppipolla.co.uk',
+ url='http://wptserve.readthedocs.org/',
+ license='BSD',
+ packages=['wptserve'],
+ include_package_data=True,
+ zip_safe=False,
+ install_requires=deps
+ )
diff --git a/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/base.py b/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/base.py
new file mode 100644
index 00000000000..fe33a029129
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/base.py
@@ -0,0 +1,61 @@
+import base64
+import logging
+import os
+import unittest
+import urllib
+import urllib2
+import urlparse
+
+import wptserve
+
+logging.basicConfig()
+
+here = os.path.split(__file__)[0]
+doc_root = os.path.join(here, "docroot")
+
+class Request(urllib2.Request):
+ def __init__(self, *args, **kwargs):
+ urllib2.Request.__init__(self, *args, **kwargs)
+ self.method = "GET"
+
+ def get_method(self):
+ return self.method
+
+ def add_data(self, data):
+ if hasattr(data, "iteritems"):
+ data = urllib.urlencode(data)
+ print data
+ self.add_header("Content-Length", str(len(data)))
+ urllib2.Request.add_data(self, data)
+
+class TestUsingServer(unittest.TestCase):
+ def setUp(self):
+ self.server = wptserve.server.WebTestHttpd(host="localhost",
+ port=0,
+ use_ssl=False,
+ certificate=None,
+ doc_root=doc_root)
+ self.server.start(False)
+
+ def tearDown(self):
+ self.server.stop()
+
+ def abs_url(self, path, query=None):
+ return urlparse.urlunsplit(("http", "%s:%i" % (self.server.host, self.server.port), path, query, None))
+
+ def request(self, path, query=None, method="GET", headers=None, body=None, auth=None):
+ req = Request(self.abs_url(path, query))
+ req.method = method
+ if headers is None:
+ headers = {}
+
+ for name, value in headers.iteritems():
+ req.add_header(name, value)
+
+ if body is not None:
+ req.add_data(body)
+
+ if auth is not None:
+ req.add_header("Authorization", "Basic %s" % base64.encodestring('%s:%s' % auth))
+
+ return urllib2.urlopen(req)
diff --git a/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/docroot/document.txt b/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/docroot/document.txt
new file mode 100644
index 00000000000..611dccd8448
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/docroot/document.txt
@@ -0,0 +1 @@
+This is a test document
diff --git a/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/docroot/sub.txt b/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/docroot/sub.txt
new file mode 100644
index 00000000000..4302db16a2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/docroot/sub.txt
@@ -0,0 +1 @@
+{{host}} {{domains[]}} {{ports[http][0]}}
diff --git a/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/docroot/sub_headers.txt b/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/docroot/sub_headers.txt
new file mode 100644
index 00000000000..ee021eb8633
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/docroot/sub_headers.txt
@@ -0,0 +1 @@
+{{headers[X-Test]}}
diff --git a/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/docroot/sub_params.txt b/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/docroot/sub_params.txt
new file mode 100644
index 00000000000..8323878d6f8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/docroot/sub_params.txt
@@ -0,0 +1 @@
+{{GET[test]}}
diff --git a/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/docroot/test.asis b/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/docroot/test.asis
new file mode 100644
index 00000000000..b05ba7da809
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/docroot/test.asis
@@ -0,0 +1,5 @@
+HTTP/1.1 202 Giraffe
+X-TEST: PASS
+Content-Length: 7
+
+Content \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/docroot/test_string.py b/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/docroot/test_string.py
new file mode 100644
index 00000000000..8fa605bb181
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/docroot/test_string.py
@@ -0,0 +1,3 @@
+def main(request, response):
+ response.headers.set("Content-Type", "text/plain")
+ return "PASS"
diff --git a/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/docroot/test_tuple_2.py b/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/docroot/test_tuple_2.py
new file mode 100644
index 00000000000..fa791fbddd2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/docroot/test_tuple_2.py
@@ -0,0 +1,2 @@
+def main(request, response):
+ return [("Content-Type", "text/html"), ("X-Test", "PASS")], "PASS"
diff --git a/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/docroot/test_tuple_3.py b/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/docroot/test_tuple_3.py
new file mode 100644
index 00000000000..2c2656d047b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/docroot/test_tuple_3.py
@@ -0,0 +1,2 @@
+def main(request, response):
+ return (202, "Giraffe"), [("Content-Type", "text/html"), ("X-Test", "PASS")], "PASS"
diff --git a/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/docroot/with_headers.txt b/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/docroot/with_headers.txt
new file mode 100644
index 00000000000..45ce1a0790d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/docroot/with_headers.txt
@@ -0,0 +1 @@
+Test document with custom headers
diff --git a/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/docroot/with_headers.txt.sub.headers b/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/docroot/with_headers.txt.sub.headers
new file mode 100644
index 00000000000..81c59853e25
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/docroot/with_headers.txt.sub.headers
@@ -0,0 +1,3 @@
+Custom-Header: PASS
+Another-Header: {{$id:uuid()}}
+Same-Value-Header: {{$id}}
diff --git a/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/test_cookies.py b/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/test_cookies.py
new file mode 100644
index 00000000000..8cfd2565296
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/test_cookies.py
@@ -0,0 +1,65 @@
+import os
+import unittest
+import urllib2
+import json
+
+import wptserve
+from base import TestUsingServer, doc_root
+
+class TestResponseSetCookie(TestUsingServer):
+ def test_name_value(self):
+ @wptserve.handlers.handler
+ def handler(request, response):
+ response.set_cookie("name", "value")
+ return "Test"
+
+ route = ("GET", "/test/name_value", handler)
+ self.server.router.register(*route)
+ resp = self.request(route[1])
+
+ self.assertEquals(resp.info()["Set-Cookie"], "name=value; Path=/")
+
+ def test_unset(self):
+ @wptserve.handlers.handler
+ def handler(request, response):
+ response.set_cookie("name", "value")
+ response.unset_cookie("name")
+ return "Test"
+
+ route = ("GET", "/test/unset", handler)
+ self.server.router.register(*route)
+ resp = self.request(route[1])
+
+ self.assertTrue("Set-Cookie" not in resp.info())
+
+ def test_delete(self):
+ @wptserve.handlers.handler
+ def handler(request, response):
+ response.delete_cookie("name")
+ return "Test"
+
+ route = ("GET", "/test/delete", handler)
+ self.server.router.register(*route)
+ resp = self.request(route[1])
+
+ parts = dict(item.split("=") for
+ item in resp.info()["Set-Cookie"].split("; ") if item)
+
+ self.assertEquals(parts["name"], "")
+ self.assertEquals(parts["Path"], "/")
+ #Should also check that expires is in the past
+
+class TestRequestCookies(TestUsingServer):
+ def test_set_cookie(self):
+ @wptserve.handlers.handler
+ def handler(request, response):
+ return request.cookies["name"].value
+
+ route = ("GET", "/test/set_cookie", handler)
+ self.server.router.register(*route)
+ resp = self.request(route[1], headers={"Cookie": "name=value"})
+
+ self.assertEquals(resp.read(), "value")
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/test_handlers.py b/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/test_handlers.py
new file mode 100644
index 00000000000..bc416932448
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/test_handlers.py
@@ -0,0 +1,212 @@
+import json
+import os
+import unittest
+import urllib2
+import uuid
+
+import wptserve
+from base import TestUsingServer, doc_root
+
+class TestFileHandler(TestUsingServer):
+ def test_GET(self):
+ resp = self.request("/document.txt")
+ self.assertEquals(200, resp.getcode())
+ self.assertEquals("text/plain", resp.info()["Content-Type"])
+ self.assertEquals(open(os.path.join(doc_root, "document.txt")).read(), resp.read())
+
+ def test_headers(self):
+ resp = self.request("/with_headers.txt")
+ self.assertEquals(200, resp.getcode())
+ self.assertEquals("PASS", resp.info()["Custom-Header"])
+ # This will fail if it isn't a valid uuid
+ uuid.UUID(resp.info()["Another-Header"])
+ self.assertEquals(resp.info()["Same-Value-Header"], resp.info()["Another-Header"])
+
+
+ def test_range(self):
+ resp = self.request("/document.txt", headers={"Range":"bytes=10-19"})
+ self.assertEquals(206, resp.getcode())
+ data = resp.read()
+ expected = open(os.path.join(doc_root, "document.txt")).read()
+ self.assertEquals(10, len(data))
+ self.assertEquals("bytes 10-19/%i" % len(expected), resp.info()['Content-Range'])
+ self.assertEquals("10", resp.info()['Content-Length'])
+ self.assertEquals(expected[10:20], data)
+
+ def test_range_no_end(self):
+ resp = self.request("/document.txt", headers={"Range":"bytes=10-"})
+ self.assertEquals(206, resp.getcode())
+ data = resp.read()
+ expected = open(os.path.join(doc_root, "document.txt")).read()
+ self.assertEquals(len(expected) - 10, len(data))
+ self.assertEquals("bytes 10-%i/%i" % (len(expected) - 1, len(expected)), resp.info()['Content-Range'])
+ self.assertEquals(expected[10:], data)
+
+ def test_range_no_start(self):
+ resp = self.request("/document.txt", headers={"Range":"bytes=-10"})
+ self.assertEquals(206, resp.getcode())
+ data = resp.read()
+ expected = open(os.path.join(doc_root, "document.txt")).read()
+ self.assertEquals(10, len(data))
+ self.assertEquals("bytes %i-%i/%i" % (len(expected) - 10,
+ len(expected) - 1,
+ len(expected)), resp.info()['Content-Range'])
+ self.assertEquals(expected[-10:], data)
+
+ def test_multiple_ranges(self):
+ resp = self.request("/document.txt", headers={"Range":"bytes=1-2,5-7,6-10"})
+ self.assertEquals(206, resp.getcode())
+ data = resp.read()
+ expected = open(os.path.join(doc_root, "document.txt")).read()
+ self.assertTrue(resp.info()["Content-Type"].startswith("multipart/byteranges; boundary="))
+ boundary = resp.info()["Content-Type"].split("boundary=")[1]
+ parts = data.split("--" + boundary)
+ self.assertEquals("\r\n", parts[0])
+ self.assertEquals("--", parts[-1])
+ expected_parts = [("1-2", expected[1:3]), ("5-10", expected[5:11])]
+ for expected_part, part in zip(expected_parts, parts[1:-1]):
+ header_string, body = part.split("\r\n\r\n")
+ headers = dict(item.split(": ", 1) for item in header_string.split("\r\n") if item.strip())
+ self.assertEquals(headers["Content-Type"], "text/plain")
+ self.assertEquals(headers["Content-Range"], "bytes %s/%i" % (expected_part[0], len(expected)))
+ self.assertEquals(expected_part[1] + "\r\n", body)
+
+ def test_range_invalid(self):
+ with self.assertRaises(urllib2.HTTPError) as cm:
+ self.request("/document.txt", headers={"Range":"bytes=11-10"})
+ self.assertEquals(cm.exception.code, 416)
+
+ expected = open(os.path.join(doc_root, "document.txt")).read()
+ with self.assertRaises(urllib2.HTTPError) as cm:
+ self.request("/document.txt", headers={"Range":"bytes=%i-%i" % (len(expected), len(expected) + 10)})
+ self.assertEquals(cm.exception.code, 416)
+
+
+class TestFunctionHandler(TestUsingServer):
+ def test_string_rv(self):
+ @wptserve.handlers.handler
+ def handler(request, response):
+ return "test data"
+
+ route = ("GET", "/test/test_string_rv", handler)
+ self.server.router.register(*route)
+ resp = self.request(route[1])
+ self.assertEquals(200, resp.getcode())
+ self.assertEquals("9", resp.info()["Content-Length"])
+ self.assertEquals("test data", resp.read())
+
+ def test_tuple_2_rv(self):
+ @wptserve.handlers.handler
+ def handler(request, response):
+ return [("Content-Length", 4), ("test-header", "test-value")], "test data"
+
+ route = ("GET", "/test/test_tuple_2_rv", handler)
+ self.server.router.register(*route)
+ resp = self.request(route[1])
+ self.assertEquals(200, resp.getcode())
+ self.assertEquals("4", resp.info()["Content-Length"])
+ self.assertEquals("test-value", resp.info()["test-header"])
+ self.assertEquals("test", resp.read())
+
+ def test_tuple_3_rv(self):
+ @wptserve.handlers.handler
+ def handler(request, response):
+ return 202, [("test-header", "test-value")], "test data"
+
+ route = ("GET", "/test/test_tuple_3_rv", handler)
+ self.server.router.register(*route)
+ resp = self.request(route[1])
+ self.assertEquals(202, resp.getcode())
+ self.assertEquals("test-value", resp.info()["test-header"])
+ self.assertEquals("test data", resp.read())
+
+ def test_tuple_3_rv_1(self):
+ @wptserve.handlers.handler
+ def handler(request, response):
+ return (202, "Some Status"), [("test-header", "test-value")], "test data"
+
+ route = ("GET", "/test/test_tuple_3_rv_1", handler)
+ self.server.router.register(*route)
+ resp = self.request(route[1])
+ self.assertEquals(202, resp.getcode())
+ self.assertEquals("Some Status", resp.msg)
+ self.assertEquals("test-value", resp.info()["test-header"])
+ self.assertEquals("test data", resp.read())
+
+class TestJSONHandler(TestUsingServer):
+ def test_json_0(self):
+ @wptserve.handlers.json_handler
+ def handler(request, response):
+ return {"data": "test data"}
+
+ route = ("GET", "/test/test_json_0", handler)
+ self.server.router.register(*route)
+ resp = self.request(route[1])
+ self.assertEquals(200, resp.getcode())
+ self.assertEquals({"data": "test data"}, json.load(resp))
+
+ def test_json_tuple_2(self):
+ @wptserve.handlers.json_handler
+ def handler(request, response):
+ return [("Test-Header", "test-value")], {"data": "test data"}
+
+ route = ("GET", "/test/test_json_tuple_2", handler)
+ self.server.router.register(*route)
+ resp = self.request(route[1])
+ self.assertEquals(200, resp.getcode())
+ self.assertEquals("test-value", resp.info()["test-header"])
+ self.assertEquals({"data": "test data"}, json.load(resp))
+
+ def test_json_tuple_3(self):
+ @wptserve.handlers.json_handler
+ def handler(request, response):
+ return (202, "Giraffe"), [("Test-Header", "test-value")], {"data": "test data"}
+
+ route = ("GET", "/test/test_json_tuple_2", handler)
+ self.server.router.register(*route)
+ resp = self.request(route[1])
+ self.assertEquals(202, resp.getcode())
+ self.assertEquals("Giraffe", resp.msg)
+ self.assertEquals("test-value", resp.info()["test-header"])
+ self.assertEquals({"data": "test data"}, json.load(resp))
+
+class TestPythonHandler(TestUsingServer):
+ def test_string(self):
+ resp = self.request("/test_string.py")
+ self.assertEquals(200, resp.getcode())
+ self.assertEquals("text/plain", resp.info()["Content-Type"])
+ self.assertEquals("PASS", resp.read())
+
+ def test_tuple_2(self):
+ resp = self.request("/test_tuple_2.py")
+ self.assertEquals(200, resp.getcode())
+ self.assertEquals("text/html", resp.info()["Content-Type"])
+ self.assertEquals("PASS", resp.info()["X-Test"])
+ self.assertEquals("PASS", resp.read())
+
+ def test_tuple_3(self):
+ resp = self.request("/test_tuple_3.py")
+ self.assertEquals(202, resp.getcode())
+ self.assertEquals("Giraffe", resp.msg)
+ self.assertEquals("text/html", resp.info()["Content-Type"])
+ self.assertEquals("PASS", resp.info()["X-Test"])
+ self.assertEquals("PASS", resp.read())
+
+class TestDirectoryHandler(TestUsingServer):
+ def test_directory(self):
+ resp = self.request("/")
+ self.assertEquals(200, resp.getcode())
+ self.assertEquals("text/html", resp.info()["Content-Type"])
+ #Add a check that the response is actually sane
+
+class TestAsIsHandler(TestUsingServer):
+ def test_as_is(self):
+ resp = self.request("/test.asis")
+ self.assertEquals(202, resp.getcode())
+ self.assertEquals("Giraffe", resp.msg)
+ self.assertEquals("PASS", resp.info()["X-Test"])
+ self.assertEquals("Content", resp.read())
+ #Add a check that the response is actually sane
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/test_pipes.py b/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/test_pipes.py
new file mode 100644
index 00000000000..08deaf01cd7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/test_pipes.py
@@ -0,0 +1,80 @@
+import os
+import unittest
+import urllib2
+import json
+import time
+
+import wptserve
+from base import TestUsingServer, doc_root
+
+class TestStatus(TestUsingServer):
+ def test_status(self):
+ resp = self.request("/document.txt", query="pipe=status(202)")
+ self.assertEquals(resp.getcode(), 202)
+
+class TestHeader(TestUsingServer):
+ def test_not_set(self):
+ resp = self.request("/document.txt", query="pipe=header(X-TEST,PASS)")
+ self.assertEquals(resp.info()["X-TEST"], "PASS")
+
+ def test_set(self):
+ resp = self.request("/document.txt", query="pipe=header(Content-Type,text/html)")
+ self.assertEquals(resp.info()["Content-Type"], "text/html")
+
+ def test_multiple(self):
+ resp = self.request("/document.txt", query="pipe=header(X-Test,PASS)|header(Content-Type,text/html)")
+ self.assertEquals(resp.info()["X-TEST"], "PASS")
+ self.assertEquals(resp.info()["Content-Type"], "text/html")
+
+ def test_multiple_same(self):
+ resp = self.request("/document.txt", query="pipe=header(Content-Type,FAIL)|header(Content-Type,text/html)")
+ self.assertEquals(resp.info()["Content-Type"], "text/html")
+
+ def test_multiple_append(self):
+ resp = self.request("/document.txt", query="pipe=header(X-Test,1)|header(X-Test,2,True)")
+ self.assertEquals(resp.info()["X-Test"], "1, 2")
+
+class TestSlice(TestUsingServer):
+ def test_both_bounds(self):
+ resp = self.request("/document.txt", query="pipe=slice(1,10)")
+ expected = open(os.path.join(doc_root, "document.txt")).read()
+ self.assertEquals(resp.read(), expected[1:10])
+
+ def test_no_upper(self):
+ resp = self.request("/document.txt", query="pipe=slice(1)")
+ expected = open(os.path.join(doc_root, "document.txt")).read()
+ self.assertEquals(resp.read(), expected[1:])
+
+ def test_no_lower(self):
+ resp = self.request("/document.txt", query="pipe=slice(null,10)")
+ expected = open(os.path.join(doc_root, "document.txt")).read()
+ self.assertEquals(resp.read(), expected[:10])
+
+class TestSub(TestUsingServer):
+ def test_sub_config(self):
+ resp = self.request("/sub.txt", query="pipe=sub")
+ expected = "localhost localhost %i\n" % self.server.port
+ self.assertEquals(resp.read(), expected)
+
+ def test_sub_headers(self):
+ resp = self.request("/sub_headers.txt", query="pipe=sub", headers={"X-Test": "PASS"})
+ expected = "PASS\n"
+ self.assertEquals(resp.read(), expected)
+
+ def test_sub_params(self):
+ resp = self.request("/sub_params.txt", query="test=PASS&pipe=sub")
+ expected = "PASS\n"
+ self.assertEquals(resp.read(), expected)
+
+class TestTrickle(TestUsingServer):
+ def test_trickle(self):
+ #Actually testing that the response trickles in is not that easy
+ t0 = time.time()
+ resp = self.request("/document.txt", query="pipe=trickle(1:d2:5:d1:r2)")
+ t1 = time.time()
+ expected = open(os.path.join(doc_root, "document.txt")).read()
+ self.assertEquals(resp.read(), expected)
+ self.assertGreater(6, t1-t0)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/test_request.py b/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/test_request.py
new file mode 100644
index 00000000000..dab68e4958f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/test_request.py
@@ -0,0 +1,86 @@
+import os
+import unittest
+import urllib2
+import json
+import time
+
+import wptserve
+from base import TestUsingServer, doc_root
+
+class TestInputFile(TestUsingServer):
+ def test_seek(self):
+ @wptserve.handlers.handler
+ def handler(request, response):
+ rv = []
+ f = request.raw_input
+ f.seek(5)
+ rv.append(f.read(2))
+ rv.append(f.tell())
+ f.seek(0)
+ rv.append(f.readline())
+ rv.append(f.tell())
+ rv.append(f.read(-1))
+ rv.append(f.tell())
+ f.seek(0)
+ rv.append(f.read())
+ f.seek(0)
+ rv.extend(f.readlines())
+
+ return " ".join(str(item) for item in rv)
+
+ route = ("POST", "/test/test_seek", handler)
+ self.server.router.register(*route)
+ resp = self.request(route[1], method="POST", body="12345ab\ncdef")
+ self.assertEquals(200, resp.getcode())
+ self.assertEquals(["ab", "7", "12345ab\n", "8", "cdef", "12",
+ "12345ab\ncdef", "12345ab\n", "cdef"],
+ resp.read().split(" "))
+
+ def test_iter(self):
+ @wptserve.handlers.handler
+ def handler(request, response):
+ f = request.raw_input
+ return " ".join(line for line in f)
+
+ route = ("POST", "/test/test_iter", handler)
+ self.server.router.register(*route)
+ resp = self.request(route[1], method="POST", body="12345\nabcdef\r\nzyxwv")
+ self.assertEquals(200, resp.getcode())
+ self.assertEquals(["12345\n", "abcdef\r\n", "zyxwv"], resp.read().split(" "))
+
+class TestRequest(TestUsingServer):
+ def test_body(self):
+ @wptserve.handlers.handler
+ def handler(request, response):
+ request.raw_input.seek(5)
+ return request.body
+
+ route = ("POST", "/test/test_body", handler)
+ self.server.router.register(*route)
+ resp = self.request(route[1], method="POST", body="12345ab\ncdef")
+ self.assertEquals("12345ab\ncdef", resp.read())
+
+ def test_route_match(self):
+ @wptserve.handlers.handler
+ def handler(request, response):
+ return request.route_match["match"] + " " + request.route_match["*"]
+
+ route = ("GET", "/test/{match}_*", handler)
+ self.server.router.register(*route)
+ resp = self.request("/test/some_route")
+ self.assertEquals("some route", resp.read())
+
+class TestAuth(TestUsingServer):
+ def test_auth(self):
+ @wptserve.handlers.handler
+ def handler(request, response):
+ return " ".join((request.auth.username, request.auth.password))
+
+ route = ("GET", "/test/test_auth", handler)
+ self.server.router.register(*route)
+ resp = self.request(route[1], auth=("test", "PASS"))
+ self.assertEquals(200, resp.getcode())
+ self.assertEquals(["test", "PASS"], resp.read().split(" "))
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/test_response.py b/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/test_response.py
new file mode 100644
index 00000000000..86398677e09
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/test_response.py
@@ -0,0 +1,51 @@
+import os
+import unittest
+import urllib2
+import json
+import time
+from types import MethodType
+
+import wptserve
+from base import TestUsingServer, doc_root
+
+def send_body_as_header(self):
+ if self._response.add_required_headers:
+ self.write_default_headers()
+
+ self.write("X-Body: ")
+ self._headers_complete = True
+
+class TestResponse(TestUsingServer):
+ def test_head_without_body(self):
+ @wptserve.handlers.handler
+ def handler(request, response):
+ response.writer.end_headers = MethodType(send_body_as_header,
+ response.writer,
+ wptserve.response.ResponseWriter)
+ return [("X-Test", "TEST")], "body\r\n"
+
+ route = ("GET", "/test/test_head_without_body", handler)
+ self.server.router.register(*route)
+ resp = self.request(route[1], method="HEAD")
+ self.assertEquals("6", resp.info()['Content-Length'])
+ self.assertEquals("TEST", resp.info()['x-Test'])
+ self.assertEquals("", resp.info()['x-body'])
+
+ def test_head_with_body(self):
+ @wptserve.handlers.handler
+ def handler(request, response):
+ response.send_body_for_head_request = True
+ response.writer.end_headers = MethodType(send_body_as_header,
+ response.writer,
+ wptserve.response.ResponseWriter)
+ return [("X-Test", "TEST")], "body\r\n"
+
+ route = ("GET", "/test/test_head_with_body", handler)
+ self.server.router.register(*route)
+ resp = self.request(route[1], method="HEAD")
+ self.assertEquals("6", resp.info()['Content-Length'])
+ self.assertEquals("TEST", resp.info()['x-Test'])
+ self.assertEquals("body", resp.info()['X-Body'])
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/test_server.py b/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/test_server.py
new file mode 100644
index 00000000000..4630ffb9fdf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/test_server.py
@@ -0,0 +1,43 @@
+import os
+import unittest
+import urllib2
+import json
+
+import wptserve
+from base import TestUsingServer, doc_root
+
+class TestFileHandler(TestUsingServer):
+ def test_not_handled(self):
+ with self.assertRaises(urllib2.HTTPError) as cm:
+ resp = self.request("/not_existing")
+
+ self.assertEquals(cm.exception.code, 404)
+
+class TestRewriter(TestUsingServer):
+ def test_rewrite(self):
+ @wptserve.handlers.handler
+ def handler(request, response):
+ return request.request_path
+
+ route = ("GET", "/test/rewritten", handler)
+ self.server.rewriter.register("GET", "/test/original", route[1])
+ self.server.router.register(*route)
+ resp = self.request("/test/original")
+ self.assertEquals(200, resp.getcode())
+ self.assertEquals("/test/rewritten", resp.read())
+
+class TestRequestHandler(TestUsingServer):
+ def test_exception(self):
+ @wptserve.handlers.handler
+ def handler(request, response):
+ raise Exception
+
+ route = ("GET", "/test/raises", handler)
+ self.server.router.register(*route)
+ with self.assertRaises(urllib2.HTTPError) as cm:
+ resp = self.request("/test/raises")
+
+ self.assertEquals(cm.exception.code, 500)
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/test_stash.py b/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/test_stash.py
new file mode 100644
index 00000000000..9cbff3a7b6d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/wptserve/tests/functional/test_stash.py
@@ -0,0 +1,39 @@
+import os
+import unittest
+import urllib2
+import json
+import uuid
+
+import wptserve
+from wptserve.router import any_method
+from base import TestUsingServer, doc_root
+
+class TestResponseSetCookie(TestUsingServer):
+ def test_put_take(self):
+ @wptserve.handlers.handler
+ def handler(request, response):
+ if request.method == "POST":
+ request.server.stash.put(request.POST.first("id"), request.POST.first("data"))
+ data = "OK"
+ elif request.method == "GET":
+ data = request.server.stash.take(request.GET.first("id"))
+ if data is None:
+ return "NOT FOUND"
+ return data
+
+ id = str(uuid.uuid4())
+ route = (any_method, "/test/put_take", handler)
+ self.server.router.register(*route)
+
+ resp = self.request(route[1], method="POST", body={"id": id, "data": "Sample data"})
+ self.assertEquals(resp.read(), "OK")
+
+ resp = self.request(route[1], query="id=" + id)
+ self.assertEquals(resp.read(), "Sample data")
+
+ resp = self.request(route[1], query="id=" + id)
+ self.assertEquals(resp.read(), "NOT FOUND")
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/wpt/web-platform-tests/tools/wptserve/wptserve/__init__.py b/tests/wpt/web-platform-tests/tools/wptserve/wptserve/__init__.py
new file mode 100644
index 00000000000..cac5aeb3ca9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/wptserve/wptserve/__init__.py
@@ -0,0 +1,3 @@
+from server import WebTestHttpd, WebTestServer, Router
+from request import Request
+from response import Response
diff --git a/tests/wpt/web-platform-tests/tools/wptserve/wptserve/constants.py b/tests/wpt/web-platform-tests/tools/wptserve/wptserve/constants.py
new file mode 100644
index 00000000000..385e512c7d5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/wptserve/wptserve/constants.py
@@ -0,0 +1,92 @@
+import utils
+
+content_types = utils.invert_dict({"text/html": ["htm", "html"],
+ "application/json": ["json"],
+ "application/xhtml+xml": ["xht", "xhtm", "xhtml"],
+ "application/xml": ["xml"],
+ "application/x-xpinstall": ["xpi"],
+ "text/javascript": ["js"],
+ "text/css": ["css"],
+ "text/plain": ["txt", "md"],
+ "image/svg+xml": ["svg"],
+ "image/gif": ["gif"],
+ "image/jpeg": ["jpg", "jpeg"],
+ "image/png": ["png"],
+ "image/bmp": ["bmp"],
+ "text/event-stream": ["event_stream"],
+ "text/cache-manifest": ["manifest"],
+ "video/mp4": ["mp4", "m4v"],
+ "audio/mp4": ["m4a"],
+ "audio/mpeg": ["mp3"],
+ "video/webm": ["webm"],
+ "audio/webm": ["weba"],
+ "video/ogg": ["ogg", "ogv"],
+ "audio/ogg": ["oga"],
+ "audio/x-wav": ["wav"],
+ "text/vtt": ["vtt"],})
+
+response_codes = {
+ 100: ('Continue', 'Request received, please continue'),
+ 101: ('Switching Protocols',
+ 'Switching to new protocol; obey Upgrade header'),
+
+ 200: ('OK', 'Request fulfilled, document follows'),
+ 201: ('Created', 'Document created, URL follows'),
+ 202: ('Accepted',
+ 'Request accepted, processing continues off-line'),
+ 203: ('Non-Authoritative Information', 'Request fulfilled from cache'),
+ 204: ('No Content', 'Request fulfilled, nothing follows'),
+ 205: ('Reset Content', 'Clear input form for further input.'),
+ 206: ('Partial Content', 'Partial content follows.'),
+
+ 300: ('Multiple Choices',
+ 'Object has several resources -- see URI list'),
+ 301: ('Moved Permanently', 'Object moved permanently -- see URI list'),
+ 302: ('Found', 'Object moved temporarily -- see URI list'),
+ 303: ('See Other', 'Object moved -- see Method and URL list'),
+ 304: ('Not Modified',
+ 'Document has not changed since given time'),
+ 305: ('Use Proxy',
+ 'You must use proxy specified in Location to access this '
+ 'resource.'),
+ 307: ('Temporary Redirect',
+ 'Object moved temporarily -- see URI list'),
+
+ 400: ('Bad Request',
+ 'Bad request syntax or unsupported method'),
+ 401: ('Unauthorized',
+ 'No permission -- see authorization schemes'),
+ 402: ('Payment Required',
+ 'No payment -- see charging schemes'),
+ 403: ('Forbidden',
+ 'Request forbidden -- authorization will not help'),
+ 404: ('Not Found', 'Nothing matches the given URI'),
+ 405: ('Method Not Allowed',
+ 'Specified method is invalid for this resource.'),
+ 406: ('Not Acceptable', 'URI not available in preferred format.'),
+ 407: ('Proxy Authentication Required', 'You must authenticate with '
+ 'this proxy before proceeding.'),
+ 408: ('Request Timeout', 'Request timed out; try again later.'),
+ 409: ('Conflict', 'Request conflict.'),
+ 410: ('Gone',
+ 'URI no longer exists and has been permanently removed.'),
+ 411: ('Length Required', 'Client must specify Content-Length.'),
+ 412: ('Precondition Failed', 'Precondition in headers is false.'),
+ 413: ('Request Entity Too Large', 'Entity is too large.'),
+ 414: ('Request-URI Too Long', 'URI is too long.'),
+ 415: ('Unsupported Media Type', 'Entity body in unsupported format.'),
+ 416: ('Requested Range Not Satisfiable',
+ 'Cannot satisfy request range.'),
+ 417: ('Expectation Failed',
+ 'Expect condition could not be satisfied.'),
+
+ 500: ('Internal Server Error', 'Server got itself in trouble'),
+ 501: ('Not Implemented',
+ 'Server does not support this operation'),
+ 502: ('Bad Gateway', 'Invalid responses from another server/proxy.'),
+ 503: ('Service Unavailable',
+ 'The server cannot process the request due to a high load'),
+ 504: ('Gateway Timeout',
+ 'The gateway server did not receive a timely response'),
+ 505: ('HTTP Version Not Supported', 'Cannot fulfill request.'),
+ }
diff --git a/tests/wpt/web-platform-tests/tools/wptserve/wptserve/handlers.py b/tests/wpt/web-platform-tests/tools/wptserve/wptserve/handlers.py
new file mode 100644
index 00000000000..8bd3fda3248
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/wptserve/wptserve/handlers.py
@@ -0,0 +1,329 @@
+import cgi
+import json
+import os
+import traceback
+import urllib
+import urlparse
+
+from constants import content_types
+from pipes import Pipeline, template
+from ranges import RangeParser
+from request import Authentication
+from response import MultipartContent
+from utils import HTTPException
+
+__all__ = ["file_handler", "python_script_handler",
+ "FunctionHandler", "handler", "json_handler",
+ "as_is_handler", "ErrorHandler", "BasicAuthHandler"]
+
+
+def guess_content_type(path):
+ ext = os.path.splitext(path)[1].lstrip(".")
+ if ext in content_types:
+ return content_types[ext]
+
+ return "application/octet-stream"
+
+
+
+def filesystem_path(base_path, request, url_base="/"):
+ if base_path is None:
+ base_path = request.doc_root
+
+ path = request.url_parts.path
+
+ if path.startswith(url_base):
+ path = path[len(url_base):]
+
+ if ".." in path:
+ raise HTTPException(404)
+
+ new_path = os.path.join(base_path, path)
+
+ # Otherwise setting path to / allows access outside the root directory
+ if not new_path.startswith(base_path):
+ raise HTTPException(404)
+
+ return new_path
+
+class DirectoryHandler(object):
+ def __init__(self, base_path=None, url_base="/"):
+ self.base_path = base_path
+ self.url_base = url_base
+
+ def __call__(self, request, response):
+ path = filesystem_path(self.base_path, request, self.url_base)
+
+ assert os.path.isdir(path)
+
+ response.headers = [("Content-Type", "text/html")]
+ response.content = """<!doctype html>
+<meta name="viewport" content="width=device-width">
+<title>Directory listing for %(path)s</title>
+<h1>Directory listing for %(path)s</h1>
+<ul>
+%(items)s
+</li>
+""" % {"path": cgi.escape(request.url_parts.path),
+ "items": "\n".join(self.list_items(request, path))}
+
+ def list_items(self, request, path):
+ # TODO: this won't actually list all routes, only the
+ # ones that correspond to a real filesystem path. It's
+ # not possible to list every route that will match
+ # something, but it should be possible to at least list the
+ # statically defined ones
+ base_path = request.url_parts.path
+
+ if not base_path.endswith("/"):
+ base_path += "/"
+ if base_path != "/":
+ link = urlparse.urljoin(base_path, "..")
+ yield ("""<li class="dir"><a href="%(link)s">%(name)s</a>""" %
+ {"link": link, "name": ".."})
+ for item in sorted(os.listdir(path)):
+ link = cgi.escape(urllib.quote(item))
+ if os.path.isdir(os.path.join(path, item)):
+ link += "/"
+ class_ = "dir"
+ else:
+ class_ = "file"
+ yield ("""<li class="%(class)s"><a href="%(link)s">%(name)s</a>""" %
+ {"link": link, "name": cgi.escape(item), "class": class_})
+
+
+directory_handler = DirectoryHandler()
+
+
+class FileHandler(object):
+ def __init__(self, base_path=None, url_base="/"):
+ self.base_path = base_path
+ self.url_base = url_base
+ self.directory_handler = DirectoryHandler(self.base_path)
+
+ def __call__(self, request, response):
+ path = filesystem_path(self.base_path, request, self.url_base)
+
+ if os.path.isdir(path):
+ return self.directory_handler(request, response)
+ try:
+ #This is probably racy with some other process trying to change the file
+ file_size = os.stat(path).st_size
+ response.headers.update(self.get_headers(request, path))
+ if "Range" in request.headers:
+ try:
+ byte_ranges = RangeParser()(request.headers['Range'], file_size)
+ except HTTPException as e:
+ if e.code == 416:
+ response.headers.set("Content-Range", "bytes */%i" % file_size)
+ raise
+ else:
+ byte_ranges = None
+ data = self.get_data(response, path, byte_ranges)
+ response.content = data
+ query = urlparse.parse_qs(request.url_parts.query)
+
+ pipeline = None
+ if "pipe" in query:
+ pipeline = Pipeline(query["pipe"][-1])
+ elif os.path.splitext(path)[0].endswith(".sub"):
+ pipeline = Pipeline("sub")
+ if pipeline is not None:
+ response = pipeline(request, response)
+
+ return response
+
+ except (OSError, IOError):
+ raise HTTPException(404)
+
+ def get_headers(self, request, path):
+ rv = self.default_headers(path)
+ rv.extend(self.load_headers(request, os.path.join(os.path.split(path)[0], "__dir__")))
+ rv.extend(self.load_headers(request, path))
+ return rv
+
+ def load_headers(self, request, path):
+ headers_path = path + ".sub.headers"
+ if os.path.exists(headers_path):
+ use_sub = True
+ else:
+ headers_path = path + ".headers"
+ use_sub = False
+
+ try:
+ with open(headers_path) as headers_file:
+ data = headers_file.read()
+ except IOError:
+ return []
+ else:
+ if use_sub:
+ data = template(request, data)
+ return [tuple(item.strip() for item in line.split(":", 1))
+ for line in data.splitlines() if line]
+
+ def get_data(self, response, path, byte_ranges):
+ with open(path, 'rb') as f:
+ if byte_ranges is None:
+ return f.read()
+ else:
+ response.status = 206
+ if len(byte_ranges) > 1:
+ parts_content_type, content = self.set_response_multipart(response,
+ byte_ranges,
+ f)
+ for byte_range in byte_ranges:
+ content.append_part(self.get_range_data(f, byte_range),
+ parts_content_type,
+ [("Content-Range", byte_range.header_value())])
+ return content
+ else:
+ response.headers.set("Content-Range", byte_ranges[0].header_value())
+ return self.get_range_data(f, byte_ranges[0])
+
+ def set_response_multipart(self, response, ranges, f):
+ parts_content_type = response.headers.get("Content-Type")
+ if parts_content_type:
+ parts_content_type = parts_content_type[-1]
+ else:
+ parts_content_type = None
+ content = MultipartContent()
+ response.headers.set("Content-Type", "multipart/byteranges; boundary=%s" % content.boundary)
+ return parts_content_type, content
+
+ def get_range_data(self, f, byte_range):
+ f.seek(byte_range.lower)
+ return f.read(byte_range.upper - byte_range.lower)
+
+ def default_headers(self, path):
+ return [("Content-Type", guess_content_type(path))]
+
+
+file_handler = FileHandler()
+
+
+class PythonScriptHandler(object):
+ def __init__(self, base_path=None, url_base="/"):
+ self.base_path = base_path
+ self.url_base = url_base
+
+ def __call__(self, request, response):
+ path = filesystem_path(self.base_path, request, self.url_base)
+
+ try:
+ environ = {"__file__": path}
+ execfile(path, environ, environ)
+ if "main" in environ:
+ handler = FunctionHandler(environ["main"])
+ handler(request, response)
+ else:
+ raise HTTPException(500, "No main function in script %s" % path)
+ except IOError:
+ raise HTTPException(404)
+
+python_script_handler = PythonScriptHandler()
+
+class FunctionHandler(object):
+ def __init__(self, func):
+ self.func = func
+
+ def __call__(self, request, response):
+ try:
+ rv = self.func(request, response)
+ except Exception:
+ msg = traceback.format_exc()
+ raise HTTPException(500, message=msg)
+ if rv is not None:
+ if isinstance(rv, tuple):
+ if len(rv) == 3:
+ status, headers, content = rv
+ response.status = status
+ elif len(rv) == 2:
+ headers, content = rv
+ else:
+ raise HTTPException(500)
+ response.headers.update(headers)
+ else:
+ content = rv
+ response.content = content
+
+
+#The generic name here is so that this can be used as a decorator
+def handler(func):
+ return FunctionHandler(func)
+
+
+class JsonHandler(object):
+ def __init__(self, func):
+ self.func = func
+
+ def __call__(self, request, response):
+ return FunctionHandler(self.handle_request)(request, response)
+
+ def handle_request(self, request, response):
+ rv = self.func(request, response)
+ response.headers.set("Content-Type", "application/json")
+ enc = json.dumps
+ if isinstance(rv, tuple):
+ rv = list(rv)
+ value = tuple(rv[:-1] + [enc(rv[-1])])
+ length = len(value[-1])
+ else:
+ value = enc(rv)
+ length = len(value)
+ response.headers.set("Content-Length", length)
+ return value
+
+def json_handler(func):
+ return JsonHandler(func)
+
+class AsIsHandler(object):
+ def __init__(self, base_path=None, url_base="/"):
+ self.base_path = base_path
+ self.url_base = url_base
+
+ def __call__(self, request, response):
+ path = filesystem_path(self.base_path, request, self.url_base)
+
+ try:
+ with open(path) as f:
+ response.writer.write_content(f.read())
+ response.close_connection = True
+ except IOError:
+ raise HTTPException(404)
+
+as_is_handler = AsIsHandler()
+
+class BasicAuthHandler(object):
+ def __init__(self, handler, user, password):
+ """
+ A Basic Auth handler
+
+ :Args:
+ - handler: a secondary handler for the request after authentication is successful (example file_handler)
+ - user: string of the valid user name or None if any / all credentials are allowed
+ - password: string of the password required
+ """
+ self.user = user
+ self.password = password
+ self.handler = handler
+
+ def __call__(self, request, response):
+ if "authorization" not in request.headers:
+ response.status = 401
+ response.headers.set("WWW-Authenticate", "Basic")
+ return response
+ else:
+ auth = Authentication(request.headers)
+ if self.user is not None and (self.user != auth.username or self.password != auth.password):
+ response.set_error(403, "Invalid username or password")
+ return response
+ return self.handler(request, response)
+
+basic_auth_handler = BasicAuthHandler(file_handler, None, None)
+
+class ErrorHandler(object):
+ def __init__(self, status):
+ self.status = status
+
+ def __call__(self, request, response):
+ response.set_error(self.status)
diff --git a/tests/wpt/web-platform-tests/tools/wptserve/wptserve/logger.py b/tests/wpt/web-platform-tests/tools/wptserve/wptserve/logger.py
new file mode 100644
index 00000000000..6c91492c7e9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/wptserve/wptserve/logger.py
@@ -0,0 +1,29 @@
+class NoOpLogger(object):
+ def critical(self, msg):
+ pass
+
+ def error(self, msg):
+ pass
+
+ def info(self, msg):
+ pass
+
+ def warning(self, msg):
+ pass
+
+ def debug(self, msg):
+ pass
+
+logger = NoOpLogger()
+_set_logger = False
+
+def set_logger(new_logger):
+ global _set_logger
+ if _set_logger:
+ raise Exception("Logger must be set at most once")
+ global logger
+ logger = new_logger
+ _set_logger = True
+
+def get_logger():
+ return logger
diff --git a/tests/wpt/web-platform-tests/tools/wptserve/wptserve/pipes.py b/tests/wpt/web-platform-tests/tools/wptserve/wptserve/pipes.py
new file mode 100644
index 00000000000..3f1f1e4554c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/wptserve/wptserve/pipes.py
@@ -0,0 +1,447 @@
+from cgi import escape
+import gzip as gzip_module
+import re
+import time
+import types
+import uuid
+from cStringIO import StringIO
+
+
+def resolve_content(response):
+ rv = "".join(item for item in response.iter_content())
+ if type(rv) == unicode:
+ rv = rv.encode(response.encoding)
+ return rv
+
+
+class Pipeline(object):
+ pipes = {}
+
+ def __init__(self, pipe_string):
+ self.pipe_functions = self.parse(pipe_string)
+
+ def parse(self, pipe_string):
+ functions = []
+ for item in PipeTokenizer().tokenize(pipe_string):
+ if not item:
+ break
+ if item[0] == "function":
+ functions.append((self.pipes[item[1]], []))
+ elif item[0] == "argument":
+ functions[-1][1].append(item[1])
+ return functions
+
+ def __call__(self, request, response):
+ for func, args in self.pipe_functions:
+ response = func(request, response, *args)
+ return response
+
+
+class PipeTokenizer(object):
+ def __init__(self):
+ #This whole class can likely be replaced by some regexps
+ self.state = None
+
+ def tokenize(self, string):
+ self.string = string
+ self.state = self.func_name_state
+ self._index = 0
+ while self.state:
+ yield self.state()
+ yield None
+
+ def get_char(self):
+ if self._index >= len(self.string):
+ return None
+ rv = self.string[self._index]
+ self._index += 1
+ return rv
+
+ def func_name_state(self):
+ rv = ""
+ while True:
+ char = self.get_char()
+ if char is None:
+ self.state = None
+ if rv:
+ return ("function", rv)
+ else:
+ return None
+ elif char == "(":
+ self.state = self.argument_state
+ return ("function", rv)
+ elif char == "|":
+ if rv:
+ return ("function", rv)
+ else:
+ rv += char
+
+ def argument_state(self):
+ rv = ""
+ while True:
+ char = self.get_char()
+ if char is None:
+ self.state = None
+ return ("argument", rv)
+ elif char == "\\":
+ rv += self.get_escape()
+ if rv is None:
+ #This should perhaps be an error instead
+ return ("argument", rv)
+ elif char == ",":
+ return ("argument", rv)
+ elif char == ")":
+ self.state = self.func_name_state
+ return ("argument", rv)
+ else:
+ rv += char
+
+ def get_escape(self):
+ char = self.get_char()
+ escapes = {"n": "\n",
+ "r": "\r",
+ "t": "\t"}
+ return escapes.get(char, char)
+
+
+class pipe(object):
+ def __init__(self, *arg_converters):
+ self.arg_converters = arg_converters
+ self.max_args = len(self.arg_converters)
+ self.min_args = 0
+ opt_seen = False
+ for item in self.arg_converters:
+ if not opt_seen:
+ if isinstance(item, opt):
+ opt_seen = True
+ else:
+ self.min_args += 1
+ else:
+ if not isinstance(item, opt):
+ raise ValueError("Non-optional argument cannot follow optional argument")
+
+ def __call__(self, f):
+ def inner(request, response, *args):
+ if not (self.min_args <= len(args) <= self.max_args):
+ raise ValueError("Expected between %d and %d args, got %d" %
+ (self.min_args, self.max_args, len(args)))
+ arg_values = tuple(f(x) for f, x in zip(self.arg_converters, args))
+ return f(request, response, *arg_values)
+ Pipeline.pipes[f.__name__] = inner
+ #We actually want the undecorated function in the main namespace
+ return f
+
+
+class opt(object):
+ def __init__(self, f):
+ self.f = f
+
+ def __call__(self, arg):
+ return self.f(arg)
+
+
+def nullable(func):
+ def inner(arg):
+ if arg.lower() == "null":
+ return None
+ else:
+ return func(arg)
+ return inner
+
+
+def boolean(arg):
+ if arg.lower() in ("true", "1"):
+ return True
+ elif arg.lower() in ("false", "0"):
+ return False
+ raise ValueError
+
+
+@pipe(int)
+def status(request, response, code):
+ """Alter the status code.
+
+ :param code: Status code to use for the response."""
+ response.status = code
+ return response
+
+
+@pipe(str, str, opt(boolean))
+def header(request, response, name, value, append=False):
+ """Set a HTTP header.
+
+ Replaces any existing HTTP header of the same name unless
+ append is set, in which case the header is appended without
+ replacement.
+
+ :param name: Name of the header to set.
+ :param value: Value to use for the header.
+ :param append: True if existing headers should not be replaced
+ """
+ if not append:
+ response.headers.set(name, value)
+ else:
+ response.headers.append(name, value)
+ return response
+
+
+@pipe(str)
+def trickle(request, response, delays):
+ """Send the response in parts, with time delays.
+
+ :param delays: A string of delays and amounts, in bytes, of the
+ response to send. Each component is separated by
+ a colon. Amounts in bytes are plain integers, whilst
+ delays are floats prefixed with a single d e.g.
+ d1:100:d2
+ Would cause a 1 second delay, would then send 100 bytes
+ of the file, and then cause a 2 second delay, before sending
+ the remainder of the file.
+
+ If the last token is of the form rN, instead of sending the
+ remainder of the file, the previous N instructions will be
+ repeated until the whole file has been sent e.g.
+ d1:100:d2:r2
+ Causes a delay of 1s, then 100 bytes to be sent, then a 2s delay
+ and then a further 100 bytes followed by a two second delay
+ until the response has been fully sent.
+ """
+ def parse_delays():
+ parts = delays.split(":")
+ rv = []
+ for item in parts:
+ if item.startswith("d"):
+ item_type = "delay"
+ item = item[1:]
+ value = float(item)
+ elif item.startswith("r"):
+ item_type = "repeat"
+ value = int(item[1:])
+ if not value % 2 == 0:
+ raise ValueError
+ else:
+ item_type = "bytes"
+ value = int(item)
+ if len(rv) and rv[-1][0] == item_type:
+ rv[-1][1] += value
+ else:
+ rv.append((item_type, value))
+ return rv
+
+ delays = parse_delays()
+ if not delays:
+ return response
+ content = resolve_content(response)
+ modified_content = []
+ offset = [0]
+
+ def sleep(seconds):
+ def inner():
+ time.sleep(seconds)
+ return ""
+ return inner
+
+ def add_content(delays, repeat=False):
+ for i, (item_type, value) in enumerate(delays):
+ if item_type == "bytes":
+ modified_content.append(content[offset[0]:offset[0] + value])
+ offset[0] += value
+ elif item_type == "delay":
+ modified_content.append(sleep(value))
+ elif item_type == "repeat":
+ assert i == len(delays) - 1
+ while offset[0] < len(content):
+ add_content(delays[-(value + 1):-1], True)
+
+ if not repeat and offset[0] < len(content):
+ modified_content.append(content[offset[0]:])
+
+ add_content(delays)
+
+ response.content = modified_content
+ return response
+
+
+@pipe(nullable(int), opt(nullable(int)))
+def slice(request, response, start, end=None):
+ """Send a byte range of the response body
+
+ :param start: The starting offset. Follows python semantics including
+ negative numbers.
+
+ :param end: The ending offset, again with python semantics and None
+ (spelled "null" in a query string) to indicate the end of
+ the file.
+ """
+ content = resolve_content(response)
+ response.content = content[start:end]
+ return response
+
+
+class ReplacementTokenizer(object):
+ def ident(scanner, token):
+ return ("ident", token)
+
+ def index(scanner, token):
+ token = token[1:-1]
+ try:
+ token = int(token)
+ except ValueError:
+ token = unicode(token, "utf8")
+ return ("index", token)
+
+ def var(scanner, token):
+ token = token[:-1]
+ return ("var", token)
+
+ def tokenize(self, string):
+ return self.scanner.scan(string)[0]
+
+ scanner = re.Scanner([(r"\$\w+:", var),
+ (r"\$?\w+(?:\(\))?", ident),
+ (r"\[[^\]]*\]", index)])
+
+
+class FirstWrapper(object):
+ def __init__(self, params):
+ self.params = params
+
+ def __getitem__(self, key):
+ try:
+ return self.params.first(key)
+ except KeyError:
+ return ""
+
+
+@pipe()
+def sub(request, response):
+ """Substitute environment information about the server and request into the script.
+
+ The format is a very limited template language. Substitutions are
+ enclosed by {{ and }}. There are several avaliable substitutions:
+
+ host
+ A simple string value and represents the primary host from which the
+ tests are being run.
+ domains
+ A dictionary of available domains indexed by subdomain name.
+ ports
+ A dictionary of lists of ports indexed by protocol.
+ location
+ A dictionary of parts of the request URL. Valid keys are
+ 'server, 'scheme', 'host', 'hostname', 'port', 'path' and 'query'.
+ 'server' is scheme://host:port, 'host' is hostname:port, and query
+ includes the leading '?', but other delimiters are omitted.
+ headers
+ A dictionary of HTTP headers in the request.
+ GET
+ A dictionary of query parameters supplied with the request.
+ uuid()
+ A pesudo-random UUID suitable for usage with stash
+
+ So for example in a setup running on localhost with a www
+ subdomain and a http server on ports 80 and 81::
+
+ {{host}} => localhost
+ {{domains[www]}} => www.localhost
+ {{ports[http][1]}} => 81
+
+
+ It is also possible to assign a value to a variable name, which must start with
+ the $ character, using the ":" syntax e.g.
+
+ {{$id:uuid()}
+
+ Later substitutions in the same file may then refer to the variable
+ by name e.g.
+
+ {{$id}}
+ """
+ content = resolve_content(response)
+
+ new_content = template(request, content)
+
+ response.content = new_content
+ return response
+
+def template(request, content):
+ #TODO: There basically isn't any error handling here
+ tokenizer = ReplacementTokenizer()
+
+ variables = {}
+
+ def config_replacement(match):
+ content, = match.groups()
+
+ tokens = tokenizer.tokenize(content)
+
+ if tokens[0][0] == "var":
+ variable = tokens[0][1]
+ tokens = tokens[1:]
+ else:
+ variable = None
+
+ assert tokens[0][0] == "ident" and all(item[0] == "index" for item in tokens[1:]), tokens
+
+ field = tokens[0][1]
+
+ if field in variables:
+ value = variables[field]
+ elif field == "headers":
+ value = request.headers
+ elif field == "GET":
+ value = FirstWrapper(request.GET)
+ elif field in request.server.config:
+ value = request.server.config[tokens[0][1]]
+ elif field == "location":
+ value = {"server": "%s://%s:%s" % (request.url_parts.scheme,
+ request.url_parts.hostname,
+ request.url_parts.port),
+ "scheme": request.url_parts.scheme,
+ "host": "%s:%s" % (request.url_parts.hostname,
+ request.url_parts.port),
+ "hostname": request.url_parts.hostname,
+ "port": request.url_parts.port,
+ "path": request.url_parts.path,
+ "query": "?%s" % request.url_parts.query}
+ elif field == "uuid()":
+ value = str(uuid.uuid4())
+ else:
+ raise Exception("Undefined template variable %s" % field)
+
+ for item in tokens[1:]:
+ value = value[item[1]]
+
+ assert isinstance(value, (int,) + types.StringTypes), tokens
+
+ if variable is not None:
+ variables[variable] = value
+
+ #Should possibly support escaping for other contexts e.g. script
+ #TODO: read the encoding of the response
+ return escape(unicode(value)).encode("utf-8")
+
+ template_regexp = re.compile(r"{{([^}]*)}}")
+ new_content, count = template_regexp.subn(config_replacement, content)
+
+ return new_content
+
+@pipe()
+def gzip(request, response):
+ """This pipe gzip-encodes response data.
+
+ It sets (or overwrites) these HTTP headers:
+ Content-Encoding is set to gzip
+ Content-Length is set to the length of the compressed content
+ """
+ content = resolve_content(response)
+ response.headers.set("Content-Encoding", "gzip")
+
+ out = StringIO()
+ with gzip_module.GzipFile(fileobj=out, mode="w") as f:
+ f.write(content)
+ response.content = out.getvalue()
+
+ response.headers.set("Content-Length", len(response.content))
+
+ return response
diff --git a/tests/wpt/web-platform-tests/tools/wptserve/wptserve/ranges.py b/tests/wpt/web-platform-tests/tools/wptserve/wptserve/ranges.py
new file mode 100644
index 00000000000..12935fd91b1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/wptserve/wptserve/ranges.py
@@ -0,0 +1,90 @@
+from utils import HTTPException
+
+
+class RangeParser(object):
+ def __call__(self, header, file_size):
+ prefix = "bytes="
+ if not header.startswith(prefix):
+ raise HTTPException(416, message="Unrecognised range type %s" % (header,))
+
+ parts = header[len(prefix):].split(",")
+ ranges = []
+ for item in parts:
+ components = item.split("-")
+ if len(components) != 2:
+ raise HTTPException(416, "Bad range specifier %s" % (item))
+ data = []
+ for component in components:
+ if component == "":
+ data.append(None)
+ else:
+ try:
+ data.append(int(component))
+ except ValueError:
+ raise HTTPException(416, "Bad range specifier %s" % (item))
+ try:
+ ranges.append(Range(data[0], data[1], file_size))
+ except ValueError:
+ raise HTTPException(416, "Bad range specifier %s" % (item))
+
+ return self.coalesce_ranges(ranges, file_size)
+
+ def coalesce_ranges(self, ranges, file_size):
+ rv = []
+ target = None
+ for current in reversed(sorted(ranges)):
+ if target is None:
+ target = current
+ else:
+ new = target.coalesce(current)
+ target = new[0]
+ if len(new) > 1:
+ rv.append(new[1])
+ rv.append(target)
+
+ return rv[::-1]
+
+
+class Range(object):
+ def __init__(self, lower, upper, file_size):
+ self.file_size = file_size
+ self.lower, self.upper = self._abs(lower, upper)
+ if self.lower >= self.upper or self.lower >= self.file_size:
+ raise ValueError
+
+ def __repr__(self):
+ return "<Range %s-%s>" % (self.lower, self.upper)
+
+ def __lt__(self, other):
+ return self.lower < other.lower
+
+ def __gt__(self, other):
+ return self.lower > other.lower
+
+ def __eq__(self, other):
+ return self.lower == other.lower and self.upper == other.upper
+
+ def _abs(self, lower, upper):
+ if lower is None and upper is None:
+ lower, upper = 0, self.file_size
+ elif lower is None:
+ lower, upper = max(0, self.file_size - upper), self.file_size
+ elif upper is None:
+ lower, upper = lower, self.file_size
+ else:
+ lower, upper = lower, min(self.file_size, upper + 1)
+
+ return lower, upper
+
+ def coalesce(self, other):
+ assert self.file_size == other.file_size
+
+ if (self.upper < other.lower or self.lower > other.upper):
+ return sorted([self, other])
+ else:
+ return [Range(min(self.lower, other.lower),
+ max(self.upper, other.upper) - 1,
+ self.file_size)]
+
+ def header_value(self):
+ return "bytes %i-%i/%i" % (self.lower, self.upper - 1, self.file_size)
diff --git a/tests/wpt/web-platform-tests/tools/wptserve/wptserve/request.py b/tests/wpt/web-platform-tests/tools/wptserve/wptserve/request.py
new file mode 100644
index 00000000000..1cc2a3d14f9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/wptserve/wptserve/request.py
@@ -0,0 +1,576 @@
+import base64
+import cgi
+import Cookie
+import StringIO
+import tempfile
+import urlparse
+
+import stash
+from utils import HTTPException
+
+missing = object()
+
+
+class Server(object):
+ """Data about the server environment
+
+ .. attribute:: config
+
+ Environment configuration information with information about the
+ various servers running, their hostnames and ports.
+
+ .. attribute:: stash
+
+ Stash object holding state stored on the server between requests.
+
+ """
+ config = None
+
+ def __init__(self, request):
+ self.stash = stash.Stash(request.url_parts.path)
+
+
+class InputFile(object):
+ max_buffer_size = 1024*1024
+
+ def __init__(self, rfile, length):
+ """File-like object used to provide a seekable view of request body data"""
+ self._file = rfile
+ self.length = length
+
+ self._file_position = 0
+
+ if length > self.max_buffer_size:
+ self._buf = tempfile.TemporaryFile(mode="rw+b")
+ else:
+ self._buf = StringIO.StringIO()
+
+ @property
+ def _buf_position(self):
+ rv = self._buf.tell()
+ assert rv <= self._file_position
+ return rv
+
+ def read(self, bytes=-1):
+ assert self._buf_position <= self._file_position
+
+ if bytes < 0:
+ bytes = self.length - self._buf_position
+ bytes_remaining = min(bytes, self.length - self._buf_position)
+
+ if bytes_remaining == 0:
+ return ""
+
+ if self._buf_position != self._file_position:
+ buf_bytes = min(bytes_remaining, self._file_position - self._buf_position)
+ old_data = self._buf.read(buf_bytes)
+ bytes_remaining -= buf_bytes
+ else:
+ old_data = ""
+
+ assert self._buf_position == self._file_position, (
+ "Before reading buffer position (%i) didn't match file position (%i)" %
+ (self._buf_position, self._file_position))
+ new_data = self._file.read(bytes_remaining)
+ self._buf.write(new_data)
+ self._file_position += bytes_remaining
+ assert self._buf_position == self._file_position, (
+ "After reading buffer position (%i) didn't match file position (%i)" %
+ (self._buf_position, self._file_position))
+
+ return old_data + new_data
+
+ def tell(self):
+ return self._buf_position
+
+ def seek(self, offset):
+ if offset > self.length or offset < 0:
+ raise ValueError
+ if offset <= self._file_position:
+ self._buf.seek(offset)
+ else:
+ self.read(offset - self._file_position)
+
+ def readline(self, max_bytes=None):
+ if max_bytes is None:
+ max_bytes = self.length - self._buf_position
+
+ if self._buf_position < self._file_position:
+ data = self._buf.readline(max_bytes)
+ if data.endswith("\n") or len(data) == max_bytes:
+ return data
+ else:
+ data = ""
+
+ assert self._buf_position == self._file_position
+
+ initial_position = self._file_position
+ found = False
+ buf = []
+ max_bytes -= len(data)
+ while not found:
+ readahead = self.read(min(2, max_bytes))
+ max_bytes -= len(readahead)
+ for i, c in enumerate(readahead):
+ if c == "\n":
+ buf.append(readahead[:i+1])
+ found = True
+ break
+ if not found:
+ buf.append(readahead)
+ if not readahead or not max_bytes:
+ break
+ new_data = "".join(buf)
+ data += new_data
+ self.seek(initial_position + len(new_data))
+ return data
+
+ def readlines(self):
+ rv = []
+ while True:
+ data = self.readline()
+ if data:
+ rv.append(data)
+ else:
+ break
+ return rv
+
+ def next(self):
+ data = self.readline()
+ if data:
+ return data
+ else:
+ raise StopIteration
+
+ def __iter__(self):
+ return self
+
+
+class Request(object):
+ """Object representing a HTTP request.
+
+ .. attribute:: doc_root
+
+ The local directory to use as a base when resolving paths
+
+ .. attribute:: route_match
+
+ Regexp match object from matching the request path to the route
+ selected for the request.
+
+ .. attribute:: protocol_version
+
+ HTTP version specified in the request.
+
+ .. attribute:: method
+
+ HTTP method in the request.
+
+ .. attribute:: request_path
+
+ Request path as it appears in the HTTP request.
+
+ .. attribute:: url
+
+ Absolute URL for the request.
+
+ .. attribute:: headers
+
+ List of request headers.
+
+ .. attribute:: raw_input
+
+ File-like object representing the body of the request.
+
+ .. attribute:: url_parts
+
+ Parts of the requested URL as obtained by urlparse.urlsplit(path)
+
+ .. attribute:: request_line
+
+ Raw request line
+
+ .. attribute:: headers
+
+ RequestHeaders object providing a dictionary-like representation of
+ the request headers.
+
+ .. attribute:: body
+
+ Request body as a string
+
+ .. attribute:: GET
+
+ MultiDict representing the parameters supplied with the request.
+ Note that these may be present on non-GET requests; the name is
+ chosen to be familiar to users of other systems such as PHP.
+
+ .. attribute:: POST
+
+ MultiDict representing the request body parameters. Most parameters
+ are present as string values, but file uploads have file-like
+ values.
+
+ .. attribute:: cookies
+
+ Cookies object representing cookies sent with the request with a
+ dictionary-like interface.
+
+ .. attribute:: auth
+
+ Object with username and password properties representing any
+ credentials supplied using HTTP authentication.
+
+ .. attribute:: server
+
+ Server object containing information about the server environment.
+ """
+
+ def __init__(self, request_handler):
+ self.doc_root = request_handler.server.router.doc_root
+ self.route_match = None # Set by the router
+
+ self.protocol_version = request_handler.protocol_version
+ self.method = request_handler.command
+
+ scheme = request_handler.server.scheme
+ host = request_handler.headers.get("Host")
+ port = request_handler.server.server_address[1]
+
+ if host is None:
+ host = request_handler.server.server_address[0]
+ else:
+ if ":" in host:
+ host, port = host.split(":", 1)
+
+ self.request_path = request_handler.path
+
+ if self.request_path.startswith(scheme + "://"):
+ self.url = request_handler.path
+ else:
+ self.url = "%s://%s:%s%s" % (scheme,
+ host,
+ port,
+ self.request_path)
+ self.url_parts = urlparse.urlsplit(self.url)
+
+ self._raw_headers = request_handler.headers
+
+ self.request_line = request_handler.raw_requestline
+
+ self._headers = None
+
+ self.raw_input = InputFile(request_handler.rfile,
+ int(self.headers.get("Content-Length", 0)))
+ self._body = None
+
+ self._GET = None
+ self._POST = None
+ self._cookies = None
+ self._auth = None
+
+ self.server = Server(self)
+
+ def __repr__(self):
+ return "<Request %s %s>" % (self.method, self.url)
+
+ @property
+ def GET(self):
+ if self._GET is None:
+ params = urlparse.parse_qsl(self.url_parts.query, keep_blank_values=True)
+ self._GET = MultiDict()
+ for key, value in params:
+ self._GET.add(key, value)
+ return self._GET
+
+ @property
+ def POST(self):
+ if self._POST is None:
+ #Work out the post parameters
+ pos = self.raw_input.tell()
+ self.raw_input.seek(0)
+ fs = cgi.FieldStorage(fp=self.raw_input,
+ environ={"REQUEST_METHOD": self.method},
+ headers=self.headers,
+ keep_blank_values=True)
+ self._POST = MultiDict.from_field_storage(fs)
+ self.raw_input.seek(pos)
+ return self._POST
+
+ @property
+ def cookies(self):
+ if self._cookies is None:
+ parser = Cookie.BaseCookie()
+ cookie_headers = self.headers.get("cookie", "")
+ parser.load(cookie_headers)
+ cookies = Cookies()
+ for key, value in parser.iteritems():
+ cookies[key] = CookieValue(value)
+ self._cookies = cookies
+ return self._cookies
+
+ @property
+ def headers(self):
+ if self._headers is None:
+ self._headers = RequestHeaders(self._raw_headers)
+ return self._headers
+
+ @property
+ def body(self):
+ if self._body is None:
+ pos = self.raw_input.tell()
+ self.raw_input.seek(0)
+ self._body = self.raw_input.read()
+ self.raw_input.seek(pos)
+ return self._body
+
+ @property
+ def auth(self):
+ if self._auth is None:
+ self._auth = Authentication(self.headers)
+ return self._auth
+
+
+class RequestHeaders(dict):
+ """Dictionary-like API for accessing request headers."""
+ def __init__(self, items):
+ for key, value in zip(items.keys(), items.values()):
+ key = key.lower()
+ if key in self:
+ self[key].append(value)
+ else:
+ dict.__setitem__(self, key, [value])
+
+ def __getitem__(self, key):
+ """Get all headers of a certain (case-insensitive) name. If there is
+ more than one, the values are returned comma separated"""
+ values = dict.__getitem__(self, key.lower())
+ if len(values) == 1:
+ return values[0]
+ else:
+ return ", ".join(values)
+
+ def __setitem__(self, name, value):
+ raise Exception
+
+ def get(self, key, default=None):
+ """Get a string representing all headers with a particular value,
+ with multiple headers separated by a comma. If no header is found
+ return a default value
+
+ :param key: The header name to look up (case-insensitive)
+ :param default: The value to return in the case of no match
+ """
+ try:
+ return self[key]
+ except KeyError:
+ return default
+
+ def get_list(self, key, default=missing):
+ """Get all the header values for a particular field name as
+ a list"""
+ try:
+ return dict.__getitem__(self, key.lower())
+ except KeyError:
+ if default is not missing:
+ return default
+ else:
+ raise
+
+ def __contains__(self, key):
+ return dict.__contains__(self, key.lower())
+
+ def iteritems(self):
+ for item in self:
+ yield item, self[item]
+
+ def itervalues(self):
+ for item in self:
+ yield self[item]
+
+class CookieValue(object):
+ """Representation of cookies.
+
+ Note that cookies are considered read-only and the string value
+ of the cookie will not change if you update the field values.
+ However this is not enforced.
+
+ .. attribute:: key
+
+ The name of the cookie.
+
+ .. attribute:: value
+
+ The value of the cookie
+
+ .. attribute:: expires
+
+ The expiry date of the cookie
+
+ .. attribute:: path
+
+ The path of the cookie
+
+ .. attribute:: comment
+
+ The comment of the cookie.
+
+ .. attribute:: domain
+
+ The domain with which the cookie is associated
+
+ .. attribute:: max_age
+
+ The max-age value of the cookie.
+
+ .. attribute:: secure
+
+ Whether the cookie is marked as secure
+
+ .. attribute:: httponly
+
+ Whether the cookie is marked as httponly
+
+ """
+ def __init__(self, morsel):
+ self.key = morsel.key
+ self.value = morsel.value
+
+ for attr in ["expires", "path",
+ "comment", "domain", "max-age",
+ "secure", "version", "httponly"]:
+ setattr(self, attr.replace("-", "_"), morsel[attr])
+
+ self._str = morsel.OutputString()
+
+ def __str__(self):
+ return self._str
+
+ def __repr__(self):
+ return self._str
+
+ def __eq__(self, other):
+ """Equality comparison for cookies. Compares to other cookies
+ based on value alone and on non-cookies based on the equality
+ of self.value with the other object so that a cookie with value
+ "ham" compares equal to the string "ham"
+ """
+ if hasattr(other, "value"):
+ return self.value == other.value
+ return self.value == other
+
+
+class MultiDict(dict):
+ """Dictionary type that holds multiple values for each
+ key"""
+ #TODO: this should perhaps also order the keys
+ def __init__(self):
+ pass
+
+ def __setitem__(self, name, value):
+ dict.__setitem__(self, name, [value])
+
+ def add(self, name, value):
+ if name in self:
+ dict.__getitem__(self, name).append(value)
+ else:
+ dict.__setitem__(self, name, [value])
+
+ def __getitem__(self, key):
+ """Get the first value with a given key"""
+ #TODO: should this instead be the last value?
+ return self.first(key)
+
+ def first(self, key, default=missing):
+ """Get the first value with a given key
+
+ :param key: The key to lookup
+ :param default: The default to return if key is
+ not found (throws if nothing is
+ specified)
+ """
+ if key in self and dict.__getitem__(self, key):
+ return dict.__getitem__(self, key)[0]
+ elif default is not missing:
+ return default
+ raise KeyError
+
+ def last(self, key, default=missing):
+ """Get the last value with a given key
+
+ :param key: The key to lookup
+ :param default: The default to return if key is
+ not found (throws if nothing is
+ specified)
+ """
+ if key in self and dict.__getitem__(self, key):
+ return dict.__getitem__(self, key)[-1]
+ elif default is not missing:
+ return default
+ raise KeyError
+
+ def get_list(self, key):
+ """Get all values with a given key as a list
+
+ :param key: The key to lookup
+ """
+ return dict.__getitem__(self, key)
+
+ @classmethod
+ def from_field_storage(cls, fs):
+ self = cls()
+ if fs.list is None:
+ return self
+ for key in fs:
+ values = fs[key]
+ if not isinstance(values, list):
+ values = [values]
+
+ for value in values:
+ if value.filename:
+ value = value
+ else:
+ value = value.value
+ self.add(key, value)
+ return self
+
+
+class Cookies(MultiDict):
+ """MultiDict specialised for Cookie values"""
+ def __init__(self):
+ pass
+
+ def __getitem__(self, key):
+ return self.last(key)
+
+
+class Authentication(object):
+ """Object for dealing with HTTP Authentication
+
+ .. attribute:: username
+
+ The username supplied in the HTTP Authorization
+ header, or None
+
+ .. attribute:: password
+
+ The password supplied in the HTTP Authorization
+ header, or None
+ """
+ def __init__(self, headers):
+ self.username = None
+ self.password = None
+
+ auth_schemes = {"Basic": self.decode_basic}
+
+ if "authorization" in headers:
+ header = headers.get("authorization")
+ auth_type, data = header.split(" ", 1)
+ if auth_type in auth_schemes:
+ self.username, self.password = auth_schemes[auth_type](data)
+ else:
+ raise HTTPException(400, "Unsupported authentication scheme %s" % auth_type)
+
+ def decode_basic(self, data):
+ decoded_data = base64.decodestring(data)
+ return decoded_data.split(":", 1)
diff --git a/tests/wpt/web-platform-tests/tools/wptserve/wptserve/response.py b/tests/wpt/web-platform-tests/tools/wptserve/wptserve/response.py
new file mode 100644
index 00000000000..52bc79c56c5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/wptserve/wptserve/response.py
@@ -0,0 +1,443 @@
+from collections import OrderedDict
+from datetime import datetime, timedelta
+import Cookie
+import json
+import types
+import uuid
+import socket
+
+from constants import response_codes
+from logger import get_logger
+
+missing = object()
+
+class Response(object):
+ """Object representing the response to a HTTP request
+
+ :param handler: RequestHandler being used for this response
+ :param request: Request that this is the response for
+
+ .. attribute:: request
+
+ Request associated with this Response.
+
+ .. attribute:: encoding
+
+ The encoding to use when converting unicode to strings for output.
+
+ .. attribute:: add_required_headers
+
+ Boolean indicating whether mandatory headers should be added to the
+ response.
+
+ .. attribute:: send_body_for_head_request
+
+ Boolean, default False, indicating whether the body content should be
+ sent when the request method is HEAD.
+
+ .. attribute:: explicit_flush
+
+ Boolean indicating whether output should be flushed automatically or only
+ when requested.
+
+ .. attribute:: writer
+
+ The ResponseWriter for this response
+
+ .. attribute:: status
+
+ Status tuple (code, message). Can be set to an integer, in which case the
+ message part is filled in automatically, or a tuple.
+
+ .. attribute:: headers
+
+ List of HTTP headers to send with the response. Each item in the list is a
+ tuple of (name, value).
+
+ .. attribute:: content
+
+ The body of the response. This can either be a string or a iterable of response
+ parts. If it is an iterable, any item may be a string or a function of zero
+ parameters which, when called, returns a string."""
+
+ def __init__(self, handler, request):
+ self.request = request
+ self.encoding = "utf8"
+
+ self.add_required_headers = True
+ self.send_body_for_head_request = False
+ self.explicit_flush = False
+ self.close_connection = False
+
+ self.writer = ResponseWriter(handler, self)
+
+ self._status = (200, None)
+ self.headers = ResponseHeaders()
+ self.content = []
+
+ self.logger = get_logger()
+
+ @property
+ def status(self):
+ return self._status
+
+ @status.setter
+ def status(self, value):
+ if hasattr(value, "__len__"):
+ if len(value) != 2:
+ raise ValueError
+ else:
+ self._status = (int(value[0]), str(value[1]))
+ else:
+ self._status = (int(value), None)
+
+ def set_cookie(self, name, value, path="/", domain=None, max_age=None,
+ expires=None, secure=False, httponly=False, comment=None):
+ """Set a cookie to be sent with a Set-Cookie header in the
+ response
+
+ :param name: String name of the cookie
+ :param value: String value of the cookie
+ :param max_age: datetime.timedelta int representing the time (in seconds)
+ until the cookie expires
+ :param path: String path to which the cookie applies
+ :param domain: String domain to which the cookie applies
+ :param secure: Boolean indicating whether the cookie is marked as secure
+ :param httponly: Boolean indicating whether the cookie is marked as
+ HTTP Only
+ :param comment: String comment
+ :param expires: datetime.datetime or datetime.timedelta indicating a
+ time or interval from now when the cookie expires
+
+ """
+ days = dict((i+1, name) for i, name in enumerate(["jan", "feb", "mar",
+ "apr", "may", "jun",
+ "jul", "aug", "sep",
+ "oct", "nov", "dec"]))
+ if value is None:
+ value = ''
+ max_age = 0
+ expires = timedelta(days=-1)
+
+ if isinstance(expires, timedelta):
+ expires = datetime.utcnow() + expires
+
+ if expires is not None:
+ expires_str = expires.strftime("%d %%s %Y %H:%M:%S GMT")
+ expires_str = expires_str % days[expires.month]
+ expires = expires_str
+
+ if max_age is not None:
+ if hasattr(max_age, "total_seconds"):
+ max_age = int(max_age.total_seconds())
+ max_age = "%.0d" % max_age
+
+ m = Cookie.Morsel()
+
+ def maybe_set(key, value):
+ if value is not None and value is not False:
+ m[key] = value
+
+ m.set(name, value, value)
+ maybe_set("path", path)
+ maybe_set("domain", domain)
+ maybe_set("comment", comment)
+ maybe_set("expires", expires)
+ maybe_set("max-age", max_age)
+ maybe_set("secure", secure)
+ maybe_set("httponly", httponly)
+
+ self.headers.append("Set-Cookie", m.OutputString())
+
+ def unset_cookie(self, name):
+ """Remove a cookie from those that are being sent with the response"""
+ cookies = self.headers.get("Set-Cookie")
+ parser = Cookie.BaseCookie()
+ for cookie in cookies:
+ parser.load(cookie)
+
+ if name in parser.keys():
+ del self.headers["Set-Cookie"]
+ for m in parser.values():
+ if m.key != name:
+ self.headers.append(("Set-Cookie", m.OutputString()))
+
+ def delete_cookie(self, name, path="/", domain=None):
+ """Delete a cookie on the client by setting it to the empty string
+ and to expire in the past"""
+ self.set_cookie(name, None, path=path, domain=domain, max_age=0,
+ expires=timedelta(days=-1))
+
+ def iter_content(self):
+ """Iterator returning chunks of response body content.
+
+ If any part of the content is a function, this will be called
+ and the resulting value (if any) returned."""
+ if type(self.content) in types.StringTypes:
+ yield self.content
+ else:
+ for item in self.content:
+ if hasattr(item, "__call__"):
+ value = item()
+ else:
+ value = item
+ if value:
+ yield value
+
+ def write_status_headers(self):
+ """Write out the status line and headers for the response"""
+ self.writer.write_status(*self.status)
+ for item in self.headers:
+ self.writer.write_header(*item)
+ self.writer.end_headers()
+
+ def write_content(self):
+ """Write out the response content"""
+ if self.request.method != "HEAD" or self.send_body_for_head_request:
+ for item in self.iter_content():
+ self.writer.write_content(item)
+
+ def write(self):
+ """Write the whole response"""
+ self.write_status_headers()
+ self.write_content()
+
+ def set_error(self, code, message=""):
+ """Set the response status headers and body to indicate an
+ error"""
+ err = {"code": code,
+ "message": message}
+ data = json.dumps({"error": err})
+ self.status = code
+ self.headers = [("Content-Type", "text/json"),
+ ("Content-Length", len(data))]
+ self.content = data
+ if code == 500:
+ self.logger.error(message)
+
+
+class MultipartContent(object):
+ def __init__(self, boundary=None, default_content_type=None):
+ self.items = []
+ if boundary is None:
+ boundary = str(uuid.uuid4())
+ self.boundary = boundary
+ self.default_content_type = default_content_type
+
+ def __call__(self):
+ boundary = "--" + self.boundary
+ rv = ["", boundary]
+ for item in self.items:
+ rv.append(str(item))
+ rv.append(boundary)
+ rv[-1] += "--"
+ return "\r\n".join(rv)
+
+ def append_part(self, data, content_type=None, headers=None):
+ if content_type is None:
+ content_type = self.default_content_type
+ self.items.append(MultipartPart(data, content_type, headers))
+
+ def __iter__(self):
+ #This is hackish; when writing the response we need an iterable
+ #or a string. For a multipart/byterange response we want an
+ #iterable that contains a single callable; the MultipartContent
+ #object itself
+ yield self
+
+
+class MultipartPart(object):
+ def __init__(self, data, content_type=None, headers=None):
+ self.headers = ResponseHeaders()
+
+ if content_type is not None:
+ self.headers.set("Content-Type", content_type)
+
+ if headers is not None:
+ for name, value in headers:
+ if name.lower() == "content-type":
+ func = self.headers.set
+ else:
+ func = self.headers.append
+ func(name, value)
+
+ self.data = data
+
+ def __str__(self):
+ rv = []
+ for item in self.headers:
+ rv.append("%s: %s" % item)
+ rv.append("")
+ rv.append(self.data)
+ return "\r\n".join(rv)
+
+
+class ResponseHeaders(object):
+ """Dictionary-like object holding the headers for the response"""
+ def __init__(self):
+ self.data = OrderedDict()
+
+ def set(self, key, value):
+ """Set a header to a specific value, overwriting any previous header
+ with the same name
+
+ :param key: Name of the header to set
+ :param value: Value to set the header to
+ """
+ self.data[key.lower()] = (key, [value])
+
+ def append(self, key, value):
+ """Add a new header with a given name, not overwriting any existing
+ headers with the same name
+
+ :param key: Name of the header to add
+ :param value: Value to set for the header
+ """
+ if key.lower() in self.data:
+ self.data[key.lower()][1].append(value)
+ else:
+ self.set(key, value)
+
+ def get(self, key, default=missing):
+ """Get the set values for a particular header."""
+ try:
+ return self[key]
+ except KeyError:
+ if default is missing:
+ return []
+ return default
+
+ def __getitem__(self, key):
+ """Get a list of values for a particular header
+
+ """
+ return self.data[key.lower()][1]
+
+ def __delitem__(self, key):
+ del self.data[key.lower()]
+
+ def __contains__(self, key):
+ return key.lower() in self.data
+
+ def __setitem__(self, key, value):
+ self.set(key, value)
+
+ def __iter__(self):
+ for key, values in self.data.itervalues():
+ for value in values:
+ yield key, value
+
+ def items(self):
+ return list(self)
+
+ def update(self, items_iter):
+ for name, value in items_iter:
+ self.set(name, value)
+
+ def __repr__(self):
+ return repr(self.data)
+
+
+class ResponseWriter(object):
+ """Object providing an API to write out a HTTP response.
+
+ :param handler: The RequestHandler being used.
+ :param response: The Response associated with this writer.
+
+ After each part of the response is written, the output is
+ flushed unless response.explicit_flush is False, in which case
+ the user must call .flush() explicitly."""
+ def __init__(self, handler, response):
+ self._wfile = handler.wfile
+ self._response = response
+ self._handler = handler
+ self._headers_seen = set()
+ self._headers_complete = False
+ self.content_written = False
+ self.request = response.request
+
+ def write_status(self, code, message=None):
+ """Write out the status line of a response.
+
+ :param code: The integer status code of the response.
+ :param message: The message of the response. Defaults to the message commonly used
+ with the status code."""
+ if message is None:
+ if code in response_codes:
+ message = response_codes[code][0]
+ else:
+ message = ''
+ self.write("%s %d %s\r\n" %
+ (self._response.request.protocol_version, code, message))
+
+ def write_header(self, name, value):
+ """Write out a single header for the response.
+
+ :param name: Name of the header field
+ :param value: Value of the header field
+ """
+ self._headers_seen.add(name.lower())
+ self.write("%s: %s\r\n" % (name, value))
+ if not self._response.explicit_flush:
+ self.flush()
+
+ def write_default_headers(self):
+ for name, f in [("Server", self._handler.version_string),
+ ("Date", self._handler.date_time_string)]:
+ if name.lower() not in self._headers_seen:
+ self.write_header(name, f())
+
+ if (type(self._response.content) in (str, unicode) and
+ "content-length" not in self._headers_seen):
+ #Would be nice to avoid double-encoding here
+ self.write_header("Content-Length", len(self.encode(self._response.content)))
+
+ def end_headers(self):
+ """Finish writing headers and write the separator.
+
+ Unless add_required_headers on the response is False,
+ this will also add HTTP-mandated headers that have not yet been supplied
+ to the response headers"""
+
+ if self._response.add_required_headers:
+ self.write_default_headers()
+
+ self.write("\r\n")
+ if "content-length" not in self._headers_seen:
+ self._response.close_connection = True
+ if not self._response.explicit_flush:
+ self.flush()
+ self._headers_complete = True
+
+ def write_content(self, data):
+ """Write the body of the response."""
+ self.write(self.encode(data))
+ if not self._response.explicit_flush:
+ self.flush()
+
+ def write(self, data):
+ """Write directly to the response, converting unicode to bytes
+ according to response.encoding. Does not flush."""
+ self.content_written = True
+ try:
+ self._wfile.write(self.encode(data))
+ except socket.error:
+ # This can happen if the socket got closed by the remote end
+ pass
+
+ def encode(self, data):
+ """Convert unicode to bytes according to response.encoding."""
+ if isinstance(data, str):
+ return data
+ elif isinstance(data, unicode):
+ return data.encode(self._response.encoding)
+ else:
+ raise ValueError
+
+ def flush(self):
+ """Flush the output."""
+ try:
+ self._wfile.flush()
+ except socket.error:
+ # This can happen if the socket got closed by the remote end
+ pass
diff --git a/tests/wpt/web-platform-tests/tools/wptserve/wptserve/router.py b/tests/wpt/web-platform-tests/tools/wptserve/wptserve/router.py
new file mode 100644
index 00000000000..3c8c87f4792
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/wptserve/wptserve/router.py
@@ -0,0 +1,168 @@
+import itertools
+import re
+import types
+
+from logger import get_logger
+
+any_method = object()
+
+class RouteTokenizer(object):
+ def literal(self, scanner, token):
+ return ("literal", token)
+
+ def slash(self, scanner, token):
+ return ("slash", None)
+
+ def group(self, scanner, token):
+ return ("group", token[1:-1])
+
+ def star(self, scanner, token):
+ return ("star", token[1:-3])
+
+ def scan(self, input_str):
+ scanner = re.Scanner([(r"/", self.slash),
+ (r"{\w*}", self.group),
+ (r"\*", self.star),
+ (r"(?:\\.|[^{\*/])*", self.literal),])
+ return scanner.scan(input_str)
+
+class RouteCompiler(object):
+ def __init__(self):
+ self.reset()
+
+ def reset(self):
+ self.star_seen = False
+
+ def compile(self, tokens):
+ self.reset()
+
+ func_map = {"slash":self.process_slash,
+ "literal":self.process_literal,
+ "group":self.process_group,
+ "star":self.process_star}
+
+ re_parts = ["^"]
+
+ if not tokens or tokens[0][0] != "slash":
+ tokens = itertools.chain([("slash", None)], tokens)
+
+ for token in tokens:
+ re_parts.append(func_map[token[0]](token))
+
+ if self.star_seen:
+ re_parts.append(")")
+ re_parts.append("$")
+
+ return re.compile("".join(re_parts))
+
+ def process_literal(self, token):
+ return re.escape(token[1])
+
+ def process_slash(self, token):
+ return "/"
+
+ def process_group(self, token):
+ if self.star_seen:
+ raise ValueError("Group seen after star in regexp")
+ return "(?P<%s>[^/]+)" % token[1]
+
+ def process_star(self, token):
+ if self.star_seen:
+ raise ValueError("Star seen after star in regexp")
+ self.star_seen = True
+ return "(.*"
+
+def compile_path_match(route_pattern):
+ """tokens: / or literal or match or *"""
+
+ tokenizer = RouteTokenizer()
+ tokens, unmatched = tokenizer.scan(route_pattern)
+
+ assert unmatched is "", unmatched
+
+ compiler = RouteCompiler()
+
+ return compiler.compile(tokens)
+
+class Router(object):
+ """Object for matching handler functions to requests.
+
+ :param doc_root: Absolute path of the filesystem location from
+ which to serve tests
+ :param routes: Initial routes to add; a list of three item tuples
+ (method, path_pattern, handler_function), defined
+ as for register()
+ """
+
+ def __init__(self, doc_root, routes):
+ self.doc_root = doc_root
+ self.routes = []
+ self.logger = get_logger()
+ for route in reversed(routes):
+ self.register(*route)
+
+ def register(self, methods, path, handler):
+ """Register a handler for a set of paths.
+
+ :param methods: Set of methods this should match. "*" is a
+ special value indicating that all methods should
+ be matched.
+
+ :param path_pattern: Match pattern that will be used to determine if
+ a request path matches this route. Match patterns
+ consist of either literal text, match groups,
+ denoted {name}, which match any character except /,
+ and, at most one \*, which matches and character and
+ creates a match group to the end of the string.
+ If there is no leading "/" on the pattern, this is
+ automatically implied. For example::
+
+ api/{resource}/*.json
+
+ Would match `/api/test/data.json` or
+ `/api/test/test2/data.json`, but not `/api/test/data.py`.
+
+ The match groups are made available in the request object
+ as a dictionary through the route_match property. For
+ example, given the route pattern above and the path
+ `/api/test/data.json`, the route_match property would
+ contain::
+
+ {"resource": "test", "*": "data.json"}
+
+ :param handler: Function that will be called to process matching
+ requests. This must take two parameters, the request
+ object and the response object.
+
+ """
+ if type(methods) in types.StringTypes or methods in (any_method, "*"):
+ methods = [methods]
+ for method in methods:
+ self.routes.append((method, compile_path_match(path), handler))
+ self.logger.debug("Route pattern: %s" % self.routes[-1][1].pattern)
+
+ def get_handler(self, request):
+ """Get a handler for a request or None if there is no handler.
+
+ :param request: Request to get a handler for.
+ :rtype: Callable or None
+ """
+ for method, regexp, handler in reversed(self.routes):
+ if (request.method == method or
+ method in (any_method, "*") or
+ (request.method == "HEAD" and method == "GET")):
+ m = regexp.match(request.url_parts.path)
+ if m:
+ if not hasattr(handler, "__class__"):
+ name = handler.__name__
+ else:
+ name = handler.__class__.__name__
+ self.logger.debug("Found handler %s" % name)
+
+ match_parts = m.groupdict().copy()
+ if len(match_parts) < len(m.groups()):
+ match_parts["*"] = m.groups()[-1]
+ request.route_match = match_parts
+
+ return handler
+ return None
diff --git a/tests/wpt/web-platform-tests/tools/wptserve/wptserve/routes.py b/tests/wpt/web-platform-tests/tools/wptserve/wptserve/routes.py
new file mode 100644
index 00000000000..d2bdcfb30ef
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/wptserve/wptserve/routes.py
@@ -0,0 +1,6 @@
+import handlers
+from router import any_method
+routes = [(any_method, "*.py", handlers.python_script_handler),
+ ("GET", "*.asis", handlers.as_is_handler),
+ ("GET", "*", handlers.file_handler),
+ ]
diff --git a/tests/wpt/web-platform-tests/tools/wptserve/wptserve/server.py b/tests/wpt/web-platform-tests/tools/wptserve/wptserve/server.py
new file mode 100644
index 00000000000..4eeb322cc61
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/wptserve/wptserve/server.py
@@ -0,0 +1,456 @@
+import BaseHTTPServer
+import errno
+import os
+import re
+import socket
+from SocketServer import ThreadingMixIn
+import ssl
+import sys
+import threading
+import time
+import traceback
+import types
+import urlparse
+
+import routes as default_routes
+from logger import get_logger
+from request import Server, Request
+from response import Response
+from router import Router
+from utils import HTTPException
+
+
+"""HTTP server designed for testing purposes.
+
+The server is designed to provide flexibility in the way that
+requests are handled, and to provide control both of exactly
+what bytes are put on the wire for the response, and in the
+timing of sending those bytes.
+
+The server is based on the stdlib HTTPServer, but with some
+notable differences in the way that requests are processed.
+Overall processing is handled by a WebTestRequestHandler,
+which is a subclass of BaseHTTPRequestHandler. This is responsible
+for parsing the incoming request. A RequestRewriter is then
+applied and may change the request data if it matches a
+supplied rule.
+
+Once the request data had been finalised, Request and Reponse
+objects are constructed. These are used by the other parts of the
+system to read information about the request and manipulate the
+response.
+
+Each request is handled by a particular handler function. The
+mapping between Request and the appropriate handler is determined
+by a Router. By default handlers are installed to interpret files
+under the document root with .py extensions as executable python
+files (see handlers.py for the api for such files), .asis files as
+bytestreams to be sent literally and all other files to be served
+statically.
+
+The handler functions are responsible for either populating the
+fields of the response object, which will then be written when the
+handler returns, or for directly writing to the output stream.
+"""
+
+
+class RequestRewriter(object):
+ def __init__(self, rules):
+ """Object for rewriting the request path.
+
+ :param rules: Initial rules to add; a list of three item tuples
+ (method, input_path, output_path), defined as for
+ register()
+ """
+ self.rules = {}
+ for rule in reversed(rules):
+ self.register(*rule)
+ self.logger = get_logger()
+
+ def register(self, methods, input_path, output_path):
+ """Register a rewrite rule.
+
+ :param methods: Set of methods this should match. "*" is a
+ special value indicating that all methods should
+ be matched.
+
+ :param input_path: Path to match for the initial request.
+
+ :param output_path: Path to replace the input path with in
+ the request.
+ """
+ if type(methods) in types.StringTypes:
+ methods = [methods]
+ self.rules[input_path] = (methods, output_path)
+
+ def rewrite(self, request_handler):
+ """Rewrite the path in a BaseHTTPRequestHandler instance, if
+ it matches a rule.
+
+ :param request_handler: BaseHTTPRequestHandler for which to
+ rewrite the request.
+ """
+ split_url = urlparse.urlsplit(request_handler.path)
+ if split_url.path in self.rules:
+ methods, destination = self.rules[split_url.path]
+ if "*" in methods or request_handler.command in methods:
+ self.logger.debug("Rewriting request path %s to %s" %
+ (request_handler.path, destination))
+ new_url = list(split_url)
+ new_url[2] = destination
+ new_url = urlparse.urlunsplit(new_url)
+ request_handler.path = new_url
+
+
+class WebTestServer(ThreadingMixIn, BaseHTTPServer.HTTPServer):
+ allow_reuse_address = True
+ acceptable_errors = (errno.EPIPE, errno.ECONNABORTED)
+ request_queue_size = 2000
+
+ # Ensure that we don't hang on shutdown waiting for requests
+ daemon_threads = True
+
+ def __init__(self, server_address, RequestHandlerClass, router, rewriter, bind_hostname,
+ config=None, use_ssl=False, key_file=None, certificate=None,
+ encrypt_after_connect=False, latency=None, **kwargs):
+ """Server for HTTP(s) Requests
+
+ :param server_address: tuple of (server_name, port)
+
+ :param RequestHandlerClass: BaseHTTPRequestHandler-like class to use for
+ handling requests.
+
+ :param router: Router instance to use for matching requests to handler
+ functions
+
+ :param rewriter: RequestRewriter-like instance to use for preprocessing
+ requests before they are routed
+
+ :param config: Dictionary holding environment configuration settings for
+ handlers to read, or None to use the default values.
+
+ :param use_ssl: Boolean indicating whether the server should use SSL
+
+ :param key_file: Path to key file to use if SSL is enabled.
+
+ :param certificate: Path to certificate to use if SSL is enabled.
+
+ :param encrypt_after_connect: For each connection, don't start encryption
+ until a CONNECT message has been received.
+ This enables the server to act as a
+ self-proxy.
+
+ :param bind_hostname True to bind the server to both the hostname and
+ port specified in the server_address parameter.
+ False to bind the server only to the port in the
+ server_address parameter, but not to the hostname.
+ :param latency: Delay in ms to wait before seving each response, or
+ callable that returns a delay in ms
+ """
+ self.router = router
+ self.rewriter = rewriter
+
+ self.scheme = "https" if use_ssl else "http"
+ self.logger = get_logger()
+
+ self.latency = latency
+
+ if bind_hostname:
+ hostname_port = server_address
+ else:
+ hostname_port = ("",server_address[1])
+
+ #super doesn't work here because BaseHTTPServer.HTTPServer is old-style
+ BaseHTTPServer.HTTPServer.__init__(self, hostname_port, RequestHandlerClass, **kwargs)
+
+ if config is not None:
+ Server.config = config
+ else:
+ self.logger.debug("Using default configuration")
+ Server.config = {"host": server_address[0],
+ "domains": {"": server_address[0]},
+ "ports": {"http": [self.server_address[1]]}}
+
+
+ self.key_file = key_file
+ self.certificate = certificate
+ self.encrypt_after_connect = use_ssl and encrypt_after_connect
+
+ if use_ssl and not encrypt_after_connect:
+ self.socket = ssl.wrap_socket(self.socket,
+ keyfile=self.key_file,
+ certfile=self.certificate,
+ server_side=True)
+
+ def handle_error(self, request, client_address):
+ error = sys.exc_value
+
+ if ((isinstance(error, socket.error) and
+ isinstance(error.args, tuple) and
+ error.args[0] in self.acceptable_errors)
+ or
+ (isinstance(error, IOError) and
+ error.errno in self.acceptable_errors)):
+ pass # remote hang up before the result is sent
+ else:
+ self.logger.error(traceback.format_exc())
+
+
+class WebTestRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
+ """RequestHandler for WebTestHttpd"""
+
+ protocol_version = "HTTP/1.1"
+
+ def handle_one_request(self):
+ response = None
+ self.logger = get_logger()
+ try:
+ self.close_connection = False
+ request_line_is_valid = self.get_request_line()
+
+ if self.close_connection:
+ return
+
+ request_is_valid = self.parse_request()
+ if not request_is_valid:
+ #parse_request() actually sends its own error responses
+ return
+
+ self.server.rewriter.rewrite(self)
+
+ request = Request(self)
+ response = Response(self, request)
+
+ if request.method == "CONNECT":
+ self.handle_connect(response)
+ return
+
+ if not request_line_is_valid:
+ response.set_error(414)
+ response.write()
+ return
+
+ self.logger.debug("%s %s" % (request.method, request.request_path))
+ handler = self.server.router.get_handler(request)
+
+ if self.server.latency is not None:
+ if callable(self.server.latency):
+ latency = self.server.latency()
+ else:
+ latency = self.server.latency
+ self.logger.warning("Latency enabled. Sleeping %i ms" % latency)
+ time.sleep(latency / 1000.)
+
+ if handler is None:
+ response.set_error(404)
+ else:
+ try:
+ handler(request, response)
+ except HTTPException as e:
+ response.set_error(e.code, e.message)
+ except Exception as e:
+ if e.message:
+ err = [e.message]
+ else:
+ err = []
+ err.append(traceback.format_exc())
+ response.set_error(500, "\n".join(err))
+ self.logger.debug("%i %s %s (%s) %i" % (response.status[0],
+ request.method,
+ request.request_path,
+ request.headers.get('Referer'),
+ request.raw_input.length))
+
+ if not response.writer.content_written:
+ response.write()
+
+ # If we want to remove this in the future, a solution is needed for
+ # scripts that produce a non-string iterable of content, since these
+ # can't set a Content-Length header. A notable example of this kind of
+ # problem is with the trickle pipe i.e. foo.js?pipe=trickle(d1)
+ if response.close_connection:
+ self.close_connection = True
+
+ if not self.close_connection:
+ # Ensure that the whole request has been read from the socket
+ request.raw_input.read()
+
+ except socket.timeout, e:
+ self.log_error("Request timed out: %r", e)
+ self.close_connection = True
+ return
+
+ except Exception as e:
+ err = traceback.format_exc()
+ if response:
+ response.set_error(500, err)
+ response.write()
+ logger.error(err)
+
+ def get_request_line(self):
+ try:
+ self.raw_requestline = self.rfile.readline(65537)
+ except socket.error:
+ self.close_connection = True
+ return False
+ if len(self.raw_requestline) > 65536:
+ self.requestline = ''
+ self.request_version = ''
+ self.command = ''
+ return False
+ if not self.raw_requestline:
+ self.close_connection = True
+ return True
+
+ def handle_connect(self, response):
+ self.logger.debug("Got CONNECT")
+ response.status = 200
+ response.write()
+ if self.server.encrypt_after_connect:
+ self.logger.debug("Enabling SSL for connection")
+ self.request = ssl.wrap_socket(self.connection,
+ keyfile=self.server.key_file,
+ certfile=self.server.certificate,
+ server_side=True)
+ self.setup()
+ return
+
+
+class WebTestHttpd(object):
+ """
+ :param host: Host from which to serve (default: 127.0.0.1)
+ :param port: Port from which to serve (default: 8000)
+ :param server_cls: Class to use for the server (default depends on ssl vs non-ssl)
+ :param handler_cls: Class to use for the RequestHandler
+ :param use_ssl: Use a SSL server if no explicit server_cls is supplied
+ :param key_file: Path to key file to use if ssl is enabled
+ :param certificate: Path to certificate file to use if ssl is enabled
+ :param encrypt_after_connect: For each connection, don't start encryption
+ until a CONNECT message has been received.
+ This enables the server to act as a
+ self-proxy.
+ :param router_cls: Router class to use when matching URLs to handlers
+ :param doc_root: Document root for serving files
+ :param routes: List of routes with which to initialize the router
+ :param rewriter_cls: Class to use for request rewriter
+ :param rewrites: List of rewrites with which to initialize the rewriter_cls
+ :param config: Dictionary holding environment configuration settings for
+ handlers to read, or None to use the default values.
+ :param bind_hostname: Boolean indicating whether to bind server to hostname.
+ :param latency: Delay in ms to wait before seving each response, or
+ callable that returns a delay in ms
+
+ HTTP server designed for testing scenarios.
+
+ Takes a router class which provides one method get_handler which takes a Request
+ and returns a handler function.
+
+ .. attribute:: host
+
+ The host name or ip address of the server
+
+ .. attribute:: port
+
+ The port on which the server is running
+
+ .. attribute:: router
+
+ The Router object used to associate requests with resources for this server
+
+ .. attribute:: rewriter
+
+ The Rewriter object used for URL rewriting
+
+ .. attribute:: use_ssl
+
+ Boolean indicating whether the server is using ssl
+
+ .. attribute:: started
+
+ Boolean indictaing whether the server is running
+
+ """
+ def __init__(self, host="127.0.0.1", port=8000,
+ server_cls=None, handler_cls=WebTestRequestHandler,
+ use_ssl=False, key_file=None, certificate=None, encrypt_after_connect=False,
+ router_cls=Router, doc_root=os.curdir, routes=None,
+ rewriter_cls=RequestRewriter, bind_hostname=True, rewrites=None,
+ latency=None, config=None):
+
+ if routes is None:
+ routes = default_routes.routes
+
+ self.host = host
+
+ self.router = router_cls(doc_root, routes)
+ self.rewriter = rewriter_cls(rewrites if rewrites is not None else [])
+
+ self.use_ssl = use_ssl
+ self.logger = get_logger()
+
+ if server_cls is None:
+ server_cls = WebTestServer
+
+ if use_ssl:
+ if key_file is not None:
+ assert os.path.exists(key_file)
+ assert certificate is not None and os.path.exists(certificate)
+
+ try:
+ self.httpd = server_cls((host, port),
+ handler_cls,
+ self.router,
+ self.rewriter,
+ config=config,
+ bind_hostname=bind_hostname,
+ use_ssl=use_ssl,
+ key_file=key_file,
+ certificate=certificate,
+ encrypt_after_connect=encrypt_after_connect,
+ latency=latency)
+ self.started = False
+
+ _host, self.port = self.httpd.socket.getsockname()
+ except Exception:
+ self.logger.error('Init failed! You may need to modify your hosts file. Refer to README.md.');
+ raise
+
+ def start(self, block=False):
+ """Start the server.
+
+ :param block: True to run the server on the current thread, blocking,
+ False to run on a separate thread."""
+ self.logger.info("Starting http server on %s:%s" % (self.host, self.port))
+ self.started = True
+ if block:
+ self.httpd.serve_forever()
+ else:
+ self.server_thread = threading.Thread(target=self.httpd.serve_forever)
+ self.server_thread.setDaemon(True) # don't hang on exit
+ self.server_thread.start()
+
+ def stop(self):
+ """
+ Stops the server.
+
+ If the server is not running, this method has no effect.
+ """
+ if self.started:
+ try:
+ self.httpd.shutdown()
+ self.httpd.server_close()
+ self.server_thread.join()
+ self.server_thread = None
+ self.logger.info("Stopped http server on %s:%s" % (self.host, self.port))
+ except AttributeError:
+ pass
+ self.started = False
+ self.httpd = None
+
+ def get_url(self, path="/", query=None, fragment=None):
+ if not self.started:
+ return None
+
+ return urlparse.urlunsplit(("http" if not self.use_ssl else "https",
+ "%s:%s" % (self.host, self.port),
+ path, query, fragment))
diff --git a/tests/wpt/web-platform-tests/tools/wptserve/wptserve/stash.py b/tests/wpt/web-platform-tests/tools/wptserve/wptserve/stash.py
new file mode 100644
index 00000000000..39bde3d6926
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/wptserve/wptserve/stash.py
@@ -0,0 +1,84 @@
+import uuid
+
+#TODO: Consider expiring values after some fixed time for long-running
+#servers
+
+
+class Stash(object):
+ """Key-value store for persisting data across HTTP requests.
+
+ This data store specifically designed for persisting data across
+ HTTP requests. It is entirely in-memory so data will not be
+ persisted across server restarts.
+
+ This has several unusual properties. Keys are of the form (path,
+ uuid), where path is, by default, the path in the HTTP request and
+ uuid is a unique id. In addition, the store is write-once, read-once,
+ i.e. the value associated with a particular key cannot be changed once
+ written and the read operation (called "take") is destructive. Taken together,
+ these properties make it difficult for data to accidentally leak
+ between different resources or different requests for the same
+ resource.
+
+ """
+
+ data = {}
+
+ def __init__(self, default_path):
+ self.default_path = default_path
+
+ def put(self, key, value, path=None):
+ """Place a value in the stash.
+
+ :param key: A UUID to use as the data's key.
+ :param value: The data to store. This can be any python object.
+ :param path: The path that has access to read the data (by default
+ the current request path)"""
+ if path is None:
+ path = self.default_path
+ if path not in self.data:
+ self.data[path] = PathStash(path)
+
+ self.data[path][key] = value
+
+ def take(self, key, path=None):
+ """Remove a value from the stash and return it.
+
+ :param key: A UUID to use as the data's key.
+ :param path: The path that has access to read the data (by default
+ the current request path)"""
+ if path is None:
+ path = self.default_path
+
+ if path in self.data:
+ value = self.data[path][key]
+ else:
+ value = None
+ return value
+
+
+class PathStash(dict):
+ def __init__(self, path):
+ self.path = path
+
+ def __setitem__(self, key, value):
+ key = uuid.UUID(key)
+ if value is None:
+ raise ValueError("Stash value may not be set to None")
+ if key in self:
+ raise StashError("Tried to overwrite existing stash value "
+ "for path %s and key %s (old value was %s, new value is %s)" %
+ (self.path, key, self[str(key)], value))
+ else:
+ dict.__setitem__(self, key, value)
+
+ def __getitem__(self, key):
+ key = uuid.UUID(key)
+ rv = dict.get(self, key, None)
+ if rv is not None:
+ del self[key]
+ return rv
+
+
+class StashError(Exception):
+ pass
diff --git a/tests/wpt/web-platform-tests/tools/wptserve/wptserve/utils.py b/tests/wpt/web-platform-tests/tools/wptserve/wptserve/utils.py
new file mode 100644
index 00000000000..e57ff196a8a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/wptserve/wptserve/utils.py
@@ -0,0 +1,14 @@
+def invert_dict(dict):
+ rv = {}
+ for key, values in dict.iteritems():
+ for value in values:
+ if value in rv:
+ raise ValueError
+ rv[value] = key
+ return rv
+
+
+class HTTPException(Exception):
+ def __init__(self, code, message=""):
+ self.code = code
+ self.message = message
diff --git a/tests/wpt/web-platform-tests/tools/wptserve/wptserve/wptserve.py b/tests/wpt/web-platform-tests/tools/wptserve/wptserve/wptserve.py
new file mode 100755
index 00000000000..816c8a5a6aa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/tools/wptserve/wptserve/wptserve.py
@@ -0,0 +1,33 @@
+#!/usr/bin/env python
+import argparse
+import os
+
+import server
+
+def abs_path(path):
+ return os.path.abspath(path)
+
+
+def parse_args():
+ parser = argparse.ArgumentParser(description="HTTP server designed for extreme flexibility "
+ "required in testing situations.")
+ parser.add_argument("document_root", action="store", type=abs_path,
+ help="Root directory to serve files from")
+ parser.add_argument("--port", "-p", dest="port", action="store",
+ type=int, default=8000,
+ help="Port number to run server on")
+ parser.add_argument("--host", "-H", dest="host", action="store",
+ type=str, default="127.0.0.1",
+ help="Host to run server on")
+ return parser.parse_args()
+
+
+def main():
+ args = parse_args()
+ httpd = server.WebTestHttpd(host=args.host, port=args.port,
+ use_ssl=False, certificate=None,
+ doc_root=args.document_root)
+ httpd.start()
+
+if __name__ == "__main__":
+ main()
diff --git a/tests/wpt/web-platform-tests/touch-events/create-touch-touchlist.html b/tests/wpt/web-platform-tests/touch-events/create-touch-touchlist.html
new file mode 100644
index 00000000000..502090c9671
--- /dev/null
+++ b/tests/wpt/web-platform-tests/touch-events/create-touch-touchlist.html
@@ -0,0 +1,185 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+ Test cases for Touch Events v1 Recommendation
+ http://www.w3.org/TR/touch-events/
+
+ These tests are based on Mozilla-Nokia-Google's single-touch tests.
+
+ The primary purpose of the tests in this document is checking that the createTouch and
+ createTouchList interfaces of the Touch Events APIs are correctly implemented.
+ Other interactions are covered in other test files.
+
+ This document references Test Assertions (abbrev TA below) written by Cathy Chan
+ http://www.w3.org/2010/webevents/wiki/TestAssertions
+-->
+
+<head>
+<title>Touch Events createTouch and createTouchList Interface Tests</title>
+<meta name="viewport" content="width=device-width">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+ setup({explicit_done: true});
+
+ // Check a Touch object's atttributes for existence and correct type
+ // TA: 1.1.2, 1.1.3
+ function check_Touch_object (t) {
+ test(function() {
+ assert_equals(Object.prototype.toString.call(t), "[object Touch]", "touch is of type Touch");
+ }, "touch point is a Touch object");
+ [
+ ["long", "identifier"],
+ ["EventTarget", "target"],
+ ["long", "screenX"],
+ ["long", "screenY"],
+ ["long", "clientX"],
+ ["long", "clientY"],
+ ["long", "pageX"],
+ ["long", "pageY"],
+ ].forEach(function(attr) {
+ var type = attr[0];
+ var name = attr[1];
+
+ // existence check
+ test(function() {
+ assert_true(name in t, name + " attribute in Touch object");
+ }, "Touch." + name + " attribute exists");
+
+ // type check
+ switch(type) {
+ case "long":
+ test(function() {
+ assert_equals(typeof t[name], "number", name + " attribute of type long");
+ }, "Touch." + name + " attribute is of type number (long)");
+ break;
+ case "EventTarget":
+ // An event target is some type of Element
+ test(function() {
+ assert_true(t[name] instanceof Element, "EventTarget must be an Element.");
+ }, "Touch." + name + " attribute is of type Element");
+ break;
+ default:
+ break;
+ }
+ });
+ }
+
+ // Check a TouchList object's attributes and methods for existence and proper type
+ // Also make sure all of the members of the list are Touch objects
+ // TA: 1.2.1, 1.2.2, 1.2.5, 1.2.6
+ function check_TouchList_object (tl) {
+ test(function() {
+ assert_equals(Object.prototype.toString.call(tl), "[object TouchList]", "touch list is of type TouchList");
+ }, "touch list is a TouchList object");
+ [
+ ["unsigned long", "length"],
+ ["function", "item"],
+ ].forEach(function(attr) {
+ var type = attr[0];
+ var name = attr[1];
+
+ // existence check
+ test(function() {
+ assert_true(name in tl, name + " attribute in TouchList");
+ }, "TouchList." + name + " attribute exists");
+
+ // type check
+ switch(type) {
+ case "unsigned long":
+ test(function() {
+ assert_equals(typeof tl[name], "number", name + " attribute of type long");
+ }, "TouchList." + name + " attribute is of type number (unsigned long)");
+ break;
+ case "function":
+ test(function() {
+ assert_equals(typeof tl[name], "function", name + " attribute of type function");
+ }, "TouchList." + name + " attribute is of type function");
+ break;
+ default:
+ break;
+ }
+ });
+ // Each member of tl should be a proper Touch object
+ for (var i=0; i < tl.length; i++) {
+ check_Touch_object(tl.item(i));
+ }
+ // TouchList.item(x) should return null if x is >= TouchList.length
+ test(function() {
+ var t = tl.item(tl.length);
+ assert_equals(t, null, "TouchList.item(TouchList.length) must return null");
+ }, "TouchList.item returns null if the index is >= the length of the list");
+ }
+
+ function check_touch_clientXY(touch) {
+ assert_equals(touch.clientX, touch.pageX - window.pageXOffset, "touch.clientX is touch.pageX - window.pageXOffset.");
+ assert_equals(touch.clientY, touch.pageY - window.pageYOffset, "touch.clientY is touch.pageY - window.pageYOffset.");
+ }
+
+ function run() {
+ var target0 = document.getElementById("target0");
+ var touch1, touch2;
+
+ test(function() {
+ touch1 = document.createTouch(window, target0, 42, 15, 20, 35, 40);
+ assert_equals(touch1.target, target0, "touch.target is target0");
+ assert_equals(touch1.identifier, 42, "touch.identifier is requested value");
+ assert_equals(touch1.pageX, 15, "touch.pageX is requested value");
+ assert_equals(touch1.pageY, 20, "touch.pageY is requested value");
+ check_touch_clientXY(touch1);
+ assert_equals(touch1.screenX, 35, "touch.screenX is requested value");
+ assert_equals(touch1.screenY, 40, "touch.screenY is requested value");
+ }, "document.createTouch exists and creates a Touch object with requested properties");
+
+ touch2 = document.createTouch(window, target0, 44, 25, 30, 45, 50);
+
+ var touchList;
+
+ test(function() {
+ touchList = document.createTouchList();
+ assert_equals(touchList.length, 0, "touchList.length is 0");
+ }, "document.createTouchList exists and correctly creates a TouchList from zero Touch objects");
+
+ if (touchList)
+ check_TouchList_object(touchList);
+
+ test(function() {
+ touchList = document.createTouchList(touch1);
+ assert_equals(touchList.length, 1, "touchList.length is 1");
+ assert_equals(touchList.item(0), touch1, "touchList.item(0) is input touch1");
+ }, "document.createTouchList exists and correctly creates a TouchList from a single Touch");
+
+ if (touchList)
+ check_TouchList_object(touchList);
+
+ test(function() {
+ touchList = document.createTouchList(touch1, touch2);
+ assert_equals(touchList.length, 2, "touchList.length is 2");
+ assert_equals(touchList.item(0), touch1, "touchList.item(0) is input touch1");
+ assert_equals(touchList.item(1), touch2, "touchList.item(1) is input touch2");
+ }, "document.createTouchList exists and correctly creates a TouchList from two Touch objects");
+
+ if (touchList)
+ check_TouchList_object(touchList);
+
+ target0.innerHTML = "Test complete."
+ done();
+ }
+</script>
+<style>
+ div {
+ margin: 0em;
+ padding: 2em;
+ }
+ #target0 {
+ background: yellow;
+ border: 1px solid orange;
+ }
+</style>
+</head>
+<body onload="run()">
+ <h1>Touch Events: createTouch and createTouchList tests</h1>
+ <div id="target0">Please wait for test to complete...</div>
+ <div id="log"></div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/touch-events/multi-touch-interactions-manual.html b/tests/wpt/web-platform-tests/touch-events/multi-touch-interactions-manual.html
new file mode 100644
index 00000000000..e9835d9c90b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/touch-events/multi-touch-interactions-manual.html
@@ -0,0 +1,49 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+ Test cases for Touch Events v1 Recommendation
+ http://www.w3.org/TR/touch-events/
+
+ These tests are based on Mozilla-Nokia-Google's single-touch
+ tests and to some extent Olli Pettay's multi-touch tests.
+
+ The primary purpose of the tests in this document is checking that the interactions
+ of various Touch events are correctly implemented under any touch patterns.
+
+ This document references Test Assertions (abbrev TA below) written by Cathy Chan
+ http://www.w3.org/2010/webevents/wiki/TestAssertions
+-->
+
+<head>
+<title>Touch Events Multi-Touch Interaction Test</title>
+<meta name="viewport" content="width=device-width">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="multi-touch-interactions.js"></script>
+<style>
+ div {
+ margin: 0em;
+ padding: 1.5em;
+ }
+ #target0 {
+ background: yellow;
+ border: 1px solid orange;
+ }
+ #target1 {
+ background: lightblue;
+ border: 1px solid blue;
+ }
+</style>
+</head>
+<body onload="run()">
+ <h1>Touch Events: Multi-Touch Interaction Test</h1>
+ <div id="target0">
+ Touch this box with one finger, then another one...
+ </div>
+ <div id="target1">
+ ...then drag to this box, then touch with a third finger, and lift all your fingers.
+ </div>
+ <div id="debug"></div>
+ <div id="log"></div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/touch-events/multi-touch-interactions.js b/tests/wpt/web-platform-tests/touch-events/multi-touch-interactions.js
new file mode 100644
index 00000000000..ac1b8ef55a8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/touch-events/multi-touch-interactions.js
@@ -0,0 +1,371 @@
+setup({explicit_done: true});
+
+var debug = document.getElementById("debug");
+
+function debug_print (x) {
+/* uncomment below statement to show debug messages */
+// document.getElementById("debug").innerHTML += x;
+}
+
+var starting_elements = {};
+
+function check_list_subset_of_targetlist(list, list_name, targetlist, targetlist_name) {
+ var exist_in_targetlist;
+ for(i=0; i<list.length; i++) {
+ exist_in_targetlist=false;
+ for(j=0; j<targetlist.length; j++)
+ if(list.item(i).identifier==targetlist.item(j).identifier)
+ exist_in_targetlist=true;
+
+ assert_true(exist_in_targetlist, list_name + ".item("+i+") exists in " + targetlist_name);
+ }
+}
+
+function check_list_subset_of_two_targetlists(list, list_name, targetlist1, targetlist1_name, targetlist2, targetlist2_name) {
+ var exist_in_targetlists;
+ for(i=0; i<list.length; i++) {
+ exist_in_targetlists=false;
+ for(j=0; j<targetlist1.length; j++)
+ if(list.item(i).identifier==targetlist1.item(j).identifier)
+ exist_in_targetlists=true;
+
+ if(!exist_in_targetlists)
+ for(j=0; j<targetlist2.length; j++)
+ if(list.item(i).identifier==targetlist2.item(j).identifier)
+ exist_in_targetlists=true;
+
+ assert_true(exist_in_targetlists, list_name + ".item("+i+") exists in " + targetlist1_name + " or " + targetlist2_name);
+ }
+
+}
+
+function is_at_least_one_item_in_targetlist(list, targetlist) {
+ for(i=0; i<list.length; i++)
+ for(j=0; j<targetlist.length; j++)
+ if(list.item(i).identifier==targetlist.item(j).identifier)
+ return true;
+
+ return false;
+}
+
+function check_no_item_in_targetlist(list, list_name, targetlist, targetlist_name) {
+ for(i=0; i<list.length; i++)
+ for(j=0; j<targetlist.length; j++) {
+ assert_false(list.item(i).identifier==targetlist.item(j).identifier, list_name + ".item("+i+") exists in " + targetlist_name);
+ return;
+ }
+}
+
+function check_targets(list, target) {
+ for(i=0; i<list.length; i++)
+ assert_true(list.item(i).target==target, "item(" + i + ").target is element receiving event");
+}
+
+function check_starting_elements(list) {
+ for (i=0; i<list.length; i++) {
+ assert_equals(list.item(i).target, starting_elements[list.item(i).identifier], "item(" + i + ").target matches starting element");
+ }
+}
+
+function run() {
+ var target0 = document.getElementById("target0");
+ var target1 = document.getElementById("target1");
+
+ var test_touchstart = async_test("touchstart event received");
+ var test_touchmove = async_test("touchmove event received");
+ var test_touchend = async_test("touchend event received");
+ var test_mousedown = async_test("Interaction with mouse events");
+
+ var touchstart_received = 0;
+ var touchmove_received = 0;
+ var touchend_received = 0;
+ var touchstart_identifier;
+
+ // last received touch lists for comparison
+ var last_touches;
+ var last_targetTouches={};
+ var last_changedTouches={};
+
+ on_event(window, "touchstart", function onTouchStart(ev) {
+ // process event only if it's targeted at target0 or target1
+ if(ev.target != target0 && ev.target != target1 )
+ return;
+
+ ev.preventDefault();
+
+ if(!touchstart_received) {
+ // Check event ordering TA: 1.6.1
+ test_touchstart.step(function() {
+ assert_true(touchmove_received==0, "touchstart precedes touchmove");
+ assert_true(touchend_received==0, "touchstart precedes touchend");
+ });
+ test_touchstart.done();
+ test_mousedown.done(); // If we got here, then the mouse event test is not needed.
+ }
+ touchstart_received++;
+
+ // TA: 1.3.2.2, 1.3.2.4
+ test(function() {
+ assert_true(ev.changedTouches.length >= 1, "changedTouches.length is at least 1");
+ assert_true(ev.changedTouches.length <= ev.touches.length, "changedTouches.length is smaller than touches.length");
+ check_list_subset_of_targetlist(ev.changedTouches, "changedTouches", ev.touches, "touches");
+ }, "touchstart #" + touchstart_received + ": changedTouches is a subset of touches");
+
+ // TA: 1.3.3.2, 1.3.3.3
+ test(function() {
+ assert_true(ev.targetTouches.length >= 1, "targetTouches.length is at least 1");
+ assert_true(ev.targetTouches.length <= ev.touches.length, "targetTouches.length is smaller than touches.length");
+ check_list_subset_of_targetlist(ev.targetTouches, "targetTouches", ev.touches, "touches");
+ }, "touchstart #" + touchstart_received + ": targetTouches is a subset of touches");
+
+ // TA: 1.3.3.9
+ test(function() {
+ check_targets(ev.targetTouches, ev.target);
+ }, "touchstart #" + touchstart_received + ": targets of targetTouches are correct");
+
+ // TA: 1.3.4.2
+ test(function() {
+ assert_true(ev.touches.length >= 1, "touches.length is at least 1");
+ }, "touchstart #" + touchstart_received + ": touches.length is valid");
+
+ if(touchstart_received == 1) {
+ // TA: 1.3.3.5, 1.3.3.7
+ test(function() {
+ assert_true(ev.targetTouches.length <= ev.changedTouches.length, "targetTouches.length is smaller than changedTouches.length");
+ check_list_subset_of_targetlist(ev.targetTouches, "targetTouches", ev.changedTouches, "changedTouches");
+ }, "touchstart #" + touchstart_received + ": targetTouches is a subset of changedTouches");
+
+ // TA: 1.3.4.3
+ test(function() {
+ assert_true(ev.touches.length==ev.changedTouches.length, "touches and changedTouches have the same length");
+ }, "touchstart #" + touchstart_received + ": touches and changedTouches have the same length");
+ } else {
+ // TA: 1.3.3.6
+ test(function() {
+ var diff_in_targetTouches = ev.targetTouches.length - (last_targetTouches[ev.target.id] ? last_targetTouches[ev.target.id].length : 0);
+ assert_true(diff_in_targetTouches > 0, "targetTouches.length is larger than last received targetTouches.length");
+ assert_true(diff_in_targetTouches <= ev.changedTouches.length, "change in targetTouches.length is smaller than changedTouches.length");
+ }, "touchstart #" + touchstart_received + ": change in targetTouches.length is valid");
+
+ // TA: 1.3.3.8
+ test(function() {
+ assert_true(is_at_least_one_item_in_targetlist(ev.targetTouches, ev.changedTouches), "at least one item of targetTouches is in changedTouches");
+ }, "touchstart #" + touchstart_received + ": at least one targetTouches item in changedTouches");
+
+ // TA: 1.3.4.4
+ test(function() {
+ var diff_in_touches = ev.touches.length - last_touches.length;
+ assert_true(diff_in_touches > 0, "touches.length is larger than last received touches.length");
+ assert_true(diff_in_touches == ev.changedTouches.length, "change in touches.length equals changedTouches.length");
+ }, "touchstart #" + touchstart_received + ": change in touches.length is valid");
+
+ // TA: 1.3.4.5
+ test(function() {
+ check_list_subset_of_two_targetlists(ev.touches, "touches", ev.changedTouches, "changedTouches", last_touches, "last touches");
+ }, "touchstart #" + touchstart_received + ": touches is subset of {changedTouches, last received touches}");
+ }
+
+ // save starting element of each new touch point
+ for (i=0; i<ev.changedTouches.length; i++) {
+ starting_elements[ev.changedTouches.item(i).identifier] = ev.changedTouches.item(i).target;
+ }
+
+ last_touches = ev.touches;
+ last_targetTouches[ev.target.id] = ev.targetTouches;
+ last_changedTouches = {}; // changedTouches are only saved for touchend events
+ });
+
+ on_event(window, "touchmove", function onTouchMove(ev) {
+ // process event only if it's targeted at target0 or target1
+ if(ev.target != target0 && ev.target != target1 )
+ return;
+
+ ev.preventDefault();
+
+ // TA: 1.6.1
+ test_touchmove.step(function() {
+ assert_true(touchstart_received>0, "touchmove follows touchstart");
+ // assert_false(touchend_received, "touchmove precedes touchend"); // this applies to scenario tests
+ });
+ test_touchmove.done();
+
+ touchmove_received++;
+
+ // do the detailed checking only for a few times
+ if(touchmove_received<6) {
+ // TA: 1.4.2.2, 1.4.2.4
+ test(function() {
+ assert_true(ev.changedTouches.length >= 1, "changedTouches.length is at least 1");
+ assert_true(ev.changedTouches.length <= ev.touches.length, "changedTouches.length is smaller than touches.length");
+ check_list_subset_of_targetlist(ev.changedTouches, "changedTouches", ev.touches, "touches");
+ }, "touchmove #" + touchmove_received + ": changedTouches is a subset of touches");
+
+ // TA: 1.4.3.2, 1.4.3.4
+ test(function() {
+ assert_true(ev.targetTouches.length >= 1, "targetTouches.length is at least 1");
+ assert_true(ev.targetTouches.length <= ev.touches.length, "targetTouches.length is smaller than touches.length");
+ check_list_subset_of_targetlist(ev.targetTouches, "targetTouches", ev.touches, "touches");
+ }, "touchmove #" + touchmove_received + ": targetTouches is a subset of touches");
+
+ // TA: 1.4.3.6
+ test(function() {
+ assert_true(is_at_least_one_item_in_targetlist(ev.targetTouches, ev.changedTouches), "at least one item of targetTouches is in changedTouches");
+ }, "touchmove #" + touchmove_received + ": at least one targetTouches item in changedTouches");
+
+ // TA: 1.4.3.8
+ test(function() {
+ check_targets(ev.targetTouches, ev.target);
+ }, "touchmove #" + touchmove_received + ": targets of targetTouches are correct");
+
+ // TA: 1.4.4.2
+ test(function() {
+ assert_true(ev.touches.length==last_touches.length, "length of touches is same as length of last received touches");
+ check_list_subset_of_targetlist(ev.touches, "touches", last_touches, "last received touches");
+ }, "touchmove #" + touchmove_received + ": touches must be same as last received touches");
+
+ // TA: 1.6.3
+ check_starting_elements(ev.changedTouches);
+ }
+
+ last_touches = ev.touches;
+ last_targetTouches[ev.target.id] = ev.targetTouches;
+ last_changedTouches = {}; // changedTouches are only saved for touchend events
+ });
+
+ on_event(window, "touchend", function onTouchEnd(ev) {
+ // process event only if it's targeted at target0 or target1
+ if(ev.target != target0 && ev.target != target1 )
+ return;
+
+ test_touchend.step(function() {
+ assert_true(touchstart_received>0, "touchend follows touchstart");
+ });
+ test_touchend.done();
+
+ touchend_received++;
+
+ debug_print("touchend #" + touchend_received + ":<br>");
+ debug_print("changedTouches.length=" + ev.changedTouches.length + "<br>");
+ debug_print("targetTouches.length=" + ev.targetTouches.length + "<br>");
+ debug_print("touches.length=" + ev.touches.length + "<br>");
+ for(i=0; i<ev.changedTouches.length; i++)
+ debug_print("changedTouches.item(" + i + ").target=" + ev.changedTouches.item(i).target.id + "<br>");
+
+ // TA: 1.5.2.2
+ test(function() {
+ assert_true(ev.changedTouches.length >= 1, "changedTouches.length is at least 1");
+ }, "touchend #" + touchend_received + ": length of changedTouches is valid");
+
+ // TA: 1.5.2.3
+ test(function() {
+ check_list_subset_of_targetlist(ev.changedTouches, "changedTouches", last_touches, "last received touches");
+ }, "touchend #" + touchend_received + ": changedTouches is a subset of last received touches");
+
+ // TA: 1.5.2.4, 1.5.2.5
+ test(function() {
+ check_no_item_in_targetlist(ev.changedTouches, "changedTouches", ev.touches, "touches");
+ check_no_item_in_targetlist(ev.changedTouches, "changedTouches", ev.targetTouches, "targetTouches");
+ }, "touchend #" + touchend_received + ": no item in changedTouches are in touches or targetTouches");
+
+ // TA: 1.5.2.6
+ test(function() {
+ var found=false;
+ for (i=0; i<ev.changedTouches.length; i++)
+ if (ev.changedTouches.item(i).target == ev.target)
+ found=true;
+ assert_true(found, "at least one item in changedTouches has matching target");
+ }, "touchend #" + touchend_received + ": at least one item in changedTouches targeted at this element");
+
+ // TA: 1.5.3.2, 1.5.3.3
+ test(function() {
+ assert_true(ev.targetTouches.length >= 0, "targetTouches.length is non-negative");
+ assert_true(ev.targetTouches.length <= ev.touches.length, "targetTouches.length is smaller than touches.length");
+ check_list_subset_of_targetlist(ev.targetTouches, "targetTouches", ev.touches, "touches");
+ }, "touchend #" + touchend_received + ": targetTouches is a subset of touches");
+
+ // TA: 1.5.3.5 (new)
+ test(function() {
+ check_targets(ev.targetTouches, ev.target);
+ }, "touchend #" + touchend_received + ": targets of targetTouches are correct");
+
+ // In some cases, when multiple touch points are released simultaneously
+ // the UA would dispatch the "same" touchend event (same changedTouches, same touches, but possibly different targetTouches)
+ // to each of the elements that are starting elments of the released touch points.
+ // in these situations, the subsequent events are exempt from TA 1.5.3.4 and 1.5.4.2
+ var same_event_as_last = false;
+ if (last_changedTouches && last_changedTouches.length==ev.changedTouches.length) {
+ same_event_as_last = true; // assume true until proven otherwise
+ for (i=0; i<last_changedTouches.length; i++) {
+ var match = false;
+ for (j=0; j<ev.changedTouches.length; j++)
+ if (last_changedTouches.item(i) == ev.changedTouches.item(j)) {
+ match = true;
+ break;
+ }
+ if (!match)
+ same_event_as_last = false;
+ }
+ }
+
+ if (!same_event_as_last) {
+ // TA: 1.5.3.4
+ // Getting semi-random failures on this and 1.5.4.2.
+ // See 1.5.4.2. Not sure if it's the same issue...
+ test(function() {
+ assert_true(last_targetTouches[ev.target.id].length > 0, "last received targetTouches.length is not zero");
+ var diff_in_targetTouches = last_targetTouches[ev.target.id].length - ev.targetTouches.length;
+ debug_print("diff_in_targetTouches=" + diff_in_targetTouches + "<br>");
+ assert_true(diff_in_targetTouches > 0, "targetTouches.length is smaller than last received targetTouches.length");
+ assert_true(diff_in_targetTouches <= ev.changedTouches.length, "change in targetTouches.length is smaller than changedTouches.length");
+ }, "touchend #" + touchend_received + ": change in targetTouches.length is valid");
+
+ // TA: 1.5.4.2
+ // Getting semi-random failures on this and 1.5.3.4.
+ // It looks like if fingers are lifted simultaneously, the "same" touchend event can be dispatched to two target elements
+ // but adapted to the element (same touches, changedTouches but different targetTouches).
+ // When one event is processed after another, ev.touches would end up being identical to last_touches, leading to failure.
+ // Question is why done() does not stop the processing of the latter event.
+ test(function() {
+ assert_true(last_touches.length > 0, "last received touches.length is not zero");
+ var diff_in_touches = last_touches.length - ev.touches.length;
+ debug_print("diff_in_touches=" + diff_in_touches + "<br>");
+ assert_true(diff_in_touches > 0, "touches.length is smaller than last received touches.length");
+ assert_equals(diff_in_touches, ev.changedTouches.length, "change in touches.length equals changedTouches.length");
+ }, "touchend #" + touchend_received + ": change in touches.length is valid");
+ }
+
+ // TA: 1.6.4
+ debug_print("touchend #" + touchend_received + ": TA 1.6.4<br>");
+ test(function() {
+ check_starting_elements(ev.changedTouches);
+ }, "touchend #" + touchend_received + ": event dispatched to correct element<br>");
+
+ debug_print("touchend #" + touchend_received + ": saving touch lists<br>");
+
+ last_touches = ev.touches;
+ last_targetTouches[ev.target.id] = ev.targetTouches;
+ last_changedTouches = ev.changedTouches;
+
+ debug_print("touchend #" + touchend_received + ": done<br>");
+ if(ev.touches.length==0)
+ done();
+ });
+
+ on_event(target0, "mousedown", function onMouseDown(ev) {
+ test_mousedown.step(function() {
+ assert_true(touchstart_received,
+ "The touchstart event must be dispatched before any mouse " +
+ "events. (If this fails, it might mean that the user agent does " +
+ "not implement W3C touch events at all.)"
+ );
+ });
+ test_mousedown.done();
+
+ if (!touchstart_received) {
+ // Abort the tests. If touch events are not supported, then most of
+ // the other event handlers will never be called, and the test will
+ // time out with misleading results.
+ done();
+ }
+ });
+}
diff --git a/tests/wpt/web-platform-tests/touch-events/multi-touch-interfaces-manual.html b/tests/wpt/web-platform-tests/touch-events/multi-touch-interfaces-manual.html
new file mode 100644
index 00000000000..6d0f7d433b9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/touch-events/multi-touch-interfaces-manual.html
@@ -0,0 +1,273 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+ Test cases for Touch Events v1 Recommendation
+ http://www.w3.org/TR/touch-events/
+
+ These tests are based on Mozilla-Nokia-Google's single-touch
+ tests and to some extent Olli Pettay's multi-touch tests.
+
+ The primary purpose of the tests in this document is checking that the
+ various interfaces of the Touch Events APIs are correctly implemented.
+ Other interactions are covered in other test files.
+
+ This document references Test Assertions (abbrev TA below) written by Cathy Chan
+ http://www.w3.org/2010/webevents/wiki/TestAssertions
+-->
+
+<head>
+<title>Touch Events Multi-Touch Interface Tests</title>
+<meta name="viewport" content="width=device-width">
+<script src="/resources/testharness.js"></script>
+<script>
+ setup({explicit_done: true});
+
+ // Check a Touch object's atttributes for existence and correct type
+ // TA: 1.1.2, 1.1.3
+ function check_Touch_object (t) {
+ test(function() {
+ assert_equals(Object.prototype.toString.call(t), "[object Touch]", "touch is of type Touch");
+ }, "touch point is a Touch object");
+ [
+ ["long", "identifier"],
+ ["EventTarget", "target"],
+ ["long", "screenX"],
+ ["long", "screenY"],
+ ["long", "clientX"],
+ ["long", "clientY"],
+ ["long", "pageX"],
+ ["long", "pageY"],
+ ].forEach(function(attr) {
+ var type = attr[0];
+ var name = attr[1];
+
+ // existence check
+ test(function() {
+ assert_true(name in t, name + " attribute in Touch object");
+ }, "Touch." + name + " attribute exists");
+
+ // type check
+ switch(type) {
+ case "long":
+ test(function() {
+ assert_equals(typeof t[name], "number", name + " attribute of type long");
+ }, "Touch." + name + " attribute is of type number (long)");
+ break;
+ case "EventTarget":
+ // An event target is some type of Element
+ test(function() {
+ assert_true(t[name] instanceof Element, "EventTarget must be an Element.");
+ }, "Touch." + name + " attribute is of type Element");
+ break;
+ default:
+ break;
+ }
+ });
+ }
+
+ // Check a TouchList object's attributes and methods for existence and proper type
+ // Also make sure all of the members of the list are Touch objects
+ // TA: 1.2.1, 1.2.2, 1.2.5, 1.2.6
+ function check_TouchList_object (tl) {
+ test(function() {
+ assert_equals(Object.prototype.toString.call(tl), "[object TouchList]", "touch list is of type TouchList");
+ }, "touch list is a TouchList object");
+ [
+ ["unsigned long", "length"],
+ ["function", "item"],
+ ].forEach(function(attr) {
+ var type = attr[0];
+ var name = attr[1];
+
+ // existence check
+ test(function() {
+ assert_true(name in tl, name + " attribute in TouchList");
+ }, "TouchList." + name + " attribute exists");
+
+ // type check
+ switch(type) {
+ case "unsigned long":
+ test(function() {
+ assert_equals(typeof tl[name], "number", name + " attribute of type long");
+ }, "TouchList." + name + " attribute is of type number (unsigned long)");
+ break;
+ case "function":
+ test(function() {
+ assert_equals(typeof tl[name], "function", name + " attribute of type function");
+ }, "TouchList." + name + " attribute is of type function");
+ break;
+ default:
+ break;
+ }
+ });
+ // Each member of tl should be a proper Touch object
+ for (var i=0; i < tl.length; i++) {
+ check_Touch_object(tl.item(i));
+ }
+ }
+
+ // Check a TouchEvent event's attributes for existence and proper type
+ // Also check that each of the event's TouchList objects are valid
+ // TA: 1.{3,4,5}.1.1, 1.{3,4,5}.1.2
+ function check_TouchEvent(ev) {
+ test(function() {
+ assert_true(ev instanceof TouchEvent, "event is a TouchEvent event");
+ }, ev.type + " event is a TouchEvent event");
+ [
+ ["TouchList", "touches"],
+ ["TouchList", "targetTouches"],
+ ["TouchList", "changedTouches"],
+ ["boolean", "altKey"],
+ ["boolean", "metaKey"],
+ ["boolean", "ctrlKey"],
+ ["boolean", "shiftKey"],
+ ].forEach(function(attr) {
+ var type = attr[0];
+ var name = attr[1];
+
+ // existence check
+ test(function() {
+ assert_true(name in ev, name + " attribute in " + ev.type + " event");
+ }, ev.type + "." + name + " attribute exists");
+
+ // type check
+ switch(type) {
+ case "boolean":
+ test(function() {
+ assert_equals(typeof ev[name], "boolean", name + " attribute of type boolean");
+ }, ev.type + "." + name + " attribute is of type boolean");
+ break;
+ case "TouchList":
+ test(function() {
+ assert_equals(Object.prototype.toString.call(ev[name]), "[object TouchList]", name + " attribute of type TouchList");
+ }, ev.type + "." + name + " attribute is of type TouchList");
+ // Now check the validity of the TouchList
+ check_TouchList_object(ev[name]);
+ break;
+ default:
+ break;
+ }
+ });
+ }
+
+ function is_touch_over_element(touch, element) {
+ var bounds = element.getBoundingClientRect();
+ return touch.pageX >= bounds.left && touch.pageX <= bounds.right &&
+ touch.pageY >= bounds.top && touch.pageY <= bounds.bottom;
+ }
+
+ function check_touch_clientXY(touch) {
+ assert_equals(touch.clientX, touch.pageX - window.pageXOffset, "touch.clientX is touch.pageX - window.pageXOffset.");
+ assert_equals(touch.clientY, touch.pageY - window.pageYOffset, "touch.clientY is touch.pageY - window.pageYOffset.");
+ }
+
+ function run() {
+ var target0 = document.getElementById("target0");
+ var target1 = document.getElementById("target1");
+
+ var test_touchstart = async_test("touchstart event received");
+ var test_touchmove = async_test("touchmove event received");
+ var test_touchend = async_test("touchend event received");
+ var test_mousedown = async_test("Interaction with mouse events");
+
+ var touchstart_received = 0;
+ var touchmove_received = false;
+ var touchend_received = false;
+ var invalid_touchmove_received = false;
+
+ on_event(target0, "touchstart", function onTouchStart(ev) {
+ ev.preventDefault();
+
+ if(!touchstart_received) {
+ // Check event ordering TA: 1.6.2
+ test_touchstart.step(function() {
+ assert_false(touchmove_received, "touchstart precedes touchmove");
+ assert_false(touchend_received, "touchstart precedes touchend");
+ });
+ test_touchstart.done();
+ test_mousedown.done(); // If we got here, then the mouse event test is not needed.
+ }
+
+ if(++touchstart_received <= 2)
+ check_TouchEvent(ev);
+ });
+
+ on_event(target0, "touchmove", function onTouchMove(ev) {
+ ev.preventDefault();
+
+ if (touchmove_received)
+ return;
+ touchmove_received = true;
+
+ test_touchmove.step(function() {
+ assert_true(touchstart_received>0, "touchmove follows touchstart");
+ assert_false(touchend_received, "touchmove precedes touchend");
+ });
+ test_touchmove.done();
+
+ check_TouchEvent(ev);
+ });
+
+ on_event(target1, "touchmove", function onTouchMove(ev) {
+ invalid_touchmove_received = true;
+ });
+
+ on_event(window, "touchend", function onTouchEnd(ev) {
+ touchend_received = true;
+
+ test_touchend.step(function() {
+ assert_true(touchstart_received>0, "touchend follows touchstart");
+ assert_true(touchmove_received, "touchend follows touchmove");
+ assert_false(invalid_touchmove_received, "touchmove dispatched to correct target");
+ });
+ test_touchend.done();
+
+ check_TouchEvent(ev);
+ done();
+ });
+
+ on_event(target0, "mousedown", function onMouseDown(ev) {
+ test_mousedown.step(function() {
+ assert_true(touchstart_received,
+ "The touchstart event must be dispatched before any mouse " +
+ "events. (If this fails, it might mean that the user agent does " +
+ "not implement W3C touch events at all.)"
+ );
+ });
+ test_mousedown.done();
+
+ if (!touchstart_received) {
+ // Abort the tests. If touch events are not supported, then most of
+ // the other event handlers will never be called, and the test will
+ // time out with misleading results.
+ done();
+ }
+ });
+ }
+</script>
+<style>
+ div {
+ margin: 0em;
+ padding: 2em;
+ }
+ #target0 {
+ background: yellow;
+ border: 1px solid orange;
+ }
+ #target1 {
+ background: lightblue;
+ border: 1px solid blue;
+ }
+</style>
+</head>
+<body onload="run()">
+ <h1>Touch Events: multi-touch interface tests</h1>
+ <div id="target0">
+ Touch this box with one finger, then another one...
+ </div>
+ <div id="target1">
+ ...then drag to this box and lift your fingers.
+ </div>
+ <div id="log"></div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/touch-events/single-touch-manual.html b/tests/wpt/web-platform-tests/touch-events/single-touch-manual.html
new file mode 100644
index 00000000000..5f76e61b419
--- /dev/null
+++ b/tests/wpt/web-platform-tests/touch-events/single-touch-manual.html
@@ -0,0 +1,378 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+ Test cases for Touch Events v1 Recommendation
+ http://www.w3.org/TR/touch-events/
+
+ These tests are based on Matt Bruebeck's single-touch tests.
+ There are NO multi-touch tests in this document.
+
+ This document references Test Assertions (abbrev TA below) written by Cathy Chan
+ http://www.w3.org/2010/webevents/wiki/TestAssertions
+-->
+
+<head>
+ <title>Touch Events Single Touch Tests</title>
+ <meta name="viewport" content="width=device-width">
+ <script src="/resources/testharness.js"></script>
+ <script>
+ setup({explicit_done: true});
+
+ // Check a Touch object's atttributes for existence and correct type
+ // TA: 1.1.2, 1.1.3
+ function check_Touch_object (t) {
+ test(function() {
+ assert_equals(Object.prototype.toString.call(t), "[object Touch]", name + " attribute of type TouchList");
+ }, "touch point is a Touch object");
+ [
+ ["long", "identifier"],
+ ["EventTarget", "target"],
+ ["long", "screenX"],
+ ["long", "screenY"],
+ ["long", "clientX"],
+ ["long", "clientY"],
+ ["long", "pageX"],
+ ["long", "pageY"],
+ ].forEach(function(attr) {
+ var type = attr[0];
+ var name = attr[1];
+
+ // existence check
+ test(function() {
+ assert_true(name in t, name + " attribute in Touch object");
+ }, "Touch." + name + " attribute exists");
+
+ // type check
+ switch(type) {
+ case "long":
+ test(function() {
+ assert_equals(typeof t[name], "number", name + " attribute of type long");
+ }, "Touch." + name + " attribute is of type number (long)");
+ break;
+ case "EventTarget":
+ // An event target is some type of Element
+ test(function() {
+ assert_true(t[name] instanceof Element, "EventTarget must be an Element.");
+ }, "Touch." + name + " attribute is of type Element");
+ break;
+ default:
+ break;
+ }
+ });
+ }
+
+ // Check a TouchList object's attributes and methods for existence and proper type
+ // Also make sure all of the members of the list are Touch objects
+ // TA: 1.2.1, 1.2.2, 1.2.5
+ function check_TouchList_object (tl) {
+ test(function() {
+ assert_equals(Object.prototype.toString.call(tl), "[object TouchList]", name + " attribute of type TouchList");
+ }, "touch list is a TouchList object");
+ [
+ ["unsigned long", "length"],
+ ["function", "item"],
+ ].forEach(function(attr) {
+ var type = attr[0];
+ var name = attr[1];
+
+ // existence check
+ test(function() {
+ assert_true(name in tl, name + " attribute in TouchList");
+ }, "TouchList." + name + " attribute exists");
+
+ // type check
+ switch(type) {
+ case "unsigned long":
+ test(function() {
+ assert_equals(typeof tl[name], "number", name + " attribute of type long");
+ }, "TouchList." + name + " attribute is of type number (unsigned long)");
+ break;
+ case "function":
+ test(function() {
+ assert_equals(typeof tl[name], "function", name + " attribute of type function");
+ }, "TouchList." + name + " attribute is of type function");
+ break;
+ default:
+ break;
+ }
+ });
+ // Each member of tl should be a proper Touch object
+ for (var i=0; i < tl.length; i++) {
+ check_Touch_object(tl.item(i));
+ }
+ }
+
+ // Check a TouchEvent event's attributes for existence and proper type
+ // Also check that each of the event's TouchList objects are valid
+ // TA: 1.{3,4,5}.1.1, 1.{3,4,5}.1.2
+ function check_TouchEvent(ev) {
+ test(function() {
+ assert_true(ev instanceof TouchEvent, "event is a TouchEvent event");
+ }, ev.type + " event is a TouchEvent event");
+ [
+ ["TouchList", "touches"],
+ ["TouchList", "targetTouches"],
+ ["TouchList", "changedTouches"],
+ ["boolean", "altKey"],
+ ["boolean", "metaKey"],
+ ["boolean", "ctrlKey"],
+ ["boolean", "shiftKey"],
+ ].forEach(function(attr) {
+ var type = attr[0];
+ var name = attr[1];
+
+ // existence check
+ test(function() {
+ assert_true(name in ev, name + " attribute in " + ev.type + " event");
+ }, ev.type + "." + name + " attribute exists");
+
+ // type check
+ switch(type) {
+ case "boolean":
+ test(function() {
+ assert_equals(typeof ev[name], "boolean", name + " attribute of type boolean");
+ }, ev.type + "." + name + " attribute is of type boolean");
+ break;
+ case "TouchList":
+ test(function() {
+ assert_equals(Object.prototype.toString.call(ev[name]), "[object TouchList]", name + " attribute of type TouchList");
+ }, ev.type + "." + name + " attribute is of type TouchList");
+ // Now check the validity of the TouchList
+ check_TouchList_object(ev[name]);
+ break;
+ default:
+ break;
+ }
+ });
+ }
+
+ function is_touch_over_element(touch, element) {
+ var bounds = element.getBoundingClientRect();
+ return touch.pageX >= bounds.left && touch.pageX <= bounds.right &&
+ touch.pageY >= bounds.top && touch.pageY <= bounds.bottom;
+ }
+
+ function check_touch_clientXY(touch) {
+ assert_equals(touch.clientX, touch.pageX - window.pageXOffset, "touch.clientX is touch.pageX - window.pageXOffset.");
+ assert_equals(touch.clientY, touch.pageY - window.pageYOffset, "touch.clientY is touch.pageY - window.pageYOffset.");
+ }
+
+ function check_screenXY_clientXY_pageXY(touch) {
+ assert_greater_than_equal(touch.screenX, 0, "touch.screenX is no less than 0");
+ assert_greater_than_equal(touch.screenY, 0, "touch.screenY is no less than 0");
+ assert_greater_than_equal(touch.clientX, 0, "touch.clientX is no less than 0");
+ assert_greater_than_equal(touch.clientY, 0, "touch.clientY is no less than 0");
+ assert_greater_than_equal(touch.pageX, 0, "touch.pageX is no less than 0");
+ assert_greater_than_equal(touch.pageY, 0, "touch.pageY is no less than 0");
+ }
+
+ function run() {
+ var target0 = document.getElementById("target0");
+ var target1 = document.getElementById("target1");
+
+ var test_touchstart = async_test("touchstart event received");
+ var test_touchmove = async_test("touchmove event received");
+ var test_touchend = async_test("touchend event received");
+ var test_mousedown = async_test("Interaction with mouse events");
+
+ var touchstart_received = false;
+ var touchmove_received = false;
+ var touchend_received = false;
+ var invalid_touchmove_received = false;
+ var touchstart_identifier;
+
+ on_event(target0, "touchstart", function onTouchStart(ev) {
+ ev.preventDefault();
+
+ // Check event ordering TA: 1.6.2
+ test_touchstart.step(function() {
+ assert_false(touchstart_received, "duplicate touchstart event");
+ assert_false(touchmove_received, "touchstart precedes touchmove");
+ assert_false(touchend_received, "touchstart precedes touchend");
+ });
+ test_touchstart.done();
+ if (touchstart_received)
+ return;
+ touchstart_received = true;
+ test_mousedown.done(); // If we got here, then the mouse event test is not needed.
+
+ check_TouchEvent(ev);
+
+ // TA: 1.3.2.1, 1.3.3.1, 1.3.4.1
+ test(function() {
+ assert_equals(ev.touches.length, 1, "One touch point.");
+ assert_equals(ev.changedTouches.length, 1, "One changed touch point.");
+ assert_equals(ev.targetTouches.length, 1, "One target touch point.");
+ }, "touchstart: all TouchList lengths are correct");
+
+ var t = ev.touches[0];
+ var ct = ev.changedTouches[0];
+ var tt = ev.targetTouches[0];
+
+ touchstart_identifier = t.identifier;
+ // TA: 1.3.3.3, 1.3.2.3, 1.3.3.4 (indirect (transitive))
+ test(function() {
+ assert_equals(ct.identifier, touchstart_identifier, "changedTouches identifier matches.");
+ assert_equals(tt.identifier, touchstart_identifier, "targetTouches identifier matches.");
+ }, "touchstart: all TouchList identifiers are consistent");
+
+ // TA: 1.3.3.9
+ test(function() {
+ assert_equals(tt.target, ev.target, "event target same as targetTouches target.");
+ }, "touchstart: event target same as targetTouches target");
+
+ test(function() {
+ assert_true(is_touch_over_element(t, target0), "touch.pageX/pageY is over target0.");
+ }, "touchstart: touch pageX/pageY inside of target element");
+ test(function() {
+ check_touch_clientXY(t);
+ }, "touchstart: touch clientX/clientY is consistent with pageX/pageY");
+ // Note we don't bother testing screenX/screenY values - there's no reliable way to
+ // verify they are consistent with clientX/clientY (due to unknown amount of window
+ // chrome), and also various forms of scaling mean they are in different units.
+
+ test(function() {
+ check_screenXY_clientXY_pageXY(t);
+ }, "touchstart: touch screenX/screenY pageX/pageY and clientX/clientY values are no less than 0");
+ });
+
+ on_event(target0, "touchmove", function onTouchMove(ev) {
+ ev.preventDefault();
+
+ if (touchmove_received)
+ return;
+ touchmove_received = true;
+
+ test_touchmove.step(function() {
+ assert_true(touchstart_received, "touchmove follows touchstart");
+ assert_false(touchend_received, "touchmove precedes touchend");
+ });
+ test_touchmove.done();
+
+ check_TouchEvent(ev);
+
+ // TA: 1.4.2.1, 1.4.3.1
+ test(function() {
+ assert_equals(ev.touches.length, 1, "One touch point.");
+ assert_equals(ev.changedTouches.length, 1, "One changed touch point.");
+ assert_equals(ev.targetTouches.length, 1, "One target touch point.");
+ }, "touchmove: all TouchList lengths are correct");
+
+ // 1.4.2.3, 1.4.3.3, 1.4.3.5, 1.4.4.3
+ test(function() {
+ assert_equals(ev.touches[0].identifier, touchstart_identifier, "Touch identifier matches.");
+ assert_equals(ev.changedTouches[0].identifier, touchstart_identifier, "Changed touch identifier matches.");
+ assert_equals(ev.targetTouches[0].identifier, touchstart_identifier, "Target touch identifier matches.");
+ }, "touchmove: all TouchList identifiers matches touchstart identifier");
+
+ // TA: 1.4.3.8
+ var tt = ev.targetTouches[0];
+ test(function() {
+ assert_equals(tt.target, ev.target, "event target same as targetTouches target.");
+ }, "touchmove: event target same as targetTouches target");
+
+ test(function() {
+ assert_true(is_touch_over_element(tt, target0) || is_touch_over_element(tt, target1),
+ "touch.pageX/pageY is over one of the targets.");
+ }, "touchmove: touch pageX/pageY inside of one of the target elements");
+ test(function() {
+ check_touch_clientXY(tt);
+ }, "touchmove: touch clientX/clientY is consistent with pageX/pageY");
+
+ test(function() {
+ check_screenXY_clientXY_pageXY(tt);
+ }, "touchmove: touch screenX/screenY pageX/pageY and clientX/clientY values are no less than 0");
+
+ });
+
+ on_event(target1, "touchmove", function onTouchMove(ev) {
+ invalid_touchmove_received = true;
+ });
+
+ on_event(window, "touchend", function onTouchEnd(ev) {
+ touchend_received = true;
+
+ test_touchend.step(function() {
+ assert_equals(ev.target, target0, "touchend is dispatched to the original target");
+ assert_true(touchstart_received, "touchend follows touchstart");
+ assert_true(touchmove_received, "touchend follows touchmove");
+ assert_false(invalid_touchmove_received, "touchmove dispatched to correct target");
+ });
+ test_touchend.done();
+
+ check_TouchEvent(ev);
+
+ // TA: 1.5.1.2, 1.5.3.1, 1.5.4.1
+ test(function() {
+ assert_equals(ev.touches.length, 0, "Zero touch points.");
+ assert_equals(ev.changedTouches.length, 1, "One changed touch point.");
+ assert_equals(ev.targetTouches.length, 0, "Zero target touch points.");
+ }, "touchend: all TouchList lengths are correct");
+
+ var t = ev.changedTouches[0];
+
+ // TA: 1.5.2.6, 1.5.2.3
+ test(function() {
+ assert_equals(t.identifier, touchstart_identifier, "changedTouches identifier matches.");
+ }, "touchend: touches identifier matches changedTouches identifier");
+
+ test(function() {
+ assert_true(is_touch_over_element(t, target1),
+ "touch.pageX/pageY is over target1.");
+ }, "touchend: touch pageX/pageY inside expected element");
+ test(function() {
+ check_touch_clientXY(t);
+ }, "touchend: touch clientX/clientY is consistent with pageX/pageY");
+
+ test(function() {
+ check_screenXY_clientXY_pageXY(t);
+ }, "touchend: touch screenX/screenY pageX/pageY and clientX/clientY values are no less than 0");
+
+ done();
+ });
+
+ on_event(target0, "mousedown", function onMouseDown(ev) {
+ test_mousedown.step(function() {
+ assert_true(touchstart_received,
+ "The touchstart event must be dispatched before any mouse " +
+ "events. (If this fails, it might mean that the user agent does " +
+ "not implement W3C touch events at all.)"
+ );
+ });
+ test_mousedown.done();
+
+ if (!touchstart_received) {
+ // Abort the tests. If touch events are not supported, then most of
+ // the other event handlers will never be called, and the test will
+ // time out with misleading results.
+ done();
+ }
+ });
+ }
+ </script>
+ <style>
+ div {
+ margin: 0em;
+ padding: 2em;
+ }
+ #target0 {
+ background: yellow;
+ border: 1px solid orange;
+ }
+ #target1 {
+ background: lightblue;
+ border: 1px solid blue;
+ }
+ </style>
+</head>
+<body onload="run()">
+ <h1>Touch Events: single-touch tests</h1>
+ <div id="target0">
+ Touch this box with one finger (or other pointing device)...
+ </div>
+ <div id="target1">
+ ...then drag to this box and lift your finger.
+ </div>
+ <div id="log"></div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/typedarrays/ArrayBuffer_constructor.html b/tests/wpt/web-platform-tests/typedarrays/ArrayBuffer_constructor.html
new file mode 100644
index 00000000000..c558c0014fb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/typedarrays/ArrayBuffer_constructor.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Typed Arrays Test: ArrayBuffer constructor</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://www.khronos.org/registry/typedarray/specs/latest/#5">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+
+var args = [
+ /* numbers */
+ [NaN, 0], [+Infinity, 0], [-Infinity, 0], [+0, 0], [-0, 0],
+ [-0.4, 0], [-0.9, 0], [1.1, 1], [2.9, 2],
+ [1, 1], [-0xF1000000, 0xF000000],
+ /* strings */
+ ["1", 1], ["1e2", 100],
+ /* null, undefined, booleans */
+ [undefined, 0], [null, 0], [false, 0], [true, 1]
+];
+
+args.forEach(function (arg, i) {
+ test(function () {
+ var abuffer = new ArrayBuffer(arg[0]);
+ assert_equals(abuffer.byteLength, arg[1]);
+ }, "The argument " + format_value(arg[0]) + " should be interpreted as " +
+ arg[1] + " for ArrayBuffer constructor." + i);
+});
+
+</script>
diff --git a/tests/wpt/web-platform-tests/typedarrays/ArrayBuffer_properties.html b/tests/wpt/web-platform-tests/typedarrays/ArrayBuffer_properties.html
new file mode 100644
index 00000000000..a4472980a21
--- /dev/null
+++ b/tests/wpt/web-platform-tests/typedarrays/ArrayBuffer_properties.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Typed Arrays Test: ArrayBuffer properties</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://www.khronos.org/registry/typedarray/specs/latest/#5">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+
+test(function () {
+ var intLen = 8;
+ var abuffer = new ArrayBuffer(intLen);
+
+ //byteLength
+ test(function () {
+ var len = abuffer.byteLength;
+ abuffer.byteLength = len + 1;
+ assert_equals(len, intLen, "the byteLength of ArrayBuffer");
+ assert_equals(abuffer.byteLength, len, "the byteLength of ArrayBuffer");
+ }, "Check if the byteLength is fixed at construction time and readonly");
+
+ //slice()
+ test(function () {
+ var b = abuffer.slice(2);
+ assert_true(b instanceof ArrayBuffer, "Returns a new ArrayBuffer");
+ assert_equals(b.byteLength, intLen-2, "The byteLength of ArrayBuffer");
+ }, "Check if the new ArrayBuffer contains all bytes from begin to the end of this ArrayBuffer when the end is unspecified");
+
+ test(function () {
+ var b = abuffer.slice(2, 6);
+ assert_true(b instanceof ArrayBuffer, "Returns a new ArrayBuffer");
+ assert_equals(b.byteLength, 4, "The byteLength of ArrayBuffer");
+ }, "Check if the new ArrayBuffer contains the bytes from begin to the end of this ArrayBuffer when the end is specified");
+
+ test(function () {
+ b = abuffer.slice(2, 10);
+ assert_equals(b.byteLength, 6, "The byteLength of ArrayBuffer");
+ }, "Check if the slice range specified by the begin and end values is clamped to the valid index range for the current array");
+
+ test(function () {
+ var b = abuffer.slice(2, -1);
+ assert_equals(b.byteLength, 5, "The byteLength of ArrayBuffer");
+ b = abuffer.slice(-2, -1);
+ assert_equals(b.byteLength, 1, "The byteLength of ArrayBuffer");
+ }, "Check if it refers to an index from the end of the array when either begin or end is negative");
+
+ test(function () {
+ var b = abuffer.slice(4, 2);
+ assert_equals(b.byteLength, 0, "The byteLength of ArrayBuffer");
+ b = abuffer.slice(-1, -2);
+ assert_equals(b.byteLength, 0, "The byteLength of ArrayBuffer");
+ }, "Check if the length is clamped to zero when the computed length of the new ArrayBuffer is negative");
+
+ //static isView()
+ test(function () {
+ var int8a = new Int8Array(8);
+ assert_true(ArrayBuffer.isView(int8a), "The return value of ArrayBufferView.isView");
+ }, "Check if the isView returns true when the value is an object implementing the ArrayBufferView interface");
+
+ test(function () {
+ var arr = new Array(8);
+ assert_false(ArrayBuffer.isView(arr), "The return value of ArrayBufferView.isView");
+ }, "Check if the isView returns false when the value is an object not implementing the ArrayBufferView interface");
+});
+
+</script>
diff --git a/tests/wpt/web-platform-tests/typedarrays/Uint8ClampedArray_constructor.html b/tests/wpt/web-platform-tests/typedarrays/Uint8ClampedArray_constructor.html
new file mode 100644
index 00000000000..056952a4fca
--- /dev/null
+++ b/tests/wpt/web-platform-tests/typedarrays/Uint8ClampedArray_constructor.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Typed Arrays Test: Uint8ClampedArray constructor</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="http://www.khronos.org/registry/typedarray/specs/latest/#7.1">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+
+test(function() {
+ var obj = new Uint8ClampedArray(new Uint8ClampedArray(8));
+ assert_true(obj instanceof Uint8ClampedArray, "The constructor return Uint8ClampedArray");
+ assert_equals(obj.length, 8, "The length of Uint8ClampedArray");
+}, "Check if the constructor(Uint8ClampedArray) create new Uint8ClampedArray");
+
+test(function() {
+ var obj = new Uint8ClampedArray(new ArrayBuffer(8));
+ assert_true(obj instanceof Uint8ClampedArray, "The constructor return Uint8ClampedArray");
+ assert_equals(obj.length, 8, "The length of Uint8ClampedArray");
+}, "Check if the constructor(ArrayBuffer) create new Uint8ClampedArray");
+
+test(function() {
+ var obj = new Uint8ClampedArray(new ArrayBuffer(8), 2);
+ assert_true(obj instanceof Uint8ClampedArray, "The constructor return object Uint8ClampedArray");
+ assert_equals(obj.length, 6, "The length of Uint8ClampedArray");
+}, "Check if the constructor(ArrayBuffer, byteOffset) create new Uint8ClampedArray");
+
+test(function() {
+ var obj = new Uint8ClampedArray(new ArrayBuffer(8), 2, 4);
+ assert_true(obj instanceof Uint8ClampedArray, "The constructor return object Uint8ClampedArray");
+ assert_equals(obj.length, 4, "The length of Uint8ClampedArray");
+}, "Check if the constructor(ArrayBuffer, byteOffset, length) create new Uint8ClampedArray");
+
+</script>
diff --git a/tests/wpt/web-platform-tests/typedarrays/Uint8ClampedArray_length.html b/tests/wpt/web-platform-tests/typedarrays/Uint8ClampedArray_length.html
new file mode 100644
index 00000000000..6551cd780de
--- /dev/null
+++ b/tests/wpt/web-platform-tests/typedarrays/Uint8ClampedArray_length.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Typed Arrays Test: Uint8ClampedArray length</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="http://www.khronos.org/registry/typedarray/specs/latest/#7.1">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+
+test(function() {
+ var arr = new Uint8ClampedArray(8);
+
+ test(function() {
+ assert_equals(arr.length, 8, "The Uint8ClampedArray.length");
+ }, "Check if the Uint8ClampedArray.length should be the value given by constructor");
+
+ test(function() {
+ var len = arr.length;
+ arr.length = len + 1;
+ assert_equals(arr.length, len, "The Uint8ClampedArray.length");
+ }, "Check if the Uint8ClampedArray.length is readonly");
+});
+
+</script>
diff --git a/tests/wpt/web-platform-tests/typedarrays/Uint8ClampedArray_setter_getter.html b/tests/wpt/web-platform-tests/typedarrays/Uint8ClampedArray_setter_getter.html
new file mode 100644
index 00000000000..28c8ecacb09
--- /dev/null
+++ b/tests/wpt/web-platform-tests/typedarrays/Uint8ClampedArray_setter_getter.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Typed Arrays Test: Uint8ClampedArray setter and getter</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="http://www.khronos.org/registry/typedarray/specs/latest/#7.1">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+
+var testData = [
+ [1, 1], [257, 255], [3.2, 3], [-3.8, 0], [+0, 0], [-0, 0],
+ ["1", 1], [false, 0], [true, 1], [undefined, 0], [null, 0],
+ [NaN, 0], [+Infinity, 255], [-Infinity, 0]
+];
+
+testData.forEach(function (arg) {
+ test(function() {
+ var obj = new Uint8ClampedArray(8);
+ //set [Clamp] octet value
+ obj[0] = arg[0];
+ assert_equals(obj[0], arg[1], "The value of Uint8ClampedArray");
+ }, "Check if the getter can get " + arg[1] + " after set " + format_value(arg[0]) + " by the setter");
+});
+
+test(function() {
+ var obj = new Uint8ClampedArray(8);
+ var arg = [1, 2, 3];
+ //set octet[]
+ obj.set(arg);
+ assert_equals(obj[1], arg[1], "The value of Uint8ClampedArray");
+}, "Check if the parameter of Uint8ClampedArray.set() accept octet[]");
+
+test(function() {
+ var obj = new Uint8ClampedArray(8);
+ var arg = [1, 2, 3];
+ //set octet[] with offset
+ obj.set(arg, 1);
+ assert_equals(obj[1], arg[0], "The value of Uint8ClampedArray");
+}, "Check if the parameter of Uint8ClampedArray.set() accept octet[] and offset");
+
+test(function() {
+ var obj = new Uint8ClampedArray(8);
+ var arg = new Uint8ClampedArray([1, 2, 3]);
+ //set Uint8ClampedArray
+ obj.set(arg);
+ assert_equals(obj[1], arg[1], "The value of Uint8ClampedArray");
+}, "Check if the parameter of Uint8ClampedArray.set() accept Uint8ClampedArray");
+
+test(function() {
+ var obj = new Uint8ClampedArray(8);
+ var arg = new Uint8ClampedArray([1, 2, 3]);
+ //set Uint8ClampedArray with offset
+ obj.set(arg, 1);
+ assert_equals(obj[1], arg[0], "The value of Uint8ClampedArray");
+}, "Check if the parameter of Uint8ClampedArray.set() accept Uint8ClampedArray and offset");
+
+test(function() {
+ var obj = new Uint8ClampedArray(3);
+ var arg = new Uint8ClampedArray([1, 2, 3]);
+ assert_throws(new RangeError(), function() {
+ obj.set(arg, 1);
+ });
+}, "Check if an exception is raised when the offset plus the length of the given array is out of range for the current array");
+
+</script>
diff --git a/tests/wpt/web-platform-tests/typedarrays/Uint8ClampedArray_subarray.html b/tests/wpt/web-platform-tests/typedarrays/Uint8ClampedArray_subarray.html
new file mode 100644
index 00000000000..3c72d853d93
--- /dev/null
+++ b/tests/wpt/web-platform-tests/typedarrays/Uint8ClampedArray_subarray.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Typed Arrays Test: Uint8ClampedArray subarray</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="http://www.khronos.org/registry/typedarray/specs/latest/#7.1">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+
+test(function() {
+ var arr = new Uint8ClampedArray([1, 2, 3, 4, 5, 6, 7, 8]);
+
+ test(function() {
+ var subarr = arr.subarray(2);
+ assert_true(subarr instanceof Uint8ClampedArray, "Returns Uint8ClampedArray");
+ assert_equals(subarr.length, 6, "The length of subarray");
+ assert_equals(subarr[0], arr[2], "The value of subarray");
+ }, "Check if a new Uint8ClampedArray is returned for the Uint8ClampedArray, referencing the elements at begin");
+
+ test(function() {
+ var subarr = arr.subarray(2, 6);
+ assert_equals(subarr.length, 4, "The length of subarray");
+ assert_equals(subarr[0], arr[2], "The value of subarray");
+ assert_equals(subarr[3], arr[5], "The value of subarray");
+ }, "Check if a new Uint8ClampedArray is returned for the Uint8ClampedArray, referencing the elements at begin to end");
+
+ test(function() {
+ var subarr = arr.subarray(2, 10);
+ assert_equals(subarr.length, 6, "The length of subarray");
+ assert_equals(subarr[0], arr[2], "The value of subarray");
+ assert_equals(subarr[5], arr[7], "The value of subarray");
+ }, "Check if the subarray range specified by the begin and end values is clamped to the valid index range for the current array");
+
+ test(function() {
+ var subarr = arr.subarray(2, -2);
+ assert_equals(subarr.length, 4, "The length of subarray");
+ subarr = arr.subarray(-2, -1);
+ assert_equals(subarr.length, 1, "The length of subarray");
+ }, "Check if it refers to an index from the end of the array when either begin or end is negative");
+
+ test(function() {
+ var subarr = arr.subarray(4, 2);
+ assert_equals(subarr.length, 0, "The length of subarray");
+ subarr = arr.subarray(-1, -2);
+ assert_equals(subarr.length, 0, "The length of subarray");
+ }, "Check if the length is clamped to zero when the computed length of the new Uint8ClampedArray is negative");
+});
+
+</script>
diff --git a/tests/wpt/web-platform-tests/typedarrays/constructors.html b/tests/wpt/web-platform-tests/typedarrays/constructors.html
new file mode 100644
index 00000000000..60e0dc8fe8d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/typedarrays/constructors.html
@@ -0,0 +1,48 @@
+<!doctype html>
+<title>Typed Array constructors</title>
+<link rel=author href=mailto:Ms2ger@gmail.com title=Ms2ger>
+<link rel=help href=https://www.khronos.org/registry/typedarray/specs/latest/#7>
+<link rel=help href=http://dev.w3.org/2006/webapi/WebIDL/#dfn-overload-resolution-algorithm>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+
+<div id=log></div>
+<script>
+var args = [
+ /* numbers */
+ [NaN, 0], [+Infinity, 0], [-Infinity, 0], [+0, 0], [-0, 0], // Step 2
+ [-0.4, 0], [-0.9, 0], [1.1, 1], [2.9, 2], // Step 3
+ [1, 1], [-0xF1000000, 0xF000000], // Step 4
+ /* strings */
+ ["1", 1], ["1e2", 100],
+ /* null, undefined, booleans */
+ [undefined, 0], [null, 0], [false, 0], [true, 1],
+ /* objects */
+ [{}, 0], [{ length: 2, 0: 0, 1: 0 }, 0], [[0, 0], 2]
+];
+var interfaces = [
+ "Int8Array", "Uint8Array", "Uint8ClampedArray", "Int16Array", "Uint16Array",
+ "Int32Array", "Uint32Array", "Float32Array", "Float64Array"
+];
+
+test(function() {
+ interfaces.concat(["ArrayBuffer", "DataView"]).forEach(function(i) {
+ test(function() {
+ // XXX The spec is wrong here.
+ assert_throws(new TypeError(), function() {
+ new window[i]();
+ });
+ }, "Constructing interface " + i + " with no arguments should throw.");
+ });
+ interfaces.forEach(function(i) {
+ args.forEach(function(arg, j) {
+ var input = arg[0], expected = arg[1];
+ test(function() {
+ var ta = new window[i](input);
+ assert_equals(ta.length, expected);
+ }, "The argument " + format_value(input) + " (" + j + ") should be interpreted as " +
+ expected + " for interface " + i + ".");
+ });
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/url/README.md b/tests/wpt/web-platform-tests/url/README.md
new file mode 100644
index 00000000000..68dfa7543ff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/url/README.md
@@ -0,0 +1,15 @@
+The test for browsers is `a-element.html`. The reusable format is `urltestdata.txt`, which
+is not documented in detail. Reverse engineering through `urltestparser.js` should not be
+too hard. Documentation welcome!
+
+[`annevk/url`](https://github.com/annevk/url) hosts some other files that might be of
+interest if you want to create additional tests.
+
+Similar to `a-element.html` it would be trivial to add more tests for other objects that
+expose links (e.g. URL and `<area>`). There's also room for enhancement and bits that
+require independent tests:
+
+* The encoding part of the URL parser
+* The state override part of the URL parser (setting individual properties of a URL)
+* Origin serialization
+* `application/x-www-form-urlencoded`
diff --git a/tests/wpt/web-platform-tests/url/a-element.html b/tests/wpt/web-platform-tests/url/a-element.html
new file mode 100644
index 00000000000..04abef6a206
--- /dev/null
+++ b/tests/wpt/web-platform-tests/url/a-element.html
@@ -0,0 +1,51 @@
+<!doctype html>
+<base id=base>
+<meta charset=utf-8>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=urltestparser.js></script>
+<div id=log></div>
+<script>
+var setup = async_test("Loading data…")
+setup.step(function() {
+ var request = new XMLHttpRequest()
+ request.open("GET", "urltestdata.txt")
+ request.send()
+ request.responseType = "text"
+ request.onload = setup.step_func(function() {
+ runURLTests(request.response);
+ setup.done()
+ })
+})
+
+function setBase(base) {
+ document.getElementById("base").href = base
+}
+
+function bURL(url, base) {
+ base = base || "about:blank"
+ setBase(base)
+ var a = document.createElement("a")
+ a.setAttribute("href", url)
+ return a
+}
+
+function runURLTests(raw) {
+ var urltests = URLTestParser(raw)
+ for(var i = 0, l = urltests.length; i < l; i++) {
+ var expected = urltests[i]
+ test(function() {
+ var url = bURL(expected.input, expected.base)
+ if(expected.protocol === ':' && url.protocol !== ':')
+ assert_unreached('Expected URL to fail parsing')
+ assert_equals(url.protocol, expected.protocol, "scheme")
+ assert_equals(url.hostname, expected.host, "host")
+ assert_equals(url.port, expected.port, "port")
+ assert_equals(url.pathname, expected.path, "path")
+ assert_equals(url.search, expected.search, "search")
+ assert_equals(url.hash, expected.hash, "hash")
+ assert_equals(url.href, expected.href, "href")
+ }, "Parsing: <" + expected.input + "> against <" + expected.base + ">")
+ }
+}
+</script>
diff --git a/tests/wpt/web-platform-tests/url/a-element.xhtml b/tests/wpt/web-platform-tests/url/a-element.xhtml
new file mode 100644
index 00000000000..dc8e154e307
--- /dev/null
+++ b/tests/wpt/web-platform-tests/url/a-element.xhtml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>URL Test</title>
+ <link rel="author" title="Intel" href="http://www.intel.com/" />
+ <link rel="help" href="http://www.w3.org/html/wg/drafts/html/CR/infrastructure.html#urls" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="urltestparser.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <script>
+ <![CDATA[
+ var setup = async_test("Loading data…")
+ setup.step(function() {
+ var request = new XMLHttpRequest()
+ request.open("GET", "urltestdata.txt")
+ request.send()
+ request.responseType = "text"
+ request.onload = setup.step_func(function() {
+ runURLTests(request.response);
+ setup.done()
+ })
+ })
+
+ function setBase(base) {
+ document.body.setAttributeNS("http://www.w3.org/XML/1998/namespace", "xml:base", base);
+ }
+
+ function bURL(url, base) {
+ base = base || "about:blank"
+ setBase(base)
+ var a = document.createElement("a")
+ a.setAttribute("href", url)
+ document.body.appendChild(a)
+ return a
+ }
+
+ function runURLTests(raw) {
+ var urltests = URLTestParser(raw)
+ for(var i = 0, l = urltests.length; i < l; i++) {
+ var expected = urltests[i]
+ test(function() {
+ var url = bURL(expected.input, expected.base)
+ if(expected.protocol === ':' && url.protocol !== ':')
+ assert_unreached('Expected URL to fail parsing')
+ assert_equals(url.protocol, expected.protocol, "scheme")
+ assert_equals(url.hostname, expected.host, "host")
+ assert_equals(url.port, expected.port, "port")
+ assert_equals(url.pathname, expected.path, "path")
+ assert_equals(url.search, expected.search, "search")
+ assert_equals(url.hash, expected.hash, "hash")
+ assert_equals(url.href, expected.href, "href")
+ }, "Parsing: <" + expected.input + "> against <" + expected.base + ">")
+ }
+ }
+ ]]>
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/url/interfaces.html b/tests/wpt/web-platform-tests/url/interfaces.html
new file mode 100644
index 00000000000..f40a1a04ac4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/url/interfaces.html
@@ -0,0 +1,81 @@
+<!doctype html>
+<title>URL IDL tests</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=/resources/WebIDLParser.js></script>
+<script src=/resources/idlharness.js></script>
+
+<h1>URL IDL tests</h1>
+<div id=log></div>
+
+<script type=text/plain>
+[Constructor(DOMString url, optional DOMString base = "about:blank"),
+ Exposed=Window,Worker]
+interface URL {
+ static DOMString domainToASCII(ScalarValueString domain);
+ static DOMString domainToUnicode(ScalarValueString domain);
+};
+URL implements URLUtils;
+
+[NoInterfaceObject]
+interface URLUtils {
+ stringifier attribute ScalarValueString href;
+ readonly attribute DOMString origin;
+
+ attribute ScalarValueString protocol;
+ attribute ScalarValueString username;
+ attribute ScalarValueString password;
+ attribute ScalarValueString host;
+ attribute ScalarValueString hostname;
+ attribute ScalarValueString port;
+ attribute ScalarValueString pathname;
+ attribute ScalarValueString search;
+ attribute URLSearchParams searchParams;
+ attribute ScalarValueString hash;
+};
+
+[NoInterfaceObject]
+interface URLUtilsReadOnly {
+ stringifier readonly attribute DOMString href;
+ readonly attribute DOMString origin;
+
+ readonly attribute DOMString protocol;
+ readonly attribute DOMString host;
+ readonly attribute DOMString hostname;
+ readonly attribute DOMString port;
+ readonly attribute DOMString pathname;
+ readonly attribute DOMString search;
+ readonly attribute DOMString hash;
+};
+interface URLSearchParams {
+ void append(ScalarValueString name, ScalarValueString value);
+ void delete(ScalarValueString name);
+ DOMString? get(ScalarValueString name);
+ sequence<DOMString> getAll(ScalarValueString name);
+ boolean has(ScalarValueString name);
+ void set(ScalarValueString name, ScalarValueString value);
+ stringifier;
+};
+typedef DOMString ScalarValueString;
+</script>
+<script>
+"use strict";
+var idlArray;
+setup(function() {
+ idlArray = new IdlArray();
+ [].forEach.call(document.querySelectorAll("script[type=text\\/plain]"), function(node) {
+ if (node.className == "untested") {
+ idlArray.add_untested_idls(node.textContent);
+ } else {
+ idlArray.add_idls(node.textContent);
+ }
+ });
+}, {explicit_done:true});
+window.onload = function() {
+ idlArray.add_objects({
+ URL: ['new URL("http://foo")']
+ });
+ idlArray.test();
+ done();
+};
+</script>
diff --git a/tests/wpt/web-platform-tests/url/urltestdata.txt b/tests/wpt/web-platform-tests/url/urltestdata.txt
new file mode 100644
index 00000000000..80afab6afd4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/url/urltestdata.txt
@@ -0,0 +1,341 @@
+# FORMAT NOT DOCUMENTED YET (parser is urltestparser.js)
+
+# Based on http://trac.webkit.org/browser/trunk/LayoutTests/fast/url/script-tests/segments.js
+http://example\t.\norg http://example.org/foo/bar s:http h:example.org p:/
+http://user:pass@foo:21/bar;par?b#c s:http u:user pass:pass h:foo port:21 p:/bar;par q:?b f:#c
+http:foo.com s:http h:example.org p:/foo/foo.com
+\t\s\s\s:foo.com\s\s\s\n s:http h:example.org p:/foo/:foo.com
+\sfoo.com\s\s s:http h:example.org p:/foo/foo.com
+a:\t\sfoo.com s:a p:\sfoo.com
+http://f:21/\sb\s?\sd\s#\se\s s:http h:f port:21 p:/%20b%20 q:?%20d%20 f:#\se
+http://f:/c s:http h:f p:/c
+http://f:0/c s:http h:f port:0 p:/c
+http://f:00000000000000/c s:http h:f port:0 p:/c
+http://f:00000000000000000000080/c s:http h:f p:/c
+http://f:b/c
+http://f:\s/c
+http://f:\n/c s:http h:f p:/c
+http://f:fifty-two/c
+http://f:999999/c s:http h:f port:999999 p:/c
+http://f:\s21\s/\sb\s?\sd\s#\se\s
+ s:http h:example.org p:/foo/bar
+\s\s\t s:http h:example.org p:/foo/bar
+:foo.com/ s:http h:example.org p:/foo/:foo.com/
+:foo.com\\ s:http h:example.org p:/foo/:foo.com/
+: s:http h:example.org p:/foo/:
+:a s:http h:example.org p:/foo/:a
+:/ s:http h:example.org p:/foo/:/
+:\\ s:http h:example.org p:/foo/:/
+:# s:http h:example.org p:/foo/: f:#
+\# s:http h:example.org p:/foo/bar f:#
+\#/ s:http h:example.org p:/foo/bar f:#/
+\#\\ s:http h:example.org p:/foo/bar f:#\\
+\#;? s:http h:example.org p:/foo/bar f:#;?
+? s:http h:example.org p:/foo/bar q:?
+/ s:http h:example.org p:/
+:23 s:http h:example.org p:/foo/:23
+/:23 s:http h:example.org p:/:23
+:: s:http h:example.org p:/foo/::
+::23 s:http h:example.org p:/foo/::23
+foo:// s:foo p://
+http://a:b@c:29/d s:http u:a pass:b h:c port:29 p:/d
+http::@c:29 s:http h:example.org p:/foo/:@c:29
+http://&a:foo(b]c@d:2/ s:http u:&a pass:foo(b]c h:d port:2 p:/
+http://::@c@d:2 s:http pass::%40c h:d port:2 p:/
+http://foo.com:b@d/ s:http u:foo.com pass:b h:d p:/
+http://foo.com/\\@ s:http h:foo.com p://@
+http:\\\\foo.com\\ s:http h:foo.com p:/
+http:\\\\a\\b:c\\d@foo.com\\ s:http h:a p:/b:c/d@foo.com/
+foo:/ s:foo p:/
+foo:/bar.com/ s:foo p:/bar.com/
+foo:///////// s:foo p://///////
+foo://///////bar.com/ s:foo p://///////bar.com/
+foo:////:///// s:foo p:////://///
+c:/foo s:c p:/foo
+//foo/bar s:http h:foo p:/bar
+http://foo/path;a??e#f#g s:http h:foo p:/path;a q:??e f:#f#g
+http://foo/abcd?efgh?ijkl s:http h:foo p:/abcd q:?efgh?ijkl
+http://foo/abcd#foo?bar s:http h:foo p:/abcd f:#foo?bar
+[61:24:74]:98 s:http h:example.org p:/foo/[61:24:74]:98
+http:[61:27]/:foo s:http h:example.org p:/foo/[61:27]/:foo
+http://[1::2]:3:4
+http://2001::1
+http://2001::1]
+http://2001::1]:80
+http://[2001::1] s:http h:[2001::1] p:/
+http://[2001::1]:80 s:http h:[2001::1] p:/
+http:/example.com/ s:http h:example.org p:/example.com/
+ftp:/example.com/ s:ftp h:example.com p:/
+https:/example.com/ s:https h:example.com p:/
+madeupscheme:/example.com/ s:madeupscheme p:/example.com/
+file:/example.com/ s:file p:/example.com/
+ftps:/example.com/ s:ftps p:/example.com/
+gopher:/example.com/ s:gopher h:example.com p:/
+ws:/example.com/ s:ws h:example.com p:/
+wss:/example.com/ s:wss h:example.com p:/
+data:/example.com/ s:data p:/example.com/
+javascript:/example.com/ s:javascript p:/example.com/
+mailto:/example.com/ s:mailto p:/example.com/
+http:example.com/ s:http h:example.org p:/foo/example.com/
+ftp:example.com/ s:ftp h:example.com p:/
+https:example.com/ s:https h:example.com p:/
+madeupscheme:example.com/ s:madeupscheme p:example.com/
+ftps:example.com/ s:ftps p:example.com/
+gopher:example.com/ s:gopher h:example.com p:/
+ws:example.com/ s:ws h:example.com p:/
+wss:example.com/ s:wss h:example.com p:/
+data:example.com/ s:data p:example.com/
+javascript:example.com/ s:javascript p:example.com/
+mailto:example.com/ s:mailto p:example.com/
+/a/b/c s:http h:example.org p:/a/b/c
+/a/\s/c s:http h:example.org p:/a/%20/c
+/a%2fc s:http h:example.org p:/a%2fc
+/a/%2f/c s:http h:example.org p:/a/%2f/c
+\#\u03B2 s:http h:example.org p:/foo/bar f:#\u03B2
+data:text/html,test#test s:data p:text/html,test f:#test
+
+# Based on http://trac.webkit.org/browser/trunk/LayoutTests/fast/url/file.html
+
+# Basic canonicalization, uppercase should be converted to lowercase
+file:c:\\foo\\bar.html file:///tmp/mock/path s:file p:/c:/foo/bar.html
+
+# Spaces should fail
+\s\sFile:c|////foo\\bar.html s:file p:/c:////foo/bar.html
+
+# This should fail
+C|/foo/bar s:file p:/C:/foo/bar
+
+# This should fail
+/C|\\foo\\bar s:file p:/C:/foo/bar
+//C|/foo/bar s:file p:/C:/foo/bar
+//server/file s:file h:server p:/file
+\\\\server\\file s:file h:server p:/file
+/\\server/file s:file h:server p:/file
+file:///foo/bar.txt s:file p:/foo/bar.txt
+file:///home/me s:file p:/home/me
+// s:file p:/
+/// s:file p:/
+///test s:file p:/test
+file://test s:file h:test p:/
+file://localhost s:file h:localhost p:/
+file://localhost/ s:file h:localhost p:/
+file://localhost/test s:file h:localhost p:/test
+test s:file p:/tmp/mock/test
+file:test s:file p:/tmp/mock/test
+
+# Based on http://trac.webkit.org/browser/trunk/LayoutTests/fast/url/script-tests/path.js
+http://example.com/././foo about:blank s:http h:example.com p:/foo
+http://example.com/./.foo s:http h:example.com p:/.foo
+http://example.com/foo/. s:http h:example.com p:/foo/
+http://example.com/foo/./ s:http h:example.com p:/foo/
+http://example.com/foo/bar/.. s:http h:example.com p:/foo/
+http://example.com/foo/bar/../ s:http h:example.com p:/foo/
+http://example.com/foo/..bar s:http h:example.com p:/foo/..bar
+http://example.com/foo/bar/../ton s:http h:example.com p:/foo/ton
+http://example.com/foo/bar/../ton/../../a s:http h:example.com p:/a
+http://example.com/foo/../../.. s:http h:example.com p:/
+http://example.com/foo/../../../ton s:http h:example.com p:/ton
+http://example.com/foo/%2e s:http h:example.com p:/foo/
+http://example.com/foo/%2e%2 s:http h:example.com p:/foo/%2e%2
+http://example.com/foo/%2e./%2e%2e/.%2e/%2e.bar s:http h:example.com p:/%2e.bar
+http://example.com////../.. s:http h:example.com p://
+http://example.com/foo/bar//../.. s:http h:example.com p:/foo/
+http://example.com/foo/bar//.. s:http h:example.com p:/foo/bar/
+http://example.com/foo s:http h:example.com p:/foo
+http://example.com/%20foo s:http h:example.com p:/%20foo
+http://example.com/foo% s:http h:example.com p:/foo%
+http://example.com/foo%2 s:http h:example.com p:/foo%2
+http://example.com/foo%2zbar s:http h:example.com p:/foo%2zbar
+http://example.com/foo%2\u00C2\u00A9zbar s:http h:example.com p:/foo%2%C3%82%C2%A9zbar
+http://example.com/foo%41%7a s:http h:example.com p:/foo%41%7a
+http://example.com/foo\t\u0091%91 s:http h:example.com p:/foo%C2%91%91
+http://example.com/foo%00%51 s:http h:example.com p:/foo%00%51
+http://example.com/(%28:%3A%29) s:http h:example.com p:/(%28:%3A%29)
+http://example.com/%3A%3a%3C%3c s:http h:example.com p:/%3A%3a%3C%3c
+http://example.com/foo\tbar s:http h:example.com p:/foobar
+http://example.com\\\\foo\\\\bar s:http h:example.com p://foo//bar
+http://example.com/%7Ffp3%3Eju%3Dduvgw%3Dd s:http h:example.com p:/%7Ffp3%3Eju%3Dduvgw%3Dd
+http://example.com/@asdf%40 s:http h:example.com p:/@asdf%40
+http://example.com/\u4F60\u597D\u4F60\u597D s:http h:example.com p:/%E4%BD%A0%E5%A5%BD%E4%BD%A0%E5%A5%BD
+http://example.com/\u2025/foo s:http h:example.com p:/%E2%80%A5/foo
+http://example.com/\uFEFF/foo s:http h:example.com p:/%EF%BB%BF/foo
+http://example.com/\u202E/foo/\u202D/bar s:http h:example.com p:/%E2%80%AE/foo/%E2%80%AD/bar
+
+# Based on http://trac.webkit.org/browser/trunk/LayoutTests/fast/url/script-tests/relative.js
+http://www.google.com/foo?bar=baz# about:blank s:http h:www.google.com p:/foo q:?bar=baz f:#
+http://www.google.com/foo?bar=baz#\s\u00BB s:http h:www.google.com p:/foo q:?bar=baz f:#\s\u00BB
+data:test#\s\u00BB s:data p:test f:#\s\u00BB
+http://[www.google.com]/
+http://www.google.com s:http h:www.google.com p:/
+http://192.0x00A80001 s:http h:192.168.0.1 p:/
+http://www/foo%2Ehtml s:http h:www p:/foo%2Ehtml
+http://www/foo/%2E/html s:http h:www p:/foo/html
+http://user:pass@/
+http://%25DOMAIN:foobar@foodomain.com/ s:http u:%25DOMAIN pass:foobar h:foodomain.com p:/
+http:\\\\www.google.com\\foo s:http h:www.google.com p:/foo
+http://foo:80/ s:http h:foo p:/
+http://foo:81/ s:http h:foo port:81 p:/
+httpa://foo:80/ s:httpa p://foo:80/
+http://foo:-80/
+https://foo:443/ s:https h:foo p:/
+https://foo:80/ s:https h:foo port:80 p:/
+ftp://foo:21/ s:ftp h:foo p:/
+ftp://foo:80/ s:ftp h:foo port:80 p:/
+gopher://foo:70/ s:gopher h:foo p:/
+gopher://foo:443/ s:gopher h:foo port:443 p:/
+ws://foo:80/ s:ws h:foo p:/
+ws://foo:81/ s:ws h:foo port:81 p:/
+ws://foo:443/ s:ws h:foo port:443 p:/
+ws://foo:815/ s:ws h:foo port:815 p:/
+wss://foo:80/ s:wss h:foo port:80 p:/
+wss://foo:81/ s:wss h:foo port:81 p:/
+wss://foo:443/ s:wss h:foo p:/
+wss://foo:815/ s:wss h:foo port:815 p:/
+http:/example.com/ s:http h:example.com p:/
+ftp:/example.com/ s:ftp h:example.com p:/
+https:/example.com/ s:https h:example.com p:/
+madeupscheme:/example.com/ s:madeupscheme p:/example.com/
+file:/example.com/ s:file p:/example.com/
+ftps:/example.com/ s:ftps p:/example.com/
+gopher:/example.com/ s:gopher h:example.com p:/
+ws:/example.com/ s:ws h:example.com p:/
+wss:/example.com/ s:wss h:example.com p:/
+data:/example.com/ s:data p:/example.com/
+javascript:/example.com/ s:javascript p:/example.com/
+mailto:/example.com/ s:mailto p:/example.com/
+http:example.com/ s:http h:example.com p:/
+ftp:example.com/ s:ftp h:example.com p:/
+https:example.com/ s:https h:example.com p:/
+madeupscheme:example.com/ s:madeupscheme p:example.com/
+ftps:example.com/ s:ftps p:example.com/
+gopher:example.com/ s:gopher h:example.com p:/
+ws:example.com/ s:ws h:example.com p:/
+wss:example.com/ s:wss h:example.com p:/
+data:example.com/ s:data p:example.com/
+javascript:example.com/ s:javascript p:example.com/
+mailto:example.com/ s:mailto p:example.com/
+
+# Based on http://trac.webkit.org/browser/trunk/LayoutTests/fast/url/segments-userinfo-vs-host.html
+http:@www.example.com about:blank s:http h:www.example.com p:/
+http:/@www.example.com s:http h:www.example.com p:/
+http://@www.example.com s:http h:www.example.com p:/
+http:a:b@www.example.com s:http u:a pass:b h:www.example.com p:/
+http:/a:b@www.example.com s:http u:a pass:b h:www.example.com p:/
+http://a:b@www.example.com s:http u:a pass:b h:www.example.com p:/
+http://@pple.com s:http h:pple.com p:/
+http::b@www.example.com s:http pass:b h:www.example.com p:/
+http:/:b@www.example.com s:http pass:b h:www.example.com p:/
+http://:b@www.example.com s:http pass:b h:www.example.com p:/
+http:/:@/www.example.com
+http://user@/www.example.com
+http:@/www.example.com
+http:/@/www.example.com
+http://@/www.example.com
+https:@/www.example.com
+http:a:b@/www.example.com
+http:/a:b@/www.example.com
+http://a:b@/www.example.com
+http::@/www.example.com
+http:a:@www.example.com s:http u:a pass: h:www.example.com p:/
+http:/a:@www.example.com s:http u:a pass: h:www.example.com p:/
+http://a:@www.example.com s:http u:a pass: h:www.example.com p:/
+http://www.@pple.com s:http u:www. h:pple.com p:/
+http:@:www.example.com
+http:/@:www.example.com
+http://@:www.example.com
+http://:@www.example.com s:http pass: h:www.example.com p:/
+
+#Others
+/ http://www.example.com/test s:http h:www.example.com p:/
+/test.txt s:http h:www.example.com p:/test.txt
+. s:http h:www.example.com p:/
+.. s:http h:www.example.com p:/
+test.txt s:http h:www.example.com p:/test.txt
+./test.txt s:http h:www.example.com p:/test.txt
+../test.txt s:http h:www.example.com p:/test.txt
+../aaa/test.txt s:http h:www.example.com p:/aaa/test.txt
+../../test.txt s:http h:www.example.com p:/test.txt
+\u4E2D/test.txt s:http h:www.example.com p:/%E4%B8%AD/test.txt
+http://www.example2.com s:http h:www.example2.com p:/
+//www.example2.com s:http h:www.example2.com p:/
+
+# Based on http://trac.webkit.org/browser/trunk/LayoutTests/fast/url/host.html
+
+# Basic canonicalization, uppercase should be converted to lowercase
+http://ExAmPlE.CoM http://other.com/ s:http p:/ h:example.com
+
+# Spaces should fail
+http://example\sexample.com
+
+# This should fail
+http://Goo%20\sgoo%7C|.com
+
+# U+3000 is mapped to U+0020 (space) which is disallowed
+http://GOO\u00a0\u3000goo.com
+
+# Other types of space (no-break, zero-width, zero-width-no-break) are
+# name-prepped away to nothing.
+# U+200B, U+2060, and U+FEFF, are ignored
+http://GOO\u200b\u2060\ufeffgoo.com s:http p:/ h:googoo.com
+
+# Ideographic full stop (full-width period for Chinese, etc.) should be
+# treated as a dot.
+# U+3002 is mapped to U+002E (dot)
+http://www.foo\u3002bar.com s:http p:/ h:www.foo.bar.com
+
+# Invalid unicode characters should fail...
+# U+FDD0 is disallowed; %ef%b7%90 is U+FDD0
+http://\ufdd0zyx.com
+
+# ...This is the same as previous but escaped.
+http://%ef%b7%90zyx.com
+
+# Test name prepping, fullwidth input should be converted to ASCII and NOT
+# IDN-ized. This is "Go" in fullwidth UTF-8/UTF-16.
+http://\uff27\uff4f.com s:http p:/ h:go.com
+
+# URL spec forbids the following.
+# https://www.w3.org/Bugs/Public/show_bug.cgi?id=24257
+http://\uff05\uff14\uff11.com
+http://%ef%bc%85%ef%bc%94%ef%bc%91.com
+
+# ...%00 in fullwidth should fail (also as escaped UTF-8 input)
+http://\uff05\uff10\uff10.com
+http://%ef%bc%85%ef%bc%90%ef%bc%90.com
+
+# Basic IDN support, UTF-8 and UTF-16 input should be converted to IDN
+http://\u4f60\u597d\u4f60\u597d s:http p:/ h:xn--6qqa088eba
+
+# Invalid escaped characters should fail and the percents should be
+# escaped. https://www.w3.org/Bugs/Public/show_bug.cgi?id=24191
+http://%zz%66%a.com
+
+# If we get an invalid character that has been escaped.
+http://%25
+http://hello%00
+
+# Escaped numbers should be treated like IP addresses if they are.
+# No special handling for IPv4 or IPv4-like URLs
+http://%30%78%63%30%2e%30%32%35%30.01 s:http p:/ h:192.168.0.1
+http://%30%78%63%30%2e%30%32%35%30.01%2e s:http p:/ h:0xc0.0250.01.
+http://192.168.0.257
+
+# Invalid escaping should trigger the regular host error handling.
+http://%3g%78%63%30%2e%30%32%35%30%2E.01
+
+# Something that isn't exactly an IP should get treated as a host and
+# spaces escaped.
+http://192.168.0.1\shello
+
+# Fullwidth and escaped UTF-8 fullwidth should still be treated as IP.
+# These are "0Xc0.0250.01" in fullwidth.
+http://\uff10\uff38\uff43\uff10\uff0e\uff10\uff12\uff15\uff10\uff0e\uff10\uff11 s:http p:/ h:192.168.0.1
+
+# Broken IPv6
+http://[google.com]
+
+# Misc Unicode
+http://foo:\uD83D\uDCA9@example.com/bar s:http h:example.com p:/bar u:foo pass:%F0%9F%92%A9
+
+# resolving a relative reference against an unknown scheme results in an error
+x test:test
diff --git a/tests/wpt/web-platform-tests/url/urltestparser.js b/tests/wpt/web-platform-tests/url/urltestparser.js
new file mode 100644
index 00000000000..8a027cc73e7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/url/urltestparser.js
@@ -0,0 +1,79 @@
+function URLTestParser(input) {
+ var relativeSchemes = ["ftp", "file", "gopher", "http", "https", "ws", "wss"],
+ tokenMap = { "\\": "\\", "#": "#", n: "\n", r: "\r", s: " ", t: "\t", f: "\f" }
+ resultMap = { s: "scheme", u: "username", pass: "password", h: "host", port: "port", p: "path", q: "query", f: "fragment" },
+ results = []
+ function Test() {
+ this.input = ""
+ this.base = ""
+ this.scheme = ""
+ this.username = ""
+ this.password = null
+ this.host = ""
+ this.port = ""
+ this.path = ""
+ this.query = ""
+ this.fragment = ""
+ Object.defineProperties(this, {
+ "href": { get: function() {
+ return !this.scheme ? this.input : this.protocol + (
+ relativeSchemes.indexOf(this.scheme) != -1 ? "//" + (
+ ("" != this.username || null != this.password) ? this.username + (
+ null != this.password ? ":" + this.password : ""
+ ) + "@" : ""
+ ) + this.host : ""
+ ) + (this.port ? ":" + this.port : "") + this.path + this.query + this.fragment
+ } },
+ "protocol": { get: function() { return this.scheme + ":" } },
+ "search": { get: function() { return "?" == this.query ? "" : this.query } },
+ "hash": { get: function() { return "#" == this.fragment ? "" : this.fragment } }
+ })
+ }
+ function normalize(input) {
+ var output = ""
+ for(var i = 0, l = input.length; i < l; i++) {
+ var c = input[i]
+ if(c == "\\") {
+ var nextC = input[++i]
+ if(tokenMap.hasOwnProperty(nextC)) {
+ output += tokenMap[nextC]
+ } else if(nextC == "u") {
+ output += String.fromCharCode(parseInt(input[++i] + input[++i] + input[++i] + input[++i], 16))
+ } else {
+ throw new Error("Input is invalid.")
+ }
+ } else {
+ output += c
+ }
+ }
+ return output
+ }
+ var lines = input.split("\n")
+ for(var i = 0, l = lines.length; i < l; i++) {
+ var line = lines[i]
+ if(line === "" || line.indexOf("#", 0) === 0) {
+ continue
+ }
+ var pieces = line.split(" "),
+ result = new Test()
+ result.input = normalize(pieces.shift())
+ var base = pieces.shift()
+ if(base === "" || base === undefined) {
+ result.base = results[results.length - 1].base
+ } else {
+ result.base = normalize(base)
+ }
+ for(var ii = 0, ll = pieces.length; ii < ll; ii++) {
+ var piece = pieces[ii]
+ if(piece.indexOf("#", 0) === 0) {
+ continue
+ }
+ var subpieces = piece.split(":"),
+ token = subpieces.shift()
+ value = subpieces.join(":")
+ result[resultMap[token]] = normalize(value)
+ }
+ results.push(result)
+ }
+ return results
+}
diff --git a/tests/wpt/web-platform-tests/user-timing/idlharness.html b/tests/wpt/web-platform-tests/user-timing/idlharness.html
new file mode 100644
index 00000000000..3ec7e1a17cc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/user-timing/idlharness.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>User Timing IDL tests</title>
+<link rel="author" title="W3C" href="http://www.w3.org/" />
+<link rel="help" href="http://www.w3.org/TR/user-timing/#extensions-performance-interface"/>
+<link rel="help" href="http://www.w3.org/TR/user-timing/#performancemark"/>
+<link rel="help" href="http://www.w3.org/TR/user-timing/#performancemeasure"/>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/WebIDLParser.js"></script>
+<script src="/resources/idlharness.js"></script>
+</head>
+<body>
+<h1>User Timing IDL tests</h1>
+<div id="log"></div>
+
+<pre id='untested_idl' style='display:none'>
+interface Performance {
+};
+
+interface PerformanceEntry {
+};
+</pre>
+
+<pre id='idl'>
+partial interface Performance {
+ void mark(DOMString markName);
+ void clearMarks(optional DOMString markName);
+
+ void measure(DOMString measureName, optional DOMString startMark, optional DOMString endMark);
+ void clearMeasures(optional DOMString measureName);
+};
+
+interface PerformanceMark : PerformanceEntry {
+};
+
+interface PerformanceMeasure : PerformanceEntry {
+};
+
+</pre>
+
+<script>
+
+(function() {
+ var idl_array = new IdlArray();
+
+ idl_array.add_untested_idls(document.getElementById("untested_idl").textContent);
+ idl_array.add_idls(document.getElementById("idl").textContent);
+
+ idl_array.add_objects({Performance: ["window.performance"]});
+
+ idl_array.test();
+})();
+
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/user-timing/resources/webperftestharness.js b/tests/wpt/web-platform-tests/user-timing/resources/webperftestharness.js
new file mode 100644
index 00000000000..750946dde20
--- /dev/null
+++ b/tests/wpt/web-platform-tests/user-timing/resources/webperftestharness.js
@@ -0,0 +1,155 @@
+/*
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+ */
+
+//
+// Helper Functions for NavigationTiming W3C tests
+//
+
+var performanceNamespace = window.performance;
+var timingAttributes = [
+ 'connectEnd',
+ 'connectStart',
+ 'domComplete',
+ 'domContentLoadedEventEnd',
+ 'domContentLoadedEventStart',
+ 'domInteractive',
+ 'domLoading',
+ 'domainLookupEnd',
+ 'domainLookupStart',
+ 'fetchStart',
+ 'loadEventEnd',
+ 'loadEventStart',
+ 'navigationStart',
+ 'redirectEnd',
+ 'redirectStart',
+ 'requestStart',
+ 'responseEnd',
+ 'responseStart',
+ 'unloadEventEnd',
+ 'unloadEventStart'
+];
+
+var namespace_check = false;
+
+//
+// All test() functions in the WebPerf test suite should use wp_test() instead.
+//
+// wp_test() validates the window.performance namespace exists prior to running tests and
+// immediately shows a single failure if it does not.
+//
+
+function wp_test(func, msg, properties)
+{
+ // only run the namespace check once
+ if (!namespace_check)
+ {
+ namespace_check = true;
+
+ if (performanceNamespace === undefined || performanceNamespace == null)
+ {
+ // show a single error that window.performance is undefined
+ test(function() { assert_true(performanceNamespace !== undefined && performanceNamespace != null, "window.performance is defined and not null"); }, "window.performance is defined and not null.", {author:"W3C http://www.w3.org/",help:"http://www.w3.org/TR/navigation-timing/#sec-window.performance-attribute",assert:"The window.performance attribute provides a hosting area for performance related attributes. "});
+ }
+ }
+
+ test(func, msg, properties);
+}
+
+function test_namespace(child_name, skip_root)
+{
+ if (skip_root === undefined) {
+ var msg = 'window.performance is defined';
+ wp_test(function () { assert_true(performanceNamespace !== undefined, msg); }, msg,{author:"W3C http://www.w3.org/",help:"http://www.w3.org/TR/navigation-timing/#sec-window.performance-attribute",assert:"The window.performance attribute provides a hosting area for performance related attributes. "});
+ }
+
+ if (child_name !== undefined) {
+ var msg2 = 'window.performance.' + child_name + ' is defined';
+ wp_test(function() { assert_true(performanceNamespace[child_name] !== undefined, msg2); }, msg2,{author:"W3C http://www.w3.org/",help:"http://www.w3.org/TR/navigation-timing/#sec-window.performance-attribute",assert:"The window.performance attribute provides a hosting area for performance related attributes. "});
+ }
+}
+
+function test_attribute_exists(parent_name, attribute_name, properties)
+{
+ var msg = 'window.performance.' + parent_name + '.' + attribute_name + ' is defined.';
+ wp_test(function() { assert_true(performanceNamespace[parent_name][attribute_name] !== undefined, msg); }, msg, properties);
+}
+
+function test_enum(parent_name, enum_name, value, properties)
+{
+ var msg = 'window.performance.' + parent_name + '.' + enum_name + ' is defined.';
+ wp_test(function() { assert_true(performanceNamespace[parent_name][enum_name] !== undefined, msg); }, msg, properties);
+
+ msg = 'window.performance.' + parent_name + '.' + enum_name + ' = ' + value;
+ wp_test(function() { assert_equals(performanceNamespace[parent_name][enum_name], value, msg); }, msg, properties);
+}
+
+function test_timing_order(attribute_name, greater_than_attribute, properties)
+{
+ // ensure it's not 0 first
+ var msg = "window.performance.timing." + attribute_name + " > 0";
+ wp_test(function() { assert_true(performanceNamespace.timing[attribute_name] > 0, msg); }, msg, properties);
+
+ // ensure it's in the right order
+ msg = "window.performance.timing." + attribute_name + " >= window.performance.timing." + greater_than_attribute;
+ wp_test(function() { assert_true(performanceNamespace.timing[attribute_name] >= performanceNamespace.timing[greater_than_attribute], msg); }, msg, properties);
+}
+
+function test_timing_greater_than(attribute_name, greater_than, properties)
+{
+ var msg = "window.performance.timing." + attribute_name + " > " + greater_than;
+ test_greater_than(performanceNamespace.timing[attribute_name], greater_than, msg, properties);
+}
+
+function test_timing_equals(attribute_name, equals, msg, properties)
+{
+ var test_msg = msg || "window.performance.timing." + attribute_name + " == " + equals;
+ test_equals(performanceNamespace.timing[attribute_name], equals, test_msg, properties);
+}
+
+//
+// Non-test related helper functions
+//
+
+function sleep_milliseconds(n)
+{
+ var start = new Date().getTime();
+ while (true) {
+ if ((new Date().getTime() - start) >= n) break;
+ }
+}
+
+//
+// Common helper functions
+//
+
+function test_true(value, msg, properties)
+{
+ wp_test(function () { assert_true(value, msg); }, msg, properties);
+}
+
+function test_equals(value, equals, msg, properties)
+{
+ wp_test(function () { assert_equals(value, equals, msg); }, msg, properties);
+}
+
+function test_greater_than(value, greater_than, msg, properties)
+{
+ wp_test(function () { assert_true(value > greater_than, msg); }, msg, properties);
+}
+
+function test_greater_or_equals(value, greater_than, msg, properties)
+{
+ wp_test(function () { assert_true(value >= greater_than, msg); }, msg, properties);
+}
+
+function test_not_equals(value, notequals, msg, properties)
+{
+ wp_test(function() { assert_true(value !== notequals, msg); }, msg, properties);
+}
diff --git a/tests/wpt/web-platform-tests/user-timing/resources/webperftestharnessextension.js b/tests/wpt/web-platform-tests/user-timing/resources/webperftestharnessextension.js
new file mode 100644
index 00000000000..579ee9096aa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/user-timing/resources/webperftestharnessextension.js
@@ -0,0 +1,199 @@
+/*
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+ */
+
+var mark_names = [
+ '',
+ '1',
+ 'abc',
+];
+
+var measures = [
+ [''],
+ ['2', 1],
+ ['aaa', 'navigationStart', ''],
+];
+
+function test_method_exists(method, method_name, properties)
+{
+ var msg;
+ if (typeof method === 'function')
+ msg = 'performance.' + method.name + ' is supported!';
+ else
+ msg = 'performance.' + method_name + ' is supported!';
+ wp_test(function() { assert_true(typeof method === 'function', msg); }, msg, properties);
+}
+
+function test_method_throw_exception(func_str, exception, msg)
+{
+ var exception_name = typeof exception === "object" ? exception.name : exception;
+ var msg = 'Invocation of ' + func_str + ' should throw ' + exception_name + ' Exception.';
+ wp_test(function() { assert_throws(exception, function() {eval(func_str)}, msg); }, msg);
+}
+
+function test_noless_than(value, greater_than, msg, properties)
+{
+ wp_test(function () { assert_true(value >= greater_than, msg); }, msg, properties);
+}
+
+function test_fail(msg, properties)
+{
+ wp_test(function() { assert_unreached(); }, msg, properties);
+}
+
+function test_resource_entries(entries, expected_entries)
+{
+ // This is slightly convoluted so that we can sort the output.
+ var actual_entries = {};
+ var origin = window.location.protocol + "//" + window.location.host;
+
+ for (var i = 0; i < entries.length; ++i) {
+ var entry = entries[i];
+ var found = false;
+ for (var expected_entry in expected_entries) {
+ if (entry.name == origin + expected_entry) {
+ found = true;
+ if (expected_entry in actual_entries) {
+ test_fail(expected_entry + ' is not expected to have duplicate entries');
+ }
+ actual_entries[expected_entry] = entry;
+ break;
+ }
+ }
+ if (!found) {
+ test_fail(entries[i].name + ' is not expected to be in the Resource Timing buffer');
+ }
+ }
+
+ sorted_urls = [];
+ for (var i in actual_entries) {
+ sorted_urls.push(i);
+ }
+ sorted_urls.sort();
+ for (var i in sorted_urls) {
+ var url = sorted_urls[i];
+ test_equals(actual_entries[url].initiatorType,
+ expected_entries[url],
+ origin + url + ' is expected to have initiatorType ' + expected_entries[url]);
+ }
+ for (var j in expected_entries) {
+ if (!(j in actual_entries)) {
+ test_fail(origin + j + ' is expected to be in the Resource Timing buffer');
+ }
+ }
+}
+function performance_entrylist_checker(type)
+{
+ var entryType = type;
+
+ function entry_check(entry, expectedNames)
+ {
+ var msg = 'Entry \"' + entry.name + '\" should be one that we have set.';
+ wp_test(function() { assert_in_array(entry.name, expectedNames, msg); }, msg);
+ test_equals(entry.entryType, entryType, 'entryType should be \"' + entryType + '\".');
+ if (type === "measure") {
+ test_true(isFinite(entry.startTime), 'startTime should be a number.');
+ test_true(isFinite(entry.duration), 'duration should be a number.');
+ } else if (type === "mark") {
+ test_greater_than(entry.startTime, 0, 'startTime should greater than 0.');
+ test_equals(entry.duration, 0, 'duration of mark should be 0.');
+ }
+ }
+
+ function entrylist_order_check(entryList)
+ {
+ var inOrder = true;
+ for (var i = 0; i < entryList.length - 1; ++i)
+ {
+ if (entryList[i + 1].startTime < entryList[i].startTime) {
+ inOrder = false;
+ break;
+ }
+ }
+ return inOrder;
+ }
+
+ function entrylist_check(entryList, expectedLength, expectedNames)
+ {
+ test_equals(entryList.length, expectedLength, 'There should be ' + expectedLength + ' entries.');
+ test_true(entrylist_order_check(entryList), 'Entries in entrylist should be in order.');
+ for (var i = 0; i < entryList.length; ++i)
+ {
+ entry_check(entryList[i], expectedNames);
+ }
+ }
+
+ return{"entrylist_check":entrylist_check};
+}
+
+function PerformanceContext(context)
+{
+ this.performanceContext = context;
+}
+
+PerformanceContext.prototype =
+{
+
+ initialMeasures: function(item, index, array)
+ {
+ this.performanceContext.measure.apply(this.performanceContext, item);
+ },
+
+ mark: function()
+ {
+ this.performanceContext.mark.apply(this.performanceContext, arguments);
+ },
+
+ measure: function()
+ {
+ this.performanceContext.measure.apply(this.performanceContext, arguments);
+ },
+
+ clearMarks: function()
+ {
+ this.performanceContext.clearMarks.apply(this.performanceContext, arguments);
+ },
+
+ clearMeasures: function()
+ {
+ this.performanceContext.clearMeasures.apply(this.performanceContext, arguments);
+
+ },
+
+ getEntries: function()
+ {
+ return this.performanceContext.getEntries.apply(this.performanceContext, arguments);
+ },
+
+ getEntriesByType: function()
+ {
+ return this.performanceContext.getEntriesByType.apply(this.performanceContext, arguments);
+ },
+
+ getEntriesByName: function()
+ {
+ return this.performanceContext.getEntriesByName.apply(this.performanceContext, arguments);
+ },
+
+ setResourceTimingBufferSize: function()
+ {
+ return this.performanceContext.setResourceTimingBufferSize.apply(this.performanceContext, arguments);
+ },
+
+ registerResourceTimingBufferFullCallback: function(func)
+ {
+ this.performanceContext.onresourcetimingbufferfull = func;
+ },
+
+ clearResourceTimings: function()
+ {
+ this.performanceContext.clearResourceTimings.apply(this.performanceContext, arguments);
+ }
+
+};
diff --git a/tests/wpt/web-platform-tests/user-timing/test_user_timing_clear_marks.html b/tests/wpt/web-platform-tests/user-timing/test_user_timing_clear_marks.html
new file mode 100644
index 00000000000..3056ddbb408
--- /dev/null
+++ b/tests/wpt/web-platform-tests/user-timing/test_user_timing_clear_marks.html
@@ -0,0 +1,134 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="UTF-8" />
+ <title>window.performance User Timing clearMarks() method is working properly</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://www.w3.org/TR/user-timing/#dom-performance-clearmarks"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="resources/webperftestharness.js"></script>
+
+ <script type="text/javascript">
+ // test marks
+ var markName1 = "mark1";
+ var markName2 = "mark2";
+ var markName3 = "markUndefined";
+ var markTestDelay = 200;
+ var entries;
+ var pass;
+
+ setup({explicit_done: true});
+
+ test_namespace();
+
+ function onload_test()
+ {
+ // test for existance of User Timing and Performance Timeline interface
+ if (window.performance.mark == undefined ||
+ window.performance.clearMarks == undefined ||
+ window.performance.measure == undefined ||
+ window.performance.clearMeasures == undefined ||
+ window.performance.getEntriesByName == undefined ||
+ window.performance.getEntriesByType == undefined ||
+ window.performance.getEntries == undefined)
+ {
+ test_true(false,
+ "The User Timing and Performance Timeline interfaces, which are required for this test, " +
+ "are defined.");
+
+ done();
+ }
+ else
+ {
+ // create a mark using the test delay; the mark's value should be equivalent to the loadEventStart
+ // navigation timing attribute plus the test delay
+ setTimeout(mark_test_cb, markTestDelay);
+ }
+ }
+
+ function mark_test_cb()
+ {
+ // create the test marks; only create "mark1" and "mark2", "markUndefined" is a non-existent mark
+ window.performance.mark(markName1);
+ window.performance.mark(markName2);
+
+ // test that two marks have been created
+ entries = window.performance.getEntriesByType("mark");
+ test_equals(entries.length, 2, "Two marks have been created for this test.");
+
+ // clear non-existent mark
+ window.performance.clearMarks(markName3);
+
+ // test that "mark1" still exists
+ entries = window.performance.getEntriesByName(markName1);
+ test_true(entries[0].name == markName1,
+ "After a call to window.performance.clearMarks(\"" + markName3 + "\"), where \"" + markName3 +
+ "\" is a non-existent mark, window.performance.getEntriesByName(\"" + markName1 + "\") " +
+ "returns an object containing the \"" + markName1 + "\" mark.");
+
+ // test that "mark2" still exists
+ entries = window.performance.getEntriesByName(markName2);
+ test_true(entries[0].name == markName2,
+ "After a call to window.performance.clearMarks(\"" + markName3 + "\"), where \"" + markName3 +
+ "\" is a non-existent mark, window.performance.getEntriesByName(\"" + markName2 + "\") " +
+ "returns an object containing the \"" + markName2 + "\" mark.");
+
+ // clear existent mark
+ window.performance.clearMarks(markName1);
+
+ // test that "mark1" was cleared
+ entries = window.performance.getEntriesByName(markName1);
+ pass = true;
+ for (var i in entries)
+ {
+ pass = false;
+ }
+ test_true(pass,
+ "After a call to window.performance.clearMarks(\"" + markName1 + "\"), " +
+ "window.performance.getEntriesByName(\"" + markName1 + "\") returns an empty object.");
+
+ // test that "mark2" still exists
+ entries = window.performance.getEntriesByName(markName2);
+ test_true(entries[0].name == markName2,
+ "After a call to window.performance.clearMarks(\"" + markName1 + "\"), " +
+ "window.performance.getEntriesByName(\"" + markName2 + "\") returns an object containing the " +
+ "\"" + markName2 + "\" mark.");
+
+ // clear all marks
+ window.performance.clearMarks();
+
+ // test that all marks were cleared
+ entries = window.performance.getEntriesByType("mark");
+ pass = true;
+ for (var i in entries)
+ {
+ pass = false;
+ }
+ test_true(pass,
+ "After a call to window.performance.clearMarks(), " +
+ "window.performance.getEntriesByType(\"mark\") returns an empty object.");
+
+ done();
+ }
+ </script>
+ </head>
+ <body onload="onload_test();">
+ <h1>Description</h1>
+ <p>This test validates that the performance.clearMarks() method is working properly. This test creates the
+ following marks to test this method:
+ <ul>
+ <li>"mark1"</li>
+ <li>"mark2"</li>
+ </ul>
+ After creating each mark, performance.clearMarks() is called three times. First, it is provided with a name
+ of "markUndefined", a non-existent mark, which shouldn't change the state of the Performance Timeline. Next,
+ it is provided with a name of "mark2", after which, this mark should no longer be present in the Performance
+ Timeline. Finally, performance.clearMarks() is called without any name provided. After this call, no marks
+ should be present in the Performance Timeline. The state of the Performance Timeline is tested with the
+ performance.getEntriesByType() and performance.getEntries() methods.
+ </p>
+
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/user-timing/test_user_timing_clear_measures.html b/tests/wpt/web-platform-tests/user-timing/test_user_timing_clear_measures.html
new file mode 100644
index 00000000000..68af877e799
--- /dev/null
+++ b/tests/wpt/web-platform-tests/user-timing/test_user_timing_clear_measures.html
@@ -0,0 +1,136 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="UTF-8" />
+ <title>window.performance User Timing clearMeasures() method is working properly</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://www.w3.org/TR/user-timing/#dom-performance-clearmeasures"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="resources/webperftestharness.js"></script>
+
+ <script type="text/javascript">
+ // test measures
+ var measureName1 = "measure1";
+ var measureName2 = "measure2";
+ var measureName3 = "measureUndefined";
+ var measureTestDelay = 200;
+ var measureEntryNames;
+ var entries;
+
+ setup({explicit_done: true});
+
+ test_namespace();
+
+ function onload_test()
+ {
+ // test for existance of User Timing and Performance Timeline interface
+ if (window.performance.mark == undefined ||
+ window.performance.clearMarks == undefined ||
+ window.performance.measure == undefined ||
+ window.performance.clearMeasures == undefined ||
+ window.performance.getEntriesByName == undefined ||
+ window.performance.getEntriesByType == undefined ||
+ window.performance.getEntries == undefined)
+ {
+ test_true(false,
+ "The User Timing and Performance Timeline interfaces, which are required for this test, " +
+ "are defined.");
+
+ done();
+ }
+ else
+ {
+ // create measures using the test delay
+ setTimeout(measure_test_cb, measureTestDelay);
+ }
+ }
+
+ function measure_test_cb()
+ {
+ // create the test measures; only create "measure1" and "measure2", "measureUndefined" is a non-existent
+ // measure; give "measure1" a startMark of "navigationStart" and "measure2" a startMark of
+ // "responseEnd", this way, "measure1" always come first in a PerformanceEntryList returned from a
+ // Performance Timeline accessor
+ window.performance.measure(measureName1, "navigationStart");
+ window.performance.measure(measureName2, "responseEnd");
+
+ // test that two measures have been created
+ entries = window.performance.getEntriesByType("measure");
+ test_equals(entries.length, 2, "Two measures have been created for this test.");
+
+ // clear non-existent measure
+ window.performance.clearMeasures(measureName3);
+
+ // test that "measure1" still exists
+ entries = window.performance.getEntriesByName(measureName1);
+ test_true(entries[0].name == measureName1,
+ "After a call to window.performance.clearMeasures(\"" + measureName3 + "\"), where \"" + measureName3 +
+ "\" is a non-existent measure, window.performance.getEntriesByName(\"" + measureName1 + "\") " +
+ "returns an object containing the \"" + measureName1 + "\" measure.");
+
+ // test that "measure2" still exists
+ entries = window.performance.getEntriesByName(measureName2);
+ test_true(entries[0].name == measureName2,
+ "After a call to window.performance.clearMeasures(\"" + measureName3 + "\"), where \"" + measureName3 +
+ "\" is a non-existent measure, window.performance.getEntriesByName(\"" + measureName2 + "\") " +
+ "returns an object containing the \"" + measureName2 + "\" measure.");
+
+ // clear existent measure
+ window.performance.clearMeasures(measureName1);
+
+ // test that "measure1" was cleared
+ entries = window.performance.getEntriesByName(measureName1);
+ pass = true;
+ for (var i in entries)
+ {
+ pass = false;
+ }
+ test_true(pass,
+ "After a call to window.performance.clearMeasures(\"" + measureName1 + "\"), " +
+ "window.performance.getEntriesByName(\"" + measureName1 + "\") returns an empty object.");
+
+ // test that "measure2" still exists
+ entries = window.performance.getEntriesByName(measureName2);
+ test_true(entries[0].name == measureName2,
+ "After a call to window.performance.clearMeasures(\"" + measureName1 + "\"), " +
+ "window.performance.getEntriesByName(\"" + measureName2 + "\") returns an object containing the " +
+ "\"" + measureName2 + "\" measure.");
+
+ // clear all measures
+ window.performance.clearMeasures();
+
+ // test that all measures were cleared
+ entries = window.performance.getEntriesByType("measure");
+ pass = true;
+ for (var i in entries)
+ {
+ pass = false;
+ }
+ test_true(pass,
+ "After a call to window.performance.clearMeasures(), " +
+ "window.performance.getEntriesByType(\"measure\") returns an empty object.");
+
+ done();
+ }
+ </script>
+ </head>
+ <body onload="onload_test();">
+ <h1>Description</h1>
+ <p>This test validates that the performance.clearMeasures() method is working properly. This test creates the
+ following measures to test this method:
+ <ul>
+ <li>"measure1"</li>
+ <li>"measure2"</li>
+ </ul>
+ After creating each measure, performance.clearMeasures() is called three times. First, it is provided with a
+ name of "measureUndefined", a non-existent measure, which shouldn't change the state of the Performance
+ Timeline. Next, it is provided with a name of "measure2", after which, this measure should no longer be
+ present in the Performance Timeline. Finally, performance.clearMeasures() is called without any name
+ provided. After this call, no measures should be present in the Performance Timeline. The state of the
+ Performance Timeline is tested with the performance.getEntriesByType() and performance.getEntries() methods.
+ </p>
+
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/user-timing/test_user_timing_entry_type.html b/tests/wpt/web-platform-tests/user-timing/test_user_timing_entry_type.html
new file mode 100644
index 00000000000..c9b336b3785
--- /dev/null
+++ b/tests/wpt/web-platform-tests/user-timing/test_user_timing_entry_type.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>user timing entry type</title>
+ <link rel="author" title="Intel" href="http://www.intel.com/" />
+ <link rel="help" href="http://www.w3.org/TR/user-timing/#extensions-performance-interface"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="resources/webperftestharness.js"></script>
+ <script src="resources/webperftestharnessextension.js"></script>
+ </head>
+ <body>
+ <h1>Description</h1>
+ <p>This test validates the user timing entry type, PerformanceMark and PerformanceMeasure.</p>
+
+ <div id="log"></div>
+ <script>
+ var context = new PerformanceContext(window.performance);
+ context.mark('mark');
+ context.measure('measure');
+ var mark_entry = context.getEntriesByName('mark')[0];
+ var measure_entry = context.getEntriesByName('measure')[0];
+
+ test_equals(Object.prototype.toString.call(mark_entry), '[object PerformanceMark]', 'Class name of mark entry should be PerformanceMark.');
+ test_equals(Object.prototype.toString.call(measure_entry), '[object PerformanceMeasure]', 'Class name of measure entry should be PerformanceMeasure.');
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/user-timing/test_user_timing_exists.html b/tests/wpt/web-platform-tests/user-timing/test_user_timing_exists.html
new file mode 100644
index 00000000000..9ddfbfcbea6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/user-timing/test_user_timing_exists.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="UTF-8" />
+ <title>window.performance User Timing exists</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://www.w3.org/TR/user-timing/"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="resources/webperftestharness.js"></script>
+
+ </head>
+ <body>
+ <h1>Description</h1>
+ <p>This test validates that all of the methods used to interact with the User Timing API are defined.</p>
+
+ <div id="log"></div>
+
+ <script>
+ test_namespace();
+
+ test_true(window.performance.mark !== undefined, "window.performance.mark is defined.");
+ test_true(window.performance.clearMarks !== undefined, "window.performance.clearMarks is defined.");
+ test_true(window.performance.measure !== undefined, "window.performance.measure is defined.");
+ test_true(window.performance.clearMeasures !== undefined, "window.performance.clearMeasures is defined.");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/user-timing/test_user_timing_mark.html b/tests/wpt/web-platform-tests/user-timing/test_user_timing_mark.html
new file mode 100644
index 00000000000..23157d8d3d6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/user-timing/test_user_timing_mark.html
@@ -0,0 +1,228 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="UTF-8" />
+ <title>window.performance User Timing mark() method is working properly</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://www.w3.org/TR/user-timing/#dom-performance-mark"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="resources/webperftestharness.js"></script>
+
+ <script type="text/javascript">
+ // test data
+ var markTestDelay = 200;
+ var testThreshold = 20;
+ var marks;
+
+ var TEST_MARKS =
+ [
+ {
+ name: "mark1",
+ expectedStartTime: undefined,
+ entryMatch: undefined
+ },
+ {
+ name: "mark1",
+ expectedStartTime: undefined,
+ entryMatch: undefined
+ }
+ ];
+
+ setup({explicit_done: true});
+
+ test_namespace();
+
+ function onload_test()
+ {
+ // test for existance of User Timing and Performance Timeline interface
+ if (window.performance.mark == undefined ||
+ window.performance.clearMarks == undefined ||
+ window.performance.measure == undefined ||
+ window.performance.clearMeasures == undefined ||
+ window.performance.getEntriesByName == undefined ||
+ window.performance.getEntriesByType == undefined ||
+ window.performance.getEntries == undefined)
+ {
+ test_true(false,
+ "The User Timing and Performance Timeline interfaces, which are required for this test, " +
+ "are defined.");
+
+ done();
+ }
+ else
+ {
+ // create first mark
+ window.performance.mark(TEST_MARKS[0].name);
+
+ // record the time that this mark is created; this should correspond to the mark's startTime
+ TEST_MARKS[0].expectedStartTime = (new Date()) - window.performance.timing.navigationStart;
+
+ // create the duplicate mark using the test delay; the duplicate mark's value should be equivalent to
+ // the loadEventStart navigation timing attribute plus the test delay
+ setTimeout(mark_test_cb, markTestDelay);
+ }
+ }
+
+ function mark_test_cb()
+ {
+ var getByNameScenarios = new Array();
+
+ // create second, duplicate mark
+ window.performance.mark(TEST_MARKS[1].name);
+
+ // record the time that this mark is created; this should correspond to the mark's startTime
+ TEST_MARKS[1].expectedStartTime = (new Date()) - window.performance.timing.navigationStart;
+
+ // test the test marks are returned by getEntriesByName
+ entries = window.performance.getEntriesByName(TEST_MARKS[0].name);
+ test_mark(entries[0],
+ "window.performance.getEntriesByName(\"" + TEST_MARKS[0].name + "\")[0]",
+ TEST_MARKS[0].name,
+ TEST_MARKS[0].expectedStartTime);
+ TEST_MARKS[0].entryMatch = entries[0];
+
+ test_mark(entries[1],
+ "window.performance.getEntriesByName(\"" + TEST_MARKS[1].name + "\")[1]",
+ TEST_MARKS[1].name,
+ TEST_MARKS[1].expectedStartTime);
+ TEST_MARKS[1].entryMatch = entries[1];
+
+ // test the test marks are returned by getEntriesByName with the entryType parameter provided
+ entries = window.performance.getEntriesByName(TEST_MARKS[0].name, "mark");
+ test_equals(entries[0].name, TEST_MARKS[0].name,
+ "window.performance.getEntriesByName(\"" + TEST_MARKS[0].name + "\", \"mark\") returns an " +
+ "object containing the \"" + TEST_MARKS[0].name + "\" mark in the correct order");
+
+ test_equals(entries[1].name, TEST_MARKS[1].name,
+ "window.performance.getEntriesByName(\"" + TEST_MARKS[1].name + "\", \"mark\") returns an " +
+ "object containing the duplicate \"" + TEST_MARKS[1].name + "\" mark in the correct order");
+
+ test_true(match_entries(entries[0], TEST_MARKS[0].entryMatch),
+ "The \"" + TEST_MARKS[0].name + "\" mark returned by " +
+ "window.performance.getEntriesByName(\"" + TEST_MARKS[0].name + "\", \"mark\") matches the " +
+ "the \"" + TEST_MARKS[0].name + "\" mark returned by " +
+ "window.performance.getEntriesByName(\"" + TEST_MARKS[0].name + "\")");
+
+ test_true(match_entries(entries[1], TEST_MARKS[1].entryMatch),
+ "The duplicate \"" + TEST_MARKS[1].name + "\" mark returned by " +
+ "window.performance.getEntriesByName(\"" + TEST_MARKS[1].name + "\", \"mark\") matches the " +
+ "the duplicate \"" + TEST_MARKS[1].name + "\" mark returned by " +
+ "window.performance.getEntriesByName(\"" + TEST_MARKS[1].name + "\")");
+
+ // test the test marks are returned by getEntries
+ entries = get_test_entries(window.performance.getEntries(), "mark");
+
+ test_equals(entries[0].name, TEST_MARKS[0].name,
+ "window.performance.getEntries() returns an object containing the original \"" +
+ TEST_MARKS[0].name + "\" mark in the correct order");
+
+ test_equals(entries[1].name, TEST_MARKS[1].name,
+ "window.performance.getEntries() returns an object containing the duplicate \"" +
+ TEST_MARKS[1].name + "\" mark in the correct order");
+
+ test_true(match_entries(entries[0], TEST_MARKS[0].entryMatch),
+ "The \"" + TEST_MARKS[0].name + "\" mark returned by " +
+ "window.performance.getEntries() matches the the \"" + TEST_MARKS[0].name + "\" mark returned " +
+ "by window.performance.getEntriesByName(\"" + TEST_MARKS[0].name + "\")");
+
+ test_true(match_entries(entries[1], TEST_MARKS[1].entryMatch),
+ "The \"" + TEST_MARKS[1].name + "\" mark returned by " +
+ "window.performance.getEntries() matches the the duplicate \"" + TEST_MARKS[1].name + "\" mark " +
+ "returned by window.performance.getEntriesByName(\"" + TEST_MARKS[1].name + "\")");
+
+ // test the test marks are returned by getEntriesByType
+ entries = window.performance.getEntriesByType("mark");
+
+ test_equals(entries[0].name, TEST_MARKS[0].name,
+ "window.performance.getEntriesByType(\"mark\") returns an object containing the original \"" +
+ TEST_MARKS[0].name + "\" mark in the correct order");
+
+ test_equals(entries[1].name, TEST_MARKS[1].name,
+ "window.performance.getEntriesByType(\"mark\") returns an object containing the duplicate \"" +
+ TEST_MARKS[1].name + "\" mark in the correct order");
+
+ test_true(match_entries(entries[0], TEST_MARKS[0].entryMatch),
+ "The \"" + TEST_MARKS[0].name + "\" mark returned by " +
+ "window.performance.getEntriesByType(\"mark\") matches the the \"" + TEST_MARKS[0].name +
+ "\" mark returned by window.performance.getEntriesByName(\"" + TEST_MARKS[0].name + "\")");
+
+ test_true(match_entries(entries[1], TEST_MARKS[1].entryMatch),
+ "The \"" + TEST_MARKS[1].name + "\" mark returned by " +
+ "window.performance.getEntriesByType(\"mark\") matches the the duplicate \"" +
+ TEST_MARKS[1].name + "\" mark returned by window.performance.getEntriesByName(\"" +
+ TEST_MARKS[1].name + "\")");
+
+ done();
+ }
+
+ function match_entries(entry1, entry2)
+ {
+ var pass = true;
+
+ // match name
+ pass = pass && (entry1.name == entry2.name);
+
+ // match startTime
+ pass = pass && (entry1.startTime == entry2.startTime);
+
+ // match entryType
+ pass = pass && (entry1.entryType == entry2.entryType);
+
+ // match duration
+ pass = pass && (entry1.duration == entry2.duration);
+
+ return pass;
+ }
+
+ function test_mark(markEntry, markEntryCommand, expectedName, expectedStartTime)
+ {
+ // test name
+ test_equals(markEntry.name, expectedName, markEntryCommand + ".name == \"" + expectedName + "\"");
+
+ // test startTime, allow for an acceptable threshold in the difference between the startTime and the
+ // expected value for the startTime (loadEventStart + markTestDelay)
+ test_true(Math.abs(markEntry.startTime - expectedStartTime) <= testThreshold,
+ markEntryCommand + ".startTime ~== " + expectedStartTime + " (up to " + testThreshold +
+ "ms difference allowed)");
+
+ // verify entryType
+ test_equals(markEntry.entryType, "mark", markEntryCommand + ".entryType == \"mark\"");
+
+ // verify duration
+ test_equals(markEntry.duration, 0, markEntryCommand + ".duration == 0");
+ }
+
+ function get_test_entries(entryList, entryType)
+ {
+ var testEntries = new Array();
+
+ // filter entryList
+ for (var i in entryList)
+ {
+ if (entryList[i].entryType == entryType)
+ {
+ testEntries.push(entryList[i]);
+ }
+ }
+
+ return testEntries;
+ }
+ </script>
+ </head>
+ <body onload="onload_test();">
+ <h1>Description</h1>
+ <p>This test validates that the performance.mark() method is working properly. This test creates the
+ following marks to test this method:
+ <ul>
+ <li>"mark1": created using a normal mark() call</li>
+ <li>"mark1": duplicate of the first mark, used to confirm names can be re-used</li>
+ </ul>
+ After creating each mark, the existence of these marks is validated by calling
+ performance.getEntriesByName() (both with and without the entryType parameter provided),
+ performance.getEntriesByType(), and performance.getEntries()
+ </p>
+
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/user-timing/test_user_timing_mark_and_measure_exception_when_invoke_without_parameter.html b/tests/wpt/web-platform-tests/user-timing/test_user_timing_mark_and_measure_exception_when_invoke_without_parameter.html
new file mode 100644
index 00000000000..e4e9bfe249d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/user-timing/test_user_timing_mark_and_measure_exception_when_invoke_without_parameter.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>exception test of performance.mark and performance.measure</title>
+ <link rel="author" title="Intel" href="http://www.intel.com/" />
+ <link rel="help" href="http://www.w3.org/TR/user-timing/#extensions-performance-interface"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="resources/webperftestharness.js"></script>
+ <script>
+ setup({explicit_done: true});
+ test_namespace();
+
+ function onload_test() {
+ if (window.performance !== undefined && window.performance.mark !== undefined)
+ {
+ try
+ {
+ window.performance.mark();
+ test_true(false, "window.performance.mark() threw an exception when invoke without a parameter.");
+ }
+ catch(e)
+ {
+ test_true(true, "window.performance.mark() threw an exception when invoke without a parameter.");
+
+ test_equals(e.name,
+ "TypeError",
+ "window.performance.mark() threw a TYPE_ERR exception when invoke without a parameter.");
+ }
+ }
+ else
+ {
+ test_true(false, "window.performance.mark() interface is not supported!");
+ }
+
+ if (window.performance !== undefined && window.performance.measure !== undefined)
+ {
+ try
+ {
+ window.performance.measure();
+ test_true(false, "window.performance.measure() threw an exception when invoke without a parameter.");
+ }
+ catch(e)
+ {
+ test_true(true, "window.performance.measure() threw an exception when invoke without a parameter.");
+
+ test_equals(e.name,
+ "TypeError",
+ "window.performance.measure() threw a TYPE_ERR exception when invoke without a parameter.");
+ }
+ }
+ else
+ {
+ test_true(false, "window.performance.measure() interface is not supported!");
+ }
+
+ done();
+ }
+ </script>
+ </head>
+ <body onload="onload_test();">
+ <h1>Description</h1>
+ <p>This test validates exception scenarios of invoking mark() and measure() without parameter.</p>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/user-timing/test_user_timing_mark_exceptions.html b/tests/wpt/web-platform-tests/user-timing/test_user_timing_mark_exceptions.html
new file mode 100644
index 00000000000..1fe214f78c8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/user-timing/test_user_timing_mark_exceptions.html
@@ -0,0 +1,105 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="UTF-8" />
+ <title>window.performance User Timing mark() method is throwing the proper exceptions</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://www.w3.org/TR/user-timing/#dom-performance-mark"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="resources/webperftestharness.js"></script>
+
+ <script type="text/javascript">
+ // navigation timing attributes
+ var timingAttributes = [
+ 'connectEnd',
+ 'connectStart',
+ 'domComplete',
+ 'domContentLoadedEventEnd',
+ 'domContentLoadedEventStart',
+ 'domInteractive',
+ 'domLoading',
+ 'domainLookupEnd',
+ 'domainLookupStart',
+ 'fetchStart',
+ 'loadEventEnd',
+ 'loadEventStart',
+ 'navigationStart',
+ 'redirectEnd',
+ 'redirectStart',
+ 'requestStart',
+ 'responseEnd',
+ 'responseStart',
+ 'unloadEventEnd',
+ 'unloadEventStart'
+ ];
+
+ // test data
+ var markExceptionThrown = false;
+
+ setup({explicit_done: true});
+
+ test_namespace();
+
+ function onload_test()
+ {
+ // test for existance of User Timing and Performance Timeline interface
+ if (window.performance.mark == undefined ||
+ window.performance.clearMarks == undefined ||
+ window.performance.measure == undefined ||
+ window.performance.clearMeasures == undefined ||
+ window.performance.getEntriesByName == undefined ||
+ window.performance.getEntriesByType == undefined ||
+ window.performance.getEntries == undefined)
+ {
+ test_true(false,
+ "The User Timing and Performance Timeline interfaces, which are required for this test, " +
+ "are defined.");
+
+ done();
+ }
+ else
+ {
+ test_mark_exceptions();
+ }
+ }
+
+ function test_mark_exceptions()
+ {
+ // loop through mark scenarios
+ for (var i in timingAttributes)
+ {
+ try
+ {
+ // create the mark
+ window.performance.mark(timingAttributes[i]);
+
+ test_true(false,
+ "window.performance.mark(\"" + timingAttributes[i] + "\") threw an exception.");
+ }
+ catch(e)
+ {
+ test_true(true,
+ "window.performance.mark(\"" + timingAttributes[i] + "\") threw an exception.");
+
+ // confirm that a SYNTAX_ERR exception is thrown and not any other exception
+ test_equals(e.code,
+ e.SYNTAX_ERR,
+ "window.performance.mark(\"" + timingAttributes[i] + "\") threw a SYNTAX_ERR " +
+ "exception.");
+ }
+ }
+
+ done();
+ }
+ </script>
+ </head>
+ <body onload="onload_test();">
+ <h1>Description</h1>
+ <p>This test validates that the performance.mark() method throws a SYNTAX_ERR exception whenever a navigation
+ timing attribute is provided for the name parameter.
+ </p>
+
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/user-timing/test_user_timing_mark_with_name_of_navigation_timing_optional_attribute.html b/tests/wpt/web-platform-tests/user-timing/test_user_timing_mark_with_name_of_navigation_timing_optional_attribute.html
new file mode 100644
index 00000000000..9532964efc3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/user-timing/test_user_timing_mark_with_name_of_navigation_timing_optional_attribute.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>exception test of performance.mark</title>
+ <link rel="author" title="Intel" href="http://www.intel.com/" />
+ <link rel="help" href="http://www.w3.org/TR/user-timing/#extensions-performance-interface"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="resources/webperftestharness.js"></script>
+ <script src="resources/webperftestharnessextension.js"></script>
+ <script>
+ setup({explicit_done: true});
+ test_namespace();
+
+ function onload_test() {
+ if (window.performance !== undefined && window.performance.timing !== undefined && window.performance.timing.secureConnectionStart !== undefined)
+ {
+ var context = new PerformanceContext(window.performance);
+ var optionalAttribute = "secureConnectionStart";
+ try
+ {
+ context.mark(optionalAttribute);
+ test_true(false,
+ "window.performance.mark(\"" + optionalAttribute + "\") threw an exception when " +
+ optinalAttribute + " attribute of Navigation Timing is supported.");
+ }
+ catch(e)
+ {
+ test_true(true,
+ "window.performance.mark(\"" + optionalAttribute + "\") threw an exception when " +
+ optionalAttribute + " attribute of Navigation Timing is supported.");
+
+ // confirm that a SYNTAX_ERR exception is thrown and not any other exception
+ test_equals(e.code,
+ e.SYNTAX_ERR,
+ "window.performance.mark(\"" + optionalAttribute + "\") threw a SYNTAX_ERR when " +
+ optionalAttribute + " attribute of Navigation Timing is supported.");
+ }
+ }
+ else
+ {
+ test_true(true,
+ "This test is ignored when secureConnectionStart attribute of Navigation Timing is not supported.");
+ }
+ done();
+ }
+ </script>
+ </head>
+ <body onload=onload_test()>
+ <h1>Description</h1>
+ <p>This test validates exception scenarios of invoking performance.mark() with param of "secureConnectionStart".</p>
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/user-timing/test_user_timing_measure.html b/tests/wpt/web-platform-tests/user-timing/test_user_timing_measure.html
new file mode 100644
index 00000000000..205b7fa1e6c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/user-timing/test_user_timing_measure.html
@@ -0,0 +1,334 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="UTF-8" />
+ <title>window.performance User Timing measure() method is working properly</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://www.w3.org/TR/user-timing/#dom-performance-measure"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="resources/webperftestharness.js"></script>
+
+ <script type="text/javascript">
+ // test data
+ var startMarkName = "mark_start";
+ var startMarkValue;
+ var endMarkName = "mark_end";
+ var endMarkValue;
+ var measures;
+ var testThreshold = 20;
+
+ // test measures
+ var measureTestDelay = 200;
+ var TEST_MEASURES =
+ [
+ {
+ name: "measure_no_start_no_end",
+ startMark: undefined,
+ endMark: undefined,
+ startTime: undefined,
+ duration: undefined,
+ entryType: "measure",
+ entryMatch: undefined,
+ order: undefined,
+ found: false
+ },
+ {
+ name: "measure_start_no_end",
+ startMark: "mark_start",
+ endMark: undefined,
+ startTime: undefined,
+ duration: undefined,
+ entryType: "measure",
+ entryMatch: undefined,
+ order: undefined,
+ found: false
+ },
+ {
+ name: "measure_start_end",
+ startMark: "mark_start",
+ endMark: "mark_end",
+ startTime: undefined,
+ duration: undefined,
+ entryType: "measure",
+ entryMatch: undefined,
+ order: undefined,
+ found: false
+ },
+ {
+ name: "measure_no_start_no_end",
+ startMark: undefined,
+ endMark: undefined,
+ startTime: undefined,
+ duration: undefined,
+ entryType: "measure",
+ entryMatch: undefined,
+ order: undefined,
+ found: false
+ }
+ ];
+
+ setup({explicit_done: true});
+
+ test_namespace();
+
+ function onload_test()
+ {
+ // test for existance of User Timing and Performance Timeline interface
+ if (window.performance.mark == undefined ||
+ window.performance.clearMarks == undefined ||
+ window.performance.measure == undefined ||
+ window.performance.clearMeasures == undefined ||
+ window.performance.getEntriesByName == undefined ||
+ window.performance.getEntriesByType == undefined ||
+ window.performance.getEntries == undefined)
+ {
+ test_true(false,
+ "The User Timing and Performance Timeline interfaces, which are required for this test, " +
+ "are defined.");
+
+ done();
+ }
+ else
+ {
+ // create the start mark for the test measures
+ window.performance.mark(startMarkName);
+
+ // get the start mark's value
+ startMarkValue = window.performance.getEntriesByName(startMarkName)[0].startTime;
+
+ // create the test end mark using the test delay; this will allow for a significant difference between
+ // the mark values that should be represented in the duration of measures using these marks
+ setTimeout(measure_test_cb, measureTestDelay);
+ }
+ }
+
+ function measure_test_cb()
+ {
+ // create the end mark for the test measures
+ window.performance.mark(endMarkName);
+
+ // get the end mark's value
+ endMarkValue = window.performance.getEntriesByName(endMarkName)[0].startTime;
+
+ // loop through all measure scenarios and create the corresponding measures
+ for (var i in TEST_MEASURES)
+ {
+ var scenario = TEST_MEASURES[i];
+
+ if (scenario.startMark == undefined && scenario.endMark == undefined)
+ {
+ // both startMark and endMark are undefined, don't provide either parameters
+ window.performance.measure(scenario.name);
+
+ // when startMark isn't provided to the measure() call, a DOMHighResTimeStamp corresponding
+ // to the navigationStart attribute with a timebase of the same attribute is used; this is
+ // equivalent to 0
+ scenario.startTime = 0;
+
+ // when endMark isn't provided to the measure() call, a DOMHighResTimeStamp corresponding to
+ // the current time with a timebase of the navigationStart attribute is used
+ scenario.duration = (new Date()) - window.performance.timing.navigationStart;
+ }
+ else if (scenario.startMark != undefined && scenario.endMark == undefined)
+ {
+ // only startMark is defined, provide startMark and don't provide endMark
+ window.performance.measure(scenario.name, scenario.startMark);
+
+ // when startMark is provided to the measure() call, the value of the mark whose name is
+ // provided is used for the startMark
+ scenario.startTime = startMarkValue;
+
+ // when endMark isn't provided to the measure() call, a DOMHighResTimeStamp corresponding to
+ // the current time with a timebase of the navigationStart attribute is used
+ scenario.duration = ((new Date()) - window.performance.timing.navigationStart) -
+ startMarkValue;
+ }
+ else if (scenario.startMark != undefined && scenario.endMark != undefined)
+ {
+ // both startMark and endMark are defined, provide both parameters
+ window.performance.measure(scenario.name, scenario.startMark, scenario.endMark);
+
+ // when startMark is provided to the measure() call, the value of the mark whose name is
+ // provided is used for the startMark
+ scenario.startTime = startMarkValue;
+
+ // when endMark is provided to the measure() call, the value of the mark whose name is
+ // provided is used for the startMark
+ scenario.duration = endMarkValue - startMarkValue;
+ }
+ }
+
+ // test that expected measures are returned by getEntriesByName
+ for (var i in TEST_MEASURES)
+ {
+ entries = window.performance.getEntriesByName(TEST_MEASURES[i].name);
+ // for all test measures, the test will be validate the test measure against the first entry returned
+ // by getEntriesByName(), except for the last measure, where since it is a duplicate measure, the test
+ // will validate it against the second entry returned by getEntriesByName()
+ test_measure(entries[(i == 3 ? 1 : 0)],
+ "window.performance.getEntriesByName(\"" + TEST_MEASURES[i].name + "\")[" +
+ (i == 3 ? 1 : 0) + "]",
+ TEST_MEASURES[i].name,
+ TEST_MEASURES[i].startTime,
+ TEST_MEASURES[i].duration);
+ TEST_MEASURES[i].entryMatch = entries[(i == 3 ? 1 : 0)];
+ }
+
+ // test that expected measures are returned by getEntriesByName with the entryType parameter provided
+ for (var i in TEST_MEASURES)
+ {
+ entries = window.performance.getEntriesByName(TEST_MEASURES[i].name, "measure");
+
+ test_true(match_entries(entries[(i == 3 ? 1 : 0)], TEST_MEASURES[i].entryMatch),
+ "window.performance.getEntriesByName(\"" + TEST_MEASURES[i].name + "\", \"measure\")[" +
+ (i == 3 ? 1 : 0) + "] returns an object containing the \"" + TEST_MEASURES[i].name +
+ "\" measure in the correct order, and its value matches the \"" + TEST_MEASURES[i].name +
+ "\" measure returned by window.performance.getEntriesByName(\"" + TEST_MEASURES[i].name +
+ "\")");
+ }
+
+ // test that expected measures are returned by getEntries
+ entries = get_test_entries(window.performance.getEntries(), "measure");
+
+ test_measure_list(entries, "window.performance.getEntries()", TEST_MEASURES);
+
+ // test that expected measures are returned by getEntriesByType
+ entries = window.performance.getEntriesByType("measure");
+
+ test_measure_list(entries, "window.performance.getEntriesByType(\"measure\")", TEST_MEASURES);
+
+ done();
+ }
+
+ function match_entries(entry1, entry2, threshold)
+ {
+ if (threshold == undefined)
+ {
+ threshold = 0;
+ }
+
+ var pass = true;
+
+ // match name
+ pass = pass && (entry1.name == entry2.name);
+
+ // match startTime
+ pass = pass && (Math.abs(entry1.startTime - entry2.startTime) <= testThreshold);
+
+ // match entryType
+ pass = pass && (entry1.entryType == entry2.entryType);
+
+ // match duration
+ pass = pass && (Math.abs(entry1.duration - entry2.duration) <= testThreshold);
+
+ return pass;
+ }
+
+ function test_measure(measureEntry, measureEntryCommand, expectedName, expectedStartTime, expectedDuration)
+ {
+ // test name
+ test_true(measureEntry.name == expectedName, measureEntryCommand + ".name == \"" + expectedName + "\"");
+
+ // test startTime; since for a mark, the startTime is always equal to a mark's value or the value of a
+ // navigation timing attribute, the actual startTime should match the expected value exactly
+ test_true(Math.abs(measureEntry.startTime - expectedStartTime) == 0,
+ measureEntryCommand + ".startTime == " + expectedStartTime);
+
+ // test entryType
+ test_true(measureEntry.entryType == "measure", measureEntryCommand + ".entryType == \"measure\"");
+
+ // test duration, allow for an acceptable threshold in the difference between the actual duration and the
+ // expected value for the duration
+ test_true(Math.abs(measureEntry.duration - expectedDuration) <= testThreshold, measureEntryCommand +
+ ".duration ~== " + expectedDuration + " (up to " + testThreshold + "ms difference allowed)");
+ }
+
+ function test_measure_list(measureEntryList, measureEntryListCommand, measureScenarios)
+ {
+ // give all entries a "found" property that can be set to ensure it isn't tested twice
+ for (var i in measureEntryList)
+ {
+ measureEntryList[i].found = false;
+ }
+
+ for (var i in measureScenarios)
+ {
+ measureScenarios[i].found = false;
+
+ for (var j in measureEntryList)
+ {
+ if (match_entries(measureEntryList[j], measureScenarios[i]) && !measureEntryList[j].found)
+ {
+ test_true(match_entries(measureEntryList[j], measureScenarios[i].entryMatch),
+ measureEntryListCommand + " returns an object containing the \"" +
+ measureScenarios[i].name + "\" measure, and it's value matches the measure " +
+ "returned by window.performance.getEntriesByName(\"" + measureScenarios[i].name +
+ "\")[" + (i == 3 ? 1 : 0) + "].");
+
+ measureEntryList[j].found = true;
+ measureScenarios[i].found = true;
+ break;
+ }
+ }
+
+ if (!measureScenarios[i].found)
+ {
+ test_true(false,
+ measureEntryListCommand + " returns an object containing the \"" +
+ measureScenarios[i].name + "\" measure.");
+ }
+ }
+
+ // verify order of output of getEntriesByType
+ var startTimeCurr = 0;
+ var pass = true;
+ for (var i in measureEntryList)
+ {
+ if (measureEntryList[i].startTime < startTimeCurr)
+ {
+ pass = false;
+ }
+ startTimeCurr = measureEntryList[i].startTime;
+ }
+ test_true(pass,
+ measureEntryListCommand + " returns an object containing all test " +
+ "measures in order.");
+ }
+
+ function get_test_entries(entryList, entryType)
+ {
+ var testEntries = new Array();
+
+ // filter entryList
+ for (var i in entryList)
+ {
+ if (entryList[i].entryType == entryType)
+ {
+ testEntries.push(entryList[i]);
+ }
+ }
+
+ return testEntries;
+ }
+ </script>
+ </head>
+ <body onload="onload_test();">
+ <h1>Description</h1>
+ <p>This test validates that the performance.measure() method is working properly. This test creates the
+ following measures to test this method:
+ <ul>
+ <li>"measure_no_start_no_end": created using a measure() call without a startMark or endMark
+ provided</li>
+ <li>"measure_start_no_end": created using a measure() call with only the startMark provided</li>
+ <li>"measure_start_end": created using a measure() call with both a startMark or endMark provided</li>
+ <li>"measure_no_start_no_end": duplicate of the first measure, used to confirm names can be re-used</li>
+ </ul>
+ After creating each measure, the existence of these measures is validated by calling
+ performance.getEntriesByName() (both with and without the entryType parameter provided),
+ performance.getEntriesByType(), and performance.getEntries()
+ </p>
+
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/user-timing/test_user_timing_measure_exceptions.html b/tests/wpt/web-platform-tests/user-timing/test_user_timing_measure_exceptions.html
new file mode 100644
index 00000000000..18a8ba1afa9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/user-timing/test_user_timing_measure_exceptions.html
@@ -0,0 +1,282 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="UTF-8" />
+ <title>window.performance User Timing measure() method is throwing the proper exceptions</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://www.w3.org/TR/user-timing/#dom-performance-measure"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="resources/webperftestharness.js"></script>
+
+ <script type="text/javascript">
+ // navigation timing attributes
+ var timingAttributes = [
+ 'connectEnd',
+ 'connectStart',
+ 'domComplete',
+ 'domContentLoadedEventEnd',
+ 'domContentLoadedEventStart',
+ 'domInteractive',
+ 'domLoading',
+ 'domainLookupEnd',
+ 'domainLookupStart',
+ 'fetchStart',
+ 'loadEventEnd',
+ 'loadEventStart',
+ 'navigationStart',
+ 'redirectEnd',
+ 'redirectStart',
+ 'requestStart',
+ 'responseEnd',
+ 'responseStart',
+ 'unloadEventEnd',
+ 'unloadEventStart'
+ ];
+
+ // test data
+ var zeroedNavTimingAtt = undefined;
+
+ setup({explicit_done: true});
+
+ test_namespace();
+
+ function onload_test()
+ {
+ // test for existance of User Timing and Performance Timeline interface
+ if (window.performance.mark == undefined ||
+ window.performance.clearMarks == undefined ||
+ window.performance.measure == undefined ||
+ window.performance.clearMeasures == undefined ||
+ window.performance.getEntriesByName == undefined ||
+ window.performance.getEntriesByType == undefined ||
+ window.performance.getEntries == undefined)
+ {
+ test_true(false,
+ "The User Timing and Performance Timeline interfaces, which are required for this test, " +
+ "are defined.");
+
+ done();
+ }
+ else
+ {
+ test_measure_exceptions();
+ }
+ }
+
+ function test_measure_exceptions()
+ {
+ // test scenarios for the SYNTAX_ERR exception
+ try
+ {
+ // create the measure
+ window.performance.measure("measure", "mark");
+
+ test_true(false,
+ "window.performance.measure(\"measure\", \"mark\"), where \"mark\" is a non-existent mark, " +
+ "threw an exception.");
+ }
+ catch(e)
+ {
+ test_true(true,
+ "window.performance.measure(\"measure\", \"mark\"), where \"mark\" is a non-existent mark, " +
+ " threw an exception.");
+
+ test_equals(e.code,
+ e.SYNTAX_ERR,
+ "window.performance.measure(\"measure\", \"mark\"), where \"mark\" is a non-existent " +
+ "mark, threw a SYNTAX_ERR exception.");
+ }
+
+ try
+ {
+ // create the measure
+ window.performance.measure("measure", "mark", "responseEnd");
+
+ test_true(false,
+ "window.performance.measure(\"measure\", \"mark\", \"responseEnd\"), where \"mark\" is a " +
+ "non-existent mark, threw an exception.");
+ }
+ catch(e)
+ {
+ test_true(true,
+ "window.performance.measure(\"measure\", \"mark\", \"responseEnd\"), where \"mark\" is a " +
+ "non-existent mark, threw an exception.");
+
+ test_equals(e.code,
+ e.SYNTAX_ERR,
+ "window.performance.measure(\"measure\", \"mark\", \"responseEnd\"), where \"mark\" is a " +
+ "non-existent mark, threw a SYNTAX_ERR exception.");
+ }
+
+ try
+ {
+ // create the measure
+ window.performance.measure("measure", "navigationStart", "mark");
+
+ test_true(false,
+ "window.performance.measure(\"measure\", \"navigationStart\", \"mark\"), where \"mark\" is " +
+ "a non-existent mark, threw an exception.");
+ }
+ catch(e)
+ {
+ test_true(true,
+ "window.performance.measure(\"measure\", \"navigationStart\", \"mark\"), where \"mark\" is " +
+ "a non-existent mark, threw an exception.");
+
+ test_equals(e.code,
+ e.SYNTAX_ERR,
+ "window.performance.measure(\"measure\", \"navigationStart\", \"mark\"), where \"mark\" " +
+ "is a non-existent mark, threw a SYNTAX_ERR exception.");
+ }
+
+ try
+ {
+ // create the measure
+ window.performance.measure("measure", "mark", "mark");
+
+ test_true(false,
+ "window.performance.measure(\"measure\", \"mark\", \"mark\"), where \"mark\" is a " +
+ "non-existent mark, threw an exception.");
+ }
+ catch(e)
+ {
+ test_true(true,
+ "window.performance.measure(\"measure\", \"mark\", \"mark\"), where \"mark\" is a " +
+ "non-existent mark, threw an exception.");
+
+ test_equals(e.code,
+ e.SYNTAX_ERR,
+ "window.performance.measure(\"measure\", \"mark\", \"mark\"), where \"mark\" is a " +
+ "non-existent mark, threw a SYNTAX_ERR exception.");
+ }
+
+
+ // for testing the INVALID_ACCESS_ERR exception, find a navigation timing attribute with a value of zero
+ for (var i in timingAttributes)
+ {
+ if (window.performance.timing[timingAttributes[i]] == 0)
+ {
+ zeroedNavTimingAtt = timingAttributes[i];
+ }
+ }
+
+ if (zeroedNavTimingAtt == undefined)
+ {
+ test_true(false,
+ "A navigation timing attribute with a value of 0 was not found to test for the " +
+ "INVALID_ACCESS_ERR exception thrown by window.performance.measure().");
+ }
+ else
+ {
+ try
+ {
+ // create the measure
+ window.performance.measure("measure", zeroedNavTimingAtt);
+
+ test_true(false,
+ "window.performance.measure(\"measure\", \"" + zeroedNavTimingAtt + "\"), where \"" +
+ zeroedNavTimingAtt + "\" is a navigation timing attribute with a value of 0, threw an " +
+ "exception.");
+ }
+ catch(e)
+ {
+ test_true(true,
+ "window.performance.measure(\"measure\", \"" + zeroedNavTimingAtt + "\"), where \"" +
+ zeroedNavTimingAtt + "\" is a navigation timing attribute with a value of 0, threw an " +
+ "exception.");
+
+ test_equals(e.code,
+ e.INVALID_ACCESS_ERR,
+ "window.performance.measure(\"measure\", \"" + zeroedNavTimingAtt + "\"), where \"" +
+ zeroedNavTimingAtt + "\" is a navigation timing attribute with a value of 0, threw " +
+ "an INVALID_ACCESS_ERR exception.");
+ }
+
+ try
+ {
+ // create the measure
+ window.performance.measure("measure", zeroedNavTimingAtt, "responseEnd");
+
+ test_true(false,
+ "window.performance.measure(\"measure\", \"" + zeroedNavTimingAtt + "\", " +
+ "\"responseEnd\"), where \"" + zeroedNavTimingAtt + "\" is a navigation timing " +
+ "attribute with a value of 0, threw an exception.");
+ }
+ catch(e)
+ {
+ test_true(true,
+ "window.performance.measure(\"measure\", \"" + zeroedNavTimingAtt + "\", " +
+ "\"responseEnd\"), where \"" + zeroedNavTimingAtt + "\" is a navigation timing " +
+ "attribute with a value of 0, threw an exception.");
+
+ test_equals(e.code,
+ e.INVALID_ACCESS_ERR,
+ "window.performance.measure(\"measure\", \"" + zeroedNavTimingAtt + "\", " +
+ "\"responseEnd\"), where \"" + zeroedNavTimingAtt + "\" is a navigation timing " +
+ "attribute with a value of 0, threw an INVALID_ACCESS_ERR exception.");
+ }
+
+ try
+ {
+ // create the measure
+ window.performance.measure("measure", "navigationStart", zeroedNavTimingAtt);
+
+ test_true(false,
+ "window.performance.measure(\"measure\", \"navigationStart\", \"" + zeroedNavTimingAtt +
+ "\"), where \"" + zeroedNavTimingAtt + "\" is a navigation timing attribute with a " +
+ "value of 0, threw an exception.");
+ }
+ catch(e)
+ {
+ test_true(true,
+ "window.performance.measure(\"measure\", \"navigationStart\", \"" + zeroedNavTimingAtt +
+ "\"), where \"" + zeroedNavTimingAtt + "\" is a navigation timing attribute with a " +
+ "value of 0, threw an exception.");
+
+ test_equals(e.code,
+ e.INVALID_ACCESS_ERR,
+ "window.performance.measure(\"measure\", \"navigationStart\", \"" + zeroedNavTimingAtt +
+ "\"), where \"" + zeroedNavTimingAtt + "\" is a navigation timing attribute with a " +
+ "value of 0, threw an INVALID_ACCESS_ERR exception.");
+ }
+
+ try
+ {
+ // create the measure
+ window.performance.measure("measure", zeroedNavTimingAtt, zeroedNavTimingAtt);
+
+ test_true(false,
+ "window.performance.measure(\"measure\", \"" + zeroedNavTimingAtt + "\", \"" +
+ zeroedNavTimingAtt + "\"), where \"" + zeroedNavTimingAtt + "\" is a navigation timing " +
+ "attribute with a value of 0, threw an exception.");
+ }
+ catch(e)
+ {
+ test_true(true,
+ "window.performance.measure(\"measure\", \"" + zeroedNavTimingAtt + "\", \"" +
+ zeroedNavTimingAtt + "\"), where \"" + zeroedNavTimingAtt + "\" is a navigation timing " +
+ "attribute with a value of 0, threw an exception.");
+
+ test_equals(e.code,
+ e.INVALID_ACCESS_ERR,
+ "window.performance.measure(\"measure\", \"" + zeroedNavTimingAtt + "\", \"" +
+ zeroedNavTimingAtt + "\"), where \"" + zeroedNavTimingAtt + "\" is a navigation " +
+ "timing attribute with a value of 0, threw an INVALID_ACCESS_ERR exception.");
+ }
+ }
+
+ done();
+ }
+ </script>
+ </head>
+ <body onload="onload_test();">
+ <h1>Description</h1>
+ <p>This test validates that the performance.measure() method throws a SYNTAX_ERR exception whenever a
+ non-existent mark is provided as the startMark or endMark, and the method also throws a INVALID_ACCESS_ERR
+ whenever a navigation timing attribute with a value of zero is provided as the startMark or endMark.
+ </p>
+
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/user-timing/test_user_timing_measure_navigation_timing.html b/tests/wpt/web-platform-tests/user-timing/test_user_timing_measure_navigation_timing.html
new file mode 100644
index 00000000000..52ca2de30b1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/user-timing/test_user_timing_measure_navigation_timing.html
@@ -0,0 +1,233 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="UTF-8" />
+ <title>window.performance User Timing clearMeasures() method is working properly with navigation timing
+ attributes</title>
+ <link rel="author" title="Microsoft" href="http://www.microsoft.com/" />
+ <link rel="help" href="http://www.w3.org/TR/user-timing/#dom-performance-measure"/>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="resources/webperftestharness.js"></script>
+
+ <script type="text/javascript">
+ // navigation timing attributes
+ var timingAttributes = [
+ 'connectEnd',
+ 'connectStart',
+ 'domComplete',
+ 'domContentLoadedEventEnd',
+ 'domContentLoadedEventStart',
+ 'domInteractive',
+ 'domLoading',
+ 'domainLookupEnd',
+ 'domainLookupStart',
+ 'fetchStart',
+ 'loadEventEnd',
+ 'loadEventStart',
+ 'navigationStart',
+ 'redirectEnd',
+ 'redirectStart',
+ 'requestStart',
+ 'responseEnd',
+ 'responseStart',
+ 'unloadEventEnd',
+ 'unloadEventStart'
+ ];
+
+ // test data
+ var startMarkName = "mark_start";
+ var startMarkValue;
+ var endMarkName = "mark_end";
+ var endMarkValue;
+ var measures;
+ var testThreshold = 20;
+
+ // test measures
+ measureTestDelay = 200;
+ var TEST_MEASURES =
+ [
+ {
+ name: "measure_nav_start_no_end",
+ startMark: "navigationStart",
+ endMark: undefined,
+ exceptionTestMessage: "window.performance.measure(\"measure_nav_start_no_end\", " +
+ "\"navigationStart\") ran without throwing any exceptions.",
+ expectedStartTime: undefined,
+ expectedDuration: undefined,
+ entryMatch: undefined
+ },
+ {
+ name: "measure_nav_start_mark_end",
+ startMark: "navigationStart",
+ endMark: "mark_end",
+ exceptionTestMessage: "window.performance.measure(\"measure_nav_start_end\", \"navigationStart\", " +
+ "\"mark_end\") ran without throwing any exceptions.",
+ expectedStartTime: undefined,
+ expectedDuration: undefined,
+ entryMatch: undefined
+ },
+ {
+ name: "measure_mark_start_nav_end",
+ startMark: "mark_start",
+ endMark: "responseEnd",
+ exceptionTestMessage: "window.performance.measure(\"measure_start_nav_end\", \"mark_start\", " +
+ "\"responseEnd\") ran without throwing any exceptions.",
+ expectedStartTime: undefined,
+ expectedDuration: undefined,
+ entryMatch: undefined
+ },
+ {
+ name: "measure_nav_start_nav_end",
+ startMark: "navigationStart",
+ endMark: "responseEnd",
+ exceptionTestMessage: "window.performance.measure(\"measure_nav_start_nav_end\", " +
+ "\"navigationStart\", \"responseEnd\") ran without throwing any exceptions.",
+ expectedStartTime: undefined,
+ expectedDuration: undefined,
+ entryMatch: undefined
+ }
+ ];
+
+ setup({explicit_done: true});
+
+ test_namespace();
+
+ function onload_test()
+ {
+ // test for existance of User Timing and Performance Timeline interface
+ if (window.performance.mark == undefined ||
+ window.performance.clearMarks == undefined ||
+ window.performance.measure == undefined ||
+ window.performance.clearMeasures == undefined ||
+ window.performance.getEntriesByName == undefined ||
+ window.performance.getEntriesByType == undefined ||
+ window.performance.getEntries == undefined)
+ {
+ test_true(false,
+ "The User Timing and Performance Timeline interfaces, which are required for this test, " +
+ "are defined.");
+
+ done();
+ }
+ else
+ {
+ // create the start mark for the test measures
+ window.performance.mark(startMarkName);
+
+ // get the start mark's value
+ startMarkValue = window.performance.getEntriesByName(startMarkName)[0].startTime;
+
+ // create the test end mark using the test delay; this will allow for a significant difference between
+ // the mark values that should be represented in the duration of measures using these marks
+ setTimeout(measure_test_cb, measureTestDelay);
+ }
+ }
+
+ function measure_test_cb()
+ {
+ // create the end mark for the test measures
+ window.performance.mark(endMarkName);
+
+ // get the end mark's value
+ endMarkValue = window.performance.getEntriesByName(endMarkName)[0].startTime;
+
+ // loop through measure scenarios
+ for (var i in TEST_MEASURES)
+ {
+ var scenario = TEST_MEASURES[i];
+
+ if (scenario.startMark != undefined && scenario.endMark == undefined)
+ {
+ // only startMark is defined, provide startMark and don't provide endMark
+ window.performance.measure(scenario.name, scenario.startMark);
+
+ // when startMark is provided to the measure() call, the value of the mark or navigation
+ // timing attribute whose name is provided is used for the startMark
+ scenario.expectedStartTime = (timingAttributes.indexOf(scenario.startMark) != -1 ?
+ window.performance.timing[scenario.startMark] -
+ window.performance.timing.navigationStart :
+ startMarkValue);
+
+ // when endMark isn't provided to the measure() call, a DOMHighResTimeStamp corresponding to
+ // the current time with a timebase of the navigationStart attribute is used
+ scenario.expectedDuration = ((new Date()) - window.performance.timing.navigationStart) -
+ scenario.expectedStartTime;
+ }
+ else if (scenario.startMark != undefined && scenario.endMark != undefined)
+ {
+ // both startMark and endMark are defined, provide both parameters
+ window.performance.measure(scenario.name, scenario.startMark, scenario.endMark);
+
+ // when startMark is provided to the measure() call, the value of the mark or navigation
+ // timing attribute whose name is provided is used for the startMark
+ scenario.expectedStartTime = (timingAttributes.indexOf(scenario.startMark) != -1 ?
+ window.performance.timing[scenario.startMark] -
+ window.performance.timing.navigationStart :
+ startMarkValue);
+
+ // when endMark is provided to the measure() call, the value of the mark whose name is
+ // provided is used for the startMark
+ scenario.expectedDuration = (timingAttributes.indexOf(scenario.endMark) != -1 ?
+ window.performance.timing[scenario.endMark] -
+ window.performance.timing.navigationStart :
+ endMarkValue) - scenario.expectedStartTime;
+ }
+ }
+
+ // test the test measures are returned by getEntriesByName
+ for (var i in TEST_MEASURES)
+ {
+ entries = window.performance.getEntriesByName(TEST_MEASURES[i].name);
+ test_measure(entries[0],
+ "window.performance.getEntriesByName(\"" + TEST_MEASURES[i].name + "\")[0]",
+ TEST_MEASURES[i].name,
+ TEST_MEASURES[i].expectedStartTime,
+ TEST_MEASURES[i].expectedDuration);
+ TEST_MEASURES[i].entryMatch = entries[0];
+ }
+
+ done();
+ }
+
+ function test_measure(measureEntry, measureEntryCommand, expectedName, expectedStartTime, expectedDuration)
+ {
+ // test name
+ test_true(measureEntry.name == expectedName, measureEntryCommand + ".name == \"" + expectedName + "\"");
+
+ // test startTime; since for a mark, the startTime is always equal to a mark's value or the value of a
+ // navigation timing attribute, the actual startTime should match the expected value exactly
+ test_true(Math.abs(measureEntry.startTime - expectedStartTime) == 0,
+ measureEntryCommand + ".startTime == " + expectedStartTime);
+
+ // test entryType
+ test_true(measureEntry.entryType == "measure", measureEntryCommand + ".entryType == \"measure\"");
+
+ // test duration, allow for an acceptable threshold in the difference between the actual duration and the
+ // expected value for the duration
+ test_true(Math.abs(measureEntry.duration - expectedDuration) <= testThreshold, measureEntryCommand +
+ ".duration ~== " + expectedDuration + " (up to " + testThreshold + "ms difference allowed)");
+ }
+ </script>
+ </head>
+ <body onload="onload_test();">
+ <h1>Description</h1>
+ <p>This test validates that the performance.measure() method is working properly when navigation timing
+ attributes are used in place of mark names. This test creates the following measures to test this method:
+ <ul>
+ <li>"measure_nav_start_no_end": created using a measure() call with a navigation timing attribute
+ provided as the startMark and nothing provided as the endMark</li>
+ <li>"measure_nav_start_mark_end": created using a measure() call with a navigation timing attribute
+ provided as the startMark and a mark name provided as the endMark</li>
+ <li>"measure_mark_start_nav_end": created using a measure() call with a mark name provided as the
+ startMark and a navigation timing attribute provided as the endMark</li>
+ <li>"measure_nav_start_nav_end":created using a measure() call with a navigation timing attribute
+ provided as both the startMark and endMark</li>
+ </ul>
+ After creating each measure, the existence of these measures is validated by calling
+ performance.getEntriesByName() with each measure name
+ </p>
+
+ <div id="log"></div>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/vibration/api-is-present.html b/tests/wpt/web-platform-tests/vibration/api-is-present.html
new file mode 100644
index 00000000000..8dde96c2b8c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/vibration/api-is-present.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset='utf-8'/>
+ <title>Vibration API: test that the vibrate() method is present (with or without vendor prefix)</title>
+ <link rel='author' title='Robin Berjon' href='mailto:robin@berjon.com'/>
+ <link rel='help' href='http://www.w3.org/TR/vibration/#methods'/>
+ <meta name='flags' content='dom'/>
+ <meta name='assert' content='Check that the vibrate() method is present.'/>
+ <link rel='stylesheet' href='/resources/testharness.css' media='all'/>
+ </head>
+ <body>
+ <h1>Description</h1>
+ <p>
+ This test checks for the presence of the <code>vibrate()</code> method, taking
+ vendor prefixes into account.
+ </p>
+ <div id='log'></div>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+ <script src='/common/vendor-prefix.js' data-prefixed-objects='[{"ancestors":["navigator"], "name":"vibrate"}]'></script>
+ <script>
+ test(function () {
+ assert_true(undefined !== navigator.vibrate, "navigator.vibrate exists");
+ }, "vibrate() is present on navigator");
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/vibration/cancel-when-hidden-manual.html b/tests/wpt/web-platform-tests/vibration/cancel-when-hidden-manual.html
new file mode 100644
index 00000000000..569970758a4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/vibration/cancel-when-hidden-manual.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<meta charset='utf-8'>
+<title>Vibration API: cancel ongoing vibrate() when hidden by switching tab/window</title>
+<link rel='author' title='Intel' href='http://www.intel.com'>
+<link rel='help' href='http://dev.w3.org/2009/dap/vibration/#vibration-interface'>
+<meta name='flags' content='interact'>
+<meta name='assert' content='If the visibilitychange event is dispatched at the Document in a browsing context, cancel the pre-existing instance of the processing vibration patterns algorithm'>
+<style>
+ button {
+ height: 100px;
+ width: 100px;
+ }
+</style>
+
+<h1>Description</h1>
+<p>
+ After hitting the button below, your device must vibrate for a short period of time (roughly one
+ second). If it vibrates for a longer time (roughly five seconds, it should feel somewhat long) then
+ the test has failed.
+</p>
+<button id='vib'>Vibrate!</button>
+<script src='/common/vendor-prefix.js' data-prefixed-objects='[{"ancestors":["navigator"], "name":"vibrate"}]'></script>
+<script>
+ var win;
+
+ if (undefined !== navigator.vibrate) {
+ document.getElementById('vib').onclick = function () {
+ navigator.vibrate(5000);
+ setTimeout(function () {
+ win = window.open('about:blank', '_blank');
+ setTimeout(function() {
+ win.close();
+ }, 100);
+ }, 1000);
+ };
+ }
+</script>
+
diff --git a/tests/wpt/web-platform-tests/vibration/cancel-with-0-manual.html b/tests/wpt/web-platform-tests/vibration/cancel-with-0-manual.html
new file mode 100644
index 00000000000..6890d5764a1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/vibration/cancel-with-0-manual.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset='utf-8'/>
+ <title>Vibration API: cancel ongoing vibrate() with 0</title>
+ <link rel='author' title='Robin Berjon' href='mailto:robin@berjon.com'/>
+ <link rel='help' href='http://www.w3.org/TR/vibration/#methods'/>
+ <meta name='flags' content='dom, interact'/>
+ <meta name='assert' content='If pattern is 0, cancel the pre-existing instance of the processing vibration patterns algorithm'/>
+ </head>
+ <body>
+ <h1>Description</h1>
+ <p>
+ After hitting the button below, your device must vibrate for a short period of time (roughly one
+ second). If it vibrates for a longer time (roughly five seconds, it should feel somewhat long) then
+ the test has failed.
+ </p>
+ <button id='vib'>Vibrate!</button>
+ <script src='/common/vendor-prefix.js' data-prefixed-objects='[{"ancestors":["navigator"], "name":"vibrate"}]'></script>
+ <script>
+ if (undefined !== navigator.vibrate) {
+ document.getElementById("vib").onclick = function () {
+ navigator.vibrate(5000);
+ setTimeout(function () {
+ navigator.vibrate(0);
+ }, 1000);
+ };
+ }
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/vibration/cancel-with-array-0-manual.html b/tests/wpt/web-platform-tests/vibration/cancel-with-array-0-manual.html
new file mode 100644
index 00000000000..60689cc2c38
--- /dev/null
+++ b/tests/wpt/web-platform-tests/vibration/cancel-with-array-0-manual.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<meta charset='utf-8'>
+<title>Vibration API: cancel ongoing vibrate() with [0]</title>
+<link rel='author' title='Intel' href='http://www.intel.com'>
+<link rel='help' href='http://dev.w3.org/2009/dap/vibration/#vibration-interface'>
+<meta name='flags' content='interact'>
+<meta name='assert' content='If pattern contains a single entry with a value of 0, cancel the pre-existing instance of the processing vibration patterns algorithm'>
+<style>
+ button {
+ height: 100px;
+ width: 100px;
+ }
+</style>
+
+<h1>Description</h1>
+<p>
+ After hitting the button below, your device must vibrate for a short period of time (roughly one
+ second). If it vibrates for a longer time (roughly five seconds, it should feel somewhat long) then
+ the test has failed.
+</p>
+<button id='vib'>Vibrate!</button>
+<script src='/common/vendor-prefix.js' data-prefixed-objects='[{"ancestors":["navigator"], "name":"vibrate"}]'></script>
+<script>
+ if (undefined !== navigator.vibrate) {
+ document.getElementById('vib').onclick = function () {
+ navigator.vibrate(5000);
+ setTimeout(function () {
+ navigator.vibrate([0]);
+ }, 1000);
+ };
+ }
+</script>
+
diff --git a/tests/wpt/web-platform-tests/vibration/cancel-with-empty-array-manual.html b/tests/wpt/web-platform-tests/vibration/cancel-with-empty-array-manual.html
new file mode 100644
index 00000000000..9d4be2b3adc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/vibration/cancel-with-empty-array-manual.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset='utf-8'/>
+ <title>Vibration API: cancel ongoing vibrate() with []</title>
+ <link rel='author' title='Robin Berjon' href='mailto:robin@berjon.com'/>
+ <link rel='help' href='http://www.w3.org/TR/vibration/#methods'/>
+ <meta name='flags' content='dom, interact'/>
+ <meta name='assert' content='If pattern is an empty list, cancel the pre-existing instance of the processing vibration patterns algorithm'/>
+ </head>
+ <body>
+ <h1>Description</h1>
+ <p>
+ After hitting the button below, your device must vibrate for a short period of time (roughly one
+ second). If it vibrates for a longer time (roughly five seconds, it should feel somewhat long) then
+ the test has failed.
+ </p>
+ <button id='vib'>Vibrate!</button>
+ <script src='/common/vendor-prefix.js' data-prefixed-objects='[{"ancestors":["navigator"], "name":"vibrate"}]'></script>
+ <script>
+ if (undefined !== navigator.vibrate) {
+ document.getElementById("vib").onclick = function () {
+ navigator.vibrate(5000);
+ setTimeout(function () {
+ navigator.vibrate([]);
+ }, 1000);
+ };
+ }
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/vibration/cancel-with-new-manual.html b/tests/wpt/web-platform-tests/vibration/cancel-with-new-manual.html
new file mode 100644
index 00000000000..1cd9daf172f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/vibration/cancel-with-new-manual.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset='utf-8'/>
+ <title>Vibration API: cancel ongoing vibrate() with a new call to vibrate</title>
+ <link rel='author' title='Robin Berjon' href='mailto:robin@berjon.com'/>
+ <link rel='help' href='http://www.w3.org/TR/vibration/#methods'/>
+ <meta name='flags' content='dom, interact'/>
+ <meta name='assert' content='Cancel the pre-existing instance of the processing vibration patterns algorithm, if any.'/>
+ </head>
+ <body>
+ <h1>Description</h1>
+ <p>
+ After hitting the button below, your device must vibrate continuously for a short period of time (roughly one
+ second), then vibrate a series of short bursts. If the initial continuously vibration is longer (roughly five
+ seconds, it should feel somewhat long) or if there is no series of short vibration bursts then the test has
+ failed.
+ </p>
+ <button id='vib'>Vibrate!</button>
+ <script src='/common/vendor-prefix.js' data-prefixed-objects='[{"ancestors":["navigator"], "name":"vibrate"}]'></script>
+ <script>
+ if (undefined !== navigator.vibrate) {
+ document.getElementById("vib").onclick = function () {
+ navigator.vibrate(5000);
+ setTimeout(function () {
+ navigator.vibrate([200, 200, 200, 200, 200, 200, 200, 200, 200]);
+ }, 1000);
+ };
+ }
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/vibration/idl.html b/tests/wpt/web-platform-tests/vibration/idl.html
new file mode 100644
index 00000000000..167090cd67b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/vibration/idl.html
@@ -0,0 +1,23 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>IDL harness tests for Vibration API</title>
+<body>
+ <h1>Description</h1>
+ <p>
+ This test validates the IDL defined by the Vibration API.
+ </p>
+ <p>
+ This test uses <a href="/resources/idlharness.js">idlharness.js</a>
+ </p>
+<div id="log"></div>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=/resources/WebIDLParser.js></script>
+<script src=/resources/idlharness.js></script>
+<script>
+var idl_array = new IdlArray();
+idl_array.add_untested_idls("interface Navigator {};");
+idl_array.add_idls("partial interface Navigator { boolean vibrate ((unsigned long or sequence<unsigned long>) pattern);};");
+idl_array.add_objects({Navigator: ['navigator']});
+idl_array.test();
+</script>
diff --git a/tests/wpt/web-platform-tests/vibration/invalid-values.html b/tests/wpt/web-platform-tests/vibration/invalid-values.html
new file mode 100644
index 00000000000..a544ac23c7e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/vibration/invalid-values.html
@@ -0,0 +1,79 @@
+<!DOCTYPE html>
+<meta charset='utf-8'>
+<title>Vibration API: vibrate(invalid)</title>
+<link rel='author' title='Intel' href='http://www.intel.com'>
+<link rel='help' href='http://dev.w3.org/2009/dap/vibration/#vibration-interface'>
+
+<h1>Description</h1>
+<p>
+ This test checks the <code>vibrate()</code> method with invalid parameter,
+ taking vendor prefixes into account.
+</p>
+<div id='log'></div>
+<script src='/resources/testharness.js'></script>
+<script src='/resources/testharnessreport.js'></script>
+<script src='../support/vendor-prefix.js' data-prefixed-objects='[{"ancestors":["navigator"], "name":"vibrate"}]'></script>
+<script>
+ test(function() {
+ assert_throws(new TypeError(), function() {
+ navigator.vibrate();
+ }, 'Argument is required, so was expecting a TypeError.');
+ }, 'Missing pattern argument');
+
+ test(function() {
+ try {
+ navigator.vibrate(undefined);
+ } catch(e) {
+ assert_unreached('error message: ' + e.message);
+ }
+ }, 'pattern of undefined resolves to []');
+
+ test(function() {
+ try {
+ navigator.vibrate(null);
+ } catch(e) {
+ assert_unreached('error message: ' + e.message);
+ }
+ }, 'pattern of null resolves to []');
+
+ test(function() {
+ try {
+ navigator.vibrate('one');
+ } catch(e) {
+ assert_unreached('error message: ' + e.message);
+ }
+ }, 'pattern of empty string resolves to [""]');
+
+ test(function() {
+ try {
+ navigator.vibrate('one');
+ } catch(e) {
+ assert_unreached('error message: ' + e.message);
+ }
+ }, 'pattern of string resolves to ["one"]');
+
+ test(function() {
+ try {
+ navigator.vibrate(new String('one'));
+ } catch(e) {
+ assert_unreached('error message: ' + e.message);
+ }
+ }, 'pattern of String instance resolves to ["one"]');
+
+ test(function() {
+ try {
+ navigator.vibrate(NaN);
+ } catch(e) {
+ assert_unreached('error message: ' + e.message);
+ }
+ }, 'pattern of NaN resolves to [NaN]');
+
+ test(function() {
+ try {
+ navigator.vibrate({});
+ } catch(e) {
+ assert_unreached('error message: ' + e.message);
+ }
+ }, 'pattern of {} resolves to [{}]');
+</script>
+
diff --git a/tests/wpt/web-platform-tests/vibration/pattern-array-extra-manual.html b/tests/wpt/web-platform-tests/vibration/pattern-array-extra-manual.html
new file mode 100644
index 00000000000..3f5ccf386fa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/vibration/pattern-array-extra-manual.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset='utf-8'/>
+ <title>Vibration API: test a pattern array parameter to vibrate() with an extra (even) item</title>
+ <link rel='author' title='Robin Berjon' href='mailto:robin@berjon.com'/>
+ <link rel='help' href='http://www.w3.org/TR/vibration/#methods'/>
+ <meta name='flags' content='dom, interact'/>
+ <meta name='assert' content='If the length of pattern is even, then remove the last entry in pattern.'/>
+ </head>
+ <body>
+ <h1>Description</h1>
+ <p>
+ After hitting the button below, your device must vibrate three times for one second, separated
+ by one second intervals.
+ </p>
+ <button id='vib'>Vibrate!</button>
+ <script src='/common/vendor-prefix.js' data-prefixed-objects='[{"ancestors":["navigator"], "name":"vibrate"}]'></script>
+ <script>
+ if (undefined !== navigator.vibrate) {
+ document.getElementById("vib").onclick = function () {
+ navigator.vibrate([1000, 1000, 1000, 1000, 1000, 1000]);
+ };
+ }
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/vibration/pattern-array-manual.html b/tests/wpt/web-platform-tests/vibration/pattern-array-manual.html
new file mode 100644
index 00000000000..43674bf8c5d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/vibration/pattern-array-manual.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset='utf-8'/>
+ <title>Vibration API: test a pattern array parameter to vibrate()</title>
+ <link rel='author' title='Robin Berjon' href='mailto:robin@berjon.com'/>
+ <link rel='help' href='http://www.w3.org/TR/vibration/#methods'/>
+ <meta name='flags' content='dom, interact'/>
+ </head>
+ <body>
+ <h1>Description</h1>
+ <p>
+ After hitting the button below, your device must vibrate three times for one second, separated
+ by one second intervals.
+ </p>
+ <button id='vib'>Vibrate!</button>
+ <script src='/common/vendor-prefix.js' data-prefixed-objects='[{"ancestors":["navigator"], "name":"vibrate"}]'></script>
+ <script>
+ if (undefined !== navigator.vibrate) {
+ document.getElementById("vib").onclick = function () {
+ navigator.vibrate([1000, 1000, 1000, 1000, 1000]);
+ };
+ }
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/vibration/pattern-array-with-0-manual.html b/tests/wpt/web-platform-tests/vibration/pattern-array-with-0-manual.html
new file mode 100644
index 00000000000..dff2f1ed7a1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/vibration/pattern-array-with-0-manual.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<meta charset='utf-8'>
+<title>Vibration API: test a pattern array with 0ms vibration and still to vibrate()</title>
+<link rel='author' title='Intel' href='http://www.intel.com'>
+<link rel='help' href='http://dev.w3.org/2009/dap/vibration/#vibration-interface'>
+<meta name='flags' content='interact'>
+<style>
+ button {
+ height: 100px;
+ width: 100px;
+ }
+</style>
+
+<h1>Description</h1>
+<p>
+ After hitting the button below, your device must vibrate continuously for about two seconds, once.
+</p>
+<button id='vib'>Vibrate!</button>
+<div id='log'></div>
+<script src='/common/vendor-prefix.js' data-prefixed-objects='[{"ancestors":["navigator"], "name":"vibrate"}]'></script>
+<script>
+ document.getElementById("vib").onclick = function () {
+ navigator.vibrate([0, 0, 2000]);
+ };
+</script>
+
diff --git a/tests/wpt/web-platform-tests/vibration/silent-ignore.html b/tests/wpt/web-platform-tests/vibration/silent-ignore.html
new file mode 100644
index 00000000000..ad6916fa687
--- /dev/null
+++ b/tests/wpt/web-platform-tests/vibration/silent-ignore.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset='utf-8'/>
+ <title>Vibration API: test that calls to vibrate() are silently ignored when the device cannot vibrate</title>
+ <link rel='author' title='Robin Berjon' href='mailto:robin@berjon.com'/>
+ <link rel='help' href='http://www.w3.org/TR/vibration/#methods'/>
+ <meta name='flags' content='dom, no-vibrator'/>
+ <meta name='assert' content='If the device does not provide a vibration mechanism, or it is disabled, the user agent must silently ignore any invocations of the vibrate() method.'/>
+ <link rel='stylesheet' href='/resources/testharness.css' media='all'/>
+ </head>
+ <body>
+ <h1>Description</h1>
+ <p>
+ <strong>This test is only useful on devices that do not have vibration capability</strong>.
+ If your device supports vibration, then <strong>skip</strong> this test. An implementation
+ supporting this API but running on a device that cannot vibrate must silently ignore the
+ call (we test that it doesn't throw).
+ </p>
+ <div id='log'></div>
+ <script src='/resources/testharness.js'></script>
+ <script src='/resources/testharnessreport.js'></script>
+ <script src='/common/vendor-prefix.js' data-prefixed-objects='[{"ancestors":["navigator"], "name":"vibrate"}]'></script>
+ <script>
+ if (undefined !== navigator.vibrate) {
+ test(function () {
+ assert_true(navigator.vibrate(1000), "vibrate() returns true when vibration is not supported");
+ }, "Calling vibrate returns true");
+ }
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/vibration/simple-array-manual.html b/tests/wpt/web-platform-tests/vibration/simple-array-manual.html
new file mode 100644
index 00000000000..4a85bd6ad05
--- /dev/null
+++ b/tests/wpt/web-platform-tests/vibration/simple-array-manual.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset='utf-8'/>
+ <title>Vibration API: test a simple array parameter to vibrate()</title>
+ <link rel='author' title='Robin Berjon' href='mailto:robin@berjon.com'/>
+ <link rel='help' href='http://www.w3.org/TR/vibration/#methods'/>
+ </head>
+ <body>
+ <h1>Description</h1>
+ <p>
+ After hitting the button below, your device must vibrate continuously for about two seconds, once.
+ </p>
+ <button id='vib'>Vibrate!</button>
+ <div id='log'></div>
+ <script src='/common/vendor-prefix.js' data-prefixed-objects='[{"ancestors":["navigator"], "name":"vibrate"}]'></script>
+ <script>
+ document.getElementById("vib").onclick = function () {
+ navigator.vibrate([2000]);
+ };
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/vibration/simple-scalar-manual.html b/tests/wpt/web-platform-tests/vibration/simple-scalar-manual.html
new file mode 100644
index 00000000000..0c7637bbad3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/vibration/simple-scalar-manual.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset='utf-8'/>
+ <title>Vibration API: test a simple scalar parameter to vibrate()</title>
+ <link rel='author' title='Robin Berjon' href='mailto:robin@berjon.com'/>
+ <link rel='help' href='http://www.w3.org/TR/vibration/#methods'/>
+ <meta name='flags' content='dom, interact'/>
+ </head>
+ <body>
+ <h1>Description</h1>
+ <p>
+ After hitting the button below, your device must vibrate continuously for about two seconds, once.
+ </p>
+ <button id='vib'>Vibrate!</button>
+ <script src='/common/vendor-prefix.js' data-prefixed-objects='[{"ancestors":["navigator"], "name":"vibrate"}]'></script>
+ <script>
+ if (undefined !== navigator.vibrate) {
+ document.getElementById("vib").onclick = function () {
+ navigator.vibrate(2000);
+ };
+ }
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/web-animations/README.md b/tests/wpt/web-platform-tests/web-animations/README.md
new file mode 100644
index 00000000000..7afc875a1ff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/web-animations/README.md
@@ -0,0 +1,4 @@
+Web Animations Tests
+====================
+
+Specification: http://w3c.github.io/web-animations/
diff --git a/tests/wpt/web-platform-tests/web-animations/animation-node/animation-node-after.html b/tests/wpt/web-platform-tests/web-animations/animation-node/animation-node-after.html
new file mode 100644
index 00000000000..4d56dbaedff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/web-animations/animation-node/animation-node-after.html
@@ -0,0 +1,420 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>AnimationNode after() method tests</title>
+<meta name="assert" content="Inserts nodes after this animation node">
+<link rel="help" href="http://w3c.github.io/web-animations/#dom-animationnode-after">
+<link rel="help" href="http://w3c.github.io/web-animations/#insert-children">
+<link rel="help" href="http://w3c.github.io/web-animations/#remove-an-animation-node">
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+<body>
+<div id="log"></div>
+<script>
+// Test step 1. If there is no parent animation group, terminate these steps.
+test(function() {
+ var nodes = [newAnimation(createDiv(this)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node) {
+ try {
+ node.after(null);
+ } catch(e) {
+ assert_unreached(type(node) + '.after(null) throws unexpected exception: ' + e);
+ }
+ });
+}, 'AnimationNode.after() does nothing if the node has no parent animation group. ' +
+ 'HierarchyRequestError is not thrown in call node.after(null)');
+
+test(function() {
+ var nodes = [newAnimation(createDiv(this)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node) {
+ try {
+ node.after(node);
+ } catch(e) {
+ assert_unreached(type(node) + '.after() throws unexpected exception: ' + e);
+ }
+ });
+}, 'AnimationNode.after() does nothing if the node has no parent animation group. ' +
+ 'No HierarchyRequestError is thrown if the node is inserted after itself');
+
+test(function() {
+ var nodes = [newAnimation(createDiv(this)), new AnimationGroup([]), new AnimationSequence([])];
+ var node2 = newAnimation(createDiv(this));
+ nodes.forEach(function(node1) {
+ node1.after(node2);
+
+ assert_equals(node1.nextSibling, null, type(node1) + '.after() should do nothing ' +
+ 'if the node has no parent animation group');
+ assert_equals(node2.previousSibling, null, type(node1) + '.after() should do nothing ' +
+ 'if the node has no parent animation group');
+ });
+}, 'AnimationNode.after() does nothing if there is no parent animation group');
+
+// Test step 2. If any of the animation nodes in nodes is an inclusive ancestor of this animation node throw a HierarchyRequestError exception and terminate these steps.
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node) {
+ var parent = new parentCtor([node]);
+
+ assert_throws('HierarchyRequestError', function() {
+ node.after(node);
+ }, type(node) + '.after() should throw HierarchyRequestError ' +
+ 'if inserting node after itself');
+ assert_equals(node.parent, parent, type(node) + '.after() should not change ' +
+ 'parent attribute before throwing HierarchyRequestError');
+ assert_array_equals(parent.children, [node], type(node) + '.after() ' +
+ 'should not change parent children before throwing HierarchyRequestError');
+ });
+ });
+}, 'HierarchyRequestError is thrown if node is inserted after itself');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node) {
+ var parent = new parentCtor([node]);
+
+ assert_throws('HierarchyRequestError', function() {
+ node.after(parent);
+ }, type(node) + '.after() should throw HierarchyRequestError ' +
+ 'if inserting node\'s parent');
+ assert_equals(node.parent, parent, type(node) + '.after() should not change ' +
+ 'parent attribute before throwing HierarchyRequestError');
+ assert_array_equals(parent.children, [node], type(node) + '.after() ' +
+ 'should not change parent children before throwing HierarchyRequestError');
+ });
+ });
+}, 'HierarchyRequestError is thrown if direct parent is inserted after the node');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node) {
+ var parent1 = new parentCtor([node]);
+ var parent2 = new parentCtor([parent1]);
+ var parent3 = new parentCtor([parent2]);
+ var parent4 = new parentCtor([parent3]);
+
+ assert_throws('HierarchyRequestError', function() {
+ node.after(parent3);
+ }, type(node) + '.after() should throw HierarchyRequestError ' +
+ 'if inserting node\'s ancestor');
+ assert_equals(node.parent, parent1, type(node) + '.after() should not change ' +
+ 'parent attribute before throwing HierarchyRequestError');
+ assert_array_equals(parent1.children, [node], type(node) + '.after() ' +
+ 'should not change parent children before throwing HierarchyRequestError');
+ assert_equals(parent3.parent, parent4, type(node) + '.after() should not change ' +
+ 'parent attribute of inserted node before throwing HierarchyRequestError');
+ assert_array_equals(parent4.children, [parent3], type(node) + '.after() ' +
+ 'should not change inserted node parent children before throwing HierarchyRequestError');
+ });
+ });
+}, 'HierarchyRequestError is thrown if an inclusive ancestor is inserted after the node');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node1) {
+ var node2 = newAnimation(createDiv(test));
+ var node3 = newAnimation(createDiv(test));
+ var parent1 = new parentCtor([node1, node2]);
+ var parent2 = new parentCtor([parent1]);
+ var parent3 = new parentCtor([parent2]);
+ var parent4 = new parentCtor([parent3]);
+ var parent5 = new ParentCtor([node3]);
+
+ assert_throws('HierarchyRequestError', function() {
+ node1.after(node3, parent3);
+ }, type(node1) + '.after() should throw HierarchyRequestError ' +
+ 'if inserting node\'s parent');
+ assert_equals(node1.parent, parent1, type(node1) + '.after() should not change ' +
+ 'parent attribute before throwing HierarchyRequestError');
+ assert_array_equals(parent1.children, [node1, node2], type(node1) + '.after() ' +
+ 'should not change parent children before throwing HierarchyRequestError');
+ assert_equals(parent3.parent, parent4, type(node1) + '.after() should not change ' +
+ 'parent attribute of inserted node before throwing HierarchyRequestError');
+ assert_array_equals(parent4.children, [parent3], type(node1) + '.after() ' +
+ 'should not change inserted node parent children before throwing HierarchyRequestError');
+ assert_equals(node3.parent, parent5, type(node1) + '.after() should not change ' +
+ 'parent attribute of inserted node before throwing HierarchyRequestError');
+ assert_array_equals(parent5.children, [node3], type(node1) + '.after() ' +
+ 'should not change inserted node parent children before throwing HierarchyRequestError');
+ });
+ });
+}, 'HierarchyRequestError is thrown if an inclusive ancestor is inserted after the node. ' +
+ 'Test several arguments in after() call');
+
+// Test step 3 and 4.
+// 3. Let reference child be the next sibling of this animation node not in nodes.
+// 4. Insert nodes before reference child.
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node1) {
+ var node2 = newAnimation(createDiv(test));
+ var parent = new parentCtor([node1]);
+
+ node1.after(node2);
+
+ assert_equals(node2.previousSibling, node1, type(node1) + '.after() should insert ' +
+ 'nodes after this node');
+ assert_equals(node2.parent, parent, 'Node should be inserted into the tree');
+ assert_equals(node1.nextSibling, node2, 'Node should be inserted into the tree ' +
+ 'after this node');
+ assert_equals(parent.children, [node1, node2], parentCtor.name +
+ '.children should be updated');
+ });
+ });
+}, 'AnimationNode.after() inserts nodes after this node');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node2) {
+ var node1 = newAnimation(createDiv(test));
+ var parent = new parentCtor([node1, node2]);
+
+ node2.after(node1);
+
+ assert_equals(node2.previousSibling, null, type(node2) + '.after() should insert ' +
+ 'nodes after this node');
+ assert_equals(node2.nextSibling, node1, 'Node should be inserted into the tree ' +
+ 'after this node');
+ assert_equals(node1.previousSibling, node2, type(node2) + '.after() should insert ' +
+ 'nodes after this node');
+ assert_equals(node1.nextSibling, null, 'Node should be inserted into the tree ' +
+ 'after this node');
+ assert_equals(parent.children, [node2, node1], parentCtor.name +
+ '.children should be updated');
+ });
+ });
+}, 'AnimationNode.after() inserts nodes after this node. Inserted node is on the same ' +
+ 'level in the tree');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node1) {
+ var node2 = newAnimation(createDiv(test));
+ var parent = new parentCtor([node1, node2]);
+
+ node1.after(node2);
+
+ assert_equals(node1.nextSibling, node2, type(node1) + '.after() should insert ' +
+ 'nodes after this node');
+ assert_equals(node2.previousSibling, node1, 'Node should be inserted into the tree ' +
+ 'after this node');
+ assert_equals(parent.children, [node1, node2], parentCtor.name +
+ '.children should not be changed');
+ });
+ });
+}, 'Test AnimationNode.after() inserts node after this node even if inserted ' +
+ 'node is already after this one');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node3) {
+ var node1 = newAnimation(createDiv(test));
+ var node2 = newAnimation(createDiv(test));
+ var node4 = newAnimation(createDiv(test));
+ var parent1 = new parentCtor([node1, node2]);
+ var parent2 = new parentCtor([node3, parent1, node4]);
+
+ node3.after(node1);
+
+ assert_equals(node1.nextSibling, parent1, type(node3) + '.after() should insert ' +
+ 'nodes after this node');
+ assert_equals(node1.parent, parent2, 'Parent group of the inserted node should be changed');
+ assert_equals(node1.previousSibling, node3, 'Node should be inserted into the tree ' +
+ 'after this node');
+
+ assert_equals(node3.nextSibling, node1, type(node3) + '.after() should insert ' +
+ 'nodes after this node');
+ assert_equals(parent1.previousSibling, node1, type(node3) + '.after() should insert ' +
+ 'nodes after this node');
+
+ assert_equals(node2.previousSibling, null, 'Inserted node should be removed from its ' +
+ 'previous position in the tree');
+ assert_array_equals(parent1.children, [node2], 'Inserted node should be removed from its ' +
+ 'previous position in the tree');
+ assert_array_equals(parent2.children, [node1, node3, parent1, node4], parentCtor.name +
+ '.children should be updated');
+ });
+ });
+}, 'Test AnimationNode.after() inserts node after this node. The previous position ' +
+ 'of the inserted node is deeper in the tree than current node');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node1) {
+ var node2 = newAnimation(createDiv(test));
+ var node3 = newAnimation(createDiv(test));
+ var node4 = newAnimation(createDiv(test));
+ var parent1 = new parentCtor([node1, node2]);
+ var parent2 = new parentCtor([node3, parent1, node4]);
+
+ node1.after(node4);
+
+ assert_equals(node4.nextSibling, node2, type(node1) + '.after() should insert ' +
+ 'nodes after this node');
+ assert_equals(node4.parent, parent1, 'Parent group of the inserted node should be changed');
+ assert_equals(node4.previousSibling, node1, type(node1) + '.after() should insert ' +
+ 'nodes after this node');
+
+ assert_equals(node1.nextSibling, node4, type(node1) + '.after() should insert ' +
+ 'nodes after this node');
+ assert_equals(node2.previousSibling, node4, 'Node should be inserted into the tree ' +
+ 'after this node');
+
+ assert_equals(parent1.nextSibling, null, 'Inserted node should be removed from its ' +
+ 'previous position in the tree');
+ assert_array_equals(parent1.children, [node1, node4, node2], parentCtor.name +
+ '.children should be updated');
+ assert_array_equals(parent2.children, [node3, parent1], 'Inserted node should be ' +
+ 'removed from its previous position in the tree');
+ });
+ });
+}, 'Test AnimationNode.after() inserts node after this node. The previous position ' +
+ 'of the inserted node is shallower in the tree than current node, but not ancestor');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node1) {
+ var node2 = newAnimation(createDiv(test));
+ var node3 = newAnimation(createDiv(test));
+ var node4 = newAnimation(createDiv(test));
+ var parent = new parentCtor([node1, node2]);
+
+ node1.after(node3, node4);
+
+ assert_equals(node1.nextSibling, node3, type(node1) + '.after() should insert ' +
+ 'nodes after this node');
+ assert_equals(node3.previousSibling, node1, type(node1) + '.after() should insert ' +
+ 'nodes after this node');
+ assert_equals(node3.nextSibling, node4, type(node1) + '.after() should insert ' +
+ 'nodes after this node');
+ assert_equals(node3.parent, parent, 'Parent group of the inserted node should be changed');
+ assert_equals(node4.previousSibling, node3, type(node1) + '.after() should insert ' +
+ 'nodes after this node');
+ assert_equals(node4.nextSibling, node2, type(node1) + '.after() should insert ' +
+ 'nodes after this node');
+ assert_equals(node4.parent, parent, 'Parent group of the inserted node should be changed');
+ assert_equals(node2.previousSibling, node4, type(node1) + '.after() should insert ' +
+ 'nodes after this node');
+ assert_array_equals(parent.children, [node1, node3, node4, node2], parentCtor.name +
+ '.children should be updated');
+ });
+ });
+}, 'Test AnimationNode.after() inserts several nodes after this node');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node1) {
+ var node2 = newAnimation(createDiv(test));
+ var node3 = newAnimation(createDiv(test));
+ var node4 = newAnimation(createDiv(test));
+ var parent = new parentCtor([node1, node2]);
+
+ node1.after(node3, node4, node3, node4);
+
+ assert_equals(node1.nextSibling, node3, type(node1) + '.after() should insert ' +
+ 'nodes after this node');
+ assert_equals(node3.previousSibling, node1, type(node1) + '.after() should insert ' +
+ 'nodes after this node');
+ assert_equals(node3.nextSibling, node4, type(node1) + '.after() should insert ' +
+ 'nodes after this node');
+ assert_equals(node3.parent, parent, 'Parent group of the inserted node should be changed');
+ assert_equals(node4.previousSibling, node3, type(node1) + '.after() should insert ' +
+ 'nodes after this node');
+ assert_equals(node4.nextSibling, node2, type(node1) + '.after() should insert ' +
+ 'nodes after this node');
+ assert_equals(node4.parent, parent, 'Parent group of the inserted node should be changed');
+ assert_equals(node2.previousSibling, node4, type(node1) + '.after() should insert ' +
+ 'nodes after this node');
+ assert_array_equals(parent.children, [node1, node3, node4, node2], parentCtor.name +
+ '.children should be updated');
+ });
+ });
+}, 'Test AnimationNode.after() inserts several nodes after this node, duplicate nodes are ignored');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node1) {
+ var node2 = newAnimation(createDiv(test));
+ var node3 = newAnimation(createDiv(test));
+ var node4 = newAnimation(createDiv(test));
+ var parent = new parentCtor([node1, node2]);
+
+ node1.after(node3, node4, node3);
+
+ assert_equals(node1.nextSibling, node4, type(node1) + '.after() should insert ' +
+ 'nodes after this node');
+ assert_equals(node4.previousSibling, node1, type(node1) + '.after() should insert ' +
+ 'nodes after this node');
+ assert_equals(node4.nextSibling, node3, type(node1) + '.after() should insert ' +
+ 'nodes after this node');
+ assert_equals(node4.parent, parent, 'Parent group of the inserted node should be changed');
+ assert_equals(node3.previousSibling, node4, type(node1) + '.after() should insert ' +
+ 'nodes after this node');
+ assert_equals(node3.nextSibling, node2, type(node1) + '.after() should insert ' +
+ 'nodes after this node');
+ assert_equals(node3.parent, parent, 'Parent group of the inserted node should be changed');
+ assert_equals(node2.previousSibling, node3, type(node1) + '.after() should insert ' +
+ 'nodes after this node');
+ assert_array_equals(parent.children, [node1, node4, node3, node2], parentCtor.name +
+ '.children should be updated');
+ });
+ });
+}, 'Test AnimationNode.after() inserts several nodes after this node, check insertion order');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node2) {
+ var node1 = newAnimation(createDiv(test));
+ var parent = new parentCtor([node1]);
+ var player = document.timeline.play(node2);
+
+ assert_equals(player.source, node2, 'The node should be associated with its player');
+ node1.after(node2);
+ assert_equals(player.source, null, 'The node should be disassociated from its player');
+ });
+ });
+}, 'Test AnimationNode.after() disassociates the inserted node from the player, ' +
+ 'if node is directly associated with a player');
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/web-animations/animation-node/animation-node-before.html b/tests/wpt/web-platform-tests/web-animations/animation-node/animation-node-before.html
new file mode 100644
index 00000000000..8eaa9ccf7d8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/web-animations/animation-node/animation-node-before.html
@@ -0,0 +1,419 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>AnimationNode before() method tests</title>
+<meta name="assert" content="Inserts nodes before this animation node.">
+<link rel="help" href="http://w3c.github.io/web-animations/#dom-animationnode-before">
+<link rel="help" href="http://w3c.github.io/web-animations/#insert-children">
+<link rel="help" href="http://w3c.github.io/web-animations/#remove-an-animation-node">
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+<body>
+<div id="log"></div>
+<script>
+// Test step 1. If there is no parent animation group, terminate these steps.
+test(function() {
+ var nodes = [newAnimation(createDiv(this)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node) {
+ try {
+ node.before(null);
+ } catch(e) {
+ assert_unreached(type(node) + '.before(null) throws unexpected exception: ' + e);
+ }
+ });
+}, 'AnimationNode.before() does nothing if the node has no parent animation group. ' +
+ 'HierarchyRequestError is not thrown in call node.before(null)');
+
+test(function() {
+ var nodes = [newAnimation(createDiv(this)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node) {
+ try {
+ node.before(node);
+ } catch(e) {
+ assert_unreached(type(node) + '.before() throws unexpected exception: ' + e);
+ }
+ });
+}, 'AnimationNode.before() does nothing if the node has no parent animation group. ' +
+ 'No HierarchyRequestError is thrown if the node is inserted before itself');
+
+test(function() {
+ var nodes = [newAnimation(createDiv(this)), new AnimationGroup([]), new AnimationSequence([])];
+ var node2 = newAnimation(createDiv(this));
+ nodes.forEach(function(node1) {
+ node1.before(node2);
+
+ assert_equals(node1.nextSibling, null, type(node1) + '.before() should do nothing ' +
+ 'if the node has no parent animation group');
+ assert_equals(node2.previousSibling, null, type(node1) + '.before() should do nothing ' +
+ 'if the node has no parent animation group');
+ });
+}, 'AnimationNode.before() does nothing if there is no parent animation group');
+
+// Test step 2. If any of the animation nodes in nodes is an inclusive ancestor of this animation node throw a HierarchyRequestError exception and terminate these steps.
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node) {
+ var parent = new parentCtor([node]);
+
+ assert_throws('HierarchyRequestError', function() {
+ node.before(node);
+ }, type(node) + '.before() should throw HierarchyRequestError ' +
+ 'if inserting node before itself');
+ assert_equals(node.parent, parent, type(node) + '.before() should not change ' +
+ 'parent attribute before throwing HierarchyRequestError');
+ assert_array_equals(parent.children, [node], type(node) + '.before() ' +
+ 'should not change parent children before throwing HierarchyRequestError');
+
+ });
+ });
+}, 'HierarchyRequestError is thrown if node is inserted before itself');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node) {
+ var parent = new parentCtor([node]);
+
+ assert_throws('HierarchyRequestError', function() {
+ node.before(parent);
+ }, type(node) + '.before() should throw HierarchyRequestError ' +
+ 'if inserting node\'s parent');
+ assert_equals(node.parent, parent, type(node) + '.before() should not change ' +
+ 'parent attribute before throwing HierarchyRequestError');
+ assert_array_equals(parent.children, [node], type(node) + '.before() ' +
+ 'should not change parent children before throwing HierarchyRequestError');
+ });
+ });
+}, 'HierarchyRequestError is thrown if direct parent is inserted before the node');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node) {
+ var parent1 = new parentCtor([node]);
+ var parent2 = new parentCtor([parent1]);
+ var parent3 = new parentCtor([parent2]);
+ var parent4 = new parentCtor([parent3]);
+
+ assert_throws('HierarchyRequestError', function() {
+ node.before(parent4);
+ }, type(node) + '.before() should throw HierarchyRequestError ' +
+ 'if inserting node\'s ancestor');
+ assert_equals(node.parent, parent1, type(node) + '.before() should not change ' +
+ 'parent attribute before throwing HierarchyRequestError');
+ assert_array_equals(parent1.children, [node], type(node) + '.before() ' +
+ 'should not change parent children before throwing HierarchyRequestError');
+ assert_equals(parent3.parent, parent4, type(node) + '.before() should not change ' +
+ 'parent attribute of inserted node before throwing HierarchyRequestError');
+ assert_array_equals(parent4.children, [parent3], type(node) + '.before() ' +
+ 'should not change inserted node parent children before throwing HierarchyRequestError');
+ });
+ });
+}, 'HierarchyRequestError is thrown if an inclusive ancestor is inserted before the node');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node1) {
+ var node2 = newAnimation(createDiv(test));
+ var node3 = newAnimation(createDiv(test));
+ var parent1 = new parentCtor([node1, node2]);
+ var parent2 = new parentCtor([parent1]);
+ var parent3 = new parentCtor([parent2]);
+ var parent4 = new parentCtor([parent3]);
+ var parent5 = new ParentCtor([node3]);
+
+ assert_throws('HierarchyRequestError', function() {
+ node1.before(node3, parent3);
+ }, type(node1) + '.before() should throw HierarchyRequestError ' +
+ 'if inserting node\'s parent');
+ assert_equals(node1.parent, parent1, type(node1) + '.before() should not change ' +
+ 'parent attribute before throwing HierarchyRequestError');
+ assert_array_equals(parent1.children, [node1, node2], type(node1) + '.before() ' +
+ 'should not change parent children before throwing HierarchyRequestError');
+ assert_equals(parent3.parent, parent4, type(node1) + '.before() should not change ' +
+ 'parent attribute of inserted node before throwing HierarchyRequestError');
+ assert_array_equals(parent4.children, [parent3], type(node1) + '.before() ' +
+ 'should not change inserted node parent children before throwing HierarchyRequestError');
+ assert_equals(node3.parent, parent5, type(node1) + '.before() should not change ' +
+ 'parent attribute of inserted node before throwing HierarchyRequestError');
+ assert_array_equals(parent5.children, [node3], type(node1) + '.before() ' +
+ 'should not change inserted node parent children before throwing HierarchyRequestError');
+ });
+ });
+}, 'HierarchyRequestError is thrown if an inclusive ancestor is inserted before the node. ' +
+ 'Test several arguments in before() call');
+
+// Test step 3. Insert nodes before this animation node.
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node1) {
+ var node2 = newAnimation(createDiv(test));
+ var parent = new parentCtor([node1]);
+
+ node1.before(node2);
+
+ assert_equals(node1.previousSibling, node2, type(node1) + '.before() should insert ' +
+ 'nodes before this node');
+ assert_equals(node2.parent, parent, 'Node should be inserted into the tree');
+ assert_equals(node2.nextSibling, node1, 'Node should be inserted into the tree ' +
+ 'before this node');
+ assert_equals(parent.children, [node2, node1], parentCtor.name +
+ '.children should be updated');
+ });
+ });
+}, 'AnimationNode.before() inserts nodes before this node');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node1) {
+ var node2 = newAnimation(createDiv(test));
+ var parent = new parentCtor([node1, node2]);
+
+ node1.before(node2);
+
+ assert_equals(node2.previousSibling, null, type(node1) + '.before() should insert ' +
+ 'nodes before this node');
+ assert_equals(node2.nextSibling, node1, 'Node should be inserted into the tree ' +
+ 'before this node');
+ assert_equals(node1.previousSibling, node2, type(node1) + '.before() should insert ' +
+ 'nodes before this node');
+ assert_equals(node1.nextSibling, null, 'Node should be inserted into the tree ' +
+ 'before this node');
+ assert_equals(parent.children, [node2, node1], parentCtor.name +
+ '.children should be updated');
+ });
+ });
+}, 'AnimationNode.before() inserts nodes before this node. Inserted node is on the same ' +
+ 'level in the tree');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node2) {
+ var node1 = newAnimation(createDiv(test));
+ var parent = new parentCtor([node1, node2]);
+
+ node2.before(node1);
+
+ assert_equals(node1.nextSibling, node2, type(node2) + '.before() should insert ' +
+ 'nodes before this node');
+ assert_equals(node2.previousSibling, node1, 'Node should be inserted into the tree ' +
+ 'before this node');
+ assert_equals(parent.children, [node1, node2], parentCtor.name +
+ '.children should not be changed');
+ });
+ });
+}, 'Test AnimationNode.before() inserts node before this node even if inserted ' +
+ 'node is already before this one');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node4) {
+ var node1 = newAnimation(createDiv(test));
+ var node2 = newAnimation(createDiv(test));
+ var node3 = newAnimation(createDiv(test));
+ var parent1 = new parentCtor([node1, node2]);
+ var parent2 = new parentCtor([node3, parent1, node4]);
+
+ node4.before(node1);
+
+ assert_equals(node1.nextSibling, parent1, type(node4) + '.before() should insert ' +
+ 'nodes before this node');
+ assert_equals(node1.parent, parent2, 'Parent group of the inserted node should be changed');
+ assert_equals(node1.previousSibling, parent1, 'Node should be inserted into the tree ' +
+ 'before this node');
+
+ assert_equals(parent1.nextSibling, node1, type(node4) + '.before() should insert ' +
+ 'nodes before this node');
+ assert_equals(node4.previousSibling, node1, type(node4) + '.before() should insert ' +
+ 'nodes before this node');
+
+ assert_equals(node2.previousSibling, null, 'Inserted node should be removed from its ' +
+ 'previous position in the tree');
+ assert_array_equals(parent1.children, [node2], 'Inserted node should be removed from its ' +
+ 'previous position in the tree');
+ assert_array_equals(parent2.children, [node3, parent1, node1, node4], parentCtor.name +
+ '.children should be updated');
+ });
+ });
+}, 'Test AnimationNode.before() inserts node before this node. The previous position ' +
+ 'of the inserted node is deeper in the tree than current node');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node2) {
+ var node1 = newAnimation(createDiv(test));
+ var node3 = newAnimation(createDiv(test));
+ var node4 = newAnimation(createDiv(test));
+ var parent1 = new parentCtor([node1, node2]);
+ var parent2 = new parentCtor([node3, parent1, node4]);
+
+ node2.before(node4);
+
+ assert_equals(node4.nextSibling, node2, type(node2) + '.before() should insert ' +
+ 'nodes before this node');
+ assert_equals(node4.parent, parent1, 'Parent group of the inserted node should be changed');
+ assert_equals(node4.previousSibling, node1, type(node2) + '.before() should insert ' +
+ 'nodes before this node');
+
+ assert_equals(node1.nextSibling, node4, type(node2) + '.before() should insert ' +
+ 'nodes before this node');
+ assert_equals(node2.previousSibling, node4, 'Node should be inserted into the tree ' +
+ 'before this node');
+
+ assert_equals(parent1.nextSibling, null, 'Inserted node should be removed from its ' +
+ 'previous position in the tree');
+ assert_array_equals(parent1.children, [node1, node4, node2], parentCtor.name +
+ '.children should be updated');
+ assert_array_equals(parent2.children, [node3, parent1], 'Inserted node should be ' +
+ 'removed from its previous position in the tree');
+ });
+ });
+}, 'Test AnimationNode.before() inserts node before this node. The previous position ' +
+ 'of the inserted node is shallower in the tree than current node, but not ancestor');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node2) {
+ var node1 = newAnimation(createDiv(test));
+ var node3 = newAnimation(createDiv(test));
+ var node4 = newAnimation(createDiv(test));
+ var parent = new parentCtor([node1, node2]);
+
+ node2.before(node3, node4);
+
+ assert_equals(node1.nextSibling, node3, type(node1) + '.before() should insert ' +
+ 'nodes before this node');
+ assert_equals(node3.previousSibling, node1, type(node1) + '.before() should insert ' +
+ 'nodes before this node');
+ assert_equals(node3.nextSibling, node4, type(node1) + '.before() should insert ' +
+ 'nodes before this node');
+ assert_equals(node3.parent, parent, 'Parent group of the inserted node should be changed');
+ assert_equals(node4.previousSibling, node3, type(node1) + '.before() should insert ' +
+ 'nodes before this node');
+ assert_equals(node4.nextSibling, node2, type(node1) + '.before() should insert ' +
+ 'nodes before this node');
+ assert_equals(node4.parent, parent, 'Parent group of the inserted node should be changed');
+ assert_equals(node2.previousSibling, node4, type(node1) + '.before() should insert ' +
+ 'nodes before this node');
+ assert_array_equals(parent.children, [node1, node3, node4, node2], parentCtor.name +
+ '.children should be updated');
+ });
+ });
+}, 'Test AnimationNode.before() inserts several nodes before this node');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node2) {
+ var node1 = newAnimation(createDiv(test));
+ var node3 = newAnimation(createDiv(test));
+ var node4 = newAnimation(createDiv(test));
+ var parent = new parentCtor([node1, node2]);
+
+ node2.before(node3, node4, node3, node4);
+
+ assert_equals(node1.nextSibling, node3, type(node1) + '.before() should insert ' +
+ 'nodes before this node');
+ assert_equals(node3.previousSibling, node1, type(node1) + '.before() should insert ' +
+ 'nodes before this node');
+ assert_equals(node3.nextSibling, node4, type(node1) + '.before() should insert ' +
+ 'nodes before this node');
+ assert_equals(node3.parent, parent, 'Parent group of the inserted node should be changed');
+ assert_equals(node4.previousSibling, node3, type(node1) + '.before() should insert ' +
+ 'nodes before this node');
+ assert_equals(node4.nextSibling, node2, type(node1) + '.before() should insert ' +
+ 'nodes before this node');
+ assert_equals(node4.parent, parent, 'Parent group of the inserted node should be changed');
+ assert_equals(node2.previousSibling, node4, type(node1) + '.before() should insert ' +
+ 'nodes before this node');
+ assert_array_equals(parent.children, [node1, node3, node4, node2], parentCtor.name +
+ '.children should be updated');
+ });
+ });
+}, 'Test AnimationNode.before() inserts several nodes before this node, duplicate nodes are ignored');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node2) {
+ var node1 = newAnimation(createDiv(test));
+ var node3 = newAnimation(createDiv(test));
+ var node4 = newAnimation(createDiv(test));
+ var parent = new parentCtor([node1, node2]);
+
+ node2.before(node3, node4, node3);
+
+ assert_equals(node1.nextSibling, node4, type(node1) + '.before() should insert ' +
+ 'nodes before this node');
+ assert_equals(node4.previousSibling, node1, type(node1) + '.before() should insert ' +
+ 'nodes before this node');
+ assert_equals(node4.nextSibling, node3, type(node1) + '.before() should insert ' +
+ 'nodes before this node');
+ assert_equals(node4.parent, parent, 'Parent group of the inserted node should be changed');
+ assert_equals(node3.previousSibling, node4, type(node1) + '.before() should insert ' +
+ 'nodes before this node');
+ assert_equals(node3.nextSibling, node2, type(node1) + '.before() should insert ' +
+ 'nodes before this node');
+ assert_equals(node3.parent, parent, 'Parent group of the inserted node should be changed');
+ assert_equals(node2.previousSibling, node3, type(node1) + '.before() should insert ' +
+ 'nodes before this node');
+ assert_array_equals(parent.children, [node1, node4, node3, node2], parentCtor.name +
+ '.children should be updated');
+ });
+ });
+}, 'Test AnimationNode.before() inserts several nodes before this node, check insertion order');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node2) {
+ var node1 = newAnimation(createDiv(test));
+ var parent = new parentCtor([node1]);
+ var player = document.timeline.play(node2);
+
+ assert_equals(player.source, node2, 'The node should be associated with its player');
+ node1.before(node2);
+ assert_equals(player.source, null, 'The node should be disassociated from its player');
+ });
+ });
+}, 'Test AnimationNode.before() disassociates the inserted node from the player, ' +
+ 'if node is directly associated with a player');
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/web-animations/animation-node/animation-node-next-sibling.html b/tests/wpt/web-platform-tests/web-animations/animation-node/animation-node-next-sibling.html
new file mode 100644
index 00000000000..69d0d7dc410
--- /dev/null
+++ b/tests/wpt/web-platform-tests/web-animations/animation-node/animation-node-next-sibling.html
@@ -0,0 +1,504 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>AnimationNode nextSibling attribute tests</title>
+<meta name="assert" content="The next sibling of this animation node">
+<link rel="help" href="http://w3c.github.io/web-animations/#dom-animationnode-nextsibling">
+<link rel="help" href="http://www.w3.org/TR/dom/#concept-tree-next-sibling">
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ var nodes = [newAnimation(createDiv(this)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node) {
+ assert_equals(node.nextSibling, null, type(node) + '.nextSibling should be null');
+ });
+}, 'AnimationNode.nextSibling is null if the node is standalone');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node) {
+ var parent = new parentCtor([node]);
+
+ assert_equals(node.nextSibling, null, type(node) + '.nextSibling ' +
+ 'should be null');
+ });
+ });
+}, 'AnimationNode.nextSibling is null if the node is the only child of its parent');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node1) {
+ var node2 = newAnimation(createDiv(test));
+ var parent = new parentCtor([node1, node2]);
+
+ assert_equals(node1.nextSibling, node2, type(node1) + '.nextSibling should return ' +
+ 'next sibling of this animation node');
+ assert_equals(node2.nextSibling, null, type(node2) + '.nextSibling should be null');
+ });
+ });
+}, 'AnimationNode.nextSibling returns next sibling of this animation node. Test first child');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node2) {
+ var node1 = newAnimation(createDiv(test));
+ var parent = new parentCtor([node1, node2]);
+
+ assert_equals(node1.nextSibling, node2, type(node1) + '.nextSibling should return ' +
+ 'next sibling of this animation node');
+ assert_equals(node2.nextSibling, null, type(node2) + '.nextSibling should be null');
+ });
+ });
+}, 'AnimationNode.nextSibling returns next sibling of this animation node. Test second child');
+
+test(function() {
+ var node1 = newAnimation(createDiv(this));
+ var node2 = newAnimation(createDiv(this));
+ var node3 = newAnimation(createDiv(this));
+ var node4 = newAnimation(createDiv(this));
+ var node5 = newAnimation(createDiv(this));
+ var node6 = newAnimation(createDiv(this));
+ var node7 = new AnimationGroup([node3, node4]);
+ var node8 = new AnimationGroup([node5, node6]);
+ var node9 = newAnimation(createDiv(this));
+ var group = new AnimationGroup([node1, node2, node7, node8, node9]);
+
+ assert_equals(group.nextSibling, null, 'AnimationNode.nextSibling should return ' +
+ 'null (root node)');
+ assert_equals(node1.nextSibling, node2, 'AnimationNode.nextSibling should return ' +
+ 'next sibling for the first node in the group');
+ assert_equals(node2.nextSibling, node7, 'AnimationNode.nextSibling should return ' +
+ 'next sibling of this animation node');
+ assert_equals(node3.nextSibling, node4, 'AnimationNode.nextSibling should return ' +
+ 'next sibling of this animation node (first node in the nested group)');
+ assert_equals(node4.nextSibling, null, 'AnimationNode.nextSibling should be null ' +
+ 'for the last node in the nested group');
+ assert_equals(node5.nextSibling, node6, 'AnimationNode.nextSibling should return ' +
+ 'next sibling of this animation node (first node in the second nested group)');
+ assert_equals(node6.nextSibling, null, 'AnimationNode.nextSibling should be null ' +
+ 'for the last node in the second nested group');
+ assert_equals(node7.nextSibling, node8, 'AnimationNode.nextSibling should return ' +
+ 'next sibling of this animation node (first nested group)');
+ assert_equals(node8.nextSibling, node9, 'AnimationNode.nextSibling should return ' +
+ 'next sibling of this animation node (second nested group)');
+ assert_equals(node9.nextSibling, null, 'AnimationNode.nextSibling should return ' +
+ 'null (the last node)');
+}, 'AnimationNode.nextSibling returns next sibling of this animation node. Test ' +
+ 'tree structure with AnimationGroup');
+
+test(function() {
+ var node1 = newAnimation(createDiv(this));
+ var node2 = newAnimation(createDiv(this));
+ var node3 = newAnimation(createDiv(this));
+ var node4 = newAnimation(createDiv(this));
+ var node5 = newAnimation(createDiv(this));
+ var node6 = newAnimation(createDiv(this));
+ var node7 = new AnimationSequence([node3, node4]);
+ var node8 = new AnimationSequence([node5, node6]);
+ var node9 = newAnimation(createDiv(this));
+ var sequence = new AnimationSequence([node1, node2, node7, node8, node9]);
+
+ assert_equals(sequence.nextSibling, null, 'AnimationNode.nextSibling should return ' +
+ 'null (root node)');
+ assert_equals(node1.nextSibling, node2, 'AnimationNode.nextSibling should return ' +
+ 'next sibling for the first node in the sequence');
+ assert_equals(node2.nextSibling, node7, 'AnimationNode.nextSibling should return ' +
+ 'next sibling of this animation node');
+ assert_equals(node3.nextSibling, node4, 'AnimationNode.nextSibling should return ' +
+ 'next sibling of this animation node (first node in the nested sequence)');
+ assert_equals(node4.nextSibling, null, 'AnimationNode.nextSibling should be null ' +
+ 'for the last node in the nested sequence');
+ assert_equals(node5.nextSibling, node6, 'AnimationNode.nextSibling should return ' +
+ 'next sibling of this animation node (first node in the second nested sequence)');
+ assert_equals(node6.nextSibling, null, 'AnimationNode.nextSibling should be null ' +
+ 'for the last node in the second nested sequence');
+ assert_equals(node7.nextSibling, node8, 'AnimationNode.nextSibling should return ' +
+ 'next sibling of this animation node (first nested sequence)');
+ assert_equals(node8.nextSibling, node9, 'AnimationNode.nextSibling should return ' +
+ 'next sibling of this animation node (second nested sequence)');
+ assert_equals(node9.nextSibling, null, 'AnimationNode.nextSibling should return ' +
+ 'null (the last node)');
+}, 'AnimationNode.nextSibling returns next sibling of this animation node. Test ' +
+ 'tree structure with AnimationSequence');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node2) {
+ var node1 = newAnimation(createDiv(test));
+ var node3 = newAnimation(createDiv(test));
+ var parent = new parentCtor([node1, node2]);
+ node2.before(node3);
+
+ assert_equals(node1.nextSibling, node3, type(node2) + '.before() should update ' +
+ 'next sibling of animation node');
+ assert_equals(node3.nextSibling, node2, type(node2) + '.before() should update ' +
+ 'next sibling of animation node');
+ assert_equals(node2.nextSibling, null, type(node2) + '.before() should update ' +
+ 'next sibling of animation node');
+ });
+ });
+}, 'AnimationNode.nextSibling returns next sibling of this animation node, ' +
+ 'the next sibling is changed by method before()');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node3) {
+ var node1 = newAnimation(createDiv(test));
+ var node2 = newAnimation(createDiv(test));
+ var parent1 = new parentCtor([node1, node2]);
+ var parent2 = new parentCtor([node3]);
+
+ node3.before(node2);
+
+ assert_equals(node1.nextSibling, null, type(node3) + '.before() should update ' +
+ 'next sibling of animation node');
+ assert_equals(node2.nextSibling, node3, type(node3) + '.before() should update ' +
+ 'next sibling of animation node');
+ });
+ });
+}, 'AnimationNode.nextSibling returns next sibling of this animation node, ' +
+ 'the next sibling is removed by method before()');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node2) {
+ var node1 = newAnimation(createDiv(test));
+ var node3 = newAnimation(createDiv(test));
+ var node4 = new AnimationGroup([]);
+ var node5 = new AnimationSequence([]);
+ var parent = new parentCtor([node1, node2]);
+ node2.before(node3, node4, node5);
+
+ assert_equals(node1.nextSibling, node3, type(node2) + '.before() should update ' +
+ 'next sibling of animation node');
+ assert_equals(node3.nextSibling, node4, type(node2) + '.before() should update ' +
+ 'next sibling of animation node');
+ assert_equals(node4.nextSibling, node5, type(node2) + '.before() should update ' +
+ 'next sibling of animation node');
+ assert_equals(node5.nextSibling, node2, type(node2) + '.before() should update ' +
+ 'next sibling of animation node');
+ assert_equals(node2.nextSibling, null, type(node2) + '.before() should update ' +
+ 'next sibling of animation node');
+ });
+ });
+}, 'AnimationNode.nextSibling returns next sibling of this animation node, ' +
+ 'several nodes are added by method before()');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node1) {
+ var node2 = newAnimation(createDiv(test));
+ var node3 = newAnimation(createDiv(test));
+ var parent = new parentCtor([node1, node2]);
+ node1.after(node3);
+
+ assert_equals(node1.nextSibling, node3, type(node1) + '.after() should update ' +
+ 'next sibling of animation node');
+ assert_equals(node3.nextSibling, node2, type(node1) + '.after() should update ' +
+ 'next sibling of animation node');
+ assert_equals(node2.nextSibling, null, type(node1) + '.after() should update ' +
+ 'next sibling of animation node');
+ });
+ });
+}, 'AnimationNode.nextSibling returns next sibling of this animation node, ' +
+ 'the next sibling is changed by method after()');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node3) {
+ var node1 = newAnimation(createDiv(test));
+ var node2 = newAnimation(createDiv(test));
+ var parent1 = new parentCtor([node1, node2]);
+ var parent2 = new parentCtor([node3]);
+
+ node3.after(node2);
+
+ assert_equals(node1.nextSibling, null, type(node3) + '.after() should update ' +
+ 'next sibling of animation node');
+ assert_equals(node3.nextSibling, node2, type(node3) + '.after() should update ' +
+ 'next sibling of animation node');
+ });
+ });
+}, 'AnimationNode.nextSibling returns next sibling of this animation node, ' +
+ 'the next sibling is removed by method after()');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node1) {
+ var node2 = newAnimation(createDiv(test));
+ var node3 = newAnimation(createDiv(test));
+ var node4 = new AnimationGroup([]);
+ var node5 = new AnimationSequence([]);
+ var parent = new parentCtor([node1, node2]);
+ node1.after(node3, node4, node5);
+
+ assert_equals(node1.nextSibling, node3, type(node1) + '.after() should update ' +
+ 'next sibling of animation node');
+ assert_equals(node3.nextSibling, node4, type(node1) + '.after() should update ' +
+ 'next sibling of animation node');
+ assert_equals(node4.nextSibling, node5, type(node1) + '.after() should update ' +
+ 'next sibling of animation node');
+ assert_equals(node5.nextSibling, node2, type(node1) + '.after() should update ' +
+ 'next sibling of animation node');
+ assert_equals(node2.nextSibling, null, type(node1) + '.after() should update ' +
+ 'next sibling of animation node');
+ });
+ });
+}, 'AnimationNode.nextSibling returns next sibling of this animation node, ' +
+ 'several nodes are added by method after()');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node2) {
+ var node1 = newAnimation(createDiv(test));
+ var node3 = newAnimation(createDiv(test));
+ var node4 = newAnimation(createDiv(test));
+ var parent = new parentCtor([node1, node2, node3]);
+ node2.replace(node4);
+
+ assert_equals(node1.nextSibling, node4, type(node2) + '.replace() should update ' +
+ 'next sibling of animation node');
+ assert_equals(node4.nextSibling, node3, type(node2) + '.replace() should update ' +
+ 'next sibling of animation node');
+ assert_equals(node2.nextSibling, null, type(node2) + '.replace() should update ' +
+ 'next sibling of animation node');
+ });
+ });
+}, 'AnimationNode.nextSibling returns next sibling of this animation node, ' +
+ 'the next sibling is changed by method replace()');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node4) {
+ var node1 = newAnimation(createDiv(test));
+ var node2 = newAnimation(createDiv(test));
+ var node3 = newAnimation(createDiv(test));
+ var parent1 = new parentCtor([node1, node2, node3]);
+ var parent2 = new parentCtor([node4]);
+
+ node4.replace(node2);
+
+ assert_equals(node1.nextSibling, node3, type(node4) + '.replace() should update ' +
+ 'next sibling of animation node');
+ assert_equals(node2.nextSibling, null, type(node4) + '.replace() should update ' +
+ 'next sibling of animation node');
+ });
+ });
+}, 'AnimationNode.nextSibling returns next sibling of this animation node, ' +
+ 'the next sibling is removed by method replace()');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node2) {
+ var node1 = newAnimation(createDiv(test));
+ var node3 = newAnimation(createDiv(test));
+ var node4 = newAnimation(createDiv(test));
+ var node5 = new AnimationGroup([]);
+ var node6 = new AnimationSequence([]);
+ var parent = new parentCtor([node1, node2, node3]);
+ node2.replace(node4, node5, node6);
+
+ assert_equals(node1.nextSibling, node4, type(node2) + '.replace() should update ' +
+ 'next sibling of animation node');
+ assert_equals(node4.nextSibling, node5, type(node2) + '.replace() should update ' +
+ 'next sibling of animation node');
+ assert_equals(node5.nextSibling, node6, type(node2) + '.replace() should update ' +
+ 'next sibling of animation node');
+ assert_equals(node6.nextSibling, node3, type(node2) + '.replace() should update ' +
+ 'next sibling of animation node');
+ assert_equals(node2.nextSibling, null, type(node2) + '.replace() should update ' +
+ 'next sibling of animation node');
+ });
+ });
+}, 'AnimationNode.nextSibling returns next sibling of this animation node, ' +
+ 'several nodes are added by method replace()');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node2) {
+ var node1 = newAnimation(createDiv(test));
+ var node3 = newAnimation(createDiv(test));
+ var parent = new parentCtor([node1, node2, node3]);
+ node2.remove();
+
+ assert_equals(node1.nextSibling, node3, type(node2) + '.replace() should update ' +
+ 'next sibling of animation node');
+ assert_equals(node2.nextSibling, null, type(node2) + '.replace() should update ' +
+ 'next sibling of animation node');
+ });
+ });
+}, 'AnimationNode.nextSibling returns next sibling of this animation node, ' +
+ 'the next sibling is changed by method remove()');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node2) {
+ var node1 = newAnimation(createDiv(test));
+ var parent = new parentCtor([node1]);
+ parent.prepend(node2);
+
+ assert_equals(node2.nextSibling, node1, parentCtor.name + '.prepend() should update ' +
+ 'next sibling of animation node');
+ });
+ });
+}, 'AnimationNode.nextSibling returns next sibling of this animation node, ' +
+ 'the next sibling is changed by method AnimationGroup.prepend()');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node1) {
+ var node2 = newAnimation(createDiv(test));
+ var node3 = newAnimation(createDiv(test));
+ var parent1 = new parentCtor([node1, node2]);
+ var parent2 = new parentCtor([node3]);
+
+ parent2.prepend(node2);
+
+ assert_equals(node1.nextSibling, null, parentCtor.name + '.prepend() should update ' +
+ 'next sibling of animation node');
+ assert_equals(node2.nextSibling, node3, parentCtor.name + '.prepend() should update ' +
+ 'next sibling of animation node');
+ });
+ });
+}, 'AnimationNode.nextSibling returns next sibling of this animation node, ' +
+ 'the next sibling is removed by method AnimationGroup.prepend()');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var node1 = newAnimation(createDiv(test));
+ var node2 = new AnimationGroup([]);
+ var node3 = new AnimationSequence([]);
+ var node4 = newAnimation(createDiv(test));
+ var parent = new parentCtor([node1]);
+ parent.prepend(node2, node3, node4);
+
+ assert_equals(node2.nextSibling, node3, parentCtor.name + '.prepend() should update ' +
+ 'next sibling of animation node');
+ assert_equals(node3.nextSibling, node4, parentCtor.name + '.prepend() should update ' +
+ 'next sibling of animation node');
+ assert_equals(node4.nextSibling, node1, parentCtor.name + '.prepend() should update ' +
+ 'next sibling of animation node');
+ });
+}, 'AnimationNode.nextSibling returns next sibling of this animation node, ' +
+ 'several nodes are added by method AnimationGroup.prepend()');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node1) {
+ var node2 = newAnimation(createDiv(test));
+ var parent = new parentCtor([node1]);
+ parent.append(node2);
+
+ assert_equals(node1.nextSibling, node2, parentCtor.name + '.append() should update ' +
+ 'next sibling of animation node');
+ assert_equals(node2.nextSibling, null, parentCtor.name + '.append() should update ' +
+ 'next sibling of animation node');
+ });
+ });
+}, 'AnimationNode.nextSibling returns next sibling of this animation node, ' +
+ 'the next sibling is changed by method AnimationGroup.append()');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node1) {
+ var node2 = newAnimation(createDiv(test));
+ var node3 = newAnimation(createDiv(test));
+ var parent1 = new parentCtor([node1, node2]);
+ var parent2 = new parentCtor([node3]);
+
+ parent2.append(node2);
+
+ assert_equals(node1.nextSibling, null, parentCtor.name + '.append() should update ' +
+ 'next sibling of animation node');
+ assert_equals(node3.nextSibling, node2, parentCtor.name + '.append() should update ' +
+ 'next sibling of animation node');
+ });
+ });
+}, 'AnimationNode.nextSibling returns next sibling of this animation node, ' +
+ 'the next sibling is removed by method AnimationGroup.append()');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node1) {
+ var node2 = newAnimation(createDiv(test));
+ var node3 = new AnimationGroup([]);
+ var node4 = new AnimationSequence([]);
+ var parent = new parentCtor([node1]);
+ parent.append(node2, node3, node4);
+
+ assert_equals(node1.nextSibling, node2, parentCtor.name + '.append() should update ' +
+ 'next sibling of animation node');
+ assert_equals(node2.nextSibling, node3, parentCtor.name + '.append() should update ' +
+ 'next sibling of animation node');
+ assert_equals(node3.nextSibling, node4, parentCtor.name + '.append() should update ' +
+ 'next sibling of animation node');
+ assert_equals(node4.nextSibling, null, parentCtor.name + '.append() should update ' +
+ 'next sibling of animation node');
+ });
+ });
+}, 'AnimationNode.nextSibling returns next sibling of this animation node, ' +
+ 'several nodes are added by method AnimationGroup.append()');
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/web-animations/animation-node/animation-node-parent.html b/tests/wpt/web-platform-tests/web-animations/animation-node/animation-node-parent.html
new file mode 100644
index 00000000000..8521a58b13a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/web-animations/animation-node/animation-node-parent.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>AnimationNode parent attribute tests</title>
+<meta name="assert" content="The parent animation group of this animation node or null if this animation node does not have a parent animation group">
+<link rel="help" href="http://w3c.github.io/web-animations/#dom-animationnode-parent">
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ var nodes = [newAnimation(createDiv(this)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node) {
+ assert_equals(node.parent, null, type(node) + '.parent should be null');
+ });
+}, 'AnimationNode.parent is null if animation node does not have a parent animation group');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node) {
+ var parent = new parentCtor([node]);
+
+ assert_equals(node.parent, parent, type(node) + '.parent should return ' +
+ 'parent animation group of this animation node');
+ });
+ });
+}, 'AnimationNode.parent returns parent animation group of this animation node');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ var parent = new parentCtor([nodes[0], nodes[1], nodes[2]]);
+ nodes.forEach(function(node) {
+ assert_equals(node.parent, parent, type(node) + '.parent should return ' +
+ 'parent animation group of this animation node');
+ });
+ });
+}, 'AnimationNode.parent returns parent animation group of this animation node. ' +
+ 'The group has several children nodes');
+
+// The rest is tested in mutator methods: AnimationNode.before(), AnimationNode.after(),
+// AnimationNode.replace(), AnimationNode.remove(),
+// AnimationGroup.prepend(), AnimationGroup.append(), AnimationGroup.clone()
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/web-animations/animation-node/animation-node-previous-sibling.html b/tests/wpt/web-platform-tests/web-animations/animation-node/animation-node-previous-sibling.html
new file mode 100644
index 00000000000..0e1f658ec42
--- /dev/null
+++ b/tests/wpt/web-platform-tests/web-animations/animation-node/animation-node-previous-sibling.html
@@ -0,0 +1,512 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>AnimationNode previousSibling attribute tests</title>
+<meta name="assert" content="The previous sibling of this animation node">
+<link rel="help" href="http://w3c.github.io/web-animations/#dom-animationnode-previoussibling">
+<link rel="help" href="http://www.w3.org/TR/dom/#concept-tree-previous-sibling">
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ var nodes = [
+ newAnimation(createDiv(this)),
+ new AnimationGroup([]),
+ new AnimationSequence([])
+ ];
+ nodes.forEach(function(node) {
+ assert_equals(node.previousSibling, null, type(node) + '.previousSibling should be null');
+ });
+}, 'AnimationNode.previousSibling is null if the node is standalone');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node) {
+ var parent = new parentCtor([node]);
+
+ assert_equals(node.previousSibling, null, type(node) + '.previousSibling ' +
+ 'should be null');
+ });
+ });
+}, 'AnimationNode.previousSibling is null if the node is the only child of its parent');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node1) {
+ var node2 = newAnimation(createDiv(test));
+ var parent = new parentCtor([node1, node2]);
+
+ assert_equals(node1.previousSibling, null, type(node1) + '.previousSibling should be null');
+ assert_equals(node2.previousSibling, node1, type(node2) + '.previousSibling should return ' +
+ 'previous sibling of this animation node');
+ });
+ });
+}, 'AnimationNode.previousSibling returns previous sibling of this animation node. Test first child');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node2) {
+ var node1 = newAnimation(createDiv(test));
+ var parent = new parentCtor([node1, node2]);
+
+ assert_equals(node1.previousSibling, null, type(node1) + '.previousSibling should be null');
+ assert_equals(node2.previousSibling, node1, type(node2) + '.previousSibling should return ' +
+ 'previous sibling of this animation node');
+ });
+ });
+}, 'AnimationNode.previousSibling returns previous sibling of this animation node. Test second child');
+
+test(function() {
+ var node1 = newAnimation(createDiv(this));
+ var node2 = newAnimation(createDiv(this));
+ var node3 = newAnimation(createDiv(this));
+ var node4 = newAnimation(createDiv(this));
+ var node5 = newAnimation(createDiv(this));
+ var node6 = newAnimation(createDiv(this));
+ var node7 = new AnimationGroup([node3, node4]);
+ var node8 = new AnimationGroup([node5, node6]);
+ var node9 = newAnimation(createDiv(this));
+ var group = new AnimationGroup([node1, node2, node7, node8, node9]);
+
+ assert_equals(group.previousSibling, null, 'AnimationNode.previousSibling should return ' +
+ 'null (root node)');
+ assert_equals(node1.previousSibling, null, 'AnimationNode.previousSibling should return ' +
+ 'null for the first node in the group');
+ assert_equals(node2.previousSibling, node1, 'AnimationNode.previousSibling should return ' +
+ 'previous sibling of this animation node');
+ assert_equals(node3.previousSibling, null, 'AnimationNode.previousSibling should be null ' +
+ 'for the first node in the nested group');
+ assert_equals(node4.previousSibling, node3, 'AnimationNode.previousSibling should return ' +
+ 'previous sibling of this animation node (first node in the nested group)');
+ assert_equals(node5.previousSibling, null, 'AnimationNode.previousSibling should be null ' +
+ 'for the first node in the second nested group');
+ assert_equals(node6.previousSibling, node5, 'AnimationNode.previousSibling should return ' +
+ 'previous sibling of this animation node (first node in the second nested group)');
+ assert_equals(node7.previousSibling, node2, 'AnimationNode.previousSibling should return ' +
+ 'previous sibling of this animation node (first nested group)');
+ assert_equals(node8.previousSibling, node7, 'AnimationNode.previousSibling should return ' +
+ 'previous sibling of this animation node (second nested group)');
+ assert_equals(node9.previousSibling, node8, 'AnimationNode.previousSibling should return ' +
+ 'previous sibling of this animation node');
+}, 'AnimationNode.previousSibling returns previous sibling of this animation node. Test ' +
+ 'tree structure with AnimationGroup');
+
+test(function() {
+ var node1 = newAnimation(createDiv(this));
+ var node2 = newAnimation(createDiv(this));
+ var node3 = newAnimation(createDiv(this));
+ var node4 = newAnimation(createDiv(this));
+ var node5 = newAnimation(createDiv(this));
+ var node6 = newAnimation(createDiv(this));
+ var node7 = new AnimationSequence([node3, node4]);
+ var node8 = new AnimationSequence([node5, node6]);
+ var node9 = newAnimation(createDiv(this));
+ var sequence = new AnimationSequence([node1, node2, node7, node8, node9]);
+
+ assert_equals(sequence.previousSibling, null, 'AnimationNode.previousSibling should return ' +
+ 'null (root node)');
+ assert_equals(node1.previousSibling, null, 'AnimationNode.previousSibling should return ' +
+ 'null for the first node in the group');
+ assert_equals(node2.previousSibling, node1, 'AnimationNode.previousSibling should return ' +
+ 'previous sibling of this animation node');
+ assert_equals(node3.previousSibling, null, 'AnimationNode.previousSibling should be null ' +
+ 'for the first node in the nested group');
+ assert_equals(node4.previousSibling, node3, 'AnimationNode.previousSibling should return ' +
+ 'previous sibling of this animation node (first node in the nested group)');
+ assert_equals(node5.previousSibling, null, 'AnimationNode.previousSibling should be null ' +
+ 'for the first node in the second nested group');
+ assert_equals(node6.previousSibling, node5, 'AnimationNode.previousSibling should return ' +
+ 'previous sibling of this animation node (first node in the second nested group)');
+ assert_equals(node7.previousSibling, node2, 'AnimationNode.previousSibling should return ' +
+ 'previous sibling of this animation node (first nested group)');
+ assert_equals(node8.previousSibling, node7, 'AnimationNode.previousSibling should return ' +
+ 'previous sibling of this animation node (second nested group)');
+ assert_equals(node9.previousSibling, node8, 'AnimationNode.previousSibling should return ' +
+ 'previous sibling of this animation node');
+}, 'AnimationNode.previousSibling returns previous sibling of this animation node. Test ' +
+ 'tree structure with AnimationSequence');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node2) {
+ var node1 = newAnimation(createDiv(test));
+ var node3 = newAnimation(createDiv(test));
+ var parent = new parentCtor([node1, node2]);
+ node2.before(node3);
+
+ assert_equals(node1.previousSibling, null, type(node2) + '.before() should update ' +
+ 'previous sibling of animation node');
+ assert_equals(node3.previousSibling, node1, type(node2) + '.before() should update ' +
+ 'previous sibling of animation node');
+ assert_equals(node2.previousSibling, node3, type(node2) + '.before() should update ' +
+ 'previous sibling of animation node');
+ });
+ });
+}, 'AnimationNode.previousSibling returns previous sibling of this animation node, ' +
+ 'the previous sibling is changed by method before()');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node3) {
+ var node1 = newAnimation(createDiv(test));
+ var node2 = newAnimation(createDiv(test));
+ var parent1 = new parentCtor([node1, node2]);
+ var parent2 = new parentCtor([node3]);
+
+ node3.before(node1);
+
+ assert_equals(node1.previousSibling, null, type(node3) + '.before() should update ' +
+ 'previous sibling of animation node');
+ assert_equals(node2.previousSibling, null, type(node3) + '.before() should update ' +
+ 'previous sibling of animation node');
+ assert_equals(node3.previousSibling, node1, type(node3) + '.before() should update ' +
+ 'previous sibling of animation node');
+ });
+ });
+}, 'AnimationNode.previousSibling returns previous sibling of this animation node, ' +
+ 'the previous sibling is removed by method before()');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node2) {
+ var node1 = newAnimation(createDiv(test));
+ var node3 = newAnimation(createDiv(test));
+ var node4 = new AnimationGroup([]);
+ var node5 = new AnimationSequence([]);
+ var parent = new parentCtor([node1, node2]);
+ node2.before(node3, node4, node5);
+
+ assert_equals(node1.previousSibling, null, type(node2) + '.before() should update ' +
+ 'previous sibling of animation node');
+ assert_equals(node3.previousSibling, node1, type(node2) + '.before() should update ' +
+ 'previous sibling of animation node');
+ assert_equals(node4.previousSibling, node3, type(node2) + '.before() should update ' +
+ 'previous sibling of animation node');
+ assert_equals(node5.previousSibling, node4, type(node2) + '.before() should update ' +
+ 'previous sibling of animation node');
+ assert_equals(node2.previousSibling, node5, type(node2) + '.before() should update ' +
+ 'previous sibling of animation node');
+ });
+ });
+}, 'AnimationNode.previousSibling returns previous sibling of this animation node, ' +
+ 'several nodes are added by method before()');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node1) {
+ var node2 = newAnimation(createDiv(test));
+ var node3 = newAnimation(createDiv(test));
+ var parent = new parentCtor([node1, node2]);
+ node1.after(node3);
+
+ assert_equals(node1.previousSibling, null, type(node1) + '.after() should update ' +
+ 'previous sibling of animation node');
+ assert_equals(node3.previousSibling, node1, type(node1) + '.after() should update ' +
+ 'previous sibling of animation node');
+ assert_equals(node2.previousSibling, node3, type(node1) + '.after() should update ' +
+ 'previous sibling of animation node');
+ });
+ });
+}, 'AnimationNode.previousSibling returns previous sibling of this animation node, ' +
+ 'the previous sibling is changed by method after()');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node3) {
+ var node1 = newAnimation(createDiv(test));
+ var node2 = newAnimation(createDiv(test));
+ var parent1 = new parentCtor([node1, node2]);
+ var parent2 = new parentCtor([node3]);
+
+ node3.after(node1);
+
+ assert_equals(node1.previousSibling, node3, type(node3) + '.after() should update ' +
+ 'previous sibling of animation node');
+ assert_equals(node2.previousSibling, null, type(node3) + '.after() should update ' +
+ 'previous sibling of animation node');
+ assert_equals(node3.previousSibling, null, type(node3) + '.after() should update ' +
+ 'previous sibling of animation node');
+ });
+ });
+}, 'AnimationNode.previousSibling returns previous sibling of this animation node, ' +
+ 'the previous sibling is removed by method after()');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node1) {
+ var node2 = newAnimation(createDiv(test));
+ var node3 = newAnimation(createDiv(test));
+ var node4 = new AnimationGroup([]);
+ var node5 = new AnimationSequence([]);
+ var parent = new parentCtor([node1, node2]);
+ node1.after(node3, node4, node5);
+
+ assert_equals(node1.previousSibling, null, type(node1) + '.after() should update ' +
+ 'previous sibling of animation node');
+ assert_equals(node3.previousSibling, node1, type(node1) + '.after() should update ' +
+ 'previous sibling of animation node');
+ assert_equals(node4.previousSibling, node3, type(node1) + '.after() should update ' +
+ 'previous sibling of animation node');
+ assert_equals(node5.previousSibling, node4, type(node1) + '.after() should update ' +
+ 'previous sibling of animation node');
+ assert_equals(node2.previousSibling, node5, type(node1) + '.after() should update ' +
+ 'previous sibling of animation node');
+ });
+ });
+}, 'AnimationNode.previousSibling returns previous sibling of this animation node, ' +
+ 'several nodes are added by method after()');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node2) {
+ var node1 = newAnimation(createDiv(test));
+ var node3 = newAnimation(createDiv(test));
+ var node4 = newAnimation(createDiv(test));
+ var parent = new parentCtor([node1, node2, node3]);
+ node2.replace(node4);
+
+ assert_equals(node4.previousSibling, node1, type(node2) + '.replace() should update ' +
+ 'previous sibling of animation node');
+ assert_equals(node2.previousSibling, null, type(node2) + '.replace() should update ' +
+ 'previous sibling of animation node');
+ assert_equals(node3.previousSibling, node4, type(node2) + '.replace() should update ' +
+ 'previous sibling of animation node');
+ });
+ });
+}, 'AnimationNode.previousSibling returns previous sibling of this animation node, ' +
+ 'the previous sibling is changed by method replace()');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node4) {
+ var node1 = newAnimation(createDiv(test));
+ var node2 = newAnimation(createDiv(test));
+ var node3 = newAnimation(createDiv(test));
+ var parent1 = new parentCtor([node1, node2, node3]);
+ var parent2 = new parentCtor([node4]);
+
+ node4.replace(node2);
+
+ assert_equals(node3.previousSibling, node1, type(node4) + '.replace() should update ' +
+ 'previous sibling of animation node');
+ assert_equals(node2.previousSibling, null, type(node4) + '.replace() should update ' +
+ 'previous sibling of animation node');
+ });
+ });
+}, 'AnimationNode.previousSibling returns previous sibling of this animation node, ' +
+ 'the previous sibling is removed by method replace()');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node2) {
+ var node1 = newAnimation(createDiv(test));
+ var node3 = newAnimation(createDiv(test));
+ var node4 = newAnimation(createDiv(test));
+ var node5 = new AnimationGroup([]);
+ var node6 = new AnimationSequence([]);
+ var parent = new parentCtor([node1, node2, node3]);
+ node2.replace(node4, node5, node6);
+
+ assert_equals(node4.previousSibling, node1, type(node2) + '.replace() should update ' +
+ 'previous sibling of animation node');
+ assert_equals(node5.previousSibling, node4, type(node2) + '.replace() should update ' +
+ 'previous sibling of animation node');
+ assert_equals(node6.previousSibling, node5, type(node2) + '.replace() should update ' +
+ 'previous sibling of animation node');
+ assert_equals(node3.previousSibling, node6, type(node2) + '.replace() should update ' +
+ 'previous sibling of animation node');
+ assert_equals(node2.previousSibling, null, type(node2) + '.replace() should update ' +
+ 'previous sibling of animation node');
+ });
+ });
+}, 'AnimationNode.previousSibling returns previous sibling of this animation node, ' +
+ 'several nodes are added by method replace()');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node2) {
+ var node1 = newAnimation(createDiv(test));
+ var node3 = newAnimation(createDiv(test));
+ var parent = new parentCtor([node1, node2, node3]);
+ node2.remove();
+
+ assert_equals(node3.previousSibling, node1, type(node2) + '.replace() should update ' +
+ 'previous sibling of animation node');
+ assert_equals(node2.previousSibling, null, type(node2) + '.replace() should update ' +
+ 'previous sibling of animation node');
+ });
+ });
+}, 'AnimationNode.previousSibling returns previous sibling of this animation node, ' +
+ 'the previous sibling is changed by method remove()');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node1) {
+ var node2 = newAnimation(createDiv(test));
+ var parent = new parentCtor([node1]);
+ parent.prepend(node2);
+
+ assert_equals(node1.previousSibling, node2, parentCtor.name + '.prepend() should update ' +
+ 'previous sibling of animation node');
+ });
+ });
+}, 'AnimationNode.previousSibling returns previous sibling of this animation node, ' +
+ 'the previous sibling is changed by method AnimationGroup.prepend()');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node2) {
+ var node1 = newAnimation(createDiv(test));
+ var node3 = newAnimation(createDiv(test));
+ var parent1 = new parentCtor([node1, node2]);
+ var parent2 = new parentCtor([node3]);
+
+ parent2.prepend(node1);
+
+ assert_equals(node2.previousSibling, null, parentCtor.name + '.prepend() should update ' +
+ 'previous sibling of animation node');
+ assert_equals(node3.previousSibling, node1, parentCtor.name + '.prepend() should update ' +
+ 'previous sibling of animation node');
+ });
+ });
+}, 'AnimationNode.previousSibling returns previous sibling of this animation node, ' +
+ 'the previous sibling is removed by method AnimationGroup.prepend()');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var node1 = newAnimation(createDiv(test));
+ var node2 = new AnimationGroup([]);
+ var node3 = new AnimationSequence([]);
+ var node4 = newAnimation(createDiv(test));
+ var parent = new parentCtor([node1]);
+ parent.prepend(node2, node3, node4);
+
+ assert_equals(node2.previousSibling, null, parentCtor.name + '.prepend() should update ' +
+ 'previous sibling of animation node');
+ assert_equals(node3.previousSibling, node2, parentCtor.name + '.prepend() should update ' +
+ 'previous sibling of animation node');
+ assert_equals(node4.previousSibling, node3, parentCtor.name + '.prepend() should update ' +
+ 'previous sibling of animation node');
+ assert_equals(node1.previousSibling, node4, parentCtor.name + '.prepend() should update ' +
+ 'previous sibling of animation node');
+ });
+}, 'AnimationNode.previousSibling returns previous sibling of this animation node, ' +
+ 'several nodes are added by method AnimationGroup.prepend()');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node2) {
+ var node1 = newAnimation(createDiv(test));
+ var parent = new parentCtor([node1]);
+ parent.append(node2);
+
+ assert_equals(node1.previousSibling, null, parentCtor.name + '.append() should update ' +
+ 'previous sibling of animation node');
+ assert_equals(node2.previousSibling, node1, parentCtor.name + '.append() should update ' +
+ 'previous sibling of animation node');
+ });
+ });
+}, 'AnimationNode.previousSibling returns previous sibling of this animation node, ' +
+ 'the previous sibling is changed by method AnimationGroup.append()');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node2) {
+ var node1 = newAnimation(createDiv(test));
+ var node3 = newAnimation(createDiv(test));
+ var parent1 = new parentCtor([node1, node2]);
+ var parent2 = new parentCtor([node3]);
+
+ parent2.append(node1);
+
+ assert_equals(node2.previousSibling, null, parentCtor.name + '.append() should update ' +
+ 'previous sibling of animation node');
+ assert_equals(node1.previousSibling, node3, parentCtor.name + '.append() should update ' +
+ 'previous sibling of animation node');
+ });
+ });
+}, 'AnimationNode.previousSibling returns previous sibling of this animation node, ' +
+ 'the previous sibling is removed by method AnimationGroup.append()');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node1) {
+ var node2 = newAnimation(createDiv(test));
+ var node3 = new AnimationGroup([]);
+ var node4 = new AnimationSequence([]);
+ var parent = new parentCtor([node1]);
+ parent.append(node2, node3, node4);
+
+ assert_equals(node2.previousSibling, node1, parentCtor.name + '.append() should update ' +
+ 'previous sibling of animation node');
+ assert_equals(node3.previousSibling, node2, parentCtor.name + '.append() should update ' +
+ 'previous sibling of animation node');
+ assert_equals(node4.previousSibling, node3, parentCtor.name + '.append() should update ' +
+ 'previous sibling of animation node');
+ });
+ });
+}, 'AnimationNode.previousSibling returns previous sibling of this animation node, ' +
+ 'several nodes are added by method AnimationGroup.append()');
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/web-animations/animation-node/animation-node-remove.html b/tests/wpt/web-platform-tests/web-animations/animation-node/animation-node-remove.html
new file mode 100644
index 00000000000..b1e3aab1896
--- /dev/null
+++ b/tests/wpt/web-platform-tests/web-animations/animation-node/animation-node-remove.html
@@ -0,0 +1,240 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>AnimationNode remove() method tests</title>
+<meta name="assert" content="Removes this animation node from its parent animation group or player">
+<link rel="help" href="http://w3c.github.io/web-animations/#dom-animationnode-remove">
+<link rel="help" href="http://w3c.github.io/web-animations/#remove-an-animation-node">
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+<body>
+<div id="log"></div>
+<script>
+test(function() {
+ var nodes = [newAnimation(createDiv(this)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node) {
+ node.remove();
+
+ assert_equals(node.parent, null, type(node) + ' node parent attribute should be null');
+ });
+}, 'AnimationNode.remove() does nothing for standalone node');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node) {
+ var parent = new parentCtor([node]);
+ node.remove();
+
+ assert_array_equals(parent.children, [], type(node) +
+ ' node should be removed from the parent ' + parentCtor.name);
+ assert_equals(node.parent, null, type(node) +
+ ' node parent attribute should be updated');
+ });
+ });
+}, 'AnimationNode.remove() removes node from the parent animation group. ' +
+ 'Removed node is the only node in the tree');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node1) {
+ var node2 = newAnimation(createDiv(test));
+ var parent = new parentCtor([node1, node2]);
+
+ node1.remove();
+
+ assert_array_equals(parent.children, [node2], type(node1) +
+ ' node should be removed from the parent ' + parentCtor.name);
+ assert_equals(parent.firstChild, node2, 'Parent ' + parentCtor.name +
+ ' firstChild attribute should be updated');
+ assert_equals(node1.parent, null, 'Removed ' + type(node1) +
+ ' node parent attribute should be updated');
+ assert_equals(node1.nextSibling, null, 'Removed ' + type(node1) +
+ ' node nextSibling attribute should be updated');
+ assert_equals(node2.previousSibling, null,
+ 'Remaining node previousSibling attribute should be updated');
+ });
+ });
+}, 'AnimationNode.remove() removes node from the parent animation group. ' +
+ 'Remove the first node in the group');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node2) {
+ var node1 = newAnimation(createDiv(test));
+ var parent = new parentCtor([node1, node2]);
+
+ node2.remove();
+
+ assert_array_equals(parent.children, [node1], type(node2) +
+ ' node should be removed from the parent ' + parentCtor.name);
+ assert_equals(parent.lastChild, node1, 'Parent ' + parentCtor.name +
+ ' lastChild attribute should be updated');
+ assert_equals(node2.parent, null, 'Removed ' + type(node2) +
+ ' node parent attribute should be updated');
+ assert_equals(node1.nextSibling, null,
+ 'Remaining node nextSibling attribute should be updated');
+ assert_equals(node2.previousSibling, null, 'Removed ' + type(node2) +
+ ' node previousSibling attribute should be updated');
+ });
+ });
+}, 'AnimationNode.remove() removes node from the parent animation group. ' +
+ 'Remove the last node in the group');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node2) {
+ var node1 = newAnimation(createDiv(test));
+ var node3 = newAnimation(createDiv(test));
+ var parent = new parentCtor([node1, node2, node3]);
+
+ node2.remove();
+
+ assert_array_equals(parent.children, [node1, node3], type(node2) +
+ ' node should be removed from the parent ' + parentCtor.name);
+ assert_equals(node2.parent, null, 'Removed ' + type(node2) +
+ ' node parent attribute should be updated');
+ assert_equals(node2.nextSibling, null, 'Removed ' + type(node2) +
+ ' node nextSibling attribute should be updated');
+ assert_equals(node2.previousSibling, null, 'Removed ' + type(node2) +
+ ' node previousSibling attribute should be updated');
+ assert_equals(node1.nextSibling, node3,
+ 'Remaining node nextSibling attribute should be updated');
+ assert_equals(node3.previousSibling, node1,
+ 'Remaining node previousSibling attribute should be updated');
+ });
+ });
+}, 'AnimationNode.remove() removes node from the parent animation group. ' +
+ 'Remove node from the middle of the group');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ parents.forEach(function(nodeCtor) {
+ var node1 = newAnimation(createDiv(test));
+ var node2 = newAnimation(createDiv(test));
+ var node3 = newAnimation(createDiv(test));
+ var node4 = new nodeCtor([node1, node2]);
+ var node5 = newAnimation(createDiv(test));
+ var parent = new parentCtor([node3, node4, node5]);
+
+ node4.remove();
+
+ assert_array_equals(node4.children, [node1, node2], 'Removed ' +
+ type(node4) + ' node children should not be changed');
+ assert_array_equals(parent.children, [node3, node5], type(node4) +
+ ' node should be removed from the parent ' + parentCtor.name);
+ assert_equals(node4.parent, null, 'Removed ' + type(node2) +
+ ' node parent attribute should be updated');
+ assert_equals(node4.nextSibling, null, 'Removed ' + type(node2) +
+ ' node nextSibling attribute should be updated');
+ assert_equals(node4.previousSibling, null, 'Removed ' + type(node2) +
+ ' node previousSibling attribute should be updated');
+ assert_equals(node3.nextSibling, node5,
+ 'Remaining node nextSibling attribute should be updated');
+ assert_equals(node5.previousSibling, node3,
+ 'Remaining node previousSibling attribute should be updated');
+ });
+ });
+}, 'Test removing a node that has children');
+
+test(function() {
+ var nodes = [newAnimation(createDiv(this)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node) {
+ var player = document.timeline.play(node);
+ node.remove();
+
+ assert_equals(player.source, null, type(node) +
+ ' node should be disassociated from the player');
+ });
+}, 'AnimationNode.remove() disassociates the node from player, ' +
+ 'if node is directly associated with a player');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node2) {
+ var node1 = newAnimation(createDiv(test));
+ var node3 = newAnimation(createDiv(test));
+ var parent = new parentCtor([node1, node2, node3]);
+ var player = document.timeline.play(parent);
+
+ node2.remove();
+
+ assert_equals(player.source, parent, type(node2) +
+ ' parent node should remain associated with the player');
+ });
+ });
+}, 'AnimationNode.remove() keeps parent direct association with the player');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ parents.forEach(function(nodeCtor) {
+ var node1 = newAnimation(createDiv(test));
+ var node2 = newAnimation(createDiv(test));
+ var node3 = newAnimation(createDiv(test));
+ var node4 = newAnimation(createDiv(test));
+ var node5 = new parentCtor([node4]);
+ var group1 = new AnimationGroup([node3, node5]);
+ var node6 = newAnimation(createDiv(test));
+ var node7 = new parentCtor([node6]);
+ var node8 = newAnimation(createDiv(test));
+ var sequence1 = new AnimationSequence([node7,node8]);
+ var node9 = new nodeCtor([node1, group1, node2, sequence1]);
+ var node10 = newAnimation(createDiv(test));
+ var parent = new parentCtor([node9, node10]);
+
+ node9.remove();
+
+ assert_equals(node9.parent, null, 'Removed ' + type(node9) +
+ ' node parent attribute should be updated');
+ assert_array_equals(node9.children, [node1, group1, node2, sequence1],
+ 'Removed ' + type(node9) + ' node children should not be changed');
+ for (var i = 0; i < node9.children.length; i++) {
+ assert_equals(node9.children[i].parent, node9, 'Removed ' + type(node9) +
+ ' node children parent attribute should not be changed for child ' + i);
+ }
+ assert_array_equals(group1.children, [node3, node5],
+ 'Removed ' + type(node9) + ' node grand children should not be changed');
+ for (var i = 0; i < group1.children.length; i++) {
+ assert_equals(group1.children[i].parent, group1, 'Removed ' + type(node9) +
+ ' node grand children parent attribute should not be changed for child ' + i);
+ }
+ assert_array_equals(sequence1.children, [node7,node8],
+ 'Removed ' + type(node9) + ' node grand children should not be changed');
+ for (var i = 0; i < sequence1.children.length; i++) {
+ assert_equals(sequence1.children[i].parent, sequence1, 'Removed ' + type(node9) +
+ ' node grand children parent attribute should not be changed for child ' + i);
+ }
+ assert_array_equals(node5.children, [node4],
+ 'Removed ' + type(node9) + ' node grand children should not be changed');
+ assert_equals(node4.parent, node5, 'Removed ' + type(node9) +
+ ' node grand children parent attribute should not be changed');
+ assert_array_equals(node7.children, [node6],
+ 'Removed ' + type(node9) + ' node grand children should not be changed');
+ assert_equals(node6.parent, node7, 'Removed ' + type(node9) +
+ ' node grand children parent attribute should not be changed');
+ });
+ });
+}, 'AnimationNode.remove() on the root of a non-trivial tree does not change child structure');
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/web-animations/animation-node/animation-node-replace.html b/tests/wpt/web-platform-tests/web-animations/animation-node/animation-node-replace.html
new file mode 100644
index 00000000000..35aa9d84d69
--- /dev/null
+++ b/tests/wpt/web-platform-tests/web-animations/animation-node/animation-node-replace.html
@@ -0,0 +1,445 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>AnimationNode replace() method tests</title>
+<meta name="assert" content="Replaces this AnimationNode with the passed in nodes parameter">
+<link rel="help" href="http://w3c.github.io/web-animations/#dom-animationnode-replace">
+<link rel="help" href="http://w3c.github.io/web-animations/#remove-an-animation-node">
+<link rel="help" href="http://w3c.github.io/web-animations/#insert-children">
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../testcommon.js"></script>
+<link rel="stylesheet" href="/resources/testharness.css">
+<body>
+<div id="log"></div>
+<script>
+// Step 1. If there is no parent animation group, terminate these steps.
+test(function() {
+ var nodes = [newAnimation(createDiv(this)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node) {
+ try {
+ node.replace(null);
+ } catch(e) {
+ assert_unreached(type(node) + '.replace(null) throws unexpected exception: ' + e);
+ }
+ });
+}, 'AnimationNode.replace(null) does nothing if node has no parent animation group');
+
+test(function() {
+ var nodes = [newAnimation(createDiv(this)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node) {
+ try {
+ node.replace(node);
+ } catch(e) {
+ assert_unreached(type(node) + '.replace(node) throws unexpected exception: ' + e);
+ }
+ });
+}, 'AnimationNode.replace() does nothing if node has no parent animation group. ' +
+ 'HierarchyRequestError is not thrown if the node is replacing itself');
+
+test(function() {
+ var test = this;
+ var nodes = [newAnimation(createDiv(this)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node1) {
+ var node2 = newAnimation(createDiv(test));
+
+ try {
+ node1.replace(node2);
+ } catch(e) {
+ assert_unreached(type(node1) + '.replace() throws unexpected exception: ' + e);
+ }
+ });
+}, 'AnimationNode.replace() does nothing if node has no parent animation group');
+
+// Step 2. If any of the animation nodes in nodes is an inclusive ancestor
+// of the parent animation group throw a HierarchyRequestError exception and terminate these steps.
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node) {
+ var parent = new parentCtor([node]);
+
+ assert_throws('HierarchyRequestError', function() {
+ node.replace(node);
+ }, 'HierarchyRequestError should be thrown if ' + type(node) +
+ ' replaces itself');
+ assert_equals(node.parent, parent, type(node) + '.replace() should not change ' +
+ 'parent attribute before throwing HierarchyRequestError');
+ assert_array_equals(parent.children, [node], type(node) + '.replace() ' +
+ 'should not change parent children before throwing HierarchyRequestError');
+ });
+ });
+}, 'HierarchyRequestError is thrown if the node replaces itself');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node) {
+ var parent = new parentCtor([node]);
+
+ assert_throws('HierarchyRequestError', function() {
+ node.replace(parent);
+ }, 'HierarchyRequestError should be thrown if ' + type(node) +
+ ' is replaced by its parent ' + parentCtor.name);
+ assert_equals(node.parent, parent, type(node) + '.replace() should not change ' +
+ 'parent attribute before throwing HierarchyRequestError');
+ assert_array_equals(parent.children, [node], type(node) + '.replace() ' +
+ 'should not change parent children before throwing HierarchyRequestError');
+ });
+ });
+}, 'HierarchyRequestError is thrown if the node is replaced by its parent');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node) {
+ var parent1 = new parentCtor([node]);
+ var parent2 = new parentCtor([parent1]);
+ var parent3 = new parentCtor([parent2]);
+ var parent4 = new parentCtor([parent3]);
+
+ assert_throws('HierarchyRequestError', function() {
+ node.replace(parent3);
+ }, 'HierarchyRequestError should be thrown if ' + type(node) +
+ ' is replaced by its inclusive ancestor' + parentCtor.name);
+ assert_equals(node.parent, parent1, type(node) + '.replace() should not change ' +
+ 'parent attribute before throwing HierarchyRequestError');
+ assert_array_equals(parent1.children, [node], type(node) + '.replace() ' +
+ 'should not change parent children before throwing HierarchyRequestError');
+ assert_equals(parent3.parent, parent4, type(node) + '.replace() should not change ' +
+ 'parent attribute of replacement node before throwing HierarchyRequestError');
+ assert_array_equals(parent4.children, [parent3], type(node) + '.replace() ' +
+ 'should not change replacement node parent children before throwing HierarchyRequestError');
+ });
+ });
+}, 'HierarchyRequestError is thrown if the node is replaced by its inclusive ancestor');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node1) {
+ var parent1 = new parentCtor([node1]);
+ var parent2 = new parentCtor([parent1]);
+ var parent3 = new parentCtor([parent2]);
+ var parent4 = new parentCtor([parent3]);
+ var node2 = newAnimation(createDiv(test));
+ var parent5 = new parentCtor([node2]);
+
+ assert_throws('HierarchyRequestError', function() {
+ node1.replace(node2, parent3);
+ }, 'HierarchyRequestError should be thrown if ' + type(node1) +
+ ' is replaced by its inclusive ancestor' + parentCtor.name);
+ assert_equals(node1.parent, parent1, type(node1) + '.replace() should not change ' +
+ 'parent attribute before throwing HierarchyRequestError');
+ assert_array_equals(parent1.children, [node1], type(node1) + '.replace() ' +
+ 'should not change parent children before throwing HierarchyRequestError');
+ assert_equals(parent3.parent, parent4, type(node1) + '.replace() should not change ' +
+ 'parent attribute of replacement node before throwing HierarchyRequestError');
+ assert_array_equals(parent4.children, [parent3], type(node1) + '.replace() ' +
+ 'should not change replacement node parent children before throwing HierarchyRequestError');
+ assert_equals(node2.parent, parent5, type(node1) + '.replace() should not change ' +
+ 'parent attribute of replacement node before throwing HierarchyRequestError');
+ assert_array_equals(parent5.children, [node2], type(node1) + '.replace() ' +
+ 'should not change replacement node parent children before throwing HierarchyRequestError');
+ });
+ });
+}, 'HierarchyRequestError is thrown if node is replaced by its inclusive ancestor. ' +
+ 'Test several arguments in replace() call');
+
+// Step 3. Let reference child be the next sibling of this animation node not in nodes.
+// Step 4. Remove this animation node from its parent animation group.
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node) {
+ var parent = new parentCtor([node]);
+
+ node.replace();
+
+ assert_array_equals(parent.children, [], type(node) +
+ ' node should be removed from parent ' + parentCtor.name);
+ assert_equals(node.parent, null, type(node) +
+ ' node parent attribute should be updated');
+ });
+ });
+}, 'AnimationNode.replace() without arguments removes the node from the parent ' +
+ 'animation group');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node1) {
+ var node2 = newAnimation(createDiv(test));
+ var parent = new parentCtor([node1]);
+
+ node1.replace(node2);
+
+ assert_array_equals(parent.children, [node2], type(node1) +
+ ' node should be removed its parent group');
+ assert_equals(node1.parent, null, type(node1) +
+ ' node should be removed from its parent group');
+ assert_equals(node1.previousSibling, null, type(node1) +
+ ' node previousSibling attribute should be updated');
+ assert_equals(node1.nextSibling, null, type(node1) +
+ ' node nextSibling attribute should be updated');
+ });
+ });
+}, 'AnimationNode.replace() removes the node from its parent animation group');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node2) {
+ var node1 = newAnimation(createDiv(test));
+ var node3 = newAnimation(createDiv(test));
+ var parent = new parentCtor([node1, node2, node3]);
+
+ node2.replace(node3);
+
+ assert_array_equals(parent.children, [node1,node3], type(node2) +
+ ' node should be removed from parent ' + parentCtor.name);
+ assert_equals(node2.parent, null, type(node2) +
+ ' node parent attribute should be updated');
+ assert_equals(node2.nextSibling, null, type(node2) +
+ ' node nextSibling attribute should be updated');
+ assert_equals(node2.previousSibling, null, type(node2) +
+ ' node previousSibling attribute should be updated');
+ assert_equals(node1.nextSibling, node3,
+ 'Sibling node nextSibling attribute should be updated');
+ assert_equals(node3.previousSibling, node1,
+ 'Sibling node previousSibling attribute should be updated');
+ });
+ });
+}, 'AnimationNode.replace(next sibling) removes the node from its parent ' +
+ 'animation group');
+
+// Step 5. Insert nodes before reference child.
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node1) {
+ var node2 = newAnimation(createDiv(test));
+ var parent = new parentCtor([node1]);
+
+ node1.replace(node2);
+
+ assert_array_equals(parent.children, [node2], type(node1) +
+ ' node should be replaced');
+ assert_equals(node2.parent, parent,
+ 'Replacement node should be assigned to a parent group');
+ });
+ });
+}, 'AnimationNode.replace() replaces node in the parent animation group');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node4) {
+ var node1 = newAnimation(createDiv(test));
+ var node2 = newAnimation(createDiv(test));
+ var node3 = newAnimation(createDiv(test));
+ var parent1 = new parentCtor([node1, node2]);
+ var parent2 = new parentCtor([node3, parent1, node4]);
+
+ node4.replace(node1);
+
+ assert_array_equals(parent1.children, [node2],
+ 'Replacement node should be removed from its previous position in the tree');
+ assert_array_equals(parent2.children, [node3, parent1, node1],
+ 'Replacement node should be inserted into the new position');
+ assert_equals(node1.parent, parent2, 'Inserted node parent group should be assigned');
+ assert_equals(node1.previousSibling, parent1,
+ 'Inserted node previousSibling attribute should be updated');
+ assert_equals(node1.nextSibling, null,
+ 'Inserted node nextSibling attribute should be updated');
+
+ assert_equals(node4.parent, null, 'Node should be removed from its parent group');
+ assert_equals(node4.previousSibling, null,
+ 'Replaced node previousSibling attribute should be updated');
+ assert_equals(node4.nextSibling, null,
+ 'Replaced node nextSibling attribute should be updated');
+ });
+ });
+}, 'Test AnimationNode.replace() replaces given node. The previous position ' +
+ 'of the replacement node is deeper in the tree than the current node');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node2) {
+ var node1 = newAnimation(createDiv(test));
+ var node3 = newAnimation(createDiv(test));
+ var node4 = newAnimation(createDiv(test));
+ var parent1 = new parentCtor([node1, node2]);
+ var parent2 = new parentCtor([node3, parent1, node4]);
+
+ node2.replace(node4);
+
+ assert_array_equals(parent1.children, [node1, node4],
+ 'Replacement node should be inserted to the new position');
+ assert_array_equals(parent2.children, [node3, parent1],
+ 'Replacement node should be removed from its previous position in the tree');
+ assert_equals(node4.parent, parent1, 'Inserted node parent group should be changed');
+ assert_equals(node4.previousSibling, node1,
+ 'Inserted node previousSibling attribute should be updated');
+ assert_equals(node1.nextSibling, node4,
+ 'Inserted node sibling nextSibling attribute should be updated');
+
+ assert_equals(node2.parent, null, 'Replaced node parent group should be changed');
+ assert_equals(node2.previousSibling, null,
+ 'Replaced node previousSibling attribute should be updated');
+ assert_equals(node2.nextSibling, null, 'Replaced node nextSibling attribute ' +
+ 'should be updated');
+ });
+ });
+}, 'Test AnimationNode.replace() replaces given node. The previous position ' +
+ 'of the replacement node is shallower in the tree than current node, but is not an ancestor');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node2) {
+ var node1 = newAnimation(createDiv(test));
+ var node3 = newAnimation(createDiv(test));
+ var node4 = newAnimation(createDiv(test));
+ var parent = new parentCtor([node1, node2]);
+
+ node2.replace(node3, node4);
+
+ assert_array_equals(parent.children, [node1, node3, node4], type(node2) + '.replace() ' +
+ 'should replace the current node by ones passed in arguments');
+ assert_equals(node1.nextSibling, node3, 'nextSibling attribute should be updated');
+ assert_equals(node3.previousSibling, node1, 'Inserted node previousSibling attribute ' +
+ 'should be updated');
+ assert_equals(node3.nextSibling, node4, 'Inserted node nextSibling attribute ' +
+ 'should be updated');
+ assert_equals(node3.parent, parent, 'Parent group of the inserted node should be changed');
+ assert_equals(node4.previousSibling, node3, 'Inserted node previousSibling attribute ' +
+ 'should be updated');
+ assert_equals(node4.nextSibling, null, 'Inserted node nextSibling attribute ' +
+ 'should be updated');
+ assert_equals(node4.parent, parent, 'Parent group of the second inserted node ' +
+ 'should be changed');
+ assert_equals(node2.parent, null, 'Replaced node parent group should be changed');
+ assert_equals(node2.previousSibling, null,
+ 'Replaced node previousSibling attribute should be updated');
+ assert_equals(node2.nextSibling, null, 'Replaced node nextSibling attribute ' +
+ 'should be updated');
+ });
+ });
+}, 'Test AnimationNode.replace() replaces given node. Test several arguments');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node2) {
+ var node1 = newAnimation(createDiv(test));
+ var node3 = newAnimation(createDiv(test));
+ var node4 = newAnimation(createDiv(test));
+ var parent = new parentCtor([node1, node2]);
+
+ node2.replace(node3, node4, node3, node4);
+
+ assert_array_equals(parent.children, [node1, node3, node4], type(node2) + '.replace() ' +
+ 'should replace the current node by ones passed in arguments');
+ assert_equals(node1.nextSibling, node3, 'nextSibling attribute should be updated');
+ assert_equals(node3.previousSibling, node1, 'Inserted node previousSibling attribute ' +
+ 'should be updated');
+ assert_equals(node3.nextSibling, node4, 'Inserted node nextSibling attribute ' +
+ 'should be updated');
+ assert_equals(node3.parent, parent, 'Parent group of the inserted node should be changed');
+ assert_equals(node4.previousSibling, node3, 'Inserted node previousSibling attribute ' +
+ 'should be updated');
+ assert_equals(node4.nextSibling, null, 'Inserted node nextSibling attribute ' +
+ 'should be updated');
+ assert_equals(node4.parent, parent, 'Parent group of the second inserted node ' +
+ 'should be changed');
+ assert_equals(node2.parent, null, 'Replaced node parent group should be changed');
+ assert_equals(node2.previousSibling, null,
+ 'Replaced node previousSibling attribute should be updated');
+ assert_equals(node2.nextSibling, null, 'Replaced node nextSibling attribute ' +
+ 'should be updated');
+ });
+ });
+}, 'Test AnimationNode.replace() replaces given node by several nodes, duplicate nodes are ignored');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node2) {
+ var node1 = newAnimation(createDiv(test));
+ var node3 = newAnimation(createDiv(test));
+ var node4 = newAnimation(createDiv(test));
+ var parent = new parentCtor([node1, node2]);
+
+ node2.replace(node3, node4, node3);
+
+ assert_array_equals(parent.children, [node1, node4, node3], type(node2) + '.replace() ' +
+ 'should replace the current node by ones passed in arguments');
+ assert_equals(node1.nextSibling, node4, 'nextSibling attribute should be updated');
+ assert_equals(node4.previousSibling, node1, 'Inserted node previousSibling attribute ' +
+ 'should be updated');
+ assert_equals(node4.nextSibling, node3, 'Inserted node nextSibling attribute ' +
+ 'should be updated');
+ assert_equals(node4.parent, parent, 'Parent group of the inserted node should be changed');
+ assert_equals(node3.previousSibling, node4, 'Inserted node previousSibling attribute ' +
+ 'should be updated');
+ assert_equals(node3.nextSibling, null, 'Inserted node nextSibling attribute ' +
+ 'should be updated');
+ assert_equals(node3.parent, parent, 'Parent group of the second inserted node ' +
+ 'should be changed');
+ assert_equals(node2.parent, null, 'Replaced node parent group should be changed');
+ assert_equals(node2.previousSibling, null,
+ 'Replaced node previousSibling attribute should be updated');
+ assert_equals(node2.nextSibling, null, 'Replaced node nextSibling attribute ' +
+ 'should be updated');
+ });
+ });
+}, 'Test AnimationNode.replace() replaces given node by several nodes, check replacement order');
+
+test(function() {
+ var test = this;
+ var parents = [AnimationGroup, AnimationSequence];
+ parents.forEach(function(parentCtor) {
+ var nodes = [newAnimation(createDiv(test)), new AnimationGroup([]), new AnimationSequence([])];
+ nodes.forEach(function(node1) {
+ var node2 = newAnimation(createDiv(test));
+ var parent = new parentCtor([node1]);
+ var player = document.timeline.play(node2);
+
+ assert_equals(player.source, node2, 'The node should be associated with its player');
+ node1.replace(node2);
+ assert_equals(player.source, null, 'The node should be disassociated from its player');
+ });
+ });
+}, 'Test AnimationNode.replace() disassociates the inserted node from the player, ' +
+ 'if node is directly associated with a player');
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/web-animations/animation-node/idlharness.html b/tests/wpt/web-platform-tests/web-animations/animation-node/idlharness.html
new file mode 100644
index 00000000000..83201e1a3b4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/web-animations/animation-node/idlharness.html
@@ -0,0 +1,54 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>AnimationNode IDL tests</title>
+<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru">
+<link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/webidl2/lib/webidl2.js"></script>
+<script src="/resources/idlharness.js"></script>
+<body>
+<div id="log"></div>
+<div id="target"></div>
+<script type="text/plain" id="untested-IDL">
+interface AnimationPlayer {
+};
+
+interface AnimationTiming {
+};
+
+interface ComputedTimingProperties {
+};
+
+interface AnimationGroup {
+};
+</script>
+<script type="text/plain" id="AnimationNode-IDL">
+interface AnimationNode {
+ // Timing
+ readonly attribute AnimationTiming timing;
+ readonly attribute ComputedTimingProperties computedTiming;
+
+ // Timing hierarchy
+ readonly attribute AnimationGroup? parent;
+ readonly attribute AnimationNode? previousSibling;
+ readonly attribute AnimationNode? nextSibling;
+ void before (AnimationNode... nodes);
+ void after (AnimationNode... nodes);
+ void replace (AnimationNode... nodes);
+ void remove ();
+};
+</script>
+<script>
+'use strict';
+
+var target = document.getElementById('target');
+var node = new Animation(target, [], 5);
+
+var idlArray = new IdlArray();
+idlArray.add_untested_idls(document.getElementById('untested-IDL').textContent);
+idlArray.add_idls(document.getElementById('AnimationNode-IDL').textContent);
+idlArray.add_objects( { AnimationNode: ['node'] } );
+idlArray.test();
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/web-animations/animation-timeline/animation-timeline.html b/tests/wpt/web-platform-tests/web-animations/animation-timeline/animation-timeline.html
new file mode 100644
index 00000000000..edb0c84553e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/web-animations/animation-timeline/animation-timeline.html
@@ -0,0 +1,89 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Web Animations API: AnimationTimeline tests</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<iframe src="data:text/html;charset=utf-8," width="10" height="10" id="iframe"></iframe>
+<script>
+'use strict';
+
+test(function() {
+ assert_equals(document.timeline, document.timeline,
+ 'document.timeline returns the same object every time');
+ var iframe = document.getElementById('iframe');
+ assert_not_equals(document.timeline, iframe.contentDocument.timeline,
+ 'document.timeline returns a different object for each document');
+ assert_not_equals(iframe.contentDocument.timeline, null,
+ 'document.timeline on an iframe is not null');
+},
+'document.timeline identity tests',
+{
+ help: 'http://dev.w3.org/fxtf/web-animations/#the-document-timeline',
+ assert: [ 'Each document has a timeline called the document timeline' ],
+ author: 'Brian Birtles'
+});
+
+async_test(function(t) {
+ assert_true(document.timeline.currentTime > 0,
+ 'document.timeline.currentTime is positive');
+ // document.timeline.currentTime should be set even before document
+ // load fires. We expect this code to be run before document load and hence
+ // the above assertion is sufficient.
+ // If the following assertion fails, this test needs to be redesigned.
+ assert_true(document.readyState !== 'complete',
+ 'Test is running prior to document load');
+
+ // Test that the document timeline's current time is measured from
+ // navigationStart.
+ //
+ // We can't just compare document.timeline.currentTime to
+ // window.performance.now() because currentTime is only updated on a sample
+ // so we use requestAnimationFrame instead.
+ window.requestAnimationFrame(t.step_func(function(rafTime) {
+ assert_equals(document.timeline.currentTime, rafTime,
+ 'document.timeline.currentTime matches' +
+ ' requestAnimationFrame time');
+ t.done();
+ }));
+},
+'document.timeline.currentTime value tests',
+{
+ help: [
+ 'http://dev.w3.org/fxtf/web-animations/#the-global-clock',
+ 'http://dev.w3.org/fxtf/web-animations/#the-document-timeline'
+ ],
+ assert: [
+ 'The global clock is a source of monotonically increasing time values',
+ 'The time values of the document timeline are calculated as a fixed' +
+ ' offset from the global clock',
+ 'the zero time corresponds to the navigationStart moment',
+ 'the time value of each document timeline must be equal to the time ' +
+ 'passed to animation frame request callbacks for that browsing context'
+ ],
+ author: 'Brian Birtles'
+});
+
+async_test(function(t) {
+ var valueAtStart = document.timeline.currentTime;
+ var timeAtStart = window.performance.now();
+ while (window.performance.now() - timeAtStart < 100) {
+ // Wait 100ms
+ }
+ assert_equals(document.timeline.currentTime, valueAtStart,
+ 'document.timeline.currentTime does not change within a script block');
+ window.requestAnimationFrame(t.step_func(function() {
+ assert_true(document.timeline.currentTime > valueAtStart,
+ 'document.timeline.currentTime increases between script blocks');
+ t.done();
+ }));
+},
+'document.timeline.currentTime liveness tests',
+{
+ help: 'http://dev.w3.org/fxtf/web-animations/#script-execution-and-live-updates-to-the-model',
+ assert: [ 'The value returned by the currentTime attribute of a' +
+ ' document timeline will not change within a script block' ],
+ author: 'Brian Birtles'
+});
+
+</script>
diff --git a/tests/wpt/web-platform-tests/web-animations/animation-timeline/idlharness.html b/tests/wpt/web-platform-tests/web-animations/animation-timeline/idlharness.html
new file mode 100644
index 00000000000..440ebb4e0e7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/web-animations/animation-timeline/idlharness.html
@@ -0,0 +1,26 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Web Animations API: AnimationTimeline tests</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/WebIDLParser.js"></script>
+<script src="/resources/idlharness.js"></script>
+<div id="log"></div>
+<script type="text/plain" id="AnimationTimeline-IDL">
+interface AnimationTimeline {
+ readonly attribute double? currentTime;
+};
+</script>
+<script>
+'use strict';
+
+var idlArray;
+test(function() {
+ idlArray = new IdlArray();
+ idlArray.add_idls(
+ document.getElementById('AnimationTimeline-IDL').textContent);
+ idlArray.add_objects( { AnimationTimeline: ['document.timeline'] } );
+});
+idlArray.test();
+
+</script>
diff --git a/tests/wpt/web-platform-tests/web-animations/testcommon.js b/tests/wpt/web-platform-tests/web-animations/testcommon.js
new file mode 100644
index 00000000000..5a704bb4dc8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/web-animations/testcommon.js
@@ -0,0 +1,58 @@
+/*
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+ */
+
+"use strict";
+
+var ANIMATION_END_TIME = 1000;
+var ANIMATION_TOP_DEFAULT = 300;
+var ANIMATION_TOP_0 = 10;
+var ANIMATION_TOP_0_5 = 100;
+var ANIMATION_TOP_1 = 200;
+
+var KEYFRAMES = [ {
+ top : ANIMATION_TOP_0 + 'px',
+ offset : 0
+}, {
+ top : ANIMATION_TOP_0_5 + 'px',
+ offset : 1 / 2
+}, {
+ top : ANIMATION_TOP_1 + 'px',
+ offset : 1
+} ];
+
+// creates new animation for given target
+function newAnimation(animationTarget) {
+ animationTarget.style.top = ANIMATION_TOP_DEFAULT + 'px';
+ return new Animation(animationTarget, KEYFRAMES, ANIMATION_END_TIME);
+}
+
+// creates div element, appends it to the document body and
+// add removing of the created element to test cleanup
+function createDiv(test, doc) {
+ if (!doc) {
+ doc = document;
+ }
+ var div = doc.createElement('div');
+ doc.body.appendChild(div);
+ test.add_cleanup(function() {
+ removeElement(div);
+ });
+ return div;
+}
+
+// Removes element
+function removeElement(element) {
+ element.parentNode.removeChild(element);
+}
+
+// Returns the type name of given object
+function type(object) {
+ return Object.prototype.toString.call(object).slice(8, -1);
+}
diff --git a/tests/wpt/web-platform-tests/webaudio/.gitignore b/tests/wpt/web-platform-tests/webaudio/.gitignore
new file mode 100644
index 00000000000..068fd1ef066
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webaudio/.gitignore
@@ -0,0 +1 @@
+idl/* \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/webaudio/README.md b/tests/wpt/web-platform-tests/webaudio/README.md
new file mode 100644
index 00000000000..e1afecd8379
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webaudio/README.md
@@ -0,0 +1,5 @@
+Our test suite is currently tracking the [editor's draft](https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html) of the Web Audio API.
+
+The tests are arranged in subdirectories, corresponding to different
+sections of the spec. So, for example, tests for the `DelayNode` are
+in `the-audio-api/the-delaynode-interface`.
diff --git a/tests/wpt/web-platform-tests/webaudio/js/buffer-loader.js b/tests/wpt/web-platform-tests/webaudio/js/buffer-loader.js
new file mode 100644
index 00000000000..453dc4a5215
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webaudio/js/buffer-loader.js
@@ -0,0 +1,44 @@
+/* Taken from
+ https://raw.github.com/WebKit/webkit/master/LayoutTests/webaudio/resources/buffer-loader.js */
+
+function BufferLoader(context, urlList, callback) {
+ this.context = context;
+ this.urlList = urlList;
+ this.onload = callback;
+ this.bufferList = new Array();
+ this.loadCount = 0;
+}
+
+BufferLoader.prototype.loadBuffer = function(url, index) {
+ // Load buffer asynchronously
+ var request = new XMLHttpRequest();
+ request.open("GET", url, true);
+ request.responseType = "arraybuffer";
+
+ var loader = this;
+
+ request.onload = function() {
+ loader.context.decodeAudioData(request.response, decodeSuccessCallback, decodeErrorCallback);
+ };
+
+ request.onerror = function() {
+ alert('BufferLoader: XHR error');
+ };
+
+ var decodeSuccessCallback = function(buffer) {
+ loader.bufferList[index] = buffer;
+ if (++loader.loadCount == loader.urlList.length)
+ loader.onload(loader.bufferList);
+ };
+
+ var decodeErrorCallback = function() {
+ alert('decodeErrorCallback: decode error');
+ };
+
+ request.send();
+}
+
+BufferLoader.prototype.load = function() {
+ for (var i = 0; i < this.urlList.length; ++i)
+ this.loadBuffer(this.urlList[i], i);
+}
diff --git a/tests/wpt/web-platform-tests/webaudio/js/helpers.js b/tests/wpt/web-platform-tests/webaudio/js/helpers.js
new file mode 100644
index 00000000000..9e4ee6fa343
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webaudio/js/helpers.js
@@ -0,0 +1,33 @@
+function assert_array_approx_equals(actual, expected, epsilon, description)
+{
+ assert_true(actual.length === expected.length,
+ (description + ": lengths differ, expected " + expected.length + " got " + actual.length))
+
+ for (var i=0; i < actual.length; i++) {
+ assert_approx_equals(actual[i], expected[i], epsilon, (description + ": element " + i))
+ }
+}
+
+/*
+ Returns an array (typed or not), of the passed array with removed trailing and ending
+ zero-valued elements
+ */
+function trimEmptyElements(array) {
+ var start = 0;
+ var end = array.length;
+
+ while (start < array.length) {
+ if (array[start] !== 0) {
+ break;
+ }
+ start++;
+ }
+
+ while (end > 0) {
+ end--;
+ if (array[end] !== 0) {
+ break;
+ }
+ }
+ return array.subarray(start, end);
+}
diff --git a/tests/wpt/web-platform-tests/webaudio/js/lodash.js b/tests/wpt/web-platform-tests/webaudio/js/lodash.js
new file mode 100644
index 00000000000..3813d2af261
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webaudio/js/lodash.js
@@ -0,0 +1,4282 @@
+/*!
+ * Lo-Dash 0.10.0 <http://lodash.com>
+ * (c) 2012 John-David Dalton <http://allyoucanleet.com/>
+ * Based on Underscore.js 1.4.2 <http://underscorejs.org>
+ * (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.
+ * Available under MIT license <http://lodash.com/license>
+ */
+;(function(window, undefined) {
+
+ /** Detect free variable `exports` */
+ var freeExports = typeof exports == 'object' && exports;
+
+ /** Detect free variable `global` and use it as `window` */
+ var freeGlobal = typeof global == 'object' && global;
+ if (freeGlobal.global === freeGlobal) {
+ window = freeGlobal;
+ }
+
+ /** Used for array and object method references */
+ var arrayRef = [],
+ // avoid a Closure Compiler bug by creatively creating an object
+ objectRef = new function(){};
+
+ /** Used to generate unique IDs */
+ var idCounter = 0;
+
+ /** Used internally to indicate various things */
+ var indicatorObject = objectRef;
+
+ /** Used by `cachedContains` as the default size when optimizations are enabled for large arrays */
+ var largeArraySize = 30;
+
+ /** Used to restore the original `_` reference in `noConflict` */
+ var oldDash = window._;
+
+ /** Used to detect template delimiter values that require a with-statement */
+ var reComplexDelimiter = /[-?+=!~*%&^<>|{(\/]|\[\D|\b(?:delete|in|instanceof|new|typeof|void)\b/;
+
+ /** Used to match HTML entities */
+ var reEscapedHtml = /&(?:amp|lt|gt|quot|#x27);/g;
+
+ /** Used to match empty string literals in compiled template source */
+ var reEmptyStringLeading = /\b__p \+= '';/g,
+ reEmptyStringMiddle = /\b(__p \+=) '' \+/g,
+ reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g;
+
+ /** Used to match regexp flags from their coerced string values */
+ var reFlags = /\w*$/;
+
+ /** Used to insert the data object variable into compiled template source */
+ var reInsertVariable = /(?:__e|__t = )\(\s*(?![\d\s"']|this\.)/g;
+
+ /** Used to detect if a method is native */
+ var reNative = RegExp('^' +
+ (objectRef.valueOf + '')
+ .replace(/[.*+?^=!:${}()|[\]\/\\]/g, '\\$&')
+ .replace(/valueOf|for [^\]]+/g, '.+?') + '$'
+ );
+
+ /**
+ * Used to match ES6 template delimiters
+ * http://people.mozilla.org/~jorendorff/es6-draft.html#sec-7.8.6
+ */
+ var reEsTemplate = /\$\{((?:(?=\\?)\\?[\s\S])*?)}/g;
+
+ /** Used to match "interpolate" template delimiters */
+ var reInterpolate = /<%=([\s\S]+?)%>/g;
+
+ /** Used to ensure capturing order of template delimiters */
+ var reNoMatch = /($^)/;
+
+ /** Used to match HTML characters */
+ var reUnescapedHtml = /[&<>"']/g;
+
+ /** Used to match unescaped characters in compiled string literals */
+ var reUnescapedString = /['\n\r\t\u2028\u2029\\]/g;
+
+ /** Used to fix the JScript [[DontEnum]] bug */
+ var shadowed = [
+ 'constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable',
+ 'toLocaleString', 'toString', 'valueOf'
+ ];
+
+ /** Used to make template sourceURLs easier to identify */
+ var templateCounter = 0;
+
+ /** Native method shortcuts */
+ var ceil = Math.ceil,
+ concat = arrayRef.concat,
+ floor = Math.floor,
+ getPrototypeOf = reNative.test(getPrototypeOf = Object.getPrototypeOf) && getPrototypeOf,
+ hasOwnProperty = objectRef.hasOwnProperty,
+ push = arrayRef.push,
+ propertyIsEnumerable = objectRef.propertyIsEnumerable,
+ slice = arrayRef.slice,
+ toString = objectRef.toString;
+
+ /* Native method shortcuts for methods with the same name as other `lodash` methods */
+ var nativeBind = reNative.test(nativeBind = slice.bind) && nativeBind,
+ nativeIsArray = reNative.test(nativeIsArray = Array.isArray) && nativeIsArray,
+ nativeIsFinite = window.isFinite,
+ nativeIsNaN = window.isNaN,
+ nativeKeys = reNative.test(nativeKeys = Object.keys) && nativeKeys,
+ nativeMax = Math.max,
+ nativeMin = Math.min,
+ nativeRandom = Math.random;
+
+ /** `Object#toString` result shortcuts */
+ var argsClass = '[object Arguments]',
+ arrayClass = '[object Array]',
+ boolClass = '[object Boolean]',
+ dateClass = '[object Date]',
+ funcClass = '[object Function]',
+ numberClass = '[object Number]',
+ objectClass = '[object Object]',
+ regexpClass = '[object RegExp]',
+ stringClass = '[object String]';
+
+ /**
+ * Detect the JScript [[DontEnum]] bug:
+ *
+ * In IE < 9 an objects own properties, shadowing non-enumerable ones, are
+ * made non-enumerable as well.
+ */
+ var hasDontEnumBug;
+
+ /** Detect if own properties are iterated after inherited properties (IE < 9) */
+ var iteratesOwnLast;
+
+ /**
+ * Detect if `Array#shift` and `Array#splice` augment array-like objects
+ * incorrectly:
+ *
+ * Firefox < 10, IE compatibility mode, and IE < 9 have buggy Array `shift()`
+ * and `splice()` functions that fail to remove the last element, `value[0]`,
+ * of array-like objects even though the `length` property is set to `0`.
+ * The `shift()` method is buggy in IE 8 compatibility mode, while `splice()`
+ * is buggy regardless of mode in IE < 9 and buggy in compatibility mode in IE 9.
+ */
+ var hasObjectSpliceBug = (hasObjectSpliceBug = { '0': 1, 'length': 1 },
+ arrayRef.splice.call(hasObjectSpliceBug, 0, 1), hasObjectSpliceBug[0]);
+
+ /** Detect if an `arguments` object's indexes are non-enumerable (IE < 9) */
+ var noArgsEnum = true;
+
+ (function() {
+ var props = [];
+ function ctor() { this.x = 1; }
+ ctor.prototype = { 'valueOf': 1, 'y': 1 };
+ for (var prop in new ctor) { props.push(prop); }
+ for (prop in arguments) { noArgsEnum = !prop; }
+
+ hasDontEnumBug = !/valueOf/.test(props);
+ iteratesOwnLast = props[0] != 'x';
+ }(1));
+
+ /** Detect if an `arguments` object's [[Class]] is unresolvable (Firefox < 4, IE < 9) */
+ var noArgsClass = !isArguments(arguments);
+
+ /** Detect if `Array#slice` cannot be used to convert strings to arrays (Opera < 10.52) */
+ var noArraySliceOnStrings = slice.call('x')[0] != 'x';
+
+ /**
+ * Detect lack of support for accessing string characters by index:
+ *
+ * IE < 8 can't access characters by index and IE 8 can only access
+ * characters by index on string literals.
+ */
+ var noCharByIndex = ('x'[0] + Object('x')[0]) != 'xx';
+
+ /**
+ * Detect if a node's [[Class]] is unresolvable (IE < 9)
+ * and that the JS engine won't error when attempting to coerce an object to
+ * a string without a `toString` property value of `typeof` "function".
+ */
+ try {
+ var noNodeClass = ({ 'toString': 0 } + '', toString.call(window.document || 0) == objectClass);
+ } catch(e) { }
+
+ /* Detect if `Function#bind` exists and is inferred to be fast (all but V8) */
+ var isBindFast = nativeBind && /\n|Opera/.test(nativeBind + toString.call(window.opera));
+
+ /* Detect if `Object.keys` exists and is inferred to be fast (IE, Opera, V8) */
+ var isKeysFast = nativeKeys && /^.+$|true/.test(nativeKeys + !!window.attachEvent);
+
+ /**
+ * Detect if sourceURL syntax is usable without erroring:
+ *
+ * The JS engine in Adobe products, like InDesign, will throw a syntax error
+ * when it encounters a single line comment beginning with the `@` symbol.
+ *
+ * The JS engine in Narwhal will generate the function `function anonymous(){//}`
+ * and throw a syntax error.
+ *
+ * Avoid comments beginning `@` symbols in IE because they are part of its
+ * non-standard conditional compilation support.
+ * http://msdn.microsoft.com/en-us/library/121hztk3(v=vs.94).aspx
+ */
+ try {
+ var useSourceURL = (Function('//@')(), !window.attachEvent);
+ } catch(e) { }
+
+ /** Used to identify object classifications that `_.clone` supports */
+ var cloneableClasses = {};
+ cloneableClasses[argsClass] = cloneableClasses[funcClass] = false;
+ cloneableClasses[arrayClass] = cloneableClasses[boolClass] = cloneableClasses[dateClass] =
+ cloneableClasses[numberClass] = cloneableClasses[objectClass] = cloneableClasses[regexpClass] =
+ cloneableClasses[stringClass] = true;
+
+ /** Used to determine if values are of the language type Object */
+ var objectTypes = {
+ 'boolean': false,
+ 'function': true,
+ 'object': true,
+ 'number': false,
+ 'string': false,
+ 'undefined': false
+ };
+
+ /** Used to escape characters for inclusion in compiled string literals */
+ var stringEscapes = {
+ '\\': '\\',
+ "'": "'",
+ '\n': 'n',
+ '\r': 'r',
+ '\t': 't',
+ '\u2028': 'u2028',
+ '\u2029': 'u2029'
+ };
+
+ /*--------------------------------------------------------------------------*/
+
+ /**
+ * The `lodash` function.
+ *
+ * @name _
+ * @constructor
+ * @category Chaining
+ * @param {Mixed} value The value to wrap in a `lodash` instance.
+ * @returns {Object} Returns a `lodash` instance.
+ */
+ function lodash(value) {
+ // exit early if already wrapped
+ if (value && value.__wrapped__) {
+ return value;
+ }
+ // allow invoking `lodash` without the `new` operator
+ if (!(this instanceof lodash)) {
+ return new lodash(value);
+ }
+ this.__wrapped__ = value;
+ }
+
+ /**
+ * By default, the template delimiters used by Lo-Dash are similar to those in
+ * embedded Ruby (ERB). Change the following template settings to use alternative
+ * delimiters.
+ *
+ * @static
+ * @memberOf _
+ * @type Object
+ */
+ lodash.templateSettings = {
+
+ /**
+ * Used to detect `data` property values to be HTML-escaped.
+ *
+ * @static
+ * @memberOf _.templateSettings
+ * @type RegExp
+ */
+ 'escape': /<%-([\s\S]+?)%>/g,
+
+ /**
+ * Used to detect code to be evaluated.
+ *
+ * @static
+ * @memberOf _.templateSettings
+ * @type RegExp
+ */
+ 'evaluate': /<%([\s\S]+?)%>/g,
+
+ /**
+ * Used to detect `data` property values to inject.
+ *
+ * @static
+ * @memberOf _.templateSettings
+ * @type RegExp
+ */
+ 'interpolate': reInterpolate,
+
+ /**
+ * Used to reference the data object in the template text.
+ *
+ * @static
+ * @memberOf _.templateSettings
+ * @type String
+ */
+ 'variable': ''
+ };
+
+ /*--------------------------------------------------------------------------*/
+
+ /**
+ * The template used to create iterator functions.
+ *
+ * @private
+ * @param {Obect} data The data object used to populate the text.
+ * @returns {String} Returns the interpolated text.
+ */
+ var iteratorTemplate = template(
+ // conditional strict mode
+ '<% if (obj.useStrict) { %>\'use strict\';\n<% } %>' +
+
+ // the `iteratee` may be reassigned by the `top` snippet
+ 'var index, value, iteratee = <%= firstArg %>, ' +
+ // assign the `result` variable an initial value
+ 'result = <%= firstArg %>;\n' +
+ // exit early if the first argument is falsey
+ 'if (!<%= firstArg %>) return result;\n' +
+ // add code before the iteration branches
+ '<%= top %>;\n' +
+
+ // array-like iteration:
+ '<% if (arrayLoop) { %>' +
+ 'var length = iteratee.length; index = -1;\n' +
+ 'if (typeof length == \'number\') {' +
+
+ // add support for accessing string characters by index if needed
+ ' <% if (noCharByIndex) { %>\n' +
+ ' if (isString(iteratee)) {\n' +
+ ' iteratee = iteratee.split(\'\')\n' +
+ ' }' +
+ ' <% } %>\n' +
+
+ // iterate over the array-like value
+ ' while (++index < length) {\n' +
+ ' value = iteratee[index];\n' +
+ ' <%= arrayLoop %>\n' +
+ ' }\n' +
+ '}\n' +
+ 'else {' +
+
+ // object iteration:
+ // add support for iterating over `arguments` objects if needed
+ ' <% } else if (noArgsEnum) { %>\n' +
+ ' var length = iteratee.length; index = -1;\n' +
+ ' if (length && isArguments(iteratee)) {\n' +
+ ' while (++index < length) {\n' +
+ ' value = iteratee[index += \'\'];\n' +
+ ' <%= objectLoop %>\n' +
+ ' }\n' +
+ ' } else {' +
+ ' <% } %>' +
+
+ // Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1
+ // (if the prototype or a property on the prototype has been set)
+ // incorrectly sets a function's `prototype` property [[Enumerable]]
+ // value to `true`. Because of this Lo-Dash standardizes on skipping
+ // the the `prototype` property of functions regardless of its
+ // [[Enumerable]] value.
+ ' <% if (!hasDontEnumBug) { %>\n' +
+ ' var skipProto = typeof iteratee == \'function\' && \n' +
+ ' propertyIsEnumerable.call(iteratee, \'prototype\');\n' +
+ ' <% } %>' +
+
+ // iterate own properties using `Object.keys` if it's fast
+ ' <% if (isKeysFast && useHas) { %>\n' +
+ ' var ownIndex = -1,\n' +
+ ' ownProps = objectTypes[typeof iteratee] ? nativeKeys(iteratee) : [],\n' +
+ ' length = ownProps.length;\n\n' +
+ ' while (++ownIndex < length) {\n' +
+ ' index = ownProps[ownIndex];\n' +
+ ' <% if (!hasDontEnumBug) { %>if (!(skipProto && index == \'prototype\')) {\n <% } %>' +
+ ' value = iteratee[index];\n' +
+ ' <%= objectLoop %>\n' +
+ ' <% if (!hasDontEnumBug) { %>}\n<% } %>' +
+ ' }' +
+
+ // else using a for-in loop
+ ' <% } else { %>\n' +
+ ' for (index in iteratee) {<%' +
+ ' if (!hasDontEnumBug || useHas) { %>\n if (<%' +
+ ' if (!hasDontEnumBug) { %>!(skipProto && index == \'prototype\')<% }' +
+ ' if (!hasDontEnumBug && useHas) { %> && <% }' +
+ ' if (useHas) { %>hasOwnProperty.call(iteratee, index)<% }' +
+ ' %>) {' +
+ ' <% } %>\n' +
+ ' value = iteratee[index];\n' +
+ ' <%= objectLoop %>;' +
+ ' <% if (!hasDontEnumBug || useHas) { %>\n }<% } %>\n' +
+ ' }' +
+ ' <% } %>' +
+
+ // Because IE < 9 can't set the `[[Enumerable]]` attribute of an
+ // existing property and the `constructor` property of a prototype
+ // defaults to non-enumerable, Lo-Dash skips the `constructor`
+ // property when it infers it's iterating over a `prototype` object.
+ ' <% if (hasDontEnumBug) { %>\n\n' +
+ ' var ctor = iteratee.constructor;\n' +
+ ' <% for (var k = 0; k < 7; k++) { %>\n' +
+ ' index = \'<%= shadowed[k] %>\';\n' +
+ ' if (<%' +
+ ' if (shadowed[k] == \'constructor\') {' +
+ ' %>!(ctor && ctor.prototype === iteratee) && <%' +
+ ' } %>hasOwnProperty.call(iteratee, index)) {\n' +
+ ' value = iteratee[index];\n' +
+ ' <%= objectLoop %>\n' +
+ ' }' +
+ ' <% } %>' +
+ ' <% } %>' +
+ ' <% if (arrayLoop || noArgsEnum) { %>\n}<% } %>\n' +
+
+ // add code to the bottom of the iteration function
+ '<%= bottom %>;\n' +
+ // finally, return the `result`
+ 'return result'
+ );
+
+ /** Reusable iterator options for `assign` and `defaults` */
+ var assignIteratorOptions = {
+ 'args': 'object, source, guard',
+ 'top':
+ 'for (var argsIndex = 1, argsLength = typeof guard == \'number\' ? 2 : arguments.length; argsIndex < argsLength; argsIndex++) {\n' +
+ ' if ((iteratee = arguments[argsIndex])) {',
+ 'objectLoop': 'result[index] = value',
+ 'bottom': ' }\n}'
+ };
+
+ /**
+ * Reusable iterator options shared by `forEach`, `forIn`, and `forOwn`.
+ */
+ var forEachIteratorOptions = {
+ 'args': 'collection, callback, thisArg',
+ 'top': 'callback = createCallback(callback, thisArg)',
+ 'arrayLoop': 'if (callback(value, index, collection) === false) return result',
+ 'objectLoop': 'if (callback(value, index, collection) === false) return result'
+ };
+
+ /** Reusable iterator options for `forIn` and `forOwn` */
+ var forOwnIteratorOptions = {
+ 'arrayLoop': null
+ };
+
+ /*--------------------------------------------------------------------------*/
+
+ /**
+ * Creates a function optimized to search large arrays for a given `value`,
+ * starting at `fromIndex`, using strict equality for comparisons, i.e. `===`.
+ *
+ * @private
+ * @param {Array} array The array to search.
+ * @param {Mixed} value The value to search for.
+ * @param {Number} [fromIndex=0] The index to search from.
+ * @param {Number} [largeSize=30] The length at which an array is considered large.
+ * @returns {Boolean} Returns `true` if `value` is found, else `false`.
+ */
+ function cachedContains(array, fromIndex, largeSize) {
+ fromIndex || (fromIndex = 0);
+
+ var length = array.length,
+ isLarge = (length - fromIndex) >= (largeSize || largeArraySize);
+
+ if (isLarge) {
+ var cache = {},
+ index = fromIndex - 1;
+
+ while (++index < length) {
+ // manually coerce `value` to a string because `hasOwnProperty`, in some
+ // older versions of Firefox, coerces objects incorrectly
+ var key = array[index] + '';
+ (hasOwnProperty.call(cache, key) ? cache[key] : (cache[key] = [])).push(array[index]);
+ }
+ }
+ return function(value) {
+ if (isLarge) {
+ var key = value + '';
+ return hasOwnProperty.call(cache, key) && indexOf(cache[key], value) > -1;
+ }
+ return indexOf(array, value, fromIndex) > -1;
+ }
+ }
+
+ /**
+ * Used by `_.max` and `_.min` as the default `callback` when a given
+ * `collection` is a string value.
+ *
+ * @private
+ * @param {String} value The character to inspect.
+ * @returns {Number} Returns the code unit of given character.
+ */
+ function charAtCallback(value) {
+ return value.charCodeAt(0);
+ }
+
+ /**
+ * Used by `sortBy` to compare transformed `collection` values, stable sorting
+ * them in ascending order.
+ *
+ * @private
+ * @param {Object} a The object to compare to `b`.
+ * @param {Object} b The object to compare to `a`.
+ * @returns {Number} Returns the sort order indicator of `1` or `-1`.
+ */
+ function compareAscending(a, b) {
+ var ai = a.index,
+ bi = b.index;
+
+ a = a.criteria;
+ b = b.criteria;
+
+ // ensure a stable sort in V8 and other engines
+ // http://code.google.com/p/v8/issues/detail?id=90
+ if (a !== b) {
+ if (a > b || a === undefined) {
+ return 1;
+ }
+ if (a < b || b === undefined) {
+ return -1;
+ }
+ }
+ return ai < bi ? -1 : 1;
+ }
+
+ /**
+ * Creates a function that, when called, invokes `func` with the `this`
+ * binding of `thisArg` and prepends any `partailArgs` to the arguments passed
+ * to the bound function.
+ *
+ * @private
+ * @param {Function|String} func The function to bind or the method name.
+ * @param {Mixed} [thisArg] The `this` binding of `func`.
+ * @param {Array} partialArgs An array of arguments to be partially applied.
+ * @returns {Function} Returns the new bound function.
+ */
+ function createBound(func, thisArg, partialArgs) {
+ var isFunc = isFunction(func),
+ isPartial = !partialArgs,
+ key = thisArg;
+
+ // juggle arguments
+ if (isPartial) {
+ partialArgs = thisArg;
+ }
+ if (!isFunc) {
+ thisArg = func;
+ }
+
+ function bound() {
+ // `Function#bind` spec
+ // http://es5.github.com/#x15.3.4.5
+ var args = arguments,
+ thisBinding = isPartial ? this : thisArg;
+
+ if (!isFunc) {
+ func = thisArg[key];
+ }
+ if (partialArgs.length) {
+ args = args.length
+ ? partialArgs.concat(slice.call(args))
+ : partialArgs;
+ }
+ if (this instanceof bound) {
+ // get `func` instance if `bound` is invoked in a `new` expression
+ noop.prototype = func.prototype;
+ thisBinding = new noop;
+
+ // mimic the constructor's `return` behavior
+ // http://es5.github.com/#x13.2.2
+ var result = func.apply(thisBinding, args);
+ return isObject(result)
+ ? result
+ : thisBinding
+ }
+ return func.apply(thisBinding, args);
+ }
+ return bound;
+ }
+
+ /**
+ * Produces an iteration callback bound to an optional `thisArg`. If `func` is
+ * a property name, the callback will return the property value for a given element.
+ *
+ * @private
+ * @param {Function|String} [func=identity|property] The function called per
+ * iteration or property name to query.
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
+ * @returns {Function} Returns a callback function.
+ */
+ function createCallback(func, thisArg) {
+ if (!func) {
+ return identity;
+ }
+ if (typeof func != 'function') {
+ return function(object) {
+ return object[func];
+ };
+ }
+ if (thisArg !== undefined) {
+ return function(value, index, object) {
+ return func.call(thisArg, value, index, object);
+ };
+ }
+ return func;
+ }
+
+ /**
+ * Creates compiled iteration functions.
+ *
+ * @private
+ * @param {Object} [options1, options2, ...] The compile options object(s).
+ * useHas - A boolean to specify using `hasOwnProperty` checks in the object loop.
+ * args - A string of comma separated arguments the iteration function will accept.
+ * top - A string of code to execute before the iteration branches.
+ * arrayLoop - A string of code to execute in the array loop.
+ * objectLoop - A string of code to execute in the object loop.
+ * bottom - A string of code to execute after the iteration branches.
+ *
+ * @returns {Function} Returns the compiled function.
+ */
+ function createIterator() {
+ var data = {
+ 'arrayLoop': '',
+ 'bottom': '',
+ 'hasDontEnumBug': hasDontEnumBug,
+ 'isKeysFast': isKeysFast,
+ 'objectLoop': '',
+ 'noArgsEnum': noArgsEnum,
+ 'noCharByIndex': noCharByIndex,
+ 'shadowed': shadowed,
+ 'top': '',
+ 'useHas': true
+ };
+
+ // merge options into a template data object
+ for (var object, index = 0; object = arguments[index]; index++) {
+ for (var key in object) {
+ data[key] = object[key];
+ }
+ }
+ var args = data.args;
+ data.firstArg = /^[^,]+/.exec(args)[0];
+
+ // create the function factory
+ var factory = Function(
+ 'createCallback, hasOwnProperty, isArguments, isString, objectTypes, ' +
+ 'nativeKeys, propertyIsEnumerable',
+ 'return function(' + args + ') {\n' + iteratorTemplate(data) + '\n}'
+ );
+ // return the compiled function
+ return factory(
+ createCallback, hasOwnProperty, isArguments, isString, objectTypes,
+ nativeKeys, propertyIsEnumerable
+ );
+ }
+
+ /**
+ * Used by `template` to escape characters for inclusion in compiled
+ * string literals.
+ *
+ * @private
+ * @param {String} match The matched character to escape.
+ * @returns {String} Returns the escaped character.
+ */
+ function escapeStringChar(match) {
+ return '\\' + stringEscapes[match];
+ }
+
+ /**
+ * Used by `escape` to convert characters to HTML entities.
+ *
+ * @private
+ * @param {String} match The matched character to escape.
+ * @returns {String} Returns the escaped character.
+ */
+ function escapeHtmlChar(match) {
+ return htmlEscapes[match];
+ }
+
+ /**
+ * A no-operation function.
+ *
+ * @private
+ */
+ function noop() {
+ // no operation performed
+ }
+
+ /**
+ * Used by `unescape` to convert HTML entities to characters.
+ *
+ * @private
+ * @param {String} match The matched character to unescape.
+ * @returns {String} Returns the unescaped character.
+ */
+ function unescapeHtmlChar(match) {
+ return htmlUnescapes[match];
+ }
+
+ /*--------------------------------------------------------------------------*/
+
+ /**
+ * Assigns own enumerable properties of source object(s) to the `destination`
+ * object. Subsequent sources will overwrite propery assignments of previous
+ * sources.
+ *
+ * @static
+ * @memberOf _
+ * @alias extend
+ * @category Objects
+ * @param {Object} object The destination object.
+ * @param {Object} [source1, source2, ...] The source objects.
+ * @returns {Object} Returns the destination object.
+ * @example
+ *
+ * _.assign({ 'name': 'moe' }, { 'age': 40 });
+ * // => { 'name': 'moe', 'age': 40 }
+ */
+ var assign = createIterator(assignIteratorOptions);
+
+ /**
+ * Checks if `value` is an `arguments` object.
+ *
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {Mixed} value The value to check.
+ * @returns {Boolean} Returns `true` if the `value` is an `arguments` object, else `false`.
+ * @example
+ *
+ * (function() { return _.isArguments(arguments); })(1, 2, 3);
+ * // => true
+ *
+ * _.isArguments([1, 2, 3]);
+ * // => false
+ */
+ function isArguments(value) {
+ return toString.call(value) == argsClass;
+ }
+ // fallback for browsers that can't detect `arguments` objects by [[Class]]
+ if (noArgsClass) {
+ isArguments = function(value) {
+ return value ? hasOwnProperty.call(value, 'callee') : false;
+ };
+ }
+
+ /**
+ * Iterates over `object`'s own and inherited enumerable properties, executing
+ * the `callback` for each property. The `callback` is bound to `thisArg` and
+ * invoked with three arguments; (value, key, object). Callbacks may exit iteration
+ * early by explicitly returning `false`.
+ *
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {Object} object The object to iterate over.
+ * @param {Function} callback The function called per iteration.
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
+ * @returns {Object} Returns `object`.
+ * @example
+ *
+ * function Dog(name) {
+ * this.name = name;
+ * }
+ *
+ * Dog.prototype.bark = function() {
+ * alert('Woof, woof!');
+ * };
+ *
+ * _.forIn(new Dog('Dagny'), function(value, key) {
+ * alert(key);
+ * });
+ * // => alerts 'name' and 'bark' (order is not guaranteed)
+ */
+ var forIn = createIterator(forEachIteratorOptions, forOwnIteratorOptions, {
+ 'useHas': false
+ });
+
+ /**
+ * Iterates over an object's own enumerable properties, executing the `callback`
+ * for each property. The `callback` is bound to `thisArg` and invoked with three
+ * arguments; (value, key, object). Callbacks may exit iteration early by explicitly
+ * returning `false`.
+ *
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {Object} object The object to iterate over.
+ * @param {Function} callback The function called per iteration.
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
+ * @returns {Object} Returns `object`.
+ * @example
+ *
+ * _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) {
+ * alert(key);
+ * });
+ * // => alerts '0', '1', and 'length' (order is not guaranteed)
+ */
+ var forOwn = createIterator(forEachIteratorOptions, forOwnIteratorOptions);
+
+ /**
+ * A fallback implementation of `isPlainObject` that checks if a given `value`
+ * is an object created by the `Object` constructor, assuming objects created
+ * by the `Object` constructor have no inherited enumerable properties and that
+ * there are no `Object.prototype` extensions.
+ *
+ * @private
+ * @param {Mixed} value The value to check.
+ * @returns {Boolean} Returns `true` if `value` is a plain object, else `false`.
+ */
+ function shimIsPlainObject(value) {
+ // avoid non-objects and false positives for `arguments` objects
+ var result = false;
+ if (!(value && typeof value == 'object') || isArguments(value)) {
+ return result;
+ }
+ // IE < 9 presents DOM nodes as `Object` objects except they have `toString`
+ // methods that are `typeof` "string" and still can coerce nodes to strings.
+ // Also check that the constructor is `Object` (i.e. `Object instanceof Object`)
+ var ctor = value.constructor;
+ if ((!noNodeClass || !(typeof value.toString != 'function' && typeof (value + '') == 'string')) &&
+ (!isFunction(ctor) || ctor instanceof ctor)) {
+ // IE < 9 iterates inherited properties before own properties. If the first
+ // iterated property is an object's own property then there are no inherited
+ // enumerable properties.
+ if (iteratesOwnLast) {
+ forIn(value, function(value, key, object) {
+ result = !hasOwnProperty.call(object, key);
+ return false;
+ });
+ return result === false;
+ }
+ // In most environments an object's own properties are iterated before
+ // its inherited properties. If the last iterated property is an object's
+ // own property then there are no inherited enumerable properties.
+ forIn(value, function(value, key) {
+ result = key;
+ });
+ return result === false || hasOwnProperty.call(value, result);
+ }
+ return result;
+ }
+
+ /**
+ * A fallback implementation of `Object.keys` that produces an array of the
+ * given object's own enumerable property names.
+ *
+ * @private
+ * @param {Object} object The object to inspect.
+ * @returns {Array} Returns a new array of property names.
+ */
+ function shimKeys(object) {
+ var result = [];
+ forOwn(object, function(value, key) {
+ result.push(key);
+ });
+ return result;
+ }
+
+ /**
+ * Used to convert characters to HTML entities:
+ *
+ * Though the `>` character is escaped for symmetry, characters like `>` and `/`
+ * don't require escaping in HTML and have no special meaning unless they're part
+ * of a tag or an unquoted attribute value.
+ * http://mathiasbynens.be/notes/ambiguous-ampersands (under "semi-related fun fact")
+ */
+ var htmlEscapes = {
+ '&': '&amp;',
+ '<': '&lt;',
+ '>': '&gt;',
+ '"': '&quot;',
+ "'": '&#x27;'
+ };
+
+ /** Used to convert HTML entities to characters */
+ var htmlUnescapes = invert(htmlEscapes);
+
+ /*--------------------------------------------------------------------------*/
+
+ /**
+ * Creates a clone of `value`. If `deep` is `true`, all nested objects will
+ * also be cloned otherwise they will be assigned by reference. Functions, DOM
+ * nodes, `arguments` objects, and objects created by constructors other than
+ * `Object` are **not** cloned.
+ *
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {Mixed} value The value to clone.
+ * @param {Boolean} deep A flag to indicate a deep clone.
+ * @param- {Object} [guard] Internally used to allow this method to work with
+ * others like `_.map` without using their callback `index` argument for `deep`.
+ * @param- {Array} [stackA=[]] Internally used to track traversed source objects.
+ * @param- {Array} [stackB=[]] Internally used to associate clones with their
+ * source counterparts.
+ * @returns {Mixed} Returns the cloned `value`.
+ * @example
+ *
+ * var stooges = [
+ * { 'name': 'moe', 'age': 40 },
+ * { 'name': 'larry', 'age': 50 },
+ * { 'name': 'curly', 'age': 60 }
+ * ];
+ *
+ * _.clone({ 'name': 'moe' });
+ * // => { 'name': 'moe' }
+ *
+ * var shallow = _.clone(stooges);
+ * shallow[0] === stooges[0];
+ * // => true
+ *
+ * var deep = _.clone(stooges, true);
+ * shallow[0] === stooges[0];
+ * // => false
+ */
+ function clone(value, deep, guard, stackA, stackB) {
+ if (value == null) {
+ return value;
+ }
+ if (guard) {
+ deep = false;
+ }
+ // inspect [[Class]]
+ var isObj = isObject(value);
+ if (isObj) {
+ // don't clone `arguments` objects, functions, or non-object Objects
+ var className = toString.call(value);
+ if (!cloneableClasses[className] || (noArgsClass && isArguments(value))) {
+ return value;
+ }
+ var isArr = className == arrayClass;
+ isObj = isArr || (className == objectClass ? isPlainObject(value) : isObj);
+ }
+ // shallow clone
+ if (!isObj || !deep) {
+ // don't clone functions
+ return isObj
+ ? (isArr ? slice.call(value) : assign({}, value))
+ : value;
+ }
+
+ var ctor = value.constructor;
+ switch (className) {
+ case boolClass:
+ case dateClass:
+ return new ctor(+value);
+
+ case numberClass:
+ case stringClass:
+ return new ctor(value);
+
+ case regexpClass:
+ return ctor(value.source, reFlags.exec(value));
+ }
+ // check for circular references and return corresponding clone
+ stackA || (stackA = []);
+ stackB || (stackB = []);
+
+ var length = stackA.length;
+ while (length--) {
+ if (stackA[length] == value) {
+ return stackB[length];
+ }
+ }
+ // init cloned object
+ var result = isArr ? ctor(value.length) : {};
+
+ // add the source value to the stack of traversed objects
+ // and associate it with its clone
+ stackA.push(value);
+ stackB.push(result);
+
+ // recursively populate clone (susceptible to call stack limits)
+ (isArr ? forEach : forOwn)(value, function(objValue, key) {
+ result[key] = clone(objValue, deep, null, stackA, stackB);
+ });
+
+ return result;
+ }
+
+ /**
+ * Assigns own enumerable properties of source object(s) to the `destination`
+ * object for all `destination` properties that resolve to `null`/`undefined`.
+ * Once a property is set, additional defaults of the same property will be
+ * ignored.
+ *
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {Object} object The destination object.
+ * @param {Object} [default1, default2, ...] The default objects.
+ * @returns {Object} Returns the destination object.
+ * @example
+ *
+ * var iceCream = { 'flavor': 'chocolate' };
+ * _.defaults(iceCream, { 'flavor': 'vanilla', 'sprinkles': 'rainbow' });
+ * // => { 'flavor': 'chocolate', 'sprinkles': 'rainbow' }
+ */
+ var defaults = createIterator(assignIteratorOptions, {
+ 'objectLoop': 'if (result[index] == null) ' + assignIteratorOptions.objectLoop
+ });
+
+ /**
+ * Creates a sorted array of all enumerable properties, own and inherited,
+ * of `object` that have function values.
+ *
+ * @static
+ * @memberOf _
+ * @alias methods
+ * @category Objects
+ * @param {Object} object The object to inspect.
+ * @returns {Array} Returns a new array of property names that have function values.
+ * @example
+ *
+ * _.functions(_);
+ * // => ['all', 'any', 'bind', 'bindAll', 'clone', 'compact', 'compose', ...]
+ */
+ function functions(object) {
+ var result = [];
+ forIn(object, function(value, key) {
+ if (isFunction(value)) {
+ result.push(key);
+ }
+ });
+ return result.sort();
+ }
+
+ /**
+ * Checks if the specified object `property` exists and is a direct property,
+ * instead of an inherited property.
+ *
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {Object} object The object to check.
+ * @param {String} property The property to check for.
+ * @returns {Boolean} Returns `true` if key is a direct property, else `false`.
+ * @example
+ *
+ * _.has({ 'a': 1, 'b': 2, 'c': 3 }, 'b');
+ * // => true
+ */
+ function has(object, property) {
+ return object ? hasOwnProperty.call(object, property) : false;
+ }
+
+ /**
+ * Creates an object composed of the inverted keys and values of the given `object`.
+ *
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {Object} object The object to invert.
+ * @returns {Object} Returns the created inverted object.
+ * @example
+ *
+ * _.invert({ 'first': 'Moe', 'second': 'Larry', 'third': 'Curly' });
+ * // => { 'Moe': 'first', 'Larry': 'second', 'Curly': 'third' } (order is not guaranteed)
+ */
+ function invert(object) {
+ var result = {};
+ forOwn(object, function(value, key) {
+ result[value] = key;
+ });
+ return result;
+ }
+
+ /**
+ * Checks if `value` is an array.
+ *
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {Mixed} value The value to check.
+ * @returns {Boolean} Returns `true` if the `value` is an array, else `false`.
+ * @example
+ *
+ * (function() { return _.isArray(arguments); })();
+ * // => false
+ *
+ * _.isArray([1, 2, 3]);
+ * // => true
+ */
+ var isArray = nativeIsArray || function(value) {
+ return toString.call(value) == arrayClass;
+ };
+
+ /**
+ * Checks if `value` is a boolean (`true` or `false`) value.
+ *
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {Mixed} value The value to check.
+ * @returns {Boolean} Returns `true` if the `value` is a boolean value, else `false`.
+ * @example
+ *
+ * _.isBoolean(null);
+ * // => false
+ */
+ function isBoolean(value) {
+ return value === true || value === false || toString.call(value) == boolClass;
+ }
+
+ /**
+ * Checks if `value` is a date.
+ *
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {Mixed} value The value to check.
+ * @returns {Boolean} Returns `true` if the `value` is a date, else `false`.
+ * @example
+ *
+ * _.isDate(new Date);
+ * // => true
+ */
+ function isDate(value) {
+ return toString.call(value) == dateClass;
+ }
+
+ /**
+ * Checks if `value` is a DOM element.
+ *
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {Mixed} value The value to check.
+ * @returns {Boolean} Returns `true` if the `value` is a DOM element, else `false`.
+ * @example
+ *
+ * _.isElement(document.body);
+ * // => true
+ */
+ function isElement(value) {
+ return value ? value.nodeType === 1 : false;
+ }
+
+ /**
+ * Checks if `value` is empty. Arrays, strings, or `arguments` objects with a
+ * length of `0` and objects with no own enumerable properties are considered
+ * "empty".
+ *
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {Array|Object|String} value The value to inspect.
+ * @returns {Boolean} Returns `true` if the `value` is empty, else `false`.
+ * @example
+ *
+ * _.isEmpty([1, 2, 3]);
+ * // => false
+ *
+ * _.isEmpty({});
+ * // => true
+ *
+ * _.isEmpty('');
+ * // => true
+ */
+ function isEmpty(value) {
+ var result = true;
+ if (!value) {
+ return result;
+ }
+ var className = toString.call(value),
+ length = value.length;
+
+ if ((className == arrayClass || className == stringClass ||
+ className == argsClass || (noArgsClass && isArguments(value))) ||
+ (className == objectClass && typeof length == 'number' && isFunction(value.splice))) {
+ return !length;
+ }
+ forOwn(value, function() {
+ return (result = false);
+ });
+ return result;
+ }
+
+ /**
+ * Performs a deep comparison between two values to determine if they are
+ * equivalent to each other.
+ *
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {Mixed} a The value to compare.
+ * @param {Mixed} b The other value to compare.
+ * @param- {Object} [stackA=[]] Internally used track traversed `a` objects.
+ * @param- {Object} [stackB=[]] Internally used track traversed `b` objects.
+ * @returns {Boolean} Returns `true` if the values are equvalent, else `false`.
+ * @example
+ *
+ * var moe = { 'name': 'moe', 'luckyNumbers': [13, 27, 34] };
+ * var clone = { 'name': 'moe', 'luckyNumbers': [13, 27, 34] };
+ *
+ * moe == clone;
+ * // => false
+ *
+ * _.isEqual(moe, clone);
+ * // => true
+ */
+ function isEqual(a, b, stackA, stackB) {
+ // exit early for identical values
+ if (a === b) {
+ // treat `+0` vs. `-0` as not equal
+ return a !== 0 || (1 / a == 1 / b);
+ }
+ // a strict comparison is necessary because `null == undefined`
+ if (a == null || b == null) {
+ return a === b;
+ }
+ // compare [[Class]] names
+ var className = toString.call(a);
+ if (className != toString.call(b)) {
+ return false;
+ }
+ switch (className) {
+ case boolClass:
+ case dateClass:
+ // coerce dates and booleans to numbers, dates to milliseconds and booleans
+ // to `1` or `0`, treating invalid dates coerced to `NaN` as not equal
+ return +a == +b;
+
+ case numberClass:
+ // treat `NaN` vs. `NaN` as equal
+ return a != +a
+ ? b != +b
+ // but treat `+0` vs. `-0` as not equal
+ : (a == 0 ? (1 / a == 1 / b) : a == +b);
+
+ case regexpClass:
+ case stringClass:
+ // coerce regexes to strings (http://es5.github.com/#x15.10.6.4)
+ // treat string primitives and their corresponding object instances as equal
+ return a == b + '';
+ }
+ // exit early, in older browsers, if `a` is array-like but not `b`
+ var isArr = className == arrayClass || className == argsClass;
+ if (noArgsClass && !isArr && (isArr = isArguments(a)) && !isArguments(b)) {
+ return false;
+ }
+ if (!isArr) {
+ // unwrap any `lodash` wrapped values
+ if (a.__wrapped__ || b.__wrapped__) {
+ return isEqual(a.__wrapped__ || a, b.__wrapped__ || b);
+ }
+ // exit for functions and DOM nodes
+ if (className != objectClass || (noNodeClass && (
+ (typeof a.toString != 'function' && typeof (a + '') == 'string') ||
+ (typeof b.toString != 'function' && typeof (b + '') == 'string')))) {
+ return false;
+ }
+ var ctorA = a.constructor,
+ ctorB = b.constructor;
+
+ // non `Object` object instances with different constructors are not equal
+ if (ctorA != ctorB && !(
+ isFunction(ctorA) && ctorA instanceof ctorA &&
+ isFunction(ctorB) && ctorB instanceof ctorB
+ )) {
+ return false;
+ }
+ }
+ // assume cyclic structures are equal
+ // the algorithm for detecting cyclic structures is adapted from ES 5.1
+ // section 15.12.3, abstract operation `JO` (http://es5.github.com/#x15.12.3)
+ stackA || (stackA = []);
+ stackB || (stackB = []);
+
+ var length = stackA.length;
+ while (length--) {
+ if (stackA[length] == a) {
+ return stackB[length] == b;
+ }
+ }
+
+ var index = -1,
+ result = true,
+ size = 0;
+
+ // add `a` and `b` to the stack of traversed objects
+ stackA.push(a);
+ stackB.push(b);
+
+ // recursively compare objects and arrays (susceptible to call stack limits)
+ if (isArr) {
+ // compare lengths to determine if a deep comparison is necessary
+ size = a.length;
+ result = size == b.length;
+
+ if (result) {
+ // deep compare the contents, ignoring non-numeric properties
+ while (size--) {
+ if (!(result = isEqual(a[size], b[size], stackA, stackB))) {
+ break;
+ }
+ }
+ }
+ return result;
+ }
+ // deep compare objects
+ for (var key in a) {
+ if (hasOwnProperty.call(a, key)) {
+ // count the number of properties.
+ size++;
+ // deep compare each property value.
+ if (!(hasOwnProperty.call(b, key) && isEqual(a[key], b[key], stackA, stackB))) {
+ return false;
+ }
+ }
+ }
+ // ensure both objects have the same number of properties
+ for (key in b) {
+ // The JS engine in Adobe products, like InDesign, has a bug that causes
+ // `!size--` to throw an error so it must be wrapped in parentheses.
+ // https://github.com/documentcloud/underscore/issues/355
+ if (hasOwnProperty.call(b, key) && !(size--)) {
+ // `size` will be `-1` if `b` has more properties than `a`
+ return false;
+ }
+ }
+ // handle JScript [[DontEnum]] bug
+ if (hasDontEnumBug) {
+ while (++index < 7) {
+ key = shadowed[index];
+ if (hasOwnProperty.call(a, key) &&
+ !(hasOwnProperty.call(b, key) && isEqual(a[key], b[key], stackA, stackB))) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Checks if `value` is, or can be coerced to, a finite number.
+ *
+ * Note: This is not the same as native `isFinite`, which will return true for
+ * booleans and empty strings. See http://es5.github.com/#x15.1.2.5.
+ *
+ * @deprecated
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {Mixed} value The value to check.
+ * @returns {Boolean} Returns `true` if the `value` is a finite number, else `false`.
+ * @example
+ *
+ * _.isFinite(-101);
+ * // => true
+ *
+ * _.isFinite('10');
+ * // => true
+ *
+ * _.isFinite(true);
+ * // => false
+ *
+ * _.isFinite('');
+ * // => false
+ *
+ * _.isFinite(Infinity);
+ * // => false
+ */
+ function isFinite(value) {
+ return nativeIsFinite(value) && !nativeIsNaN(parseFloat(value));
+ }
+
+ /**
+ * Checks if `value` is a function.
+ *
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {Mixed} value The value to check.
+ * @returns {Boolean} Returns `true` if the `value` is a function, else `false`.
+ * @example
+ *
+ * _.isFunction(_);
+ * // => true
+ */
+ function isFunction(value) {
+ return typeof value == 'function';
+ }
+ // fallback for older versions of Chrome and Safari
+ if (isFunction(/x/)) {
+ isFunction = function(value) {
+ return toString.call(value) == funcClass;
+ };
+ }
+
+ /**
+ * Checks if `value` is the language type of Object.
+ * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
+ *
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {Mixed} value The value to check.
+ * @returns {Boolean} Returns `true` if the `value` is an object, else `false`.
+ * @example
+ *
+ * _.isObject({});
+ * // => true
+ *
+ * _.isObject([1, 2, 3]);
+ * // => true
+ *
+ * _.isObject(1);
+ * // => false
+ */
+ function isObject(value) {
+ // check if the value is the ECMAScript language type of Object
+ // http://es5.github.com/#x8
+ // and avoid a V8 bug
+ // http://code.google.com/p/v8/issues/detail?id=2291
+ return value ? objectTypes[typeof value] : false;
+ }
+
+ /**
+ * Checks if `value` is `NaN`.
+ *
+ * Note: This is not the same as native `isNaN`, which will return true for
+ * `undefined` and other values. See http://es5.github.com/#x15.1.2.4.
+ *
+ * @deprecated
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {Mixed} value The value to check.
+ * @returns {Boolean} Returns `true` if the `value` is `NaN`, else `false`.
+ * @example
+ *
+ * _.isNaN(NaN);
+ * // => true
+ *
+ * _.isNaN(new Number(NaN));
+ * // => true
+ *
+ * isNaN(undefined);
+ * // => true
+ *
+ * _.isNaN(undefined);
+ * // => false
+ */
+ function isNaN(value) {
+ // `NaN` as a primitive is the only value that is not equal to itself
+ // (perform the [[Class]] check first to avoid errors with some host objects in IE)
+ return toString.call(value) == numberClass && value != +value
+ }
+
+ /**
+ * Checks if `value` is `null`.
+ *
+ * @deprecated
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {Mixed} value The value to check.
+ * @returns {Boolean} Returns `true` if the `value` is `null`, else `false`.
+ * @example
+ *
+ * _.isNull(null);
+ * // => true
+ *
+ * _.isNull(undefined);
+ * // => false
+ */
+ function isNull(value) {
+ return value === null;
+ }
+
+ /**
+ * Checks if `value` is a number.
+ *
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {Mixed} value The value to check.
+ * @returns {Boolean} Returns `true` if the `value` is a number, else `false`.
+ * @example
+ *
+ * _.isNumber(8.4 * 5);
+ * // => true
+ */
+ function isNumber(value) {
+ return toString.call(value) == numberClass;
+ }
+
+ /**
+ * Checks if a given `value` is an object created by the `Object` constructor.
+ *
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {Mixed} value The value to check.
+ * @returns {Boolean} Returns `true` if `value` is a plain object, else `false`.
+ * @example
+ *
+ * function Stooge(name, age) {
+ * this.name = name;
+ * this.age = age;
+ * }
+ *
+ * _.isPlainObject(new Stooge('moe', 40));
+ * // => false
+ *
+ * _.isPlainObject([1, 2, 3]);
+ * // => false
+ *
+ * _.isPlainObject({ 'name': 'moe', 'age': 40 });
+ * // => true
+ */
+ var isPlainObject = !getPrototypeOf ? shimIsPlainObject : function(value) {
+ if (!(value && typeof value == 'object')) {
+ return false;
+ }
+ var valueOf = value.valueOf,
+ objProto = typeof valueOf == 'function' && (objProto = getPrototypeOf(valueOf)) && getPrototypeOf(objProto);
+
+ return objProto
+ ? value == objProto || (getPrototypeOf(value) == objProto && !isArguments(value))
+ : shimIsPlainObject(value);
+ };
+
+ /**
+ * Checks if `value` is a regular expression.
+ *
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {Mixed} value The value to check.
+ * @returns {Boolean} Returns `true` if the `value` is a regular expression, else `false`.
+ * @example
+ *
+ * _.isRegExp(/moe/);
+ * // => true
+ */
+ function isRegExp(value) {
+ return toString.call(value) == regexpClass;
+ }
+
+ /**
+ * Checks if `value` is a string.
+ *
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {Mixed} value The value to check.
+ * @returns {Boolean} Returns `true` if the `value` is a string, else `false`.
+ * @example
+ *
+ * _.isString('moe');
+ * // => true
+ */
+ function isString(value) {
+ return toString.call(value) == stringClass;
+ }
+
+ /**
+ * Checks if `value` is `undefined`.
+ *
+ * @deprecated
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {Mixed} value The value to check.
+ * @returns {Boolean} Returns `true` if the `value` is `undefined`, else `false`.
+ * @example
+ *
+ * _.isUndefined(void 0);
+ * // => true
+ */
+ function isUndefined(value) {
+ return value === undefined;
+ }
+
+ /**
+ * Creates an array composed of the own enumerable property names of `object`.
+ *
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {Object} object The object to inspect.
+ * @returns {Array} Returns a new array of property names.
+ * @example
+ *
+ * _.keys({ 'one': 1, 'two': 2, 'three': 3 });
+ * // => ['one', 'two', 'three'] (order is not guaranteed)
+ */
+ var keys = !nativeKeys ? shimKeys : function(object) {
+ // avoid iterating over the `prototype` property
+ return typeof object == 'function' && propertyIsEnumerable.call(object, 'prototype')
+ ? shimKeys(object)
+ : (isObject(object) ? nativeKeys(object) : []);
+ };
+
+ /**
+ * Merges enumerable properties of the source object(s) into the `destination`
+ * object. Subsequent sources will overwrite propery assignments of previous
+ * sources.
+ *
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {Object} object The destination object.
+ * @param {Object} [source1, source2, ...] The source objects.
+ * @param- {Object} [indicator] Internally used to indicate that the `stack`
+ * argument is an array of traversed objects instead of another source object.
+ * @param- {Array} [stackA=[]] Internally used to track traversed source objects.
+ * @param- {Array} [stackB=[]] Internally used to associate values with their
+ * source counterparts.
+ * @returns {Object} Returns the destination object.
+ * @example
+ *
+ * var stooges = [
+ * { 'name': 'moe' },
+ * { 'name': 'larry' }
+ * ];
+ *
+ * var ages = [
+ * { 'age': 40 },
+ * { 'age': 50 }
+ * ];
+ *
+ * _.merge(stooges, ages);
+ * // => [{ 'name': 'moe', 'age': 40 }, { 'name': 'larry', 'age': 50 }]
+ */
+ function merge(object, source, indicator) {
+ var args = arguments,
+ index = 0,
+ length = 2,
+ stackA = args[3],
+ stackB = args[4];
+
+ if (indicator !== indicatorObject) {
+ stackA = [];
+ stackB = [];
+
+ // work with `_.reduce` by only using its callback `accumulator` and `value` arguments
+ if (typeof indicator != 'number') {
+ length = args.length;
+ }
+ }
+ while (++index < length) {
+ forOwn(args[index], function(source, key) {
+ var found, isArr, value;
+ if (source && ((isArr = isArray(source)) || isPlainObject(source))) {
+ // avoid merging previously merged cyclic sources
+ var stackLength = stackA.length;
+ while (stackLength--) {
+ found = stackA[stackLength] == source;
+ if (found) {
+ break;
+ }
+ }
+ if (found) {
+ object[key] = stackB[stackLength];
+ }
+ else {
+ // add `source` and associated `value` to the stack of traversed objects
+ stackA.push(source);
+ stackB.push(value = (value = object[key], isArr)
+ ? (isArray(value) ? value : [])
+ : (isPlainObject(value) ? value : {})
+ );
+ // recursively merge objects and arrays (susceptible to call stack limits)
+ object[key] = merge(value, source, indicatorObject, stackA, stackB);
+ }
+ } else if (source != null) {
+ object[key] = source;
+ }
+ });
+ }
+ return object;
+ }
+
+ /**
+ * Creates a shallow clone of `object` excluding the specified properties.
+ * Property names may be specified as individual arguments or as arrays of
+ * property names. If `callback` is passed, it will be executed for each property
+ * in the `object`, omitting the properties `callback` returns truthy for. The
+ * `callback` is bound to `thisArg` and invoked with three arguments; (value, key, object).
+ *
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {Object} object The source object.
+ * @param {Function|String} callback|[prop1, prop2, ...] The properties to omit
+ * or the function called per iteration.
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
+ * @returns {Object} Returns an object without the omitted properties.
+ * @example
+ *
+ * _.omit({ 'name': 'moe', 'age': 40, 'userid': 'moe1' }, 'userid');
+ * // => { 'name': 'moe', 'age': 40 }
+ *
+ * _.omit({ 'name': 'moe', '_hint': 'knucklehead', '_seed': '96c4eb' }, function(value, key) {
+ * return key.charAt(0) == '_';
+ * });
+ * // => { 'name': 'moe' }
+ */
+ function omit(object, callback, thisArg) {
+ var isFunc = typeof callback == 'function',
+ result = {};
+
+ if (isFunc) {
+ callback = createCallback(callback, thisArg);
+ } else {
+ var props = concat.apply(arrayRef, arguments);
+ }
+ forIn(object, function(value, key, object) {
+ if (isFunc
+ ? !callback(value, key, object)
+ : indexOf(props, key, 1) < 0
+ ) {
+ result[key] = value;
+ }
+ });
+ return result;
+ }
+
+ /**
+ * Creates a two dimensional array of the given object's key-value pairs,
+ * i.e. `[[key1, value1], [key2, value2]]`.
+ *
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {Object} object The object to inspect.
+ * @returns {Array} Returns new array of key-value pairs.
+ * @example
+ *
+ * _.pairs({ 'moe': 30, 'larry': 40, 'curly': 50 });
+ * // => [['moe', 30], ['larry', 40], ['curly', 50]] (order is not guaranteed)
+ */
+ function pairs(object) {
+ var result = [];
+ forOwn(object, function(value, key) {
+ result.push([key, value]);
+ });
+ return result;
+ }
+
+ /**
+ * Creates a shallow clone of `object` composed of the specified properties.
+ * Property names may be specified as individual arguments or as arrays of
+ * property names. If `callback` is passed, it will be executed for each property
+ * in the `object`, picking the properties `callback` returns truthy for. The
+ * `callback` is bound to `thisArg` and invoked with three arguments; (value, key, object).
+ *
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {Object} object The source object.
+ * @param {Function|String} callback|[prop1, prop2, ...] The properties to pick
+ * or the function called per iteration.
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
+ * @returns {Object} Returns an object composed of the picked properties.
+ * @example
+ *
+ * _.pick({ 'name': 'moe', 'age': 40, 'userid': 'moe1' }, 'name', 'age');
+ * // => { 'name': 'moe', 'age': 40 }
+ *
+ * _.pick({ 'name': 'moe', '_hint': 'knucklehead', '_seed': '96c4eb' }, function(value, key) {
+ * return key.charAt(0) != '_';
+ * });
+ * // => { 'name': 'moe' }
+ */
+ function pick(object, callback, thisArg) {
+ var result = {};
+ if (typeof callback != 'function') {
+ var index = 0,
+ props = concat.apply(arrayRef, arguments),
+ length = props.length;
+
+ while (++index < length) {
+ var key = props[index];
+ if (key in object) {
+ result[key] = object[key];
+ }
+ }
+ } else {
+ callback = createCallback(callback, thisArg);
+ forIn(object, function(value, key, object) {
+ if (callback(value, key, object)) {
+ result[key] = value;
+ }
+ });
+ }
+ return result;
+ }
+
+ /**
+ * Creates an array composed of the own enumerable property values of `object`.
+ *
+ * @static
+ * @memberOf _
+ * @category Objects
+ * @param {Object} object The object to inspect.
+ * @returns {Array} Returns a new array of property values.
+ * @example
+ *
+ * _.values({ 'one': 1, 'two': 2, 'three': 3 });
+ * // => [1, 2, 3]
+ */
+ function values(object) {
+ var result = [];
+ forOwn(object, function(value) {
+ result.push(value);
+ });
+ return result;
+ }
+
+ /*--------------------------------------------------------------------------*/
+
+ /**
+ * Checks if a given `target` element is present in a `collection` using strict
+ * equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used
+ * as the offset from the end of the collection.
+ *
+ * @static
+ * @memberOf _
+ * @alias include
+ * @category Collections
+ * @param {Array|Object|String} collection The collection to iterate over.
+ * @param {Mixed} target The value to check for.
+ * @param {Number} [fromIndex=0] The index to search from.
+ * @returns {Boolean} Returns `true` if the `target` element is found, else `false`.
+ * @example
+ *
+ * _.contains([1, 2, 3], 1);
+ * // => true
+ *
+ * _.contains([1, 2, 3], 1, 2);
+ * // => false
+ *
+ * _.contains({ 'name': 'moe', 'age': 40 }, 'moe');
+ * // => true
+ *
+ * _.contains('curly', 'ur');
+ * // => true
+ */
+ function contains(collection, target, fromIndex) {
+ var index = -1,
+ length = collection ? collection.length : 0,
+ result = false;
+
+ fromIndex = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex) || 0;
+ if (typeof length == 'number') {
+ result = (isString(collection)
+ ? collection.indexOf(target, fromIndex)
+ : indexOf(collection, target, fromIndex)
+ ) > -1;
+ } else {
+ forEach(collection, function(value) {
+ if (++index >= fromIndex) {
+ return !(result = value === target);
+ }
+ });
+ }
+ return result;
+ }
+
+ /**
+ * Creates an object composed of keys returned from running each element of
+ * `collection` through a `callback`. The corresponding value of each key is
+ * the number of times the key was returned by `callback`. The `callback` is
+ * bound to `thisArg` and invoked with three arguments; (value, index|key, collection).
+ * The `callback` argument may also be the name of a property to count by (e.g. 'length').
+ *
+ * @static
+ * @memberOf _
+ * @category Collections
+ * @param {Array|Object|String} collection The collection to iterate over.
+ * @param {Function|String} callback|property The function called per iteration
+ * or property name to count by.
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
+ * @returns {Object} Returns the composed aggregate object.
+ * @example
+ *
+ * _.countBy([4.3, 6.1, 6.4], function(num) { return Math.floor(num); });
+ * // => { '4': 1, '6': 2 }
+ *
+ * _.countBy([4.3, 6.1, 6.4], function(num) { return this.floor(num); }, Math);
+ * // => { '4': 1, '6': 2 }
+ *
+ * _.countBy(['one', 'two', 'three'], 'length');
+ * // => { '3': 2, '5': 1 }
+ */
+ function countBy(collection, callback, thisArg) {
+ var result = {};
+ callback = createCallback(callback, thisArg);
+ forEach(collection, function(value, key, collection) {
+ key = callback(value, key, collection);
+ (hasOwnProperty.call(result, key) ? result[key]++ : result[key] = 1);
+ });
+ return result;
+ }
+
+ /**
+ * Checks if the `callback` returns a truthy value for **all** elements of a
+ * `collection`. The `callback` is bound to `thisArg` and invoked with three
+ * arguments; (value, index|key, collection).
+ *
+ * @static
+ * @memberOf _
+ * @alias all
+ * @category Collections
+ * @param {Array|Object|String} collection The collection to iterate over.
+ * @param {Function} [callback=identity] The function called per iteration.
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
+ * @returns {Boolean} Returns `true` if all elements pass the callback check,
+ * else `false`.
+ * @example
+ *
+ * _.every([true, 1, null, 'yes'], Boolean);
+ * // => false
+ */
+ function every(collection, callback, thisArg) {
+ var result = true;
+ callback = createCallback(callback, thisArg);
+
+ if (isArray(collection)) {
+ var index = -1,
+ length = collection.length;
+
+ while (++index < length) {
+ if (!(result = !!callback(collection[index], index, collection))) {
+ break;
+ }
+ }
+ } else {
+ forEach(collection, function(value, index, collection) {
+ return (result = !!callback(value, index, collection));
+ });
+ }
+ return result;
+ }
+
+ /**
+ * Examines each element in a `collection`, returning an array of all elements
+ * the `callback` returns truthy for. The `callback` is bound to `thisArg` and
+ * invoked with three arguments; (value, index|key, collection).
+ *
+ * @static
+ * @memberOf _
+ * @alias select
+ * @category Collections
+ * @param {Array|Object|String} collection The collection to iterate over.
+ * @param {Function} [callback=identity] The function called per iteration.
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
+ * @returns {Array} Returns a new array of elements that passed the callback check.
+ * @example
+ *
+ * var evens = _.filter([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
+ * // => [2, 4, 6]
+ */
+ function filter(collection, callback, thisArg) {
+ var result = [];
+ callback = createCallback(callback, thisArg);
+
+ if (isArray(collection)) {
+ var index = -1,
+ length = collection.length;
+
+ while (++index < length) {
+ var value = collection[index];
+ if (callback(value, index, collection)) {
+ result.push(value);
+ }
+ }
+ } else {
+ forEach(collection, function(value, index, collection) {
+ if (callback(value, index, collection)) {
+ result.push(value);
+ }
+ });
+ }
+ return result;
+ }
+
+ /**
+ * Examines each element in a `collection`, returning the first one the `callback`
+ * returns truthy for. The function returns as soon as it finds an acceptable
+ * element, and does not iterate over the entire `collection`. The `callback` is
+ * bound to `thisArg` and invoked with three arguments; (value, index|key, collection).
+ *
+ * @static
+ * @memberOf _
+ * @alias detect
+ * @category Collections
+ * @param {Array|Object|String} collection The collection to iterate over.
+ * @param {Function} callback The function called per iteration.
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
+ * @returns {Mixed} Returns the element that passed the callback check,
+ * else `undefined`.
+ * @example
+ *
+ * var even = _.find([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
+ * // => 2
+ */
+ function find(collection, callback, thisArg) {
+ var result;
+ callback = createCallback(callback, thisArg);
+ forEach(collection, function(value, index, collection) {
+ if (callback(value, index, collection)) {
+ result = value;
+ return false;
+ }
+ });
+ return result;
+ }
+
+ /**
+ * Iterates over a `collection`, executing the `callback` for each element in
+ * the `collection`. The `callback` is bound to `thisArg` and invoked with three
+ * arguments; (value, index|key, collection). Callbacks may exit iteration early
+ * by explicitly returning `false`.
+ *
+ * @static
+ * @memberOf _
+ * @alias each
+ * @category Collections
+ * @param {Array|Object|String} collection The collection to iterate over.
+ * @param {Function} callback The function called per iteration.
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
+ * @returns {Array|Object|String} Returns `collection`.
+ * @example
+ *
+ * _([1, 2, 3]).forEach(alert).join(',');
+ * // => alerts each number and returns '1,2,3'
+ *
+ * _.forEach({ 'one': 1, 'two': 2, 'three': 3 }, alert);
+ * // => alerts each number (order is not guaranteed)
+ */
+ var forEach = createIterator(forEachIteratorOptions);
+
+ /**
+ * Creates an object composed of keys returned from running each element of
+ * `collection` through a `callback`. The corresponding value of each key is an
+ * array of elements passed to `callback` that returned the key. The `callback`
+ * is bound to `thisArg` and invoked with three arguments; (value, index|key, collection).
+ * The `callback` argument may also be the name of a property to group by (e.g. 'length').
+ *
+ * @static
+ * @memberOf _
+ * @category Collections
+ * @param {Array|Object|String} collection The collection to iterate over.
+ * @param {Function|String} callback|property The function called per iteration
+ * or property name to group by.
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
+ * @returns {Object} Returns the composed aggregate object.
+ * @example
+ *
+ * _.groupBy([4.2, 6.1, 6.4], function(num) { return Math.floor(num); });
+ * // => { '4': [4.2], '6': [6.1, 6.4] }
+ *
+ * _.groupBy([4.2, 6.1, 6.4], function(num) { return this.floor(num); }, Math);
+ * // => { '4': [4.2], '6': [6.1, 6.4] }
+ *
+ * _.groupBy(['one', 'two', 'three'], 'length');
+ * // => { '3': ['one', 'two'], '5': ['three'] }
+ */
+ function groupBy(collection, callback, thisArg) {
+ var result = {};
+ callback = createCallback(callback, thisArg);
+ forEach(collection, function(value, key, collection) {
+ key = callback(value, key, collection);
+ (hasOwnProperty.call(result, key) ? result[key] : result[key] = []).push(value);
+ });
+ return result;
+ }
+
+ /**
+ * Invokes the method named by `methodName` on each element in the `collection`,
+ * returning an array of the results of each invoked method. Additional arguments
+ * will be passed to each invoked method. If `methodName` is a function it will
+ * be invoked for, and `this` bound to, each element in the `collection`.
+ *
+ * @static
+ * @memberOf _
+ * @category Collections
+ * @param {Array|Object|String} collection The collection to iterate over.
+ * @param {Function|String} methodName The name of the method to invoke or
+ * the function invoked per iteration.
+ * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the method with.
+ * @returns {Array} Returns a new array of the results of each invoked method.
+ * @example
+ *
+ * _.invoke([[5, 1, 7], [3, 2, 1]], 'sort');
+ * // => [[1, 5, 7], [1, 2, 3]]
+ *
+ * _.invoke([123, 456], String.prototype.split, '');
+ * // => [['1', '2', '3'], ['4', '5', '6']]
+ */
+ function invoke(collection, methodName) {
+ var args = slice.call(arguments, 2),
+ isFunc = typeof methodName == 'function',
+ result = [];
+
+ forEach(collection, function(value) {
+ result.push((isFunc ? methodName : value[methodName]).apply(value, args));
+ });
+ return result;
+ }
+
+ /**
+ * Creates an array of values by running each element in the `collection`
+ * through a `callback`. The `callback` is bound to `thisArg` and invoked with
+ * three arguments; (value, index|key, collection).
+ *
+ * @static
+ * @memberOf _
+ * @alias collect
+ * @category Collections
+ * @param {Array|Object|String} collection The collection to iterate over.
+ * @param {Function} [callback=identity] The function called per iteration.
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
+ * @returns {Array} Returns a new array of the results of each `callback` execution.
+ * @example
+ *
+ * _.map([1, 2, 3], function(num) { return num * 3; });
+ * // => [3, 6, 9]
+ *
+ * _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { return num * 3; });
+ * // => [3, 6, 9] (order is not guaranteed)
+ */
+ function map(collection, callback, thisArg) {
+ var index = -1,
+ length = collection ? collection.length : 0,
+ result = Array(typeof length == 'number' ? length : 0);
+
+ callback = createCallback(callback, thisArg);
+ if (isArray(collection)) {
+ while (++index < length) {
+ result[index] = callback(collection[index], index, collection);
+ }
+ } else {
+ forEach(collection, function(value, key, collection) {
+ result[++index] = callback(value, key, collection);
+ });
+ }
+ return result;
+ }
+
+ /**
+ * Retrieves the maximum value of an `array`. If `callback` is passed,
+ * it will be executed for each value in the `array` to generate the
+ * criterion by which the value is ranked. The `callback` is bound to
+ * `thisArg` and invoked with three arguments; (value, index, collection).
+ *
+ * @static
+ * @memberOf _
+ * @category Collections
+ * @param {Array|Object|String} collection The collection to iterate over.
+ * @param {Function} [callback] The function called per iteration.
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
+ * @returns {Mixed} Returns the maximum value.
+ * @example
+ *
+ * var stooges = [
+ * { 'name': 'moe', 'age': 40 },
+ * { 'name': 'larry', 'age': 50 },
+ * { 'name': 'curly', 'age': 60 }
+ * ];
+ *
+ * _.max(stooges, function(stooge) { return stooge.age; });
+ * // => { 'name': 'curly', 'age': 60 };
+ */
+ function max(collection, callback, thisArg) {
+ var computed = -Infinity,
+ index = -1,
+ length = collection ? collection.length : 0,
+ result = computed;
+
+ if (callback || !isArray(collection)) {
+ callback = !callback && isString(collection)
+ ? charAtCallback
+ : createCallback(callback, thisArg);
+
+ forEach(collection, function(value, index, collection) {
+ var current = callback(value, index, collection);
+ if (current > computed) {
+ computed = current;
+ result = value;
+ }
+ });
+ } else {
+ while (++index < length) {
+ if (collection[index] > result) {
+ result = collection[index];
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Retrieves the minimum value of an `array`. If `callback` is passed,
+ * it will be executed for each value in the `array` to generate the
+ * criterion by which the value is ranked. The `callback` is bound to `thisArg`
+ * and invoked with three arguments; (value, index, collection).
+ *
+ * @static
+ * @memberOf _
+ * @category Collections
+ * @param {Array|Object|String} collection The collection to iterate over.
+ * @param {Function} [callback] The function called per iteration.
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
+ * @returns {Mixed} Returns the minimum value.
+ * @example
+ *
+ * _.min([10, 5, 100, 2, 1000]);
+ * // => 2
+ */
+ function min(collection, callback, thisArg) {
+ var computed = Infinity,
+ index = -1,
+ length = collection ? collection.length : 0,
+ result = computed;
+
+ if (callback || !isArray(collection)) {
+ callback = !callback && isString(collection)
+ ? charAtCallback
+ : createCallback(callback, thisArg);
+
+ forEach(collection, function(value, index, collection) {
+ var current = callback(value, index, collection);
+ if (current < computed) {
+ computed = current;
+ result = value;
+ }
+ });
+ } else {
+ while (++index < length) {
+ if (collection[index] < result) {
+ result = collection[index];
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Retrieves the value of a specified property from all elements in
+ * the `collection`.
+ *
+ * @static
+ * @memberOf _
+ * @category Collections
+ * @param {Array|Object|String} collection The collection to iterate over.
+ * @param {String} property The property to pluck.
+ * @returns {Array} Returns a new array of property values.
+ * @example
+ *
+ * var stooges = [
+ * { 'name': 'moe', 'age': 40 },
+ * { 'name': 'larry', 'age': 50 },
+ * { 'name': 'curly', 'age': 60 }
+ * ];
+ *
+ * _.pluck(stooges, 'name');
+ * // => ['moe', 'larry', 'curly']
+ */
+ function pluck(collection, property) {
+ var result = [];
+ forEach(collection, function(value) {
+ result.push(value[property]);
+ });
+ return result;
+ }
+
+ /**
+ * Boils down a `collection` to a single value. The initial state of the
+ * reduction is `accumulator` and each successive step of it should be returned
+ * by the `callback`. The `callback` is bound to `thisArg` and invoked with 4
+ * arguments; for arrays they are (accumulator, value, index|key, collection).
+ *
+ * @static
+ * @memberOf _
+ * @alias foldl, inject
+ * @category Collections
+ * @param {Array|Object|String} collection The collection to iterate over.
+ * @param {Function} callback The function called per iteration.
+ * @param {Mixed} [accumulator] Initial value of the accumulator.
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
+ * @returns {Mixed} Returns the accumulated value.
+ * @example
+ *
+ * var sum = _.reduce([1, 2, 3], function(memo, num) { return memo + num; });
+ * // => 6
+ */
+ function reduce(collection, callback, accumulator, thisArg) {
+ var noaccum = arguments.length < 3;
+ callback = createCallback(callback, thisArg);
+ forEach(collection, function(value, index, collection) {
+ accumulator = noaccum
+ ? (noaccum = false, value)
+ : callback(accumulator, value, index, collection)
+ });
+ return accumulator;
+ }
+
+ /**
+ * The right-associative version of `_.reduce`.
+ *
+ * @static
+ * @memberOf _
+ * @alias foldr
+ * @category Collections
+ * @param {Array|Object|String} collection The collection to iterate over.
+ * @param {Function} callback The function called per iteration.
+ * @param {Mixed} [accumulator] Initial value of the accumulator.
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
+ * @returns {Mixed} Returns the accumulated value.
+ * @example
+ *
+ * var list = [[0, 1], [2, 3], [4, 5]];
+ * var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []);
+ * // => [4, 5, 2, 3, 0, 1]
+ */
+ function reduceRight(collection, callback, accumulator, thisArg) {
+ var iteratee = collection,
+ length = collection ? collection.length : 0,
+ noaccum = arguments.length < 3;
+
+ if (typeof length != 'number') {
+ var props = keys(collection);
+ length = props.length;
+ } else if (noCharByIndex && isString(collection)) {
+ iteratee = collection.split('');
+ }
+ forEach(collection, function(value, index, collection) {
+ index = props ? props[--length] : --length;
+ accumulator = noaccum
+ ? (noaccum = false, iteratee[index])
+ : callback.call(thisArg, accumulator, iteratee[index], index, collection);
+ });
+ return accumulator;
+ }
+
+ /**
+ * The opposite of `_.filter`, this method returns the values of a
+ * `collection` that `callback` does **not** return truthy for.
+ *
+ * @static
+ * @memberOf _
+ * @category Collections
+ * @param {Array|Object|String} collection The collection to iterate over.
+ * @param {Function} [callback=identity] The function called per iteration.
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
+ * @returns {Array} Returns a new array of elements that did **not** pass the
+ * callback check.
+ * @example
+ *
+ * var odds = _.reject([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
+ * // => [1, 3, 5]
+ */
+ function reject(collection, callback, thisArg) {
+ callback = createCallback(callback, thisArg);
+ return filter(collection, function(value, index, collection) {
+ return !callback(value, index, collection);
+ });
+ }
+
+ /**
+ * Creates an array of shuffled `array` values, using a version of the
+ * Fisher-Yates shuffle. See http://en.wikipedia.org/wiki/Fisher-Yates_shuffle.
+ *
+ * @static
+ * @memberOf _
+ * @category Collections
+ * @param {Array|Object|String} collection The collection to shuffle.
+ * @returns {Array} Returns a new shuffled collection.
+ * @example
+ *
+ * _.shuffle([1, 2, 3, 4, 5, 6]);
+ * // => [4, 1, 6, 3, 5, 2]
+ */
+ function shuffle(collection) {
+ var index = -1,
+ result = Array(collection ? collection.length : 0);
+
+ forEach(collection, function(value) {
+ var rand = floor(nativeRandom() * (++index + 1));
+ result[index] = result[rand];
+ result[rand] = value;
+ });
+ return result;
+ }
+
+ /**
+ * Gets the size of the `collection` by returning `collection.length` for arrays
+ * and array-like objects or the number of own enumerable properties for objects.
+ *
+ * @static
+ * @memberOf _
+ * @category Collections
+ * @param {Array|Object|String} collection The collection to inspect.
+ * @returns {Number} Returns `collection.length` or number of own enumerable properties.
+ * @example
+ *
+ * _.size([1, 2]);
+ * // => 2
+ *
+ * _.size({ 'one': 1, 'two': 2, 'three': 3 });
+ * // => 3
+ *
+ * _.size('curly');
+ * // => 5
+ */
+ function size(collection) {
+ var length = collection ? collection.length : 0;
+ return typeof length == 'number' ? length : keys(collection).length;
+ }
+
+ /**
+ * Checks if the `callback` returns a truthy value for **any** element of a
+ * `collection`. The function returns as soon as it finds passing value, and
+ * does not iterate over the entire `collection`. The `callback` is bound to
+ * `thisArg` and invoked with three arguments; (value, index|key, collection).
+ *
+ * @static
+ * @memberOf _
+ * @alias any
+ * @category Collections
+ * @param {Array|Object|String} collection The collection to iterate over.
+ * @param {Function} [callback=identity] The function called per iteration.
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
+ * @returns {Boolean} Returns `true` if any element passes the callback check,
+ * else `false`.
+ * @example
+ *
+ * _.some([null, 0, 'yes', false], Boolean);
+ * // => true
+ */
+ function some(collection, callback, thisArg) {
+ var result;
+ callback = createCallback(callback, thisArg);
+
+ if (isArray(collection)) {
+ var index = -1,
+ length = collection.length;
+
+ while (++index < length) {
+ if ((result = callback(collection[index], index, collection))) {
+ break;
+ }
+ }
+ } else {
+ forEach(collection, function(value, index, collection) {
+ return !(result = callback(value, index, collection));
+ });
+ }
+ return !!result;
+ }
+
+ /**
+ * Creates an array, stable sorted in ascending order by the results of
+ * running each element of `collection` through a `callback`. The `callback`
+ * is bound to `thisArg` and invoked with three arguments; (value, index|key, collection).
+ * The `callback` argument may also be the name of a property to sort by (e.g. 'length').
+ *
+ * @static
+ * @memberOf _
+ * @category Collections
+ * @param {Array|Object|String} collection The collection to iterate over.
+ * @param {Function|String} callback|property The function called per iteration
+ * or property name to sort by.
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
+ * @returns {Array} Returns a new array of sorted elements.
+ * @example
+ *
+ * _.sortBy([1, 2, 3], function(num) { return Math.sin(num); });
+ * // => [3, 1, 2]
+ *
+ * _.sortBy([1, 2, 3], function(num) { return this.sin(num); }, Math);
+ * // => [3, 1, 2]
+ *
+ * _.sortBy(['larry', 'brendan', 'moe'], 'length');
+ * // => ['moe', 'larry', 'brendan']
+ */
+ function sortBy(collection, callback, thisArg) {
+ var result = [];
+ callback = createCallback(callback, thisArg);
+ forEach(collection, function(value, index, collection) {
+ result.push({
+ 'criteria': callback(value, index, collection),
+ 'index': index,
+ 'value': value
+ });
+ });
+
+ var length = result.length;
+ result.sort(compareAscending);
+ while (length--) {
+ result[length] = result[length].value;
+ }
+ return result;
+ }
+
+ /**
+ * Converts the `collection`, to an array.
+ *
+ * @static
+ * @memberOf _
+ * @category Collections
+ * @param {Array|Object|String} collection The collection to convert.
+ * @returns {Array} Returns the new converted array.
+ * @example
+ *
+ * (function() { return _.toArray(arguments).slice(1); })(1, 2, 3, 4);
+ * // => [2, 3, 4]
+ */
+ function toArray(collection) {
+ if (collection && typeof collection.length == 'number') {
+ return (noArraySliceOnStrings ? isString(collection) : typeof collection == 'string')
+ ? collection.split('')
+ : slice.call(collection);
+ }
+ return values(collection);
+ }
+
+ /**
+ * Examines each element in a `collection`, returning an array of all elements
+ * that contain the given `properties`.
+ *
+ * @static
+ * @memberOf _
+ * @category Collections
+ * @param {Array|Object|String} collection The collection to iterate over.
+ * @param {Object} properties The object of property values to filter by.
+ * @returns {Array} Returns a new array of elements that contain the given `properties`.
+ * @example
+ *
+ * var stooges = [
+ * { 'name': 'moe', 'age': 40 },
+ * { 'name': 'larry', 'age': 50 },
+ * { 'name': 'curly', 'age': 60 }
+ * ];
+ *
+ * _.where(stooges, { 'age': 40 });
+ * // => [{ 'name': 'moe', 'age': 40 }]
+ */
+ function where(collection, properties) {
+ var props = keys(properties);
+ return filter(collection, function(object) {
+ var length = props.length;
+ while (length--) {
+ var result = object[props[length]] === properties[props[length]];
+ if (!result) {
+ break;
+ }
+ }
+ return !!result;
+ });
+ }
+
+ /*--------------------------------------------------------------------------*/
+
+ /**
+ * Creates an array with all falsey values of `array` removed. The values
+ * `false`, `null`, `0`, `""`, `undefined` and `NaN` are all falsey.
+ *
+ * @static
+ * @memberOf _
+ * @category Arrays
+ * @param {Array} array The array to compact.
+ * @returns {Array} Returns a new filtered array.
+ * @example
+ *
+ * _.compact([0, 1, false, 2, '', 3]);
+ * // => [1, 2, 3]
+ */
+ function compact(array) {
+ var index = -1,
+ length = array ? array.length : 0,
+ result = [];
+
+ while (++index < length) {
+ var value = array[index];
+ if (value) {
+ result.push(value);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Creates an array of `array` elements not present in the other arrays
+ * using strict equality for comparisons, i.e. `===`.
+ *
+ * @static
+ * @memberOf _
+ * @category Arrays
+ * @param {Array} array The array to process.
+ * @param {Array} [array1, array2, ...] Arrays to check.
+ * @returns {Array} Returns a new array of `array` elements not present in the
+ * other arrays.
+ * @example
+ *
+ * _.difference([1, 2, 3, 4, 5], [5, 2, 10]);
+ * // => [1, 3, 4]
+ */
+ function difference(array) {
+ var index = -1,
+ length = array ? array.length : 0,
+ flattened = concat.apply(arrayRef, arguments),
+ contains = cachedContains(flattened, length),
+ result = [];
+
+ while (++index < length) {
+ var value = array[index];
+ if (!contains(value)) {
+ result.push(value);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Gets the first element of the `array`. Pass `n` to return the first `n`
+ * elements of the `array`.
+ *
+ * @static
+ * @memberOf _
+ * @alias head, take
+ * @category Arrays
+ * @param {Array} array The array to query.
+ * @param {Number} [n] The number of elements to return.
+ * @param- {Object} [guard] Internally used to allow this method to work with
+ * others like `_.map` without using their callback `index` argument for `n`.
+ * @returns {Mixed} Returns the first element or an array of the first `n`
+ * elements of `array`.
+ * @example
+ *
+ * _.first([5, 4, 3, 2, 1]);
+ * // => 5
+ */
+ function first(array, n, guard) {
+ if (array) {
+ return (n == null || guard) ? array[0] : slice.call(array, 0, n);
+ }
+ }
+
+ /**
+ * Flattens a nested array (the nesting can be to any depth). If `shallow` is
+ * truthy, `array` will only be flattened a single level.
+ *
+ * @static
+ * @memberOf _
+ * @category Arrays
+ * @param {Array} array The array to compact.
+ * @param {Boolean} shallow A flag to indicate only flattening a single level.
+ * @returns {Array} Returns a new flattened array.
+ * @example
+ *
+ * _.flatten([1, [2], [3, [[4]]]]);
+ * // => [1, 2, 3, 4];
+ *
+ * _.flatten([1, [2], [3, [[4]]]], true);
+ * // => [1, 2, 3, [[4]]];
+ */
+ function flatten(array, shallow) {
+ var index = -1,
+ length = array ? array.length : 0,
+ result = [];
+
+ while (++index < length) {
+ var value = array[index];
+
+ // recursively flatten arrays (susceptible to call stack limits)
+ if (isArray(value)) {
+ push.apply(result, shallow ? value : flatten(value));
+ } else {
+ result.push(value);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Gets the index at which the first occurrence of `value` is found using
+ * strict equality for comparisons, i.e. `===`. If the `array` is already
+ * sorted, passing `true` for `fromIndex` will run a faster binary search.
+ *
+ * @static
+ * @memberOf _
+ * @category Arrays
+ * @param {Array} array The array to search.
+ * @param {Mixed} value The value to search for.
+ * @param {Boolean|Number} [fromIndex=0] The index to search from or `true` to
+ * perform a binary search on a sorted `array`.
+ * @returns {Number} Returns the index of the matched value or `-1`.
+ * @example
+ *
+ * _.indexOf([1, 2, 3, 1, 2, 3], 2);
+ * // => 1
+ *
+ * _.indexOf([1, 2, 3, 1, 2, 3], 2, 3);
+ * // => 4
+ *
+ * _.indexOf([1, 1, 2, 2, 3, 3], 2, true);
+ * // => 2
+ */
+ function indexOf(array, value, fromIndex) {
+ var index = -1,
+ length = array ? array.length : 0;
+
+ if (typeof fromIndex == 'number') {
+ index = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex || 0) - 1;
+ } else if (fromIndex) {
+ index = sortedIndex(array, value);
+ return array[index] === value ? index : -1;
+ }
+ while (++index < length) {
+ if (array[index] === value) {
+ return index;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Gets all but the last element of `array`. Pass `n` to exclude the last `n`
+ * elements from the result.
+ *
+ * @static
+ * @memberOf _
+ * @category Arrays
+ * @param {Array} array The array to query.
+ * @param {Number} [n=1] The number of elements to exclude.
+ * @param- {Object} [guard] Internally used to allow this method to work with
+ * others like `_.map` without using their callback `index` argument for `n`.
+ * @returns {Array} Returns all but the last element or `n` elements of `array`.
+ * @example
+ *
+ * _.initial([3, 2, 1]);
+ * // => [3, 2]
+ */
+ function initial(array, n, guard) {
+ return array
+ ? slice.call(array, 0, -((n == null || guard) ? 1 : n))
+ : [];
+ }
+
+ /**
+ * Computes the intersection of all the passed-in arrays using strict equality
+ * for comparisons, i.e. `===`.
+ *
+ * @static
+ * @memberOf _
+ * @category Arrays
+ * @param {Array} [array1, array2, ...] Arrays to process.
+ * @returns {Array} Returns a new array of unique elements, in order, that are
+ * present in **all** of the arrays.
+ * @example
+ *
+ * _.intersection([1, 2, 3], [101, 2, 1, 10], [2, 1]);
+ * // => [1, 2]
+ */
+ function intersection(array) {
+ var args = arguments,
+ argsLength = args.length,
+ cache = {},
+ result = [];
+
+ forEach(array, function(value) {
+ if (indexOf(result, value) < 0) {
+ var length = argsLength;
+ while (--length) {
+ if (!(cache[length] || (cache[length] = cachedContains(args[length])))(value)) {
+ return;
+ }
+ }
+ result.push(value);
+ }
+ });
+ return result;
+ }
+
+ /**
+ * Gets the last element of the `array`. Pass `n` to return the last `n`
+ * elements of the `array`.
+ *
+ * @static
+ * @memberOf _
+ * @category Arrays
+ * @param {Array} array The array to query.
+ * @param {Number} [n] The number of elements to return.
+ * @param- {Object} [guard] Internally used to allow this method to work with
+ * others like `_.map` without using their callback `index` argument for `n`.
+ * @returns {Mixed} Returns the last element or an array of the last `n`
+ * elements of `array`.
+ * @example
+ *
+ * _.last([3, 2, 1]);
+ * // => 1
+ */
+ function last(array, n, guard) {
+ if (array) {
+ var length = array.length;
+ return (n == null || guard) ? array[length - 1] : slice.call(array, -n || length);
+ }
+ }
+
+ /**
+ * Gets the index at which the last occurrence of `value` is found using strict
+ * equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used
+ * as the offset from the end of the collection.
+ *
+ * @static
+ * @memberOf _
+ * @category Arrays
+ * @param {Array} array The array to search.
+ * @param {Mixed} value The value to search for.
+ * @param {Number} [fromIndex=array.length-1] The index to search from.
+ * @returns {Number} Returns the index of the matched value or `-1`.
+ * @example
+ *
+ * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2);
+ * // => 4
+ *
+ * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2, 3);
+ * // => 1
+ */
+ function lastIndexOf(array, value, fromIndex) {
+ var index = array ? array.length : 0;
+ if (typeof fromIndex == 'number') {
+ index = (fromIndex < 0 ? nativeMax(0, index + fromIndex) : nativeMin(fromIndex, index - 1)) + 1;
+ }
+ while (index--) {
+ if (array[index] === value) {
+ return index;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Creates an object composed from arrays of `keys` and `values`. Pass either
+ * a single two dimensional array, i.e. `[[key1, value1], [key2, value2]]`, or
+ * two arrays, one of `keys` and one of corresponding `values`.
+ *
+ * @static
+ * @memberOf _
+ * @category Arrays
+ * @param {Array} keys The array of keys.
+ * @param {Array} [values=[]] The array of values.
+ * @returns {Object} Returns an object composed of the given keys and
+ * corresponding values.
+ * @example
+ *
+ * _.object(['moe', 'larry', 'curly'], [30, 40, 50]);
+ * // => { 'moe': 30, 'larry': 40, 'curly': 50 }
+ */
+ function object(keys, values) {
+ var index = -1,
+ length = keys ? keys.length : 0,
+ result = {};
+
+ while (++index < length) {
+ var key = keys[index];
+ if (values) {
+ result[key] = values[index];
+ } else {
+ result[key[0]] = key[1];
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Creates an array of numbers (positive and/or negative) progressing from
+ * `start` up to but not including `stop`. This method is a port of Python's
+ * `range()` function. See http://docs.python.org/library/functions.html#range.
+ *
+ * @static
+ * @memberOf _
+ * @category Arrays
+ * @param {Number} [start=0] The start of the range.
+ * @param {Number} end The end of the range.
+ * @param {Number} [step=1] The value to increment or descrement by.
+ * @returns {Array} Returns a new range array.
+ * @example
+ *
+ * _.range(10);
+ * // => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+ *
+ * _.range(1, 11);
+ * // => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
+ *
+ * _.range(0, 30, 5);
+ * // => [0, 5, 10, 15, 20, 25]
+ *
+ * _.range(0, -10, -1);
+ * // => [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
+ *
+ * _.range(0);
+ * // => []
+ */
+ function range(start, end, step) {
+ start = +start || 0;
+ step = +step || 1;
+
+ if (end == null) {
+ end = start;
+ start = 0;
+ }
+ // use `Array(length)` so V8 will avoid the slower "dictionary" mode
+ // http://www.youtube.com/watch?v=XAqIpGU8ZZk#t=16m27s
+ var index = -1,
+ length = nativeMax(0, ceil((end - start) / step)),
+ result = Array(length);
+
+ while (++index < length) {
+ result[index] = start;
+ start += step;
+ }
+ return result;
+ }
+
+ /**
+ * The opposite of `_.initial`, this method gets all but the first value of
+ * `array`. Pass `n` to exclude the first `n` values from the result.
+ *
+ * @static
+ * @memberOf _
+ * @alias drop, tail
+ * @category Arrays
+ * @param {Array} array The array to query.
+ * @param {Number} [n=1] The number of elements to exclude.
+ * @param- {Object} [guard] Internally used to allow this method to work with
+ * others like `_.map` without using their callback `index` argument for `n`.
+ * @returns {Array} Returns all but the first value or `n` values of `array`.
+ * @example
+ *
+ * _.rest([3, 2, 1]);
+ * // => [2, 1]
+ */
+ function rest(array, n, guard) {
+ return array
+ ? slice.call(array, (n == null || guard) ? 1 : n)
+ : [];
+ }
+
+ /**
+ * Uses a binary search to determine the smallest index at which the `value`
+ * should be inserted into `array` in order to maintain the sort order of the
+ * sorted `array`. If `callback` is passed, it will be executed for `value` and
+ * each element in `array` to compute their sort ranking. The `callback` is
+ * bound to `thisArg` and invoked with one argument; (value). The `callback`
+ * argument may also be the name of a property to order by.
+ *
+ * @static
+ * @memberOf _
+ * @category Arrays
+ * @param {Array} array The array to iterate over.
+ * @param {Mixed} value The value to evaluate.
+ * @param {Function|String} [callback=identity|property] The function called
+ * per iteration or property name to order by.
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
+ * @returns {Number} Returns the index at which the value should be inserted
+ * into `array`.
+ * @example
+ *
+ * _.sortedIndex([20, 30, 50], 40);
+ * // => 2
+ *
+ * _.sortedIndex([{ 'x': 20 }, { 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x');
+ * // => 2
+ *
+ * var dict = {
+ * 'wordToNumber': { 'twenty': 20, 'thirty': 30, 'fourty': 40, 'fifty': 50 }
+ * };
+ *
+ * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) {
+ * return dict.wordToNumber[word];
+ * });
+ * // => 2
+ *
+ * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) {
+ * return this.wordToNumber[word];
+ * }, dict);
+ * // => 2
+ */
+ function sortedIndex(array, value, callback, thisArg) {
+ var low = 0,
+ high = array ? array.length : low;
+
+ // explicitly reference `identity` for better engine inlining
+ callback = callback ? createCallback(callback, thisArg) : identity;
+ value = callback(value);
+ while (low < high) {
+ var mid = (low + high) >>> 1;
+ callback(array[mid]) < value
+ ? low = mid + 1
+ : high = mid;
+ }
+ return low;
+ }
+
+ /**
+ * Computes the union of the passed-in arrays using strict equality for
+ * comparisons, i.e. `===`.
+ *
+ * @static
+ * @memberOf _
+ * @category Arrays
+ * @param {Array} [array1, array2, ...] Arrays to process.
+ * @returns {Array} Returns a new array of unique values, in order, that are
+ * present in one or more of the arrays.
+ * @example
+ *
+ * _.union([1, 2, 3], [101, 2, 1, 10], [2, 1]);
+ * // => [1, 2, 3, 101, 10]
+ */
+ function union() {
+ return uniq(concat.apply(arrayRef, arguments));
+ }
+
+ /**
+ * Creates a duplicate-value-free version of the `array` using strict equality
+ * for comparisons, i.e. `===`. If the `array` is already sorted, passing `true`
+ * for `isSorted` will run a faster algorithm. If `callback` is passed, each
+ * element of `array` is passed through a callback` before uniqueness is computed.
+ * The `callback` is bound to `thisArg` and invoked with three arguments; (value, index, array).
+ *
+ * @static
+ * @memberOf _
+ * @alias unique
+ * @category Arrays
+ * @param {Array} array The array to process.
+ * @param {Boolean} [isSorted=false] A flag to indicate that the `array` is already sorted.
+ * @param {Function} [callback=identity] The function called per iteration.
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
+ * @returns {Array} Returns a duplicate-value-free array.
+ * @example
+ *
+ * _.uniq([1, 2, 1, 3, 1]);
+ * // => [1, 2, 3]
+ *
+ * _.uniq([1, 1, 2, 2, 3], true);
+ * // => [1, 2, 3]
+ *
+ * _.uniq([1, 2, 1.5, 3, 2.5], function(num) { return Math.floor(num); });
+ * // => [1, 2, 3]
+ *
+ * _.uniq([1, 2, 1.5, 3, 2.5], function(num) { return this.floor(num); }, Math);
+ * // => [1, 2, 3]
+ */
+ function uniq(array, isSorted, callback, thisArg) {
+ var index = -1,
+ length = array ? array.length : 0,
+ result = [],
+ seen = result;
+
+ // juggle arguments
+ if (typeof isSorted == 'function') {
+ thisArg = callback;
+ callback = isSorted;
+ isSorted = false;
+ }
+ // init value cache for large arrays
+ var isLarge = !isSorted && length > 74;
+ if (isLarge) {
+ var cache = {};
+ }
+ if (callback) {
+ seen = [];
+ callback = createCallback(callback, thisArg);
+ }
+ while (++index < length) {
+ var value = array[index],
+ computed = callback ? callback(value, index, array) : value;
+
+ if (isLarge) {
+ // manually coerce `computed` to a string because `hasOwnProperty`, in
+ // some older versions of Firefox, coerces objects incorrectly
+ seen = hasOwnProperty.call(cache, computed + '') ? cache[computed] : (cache[computed] = []);
+ }
+ if (isSorted
+ ? !index || seen[seen.length - 1] !== computed
+ : indexOf(seen, computed) < 0
+ ) {
+ if (callback || isLarge) {
+ seen.push(computed);
+ }
+ result.push(value);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Creates an array with all occurrences of the passed values removed using
+ * strict equality for comparisons, i.e. `===`.
+ *
+ * @static
+ * @memberOf _
+ * @category Arrays
+ * @param {Array} array The array to filter.
+ * @param {Mixed} [value1, value2, ...] Values to remove.
+ * @returns {Array} Returns a new filtered array.
+ * @example
+ *
+ * _.without([1, 2, 1, 0, 3, 1, 4], 0, 1);
+ * // => [2, 3, 4]
+ */
+ function without(array) {
+ var index = -1,
+ length = array ? array.length : 0,
+ contains = cachedContains(arguments, 1, 20),
+ result = [];
+
+ while (++index < length) {
+ var value = array[index];
+ if (!contains(value)) {
+ result.push(value);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Groups the elements of each array at their corresponding indexes. Useful for
+ * separate data sources that are coordinated through matching array indexes.
+ * For a matrix of nested arrays, `_.zip.apply(...)` can transpose the matrix
+ * in a similar fashion.
+ *
+ * @static
+ * @memberOf _
+ * @category Arrays
+ * @param {Array} [array1, array2, ...] Arrays to process.
+ * @returns {Array} Returns a new array of grouped elements.
+ * @example
+ *
+ * _.zip(['moe', 'larry', 'curly'], [30, 40, 50], [true, false, false]);
+ * // => [['moe', 30, true], ['larry', 40, false], ['curly', 50, false]]
+ */
+ function zip(array) {
+ var index = -1,
+ length = array ? max(pluck(arguments, 'length')) : 0,
+ result = Array(length);
+
+ while (++index < length) {
+ result[index] = pluck(arguments, index);
+ }
+ return result;
+ }
+
+ /*--------------------------------------------------------------------------*/
+
+ /**
+ * Creates a function that is restricted to executing `func` only after it is
+ * called `n` times. The `func` is executed with the `this` binding of the
+ * created function.
+ *
+ * @static
+ * @memberOf _
+ * @category Functions
+ * @param {Number} n The number of times the function must be called before
+ * it is executed.
+ * @param {Function} func The function to restrict.
+ * @returns {Function} Returns the new restricted function.
+ * @example
+ *
+ * var renderNotes = _.after(notes.length, render);
+ * _.forEach(notes, function(note) {
+ * note.asyncSave({ 'success': renderNotes });
+ * });
+ * // `renderNotes` is run once, after all notes have saved
+ */
+ function after(n, func) {
+ if (n < 1) {
+ return func();
+ }
+ return function() {
+ if (--n < 1) {
+ return func.apply(this, arguments);
+ }
+ };
+ }
+
+ /**
+ * Creates a function that, when called, invokes `func` with the `this`
+ * binding of `thisArg` and prepends any additional `bind` arguments to those
+ * passed to the bound function.
+ *
+ * @static
+ * @memberOf _
+ * @category Functions
+ * @param {Function} func The function to bind.
+ * @param {Mixed} [thisArg] The `this` binding of `func`.
+ * @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied.
+ * @returns {Function} Returns the new bound function.
+ * @example
+ *
+ * var func = function(greeting) {
+ * return greeting + ' ' + this.name;
+ * };
+ *
+ * func = _.bind(func, { 'name': 'moe' }, 'hi');
+ * func();
+ * // => 'hi moe'
+ */
+ function bind(func, thisArg) {
+ // use `Function#bind` if it exists and is fast
+ // (in V8 `Function#bind` is slower except when partially applied)
+ return isBindFast || (nativeBind && arguments.length > 2)
+ ? nativeBind.call.apply(nativeBind, arguments)
+ : createBound(func, thisArg, slice.call(arguments, 2));
+ }
+
+ /**
+ * Binds methods on `object` to `object`, overwriting the existing method.
+ * If no method names are provided, all the function properties of `object`
+ * will be bound.
+ *
+ * @static
+ * @memberOf _
+ * @category Functions
+ * @param {Object} object The object to bind and assign the bound methods to.
+ * @param {String} [methodName1, methodName2, ...] Method names on the object to bind.
+ * @returns {Object} Returns `object`.
+ * @example
+ *
+ * var buttonView = {
+ * 'label': 'lodash',
+ * 'onClick': function() { alert('clicked: ' + this.label); }
+ * };
+ *
+ * _.bindAll(buttonView);
+ * jQuery('#lodash_button').on('click', buttonView.onClick);
+ * // => When the button is clicked, `this.label` will have the correct value
+ */
+ function bindAll(object) {
+ var funcs = arguments,
+ index = funcs.length > 1 ? 0 : (funcs = functions(object), -1),
+ length = funcs.length;
+
+ while (++index < length) {
+ var key = funcs[index];
+ object[key] = bind(object[key], object);
+ }
+ return object;
+ }
+
+ /**
+ * Creates a function that, when called, invokes the method at `object[key]`
+ * and prepends any additional `bindKey` arguments to those passed to the bound
+ * function. This method differs from `_.bind` by allowing bound functions to
+ * reference methods that will be redefined or don't yet exist.
+ * See http://michaux.ca/articles/lazy-function-definition-pattern.
+ *
+ * @static
+ * @memberOf _
+ * @category Functions
+ * @param {Object} object The object the method belongs to.
+ * @param {String} key The key of the method.
+ * @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied.
+ * @returns {Function} Returns the new bound function.
+ * @example
+ *
+ * var object = {
+ * 'name': 'moe',
+ * 'greet': function(greeting) {
+ * return greeting + ' ' + this.name;
+ * }
+ * };
+ *
+ * var func = _.bindKey(object, 'greet', 'hi');
+ * func();
+ * // => 'hi moe'
+ *
+ * object.greet = function(greeting) {
+ * return greeting + ', ' + this.name + '!';
+ * };
+ *
+ * func();
+ * // => 'hi, moe!'
+ */
+ function bindKey(object, key) {
+ return createBound(object, key, slice.call(arguments, 2));
+ }
+
+ /**
+ * Creates a function that is the composition of the passed functions,
+ * where each function consumes the return value of the function that follows.
+ * In math terms, composing the functions `f()`, `g()`, and `h()` produces `f(g(h()))`.
+ * Each function is executed with the `this` binding of the composed function.
+ *
+ * @static
+ * @memberOf _
+ * @category Functions
+ * @param {Function} [func1, func2, ...] Functions to compose.
+ * @returns {Function} Returns the new composed function.
+ * @example
+ *
+ * var greet = function(name) { return 'hi: ' + name; };
+ * var exclaim = function(statement) { return statement + '!'; };
+ * var welcome = _.compose(exclaim, greet);
+ * welcome('moe');
+ * // => 'hi: moe!'
+ */
+ function compose() {
+ var funcs = arguments;
+ return function() {
+ var args = arguments,
+ length = funcs.length;
+
+ while (length--) {
+ args = [funcs[length].apply(this, args)];
+ }
+ return args[0];
+ };
+ }
+
+ /**
+ * Creates a function that will delay the execution of `func` until after
+ * `wait` milliseconds have elapsed since the last time it was invoked. Pass
+ * `true` for `immediate` to cause debounce to invoke `func` on the leading,
+ * instead of the trailing, edge of the `wait` timeout. Subsequent calls to
+ * the debounced function will return the result of the last `func` call.
+ *
+ * @static
+ * @memberOf _
+ * @category Functions
+ * @param {Function} func The function to debounce.
+ * @param {Number} wait The number of milliseconds to delay.
+ * @param {Boolean} immediate A flag to indicate execution is on the leading
+ * edge of the timeout.
+ * @returns {Function} Returns the new debounced function.
+ * @example
+ *
+ * var lazyLayout = _.debounce(calculateLayout, 300);
+ * jQuery(window).on('resize', lazyLayout);
+ */
+ function debounce(func, wait, immediate) {
+ var args,
+ result,
+ thisArg,
+ timeoutId;
+
+ function delayed() {
+ timeoutId = null;
+ if (!immediate) {
+ result = func.apply(thisArg, args);
+ }
+ }
+ return function() {
+ var isImmediate = immediate && !timeoutId;
+ args = arguments;
+ thisArg = this;
+
+ clearTimeout(timeoutId);
+ timeoutId = setTimeout(delayed, wait);
+
+ if (isImmediate) {
+ result = func.apply(thisArg, args);
+ }
+ return result;
+ };
+ }
+
+ /**
+ * Executes the `func` function after `wait` milliseconds. Additional arguments
+ * will be passed to `func` when it is invoked.
+ *
+ * @static
+ * @memberOf _
+ * @category Functions
+ * @param {Function} func The function to delay.
+ * @param {Number} wait The number of milliseconds to delay execution.
+ * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the function with.
+ * @returns {Number} Returns the `setTimeout` timeout id.
+ * @example
+ *
+ * var log = _.bind(console.log, console);
+ * _.delay(log, 1000, 'logged later');
+ * // => 'logged later' (Appears after one second.)
+ */
+ function delay(func, wait) {
+ var args = slice.call(arguments, 2);
+ return setTimeout(function() { func.apply(undefined, args); }, wait);
+ }
+
+ /**
+ * Defers executing the `func` function until the current call stack has cleared.
+ * Additional arguments will be passed to `func` when it is invoked.
+ *
+ * @static
+ * @memberOf _
+ * @category Functions
+ * @param {Function} func The function to defer.
+ * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the function with.
+ * @returns {Number} Returns the `setTimeout` timeout id.
+ * @example
+ *
+ * _.defer(function() { alert('deferred'); });
+ * // returns from the function before `alert` is called
+ */
+ function defer(func) {
+ var args = slice.call(arguments, 1);
+ return setTimeout(function() { func.apply(undefined, args); }, 1);
+ }
+
+ /**
+ * Creates a function that memoizes the result of `func`. If `resolver` is
+ * passed, it will be used to determine the cache key for storing the result
+ * based on the arguments passed to the memoized function. By default, the first
+ * argument passed to the memoized function is used as the cache key. The `func`
+ * is executed with the `this` binding of the memoized function.
+ *
+ * @static
+ * @memberOf _
+ * @category Functions
+ * @param {Function} func The function to have its output memoized.
+ * @param {Function} [resolver] A function used to resolve the cache key.
+ * @returns {Function} Returns the new memoizing function.
+ * @example
+ *
+ * var fibonacci = _.memoize(function(n) {
+ * return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
+ * });
+ */
+ function memoize(func, resolver) {
+ var cache = {};
+ return function() {
+ var key = resolver ? resolver.apply(this, arguments) : arguments[0];
+ return hasOwnProperty.call(cache, key)
+ ? cache[key]
+ : (cache[key] = func.apply(this, arguments));
+ };
+ }
+
+ /**
+ * Creates a function that is restricted to execute `func` once. Repeat calls to
+ * the function will return the value of the first call. The `func` is executed
+ * with the `this` binding of the created function.
+ *
+ * @static
+ * @memberOf _
+ * @category Functions
+ * @param {Function} func The function to restrict.
+ * @returns {Function} Returns the new restricted function.
+ * @example
+ *
+ * var initialize = _.once(createApplication);
+ * initialize();
+ * initialize();
+ * // Application is only created once.
+ */
+ function once(func) {
+ var result,
+ ran = false;
+
+ return function() {
+ if (ran) {
+ return result;
+ }
+ ran = true;
+ result = func.apply(this, arguments);
+
+ // clear the `func` variable so the function may be garbage collected
+ func = null;
+ return result;
+ };
+ }
+
+ /**
+ * Creates a function that, when called, invokes `func` with any additional
+ * `partial` arguments prepended to those passed to the new function. This
+ * method is similar to `bind`, except it does **not** alter the `this` binding.
+ *
+ * @static
+ * @memberOf _
+ * @category Functions
+ * @param {Function} func The function to partially apply arguments to.
+ * @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied.
+ * @returns {Function} Returns the new partially applied function.
+ * @example
+ *
+ * var greet = function(greeting, name) { return greeting + ': ' + name; };
+ * var hi = _.partial(greet, 'hi');
+ * hi('moe');
+ * // => 'hi: moe'
+ */
+ function partial(func) {
+ return createBound(func, slice.call(arguments, 1));
+ }
+
+ /**
+ * Creates a function that, when executed, will only call the `func`
+ * function at most once per every `wait` milliseconds. If the throttled
+ * function is invoked more than once during the `wait` timeout, `func` will
+ * also be called on the trailing edge of the timeout. Subsequent calls to the
+ * throttled function will return the result of the last `func` call.
+ *
+ * @static
+ * @memberOf _
+ * @category Functions
+ * @param {Function} func The function to throttle.
+ * @param {Number} wait The number of milliseconds to throttle executions to.
+ * @returns {Function} Returns the new throttled function.
+ * @example
+ *
+ * var throttled = _.throttle(updatePosition, 100);
+ * jQuery(window).on('scroll', throttled);
+ */
+ function throttle(func, wait) {
+ var args,
+ result,
+ thisArg,
+ timeoutId,
+ lastCalled = 0;
+
+ function trailingCall() {
+ lastCalled = new Date;
+ timeoutId = null;
+ result = func.apply(thisArg, args);
+ }
+ return function() {
+ var now = new Date,
+ remaining = wait - (now - lastCalled);
+
+ args = arguments;
+ thisArg = this;
+
+ if (remaining <= 0) {
+ clearTimeout(timeoutId);
+ lastCalled = now;
+ result = func.apply(thisArg, args);
+ }
+ else if (!timeoutId) {
+ timeoutId = setTimeout(trailingCall, remaining);
+ }
+ return result;
+ };
+ }
+
+ /**
+ * Creates a function that passes `value` to the `wrapper` function as its
+ * first argument. Additional arguments passed to the function are appended
+ * to those passed to the `wrapper` function. The `wrapper` is executed with
+ * the `this` binding of the created function.
+ *
+ * @static
+ * @memberOf _
+ * @category Functions
+ * @param {Mixed} value The value to wrap.
+ * @param {Function} wrapper The wrapper function.
+ * @returns {Function} Returns the new function.
+ * @example
+ *
+ * var hello = function(name) { return 'hello ' + name; };
+ * hello = _.wrap(hello, function(func) {
+ * return 'before, ' + func('moe') + ', after';
+ * });
+ * hello();
+ * // => 'before, hello moe, after'
+ */
+ function wrap(value, wrapper) {
+ return function() {
+ var args = [value];
+ push.apply(args, arguments);
+ return wrapper.apply(this, args);
+ };
+ }
+
+ /*--------------------------------------------------------------------------*/
+
+ /**
+ * Converts the characters `&`, `<`, `>`, `"`, and `'` in `string` to their
+ * corresponding HTML entities.
+ *
+ * @static
+ * @memberOf _
+ * @category Utilities
+ * @param {String} string The string to escape.
+ * @returns {String} Returns the escaped string.
+ * @example
+ *
+ * _.escape('Moe, Larry & Curly');
+ * // => "Moe, Larry &amp; Curly"
+ */
+ function escape(string) {
+ return string == null ? '' : (string + '').replace(reUnescapedHtml, escapeHtmlChar);
+ }
+
+ /**
+ * This function returns the first argument passed to it.
+ *
+ * Note: It is used throughout Lo-Dash as a default callback.
+ *
+ * @static
+ * @memberOf _
+ * @category Utilities
+ * @param {Mixed} value Any value.
+ * @returns {Mixed} Returns `value`.
+ * @example
+ *
+ * var moe = { 'name': 'moe' };
+ * moe === _.identity(moe);
+ * // => true
+ */
+ function identity(value) {
+ return value;
+ }
+
+ /**
+ * Adds functions properties of `object` to the `lodash` function and chainable
+ * wrapper.
+ *
+ * @static
+ * @memberOf _
+ * @category Utilities
+ * @param {Object} object The object of function properties to add to `lodash`.
+ * @example
+ *
+ * _.mixin({
+ * 'capitalize': function(string) {
+ * return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase();
+ * }
+ * });
+ *
+ * _.capitalize('larry');
+ * // => 'Larry'
+ *
+ * _('curly').capitalize();
+ * // => 'Curly'
+ */
+ function mixin(object) {
+ forEach(functions(object), function(methodName) {
+ var func = lodash[methodName] = object[methodName];
+
+ lodash.prototype[methodName] = function() {
+ var args = [this.__wrapped__];
+ push.apply(args, arguments);
+
+ var result = func.apply(lodash, args);
+ if (this.__chain__) {
+ result = new lodash(result);
+ result.__chain__ = true;
+ }
+ return result;
+ };
+ });
+ }
+
+ /**
+ * Reverts the '_' variable to its previous value and returns a reference to
+ * the `lodash` function.
+ *
+ * @static
+ * @memberOf _
+ * @category Utilities
+ * @returns {Function} Returns the `lodash` function.
+ * @example
+ *
+ * var lodash = _.noConflict();
+ */
+ function noConflict() {
+ window._ = oldDash;
+ return this;
+ }
+
+ /**
+ * Produces a random number between `min` and `max` (inclusive). If only one
+ * argument is passed, a number between `0` and the given number will be returned.
+ *
+ * @static
+ * @memberOf _
+ * @category Utilities
+ * @param {Number} [min=0] The minimum possible value.
+ * @param {Number} [max=1] The maximum possible value.
+ * @returns {Number} Returns a random number.
+ * @example
+ *
+ * _.random(0, 5);
+ * // => a number between 1 and 5
+ *
+ * _.random(5);
+ * // => also a number between 1 and 5
+ */
+ function random(min, max) {
+ if (min == null && max == null) {
+ max = 1;
+ }
+ min = +min || 0;
+ if (max == null) {
+ max = min;
+ min = 0;
+ }
+ return min + floor(nativeRandom() * ((+max || 0) - min + 1));
+ }
+
+ /**
+ * Resolves the value of `property` on `object`. If `property` is a function
+ * it will be invoked and its result returned, else the property value is
+ * returned. If `object` is falsey, then `null` is returned.
+ *
+ * @deprecated
+ * @static
+ * @memberOf _
+ * @category Utilities
+ * @param {Object} object The object to inspect.
+ * @param {String} property The property to get the value of.
+ * @returns {Mixed} Returns the resolved value.
+ * @example
+ *
+ * var object = {
+ * 'cheese': 'crumpets',
+ * 'stuff': function() {
+ * return 'nonsense';
+ * }
+ * };
+ *
+ * _.result(object, 'cheese');
+ * // => 'crumpets'
+ *
+ * _.result(object, 'stuff');
+ * // => 'nonsense'
+ */
+ function result(object, property) {
+ // based on Backbone's private `getValue` function
+ // https://github.com/documentcloud/backbone/blob/0.9.2/backbone.js#L1419-1424
+ var value = object ? object[property] : null;
+ return isFunction(value) ? object[property]() : value;
+ }
+
+ /**
+ * A micro-templating method that handles arbitrary delimiters, preserves
+ * whitespace, and correctly escapes quotes within interpolated code.
+ *
+ * Note: In the development build `_.template` utilizes sourceURLs for easier
+ * debugging. See http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl
+ *
+ * Note: Lo-Dash may be used in Chrome extensions by either creating a `lodash csp`
+ * build and avoiding `_.template` use, or loading Lo-Dash in a sandboxed page.
+ * See http://developer.chrome.com/trunk/extensions/sandboxingEval.html
+ *
+ * @static
+ * @memberOf _
+ * @category Utilities
+ * @param {String} text The template text.
+ * @param {Obect} data The data object used to populate the text.
+ * @param {Object} options The options object.
+ * escape - The "escape" delimiter regexp.
+ * evaluate - The "evaluate" delimiter regexp.
+ * interpolate - The "interpolate" delimiter regexp.
+ * sourceURL - The sourceURL of the template's compiled source.
+ * variable - The data object variable name.
+ *
+ * @returns {Function|String} Returns a compiled function when no `data` object
+ * is given, else it returns the interpolated text.
+ * @example
+ *
+ * // using a compiled template
+ * var compiled = _.template('hello <%= name %>');
+ * compiled({ 'name': 'moe' });
+ * // => 'hello moe'
+ *
+ * var list = '<% _.forEach(people, function(name) { %><li><%= name %></li><% }); %>';
+ * _.template(list, { 'people': ['moe', 'larry', 'curly'] });
+ * // => '<li>moe</li><li>larry</li><li>curly</li>'
+ *
+ * // using the "escape" delimiter to escape HTML in data property values
+ * _.template('<b><%- value %></b>', { 'value': '<script>' });
+ * // => '<b>&lt;script&gt;</b>'
+ *
+ * // using the ES6 delimiter as an alternative to the default "interpolate" delimiter
+ * _.template('hello ${ name }', { 'name': 'curly' });
+ * // => 'hello curly'
+ *
+ * // using the internal `print` function in "evaluate" delimiters
+ * _.template('<% print("hello " + epithet); %>!', { 'epithet': 'stooge' });
+ * // => 'hello stooge!'
+ *
+ * // using custom template delimiters
+ * _.templateSettings = {
+ * 'interpolate': /{{([\s\S]+?)}}/g
+ * };
+ *
+ * _.template('hello {{ name }}!', { 'name': 'mustache' });
+ * // => 'hello mustache!'
+ *
+ * // using the `sourceURL` option to specify a custom sourceURL for the template
+ * var compiled = _.template('hello <%= name %>', null, { 'sourceURL': '/basic/greeting.jst' });
+ * compiled(data);
+ * // => find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector
+ *
+ * // using the `variable` option to ensure a with-statement isn't used in the compiled template
+ * var compiled = _.template('hello <%= data.name %>!', null, { 'variable': 'data' });
+ * compiled.source;
+ * // => function(data) {
+ * var __t, __p = '', __e = _.escape;
+ * __p += 'hello ' + ((__t = ( data.name )) == null ? '' : __t) + '!';
+ * return __p;
+ * }
+ *
+ * // using the `source` property to inline compiled templates for meaningful
+ * // line numbers in error messages and a stack trace
+ * fs.writeFileSync(path.join(cwd, 'jst.js'), '\
+ * var JST = {\
+ * "main": ' + _.template(mainText).source + '\
+ * };\
+ * ');
+ */
+ function template(text, data, options) {
+ // based on John Resig's `tmpl` implementation
+ // http://ejohn.org/blog/javascript-micro-templating/
+ // and Laura Doktorova's doT.js
+ // https://github.com/olado/doT
+ text || (text = '');
+ options || (options = {});
+
+ var isEvaluating,
+ result,
+ settings = lodash.templateSettings,
+ index = 0,
+ interpolate = options.interpolate || settings.interpolate || reNoMatch,
+ source = "__p += '",
+ variable = options.variable || settings.variable,
+ hasVariable = variable;
+
+ // compile regexp to match each delimiter
+ var reDelimiters = RegExp(
+ (options.escape || settings.escape || reNoMatch).source + '|' +
+ interpolate.source + '|' +
+ (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + '|' +
+ (options.evaluate || settings.evaluate || reNoMatch).source + '|$'
+ , 'g');
+
+ text.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {
+ interpolateValue || (interpolateValue = esTemplateValue);
+
+ // escape characters that cannot be included in string literals
+ source += text.slice(index, offset).replace(reUnescapedString, escapeStringChar);
+
+ // replace delimiters with snippets
+ source +=
+ escapeValue ? "' +\n__e(" + escapeValue + ") +\n'" :
+ evaluateValue ? "';\n" + evaluateValue + ";\n__p += '" :
+ interpolateValue ? "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'" : '';
+
+ isEvaluating || (isEvaluating = evaluateValue || reComplexDelimiter.test(escapeValue || interpolateValue));
+ index = offset + match.length;
+ });
+
+ source += "';\n";
+
+ // if `variable` is not specified and the template contains "evaluate"
+ // delimiters, wrap a with-statement around the generated code to add the
+ // data object to the top of the scope chain
+ if (!hasVariable) {
+ variable = 'obj';
+ if (isEvaluating) {
+ source = 'with (' + variable + ') {\n' + source + '\n}\n';
+ }
+ else {
+ // avoid a with-statement by prepending data object references to property names
+ var reDoubleVariable = RegExp('(\\(\\s*)' + variable + '\\.' + variable + '\\b', 'g');
+ source = source
+ .replace(reInsertVariable, '$&' + variable + '.')
+ .replace(reDoubleVariable, '$1__d');
+ }
+ }
+
+ // cleanup code by stripping empty strings
+ source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source)
+ .replace(reEmptyStringMiddle, '$1')
+ .replace(reEmptyStringTrailing, '$1;');
+
+ // frame code as the function body
+ source = 'function(' + variable + ') {\n' +
+ (hasVariable ? '' : variable + ' || (' + variable + ' = {});\n') +
+ 'var __t, __p = \'\', __e = _.escape' +
+ (isEvaluating
+ ? ', __j = Array.prototype.join;\n' +
+ 'function print() { __p += __j.call(arguments, \'\') }\n'
+ : (hasVariable ? '' : ', __d = ' + variable + '.' + variable + ' || ' + variable) + ';\n'
+ ) +
+ source +
+ 'return __p\n}';
+
+ // use a sourceURL for easier debugging
+ // http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl
+ var sourceURL = useSourceURL
+ ? '\n//@ sourceURL=' + (options.sourceURL || '/lodash/template/source[' + (templateCounter++) + ']')
+ : '';
+
+ try {
+ result = Function('_', 'return ' + source + sourceURL)(lodash);
+ } catch(e) {
+ e.source = source;
+ throw e;
+ }
+
+ if (data) {
+ return result(data);
+ }
+ // provide the compiled function's source via its `toString` method, in
+ // supported environments, or the `source` property as a convenience for
+ // inlining compiled templates during the build process
+ result.source = source;
+ return result;
+ }
+
+ /**
+ * Executes the `callback` function `n` times, returning an array of the results
+ * of each `callback` execution. The `callback` is bound to `thisArg` and invoked
+ * with one argument; (index).
+ *
+ * @static
+ * @memberOf _
+ * @category Utilities
+ * @param {Number} n The number of times to execute the callback.
+ * @param {Function} callback The function called per iteration.
+ * @param {Mixed} [thisArg] The `this` binding of `callback`.
+ * @returns {Array} Returns a new array of the results of each `callback` execution.
+ * @example
+ *
+ * var diceRolls = _.times(3, _.partial(_.random, 1, 6));
+ * // => [3, 6, 4]
+ *
+ * _.times(3, function(n) { mage.castSpell(n); });
+ * // => calls `mage.castSpell(n)` three times, passing `n` of `0`, `1`, and `2` respectively
+ *
+ * _.times(3, function(n) { this.cast(n); }, mage);
+ * // => also calls `mage.castSpell(n)` three times
+ */
+ function times(n, callback, thisArg) {
+ n = +n || 0;
+ var index = -1,
+ result = Array(n);
+
+ while (++index < n) {
+ result[index] = callback.call(thisArg, index);
+ }
+ return result;
+ }
+
+ /**
+ * The opposite of `_.escape`, this method converts the HTML entities
+ * `&amp;`, `&lt;`, `&gt;`, `&quot;`, and `&#x27;` in `string` to their
+ * corresponding characters.
+ *
+ * @static
+ * @memberOf _
+ * @category Utilities
+ * @param {String} string The string to unescape.
+ * @returns {String} Returns the unescaped string.
+ * @example
+ *
+ * _.unescape('Moe, Larry &amp; Curly');
+ * // => "Moe, Larry & Curly"
+ */
+ function unescape(string) {
+ return string == null ? '' : (string + '').replace(reEscapedHtml, unescapeHtmlChar);
+ }
+
+ /**
+ * Generates a unique id. If `prefix` is passed, the id will be appended to it.
+ *
+ * @static
+ * @memberOf _
+ * @category Utilities
+ * @param {String} [prefix] The value to prefix the id with.
+ * @returns {Number|String} Returns a numeric id if no prefix is passed, else
+ * a string id may be returned.
+ * @example
+ *
+ * _.uniqueId('contact_');
+ * // => 'contact_104'
+ */
+ function uniqueId(prefix) {
+ var id = idCounter++;
+ return prefix ? prefix + id : id;
+ }
+
+ /*--------------------------------------------------------------------------*/
+
+ /**
+ * Wraps the value in a `lodash` wrapper object.
+ *
+ * @static
+ * @memberOf _
+ * @category Chaining
+ * @param {Mixed} value The value to wrap.
+ * @returns {Object} Returns the wrapper object.
+ * @example
+ *
+ * var stooges = [
+ * { 'name': 'moe', 'age': 40 },
+ * { 'name': 'larry', 'age': 50 },
+ * { 'name': 'curly', 'age': 60 }
+ * ];
+ *
+ * var youngest = _.chain(stooges)
+ * .sortBy(function(stooge) { return stooge.age; })
+ * .map(function(stooge) { return stooge.name + ' is ' + stooge.age; })
+ * .first()
+ * .value();
+ * // => 'moe is 40'
+ */
+ function chain(value) {
+ value = new lodash(value);
+ value.__chain__ = true;
+ return value;
+ }
+
+ /**
+ * Invokes `interceptor` with the `value` as the first argument, and then
+ * returns `value`. The purpose of this method is to "tap into" a method chain,
+ * in order to perform operations on intermediate results within the chain.
+ *
+ * @static
+ * @memberOf _
+ * @category Chaining
+ * @param {Mixed} value The value to pass to `interceptor`.
+ * @param {Function} interceptor The function to invoke.
+ * @returns {Mixed} Returns `value`.
+ * @example
+ *
+ * _.chain([1, 2, 3, 200])
+ * .filter(function(num) { return num % 2 == 0; })
+ * .tap(alert)
+ * .map(function(num) { return num * num })
+ * .value();
+ * // => // [2, 200] (alerted)
+ * // => [4, 40000]
+ */
+ function tap(value, interceptor) {
+ interceptor(value);
+ return value;
+ }
+
+ /**
+ * Enables method chaining on the wrapper object.
+ *
+ * @name chain
+ * @deprecated
+ * @memberOf _
+ * @category Chaining
+ * @returns {Mixed} Returns the wrapper object.
+ * @example
+ *
+ * _([1, 2, 3]).value();
+ * // => [1, 2, 3]
+ */
+ function wrapperChain() {
+ this.__chain__ = true;
+ return this;
+ }
+
+ /**
+ * Extracts the wrapped value.
+ *
+ * @name value
+ * @memberOf _
+ * @category Chaining
+ * @returns {Mixed} Returns the wrapped value.
+ * @example
+ *
+ * _([1, 2, 3]).value();
+ * // => [1, 2, 3]
+ */
+ function wrapperValue() {
+ return this.__wrapped__;
+ }
+
+ /*--------------------------------------------------------------------------*/
+
+ /**
+ * The semantic version number.
+ *
+ * @static
+ * @memberOf _
+ * @type String
+ */
+ lodash.VERSION = '0.10.0';
+
+ // assign static methods
+ lodash.assign = assign;
+ lodash.after = after;
+ lodash.bind = bind;
+ lodash.bindAll = bindAll;
+ lodash.bindKey = bindKey;
+ lodash.chain = chain;
+ lodash.clone = clone;
+ lodash.compact = compact;
+ lodash.compose = compose;
+ lodash.contains = contains;
+ lodash.countBy = countBy;
+ lodash.debounce = debounce;
+ lodash.defaults = defaults;
+ lodash.defer = defer;
+ lodash.delay = delay;
+ lodash.difference = difference;
+ lodash.escape = escape;
+ lodash.every = every;
+ lodash.filter = filter;
+ lodash.find = find;
+ lodash.first = first;
+ lodash.flatten = flatten;
+ lodash.forEach = forEach;
+ lodash.forIn = forIn;
+ lodash.forOwn = forOwn;
+ lodash.functions = functions;
+ lodash.groupBy = groupBy;
+ lodash.has = has;
+ lodash.identity = identity;
+ lodash.indexOf = indexOf;
+ lodash.initial = initial;
+ lodash.intersection = intersection;
+ lodash.invert = invert;
+ lodash.invoke = invoke;
+ lodash.isArguments = isArguments;
+ lodash.isArray = isArray;
+ lodash.isBoolean = isBoolean;
+ lodash.isDate = isDate;
+ lodash.isElement = isElement;
+ lodash.isEmpty = isEmpty;
+ lodash.isEqual = isEqual;
+ lodash.isFinite = isFinite;
+ lodash.isFunction = isFunction;
+ lodash.isNaN = isNaN;
+ lodash.isNull = isNull;
+ lodash.isNumber = isNumber;
+ lodash.isObject = isObject;
+ lodash.isPlainObject = isPlainObject;
+ lodash.isRegExp = isRegExp;
+ lodash.isString = isString;
+ lodash.isUndefined = isUndefined;
+ lodash.keys = keys;
+ lodash.last = last;
+ lodash.lastIndexOf = lastIndexOf;
+ lodash.map = map;
+ lodash.max = max;
+ lodash.memoize = memoize;
+ lodash.merge = merge;
+ lodash.min = min;
+ lodash.mixin = mixin;
+ lodash.noConflict = noConflict;
+ lodash.object = object;
+ lodash.omit = omit;
+ lodash.once = once;
+ lodash.pairs = pairs;
+ lodash.partial = partial;
+ lodash.pick = pick;
+ lodash.pluck = pluck;
+ lodash.random = random;
+ lodash.range = range;
+ lodash.reduce = reduce;
+ lodash.reduceRight = reduceRight;
+ lodash.reject = reject;
+ lodash.rest = rest;
+ lodash.result = result;
+ lodash.shuffle = shuffle;
+ lodash.size = size;
+ lodash.some = some;
+ lodash.sortBy = sortBy;
+ lodash.sortedIndex = sortedIndex;
+ lodash.tap = tap;
+ lodash.template = template;
+ lodash.throttle = throttle;
+ lodash.times = times;
+ lodash.toArray = toArray;
+ lodash.unescape = unescape;
+ lodash.union = union;
+ lodash.uniq = uniq;
+ lodash.uniqueId = uniqueId;
+ lodash.values = values;
+ lodash.where = where;
+ lodash.without = without;
+ lodash.wrap = wrap;
+ lodash.zip = zip;
+
+ // assign aliases
+ lodash.all = every;
+ lodash.any = some;
+ lodash.collect = map;
+ lodash.detect = find;
+ lodash.drop = rest;
+ lodash.each = forEach;
+ lodash.extend = assign;
+ lodash.foldl = reduce;
+ lodash.foldr = reduceRight;
+ lodash.head = first;
+ lodash.include = contains;
+ lodash.inject = reduce;
+ lodash.methods = functions;
+ lodash.select = filter;
+ lodash.tail = rest;
+ lodash.take = first;
+ lodash.unique = uniq;
+
+ // add pseudo private property to be used and removed during the build process
+ lodash._iteratorTemplate = iteratorTemplate;
+
+ /*--------------------------------------------------------------------------*/
+
+ // add all static functions to `lodash.prototype`
+ mixin(lodash);
+
+ // add `lodash.prototype.chain` after calling `mixin()` to avoid overwriting
+ // it with the wrapped `lodash.chain`
+ lodash.prototype.chain = wrapperChain;
+ lodash.prototype.value = wrapperValue;
+
+ // add all mutator Array functions to the wrapper.
+ forEach(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(methodName) {
+ var func = arrayRef[methodName];
+
+ lodash.prototype[methodName] = function() {
+ var value = this.__wrapped__;
+ func.apply(value, arguments);
+
+ // avoid array-like object bugs with `Array#shift` and `Array#splice` in
+ // Firefox < 10 and IE < 9
+ if (hasObjectSpliceBug && value.length === 0) {
+ delete value[0];
+ }
+ if (this.__chain__) {
+ value = new lodash(value);
+ value.__chain__ = true;
+ }
+ return value;
+ };
+ });
+
+ // add all accessor Array functions to the wrapper.
+ forEach(['concat', 'join', 'slice'], function(methodName) {
+ var func = arrayRef[methodName];
+
+ lodash.prototype[methodName] = function() {
+ var value = this.__wrapped__,
+ result = func.apply(value, arguments);
+
+ if (this.__chain__) {
+ result = new lodash(result);
+ result.__chain__ = true;
+ }
+ return result;
+ };
+ });
+
+ /*--------------------------------------------------------------------------*/
+
+ // expose Lo-Dash
+ // some AMD build optimizers, like r.js, check for specific condition patterns like the following:
+ if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
+ // Expose Lo-Dash to the global object even when an AMD loader is present in
+ // case Lo-Dash was injected by a third-party script and not intended to be
+ // loaded as a module. The global assignment can be reverted in the Lo-Dash
+ // module via its `noConflict()` method.
+ window._ = lodash;
+
+ // define as an anonymous module so, through path mapping, it can be
+ // referenced as the "underscore" module
+ define(function() {
+ return lodash;
+ });
+ }
+ // check for `exports` after `define` in case a build optimizer adds an `exports` object
+ else if (freeExports) {
+ // in Node.js or RingoJS v0.8.0+
+ if (typeof module == 'object' && module && module.exports == freeExports) {
+ (module.exports = lodash)._ = lodash;
+ }
+ // in Narwhal or RingoJS v0.7.0-
+ else {
+ freeExports._ = lodash;
+ }
+ }
+ else {
+ // in a browser or Rhino
+ window._ = lodash;
+ }
+}(this));
diff --git a/tests/wpt/web-platform-tests/webaudio/js/vendor-prefixes.js b/tests/wpt/web-platform-tests/webaudio/js/vendor-prefixes.js
new file mode 100644
index 00000000000..287d692b3c3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webaudio/js/vendor-prefixes.js
@@ -0,0 +1,2 @@
+window.AudioContext = window.AudioContext || window.webkitAudioContext;
+window.OfflineAudioContext = window.OfflineAudioContext || window.webkitOfflineAudioContext;
diff --git a/tests/wpt/web-platform-tests/webaudio/refresh_idl.rb b/tests/wpt/web-platform-tests/webaudio/refresh_idl.rb
new file mode 100755
index 00000000000..a07847535ad
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webaudio/refresh_idl.rb
@@ -0,0 +1,57 @@
+#!/usr/bin/env ruby
+require 'nokogiri'
+
+def base_dir
+ File.dirname(__FILE__)
+end
+
+def output_directory
+ File.join(base_dir, 'idl')
+end
+
+def specification
+ file = File.open(File.join(base_dir, 'specification.html'))
+ doc = Nokogiri::XML(file)
+ file.close
+ doc
+end
+
+def write_node_inner_text_to_file(filename, node)
+ File.open(filename, 'w') { |file| file.write(node.inner_text.strip) }
+ puts "Wrote: #{filename}"
+end
+
+def load_idl(id)
+ file = File.join(output_directory, id)
+ return false if !File.exist?(file)
+ File.read(file)
+end
+
+# Parse the specification writing each block of idl to its own file
+specification.css(".idl-code").each do |idl_block|
+ id = idl_block["id"]
+ write_node_inner_text_to_file(File.join(output_directory, id), idl_block) if id
+end
+
+# Update the idl in the pre blocks for each idl test
+idl_test_files = [
+ File.join(base_dir, 'the-audio-api', 'the-gainnode-interface', 'idl-test.html'),
+ File.join(base_dir, 'the-audio-api', 'the-audiodestinationnode-interface', 'idl-test.html'),
+ File.join(base_dir, 'the-audio-api', 'the-delaynode-interface', 'idl-test.html'),
+ File.join(base_dir, 'the-audio-api', 'the-audiobuffer-interface', 'idl-test.html'),
+]
+
+idl_test_files.each do |fn|
+ file = File.open(fn)
+ doc = Nokogiri::HTML(file)
+ file.close
+
+ doc.css('pre').each do |node|
+ node_id = node["id"]
+ if idl = load_idl(node_id)
+ node.content = idl
+ end
+ end
+
+ File.open(fn, 'w') { |file| file.write(doc.to_html)}
+end
diff --git a/tests/wpt/web-platform-tests/webaudio/resources/sin_440Hz_-6dBFS_1s.wav b/tests/wpt/web-platform-tests/webaudio/resources/sin_440Hz_-6dBFS_1s.wav
new file mode 100644
index 00000000000..f660c3c4b8e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webaudio/resources/sin_440Hz_-6dBFS_1s.wav
Binary files differ
diff --git a/tests/wpt/web-platform-tests/webaudio/specification.html b/tests/wpt/web-platform-tests/webaudio/specification.html
new file mode 100644
index 00000000000..3178c5e1022
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webaudio/specification.html
@@ -0,0 +1,5911 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <title>Web Audio API</title>
+ <meta name="revision"
+ content="$Id: Overview.html,v 1.4 2012/07/30 11:44:57 tmichel Exp $" />
+ <link rel="stylesheet" href="style.css" type="text/css" />
+ <!--
+ <script src="section-links.js" type="application/ecmascript"></script>
+ <script src="dfn.js" type="application/ecmascript"></script>
+ -->
+ <!--[if IE]>
+ <style type='text/css'>
+ .ignore {
+ -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";
+ filter: alpha(opacity=50);
+ }
+ </style>
+ <![endif]-->
+ <link rel="stylesheet" href="//www.w3.org/StyleSheets/TR/W3C-ED"
+ type="text/css" />
+</head>
+
+<body>
+
+<div class="head">
+<p><a href="http://www.w3.org/"><img width="72" height="48" alt="W3C"
+src="http://www.w3.org/Icons/w3c_home" /></a> </p>
+
+<h1 id="title" class="title">Web Audio API </h1>
+
+<h2 id="w3c-date-document"><acronym
+title="World Wide Web Consortium">W3C</acronym> Editor's Draft
+</h2>
+<dl>
+ <dt>This version: </dt>
+ <dd><a
+ href="https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html">https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html</a>
+ </dd>
+ <dt>Latest published version: </dt>
+ <dd><a
+ href="http://www.w3.org/TR/webaudio/">http://www.w3.org/TR/webaudio/</a>
+ </dd>
+ <dt>Previous version: </dt>
+ <dd><a
+ href="http://www.w3.org/TR/2012/WD-webaudio-20120315/">http://www.w3.org/TR/2012/WD-webaudio-20120315/</a>
+ </dd>
+</dl>
+
+<dl>
+ <dt>Editor: </dt>
+ <dd>Chris Rogers, Google &lt;crogers@google.com&gt;</dd>
+</dl>
+
+<p class="copyright"><a
+href="http://www.w3.org/Consortium/Legal/ipr-notice#Copyright">Copyright</a> ©
+2012 <a href="http://www.w3.org/"><acronym
+title="World Wide Web Consortium">W3C</acronym></a><sup>®</sup> (<a
+href="http://www.csail.mit.edu/"><acronym
+title="Massachusetts Institute of Technology">MIT</acronym></a>, <a
+href="http://www.ercim.eu/"><acronym
+title="European Research Consortium for Informatics and Mathematics">ERCIM</acronym></a>,
+<a href="http://www.keio.ac.jp/">Keio</a>), All Rights Reserved. W3C <a
+href="http://www.w3.org/Consortium/Legal/ipr-notice#Legal_Disclaimer">liability</a>,
+<a
+href="http://www.w3.org/Consortium/Legal/ipr-notice#W3C_Trademarks">trademark</a>
+and <a href="http://www.w3.org/Consortium/Legal/copyright-documents">document
+use</a> rules apply.</p>
+<hr />
+</div>
+
+<div id="abstract-section" class="section">
+<h2 id="abstract">Abstract</h2>
+
+<p>This specification describes a high-level JavaScript <acronym
+title="Application Programming Interface">API</acronym> for processing and
+synthesizing audio in web applications. The primary paradigm is of an audio
+routing graph, where a number of <a
+href="#AudioNode-section"><code>AudioNode</code></a> objects are connected
+together to define the overall audio rendering. The actual processing will
+primarily take place in the underlying implementation (typically optimized
+Assembly / C / C++ code), but <a href="#JavaScriptProcessing-section">direct
+JavaScript processing and synthesis</a> is also supported. </p>
+
+<p>The <a href="#introduction">introductory</a> section covers the motivation
+behind this specification.</p>
+
+<p>This API is designed to be used in conjunction with other APIs and elements
+on the web platform, notably: XMLHttpRequest
+(using the <code>responseType</code> and <code>response</code> attributes). For
+games and interactive applications, it is anticipated to be used with the
+<code>canvas</code> 2D and WebGL 3D graphics APIs. </p>
+</div>
+
+<div id="sotd-section" class="section">
+<h2 id="sotd">Status of this Document</h2>
+
+
+<p><em>This section describes the status of this document at the time of its
+publication. Other documents may supersede this document. A list of current W3C
+publications and the latest revision of this technical report can be found in
+the <a href="http://www.w3.org/TR/">W3C technical reports index</a> at
+http://www.w3.org/TR/. </em></p>
+
+<p>This is the Editor's Draft of the <cite>Web Audio API</cite>
+specification. It has been produced by the <a
+href="http://www.w3.org/2011/audio/"><b>W3C Audio Working Group</b></a> , which
+is part of the W3C WebApps Activity.</p>
+
+<p></p>
+
+<p>Please send comments about this document to &lt;<a
+href="mailto:public-audio@w3.org">public-audio@w3.org</a>&gt; (<a
+href="http://lists.w3.org/Archives/Public/public-audio/">public archives</a> of
+the W3C audio mailing list). Web content and browser developers are encouraged
+to review this draft. </p>
+
+<p>Publication as a Working Draft does not imply endorsement by the W3C
+Membership. This is a draft document and may be updated, replaced or obsoleted
+by other documents at any time. It is inappropriate to cite this document as
+other than work in progress.</p>
+
+<p> This document was produced by a group operating under the <a href="http://www.w3.org/Consortium/Patent-Policy-20040205/">5 February 2004 W3C Patent Policy</a>. W3C maintains a <a rel="disclosure" href="http://www.w3.org/2004/01/pp-impl/46884/status">public list of any patent disclosures</a> made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains <a href="http://www.w3.org/Consortium/Patent-Policy-20040205/#def-essential">Essential Claim(s)</a> must disclose the information in accordance with <a href="http://www.w3.org/Consortium/Patent-Policy-20040205/#sec-Disclosure">section 6 of the W3C Patent Policy</a>. </p>
+</div>
+
+<div id="toc">
+<h2 id="L13522">Table of Contents</h2>
+
+<div class="toc">
+<ul>
+ <li><a href="#introduction">1. Introduction</a>
+ <ul>
+ <li><a href="#Features">1.1. Features</a></li>
+ <li><a href="#ModularRouting">1.2. Modular Routing</a></li>
+ <li><a href="#APIOverview">1.3. API Overview</a></li>
+ </ul>
+ </li>
+ <li><a href="#conformance">2. Conformance</a></li>
+ <li><a href="#API-section">4. The Audio API</a>
+ <ul>
+ <li><a href="#AudioContext-section">4.1. The AudioContext Interface</a>
+ <ul>
+ <li><a href="#attributes-AudioContext">4.1.1. Attributes</a></li>
+ <li><a href="#methodsandparams-AudioContext">4.1.2. Methods and
+ Parameters</a></li>
+ <li><a href="#lifetime-AudioContext">4.1.3. Lifetime</a></li>
+ </ul>
+ </li>
+ <li><a href="#OfflineAudioContext-section">4.1b. The OfflineAudioContext Interface</a>
+ </li>
+
+ <li><a href="#AudioNode-section">4.2. The AudioNode Interface</a>
+ <ul>
+ <li><a href="#attributes-AudioNode">4.2.1. Attributes</a></li>
+ <li><a href="#methodsandparams-AudioNode">4.2.2. Methods and
+ Parameters</a></li>
+ <li><a href="#lifetime-AudioNode">4.2.3. Lifetime</a></li>
+ </ul>
+ </li>
+ <li><a href="#AudioDestinationNode">4.4. The AudioDestinationNode
+ Interface</a>
+ <ul>
+ <li><a href="#attributes-AudioDestinationNode">4.4.1. Attributes</a></li>
+ </ul>
+ </li>
+ <li><a href="#AudioParam">4.5. The AudioParam Interface</a>
+ <ul>
+ <li><a href="#attributes-AudioParam">4.5.1. Attributes</a></li>
+ <li><a href="#methodsandparams-AudioParam">4.5.2. Methods and
+ Parameters</a></li>
+ <li><a href="#computedValue-AudioParam-section">4.5.3. Computation of Value</a></li>
+ <li><a href="#example1-AudioParam-section">4.5.4. AudioParam Automation Example</a></li>
+ </ul>
+ </li>
+ <li><a href="#GainNode">4.7. The GainNode Interface</a>
+ <ul>
+ <li><a href="#attributes-GainNode">4.7.1. Attributes</a></li>
+ </ul>
+ </li>
+ <li><a href="#DelayNode">4.8. The DelayNode Interface</a>
+ <ul>
+ <li><a href="#attributes-GainNode_2">4.8.1. Attributes</a></li>
+ </ul>
+ </li>
+ <li><a href="#AudioBuffer">4.9. The AudioBuffer Interface</a>
+ <ul>
+ <li><a href="#attributes-AudioBuffer">4.9.1. Attributes</a></li>
+ <li><a href="#methodsandparams-AudioBuffer">4.9.2. Methods and
+ Parameters</a></li>
+ </ul>
+ </li>
+ <li><a href="#AudioBufferSourceNode">4.10. The AudioBufferSourceNode
+ Interface</a>
+ <ul>
+ <li><a href="#attributes-AudioBufferSourceNode">4.10.1.
+ Attributes</a></li>
+ <li><a href="#methodsandparams-AudioBufferSourceNode">4.10.2. Methods and
+ Parameters</a></li>
+ </ul>
+ </li>
+ <li><a href="#MediaElementAudioSourceNode">4.11. The
+ MediaElementAudioSourceNode Interface</a></li>
+ <li><a href="#ScriptProcessorNode">4.12. The ScriptProcessorNode
+ Interface</a>
+ <ul>
+ <li><a href="#attributes-ScriptProcessorNode">4.12.1. Attributes</a></li>
+ </ul>
+ </li>
+ <li><a href="#AudioProcessingEvent">4.13. The AudioProcessingEvent
+ Interface</a>
+ <ul>
+ <li><a href="#attributes-AudioProcessingEvent">4.13.1. Attributes</a></li>
+ </ul>
+ </li>
+ <li><a href="#PannerNode">4.14. The PannerNode Interface</a>
+ <ul>
+ <li><a href="#attributes-PannerNode_attributes">4.14.2.
+ Attributes</a></li>
+ <li><a href="#Methods_and_Parameters">4.14.3. Methods and
+ Parameters</a></li>
+ </ul>
+ </li>
+ <li><a href="#AudioListener">4.15. The AudioListener Interface</a>
+ <ul>
+ <li><a href="#attributes-AudioListener">4.15.1. Attributes</a></li>
+ <li><a href="#L15842">4.15.2. Methods and Parameters</a></li>
+ </ul>
+ </li>
+ <li><a href="#ConvolverNode">4.16. The ConvolverNode Interface</a>
+ <ul>
+ <li><a href="#attributes-ConvolverNode">4.16.1. Attributes</a></li>
+ </ul>
+ </li>
+ <li><a href="#AnalyserNode">4.17. The AnalyserNode
+ Interface</a>
+ <ul>
+ <li><a href="#attributes-ConvolverNode_2">4.17.1. Attributes</a></li>
+ <li><a href="#methods-and-parameters">4.17.2. Methods and
+ Parameters</a></li>
+ </ul>
+ </li>
+ <li><a href="#ChannelSplitterNode">4.18. The ChannelSplitterNode
+ Interface</a>
+ <ul>
+ <li><a href="#example-1">Example:</a></li>
+ </ul>
+ </li>
+ <li><a href="#ChannelMergerNode">4.19. The ChannelMergerNode Interface</a>
+ <ul>
+ <li><a href="#example-2">Example:</a></li>
+ </ul>
+ </li>
+ <li><a href="#DynamicsCompressorNode">4.20. The DynamicsCompressorNode
+ Interface</a>
+ <ul>
+ <li><a href="#attributes-DynamicsCompressorNode">4.20.1.
+ Attributes</a></li>
+ </ul>
+ </li>
+ <li><a href="#BiquadFilterNode">4.21. The BiquadFilterNode Interface</a>
+ <ul>
+ <li><a href="#BiquadFilterNode-description">4.21.1 Lowpass</a></li>
+ <li><a href="#HIGHPASS">4.21.2 Highpass</a></li>
+ <li><a href="#BANDPASS">4.21.3 Bandpass</a></li>
+ <li><a href="#LOWSHELF">4.21.4 Lowshelf</a></li>
+ <li><a href="#L16352">4.21.5 Highshelf</a></li>
+ <li><a href="#PEAKING">4.21.6 Peaking</a></li>
+ <li><a href="#NOTCH">4.21.7 Notch</a></li>
+ <li><a href="#ALLPASS">4.21.8 Allpass</a></li>
+ <li><a href="#Methods">4.21.9. Methods</a></li>
+ </ul>
+ </li>
+ <li><a href="#WaveShaperNode">4.22. The WaveShaperNode Interface</a>
+ <ul>
+ <li><a href="#attributes-WaveShaperNode">4.22.1.
+ Attributes</a></li>
+ </ul>
+ </li>
+ <li><a href="#OscillatorNode">4.23. The OscillatorNode Interface</a>
+ <ul>
+ <li><a href="#attributes-OscillatorNode">4.23.1.
+ Attributes</a></li>
+ <li><a href="#methodsandparams-OscillatorNode-section">4.23.2. Methods and
+ Parameters</a></li>
+ </ul>
+ </li>
+ <li><a href="#PeriodicWave">4.24. The PeriodicWave Interface</a>
+ </li>
+ <li><a href="#MediaStreamAudioSourceNode">4.25. The
+ MediaStreamAudioSourceNode Interface</a></li>
+ <li><a href="#MediaStreamAudioDestinationNode">4.26. The
+ MediaStreamAudioDestinationNode Interface</a></li>
+ </ul>
+ </li>
+ <li><a href="#MixerGainStructure">6. Mixer Gain Structure</a>
+ <ul>
+ <li><a href="#background">Background</a></li>
+ <li><a href="#SummingJunction">Summing Inputs</a></li>
+ <li><a href="#gain-Control">Gain Control</a></li>
+ <li><a href="#Example-mixer-with-send-busses">Example: Mixer with Send
+ Busses</a></li>
+ </ul>
+ </li>
+ <li><a href="#DynamicLifetime">7. Dynamic Lifetime</a>
+ <ul>
+ <li><a href="#DynamicLifetime-background">Background</a></li>
+ <li><a href="#Example-DynamicLifetime">Example</a></li>
+ </ul>
+ </li>
+ <li><a href="#UpMix">9. Channel up-mixing and down-mixing</a>
+ <ul>
+ <li><a href="#ChannelLayouts">9.1. Speaker Channel Layouts</a>
+ <ul>
+ <li><a href="#ChannelOrdering">9.1.1. Channel Ordering</a></li>
+ <li><a href="#UpMix-sub">9.1.2. Up Mixing</a></li>
+ <li><a href="#down-mix">9.1.3. Down Mixing</a></li>
+ </ul>
+ </li>
+
+ <li><a href="#ChannelRules-section">9.2. Channel Rules Examples</a>
+
+ </ul>
+ </li>
+ <li><a href="#Spatialization">11. Spatialization / Panning </a>
+ <ul>
+ <li><a href="#Spatialization-background">Background</a></li>
+ <li><a href="#Spatialization-panning-algorithm">Panning Algorithm</a></li>
+ <li><a href="#Spatialization-distance-effects">Distance Effects</a></li>
+ <li><a href="#Spatialization-sound-cones">Sound Cones</a></li>
+ <li><a href="#Spatialization-doppler-shift">Doppler Shift</a></li>
+ </ul>
+ </li>
+ <li><a href="#Convolution">12. Linear Effects using Convolution</a>
+ <ul>
+ <li><a href="#Convolution-background">Background</a></li>
+ <li><a href="#Convolution-motivation">Motivation for use as a
+ Standard</a></li>
+ <li><a href="#Convolution-implementation-guide">Implementation Guide</a></li>
+ <li><a href="#Convolution-reverb-effect">Reverb Effect (with
+ matrixing)</a></li>
+ <li><a href="#recording-impulse-responses">Recording Impulse
+ Responses</a></li>
+ <li><a href="#tools">Tools</a></li>
+ <li><a href="#recording-setup">Recording Setup</a></li>
+ <li><a href="#warehouse">The Warehouse Space</a></li>
+ </ul>
+ </li>
+ <li><a href="#JavaScriptProcessing">13. JavaScript Synthesis and
+ Processing</a>
+ <ul>
+ <li><a href="#custom-DSP-effects">Custom DSP Effects</a></li>
+ <li><a href="#educational-applications">Educational Applications</a></li>
+ <li><a href="#javaScript-performance">JavaScript Performance</a></li>
+ </ul>
+ </li>
+ <li><a href="#Performance">15. Performance Considerations</a>
+ <ul>
+ <li><a href="#Latency">15.1. Latency: What it is and Why it's
+ Important</a></li>
+ <li><a href="#audio-glitching">15.2. Audio Glitching</a></li>
+ <li><a href="#hardware-scalability">15.3. Hardware Scalability</a>
+ <ul>
+ <li><a href="#CPU-monitoring">15.3.1. CPU monitoring</a></li>
+ <li><a href="#Voice-dropping">15.3.2. Voice Dropping</a></li>
+ <li><a href="#Simplification-of-Effects-Processing">15.3.3.
+ Simplification of Effects Processing</a></li>
+ <li><a href="#Sample-rate">15.3.4. Sample Rate</a></li>
+ <li><a href="#pre-flighting">15.3.5. Pre-flighting</a></li>
+ <li><a href="#Authoring-for-different-user-agents">15.3.6. Authoring
+ for different user agents</a></li>
+ <li><a href="#Scalability-of-Direct-JavaScript-Synthesis">15.3.7.
+ Scalability of Direct JavaScript Synthesis / Processing</a></li>
+ </ul>
+ </li>
+ <li><a href="#JavaScriptPerformance">15.4. JavaScript Issues with
+ real-time Processing and Synthesis: </a></li>
+ </ul>
+ </li>
+ <li><a href="#ExampleApplications">16. Example Applications</a>
+ <ul>
+ <li><a href="#basic-sound-playback">Basic Sound Playback</a></li>
+ <li><a href="#threeD-environmentse-and-games">3D Environments and
+ Games</a></li>
+ <li><a href="#musical-applications">Musical Applications</a></li>
+ <li><a href="#music-visualizers">Music Visualizers</a></li>
+ <li><a href="#educational-applications_2">Educational
+ Applications</a></li>
+ <li><a href="#artistic-audio-exploration">Artistic Audio
+ Exploration</a></li>
+ </ul>
+ </li>
+ <li><a href="#SecurityConsiderations">17. Security Considerations</a></li>
+ <li><a href="#PrivacyConsiderations">18. Privacy Considerations</a></li>
+ <li><a href="#requirements">19. Requirements and Use Cases</a></li>
+ <li><a href="#OldNames">20. Old Names</a></li>
+ <li><a href="#L17310">A.References</a>
+ <ul>
+ <li><a href="#Normative-references">A.1 Normative references</a></li>
+ <li><a href="#Informative-references">A.2 Informative references</a></li>
+ </ul>
+ </li>
+ <li><a href="#L17335">B.Acknowledgements</a></li>
+ <li><a href="#ChangeLog">C. Web Audio API Change Log</a></li>
+</ul>
+</div>
+</div>
+
+<div id="sections">
+
+<div id="div-introduction" class="section">
+<h2 id="introduction">1. Introduction</h2>
+
+<p class="norm">This section is informative.</p>
+
+<p>Audio on the web has been fairly primitive up to this point and until very
+recently has had to be delivered through plugins such as Flash and QuickTime.
+The introduction of the <code>audio</code> element in HTML5 is very important,
+allowing for basic streaming audio playback. But, it is not powerful enough to
+handle more complex audio applications. For sophisticated web-based games or
+interactive applications, another solution is required. It is a goal of this
+specification to include the capabilities found in modern game audio engines as
+well as some of the mixing, processing, and filtering tasks that are found in
+modern desktop audio production applications. </p>
+
+<p>The APIs have been designed with a wide variety of <a
+href="#ExampleApplications-section">use cases</a> in mind. Ideally, it should
+be able to support <i>any</i> use case which could reasonably be implemented
+with an optimized C++ engine controlled via JavaScript and run in a browser.
+That said, modern desktop audio software can have very advanced capabilities,
+some of which would be difficult or impossible to build with this system.
+Apple's Logic Audio is one such application which has support for external MIDI
+controllers, arbitrary plugin audio effects and synthesizers, highly optimized
+direct-to-disk audio file reading/writing, tightly integrated time-stretching,
+and so on. Nevertheless, the proposed system will be quite capable of
+supporting a large range of reasonably complex games and interactive
+applications, including musical ones. And it can be a very good complement to
+the more advanced graphics features offered by WebGL. The API has been designed
+so that more advanced capabilities can be added at a later time. </p>
+
+<div id="Features-section" class="section">
+<h2 id="Features">1.1. Features</h2>
+</div>
+
+<p>The API supports these primary features: </p>
+<ul>
+ <li><a href="#ModularRouting-section">Modular routing</a> for simple or
+ complex mixing/effect architectures, including <a
+ href="#MixerGainStructure-section">multiple sends and submixes</a>.</li>
+ <li><a href="#AudioParam">Sample-accurate scheduled sound
+ playback</a> with low <a href="#Latency-section">latency</a> for musical
+ applications requiring a very high degree of rhythmic precision such as
+ drum machines and sequencers. This also includes the possibility of <a
+ href="#DynamicLifetime-section">dynamic creation</a> of effects. </li>
+ <li>Automation of audio parameters for envelopes, fade-ins / fade-outs,
+ granular effects, filter sweeps, LFOs etc. </li>
+ <li>Flexible handling of channels in an audio stream, allowing them to be split and merged.</li>
+
+ <li>Processing of audio sources from an <code>audio</code> or
+ <code>video</code> <a href="#MediaElementAudioSourceNode">media
+ element</a>. </li>
+
+ <li>Processing live audio input using a <a href="#MediaStreamAudioSourceNode">MediaStream</a>
+ from getUserMedia().
+ </li>
+
+ <li>Integration with WebRTC
+ <ul>
+
+
+ <li>Processing audio received from a remote peer using a <a href="#MediaStreamAudioSourceNode">MediaStream</a>.
+ </li>
+
+ <li>Sending a generated or processed audio stream to a remote peer using a <a href="#MediaStreamAudioDestinationNode">MediaStream</a>.
+ </li>
+
+ </ul>
+ </li>
+
+ <li>Audio stream synthesis and processing <a
+ href="#JavaScriptProcessing-section">directly in JavaScript</a>. </li>
+ <li><a href="#Spatialization-section">Spatialized audio</a> supporting a wide
+ range of 3D games and immersive environments:
+ <ul>
+ <li>Panning models: equal-power, HRTF, pass-through </li>
+ <li>Distance Attenuation </li>
+ <li>Sound Cones </li>
+ <li>Obstruction / Occlusion </li>
+ <li>Doppler Shift </li>
+ <li>Source / Listener based</li>
+ </ul>
+ </li>
+ <li>A <a href="#Convolution-section">convolution engine</a> for a wide range
+ of linear effects, especially very high-quality room effects. Here are some
+ examples of possible effects:
+ <ul>
+ <li>Small / large room </li>
+ <li>Cathedral </li>
+ <li>Concert hall </li>
+ <li>Cave </li>
+ <li>Tunnel </li>
+ <li>Hallway </li>
+ <li>Forest </li>
+ <li>Amphitheater </li>
+ <li>Sound of a distant room through a doorway </li>
+ <li>Extreme filters</li>
+ <li>Strange backwards effects</li>
+ <li>Extreme comb filter effects </li>
+ </ul>
+ </li>
+ <li>Dynamics compression for overall control and sweetening of the mix </li>
+ <li>Efficient <a href="#AnalyserNode">real-time time-domain and
+ frequency analysis / music visualizer support</a></li>
+ <li>Efficient biquad filters for lowpass, highpass, and other common filters.
+ </li>
+ <li>A Waveshaping effect for distortion and other non-linear effects</li>
+ <li>Oscillators</li>
+
+</ul>
+
+<div id="ModularRouting-section">
+<h2 id="ModularRouting">1.2. Modular Routing</h2>
+
+<p>Modular routing allows arbitrary connections between different <a
+href="#AudioNode-section"><code>AudioNode</code></a> objects. Each node can
+have <dfn>inputs</dfn> and/or <dfn>outputs</dfn>. A <dfn>source node</dfn> has no inputs
+and a single output. A <dfn>destination node</dfn> has
+one input and no outputs, the most common example being <a
+href="#AudioDestinationNode-section"><code>AudioDestinationNode</code></a> the final destination to the audio
+hardware. Other nodes such as filters can be placed between the source and destination nodes.
+The developer doesn't have to worry about low-level stream format details
+when two objects are connected together; <a href="#UpMix-section">the right
+thing just happens</a>. For example, if a mono audio stream is connected to a
+stereo input it should just mix to left and right channels <a
+href="#UpMix-section">appropriately</a>. </p>
+
+<p>In the simplest case, a single source can be routed directly to the output.
+All routing occurs within an <a
+href="#AudioContext-section"><code>AudioContext</code></a> containing a single
+<a href="#AudioDestinationNode-section"><code>AudioDestinationNode</code></a>:
+</p>
+<img alt="modular routing" src="images/modular-routing1.png" />
+
+<p>Illustrating this simple routing, here's a simple example playing a single
+sound: </p>
+
+<div class="block">
+
+<div class="blockTitleDiv">
+<span class="blockTitle">ECMAScript</span> </div>
+
+<div class="blockContent">
+<pre class="code"><code class="es-code">
+
+var context = new AudioContext();
+
+function playSound() {
+ var source = context.createBufferSource();
+ source.buffer = dogBarkingBuffer;
+ source.connect(context.destination);
+ source.start(0);
+}
+ </code></pre>
+</div>
+</div>
+
+<p>Here's a more complex example with three sources and a convolution reverb
+send with a dynamics compressor at the final output stage: </p>
+<img alt="modular routing2" src="images/modular-routing2.png" />
+
+<div class="example">
+
+<div class="exampleHeader">
+Example</div>
+
+<div class="block">
+
+<div class="blockTitleDiv">
+<span class="blockTitle">ECMAScript</span></div>
+
+<div class="blockContent">
+<pre class="code"><code class="es-code">
+
+var context = 0;
+var compressor = 0;
+var reverb = 0;
+
+var source1 = 0;
+var source2 = 0;
+var source3 = 0;
+
+var lowpassFilter = 0;
+var waveShaper = 0;
+var panner = 0;
+
+var dry1 = 0;
+var dry2 = 0;
+var dry3 = 0;
+
+var wet1 = 0;
+var wet2 = 0;
+var wet3 = 0;
+
+var masterDry = 0;
+var masterWet = 0;
+
+function setupRoutingGraph () {
+ context = new AudioContext();
+
+ // Create the effects nodes.
+ lowpassFilter = context.createBiquadFilter();
+ waveShaper = context.createWaveShaper();
+ panner = context.createPanner();
+ compressor = context.createDynamicsCompressor();
+ reverb = context.createConvolver();
+
+ // Create master wet and dry.
+ masterDry = context.createGain();
+ masterWet = context.createGain();
+
+ // Connect final compressor to final destination.
+ compressor.connect(context.destination);
+
+ // Connect master dry and wet to compressor.
+ masterDry.connect(compressor);
+ masterWet.connect(compressor);
+
+ // Connect reverb to master wet.
+ reverb.connect(masterWet);
+
+ // Create a few sources.
+ source1 = context.createBufferSource();
+ source2 = context.createBufferSource();
+ source3 = context.createOscillator();
+
+ source1.buffer = manTalkingBuffer;
+ source2.buffer = footstepsBuffer;
+ source3.frequency.value = 440;
+
+ // Connect source1
+ dry1 = context.createGain();
+ wet1 = context.createGain();
+ source1.connect(lowpassFilter);
+ lowpassFilter.connect(dry1);
+ lowpassFilter.connect(wet1);
+ dry1.connect(masterDry);
+ wet1.connect(reverb);
+
+ // Connect source2
+ dry2 = context.createGain();
+ wet2 = context.createGain();
+ source2.connect(waveShaper);
+ waveShaper.connect(dry2);
+ waveShaper.connect(wet2);
+ dry2.connect(masterDry);
+ wet2.connect(reverb);
+
+ // Connect source3
+ dry3 = context.createGain();
+ wet3 = context.createGain();
+ source3.connect(panner);
+ panner.connect(dry3);
+ panner.connect(wet3);
+ dry3.connect(masterDry);
+ wet3.connect(reverb);
+
+ // Start the sources now.
+ source1.start(0);
+ source2.start(0);
+ source3.start(0);
+}
+ </code></pre>
+</div>
+</div>
+</div>
+</div>
+
+</div>
+
+<div id="APIOverview-section" class="section">
+<h2 id="APIOverview">1.3. API Overview</h2>
+</div>
+
+<p>The interfaces defined are: </p>
+<ul>
+ <li>An <a class="dfnref" href="#AudioContext-section">AudioContext</a>
+ interface, which contains an audio signal graph representing connections
+ betweens AudioNodes. </li>
+ <li>An <a class="dfnref" href="#AudioNode-section">AudioNode</a> interface,
+ which represents audio sources, audio outputs, and intermediate processing
+ modules. AudioNodes can be dynamically connected together in a <a
+ href="#ModularRouting-section">modular fashion</a>. <code>AudioNodes</code>
+ exist in the context of an <code>AudioContext</code> </li>
+ <li>An <a class="dfnref"
+ href="#AudioDestinationNode-section">AudioDestinationNode</a> interface, an
+ AudioNode subclass representing the final destination for all rendered
+ audio. </li>
+ <li>An <a class="dfnref" href="#AudioBuffer-section">AudioBuffer</a>
+ interface, for working with memory-resident audio assets. These can
+ represent one-shot sounds, or longer audio clips. </li>
+ <li>An <a class="dfnref"
+ href="#AudioBufferSourceNode-section">AudioBufferSourceNode</a> interface,
+ an AudioNode which generates audio from an AudioBuffer. </li>
+ <li>A <a class="dfnref"
+ href="#MediaElementAudioSourceNode-section">MediaElementAudioSourceNode</a>
+ interface, an AudioNode which is the audio source from an
+ <code>audio</code>, <code>video</code>, or other media element. </li>
+ <li>A <a class="dfnref"
+ href="#MediaStreamAudioSourceNode-section">MediaStreamAudioSourceNode</a>
+ interface, an AudioNode which is the audio source from a
+ MediaStream such as live audio input, or from a remote peer. </li>
+ <li>A <a class="dfnref"
+ href="#MediaStreamAudioDestinationNode-section">MediaStreamAudioDestinationNode</a>
+ interface, an AudioNode which is the audio destination to a
+ MediaStream sent to a remote peer. </li>
+ <li>A <a class="dfnref"
+ href="#ScriptProcessorNode-section">ScriptProcessorNode</a> interface, an
+ AudioNode for generating or processing audio directly in JavaScript. </li>
+ <li>An <a class="dfnref"
+ href="#AudioProcessingEvent-section">AudioProcessingEvent</a> interface,
+ which is an event type used with <code>ScriptProcessorNode</code> objects.
+ </li>
+ <li>An <a class="dfnref" href="#AudioParam-section">AudioParam</a> interface,
+ for controlling an individual aspect of an AudioNode's functioning, such as
+ volume. </li>
+ <li>An <a class="dfnref" href="#GainNode-section">GainNode</a>
+ interface, for explicit gain control. Because inputs to AudioNodes support
+ multiple connections (as a unity-gain summing junction), mixers can be <a
+ href="#MixerGainStructure-section">easily built</a> with GainNodes.
+ </li>
+ <li>A <a class="dfnref" href="#BiquadFilterNode-section">BiquadFilterNode</a>
+ interface, an AudioNode for common low-order filters such as:
+ <ul>
+ <li>Low Pass</li>
+ <li>High Pass </li>
+ <li>Band Pass </li>
+ <li>Low Shelf </li>
+ <li>High Shelf </li>
+ <li>Peaking </li>
+ <li>Notch </li>
+ <li>Allpass </li>
+ </ul>
+ </li>
+ <li>A <a class="dfnref" href="#DelayNode-section">DelayNode</a> interface, an
+ AudioNode which applies a dynamically adjustable variable delay. </li>
+ <li>An <a class="dfnref" href="#PannerNode-section">PannerNode</a>
+ interface, for spatializing / positioning audio in 3D space. </li>
+ <li>An <a class="dfnref" href="#AudioListener-section">AudioListener</a>
+ interface, which works with an <code>PannerNode</code> for
+ spatialization. </li>
+ <li>A <a class="dfnref" href="#ConvolverNode-section">ConvolverNode</a>
+ interface, an AudioNode for applying a <a
+ href="#Convolution-section">real-time linear effect</a> (such as the sound
+ of a concert hall). </li>
+ <li>A <a class="dfnref"
+ href="#AnalyserNode-section">AnalyserNode</a> interface,
+ for use with music visualizers, or other visualization applications. </li>
+ <li>A <a class="dfnref"
+ href="#ChannelSplitterNode-section">ChannelSplitterNode</a> interface,
+ for accessing the individual channels of an audio stream in the routing
+ graph. </li>
+ <li>A <a class="dfnref"
+ href="#ChannelMergerNode-section">ChannelMergerNode</a> interface, for
+ combining channels from multiple audio streams into a single audio stream.
+ </li>
+ <li>A <a
+ href="#DynamicsCompressorNode-section">DynamicsCompressorNode</a> interface, an
+ AudioNode for dynamics compression. </li>
+ <li>A <a class="dfnref" href="#dfn-WaveShaperNode">WaveShaperNode</a>
+ interface, an AudioNode which applies a non-linear waveshaping effect for
+ distortion and other more subtle warming effects. </li>
+ <li>A <a class="dfnref" href="#dfn-OscillatorNode">OscillatorNode</a>
+ interface, an audio source generating a periodic waveform. </li>
+</ul>
+</div>
+
+<div id="conformance-section" class="section">
+<h2 id="conformance">2. Conformance</h2>
+
+<p>Everything in this specification is normative except for examples and
+sections marked as being informative. </p>
+
+<p>The keywords “<span class="rfc2119">MUST</span>”, “<span
+class="rfc2119">MUST NOT</span>”, “<span
+class="rfc2119">REQUIRED</span>”, “<span class="rfc2119">SHALL</span>”,
+“<span class="rfc2119">SHALL NOT</span>”, “<span
+class="rfc2119">RECOMMENDED</span>”, “<span class="rfc2119">MAY</span>”
+and “<span class="rfc2119">OPTIONAL</span>” in this document are to be
+interpreted as described in <cite><a href="http://www.ietf.org/rfc/rfc2119">Key
+words for use in RFCs to Indicate Requirement Levels</a></cite> <a
+href="#RFC2119">[RFC2119]</a>. </p>
+
+<p>The following conformance classes are defined by this specification: </p>
+<dl>
+ <dt><dfn id="dfn-conforming-implementation">conforming
+ implementation</dfn></dt>
+ <dd><p>A user agent is considered to be a <a class="dfnref"
+ href="#dfn-conforming-implementation">conforming implementation</a> if it
+ satisfies all of the <span class="rfc2119">MUST</span>-, <span
+ class="rfc2119">REQUIRED</span>- and <span
+ class="rfc2119">SHALL</span>-level criteria in this specification that
+ apply to implementations. </p>
+ </dd>
+</dl>
+</div>
+
+<div id="terminology-section" class="section">
+
+<div id="API-section-section" class="section">
+<h2 id="API-section">4. The Audio API</h2>
+</div>
+
+<div id="AudioContext-section-section" class="section">
+<h2 id="AudioContext-section">4.1. The AudioContext Interface</h2>
+
+<p>This interface represents a set of <a
+href="#AudioNode-section"><code>AudioNode</code></a> objects and their
+connections. It allows for arbitrary routing of signals to the <a
+href="#AudioDestinationNode-section"><code>AudioDestinationNode</code></a>
+(what the user ultimately hears). Nodes are created from the context and are
+then <a href="#ModularRouting-section">connected</a> together. In most use
+cases, only a single AudioContext is used per document.</p>
+
+<br>
+
+<div class="block">
+
+<div class="blockTitleDiv">
+<span class="blockTitle">Web IDL</span></div>
+
+<div class="blockContent">
+<pre class="code"><code class="idl-code" id="audio-context-idl">
+
+callback DecodeSuccessCallback = void (AudioBuffer decodedData);
+callback DecodeErrorCallback = void ();
+
+[Constructor]
+interface <dfn id="dfn-AudioContext">AudioContext</dfn> : EventTarget {
+
+ readonly attribute AudioDestinationNode destination;
+ readonly attribute float sampleRate;
+ readonly attribute double currentTime;
+ readonly attribute AudioListener listener;
+
+ AudioBuffer createBuffer(unsigned long numberOfChannels, unsigned long length, float sampleRate);
+
+ void decodeAudioData(ArrayBuffer audioData,
+ DecodeSuccessCallback successCallback,
+ optional DecodeErrorCallback errorCallback);
+
+
+ <span class="comment">// AudioNode creation </span>
+ AudioBufferSourceNode createBufferSource();
+
+ MediaElementAudioSourceNode createMediaElementSource(HTMLMediaElement mediaElement);
+
+ MediaStreamAudioSourceNode createMediaStreamSource(MediaStream mediaStream);
+ MediaStreamAudioDestinationNode createMediaStreamDestination();
+
+ ScriptProcessorNode createScriptProcessor(optional unsigned long bufferSize = 0,
+ optional unsigned long numberOfInputChannels = 2,
+ optional unsigned long numberOfOutputChannels = 2);
+
+ AnalyserNode createAnalyser();
+ GainNode createGain();
+ DelayNode createDelay(optional double maxDelayTime = 1.0);
+ BiquadFilterNode createBiquadFilter();
+ WaveShaperNode createWaveShaper();
+ PannerNode createPanner();
+ ConvolverNode createConvolver();
+
+ ChannelSplitterNode createChannelSplitter(optional unsigned long numberOfOutputs = 6);
+ ChannelMergerNode createChannelMerger(optional unsigned long numberOfInputs = 6);
+
+ DynamicsCompressorNode createDynamicsCompressor();
+
+ OscillatorNode createOscillator();
+ PeriodicWave createPeriodicWave(Float32Array real, Float32Array imag);
+
+};
+</code></pre>
+</div>
+</div>
+
+<div id="attributes-AudioContext-section" class="section">
+<h3 id="attributes-AudioContext">4.1.1. Attributes</h3>
+<dl>
+ <dt id="dfn-destination"><code>destination</code></dt>
+ <dd><p>An <a
+ href="#AudioDestinationNode-section"><code>AudioDestinationNode</code></a>
+ with a single input representing the final destination for all audio.
+ Usually this will represent the actual audio hardware.
+ All AudioNodes actively rendering
+ audio will directly or indirectly connect to <code>destination</code>.</p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-sampleRate"><code>sampleRate</code></dt>
+ <dd><p>The sample rate (in sample-frames per second) at which the
+ AudioContext handles audio. It is assumed that all AudioNodes in the
+ context run at this rate. In making this assumption, sample-rate
+ converters or "varispeed" processors are not supported in real-time
+ processing.</p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-currentTime"><code>currentTime</code></dt>
+ <dd><p>This is a time in seconds which starts at zero when the context is
+ created and increases in real-time. All scheduled times are relative to
+ it. This is not a "transport" time which can be started, paused, and
+ re-positioned. It is always moving forward. A GarageBand-like timeline
+ transport system can be very easily built on top of this (in JavaScript).
+ This time corresponds to an ever-increasing hardware timestamp. </p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-listener"><code>listener</code></dt>
+ <dd><p>An <a href="#AudioListener-section"><code>AudioListener</code></a>
+ which is used for 3D <a
+ href="#Spatialization-section">spatialization</a>.</p>
+ </dd>
+</dl>
+</div>
+
+<div id="methodsandparams-AudioContext-section" class="section">
+<h3 id="methodsandparams-AudioContext">4.1.2. Methods and Parameters</h3>
+<dl>
+ <dt id="dfn-createBuffer">The <code>createBuffer</code> method</dt>
+ <dd><p>Creates an AudioBuffer of the given size. The audio data in the
+ buffer will be zero-initialized (silent). An NOT_SUPPORTED_ERR exception will be thrown if
+ the <code>numberOfChannels</code> or <code>sampleRate</code> are out-of-bounds,
+ or if length is 0.</p>
+ <p>The <dfn id="dfn-numberOfChannels">numberOfChannels</dfn> parameter
+ determines how many channels the buffer will have. An implementation must support at least 32 channels. </p>
+ <p>The <dfn id="dfn-length">length</dfn> parameter determines the size of
+ the buffer in sample-frames. </p>
+ <p>The <dfn id="dfn-sampleRate_2">sampleRate</dfn> parameter describes
+ the sample-rate of the linear PCM audio data in the buffer in
+ sample-frames per second. An implementation must support sample-rates in at least the range 22050 to 96000.</p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-decodeAudioData">The <code>decodeAudioData</code> method</dt>
+ <dd><p>Asynchronously decodes the audio file data contained in the
+ ArrayBuffer. The ArrayBuffer can, for example, be loaded from an XMLHttpRequest's
+ <code>response</code> attribute after setting the <code>responseType</code> to "arraybuffer".
+ Audio file data can be in any of the
+ formats supported by the <code>audio</code> element. </p>
+ <p><dfn id="dfn-audioData">audioData</dfn> is an ArrayBuffer containing
+ audio file data.</p>
+ <p><dfn id="dfn-successCallback">successCallback</dfn> is a callback
+ function which will be invoked when the decoding is finished. The single
+ argument to this callback is an AudioBuffer representing the decoded PCM
+ audio data.</p>
+ <p><dfn id="dfn-errorCallback">errorCallback</dfn> is a callback function
+ which will be invoked if there is an error decoding the audio file
+ data.</p>
+
+ <p>
+ The following steps must be performed:
+ </p>
+ <ol>
+
+ <li>Temporarily neuter the <dfn>audioData</dfn> ArrayBuffer in such a way that JavaScript code may not
+ access or modify the data.</li>
+ <li>Queue a decoding operation to be performed on another thread.</li>
+ <li>The decoding thread will attempt to decode the encoded <dfn>audioData</dfn> into linear PCM.
+ If a decoding error is encountered due to the audio format not being recognized or supported, or
+ because of corrupted/unexpected/inconsistent data then the <dfn>audioData</dfn> neutered state
+ will be restored to normal and the <dfn>errorCallback</dfn> will be
+ scheduled to run on the main thread's event loop and these steps will be terminated.</li>
+ <li>The decoding thread will take the result, representing the decoded linear PCM audio data,
+ and resample it to the sample-rate of the AudioContext if it is different from the sample-rate
+ of <dfn>audioData</dfn>. The final result (after possibly sample-rate converting) will be stored
+ in an AudioBuffer.
+ </li>
+ <li>The <dfn>audioData</dfn> neutered state will be restored to normal
+ </li>
+ <li>
+ The <dfn>successCallback</dfn> function will be scheduled to run on the main thread's event loop
+ given the AudioBuffer from step (4) as an argument.
+ </li>
+ </ol>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-createBufferSource">The <code>createBufferSource</code>
+ method</dt>
+ <dd><p>Creates an <a
+ href="#AudioBufferSourceNode-section"><code>AudioBufferSourceNode</code></a>.</p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-createMediaElementSource">The <code>createMediaElementSource</code>
+ method</dt>
+ <dd><p>Creates a <a
+ href="#MediaElementAudioSourceNode-section"><code>MediaElementAudioSourceNode</code></a> given an HTMLMediaElement.
+ As a consequence of calling this method, audio playback from the HTMLMediaElement will be re-routed
+ into the processing graph of the AudioContext.</p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-createMediaStreamSource">The <code>createMediaStreamSource</code>
+ method</dt>
+ <dd><p>Creates a <a
+ href="#MediaStreamAudioSourceNode-section"><code>MediaStreamAudioSourceNode</code></a> given a MediaStream.
+ As a consequence of calling this method, audio playback from the MediaStream will be re-routed
+ into the processing graph of the AudioContext.</p>
+ </dd>
+</dl>
+
+<dl>
+ <dt id="dfn-createMediaStreamDestination">The <code>createMediaStreamDestination</code>
+ method</dt>
+ <dd><p>Creates a <a
+ href="#MediaStreamAudioDestinationNode-section"><code>MediaStreamAudioDestinationNode</code></a>.
+ </p>
+ </dd>
+</dl>
+
+<dl>
+ <dt id="dfn-createScriptProcessor">The <code>createScriptProcessor</code>
+ method</dt>
+ <dd><p>Creates a <a
+ href="#ScriptProcessorNode"><code>ScriptProcessorNode</code></a> for
+ direct audio processing using JavaScript. An INDEX_SIZE_ERR exception MUST be thrown if <code>bufferSize</code> or <code>numberOfInputChannels</code> or <code>numberOfOutputChannels</code>
+ are outside the valid range. </p>
+ <p>The <dfn id="dfn-bufferSize">bufferSize</dfn> parameter determines the
+ buffer size in units of sample-frames. If it's not passed in, or if the
+ value is 0, then the implementation will choose the best buffer size for
+ the given environment, which will be constant power of 2 throughout the lifetime
+ of the node. Otherwise if the author explicitly specifies the bufferSize,
+ it must be one of the following values: 256, 512, 1024, 2048, 4096, 8192,
+ 16384. This value controls how
+ frequently the <code>audioprocess</code> event is dispatched and
+ how many sample-frames need to be processed each call. Lower values for
+ <code>bufferSize</code> will result in a lower (better) <a
+ href="#Latency-section">latency</a>. Higher values will be necessary to
+ avoid audio breakup and <a href="#Glitching-section">glitches</a>.
+ It is recommended for authors to not specify this buffer size and allow
+ the implementation to pick a good buffer size to balance between latency
+ and audio quality.
+ </p>
+ <p>The <dfn id="dfn-numberOfInputChannels">numberOfInputChannels</dfn> parameter (defaults to 2) and
+ determines the number of channels for this node's input. Values of up to 32 must be supported. </p>
+ <p>The <dfn id="dfn-numberOfOutputChannels">numberOfOutputChannels</dfn> parameter (defaults to 2) and
+ determines the number of channels for this node's output. Values of up to 32 must be supported.</p>
+ <p>It is invalid for both <code>numberOfInputChannels</code> and
+ <code>numberOfOutputChannels</code> to be zero. </p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-createAnalyser">The <code>createAnalyser</code> method</dt>
+ <dd><p>Creates a <a
+ href="#AnalyserNode-section"><code>AnalyserNode</code></a>.</p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-createGain">The <code>createGain</code> method</dt>
+ <dd><p>Creates a <a
+ href="#GainNode-section"><code>GainNode</code></a>.</p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-createDelay">The <code>createDelay</code> method</dt>
+ <dd><p>Creates a <a href="#DelayNode-section"><code>DelayNode</code></a>
+ representing a variable delay line. The initial default delay time will
+ be 0 seconds.</p>
+ <p>The <dfn id="dfn-maxDelayTime">maxDelayTime</dfn> parameter is
+ optional and specifies the maximum delay time in seconds allowed for the delay line. If specified, this value MUST be
+ greater than zero and less than three minutes or a NOT_SUPPORTED_ERR exception will be thrown.</p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-createBiquadFilter">The <code>createBiquadFilter</code>
+ method</dt>
+ <dd><p>Creates a <a
+ href="#BiquadFilterNode-section"><code>BiquadFilterNode</code></a>
+ representing a second order filter which can be configured as one of
+ several common filter types.</p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-createWaveShaper">The <code>createWaveShaper</code>
+ method</dt>
+ <dd><p>Creates a <a
+ href="#WaveShaperNode-section"><code>WaveShaperNode</code></a>
+ representing a non-linear distortion.</p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-createPanner">The <code>createPanner</code> method</dt>
+ <dd><p>Creates an <a
+ href="#PannerNode-section"><code>PannerNode</code></a>.</p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-createConvolver">The <code>createConvolver</code> method</dt>
+ <dd><p>Creates a <a
+ href="#ConvolverNode-section"><code>ConvolverNode</code></a>.</p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-createChannelSplitter">The <code>createChannelSplitter</code>
+ method</dt>
+ <dd><p>Creates an <a
+ href="#ChannelSplitterNode-section"><code>ChannelSplitterNode</code></a>
+ representing a channel splitter. An exception will be thrown for invalid parameter values.</p>
+ <p>The <dfn id="dfn-numberOfOutputs">numberOfOutputs</dfn> parameter
+ determines the number of outputs. Values of up to 32 must be supported. If not specified, then 6 will be used. </p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-createChannelMerger">The <code>createChannelMerger</code>
+ method</dt>
+ <dd><p>Creates an <a
+ href="#ChannelMergerNode-section"><code>ChannelMergerNode</code></a>
+ representing a channel merger. An exception will be thrown for invalid parameter values.</p>
+ <p>The <dfn id="dfn-numberOfInputs">numberOfInputs</dfn> parameter
+ determines the number of inputs. Values of up to 32 must be supported. If not specified, then 6 will be used. </p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-createDynamicsCompressor">The
+ <code>createDynamicsCompressor</code> method</dt>
+ <dd><p>Creates a <a
+ href="#DynamicsCompressorNode-section"><code>DynamicsCompressorNode</code></a>.</p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-createOscillator">The
+ <code>createOscillator</code> method</dt>
+ <dd><p>Creates an <a
+ href="#OscillatorNode-section"><code>OscillatorNode</code></a>.</p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-createPeriodicWave">The
+ <code>createPeriodicWave</code> method</dt>
+ <dd><p>Creates a <a
+ href="#PeriodicWave-section"><code>PeriodicWave</code></a> representing a waveform containing arbitrary harmonic content.
+ The <code>real</code> and <code>imag</code> parameters must be of type <code>Float32Array</code> of equal
+ lengths greater than zero and less than or equal to 4096 or an exception will be thrown.
+ These parameters specify the Fourier coefficients of a
+ <a href="http://en.wikipedia.org/wiki/Fourier_series">Fourier series</a> representing the partials of a periodic waveform.
+ The created PeriodicWave will be used with an <a href="#OscillatorNode-section"><code>OscillatorNode</code></a>
+ and will represent a <em>normalized</em> time-domain waveform having maximum absolute peak value of 1.
+ Another way of saying this is that the generated waveform of an <a href="#OscillatorNode-section"><code>OscillatorNode</code></a>
+ will have maximum peak value at 0dBFS. Conveniently, this corresponds to the full-range of the signal values used by the Web Audio API.
+ Because the PeriodicWave will be normalized on creation, the <code>real</code> and <code>imag</code> parameters
+ represent <em>relative</em> values.
+ </p>
+ <p>The <dfn id="dfn-real">real</dfn> parameter represents an array of <code>cosine</code> terms (traditionally the A terms).
+ In audio terminology, the first element (index 0) is the DC-offset of the periodic waveform and is usually set to zero.
+ The second element (index 1) represents the fundamental frequency. The third element represents the first overtone, and so on.</p>
+ <p>The <dfn id="dfn-imag">imag</dfn> parameter represents an array of <code>sine</code> terms (traditionally the B terms).
+ The first element (index 0) should be set to zero (and will be ignored) since this term does not exist in the Fourier series.
+ The second element (index 1) represents the fundamental frequency. The third element represents the first overtone, and so on.</p>
+ </dd>
+</dl>
+</div>
+</div>
+
+<h3 id="lifetime-AudioContext">4.1.3. Lifetime</h3>
+<p class="norm">This section is informative.</p>
+
+<p>
+Once created, an <code>AudioContext</code> will continue to play sound until it has no more sound to play, or
+the page goes away.
+</p>
+
+<div id="OfflineAudioContext-section-section" class="section">
+<h2 id="OfflineAudioContext-section">4.1b. The OfflineAudioContext Interface</h2>
+<p>
+OfflineAudioContext is a particular type of AudioContext for rendering/mixing-down (potentially) faster than real-time.
+It does not render to the audio hardware, but instead renders as quickly as possible, calling a completion event handler
+with the result provided as an AudioBuffer.
+</p>
+
+
+<p>
+</p>
+
+<div class="block">
+
+<div class="blockTitleDiv">
+<span class="blockTitle">Web IDL</span></div>
+
+<div class="blockContent">
+<pre class="code"><code class="idl-code" id="offline-audio-context-idl">
+[Constructor(unsigned long numberOfChannels, unsigned long length, float sampleRate)]
+interface <dfn id="dfn-OfflineAudioContext">OfflineAudioContext</dfn> : AudioContext {
+
+ void startRendering();
+
+ attribute EventHandler oncomplete;
+
+};
+</code></pre>
+</div>
+</div>
+
+
+<div id="attributes-OfflineAudioContext-section" class="section">
+<h3 id="attributes-OfflineAudioContext">4.1b.1. Attributes</h3>
+<dl>
+ <dt id="dfn-oncomplete"><code>oncomplete</code></dt>
+ <dd><p>An EventHandler of type <a href="#OfflineAudioCompletionEvent-section">OfflineAudioCompletionEvent</a>.</p>
+ </dd>
+</dl>
+</div>
+
+
+<div id="methodsandparams-OfflineAudioContext-section" class="section">
+<h3 id="methodsandparams-OfflineAudioContext">4.1b.2. Methods and Parameters</h3>
+<dl>
+ <dt id="dfn-startRendering">The <code>startRendering</code>
+ method</dt>
+ <dd><p>Given the current connections and scheduled changes, starts rendering audio. The
+ <code>oncomplete</code> handler will be called once the rendering has finished.
+ This method must only be called one time or an exception will be thrown.</p>
+ </dd>
+</dl>
+</div>
+
+
+<div id="OfflineAudioCompletionEvent-section" class="section">
+<h2 id="OfflineAudioCompletionEvent">4.1c. The OfflineAudioCompletionEvent Interface</h2>
+
+<p>This is an <code>Event</code> object which is dispatched to <a
+href="#OfflineAudioContext-section"><code>OfflineAudioContext</code></a>. </p>
+
+
+<div class="block">
+
+<div class="blockTitleDiv">
+<span class="blockTitle">Web IDL</span></div>
+
+<div class="blockContent">
+<pre class="code"><code class="idl-code" id="offline-audio-completion-event-idl">
+
+interface <dfn id="dfn-OfflineAudioCompletionEvent">OfflineAudioCompletionEvent</dfn> : Event {
+
+ readonly attribute AudioBuffer renderedBuffer;
+
+};
+</code></pre>
+</div>
+</div>
+
+<div id="attributes-OfflineAudioCompletionEvent-section" class="section">
+<h3 id="attributes-OfflineAudioCompletionEvent">4.1c.1. Attributes</h3>
+<dl>
+ <dt id="dfn-renderedBuffer"><code>renderedBuffer</code></dt>
+ <dd><p>An AudioBuffer containing the rendered audio data once an OfflineAudioContext has finished rendering.
+ It will have a number of channels equal to the <code>numberOfChannels</code> parameter
+ of the OfflineAudioContext constructor.</p>
+ </dd>
+</dl>
+</div>
+</div>
+
+
+<div id="AudioNode-section-section" class="section">
+<h2 id="AudioNode-section">4.2. The AudioNode Interface</h2>
+
+<p>AudioNodes are the building blocks of an <a
+href="#AudioContext-section"><code>AudioContext</code></a>. This interface
+represents audio sources, the audio destination, and intermediate processing
+modules. These modules can be connected together to form <a
+href="#ModularRouting-section">processing graphs</a> for rendering audio to the
+audio hardware. Each node can have <dfn>inputs</dfn> and/or <dfn>outputs</dfn>.
+A <dfn>source node</dfn> has no inputs
+and a single output. An <a
+href="#AudioDestinationNode-section"><code>AudioDestinationNode</code></a> has
+one input and no outputs and represents the final destination to the audio
+hardware. Most processing nodes such as filters will have one input and one
+output. Each type of <code>AudioNode</code> differs in the details of how it processes or synthesizes audio. But, in general, <code>AudioNodes</code>
+will process its inputs (if it has any), and generate audio for its outputs (if it has any).
+ </p>
+
+<p>
+Each <dfn>output</dfn> has one or more <dfn>channels</dfn>. The exact number of channels depends on the details of the specific AudioNode.
+</p>
+
+<p>
+An output may connect to one or more <code>AudioNode</code> inputs, thus <em>fan-out</em> is supported. An input initially has no connections,
+but may be connected from one
+or more <code>AudioNode</code> outputs, thus <em>fan-in</em> is supported. When the <code>connect()</code> method is called to connect
+an output of an AudioNode to an input of an AudioNode, we call that a <dfn>connection</dfn> to the input.
+</p>
+
+<p>
+Each AudioNode <dfn>input</dfn> has a specific number of channels at any given time. This number can change depending on the <dfn>connection(s)</dfn>
+made to the input. If the input has no connections then it has one channel which is silent.
+</p>
+
+<p>
+For each <dfn>input</dfn>, an <code>AudioNode</code> performs a mixing (usually an up-mixing) of all connections to that input.
+
+Please see <a href="#MixerGainStructure-section">Mixer Gain Structure</a> for more informative details, and the <a href="#UpMix-section">Channel up-mixing and down-mixing</a>
+ section for normative requirements.
+
+</p>
+
+<p>
+For performance reasons, practical implementations will need to use block processing, with each <code>AudioNode</code> processing a
+fixed number of sample-frames of size <em>block-size</em>. In order to get uniform behavior across implementations, we will define this
+value explicitly. <em>block-size</em> is defined to be 128 sample-frames which corresponds to roughly 3ms at a sample-rate of 44.1KHz.
+</p>
+
+<p>
+AudioNodes are <em>EventTarget</em>s, as described in <cite><a href="http://dom.spec.whatwg.org/">DOM</a></cite>
+<a href="#DOM">[DOM]</a>. This means that it is possible to dispatch events to AudioNodes the same
+way that other EventTargets accept events.
+</p>
+
+<div class="block">
+
+<div class="blockTitleDiv">
+<span class="blockTitle">Web IDL</span></div>
+
+<div class="blockContent">
+<pre class="code"><code class="idl-code" id="audio-node-idl">
+
+enum <dfn>ChannelCountMode</dfn> {
+ "max",
+ "clamped-max",
+ "explicit"
+};
+
+enum <dfn>ChannelInterpretation</dfn> {
+ "speakers",
+ "discrete"
+};
+
+interface <dfn id="dfn-AudioNode">AudioNode</dfn> : EventTarget {
+
+ void connect(AudioNode destination, optional unsigned long output = 0, optional unsigned long input = 0);
+ void connect(AudioParam destination, optional unsigned long output = 0);
+ void disconnect(optional unsigned long output = 0);
+
+ readonly attribute AudioContext context;
+ readonly attribute unsigned long numberOfInputs;
+ readonly attribute unsigned long numberOfOutputs;
+
+ // Channel up-mixing and down-mixing rules for all inputs.
+ attribute unsigned long channelCount;
+ attribute ChannelCountMode channelCountMode;
+ attribute ChannelInterpretation channelInterpretation;
+
+};
+</code></pre>
+</div>
+</div>
+
+<div id="attributes-AudioNode-section" class="section">
+<h3 id="attributes-AudioNode">4.2.1. Attributes</h3>
+<dl>
+ <dt id="dfn-context"><code>context</code></dt>
+ <dd><p>The AudioContext which owns this AudioNode.</p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-numberOfInputs_2"><code>numberOfInputs</code></dt>
+ <dd><p>The number of inputs feeding into the AudioNode. For <dfn>source nodes</dfn>,
+ this will be 0.</p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-numberOfOutputs_2"><code>numberOfOutputs</code></dt>
+ <dd><p>The number of outputs coming out of the AudioNode. This will be 0
+ for an AudioDestinationNode.</p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-channelCount"><code>channelCount</code><dt>
+ <dd><p>The number of channels used when up-mixing and down-mixing connections to any inputs to the node. The default value is 2
+ except for specific nodes where its value is specially determined.
+ This attribute has no effect for nodes with no inputs.
+ If this value is set to zero, the implementation MUST raise the
+ NOT_SUPPORTED_ERR exception.</p>
+ <p>See the <a href="#UpMix-section">Channel up-mixing and down-mixing</a>
+ section for more information on this attribute.</p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-channelCountMode"><code>channelCountMode</code><dt>
+ <dd><p>Determines how channels will be counted when up-mixing and down-mixing connections to any inputs to the node
+ . This attribute has no effect for nodes with no inputs.</p>
+ <p>See the <a href="#UpMix-section">Channel up-mixing and down-mixing</a>
+ section for more information on this attribute.</p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-channelInterpretation"><code>channelInterpretation</code><dt>
+ <dd><p>Determines how individual channels will be treated when up-mixing and down-mixing connections to any inputs to the node.
+ This attribute has no effect for nodes with no inputs.</p>
+ <p>See the <a href="#UpMix-section">Channel up-mixing and down-mixing</a>
+ section for more information on this attribute.</p>
+ </dd>
+</dl>
+</div>
+
+<div id="methodsandparams-AudioNode-section" class="section">
+<h3 id="methodsandparams-AudioNode">4.2.2. Methods and Parameters</h3>
+<dl>
+ <dt id="dfn-connect-AudioNode">The <code>connect</code> to AudioNode method</dt>
+ <dd><p>Connects the AudioNode to another AudioNode.</p>
+ <p>The <dfn id="dfn-destination_2">destination</dfn> parameter is the
+ AudioNode to connect to.</p>
+ <p>The <dfn id="dfn-output_2">output</dfn> parameter is an index
+ describing which output of the AudioNode from which to connect. An
+ out-of-bound value throws an exception.</p>
+ <p>The <dfn id="dfn-input_2">input</dfn> parameter is an index describing
+ which input of the destination AudioNode to connect to. An out-of-bound
+ value throws an exception. </p>
+ <p>It is possible to connect an AudioNode output to more than one input
+ with multiple calls to connect(). Thus, "fan-out" is supported. </p>
+ <p>
+ It is possible to connect an AudioNode to another AudioNode which creates a <em>cycle</em>.
+ In other words, an AudioNode may connect to another AudioNode, which in turn connects back
+ to the first AudioNode. This is allowed only if there is at least one
+ <a class="dfnref" href="#DelayNode-section">DelayNode</a> in the <em>cycle</em> or an exception will
+ be thrown.
+ </p>
+
+ <p>
+ There can only be one connection between a given output of one specific node and a given input of another specific node.
+ Multiple connections with the same termini are ignored. For example:
+ </p>
+
+ <pre>
+ nodeA.connect(nodeB);
+ nodeA.connect(nodeB);
+
+ will have the same effect as
+
+ nodeA.connect(nodeB);
+ </pre>
+
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-connect-AudioParam">The <code>connect</code> to AudioParam method</dt>
+ <dd><p>Connects the AudioNode to an AudioParam, controlling the parameter
+ value with an audio-rate signal.
+ </p>
+
+ <p>The <dfn id="dfn-destination_3">destination</dfn> parameter is the
+ AudioParam to connect to.</p>
+ <p>The <dfn id="dfn-output_3-destination">output</dfn> parameter is an index
+ describing which output of the AudioNode from which to connect. An
+ out-of-bound value throws an exception.</p>
+
+ <p>It is possible to connect an AudioNode output to more than one AudioParam
+ with multiple calls to connect(). Thus, "fan-out" is supported. </p>
+ <p>It is possible to connect more than one AudioNode output to a single AudioParam
+ with multiple calls to connect(). Thus, "fan-in" is supported. </p>
+ <p>An AudioParam will take the rendered audio data from any AudioNode output connected to it and <a href="#down-mix">convert it to mono</a> by down-mixing if it is not
+ already mono, then mix it together with other such outputs and finally will mix with the <em>intrinsic</em>
+ parameter value (the value the AudioParam would normally have without any audio connections), including any timeline changes
+ scheduled for the parameter. </p>
+
+ <p>
+ There can only be one connection between a given output of one specific node and a specific AudioParam.
+ Multiple connections with the same termini are ignored. For example:
+ </p>
+
+ <pre>
+ nodeA.connect(param);
+ nodeA.connect(param);
+
+ will have the same effect as
+
+ nodeA.connect(param);
+ </pre>
+
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-disconnect">The <code>disconnect</code> method</dt>
+ <dd><p>Disconnects an AudioNode's output.</p>
+ <p>The <dfn id="dfn-output_3-disconnect">output</dfn> parameter is an index
+ describing which output of the AudioNode to disconnect. An out-of-bound
+ value throws an exception.</p>
+ </dd>
+</dl>
+</div>
+</div>
+
+<h3 id="lifetime-AudioNode">4.2.3. Lifetime</h3>
+
+<p class="norm">This section is informative.</p>
+
+<p>An implementation may choose any method to avoid unnecessary resource usage and unbounded memory growth of unused/finished
+nodes. The following is a description to help guide the general expectation of how node lifetime would be managed.
+</p>
+
+<p>
+An <code>AudioNode</code> will live as long as there are any references to it. There are several types of references:
+</p>
+
+<ol>
+<li>A <em>normal</em> JavaScript reference obeying normal garbage collection rules. </li>
+<li>A <em>playing</em> reference for both <code>AudioBufferSourceNodes</code> and <code>OscillatorNodes</code>.
+These nodes maintain a <em>playing</em>
+reference to themselves while they are currently playing.</li>
+<li>A <em>connection</em> reference which occurs if another <code>AudioNode</code> is connected to it. </li>
+<li>A <em>tail-time</em> reference which an <code>AudioNode</code> maintains on itself as long as it has
+any internal processing state which has not yet been emitted. For example, a <code>ConvolverNode</code> has
+a tail which continues to play even after receiving silent input (think about clapping your hands in a large concert
+ hall and continuing to hear the sound reverberate throughout the hall). Some <code>AudioNodes</code> have this
+ property. Please see details for specific nodes.</li>
+</ol>
+
+<p>
+Any <code>AudioNodes</code> which are connected in a cycle <em>and</em> are directly or indirectly connected to the
+<code>AudioDestinationNode</code> of the <code>AudioContext</code> will stay alive as long as the <code>AudioContext</code> is alive.
+</p>
+
+<p>
+When an <code>AudioNode</code> has no references it will be deleted. But before it is deleted, it will disconnect itself
+from any other <code>AudioNodes</code> which it is connected to. In this way it releases all connection references (3) it has to other nodes.
+</p>
+
+<p>
+Regardless of any of the above references, it can be assumed that the <code>AudioNode</code> will be deleted when its <code>AudioContext</code> is deleted.
+</p>
+
+
+<div id="AudioDestinationNode-section" class="section">
+<h2 id="AudioDestinationNode">4.4. The AudioDestinationNode Interface</h2>
+
+<p>This is an <a href="#AudioNode-section"><code>AudioNode</code></a>
+representing the final audio destination and is what the user will ultimately
+hear. It can often be considered as an audio output device which is connected to
+speakers. All rendered audio to be heard will be routed to this node, a
+"terminal" node in the AudioContext's routing graph. There is only a single
+AudioDestinationNode per AudioContext, provided through the
+<code>destination</code> attribute of <a
+href="#AudioContext-section"><code>AudioContext</code></a>. </p>
+<pre>
+ numberOfInputs : 1
+ numberOfOutputs : 0
+
+ channelCount = 2;
+ channelCountMode = "explicit";
+ channelInterpretation = "speakers";
+</pre>
+
+<div class="block">
+
+<div class="blockTitleDiv">
+<span class="blockTitle">Web IDL</span></div>
+
+<div class="blockContent">
+<pre class="code"><code class="idl-code" id="audio-destination-node-idl">
+
+interface <dfn id="dfn-AudioDestinationNode">AudioDestinationNode</dfn> : AudioNode {
+
+ readonly attribute unsigned long maxChannelCount;
+
+};
+</code></pre>
+</div>
+</div>
+
+<div id="attributes-AudioDestinationNode-section" class="section">
+<h3 id="attributes-AudioDestinationNode">4.4.1. Attributes</h3>
+<dl>
+ <dt id="dfn-maxChannelCount"><code>maxChannelCount</code></dt>
+ <dd><p>The maximum number of channels that the <code>channelCount</code> attribute can be set to.
+ An <code>AudioDestinationNode</code> representing the audio hardware end-point (the normal case) can potentially output more than
+ 2 channels of audio if the audio hardware is multi-channel. <code>maxChannelCount</code> is the maximum number of channels that
+ this hardware is capable of supporting. If this value is 0, then this indicates that <code>channelCount</code> may not be
+ changed. This will be the case for an <code>AudioDestinationNode</code> in an <code>OfflineAudioContext</code> and also for
+ basic implementations with hardware support for stereo output only.</p>
+
+ <p><code>channelCount</code> defaults to 2 for a destination in a normal AudioContext, and may be set to any non-zero value less than or equal
+ to <code>maxChannelCount</code>. An exception will be thrown if this value is not within the valid range. Giving a concrete example, if
+ the audio hardware supports 8-channel output, then we may set <code>numberOfChannels</code> to 8, and render 8-channels of output.
+ </p>
+
+ <p>
+ For an AudioDestinationNode in an OfflineAudioContext, the <code>channelCount</code> is determined when the offline context is created and this value
+ may not be changed.
+ </p>
+
+ </dd>
+</dl>
+
+</div>
+</div>
+
+<div id="AudioParam-section" class="section">
+<h2 id="AudioParam">4.5. The AudioParam Interface</h2>
+
+<p>AudioParam controls an individual aspect of an <a
+href="#AudioNode-section"><code>AudioNode</code></a>'s functioning, such as
+volume. The parameter can be set immediately to a particular value using the
+"value" attribute. Or, value changes can be scheduled to happen at
+very precise times (in the coordinate system of AudioContext.currentTime), for envelopes, volume fades, LFOs, filter sweeps, grain
+windows, etc. In this way, arbitrary timeline-based automation curves can be
+set on any AudioParam. Additionally, audio signals from the outputs of <code>AudioNodes</code> can be connected
+to an <code>AudioParam</code>, summing with the <em>intrinsic</em> parameter value.
+</p>
+
+<p>
+Some synthesis and processing <code>AudioNodes</code> have <code>AudioParams</code> as attributes whose values must
+ be taken into account on a per-audio-sample basis.
+For other <code>AudioParams</code>, sample-accuracy is not important and the value changes can be sampled more coarsely.
+Each individual <code>AudioParam</code> will specify that it is either an <em>a-rate</em> parameter
+which means that its values must be taken into account on a per-audio-sample basis, or it is a <em>k-rate</em> parameter.
+</p>
+
+<p>
+Implementations must use block processing, with each <code>AudioNode</code>
+processing 128 sample-frames in each block.
+</p>
+
+<p>
+For each 128 sample-frame block, the value of a <em>k-rate</em> parameter must
+be sampled at the time of the very first sample-frame, and that value must be
+used for the entire block. <em>a-rate</em> parameters must be sampled for each
+sample-frame of the block.
+</p>
+
+
+<div class="block">
+
+<div class="blockTitleDiv">
+<span class="blockTitle">Web IDL</span></div>
+
+<div class="blockContent">
+<pre class="code"><code class="idl-code" id="audio-param-idl">
+
+interface <dfn id="dfn-AudioParam">AudioParam</dfn> {
+
+ attribute float value;
+ readonly attribute float defaultValue;
+
+ <span class="comment">// Parameter automation. </span>
+ void setValueAtTime(float value, double startTime);
+ void linearRampToValueAtTime(float value, double endTime);
+ void exponentialRampToValueAtTime(float value, double endTime);
+
+ <span class="comment">// Exponentially approach the target value with a rate having the given time constant. </span>
+ void setTargetAtTime(float target, double startTime, double timeConstant);
+
+ <span class="comment">// Sets an array of arbitrary parameter values starting at time for the given duration. </span>
+ <span class="comment">// The number of values will be scaled to fit into the desired duration. </span>
+ void setValueCurveAtTime(Float32Array values, double startTime, double duration);
+
+ <span class="comment">// Cancels all scheduled parameter changes with times greater than or equal to startTime. </span>
+ void cancelScheduledValues(double startTime);
+
+};
+</code></pre>
+</div>
+</div>
+
+
+
+<div id="attributes-AudioParam-section" class="section">
+<h3 id="attributes-AudioParam">4.5.1. Attributes</h3>
+
+<dl>
+ <dt id="dfn-value"><code>value</code></dt>
+ <dd><p>The parameter's floating-point value. This attribute is initialized to the
+ <code>defaultValue</code>. If a value is set during a time when there are any automation events scheduled then
+ it will be ignored and no exception will be thrown.</p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-defaultValue"><code>defaultValue</code></dt>
+ <dd><p>Initial value for the value attribute</p>
+ </dd>
+</dl>
+</div>
+
+<div id="methodsandparams-AudioParam-section" class="section">
+<h3 id="methodsandparams-AudioParam">4.5.2. Methods and Parameters</h3>
+
+<p>
+An <code>AudioParam</code> maintains a time-ordered event list which is initially empty. The times are in
+the time coordinate system of AudioContext.currentTime. The events define a mapping from time to value. The following methods
+can change the event list by adding a new event into the list of a type specific to the method. Each event
+has a time associated with it, and the events will always be kept in time-order in the list. These
+methods will be called <em>automation</em> methods:</p>
+
+<ul>
+<li>setValueAtTime() - <em>SetValue</em></li>
+<li>linearRampToValueAtTime() - <em>LinearRampToValue</em></li>
+<li>exponentialRampToValueAtTime() - <em>ExponentialRampToValue</em></li>
+<li>setTargetAtTime() - <em>SetTarget</em></li>
+<li>setValueCurveAtTime() - <em>SetValueCurve</em></li>
+</ul>
+
+<p>
+The following rules will apply when calling these methods:
+</p>
+<ul>
+<li>If one of these events is added at a time where there is already an event of the exact same type, then the new event will replace the old
+one.</li>
+<li>If one of these events is added at a time where there is already one or more events of a different type, then it will be
+placed in the list after them, but before events whose times are after the event. </li>
+<li>If setValueCurveAtTime() is called for time T and duration D and there are any events having a time greater than T, but less than
+T + D, then an exception will be thrown. In other words, it's not ok to schedule a value curve during a time period containing other events.</li>
+<li>Similarly an exception will be thrown if any <em>automation</em> method is called at a time which is inside of the time interval
+of a <em>SetValueCurve</em> event at time T and duration D.</li>
+</ul>
+<p>
+</p>
+
+<dl>
+ <dt id="dfn-setValueAtTime">The <code>setValueAtTime</code> method</dt>
+ <dd><p>Schedules a parameter value change at the given time.</p>
+ <p>The <dfn id="dfn-value_2">value</dfn> parameter is the value the
+ parameter will change to at the given time.</p>
+ <p>The <dfn id="dfn-startTime_2">startTime</dfn> parameter is the time in the same time coordinate system as AudioContext.currentTime.</p>
+ <p>
+ If there are no more events after this <em>SetValue</em> event, then for t >= startTime, v(t) = value. In other words, the value will remain constant.
+ </p>
+ <p>
+ If the next event (having time T1) after this <em>SetValue</em> event is not of type <em>LinearRampToValue</em> or <em>ExponentialRampToValue</em>,
+ then, for t: startTime &lt;= t &lt; T1, v(t) = value.
+ In other words, the value will remain constant during this time interval, allowing the creation of "step" functions.
+ </p>
+ <p>
+ If the next event after this <em>SetValue</em> event is of type <em>LinearRampToValue</em> or <em>ExponentialRampToValue</em> then please
+ see details below.
+ </p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-linearRampToValueAtTime">The <code>linearRampToValueAtTime</code>
+ method</dt>
+ <dd><p>Schedules a linear continuous change in parameter value from the
+ previous scheduled parameter value to the given value.</p>
+ <p>The <dfn id="dfn-value_3">value</dfn> parameter is the value the
+ parameter will linearly ramp to at the given time.</p>
+ <p>The <dfn id="dfn-endTime_3">endTime</dfn> parameter is the time in the same time coordinate system as AudioContext.currentTime.</p>
+
+ <p>
+ The value during the time interval T0 &lt;= t &lt; T1 (where T0 is the time of the previous event and T1 is the endTime parameter passed into this method)
+ will be calculated as:
+ </p>
+ <pre>
+ v(t) = V0 + (V1 - V0) * ((t - T0) / (T1 - T0))
+ </pre>
+ <p>
+ Where V0 is the value at the time T0 and V1 is the value parameter passed into this method.
+ </p>
+ <p>
+ If there are no more events after this LinearRampToValue event then for t >= T1, v(t) = V1
+ </p>
+
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-exponentialRampToValueAtTime">The
+ <code>exponentialRampToValueAtTime</code> method</dt>
+ <dd><p>Schedules an exponential continuous change in parameter value from
+ the previous scheduled parameter value to the given value. Parameters
+ representing filter frequencies and playback rate are best changed
+ exponentially because of the way humans perceive sound. </p>
+ <p>The <dfn id="dfn-value_4">value</dfn> parameter is the value the
+ parameter will exponentially ramp to at the given time. An exception will be thrown if this value is less than
+ or equal to 0, or if the value at the time of the previous event is less than or equal to 0.</p>
+ <p>The <dfn id="dfn-endTime_4">endTime</dfn> parameter is the time in the same time coordinate system as AudioContext.currentTime.</p>
+ <p>
+ The value during the time interval T0 &lt;= t &lt; T1 (where T0 is the time of the previous event and T1 is the endTime parameter passed into this method)
+ will be calculated as:
+ </p>
+ <pre>
+ v(t) = V0 * (V1 / V0) ^ ((t - T0) / (T1 - T0))
+ </pre>
+ <p>
+ Where V0 is the value at the time T0 and V1 is the value parameter passed into this method.
+ </p>
+ <p>
+ If there are no more events after this ExponentialRampToValue event then for t >= T1, v(t) = V1
+ </p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-setTargetAtTime">The <code>setTargetAtTime</code>
+ method</dt>
+ <dd><p>Start exponentially approaching the target value at the given time
+ with a rate having the given time constant. Among other uses, this is
+ useful for implementing the "decay" and "release" portions of an ADSR
+ envelope. Please note that the parameter value does not immediately
+ change to the target value at the given time, but instead gradually
+ changes to the target value.</p>
+ <p>The <dfn id="dfn-target">target</dfn> parameter is the value
+ the parameter will <em>start</em> changing to at the given time.</p>
+ <p>The <dfn id="dfn-startTime">startTime</dfn> parameter is the time in the same time coordinate system as AudioContext.currentTime.</p>
+ <p>The <dfn id="dfn-timeConstant">timeConstant</dfn> parameter is the
+ time-constant value of first-order filter (exponential) approach to the
+ target value. The larger this value is, the slower the transition will
+ be.</p>
+ <p>
+ More precisely, <em>timeConstant</em> is the time it takes a first-order linear continuous time-invariant system
+ to reach the value 1 - 1/e (around 63.2%) given a step input response (transition from 0 to 1 value).
+ </p>
+ <p>
+ During the time interval: <em>T0</em> &lt;= t &lt; <em>T1</em>, where T0 is the <em>startTime</em> parameter and T1 represents the time of the event following this
+ event (or <em>infinity</em> if there are no following events):
+ </p>
+ <pre>
+ v(t) = V1 + (V0 - V1) * exp(-(t - T0) / <em>timeConstant</em>)
+ </pre>
+ <p>
+ Where V0 is the initial value (the .value attribute) at T0 (the <em>startTime</em> parameter) and V1 is equal to the <em>target</em>
+ parameter.
+ </p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-setValueCurveAtTime">The <code>setValueCurveAtTime</code>
+ method</dt>
+ <dd><p>Sets an array of arbitrary parameter values starting at the given
+ time for the given duration. The number of values will be scaled to fit
+ into the desired duration. </p>
+ <p>The <dfn id="dfn-values">values</dfn> parameter is a Float32Array
+ representing a parameter value curve. These values will apply starting at
+ the given time and lasting for the given duration. </p>
+ <p>The <dfn id="dfn-startTime_5">startTime</dfn> parameter is the time in the same time coordinate system as AudioContext.currentTime.</p>
+ <p>The <dfn id="dfn-duration_5">duration</dfn> parameter is the
+ amount of time in seconds (after the <em>time</em> parameter) where values will be calculated according to the <em>values</em> parameter..</p>
+ <p>
+ During the time interval: <em>startTime</em> &lt;= t &lt; <em>startTime</em> + <em>duration</em>, values will be calculated:
+ </p>
+ <pre>
+ v(t) = values[N * (t - startTime) / duration], where <em>N</em> is the length of the <em>values</em> array.
+ </pre>
+ <p>
+ After the end of the curve time interval (t >= <em>startTime</em> + <em>duration</em>), the value will remain constant at the final curve value,
+ until there is another automation event (if any).
+ </p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-cancelScheduledValues">The <code>cancelScheduledValues</code>
+ method</dt>
+ <dd><p>Cancels all scheduled parameter changes with times greater than or
+ equal to startTime.</p>
+ <p>The <dfn>startTime</dfn> parameter is the starting
+ time at and after which any previously scheduled parameter changes will
+ be cancelled. It is a time in the same time coordinate system as AudioContext.currentTime.</p>
+ </dd>
+</dl>
+</div>
+</div>
+
+
+
+<div id="computedValue-AudioParam-section" class="section">
+<h3>4.5.3. Computation of Value</h3>
+
+<p>
+<dfn>computedValue</dfn> is the final value controlling the audio DSP and is computed by the audio rendering thread during each rendering time quantum.
+ It must be internally computed as follows:
+</p>
+
+<ol>
+<li>An <em>intrinsic</em> parameter value will be calculated at each time, which is either the value set directly to the .value attribute,
+or, if there are any scheduled parameter changes (automation events) with times before or at this time,
+the value as calculated from these events. If the .value attribute
+is set after any automation events have been scheduled, then these events will be removed. When read, the .value attribute
+always returns the <em>intrinsic</em> value for the current time. If automation events are removed from a given time range, then the
+<em>intrinsic</em> value will remain unchanged and stay at its previous value until either the .value attribute is directly set, or automation events are added
+for the time range.
+</li>
+
+<li>
+An AudioParam will take the rendered audio data from any AudioNode output connected to it and <a href="#down-mix">convert it to mono</a> by down-mixing if it is not
+already mono, then mix it together with other such outputs. If there are no AudioNodes connected to it, then this value is 0, having no
+effect on the <em>computedValue</em>.
+</li>
+
+<li>
+The <em>computedValue</em> is the sum of the <em>intrinsic</em> value and the value calculated from (2).
+</li>
+
+</ol>
+
+</div>
+
+
+<div id="example1-AudioParam-section" class="section">
+<h3 id="example1-AudioParam">4.5.4. AudioParam Automation Example</h3>
+
+
+
+<div class="example">
+
+<div class="exampleHeader">
+Example</div>
+<img alt="AudioParam automation" src="images/audioparam-automation1.png" />
+
+<div class="block">
+
+<div class="blockTitleDiv">
+<span class="blockTitle">ECMAScript</span></div>
+
+<div class="blockContent">
+<pre class="code"><code class="es-code">
+var t0 = 0;
+var t1 = 0.1;
+var t2 = 0.2;
+var t3 = 0.3;
+var t4 = 0.4;
+var t5 = 0.6;
+var t6 = 0.7;
+var t7 = 1.0;
+
+var curveLength = 44100;
+var curve = new Float32Array(curveLength);
+for (var i = 0; i &lt; curveLength; ++i)
+ curve[i] = Math.sin(Math.PI * i / curveLength);
+
+param.setValueAtTime(0.2, t0);
+param.setValueAtTime(0.3, t1);
+param.setValueAtTime(0.4, t2);
+param.linearRampToValueAtTime(1, t3);
+param.linearRampToValueAtTime(0.15, t4);
+param.exponentialRampToValueAtTime(0.75, t5);
+param.exponentialRampToValueAtTime(0.05, t6);
+param.setValueCurveAtTime(curve, t6, t7 - t6);
+</code></pre>
+</div>
+</div>
+</div>
+</div>
+
+<div id="GainNode-section" class="section">
+<h2 id="GainNode">4.7. The GainNode Interface</h2>
+
+<p>Changing the gain of an audio signal is a fundamental operation in audio
+applications. The <code>GainNode</code> is one of the building blocks for creating <a
+href="#MixerGainStructure-section">mixers</a>.
+This interface is an AudioNode with a single input and single
+output: </p>
+<pre>
+ numberOfInputs : 1
+ numberOfOutputs : 1
+
+ channelCountMode = "max";
+ channelInterpretation = "speakers";
+</pre>
+
+<p>It multiplies the input audio signal by the (possibly time-varying) <code>gain</code> attribute, copying the result to the output.
+ By default, it will take the input and pass it through to the output unchanged, which represents a constant gain change
+ of 1.
+</p>
+
+<p>
+As with other <code>AudioParams</code>, the <code>gain</code> parameter represents a mapping from time
+(in the coordinate system of AudioContext.currentTime) to floating-point value.
+
+Every PCM audio sample in the input is multiplied by the <code>gain</code> parameter's value for the specific time
+corresponding to that audio sample. This multiplied value represents the PCM audio sample for the output.
+</p>
+
+<p>
+The number of channels of the output will always equal the number of channels of the input, with each channel
+of the input being multiplied by the <code>gain</code> values and being copied into the corresponding channel
+of the output.
+</p>
+
+<p>
+ The implementation must make
+gain changes to the audio stream smoothly, without introducing noticeable
+clicks or glitches. This process is called "de-zippering". </p>
+
+<div class="block">
+
+<div class="blockTitleDiv">
+<span class="blockTitle">Web IDL</span></div>
+
+<div class="blockContent">
+<pre class="code"><code class="idl-code" id="gain-node-idl">
+
+interface <dfn id="dfn-GainNode">GainNode</dfn> : AudioNode {
+
+ readonly attribute AudioParam gain;
+
+};
+</code></pre>
+</div>
+</div>
+
+<div id="attributes-GainNode-section" class="section">
+<h3 id="attributes-GainNode">4.7.1. Attributes</h3>
+<dl>
+ <dt id="dfn-gain"><code>gain</code></dt>
+ <dd><p>Represents the amount of gain to apply. Its
+ default <code>value</code> is 1 (no gain change). The nominal <code>minValue</code> is 0, but may be
+ set negative for phase inversion. The nominal <code>maxValue</code> is 1, but higher values are allowed (no
+ exception thrown).This parameter is <em>a-rate</em> </p>
+ </dd>
+</dl>
+</div>
+</div>
+
+<div id="DelayNode-section" class="section">
+<h2 id="DelayNode">4.8. The DelayNode Interface</h2>
+
+<p>A delay-line is a fundamental building block in audio applications. This
+interface is an AudioNode with a single input and single output: </p>
+<pre>
+ numberOfInputs : 1
+ numberOfOutputs : 1
+
+ channelCountMode = "max";
+ channelInterpretation = "speakers";
+</pre>
+
+<p>
+The number of channels of the output always equals the number of channels of the input.
+</p>
+
+<p>It delays the incoming audio signal by a certain amount. The default
+amount is 0 seconds (no delay). When the delay time is changed, the
+implementation must make the transition smoothly, without introducing
+noticeable clicks or glitches to the audio stream. </p>
+
+<div class="block">
+
+<div class="blockTitleDiv">
+<span class="blockTitle">Web IDL</span></div>
+
+<div class="blockContent">
+<pre class="code"><code class="idl-code" id="delay-node-idl">
+
+interface <dfn id="dfn-DelayNode">DelayNode</dfn> : AudioNode {
+
+ readonly attribute AudioParam delayTime;
+
+};
+</code></pre>
+</div>
+</div>
+
+<div id="attributes-GainNode-section_2" class="section">
+<h3 id="attributes-GainNode_2">4.8.1. Attributes</h3>
+<dl>
+ <dt id="dfn-delayTime_2"><code>delayTime</code></dt>
+ <dd><p>An AudioParam object representing the amount of delay (in seconds)
+ to apply. The default value (<code>delayTime.value</code>) is 0 (no
+ delay). The minimum value is 0 and the maximum value is determined by the <em>maxDelayTime</em>
+ argument to the <code>AudioContext</code> method <code>createDelay</code>. This parameter is <em>a-rate</em></p>
+ </dd>
+</dl>
+</div>
+</div>
+
+<div id="AudioBuffer-section" class="section">
+<h2 id="AudioBuffer">4.9. The AudioBuffer Interface</h2>
+
+<p>This interface represents a memory-resident audio asset (for one-shot sounds
+and other short audio clips). Its format is non-interleaved IEEE 32-bit linear PCM with a
+nominal range of -1 -&gt; +1. It can contain one or more channels. Typically, it would be expected that the length
+of the PCM data would be fairly short (usually somewhat less than a minute).
+For longer sounds, such as music soundtracks, streaming should be used with the
+<code>audio</code> element and <code>MediaElementAudioSourceNode</code>. </p>
+
+<p>
+An AudioBuffer may be used by one or more AudioContexts.
+</p>
+
+<div class="block">
+
+<div class="blockTitleDiv">
+<span class="blockTitle">Web IDL</span></div>
+
+<div class="blockContent">
+<pre class="code"><code class="idl-code" id="audio-buffer-idl">
+
+interface <dfn id="dfn-AudioBuffer">AudioBuffer</dfn> {
+
+ readonly attribute float sampleRate;
+ readonly attribute long length;
+
+ <span class="comment">// in seconds </span>
+ readonly attribute double duration;
+
+ readonly attribute long numberOfChannels;
+
+ Float32Array getChannelData(unsigned long channel);
+
+};
+</code></pre>
+</div>
+</div>
+
+<div id="attributes-AudioBuffer-section" class="section">
+<h3 id="attributes-AudioBuffer">4.9.1. Attributes</h3>
+<dl>
+ <dt id="dfn-sampleRate_AudioBuffer"><code>sampleRate</code></dt>
+ <dd><p>The sample-rate for the PCM audio data in samples per second.</p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-length_AudioBuffer"><code>length</code></dt>
+ <dd><p>Length of the PCM audio data in sample-frames.</p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-duration_AudioBuffer"><code>duration</code></dt>
+ <dd><p>Duration of the PCM audio data in seconds.</p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-numberOfChannels_AudioBuffer"><code>numberOfChannels</code></dt>
+ <dd><p>The number of discrete audio channels.</p>
+ </dd>
+</dl>
+</div>
+
+<div id="methodsandparams-AudioBuffer-section" class="section">
+<h3 id="methodsandparams-AudioBuffer">4.9.2. Methods and Parameters</h3>
+<dl>
+ <dt id="dfn-getChannelData">The <code>getChannelData</code> method</dt>
+ <dd><p>Returns the <code>Float32Array</code> representing the PCM audio data for the specific channel.</p>
+ <p>The <dfn id="dfn-channel">channel</dfn> parameter is an index
+ representing the particular channel to get data for. An index value of 0 represents
+ the first channel. This index value MUST be less than <code>numberOfChannels</code>
+ or an exception will be thrown.</p>
+ </dd>
+</dl>
+</div>
+</div>
+
+<div id="AudioBufferSourceNode-section" class="section">
+<h2 id="AudioBufferSourceNode">4.10. The AudioBufferSourceNode Interface</h2>
+
+<p>This interface represents an audio source from an in-memory audio asset in
+an <code>AudioBuffer</code>. It is useful for playing short audio assets
+which require a high degree of scheduling flexibility (can playback in
+rhythmically perfect ways). The start() method is used to schedule when
+sound playback will happen. The playback will stop automatically when
+the buffer's audio data has been completely
+played (if the <code>loop</code> attribute is false), or when the stop()
+method has been called and the specified time has been reached. Please see more
+details in the start() and stop() description. start() and stop() may not be issued
+multiple times for a given
+AudioBufferSourceNode. </p>
+<pre> numberOfInputs : 0
+ numberOfOutputs : 1
+ </pre>
+
+<p>
+The number of channels of the output always equals the number of channels of the AudioBuffer
+assigned to the .buffer attribute, or is one channel of silence if .buffer is NULL.
+</p>
+
+<div class="block">
+
+<div class="blockTitleDiv">
+<span class="blockTitle">Web IDL</span></div>
+
+<div class="blockContent">
+<pre class="code"><code class="idl-code" id="audio-buffer-source-node-idl">
+
+interface <dfn id="dfn-AudioBufferSourceNode">AudioBufferSourceNode</dfn> : AudioNode {
+
+ attribute AudioBuffer? buffer;
+
+ readonly attribute AudioParam playbackRate;
+
+ attribute boolean loop;
+ attribute double loopStart;
+ attribute double loopEnd;
+
+ void start(optional double when = 0, optional double offset = 0, optional double duration);
+ void stop(optional double when = 0);
+
+ attribute EventHandler onended;
+
+};
+</code></pre>
+</div>
+</div>
+
+<div id="attributes-AudioBufferSourceNode-section" class="section">
+<h3 id="attributes-AudioBufferSourceNode">4.10.1. Attributes</h3>
+<dl>
+ <dt id="dfn-buffer_AudioBufferSourceNode"><code>buffer</code></dt>
+ <dd><p>Represents the audio asset to be played. </p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-playbackRate_AudioBufferSourceNode"><code>playbackRate</code></dt>
+ <dd><p>The speed at which to render the audio stream. The default
+ playbackRate.value is 1. This parameter is <em>a-rate</em> </p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-loop_AudioBufferSourceNode"><code>loop</code></dt>
+ <dd><p>Indicates if the audio data should play in a loop. The default value is false. </p>
+ </dd>
+</dl>
+
+<dl>
+ <dt id="dfn-loopStart_AudioBufferSourceNode"><code>loopStart</code></dt>
+ <dd><p>An optional value in seconds where looping should begin if the <code>loop</code> attribute is true.
+ Its default value is 0, and it may usefully be set to any value between 0 and the duration of the buffer.</p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-loopEnd_AudioBufferSourceNode"><code>loopEnd</code></dt>
+ <dd><p>An optional value in seconds where looping should end if the <code>loop</code> attribute is true.
+ Its default value is 0, and it may usefully be set to any value between 0 and the duration of the buffer.</p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-onended_AudioBufferSourceNode"><code>onended</code></dt>
+ <dd><p>A property used to set the <code>EventHandler</code> (described in <cite><a
+ href="http://www.whatwg.org/specs/web-apps/current-work/#eventhandler">HTML</a></cite>)
+ for the ended event that is dispatched to <a
+ href="#AudioBufferSourceNode-section"><code>AudioBufferSourceNode</code></a>
+ node types. When the playback of the buffer for an <code>AudioBufferSourceNode</code>
+ is finished, an event of type <code>Event</code> (described in <cite><a
+ href="http://www.whatwg.org/specs/web-apps/current-work/#event">HTML</a></cite>)
+ will be dispatched to the event handler. </p>
+ </dd>
+</dl>
+
+
+</div>
+</div>
+
+<div id="methodsandparams-AudioBufferSourceNode-section" class="section">
+<h3 id="methodsandparams-AudioBufferSourceNode">4.10.2. Methods and
+Parameters</h3>
+<dl>
+ <dt id="dfn-start">The <code>start</code> method</dt>
+ <dd><p>Schedules a sound to playback at an exact time.</p>
+ <p>The <dfn id="dfn-when">when</dfn> parameter describes at what time (in
+ seconds) the sound should start playing. It is in the same
+ time coordinate system as AudioContext.currentTime. If 0 is passed in for
+ this value or if the value is less than <b>currentTime</b>, then the
+ sound will start playing immediately. <code>start</code> may only be called one time
+ and must be called before <code>stop</code> is called or an exception will be thrown.</p>
+ <p>The <dfn id="dfn-offset">offset</dfn> parameter describes
+ the offset time in the buffer (in seconds) where playback will begin. If 0 is passed
+ in for this value, then playback will start from the beginning of the buffer.</p>
+ <p>The <dfn id="dfn-duration">duration</dfn> parameter
+ describes the duration of the portion (in seconds) to be played. If this parameter is not passed,
+ the duration will be equal to the total duration of the AudioBuffer minus the <code>offset</code> parameter.
+ Thus if neither <code>offset</code> nor <code>duration</code> are specified then the implied duration is
+ the total duration of the AudioBuffer.
+ </p>
+
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-stop">The <code>stop</code> method</dt>
+ <dd><p>Schedules a sound to stop playback at an exact time.</p>
+ <p>The <dfn id="dfn-when_AudioBufferSourceNode_2">when</dfn> parameter
+ describes at what time (in seconds) the sound should stop playing.
+ It is in the same time coordinate system as AudioContext.currentTime.
+ If 0 is passed in for this value or if the value is less than
+ <b>currentTime</b>, then the sound will stop playing immediately.
+ <code>stop</code> must only be called one time and only after a call to <code>start</code> or <code>stop</code>,
+ or an exception will be thrown.</p>
+ </dd>
+</dl>
+</div>
+
+<div id="looping-AudioBufferSourceNode-section" class="section">
+<h3 id="looping-AudioBufferSourceNode">4.10.3. Looping</h3>
+<p>
+If the <code>loop</code> attribute is true when <code>start()</code> is called, then playback will continue indefinitely
+until <code>stop()</code> is called and the stop time is reached. We'll call this "loop" mode. Playback always starts at the point in the buffer indicated
+by the <code>offset</code> argument of <code>start()</code>, and in <em>loop</em> mode will continue playing until it reaches the <em>actualLoopEnd</em> position
+in the buffer (or the end of the buffer), at which point it will wrap back around to the <em>actualLoopStart</em> position in the buffer, and continue
+playing according to this pattern.
+</p>
+
+<p>
+In <em>loop</em> mode then the <em>actual</em> loop points are calculated as follows from the <code>loopStart</code> and <code>loopEnd</code> attributes:
+</p>
+
+<blockquote>
+<pre>
+ if ((loopStart || loopEnd) &amp;&amp; loopStart >= 0 &amp;&amp; loopEnd > 0 &amp;&amp; loopStart &lt; loopEnd) {
+ actualLoopStart = loopStart;
+ actualLoopEnd = min(loopEnd, buffer.length);
+ } else {
+ actualLoopStart = 0;
+ actualLoopEnd = buffer.length;
+ }
+</pre>
+</blockquote>
+
+<p>
+Note that the default values for <code>loopStart</code> and <code>loopEnd</code> are both 0, which indicates that looping should occur from the very start
+to the very end of the buffer.
+</p>
+
+<p>
+Please note that as a low-level implementation detail, the AudioBuffer is at a specific sample-rate (usually the same as the AudioContext sample-rate), and
+that the loop times (in seconds) must be converted to the appropriate sample-frame positions in the buffer according to this sample-rate.
+</p>
+
+</div>
+
+<div id="MediaElementAudioSourceNode-section" class="section">
+<h2 id="MediaElementAudioSourceNode">4.11. The MediaElementAudioSourceNode
+Interface</h2>
+
+<p>This interface represents an audio source from an <code>audio</code> or
+<code>video</code> element. </p>
+<pre> numberOfInputs : 0
+ numberOfOutputs : 1
+ </pre>
+
+<p>
+The number of channels of the output corresponds to the number of channels of the media referenced by the HTMLMediaElement.
+Thus, changes to the media element's .src attribute can change the number of channels output by this node.
+If the .src attribute is not set, then the number of channels output will be one silent channel.
+</p>
+
+<div class="block">
+
+<div class="blockTitleDiv">
+<span class="blockTitle">Web IDL</span></div>
+
+<div class="blockContent">
+<pre class="code"><code class="idl-code" id="media-element-audio-source-node-idl">
+
+interface <dfn id="dfn-MediaElementAudioSourceNode">MediaElementAudioSourceNode</dfn> : AudioNode {
+
+};
+</code></pre>
+</div>
+</div>
+</div>
+
+<p>A MediaElementAudioSourceNode
+is created given an HTMLMediaElement using the AudioContext <a href="#dfn-createMediaElementSource">createMediaElementSource()</a> method. </p>
+
+<p>
+The number of channels of the single output equals the number of channels of the audio referenced by
+the HTMLMediaElement passed in as the argument to createMediaElementSource(), or is 1 if the HTMLMediaElement
+has no audio.
+</p>
+
+<p>
+The HTMLMediaElement must behave in an identical fashion after the MediaElementAudioSourceNode has
+been created, <em>except</em> that the rendered audio will no longer be heard directly, but instead will be heard
+as a consequence of the MediaElementAudioSourceNode being connected through the routing graph. Thus pausing, seeking,
+volume, <code>.src</code> attribute changes, and other aspects of the HTMLMediaElement must behave as they normally would
+if <em>not</em> used with a MediaElementAudioSourceNode.
+</p>
+
+<div class="example">
+
+<div class="exampleHeader">
+Example</div>
+
+<div class="block">
+
+<div class="blockTitleDiv">
+<span class="blockTitle">ECMAScript</span></div>
+
+<div class="blockContent">
+<pre class="code"><code class="es-code">
+var mediaElement = document.getElementById('mediaElementID');
+var sourceNode = context.createMediaElementSource(mediaElement);
+sourceNode.connect(filterNode);
+ </code></pre>
+</div>
+</div>
+</div>
+</div>
+
+
+<div id="ScriptProcessorNode-section" class="section">
+<h2 id="ScriptProcessorNode">4.12. The ScriptProcessorNode Interface</h2>
+
+<p>This interface is an AudioNode which can generate, process, or analyse audio
+directly using JavaScript. </p>
+<pre>
+ numberOfInputs : 1
+ numberOfOutputs : 1
+
+ channelCount = numberOfInputChannels;
+ channelCountMode = "explicit";
+ channelInterpretation = "speakers";
+</pre>
+
+<p>The ScriptProcessorNode is constructed with a <code>bufferSize</code> which
+must be one of the following values: 256, 512, 1024, 2048, 4096, 8192, 16384.
+This value controls how frequently the <code>audioprocess</code> event
+is dispatched and how many sample-frames need to be processed each call.
+Lower numbers for <code>bufferSize</code> will result in a lower (better) <a
+href="#Latency-section">latency</a>. Higher numbers will be necessary to avoid
+audio breakup and <a href="#Glitching-section">glitches</a>.
+This value will be picked by the implementation if the bufferSize argument
+to <code>createScriptProcessor</code> is not passed in, or is set to 0.</p>
+
+<p><code>numberOfInputChannels</code> and <code>numberOfOutputChannels</code>
+determine the number of input and output channels. It is invalid for both
+<code>numberOfInputChannels</code> and <code>numberOfOutputChannels</code> to
+be zero. </p>
+<pre> var node = context.createScriptProcessor(bufferSize, numberOfInputChannels, numberOfOutputChannels);
+ </pre>
+
+<div class="block">
+
+<div class="blockTitleDiv">
+<span class="blockTitle">Web IDL</span></div>
+
+<div class="blockContent">
+<pre class="code"><code class="idl-code" id="script-processor-node-idl">
+
+interface <dfn id="dfn-ScriptProcessorNode">ScriptProcessorNode</dfn> : AudioNode {
+
+ attribute EventHandler onaudioprocess;
+
+ readonly attribute long bufferSize;
+
+};
+</code></pre>
+</div>
+</div>
+
+<div id="attributes-ScriptProcessorNode-section" class="section">
+<h3 id="attributes-ScriptProcessorNode">4.12.1. Attributes</h3>
+<dl>
+ <dt id="dfn-onaudioprocess"><code>onaudioprocess</code></dt>
+ <dd><p>A property used to set the <code>EventHandler</code> (described in <cite><a
+ href="http://www.whatwg.org/specs/web-apps/current-work/#eventhandler">HTML</a></cite>)
+ for the audioprocess event that is dispatched to <a
+ href="#ScriptProcessorNode-section"><code>ScriptProcessorNode</code></a>
+ node types. An event of type <a
+ href="#AudioProcessingEvent-section"><code>AudioProcessingEvent</code></a>
+ will be dispatched to the event handler. </p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-bufferSize_ScriptProcessorNode"><code>bufferSize</code></dt>
+ <dd><p>The size of the buffer (in sample-frames) which needs to be
+ processed each time <code>onprocessaudio</code> is called. Legal values
+ are (256, 512, 1024, 2048, 4096, 8192, 16384). </p>
+ </dd>
+</dl>
+</div>
+</div>
+
+<div id="AudioProcessingEvent-section" class="section">
+<h2 id="AudioProcessingEvent">4.13. The AudioProcessingEvent Interface</h2>
+
+<p>This is an <code>Event</code> object which is dispatched to <a
+href="#ScriptProcessorNode-section"><code>ScriptProcessorNode</code></a> nodes. </p>
+
+<p>The event handler processes audio from the input (if any) by accessing the
+audio data from the <code>inputBuffer</code> attribute. The audio data which is
+the result of the processing (or the synthesized data if there are no inputs)
+is then placed into the <code>outputBuffer</code>. </p>
+
+<div class="block">
+
+<div class="blockTitleDiv">
+<span class="blockTitle">Web IDL</span></div>
+
+<div class="blockContent">
+<pre class="code"><code class="idl-code" id="audio-processing-event-idl">
+
+interface <dfn id="dfn-AudioProcessingEvent">AudioProcessingEvent</dfn> : Event {
+
+ readonly attribute double playbackTime;
+ readonly attribute AudioBuffer inputBuffer;
+ readonly attribute AudioBuffer outputBuffer;
+
+};
+</code></pre>
+</div>
+</div>
+
+<div id="attributes-AudioProcessingEvent-section" class="section">
+<h3 id="attributes-AudioProcessingEvent">4.13.1. Attributes</h3>
+<dl>
+ <dt id="dfn-playbackTime"><code>playbackTime</code></dt>
+ <dd><p>The time when the audio will be played in the same time coordinate system as AudioContext.currentTime.
+ <code>playbackTime</code> allows for very tight synchronization between
+ processing directly in JavaScript with the other events in the context's
+ rendering graph. </p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-inputBuffer"><code>inputBuffer</code></dt>
+ <dd><p>An AudioBuffer containing the input audio data. It will have a number of channels equal to the <code>numberOfInputChannels</code> parameter
+ of the createScriptProcessor() method. This AudioBuffer is only valid while in the scope of the <code>onaudioprocess</code>
+ function. Its values will be meaningless outside of this scope.</p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-outputBuffer"><code>outputBuffer</code></dt>
+ <dd><p>An AudioBuffer where the output audio data should be written. It will have a number of channels equal to the
+ <code>numberOfOutputChannels</code> parameter of the createScriptProcessor() method.
+ Script code within the scope of the <code>onaudioprocess</code> function is expected to modify the
+ <code>Float32Array</code> arrays representing channel data in this AudioBuffer.
+ Any script modifications to this AudioBuffer outside of this scope will not produce any audible effects.</p>
+ </dd>
+</dl>
+</div>
+</div>
+
+<div id="PannerNode-section" class="section">
+<h2 id="PannerNode">4.14. The PannerNode Interface</h2>
+
+<p>This interface represents a processing node which <a
+href="#Spatialization-section">positions / spatializes</a> an incoming audio
+stream in three-dimensional space. The spatialization is in relation to the <a
+href="#AudioContext-section"><code>AudioContext</code></a>'s <a
+href="#AudioListener-section"><code>AudioListener</code></a>
+(<code>listener</code> attribute). </p>
+
+<pre>
+ numberOfInputs : 1
+ numberOfOutputs : 1
+
+ channelCount = 2;
+ channelCountMode = "clamped-max";
+ channelInterpretation = "speakers";
+</pre>
+
+<p>
+The audio stream from the input will be either mono or stereo, depending on the connection(s) to the input.
+</p>
+
+<p>
+The output of this node is hard-coded to stereo (2 channels) and <em>currently</em> cannot be configured.
+</p>
+
+
+<div class="block">
+
+<div class="blockTitleDiv">
+<span class="blockTitle">Web IDL</span></div>
+
+<div class="blockContent">
+<pre class="code"><code class="idl-code" id="panner-node-idl">
+
+enum <dfn>PanningModelType</dfn> {
+ "equalpower",
+ "HRTF"
+};
+
+enum <dfn>DistanceModelType</dfn> {
+ "linear",
+ "inverse",
+ "exponential"
+};
+
+interface <dfn id="dfn-PannerNode">PannerNode</dfn> : AudioNode {
+
+ <span class="comment">// Default for stereo is HRTF </span>
+ attribute PanningModelType panningModel;
+
+ <span class="comment">// Uses a 3D cartesian coordinate system </span>
+ void setPosition(double x, double y, double z);
+ void setOrientation(double x, double y, double z);
+ void setVelocity(double x, double y, double z);
+
+ <span class="comment">// Distance model and attributes </span>
+ attribute DistanceModelType distanceModel;
+ attribute double refDistance;
+ attribute double maxDistance;
+ attribute double rolloffFactor;
+
+ <span class="comment">// Directional sound cone </span>
+ attribute double coneInnerAngle;
+ attribute double coneOuterAngle;
+ attribute double coneOuterGain;
+
+};
+</code></pre>
+</div>
+</div>
+</div>
+
+<div id="attributes-PannerNode_attributes-section" class="section">
+<h3 id="attributes-PannerNode_attributes">4.14.2. Attributes</h3>
+<dl>
+ <dt id="dfn-panningModel"><code>panningModel</code></dt>
+ <dd><p>Determines which spatialization algorithm will be used to position
+ the audio in 3D space. The default is "HRTF". </p>
+
+ <dl>
+ <dt id="dfn-EQUALPOWER"><code>"equalpower"</code></dt>
+ <dd><p>A simple and efficient spatialization algorithm using equal-power
+ panning. </p>
+ </dd>
+ </dl>
+ <dl>
+ <dt id="dfn-HRTF"><code>"HRTF"</code></dt>
+ <dd><p>A higher quality spatialization algorithm using a convolution with
+ measured impulse responses from human subjects. This panning method
+ renders stereo output. </p>
+ </dd>
+ </dl>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-distanceModel"><code>distanceModel</code></dt>
+ <dd><p>Determines which algorithm will be used to reduce the volume of an
+ audio source as it moves away from the listener. The default is "inverse".
+</p>
+
+<dl>
+ <dt id="dfn-LINEAR_DISTANCE"><code>"linear"</code></dt>
+ <dd><p>A linear distance model which calculates <em>distanceGain</em> according to: </p>
+ <pre>
+1 - rolloffFactor * (distance - refDistance) / (maxDistance - refDistance)
+ </pre>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-INVERSE_DISTANCE"><code>"inverse"</code></dt>
+ <dd><p>An inverse distance model which calculates <em>distanceGain</em> according to: </p>
+ <pre>
+refDistance / (refDistance + rolloffFactor * (distance - refDistance))
+ </pre>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-EXPONENTIAL_DISTANCE"><code>"exponential"</code></dt>
+ <dd><p>An exponential distance model which calculates <em>distanceGain</em> according to: </p>
+ <pre>
+pow(distance / refDistance, -rolloffFactor)
+ </pre>
+ </dd>
+</dl>
+
+
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-refDistance"><code>refDistance</code></dt>
+ <dd><p>A reference distance for reducing volume as source move further from
+ the listener. The default value is 1. </p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-maxDistance"><code>maxDistance</code></dt>
+ <dd><p>The maximum distance between source and listener, after which the
+ volume will not be reduced any further. The default value is 10000. </p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-rolloffFactor"><code>rolloffFactor</code></dt>
+ <dd><p>Describes how quickly the volume is reduced as source moves away
+ from listener. The default value is 1. </p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-coneInnerAngle"><code>coneInnerAngle</code></dt>
+ <dd><p>A parameter for directional audio sources, this is an angle, inside
+ of which there will be no volume reduction. The default value is 360. </p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-coneOuterAngle"><code>coneOuterAngle</code></dt>
+ <dd><p>A parameter for directional audio sources, this is an angle, outside
+ of which the volume will be reduced to a constant value of
+ <b>coneOuterGain</b>. The default value is 360. </p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-coneOuterGain"><code>coneOuterGain</code></dt>
+ <dd><p>A parameter for directional audio sources, this is the amount of
+ volume reduction outside of the <b>coneOuterAngle</b>. The default value is 0. </p>
+ </dd>
+</dl>
+</div>
+
+<h3 id="Methods_and_Parameters">4.14.3. Methods and Parameters</h3>
+<dl>
+ <dt id="dfn-setPosition">The <code>setPosition</code> method</dt>
+ <dd><p>Sets the position of the audio source relative to the
+ <b>listener</b> attribute. A 3D cartesian coordinate system is used.</p>
+ <p>The <dfn id="dfn-x">x, y, z</dfn> parameters represent the coordinates
+ in 3D space. </p>
+ <p>The default value is (0,0,0)
+ </p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-setOrientation">The <code>setOrientation</code> method</dt>
+ <dd><p>Describes which direction the audio source is pointing in the 3D
+ cartesian coordinate space. Depending on how directional the sound is
+ (controlled by the <b>cone</b> attributes), a sound pointing away from
+ the listener can be very quiet or completely silent.</p>
+ <p>The <dfn id="dfn-x_2">x, y, z</dfn> parameters represent a direction
+ vector in 3D space. </p>
+ <p>The default value is (1,0,0)
+ </p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-setVelocity">The <code>setVelocity</code> method</dt>
+ <dd><p>Sets the velocity vector of the audio source. This vector controls
+ both the direction of travel and the speed in 3D space. This velocity
+ relative to the listener's velocity is used to determine how much doppler
+ shift (pitch change) to apply. The units used for this vector is <em>meters / second</em>
+ and is independent of the units used for position and orientation vectors.</p>
+ <p>The <dfn id="dfn-x_3">x, y, z</dfn> parameters describe a direction
+ vector indicating direction of travel and intensity. </p>
+ <p>The default value is (0,0,0)
+ </p>
+ </dd>
+</dl>
+
+<div id="AudioListener-section" class="section">
+<h2 id="AudioListener">4.15. The AudioListener Interface</h2>
+
+<p>This interface represents the position and orientation of the person
+listening to the audio scene. All <a
+href="#PannerNode-section"><code>PannerNode</code></a> objects
+spatialize in relation to the AudioContext's <code>listener</code>. See <a
+href="#Spatialization-section">this</a> section for more details about
+spatialization. </p>
+
+<div class="block">
+
+<div class="blockTitleDiv">
+<span class="blockTitle">Web IDL</span></div>
+
+<div class="blockContent">
+<pre class="code"><code class="idl-code" id="audio-listener-idl">
+
+interface <dfn id="dfn-AudioListener">AudioListener</dfn> {
+
+ attribute double dopplerFactor;
+ attribute double speedOfSound;
+
+ <span class="comment">// Uses a 3D cartesian coordinate system </span>
+ void setPosition(double x, double y, double z);
+ void setOrientation(double x, double y, double z, double xUp, double yUp, double zUp);
+ void setVelocity(double x, double y, double z);
+
+};
+</code></pre>
+</div>
+</div>
+</div>
+
+<div id="attributes-AudioListener-section" class="section">
+<h3 id="attributes-AudioListener">4.15.1. Attributes</h3>
+<dl>
+ <dt id="dfn-dopplerFactor"><code>dopplerFactor</code></dt>
+ <dd><p>A constant used to determine the amount of pitch shift to use when
+ rendering a doppler effect. The default value is 1. </p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-speedOfSound"><code>speedOfSound</code></dt>
+ <dd><p>The speed of sound used for calculating doppler shift. The default
+ value is 343.3. </p>
+ </dd>
+</dl>
+</div>
+
+<h3 id="L15842">4.15.2. Methods and Parameters</h3>
+<dl>
+ <dt id="dfn-setPosition_2">The <code>setPosition</code> method</dt>
+ <dd><p>Sets the position of the listener in a 3D cartesian coordinate
+ space. <code>PannerNode</code> objects use this position relative to
+ individual audio sources for spatialization.</p>
+ <p>The <dfn id="dfn-x_AudioListener">x, y, z</dfn> parameters represent
+ the coordinates in 3D space. </p>
+ <p>The default value is (0,0,0)
+ </p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-setOrientation_2">The <code>setOrientation</code> method</dt>
+ <dd><p>Describes which direction the listener is pointing in the 3D
+ cartesian coordinate space. Both a <b>front</b> vector and an <b>up</b>
+ vector are provided. In simple human terms, the <b>front</b> vector represents which
+ direction the person's nose is pointing. The <b>up</b> vector represents the
+ direction the top of a person's head is pointing. These values are expected to
+ be linearly independent (at right angles to each other). For normative requirements
+ of how these values are to be interpreted, see the
+ <a href="#Spatialization-section">spatialization section</a>.
+ </p>
+ <p>The <dfn id="dfn-x_setOrientation">x, y, z</dfn> parameters represent
+ a <b>front</b> direction vector in 3D space, with the default value being (0,0,-1) </p>
+ <p>The <dfn id="dfn-x_setOrientation_2">xUp, yUp, zUp</dfn> parameters
+ represent an <b>up</b> direction vector in 3D space, with the default value being (0,1,0) </p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-setVelocity_4">The <code>setVelocity</code> method</dt>
+ <dd><p>Sets the velocity vector of the listener. This vector controls both
+ the direction of travel and the speed in 3D space. This velocity relative to
+ an audio source's velocity is used to determine how much doppler shift
+ (pitch change) to apply. The units used for this vector is <em>meters / second</em>
+ and is independent of the units used for position and orientation vectors.</p>
+ <p>The <dfn id="dfn-x_setVelocity_5">x, y, z</dfn> parameters describe a
+ direction vector indicating direction of travel and intensity. </p>
+ <p>The default value is (0,0,0)
+ </p>
+ </dd>
+</dl>
+
+<div id="ConvolverNode-section" class="section">
+<h2 id="ConvolverNode">4.16. The ConvolverNode Interface</h2>
+
+<p>This interface represents a processing node which applies a <a
+href="#Convolution-section">linear convolution effect</a> given an impulse
+response. Normative requirements for multi-channel convolution matrixing are described
+<a href="#Convolution-reverb-effect">here</a>. </p>
+<pre>
+ numberOfInputs : 1
+ numberOfOutputs : 1
+
+ channelCount = 2;
+ channelCountMode = "clamped-max";
+ channelInterpretation = "speakers";
+</pre>
+
+<div class="block">
+
+<div class="blockTitleDiv">
+<span class="blockTitle">Web IDL</span></div>
+
+<div class="blockContent">
+<pre class="code"><code class="idl-code" id="convolver-node-idl">
+
+interface <dfn id="dfn-ConvolverNode">ConvolverNode</dfn> : AudioNode {
+
+ attribute AudioBuffer? buffer;
+ attribute boolean normalize;
+
+};
+</code></pre>
+</div>
+</div>
+</div>
+
+<div id="attributes-ConvolverNode-section" class="section">
+<h3 id="attributes-ConvolverNode">4.16.1. Attributes</h3>
+<dl>
+ <dt id="dfn-buffer_ConvolverNode"><code>buffer</code></dt>
+ <dd><p>A mono, stereo, or 4-channel <code>AudioBuffer</code> containing the (possibly multi-channel) impulse response
+ used by the ConvolverNode. This <code>AudioBuffer</code> must be of the same sample-rate as the AudioContext or an exception will
+ be thrown. At the time when this attribute is set, the <em>buffer</em> and the state of the <em>normalize</em>
+ attribute will be used to configure the ConvolverNode with this impulse response having the given normalization.
+ The initial value of this attribute is null.</p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-normalize"><code>normalize</code></dt>
+ <dd><p>Controls whether the impulse response from the buffer will be scaled
+ by an equal-power normalization when the <code>buffer</code> atttribute
+ is set. Its default value is <code>true</code> in order to achieve a more
+ uniform output level from the convolver when loaded with diverse impulse
+ responses. If <code>normalize</code> is set to <code>false</code>, then
+ the convolution will be rendered with no pre-processing/scaling of the
+ impulse response. Changes to this value do not take effect until the next time
+ the <em>buffer</em> attribute is set. </p>
+
+ </dd>
+</dl>
+
+ <p>
+ If the <em>normalize</em> attribute is false when the <em>buffer</em> attribute is set then the
+ ConvolverNode will perform a linear convolution given the exact impulse response contained within the <em>buffer</em>.
+ </p>
+ <p>
+ Otherwise, if the <em>normalize</em> attribute is true when the <em>buffer</em> attribute is set then the
+ ConvolverNode will first perform a scaled RMS-power analysis of the audio data contained within <em>buffer</em> to calculate a
+ <em>normalizationScale</em> given this algorithm:
+ </p>
+
+
+ <div class="block">
+
+ <div class="blockTitleDiv">
+
+ <div class="blockContent">
+ <pre class="code"><code class="es-code">
+
+float calculateNormalizationScale(buffer)
+{
+ const float GainCalibration = 0.00125;
+ const float GainCalibrationSampleRate = 44100;
+ const float MinPower = 0.000125;
+
+ // Normalize by RMS power.
+ size_t numberOfChannels = buffer->numberOfChannels();
+ size_t length = buffer->length();
+
+ float power = 0;
+
+ for (size_t i = 0; i &lt; numberOfChannels; ++i) {
+ float* sourceP = buffer->channel(i)->data();
+ float channelPower = 0;
+
+ int n = length;
+ while (n--) {
+ float sample = *sourceP++;
+ channelPower += sample * sample;
+ }
+
+ power += channelPower;
+ }
+
+ power = sqrt(power / (numberOfChannels * length));
+
+ // Protect against accidental overload.
+ if (isinf(power) || isnan(power) || power &lt; MinPower)
+ power = MinPower;
+
+ float scale = 1 / power;
+
+ // Calibrate to make perceived volume same as unprocessed.
+ scale *= GainCalibration;
+
+ // Scale depends on sample-rate.
+ if (buffer->sampleRate())
+ scale *= GainCalibrationSampleRate / buffer->sampleRate();
+
+ // True-stereo compensation.
+ if (buffer->numberOfChannels() == 4)
+ scale *= 0.5;
+
+ return scale;
+}
+ </code></pre>
+
+ </div>
+ </div>
+ </div>
+
+<p>
+During processing, the ConvolverNode will then take this calculated <em>normalizationScale</em> value and multiply it by the result of the linear convolution
+resulting from processing the input with the impulse response (represented by the <em>buffer</em>) to produce the
+final output. Or any mathematically equivalent operation may be used, such as pre-multiplying the
+input by <em>normalizationScale</em>, or pre-multiplying a version of the impulse-response by <em>normalizationScale</em>.
+</p>
+
+</div>
+
+<div id="AnalyserNode-section" class="section">
+<h2 id="AnalyserNode">4.17. The AnalyserNode Interface</h2>
+
+<p>This interface represents a node which is able to provide real-time
+frequency and time-domain <a href="#AnalyserNode">analysis</a>
+information. The audio stream will be passed un-processed from input to output.
+</p>
+<pre>
+ numberOfInputs : 1
+ numberOfOutputs : 1 <em>Note that this output may be left unconnected.</em>
+
+ channelCount = 1;
+ channelCountMode = "explicit";
+ channelInterpretation = "speakers";
+</pre>
+
+<div class="block">
+
+<div class="blockTitleDiv">
+<span class="blockTitle">Web IDL</span></div>
+
+<div class="blockContent">
+<pre class="code"><code class="idl-code" id="analyser-node-idl">
+
+interface <dfn id="dfn-AnalyserNode">AnalyserNode</dfn> : AudioNode {
+
+ <span class="comment">// Real-time frequency-domain data </span>
+ void getFloatFrequencyData(Float32Array array);
+ void getByteFrequencyData(Uint8Array array);
+
+ <span class="comment">// Real-time waveform data </span>
+ void getByteTimeDomainData(Uint8Array array);
+
+ attribute unsigned long fftSize;
+ readonly attribute unsigned long frequencyBinCount;
+
+ attribute double minDecibels;
+ attribute double maxDecibels;
+
+ attribute double smoothingTimeConstant;
+
+};
+</code></pre>
+</div>
+</div>
+</div>
+
+<div id="attributes-ConvolverNode-section_2" class="section">
+<h3 id="attributes-ConvolverNode_2">4.17.1. Attributes</h3>
+<dl>
+ <dt id="dfn-fftSize"><code>fftSize</code></dt>
+ <dd><p>The size of the FFT used for frequency-domain analysis. This must be
+ a non-zero power of two in the range 32 to 2048, otherwise an INDEX_SIZE_ERR exception MUST be thrown.
+ The default value is 2048.</p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-frequencyBinCount"><code>frequencyBinCount</code></dt>
+ <dd><p>Half the FFT size. </p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-minDecibels"><code>minDecibels</code></dt>
+ <dd><p>The minimum power value in the scaling range for the FFT analysis
+ data for conversion to unsigned byte values.
+ The default value is -100.
+ If the value of this attribute is set to a value more than or equal to <code>maxDecibels</code>,
+ an INDEX_SIZE_ERR exception MUST be thrown.</p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-maxDecibels"><code>maxDecibels</code></dt>
+ <dd><p>The maximum power value in the scaling range for the FFT analysis
+ data for conversion to unsigned byte values.
+ The default value is -30.
+ If the value of this attribute is set to a value less than or equal to <code>minDecibels</code>,
+ an INDEX_SIZE_ERR exception MUST be thrown.</p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-smoothingTimeConstant"><code>smoothingTimeConstant</code></dt>
+ <dd><p>A value from 0 -&gt; 1 where 0 represents no time averaging
+ with the last analysis frame.
+ The default value is 0.8.
+ If the value of this attribute is set to a value less than 0 or more than 1,
+ an INDEX_SIZE_ERR exception MUST be thrown.</p>
+ </dd>
+</dl>
+</div>
+
+<h3 id="methods-and-parameters">4.17.2. Methods and Parameters</h3>
+<dl>
+ <dt id="dfn-getFloatFrequencyData">The <code>getFloatFrequencyData</code>
+ method</dt>
+ <dd><p>Copies the current frequency data into the passed floating-point
+ array. If the array has fewer elements than the frequencyBinCount, the
+ excess elements will be dropped. If the array has more elements than
+ the frequencyBinCount, the excess elements will be ignored.</p>
+ <p>The <dfn id="dfn-array">array</dfn> parameter is where
+ frequency-domain analysis data will be copied. </p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-getByteFrequencyData">The <code>getByteFrequencyData</code>
+ method</dt>
+ <dd><p>Copies the current frequency data into the passed unsigned byte
+ array. If the array has fewer elements than the frequencyBinCount, the
+ excess elements will be dropped. If the array has more elements than
+ the frequencyBinCount, the excess elements will be ignored.</p>
+ <p>The <dfn id="dfn-array_2">array</dfn> parameter is where
+ frequency-domain analysis data will be copied. </p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-getByteTimeDomainData">The <code>getByteTimeDomainData</code>
+ method</dt>
+ <dd><p>Copies the current time-domain (waveform) data into the passed
+ unsigned byte array. If the array has fewer elements than the
+ fftSize, the excess elements will be dropped. If the array has more
+ elements than fftSize, the excess elements will be ignored.</p>
+ <p>The <dfn id="dfn-array_3">array</dfn> parameter is where time-domain
+ analysis data will be copied. </p>
+ </dd>
+</dl>
+
+<div id="ChannelSplitterNode-section" class="section">
+<h2 id="ChannelSplitterNode">4.18. The ChannelSplitterNode Interface</h2>
+
+<p>The <code>ChannelSplitterNode</code> is for use in more advanced
+applications and would often be used in conjunction with <a
+href="#ChannelMergerNode-section"><code>ChannelMergerNode</code></a>. </p>
+<pre>
+ numberOfInputs : 1
+ numberOfOutputs : Variable N (defaults to 6) // number of "active" (non-silent) outputs is determined by number of channels in the input
+
+ channelCountMode = "max";
+ channelInterpretation = "speakers";
+</pre>
+
+<p>This interface represents an AudioNode for accessing the individual channels
+of an audio stream in the routing graph. It has a single input, and a number of
+"active" outputs which equals the number of channels in the input audio stream.
+For example, if a stereo input is connected to an
+<code>ChannelSplitterNode</code> then the number of active outputs will be two
+(one from the left channel and one from the right). There are always a total
+number of N outputs (determined by the <code>numberOfOutputs</code> parameter to the AudioContext method <code>createChannelSplitter()</code>),
+ The default number is 6 if this value is not provided. Any outputs
+which are not "active" will output silence and would typically not be connected
+to anything. </p>
+
+<h3 id="example-1">Example:</h3>
+<img alt="channel splitter" src="images/channel-splitter.png" />
+
+<p>Please note that in this example, the splitter does <b>not</b> interpret the channel identities (such as left, right, etc.), but
+simply splits out channels in the order that they are input.</p>
+
+<p>One application for <code>ChannelSplitterNode</code> is for doing "matrix
+mixing" where individual gain control of each channel is desired. </p>
+
+<div class="block">
+
+<div class="blockTitleDiv">
+<span class="blockTitle">Web IDL</span></div>
+
+<div class="blockContent">
+<pre class="code"><code class="idl-code" id="channel-splitter-node-idl">
+
+interface <dfn id="dfn-ChannelSplitterNode">ChannelSplitterNode</dfn> : AudioNode {
+
+};
+</code></pre>
+</div>
+</div>
+</div>
+
+<div id="ChannelMergerNode-section" class="section">
+<h2 id="ChannelMergerNode">4.19. The ChannelMergerNode Interface</h2>
+
+<p>The <code>ChannelMergerNode</code> is for use in more advanced applications
+and would often be used in conjunction with <a
+href="#ChannelSplitterNode-section"><code>ChannelSplitterNode</code></a>. </p>
+<pre>
+ numberOfInputs : Variable N (default to 6) // number of connected inputs may be less than this
+ numberOfOutputs : 1
+
+ channelCountMode = "max";
+ channelInterpretation = "speakers";
+</pre>
+
+<p>This interface represents an AudioNode for combining channels from multiple
+audio streams into a single audio stream. It has a variable number of inputs (defaulting to 6), but not all of them
+need be connected. There is a single output whose audio stream has a number of
+channels equal to the sum of the numbers of channels of all the connected
+inputs. For example, if an <code>ChannelMergerNode</code> has two connected
+inputs (both stereo), then the output will be four channels, the first two from
+the first input and the second two from the second input. In another example
+with two connected inputs (both mono), the output will be two channels
+(stereo), with the left channel coming from the first input and the right
+channel coming from the second input. </p>
+
+<h3 id="example-2">Example:</h3>
+<img alt="channel merger" src="images/channel-merger.png" />
+
+<p>Please note that in this example, the merger does <b>not</b> interpret the channel identities (such as left, right, etc.), but
+simply combines channels in the order that they are input.</p>
+
+
+<p>Be aware that it is possible to connect an <code>ChannelMergerNode</code>
+in such a way that it outputs an audio stream with a large number of channels
+greater than the maximum supported by the audio hardware. In this case where such an output is connected
+to the AudioContext .destination (the audio hardware), then the extra channels will be ignored.
+Thus, the <code>ChannelMergerNode</code> should be used in situations where the number
+of channels is well understood. </p>
+
+<div class="block">
+
+<div class="blockTitleDiv">
+<span class="blockTitle">Web IDL</span></div>
+
+<div class="blockContent">
+<pre class="code"><code class="idl-code" id="channel-merger-node-idl">
+
+interface <dfn id="dfn-ChannelMergerNode">ChannelMergerNode</dfn> : AudioNode {
+
+};
+</code></pre>
+</div>
+</div>
+</div>
+
+<div id="DynamicsCompressorNode-section" class="section">
+<h2 id="DynamicsCompressorNode">4.20. The DynamicsCompressorNode Interface</h2>
+
+<p>DynamicsCompressorNode is an AudioNode processor implementing a dynamics
+compression effect. </p>
+
+<p>Dynamics compression is very commonly used in musical production and game
+audio. It lowers the volume of the loudest parts of the signal and raises the
+volume of the softest parts. Overall, a louder, richer, and fuller sound can be
+achieved. It is especially important in games and musical applications where
+large numbers of individual sounds are played simultaneous to control the
+overall signal level and help avoid clipping (distorting) the audio output to
+the speakers. </p>
+<pre>
+ numberOfInputs : 1
+ numberOfOutputs : 1
+
+ channelCount = 2;
+ channelCountMode = "explicit";
+ channelInterpretation = "speakers";
+</pre>
+
+<div class="block">
+
+<div class="blockTitleDiv">
+<span class="blockTitle">Web IDL</span></div>
+
+<div class="blockContent">
+<pre class="code"><code class="idl-code" id="dynamics-compressor-node-idl">
+
+interface <dfn id="dfn-DynamicsCompressorNode">DynamicsCompressorNode</dfn> : AudioNode {
+
+ readonly attribute AudioParam threshold; // in Decibels
+ readonly attribute AudioParam knee; // in Decibels
+ readonly attribute AudioParam ratio; // unit-less
+ readonly attribute AudioParam reduction; // in Decibels
+ readonly attribute AudioParam attack; // in Seconds
+ readonly attribute AudioParam release; // in Seconds
+
+};
+</code>
+</pre>
+</div>
+</div>
+
+<div id="attributes-DynamicsCompressorNode-section" class="section">
+<h3 id="attributes-DynamicsCompressorNode">4.20.1. Attributes</h3>
+<p>
+All parameters are <em>k-rate</em>
+</p>
+
+<dl>
+ <dt id="dfn-threshold"><code>threshold</code></dt>
+ <dd><p>The decibel value above which the compression will start taking
+ effect. Its default value is -24, with a nominal range of -100 to 0. </p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-knee"><code>knee</code></dt>
+ <dd><p>A decibel value representing the range above the threshold where the
+ curve smoothly transitions to the "ratio" portion. Its default value is 30, with a nominal range of 0 to 40. </p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-ratio"><code>ratio</code></dt>
+ <dd><p>The amount of dB change in input for a 1 dB change in output. Its default value is 12, with a nominal range of 1 to 20. </p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-reduction"><code>reduction</code></dt>
+ <dd><p>A read-only decibel value for metering purposes, representing the
+ current amount of gain reduction that the compressor is applying to the
+ signal. If fed no signal the value will be 0 (no gain reduction). The nominal range is -20 to 0. </p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-attack"><code>attack</code></dt>
+ <dd><p>The amount of time (in seconds) to reduce the gain by 10dB. Its default value is 0.003, with a nominal range of 0 to 1. </p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-release"><code>release</code></dt>
+ <dd><p>The amount of time (in seconds) to increase the gain by 10dB. Its default value is 0.250, with a nominal range of 0 to 1. </p>
+ </dd>
+</dl>
+</div>
+</div>
+
+<div id="BiquadFilterNode-section" class="section">
+<h2 id="BiquadFilterNode">4.21. The BiquadFilterNode Interface</h2>
+
+<p>BiquadFilterNode is an AudioNode processor implementing very common
+low-order filters. </p>
+
+<p>Low-order filters are the building blocks of basic tone controls (bass, mid,
+treble), graphic equalizers, and more advanced filters. Multiple
+BiquadFilterNode filters can be combined to form more complex filters. The
+filter parameters such as "frequency" can be changed over time for filter
+sweeps, etc. Each BiquadFilterNode can be configured as one of a number of
+common filter types as shown in the IDL below. The default filter type
+is "lowpass".</p>
+<pre>
+ numberOfInputs : 1
+ numberOfOutputs : 1
+
+ channelCountMode = "max";
+ channelInterpretation = "speakers";
+</pre>
+<p>
+The number of channels of the output always equals the number of channels of the input.
+</p>
+
+<div class="block">
+
+<div class="blockTitleDiv">
+<span class="blockTitle">Web IDL</span></div>
+
+<div class="blockContent">
+<pre class="code"><code class="idl-code" id="biquad-filter-node-idl">
+
+enum <dfn>BiquadFilterType</dfn> {
+ "lowpass",
+ "highpass",
+ "bandpass",
+ "lowshelf",
+ "highshelf",
+ "peaking",
+ "notch",
+ "allpass"
+};
+
+interface <dfn id="dfn-BiquadFilterNode">BiquadFilterNode</dfn> : AudioNode {
+
+ attribute BiquadFilterType type;
+ readonly attribute AudioParam frequency; // in Hertz
+ readonly attribute AudioParam detune; // in Cents
+ readonly attribute AudioParam Q; // Quality factor
+ readonly attribute AudioParam gain; // in Decibels
+
+ void getFrequencyResponse(Float32Array frequencyHz,
+ Float32Array magResponse,
+ Float32Array phaseResponse);
+
+};
+</code></pre>
+</div>
+</div>
+</div>
+
+<p>The filter types are briefly described below. We note that all of these
+filters are very commonly used in audio processing. In terms of implementation,
+they have all been derived from standard analog filter prototypes. For more
+technical details, we refer the reader to the excellent <a
+href="http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt">reference</a> by
+Robert Bristow-Johnson.</p>
+
+<p>
+All parameters are <em>k-rate</em> with the following default parameter values:
+</p>
+
+<blockquote>
+<dl>
+ <dt>frequency</dt>
+ <dd>350Hz, with a nominal range of 10 to the Nyquist frequency (half the sample-rate).
+ </dd>
+ <dt><a href="http://en.wikipedia.org/wiki/Q_factor">Q</a></dt>
+ <dd>1, with a nominal range of 0.0001 to 1000.</dd>
+ <dt>gain</dt>
+ <dd>0, with a nominal range of -40 to 40.</dd>
+</dl>
+</blockquote>
+
+
+
+<div id="BiquadFilterNode-description-section" class="section">
+<h3 id="BiquadFilterNode-description">4.21.1 "lowpass"</h3>
+
+<p>A <a href="http://en.wikipedia.org/wiki/Low-pass_filter">lowpass filter</a>
+allows frequencies below the cutoff frequency to pass through and attenuates
+frequencies above the cutoff. It implements a standard second-order
+resonant lowpass filter with 12dB/octave rolloff.</p>
+
+<blockquote>
+ <dl>
+ <dt>frequency</dt>
+ <dd>The cutoff frequency</dd>
+ <dt>Q</dt>
+ <dd>Controls how peaked the response will be at the cutoff frequency. A
+ large value makes the response more peaked. Please note that for this filter type, this
+ value is not a traditional Q, but is a resonance value in decibels.</dd>
+ <dt>gain</dt>
+ <dd>Not used in this filter type</dd>
+ </dl>
+</blockquote>
+
+<h3 id="HIGHPASS">4.21.2 "highpass"</h3>
+
+<p>A <a href="http://en.wikipedia.org/wiki/High-pass_filter">highpass
+filter</a> is the opposite of a lowpass filter. Frequencies above the cutoff
+frequency are passed through, but frequencies below the cutoff are attenuated.
+It implements a standard second-order resonant highpass filter with
+12dB/octave rolloff.</p>
+
+<blockquote>
+ <dl>
+ <dt>frequency</dt>
+ <dd>The cutoff frequency below which the frequencies are attenuated</dd>
+ <dt>Q</dt>
+ <dd>Controls how peaked the response will be at the cutoff frequency. A
+ large value makes the response more peaked. Please note that for this filter type, this
+ value is not a traditional Q, but is a resonance value in decibels.</dd>
+ <dt>gain</dt>
+ <dd>Not used in this filter type</dd>
+ </dl>
+</blockquote>
+
+<h3 id="BANDPASS">4.21.3 "bandpass"</h3>
+
+<p>A <a href="http://en.wikipedia.org/wiki/Band-pass_filter">bandpass
+filter</a> allows a range of frequencies to pass through and attenuates the
+frequencies below and above this frequency range. It implements a
+second-order bandpass filter.</p>
+
+<blockquote>
+ <dl>
+ <dt>frequency</dt>
+ <dd>The center of the frequency band</dd>
+ <dt><a href="http://en.wikipedia.org/wiki/Q_factor">Q</a></dt>
+ <dd>Controls the width of the band. The width becomes narrower as the Q
+ value increases.</dd>
+ <dt>gain</dt>
+ <dd>Not used in this filter type</dd>
+ </dl>
+</blockquote>
+
+<h3 id="LOWSHELF">4.21.4 "lowshelf"</h3>
+
+<p>The lowshelf filter allows all frequencies through, but adds a boost (or
+attenuation) to the lower frequencies. It implements a second-order
+lowshelf filter.</p>
+
+<blockquote>
+ <dl>
+ <dt>frequency</dt>
+ <dd>The upper limit of the frequences where the boost (or attenuation) is
+ applied.</dd>
+ <dt><a href="http://en.wikipedia.org/wiki/Q_factor">Q</a></dt>
+ <dd>Not used in this filter type.</dd>
+ <dt>gain</dt>
+ <dd>The boost, in dB, to be applied. If the value is negative, the
+ frequencies are attenuated.</dd>
+ </dl>
+</blockquote>
+
+<h3 id="L16352">4.21.5 "highshelf"</h3>
+
+<p>The highshelf filter is the opposite of the lowshelf filter and allows all
+frequencies through, but adds a boost to the higher frequencies. It
+implements a second-order highshelf filter</p>
+
+<blockquote>
+ <dl>
+ <dt>frequency</dt>
+ <dd>The lower limit of the frequences where the boost (or attenuation) is
+ applied.</dd>
+ <dt><a href="http://en.wikipedia.org/wiki/Q_factor">Q</a></dt>
+ <dd>Not used in this filter type.</dd>
+ <dt>gain</dt>
+ <dd>The boost, in dB, to be applied. If the value is negative, the
+ frequencies are attenuated.</dd>
+ </dl>
+</blockquote>
+
+<h3 id="PEAKING">4.21.6 "peaking"</h3>
+
+<p>The peaking filter allows all frequencies through, but adds a boost (or
+attenuation) to a range of frequencies. </p>
+
+<blockquote>
+ <dl>
+ <dt>frequency</dt>
+ <dd>The center frequency of where the boost is applied.</dd>
+ <dt><a href="http://en.wikipedia.org/wiki/Q_factor">Q</a></dt>
+ <dd>Controls the width of the band of frequencies that are boosted. A
+ large value implies a narrow width.</dd>
+ <dt>gain</dt>
+ <dd>The boost, in dB, to be applied. If the value is negative, the
+ frequencies are attenuated.</dd>
+ </dl>
+</blockquote>
+
+<h3 id="NOTCH">4.21.7 "notch"</h3>
+
+<p>The notch filter (also known as a <a
+href="http://en.wikipedia.org/wiki/Band-stop_filter">band-stop or
+band-rejection filter</a>) is the opposite of a bandpass filter. It allows all
+frequencies through, except for a set of frequencies.</p>
+
+<blockquote>
+ <dl>
+ <dt>frequency</dt>
+ <dd>The center frequency of where the notch is applied.</dd>
+ <dt><a href="http://en.wikipedia.org/wiki/Q_factor">Q</a></dt>
+ <dd>Controls the width of the band of frequencies that are attenuated. A
+ large value implies a narrow width.</dd>
+ <dt>gain</dt>
+ <dd>Not used in this filter type.</dd>
+ </dl>
+</blockquote>
+
+<h3 id="ALLPASS">4.21.8 "allpass"</h3>
+
+<p>An <a
+href="http://en.wikipedia.org/wiki/All-pass_filter#Digital_Implementation">allpass
+filter</a> allows all frequencies through, but changes the phase relationship
+between the various frequencies. It implements a second-order allpass
+filter</p>
+
+<blockquote>
+ <dl>
+ <dt>frequency</dt>
+ <dd>The frequency where the center of the phase transition occurs. Viewed
+ another way, this is the frequency with maximal <a
+ href="http://en.wikipedia.org/wiki/Group_delay">group delay</a>.</dd>
+ <dt><a href="http://en.wikipedia.org/wiki/Q_factor">Q</a></dt>
+ <dd>Controls how sharp the phase transition is at the center frequency. A
+ larger value implies a sharper transition and a larger group delay.</dd>
+ <dt>gain</dt>
+ <dd>Not used in this filter type.</dd>
+ </dl>
+</blockquote>
+
+<h3 id="Methods">4.21.9. Methods</h3>
+<dl>
+ <dt id="dfn-getFrequencyResponse">The <code>getFrequencyResponse</code>
+ method</dt>
+ <dd><p>Given the current filter parameter settings, calculates the
+ frequency response for the specified frequencies. </p>
+ <p>The <dfn id="dfn-frequencyHz">frequencyHz</dfn> parameter specifies an
+ array of frequencies at which the response values will be calculated.</p>
+ <p>The <dfn id="dfn-magResponse">magResponse</dfn> parameter specifies an
+ output array receiving the linear magnitude response values.</p>
+ <p>The <dfn id="dfn-phaseResponse">phaseResponse</dfn> parameter
+ specifies an output array receiving the phase response values in
+ radians.</p>
+ </dd>
+</dl>
+</div>
+
+<div id="WaveShaperNode-section" class="section">
+<h2 id="WaveShaperNode">4.22. The WaveShaperNode Interface</h2>
+
+<p>WaveShaperNode is an AudioNode processor implementing non-linear distortion
+effects. </p>
+
+<p>Non-linear waveshaping distortion is commonly used for both subtle
+non-linear warming, or more obvious distortion effects. Arbitrary non-linear
+shaping curves may be specified.</p>
+<pre>
+ numberOfInputs : 1
+ numberOfOutputs : 1
+
+ channelCountMode = "max";
+ channelInterpretation = "speakers";
+</pre>
+
+<p>
+The number of channels of the output always equals the number of channels of the input.
+</p>
+
+<div class="block">
+
+<div class="blockTitleDiv">
+<span class="blockTitle">Web IDL</span></div>
+
+<div class="blockContent">
+<pre class="code"><code class="idl-code" id="wave-shaper-node-idl">
+
+enum <dfn>OverSampleType</dfn> {
+ "none",
+ "2x",
+ "4x"
+};
+
+interface <dfn id="dfn-WaveShaperNode">WaveShaperNode</dfn> : AudioNode {
+
+ attribute Float32Array? curve;
+ attribute OverSampleType oversample;
+
+};
+</code></pre>
+</div>
+</div>
+
+<div id="attributes-WaveShaperNode-section" class="section">
+<h3 id="attributes-WaveShaperNode">4.22.1. Attributes</h3>
+<dl>
+ <dt id="dfn-curve"><code>curve</code></dt>
+ <dd><p>The shaping curve used for the waveshaping effect. The input signal
+ is nominally within the range -1 -&gt; +1. Each input sample within this
+ range will index into the shaping curve with a signal level of zero
+ corresponding to the center value of the curve array. Any sample value
+ less than -1 will correspond to the first value in the curve array. Any
+ sample value greater than +1 will correspond to the last value in
+ the curve array. The implementation must perform linear interpolation between
+ adjacent points in the curve. Initially the curve attribute is null, which means that
+ the WaveShaperNode will pass its input to its output without modification.</p>
+ </dd>
+</dl>
+
+<dl>
+ <dt id="dfn-oversample"><code>oversample</code></dt>
+ <dd><p>Specifies what type of oversampling (if any) should be used when applying the shaping curve.
+ The default value is "none", meaning the curve will be applied directly to the input samples.
+ A value of "2x" or "4x" can improve the quality of the processing by avoiding some aliasing, with
+ the "4x" value yielding the highest quality. For some applications, it's better to use no oversampling
+ in order to get a very precise shaping curve.
+ </p>
+ <p>
+ A value of "2x" or "4x" means that the following steps must be performed:
+ <ol>
+ <li>Up-sample the input samples to 2x or 4x the sample-rate of the AudioContext. Thus for each
+ processing block of 128 samples, generate 256 (for 2x) or 512 (for 4x) samples.</li>
+ <li>Apply the shaping curve.</li>
+ <li>Down-sample the result back to the sample-rate of the AudioContext. Thus taking the 256 (or 512) processed samples, generating 128 as
+ the final result.
+ </ol>
+ The exact up-sampling and down-sampling filters are not specified, and can be tuned for sound quality (low aliasing, etc.), low latency, and performance.
+ </p>
+ </dd>
+</dl>
+</div>
+</div>
+
+<div id="OscillatorNode-section" class="section">
+<h2 id="OscillatorNode">4.23. The OscillatorNode Interface</h2>
+
+<p>OscillatorNode represents an audio source generating a periodic waveform. It can be set to
+a few commonly used waveforms. Additionally, it can be set to an arbitrary periodic
+waveform through the use of a <a href="#PeriodicWave-section"><code>PeriodicWave</code></a> object. </p>
+
+<p>Oscillators are common foundational building blocks in audio synthesis. An OscillatorNode will start emitting sound at the time
+specified by the <code>start()</code> method. </p>
+
+<p>
+Mathematically speaking, a <em>continuous-time</em> periodic waveform can have very high (or infinitely high) frequency information when considered
+in the frequency domain. When this waveform is sampled as a discrete-time digital audio signal at a particular sample-rate,
+then care must be taken to discard (filter out) the high-frequency information higher than the <em>Nyquist</em> frequency (half the sample-rate)
+before converting the waveform to a digital form. If this is not done, then <em>aliasing</em> of higher frequencies (than the Nyquist frequency) will fold
+back as mirror images into frequencies lower than the Nyquist frequency. In many cases this will cause audibly objectionable artifacts.
+This is a basic and well understood principle of audio DSP.
+</p>
+
+<p>
+There are several practical approaches that an implementation may take to avoid this aliasing.
+But regardless of approach, the <em>idealized</em> discrete-time digital audio signal is well defined mathematically.
+The trade-off for the implementation is a matter of implementation cost (in terms of CPU usage) versus fidelity to
+achieving this ideal.
+</p>
+
+<p>
+It is expected that an implementation will take some care in achieving this ideal, but it is reasonable to consider lower-quality,
+less-costly approaches on lower-end hardware.
+</p>
+
+<p>
+Both .frequency and .detune are <em>a-rate</em> parameters and are used together to determine a <em>computedFrequency</em> value:
+</p>
+
+<pre>
+computedFrequency(t) = frequency(t) * pow(2, detune(t) / 1200)
+</pre>
+
+<p>
+The OscillatorNode's instantaneous phase at each time is the time integral of <em>computedFrequency</em>.
+</p>
+
+<pre> numberOfInputs : 0
+ numberOfOutputs : 1 (mono output)
+ </pre>
+
+<div class="block">
+
+<div class="blockTitleDiv">
+<span class="blockTitle">Web IDL</span></div>
+
+<div class="blockContent">
+<pre class="code"><code class="idl-code" id="oscillator-node-idl">
+
+enum <dfn>OscillatorType</dfn> {
+ "sine",
+ "square",
+ "sawtooth",
+ "triangle",
+ "custom"
+};
+
+interface <dfn id="dfn-OscillatorNode">OscillatorNode</dfn> : AudioNode {
+
+ attribute OscillatorType type;
+
+ readonly attribute AudioParam frequency; // in Hertz
+ readonly attribute AudioParam detune; // in Cents
+
+ void start(double when);
+ void stop(double when);
+ void setPeriodicWave(PeriodicWave periodicWave);
+
+ attribute EventHandler onended;
+
+};
+</code></pre>
+</div>
+</div>
+
+<div id="attributes-OscillatorNode-section" class="section">
+<h3 id="attributes-OscillatorNode">4.23.1. Attributes</h3>
+<dl>
+ <dt id="dfn-type"><code>type</code></dt>
+ <dd><p>The shape of the periodic waveform. It may directly be set to any of the type constant values except for "custom".
+ The <a href="#dfn-setPeriodicWave"><code>setPeriodicWave()</code></a> method can be used to set a custom waveform, which results in this attribute
+ being set to "custom". The default value is "sine". </p>
+ </dd>
+</dl>
+
+<dl>
+ <dt id="dfn-frequency"><code>frequency</code></dt>
+ <dd><p>The frequency (in Hertz) of the periodic waveform. This parameter is <em>a-rate</em> </p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-detune"><code>detune</code></dt>
+ <dd><p>A detuning value (in Cents) which will offset the <code>frequency</code> by the given amount.
+ This parameter is <em>a-rate</em> </p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-onended"><code>onended</code></dt>
+ <dd><p>A property used to set the <code>EventHandler</code> (described in <cite><a
+ href="http://www.whatwg.org/specs/web-apps/current-work/#eventhandler">HTML</a></cite>)
+ for the ended event that is dispatched to <a
+ href="#OscillatorNode-section"><code>OscillatorNode</code></a>
+ node types. When the playback of the buffer for an <code>OscillatorNode</code>
+ is finished, an event of type <code>Event</code> (described in <cite><a
+ href="http://www.whatwg.org/specs/web-apps/current-work/#event">HTML</a></cite>)
+ will be dispatched to the event handler. </p>
+ </dd>
+</dl>
+</div>
+</div>
+
+<div id="methodsandparams-OscillatorNode-section" class="section">
+<h3 id="methodsandparams-OscillatorNode">4.23.2. Methods and Parameters</h3>
+<dl>
+ <dt id="dfn-setPeriodicWave">The <code>setPeriodicWave</code>
+ method</dt>
+ <dd><p>Sets an arbitrary custom periodic waveform given a <a href="#PeriodicWave-section"><code>PeriodicWave</code></a>.</p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-start-AudioBufferSourceNode">The <code>start</code>
+ method</dt>
+ <dd><p>defined as in <a href="#AudioBufferSourceNode-section"><code>AudioBufferSourceNode</code></a>. </p>
+ </dd>
+</dl>
+<dl>
+ <dt id="dfn-stop-AudioBufferSourceNode">The <code>stop</code>
+ method</dt>
+ <dd><p>defined as in <a href="#AudioBufferSourceNode-section"><code>AudioBufferSourceNode</code></a>. </p>
+ </dd>
+</dl>
+</div>
+
+
+<div id="PeriodicWave-section" class="section">
+<h2 id="PeriodicWave">4.24. The PeriodicWave Interface</h2>
+
+<p>PeriodicWave represents an arbitrary periodic waveform to be used with an <a href="#OscillatorNode-section"><code>OscillatorNode</code></a>.
+Please see <a href="#dfn-createPeriodicWave">createPeriodicWave()</a> and <a href="#dfn-setPeriodicWave">setPeriodicWave()</a> and for more details. </p>
+
+<div class="block">
+
+<div class="blockTitleDiv">
+<span class="blockTitle">Web IDL</span></div>
+
+<div class="blockContent">
+<pre class="code"><code class="idl-code" id="wavetable-idl">
+
+interface <dfn id="dfn-PeriodicWave">PeriodicWave</dfn> {
+
+};
+</code></pre>
+</div>
+</div>
+</div>
+
+<div id="MediaStreamAudioSourceNode-section" class="section">
+<h2 id="MediaStreamAudioSourceNode">4.25. The MediaStreamAudioSourceNode
+Interface</h2>
+
+<p>This interface represents an audio source from a <code>MediaStream</code>.
+The first <code>AudioMediaStreamTrack</code> from the <code>MediaStream</code> will be
+used as a source of audio.</p>
+<pre> numberOfInputs : 0
+ numberOfOutputs : 1
+</pre>
+
+ <p>
+ The number of channels of the output corresponds to the number of channels of the <code>AudioMediaStreamTrack</code>.
+ If there is no valid audio track, then the number of channels output will be one silent channel.
+ </p>
+
+<div class="block">
+
+<div class="blockTitleDiv">
+<span class="blockTitle">Web IDL</span></div>
+
+<div class="blockContent">
+<pre class="code"><code class="idl-code" id="media-stream-audio-source-node-idl">
+
+interface <dfn id="dfn-MediaStreamAudioSourceNode">MediaStreamAudioSourceNode</dfn> : AudioNode {
+
+};
+</code></pre>
+</div>
+</div>
+</div>
+
+<div id="MediaStreamAudioDestinationNode-section" class="section">
+<h2 id="MediaStreamAudioDestinationNode">4.26. The MediaStreamAudioDestinationNode
+Interface</h2>
+
+<p>This interface is an audio destination representing a <code>MediaStream</code> with a single <code>AudioMediaStreamTrack</code>.
+This MediaStream is created when the node is created and is accessible via the <dfn>stream</dfn> attribute.
+This stream can be used in a similar way as a MediaStream obtained via getUserMedia(), and
+can, for example, be sent to a remote peer using the RTCPeerConnection addStream() method.
+</p>
+<pre>
+ numberOfInputs : 1
+ numberOfOutputs : 0
+
+ channelCount = 2;
+ channelCountMode = "explicit";
+ channelInterpretation = "speakers";
+</pre>
+
+<p>
+The number of channels of the input is by default 2 (stereo). Any connections to the input
+are up-mixed/down-mixed to the number of channels of the input.
+</p>
+
+<div class="block">
+
+<div class="blockTitleDiv">
+<span class="blockTitle">Web IDL</span></div>
+
+<div class="blockContent">
+<pre class="code"><code class="idl-code" id="media-stream-audio-destination-node-idl">
+
+interface <dfn id="dfn-MediaStreamAudioDestinationNode">MediaStreamAudioDestinationNode</dfn> : AudioNode {
+
+ readonly attribute MediaStream stream;
+
+};
+</code></pre>
+</div>
+</div>
+
+<div id="attributes-MediaStreamAudioDestinationNode-section" class="section">
+<h3 id="attributes-MediaStreamAudioDestinationNode">4.26.1. Attributes</h3>
+<dl>
+ <dt id="dfn-stream"><code>stream</code></dt>
+ <dd><p>A MediaStream containing a single AudioMediaStreamTrack with the same number of channels
+ as the node itself.</p>
+ </dd>
+</dl>
+</div>
+
+</div>
+
+<div id="MixerGainStructure-section" class="section">
+<h2 id="MixerGainStructure">6. Mixer Gain Structure</h2>
+
+<p class="norm">This section is informative.</p>
+
+<h3 id="background">Background</h3>
+
+<p>One of the most important considerations when dealing with audio processing
+graphs is how to adjust the gain (volume) at various points. For example, in a
+standard mixing board model, each input bus has pre-gain, post-gain, and
+send-gains. Submix and master out busses also have gain control. The gain
+control described here can be used to implement standard mixing boards as well
+as other architectures. </p>
+
+<div id="SummingJunction-section" class="section">
+<h3 id="SummingJunction">Summing Inputs</h3>
+</div>
+
+<p>The inputs to <a href="#AudioNode-section"><code>AudioNodes</code></a> have
+the ability to accept connections from multiple outputs. The input then acts as
+a unity gain summing junction with each output signal being added with the
+others: </p>
+<img alt="unity gain summing junction"
+src="images/unity-gain-summing-junction.png" />
+
+<p>In cases where the channel layouts of the outputs do not match, a mix (usually up-mix) will occur according to the <a
+href="#UpMix-section">mixing rules</a>.
+</p>
+
+<h3 id="gain-Control">Gain Control</h3>
+
+<p>But many times, it's important to be able to control the gain for each of
+the output signals. The <a
+href="#GainNode-section"><code>GainNode</code></a> gives this
+control: </p>
+<img alt="mixer architecture new" src="images/mixer-architecture-new.png" />
+
+<p>Using these two concepts of unity gain summing junctions and GainNodes,
+it's possible to construct simple or complex mixing scenarios. </p>
+
+<h3 id="Example-mixer-with-send-busses">Example: Mixer with Send Busses</h3>
+
+<p>In a routing scenario involving multiple sends and submixes, explicit
+control is needed over the volume or "gain" of each connection to a mixer. Such
+routing topologies are very common and exist in even the simplest of electronic
+gear sitting around in a basic recording studio. </p>
+
+<p>Here's an example with two send mixers and a main mixer. Although possible,
+for simplicity's sake, pre-gain control and insert effects are not illustrated:
+</p>
+<img alt="mixer gain structure" src="images/mixer-gain-structure.png" />
+
+<p>This diagram is using a shorthand notation where "send 1", "send 2", and
+"main bus" are actually inputs to AudioNodes, but here are represented as
+summing busses, where the intersections g2_1, g3_1, etc. represent the "gain"
+or volume for the given source on the given mixer. In order to expose this
+gain, an <a href="#dfn-GainNode"><code>GainNode</code></a> is used:
+</p>
+
+<p>Here's how the above diagram could be constructed in JavaScript: </p>
+
+<div class="example">
+
+<div class="exampleHeader">
+Example</div>
+
+<div class="block">
+
+<div class="blockTitleDiv">
+<span class="blockTitle">ECMAScript</span></div>
+
+<div class="blockContent">
+<pre class="code"><code class="es-code">
+
+var context = 0;
+var compressor = 0;
+var reverb = 0;
+var delay = 0;
+var s1 = 0;
+var s2 = 0;
+
+var source1 = 0;
+var source2 = 0;
+var g1_1 = 0;
+var g2_1 = 0;
+var g3_1 = 0;
+var g1_2 = 0;
+var g2_2 = 0;
+var g3_2 = 0;
+
+<span class="comment">// Setup routing graph </span>
+function setupRoutingGraph() {
+ context = new AudioContext();
+
+ compressor = context.createDynamicsCompressor();
+
+ <span class="comment">// Send1 effect </span>
+ reverb = context.createConvolver();
+ <span class="comment">// Convolver impulse response may be set here or later </span>
+
+ <span class="comment">// Send2 effect </span>
+ delay = context.createDelay();
+
+ <span class="comment">// Connect final compressor to final destination </span>
+ compressor.connect(context.destination);
+
+ <span class="comment">// Connect sends 1 &amp; 2 through effects to main mixer </span>
+ s1 = context.createGain();
+ reverb.connect(s1);
+ s1.connect(compressor);
+
+ s2 = context.createGain();
+ delay.connect(s2);
+ s2.connect(compressor);
+
+ <span class="comment">// Create a couple of sources </span>
+ source1 = context.createBufferSource();
+ source2 = context.createBufferSource();
+ source1.buffer = manTalkingBuffer;
+ source2.buffer = footstepsBuffer;
+
+ <span class="comment">// Connect source1 </span>
+ g1_1 = context.createGain();
+ g2_1 = context.createGain();
+ g3_1 = context.createGain();
+ source1.connect(g1_1);
+ source1.connect(g2_1);
+ source1.connect(g3_1);
+ g1_1.connect(compressor);
+ g2_1.connect(reverb);
+ g3_1.connect(delay);
+
+ <span class="comment">// Connect source2 </span>
+ g1_2 = context.createGain();
+ g2_2 = context.createGain();
+ g3_2 = context.createGain();
+ source2.connect(g1_2);
+ source2.connect(g2_2);
+ source2.connect(g3_2);
+ g1_2.connect(compressor);
+ g2_2.connect(reverb);
+ g3_2.connect(delay);
+
+ <span class="comment">// We now have explicit control over all the volumes g1_1, g2_1, ..., s1, s2 </span>
+ g2_1.gain.value = 0.2; <span class="comment"> // For example, set source1 reverb gain </span>
+
+ <span class="comment"> // Because g2_1.gain is an "AudioParam", </span>
+ <span class="comment"> // an automation curve could also be attached to it. </span>
+ <span class="comment"> // A "mixing board" UI could be created in canvas or WebGL controlling these gains. </span>
+}
+
+ </code></pre>
+</div>
+</div>
+</div>
+</div>
+<br />
+
+
+<div id="DynamicLifetime-section">
+<h2 id="DynamicLifetime">7. Dynamic Lifetime</h2>
+
+<h3 id="DynamicLifetime-background">Background</h3>
+
+<p class="norm">This section is informative. Please see <a href="#lifetime-AudioContext">AudioContext lifetime</a>
+and <a href="#lifetime-AudioNode">AudioNode lifetime</a> for normative requirements
+</p>
+
+<p>In addition to allowing the creation of static routing configurations, it
+should also be possible to do custom effect routing on dynamically allocated
+voices which have a limited lifetime. For the purposes of this discussion,
+let's call these short-lived voices "notes". Many audio applications
+incorporate the ideas of notes, examples being drum machines, sequencers, and
+3D games with many one-shot sounds being triggered according to game play. </p>
+
+<p>In a traditional software synthesizer, notes are dynamically allocated and
+released from a pool of available resources. The note is allocated when a MIDI
+note-on message is received. It is released when the note has finished playing
+either due to it having reached the end of its sample-data (if non-looping), it
+having reached a sustain phase of its envelope which is zero, or due to a MIDI
+note-off message putting it into the release phase of its envelope. In the MIDI
+note-off case, the note is not released immediately, but only when the release
+envelope phase has finished. At any given time, there can be a large number of
+notes playing but the set of notes is constantly changing as new notes are
+added into the routing graph, and old ones are released. </p>
+
+<p>The audio system automatically deals with tearing-down the part of the
+routing graph for individual "note" events. A "note" is represented by an
+<code>AudioBufferSourceNode</code>, which can be directly connected to other
+processing nodes. When the note has finished playing, the context will
+automatically release the reference to the <code>AudioBufferSourceNode</code>,
+which in turn will release references to any nodes it is connected to, and so
+on. The nodes will automatically get disconnected from the graph and will be
+deleted when they have no more references. Nodes in the graph which are
+long-lived and shared between dynamic voices can be managed explicitly.
+Although it sounds complicated, this all happens automatically with no extra
+JavaScript handling required. </p>
+
+<h3 id="Example-DynamicLifetime">Example</h3>
+
+<div class="example">
+
+<div class="exampleHeader">
+Example</div>
+<img alt="dynamic allocation" src="images/dynamic-allocation.png" />
+
+<p>The low-pass filter, panner, and second gain nodes are directly connected
+from the one-shot sound. So when it has finished playing the context will
+automatically release them (everything within the dotted line). If there are no
+longer any JavaScript references to the one-shot sound and connected nodes,
+then they will be immediately removed from the graph and deleted. The streaming
+source, has a global reference and will remain connected until it is explicitly
+disconnected. Here's how it might look in JavaScript: </p>
+
+<div class="block">
+
+<div class="blockTitleDiv">
+<span class="blockTitle">ECMAScript</span></div>
+
+<div class="blockContent">
+<pre class="code"><code class="es-code">
+
+var context = 0;
+var compressor = 0;
+var gainNode1 = 0;
+var streamingAudioSource = 0;
+
+<span class="comment">// Initial setup of the "long-lived" part of the routing graph </span>
+function setupAudioContext() {
+ context = new AudioContext();
+
+ compressor = context.createDynamicsCompressor();
+ gainNode1 = context.createGain();
+
+ // Create a streaming audio source.
+ var audioElement = document.getElementById('audioTagID');
+ streamingAudioSource = context.createMediaElementSource(audioElement);
+ streamingAudioSource.connect(gainNode1);
+
+ gainNode1.connect(compressor);
+ compressor.connect(context.destination);
+}
+
+<span class="comment">// Later in response to some user action (typically mouse or key event) </span>
+<span class="comment">// a one-shot sound can be played. </span>
+function playSound() {
+ var oneShotSound = context.createBufferSource();
+ oneShotSound.buffer = dogBarkingBuffer;
+
+ <span class="comment">// Create a filter, panner, and gain node. </span>
+ var lowpass = context.createBiquadFilter();
+ var panner = context.createPanner();
+ var gainNode2 = context.createGain();
+
+ <span class="comment">// Make connections </span>
+ oneShotSound.connect(lowpass);
+ lowpass.connect(panner);
+ panner.connect(gainNode2);
+ gainNode2.connect(compressor);
+
+ <span class="comment">// Play 0.75 seconds from now (to play immediately pass in 0)</span>
+ oneShotSound.start(context.currentTime + 0.75);
+}
+</code></pre>
+</div>
+</div>
+</div>
+</div>
+
+
+
+<div id="UpMix-section" class="section">
+<h2 id="UpMix">9. Channel up-mixing and down-mixing</h2>
+
+<p class="norm">This section is normative.</p>
+
+<img src="images/unity-gain-summing-junction.png">
+
+<p>
+<a href="#MixerGainStructure-section">Mixer Gain Structure</a>
+describes how an <dfn>input</dfn> to an AudioNode can be connected from one or more <dfn>outputs</dfn>
+of an AudioNode. Each of these connections from an output represents a stream with
+a specific non-zero number of channels. An input has <em>mixing rules</em> for combining the channels
+from all of the connections to it. As a simple example, if an input is connected from a mono output and
+a stereo output, then the mono connection will usually be up-mixed to stereo and summed with
+the stereo connection. But, of course, it's important to define the exact <em>mixing rules</em> for
+every input to every AudioNode. The default mixing rules for all of the inputs have been chosen so that
+things "just work" without worrying too much about the details, especially in the very common
+case of mono and stereo streams. But the rules can be changed for advanced use cases, especially
+multi-channel.
+</p>
+
+<p>
+To define some terms, <em>up-mixing</em> refers to the process of taking a stream with a smaller
+number of channels and converting it to a stream with a larger number of channels. <em>down-mixing</em>
+refers to the process of taking a stream with a larger number of channels and converting it to a stream
+with a smaller number of channels.
+</p>
+
+<p>
+An AudioNode input use three basic pieces of information to determine how to mix all the outputs
+connected to it. As part of this process it computes an internal value <dfn>computedNumberOfChannels</dfn>
+ representing the actual number of channels of the input at any given time:
+</p>
+
+<p>
+The AudioNode attributes involved in channel up-mixing and down-mixing rules are defined
+<a href="#attributes-AudioNode-section">above</a>. The following is a more precise specification
+on what each of them mean.
+</p>
+
+<ul>
+<li><dfn>channelCount</dfn> is used to help compute <dfn>computedNumberOfChannels</dfn>.</li>
+
+<li><dfn>channelCountMode</dfn> determines how <dfn>computedNumberOfChannels</dfn> will be computed.
+Once this number is computed, all of the connections will be up or down-mixed to that many channels. For most nodes,
+the default value is "max".
+<ul>
+<li>“max”: <dfn>computedNumberOfChannels</dfn> is computed as the maximum of the number of channels of all connections.
+In this mode <dfn>channelCount</dfn> is ignored.</li>
+<li>“clamped-max”: same as “max” up to a limit of the <dfn>channelCount</dfn></li>
+<li>“explicit”: <dfn>computedNumberOfChannels</dfn> is the exact value as specified in <dfn>channelCount</dfn></li>
+</ul>
+
+</li>
+
+<li><dfn>channelInterpretation</dfn> determines how the individual channels will be treated.
+For example, will they be treated as speakers having a specific layout, or will they
+be treated as simple discrete channels? This value influences exactly how the up and down mixing is
+performed. The default value is "speakers".
+
+<ul>
+<li>“speakers”: use <a href="#ChannelLayouts">up-down-mix equations for mono/stereo/quad/5.1</a>.
+In cases where the number of channels do not match any of these basic speaker layouts, revert
+to "discrete".
+</li>
+<li>“discrete”: up-mix by filling channels until they run out then zero out remaining channels.
+ down-mix by filling as many channels as possible, then dropping remaining channels</li>
+</ul>
+
+</li>
+
+</ul>
+
+<p>
+For each input of an AudioNode, an implementation must:
+</p>
+
+<ol>
+<li>Compute <dfn>computedNumberOfChannels</dfn>.</li>
+<li>For each connection to the input:
+<ul>
+<li> up-mix or down-mix the connection to <dfn>computedNumberOfChannels</dfn> according to <dfn>channelInterpretation</dfn>.</li>
+<li> Mix it together with all of the other mixed streams (from other connections). This is a straight-forward mixing together of each of the corresponding channels from each
+connection.</li>
+</ul>
+</li>
+</ol>
+
+
+
+
+<div id="ChannelLayouts-section" class="section">
+<h3 id="ChannelLayouts">9.1. Speaker Channel Layouts</h3>
+
+<p class="norm">This section is normative.</p>
+
+<p>
+When <dfn>channelInterpretation</dfn> is "speakers" then the up-mixing and down-mixing
+is defined for specific channel layouts.
+</p>
+
+<p>It's important to define the channel ordering (and define some
+abbreviations) for these speaker layouts.</p>
+
+<p>
+For now, only considers cases for mono, stereo, quad, 5.1. Later other channel
+layouts can be defined.
+</p>
+
+<h4 id ="ChannelOrdering">9.1.1. Channel ordering</h4>
+
+<pre> Mono
+ 0: M: mono
+
+ Stereo
+ 0: L: left
+ 1: R: right
+ </pre>
+
+<pre> Quad
+ 0: L: left
+ 1: R: right
+ 2: SL: surround left
+ 3: SR: surround right
+
+ 5.1
+ 0: L: left
+ 1: R: right
+ 2: C: center
+ 3: LFE: subwoofer
+ 4: SL: surround left
+ 5: SR: surround right
+ </pre>
+</div>
+
+<h4 id="UpMix-sub">9.1.2. Up Mixing speaker layouts</h4>
+
+<pre>Mono up-mix:
+
+ 1 -&gt; 2 : up-mix from mono to stereo
+ output.L = input;
+ output.R = input;
+
+ 1 -&gt; 4 : up-mix from mono to quad
+ output.L = input;
+ output.R = input;
+ output.SL = 0;
+ output.SR = 0;
+
+ 1 -&gt; 5.1 : up-mix from mono to 5.1
+ output.L = 0;
+ output.R = 0;
+ output.C = input; // put in center channel
+ output.LFE = 0;
+ output.SL = 0;
+ output.SR = 0;
+
+Stereo up-mix:
+
+ 2 -&gt; 4 : up-mix from stereo to quad
+ output.L = input.L;
+ output.R = input.R;
+ output.SL = 0;
+ output.SR = 0;
+
+ 2 -&gt; 5.1 : up-mix from stereo to 5.1
+ output.L = input.L;
+ output.R = input.R;
+ output.C = 0;
+ output.LFE = 0;
+ output.SL = 0;
+ output.SR = 0;
+
+Quad up-mix:
+
+ 4 -&gt; 5.1 : up-mix from stereo to 5.1
+ output.L = input.L;
+ output.R = input.R;
+ output.C = 0;
+ output.LFE = 0;
+ output.SL = input.SL;
+ output.SR = input.SR;</pre>
+
+<h4 id="down-mix">9.1.3. Down Mixing speaker layouts</h4>
+
+<p>A down-mix will be necessary, for example, if processing 5.1 source
+material, but playing back stereo. </p>
+<pre>
+Mono down-mix:
+
+ 2 -&gt; 1 : stereo to mono
+ output = 0.5 * (input.L + input.R);
+
+ 4 -&gt; 1 : quad to mono
+ output = 0.25 * (input.L + input.R + input.SL + input.SR);
+
+ 5.1 -&gt; 1 : 5.1 to mono
+ output = 0.7071 * (input.L + input.R) + input.C + 0.5 * (input.SL + input.SR)
+
+
+Stereo down-mix:
+
+ 4 -&gt; 2 : quad to stereo
+ output.L = 0.5 * (input.L + input.SL);
+ output.R = 0.5 * (input.R + input.SR);
+
+ 5.1 -&gt; 2 : 5.1 to stereo
+ output.L = L + 0.7071 * (input.C + input.SL)
+ output.R = R + 0.7071 * (input.C + input.SR)
+
+Quad down-mix:
+
+ 5.1 -&gt; 4 : 5.1 to quad
+ output.L = L + 0.7071 * input.C
+ output.R = R + 0.7071 * input.C
+ output.SL = input.SL
+ output.SR = input.SR
+
+</pre>
+</div>
+
+<h3 id="ChannelRules-section">9.2. Channel Rules Examples</h3>
+
+<p class="norm">This section is informative.</p>
+
+<div class="block">
+<div class="blockTitleDiv">
+<div class="blockContent">
+<pre class="code"><code class="idl-code">
+// Set gain node to explicit 2-channels (stereo).
+gain.channelCount = 2;
+gain.channelCountMode = "explicit";
+gain.channelInterpretation = "speakers";
+
+// Set "hardware output" to 4-channels for DJ-app with two stereo output busses.
+context.destination.channelCount = 4;
+context.destination.channelCountMode = "explicit";
+context.destination.channelInterpretation = "discrete";
+
+// Set "hardware output" to 8-channels for custom multi-channel speaker array
+// with custom matrix mixing.
+context.destination.channelCount = 8;
+context.destination.channelCountMode = "explicit";
+context.destination.channelInterpretation = "discrete";
+
+// Set "hardware output" to 5.1 to play an HTMLAudioElement.
+context.destination.channelCount = 6;
+context.destination.channelCountMode = "explicit";
+context.destination.channelInterpretation = "speakers";
+
+// Explicitly down-mix to mono.
+gain.channelCount = 1;
+gain.channelCountMode = "explicit";
+gain.channelInterpretation = "speakers";
+</code></pre>
+</div>
+</div>
+</div>
+
+
+<div id="Spatialization-section" class="section">
+<h2 id="Spatialization">11. Spatialization / Panning </h2>
+
+<h3 id="Spatialization-background">Background</h3>
+
+<p>A common feature requirement for modern 3D games is the ability to
+dynamically spatialize and move multiple audio sources in 3D space. Game audio
+engines such as OpenAL, FMOD, Creative's EAX, Microsoft's XACT Audio, etc. have
+this ability. </p>
+
+<p>Using an <code>PannerNode</code>, an audio stream can be spatialized or
+positioned in space relative to an <code>AudioListener</code>. An <a
+href="#AudioContext-section"><code>AudioContext</code></a> will contain a
+single <code>AudioListener</code>. Both panners and listeners have a position
+in 3D space using a right-handed cartesian coordinate system.
+The units used in the coordinate system are not defined, and do not need to be
+because the effects calculated with these coordinates are independent/invariant
+of any particular units such as meters or feet. <code>PannerNode</code>
+objects (representing the source stream) have an <code>orientation</code>
+vector representing in which direction the sound is projecting. Additionally,
+they have a <code>sound cone</code> representing how directional the sound is.
+For example, the sound could be omnidirectional, in which case it would be
+heard anywhere regardless of its orientation, or it can be more directional and
+heard only if it is facing the listener. <code>AudioListener</code> objects
+(representing a person's ears) have an <code>orientation</code> and
+<code>up</code> vector representing in which direction the person is facing.
+Because both the source stream and the listener can be moving, they both have a
+<code>velocity</code> vector representing both the speed and direction of
+movement. Taken together, these two velocities can be used to generate a
+doppler shift effect which changes the pitch. </p>
+
+<p>
+During rendering, the <code>PannerNode</code> calculates an <em>azimuth</em>
+and <em>elevation</em>. These values are used internally by the implementation in
+order to render the spatialization effect. See the <a href="#Spatialization-panning-algorithm">Panning Algorithm</a> section
+for details of how these values are used.
+</p>
+
+<p>
+The following algorithm must be used to calculate the <em>azimuth</em>
+and <em>elevation</em>:
+</p>
+
+<div class="block">
+<div class="blockTitleDiv">
+<div class="blockContent">
+<pre class="code"><code class="es-code">
+// Calculate the source-listener vector.
+vec3 sourceListener = source.position - listener.position;
+
+if (sourceListener.isZero()) {
+ // Handle degenerate case if source and listener are at the same point.
+ azimuth = 0;
+ elevation = 0;
+ return;
+}
+
+sourceListener.normalize();
+
+// Align axes.
+vec3 listenerFront = listener.orientation;
+vec3 listenerUp = listener.up;
+vec3 listenerRight = listenerFront.cross(listenerUp);
+listenerRight.normalize();
+
+vec3 listenerFrontNorm = listenerFront;
+listenerFrontNorm.normalize();
+
+vec3 up = listenerRight.cross(listenerFrontNorm);
+
+float upProjection = sourceListener.dot(up);
+
+vec3 projectedSource = sourceListener - upProjection * up;
+projectedSource.normalize();
+
+azimuth = 180 * acos(projectedSource.dot(listenerRight)) / PI;
+
+// Source in front or behind the listener.
+double frontBack = projectedSource.dot(listenerFrontNorm);
+if (frontBack &lt; 0)
+ azimuth = 360 - azimuth;
+
+// Make azimuth relative to "front" and not "right" listener vector.
+if ((azimuth >= 0) &amp;&amp; (azimuth &lt;= 270))
+ azimuth = 90 - azimuth;
+else
+ azimuth = 450 - azimuth;
+
+elevation = 90 - 180 * acos(sourceListener.dot(up)) / PI;
+
+if (elevation > 90)
+ elevation = 180 - elevation;
+else if (elevation &lt; -90)
+ elevation = -180 - elevation;
+</code></pre>
+</div>
+</div>
+</div>
+
+<h3 id="Spatialization-panning-algorithm">Panning Algorithm</h3>
+
+<p>
+<em>mono->stereo</em> and <em>stereo->stereo</em> panning must be supported.
+<em>mono->stereo</em> processing is used when all connections to the input are mono.
+Otherwise <em>stereo->stereo</em> processing is used.</p>
+
+<p>The following algorithms must be implemented: </p>
+<ul>
+ <li>Equal-power (Vector-based) panning
+ <p>This is a simple and relatively inexpensive algorithm which provides
+ basic, but reasonable results. It is commonly used when panning musical sources.
+ </p>
+ The <em>elevation</em> value is ignored in this panning algorithm.
+
+ <p>
+ The following steps are used for processing:
+ </p>
+
+ <ol>
+
+ <li>
+ <p>
+ The <em>azimuth</em> value is first contained to be within the range -90 &lt;= <em>azimuth</em> &lt;= +90 according to:
+ </p>
+ <pre>
+ // Clamp azimuth to allowed range of -180 -> +180.
+ azimuth = max(-180, azimuth);
+ azimuth = min(180, azimuth);
+
+ // Now wrap to range -90 -> +90.
+ if (azimuth &lt; -90)
+ azimuth = -180 - azimuth;
+ else if (azimuth > 90)
+ azimuth = 180 - azimuth;
+ </pre>
+ </li>
+
+ <li>
+ <p>
+ A 0 -> 1 normalized value <em>x</em> is calculated from <em>azimuth</em> for <em>mono->stereo</em> as:
+ </p>
+ <pre>
+ x = (azimuth + 90) / 180
+ </pre>
+
+ <p>
+ Or for <em>stereo->stereo</em> as:
+ </p>
+ <pre>
+ if (azimuth &lt;= 0) { // from -90 -> 0
+ // inputL -> outputL and "equal-power pan" inputR as in mono case
+ // by transforming the "azimuth" value from -90 -> 0 degrees into the range -90 -> +90.
+ x = (azimuth + 90) / 90;
+ } else { // from 0 -> +90
+ // inputR -> outputR and "equal-power pan" inputL as in mono case
+ // by transforming the "azimuth" value from 0 -> +90 degrees into the range -90 -> +90.
+ x = azimuth / 90;
+ }
+ </pre>
+ </li>
+
+ <li>
+ <p>
+ Left and right gain values are then calculated:
+ </p>
+ <pre>
+ gainL = cos(0.5 * PI * x);
+ gainR = sin(0.5 * PI * x);
+ </pre>
+ </li>
+
+ <li>
+ <p>For <em>mono->stereo</em>, the output is calculated as:</p>
+ <pre>
+ outputL = input * gainL
+ outputR = input * gainR
+ </pre>
+ <p>Else for <em>stereo->stereo</em>, the output is calculated as:</p>
+ <pre>
+ if (azimuth &lt;= 0) { // from -90 -> 0
+ outputL = inputL + inputR * gainL;
+ outputR = inputR * gainR;
+ } else { // from 0 -> +90
+ outputL = inputL * gainL;
+ outputR = inputR + inputL * gainR;
+ }
+ </pre>
+ </li>
+
+ </ol>
+
+
+
+ </li>
+ <li><a
+ href="http://en.wikipedia.org/wiki/Head-related_transfer_function">HRTF</a>
+ panning (stereo only)
+ <p>This requires a set of HRTF impulse responses recorded at a variety of
+ azimuths and elevations. There are a small number of open/free impulse
+ responses available. The implementation requires a highly optimized
+ convolution function. It is somewhat more costly than "equal-power", but
+ provides a more spatialized sound. </p>
+ <img alt="HRTF panner" src="images/HRTF_panner.png" /></li>
+</ul>
+
+<h3 id="Spatialization-distance-effects">Distance Effects</h3>
+<p>
+Sounds which are closer are louder, while sounds further away are quieter.
+Exactly <em>how</em> a sound's volume changes according to distance from the listener
+depends on the <em>distanceModel</em> attribute.
+</p>
+
+
+<p>
+During audio rendering, a <em>distance</em> value will be calculated based on the panner and listener positions according to:
+</p>
+<pre>
+v = panner.position - listener.position
+</pre>
+<pre>
+distance = sqrt(dot(v, v))
+</pre>
+
+<p>
+<em>distance</em> will then be used to calculate <em>distanceGain</em> which depends
+on the <em>distanceModel</em> attribute. See the <a href="#dfn-distanceModel">distanceModel</a> section for details of
+how this is calculated for each distance model.
+</p>
+<p>As part of its processing, the <code>PannerNode</code> scales/multiplies the input audio signal by <em>distanceGain</em>
+to make distant sounds quieter and nearer ones louder.
+</p>
+
+
+
+
+<h3 id="Spatialization-sound-cones">Sound Cones</h3>
+
+<p>The listener and each sound source have an orientation vector describing
+which way they are facing. Each sound source's sound projection characteristics
+are described by an inner and outer "cone" describing the sound intensity as a
+function of the source/listener angle from the source's orientation vector.
+Thus, a sound source pointing directly at the listener will be louder than if
+it is pointed off-axis. Sound sources can also be omni-directional. </p>
+
+<p>
+The following algorithm must be used to calculate the gain contribution due
+to the cone effect, given the source (the <code>PannerNode</code>) and the listener:
+</p>
+
+<div class="block">
+<div class="blockTitleDiv">
+<div class="blockContent">
+<pre class="code"><code class="idl-code">
+if (source.orientation.isZero() || ((source.coneInnerAngle == 360) &amp;&amp; (source.coneOuterAngle == 360)))
+ return 1; // no cone specified - unity gain
+
+// Normalized source-listener vector
+vec3 sourceToListener = listener.position - source.position;
+sourceToListener.normalize();
+
+vec3 normalizedSourceOrientation = source.orientation;
+normalizedSourceOrientation.normalize();
+
+// Angle between the source orientation vector and the source-listener vector
+double dotProduct = sourceToListener.dot(normalizedSourceOrientation);
+double angle = 180 * acos(dotProduct) / PI;
+double absAngle = fabs(angle);
+
+// Divide by 2 here since API is entire angle (not half-angle)
+double absInnerAngle = fabs(source.coneInnerAngle) / 2;
+double absOuterAngle = fabs(source.coneOuterAngle) / 2;
+double gain = 1;
+
+if (absAngle &lt;= absInnerAngle)
+ // No attenuation
+ gain = 1;
+else if (absAngle &gt;= absOuterAngle)
+ // Max attenuation
+ gain = source.coneOuterGain;
+else {
+ // Between inner and outer cones
+ // inner -> outer, x goes from 0 -> 1
+ double x = (absAngle - absInnerAngle) / (absOuterAngle - absInnerAngle);
+ gain = (1 - x) + source.coneOuterGain * x;
+}
+
+return gain;
+</code></pre>
+</div>
+</div>
+</div>
+
+<h3 id="Spatialization-doppler-shift">Doppler Shift</h3>
+<ul>
+ <li>Introduces a pitch shift which can realistically simulate moving
+ sources.</li>
+ <li>Depends on: source / listener velocity vectors, speed of sound, doppler
+ factor.</li>
+</ul>
+
+<p>
+The following algorithm must be used to calculate the doppler shift value which is used
+as an additional playback rate scalar for all AudioBufferSourceNodes connecting directly or
+indirectly to the AudioPannerNode:
+</p>
+
+<div class="block">
+<div class="blockTitleDiv">
+<div class="blockContent">
+<pre class="code"><code class="idl-code">
+double dopplerShift = 1; // Initialize to default value
+double dopplerFactor = listener.dopplerFactor;
+
+if (dopplerFactor > 0) {
+ double speedOfSound = listener.speedOfSound;
+
+ // Don't bother if both source and listener have no velocity.
+ if (!source.velocity.isZero() || !listener.velocity.isZero()) {
+ // Calculate the source to listener vector.
+ vec3 sourceToListener = source.position - listener.position;
+
+ double sourceListenerMagnitude = sourceToListener.length();
+
+ double listenerProjection = sourceToListener.dot(listener.velocity) / sourceListenerMagnitude;
+ double sourceProjection = sourceToListener.dot(source.velocity) / sourceListenerMagnitude;
+
+ listenerProjection = -listenerProjection;
+ sourceProjection = -sourceProjection;
+
+ double scaledSpeedOfSound = speedOfSound / dopplerFactor;
+ listenerProjection = min(listenerProjection, scaledSpeedOfSound);
+ sourceProjection = min(sourceProjection, scaledSpeedOfSound);
+
+ dopplerShift = ((speedOfSound - dopplerFactor * listenerProjection) / (speedOfSound - dopplerFactor * sourceProjection));
+ fixNANs(dopplerShift); // Avoid illegal values
+
+ // Limit the pitch shifting to 4 octaves up and 3 octaves down.
+ dopplerShift = min(dopplerShift, 16);
+ dopplerShift = max(dopplerShift, 0.125);
+ }
+}
+</code></pre>
+</div>
+</div>
+</div>
+
+
+
+
+</div>
+
+<div id="Convolution-section" class="section">
+<h2 id="Convolution">12. Linear Effects using Convolution</h2>
+
+<h3 id="Convolution-background">Background</h3>
+
+<p><a href="http://en.wikipedia.org/wiki/Convolution">Convolution</a> is a
+mathematical process which can be applied to an audio signal to achieve many
+interesting high-quality linear effects. Very often, the effect is used to
+simulate an acoustic space such as a concert hall, cathedral, or outdoor
+amphitheater. It can also be used for complex filter effects, like a muffled
+sound coming from inside a closet, sound underwater, sound coming through a
+telephone, or playing through a vintage speaker cabinet. This technique is very
+commonly used in major motion picture and music production and is considered to
+be extremely versatile and of high quality. </p>
+
+<p>Each unique effect is defined by an <code>impulse response</code>. An
+impulse response can be represented as an audio file and <a
+href="#recording-impulse-responses">can be recorded</a> from a real acoustic
+space such as a cave, or can be synthetically generated through a great variety
+of techniques. </p>
+
+<h3 id="Convolution-motivation">Motivation for use as a Standard</h3>
+
+<p>A key feature of many game audio engines (OpenAL, FMOD, Creative's EAX,
+Microsoft's XACT Audio, etc.) is a reverberation effect for simulating the
+sound of being in an acoustic space. But the code used to generate the effect
+has generally been custom and algorithmic (generally using a hand-tweaked set
+of delay lines and allpass filters which feedback into each other). In nearly
+all cases, not only is the implementation custom, but the code is proprietary
+and closed-source, each company adding its own "black magic" to achieve its
+unique quality. Each implementation being custom with a different set of
+parameters makes it impossible to achieve a uniform desired effect. And the
+code being proprietary makes it impossible to adopt a single one of the
+implementations as a standard. Additionally, algorithmic reverberation effects
+are limited to a relatively narrow range of different effects, regardless of
+how the parameters are tweaked. </p>
+
+<p>A convolution effect solves these problems by using a very precisely defined
+mathematical algorithm as the basis of its processing. An impulse response
+represents an exact sound effect to be applied to an audio stream and is easily
+represented by an audio file which can be referenced by URL. The range of
+possible effects is enormous. </p>
+
+<h3 id="Convolution-implementation-guide">Implementation Guide</h3>
+<p>
+Linear convolution can be implemented efficiently.
+Here are some <a href="https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/convolution.html">notes</a>
+describing how it can be practically implemented.
+</p>
+
+<h3 id="Convolution-reverb-effect">Reverb Effect (with matrixing)</h3>
+
+<p class="norm">This section is normative.</p>
+
+<p>
+In the general case the source
+has N input channels, the impulse response has K channels, and the playback
+system has M output channels. Thus it's a matter of how to matrix these
+channels to achieve the final result.
+</p>
+
+<p>
+The subset of N, M, K below must be implemented (note that the first image in the diagram is just illustrating
+the general case and is not normative, while the following images are normative).
+Without loss of generality, developers desiring more complex and arbitrary matrixing can use multiple <code>ConvolverNode</code>
+objects in conjunction with an <code>ChannelMergerNode</code>.
+</p>
+
+
+<p>Single channel convolution operates on a mono audio input, using a mono
+impulse response, and generating a mono output. But to achieve a more spacious sound, 2 channel audio
+inputs and 1, 2, or 4 channel impulse responses will be considered. The following diagram, illustrates the
+common cases for stereo playback where N and M are 1 or 2 and K is 1, 2, or 4.
+</p>
+<img alt="reverb matrixing" src="images/reverb-matrixing.png" />
+
+<h3 id="recording-impulse-responses">Recording Impulse Responses</h3>
+
+<p class="norm">This section is informative.</p>
+<img alt="impulse response" src="images/impulse-response.png" /> <br />
+<br />
+
+
+<p>The most <a
+href="http://pcfarina.eng.unipr.it/Public/Papers/226-AES122.pdf">modern</a> and
+accurate way to record the impulse response of a real acoustic space is to use
+a long exponential sine sweep. The test-tone can be as long as 20 or 30
+seconds, or longer. <br />
+Several recordings of the test tone played through a speaker can be made with
+microphones placed and oriented at various positions in the room. It's
+important to document speaker placement/orientation, the types of microphones,
+their settings, placement, and orientations for each recording taken. </p>
+
+<p>Post-processing is required for each of these recordings by performing an
+inverse-convolution with the test tone, yielding the impulse response of the
+room with the corresponding microphone placement. These impulse responses are
+then ready to be loaded into the convolution reverb engine to re-create the
+sound of being in the room. </p>
+
+<h3 id="tools">Tools</h3>
+
+<p>Two command-line tools have been written: <br />
+<code>generate_testtones</code> generates an exponential sine-sweep test-tone
+and its inverse. Another tool <code>convolve</code> was written for
+post-processing. With these tools, anybody with recording equipment can record
+their own impulse responses. To test the tools in practice, several recordings
+were made in a warehouse space with interesting acoustics. These were later
+post-processed with the command-line tools. </p>
+<pre>% generate_testtones -h
+Usage: generate_testtone
+ [-o /Path/To/File/To/Create] Two files will be created: .tone and .inverse
+ [-rate &lt;sample rate&gt;] sample rate of the generated test tones
+ [-duration &lt;duration&gt;] The duration, in seconds, of the generated files
+ [-min_freq &lt;min_freq&gt;] The minimum frequency, in hertz, for the sine sweep
+
+% convolve -h
+Usage: convolve input_file impulse_response_file output_file</pre>
+<br />
+
+
+<h3 id="recording-setup">Recording Setup</h3>
+<img alt="recording setup" src="images/recording-setup.png" /> <br />
+<br />
+Audio Interface: Metric Halo Mobile I/O 2882 <br />
+<br />
+<br />
+<br />
+<img alt="microphones speaker" src="images/microphones-speaker.png" /> <br />
+<br />
+<img alt="microphone" src="images/microphone.png" /> <img alt="speaker"
+src="images/speaker.png" /> <br />
+<br />
+Microphones: AKG 414s, Speaker: Mackie HR824 <br />
+<br />
+<br />
+
+
+<h3 id="warehouse">The Warehouse Space</h3>
+<img alt="warehouse" src="images/warehouse.png" /> <br />
+<br />
+</div>
+
+<div id="JavaScriptProcessing-section" class="section">
+<h2 id="JavaScriptProcessing">13. JavaScript Synthesis and Processing</h2>
+
+<p class="norm">This section is informative.</p>
+
+<p>The Mozilla project has conducted <a
+href="https://wiki.mozilla.org/Audio_Data_API">Experiments</a> to synthesize
+and process audio directly in JavaScript. This approach is interesting for a
+certain class of audio processing and they have produced a number of impressive
+demos. This specification includes a means of synthesizing and processing
+directly using JavaScript by using a special subtype of <a
+href="#AudioNode-section"><code>AudioNode</code></a> called <a
+href="#ScriptProcessorNode-section"><code>ScriptProcessorNode</code></a>. </p>
+
+<p>Here are some interesting examples where direct JavaScript processing can be
+useful: </p>
+
+<h3 id="custom-DSP-effects">Custom DSP Effects</h3>
+
+<p>Unusual and interesting custom audio processing can be done directly in JS.
+It's also a good test-bed for prototyping new algorithms. This is an extremely
+rich area. </p>
+
+<h3 id="educational-applications">Educational Applications</h3>
+
+<p>JS processing is ideal for illustrating concepts in computer music synthesis
+and processing, such as showing the de-composition of a square wave into its
+harmonic components, FM synthesis techniques, etc. </p>
+
+<h3 id="javaScript-performance">JavaScript Performance</h3>
+
+<p>JavaScript has a variety of <a
+href="#JavaScriptPerformance-section">performance issues</a> so it is not
+suitable for all types of audio processing. The approach proposed in this
+document includes the ability to perform computationally intensive aspects of
+the audio processing (too expensive for JavaScript to compute in real-time)
+such as multi-source 3D spatialization and convolution in optimized C++ code.
+Both direct JavaScript processing and C++ optimized code can be combined due to
+the APIs <a href="#ModularRouting-section">modular approach</a>. </p>
+
+<div id="Performance-section" class="section">
+<h2 id="Performance">15. Performance Considerations</h2>
+
+<div id="Latency-section" class="section">
+<h3 id="Latency">15.1. Latency: What it is and Why it's Important</h3>
+</div>
+<img alt="latency" src="images/latency.png" />
+
+<p>For web applications, the time delay between mouse and keyboard events
+(keydown, mousedown, etc.) and a sound being heard is important. </p>
+
+<p>This time delay is called latency and is caused by several factors (input
+device latency, internal buffering latency, DSP processing latency, output
+device latency, distance of user's ears from speakers, etc.), and is
+cummulative. The larger this latency is, the less satisfying the user's
+experience is going to be. In the extreme, it can make musical production or
+game-play impossible. At moderate levels it can affect timing and give the
+impression of sounds lagging behind or the game being non-responsive. For
+musical applications the timing problems affect rhythm. For gaming, the timing
+problems affect precision of gameplay. For interactive applications, it
+generally cheapens the users experience much in the same way that very low
+animation frame-rates do. Depending on the application, a reasonable latency
+can be from as low as 3-6 milliseconds to 25-50 milliseconds. </p>
+
+<div id="Glitching-section" class="section">
+<h3 id="audio-glitching">15.2. Audio Glitching</h3>
+</div>
+
+<p>Audio glitches are caused by an interruption of the normal continuous audio
+stream, resulting in loud clicks and pops. It is considered to be a
+catastrophic failure of a multi-media system and must be avoided. It can be
+caused by problems with the threads responsible for delivering the audio stream
+to the hardware, such as scheduling latencies caused by threads not having the
+proper priority and time-constraints. It can also be caused by the audio DSP
+trying to do more work than is possible in real-time given the CPU's speed. </p>
+
+<h3 id="hardware-scalability">15.3. Hardware Scalability</h3>
+
+<p>The system should gracefully degrade to allow audio processing under
+resource constrained conditions without dropping audio frames. </p>
+
+<p>First of all, it should be clear that regardless of the platform, the audio
+processing load should never be enough to completely lock up the machine.
+Second, the audio rendering needs to produce a clean, un-interrupted audio
+stream without audible <a href="#Glitching-section">glitches</a>. </p>
+
+<p>The system should be able to run on a range of hardware, from mobile phones
+and tablet devices to laptop and desktop computers. But the more limited
+compute resources on a phone device make it necessary to consider techniques to
+scale back and reduce the complexity of the audio rendering. For example,
+voice-dropping algorithms can be implemented to reduce the total number of
+notes playing at any given time. </p>
+
+<p>Here's a list of some techniques which can be used to limit CPU usage: </p>
+
+<h4 id="CPU-monitoring">15.3.1. CPU monitoring</h4>
+
+<p>In order to avoid audio breakup, CPU usage must remain below 100%. </p>
+
+<p>The relative CPU usage can be dynamically measured for each AudioNode (and
+chains of connected nodes) as a percentage of the rendering time quantum. In a
+single-threaded implementation, overall CPU usage must remain below 100%. The
+measured usage may be used internally in the implementation for dynamic
+adjustments to the rendering. It may also be exposed through a
+<code>cpuUsage</code> attribute of <code>AudioNode</code> for use by
+JavaScript. </p>
+
+<p>In cases where the measured CPU usage is near 100% (or whatever threshold is
+considered too high), then an attempt to add additional <code>AudioNodes</code>
+into the rendering graph can trigger voice-dropping. </p>
+
+<h4 id="Voice-dropping">15.3.2. Voice Dropping</h4>
+
+<p>Voice-dropping is a technique which limits the number of voices (notes)
+playing at the same time to keep CPU usage within a reasonable range. There can
+either be an upper threshold on the total number of voices allowed at any given
+time, or CPU usage can be dynamically monitored and voices dropped when CPU
+usage exceeds a threshold. Or a combination of these two techniques can be
+applied. When CPU usage is monitored for each voice, it can be measured all the
+way from a source node through any effect processing nodes which apply
+uniquely to that voice. </p>
+
+<p>When a voice is "dropped", it needs to happen in such a way that it doesn't
+introduce audible clicks or pops into the rendered audio stream. One way to
+achieve this is to quickly fade-out the rendered audio for that voice before
+completely removing it from the rendering graph. </p>
+
+<p>When it is determined that one or more voices must be dropped, there are
+various strategies for picking which voice(s) to drop out of the total ensemble
+of voices currently playing. Here are some of the factors which can be used in
+combination to help with this decision: </p>
+<ul>
+ <li>Older voices, which have been playing the longest can be dropped instead
+ of more recent voices. </li>
+ <li>Quieter voices, which are contributing less to the overall mix may be
+ dropped instead of louder ones. </li>
+ <li>Voices which are consuming relatively more CPU resources may be dropped
+ instead of less "expensive" voices.</li>
+ <li>An AudioNode can have a <code>priority</code> attribute to help determine
+ the relative importance of the voices.</li>
+</ul>
+
+<h4 id="Simplification-of-Effects-Processing">15.3.3. Simplification of Effects
+Processing</h4>
+
+<p>Most of the effects described in this document are relatively inexpensive
+and will likely be able to run even on the slower mobile devices. However, the
+<a href="#ConvolverNode-section">convolution effect</a> can be configured with
+a variety of impulse responses, some of which will likely be too heavy for
+mobile devices. Generally speaking, CPU usage scales with the length of the
+impulse response and the number of channels it has. Thus, it is reasonable to
+consider that impulse responses which exceed a certain length will not be
+allowed to run. The exact limit can be determined based on the speed of the
+device. Instead of outright rejecting convolution with these long responses, it
+may be interesting to consider truncating the impulse responses to the maximum
+allowed length and/or reducing the number of channels of the impulse response.
+</p>
+
+<p>In addition to the convolution effect. The <a
+href="#PannerNode-section"><code>PannerNode</code></a> may also be
+expensive if using the HRTF panning model. For slower devices, a cheaper
+algorithm such as EQUALPOWER can be used to conserve compute resources. </p>
+
+<h4 id="Sample-rate">15.3.4. Sample Rate</h4>
+
+<p>For very slow devices, it may be worth considering running the rendering at
+a lower sample-rate than normal. For example, the sample-rate can be reduced
+from 44.1KHz to 22.05KHz. This decision must be made when the
+<code>AudioContext</code> is created, because changing the sample-rate
+on-the-fly can be difficult to implement and will result in audible glitching
+when the transition is made. </p>
+
+<h4 id="pre-flighting">15.3.5. Pre-flighting</h4>
+
+<p>It should be possible to invoke some kind of "pre-flighting" code (through
+JavaScript) to roughly determine the power of the machine. The JavaScript code
+can then use this information to scale back any more intensive processing it
+may normally run on a more powerful machine. Also, the underlying
+implementation may be able to factor in this information in the voice-dropping
+algorithm. </p>
+
+<p><span class="ednote">TODO: add specification and more detail here </span></p>
+
+<h4 id="Authoring-for-different-user-agents">15.3.6. Authoring for different
+user agents</h4>
+JavaScript code can use information about user-agent to scale back any more
+intensive processing it may normally run on a more powerful machine.
+
+<h4 id="Scalability-of-Direct-JavaScript-Synthesis">15.3.7. Scalability of
+Direct JavaScript Synthesis / Processing</h4>
+
+<p>Any audio DSP / processing code done directly in JavaScript should also be
+concerned about scalability. To the extent possible, the JavaScript code itself
+needs to monitor CPU usage and scale back any more ambitious processing when
+run on less powerful devices. If it's an "all or nothing" type of processing,
+then user-agent check or pre-flighting should be done to avoid generating an
+audio stream with audio breakup. </p>
+
+<div id="JavaScriptPerformance-section" class="section">
+<h3 id="JavaScriptPerformance">15.4. JavaScript Issues with real-time
+Processing and Synthesis: </h3>
+</div>
+While processing audio in JavaScript, it is extremely challenging to get
+reliable, glitch-free audio while achieving a reasonably low-latency,
+especially under heavy processor load.
+<ul>
+ <li>JavaScript is very much slower than heavily optimized C++ code and is not
+ able to take advantage of SSE optimizations and multi-threading which is
+ critical for getting good performance on today's processors. Optimized
+ native code can be on the order of twenty times faster for processing FFTs
+ as compared with JavaScript. It is not efficient enough for heavy-duty
+ processing of audio such as convolution and 3D spatialization of large
+ numbers of audio sources. </li>
+ <li>setInterval() and XHR handling will steal time from the audio processing.
+ In a reasonably complex game, some JavaScript resources will be needed for
+ game physics and graphics. This creates challenges because audio rendering
+ is deadline driven (to avoid glitches and get low enough latency).</li>
+ <li>JavaScript does not run in a real-time processing thread and thus can be
+ pre-empted by many other threads running on the system.</li>
+ <li>Garbage Collection (and autorelease pools on Mac OS X) can cause
+ unpredictable delay on a JavaScript thread. </li>
+ <li>Multiple JavaScript contexts can be running on the main thread, stealing
+ time from the context doing the processing. </li>
+ <li>Other code (other than JavaScript) such as page rendering runs on the
+ main thread. </li>
+ <li>Locks can be taken and memory is allocated on the JavaScript thread. This
+ can cause additional thread preemption. </li>
+</ul>
+The problems are even more difficult with today's generation of mobile devices
+which have processors with relatively poor performance and power consumption /
+battery-life issues. <br />
+<br />
+
+
+<div id="ExampleApplications-section" class="section">
+<h2 id="ExampleApplications">16. Example Applications</h2>
+
+<p class="norm">This section is informative.</p>
+
+<p>Please see the <a
+href="http://chromium.googlecode.com/svn/trunk/samples/audio/index.html">demo</a>
+page for working examples. </p>
+
+<p>Here are some of the types of applications a web audio system should be able
+to support: </p>
+
+<h3 id="basic-sound-playback">Basic Sound Playback</h3>
+
+<p>Simple and <a href="#Latency-section"><strong>low-latency</strong></a>
+playback of sound effects in response to simple user actions such as mouse
+click, roll-over, key press. </p>
+<br />
+
+
+<h3 id="threeD-environmentse-and-games">3D Environments and Games</h3>
+<img alt="quake" src="http://payload48.cargocollective.com/1/2/66805/3278334/redteam_680.jpg" />
+<br />
+<br />
+
+
+<p>Electronic Arts has produced an impressive immersive game called
+ <a href="http://sophie-lu.com/Strike-Fortress-EA">Strike Fortress</a>,
+taking advantage of 3D spatialization and convolution for room simulation.</p>
+
+<img alt="beach demo" src="images/beach-demo.png" />
+
+<p>3D environments with audio are common in games made for desktop applications
+and game consoles. Imagine a 3D island environment with spatialized audio,
+seagulls flying overhead, the waves crashing against the shore, the crackling
+of the fire, the creaking of the bridge, and the rustling of the trees in the
+wind. The sounds can be positioned naturally as one moves through the scene.
+Even going underwater, low-pass filters can be tweaked for just the right
+underwater sound. </p>
+<br />
+<br />
+<img alt="box2d" src="images/box2d.png" /> <img alt="8-ball"
+src="images/8-ball.png" /> <br />
+<br />
+
+
+<p><a href="http://box2d.org/">Box2D</a> is an interesting open-source
+library for 2D game physics. It has various implementations, including one
+based on Canvas 2D. A demo has been created with dynamic sound effects for each
+of the object collisions, taking into account the velocities vectors and
+positions to spatialize the sound events, and modulate audio effect parameters
+such as filter cutoff. </p>
+
+<p>A virtual pool game with multi-sampled sound effects has also been created.
+</p>
+<br />
+
+
+<h3 id="musical-applications">Musical Applications</h3>
+<img alt="garageband" src="images/garage-band.png" /> <img
+alt="shiny drum machine" src="images/shiny-drum-machine.png" /> <img
+alt="tonecraft" src="images/tonecraft.png" /> <br />
+<br />
+Many music composition and production applications are possible. Applications
+requiring tight scheduling of audio events can be implemented and can be both
+educational and entertaining. Drum machines, digital DJ applications, and even
+timeline-based digital music production software with some of the features of
+<a href="http://en.wikipedia.org/wiki/GarageBand">GarageBand</a> can be
+written. <br />
+<br />
+
+
+<h3 id="music-visualizers">Music Visualizers</h3>
+<img alt="music visualizer" src="images/music-visualizer.png" /> <br />
+<br />
+When combined with WebGL GLSL shaders, realtime analysis data can be presented
+in entertaining ways. These can be as advanced as any found in iTunes. <br />
+<br />
+
+
+<h3 id="educational-applications_2">Educational Applications</h3>
+<img alt="javascript processing" src="images/javascript-processing.png" />
+
+<p>A variety of educational applications can be written, illustrating concepts
+in music theory and computer music synthesis and processing. </p>
+<br />
+
+
+<h3 id="artistic-audio-exploration">Artistic Audio Exploration</h3>
+
+<p>There are many creative possibilites for artistic sonic environments for
+installation pieces. </p>
+<br />
+</div>
+
+<div id="SecurityConsiderations-section" class="section">
+<h2 id="SecurityConsiderations">17. Security Considerations</h2>
+
+<p>This section is <em>informative.</em> </p>
+</div>
+
+<div id="PrivacyConsiderations-section" class="section">
+<h2 id="PrivacyConsiderations">18. Privacy Considerations</h2>
+
+<p>This section is <em>informative</em>. When giving various information on
+available AudioNodes, the Web Audio API potentially exposes information on
+characteristic features of the client (such as audio hardware sample-rate) to
+any page that makes use of the AudioNode interface. Additionally, timing
+information can be collected through the RealtimeAnalyzerNode or
+ScriptProcessorNode interface. The information could subsequently be used to
+create a fingerprint of the client. </p>
+
+<p>Currently audio input is not specified in this document, but it will involve
+gaining access to the client machine's audio input or microphone. This will
+require asking the user for permission in an appropriate way, probably via the
+<a href="http://developers.whatwg.org/">getUserMedia()
+API</a>. </p>
+</div>
+
+<div id="requirements-section" class="section">
+<h2 id="requirements">19. Requirements and Use Cases</h2>
+
+<p>Please see <a href="#ExampleApplications-section">Example Applications</a>
+</p>
+</div>
+
+<div id="oldnames-section" class="section">
+<h2 id="OldNames">20. Old Names</h2>
+
+<p class="norm">This section is informative.</p>
+
+<p>Some method and attribute names have been improved during API review.
+The new names are described in the main body of this specification in the
+description for each node type, etc. Here's a description of the older names
+to help content authors migrate to the latest spec. Note that the partial
+interfaces are not normative and are only descriptive:
+</p>
+<blockquote>
+<pre>
+
+partial interface <dfn>AudioBufferSourceNode</dfn> {
+ // Same as start()
+ void noteOn(double when);
+ void noteGrainOn(double when, double grainOffset, double grainDuration);
+
+ // Same as stop()
+ void noteOff(double when);
+};
+
+partial interface <dfn>AudioContext</dfn> {
+ // Same as createGain()
+ GainNode createGainNode();
+
+ // Same as createDelay()
+ DelayNode createDelayNode(optional double maxDelayTime = 1.0);
+
+ // Same as createScriptProcessor()
+ ScriptProcessorNode createJavaScriptNode(optional unsigned long bufferSize = 0,
+ optional unsigned long numberOfInputChannels = 2,
+ optional unsigned long numberOfOutputChannels = 2);
+};
+
+partial interface <dfn>OscillatorNode</dfn> {
+ // Same as start()
+ void noteOn(double when);
+
+ // Same as stop()
+ void noteOff(double when);
+};
+
+partial interface <dfn>AudioParam</dfn> {
+ // Same as setTargetAtTime()
+ void setTargetValueAtTime(float target, double startTime, double timeConstant);
+};
+
+</pre>
+</blockquote>
+
+<p>Some attributes taking constant values have changed during API review.
+The old way used integer values, while the new way uses Web IDL string values.
+</p>
+
+<blockquote>
+<pre>
+// PannerNode constants for the .panningModel attribute
+
+// Old way
+const unsigned short EQUALPOWER = 0;
+const unsigned short HRTF = 1;
+
+// New way
+enum <dfn>PanningModelType</dfn> {
+ "equalpower",
+ "HRTF"
+};
+</pre>
+</blockquote>
+
+<blockquote>
+<pre>
+// PannerNode constants for the .distanceModel attribute
+
+// Old way
+const unsigned short LINEAR_DISTANCE = 0;
+const unsigned short INVERSE_DISTANCE = 1;
+const unsigned short EXPONENTIAL_DISTANCE = 2;
+
+// New way
+enum <dfn>DistanceModelType</dfn> {
+ "linear",
+ "inverse",
+ "exponential"
+};
+</pre>
+</blockquote>
+
+
+
+<blockquote>
+<pre>
+// BiquadFilterNode constants for the .type attribute
+
+// Old way
+const unsigned short LOWPASS = 0;
+const unsigned short HIGHPASS = 1;
+const unsigned short BANDPASS = 2;
+const unsigned short LOWSHELF = 3;
+const unsigned short HIGHSHELF = 4;
+const unsigned short PEAKING = 5;
+const unsigned short NOTCH = 6;
+const unsigned short ALLPASS = 7;
+
+// New way
+enum <dfn>BiquadFilterType</dfn> {
+ "lowpass",
+ "highpass",
+ "bandpass",
+ "lowshelf",
+ "highshelf",
+ "peaking",
+ "notch",
+ "allpass"
+};
+</pre>
+</blockquote>
+
+<blockquote>
+<pre>
+// OscillatorNode constants for the .type attribute
+
+// Old way
+const unsigned short SINE = 0;
+const unsigned short SQUARE = 1;
+const unsigned short SAWTOOTH = 2;
+const unsigned short TRIANGLE = 3;
+const unsigned short CUSTOM = 4;
+
+// New way
+enum <dfn>OscillatorType</dfn> {
+ "sine",
+ "square",
+ "sawtooth",
+ "triangle",
+ "custom"
+};
+</pre>
+</blockquote>
+
+
+
+</div>
+
+</div>
+</div>
+
+<div class="appendix section" id="references">
+<h2 id="L17310">A.References</h2>
+
+<div class="section" id="normative-references">
+<h3 id="Normative-references">A.1 Normative references</h3>
+<dl>
+ <dt id="DOM">[DOM] </dt>
+ <dd><a href="http://dom.spec.whatwg.org/">DOM</a>,
+ A. van Kesteren, A. Gregor, Ms2ger. WHATWG.</dd>
+ <dt id="HTML">[HTML] </dt>
+ <dd><a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/">HTML</a>,
+ I. Hickson. WHATWG.</dd>
+ <dt id="RFC2119">[RFC2119] </dt>
+ <dd>S. Bradner. <a
+ href="http://www.ietf.org/rfc/rfc2119.txt"><cite><span>Key words for use
+ in RFCs to Indicate Requirement Levels.</span></cite></a> Internet RFC
+ 2119. URL: <a
+ href="http://www.ietf.org/rfc/rfc2119.txt">http://www.ietf.org/rfc/rfc2119.txt</a>
+ </dd>
+</dl>
+</div>
+
+<div class="section" id="informative-references">
+<h3 id="Informative-references">A.2 Informative references</h3>
+
+<p>No informative references.</p>
+</div>
+</div>
+
+<div class="section" id="acknowledgements">
+<h2 id="L17335">B.Acknowledgements</h2>
+
+<p>Special thanks to the W3C <a href="http://www.w3.org/2011/audio/">Audio
+Working Group</a>. Members of the Working Group are (at the time of writing,
+and by alphabetical order): <br />
+Berkovitz, Joe (public Invited expert);Cardoso, Gabriel (INRIA);Carlson, Eric
+(Apple, Inc.);Gregan, Matthew (Mozilla Foundation);Jägenstedt, Philip (Opera
+Software);Kalliokoski, Jussi (public Invited expert);Lowis, Chris (British
+Broadcasting Corporation);MacDonald, Alistair (W3C Invited Experts);Michel,
+Thierry (W3C/ERCIM);Noble, Jer (Apple, Inc.);O'Callahan, Robert(Mozilla
+Foundation);Paradis, Matthew (British Broadcasting Corporation);Raman, T.V.
+(Google, Inc.);Rogers, Chris (Google, Inc.);Schepers, Doug (W3C/MIT);Shires,
+Glen (Google, Inc.);Smith, Michael (W3C/Keio);Thereaux, Olivier (British
+Broadcasting Corporation);Wei, James (Intel Corporation);Wilson, Chris (Google,
+Inc.); </p>
+</div>
+
+<div class="section" id="ChangeLog-section">
+<h2 id="ChangeLog">C. Web Audio API Change Log</h2>
+<pre>
+user: crogers
+date: Sun Dec 09 17:13:56 2012 -0800
+summary: Basic description of OfflineAudioContext
+
+user: crogers
+date: Tue Dec 04 15:59:30 2012 -0800
+summary: minor correction to wording for minValue and maxValue
+
+user: crogers
+date: Tue Dec 04 15:49:29 2012 -0800
+summary: Bug 20161: Make decodeAudioData neuter its array buffer argument when it begins decoding a buffer, and bring it back to normal when the decoding is finished
+
+user: crogers
+date: Tue Dec 04 15:35:17 2012 -0800
+summary: Bug 20039: Refine description of audio decoding
+
+user: crogers
+date: Tue Dec 04 15:23:07 2012 -0800
+summary: elaborate on decoding steps for AudioContext createBuffer() and decodeAudioData()
+
+user: crogers
+date: Tue Dec 04 14:56:19 2012 -0800
+summary: Bug 19770: Note that if the last event for an AudioParam is a setCurveValue event, the computed value after that event will be equal to the latest curve value
+
+user: crogers
+date: Tue Dec 04 14:48:04 2012 -0800
+summary: Bug 19769: Note that before the first automation event, the computed AudioParam value will be AudioParam.value
+
+user: crogers
+date: Tue Dec 04 14:40:51 2012 -0800
+summary: Bug 19768: Explicitly mention that the initial value of AudioParam.value will be defaultValue
+
+user: crogers
+date: Tue Dec 04 14:35:59 2012 -0800
+summary: Bug 19767: Explicitly mention that the 2nd component of AudioParam.computedValue will be 0 if there are no AudioNodes connected to it
+
+user: crogers
+date: Tue Dec 04 14:30:08 2012 -0800
+summary: Bug 19764: Note in the spec that AudioParam.minValue/maxValue are merely informational
+
+user: crogers
+date: Mon Dec 03 18:03:13 2012 -0800
+summary: Convert integer constants to Web IDL enum string constants
+
+user: crogers
+date: Mon Dec 03 15:19:22 2012 -0800
+summary: Bug 17411: (AudioPannerNodeUnits): AudioPannerNode units are underspecified
+
+user: Ehsan Akhgari (Mozilla)
+date: Thu Nov 29 15:59:38 2012 -0500
+summary: Change the Web IDL description of decodeAudioData arguments
+
+user: crogers
+date: Wed Nov 14 13:24:01 2012 -0800
+summary: Bug 17393: (UseDoubles): float/double inconsistency
+
+user: crogers
+date: Wed Nov 14 13:16:57 2012 -0800
+summary: Bug 17356: (AudioListenerOrientation): AudioListener.setOrientation vectors
+
+user: crogers
+date: Wed Nov 14 12:56:06 2012 -0800
+summary: Bug 19957: PannerNode.coneGain is unused
+
+user: crogers
+date: Wed Nov 14 12:40:46 2012 -0800
+summary: Bug 17412: AudioPannerNodeVectorNormalization): AudioPannerNode orientation normalization unspecified
+
+user: crogers
+date: Wed Nov 14 12:16:41 2012 -0800
+summary: Bug 17411: (AudioPannerNodeUnits): AudioPannerNode units are underspecified
+
+user: crogers
+date: Tue Nov 13 16:14:22 2012 -0800
+summary: be more explicit about maxDelayTime units
+
+user: crogers
+date: Tue Nov 13 16:02:50 2012 -0800
+summary: Bug 19766: Clarify that reading AudioParam.computedValue will return the latest computed value for the latest audio quantum
+
+user: crogers
+date: Tue Nov 13 15:47:25 2012 -0800
+summary: Bug 19872: Should specify the defaults for PannerNode's position, ...
+
+user: crogers
+date: Tue Nov 13 15:27:53 2012 -0800
+summary: Bug 17390: (Joe Berkovitz): Loop start/stop points
+
+user: croger
+date: Tue Nov 13 14:49:20 2012 -0800
+summary: Bug 19765: Note that setting AudioParam.value will be ignored when any automation events have been set on the object
+
+user: crogers
+date: Tue Nov 13 14:39:07 2012 -0800
+summary: Bug 19873: Clarify PannerNode.listener
+
+user: crogers
+date: Tue Nov 13 13:35:21 2012 -0800
+summary: Bug 19900: Clarify the default values for the AudioParam attributes of BiquadFilterNode
+
+user: crogers
+date: Tue Nov 13 13:06:38 2012 -0800
+summary: Bug 19884: Specify the default value and ranges for the DynamicsCompressorNode AudioParam members
+
+user: crogers
+date: Tue Nov 13 12:57:02 2012 -0800
+summary: Bug 19910: Disallow AudioContext.createDelay(max) where max &lt;= 0
+
+user: crogers
+date: Mon Nov 12 12:02:18 2012 -0800
+summary: Add example code for more complex example
+
+user: Ehsan Akhgari (Mozilla)
+date: Thu Nov 01 11:32:39 2012 -0400
+summary: Specify the default value for the AudioContext.createDelay() optional argument in Web IDL
+
+user: Ehsan Akhgari (Mozilla)
+date: Tue Oct 30 20:29:48 2012 -0400
+summary: Mark the AudioParam members as readonly
+
+user: Ehsan Akhgari (Mozilla)
+date: Tue Oct 30 20:24:52 2012 -0400
+summary: Make GainNode and DelayNode valid Web IDL
+
+user: crogers
+date: Mon Oct 29 14:29:23 2012 -0700
+summary: consolidate AudioBufferSourceNode start() method
+
+user: crogers
+date: Fri Oct 19 15:15:28 2012 -0700
+summary: Bug 18332: Node creation method naming inconsistencies
+
+user: crogers
+date: Mon Oct 15 17:22:54 2012 -0700
+summary: Bug 17407: Interface naming inconsistency
+
+user: crogers
+date: Tue Oct 09 17:21:19 2012 -0700
+summary: Bug 17369: Oscillator.detune attribute not defined
+
+user: crogers
+date: Tue Oct 09 16:08:50 2012 -0700
+summary: Bug 17346: HTMLMediaElement integration
+
+user: crogers
+date: Tue Oct 09 15:20:50 2012 -0700
+summary: Bug 17354: AudioListener default position, orientation and velocity
+
+user: crogers
+date: Tue Oct 09 15:02:04 2012 -0700
+summary: Bug 17795: Behavior of multiple connections to same node needs to be explicitly defined
+
+user: crogers
+date: Mon Oct 08 13:18:45 2012 -0700
+summary: Add missing AudioContext.createWaveShaper() method
+
+user: crogers
+date: Fri Oct 05 18:13:44 2012 -0700
+summary: Bug 17399: AudioParam sampling is undefined
+
+user: crogers
+date: Fri Oct 05 17:41:52 2012 -0700
+summary: Bug 17386: Realtime Analysis empty section
+
+user: crogers
+date: Fri Oct 05 17:38:14 2012 -0700
+summary: minor tweak to down-mix section
+
+user: crogers
+date: Fri Oct 05 17:35:05 2012 -0700
+summary: Bug 17380: Channel down mixing incomplete
+
+user: crogers
+date: Fri Oct 05 15:40:57 2012 -0700
+summary: Bug 17375: MixerGainStructure should be marked as informative
+
+user: crogers
+date: Fri Oct 05 14:29:20 2012 -0700
+summary: Bug 17381: (EventScheduling): Event Scheduling ('Need more detail here')
+
+user: crogers
+date: Fri Oct 05 13:12:46 2012 -0700
+summary: Fix 18663: Need a method to get a readonly reading of the combined value when using AudioParam automation curve
+
+user: crogers
+date: Fri Oct 05 12:48:36 2012 -0700
+summary: Fix 18662: Setting audioparam value while there is an automation curve will cancel that automation curve and set value immediately
+
+user: crogers
+date: Fri Oct 05 12:26:28 2012 -0700
+summary: Fix 18661: Use startTime / endTime parameter names for AudioParam automation methods
+
+user: crogers
+date: Wed Oct 03 12:26:39 2012 -0700
+summary: Specify default value for .distanceModel
+
+user: crogers
+date: Tue Oct 02 12:33:36 2012 -0700
+summary: Fix Issues 17338 and 17337: AudioGain interface is not needed (Part 2)
+
+user: crogers
+date: Tue Oct 02 12:28:55 2012 -0700
+summary: Fix Issues 17338 and 17337: AudioGain interface is not needed
+
+user: Ehsan Akhgari (Mozilla)
+date: Wed Sep 26 18:22:36 2012 -0400
+summary: Make AudioBufferSourceNode.buffer nullable
+
+user: crogers
+date: Tue Sep 25 12:56:14 2012 -0700
+summary: noteOn/noteOff changed to start/stop -- added deprecation notes
+
+user: Ehsan Akhgari (Mozilla)
+date: Fri Aug 24 18:27:29 2012 -0400
+summary: Make the AudioContext object have a constructor
+
+user: Ehsan Akhgari (Mozilla)
+date: Fri Aug 24 15:54:10 2012 -0400
+summary: Denote IDL definitions as Web IDL
+
+user: Ehsan Akhgari (Mozilla)
+date: Fri Aug 24 15:04:37 2012 -0400
+summary: Use `long` instead of `int`, since the int type doesn't exist in Web IDL
+
+user: Ehsan Akhgari (Mozilla)
+date: Fri Aug 24 15:02:43 2012 -0400
+summary: Add a missing attribute keyword in AudioProcessingEvent
+
+user: Ehsan Akhgari (Mozilla)
+date: Tue Aug 21 15:36:48 2012 -0400
+summary: Remove the 'raises' notation from the IDLs
+
+user: crogers
+date: Thu Aug 16 16:30:55 2012 -0700
+summary: Issue 17398: Add more detailed information about how AudioParam value is calculated
+
+user: crogers
+date: Thu Aug 16 15:21:38 2012 -0700
+summary: another try with the style sheet
+
+user: crogers
+date: Thu Aug 16 14:53:54 2012 -0700
+summary: use local style sheet to avoid https errors
+
+user: Ehsan Akhgari (Mozilla)
+date: Wed Aug 15 23:05:49 2012 -0400
+summary: Replace the white-space based indentation of Web IDL code with a CSS-based one
+
+user: Ehsan Akhgari (Mozilla)
+date: Wed Aug 15 22:56:03 2012 -0400
+summary: Remove more useless trailing whitespaces
+
+user: Ehsan Akhgari (Mozilla)
+date: Wed Aug 15 22:47:21 2012 -0400
+summary: Remove the optional 'in' keyword from the Web IDL method declarations
+
+user: Ehsan Akhgari (Mozilla)
+date: Wed Aug 15 22:42:03 2012 -0400
+summary: Add trailing semicolons for Web IDL interface declarations
+
+user: Ehsan Akhgari (Mozilla)
+date: Wed Aug 15 22:37:32 2012 -0400
+summary: Remove useless trailing spaces
+
+user: Ehsan Akhgari (Mozilla)
+date: Wed Aug 15 22:35:33 2012 -0400
+summary: Use the correct Web IDL notation for the AudioBufferCallback callback type
+
+user: Ehsan Akhgari (Mozilla)
+date: Wed Aug 15 22:28:37 2012 -0400
+summary: Remove the extra semicolon in the IDL file for AudioContext
+
+user: Ehsan Akhgari (Mozilla)
+date: Wed Aug 15 22:24:02 2012 -0400
+summary: Replace the old [Optional] IDL tag with the Web IDL optional keyword
+
+user: Ehsan Akhgari (Mozilla)
+date: Tue Aug 14 10:18:19 2012 -0400
+summary: Empty changeset to test my commit access
+
+date: Mon Aug 13 13:26:52 2012 -0700
+* Integrate Thierry Michel's 3rd public working draft edits
+
+date: Tue Jun 26 15:56:31 2012 -0700
+* add MediaStreamAudioSourceNode
+
+date: Mon Jun 18 13:26:21 2012 -0700
+* minor formatting fix
+
+date: Mon Jun 18 13:19:34 2012 -0700
+* Add details for azimuth/elevation calculation
+
+date: Fri Jun 15 17:35:27 2012 -0700
+* Add equal-power-panning details
+
+date: Thu Jun 14 17:31:16 2012 -0700
+* Add equations for distance models
+
+date: Wed Jun 13 17:40:49 2012 -0700
+* Bug 17334: Add precise equations for AudioParam.setTargetValueAtTime()
+
+date: Fri Jun 08 17:44:26 2012 -0700
+* fix small typo
+
+date: Fri Jun 08 16:54:04 2012 -0700
+* Bug 17413: AudioBuffers' relationship to AudioContext
+
+date: Fri Jun 08 16:05:45 2012 -0700
+* Bug 17359: Add much more detail about ConvolverNode
+
+date: Fri Jun 08 12:59:29 2012 -0700
+* minor formatting fix
+
+date: Fri Jun 08 12:57:11 2012 -0700
+* Bug 17335: Add much more technical detail to setValueCurveAtTime()
+
+date: Wed Jun 06 16:34:43 2012 -0700
+*Add much more detail about parameter automation, including an example
+
+date: Mon Jun 04 17:25:08 2012 -0700
+* ISSUE-85: OscillatorNode folding considerations
+
+date: Mon Jun 04 17:02:20 2012 -0700
+* ISSUE-45: AudioGain scale underdefined
+
+date: Mon Jun 04 16:40:43 2012 -0700
+* ISSUE-41: AudioNode as input to AudioParam underdefined
+
+date: Mon Jun 04 16:14:48 2012 -0700
+* ISSUE-20: Relationship to currentTime
+
+date: Mon Jun 04 15:48:49 2012 -0700
+* ISSUE-94: Dynamic Lifetime
+
+date: Mon Jun 04 13:59:31 2012 -0700
+* ISSUE-42: add more detail about AudioParam sampling and block processing
+
+date: Mon Jun 04 12:28:48 2012 -0700
+* fix typo - minor edits
+
+date: Thu May 24 18:01:20 2012 -0700
+* ISSUE-69: add implementors guide for linear convolution
+
+date: Thu May 24 17:35:45 2012 -0700
+* ISSUE-49: better define AudioBuffer audio data access
+
+date: Thu May 24 17:15:29 2012 -0700
+* fix small typo
+
+date: Thu May 24 17:13:34 2012 -0700
+* ISSUE-24: define circular routing behavior
+
+date: Thu May 24 16:35:24 2012 -0700
+* ISSUE-42: specify a-rate or k-rate for each AudioParam
+
+date: Fri May 18 17:01:36 2012 -0700
+* ISSUE-53: noteOn and noteOff interaction
+
+date: Fri May 18 16:33:29 2012 -0700
+* ISSUE-34: Remove .name attribute from AudioParam
+
+date: Fri May 18 16:27:19 2012 -0700
+* ISSUE-33: Add maxNumberOfChannels attribute to AudioDestinationNode
+
+date: Fri May 18 15:50:08 2012 -0700
+* ISSUE-19: added more info about AudioBuffer - IEEE 32-bit
+
+date: Fri May 18 15:37:27 2012 -0700
+* ISSUE-29: remove reference to webkitAudioContext
+
+date: Fri Apr 27 12:36:54 2012 -0700
+* fix two small typos reported by James Wei
+
+date: Tue Apr 24 12:27:11 2012 -0700
+* small cleanup to ChannelSplitterNode and ChannelMergerNode
+
+date: Tue Apr 17 11:35:56 2012 -0700
+* small fix to createWaveTable()
+
+date: Tue Apr 13 2012
+* Cleanup AudioNode connect() and disconnect() method descriptions.
+* Add AudioNode connect() to AudioParam method.
+
+date: Tue Apr 13 2012
+* Add OscillatorNode and WaveTable
+* Define default values for optional arguments in createJavaScriptNode(), createChannelSplitter(), createChannelMerger()
+* Define default filter type for BiquadFilterNode as LOWPASS
+
+date: Tue Apr 11 2012
+* add AudioContext .activeSourceCount attribute
+* createBuffer() methods can throw exceptions
+* add AudioContext method createMediaElementSource()
+* update AudioContext methods createJavaScriptNode() (clean up description of parameters)
+* update AudioContext method createChannelSplitter() (add numberOfOutputs parameter)
+* update AudioContext method createChannelMerger() (add numberOfInputs parameter)
+* update description of out-of-bounds AudioParam values (exception will not be thrown)
+* remove AudioBuffer .gain attribute
+* remove AudioBufferSourceNode .gain attribute
+* remove AudioListener .gain attribute
+* add AudioBufferSourceNode .playbackState attribute and state constants
+* AnalyserNode no longer requires its output be connected to anything
+* update ChannelMergerNode section describing numberOfOutputs (defaults to 6 but settable in constructor)
+* update ChannelSplitterNode section describing numberOfInputs (defaults to 6 but settable in constructor)
+* add note in Spatialization sections about potential to get arbitrary convolution matrixing
+
+date: Tue Apr 10 2012
+* Rebased editor's draft document based on edits from Thierry Michel (from 2nd public working draft).
+
+date: Tue Mar 13 12:13:41 2012 -0100
+* fixed all the HTML errors
+* added ids to all Headings
+* added alt attribute to all img
+* fix broken anchors
+* added a new status of this document section
+* added mandatory spec headers
+* generated a new table of content
+* added a Reference section
+* added an Acknowledgments section
+* added a Web Audio API Change Log
+
+date: Fri Mar 09 15:12:42 2012 -0800
+* add optional maxDelayTime argument to createDelay()
+* add more detail about playback state to AudioBufferSourceNode
+* upgrade noteOn(), noteGrainOn(), noteOff() times to double from float
+
+date: Mon Feb 06 16:52:39 2012 -0800
+* Cleanup ScriptProcessorNode section
+* Add distance model constants for PannerNode according to the OpenAL spec
+* Add .normalize attribute to ConvolverNode
+* Add getFrequencyResponse() method to BiquadFilterNode
+* Tighten up the up-mix equations
+
+date: Fri Nov 04 15:40:58 2011 -0700
+summary: Add more technical detail to BiquadFilterNode description (contributed by Raymond Toy)
+
+date: Sat Oct 15 19:08:15 2011 -0700
+summary: small edits to the introduction
+
+date: Sat Oct 15 19:00:15 2011 -0700
+summary: initial commit
+
+date: Tue Sep 13 12:49:11 2011 -0700
+summary: add convolution reverb design document
+
+date: Mon Aug 29 17:05:58 2011 -0700
+summary: document the decodeAudioData() method
+
+date: Mon Aug 22 14:36:33 2011 -0700
+summary: fix broken MediaElementAudioSourceNode link
+
+date: Mon Aug 22 14:33:57 2011 -0700
+summary: refine section describing integration with HTMLMediaElement
+
+date: Mon Aug 01 12:05:53 2011 -0700
+summary: add Privacy section
+
+date: Mon Jul 18 17:53:50 2011 -0700
+summary: small update - tweak musical applications thumbnail images
+
+date: Mon Jul 18 17:23:00 2011 -0700
+summary: initial commit of Web Audio API specification</pre>
+</div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-analysernode-interface/.gitkeep b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-analysernode-interface/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-analysernode-interface/.gitkeep
diff --git a/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-audiobuffer-interface/.gitkeep b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-audiobuffer-interface/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-audiobuffer-interface/.gitkeep
diff --git a/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-audiobuffer-interface/idl-test.html b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-audiobuffer-interface/idl-test.html
new file mode 100644
index 00000000000..be38d2c8dab
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-audiobuffer-interface/idl-test.html
@@ -0,0 +1,107 @@
+<!DOCTYPE html>
+<html class="a">
+<head>
+<title>AudioBuffer IDL Test</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script><script src="/resources/idlharness.js"></script><script src="/resources/webidl2/lib/webidl2.js"></script><script src="/webaudio/js/lodash.js"></script><script src="/webaudio/js/vendor-prefixes.js"></script><script src="/webaudio/js/helpers.js"></script><style type="text/css">
+ #event-target-idl,
+ #audio-context-idl
+ { visibility:hidden; height: 0px;}
+ </style>
+</head>
+<body class="a">
+
+ <pre id="event-target-idl">interface EventTarget {
+ void addEventListener(DOMString type, EventListener? callback, optional boolean capture = false);
+ void removeEventListener(DOMString type, EventListener? callback, optional boolean capture = false);
+ boolean dispatchEvent(Event event);
+};
+
+/*
+callback interface EventListener {
+ void handleEvent(Event event);
+};
+*/
+// Callback interfaces are not supported yet, but that's ok
+interface EventListener {};
+</pre>
+
+ <pre id="audio-context-idl">callback DecodeSuccessCallback = void (AudioBuffer decodedData);
+callback DecodeErrorCallback = void ();
+
+[Constructor]
+interface AudioContext : EventTarget {
+
+ readonly attribute AudioDestinationNode destination;
+ readonly attribute float sampleRate;
+ readonly attribute double currentTime;
+ readonly attribute AudioListener listener;
+
+ AudioBuffer createBuffer(unsigned long numberOfChannels, unsigned long length, float sampleRate);
+
+ void decodeAudioData(ArrayBuffer audioData,
+ DecodeSuccessCallback successCallback,
+ optional DecodeErrorCallback errorCallback);
+
+
+ // AudioNode creation
+ AudioBufferSourceNode createBufferSource();
+
+ MediaElementAudioSourceNode createMediaElementSource(HTMLMediaElement mediaElement);
+
+ MediaStreamAudioSourceNode createMediaStreamSource(MediaStream mediaStream);
+ MediaStreamAudioDestinationNode createMediaStreamDestination();
+
+ ScriptProcessorNode createScriptProcessor(optional unsigned long bufferSize = 0,
+ optional unsigned long numberOfInputChannels = 2,
+ optional unsigned long numberOfOutputChannels = 2);
+
+ AnalyserNode createAnalyser();
+ GainNode createGain();
+ DelayNode createDelay(optional double maxDelayTime = 1.0);
+ BiquadFilterNode createBiquadFilter();
+ WaveShaperNode createWaveShaper();
+ PannerNode createPanner();
+ ConvolverNode createConvolver();
+
+ ChannelSplitterNode createChannelSplitter(optional unsigned long numberOfOutputs = 6);
+ ChannelMergerNode createChannelMerger(optional unsigned long numberOfInputs = 6);
+
+ DynamicsCompressorNode createDynamicsCompressor();
+
+ OscillatorNode createOscillator();
+ PeriodicWave createPeriodicWave(Float32Array real, Float32Array imag);
+
+};</pre>
+
+ <pre id="audio-buffer-idl">interface AudioBuffer {
+
+ readonly attribute float sampleRate;
+ readonly attribute long length;
+
+ // in seconds
+ readonly attribute double duration;
+
+ readonly attribute long numberOfChannels;
+
+ Float32Array getChannelData(unsigned long channel);
+
+};</pre>
+
+ <div id="log"></div>
+
+ <script>
+(function() {
+ var idl_array = new IdlArray();
+ idl_array.add_untested_idls(document.getElementById("event-target-idl").textContent);
+ idl_array.add_untested_idls(document.getElementById("audio-context-idl").textContent);
+ idl_array.add_idls(document.getElementById("audio-buffer-idl").textContent);
+
+ // For these tests the value of the arguments is unimportant.
+ audio_buffer = (new AudioContext).createBuffer(numberOfChannels = 1, length = 256, sampleRate = 44100);
+
+ idl_array.add_objects({AudioBuffer: ["audio_buffer"]});
+ idl_array.test();
+})();
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-audiobuffersourcenode-interface/.gitkeep b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-audiobuffersourcenode-interface/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-audiobuffersourcenode-interface/.gitkeep
diff --git a/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-audiocontext-interface/.gitkeep b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-audiocontext-interface/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-audiocontext-interface/.gitkeep
diff --git a/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-audiodestinationnode-interface/.gitkeep b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-audiodestinationnode-interface/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-audiodestinationnode-interface/.gitkeep
diff --git a/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-audiodestinationnode-interface/idl-test.html b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-audiodestinationnode-interface/idl-test.html
new file mode 100644
index 00000000000..fb6b52dedfb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-audiodestinationnode-interface/idl-test.html
@@ -0,0 +1,128 @@
+<!DOCTYPE html>
+<html class="a">
+<head>
+<title>AudioDestinationNode IDL Test</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script><script src="/resources/idlharness.js"></script><script src="/resources/webidl2/lib/webidl2.js"></script><script src="/webaudio/js/lodash.js"></script><script src="/webaudio/js/vendor-prefixes.js"></script><script src="/webaudio/js/helpers.js"></script><style type="text/css">
+ #event-target-idl,
+ #audio-context-idl,
+ #audio-node-idl
+ { visibility:hidden; height: 0px;}
+ </style>
+</head>
+<body class="a">
+
+ <pre id="event-target-idl">interface EventTarget {
+ void addEventListener(DOMString type, EventListener? callback, optional boolean capture = false);
+ void removeEventListener(DOMString type, EventListener? callback, optional boolean capture = false);
+ boolean dispatchEvent(Event event);
+};
+
+/*
+callback interface EventListener {
+ void handleEvent(Event event);
+};
+*/
+// Callback interfaces are not supported yet, but that's ok
+interface EventListener {};
+</pre>
+
+ <pre id="audio-context-idl">callback DecodeSuccessCallback = void (AudioBuffer decodedData);
+callback DecodeErrorCallback = void ();
+
+[Constructor]
+interface AudioContext : EventTarget {
+
+ readonly attribute AudioDestinationNode destination;
+ readonly attribute float sampleRate;
+ readonly attribute double currentTime;
+ readonly attribute AudioListener listener;
+
+ AudioBuffer createBuffer(unsigned long numberOfChannels, unsigned long length, float sampleRate);
+
+ void decodeAudioData(ArrayBuffer audioData,
+ DecodeSuccessCallback successCallback,
+ optional DecodeErrorCallback errorCallback);
+
+
+ // AudioNode creation
+ AudioBufferSourceNode createBufferSource();
+
+ MediaElementAudioSourceNode createMediaElementSource(HTMLMediaElement mediaElement);
+
+ MediaStreamAudioSourceNode createMediaStreamSource(MediaStream mediaStream);
+ MediaStreamAudioDestinationNode createMediaStreamDestination();
+
+ ScriptProcessorNode createScriptProcessor(optional unsigned long bufferSize = 0,
+ optional unsigned long numberOfInputChannels = 2,
+ optional unsigned long numberOfOutputChannels = 2);
+
+ AnalyserNode createAnalyser();
+ GainNode createGain();
+ DelayNode createDelay(optional double maxDelayTime = 1.0);
+ BiquadFilterNode createBiquadFilter();
+ WaveShaperNode createWaveShaper();
+ PannerNode createPanner();
+ ConvolverNode createConvolver();
+
+ ChannelSplitterNode createChannelSplitter(optional unsigned long numberOfOutputs = 6);
+ ChannelMergerNode createChannelMerger(optional unsigned long numberOfInputs = 6);
+
+ DynamicsCompressorNode createDynamicsCompressor();
+
+ OscillatorNode createOscillator();
+ PeriodicWave createPeriodicWave(Float32Array real, Float32Array imag);
+
+};</pre>
+
+ <pre id="audio-node-idl">enum ChannelCountMode {
+ "max",
+ "clamped-max",
+ "explicit"
+};
+
+enum ChannelInterpretation {
+ "speakers",
+ "discrete"
+};
+
+interface AudioNode : EventTarget {
+
+ void connect(AudioNode destination, optional unsigned long output = 0, optional unsigned long input = 0);
+ void connect(AudioParam destination, optional unsigned long output = 0);
+ void disconnect(optional unsigned long output = 0);
+
+ readonly attribute AudioContext context;
+ readonly attribute unsigned long numberOfInputs;
+ readonly attribute unsigned long numberOfOutputs;
+
+ // Channel up-mixing and down-mixing rules for all inputs.
+ attribute unsigned long channelCount;
+ attribute ChannelCountMode channelCountMode;
+ attribute ChannelInterpretation channelInterpretation;
+
+};</pre>
+
+ <pre id="audio-destination-node-idl">interface AudioDestinationNode : AudioNode {
+
+ readonly attribute unsigned long maxChannelCount;
+
+};</pre>
+
+ <div id="log"></div>
+
+ <script>
+(function() {
+ var idl_array = new IdlArray();
+ idl_array.add_untested_idls(document.getElementById("event-target-idl").textContent);
+ idl_array.add_untested_idls(document.getElementById("audio-context-idl").textContent);
+ idl_array.add_untested_idls(document.getElementById("audio-node-idl").textContent);
+ idl_array.add_idls(document.getElementById("audio-destination-node-idl").textContent);
+
+ audio_destination_node = (new AudioContext).destination;
+
+ idl_array.add_objects({AudioDestinationNode: ["audio_destination_node"]});
+ idl_array.test();
+})();
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-audiolistener-interface/.gitkeep b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-audiolistener-interface/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-audiolistener-interface/.gitkeep
diff --git a/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-audionode-interface/.gitkeep b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-audionode-interface/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-audionode-interface/.gitkeep
diff --git a/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-audioparam-interface/.gitkeep b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-audioparam-interface/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-audioparam-interface/.gitkeep
diff --git a/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-audioprocessingevent-interface/.gitkeep b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-audioprocessingevent-interface/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-audioprocessingevent-interface/.gitkeep
diff --git a/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-biquadfilternode-interface/.gitkeep b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-biquadfilternode-interface/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-biquadfilternode-interface/.gitkeep
diff --git a/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-channelmergernode-interface/.gitkeep b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-channelmergernode-interface/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-channelmergernode-interface/.gitkeep
diff --git a/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-channelsplitternode-interface/.gitkeep b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-channelsplitternode-interface/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-channelsplitternode-interface/.gitkeep
diff --git a/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-convolvernode-interface/.gitkeep b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-convolvernode-interface/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-convolvernode-interface/.gitkeep
diff --git a/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-delaynode-interface/.gitkeep b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-delaynode-interface/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-delaynode-interface/.gitkeep
diff --git a/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-delaynode-interface/idl-test.html b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-delaynode-interface/idl-test.html
new file mode 100644
index 00000000000..b80ff2f83ca
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-delaynode-interface/idl-test.html
@@ -0,0 +1,152 @@
+<!DOCTYPE html>
+<html class="a">
+<head>
+<title>DelayNode IDL Test</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script><script src="/resources/idlharness.js"></script><script src="/resources/webidl2/lib/webidl2.js"></script><script src="/webaudio/js/lodash.js"></script><script src="/webaudio/js/vendor-prefixes.js"></script><script src="/webaudio/js/helpers.js"></script><style type="text/css">
+ #event-target-idl,
+ #audio-context-idl,
+ #audio-node-idl,
+ #audio-param-idl
+ { visibility:hidden; height: 0px;}
+ </style>
+</head>
+<body class="a">
+
+ <pre id="event-target-idl">interface EventTarget {
+ void addEventListener(DOMString type, EventListener? callback, optional boolean capture = false);
+ void removeEventListener(DOMString type, EventListener? callback, optional boolean capture = false);
+ boolean dispatchEvent(Event event);
+};
+
+/*
+callback interface EventListener {
+ void handleEvent(Event event);
+};
+*/
+// Callback interfaces are not supported yet, but that's ok
+interface EventListener {};
+</pre>
+
+ <pre id="audio-context-idl">callback DecodeSuccessCallback = void (AudioBuffer decodedData);
+callback DecodeErrorCallback = void ();
+
+[Constructor]
+interface AudioContext : EventTarget {
+
+ readonly attribute AudioDestinationNode destination;
+ readonly attribute float sampleRate;
+ readonly attribute double currentTime;
+ readonly attribute AudioListener listener;
+
+ AudioBuffer createBuffer(unsigned long numberOfChannels, unsigned long length, float sampleRate);
+
+ void decodeAudioData(ArrayBuffer audioData,
+ DecodeSuccessCallback successCallback,
+ optional DecodeErrorCallback errorCallback);
+
+
+ // AudioNode creation
+ AudioBufferSourceNode createBufferSource();
+
+ MediaElementAudioSourceNode createMediaElementSource(HTMLMediaElement mediaElement);
+
+ MediaStreamAudioSourceNode createMediaStreamSource(MediaStream mediaStream);
+ MediaStreamAudioDestinationNode createMediaStreamDestination();
+
+ ScriptProcessorNode createScriptProcessor(optional unsigned long bufferSize = 0,
+ optional unsigned long numberOfInputChannels = 2,
+ optional unsigned long numberOfOutputChannels = 2);
+
+ AnalyserNode createAnalyser();
+ GainNode createGain();
+ DelayNode createDelay(optional double maxDelayTime = 1.0);
+ BiquadFilterNode createBiquadFilter();
+ WaveShaperNode createWaveShaper();
+ PannerNode createPanner();
+ ConvolverNode createConvolver();
+
+ ChannelSplitterNode createChannelSplitter(optional unsigned long numberOfOutputs = 6);
+ ChannelMergerNode createChannelMerger(optional unsigned long numberOfInputs = 6);
+
+ DynamicsCompressorNode createDynamicsCompressor();
+
+ OscillatorNode createOscillator();
+ PeriodicWave createPeriodicWave(Float32Array real, Float32Array imag);
+
+};</pre>
+
+ <pre id="audio-node-idl">enum ChannelCountMode {
+ "max",
+ "clamped-max",
+ "explicit"
+};
+
+enum ChannelInterpretation {
+ "speakers",
+ "discrete"
+};
+
+interface AudioNode : EventTarget {
+
+ void connect(AudioNode destination, optional unsigned long output = 0, optional unsigned long input = 0);
+ void connect(AudioParam destination, optional unsigned long output = 0);
+ void disconnect(optional unsigned long output = 0);
+
+ readonly attribute AudioContext context;
+ readonly attribute unsigned long numberOfInputs;
+ readonly attribute unsigned long numberOfOutputs;
+
+ // Channel up-mixing and down-mixing rules for all inputs.
+ attribute unsigned long channelCount;
+ attribute ChannelCountMode channelCountMode;
+ attribute ChannelInterpretation channelInterpretation;
+
+};</pre>
+
+ <pre id="audio-param-idl">interface AudioParam {
+
+ attribute float value;
+ readonly attribute float defaultValue;
+
+ // Parameter automation.
+ void setValueAtTime(float value, double startTime);
+ void linearRampToValueAtTime(float value, double endTime);
+ void exponentialRampToValueAtTime(float value, double endTime);
+
+ // Exponentially approach the target value with a rate having the given time constant.
+ void setTargetAtTime(float target, double startTime, double timeConstant);
+
+ // Sets an array of arbitrary parameter values starting at time for the given duration.
+ // The number of values will be scaled to fit into the desired duration.
+ void setValueCurveAtTime(Float32Array values, double startTime, double duration);
+
+ // Cancels all scheduled parameter changes with times greater than or equal to startTime.
+ void cancelScheduledValues(double startTime);
+
+};</pre>
+
+<pre id="delay-node-idl">interface DelayNode : AudioNode {
+
+ readonly attribute AudioParam delayTime;
+
+};</pre>
+
+ <div id="log"></div>
+
+ <script>
+(function() {
+ var idl_array = new IdlArray();
+ idl_array.add_untested_idls(document.getElementById("event-target-idl").textContent);
+ idl_array.add_untested_idls(document.getElementById("audio-context-idl").textContent);
+ idl_array.add_untested_idls(document.getElementById("audio-node-idl").textContent);
+ idl_array.add_untested_idls(document.getElementById("audio-param-idl").textContent);
+ idl_array.add_idls(document.getElementById("delay-node-idl").textContent);
+
+ delay_node = (new AudioContext).createDelay();
+
+ idl_array.add_objects({DelayNode: ["delay_node"]});
+ idl_array.test();
+})();
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-dynamicscompressornode-interface/.gitkeep b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-dynamicscompressornode-interface/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-dynamicscompressornode-interface/.gitkeep
diff --git a/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-gainnode-interface/.gitkeep b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-gainnode-interface/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-gainnode-interface/.gitkeep
diff --git a/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-gainnode-interface/gain-expected.wav b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-gainnode-interface/gain-expected.wav
new file mode 100644
index 00000000000..b445bd8a620
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-gainnode-interface/gain-expected.wav
Binary files differ
diff --git a/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-gainnode-interface/idl-test.html b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-gainnode-interface/idl-test.html
new file mode 100644
index 00000000000..c6c507b6bae
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-gainnode-interface/idl-test.html
@@ -0,0 +1,152 @@
+<!DOCTYPE html>
+<html class="a">
+<head>
+<title>GainNode IDL Test</title>
+<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script><script src="/resources/idlharness.js"></script><script src="/resources/webidl2/lib/webidl2.js"></script><script src="/webaudio/js/lodash.js"></script><script src="/webaudio/js/vendor-prefixes.js"></script><script src="/webaudio/js/helpers.js"></script><style type="text/css">
+ #event-target-idl,
+ #audio-context-idl,
+ #audio-node-idl,
+ #audio-param-idl
+ { visibility:hidden; height: 0px;}
+ </style>
+</head>
+<body class="a">
+
+ <pre id="event-target-idl">interface EventTarget {
+ void addEventListener(DOMString type, EventListener? callback, optional boolean capture = false);
+ void removeEventListener(DOMString type, EventListener? callback, optional boolean capture = false);
+ boolean dispatchEvent(Event event);
+};
+
+/*
+callback interface EventListener {
+ void handleEvent(Event event);
+};
+*/
+// Callback interfaces are not supported yet, but that's ok
+interface EventListener {};
+</pre>
+
+ <pre id="audio-context-idl">callback DecodeSuccessCallback = void (AudioBuffer decodedData);
+callback DecodeErrorCallback = void ();
+
+[Constructor]
+interface AudioContext : EventTarget {
+
+ readonly attribute AudioDestinationNode destination;
+ readonly attribute float sampleRate;
+ readonly attribute double currentTime;
+ readonly attribute AudioListener listener;
+
+ AudioBuffer createBuffer(unsigned long numberOfChannels, unsigned long length, float sampleRate);
+
+ void decodeAudioData(ArrayBuffer audioData,
+ DecodeSuccessCallback successCallback,
+ optional DecodeErrorCallback errorCallback);
+
+
+ // AudioNode creation
+ AudioBufferSourceNode createBufferSource();
+
+ MediaElementAudioSourceNode createMediaElementSource(HTMLMediaElement mediaElement);
+
+ MediaStreamAudioSourceNode createMediaStreamSource(MediaStream mediaStream);
+ MediaStreamAudioDestinationNode createMediaStreamDestination();
+
+ ScriptProcessorNode createScriptProcessor(optional unsigned long bufferSize = 0,
+ optional unsigned long numberOfInputChannels = 2,
+ optional unsigned long numberOfOutputChannels = 2);
+
+ AnalyserNode createAnalyser();
+ GainNode createGain();
+ DelayNode createDelay(optional double maxDelayTime = 1.0);
+ BiquadFilterNode createBiquadFilter();
+ WaveShaperNode createWaveShaper();
+ PannerNode createPanner();
+ ConvolverNode createConvolver();
+
+ ChannelSplitterNode createChannelSplitter(optional unsigned long numberOfOutputs = 6);
+ ChannelMergerNode createChannelMerger(optional unsigned long numberOfInputs = 6);
+
+ DynamicsCompressorNode createDynamicsCompressor();
+
+ OscillatorNode createOscillator();
+ PeriodicWave createPeriodicWave(Float32Array real, Float32Array imag);
+
+};</pre>
+
+ <pre id="audio-node-idl">enum ChannelCountMode {
+ "max",
+ "clamped-max",
+ "explicit"
+};
+
+enum ChannelInterpretation {
+ "speakers",
+ "discrete"
+};
+
+interface AudioNode : EventTarget {
+
+ void connect(AudioNode destination, optional unsigned long output = 0, optional unsigned long input = 0);
+ void connect(AudioParam destination, optional unsigned long output = 0);
+ void disconnect(optional unsigned long output = 0);
+
+ readonly attribute AudioContext context;
+ readonly attribute unsigned long numberOfInputs;
+ readonly attribute unsigned long numberOfOutputs;
+
+ // Channel up-mixing and down-mixing rules for all inputs.
+ attribute unsigned long channelCount;
+ attribute ChannelCountMode channelCountMode;
+ attribute ChannelInterpretation channelInterpretation;
+
+};</pre>
+
+ <pre id="audio-param-idl">interface AudioParam {
+
+ attribute float value;
+ readonly attribute float defaultValue;
+
+ // Parameter automation.
+ void setValueAtTime(float value, double startTime);
+ void linearRampToValueAtTime(float value, double endTime);
+ void exponentialRampToValueAtTime(float value, double endTime);
+
+ // Exponentially approach the target value with a rate having the given time constant.
+ void setTargetAtTime(float target, double startTime, double timeConstant);
+
+ // Sets an array of arbitrary parameter values starting at time for the given duration.
+ // The number of values will be scaled to fit into the desired duration.
+ void setValueCurveAtTime(Float32Array values, double startTime, double duration);
+
+ // Cancels all scheduled parameter changes with times greater than or equal to startTime.
+ void cancelScheduledValues(double startTime);
+
+};</pre>
+
+<pre id="gain-node-idl">interface GainNode : AudioNode {
+
+ readonly attribute AudioParam gain;
+
+};</pre>
+
+ <div id="log"></div>
+
+ <script>
+(function() {
+ var idl_array = new IdlArray();
+ idl_array.add_untested_idls(document.getElementById("event-target-idl").textContent);
+ idl_array.add_untested_idls(document.getElementById("audio-context-idl").textContent);
+ idl_array.add_untested_idls(document.getElementById("audio-node-idl").textContent);
+ idl_array.add_untested_idls(document.getElementById("audio-param-idl").textContent);
+ idl_array.add_idls(document.getElementById("gain-node-idl").textContent);
+
+ gain_node = (new AudioContext).createGain();
+
+ idl_array.add_objects({GainNode: ["gain_node"]});
+ idl_array.test();
+})();
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-gainnode-interface/test.html b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-gainnode-interface/test.html
new file mode 100644
index 00000000000..4f92fbbe58b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-gainnode-interface/test.html
@@ -0,0 +1,121 @@
+<!doctype html>
+
+<!--
+Tests that GainNode is properly scaling the gain.
+We'll render 11 notes, starting at a gain of 1.0, decreasing in gain by 0.1.
+The 11th note will be of gain 0.0, so it should be silent (at the end in the rendered output).
+
+Based on a test from the WebKit test suite
+(https://github.com/WebKit/webkit/blob/master/LayoutTests/webaudio/gain.html)
+-->
+
+<html class="a">
+ <head>
+ <title>GainNode interface</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/webaudio/js/lodash.js"></script>
+ <script src="/webaudio/js/vendor-prefixes.js"></script>
+ <script src="/webaudio/js/helpers.js"></script>
+ <script src="/webaudio/js/buffer-loader.js"></script>
+ </head>
+ <body class="a">
+ <div id="log"></div>
+ <script>
+var gainNodeTest = async_test("GainNode");
+
+var sampleRate = 44100.0;
+var bufferDurationSeconds = 0.125;
+var numberOfNotes = 11;
+var noteSpacing = bufferDurationSeconds + 0.020; // leave 20ms of silence between each "note"
+var lengthInSeconds = numberOfNotes * noteSpacing;
+
+var context = 0;
+var expectedBuffer = 0;
+var actualBuffer = 0;
+var sinWaveBuffer = 0;
+
+function createSinWaveBuffer(lengthInSeconds, frequency) {
+ var audioBuffer = context.createBuffer(2, lengthInSeconds * sampleRate, sampleRate);
+
+ var n = audioBuffer.length;
+ var channelL = audioBuffer.getChannelData(0);
+ var channelR = audioBuffer.getChannelData(1);
+
+ for (var i = 0; i < n; ++i) {
+ channelL[i] = Math.sin(frequency * 2.0*Math.PI * i / sampleRate);
+ channelR[i] = channelL[i];
+ }
+
+ return audioBuffer;
+}
+
+function playNote(time, gain) {
+ var source = context.createBufferSource();
+ source.buffer = sinWaveBuffer;
+
+ var gainNode = context.createGain();
+ gainNode.gain.value = gain;
+
+ source.connect(gainNode);
+ gainNode.connect(context.destination);
+
+ source.start(time);
+}
+
+function loadExpectedBuffer(event) {
+ actualBuffer = event.renderedBuffer;
+
+ bufferLoader = new BufferLoader(
+ context,
+ ['/webaudio/the-audio-api/the-gainnode-interface/gain-expected.wav'],
+ bufferLoadCompleted
+ );
+ bufferLoader.load();
+};
+
+function bufferLoadCompleted(buffer) {
+ compareExpectedWithActualBuffer(buffer);
+};
+
+setup( function() {
+ // Create offline audio context.
+ context = new OfflineAudioContext(2, sampleRate * lengthInSeconds, sampleRate);
+
+ // Create a buffer for a short "note".
+ sinWaveBuffer = createSinWaveBuffer(bufferDurationSeconds, 880.0);
+
+ // Render 11 notes, starting at a gain of 1.0, decreasing in gain by 0.1.
+ // The last note will be of gain 0.0, so shouldn't be perceptible in the rendered output.
+ for (var i = 0; i < numberOfNotes; ++i) {
+ var time = i * noteSpacing;
+ var gain = 1.0 - i / (numberOfNotes - 1);
+ playNote(time, gain);
+ }
+
+ context.oncomplete = loadExpectedBuffer;
+ context.startRendering();
+}, {timeout: 10000});
+
+function compareExpectedWithActualBuffer(expected) {
+ var expectedBuffer = expected[0];
+
+ gainNodeTest.step(function() {
+ assert_array_approx_equals(expectedBuffer.getChannelData(0),
+ actualBuffer.getChannelData(0),
+ 1e-4,
+ "comparing expected and rendered buffers (channel 0)");
+ });
+
+ gainNodeTest.step(function() {
+ assert_array_approx_equals(expectedBuffer.getChannelData(1),
+ actualBuffer.getChannelData(1),
+ 1e-4,
+ "comparing expected and rendered buffers (channel 1)");
+ });
+
+ gainNodeTest.done();
+};
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-mediaelementaudiosourcenode-interface/.gitkeep b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-mediaelementaudiosourcenode-interface/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-mediaelementaudiosourcenode-interface/.gitkeep
diff --git a/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-mediaelementaudiosourcenode-interface/mediaElementAudioSourceToScriptProcessorTest.html b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-mediaelementaudiosourcenode-interface/mediaElementAudioSourceToScriptProcessorTest.html
new file mode 100644
index 00000000000..f75bdc449d7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-mediaelementaudiosourcenode-interface/mediaElementAudioSourceToScriptProcessorTest.html
@@ -0,0 +1,123 @@
+<!doctype html>
+
+<!--
+Tests that a create MediaElementSourceNode that is passed through
+a script processor passes the stream data.
+The the script processor saves the input buffers it gets to a temporary
+array, and after the playback has stopped, the contents are compared
+to those of a loaded AudioBuffer with the same source.
+
+Somewhat similiar to a test from Mozilla:
+(http://mxr.mozilla.org/mozilla-central/source/content/media/webaudio/test/test_mediaElementAudioSourceNode.html?force=1)
+-->
+
+<html class="a">
+ <head>
+ <title>MediaElementAudioSource interface test (to scriptProcessor)</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/webaudio/js/lodash.js"></script>
+ <script src="/webaudio/js/vendor-prefixes.js"></script>
+ <script src="/webaudio/js/helpers.js"></script>
+ <script src="/webaudio/js/buffer-loader.js"></script>
+ </head>
+ <body class="a">
+ <div id="log"></div>
+ <script>
+ var elementSourceTest = async_test("Element Source tests completed");
+
+ var src = '/webaudio/resources/sin_440Hz_-6dBFS_1s.wav';
+ var BUFFER_SIZE = 2048;
+ var context = null;
+ var actualBufferArrayC0 = new Float32Array(0);
+ var actualBufferArrayC1 = new Float32Array(0);
+ var audio = null, source = null, processor = null
+
+ function loadExpectedBuffer(event) {
+ bufferLoader = new BufferLoader(
+ context,
+ [src],
+ bufferLoadCompleted
+ );
+ bufferLoader.load();
+ };
+
+ function bufferLoadCompleted(buffer) {
+ runTests(buffer);
+ };
+
+ function concatTypedArray(arr1, arr2) {
+ var result = new Float32Array(arr1.length + arr2.length);
+ result.set(arr1);
+ result.set(arr2, arr1.length);
+ return result;
+ }
+
+ // Create Audio context
+ context = new AudioContext();
+
+ // Create an audio element, and a media element source
+ audio = document.createElement('audio');
+ audio.src = src;
+ source = context.createMediaElementSource(audio);
+
+ // Create a processor node to copy the input to the actual buffer
+ processor = context.createScriptProcessor(BUFFER_SIZE);
+ source.connect(processor);
+ processor.connect(context.destination);
+ processor.addEventListener('audioprocess',
+ (function (e) {
+ actualBufferArrayC0 = concatTypedArray(actualBufferArrayC0, e.inputBuffer.getChannelData(0));
+ actualBufferArrayC1 = concatTypedArray(actualBufferArrayC1, e.inputBuffer.getChannelData(1));
+ }));
+
+ // When media playback ended, save the begin to compare with expected buffer
+ audio.addEventListener("ended", function(e) {
+ // Setting a timeout since we need audioProcess event to run for all samples
+ window.setTimeout(loadExpectedBuffer, 50);
+ });
+
+ audio.play();
+
+ function runTests(expected) {
+ source.disconnect();
+ processor.disconnect();
+
+ // firefox seems to process events after disconnect
+ processor.removeEventListener('audioprocess')
+
+ var expectedBuffer = expected[0];
+
+ // Trim the actual elements because we don't have a fine-grained
+ // control over the start and end time of recording the data.
+ var actualTrimmedC0 = trimEmptyElements(actualBufferArrayC0);
+ var actualTrimmedC1 = trimEmptyElements(actualBufferArrayC1);
+ var expectedLength = trimEmptyElements(expectedBuffer.getChannelData(0)).length;
+
+ // Test that there is some data.
+ test(function() {
+ assert_greater_than(actualTrimmedC0.length, 0,
+ "processed data array (C0) length greater than 0");
+ assert_greater_than(actualTrimmedC1.length, 0,
+ "processed data array (C1) length greater than 0");
+ }, "Channel 0 processed some data");
+
+ // Test the actual contents of the 1st and second channel.
+ test(function() {
+ assert_array_approx_equals(
+ actualTrimmedC0,
+ trimEmptyElements(expectedBuffer.getChannelData(0)),
+ 1e-4,
+ "comparing expected and rendered buffers (channel 0)");
+ assert_array_approx_equals(
+ actualTrimmedC1,
+ trimEmptyElements(expectedBuffer.getChannelData(1)),
+ 1e-4,
+ "comparing expected and rendered buffers (channel 1)");
+ }, "All data processed correctly");
+
+ elementSourceTest.done();
+ };
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-mediastreamaudiodestinationnode-interface/.gitkeep b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-mediastreamaudiodestinationnode-interface/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-mediastreamaudiodestinationnode-interface/.gitkeep
diff --git a/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-mediastreamaudiosourcenode-interface/.gitkeep b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-mediastreamaudiosourcenode-interface/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-mediastreamaudiosourcenode-interface/.gitkeep
diff --git a/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-offlineaudiocontext-interface/.gitkeep b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-offlineaudiocontext-interface/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-offlineaudiocontext-interface/.gitkeep
diff --git a/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-oscillatornode-interface/.gitkeep b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-oscillatornode-interface/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-oscillatornode-interface/.gitkeep
diff --git a/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-pannernode-interface/.gitkeep b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-pannernode-interface/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-pannernode-interface/.gitkeep
diff --git a/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-periodicwave-interface/.gitkeep b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-periodicwave-interface/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-periodicwave-interface/.gitkeep
diff --git a/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-scriptprocessornode-interface/.gitkeep b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-scriptprocessornode-interface/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-scriptprocessornode-interface/.gitkeep
diff --git a/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-waveshapernode-interface/.gitkeep b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-waveshapernode-interface/.gitkeep
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-waveshapernode-interface/.gitkeep
diff --git a/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-waveshapernode-interface/curve-tests.html b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-waveshapernode-interface/curve-tests.html
new file mode 100644
index 00000000000..32ace55e6d1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-waveshapernode-interface/curve-tests.html
@@ -0,0 +1,212 @@
+<!doctype html>
+<html>
+<head>
+ <title>WaveShaperNode interface - Curve tests | WebAudio</title>
+
+ <script type="text/javascript" src="../../../resources/testharness.js"></script>
+ <script type="text/javascript" src="../../../resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="../../js/vendor-prefixes.js"></script>
+</head>
+<body>
+ <div id="log">
+ </div>
+
+ <script type="text/javascript">
+ var sampleRate=44100.0;
+ var tolerance=0.01;
+
+ /*
+ Testing that -1, 0 and +1 map correctly to curve (with 1:1 correlation)
+ =======================================================================
+ From the specification:
+ The input signal is nominally within the range -1 -> +1.
+ Each input sample within this range will index into the shaping curve with a signal level of zero corresponding
+ to the center value of the curve array.
+ */
+ (function() {
+ var threeElementCurve=[2.0, -3.0, 4.0];
+ var inputData=[-1.0, 0, 1.0];
+ var expectedData=[2.0, -3.0, 4.0];
+ executeTest(threeElementCurve, inputData, expectedData, "Testing that -1, 0 and +1 map correctly to curve (with 1:1 correlation)");
+ })();
+
+ /*
+ Testing interpolation (where inputs don't correlate directly to curve elements)
+ ===============================================================================
+ From the specification:
+ The implementation must perform linear interpolation between adjacent points in the curve.
+ */
+ (function() {
+ var threeElementCurve=[2.0, -3.0, 4.0];
+ var inputData=[-0.5, +0.5, +0.75];
+ var expectedData=[-0.5, +0.5, +2.25];
+ executeTest(threeElementCurve, inputData, expectedData, "Testing interpolation (where inputs don't correlate directly to curve elements)");
+ })();
+
+ /*
+ Testing out-of-range inputs (should be mapped to the first/last elements of the curve)
+ ======================================================================================
+ From the specification:
+ Any sample value less than -1 will correspond to the first value in the curve array.
+ Any sample value greater than +1 will correspond to the last value in the curve array.
+ */
+ (function() {
+ var threeElementCurve=[2.0, -3.0, 4.0];
+ var inputData=[-1.5, +1.5];
+ var expectedData=[2.0, 4.0];
+ executeTest(threeElementCurve, inputData, expectedData, "Testing out-of-range inputs (should be mapped to the first/last elements of the curve)");
+ })();
+
+ /*
+ Testing a 2-element curve (does not have a middle element)
+ ==========================================================
+ From the specification:
+ Each input sample within this range will index into the shaping curve with a signal level of zero corresponding
+ to the center value of the curve array.
+ The implementation must perform linear interpolation between adjacent points in the curve.
+ */
+ (function() {
+ var twoElementCurve=[2.0, -2.0];
+ var inputData=[-1.0, 0, 1.0];
+ var expectedData=[2.0, 0.0, -2.0];
+ executeTest(twoElementCurve, inputData, expectedData, "Testing a 2-element curve (does not have a middle element)");
+ })();
+
+ /*
+ Testing a 4-element curve (does not have a middle element)
+ ==========================================================
+ From the specification:
+ Each input sample within this range will index into the shaping curve with a signal level of zero corresponding
+ to the center value of the curve array.
+ The implementation must perform linear interpolation between adjacent points in the curve.
+ */
+ (function() {
+ var fourElementCurve=[1.0, 2.0, 4.0, 7.0];
+ var inputData=[-1.0, 0, 1.0];
+ var expectedData=[1.0, 3.0, 7.0];
+ executeTest(fourElementCurve, inputData, expectedData, "Testing a 4-element curve (does not have a middle element)");
+ })();
+
+ /*
+ Testing a huge curve
+ ====================
+ From the specification:
+ Each input sample within this range will index into the shaping curve with a signal level of zero corresponding
+ to the center value of the curve array.
+ */
+ (function() {
+ var bigCurve=[];
+ for(var i=0;i<=60000;i++) { bigCurve.push(i/3.5435); }
+ var inputData=[-1.0, 0, 1.0];
+ var expectedData=[bigCurve[0], bigCurve[30000], bigCurve[60000]];
+ executeTest(bigCurve, inputData, expectedData, "Testing a huge curve");
+ })();
+
+ /*
+ Testing single-element curve (boundary condition)
+ =================================================
+ From the specification:
+ Each input sample within this range will index into the shaping curve with a signal level of zero corresponding
+ to the center value of the curve array.
+ Any sample value less than -1 will correspond to the first value in the curve array.
+ Any sample value greater than +1 will correspond to the last value in the curve array.
+ The implementation must perform linear interpolation between adjacent points in the curve.
+ Note:
+ I found a post on the W3C audio mailing list (from one of the Chris's) that suggested it would be feasible
+ to use the WaveShaperNode to create constant values.
+ */
+ (function() {
+ var oneElementCurve=[1.0];
+ var inputData=[-1.0, 0, 1.0, -2.0, 2.0];
+ var expectedData=[1.0, 1.0, 1.0, 1.0, 1.0];
+ executeTest(oneElementCurve, inputData, expectedData, "Testing single-element curve (boundary condition)");
+ })();
+
+ /*
+ Testing null curve (should return input values)
+ ===============================================
+ From the specification:
+ Initially the curve attribute is null, which means that the WaveShaperNode will pass its input to its output
+ without modification.
+ */
+ (function() {
+ var inputData=[-1.0, 0, 1.0, 2.0];
+ var expectedData=[-1.0, 0.0, 1.0, 2.0];
+ executeTest(null, inputData, expectedData, "Testing null curve (should return input values)");
+ })();
+
+ /*
+ Testing zero-element curve (unspecified result)
+ ===============================================
+ From the specification:
+ Unspecified result (I assume it will be treated in the same way as a null curve).
+ Note:
+ Mozilla test_waveShaperNoCurve.html indicates they expect same results as a null curve.
+ */
+ (function() {
+ var zeroElementCurve=[];
+ var inputData=[-1.0, 0, 1.0, 2.0];
+ var expectedData=[-1.0, 0.0, 1.0, 2.0];
+ executeTest(zeroElementCurve, inputData, expectedData, "Testing zero-element curve (unspecified result)");
+ })();
+
+
+ /**
+ * Function that does the actual testing (using an asynchronous test).
+ * @param {?Array.<number>} curveData - Array containing values for the WaveShaper curve.
+ * @param {!Array.<number>} inputData - Array containing values for the input stream.
+ * @param {!Array.<number>} expectedData - Array containing expected results for each of the corresponding inputs.
+ * @param {!string} testName - Name of the test case.
+ */
+ function executeTest(curveData, inputData, expectedData, testName) {
+ var stTest=async_test("WaveShaperNode - "+testName);
+
+ // Create offline audio context.
+ var ac=new OfflineAudioContext(1, inputData.length, sampleRate);
+
+ // Create the WaveShaper and its curve.
+ var waveShaper=ac.createWaveShaper();
+ if(curveData!=null) {
+ var curve=new Float32Array(curveData.length);
+ for(var i=0;i<curveData.length;i++) { curve[i]=curveData[i]; }
+ waveShaper.curve=curve;
+ }
+ waveShaper.connect(ac.destination);
+
+ // Create buffer containing the input values.
+ var inputBuffer=ac.createBuffer(1, Math.max(inputData.length, 2), sampleRate);
+ var d=inputBuffer.getChannelData(0);
+ for(var i=0;i<inputData.length;i++) { d[i]=inputData[i]; }
+
+ // Play the input buffer through the WaveShaper.
+ var src=ac.createBufferSource();
+ src.buffer=inputBuffer;
+ src.connect(waveShaper);
+ src.start();
+
+ // Test the outputs match the expected values.
+ ac.oncomplete=function(ev) {
+ var d=ev.renderedBuffer.getChannelData(0);
+
+ stTest.step(function() {
+ for(var i=0;i<expectedData.length;i++) {
+ var curveText="null";
+ if(curve!=null) {
+ if(curveData.length<20) {
+ curveText=curveData.join(",");
+ } else {
+ curveText="TooBigToDisplay ("+(curveData.length-1)+" elements)";
+ }
+ }
+ var comment="Input="+inputData[i]+", Curve=["+curveText+"] >>> ";
+ assert_approx_equals(d[i], expectedData[i], tolerance, comment);
+ }
+ });
+
+ stTest.done();
+ };
+ ac.startRendering();
+ }
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webdriver/README.md b/tests/wpt/web-platform-tests/webdriver/README.md
new file mode 100644
index 00000000000..7a89fb78ad4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/README.md
@@ -0,0 +1,38 @@
+# W3C Browser Automation Specification Tests
+
+This repository defines a set of conformance tests for the W3C web
+browser automation specification known as WebDriver. The purpose is
+for the different driver implementations to be tested to determine
+whether they meet the recognized standard.
+
+## How to run the tests
+
+1. Go to the WebDriver tests: `cd _WEBDRIVER_TEST_ROOT_`
+2. Run the tests: `python runtests.py`
+3. Run the test against a different config specified in webdriver.cfg:
+ `WD_BROWSER=chrome python runtests.py`
+
+To be run a specific test file you can just run `python test_file.py`
+
+Similarly you can specify a different browser to run against if in webdriver.cfg:
+ `WD_BROWSER=chrome python ecmascript/ecmascript_test.py`
+
+Note: that you will need likely need to start the driver's server before running.
+
+## Updating configuration
+
+The _webdriver.cfg_ file holds any configuration that the tests might
+require. Change the value of browser to your needs. This will then
+be picked up by WebDriverBaseTest when tests are run.
+
+Be sure not to commit your _webdriver.cfg_ changes when your create or modify tests.
+
+## How to write tests
+
+1. Create a test file per section from the specification.
+2. For each test there needs to be one or more corresponding HTML
+ files that will be used for testing. HTML files are not to be
+ reused between tests. HTML files and other support files
+ should be stored in a folder named 'res'.
+3. Test name should explain the intention of the test e.g. `def
+ test_navigate_and_return_title(self):`
diff --git a/tests/wpt/web-platform-tests/webdriver/base_test.py b/tests/wpt/web-platform-tests/webdriver/base_test.py
new file mode 100644
index 00000000000..9fe6b6ef3f0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/base_test.py
@@ -0,0 +1,49 @@
+import ConfigParser
+import json
+import os
+import sys
+import unittest
+
+from network import get_lan_ip
+
+repo_root = os.path.abspath(os.path.join(__file__, "../.."))
+sys.path.insert(1, os.path.join(repo_root, "tools", "webdriver"))
+sys.path.insert(1, os.path.join(repo_root, "tools", "wptserve"))
+from wptserve import server
+from webdriver.driver import WebDriver
+
+
+class WebDriverBaseTest(unittest.TestCase):
+ @classmethod
+ def setUpClass(cls):
+ cls.driver = create_driver()
+
+ cls.webserver = server.WebTestHttpd(host=get_lan_ip())
+ cls.webserver.start()
+ cls.webserver.where_is = cls.webserver.get_url
+
+ @classmethod
+ def tearDownClass(cls):
+ cls.webserver.stop()
+ if cls.driver:
+ cls.driver.quit()
+
+
+def create_driver():
+ config = ConfigParser.ConfigParser()
+ config.read('webdriver.cfg')
+ section = os.environ.get("WD_BROWSER", 'firefox')
+ url = 'http://127.0.0.1:4444/wd/hub'
+ if config.has_option(section, 'url'):
+ url = config.get(section, "url")
+ capabilities = None
+ if config.has_option(section, 'capabilities'):
+ try:
+ capabilities = json.loads(config.get(section, "capabilities"))
+ except:
+ pass
+ mode = 'compatibility'
+ if config.has_option(section, 'mode'):
+ mode = config.get(section, 'mode')
+
+ return WebDriver(url, {}, capabilities, mode)
diff --git a/tests/wpt/web-platform-tests/webdriver/cookie/__init__.py b/tests/wpt/web-platform-tests/webdriver/cookie/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/cookie/__init__.py
diff --git a/tests/wpt/web-platform-tests/webdriver/cookie/cookie_test.py b/tests/wpt/web-platform-tests/webdriver/cookie/cookie_test.py
new file mode 100644
index 00000000000..e4211cbb946
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/cookie/cookie_test.py
@@ -0,0 +1,67 @@
+import os
+import sys
+import unittest
+
+sys.path.insert(1, os.path.abspath(os.path.join(__file__, "../..")))
+import base_test
+from webdriver import exceptions
+
+
+class CookieTest(base_test.WebDriverBaseTest):
+ def setUp(self):
+ self.driver.get(self.webserver.where_is("cookie/res/cookie_container.html"))
+
+ def test_can_create_a_well_formed_cookie( self ):
+ name = 'foo'
+ value = 'bar'
+
+ self.driver.add_cookie({ 'name': name, 'value': value })
+
+ def test_cookies_should_allow_secure_to_be_set( self ):
+ name = 'foo'
+ value = 'bar'
+ secure = True
+
+ self.driver.add_cookie({ 'name': name,
+ 'value': value,
+ 'path': '/',
+ 'secure': secure})
+ self.assertTrue(self.driver.get_cookie(name)[0]['secure'])
+
+ def test_secure_defaults_to_false( self ):
+ name = 'foo'
+ value = 'bar'
+
+ self.driver.add_cookie({ 'name': name,
+ 'value': value})
+
+ self.assertFalse(self.driver.get_cookie(name)[0]['secure'])
+
+ def test_should_throw_an_exception_when_semicolon_exists_in_the_cookie_attribute(self):
+ invalid_name = 'foo;bar'
+ value = 'foobar'
+
+ try:
+ self.driver.add_cookie({ 'name': invalid_name, 'value': value })
+ self.fail( 'should have thrown exceptions.' )
+
+ except exceptions.UnableToSetCookieException:
+ pass
+ except exceptions.InvalidCookieDomainException:
+ pass
+
+ def test_should_throw_an_exception_the_name_is_null(self):
+ val = 'foobar'
+
+ try:
+ self.driver.add_cookie({ 'name': None, 'value': val })
+ self.fail( 'should have thrown exceptions.' )
+
+ except exceptions.UnableToSetCookieException:
+ pass
+ except exceptions.InvalidCookieDomainException:
+ pass
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/wpt/web-platform-tests/webdriver/cookie/res/cookie_container.html b/tests/wpt/web-platform-tests/webdriver/cookie/res/cookie_container.html
new file mode 100644
index 00000000000..bb6b209bb6f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/cookie/res/cookie_container.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Cookie Container</title>
+<body>
+</body>
diff --git a/tests/wpt/web-platform-tests/webdriver/ecmascript/ecmascript_test.py b/tests/wpt/web-platform-tests/webdriver/ecmascript/ecmascript_test.py
new file mode 100644
index 00000000000..89764bf688e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/ecmascript/ecmascript_test.py
@@ -0,0 +1,17 @@
+import os
+import sys
+import unittest
+
+sys.path.insert(1, os.path.abspath(os.path.join(__file__, "../..")))
+import base_test
+
+
+class EcmasScriptTest(base_test.WebDriverBaseTest):
+ def test_that_ecmascript_returns_document_title(self):
+ self.driver.get(self.webserver.where_is("ecmascript/res/ecmascript_test.html"))
+ result = self.driver.execute_script("return document.title;");
+ self.assertEquals("ecmascript test", result);
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/wpt/web-platform-tests/webdriver/ecmascript/res/ecmascript_test.html b/tests/wpt/web-platform-tests/webdriver/ecmascript/res/ecmascript_test.html
new file mode 100644
index 00000000000..346e2ef75d2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/ecmascript/res/ecmascript_test.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<title>ecmascript test</title> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/webdriver/element_location/__init__.py b/tests/wpt/web-platform-tests/webdriver/element_location/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_location/__init__.py
diff --git a/tests/wpt/web-platform-tests/webdriver/element_location/element_location_test.py b/tests/wpt/web-platform-tests/webdriver/element_location/element_location_test.py
new file mode 100644
index 00000000000..acbc56d7ee4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_location/element_location_test.py
@@ -0,0 +1,37 @@
+import os
+import sys
+import unittest
+
+sys.path.insert(1, os.path.abspath(os.path.join(__file__, "../..")))
+import base_test
+
+
+class ElementLocationTest(base_test.WebDriverBaseTest):
+ def test_find_element_by_name(self):
+ self.driver.get(self.webserver.where_is("element_location/res/elements.html"))
+ e = self.driver.find_element_by_css("*[name='name']")
+ self.assertEquals("name", e.text)
+
+ def test_find_element_by_css_selector(self):
+ self.driver.get(self.webserver.where_is("element_location/res/elements.html"))
+ e = self.driver.find_element_by_css("#id")
+ self.assertEquals("id", e.text)
+
+ def test_find_element_by_link_text(self):
+ self.driver.get(self.webserver.where_is("element_location/res/elements.html"))
+ e = self.driver.find_element_by_link_text("link text")
+ self.assertEquals("link text", e.text)
+
+ def test_find_element_by_partial_link_text(self):
+ self.driver.get(self.webserver.where_is("element_location/res/elements.html"))
+ e = self.driver.find_element_by_partial_link_text("link tex")
+ self.assertEquals("link text", e.text)
+
+ def test_find_element_by_xpath(self):
+ self.driver.get(self.webserver.where_is("element_location/res/elements.html"))
+ e = self.driver.find_element_by_xpath("//*[@id='id']")
+ self.assertEquals("id", e.text)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/wpt/web-platform-tests/webdriver/element_location/res/elements.html b/tests/wpt/web-platform-tests/webdriver/element_location/res/elements.html
new file mode 100644
index 00000000000..45b7c237012
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_location/res/elements.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+
+<title>Element location</title>
+
+<body>
+ <div id="id">id</div>
+ <div id="name" name="name">name</div>
+ <a id="link">link text</a>
+</body>
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/__init__.py b/tests/wpt/web-platform-tests/webdriver/element_state/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/__init__.py
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/method_test.py b/tests/wpt/web-platform-tests/webdriver/element_state/method_test.py
new file mode 100644
index 00000000000..e357471a0c2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/method_test.py
@@ -0,0 +1,71 @@
+import os
+import sys
+import unittest
+
+sys.path.insert(1, os.path.abspath(os.path.join(__file__, "../..")))
+import base_test
+
+
+class GetElementAttributeTest(base_test.WebDriverBaseTest):
+ def test_get_element_attribute(self):
+ self.driver.get(self.webserver.where_is("element_state/res/element-with-id-attribute.html"))
+ el = self.driver.find_element_by_css("div")
+ self.assertEqual("myId", el.get_attribute("id"))
+
+ def test_style_attribute(self):
+ self.driver.get(self.webserver.where_is("element_state/res/element-with-style-attribute.html"))
+ el = self.driver.find_element_by_css("div")
+ expected_style = """
+ font-family: \"Gill Sans Extrabold\",Helvetica,sans-serif;
+ line-height: 1.2; font-weight: bold;
+ """
+ self.assertEqual(expected_style, el.get_attribute("style"))
+
+ def test_color_serialization_of_style_attribute(self):
+ self.driver.get(self.webserver.where_is("element_state/res/element-with-color-style-attribute.html"))
+ el = self.driver.find_element_by_css("div")
+ self.assertEqual("color: rgba(255, 0, 0, 1.0);", el.get_attribute("style"))
+
+ def test_true_if_boolean_attribute_present(self):
+ self.driver.get(self.webserver.where_is("element_state/res/input-with-checked-attribute.html"))
+ el = self.driver.find_element_by_css("input")
+ self.assertEqual("true", el.get_attribute("checked"))
+
+ def test_none_if_boolean_attribute_absent(self):
+ self.driver.get(self.webserver.where_is("element_state/res/input-without-checked-attribute.html"))
+ el = self.driver.find_element_by_css("input")
+ self.assertIsNone(el.get_attribute("checked"))
+
+ def test_option_with_attribute_value(self):
+ self.driver.get(self.webserver.where_is("element_state/res/option-with-value-attribute.html"))
+ el = self.driver.find_element_by_css("option")
+ self.assertEqual("value1", el.get_attribute("value"))
+
+ def test_option_without_value_attribute(self):
+ self.driver.get(self.webserver.where_is("element_state/res/option-without-value-attribute.html"))
+ el = self.driver.find_element_by_css("option")
+ self.assertEqual("Value 1", el.get_attribute("value"))
+
+ def test_a_href_attribute(self):
+ self.driver.get(self.webserver.where_is("element_state/res/a-with-href-attribute.html"))
+ el = self.driver.find_element_by_css("a")
+ self.assertEqual("http://web-platform.test:8000/path#fragment", el.get_attribute("href"))
+
+ def test_img_src_attribute(self):
+ self.driver.get(self.webserver.where_is("element_state/res/img-with-src-attribute.html"))
+ el = self.driver.find_element_by_css("img")
+ self.assertEqual("http://web-platform.test:8000/images/blue.png", el.get_attribute("src"))
+
+ def test_custom_attribute(self):
+ self.driver.get(self.webserver.where_is("element_state/res/element-with-custom-attribute.html"))
+ el = self.driver.find_element_by_css("div")
+ self.assertEqual("attribute value", el.get_attribute("webdriver-custom-attribute"))
+
+ def test_attribute_not_present(self):
+ self.driver.get(self.webserver.where_is("element_state/res/element-without-attribute.html"))
+ el = self.driver.find_element_by_css("div")
+ self.assertIsNone(el.get_attribute("class"))
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/res/0x0-pixels.html b/tests/wpt/web-platform-tests/webdriver/element_state/res/0x0-pixels.html
new file mode 100644
index 00000000000..3b081ca090f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/res/0x0-pixels.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<meta charset='utf-8'>
+<title>0x0 pixel element</title>
+
+<style>
+div {
+ height: 0;
+ width: 0;
+}
+</style>
+
+<div>This element is not visible.</div>
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/res/1x1-pixels.html b/tests/wpt/web-platform-tests/webdriver/element_state/res/1x1-pixels.html
new file mode 100644
index 00000000000..f9b2cbc3c3a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/res/1x1-pixels.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<meta charset='utf-8'>
+<title>1x1 pixel element</title>
+
+<style>
+p {
+ height: 1px;
+ width: 1px;
+}
+</style>
+
+<p>This element is visible.</p>
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/res/a-with-href-attribute.html b/tests/wpt/web-platform-tests/webdriver/element_state/res/a-with-href-attribute.html
new file mode 100644
index 00000000000..7722426a3a5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/res/a-with-href-attribute.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>"a" element with not fully qualified url</title>
+
+<a href="//web-platform.test:8000/path#fragment">&nbsp;</a> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/res/absolute-children-ancestor-hidden-overflow.html b/tests/wpt/web-platform-tests/webdriver/element_state/res/absolute-children-ancestor-hidden-overflow.html
new file mode 100644
index 00000000000..fcf1044140a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/res/absolute-children-ancestor-hidden-overflow.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Parent node visible with absolutely positioned children, where ancestor overflow is hidden</title>
+
+<style>
+ body {
+ overflow: hidden;
+ height: 0;
+ width: 0;
+ }
+ .child { position: absolute }
+</style>
+
+<div id=parent>
+ <div class=child>grated</div>
+ <div class=child>cheese</div>
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/res/body_empty.html b/tests/wpt/web-platform-tests/webdriver/element_state/res/body_empty.html
new file mode 100644
index 00000000000..0f4dff6917f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/res/body_empty.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>BODY element has no children. MUST be reported displayed</title>
+<body/>
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/res/body_implicit.html b/tests/wpt/web-platform-tests/webdriver/element_state/res/body_implicit.html
new file mode 100644
index 00000000000..f4581538006
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/res/body_implicit.html
@@ -0,0 +1,3 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>BODY tag is omitted; BODY element MUST be reported displayed</title>
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/res/body_overflow_hidden.html b/tests/wpt/web-platform-tests/webdriver/element_state/res/body_overflow_hidden.html
new file mode 100644
index 00000000000..1411ef37be0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/res/body_overflow_hidden.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>BODY element with style=overflow:hidden. MUST be reported displayed</title>
+<body style="overflow:hidden"/>
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/res/body_visibility_hidden.html b/tests/wpt/web-platform-tests/webdriver/element_state/res/body_visibility_hidden.html
new file mode 100644
index 00000000000..ce4d410365a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/res/body_visibility_hidden.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>BODY element with style=visibility:hidden. MUST be reported displayed</title>
+<body style="visibility:hidden"/>
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/res/display-block.html b/tests/wpt/web-platform-tests/webdriver/element_state/res/display-block.html
new file mode 100644
index 00000000000..0f31557e6b3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/res/display-block.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset='utf-8'>
+<title>display: block;</title>
+
+<p>This element is visible.</p>
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/res/display-none-child-link.html b/tests/wpt/web-platform-tests/webdriver/element_state/res/display-none-child-link.html
new file mode 100644
index 00000000000..88bdef6b5b6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/res/display-none-child-link.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>display: none applies to child node links</title>
+
+<style>
+#parent { display: none }
+</style>
+
+<div id="parent">
+ <a id="child">hidden</a>
+</div>
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/res/display-none-child-paragraph.html b/tests/wpt/web-platform-tests/webdriver/element_state/res/display-none-child-paragraph.html
new file mode 100644
index 00000000000..31ab16da4f3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/res/display-none-child-paragraph.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>display: none applies to child node paragraphs</title>
+
+<style>
+#parent { display: none }
+</style>
+
+<div id="parent">
+ <p id="child">hidden</p>
+</div>
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/res/display-none-child.html b/tests/wpt/web-platform-tests/webdriver/element_state/res/display-none-child.html
new file mode 100644
index 00000000000..b45ea0e5a07
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/res/display-none-child.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>display: none applies to child nodes</title>
+
+<style>
+#parent { display: none }
+</style>
+
+<div id="parent">
+ <div id="child">Brie is good</div>
+</div>
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/res/display-none-dynamic.html b/tests/wpt/web-platform-tests/webdriver/element_state/res/display-none-dynamic.html
new file mode 100644
index 00000000000..074f0b3c1b0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/res/display-none-dynamic.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>display: none set dynamically</title>
+
+<p id="hidden">Should not be visible</span>
+
+<script>
+ var hidden = document.getElementById("hidden");
+ hidden.style.display = "none";
+</script>
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/res/display-none-parent-presedence-visibility.html b/tests/wpt/web-platform-tests/webdriver/element_state/res/display-none-parent-presedence-visibility.html
new file mode 100644
index 00000000000..37ca02391aa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/res/display-none-parent-presedence-visibility.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>display: none on parent takes presedence over visibility: visible on child node</title>
+
+<style>
+ #parent { display: none }
+ #child { visibility: visible }
+</style>
+
+<div id="parent">
+ <div id="child">
+ hidden
+ </div>
+</div>
+in \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/res/display-none-parent-presedence.html b/tests/wpt/web-platform-tests/webdriver/element_state/res/display-none-parent-presedence.html
new file mode 100644
index 00000000000..0f166d1e5e4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/res/display-none-parent-presedence.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>display: none on parent takes presedence</title>
+
+<style>
+ #parent { display: none }
+ #child { dipslay: block }
+</style>
+
+<div id="parent">
+ <div id="child">
+ hidden
+ </div>
+</div>
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/res/display-none.html b/tests/wpt/web-platform-tests/webdriver/element_state/res/display-none.html
new file mode 100644
index 00000000000..469fc934b3a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/res/display-none.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<meta charset='utf-8'>
+<title>display: none;</title>
+
+<style>
+p {
+ display: none;
+}
+</style>
+
+<p>This element is not visible.</p>
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/res/element-dynamically-moved-outside-viewport.html b/tests/wpt/web-platform-tests/webdriver/element_state/res/element-dynamically-moved-outside-viewport.html
new file mode 100644
index 00000000000..e31912bfd91
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/res/element-dynamically-moved-outside-viewport.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>Element outside viewport</title>
+
+<style>
+ div { position: absolute }
+</style>
+
+<div>hidden</div>
+
+<script>
+ var el = document.getElementsByTagName("div")[0];
+ el.style.top = "-500px";
+ el.style.left = "-500px";
+</script>
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/res/element-hidden-by-other-element.html b/tests/wpt/web-platform-tests/webdriver/element_state/res/element-hidden-by-other-element.html
new file mode 100644
index 00000000000..a2cf645a3bb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/res/element-hidden-by-other-element.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>Element hidden by other element</title>
+
+<style>
+ div {
+ position: absolute;
+ height: 100px;
+ width: 100px;
+ }
+
+ #overlay {
+ background: blue;
+ }
+
+ #hidden { background: red }
+</style>
+
+<div id="hidden"></div>
+<div id="overlay"></div>
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/res/element-hidden-by-z-index.html b/tests/wpt/web-platform-tests/webdriver/element_state/res/element-hidden-by-z-index.html
new file mode 100644
index 00000000000..c51049079b8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/res/element-hidden-by-z-index.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>Element hidden by z-index</title>
+
+<style>
+ * { position: relative }
+
+ #overlay,
+ #hidden {
+ height: 50px;
+ width: 50px;
+ }
+
+ #overlay {
+ background: blue;
+
+ z-index: 1;
+ }
+
+ #hidden {
+ background: red;
+ top: -50px;
+
+ z-index: -1;
+ }
+</style>
+
+<div id="overlay"></div>
+<div id="hidden"></div>
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/res/element-moved-behind-other-element-by-transform.html b/tests/wpt/web-platform-tests/webdriver/element_state/res/element-moved-behind-other-element-by-transform.html
new file mode 100644
index 00000000000..ee5470514e9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/res/element-moved-behind-other-element-by-transform.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>Element moved behind other element by transform</title>
+
+<style>
+ * { position: relative }
+
+ #overlay {
+ height: 50px;
+ width: 50px;
+ background: blue;
+ z-index: 1;
+ }
+
+ #hidden {
+ height: 50px;
+ width: 50px;
+ background: red;
+ z-index: -1;
+
+ transform: translate(0, -50px);
+
+ /* fix your browsers god damnit */
+ -webkit-transform: translate(0, -50px);
+ -moz-transform: translate(0x, -50px);
+ }
+</style>
+
+<div id="overlay"></div>
+<div id="hidden"></div>
+
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/res/element-moved-outside-viewport-by-transform.html b/tests/wpt/web-platform-tests/webdriver/element_state/res/element-moved-outside-viewport-by-transform.html
new file mode 100644
index 00000000000..51f6ee89f2f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/res/element-moved-outside-viewport-by-transform.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>Element moved outside viewpor by transform</title>
+
+<style>
+ div {
+ transform: translate(-200px, -200px);
+
+ /* fix your browsers god damnit */
+ -webkit-transform: translate(-200px, -200px);
+ -moz-transform: translate(-200px, -200px);
+ }
+</style>
+
+<div>Cheddar!</div>
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/res/element-outside-viewport.html b/tests/wpt/web-platform-tests/webdriver/element_state/res/element-outside-viewport.html
new file mode 100644
index 00000000000..e3382ad0969
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/res/element-outside-viewport.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>Element outside viewport</title>
+
+<style>
+ div {
+ position: absolute;
+ top: -500px;
+ left: -500px;
+ }
+</style>
+
+<div>hidden</div>
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/res/element-partially-hidden-by-other-element.html b/tests/wpt/web-platform-tests/webdriver/element_state/res/element-partially-hidden-by-other-element.html
new file mode 100644
index 00000000000..2a234cc2afb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/res/element-partially-hidden-by-other-element.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>Element partially hidden by other element</title>
+
+<style>
+ div {
+ height: 100px;
+ width: 100px;
+ }
+
+ #partial {
+ background: yellow;
+ }
+
+ #other {
+ background: blue;
+ margin-top: -50px;
+ margin-left: 50px;
+ }
+</style>
+
+<div id="partial"></div>
+<div id="other"></div>
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/res/element-with-color-style-attribute.html b/tests/wpt/web-platform-tests/webdriver/element_state/res/element-with-color-style-attribute.html
new file mode 100644
index 00000000000..acf2fc0957f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/res/element-with-color-style-attribute.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>Element with color style attribute</title>
+
+<div style="color: red">&nbsp;</div> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/res/element-with-custom-attribute.html b/tests/wpt/web-platform-tests/webdriver/element_state/res/element-with-custom-attribute.html
new file mode 100644
index 00000000000..8f84b97ff94
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/res/element-with-custom-attribute.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>Element with custom attribute</title>
+
+<div webdriver-custom-attribute="attribute value">&nbsp;</div> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/res/element-with-id-attribute.html b/tests/wpt/web-platform-tests/webdriver/element_state/res/element-with-id-attribute.html
new file mode 100644
index 00000000000..7512344f503
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/res/element-with-id-attribute.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>Element with id attribute</title>
+
+<div id="myId">&nbsp;</div> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/res/element-with-same-color-as-background.html b/tests/wpt/web-platform-tests/webdriver/element_state/res/element-with-same-color-as-background.html
new file mode 100644
index 00000000000..aaea9a935c5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/res/element-with-same-color-as-background.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>Element with same color as background</title>
+
+<style>
+ body, div { background: white }
+ div { width: 50px; height: 50px; }
+</style>
+
+<div>&nbsp;</div>
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/res/element-with-same-color-as-parent-background.html b/tests/wpt/web-platform-tests/webdriver/element_state/res/element-with-same-color-as-parent-background.html
new file mode 100644
index 00000000000..88cda898ad5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/res/element-with-same-color-as-parent-background.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>Element with same color as background</title>
+
+<style>
+ #overlay,
+ #hidden {
+ background: blue;
+ width: 50px; height: 50px;
+ }
+
+ #hidden {
+ margin-top: -50px;
+ }
+</style>
+
+<div id="overlay"></div>
+<div id="hidden"></div>
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/res/element-with-style-attribute.html b/tests/wpt/web-platform-tests/webdriver/element_state/res/element-with-style-attribute.html
new file mode 100644
index 00000000000..b163a751a45
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/res/element-with-style-attribute.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>Element with style attribute</title>
+
+<div style='font-family: "Gill Sans Extrabold", Helvetica, sans-serif; line-height: 1.2; font-weight:bold'>&nbsp;</div> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/res/element-without-attribute.html b/tests/wpt/web-platform-tests/webdriver/element_state/res/element-without-attribute.html
new file mode 100644
index 00000000000..b03d4545b5e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/res/element-without-attribute.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>Element without attribute</title>
+
+<div>&nbsp;</div> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/res/hidden-input-type-checkbox-untogglable.html b/tests/wpt/web-platform-tests/webdriver/element_state/res/hidden-input-type-checkbox-untogglable.html
new file mode 100644
index 00000000000..7e7c2e23811
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/res/hidden-input-type-checkbox-untogglable.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>Hidden INPUT @type="checkbox" is untogglable</title>
+
+<style>
+ input { display: none }
+</style>
+
+<input type="checkbox" />
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/res/hidden-input-type-text-writing.html b/tests/wpt/web-platform-tests/webdriver/element_state/res/hidden-input-type-text-writing.html
new file mode 100644
index 00000000000..a1db85009ad
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/res/hidden-input-type-text-writing.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>Typing in hidden input is impossible</title>
+
+<style>
+ input { display: none }
+</style>
+
+<input type="text" />
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/res/hidden.html b/tests/wpt/web-platform-tests/webdriver/element_state/res/hidden.html
new file mode 100644
index 00000000000..0e8097e973e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/res/hidden.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<div id='singleHidden' hidden>This will not be visible</div>
+<div id='parent' hidden>
+ <div id='child'>My parent is hidden so you can't see me</div>
+</div> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/res/img-with-src-attribute.html b/tests/wpt/web-platform-tests/webdriver/element_state/res/img-with-src-attribute.html
new file mode 100644
index 00000000000..057bb9bf5f8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/res/img-with-src-attribute.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>"img" element with not fully qualified url</title>
+
+<img src="//web-platform.test:8000/images/blue.png">&nbsp;</a> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/res/input-morphs-into-hidden.html b/tests/wpt/web-platform-tests/webdriver/element_state/res/input-morphs-into-hidden.html
new file mode 100644
index 00000000000..98b954855f1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/res/input-morphs-into-hidden.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>INPUT motphs into @type="hidden"</title>
+
+<input />
+
+<script>
+ var input = document.getElementsByTagName("input")[0];
+ input.type = "hidden";
+</script>
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/res/input-type-hidden-unclickable.html b/tests/wpt/web-platform-tests/webdriver/element_state/res/input-type-hidden-unclickable.html
new file mode 100644
index 00000000000..b06822b108c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/res/input-type-hidden-unclickable.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>INPUT @type="hidden" is unclickable</title>
+
+<input type="hidden" />
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/res/input-type-hidden.html b/tests/wpt/web-platform-tests/webdriver/element_state/res/input-type-hidden.html
new file mode 100644
index 00000000000..b7195709d89
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/res/input-type-hidden.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>INPUT @type="hidden" are always hidden</title>
+
+<input type="hidden" />
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/res/input-with-checked-attribute.html b/tests/wpt/web-platform-tests/webdriver/element_state/res/input-with-checked-attribute.html
new file mode 100644
index 00000000000..d7aad5ea5f4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/res/input-with-checked-attribute.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>Input with checked attribute</title>
+
+<input type=checkbox checked="false">&nbsp;</input> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/res/input-without-checked-attribute.html b/tests/wpt/web-platform-tests/webdriver/element_state/res/input-without-checked-attribute.html
new file mode 100644
index 00000000000..9f1d5ad3548
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/res/input-without-checked-attribute.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>Input without checked attribute</title>
+
+<input type=checkbox>&nbsp;</input> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/res/option-with-value-attribute.html b/tests/wpt/web-platform-tests/webdriver/element_state/res/option-with-value-attribute.html
new file mode 100644
index 00000000000..5ef08c40588
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/res/option-with-value-attribute.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>Option with value attribute</title>
+
+<select>
+ <option value="value1">Value 1</option>
+</select> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/res/option-without-value-attribute.html b/tests/wpt/web-platform-tests/webdriver/element_state/res/option-without-value-attribute.html
new file mode 100644
index 00000000000..5f6087ddde1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/res/option-without-value-attribute.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>Option without value attribute</title>
+
+<select>
+ <option>Value 1</option>
+</select> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/res/text-with-matching-color-and-background.html b/tests/wpt/web-platform-tests/webdriver/element_state/res/text-with-matching-color-and-background.html
new file mode 100644
index 00000000000..d6591ef0455
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/res/text-with-matching-color-and-background.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>Text with matching color and background</title>
+
+<style>
+ p {
+ background: blue;
+ color: blue;
+ }
+</style>
+
+<p>
+ This on the other hand, should be visible
+</p>
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/res/text-with-same-color-as-background.html b/tests/wpt/web-platform-tests/webdriver/element_state/res/text-with-same-color-as-background.html
new file mode 100644
index 00000000000..e6290d57659
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/res/text-with-same-color-as-background.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>Text with same color as background</title>
+
+<style>
+ body { background: white }
+ p { color: white }
+</style>
+
+<p>
+ Shouldn't be visible.
+</p>
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/res/text-with-same-color-as-parent-background.html b/tests/wpt/web-platform-tests/webdriver/element_state/res/text-with-same-color-as-parent-background.html
new file mode 100644
index 00000000000..f7480f5094e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/res/text-with-same-color-as-parent-background.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>Text with same color as parent background</title>
+
+<style>
+ #parent { background: gray }
+ p { color: gray }
+</style>
+
+<div id="parent">
+ <p>
+ Should not be visible
+ </p>
+</div>g
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/res/visibility-child-link.html b/tests/wpt/web-platform-tests/webdriver/element_state/res/visibility-child-link.html
new file mode 100644
index 00000000000..638c3c9eeb7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/res/visibility-child-link.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>visibility: hidden applies to child node of type A</title>
+
+<style>
+#parent { visibility: hidden }
+</style>
+
+<div id="parent">
+ <a id="child" href="#">Brie is good</a>
+</div>
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/res/visibility-child-paragraph.html b/tests/wpt/web-platform-tests/webdriver/element_state/res/visibility-child-paragraph.html
new file mode 100644
index 00000000000..8f703ba54d6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/res/visibility-child-paragraph.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>visibility: hidden applies to child nodes of type P</title>
+
+<style>
+#parent { visibility: hidden }
+</style>
+
+<div id="parent">
+ <p id="child">Brie is good</p>
+</div>
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/res/visibility-child-presedence.html b/tests/wpt/web-platform-tests/webdriver/element_state/res/visibility-child-presedence.html
new file mode 100644
index 00000000000..adf679c8a0c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/res/visibility-child-presedence.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>visibility: visible on child node takes presedence</title>
+
+<style>
+#parent { visibility: hidden }
+#child { visibility: visible }
+</style>
+
+<div id="parent">
+ <div id="child">Brie is good</div>
+</div>
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/res/visibility-child.html b/tests/wpt/web-platform-tests/webdriver/element_state/res/visibility-child.html
new file mode 100644
index 00000000000..5464025faf8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/res/visibility-child.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>visibility: hidden applies to child nodes</title>
+
+<style>
+#parent { visibility: hidden }
+</style>
+
+<div id="parent">
+ <div id="child">Brie is good</div>
+</div>
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/res/visibility-hidden.html b/tests/wpt/web-platform-tests/webdriver/element_state/res/visibility-hidden.html
new file mode 100644
index 00000000000..24e89499ff5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/res/visibility-hidden.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<meta charset='utf-8'>
+<title>visibility: hidden;</title>
+
+<style>
+p {
+ visibility: hidden;
+}
+</style>
+
+<p>This element is not visible.</p>
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/res/visibility-visible.html b/tests/wpt/web-platform-tests/webdriver/element_state/res/visibility-visible.html
new file mode 100644
index 00000000000..e0c090217f5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/res/visibility-visible.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset='utf-8'>
+<title>visibility: visible;</title>
+
+<p>This element is visible.</p>
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/res/x-auto-y-hidden.html b/tests/wpt/web-platform-tests/webdriver/element_state/res/x-auto-y-hidden.html
new file mode 100644
index 00000000000..96fd750a6b4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/res/x-auto-y-hidden.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Page with overflow</title>
+ <style>
+ #over {
+ width:400px;
+ height: 300px;
+ overflow-x: auto;
+ overflow-y: hidden;
+ }
+ </style>
+</head>
+<body>
+ <div id="over">
+ <div style="width: 5000px;">
+ <div style="width: 100%; text-align: right;" ><a href="#" id="right" onclick="document.getElementById('right-clicked').innerText='ok'">Click right</a></div>
+ </div>
+ <div style="height: 5000px; width: 5000px;">
+ Right clicked: <span id="right-clicked"></span></br>
+ Bottom clicked: <span id="bottom-clicked"></span></br>
+ Bottom-right clicked: <span id="bottom-right-clicked"></span></br>
+ </div>
+ <div style="width: 5000px;">
+ <div style="width: 100%; text-align: right;" ><a href="#" id="bottom-right" onclick="document.getElementById('bottom-right-clicked').innerText='ok'">Click bottom-right</a></div>
+ </div>
+ <a href="#" id="bottom" onclick="document.getElementById('bottom-clicked').innerText='ok'">Click bottom</a>
+ </div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/res/x-hidden-y-auto.html b/tests/wpt/web-platform-tests/webdriver/element_state/res/x-hidden-y-auto.html
new file mode 100644
index 00000000000..24dd1928306
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/res/x-hidden-y-auto.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Page with overflow</title>
+ <style>
+ #over {
+ width:400px;
+ height: 300px;
+ overflow-x: hidden;
+ overflow-y: auto;
+ }
+ </style>
+</head>
+<body>
+ <div id="over">
+ <div style="width: 5000px;">
+ <div style="width: 100%; text-align: right;" ><a href="#" id="right" onclick="document.getElementById('right-clicked').innerText='ok'">Click right</a></div>
+ </div>
+ <div style="height: 5000px; width: 5000px;">
+ Right clicked: <span id="right-clicked"></span></br>
+ Bottom clicked: <span id="bottom-clicked"></span></br>
+ Bottom-right clicked: <span id="bottom-right-clicked"></span></br>
+ </div>
+ <div style="width: 5000px;">
+ <div style="width: 100%; text-align: right;" ><a href="#" id="bottom-right" onclick="document.getElementById('bottom-right-clicked').innerText='ok'">Click bottom-right</a></div>
+ </div>
+ <a href="#" id="bottom" onclick="document.getElementById('bottom-clicked').innerText='ok'">Click bottom</a>
+ </div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/res/x-hidden-y-hidden.html b/tests/wpt/web-platform-tests/webdriver/element_state/res/x-hidden-y-hidden.html
new file mode 100644
index 00000000000..cae566578f0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/res/x-hidden-y-hidden.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Page with overflow</title>
+ <style>
+ #over {
+ width:400px;
+ height: 300px;
+ overflow-x: hidden;
+ overflow-y: hidden;
+ }
+ </style>
+</head>
+<body>
+ <div id="over">
+ <div style="width: 5000px;">
+ <div style="width: 100%; text-align: right;" ><a href="#" id="right" onclick="document.getElementById('right-clicked').innerText='ok'">Click right</a></div>
+ </div>
+ <div style="height: 5000px; width: 5000px;">
+ Right clicked: <span id="right-clicked"></span></br>
+ Bottom clicked: <span id="bottom-clicked"></span></br>
+ Bottom-right clicked: <span id="bottom-right-clicked"></span></br>
+ </div>
+ <div style="width: 5000px;">
+ <div style="width: 100%; text-align: right;" ><a href="#" id="bottom-right" onclick="document.getElementById('bottom-right-clicked').innerText='ok'">Click bottom-right</a></div>
+ </div>
+ <a href="#" id="bottom" onclick="document.getElementById('bottom-clicked').innerText='ok'">Click bottom</a>
+ </div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/res/x-hidden-y-scroll.html b/tests/wpt/web-platform-tests/webdriver/element_state/res/x-hidden-y-scroll.html
new file mode 100644
index 00000000000..d4ffa3970fb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/res/x-hidden-y-scroll.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Page with overflow</title>
+ <style>
+ #over {
+ width:400px;
+ height: 300px;
+ overflow-x: hidden;
+ overflow-y: scroll;
+ }
+ </style>
+</head>
+<body>
+ <div id="over">
+ <div style="width: 5000px;">
+ <div style="width: 100%; text-align: right;" ><a href="#" id="right" onclick="document.getElementById('right-clicked').innerText='ok'">Click right</a></div>
+ </div>
+ <div style="height: 5000px; width: 5000px;">
+ Right clicked: <span id="right-clicked"></span></br>
+ Bottom clicked: <span id="bottom-clicked"></span></br>
+ Bottom-right clicked: <span id="bottom-right-clicked"></span></br>
+ </div>
+ <div style="width: 5000px;">
+ <div style="width: 100%; text-align: right;" ><a href="#" id="bottom-right" onclick="document.getElementById('bottom-right-clicked').innerText='ok'">Click bottom-right</a></div>
+ </div>
+ <a href="#" id="bottom" onclick="document.getElementById('bottom-clicked').innerText='ok'">Click bottom</a>
+ </div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/res/x-scroll-y-hidden.html b/tests/wpt/web-platform-tests/webdriver/element_state/res/x-scroll-y-hidden.html
new file mode 100644
index 00000000000..4a6ff595d3b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/res/x-scroll-y-hidden.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Page with overflow</title>
+ <style>
+ #over {
+ width:400px;
+ height: 300px;
+ overflow-x: scroll;
+ overflow-y: hidden;
+ }
+ </style>
+</head>
+<body>
+ <div id="over">
+ <div style="width: 5000px;">
+ <div style="width: 100%; text-align: right;" ><a href="#" id="right" onclick="document.getElementById('right-clicked').innerText='ok'">Click right</a></div>
+ </div>
+ <div style="height: 5000px; width: 5000px;">
+ Right clicked: <span id="right-clicked"></span></br>
+ Bottom clicked: <span id="bottom-clicked"></span></br>
+ Bottom-right clicked: <span id="bottom-right-clicked"></span></br>
+ </div>
+ <div style="width: 5000px;">
+ <div style="width: 100%; text-align: right;" ><a href="#" id="bottom-right" onclick="document.getElementById('bottom-right-clicked').innerText='ok'">Click bottom-right</a></div>
+ </div>
+ <a href="#" id="bottom" onclick="document.getElementById('bottom-clicked').innerText='ok'">Click bottom</a>
+ </div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/res/zero-sized-element-with-sizable-decendant.html b/tests/wpt/web-platform-tests/webdriver/element_state/res/zero-sized-element-with-sizable-decendant.html
new file mode 100644
index 00000000000..f7e37f855b6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/res/zero-sized-element-with-sizable-decendant.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>Zero sized element with sizable decendant</title>
+
+<style>
+ #parent { width: 0; height: 0; }
+ #child { width: 100; height: 100; background-color: blue; }
+</style>
+
+<div id="parent">
+ <div id="child">
+ &nbsp;
+ </div>
+</div>
diff --git a/tests/wpt/web-platform-tests/webdriver/element_state/visibility_test.py b/tests/wpt/web-platform-tests/webdriver/element_state/visibility_test.py
new file mode 100644
index 00000000000..02efadb0aca
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/element_state/visibility_test.py
@@ -0,0 +1,324 @@
+import os
+import sys
+import unittest
+
+sys.path.insert(1, os.path.abspath(os.path.join(__file__, "../..")))
+import base_test
+from webdriver import exceptions
+
+
+class NaturalNonVisibleElementsTest(base_test.WebDriverBaseTest):
+ def test_0x0_pixel_element_is_not_visible(self):
+ self.driver.get(self.webserver.where_is("element_state/res/0x0-pixels.html"))
+ el = self.driver.find_element_by_css("div")
+ self.assertFalse(el.is_displayed())
+
+ def test_0x0_pixel_text_node_is_visible(self):
+ self.driver.get(self.webserver.where_is("element_state/res/0x0-pixels-text-node.html"))
+ el = self.driver.find_element_by_css("p")
+ self.assertTrue(el.is_displayed())
+
+ def test_1x1_pixel_element(self):
+ self.driver.get(self.webserver.where_is("element_state/res/1x1-pixels.html"))
+ el = self.driver.find_element_by_css("p")
+ self.assertTrue(el.is_displayed())
+
+ def test_zero_sized_element_is_shown_if_decendant_has_size(self):
+ self.driver.get(self.webserver.where_is("element_state/res/zero-sized-element-with-sizable-decendant.html"))
+ parent = self.driver.find_element_by_css("#parent")
+ child = self.driver.find_element_by_css("#child")
+
+ self.assertTrue(parent.is_displayed())
+ self.assertTrue(child.is_displayed())
+
+ def test_input_type_hidden_is_never_visible(self):
+ self.driver.get(self.webserver.where_is("element_state/res/input-type-hidden.html"))
+ input = self.driver.find_element_by_css("input")
+ self.assertFalse(input.is_displayed())
+
+ def test_input_morphs_into_hidden(self):
+ self.driver.get(self.webserver.where_is("element_state/res/input-morphs-into-hidden.html"))
+ input = self.driver.find_element_by_css("input")
+ self.assertFalse(input.is_displayed())
+
+ def test_parent_node_visible_when_all_children_are_absolutely_positioned_and_overflow_is_hidden(self):
+ pass
+
+ def test_parent_of_absolutely_positioned_elements_visible_where_ancestor_overflow_is_hidden(self):
+ """When a parent's ancestor hides any overflow, absolutely positioned child elements are
+ still visible. The parent container is also considered visible by webdriver for this
+ reason because it is interactable."""
+
+ self.driver.get(self.webserver.where_is("element_state/res/absolute-children-ancestor-hidden-overflow.html"))
+
+ children = self.driver.find_elements_by_css(".child")
+ assert all(child.is_displayed() for child in children)
+
+ parent = self.driver.find_element_by_css("#parent")
+ assert parent.is_displayed()
+
+ def test_element_hidden_by_overflow_x_is_not_visible(self):
+ # TODO(andreastt): This test should probably be split in three. Also it's making two
+ # assertions.
+ pages = ["element_state/res/x-hidden-y-hidden.html",
+ "element_state/res/x-hidden-y-scroll.html",
+ "element_state/res/x-hidden-y-auto.html"]
+
+ for page in pages:
+ self.driver.get(self.webserver.where_is(page))
+ right = self.driver.find_element_by_css("#right")
+ bottom_right = self.driver.find_element_by_css("#bottom-right")
+
+ self.assertFalse(right.is_displayed())
+ self.assertFalse(bottom_right.is_displayed())
+
+ def test_element_hidden_by_overflow_y_is_not_visible(self):
+ # TODO(andreastt): This test should probably be split in three. Also it's making two
+ # assertions.
+ pages = ["element_state/res/x-hidden-y-hidden.html",
+ "element_state/res/x-scroll-y-hidden.html",
+ "element_state/res/x-auto-y-hidden.html"]
+
+ for page in pages:
+ self.driver.get(self.webserver.where_is(page))
+ bottom = self.driver.find_element_by_css("#bottom")
+ bottom_right = self.driver.find_element_by_css("#bottom-right")
+
+ self.assertFalse(bottom.is_displayed())
+ self.assertFalse(bottom_right.is_displayed())
+
+ def test_parent_node_visible_when_all_children_are_absolutely_position_and_overflow_is_hidden(self):
+ pass
+
+ def test_element_scrollable_by_overflow_x_is_visible(self):
+ pass
+
+ def test_element_scrollable_by_overflow_y_is_visible(self):
+ pass
+
+ def test_element_scrollable_by_overflow_x_and_y_is_visible(self):
+ pass
+
+ def test_element_scrollable_by_overflow_y_is_visible(self):
+ pass
+
+ def test_element_outside_viewport(self):
+ self.driver.get(self.webserver.where_is("element_state/res/element-outside-viewport.html"))
+ hidden = self.driver.find_element_by_css("div")
+ self.assertFalse(hidden.is_displayed())
+
+ def test_element_dynamically_moved_outside_viewport(self):
+ self.driver.get(self.webserver.where_is("element_state/res/element-dynamically-moved-outside-viewport.html"))
+ hidden = self.driver.find_element_by_css("div")
+ self.assertFalse(hidden.is_displayed())
+
+ def test_element_hidden_by_other_element(self):
+ self.driver.get(self.webserver.where_is("element_state/res/element-hidden-by-other-element.html"))
+ overlay = self.driver.find_element_by_css("#overlay")
+ hidden = self.driver.find_element_by_css("#hidden")
+
+ self.assertTrue(overlay.is_displayed())
+ self.assertFalse(hidden.is_displayed())
+
+ def test_element_partially_hidden_by_other_element(self):
+ self.driver.get(self.webserver.where_is("element_state/res/element-partially-hidden-by-other-element.html"))
+ partial = self.driver.find_element_by_css("#partial")
+ self.assertTrue(partial.is_displayed())
+
+ def test_element_hidden_by_z_index(self):
+ self.driver.get(self.webserver.where_is("element_state/res/element-hidden-by-z-index.html"))
+ overlay = self.driver.find_element_by_css("#overlay")
+ hidden = self.driver.find_element_by_css("#hidden")
+
+ self.assertTrue(overlay.is_displayed())
+ self.assertFalse(hidden.is_displayed())
+
+ def test_element_moved_outside_viewport_by_transform(self):
+ self.driver.get(self.webserver.where_is("element_state/res/element-moved-outside-viewport-by-transform.html"))
+ el = self.driver.find_element_by_css("div")
+ self.assertFalse(el.is_displayed())
+
+ def test_element_moved_behind_other_element_by_transform(self):
+ self.driver.get(self.webserver.where_is("element_state/res/element-moved-behind-other-element-by-transform.html"))
+ overlay = self.driver.find_element_by_css("#overlay")
+ hidden = self.driver.find_element_by_css("#hidden")
+
+ self.assertTrue(overlay.is_displayed())
+ self.assertFalse(hidden.is_displayed())
+
+ def test_text_with_same_color_as_background(self):
+ self.driver.get(self.webserver.where_is("element_state/res/text-with-same-color-as-background.html"))
+ p = self.driver.find_element_by_css("p")
+ self.assertFalse(p.is_displayed())
+
+ def test_text_with_same_color_as_parent_background(self):
+ self.driver.get(self.webserver.where_is("element_state/res/text-with-same-color-as-parent-background.html"))
+ p = self.driver.find_element_by_css("p")
+ self.assertFalse(p.is_displayed())
+
+ def test_text_with_matching_color_and_background(self):
+ self.driver.get(self.webserver.where_is("element_state/res/text-with-matching-color-and-background.html"))
+ p = self.driver.find_element_by_css("p")
+ self.assertTrue(p.is_displayed())
+
+ def test_element_with_same_color_as_background(self):
+ self.driver.get(self.webserver.where_is("element_state/res/element-with-same-color-as-background.html"))
+ el = self.driver.find_element_by_css("div")
+ self.assertFalse(el.is_displayed())
+
+ def test_element_with_same_color_as_parent_background(self):
+ self.driver.get(self.webserver.where_is("element_state/res/element-with-same-color-as-parent-background.html"))
+ hidden = self.driver.find_element_by_css("#hidden")
+ self.assertFalse(hidden.is_displayed())
+
+
+class BodyElementIsAlwaysDisplayedTest(base_test.WebDriverBaseTest):
+ def assert_body_is_displayed_on(self, page):
+ self.driver.get(self.webserver.where_is(page))
+ body = self.driver.find_element_by_css("body")
+ assert body.is_displayed()
+
+ def test_implicit(self):
+ self.assert_body_is_displayed_on("element_state/res/body_implicit.html")
+
+ def test_empty(self):
+ self.assert_body_is_displayed_on("element_state/res/body_empty.html")
+
+ def test_visibility_hidden(self):
+ self.assert_body_is_displayed_on("element_state/res/body_visibility_hidden.html")
+
+ def test_overflow_hidden(self):
+ self.assert_body_is_displayed_on("element_state/res/body_overflow_hidden.html")
+
+
+class DisplayTest(base_test.WebDriverBaseTest):
+ def test_display_block(self):
+ self.driver.get(self.webserver.where_is("element_state/res/display-block.html"))
+ el = self.driver.find_element_by_css("p")
+ self.assertTrue(el.is_displayed())
+
+ def test_display_none(self):
+ self.driver.get(self.webserver.where_is("element_state/res/display-none.html"))
+ el = self.driver.find_element_by_css("p")
+ self.assertFalse(el.is_displayed())
+
+ def test_display_none_hides_child_node(self):
+ self.driver.get(self.webserver.where_is("element_state/res/display-none-child.html"))
+ parent = self.driver.find_element_by_css("#parent")
+ child = self.driver.find_element_by_css("#child")
+
+ self.assertFalse(parent.is_displayed())
+ self.assertFalse(child.is_displayed())
+
+ def test_display_none_hides_child_node_link(self):
+ self.driver.get(self.webserver.where_is("element_state/res/display-none-child-link.html"))
+ child = self.driver.find_element_by_css("#child")
+ self.assertFalse(child.is_displayed())
+
+ def test_display_none_hides_child_node_paragraph(self):
+ self.driver.get(self.webserver.where_is("element_state/res/display-none-child-paragraph.html"))
+ child = self.driver.find_element_by_css("#child")
+ self.assertFalse(child.is_displayed())
+
+ def test_display_none_on_parent_takes_presedence(self):
+ self.driver.get(self.webserver.where_is("element_state/res/display-none-parent-presedence.html"))
+ child = self.driver.find_element_by_css("#child")
+ self.assertFalse(child.is_displayed())
+
+ def test_display_none_on_parent_takes_presedence_over_visibility_visible(self):
+ self.driver.get(self.webserver.where_is("element_state/res/display-none-parent-presedence-visibility.html"))
+ child = self.driver.find_element_by_css("#child")
+ self.assertFalse(child.is_displayed())
+
+ def test_display_none_hidden_dynamically(self):
+ self.driver.get(self.webserver.where_is("element_state/res/display-none-dynamic.html"))
+ hidden = self.driver.find_element_by_css("#hidden")
+ self.assertFalse(hidden.is_displayed())
+
+
+class VisibilityTest(base_test.WebDriverBaseTest):
+ def test_element_state_hidden(self):
+ self.driver.get(self.webserver.where_is("element_state/res/visibility-hidden.html"))
+ el = self.driver.find_element_by_css("p")
+ self.assertFalse(el.is_displayed())
+
+ def test_element_state_visible(self):
+ self.driver.get(self.webserver.where_is("element_state/res/visibility-visible.html"))
+ el = self.driver.find_element_by_css("p")
+ self.assertTrue(el.is_displayed())
+
+ def test_visibility_hidden_hides_child_node(self):
+ self.driver.get(self.webserver.where_is("element_state/res/visibility-child.html"))
+ parent = self.driver.find_element_by_css("#parent")
+ child = self.driver.find_element_by_css("#child")
+
+ self.assertFalse(parent.is_displayed())
+ self.assertFalse(child.is_displayed())
+
+ def test_visibility_hidden_hides_child_node_link(self):
+ self.driver.get(self.webserver.where_is("element_state/res/visibility-child-link.html"))
+ parent = self.driver.find_element_by_css("#parent")
+ child = self.driver.find_element_by_css("#child")
+
+ self.assertFalse(parent.is_displayed())
+ self.assertFalse(child.is_displayed())
+
+ def test_visibility_hidden_hides_child_node_paragraph(self):
+ self.driver.get(self.webserver.where_is("element_state/res/visibility-child-paragraph.html"))
+ parent = self.driver.find_element_by_css("#parent")
+ child = self.driver.find_element_by_css("#child")
+
+ self.assertFalse(parent.is_displayed())
+ self.assertFalse(child.is_displayed())
+
+ def test_visibility_hidden_on_child_takes_precedence(self):
+ self.driver.get(self.webserver.where_is("element_state/res/visibility-child-presedence.html"))
+ child = self.driver.find_element_by_css("#child")
+ self.assertTrue(child.is_displayed())
+
+ def test_visibility_hidden_on_parent_takes_precedence_over_display_block(self):
+ pass
+
+ def test_visibility_hidden_set_dynamically(self):
+ pass
+
+ def test_should_show_element_not_visible_with_hidden_attribute(self):
+ self.driver.get(self.webserver.where_is("element_state/res/hidden.html"))
+ singleHidden = self.driver.find_element_by_css('#singleHidden')
+ self.assertFalse(singleHidden.is_displayed())
+
+ def test_should_show_element_not_visible_when_parent_element_has_hidden_attribute(self):
+ self.driver.get(self.webserver.where_is("element_state/res/hidden.html"))
+ child = self.driver.find_element_by_css('#child')
+ self.assertFalse(child.is_displayed())
+
+
+class VisibilityInteractionTest(base_test.WebDriverBaseTest):
+ def test_input_hidden_is_unclickable(self):
+ self.driver.get(self.webserver.where_is("element_state/res/input-type-hidden-unclickable.html"))
+ input = self.driver.find_element_by_css("input")
+
+ with self.assertRaises(exceptions.ElementNotVisibleException):
+ input.click()
+
+ def test_hidden_input_checkbox_is_untogglable(self):
+ self.driver.get(self.webserver.where_is("element_state/res/hidden-input-type-checkbox-untogglable.html"))
+ checkbox = self.driver.find_element_by_css("input")
+
+ with self.assertRaises(exceptions.ElementNotVisibleException):
+ checkbox.click()
+
+ def test_typing_in_hidden_input_is_impossible(self):
+ self.driver.get(self.webserver.where_is("element_state/res/hidden-input-type-text-writing.html"))
+ textfield = self.driver.find_element_by_css("input")
+
+ with self.assertRaises(exceptions.ElementNotVisibleException):
+ textfield.send_keys("Koha is a popular Indian cheese")
+
+
+class OpacityTest(base_test.WebDriverBaseTest):
+ pass
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/wpt/web-platform-tests/webdriver/javascript/__init__.py b/tests/wpt/web-platform-tests/webdriver/javascript/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/javascript/__init__.py
diff --git a/tests/wpt/web-platform-tests/webdriver/javascript/execute_script_test.py b/tests/wpt/web-platform-tests/webdriver/javascript/execute_script_test.py
new file mode 100644
index 00000000000..72810a5fe04
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/javascript/execute_script_test.py
@@ -0,0 +1,128 @@
+import os
+import sys
+import unittest
+
+sys.path.insert(1, os.path.abspath(os.path.join(__file__, "../..")))
+import base_test
+
+
+class ExecuteScriptTest(base_test.WebDriverBaseTest):
+ def test_ecmascript_translates_null_return_to_none(self):
+ self.driver.get(self.webserver.where_is("javascript/res/execute_script_test.html"))
+ result = self.driver.execute_script("return null;")
+ self.assertIsNone(result)
+
+ def test_ecmascript_translates_undefined_return_to_none(self):
+ self.driver.get(self.webserver.where_is("javascript/res/execute_script_test.html"))
+ result = self.driver.execute_script("var undef; return undef;")
+ self.assertIsNone(result)
+
+ def test_can_return_numbers_from_scripts(self):
+ self.driver.get(self.webserver.where_is("javascript/res/execute_script_test.html"))
+ self.assertEquals(1, self.driver.execute_script("return 1;"))
+ self.assertEquals(3.14, self.driver.execute_script("return 3.14;"))
+
+ def test_can_return_strings_from_scripts(self):
+ self.driver.get(self.webserver.where_is("javascript/res/execute_script_test.html"))
+ self.assertEquals("hello, world!",
+ self.driver.execute_script("return 'hello, world!'"))
+
+ def test_can_return_booleans_from_scripts(self):
+ self.driver.get(self.webserver.where_is("javascript/res/execute_script_test.html"))
+ self.assertTrue(self.driver.execute_script("return true;"))
+ self.assertFalse(self.driver.execute_script("return false;"))
+
+ def test_can_return_an_array_of_primitives(self):
+ self.driver.get(self.webserver.where_is("javascript/res/execute_script_test.html"))
+
+ result = self.driver.execute_script("return [1, false, null, 3.14]")
+ self.assertListEqual([1, False, None, 3.14], result)
+
+ def test_can_return_nested_arrays(self):
+ self.driver.get(self.webserver.where_is("javascript/res/execute_script_test.html"))
+ result = self.driver.execute_script("return [[1, 2, [3]]]")
+
+ self.assertIsInstance(result, list)
+ self.assertEquals(1, len(result))
+
+ result = result[0]
+ self.assertListEqual([1, 2], result[:2])
+ self.assertListEqual([3], result[2])
+
+ def test_can_return_object_literals(self):
+ self.driver.get(self.webserver.where_is("javascript/res/execute_script_test.html"))
+
+ result = self.driver.execute_script("return {}")
+ self.assertDictEqual({}, result)
+
+ result = self.driver.execute_script("return {a: 1, b: false, c: null}")
+ self.assertDictEqual({
+ "a": 1,
+ "b": False,
+ "c": None
+ }, result)
+
+ def test_can_return_complex_object_literals(self):
+ self.driver.get(self.webserver.where_is("javascript/res/execute_script_test.html"))
+ result = self.driver.execute_script("return {a:{b: 'hello'}}")
+ self.assertIsInstance(result, dict)
+ self.assertIsInstance(result['a'], dict)
+ self.assertDictEqual({"b": "hello"}, result["a"])
+
+ def test_dom_element_return_value_is_translated_to_a_web_element(self):
+ self.driver.get(self.webserver.where_is(
+ "javascript/res/return_document_body.html"))
+
+ result = self.driver.execute_script("return document.body")
+ self.assertEquals(result.text, "Hello, world!")
+
+ def test_return_an_array_of_dom_elements(self):
+ self.driver.get(self.webserver.where_is(
+ "javascript/res/return_array_of_dom_elements.html"))
+
+ result = self.driver.execute_script(
+ "var nodes = document.getElementsByTagName('div');"
+ "return [nodes[0], nodes[1]]")
+
+ self.assertIsInstance(result, list)
+ self.assertEquals(2, len(result))
+ self.assertEquals("a", result[0].text)
+ self.assertEquals("b", result[1].text)
+
+ def test_node_list_return_value_is_translated_to_list_of_web_elements(self):
+ self.driver.get(self.webserver.where_is(
+ "javascript/res/return_array_of_dom_elements.html"))
+
+ result = self.driver.execute_script(
+ "return document.getElementsByTagName('div');")
+
+ self.assertIsInstance(result, list)
+ self.assertEquals(2, len(result))
+ self.assertEquals("a", result[0].text)
+ self.assertEquals("b", result[1].text)
+
+ def test_return_object_literal_with_dom_element_property(self):
+ self.driver.get(self.webserver.where_is("javascript/res/execute_script_test.html"))
+ result = self.driver.execute_script("return {a: document.body}")
+ self.assertIsInstance(result, dict)
+ self.assertEquals("body", result["a"].tag_name)
+
+ def test_scripts_execute_in_anonymous_function_and_do_not_pollute_global_scope(self):
+ self.driver.get(self.webserver.where_is("javascript/res/execute_script_test.html"))
+ self.driver.execute_script("var x = 1;")
+ self.assertEquals("undefined", self.driver.execute_script("return typeof x;"));
+
+ def test_scripts_can_modify_context_window_object(self):
+ self.driver.get(self.webserver.where_is("javascript/res/execute_script_test.html"))
+ self.driver.execute_script("window.x = 1;")
+ self.assertEquals("number", self.driver.execute_script("return typeof x;"));
+ self.assertEquals(1, self.driver.execute_script("return x;"));
+
+ def test_that_ecmascript_returns_document_title(self):
+ self.driver.get(self.webserver.where_is("javascript/res/execute_script_test.html"))
+ result = self.driver.execute_script("return document.title;")
+ self.assertEquals("executeScript test", result)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/wpt/web-platform-tests/webdriver/javascript/res/execute_script_test.html b/tests/wpt/web-platform-tests/webdriver/javascript/res/execute_script_test.html
new file mode 100644
index 00000000000..9491b441a0a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/javascript/res/execute_script_test.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<title>executeScript test</title> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/webdriver/javascript/res/return_array_of_dom_elements.html b/tests/wpt/web-platform-tests/webdriver/javascript/res/return_array_of_dom_elements.html
new file mode 100644
index 00000000000..32827f950ff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/javascript/res/return_array_of_dom_elements.html
@@ -0,0 +1,3 @@
+<!DOCTYPE html>
+<div id="one">a</div>
+<div id="two">b</div>
diff --git a/tests/wpt/web-platform-tests/webdriver/javascript/res/return_document_body.html b/tests/wpt/web-platform-tests/webdriver/javascript/res/return_document_body.html
new file mode 100644
index 00000000000..ba1eab4465e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/javascript/res/return_document_body.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<div>Hello, world!</div>
diff --git a/tests/wpt/web-platform-tests/webdriver/javascript/res/return_node_list.html b/tests/wpt/web-platform-tests/webdriver/javascript/res/return_node_list.html
new file mode 100644
index 00000000000..32827f950ff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/javascript/res/return_node_list.html
@@ -0,0 +1,3 @@
+<!DOCTYPE html>
+<div id="one">a</div>
+<div id="two">b</div>
diff --git a/tests/wpt/web-platform-tests/webdriver/modal/__init__.py b/tests/wpt/web-platform-tests/webdriver/modal/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/modal/__init__.py
diff --git a/tests/wpt/web-platform-tests/webdriver/modal/alerts_quit_test.py b/tests/wpt/web-platform-tests/webdriver/modal/alerts_quit_test.py
new file mode 100644
index 00000000000..2650a2dc678
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/modal/alerts_quit_test.py
@@ -0,0 +1,25 @@
+import os
+import sys
+import unittest
+
+sys.path.insert(1, os.path.abspath(os.path.join(__file__, "../..")))
+import base_test
+from webdriver import exceptions, wait
+
+
+class AlertsQuitTest(base_test.WebDriverBaseTest):
+ def setUp(self):
+ self.wait = wait.WebDriverWait(self.driver, 5, ignored_exceptions=[exceptions.NoSuchAlertException])
+ self.driver.get(self.webserver.where_is('modal/res/alerts.html'))
+
+ def test_can_quit_when_an_alert_is_present(self):
+ self.driver.find_element_by_css('#alert').click()
+ alert = self.wait.until(lambda x: x.switch_to_alert())
+ self.driver.quit()
+ with self.assertRaises(Exception):
+ alert.accept()
+ AlertsQuitTest.driver = None
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/wpt/web-platform-tests/webdriver/modal/alerts_test.py b/tests/wpt/web-platform-tests/webdriver/modal/alerts_test.py
new file mode 100644
index 00000000000..d4182f6d07b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/modal/alerts_test.py
@@ -0,0 +1,147 @@
+import os
+import sys
+import unittest
+
+sys.path.insert(1, os.path.abspath(os.path.join(__file__, "../..")))
+import base_test
+from webdriver import exceptions, wait
+
+
+class AlertsTest(base_test.WebDriverBaseTest):
+ def setUp(self):
+ self.wait = wait.WebDriverWait(self.driver, 5, ignored_exceptions = [exceptions.NoSuchAlertException])
+ self.driver.get(self.webserver.where_is('modal/res/alerts.html'))
+
+ def tearDown(self):
+ try:
+ self.driver.switch_to_alert().dismiss()
+ except exceptions.NoSuchAlertException:
+ pass
+
+ # Alerts
+ def test_should_allow_user_to_accept_an_alert(self):
+ self.driver.find_element_by_css('#alert').click()
+ alert = self.wait.until(lambda x: x.switch_to_alert())
+ alert.accept()
+ self.driver.get_current_url()
+
+ def test_should_allow_user_to_accept_an_alert_with_no_text(self):
+ self.driver.find_element_by_css('#empty-alert').click()
+ alert = self.wait.until(lambda x: x.switch_to_alert())
+ alert.accept()
+ self.driver.get_current_url()
+
+ def test_should_allow_user_to_dismiss_an_alert(self):
+ self.driver.find_element_by_css('#alert').click()
+ alert = self.wait.until(lambda x: x.switch_to_alert())
+ alert.dismiss()
+ self.driver.get_current_url()
+
+ def test_should_allow_user_to_get_text_of_an_alert(self):
+ self.driver.find_element_by_css('#alert').click()
+ alert = self.wait.until(lambda x: x.switch_to_alert())
+ value = alert.get_text()
+ alert.accept()
+ self.assertEquals('cheese', value)
+
+ def test_setting_the_value_of_an_alert_throws(self):
+ self.driver.find_element_by_css('#alert').click()
+ alert = self.wait.until(lambda x: x.switch_to_alert())
+ with self.assertRaises(exceptions.ElementNotVisibleException):
+ alert.send_keys('cheese')
+ alert.accept()
+
+ def test_alert_should_not_allow_additional_commands_if_dismissed(self):
+ self.driver.find_element_by_css('#alert').click()
+ alert = self.wait.until(lambda x: x.switch_to_alert())
+ alert.accept()
+ with self.assertRaises(exceptions.NoSuchAlertException):
+ alert.get_text()
+
+ # Prompts
+ def test_should_allow_user_to_accept_a_prompt(self):
+ self.driver.find_element_by_css('#prompt').click()
+ alert = self.wait.until(lambda x: x.switch_to_alert())
+ alert.accept()
+ self.wait.until(lambda x: x.find_element_by_css('#text').text == '')
+
+ def test_should_allow_user_to_dismiss_a_prompt(self):
+ self.driver.find_element_by_css('#prompt').click()
+ alert = self.wait.until(lambda x: x.switch_to_alert())
+ alert.dismiss()
+ self.wait.until(lambda x: x.find_element_by_css('#text').text == 'null')
+
+ def test_should_allow_user_to_set_the_value_of_a_prompt(self):
+ self.driver.find_element_by_css('#prompt').click()
+ alert = self.wait.until(lambda x: x.switch_to_alert())
+ alert.send_keys('cheese')
+ alert.accept()
+ self.wait.until(lambda x: x.find_element_by_css('#text').text == 'cheese')
+
+ def test_should_allow_user_to_get_text_of_a_prompt(self):
+ self.driver.find_element_by_css('#prompt').click()
+ alert = self.wait.until(lambda x: x.switch_to_alert())
+ value = alert.get_text()
+ alert.accept()
+ self.assertEquals('Enter something', value)
+
+ def test_prompt_should_not_allow_additional_commands_if_dismissed(self):
+ self.driver.find_element_by_css('#prompt').click()
+ alert = self.wait.until(lambda x: x.switch_to_alert())
+ alert.accept()
+ with self.assertRaises(exceptions.NoSuchAlertException):
+ alert.get_text()
+
+ def test_prompt_should_use_default_value_if_no_keys_sent(self):
+ self.driver.find_element_by_css('#prompt-with-default').click()
+ alert = self.wait.until(lambda x: x.switch_to_alert())
+ alert.accept()
+ self.wait.until(lambda x: x.find_element_by_css('#text').text == 'This is a default value')
+
+ def test_prompt_should_have_null_value_if_dismissed(self):
+ self.driver.find_element_by_css('#prompt-with-default').click()
+ alert = self.wait.until(lambda x: x.switch_to_alert())
+ alert.dismiss()
+ self.wait.until(lambda x: x.find_element_by_css('#text').text == 'null')
+
+ # Confirmations
+ def test_should_allow_user_to_accept_a_confirm(self):
+ self.driver.find_element_by_css('#confirm').click()
+ alert = self.wait.until(lambda x: x.switch_to_alert())
+ alert.accept()
+ self.wait.until(lambda x: x.find_element_by_css('#text').text == 'true')
+
+ def test_should_allow_user_to_dismiss_a_confirm(self):
+ self.driver.find_element_by_css('#confirm').click()
+ alert = self.wait.until(lambda x: x.switch_to_alert())
+ alert.dismiss()
+ self.wait.until(lambda x: x.find_element_by_css('#text').text == 'false')
+
+ def test_setting_the_value_of_a_confirm_throws(self):
+ self.driver.find_element_by_css('#confirm').click()
+ alert = self.wait.until(lambda x: x.switch_to_alert())
+ with self.assertRaises(exceptions.ElementNotVisibleException):
+ alert.send_keys('cheese')
+ alert.accept()
+
+ def test_should_allow_user_to_get_text_of_a_confirm(self):
+ self.driver.find_element_by_css('#confirm').click()
+ alert = self.wait.until(lambda x: x.switch_to_alert())
+ value = alert.get_text()
+ alert.accept()
+ self.assertEquals('cheese', value)
+
+ def test_confirm_should_not_allow_additional_commands_if_dismissed(self):
+ self.driver.find_element_by_css('#confirm').click()
+ alert = self.wait.until(lambda x: x.switch_to_alert())
+ alert.accept()
+ with self.assertRaises(exceptions.NoSuchAlertException):
+ alert.get_text()
+
+ def test_switch_to_missing_alert_fails(self):
+ with self.assertRaises(exceptions.NoSuchAlertException):
+ self.driver.switch_to_alert()
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/wpt/web-platform-tests/webdriver/modal/res/alerts.html b/tests/wpt/web-platform-tests/webdriver/modal/res/alerts.html
new file mode 100644
index 00000000000..36c5dc139f4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/modal/res/alerts.html
@@ -0,0 +1,53 @@
+<html>
+<!-- Padding to account for small screens of mobile devices -->
+<style>
+ p {margin-top:48px;}
+</style>
+<head>
+ <title>Testing Alerts</title>
+
+ <script type="text/javascript">
+ function setInnerText(id, value) {
+ document.getElementById(id).innerHTML = '<p>' + value + '</p>';
+ }
+
+ function displayPrompt() {
+ setInnerText('text', prompt('Enter something'));
+ }
+
+ function displayPromptWithDefault() {
+ setInnerText('text', prompt('Enter something', 'This is a default value'));
+ }
+
+ function displayTwoPrompts() {
+ setInnerText('text1', prompt('First'));
+ setInnerText('text2', prompt('Second'));
+ }
+
+ function displayConfirm() {
+ setInnerText('text', confirm('cheese'));
+ }
+ </script>
+</head>
+<body>
+
+<h1>Testing Alerts and Stuff</h1>
+
+<p>This tests alerts: <a href="#" id="alert" onclick="alert('cheese');">click me</a></p>
+
+<p>This tests alerts: <a href="#" id="empty-alert" onclick="alert('');">click me</a></p>
+
+<p>Let's make the <a href="#" id="prompt" onclick="displayPrompt();">prompt happen</a></p>
+
+<p>Let's make the <a href="#" id="prompt-with-default" onclick="displayPromptWithDefault();">prompt with default happen</a></p>
+
+<p>Let's make TWO <a href="#" id="double-prompt" onclick="displayTwoPrompts();">prompts happen</a></p>
+
+<p>This tests confirm: <a href="#" id="confirm" onclick="displayConfirm();">test confirm</a></p>
+
+<div id="text"></div>
+<div id="text1"></div>
+<div id="text2"></div>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webdriver/navigation/__init__.py b/tests/wpt/web-platform-tests/webdriver/navigation/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/navigation/__init__.py
diff --git a/tests/wpt/web-platform-tests/webdriver/navigation/auth_tests.py b/tests/wpt/web-platform-tests/webdriver/navigation/auth_tests.py
new file mode 100644
index 00000000000..068e44fe9f6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/navigation/auth_tests.py
@@ -0,0 +1,42 @@
+import os
+import sys
+import unittest
+import ConfigParser
+
+sys.path.insert(1, os.path.abspath(os.path.join(__file__, "../..")))
+import base_test
+from webdriver import exceptions
+from wptserve import server
+from wptserve.router import any_method
+from wptserve.handlers import basic_auth_handler
+
+class WebDriverAuthTest(unittest.TestCase):
+
+ # Set up class to start HTTP Server that responds to
+ # test URLs with various 401 responses
+ @classmethod
+ def setUpClass(cls):
+ cls.driver = base_test.create_driver()
+ cls.webserver = server.WebTestHttpd(routes=[(any_method, "*", basic_auth_handler)])
+ cls.webserver.start()
+
+ @classmethod
+ def tearDownClass(cls):
+ cls.driver.quit()
+ cls.webserver.stop()
+
+ # Test that when 401 is seen by browser, a WebDriver response is still sent
+ def test_response_401_auth_basic(self):
+ page = self.webserver.get_url('navigation/res/authenticated.html')
+ self.driver.set_page_load_timeout(5)
+ try:
+ self.driver.get( page )
+ # if we got a responses instead of timeout, that's success
+ self.assertTrue(True)
+ except exceptions.TimeoutException:
+ self.fail("Did not get response from browser.")
+ except:
+ self.fail("Unexpected failure. Please investigate.")
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/wpt/web-platform-tests/webdriver/navigation/forward.py b/tests/wpt/web-platform-tests/webdriver/navigation/forward.py
new file mode 100644
index 00000000000..6cc77c2a458
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/navigation/forward.py
@@ -0,0 +1,24 @@
+import unittest
+import sys
+import os
+
+sys.path.insert(1, os.path.abspath(os.path.join(__file__, "../..")))
+import base_test
+
+
+class ForwardTest(base_test.WebDriverBaseTest):
+ # Get a static page that must be the same upon refresh
+ def test_forward(self):
+ self.driver.get(self.webserver.where_is('navigation/res/forwardStart.html'))
+ self.driver.get(self.webserver.where_is('navigation/res/forwardNext.html'))
+ nextbody = self.driver.find_element_by_css("body").text
+ self.driver.go_back()
+ currbody = self.driver.find_element_by_css("body").text
+ self.assertNotEqual(nextbody, currbody)
+ self.driver.go_forward()
+ currbody = self.driver.find_element_by_css("body").text
+ self.assertEqual(nextbody, currbody)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/wpt/web-platform-tests/webdriver/navigation/forwardToNothing.py b/tests/wpt/web-platform-tests/webdriver/navigation/forwardToNothing.py
new file mode 100644
index 00000000000..057fb9c5828
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/navigation/forwardToNothing.py
@@ -0,0 +1,20 @@
+import os
+import sys
+import unittest
+
+sys.path.insert(1, os.path.abspath(os.path.join(__file__, "../..")))
+import base_test
+
+
+class ForwardToNothingTest(base_test.WebDriverBaseTest):
+ # Get a static page that must be the same upon refresh
+ def test_forwardToNothing(self):
+ self.driver.get(self.webserver.where_is('navigation/forwardStart.html'))
+ body = self.driver.find_element_by_css("body").text
+ self.driver.go_forward()
+ currbody = self.driver.find_element_by_css("body").text
+ self.assertEqual(body, currbody)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/wpt/web-platform-tests/webdriver/navigation/get_from_http_test.py b/tests/wpt/web-platform-tests/webdriver/navigation/get_from_http_test.py
new file mode 100644
index 00000000000..714e65f2b4d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/navigation/get_from_http_test.py
@@ -0,0 +1,60 @@
+import os
+import sys
+import unittest
+
+sys.path.insert(1, os.path.abspath(os.path.join(__file__, "../..")))
+import base_test
+
+
+class GetFromHttpTest(base_test.WebDriverBaseTest):
+ def testGetUrlWithNoRedirectionOverHttp(self):
+ page = self.webserver.where_is('navigation/res/empty.html')
+ self.driver.get(page)
+ url = self.driver.get_current_url()
+ self.assertEquals(page, url)
+
+
+ def testGetWillFollowTheLocationHeader(self):
+ page = self.webserver.where_is('navigation/redirect')
+ self.driver.get(page)
+ expected = self.webserver.where_is('navigation/res/empty.html')
+ url = self.driver.get_current_url()
+ self.assertEquals(expected, url)
+
+
+ def testGetWillFollowMetaRefreshThatRefreshesInstantly(self):
+ page = self.webserver.where_is('navigation/res/instant-meta-redirect.html')
+ self.driver.get(page)
+ expected = self.webserver.where_is('navigation/res/empty.html')
+ url = self.driver.get_current_url()
+ self.assertEquals(expected, url)
+
+
+ def testGetWillFollowMetaRefreshThatRefreshesAfterOneSecond(self):
+ page = self.webserver.where_is('navigation/res/1s-meta-redirect.html')
+ self.driver.get(page)
+ expected = self.webserver.where_is('navigation/res/empty.html')
+ url = self.driver.get_current_url()
+ self.assertEquals(expected, url)
+
+
+ def testGetWillNotFollowMetaRefreshThatRefreshesAfterMoreThanOneSecond(self):
+ page = self.webserver.where_is('navigation/res/60s-meta-redirect.html')
+ self.driver.get(page)
+ url = self.driver.get_current_url()
+ self.assertEquals(page, url)
+
+
+ def testGetFragmentInCurrentDocumentDoesNotReloadPage(self):
+ page = self.webserver.where_is("navigation/res/fragment.html")
+ fragment_page = "%s#%s" % (page, "fragment")
+
+ self.driver.get(page)
+ self.driver.execute_script("state = true")
+
+ self.driver.get(fragment_page)
+ self.assertEquals(True, self.driver.execute_script("return state"))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/wpt/web-platform-tests/webdriver/navigation/invalid_cert_test.py b/tests/wpt/web-platform-tests/webdriver/navigation/invalid_cert_test.py
new file mode 100644
index 00000000000..5f84827966d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/navigation/invalid_cert_test.py
@@ -0,0 +1,28 @@
+import BaseHTTPServer
+import os
+import ssl
+import sys
+import unittest
+
+sys.path.insert(1, os.path.abspath(os.path.join(__file__, "../..")))
+import base_test
+
+
+here = os.path.dirname(os.path.abspath(__file__))
+
+
+class InvalidCertTest(base_test.WebDriverBaseTest):
+ def testCanNavigateToSiteWithSelfSignedCert(self):
+ self.webserver.httpd.socket = ssl.wrap_socket(
+ self.webserver.httpd.socket,
+ certfile=os.path.join(here, 'res/self-signed.key'),
+ server_side=True)
+ expected = self.webserver.where_is(
+ 'navigation/res/empty.html').replace('http:', 'https:', 1)
+
+ self.driver.get(expected)
+ self.assertEquals(expected, self.driver.get_current_url())
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/wpt/web-platform-tests/webdriver/navigation/refresh-page.py b/tests/wpt/web-platform-tests/webdriver/navigation/refresh-page.py
new file mode 100644
index 00000000000..b0638e56893
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/navigation/refresh-page.py
@@ -0,0 +1,27 @@
+import os
+import sys
+import unittest
+
+sys.path.insert(1, os.path.abspath(os.path.join(__file__, "../..")))
+import base_test
+
+
+class RefreshPageTest(base_test.WebDriverBaseTest):
+ # Get a static page that must be the same upon refresh
+ def test_refreshPage(self):
+ self.driver.get(self.webserver.where_is('navigation/res/refreshPageStatic.html'))
+ body = self.driver.find_element_by_css("body").text
+ self.driver.execute_script("document.getElementById('body').innerHTML=''")
+ self.driver.refresh()
+ newbody = self.driver.find_element_by_css("body").text
+ self.assertEqual(body, newbody)
+
+ self.driver.get(self.webserver.where_is('navigation/res/refreshPageDynamic.html'))
+ body = self.driver.find_element_by_css("body").text
+ self.driver.refresh()
+ newbody = self.driver.find_element_by_css("body").text
+ self.assertNotEqual(body, newbody)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/wpt/web-platform-tests/webdriver/navigation/res/1s-meta-redirect.html b/tests/wpt/web-platform-tests/webdriver/navigation/res/1s-meta-redirect.html
new file mode 100644
index 00000000000..44fd332bd26
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/navigation/res/1s-meta-redirect.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<meta http-equiv="Refresh" content="1; URL=empty.html">
+<title>meta-redirect</title>
diff --git a/tests/wpt/web-platform-tests/webdriver/navigation/res/60s-meta-redirect.html b/tests/wpt/web-platform-tests/webdriver/navigation/res/60s-meta-redirect.html
new file mode 100644
index 00000000000..9e56bc96aa7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/navigation/res/60s-meta-redirect.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<meta http-equiv="Refresh" content="60; URL=empty.html">
+<title>meta-redirect</title>
diff --git a/tests/wpt/web-platform-tests/webdriver/navigation/res/authenticated.html b/tests/wpt/web-platform-tests/webdriver/navigation/res/authenticated.html
new file mode 100644
index 00000000000..c7744934486
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/navigation/res/authenticated.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+
+<title>authentication successful</title>
+<h1>You're in!</h1> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/webdriver/navigation/res/empty.html b/tests/wpt/web-platform-tests/webdriver/navigation/res/empty.html
new file mode 100644
index 00000000000..da58ac21d00
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/navigation/res/empty.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+
+<title>Cheese</title>
diff --git a/tests/wpt/web-platform-tests/webdriver/navigation/res/forwardNext.html b/tests/wpt/web-platform-tests/webdriver/navigation/res/forwardNext.html
new file mode 100644
index 00000000000..edd77f8667c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/navigation/res/forwardNext.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<body id=body>
+This is the next page.
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/webdriver/navigation/res/forwardStart.html b/tests/wpt/web-platform-tests/webdriver/navigation/res/forwardStart.html
new file mode 100644
index 00000000000..3ab4f3cddf0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/navigation/res/forwardStart.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<body>
+This is the start page.
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/webdriver/navigation/res/fragment.html b/tests/wpt/web-platform-tests/webdriver/navigation/res/fragment.html
new file mode 100644
index 00000000000..bd09434a6f8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/navigation/res/fragment.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>Fragment</title>
+
+<script>
+ var state = false;
+</script>
+
+<p id="fragment">I wish I were a pea, alas I am only a fragment.</p> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/webdriver/navigation/res/instant-meta-redirect.html b/tests/wpt/web-platform-tests/webdriver/navigation/res/instant-meta-redirect.html
new file mode 100644
index 00000000000..c6ad7c9f2fe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/navigation/res/instant-meta-redirect.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<meta http-equiv="Refresh" content="0; URL=empty.html">
+<title>meta-redirect</title>
diff --git a/tests/wpt/web-platform-tests/webdriver/navigation/res/refreshPageDynamic.html b/tests/wpt/web-platform-tests/webdriver/navigation/res/refreshPageDynamic.html
new file mode 100644
index 00000000000..bedd20c3565
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/navigation/res/refreshPageDynamic.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<body id="body">
+This is a dynamic page. It will always have different content if refreshed.
+<div id="dynamic"></div>
+</body>
+</html>
+<script>
+document.getElementById('dynamic').innerHTML = Math.random();
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/webdriver/navigation/res/refreshPageStatic.html b/tests/wpt/web-platform-tests/webdriver/navigation/res/refreshPageStatic.html
new file mode 100644
index 00000000000..7d339aa9db9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/navigation/res/refreshPageStatic.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<body id="body">
+This is a static page. It will always have the same content if refreshed.
+</body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/webdriver/navigation/res/self-signed.key b/tests/wpt/web-platform-tests/webdriver/navigation/res/self-signed.key
new file mode 100644
index 00000000000..bca61cdf76d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/navigation/res/self-signed.key
@@ -0,0 +1,28 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXAIBAAKBgQDoww50sF8aKYNe1owbtsEilK2KOZx2F1Iv+EElpO7N2hDarIBu
+9f87H+03b5RpI9oCSFCo67wTdCJ0A4B8SLwV2SUZY78CGJB1A8kXqP04tz0S0SYD
+2TQRliwTxx1r7pDv1VmLc7XZRE6n6FFKTEjKmdUhCwHuQfC1sOkCXqSzFQIDAQAB
+AoGAS5XcAeSsXXCRqqB9SxqjyTkCydo/htG37L/vV+whaFOiGYDfDClyQp7xh4kC
+Zsovp4IYP2Kd5qtV7NqeRL3R5Z/Dxf6+6G4HdbI7np5m7A7cU32hMIzxi5M55Lo6
+gveNgHb3uy+R+tZTyab6saUxFy1DqbMh/2ga4lbatRm7JdkCQQD9C8+Q3nN8FkH4
+sKbOnHsKEV27459EYz7WnENiwhcYByBt7vw9BPM/LrO4UzWtgNjtRtxBpFeVT/V+
+dF7OZuH/AkEA63qhJcs6Ru3G29R3kJ82ttyHU1INawB/7od3bKp3rE+jUwNG7ZbQ
+mtRdPTI02/OOeqZKeo46JX3D57gfMRDC6wJABZk/TGs/jt1HNGNkLWoU5tIfisqs
+eWzgtQrcCtFUhXmS5BvHhOoZH6q+2zMsGtyg8A8DTIiAT5NnURbuCg8IrQJAd3kh
+d85zw/byFSjofPz6wq6DDngsDKUVQ42BvyWCUG+bewvHmdYSAuxKXjkx7oLVQE9M
+rH+q6sizc8bMNJW/fwJBAPcobQ59ZGAEWrnDdtbWnNS1ieSV8p6u7sg20HvrUIPS
+TIQXeems9IKu0xs0dnLXNucm4ur8MnE7snkvWZnx2C8=
+-----END RSA PRIVATE KEY-----
+-----BEGIN CERTIFICATE-----
+MIICAzCCAWwCCQCc6Lx6zkc0BDANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJV
+UzETMBEGA1UECAwKQ2FsaWZvcm5pYTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0
+cyBQdHkgTHRkMCAXDTEzMDcxMjIyMzMxNVoYDzIyODcwNDI2MjIzMzE1WjBFMQsw
+CQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEhMB8GA1UECgwYSW50ZXJu
+ZXQgV2lkZ2l0cyBQdHkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDo
+ww50sF8aKYNe1owbtsEilK2KOZx2F1Iv+EElpO7N2hDarIBu9f87H+03b5RpI9oC
+SFCo67wTdCJ0A4B8SLwV2SUZY78CGJB1A8kXqP04tz0S0SYD2TQRliwTxx1r7pDv
+1VmLc7XZRE6n6FFKTEjKmdUhCwHuQfC1sOkCXqSzFQIDAQABMA0GCSqGSIb3DQEB
+BQUAA4GBAD6atn+xbACigA9+EmcZo2bpAzxLAuXOAVEBM6J7Nrd8pk1D3PRP0QPg
+UxjIDQ7ZqEWwLAcKb6AIfWwJ2Wj7q5LSX5nEFnUXggpywfUNTuZaR/fquUVnhMaO
+tF8fQB9AYSa1WjqUbIKlns3Z2RhUv2DSEifi6UNjsf2UpmDTxtkN
+-----END CERTIFICATE-----
diff --git a/tests/wpt/web-platform-tests/webdriver/network.py b/tests/wpt/web-platform-tests/webdriver/network.py
new file mode 100644
index 00000000000..0674b989de3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/network.py
@@ -0,0 +1,30 @@
+# this comes from this stack overflow post:
+# http://stackoverflow.com/a/1947766/725944
+
+# module for getting the lan ip address of the computer
+
+import os
+import socket
+
+if os.name != "nt":
+ import fcntl
+ import struct
+ def get_interface_ip(ifname):
+ sckt = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+ return socket.inet_ntoa(fcntl.ioctl(
+ sckt.fileno(),
+ 0x8915, # SIOCGIFADDR
+ struct.pack('256s', ifname[:15])
+ )[20:24])
+
+def get_lan_ip():
+ ip = socket.gethostbyname(socket.gethostname())
+ if ip.startswith("127.") and os.name != "nt":
+ interfaces = ["eth0","eth1","eth2","wlan0","wlan1","wifi0","ath0","ath1","ppp0"]
+ for ifname in interfaces:
+ try:
+ ip = get_interface_ip(ifname)
+ break
+ except IOError:
+ pass
+ return ip
diff --git a/tests/wpt/web-platform-tests/webdriver/runtests.py b/tests/wpt/web-platform-tests/webdriver/runtests.py
new file mode 100644
index 00000000000..1cd9a3836bb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/runtests.py
@@ -0,0 +1,14 @@
+import unittest
+
+from unittest import TestLoader, TextTestRunner, TestSuite
+
+if __name__ == "__main__":
+
+ loader = TestLoader()
+ suite = TestSuite((
+ loader.discover(".", pattern="*.py")
+ ))
+
+ runner = TextTestRunner(verbosity=2)
+ runner.run(suite)
+ unittest.main()
diff --git a/tests/wpt/web-platform-tests/webdriver/timeouts/__init__.py b/tests/wpt/web-platform-tests/webdriver/timeouts/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/timeouts/__init__.py
diff --git a/tests/wpt/web-platform-tests/webdriver/timeouts/implicit_waits_tests.py b/tests/wpt/web-platform-tests/webdriver/timeouts/implicit_waits_tests.py
new file mode 100644
index 00000000000..e39723c50c1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/timeouts/implicit_waits_tests.py
@@ -0,0 +1,64 @@
+import os
+import sys
+import unittest
+
+sys.path.insert(1, os.path.abspath(os.path.join(__file__, "../..")))
+import base_test
+from webdriver import exceptions
+
+
+class ImplicitWaitsTests(base_test.WebDriverBaseTest):
+ def setUp(self):
+ self.driver.get(self.webserver.where_is('timeouts/res/implicit_waits_tests.html'))
+
+ def test_find_element_by_id(self):
+ add = self.driver.find_element_by_css("#adder")
+ self.driver.set_implicit_timeout(3)
+ add.click()
+ self.driver.find_element_by_css("#box0") # All is well if this doesn't throw.
+
+ def test_should_still_fail_to_find_an_element_when_implicit_waits_are_enabled(self):
+ self.driver.set_implicit_timeout(0.5)
+ try:
+ self.driver.find_element_by_css("#box0")
+ self.fail("Expected NoSuchElementException to have been thrown")
+ except exceptions.NoSuchElementException as e:
+ pass
+ except Exception as e:
+ self.fail("Expected NoSuchElementException but got " + str(e))
+
+ def test_should_return_after_first_attempt_to_find_one_after_disabling_implicit_waits(self):
+ self.driver.set_implicit_timeout(3)
+ self.driver.set_implicit_timeout(0)
+ try:
+ self.driver.find_element_by_css("#box0")
+ self.fail("Expected NoSuchElementException to have been thrown")
+ except exceptions.NoSuchElementException as e:
+ pass
+ except Exception as e:
+ self.fail("Expected NoSuchElementException but got " + str(e))
+
+ def test_should_implicitly_wait_until_at_least_one_element_is_found_when_searching_for_many(self):
+ add = self.driver.find_element_by_css("#adder")
+ self.driver.set_implicit_timeout(2)
+ add.click()
+ add.click()
+ elements = self.driver.find_elements_by_css(".redbox")
+ self.assertTrue(len(elements) >= 1)
+
+ def test_should_still_fail_to_find_an_element_by_class_when_implicit_waits_are_enabled(self):
+ self.driver.set_implicit_timeout(0.5)
+ elements = self.driver.find_elements_by_css(".redbox")
+ self.assertEqual(0, len(elements))
+
+ def test_should_return_after_first_attempt_to_find_many_after_disabling_implicit_waits(self):
+ add = self.driver.find_element_by_css("#adder")
+ self.driver.set_implicit_timeout(1.1)
+ self.driver.set_implicit_timeout(0)
+ add.click()
+ elements = self.driver.find_elements_by_css(".redbox")
+ self.assertEqual(0, len(elements))
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/wpt/web-platform-tests/webdriver/timeouts/page_load_timeouts_tests.py b/tests/wpt/web-platform-tests/webdriver/timeouts/page_load_timeouts_tests.py
new file mode 100644
index 00000000000..6d8693f6c2e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/timeouts/page_load_timeouts_tests.py
@@ -0,0 +1,26 @@
+import os
+import sys
+import unittest
+
+sys.path.insert(1, os.path.abspath(os.path.join(__file__, "../..")))
+import base_test
+from webdriver import exceptions
+
+
+class PageLoadTimeoutTest(base_test.WebDriverBaseTest):
+ def test_should_timeout_on_page_load_taking_too_long(self):
+ self.driver.set_page_load_timeout(0.01)
+ with self.assertRaises(exceptions.TimeoutException):
+ self.load_page()
+
+ def test_should_not_timeout_on_page_load(self):
+ self.driver.set_page_load_timeout(30)
+ self.load_page()
+ pass
+
+ def load_page(self):
+ self.driver.get(self.webserver.where_is('timeouts/res/page_load_timeouts_tests.html'))
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/wpt/web-platform-tests/webdriver/timeouts/res/implicit_waits_tests.html b/tests/wpt/web-platform-tests/webdriver/timeouts/res/implicit_waits_tests.html
new file mode 100644
index 00000000000..ce39877fac7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/timeouts/res/implicit_waits_tests.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title></title>
+ <script type="text/javascript">
+ var next = 0;
+
+ function addMore() {
+ var box = document.createElement('DIV');
+ box.id = 'box' + next++;
+ box.className = 'redbox';
+ box.style.width = '150px';
+ box.style.height = '150px';
+ box.style.backgroundColor = 'red';
+ box.style.border = '1px solid black';
+ box.style.margin = '5px';
+
+ window.setTimeout(function() {
+ document.body.appendChild(box);
+ }, 1000);
+ }
+
+ function reveal() {
+ var elem = document.getElementById('revealed');
+ window.setTimeout(function() {
+ elem.style.display = '';
+ }, 1000);
+ }
+ </script>
+ </head>
+ <body>
+ <input id="adder" type="button" value="Add a box!" onclick="addMore()"/>
+
+ <input id="reveal" type="button" value="Reveal a new input" onclick="reveal();" />
+
+ <input id="revealed" style="display:none;" />
+ </body>
+</html> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/webdriver/timeouts/res/page_load_timeouts_tests.html b/tests/wpt/web-platform-tests/webdriver/timeouts/res/page_load_timeouts_tests.html
new file mode 100644
index 00000000000..555e19b70ef
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/timeouts/res/page_load_timeouts_tests.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Hello WebDriver</title>
+</head>
+<body>
+ <h1>Page Load Timeouts Test</h1>
+ <div>
+ Say Cheese
+ </div>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webdriver/user_input/__init__.py b/tests/wpt/web-platform-tests/webdriver/user_input/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/user_input/__init__.py
diff --git a/tests/wpt/web-platform-tests/webdriver/user_input/clear_test.py b/tests/wpt/web-platform-tests/webdriver/user_input/clear_test.py
new file mode 100644
index 00000000000..5375725128b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/user_input/clear_test.py
@@ -0,0 +1,53 @@
+# -*- mode: python; fill-column: 100; comment-column: 100; -*-
+
+import os
+import sys
+import unittest
+
+sys.path.insert(1, os.path.abspath(os.path.join(__file__, "../..")))
+import base_test
+from webdriver import exceptions
+
+
+class ElementClearTest(base_test.WebDriverBaseTest):
+ def test_writable_text_input_element_should_clear(self):
+ self.driver.get(self.webserver.where_is("user_input/res/element_clear_writable_input_page.html"))
+ e = self.driver.find_element_by_css("#writableTextInput")
+ e.clear()
+ self.assertEquals("", e.get_attribute("value"))
+
+ def test_disabled_text_input_element_should_not_clear(self):
+ self.driver.get(self.webserver.where_is("user_input/res/element_clear_disabled_input_page.html"))
+ e = self.driver.find_element_by_css("#disabledTextInput")
+ self.assertRaises(exceptions.InvalidElementStateException, lambda: e.clear())
+
+ def test_read_only_text_input_element_should_not_clear(self):
+ self.driver.get(self.webserver.where_is("user_input/res/element_clear_readonly_input_page.html"))
+ e = self.driver.find_element_by_css("#readOnlyTextInput")
+ self.assertRaises(exceptions.InvalidElementStateException, lambda: e.clear())
+
+ def test_writable_text_area_element_should_clear(self):
+ self.driver.get(self.webserver.where_is("user_input/res/element_clear_writable_textarea_page.html"))
+ e = self.driver.find_element_by_css("#writableTextArea")
+ e.clear()
+ self.assertEquals("", e.get_attribute("value"))
+
+ def test_disabled_text_area_element_should_not_clear(self):
+ self.driver.get(self.webserver.where_is("user_input/res/element_clear_disabled_textarea_page.html"))
+ e = self.driver.find_element_by_css("#disabledTextArea")
+ self.assertRaises(exceptions.InvalidElementStateException, lambda: e.clear())
+
+ def test_read_only_text_input_element_should_not_clear(self):
+ self.driver.get(self.webserver.where_is("user_input/res/element_clear_readonly_textarea_page.html"))
+ e = self.driver.find_element_by_css("#readOnlyTextArea")
+ self.assertRaises(exceptions.InvalidElementStateException, lambda: e.clear())
+
+ def test_content_editable_area_should_clear(self):
+ self.driver.get(self.webserver.where_is("user_input/res/element_clear_contenteditable_page.html"))
+ e = self.driver.find_element_by_css("#contentEditableElement")
+ e.clear()
+ self.assertEquals("", e.text)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/wpt/web-platform-tests/webdriver/user_input/res/element_clear_contenteditable_page.html b/tests/wpt/web-platform-tests/webdriver/user_input/res/element_clear_contenteditable_page.html
new file mode 100644
index 00000000000..2d65d3880f5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/user_input/res/element_clear_contenteditable_page.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Clear Elements Test</title>
+<meta charset=utf-8>
+</head>
+<body>
+<div id="contentEditableElement" contentEditable="true">
+This is a contentEditable area
+</div>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/webdriver/user_input/res/element_clear_disabled_input_page.html b/tests/wpt/web-platform-tests/webdriver/user_input/res/element_clear_disabled_input_page.html
new file mode 100644
index 00000000000..b0f21235f3a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/user_input/res/element_clear_disabled_input_page.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Clear Elements Test</title>
+<meta charset=utf-8>
+</head>
+<body>
+<input id="disabledTextInput" type="text" disabled="true" value="Test"/>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/webdriver/user_input/res/element_clear_disabled_textarea_page.html b/tests/wpt/web-platform-tests/webdriver/user_input/res/element_clear_disabled_textarea_page.html
new file mode 100644
index 00000000000..e274a05828d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/user_input/res/element_clear_disabled_textarea_page.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Clear Elements Test</title>
+<meta charset=utf-8>
+</head>
+<body>
+<textarea rows="5" id="disabledTextArea" disabled="true" cols="20">
+text area which is not supposed to be cleared
+</textarea>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/webdriver/user_input/res/element_clear_readonly_input_page.html b/tests/wpt/web-platform-tests/webdriver/user_input/res/element_clear_readonly_input_page.html
new file mode 100644
index 00000000000..5d3a7ac67c3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/user_input/res/element_clear_readonly_input_page.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Clear Elements Test</title>
+<meta charset=utf-8>
+</head>
+<body>
+<input id="readOnlyTextInput" type="text" readonly value="Test"/>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/webdriver/user_input/res/element_clear_readonly_textarea_page.html b/tests/wpt/web-platform-tests/webdriver/user_input/res/element_clear_readonly_textarea_page.html
new file mode 100644
index 00000000000..d11241e86e9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/user_input/res/element_clear_readonly_textarea_page.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Clear Elements Test</title>
+<meta charset=utf-8>
+</head>
+<body>
+<textarea id="readOnlyTextArea" readonly rows="5" cols="20">
+text area which is not supposed to be cleared
+</textarea>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/webdriver/user_input/res/element_clear_writable_input_page.html b/tests/wpt/web-platform-tests/webdriver/user_input/res/element_clear_writable_input_page.html
new file mode 100644
index 00000000000..448cd37df95
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/user_input/res/element_clear_writable_input_page.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Clear Elements Test</title>
+<meta charset=utf-8>
+</head>
+<body>
+<input id="writableTextInput" type="text" value="Test"/>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/webdriver/user_input/res/element_clear_writable_textarea_page.html b/tests/wpt/web-platform-tests/webdriver/user_input/res/element_clear_writable_textarea_page.html
new file mode 100644
index 00000000000..d16657aa5e3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/user_input/res/element_clear_writable_textarea_page.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Clear Elements Test</title>
+<meta charset=utf-8>
+</head>
+<body>
+<textarea id="writableTextArea" rows="2" cols="20">
+This is a sample text area which is supposed to be cleared
+</textarea>
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/webdriver/webdriver.cfg b/tests/wpt/web-platform-tests/webdriver/webdriver.cfg
new file mode 100644
index 00000000000..98ecde7bd7c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webdriver/webdriver.cfg
@@ -0,0 +1,31 @@
+# to add more browsers specify a [section header] with the name
+# the 'browser' is currently required
+# url and capabilities are optional
+# url is the 'command_executor' argument passed in to the 'browser' class
+# capabilities is the 'desired_capabilities' argument.
+
+[firefox]
+capabilities: {"browserName": "firefox"}
+mode: compatibility
+
+[selendroid]
+capabilities: {"platform": "ANDROID", "browserName": "android"}
+mode: compatibility
+
+[chrome]
+url: http://localhost:9515
+capabilities: {"browserName": "chrome"}
+mode: compatibility
+
+[ie]
+capabilities: {"browserName": "ie"}
+mode: compatibility
+
+[ios-driver]
+capabilities: {"browserName": "iphone"}
+mode: compatibility
+
+[blackberry]
+url: http://169.254.0.1:1338
+capabilities: {"browserName": "blackberry"}
+mode: compatibility
diff --git a/tests/wpt/web-platform-tests/webgl/bufferSubData.html b/tests/wpt/web-platform-tests/webgl/bufferSubData.html
new file mode 100644
index 00000000000..a97df9062d6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webgl/bufferSubData.html
@@ -0,0 +1,26 @@
+<!doctype html>
+<title>bufferSubData</title>
+<link rel=author href=mailto:Ms2ger@gmail.com title=Ms2ger>
+<link rel=help href=https://www.khronos.org/registry/webgl/specs/latest/#5.14.5>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=common.js></script>
+
+<div id=log></div>
+<script>
+test(function() {
+ var gl = getGl();
+ assert_equals(gl.getError(), WebGLRenderingContext.NO_ERROR);
+
+ var b = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, b);
+
+ var a = new Float32Array(1);
+ gl.bufferData(gl.ARRAY_BUFFER, a, gl.STATIC_DRAW);
+
+ var nan = 0 / 0;
+ gl.bufferSubData(gl.ARRAY_BUFFER, nan, a);
+
+ assert_equals(gl.getError(), WebGLRenderingContext.NO_ERROR);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/webgl/common.js b/tests/wpt/web-platform-tests/webgl/common.js
new file mode 100644
index 00000000000..416c21ce933
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webgl/common.js
@@ -0,0 +1,13 @@
+function getGl() {
+ var c = document.createElement("canvas");
+ var gl = c.getContext("experimental-webgl");
+ assert_true(!!gl, "Should be able to get a context.");
+ return gl;
+}
+
+function shouldGenerateGLError(cx, glError, fn) {
+ test(function() {
+ fn();
+ assert_equals(cx.getError(), glError);
+ }, "Calling " + fn + " should generate a " + glError + " error.");
+}
diff --git a/tests/wpt/web-platform-tests/webgl/compressedTexImage2D.html b/tests/wpt/web-platform-tests/webgl/compressedTexImage2D.html
new file mode 100644
index 00000000000..b0a031add0b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webgl/compressedTexImage2D.html
@@ -0,0 +1,30 @@
+<!doctype html>
+<title>compressedTexImage2D</title>
+<link rel=author href=mailto:Ms2ger@gmail.com title=Ms2ger>
+<link rel=help href=https://www.khronos.org/registry/webgl/specs/latest/#5.14.8>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=common.js></script>
+
+<div id=log></div>
+<script>
+test(function() {
+ var COMPRESSED_RGB_S3TC_DXT1_EXT = 0x83F0;
+ var gl = getGl();
+
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+
+ shouldGenerateGLError(gl, gl.INVALID_ENUM, function() {
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0, new Uint8Array(8));
+ });
+ shouldGenerateGLError(gl, gl.INVALID_ENUM, function() {
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0, new Uint8Array(8), null);
+ });
+ test(function() {
+ assert_throws(new TypeError(), function() {
+ gl.compressedTexImage2D(gl.TEXTURE_2D, 0, COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 0);
+ });
+ }, "Should throw a TypeError when passing too few arguments.");
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/webgl/compressedTexSubImage2D.html b/tests/wpt/web-platform-tests/webgl/compressedTexSubImage2D.html
new file mode 100644
index 00000000000..539f9e17f8a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webgl/compressedTexSubImage2D.html
@@ -0,0 +1,30 @@
+<!doctype html>
+<title>compressedTexSubImage2D</title>
+<link rel=author href=mailto:Ms2ger@gmail.com title=Ms2ger>
+<link rel=help href=https://www.khronos.org/registry/webgl/specs/latest/#5.14.8>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=common.js></script>
+
+<div id=log></div>
+<script>
+test(function() {
+ var COMPRESSED_RGB_S3TC_DXT1_EXT = 0x83F0;
+ var gl = getGl();
+
+ var tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+
+ shouldGenerateGLError(gl, gl.INVALID_ENUM, function() {
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 10, 10, COMPRESSED_RGB_S3TC_DXT1_EXT, new Uint8Array(8));
+ });
+ shouldGenerateGLError(gl, gl.INVALID_ENUM, function() {
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 10, 10, COMPRESSED_RGB_S3TC_DXT1_EXT, new Uint8Array(8), null);
+ });
+ test(function() {
+ assert_throws(new TypeError(), function() {
+ gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 10, 10, COMPRESSED_RGB_S3TC_DXT1_EXT);
+ });
+ }, "Should throw a TypeError when passing too few arguments.");
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/webgl/texImage2D.html b/tests/wpt/web-platform-tests/webgl/texImage2D.html
new file mode 100644
index 00000000000..2f769160dfd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webgl/texImage2D.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<title>texImage2D</title>
+<link rel=author href=mailto:Ms2ger@gmail.com title=Ms2ger>
+<link rel=help href=https://www.khronos.org/registry/webgl/specs/latest/#5.14.8>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=common.js></script>
+
+<div id=log></div>
+<script>
+test(function() {
+ var gl = getGl();
+ assert_throws(new TypeError(), function() {
+ gl.texImage2D(0, 0, 0, 0, 0, window);
+ });
+ assert_throws(new TypeError(), function() {
+ gl.texImage2D(0, 0, 0, 0, 0, { get width() { throw 7 }, get height() { throw 7 }, data: new Uint8ClampedArray(10) });
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/webgl/texSubImage2D.html b/tests/wpt/web-platform-tests/webgl/texSubImage2D.html
new file mode 100644
index 00000000000..294b30c7607
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webgl/texSubImage2D.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<title>texSubImage2D</title>
+<link rel=author href=mailto:Ms2ger@gmail.com title=Ms2ger>
+<link rel=help href=https://www.khronos.org/registry/webgl/specs/latest/#5.14.8>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=common.js></script>
+
+<div id=log></div>
+<script>
+test(function() {
+ var gl = getGl();
+ assert_throws(new TypeError(), function() {
+ gl.texSubImage2D(0, 0, 0, 0, 0, 0, window);
+ });
+ assert_throws(new TypeError(), function() {
+ gl.texSubImage2D(0, 0, 0, 0, 0, 0, { get width() { throw 7 }, get height() { throw 7 }, data: new Uint8ClampedArray(10) });
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/webgl/uniformMatrixNfv.html b/tests/wpt/web-platform-tests/webgl/uniformMatrixNfv.html
new file mode 100644
index 00000000000..f75cbcb9972
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webgl/uniformMatrixNfv.html
@@ -0,0 +1,33 @@
+<!doctype html>
+<title>uniformMatrix*fv</title>
+<link rel=author href=mailto:Ms2ger@gmail.com title=Ms2ger>
+<link rel=help href=https://www.khronos.org/registry/webgl/specs/latest/#WebGLRenderingContext>
+<link rel=help href=http://dev.w3.org/2006/webapi/WebIDL/#es-boolean>
+<link rel=help href=http://es5.github.com/#x9.2>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=common.js></script>
+
+<div id=log></div>
+<script id="vshader" type="x-shader/x-vertex">
+uniform mat2 m2;
+uniform mat3 m3;
+uniform mat4 m4;
+</script>
+<script>
+var floatArray = function(n) {
+ var a = [];
+ for (var i = 0; i < n; ++i) {
+ a.push(1);
+ }
+ return a;
+};
+[2, 3, 4].forEach(function(n) {
+ test(function() {
+ var gl = getGl();
+ var f = "uniformMatrix" + n + "fv";
+ var loc = gl.getUniformLocation(gl.createProgram(), "m" + n);
+ gl[f](loc, { valueOf: function() { throw "Error"; } }, floatArray(n));
+ }, "Should not throw for " + n);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/webmessaging/Channel_MessagePort_initial_disabled.htm b/tests/wpt/web-platform-tests/webmessaging/Channel_MessagePort_initial_disabled.htm
new file mode 100644
index 00000000000..2a91aecbd53
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/Channel_MessagePort_initial_disabled.htm
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title> MessageChannel: port message queue is initially disabled </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id=log></div>
+<script>
+
+ var TestResult = true;
+
+ var t = async_test("Test Description: A port message queue can be enabled or disabled, and is initially disabled.");
+
+ var channel = new MessageChannel();
+
+ channel.port2.addEventListener("message", TestMessageEvent, true);
+
+ channel.port1.postMessage("ping");
+
+ setTimeout(t.step_func(VerifyResult), 100);
+
+ function TestMessageEvent(evt)
+ {
+ TestResult = false;
+ }
+
+ function VerifyResult()
+ {
+ assert_true(TestResult, "Port message queue is initially disabled?");
+ t.done();
+ }
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webmessaging/Channel_MessagePort_onmessage_start.htm b/tests/wpt/web-platform-tests/webmessaging/Channel_MessagePort_onmessage_start.htm
new file mode 100644
index 00000000000..a1c0ed82de1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/Channel_MessagePort_onmessage_start.htm
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title> MessageChannel: port.onmessage enables message queue </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id=log></div>
+<script>
+
+ var TestResult = false;
+ var description = "The first time a MessagePort object's onmessage IDL attribute is set, the port's "
+ + "port message queue must be enabled, as if the start() method had been called.";
+
+ var t = async_test("Test Description: " + description);
+
+ var channel = new MessageChannel();
+
+ channel.port2.onmessage = TestMessageEvent;
+
+ channel.port1.postMessage("ping");
+
+ setTimeout(t.step_func(VerifyResult), 100);
+
+ function TestMessageEvent(evt)
+ {
+ TestResult = true;
+ }
+
+ function VerifyResult()
+ {
+ assert_true(TestResult, "Port message queue is enabled?");
+ t.done();
+ }
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webmessaging/Channel_postMessage_DataCloneErr.htm b/tests/wpt/web-platform-tests/webmessaging/Channel_postMessage_DataCloneErr.htm
new file mode 100644
index 00000000000..9f4cd6b9be7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/Channel_postMessage_DataCloneErr.htm
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title> postMessage() with a host object raises DataCloneError </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id=log></div>
+<script>
+
+ var description = "Throw a DataCloneError when a host object (e.g. a DOM node) is used with postMessage.";
+
+ test(function()
+ {
+ var channel = new MessageChannel();
+ channel.port1.start();
+
+ assert_throws("DATA_CLONE_ERR", function()
+ {
+ channel.port1.postMessage(navigator);
+ });
+ }, description);
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webmessaging/Channel_postMessage_clone_port.htm b/tests/wpt/web-platform-tests/webmessaging/Channel_postMessage_clone_port.htm
new file mode 100644
index 00000000000..0e2e2fcd141
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/Channel_postMessage_clone_port.htm
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title> postMessage(): clone a port </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id=log></div>
+<script>
+ var OriginalPort = null;
+ var ClonedPort = null;
+ var description = "Test Description: When the user agent is to clone a port original port, with "
+ + "the clone being owned by owner, it must return a new MessagePort object";
+
+ var t = async_test("Test Description: " + description);
+
+ var ChannelA = new MessageChannel();
+ var ChannelB = new MessageChannel();
+ OriginalPort = ChannelB.port2;
+
+ ChannelA.port2.onmessage = t.step_func(function(evt)
+ {
+ if(evt.data == "ports")
+ {
+ ClonedPort = evt.ports[0];
+
+ assert_not_equals(ClonedPort, OriginalPort, "new cloned port object should not equal to the original port!");
+
+ ClonedPort.onmessage = function(e)
+ {
+ test(function(){ assert_equals(e.data, "ping"); }, "Data sent through remote port is received by the new cloned port");
+ t.done();
+ }
+ }
+ });
+
+ ChannelA.port1.postMessage("ports", [OriginalPort]);
+ ChannelB.port1.postMessage("ping");
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webmessaging/Channel_postMessage_clone_port_error.htm b/tests/wpt/web-platform-tests/webmessaging/Channel_postMessage_clone_port_error.htm
new file mode 100644
index 00000000000..c33feaa5f09
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/Channel_postMessage_clone_port_error.htm
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title> postMessage() DataCloneError: cloning source port </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id=log></div>
+<script>
+
+ var description = "Test Description: Throw a DataCloneError if transfer array in postMessage contains source port.";
+
+ test(function()
+ {
+ var channel = new MessageChannel();
+ channel.port1.start();
+
+ assert_throws("DATA_CLONE_ERR", function()
+ {
+ channel.port1.postMessage("ports", [channel.port1]);
+ });
+ }, description);
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webmessaging/Channel_postMessage_event_properties.htm b/tests/wpt/web-platform-tests/webmessaging/Channel_postMessage_event_properties.htm
new file mode 100644
index 00000000000..4be7203fce8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/Channel_postMessage_event_properties.htm
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title> postMessage(): MessageEvent properties </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id=log></div>
+<script>
+
+ var TargetPort = null;
+ var description = "The postMessage() method - Create an event that uses the MessageEvent interface, "
+ + "with the name message, which does not bubble and is not cancelable.";
+
+ var t = async_test("Test Description: " + description);
+
+ var channel = new MessageChannel();
+
+ TargetPort = channel.port2;
+ TargetPort.start();
+ TargetPort.addEventListener("message", t.step_func(TestMessageEvent), true);
+
+ channel.port1.postMessage("ping");
+
+ function TestMessageEvent(evt)
+ {
+ ExpectedResult = [true, "message", false, false];
+ ActualResult = [(evt instanceof MessageEvent), evt.type, evt.bubbles, evt.cancelable];
+
+ assert_array_equals(ActualResult, ExpectedResult);
+ t.done();
+ }
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webmessaging/Channel_postMessage_ports_readonly_array.htm b/tests/wpt/web-platform-tests/webmessaging/Channel_postMessage_ports_readonly_array.htm
new file mode 100644
index 00000000000..de2952dc12d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/Channel_postMessage_ports_readonly_array.htm
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title> postMessage(): read-only ports array </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id=log></div>
+<script>
+
+ var TargetPort = null;
+ var description = "The postMessage() method - Make new ports into a read only array.";
+
+ var t = async_test("Test Description: " + description);
+
+ var channel = new MessageChannel();
+
+ TargetPort = channel.port2;
+ TargetPort.start();
+ TargetPort.addEventListener("message", t.step_func(TestMessageEvent), true);
+
+ var channel2 = new MessageChannel();
+
+ channel.port1.postMessage("ports", [channel2.port1]);
+
+ function TestMessageEvent(evt)
+ {
+ var channel3 = new MessageChannel();
+ evt.ports.push(channel3.port1);
+ evt.ports.push(channel3.port1);
+
+ assert_equals(evt.ports.length, 1, "ports is a read only array with length == 1.");
+ t.done();
+ }
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webmessaging/Channel_postMessage_target_source.htm b/tests/wpt/web-platform-tests/webmessaging/Channel_postMessage_target_source.htm
new file mode 100644
index 00000000000..4b00e68d49e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/Channel_postMessage_target_source.htm
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title> postMessage(): target port and source port </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id=log></div>
+<script>
+
+ var TARGET = null;
+ var SOURCE = null;
+ var description = "The postMessage() method - Let target port be the port with which source "
+ + "port is entangled, if any.";
+
+ var t = async_test("Test Description: " + description);
+
+ var channel = new MessageChannel();
+ SOURCE = channel.port1;
+ TARGET = channel.port2;
+ TARGET.start();
+ TARGET.addEventListener("message", t.step_func(TestMessageEvent), true);
+
+ SOURCE.postMessage("ping");
+
+ function TestMessageEvent(evt)
+ {
+ assert_equals(evt.target, TARGET);
+ assert_not_equals(evt.target, SOURCE);
+ t.done();
+ }
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webmessaging/MessageEvent_properties.htm b/tests/wpt/web-platform-tests/webmessaging/MessageEvent_properties.htm
new file mode 100644
index 00000000000..f95c257f0c9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/MessageEvent_properties.htm
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title> MessageEvent interface and properties </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id=log></div>
+
+<div style="display:none">
+ <iframe width="70%" onload="PostMessageTest()" src="./support/ChildWindowPostMessage.htm"></iframe>
+</div>
+
+<script>
+
+
+ var description = "Test Description: " +
+ "Create an event that uses the MessageEvent interface, with the event type message, " +
+ "which does not bubble, is not cancelable, and has no default action.";
+
+ var t = async_test(description);
+
+ var DATA = "foo";
+ var TARGET = document.querySelector("iframe");
+ var ExpectedResult = [true, true, false, false, false];
+ var ActualResult = [];
+
+ function PostMessageTest()
+ {
+ TARGET.contentWindow.postMessage(DATA, "*");
+ }
+
+ window.addEventListener("message", t.step_func(function(e)
+ {
+ e.preventDefault();
+
+ ActualResult = [(e instanceof MessageEvent), (e.type == "message"), e.bubbles, e.cancelable, e.defaultPrevented];
+
+ assert_array_equals(ActualResult, ExpectedResult, "ActualResult");
+
+ t.done();
+
+ }), false);
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webmessaging/README.md b/tests/wpt/web-platform-tests/webmessaging/README.md
new file mode 100644
index 00000000000..06b3a11475d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/README.md
@@ -0,0 +1,10 @@
+This directory contains the HTML5 Web Messaging test suite.
+
+The following document contains a list of each test file in the test suite and the results of running the test file on several browsers <http://www.w3.org/wiki/Webapps/Interop/WebMessaging>.
+
+To run this test suite within a browser, go to: <http://w3c-test.org/web-platform-tests/master/webmessaging/>.
+
+The latest Editor's Draft of HTML5 Web Messaging is: <http://dev.w3.org/html5/postmsg/>.
+
+The latest W3C Technical Report of HTML5 Web Messaging is <http://www.w3.org/TR/webmessaging/>.
+
diff --git a/tests/wpt/web-platform-tests/webmessaging/Transferred_objects_unusable.sub.htm b/tests/wpt/web-platform-tests/webmessaging/Transferred_objects_unusable.sub.htm
new file mode 100644
index 00000000000..55c3dbdba18
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/Transferred_objects_unusable.sub.htm
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title> Transferred objects are no longer usable on the sending side </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id=log></div>
+
+<div style="display:none">
+ <iframe width="70%" onload="PostMessageTest()" src="{{location[scheme]}}://{{domains[www1]}}:{{location[port]}}/webmessaging/support/ChildWindowPostMessage.htm"></iframe>
+</div>
+
+<script>
+
+
+ var description = "Test Description: " +
+ "Objects listed in transfer are transferred, not just cloned, meaning that they are " +
+ "no longer usable on the sending side.";
+
+ var t = async_test(description);
+
+ var DATA = {test: "e.ports[0].postMessage('TRANSFERRED')"};
+ var TARGET = document.querySelector("iframe");
+ var ExpectedResult = ["PING", "TRANSFERRED"];
+ var ActualResult = [];
+
+ function PostMessageTest()
+ {
+ test(function()
+ {
+ assert_own_property(window, "MessageChannel", "window");
+
+ var channel = new MessageChannel();
+
+ channel.port2.onmessage = t.step_func(VerifyResult);
+
+ channel.port1.postMessage("PING");
+
+ TARGET.contentWindow.postMessage(DATA, "*", [channel.port1]);
+
+ channel.port1.postMessage("PONG");
+
+ }, "MessageChannel is supported.");
+ }
+
+ function VerifyResult(e)
+ {
+ ActualResult.push(e.data)
+
+ if (ActualResult.length >= ExpectedResult.length)
+ {
+ assert_array_equals(ActualResult, ExpectedResult, "ActualResult");
+ t.done();
+ }
+ }
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webmessaging/event.data.sub.htm b/tests/wpt/web-platform-tests/webmessaging/event.data.sub.htm
new file mode 100644
index 00000000000..97584c4a390
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/event.data.sub.htm
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title> event.data returns the data of the message </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id=log></div>
+
+<div style="display:none">
+ <iframe width="70%" onload="PostMessageTest()" src="{{location[scheme]}}://{{domains[www]}}:{{location[port]}}/webmessaging/support/ChildWindowPostMessage.htm"></iframe>
+ <iframe width="70%" onload="PostMessageTest()" src="./support/ChildWindowPostMessage.htm"></iframe>
+</div>
+
+<script>
+
+
+ var description = "Test Description: event.data returns the data of the message.";
+
+ var t = async_test(description);
+
+ var PORT = location.port !== "" ? ":" + location.port : "";
+ var DATA = "STRING";
+ var TYPE = "string";
+ var TARGET1 = document.querySelectorAll("iframe")[0];
+ var TARGET2 = document.querySelectorAll("iframe")[1];
+ var XORIGIN = "{{location[scheme]}}://{{domains[www]}}" + PORT;
+ var SORIGIN = "{{location[scheme]}}://{{host}}" + PORT;
+ var ExpectedResult = [DATA, TYPE, DATA, TYPE];
+ var ActualResult = [];
+ var loaded = 0;
+
+ function PostMessageTest()
+ {
+ loaded++;
+
+ if (loaded == 2)
+ {
+ TARGET1.contentWindow.postMessage(DATA, XORIGIN);
+ TARGET2.contentWindow.postMessage(DATA, SORIGIN);
+ }
+ }
+
+ window.onmessage = t.step_func(function(e)
+ {
+ if (e.data.toString() === "STRING") {
+ ActualResult.push(e.data, typeof(e.data));
+
+ if (ActualResult.length >= ExpectedResult.length) {
+ assert_array_equals(ActualResult, ExpectedResult, "ActualResult");
+ t.done();
+ }
+ }
+ });
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webmessaging/event.origin.sub.htm b/tests/wpt/web-platform-tests/webmessaging/event.origin.sub.htm
new file mode 100644
index 00000000000..ce944ae3443
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/event.origin.sub.htm
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title> event.origin returns the origin of the message </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id=log></div>
+
+<div style="display:none">
+ <iframe width="70%" onload="PostMessageTest()" src="{{location[scheme]}}://{{domains[www]}}:{{location[port]}}/webmessaging/support/ChildWindowPostMessage.htm"></iframe>
+ <iframe width="70%" onload="PostMessageTest()" src="./support/ChildWindowPostMessage.htm"></iframe>
+</div>
+
+<script>
+
+
+ var description = "Test Description: event.origin returns the origin of the message.";
+
+ var t = async_test(description);
+
+ var PORT = location.port !== "" ? ":" + location.port : "";
+ var TARGET1 = document.querySelectorAll("iframe")[0];
+ var TARGET2 = document.querySelectorAll("iframe")[1];
+ var XORIGIN = "{{location[scheme]}}://{{domains[www]}}" + PORT;
+ var SORIGIN = "{{location[scheme]}}://{{host}}" + PORT;
+ var ExpectedResult = ["#1", XORIGIN, "#2", SORIGIN];
+ var ActualResult = [];
+ var loaded = 0;
+
+ function PostMessageTest()
+ {
+ loaded++;
+
+ if (loaded == 2)
+ {
+ TARGET1.contentWindow.postMessage("#1", XORIGIN);
+ TARGET2.contentWindow.postMessage("#2", SORIGIN);
+ }
+ }
+
+ window.onmessage = t.step_func(function(e)
+ {
+ // testharness.js uses postMessage so we must check what data we want to receive
+ if (e.data.toString() === "#1" || e.data.toString() === "#2") {
+ ActualResult.push(e.data, e.origin);
+ if (ActualResult.length === ExpectedResult.length) {
+ assert_array_equals(ActualResult, ExpectedResult, "ActualResult");
+ t.done();
+ }
+ }
+ });
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webmessaging/event.ports.sub.htm b/tests/wpt/web-platform-tests/webmessaging/event.ports.sub.htm
new file mode 100644
index 00000000000..a4ca24b15ee
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/event.ports.sub.htm
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title> event.ports returns the MessagePort array sent with the message </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id=log></div>
+
+<div style="display:none">
+ <iframe width="70%" onload="PostMessageTest()" src="{{location[scheme]}}://{{domains[www1]}}:{{location[port]}}/webmessaging/support/ChildWindowPostMessage.htm"></iframe>
+</div>
+
+<script>
+
+
+ var description = "Test Description: event.ports returns the MessagePort array sent with the message.";
+
+ var t = async_test(description);
+
+ var DATA = {test: "e.source.postMessage(e.ports.toString(), '*', e.ports)"};
+ var TARGET = document.querySelector("iframe");
+ var ExpectedResult = "";
+
+ function PostMessageTest()
+ {
+ test(function()
+ {
+ assert_own_property(window, "MessageChannel", "window");
+
+ var channel = new MessageChannel();
+ var ports = [channel.port1, channel.port2];
+ ExpectedResult = ports.toString();
+ TARGET.contentWindow.postMessage(DATA, "*", ports);
+
+ }, "MessageChannel is supported.");
+ }
+
+ window.onmessage = t.step_func(function(e)
+ {
+ assert_equals(e.data, ExpectedResult, "e.data");
+ assert_true(e.ports[0] instanceof MessagePort, e.ports[0] + " instanceof MessageChannel");
+ assert_true(e.ports[1] instanceof MessagePort, e.ports[1] + " instanceof MessageChannel");
+ t.done();
+ });
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webmessaging/event.source.htm b/tests/wpt/web-platform-tests/webmessaging/event.source.htm
new file mode 100644
index 00000000000..e270d7def04
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/event.source.htm
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title> Same-origin: event.source returns the WindowProxy of the source window </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id=log></div>
+
+<div style="display:none">
+ <iframe width="70%" onload="PostMessageTest()" src="./support/ChildWindowPostMessage.htm"></iframe>
+</div>
+
+<script>
+
+
+ var description = "Test Description: Same-origin: event.source returns the WindowProxy of the source window.";
+
+ var t = async_test(description);
+
+ var DATA = "foo";
+ var TARGET = document.querySelector("iframe");
+ var SORIGIN = location.protocol + "//" + location.host;
+ var ExpectedResult = [SORIGIN, "AccessCookieAllowed"];
+ var ActualResult = [];
+
+ function PostMessageTest()
+ {
+ TARGET.contentWindow.postMessage(DATA, SORIGIN);
+ }
+
+ window.onmessage = t.step_func(function(e)
+ {
+ try
+ {
+ var sdomainCookie = e.source.document.cookie;
+ ActualResult.push(e.origin, "AccessCookieAllowed");
+ }
+ catch(ex)
+ {
+ ActualResult.push(e.origin, "AccessCookieDenied");
+ }
+
+ assert_true(e.source === TARGET.contentWindow);
+ assert_array_equals(ActualResult, ExpectedResult, "ActualResult");
+ t.done();
+ });
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webmessaging/event.source.xorigin.sub.htm b/tests/wpt/web-platform-tests/webmessaging/event.source.xorigin.sub.htm
new file mode 100644
index 00000000000..6190c9624e7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/event.source.xorigin.sub.htm
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title> Corss-origin: event.source returns the WindowProxy of the source window </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id=log></div>
+
+<div style="display:none">
+ <iframe width="70%" onload="PostMessageTest()" src="{{location[scheme]}}://{{domains[www1]}}:{{location[port]}}/webmessaging/support/ChildWindowPostMessage.htm"></iframe>
+</div>
+
+<script>
+
+ var description = "Test Description: Cross-origin: event.source returns the WindowProxy of the source window.";
+
+ var t = async_test(description);
+
+ var PORT = location.port !== "" ? ":" + location.port : "";
+ var DATA = "foo";
+ var TARGET = document.querySelector("iframe");
+ var XORIGIN = "{{location[scheme]}}://{{domains[www1]}}" + PORT;
+ var ExpectedResult = [XORIGIN, "AccessCookieDenied"];
+ var ActualResult = [];
+
+ function PostMessageTest()
+ {
+ TARGET.contentWindow.postMessage(DATA, XORIGIN);
+ }
+
+ window.onmessage = t.step_func(function(e)
+ {
+ try
+ {
+ var sdomainCookie = e.source.document.cookie;
+ ActualResult.push(e.origin, "AccessCookieAllowed");
+ }
+ catch(ex)
+ {
+ ActualResult.push(e.origin, "AccessCookieDenied");
+ }
+
+ assert_true(e.source.parent === window);
+ assert_array_equals(ActualResult, ExpectedResult, "ActualResult");
+ t.done();
+ });
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webmessaging/message-channels/001.html b/tests/wpt/web-platform-tests/webmessaging/message-channels/001.html
new file mode 100644
index 00000000000..12fac8229c6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/message-channels/001.html
@@ -0,0 +1,17 @@
+<!doctype html>
+<title>basic messagechannel test</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function(t) {
+ var channel = new MessageChannel();
+ channel.port1.postMessage(1);
+ channel.port2.onmessage = t.step_func(
+ function(e) {
+ assert_equals(e.data, 1);
+ t.done();
+ });
+ channel.port2.start();
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/webmessaging/message-channels/002.html b/tests/wpt/web-platform-tests/webmessaging/message-channels/002.html
new file mode 100644
index 00000000000..8b712671893
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/message-channels/002.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<title>without start()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function(t) {
+ var channel = new MessageChannel();
+ channel.port1.postMessage(1);
+ var i = 0;
+ channel.port2.addEventListener('message', function() { i++; }, false);
+ setTimeout(t.step_func(function() { assert_equals(i, 0); t.done();}), 50);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/webmessaging/message-channels/003.html b/tests/wpt/web-platform-tests/webmessaging/message-channels/003.html
new file mode 100644
index 00000000000..7addaeb0faf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/message-channels/003.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<title>onmessage implied start()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function(t) {
+ var channel = new MessageChannel();
+ channel.port1.postMessage(1);
+ channel.port2.onmessage = function() {
+ setTimeout(t.step_func(function() {
+ t.done();
+ }), 50);
+ channel.port2.onmessage = t.step_func(function() {
+ assert_unreached();
+ });
+ }; // implies start()
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/webmessaging/message-channels/004-1.html b/tests/wpt/web-platform-tests/webmessaging/message-channels/004-1.html
new file mode 100644
index 00000000000..b5dd282cdca
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/message-channels/004-1.html
@@ -0,0 +1,8 @@
+<!doctype html>
+<title>004-1</title>
+<script>
+onmessage = function(e) {
+ var port = e.ports[0];
+ port.postMessage(e.data);
+}
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/webmessaging/message-channels/004-2.html b/tests/wpt/web-platform-tests/webmessaging/message-channels/004-2.html
new file mode 100644
index 00000000000..1b8ef0a7a0f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/message-channels/004-2.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>004-2</title>
+<script>
+onmessage = function(e) {
+ var port = e.ports[0];
+ port.onmessage = function(e) { // implied start()
+ parent.postMessage(e.data, '*');
+ }
+}
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/webmessaging/message-channels/004.html b/tests/wpt/web-platform-tests/webmessaging/message-channels/004.html
new file mode 100644
index 00000000000..19921fef85b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/message-channels/004.html
@@ -0,0 +1,22 @@
+<!doctype html>
+<title>cross-document channel</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<iframe src=004-1.html></iframe><iframe src=004-2.html></iframe>
+<div id="log"></div>
+<script>
+var t = async_test();
+onload = t.step_func(
+ function() {
+ var channel = new MessageChannel();
+ window[0].postMessage(1, '*', [channel.port1]);
+ window[1].postMessage(2, '*', [channel.port2]);
+ channel = null;
+ window.onmessage = t.step_func(
+ function(e) {
+ assert_equals(e.data, 1);
+ t.done();
+ });
+ }
+);
+</script>
diff --git a/tests/wpt/web-platform-tests/webmessaging/postMessage_ArrayBuffer.sub.htm b/tests/wpt/web-platform-tests/webmessaging/postMessage_ArrayBuffer.sub.htm
new file mode 100644
index 00000000000..457cf94fa56
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/postMessage_ArrayBuffer.sub.htm
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title> postMessage with ArrayBuffer object </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id=log></div>
+
+<div style="display:none">
+ <iframe width="70%" onload="PostMessageTest()" src="{{location[scheme]}}://{{domains[www]}}:{{location[port]}}/webmessaging/support/ChildWindowPostMessage.htm"></iframe>
+</div>
+
+<script>
+
+
+ var description = "Test Description: postMessage with ArrayBuffer object.";
+
+ var t = async_test(description);
+
+ var DATA;
+ var TYPE = "object";
+ var TARGET = document.querySelector("iframe");
+
+ function PostMessageTest()
+ {
+ test(function()
+ {
+ DATA = new ArrayBuffer(32);
+ TARGET.contentWindow.postMessage(DATA, "*");
+ }, "ArrayBuffer is supported.");
+ }
+
+ window.onmessage = t.step_func(function(e)
+ {
+ assert_equals(typeof(e.data), TYPE);
+ assert_equals(e.data.toString(), DATA.toString());
+ assert_equals(e.data.byteLength, 32);
+ t.done();
+ });
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webmessaging/postMessage_Date.sub.htm b/tests/wpt/web-platform-tests/webmessaging/postMessage_Date.sub.htm
new file mode 100644
index 00000000000..0f89738f3ad
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/postMessage_Date.sub.htm
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title> postMessage with Date object </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id=log></div>
+
+<div style="display:none">
+ <iframe width="70%" onload="PostMessageTest()" src="{{location[scheme]}}://{{domains[www1]}}:{{location[port]}}/webmessaging/support/ChildWindowPostMessage.htm"></iframe>
+</div>
+
+<script>
+
+
+ var description = "Test Description: Messages can contain JavaScript values (e.g., Dates).";
+
+ var t = async_test(description);
+
+ var DATA = new Date();
+ var TYPE = "object";
+ var TARGET = document.querySelector("iframe");
+
+ function PostMessageTest()
+ {
+ TARGET.contentWindow.postMessage(DATA, "*");
+ }
+
+ window.onmessage = t.step_func(function(e)
+ {
+ assert_equals(typeof(e.data), TYPE);
+ assert_equals(e.data.valueOf(), DATA.valueOf());
+ assert_not_equals(e.data, DATA, "Object is cloned");
+ t.done();
+ });
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webmessaging/postMessage_Document.htm b/tests/wpt/web-platform-tests/webmessaging/postMessage_Document.htm
new file mode 100644
index 00000000000..97765fae818
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/postMessage_Document.htm
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title> postMessage with Document object </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id=log></div>
+
+<div style="display:none">
+ <iframe width="70%" onload="PostMessageTest()" src="./support/ChildWindowPostMessage.htm"></iframe>
+</div>
+
+<script>
+
+
+ var description = "Test Description: " +
+ "postMessage with Document object: Throw a DataCloneError if message could not be cloned.";
+
+ var DATA = document;
+ var TARGET = document.querySelector("iframe");
+
+ function PostMessageTest()
+ {
+ test(function()
+ {
+ assert_throws("DATA_CLONE_ERR", function()
+ {
+ TARGET.contentWindow.postMessage(DATA, "*");
+ });
+ }, description);
+ }
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webmessaging/postMessage_Function.htm b/tests/wpt/web-platform-tests/webmessaging/postMessage_Function.htm
new file mode 100644
index 00000000000..c53e8fcc3cd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/postMessage_Function.htm
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title> postMessage with Function object </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id=log></div>
+
+<div style="display:none">
+ <iframe width="70%" onload="PostMessageTest()" src="./support/ChildWindowPostMessage.htm"></iframe>
+</div>
+
+<script>
+
+
+ var description = "Test Description: " +
+ "postMessage with Function object: Throw a DataCloneError if message could not be cloned.";
+
+ var DATA = new Function();
+ var TARGET = document.querySelector("iframe");
+
+ function PostMessageTest()
+ {
+ test(function()
+ {
+ assert_throws("DATA_CLONE_ERR", function()
+ {
+ TARGET.contentWindow.postMessage(DATA, "*");
+ });
+ }, description);
+ }
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webmessaging/postMessage_MessagePorts_sorigin.htm b/tests/wpt/web-platform-tests/webmessaging/postMessage_MessagePorts_sorigin.htm
new file mode 100644
index 00000000000..6526e972c48
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/postMessage_MessagePorts_sorigin.htm
@@ -0,0 +1,76 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title> postMessage to same-origin iframe with MessagePort array [100 ports] </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id=log></div>
+
+<div style="display:none">
+ <iframe width="70%" onload="PostMessageTest()" src="./support/ChildWindowPostMessage.htm"></iframe>
+</div>
+
+<script>
+
+
+ var description = "Test Description: postMessage to same-origin iframe with MessagePort array containing 100 ports.";
+
+ var t = async_test(description);
+
+ var TOTALPORTS = 100;
+ var LocalPorts = [];
+ var RemotePorts = [];
+ var PassedResult = 0;
+ var sum = 0;
+ var TARGET = document.querySelector("iframe").contentWindow;
+
+ function PostMessageTest()
+ {
+ test(function()
+ {
+ assert_own_property(window, "MessageChannel", "window");
+
+ var channels = [];
+
+ for (var i=0; i<TOTALPORTS; i++)
+ {
+ channels[i] = new MessageChannel();
+ LocalPorts[i] = channels[i].port1;
+ LocalPorts[i].foo = i;
+ RemotePorts[i] = channels[i].port2;
+
+ LocalPorts[i].onmessage = t.step_func(function(e)
+ {
+ assert_equals(e.target.foo, e.data);
+
+ PassedResult++;
+ sum += e.data;
+
+ if (PassedResult == TOTALPORTS)
+ {
+ assert_equals(sum, 4950);
+ t.done();
+ }
+ });
+ }
+
+ TARGET.postMessage("ports", "*", RemotePorts);
+
+ }, "MessageChannel is supported.");
+ }
+
+ window.onmessage = function(e)
+ {
+ if (e.data === "ports")
+ {
+ for (var i=0; i<TOTALPORTS; i++)
+ {
+ LocalPorts[i].postMessage(LocalPorts[i].foo);
+ }
+ }
+ }
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webmessaging/postMessage_MessagePorts_xorigin.sub.htm b/tests/wpt/web-platform-tests/webmessaging/postMessage_MessagePorts_xorigin.sub.htm
new file mode 100644
index 00000000000..cf2b8eb4c11
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/postMessage_MessagePorts_xorigin.sub.htm
@@ -0,0 +1,76 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title> postMessage to cross-origin iframe with MessagePort array [100 ports] </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id=log></div>
+
+<div style="display:none">
+ <iframe width="70%" onload="PostMessageTest()" src="{{location[scheme]}}://{{domains[www1]}}:{{location[port]}}/webmessaging/support/ChildWindowPostMessage.htm"></iframe>
+</div>
+
+<script>
+
+
+ var description = "Test Description: postMessage to cross-origin iframe with MessagePort array containing 100 ports.";
+
+ var t = async_test(description);
+
+ var TOTALPORTS = 100;
+ var LocalPorts = [];
+ var RemotePorts = [];
+ var PassedResult = 0;
+ var sum = 0;
+ var TARGET = document.querySelector("iframe").contentWindow;
+
+ function PostMessageTest()
+ {
+ test(function()
+ {
+ assert_own_property(window, "MessageChannel", "window");
+
+ var channels = [];
+
+ for (var i=0; i<TOTALPORTS; i++)
+ {
+ channels[i] = new MessageChannel();
+ LocalPorts[i] = channels[i].port1;
+ LocalPorts[i].foo = i;
+ RemotePorts[i] = channels[i].port2;
+
+ LocalPorts[i].onmessage = t.step_func(function(e)
+ {
+ assert_equals(e.target.foo, e.data);
+
+ PassedResult++;
+ sum += e.data;
+
+ if (PassedResult == TOTALPORTS)
+ {
+ assert_equals(sum, 4950);
+ t.done();
+ }
+ });
+ }
+
+ TARGET.postMessage("ports", "*", RemotePorts);
+
+ }, "MessageChannel is supported.");
+ }
+
+ window.onmessage = function(e)
+ {
+ if (e.data === "ports")
+ {
+ for (var i=0; i<TOTALPORTS; i++)
+ {
+ LocalPorts[i].postMessage(LocalPorts[i].foo);
+ }
+ }
+ }
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webmessaging/postMessage_arrays.sub.htm b/tests/wpt/web-platform-tests/webmessaging/postMessage_arrays.sub.htm
new file mode 100644
index 00000000000..41e4a75eda6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/postMessage_arrays.sub.htm
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title> postMessage with arrays </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id=log></div>
+
+<div style="display:none">
+ <iframe width="70%" onload="PostMessageTest()" src="{{location[scheme]}}://{{domains[www]}}:{{location[port]}}/webmessaging/support/ChildWindowPostMessage.htm"></iframe>
+</div>
+
+<script>
+
+
+ var description = "Test Description: Messages can be structured objects, e.g., arrays.";
+
+ var t = async_test(description);
+
+ var DATA = [1,2,3,4,5,6,7,8];
+ var TYPE = "object";
+ var TARGET = document.querySelector("iframe");
+
+ function PostMessageTest()
+ {
+ TARGET.contentWindow.postMessage(DATA, "*");
+ }
+
+ window.onmessage = t.step_func(function(e)
+ {
+ assert_equals(typeof(e.data), TYPE);
+ assert_array_equals(e.data, DATA);
+ t.done();
+ });
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webmessaging/postMessage_asterisk_xorigin.sub.htm b/tests/wpt/web-platform-tests/webmessaging/postMessage_asterisk_xorigin.sub.htm
new file mode 100644
index 00000000000..a12524625a7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/postMessage_asterisk_xorigin.sub.htm
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title> Cross-origin postMessage with targetOrigin == "*" </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id=log></div>
+
+<div style="display:none">
+ <iframe width="70%" onload="PostMessageTest()" src="{{location[scheme]}}://{{domains[www]}}:{{location[port]}}/webmessaging/support/ChildWindowPostMessage.htm"></iframe>
+ <iframe width="70%" onload="PostMessageTest()" src="./support/ChildWindowPostMessage.htm"></iframe>
+</div>
+
+<script>
+
+
+ var description = "Test Description: To send the message to the target regardless of origin, set the target origin to '*'.";
+
+ var t = async_test(description);
+
+ var PORT = location.port !== "" ? ":" + location.port : "";
+ var TARGET1 = document.querySelectorAll("iframe")[0];
+ var TARGET2 = document.querySelectorAll("iframe")[1];
+ var XORIGIN = "{{location[scheme]}}://{{domains[www]}}" + PORT;
+ var SORIGIN = "{{location[scheme]}}://{{host}}" + PORT;
+ var ExpectedResult = ["#1", XORIGIN, "#2", SORIGIN];
+ var ActualResult = [];
+ var loaded = 0;
+
+ function PostMessageTest()
+ {
+ loaded++;
+
+ if (loaded == 2)
+ {
+ TARGET1.contentWindow.postMessage("#1", "*");
+ TARGET2.contentWindow.postMessage("#2", "*");
+ }
+ }
+
+ window.onmessage = t.step_func(function(e)
+ {
+ ActualResult.push(e.data, e.origin);
+
+ if (ActualResult.length >= ExpectedResult.length)
+ {
+ assert_array_equals(ActualResult, ExpectedResult, "ActualResult");
+ t.done();
+ }
+ });
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webmessaging/postMessage_dup_transfer_objects.htm b/tests/wpt/web-platform-tests/webmessaging/postMessage_dup_transfer_objects.htm
new file mode 100644
index 00000000000..a28c9640067
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/postMessage_dup_transfer_objects.htm
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title> postMessage with duplicate transfer objects raises DataCloneError exception </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id=log></div>
+
+<div style="display:none">
+ <iframe width="70%" onload="PostMessageTest()" src="./support/ChildWindowPostMessage.htm"></iframe>
+</div>
+
+<script>
+
+
+ var description = "Test Description: " +
+ "postMessage with duplicate transfer objects raises DataCloneError exception.";
+
+ var DATA = "ports";
+ var TARGET = document.querySelector("iframe");
+
+ function PostMessageTest()
+ {
+ test(function()
+ {
+ assert_throws("DATA_CLONE_ERR", function()
+ {
+ assert_own_property(window, "MessageChannel", "window");
+ var channel = new MessageChannel();
+ TARGET.contentWindow.postMessage(DATA, "*", [channel.port1, channel.port1]);
+ });
+ }, description);
+ }
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webmessaging/postMessage_invalid_targetOrigin.htm b/tests/wpt/web-platform-tests/webmessaging/postMessage_invalid_targetOrigin.htm
new file mode 100644
index 00000000000..d6e16460f19
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/postMessage_invalid_targetOrigin.htm
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title> postMessage with invalid targetOrigin raises SyntaxError exception </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id=log></div>
+
+<div style="display:none">
+ <iframe width="70%" onload="PostMessageTest()" src="./support/ChildWindowPostMessage.htm"></iframe>
+</div>
+
+<script>
+
+
+ var description = "Test Description: " +
+ "If the value of the targetOrigin argument is neither a single U+002A ASTERISK character (*), " +
+ "a single U+002F SOLIDUS character (/), nor an absolute URL, then throw a SyntaxError exception " +
+ "and abort the overall set of steps.";
+
+ var DATA = "InvalidOrigin";
+ var TARGET = document.querySelector("iframe");
+
+ function PostMessageTest()
+ {
+ test(function()
+ {
+ assert_throws("SYNTAX_ERR", function()
+ {
+ TARGET.contentWindow.postMessage(DATA, DATA);
+ });
+ }, description);
+ }
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webmessaging/postMessage_objects.sub.htm b/tests/wpt/web-platform-tests/webmessaging/postMessage_objects.sub.htm
new file mode 100644
index 00000000000..dab207188af
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/postMessage_objects.sub.htm
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title> postMessage with nested objects </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id=log></div>
+
+<div style="display:none">
+ <iframe width="70%" onload="PostMessageTest()" src="{{location[scheme]}}://{{domains[www]}}:{{location[port]}}/webmessaging/support/ChildWindowPostMessage.htm"></iframe>
+</div>
+
+<script>
+
+
+ var description = "Test Description: Messages can be structured objects, e.g., nested objects.";
+
+ var t = async_test(description);
+
+ var DATA = {foo: {bar: "wow"}};
+ var TYPE = "object";
+ var TARGET = document.querySelector("iframe");
+
+ function PostMessageTest()
+ {
+ TARGET.contentWindow.postMessage(DATA, "*");
+ }
+
+ window.onmessage = t.step_func(function(e)
+ {
+ assert_equals(typeof(e.data), TYPE);
+ assert_equals(typeof(e.data.foo), TYPE);
+ assert_object_equals(e.data, DATA);
+ t.done();
+ });
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webmessaging/postMessage_origin_mismatch.sub.htm b/tests/wpt/web-platform-tests/webmessaging/postMessage_origin_mismatch.sub.htm
new file mode 100644
index 00000000000..6c8ac8353a7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/postMessage_origin_mismatch.sub.htm
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title> Same-origin: Origin of the target window doesn't match the given origin </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id=log></div>
+
+<div style="display:none">
+ <iframe width="70%" onload="PostMessageTest()" src="./support/ChildWindowPostMessage.htm"></iframe>
+</div>
+
+<script>
+
+
+ var description = "Test Description: " +
+ "Same-origin: If the origin of the target window doesn't match the given origin, " +
+ "the message is discarded.";
+
+ var t = async_test(description);
+
+ var PORT = location.port !== "" ? ":" + location.port : "";
+ var TARGET = document.querySelector("iframe");
+ var XORIGIN = "{{location[scheme]}}://{{domains[www1]}}" + PORT;
+ var SORIGIN = "{{location[scheme]}}://{{host}}" + PORT;
+ var ExpectedResult = ["#0", SORIGIN, "#3", SORIGIN];
+ var ActualResult = [];
+
+ function PostMessageTest()
+ {
+ TARGET.contentWindow.postMessage("#0", SORIGIN);
+ TARGET.contentWindow.postMessage("#1", "http://www.invalid-domain.com");
+ TARGET.contentWindow.postMessage("#2", XORIGIN);
+ TARGET.contentWindow.postMessage("#3", "*");
+ }
+
+ window.onmessage = t.step_func(function(e)
+ {
+ ActualResult.push(e.data, e.origin);
+
+ if (ActualResult.length >= ExpectedResult.length)
+ {
+ assert_array_equals(ActualResult, ExpectedResult, "ActualResult");
+ t.done();
+ }
+ });
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webmessaging/postMessage_origin_mismatch_xorigin.sub.htm b/tests/wpt/web-platform-tests/webmessaging/postMessage_origin_mismatch_xorigin.sub.htm
new file mode 100644
index 00000000000..d8e38e2919f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/postMessage_origin_mismatch_xorigin.sub.htm
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title> Cross-origin: Origin of the target window doesn't match the given origin </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id=log></div>
+
+<div style="display:none">
+ <iframe width="70%" onload="PostMessageTest()" src="{{location[scheme]}}://{{domains[www1]}}:{{location[port]}}/webmessaging/support/ChildWindowPostMessage.htm"></iframe>
+</div>
+
+<script>
+
+
+ var description = "Test Description: " +
+ "Cross-origin: If the origin of the target window doesn't match the given origin, " +
+ "the message is discarded.";
+
+ var t = async_test(description);
+
+ var PORT = location.port !== "" ? ":" + location.port : "";
+ var TARGET = document.querySelector("iframe");
+ var XORIGIN = "{{location[scheme]}}://{{domains[www1]}}" + PORT;
+ var SORIGIN = "{{location[scheme]}}://{{host}}" + PORT;
+ var ExpectedResult = ["#0", XORIGIN, "#3", XORIGIN];
+ var ActualResult = [];
+
+ function PostMessageTest()
+ {
+ TARGET.contentWindow.postMessage("#0", XORIGIN);
+ TARGET.contentWindow.postMessage("#1", "http://www.invalid-domain.com");
+ TARGET.contentWindow.postMessage("#2", SORIGIN);
+ TARGET.contentWindow.postMessage("#3", "*");
+ }
+
+ window.onmessage = t.step_func(function(e)
+ {
+ ActualResult.push(e.data, e.origin);
+
+ if (ActualResult.length >= ExpectedResult.length)
+ {
+ assert_array_equals(ActualResult, ExpectedResult, "ActualResult");
+ t.done();
+ }
+ });
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webmessaging/postMessage_solidus_sorigin.htm b/tests/wpt/web-platform-tests/webmessaging/postMessage_solidus_sorigin.htm
new file mode 100644
index 00000000000..92f5afb7985
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/postMessage_solidus_sorigin.htm
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title> Same-origin postMessage with targetOrigin == "/" </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id=log></div>
+
+<div style="display:none">
+ <iframe width="70%" onload="PostMessageTest()" src="./support/ChildWindowPostMessage.htm"></iframe>
+</div>
+
+<script>
+
+
+ var description = "Test Description: " +
+ "To restrict the message to same-origin targets only, without needing to explicitly " +
+ "state the origin, set the target origin to '/'.";
+
+ var t = async_test(description);
+
+ var DATA = "/";
+ var TARGET = document.querySelector("iframe");
+ var SORIGIN = location.protocol + "//" + location.host;
+ var ExpectedResult = [DATA, SORIGIN];
+ var ActualResult = [];
+
+ function PostMessageTest()
+ {
+ TARGET.contentWindow.postMessage(DATA, "/");
+ }
+
+ window.onmessage = t.step_func(function(e)
+ {
+ ActualResult.push(e.data, e.origin);
+ assert_array_equals(ActualResult, ExpectedResult, "ActualResult");
+ t.done();
+ });
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webmessaging/postMessage_solidus_xorigin.sub.htm b/tests/wpt/web-platform-tests/webmessaging/postMessage_solidus_xorigin.sub.htm
new file mode 100644
index 00000000000..eebc85432fe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/postMessage_solidus_xorigin.sub.htm
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title> Cross-origin postMessage with targetOrigin == "/" </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id=log></div>
+
+<div style="display:none">
+ <iframe width="70%" onload="PostMessageTest()" src="{{location[scheme]}}://{{domains[www1]}}:{{location[port]}}/webmessaging/support/ChildWindowPostMessage.htm"></iframe>
+</div>
+
+<script>
+
+
+ var description = "Test Description: " +
+ "If the targetOrigin argument is a single literal U+002F SOLIDUS character (/), and " +
+ "the Document of the Window object on which the method was invoked does not have the " +
+ "same origin as the entry script's document, then abort these steps silently.";
+
+ var t = async_test(description);
+
+ var DATA = "NoExceptionRaised";
+ var TARGET = document.querySelector("iframe");
+
+ function PostMessageTest()
+ {
+ try
+ {
+ TARGET.contentWindow.postMessage("/", "/");
+ TARGET.contentWindow.postMessage(DATA, "*");
+ }
+ catch(ex)
+ {
+ TARGET.contentWindow.postMessage("ExceptionRaised", "*");
+ }
+ }
+
+ window.onmessage = t.step_func(function(e)
+ {
+ assert_equals(e.data, DATA, "e.data");
+ t.done();
+ });
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webmessaging/support/ChildWindowPostMessage.htm b/tests/wpt/web-platform-tests/webmessaging/support/ChildWindowPostMessage.htm
new file mode 100644
index 00000000000..13d4103a826
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/support/ChildWindowPostMessage.htm
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title> Child window for Web Messaging tests </title>
+</head>
+<body>
+ <script>
+ if (window.opener)
+ {
+ window.onload = function()
+ {
+ try
+ {
+ window.opener.postMessage("MSG_ONLOAD_FIRED", "*");
+ }
+ catch(ex)
+ {
+ window.close();
+ }
+ }
+ }
+
+ window.onmessage = function(e)
+ {
+ try
+ {
+ if (typeof(e.data) == "object" && typeof(e.data.test) == "string")
+ {
+ eval(e.data.test);
+ }
+ else if (e.data == "*" || e.data == "/")
+ {
+ e.source.postMessage(e.data, e.data);
+ }
+ else
+ {
+ e.source.postMessage(e.data, e.origin);
+ }
+
+ if (e.data == "ports")
+ {
+ var total = e.ports.length;
+ for (var i=0; i<total; i++)
+ {
+ e.ports[i].onmessage = function (evt)
+ {
+ evt.target.postMessage(evt.data);
+ }
+ }
+ }
+ }
+ catch(ex)
+ {
+ }
+ }
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webmessaging/support/compare.js b/tests/wpt/web-platform-tests/webmessaging/support/compare.js
new file mode 100644
index 00000000000..5341b374381
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/support/compare.js
@@ -0,0 +1,39 @@
+function sameDate(d1, d2) {
+ return (d1 instanceof Date && d2 instanceof Date && d1.valueOf() == d2.valueOf());
+}
+
+function sameRE(r1, r2) {
+ return (r1 instanceof RegExp && r2 instanceof RegExp && r1.toString() == r2.toString());
+}
+
+function assert_array_equals_(observed, expected, msg) {
+ if (observed.length == expected.length) {
+ for (var i = 0; i < observed.length; i++) {
+ if (observed[i] instanceof Date) {
+ observed[i] = sameDate(observed[i], expected[i]);
+ expected[i] = true;
+ } else if (observed[i] instanceof RegExp) {
+ observed[i] = sameRE(observed[i], expected[i]);
+ expected[i] = true;
+ }
+ }
+ }
+
+ assert_array_equals(observed, expected, msg);
+}
+
+function assert_object_equals_(observed, expected, msg) {
+ for (var p in observed) {
+ if (observed[p] instanceof Date) {
+ observed[p] = sameDate(observed[p], expected[p]);
+ expected[p] = true;
+ } else if (observed[p] instanceof RegExp) {
+ observed[p] = sameRE(observed[p], expected[p]);
+ expected[p] = true;
+ } else if (observed[p] instanceof Array || String(observed[p]) === '[object Object]') {
+ observed[p] = String(observed[p]) === String(expected[p]);
+ expected[p] = true;
+ }
+ assert_equals(observed[p], expected[p], msg);
+ }
+}
diff --git a/tests/wpt/web-platform-tests/webmessaging/with-ports/001.html b/tests/wpt/web-platform-tests/webmessaging/with-ports/001.html
new file mode 100644
index 00000000000..e3687f16226
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/with-ports/001.html
@@ -0,0 +1,12 @@
+<!doctype html>
+<title>resolving broken url</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ assert_throws('SYNTAX_ERR', function() {
+ postMessage('', 'http://foo bar', []);
+ }, 'should have failed to resolve');
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/webmessaging/with-ports/002.html b/tests/wpt/web-platform-tests/webmessaging/with-ports/002.html
new file mode 100644
index 00000000000..f7d085937cd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/with-ports/002.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<title>resolving url with stuff in host-specific</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+ postMessage('', location.protocol + '//' + location.host + '//', []);
+ onmessage = this.step_func(function(e) {
+ assert_equals(e.origin, location.protocol + '//' + location.host);
+ this.done();
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/webmessaging/with-ports/003.html b/tests/wpt/web-platform-tests/webmessaging/with-ports/003.html
new file mode 100644
index 00000000000..3c0d4296b07
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/with-ports/003.html
@@ -0,0 +1,12 @@
+<!doctype html>
+<title>resolving 'example.org'</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ assert_throws('SYNTAX_ERR', function() {
+ postMessage('', 'example.org', []);
+ }, 'targetOrigin is not an absolute url');
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/webmessaging/with-ports/004.html b/tests/wpt/web-platform-tests/webmessaging/with-ports/004.html
new file mode 100644
index 00000000000..d129ad119a8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/with-ports/004.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<title>special value '/'</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+ postMessage('', '/', []);
+ onmessage = this.step_func(function(e) {
+ assert_equals(e.data, '');
+ this.done();
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/webmessaging/with-ports/005.html b/tests/wpt/web-platform-tests/webmessaging/with-ports/005.html
new file mode 100644
index 00000000000..e8039689198
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/with-ports/005.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<title>resolving a same origin targetOrigin</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+ postMessage('', location.protocol + '//' + location.host, []);
+ onmessage = this.step_func(function(e) {
+ assert_equals(e.data, '');
+ this.done();
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/webmessaging/with-ports/006.html b/tests/wpt/web-platform-tests/webmessaging/with-ports/006.html
new file mode 100644
index 00000000000..4e3f1ede841
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/with-ports/006.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<title>resolving a same origin targetOrigin with trailing slash</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+ postMessage('', location.protocol + '//' + location.host + '/', []);
+ onmessage = this.step_func(function(e) {
+ assert_equals(e.data, '');
+ this.done();
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/webmessaging/with-ports/007.html b/tests/wpt/web-platform-tests/webmessaging/with-ports/007.html
new file mode 100644
index 00000000000..c049a1337d3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/with-ports/007.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<title>targetOrigin '*'</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+ postMessage('', '*', []);
+ onmessage = this.step_func(function(e) {
+ assert_equals(e.data, '');
+ this.done();
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/webmessaging/with-ports/010.html b/tests/wpt/web-platform-tests/webmessaging/with-ports/010.html
new file mode 100644
index 00000000000..672d4a0dda6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/with-ports/010.html
@@ -0,0 +1,113 @@
+<!doctype html>
+<title>message clone</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../support/compare.js"></script>
+<div id=log></div>
+<script>
+ var err = new Error('foo');
+ var date = new Date();
+
+ var test_array = [ undefined,
+ null,
+ false,
+ true,
+ 1,
+ NaN,
+ Infinity,
+ 'foo',
+ date,
+ /foo/,
+ null/*self*/,
+ null/*err*/];
+
+ var cloned_array = [ undefined,
+ null,
+ false,
+ true,
+ 1,
+ NaN,
+ Infinity,
+ 'foo',
+ date,
+ /foo/,
+ null/*self*/,
+ null/*err*/];
+
+ var test_object = {a: undefined,
+ b: null,
+ c: false,
+ d: true,
+ e: 1,
+ f: NaN,
+ g: Infinity,
+ h: 'foo',
+ i: date,
+ j: /foo/,
+ k: null/*self*/,
+ l: [],
+ m: {},
+ n: null /*err*/};
+
+ var cloned_object = {a:undefined, b:null, c:false, d:true, e:1, f:NaN, g:Infinity, h:'foo', i: date, j: /foo/, k:null, l: [], m: {}, n:null};
+
+ var tests = [undefined, null,
+ false, true,
+ 1, NaN, Infinity,
+ 'foo',
+ date,
+ /foo/,
+ /* ImageData, File, FileData, FileList, */
+ null /*self*/,
+ test_array,
+ test_object,
+ null /*err*/];
+
+ for (var i = 0; i < tests.length; ++i) {
+ postMessage(tests[i], '*', []);
+ }
+
+ var test_undefined = async_test('undefined');
+ var test_null = async_test('null');
+ var test_false = async_test('false');
+ var test_true = async_test('true');
+ var test_1 = async_test('1');
+ var test_NaN = async_test('NaN');
+ var test_Infinity = async_test('Infinity');
+ var test_string = async_test('string');
+ var test_date = async_test('date');
+ var test_regex = async_test('regex');
+ var test_self = async_test('self');
+ var test_array = async_test('array');
+ var test_object = async_test('object');
+ var test_error = async_test('error');
+ var test_unreached = async_test('unreached');
+
+ var j = 0;
+ onmessage = function(e) {
+ switch (j) {
+ case 0: test_undefined.step(function() { assert_equals(e.data, undefined); this.done(); }); break;
+ case 1: test_null.step(function() { assert_equals(e.data, null); this.done(); }); break;
+ case 2: test_false.step(function() { assert_false(e.data); this.done(); }); break;
+ case 3: test_true.step(function() { assert_true(e.data); this.done(); }); break;
+ case 4: test_1.step(function() { assert_equals(e.data, 1); this.done(); }); break;
+ case 5: test_NaN.step(function() { assert_equals(e.data, NaN); this.done(); }); break;
+ case 6: test_Infinity.step(function() { assert_equals(e.data, Infinity); this.done(); }); break;
+ case 7: test_string.step(function() { assert_equals(e.data, 'foo'); this.done(); }); break;
+ case 8: test_date.step(function() { assert_true(sameDate(e.data, date)); this.done(); }); break;
+ case 9: test_regex.step(function() { assert_equals('' + e.data, '/foo/'); assert_equals(e.data instanceof RegExp, true, 'e.data instanceof RegExp'); this.done(); }); break;
+ // not testing it any more, as cloning host objects will now raise exceptions. TODO: add (exceptional) tests for these.
+ case 10: test_self.step(function() { assert_equals(e.data, null); this.done(); }); break;
+ case 11: test_array.step(function() { assert_array_equals_(e.data, cloned_array, 'array'); this.done(); }); break;
+ case 12: test_object.step(function() { assert_object_equals_(e.data, cloned_object, 'object'); this.done(); }); break;
+ case 13:
+ test_error.step(function() { assert_equals(e.data, null, 'new Error()'); this.done(); });
+ setTimeout(test_unreached.step_func(function() { assert_equals(j, 14); this.done(); }), 50);
+ break;
+ default: test_unreached.step(function() { assert_unreached('got an unexpected message event ('+i+')'); });
+ };
+ j++;
+ }
+
+
+</script>
diff --git a/tests/wpt/web-platform-tests/webmessaging/with-ports/011.html b/tests/wpt/web-platform-tests/webmessaging/with-ports/011.html
new file mode 100644
index 00000000000..782b3208ba4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/with-ports/011.html
@@ -0,0 +1,29 @@
+<!doctype html>
+<title>posting an imagedata (from a cloned canvas) in an array</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+
+ var canvas = document.createElement('canvas');
+ var clone = canvas.cloneNode(true);
+ var ctx = clone.getContext('2d');
+ var imagedata = ctx.getImageData(0, 0, 300, 150);
+ postMessage([imagedata], '*', []);
+
+ onmessage = this.step_func(function(e) {
+ function processPixels(imagedata) {
+ var pixeldata = imagedata.data;
+ for (var i = 0; i < pixeldata.length; i = i+4) {
+ pixeldata[i] = 128;
+ assert_equals(pixeldata[i], 128);
+ }
+ }
+ processPixels(e.data[0]);
+ this.done();
+ });
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/webmessaging/with-ports/012.html b/tests/wpt/web-platform-tests/webmessaging/with-ports/012.html
new file mode 100644
index 00000000000..6efe4c114ab
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/with-ports/012.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<title>loop in array in structured clone</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+ var x = [];
+ x[0] = x;
+ postMessage(x, '*', []);
+ onmessage = this.step_func(function(e) {
+ assert_equals(e.data, e.data[0]);
+ this.done();
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/webmessaging/with-ports/013.html b/tests/wpt/web-platform-tests/webmessaging/with-ports/013.html
new file mode 100644
index 00000000000..248958ea108
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/with-ports/013.html
@@ -0,0 +1,17 @@
+<!doctype html>
+<title>loop in object in structured clone</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+ var x = {};
+ x.foo = x;
+ postMessage(x, '*', []);
+ onmessage = this.step_func(function(e) {
+ assert_equals(e.data, e.data.foo);
+ this.done();
+ });
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/webmessaging/with-ports/014.html b/tests/wpt/web-platform-tests/webmessaging/with-ports/014.html
new file mode 100644
index 00000000000..3c970c42ade
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/with-ports/014.html
@@ -0,0 +1,17 @@
+<!doctype html>
+<title>structured clone vs reference</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function(t) {
+ var x = [];
+ y = [x,x];
+ postMessage(y, '*', []);
+ onmessage = t.step_func(function(e) {
+ assert_equals(e.data[0], e.data[1], 'e.data[0] === e.data[1]');
+ assert_not_equals(e.data[0], x, 'e.data[0] !== x');
+ t.done();
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/webmessaging/with-ports/015.html b/tests/wpt/web-platform-tests/webmessaging/with-ports/015.html
new file mode 100644
index 00000000000..a17c97be19a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/with-ports/015.html
@@ -0,0 +1,15 @@
+<!doctype html>
+<title>different origin</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+ postMessage('', 'http://example.org', []);
+ onmessage = this.step_func(function(e) {
+ assert_unreached();
+ });
+ setTimeout(this.step_func(function(){ this.done(); }), 50);
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/webmessaging/with-ports/016.html b/tests/wpt/web-platform-tests/webmessaging/with-ports/016.html
new file mode 100644
index 00000000000..7257c95d0d7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/with-ports/016.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<title>origin of the script that invoked the method, data:</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<iframe src="data:text/html,"></iframe>
+<div id=log></div>
+<script>
+async_test(function() {
+ window[0].postMessage('', '*', []);
+ window[0].onmessage = this.step_func(function(e) {
+ assert_equals(e.origin, location.protocol + '//' + location.host);
+ assert_array_equals(e.ports, []);
+ this.done();
+ });
+});
+</script>
+
+
diff --git a/tests/wpt/web-platform-tests/webmessaging/with-ports/017.html b/tests/wpt/web-platform-tests/webmessaging/with-ports/017.html
new file mode 100644
index 00000000000..94cd3e6ae2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/with-ports/017.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<title>origin of the script that invoked the method, about:blank</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<iframe src="about:blank"></iframe>
+<div id=log></div>
+<script>
+async_test(function() {
+ window[0].postMessage('', '*', []);
+ window[0].onmessage = this.step_func(function(e) {
+ assert_equals(e.origin, location.protocol + '//' + location.host);
+ assert_array_equals(e.ports, []);
+ this.done();
+ });
+});
+</script>
+
+
diff --git a/tests/wpt/web-platform-tests/webmessaging/with-ports/018.html b/tests/wpt/web-platform-tests/webmessaging/with-ports/018.html
new file mode 100644
index 00000000000..5525206e444
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/with-ports/018.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<title>origin of the script that invoked the method, javascript:</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<iframe src="javascript:''"></iframe>
+<div id=log></div>
+<script>
+async_test(function() {
+ window[0].postMessage('', '*', []);
+ window[0].onmessage = this.step_func(function(e) {
+ assert_equals(e.origin, location.protocol + '//' + location.host);
+ assert_array_equals(e.ports, []);
+ this.done();
+ });
+});
+</script>
+
+
diff --git a/tests/wpt/web-platform-tests/webmessaging/with-ports/019.html b/tests/wpt/web-platform-tests/webmessaging/with-ports/019.html
new file mode 100644
index 00000000000..2c65d58169f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/with-ports/019.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<title>origin of the script that invoked the method, scheme/host/port</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<iframe src="../without-ports/019-1.html"></iframe>
+<div id=log></div>
+<script>
+async_test(function() {
+ window[0].postMessage('', location.protocol.toUpperCase() + '//' + location.host.toUpperCase() + '/', []);
+ window[0].onmessage = this.step_func(function(e) {
+ assert_equals(e.origin, location.protocol + '//' + location.host);
+ assert_array_equals(e.ports, []);
+ this.done();
+ });
+});
+</script>
+
+
diff --git a/tests/wpt/web-platform-tests/webmessaging/with-ports/020.html b/tests/wpt/web-platform-tests/webmessaging/with-ports/020.html
new file mode 100644
index 00000000000..e1e0c7320e1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/with-ports/020.html
@@ -0,0 +1,32 @@
+<!doctype html>
+<title>cross-origin test</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<iframe src="../without-ports/020-1.html"></iframe>
+<div id="log"></div>
+<script>
+var iframe = document.createElement('iframe');
+var url_prefix = location.href.replace('://', '://www1.').replace(/\/with(out)?-ports\/[^\/]+$/, '');
+var url = url_prefix + '/without-ports/020-1.html';
+iframe.src = url;
+document.body.appendChild(iframe);
+</script>
+<div id=log></div>
+<script>
+var t = async_test();
+onload = t.step_func(function() {
+ window[0].postMessage(1, location.href, []);
+ window[1].postMessage(2, url, []);
+ var i = 0;
+ onmessage = t.step_func(function(e) {
+ i++;
+ assert_equals(e.data[0], i);
+ assert_equals(e.data[1], location.protocol + '//' + location.host);
+ if (i === 2) {
+ t.done();
+ }
+ });
+ setTimeout(t.step_func(function() { assert_unreached("Only got " + i + " events before timeout, expected 2") }), 1000);
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/webmessaging/with-ports/021.html b/tests/wpt/web-platform-tests/webmessaging/with-ports/021.html
new file mode 100644
index 00000000000..94cc4796768
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/with-ports/021.html
@@ -0,0 +1,32 @@
+<!doctype html>
+<title>cross-origin test</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<iframe src="../without-ports/020-1.html"></iframe>
+<div id="log"></div>
+<script>
+var iframe = document.createElement('iframe');
+var url_prefix = location.href.replace('://', '://www1.').replace(/\/with(out)?-ports\/[^\/]+$/, '');
+var url = url_prefix + '/without-ports/020-1.html';
+iframe.src = url;
+document.body.appendChild(iframe);
+</script>
+<div id=log></div>
+<script>
+var t = async_test();
+onload = t.step_func(function() {
+ window[0].postMessage(1, '*', []);
+ window[1].postMessage(2, '*', []);
+ var i = 0;
+ onmessage = t.step_func(function(e) {
+ i++;
+ assert_equals(e.data[0], i);
+ assert_equals(e.data[1], location.protocol + '//' + location.host);
+ if (i === 2) {
+ t.done();
+ }
+ });
+ setTimeout(t.step_func(function() { assert_unreached("Only got " + i + " events before timeout, expected 2") }), 1000);
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/webmessaging/with-ports/023.html b/tests/wpt/web-platform-tests/webmessaging/with-ports/023.html
new file mode 100644
index 00000000000..664289585da
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/with-ports/023.html
@@ -0,0 +1,15 @@
+<!doctype html>
+<title>null ports</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ postMessage('', '*', null);
+ onmessage = t.step_func(function(e) {
+ assert_array_equals(e.ports, []);
+ this.done();
+ });
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/webmessaging/with-ports/024.html b/tests/wpt/web-platform-tests/webmessaging/with-ports/024.html
new file mode 100644
index 00000000000..e6c0dcba086
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/with-ports/024.html
@@ -0,0 +1,15 @@
+<!doctype html>
+<title>undefined as ports</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+ postMessage('', '*', undefined);
+ onmessage = this.step_func(function(e) {
+ assert_array_equals(e.ports, []);
+ this.done();
+ });
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/webmessaging/with-ports/025.html b/tests/wpt/web-platform-tests/webmessaging/with-ports/025.html
new file mode 100644
index 00000000000..9a0e5cf6ffb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/with-ports/025.html
@@ -0,0 +1,13 @@
+<!doctype html>
+<title>1 as ports</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+test(function() {
+ assert_throws(new TypeError(), function() {
+ postMessage('', '*', 1);
+ });
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/webmessaging/with-ports/026.html b/tests/wpt/web-platform-tests/webmessaging/with-ports/026.html
new file mode 100644
index 00000000000..cf5c5e18ae5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/with-ports/026.html
@@ -0,0 +1,13 @@
+<!doctype html>
+<title>object with length as transferable</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+test(function() {
+ assert_throws(new TypeError(), function() {
+ postMessage('', '*', {length:1});
+ });
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/webmessaging/with-ports/027.html b/tests/wpt/web-platform-tests/webmessaging/with-ports/027.html
new file mode 100644
index 00000000000..c85e02dc7a6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/with-ports/027.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<title>message channel as ports</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var channel = new MessageChannel();
+ channel[0] = channel.port1;
+ channel[1] = channel.port2;
+ channel.length = 2;
+ postMessage('', '*', channel);
+ onmessage = t.step_func(function(e) {
+ assert_equals(e.ports.length, 2);
+ t.done();
+ });
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/webmessaging/without-ports/001.html b/tests/wpt/web-platform-tests/webmessaging/without-ports/001.html
new file mode 100644
index 00000000000..8f77c31fc61
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/without-ports/001.html
@@ -0,0 +1,12 @@
+<!doctype html>
+<title>resolving broken url</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ assert_throws('SYNTAX_ERR', function() {
+ postMessage('', 'http://foo bar');
+ }, 'should have failed to resolve');
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/webmessaging/without-ports/002.html b/tests/wpt/web-platform-tests/webmessaging/without-ports/002.html
new file mode 100644
index 00000000000..ef3eceb2a02
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/without-ports/002.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<title>resolving url with stuff in host-specific</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+ postMessage('', location.protocol + '//' + location.host + '//');
+ onmessage = this.step_func(function(e) {
+ assert_equals(e.origin, location.protocol + '//' + location.host);
+ this.done();
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/webmessaging/without-ports/003.html b/tests/wpt/web-platform-tests/webmessaging/without-ports/003.html
new file mode 100644
index 00000000000..5021e09f46b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/without-ports/003.html
@@ -0,0 +1,12 @@
+<!doctype html>
+<title>resolving 'example.org'</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ assert_throws('SYNTAX_ERR', function() {
+ postMessage('', 'example.org');
+ }, 'targetOrigin is not an absolute url');
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/webmessaging/without-ports/004.html b/tests/wpt/web-platform-tests/webmessaging/without-ports/004.html
new file mode 100644
index 00000000000..9a9eb81a5de
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/without-ports/004.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<title>special value '/'</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+ postMessage('', '/');
+ onmessage = this.step_func(function(e) {
+ assert_equals(e.data, '');
+ this.done();
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/webmessaging/without-ports/005.html b/tests/wpt/web-platform-tests/webmessaging/without-ports/005.html
new file mode 100644
index 00000000000..ed05a476bc4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/without-ports/005.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<title>resolving a same origin targetOrigin</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+ postMessage('', location.protocol + '//' + location.host);
+ onmessage = this.step_func(function(e) {
+ assert_equals(e.data, '');
+ this.done();
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/webmessaging/without-ports/006.html b/tests/wpt/web-platform-tests/webmessaging/without-ports/006.html
new file mode 100644
index 00000000000..47479ea0118
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/without-ports/006.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<title>resolving a same origin targetOrigin with trailing slash</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+ postMessage('', location.protocol + '//' + location.host + '/');
+ onmessage = this.step_func(function(e) {
+ assert_equals(e.data, '');
+ this.done();
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/webmessaging/without-ports/007.html b/tests/wpt/web-platform-tests/webmessaging/without-ports/007.html
new file mode 100644
index 00000000000..eb2b5c52e56
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/without-ports/007.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<title>targetOrigin '*'</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+ postMessage('', '*');
+ onmessage = this.step_func(function(e) {
+ assert_equals(e.data, '');
+ this.done();
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/webmessaging/without-ports/008.html b/tests/wpt/web-platform-tests/webmessaging/without-ports/008.html
new file mode 100644
index 00000000000..30bf607f357
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/without-ports/008.html
@@ -0,0 +1,12 @@
+<!doctype html>
+<title>just one argument</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ assert_throws(new TypeError(), function() {
+ postMessage('');
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/webmessaging/without-ports/009.html b/tests/wpt/web-platform-tests/webmessaging/without-ports/009.html
new file mode 100644
index 00000000000..779383da203
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/without-ports/009.html
@@ -0,0 +1,12 @@
+<!doctype html>
+<title>zero arguments</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ assert_throws(new TypeError(), function() {
+ postMessage();
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/webmessaging/without-ports/010.html b/tests/wpt/web-platform-tests/webmessaging/without-ports/010.html
new file mode 100644
index 00000000000..dcbffd9c8a1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/without-ports/010.html
@@ -0,0 +1,112 @@
+<!doctype html>
+<title>message clone</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../support/compare.js"></script>
+<div id=log></div>
+<script>
+ var err = new Error('foo');
+ var date = new Date();
+
+ var test_array = [ undefined,
+ null,
+ false,
+ true,
+ 1,
+ NaN,
+ Infinity,
+ 'foo',
+ date,
+ /foo/,
+ null/*self*/,
+ null/*err*/];
+
+ var cloned_array = [ undefined,
+ null,
+ false,
+ true,
+ 1,
+ NaN,
+ Infinity,
+ 'foo',
+ date,
+ /foo/,
+ null/*self*/,
+ null/*err*/];
+
+ var test_object = {a: undefined,
+ b: null,
+ c: false,
+ d: true,
+ e: 1,
+ f: NaN,
+ g: Infinity,
+ h: 'foo',
+ i: date,
+ j: /foo/,
+ k: null/*self*/,
+ l: [],
+ m: {},
+ n: null /*err*/};
+
+ var cloned_object = {a:undefined, b:null, c:false, d:true, e:1, f:NaN, g:Infinity, h:'foo', i: date, j: /foo/, k:null, l: [], m: {}, n:null};
+
+ var tests = [undefined, null,
+ false, true,
+ 1, NaN, Infinity,
+ 'foo',
+ date,
+ /foo/,
+ /* ImageData, File, FileData, FileList, */
+ null /*self*/,
+ test_array,
+ test_object,
+ null /*err*/];
+
+ for (var i = 0; i < tests.length; ++i) {
+ postMessage(tests[i], '*');
+ }
+
+ var test_undefined = async_test('undefined');
+ var test_null = async_test('null');
+ var test_false = async_test('false');
+ var test_true = async_test('true');
+ var test_1 = async_test('1');
+ var test_NaN = async_test('NaN');
+ var test_Infinity = async_test('Infinity');
+ var test_string = async_test('string');
+ var test_date = async_test('date');
+ var test_regex = async_test('regex');
+ var test_self = async_test('self');
+ var test_array = async_test('array');
+ var test_object = async_test('object');
+ var test_error = async_test('error');
+ var test_unreached = async_test('unreached');
+
+ var j = 0;
+ onmessage = function(e) {
+ switch (j) {
+ case 0: test_undefined.step(function() { assert_equals(e.data, undefined); this.done(); }); break;
+ case 1: test_null.step(function() { assert_equals(e.data, null); this.done(); }); break;
+ case 2: test_false.step(function() { assert_false(e.data); this.done(); }); break;
+ case 3: test_true.step(function() { assert_true(e.data); this.done(); }); break;
+ case 4: test_1.step(function() { assert_equals(e.data, 1); this.done(); }); break;
+ case 5: test_NaN.step(function() { assert_equals(e.data, NaN); this.done(); }); break;
+ case 6: test_Infinity.step(function() { assert_equals(e.data, Infinity); this.done(); }); break;
+ case 7: test_string.step(function() { assert_equals(e.data, 'foo'); this.done(); }); break;
+ case 8: test_date.step(function() { assert_true(sameDate(e.data, date)); this.done(); }); break;
+ case 9: test_regex.step(function() { assert_equals('' + e.data, '/foo/'); assert_equals(e.data instanceof RegExp, true, 'e.data instanceof RegExp'); this.done(); }); break;
+ // not testing it any more, as cloning host objects will now raise exceptions. TODO: add (exceptional) tests for these.
+ case 10: test_self.step(function() { assert_equals(e.data, null); this.done(); }); break;
+ case 11: test_array.step(function() { assert_array_equals_(e.data, cloned_array, 'array'); this.done(); }); break;
+ case 12: test_object.step(function() { assert_object_equals_(e.data, cloned_object, 'object'); this.done(); }); break;
+ case 13:
+ test_error.step(function() { assert_equals(e.data, null, 'new Error()'); this.done(); });
+ setTimeout(test_unreached.step_func(function() { assert_equals(j, 14); this.done(); }), 50);
+ break;
+ default: test_unreached.step(function() { assert_unreached('got an unexpected message event ('+i+')'); });
+ };
+ j++;
+ }
+
+</script>
diff --git a/tests/wpt/web-platform-tests/webmessaging/without-ports/011.html b/tests/wpt/web-platform-tests/webmessaging/without-ports/011.html
new file mode 100644
index 00000000000..cac2990c49a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/without-ports/011.html
@@ -0,0 +1,29 @@
+<!doctype html>
+<title>posting an imagedata (from a cloned canvas) in an array</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+
+ var canvas = document.createElement('canvas');
+ var clone = canvas.cloneNode(true);
+ var ctx = clone.getContext('2d');
+ var imagedata = ctx.getImageData(0, 0, 300, 150);
+ postMessage([imagedata], '*');
+
+ onmessage = this.step_func(function(e) {
+ function processPixels(imagedata) {
+ var pixeldata = imagedata.data;
+ for (var i = 0; i < pixeldata.length; i = i+4) {
+ pixeldata[i] = 128;
+ assert_equals(pixeldata[i], 128);
+ }
+ }
+ processPixels(e.data[0]);
+ this.done();
+ });
+
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/webmessaging/without-ports/012.html b/tests/wpt/web-platform-tests/webmessaging/without-ports/012.html
new file mode 100644
index 00000000000..8eb46539b7e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/without-ports/012.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<title>loop in array in structured clone</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+ var x = [];
+ x[0] = x;
+ postMessage(x, '*');
+ onmessage = this.step_func(function(e) {
+ assert_equals(e.data, e.data[0]);
+ this.done();
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/webmessaging/without-ports/013.html b/tests/wpt/web-platform-tests/webmessaging/without-ports/013.html
new file mode 100644
index 00000000000..34ba76221aa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/without-ports/013.html
@@ -0,0 +1,17 @@
+<!doctype html>
+<title>loop in object in structured clone</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+ var x = {};
+ x.foo = x;
+ postMessage(x, '*');
+ onmessage = this.step_func(function(e) {
+ assert_equals(e.data, e.data.foo);
+ this.done();
+ });
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/webmessaging/without-ports/014.html b/tests/wpt/web-platform-tests/webmessaging/without-ports/014.html
new file mode 100644
index 00000000000..f200aa46736
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/without-ports/014.html
@@ -0,0 +1,17 @@
+<!doctype html>
+<title>structured clone vs reference</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function(t) {
+ var x = [];
+ y = [x,x];
+ postMessage(y, '*');
+ onmessage = t.step_func(function(e) {
+ assert_equals(e.data[0], e.data[1], 'e.data[0] === e.data[1]');
+ assert_not_equals(e.data[0], x, 'e.data[0] !== x');
+ t.done();
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/webmessaging/without-ports/015.html b/tests/wpt/web-platform-tests/webmessaging/without-ports/015.html
new file mode 100644
index 00000000000..a17c97be19a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/without-ports/015.html
@@ -0,0 +1,15 @@
+<!doctype html>
+<title>different origin</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+ postMessage('', 'http://example.org', []);
+ onmessage = this.step_func(function(e) {
+ assert_unreached();
+ });
+ setTimeout(this.step_func(function(){ this.done(); }), 50);
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/webmessaging/without-ports/016.html b/tests/wpt/web-platform-tests/webmessaging/without-ports/016.html
new file mode 100644
index 00000000000..da1d8e59599
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/without-ports/016.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<title>origin of the script that invoked the method, data:</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<iframe src="data:text/html,"></iframe>
+<div id=log></div>
+<script>
+async_test(function() {
+ window[0].postMessage('', '*');
+ window[0].onmessage = this.step_func(function(e) {
+ assert_equals(e.origin, location.protocol + '//' + location.host);
+ assert_array_equals(e.ports, []);
+ this.done();
+ });
+});
+</script>
+
+
diff --git a/tests/wpt/web-platform-tests/webmessaging/without-ports/017.html b/tests/wpt/web-platform-tests/webmessaging/without-ports/017.html
new file mode 100644
index 00000000000..a4a0483624f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/without-ports/017.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<title>origin of the script that invoked the method, about:blank</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<iframe src="about:blank"></iframe>
+<div id=log></div>
+<script>
+async_test(function() {
+ window[0].postMessage('', '*');
+ window[0].onmessage = this.step_func(function(e) {
+ assert_equals(e.origin, location.protocol + '//' + location.host);
+ assert_array_equals(e.ports, []);
+ this.done();
+ });
+});
+</script>
+
+
diff --git a/tests/wpt/web-platform-tests/webmessaging/without-ports/018.html b/tests/wpt/web-platform-tests/webmessaging/without-ports/018.html
new file mode 100644
index 00000000000..207ae36ed83
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/without-ports/018.html
@@ -0,0 +1,17 @@
+<!doctype html>
+<title>origin of the script that invoked the method, javascript:</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<iframe src="javascript:''"></iframe>
+<div id=log></div>
+<script>
+async_test(function() {
+ window[0].postMessage('', '*');
+ window[0].onmessage = this.step_func(function(e) {
+ assert_equals(e.origin, location.protocol + '//' + location.host);
+ this.done();
+ });
+});
+</script>
+
+
diff --git a/tests/wpt/web-platform-tests/webmessaging/without-ports/019-1.html b/tests/wpt/web-platform-tests/webmessaging/without-ports/019-1.html
new file mode 100644
index 00000000000..513123ee6d5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/without-ports/019-1.html
@@ -0,0 +1 @@
+<!-- blank --> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/webmessaging/without-ports/019.html b/tests/wpt/web-platform-tests/webmessaging/without-ports/019.html
new file mode 100644
index 00000000000..f271a9e716a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/without-ports/019.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<title>origin of the script that invoked the method, scheme/host/port</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<iframe src="../without-ports/019-1.html"></iframe>
+<div id=log></div>
+<script>
+async_test(function() {
+ window[0].postMessage('', location.protocol.toUpperCase() + '//' + location.host.toUpperCase() + '/');
+ window[0].onmessage = this.step_func(function(e) {
+ assert_equals(e.origin, location.protocol + '//' + location.host);
+ assert_array_equals(e.ports, []);
+ this.done();
+ });
+});
+</script>
+
+
diff --git a/tests/wpt/web-platform-tests/webmessaging/without-ports/020-1.html b/tests/wpt/web-platform-tests/webmessaging/without-ports/020-1.html
new file mode 100644
index 00000000000..225bd7a41e3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/without-ports/020-1.html
@@ -0,0 +1,5 @@
+<script>
+onmessage = function(e) {
+ parent.postMessage([e.data, e.origin], '*');
+}
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/webmessaging/without-ports/020.html b/tests/wpt/web-platform-tests/webmessaging/without-ports/020.html
new file mode 100644
index 00000000000..b8c7ff9df90
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/without-ports/020.html
@@ -0,0 +1,32 @@
+<!doctype html>
+<title>cross-origin test</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<iframe src="../without-ports/020-1.html"></iframe>
+<div id="log"></div>
+<script>
+var iframe = document.createElement('iframe');
+var url_prefix = location.href.replace('://', '://www1.').replace(/\/with(out)?-ports\/[^\/]+$/, '');
+var url = url_prefix + '/without-ports/020-1.html';
+iframe.src = url;
+document.body.appendChild(iframe);
+</script>
+<div id=log></div>
+<script>
+var t = async_test();
+onload = t.step_func(function() {
+ window[0].postMessage(1, location.href);
+ window[1].postMessage(2, url);
+ var i = 0;
+ onmessage = t.step_func(function(e) {
+ i++;
+ assert_equals(e.data[0], i);
+ assert_equals(e.data[1], location.protocol + '//' + location.host);
+ if (i == 2) {
+ t.done();
+ }
+ });
+ setTimeout(t.step_func(function() {assert_unreached("Only got " + i + " events before timeout, expected 2")}), 1000);
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/webmessaging/without-ports/021.html b/tests/wpt/web-platform-tests/webmessaging/without-ports/021.html
new file mode 100644
index 00000000000..992a898e794
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/without-ports/021.html
@@ -0,0 +1,32 @@
+<!doctype html>
+<title>cross-origin test</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<iframe src="../without-ports/020-1.html"></iframe>
+<div id="log"></div>
+<script>
+var iframe = document.createElement('iframe');
+var url_prefix = location.href.replace('://', '://www1.').replace(/\/with(out)?-ports\/[^\/]+$/, '');
+var url = url_prefix + '/without-ports/020-1.html';
+iframe.src = url;
+document.body.appendChild(iframe);
+</script>
+<div id=log></div>
+<script>
+var t = async_test();
+onload = t.step_func(function() {
+ window[0].postMessage(1, '*');
+ window[1].postMessage(2, '*');
+ var i = 0;
+ onmessage = t.step_func(function(e) {
+ i++;
+ assert_equals(e.data[0], i);
+ assert_equals(e.data[1], location.protocol + '//' + location.host);
+ if (i === 2) {
+ t.done();
+ }
+ });
+ setTimeout(t.step_func(function() { assert_unreached("Only got " + i + " events before timeout, expected 2")}), 1000);
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/webmessaging/without-ports/023.html b/tests/wpt/web-platform-tests/webmessaging/without-ports/023.html
new file mode 100644
index 00000000000..1e12ac4a55e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/without-ports/023.html
@@ -0,0 +1,29 @@
+<!doctype html>
+<title>Object cloning: own properties only, don't follow prototype</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var Parent = function(){
+ this.c = "xyz";
+};
+
+var Child = function(a, b) {
+ this.a = a;
+ this.b = b;
+};
+Child.prototype = new Parent;
+
+async_test(function() {
+ var obj = new Child(1, 2);
+ var ch = new MessageChannel();
+ ch.port1.onmessage = this.step_func(function(e) {
+ for (var i in e.data.obj)
+ assert_not_equals(i, 'c');
+ this.done();
+ });
+ ch.port2.start();
+ ch.port2.postMessage({obj: obj});
+});
+
+</script>
diff --git a/tests/wpt/web-platform-tests/webmessaging/without-ports/024.html b/tests/wpt/web-platform-tests/webmessaging/without-ports/024.html
new file mode 100644
index 00000000000..8d99994599c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/without-ports/024.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<title>Object cloning: throw an exception if function values encountered</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+test(function() {
+ var obj = { f : function(){}};
+ var ch = new MessageChannel();
+ ch.port1.onmessage = function(){};
+ ch.port2.start();
+ assert_throws('DATA_CLONE_ERR', function() { ch.port2.postMessage({obj: obj}); });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/webmessaging/without-ports/025-1.js b/tests/wpt/web-platform-tests/webmessaging/without-ports/025-1.js
new file mode 100644
index 00000000000..b1e38b125cf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/without-ports/025-1.js
@@ -0,0 +1,10 @@
+var ch = new MessageChannel();
+var pass1 = false;
+var pass2 = false;
+try {
+ pass1 = ch.port1 instanceof MessagePort;
+ try { var p = new MessagePort(); } catch(e) { pass2 = e instanceof TypeError; }
+} catch (e) {
+ ;
+}
+postMessage([pass1, pass2]);
diff --git a/tests/wpt/web-platform-tests/webmessaging/without-ports/025.html b/tests/wpt/web-platform-tests/webmessaging/without-ports/025.html
new file mode 100644
index 00000000000..3239d9dd290
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/without-ports/025.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<title>MessagePort constructor properties</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+ var ch = new MessageChannel();
+ assert_true(ch.port1 instanceof MessagePort, "MessageChannel's port not an instance of MessagePort");
+ assert_throws(new TypeError(), function () { var p = new MessagePort();}, "MessagePort is [[Callable]]");
+ var w = new Worker("025-1.js");
+ w.onmessage = this.step_func(function(e) {
+ assert_true(e.data[0], "Worker MessageChannel's port not an instance of MessagePort");
+ assert_true(e.data[1], "Worker MessagePort is [[Callable]]");
+ this.done();
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/webmessaging/without-ports/026.html b/tests/wpt/web-platform-tests/webmessaging/without-ports/026.html
new file mode 100644
index 00000000000..e8d799c5d25
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/without-ports/026.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<title>Cloning objects with getter properties</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+ var obj = {};
+ obj.__defineGetter__( "field", function(){ throw new Error("getter_should_propagate_exceptions"); });
+
+ assert_throws(new Error("getter_should_propagate_exceptions"), function() {
+ postMessage(obj, '*');
+ });
+ this.done();
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/webmessaging/without-ports/027.html b/tests/wpt/web-platform-tests/webmessaging/without-ports/027.html
new file mode 100644
index 00000000000..36aa9446a5e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/without-ports/027.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<title>Cloning objects, preserving sharing</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+ var obj1 = {o: 1};
+ var obj2 = {d: obj1};
+ var obj3 = {d: obj1};
+ var obj_dag = {b: obj2, c: obj3};
+
+ postMessage(obj_dag, '*');
+ onmessage = this.step_func(function(e) {
+ assert_equals(e.data.b.d, e.data.c.d);
+ this.done();
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/webmessaging/without-ports/028.html b/tests/wpt/web-platform-tests/webmessaging/without-ports/028.html
new file mode 100644
index 00000000000..dc5e6d663ef
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/without-ports/028.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<title>Cloning objects, preserving sharing #2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<canvas id="a" width=30 height=30></canvas>
+<div id=log></div>
+<script>
+async_test(function() {
+ var img_data = null;
+ var canvas = document.getElementsByTagName("canvas")[0];
+ var context = canvas.getContext("2d");
+ img_data = context.getImageData(0, 0, 30, 30);
+ var obj = {a: img_data, b: {c: img_data, d: 3}};
+ postMessage(obj, '*');
+ onmessage = this.step_func(function(e) {
+ assert_equals(e.data.a, e.data.b.c);
+ this.done();
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/webmessaging/without-ports/029.html b/tests/wpt/web-platform-tests/webmessaging/without-ports/029.html
new file mode 100644
index 00000000000..4b1b38f741c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webmessaging/without-ports/029.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<title>Check that getters don't linger after deletion wrt cloning</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+ var obj = {};
+ obj.__defineGetter__( "a", function(){ return 2; } );
+ obj.__defineSetter__( "a", function(v){ return; } );
+ delete obj.a;
+ obj.a = 2;
+
+ postMessage(obj, '*');
+ onmessage = this.step_func(function(e) {
+ assert_equals(e.data.a, 2);
+ this.done();
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/webrtc/simplecall.html b/tests/wpt/web-platform-tests/webrtc/simplecall.html
new file mode 100644
index 00000000000..282bf341d4b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webrtc/simplecall.html
@@ -0,0 +1,126 @@
+<!doctype html>
+<!--
+To quickly iterate when developing this test, use --use-fake-ui-for-media-stream
+for Chrome and set the media.navigator.permission.disabled property to true in
+Firefox. You must either have a webcam/mic available on the system or use for
+instance --use-fake-device-for-media-stream for Chrome.
+-->
+
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>RTCPeerConnection Connection Test</title>
+</head>
+<body>
+ <div id="log"></div>
+ <div>
+ <video id="local-view" autoplay="autoplay"></video>
+ <video id="remote-view" autoplay="autoplay"/>
+ </video>
+ </div>
+
+ <!-- These files are in place when executing on W3C. -->
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/common/vendor-prefix.js"
+ data-prefixed-objects=
+ '[{"ancestors":["navigator"], "name":"getUserMedia"},
+ {"ancestors":["window"], "name":"RTCPeerConnection"},
+ {"ancestors":["window"], "name":"RTCSessionDescription"},
+ {"ancestors":["window"], "name":"RTCIceCandidate"}]'
+ data-prefixed-prototypes=
+ '[{"ancestors":["HTMLMediaElement"],"name":"srcObject"}]'>
+ </script>
+ <script type="text/javascript">
+ var test = async_test('Can set up a basic WebRTC call.', {timeout: 5000});
+
+ var gFirstConnection = null;
+ var gSecondConnection = null;
+
+ function getUserMediaOkCallback(localStream) {
+ gFirstConnection = new RTCPeerConnection(null, null);
+ gFirstConnection.onicecandidate = onIceCandidateToFirst;
+ gFirstConnection.addStream(localStream);
+ gFirstConnection.createOffer(onOfferCreated, failed('createOffer'));
+
+ var videoTag = document.getElementById('local-view');
+ videoTag.srcObject = localStream;
+ };
+
+ var onOfferCreated = test.step_func(function(offer) {
+ gFirstConnection.setLocalDescription(offer);
+
+ // This would normally go across the application's signaling solution.
+ // In our case, the "signaling" is to call this function.
+ receiveCall(offer.sdp);
+ });
+
+ function receiveCall(offerSdp) {
+ gSecondConnection = new RTCPeerConnection(null, null);
+ gSecondConnection.onicecandidate = onIceCandidateToSecond;
+ gSecondConnection.onaddstream = onRemoteStream;
+
+ var parsedOffer = new RTCSessionDescription({ type: 'offer',
+ sdp: offerSdp });
+ gSecondConnection.setRemoteDescription(parsedOffer);
+
+ gSecondConnection.createAnswer(onAnswerCreated,
+ failed('createAnswer'));
+ };
+
+ var onAnswerCreated = test.step_func(function(answer) {
+ gSecondConnection.setLocalDescription(answer);
+
+ // Similarly, this would go over the application's signaling solution.
+ handleAnswer(answer.sdp);
+ });
+
+ function handleAnswer(answerSdp) {
+ var parsedAnswer = new RTCSessionDescription({ type: 'answer',
+ sdp: answerSdp });
+ gFirstConnection.setRemoteDescription(parsedAnswer);
+
+ // Call negotiated: done.
+ test.done();
+ };
+
+ // Note: the ice candidate handlers are special. We can not wrap them in test
+ // steps since that seems to cause some kind of starvation that prevents the
+ // call of being set up. Unfortunately we cannot report errors in here.
+ var onIceCandidateToFirst = function(event) {
+ // If event.candidate is null = no more candidates.
+ if (event.candidate) {
+ var candidate = new RTCIceCandidate(event.candidate);
+ gSecondConnection.addIceCandidate(candidate);
+ }
+ };
+
+ var onIceCandidateToSecond = function(event) {
+ if (event.candidate) {
+ var candidate = new RTCIceCandidate(event.candidate);
+ gFirstConnection.addIceCandidate(candidate);
+ }
+ };
+
+ var onRemoteStream = test.step_func(function(event) {
+ var videoTag = document.getElementById('remote-view');
+ videoTag.srcObject = event.stream;
+ });
+
+ // Returns a suitable error callback.
+ function failed(function_name) {
+ return test.step_func(function() {
+ assert_unreached('WebRTC called error callback for ' + function_name);
+ });
+ }
+
+ // This function starts the test.
+ test.step(function() {
+ navigator.getUserMedia({ video: true, audio: true },
+ getUserMediaOkCallback,
+ failed('getUserMedia'));
+ });
+</script>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Close-0.htm b/tests/wpt/web-platform-tests/websockets/Close-0.htm
new file mode 100644
index 00000000000..e6496d9909b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Close-0.htm
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Close WebSocket - Code is 0</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var test = async_test("W3C WebSocket API - Create WebSocket - Close the Connection - close(0) - INVALID_ACCESS_ERR is thrown");
+
+ var wsocket = CreateWebSocket(false, false, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', test.step_func(function (evt) {
+ assert_throws("INVALID_ACCESS_ERR", function () { wsocket.close(0, "Close not in range 3000-4999") });
+ test.done();
+ }), true);
+ </script>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Close-1000-reason.htm b/tests/wpt/web-platform-tests/websockets/Close-1000-reason.htm
new file mode 100644
index 00000000000..88fbc611640
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Close-1000-reason.htm
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Close WebSocket - Code is 1000 and reason</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var testOpen = async_test("W3C WebSocket API - Create WebSocket - Close the Connection - Connection should be opened");
+ var testClose = async_test("W3C WebSocket API - Create WebSocket - Close the Connection - close(1000, reason) - readyState should be in CLOSED state and wasClean is TRUE - Connection should be closed");
+
+ var wsocket = CreateWebSocket(false, false, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', testOpen.step_func(function (evt) {
+ wsocket.close(1000, "Clean Close");
+ isOpenCalled = true;
+ testOpen.done();
+ }), true);
+
+ wsocket.addEventListener('close', testClose.step_func(function (evt) {
+ assert_true(isOpenCalled, "WebSocket connection should be opened");
+ assert_equals(wsocket.readyState, 3, "readyState should be 3(CLOSED)");
+ assert_equals(evt.wasClean, true, "wasClean should be TRUE");
+ testClose.done();
+ }), true);
+
+ </script>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Close-1000.htm b/tests/wpt/web-platform-tests/websockets/Close-1000.htm
new file mode 100644
index 00000000000..d1711d924f6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Close-1000.htm
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Close WebSocket - Code is 1000</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var testOpen = async_test("W3C WebSocket API - Create WebSocket - Connection should be opened");
+ var testClose = async_test("W3C WebSocket API - Create WebSocket - Close the Connection - close(1000) - readyState should be in CLOSED state and wasClean is TRUE - Connection should be closed");
+
+ var wsocket = CreateWebSocket(false, false, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', testOpen.step_func(function (evt) {
+ wsocket.close(1000);
+ isOpenCalled = true;
+ testOpen.done();
+ }), true);
+
+ wsocket.addEventListener('close', testClose.step_func(function (evt) {
+ assert_true(isOpenCalled, "WebSocket connection should be opened");
+ assert_equals(wsocket.readyState, 3, "readyState should be 3(CLOSED)");
+ assert_equals(evt.wasClean, true, "wasClean should be TRUE");
+ testClose.done();
+ }), true);
+
+ </script>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Close-NaN.htm b/tests/wpt/web-platform-tests/websockets/Close-NaN.htm
new file mode 100644
index 00000000000..05b471fc558
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Close-NaN.htm
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Close WebSocket - Code is NaN</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var test = async_test("W3C WebSocket API - Create WebSocket - Close the Connection - close(NaN) - INVALID_ACCESS_ERR is thrown");
+
+ var wsocket = CreateWebSocket(false, false, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', test.step_func(function (evt) {
+ assert_throws("INVALID_ACCESS_ERR", function () { wsocket.close(NaN) });
+ test.done();
+ }), true);
+ </script>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Close-Reason-124Bytes.htm b/tests/wpt/web-platform-tests/websockets/Close-Reason-124Bytes.htm
new file mode 100644
index 00000000000..bfc12e33733
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Close-Reason-124Bytes.htm
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Close WebSocket - Reason is more than 123 bytes long</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var test = async_test("W3C WebSocket API - Create WebSocket - Close the Connection - close(code, 'reason more than 123 bytes') - SYNTAX_ERR is thrown");
+
+ var wsocket = CreateWebSocket(false, false, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', test.step_func(function (evt) {
+ var reason = "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123";
+ assert_equals(reason.length, 124);
+ assert_throws("SYNTAX_ERR", function () { wsocket.close(1000, reason) });
+ test.done();
+ }), true);
+ </script>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Close-null.htm b/tests/wpt/web-platform-tests/websockets/Close-null.htm
new file mode 100644
index 00000000000..165fc2d0dfb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Close-null.htm
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Close WebSocket - Code is null</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var test = async_test("W3C WebSocket API - Create WebSocket - Close the Connection - close(null) - INVALID_ACCESS_ERR is thrown");
+
+ var wsocket = CreateWebSocket(false, false, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', test.step_func(function (evt) {
+ assert_throws("INVALID_ACCESS_ERR", function () { wsocket.close(null) });
+ test.done();
+ }), true);
+ </script>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Close-reason-unpaired-surrogates.htm b/tests/wpt/web-platform-tests/websockets/Close-reason-unpaired-surrogates.htm
new file mode 100644
index 00000000000..cabbe97ca61
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Close-reason-unpaired-surrogates.htm
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Close WebSocket - Reason with unpaired surrogates</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var testOpen = async_test("W3C WebSocket API - Create WebSocket - Close the Connection - close(reason with unpaired surrogates) - connection should get opened");
+ var testClose = async_test("W3C WebSocket API - Create WebSocket - Close the Connection - close(reason with unpaired surrogates) - connection should get closed");
+
+ var wsocket = CreateWebSocket(false, false, false);
+ var isOpenCalled = false;
+ var replacementChar = "\uFFFD";
+ var reason = "\uD807";
+
+ wsocket.addEventListener('open', testOpen.step_func(function (evt) {
+ wsocket.close(1000, reason);
+ isOpenCalled = true;
+ testOpen.done();
+ }), true);
+
+ wsocket.addEventListener('close', testClose.step_func(function (evt) {
+ assert_true(isOpenCalled, "WebSocket connection should be opened");
+ assert_equals(evt.reason, replacementChar, "reason replaced with replacement character");
+ testClose.done();
+ }), true);
+
+ </script>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Close-string.htm b/tests/wpt/web-platform-tests/websockets/Close-string.htm
new file mode 100644
index 00000000000..75a3a90ac66
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Close-string.htm
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Close WebSocket - Code is String</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var test = async_test("W3C WebSocket API - Create WebSocket - Close the Connection - close(String) - INVALID_ACCESS_ERR is thrown");
+
+ var wsocket = CreateWebSocket(false, false, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', test.step_func(function (evt) {
+ assert_throws("INVALID_ACCESS_ERR", function () { wsocket.close('string') });
+ test.done();
+ }), true);
+ </script>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Close-undefined.htm b/tests/wpt/web-platform-tests/websockets/Close-undefined.htm
new file mode 100644
index 00000000000..4f67c067e74
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Close-undefined.htm
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Close WebSocket - Code is undefined</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var test = async_test("W3C WebSocket API - Create WebSocket - Close the Connection - close(undefined) - INVALID_ACCESS_ERR is thrown");
+
+ var wsocket = CreateWebSocket(false, false, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', test.step_func(function (evt) {
+ assert_throws("INVALID_ACCESS_ERR", function () { wsocket.close(undefined) });
+ test.done();
+ }), true);
+ </script>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Create-Secure-blocked-port.htm b/tests/wpt/web-platform-tests/websockets/Create-Secure-blocked-port.htm
new file mode 100644
index 00000000000..8a4866d0724
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Create-Secure-blocked-port.htm
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Create Secure WebSocket - blocked port</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script>
+ test(function () {
+ var wsocket;
+ var blockedPort = 25;
+ assert_throws("SECURITY_ERR", function () { wsocket = CreateWebSocketWithBlockedPort(blockedPort) });
+ }, "W3C WebSocket API - Create Secure WebSocket - Pass a URL with a blocked port - SECURITY_ERR should be thrown")
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Create-Secure-extensions-empty.htm b/tests/wpt/web-platform-tests/websockets/Create-Secure-extensions-empty.htm
new file mode 100644
index 00000000000..ea1774d9618
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Create-Secure-extensions-empty.htm
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Create Secure WebSocket</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var testOpen = async_test("W3C WebSocket API - Create Secure WebSocket - wsocket.extensions should be set to '' after connection is established - Connection should be opened");
+ var testClose = async_test("W3C WebSocket API - Create Secure WebSocket - wsocket.extensions should be set to '' after connection is established - Connection should be closed");
+
+ var wsocket = CreateWebSocket(true, false, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', testOpen.step_func(function (evt) {
+ assert_equals(wsocket.extensions, "", "extensions should be empty");
+ wsocket.close();
+ isOpenCalled = true;
+ testOpen.done();
+ }), true);
+
+ wsocket.addEventListener('close', testClose.step_func(function (evt) {
+ assert_true(isOpenCalled, "WebSocket connection should be closed");
+ assert_equals(evt.wasClean, true, "wasClean should be true");
+ testClose.done();
+ }), true);
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Create-Secure-url-with-space.htm b/tests/wpt/web-platform-tests/websockets/Create-Secure-url-with-space.htm
new file mode 100644
index 00000000000..f5fc467b4ad
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Create-Secure-url-with-space.htm
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Create Secure WebSocket - url with space</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+ test(function () {
+ var wsocket;
+ var spaceUrl = "web platform.test";
+ assert_throws("SYNTAX_ERR", function () { wsocket = CreateWebSocketWithSpaceInUrl(spaceUrl) });
+ }, "W3C WebSocket API - Create Secure WebSocket - Pass a URL with a space - SYNTAX_ERR should be thrown")
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Create-Secure-valid-url-array-protocols.htm b/tests/wpt/web-platform-tests/websockets/Create-Secure-valid-url-array-protocols.htm
new file mode 100644
index 00000000000..427f94499c6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Create-Secure-valid-url-array-protocols.htm
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Create Secure WebSocket with valid url and array of protocols</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var testOpen = async_test("W3C WebSocket API - Create Secure WebSocket - Pass a valid URL and array of protocol strings - Connection should be opened");
+ var testClose = async_test("W3C WebSocket API - Create Secure WebSocket - Pass a valid URL and array of protocol strings - Connection should be closed");
+
+ var wsocket = CreateWebSocket(true, false, true);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', testOpen.step_func(function (evt) {
+ assert_equals(wsocket.readyState, 1, "readyState should be 1(OPEN)");
+ wsocket.close();
+ isOpenCalled = true;
+ testOpen.done();
+ }), true);
+
+ wsocket.addEventListener('close', testClose.step_func(function (evt) {
+ assert_true(isOpenCalled, "WebSocket connection should be open");
+ assert_equals(evt.wasClean, true, "wasClean should be true");
+ testClose.done();
+ }), true);
+
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Create-Secure-valid-url-binaryType-blob.htm b/tests/wpt/web-platform-tests/websockets/Create-Secure-valid-url-binaryType-blob.htm
new file mode 100644
index 00000000000..a9f772ffdf3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Create-Secure-valid-url-binaryType-blob.htm
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Create Secure WebSocket - binaryType set correctly</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var testOpen = async_test("W3C WebSocket API - Create Secure WebSocket - wsocket.binaryType should be set to 'blob' after connection is established - Connection should be opened");
+ var testClose = async_test("W3C WebSocket API - Create Secure WebSocket - wsocket.binaryType should be set to 'blob' after connection is established - Connection should be closed");
+
+ var wsocket = CreateWebSocket(true, false, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', testOpen.step_func(function (evt) {
+ assert_equals(wsocket.binaryType, "blob", "binaryType should be set to Blob");
+ wsocket.close();
+ isOpenCalled = true;
+ testOpen.done();
+ }), true);
+
+ wsocket.addEventListener('close', testClose.step_func(function (evt) {
+ assert_true(isOpenCalled, "WebSocket connection should be open");
+ assert_equals(evt.wasClean, true, "wasClean should be true");
+ testClose.done();
+ }), true);
+
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Create-Secure-valid-url-protocol-setCorrectly.htm b/tests/wpt/web-platform-tests/websockets/Create-Secure-valid-url-protocol-setCorrectly.htm
new file mode 100644
index 00000000000..a6b429397b3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Create-Secure-valid-url-protocol-setCorrectly.htm
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Create Secure WebSocket and verify if protocol is set correctly after connection</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var testOpen = async_test("W3C WebSocket API - Create Secure WebSocket - Pass a valid URL and protocol string - protocol should be set correctly - Connection should be opened");
+ var testClose = async_test("W3C WebSocket API - Create Secure WebSocket - Pass a valid URL and protocol string - Connection should be closed");
+
+ var wsocket = CreateWebSocket(true, true, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', testOpen.step_func(function (evt) {
+ assert_equals(wsocket.protocol, __PROTOCOL, "protocol should be set to echo");
+ wsocket.close();
+ isOpenCalled = true;
+ testOpen.done();
+ }), true);
+
+ wsocket.addEventListener('close', testClose.step_func(function (evt) {
+ assert_true(isOpenCalled, "WebSocket connection should be open");
+ assert_equals(evt.wasClean, true, "wasClean should be true");
+ testClose.done();
+ }), true);
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Create-Secure-valid-url-protocol-string.htm b/tests/wpt/web-platform-tests/websockets/Create-Secure-valid-url-protocol-string.htm
new file mode 100644
index 00000000000..6fcaaec6f07
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Create-Secure-valid-url-protocol-string.htm
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Create Secure WebSocket with valid url and protocol string</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var testOpen = async_test("W3C WebSocket API - Create Secure WebSocket - Check readyState is 1");
+ var testClose = async_test("W3C WebSocket API - Create Secure WebSocket - Pass a valid URL and protocol string - Connection should be closed");
+
+ var wsocket = CreateWebSocket(true, true, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', testOpen.step_func(function (evt) {
+ assert_equals(wsocket.readyState, 1, "readyState should be 1(OPEN)");
+ wsocket.close();
+ isOpenCalled = true;
+ testOpen.done();
+ }), true);
+
+ wsocket.addEventListener('close', testClose.step_func(function (evt) {
+ assert_true(isOpenCalled, "WebSocket connection should be open");
+ assert_equals(evt.wasClean, true, "wasClean should be true");
+ testClose.done();
+ }), true);
+
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Create-Secure-valid-url.htm b/tests/wpt/web-platform-tests/websockets/Create-Secure-valid-url.htm
new file mode 100644
index 00000000000..2e448f24ec6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Create-Secure-valid-url.htm
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Create Secure WebSocket with valid url</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var testOpen = async_test("W3C WebSocket API - Create Secure WebSocket - Pass a valid URL - Connection should be opened");
+ var testClose = async_test("W3C WebSocket API - Create Secure WebSocket - Pass a valid URL - Connection should be closed");
+
+ var wsocket = CreateWebSocket(true, false, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', testOpen.step_func(function (evt) {
+ assert_equals(wsocket.readyState, 1, "readyState should be 1(OPEN)");
+ wsocket.close();
+ isOpenCalled = true;
+ testOpen.done();
+ }), true);
+
+ wsocket.addEventListener('close', testClose.step_func(function (evt) {
+ assert_true(isOpenCalled, "WebSocket connection should be open");
+ assert_equals(evt.wasClean, true, "wasClean should be true");
+ testClose.done();
+ }), true);
+
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Create-Secure-verify-url-set-non-default-port.htm b/tests/wpt/web-platform-tests/websockets/Create-Secure-verify-url-set-non-default-port.htm
new file mode 100644
index 00000000000..01cb239e7ba
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Create-Secure-verify-url-set-non-default-port.htm
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Create Secure WebSocket - wsocket.url is set correctly - non default port</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+ test(function () {
+ var urlNonDefaultPort = "wss://" + __SERVER__NAME + ":" + __NEW__SECURE__PORT + "/" + __PATH;
+ var wsocket = new WebSocket(urlNonDefaultPort);
+ assert_equals(wsocket.url, urlNonDefaultPort, "wsocket.url is set correctly");
+ }, "W3C WebSocket API - Create Secure WebSocket - wsocket.url should be set correctly")
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Create-invalid-urls.htm b/tests/wpt/web-platform-tests/websockets/Create-invalid-urls.htm
new file mode 100644
index 00000000000..483ba29ccc8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Create-invalid-urls.htm
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Create WebSocket - pass in list of invalid urls</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+ var wsocket;
+ test(function() {
+ assert_throws("SYNTAX_ERR", function () { wsocket = new WebSocket("/echo") });
+ }, "Url is /echo - should throw SYNTAX_ERR");
+
+ test(function () {
+ assert_throws("SYNTAX_ERR", function () { wsocket = new WebSocket("mailto:microsoft@microsoft.com") });
+ }, "Url is a mail address - should throw SYNTAX_ERR");
+
+ test(function () {
+ assert_throws("SYNTAX_ERR", function () { wsocket = new WebSocket("about:blank") });
+ }, "Url is about:blank - should throw SYNTAX_ERR");
+
+ test(function () {
+ assert_throws("SYNTAX_ERR", function () { wsocket = new WebSocket("?test") });
+ }, "Url is ?test - should throw SYNTAX_ERR");
+
+ test(function () {
+ assert_throws("SYNTAX_ERR", function () { wsocket = new WebSocket("#test") });
+ }, "Url is #test - should throw SYNTAX_ERR");
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Create-non-absolute-url.htm b/tests/wpt/web-platform-tests/websockets/Create-non-absolute-url.htm
new file mode 100644
index 00000000000..5fa19c9e614
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Create-non-absolute-url.htm
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Create WebSocket - non absolute url</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+ test(function () {
+ var wsocket;
+ assert_throws("SYNTAX_ERR", function () { wsocket = CreateWebSocketNonAbsolute() });
+ }, "W3C WebSocket API - Create WebSocket - Pass a non absolute URL - SYNTAX_ERR is thrown")
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Create-nonAscii-protocol-string.htm b/tests/wpt/web-platform-tests/websockets/Create-nonAscii-protocol-string.htm
new file mode 100644
index 00000000000..7c758470187
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Create-nonAscii-protocol-string.htm
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Create WebSocket - non ascii protocol string</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+ if(window.WebSocket) {
+ test(function () {
+ var nonAsciiProtocol = "\u0080echo";
+ var wsocket;
+ assert_throws("SYNTAX_ERR", function () { wsocket = CreateWebSocketNonAsciiProtocol(nonAsciiProtocol) });
+ }, "W3C WebSocket API - Create WebSocket - Pass a valid URL and a protocol string with non-ascii values - SYNTAX_ERR is thrown")
+ }
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Create-protocol-with-space.htm b/tests/wpt/web-platform-tests/websockets/Create-protocol-with-space.htm
new file mode 100644
index 00000000000..54100be9afc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Create-protocol-with-space.htm
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Create WebSocket - protocol with space</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+ test(function () {
+ var wsocket;
+ assert_throws("SYNTAX_ERR", function () { wsocket = CreateWebSocketWithSpaceInProtocol("ec ho") });
+ }, "W3C WebSocket API - Create WebSocket - Pass a valid URL and a protocol string with a space in it - SYNTAX_ERR is thrown")
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Create-protocols-repeated.htm b/tests/wpt/web-platform-tests/websockets/Create-protocols-repeated.htm
new file mode 100644
index 00000000000..eaad41d9bf4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Create-protocols-repeated.htm
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Create WebSocket - repeated protocols</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+ test(function () {
+ var wsocket;
+ assert_throws("SYNTAX_ERR", function () { wsocket = CreateWebSocketWithRepeatedProtocols() });
+ }, "W3C WebSocket API - Create WebSocket - Pass a valid URL and an array of protocol strings with repeated values - SYNTAX_ERR is thrown")
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Create-valid-url-array-protocols.htm b/tests/wpt/web-platform-tests/websockets/Create-valid-url-array-protocols.htm
new file mode 100644
index 00000000000..ef979114a8a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Create-valid-url-array-protocols.htm
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Create WebSocket with valid url and array of protocols</title>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var testOpen = async_test("W3C WebSocket API - Create WebSocket - Pass a valid URL and array of protocol strings - Connection should be opened");
+ var testClose = async_test("W3C WebSocket API - Create WebSocket - Pass a valid URL and array of protocol strings - Connection should be closed");
+
+ var wsocket = CreateWebSocket(false, false, true);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', testOpen.step_func(function (evt) {
+ assert_equals(wsocket.readyState, 1, "readyState should be 1(OPEN)");
+ wsocket.close();
+ isOpenCalled = true;
+ testOpen.done();
+ }), true);
+
+ wsocket.addEventListener('close', testClose.step_func(function (evt) {
+ assert_true(isOpenCalled, "WebSocket connection should be open");
+ assert_equals(evt.wasClean, true, "wasClean should be true");
+ testClose.done();
+ }), true);
+
+ </script>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Create-valid-url-protocol-empty.htm b/tests/wpt/web-platform-tests/websockets/Create-valid-url-protocol-empty.htm
new file mode 100644
index 00000000000..9961075f3ab
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Create-valid-url-protocol-empty.htm
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Create WebSocket - wsocket.protocol is empty before connection is established</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+ test(function () {
+ var wsocket = CreateWebSocket(false, true, false);
+ assert_equals(wsocket.protocol, "", "protocol should be empty");
+ wsocket.close();
+ }, "W3C WebSocket API - Create WebSocket - wsocket.protocol should be empty before connection is established")
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Create-valid-url-protocol.htm b/tests/wpt/web-platform-tests/websockets/Create-valid-url-protocol.htm
new file mode 100644
index 00000000000..3457b704e50
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Create-valid-url-protocol.htm
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Create WebSocket with a valid url and protocol string</title>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var testOpen = async_test("W3C WebSocket API - Create WebSocket - Pass a valid URL and a protocol string - Connection should be opened");
+ var testClose = async_test("W3C WebSocket API - Create WebSocket - Pass a valid URL and a protocol string - Connection should be closed");
+
+ var wsocket = CreateWebSocket(false, true, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', testOpen.step_func(function (evt) {
+ assert_equals(wsocket.readyState, 1, "readyState should be 1(OPEN)");
+ wsocket.close();
+ isOpenCalled = true;
+ testOpen.done();
+ }), true);
+
+ wsocket.addEventListener('close', testClose.step_func(function (evt) {
+ assert_true(isOpenCalled, "WebSocket connection should be open");
+ assert_equals(evt.wasClean, true, "wasClean should be true");
+ testClose.done();
+ }), true);
+
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Create-valid-url.htm b/tests/wpt/web-platform-tests/websockets/Create-valid-url.htm
new file mode 100644
index 00000000000..7803a6e9748
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Create-valid-url.htm
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Create WebSocket with valid url</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var testOpen = async_test("W3C WebSocket API - Create WebSocket - Pass a valid URL - Connection should be opened");
+ var testClose = async_test("W3C WebSocket API - Create WebSocket - Pass a valid URL - Connection should be closed");
+
+ var wsocket = CreateWebSocket(false, false, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', testOpen.step_func(function (evt) {
+ assert_equals(wsocket.readyState, 1, "readyState should be 1(OPEN)");
+ wsocket.close();
+ isOpenCalled = true;
+ testOpen.done();
+ }), true);
+
+ wsocket.addEventListener('close', testClose.step_func(function (evt) {
+ assert_true(isOpenCalled, "WebSocket connection should be open");
+ assert_equals(evt.wasClean, true, "wasClean should be true");
+ testClose.done();
+ }), true);
+
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Create-verify-url-set-non-default-port.htm b/tests/wpt/web-platform-tests/websockets/Create-verify-url-set-non-default-port.htm
new file mode 100644
index 00000000000..08a01cb52c0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Create-verify-url-set-non-default-port.htm
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Create WebSocket - wsocket.url is set correctly - non default port</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+ test(function () {
+ var urlNonDefaultPort = "ws://" + __SERVER__NAME + ":" + __NEW__PORT + "/" + __PATH;
+ var wsocket = new WebSocket(urlNonDefaultPort);
+ assert_equals(wsocket.url, urlNonDefaultPort, "wsocket.url is set correctly");
+ }, "W3C WebSocket API - Create WebSocket - wsocket.url should be set correctly");
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Create-wrong-scheme.htm b/tests/wpt/web-platform-tests/websockets/Create-wrong-scheme.htm
new file mode 100644
index 00000000000..6507761882d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Create-wrong-scheme.htm
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Create WebSocket - non ws/wss scheme in url</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+ test(function () {
+ var wsocket;
+ assert_throws("SYNTAX_ERR", function () { wsocket = CreateWebSocketNonWsScheme() });
+ }, "W3C WebSocket API - Create WebSocket - Pass a URL with a non ws/wss scheme - SYNTAX_ERR is thrown")
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/README.md b/tests/wpt/web-platform-tests/websockets/README.md
new file mode 100644
index 00000000000..4ad032e089f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/README.md
@@ -0,0 +1,10 @@
+This directory contains the WebSocket API test suite.
+
+The following document contains a list of each test file in the test suite and the results of running the test file on several browsers <http://www.w3.org/wiki/Webapps/Interop/WebSockets>.
+
+To run this test suite within a browser, go to: <http://w3c-test.org/web-platform-tests/master/websockets/>.
+
+The latest Editor's Draft of WebSocket API is: <http://dev.w3.org/html5/websockets/>.
+
+The latest W3C Technical Report of WebSocket API is <http://www.w3.org/TR/websockets/>.
+
diff --git a/tests/wpt/web-platform-tests/websockets/Secure-Close-0.htm b/tests/wpt/web-platform-tests/websockets/Secure-Close-0.htm
new file mode 100644
index 00000000000..1babd4b4825
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Secure-Close-0.htm
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Close Secure WebSocket - Code is 0</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var test = async_test("W3C WebSocket API - Create Secure WebSocket - Close the Connection - close(0) - INVALID_ACCESS_ERR is thrown");
+
+ var wsocket = CreateWebSocket(true, false, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', test.step_func(function (evt) {
+ assert_throws("INVALID_ACCESS_ERR", function () { wsocket.close(0, "Close not in range 3000-4999") });
+ test.done();
+ }), true);
+ </script>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Secure-Close-1000-reason.htm b/tests/wpt/web-platform-tests/websockets/Secure-Close-1000-reason.htm
new file mode 100644
index 00000000000..750c43c5ae3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Secure-Close-1000-reason.htm
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Close Secure WebSocket - Code is 1000 and reason</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var testOpen = async_test("W3C WebSocket API - Create Secure WebSocket - Close the Connection - close(1000, reason) - Connection should be opened");
+ var testClose = async_test("W3C WebSocket API - Create Secure WebSocket - Close the Connection - close(1000, reason) - readyState should be in CLOSED state and wasClean is TRUE - Connection should be closed");
+
+ var wsocket = CreateWebSocket(true, false, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', testOpen.step_func(function (evt) {
+ wsocket.close(1000, "Clean Close");
+ isOpenCalled = true;
+ testOpen.done();
+ }), true);
+
+ wsocket.addEventListener('close', testClose.step_func(function (evt) {
+ assert_true(isOpenCalled, "WebSocket connection should be open");
+ assert_equals(wsocket.readyState, 3, "readyState should be 3(CLOSED)");
+ assert_equals(evt.wasClean, true, "wasClean should be TRUE");
+ testClose.done();
+ }), true);
+
+ </script>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Secure-Close-1000-verify-code.htm b/tests/wpt/web-platform-tests/websockets/Secure-Close-1000-verify-code.htm
new file mode 100644
index 00000000000..b0f6c8ea843
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Secure-Close-1000-verify-code.htm
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Close Secure WebSocket - Code is 1000 - verify code in CloseEvent is 1000</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var testOpen = async_test("W3C WebSocket API - Create Secure WebSocket - Close the Connection - close(1000, reason) - Connection should be opened");
+ var testClose = async_test("W3C WebSocket API - Create Secure WebSocket - Close the Connection - close(1000, reason) - event.code == 1000 and event.reason = 'Clean Close'");
+
+ var wsocket = CreateWebSocket(true, false, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', testOpen.step_func(function (evt) {
+ wsocket.close(1000, "Clean Close");
+ isOpenCalled = true;
+ testOpen.done();
+ }), true);
+
+ wsocket.addEventListener('close', testClose.step_func(function (evt) {
+ assert_true(isOpenCalled, "WebSocket connection should be open");
+ assert_equals(evt.code, 1000, "CloseEvent.code should be 1000");
+ assert_equals(evt.reason, "Clean Close", "CloseEvent.reason should be the same as the reason sent in close");
+ testClose.done();
+ }), true);
+
+ </script>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Secure-Close-1000.htm b/tests/wpt/web-platform-tests/websockets/Secure-Close-1000.htm
new file mode 100644
index 00000000000..ebe4f7844c7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Secure-Close-1000.htm
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Close Secure WebSocket - Code is 1000</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var testOpen = async_test("W3C WebSocket API - Create Secure WebSocket - Close the Connection - close(1000) - Connection should be opened");
+ var testClose = async_test("W3C WebSocket API - Create Secure WebSocket - Close the Connection - close(1000) - readyState should be in CLOSED state and wasClean is TRUE - Connection should be closed");
+
+ var wsocket = CreateWebSocket(true, false, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', testOpen.step_func(function (evt) {
+ wsocket.close(1000);
+ isOpenCalled = true;
+ testOpen.done();
+ }), true);
+
+ wsocket.addEventListener('close', testClose.step_func(function (evt) {
+ assert_true(isOpenCalled, "WebSocket connection should be open");
+ assert_equals(wsocket.readyState, 3, "readyState should be 3(CLOSED)");
+ assert_equals(evt.wasClean, true, "wasClean should be TRUE");
+ testClose.done();
+ }), true);
+
+ </script>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Secure-Close-1005-verify-code.htm b/tests/wpt/web-platform-tests/websockets/Secure-Close-1005-verify-code.htm
new file mode 100644
index 00000000000..4d2d81cf1cd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Secure-Close-1005-verify-code.htm
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Close Secure WebSocket - verify return code is 1005</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var testOpen = async_test("W3C WebSocket API - Create Secure WebSocket - Close the Connection - close() - Connection should be opened");
+ var testClose = async_test("W3C WebSocket API - Create Secure WebSocket - Close the Connection - close() - return close code is 1005 - Connection should be closed");
+
+ var wsocket = CreateWebSocket(true, false, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', testOpen.step_func(function (evt) {
+ wsocket.close();
+ isOpenCalled = true;
+ testOpen.done();
+ }), true);
+
+ wsocket.addEventListener('close', testClose.step_func(function (evt) {
+ assert_true(isOpenCalled, "WebSocket connection should be open");
+ assert_equals(evt.code, 1005, "CloseEvent.code should be 1005");
+ assert_equals(evt.reason, "", "CloseEvent.reason should be empty");
+ testClose.done();
+ }), true);
+
+ </script>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Secure-Close-1005.htm b/tests/wpt/web-platform-tests/websockets/Secure-Close-1005.htm
new file mode 100644
index 00000000000..7f6f6e11b44
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Secure-Close-1005.htm
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Close Secure WebSocket - Code is 1005</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var test = async_test("W3C WebSocket API - Create Secure WebSocket - Close the Connection - close(1005) - see '7.1.5. The WebSocket Connection Close Code' in http://www.ietf.org/rfc/rfc6455.txt");
+
+ var wsocket = CreateWebSocket(true, false, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', test.step_func(function (evt) {
+ assert_throws("INVALID_ACCESS_ERR", function () { wsocket.close(1005, "1005 - reserved code") });
+ test.done();
+ }), true);
+ </script>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Secure-Close-2999-reason.htm b/tests/wpt/web-platform-tests/websockets/Secure-Close-2999-reason.htm
new file mode 100644
index 00000000000..0eddc1d6263
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Secure-Close-2999-reason.htm
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Close Secure WebSocket - Code is 2999 and reason</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var test = async_test("W3C WebSocket API - Create Secure WebSocket - Close the Connection - close(2999, reason) - INVALID_ACCESS_ERR is thrown");
+
+ var wsocket = CreateWebSocket(true, false, false);
+
+ wsocket.addEventListener('open', test.step_func(function (evt) {
+ assert_throws("INVALID_ACCESS_ERR", function () { wsocket.close(2999, "Close not in range 3000-4999") });
+ test.done();
+ }), true);
+ </script>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Secure-Close-3000-reason.htm b/tests/wpt/web-platform-tests/websockets/Secure-Close-3000-reason.htm
new file mode 100644
index 00000000000..647bbf2d05a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Secure-Close-3000-reason.htm
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Close Secure WebSocket - Code is 3000 and reason</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var testOpen = async_test("W3C WebSocket API - Create Secure WebSocket - Close the Connection - close(3000, reason) - Connection should be opened");
+ var testClose = async_test("W3C WebSocket API - Create Secure WebSocket - Close the Connection - close(3000, reason) - readyState should be in CLOSED state and wasClean is TRUE - Connection should be closed");
+
+ var wsocket = CreateWebSocket(true, false, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', testOpen.step_func(function (evt) {
+ wsocket.close(3000, "Clean Close with code - 3000");
+ isOpenCalled = true;
+ testOpen.done();
+ }), true);
+
+ wsocket.addEventListener('close', testClose.step_func(function (evt) {
+ assert_true(isOpenCalled, "WebSocket connection should be open");
+ assert_equals(wsocket.readyState, 3, "readyState should be 3(CLOSED)");
+ assert_equals(evt.wasClean, true, "wasClean should be TRUE");
+ testClose.done();
+ }), true);
+
+ </script>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Secure-Close-3000-verify-code.htm b/tests/wpt/web-platform-tests/websockets/Secure-Close-3000-verify-code.htm
new file mode 100644
index 00000000000..5a13d442705
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Secure-Close-3000-verify-code.htm
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Close Secure WebSocket - Code is 3000 - verify code in CloseEvent is 3000</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var testOpen = async_test("W3C WebSocket API - Create Secure WebSocket - Close the Connection - close(3000, reason) - Connection should be opened");
+ var testClose = async_test("W3C WebSocket API - Create Secure WebSocket - Close the Connection - close(3000, reason) - verify return code is 3000 - Connection should be closed");
+
+ var wsocket = CreateWebSocket(true, false, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', testOpen.step_func(function (evt) {
+ wsocket.close(3000, "Clean Close");
+ isOpenCalled = true;
+ testOpen.done();
+ }), true);
+
+ wsocket.addEventListener('close', testClose.step_func(function (evt) {
+ assert_true(isOpenCalled, "WebSocket connection should be open");
+ assert_equals(evt.code, 3000, "CloseEvent.code should be 3000");
+ testClose.done();
+ }), true);
+
+ </script>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Secure-Close-4999-reason.htm b/tests/wpt/web-platform-tests/websockets/Secure-Close-4999-reason.htm
new file mode 100644
index 00000000000..cfa5693f3ba
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Secure-Close-4999-reason.htm
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Close Secure WebSocket - Code is 4999 and reason</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var testOpen = async_test("W3C WebSocket API - Create Secure WebSocket - Close the Connection - close(4999, reason) - Connection should be opened");
+ var testClose = async_test("W3C WebSocket API - Create Secure WebSocket - Close the Connection - close(4999, reason) - readyState should be in CLOSED state and wasClean is TRUE - Connection should be closed");
+
+ var wsocket = CreateWebSocket(true, false, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', testOpen.step_func(function (evt) {
+ wsocket.close(3000, "Clean Close with code - 4999");
+ isOpenCalled = true;
+ testOpen.done();
+ }), true);
+
+ wsocket.addEventListener('close', testClose.step_func(function (evt) {
+ assert_true(isOpenCalled, "WebSocket connection should be open");
+ assert_equals(wsocket.readyState, 3, "readyState should be 3(CLOSED)");
+ assert_equals(evt.wasClean, true, "wasClean should be TRUE");
+ testClose.done();
+ }), true);
+
+ </script>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Secure-Close-NaN.htm b/tests/wpt/web-platform-tests/websockets/Secure-Close-NaN.htm
new file mode 100644
index 00000000000..10013024d93
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Secure-Close-NaN.htm
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Close Secure WebSocket - Code is NaN</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var test = async_test("W3C WebSocket API - Create WebSocket - Close the Connection - close(NaN) - INVALID_ACCESS_ERR is thrown");
+
+ var wsocket = CreateWebSocket(true, false, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', test.step_func(function (evt) {
+ assert_throws("INVALID_ACCESS_ERR", function () { wsocket.close(NaN) });
+ test.done();
+ }), true);
+ </script>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Secure-Close-Reason-124Bytes.htm b/tests/wpt/web-platform-tests/websockets/Secure-Close-Reason-124Bytes.htm
new file mode 100644
index 00000000000..0c0c1b59546
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Secure-Close-Reason-124Bytes.htm
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Close Secure WebSocket - Reason is more than 123 bytes long</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var test = async_test("W3C WebSocket API - Create Secure WebSocket - Close the Connection - close(code, 'reason more than 123 bytes') - SYNTAX_ERR is thrown");
+
+ var wsocket = CreateWebSocket(true, false, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', test.step_func(function (evt) {
+ var reason = "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123";
+ assert_equals(reason.length, 124);
+ assert_throws("SYNTAX_ERR", function () { wsocket.close(1000, reason) });
+ test.done();
+ }), true);
+ </script>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Secure-Close-Reason-Unpaired-surrogates.htm b/tests/wpt/web-platform-tests/websockets/Secure-Close-Reason-Unpaired-surrogates.htm
new file mode 100644
index 00000000000..033555db7d6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Secure-Close-Reason-Unpaired-surrogates.htm
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Close Secure WebSocket - Reason with unpaired surrogates</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var testOpen = async_test("W3C WebSocket API - Create Secure WebSocket - Close the Connection - close(reason with unpaired surrogates) - connection should get opened");
+ var testClose = async_test("W3C WebSocket API - Create Secure WebSocket - Close the Connection - close(reason with unpaired surrogates) - connection should get closed");
+
+ var wsocket = CreateWebSocket(true, false, false);
+ var isOpenCalled = false;
+ var replacementChar = "\uFFFD";
+ var reason = "\uD807";
+
+ wsocket.addEventListener('open', testOpen.step_func(function (evt) {
+ wsocket.close(1000, reason);
+ isOpenCalled = true;
+ testOpen.done();
+ }), true);
+
+ wsocket.addEventListener('close', testClose.step_func(function (evt) {
+ assert_true(isOpenCalled, "WebSocket connection should be opened");
+ assert_equals(evt.reason, replacementChar, "reason replaced with replacement character");
+ testClose.done();
+ }), true);
+
+ </script>
+
+</body>
+</html>
+
diff --git a/tests/wpt/web-platform-tests/websockets/Secure-Close-null.htm b/tests/wpt/web-platform-tests/websockets/Secure-Close-null.htm
new file mode 100644
index 00000000000..30f4935f897
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Secure-Close-null.htm
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Close Secure WebSocket - Code is null</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var test = async_test("W3C WebSocket API - Create WebSocket - Close the Connection - close(null) - INVALID_ACCESS_ERR is thrown");
+
+ var wsocket = CreateWebSocket(true, false, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', test.step_func(function (evt) {
+ assert_throws("INVALID_ACCESS_ERR", function () { wsocket.close(null) });
+ test.done();
+ }), true);
+ </script>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Secure-Close-onlyReason.htm b/tests/wpt/web-platform-tests/websockets/Secure-Close-onlyReason.htm
new file mode 100644
index 00000000000..cad49329c00
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Secure-Close-onlyReason.htm
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Close Secure WebSocket - Only reason</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var test = async_test("W3C WebSocket API - Create Secure WebSocket - Close the Connection - close(only reason) - INVALID_ACCESS_ERR is thrown");
+
+ var wsocket = CreateWebSocket(true, false, false);
+
+ wsocket.addEventListener('open', test.step_func(function (evt) {
+ assert_throws("INVALID_ACCESS_ERR", function () { wsocket.close("Close with only reason") });
+ test.done();
+ }), true);
+ </script>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Secure-Close-readyState-Closed.htm b/tests/wpt/web-platform-tests/websockets/Secure-Close-readyState-Closed.htm
new file mode 100644
index 00000000000..3e7b09c47f7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Secure-Close-readyState-Closed.htm
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Close Secure WebSocket - verify readyState is 3 when onclose is fired</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var testOpen = async_test("W3C WebSocket API - Create Secure WebSocket - Close the Connection - Connection should be opened");
+ var testClose = async_test("W3C WebSocket API - Create Secure WebSocket - Close the Connection - readyState should be in CLOSED state and wasClean is TRUE - Connection should be closed");
+
+ var wsocket = CreateWebSocket(true, false, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', testOpen.step_func(function (evt) {
+ wsocket.close();
+ isOpenCalled = true;
+ testOpen.done();
+ }), true);
+
+ wsocket.addEventListener('close', testClose.step_func(function (evt) {
+ assert_true(isOpenCalled, "WebSocket connection should be open");
+ assert_equals(wsocket.readyState, 3, "readyState should be 3(CLOSED)");
+ assert_equals(evt.wasClean, true, "wasClean should be TRUE");
+ testClose.done();
+ }), true);
+
+ </script>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Secure-Close-readyState-Closing.htm b/tests/wpt/web-platform-tests/websockets/Secure-Close-readyState-Closing.htm
new file mode 100644
index 00000000000..0e085c65c05
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Secure-Close-readyState-Closing.htm
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Close Secure WebSocket - verify readyState is 2 before onclose is fired</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var test = async_test("W3C WebSocket API - Create Secure WebSocket - Close the Connection - readyState should be in CLOSING state just before onclose is called");
+
+ var wsocket = CreateWebSocket(true, false, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', test.step_func(function (evt) {
+ wsocket.close();
+ assert_equals(wsocket.readyState, 2, "readyState should be 2(CLOSING)");
+ test.done();
+ }), true);
+
+ </script>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Secure-Close-server-initiated-close.htm b/tests/wpt/web-platform-tests/websockets/Secure-Close-server-initiated-close.htm
new file mode 100644
index 00000000000..2fa07bbece9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Secure-Close-server-initiated-close.htm
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Close Secure WebSocket - Server Initiated close</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var testOpen = async_test("W3C WebSocket API - Create Secure WebSocket - Server initiated Close - Client sends back a CLOSE - Connection should be opened");
+ var testClose = async_test("W3C WebSocket API - Create Secure WebSocket - Server initiated Close - Client sends back a CLOSE - readyState should be in CLOSED state and wasClean is TRUE - Connection should be closed");
+
+ var wsocket = CreateWebSocket(true, false, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', testOpen.step_func(function (evt) {
+ wsocket.send(".close");
+ isOpenCalled = true;
+ testOpen.done();
+ }), true);
+
+ wsocket.addEventListener('close', testClose.step_func(function (evt) {
+ assert_true(isOpenCalled, "WebSocket connection should be open");
+ assert_equals(wsocket.readyState, 3, "readyState should be 3(CLOSED)");
+ assert_equals(evt.wasClean, true, "wasClean should be TRUE");
+ testClose.done();
+ }), true);
+
+ </script>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Secure-Close-string.htm b/tests/wpt/web-platform-tests/websockets/Secure-Close-string.htm
new file mode 100644
index 00000000000..20dffe1e661
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Secure-Close-string.htm
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Close Secure WebSocket - Code is string</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var test = async_test("W3C WebSocket API - Create WebSocket - Close the Connection - close(string) - INVALID_ACCESS_ERR is thrown");
+
+ var wsocket = CreateWebSocket(true, false, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', test.step_func(function (evt) {
+ assert_throws("INVALID_ACCESS_ERR", function () { wsocket.close('string') });
+ test.done();
+ }), true);
+ </script>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Secure-Close-undefined.htm b/tests/wpt/web-platform-tests/websockets/Secure-Close-undefined.htm
new file mode 100644
index 00000000000..ef4a874ea75
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Secure-Close-undefined.htm
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Close Secure WebSocket - Code is undefined</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var test = async_test("W3C WebSocket API - Create Secure WebSocket - Close the Connection - close(undefined) - INVALID_ACCESS_ERR is thrown");
+
+ var wsocket = CreateWebSocket(true, false, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', test.step_func(function (evt) {
+ assert_throws("INVALID_ACCESS_ERR", function () { wsocket.close(undefined) });
+ test.done();
+ }), true);
+ </script>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Secure-Send-65K-data.htm b/tests/wpt/web-platform-tests/websockets/Secure-Send-65K-data.htm
new file mode 100644
index 00000000000..cbbf5c2c511
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Secure-Send-65K-data.htm
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Send 65K data - Secure WebSocket</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var testOpen = async_test("W3C WebSocket API - Send 65K data on a Secure WebSocket - Connection should be opened");
+ var testMessage = async_test("W3C WebSocket API - Send 65K data on a Secure WebSocket - Message should be received");
+ var testClose = async_test("W3C WebSocket API - Send 65K data on a Secure WebSocket - Connection should be closed");
+
+ var data = "";
+ var wsocket = CreateWebSocket(true, false, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', testOpen.step_func(function (evt) {
+ for (var i = 0; i < 65000; i++) {
+ data = data + "c";
+ }
+ wsocket.send(data);
+ assert_equals(data.length, wsocket.bufferedAmount);
+ isOpenCalled = true;
+ testOpen.done();
+ }), true);
+
+ wsocket.addEventListener('message', testMessage.step_func(function (evt) {
+ assert_equals(evt.data, data);
+ wsocket.close();
+ testMessage.done();
+ }), true);
+
+ wsocket.addEventListener('close', testClose.step_func(function (evt) {
+ assert_true(isOpenCalled, "WebSocket connection should be open");
+ assert_equals(evt.wasClean, true, "wasClean should be true");
+ testClose.done();
+ }), true);
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Secure-Send-binary-65K-arraybuffer.htm b/tests/wpt/web-platform-tests/websockets/Secure-Send-binary-65K-arraybuffer.htm
new file mode 100644
index 00000000000..bd488f021f0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Secure-Send-binary-65K-arraybuffer.htm
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Send 65K binary data - ArrayBuffer - Secure WebSocket</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var testOpen = async_test("W3C WebSocket API - Send 65K binary data on a Secure WebSocket - ArrayBuffer - Connection should be opened");
+ var testMessage = async_test("W3C WebSocket API - Send 65K binary data on a Secure WebSocket - ArrayBuffer - Message should be received");
+ var testClose = async_test("W3C WebSocket API - Send 65K binary data on a Secure WebSocket - ArrayBuffer - Connection should be closed");
+
+ var data = "";
+ var datasize = 65000;
+ var wsocket = CreateWebSocket(true, false, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', testOpen.step_func(function (evt) {
+ wsocket.binaryType = "arraybuffer";
+ data = new ArrayBuffer(datasize);
+ wsocket.send(data);
+ assert_equals(datasize, wsocket.bufferedAmount);
+ isOpenCalled = true;
+ testOpen.done();
+ }), true);
+
+ wsocket.addEventListener('message', testMessage.step_func(function (evt) {
+ assert_equals(evt.data.byteLength, datasize);
+ wsocket.close();
+ testMessage.done();
+ }), true);
+
+ wsocket.addEventListener('close', testClose.step_func(function (evt) {
+ assert_true(isOpenCalled, "WebSocket connection should be open");
+ assert_equals(evt.wasClean, true, "wasClean should be true");
+ testClose.done();
+ }), true);
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Secure-Send-binary-arraybuffer.htm b/tests/wpt/web-platform-tests/websockets/Secure-Send-binary-arraybuffer.htm
new file mode 100644
index 00000000000..9c81e462f42
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Secure-Send-binary-arraybuffer.htm
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Send binary data - ArrayBuffer - Secure WebSocket</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var testOpen = async_test("W3C WebSocket API - Send binary data on a Secure WebSocket - ArrayBuffer - Connection should be opened");
+ var testMessage = async_test("W3C WebSocket API - Send binary data on a Secure WebSocket - ArrayBuffer - Message should be received");
+ var testClose = async_test("W3C WebSocket API - Send binary data on a Secure WebSocket - ArrayBuffer - Connection should be closed");
+
+ var data = "";
+ var datasize = 15;
+ var wsocket = CreateWebSocket(true, false, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', testOpen.step_func(function (evt) {
+ wsocket.binaryType = "arraybuffer";
+ data = new ArrayBuffer(datasize);
+ wsocket.send(data);
+ assert_equals(datasize, wsocket.bufferedAmount);
+ isOpenCalled = true;
+ testOpen.done();
+ }), true);
+
+ wsocket.addEventListener('message', testMessage.step_func(function (evt) {
+ assert_equals(evt.data.byteLength, datasize);
+ wsocket.close();
+ testMessage.done();
+ }), true);
+
+ wsocket.addEventListener('close', testClose.step_func(function (evt) {
+ assert_true(isOpenCalled, "WebSocket connection should be open");
+ assert_equals(evt.wasClean, true, "wasClean should be true");
+ testClose.done();
+ }), true);
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Secure-Send-binary-arraybufferview-float32.htm b/tests/wpt/web-platform-tests/websockets/Secure-Send-binary-arraybufferview-float32.htm
new file mode 100644
index 00000000000..cdc7c240fcd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Secure-Send-binary-arraybufferview-float32.htm
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Send binary data - ArrayBufferView - Float32Array - WebSocket</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var testOpen = async_test("W3C WebSocket API - Send binary data on a WebSocket - ArrayBufferView - Float32Array - Connection should be opened");
+ var testMessage = async_test("W3C WebSocket API - Send binary data on a WebSocket - ArrayBufferView - Float32Array - Message should be received");
+ var testClose = async_test("W3C WebSocket API - Send binary data on a WebSocket - ArrayBufferView - Float32Array - Connection should be closed");
+
+ var data = "";
+ var datasize = 8;
+ var view;
+ var wsocket = CreateWebSocket(false, false, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', testOpen.step_func(function (evt) {
+ wsocket.binaryType = "arraybuffer";
+ data = new ArrayBuffer(datasize);
+ view = new Float32Array(data);
+ for(var i = 0; i < 2; i++) {
+ view[i] = i;
+ }
+ wsocket.send(view);
+ isOpenCalled = true;
+ testOpen.done();
+ }), true);
+
+ wsocket.addEventListener('message', testMessage.step_func(function (evt) {
+ var resultView = new Float32Array(evt.data);
+ for(var i = 0; i < resultView.length; i++) {
+ assert_equals(resultView[i], view[i], "ArrayBufferView returned is the same");
+ }
+ wsocket.close();
+ testMessage.done();
+ }), true);
+
+ wsocket.addEventListener('close', testClose.step_func(function (evt) {
+ assert_true(isOpenCalled, "WebSocket connection should be open");
+ assert_equals(evt.wasClean, true, "wasClean should be true");
+ testClose.done();
+ }), true);
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Secure-Send-binary-arraybufferview-float64.htm b/tests/wpt/web-platform-tests/websockets/Secure-Send-binary-arraybufferview-float64.htm
new file mode 100644
index 00000000000..2123b5d4c89
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Secure-Send-binary-arraybufferview-float64.htm
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Send binary data - ArrayBufferView - Float32Array - WebSocket</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var testOpen = async_test("W3C WebSocket API - Send binary data on a WebSocket - ArrayBufferView - Float64Array - Connection should be opened");
+ var testMessage = async_test("W3C WebSocket API - Send binary data on a WebSocket - ArrayBufferView - Float64Array - Message should be received");
+ var testClose = async_test("W3C WebSocket API - Send binary data on a WebSocket - ArrayBufferView - Float64Array - Connection should be closed");
+
+ var data = "";
+ var datasize = 8;
+ var view;
+ var wsocket = CreateWebSocket(true, false, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', testOpen.step_func(function (evt) {
+ wsocket.binaryType = "arraybuffer";
+ data = new ArrayBuffer(datasize);
+ view = new Float64Array(data);
+ for (var i = 0; i < 1; i++) {
+ view[i] = i;
+ }
+ wsocket.send(view);
+ isOpenCalled = true;
+ testOpen.done();
+ }), true);
+
+ wsocket.addEventListener('message', testMessage.step_func(function (evt) {
+ var resultView = new Float64Array(evt.data);
+ for(var i = 0; i < resultView.length; i++) {
+ assert_equals(resultView[i], view[i], "ArrayBufferView returned is the same");
+ }
+ wsocket.close();
+ testMessage.done();
+ }), true);
+
+ wsocket.addEventListener('close', testClose.step_func(function (evt) {
+ assert_true(isOpenCalled, "WebSocket connection should be open");
+ assert_equals(evt.wasClean, true, "wasClean should be true");
+ testClose.done();
+ }), true);
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Secure-Send-binary-arraybufferview-int32.htm b/tests/wpt/web-platform-tests/websockets/Secure-Send-binary-arraybufferview-int32.htm
new file mode 100644
index 00000000000..406f9234d9d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Secure-Send-binary-arraybufferview-int32.htm
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Send binary data - ArrayBufferView - Int32Array - WebSocket</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var testOpen = async_test("W3C WebSocket API - Send binary data on a WebSocket - ArrayBufferView - Int32Array - Connection should be opened");
+ var testMessage = async_test("W3C WebSocket API - Send binary data on a WebSocket - ArrayBufferView - Int32Array - Message should be received");
+ var testClose = async_test("W3C WebSocket API - Send binary data on a WebSocket - ArrayBufferView - Int32Array - Connection should be closed");
+
+ var data = "";
+ var datasize = 8;
+ var view;
+ var wsocket = CreateWebSocket(true, false, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', testOpen.step_func(function (evt) {
+ wsocket.binaryType = "arraybuffer";
+ data = new ArrayBuffer(datasize);
+ view = new Int32Array(data);
+ for(var i = 0; i < 2; i++) {
+ view[i] = i;
+ }
+ wsocket.send(view);
+ isOpenCalled = true;
+ testOpen.done();
+ }), true);
+
+ wsocket.addEventListener('message', testMessage.step_func(function (evt) {
+ var resultView = new Int32Array(evt.data);
+ for(var i = 0; i < resultView.length; i++) {
+ assert_equals(resultView[i], view[i], "ArrayBufferView returned is the same");
+ }
+ wsocket.close();
+ testMessage.done();
+ }), true);
+
+ wsocket.addEventListener('close', testClose.step_func(function (evt) {
+ assert_true(isOpenCalled, "WebSocket connection should be open");
+ assert_equals(evt.wasClean, true, "wasClean should be true");
+ testClose.done();
+ }), true);
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Secure-Send-binary-arraybufferview-uint16-offset-length.htm b/tests/wpt/web-platform-tests/websockets/Secure-Send-binary-arraybufferview-uint16-offset-length.htm
new file mode 100644
index 00000000000..0de53f6883d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Secure-Send-binary-arraybufferview-uint16-offset-length.htm
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Send binary data - ArrayBufferView - Uint16Array with offset and length - WebSocket</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var testOpen = async_test("W3C WebSocket API - Send binary data on a WebSocket - ArrayBufferView - Uint16Array with offset and length - Connection should be opened");
+ var testMessage = async_test("W3C WebSocket API - Send binary data on a WebSocket - ArrayBufferView - Uint16Array with offset and length - Message should be received");
+ var testClose = async_test("W3C WebSocket API - Send binary data on a WebSocket - ArrayBufferView - Uint16Array with offset and length - Connection should be closed");
+
+ var data = "";
+ var datasize = 8;
+ var view;
+ var wsocket = CreateWebSocket(true, false, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', testOpen.step_func(function (evt) {
+ wsocket.binaryType = "arraybuffer";
+ data = new ArrayBuffer(datasize);
+ view = new Uint16Array(data, 2, 2);
+ for(var i = 0; i < 4; i++) {
+ view[i] = i;
+ }
+ wsocket.send(view);
+ isOpenCalled = true;
+ testOpen.done();
+ }), true);
+
+ wsocket.addEventListener('message', testMessage.step_func(function (evt) {
+ var resultView = new Uint16Array(evt.data);
+ for(var i = 0; i < resultView.length; i++) {
+ assert_equals(resultView[i], view[i], "ArrayBufferView returned is the same");
+ }
+ wsocket.close();
+ testMessage.done();
+ }), true);
+
+ wsocket.addEventListener('close', testClose.step_func(function (evt) {
+ assert_true(isOpenCalled, "WebSocket connection should be open");
+ assert_equals(evt.wasClean, true, "wasClean should be true");
+ testClose.done();
+ }), true);
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Secure-Send-binary-arraybufferview-uint32-offset.htm b/tests/wpt/web-platform-tests/websockets/Secure-Send-binary-arraybufferview-uint32-offset.htm
new file mode 100644
index 00000000000..89347004a13
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Secure-Send-binary-arraybufferview-uint32-offset.htm
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Send binary data - ArrayBufferView - Uint32Array with offset - WebSocket</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var testOpen = async_test("W3C WebSocket API - Send binary data on a WebSocket - ArrayBufferView - Uint32Array with offset - Connection should be opened");
+ var testMessage = async_test("W3C WebSocket API - Send binary data on a WebSocket - ArrayBufferView - Uint32Array with offset - Message should be received");
+ var testClose = async_test("W3C WebSocket API - Send binary data on a WebSocket - ArrayBufferView - Uint32Array with offset - Connection should be closed");
+
+ var data = "";
+ var datasize = 8;
+ var view;
+ var wsocket = CreateWebSocket(true, false, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', testOpen.step_func(function (evt) {
+ wsocket.binaryType = "arraybuffer";
+ data = new ArrayBuffer(datasize);
+ view = new Uint32Array(data, 0);
+ for(var i = 0; i < 2; i++) {
+ view[i] = i;
+ }
+ wsocket.send(view);
+ isOpenCalled = true;
+ testOpen.done();
+ }), true);
+
+ wsocket.addEventListener('message', testMessage.step_func(function (evt) {
+ var resultView = new Uint32Array(evt.data);
+ for(var i = 0; i < resultView.length; i++) {
+ assert_equals(resultView[i], view[i], "ArrayBufferView returned is the same");
+ }
+ wsocket.close();
+ testMessage.done();
+ }), true);
+
+ wsocket.addEventListener('close', testClose.step_func(function (evt) {
+ assert_true(isOpenCalled, "WebSocket connection should be open");
+ assert_equals(evt.wasClean, true, "wasClean should be true");
+ testClose.done();
+ }), true);
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Secure-Send-binary-arraybufferview-uint8-offset-length.htm b/tests/wpt/web-platform-tests/websockets/Secure-Send-binary-arraybufferview-uint8-offset-length.htm
new file mode 100644
index 00000000000..c2849c845b1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Secure-Send-binary-arraybufferview-uint8-offset-length.htm
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Send binary data - ArrayBufferView - Uint8Array with offset and length - WebSocket</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var testOpen = async_test("W3C WebSocket API - Send binary data on a WebSocket - ArrayBufferView - Uint8Array with offset and length - Connection should be opened");
+ var testMessage = async_test("W3C WebSocket API - Send binary data on a WebSocket - ArrayBufferView - Uint8Array with offset and length - Message should be received");
+ var testClose = async_test("W3C WebSocket API - Send binary data on a WebSocket - ArrayBufferView - Uint8Array with offset and length - Connection should be closed");
+
+ var data = "";
+ var datasize = 8;
+ var view;
+ var wsocket = CreateWebSocket(true, false, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', testOpen.step_func(function (evt) {
+ wsocket.binaryType = "arraybuffer";
+ data = new ArrayBuffer(datasize);
+ view = new Uint8Array(data, 2, 4);
+ for(var i = 0; i < 8; i++) {
+ view[i] = i;
+ }
+ wsocket.send(view);
+ isOpenCalled = true;
+ testOpen.done();
+ }), true);
+
+ wsocket.addEventListener('message', testMessage.step_func(function (evt) {
+ var resultView = new Uint8Array(evt.data);
+ for(var i = 0; i < resultView.length; i++) {
+ assert_equals(resultView[i], view[i], "ArrayBufferView returned is the same");
+ }
+ wsocket.close();
+ testMessage.done();
+ }), true);
+
+ wsocket.addEventListener('close', testClose.step_func(function (evt) {
+ assert_true(isOpenCalled, "WebSocket connection should be open");
+ assert_equals(evt.wasClean, true, "wasClean should be true");
+ testClose.done();
+ }), true);
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Secure-Send-binary-arraybufferview-uint8-offset.htm b/tests/wpt/web-platform-tests/websockets/Secure-Send-binary-arraybufferview-uint8-offset.htm
new file mode 100644
index 00000000000..1e0934029d8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Secure-Send-binary-arraybufferview-uint8-offset.htm
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Send binary data - ArrayBufferView - Uint8Array with offset - WebSocket</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var testOpen = async_test("W3C WebSocket API - Send binary data on a WebSocket - ArrayBufferView - Uint8Array with offset - Connection should be opened");
+ var testMessage = async_test("W3C WebSocket API - Send binary data on a WebSocket - ArrayBufferView - Uint8Array with offset - Message should be received");
+ var testClose = async_test("W3C WebSocket API - Send binary data on a WebSocket - ArrayBufferView - Uint8Array with offset - Connection should be closed");
+
+ var data = "";
+ var datasize = 8;
+ var view;
+ var wsocket = CreateWebSocket(true, false, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', testOpen.step_func(function (evt) {
+ wsocket.binaryType = "arraybuffer";
+ data = new ArrayBuffer(datasize);
+ view = new Uint8Array(data, 2);
+ for(var i = 0; i < 8; i++) {
+ view[i] = i;
+ }
+ wsocket.send(view);
+ isOpenCalled = true;
+ testOpen.done();
+ }), true);
+
+ wsocket.addEventListener('message', testMessage.step_func(function (evt) {
+ var resultView = new Uint8Array(evt.data);
+ for(var i = 0; i < resultView.length; i++) {
+ assert_equals(resultView[i], view[i], "ArrayBufferView returned is the same");
+ }
+ wsocket.close();
+ testMessage.done();
+ }), true);
+
+ wsocket.addEventListener('close', testClose.step_func(function (evt) {
+ assert_true(isOpenCalled, "WebSocket connection should be open");
+ assert_equals(evt.wasClean, true, "wasClean should be true");
+ testClose.done();
+ }), true);
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Secure-Send-binary-blob.htm b/tests/wpt/web-platform-tests/websockets/Secure-Send-binary-blob.htm
new file mode 100644
index 00000000000..ca1d2a281b4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Secure-Send-binary-blob.htm
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Send binary data - Blob - Secure WebSocket</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var testOpen = async_test("W3C WebSocket API - Send binary data on a Secure WebSocket - Blob - Connection should be opened");
+ var testMessage = async_test("W3C WebSocket API - Send binary data on a Secure WebSocket - Blob - Message should be received");
+ var testClose = async_test("W3C WebSocket API - Send binary data on a Secure WebSocket - Blob - Connection should be closed");
+
+ var data = "";
+ var datasize = 65000;
+ var isOpenCalled = false;
+
+ var wsocket = CreateWebSocket(true, false, false);
+
+ wsocket.addEventListener('open', testOpen.step_func(function (evt) {
+ wsocket.binaryType = "blob";
+ data = new ArrayBuffer(datasize);
+ isOpenCalled = true;
+ wsocket.send(data);
+ testOpen.done();
+ }), true);
+
+ wsocket.addEventListener('message', testMessage.step_func(function (evt) {
+ assert_true(evt.data instanceof Blob);
+ assert_equals(evt.data.size, datasize);
+ wsocket.close();
+ testMessage.done();
+ }), true);
+
+ wsocket.addEventListener('close', testClose.step_func(function (evt) {
+ assert_true(isOpenCalled, "WebSocket connection should be open");
+ assert_true(evt.wasClean, "wasClean should be true");
+ testClose.done();
+ }), true);
+
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Secure-Send-data.htm b/tests/wpt/web-platform-tests/websockets/Secure-Send-data.htm
new file mode 100644
index 00000000000..7f679fe731a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Secure-Send-data.htm
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Send data - Secure WebSocket</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var testOpen = async_test("W3C WebSocket API - Send data on a Secure WebSocket - Connection should be opened");
+ var testMessage = async_test("W3C WebSocket API - Send data on a Secure WebSocket - Message should be received");
+ var testClose = async_test("W3C WebSocket API - Send data on a Secure WebSocket - Connection should be closed");
+
+ var data = "Message to send";
+ var wsocket = CreateWebSocket(true, false, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', testOpen.step_func(function (evt) {
+ wsocket.send(data);
+ assert_equals(data.length, wsocket.bufferedAmount);
+ isOpenCalled = true;
+ testOpen.done();
+ }), true);
+
+ wsocket.addEventListener('message', testMessage.step_func(function (evt) {
+ assert_equals(evt.data, data);
+ wsocket.close();
+ testMessage.done();
+ }), true);
+
+ wsocket.addEventListener('close', testClose.step_func(function (evt) {
+ assert_true(isOpenCalled, "WebSocket connection should be open");
+ assert_equals(evt.wasClean, true, "wasClean should be true");
+ testClose.done();
+ }), true);
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Secure-Send-null.htm b/tests/wpt/web-platform-tests/websockets/Secure-Send-null.htm
new file mode 100644
index 00000000000..1adf3c9a891
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Secure-Send-null.htm
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Send null data - Secure WebSocket</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var testOpen = async_test("W3C WebSocket API - Send null data on a Secure WebSocket - Connection should be opened");
+ var testMessage = async_test("W3C WebSocket API - Send null data on a Secure WebSocket - Message should be received");
+ var testClose = async_test("W3C WebSocket API - Send null data on a Secure WebSocket - Connection should be closed");
+
+ var data = null;
+ var nullReturned = false;
+ var wsocket = CreateWebSocket(true, false, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', testOpen.step_func(function (evt) {
+ wsocket.send(data);
+ isOpenCalled = true;
+ testOpen.done();
+ }), true);
+
+ wsocket.addEventListener('message', testMessage.step_func(function (evt) {
+ if ("null" == evt.data || "" == evt.data)
+ nullReturned = true;
+ assert_true(nullReturned);
+ wsocket.close();
+ testMessage.done();
+ }), true);
+
+ wsocket.addEventListener('close', testClose.step_func(function (evt) {
+ assert_true(isOpenCalled, "WebSocket connection should be open");
+ assert_equals(evt.wasClean, true, "wasClean should be true");
+ testClose.done();
+ }), true);
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Secure-Send-paired-surrogates.htm b/tests/wpt/web-platform-tests/websockets/Secure-Send-paired-surrogates.htm
new file mode 100644
index 00000000000..4261815be52
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Secure-Send-paired-surrogates.htm
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Send (paired surrogates) data - Secure WebSocket</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var testOpen = async_test("W3C WebSocket API - Send paired surrogates data on a Secure WebSocket - Connection should be opened");
+ var testMessage = async_test("W3C WebSocket API - Send paired surrogates data on a Secure WebSocket - Message should be received");
+ var testClose = async_test("W3C WebSocket API - Send paired surrogates data on a Secure WebSocket - Connection should be closed");
+
+ var data = "\uD801\uDC07";
+ var wsocket = CreateWebSocket(true, false, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', testOpen.step_func(function (evt) {
+ wsocket.send(data);
+ assert_equals(data.length * 2, wsocket.bufferedAmount);
+ isOpenCalled = true;
+ testOpen.done();
+ }), true);
+
+ wsocket.addEventListener('message', testMessage.step_func(function (evt) {
+ assert_equals(evt.data, data);
+ wsocket.close();
+ testMessage.done();
+ }), true);
+
+ wsocket.addEventListener('close', testClose.step_func(function (evt) {
+ assert_true(isOpenCalled, "WebSocket connection should be open");
+ assert_equals(evt.wasClean, true, "wasClean should be true");
+ testClose.done();
+ }), true);
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Secure-Send-unicode-data.htm b/tests/wpt/web-platform-tests/websockets/Secure-Send-unicode-data.htm
new file mode 100644
index 00000000000..01555e069d7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Secure-Send-unicode-data.htm
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Send unicode data - Secure WebSocket</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var testOpen = async_test("W3C WebSocket API - Send unicode data on a Secure WebSocket - Connection should be opened");
+ var testMessage = async_test("W3C WebSocket API - Send unicode data on a Secure WebSocket - Message should be received");
+ var testClose = async_test("W3C WebSocket API - Send unicode data on a Secure WebSocket - Connection should be closed");
+
+ var data = "¥¥¥¥¥¥";
+ var wsocket = CreateWebSocket(true, false, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', testOpen.step_func(function (evt) {
+ wsocket.send(data);
+ assert_equals(data.length * 2, wsocket.bufferedAmount);
+ isOpenCalled = true;
+ testOpen.done();
+ }), true);
+
+ wsocket.addEventListener('message', testMessage.step_func(function (evt) {
+ assert_equals(evt.data, data);
+ wsocket.close();
+ testMessage.done();
+ }), true);
+
+ wsocket.addEventListener('close', testClose.step_func(function (evt) {
+ assert_true(isOpenCalled, "WebSocket connection should be open");
+ assert_equals(evt.wasClean, true, "wasClean should be true");
+ testClose.done();
+ }), true);
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Secure-Send-unpaired-surrogates.htm b/tests/wpt/web-platform-tests/websockets/Secure-Send-unpaired-surrogates.htm
new file mode 100644
index 00000000000..99dfbd3ec24
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Secure-Send-unpaired-surrogates.htm
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Send unpaired surrogates - Secure WebSocket</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var testOpen = async_test("W3C WebSocket API - Send unpaired surrogates on a Secure WebSocket - Connection should be opened");
+ var testMessage = async_test("W3C WebSocket API - Send unpaired surrogates on a Secure WebSocket - Message should be received");
+ var testClose = async_test("W3C WebSocket API - Send unpaired surrogates on a Secure WebSocket - Connection should be closed");
+
+ var data = "\uD807";
+ var replacementChar = "\uFFFD";
+ var wsocket = CreateWebSocket(true, false, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', testOpen.step_func(function (evt) {
+ wsocket.send(data);
+ isOpenCalled = true;
+ testOpen.done();
+ }), true);
+
+ wsocket.addEventListener('message', testMessage.step_func(function (evt) {
+ assert_equals(evt.data, replacementChar);
+ wsocket.close();
+ testMessage.done();
+ }), true);
+
+ wsocket.addEventListener('close', testClose.step_func(function (evt) {
+ assert_true(isOpenCalled, "WebSocket connection should be open");
+ assert_equals(evt.wasClean, true, "wasClean should be true");
+ testClose.done();
+ }), true);
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Send-0byte-data.htm b/tests/wpt/web-platform-tests/websockets/Send-0byte-data.htm
new file mode 100644
index 00000000000..328816f82f6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Send-0byte-data.htm
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Send 0 byte data - WebSocket</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var testOpen = async_test("W3C WebSocket API - Send 0 byte data on a WebSocket - Connection should be opened");
+ var testMessage = async_test("W3C WebSocket API - Send 0 byte data on a WebSocket - Message should be received");
+ var testClose = async_test("W3C WebSocket API - Send 0 byte data on a WebSocket - Connection should be closed");
+
+ var data = "";
+ var wsocket = CreateWebSocket(false, false, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', testOpen.step_func(function (evt) {
+ wsocket.send(data);
+ assert_equals(data.length, wsocket.bufferedAmount);
+ isOpenCalled = true;
+ testOpen.done();
+ }), true);
+
+ wsocket.addEventListener('message', testMessage.step_func(function (evt) {
+ assert_equals(evt.data, data);
+ wsocket.close();
+ testMessage.done();
+ }), true);
+
+ wsocket.addEventListener('close', testClose.step_func(function (evt) {
+ assert_true(isOpenCalled, "WebSocket connection should be open");
+ assert_equals(evt.wasClean, true, "wasClean should be true");
+ testClose.done();
+ }), true);
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Send-65K-data.htm b/tests/wpt/web-platform-tests/websockets/Send-65K-data.htm
new file mode 100644
index 00000000000..151af2da4a7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Send-65K-data.htm
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Send 65K data - WebSocket</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var testOpen = async_test("W3C WebSocket API - Send 65K data on a WebSocket - Connection should be opened");
+ var testMessage = async_test("W3C WebSocket API - Send 65K data on a WebSocket - Message should be received");
+ var testClose = async_test("W3C WebSocket API - Send 65K data on a WebSocket - Connection should be closed");
+
+ var data = "";
+ var wsocket = CreateWebSocket(false, false, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', testOpen.step_func(function (evt) {
+ for (var i = 0; i < 65000; i++) {
+ data = data + "c";
+ }
+ wsocket.send(data);
+ assert_equals(data.length, wsocket.bufferedAmount);
+ isOpenCalled = true;
+ testOpen.done();
+ }), true);
+
+ wsocket.addEventListener('message', testMessage.step_func(function (evt) {
+ assert_equals(evt.data, data);
+ wsocket.close();
+ testMessage.done();
+ }), true);
+
+ wsocket.addEventListener('close', testClose.step_func(function (evt) {
+ assert_true(isOpenCalled, "WebSocket connection should be open");
+ assert_equals(evt.wasClean, true, "wasClean should be true");
+ testClose.done();
+ }), true);
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Send-Unpaired-Surrogates.htm b/tests/wpt/web-platform-tests/websockets/Send-Unpaired-Surrogates.htm
new file mode 100644
index 00000000000..3e70923e742
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Send-Unpaired-Surrogates.htm
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Send unpaired surrogates - WebSocket</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var testOpen = async_test("W3C WebSocket API - Send unpaired surrogates on a WebSocket - Connection should be opened");
+ var testMessage = async_test("W3C WebSocket API - Send unpaired surrogates on a WebSocket - Message should be received");
+ var testClose = async_test("W3C WebSocket API - Send unpaired surrogates on a WebSocket - Connection should be closed");
+
+ var data = "\uD807";
+ var replacementChar = "\uFFFD";
+ var wsocket = CreateWebSocket(false, false, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', testOpen.step_func(function (evt) {
+ wsocket.send(data);
+ isOpenCalled = true;
+ testOpen.done();
+ }), true);
+
+ wsocket.addEventListener('message', testMessage.step_func(function (evt) {
+ assert_equals(evt.data, replacementChar);
+ wsocket.close();
+ testMessage.done();
+ }), true);
+
+ wsocket.addEventListener('close', testClose.step_func(function (evt) {
+ assert_true(isOpenCalled, "WebSocket connection should be open");
+ assert_equals(evt.wasClean, true, "wasClean should be true");
+ testClose.done();
+ }), true);
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Send-before-open.htm b/tests/wpt/web-platform-tests/websockets/Send-before-open.htm
new file mode 100644
index 00000000000..23a9460e646
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Send-before-open.htm
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Send WebSocket - Send before connection in established</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+ test(function () {
+ var wsocket = CreateWebSocket(false, false, false);
+ assert_throws("INVALID_STATE_ERR", function () { wsocket.send("Message to send") });
+ }, "W3C WebSocket API - Send data on a WebSocket before connection is opened - INVALID_STATE_ERR is returned")
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Send-binary-65K-arraybuffer.htm b/tests/wpt/web-platform-tests/websockets/Send-binary-65K-arraybuffer.htm
new file mode 100644
index 00000000000..e4d26846f74
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Send-binary-65K-arraybuffer.htm
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Send 65K binary data - ArrayBuffer - WebSocket</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var testOpen = async_test("W3C WebSocket API - Send 65K binary data on a WebSocket - ArrayBuffer - Connection should be opened");
+ var testMessage = async_test("W3C WebSocket API - Send 65K binary data on a WebSocket - ArrayBuffer - Message should be received");
+ var testClose = async_test("W3C WebSocket API - Send 65K binary data on a WebSocket - ArrayBuffer - Connection should be closed");
+
+ var data = "";
+ var datasize = 65000;
+ var wsocket = CreateWebSocket(false, false, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', testOpen.step_func(function (evt) {
+ wsocket.binaryType = "arraybuffer";
+ data = new ArrayBuffer(datasize);
+ wsocket.send(data);
+ assert_equals(datasize, wsocket.bufferedAmount);
+ isOpenCalled = true;
+ testOpen.done();
+ }), true);
+
+ wsocket.addEventListener('message', testMessage.step_func(function (evt) {
+ assert_equals(evt.data.byteLength, datasize);
+ wsocket.close();
+ testMessage.done();
+ }), true);
+
+ wsocket.addEventListener('close', testClose.step_func(function (evt) {
+ assert_true(isOpenCalled, "WebSocket connection should be open");
+ assert_equals(evt.wasClean, true, "wasClean should be true");
+ testClose.done();
+ }), true);
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Send-binary-arraybuffer.htm b/tests/wpt/web-platform-tests/websockets/Send-binary-arraybuffer.htm
new file mode 100644
index 00000000000..aeb4a38e76b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Send-binary-arraybuffer.htm
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Send binary data - ArrayBuffer - WebSocket</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var testOpen = async_test("W3C WebSocket API - Send binary data on a WebSocket - ArrayBuffer - Connection should be opened");
+ var testMessage = async_test("W3C WebSocket API - Send binary data on a WebSocket - ArrayBuffer - Message should be received");
+ var testClose = async_test("W3C WebSocket API - Send binary data on a WebSocket - ArrayBuffer - Connection should be closed");
+
+ var data = "";
+ var datasize = 15;
+ var wsocket = CreateWebSocket(false, false, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', testOpen.step_func(function (evt) {
+ wsocket.binaryType = "arraybuffer";
+ data = new ArrayBuffer(datasize);
+ wsocket.send(data);
+ assert_equals(datasize, wsocket.bufferedAmount);
+ isOpenCalled = true;
+ testOpen.done();
+ }), true);
+
+ wsocket.addEventListener('message', testMessage.step_func(function (evt) {
+ assert_equals(evt.data.byteLength, datasize);
+ wsocket.close();
+ testMessage.done();
+ }), true);
+
+ wsocket.addEventListener('close', testClose.step_func(function (evt) {
+ assert_true(isOpenCalled, "WebSocket connection should be open");
+ assert_equals(evt.wasClean, true, "wasClean should be true");
+ testClose.done();
+ }), true);
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Send-binary-arraybufferview-int16-offset.htm b/tests/wpt/web-platform-tests/websockets/Send-binary-arraybufferview-int16-offset.htm
new file mode 100644
index 00000000000..869e6de0388
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Send-binary-arraybufferview-int16-offset.htm
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Send binary data - ArrayBufferView - Int16Array with offset - WebSocket</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var testOpen = async_test("W3C WebSocket API - Send binary data on a WebSocket - ArrayBufferView - Int16Array with offset - Connection should be opened");
+ var testMessage = async_test("W3C WebSocket API - Send binary data on a WebSocket - ArrayBufferView - Int16Array with offset - Message should be received");
+ var testClose = async_test("W3C WebSocket API - Send binary data on a WebSocket - ArrayBufferView - Int16Array with offset - Connection should be closed");
+
+ var data = "";
+ var datasize = 8;
+ var view;
+ var wsocket = CreateWebSocket(false, false, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', testOpen.step_func(function (evt) {
+ wsocket.binaryType = "arraybuffer";
+ data = new ArrayBuffer(datasize);
+ view = new Int16Array(data, 2);
+ for(var i = 0; i < 4; i++) {
+ view[i] = i;
+ }
+ wsocket.send(view);
+ isOpenCalled = true;
+ testOpen.done();
+ }), true);
+
+ wsocket.addEventListener('message', testMessage.step_func(function (evt) {
+ var resultView = new Int16Array(evt.data);
+ for(var i = 0; i < resultView.length; i++) {
+ assert_equals(resultView[i], view[i], "ArrayBufferView returned is the same");
+ }
+ wsocket.close();
+ testMessage.done();
+ }), true);
+
+ wsocket.addEventListener('close', testClose.step_func(function (evt) {
+ assert_true(isOpenCalled, "WebSocket connection should be open");
+ assert_equals(evt.wasClean, true, "wasClean should be true");
+ testClose.done();
+ }), true);
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Send-binary-arraybufferview-int8.htm b/tests/wpt/web-platform-tests/websockets/Send-binary-arraybufferview-int8.htm
new file mode 100644
index 00000000000..c46d7aa1a6c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Send-binary-arraybufferview-int8.htm
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Send binary data - ArrayBufferView - Int8Array - WebSocket</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var testOpen = async_test("W3C WebSocket API - Send binary data on a WebSocket - ArrayBufferView - Int8Array - Connection should be opened");
+ var testMessage = async_test("W3C WebSocket API - Send binary data on a WebSocket - ArrayBufferView - Int8Array - Message should be received");
+ var testClose = async_test("W3C WebSocket API - Send binary data on a WebSocket - ArrayBufferView - Int8Array - Connection should be closed");
+
+ var data = "";
+ var datasize = 8;
+ var int8View;
+ var wsocket = CreateWebSocket(false, false, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', testOpen.step_func(function (evt) {
+ wsocket.binaryType = "arraybuffer";
+ data = new ArrayBuffer(datasize);
+ int8View = new Int8Array(data);
+ for (var i = 0; i < 8; i++) {
+ int8View[i] = i;
+ }
+ wsocket.send(int8View);
+ isOpenCalled = true;
+ testOpen.done();
+ }), true);
+
+ wsocket.addEventListener('message', testMessage.step_func(function (evt) {
+ var resultView = new Int8Array(evt.data);
+ for (var i = 0; i < resultView.length; i++) {
+ assert_equals(resultView[i], int8View[i], "ArrayBufferView returned is the same");
+ }
+ wsocket.close();
+ testMessage.done();
+ }), true);
+
+ wsocket.addEventListener('close', testClose.step_func(function (evt) {
+ assert_true(isOpenCalled, "WebSocket connection should be open");
+ assert_equals(evt.wasClean, true, "wasClean should be true");
+ testClose.done();
+ }), true);
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Send-binary-blob.htm b/tests/wpt/web-platform-tests/websockets/Send-binary-blob.htm
new file mode 100644
index 00000000000..22238bac722
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Send-binary-blob.htm
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Send binary data - Blob - WebSocket</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var testOpen = async_test("W3C WebSocket API - Send binary data on a WebSocket - Blob - Connection should be opened");
+ var testMessage = async_test("W3C WebSocket API - Send binary data on a WebSocket - Blob - Message should be received");
+ var testClose = async_test("W3C WebSocket API - Send binary data on a WebSocket - Blob - Connection should be closed");
+
+ var data = "";
+ var datasize = 65000;
+ var isOpenCalled = false;
+
+ var wsocket = CreateWebSocket(false, false, false);
+
+ wsocket.addEventListener('open', testOpen.step_func(function (evt) {
+ wsocket.binaryType = "blob";
+ data = new ArrayBuffer(datasize);
+ isOpenCalled = true;
+ wsocket.send(data);
+ testOpen.done();
+ }), true);
+
+ wsocket.addEventListener('message', testMessage.step_func(function (evt) {
+ assert_true(evt.data instanceof Blob);
+ assert_equals(evt.data.size, datasize);
+ wsocket.close();
+ testMessage.done();
+ }), true);
+
+ wsocket.addEventListener('close', testClose.step_func(function (evt) {
+ assert_true(isOpenCalled, "WebSocket connection should be open");
+ assert_true(evt.wasClean, "wasClean should be true");
+ testClose.done();
+ }), true);
+
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Send-data.htm b/tests/wpt/web-platform-tests/websockets/Send-data.htm
new file mode 100644
index 00000000000..cb58a30a3ea
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Send-data.htm
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Send data - WebSocket</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var testOpen = async_test("W3C WebSocket API - Send data on a WebSocket - Connection should be opened");
+ var testMessage = async_test("W3C WebSocket API - Send data on a WebSocket - Message should be received");
+ var testClose = async_test("W3C WebSocket API - Send data on a WebSocket - Connection should be closed");
+
+ var data = "Message to send";
+ var wsocket = CreateWebSocket(false, false, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', testOpen.step_func(function (evt) {
+ wsocket.send(data);
+ assert_equals(data.length, wsocket.bufferedAmount);
+ isOpenCalled = true;
+ testOpen.done();
+ }), true);
+
+ wsocket.addEventListener('message', testMessage.step_func(function (evt) {
+ assert_equals(evt.data, data);
+ wsocket.close();
+ testMessage.done();
+ }), true);
+
+ wsocket.addEventListener('close', testClose.step_func(function (evt) {
+ assert_true(isOpenCalled, "WebSocket connection should be open");
+ assert_equals(evt.wasClean, true, "wasClean should be true");
+ testClose.done();
+ }), true);
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Send-null.htm b/tests/wpt/web-platform-tests/websockets/Send-null.htm
new file mode 100644
index 00000000000..b59e4a30573
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Send-null.htm
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Send null data - WebSocket</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var testOpen = async_test("W3C WebSocket API - Send null data on a WebSocket - Connection should be opened");
+ var testMessage = async_test("W3C WebSocket API - Send null data on a WebSocket - Message should be received");
+ var testClose = async_test("W3C WebSocket API - Send null data on a WebSocket - Connection should be closed");
+
+ var data = null;
+ var nullReturned = false;
+ var wsocket = CreateWebSocket(false, false, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', testOpen.step_func(function (evt) {
+ wsocket.send(data);
+ isOpenCalled = true;
+ testOpen.done();
+ }), true);
+
+ wsocket.addEventListener('message', testMessage.step_func(function (evt) {
+ if ("null" == evt.data || "" == evt.data)
+ nullReturned = true;
+ assert_true(nullReturned);
+ wsocket.close();
+ testMessage.done();
+ }), true);
+
+ wsocket.addEventListener('close', testClose.step_func(function (evt) {
+ assert_true(isOpenCalled, "WebSocket connection should be open");
+ assert_equals(evt.wasClean, true, "wasClean should be true");
+ testClose.done();
+ }), true);
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Send-paired-surrogates.htm b/tests/wpt/web-platform-tests/websockets/Send-paired-surrogates.htm
new file mode 100644
index 00000000000..055cfd212c9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Send-paired-surrogates.htm
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Send (paired surrogates) data - WebSocket</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var testOpen = async_test("W3C WebSocket API - Send (paired surrogates) data on a WebSocket - Connection should be opened");
+ var testMessage = async_test("W3C WebSocket API - Send (paired surrogates) data on a WebSocket - Message should be received");
+ var testClose = async_test("W3C WebSocket API - Send (paired surrogates) data on a WebSocket - Connection should be closed");
+
+ var data = "\uD801\uDC07";
+ var wsocket = CreateWebSocket(false, false, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', testOpen.step_func(function (evt) {
+ wsocket.send(data);
+ assert_equals(data.length * 2, wsocket.bufferedAmount);
+ isOpenCalled = true;
+ testOpen.done();
+ }), true);
+
+ wsocket.addEventListener('message', testMessage.step_func(function (evt) {
+ assert_equals(evt.data, data);
+ wsocket.close();
+ testMessage.done();
+ }), true);
+
+ wsocket.addEventListener('close', testClose.step_func(function (evt) {
+ assert_true(isOpenCalled, "WebSocket connection should be open");
+ assert_equals(evt.wasClean, true, "wasClean should be true");
+ testClose.done();
+ }), true);
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/Send-unicode-data.htm b/tests/wpt/web-platform-tests/websockets/Send-unicode-data.htm
new file mode 100644
index 00000000000..77ec1b66e68
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/Send-unicode-data.htm
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Send unicode data - WebSocket</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js?pipe=sub"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var testOpen = async_test("W3C WebSocket API - Send unicode data on a WebSocket - Connection should be opened");
+ var testMessage = async_test("W3C WebSocket API - Send unicode data on a WebSocket - Message should be received");
+ var testClose = async_test("W3C WebSocket API - Send unicode data on a WebSocket - Connection should be closed");
+
+ var data = "¥¥¥¥¥¥";
+ var wsocket = CreateWebSocket(false, false, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', testOpen.step_func(function (evt) {
+ wsocket.send(data);
+ assert_equals(data.length * 2, wsocket.bufferedAmount);
+ isOpenCalled = true;
+ testOpen.done();
+ }), true);
+
+ wsocket.addEventListener('message', testMessage.step_func(function (evt) {
+ assert_equals(evt.data, data);
+ wsocket.close();
+ testMessage.done();
+ }), true);
+
+ wsocket.addEventListener('close', testClose.step_func(function (evt) {
+ assert_true(isOpenCalled, "WebSocket connection should be open");
+ assert_equals(evt.wasClean, true, "wasClean should be true");
+ testClose.done();
+ }), true);
+ </script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/binary/001.html b/tests/wpt/web-platform-tests/websockets/binary/001.html
new file mode 100644
index 00000000000..87d1df3b08e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/binary/001.html
@@ -0,0 +1,24 @@
+<!doctype html>
+<title>WebSockets: Send/Receive blob, blob size less than network array buffer</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+async_test(function(t){
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT + '/echo');
+ var data = "";
+ var datasize = 10;
+ ws.onopen = t.step_func(function(e) {
+ ws.binaryType = "blob";
+ data = new ArrayBuffer(datasize);
+ ws.send(data);
+ })
+ ws.onmessage = t.step_func(function(e) {
+ assert_true(e.data instanceof Blob);
+ assert_equals(e.data.size, datasize);
+ t.done();
+ })
+
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/binary/002.html b/tests/wpt/web-platform-tests/websockets/binary/002.html
new file mode 100644
index 00000000000..639af7d8af5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/binary/002.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<title>WebSockets: Send/Receive blob, blob size greater than network array buffer</title>
+<meta name=timeout content=long>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+async_test(function(t){
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/echo');
+ var data = "";
+ var datasize = 100000;
+ ws.onopen = t.step_func(function(e) {
+ ws.binaryType = "blob";
+ data = new ArrayBuffer(datasize);
+ ws.send(data);
+ });
+ ws.onmessage = t.step_func(function(e) {
+ assert_true(e.data instanceof Blob);
+ assert_equals(e.data.size, datasize);
+ t.done();
+ });
+
+}, null, {timeout:20000});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/binary/004.html b/tests/wpt/web-platform-tests/websockets/binary/004.html
new file mode 100644
index 00000000000..e7335750ad4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/binary/004.html
@@ -0,0 +1,24 @@
+<!doctype html>
+<title>WebSockets: Send/Receive ArrayBuffer, size greater than network array buffer</title>
+<meta name=timeout content=long>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+async_test(function(t){
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/echo');
+ var data = "";
+ var datasize = 100000;
+ ws.onopen = t.step_func(function(e) {
+ ws.binaryType = "arraybuffer";
+ data = new ArrayBuffer(datasize);
+ ws.send(data);
+ })
+ ws.onmessage = t.step_func(function(e) {
+ assert_equals(e.data.byteLength, datasize);
+ t.done();
+ })
+
+}, null, {timeout:20000});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/binary/005.html b/tests/wpt/web-platform-tests/websockets/binary/005.html
new file mode 100644
index 00000000000..818ba2af276
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/binary/005.html
@@ -0,0 +1,22 @@
+<!doctype html>
+<title>WebSockets: Send/Receive ArrayBuffer, size less than network array buffer</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+async_test(function(t){
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/echo');
+ var data = "";
+ var datasize = 10;
+ ws.onopen = t.step_func(function(e) {
+ ws.binaryType = "arraybuffer";
+ data = new ArrayBuffer(datasize);
+ ws.send(data);
+ });
+ ws.onmessage = t.step_func(function(e) {
+ assert_equals(e.data.byteLength, datasize);
+ t.done();
+ });
+ });
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/binaryType-wrong-value.htm b/tests/wpt/web-platform-tests/websockets/binaryType-wrong-value.htm
new file mode 100644
index 00000000000..9041fd66a8d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/binaryType-wrong-value.htm
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>W3C WebSocket API - Create Secure WebSocket - binaryType is set to something other than blob/arraybuffer</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+ <script type="text/javascript" src="websocket.js"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script type="text/javascript">
+
+ var testOpen = async_test("W3C WebSocket API - Create WebSocket - set binaryType to something other than blob or arraybuffer - SYNTAX_ERR is returned - Connection should be opened");
+ var testClose = async_test("W3C WebSocket API - Create WebSocket - set binaryType to something other than blob or arraybuffer - SYNTAX_ERR is returned - Connection should be closed");
+
+ var wsocket = CreateWebSocket(true, false, false);
+ var isOpenCalled = false;
+
+ wsocket.addEventListener('open', testOpen.step_func(function (evt) {
+ assert_equals(wsocket.binaryType, "blob");
+ wsocket.binaryType = "notBlobOrArrayBuffer";
+ assert_equals(wsocket.binaryType, "blob");
+ wsocket.close();
+ isOpenCalled = true;
+ testOpen.done();
+ }), true);
+
+ wsocket.addEventListener('close', testClose.step_func(function (evt) {
+ assert_true(isOpenCalled, "WebSocket connection should be opened");
+ assert_true(evt.wasClean, "wasClean should be true");
+ clearTimeout(timeOut);
+ testClose.done();
+ }), true);
+
+ </script>
+
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/websockets/closing-handshake/002.html b/tests/wpt/web-platform-tests/websockets/closing-handshake/002.html
new file mode 100644
index 00000000000..1f72417c681
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/closing-handshake/002.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<title>WebSockets: server sends closing handshake</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+async_test(function(t){
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/echo_exit');
+ ws.onmessage = ws.onerror = t.step_func(function() {assert_unreached()});
+ ws.onopen = t.step_func(function(e) {
+ ws.send('Goodbye');
+ })
+ ws.onclose = function(e) {
+ assert_equals(e.wasClean, true, 'e.wasClean');
+ ws.onclose = t.step_func(function() {assert_unreached()});
+
+ setTimeout(t.step_func(function() {t.done();}), 50)
+ }
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/closing-handshake/003.html b/tests/wpt/web-platform-tests/websockets/closing-handshake/003.html
new file mode 100644
index 00000000000..b0d718653f1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/closing-handshake/003.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<title>WebSockets: client sends closing handshake</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT + '/echo');
+ ws.onmessage = ws.onerror = t.step_func(function() {assert_unreached()});
+ ws.onopen = function(e) {
+ ws.close();
+ }
+ ws.onclose = function(e) {
+ assert_equals(e.wasClean, true, 'e.wasClean');
+ ws.onclose = t.step_func(function() {assert_unreached()});
+ setTimeout(t.step_func(function() {t.done()}), 50);
+ }
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/closing-handshake/004.html b/tests/wpt/web-platform-tests/websockets/closing-handshake/004.html
new file mode 100644
index 00000000000..9f4c58a2f3c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/closing-handshake/004.html
@@ -0,0 +1,22 @@
+<!doctype html>
+<title>WebSockets: data after closing handshake</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/echo_close_data');
+ ws.onmessage = ws.onerror = t.step_func(function() {assert_unreached()});
+
+ ws.onopen = t.step_func(function(e) {
+ ws.send('Goodbye');
+ })
+
+ ws.onclose = t.step_func(function(e) {
+ assert_equals(e.wasClean, true);
+ ws.onclose = t.step_func(function() {assert_unreached()});
+ setTimeout(t.step_func(function() {t.done()}), 50);
+ })
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/constants.js b/tests/wpt/web-platform-tests/websockets/constants.js
new file mode 100644
index 00000000000..f7d46d2c44e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/constants.js
@@ -0,0 +1,18 @@
+//This file requires server-side substitutions and must be included as constants.js?pipe=config
+var DOMAIN_FOR_WS_TESTS = "{{host}}";
+var DOMAIN_FOR_WSS_TESTS = "{{host}}";
+
+var PORT = "{{ports[ws][0]}}";
+//FIXME: Add support for wss
+var PORT_SSL = "{{ports[ws][0]}}";
+
+// logic for using wss URLs instead of ws
+var SCHEME_AND_DOMAIN;
+var SCHEME_DOMAIN_PORT;
+if (location.search == '?wss') {
+ SCHEME_AND_DOMAIN = 'wss://'+DOMAIN_FOR_WSS_TESTS;
+ SCHEME_DOMAIN_PORT = SCHEME_AND_DOMAIN + ":" + PORT_SSL;
+} else {
+ SCHEME_AND_DOMAIN = 'ws://'+DOMAIN_FOR_WS_TESTS;
+ SCHEME_DOMAIN_PORT = SCHEME_AND_DOMAIN + ":" + PORT;
+}
diff --git a/tests/wpt/web-platform-tests/websockets/constructor.html b/tests/wpt/web-platform-tests/websockets/constructor.html
new file mode 100644
index 00000000000..ca379bdfa2b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/constructor.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<title>WebSocket constructor</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="websocket.js?pipe=sub"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ var ws = new WebSocket("ws://" + __SERVER__NAME + ":" + __PORT + "/" + __PATH,
+ "echo", "Stray argument")
+ assert_true(ws instanceof WebSocket, "Expected a WebSocket instance.")
+}, "Calling the WebSocket constructor with too many arguments should not throw.")
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/constructor/001.html b/tests/wpt/web-platform-tests/websockets/constructor/001.html
new file mode 100644
index 00000000000..64abe3e96f3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/constructor/001.html
@@ -0,0 +1,11 @@
+<!doctype html>
+<title>WebSockets: new WebSocket() with no args</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+test(function() {
+ assert_throws(new TypeError(), function(){new WebSocket()});
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/constructor/002.html b/tests/wpt/web-platform-tests/websockets/constructor/002.html
new file mode 100644
index 00000000000..956cb1e9248
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/constructor/002.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<title>WebSockets: new WebSocket(invalid url)</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+test(function() {assert_throws("SyntaxError", function(){new WebSocket("/test")})});
+test(function() {assert_throws("SyntaxError", function(){new WebSocket("ws://foo bar.com/")})});
+test(function() {assert_throws("SyntaxError", function(){new WebSocket("wss://foo bar.com/")})});
+test(function() {assert_throws("SyntaxError", function(){new WebSocket("http://"+location.host+"/")})});
+test(function() {assert_throws("SyntaxError", function(){new WebSocket("mailto:example@example.org")})});
+test(function() {assert_throws("SyntaxError", function(){new WebSocket("about:blank")})});
+test(function() {assert_throws("SyntaxError", function(){new WebSocket("ws://"+location.host+"/#")})});
+test(function() {assert_throws("SyntaxError", function(){new WebSocket("ws://"+location.host+"/#test")})});
+test(function() {assert_throws("SyntaxError", function(){new WebSocket("?test")})});
+test(function() {assert_throws("SyntaxError", function(){new WebSocket("#test")})});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/constructor/004.html b/tests/wpt/web-platform-tests/websockets/constructor/004.html
new file mode 100644
index 00000000000..a58fb3720ac
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/constructor/004.html
@@ -0,0 +1,23 @@
+<!doctype html>
+<title>WebSockets: new WebSocket(url, invalid protocol)</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+// empty string
+test(function() {assert_throws("SyntaxError", function(){new WebSocket("ws://"+location.host+"/", "")})});
+
+// chars below U+0020 except U+0000; U+0000 is tested in a separate test
+for (var i = 1; i < 0x20; ++i) {
+test(function() {
+ assert_throws("SyntaxError", function(){new WebSocket("ws://"+location.host+"/", "a"+String.fromCharCode(i)+"b")}, 'char code '+i);
+})
+}
+// some chars above U+007E
+for (var i = 0x7F; i < 0x100; ++i) {
+test(function() {
+ assert_throws("SyntaxError", function(){new WebSocket("ws://"+location.host+"/", "a"+String.fromCharCode(i)+"b")}, 'char code '+i);
+})
+}
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/constructor/005.html b/tests/wpt/web-platform-tests/websockets/constructor/005.html
new file mode 100644
index 00000000000..bb4d6d0f29a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/constructor/005.html
@@ -0,0 +1,11 @@
+<!doctype html>
+<title>WebSockets: return value</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+test(function() {
+ assert_true(new WebSocket("ws://"+location.host+"/") instanceof WebSocket);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/constructor/006.html b/tests/wpt/web-platform-tests/websockets/constructor/006.html
new file mode 100644
index 00000000000..83e77095694
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/constructor/006.html
@@ -0,0 +1,26 @@
+<!doctype html>
+<title>WebSockets: converting first arguments</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var a = document.createElement('a');
+ a.href = SCHEME_DOMAIN_PORT+'/echo';
+ var ws = new WebSocket(a); // should stringify arguments; <a> stringifies to its .href
+ assert_equals(ws.url, a.href);
+ ws.onopen = t.step_func(function(e) {
+ ws.send('test');
+ });
+ ws.onmessage = t.step_func(function(e) {
+ assert_equals(e.data, 'test');
+ ws.onclose = t.step_func(function(e) {
+ ws.onclose = t.step_func(function() {assert_unreached()});
+ setTimeout(t.step_func(function() {t.done()}), 50);
+ });
+ ws.close();
+ });
+ ws.onerror = ws.onclose = t.step_func(function() {assert_unreached()});
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/constructor/007.html b/tests/wpt/web-platform-tests/websockets/constructor/007.html
new file mode 100644
index 00000000000..a3985cdcc6b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/constructor/007.html
@@ -0,0 +1,9 @@
+<!doctype html>
+<title>WebSockets: new WebSocket(url, null char)</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+test(function() {assert_throws("SyntaxError", function(){new WebSocket("ws://"+location.host+"/", 'a'+String.fromCharCode(0)+'b')})});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/constructor/008.html b/tests/wpt/web-platform-tests/websockets/constructor/008.html
new file mode 100644
index 00000000000..2ed97ee17a7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/constructor/008.html
@@ -0,0 +1,13 @@
+<!doctype html>
+<title>WebSockets: new WebSocket(url with not blocked port)</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+//Pass condition is to not throw
+test(function(){new WebSocket('ws://example.invalid:80/')});
+test(function(){new WebSocket('ws://example.invalid:443/')});
+test(function(){new WebSocket('wss://example.invalid:80/')});
+test(function(){new WebSocket('wss://example.invalid:443/')});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/constructor/009.html b/tests/wpt/web-platform-tests/websockets/constructor/009.html
new file mode 100644
index 00000000000..b0fb80d74f2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/constructor/009.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<title>WebSockets: protocol</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/protocol', 'foobar');
+
+ ws.onmessage = t.step_func(function(e) {
+ assert_equals(ws.protocol, 'foobar');
+ ws.onclose = t.step_func(function(e) {
+ ws.onclose = t.step_func(function() {assert_unreached()});
+ setTimeout(t.step_func(function() {t.done()}), 50);
+ })
+ ws.close();
+ })
+ ws.onerror = t.step_func(function() {assert_unreached()});
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/constructor/010.html b/tests/wpt/web-platform-tests/websockets/constructor/010.html
new file mode 100644
index 00000000000..4abb417beef
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/constructor/010.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<title>WebSockets: protocol in response but no requested protocol</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/handshake_protocol');
+ ws.onerror = ws.onmessage = ws.onclose = t.step_func(function(e) {assert_unreached(e.type)});
+ ws.onopen = t.step_func(function(e) {
+ ws.onclose = t.step_func(function(e) {
+ ws.onclose = t.step_func(function(e) {assert_unreached(e.type)});
+ setTimeout(t.step_func(function() {t.done();}), 50);
+ })
+ ws.close();
+ })
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/websockets/constructor/011.html b/tests/wpt/web-platform-tests/websockets/constructor/011.html
new file mode 100644
index 00000000000..0efe0221651
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/constructor/011.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<title>WebSockets: protocol mismatch</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/handshake_protocol', 'FOOBAR');
+ var gotOpen = false;
+ var gotError = false;
+ ws.onopen = t.step_func(function(e) {
+ gotOpen = true;
+ })
+ ws.onerror = t.step_func(function(e) {
+ gotError = true;
+ })
+ ws.onclose = t.step_func(function(e) {
+ assert_true(gotOpen, 'got open');
+ assert_true(gotError, 'got error');
+ ws.onclose = t.step_func(function() {assert_unreached()});
+ setTimeout(t.step_func(function() {t.done();}), 50);
+ })
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/constructor/012.html b/tests/wpt/web-platform-tests/websockets/constructor/012.html
new file mode 100644
index 00000000000..66ca9eaf2a9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/constructor/012.html
@@ -0,0 +1,17 @@
+<!doctype html>
+<title>WebSockets: no protocol in response</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/handshake_no_protocol', 'foobar');
+ ws.onclose = t.step_func(function(e) {
+ ws.onclose = t.step_func(function() {assert_unreached()});
+ setTimeout(t.step_func(function() {t.done();}), 50)
+ })
+ ws.onmessage = t.step_func(function() {assert_unreached()});
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/websockets/constructor/013.html b/tests/wpt/web-platform-tests/websockets/constructor/013.html
new file mode 100644
index 00000000000..137922daeb0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/constructor/013.html
@@ -0,0 +1,39 @@
+<!doctype html>
+<title>WebSockets: multiple WebSocket objects</title>
+<meta name=timeout content=long>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ // test that the events are fired as they should when opening 25 websockets and
+ // sending a message on each and then closing when getting the message back
+ var ws = [];
+ var events = 0;
+ for (var i = 0; i < 25; ++i) {
+ ws[i] = new WebSocket(SCHEME_DOMAIN_PORT+'/echo');
+ ws[i].id = i;
+ ws[i].onopen = t.step_func(function(e) {
+ events++;
+ this.send(this.id);
+ this.onopen = t.step_func(function() {assert_unreached()});
+ }, ws[i]);
+ ws[i].onmessage = t.step_func(function(e) {
+ events++;
+ assert_equals(e.data, ''+this.id);
+ this.close();
+ this.onmessage = t.step_func(function() {assert_unreached()});
+ }, ws[i]);
+ ws[i].onclose = t.step_func(function(e) {
+ events++;
+ if (events == 75) {
+ t.done();
+ }
+ this.onclose = t.step_func(function() {assert_unreached()});
+ }, ws[i]);
+ ws[i].onerror = t.step_func(function() {assert_unreached()});
+ }
+}, null, {timeout:25000});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/websockets/constructor/014.html b/tests/wpt/web-platform-tests/websockets/constructor/014.html
new file mode 100644
index 00000000000..b7d1e839015
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/constructor/014.html
@@ -0,0 +1,35 @@
+<!doctype html>
+<title>WebSockets: serialize establish a connection</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+
+async_test(function(t) {
+ var ws = [];
+ var events = 0;
+ var prevDate;
+ var date;
+ for (var i = 0; i < 4; ++i) {
+ ws[i] = new WebSocket(SCHEME_DOMAIN_PORT+'/handshake_sleep_1');
+ ws[i].id = i;
+ ws[i].onopen = t.step_func(function(e) {
+ events++;
+ date = new Date();
+ if (prevDate)
+ assert_greater_than(date-prevDate, 998);
+ prevDate = date;
+ this.onopen = t.step_func(function() {assert_unreached()});
+ })
+ ws[i].onclose = t.step_func(function(e) {
+ events++;
+ if (events == 8) {
+ t.done();
+ }
+ this.onclose = t.step_func(function() {assert_unreached()});
+ });
+ ws[i].onerror = ws[i].onmessage = t.step_func(function() {assert_unreached()});
+ }
+}, null, {timeout:10000});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/constructor/016.html b/tests/wpt/web-platform-tests/websockets/constructor/016.html
new file mode 100644
index 00000000000..938d591e363
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/constructor/016.html
@@ -0,0 +1,17 @@
+<!doctype html>
+<meta charset=windows-1252>
+<title>WebSockets: non-ascii URL in query, document encoding windows-1252</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/echo-query_v13?');
+ ws.onclose = t.step_func(function() {assert_unreached()});
+ ws.onmessage = t.step_func(function(e) {
+ assert_equals(e.data, '%C3%A5%C3%A4%C3%B6');
+ t.done();
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/constructor/017.html b/tests/wpt/web-platform-tests/websockets/constructor/017.html
new file mode 100644
index 00000000000..18356867754
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/constructor/017.html
@@ -0,0 +1,13 @@
+<!doctype html>
+<title>WebSockets: too few slashes after ws: and wss:</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+var tests = ['ws:', 'ws:/', 'wss:', 'wss:/'];
+//Pass condition is to not throw
+for (var i = 0; i < tests.length; ++i) {
+ test(function(){new WebSocket(tests[i]+location.host+'/echo')}, tests[i]);
+}
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/constructor/018.html b/tests/wpt/web-platform-tests/websockets/constructor/018.html
new file mode 100644
index 00000000000..71359d0d093
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/constructor/018.html
@@ -0,0 +1,17 @@
+<!doctype html>
+<title>WebSockets: NULL char in url</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/echo-query?x\u0000');
+ ws.onmessage = t.step_func(function(e) {
+ assert_equals(e.data, 'x%00');
+ ws.close();
+ t.done();
+ })
+ ws.onclose = ws.onerror = t.step_func(function(e) {assert_unreached(e.type)});
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/constructor/019.html b/tests/wpt/web-platform-tests/websockets/constructor/019.html
new file mode 100644
index 00000000000..9e5c7922519
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/constructor/019.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<title>WebSockets: uppercase 'WS:'</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var scheme = SCHEME_DOMAIN_PORT.split('://')[0];
+ var domain = SCHEME_DOMAIN_PORT.split('://')[1];
+ var ws = new WebSocket(scheme.toUpperCase()+'://'+domain+'/echo');
+ ws.onopen = t.step_func(function(e) {
+ ws.close();
+ t.done();
+ })
+ ws.onclose = ws.onerror = ws.onmessage = t.step_func(function() {assert_unreached()});
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/constructor/020.html b/tests/wpt/web-platform-tests/websockets/constructor/020.html
new file mode 100644
index 00000000000..37aaf8d01c7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/constructor/020.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<title>WebSockets: uppercase host</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var scheme = SCHEME_DOMAIN_PORT.split('://')[0];
+ var domain = SCHEME_DOMAIN_PORT.split('://')[1];
+ var ws = new WebSocket(scheme+'://'+domain.toUpperCase()+'/echo');
+ ws.onopen = t.step_func(function(e) {
+ ws.close();
+ t.done();
+ });
+ ws.onclose = ws.onerror = ws.onmessage = t.step_func(function() {assert_unreached()});
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/constructor/021.html b/tests/wpt/web-platform-tests/websockets/constructor/021.html
new file mode 100644
index 00000000000..a313c7734bf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/constructor/021.html
@@ -0,0 +1,9 @@
+<!doctype html>
+<title>WebSockets: Same sub protocol twice</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+test(function() {assert_throws("SyntaxError", function(){new WebSocket("ws://certo2.oslo.osa/protocol_array",["foobar, foobar"])})});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/constructor/022.html b/tests/wpt/web-platform-tests/websockets/constructor/022.html
new file mode 100644
index 00000000000..0e6c3480717
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/constructor/022.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<title>WebSockets: protocol array</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/protocol_array',['foobar','foobar2']);
+ ws.onmessage = t.step_func(function(e) {
+ assert_equals(ws.protocol, 'foobar');
+ ws.onclose = t.step_func(function(e) {
+ ws.onclose = t.step_func(function() {assert_unreached()});
+ setTimeout(t.step_func(function() {t.done();}), 50)
+ });
+ ws.close();
+ });
+ ws.onerror = t.step_func(function() {assert_unreached()});
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/cookies/001.html b/tests/wpt/web-platform-tests/websockets/cookies/001.html
new file mode 100644
index 00000000000..b0701d0cd91
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/cookies/001.html
@@ -0,0 +1,23 @@
+<!doctype html>
+<title>WebSockets: Cookie in request</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+var cookie_id = ((new Date())-0) + '.' + Math.random();
+async_test(function(t) {
+ if (window.WebSocket) {
+ document.cookie = 'ws_test_'+cookie_id+'=test; Path=/';
+ }
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/echo-cookie');
+ ws.onmessage = t.step_func(function(e) {
+ assert_regexp_match(e.data, new RegExp('ws_test_'+cookie_id+'=test'));
+ ws.close();
+ t.done();
+ });
+ ws.onerror = ws.onclose = t.step_func(function(e) {assert_unreached(e.type)});
+});
+// remove cookie
+document.cookie = 'ws_test_'+cookie_id+'=; Path=/; Expires=Sun, 06 Nov 1994 08:49:37 GMT';
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/cookies/002.html b/tests/wpt/web-platform-tests/websockets/cookies/002.html
new file mode 100644
index 00000000000..1e6a1dbeab2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/cookies/002.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<title>WebSockets: Set-Cookie in response</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+var cookie_id = ((new Date())-0) + '.' + Math.random();
+async_test(function(t) {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/set-cookie?'+cookie_id);
+ ws.onopen = t.step_func(function(e) {
+ assert_regexp_match(document.cookie, new RegExp('ws_test_'+cookie_id+'=test'));
+ // remove cookie
+ document.cookie = 'ws_test_'+cookie_id+'=; Path=/; Expires=Sun, 06 Nov 1994 08:49:37 GMT';
+ ws.close();
+ t.done();
+ });
+ ws.onerror = ws.onclose = t.step_func(function(e) {assert_unreached(e.type)});
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/cookies/003.html b/tests/wpt/web-platform-tests/websockets/cookies/003.html
new file mode 100644
index 00000000000..e424d9fcf92
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/cookies/003.html
@@ -0,0 +1,33 @@
+<!doctype html>
+<title>WebSockets: sending HttpOnly cookies in ws request</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+setup({explict_done:true})
+var cookie_id = ((new Date())-0) + '.' + Math.random();
+
+var t = async_test(function(t) {
+var iframe = document.createElement('iframe');
+iframe.src = 'support/set-cookie.py?'+encodeURIComponent('ws_test_'+cookie_id+'=test; Path=/; HttpOnly');
+iframe.onload = t.step_func(function() {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/echo-cookie');
+ ws.onmessage = t.step_func(function(e) {
+ ws.close();
+ assert_regexp_match(e.data, new RegExp('ws_test_'+cookie_id+'=test'));
+ t.done();;
+ });
+ ws.onclose = function() { deleteCookie(false, e.type); }
+});
+
+var cookie_removed = false;
+
+add_result_callback(function() {
+ iframe.src = 'support/set-cookie.py?'+encodeURIComponent('ws_test_'+cookie_id+'=; Path=/; HttpOnly; Expires=Sun, 06 Nov 1994 08:49:37 GMT');
+ iframe.onload = done;
+});
+
+document.body.appendChild(iframe);
+}, null, {timeout:9900});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/cookies/004.html b/tests/wpt/web-platform-tests/websockets/cookies/004.html
new file mode 100644
index 00000000000..894ef2eff89
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/cookies/004.html
@@ -0,0 +1,29 @@
+<!doctype html>
+<title>WebSockets: setting HttpOnly cookies in ws response, checking document.cookie</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+setup({explicit_done:true})
+var cookie_id = ((new Date())-0) + '.' + Math.random();
+
+var t = async_test(function(t) {
+ var iframe = document.createElement('iframe');
+ var url = SCHEME_DOMAIN_PORT+'/set-cookie_http?'+cookie_id;
+ var ws = new WebSocket(url);
+ ws.onopen = t.step_func(function(e) {
+ ws.close();
+ assert_false(new RegExp('ws_test_'+cookie_id+'=test').test(document.cookie));
+ t.done();
+ });
+ ws.onclose = t.step_func(function(e) {assert_unreached()});
+
+
+ add_result_callback(function() {
+ iframe.src = 'support/set-cookie.py?'+encodeURIComponent('ws_test_'+cookie_id+'=; Path=/; HttpOnly; Expires=Sun, 06 Nov 1994 08:49:37 GMT');
+ iframe.onload = done;
+ });
+ document.body.appendChild(iframe);
+}, null, {timeout:9900})
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/cookies/005.html b/tests/wpt/web-platform-tests/websockets/cookies/005.html
new file mode 100644
index 00000000000..e7aefd5978e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/cookies/005.html
@@ -0,0 +1,32 @@
+<!doctype html>
+<title>WebSockets: setting HttpOnly cookies in ws response, checking ws request</title>
+<meta name=timeout content=long>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+setup({explicit_done:true})
+var cookie_id = ((new Date())-0) + '.' + Math.random();
+
+var t = async_test(function(t) {
+ var iframe = document.createElement('iframe');
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/set-cookie_http?'+cookie_id);
+ ws.onopen = t.step_func(function(e) {
+ var ws2 = new WebSocket(SCHEME_DOMAIN_PORT+'/echo-cookie');
+ ws2.onmessage = t.step_func(function(e) {
+ ws.close();
+ ws2.close();
+ assert_regexp_match(e.data, new RegExp('ws_test_'+cookie_id+'=test'));
+ t.done();
+ });
+ });
+ ws.onclose = t.step_func(function() {assert_unreached()});
+
+ add_result_callback(function() {
+ iframe.src = 'support/set-cookie.py?'+encodeURIComponent('ws_test_'+cookie_id+'=; Path=/; HttpOnly; Expires=Sun, 06 Nov 1994 08:49:37 GMT');
+ iframe.onload = done;
+ });
+ document.body.appendChild(iframe);
+})
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/cookies/006.html b/tests/wpt/web-platform-tests/websockets/cookies/006.html
new file mode 100644
index 00000000000..05c848033b1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/cookies/006.html
@@ -0,0 +1,27 @@
+<!doctype html>
+<title>WebSockets: setting Secure cookie with document.cookie, checking ws request</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+var cookie_id = ((new Date())-0) + '.' + Math.random();
+async_test(function(t) {
+ if (window.WebSocket) {
+ document.cookie = 'ws_test_'+cookie_id+'=test; Path=/; Secure';
+ }
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/echo-cookie');
+ ws.onmessage = t.step_func(function(e) {
+ ws.close();
+ if (SCHEME_DOMAIN_PORT.substr(0,3) == 'wss') {
+ assert_regexp_match(e.data, new RegExp('ws_test_'+cookie_id+'=test'));
+ } else {
+ assert_false(new RegExp('ws_test_'+cookie_id+'=test').test(e.data));
+ }
+ t.done();
+ })
+ ws.onclose = t.step_func(function() {assert_unreached()});
+});
+// remove cookie
+document.cookie = 'ws_test_'+cookie_id+'; Path=/; Secure; Expires=Sun, 06 Nov 1994 08:49:37 GMT';
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/cookies/007.html b/tests/wpt/web-platform-tests/websockets/cookies/007.html
new file mode 100644
index 00000000000..efea696a1e9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/cookies/007.html
@@ -0,0 +1,30 @@
+<!doctype html>
+<title>WebSockets: when to process set-cookie fields in ws response</title>
+<meta name=timeout content=long>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+var cookie_id = ((new Date())-0) + '.' + Math.random();
+async_test(function(t) {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/set-cookie?'+cookie_id);
+ ws.onopen = t.step_func(function(e) {
+ ws.close();
+ assert_regexp_match(document.cookie, new RegExp('ws_test_'+cookie_id+'=test'));
+ // remove cookie
+ document.cookie = 'ws_test_'+cookie_id+'; Path=/; Expires=Sun, 06 Nov 1994 08:49:37 GMT';
+ t.done();
+ });
+ ws.onclose = t.step_func(function() {assert_unreached()});
+
+ // sleep for 2 seconds with sync xhr
+ var sleep = new XMLHttpRequest();
+ sleep.open('GET', '/common/blank.html?pipe=trickle(d2)', false);
+ sleep.send(null);
+
+ if (new RegExp('ws_test_'+cookie_id+'=test').test(document.cookie)) {
+ assert_unreached('cookie was set during script execution');
+ }
+}, null, {timeout:12000});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/cookies/support/set-cookie.py b/tests/wpt/web-platform-tests/websockets/cookies/support/set-cookie.py
new file mode 100644
index 00000000000..8a47d7cdd8e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/cookies/support/set-cookie.py
@@ -0,0 +1,5 @@
+import urllib
+
+def main(request, response):
+ response.headers.set('Set-Cookie', urllib.unquote(request.url_parts.query))
+ return [("Content-Type", "text/plain")], ""
diff --git a/tests/wpt/web-platform-tests/websockets/eventhandlers.html b/tests/wpt/web-platform-tests/websockets/eventhandlers.html
new file mode 100644
index 00000000000..4fae08d4338
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/eventhandlers.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<title>WebSocket event handlers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="websocket.js?pipe=sub"></script>
+<div id="log"></div>
+<script>
+function testEventHandler(name) {
+ test(function() {
+ var ws = new WebSocket("ws://" + __SERVER__NAME + ":" + __PORT + "/" + __PATH,
+ "echo")
+ assert_equals(ws["on" + name], null);
+ ws["on" + name] = function() {};
+ ws["on" + name] = 2;
+ assert_equals(ws["on" + name], null);
+ }, "Event handler for " + name + " should have [TreatNonCallableAsNull]")
+}
+["open", "error", "close", "message"].forEach(testEventHandler);
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/extended-payload-length.html b/tests/wpt/web-platform-tests/websockets/extended-payload-length.html
new file mode 100644
index 00000000000..af0d90f0eb9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/extended-payload-length.html
@@ -0,0 +1,65 @@
+<!doctype html>
+<title>WebSockets : Boundary-value tests for the 'Extended payload length' field in RFC6455 section5.2 'Base Framing Protocol'</title>
+<meta name=timeout content=long>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+async_test(function(t){
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/echo');
+ var datasize = 125;
+ var data = null;
+ ws.onopen = t.step_func(function(e) {
+ data = new Array(datasize + 1).join('a');
+ ws.send(data);
+ });
+ ws.onmessage = t.step_func(function(e) {
+ assert_equals(e.data, data);
+ t.done();
+ });
+}, "Application data is 125 byte which means any 'Extended payload length' field isn't used at all.", {timeout:20000});
+
+async_test(function(t){
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/echo');
+ var datasize = 126;
+ var data = null;
+ ws.onopen = t.step_func(function(e) {
+ data = new Array(datasize + 1).join('a');
+ ws.send(data);
+ });
+ ws.onmessage = t.step_func(function(e) {
+ assert_equals(e.data, data);
+ t.done();
+ });
+}, "Application data is 126 byte which starts to use the 16 bit 'Extended payload length' field.", {timeout:20000});
+
+async_test(function(t){
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/echo');
+ var datasize = 0xFFFF;
+ var data = null;
+ ws.onopen = t.step_func(function(e) {
+ data = new Array(datasize + 1).join('a');
+ ws.send(data);
+ });
+ ws.onmessage = t.step_func(function(e) {
+ assert_equals(e.data, data);
+ t.done();
+ });
+}, "Application data is 0xFFFF byte which means the upper bound of the 16 bit 'Extended payload length' field.", {timeout:20000});
+
+async_test(function(t){
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/echo');
+ var datasize = 0xFFFF + 1;
+ var data = null;
+ ws.onopen = t.step_func(function(e) {
+ data = new Array(datasize + 1).join('a');
+ ws.send(data);
+ });
+ ws.onmessage = t.step_func(function(e) {
+ assert_equals(e.data, data);
+ t.done();
+ });
+}, "Application data is (0xFFFF + 1) byte which starts to use the 64 bit 'Extended payload length' field", {timeout:20000});
+
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/handlers/echo-cookie_wsh.py b/tests/wpt/web-platform-tests/websockets/handlers/echo-cookie_wsh.py
new file mode 100755
index 00000000000..367d03190cf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/handlers/echo-cookie_wsh.py
@@ -0,0 +1,12 @@
+#!/usr/bin/python
+
+from mod_pywebsocket import msgutil
+
+def web_socket_do_extra_handshake(request):
+ request.ws_cookie = request.headers_in.get('Cookie')
+
+def web_socket_transfer_data(request):
+ if request.ws_cookie is not None:
+ msgutil.send_message(request, request.ws_cookie)
+ else:
+ msgutil.send_message(request, '(none)')
diff --git a/tests/wpt/web-platform-tests/websockets/handlers/echo-query_v13_wsh.py b/tests/wpt/web-platform-tests/websockets/handlers/echo-query_v13_wsh.py
new file mode 100755
index 00000000000..4083c49bc7e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/handlers/echo-query_v13_wsh.py
@@ -0,0 +1,11 @@
+#!/usr/bin/python
+
+from mod_pywebsocket import msgutil, util
+
+def web_socket_do_extra_handshake(request):
+ pass
+
+def web_socket_transfer_data(request):
+ while True:
+ msgutil.send_message(request, request.unparsed_uri.split('?')[1] or '')
+ return
diff --git a/tests/wpt/web-platform-tests/websockets/handlers/echo-query_wsh.py b/tests/wpt/web-platform-tests/websockets/handlers/echo-query_wsh.py
new file mode 100755
index 00000000000..8fd7ac36b2a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/handlers/echo-query_wsh.py
@@ -0,0 +1,9 @@
+#!/usr/bin/python
+
+from mod_pywebsocket import msgutil, util
+
+def web_socket_do_extra_handshake(request):
+ pass # Always accept.
+
+def web_socket_transfer_data(request):
+ msgutil.send_message(request, request.unparsed_uri.split('?', 1)[1] or '')
diff --git a/tests/wpt/web-platform-tests/websockets/handlers/echo_close_data_wsh.py b/tests/wpt/web-platform-tests/websockets/handlers/echo_close_data_wsh.py
new file mode 100755
index 00000000000..4da4ce61f7b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/handlers/echo_close_data_wsh.py
@@ -0,0 +1,22 @@
+#!/usr/bin/python
+from mod_pywebsocket import msgutil
+
+_GOODBYE_MESSAGE = u'Goodbye'
+
+def web_socket_do_extra_handshake(request):
+ # This example handler accepts any request. See origin_check_wsh.py for how
+ # to reject access from untrusted scripts based on origin value.
+
+ pass # Always accept.
+
+
+def web_socket_transfer_data(request):
+ while True:
+ line = request.ws_stream.receive_message()
+ if line is None:
+ return
+ if isinstance(line, unicode):
+ if line == _GOODBYE_MESSAGE:
+ return
+ request.ws_stream.send_message(line, binary=False)
+
diff --git a/tests/wpt/web-platform-tests/websockets/handlers/echo_exit_wsh.py b/tests/wpt/web-platform-tests/websockets/handlers/echo_exit_wsh.py
new file mode 100755
index 00000000000..200b92e583b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/handlers/echo_exit_wsh.py
@@ -0,0 +1,21 @@
+#!/usr/bin/python
+from mod_pywebsocket import msgutil
+
+_GOODBYE_MESSAGE = u'Goodbye'
+
+def web_socket_do_extra_handshake(request):
+ # This example handler accepts any request. See origin_check_wsh.py for how
+ # to reject access from untrusted scripts based on origin value.
+
+ pass # Always accept.
+
+
+def web_socket_transfer_data(request):
+ while True:
+ line = request.ws_stream.receive_message()
+ if line is None:
+ return
+ if isinstance(line, unicode):
+ if line == _GOODBYE_MESSAGE:
+ return
+
diff --git a/tests/wpt/web-platform-tests/websockets/handlers/echo_raw_wsh.py b/tests/wpt/web-platform-tests/websockets/handlers/echo_raw_wsh.py
new file mode 100755
index 00000000000..c3a030c9689
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/handlers/echo_raw_wsh.py
@@ -0,0 +1,15 @@
+#!/usr/bin/python
+
+from mod_pywebsocket import msgutil
+import urllib
+
+
+def web_socket_do_extra_handshake(request):
+ pass # Always accept.
+
+def web_socket_transfer_data(request):
+ while True:
+ line = msgutil.receive_message(request)
+ if line == 'exit':
+ return
+ request.connection.write(line.decode("string-escape"))
diff --git a/tests/wpt/web-platform-tests/websockets/handlers/echo_wsh.py b/tests/wpt/web-platform-tests/websockets/handlers/echo_wsh.py
new file mode 100755
index 00000000000..5829c2f8c18
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/handlers/echo_wsh.py
@@ -0,0 +1,25 @@
+#!/usr/bin/python
+from mod_pywebsocket import msgutil
+
+_GOODBYE_MESSAGE = u'Goodbye'
+
+def web_socket_do_extra_handshake(request):
+ # This example handler accepts any request. See origin_check_wsh.py for how
+ # to reject access from untrusted scripts based on origin value.
+ if request.ws_requested_protocols:
+ if "echo" in request.ws_requested_protocols:
+ request.ws_protocol = "echo"
+
+
+def web_socket_transfer_data(request):
+ while True:
+ line = request.ws_stream.receive_message()
+ if line is None:
+ return
+ if isinstance(line, unicode):
+ request.ws_stream.send_message(line, binary=False)
+ if line == _GOODBYE_MESSAGE:
+ return
+ else:
+ request.ws_stream.send_message(line, binary=True)
+
diff --git a/tests/wpt/web-platform-tests/websockets/handlers/empty-message_wsh.py b/tests/wpt/web-platform-tests/websockets/handlers/empty-message_wsh.py
new file mode 100755
index 00000000000..0eb107f0b12
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/handlers/empty-message_wsh.py
@@ -0,0 +1,13 @@
+#!/usr/bin/python
+
+from mod_pywebsocket import msgutil
+
+def web_socket_do_extra_handshake(request):
+ pass # Always accept.
+
+def web_socket_transfer_data(request):
+ line = msgutil.receive_message(request)
+ if line == "":
+ msgutil.send_message(request, 'pass')
+ else:
+ msgutil.send_message(request, 'fail')
diff --git a/tests/wpt/web-platform-tests/websockets/handlers/handshake_no_protocol_wsh.py b/tests/wpt/web-platform-tests/websockets/handlers/handshake_no_protocol_wsh.py
new file mode 100755
index 00000000000..3e6b8e664c2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/handlers/handshake_no_protocol_wsh.py
@@ -0,0 +1,12 @@
+#!/usr/bin/python
+
+from mod_pywebsocket import common, msgutil, util
+from mod_pywebsocket.handshake import hybi
+
+def web_socket_do_extra_handshake(request):
+ request.connection.write('HTTP/1.1 101 Switching Protocols:\x0D\x0AConnection: Upgrade\x0D\x0AUpgrade: WebSocket\x0D\x0ASec-WebSocket-Origin: '+request.ws_origin+'\x0D\x0ASec-WebSocket-Accept: '+hybi.compute_accept(request.headers_in.get(common.SEC_WEBSOCKET_KEY_HEADER))[0]+'\x0D\x0A\x0D\x0A')
+ return
+
+def web_socket_transfer_data(request):
+ while True:
+ return
diff --git a/tests/wpt/web-platform-tests/websockets/handlers/handshake_protocol_wsh.py b/tests/wpt/web-platform-tests/websockets/handlers/handshake_protocol_wsh.py
new file mode 100755
index 00000000000..d3ebb273daa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/handlers/handshake_protocol_wsh.py
@@ -0,0 +1,12 @@
+#!/usr/bin/python
+
+from mod_pywebsocket import common, msgutil, util
+from mod_pywebsocket.handshake import hybi
+
+def web_socket_do_extra_handshake(request):
+ request.connection.write('HTTP/1.1 101 Switching Protocols:\x0D\x0AConnection: Upgrade\x0D\x0AUpgrade: WebSocket\x0D\x0ASec-WebSocket-Protocol: foobar\x0D\x0ASec-WebSocket-Origin: '+request.ws_origin+'\x0D\x0ASec-WebSocket-Accept: '+hybi.compute_accept(request.headers_in.get(common.SEC_WEBSOCKET_KEY_HEADER))[0]+'\x0D\x0A\x0D\x0A')
+ return
+
+def web_socket_transfer_data(request):
+ while True:
+ return \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/websockets/handlers/handshake_sleep_1_wsh.py b/tests/wpt/web-platform-tests/websockets/handlers/handshake_sleep_1_wsh.py
new file mode 100755
index 00000000000..df785a4f7c8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/handlers/handshake_sleep_1_wsh.py
@@ -0,0 +1,10 @@
+#!/usr/bin/python
+
+from mod_pywebsocket import msgutil
+import time
+
+def web_socket_do_extra_handshake(request):
+ time.sleep(1)
+
+def web_socket_transfer_data(request):
+ pass
diff --git a/tests/wpt/web-platform-tests/websockets/handlers/invalid_wsh.py b/tests/wpt/web-platform-tests/websockets/handlers/invalid_wsh.py
new file mode 100755
index 00000000000..886e970b8dc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/handlers/invalid_wsh.py
@@ -0,0 +1,9 @@
+#!/usr/bin/python
+
+from mod_pywebsocket import msgutil
+
+def web_socket_do_extra_handshake(request):
+ request.connection.write("FOO BAR BAZ\r\n\r\n")
+
+def web_socket_transfer_data(request):
+ pass
diff --git a/tests/wpt/web-platform-tests/websockets/handlers/origin_wsh.py b/tests/wpt/web-platform-tests/websockets/handlers/origin_wsh.py
new file mode 100755
index 00000000000..ce5f3a7f6ae
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/handlers/origin_wsh.py
@@ -0,0 +1,11 @@
+#!/usr/bin/python
+
+from mod_pywebsocket import msgutil
+
+
+def web_socket_do_extra_handshake(request):
+ pass # Always accept.
+
+
+def web_socket_transfer_data(request):
+ msgutil.send_message(request, request.ws_origin)
diff --git a/tests/wpt/web-platform-tests/websockets/handlers/protocol_array_wsh.py b/tests/wpt/web-platform-tests/websockets/handlers/protocol_array_wsh.py
new file mode 100755
index 00000000000..5d46c588c27
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/handlers/protocol_array_wsh.py
@@ -0,0 +1,14 @@
+#!/usr/bin/python
+
+from mod_pywebsocket import msgutil, util
+
+def web_socket_do_extra_handshake(request):
+ line = request.headers_in.get('Sec-WebSocket-Protocol')
+ request.ws_protocol = line.split(',', 1)[0]
+
+#pass
+
+def web_socket_transfer_data(request):
+ while True:
+ msgutil.send_message(request, request.ws_protocol)
+ return
diff --git a/tests/wpt/web-platform-tests/websockets/handlers/protocol_wsh.py b/tests/wpt/web-platform-tests/websockets/handlers/protocol_wsh.py
new file mode 100755
index 00000000000..96a45258456
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/handlers/protocol_wsh.py
@@ -0,0 +1,12 @@
+#!/usr/bin/python
+
+from mod_pywebsocket import msgutil, util
+
+def web_socket_do_extra_handshake(request):
+ request.ws_protocol = request.headers_in.get('Sec-WebSocket-Protocol')
+#pass
+
+def web_socket_transfer_data(request):
+ while True:
+ msgutil.send_message(request, request.ws_protocol)
+ return
diff --git a/tests/wpt/web-platform-tests/websockets/handlers/set-cookie_http_wsh.py b/tests/wpt/web-platform-tests/websockets/handlers/set-cookie_http_wsh.py
new file mode 100755
index 00000000000..14784245711
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/handlers/set-cookie_http_wsh.py
@@ -0,0 +1,14 @@
+#!/usr/bin/python
+
+from mod_pywebsocket import common, msgutil, util
+from mod_pywebsocket.handshake import hybi
+import urlparse
+
+def web_socket_do_extra_handshake(request):
+ url_parts = urlparse.urlsplit(request.uri)
+ request.connection.write('HTTP/1.1 101 Switching Protocols:\x0D\x0AConnection: Upgrade\x0D\x0AUpgrade: WebSocket\x0D\x0ASet-Cookie: ws_test_'+(url_parts.query or '')+'=test; Path=/; HttpOnly\x0D\x0ASec-WebSocket-Origin: '+request.ws_origin+'\x0D\x0ASec-WebSocket-Accept: '+hybi.compute_accept(request.headers_in.get(common.SEC_WEBSOCKET_KEY_HEADER))[0]+'\x0D\x0A\x0D\x0A')
+ return
+
+def web_socket_transfer_data(request):
+ while True:
+ return
diff --git a/tests/wpt/web-platform-tests/websockets/handlers/set-cookie_wsh.py b/tests/wpt/web-platform-tests/websockets/handlers/set-cookie_wsh.py
new file mode 100755
index 00000000000..b0e6504765f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/handlers/set-cookie_wsh.py
@@ -0,0 +1,15 @@
+#!/usr/bin/python
+import urlparse
+
+from mod_pywebsocket import common, msgutil, util
+from mod_pywebsocket.handshake import hybi
+
+
+def web_socket_do_extra_handshake(request):
+ url_parts = urlparse.urlsplit(request.uri)
+ request.connection.write('HTTP/1.1 101 Switching Protocols:\x0D\x0AConnection: Upgrade\x0D\x0AUpgrade: WebSocket\x0D\x0ASet-Cookie: ws_test_'+(url_parts.query or '')+'=test; Path=/\x0D\x0ASec-WebSocket-Origin: '+request.ws_origin+'\x0D\x0ASec-WebSocket-Accept: '+hybi.compute_accept(request.headers_in.get(common.SEC_WEBSOCKET_KEY_HEADER))[0]+'\x0D\x0A\x0D\x0A')
+ return
+
+def web_socket_transfer_data(request):
+ while True:
+ return
diff --git a/tests/wpt/web-platform-tests/websockets/handlers/simple_handshake_wsh.py b/tests/wpt/web-platform-tests/websockets/handlers/simple_handshake_wsh.py
new file mode 100755
index 00000000000..07500990798
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/handlers/simple_handshake_wsh.py
@@ -0,0 +1,13 @@
+#!/usr/bin/python
+
+from mod_pywebsocket import common, msgutil, util
+from mod_pywebsocket.handshake import hybi
+
+
+def web_socket_do_extra_handshake(request):
+ request.connection.write('HTTP/1.1 101 Switching Protocols:\x0D\x0AConnection: Upgrade\x0D\x0AUpgrade: WebSocket\x0D\x0ASet-Cookie: ws_test=test\x0D\x0ASec-WebSocket-Origin: '+request.ws_origin+'\x0D\x0ASec-WebSocket-Accept: '+hybi.compute_accept(request.headers_in.get(common.SEC_WEBSOCKET_KEY_HEADER))[0]+'\x0D\x0A\x0D\x0A')
+ return
+
+def web_socket_transfer_data(request):
+ while True:
+ return
diff --git a/tests/wpt/web-platform-tests/websockets/handlers/sleep_10_v13_wsh.py b/tests/wpt/web-platform-tests/websockets/handlers/sleep_10_v13_wsh.py
new file mode 100755
index 00000000000..e1a6d9640fd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/handlers/sleep_10_v13_wsh.py
@@ -0,0 +1,25 @@
+#!/usr/bin/python
+
+import sys, urllib, time
+from mod_pywebsocket import common, msgutil, util
+
+def web_socket_do_extra_handshake(request):
+ request.connection.write('x')
+ time.sleep(2)
+ request.connection.write('x')
+ time.sleep(2)
+ request.connection.write('x')
+ time.sleep(2)
+ request.connection.write('x')
+ time.sleep(2)
+ request.connection.write('x')
+ time.sleep(2)
+ return
+
+def web_socket_transfer_data(request):
+ while True:
+ line = msgutil.receive_message(request)
+ if line == 'Goodbye':
+ return
+ request.ws_stream.send_message(line, binary=False)
+
diff --git a/tests/wpt/web-platform-tests/websockets/handlers/wrong_accept_key_wsh.py b/tests/wpt/web-platform-tests/websockets/handlers/wrong_accept_key_wsh.py
new file mode 100755
index 00000000000..f504a81f491
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/handlers/wrong_accept_key_wsh.py
@@ -0,0 +1,13 @@
+#!/usr/bin/python
+
+import sys, urllib, time
+from mod_pywebsocket import common, msgutil, util
+
+def web_socket_do_extra_handshake(request):
+ request.connection.write('HTTP/1.1 101 Switching Protocols:\x0D\x0AConnection: Upgrade\x0D\x0AUpgrade: WebSocket\x0D\x0ASec-WebSocket-Origin: '+request.ws_origin+'\x0D\x0ASec-WebSocket-Accept: thisisawrongacceptkey\x0D\x0A\x0D\x0A')
+ return
+
+def web_socket_transfer_data(request):
+ while True:
+ request.ws_stream.send_message('test', binary=False)
+ return
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces.html b/tests/wpt/web-platform-tests/websockets/interfaces.html
new file mode 100644
index 00000000000..318ad41a226
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces.html
@@ -0,0 +1,79 @@
+<!doctype html>
+<title>Web Sockets IDL tests</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=/resources/webidl2/lib/webidl2.js></script>
+<script src=/resources/idlharness.js></script>
+
+<h1>Web Sockets IDL tests</h1>
+<div id=log></div>
+
+<script type=text/plain>
+enum BinaryType { "blob", "arraybuffer" };
+[Constructor(DOMString url, optional (DOMString or DOMString[]) protocols), Exposed=Window,Worker]
+interface WebSocket : EventTarget {
+ readonly attribute DOMString url;
+
+ // ready state
+ const unsigned short CONNECTING = 0;
+ const unsigned short OPEN = 1;
+ const unsigned short CLOSING = 2;
+ const unsigned short CLOSED = 3;
+ readonly attribute unsigned short readyState;
+ readonly attribute unsigned long bufferedAmount;
+
+ // networking
+ attribute EventHandler onopen;
+ attribute EventHandler onerror;
+ attribute EventHandler onclose;
+ readonly attribute DOMString extensions;
+ readonly attribute DOMString protocol;
+ void close([Clamp] optional unsigned short code, optional DOMString reason);
+
+ // messaging
+ attribute EventHandler onmessage;
+ attribute BinaryType binaryType;
+ void send(DOMString data);
+ void send(Blob data);
+ void send(ArrayBuffer data);
+ void send(ArrayBufferView data);
+};
+
+[Constructor(DOMString type, optional CloseEventInit eventInitDict), Exposed=Window,Worker]
+interface CloseEvent : Event {
+ readonly attribute boolean wasClean;
+ readonly attribute unsigned short code;
+ readonly attribute DOMString reason;
+};
+
+dictionary CloseEventInit : EventInit {
+ boolean wasClean;
+ unsigned short code;
+ DOMString reason;
+};
+
+[TreatNonCallableAsNull]
+callback EventHandlerNonNull = any (Event event);
+typedef EventHandlerNonNull? EventHandler;
+</script>
+<script>
+"use strict";
+var idlArray;
+setup(function() {
+ idlArray = new IdlArray();
+ [].forEach.call(document.querySelectorAll("script[type=text\\/plain]"), function(node) {
+ if (node.className == "untested") {
+ idlArray.add_untested_idls(node.textContent);
+ } else {
+ idlArray.add_idls(node.textContent);
+ }
+ });
+}, {explicit_done:true});
+window.onload = function() {
+ idlArray.add_objects({
+ WebSocket: ['new WebSocket("ws://foo")'],
+ });
+ idlArray.test();
+ done();
+};
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/CloseEvent/clean-close.html b/tests/wpt/web-platform-tests/websockets/interfaces/CloseEvent/clean-close.html
new file mode 100644
index 00000000000..78a7b5034ab
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/CloseEvent/clean-close.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<title>WebSockets: wasClean, true</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/echo');
+ ws.onopen = t.step_func(function(e) {
+ ws.send('Test');
+ });
+ ws.onmessage = t.step_func(function(e) {
+ ws.close();
+ });
+ ws.onclose = t.step_func(function(e) {
+ assert_equals(e.wasClean,true);
+ t.done();
+ });
+}, null, {timeout:2000});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/CloseEvent/constructor.html b/tests/wpt/web-platform-tests/websockets/interfaces/CloseEvent/constructor.html
new file mode 100644
index 00000000000..1ed86bdf8fd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/CloseEvent/constructor.html
@@ -0,0 +1,35 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>CloseEvent: constructor</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function() {
+ var event = new CloseEvent("foo");
+ assert_true(event instanceof CloseEvent, "should be a CloseEvent");
+ assert_equals(event.type, "foo");
+ assert_false(event.bubbles, "bubbles");
+ assert_false(event.cancelable, "cancelable");
+ assert_false(event.wasClean, "wasClean");
+ assert_equals(event.code, 0);
+ assert_equals(event.reason, "");
+}, "new CloseEvent() without dictionary");
+
+test(function() {
+ var event = new CloseEvent("foo", {
+ bubbles: true,
+ cancelable: true,
+ wasClean: true,
+ code: 7,
+ reason: "x",
+ });
+ assert_true(event instanceof CloseEvent, "should be a CloseEvent");
+ assert_equals(event.type, "foo");
+ assert_true(event.bubbles, "bubbles");
+ assert_true(event.cancelable, "cancelable");
+ assert_true(event.wasClean, "wasClean");
+ assert_equals(event.code, 7);
+ assert_equals(event.reason, "x");
+}, "new CloseEvent() with dictionary");
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/CloseEvent/historical.html b/tests/wpt/web-platform-tests/websockets/interfaces/CloseEvent/historical.html
new file mode 100644
index 00000000000..870022f5e83
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/CloseEvent/historical.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>CloseEvent: historical initialization</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function() {
+ assert_throws("NotSupportedError", function() {
+ document.createEvent("CloseEvent")
+ });
+}, "createEvent(\"CloseEvent\")");
+
+test(function() {
+ assert_false("initCloseEvent" in CloseEvent.prototype);
+ assert_false("initCloseEvent" in new CloseEvent());
+}, "initCloseEvent");
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/bufferedAmount/bufferedAmount-arraybuffer.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/bufferedAmount/bufferedAmount-arraybuffer.html
new file mode 100644
index 00000000000..7b1b49124af
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/bufferedAmount/bufferedAmount-arraybuffer.html
@@ -0,0 +1,23 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>WebSockets: bufferedAmount for ArrayBuffer</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/echo');
+ var datasize = 10;
+ ws.onopen = t.step_func(function(e) {
+ ws.binaryType = "arraybuffer";
+ var data = new ArrayBuffer(datasize);
+ ws.send(data);
+ assert_equals(ws.bufferedAmount, data.byteLength);
+ })
+ ws.onmessage = t.step_func(function(e) {
+ assert_equals(e.data.byteLength, datasize);
+ t.done();
+ })
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/bufferedAmount/bufferedAmount-blob.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/bufferedAmount/bufferedAmount-blob.html
new file mode 100644
index 00000000000..685cb322dd7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/bufferedAmount/bufferedAmount-blob.html
@@ -0,0 +1,24 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>WebSockets: bufferedAmount for blob</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/echo');
+ var datasize = 10;
+ ws.onopen = t.step_func(function(e) {
+ ws.binaryType = "blob";
+ var data = new ArrayBuffer(datasize);
+ ws.send(data);
+ assert_equals(ws.bufferedAmount, data.byteLength);
+ });
+ ws.onmessage = t.step_func(function(e) {
+ assert_true(e.data instanceof Blob);
+ assert_equals(e.data.size, datasize);
+ t.done();
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/bufferedAmount/bufferedAmount-defineProperty-getter.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/bufferedAmount/bufferedAmount-defineProperty-getter.html
new file mode 100644
index 00000000000..c089d6b8e2e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/bufferedAmount/bufferedAmount-defineProperty-getter.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>WebSockets: defineProperty getter for bufferedAmount</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+test(function(){
+ Object.defineProperty(WebSocket.prototype, 'bufferedAmount', {
+ get: function() { return 'foo'; }
+ });
+ var ws = new WebSocket('ws://example.invalid/');
+ assert_equals(ws.bufferedAmount, 'foo');
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/bufferedAmount/bufferedAmount-defineProperty-setter.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/bufferedAmount/bufferedAmount-defineProperty-setter.html
new file mode 100644
index 00000000000..99798683799
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/bufferedAmount/bufferedAmount-defineProperty-setter.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>WebSockets: defineProperty setter for bufferedAmount</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+test(function() {
+ window.setter_ran = false;
+ Object.defineProperty(WebSocket.prototype, 'bufferedAmount', {
+ set: function(v) { window[v] = true; }
+ });
+ var ws = new WebSocket('ws://example.invalid/');
+ ws.bufferedAmount = 'setter_ran';
+ assert_true(setter_ran);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/bufferedAmount/bufferedAmount-deleting.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/bufferedAmount/bufferedAmount-deleting.html
new file mode 100644
index 00000000000..c00a80a8bc1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/bufferedAmount/bufferedAmount-deleting.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>WebSockets: delete bufferedAmount</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+test(function(){
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/echo');
+ assert_equals(ws.bufferedAmount, 0, 'after creation');
+ ws.close();
+ delete ws.bufferedAmount;
+ assert_equals(ws.bufferedAmount, 0,
+ 'after attempt to delete ws.bufferedAmount');
+ delete WebSocket.prototype.bufferedAmount;
+ assert_equals(ws.bufferedAmount, undefined,
+ 'after attempt to delete WebSocket.prototype.bufferedAmount');
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/bufferedAmount/bufferedAmount-getting.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/bufferedAmount/bufferedAmount-getting.html
new file mode 100644
index 00000000000..ba526a79d56
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/bufferedAmount/bufferedAmount-getting.html
@@ -0,0 +1,51 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>WebSockets: bufferedAmount after send()ing</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+async_test(function(t){
+ // bufferedAmount should increase sync in the send() method and decrease between
+ // events in the event loop (so never while script is running).
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/echo');
+ ws.onopen = t.step_func(function(e) {
+ ws.send('x');
+ assert_equals(ws.bufferedAmount, 1, 'bufferedAmount after sent "x"');
+ ws.send('\u00E5');
+ assert_equals(ws.bufferedAmount, 1+2, 'bufferedAmount after sent "x", "\u00E5"');
+ ws.send('\u5336');
+ assert_equals(ws.bufferedAmount, 1+2+3, 'bufferedAmount after sent "x", "\u00E5", "\u5336"');
+ ws.send('\uD801\uDC7E');
+ assert_equals(ws.bufferedAmount, 1+2+3+4, 'bufferedAmount after sent "x", "\u00E5", "\u5336", "\uD801\uDC7E"');
+ })
+ var i = 0;
+ ws.onmessage = t.step_func(function(e) {
+ i++;
+ switch(i) {
+ case 1:
+ assert_equals(e.data, 'x');
+ assert_true(ws.bufferedAmount < 2+3+4 + 1, 'bufferedAmount after received "x"');
+ break;
+ case 2:
+ assert_equals(e.data, '\u00E5');
+ assert_true(ws.bufferedAmount < 3+4 + 1, 'bufferedAmount after received "x", "\u00E5"');
+ break;
+ case 3:
+ assert_equals(e.data, '\u5336');
+ assert_true(ws.bufferedAmount < 4 + 1, 'bufferedAmount after received "x", "\u00E5", "\u5336"');
+ break;
+ case 4:
+ assert_equals(e.data, '\uD801\uDC7E');
+ assert_equals(ws.bufferedAmount, 0, 'bufferedAmount after received "x", "\u00E5", "\u5336", "\uD801\uDC7E"');
+ t.done();
+ break;
+ default:
+ assert_unreached(i);
+ }
+ })
+ ws.onerror = ws.onclose = t.step_func(function() {assert_unreached()});
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/bufferedAmount/bufferedAmount-initial.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/bufferedAmount/bufferedAmount-initial.html
new file mode 100644
index 00000000000..225990c8ef6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/bufferedAmount/bufferedAmount-initial.html
@@ -0,0 +1,13 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>WebSockets: getting bufferedAmount</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+test(function(){
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/');
+ assert_equals(ws.bufferedAmount, 0);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/bufferedAmount/bufferedAmount-large.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/bufferedAmount/bufferedAmount-large.html
new file mode 100644
index 00000000000..228c29fc30c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/bufferedAmount/bufferedAmount-large.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>WebSockets: bufferedAmount for 65K data</title>
+<meta name=timeout content=long>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/echo');
+ var data = "";
+ ws.onopen = t.step_func(function(e) {
+ for (var i = 0; i < 65000; i++) {
+ data = data + "x";
+ }
+ ws.send(data);
+ assert_equals(data.length, ws.bufferedAmount);
+ });
+ ws.onmessage = t.step_func(function(e) {
+ assert_equals(e.data, data);
+ t.done();
+ })
+}, null, {timeout:20000});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/bufferedAmount/bufferedAmount-readonly.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/bufferedAmount/bufferedAmount-readonly.html
new file mode 100644
index 00000000000..2c6016ced20
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/bufferedAmount/bufferedAmount-readonly.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>WebSockets: setting bufferedAmount</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+test(function(){
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/');
+ ws.bufferedAmount = 5;
+ assert_equals(ws.bufferedAmount, 0);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/bufferedAmount/bufferedAmount-unicode.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/bufferedAmount/bufferedAmount-unicode.html
new file mode 100644
index 00000000000..a8eff27b367
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/bufferedAmount/bufferedAmount-unicode.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>WebSockets: bufferedAmount for unicode data</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/echo');
+ var data = "¥¥¥¥¥¥";
+ ws.onopen = t.step_func(function(e) {
+ ws.send(data);
+ assert_equals(data.length * 2, ws.bufferedAmount);
+ });
+ ws.onmessage = t.step_func(function(e) {
+ assert_equals(e.data, data);
+ t.done();
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/close/close-basic.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/close/close-basic.html
new file mode 100644
index 00000000000..775c83eff53
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/close/close-basic.html
@@ -0,0 +1,22 @@
+<!doctype html>
+<title>WebSockets: close()</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/');
+ ws.onclose = t.step_func(function(e) {
+ assert_equals(e instanceof CloseEvent, true, 'e instanceof CloseEvent');
+ assert_equals(e.wasClean, false, 'e.wasClean');
+ e.wasClean = true;
+ assert_equals(e.wasClean, false, 'e.wasClean = true');
+ delete e.wasClean;
+ assert_equals(e.wasClean, false, 'delete e.wasClean');
+ t.done();
+ });
+ ws.close();
+ assert_equals(ws.readyState, ws.CLOSING);
+}, undefined, {timeout:9900});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/close/close-connecting.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/close/close-connecting.html
new file mode 100644
index 00000000000..b9aed783df4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/close/close-connecting.html
@@ -0,0 +1,23 @@
+<!doctype html>
+<title>WebSockets: close() when connecting</title>
+<meta name=timeout content=long>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/sleep_10_v13');
+ setTimeout(t.step_func(function() {
+ assert_equals(ws.readyState, ws.CONNECTING);
+ ws.close();
+ assert_equals(ws.readyState, ws.CLOSING);
+ ws.onclose = t.step_func(function(e) {
+ assert_equals(ws.readyState, ws.CLOSED);
+ assert_equals(e.wasClean, false);
+ t.done();
+ });
+ }), 1000);
+ ws.onopen = ws.onclose = t.step_func(assert_unreached);
+}, undefined, {timeout:12000});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/close/close-multiple.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/close/close-multiple.html
new file mode 100644
index 00000000000..f5b142b93c4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/close/close-multiple.html
@@ -0,0 +1,22 @@
+<!doctype html>
+<title>WebSockets: close() several times</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+var i = 0;
+async_test(function(t) {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/');
+ ws.onclose = function(e) {
+ i++;
+ }
+ ws.close();
+ ws.close();
+ ws.close();
+ setTimeout(t.step_func(function() {
+ assert_equals(i, 1);
+ t.done()
+ }), 50);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/close/close-nested.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/close/close-nested.html
new file mode 100644
index 00000000000..39506bbbe8e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/close/close-nested.html
@@ -0,0 +1,26 @@
+<!doctype html>
+<title>WebSockets: close() in close event handler</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/');
+ var i = 0;
+ ws.onclose = t.step_func(function(e) {
+ i++;
+ if (i == 1) {
+ assert_equals(ws.readyState, ws.CLOSED);
+ ws.close();
+ assert_equals(ws.readyState, ws.CLOSED);
+ }
+ setTimeout(t.step_func(function() {
+ assert_equals(i, 1);
+ t.done();
+ }), 50);
+ });
+ ws.close();
+ assert_equals(ws.readyState, ws.CLOSING);
+}, undefined, {timeout:9900});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/close/close-replace.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/close/close-replace.html
new file mode 100644
index 00000000000..a880126d8cb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/close/close-replace.html
@@ -0,0 +1,13 @@
+<!doctype html>
+<title>WebSockets: replacing close</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+test(function() {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/');
+ ws.close = 5;
+ assert_equals(ws.close, 5);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/close/close-return.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/close/close-return.html
new file mode 100644
index 00000000000..c9ddec18bf4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/close/close-return.html
@@ -0,0 +1,12 @@
+<!doctype html>
+<title>WebSockets: close() return value</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+test(function() {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/');
+ assert_equals(ws.close(), undefined);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/constants/001.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/constants/001.html
new file mode 100644
index 00000000000..061a4d4096b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/constants/001.html
@@ -0,0 +1,15 @@
+<!doctype html>
+<title>WebSockets: getting constants on constructor</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+var constants = ['CONNECTING', 'OPEN', 'CLOSING', 'CLOSED'];
+for (var i = 0; i < constants.length; ++i) {
+ test(function(){
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/');
+ assert_equals(WebSocket[constants[i]], i, 'WebSocket.'+constants[i]);
+ }, "Constants on constructors " + constants[i]);
+};
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/constants/002.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/constants/002.html
new file mode 100644
index 00000000000..6c1330db102
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/constants/002.html
@@ -0,0 +1,22 @@
+<!doctype html>
+<title>WebSockets: setting constants</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+// this test is testing WebIDL stuff
+var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/');
+var constants = ['CONNECTING', 'OPEN', 'CLOSING', 'CLOSED'];
+for (var i = 0; i < constants.length; ++i) {
+ test(function() {
+ WebSocket[constants[i]] = 5; // should be ignored, has { ReadOnly }
+ WebSocket.prototype[constants[i]] = 5; // should be ignored, has { ReadOnly }
+ ws[constants[i]] = 5; // should be ignored, { ReadOnly } is inherited from prototype
+ assert_equals(WebSocket[constants[i]], i, 'WebSocket.'+constants[i]);
+ assert_equals(WebSocket.prototype[constants[i]], i, 'WebSocket.prototype.'+constants[i]);
+ assert_equals(ws[constants[i]], i, 'ws.'+constants[i]);
+ }, "Readonly constants " + constants[i]);
+};
+</script>
+
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/constants/003.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/constants/003.html
new file mode 100644
index 00000000000..642e444cc00
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/constants/003.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<title>WebSockets: deleting constants</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+var constants = ['CONNECTING', 'OPEN', 'CLOSING', 'CLOSED'];
+for (var i = 0; i < constants.length; ++i) {
+ test(function(){
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/');
+ delete WebSocket[constants[i]]; // should be ignored, has { DontDelete }
+ delete WebSocket.prototype[constants[i]]; // should be ignored, has { DontDelete }
+ delete ws[constants[i]]; // should be ignored, there is no such property on the object
+ assert_equals(WebSocket[constants[i]], i, 'WebSocket.'+constants[i]);
+ assert_equals(WebSocket.prototype[constants[i]], i, 'WebSocket.prototype.'+constants[i]);
+ assert_equals(ws[constants[i]], i, 'ws.'+constants[i]);
+ })
+};
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/constants/004.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/constants/004.html
new file mode 100644
index 00000000000..4b3306440b1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/constants/004.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<title>WebSockets: getting constants on prototype and object</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+var constants = ['CONNECTING', 'OPEN', 'CLOSING', 'CLOSED'];
+for (var i = 0; i < constants.length; ++i) {
+ test(function() {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/');
+ assert_equals(WebSocket.prototype[constants[i]], i);
+ }, 'WebSocket.prototype.'+constants[i]);
+ test(function() {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/');
+ assert_equals(ws[constants[i]], i);
+ }, 'ws.'+constants[i]);
+};
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/constants/005.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/constants/005.html
new file mode 100644
index 00000000000..93b120088c8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/constants/005.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<title>WebSockets: defineProperty getter for constants</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+var constants = ['CONNECTING', 'OPEN', 'CLOSING', 'CLOSED'];
+for (var i = 0; i < constants.length; ++i) {
+ test(function() {
+ assert_throws(new TypeError(), function() {
+ Object.defineProperty(WebSocket.prototype, constants[i], {
+ get: function() { return 'foo'; }
+ });
+ });
+ }, "defineProperty getter " + constants[i]);
+};
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/constants/006.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/constants/006.html
new file mode 100644
index 00000000000..0a17f78f183
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/constants/006.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<title>WebSockets: defineProperty setter for constants</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+var constants = ['CONNECTING', 'OPEN', 'CLOSING', 'CLOSED'];
+for (var i = 0; i < constants.length; ++i) {
+ test(function() {
+ assert_throws(new TypeError(), function(){
+ Object.defineProperty(WebSocket.prototype, constants[i], {
+ set: function() { return 'foo'; }
+ });
+ });
+ }, "defineProperty setter " + constants[i])
+};
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/001.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/001.html
new file mode 100644
index 00000000000..bb790bf4845
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/001.html
@@ -0,0 +1,15 @@
+<!doctype html>
+<title>WebSockets: getting on*</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+var events = ['open', 'message', 'error', 'close'];
+for (var i = 0; i < events.length; ++i) {
+ test(function(){
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/');
+ assert_equals(ws['on'+events[i]], null, 'on'+events[i]);
+ });
+};
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/002.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/002.html
new file mode 100644
index 00000000000..caac06fd441
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/002.html
@@ -0,0 +1,17 @@
+<!doctype html>
+<title>WebSockets: setting on*</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+var events = ['open', 'message', 'error', 'close'];
+for (var i = 0; i < events.length; ++i) {
+ test(function(){
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/');
+ var foo = function () {};
+ ws['on'+events[i]] = foo;
+ assert_equals(ws['on'+events[i]], foo);
+ });
+}
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/003.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/003.html
new file mode 100644
index 00000000000..962fae31929
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/003.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<title>WebSockets: listening for events with onopen</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/');
+ var foo = t.step_func(function (e) {
+ if (e.detail == 5)
+ t.done();
+ })
+ ws.onopen = foo;
+ var ev = document.createEvent('UIEvents');
+ ev.initUIEvent('open', false, false, window, 5);
+ ws.dispatchEvent(ev);
+}, null, {timeout:2000});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/004.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/004.html
new file mode 100644
index 00000000000..b26b2796f26
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/004.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<title>WebSockets: members of EventTarget</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+test(function(){
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/');
+ assert_equals(typeof ws.addEventListener, 'function');
+ assert_equals(typeof ws.removeEventListener, 'function');
+ assert_equals(typeof ws.dispatchEvent, 'function');
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/006.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/006.html
new file mode 100644
index 00000000000..6fc1247e5a0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/006.html
@@ -0,0 +1,15 @@
+<!doctype html>
+<title>WebSockets: 'on*' in ws</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+test(function(){
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/');
+ assert_equals('onopen' in ws, true, 'onopen');
+ assert_equals('onmessage' in ws, true, 'onmessage');
+ assert_equals('onerror' in ws, true, 'onerror');
+ assert_equals('onclose' in ws, true, 'onclose');
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/007.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/007.html
new file mode 100644
index 00000000000..79fd86271c4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/007.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<title>WebSockets: listening for events with onmessage</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/');
+ var foo = t.step_func(function (e) {
+ if (e.detail == 5)
+ t.done();
+ })
+ ws.onmessage = foo;
+ var ev = document.createEvent('UIEvents');
+ ev.initUIEvent('message', false, false, window, 5);
+ ws.dispatchEvent(ev);
+}, null, {timeout:2000});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/008.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/008.html
new file mode 100644
index 00000000000..122928122b1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/008.html
@@ -0,0 +1,22 @@
+<!doctype html>
+<title>WebSockets: listening for events with onerror</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/');
+ var run = false;
+ var foo = t.step_func(function (e) {
+ run = true;
+ assert_equals(e.detail, 5)
+ });
+ ws.onerror = foo;
+ var ev = document.createEvent('UIEvents');
+ ev.initUIEvent('error', false, false, window, 5);
+ ws.dispatchEvent(ev);
+ assert_true(run);
+ t.done();
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/009.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/009.html
new file mode 100644
index 00000000000..76a13c81a6c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/009.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<title>WebSockets: listening for events with onclose</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/');
+ var foo = t.step_func(function (e) {
+ if (e.detail == 5)
+ t.done();
+ });
+ ws.onclose = foo;
+ var ev = document.createEvent('UIEvents');
+ ev.initUIEvent('close', false, false, window, 5);
+ ws.dispatchEvent(ev);
+}, null, {timeout:2000});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/010.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/010.html
new file mode 100644
index 00000000000..367c36c7940
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/010.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<title>WebSockets: setting event handlers to undefined</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+var events = ['onclose', 'onopen', 'onerror', 'onmessage'];
+for (var i = 0; i < events.length; ++i) {
+ test(function(){
+ var ws = new WebSocket(SCHEME_AND_DOMAIN+'/');
+ var foo = function() {}
+ ws[events[i]] = foo;
+ assert_equals(ws[events[i]], foo, events[i]);
+ ws[events[i]] = undefined;
+ assert_equals(ws[events[i]], null, events[i]);
+ });
+}
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/011.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/011.html
new file mode 100644
index 00000000000..a0043ed6456
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/011.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<title>WebSockets: setting event handlers to 1</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+var events = ['onclose', 'onopen', 'onerror', 'onmessage'];
+for (var i = 0; i < events.length; ++i) {
+ test(function(t) {
+ var ws = new WebSocket(SCHEME_AND_DOMAIN+'/');
+ ws[events[i]] = 1;
+ assert_equals(ws[events[i]], null);
+ }, events[i]);
+};
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/012.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/012.html
new file mode 100644
index 00000000000..8a507d37808
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/012.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<title>WebSockets: setting event handlers to ";"</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+var events = ['onclose', 'onopen', 'onerror', 'onmessage'];
+for (var i = 0; i < events.length; ++i) {
+ test(function(t) {
+ var ws = new WebSocket(SCHEME_AND_DOMAIN+'/');
+ ws[events[i]] = ";";
+ assert_equals(ws[events[i]], null);
+ }, events[i]);
+};
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/013.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/013.html
new file mode 100644
index 00000000000..bb0972e6fd9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/013.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<title>WebSockets: setting event handlers to {handleEvent:function(){}}</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+var events = ['onclose', 'onopen', 'onerror', 'onmessage'];
+for (var i = 0; i < events.length; ++i) {
+ test(function(t) {
+ var ws = new WebSocket(SCHEME_AND_DOMAIN+'/');
+ ws[events[i]] = {handleEvent:function(){}};
+ assert_equals(ws[events[i]], null);
+ }, events[i]);
+};
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/014.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/014.html
new file mode 100644
index 00000000000..92304a600be
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/014.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<title>WebSockets: setting event handlers to null</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+var events = ['onclose', 'onopen', 'onerror', 'onmessage'];
+for (var i = 0; i < events.length; ++i) {
+ test(function() {
+ var ws = new WebSocket(SCHEME_AND_DOMAIN+'/');
+ var foo = function() {}
+ ws[events[i]] = foo;
+ assert_equals(ws[events[i]], foo, events[i]);
+ ws[events[i]] = null;
+ assert_equals(ws[events[i]], null, events[i]);
+ }, "Setting event handlers to null " + events[i]);
+};
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/015.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/015.html
new file mode 100644
index 00000000000..b677e1ca190
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/015.html
@@ -0,0 +1,31 @@
+<!doctype html>
+<title>WebSockets: instanceof on events</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/echo_raw');
+ ws.onopen = t.step_func(function(e) {
+ assert_true(e instanceof Event);
+ // first a text frame, then a frame with reserved opcode 3
+ // which should fail the connection
+ ws.send('\\x81\\x04test\\x83\\x03LOL');
+ });
+ ws.onmessage = t.step_func(function(e) {
+ assert_true(e instanceof Event);
+ assert_true(e instanceof MessageEvent);
+ assert_equals(ws.readyState, ws.OPEN);
+ })
+ ws.onerror = t.step_func(function(e) {
+ assert_true(e instanceof Event);
+ assert_equals(ws.readyState, ws.CLOSED);
+ })
+ ws.onclose = t.step_func(function(e) {
+ assert_true(e instanceof Event);
+ assert_true(e instanceof CloseEvent);
+ t.done();
+ })
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/016.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/016.html
new file mode 100644
index 00000000000..f76fa7f7185
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/016.html
@@ -0,0 +1,35 @@
+<!doctype html>
+<title>WebSockets: addEventListener</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/echo');
+ var count = 0;
+ var checkCount = t.step_func(function (c, e) {
+ count++;
+ assert_equals(count, c);
+ });
+ // no spec requires this order for event listeners but the web does
+ ws.addEventListener('open', t.step_func(function(e) {
+ checkCount(1, e);
+ ws.send('Goodbye');
+ }), false);
+ ws.onopen = t.step_func(function(e) {checkCount(2, e) });
+ ws.addEventListener('open', t.step_func(function(e) {checkCount(3, e); }), false);
+
+ ws.addEventListener('message', t.step_func(function(e) {checkCount(4, e); }), false);
+ ws.onmessage = t.step_func(function(e) {checkCount(5, e) });
+ ws.addEventListener('message', t.step_func(function(e) {checkCount(6, e); }), false);
+
+ ws.addEventListener('close', t.step_func(function(e) {checkCount(7, e); }), false);
+ ws.onclose = t.step_func(function(e) {checkCount(8, e) });
+ ws.addEventListener('close', t.step_func(function(e) {
+ checkCount(9, e);
+ t.done();
+ }), false);
+
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/017.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/017.html
new file mode 100644
index 00000000000..dd7c0f9b71b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/017.html
@@ -0,0 +1,51 @@
+<!doctype html>
+<title>WebSockets: this, e.target, e.currentTarget, e.eventPhase</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/echo_raw');
+ ws.addEventListener('open', function(e) {
+ var this_val = this;
+ t.step(function() {
+ // first a text frame, then a frame with reserved opcode 3
+ // which should fail the connection
+ ws.send('\\x81\\x04test\\x83\\x03LOL');
+ assert_equals(this_val, ws);
+ assert_equals(e.target, ws);
+ assert_equals(e.currentTarget, ws);
+ assert_equals(e.eventPhase, 2);
+ });
+ }, false);
+ ws.addEventListener('message', function(e) {
+ var this_val = this;
+ t.step(function() {
+ assert_equals(this_val, ws);
+ assert_equals(e.target, ws);
+ assert_equals(e.currentTarget, ws);
+ assert_equals(e.eventPhase, 2);
+ });
+ }, false);
+ ws.addEventListener('error', function(e) {
+ var this_val = this;
+ t.step(function() {
+ assert_equals(this_val, ws);
+ assert_equals(e.target, ws);
+ assert_equals(e.currentTarget, ws);
+ assert_equals(e.eventPhase, 2);
+ });
+ }, false);
+ ws.addEventListener('close', function(e) {
+ var this_val = this;
+ t.step(function() {
+ assert_equals(this_val, ws);
+ assert_equals(e.target, ws);
+ assert_equals(e.currentTarget, ws);
+ assert_equals(e.eventPhase, 2);
+ t.done();
+ });
+ }, false);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/018.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/018.html
new file mode 100644
index 00000000000..da08fd212d6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/018.html
@@ -0,0 +1,35 @@
+<!doctype html>
+<title>WebSockets: toString(), bubbles, cancelable</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/echo_raw');
+ ws.addEventListener('open', t.step_func(function(e) {
+ // first a text frame, then a frame with reserved opcode 3
+ // which should fail the connection
+ ws.send('\\x81\\x04test\\x83\\x03LOL');
+ assert_equals(e.toString(), '[object Event]', "open e.toString()");
+ assert_equals(e.bubbles, false, 'open e.bubbles');
+ assert_equals(e.cancelable, false, 'open e.cancelable');
+ }), false);
+ ws.addEventListener('message', t.step_func(function(e) {
+ assert_equals(e.toString(), '[object MessageEvent]', "message e.toString()");
+ assert_equals(e.bubbles, false, 'message e.bubbles');
+ assert_equals(e.cancelable, false, 'message e.cancelable');
+ }), false);
+ ws.addEventListener('error', t.step_func(function(e) {
+ assert_equals(e.toString(), '[object Event]', "error e.toString()");
+ assert_equals(e.bubbles, false, 'error e.bubbles');
+ assert_equals(e.cancelable, false, 'error e.cancelable');
+ }), false);
+ ws.addEventListener('close', t.step_func(function(e) {
+ assert_equals(e.toString(), '[object CloseEvent]', "close e.toString()");
+ assert_equals(e.bubbles, false, 'close e.bubbles');
+ assert_equals(e.cancelable, false, 'close e.cancelable');
+ t.done();
+ }), false);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/019.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/019.html
new file mode 100644
index 00000000000..605cfce2abe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/019.html
@@ -0,0 +1,29 @@
+<!doctype html>
+<title>WebSockets: removeEventListener</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+var events = ['open', 'message', 'error', 'close'];
+for (var i = 0; i < events.length; ++i) {
+ test(function(t) {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/echo');
+ ws.close();
+ var got = [];
+ var event;
+ function addThis(e) {
+ got.push(e.type);
+ }
+ ws.addEventListener(events[i], addThis, false);
+ ws.removeEventListener(events[i], addThis, false);
+ event = document.createEvent('Event');
+ event.initEvent(events[i], false, false);
+ ws.dispatchEvent(event);
+ assert_equals(got.length, 0);
+ if (got.length) {
+ debug('Got: '+got);
+ }
+ })
+};
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/020.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/020.html
new file mode 100644
index 00000000000..6fd116d91a0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/events/020.html
@@ -0,0 +1,15 @@
+<!doctype html>
+<title>WebSockets: error events</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var ws = new WebSocket('ws://example.invalid/');
+ ws.onerror = t.step_func(function(e) {
+ assert_true(e instanceof Event);
+ t.done();
+ })
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/extensions/001.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/extensions/001.html
new file mode 100644
index 00000000000..23b9fa66432
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/extensions/001.html
@@ -0,0 +1,12 @@
+<!doctype html>
+<title>WebSockets: getting extensions in connecting</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+test(function(t) {
+ // The extensions attribute must initially return the empty string
+ assert_equals((new WebSocket(SCHEME_AND_DOMAIN+'/')).extensions, '');
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/protocol/protocol-initial.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/protocol/protocol-initial.html
new file mode 100644
index 00000000000..f89c1f05815
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/protocol/protocol-initial.html
@@ -0,0 +1,12 @@
+<!doctype html>
+<title>WebSockets: getting protocol in connecting</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+test(function(t) {
+ // The protocol attribute must initially return the empty string
+ assert_equals((new WebSocket(SCHEME_AND_DOMAIN+'/')).protocol, '');
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/readyState/001.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/readyState/001.html
new file mode 100644
index 00000000000..cd2a8715d35
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/readyState/001.html
@@ -0,0 +1,11 @@
+<!doctype html>
+<title>WebSockets: getting readyState in connecting</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+test(function(t) {
+ assert_equals((new WebSocket(SCHEME_DOMAIN_PORT+'/')).readyState, WebSocket.CONNECTING);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/readyState/002.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/readyState/002.html
new file mode 100644
index 00000000000..9b88e04938f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/readyState/002.html
@@ -0,0 +1,13 @@
+<!doctype html>
+<title>WebSockets: setting readyState</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+test(function(t) {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/');
+ ws.readyState = 5;
+ assert_equals(ws.readyState, ws.CONNECTING);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/readyState/003.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/readyState/003.html
new file mode 100644
index 00000000000..8071d220e3a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/readyState/003.html
@@ -0,0 +1,15 @@
+<!doctype html>
+<title>WebSockets: delete readyState</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+test(function(t) {
+ delete WebSocket.prototype.readyState;
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/');
+ ws.close();
+ delete ws.readyState;
+ assert_equals(ws.readyState, ws.CLOSING);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/readyState/004.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/readyState/004.html
new file mode 100644
index 00000000000..3cc77f7117d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/readyState/004.html
@@ -0,0 +1,15 @@
+<!doctype html>
+<title>WebSockets: defineProperty getter for readyState</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+test(function() {
+ Object.defineProperty(WebSocket.prototype, 'readyState', {
+ get: function() { return 'foo'; }
+ });
+ var ws = new WebSocket('ws://example.invalid/');
+ assert_equals(ws.readyState, 'foo');
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/readyState/005.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/readyState/005.html
new file mode 100644
index 00000000000..a222f051d69
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/readyState/005.html
@@ -0,0 +1,17 @@
+<!doctype html>
+<title>WebSockets: defineProperty setter for readyState</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+test(function(){
+ window.setter_ran = false;
+ Object.defineProperty(WebSocket.prototype, 'readyState', {
+ set: function(v) { window[v] = true; }
+ });
+ var ws = new WebSocket('ws://example.invalid/');
+ ws.readyState = 'setter_ran';
+ assert_true(setter_ran);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/readyState/006.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/readyState/006.html
new file mode 100644
index 00000000000..62b3a05bd77
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/readyState/006.html
@@ -0,0 +1,17 @@
+<!doctype html>
+<title>WebSockets: getting readyState in open</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/echo');
+ ws.onopen = t.step_func(function(e) {
+ assert_equals(ws.readyState, ws.OPEN);
+ ws.close();
+ t.done();
+ });
+ ws.onerror = ws.onmessage = ws.onclose = t.step_func(function() {assert_unreached()});
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/readyState/007.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/readyState/007.html
new file mode 100644
index 00000000000..39368aaf816
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/readyState/007.html
@@ -0,0 +1,17 @@
+<!doctype html>
+<title>WebSockets: getting readyState in closing</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/echo');
+ ws.onopen = t.step_func(function(e) {
+ ws.close();
+ assert_equals(ws.readyState, ws.CLOSING);
+ t.done();
+ });
+ ws.onerror = ws.onmessage = ws.onclose = t.step_func(function() {assert_unreached()});
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/readyState/008.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/readyState/008.html
new file mode 100644
index 00000000000..473f634537b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/readyState/008.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<title>WebSockets: getting readyState in closed</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/echo');
+ ws.onopen = t.step_func(function(e) {
+ ws.onclose = t.step_func(function(e) {
+ assert_equals(ws.readyState, ws.CLOSED);
+ t.done();
+ })
+ ws.close();
+ });
+ ws.onerror = ws.onmessage = ws.onclose = t.step_func(function() {assert_unreached()});
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/send/001.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/send/001.html
new file mode 100644
index 00000000000..8e751787a82
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/send/001.html
@@ -0,0 +1,13 @@
+<!doctype html>
+<title>WebSockets: send() with no args</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+test(function(t) {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/');
+ assert_throws(new TypeError(), function(){ws.send()});
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/send/002.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/send/002.html
new file mode 100644
index 00000000000..407693881a5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/send/002.html
@@ -0,0 +1,13 @@
+<!doctype html>
+<title>WebSockets: replacing send</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+test(function() {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/');
+ ws.send = 5;
+ assert_equals(ws.send, 5);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/send/003.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/send/003.html
new file mode 100644
index 00000000000..ddee85c243c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/send/003.html
@@ -0,0 +1,13 @@
+<!doctype html>
+<title>WebSockets: send() when readyState is CONNECTING</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+test(function(t) {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/');
+ assert_throws("INVALID_STATE_ERR", function(){ws.send('a')});
+});
+</script>
+
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/send/004.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/send/004.html
new file mode 100644
index 00000000000..0033d144179
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/send/004.html
@@ -0,0 +1,23 @@
+<!doctype html>
+<title>WebSockets: send() with unpaired surrogate when readyState is CONNECTING</title>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+test(function(t) {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/');
+ assert_throws("INVALID_STATE_ERR", function(){ws.send('a\uDC00x')});
+}, "lone low surrogate");
+
+test(function(t) {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/');
+ assert_throws("INVALID_STATE_ERR", function(){ws.send('a\uD800x')});
+}, "lone high surrogate");
+
+test(function(t) {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/');
+ assert_throws("INVALID_STATE_ERR", function(){ws.send('a\uDC00\uD800x')});
+}, "surrogates in wrong order");
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/send/005.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/send/005.html
new file mode 100644
index 00000000000..2ead7ff928f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/send/005.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<title>WebSockets: send() return value</title>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+async_test(function(t){
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/echo');
+ ws.onopen = t.step_func(function(e) {
+ assert_equals(ws.send('test'), undefined);
+ t.done();
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/send/006.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/send/006.html
new file mode 100644
index 00000000000..dc7197801b3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/send/006.html
@@ -0,0 +1,23 @@
+<!doctype html>
+<title>WebSockets: send() with unpaired surrogate when readyState is OPEN</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id="log"></div>
+<script>
+async_test(function(t) {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/echo');
+ ws.onopen = t.step_func(function(e) {
+ // lone low surrogate, lone high surrogate + surrogates in wrong order.
+ ws.send('a\uDC00xb\uD800xc\uDC00\uD800x');
+ })
+ ws.onmessage = t.step_func(function(e) {
+ assert_equals(e.data, 'a\uFFFDxb\uFFFDxc\uFFFD\uFFFDx');
+ ws.onclose = t.step_func(function(e) {
+ ws.onclose = t.step_func(function() {assert_unreached()});
+ setTimeout(function() {t.done();}, 50);
+ });
+ ws.close();
+ })
+ });
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/send/007.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/send/007.html
new file mode 100644
index 00000000000..e10dd01e928
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/send/007.html
@@ -0,0 +1,24 @@
+<!doctype html>
+<title>WebSockets: close() followed by send()</title>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+
+async_test(function(t) {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/echo');
+ ws.onopen = t.step_func(function(e) {
+ // test that nothing strange happens if we send something after close()
+ ws.close();
+ var sent = ws.send('test');
+ assert_equals(sent, undefined);
+ });
+ ws.onclose = t.step_func(function(e) {
+ ws.onclose = t.step_func(function() {assert_unreached()});
+ setTimeout(function() {t.done()}, 50);
+ });
+ ws.onerror = ws.onmessage = t.step_func(function() {assert_unreached()});
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/send/008.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/send/008.html
new file mode 100644
index 00000000000..bca801e6664
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/send/008.html
@@ -0,0 +1,23 @@
+<!doctype html>
+<title>WebSockets: send() in onclose</title>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/echo');
+ ws.onopen = t.step_func(function(e) {
+ ws.send('Goodbye');
+ })
+ ws.onclose = t.step_func(function(e) {
+ // test that nothing strange happens when send()ing in closed state
+ var sent = ws.send('test');
+ assert_equals(sent, undefined);
+ ws.onclose = t.step_func(function() {assert_unreached()});
+ setTimeout(function() {t.done()}, 50);
+ })
+ ws.onerror = t.step_func(function() {assert_unreached()});
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/send/009.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/send/009.html
new file mode 100644
index 00000000000..ad1d0114b52
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/send/009.html
@@ -0,0 +1,24 @@
+<!doctype html>
+<title>WebSockets: send('')</title>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+async_test(function(t){
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/empty-message');
+ ws.onopen = t.step_func(function(e) {
+ ws.send('');
+ })
+ ws.onmessage = t.step_func(function(e) {
+ assert_equals(e.data, 'pass');
+ ws.close();
+ });
+ ws.onclose = t.step_func(function(e) {
+ ws.onclose = t.step_func(function() {assert_unreached()});
+ setTimeout(function() {t.done()}, 50);
+ });
+ ws.onerror = t.step_func(function() {assert_unreached()});
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/send/010.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/send/010.html
new file mode 100644
index 00000000000..f7d785beae9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/send/010.html
@@ -0,0 +1,39 @@
+<!doctype html>
+<title>WebSockets: sending non-strings</title>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+async_test(function(outer) {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/echo');
+ var stuffToSend = [null, undefined, 1, window, document.body, {}, [], ws, function(){}, new Error()]
+ var tests = [];
+
+ for (var i=0; i<stuffToSend.length; i++) {
+ tests.push(async_test(document.title + " (" + stuffToSend[i] + ")"));
+ }
+
+ i = 0;
+ function sendNext() {
+ if (i === stuffToSend.length) {
+ outer.done()
+ ws.close();
+ } else {
+ var t = tests[i];
+ ws.onmessage = t.step_func(function(e) {
+ assert_equals(e.data, String(stuffToSend[i]));
+ i++;
+ sendNext();
+ t.done();
+ });
+ ws.onclose = ws.onerror = t.step_func(function() {assert_unreached()});
+ ws.send(stuffToSend[i]);
+ }
+ }
+ ws.onopen = function(e) {
+ sendNext();
+ }
+}, "Constructor succeeds");
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/send/011.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/send/011.html
new file mode 100644
index 00000000000..cfefba2aa63
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/send/011.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<title>WebSockets: sending non-ascii, combining chars and non-BMP</title>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+
+async_test(function(t) {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/echo');
+ ws.onopen = t.step_func(function(e) {
+ ws.send('\u00E5 a\u030A \uD801\uDC7E');
+ });
+ ws.onmessage = t.step_func(function(e) {
+ assert_equals(e.data, '\u00E5 a\u030A \uD801\uDC7E');
+ ws.onclose = t.step_func(function(e) {
+ ws.onclose = t.step_func(function() {assert_unreached()});
+ setTimeout(function() {t.done()}, 50);
+ })
+ ws.close();
+ })
+ ws.onclose = ws.onerror = t.step_func(function() {assert_unreached()});
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/send/012.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/send/012.html
new file mode 100644
index 00000000000..76b112d004c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/send/012.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<title>WebSockets: sending null</title>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+
+async_test(function(t){
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/echo');
+ ws.onopen = t.step_func(function(e) {
+ ws.send(null);
+ });
+ ws.onmessage = t.step_func(function(e) {
+ assert_equals(e.data, 'null');
+ ws.onclose = t.step_func(function(e) {
+ ws.onclose = t.step_func(function() {assert_unreached()});
+ setTimeout(function() {t.done()}, 50);
+ })
+ ws.close();
+ });
+ ws.onclose = ws.onerror = t.step_func(function() {assert_unreached()});
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/url/001.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/url/001.html
new file mode 100644
index 00000000000..5999f7e3489
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/url/001.html
@@ -0,0 +1,11 @@
+<!doctype html>
+<title>WebSockets: getting url</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+test(function() {
+ assert_equals((new WebSocket(SCHEME_DOMAIN_PORT)).url, SCHEME_DOMAIN_PORT+'/');
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/url/002.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/url/002.html
new file mode 100644
index 00000000000..1c58e86e022
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/url/002.html
@@ -0,0 +1,13 @@
+<!doctype html>
+<title>WebSockets: setting url</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+test(function() {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/');
+ ws.url = SCHEME_DOMAIN_PORT+'/test';
+ assert_equals(ws.url, SCHEME_DOMAIN_PORT+'/');
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/url/003.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/url/003.html
new file mode 100644
index 00000000000..12118937123
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/url/003.html
@@ -0,0 +1,13 @@
+<!doctype html>
+<title>WebSockets: deleting url</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+test(function() {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/');
+ delete ws.url;
+ assert_equals(ws.url, SCHEME_DOMAIN_PORT+'/');
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/url/004.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/url/004.html
new file mode 100644
index 00000000000..9203e1f3555
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/url/004.html
@@ -0,0 +1,15 @@
+<!doctype html>
+<title>WebSockets: 'URL'</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+test(function() {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/');
+ assert_equals(ws.URL, undefined);
+ assert_equals('URL' in ws, false);
+ assert_equals(WebSocket.prototype.URL, undefined);
+ assert_equals('URL' in WebSocket.prototype, false);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/url/005.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/url/005.html
new file mode 100644
index 00000000000..1fa1fcc57ad
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/url/005.html
@@ -0,0 +1,15 @@
+<!doctype html>
+<title>WebSockets: defineProperty getter for url</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+test(function() {
+ Object.defineProperty(WebSocket.prototype, 'url', {
+ get: function() { return 'foo'; }
+ });
+ var ws = new WebSocket('ws://example.invalid/');
+ assert_equals(ws.url, 'foo');
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/url/006.html b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/url/006.html
new file mode 100644
index 00000000000..72493f8da4e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/interfaces/WebSocket/url/006.html
@@ -0,0 +1,17 @@
+<!doctype html>
+<title>WebSockets: defineProperty setter for url</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../../../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+test(function() {
+ window.setter_ran = false;
+ Object.defineProperty(WebSocket.prototype, 'url', {
+ set: function(v) { window[v] = true; }
+ });
+ var ws = new WebSocket('ws://example.invalid/');
+ ws.url = 'setter_ran';
+ assert_true(setter_ran);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/keeping-connection-open/001.html b/tests/wpt/web-platform-tests/websockets/keeping-connection-open/001.html
new file mode 100644
index 00000000000..c291502daf5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/keeping-connection-open/001.html
@@ -0,0 +1,26 @@
+<!doctype html>
+<title>WebSockets: 20s inactivity after handshake</title>
+<meta name=timeout content=long>
+<p>Note: This test takes 20 seconds to run.</p>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/echo');
+ ws.onclose = ws.onerror = ws.onmessage = t.step_func(function() {assert_unreached()});
+ ws.onopen = t.step_func(function(e) {
+ setTimeout(t.step_func(function() {
+ ws.send('test');
+ ws.onmessage = t.step_func(function(e) {
+ assert_equals(e.data, 'test');
+ ws.onclose = t.step_func(function(e) {
+ setTimeout(t.step_func(function() {t.done();}), 50)
+ });
+ ws.close();
+ });
+ }), 20000);
+ })
+}, null, {timeout:30000});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/opening-handshake/001.html b/tests/wpt/web-platform-tests/websockets/opening-handshake/001.html
new file mode 100644
index 00000000000..817189826f4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/opening-handshake/001.html
@@ -0,0 +1,17 @@
+<!doctype html>
+<title>WebSockets: invalid handshake</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/invalid');
+ ws.onclose = t.step_func(function(e) {
+ assert_false(e.wasClean);
+ ws.onclose = t.step_func(function() {assert_unreached()});
+ setTimeout(t.step_func(function() {t.done();}), 50)
+ });
+ ws.onmessage = ws.onopen = t.step_func(function() {assert_unreached()});
+}, null, {timeout:9900});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/opening-handshake/002.html b/tests/wpt/web-platform-tests/websockets/opening-handshake/002.html
new file mode 100644
index 00000000000..26e5b07806f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/opening-handshake/002.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<title>WebSockets: valid handshake</title>
+<meta name=timeout content=long>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/echo');
+ ws.onopen = t.step_func(function(e) {
+ ws.onclose = t.step_func(function(e) {
+ assert_equals(e.wasClean, true);
+ ws.onclose = t.step_func(function() {assert_unreached()});
+ setTimeout(t.step_func(function() {t.done();}), 50)
+ })
+ ws.close();
+ });
+ ws.onerror = ws.onmessage = ws.onclose = t.step_func(function() {assert_unreached()});
+}, null, {timeout:9900});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/opening-handshake/003.html b/tests/wpt/web-platform-tests/websockets/opening-handshake/003.html
new file mode 100644
index 00000000000..b5220428cbe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/opening-handshake/003.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<title>WebSockets: origin</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/origin');
+ ws.onmessage = t.step_func(function(e) {
+ assert_equals(e.data, location.protocol+'//'+location.host);
+ ws.onclose = t.step_func(function(e) {
+ assert_equals(e.wasClean, true);
+ ws.onclose = t.step_func(function() {assert_unreached()});
+ setTimeout(t.step_func(function() {t.done();}), 50)
+ })
+ ws.close();
+ })
+ ws.onerror = ws.onclose = t.step_func(function() {assert_unreached()});
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/opening-handshake/005.html b/tests/wpt/web-platform-tests/websockets/opening-handshake/005.html
new file mode 100644
index 00000000000..fc5bc4dfb9f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/opening-handshake/005.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<title>WebSockets: proper first line</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/simple_handshake');
+ ws.onmessage = t.step_func(function() {assert_unreached()});
+ ws.onopen = t.step_func(function(e) {
+ ws.onclose = t.step_func(function(e) {
+ assert_equals(e.wasClean, true);
+ ws.onclose = t.step_func(function() {assert_unreached()});
+ setTimeout(t.step_func(function() {t.done();}), 50)
+ })
+ ws.close();
+ })
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/security/001.html b/tests/wpt/web-platform-tests/websockets/security/001.html
new file mode 100644
index 00000000000..04a6cedddaf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/security/001.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<title>WebSockets: wrong accept key</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/wrong_accept_key');
+ ws.onclose = function(e) {
+ t.done();
+ }
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/security/002.html b/tests/wpt/web-platform-tests/websockets/security/002.html
new file mode 100644
index 00000000000..bb4d8eb8842
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/security/002.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<title>WebSockets: check Sec-WebSocket-Key</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../constants.js?pipe=sub></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var xhr = new XMLHttpRequest();
+ xhr.onload = t.step_func(function() {
+ assert_equals(xhr.responseText, 'PASS');
+ t.done();
+ });
+ xhr.open("GET", "check.py", true);
+ xhr.setRequestHeader('Sec-WebSocket-Key', 'jW7qmdXj5Kk5jTClF1BN3');
+ xhr.send(null);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/security/check.py b/tests/wpt/web-platform-tests/websockets/security/check.py
new file mode 100644
index 00000000000..f1414376dcf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/security/check.py
@@ -0,0 +1,2 @@
+def main(request, response):
+ return "FAIL" if 'Sec-WebSocket-Key' in request.headers else "PASS"
diff --git a/tests/wpt/web-platform-tests/websockets/unload-a-document/001-1.html b/tests/wpt/web-platform-tests/websockets/unload-a-document/001-1.html
new file mode 100644
index 00000000000..08ae66616c3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/unload-a-document/001-1.html
@@ -0,0 +1,26 @@
+<!doctype html>
+<title>WebSockets: navigating top-level browsing context</title>
+<script src=../constants.js?pipe=sub></script>
+<script>
+var controller = opener || parent;
+var t = controller.t;
+var assert_equals = controller.asset_equals;
+var assert_unreached = controller.assert_unreached;
+var uuid = controller.uuid;
+t.add_cleanup(function() {delete sessionStorage[uuid];});
+t.step(function() {
+ if (sessionStorage[uuid]) {
+ t.done();
+ } else {
+ sessionStorage[uuid] = 'true';
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/echo');
+ ws.onopen = t.step_func(function(e) {
+ setTimeout(t.step_func(function() {
+ assert_unreached('document was not discarded');
+ }), 1000);
+ controller.navigate();
+ })
+ ws.onerror = ws.onmessage = ws.onclose = t.step_func(function(e) {assert_unreached("Got unexpected event " + e.type)});
+ }
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/unload-a-document/001.html b/tests/wpt/web-platform-tests/websockets/unload-a-document/001.html
new file mode 100644
index 00000000000..dfc55aa7d69
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/unload-a-document/001.html
@@ -0,0 +1,23 @@
+<!doctype html>
+<title>WebSockets: navigating top-level browsing context</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=/common/utils.js></script>
+<script src=../constants.js?pipe=sub></script>
+<p>Test requires popup blocker disabled</p>
+<div id=log></div>
+<script>
+var t = async_test();
+var w;
+var uuid;
+t.step(function() {
+ uuid = token()
+ w = window.open("001-1.html");
+ add_result_callback(function() {
+ w.close();
+ });
+});
+navigate = t.step_func(function() {
+ w.location = 'data:text/html,<body onload="history.back()">';
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/unload-a-document/002-1.html b/tests/wpt/web-platform-tests/websockets/unload-a-document/002-1.html
new file mode 100644
index 00000000000..7f4e004f37d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/unload-a-document/002-1.html
@@ -0,0 +1,32 @@
+<!doctype html>
+<title>WebSockets: navigating top-level browsing context with closed websocket</title>
+<script src=../constants.js?pipe=sub></script>
+<script>
+var controller = opener || parent;
+var t = controller.t;
+var assert_equals = controller.asset_equals;
+var assert_unreached = controller.assert_unreached ;
+var uuid = controller.token;
+t.add_cleanup(function() {delete sessionStorage[uuid];});
+t.step(function() {
+ // this test can fail if the document is unloaded on navigation e.g. due to OOM
+ if (sessionStorage[uuid]) {
+ assert_unreached('document was discarded');
+ } else {
+ sessionStorage[uuid] = 'true';
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/echo');
+ ws.onopen = t.step_func(function(e) {
+
+ setTimeout(t.step_func(function() {
+ assert_equals(ws.readyState, ws.CLOSED, 'ws.readyState');
+ t.done();
+ }), 4000);
+ ws.close();
+ ws.onclose = t.step_func(function() {
+ controller.navigate();
+ });
+ })
+ ws.onerror = ws.onmessage = ws.onclose = t.step_func(function(e) {assert_unreached("Got unexpected event " + e.type)});
+ }
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/unload-a-document/002.html b/tests/wpt/web-platform-tests/websockets/unload-a-document/002.html
new file mode 100644
index 00000000000..9894b1e1dec
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/unload-a-document/002.html
@@ -0,0 +1,24 @@
+<!doctype html>
+<title>WebSockets: navigating top-level browsing context with closed websocket</title>
+<meta name=timeout content=long>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=/common/utils.js></script>
+<script src=../constants.js?pipe=sub></script>
+<p>Test requires popup blocker disabled</p>
+<div id=log></div>
+<script>
+var t = async_test(null, {timeout:15000});
+var w;
+var uuid;
+t.step(function() {
+ uuid = token()
+ w = window.open("002-1.html");
+ add_result_callback(function() {
+ w.close();
+ });
+});
+navigate = t.step_func(function() {
+ w.location = 'data:text/html,<body onload="history.back()">';
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/unload-a-document/003.html b/tests/wpt/web-platform-tests/websockets/unload-a-document/003.html
new file mode 100644
index 00000000000..554daf458a9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/unload-a-document/003.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<title>WebSockets: navigating nested browsing context</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=/common/utils.js></script>
+<div id=log></div>
+<script>
+var uuid;
+var t = async_test(function() {uuid = token()});
+var navigate = t.step_func(function() {
+ document.getElementsByTagName("iframe")[0].src = 'data:text/html,<body onload="history.back()">';
+});
+</script>
+<iframe src=001-1.html></iframe> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/websockets/unload-a-document/004.html b/tests/wpt/web-platform-tests/websockets/unload-a-document/004.html
new file mode 100644
index 00000000000..0ef4fbc9f81
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/unload-a-document/004.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<title>WebSockets: navigating nested browsing context with closed websocket</title>
+<meta name=timeout content=long>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=/common/utils.js></script>
+<div id=log></div>
+<script>
+var uuid;
+var t = async_test(null, {timeout:15000})
+t.step(function() {uuid = token()});
+var navigate = t.step_func(function() {
+ document.getElementsByTagName("iframe")[0].src = 'data:text/html,<body onload="history.back()">';
+});
+</script>
+<iframe src=002-1.html></iframe>
diff --git a/tests/wpt/web-platform-tests/websockets/unload-a-document/005-1.html b/tests/wpt/web-platform-tests/websockets/unload-a-document/005-1.html
new file mode 100644
index 00000000000..a3386634f62
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/unload-a-document/005-1.html
@@ -0,0 +1,23 @@
+<!doctype html>
+<title>WebSockets: navigating nested browsing context with a websocket in top-level</title>
+<script src=../constants.js?pipe=sub></script>
+<script>
+var t = opener.t;
+var assert_unreached = opener.assert_unreached;
+var hasRun = false;
+function run(){
+ var ws = new WebSocket(SCHEME_DOMAIN_PORT+'/echo');
+ ws.onopen = t.step_func(function(e) {
+ setTimeout(t.step_func(function() {
+ ws.send('test');
+ }), 1000);
+ window[0].location = 'data:text/html,<body onload="history.back()">';
+ ws.onmessage = t.step_func(function(e) {
+ ws.close();
+ t.done();
+ });
+ });
+ ws.onerror = ws.onmessage = ws.onclose = t.step_func(function(e) {assert_unreached("Got unexpected event " + e.type)});
+}
+</script>
+<iframe src='data:text/html,foo' onload='if (hasRun) return; hasRun = true; t.step(run)'></iframe>
diff --git a/tests/wpt/web-platform-tests/websockets/unload-a-document/005.html b/tests/wpt/web-platform-tests/websockets/unload-a-document/005.html
new file mode 100644
index 00000000000..7375f642ad3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/unload-a-document/005.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<title>WebSockets: navigating nested browsing context with a websocket in top-level</title>
+<meta name=timeout content=long>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=../constants.js?pipe=sub></script>
+<div id=log></div>
+<p>Test requires popup blocker disabled</p>
+<div id=log></div>
+<script>
+var t = async_test(null, {timeout:15000});
+t.step(function() {
+ var w = window.open("005-1.html");
+ add_result_callback(function() {
+ w.close();
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/websockets/websocket.js b/tests/wpt/web-platform-tests/websockets/websocket.js
new file mode 100644
index 00000000000..a7c2e201c4c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/websockets/websocket.js
@@ -0,0 +1,110 @@
+var __SERVER__NAME = "{{host}}";
+var __PORT = {{ports[ws][0]}};
+var __SECURE__PORT = null; //{{ports[ws][0]}}; //Should be wss
+var __NEW__PORT = __PORT; //All ports are non-default for now
+var __NEW_SECURE_PORT = __PORT; //All ports are non-default for now
+var __PATH = "echo";
+var __CONTROLPATH = "control";
+var __PROTOCOL = "echo";
+var __PROTOCOLS = ["echo", "chat"];
+var __REPEATED__PROTOCOLS = ["echo", "echo"];
+var __URL;
+var __IS__WEBSOCKET;
+var __PASS = "Pass";
+var __FAIL = "Fail";
+var wsocket;
+var csocket;
+var data;
+
+// variables for testing Close Browser/Navigate Away scenarios
+var isAssociated = false;
+var guid;
+var dataReceived;
+var closeCode;
+var urlToOpen;
+
+function IsWebSocket() {
+ if (!window.WebSocket) {
+ assert_true(false, "Browser does not support WebSocket");
+ }
+}
+
+function CreateWebSocketNonAbsolute() {
+ IsWebSocket();
+ __URL = __SERVER__NAME;
+ wsocket = new WebSocket(__URL);
+}
+
+function CreateWebSocketNonWsScheme() {
+ IsWebSocket();
+ __URL = "http://" + __SERVER__NAME + ":" + __PORT + "/" + __PATH;
+ wsocket = new WebSocket(__URL);
+}
+
+function CreateWebSocketNonAsciiProtocol(nonAsciiProtocol) {
+ IsWebSocket();
+ __URL = "ws://" + __SERVER__NAME + ":" + __PORT + "/" + __PATH;
+ wsocket = new WebSocket(__URL, nonAsciiProtocol);
+}
+
+function CreateWebSocketWithBlockedPort(blockedPort) {
+ IsWebSocket();
+ __URL = "wss://" + __SERVER__NAME + ":" + blockedPort + "/" + __PATH;
+ wsocket = new WebSocket(__URL);
+}
+
+function CreateWebSocketWithSpaceInUrl(urlWithSpace) {
+ IsWebSocket();
+ __URL = "ws://" + urlWithSpace + ":" + __PORT + "/" + __PATH;
+ wsocket = new WebSocket(__URL);
+}
+
+function CreateWebSocketWithSpaceInProtocol(protocolWithSpace) {
+ IsWebSocket();
+ __URL = "ws://" + __SERVER__NAME + ":" + __PORT + "/" + __PATH;
+ wsocket = new WebSocket(__URL, protocolWithSpace);
+}
+
+function CreateWebSocketWithRepeatedProtocols() {
+ IsWebSocket();
+ __URL = "ws://" + __SERVER__NAME + ":" + __PORT + "/" + __PATH;
+ wsocket = new WebSocket(__URL, __REPEATED__PROTOCOLS);
+}
+
+function CreateWebSocket(isSecure, isProtocol, isProtocols) {
+ IsWebSocket();
+ if (isSecure) {
+ if (__SECURE__PORT === null) {
+ throw new Error("wss not yet supported");
+ }
+ __URL = "wss://" + __SERVER__NAME + ":" + __SECURE__PORT + "/" + __PATH;
+ }
+ else {
+ __URL = "ws://" + __SERVER__NAME + ":" + __PORT + "/" + __PATH;
+ }
+
+ if (isProtocol) {
+ wsocket = new WebSocket(__URL, __PROTOCOL);
+ }
+ else if (isProtocols) {
+ wsocket = new WebSocket(__URL, __PROTOCOLS);
+ }
+ else {
+ wsocket = new WebSocket(__URL);
+ }
+ return wsocket;
+}
+
+function CreateControlWebSocket(isSecure) {
+ IsWebSocket();
+ if (isSecure) {
+ __URL = "wss://" + __SERVER__NAME + ":" + __SECURE__PORT + "/" + __CONTROLPATH;
+ }
+ else {
+ __URL = "ws://" + __SERVER__NAME + ":" + __PORT + "/" + __CONTROLPATH;
+ }
+
+ csocket = new WebSocket(__URL);
+ return csocket;
+}
+
diff --git a/tests/wpt/web-platform-tests/webstorage/README.md b/tests/wpt/web-platform-tests/webstorage/README.md
new file mode 100644
index 00000000000..298028cc160
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webstorage/README.md
@@ -0,0 +1,10 @@
+This directory contains the Web Storage test suite.
+
+The spec's Implementation Report contains a list of each test file in the test suite and the results of running the test file on several browsers <http://www.w3.org/wiki/Webapps/Interop/WebStorage>.
+
+To run this test suite within a browser, go to: <http://w3c-test.org/webstorage/>.
+
+A W3C Recommendation of Web Storage was published on 30 July 2013 <http://www.w3.org/TR/2013/REC-webstorage-20130730/>.
+
+Latest Editor's Draft of Web Storage is: <http://dev.w3.org/html5/webstorage/>.
+
diff --git a/tests/wpt/web-platform-tests/webstorage/builtins.html b/tests/wpt/web-platform-tests/webstorage/builtins.html
new file mode 100644
index 00000000000..50561e19c22
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webstorage/builtins.html
@@ -0,0 +1,24 @@
+<!DOCTYPE HTML>
+<mete charset=utf-8>
+<title>Builtins</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+["localStorage", "sessionStorage"].forEach(function(name) {
+ test(function() {
+ var storage = window[name];
+ storage.clear();
+ assert_equals(storage.length, 0, "storage.length");
+
+ var builtins = ["key", "getItem", "setItem", "removeItem", "clear"];
+ var origBuiltins = builtins.map(function(b) { return Storage.prototype[b]; });
+ assert_array_equals(builtins.map(function(b) { return storage[b]; }), origBuiltins, "a");
+ builtins.forEach(function(b) { storage[b] = b; });
+ assert_array_equals(builtins.map(function(b) { return storage[b]; }), origBuiltins, "b");
+ assert_array_equals(builtins.map(function(b) { return storage.getItem(b); }), builtins, "c");
+
+ assert_equals(storage.length, builtins.length, "storage.length");
+ }, "Builtins in " + name);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/webstorage/clear.html b/tests/wpt/web-platform-tests/webstorage/clear.html
new file mode 100644
index 00000000000..2565b080399
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webstorage/clear.html
@@ -0,0 +1,24 @@
+<!DOCTYPE HTML>
+<mete charset=utf-8>
+<title>Clear</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+["localStorage", "sessionStorage"].forEach(function(name) {
+ test(function() {
+ var storage = window[name];
+ storage.clear();
+
+ storage.setItem("name", "user1");
+ assert_equals(storage.getItem("name"), "user1");
+ assert_equals(storage.name, "user1");
+ assert_equals(storage.length, 1);
+
+ storage.clear();
+ assert_equals(storage.getItem("name"), null, "storage.getItem('name')");
+ assert_equals(storage.name, undefined, "storage.name");
+ assert_equals(storage.length, 0, "storage.length");
+ }, "Clear in " + name);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/webstorage/event_constructor.html b/tests/wpt/web-platform-tests/webstorage/event_constructor.html
new file mode 100644
index 00000000000..cc543c7fc90
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webstorage/event_constructor.html
@@ -0,0 +1,32 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Web Storage</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <h1>event_session_Constructor</h1>
+ <div id="log"></div>
+ <script>
+ test(function() {
+ var t = async_test("storageeventinit test");
+ function onStorageEvent(event) {
+ t.step(function() {
+ assert_equals(event.type, 'storage');
+ assert_equals(event.key, null);
+ assert_equals(event.oldValue, null);
+ assert_equals(event.newValue, null);
+ assert_equals(event.url, '');
+ assert_equals(event.storageArea, null);
+ });
+ t.done();
+ }
+
+ window.addEventListener('storage', onStorageEvent, false);
+ var event = new StorageEvent('storage');
+ window.dispatchEvent(event);
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webstorage/event_constructor_js.html b/tests/wpt/web-platform-tests/webstorage/event_constructor_js.html
new file mode 100644
index 00000000000..3bfca4b1384
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webstorage/event_constructor_js.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Web Storage</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <h1>event_Constructor</h1>
+ <div id="log"></div>
+ <script>
+ test(function() {
+ var t = async_test("StorageEvent constructor and nulls");
+ function onStorageEvent(event) {
+ t.step(function() {
+ assert_equals(event.type, 'storage', 'type');
+ assert_equals(event.key, null, 'key');
+ assert_equals(event.oldValue, null, 'oldValue');
+ assert_equals(event.newValue, null, 'newValue');
+ assert_equals(event.url, 'null', 'url');
+ assert_equals(event.storageArea, null, 'storageArea');
+ });
+ t.done();
+ }
+
+ window.addEventListener('storage', onStorageEvent, false);
+ var event = new StorageEvent('storage', {
+ key: null,
+ oldValue: null,
+ newValue: null,
+ url: null
+ });
+ window.dispatchEvent(event);
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webstorage/event_local_key.html b/tests/wpt/web-platform-tests/webstorage/event_local_key.html
new file mode 100644
index 00000000000..0906912100b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webstorage/event_local_key.html
@@ -0,0 +1,42 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Web Storage</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ function fail(msg) {
+ t.step(function() {
+ assert_unreached(msg);
+ });
+ t.done();
+ }
+ </script>
+ </head>
+ <body>
+ <h1>event_local_key</h1>
+ <div id="log"></div>
+ <script>
+ test(function() {
+ localStorage.clear();
+ var t = async_test("key property test of local event");
+ var expected = ['name', null]
+ function onStorageEvent(event) {
+ t.step(function() {
+ assert_equals(event.key, expected.shift());
+ });
+ if (!expected.length) {
+ t.done();
+ }
+ }
+
+ window.addEventListener('storage', onStorageEvent, false);
+
+ var el = document.createElement("iframe");
+ el.setAttribute('id', 'ifrm');
+ el.setAttribute('src', 'iframe/local_set_item_clear_iframe.html');
+ document.body.appendChild(el);
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webstorage/event_local_newvalue.html b/tests/wpt/web-platform-tests/webstorage/event_local_newvalue.html
new file mode 100644
index 00000000000..700e8dcc055
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webstorage/event_local_newvalue.html
@@ -0,0 +1,42 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Web Storage</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ function fail(msg) {
+ t.step(function() {
+ assert_unreached(msg);
+ });
+ t.done();
+ }
+ </script>
+ </head>
+ <body>
+ <h1>event_local_newValue</h1>
+ <div id="log"></div>
+ <script>
+ test(function() {
+ localStorage.clear();
+ var t = async_test("newValue property test of local event");
+ var expected = ['user1', 'user2', null]
+ function onStorageEvent(event) {
+ t.step(function() {
+ assert_equals(event.newValue, expected.shift());
+ });
+ if (!expected.length) {
+ t.done();
+ }
+ }
+
+ window.addEventListener('storage', onStorageEvent, false);
+
+ var el = document.createElement("iframe");
+ el.setAttribute('id', 'ifrm');
+ el.setAttribute('src', 'iframe/local_change_item_iframe.html');
+ document.body.appendChild(el);
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webstorage/event_local_oldvalue.html b/tests/wpt/web-platform-tests/webstorage/event_local_oldvalue.html
new file mode 100644
index 00000000000..f113657cab4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webstorage/event_local_oldvalue.html
@@ -0,0 +1,42 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Web Storage</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ function fail(msg) {
+ t.step(function() {
+ assert_unreached(msg);
+ });
+ t.done();
+ }
+ </script>
+ </head>
+ <body>
+ <h1>event_local_oldValue</h1>
+ <div id="log"></div>
+ <script>
+ test(function() {
+ localStorage.clear();
+ var t = async_test("oldValue property test of local event");
+ var expected = [null, 'user1', null]
+ function onStorageEvent(event) {
+ t.step(function() {
+ assert_equals(event.oldValue, expected.shift());
+ });
+ if (!expected.length) {
+ t.done();
+ }
+ }
+
+ window.addEventListener('storage', onStorageEvent, false);
+
+ var el = document.createElement("iframe");
+ el.setAttribute('id', 'ifrm');
+ el.setAttribute('src', 'iframe/local_change_item_iframe.html');
+ document.body.appendChild(el);
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webstorage/event_local_storagearea.html b/tests/wpt/web-platform-tests/webstorage/event_local_storagearea.html
new file mode 100644
index 00000000000..df92ad35ef5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webstorage/event_local_storagearea.html
@@ -0,0 +1,43 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Web Storage</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ function fail(msg) {
+ t.step(function() {
+ assert_unreached(msg);
+ });
+ t.done();
+ }
+ </script>
+ </head>
+ <body>
+ <h1>event_local_storageArea</h1>
+ <div id="log"></div>
+ <script>
+ test(function() {
+ localStorage.clear();
+ var t = async_test("storageArea property test of local event");
+ function onStorageEvent(event) {
+ t.step(function() {
+ assert_equals(event.storageArea.length, 1);
+ var key = event.storageArea.key(0);
+ var value = event.storageArea.getItem(key);
+ assert_equals(key, "name");
+ assert_equals(value, "user1");
+ });
+ t.done();
+ }
+
+ window.addEventListener('storage', onStorageEvent, false);
+
+ var el = document.createElement("iframe");
+ el.setAttribute('id', 'ifrm');
+ el.setAttribute('src', 'iframe/local_set_item_iframe.html');
+ document.body.appendChild(el);
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webstorage/event_local_storageeventinit.html b/tests/wpt/web-platform-tests/webstorage/event_local_storageeventinit.html
new file mode 100644
index 00000000000..36e5a19e82d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webstorage/event_local_storageeventinit.html
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Web Storage</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <h1>event_local_StorageEventInit</h1>
+ <div id="log"></div>
+ <script>
+ test(function() {
+ var t = async_test("storageeventinit test");
+ function onStorageEvent(event) {
+ t.step(function() {
+ assert_equals(event.key, 'key');
+ assert_equals(event.oldValue, 'oldValue');
+ assert_equals(event.newValue, 'newValue');
+ assert_equals(event.url, window.location.href);
+ assert_equals(event.storageArea, window.localStorage);
+ });
+ t.done();
+ }
+
+ window.addEventListener('storage', onStorageEvent, false);
+
+ var event = new StorageEvent('storage', {
+ key: 'key',
+ oldValue: 'oldValue',
+ newValue: 'newValue',
+ url: window.location.href,
+ storageArea: window.localStorage
+ });
+
+ window.dispatchEvent(event);
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webstorage/event_local_url.html b/tests/wpt/web-platform-tests/webstorage/event_local_url.html
new file mode 100644
index 00000000000..6bc1b2592e2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webstorage/event_local_url.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Web Storage</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ function fail(msg) {
+ t.step(function() {
+ assert_unreached(msg);
+ });
+ t.done();
+ }
+ </script>
+ </head>
+ <body>
+ <h1>event_local_url</h1>
+ <div id="log"></div>
+ <script>
+ test(function() {
+ localStorage.clear();
+ var t = async_test("url property test of local event");
+ function onStorageEvent(event) {
+ t.step(function() {
+ var url = window.location.href;
+
+ var pos = url.lastIndexOf("/");
+ if (pos != -1) {
+ url = url.substr(0, pos + 1);
+ url = url + "iframe/local_set_item_iframe.html";
+ }
+
+ assert_equals(event.url, url);
+ });
+ t.done();
+ }
+
+ window.addEventListener('storage', onStorageEvent, false);
+
+ var el = document.createElement("iframe");
+ el.setAttribute('id', 'ifrm');
+ el.setAttribute('src', 'iframe/local_set_item_iframe.html');
+ document.body.appendChild(el);
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webstorage/event_session_key.html b/tests/wpt/web-platform-tests/webstorage/event_session_key.html
new file mode 100644
index 00000000000..07b61556907
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webstorage/event_session_key.html
@@ -0,0 +1,42 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Web Storage</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ function fail(msg) {
+ t.step(function() {
+ assert_unreached(msg);
+ });
+ t.done();
+ }
+ </script>
+ </head>
+ <body>
+ <h1>event_session_key</h1>
+ <div id="log"></div>
+ <script>
+ test(function() {
+ sessionStorage.clear();
+ var t = async_test("key property test of session event");
+ var expected = ['name', null]
+ function onStorageEvent(event) {
+ t.step(function() {
+ assert_equals(event.key, expected.shift());
+ });
+ if (!expected.length) {
+ t.done();
+ }
+ }
+
+ window.addEventListener('storage', onStorageEvent, false);
+
+ var el = document.createElement("iframe");
+ el.setAttribute('id', 'ifrm');
+ el.setAttribute('src', 'iframe/session_set_item_clear_iframe.html');
+ document.body.appendChild(el);
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webstorage/event_session_newvalue.html b/tests/wpt/web-platform-tests/webstorage/event_session_newvalue.html
new file mode 100644
index 00000000000..1973adab26e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webstorage/event_session_newvalue.html
@@ -0,0 +1,42 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Web Storage</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ function fail(msg) {
+ t.step(function() {
+ assert_unreached(msg);
+ });
+ t.done();
+ }
+ </script>
+ </head>
+ <body>
+ <h1>event_session_newValue</h1>
+ <div id="log"></div>
+ <script>
+ test(function() {
+ sessionStorage.clear();
+ var t = async_test("newvalue property test of session event");
+ var expected = ['user1', 'user2', null]
+ function onStorageEvent(event) {
+ t.step(function() {
+ assert_equals(event.newValue, expected.shift());
+ });
+ if (!expected.length) {
+ t.done();
+ }
+ }
+
+ window.addEventListener('storage', onStorageEvent, false);
+
+ var el = document.createElement("iframe");
+ el.setAttribute('id', 'ifrm');
+ el.setAttribute('src', 'iframe/session_change_item_iframe.html');
+ document.body.appendChild(el);
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webstorage/event_session_oldvalue.html b/tests/wpt/web-platform-tests/webstorage/event_session_oldvalue.html
new file mode 100644
index 00000000000..10c56fe58d9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webstorage/event_session_oldvalue.html
@@ -0,0 +1,42 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Web Storage</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ function fail(msg) {
+ t.step(function() {
+ assert_unreached(msg);
+ });
+ t.done();
+ }
+ </script>
+ </head>
+ <body>
+ <h1>event_session_oldValue</h1>
+ <div id="log"></div>
+ <script>
+ test(function() {
+ sessionStorage.clear();
+ var t = async_test("oldvalue property test of session event");
+ var expected = [null, 'user1', null]
+ function onStorageEvent(event) {
+ t.step(function() {
+ assert_equals(event.oldValue, expected.shift());
+ });
+ if (!expected.length) {
+ t.done();
+ }
+ }
+
+ window.addEventListener('storage', onStorageEvent, false);
+
+ var el = document.createElement("iframe");
+ el.setAttribute('id', 'ifrm');
+ el.setAttribute('src', 'iframe/session_change_item_iframe.html');
+ document.body.appendChild(el);
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webstorage/event_session_storagearea.html b/tests/wpt/web-platform-tests/webstorage/event_session_storagearea.html
new file mode 100644
index 00000000000..8ffd87189fe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webstorage/event_session_storagearea.html
@@ -0,0 +1,43 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Web Storage</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ function fail(msg) {
+ t.step(function() {
+ assert_unreached(msg);
+ });
+ t.done();
+ }
+ </script>
+ </head>
+ <body>
+ <h1>event_session_storageArea</h1>
+ <div id="log"></div>
+ <script>
+ test(function() {
+ var t = async_test("storageArea property test of session event");
+ function onStorageEvent(event) {
+ t.step(function() {
+ assert_equals(event.storageArea.length, 1);
+ var key = event.storageArea.key(0);
+ var value = event.storageArea.getItem(key);
+ assert_equals(key, "name");
+ assert_equals(value, "user1");
+ });
+ t.done();
+ }
+
+ window.addEventListener('storage', onStorageEvent, false);
+
+ var el = document.createElement("iframe");
+ el.setAttribute('id', 'ifrm');
+ el.setAttribute('src', 'iframe/session_set_item_iframe.html');
+ document.body.appendChild(el);
+ });
+ </script>
+
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webstorage/event_session_storageeventinit.html b/tests/wpt/web-platform-tests/webstorage/event_session_storageeventinit.html
new file mode 100644
index 00000000000..a2d2c1a7365
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webstorage/event_session_storageeventinit.html
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Web Storage</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <h1>event_session_StorageEventInit</h1>
+ <div id="log"></div>
+ <script>
+ test(function() {
+ var t = async_test("storageeventinit test");
+ function onStorageEvent(event) {
+ t.step(function() {
+ assert_equals(event.key, 'key');
+ assert_equals(event.oldValue, 'oldValue');
+ assert_equals(event.newValue, 'newValue');
+ assert_equals(event.url, window.location.href);
+ assert_equals(event.storageArea, window.sessionStorage);
+ });
+ t.done();
+ }
+
+ window.addEventListener('storage', onStorageEvent, false);
+
+ var event = new StorageEvent('storage', {
+ key: 'key',
+ oldValue: 'oldValue',
+ newValue: 'newValue',
+ url: window.location.href,
+ storageArea: window.sessionStorage
+ });
+
+ window.dispatchEvent(event);
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webstorage/event_session_url.html b/tests/wpt/web-platform-tests/webstorage/event_session_url.html
new file mode 100644
index 00000000000..30de7a6236c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webstorage/event_session_url.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Web Storage</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ function fail(msg) {
+ t.step(function() {
+ assert_unreached(msg);
+ });
+ t.done();
+ }
+ </script>
+ </head>
+ <body>
+ <h1>event_session_url</h1>
+ <div id="log"></div>
+ <script>
+ test(function() {
+ sessionStorage.clear();
+ var t = async_test("url property test of session event");
+ function onStorageEvent(event) {
+ t.step(function() {
+ var url = window.location.href;
+
+ var pos = url.lastIndexOf("/");
+ if (pos != -1) {
+ url = url.substr(0, pos + 1);
+ url = url + "iframe/session_set_item_iframe.html";
+ }
+
+ assert_equals(event.url, url);
+ });
+ t.done();
+ }
+
+ window.addEventListener('storage', onStorageEvent, false);
+
+ var el = document.createElement("iframe");
+ el.setAttribute('id', 'ifrm');
+ el.setAttribute('src', 'iframe/session_set_item_iframe.html');
+ document.body.appendChild(el);
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webstorage/getitem.html b/tests/wpt/web-platform-tests/webstorage/getitem.html
new file mode 100644
index 00000000000..13e9c444a18
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webstorage/getitem.html
@@ -0,0 +1,42 @@
+<!DOCTYPE HTML>
+<mete charset=utf-8>
+<title>getItem and named getter</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+["localStorage", "sessionStorage"].forEach(function(name) {
+ test(function() {
+ var storage = window[name];
+ storage.clear();
+ storage.setItem("name", "x");
+ storage.setItem("undefined", "foo");
+ storage.setItem("null", "bar");
+ storage.setItem("", "baz");
+
+ test(function() {
+ assert_equals(storage.length, 4);
+ }, "All items should be added to " + name + ".");
+
+ test(function() {
+ assert_equals(storage["unknown"], undefined, "storage['unknown']")
+ assert_equals(storage["name"], "x", "storage['name']")
+ assert_equals(storage["undefined"], "foo", "storage['undefined']")
+ assert_equals(storage["null"], "bar", "storage['null']")
+ assert_equals(storage[undefined], "foo", "storage[undefined]")
+ assert_equals(storage[null], "bar", "storage[null]")
+ assert_equals(storage[""], "baz", "storage['']")
+ }, "Named access to " + name + " should be correct");
+
+ test(function() {
+ assert_equals(storage.getItem("unknown"), null, "storage.getItem('unknown')")
+ assert_equals(storage.getItem("name"), "x", "storage.getItem('name')")
+ assert_equals(storage.getItem("undefined"), "foo", "storage.getItem('undefined')")
+ assert_equals(storage.getItem("null"), "bar", "storage.getItem('null')")
+ assert_equals(storage.getItem(undefined), "foo", "storage.getItem(undefined)")
+ assert_equals(storage.getItem(null), "bar", "storage.getItem(null)")
+ assert_equals(storage.getItem(""), "baz", "storage.getItem('')")
+ }, name + ".getItem should be correct")
+ }, "Builtins in " + name);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/webstorage/idlharness.html b/tests/wpt/web-platform-tests/webstorage/idlharness.html
new file mode 100644
index 00000000000..9c82721366d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webstorage/idlharness.html
@@ -0,0 +1,81 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Web Storage IDL tests</title>
+<link rel="author" title="W3C" href="http://www.w3.org/" />
+<link rel="help" href="http://www.w3.org/TR/webstorage/#storage"/>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/WebIDLParser.js"></script>
+<script src="/resources/idlharness.js"></script>
+</head>
+<body>
+<h1>Web Storage IDL tests</h1>
+<div id="log"></div>
+
+<pre id='untested_idl' style='display:none'>
+[PrimaryGlobal]
+interface Window {
+};
+
+interface Event {
+};
+
+interface EventInit {
+};
+</pre>
+
+<pre id='idl'>
+interface Storage {
+ readonly attribute unsigned long length;
+ DOMString? key(unsigned long index);
+ getter DOMString getItem(DOMString key);
+ setter creator void setItem(DOMString key, DOMString value);
+ deleter void removeItem(DOMString key);
+ void clear();
+};
+[NoInterfaceObject]
+interface WindowSessionStorage {
+ readonly attribute Storage sessionStorage;
+};
+Window implements WindowSessionStorage;
+[NoInterfaceObject]
+interface WindowLocalStorage {
+ readonly attribute Storage localStorage;
+};
+Window implements WindowLocalStorage;
+[Constructor(DOMString type, optional StorageEventInit eventInitDict)]
+interface StorageEvent : Event {
+ readonly attribute DOMString key;
+ readonly attribute DOMString? oldValue;
+ readonly attribute DOMString? newValue;
+ readonly attribute DOMString url;
+ readonly attribute Storage? storageArea;
+};
+
+dictionary StorageEventInit : EventInit {
+ DOMString key;
+ DOMString? oldValue;
+ DOMString? newValue;
+ DOMString url;
+ Storage? storageArea;
+};
+</pre>
+
+<script>
+
+(function() {
+ var idl_array = new IdlArray();
+
+ idl_array.add_untested_idls(document.getElementById("untested_idl").textContent);
+ idl_array.add_idls(document.getElementById("idl").textContent);
+
+ idl_array.add_objects({Storage: ["window.localStorage"]});
+
+ idl_array.test();
+})();
+
+</script>
+</body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webstorage/iframe/local_change_item_iframe.html b/tests/wpt/web-platform-tests/webstorage/iframe/local_change_item_iframe.html
new file mode 100644
index 00000000000..17be8fb26e0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webstorage/iframe/local_change_item_iframe.html
@@ -0,0 +1,18 @@
+<!DOCTYPE HTML>
+<html>
+ <body>
+ <script>
+ if (('localStorage' in window) && window.localStorage !== null){
+ try {
+ localStorage.setItem("name", "user1");
+ localStorage.setItem("name", "user2");
+ } catch (e) {
+ parent.fail("setItem method is failed.");
+ }
+ localStorage.clear();
+ } else {
+ parent.fail("localStorage is not supported.");
+ }
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webstorage/iframe/local_set_item_clear_iframe.html b/tests/wpt/web-platform-tests/webstorage/iframe/local_set_item_clear_iframe.html
new file mode 100644
index 00000000000..742b7dad1a3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webstorage/iframe/local_set_item_clear_iframe.html
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML>
+<html>
+ <body>
+ <script>
+ if (('localStorage' in window) && window.localStorage !== null){
+ try {
+ localStorage.setItem("name", "user1");
+ } catch (e) {
+ parent.fail("setItem method is failed.");
+ }
+ localStorage.clear();
+ } else {
+ parent.fail("localStorage is not supported.");
+ }
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webstorage/iframe/local_set_item_iframe.html b/tests/wpt/web-platform-tests/webstorage/iframe/local_set_item_iframe.html
new file mode 100644
index 00000000000..0693824e5db
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webstorage/iframe/local_set_item_iframe.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML>
+<html>
+ <body>
+ <script>
+ if (('localStorage' in window) && window.localStorage !== null){
+ try {
+ localStorage.setItem("name", "user1");
+ } catch (e) {
+ parent.fail("setItem method is failed.");
+ }
+ } else {
+ parent.fail("localStorage is not supported.");
+ }
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webstorage/iframe/session_change_item_iframe.html b/tests/wpt/web-platform-tests/webstorage/iframe/session_change_item_iframe.html
new file mode 100644
index 00000000000..1e1867e51ec
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webstorage/iframe/session_change_item_iframe.html
@@ -0,0 +1,18 @@
+<!DOCTYPE HTML>
+<html>
+ <body>
+ <script>
+ if (('sessionStorage' in window) && window.sessionStorage !== null){
+ try {
+ sessionStorage.setItem("name", "user1");
+ sessionStorage.setItem("name", "user2");
+ } catch (e) {
+ parent.fail("setItem method is failed.");
+ }
+ sessionStorage.clear();
+ } else {
+ parent.fail("sessionStorage is not supported.");
+ }
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webstorage/iframe/session_set_item_clear_iframe.html b/tests/wpt/web-platform-tests/webstorage/iframe/session_set_item_clear_iframe.html
new file mode 100644
index 00000000000..7deaa9b17c5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webstorage/iframe/session_set_item_clear_iframe.html
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML>
+<html>
+ <body>
+ <script>
+ if (('sessionStorage' in window) && window.sessionStorage !== null){
+ try {
+ sessionStorage.setItem('name', 'user1');
+ } catch (e) {
+ parent.fail('setItem method is failed.');
+ }
+ sessionStorage.clear();
+ } else {
+ parent.fail('sessionStorage is not supported.');
+ }
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webstorage/iframe/session_set_item_iframe.html b/tests/wpt/web-platform-tests/webstorage/iframe/session_set_item_iframe.html
new file mode 100644
index 00000000000..de844cca453
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webstorage/iframe/session_set_item_iframe.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML>
+<html>
+ <body>
+ <script>
+ if (('sessionStorage' in window) && window.sessionStorage !== null){
+ try {
+ sessionStorage.setItem('name', 'user1');
+ } catch (e) {
+ parent.fail('setItem method is failed.');
+ }
+ } else {
+ parent.fail('sessionStorage is not supported.');
+ }
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webstorage/in.html b/tests/wpt/web-platform-tests/webstorage/in.html
new file mode 100644
index 00000000000..f7a95012324
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webstorage/in.html
@@ -0,0 +1,30 @@
+<!DOCTYPE HTML>
+<mete charset=utf-8>
+<title>The in operator</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+["localStorage", "sessionStorage"].forEach(function(name) {
+ test(function() {
+ var storage = window[name];
+ storage.clear();
+
+ assert_false("name" in storage);
+ storage["name"] = "user1";
+ assert_true("name" in storage);
+ }, "The in operator in " + name + ": property access");
+
+ test(function() {
+ var storage = window[name];
+ storage.clear();
+
+ assert_false("name" in storage);
+ storage.setItem("name", "user1");
+ assert_true("name" in storage);
+ assert_equals(storage.name, "user1");
+ storage.removeItem("name");
+ assert_false("name" in storage);
+ }, "The in operator in " + name + ": method access");
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/webstorage/indexing.html b/tests/wpt/web-platform-tests/webstorage/indexing.html
new file mode 100644
index 00000000000..b8abb420b54
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webstorage/indexing.html
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML>
+<mete charset=utf-8>
+<title>Indexed getter</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+["localStorage", "sessionStorage"].forEach(function(name) {
+ test(function() {
+ var storage = window[name];
+ storage.clear();
+ storage["name"] = "user1";
+ storage["age"] = "42";
+
+ test(function() {
+ assert_equals(storage[-1], undefined);
+ assert_equals(storage[0], undefined);
+ assert_equals(storage[1], undefined);
+ assert_equals(storage[2], undefined);
+ }, "Getting number properties on " + name);
+
+ test(function() {
+ assert_equals(storage["-1"], undefined);
+ assert_equals(storage["0"], undefined);
+ assert_equals(storage["1"], undefined);
+ assert_equals(storage["2"], undefined);
+ }, "Getting number-valued string properties on " + name);
+
+ test(function() {
+ storage.setItem(1, "number");
+ assert_equals(storage[1], "number");
+ assert_equals(storage["1"], "number");
+ }, "Getting existing number-valued properties on " + name);
+ }, "Indexed getter on " + name);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/webstorage/key.html b/tests/wpt/web-platform-tests/webstorage/key.html
new file mode 100644
index 00000000000..3697f28ba88
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webstorage/key.html
@@ -0,0 +1,59 @@
+<!DOCTYPE HTML>
+<mete charset=utf-8>
+<title>Key</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+["localStorage", "sessionStorage"].forEach(function(name) {
+ test(function() {
+ var storage = window[name];
+ storage.clear();
+
+ storage.setItem("name", "user1");
+ storage.setItem("age", "20");
+ storage.setItem("a", "1");
+ storage.setItem("b", "2");
+
+ var keys = ["name", "age", "a", "b"];
+ function doTest(index) {
+ test(function() {
+ var key = storage.key(index);
+ assert_not_equals(key, null);
+ assert_true(keys.indexOf(key) >= 0,
+ "Unexpected key " + key + " found.");
+ }, name + ".key(" + index + ") should return the right thing.");
+ }
+ for (var i = 0; i < keys.length; ++i) {
+ doTest(i);
+ doTest(i + 0x100000000);
+ }
+
+ test(function() {
+ assert_equals(storage.key(-1), null, "storage.key(-1)");
+ assert_equals(storage.key(4), null, "storage.key(4)");
+ }, name + ".key() should return null for out-of-range arguments.");
+ }, name + ".key");
+
+ test(function() {
+ var get_keys = function(s) {
+ var keys = [];
+ for (var i = 0; i < s.length; ++i) {
+ keys.push(s.key(i));
+ }
+ return keys;
+ };
+ var storage = window[name];
+ storage.clear();
+
+ storage.setItem("name", "user1");
+ storage.setItem("age", "20");
+ storage.setItem("a", "1");
+ storage.setItem("b", "2");
+
+ var expected_keys = get_keys(storage);
+ storage.setItem("name", "user2");
+ assert_array_equals(get_keys(storage), expected_keys);
+ }, name + ".key with value changes");
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/webstorage/length.html b/tests/wpt/web-platform-tests/webstorage/length.html
new file mode 100644
index 00000000000..cc164da94f0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webstorage/length.html
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML>
+<mete charset=utf-8>
+<title>Length</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+["localStorage", "sessionStorage"].forEach(function(name) {
+ test(function() {
+ var storage = window[name];
+ storage.clear();
+ assert_equals(storage.length, 0, "storage.length")
+
+ storage["name"] = "user1";
+ storage["age"] = "20";
+
+ assert_equals(storage.length, 2, "storage.length")
+ }, name + ".length (method access)");
+
+ test(function() {
+ var storage = window[name];
+ storage.clear();
+ assert_equals(storage.length, 0, "storage.length")
+
+ storage.setItem("name", "user1");
+ storage.setItem("age", "20");
+
+ assert_equals(storage.length, 2, "storage.length")
+ }, name + ".length (proprty access)");
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/webstorage/missing_arguments.html b/tests/wpt/web-platform-tests/webstorage/missing_arguments.html
new file mode 100644
index 00000000000..984c60a1223
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webstorage/missing_arguments.html
@@ -0,0 +1,32 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Web Storage</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <h1>missing_arguments</h1>
+ <div id="log"></div>
+ <script>
+ var tests = [
+ function() { localStorage.key(); },
+ function() { localStorage.getItem(); },
+ function() { localStorage.setItem(); },
+ function() { localStorage.setItem("a"); },
+ function() { localStorage.removeItem(); },
+ function() { sessionStorage.key(); },
+ function() { sessionStorage.getItem(); },
+ function() { sessionStorage.setItem(); },
+ function() { sessionStorage.setItem("a"); },
+ function() { sessionStorage.removeItem(); },
+ function() { new StorageEvent(); }
+ ];
+ tests.forEach(function(fun) {
+ test(function() {
+ assert_throws(new TypeError(), fun);
+ }, "Should throw TypeError for " + format_value(fun) + ".");
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webstorage/removeitem.html b/tests/wpt/web-platform-tests/webstorage/removeitem.html
new file mode 100644
index 00000000000..a0b9b369502
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webstorage/removeitem.html
@@ -0,0 +1,52 @@
+<!DOCTYPE HTML>
+<mete charset=utf-8>
+<title>RemoveItem</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+["localStorage", "sessionStorage"].forEach(function(name) {
+ test(function() {
+ var storage = window[name];
+ storage.clear();
+
+ storage.setItem("name", "user1");
+ assert_equals(storage.getItem("name"), "user1");
+
+ storage.removeItem("name");
+ storage.removeItem("unknown");
+ assert_equals(storage.getItem("name"), null, "storage.getItem('name')")
+ }, name + ".removeItem()");
+
+ test(function() {
+ var storage = window[name];
+ storage.clear();
+
+ storage.setItem("name", "user1");
+ assert_equals(storage.getItem("name"), "user1");
+ delete storage["name"];
+ delete storage["unknown"];
+ assert_equals(storage.getItem("name"), null, "storage.getItem('name')")
+ }, "delete " + name + "[]");
+
+ test(function() {
+ var storage = window[name];
+ storage.clear();
+
+ storage.setItem("null", "test");
+ assert_true("null" in storage);
+ storage.removeItem(null);
+ assert_false("null" in storage);
+ }, name + ".removeItem(null)");
+
+ test(function() {
+ var storage = window[name];
+ storage.clear();
+
+ storage.setItem("undefined", "test");
+ assert_true("undefined" in storage);
+ storage.removeItem(undefined);
+ assert_false("undefined" in storage);
+ }, name + ".removeItem(undefined)");
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/webstorage/setitem.html b/tests/wpt/web-platform-tests/webstorage/setitem.html
new file mode 100644
index 00000000000..f3101b9a406
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webstorage/setitem.html
@@ -0,0 +1,160 @@
+<!DOCTYPE HTML>
+<mete charset=utf-8>
+<title>SetItem</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+["localStorage", "sessionStorage"].forEach(function(name) {
+ var test_error = { name: "test" };
+
+ test(function() {
+ var storage = window[name];
+ storage.clear();
+
+ storage.setItem("name", "user1");
+ assert_equals(storage.length, 1, "localStorage.setItem")
+ }, name + ".setItem()");
+
+ test(function() {
+ var storage = window[name];
+ storage.clear();
+
+ storage["name"] = "user1";
+ assert_true("name" in storage);
+ assert_equals(storage.length, 1, "storage.length")
+ assert_equals(storage.getItem("name"), "user1");
+ assert_equals(storage["name"], "user1");
+ }, name + "[]");
+
+ test(function() {
+ var storage = window[name];
+ storage.clear();
+
+ storage["name"] = "user1";
+ storage["name"] = "user2";
+ assert_true("name" in storage);
+ assert_equals(storage.length, 1, "storage.length")
+ assert_equals(storage.getItem("name"), "user2");
+ assert_equals(storage["name"], "user2");
+ }, name + "[] update");
+
+ test(function() {
+ var storage = window[name];
+ storage.clear();
+
+ storage.setItem("age", null);
+ assert_true("age" in storage);
+ assert_equals(storage.length, 1, "storage.length")
+ assert_equals(storage.getItem("age"), "null");
+ assert_equals(storage["age"], "null");
+ }, name + ".setItem(_, null)");
+
+ test(function() {
+ var storage = window[name];
+ storage.clear();
+
+ storage["age"] = null;
+ assert_true("age" in storage);
+ assert_equals(storage.length, 1, "storage.length")
+ assert_equals(storage.getItem("age"), "null");
+ assert_equals(storage["age"], "null");
+ }, name + "[] = null");
+
+ test(function() {
+ var storage = window[name];
+ storage.clear();
+
+ storage.setItem("age", undefined);
+ assert_true("age" in storage);
+ assert_equals(storage.length, 1, "storage.length")
+ assert_equals(storage.getItem("age"), "undefined");
+ assert_equals(storage["age"], "undefined");
+ }, name + ".setItem(_, undefined)");
+
+ test(function() {
+ var storage = window[name];
+ storage.clear();
+
+ storage["age"] = undefined;
+ assert_true("age" in storage);
+ assert_equals(storage.length, 1, "storage.length")
+ assert_equals(storage.getItem("age"), "undefined");
+ assert_equals(storage["age"], "undefined");
+ }, name + "[] = undefined");
+
+ test(function() {
+ var storage = window[name];
+ storage.clear();
+
+ storage.setItem("age", "10");
+ assert_throws(test_error, function() {
+ storage.setItem("age",
+ { toString: function() { throw test_error; } });
+ });
+ assert_true("age" in storage);
+ assert_equals(storage.length, 1, "storage.length")
+ assert_equals(storage.getItem("age"), "10");
+ assert_equals(storage["age"], "10");
+ }, name + ".setItem({ throws })");
+
+ test(function() {
+ var storage = window[name];
+ storage.clear();
+
+ storage.setItem("age", "10");
+ assert_throws(test_error, function() {
+ storage["age"] =
+ { toString: function() { throw test_error; } };
+ });
+ assert_true("age" in storage);
+ assert_equals(storage.length, 1, "storage.length")
+ assert_equals(storage.getItem("age"), "10");
+ assert_equals(storage["age"], "10");
+ }, name + "[] = { throws }");
+
+ test(function() {
+ var storage = window[name];
+ storage.clear();
+
+ storage.setItem(undefined, "test");
+ assert_true("undefined" in storage);
+ assert_equals(storage.length, 1, "storage.length")
+ assert_equals(storage.getItem("undefined"), "test");
+ assert_equals(storage["undefined"], "test");
+ }, name + ".setItem(undefined, _)");
+
+ test(function() {
+ var storage = window[name];
+ storage.clear();
+
+ storage[undefined] = "test2";
+ assert_true("undefined" in storage);
+ assert_equals(storage.length, 1, "storage.length")
+ assert_equals(storage.getItem("undefined"), "test2");
+ assert_equals(storage["undefined"], "test2");
+ }, name + "[undefined]");
+
+ test(function() {
+ var storage = window[name];
+ storage.clear();
+
+ storage.setItem(null, "test");
+ assert_true("null" in storage);
+ assert_equals(storage.length, 1, "storage.length")
+ assert_equals(storage.getItem("null"), "test");
+ assert_equals(storage["null"], "test");
+ }, name + ".setItem(null, _)");
+
+ test(function() {
+ var storage = window[name];
+ storage.clear();
+
+ storage[null] = "test2";
+ assert_true("null" in storage);
+ assert_equals(storage.length, 1, "storage.length")
+ assert_equals(storage.getItem("null"), "test2");
+ assert_equals(storage["null"], "test2");
+ }, name + "[null]");
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/webstorage/storage_local_setitem_quotaexceedederr.html b/tests/wpt/web-platform-tests/webstorage/storage_local_setitem_quotaexceedederr.html
new file mode 100644
index 00000000000..14c71eef47b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webstorage/storage_local_setitem_quotaexceedederr.html
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Web Storage</title>
+ <meta name="timeout" content="long">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <h1>storage_local_setItem_QUOTA_EXCEEDED_ERR</h1>
+ <div id="log"></div>
+ <script>
+ test(function() {
+ localStorage.clear();
+
+ var index = 0;
+ var key = "name";
+ var val = "user";
+
+ assert_throws("QUOTA_EXCEEDED_ERR", function() {
+ while (true) {
+ index++;
+ localStorage.setItem("" + key + index, "" + name + index);
+ }
+ });
+
+ localStorage.clear();
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webstorage/storage_session_setitem_quotaexceedederr.html b/tests/wpt/web-platform-tests/webstorage/storage_session_setitem_quotaexceedederr.html
new file mode 100644
index 00000000000..5e211552ec6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webstorage/storage_session_setitem_quotaexceedederr.html
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Web Storage</title>
+ <meta name="timeout" content="long">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <h1>storage_session_setItem_QUOTA_EXCEEDED_ERR</h1>
+ <div id="log"></div>
+ <script>
+ test(function() {
+ sessionStorage.clear();
+
+ var index = 0;
+ var key = "name";
+ var val = "user";
+
+ assert_throws("QUOTA_EXCEEDED_ERR", function() {
+ while (true) {
+ index++;
+ sessionStorage.setItem("" + key + index, "" + name + index);
+ }
+ });
+
+ sessionStorage.clear();
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/interfaces.html b/tests/wpt/web-platform-tests/webvtt/interfaces.html
new file mode 100644
index 00000000000..cb288350f0e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/interfaces.html
@@ -0,0 +1,64 @@
+<!doctype html>
+<title>WebVTT IDL tests</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=/resources/WebIDLParser.js></script>
+<script src=/resources/idlharness.js></script>
+
+<h1>WebVTT IDL tests</h1>
+<div id=log></div>
+
+<script type=text/plain>
+enum AutoKeyword { "auto" };
+enum DirectionSetting { "" /* horizontal */, "rl", "lr" };
+enum AlignSetting { "start", "middle", "end", "left", "right" };
+[Constructor(double startTime, double endTime, DOMString text)]
+interface VTTCue : TextTrackCue {
+ attribute VTTRegion? region;
+ attribute DirectionSetting vertical;
+ attribute boolean snapToLines;
+ attribute (double or AutoKeyword) line;
+ attribute AlignSetting lineAlign;
+ attribute double position;
+ attribute AlignSetting positionAlign;
+ attribute double size;
+ attribute AlignSetting align;
+ attribute DOMString text;
+ DocumentFragment getCueAsHTML();
+};
+
+enum ScrollSetting { "" /* none */, "up" };
+[Constructor]
+interface VTTRegion {
+ attribute double width;
+ attribute long lines;
+ attribute double regionAnchorX;
+ attribute double regionAnchorY;
+ attribute double viewportAnchorX;
+ attribute double viewportAnchorY;
+ attribute ScrollSetting scroll;
+};
+</script>
+<script>
+"use strict";
+var idlArray;
+setup(function() {
+ idlArray = new IdlArray();
+ [].forEach.call(document.querySelectorAll("script[type=text\\/plain]"), function(node) {
+ if (node.className == "untested") {
+ idlArray.add_untested_idls(node.textContent);
+ } else {
+ idlArray.add_idls(node.textContent);
+ }
+ });
+}, {explicit_done:true});
+window.onload = function() {
+ idlArray.add_objects({
+ // WebVTT
+ VTTCue: ['new VTTCue(0, 1, "foo")'],
+ VTTRegion: ['new VTTRegion()']
+ });
+ idlArray.test();
+ done();
+};
+</script>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/2_cues_overlapping_completely_move_up-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/2_cues_overlapping_completely_move_up-ref.html
new file mode 100644
index 00000000000..f90f72343fc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/2_cues_overlapping_completely_move_up-ref.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, repositioning (up) when 2 cues overlap completely</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+#cue1 {
+ position: absolute;
+ top: 50%;
+ left: 0;
+ right: 0;
+ margin-top: -18px;
+ text-align: center
+}
+#cue2 {
+ position: absolute;
+ top: 50%;
+ left: 0;
+ right: 0;
+ margin-top: -54px;
+ text-align: center
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: green;
+ font-size: 36px;
+}
+</style>
+<div class="video"><span class="cue" id="cue1"><span>This is a test subtitle</span></span><span class="cue" id="cue2"><span>This is another test subtitle</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/2_cues_overlapping_completely_move_up.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/2_cues_overlapping_completely_move_up.html
new file mode 100644
index 00000000000..11ea59d9ac1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/2_cues_overlapping_completely_move_up.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>WebVTT rendering, repositioning (up) when 2 cues overlap completely</title>
+<link rel="match" href="2_cues_overlapping_completely_move_up-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family: Ahem, sans-serif;
+ color: green
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); this.currentTime = 2;" onseeked="this.onseeked = null; takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="support/2_cues_overlapping_completely_move_up.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/2_cues_overlapping_partially_move_down-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/2_cues_overlapping_partially_move_down-ref.html
new file mode 100644
index 00000000000..4ddb155d20f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/2_cues_overlapping_partially_move_down-ref.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, repositioning (down) when 2 cues overlap partially</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+#cue1 {
+ position: absolute;
+ top: 50%;
+ left: 0;
+ right: 0;
+ margin-top: -18px;
+ text-align: center
+}
+#cue2 {
+ position: absolute;
+ top: 50%;
+ left: 0;
+ right: 0;
+ margin-top: 18px;
+ text-align: center
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: green;
+ font-size: 36px;
+}
+</style>
+<div class="video"><span class="cue" id="cue1"><span>This is a test subtitle</span></span><span class="cue" id="cue2"><span>This is another test subtitle</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/2_cues_overlapping_partially_move_down.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/2_cues_overlapping_partially_move_down.html
new file mode 100644
index 00000000000..9fd5c442ec1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/2_cues_overlapping_partially_move_down.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>WebVTT rendering, repositioning (down) when 2 cues overlap partially</title>
+<link rel="match" href="2_cues_overlapping_partially_move_down-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family: Ahem, sans-serif;
+ color: green
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); this.currentTime = 2;" onseeked="this.onseeked = null; takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="support/2_cues_overlapping_partially_move_down.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/2_cues_overlapping_partially_move_up-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/2_cues_overlapping_partially_move_up-ref.html
new file mode 100644
index 00000000000..cc3047d31d6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/2_cues_overlapping_partially_move_up-ref.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, repositioning (down) when 2 cues overlap partially</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+#cue1 {
+ position: absolute;
+ top: 50%;
+ left: 0;
+ right: 0;
+ margin-top: -18px;
+ text-align: center
+}
+#cue2 {
+ position: absolute;
+ top: 50%;
+ left: 0;
+ right: 0;
+ margin-top: -54px;
+ text-align: center
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: green;
+ font-size: 36px;
+}
+</style>
+<div class="video"><span class="cue" id="cue1"><span>This is a test subtitle</span></span><span class="cue" id="cue2"><span>This is another test subtitle</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/2_cues_overlapping_partially_move_up.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/2_cues_overlapping_partially_move_up.html
new file mode 100644
index 00000000000..c78c3033aae
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/2_cues_overlapping_partially_move_up.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>WebVTT rendering, repositioning (down) when 2 cues overlap partially</title>
+<link rel="match" href="2_cues_overlapping_partially_move_up-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family: Ahem, sans-serif;
+ color: green
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); this.currentTime = 2;" onseeked="this.onseeked = null; takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="support/2_cues_overlapping_partially_move_up.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/2_tracks-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/2_tracks-ref.html
new file mode 100644
index 00000000000..f0f4504a457
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/2_tracks-ref.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, 2 tracks enabled at the same time</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: white;
+ font-size: 36px;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <u>test subtitle</u><br>This is a test subtitle</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/2_tracks.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/2_tracks.html
new file mode 100644
index 00000000000..2394d6b5c35
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/2_tracks.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>WebVTT rendering, 2 tracks enabled at the same time</title>
+<link rel="match" href="2_tracks-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="support/test.vtt">
+ <track src="support/test_underline.vtt">
+</video>
+<script>
+document.getElementsByTagName('track')[0].track.mode = 'showing';
+document.getElementsByTagName('track')[1].track.mode = 'showing';
+</script>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/3_tracks-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/3_tracks-ref.html
new file mode 100644
index 00000000000..9fdd7b18fef
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/3_tracks-ref.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, 3 tracks enabled at the same time</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: white;
+ font-size: 36px;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <b>test subtitle</b><br>This is a <u>test subtitle</u><br>This is a test subtitle</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/3_tracks.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/3_tracks.html
new file mode 100644
index 00000000000..fee125f6146
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/3_tracks.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>WebVTT rendering, 3 tracks enabled at the same time</title>
+<link rel="match" href="3_tracks-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="support/test.vtt">
+ <track src="support/test_underline.vtt">
+ <track src="support/test_bold.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ document.getElementsByTagName('track')[1].track.mode = 'showing';
+ document.getElementsByTagName('track')[2].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_end-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_end-ref.html
new file mode 100644
index 00000000000..030fe6aff75
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_end-ref.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, align:end</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ width: 50%;
+ text-align: right;
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: green;
+ font-size: 36px
+}
+</style>
+<div class=video><span class=cue><span>This is a test</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_end.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_end.html
new file mode 100644
index 00000000000..d4b5cf49e37
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_end.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>WebVTT rendering, align:end</title>
+<link rel="match" href="align_end-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family: Ahem, sans-serif;
+ color: green
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="support/align_end.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_end_wrapped-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_end_wrapped-ref.html
new file mode 100644
index 00000000000..eed9217d9d4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_end_wrapped-ref.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, align:end with long cues</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ width: 50%;
+ text-align: right
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: green;
+ font-size: 36px
+}
+</style>
+<div class=video><span class=cue><span>This is a test <br>subtitle that <br>most likely <br>will span over <br>several rows <br>since it is a <br>pretty long <br>cue with a <br>lot of text.</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_end_wrapped.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_end_wrapped.html
new file mode 100644
index 00000000000..72477950235
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_end_wrapped.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>WebVTT rendering, align:end with long cues</title>
+<link rel="match" href="align_end_wrapped-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family: Ahem, sans-serif;
+ color: green
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="support/align_end_long.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_middle-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_middle-ref.html
new file mode 100644
index 00000000000..55cc7dd07c2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_middle-ref.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, align:middle</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center;
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: green;
+ font-size: 36px
+}
+</style>
+<div class=video><span class=cue><span>This is a test</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_middle.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_middle.html
new file mode 100644
index 00000000000..530dccf60cf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_middle.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>WebVTT rendering, align:middle</title>
+<link rel="match" href="align_middle-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family: Ahem, sans-serif;
+ color: green
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="support/align_middle.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_middle_position_50-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_middle_position_50-ref.html
new file mode 100644
index 00000000000..2c7d6c8c287
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_middle_position_50-ref.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, align:middle, position:50%</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center;
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: green;
+ font-size: 36px
+}
+</style>
+<div class=video><span class=cue><span>This is a test</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_middle_position_50.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_middle_position_50.html
new file mode 100644
index 00000000000..88b66428845
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_middle_position_50.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>WebVTT rendering, align:middle, position:50%</title>
+<link rel="match" href="align_middle_position_50-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family: Ahem, sans-serif;
+ color: green
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="support/align_middle_position_50.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_middle_position_gt_50-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_middle_position_gt_50-ref.html
new file mode 100644
index 00000000000..93bfd0c604a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_middle_position_gt_50-ref.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, align:middle, position greater than 50%</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ right: 92px;
+ width: 256px;
+ text-align: center;
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: green;
+ font-size: 36px
+}
+</style>
+<div class=video><span class=cue><span>Aweso<br>me!!!</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_middle_position_gt_50.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_middle_position_gt_50.html
new file mode 100644
index 00000000000..7790b20d257
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_middle_position_gt_50.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>WebVTT rendering, align:middle, position greater than 50%</title>
+<link rel="match" href="align_middle_position_gt_50-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family: Ahem, sans-serif;
+ color: green
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="support/align_middle_position_gt_50.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_middle_position_lt_50-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_middle_position_lt_50-ref.html
new file mode 100644
index 00000000000..86b3b5cb60c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_middle_position_lt_50-ref.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, align:middle, position less than 50%</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 92px;
+ right: 0;
+ width: 256px;
+ text-align: center
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: green;
+ font-size: 36px
+}
+</style>
+<div class=video><span class=cue><span>Awesome<br>!!!</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_middle_position_lt_50.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_middle_position_lt_50.html
new file mode 100644
index 00000000000..137dad80647
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_middle_position_lt_50.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>WebVTT rendering, align:middle, position less than 50%</title>
+<link rel="match" href="align_middle_position_lt_50-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family: Ahem, sans-serif;
+ color: green
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="support/align_middle_position_lt_50.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_middle_position_lt_50_size_gt_maximum_size-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_middle_position_lt_50_size_gt_maximum_size-ref.html
new file mode 100644
index 00000000000..a9303312bea
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_middle_position_lt_50_size_gt_maximum_size-ref.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, align:middle, position less than 50%, size greater than maximum size</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 92px;
+ right: 0;
+ width: 256px;
+ text-align: center;
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: green;
+ font-size: 36px
+}
+</style>
+<div class=video><span class=cue><span>Aweso<br>me!!!</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_middle_position_lt_50_size_gt_maximum_size.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_middle_position_lt_50_size_gt_maximum_size.html
new file mode 100644
index 00000000000..50cc5c15432
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_middle_position_lt_50_size_gt_maximum_size.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>WebVTT rendering, align:middle, position less than 50%, size greater than maximum size</title>
+<link rel="match" href="align_middle_position_lt_50_size_gt_maximum_size-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family: Ahem, sans-serif;
+ color: green
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="support/align_middle_position_lt_50_size_gt_maximum_size.vtt">
+</video>
+<script>
+document.getElementsByTagName('track')[0].track.mode = 'showing';
+</script>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_middle_wrapped-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_middle_wrapped-ref.html
new file mode 100644
index 00000000000..1c751fe1556
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_middle_wrapped-ref.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, align:middle with long cues</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center;
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: green;
+ font-size: 36px
+}
+</style>
+<div class=video><span class=cue><span>This is a test subtitle that <br>most likely will span over <br>several rows since it is a pretty <br>long cue with a lot of text.</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_middle_wrapped.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_middle_wrapped.html
new file mode 100644
index 00000000000..552788aaabc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_middle_wrapped.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>WebVTT rendering, align:middle with long cues</title>
+<link rel="match" href="align_middle_wrapped-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family: Ahem, sans-serif;
+ color: green
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="support/align_middle_long.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_start-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_start-ref.html
new file mode 100644
index 00000000000..4cdbc0e5b5e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_start-ref.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, align:start</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 50%;
+ right: 0;
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: green;
+ font-size: 36px
+}
+</style>
+<div class=video><span class=cue><span>This is a test</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_start.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_start.html
new file mode 100644
index 00000000000..a0f2eb07e5f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_start.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>WebVTT rendering, align:start</title>
+<link rel="match" href="align_start-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family: Ahem, sans-serif;
+ color: green
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="support/align_start.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_start_wrapped-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_start_wrapped-ref.html
new file mode 100644
index 00000000000..01051f01255
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_start_wrapped-ref.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, align:start with long cues</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 50%;
+ right: 0;
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: green;
+ font-size: 36px
+}
+</style>
+<div class=video><span class=cue><span>This is a test <br>subtitle that <br>most likely <br>will span over <br>several rows <br>since it is a <br>pretty long <br>cue with a <br>lot of text.</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_start_wrapped.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_start_wrapped.html
new file mode 100644
index 00000000000..e7244bf643f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/align_start_wrapped.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>WebVTT rendering, align:start with long cues</title>
+<link rel="match" href="align_start_wrapped-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family: Ahem, sans-serif;
+ color: green
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="support/align_start_long.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/audio_has_no_subtitles-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/audio_has_no_subtitles-ref.html
new file mode 100644
index 00000000000..a8a1c037149
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/audio_has_no_subtitles-ref.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>Reference for WebVTT rendering, &lt;audio&gt; should not have subtitles</title>
+<style>
+audio {
+ width: 1280px;
+ height: 720px;
+ outline: solid
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<audio autoplay controls onplaying="this.onplaying = null; this.pause(); this.currentTime = 0; takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+</audio>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/audio_has_no_subtitles.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/audio_has_no_subtitles.html
new file mode 100644
index 00000000000..013e45558ea
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/audio_has_no_subtitles.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>WebVTT rendering, &lt;audio&gt; should not have subtitles</title>
+<link rel="match" href="audio_has_no_subtitles-ref.html">
+<style>
+audio {
+ width: 1280px;
+ height: 720px;
+ outline: solid
+}
+::cue {
+ font-family: Ahem, sans-serif;
+ color: green
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<audio autoplay controls onplaying="this.onplaying = null; this.pause(); this.currentTime = 0; takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="support/test.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</audio>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/basic-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/basic-ref.html
new file mode 100644
index 00000000000..261a640e945
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/basic-ref.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, basic</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: green;
+ font-size: 36px;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/basic.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/basic.html
new file mode 100644
index 00000000000..fdaed5a6eb6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/basic.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>WebVTT rendering, basic</title>
+<link rel="match" href="basic-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family: Ahem, sans-serif;
+ color: green
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="support/test.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/bidi_ruby-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/bidi_ruby-ref.html
new file mode 100644
index 00000000000..cda42beb1cc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/bidi_ruby-ref.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, bidi ruby</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: white;
+ font-size: 36px;
+}
+</style>
+<div class="video"><span class="cue"><span><ruby>.<rt><bdo dir="ltr">&#x05D0;&#x05D0;</bdo></rt>ab)<rt>x</rt></ruby></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/bidi_ruby.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/bidi_ruby.html
new file mode 100644
index 00000000000..78393bf1f92
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/bidi_ruby.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, bidi ruby</title>
+<link rel="match" href="bidi_ruby-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../support/bidi_ruby.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/u002E_LF_u05D0-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/u002E_LF_u05D0-ref.html
new file mode 100644
index 00000000000..1d2255624b2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/u002E_LF_u05D0-ref.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, bidi U+002E LF U+05D0</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: white;
+ font-size: 36px;
+}
+</style>
+<div class="video"><span class="cue"><span>.<br><bdo dir=ltr>&#x05D0;ab)</bdo></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/u002E_LF_u05D0.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/u002E_LF_u05D0.html
new file mode 100644
index 00000000000..2cea16ee196
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/u002E_LF_u05D0.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, bidi U+002E LF U+05D0</title>
+<link rel="match" href="u002E_LF_u05D0-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../support/u002E_LF_u05D0.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/u002E_u2028_u05D0-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/u002E_u2028_u05D0-ref.html
new file mode 100644
index 00000000000..a1d748ed892
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/u002E_u2028_u05D0-ref.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, bidi U+002E U+2028 U+05D0</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: white;
+ font-size: 36px;
+}
+</style>
+<div class="video"><span class="cue"><span>.<br><bdo dir=ltr>(ab&#x05D0;</bdo></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/u002E_u2028_u05D0.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/u002E_u2028_u05D0.html
new file mode 100644
index 00000000000..f38c7964f92
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/u002E_u2028_u05D0.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, bidi U+002E U+2028 U+05D0</title>
+<link rel="match" href="u002E_u2028_u05D0-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../support/u002E_u2028_u05D0.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/u002E_u2029_u05D0-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/u002E_u2029_u05D0-ref.html
new file mode 100644
index 00000000000..09be0be5e43
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/u002E_u2029_u05D0-ref.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, bidi U+002E U+2029 U+05D0</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: white;
+ font-size: 36px;
+}
+</style>
+<div class="video"><span class="cue"><span>.<br><bdo dir=ltr>&#x05D0;ab)</bdo></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/u002E_u2029_u05D0.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/u002E_u2029_u05D0.html
new file mode 100644
index 00000000000..6243caa60f1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/u002E_u2029_u05D0.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, bidi U+002E U+2029 U+05D0</title>
+<link rel="match" href="u002E_u2029_u05D0-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../support/u002E_u2029_u05D0.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/u0041_first-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/u0041_first-ref.html
new file mode 100644
index 00000000000..208d20a5724
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/u0041_first-ref.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, bidi U+0041 first</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: white;
+ font-size: 36px;
+}
+</style>
+<div class="video"><span class="cue"><span><bdo dir=ltr>Aab)</bdo></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/u0041_first.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/u0041_first.html
new file mode 100644
index 00000000000..df9ed1a8142
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/u0041_first.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, bidi U+0041 first</title>
+<link rel="match" href="u0041_first-ref.html">
+<!--
+0041..005A ; L # L& [26] LATIN CAPITAL LETTER A..LATIN CAPITAL LETTER Z
+http://www.unicode.org/Public/UNIDATA/extracted/DerivedBidiClass.txt
+-->
+<style>
+html { overflow:hidden }
+body { margin:0 }
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../support/u0041_first.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/u05D0_first-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/u05D0_first-ref.html
new file mode 100644
index 00000000000..211f86455dd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/u05D0_first-ref.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, bidi U+05D0 first</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: white;
+ font-size: 36px;
+}
+</style>
+<div class="video"><span class="cue"><span><bdo dir=ltr>(ab&#x05D0;</bdo></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/u05D0_first.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/u05D0_first.html
new file mode 100644
index 00000000000..ea18c7ae994
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/u05D0_first.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, bidi U+05D0 first</title>
+<link rel="match" href="u05D0_first-ref.html">
+<!--
+05D0..05EA ; R # Lo [27] HEBREW LETTER ALEF..HEBREW LETTER TAV
+http://www.unicode.org/Public/UNIDATA/extracted/DerivedBidiClass.txt
+-->
+<style>
+html { overflow:hidden }
+body { margin:0 }
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../support/u05D0_first.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/u0628_first-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/u0628_first-ref.html
new file mode 100644
index 00000000000..4fb97c4f4b1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/u0628_first-ref.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, bidi U+0628 first</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: white;
+ font-size: 36px;
+}
+</style>
+<div class="video"><span class="cue"><span><bdo dir=ltr>(ab&#x0628;</bdo></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/u0628_first.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/u0628_first.html
new file mode 100644
index 00000000000..9f3d9e815d2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/u0628_first.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, bidi U+0628 first</title>
+<link rel="match" href="u0628_first-ref.html">
+<!--
+0620..063F ; AL # Lo [32] ARABIC LETTER KASHMIRI YEH..ARABIC LETTER FARSI YEH WITH THREE DOTS ABOVE
+http://www.unicode.org/Public/UNIDATA/extracted/DerivedBidiClass.txt
+-->
+<style>
+html { overflow:hidden }
+body { margin:0 }
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../support/u0628_first.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/u06E9_no_strong_dir-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/u06E9_no_strong_dir-ref.html
new file mode 100644
index 00000000000..cbd9ee0c2b4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/u06E9_no_strong_dir-ref.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, bidi U+06E9 no strong direction</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: white;
+ font-size: 36px;
+}
+</style>
+<div class="video"><span class="cue"><span><bdo dir=ltr>&#x06E9;)</bdo></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/u06E9_no_strong_dir.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/u06E9_no_strong_dir.html
new file mode 100644
index 00000000000..af6288a3774
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/bidi/u06E9_no_strong_dir.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, bidi U+06E9 no strong direction</title>
+<link rel="match" href="u06E9_no_strong_dir-ref.html">
+<!--
+06E9 ; ON # So ARABIC PLACE OF SAJDAH
+http://www.unicode.org/Public/UNIDATA/extracted/DerivedBidiClass.txt
+-->
+<style>
+html { overflow:hidden }
+body { margin:0 }
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../support/u06E9_no_strong_dir.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/cue_too_long-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/cue_too_long-ref.html
new file mode 100644
index 00000000000..56ce01cb91a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/cue_too_long-ref.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, size:50%, cue too long - should be cut</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 25%;
+ right: 0;
+ width: 50%;
+ text-align: center
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: green;
+ font-size: 36px;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle that should wrap several times and become so long that the cue must be cut when displayed, because it does not fit on the screen. This is a test subtitle that should wrap several times and become so long that the cue must be cut when displayed, because it does not fit on the</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/cue_too_long.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/cue_too_long.html
new file mode 100644
index 00000000000..21c4f11f1a0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/cue_too_long.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>WebVTT rendering, size:50%, cue too long - should be cut</title>
+<link rel="match" href="cue_too_long-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family: Ahem, sans-serif;
+ color: green
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="support/very_long_cue.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/decode_escaped_entities-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/decode_escaped_entities-ref.html
new file mode 100644
index 00000000000..7b9db92cc42
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/decode_escaped_entities-ref.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, decoding of escaped entities</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: green;
+ font-size: 36px;
+}
+</style>
+<div class="video"><span class="cue"><span>Here are the escaped <br>entities: &amp; &lt; &gt; &lrm; &rlm; &nbsp;</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/decode_escaped_entities.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/decode_escaped_entities.html
new file mode 100644
index 00000000000..b729e0650bc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/decode_escaped_entities.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>Reference for WebVTT rendering, decoding of escaped entities</title>
+<link rel="match" href="decode_escaped_entities-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family: Ahem, sans-serif;
+ color: green
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="support/decode_escaped_entities.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/disable_controls_reposition-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/disable_controls_reposition-ref.html
new file mode 100644
index 00000000000..eb9ba0ac956
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/disable_controls_reposition-ref.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, cue reposition after enabling controls</title>
+<style>
+.video {
+ display: inline-block;
+ outline: solid;
+ width: 320px;
+ height: 240px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: green;
+ font-size: 50px;
+}
+</style>
+<div class="video"><span class="cue"><span>Foo</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/disable_controls_reposition.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/disable_controls_reposition.html
new file mode 100644
index 00000000000..892e7e6a527
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/disable_controls_reposition.html
@@ -0,0 +1,28 @@
+<!doctype html>
+<html class="reftest-wait">
+<title>WebVTT rendering, cue reposition after disabling controls</title>
+<link rel="match" href="disable_controls_reposition-ref.html">
+<style>
+video {
+ outline: solid;
+ width: 320px;
+ height: 240px;
+}
+::cue {
+ font-family: Ahem, sans-serif;
+ font-size: 50px;
+ color: green;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video autoplay controls onplaying="this.onplaying = null;
+ this.pause();
+ this.currentTime = 0;
+ setTimeout(function(video){
+ video.controls = false;
+ }, 100, this);
+ setTimeout(takeScreenshot, 200);">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src=support/foo.vtt>
+</video>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/dom_override_cue_align_position_line_size-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/dom_override_cue_align_position_line_size-ref.html
new file mode 100644
index 00000000000..3ee9a946c7a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/dom_override_cue_align_position_line_size-ref.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, a cue's align, position, line and size properties is possible to override using the DOM APIs</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ top: 0;
+ right: 204.8px;
+ width: 256px;
+ text-align: left
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: green;
+ font-size: 36px;
+}
+</style>
+<div class="video"><span class="cue"><span>There is nothing to see here people, move on</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/dom_override_cue_align_position_line_size.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/dom_override_cue_align_position_line_size.html
new file mode 100644
index 00000000000..2db260a77f9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/dom_override_cue_align_position_line_size.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>WebVTT rendering, a cue's align, position, line and size properties is possible to override using the DOM APIs</title>
+<link rel="match" href="dom_override_cue_align_position_line_size-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family: Ahem, sans-serif;
+ color: green
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script>
+ function updateCue() {
+ var t = document.getElementById('track');
+ var c = t.track.cues[0];
+ c.align = 'start';
+ c.position = 80;
+ c.line = 0;
+ c.size = 20;
+ c.text = 'There is nothing to see here people, move on';
+ updateRendering();
+ }
+ function updateRendering() {
+ var v = document.getElementById('video');
+ v.onplaying = function() {
+ this.onplaying = null;
+ this.pause();
+ takeScreenshot();
+ };
+ v.play();
+ }
+</script>
+<video id="video" width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); updateCue();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track id="track" src="support/test.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/dom_override_cue_align_position_line_size_while_paused-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/dom_override_cue_align_position_line_size_while_paused-ref.html
new file mode 100644
index 00000000000..f796ddf21d3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/dom_override_cue_align_position_line_size_while_paused-ref.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, a cue's align, position, line and size properties should be rerendered when overriding them using the DOM APIs while paused</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ top: 0;
+ right: 204.8px;
+ width: 256px;
+ text-align: left
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: green;
+ font-size: 36px;
+}
+</style>
+<div class="video"><span class="cue"><span>This test tests</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/dom_override_cue_align_position_line_size_while_paused.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/dom_override_cue_align_position_line_size_while_paused.html
new file mode 100644
index 00000000000..4bf3a24a3f0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/dom_override_cue_align_position_line_size_while_paused.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>WebVTT rendering, a cue's align, position, line and size properties should be rerendered when overriding them using the DOM APIs while paused</title>
+<link rel="match" href="dom_override_cue_align_position_line_size_while_paused-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family: Ahem, sans-serif;
+ color: green
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script>
+ function updateCue() {
+ var t = document.getElementById('track');
+ var c = t.track.cues[0];
+ c.align = 'start';
+ c.position = 80;
+ c.line = 0;
+ c.size = 20;
+ c.text = 'This test tests';
+ takeScreenshot();
+ }
+</script>
+<video id="video" width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); updateCue();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track id="track" src="support/test.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/dom_override_cue_line-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/dom_override_cue_line-ref.html
new file mode 100644
index 00000000000..53de10228b6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/dom_override_cue_line-ref.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, it is possible to override cue line with the DOM APIs</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: green;
+ font-size: 36px;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/dom_override_cue_line.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/dom_override_cue_line.html
new file mode 100644
index 00000000000..f4094115bc7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/dom_override_cue_line.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>WebVTT rendering, it is possible to override cue line with the DOM APIs</title>
+<link rel="match" href="dom_override_cue_line-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family: Ahem, sans-serif;
+ color: green
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script>
+ function updateCue() {
+ var t = document.getElementById('track');
+ var c = t.track.cues[0];
+ c.line = 0;
+ updateRendering();
+ }
+ function updateRendering() {
+ var v = document.getElementById('video');
+ v.onplaying = function() {
+ this.onplaying = null;
+ this.pause();
+ takeScreenshot();
+ };
+ v.play();
+ }
+</script>
+<video id="video" width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); updateCue();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track id="track" src="support/test.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/dom_override_cue_text-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/dom_override_cue_text-ref.html
new file mode 100644
index 00000000000..fb9f13f8bff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/dom_override_cue_text-ref.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, it is possible to override cue text with the DOM APIs</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: green;
+ font-size: 36px;
+}
+</style>
+<div class="video"><span class="cue"><span>f o o</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/dom_override_cue_text.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/dom_override_cue_text.html
new file mode 100644
index 00000000000..a5d1026a91c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/dom_override_cue_text.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>WebVTT rendering, it is possible to override cue text with the DOM APIs</title>
+<link rel="match" href="dom_override_cue_text-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family: Ahem, sans-serif;
+ color: green
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script>
+ function updateCue() {
+ var t = document.getElementById('track');
+ var c = t.track.cues[0];
+ c.text = 'f o o';
+ updateRendering();
+ }
+ function updateRendering() {
+ var v = document.getElementById('video');
+ v.onplaying = function() {
+ this.onplaying = null;
+ this.pause();
+ takeScreenshot();
+ };
+ v.play();
+ }
+</script>
+<video id="video" width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); updateCue();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track id="track" src="support/test.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/dom_override_cue_text_while_paused-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/dom_override_cue_text_while_paused-ref.html
new file mode 100644
index 00000000000..42ca638a637
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/dom_override_cue_text_while_paused-ref.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, cue text should be rerendered when overriding them using the DOM APIs while paused</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: green;
+ font-size: 36px;
+}
+</style>
+<div class="video"><span class="cue"><span>f o o</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/dom_override_cue_text_while_paused.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/dom_override_cue_text_while_paused.html
new file mode 100644
index 00000000000..295db32f5e2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/dom_override_cue_text_while_paused.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>WebVTT rendering, cue text should be rerendered when overriding them using the DOM APIs while paused</title>
+<link rel="match" href="dom_override_cue_text_while_paused-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family: Ahem, sans-serif;
+ color: green
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script>
+ function updateCue() {
+ var t = document.getElementById('track');
+ var c = t.track.cues[0];
+ c.text = 'f o o';
+ takeScreenshot();
+ }
+</script>
+<video id="video" width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); updateCue();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track id="track" src="support/test.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/dom_override_remove_cue_while_paused-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/dom_override_remove_cue_while_paused-ref.html
new file mode 100644
index 00000000000..4525a7cf70b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/dom_override_remove_cue_while_paused-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, cue text should be removed when removing them using the DOM APIs while paused</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+</style>
+<div class="video"></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/dom_override_remove_cue_while_paused.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/dom_override_remove_cue_while_paused.html
new file mode 100644
index 00000000000..37481086d74
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/dom_override_remove_cue_while_paused.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>WebVTT rendering, cue text should be removed when removing them using the DOM APIs while paused</title>
+<link rel="match" href="dom_override_remove_cue_while_paused-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family: Ahem, sans-serif;
+ color: green
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script>
+ function updateCue() {
+ var t = document.getElementById('track');
+ var c = t.track.cues[0];
+ t.track.removeCue(c);
+ takeScreenshot();
+ }
+</script>
+<video id="video" width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); updateCue();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track id="track" src="support/test.vtt">
+</video>
+<script>
+document.getElementsByTagName('track')[0].track.mode = 'showing';
+</script>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/enable_controls_reposition-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/enable_controls_reposition-ref.html
new file mode 100644
index 00000000000..207662291e5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/enable_controls_reposition-ref.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, cue reposition after enabling controls</title>
+<style>
+.video {
+ display: inline-block;
+ outline: solid;
+ width: 320px;
+ height: 240px;
+ position: relative
+}
+video {
+ position: absolute;
+ width:320px;
+ height:240px;
+}
+.cue {
+ position: absolute;
+ bottom: 50px;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: green;
+ font-size: 50px;
+}
+</style>
+<video controls>
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+</video>
+<div class="video"><span class="cue"><span>Foo</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/enable_controls_reposition.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/enable_controls_reposition.html
new file mode 100644
index 00000000000..ab37c369c02
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/enable_controls_reposition.html
@@ -0,0 +1,28 @@
+<!doctype html>
+<html class="reftest-wait">
+<title>WebVTT rendering, cue reposition after enabling controls</title>
+<link rel="match" href="enable_controls_reposition-ref.html">
+<style>
+video {
+ outline: solid;
+ width: 320px;
+ height: 240px;
+}
+::cue {
+ font-family: Ahem, sans-serif;
+ font-size: 50px;
+ color: green;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video autoplay onplaying="this.onplaying = null;
+ this.pause();
+ this.currentTime = 0;
+ setTimeout(function(video){
+ video.controls = true;
+ }, 100, this);
+ setTimeout(takeScreenshot, 200);">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src=support/foo.vtt>
+</video>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/9_cues_overlapping_completely-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/9_cues_overlapping_completely-ref.html
new file mode 100644
index 00000000000..62fe1a62784
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/9_cues_overlapping_completely-ref.html
@@ -0,0 +1,112 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, repositioning of 9 cues that overlap completely</title>
+<style>
+.video {
+ display: inline-block;
+ width: 720px;
+ height: 720px;
+ outline: solid;
+ position: relative
+}
+#cue1 {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ right: 0;
+ margin-top: -18px;
+ margin-left: -18px;
+ color: #000
+}
+#cue2 {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ right: 0;
+ margin-top: -54px;
+ margin-left: -18px;
+ color: #222
+}
+#cue3 {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ right: 0;
+ margin-top: -18px;
+ margin-left: -54px;
+ color: #444
+}
+#cue4 {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ right: 0;
+ margin-top: -18px;
+ margin-left: 18px;
+ color: #666
+}
+#cue5 {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ right: 0;
+ margin-top: 18px;
+ margin-left: -18px;
+ color: #888
+}
+#cue6 {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ right: 0;
+ margin-top: -54px;
+ margin-left: -54px;
+ color: #aaa
+}
+#cue7 {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ right: 0;
+ margin-top: -54px;
+ margin-left: 18px;
+ color: #ccc
+}
+#cue8 {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ right: 0;
+ margin-top: 18px;
+ margin-left: -54px;
+ color: #eee
+}
+#cue9 {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ right: 0;
+ margin-top: 18px;
+ margin-left: 18px;
+ color: green
+}
+.cue {
+ width: 36px;
+ text-align: center
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+}
+</style>
+<div class="video">
+ <span class="cue" id="cue1"><span>1</span></span>
+ <span class="cue" id="cue2"><span>2</span></span>
+ <span class="cue" id="cue3"><span>3</span></span>
+ <span class="cue" id="cue4"><span>4</span></span>
+ <span class="cue" id="cue5"><span>5</span></span>
+ <span class="cue" id="cue6"><span>6</span></span>
+ <span class="cue" id="cue7"><span>7</span></span>
+ <span class="cue" id="cue8"><span>8</span></span>
+ <span class="cue" id="cue9"><span>9</span></span>
+</div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/9_cues_overlapping_completely.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/9_cues_overlapping_completely.html
new file mode 100644
index 00000000000..ac897a130e7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/9_cues_overlapping_completely.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, repositioning of 9 cues that overlap completely</title>
+<link rel="match" href="9_cues_overlapping_completely-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family: Ahem, sans-serif;
+}
+::cue(#cue1) {
+ color: #000
+}
+::cue(#cue2) {
+ color: #222
+}
+::cue(#cue3) {
+ color: #444
+}
+::cue(#cue4) {
+ color: #666
+}
+::cue(#cue5) {
+ color: #888
+}
+::cue(#cue6) {
+ color: #aaa
+}
+::cue(#cue7) {
+ color: #ccc
+}
+::cue(#cue8) {
+ color: #eee
+}
+::cue(#cue9) {
+ color: green
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="720" height="720" autoplay ontimeupdate="if (this.currentTime >= 1) { this.ontimeupdate = null; this.pause(); takeScreenshot(); }">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="support/9_cues_overlapping_completely.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/9_cues_overlapping_completely_all_cues_have_same_timestamp-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/9_cues_overlapping_completely_all_cues_have_same_timestamp-ref.html
new file mode 100644
index 00000000000..66140c0154e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/9_cues_overlapping_completely_all_cues_have_same_timestamp-ref.html
@@ -0,0 +1,112 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, repositioning of 9 cues that overlap completely and all cues have the same timestamp</title>
+<style>
+.video {
+ display: inline-block;
+ width: 720px;
+ height: 720px;
+ outline: solid;
+ position: relative
+}
+#cue1 {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ right: 0;
+ margin-top: -18px;
+ margin-left: -18px;
+ color: #000
+}
+#cue2 {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ right: 0;
+ margin-top: -54px;
+ margin-left: -18px;
+ color: #222
+}
+#cue3 {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ right: 0;
+ margin-top: -18px;
+ margin-left: -54px;
+ color: #444
+}
+#cue4 {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ right: 0;
+ margin-top: -18px;
+ margin-left: 18px;
+ color: #666
+}
+#cue5 {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ right: 0;
+ margin-top: 18px;
+ margin-left: -18px;
+ color: #888
+}
+#cue6 {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ right: 0;
+ margin-top: -54px;
+ margin-left: -54px;
+ color: #aaa
+}
+#cue7 {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ right: 0;
+ margin-top: -54px;
+ margin-left: 18px;
+ color: #ccc
+}
+#cue8 {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ right: 0;
+ margin-top: 18px;
+ margin-left: -54px;
+ color: #eee
+}
+#cue9 {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ right: 0;
+ margin-top: 18px;
+ margin-left: 18px;
+ color: green
+}
+.cue {
+ width: 36px;
+ text-align: center
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+}
+</style>
+<div class="video">
+ <span class="cue" id="cue1"><span>1</span></span>
+ <span class="cue" id="cue2"><span>2</span></span>
+ <span class="cue" id="cue3"><span>3</span></span>
+ <span class="cue" id="cue4"><span>4</span></span>
+ <span class="cue" id="cue5"><span>5</span></span>
+ <span class="cue" id="cue6"><span>6</span></span>
+ <span class="cue" id="cue7"><span>7</span></span>
+ <span class="cue" id="cue8"><span>8</span></span>
+ <span class="cue" id="cue9"><span>9</span></span>
+</div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/9_cues_overlapping_completely_all_cues_have_same_timestamp.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/9_cues_overlapping_completely_all_cues_have_same_timestamp.html
new file mode 100644
index 00000000000..267c3190f01
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/9_cues_overlapping_completely_all_cues_have_same_timestamp.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, repositioning of 9 cues that overlap completely and all cues have the same timestamp</title>
+<link rel="match" href="9_cues_overlapping_completely_all_cues_have_same_timestamp-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family: Ahem, sans-serif;
+}
+::cue(#cue1) {
+ color: #000
+}
+::cue(#cue2) {
+ color: #222
+}
+::cue(#cue3) {
+ color: #444
+}
+::cue(#cue4) {
+ color: #666
+}
+::cue(#cue5) {
+ color: #888
+}
+::cue(#cue6) {
+ color: #aaa
+}
+::cue(#cue7) {
+ color: #ccc
+}
+::cue(#cue8) {
+ color: #eee
+}
+::cue(#cue9) {
+ color: green
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="720" height="720" autoplay ontimeupdate="if (this.currentTime >= 1) { this.ontimeupdate = null; this.pause(); takeScreenshot(); }">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="support/9_cues_overlapping_completely_all_cues_have_same_timestamp.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/media_404_omit_subtitles-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/media_404_omit_subtitles-ref.html
new file mode 100644
index 00000000000..a3b48034c91
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/media_404_omit_subtitles-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, when media cannot be played (404 error), subtitles are not displayed</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+</style>
+<div class="video"></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/media_404_omit_subtitles.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/media_404_omit_subtitles.html
new file mode 100644
index 00000000000..15b12488b3d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/media_404_omit_subtitles.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, when media cannot be played (404 error), subtitles are not displayed</title>
+<link rel="match" href="media_404_omit_subtitles-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family: Ahem, sans-serif;
+ color: green
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="videonotfound.webm" type="video/webm">
+ <source src="videonotfound.mp4" type="video/mp4">
+ <track src="support/test.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/media_height_19-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/media_height_19-ref.html
new file mode 100644
index 00000000000..5908cf22b6a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/media_height_19-ref.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, when media height is 19 or less, font size should be smaller than when it is 20 and above</title>
+<style>
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 19px;
+ outline: solid;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: green;
+ font-size: 0.95px
+}
+</style>
+<div class=video><span class=cue><span>This is a test subtitle</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/media_height_19.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/media_height_19.html
new file mode 100644
index 00000000000..9e2a060f766
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/media_height_19.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, when media height is 19 or less, font size should be smaller than when it is 20 and above</title>
+<link rel="match" href="media_height_19-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family:Ahem, sans-serif;
+ color:green
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="19" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="support/test.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/single_quote-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/single_quote-ref.html
new file mode 100644
index 00000000000..2f1c1505893
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/single_quote-ref.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, single quote should not be levitated</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: green;
+ font-size: 36px;
+}
+</style>
+<div class="video"><span class="cue"><span>'</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/single_quote.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/single_quote.html
new file mode 100644
index 00000000000..af36ad78242
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/single_quote.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, single quote should not be levitated</title>
+<link rel="match" href="single_quote-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family: Ahem, sans-serif;
+ color: green
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="support/single_quote.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/size_90-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/size_90-ref.html
new file mode 100644
index 00000000000..65cf4c87112
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/size_90-ref.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, size:90% == size:100% when text does not need to wrap</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: green;
+ font-size: 36px
+}
+</style>
+<div class=video><span class=cue><span>This is a test subtitle</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/size_90.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/size_90.html
new file mode 100644
index 00000000000..9470da49d4f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/size_90.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, size:99% == size:100% when text does not need to wrap</title>
+<link rel="match" href="size_90-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family: Ahem, sans-serif;
+ color: green
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="support/size_90.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/size_99-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/size_99-ref.html
new file mode 100644
index 00000000000..ffabbe439bd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/size_99-ref.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, size:99% == size:100% when text does not need to wrap</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: green;
+ font-size: 36px
+}
+</style>
+<div class=video><span class=cue><span>This is a test subtitle</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/size_99.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/size_99.html
new file mode 100644
index 00000000000..8eef684ef99
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/size_99.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, size:99% == size:100% when text does not need to wrap</title>
+<link rel="match" href="size_99-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family: Ahem, sans-serif;
+ color: green
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="support/size_99.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/support/9_cues_overlapping_completely.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/support/9_cues_overlapping_completely.vtt
new file mode 100644
index 00000000000..3f4250d8b1c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/support/9_cues_overlapping_completely.vtt
@@ -0,0 +1,37 @@
+WEBVTT
+
+cue1
+00:00:00.001 --> 00:00:05.000 position:50% size:5% line:50%
+1
+
+cue2
+00:00:00.002 --> 00:00:05.000 position:50% size:5% line:50%
+2
+
+cue3
+00:00:00.003 --> 00:00:05.000 position:50% size:5% line:50%
+3
+
+cue4
+00:00:00.004 --> 00:00:05.000 position:50% size:5% line:50%
+4
+
+cue5
+00:00:00.005 --> 00:00:05.000 position:50% size:5% line:50%
+5
+
+cue6
+00:00:00.006 --> 00:00:05.000 position:50% size:5% line:50%
+6
+
+cue7
+00:00:00.007 --> 00:00:05.000 position:50% size:5% line:50%
+7
+
+cue8
+00:00:00.008 --> 00:00:05.000 position:50% size:5% line:50%
+8
+
+cue9
+00:00:00.009 --> 00:00:05.000 position:50% size:5% line:50%
+9
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/support/9_cues_overlapping_completely_all_cues_have_same_timestamp.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/support/9_cues_overlapping_completely_all_cues_have_same_timestamp.vtt
new file mode 100644
index 00000000000..d5019e0ed2c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/support/9_cues_overlapping_completely_all_cues_have_same_timestamp.vtt
@@ -0,0 +1,37 @@
+WEBVTT
+
+cue1
+00:00:00.000 --> 00:00:05.000 position:50% size:5% line:50%
+1
+
+cue2
+00:00:00.000 --> 00:00:05.000 position:50% size:5% line:50%
+2
+
+cue3
+00:00:00.000 --> 00:00:05.000 position:50% size:5% line:50%
+3
+
+cue4
+00:00:00.000 --> 00:00:05.000 position:50% size:5% line:50%
+4
+
+cue5
+00:00:00.000 --> 00:00:05.000 position:50% size:5% line:50%
+5
+
+cue6
+00:00:00.000 --> 00:00:05.000 position:50% size:5% line:50%
+6
+
+cue7
+00:00:00.000 --> 00:00:05.000 position:50% size:5% line:50%
+7
+
+cue8
+00:00:00.000 --> 00:00:05.000 position:50% size:5% line:50%
+8
+
+cue9
+00:00:00.000 --> 00:00:05.000 position:50% size:5% line:50%
+9
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/support/single_quote.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/support/single_quote.vtt
new file mode 100644
index 00000000000..5e7eefd2628
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/support/single_quote.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000
+'
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/support/size_90.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/support/size_90.vtt
new file mode 100644
index 00000000000..2ab4fa179f4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/support/size_90.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000 size:90%
+This is a test subtitle
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/support/size_99.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/support/size_99.vtt
new file mode 100644
index 00000000000..cd14574f098
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/support/size_99.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000 size:99%
+This is a test subtitle
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/support/test.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/support/test.vtt
new file mode 100644
index 00000000000..ab71ec59840
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/evil/support/test.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000
+This is a test subtitle
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_-2_wrapped_cue_grow_upwards-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_-2_wrapped_cue_grow_upwards-ref.html
new file mode 100644
index 00000000000..b62f6eaff60
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_-2_wrapped_cue_grow_upwards-ref.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, line:-2, size:50%, wrapped cue should grow upwards</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 36px;
+ left: 320px;
+ right: 0;
+ width: 640px;
+ text-align: center
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: green;
+ font-size: 36px;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle that will line break</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_-2_wrapped_cue_grow_upwards.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_-2_wrapped_cue_grow_upwards.html
new file mode 100644
index 00000000000..0fc7b1d5d4b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_-2_wrapped_cue_grow_upwards.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>WebVTT rendering, line:-2, size:50%, wrapped cue should grow upwards</title>
+<link rel="match" href="line_-2_wrapped_cue_grow_upwards-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family: Ahem, sans-serif;
+ color: green
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="support/line_-2_long.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_0_is_top-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_0_is_top-ref.html
new file mode 100644
index 00000000000..8538a20b8bd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_0_is_top-ref.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, line:0 should be top line</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: green;
+ font-size: 36px;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_0_is_top.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_0_is_top.html
new file mode 100644
index 00000000000..86ba937b46a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_0_is_top.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>WebVTT rendering, line:0 should be top line</title>
+<link rel="match" href="line_0_is_top-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family: Ahem, sans-serif;
+ color: green
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="support/line_0.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_1_wrapped_cue_grow_downwards-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_1_wrapped_cue_grow_downwards-ref.html
new file mode 100644
index 00000000000..0b48ad68450
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_1_wrapped_cue_grow_downwards-ref.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, line:1, size:50%, wrapped cue should grow downwards</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ top: 36px;
+ left: 320px;
+ right: 0;
+ width: 640px;
+ text-align: center
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: green;
+ font-size: 36px;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle that will line break</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_1_wrapped_cue_grow_downwards.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_1_wrapped_cue_grow_downwards.html
new file mode 100644
index 00000000000..34048ee1fbf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_1_wrapped_cue_grow_downwards.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>WebVTT rendering, line:1, size:50%, wrapped cue should grow downwards</title>
+<link rel="match" href="line_1_wrapped_cue_grow_downwards-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family: Ahem, sans-serif;
+ color: green
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="support/line_1_long.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_50_percent-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_50_percent-ref.html
new file mode 100644
index 00000000000..bd3cffc4a78
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_50_percent-ref.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, line:50% should be vertically centered</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ top: 50%;
+ left: 0;
+ right: 0;
+ margin-top: -18px;
+ text-align: center
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: green;
+ font-size: 36px;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_50_percent.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_50_percent.html
new file mode 100644
index 00000000000..ddfb450b470
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_50_percent.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>WebVTT rendering, line:50% should be vertically centered</title>
+<link rel="match" href="line_50_percent-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family: Ahem, sans-serif;
+ color: green
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="support/line_50_percent.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_integer_and_percent_mixed_overlap-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_integer_and_percent_mixed_overlap-ref.html
new file mode 100644
index 00000000000..4d853a17c41
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_integer_and_percent_mixed_overlap-ref.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, line integer and percent mixed with overlap</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+#cue1 {
+ position: absolute;
+ top: 324px;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+#cue2 {
+ position: absolute;
+ top: 360px;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: green;
+ font-size: 36px;
+}
+</style>
+<div class="video"><span id="cue1" class="cue"><span>This is a test subtitle</span></span><span id="cue2" class="cue"><span>This is another test subtitle</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_integer_and_percent_mixed_overlap.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_integer_and_percent_mixed_overlap.html
new file mode 100644
index 00000000000..3a3c13efc98
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_integer_and_percent_mixed_overlap.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>WebVTT rendering, line integer and percent mixed with overlap</title>
+<link rel="match" href="line_integer_and_percent_mixed_overlap-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family: Ahem, sans-serif;
+ color: green;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="support/line_integer_and_percent_overlap.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_integer_and_percent_mixed_overlap_move_up-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_integer_and_percent_mixed_overlap_move_up-ref.html
new file mode 100644
index 00000000000..05ff96677d3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_integer_and_percent_mixed_overlap_move_up-ref.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, line integer and percent mixed with overlap move up</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+#cue1 {
+ position: absolute;
+ top: 360px;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+#cue2 {
+ position: absolute;
+ top: 324px;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: green;
+ font-size: 36px;
+}
+</style>
+<div class="video"><span id="cue1" class="cue"><span>This is a test subtitle</span></span><span id="cue2" class="cue"><span>This is another test subtitle</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_integer_and_percent_mixed_overlap_move_up.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_integer_and_percent_mixed_overlap_move_up.html
new file mode 100644
index 00000000000..e0474200f28
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_integer_and_percent_mixed_overlap_move_up.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>WebVTT rendering, line integer and percent mixed with overlap move up</title>
+<link rel="match" href="line_integer_and_percent_mixed_overlap_move_up-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family: Ahem, sans-serif;
+ color: green;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="support/line_integer_and_percent_overlap_move_up.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_percent_and_integer_mixed_overlap-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_percent_and_integer_mixed_overlap-ref.html
new file mode 100644
index 00000000000..8c4fd892203
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_percent_and_integer_mixed_overlap-ref.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, line percent and integer mixed with overlap</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+#cue1 {
+ position: absolute;
+ top: 307.8px;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+#cue2 {
+ position: absolute;
+ top: 360px;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: green;
+ font-size: 36px;
+}
+</style>
+<div class="video"><span id="cue1" class="cue"><span>This is a test subtitle</span></span><span id="cue2" class="cue"><span>This is another test subtitle</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_percent_and_integer_mixed_overlap.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_percent_and_integer_mixed_overlap.html
new file mode 100644
index 00000000000..be2460020bb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_percent_and_integer_mixed_overlap.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>WebVTT rendering, line percent and integer mixed with overlap</title>
+<link rel="match" href="line_percent_and_integer_mixed_overlap-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family: Ahem, sans-serif;
+ color: green;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="support/line_percent_and_integer_overlap.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_percent_and_integer_mixed_overlap_move_up-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_percent_and_integer_mixed_overlap_move_up-ref.html
new file mode 100644
index 00000000000..e728943859f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_percent_and_integer_mixed_overlap_move_up-ref.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, line percent and integer mixed with overlap move up</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+#cue1 {
+ position: absolute;
+ top: 376.2px;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+#cue2 {
+ position: absolute;
+ top: 324px;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: green;
+ font-size: 36px;
+}
+</style>
+<div class="video"><span id="cue1" class="cue"><span>This is a test subtitle</span></span><span id="cue2" class="cue"><span>This is another test subtitle</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_percent_and_integer_mixed_overlap_move_up.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_percent_and_integer_mixed_overlap_move_up.html
new file mode 100644
index 00000000000..a78bad2c7b3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/line_percent_and_integer_mixed_overlap_move_up.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>WebVTT rendering, line percent and integer mixed with overlap move up</title>
+<link rel="match" href="line_percent_and_integer_mixed_overlap_move_up-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family: Ahem, sans-serif;
+ color: green;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="support/line_percent_and_integer_overlap_move_up.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/media/background.gif b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/media/background.gif
new file mode 100644
index 00000000000..b3185c409c6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/media/background.gif
Binary files differ
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/media_height400_with_controls-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/media_height400_with_controls-ref.html
new file mode 100644
index 00000000000..468e4061255
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/media_height400_with_controls-ref.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>Reference for WebVTT rendering, the subtitles is not covered by or covering the controls</title>
+<style>
+.video {
+ display: inline-block;
+ position: absolute;
+ width: 1280px;
+ height: 400px;
+ outline: solid
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center;
+ padding-bottom: 40px
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: green;
+ font-size: 20px
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<div class="video"><span class="cue"><span>This is a test subtitle</span></span></div>
+<video width="1280" height="400" autoplay controls onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track>
+</video>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/media_height400_with_controls.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/media_height400_with_controls.html
new file mode 100644
index 00000000000..6a5c36c3dc8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/media_height400_with_controls.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>WebVTT rendering, the subtitles is not covered by or covering the controls</title>
+<link rel="match" href="media_height400_with_controls-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family: Ahem, sans-serif;
+ color: green
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="400" autoplay controls onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="support/test.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/media_with_controls-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/media_with_controls-ref.html
new file mode 100644
index 00000000000..798bef10ff1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/media_with_controls-ref.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>Reference for WebVTT rendering, the subtitles are moved up to correct position when controls are visible</title>
+<style>
+.video {
+ display: inline-block;
+ position: absolute;
+ width: 1280px;
+ height: 720px;
+ outline: solid
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center;
+ padding-bottom: 36px
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: green;
+ font-size: 36px
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<div class="video"><span class="cue"><span>This is a test subtitle</span></span></div>
+<video width="1280" height="720" autoplay controls onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track>
+</video>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/media_with_controls.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/media_with_controls.html
new file mode 100644
index 00000000000..dcb89931276
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/media_with_controls.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>WebVTT rendering, the subtitles are moved up to correct position when controls are visible</title>
+<link rel="match" href="media_with_controls-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family: Ahem, sans-serif;
+ color: green
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay controls onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="support/test.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/navigate_cue_position-1.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/navigate_cue_position-1.html
new file mode 100644
index 00000000000..5effb332bc7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/navigate_cue_position-1.html
@@ -0,0 +1,23 @@
+<!doctype html>
+<html>
+<title>WebVTT rendering, cue position after navigation</title>
+<style>
+video {
+ outline: solid;
+ width: 320px;
+ height: 240px;
+}
+::cue {
+ font-family: Ahem, sans-serif;
+ font-size: 50px;
+ color: green;
+}
+</style>
+<video autoplay controls onplaying="this.onplaying = null;
+ this.pause();
+ this.currentTime = 0;
+ ">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src=support/foo.vtt>
+</video> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/navigate_cue_position-ref-1.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/navigate_cue_position-ref-1.html
new file mode 100644
index 00000000000..e155162f93d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/navigate_cue_position-ref-1.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, cue position after navigation</title>
+<style>
+.video {
+ display: inline-block;
+ outline: solid;
+ width: 320px;
+ height: 240px;
+ position: relative
+}
+video {
+ position: absolute;
+ width:320px;
+ height:240px;
+}
+.cue {
+ position: absolute;
+ bottom: 50px;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: green;
+ font-size: 50px;
+}
+</style>
+<video controls>
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+</video>
+<div class="video"><span class="cue"><span>Foo</span></span></div> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/navigate_cue_position-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/navigate_cue_position-ref.html
new file mode 100644
index 00000000000..b973a71c0de
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/navigate_cue_position-ref.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, cue position after navigation</title>
+<style>iframe {width:100%; height:500px}</style>
+<iframe src="navigate_cue_position-ref-1.html"></iframe>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/navigate_cue_position.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/navigate_cue_position.html
new file mode 100644
index 00000000000..6a50429e1b6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/navigate_cue_position.html
@@ -0,0 +1,27 @@
+<!doctype html>
+<html class="reftest-wait">
+<title>WebVTT rendering, cue position after navigation</title>
+<link rel="match" href="navigate_cue_position-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/utils.js"></script>
+<style>iframe {width:100%; height:500px}</style>
+<script>
+var uuid = token();
+onload = function() {
+ var frame = document.getElementsByTagName("iframe")[0].contentWindow;
+ if (sessionStorage[uuid]) {
+ document.body.appendChild(document.createTextNode('FAIL (page reloaded after navigation)'));
+ delete sessionStorage[uuid]
+ takeScreenshotDelayed(100);
+ } else {
+ setTimeout(function() {
+ frame.location.assign('data:text/html,<body onload="setTimeout(function(){history.back()}, 100); sessionStorage[\'' + uuid + '\'] = \'true\';">x');
+ setTimeout(function() {
+ delete sessionStorage[uuid];
+ takeScreenshot();
+ }, 500);
+ }, 100);
+ }
+}
+</script>
+<iframe src="navigate_cue_position-1.html"></iframe> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/one_line_cue_plus_wrapped_cue-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/one_line_cue_plus_wrapped_cue-ref.html
new file mode 100644
index 00000000000..f77a6dc367c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/one_line_cue_plus_wrapped_cue-ref.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, one line cue and cue that wraps - both should be fully visible</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 15%;
+ right: 0;
+ width: 70%;
+ text-align: center
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: green;
+ font-size: 36px;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle<br>This test subtitle wraps and should be visible</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/one_line_cue_plus_wrapped_cue.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/one_line_cue_plus_wrapped_cue.html
new file mode 100644
index 00000000000..c6ad95e8dbe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/one_line_cue_plus_wrapped_cue.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>WebVTT rendering, one line cue and cue that wraps - both should be fully visible</title>
+<link rel="match" href="one_line_cue_plus_wrapped_cue-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family: Ahem, sans-serif;
+ color: green
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="support/one_line_cue_plus_wrapped_cue.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/repaint-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/repaint-ref.html
new file mode 100644
index 00000000000..d0943070c11
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/repaint-ref.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, cue should repaint after hiding a covering abspos box</title>
+<style>
+.video {
+ display: inline-block;
+ width: 320px;
+ height: 240px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: green;
+ font-size: 50px;
+}
+</style>
+<p>You should see the word 'PASS' below.</p>
+<div class="video"><span class="cue"><span>PASS</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/repaint.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/repaint.html
new file mode 100644
index 00000000000..669880b9765
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/repaint.html
@@ -0,0 +1,51 @@
+<!doctype html>
+<html class="reftest-wait">
+<title>WebVTT rendering, cue should repaint after hiding a covering abspos box</title>
+<link rel="match" href="repaint-ref.html">
+<style>
+#wrapper {
+ position: relative;
+}
+#cover {
+ position: absolute;
+ left: 0px;
+ top: 180px;
+ width: 320px;
+ height: 60px;
+ background-color: gray;
+}
+video {
+ width: 320px;
+ height: 240px;
+}
+::cue {
+ font-size: 50px;
+ color: green;
+}
+</style>
+<p>You should see the word 'PASS' below.</p>
+<script src="/common/reftest-wait.js"></script>
+<div id=wrapper>
+ <video>
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ </video>
+ <div id=cover></div>
+</div>
+<script>
+var v = document.querySelector('video');
+var c = document.getElementById('cover');
+var t = v.addTextTrack('subtitles');
+t.mode = "showing";
+t.addCue(new VTTCue(0, 100, 'PASS'));
+v.onplaying = function() {
+ setTimeout(function() {
+ v.pause();
+ setTimeout(function() {
+ c.style.visibility = 'hidden';
+ setTimeout(takeScreenshot, 100);
+ }, 100);
+ }, 100);
+};
+v.play();
+</script>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/background_properties-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/background_properties-ref.html
new file mode 100644
index 00000000000..b23278a9c32
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/background_properties-ref.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue, background properties</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: #0f0 url('../../media/background.gif') repeat-x top left;
+ font-size: 36px;
+ color: green;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/background_properties.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/background_properties.html
new file mode 100644
index 00000000000..ef1f0a9ba61
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/background_properties.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue, background properties</title>
+<link rel="match" href="background_properties-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family: Ahem, sans-serif;
+ background-color: #0f0;
+ background-image: url('../../media/background.gif');
+ background-repeat: repeat-x;
+ background-position: top left;
+ color: green;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/test.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/background_shorthand-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/background_shorthand-ref.html
new file mode 100644
index 00000000000..944723c44f4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/background_shorthand-ref.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue, background shorthand</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: #0f0 url('../../media/background.gif') repeat-x top left;
+ font-size: 36px;
+ color: green;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/background_shorthand.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/background_shorthand.html
new file mode 100644
index 00000000000..612fe90fd93
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/background_shorthand.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue, background shorthand</title>
+<link rel="match" href="background_shorthand-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family: Ahem, sans-serif;
+ background: #0f0 url('../../media/background.gif') repeat-x top left;
+ color: green;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/test.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/background_shorthand_css_relative_url-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/background_shorthand_css_relative_url-ref.html
new file mode 100644
index 00000000000..4ad42151279
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/background_shorthand_css_relative_url-ref.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue, background shorthand, background image URL with relative path from CSS file</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: #0f0 url('../../media/background.gif') repeat-x top left;
+ font-size: 36px;
+ color: green;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/background_shorthand_css_relative_url.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/background_shorthand_css_relative_url.html
new file mode 100644
index 00000000000..91cd11e703b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/background_shorthand_css_relative_url.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue, background shorthand, background image URL with relative path from CSS file</title>
+<link rel="match" href="background_shorthand_css_relative_url-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family: Ahem, sans-serif;
+ background: #0f0 url('../../media/background.gif') repeat-x top left;
+ color: green;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/test.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/color_hex-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/color_hex-ref.html
new file mode 100644
index 00000000000..58942864d6e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/color_hex-ref.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue, color: #60ff60</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: #60ff60;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/color_hex.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/color_hex.html
new file mode 100644
index 00000000000..e8d091b25a7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/color_hex.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue, color: #60ff60</title>
+<link rel="match" href="color_hex-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family: Ahem, sans-serif;
+ color: #60ff60;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/test.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/color_hsla-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/color_hsla-ref.html
new file mode 100644
index 00000000000..2fd9a03134d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/color_hsla-ref.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue, color: hsla()</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: hsla(100,100%,50%,0.5);
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/color_hsla.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/color_hsla.html
new file mode 100644
index 00000000000..3830e8f4954
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/color_hsla.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue, color: hsla()</title>
+<link rel="match" href="color_hsla-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family: Ahem, sans-serif;
+ color: hsla(100,100%,50%,0.5);
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/test.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/color_rgba-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/color_rgba-ref.html
new file mode 100644
index 00000000000..50326b95c3c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/color_rgba-ref.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue, color: rgba()</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: rgba(128,255,128,0.5);
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/color_rgba.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/color_rgba.html
new file mode 100644
index 00000000000..c1eb1d95d8b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/color_rgba.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue, color: rgba()</title>
+<link rel="match" href="color_rgba-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family: Ahem, sans-serif;
+ color: rgba(128,255,128,0.5);
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/test.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/cue_selector_single_colon-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/cue_selector_single_colon-ref.html
new file mode 100644
index 00000000000..709f5177f0c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/cue_selector_single_colon-ref.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, :cue (single colon) should not be supported</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 25%;
+ right: 0;
+ width: 50%;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: white;
+ font-size: 36px;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/cue_selector_single_colon.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/cue_selector_single_colon.html
new file mode 100644
index 00000000000..51308553c0d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/cue_selector_single_colon.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, :cue (single colon) should not be supported</title>
+<link rel="match" href="cue_selector_single_colon-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+:cue {
+ background: red;
+ color: yellow
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/test.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/font_properties-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/font_properties-ref.html
new file mode 100644
index 00000000000..d7071fcc26a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/font_properties-ref.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue, font properties</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ font: italic small-caps bold 36px/72px sans-serif;
+ text-align: center
+}
+.cue > span {
+ background: rgba(0,0,0,0.8);
+ color: white;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle that most likely will span over several rows since it's a pretty long cue with a lot of text.</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/font_properties.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/font_properties.html
new file mode 100644
index 00000000000..1d24f9217e6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/font_properties.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue, font properties</title>
+<link rel="match" href="font_properties-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-style: italic;
+ font-variant: small-caps;
+ font-weight: bold;
+ font-size: 36px;
+ line-height: 72px;
+ font-family: sans-serif;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/test_long.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/font_shorthand-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/font_shorthand-ref.html
new file mode 100644
index 00000000000..b3a5d47f0cc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/font_shorthand-ref.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue, font shorthand</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ font: italic small-caps bold 36px/72px sans-serif;
+ text-align: center
+}
+.cue > span {
+ background: rgba(0,0,0,0.8);
+ color: white;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle that most likely will span over several rows since it's a pretty long cue with a lot of text.</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/font_shorthand.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/font_shorthand.html
new file mode 100644
index 00000000000..b7a3a267f92
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/font_shorthand.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue, font shorthand</title>
+<link rel="match" href="font_shorthand-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font: italic small-caps bold 36px/72px sans-serif;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/test_long.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/inherit_values_from_media_element-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/inherit_values_from_media_element-ref.html
new file mode 100644
index 00000000000..e8ef51b5e73
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/inherit_values_from_media_element-ref.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue, css properties with value inherit should inherit from media element</title>
+<style>
+.video {
+ position: absolute;
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative;
+ color: #f0f;
+ white-space: pre-wrap;
+ font: italic small-caps bold 36px/72px sans-serif;
+ text-decoration: overline underline line-through;
+ text-shadow: 0px 0px 5px #0f0;
+ background: #0f0 url('../../media/background.gif') repeat-x top left;
+ outline: solid #00f 2px;
+}
+.videoWhite {
+ position: absolute;
+ top: 0;
+ left: 160px;
+ width: 960px;
+ height: 720px;;
+ background: #fff;
+ z-index: 1;
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 30%;
+ right: 0;
+ width: 40%;
+ text-align: center;
+ outline: inherit;
+ text-shadow: inherit;
+ text-decoration: inherit;
+ outline-bottom: none;
+ z-index: 2
+}
+.cue > span {
+ background: #0f0 url('../../media/background.gif') repeat-x top left;
+ text-decoration: inherit;
+ white-space: pre-wrap
+}
+</style>
+<div class="video"><div class="videoWhite"></div><span class="cue"><span>A A A A A A A A A A A</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/inherit_values_from_media_element.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/inherit_values_from_media_element.html
new file mode 100644
index 00000000000..b93ac56ae34
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/inherit_values_from_media_element.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue, css properties with value inherit should inherit from media element</title>
+<link rel="match" href="inherit_values_from_media_element-ref.html">
+<style>
+video {
+ color: #f0f;
+ white-space: pre-wrap;
+ font: italic small-caps bold 36px/72px sans-serif;
+ text-decoration: overline underline line-through;
+ text-shadow: 0px 0px 5px #0f0;
+ background: #0f0 url('../../media/background.gif') repeat-x top left;
+ outline: solid #00f 2px;
+}
+::cue {
+ white-space: inherit;
+ font: inherit;
+ color: inherit;
+ text-decoration: inherit;
+ text-shadow: inherit;
+ background: inherit;
+ outline: inherit;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/white-spaces_long.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/outline_properties-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/outline_properties-ref.html
new file mode 100644
index 00000000000..be06607a2c6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/outline_properties-ref.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue, outline properties</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ outline: solid #00f 2px;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: green;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/outline_properties.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/outline_properties.html
new file mode 100644
index 00000000000..bfac1219825
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/outline_properties.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue, outline properties</title>
+<link rel="match" href="outline_properties-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family: Ahem, sans-serif;
+ outline-style: solid;
+ outline-color: #00f;
+ outline-width: 2px;
+ color: green;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/test.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/outline_shorthand-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/outline_shorthand-ref.html
new file mode 100644
index 00000000000..252094fc1b7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/outline_shorthand-ref.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue, outline shorthand</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ outline: solid #00f 2px;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: green;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/outline_shorthand.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/outline_shorthand.html
new file mode 100644
index 00000000000..4c39516c712
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/outline_shorthand.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue, outline shorthand</title>
+<link rel="match" href="outline_shorthand-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family: Ahem, sans-serif;
+ outline: solid #00f 2px;
+ color: green;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/test.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-decoration_line-through-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-decoration_line-through-ref.html
new file mode 100644
index 00000000000..70e314aa8c6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-decoration_line-through-ref.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue, text-decoration: line-through</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+ text-decoration: line-through;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-decoration_line-through.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-decoration_line-through.html
new file mode 100644
index 00000000000..3233b9d35ad
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-decoration_line-through.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue, text-decoration: line-through</title>
+<link rel="match" href="text-decoration_line-through-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family: sans-serif;
+ text-decoration: line-through;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/test.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-decoration_overline-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-decoration_overline-ref.html
new file mode 100644
index 00000000000..e3a3473935e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-decoration_overline-ref.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue, text-decoration: overline</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+ text-decoration: overline;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-decoration_overline.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-decoration_overline.html
new file mode 100644
index 00000000000..1d17b7f38dd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-decoration_overline.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue, text-decoration: overline</title>
+<link rel="match" href="text-decoration_overline-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family: sans-serif;
+ text-decoration: overline;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/test.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-decoration_overline_underline_line-through-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-decoration_overline_underline_line-through-ref.html
new file mode 100644
index 00000000000..7fb7d24c909
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-decoration_overline_underline_line-through-ref.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue, text-decoration: overline underline line-through</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+ text-decoration: overline underline line-through;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-decoration_overline_underline_line-through.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-decoration_overline_underline_line-through.html
new file mode 100644
index 00000000000..3d75cde0ed6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-decoration_overline_underline_line-through.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue, text-decoration: overline underline line-through</title>
+<link rel="match" href="text-decoration_overline_underline_line-through-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family: sans-serif;
+ text-decoration: overline underline line-through;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/test.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-decoration_underline-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-decoration_underline-ref.html
new file mode 100644
index 00000000000..acc0fb3eab8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-decoration_underline-ref.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue, text-decoration: underline</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+ text-decoration: underline;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-decoration_underline.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-decoration_underline.html
new file mode 100644
index 00000000000..bc2e1e9fa93
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-decoration_underline.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue, text-decoration: underline</title>
+<link rel="match" href="text-decoration_underline-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family: sans-serif;
+ text-decoration: underline;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/test.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-shadow-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-shadow-ref.html
new file mode 100644
index 00000000000..d12360fce67
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-shadow-ref.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue, text-shadow</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+ text-shadow: 0px 0px 5px #0f0;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-shadow.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-shadow.html
new file mode 100644
index 00000000000..cc4bfbd4484
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/text-shadow.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue, text-shadow</title>
+<link rel="match" href="text-shadow-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family: sans-serif;
+ text-shadow: 0px 0px 5px #0f0;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/test.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_normal_wrapped-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_normal_wrapped-ref.html
new file mode 100644
index 00000000000..56a79a1868c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_normal_wrapped-ref.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue, white-space: normal (cue that wraps)</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ font-size: 36px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 40%;
+ right: 0;
+ width: 20%;
+ text-align: center;
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: white;
+ white-space: normal
+}
+</style>
+<div class="video"><span class="cue"><span>foo bar baz</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_normal_wrapped.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_normal_wrapped.html
new file mode 100644
index 00000000000..68c2e45744c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_normal_wrapped.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue, white-space: normal (cue that wraps)</title>
+<link rel="match" href="white-space_normal_wrapped-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ white-space: normal
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/foo_space_space_bar_LF_baz.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_nowrap_wrapped-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_nowrap_wrapped-ref.html
new file mode 100644
index 00000000000..ab23711dcf2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_nowrap_wrapped-ref.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue, white-space: nowrap (cue that wraps)</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ font-size: 36px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 40%;
+ right: 0;
+ width: 20%;
+ text-align: center;
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: white;
+ white-space: nowrap
+}
+</style>
+<div class="video"><span class="cue"><span>A A A A A A A A A A A</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_nowrap_wrapped.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_nowrap_wrapped.html
new file mode 100644
index 00000000000..b22b5e122c7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_nowrap_wrapped.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue, white-space: nowrap (cue that wraps)</title>
+<link rel="match" href="white-space_nowrap_wrapped-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ white-space: nowrap
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/white-spaces_long_size_20.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_pre-line_wrapped-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_pre-line_wrapped-ref.html
new file mode 100644
index 00000000000..3d7607a11a2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_pre-line_wrapped-ref.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue, white-space: pre-line (cue that wraps)</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ font-size: 36px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 40%;
+ right: 0;
+ width: 20%;
+ text-align: center;
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: white;
+ white-space: normal
+}
+</style>
+<div class="video"><span class="cue"><span>A A A A A A<br> A A A A A</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_pre-line_wrapped.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_pre-line_wrapped.html
new file mode 100644
index 00000000000..8069ad6da50
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_pre-line_wrapped.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue, white-space: pre-line (cue that wraps)</title>
+<link rel="match" href="white-space_pre-line_wrapped-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ white-space: pre-line
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/white-spaces_long_size_20.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_pre-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_pre-ref.html
new file mode 100644
index 00000000000..ad03b218329
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_pre-ref.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue, white-space: pre</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ font-size: 36px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ font-family: sans-serif;
+ text-align: center
+}
+.cue > span {
+ background: rgba(0,0,0,0.8);
+ color: white;
+ white-space: pre
+}
+</style>
+<div class="video"><span class="cue"><span>A A A A A A</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_pre-wrap_wrapped-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_pre-wrap_wrapped-ref.html
new file mode 100644
index 00000000000..c92c303fb1e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_pre-wrap_wrapped-ref.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue, white-space: pre-wrap (cue that wraps)</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ font-size: 36px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 30%;
+ right: 0;
+ width: 40%;
+ font-family: sans-serif;
+ text-align: center;
+}
+.cue > span {
+ background: rgba(0,0,0,0.8);
+ color: white;
+ white-space: pre
+}
+</style>
+<div class="video"><span class="cue"><span>A A A A A <br> A <br>A A A A A</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_pre-wrap_wrapped.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_pre-wrap_wrapped.html
new file mode 100644
index 00000000000..e056a7d45b3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_pre-wrap_wrapped.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue, white-space: pre-wrap (cue that wraps)</title>
+<link rel="match" href="white-space_pre-wrap_wrapped-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ white-space: pre-wrap
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/white-spaces_long.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_pre.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_pre.html
new file mode 100644
index 00000000000..7b0c6021f66
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_pre.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue, white-space: pre</title>
+<link rel="match" href="white-space_pre-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ white-space: pre
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/white-spaces.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_pre_wrapped-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_pre_wrapped-ref.html
new file mode 100644
index 00000000000..65adcd3a609
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_pre_wrapped-ref.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue, white-space: pre (cue that wraps)</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ font-size: 36px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 30%;
+ right: 0;
+ width: 40%;
+ font-family: sans-serif;
+ text-align: center;
+}
+.cue > span {
+ background: rgba(0,0,0,0.8);
+ color: white;
+ white-space: pre
+}
+</style>
+<div class="video"><span class="cue"><span>A A A A A <br> A <br>A A A A A</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_pre_wrapped.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_pre_wrapped.html
new file mode 100644
index 00000000000..512808ef853
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue/white-space_pre_wrapped.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue, white-space: pre (cue that wraps)</title>
+<link rel="match" href="white-space_pre_wrapped-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ white-space: pre
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/white-spaces_long.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/background_box-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/background_box-ref.html
new file mode 100644
index 00000000000..05948c5af01
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/background_box-ref.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(* *) should match nothing (since the background box is anonymous)</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 25%;
+ right: 0;
+ width: 50%;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: white;
+ font-size: 36px;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/background_box.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/background_box.html
new file mode 100644
index 00000000000..be87c0281a3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/background_box.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(* *) should match nothing (since the background box is anonymous)</title>
+<link rel="match" href="background_box-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(* *) {
+ background:red;
+ color:yellow
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/test.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/background_properties-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/background_properties-ref.html
new file mode 100644
index 00000000000..8e1fa2e944b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/background_properties-ref.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(), background properties</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: #0f0 url('../../media/background.gif') repeat-x top left;
+ font-size: 36px;
+ color: green;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/background_properties.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/background_properties.html
new file mode 100644
index 00000000000..d95a4f26335
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/background_properties.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(), background properties</title>
+<link rel="match" href="background_properties-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(*) {
+ font-family: Ahem, sans-serif;
+ background-color: #0f0;
+ background-image: url('../../media/background.gif');
+ background-repeat: repeat-x;
+ background-position: top left;
+ color: green;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/test.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/background_shorthand-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/background_shorthand-ref.html
new file mode 100644
index 00000000000..22769b2ac90
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/background_shorthand-ref.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(), background shorthand</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: #0f0 url('../../media/background.gif') repeat-x top left;
+ font-size: 36px;
+ color: green;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/background_shorthand.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/background_shorthand.html
new file mode 100644
index 00000000000..b5653c7f01c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/background_shorthand.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(), background shorthand</title>
+<link rel="match" href="background_shorthand-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(*) {
+ font-family: Ahem, sans-serif;
+ background: #0f0 url('../../media/background.gif') repeat-x top left;
+ color: green;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/test.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/background_shorthand_css_relative_url-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/background_shorthand_css_relative_url-ref.html
new file mode 100644
index 00000000000..9ac9fe9e630
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/background_shorthand_css_relative_url-ref.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(), background shorthand, background image URL with relative path from CSS file</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: #0f0 url('../../media/background.gif') repeat-x top left;
+ font-size: 36px;
+ color: green;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/background_shorthand_css_relative_url.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/background_shorthand_css_relative_url.html
new file mode 100644
index 00000000000..1a206765beb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/background_shorthand_css_relative_url.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(), background shorthand, background image URL with relative path from CSS file</title>
+<link rel="match" href="background_shorthand_css_relative_url-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(*) {
+ font-family: Ahem, sans-serif;
+ background: #0f0 url('../../media/background.gif') repeat-x top left;
+ color: green;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/test.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_animation_with_timestamp-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_animation_with_timestamp-ref.html
new file mode 100644
index 00000000000..747b525e93a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_animation_with_timestamp-ref.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, bold object animation with timestamp, ::cue(b:past) selector</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+}
+.green {
+ color: #80ff80;
+ font-weight: bold;
+}
+</style>
+<div class="video"><span class="cue"><span><span class="green">This is a test subtitle</span></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_animation_with_timestamp.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_animation_with_timestamp.html
new file mode 100644
index 00000000000..8d5cfee937d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_animation_with_timestamp.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, bold object animation with timestamp, ::cue(b:past) selector</title>
+<link rel="match" href="bold_animation_with_timestamp-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(b:past) {
+ -o-animation: test 9s steps(2, start);
+ animation: test 9s steps(2, start);
+}
+@-o-keyframes test {
+ 0% {
+ color: #ffffff;
+ }
+ 100% {
+ color: #00ff00;
+ }
+}
+@keyframes test {
+ 0% {
+ color: #ffffff;
+ }
+ 100% {
+ color: #00ff00;
+ }
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; takeScreenshotDelayed(200);">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/bold_with_timestamp.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_background_properties-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_background_properties-ref.html
new file mode 100644
index 00000000000..40e105467e2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_background_properties-ref.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(b), background properties</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ font-size: 36px;
+ background: rgba(0,0,0,0.8);
+ color: white;
+}
+.cue > span > b {
+ background: #0f0 url('../../../media/background.gif') repeat-x top left;
+ color: #000;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <b>test subtitle</b></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_background_properties.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_background_properties.html
new file mode 100644
index 00000000000..d964bc83367
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_background_properties.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(b), background properties</title>
+<link rel="match" href="bold_background_properties-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(b) {
+ font-family: sans-serif;
+ background-color: #0f0;
+ background-image: url('../../../media/background.gif');
+ background-repeat: repeat-x;
+ background-position: top left;
+ color: black;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_bold.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_background_shorthand-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_background_shorthand-ref.html
new file mode 100644
index 00000000000..68571ebf57b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_background_shorthand-ref.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(b), background shorthand</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ font-size: 36px;
+ background: rgba(0,0,0,0.8);
+ color: white;
+}
+.cue > span > b {
+ background: #0f0 url('../../../media/background.gif') repeat-x top left;
+ color: #000;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <b>test subtitle</b></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_background_shorthand.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_background_shorthand.html
new file mode 100644
index 00000000000..c42e28b661a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_background_shorthand.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(b), background shorthand</title>
+<link rel="match" href="bold_background_shorthand-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(b) {
+ font-family: sans-serif;
+ background: #0f0 url('../../../media/background.gif') repeat-x top left;
+ color: #000;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_bold.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_color-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_color-ref.html
new file mode 100644
index 00000000000..1d703ed4154
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_color-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(b), color: #0000ff</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+}
+.cue > span > b {
+ color: #0000ff;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <b>test subtitle</b></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_color.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_color.html
new file mode 100644
index 00000000000..73f3b8c2d6b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_color.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(b), color: #0000ff</title>
+<link rel="match" href="bold_color-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(b) {
+ font-family: sans-serif;
+ color: #0000ff;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_bold.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_font_properties-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_font_properties-ref.html
new file mode 100644
index 00000000000..68c7e5b4aa5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_font_properties-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(b), font properties</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ font-family: sans-serif;
+ font-size: 36px;
+ text-align: center
+}
+.cue > span {
+ background: rgba(0,0,0,0.8);
+ color: white;
+}
+.cue > span > b {
+ font: italic small-caps normal 36px/72px sans-serif;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <b>test subtitle</b></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_font_properties.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_font_properties.html
new file mode 100644
index 00000000000..fe86d0a9f00
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_font_properties.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(b), font properties</title>
+<link rel="match" href="bold_font_properties-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(b) {
+ font-style: italic;
+ font-variant: small-caps;
+ font-weight: normal;
+ font-size: 36px;
+ line-height: 72px;
+ font-family: sans-serif;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_bold.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_font_shorthand-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_font_shorthand-ref.html
new file mode 100644
index 00000000000..6cbd672993d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_font_shorthand-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(b), font shorthand</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ font-family: sans-serif;
+ font-size: 36px;
+ text-align: center
+}
+.cue > span {
+ background: rgba(0,0,0,0.8);
+ color: white;
+}
+.cue > span > b {
+ font: normal small-caps normal 36px/72px sans-serif;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <b>test subtitle</b></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_font_shorthand.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_font_shorthand.html
new file mode 100644
index 00000000000..ed86c07b1db
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_font_shorthand.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(b), font shorthand</title>
+<link rel="match" href="bold_font_shorthand-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(b) {
+ font: normal small-caps normal 36px/72px sans-serif;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_bold.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_namespace-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_namespace-ref.html
new file mode 100644
index 00000000000..a0c20ef6452
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_namespace-ref.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(|b) should match</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: green;
+ font-size: 36px
+}
+.green {
+ font-weight: bold;
+ color: green;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <span class="green">test subtitle</span></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_namespace.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_namespace.html
new file mode 100644
index 00000000000..7db2820ca51
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_namespace.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(|b) should match</title>
+<link rel="match" href="bold_namespace-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ color: green;
+}
+::cue(*|b) {
+ color: red
+}
+::cue(|b) {
+ color: green
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_bold.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_outline_properties-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_outline_properties-ref.html
new file mode 100644
index 00000000000..a7711522a71
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_outline_properties-ref.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(b), outline properties</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+}
+.cue > span > b {
+ display: inline-block;
+ margin-left: -2px;
+ margin-right: -2px;
+ border: solid #00f 2px;
+ border-bottom: none;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <b>test subtitle</b></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_outline_properties.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_outline_properties.html
new file mode 100644
index 00000000000..1e04f8481b1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_outline_properties.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(b), outline properties</title>
+<link rel="match" href="bold_outline_properties-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(b) {
+ font-family: sans-serif;
+ outline-style: solid;
+ outline-color: #00f;
+ outline-width: 2px;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_bold.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_outline_shorthand-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_outline_shorthand-ref.html
new file mode 100644
index 00000000000..46f19dddea6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_outline_shorthand-ref.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(b), outline shorthand</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+}
+.cue > span > b {
+ display: inline-block;
+ margin-left: -2px;
+ margin-right: -2px;
+ border: solid #00f 2px;
+ border-bottom: none;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <b>test subtitle</b></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_outline_shorthand.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_outline_shorthand.html
new file mode 100644
index 00000000000..96e2791e6ed
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_outline_shorthand.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(b), outline shorthand</title>
+<link rel="match" href="bold_outline_shorthand-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(b) {
+ font-family: sans-serif;
+ outline: solid #00f 2px;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_bold.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_text-decoration_line-through-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_text-decoration_line-through-ref.html
new file mode 100644
index 00000000000..aa984fc8922
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_text-decoration_line-through-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(b), text-decoration: line-through</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+}
+.cue > span > b {
+ text-decoration: line-through;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <b>test subtitle</b></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_text-decoration_line-through.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_text-decoration_line-through.html
new file mode 100644
index 00000000000..caf81d78b01
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_text-decoration_line-through.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(b), text-decoration: line-through</title>
+<link rel="match" href="bold_text-decoration_line-through-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(b) {
+ font-family: sans-serif;
+ text-decoration: line-through;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_bold.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_text-shadow-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_text-shadow-ref.html
new file mode 100644
index 00000000000..c1d644009a1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_text-shadow-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(b), text-shadow</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+}
+.cue > span > b {
+ text-shadow: 0px 0px 5px #0f0;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <b>test subtitle</b></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_text-shadow.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_text-shadow.html
new file mode 100644
index 00000000000..00f5d449861
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_text-shadow.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(b), text-shadow</title>
+<link rel="match" href="bold_text-shadow-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(b) {
+ font-family: sans-serif;
+ text-shadow: 0px 0px 5px #0f0;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_bold.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_timestamp_future-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_timestamp_future-ref.html
new file mode 100644
index 00000000000..bdc4c16dcfb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_timestamp_future-ref.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, bold object transition with timestamp, ::cue(b:future) selector</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ font-weight: bold;
+ color: white;
+}
+.green {
+ color: #00ff00;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <span class="green">test subtitle</span></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_timestamp_future.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_timestamp_future.html
new file mode 100644
index 00000000000..ffe710fd282
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_timestamp_future.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, bold object transition with timestamp, ::cue(b:future) selector</title>
+<link rel="match" href="bold_timestamp_future-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(b:future) {
+ color: #00ff00;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; takeScreenshotDelayed(200);">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/bold_with_2_timestamps.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_timestamp_past-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_timestamp_past-ref.html
new file mode 100644
index 00000000000..f0fd1ae2ff2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_timestamp_past-ref.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, bold object transition with timestamp, ::cue(b:past) selector</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ font-weight: bold;
+ color: white;
+}
+.green {
+ color: #00ff00;
+}
+</style>
+<div class="video"><span class="cue"><span><span class="green">This is a test subtitle</span></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_timestamp_past.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_timestamp_past.html
new file mode 100644
index 00000000000..b46a5ae89cd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_timestamp_past.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, bold object transition with timestamp, ::cue(b:past) selector</title>
+<link rel="match" href="bold_timestamp_past-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(b:past) {
+ color: #00ff00;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; takeScreenshotDelayed(200);">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/bold_with_timestamp.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_transition_with_timestamp-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_transition_with_timestamp-ref.html
new file mode 100644
index 00000000000..602480ad8cb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_transition_with_timestamp-ref.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, bold object transition with timestamp, ::cue(b:past) selector</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+}
+.green {
+ color: #80ff80;
+ font-weight: bold;
+}
+</style>
+<div class="video"><span class="cue"><span><span class="green">This is a test subtitle</span></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_transition_with_timestamp.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_transition_with_timestamp.html
new file mode 100644
index 00000000000..01e8751c65a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_transition_with_timestamp.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, bold object transition with timestamp, ::cue(b:past) selector</title>
+<link rel="match" href="bold_transition_with_timestamp-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(b) {
+ -o-transition: color 9s steps(2, start);
+ transition: color 9s steps(2, start);
+}
+::cue(b:past) {
+ color: #00ff00;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; takeScreenshotDelayed(200);">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/bold_with_timestamp.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_normal_wrapped-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_normal_wrapped-ref.html
new file mode 100644
index 00000000000..3ba3d4b45f7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_normal_wrapped-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, bold object, ::cue(b), white-space: normal (cue that wraps)</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ font-size: 36px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 25%;
+ right: 0;
+ width: 50%;
+ text-align: center;
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: white;
+ font-weight: bold;
+ white-space: normal
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle that most likely will span over several rows since it's a pretty long cue with a lot of text.</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_normal_wrapped.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_normal_wrapped.html
new file mode 100644
index 00000000000..3ac0ddead93
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_normal_wrapped.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, bold object, ::cue(b), white-space: normal (cue that wraps)</title>
+<link rel="match" href="bold_white-space_normal_wrapped-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(b) {
+ white-space: normal
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/bold_long.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_nowrap-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_nowrap-ref.html
new file mode 100644
index 00000000000..4aca609415a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_nowrap-ref.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, bold object, ::cue(b), white-space: nowrap (cue does not wrap)</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ font-size: 36px;
+ position: relative;
+ overflow: hidden;
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 25%;
+ right: 0;
+ width: 50%;
+ text-align: center;
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: white;
+ font-weight: bold;
+ white-space: nowrap
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle that most likely will span over several rows since it's a pretty long cue with a lot of text.</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_nowrap.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_nowrap.html
new file mode 100644
index 00000000000..150f1d28aed
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_nowrap.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, bold object, ::cue(b), white-space: nowrap (cue does not wrap)</title>
+<link rel="match" href="bold_white-space_nowrap-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(b) {
+ white-space: nowrap
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/bold_long.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_pre-line_wrapped-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_pre-line_wrapped-ref.html
new file mode 100644
index 00000000000..19da7439dde
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_pre-line_wrapped-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, bold object, ::cue(b), white-space: pre-line (cue that wraps)</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ font-size: 36px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 25%;
+ right: 0;
+ width: 50%;
+ text-align: center;
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: white;
+ font-weight: bold;
+ white-space: pre-line
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle that most likely will span over several rows since it's a pretty long cue with a lot of text.</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_pre-line_wrapped.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_pre-line_wrapped.html
new file mode 100644
index 00000000000..e6d52f8695b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_pre-line_wrapped.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, bold object, ::cue(b), white-space: pre-line (cue that wraps)</title>
+<link rel="match" href="bold_white-space_pre-line_wrapped-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(b) {
+ white-space: pre-line
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/bold_long.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_pre-wrap_wrapped-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_pre-wrap_wrapped-ref.html
new file mode 100644
index 00000000000..4d4eecf4e3c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_pre-wrap_wrapped-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, bold object, ::cue(b), white-space: pre-wrap (cue that wraps)</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ font-size: 36px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 25%;
+ right: 0;
+ width: 50%;
+ text-align: center;
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: white;
+ font-weight: bold;
+ white-space: pre-wrap
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle that most likely will span over several rows since it's a pretty long cue with a lot of text.</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_pre-wrap_wrapped.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_pre-wrap_wrapped.html
new file mode 100644
index 00000000000..4ac9e526981
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_pre-wrap_wrapped.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, bold object, ::cue(b), white-space: pre-wrap (cue that wraps)</title>
+<link rel="match" href="bold_white-space_pre-wrap_wrapped-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(b) {
+ white-space: pre-wrap
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/bold_long.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_pre_wrapped-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_pre_wrapped-ref.html
new file mode 100644
index 00000000000..398c09095d4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_pre_wrapped-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, bold object, ::cue(b), white-space: pre (cue that wraps)</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ font-size: 36px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 25%;
+ right: 0;
+ width: 50%;
+ text-align: center;
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: white;
+ font-weight: bold;
+ white-space: pre
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle that most <br>likely will span over several <br>rows since it's a pretty long cue <br>with a lot of text.</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_pre_wrapped.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_pre_wrapped.html
new file mode 100644
index 00000000000..3b100b5518d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_white-space_pre_wrapped.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, bold object, ::cue(b), white-space: pre (cue that wraps)</title>
+<link rel="match" href="bold_white-space_pre_wrapped-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(b) {
+ white-space: pre
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/bold_long.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_with_class-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_with_class-ref.html
new file mode 100644
index 00000000000..7e0b4aff8fe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_with_class-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, bold object with class, ::cue(.foo) selector</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+}
+.green {
+ color: #00ff00;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <b>test subtitle</b>, <b class="green">test subtitle</b></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_with_class.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_with_class.html
new file mode 100644
index 00000000000..ad542c52b49
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_with_class.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, bold object with class, ::cue(.foo) selector</title>
+<link rel="match" href="bold_with_class-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(.foo) {
+ font-family: sans-serif;
+ color: #00ff00;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_bold_with_class.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_with_class_object_specific_selector-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_with_class_object_specific_selector-ref.html
new file mode 100644
index 00000000000..7097530bb42
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_with_class_object_specific_selector-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, bold object with class, ::cue(b.foo) selector</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+}
+.green {
+ color: #00ff00;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <b>test subtitle</b>, <b class="green">test subtitle</b></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_with_class_object_specific_selector.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_with_class_object_specific_selector.html
new file mode 100644
index 00000000000..1d54d956d99
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/bold_object/bold_with_class_object_specific_selector.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, bold object with class, ::cue(b.foo) selector</title>
+<link rel="match" href="bold_with_class_object_specific_selector-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(b.foo) {
+ font-family: sans-serif;
+ color: #00ff00;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_bold_with_class.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_animation_with_timestamp-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_animation_with_timestamp-ref.html
new file mode 100644
index 00000000000..81c6ca5b132
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_animation_with_timestamp-ref.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, class object animation with timestamp, ::cue(c:past) selector</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+}
+.green {
+ color: #80ff80;
+ font-weight: bold;
+}
+</style>
+<div class="video"><span class="cue"><span><span class="green">This is a test subtitle</span></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_animation_with_timestamp.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_animation_with_timestamp.html
new file mode 100644
index 00000000000..896dc711297
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_animation_with_timestamp.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, class object animation with timestamp, ::cue(c:past) selector</title>
+<link rel="match" href="class_animation_with_timestamp-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(c:past) {
+ -o-animation: test 9s steps(2, start);
+ animation: test 9s steps(2, start);
+}
+@-o-keyframes test {
+ 0% {
+ color: #ffffff;
+ }
+ 100% {
+ color: #00ff00;
+ }
+}
+@keyframes test {
+ 0% {
+ color: #ffffff;
+ }
+ 100% {
+ color: #00ff00;
+ }
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; takeScreenshotDelayed(200);">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/class_with_timestamp.vtt">
+</video>
+<script>
+document.getElementsByTagName('track')[0].track.mode = 'showing';
+</script>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_background_properties-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_background_properties-ref.html
new file mode 100644
index 00000000000..703daabd7f2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_background_properties-ref.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(c), background properties</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ font-size: 36px;
+ background: rgba(0,0,0,0.8);
+ color: white;
+}
+.cue > span > span {
+ background: #0f0 url('../../../media/background.gif') repeat-x top left;
+ color: #000;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <span>test subtitle</span></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_background_properties.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_background_properties.html
new file mode 100644
index 00000000000..765b01f65c0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_background_properties.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(c), background properties</title>
+<link rel="match" href="class_background_properties-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(c) {
+ font-family: sans-serif;
+ background-color: #0f0;
+ background-image: url('../../../media/background.gif');
+ background-repeat: repeat-x;
+ background-position: top left;
+ color: black;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_class.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_background_shorthand-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_background_shorthand-ref.html
new file mode 100644
index 00000000000..b66ec767b38
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_background_shorthand-ref.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(c), background shorthand</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ font-size: 36px;
+ background: rgba(0,0,0,0.8);
+ color: white;
+}
+.cue > span > span {
+ background: #0f0 url('../../../media/background.gif') repeat-x top left;
+ color: #000;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <span>test subtitle</span></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_background_shorthand.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_background_shorthand.html
new file mode 100644
index 00000000000..f57619c86ec
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_background_shorthand.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(c), background shorthand</title>
+<link rel="match" href="class_background_shorthand-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(c) {
+ font-family: sans-serif;
+ background: #0f0 url('../../../media/background.gif') repeat-x top left;
+ color: #000;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_class.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_color-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_color-ref.html
new file mode 100644
index 00000000000..e665021ebf6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_color-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(c), color: #0000ff</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+}
+.cue > span > span {
+ color: #0000ff;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <span>test subtitle</span></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_color.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_color.html
new file mode 100644
index 00000000000..0a609d1d94a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_color.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(c), color: #0000ff</title>
+<link rel="match" href="class_color-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(c) {
+ font-family: sans-serif;
+ color: #0000ff;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_class.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_font_properties-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_font_properties-ref.html
new file mode 100644
index 00000000000..2c6fec8f2af
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_font_properties-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(c), font properties</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ font-family: sans-serif;
+ font-size: 36px;
+ text-align: center
+}
+.cue > span {
+ background: rgba(0,0,0,0.8);
+ color: white;
+}
+.cue > span > span {
+ font: italic small-caps bold 36px/72px sans-serif;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <span>test subtitle</span></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_font_properties.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_font_properties.html
new file mode 100644
index 00000000000..42ae57e15d8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_font_properties.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(c), font properties</title>
+<link rel="match" href="class_font_properties-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(c) {
+ font-style: italic;
+ font-variant: small-caps;
+ font-weight: bold;
+ font-size: 36px;
+ line-height: 72px;
+ font-family: sans-serif;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_class.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_font_shorthand-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_font_shorthand-ref.html
new file mode 100644
index 00000000000..1ea755a3961
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_font_shorthand-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(c), font shorthand</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ font-family: sans-serif;
+ font-size: 36px;
+ text-align: center
+}
+.cue > span {
+ background: rgba(0,0,0,0.8);
+ color: white;
+}
+.cue > span > span {
+ font: normal small-caps bold 36px/72px sans-serif;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <span>test subtitle</span></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_font_shorthand.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_font_shorthand.html
new file mode 100644
index 00000000000..e4fd5735374
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_font_shorthand.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(c), font shorthand</title>
+<link rel="match" href="class_font_shorthand-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(c) {
+ font: normal small-caps bold 36px/72px sans-serif;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_class.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_namespace-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_namespace-ref.html
new file mode 100644
index 00000000000..3ca6dfd85d4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_namespace-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(|c) should match</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: green;
+ font-size: 36px
+}
+.green {
+ color: green;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <span class="green">test subtitle</span></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_namespace.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_namespace.html
new file mode 100644
index 00000000000..474a54d0a25
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_namespace.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(|c) should match</title>
+<link rel="match" href="class_namespace-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ color: green;
+ font-family: Ahem, sans-serif
+}
+::cue(*|c) {
+ color: red
+}
+::cue(|c) {
+ color: green
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_class.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_outline_properties-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_outline_properties-ref.html
new file mode 100644
index 00000000000..03841412514
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_outline_properties-ref.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(c), outline properties</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+}
+.cue > span > span {
+ display: inline-block;
+ margin-left: -2px;
+ margin-right: -2px;
+ border: solid #00f 2px;
+ border-bottom: none;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <span>test subtitle</span></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_outline_properties.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_outline_properties.html
new file mode 100644
index 00000000000..de7abf8b253
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_outline_properties.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(c), outline properties</title>
+<link rel="match" href="class_outline_properties-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(c) {
+ font-family: sans-serif;
+ outline-style: solid;
+ outline-color: #00f;
+ outline-width: 2px;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_class.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_outline_shorthand-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_outline_shorthand-ref.html
new file mode 100644
index 00000000000..fa6bdb61cae
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_outline_shorthand-ref.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(c), outline shorthand</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+}
+.cue > span > span {
+ display: inline-block;
+ margin-left: -2px;
+ margin-right: -2px;
+ border: solid #00f 2px;
+ border-bottom: none;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <span>test subtitle</span></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_outline_shorthand.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_outline_shorthand.html
new file mode 100644
index 00000000000..c0dab359459
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_outline_shorthand.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(c), outline shorthand</title>
+<link rel="match" href="class_outline_shorthand-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(c) {
+ font-family: sans-serif;
+ outline: solid #00f 2px;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_class.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_text-decoration_line-through-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_text-decoration_line-through-ref.html
new file mode 100644
index 00000000000..ceec8b8c537
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_text-decoration_line-through-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(c), text-decoration: line-through</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+}
+.cue > span > span {
+ text-decoration: line-through;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <span>test subtitle</span></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_text-decoration_line-through.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_text-decoration_line-through.html
new file mode 100644
index 00000000000..72bb88582ba
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_text-decoration_line-through.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(c), text-decoration: line-through</title>
+<link rel="match" href="class_text-decoration_line-through-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(c) {
+ font-family: sans-serif;
+ text-decoration: line-through;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_class.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_text-shadow-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_text-shadow-ref.html
new file mode 100644
index 00000000000..cfd46836863
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_text-shadow-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(c), text-shadow</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+}
+.cue > span > span {
+ text-shadow: 0px 0px 5px #0f0;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <span>test subtitle</span></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_text-shadow.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_text-shadow.html
new file mode 100644
index 00000000000..07a1ed66954
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_text-shadow.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(c), text-shadow</title>
+<link rel="match" href="class_text-shadow-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(c) {
+ font-family: sans-serif;
+ text-shadow: 0px 0px 5px #0f0;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_class.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_timestamp_future-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_timestamp_future-ref.html
new file mode 100644
index 00000000000..5333596fe5a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_timestamp_future-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, class object transition with timestamp, ::cue(c:future) selector</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+}
+.green {
+ color: #00ff00;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <span class="green">test subtitle</span></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_timestamp_future.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_timestamp_future.html
new file mode 100644
index 00000000000..c1939ff6db0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_timestamp_future.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, class object transition with timestamp, ::cue(c:future) selector</title>
+<link rel="match" href="class_timestamp_future-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(c:future) {
+ color: #00ff00;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; takeScreenshotDelayed(200);">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/class_with_2_timestamps.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_timestamp_past-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_timestamp_past-ref.html
new file mode 100644
index 00000000000..5f45ee729a0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_timestamp_past-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, class object transition with timestamp, ::cue(c:past) selector</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+}
+.green {
+ color: #00ff00;
+}
+</style>
+<div class="video"><span class="cue"><span><span class="green">This is a test subtitle</span></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_timestamp_past.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_timestamp_past.html
new file mode 100644
index 00000000000..6f80b4e00e6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_timestamp_past.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, class object transition with timestamp, ::cue(c:past) selector</title>
+<link rel="match" href="class_timestamp_past-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(c:past) {
+ color: #00ff00;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; takeScreenshotDelayed(200);">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/class_with_timestamp.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_transition_with_timestamp-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_transition_with_timestamp-ref.html
new file mode 100644
index 00000000000..4a53043a14f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_transition_with_timestamp-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, class object transition with timestamp, ::cue(c:past) selector</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+}
+.green {
+ color: #80ff80;
+}
+</style>
+<div class="video"><span class="cue"><span><span class="green">This is a test subtitle</span></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_transition_with_timestamp.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_transition_with_timestamp.html
new file mode 100644
index 00000000000..10f7da72196
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_transition_with_timestamp.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, class object transition with timestamp, ::cue(c:past) selector</title>
+<link rel="match" href="class_transition_with_timestamp-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(c) {
+ -o-transition: color 9s steps(2, start);
+ transition: color 9s steps(2, start);
+}
+::cue(c:past) {
+ color: #00ff00;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; takeScreenshotDelayed(200);">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/class_with_timestamp.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_normal_wrapped-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_normal_wrapped-ref.html
new file mode 100644
index 00000000000..7cd630d7add
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_normal_wrapped-ref.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, class object, ::cue(c), white-space: normal (cue that wraps)</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ font-size: 36px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 25%;
+ right: 0;
+ width: 50%;
+ text-align: center;
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: white;
+ white-space: normal
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle that most likely will span over several rows since it's a pretty long cue with a lot of text.</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_normal_wrapped.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_normal_wrapped.html
new file mode 100644
index 00000000000..9213a4db3da
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_normal_wrapped.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, class object, ::cue(c), white-space: normal (cue that wraps)</title>
+<link rel="match" href="class_white-space_normal_wrapped-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(c) {
+ white-space: normal
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/class_long.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_nowrap-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_nowrap-ref.html
new file mode 100644
index 00000000000..640a88985ce
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_nowrap-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, class object, ::cue(c), white-space: nowrap (cue does not wrap)</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ font-size: 36px;
+ position: relative;
+ overflow: hidden;
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 25%;
+ right: 0;
+ width: 50%;
+ text-align: center;
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: white;
+ white-space: nowrap
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle that most likely will span over several rows since it's a pretty long cue with a lot of text.</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_nowrap.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_nowrap.html
new file mode 100644
index 00000000000..27e5d8a9311
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_nowrap.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, class object, ::cue(c), white-space: nowrap (cue does not wrap)</title>
+<link rel="match" href="class_white-space_nowrap-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(c) {
+ white-space: nowrap
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/class_long.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_pre-line_wrapped-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_pre-line_wrapped-ref.html
new file mode 100644
index 00000000000..2c9a49d22be
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_pre-line_wrapped-ref.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, class object, ::cue(c), white-space: pre-line (cue that wraps)</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ font-size: 36px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 25%;
+ right: 0;
+ width: 50%;
+ text-align: center;
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: white;
+ white-space: pre-line
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle that most likely will span over several rows since it's a pretty long cue with a lot of text.</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_pre-line_wrapped.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_pre-line_wrapped.html
new file mode 100644
index 00000000000..3b5045c0bf5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_pre-line_wrapped.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, class object, ::cue(c), white-space: pre-line (cue that wraps)</title>
+<link rel="match" href="class_white-space_pre-line_wrapped-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(c) {
+ white-space: pre-line
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/class_long.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_pre-wrap_wrapped-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_pre-wrap_wrapped-ref.html
new file mode 100644
index 00000000000..da4db854fc0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_pre-wrap_wrapped-ref.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, class object, ::cue(c), white-space: pre-wrap (cue that wraps)</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ font-size: 36px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 25%;
+ right: 0;
+ width: 50%;
+ text-align: center;
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: white;
+ white-space: pre-wrap
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle that most likely will span over several rows since it's a pretty long cue with a lot of text.</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_pre-wrap_wrapped.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_pre-wrap_wrapped.html
new file mode 100644
index 00000000000..a269ca1bc62
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_pre-wrap_wrapped.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, class object, ::cue(c), white-space: pre-wrap (cue that wraps)</title>
+<link rel="match" href="class_white-space_pre-wrap_wrapped-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(c) {
+ white-space: pre-wrap
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/class_long.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_pre_wrapped-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_pre_wrapped-ref.html
new file mode 100644
index 00000000000..03852d9b462
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_pre_wrapped-ref.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, class object, ::cue(c), white-space: pre (cue that wraps)</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ font-size: 36px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 25%;
+ right: 0;
+ width: 50%;
+ text-align: center;
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: white;
+ white-space: pre
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle that most <br>likely will span over several <br>rows since it's a pretty long cue <br>with a lot of text.</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_pre_wrapped.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_pre_wrapped.html
new file mode 100644
index 00000000000..418ea448f1f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_pre_wrapped.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, class object, ::cue(c), white-space: pre (cue that wraps)</title>
+<link rel="match" href="class_white-space_pre_wrapped-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(c) {
+ white-space: pre
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/class_long.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_with_class-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_with_class-ref.html
new file mode 100644
index 00000000000..343fccc9209
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_with_class-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, class object with class, ::cue(.foo) selector</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+}
+.green {
+ color: #00ff00;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <span>test subtitle</span>, <span class="green">test subtitle</span></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_with_class.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_with_class.html
new file mode 100644
index 00000000000..622edca4c3f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_with_class.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, class object with class, ::cue(.foo) selector</title>
+<link rel="match" href="class_with_class-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(.foo) {
+ font-family: sans-serif;
+ color: #00ff00;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_class_with_class.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_with_class_object_specific_selector-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_with_class_object_specific_selector-ref.html
new file mode 100644
index 00000000000..01081e9823d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_with_class_object_specific_selector-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, class object with class, ::cue(c.foo) selector</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+}
+.green {
+ color: #00ff00;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <span>test subtitle</span>, <span class="green">test subtitle</span></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_with_class_object_specific_selector.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_with_class_object_specific_selector.html
new file mode 100644
index 00000000000..682be9071fa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_with_class_object_specific_selector.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, class object with class, ::cue(c.foo) selector</title>
+<link rel="match" href="class_with_class_object_specific_selector-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(c.foo) {
+ font-family: sans-serif;
+ color: #00ff00;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_class_with_class.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/color_hex-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/color_hex-ref.html
new file mode 100644
index 00000000000..5a0a0b1209c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/color_hex-ref.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(), color: #60ff60</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: #60ff60;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/color_hex.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/color_hex.html
new file mode 100644
index 00000000000..42eaf66f775
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/color_hex.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(), color: #60ff60</title>
+<link rel="match" href="color_hex-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(*) {
+ font-family: Ahem, sans-serif;
+ color: #60ff60;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/test.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/color_hsla-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/color_hsla-ref.html
new file mode 100644
index 00000000000..15c19e96d54
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/color_hsla-ref.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(), color: hsla()</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: hsla(100,100%,50%,0.5);
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/color_hsla.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/color_hsla.html
new file mode 100644
index 00000000000..7dadd55da01
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/color_hsla.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(), color: hsla()</title>
+<link rel="match" href="color_hsla-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(*) {
+ font-family: Ahem, sans-serif;
+ color: hsla(100,100%,50%,0.5);
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/test.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/color_rgba-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/color_rgba-ref.html
new file mode 100644
index 00000000000..87004f8e2dd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/color_rgba-ref.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(), color: rgba()</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: rgba(128,255,128,0.5);
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/color_rgba.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/color_rgba.html
new file mode 100644
index 00000000000..cd8ed2f14a0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/color_rgba.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(), color: rgba()</title>
+<link rel="match" href="color_rgba-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(*) {
+ font-family: Ahem, sans-serif;
+ color: rgba(128,255,128,0.5);
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/test.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/cue_func_selector_single_colon-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/cue_func_selector_single_colon-ref.html
new file mode 100644
index 00000000000..bc541fba65d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/cue_func_selector_single_colon-ref.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, :cue()</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 25%;
+ right: 0;
+ width: 50%;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: white;
+ font-size: 36px;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/cue_func_selector_single_colon.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/cue_func_selector_single_colon.html
new file mode 100644
index 00000000000..4ab2d9a59c7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/cue_func_selector_single_colon.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, :cue()</title>
+<link rel="match" href="cue_func_selector_single_colon-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+:cue(*) {
+ background: red;
+ color: yellow
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/test.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/font_properties-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/font_properties-ref.html
new file mode 100644
index 00000000000..41be87acac3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/font_properties-ref.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(), font properties</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ font: italic small-caps bold 36px/72px sans-serif;
+ text-align: center
+}
+.cue > span {
+ background: rgba(0,0,0,0.8);
+ color: white;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle that most likely will span over several rows since it's a pretty long cue with a lot of text.</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/font_properties.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/font_properties.html
new file mode 100644
index 00000000000..e9d1ef81624
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/font_properties.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(), font properties</title>
+<link rel="match" href="font_properties-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(*) {
+ font-style: italic;
+ font-variant: small-caps;
+ font-weight: bold;
+ font-size: 36px;
+ line-height: 72px;
+ font-family: sans-serif;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/test_long.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/font_shorthand-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/font_shorthand-ref.html
new file mode 100644
index 00000000000..341079b14cf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/font_shorthand-ref.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(), font shorthand</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ font: italic small-caps bold 36px/72px sans-serif;
+ text-align: center
+}
+.cue > span {
+ background: rgba(0,0,0,0.8);
+ color: white;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle that most likely will span over several rows since it's a pretty long cue with a lot of text.</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/font_shorthand.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/font_shorthand.html
new file mode 100644
index 00000000000..d711f54d0e3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/font_shorthand.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(), font shorthand</title>
+<link rel="match" href="font_shorthand-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(*) {
+ font: italic small-caps bold 36px/72px sans-serif;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/test_long.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/id_color-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/id_color-ref.html
new file mode 100644
index 00000000000..5effb11d953
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/id_color-ref.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, cue with ID, ::cue(#foo) selector</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: #00ff00;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/id_color.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/id_color.html
new file mode 100644
index 00000000000..85ffff6de4f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/id_color.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, cue with ID, ::cue(#foo) selector</title>
+<link rel="match" href="id_color-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(#foo) {
+ font-family: Ahem, sans-serif;
+ color: #00ff00;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/cue_with_id.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/inherit_values_from_media_element-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/inherit_values_from_media_element-ref.html
new file mode 100644
index 00000000000..ba554e2b0ec
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/inherit_values_from_media_element-ref.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(*), css properties with value inherit should inherit from media element</title>
+<style>
+.video {
+ position: absolute;
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative;
+ color: #f0f;
+ white-space: pre-wrap;
+ font: italic small-caps bold 36px/72px sans-serif;
+ text-decoration: overline underline line-through;
+ text-shadow: 0px 0px 5px #0f0;
+ background: #0f0 url('../../media/background.gif') repeat-x top left;
+ outline: solid #00f 2px;
+}
+.videoWhite {
+ position: absolute;
+ top: 0;
+ left: 160px;
+ width: 960px;
+ height: 720px;;
+ background: #fff;
+ z-index: 1;
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 30%;
+ right: 0;
+ width: 40%;
+ text-align: center;
+ outline: inherit;
+ text-shadow: inherit;
+ text-decoration: inherit;
+ outline-bottom: none;
+ z-index: 2
+}
+.cue > span {
+ background: #0f0 url('../../media/background.gif') repeat-x top left;
+ text-decoration: inherit;
+ white-space: pre-wrap
+}
+</style>
+<div class="video"><div class="videoWhite"></div><span class="cue"><span>A A A A A A A A A A A</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/inherit_values_from_media_element.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/inherit_values_from_media_element.html
new file mode 100644
index 00000000000..a3be846a0ec
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/inherit_values_from_media_element.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(*), css properties with value inherit should inherit from media element</title>
+<link rel="match" href="inherit_values_from_media_element-ref.html">
+<style>
+video {
+ color: #f0f;
+ white-space: pre-wrap;
+ font: italic small-caps bold 36px/72px sans-serif;
+ text-decoration: overline underline line-through;
+ text-shadow: 0px 0px 5px #0f0;
+ background: #0f0 url('../../media/background.gif') repeat-x top left;
+ outline: solid #00f 2px;
+}
+::cue(*) {
+ white-space: inherit;
+ font: inherit;
+ color: inherit;
+ text-decoration: inherit;
+ text-shadow: inherit;
+ background: inherit;
+ outline: inherit;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/white-spaces_long.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_animation_with_timestamp-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_animation_with_timestamp-ref.html
new file mode 100644
index 00000000000..8567adbe8eb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_animation_with_timestamp-ref.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, italic object animation with timestamp, ::cue(i:past) selector</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+}
+.green {
+ color: #80ff80;
+ font-weight: bold;
+}
+</style>
+<div class="video"><span class="cue"><span><span class="green">This is a test subtitle</span></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_animation_with_timestamp.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_animation_with_timestamp.html
new file mode 100644
index 00000000000..2b32ff83476
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_animation_with_timestamp.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, italic object animation with timestamp, ::cue(i:past) selector</title>
+<link rel="match" href="italic_animation_with_timestamp-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(i:past) {
+ -o-animation: test 9s steps(2, start);
+ animation: test 9s steps(2, start);
+}
+@-o-keyframes test {
+ 0% {
+ color: #ffffff;
+ }
+ 100% {
+ color: #00ff00;
+ }
+}
+@keyframes test {
+ 0% {
+ color: #ffffff;
+ }
+ 100% {
+ color: #00ff00;
+ }
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; takeScreenshotDelayed(200);">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/italic_with_timestamp.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_background_properties-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_background_properties-ref.html
new file mode 100644
index 00000000000..6cd53d42aad
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_background_properties-ref.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(i), background properties</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ font-size: 36px;
+ background: rgba(0,0,0,0.8);
+ color: white;
+}
+.cue > span > i {
+ background: #0f0 url('../../../media/background.gif') repeat-x top left;
+ color: #000;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <i>test subtitle</i></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_background_properties.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_background_properties.html
new file mode 100644
index 00000000000..a9ceca7b1b4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_background_properties.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(i), background properties</title>
+<link rel="match" href="italic_background_properties-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(i) {
+ font-family: sans-serif;
+ background-color: #0f0;
+ background-image: url('../../../media/background.gif');
+ background-repeat: repeat-x;
+ background-position: top left;
+ color: black;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_italic.vtt">
+</video>
+<script>
+document.getElementsByTagName('track')[0].track.mode = 'showing';
+</script>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_background_shorthand-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_background_shorthand-ref.html
new file mode 100644
index 00000000000..d4d94a6ed49
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_background_shorthand-ref.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(i), background shorthand</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ font-size: 36px;
+ background: rgba(0,0,0,0.8);
+ color: white;
+}
+.cue > span > i {
+ background: #0f0 url('../../../media/background.gif') repeat-x top left;
+ color: #000;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <i>test subtitle</i></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_background_shorthand.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_background_shorthand.html
new file mode 100644
index 00000000000..b7d98e2f86a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_background_shorthand.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(i), background shorthand</title>
+<link rel="match" href="italic_background_shorthand-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(i) {
+ font-family: sans-serif;
+ background: #0f0 url('../../../media/background.gif') repeat-x top left;
+ color: #000;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_italic.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_color-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_color-ref.html
new file mode 100644
index 00000000000..f7b60d70d68
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_color-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(i), color: #0000ff</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+}
+.cue > span > i {
+ color: #0000ff;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <i>test subtitle</i></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_color.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_color.html
new file mode 100644
index 00000000000..c7e888236ec
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_color.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(i), color: #0000ff</title>
+<link rel="match" href="italic_color-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(i) {
+ font-family: sans-serif;
+ color: #0000ff;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_italic.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_font_properties-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_font_properties-ref.html
new file mode 100644
index 00000000000..c02042f2313
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_font_properties-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(i), font properties</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ font-family: sans-serif;
+ font-size: 36px;
+ text-align: center
+}
+.cue > span {
+ background: rgba(0,0,0,0.8);
+ color: white;
+}
+.cue > span > i {
+ font: italic small-caps bold 36px/72px sans-serif;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <i>test subtitle</i></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_font_properties.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_font_properties.html
new file mode 100644
index 00000000000..5fb925097c7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_font_properties.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(i), font properties</title>
+<link rel="match" href="italic_font_properties-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(i) {
+ font-style: italic;
+ font-variant: small-caps;
+ font-weight: bold;
+ font-size: 36px;
+ line-height: 72px;
+ font-family: sans-serif;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_italic.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_font_shorthand-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_font_shorthand-ref.html
new file mode 100644
index 00000000000..f00ee6087c1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_font_shorthand-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(i), font shorthand</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ font-family: sans-serif;
+ font-size: 36px;
+ text-align: center
+}
+.cue > span {
+ background: rgba(0,0,0,0.8);
+ color: white;
+}
+.cue > span > i {
+ font: normal small-caps bold 36px/72px sans-serif;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <i>test subtitle</i></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_font_shorthand.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_font_shorthand.html
new file mode 100644
index 00000000000..21effa113fe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_font_shorthand.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(i), font shorthand</title>
+<link rel="match" href="italic_font_shorthand-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(i) {
+ font: normal small-caps bold 36px/72px sans-serif;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_italic.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_namespace-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_namespace-ref.html
new file mode 100644
index 00000000000..6bad23b43c4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_namespace-ref.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(|i) should match</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: green;
+ font-size: 36px
+}
+.green {
+ font-style: italic;
+ color: green;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <span class="green">test subtitle</span></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_namespace.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_namespace.html
new file mode 100644
index 00000000000..0f51c5c18f9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_namespace.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(|i) should match</title>
+<link rel="match" href="italic_namespace-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ color: green;
+}
+::cue(*|i) {
+ color: red
+}
+::cue(|i) {
+ color: green
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_italic.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_outline_properties-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_outline_properties-ref.html
new file mode 100644
index 00000000000..849d6e756a1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_outline_properties-ref.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(i), outline properties</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+}
+.cue > span > i {
+ display: inline-block;
+ margin-left: -2px;
+ margin-right: -2px;
+ border: solid #00f 2px;
+ border-bottom: none;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <i>test subtitle</i></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_outline_properties.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_outline_properties.html
new file mode 100644
index 00000000000..e83daeb6d4f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_outline_properties.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(i), outline properties</title>
+<link rel="match" href="italic_outline_properties-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(i) {
+ font-family: sans-serif;
+ outline-style: solid;
+ outline-color: #00f;
+ outline-width: 2px;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_italic.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_outline_shorthand-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_outline_shorthand-ref.html
new file mode 100644
index 00000000000..218eb009f43
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_outline_shorthand-ref.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(i), outline shorthand</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+}
+.cue > span > i {
+ display: inline-block;
+ margin-left: -2px;
+ margin-right: -2px;
+ border: solid #00f 2px;
+ border-bottom: none;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <i>test subtitle</i></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_outline_shorthand.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_outline_shorthand.html
new file mode 100644
index 00000000000..cbceba8ba69
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_outline_shorthand.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(i), outline shorthand</title>
+<link rel="match" href="italic_outline_shorthand-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(i) {
+ font-family: sans-serif;
+ outline: solid #00f 2px;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_italic.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_text-decoration_line-through-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_text-decoration_line-through-ref.html
new file mode 100644
index 00000000000..c1de8d04abc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_text-decoration_line-through-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(i), text-decoration: line-through</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+}
+.cue > span > i {
+ text-decoration: line-through;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <i>test subtitle</i></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_text-decoration_line-through.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_text-decoration_line-through.html
new file mode 100644
index 00000000000..dd1212ada29
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_text-decoration_line-through.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(i), text-decoration: line-through</title>
+<link rel="match" href="italic_text-decoration_line-through-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(i) {
+ font-family: sans-serif;
+ text-decoration: line-through;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_italic.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_text-shadow-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_text-shadow-ref.html
new file mode 100644
index 00000000000..a20a8eba626
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_text-shadow-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(i), text-shadow</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+}
+.cue > span > i {
+ text-shadow: 0px 0px 5px #0f0;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <i>test subtitle</i></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_text-shadow.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_text-shadow.html
new file mode 100644
index 00000000000..41582bb0623
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_text-shadow.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(i), text-shadow</title>
+<link rel="match" href="italic_text-shadow-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(i) {
+ font-family: sans-serif;
+ text-shadow: 0px 0px 5px #0f0;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_italic.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_timestamp_future-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_timestamp_future-ref.html
new file mode 100644
index 00000000000..17f7709d29f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_timestamp_future-ref.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, italic object transition with timestamp, ::cue(i:future) selector</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ font-style: italic;
+ color: white;
+}
+.green {
+ color: #00ff00;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <span class="green">test subtitle</span></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_timestamp_future.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_timestamp_future.html
new file mode 100644
index 00000000000..83308816dd6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_timestamp_future.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, italic object transition with timestamp, ::cue(i:future) selector</title>
+<link rel="match" href="italic_timestamp_future-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(i:future) {
+ color: #00ff00;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; takeScreenshotDelayed(200);">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/italic_with_2_timestamps.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_timestamp_past-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_timestamp_past-ref.html
new file mode 100644
index 00000000000..6b02c72b5d5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_timestamp_past-ref.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, italic object transition with timestamp, ::cue(i:past) selector</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ font-style: italic;
+ color: white;
+}
+.green {
+ color: #00ff00;
+}
+</style>
+<div class="video"><span class="cue"><span><span class="green">This is a test subtitle</span></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_timestamp_past.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_timestamp_past.html
new file mode 100644
index 00000000000..294b642e538
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_timestamp_past.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, italic object transition with timestamp, ::cue(i:past) selector</title>
+<link rel="match" href="italic_timestamp_past-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(i:past) {
+ color: #00ff00;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; takeScreenshotDelayed(200);">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/italic_with_timestamp.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_transition_with_timestamp-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_transition_with_timestamp-ref.html
new file mode 100644
index 00000000000..9bca41113f2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_transition_with_timestamp-ref.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, italic object transition with timestamp, ::cue(i:past) selector</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+}
+.green {
+ color: #80ff80;
+ font-style: italic;
+}
+</style>
+<div class="video"><span class="cue"><span><span class="green">This is a test subtitle</span></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_transition_with_timestamp.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_transition_with_timestamp.html
new file mode 100644
index 00000000000..a6028a367c8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_transition_with_timestamp.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, italic object transition with timestamp, ::cue(i:past) selector</title>
+<link rel="match" href="italic_transition_with_timestamp-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(i) {
+ -o-transition: color 9s steps(2, start);
+ transition: color 9s steps(2, start);
+}
+::cue(i:past) {
+ color: #00ff00;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; takeScreenshotDelayed(200);">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/italic_with_timestamp.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_normal_wrapped-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_normal_wrapped-ref.html
new file mode 100644
index 00000000000..a765d9f76ef
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_normal_wrapped-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, italic object, ::cue(i), white-space: normal (cue that wraps)</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ font-size: 36px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 25%;
+ right: 0;
+ width: 50%;
+ text-align: center;
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: white;
+ font-style: italic;
+ white-space: normal
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle that most likely will span over several rows since it's a pretty long cue with a lot of text.</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_normal_wrapped.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_normal_wrapped.html
new file mode 100644
index 00000000000..251cf9c0637
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_normal_wrapped.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, italic object, ::cue(i), white-space: normal (cue that wraps)</title>
+<link rel="match" href="italic_white-space_normal_wrapped-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(i) {
+ white-space: normal
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/italic_long.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_nowrap-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_nowrap-ref.html
new file mode 100644
index 00000000000..ee0bd0230bf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_nowrap-ref.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, italic object, ::cue(i), white-space: nowrap (cue does not wrap)</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ font-size: 36px;
+ position: relative;
+ overflow: hidden;
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 25%;
+ right: 0;
+ width: 50%;
+ text-align: center;
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: white;
+ font-style: italic;
+ white-space: nowrap
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle that most likely will span over several rows since it's a pretty long cue with a lot of text.</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_nowrap.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_nowrap.html
new file mode 100644
index 00000000000..4fabbdbbfa8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_nowrap.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, italic object, ::cue(i), white-space: nowrap (cue does not wrap)</title>
+<link rel="match" href="italic_white-space_nowrap-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(i) {
+ white-space: nowrap
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/italic_long.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_pre-line_wrapped-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_pre-line_wrapped-ref.html
new file mode 100644
index 00000000000..d0177e3429c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_pre-line_wrapped-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, italic object, ::cue(i), white-space: pre-line (cue that wraps)</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ font-size: 36px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 25%;
+ right: 0;
+ width: 50%;
+ text-align: center;
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: white;
+ font-style: italic;
+ white-space: pre-line
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle that most likely will span over several rows since it's a pretty long cue with a lot of text.</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_pre-line_wrapped.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_pre-line_wrapped.html
new file mode 100644
index 00000000000..c0dc1ec169c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_pre-line_wrapped.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, italic object, ::cue(i), white-space: pre-line (cue that wraps)</title>
+<link rel="match" href="italic_white-space_pre-line_wrapped-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(i) {
+ white-space: pre-line
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/italic_long.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_pre-wrap_wrapped-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_pre-wrap_wrapped-ref.html
new file mode 100644
index 00000000000..1dfdb7b0335
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_pre-wrap_wrapped-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, italic object, ::cue(i), white-space: pre-wrap (cue that wraps)</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ font-size: 36px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 25%;
+ right: 0;
+ width: 50%;
+ text-align: center;
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: white;
+ font-style: italic;
+ white-space: pre-wrap
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle that most likely will span over several rows since it's a pretty long cue with a lot of text.</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_pre-wrap_wrapped.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_pre-wrap_wrapped.html
new file mode 100644
index 00000000000..1f88ec6c766
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_pre-wrap_wrapped.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, italic object, ::cue(i), white-space: pre-wrap (cue that wraps)</title>
+<link rel="match" href="italic_white-space_pre-wrap_wrapped-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(i) {
+ white-space: pre-wrap
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/italic_long.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_pre_wrapped-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_pre_wrapped-ref.html
new file mode 100644
index 00000000000..2734b323f1e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_pre_wrapped-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, italic object, ::cue(i), white-space: pre (cue that wraps)</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ font-size: 36px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 25%;
+ right: 0;
+ width: 50%;
+ text-align: center;
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: white;
+ font-style: italic;
+ white-space: pre
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle that most <br>likely will span over several <br>rows since it's a pretty long cue <br>with a lot of text.</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_pre_wrapped.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_pre_wrapped.html
new file mode 100644
index 00000000000..308571d4c5a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_pre_wrapped.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, italic object, ::cue(i), white-space: pre (cue that wraps)</title>
+<link rel="match" href="italic_white-space_pre_wrapped-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(i) {
+ white-space: pre
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/italic_long.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_with_class-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_with_class-ref.html
new file mode 100644
index 00000000000..658c2008303
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_with_class-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, italic object with class, ::cue(.foo) selector</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+}
+.green {
+ color: #00ff00;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <i>test subtitle</i>, <i class="green">test subtitle</i></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_with_class.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_with_class.html
new file mode 100644
index 00000000000..b3ac8c703c7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_with_class.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, italic object with class, ::cue(.foo) selector</title>
+<link rel="match" href="italic_with_class-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(.foo) {
+ font-family: sans-serif;
+ color: #00ff00;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_italic_with_class.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_with_class_object_specific_selector-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_with_class_object_specific_selector-ref.html
new file mode 100644
index 00000000000..ed73e774ba4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_with_class_object_specific_selector-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, italic object with class, ::cue(i.foo) selector</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+}
+.green {
+ color: #00ff00;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <i>test subtitle</i>, <i class="green">test subtitle</i></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_with_class_object_specific_selector.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_with_class_object_specific_selector.html
new file mode 100644
index 00000000000..9f62a627f14
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_with_class_object_specific_selector.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, italic object with class, ::cue(i.foo) selector</title>
+<link rel="match" href="italic_with_class_object_specific_selector-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(i.foo) {
+ font-family: sans-serif;
+ color: #00ff00;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_italic_with_class.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/not_allowed_properties-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/not_allowed_properties-ref.html
new file mode 100644
index 00000000000..c3fcae2cc4d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/not_allowed_properties-ref.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(), properties that should not affect the cue</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/not_allowed_properties.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/not_allowed_properties.html
new file mode 100644
index 00000000000..f105b016baa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/not_allowed_properties.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(), properties that should not affect the cue</title>
+<link rel="match" href="not_allowed_properties-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(*) {
+ border: 2px solid red;
+ border-radius: 5px;
+ bottom: 300px;
+ box-shadow: 5px 5px 5px 5px #123456;
+ box-sizing: border-box;
+ clip: rect(0px, 5px, 0px, 5px);
+ columns: 100px 2;
+ content: 'hello!';
+ display: inline-block;
+ float: left;
+ font-family: sans-serif;
+ height: 90px;
+ left: -150px;
+ letter-spacing: 20px;
+ margin: 20px;
+ min-height: 100px;
+ min-width: 100px;
+ opacity: 0.2;
+ overflow: scroll;
+ padding: 20px;
+ position: absolute;
+ right: 200px;
+ text-align: left;
+ text-indent: 50px;
+ top: -50px;
+ width: 140px;
+ word-spacing: 50px;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/test.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/not_root_selector-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/not_root_selector-ref.html
new file mode 100644
index 00000000000..fd7ce73f8d8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/not_root_selector-ref.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(:not(:root)) should not match the root</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 25%;
+ right: 0;
+ width: 50%;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: white;
+ font-size: 36px;
+}
+.cue > span > span {
+ color: lime
+}
+</style>
+<div class="video"><span class="cue"><span>Foo<span>bar</span></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/not_root_selector.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/not_root_selector.html
new file mode 100644
index 00000000000..94d44369050
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/not_root_selector.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(:not(:root)) should not match the root</title>
+<link rel="match" href="not_root_selector-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(:not(:root)) {
+ color:lime
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/foo_c_bar.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/outline_properties-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/outline_properties-ref.html
new file mode 100644
index 00000000000..4fe5d753b86
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/outline_properties-ref.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(), outline properties</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ outline: solid #00f 2px;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: green;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/outline_properties.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/outline_properties.html
new file mode 100644
index 00000000000..5684f17acf1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/outline_properties.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(), outline properties</title>
+<link rel="match" href="outline_properties-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(*) {
+ font-family: Ahem, sans-serif;
+ outline-style: solid;
+ outline-color: #00f;
+ outline-width: 2px;
+ color: green;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/test.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/outline_shorthand-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/outline_shorthand-ref.html
new file mode 100644
index 00000000000..4b4dcd92a72
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/outline_shorthand-ref.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(), outline shorthand</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ outline: solid #00f 2px;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: green;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/outline_shorthand.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/outline_shorthand.html
new file mode 100644
index 00000000000..40a856aac45
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/outline_shorthand.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(), outline shorthand</title>
+<link rel="match" href="outline_shorthand-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(*) {
+ font-family: Ahem, sans-serif;
+ outline: solid #00f 2px;
+ color: green;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/test.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/root_namespace-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/root_namespace-ref.html
new file mode 100644
index 00000000000..3e882f844ce
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/root_namespace-ref.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(|*) should match the root</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: green;
+ font-size: 36px
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/root_namespace.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/root_namespace.html
new file mode 100644
index 00000000000..41198683b74
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/root_namespace.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(|*) should match the root</title>
+<link rel="match" href="root_namespace-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family: Ahem, sans-serif
+}
+::cue(*|*) {
+ color: red
+}
+::cue(|*) {
+ color: green
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/test.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/root_selector-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/root_selector-ref.html
new file mode 100644
index 00000000000..7216054ccb1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/root_selector-ref.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(:root) should match the root</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 25%;
+ right: 0;
+ width: 50%;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: lime;
+ font-size: 36px;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/root_selector.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/root_selector.html
new file mode 100644
index 00000000000..e5cda77b25a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/root_selector.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(:root) should match the root</title>
+<link rel="match" href="root_selector-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(:root) {
+ color:lime
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/test.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-decoration_line-through-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-decoration_line-through-ref.html
new file mode 100644
index 00000000000..8bf1dd4253d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-decoration_line-through-ref.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(), text-decoration: line-through</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+ text-decoration: line-through;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-decoration_line-through.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-decoration_line-through.html
new file mode 100644
index 00000000000..76f38f1d234
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-decoration_line-through.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(), text-decoration: line-through</title>
+<link rel="match" href="text-decoration_line-through-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(*) {
+ font-family: sans-serif;
+ text-decoration: line-through;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/test.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-decoration_overline-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-decoration_overline-ref.html
new file mode 100644
index 00000000000..351353b670a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-decoration_overline-ref.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(), text-decoration: overline</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+ text-decoration: overline;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-decoration_overline.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-decoration_overline.html
new file mode 100644
index 00000000000..8031b3dde73
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-decoration_overline.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(), text-decoration: overline</title>
+<link rel="match" href="text-decoration_overline-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(*) {
+ font-family: sans-serif;
+ text-decoration: overline;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/test.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-decoration_overline_underline_line-through-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-decoration_overline_underline_line-through-ref.html
new file mode 100644
index 00000000000..9a6017a7f6f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-decoration_overline_underline_line-through-ref.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(), text-decoration: overline underline line-through</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+ text-decoration: overline underline line-through;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-decoration_overline_underline_line-through.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-decoration_overline_underline_line-through.html
new file mode 100644
index 00000000000..191e1bcc29c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-decoration_overline_underline_line-through.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(), text-decoration: overline underline line-through</title>
+<link rel="match" href="text-decoration_overline_underline_line-through-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(*) {
+ font-family: sans-serif;
+ text-decoration: overline underline line-through;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/test.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-decoration_underline-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-decoration_underline-ref.html
new file mode 100644
index 00000000000..864a930f9b7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-decoration_underline-ref.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(), text-decoration: underline</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+ text-decoration: underline;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-decoration_underline.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-decoration_underline.html
new file mode 100644
index 00000000000..13e97614fb0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-decoration_underline.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(), text-decoration: underline</title>
+<link rel="match" href="text-decoration_underline-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(*) {
+ font-family: sans-serif;
+ text-decoration: underline;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/test.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-shadow-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-shadow-ref.html
new file mode 100644
index 00000000000..e3a591938c1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-shadow-ref.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(), text-shadow</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+ text-shadow: 0px 0px 5px #0f0;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-shadow.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-shadow.html
new file mode 100644
index 00000000000..dffde42ad1b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/text-shadow.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(), text-shadow</title>
+<link rel="match" href="text-shadow-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(*) {
+ font-family: sans-serif;
+ text-shadow: 0px 0px 5px #0f0;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/test.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/type_selector_root-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/type_selector_root-ref.html
new file mode 100644
index 00000000000..016b3c4bcd6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/type_selector_root-ref.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(root) should match nothing; the root element should have no name</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 25%;
+ right: 0;
+ width: 50%;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: white;
+ font-size: 36px;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/type_selector_root.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/type_selector_root.html
new file mode 100644
index 00000000000..5c54ed31096
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/type_selector_root.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(root) should match nothing; the root element should have no name</title>
+<link rel="match" href="type_selector_root-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(root) {
+ color:yellow;
+ background:red
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/test.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_animation_with_timestamp-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_animation_with_timestamp-ref.html
new file mode 100644
index 00000000000..7822dd6e712
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_animation_with_timestamp-ref.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, underline object animation with timestamp, ::cue(u:past) selector</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+}
+.green {
+ color: #80ff80;
+ font-weight: bold;
+}
+</style>
+<div class="video"><span class="cue"><span><span class="green">This is a test subtitle</span></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_animation_with_timestamp.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_animation_with_timestamp.html
new file mode 100644
index 00000000000..08602160183
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_animation_with_timestamp.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, underline object animation with timestamp, ::cue(u:past) selector</title>
+<link rel="match" href="underline_animation_with_timestamp-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(u:past) {
+ -o-animation: test 9s steps(2, start);
+ animation: test 9s steps(2, start);
+}
+@-o-keyframes test {
+ 0% {
+ color: #ffffff;
+ }
+ 100% {
+ color: #00ff00;
+ }
+}
+@keyframes test {
+ 0% {
+ color: #ffffff;
+ }
+ 100% {
+ color: #00ff00;
+ }
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; takeScreenshotDelayed(200);">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/underline_with_timestamp.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_background_properties-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_background_properties-ref.html
new file mode 100644
index 00000000000..f065a514fdf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_background_properties-ref.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(u), background properties</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ font-size: 36px;
+ background: rgba(0,0,0,0.8);
+ color: white;
+}
+.cue > span > u {
+ background: #0f0 url('../../../media/background.gif') repeat-x top left;
+ color: #000;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <u>test subtitle</u></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_background_properties.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_background_properties.html
new file mode 100644
index 00000000000..121258de2da
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_background_properties.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(u), background properties</title>
+<link rel="match" href="underline_background_properties-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(u) {
+ font-family: sans-serif;
+ background-color: #0f0;
+ background-image: url('../../../media/background.gif');
+ background-repeat: repeat-x;
+ background-position: top left;
+ color: black;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_underline.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_background_shorthand-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_background_shorthand-ref.html
new file mode 100644
index 00000000000..d435823500a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_background_shorthand-ref.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(u), background shorthand</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ font-size: 36px;
+ background: rgba(0,0,0,0.8);
+ color: white;
+}
+.cue > span > u {
+ background: #0f0 url('../../../media/background.gif') repeat-x top left;
+ color: #000;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <u>test subtitle</u></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_background_shorthand.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_background_shorthand.html
new file mode 100644
index 00000000000..b1512f2f4a5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_background_shorthand.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(u), background shorthand</title>
+<link rel="match" href="underline_background_shorthand-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(u) {
+ font-family: sans-serif;
+ background: #0f0 url('../../../media/background.gif') repeat-x top left;
+ color: #000;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_underline.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_color-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_color-ref.html
new file mode 100644
index 00000000000..64367cf198f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_color-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(u), color: #0000ff</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+}
+.cue > span > u {
+ color: #0000ff;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <u>test subtitle</u></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_color.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_color.html
new file mode 100644
index 00000000000..d59a8284f37
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_color.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(u), color: #0000ff</title>
+<link rel="match" href="underline_color-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(u) {
+ font-family: sans-serif;
+ color: #0000ff;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_underline.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_font_properties-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_font_properties-ref.html
new file mode 100644
index 00000000000..edc2f023cd3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_font_properties-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(u), font properties</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ font-family: sans-serif;
+ font-size: 36px;
+ text-align: center
+}
+.cue > span {
+ background: rgba(0,0,0,0.8);
+ color: white;
+}
+.cue > span > u {
+ font: italic small-caps normal 36px/72px sans-serif;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <u>test subtitle</u></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_font_properties.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_font_properties.html
new file mode 100644
index 00000000000..9efbd384b77
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_font_properties.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(u), font properties</title>
+<link rel="match" href="underline_font_properties-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(u) {
+ font-style: italic;
+ font-variant: small-caps;
+ font-weight: normal;
+ font-size: 36px;
+ line-height: 72px;
+ font-family: sans-serif;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_underline.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_font_shorthand-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_font_shorthand-ref.html
new file mode 100644
index 00000000000..355f5d7fc51
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_font_shorthand-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(u), font shorthand</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ font-family: sans-serif;
+ font-size: 36px;
+ text-align: center
+}
+.cue > span {
+ background: rgba(0,0,0,0.8);
+ color: white;
+}
+.cue > span > u {
+ font: normal small-caps normal 36px/72px sans-serif;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <u>test subtitle</u></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_font_shorthand.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_font_shorthand.html
new file mode 100644
index 00000000000..347cb8a212c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_font_shorthand.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(u), font shorthand</title>
+<link rel="match" href="underline_font_shorthand-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(u) {
+ font: normal small-caps normal 36px/72px sans-serif;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_underline.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_namespace-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_namespace-ref.html
new file mode 100644
index 00000000000..31b61e129c5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_namespace-ref.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(|u) should match</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: green;
+ font-size: 36px
+}
+.green {
+ text-decoration: underline;
+ color: green;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <span class="green">test subtitle</span></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_namespace.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_namespace.html
new file mode 100644
index 00000000000..9b75bf79169
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_namespace.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(|u) should match</title>
+<link rel="match" href="underline_namespace-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ color: green;
+}
+::cue(*|u) {
+ color: red
+}
+::cue(|u) {
+ color: green
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_underline.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_outline_properties-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_outline_properties-ref.html
new file mode 100644
index 00000000000..8554b59eb88
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_outline_properties-ref.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(u), outline properties</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+}
+.cue > span > u {
+ display: inline-block;
+ margin-left: -2px;
+ margin-right: -2px;
+ border: solid #00f 2px;
+ border-bottom: none;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <u>test subtitle</u></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_outline_properties.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_outline_properties.html
new file mode 100644
index 00000000000..9e9b10787eb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_outline_properties.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(u), outline properties</title>
+<link rel="match" href="underline_outline_properties-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(u) {
+ font-family: sans-serif;
+ outline-style: solid;
+ outline-color: #00f;
+ outline-width: 2px;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_underline.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_outline_shorthand-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_outline_shorthand-ref.html
new file mode 100644
index 00000000000..6537b8700e1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_outline_shorthand-ref.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(u), outline shorthand</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+}
+.cue > span > u {
+ display: inline-block;
+ margin-left: -2px;
+ margin-right: -2px;
+ border: solid #00f 2px;
+ border-bottom: none;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <u>test subtitle</u></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_outline_shorthand.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_outline_shorthand.html
new file mode 100644
index 00000000000..f76a52059bd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_outline_shorthand.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(u), outline shorthand</title>
+<link rel="match" href="underline_outline_shorthand-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(u) {
+ font-family: sans-serif;
+ outline: solid #00f 2px;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_underline.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_text-decoration_line-through-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_text-decoration_line-through-ref.html
new file mode 100644
index 00000000000..cd30f4669b3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_text-decoration_line-through-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(u), text-decoration: line-through</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+}
+.cue > span > u {
+ text-decoration: line-through;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <u>test subtitle</u></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_text-decoration_line-through.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_text-decoration_line-through.html
new file mode 100644
index 00000000000..e0f81b79d0b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_text-decoration_line-through.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(u), text-decoration: line-through</title>
+<link rel="match" href="underline_text-decoration_line-through-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(u) {
+ font-family: sans-serif;
+ text-decoration: line-through;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_underline.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_text-shadow-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_text-shadow-ref.html
new file mode 100644
index 00000000000..7bbc39f25e1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_text-shadow-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(u), text-shadow</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+}
+.cue > span > u {
+ text-shadow: 0px 0px 5px #0f0;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <u>test subtitle</u></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_text-shadow.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_text-shadow.html
new file mode 100644
index 00000000000..28daaf325e1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_text-shadow.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(u), text-shadow</title>
+<link rel="match" href="underline_text-shadow-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(u) {
+ font-family: sans-serif;
+ text-shadow: 0px 0px 5px #0f0;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_underline.vtt">
+</video>
+<script>
+document.getElementsByTagName('track')[0].track.mode = 'showing';
+</script>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_timestamp_future-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_timestamp_future-ref.html
new file mode 100644
index 00000000000..1fa3755c5d7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_timestamp_future-ref.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, underline object transition with timestamp, ::cue(u:future) selector</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ text-decoration: underline;
+ color: white;
+}
+.green {
+ text-decoration: underline;
+ color: #00ff00;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <span class="green">test subtitle</span></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_timestamp_future.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_timestamp_future.html
new file mode 100644
index 00000000000..b87678cbae5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_timestamp_future.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, underline object transition with timestamp, ::cue(u:future) selector</title>
+<link rel="match" href="underline_timestamp_future-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(u:future) {
+ color: #00ff00;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; takeScreenshotDelayed(200);">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/underline_with_2_timestamps.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_timestamp_past-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_timestamp_past-ref.html
new file mode 100644
index 00000000000..e32ff05cbba
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_timestamp_past-ref.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, underline object transition with timestamp, ::cue(u:past) selector</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+}
+.green {
+ text-decoration: underline;
+ color: #00ff00;
+}
+</style>
+<div class="video"><span class="cue"><span><span class="green">This is a test subtitle</span></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_timestamp_past.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_timestamp_past.html
new file mode 100644
index 00000000000..e686ef9566b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_timestamp_past.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, underline object transition with timestamp, ::cue(u:past) selector</title>
+<link rel="match" href="underline_timestamp_past-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(u:past) {
+ color: #00ff00;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; takeScreenshotDelayed(200);">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/underline_with_timestamp.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_transition_with_timestamp-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_transition_with_timestamp-ref.html
new file mode 100644
index 00000000000..6d5d3fa915f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_transition_with_timestamp-ref.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, underline object transition with timestamp, ::cue(u:past) selector</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+}
+.green {
+ color: #80ff80;
+ text-decoration: underline;
+}
+</style>
+<div class="video"><span class="cue"><span><span class="green">This is a test subtitle</span></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_transition_with_timestamp.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_transition_with_timestamp.html
new file mode 100644
index 00000000000..ad2dbd9c7bc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_transition_with_timestamp.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, underline object transition with timestamp, ::cue(u:past) selector</title>
+<link rel="match" href="underline_transition_with_timestamp-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(u) {
+ -o-transition: color 9s steps(2, start);
+ transition: color 9s steps(2, start);
+}
+::cue(u:past) {
+ color: #00ff00;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; takeScreenshotDelayed(200);">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/underline_with_timestamp.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_normal_wrapped-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_normal_wrapped-ref.html
new file mode 100644
index 00000000000..fe576afade1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_normal_wrapped-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, underline object, ::cue(u), white-space: normal (cue that wraps)</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ font-size: 36px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 25%;
+ right: 0;
+ width: 50%;
+ text-align: center;
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: white;
+ text-decoration: underline;
+ white-space: normal
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle that most likely will span over several rows since it's a pretty long cue with a lot of text.</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_normal_wrapped.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_normal_wrapped.html
new file mode 100644
index 00000000000..9c5cb5c4cd2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_normal_wrapped.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, voice object, ::cue(u), white-space: normal (cue that wraps)</title>
+<link rel="match" href="underline_white-space_normal_wrapped-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(u) {
+ white-space: normal
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/underline_long.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_nowrap-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_nowrap-ref.html
new file mode 100644
index 00000000000..1dc7af87fae
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_nowrap-ref.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, underline object, ::cue(u), white-space: nowrap (cue does not wrap)</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ font-size: 36px;
+ position: relative;
+ overflow: hidden;
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 25%;
+ right: 0;
+ width: 50%;
+ text-align: center;
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: white;
+ text-decoration: underline;
+ white-space: nowrap
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle that most likely will span over several rows since it's a pretty long cue with a lot of text.</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_nowrap.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_nowrap.html
new file mode 100644
index 00000000000..64d5d12b66c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_nowrap.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, underline object, ::cue(u), white-space: nowrap (cue does not wrap)</title>
+<link rel="match" href="underline_white-space_nowrap-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(u) {
+ white-space: nowrap
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/underline_long.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_pre-line_wrapped-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_pre-line_wrapped-ref.html
new file mode 100644
index 00000000000..288d89cf9b6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_pre-line_wrapped-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, underline object, ::cue(u), white-space: pre-line (cue that wraps)</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ font-size: 36px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 25%;
+ right: 0;
+ width: 50%;
+ text-align: center;
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: white;
+ text-decoration: underline;
+ white-space: pre-line
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle that most likely will span over several rows since it's a pretty long cue with a lot of text.</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_pre-line_wrapped.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_pre-line_wrapped.html
new file mode 100644
index 00000000000..7032ae8ccf7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_pre-line_wrapped.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, underline object, ::cue(u), white-space: pre-line (cue that wraps)</title>
+<link rel="match" href="underline_white-space_pre-line_wrapped-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(u) {
+ white-space: pre-line
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/underline_long.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_pre-wrap_wrapped-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_pre-wrap_wrapped-ref.html
new file mode 100644
index 00000000000..8819e442984
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_pre-wrap_wrapped-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, underline object, ::cue(u), white-space: pre-wrap (cue that wraps)</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ font-size: 36px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 25%;
+ right: 0;
+ width: 50%;
+ text-align: center;
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: white;
+ text-decoration: underline;
+ white-space: pre-wrap
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle that most likely will span over several rows since it's a pretty long cue with a lot of text.</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_pre-wrap_wrapped.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_pre-wrap_wrapped.html
new file mode 100644
index 00000000000..6ffe2b18f6e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_pre-wrap_wrapped.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, underline object, ::cue(u), white-space: pre-wrap (cue that wraps)</title>
+<link rel="match" href="underline_white-space_pre-wrap_wrapped-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(u) {
+ white-space: pre-wrap
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/underline_long.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_pre_wrapped-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_pre_wrapped-ref.html
new file mode 100644
index 00000000000..2c3b2047eb6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_pre_wrapped-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, underline object, ::cue(u), white-space: pre (cue that wraps)</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ font-size: 36px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 25%;
+ right: 0;
+ width: 50%;
+ text-align: center;
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: white;
+ text-decoration: underline;
+ white-space: pre
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle that most <br>likely will span over several <br>rows since it's a pretty long cue <br>with a lot of text.</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_pre_wrapped.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_pre_wrapped.html
new file mode 100644
index 00000000000..4bf3e45d1df
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_pre_wrapped.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, underline object, ::cue(u), white-space: pre (cue that wraps)</title>
+<link rel="match" href="underline_white-space_pre_wrapped-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(u) {
+ white-space: pre
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/underline_long.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_with_class-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_with_class-ref.html
new file mode 100644
index 00000000000..b948cc8cbd7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_with_class-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, underline object with class, ::cue(.foo) selector</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+}
+.green {
+ color: #00ff00;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <u>test subtitle</u>, <u class="green">test subtitle</u></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_with_class.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_with_class.html
new file mode 100644
index 00000000000..96f909b4c91
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_with_class.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, underline object with class, ::cue(.foo) selector</title>
+<link rel="match" href="underline_with_class-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(.foo) {
+ font-family: sans-serif;
+ color: #00ff00;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_underline_with_class.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_with_class_object_specific_selector-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_with_class_object_specific_selector-ref.html
new file mode 100644
index 00000000000..9ce9e3b6f36
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_with_class_object_specific_selector-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, underline object with class, ::cue(u.foo) selector</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+}
+.green {
+ color: #00ff00;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <u>test subtitle</u>, <u class="green">test subtitle</u></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_with_class_object_specific_selector.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_with_class_object_specific_selector.html
new file mode 100644
index 00000000000..045bf10eec6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_with_class_object_specific_selector.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, underline object with class, ::cue(u.foo) selector</title>
+<link rel="match" href="underline_with_class_object_specific_selector-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(u.foo) {
+ font-family: sans-serif;
+ color: #00ff00;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_underline_with_class.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_animation_with_timestamp-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_animation_with_timestamp-ref.html
new file mode 100644
index 00000000000..fb57a8f9096
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_animation_with_timestamp-ref.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, voice object animation with timestamp, ::cue(v:past) selector</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+}
+.green {
+ color: #80ff80;
+ font-weight: bold;
+}
+</style>
+<div class="video"><span class="cue"><span><span class="green">This is a test subtitle</span></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_animation_with_timestamp.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_animation_with_timestamp.html
new file mode 100644
index 00000000000..a6e43e82c3f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_animation_with_timestamp.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, voice object animation with timestamp, ::cue(v:past) selector</title>
+<link rel="match" href="voice_animation_with_timestamp-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(v:past) {
+ -o-animation: test 9s steps(2, start);
+ animation: test 9s steps(2, start);
+}
+@-o-keyframes test {
+ 0% {
+ color: #ffffff;
+ }
+ 100% {
+ color: #00ff00;
+ }
+}
+@keyframes test {
+ 0% {
+ color: #ffffff;
+ }
+ 100% {
+ color: #00ff00;
+ }
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; takeScreenshotDelayed(200);">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/voice_with_timestamp.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_background_properties-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_background_properties-ref.html
new file mode 100644
index 00000000000..7ead3aebdcc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_background_properties-ref.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(v), background properties</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ font-size: 36px;
+ background: rgba(0,0,0,0.8);
+ color: white;
+}
+.cue > span > span {
+ background: #0f0 url('../../../media/background.gif') repeat-x top left;
+ color: #000;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <span>test subtitle</span></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_background_properties.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_background_properties.html
new file mode 100644
index 00000000000..7392ca9c0bb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_background_properties.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(v), background properties</title>
+<link rel="match" href="voice_background_properties-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(v) {
+ font-family: sans-serif;
+ background-color: #0f0;
+ background-image: url('../../../media/background.gif');
+ background-repeat: repeat-x;
+ background-position: top left;
+ color: black;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_voice.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_background_shorthand-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_background_shorthand-ref.html
new file mode 100644
index 00000000000..30ca28885cb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_background_shorthand-ref.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(v), background shorthand</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ font-size: 36px;
+ background: rgba(0,0,0,0.8);
+ color: white;
+}
+.cue > span > span {
+ background: #0f0 url('../../../media/background.gif') repeat-x top left;
+ color: #000;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <span>test subtitle</span></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_background_shorthand.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_background_shorthand.html
new file mode 100644
index 00000000000..51cef0e8d94
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_background_shorthand.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(v), background shorthand</title>
+<link rel="match" href="voice_background_shorthand-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(v) {
+ font-family: sans-serif;
+ background: #0f0 url('../../../media/background.gif') repeat-x top left;
+ color: #000;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_voice.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_color-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_color-ref.html
new file mode 100644
index 00000000000..8375977a5ac
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_color-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(v), color: #0000ff</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+}
+.cue > span > span {
+ color: #0000ff;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <span>test subtitle</span></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_color.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_color.html
new file mode 100644
index 00000000000..98ad93694e8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_color.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(v), color: #0000ff</title>
+<link rel="match" href="voice_color-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(v) {
+ font-family: sans-serif;
+ color: #0000ff;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_voice.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_font_properties-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_font_properties-ref.html
new file mode 100644
index 00000000000..6675e8c24e1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_font_properties-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(v), font properties</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ font-family: sans-serif;
+ font-size: 36px;
+ text-align: center
+}
+.cue > span {
+ background: rgba(0,0,0,0.8);
+ color: white;
+}
+.cue > span > span {
+ font: italic small-caps bold 36px/72px sans-serif;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <span>test subtitle</span></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_font_properties.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_font_properties.html
new file mode 100644
index 00000000000..8626d9ea5f4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_font_properties.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(v), font properties</title>
+<link rel="match" href="voice_font_properties-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(v) {
+ font-style: italic;
+ font-variant: small-caps;
+ font-weight: bold;
+ font-size: 36px;
+ line-height: 72px;
+ font-family: sans-serif;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_voice.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_font_shorthand-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_font_shorthand-ref.html
new file mode 100644
index 00000000000..b656ea98fdd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_font_shorthand-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(v), font shorthand</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ font-family: sans-serif;
+ font-size: 36px;
+ text-align: center
+}
+.cue > span {
+ background: rgba(0,0,0,0.8);
+ color: white;
+}
+.cue > span > span {
+ font: normal small-caps bold 36px/72px sans-serif;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <span>test subtitle</span></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_font_shorthand.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_font_shorthand.html
new file mode 100644
index 00000000000..522a20dae61
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_font_shorthand.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(v), font shorthand</title>
+<link rel="match" href="voice_font_shorthand-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(v) {
+ font: normal small-caps bold 36px/72px sans-serif;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_voice.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_namespace-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_namespace-ref.html
new file mode 100644
index 00000000000..275f00f3fcf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_namespace-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(|v) should match</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: green;
+ font-size: 36px
+}
+.green {
+ color: green;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <span class="green">test subtitle</span></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_namespace.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_namespace.html
new file mode 100644
index 00000000000..aa5eb258f4e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_namespace.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(|v) should match</title>
+<link rel="match" href="voice_namespace-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ color: green;
+ font-family: Ahem, sans-serif
+}
+::cue(*|v) {
+ color: red
+}
+::cue(|v) {
+ color: green
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_voice.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_outline_properties-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_outline_properties-ref.html
new file mode 100644
index 00000000000..2d2fd34b40c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_outline_properties-ref.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(v), outline properties</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+}
+.cue > span > span {
+ display: inline-block;
+ margin-left: -2px;
+ margin-right: -2px;
+ border: solid #00f 2px;
+ border-bottom: none;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <span>test subtitle</span></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_outline_properties.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_outline_properties.html
new file mode 100644
index 00000000000..082be8e3286
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_outline_properties.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(v), outline properties</title>
+<link rel="match" href="voice_outline_properties-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(v) {
+ font-family: sans-serif;
+ outline-style: solid;
+ outline-color: #00f;
+ outline-width: 2px;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_voice.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_outline_shorthand-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_outline_shorthand-ref.html
new file mode 100644
index 00000000000..01731bd1132
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_outline_shorthand-ref.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(v), outline shorthand</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+}
+.cue > span > span {
+ display: inline-block;
+ margin-left: -2px;
+ margin-right: -2px;
+ border: solid #00f 2px;
+ border-bottom: none;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <span>test subtitle</span></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_outline_shorthand.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_outline_shorthand.html
new file mode 100644
index 00000000000..260243ad68a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_outline_shorthand.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(v), outline shorthand</title>
+<link rel="match" href="voice_outline_shorthand-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(v) {
+ font-family: sans-serif;
+ outline: solid #00f 2px;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_voice.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_text-decoration_line-through-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_text-decoration_line-through-ref.html
new file mode 100644
index 00000000000..b6bc91f1b6c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_text-decoration_line-through-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(v), text-decoration: line-through</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+}
+.cue > span > span {
+ text-decoration: line-through;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <span>test subtitle</span></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_text-decoration_line-through.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_text-decoration_line-through.html
new file mode 100644
index 00000000000..217dbfa5393
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_text-decoration_line-through.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(v), text-decoration: line-through</title>
+<link rel="match" href="voice_text-decoration_line-through-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(v) {
+ font-family: sans-serif;
+ text-decoration: line-through;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_voice.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_text-shadow-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_text-shadow-ref.html
new file mode 100644
index 00000000000..b67b96c5955
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_text-shadow-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(v), text-shadow</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+}
+.cue > span > span {
+ text-shadow: 0px 0px 5px #0f0;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <span>test subtitle</span></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_text-shadow.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_text-shadow.html
new file mode 100644
index 00000000000..de83df957b7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_text-shadow.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(v), text-shadow</title>
+<link rel="match" href="voice_text-shadow-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(v) {
+ font-family: sans-serif;
+ text-shadow: 0px 0px 5px #0f0;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_voice.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_timestamp_future-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_timestamp_future-ref.html
new file mode 100644
index 00000000000..9face626e81
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_timestamp_future-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, voice object transition with timestamp, ::cue(v:future) selector</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+}
+.green {
+ color: #00ff00;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <span class="green">test subtitle</span></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_timestamp_future.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_timestamp_future.html
new file mode 100644
index 00000000000..4c515ccb3ef
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_timestamp_future.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, voice object transition with timestamp, ::cue(v:future) selector</title>
+<link rel="match" href="voice_timestamp_future-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(v:future) {
+ color: #00ff00;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; takeScreenshotDelayed(200);">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/voice_with_2_timestamps.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_timestamp_past-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_timestamp_past-ref.html
new file mode 100644
index 00000000000..e7bb2ec4431
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_timestamp_past-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, voice object transition with timestamp, ::cue(v:past) selector</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+}
+.green {
+ color: #00ff00;
+}
+</style>
+<div class="video"><span class="cue"><span><span class="green">This is a test subtitle</span></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_timestamp_past.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_timestamp_past.html
new file mode 100644
index 00000000000..afb1af1f5af
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_timestamp_past.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, voice object transition with timestamp, ::cue(v:past) selector</title>
+<link rel="match" href="voice_timestamp_past-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(v:past) {
+ color: #00ff00;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; takeScreenshotDelayed(200);">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/voice_with_timestamp.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_transition_with_timestamp-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_transition_with_timestamp-ref.html
new file mode 100644
index 00000000000..b672da26e0b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_transition_with_timestamp-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, voice object transition with timestamp, ::cue(v:past) selector</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+}
+.green {
+ color: #80ff80;
+}
+</style>
+<div class="video"><span class="cue"><span><span class="green">This is a test subtitle</span></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_transition_with_timestamp.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_transition_with_timestamp.html
new file mode 100644
index 00000000000..a10ab6db399
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_transition_with_timestamp.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, voice object transition with timestamp, ::cue(v:past) selector</title>
+<link rel="match" href="voice_transition_with_timestamp-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(v) {
+ -o-transition: color 9s steps(2, start);
+ transition: color 9s steps(2, start);
+}
+::cue(v:past) {
+ color: #00ff00;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; takeScreenshotDelayed(200);">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/voice_with_timestamp.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_voice_attribute-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_voice_attribute-ref.html
new file mode 100644
index 00000000000..cac9a8697cd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_voice_attribute-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(v[voice="bar"])</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+}
+.green {
+ color: #00ff00;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <span>test subtitle</span>, <span class="green">test subtitle</span></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_voice_attribute.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_voice_attribute.html
new file mode 100644
index 00000000000..2f67bf2cdc6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_voice_attribute.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(v[voice="bar"])</title>
+<link rel="match" href="voice_voice_attribute-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(v[voice="bar"]) {
+ font-family: sans-serif;
+ color: #00ff00;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_two_voices.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_normal_wrapped-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_normal_wrapped-ref.html
new file mode 100644
index 00000000000..046d1a29bce
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_normal_wrapped-ref.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, voice object, ::cue(v), white-space: normal (cue that wraps)</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ font-size: 36px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 25%;
+ right: 0;
+ width: 50%;
+ text-align: center;
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: white;
+ white-space: normal
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle that most likely will span over several rows since it's a pretty long cue with a lot of text.</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_normal_wrapped.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_normal_wrapped.html
new file mode 100644
index 00000000000..e8e272cda8b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_normal_wrapped.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, voice object, ::cue(v), white-space: normal (cue that wraps)</title>
+<link rel="match" href="voice_white-space_normal_wrapped-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(v) {
+ white-space: normal
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/voice_long.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_nowrap-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_nowrap-ref.html
new file mode 100644
index 00000000000..014a2c8c684
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_nowrap-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, voice object, ::cue(v), white-space: nowrap (cue does not wrap)</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ font-size: 36px;
+ position: relative;
+ overflow: hidden;
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 25%;
+ right: 0;
+ width: 50%;
+ text-align: center;
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: white;
+ white-space: nowrap
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle that most likely will span over several rows since it's a pretty long cue with a lot of text.</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_nowrap.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_nowrap.html
new file mode 100644
index 00000000000..45bb59a2d8b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_nowrap.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, voice object, ::cue(v), white-space: nowrap (cue does not wrap)</title>
+<link rel="match" href="voice_white-space_nowrap-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(v) {
+ white-space: nowrap
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/voice_long.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_pre-line_wrapped-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_pre-line_wrapped-ref.html
new file mode 100644
index 00000000000..59d9d35c338
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_pre-line_wrapped-ref.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, voice object, ::cue(v), white-space: pre-line (cue that wraps)</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ font-size: 36px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 25%;
+ right: 0;
+ width: 50%;
+ text-align: center;
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: white;
+ white-space: pre-line
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle that most likely will span over several rows since it's a pretty long cue with a lot of text.</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_pre-line_wrapped.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_pre-line_wrapped.html
new file mode 100644
index 00000000000..a7a31727cfd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_pre-line_wrapped.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, voice object, ::cue(v), white-space: pre-line (cue that wraps)</title>
+<link rel="match" href="voice_white-space_pre-line_wrapped-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(v) {
+ white-space: pre-line
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/voice_long.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_pre-wrap_wrapped-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_pre-wrap_wrapped-ref.html
new file mode 100644
index 00000000000..c15e59e63f4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_pre-wrap_wrapped-ref.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, voice object, ::cue(v), white-space: pre-wrap (cue that wraps)</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ font-size: 36px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 25%;
+ right: 0;
+ width: 50%;
+ text-align: center;
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: white;
+ white-space: pre-wrap
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle that most likely will span over several rows since it's a pretty long cue with a lot of text.</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_pre-wrap_wrapped.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_pre-wrap_wrapped.html
new file mode 100644
index 00000000000..610c07dba4e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_pre-wrap_wrapped.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, voice object, ::cue(v), white-space: pre-wrap (cue that wraps)</title>
+<link rel="match" href="voice_white-space_pre-wrap_wrapped-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(v) {
+ white-space: pre-wrap
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/voice_long.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_pre_wrapped-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_pre_wrapped-ref.html
new file mode 100644
index 00000000000..9ae0bf8d706
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_pre_wrapped-ref.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, voice object, ::cue(v), white-space: pre (cue that wraps)</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ font-size: 36px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 25%;
+ right: 0;
+ width: 50%;
+ text-align: center;
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: white;
+ white-space: pre
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle that most <br>likely will span over several <br>rows since it's a pretty long cue <br>with a lot of text.</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_pre_wrapped.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_pre_wrapped.html
new file mode 100644
index 00000000000..06a0d0f7fd0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_pre_wrapped.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, voice object, ::cue(v), white-space: pre (cue that wraps)</title>
+<link rel="match" href="voice_white-space_pre_wrapped-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(v) {
+ white-space: pre
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/voice_long.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_with_class-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_with_class-ref.html
new file mode 100644
index 00000000000..af1988c7b84
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_with_class-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, voice object with class, ::cue(.foo) selector</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+}
+.green {
+ color: #00ff00;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <span>test subtitle</span>, <span class="green">test subtitle</span></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_with_class.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_with_class.html
new file mode 100644
index 00000000000..5d99d4c50d5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_with_class.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, voice object with class, ::cue(.foo) selector</title>
+<link rel="match" href="voice_with_class-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(.foo) {
+ font-family: sans-serif;
+ color: #00ff00;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_voice_with_class.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_with_class_object_specific_selector-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_with_class_object_specific_selector-ref.html
new file mode 100644
index 00000000000..8e5fc0699cd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_with_class_object_specific_selector-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, voice object with class, ::cue(v.foo) selector</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-align: center
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ font-size: 36px;
+ color: white;
+}
+.green {
+ color: #00ff00;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <span>test subtitle</span>, <span class="green">test subtitle</span></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_with_class_object_specific_selector.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_with_class_object_specific_selector.html
new file mode 100644
index 00000000000..a6105695c25
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_with_class_object_specific_selector.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, voice object with class, ::cue(v.foo) selector</title>
+<link rel="match" href="voice_with_class_object_specific_selector-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(v.foo) {
+ font-family: sans-serif;
+ color: #00ff00;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../../support/test_voice_with_class.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_normal_wrapped-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_normal_wrapped-ref.html
new file mode 100644
index 00000000000..bb5f6d5d44c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_normal_wrapped-ref.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(), white-space: normal (cue that wraps)</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ font-size: 36px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 40%;
+ right: 0;
+ width: 20%;
+ text-align: center;
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: white;
+ white-space: normal
+}
+</style>
+<div class="video"><span class="cue"><span>foo bar baz</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_normal_wrapped.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_normal_wrapped.html
new file mode 100644
index 00000000000..469b5c7e372
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_normal_wrapped.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(), white-space: normal (cue that wraps)</title>
+<link rel="match" href="white-space_normal_wrapped-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(*) {
+ white-space: normal
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/foo_space_space_bar_LF_baz.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_nowrap_wrapped-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_nowrap_wrapped-ref.html
new file mode 100644
index 00000000000..c1519e74f15
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_nowrap_wrapped-ref.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(), white-space: nowrap (cue that wraps)</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ font-size: 36px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 40%;
+ right: 0;
+ width: 20%;
+ text-align: center;
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: white;
+ white-space: nowrap
+}
+</style>
+<div class="video"><span class="cue"><span>A A A A A A A A A A A</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_nowrap_wrapped.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_nowrap_wrapped.html
new file mode 100644
index 00000000000..510f0e96434
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_nowrap_wrapped.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(), white-space: nowrap (cue that wraps)</title>
+<link rel="match" href="white-space_nowrap_wrapped-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(*) {
+ white-space: nowrap
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/white-spaces_long_size_20.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_pre-line_wrapped-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_pre-line_wrapped-ref.html
new file mode 100644
index 00000000000..bc8214d2cb5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_pre-line_wrapped-ref.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(), white-space: pre-line (cue that wraps)</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ font-size: 36px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 40%;
+ right: 0;
+ width: 20%;
+ text-align: center;
+}
+.cue > span {
+ font-family: sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: white;
+ white-space: normal
+}
+</style>
+<div class="video"><span class="cue"><span>A A A A A A<br> A A A A A</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_pre-line_wrapped.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_pre-line_wrapped.html
new file mode 100644
index 00000000000..15d21e8f823
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_pre-line_wrapped.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(), white-space: pre-line (cue that wraps)</title>
+<link rel="match" href="white-space_pre-line_wrapped-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(*) {
+ white-space: pre-line
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/white-spaces_long_size_20.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_pre-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_pre-ref.html
new file mode 100644
index 00000000000..8b7ccdad60b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_pre-ref.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(), white-space: pre</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ font-size: 36px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ font-family: sans-serif;
+ text-align: center
+}
+.cue > span {
+ background: rgba(0,0,0,0.8);
+ color: white;
+ white-space: pre
+}
+</style>
+<div class="video"><span class="cue"><span>A A A A A A</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_pre-wrap_wrapped-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_pre-wrap_wrapped-ref.html
new file mode 100644
index 00000000000..6979f1d80d9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_pre-wrap_wrapped-ref.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(), white-space: pre-wrap (cue that wraps)</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ font-size: 36px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 30%;
+ right: 0;
+ width: 40%;
+ font-family: sans-serif;
+ text-align: center;
+}
+.cue > span {
+ background: rgba(0,0,0,0.8);
+ color: white;
+ white-space: pre
+}
+</style>
+<div class="video"><span class="cue"><span>A A A A A <br> A <br>A A A A A</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_pre-wrap_wrapped.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_pre-wrap_wrapped.html
new file mode 100644
index 00000000000..2a42498d618
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_pre-wrap_wrapped.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(), white-space: pre-wrap (cue that wraps)</title>
+<link rel="match" href="white-space_pre-wrap_wrapped-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(*) {
+ white-space: pre-wrap
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/white-spaces_long.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_pre.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_pre.html
new file mode 100644
index 00000000000..ef6f37fa65b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_pre.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(), white-space: pre</title>
+<link rel="match" href="white-space_pre-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(*) {
+ white-space: pre
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/white-spaces.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_pre_wrapped-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_pre_wrapped-ref.html
new file mode 100644
index 00000000000..1ad6d44c59f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_pre_wrapped-ref.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, ::cue(), white-space: pre (cue that wraps)</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ font-size: 36px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 30%;
+ right: 0;
+ width: 40%;
+ font-family: sans-serif;
+ text-align: center;
+}
+.cue > span {
+ background: rgba(0,0,0,0.8);
+ color: white;
+ white-space: pre
+}
+</style>
+<div class="video"><span class="cue"><span>A A A A A <br> A <br>A A A A A</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_pre_wrapped.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_pre_wrapped.html
new file mode 100644
index 00000000000..51919b62504
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/white-space_pre_wrapped.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, ::cue(), white-space: pre (cue that wraps)</title>
+<link rel="match" href="white-space_pre_wrapped-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue(*) {
+ white-space: pre
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/white-spaces_long.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/default_styles/bold_object_default_font-style-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/default_styles/bold_object_default_font-style-ref.html
new file mode 100644
index 00000000000..4097c4b66ef
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/default_styles/bold_object_default_font-style-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, default style, bold objects</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ font-family: sans-serif;
+ font-size: 36px;
+ text-align: center
+}
+.cue > span {
+ background: rgba(0,0,0,0.8);
+ color: white;
+}
+.cue > span > span {
+ font-weight: bold;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <span>test subtitle</span></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/default_styles/bold_object_default_font-style.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/default_styles/bold_object_default_font-style.html
new file mode 100644
index 00000000000..53148d8bee9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/default_styles/bold_object_default_font-style.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, default style, bold objects</title>
+<link rel="match" href="bold_object_default_font-style-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/test_bold.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/default_styles/inherit_as_default_value_inherits_values_from_media_element-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/default_styles/inherit_as_default_value_inherits_values_from_media_element-ref.html
new file mode 100644
index 00000000000..f8d433ae2a5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/default_styles/inherit_as_default_value_inherits_values_from_media_element-ref.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, only css properties with default value inherit should inherit from media element</title>
+<style>
+.video {
+ position: absolute;
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative;
+ color: #f0f;
+ white-space: pre-line;
+ font: italic small-caps bold 36px/72px sans-serif;
+ text-shadow: 0px 0px 5px #0f0;
+ background: #0f0 url('../../media/background.gif') repeat-x top left;
+ outline: solid #00f 2px;
+}
+.videoWhite {
+ position: absolute;
+ top: 0;
+ left: 160px;
+ width: 960px;
+ height: 720px;;
+ background: #fff;
+ z-index: 1;
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 30%;
+ right: 0;
+ width: 40%;
+ text-align: center;
+ z-index: 2
+}
+.cue > span {
+ background-color: rgba(0,0,0,0.8);
+ color: #fff;
+}
+</style>
+<div class="video"><div class="videoWhite"></div><span class="cue"><span>A A A A A A A A A A A</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/default_styles/inherit_as_default_value_inherits_values_from_media_element.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/default_styles/inherit_as_default_value_inherits_values_from_media_element.html
new file mode 100644
index 00000000000..381c63c188d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/default_styles/inherit_as_default_value_inherits_values_from_media_element.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, only css properties with default value inherit should inherit from media element</title>
+<link rel="match" href="inherit_as_default_value_inherits_values_from_media_element-ref.html">
+<style>
+video {
+ color: #f0f;
+ white-space: pre-wrap;
+ font: italic small-caps bold 36px/72px sans-serif;
+ text-decoration: overline underline line-through;
+ text-shadow: 0px 0px 5px #0f0;
+ background: #0f0 url('../../media/background.gif') repeat-x top left;
+ outline: solid #00f 2px;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/white-spaces_long.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/default_styles/italic_object_default_font-style-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/default_styles/italic_object_default_font-style-ref.html
new file mode 100644
index 00000000000..b24a2595f41
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/default_styles/italic_object_default_font-style-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, default style, italic objects</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ font-family: sans-serif;
+ font-size: 36px;
+ text-align: center
+}
+.cue > span {
+ background: rgba(0,0,0,0.8);
+ color: white;
+}
+.cue > span > span {
+ font-style: italic;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <span>test subtitle</span></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/default_styles/italic_object_default_font-style.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/default_styles/italic_object_default_font-style.html
new file mode 100644
index 00000000000..6f07cb8ae09
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/default_styles/italic_object_default_font-style.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, default style, italic objects</title>
+<link rel="match" href="italic_object_default_font-style-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/test_italic.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/default_styles/underline_object_default_font-style-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/default_styles/underline_object_default_font-style-ref.html
new file mode 100644
index 00000000000..1b3744ab6b3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/default_styles/underline_object_default_font-style-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, default style, underline objects</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ font-family: sans-serif;
+ font-size: 36px;
+ text-align: center
+}
+.cue > span {
+ background: rgba(0,0,0,0.8);
+ color: white;
+}
+.cue > span > span {
+ text-decoration: underline;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a <span>test subtitle</span></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/default_styles/underline_object_default_font-style.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/default_styles/underline_object_default_font-style.html
new file mode 100644
index 00000000000..431ca4c6d40
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/selectors/default_styles/underline_object_default_font-style.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<title>WebVTT rendering, default style, underline objects</title>
+<link rel="match" href="underline_object_default_font-style-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="../../support/test_underline.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/size_50-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/size_50-ref.html
new file mode 100644
index 00000000000..c76f675cf5c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/size_50-ref.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, size:50%</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 25%;
+ right: 0;
+ width: 50%;
+ text-align: center
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: green;
+ font-size: 36px;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle that should wrap</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/size_50.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/size_50.html
new file mode 100644
index 00000000000..9888cb687ee
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/size_50.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>WebVTT rendering, size:50%</title>
+<link rel="match" href="size_50-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family: Ahem, sans-serif;
+ color: green
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="support/size_50.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/2_cues_overlapping_completely_move_up.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/2_cues_overlapping_completely_move_up.vtt
new file mode 100644
index 00000000000..d4a96792482
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/2_cues_overlapping_completely_move_up.vtt
@@ -0,0 +1,7 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000 line:50%
+This is a test subtitle
+
+00:00:01.000 --> 00:00:05.000 line:50%
+This is another test subtitle
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/2_cues_overlapping_partially_move_down.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/2_cues_overlapping_partially_move_down.vtt
new file mode 100644
index 00000000000..227e7db6e4b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/2_cues_overlapping_partially_move_down.vtt
@@ -0,0 +1,7 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000 line:50%
+This is a test subtitle
+
+00:00:01.000 --> 00:00:05.000 line:52%
+This is another test subtitle
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/2_cues_overlapping_partially_move_up.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/2_cues_overlapping_partially_move_up.vtt
new file mode 100644
index 00000000000..6c99ce3b1fe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/2_cues_overlapping_partially_move_up.vtt
@@ -0,0 +1,7 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000 line:50%
+This is a test subtitle
+
+00:00:01.000 --> 00:00:05.000 line:49%
+This is another test subtitle
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/align_end.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/align_end.vtt
new file mode 100644
index 00000000000..83f691e6ffa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/align_end.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000 align:end
+This is a test
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/align_end_long.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/align_end_long.vtt
new file mode 100644
index 00000000000..09ace0d2278
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/align_end_long.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000 align:end
+This is a test subtitle that most likely will span over several rows since it is a pretty long cue with a lot of text.
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/align_middle.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/align_middle.vtt
new file mode 100644
index 00000000000..cdee051d777
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/align_middle.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000 align:middle
+This is a test
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/align_middle_long.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/align_middle_long.vtt
new file mode 100644
index 00000000000..8c89441a974
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/align_middle_long.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000 align:middle
+This is a test subtitle that most likely will span over several rows since it is a pretty long cue with a lot of text.
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/align_middle_position_50.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/align_middle_position_50.vtt
new file mode 100644
index 00000000000..c443773984e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/align_middle_position_50.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000 align:middle position:50%
+This is a test
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/align_middle_position_gt_50.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/align_middle_position_gt_50.vtt
new file mode 100644
index 00000000000..186ae1ecd23
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/align_middle_position_gt_50.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000 align:middle position:90%
+Awesome!!!
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/align_middle_position_lt_50.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/align_middle_position_lt_50.vtt
new file mode 100644
index 00000000000..6928c5dc218
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/align_middle_position_lt_50.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000 align:middle position:10%
+Awesome!!!
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/align_middle_position_lt_50_size_gt_maximum_size.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/align_middle_position_lt_50_size_gt_maximum_size.vtt
new file mode 100644
index 00000000000..32bc4ed3fc8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/align_middle_position_lt_50_size_gt_maximum_size.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000 align:middle position:10% size:75%
+Awesome!!!
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/align_start.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/align_start.vtt
new file mode 100644
index 00000000000..161c457465d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/align_start.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000 align:start
+This is a test
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/align_start_long.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/align_start_long.vtt
new file mode 100644
index 00000000000..c70ac13eaf7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/align_start_long.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000 align:start
+This is a test subtitle that most likely will span over several rows since it is a pretty long cue with a lot of text.
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/bidi_ruby.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/bidi_ruby.vtt
new file mode 100644
index 00000000000..19e67450160
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/bidi_ruby.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000
+<ruby>.<rt>א<c>א</c></rt>ab)<rt>x</rt></ruby>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/bold_long.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/bold_long.vtt
new file mode 100644
index 00000000000..c452682e4c5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/bold_long.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000 size:50%
+<b>This is a test subtitle that most likely will span over several rows since it's a pretty long cue with a lot of text.</b>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/bold_with_2_timestamps.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/bold_with_2_timestamps.vtt
new file mode 100644
index 00000000000..53508f991f6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/bold_with_2_timestamps.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:10.000
+<00:00.000><b>This is a </b><00:05.000><b>test subtitle</b>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/bold_with_timestamp.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/bold_with_timestamp.vtt
new file mode 100644
index 00000000000..85474b1b955
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/bold_with_timestamp.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:10.000
+<00:00.000><b>This is a test subtitle</b><00:00.001>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/class_long.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/class_long.vtt
new file mode 100644
index 00000000000..a551d677435
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/class_long.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000 size:50%
+<c>This is a test subtitle that most likely will span over several rows since it's a pretty long cue with a lot of text.</c>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/class_with_2_timestamps.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/class_with_2_timestamps.vtt
new file mode 100644
index 00000000000..d95f7602573
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/class_with_2_timestamps.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:10.000
+<00:00.000><c>This is a </c><00:05.000><c>test subtitle</c>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/class_with_timestamp.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/class_with_timestamp.vtt
new file mode 100644
index 00000000000..2e328ab9b72
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/class_with_timestamp.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:10.000
+<00:00.000><c>This is a test subtitle</c><00:00.001>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/cue_with_id.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/cue_with_id.vtt
new file mode 100644
index 00000000000..3a8a88cf735
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/cue_with_id.vtt
@@ -0,0 +1,5 @@
+WEBVTT
+
+foo
+00:00:00.000 --> 00:00:05.000
+This is a test subtitle
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/decode_escaped_entities.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/decode_escaped_entities.vtt
new file mode 100644
index 00000000000..36373d2e203
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/decode_escaped_entities.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000
+Here are the escaped entities: &amp; &lt; &gt; &lrm; &rlm; &nbsp;
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/foo.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/foo.vtt
new file mode 100644
index 00000000000..b533895c604
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/foo.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000
+Foo
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/foo_c_bar.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/foo_c_bar.vtt
new file mode 100644
index 00000000000..325df1e509c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/foo_c_bar.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000
+Foo<c>bar</c>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/foo_space_space_bar_LF_baz.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/foo_space_space_bar_LF_baz.vtt
new file mode 100644
index 00000000000..047d80eddf9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/foo_space_space_bar_LF_baz.vtt
@@ -0,0 +1,5 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000
+foo bar
+baz
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/italic_long.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/italic_long.vtt
new file mode 100644
index 00000000000..75cbd1e6ef2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/italic_long.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000 size:50%
+<i>This is a test subtitle that most likely will span over several rows since it's a pretty long cue with a lot of text.</i>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/italic_with_2_timestamps.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/italic_with_2_timestamps.vtt
new file mode 100644
index 00000000000..d239c4ee243
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/italic_with_2_timestamps.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:10.000
+<00:00.000><i>This is a </i><00:05.000><i>test subtitle</i>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/italic_with_timestamp.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/italic_with_timestamp.vtt
new file mode 100644
index 00000000000..94b03a2077f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/italic_with_timestamp.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:10.000
+<00:00.000><i>This is a test subtitle</i><00:00.001>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/line_-2_long.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/line_-2_long.vtt
new file mode 100644
index 00000000000..0f366c18cc6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/line_-2_long.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000 line:-2 size:50%
+This is a test subtitle that will line break
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/line_0.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/line_0.vtt
new file mode 100644
index 00000000000..18d2bd46ae4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/line_0.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000 line:0
+This is a test subtitle
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/line_1_long.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/line_1_long.vtt
new file mode 100644
index 00000000000..414c9de3912
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/line_1_long.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000 line:1 size:50%
+This is a test subtitle that will line break
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/line_50_percent.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/line_50_percent.vtt
new file mode 100644
index 00000000000..acf612c44f6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/line_50_percent.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000 line:50%
+This is a test subtitle
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/line_integer_and_percent_overlap.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/line_integer_and_percent_overlap.vtt
new file mode 100644
index 00000000000..6a1326e9411
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/line_integer_and_percent_overlap.vtt
@@ -0,0 +1,7 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:10.000 line:9
+This is a test subtitle
+
+00:00:00.000 --> 00:00:10.000 line:50%
+This is another test subtitle
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/line_integer_and_percent_overlap_move_up.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/line_integer_and_percent_overlap_move_up.vtt
new file mode 100644
index 00000000000..819f8e2a211
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/line_integer_and_percent_overlap_move_up.vtt
@@ -0,0 +1,7 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:10.000 line:10
+This is a test subtitle
+
+00:00:00.000 --> 00:00:10.000 line:48%
+This is another test subtitle
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/line_percent_and_integer_overlap.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/line_percent_and_integer_overlap.vtt
new file mode 100644
index 00000000000..47819a05109
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/line_percent_and_integer_overlap.vtt
@@ -0,0 +1,7 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:10.000 line:45%
+This is a test subtitle
+
+00:00:00.000 --> 00:00:10.000 line:9
+This is another test subtitle
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/line_percent_and_integer_overlap_move_up.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/line_percent_and_integer_overlap_move_up.vtt
new file mode 100644
index 00000000000..1a7bd7fed5d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/line_percent_and_integer_overlap_move_up.vtt
@@ -0,0 +1,7 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:10.000 line:55%
+This is a test subtitle
+
+00:00:00.000 --> 00:00:10.000 line:10
+This is another test subtitle
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/one_line_cue_plus_wrapped_cue.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/one_line_cue_plus_wrapped_cue.vtt
new file mode 100644
index 00000000000..b9b3fecf6d6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/one_line_cue_plus_wrapped_cue.vtt
@@ -0,0 +1,7 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:10.000 size:70%
+This is a test subtitle
+
+00:00:00.000 --> 00:00:10.000 size:70%
+This test subtitle wraps and should be visible
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/size_50.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/size_50.vtt
new file mode 100644
index 00000000000..b165af1533b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/size_50.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000 size:50%
+This is a test subtitle that should wrap
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/test.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/test.vtt
new file mode 100644
index 00000000000..ab71ec59840
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/test.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000
+This is a test subtitle
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/test_bold.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/test_bold.vtt
new file mode 100644
index 00000000000..5709f4dd305
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/test_bold.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000
+This is a <b>test subtitle</b>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/test_bold_with_class.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/test_bold_with_class.vtt
new file mode 100644
index 00000000000..1eebeea5cb4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/test_bold_with_class.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000
+This is a <b>test subtitle</b>, <b.foo>test subtitle</b>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/test_class.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/test_class.vtt
new file mode 100644
index 00000000000..8ee08aada4e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/test_class.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000
+This is a <c>test subtitle</c>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/test_class_with_class.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/test_class_with_class.vtt
new file mode 100644
index 00000000000..c17abc9c959
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/test_class_with_class.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000
+This is a <c>test subtitle</c>, <c.foo>test subtitle</c>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/test_italic.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/test_italic.vtt
new file mode 100644
index 00000000000..11c2c81deb8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/test_italic.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000
+This is a <i>test subtitle</i>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/test_italic_with_class.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/test_italic_with_class.vtt
new file mode 100644
index 00000000000..a2255d000ad
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/test_italic_with_class.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000
+This is a <i>test subtitle</i>, <i.foo>test subtitle</i>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/test_long.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/test_long.vtt
new file mode 100644
index 00000000000..826ec1de17e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/test_long.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000
+This is a test subtitle that most likely will span over several rows since it's a pretty long cue with a lot of text.
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/test_two_voices.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/test_two_voices.vtt
new file mode 100644
index 00000000000..c41fe2e1695
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/test_two_voices.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000
+This is a <v foo>test subtitle</v>, <v bar>test subtitle</v>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/test_underline.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/test_underline.vtt
new file mode 100644
index 00000000000..8b1f02183d2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/test_underline.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000
+This is a <u>test subtitle</u>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/test_underline_with_class.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/test_underline_with_class.vtt
new file mode 100644
index 00000000000..7894c87e005
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/test_underline_with_class.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000
+This is a <u>test subtitle</u>, <u.foo>test subtitle</u>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/test_voice.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/test_voice.vtt
new file mode 100644
index 00000000000..3e25cff699b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/test_voice.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000
+This is a <v foo>test subtitle</v>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/test_voice_with_class.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/test_voice_with_class.vtt
new file mode 100644
index 00000000000..8f1f37581be
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/test_voice_with_class.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000
+This is a <v foo>test subtitle</v>, <v.foo>test subtitle</v>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/too_many_cues.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/too_many_cues.vtt
new file mode 100644
index 00000000000..6deac9306d3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/too_many_cues.vtt
@@ -0,0 +1,64 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:10.000
+This is a test subtitle
+
+00:00:00.000 --> 00:00:10.000
+This is a test subtitle
+
+00:00:00.000 --> 00:00:10.000
+This is a test subtitle
+
+00:00:00.000 --> 00:00:10.000
+This is a test subtitle
+
+00:00:00.000 --> 00:00:10.000
+This is a test subtitle
+
+00:00:00.000 --> 00:00:10.000
+This is a test subtitle
+
+00:00:00.000 --> 00:00:10.000
+This is a test subtitle
+
+00:00:00.000 --> 00:00:10.000
+This is a test subtitle
+
+00:00:00.000 --> 00:00:10.000
+This is a test subtitle
+
+00:00:00.000 --> 00:00:10.000
+This is a test subtitle
+
+00:00:00.000 --> 00:00:10.000
+This is a test subtitle
+
+00:00:00.000 --> 00:00:10.000
+This is a test subtitle
+
+00:00:00.000 --> 00:00:10.000
+This is a test subtitle
+
+00:00:00.000 --> 00:00:10.000
+This is a test subtitle
+
+00:00:00.000 --> 00:00:10.000
+This is a test subtitle
+
+00:00:00.000 --> 00:00:10.000
+This is a test subtitle
+
+00:00:00.000 --> 00:00:10.000
+This is a test subtitle
+
+00:00:00.000 --> 00:00:10.000
+This is a test subtitle
+
+00:00:00.000 --> 00:00:10.000
+This is a test subtitle
+
+00:00:00.000 --> 00:00:10.000
+This is a test subtitle
+
+00:00:00.000 --> 00:00:10.000
+abcdefghijklmnopqrstuvw
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/too_many_cues_wrapped.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/too_many_cues_wrapped.vtt
new file mode 100644
index 00000000000..1363acb6066
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/too_many_cues_wrapped.vtt
@@ -0,0 +1,61 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:10.000
+This is a test subtitle
+
+00:00:00.000 --> 00:00:10.000
+This is a test subtitle
+
+00:00:00.000 --> 00:00:10.000
+This is a test subtitle
+
+00:00:00.000 --> 00:00:10.000
+This is a test subtitle
+
+00:00:00.000 --> 00:00:10.000
+This is a test subtitle
+
+00:00:00.000 --> 00:00:10.000
+This is a test subtitle
+
+00:00:00.000 --> 00:00:10.000
+This is a test subtitle
+
+00:00:00.000 --> 00:00:10.000
+This is a test subtitle
+
+00:00:00.000 --> 00:00:10.000
+This is a test subtitle
+
+00:00:00.000 --> 00:00:10.000
+This is a test subtitle
+
+00:00:00.000 --> 00:00:10.000
+This is a test subtitle
+
+00:00:00.000 --> 00:00:10.000
+This is a test subtitle
+
+00:00:00.000 --> 00:00:10.000
+This is a test subtitle
+
+00:00:00.000 --> 00:00:10.000
+This is a test subtitle
+
+00:00:00.000 --> 00:00:10.000
+This is a test subtitle
+
+00:00:00.000 --> 00:00:10.000
+This is a test subtitle
+
+00:00:00.000 --> 00:00:10.000
+This is a test subtitle
+
+00:00:00.000 --> 00:00:10.000
+This is a test subtitle
+
+00:00:00.000 --> 00:00:10.000
+This is a test subtitle
+
+00:00:00.000 --> 00:00:10.000 size:70%
+This is a test subtitle that wraps and the part after the first subtitle should be cut out
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/u002E_LF_u05D0.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/u002E_LF_u05D0.vtt
new file mode 100644
index 00000000000..24cd29be669
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/u002E_LF_u05D0.vtt
@@ -0,0 +1,5 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000
+.
+אab)
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/u002E_u2028_u05D0.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/u002E_u2028_u05D0.vtt
new file mode 100644
index 00000000000..9367a095a09
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/u002E_u2028_u05D0.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000
+.
אab)
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/u002E_u2029_u05D0.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/u002E_u2029_u05D0.vtt
new file mode 100644
index 00000000000..81d21a453e6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/u002E_u2029_u05D0.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000
+.
אab)
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/u0041_first.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/u0041_first.vtt
new file mode 100644
index 00000000000..19dc55c4527
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/u0041_first.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000
+Aab)
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/u05D0_first.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/u05D0_first.vtt
new file mode 100644
index 00000000000..fdc74bf4fab
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/u05D0_first.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000
+אab)
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/u0628_first.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/u0628_first.vtt
new file mode 100644
index 00000000000..a0b953d6c9a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/u0628_first.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000
+بab)
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/u06E9_no_strong_dir.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/u06E9_no_strong_dir.vtt
new file mode 100644
index 00000000000..f0971515671
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/u06E9_no_strong_dir.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000
+۩)
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/underline_long.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/underline_long.vtt
new file mode 100644
index 00000000000..7f4ee28405d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/underline_long.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000 size:50%
+<u>This is a test subtitle that most likely will span over several rows since it's a pretty long cue with a lot of text.</u>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/underline_with_2_timestamps.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/underline_with_2_timestamps.vtt
new file mode 100644
index 00000000000..54905bfb763
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/underline_with_2_timestamps.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:10.000
+<00:00.000><u>This is a </u><00:05.000><u>test subtitle</u>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/underline_with_timestamp.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/underline_with_timestamp.vtt
new file mode 100644
index 00000000000..e6d942b962a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/underline_with_timestamp.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:10.000
+<00:00.000><u>This is a test subtitle</u><00:00.001>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/very_long_cue.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/very_long_cue.vtt
new file mode 100644
index 00000000000..fc62842108f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/very_long_cue.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:10.000 size:50%
+This is a test subtitle that should wrap several times and become so long that the cue must be cut when displayed, because it does not fit on the screen. This is a test subtitle that should wrap several times and become so long that the cue must be cut when displayed, because it does not fit on the screen.
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/voice_long.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/voice_long.vtt
new file mode 100644
index 00000000000..1a443df0994
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/voice_long.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000 size:50%
+<v foo>This is a test subtitle that most likely will span over several rows since it's a pretty long cue with a lot of text.</v>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/voice_with_2_timestamps.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/voice_with_2_timestamps.vtt
new file mode 100644
index 00000000000..b5d2089fb68
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/voice_with_2_timestamps.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:10.000
+<00:00.000><v>This is a </v><00:05.000><v>test subtitle</v>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/voice_with_timestamp.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/voice_with_timestamp.vtt
new file mode 100644
index 00000000000..99f49377057
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/voice_with_timestamp.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:10.000
+<00:00.000><v>This is a test subtitle</v><00:00.001>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/white-spaces.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/white-spaces.vtt
new file mode 100644
index 00000000000..99b772ffd93
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/white-spaces.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000
+A A A A A A
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/white-spaces_long.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/white-spaces_long.vtt
new file mode 100644
index 00000000000..53522123935
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/white-spaces_long.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000 size:40%
+A A A A A A A A A A A
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/white-spaces_long_size_20.vtt b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/white-spaces_long_size_20.vtt
new file mode 100644
index 00000000000..7807ca32a2d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/support/white-spaces_long_size_20.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:05.000 size:20%
+A A A A A A A A A A A
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/too_many_cues-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/too_many_cues-ref.html
new file mode 100644
index 00000000000..a14dfb92bb0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/too_many_cues-ref.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, too many cues - cues that cannot fit should not be shown</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 15%;
+ right: 0;
+ width: 70%;
+ text-align: center
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: green;
+ font-size: 36px;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle<br>This is a test subtitle<br>This is a test subtitle<br>This is a test subtitle<br>This is a test subtitle<br>This is a test subtitle<br>This is a test subtitle<br>This is a test subtitle<br>This is a test subtitle<br>This is a test subtitle<br>This is a test subtitle<br>This is a test subtitle<br>This is a test subtitle<br>This is a test subtitle<br>This is a test subtitle<br>This is a test subtitle<br>This is a test subtitle<br>This is a test subtitle<br>This is a test subtitle<br>This is a test subtitle<br></span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/too_many_cues.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/too_many_cues.html
new file mode 100644
index 00000000000..573ffcc21a9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/too_many_cues.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>WebVTT rendering, too many cues - cues that cannot fit should not be shown</title>
+<link rel="match" href="too_many_cues-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family: Ahem, sans-serif;
+ color: green
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="support/too_many_cues.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/too_many_cues_wrapped-ref.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/too_many_cues_wrapped-ref.html
new file mode 100644
index 00000000000..f05cd51f8ae
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/too_many_cues_wrapped-ref.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>Reference for WebVTT rendering, too many cues (wrapped) - cues that cannot fit should not be shown</title>
+<style>
+html { overflow:hidden }
+body { margin:0 }
+.video {
+ display: inline-block;
+ width: 1280px;
+ height: 720px;
+ position: relative
+}
+.cue {
+ position: absolute;
+ bottom: 0;
+ left: 15%;
+ right: 0;
+ width: 70%;
+ text-align: center
+}
+.cue > span {
+ font-family: Ahem, sans-serif;
+ background: rgba(0,0,0,0.8);
+ color: green;
+ font-size: 36px;
+}
+</style>
+<div class="video"><span class="cue"><span>This is a test subtitle<br>This is a test subtitle<br>This is a test subtitle<br>This is a test subtitle<br>This is a test subtitle<br>This is a test subtitle<br>This is a test subtitle<br>This is a test subtitle<br>This is a test subtitle<br>This is a test subtitle<br>This is a test subtitle<br>This is a test subtitle<br>This is a test subtitle<br>This is a test subtitle<br>This is a test subtitle<br>This is a test subtitle<br>This is a test subtitle<br>This is a test subtitle<br>This is a test subtitle<br>This is a test subtitle</span></span></div>
diff --git a/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/too_many_cues_wrapped.html b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/too_many_cues_wrapped.html
new file mode 100644
index 00000000000..beb816001c2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/rendering/cues-with-video/processing-model/too_many_cues_wrapped.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>WebVTT rendering, too many cues (wrapped) - cues that cannot fit should not be shown</title>
+<link rel="match" href="too_many_cues_wrapped-ref.html">
+<style>
+html { overflow:hidden }
+body { margin:0 }
+::cue {
+ font-family: Ahem, sans-serif;
+ color: green
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<video width="1280" height="720" autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();">
+ <source src="/media/white.webm" type="video/webm">
+ <source src="/media/white.mp4" type="video/mp4">
+ <track src="support/too_many_cues_wrapped.vtt">
+ <script>
+ document.getElementsByTagName('track')[0].track.mode = 'showing';
+ </script>
+</video>
+</html>
diff --git a/tests/wpt/web-platform-tests/webvtt/webvtt-api-for-browsers/vttcue-interface/align.html b/tests/wpt/web-platform-tests/webvtt/webvtt-api-for-browsers/vttcue-interface/align.html
new file mode 100644
index 00000000000..946081e40b4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/webvtt-api-for-browsers/vttcue-interface/align.html
@@ -0,0 +1,54 @@
+<!doctype html>
+<title>VTTCue.align</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function(){
+ var video = document.createElement('video');
+ document.body.appendChild(video);
+ var c1 = new VTTCue(0, 1, 'text1');
+ assert_equals(c1.align, 'middle');
+ var track = document.createElement('track');
+ var t = track.track;
+ t.addCue(c1);
+ assert_equals(c1.align, 'middle');
+ video.appendChild(track);
+ assert_equals(c1.align, 'middle');
+ t.mode = 'showing';
+ assert_equals(c1.align, 'middle');
+ c1.align = 'start';
+ assert_equals(c1.align, 'start');
+ c1.align = 'end';
+ assert_equals(c1.align, 'end');
+ c1.align = 'start\u0000';
+ assert_equals(c1.align, 'end');
+}, document.title+', script-created cue');
+
+var t_parsed = async_test(document.title+', parsed cue');
+t_parsed.step(function(){
+ var video = document.createElement('video');
+ document.body.appendChild(video);
+ var t = document.createElement('track');
+ t.onload = this.step_func(function(){
+ var c1 = t.track.cues[0];
+ var c2 = t.track.cues[1];
+ var c3 = t.track.cues[2];
+ var c4 = t.track.cues[3];
+ assert_equals(c1.align, 'middle');
+ assert_equals(c2.align, 'start');
+ assert_equals(c3.align, 'middle');
+ assert_equals(c4.align, 'end');
+ this.done();
+ });
+ t.onerror = this.step_func(function() {
+ assert_unreached('got error event');
+ });
+ t.src = 'data:text/vtt,'+encodeURIComponent('WEBVTT\n\n00:00:00.000 --> 00:00:00.001\ntest\n\n'+
+ '00:00:00.000 --> 00:00:00.001 align:start\ntest\n\n'+
+ '00:00:00.000 --> 00:00:00.001 align:middle\ntest\n\n'+
+ '00:00:00.000 --> 00:00:00.001 align:end\ntest');
+ t.track.mode = 'showing';
+ video.appendChild(t);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/webvtt/webvtt-api-for-browsers/vttcue-interface/getCueAsHTML.html b/tests/wpt/web-platform-tests/webvtt/webvtt-api-for-browsers/vttcue-interface/getCueAsHTML.html
new file mode 100644
index 00000000000..5be09a5d347
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/webvtt-api-for-browsers/vttcue-interface/getCueAsHTML.html
@@ -0,0 +1,92 @@
+<!doctype html>
+<title>VTTCue.getCueAsHTML()</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function(){
+ var video = document.createElement('video');
+ var t1 = video.addTextTrack('subtitles');
+ document.body.appendChild(video);
+ var c1 = new VTTCue(0, 1, '<c></c><c.a.b></c><i></i><b></b><u></u><ruby><rt></rt></ruby><v></v><v a b></v><00:00:00.500>x\0');
+ t1.addCue(c1);
+ window.frag = c1.getCueAsHTML();
+ assert_equals(frag.childNodes.length, 10, 'childNodes.length');
+ assert_true(frag instanceof DocumentFragment, 'getCueAsHTML() should return DocumentFragment');
+}, document.title+', creating the cue');
+test(function(){
+ assert_equals(frag.childNodes[0].namespaceURI, 'http://www.w3.org/1999/xhtml', 'namespaceURI');
+ assert_equals(frag.childNodes[0].localName, 'span', 'localName');
+ assert_equals(frag.childNodes[0].attributes.length, 0, 'attributes');
+ assert_false(frag.childNodes[0].hasChildNodes(), 'hasChildNodes()');
+ assert_true(frag.childNodes[0] instanceof HTMLElement, 'instanceof');
+}, document.title+', <c>');
+test(function(){
+ assert_equals(frag.childNodes[1].namespaceURI, 'http://www.w3.org/1999/xhtml', 'namespaceURI');
+ assert_equals(frag.childNodes[1].localName, 'span', 'localName');
+ assert_equals(frag.childNodes[1].attributes.length, 1, 'attributes');
+ assert_equals(frag.childNodes[1].getAttributeNS('', 'class'), 'a b', 'class attribute');
+ assert_false(frag.childNodes[1].hasChildNodes(), 'hasChildNodes()');
+ assert_true(frag.childNodes[1] instanceof HTMLElement, 'instanceof');
+}, document.title+', <c.a.b>');
+test(function(){
+ assert_equals(frag.childNodes[2].namespaceURI, 'http://www.w3.org/1999/xhtml', 'namespaceURI');
+ assert_equals(frag.childNodes[2].localName, 'i', 'localName');
+ assert_equals(frag.childNodes[2].attributes.length, 0, 'attributes');
+ assert_false(frag.childNodes[2].hasChildNodes(), 'hasChildNodes()');
+ assert_true(frag.childNodes[2] instanceof HTMLElement, 'instanceof');
+}, document.title+', <i>');
+test(function(){
+ assert_equals(frag.childNodes[3].namespaceURI, 'http://www.w3.org/1999/xhtml', 'namespaceURI');
+ assert_equals(frag.childNodes[3].localName, 'b', 'localName');
+ assert_equals(frag.childNodes[3].attributes.length, 0, 'attributes');
+ assert_false(frag.childNodes[3].hasChildNodes(), 'hasChildNodes()');
+ assert_true(frag.childNodes[3] instanceof HTMLElement, 'instanceof');
+}, document.title+', <b>');
+test(function(){
+ assert_equals(frag.childNodes[4].namespaceURI, 'http://www.w3.org/1999/xhtml', 'namespaceURI');
+ assert_equals(frag.childNodes[4].localName, 'u', 'localName');
+ assert_equals(frag.childNodes[4].attributes.length, 0, 'attributes');
+ assert_false(frag.childNodes[4].hasChildNodes(), 'hasChildNodes()');
+ assert_true(frag.childNodes[4] instanceof HTMLElement, 'instanceof');
+}, document.title+', <u>');
+test(function(){
+ assert_equals(frag.childNodes[5].namespaceURI, 'http://www.w3.org/1999/xhtml', 'namespaceURI');
+ assert_equals(frag.childNodes[5].localName, 'ruby', 'localName');
+ assert_equals(frag.childNodes[5].attributes.length, 0, 'attributes');
+ assert_true(frag.childNodes[5].hasChildNodes(), 'hasChildNodes()');
+ assert_true(frag.childNodes[5] instanceof HTMLElement, 'instanceof');
+}, document.title+', <ruby>');
+test(function(){
+ assert_equals(frag.childNodes[5].firstChild.namespaceURI, 'http://www.w3.org/1999/xhtml', 'namespaceURI');
+ assert_equals(frag.childNodes[5].firstChild.localName, 'rt', 'localName');
+ assert_equals(frag.childNodes[5].firstChild.attributes.length, 0, 'attributes');
+ assert_false(frag.childNodes[5].firstChild.hasChildNodes(), 'hasChildNodes()');
+ assert_true(frag.childNodes[5].firstChild instanceof HTMLElement, 'instanceof');
+}, document.title+', <rt>');
+test(function(){
+ assert_equals(frag.childNodes[6].namespaceURI, 'http://www.w3.org/1999/xhtml', 'namespaceURI');
+ assert_equals(frag.childNodes[6].localName, 'span', 'localName');
+ assert_equals(frag.childNodes[6].attributes.length, 1, 'attributes');
+ assert_equals(frag.childNodes[6].getAttributeNS('', 'title'), '', 'title attribute');
+ assert_false(frag.childNodes[6].hasChildNodes(), 'hasChildNodes()');
+ assert_true(frag.childNodes[6] instanceof HTMLElement, 'instanceof');
+}, document.title+', <v>');
+test(function(){
+ assert_equals(frag.childNodes[7].namespaceURI, 'http://www.w3.org/1999/xhtml', 'namespaceURI');
+ assert_equals(frag.childNodes[7].localName, 'span', 'localName');
+ assert_equals(frag.childNodes[7].attributes.length, 1, 'attributes');
+ assert_equals(frag.childNodes[7].getAttributeNS('', 'title'), 'a b', 'title attribute');
+ assert_false(frag.childNodes[7].hasChildNodes(), 'hasChildNodes()');
+ assert_true(frag.childNodes[7] instanceof HTMLElement, 'instanceof');
+}, document.title+', <v a b>');
+test(function(){
+ assert_equals(frag.childNodes[8].target, 'timestamp', 'target');
+ assert_equals(frag.childNodes[8].data, '00:00:00.500', 'data');
+ assert_true(frag.childNodes[8] instanceof ProcessingInstruction, 'instanceof');
+}, document.title+', <00:00:00.500>');
+test(function(){
+ assert_equals(frag.childNodes[9].data, 'x\0', 'data');
+ assert_true(frag.childNodes[9] instanceof Text, 'instanceof');
+}, document.title+', x\\0');
+</script>
diff --git a/tests/wpt/web-platform-tests/webvtt/webvtt-api-for-browsers/vttcue-interface/line.html b/tests/wpt/web-platform-tests/webvtt/webvtt-api-for-browsers/vttcue-interface/line.html
new file mode 100644
index 00000000000..ae0bda9fa36
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/webvtt-api-for-browsers/vttcue-interface/line.html
@@ -0,0 +1,62 @@
+<!doctype html>
+<title>VTTCue.line</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function(){
+ var video = document.createElement('video');
+ document.body.appendChild(video);
+ var c1 = new VTTCue(0, 1, 'text1');
+ assert_equals(c1.line, -1);
+ var track = document.createElement('track');
+ var t = track.track;
+ t.addCue(c1);
+ assert_equals(c1.line, -1);
+ video.appendChild(track);
+ assert_equals(c1.line, -1);
+ t.mode = 'showing';
+ assert_equals(c1.line, -1);
+ var c2 = new VTTCue(0, 1, 'text2');
+ var track2 = document.createElement('track');
+ var t2 = track2.track;
+ t2.addCue(c2);
+ assert_equals(c2.line, -1);
+ video.appendChild(track2);
+ t2.mode = 'showing';
+ assert_equals(c2.line, -2);
+ assert_equals(c1.line, -1);
+ c1.line = -5;
+ assert_equals(c1.line, -5);
+ assert_equals(c2.line, -2);
+ c1.line = 0;
+ c1.snapToLines = false;
+ assert_equals(c1.line, 0);
+ assert_equals(c2.line, -2);
+}, document.title+', script-created cue');
+
+var t_parsed = async_test(document.title+', parsed cue');
+t_parsed.step(function(){
+ var video = document.createElement('video');
+ document.body.appendChild(video);
+ var t = document.createElement('track');
+ t.onload = this.step_func(function(){
+ var c1 = t.track.cues[0];
+ var c2 = t.track.cues[1];
+ var c3 = t.track.cues[2];
+ assert_equals(c1.line, -1);
+ assert_equals(c2.line, 0);
+ assert_equals(c3.line, 0);
+
+ this.done();
+ });
+ t.onerror = this.step_func(function() {
+ assert_unreached('got error event');
+ });
+ t.src = 'data:text/vtt,'+encodeURIComponent('WEBVTT\n\n00:00:00.000 --> 00:00:00.001\ntest\n\n'+
+ '00:00:00.000 --> 00:00:00.001 line:0\ntest\n\n'+
+ '00:00:00.000 --> 00:00:00.001 line:0%\ntest');
+ t.track.mode = 'showing';
+ video.appendChild(t);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/webvtt/webvtt-api-for-browsers/vttcue-interface/snapToLines.html b/tests/wpt/web-platform-tests/webvtt/webvtt-api-for-browsers/vttcue-interface/snapToLines.html
new file mode 100644
index 00000000000..c28b9d064e2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/webvtt-api-for-browsers/vttcue-interface/snapToLines.html
@@ -0,0 +1,97 @@
+<!doctype html>
+<title>VTTCue.snapToLines</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+setup(function(){
+ window.video = document.createElement('video');
+ window.t1 = video.addTextTrack('subtitles');
+ document.body.appendChild(video);
+});
+test(function(){
+ var c1 = new VTTCue(0, 1, 'text1');
+ assert_true(c1.snapToLines);
+ c1.line = 101;
+ c1.snapToLines = false;
+ assert_false(c1.snapToLines);
+ c1.snapToLines = true;
+ assert_true(c1.snapToLines);
+ c1.line = -1;
+ c1.snapToLines = false;
+ assert_false(c1.snapToLines);
+ c1.snapToLines = true;
+ assert_true(c1.snapToLines);
+ c1.line = 0;
+ c1.snapToLines = false;
+ assert_false(c1.snapToLines);
+}, document.title+', script-created cue');
+
+var t_parsed = async_test(document.title+', parsed cue');
+t_parsed.step(function(){
+ var t = document.createElement('track');
+ t.onload = this.step_func(function(){
+ var c1 = t.track.cues[0];
+ assert_true(c1.snapToLines);
+ c1.line = 101;
+ c1.snapToLines = false;
+ assert_false(c1.snapToLines);
+ c1.snapToLines = true;
+ assert_true(c1.snapToLines);
+ c1.line = -1;
+ c1.snapToLines = false;
+ assert_false(c1.snapToLines);
+ c1.snapToLines = true;
+ assert_true(c1.snapToLines);
+ c1.line = 0;
+ c1.snapToLines = false;
+ assert_false(c1.snapToLines);
+
+ var c2 = t.track.cues[1];
+ assert_true(c2.snapToLines);
+ c2.line = 101;
+ c2.snapToLines = false;
+ assert_false(c2.snapToLines);
+ c2.snapToLines = true;
+ assert_true(c2.snapToLines);
+ c2.line = -1;
+ c2.snapToLines = false;
+ assert_false(c2.snapToLines);
+ c2.snapToLines = true;
+ assert_true(c2.snapToLines);
+ c2.line = 0;
+ c2.snapToLines = false;
+ assert_false(c2.snapToLines);
+
+ var c3 = t.track.cues[2];
+ assert_false(c3.snapToLines);
+ c3.snapToLines = false;
+ assert_false(c3.snapToLines);
+ c3.snapToLines = true;
+ assert_true(c3.snapToLines);
+ c3.line = 101;
+ c3.snapToLines = false;
+ assert_false(c3.snapToLines);
+ c3.snapToLines = true;
+ assert_true(c3.snapToLines);
+ c3.line = -1;
+ c3.snapToLines = false;
+ assert_false(c3.snapToLines);
+ c3.snapToLines = true;
+ assert_true(c3.snapToLines);
+ c3.line = 0;
+ c3.snapToLines = false;
+ assert_false(c3.snapToLines);
+
+ this.done();
+ });
+ t.onerror = this.step_func(function() {
+ assert_unreached('got error event');
+ });
+ t.src = 'data:text/vtt,'+encodeURIComponent('WEBVTT\n\n00:00:00.000 --> 00:00:00.001\ntest\n\n'+
+ '00:00:00.000 --> 00:00:00.001 line:0\ntest\n\n'+
+ '00:00:00.000 --> 00:00:00.001 line:0%\ntest');
+ t.track.mode = 'showing';
+ video.appendChild(t);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/webvtt/webvtt-api-for-browsers/vttcue-interface/text.html b/tests/wpt/web-platform-tests/webvtt/webvtt-api-for-browsers/vttcue-interface/text.html
new file mode 100644
index 00000000000..ec317f82851
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/webvtt-api-for-browsers/vttcue-interface/text.html
@@ -0,0 +1,38 @@
+<!doctype html>
+<title>VTTCue.text</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+setup(function(){
+ window.video = document.createElement('video');
+ window.t1 = video.addTextTrack('subtitles');
+ document.body.appendChild(video);
+});
+test(function(){
+ var c1 = new VTTCue(0, 1, 'text1\r\n\n\u0000');
+ assert_equals(c1.text, 'text1\r\n\n\u0000');
+ c1.text = c1.text;
+ assert_equals(c1.text, 'text1\r\n\n\u0000');
+ c1.text = null;
+ assert_equals(c1.text, 'null');
+}, document.title+', script-created cue');
+
+var t_parsed = async_test(document.title+', parsed cue');
+t_parsed.step(function(){
+ var t = document.createElement('track');
+ t.onload = this.step_func(function(){
+ var c = t.track.cues;
+ assert_equals(c[0].text, '');
+ assert_equals(c[1].text, 'test');
+ this.done();
+ });
+ t.onerror = this.step_func(function() {
+ assert_unreached('got error event');
+ });
+ t.src = 'data:text/vtt,'+encodeURIComponent('WEBVTT\n\n00:00:00.000 --> 00:00:00.001\n'+
+ '\n\nfoobar\n00:00:00.000 --> 00:00:00.001\ntest');
+ t.track.mode = 'showing';
+ video.appendChild(t);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/webvtt/webvtt-api-for-browsers/vttcue-interface/vertical.html b/tests/wpt/web-platform-tests/webvtt/webvtt-api-for-browsers/vttcue-interface/vertical.html
new file mode 100644
index 00000000000..56a35c23c5f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/webvtt-api-for-browsers/vttcue-interface/vertical.html
@@ -0,0 +1,54 @@
+<!doctype html>
+<title>VTTCue.vertical</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+setup(function(){
+ window.video = document.createElement('video');
+ window.t1 = video.addTextTrack('subtitles');
+ document.body.appendChild(video);
+});
+test(function(){
+ var video = document.createElement('video');
+ document.body.appendChild(video);
+ var c1 = new VTTCue(0, 1, 'text1');
+ assert_equals(c1.vertical, '');
+ var track = document.createElement('track');
+ var t = track.track;
+ t.addCue(c1);
+ assert_equals(c1.vertical, '');
+ video.appendChild(track);
+ assert_equals(c1.vertical, '');
+ t.mode = 'showing';
+ assert_equals(c1.vertical, '');
+ c1.vertical = 'rl';
+ assert_equals(c1.vertical, 'rl');
+ c1.vertical = 'lr';
+ assert_equals(c1.vertical, 'lr');
+ c1.vertical = 'rl\u0000';
+ assert_equals(c1.vertical, 'lr');
+}, document.title+', script-created cue');
+
+var t_parsed = async_test(document.title+', parsed cue');
+t_parsed.step(function(){
+ var t = document.createElement('track');
+ t.onload = this.step_func(function(){
+ var c1 = t.track.cues[0];
+ var c2 = t.track.cues[1];
+ var c3 = t.track.cues[2];
+ assert_equals(c1.vertical, '');
+ assert_equals(c2.vertical, 'rl');
+ assert_equals(c3.vertical, 'lr');
+ this.done();
+ });
+ t.onerror = this.step_func(function() {
+ assert_unreached('got error event');
+ });
+ t.src = 'data:text/vtt,'+encodeURIComponent('WEBVTT\n\n00:00:00.000 --> 00:00:00.001\ntest'+
+ '00:00:00.000 --> 00:00:00.001 vertical:rl\ntest\n\n'+
+ '00:00:00.000 --> 00:00:00.001 vertical:lr\ntest');
+ t.track.mode = 'showing';
+ video.appendChild(t);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-cue-text-parsing-rules/buildtests.py b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-cue-text-parsing-rules/buildtests.py
new file mode 100644
index 00000000000..bfef335a7d3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-cue-text-parsing-rules/buildtests.py
@@ -0,0 +1,67 @@
+#!/usr/bin/python
+
+import os
+import urllib
+import hashlib
+
+doctmpl = """<!doctype html>
+<title>WebVTT cue data parser test %s</title>
+<style>video { display:none }</style>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=/html/syntax/parsing/template.js></script>
+<script src=/html/syntax/parsing/common.js></script>
+<script src=../common.js></script>
+<div id=log></div>
+<script>
+runTests([
+%s
+]);
+</script>"""
+
+testobj = "{name:'%s', input:'%s', expected:'%s'}"
+
+def appendtest(tests, input, expected):
+ tests.append(testobj % (hashlib.sha1(input).hexdigest(), urllib.quote(input[:-1]), urllib.quote(expected[:-1])))
+
+files = os.listdir('dat/')
+for file in files:
+ if os.path.isdir('dat/'+file) or file[0] == ".":
+ continue
+ tests = []
+ input = ""
+ expected = ""
+ state = ""
+ f = open('dat/'+file)
+ while 1:
+ line = f.readline()
+ if not line:
+ if state != "":
+ appendtest(tests, input, expected)
+ input = ""
+ expected = ""
+ state = ""
+ break
+ if line[0] == "#":
+ state = line
+ if line == "#document-fragment\n":
+ expected = expected + line
+ elif state == "#data\n":
+ input = input + line
+ elif state == "#errors\n":
+ pass
+ elif state == "#document-fragment\n":
+ if line == "\n":
+ appendtest(tests, input, expected)
+ input = ""
+ expected = ""
+ state = ""
+ else:
+ expected = expected + line
+ else:
+ raise Exception("failed to parse file "+file+" line:"+line+" (state: "+state+")")
+ f.close()
+ barename = file.replace(".dat", "")
+ out = open('tests/'+barename+".html", "w")
+ out.write(doctmpl % (barename, ",\n".join(tests)))
+ out.close()
diff --git a/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-cue-text-parsing-rules/common.js b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-cue-text-parsing-rules/common.js
new file mode 100644
index 00000000000..543fe46556f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-cue-text-parsing-rules/common.js
@@ -0,0 +1,189 @@
+var namespaces = {
+ "html":"http://www.w3.org/1999/xhtml",
+ "mathml":"http://www.w3.org/1998/Math/MathML",
+ "svg":"http://www.w3.org/2000/svg",
+ "xlink":"http://www.w3.org/1999/xlink",
+ "xml":"http://www.w3.org/XML/1998/namespace",
+ "xmlns":"http://www.w3.org/2000/xmlns/"
+};
+
+var prefixes = {};
+for (var prefix in namespaces) {
+ if (namespaces.hasOwnProperty(prefix)) {
+ prefixes[namespaces[prefix]] = prefix;
+ }
+}
+prefixes[namespaces["mathml"]] = "math";
+
+function format(format_string) {
+ var insertions = Array.prototype.slice.call(arguments, 1);
+ var regexp = /%s/g;
+ var match_count = 0;
+ var rv = format_string.replace(regexp, function(match) {
+ var rv = insertions[match_count];
+ match_count++;
+ return rv;
+ });
+ return rv;
+}
+
+function test_serializer(element) {
+ //element.normalize();
+ var lines = [];
+ function serialize_element(element, indent) {
+ var indent_spaces = (new Array(indent)).join(" ");
+ switch(element.nodeType) {
+ case Node.DOCUMENT_TYPE_NODE:
+ if (element.name) {
+ if (element.publicId || element.systemId) {
+ var publicId = element.publicId ? element.publicId : "";
+ var systemId = element.systemId ? element.systemId : "";
+ lines.push(format("|%s<!DOCTYPE %s \"%s\" \"%s\">", indent_spaces,
+ element.name, publicId, systemId));
+ } else {
+ lines.push(format("|%s<!DOCTYPE %s>", indent_spaces,
+ element.name));
+ }
+ } else {
+ lines.push(format("|%s<!DOCTYPE >", indent_spaces));
+ }
+ break;
+ case Node.DOCUMENT_NODE:
+ lines.push("#document");
+ break;
+ case Node.DOCUMENT_FRAGMENT_NODE:
+ lines.push("#document-fragment");
+ break;
+ case Node.PROCESSING_INSTRUCTION_NODE:
+ lines.push(format("|%s<?%s %s>", indent_spaces, element.target, element.data));
+ break;
+ case Node.COMMENT_NODE:
+ lines.push(format("|%s<!-- %s -->", indent_spaces, element.nodeValue));
+ break;
+ case Node.TEXT_NODE:
+ lines.push(format("|%s\"%s\"", indent_spaces, element.nodeValue));
+ break;
+ case Node.ELEMENT_NODE:
+ if (element.getAttribute("data-skip") !== null) {
+ return;
+ }
+ if (element.namespaceURI !== null && element.namespaceURI !== namespaces.html) {
+ var name = format("%s %s", prefixes[element.namespaceURI],
+ element.localName);
+ } else {
+ var name = element.localName;
+ }
+ lines.push(format("|%s<%s>", indent_spaces, name));
+
+ var attributes = Array.prototype.map.call(
+ element.attributes,
+ function(attr) {
+ var name = (attr.namespaceURI ? prefixes[attr.namespaceURI] + " " : "") +
+ attr.localName;
+ return [name, attr.value];
+ });
+ attributes.sort(function (a, b) {
+ var x = a[0];
+ var y = b[0];
+ if (x === y) {
+ return 0;
+ }
+ return x > y ? 1 : -1;
+ });
+
+ attributes.forEach(
+ function(attr) {
+ var indent_spaces = (new Array(indent + 2)).join(" ");
+ lines.push(format("|%s%s=\"%s\"", indent_spaces, attr[0], attr[1]));
+ }
+ );
+ break;
+ }
+ indent += 2;
+ Array.prototype.forEach.call(element.childNodes,
+ function(node) {
+ serialize_element(node, indent);
+ });
+ }
+ serialize_element(element, 0);
+ return lines.join("\n");
+}
+
+function print_diffs(test_id, uri_encoded_input, expected, actual, container) {
+ container = container ? container : null;
+ if (actual) {
+ var diffs = mark_diffs(expected, actual);
+ var expected_text = diffs[0];
+ var actual_text = diffs[1];
+ } else {
+ var expected_text = expected;
+ var actual_text = "";
+ }
+
+ var tmpl = ["div", {"id":"${test_id}"},
+ ["h2", {}, "${test_id}"],
+ function(vars) {
+ if (vars.container !== null) {
+ return ["div", {"class":"container"},
+ ["h3", {}, "innerHTML Container"],
+ ["pre", {}, vars.container]];
+ } else {
+ return null;
+ }
+ },
+ ["div", {"id":"input_${test_id}"}, ["h3", {}, "Input"], ["pre", {},
+ ["code", {}, decodeURIComponent(uri_encoded_input)]]],
+ ["div", {"id":"expected_${test_id}"}, ["h3", {}, "Expected"],
+ ["pre", {}, ["code", {}, expected_text]]],
+ ["div", {"id":"actual_${test_id}"}, ["h3", {}, "Actual"],
+ ["pre", {}, ["code", {}, actual_text]]]
+ ];
+
+ var diff_dom = template.render(tmpl, {test_id:test_id, container:container});
+ document.body.appendChild(diff_dom);
+}
+
+function runTests(tests) {
+ tests.forEach(function(test){
+ var expected = decodeURIComponent(test.expected);
+ var t = async_test(document.title + ' - ' + test.name);
+ t.step(function(){
+ var video = document.createElement('video');
+ var track = document.createElement('track');
+ assert_true('src' in track, 'track not supported');
+ t.test_id = test.name;
+ t.url_encoded_input = test.input;
+ t.expected = expected;
+ track.src = 'data:text/vtt,'+encodeURIComponent('WEBVTT\n\n00:00.000 --> 00:01.000\n')+test.input;
+ track['default'] = true;
+ track.kind = 'subtitles';
+ track.onload = t.step_func(trackLoaded);
+ track.onerror = t.step_func(trackError);
+ video.appendChild(track);
+ document.body.appendChild(video);
+ });
+ });
+}
+
+function trackLoaded(e) {
+ var track = e.target;
+ setTimeout(removeElm, 0, track.parentNode);
+ var cue = track.track.cues[0];
+ var frag = cue.getCueAsHTML();
+ var got = test_serializer(frag);
+ if (got !== this.expected) {
+ print_diffs(this.test_id, this.url_encoded_input, this.expected, got);
+ }
+ assert_equals(got, this.expected);
+ this.done();
+}
+
+function trackError(e) {
+ setTimeout(removeElm, 0, e.target.parentNode);
+ assert_unreached('got error event');
+ this.done();
+}
+
+function removeElm(elm) {
+ document.body.removeChild(elm);
+}
diff --git a/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-cue-text-parsing-rules/dat/entities.dat b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-cue-text-parsing-rules/dat/entities.dat
new file mode 100644
index 00000000000..cddcb27ffaa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-cue-text-parsing-rules/dat/entities.dat
@@ -0,0 +1,114 @@
+#data
+&
+#errors
+#document-fragment
+| "&"
+
+#data
+&amp
+#errors
+#document-fragment
+| "&amp"
+
+#data
+&amp;
+#errors
+#document-fragment
+| "&"
+
+#data
+&AMP;
+#errors
+#document-fragment
+| "&AMP;"
+
+#data
+&lt;
+#errors
+#document-fragment
+| "<"
+
+#data
+&gt;
+#errors
+#document-fragment
+| ">"
+
+#data
+a&lrm;b
+#errors
+#document-fragment
+| "a‎b"
+
+#data
+a&rlm;b
+#errors
+#document-fragment
+| "a‏b"
+
+#data
+&quot;
+#errors
+#document-fragment
+| "&quot;"
+
+#data
+&nbsp;
+#errors
+#document-fragment
+| " "
+
+#data
+&copy;
+#errors
+#document-fragment
+| "&copy;"
+
+#data
+&&
+#errors
+#document-fragment
+| "&&"
+
+#data
+&1
+#errors
+#document-fragment
+| "&1"
+
+#data
+&1;
+#errors
+#document-fragment
+| "&1;"
+
+#data
+&<
+#errors
+#document-fragment
+| "&"
+
+#data
+&<c
+#errors
+#document-fragment
+| "&"
+| <span>
+
+#data
+&#32;
+#errors
+#document-fragment
+| "&#32;"
+
+#data
+&#x20;
+#errors
+#document-fragment
+| "&#x20;"
+
+#data
+&;
+#errors
+#document-fragment
+| "&;"
diff --git a/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-cue-text-parsing-rules/dat/tags.dat b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-cue-text-parsing-rules/dat/tags.dat
new file mode 100644
index 00000000000..425af32e281
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-cue-text-parsing-rules/dat/tags.dat
@@ -0,0 +1,56 @@
+#data
+<
+#errors
+#document-fragment
+
+#data
+<<
+#errors
+#document-fragment
+
+#data
+<
+#errors
+#document-fragment
+
+#data
+<
+
+#errors
+#document-fragment
+
+#data
+<
+#errors
+#document-fragment
+
+#data
+<.
+#errors
+#document-fragment
+
+#data
+<c.
+#errors
+#document-fragment
+| <span>
+
+#data
+</
+#errors
+#document-fragment
+
+#data
+<c></>x
+#errors
+#document-fragment
+| <span>
+| "x"
+
+#data
+<c></
+c>x
+#errors
+#document-fragment
+| <span>
+| "x"
diff --git a/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-cue-text-parsing-rules/dat/timestamps.dat b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-cue-text-parsing-rules/dat/timestamps.dat
new file mode 100644
index 00000000000..ba0f686ae95
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-cue-text-parsing-rules/dat/timestamps.dat
@@ -0,0 +1,58 @@
+#data
+<0
+#errors
+#document-fragment
+
+#data
+<0.500
+#errors
+#document-fragment
+
+#data
+<0:00.500
+#errors
+#document-fragment
+
+#data
+<00:00.500
+#errors
+#document-fragment
+| <?timestamp 00:00:00.500>
+
+#data
+<00:00:00.500
+#errors
+#document-fragment
+| <?timestamp 00:00:00.500>
+
+#data
+test<00:00:00.500>test
+#errors
+#document-fragment
+| "test"
+| <?timestamp 00:00:00.500>
+| "test"
+
+#data
+test<01:00:00.000>test
+#errors
+#document-fragment
+| "test"
+| <?timestamp 01:00:00.000>
+| "test"
+
+#data
+test<10:00:00.000>test
+#errors
+#document-fragment
+| "test"
+| <?timestamp 10:00:00.000>
+| "test"
+
+#data
+test<100:00:00.000>test
+#errors
+#document-fragment
+| "test"
+| <?timestamp 100:00:00.000>
+| "test"
diff --git a/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-cue-text-parsing-rules/dat/tree-building.dat b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-cue-text-parsing-rules/dat/tree-building.dat
new file mode 100644
index 00000000000..08410d1ffad
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-cue-text-parsing-rules/dat/tree-building.dat
@@ -0,0 +1,171 @@
+#data
+test
+#errors
+#document-fragment
+| "test"
+
+#data
+<c>test
+#errors
+#document-fragment
+| <span>
+| "test"
+
+#data
+<i>test
+#errors
+#document-fragment
+| <i>
+| "test"
+
+#data
+<b>test
+#errors
+#document-fragment
+| <b>
+| "test"
+
+#data
+<u>test
+#errors
+#document-fragment
+| <u>
+| "test"
+
+#data
+<ruby>test
+#errors
+#document-fragment
+| <ruby>
+| "test"
+
+#data
+<rt>test
+#errors
+#document-fragment
+| "test"
+
+#data
+<ruby>test<rt>test
+#errors
+#document-fragment
+| <ruby>
+| "test"
+| <rt>
+| "test"
+
+#data
+<ruby>test<rt>test</rt>test
+#errors
+#document-fragment
+| <ruby>
+| "test"
+| <rt>
+| "test"
+| "test"
+
+#data
+<ruby>test<rt>test</rt></ruby>test
+#errors
+#document-fragment
+| <ruby>
+| "test"
+| <rt>
+| "test"
+| "test"
+
+#data
+<ruby>test<rt>test</ruby>test
+#errors
+#document-fragment
+| <ruby>
+| "test"
+| <rt>
+| "test"
+| "test"
+
+#data
+<ruby>test<rt><b>test</rt></ruby>test
+#errors
+#document-fragment
+| <ruby>
+| "test"
+| <rt>
+| <b>
+| "test"
+| "test"
+
+#data
+<ruby>test<rt><b>test</ruby>test
+#errors
+#document-fragment
+| <ruby>
+| "test"
+| <rt>
+| <b>
+| "test"
+| "test"
+
+#data
+<ruby>test<rt><b>test</rt></ruby></b>test
+#errors
+#document-fragment
+| <ruby>
+| "test"
+| <rt>
+| <b>
+| "test"
+| "test"
+
+#data
+<ruby>test<rt><b>test</rt></b></ruby>test
+#errors
+#document-fragment
+| <ruby>
+| "test"
+| <rt>
+| <b>
+| "test"
+| "test"
+
+#data
+<v>test
+#errors
+#document-fragment
+| <span>
+| title=""
+| "test"
+
+#data
+<v a>test
+#errors
+#document-fragment
+| <span>
+| title="a"
+| "test"
+
+#data
+<v a b>test
+#errors
+#document-fragment
+| <span>
+| title="a b"
+| "test"
+
+#data
+<v.a>test
+#errors
+#document-fragment
+| <span>
+| class="a"
+| title=""
+| "test"
+
+#data
+<v.a.b>test
+#errors
+#document-fragment
+| <span>
+| class="a b"
+| title=""
+| "test"
diff --git a/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-cue-text-parsing-rules/tests/entities.html b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-cue-text-parsing-rules/tests/entities.html
new file mode 100644
index 00000000000..2568258a266
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-cue-text-parsing-rules/tests/entities.html
@@ -0,0 +1,32 @@
+<!doctype html>
+<title>WebVTT cue data parser test entities</title>
+<style>video { display:none }</style>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=/html/syntax/parsing/template.js></script>
+<script src=/html/syntax/parsing/common.js></script>
+<script src=../common.js></script>
+<div id=log></div>
+<script>
+runTests([
+{name:'3686fc0cdc60dc536e75df054b0bd372273db2cc', input:'%26', expected:'%23document-fragment%0A%7C%20%22%26%22'},
+{name:'f1869f6e2853635eec81cc3afa3e2b8148ccbdc0', input:'%26amp', expected:'%23document-fragment%0A%7C%20%22%26amp%22'},
+{name:'92d76530d723b6b4e4ef8280c01cf1c80f9bebdb', input:'%26amp%3B', expected:'%23document-fragment%0A%7C%20%22%26%22'},
+{name:'261cd4e9df4a12535b66a0c39e9635aab2bb19aa', input:'%26AMP%3B', expected:'%23document-fragment%0A%7C%20%22%26AMP%3B%22'},
+{name:'1a2269cdb73bf97ec6a99b0edabfe646c471b67e', input:'%26lt%3B', expected:'%23document-fragment%0A%7C%20%22%3C%22'},
+{name:'44ceb90884cceeeccb4f7024e3598f7dc5ceebfa', input:'%26gt%3B', expected:'%23document-fragment%0A%7C%20%22%3E%22'},
+{name:'05def72af03fc2b1617da950d871b9fd0ba20e5a', input:'a%26lrm%3Bb', expected:'%23document-fragment%0A%7C%20%22a%E2%80%8Eb%22'},
+{name:'da999a55445eca43aa41e039ec439c1a812db297', input:'a%26rlm%3Bb', expected:'%23document-fragment%0A%7C%20%22a%E2%80%8Fb%22'},
+{name:'0fd9e3823b62c028c1d50e35b1f3ee3df02a62eb', input:'%26quot%3B', expected:'%23document-fragment%0A%7C%20%22%26quot%3B%22'},
+{name:'e7387003fbacb22b706796c98b781eb4ebf5ff85', input:'%26nbsp%3B', expected:'%23document-fragment%0A%7C%20%22%C2%A0%22'},
+{name:'216cd0e914b9f2ccd04eff6d02a0b1ce24441d95', input:'%26copy%3B', expected:'%23document-fragment%0A%7C%20%22%26copy%3B%22'},
+{name:'2cdf20980d17a5d077299215e6a7e97f3c6b07e2', input:'%26%26', expected:'%23document-fragment%0A%7C%20%22%26%26%22'},
+{name:'83f4500c0bd8598480713997a041d8f70fd3f11e', input:'%261', expected:'%23document-fragment%0A%7C%20%22%261%22'},
+{name:'2c6b2ba38a08eca45370f28a5b7df2aa463fb3dc', input:'%261%3B', expected:'%23document-fragment%0A%7C%20%22%261%3B%22'},
+{name:'f4bb977c0a06851bdd19260c035a766c5c8ea093', input:'%26%3C', expected:'%23document-fragment%0A%7C%20%22%26%22'},
+{name:'b1fff1ac42688d16e00f6c758d84e5152e39702d', input:'%26%3Cc', expected:'%23document-fragment%0A%7C%20%22%26%22%0A%7C%20%3Cspan%3E'},
+{name:'bd68f6beda2c2264e61dff7359c1ad48bc0a9934', input:'%26%2332%3B', expected:'%23document-fragment%0A%7C%20%22%26%2332%3B%22'},
+{name:'5b77a0be23453dfe6eea59d43bb0708f89e1df82', input:'%26%23x20%3B', expected:'%23document-fragment%0A%7C%20%22%26%23x20%3B%22'},
+{name:'87986551b0e6180cb279f2aa4cdddf77daa90c11', input:'%26%3B', expected:'%23document-fragment%0A%7C%20%22%26%3B%22'}
+]);
+</script>
diff --git a/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-cue-text-parsing-rules/tests/tags.html b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-cue-text-parsing-rules/tests/tags.html
new file mode 100644
index 00000000000..d42478dc988
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-cue-text-parsing-rules/tests/tags.html
@@ -0,0 +1,23 @@
+<!doctype html>
+<title>WebVTT cue data parser test tags</title>
+<style>video { display:none }</style>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=/html/syntax/parsing/template.js></script>
+<script src=/html/syntax/parsing/common.js></script>
+<script src=../common.js></script>
+<div id=log></div>
+<script>
+runTests([
+{name:'d49e42f7582c6f00b2569f2d14629611c0c6b0e6', input:'%3C', expected:'%23document-fragment'},
+{name:'9dd187edd10c907e6b92148fd82940e401dbe79f', input:'%3C%3C', expected:'%23document-fragment'},
+{name:'2d2c4333983e23a4962083e8120e5d42c839f77b', input:'%3C%09', expected:'%23document-fragment'},
+{name:'94f898df44b470e2d05d74c6816fd908e55c9fdf', input:'%3C%0A', expected:'%23document-fragment'},
+{name:'2fdc1b84ba41ec98833851e80781df1fbe72182f', input:'%3C%20', expected:'%23document-fragment'},
+{name:'487690a6f5da4666f9caaf3a3ecc10992aca1414', input:'%3C.', expected:'%23document-fragment'},
+{name:'0d7df935b172f2a1b357b94596d68f2443f30f8b', input:'%3Cc.', expected:'%23document-fragment%0A%7C%20%3Cspan%3E'},
+{name:'cd1d6dd274e03ae8fc56bc4ef163998d9ff24496', input:'%3C/', expected:'%23document-fragment'},
+{name:'fca1a11d42b735453117f42456360e88082a3fd7', input:'%3Cc%3E%3C/%3Ex', expected:'%23document-fragment%0A%7C%20%3Cspan%3E%0A%7C%20%20%20%22x%22'},
+{name:'fe3b6277edf5c2f84e7a6779eddd0cac30552bca', input:'%3Cc%3E%3C/%0Ac%3Ex', expected:'%23document-fragment%0A%7C%20%3Cspan%3E%0A%7C%20%20%20%22x%22'}
+]);
+</script>
diff --git a/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-cue-text-parsing-rules/tests/timestamps.html b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-cue-text-parsing-rules/tests/timestamps.html
new file mode 100644
index 00000000000..bc19e2d8e05
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-cue-text-parsing-rules/tests/timestamps.html
@@ -0,0 +1,22 @@
+<!doctype html>
+<title>WebVTT cue data parser test timestamps</title>
+<style>video { display:none }</style>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=/html/syntax/parsing/template.js></script>
+<script src=/html/syntax/parsing/common.js></script>
+<script src=../common.js></script>
+<div id=log></div>
+<script>
+runTests([
+{name:'54c245f3fbe7a3e25398b13971d44f2bb3a5f947', input:'%3C0', expected:'%23document-fragment'},
+{name:'5e190a1b4541fcb10e403af111c14ef152fecb0d', input:'%3C0.500', expected:'%23document-fragment'},
+{name:'92b97d3497836259e0b9305e27f2b91ea1dc9b31', input:'%3C0%3A00.500', expected:'%23document-fragment'},
+{name:'47fa4306a695161da88533d456ce94829e53b13d', input:'%3C00%3A00.500', expected:'%23document-fragment%0A%7C%20%3C%3Ftimestamp%2000%3A00%3A00.500%3E'},
+{name:'c1036a4322c1852e02e5a1843a9a81dfca6d7af3', input:'%3C00%3A00%3A00.500', expected:'%23document-fragment%0A%7C%20%3C%3Ftimestamp%2000%3A00%3A00.500%3E'},
+{name:'70ec34d828ca661a583c651207becb968bb41653', input:'test%3C00%3A00%3A00.500%3Etest', expected:'%23document-fragment%0A%7C%20%22test%22%0A%7C%20%3C%3Ftimestamp%2000%3A00%3A00.500%3E%0A%7C%20%22test%22'},
+{name:'66ba641ff047a226fa60fe867fd2479d40f3ff0f', input:'test%3C01%3A00%3A00.000%3Etest', expected:'%23document-fragment%0A%7C%20%22test%22%0A%7C%20%3C%3Ftimestamp%2001%3A00%3A00.000%3E%0A%7C%20%22test%22'},
+{name:'398e8da1aaaf392739ca72057fef58bd5333f74d', input:'test%3C10%3A00%3A00.000%3Etest', expected:'%23document-fragment%0A%7C%20%22test%22%0A%7C%20%3C%3Ftimestamp%2010%3A00%3A00.000%3E%0A%7C%20%22test%22'},
+{name:'391fce67644cf4dd9967e1436d1449ef5baf675f', input:'test%3C100%3A00%3A00.000%3Etest', expected:'%23document-fragment%0A%7C%20%22test%22%0A%7C%20%3C%3Ftimestamp%20100%3A00%3A00.000%3E%0A%7C%20%22test%22'}
+]);
+</script>
diff --git a/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-cue-text-parsing-rules/tests/tree-building.html b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-cue-text-parsing-rules/tests/tree-building.html
new file mode 100644
index 00000000000..98062f8303e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-cue-text-parsing-rules/tests/tree-building.html
@@ -0,0 +1,33 @@
+<!doctype html>
+<title>WebVTT cue data parser test tree-building</title>
+<style>video { display:none }</style>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=/html/syntax/parsing/template.js></script>
+<script src=/html/syntax/parsing/common.js></script>
+<script src=../common.js></script>
+<div id=log></div>
+<script>
+runTests([
+{name:'4e1243bd22c66e76c2ba9eddc1f91394e57f9f83', input:'test', expected:'%23document-fragment%0A%7C%20%22test%22'},
+{name:'6ceded63b53eeab3681a0fc540e959ca88f7dce9', input:'%3Cc%3Etest', expected:'%23document-fragment%0A%7C%20%3Cspan%3E%0A%7C%20%20%20%22test%22'},
+{name:'71de37451e7d5524eacc8a190d21cd64c4304e14', input:'%3Ci%3Etest', expected:'%23document-fragment%0A%7C%20%3Ci%3E%0A%7C%20%20%20%22test%22'},
+{name:'985284b688a09f1f55e3c9aab49d7e4ca11f870a', input:'%3Cb%3Etest', expected:'%23document-fragment%0A%7C%20%3Cb%3E%0A%7C%20%20%20%22test%22'},
+{name:'fa6993eaa94404648d8b52e2830e53369404fdcb', input:'%3Cu%3Etest', expected:'%23document-fragment%0A%7C%20%3Cu%3E%0A%7C%20%20%20%22test%22'},
+{name:'e4d351e1a6b40a7dace801b722efaa200c4895f2', input:'%3Cruby%3Etest', expected:'%23document-fragment%0A%7C%20%3Cruby%3E%0A%7C%20%20%20%22test%22'},
+{name:'68e1d0376f827ebe0c047751a2067594ff41b612', input:'%3Crt%3Etest', expected:'%23document-fragment%0A%7C%20%22test%22'},
+{name:'2564487cfc7e317428fb437ef8de8de4f4963426', input:'%3Cruby%3Etest%3Crt%3Etest', expected:'%23document-fragment%0A%7C%20%3Cruby%3E%0A%7C%20%20%20%22test%22%0A%7C%20%20%20%3Crt%3E%0A%7C%20%20%20%20%20%22test%22'},
+{name:'9b1902c975558eeaff4afbaf0a6dc100e1978769', input:'%3Cruby%3Etest%3Crt%3Etest%3C/rt%3Etest', expected:'%23document-fragment%0A%7C%20%3Cruby%3E%0A%7C%20%20%20%22test%22%0A%7C%20%20%20%3Crt%3E%0A%7C%20%20%20%20%20%22test%22%0A%7C%20%20%20%22test%22'},
+{name:'119c596ea09649d3bd03934485e3067e89377412', input:'%3Cruby%3Etest%3Crt%3Etest%3C/rt%3E%3C/ruby%3Etest', expected:'%23document-fragment%0A%7C%20%3Cruby%3E%0A%7C%20%20%20%22test%22%0A%7C%20%20%20%3Crt%3E%0A%7C%20%20%20%20%20%22test%22%0A%7C%20%22test%22'},
+{name:'c94512b045699cb72f730e46b2a0a3bed2c939f9', input:'%3Cruby%3Etest%3Crt%3Etest%3C/ruby%3Etest', expected:'%23document-fragment%0A%7C%20%3Cruby%3E%0A%7C%20%20%20%22test%22%0A%7C%20%20%20%3Crt%3E%0A%7C%20%20%20%20%20%22test%22%0A%7C%20%22test%22'},
+{name:'325c1e590e74f1ff33ca5b4838c04cf6b6dd71ba', input:'%3Cruby%3Etest%3Crt%3E%3Cb%3Etest%3C/rt%3E%3C/ruby%3Etest', expected:'%23document-fragment%0A%7C%20%3Cruby%3E%0A%7C%20%20%20%22test%22%0A%7C%20%20%20%3Crt%3E%0A%7C%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%22test%22%0A%7C%20%20%20%20%20%20%20%22test%22'},
+{name:'92847ed2694c9639ba96f4cc61e2215362a74904', input:'%3Cruby%3Etest%3Crt%3E%3Cb%3Etest%3C/ruby%3Etest', expected:'%23document-fragment%0A%7C%20%3Cruby%3E%0A%7C%20%20%20%22test%22%0A%7C%20%20%20%3Crt%3E%0A%7C%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%22test%22%0A%7C%20%20%20%20%20%20%20%22test%22'},
+{name:'c0da62d1c8716ca544c96799f06ac7e4664500fb', input:'%3Cruby%3Etest%3Crt%3E%3Cb%3Etest%3C/rt%3E%3C/ruby%3E%3C/b%3Etest', expected:'%23document-fragment%0A%7C%20%3Cruby%3E%0A%7C%20%20%20%22test%22%0A%7C%20%20%20%3Crt%3E%0A%7C%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%22test%22%0A%7C%20%20%20%20%20%22test%22'},
+{name:'b85bd616672eba0591718182ef32e3307d223bb0', input:'%3Cruby%3Etest%3Crt%3E%3Cb%3Etest%3C/rt%3E%3C/b%3E%3C/ruby%3Etest', expected:'%23document-fragment%0A%7C%20%3Cruby%3E%0A%7C%20%20%20%22test%22%0A%7C%20%20%20%3Crt%3E%0A%7C%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%22test%22%0A%7C%20%22test%22'},
+{name:'ab2024b4e65ed64a751adbe8aae1e84ee61bf3e6', input:'%3Cv%3Etest', expected:'%23document-fragment%0A%7C%20%3Cspan%3E%0A%7C%20%20%20title%3D%22%22%0A%7C%20%20%20%22test%22'},
+{name:'10f4823ffb17c71654c4602bc45c58300e3ecbcc', input:'%3Cv%20a%3Etest', expected:'%23document-fragment%0A%7C%20%3Cspan%3E%0A%7C%20%20%20title%3D%22a%22%0A%7C%20%20%20%22test%22'},
+{name:'909924ef392fb20c9526acfa4f18f891eda61a0c', input:'%3Cv%20a%20b%3Etest', expected:'%23document-fragment%0A%7C%20%3Cspan%3E%0A%7C%20%20%20title%3D%22a%20b%22%0A%7C%20%20%20%22test%22'},
+{name:'e5ca35cc29404efc0ebd58aa5f6efefc86fc5287', input:'%3Cv.a%3Etest', expected:'%23document-fragment%0A%7C%20%3Cspan%3E%0A%7C%20%20%20class%3D%22a%22%0A%7C%20%20%20title%3D%22%22%0A%7C%20%20%20%22test%22'},
+{name:'e535c486dac7dc571463b150adc55fd841bc3008', input:'%3Cv.a.b%3Etest', expected:'%23document-fragment%0A%7C%20%3Cspan%3E%0A%7C%20%20%20class%3D%22a%20b%22%0A%7C%20%20%20title%3D%22%22%0A%7C%20%20%20%22test%22'}
+]);
+</script>
diff --git a/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/001.html b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/001.html
new file mode 100644
index 00000000000..8baa66549c2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/001.html
@@ -0,0 +1,96 @@
+<!doctype html>
+<title>WebVTT parser tests</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+setup({explicit_done: true});
+var files = [];
+var path = 'support/';
+var cueDefaults = {
+"id":"",
+"startTime":0,
+"endTime":1,
+"pauseOnExit":false,
+//"vertical":"", (not supported)
+"snapToLines":true,
+"line":-1,
+"position":50,
+"size":100,
+"align":"middle"
+}
+var cueCounts;
+(function(){
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', path+'cue-counts.json', true);
+ xhr.onreadystatechange = function() {
+ if (xhr.readyState == 4) {
+ cueCounts = JSON.parse(xhr.responseText);
+ for (var file in cueCounts) {
+ files.push(file);
+ }
+ startTests();
+ }
+ }
+ xhr.send();
+})();
+
+function checkProps(cue, exp, i) {
+ for (var prop in cueDefaults) {
+ if (!(prop in exp))
+ exp[prop] = cueDefaults[prop];
+ assert_equals(cue[prop], exp[prop], prop + ' (cue '+(i+1)+')');
+ }
+}
+
+function startTests() {
+ files.forEach(function(file) {
+ var t = async_test(document.title+', '+file);
+ t.step(function(){
+ var video = document.createElement('video');
+ var track = document.createElement('track');
+ assert_true('src' in track, 'track element not supported');
+ track.src = path + file;
+ track['default'] = true;
+ track.kind = 'subtitles';
+ track.onload = this.step_func(trackLoaded);
+ track.onerror = this.step_func(trackError);
+ video.appendChild(track);
+ document.body.appendChild(video);
+ });
+ });
+ done();
+}
+
+function trackLoaded(e) {
+ var track = e.target;
+ var video = track.parentNode;
+ setTimeout(removeElm, 0, video);
+ var cues = video.textTracks[0].cues;
+ var file = track.src.substr(track.src.lastIndexOf('/') + 1);
+ assert_equals(cues.length, cueCounts[file], 'number of cues');
+ var expected;
+ var cue;
+ for (var i = 0; i < cues.length; ++i) {
+ cue = cues[i];
+ expected = JSON.parse(cue.text);
+ assert_not_equals(expected, 'FAIL', 'cue '+(i+1)+' should have been dropped');
+ checkProps(cue, expected, i);
+ }
+ this.done();
+}
+
+function trackError(e) {
+ var track = e.target;
+ var video = track.parentNode;
+ setTimeout(removeElm, 0, video);
+ var file = track.src.substr(track.src.lastIndexOf('/') + 1);
+ assert_equals('error', cueCounts[file], 'got unexpected error event');
+ this.done();
+}
+
+function removeElm(elm) {
+ document.body.removeChild(elm);
+}
+
+</script>
diff --git a/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/arrows.vtt b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/arrows.vtt
new file mode 100644
index 00000000000..057cede2914
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/arrows.vtt
@@ -0,0 +1,19 @@
+WEBVTT
+
+-->
+00:00:00.000 --> 00:00:01.000
+{}
+foo-->
+00:00:00.000 --> 00:00:01.000
+{}
+-->foo
+00:00:00.000 --> 00:00:01.000
+{}
+--->
+00:00:00.000 --> 00:00:01.000
+{}
+-->-->
+00:00:00.000 --> 00:00:01.000
+{}
+00:00:00.000 --> 00:00:01.000
+{}
diff --git a/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/cue-counts.json b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/cue-counts.json
new file mode 100644
index 00000000000..7fcf35b6bd5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/cue-counts.json
@@ -0,0 +1,36 @@
+{"settings-vertical.vtt":6,
+"settings-size.vtt":12,
+"settings-position.vtt":13,
+"settings-multiple.vtt":2,
+"settings-line.vtt":29,
+"settings-align.vtt":9,
+"signature-bom.vtt":0,
+"signature-space.vtt":0,
+"signature-space-no-newline.vtt":0,
+"signature-tab.vtt":0,
+"signature-tab-no-newline.vtt":0,
+"signature-timings.vtt":0,
+"signature-two-boms.vtt":"error",
+"signature-lowercase.vtt":"error",
+"signature-too-short.vtt":"error",
+"signature-websrt.vtt":"error",
+"signature-formfeed.vtt":"error",
+"signature-null.vtt":"error",
+"signature-no-newline.vtt":0,
+"no-signature.vtt":"error",
+"nulls.vtt":7,
+"header-garbage.vtt":1,
+"header-timings.vtt":1,
+"header-space.vtt":1,
+"header-tab.vtt":1,
+"ids.vtt":5,
+"arrows.vtt":6,
+"space-chars.vtt":3,
+"timings-garbage.vtt":0,
+"timings-too-short.vtt":2,
+"timings-too-long.vtt":2,
+"newlines.vtt":4,
+"omitted-hours.vtt":3,
+"timings-60.vtt":2,
+"timings-negative.vtt":4
+}
diff --git a/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/header-garbage.vtt b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/header-garbage.vtt
new file mode 100644
index 00000000000..5935db50f5b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/header-garbage.vtt
@@ -0,0 +1,5 @@
+WEBVTT
+foobar
+
+00:00:00.000 --> 00:00:01.000
+{} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/header-space.vtt b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/header-space.vtt
new file mode 100644
index 00000000000..62a7426381b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/header-space.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:01.000
+{}
diff --git a/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/header-tab.vtt b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/header-tab.vtt
new file mode 100644
index 00000000000..f8eac7084a8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/header-tab.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:01.000
+{}
diff --git a/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/header-timings.vtt b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/header-timings.vtt
new file mode 100644
index 00000000000..bd084debc9d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/header-timings.vtt
@@ -0,0 +1,3 @@
+WEBVTT
+00:00:00.000 --> 00:00:01.000
+{} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/ids.vtt b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/ids.vtt
new file mode 100644
index 00000000000..ea335ee9eb5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/ids.vtt
@@ -0,0 +1,21 @@
+WEBVTT
+
+ leading space
+00:00:00.000 --> 00:00:01.000
+{"id":" leading space"}
+
+trailing space
+00:00:00.000 --> 00:00:01.000
+{"id":"trailing space "}
+
+-- >
+00:00:00.000 --> 00:00:01.000
+{"id":"-- >"}
+
+->
+00:00:00.000 --> 00:00:01.000
+{"id":"->"}
+
+
+00:00:00.000 --> 00:00:01.000
+{"id":" "} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/newlines.vtt b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/newlines.vtt
new file mode 100644
index 00000000000..ee2f00804a7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/newlines.vtt
@@ -0,0 +1,12 @@
+WEBVTT cr 00:00:00.000 --> 00:00:01.000 {"id":"cr"}
+
+lf
+00:00:00.000 --> 00:00:01.000
+{"id":"lf"}
+
+crlf
+00:00:00.000 --> 00:00:01.000
+{"id":"crlf"}
+ lfcr 00:00:00.000 --> 00:00:01.000
+{"id":"lfcr"}
+ \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/no-signature.vtt b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/no-signature.vtt
new file mode 100644
index 00000000000..44ad480844f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/no-signature.vtt
@@ -0,0 +1,2 @@
+00:00:00.000 --> 00:00:01.000
+"FAIL"
diff --git a/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/nulls.vtt b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/nulls.vtt
new file mode 100644
index 00000000000..85669c265d8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/nulls.vtt
Binary files differ
diff --git a/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/omitted-hours.vtt b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/omitted-hours.vtt
new file mode 100644
index 00000000000..3222dea372e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/omitted-hours.vtt
@@ -0,0 +1,10 @@
+WEBVTT
+
+00:00.000 --> 00:00:01.000
+{}
+
+00:00:00.000 --> 00:01.000
+{}
+
+00:00.000 --> 00:01.000
+{}
diff --git a/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/settings-align.vtt b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/settings-align.vtt
new file mode 100644
index 00000000000..a601bbbdcd5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/settings-align.vtt
@@ -0,0 +1,28 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:01.000 align:start
+{"align":"start"}
+
+00:00:00.000 --> 00:00:01.000 align:middle
+{"align":"middle"}
+
+00:00:00.000 --> 00:00:01.000 align:end
+{"align":"end"}
+
+00:00:00.000 --> 00:00:01.000 align:start align:end
+{"align":"end"}
+
+00:00:00.000 --> 00:00:01.000 align:end align:MIDDLE
+{"align":"end"}
+
+00:00:00.000 --> 00:00:01.000 align:end align: middle
+{"align":"end"}
+
+00:00:00.000 --> 00:00:01.000 align:end align:
+{"align":"end"}
+
+00:00:00.000 --> 00:00:01.000 align:end align
+{"align":"end"}
+
+00:00:00.000 --> 00:00:01.000 align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:middle
+{"align":"middle"} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/settings-line.vtt b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/settings-line.vtt
new file mode 100644
index 00000000000..e95f3282cdd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/settings-line.vtt
@@ -0,0 +1,88 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:01.000 line:-1
+{"line":-1}
+
+00:00:00.000 --> 00:00:01.000 line:0
+{"line":0}
+
+00:00:00.000 --> 00:00:01.000 line:-0
+{"line":0}
+
+00:00:00.000 --> 00:00:01.000 line:1
+{"line":1}
+
+00:00:00.000 --> 00:00:01.000 line:100
+{"line":100}
+
+00:00:00.000 --> 00:00:01.000 line:101
+{"line":101}
+
+00:00:00.000 --> 00:00:01.000 line:65536
+{"line":65536}
+
+00:00:00.000 --> 00:00:01.000 line:4294967296
+{"line":2147483647}
+
+00:00:00.000 --> 00:00:01.000 line:18446744073709552000
+{"line":2147483647}
+
+00:00:00.000 --> 00:00:01.000 line:10000000000000000000000000000000000
+{"line":2147483647}
+
+00:00:00.000 --> 00:00:01.000 line:65536%
+{}
+
+00:00:00.000 --> 00:00:01.000 line:4294967296%
+{}
+
+00:00:00.000 --> 00:00:01.000 line:18446744073709552000%
+{}
+
+00:00:00.000 --> 00:00:01.000 line:10000000000000000000000000000000000%
+{}
+
+00:00:00.000 --> 00:00:01.000 line:1.5
+{}
+
+00:00:00.000 --> 00:00:01.000 line:0%
+{"snapToLines":false, "line":0}
+
+00:00:00.000 --> 00:00:01.000 line:-0%
+{}
+
+00:00:00.000 --> 00:00:01.000 line:101%
+{}
+
+00:00:00.000 --> 00:00:01.000 line:100%
+{"snapToLines":false, "line":100}
+
+00:00:00.000 --> 00:00:01.000 line:1%-
+{}
+
+00:00:00.000 --> 00:00:01.000 line:1-
+{}
+
+00:00:00.000 --> 00:00:01.000 line:%1
+{}
+
+00:00:00.000 --> 00:00:01.000 line:1%%
+{}
+
+00:00:00.000 --> 00:00:01.000 line:00%
+{"snapToLines":false, "line":0}
+
+00:00:00.000 --> 00:00:01.000 line:0%0
+{}
+
+00:00:00.000 --> 00:00:01.000 line: 0%
+{}
+
+00:00:00.000 --> 00:00:01.000 line:0%x
+{}
+
+00:00:00.000 --> 00:00:01.000 line:-
+{}
+
+00:00:00.000 --> 00:00:01.000 line:%
+{} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/settings-multiple.vtt b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/settings-multiple.vtt
new file mode 100644
index 00000000000..bd078ff9ad3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/settings-multiple.vtt
@@ -0,0 +1,16 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:01.000 align:start line:1% vertical:lr size:50% position:25%
+{"align":"start",
+"line":1,
+"snapToLines":false,
+"vertical":"lr",
+"size":50,
+"position":25}
+
+00:00:00.000 --> 00:00:01.000 align:middle line:1 vertical:rl size:0% position:100%
+{"align":"middle",
+"line":1,
+"vertical":"rl",
+"size":0,
+"position":100} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/settings-position.vtt b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/settings-position.vtt
new file mode 100644
index 00000000000..531cf9fec06
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/settings-position.vtt
@@ -0,0 +1,40 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:01.000 position:-1%
+{}
+
+00:00:00.000 --> 00:00:01.000 position:1
+{}
+
+00:00:00.000 --> 00:00:01.000 position:1x
+{}
+
+00:00:00.000 --> 00:00:01.000 position:1%x
+{}
+
+00:00:00.000 --> 00:00:01.000 position:
+{}
+
+00:00:00.000 --> 00:00:01.000 position: 1%
+{}
+
+00:00:00.000 --> 00:00:01.000 position:1%
+{"position":1}
+
+00:00:00.000 --> 00:00:01.000 position:100%
+{"position":100}
+
+00:00:00.000 --> 00:00:01.000 position:101%
+{}
+
+00:00:00.000 --> 00:00:01.000 position:1% position:x
+{"position":1}
+
+00:00:00.000 --> 00:00:01.000 position:1.5%
+{}
+
+00:00:00.000 --> 00:00:01.000 position:65536%
+{}
+
+00:00:00.000 --> 00:00:01.000 position:4294967296%
+{} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/settings-size.vtt b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/settings-size.vtt
new file mode 100644
index 00000000000..5de885fd3f7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/settings-size.vtt
@@ -0,0 +1,37 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:01.000 size:
+{}
+
+00:00:00.000 --> 00:00:01.000 size:x
+{}
+
+00:00:00.000 --> 00:00:01.000 size:1xx size:2%
+{"size":2}
+
+00:00:00.000 --> 00:00:01.000 size:%
+{}
+
+00:00:00.000 --> 00:00:01.000 size:%%
+{}
+
+00:00:00.000 --> 00:00:01.000 size:1%%
+{}
+
+00:00:00.000 --> 00:00:01.000 size:1%x
+{}
+
+00:00:00.000 --> 00:00:01.000 size:0%
+{"size":0}
+
+00:00:00.000 --> 00:00:01.000 size:00%
+{"size":0}
+
+00:00:00.000 --> 00:00:01.000 size:50% size:100%
+{"size":100}
+
+00:00:00.000 --> 00:00:01.000 size:101%
+{}
+
+00:00:00.000 --> 00:00:01.000 size:50% size:101%
+{"size":50} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/settings-vertical.vtt b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/settings-vertical.vtt
new file mode 100644
index 00000000000..cae64cbf85e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/settings-vertical.vtt
@@ -0,0 +1,19 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:01.000 vertical:lr
+{"vertical":"lr"}
+
+00:00:00.000 --> 00:00:01.000 vertical:rl
+{"vertical":"rl"}
+
+00:00:00.000 --> 00:00:01.000 vertical:rl vertical:lr
+{"vertical":"lr"}
+
+00:00:00.000 --> 00:00:01.000 vertical:
+{}
+
+00:00:00.000 --> 00:00:01.000 vertical:RL
+{}
+
+00:00:00.000 --> 00:00:01.000 vertical:vertical-rl
+{} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/signature-bom.vtt b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/signature-bom.vtt
new file mode 100644
index 00000000000..c0a1057770b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/signature-bom.vtt
@@ -0,0 +1 @@
+WEBVTT
diff --git a/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/signature-formfeed.vtt b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/signature-formfeed.vtt
new file mode 100644
index 00000000000..0ba52863731
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/signature-formfeed.vtt
@@ -0,0 +1 @@
+WEBVTT
diff --git a/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/signature-lowercase.vtt b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/signature-lowercase.vtt
new file mode 100644
index 00000000000..994d1694fd1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/signature-lowercase.vtt
@@ -0,0 +1 @@
+webvtt
diff --git a/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/signature-no-newline.vtt b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/signature-no-newline.vtt
new file mode 100644
index 00000000000..af1827ddf91
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/signature-no-newline.vtt
@@ -0,0 +1 @@
+WEBVTT \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/signature-null.vtt b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/signature-null.vtt
new file mode 100644
index 00000000000..ead93cc166f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/signature-null.vtt
Binary files differ
diff --git a/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/signature-space-no-newline.vtt b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/signature-space-no-newline.vtt
new file mode 100644
index 00000000000..6abbf425aee
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/signature-space-no-newline.vtt
@@ -0,0 +1 @@
+WEBVTT \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/signature-space.vtt b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/signature-space.vtt
new file mode 100644
index 00000000000..1352a209319
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/signature-space.vtt
@@ -0,0 +1 @@
+WEBVTT
diff --git a/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/signature-tab-no-newline.vtt b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/signature-tab-no-newline.vtt
new file mode 100644
index 00000000000..e28ec9b83b1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/signature-tab-no-newline.vtt
@@ -0,0 +1 @@
+WEBVTT \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/signature-tab.vtt b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/signature-tab.vtt
new file mode 100644
index 00000000000..ab4bb0ea6f5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/signature-tab.vtt
@@ -0,0 +1 @@
+WEBVTT
diff --git a/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/signature-timings.vtt b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/signature-timings.vtt
new file mode 100644
index 00000000000..036788609ad
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/signature-timings.vtt
@@ -0,0 +1,2 @@
+WEBVTT 00:00:00.000 --> 00:00:01.000
+"FAIL"
diff --git a/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/signature-too-short.vtt b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/signature-too-short.vtt
new file mode 100644
index 00000000000..3e5de2b6c94
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/signature-too-short.vtt
@@ -0,0 +1 @@
+WEBVT
diff --git a/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/signature-two-boms.vtt b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/signature-two-boms.vtt
new file mode 100644
index 00000000000..05c973be183
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/signature-two-boms.vtt
@@ -0,0 +1 @@
+WEBVTT
diff --git a/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/signature-websrt.vtt b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/signature-websrt.vtt
new file mode 100644
index 00000000000..4a02525e381
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/signature-websrt.vtt
@@ -0,0 +1 @@
+WEBSRT
diff --git a/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/space-chars.vtt b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/space-chars.vtt
new file mode 100644
index 00000000000..012e94dea88
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/space-chars.vtt
@@ -0,0 +1,17 @@
+WEBVTT
+
+spaces
+ 00:00:00.000 --> 00:00:01.000
+{"id":"spaces"}
+
+tabs
+ 00:00:00.000 --> 00:00:01.000
+{"id":"tabs"}
+
+form feed
+ 00:00:00.000 --> 00:00:01.000
+{"id":"form feed"}
+
+vertical tab
+ 00:00:00.000 --> 00:00:01.000
+"FAIL" \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/timings-60.vtt b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/timings-60.vtt
new file mode 100644
index 00000000000..137a56e41cb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/timings-60.vtt
@@ -0,0 +1,20 @@
+WEBVTT
+
+00:00:60.000 --> 00:00:01.000
+"FAIL"
+
+00:60:00.000 --> 00:00:01.000
+"FAIL"
+
+00:00:00.000 --> 00:00:60.000
+"FAIL"
+
+00:00:00.000 --> 00:60:00.000
+"FAIL"
+
+00:00:00.000 --> 60:00:01.000
+{"endTime":216001}
+
+60:00:00.000 --> 60:00:01.000
+{"startTime":216000,
+"endTime":216001}
diff --git a/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/timings-garbage.vtt b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/timings-garbage.vtt
new file mode 100644
index 00000000000..89698673714
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/timings-garbage.vtt
@@ -0,0 +1,190 @@
+WEBVTT
+
+x00:00:00.000 --> 00:00:01.000
+"FAIL"
+
+0x0:00:00.000 --> 00:00:01.000
+"FAIL"
+
+00x:00:00.000 --> 00:00:01.000
+"FAIL"
+
+00:x00:00.000 --> 00:00:01.000
+"FAIL"
+
+00:0x0:00.000 --> 00:00:01.000
+"FAIL"
+
+00:00x:00.000 --> 00:00:01.000
+"FAIL"
+
+00:00:x00.000 --> 00:00:01.000
+"FAIL"
+
+00:00:0x0.000 --> 00:00:01.000
+"FAIL"
+
+00:00:00x.000 --> 00:00:01.000
+"FAIL"
+
+00:00:00.x000 --> 00:00:01.000
+"FAIL"
+
+00:00:00.0x00 --> 00:00:01.000
+"FAIL"
+
+00:00:00.00x0 --> 00:00:01.000
+"FAIL"
+
+00:00:00.000x --> 00:00:01.000
+"FAIL"
+
+00:00:00.000 x--> 00:00:01.000
+"FAIL"
+
+00:00:00.000 -x-> 00:00:01.000
+"FAIL"
+
+00:00:00.000 --x> 00:00:01.000
+"FAIL"
+
+00:00:00.000 -->x 00:00:01.000
+"FAIL"
+
+00:00:00.000 --> x00:00:01.000
+"FAIL"
+
+00:00:00.000 --> 0x0:00:01.000
+"FAIL"
+
+00:00:00.000 --> 00x:00:01.000
+"FAIL"
+
+00:00:00.000 --> 00:x00:01.000
+"FAIL"
+
+00:00:00.000 --> 00:0x0:01.000
+"FAIL"
+
+00:00:00.000 --> 00:00x:01.000
+"FAIL"
+
+00:00:00.000 --> 00:00:x01.000
+"FAIL"
+
+00:00:00.000 --> 00:00:0x1.000
+"FAIL"
+
+00:00:00.000 --> 00:00:01x.000
+"FAIL"
+
+00:00:00.000 --> 00:00:01.x000
+"FAIL"
+
+00:00:00.000 --> 00:00:01.0x00
+"FAIL"
+
+00:00:00.000 --> 00:00:01.00x0
+"FAIL"
+
+x0:00:00.000 --> 00:00:01.000
+"FAIL"
+
+0x:00:00.000 --> 00:00:01.000
+"FAIL"
+
+00x00:00.000 --> 00:00:01.000
+"FAIL"
+
+00:x0:00.000 --> 00:00:01.000
+"FAIL"
+
+00:0x:00.000 --> 00:00:01.000
+"FAIL"
+
+00:00x00.000 --> 00:00:01.000
+"FAIL"
+
+00:00:x0.000 --> 00:00:01.000
+"FAIL"
+
+00:00:0x.000 --> 00:00:01.000
+"FAIL"
+
+00:00:00x000 --> 00:00:01.000
+"FAIL"
+
+00:00:00.x00 --> 00:00:01.000
+"FAIL"
+
+00:00:00.0x0 --> 00:00:01.000
+"FAIL"
+
+00:00:00.00x --> 00:00:01.000
+"FAIL"
+
+00:00:00.000x--> 00:00:01.000
+"FAIL"
+
+00:00:00.000 x-> 00:00:01.000
+"FAIL"
+
+00:00:00.000 -x> 00:00:01.000
+"FAIL"
+
+00:00:00.000 --x 00:00:01.000
+"FAIL"
+
+00:00:00.000 -->x00:00:01.000
+"FAIL"
+
+00:00:00.000 --> x0:00:01.000
+"FAIL"
+
+00:00:00.000 --> 0x:00:01.000
+"FAIL"
+
+00:00:00.000 --> 00x00:01.000
+"FAIL"
+
+00:00:00.000 --> 00:x0:01.000
+"FAIL"
+
+00:00:00.000 --> 00:0x:01.000
+"FAIL"
+
+00:00:00.000 --> 00:00x01.000
+"FAIL"
+
+00:00:00.000 --> 00:00:x1.000
+"FAIL"
+
+00:00:00.000 --> 00:00:0x.000
+"FAIL"
+
+00:00:00.000 --> 00:00:01x000
+"FAIL"
+
+00:00:00.000 --> 00:00:01.x00
+"FAIL"
+
+00:00:00.000 --> 00:00:01.0x0
+"FAIL"
+
+00:00:00.000 --> 00:00:01.00x
+"FAIL"
+
+00.00:00.000 --> 00:00:01.000
+"FAIL"
+
+00:00.00.000 --> 00:00:01.000
+"FAIL"
+
+00:00:00:000 --> 00:00:01.000
+"FAIL"
+
+00:00.00:000 --> 00:00:01.000
+"FAIL"
+
+00:00:00,000 --> 00:00:01,000
+"FAIL" \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/timings-negative.vtt b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/timings-negative.vtt
new file mode 100644
index 00000000000..e13f0f2544e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/timings-negative.vtt
@@ -0,0 +1,13 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:00.000
+{"endTime":0}
+
+00:00:01.000 --> 00:00:00.999
+{"startTime":1, "endTime":0.999}
+
+00:01:00.000 --> 00:00:59.999
+{"startTime":60, "endTime":59.999}
+
+01:00:00.000 --> 00:59:59.999
+{"startTime":3600, "endTime":3599.999}
diff --git a/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/timings-too-long.vtt b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/timings-too-long.vtt
new file mode 100644
index 00000000000..23b498b187d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/timings-too-long.vtt
@@ -0,0 +1,47 @@
+WEBVTT
+
+000:00:00.000 --> 00:00:01.000
+{}
+
+00::00:00.000 --> 00:00:01.000
+"FAIL"
+
+00:000:00.000 --> 00:00:01.000
+"FAIL"
+
+00:00::00.000 --> 00:00:01.000
+"FAIL"
+
+00:00:000.000 --> 00:00:01.000
+"FAIL"
+
+00:00:00..000 --> 00:00:01.000
+"FAIL"
+
+00:00:00.0000 --> 00:00:01.000
+"FAIL"
+
+00:00.0000 --> 00:00:01.000
+"FAIL"
+
+000:00.000 --> 00:01.000
+"FAIL"
+
+00::00.000 --> 00:01.000
+"FAIL"
+
+00:000.000 --> 00:01.000
+"FAIL"
+
+00:00..000 --> 00:01.000
+"FAIL"
+
+00:00.0000 --> 00:01.000
+"FAIL"
+
+00:00.000 --> 000:01.000
+"FAIL"
+
+00:00:00.000 --> 000:00:01.000
+{}
+
diff --git a/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/timings-too-short.vtt b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/timings-too-short.vtt
new file mode 100644
index 00000000000..864ad3832b8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webvtt/webvtt-file-format-parsing/webvtt-file-parsing/support/timings-too-short.vtt
@@ -0,0 +1,98 @@
+WEBVTT
+
+0:00:00.000 --> 00:00:01.000
+{}
+
+0000:00.000 --> 00:00:01.000
+"FAIL"
+
+00:0:00.000 --> 00:00:01.000
+"FAIL"
+
+00:0000.000 --> 00:00:01.000
+"FAIL"
+
+00:00:0.000 --> 00:00:01.000
+"FAIL"
+
+00:00:00000 --> 00:00:01.000
+"FAIL"
+
+00:00:00.00 --> 00:00:01.000
+"FAIL"
+
+00:00:00.0 --> 00:00:01.000
+"FAIL"
+
+00:00:00. --> 00:00:01.000
+"FAIL"
+
+00:00:00 --> 00:00:01.000
+"FAIL"
+
+00:00:0 --> 00:00:01.000
+"FAIL"
+
+00:00: --> 00:00:01.000
+"FAIL"
+
+00:00 --> 00:00:01.000
+"FAIL"
+
+00:0 --> 00:00:01.000
+"FAIL"
+
+00: --> 00:00:01.000
+"FAIL"
+
+00 --> 00:00:01.000
+"FAIL"
+
+0 --> 00:00:01.000
+"FAIL"
+
+ --> 00:00:01.000
+"FAIL"
+
+0:00.000 --> 00:01.000
+"FAIL"
+
+0000.000 --> 00:01.000
+"FAIL"
+
+00:0.000 --> 00:01.000
+"FAIL"
+
+00:00000 --> 00:01.000
+"FAIL"
+
+00:00.00 --> 00:01.000
+"FAIL"
+
+00:00.0 --> 00:01.000
+"FAIL"
+
+00:00. --> 00:01.000
+"FAIL"
+
+0:00. --> 00:01.000
+"FAIL"
+
+:00. --> 00:01.000
+"FAIL"
+
+00. --> 00:01.000
+"FAIL"
+
+0. --> 00:01.000
+"FAIL"
+
+. --> 00:01.000
+"FAIL"
+
+00:00.000 --> 0:01.000
+"FAIL"
+
+00:00:00.000 --> 0:00:01.000
+{}
+
diff --git a/tests/wpt/web-platform-tests/workers/MessagePort_initial_disabled.htm b/tests/wpt/web-platform-tests/workers/MessagePort_initial_disabled.htm
new file mode 100644
index 00000000000..453bfb522d1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/MessagePort_initial_disabled.htm
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<title> MessageChannel: port message queue is initially disabled </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var channel = new MessageChannel();
+ channel.port2.addEventListener("message", t.unreached_func(), true);
+ channel.port1.postMessage("ping");
+ setTimeout(t.step_func_done(), 100);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/workers/MessagePort_onmessage_start.htm b/tests/wpt/web-platform-tests/workers/MessagePort_onmessage_start.htm
new file mode 100644
index 00000000000..fe2d7b7db39
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/MessagePort_onmessage_start.htm
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<title> MessageChannel: port.onmessage enables message queue </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var channel = new MessageChannel();
+ channel.port2.onmessage = t.step_func_done();
+ channel.port1.postMessage("ping");
+ setTimeout(t.unreached_func(), 100);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/workers/README.md b/tests/wpt/web-platform-tests/workers/README.md
new file mode 100644
index 00000000000..3a1c58f3bc6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/README.md
@@ -0,0 +1,8 @@
+This directory contains the Web Workers test suite.
+
+To run this test suite within a browser, go to: <http://w3c-test.org/web-platform-tests/master/workers/>.
+
+The latest Editor's Draft of Web Workers is: <http://dev.w3.org/html5/workers/>.
+
+The latest W3C Technical Report of Web Workers is <http://www.w3.org/TR/workers/>.
+
diff --git a/tests/wpt/web-platform-tests/workers/WorkerGlobalScope_ErrorEvent_colno.htm b/tests/wpt/web-platform-tests/workers/WorkerGlobalScope_ErrorEvent_colno.htm
new file mode 100644
index 00000000000..b762beeb406
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/WorkerGlobalScope_ErrorEvent_colno.htm
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<title> WorkerGlobalScope onerror event handler argument: col </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var worker = new Worker('./support/ErrorEvent.js');
+ worker.onmessage = t.step_func_done(function(e) {
+ assert_equals(typeof e.data.colno, "number");
+ });
+ worker.postMessage("Error Message");
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/workers/WorkerGlobalScope_ErrorEvent_filename.htm b/tests/wpt/web-platform-tests/workers/WorkerGlobalScope_ErrorEvent_filename.htm
new file mode 100644
index 00000000000..9390b7441a3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/WorkerGlobalScope_ErrorEvent_filename.htm
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<title> WorkerGlobalScope onerror event handler argument: location </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var worker = new Worker('./support/ErrorEvent.js');
+ worker.onmessage = t.step_func_done(function(e) {
+ var href = location.href;
+ var expected = href.substring(0, href.lastIndexOf('/')) + '/support/ErrorEvent.js';
+ assert_equals(e.data.filename, expected);
+ });
+ worker.postMessage("Error Message");
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/workers/WorkerGlobalScope_ErrorEvent_lineno.htm b/tests/wpt/web-platform-tests/workers/WorkerGlobalScope_ErrorEvent_lineno.htm
new file mode 100644
index 00000000000..c3c145d4bb1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/WorkerGlobalScope_ErrorEvent_lineno.htm
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<title> WorkerGlobalScope onerror event handler argument: line </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var worker = new Worker('./support/ErrorEvent.js');
+ worker.onmessage = t.step_func_done(function(e) {
+ assert_equals(e.data.lineno, 3);
+ });
+ worker.postMessage("Error Message");
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/workers/WorkerGlobalScope_ErrorEvent_message.htm b/tests/wpt/web-platform-tests/workers/WorkerGlobalScope_ErrorEvent_message.htm
new file mode 100644
index 00000000000..55a7b7fbba2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/WorkerGlobalScope_ErrorEvent_message.htm
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<title> WorkerGlobalScope onerror event handler argument: message </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var message = 'Error Message';
+ var worker = new Worker('./support/ErrorEvent.js');
+ worker.onmessage = t.step_func_done(function(e) {
+ assert_greater_than(e.data.message.indexOf(message), -1);
+ });
+ worker.postMessage(message);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/workers/WorkerGlobalScope_close.htm b/tests/wpt/web-platform-tests/workers/WorkerGlobalScope_close.htm
new file mode 100644
index 00000000000..2ad5205d1b9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/WorkerGlobalScope_close.htm
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<title> WorkerGlobalScope close(): clear events queue </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var worker = new Worker('./support/WorkerClose.js');
+ worker.onmessage = t.step_func(function(e) {
+ assert_equals(e.data, "ping");
+ worker.onmessage = t.unreached_func("Unexpected message event");
+ worker.postMessage("pong");
+ setTimeout(t.step_func_done(), 100);
+ });
+ worker.postMessage("ping");
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/workers/WorkerGlobalScope_importScripts.htm b/tests/wpt/web-platform-tests/workers/WorkerGlobalScope_importScripts.htm
new file mode 100644
index 00000000000..1a3616df98b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/WorkerGlobalScope_importScripts.htm
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<title> WorkerGlobalScope API: importScripts() </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var worker = new Worker("./support/ImportScripts.js");
+ worker.onmessage = t.step_func_done(function(e) {
+ assert_equals(e.data, "Pass");
+ });
+ worker.postMessage("ping");
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/workers/WorkerGlobalScope_importScripts_NetworkErr.htm b/tests/wpt/web-platform-tests/workers/WorkerGlobalScope_importScripts_NetworkErr.htm
new file mode 100644
index 00000000000..36fe6e0b2d3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/WorkerGlobalScope_importScripts_NetworkErr.htm
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<title> importScripts() with non-existent script file </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var worker = new Worker("./support/ImportScriptsNetworkErr.js");
+ worker.onmessage = t.step_func_done(function(e) {
+ assert_equals(e.data, "Pass");
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/workers/WorkerGlobalScope_setInterval.htm b/tests/wpt/web-platform-tests/workers/WorkerGlobalScope_setInterval.htm
new file mode 100644
index 00000000000..4e147fbf60f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/WorkerGlobalScope_setInterval.htm
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<title> WorkerGlobalScope API: setInterval() </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var result = [];
+ var worker = new Worker('./support/Timer.js');
+ worker.onmessage = t.step_func(function(e) {
+ result.push(e.data);
+ if (result.length == 3) {
+ assert_array_equals(result, ["hello", "worker", "worker"]);
+ worker.onmessage = t.unreached_func('Unexpected message event');
+ setTimeout(t.step_func_done(), 100);
+ }
+ });
+ worker.postMessage("IntervalHandler");
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/workers/WorkerGlobalScope_setTimeout.htm b/tests/wpt/web-platform-tests/workers/WorkerGlobalScope_setTimeout.htm
new file mode 100644
index 00000000000..89fdf3d740a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/WorkerGlobalScope_setTimeout.htm
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<title> WorkerGlobalScope API: setTimeout() </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var result = [];
+ var worker = new Worker('./support/Timer.js');
+ worker.onmessage = t.step_func(function(e) {
+ result.push(e.data);
+ if (result.length == 3) {
+ assert_array_equals(result, ["hello", "worker", "worker"]);
+ worker.onmessage = t.unreached_func('Unexpected message event');
+ setTimeout(t.step_func_done(), 100);
+ }
+ });
+ worker.postMessage("TimeoutHandler");
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/workers/WorkerLocation.htm b/tests/wpt/web-platform-tests/workers/WorkerLocation.htm
new file mode 100644
index 00000000000..a74f13a8b48
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/WorkerLocation.htm
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<title> WorkerLocation object </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var worker = new Worker('./support/WorkerLocation.js');
+ worker.onmessage = t.step_func_done(function(e) {
+ var href = window.location.href;
+ var ExpectedResult = href.substring(0, href.lastIndexOf('/')) + '/support/WorkerLocation.js';
+ assert_equals(e.data.location, ExpectedResult);
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/workers/WorkerLocation_hash.htm b/tests/wpt/web-platform-tests/workers/WorkerLocation_hash.htm
new file mode 100644
index 00000000000..74a424efc3c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/WorkerLocation_hash.htm
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<title> WorkerLocation URL decomposition IDL attribute: hash </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var worker = new Worker("./support/WorkerLocation.js#HashString");
+ worker.onmessage = t.step_func_done(function(e) {
+ assert_equals(e.data.hash, "#HashString");
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/workers/WorkerLocation_hash_encoding.htm b/tests/wpt/web-platform-tests/workers/WorkerLocation_hash_encoding.htm
new file mode 100644
index 00000000000..b2a171a092a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/WorkerLocation_hash_encoding.htm
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<title> WorkerLocation.hash with url encoding string </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var worker = new Worker("./support/WorkerLocation.js#question%3f");
+ worker.onmessage = t.step_func_done(function(e) {
+ assert_equals(e.data.hash, "#question%3f");
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/workers/WorkerLocation_hash_nonexist.htm b/tests/wpt/web-platform-tests/workers/WorkerLocation_hash_nonexist.htm
new file mode 100644
index 00000000000..2d898c075c3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/WorkerLocation_hash_nonexist.htm
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<title> WorkerLocation.hash with no &lt;fragment&gt; component </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var worker = new Worker('./support/WorkerLocation.js');
+ worker.onmessage = t.step_func_done(function(e) {
+ assert_equals(e.data.hash, "");
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/workers/WorkerLocation_host.htm b/tests/wpt/web-platform-tests/workers/WorkerLocation_host.htm
new file mode 100644
index 00000000000..53286ddfc53
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/WorkerLocation_host.htm
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<title> WorkerLocation URL decomposition IDL attribute: host </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var worker = new Worker('./support/WorkerLocation.js');
+ worker.onmessage = t.step_func_done(function(e) {
+ assert_equals(e.data.host, location.host);
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/workers/WorkerLocation_hostname.htm b/tests/wpt/web-platform-tests/workers/WorkerLocation_hostname.htm
new file mode 100644
index 00000000000..97250805c9f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/WorkerLocation_hostname.htm
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<title> WorkerLocation URL decomposition IDL attribute: hostname </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var worker = new Worker('./support/WorkerLocation.js');
+ worker.onmessage = t.step_func_done(function(e) {
+ assert_equals(e.data.hostname, location.hostname);
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/workers/WorkerLocation_href.htm b/tests/wpt/web-platform-tests/workers/WorkerLocation_href.htm
new file mode 100644
index 00000000000..3ed1dbd4f51
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/WorkerLocation_href.htm
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<title> WorkerLocation href attribute </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var worker = new Worker("./support/WorkerLocation.js?srch%20#hash");
+ worker.onmessage = t.step_func_done(function(e) {
+ var href = location.href;
+ var expected = href.substring(0, href.lastIndexOf('/')) + "/support/WorkerLocation.js?srch%20#hash";
+ assert_equals(e.data.href, expected);
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/workers/WorkerLocation_pathname.htm b/tests/wpt/web-platform-tests/workers/WorkerLocation_pathname.htm
new file mode 100644
index 00000000000..34698451155
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/WorkerLocation_pathname.htm
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<title> WorkerLocation URL decomposition IDL attribute: pathname </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var worker = new Worker('./support/WorkerLocation.js');
+ worker.onmessage = t.step_func_done(function(e) {
+ var pathname = location.pathname;
+ var expected = pathname.substring(0, pathname.lastIndexOf('/')) + '/support/WorkerLocation.js';
+ assert_equals(e.data.pathname, expected);
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/workers/WorkerLocation_port.htm b/tests/wpt/web-platform-tests/workers/WorkerLocation_port.htm
new file mode 100644
index 00000000000..ef86cfacb61
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/WorkerLocation_port.htm
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<title> WorkerLocation URL decomposition IDL attribute: port </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var worker = new Worker('./support/WorkerLocation.js');
+ worker.onmessage = t.step_func_done(function(e) {
+ assert_equals(e.data.port, location.port);
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/workers/WorkerLocation_protocol.htm b/tests/wpt/web-platform-tests/workers/WorkerLocation_protocol.htm
new file mode 100644
index 00000000000..f792dee5156
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/WorkerLocation_protocol.htm
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<title> WorkerLocation URL decomposition IDL attribute: protocol </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var worker = new Worker('./support/WorkerLocation.js');
+ worker.onmessage = t.step_func_done(function(e) {
+ assert_equals(e.data.protocol, location.protocol);
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/workers/WorkerLocation_search.htm b/tests/wpt/web-platform-tests/workers/WorkerLocation_search.htm
new file mode 100644
index 00000000000..bc6add8768a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/WorkerLocation_search.htm
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<title> WorkerLocation URL decomposition IDL attribute: search </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var worker = new Worker('./support/WorkerLocation.js?SearchString');
+ worker.onmessage = t.step_func_done(function(e) {
+ assert_equals(e.data.search, '?SearchString');
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/workers/WorkerLocation_search_empty.htm b/tests/wpt/web-platform-tests/workers/WorkerLocation_search_empty.htm
new file mode 100644
index 00000000000..a32d4309128
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/WorkerLocation_search_empty.htm
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<title> WorkerLocation.search with empty &lt;query&gt; </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var worker = new Worker("./support/WorkerLocation.js?");
+ worker.onmessage = t.step_func_done(function(e) {
+ assert_equals(e.data.search, "");
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/workers/WorkerLocation_search_fragment.htm b/tests/wpt/web-platform-tests/workers/WorkerLocation_search_fragment.htm
new file mode 100644
index 00000000000..3ec4cffa6b5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/WorkerLocation_search_fragment.htm
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<title> WorkerLocation.search with &lt;fragment&gt; in &lt;query&gt; </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var worker = new Worker('./support/WorkerLocation.js?test#');
+ worker.onmessage = t.step_func_done(function(e) {
+ assert_equals(e.data.search, "?test");
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/workers/WorkerLocation_search_nonexist.htm b/tests/wpt/web-platform-tests/workers/WorkerLocation_search_nonexist.htm
new file mode 100644
index 00000000000..9907e6473c2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/WorkerLocation_search_nonexist.htm
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<title> WorkerLocation.search with no &lt;query&gt; component </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var worker = new Worker('./support/WorkerLocation.js');
+ worker.onmessage = t.step_func_done(function(e) {
+ assert_equals(e.data.search, "");
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/workers/WorkerNavigator_appName.htm b/tests/wpt/web-platform-tests/workers/WorkerNavigator_appName.htm
new file mode 100644
index 00000000000..832c46ff5e2
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/WorkerNavigator_appName.htm
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<title> WorkerNavigator appName </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var worker = new Worker("./support/WorkerNavigator.js");
+ worker.onmessage = t.step_func_done(function(e) {
+ assert_equals(e.data.appName, navigator.appName);
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/workers/WorkerNavigator_appVersion.htm b/tests/wpt/web-platform-tests/workers/WorkerNavigator_appVersion.htm
new file mode 100644
index 00000000000..7deaa4256af
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/WorkerNavigator_appVersion.htm
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<title> WorkerNavigator appVersion </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var worker = new Worker("./support/WorkerNavigator.js");
+ worker.onmessage = t.step_func_done(function(e) {
+ assert_equals(e.data.appVersion, navigator.appVersion);
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/workers/WorkerNavigator_onLine.htm b/tests/wpt/web-platform-tests/workers/WorkerNavigator_onLine.htm
new file mode 100644
index 00000000000..f9e819b8aab
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/WorkerNavigator_onLine.htm
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<title> WorkerNavigator.onLine </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var worker = new Worker("./support/WorkerNavigator.js");
+ worker.onmessage = t.step_func_done(function(e) {
+ assert_equals(e.data.onLine, navigator.onLine);
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/workers/WorkerNavigator_platform.htm b/tests/wpt/web-platform-tests/workers/WorkerNavigator_platform.htm
new file mode 100644
index 00000000000..3a6de80eb96
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/WorkerNavigator_platform.htm
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<title> WorkerNavigator.platform </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var worker = new Worker("./support/WorkerNavigator.js");
+ worker.onmessage = t.step_func_done(function(e) {
+ assert_equals(e.data.platform, navigator.platform);
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/workers/WorkerNavigator_userAgent.htm b/tests/wpt/web-platform-tests/workers/WorkerNavigator_userAgent.htm
new file mode 100644
index 00000000000..8a34fb480ac
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/WorkerNavigator_userAgent.htm
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<title> WorkerNavigator.userAgent </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var worker = new Worker("./support/WorkerNavigator.js");
+ worker.onmessage = t.step_func_done(function(e) {
+ assert_equals(e.data.userAgent, navigator.userAgent);
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/workers/Worker_ErrorEvent_filename.htm b/tests/wpt/web-platform-tests/workers/Worker_ErrorEvent_filename.htm
new file mode 100644
index 00000000000..23dda66e6da
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/Worker_ErrorEvent_filename.htm
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<title> AbstractWorker ErrorEvent.filename </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var worker = new Worker('./support/ErrorEvent.js');
+ worker.onerror = t.step_func_done(function(e) {
+ var href = location.href;
+ var expected = href.substring(0, href.lastIndexOf('/')) + '/support/ErrorEvent.js';
+ assert_equals(e.filename, expected);
+ });
+ worker.postMessage("Error Message");
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/workers/Worker_ErrorEvent_lineno.htm b/tests/wpt/web-platform-tests/workers/Worker_ErrorEvent_lineno.htm
new file mode 100644
index 00000000000..912cf6e5a28
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/Worker_ErrorEvent_lineno.htm
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<title> AbstractWorker ErrorEvent.lineno </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var worker = new Worker('./support/ErrorEvent.js');
+ worker.onerror = t.step_func_done(function(e) {
+ assert_equals(e.lineno, 3);
+ });
+ worker.postMessage("Error Message");
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/workers/Worker_ErrorEvent_message.htm b/tests/wpt/web-platform-tests/workers/Worker_ErrorEvent_message.htm
new file mode 100644
index 00000000000..10a140c8651
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/Worker_ErrorEvent_message.htm
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<title> AbstractWorker ErrorEvent.message </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var message = 'Error Message';
+ var worker = new Worker('./support/ErrorEvent.js');
+ worker.onerror = t.step_func_done(function(e) {
+ assert_greater_than(e.message.indexOf(message), -1);
+ });
+ worker.postMessage(message);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/workers/Worker_ErrorEvent_type.htm b/tests/wpt/web-platform-tests/workers/Worker_ErrorEvent_type.htm
new file mode 100644
index 00000000000..29fdfdc708a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/Worker_ErrorEvent_type.htm
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<title> AbstractWorker ErrorEvent.type </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var worker = new Worker('./support/ErrorEvent.js');
+ worker.onerror = t.step_func_done(function(e) {
+ assert_class_string(e, 'ErrorEvent');
+ assert_equals(e.type, 'error');
+ });
+ worker.postMessage("Error Message");
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/workers/Worker_basic.htm b/tests/wpt/web-platform-tests/workers/Worker_basic.htm
new file mode 100644
index 00000000000..d2b57b4918b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/Worker_basic.htm
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<title> Web Workers Basic Tests </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+function create_worker() {
+ return new Worker('./support/WorkerBasic.js');
+}
+
+test(function() {
+ var worker = create_worker();
+ assert_class_string(worker, "Worker");
+}, "Worker constructor");
+
+async_test(function(t) {
+ var worker = create_worker();
+ worker.onmessage = t.step_func_done(function(e) {
+ assert_equals(e.data, "Pass");
+ });
+ worker.postMessage("start");
+}, "MessageEvent.data");
+
+async_test(function(t) {
+ var worker = create_worker();
+ worker.addEventListener("message", t.step_func_done(function(e) {
+ assert_equals(e.type, "message");
+ }), true);
+ worker.postMessage("start");
+}, "MessageEvent.type");
+</script>
diff --git a/tests/wpt/web-platform-tests/workers/Worker_cross_origin_security_err.htm b/tests/wpt/web-platform-tests/workers/Worker_cross_origin_security_err.htm
new file mode 100644
index 00000000000..53e8a7b0537
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/Worker_cross_origin_security_err.htm
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<title> Worker cross-origin URL </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+test(function() {
+ assert_throws("SECURITY_ERR", function() {
+ new Worker("ftp://example.org/support/WorkerBasic.js");
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/workers/Worker_dispatchEvent_ErrorEvent.htm b/tests/wpt/web-platform-tests/workers/Worker_dispatchEvent_ErrorEvent.htm
new file mode 100644
index 00000000000..58a31f04252
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/Worker_dispatchEvent_ErrorEvent.htm
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<title> ErrorEvent and Worker.dispatchEvent() </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var event = "error";
+ var filename = './support/ErrorEvent.js';
+ var message = 'Hello Worker';
+ var lineno = 5;
+ var colno = 6;
+ var error = new Error("test");
+ var worker = new Worker(filename);
+ worker.addEventListener(event, t.step_func_done(function(e) {
+ assert_equals(e.type, event, 'type');
+ assert_equals(e.message, message, 'message');
+ assert_equals(e.filename, filename, 'filename');
+ assert_equals(e.lineno, lineno, 'lineno');
+ assert_equals(e.colno, colno, 'colno');
+ assert_equals(e.error, error, 'error');
+ }), true);
+ var e = new ErrorEvent(event, {bubbles:true, cancelable:true, message:message, filename:filename, lineno:lineno, colno:colno, error:error});
+ worker.dispatchEvent(e);
+});
+
+test(function() {
+ assert_throws("NotSupportedError", function() {
+ document.createEvent("ErrorEvent");
+ }, "should not be supported");
+}, "document.createEvent('ErrorEvent')");
+
+test(function() {
+ var e = new ErrorEvent("error");
+ assert_false("initErrorEvent" in e, "should not be supported");
+}, "initErrorEvent");
+</script>
diff --git a/tests/wpt/web-platform-tests/workers/Worker_script_mimetype.htm b/tests/wpt/web-platform-tests/workers/Worker_script_mimetype.htm
new file mode 100644
index 00000000000..04fe68e6628
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/Worker_script_mimetype.htm
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<title> Worker constructor with script inside text file </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var worker = new Worker('./support/WorkerText.txt');
+ worker.onmessage = t.step_func_done(function(e) {
+ assert_equals(e.data, "Pass");
+ });
+ worker.postMessage("start");
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/workers/Worker_terminate_event_queue.htm b/tests/wpt/web-platform-tests/workers/Worker_terminate_event_queue.htm
new file mode 100644
index 00000000000..cbb6bdae578
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/Worker_terminate_event_queue.htm
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<title> AbstractWorker terminate(): clear event queue </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var testResult;
+ var worker = new Worker('./support/WorkerTerminate.js');
+ worker.onmessage = function(e) {
+ testResult = e.data;
+ if (testResult >= 10000) {
+ worker.terminate();
+ worker.onmessage = t.unreached_func('Unexpected message event');
+ setTimeout(t.step_func_done(function() {
+ assert_equals(testResult, 10000);
+ }), 100);
+ }
+ };
+ worker.postMessage("ping");
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/1 b/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/1
new file mode 100644
index 00000000000..c3f67beea90
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/1
@@ -0,0 +1,3 @@
+onconnect = function(e) {
+ e.ports[0].postMessage(['1', self.name]);
+} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/connect-event.html b/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/connect-event.html
new file mode 100644
index 00000000000..a9719d9dea6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/connect-event.html
@@ -0,0 +1,26 @@
+<!--
+onconnect = function(e) {
+ e.ports[0].postMessage([e.data === '', e instanceof MessageEvent, e.ports.length == 1]);
+};
+/*
+-->
+<!doctype html>
+<title>connect event</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+(async_test()).step(function() {
+ var worker = new SharedWorker('#');
+ worker.port.addEventListener('message', this.step_func(function(e) {
+ assert_true(e.data[0], "e.data === ''");
+ assert_true(e.data[1], "e instanceof MessageEvent");
+ assert_true(e.data[2], "e.ports.length == 1");
+ this.done();
+ }), false);
+ worker.port.start();
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/dummy-name.html b/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/dummy-name.html
new file mode 100644
index 00000000000..9e2732923ec
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/dummy-name.html
@@ -0,0 +1,17 @@
+<!--
+/*
+-->
+<!doctype html>
+<title>creating a dummy shared worker with name "foo"</title>
+<link rel=help href="http://www.whatwg.org/html/#dom-sharedworker">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ var worker = new SharedWorker('#', 'foo');
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/dummy-shared-worker.html b/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/dummy-shared-worker.html
new file mode 100644
index 00000000000..e9aff9c5b4c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/dummy-shared-worker.html
@@ -0,0 +1,17 @@
+<!--
+/*
+-->
+<!doctype html>
+<title>creating a dummy shared worker</title>
+<link rel=help href="http://www.whatwg.org/html/#dom-sharedworker">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ var worker = new SharedWorker('#');
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/empty-name.html b/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/empty-name.html
new file mode 100644
index 00000000000..95ff6d1ad29
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/empty-name.html
@@ -0,0 +1,17 @@
+<!--
+/*
+-->
+<!doctype html>
+<title>creating a dummy shared worker with explicit name ""</title>
+<link rel=help href="http://www.whatwg.org/html/#dom-sharedworker">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ var worker = new SharedWorker('#', '');
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/global-members.html b/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/global-members.html
new file mode 100644
index 00000000000..af4eb1d4532
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/global-members.html
@@ -0,0 +1,34 @@
+<!--
+var expected = 'self location close onerror importScripts navigator addEventListener removeEventListener dispatchEvent name applicationCache onconnect setTimeout clearTimeout setInterval clearInterval'.split(' ');
+var log = '';
+for (var i = 0; i < expected.length; ++i) {
+ if (!(expected[i] in self))
+ log += expected[i] + ' did not exist\n';
+}
+onconnect = function(e) {
+ e.ports[0].postMessage(log);
+};
+/*
+-->
+<!doctype html>
+<title>members of SharedWorkerGlobalScope</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+(async_test()).step(function() {
+ var worker = new SharedWorker('#');
+ worker.port.addEventListener('message', this.step_func(function(e) {
+ assert_equals(e.data, '');
+ this.done();
+ }), false);
+ worker.port.start();
+});
+</script>
+<!--
+*/
+//-->
+
+
+
+
diff --git a/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/interface-objects.html b/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/interface-objects.html
new file mode 100644
index 00000000000..e91b2dc6a8c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/interface-objects.html
@@ -0,0 +1,41 @@
+<!--
+var prt;
+function handleCall(e) {
+ var log = [];
+ for (var i = 0; i < e.data.length; ++i) {
+ if (!(e.data[i] in self))
+ log.push(e.data[i]);
+ }
+ prt.postMessage('These were missing: '+log.join(', '));
+}
+onconnect = function(e) {
+ prt = e.ports[0];
+ prt.onmessage = handleCall;
+};
+/*
+-->
+<!doctype html>
+<title>expected interface objects/constructors</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+(async_test()).step(function() {
+ var expected = 'XMLHttpRequest WebSocket EventSource MessageChannel Worker SharedWorker ApplicationCache'.split(' ');
+ var supported = [];
+ for (var i = 0; i < expected.length; ++i) {
+ if (expected[i] in window)
+ supported.push(expected[i]);
+ }
+ var worker = new SharedWorker('#');
+ worker.port.start();
+ worker.port.postMessage(supported);
+ worker.port.addEventListener('message', this.step_func(function(e) {
+ assert_equals(e.data, '');
+ this.done();
+ }), false);
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/name.html b/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/name.html
new file mode 100644
index 00000000000..823e16c7c1f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/name.html
@@ -0,0 +1,24 @@
+<!--
+onconnect = function(e) {
+ e.ports[0].postMessage(self.name);
+}
+/*
+-->
+<!doctype html>
+<title>self.name</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+(async_test()).step(function() {
+ var worker = new SharedWorker('#', 'hello');
+ worker.port.addEventListener('message', this.step_func(function(e) {
+ assert_equals(e.data, 'hello');
+ this.done();
+ }), false);
+ worker.port.start();
+});
+</script>
+<!--
+*/
+//--> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/no-arguments-ctor.html b/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/no-arguments-ctor.html
new file mode 100644
index 00000000000..eaee870db0e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/no-arguments-ctor.html
@@ -0,0 +1,20 @@
+<!--
+/*
+-->
+<!doctype html>
+<title>no arguments</title>
+<link rel=help href="http://www.whatwg.org/html/#sharedworker">
+<link rel=help href="http://dev.w3.org/2006/webapi/WebIDL/#es-interface-call">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ assert_throws(new TypeError(), function() {
+ var worker = new SharedWorker();
+ });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/null b/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/null
new file mode 100644
index 00000000000..5c38505b6c8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/null
@@ -0,0 +1,3 @@
+onconnect = function(e) {
+ e.ports[0].postMessage(['null', self.name]);
+} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/null-arguments.html b/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/null-arguments.html
new file mode 100644
index 00000000000..c711b2cb5ac
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/null-arguments.html
@@ -0,0 +1,25 @@
+<!--
+onconnect = function(e) {
+ e.ports[0].postMessage(['FAIL', self.name]);
+}
+/*
+-->
+<!doctype html>
+<title>null as arguments</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+(async_test()).step(function() {
+ var worker = new SharedWorker(null, null);
+ worker.port.addEventListener('message', this.step_func(function(e) {
+ assert_equals(e.data[0], 'null', 'first arg');
+ assert_equals(e.data[1], 'null', 'second arg');
+ this.done();
+ }), false);
+ worker.port.start();
+});
+</script>
+<!--
+*/
+//--> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/number-arguments.html b/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/number-arguments.html
new file mode 100644
index 00000000000..1a4cfb2eacb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/number-arguments.html
@@ -0,0 +1,25 @@
+<!--
+onconnect = function(e) {
+ e.ports[0].postMessage(['FAIL', self.name]);
+}
+/*
+-->
+<!doctype html>
+<title>1 as arguments</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+(async_test()).step(function() {
+ var worker = new SharedWorker(1, 1);
+ worker.port.addEventListener('message', this.step_func(function(e) {
+ assert_equals(e.data[0], '1', 'first arg');
+ assert_equals(e.data[1], '1', 'second arg');
+ this.done();
+ }), false);
+ worker.port.start();
+});
+</script>
+<!--
+*/
+//--> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/port-onmessage.html b/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/port-onmessage.html
new file mode 100644
index 00000000000..a2f4df0bfdd
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/port-onmessage.html
@@ -0,0 +1,23 @@
+<!--
+onconnect = function(e) {
+ e.ports[0].postMessage(true);
+}
+/*
+-->
+<!doctype html>
+<title>worker.port.onmessage</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+(async_test()).step(function() {
+ var worker = new SharedWorker('#', '');
+ worker.port.onmessage = this.step_func(function(e) {
+ assert_true(e.data);
+ this.done();
+ });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/port-properties.html b/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/port-properties.html
new file mode 100644
index 00000000000..f8a676dd248
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/port-properties.html
@@ -0,0 +1,26 @@
+<!--
+/*
+-->
+<!doctype html>
+<title>worker.port</title>
+<link rel=help href="http://www.whatwg.org/html/#sharedworker">
+<link rel=help href="http://www.whatwg.org/html/#messageport">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ var worker = new SharedWorker('#', '');
+ assert_true('port' in worker, "port");
+ assert_true('postMessage' in worker.port, "postMessage");
+ assert_true('start' in worker.port, "start");
+ assert_true('close' in worker.port, "close");
+ assert_true('onmessage' in worker.port, "onmessage");
+ assert_true('addEventListener' in worker.port, "addEventListener");
+ assert_true('removeEventListener' in worker.port, "removeEventListener");
+ assert_true('dispatchEvent' in worker.port, "dispatchEvent");
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/port-readonly.html b/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/port-readonly.html
new file mode 100644
index 00000000000..f087ab0f623
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/port-readonly.html
@@ -0,0 +1,21 @@
+<!--
+/*
+-->
+<!doctype html>
+<title>setting worker.port</title>
+<link rel=help href="http://www.whatwg.org/html/#sharedworker">
+<link rel=help href="http://dev.w3.org/2006/webapi/WebIDL/#dfn-attribute-setter">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ var worker = new SharedWorker('#', '');
+ var x = worker.port;
+ worker.port = 1;
+ assert_equals(worker.port, x);
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/same-origin.html b/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/same-origin.html
new file mode 100644
index 00000000000..196b53bedbe
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/same-origin.html
@@ -0,0 +1,48 @@
+<!--
+/*
+-->
+<!doctype html>
+<title>same-origin checks</title>
+<link rel=help href="http://www.whatwg.org/html/#dom-sharedworker">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+// Needed to prevent a race condition if a worker throws an exception that may or may
+// not propogate to the window before the tests finish
+setup({allow_uncaught_exception: true});
+
+test(function() {
+ assert_throws("SecurityError", function() { new SharedWorker('unsupported:', ''); });
+}, "unsupported_scheme");
+async_test(function() {
+ var worker = new SharedWorker('data:,onconnect = function(e) { e.ports[0].postMessage(1); }', '');
+ worker.port.onmessage = this.step_func_done(function(e) {
+ assert_equals(e.data, 1);
+ });
+}, "data_url");
+test(function() {
+ assert_throws("SecurityError", function() { new SharedWorker('javascript:""', ''); });
+}, "javascript_url");
+test(function() {
+ assert_throws("SecurityError", function() { new SharedWorker('about:blank', ''); });
+}, "about_blank");
+test(function() {
+ assert_throws("SecurityError", function() { new SharedWorker('http://www.opera.com/', ''); });
+}, "opera_com");
+test(function() {
+ assert_throws("SecurityError", function() { new SharedWorker(location.protocol+'//'+location.hostname+':81/', ''); });
+}, "port_81");
+test(function() {
+ assert_throws("SecurityError", function() { new SharedWorker('https://'+location.hostname+':80/', ''); });
+}, "https_port_80");
+test(function() {
+ assert_throws("SecurityError", function() { new SharedWorker('https://'+location.hostname+':8000/', ''); });
+}, "https_port_8000");
+test(function() {
+ assert_throws("SecurityError", function() { new SharedWorker('http://'+location.hostname+':8012/', ''); });
+}, "http_port_8012");
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/setting-port-members.html b/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/setting-port-members.html
new file mode 100644
index 00000000000..8c79ff295e5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/setting-port-members.html
@@ -0,0 +1,59 @@
+<!--
+/*
+-->
+<!doctype html>
+<title>setting members of worker.port</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+setup(function() {
+ window.worker = new SharedWorker('#', '');
+});
+test(function() {
+ worker.port.postMessage = 1;
+ assert_equals(worker.port.postMessage, 1);
+}, 'postMessage');
+test(function() {
+ worker.port.start = 1;
+ assert_equals(worker.port.start, 1);
+}, 'start');
+test(function() {
+ worker.port.close = 1;
+ assert_equals(worker.port.close, 1);
+}, 'close');
+test(function() {
+ var f = function(){};
+ worker.port.onmessage = f;
+ assert_equals(worker.port.onmessage, f, 'function(){}');
+ worker.port.onmessage = 1;
+ assert_equals(worker.port.onmessage, null, '1');
+ worker.port.onmessage = f;
+ worker.port.onmessage = ';';
+ assert_equals(worker.port.onmessage, null, '";"');
+ worker.port.onmessage = f;
+ worker.port.onmessage = {handleEvent:function(){}};
+ assert_equals(worker.port.onmessage, null, '{handleEvent:function(){}}');
+ worker.port.onmessage = f;
+ worker.port.onmessage = null;
+ assert_equals(worker.port.onmessage, null, 'null');
+ worker.port.onmessage = f;
+ worker.port.onmessage = undefined;
+ assert_equals(worker.port.onmessage, null, 'undefined');
+}, 'onmessage');
+test(function() {
+ worker.port.addEventListener = 1;
+ assert_equals(worker.port.addEventListener, 1);
+}, 'addEventListener');
+test(function() {
+ worker.port.removeEventListener = 1;
+ assert_equals(worker.port.removeEventListener, 1);
+}, 'removeEventListener');
+test(function() {
+ worker.port.despatchEvent = 1;
+ assert_equals(worker.port.despatchEvent, 1);
+}, 'despatchEvent');
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/undefined b/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/undefined
new file mode 100644
index 00000000000..3fe840d3042
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/undefined
@@ -0,0 +1,3 @@
+onconnect = function(e) {
+ e.ports[0].postMessage(['undefined', self.name]);
+} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/undefined-arguments.html b/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/undefined-arguments.html
new file mode 100644
index 00000000000..b9a3b3692c3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/undefined-arguments.html
@@ -0,0 +1,25 @@
+<!--
+onconnect = function(e) {
+ e.ports[0].postMessage(['FAIL', self.name]);
+}
+/*
+-->
+<!doctype html>
+<title>undefined as arguments</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+(async_test()).step(function() {
+ var worker = new SharedWorker(undefined, undefined);
+ worker.port.addEventListener('message', this.step_func(function(e) {
+ assert_equals(e.data[0], 'undefined', 'first arg');
+ assert_equals(e.data[1], 'undefined', 'second arg');
+ this.done();
+ }), false);
+ worker.port.start();
+});
+</script>
+<!--
+*/
+//--> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/unexpected-global-properties.html b/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/unexpected-global-properties.html
new file mode 100644
index 00000000000..39739022d7e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/unexpected-global-properties.html
@@ -0,0 +1,30 @@
+<!--
+var unexpected = 'open print stop getComputedStyle getSelection releaseEvents captureEvents alert confirm prompt addEventStream removeEventStream back forward attachEvent detachEvent navigate DOMParser XMLSerializer XPathEvaluator XSLTProcessor opera Image Option frames Audio SVGUnitTypes SVGZoomAndPan java netscape sun Packages ByteArray closed defaultStatus document event frameElement history innerHeight innerWidth opener outerHeight outerWidth pageXOffset pageYOffset parent screen screenLeft screenTop screenX screenY status top window length'.split(' '); // iterated window in opera and removed expected ones
+var log = '';
+for (var i = 0; i < unexpected.length; ++i) {
+ if (unexpected[i] in self)
+ log += unexpected[i] + ' ';
+}
+onconnect = function(e) {
+ e.ports[0].postMessage(log);
+};
+/*
+-->
+<!doctype html>
+<title>unexpected members/interface objects/constructors</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+(async_test()).step(function() {
+ var worker = new SharedWorker('#');
+ worker.port.addEventListener('message', this.step_func(function(e) {
+ assert_equals(e.data, '');
+ this.done();
+ }), false);
+ worker.port.start();
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/unresolvable-url.html b/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/unresolvable-url.html
new file mode 100644
index 00000000000..2ca3d93d3e8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/constructors/SharedWorker/unresolvable-url.html
@@ -0,0 +1,19 @@
+<!--
+/*
+-->
+<!doctype html>
+<title>resolving broken url</title>
+<link rel=help href="http://www.whatwg.org/html/#dom-sharedworker">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ assert_throws("SyntaxError", function() {
+ var worker = new SharedWorker('http://foo bar');
+ });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/constructors/Worker/1 b/tests/wpt/web-platform-tests/workers/constructors/Worker/1
new file mode 100644
index 00000000000..ea0b7c8f4cc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/constructors/Worker/1
@@ -0,0 +1 @@
+postMessage('1');
diff --git a/tests/wpt/web-platform-tests/workers/constructors/Worker/AbstractWorker.onerror.html b/tests/wpt/web-platform-tests/workers/constructors/Worker/AbstractWorker.onerror.html
new file mode 100644
index 00000000000..5858b1c005d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/constructors/Worker/AbstractWorker.onerror.html
@@ -0,0 +1,41 @@
+<!--
+for (;) // should cause onerror to be invoked, but onerror is null, so
+ // the error is "not handled". should fire an ErrorEvent on the
+ // worker.
+ break;
+postMessage(1); // shouldn't do anything since the script doesn't compile
+/*
+-->
+<!doctype html>
+<title>AbstractWorker.onerror</title>
+<link rel=help href="http://www.whatwg.org/html/#runtime-script-errors-0">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var t = async_test();
+t.step(function() {
+ var worker = new Worker('#');
+ worker.onerror = function(a, b, c) {
+ t.step(function() {
+ assert_equals('' + a, '[object ErrorEvent]');
+ assert_true("message" in a, 'ErrorEvent.message');
+ assert_equals(typeof a.message, "string", 'ErrorEvent.message');
+ assert_equals(a.filename, document.URL + '#', 'ErrorEvent.filename');
+ assert_true("lineno" in a, 'ErrorEvent.lineno');
+ assert_equals(typeof a.lineno, "number", 'ErrorEvent.lineno');
+ assert_equals(b, undefined, 'unexpected second argument to onerror');
+ assert_equals(c, undefined, 'unexpected third argument to onerror');
+ });
+ t.done();
+ }
+ worker.onmessage = function(e) {
+ t.step(function() {
+ assert_unreached('onmessage was invoked but worker script shouldn\'t have compiled');
+ });
+ }
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/constructors/Worker/DedicatedWorkerGlobalScope-members.html b/tests/wpt/web-platform-tests/workers/constructors/Worker/DedicatedWorkerGlobalScope-members.html
new file mode 100644
index 00000000000..24f8b642696
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/constructors/Worker/DedicatedWorkerGlobalScope-members.html
@@ -0,0 +1,34 @@
+<!--
+var expected = [
+ 'postMessage', 'onmessage', /* DedicatedWorkerGlobalScope */
+ 'self', 'location', 'close', 'onerror', 'onoffline', 'ononline', /* WorkerGlobalScope */
+ 'addEventListener', 'removeEventListener', 'dispatchEvent', /* EventListener */
+ 'importScripts', 'navigator', /* WorkerUtils */
+ 'setTimeout', 'clearTimeout', 'setInterval', 'clearInterval', /* WindowTimers */
+ 'btoa', 'atob' /* WindowBase64 */
+];
+for (var i = 0; i < expected.length; ++i) {
+ if (!(expected[i] in self)) {
+ postMessage(expected[i] + ' did not exist');
+ }
+}
+postMessage('done');
+/*
+-->
+<!doctype html>
+<title>members of DedicatedWorkerGlobalScope</title>
+<link rel=help href="http://www.whatwg.org/html/#dom-worker">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../workers.js"></script>
+<div id="log"></div>
+<script>
+var t = async_test();
+t.step(function() {
+ var worker = new Worker('#');
+ listenForMessages(t, worker);
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/constructors/Worker/ctor-1.html b/tests/wpt/web-platform-tests/workers/constructors/Worker/ctor-1.html
new file mode 100644
index 00000000000..bd865261fc6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/constructors/Worker/ctor-1.html
@@ -0,0 +1,23 @@
+<!--
+postMessage('FAIL');
+/*
+-->
+<!doctype html>
+<title>1 as argument</title>
+<link rel=help href="http://www.whatwg.org/html/#dom-worker">
+<link rel=help href="http://dev.w3.org/2006/webapi/WebIDL/#es-DOMString">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var t = async_test();
+t.step(function() {
+ var worker = new Worker(1);
+ worker.addEventListener('message', t.step_func_done(function(e) {
+ assert_equals(e.data, '1')
+ }), false);
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/constructors/Worker/ctor-null.html b/tests/wpt/web-platform-tests/workers/constructors/Worker/ctor-null.html
new file mode 100644
index 00000000000..94ab71aeff6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/constructors/Worker/ctor-null.html
@@ -0,0 +1,23 @@
+<!--
+postMessage('FAIL');
+/*
+-->
+<!doctype html>
+<title>null as argument</title>
+<link rel=help href="http://www.whatwg.org/html/#dom-worker">
+<link rel=help href="http://dev.w3.org/2006/webapi/WebIDL/#es-DOMString">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var t = async_test();
+t.step(function() {
+ var worker = new Worker(null);
+ worker.addEventListener('message', t.step_func_done(function(e) {
+ assert_equals(e.data, 'null')
+ }), false);
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/constructors/Worker/ctor-undefined.html b/tests/wpt/web-platform-tests/workers/constructors/Worker/ctor-undefined.html
new file mode 100644
index 00000000000..2d9eb6e6563
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/constructors/Worker/ctor-undefined.html
@@ -0,0 +1,23 @@
+<!--
+postMessage('FAIL');
+/*
+-->
+<!doctype html>
+<title>undefined as argument</title>
+<link rel=help href="http://www.whatwg.org/html/#dom-worker">
+<link rel=help href="http://dev.w3.org/2006/webapi/WebIDL/#es-DOMString">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var t = async_test();
+t.step(function() {
+ var worker = new Worker(undefined);
+ worker.addEventListener('message', t.step_func_done(function(e) {
+ assert_equals(e.data, 'undefined')
+ }), false);
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/constructors/Worker/expected-self-properties.html b/tests/wpt/web-platform-tests/workers/constructors/Worker/expected-self-properties.html
new file mode 100644
index 00000000000..3fc4e3bac98
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/constructors/Worker/expected-self-properties.html
@@ -0,0 +1,30 @@
+<!--
+onmessage = function(e) {
+ for (var i = 0; i < e.data.length; ++i) {
+ if (!(e.data[i] in self)) {
+ postMessage(e.data[i] + ' did not exist');
+ }
+ }
+ postMessage('done');
+}
+/*
+-->
+<!doctype html>
+<title>expected interface objects/constructors</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../workers.js"></script>
+<div id="log"></div>
+<script>
+var t = async_test();
+t.step(function() {
+ var expected = ['XMLHttpRequest', 'WebSocket', 'EventSource', 'MessageChannel', 'Worker', 'SharedWorker'];
+ var supported = expected.filter(function(iface) { return iface in window; });
+ var worker = new Worker('#');
+ listenForMessages(t, worker);
+ worker.postMessage(supported);
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/constructors/Worker/no-arguments-ctor.html b/tests/wpt/web-platform-tests/workers/constructors/Worker/no-arguments-ctor.html
new file mode 100644
index 00000000000..770c7cc93a9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/constructors/Worker/no-arguments-ctor.html
@@ -0,0 +1,13 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>without arguments</title>
+<link rel=help href="http://dev.w3.org/2006/webapi/WebIDL/#es-interface-call">
+<link rel=help href="http://www.whatwg.org/html/#dedicated-workers-and-the-worker-interface">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ assert_throws(new TypeError(), function() { new Worker(); });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/workers/constructors/Worker/null b/tests/wpt/web-platform-tests/workers/constructors/Worker/null
new file mode 100644
index 00000000000..6d079b514cf
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/constructors/Worker/null
@@ -0,0 +1 @@
+postMessage('null');
diff --git a/tests/wpt/web-platform-tests/workers/constructors/Worker/resolve-empty-string.html b/tests/wpt/web-platform-tests/workers/constructors/Worker/resolve-empty-string.html
new file mode 100644
index 00000000000..0426223e0a8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/constructors/Worker/resolve-empty-string.html
@@ -0,0 +1,22 @@
+<!--
+postMessage('ok');
+/*
+-->
+<!doctype html>
+<meta charset=utf-8>
+<title>resolve the empty string</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var t = async_test();
+t.step(function() {
+ var worker = new Worker('');
+ worker.addEventListener('message', t.step_func_done(function(e) {
+ assert_equals(e.data, 'ok');
+ }), false);
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/constructors/Worker/same-origin.html b/tests/wpt/web-platform-tests/workers/constructors/Worker/same-origin.html
new file mode 100644
index 00000000000..0b4f2de5960
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/constructors/Worker/same-origin.html
@@ -0,0 +1,51 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>same-origin checks; the script is in a script element</title>
+<link rel=help href="http://www.whatwg.org/html/#dom-worker">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+// Needed to prevent a race condition if a worker throws an exception that may or may
+// not propogate to the window before the tests finish
+setup({allow_uncaught_exception: true});
+
+test(function() {
+ assert_throws("SecurityError", function() { new Worker('unsupported:'); });
+}, "unsupported_scheme");
+
+async_test(function() {
+ var worker = new Worker('data:,postMessage(1);');
+ worker.onmessage = this.step_func_done(function(e) {
+ assert_equals(e.data, 1);
+ });
+}, "data_url");
+
+test(function() {
+ assert_throws("SecurityError", function() { new Worker('about:blank'); });
+}, "about_blank");
+
+test(function() {
+ assert_throws("SecurityError", function() { new Worker('http://www.example.invalid/'); });
+}, "example_invalid");
+
+test(function() {
+ assert_throws("SecurityError", function() { new Worker(location.protocol+'//'+location.hostname+':81/'); });
+}, "port_81");
+
+test(function() {
+ assert_throws("SecurityError", function() { new Worker('https://'+location.hostname+':80/'); });
+}, "https_port_80");
+
+test(function() {
+ assert_throws("SecurityError", function() { new Worker('https://'+location.hostname+':8000/'); });
+}, "https_port_8000");
+
+test(function() {
+ assert_throws("SecurityError", function() { new Worker('http://'+location.hostname+':8012/'); });
+}, "http_post_8012");
+
+test(function() {
+ assert_throws("SecurityError", function() { new Worker('javascript:""'); });
+}, "javascript_url");
+</script>
diff --git a/tests/wpt/web-platform-tests/workers/constructors/Worker/terminate.html b/tests/wpt/web-platform-tests/workers/constructors/Worker/terminate.html
new file mode 100644
index 00000000000..2e85c926568
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/constructors/Worker/terminate.html
@@ -0,0 +1,45 @@
+<!--
+(function f() {
+ postMessage(1);
+ setTimeout(f, 0);
+})();
+/*
+-->
+<!doctype html>
+<title>terminate()</title>
+<link rel=help href="http://www.whatwg.org/html/#dom-worker-terminate">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../workers.js"></script>
+<div id="log"></div>
+<script>
+var t = async_test();
+t.step(function() {
+ var worker = new Worker('#');
+ var i = 0;
+ var expected;
+
+ worker.onmessage = t.step_func(function() {
+ i++;
+ });
+
+ setTimeout(t.step_func(function() {
+ expected = i;
+ start_time = Date.now();
+ //Hang the main thread for a bit to give the worker the chance to post some more messages
+ while(Date.now() - start_time < 500) {
+ //pass
+ }
+ worker.terminate();
+
+ setTimeout(t.step_func(function() {
+ assert_equals(i, expected);
+ t.done();
+ }), 100);
+
+ }), 100);
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/constructors/Worker/undefined b/tests/wpt/web-platform-tests/workers/constructors/Worker/undefined
new file mode 100644
index 00000000000..bc7f482e94a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/constructors/Worker/undefined
@@ -0,0 +1 @@
+postMessage('undefined');
diff --git a/tests/wpt/web-platform-tests/workers/constructors/Worker/unexpected-self-properties.html b/tests/wpt/web-platform-tests/workers/constructors/Worker/unexpected-self-properties.html
new file mode 100644
index 00000000000..683cdf26892
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/constructors/Worker/unexpected-self-properties.html
@@ -0,0 +1,26 @@
+<!--
+var unexpected = ['open', 'print', 'stop', 'getComputedStyle', 'getSelection', 'releaseEvents', 'captureEvents', 'alert', 'confirm', 'prompt', 'addEventStream', 'removeEventStream', 'back', 'forward', 'attachEvent', 'detachEvent', 'navigate', 'DOMParser', 'XMLSerializer', 'XPathEvaluator', 'XSLTProcessor', 'opera', 'Image', 'Option', 'frames', 'Audio', 'SVGUnitTypes', 'SVGZoomAndPan', 'java', 'netscape', 'sun', 'Packages', 'ByteArray', 'closed', 'defaultStatus', 'document', 'event', 'frameElement', 'history', 'innerHeight', 'innerWidth', 'name', 'opener', 'outerHeight', 'outerWidth', 'pageXOffset', 'pageYOffset', 'parent', 'screen', 'screenLeft', 'screenTop', 'screenX', 'screenY', 'status', 'top', 'window', 'length']; // iterated window in opera and removed expected ones
+for (var i = 0; i < unexpected.length; ++i) {
+ if (unexpected[i] in self) {
+ postMessage(unexpected[i] + ' existed');
+ }
+}
+postMessage('done');
+/*
+-->
+<!doctype html>
+<title>unexpected members/interface objects/constructors</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../workers.js"></script>
+<div id="log"></div>
+<script>
+var t = async_test();
+t.step(function() {
+ var worker = new Worker('#');
+ listenForMessages(t, worker);
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/constructors/Worker/unresolvable-url.html b/tests/wpt/web-platform-tests/workers/constructors/Worker/unresolvable-url.html
new file mode 100644
index 00000000000..8c04b008783
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/constructors/Worker/unresolvable-url.html
@@ -0,0 +1,12 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>unresolvable url</title>
+<link rel=help href="http://www.whatwg.org/html/#dom-worker">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ assert_throws("SyntaxError", function() { new Worker('http://invalid url/'); });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/workers/interfaces.idl b/tests/wpt/web-platform-tests/workers/interfaces.idl
new file mode 100644
index 00000000000..5bfd2883525
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces.idl
@@ -0,0 +1,116 @@
+// -----------------------------------------------------------------------------
+// URL
+// -----------------------------------------------------------------------------
+[NoInterfaceObject/*,
+ Exposed=(Window,Worker)*/]
+interface URLUtilsReadOnly {
+ stringifier readonly attribute USVString href;
+ readonly attribute USVString origin;
+
+ readonly attribute USVString protocol;
+ readonly attribute USVString host;
+ readonly attribute USVString hostname;
+ readonly attribute USVString port;
+ readonly attribute USVString pathname;
+ readonly attribute USVString search;
+ readonly attribute USVString hash;
+};
+
+// -----------------------------------------------------------------------------
+// DOM
+// -----------------------------------------------------------------------------
+//[Exposed=Window,Worker]
+interface EventTarget {
+ void addEventListener(DOMString type, EventListener? callback, optional boolean capture = false);
+ void removeEventListener(DOMString type, EventListener? callback, optional boolean capture = false);
+ boolean dispatchEvent(Event event);
+};
+
+callback interface EventListener {
+ void handleEvent(Event event);
+};
+
+// -----------------------------------------------------------------------------
+// HTML
+// -----------------------------------------------------------------------------
+[TreatNonCallableAsNull]
+callback EventHandlerNonNull = any (Event event);
+typedef EventHandlerNonNull? EventHandler;
+
+[TreatNonCallableAsNull]
+callback OnErrorEventHandlerNonNull = any ((Event or DOMString) event, optional DOMString source, optional unsigned long lineno, optional unsigned long column, optional any error);
+typedef OnErrorEventHandlerNonNull? OnErrorEventHandler;
+
+//[Exposed=Worker]
+interface WorkerGlobalScope : EventTarget {
+ readonly attribute WorkerGlobalScope self;
+ readonly attribute WorkerLocation location;
+
+ void close();
+ attribute OnErrorEventHandler onerror;
+ attribute EventHandler onlanguagechange;
+ attribute EventHandler onoffline;
+ attribute EventHandler ononline;
+};
+
+[Global/*=(Worker,DedicatedWorker),Exposed=DedicatedWorker*/]
+/*sealed*/ interface DedicatedWorkerGlobalScope : WorkerGlobalScope {
+ void postMessage(any message, optional sequence<Transferable> transfer);
+ attribute EventHandler onmessage;
+};
+
+//[Exposed=Worker]
+partial interface WorkerGlobalScope { // not obsolete
+ void importScripts(DOMString... urls);
+ readonly attribute WorkerNavigator navigator;
+};
+WorkerGlobalScope implements WindowTimers;
+WorkerGlobalScope implements WindowBase64;
+
+[NoInterfaceObject/*, Exposed=(Window,Worker)*/]
+interface WindowTimers {
+ long setTimeout(Function handler, optional long timeout = 0, any... arguments);
+ long setTimeout(DOMString handler, optional long timeout = 0, any... arguments);
+ void clearTimeout(optional long handle = 0);
+ long setInterval(Function handler, optional long timeout = 0, any... arguments);
+ long setInterval(DOMString handler, optional long timeout = 0, any... arguments);
+ void clearInterval(optional long handle = 0);
+};
+
+[NoInterfaceObject/*, Exposed=(Window,Worker)*/]
+interface WindowBase64 {
+ DOMString btoa(DOMString btoa);
+ DOMString atob(DOMString atob);
+};
+
+//[Exposed=Worker]
+interface WorkerNavigator {};
+WorkerNavigator implements NavigatorID;
+WorkerNavigator implements NavigatorLanguage;
+WorkerNavigator implements NavigatorOnLine;
+
+[NoInterfaceObject/*, Exposed=(Window,Worker)*/]
+interface NavigatorID {
+ readonly attribute DOMString appCodeName; // constant "Mozilla"
+ readonly attribute DOMString appName;
+ readonly attribute DOMString appVersion;
+ readonly attribute DOMString platform;
+ readonly attribute DOMString product; // constant "Gecko"
+ boolean taintEnabled(); // constant false
+ readonly attribute DOMString userAgent;
+};
+
+[NoInterfaceObject/*, Exposed=(Window,Worker)*/]
+interface NavigatorLanguage {
+ readonly attribute DOMString? language;
+ readonly attribute DOMString[] languages;
+};
+
+[NoInterfaceObject/*, Exposed=(Window,Worker)*/]
+interface NavigatorOnLine {
+ readonly attribute boolean onLine;
+};
+
+//[Exposed=Worker]
+interface WorkerLocation { };
+WorkerLocation implements URLUtilsReadOnly;
diff --git a/tests/wpt/web-platform-tests/workers/interfaces.worker.js b/tests/wpt/web-platform-tests/workers/interfaces.worker.js
new file mode 100644
index 00000000000..f07669ba71c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces.worker.js
@@ -0,0 +1,20 @@
+"use strict";
+
+importScripts("/resources/testharness.js");
+importScripts("/resources/WebIDLParser.js", "/resources/idlharness.js");
+
+var request = new XMLHttpRequest();
+request.onload = function() {
+ var idlArray = new IdlArray();
+ var idls = request.responseText;
+ idlArray.add_idls(idls);
+ idlArray.add_objects({
+ DedicatedWorkerGlobalScope: ['self'],
+ WorkerNavigator: ['self.navigator'],
+ WorkerLocation: ['self.location'],
+ });
+ idlArray.test();
+ done();
+};
+request.open("GET", "interfaces.idl");
+request.send();
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/DedicatedWorkerGlobalScope/EventTarget.worker.js b/tests/wpt/web-platform-tests/workers/interfaces/DedicatedWorkerGlobalScope/EventTarget.worker.js
new file mode 100644
index 00000000000..ff0c6fc951c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/DedicatedWorkerGlobalScope/EventTarget.worker.js
@@ -0,0 +1,21 @@
+importScripts("/resources/testharness.js");
+
+test(function() {
+ var i = 0;
+ addEventListener("message", this.step_func(function listener(evt) {
+ ++i;
+ removeEventListener("message", listener, true);
+ }), true);
+ self.dispatchEvent(new Event("message"));
+ self.dispatchEvent(new Event("message"));
+ assert_equals(i, 1);
+}, "removeEventListener");
+
+test(function() {
+ addEventListener("message", this.step_func(function(evt) {
+ assert_equals(evt.target, self);
+ }), true);
+ self.dispatchEvent(new Event("message"));
+}, "target");
+
+done();
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/DedicatedWorkerGlobalScope/onmessage.worker.js b/tests/wpt/web-platform-tests/workers/interfaces/DedicatedWorkerGlobalScope/onmessage.worker.js
new file mode 100644
index 00000000000..6f285caac38
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/DedicatedWorkerGlobalScope/onmessage.worker.js
@@ -0,0 +1,40 @@
+importScripts("/resources/testharness.js");
+
+test(function() {
+ self.onmessage = 1;
+ assert_equals(self.onmessage, null,
+ "attribute should return null after being set to a primitive");
+}, "Setting onmessage to 1");
+
+test(function() {
+ var object = {
+ handleEvent: this.unreached_func()
+ };
+ self.onmessage = object;
+ assert_equals(self.onmessage, object,
+ "attribute should return the object it was set to.");
+
+ self.dispatchEvent(new Event("message"));
+}, "Setting onmessage to an object");
+
+test(function() {
+ var triggered = false;
+ var f = function(e) { triggered = true; };
+ self.onmessage = f;
+ assert_equals(self.onmessage, f,
+ "attribute should return the function it was set to.");
+
+ self.dispatchEvent(new Event("message"));
+ assert_true(triggered, "event handler should have been triggered");
+}, "Setting onmessage to a function");
+
+
+test(function() {
+ assert_not_equals(self.onmessage, null,
+ "attribute should not return null after being set to a function");
+ self.onmessage = 1;
+ assert_equals(self.onmessage, null,
+ "attribute should return null after being set to a primitive");
+}, "Setting onmessage to 1 (again)");
+
+done();
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/event-ports-dedicated.html b/tests/wpt/web-platform-tests/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/event-ports-dedicated.html
new file mode 100644
index 00000000000..7ae4b070474
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/event-ports-dedicated.html
@@ -0,0 +1,25 @@
+<!--
+onmessage = function(e) {
+ postMessage(e.ports instanceof Array && e.ports.length === 0);
+}
+/*
+-->
+<!doctype html>
+<title>e.ports in dedicated worker</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+(async_test()).step(function() {
+ var worker = new Worker('#');
+ worker.postMessage(1);
+ worker.onmessage = this.step_func(function(e) {
+ assert_true(e.data);
+ this.done();
+ });
+});
+</script>
+<!--
+*/
+//-->
+
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/imagedata-cloned-canvas-in-array.html b/tests/wpt/web-platform-tests/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/imagedata-cloned-canvas-in-array.html
new file mode 100644
index 00000000000..20413015418
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/imagedata-cloned-canvas-in-array.html
@@ -0,0 +1,39 @@
+<!--
+onmessage = function(e) {
+ function processPixels(imagedata) {
+ var pixeldata = imagedata.data;
+ for (var i = 0; i < pixeldata.length; i = i+4) {
+ pixeldata[i] = 128;
+ }
+ postMessage(imagedata);
+ }
+ processPixels(e.data[0]);
+}
+
+/*
+-->
+<!doctype html>
+<title>posting an imagedata (from a cloned canvas) in an array</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+(async_test()).step(function() {
+ var worker = new Worker('#');
+ var canvas = document.createElement('canvas');
+ var clone = canvas.cloneNode(true);
+ var ctx = clone.getContext('2d');
+ var imagedata = ctx.getImageData(0, 0, 300, 150);
+ worker.postMessage([imagedata]);
+ worker.onmessage = this.step_func(function(e) {
+ var pixeldata = e.data.data;
+ for (var i = 0; i < pixeldata.length; i++) {
+ assert_equals(pixeldata[i], (i % 4 == 0) ? 128 : 0);
+ }
+ this.done();
+ });
+});
+</script>
+<!--
+*/
+//--> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/message-event.html b/tests/wpt/web-platform-tests/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/message-event.html
new file mode 100644
index 00000000000..91ec632685f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/message-event.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>'message' event properties</title>
+<link rel=help href="http://www.whatwg.org/html/#dom-dedicatedworkerglobalscope-postmessage">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+async_test("Properties of the 'message' event").step(function() {
+ var worker = new Worker("message-event.js");
+ worker.onmessage = this.step_func_done(function (evt) {
+ assert_class_string(evt, "MessageEvent");
+ assert_equals(evt.type, "message");
+ assert_false(evt.bubbles, "bubbles should be false");
+ assert_false(evt.cancelable, "cancelable should be false");
+ assert_equals(evt.data, "test");
+ assert_equals(evt.origin, "", "origin");
+ assert_equals(evt.lastEventId, "", "lastEventId");
+ assert_equals(evt.source, null, "source");
+ assert_array_equals(evt.ports, [], "ports");
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/message-event.js b/tests/wpt/web-platform-tests/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/message-event.js
new file mode 100644
index 00000000000..54a250005e8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/message-event.js
@@ -0,0 +1 @@
+postMessage("test");
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/return-value.worker.js b/tests/wpt/web-platform-tests/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/return-value.worker.js
new file mode 100644
index 00000000000..521251699a0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/return-value.worker.js
@@ -0,0 +1,8 @@
+importScripts("/resources/testharness.js");
+
+test(function() {
+ var rv = postMessage(1);
+ assert_equals(rv, undefined);
+}, "return value of postMessage");
+
+done();
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/second-argument-null-in-array.html b/tests/wpt/web-platform-tests/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/second-argument-null-in-array.html
new file mode 100644
index 00000000000..df4c9f83e6f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/second-argument-null-in-array.html
@@ -0,0 +1,26 @@
+<!--
+try {
+ postMessage(false, [null]);
+} catch(e) {
+ postMessage(e instanceof TypeError);
+}
+/*
+-->
+<!doctype html>
+<title>Using [null] in postMessage's second argument</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+(async_test()).step(function() {
+ var worker = new Worker('#');
+ worker.onmessage = this.step_func(function(e) {
+ assert_true(e.data);
+ this.done();
+ });
+});
+</script>
+<!--
+*/
+//-->
+
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/second-argument-null.html b/tests/wpt/web-platform-tests/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/second-argument-null.html
new file mode 100644
index 00000000000..e81a56bad3d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/second-argument-null.html
@@ -0,0 +1,25 @@
+<!--
+try {
+ postMessage(1, null);
+} catch(e) {
+ postMessage(e instanceof TypeError);
+}
+/*
+-->
+<!doctype html>
+<title>Using null in postMessage's second argument</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+(async_test()).step(function() {
+ var worker = new Worker('#');
+ worker.onmessage = this.step_func(function(e) {
+ assert_true(e.data);
+ this.done();
+ });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/second-argument-undefined.html b/tests/wpt/web-platform-tests/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/second-argument-undefined.html
new file mode 100644
index 00000000000..7d01eba7aff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/second-argument-undefined.html
@@ -0,0 +1,25 @@
+<!--
+try {
+ postMessage(1, undefined);
+} catch(e) {
+ postMessage(''+e);
+}
+/*
+-->
+<!doctype html>
+<title>Using undefined in postMessage's second argument</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+(async_test()).step(function() {
+ var worker = new Worker('#');
+ worker.onmessage = this.step_func(function(e) {
+ assert_equals(e.data, 1);
+ this.done();
+ });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/setting-postMessage.html b/tests/wpt/web-platform-tests/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/setting-postMessage.html
new file mode 100644
index 00000000000..d1a3f0f5c70
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/setting-postMessage.html
@@ -0,0 +1,24 @@
+<!--
+var x = postMessage;
+postMessage = 1;
+x(postMessage == 1);
+
+/*
+-->
+<!doctype html>
+<title>setting postMessage</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+(async_test()).step(function() {
+ var worker = new Worker('#');
+ worker.onmessage = this.step_func(function(e) {
+ assert_true(e.data);
+ this.done();
+ });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/structured-clone-imagedata.html b/tests/wpt/web-platform-tests/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/structured-clone-imagedata.html
new file mode 100644
index 00000000000..c0ded6a2805
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/structured-clone-imagedata.html
@@ -0,0 +1,30 @@
+<!--
+onmessage = function(e) {
+ var imagedata = e.data;
+ imagedata.data[0] = 128;
+ postMessage(imagedata);
+}
+
+/*
+-->
+<!doctype html>
+<title>structured clone of ImageData</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+(async_test()).step(function() {
+ var worker = new Worker('#');
+ var ctx = document.createElement('canvas').getContext('2d');
+ var imagedata = ctx.getImageData(0, 0, 300, 150);
+ worker.postMessage(imagedata);
+ worker.onmessage = this.step_func(function(e) {
+ assert_equals(''+e.data, '[object ImageData]');
+ assert_equals(e.data.data[0], 128);
+ this.done();
+ });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/structured-clone-message.html b/tests/wpt/web-platform-tests/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/structured-clone-message.html
new file mode 100644
index 00000000000..ba357421f99
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/DedicatedWorkerGlobalScope/postMessage/structured-clone-message.html
@@ -0,0 +1,58 @@
+<!--
+var err = new Error('foo');
+var date = new Date();
+// commented out bits are either tested elsewhere or not supported yet. or uncloneable.
+var tests = [undefined, null, false, true, 1, NaN, Infinity, 'foo', date, /foo/, /* ImageData, File, FileData, FileList,*/ null/*self*/,
+ [undefined, null, false, true, 1, NaN, Infinity, 'foo', /*date, /foo/,*/ null/*self*/, /*[], {},*/ null/*err*/],
+ {a:undefined, b:null, c:false, d:true, e:1, f:NaN, g:Infinity, h:'foo', /*i:date, j:/foo/,*/ k:null/*self*/, /*l:[], m:{},*/ n:null/*err*/},
+ null/*err*/];
+for (var i = 0; i < tests.length; ++i) {
+ try {
+ postMessage(tests[i]);
+ } catch(e) {
+ postMessage(''+e);
+ }
+}
+/*
+-->
+<!doctype html>
+<title>structured clone of message</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var wrapper_test = async_test();
+var tests = [
+ {test:async_test('undefined'), check:function(e) { assert_equals(e.data, undefined); }},
+ {test:async_test('null'), check:function(e) { assert_equals(e.data, null); }},
+ {test:async_test('false'), check:function(e) { assert_false(e.data); }},
+ {test:async_test('true'), check:function(e) { assert_true(e.data); }},
+ {test:async_test('1'), check:function(e) { assert_equals(e.data, 1); }},
+ {test:async_test('NaN'), check:function(e) { assert_equals(e.data, NaN); }},
+ {test:async_test('Infinity'), check:function(e) { assert_equals(e.data, Infinity); }},
+ {test:async_test('string'), check:function(e) { assert_equals(e.data, 'foo'); }},
+ {test:async_test('date'), check:function(e) { assert_equals(e.data instanceof Date, true); }},
+ {test:async_test('regexp'), check:function(e) { assert_equals('' + e.data, '/foo/'); assert_equals(e.data instanceof RegExp, true, 'e.data instanceof RegExp'); }},
+ {test:async_test('self'), check:function(e) { assert_equals(e.data, null); }},
+ {test:async_test('array'), check:function(e) { assert_array_equals(e.data, [undefined, null, false, true, 1, NaN, Infinity, 'foo', null, null]); }},
+ {test:async_test('object'), check:function(e) { assert_object_equals(e.data, {a:undefined, b:null, c:false, d:true, e:1, f:NaN, g:Infinity, h:'foo', k:null, n:null}); }},
+ {test:async_test('error'), check:function(e) { assert_equals(e.data, null, 'new Error()'); }},
+ {test:wrapper_test, check:function(e) { assert_unreached(); }}
+];
+// make wrapper_test pass after 500ms
+setTimeout(tests[tests.length-1].test.step_func(function() {
+ this.done();
+}), 500);
+
+wrapper_test.step(function() {
+ var worker = new Worker('#');
+ var i = 0;
+ worker.onmessage = function(e) {
+ tests[i].test.step(function() { tests[i].check(e); this.done(); });
+ i++;
+ };
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/SharedWorkerGlobalScope/name/getting.html b/tests/wpt/web-platform-tests/workers/interfaces/SharedWorkerGlobalScope/name/getting.html
new file mode 100644
index 00000000000..bfe81a8a9c0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/SharedWorkerGlobalScope/name/getting.html
@@ -0,0 +1,34 @@
+<!--
+addEventListener('connect', function(e) {
+ var passed;
+ switch (location.hash) {
+ case '#1': passed = name == ''; break;
+ case '#2': passed = name == 'a'; break;
+ case '#3': passed = name == '0'; break;
+ }
+ e.ports[0].postMessage(passed);
+}, false);
+/*
+-->
+<!doctype html>
+<title>getting name</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var tests = [['#1', ''], ['#2', 'a'], ['#3', -0]];
+tests.forEach(function(t) {
+ async_test(function() {
+ var w = new SharedWorker(t[0], t[1]);
+ w.port.onmessage = this.step_func(function(e) {
+ assert_true(e.data);
+ this.done();
+ });
+ });
+});
+</script>
+<!--
+*/
+//-->
+
+
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/SharedWorkerGlobalScope/name/setting.html b/tests/wpt/web-platform-tests/workers/interfaces/SharedWorkerGlobalScope/name/setting.html
new file mode 100644
index 00000000000..39cdf7b674b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/SharedWorkerGlobalScope/name/setting.html
@@ -0,0 +1,25 @@
+<!--
+addEventListener('connect', function(e) {
+ name = 1;
+ e.ports[0].postMessage(name);
+}, false);
+/*
+-->
+<!doctype html>
+<title>setting name</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+ var w1 = new SharedWorker('#1', 'x');
+ w1.port.addEventListener('message', this.step_func(function(e) {
+ assert_equals(e.data, 'x');
+ this.done();
+ }), false);
+ w1.port.start();
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/SharedWorkerGlobalScope/onconnect.html b/tests/wpt/web-platform-tests/workers/interfaces/SharedWorkerGlobalScope/onconnect.html
new file mode 100644
index 00000000000..2ad155bf7a9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/SharedWorkerGlobalScope/onconnect.html
@@ -0,0 +1,39 @@
+<!--
+var results = [];
+try {
+ self.onconnect = 1;
+ results.push(String(onconnect));
+} catch(e) {
+ results.push(''+e);
+}
+try {
+ self.onconnect = {handleEvent:function(){}};
+ results.push(String(onconnect));
+} catch(e) {
+ results.push(''+e);
+}
+var f = function(e) {
+ results.push(e.data);
+ e.ports[0].postMessage(results);
+};
+onconnect = f;
+results.push(typeof onconnect);
+/*
+-->
+<!doctype html>
+<title>onconnect</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+ var w1 = new SharedWorker('#', '');
+ w1.port.addEventListener('message', this.step_func(function(e) {
+ assert_array_equals(e.data, ['null', 'null', 'function', '']);
+ }), false);
+ w1.port.start();
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/close/incoming-message.html b/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/close/incoming-message.html
new file mode 100644
index 00000000000..767693da02e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/close/incoming-message.html
@@ -0,0 +1,37 @@
+<!--
+onmessage = function(e) {
+ postMessage(1);
+ throw new Error();
+}
+close();
+/*
+-->
+<!doctype html>
+<title>close() and incoming message</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+ var gotMessage = false;
+ var gotError = false;
+ var worker = new Worker('#');
+ worker.onmessage = function(e) {
+ gotMessage = true;
+ };
+ worker.onerror = function(e) {
+ gotError = true;
+ };
+ worker.postMessage(1);
+ setTimeout(this.step_func(function() {
+ assert_false(gotMessage, 'got message');
+ assert_true(gotError, 'got error');
+ this.done();
+ }), 500);
+});
+</script>
+<!--
+*/
+//-->
+
+
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/close/sending-messages.html b/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/close/sending-messages.html
new file mode 100644
index 00000000000..983c422cc55
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/close/sending-messages.html
@@ -0,0 +1,27 @@
+<!--
+postMessage(1);
+close();
+postMessage(2);
+/*
+-->
+<!doctype html>
+<title>close() and sending messages</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+ var worker = new Worker('#');
+ var i = 0;
+ worker.onmessage = this.step_func(function(e) {
+ i++;
+ assert_equals(e.data, i);
+ if (i == 2) {
+ this.done();
+ }
+ });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/close/setInterval.html b/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/close/setInterval.html
new file mode 100644
index 00000000000..cd7130785a9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/close/setInterval.html
@@ -0,0 +1,42 @@
+<!--
+var interval1 = setInterval(function() {
+ clearInterval(interval1);
+ postMessage(1);
+ throw new Error();
+}, 10);
+close();
+var interval2 = setInterval(function() {
+ clearInterval(interval2);
+ postMessage(1);
+ throw new Error();
+}, 10);
+/*
+-->
+<!doctype html>
+<title>close() and setInterval</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+ var gotMessage = false;
+ var gotError = false;
+ var worker = new Worker('#');
+ worker.onmessage = function(e) {
+ gotMessage = true;
+ };
+ worker.onerror = function(e) {
+ gotError = true;
+ };
+ setTimeout(this.step_func(function() {
+ assert_false(gotMessage, 'got message');
+ assert_true(gotError, 'got error');
+ this.done();
+ }), 500);
+});
+</script>
+<!--
+*/
+//-->
+
+
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/close/setTimeout.html b/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/close/setTimeout.html
new file mode 100644
index 00000000000..19686650aa5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/close/setTimeout.html
@@ -0,0 +1,40 @@
+<!--
+function x() {
+ postMessage(1);
+ throw new Error();
+}
+setTimeout(x, 0);
+close();
+setTimeout(x, 0);
+/*
+-->
+<!doctype html>
+<title>close() and setTimeout</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+setup({allow_uncaught_exception: true});
+
+async_test(function() {
+ var gotMessage = false;
+ var gotError = false;
+ var worker = new Worker('#');
+ worker.onmessage = function(e) {
+ gotMessage = true;
+ };
+ worker.onerror = function(e) {
+ gotError = true;
+ };
+ setTimeout(this.step_func(function() {
+ assert_false(gotMessage, 'got message');
+ assert_true(gotError, 'got error');
+ this.done();
+ }), 500);
+});
+</script>
+<!--
+*/
+//-->
+
+
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/location/helper-redirect.py b/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/location/helper-redirect.py
new file mode 100644
index 00000000000..eb1599a577f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/location/helper-redirect.py
@@ -0,0 +1,3 @@
+def main(request, response):
+ response.status = 302
+ response.headers.append("Location", "post-location-members.js?a")
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/location/members.html b/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/location/members.html
new file mode 100644
index 00000000000..31ddf37a1b0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/location/members.html
@@ -0,0 +1,31 @@
+<!--
+postMessage([null, location.href, location.protocol, location.host,
+ location.hostname, location.port, location.pathname,
+ location.search, location.hash]);
+/*
+-->
+<!doctype html>
+<title>members of WorkerLocation</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+ var worker = new Worker('#');
+ worker.onmessage = this.step_func(function(e) {
+ assert_equals(e.data[0], null);
+ assert_equals(e.data[1], location.href + '#', 'href');
+ assert_equals(e.data[2], location.protocol, 'protocol');
+ assert_equals(e.data[3], location.host, 'host');
+ assert_equals(e.data[4], location.hostname, 'hostname');
+ assert_equals(e.data[5], location.port, 'port');
+ assert_equals(e.data[6], location.pathname, 'pathname');
+ assert_equals(e.data[7], location.search, 'search');
+ assert_equals(e.data[8], '', 'hash');
+ this.done();
+ });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/location/post-location-members.js b/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/location/post-location-members.js
new file mode 100644
index 00000000000..e850b76b6e5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/location/post-location-members.js
@@ -0,0 +1,8 @@
+postMessage([location.href,
+ location.protocol,
+ location.host,
+ location.hostname,
+ location.port,
+ location.pathname,
+ location.search,
+ location.hash]); \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/location/redirect.html b/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/location/redirect.html
new file mode 100644
index 00000000000..d939dc150da
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/location/redirect.html
@@ -0,0 +1,28 @@
+<!--
+/*
+-->
+<!doctype html>
+<title>location with a worker in separate file that redirects</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+ var worker = new Worker('helper-redirect.py?fail');
+ worker.onmessage = this.step_func(function(e) {
+ assert_equals(e.data[0], location.href.replace(/\/[^\/]+$/, '/post-location-members.js?a'));
+ assert_equals(e.data[1], location.protocol);
+ assert_equals(e.data[2], location.host);
+ assert_equals(e.data[3], location.hostname);
+ assert_equals(e.data[4], location.port);
+ assert_equals(e.data[5], location.pathname.replace(/\/[^\/]+$/, '/post-location-members.js'));
+ assert_equals(e.data[6], '?a');
+ assert_equals(e.data[7], '');
+ });
+});
+</script>
+<!--
+*/
+//-->
+
+
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/location/returns-same-object.html b/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/location/returns-same-object.html
new file mode 100644
index 00000000000..40559c1660c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/location/returns-same-object.html
@@ -0,0 +1,21 @@
+<!--
+postMessage(location === location);
+/*
+-->
+<!doctype html>
+<title>location === location</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+ var worker = new Worker('#');
+ worker.onmessage = this.step_func(function(e) {
+ assert_true(e.data);
+ this.done();
+ });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/location/setting-members.html b/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/location/setting-members.html
new file mode 100644
index 00000000000..d2f470ffcb4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/location/setting-members.html
@@ -0,0 +1,43 @@
+<!--
+var exceptions = [];
+try { location.href = 1; } catch(e) { exceptions.push('href'); }
+try { location.protocol = 1; } catch(e) { exceptions.push('protocol'); }
+try { location.host = 1; } catch(e) { exceptions.push('host'); }
+try { location.hostname = 1; } catch(e) { exceptions.push('hostname');}
+try { location.port = 1; } catch(e) { exceptions.push('port'); }
+try { location.pathname = 1; } catch(e) { exceptions.push('pathname'); }
+try { location.search = 1; } catch(e) { exceptions.push('search'); }
+try { location.hash = 1; } catch(e) { exceptions.push('hash'); }
+
+postMessage([null, location.href, location.protocol, location.host,
+ location.hostname, location.port, location.pathname,
+ location.search, location.hash, exceptions]);
+/*
+-->
+<!doctype html>
+<title>setting members of WorkerLocation</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+ var worker = new Worker('#');
+ worker.onmessage = this.step_func(function(e) {
+ assert_equals(e.data[0], null);
+ assert_equals(e.data[1], location.href + '#', 'href');
+ assert_equals(e.data[2], location.protocol, 'protocol');
+ assert_equals(e.data[3], location.host, 'host');
+ assert_equals(e.data[4], location.hostname, 'hostname');
+ assert_equals(e.data[5], location.port, 'port');
+ assert_equals(e.data[6], location.pathname, 'pathname');
+ assert_equals(e.data[7], location.search, 'search');
+ assert_equals(e.data[8], '', 'hash');
+ assert_array_equals(e.data[9], [], 'number of exceptions');
+ this.done();
+ });
+});
+</script>
+<!--
+*/
+//-->
+
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/location/worker-separate-file.html b/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/location/worker-separate-file.html
new file mode 100644
index 00000000000..ac8e64dcc88
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/location/worker-separate-file.html
@@ -0,0 +1,28 @@
+<!--
+/*
+-->
+<!doctype html>
+<title>location with a worker in separate file</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+ var worker = new Worker('post-location-members.js?a#b?c');
+ worker.onmessage = this.step_func(function(e) {
+ assert_equals(e.data[0], location.href.replace(/\/[^\/]+$/, '/post-location-members.js?a#b?c'));
+ assert_equals(e.data[1], location.protocol);
+ assert_equals(e.data[2], location.host);
+ assert_equals(e.data[3], location.hostname);
+ assert_equals(e.data[4], location.port);
+ assert_equals(e.data[5], location.pathname.replace(/\/[^\/]+$/, '/post-location-members.js'));
+ assert_equals(e.data[6], '?a');
+ assert_equals(e.data[7], '#b?c');
+ this.done();
+ });
+});
+</script>
+<!--
+*/
+//-->
+
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/onerror/exception-in-onerror.html b/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/onerror/exception-in-onerror.html
new file mode 100644
index 00000000000..79adef16014
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/onerror/exception-in-onerror.html
@@ -0,0 +1,32 @@
+<!--
+onerror = function(a, b, c, d) {
+ y(); // the error is "not handled"
+}
+function x() {
+ y();
+}
+x();
+/*
+-->
+<!doctype html>
+<title>onerror, "not handled" with an error in the onerror function</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+ var worker = new Worker('#');
+ worker.onerror = this.step_func(function(e) {
+ assert_true(e instanceof ErrorEvent, 'e instanceof ErrorEvent');
+ assert_equals(typeof e.message, 'string', 'typeof e.message');
+ assert_equals(e.filename, document.URL+'#', 'e.filename');
+ assert_equals(typeof e.lineno, 'number', 'typeof e.lineno');
+ assert_equals(typeof e.column, 'number', 'typeof e.column');
+ e.preventDefault(); // "handled"
+ this.done();
+ });
+});
+</script>
+<!--
+*/
+//--> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/onerror/handled.html b/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/onerror/handled.html
new file mode 100644
index 00000000000..56fee8e0635
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/onerror/handled.html
@@ -0,0 +1,36 @@
+<!--
+onerror = function(a, b, c, d) {
+ postMessage([a, b, c, d]);
+ return true; // the error is "handled"
+}
+function x() {
+ y();
+}
+x();
+/*
+-->
+<!doctype html>
+<title>onerror, "handled"</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+ var worker = new Worker('#');
+ worker.onmessage = this.step_func(function(e) {
+ assert_equals(typeof e.data[0], 'string', 'first argument');
+ assert_equals(e.data[1], document.URL+'#', 'second argument');
+ assert_equals(typeof e.data[2], 'number', 'third argument');
+ assert_equals(typeof e.data[3], 'number', 'fourth argument');
+ setTimeout(this.step_func(function() {
+ this.done();
+ }), 100);
+ });
+ worker.onerror = this.step_func(function(e) {
+ assert_unreached();
+ });
+});
+</script>
+<!--
+*/
+//--> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/onerror/not-handled.html b/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/onerror/not-handled.html
new file mode 100644
index 00000000000..96ee06dd207
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/onerror/not-handled.html
@@ -0,0 +1,32 @@
+<!--
+onerror = function(a, b, c, d) {
+ return false; // the error is "not handled"
+}
+function x() {
+ y();
+}
+x();
+/*
+-->
+<!doctype html>
+<title>onerror, "not handled"</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+ var worker = new Worker('#');
+ worker.onerror = this.step_func(function(e) {
+ assert_true(e instanceof ErrorEvent, 'e instanceof ErrorEvent');
+ assert_equals(typeof e.message, 'string', 'typeof e.message');
+ assert_equals(e.filename, document.URL+'#', 'e.filename');
+ assert_equals(typeof e.lineno, 'number', 'typeof e.lineno');
+ assert_equals(typeof e.column, 'number', 'typeof e.column');
+ e.preventDefault(); // "handled"
+ this.done();
+ });
+});
+</script>
+<!--
+*/
+//--> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/onerror/propagate-to-window-onerror.html b/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/onerror/propagate-to-window-onerror.html
new file mode 100644
index 00000000000..006321675b6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/onerror/propagate-to-window-onerror.html
@@ -0,0 +1,35 @@
+<!--
+function x() {
+ y();
+}
+x();
+/*
+-->
+<!doctype html>
+<title>onerror, "not handled" with only window.onerror defined</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+setup({
+ allow_uncaught_exception: true,
+});
+async_test(function() {
+ var worker = new Worker('#');
+ var timeout = setTimeout(this.step_func(function() {
+ assert_unreached();
+ }, 500));
+ window.onerror = this.step_func(function(a, b, c, d) {
+ assert_true(typeof a, 'string', 'first argument');
+ assert_equals(b, document.URL+'#', 'second argument');
+ assert_equals(typeof c, 'number', 'third argument');
+ assert_equals(typeof d, 'number', 'fourth argument');
+ clearTimeout(timeout);
+ this.done();
+ return true; // "handled"
+ });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/self.html b/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/self.html
new file mode 100644
index 00000000000..39c2c36c00d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/WorkerGlobalScope/self.html
@@ -0,0 +1,39 @@
+<!--
+var results = [];
+function check(func, msg) {
+ try {
+ results.push([func(), msg]);
+ } catch(ex) {
+ results.push([String(ex), msg]);
+ }
+}
+check(function() { return self === self; }, 'self === self');
+check(function() { return self instanceof WorkerGlobalScope; }, 'self instanceof WorkerGlobalScope');
+check(function() { return 'self' in self; }, '\'self\' in self');
+check(function() {
+ var x = self;
+ self = 1;
+ return x === self;
+}, 'self = 1');
+postMessage(results);
+/*
+-->
+<!doctype html>
+<title>self</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+ var worker = new Worker('#');
+ worker.onmessage = this.step_func(function(e) {
+ for (var i = 0; i < e.data.length; ++i) {
+ assert_true(e.data[i][0], e.data[i][1]);
+ }
+ this.done();
+ });
+});
+</script>
+<!--
+*/
+//--> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/WindowTimers/001.html b/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/WindowTimers/001.html
new file mode 100644
index 00000000000..a80897518a1
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/WindowTimers/001.html
@@ -0,0 +1,23 @@
+<!--
+setTimeout(function() { postMessage(1) }, 10);
+/*
+-->
+<!doctype html>
+<title>setTimeout</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+ var worker = new Worker('#');
+ worker.onmessage = this.step_func(function(e) {
+ assert_equals(e.data, 1);
+ this.done();
+ });
+});
+</script>
+<!--
+*/
+//-->
+
+
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/WindowTimers/002.html b/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/WindowTimers/002.html
new file mode 100644
index 00000000000..06685a9056a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/WindowTimers/002.html
@@ -0,0 +1,21 @@
+<!--
+var t = setTimeout(function() { postMessage(1); }, 10);
+clearTimeout(t);
+/*
+-->
+<!doctype html>
+<title>clearTimeout</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+ var worker = new Worker('#');
+ var gotMessage = false;
+ worker.onmessage = function() { gotMessage = true; };
+ setTimeout(this.step_func(function() { assert_false(gotMessage); this.done(); }), 100);
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/WindowTimers/003.html b/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/WindowTimers/003.html
new file mode 100644
index 00000000000..942f139fa52
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/WindowTimers/003.html
@@ -0,0 +1,22 @@
+<!--
+setInterval(function() { postMessage(1); }, 10);
+/*
+-->
+<!doctype html>
+<title>setInterval</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+ var worker = new Worker('#');
+ worker.onmessage = this.step_func(function(e) {
+ assert_equals(e.data, 1);
+ this.done();
+ });
+});
+</script>
+<!--
+*/
+//-->
+
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/WindowTimers/004.html b/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/WindowTimers/004.html
new file mode 100644
index 00000000000..5548eec4ab4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/WindowTimers/004.html
@@ -0,0 +1,23 @@
+<!--
+var t = setInterval(function() {
+ postMessage(1);
+}, 10);
+clearInterval(t);
+/*
+-->
+<!doctype html>
+<title>clearInterval</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+ var worker = new Worker('#');
+ var i = 0;
+ worker.onmessage = function() { i++; }
+ setTimeout(this.step_func(function() { assert_equals(i, 0); this.done(); }), 100);
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/001.html b/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/001.html
new file mode 100644
index 00000000000..00398c78077
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/001.html
@@ -0,0 +1,26 @@
+<!--
+try {
+ importScripts();
+ postMessage(true);
+} catch(ex) {
+ postMessage(String(ex));
+}
+/*
+-->
+<!doctype html>
+<title>importScripts no arguments</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+ var worker = new Worker('#');
+ worker.onmessage = this.step_func(function(e) {
+ assert_true(e.data);
+ this.done();
+ });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/002.html b/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/002.html
new file mode 100644
index 00000000000..e7d52e9797d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/002.html
@@ -0,0 +1,32 @@
+<!--
+var ran = false;
+var threw = false;
+var code = undefined;
+try {
+ importScripts('data:text/javascript,ran=true','http://foo bar');
+} catch(e) {
+ threw = true;
+ code = e.code;
+}
+postMessage([ran, threw, code]);
+/*
+-->
+<!doctype html>
+<title>importScripts resolving urls</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+ var worker = new Worker('#');
+ worker.onmessage = this.step_func(function(e) {
+ assert_false(e.data[0], 'first argument to importScripts ran');
+ assert_true(e.data[1], 'space in URL in second argument to importScripts did not throw');
+ assert_equals(e.data[2], 12, 'exception code');
+ this.done();
+ });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/003.html b/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/003.html
new file mode 100644
index 00000000000..7ff30ae2a61
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/003.html
@@ -0,0 +1,28 @@
+<!--
+var x = 'a';
+try {
+ importScripts('data:text/javascript,x+="b"',
+ 'data:text/javascript,x+="c"');
+} catch(e) {
+ x += "d"
+}
+postMessage(x);
+/*
+-->
+<!doctype html>
+<title>importScripts running scripts</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+ var worker = new Worker('#');
+ worker.onmessage = this.step_func(function(e) {
+ assert_equals(e.data, "abc");
+ this.done();
+ });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/004.html b/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/004.html
new file mode 100644
index 00000000000..2d39d3ce72e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/004.html
@@ -0,0 +1,34 @@
+<!--
+var x = '';
+var exception;
+try {
+ importScripts('data:text/javascript,x+="first script successful. "',
+ 'data:text/javascript,x+="FAIL (second script). "; for(;) break;', // doesn't compile
+ 'data:text/javascript,x+="FAIL (third script)"');
+} catch(ex) {
+ if (ex instanceof SyntaxError)
+ exception = true;
+ else
+ exception = String(ex);
+}
+postMessage([x, exception]);
+/*
+-->
+<!doctype html>
+<title>importScripts broken script</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+ var worker = new Worker('#');
+ worker.onmessage = this.step_func(function(e) {
+ assert_equals(e.data[0], "first script successful. ");
+ assert_true(e.data[1], 'expected SyntaxError');
+ this.done();
+ });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/005.html b/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/005.html
new file mode 100644
index 00000000000..f8abe14c23e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/005.html
@@ -0,0 +1,30 @@
+<!--
+var x;
+var y;
+try {
+ importScripts('data:text/javascript,x={',
+ 'data:text/javascript,}');
+} catch(e) {
+ y = true;
+}
+postMessage([x, y]);
+/*
+-->
+<!doctype html>
+<title>importScripts separate scripts</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+ var worker = new Worker('#');
+ worker.onmessage = this.step_func(function(e) {
+ assert_equals(e.data[0], undefined);
+ assert_true(e.data[1]);
+ this.done();
+ });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/006.html b/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/006.html
new file mode 100644
index 00000000000..06aea969621
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/006.html
@@ -0,0 +1,33 @@
+<!--
+var x;
+var y;
+var z;
+try {
+ importScripts('data:text/javascript,x=1',
+ 'data:text/javascript,throw 2',
+ 'data:text/javascript,z=3');
+} catch(e) {
+ y = e;
+}
+postMessage([x, y, z]);
+/*
+-->
+<!doctype html>
+<title>importScripts uncaught exception</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+ var worker = new Worker('#');
+ worker.onmessage = this.step_func(function(e) {
+ assert_equals(e.data[0], 1);
+ assert_equals(e.data[1], 2);
+ assert_equals(e.data[2], undefined);
+ this.done();
+ });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/007.html b/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/007.html
new file mode 100644
index 00000000000..128fb1b64f7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/007.html
@@ -0,0 +1,25 @@
+<!--
+importScripts('data:text/javascript,postMessage(1)');
+postMessage(2);
+/*
+-->
+<!doctype html>
+<title>postMessage in importScripts</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+ var worker = new Worker('#');
+ var i = 0;
+ worker.onmessage = this.step_func(function(e) {
+ i++;
+ assert_equals(e.data, i);
+ if (i == 2)
+ this.done();
+ });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/008.html b/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/008.html
new file mode 100644
index 00000000000..07b800ebb89
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/008.html
@@ -0,0 +1,23 @@
+<!--
+var log = postMessage;
+importScripts('data:text/javascript,function run() { log(true) }');
+run();
+/*
+-->
+<!doctype html>
+<title>variables and functions crossing importScripts boundary</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+ var worker = new Worker('#');
+ worker.onmessage = this.step_func(function(e) {
+ assert_true(e.data);
+ this.done();
+ });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/009.html b/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/009.html
new file mode 100644
index 00000000000..95d3839dc23
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/009.html
@@ -0,0 +1,29 @@
+<!--
+var log = postMessage;
+importScripts('data:text/javascript,function run() { for(var i = 0; i < 1000; ++i) { if (i == 500) log(true); } return 1; }');
+postMessage(run());
+/*
+-->
+<!doctype html>
+<title>variables and functions crossing importScripts boundary, take 2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+ var worker = new Worker('#');
+ var i = 0;
+ worker.onmessage = this.step_func(function(e) {
+ i++;
+ if (i == 1) {
+ assert_true(e.data);
+ } else {
+ assert_equals(e.data, 1);
+ this.done();
+ }
+ });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/010.html b/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/010.html
new file mode 100644
index 00000000000..9c76e7d4daa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/010.html
@@ -0,0 +1,34 @@
+<!--
+// prevent recursion
+if ('beenThere' in self) {
+ throw 'undefined stringified to the empty string';
+}
+beenThere = true;
+try {
+ importScripts(undefined);
+ postMessage(got);
+} catch(ex) {
+ postMessage(String(ex));
+}
+/*
+-->
+<!doctype html>
+<title>importScripts(undefined)</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+ var worker = new Worker('#');
+ worker.onmessage = this.step_func(function(e) {
+ assert_equals(e.data, 'undefined');
+ this.done();
+ })
+ worker.onerror = this.step_func(function(e) {
+ assert_unreached(e.message);
+ });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/011.html b/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/011.html
new file mode 100644
index 00000000000..46499318fb3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/011.html
@@ -0,0 +1,34 @@
+<!--
+// prevent recursion
+if ('beenThere' in self) {
+ throw 'null stringified to the empty string';
+}
+beenThere = true;
+try {
+ importScripts(null);
+ postMessage(got);
+} catch(ex) {
+ postMessage(String(ex));
+}
+/*
+-->
+<!doctype html>
+<title>importScripts(null)</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+ var worker = new Worker('#');
+ worker.onmessage = this.step_func(function(e) {
+ assert_equals(e.data, 'null');
+ this.done();
+ });
+ worker.onerror = this.step_func(function(e) {
+ assert_unreached(e.message);
+ });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/012.html b/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/012.html
new file mode 100644
index 00000000000..f7622bdc9df
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/012.html
@@ -0,0 +1,34 @@
+<!--
+// prevent recursion
+if ('beenThere' in self) {
+ throw '1 stringified to the empty string';
+}
+beenThere = true;
+try {
+ importScripts(1);
+ postMessage(got);
+} catch(ex) {
+ postMessage(String(ex));
+}
+/*
+-->
+<!doctype html>
+<title>importScripts(1)</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(function() {
+ var worker = new Worker('#');
+ worker.onmessage = this.step_func(function(e) {
+ assert_equals(e.data, '1');
+ this.done();
+ });
+ worker.onerror = this.step_func(function(e) {
+ assert_unreached(e.message);
+ });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/1 b/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/1
new file mode 100644
index 00000000000..18cea4ff0f4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/1
@@ -0,0 +1 @@
+var got = '1'; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/null b/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/null
new file mode 100644
index 00000000000..8e54b66c50e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/null
@@ -0,0 +1 @@
+var got = 'null'; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/undefined b/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/undefined
new file mode 100644
index 00000000000..f99ba4be744
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/undefined
@@ -0,0 +1 @@
+var got = 'undefined'; \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/navigator/002.html b/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/navigator/002.html
new file mode 100644
index 00000000000..d3aa2ec658d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/navigator/002.html
@@ -0,0 +1,21 @@
+<!--
+postMessage(navigator.appName);
+/*
+-->
+<!doctype html>
+<title>navigator.appName</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+ var worker = new Worker('#');
+ worker.onmessage = this.step_func(function(e) {
+ assert_equals(e.data, navigator.appName);
+ this.done();
+ });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/navigator/003.html b/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/navigator/003.html
new file mode 100644
index 00000000000..a2e5c948791
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/navigator/003.html
@@ -0,0 +1,21 @@
+<!--
+postMessage(navigator.appVersion);
+/*
+-->
+<!doctype html>
+<title>navigator.appVersion</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+ var worker = new Worker('#');
+ worker.onmessage = this.step_func(function(e) {
+ assert_equals(e.data, navigator.appVersion);
+ this.done();
+ });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/navigator/004.html b/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/navigator/004.html
new file mode 100644
index 00000000000..2231c4ab821
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/navigator/004.html
@@ -0,0 +1,21 @@
+<!--
+postMessage(navigator.platform);
+/*
+-->
+<!doctype html>
+<title>navigator.platform</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+ var worker = new Worker('#');
+ worker.onmessage = this.step_func(function(e) {
+ assert_equals(e.data, navigator.platform);
+ this.done();
+ });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/navigator/005.html b/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/navigator/005.html
new file mode 100644
index 00000000000..b3d99588f75
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/navigator/005.html
@@ -0,0 +1,21 @@
+<!--
+postMessage(navigator.userAgent);
+/*
+-->
+<!doctype html>
+<title>navigator.userAgent</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+ var worker = new Worker('#');
+ worker.onmessage = this.step_func(function(e) {
+ assert_equals(e.data, navigator.userAgent);
+ this.done();
+ });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/navigator/006.html b/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/navigator/006.html
new file mode 100644
index 00000000000..c027d630d4c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/navigator/006.html
@@ -0,0 +1,21 @@
+<!--
+postMessage(navigator.onLine);
+/*
+-->
+<!doctype html>
+<title>navigator.onLine</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+ var worker = new Worker('#');
+ worker.onmessage = this.step_func(function(e) {
+ assert_equals(e.data, navigator.onLine);
+ this.done();
+ });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/navigator/007.html b/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/navigator/007.html
new file mode 100644
index 00000000000..681d3e7934a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/navigator/007.html
@@ -0,0 +1,28 @@
+<!--
+var log = [];
+for (x in navigator) {
+ navigator[x] = 1; // this should silently fail and not throw per webidl
+ if (navigator[x] === 1)
+ log.push(x);
+}
+postMessage(log.join(', '));
+/*
+-->
+<!doctype html>
+<title>readonlyness of members of Navigator</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+ var worker = new Worker('#');
+ worker.onmessage = this.step_func(function(e) {
+ assert_equals(e.data, '');
+ this.done();
+ });
+});
+</script>
+<!--
+*/
+//-->
+
diff --git a/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/navigator/language.html b/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/navigator/language.html
new file mode 100644
index 00000000000..f1aa446cb9a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/interfaces/WorkerUtils/navigator/language.html
@@ -0,0 +1,21 @@
+<!--
+postMessage(navigator.language);
+/*
+-->
+<!doctype html>
+<title>navigator.language</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+ var worker = new Worker('#');
+ worker.onmessage = this.step_func(function(e) {
+ assert_equals(e.data, navigator.language);
+ this.done();
+ });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/nested_worker.worker.js b/tests/wpt/web-platform-tests/workers/nested_worker.worker.js
new file mode 100644
index 00000000000..8848fa216bc
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/nested_worker.worker.js
@@ -0,0 +1,11 @@
+importScripts("/resources/testharness.js");
+
+async_test(function() {
+ var worker1 = new Worker("support/WorkerBasic.js");
+ worker1.postMessage("ping");
+ worker1.onmessage = this.step_func_done(function(evt) {
+ assert_equals(evt.data, "Pass");
+ worker1.terminate();
+ done();
+ });
+}, "Nested worker");
diff --git a/tests/wpt/web-platform-tests/workers/non-automated/application-cache-dedicated.html b/tests/wpt/web-platform-tests/workers/non-automated/application-cache-dedicated.html
new file mode 100644
index 00000000000..704ecbcd7ff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/non-automated/application-cache-dedicated.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<html manifest=cache.manifest>
+<title>cache manifest</title>
+<p>Script did not run.</p>
+<p>To run this test again, delete private data and then load this test again.</p>
+<script>
+var p = document.querySelector('p');
+if (sessionStorage.testHasBeenLoadedBefore) {
+ var worker = new Worker('application-cache-dedicated.js');
+ worker.onmessage = function(e) {
+ p.textContent = 'PASS';
+ }
+ setTimeout(function(){
+ if (p.textContent != 'PASS')
+ p.textContent = 'FAIL (got no message from worker)';
+ }, 250);
+} else {
+ sessionStorage.testHasBeenLoadedBefore = true;
+ p.textContent = 'Enable offline mode and then reload this test. It should say PASS.';
+}
+</script>
diff --git a/tests/wpt/web-platform-tests/workers/non-automated/application-cache-dedicated.js b/tests/wpt/web-platform-tests/workers/non-automated/application-cache-dedicated.js
new file mode 100644
index 00000000000..2318c2e267d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/non-automated/application-cache-dedicated.js
@@ -0,0 +1 @@
+postMessage(1); \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/workers/non-automated/cache.manifest b/tests/wpt/web-platform-tests/workers/non-automated/cache.manifest
new file mode 100644
index 00000000000..8d80e03b20c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/non-automated/cache.manifest
@@ -0,0 +1,3 @@
+CACHE MANIFEST
+application-cache-dedicated.html
+application-cache-dedicated.js
diff --git a/tests/wpt/web-platform-tests/workers/non-automated/infinite-nested.html b/tests/wpt/web-platform-tests/workers/non-automated/infinite-nested.html
new file mode 100644
index 00000000000..3ff3edb3534
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/non-automated/infinite-nested.html
@@ -0,0 +1,12 @@
+<!doctype html>
+<title>infinite nested workers</title>
+<p>There number below should be increasing (ideally never-ending).</p>
+<div>0</div>
+<script>
+var worker = new Worker('infinite-nested.js');
+var div = document.getElementsByTagName('div')[0];
+var i = 0;
+worker.onmessage = function(e) {
+ div.textContent = i++;
+}
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/workers/non-automated/infinite-nested.js b/tests/wpt/web-platform-tests/workers/non-automated/infinite-nested.js
new file mode 100644
index 00000000000..137dd0a2e28
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/non-automated/infinite-nested.js
@@ -0,0 +1,5 @@
+postMessage(1);
+var w = new Worker('infinite-nested.js');
+w.onmessage = function(e) {
+ postMessage(e.data);
+} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/workers/non-automated/infinite-sibling-and-nested.html b/tests/wpt/web-platform-tests/workers/non-automated/infinite-sibling-and-nested.html
new file mode 100644
index 00000000000..463546cc969
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/non-automated/infinite-sibling-and-nested.html
@@ -0,0 +1,12 @@
+<!doctype html>
+<title>infinite sibling and nested workers</title>
+<p>The number below should be increasing (ideally never-ending).</p>
+<div>0</div>
+<script>
+var worker = new Worker('infinite-sibling-and-nested.js');
+var div = document.getElementsByTagName('div')[0];
+var i = 0;
+worker.onmessage = function(e) {
+ div.textContent = i + e.data;
+}
+</script>
diff --git a/tests/wpt/web-platform-tests/workers/non-automated/infinite-sibling-and-nested.js b/tests/wpt/web-platform-tests/workers/non-automated/infinite-sibling-and-nested.js
new file mode 100644
index 00000000000..cf7b794a414
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/non-automated/infinite-sibling-and-nested.js
@@ -0,0 +1,8 @@
+function createWorker() {
+ var worker = new Worker('infinite-nested.js?' + Math.random());
+ worker.onmessage = function(e) {
+ postMessage(e.data);
+ createWorker();
+ }
+}
+createWorker(); \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/workers/non-automated/infinite-sibling.html b/tests/wpt/web-platform-tests/workers/non-automated/infinite-sibling.html
new file mode 100644
index 00000000000..edcb8d70722
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/non-automated/infinite-sibling.html
@@ -0,0 +1,12 @@
+<!doctype html>
+<title>infinite sibling workers</title>
+<p>The number below should be increasing (ideally never-ending).</p>
+<div>0</div>
+<script>
+var worker = new Worker('infinite-sibling.js');
+var div = document.getElementsByTagName('div')[0];
+var i = 0;
+worker.onmessage = function(e) {
+ div.textContent = i + e.data;
+}
+</script>
diff --git a/tests/wpt/web-platform-tests/workers/non-automated/infinite-sibling.js b/tests/wpt/web-platform-tests/workers/non-automated/infinite-sibling.js
new file mode 100644
index 00000000000..6424f700932
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/non-automated/infinite-sibling.js
@@ -0,0 +1,8 @@
+function createWorker() {
+ var worker = new Worker('post-a-1.js?' + Math.random());
+ worker.onmessage = function(e) {
+ postMessage(e.data);
+ createWorker();
+ }
+}
+createWorker(); \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/workers/non-automated/navigator-onLine.html b/tests/wpt/web-platform-tests/workers/non-automated/navigator-onLine.html
new file mode 100644
index 00000000000..d71aeaf0a88
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/non-automated/navigator-onLine.html
@@ -0,0 +1,46 @@
+<!--
+if ('onmessage' in self) { // dedicated worker
+ onmessage = function(e) {
+ postMessage(navigator.onLine);
+ }
+} else { // shared worker
+ onconnect = function(e) {
+ e.ports[0].onmessage = function(e) {
+ this.postMessage(navigator.onLine);
+ }
+ }
+}
+/*
+-->
+<!doctype html>
+<title>navigator.onLine in dedicated worker</title>
+<pre>Log:
+</pre>
+<script>
+var pre = document.querySelector('pre');
+var worker, shared;
+try { worker = new Worker('#'); } catch(e) { pre.textContent += '\nnew Worker threw: ' + e.message; }
+try { shared = new SharedWorker('#', ''); } catch(e) { pre.textContent += '\nnew SharedWorker threw: ' + e.message; }
+if (worker) {
+ worker.onmessage = function(e) {
+ pre.textContent += '\ndedicated worker: ' + e.data;
+ }
+}
+if (shared) {
+ shared.port.onmessage = function(e) {
+ pre.textContent += '\nshared worker: ' + e.data;
+ }
+}
+function update() {
+ pre.textContent += '\n\n' + new Date() + '\n<script>: ' + navigator.onLine;
+ if (worker) worker.postMessage(1);
+ if (shared) shared.port.postMessage(1);
+}
+update();
+ononline = onoffline = update;
+</script>
+<p>As you go online and offline, the log should be filled with the correct status of navigator.onLine.</p>
+<p><button onclick="update()">Check navigator.onLine status</button></p>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/non-automated/post-a-1.js b/tests/wpt/web-platform-tests/workers/non-automated/post-a-1.js
new file mode 100644
index 00000000000..2318c2e267d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/non-automated/post-a-1.js
@@ -0,0 +1 @@
+postMessage(1); \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/workers/postMessage_DataCloneErr.htm b/tests/wpt/web-platform-tests/workers/postMessage_DataCloneErr.htm
new file mode 100644
index 00000000000..24093ce4e3e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/postMessage_DataCloneErr.htm
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<title> postMessage() with WorkerNavigator </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var worker = new Worker("./support/WorkerDataCloneErr.js");
+ worker.onmessage = t.step_func_done(function(e) {
+ assert_equals(e.data, "Pass");
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/workers/postMessage_clone_port.htm b/tests/wpt/web-platform-tests/workers/postMessage_clone_port.htm
new file mode 100644
index 00000000000..b1d7b84e3c0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/postMessage_clone_port.htm
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<title> postMessage(): clone a port </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var channelA = new MessageChannel();
+ var channelB = new MessageChannel();
+ var originalPort = channelB.port2;
+ channelA.port2.onmessage = t.step_func(function(e) {
+ assert_equals(e.data, "ports");
+ var clonedPort = e.ports[0];
+ assert_not_equals(clonedPort, originalPort, "new cloned port object should not equal to the original port!");
+ clonedPort.onmessage = t.step_func_done(function(e) {
+ assert_equals(e.data, "ping", "Data sent through remote port is received by the new cloned port");
+ });
+ });
+ channelA.port1.postMessage("ports", [channelB.port2]);
+ channelB.port1.postMessage("ping");
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/workers/postMessage_clone_port_error.htm b/tests/wpt/web-platform-tests/workers/postMessage_clone_port_error.htm
new file mode 100644
index 00000000000..30012962d86
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/postMessage_clone_port_error.htm
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<title> postMessage(): cloning source port </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+test(function() {
+ var channel = new MessageChannel();
+ channel.port1.start();
+ assert_throws("DataCloneError", function() {
+ channel.port1.postMessage("ports", [channel.port1]);
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/workers/postMessage_event_properties.htm b/tests/wpt/web-platform-tests/workers/postMessage_event_properties.htm
new file mode 100644
index 00000000000..8122413de40
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/postMessage_event_properties.htm
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<title> postMessage(): MessageEvent properties </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var channel = new MessageChannel();
+ var targetPort = channel.port2;
+ targetPort.start();
+ targetPort.addEventListener("message", t.step_func_done(function (evt) {
+ assert_class_string(evt, "MessageEvent");
+ assert_equals(evt.type, "message");
+ assert_false(evt.bubbles, "bubbles should be false");
+ assert_false(evt.cancelable, "cancelable should be false");
+ assert_equals(evt.data, "ping", "data");
+ assert_equals(evt.origin, "", "origin");
+ assert_equals(evt.lastEventId, "", "lastEventId");
+ assert_equals(evt.source, null, "source");
+ assert_array_equals(evt.ports, [], "ports");
+ }), true);
+ channel.port1.postMessage("ping");
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/workers/postMessage_ports_readonly_array.htm b/tests/wpt/web-platform-tests/workers/postMessage_ports_readonly_array.htm
new file mode 100644
index 00000000000..5e2b9054afa
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/postMessage_ports_readonly_array.htm
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<title> postMessage(): read-only ports array </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var channel = new MessageChannel();
+ var targetPort = channel.port2;
+ targetPort.start();
+ targetPort.addEventListener("message", t.step_func_done(function(e) {
+ var channel3 = new MessageChannel();
+ e.ports.push(channel3.port1);
+ e.ports.push(channel3.port1);
+ assert_equals(e.ports.length, 1, "ports is a read only array with length == 1.");
+ }), true);
+ var channel2 = new MessageChannel();
+ channel.port1.postMessage("ports", [channel2.port1]);
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/workers/postMessage_target_source.htm b/tests/wpt/web-platform-tests/workers/postMessage_target_source.htm
new file mode 100644
index 00000000000..7d684916dde
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/postMessage_target_source.htm
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<title> postMessage(): target port and source port </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var channel = new MessageChannel();
+ var source = channel.port1;
+ var target = channel.port2;
+ target.start();
+ target.addEventListener("message", t.step_func_done(function(e) {
+ assert_equals(e.target, target);
+ assert_not_equals(e.target, source);
+ }), true);
+ source.postMessage("ping");
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/workers/semantics/encodings/001.html b/tests/wpt/web-platform-tests/workers/semantics/encodings/001.html
new file mode 100644
index 00000000000..0ebec0b0338
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/semantics/encodings/001.html
@@ -0,0 +1,21 @@
+<!--
+postMessage('å');
+/*
+-->
+<!doctype html>
+<title>encoding, dedicated worker</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+ var worker = new Worker('#');
+ worker.onmessage = this.step_func(function(e) {
+ assert_equals(e.data, '\u00e5');
+ this.done();
+ });
+});
+</script>
+<!--
+*/
+//--> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/workers/semantics/encodings/001.html.headers b/tests/wpt/web-platform-tests/workers/semantics/encodings/001.html.headers
new file mode 100644
index 00000000000..2340a89c93c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/semantics/encodings/001.html.headers
@@ -0,0 +1 @@
+Content-Type: text/html; charset=windows-1252
diff --git a/tests/wpt/web-platform-tests/workers/semantics/encodings/002.html b/tests/wpt/web-platform-tests/workers/semantics/encodings/002.html
new file mode 100644
index 00000000000..fdcc4f0a21c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/semantics/encodings/002.html
@@ -0,0 +1,23 @@
+<!--
+onconnect = function(e) {
+ e.ports[0].postMessage('å');
+}
+/*
+-->
+<!doctype html>
+<title>encoding, shared worker</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+ var worker = new SharedWorker('#', '');
+ worker.port.onmessage = this.step_func(function(e) {
+ assert_equals(e.data, '\u00e5');
+ this.done();
+ });
+});
+</script>
+<!--
+*/
+//--> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/workers/semantics/encodings/002.html.headers b/tests/wpt/web-platform-tests/workers/semantics/encodings/002.html.headers
new file mode 100644
index 00000000000..2340a89c93c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/semantics/encodings/002.html.headers
@@ -0,0 +1 @@
+Content-Type: text/html; charset=windows-1252
diff --git a/tests/wpt/web-platform-tests/workers/semantics/encodings/003-1.py b/tests/wpt/web-platform-tests/workers/semantics/encodings/003-1.py
new file mode 100644
index 00000000000..1e899aac271
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/semantics/encodings/003-1.py
@@ -0,0 +1,4 @@
+ # -*- coding: utf-8 -*-
+
+def main(request, response):
+ return "PASS" if request.GET.first('x') == 'å' else "FAIL"
diff --git a/tests/wpt/web-platform-tests/workers/semantics/encodings/003.html b/tests/wpt/web-platform-tests/workers/semantics/encodings/003.html
new file mode 100644
index 00000000000..a0f964c3c4d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/semantics/encodings/003.html
@@ -0,0 +1,26 @@
+<!--
+var xhr = new XMLHttpRequest();
+xhr.open('GET', '003-1.py?x=å', false);
+xhr.send();
+var passed = xhr.responseText == 'PASS';
+postMessage(passed);
+
+/*
+-->
+<!doctype html>
+<title>URL encoding, dedicated worker</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+ var worker = new Worker('#');
+ worker.onmessage = this.step_func(function(e) {
+ assert_true(e.data);
+ this.done();
+ });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/semantics/encodings/004.html b/tests/wpt/web-platform-tests/workers/semantics/encodings/004.html
new file mode 100644
index 00000000000..bb144263310
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/semantics/encodings/004.html
@@ -0,0 +1,27 @@
+<!--
+onconnect = function(e) {
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', '003-1.py?x=å', false);
+ xhr.send();
+ var passed = xhr.responseText == 'PASS';
+ e.ports[0].postMessage(passed);
+}
+/*
+-->
+<!doctype html>
+<title>URL encoding, shared worker</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+ var worker = new SharedWorker('#');
+ worker.port.onmessage = this.step_func(function(e) {
+ assert_true(e.data);
+ this.done();
+ });
+});
+</script>
+<!--
+*/
+//--> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/workers/semantics/interface-objects/001.worker.js b/tests/wpt/web-platform-tests/workers/semantics/interface-objects/001.worker.js
new file mode 100644
index 00000000000..75cb3809f29
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/semantics/interface-objects/001.worker.js
@@ -0,0 +1,48 @@
+importScripts("/resources/testharness.js");
+var expected = [
+ "WorkerGlobalScope",
+ "EventTarget",
+ "DedicatedWorkerGlobalScope",
+ "ErrorEvent",
+ "Event",
+ "Worker",
+ "DOMException",
+ "SharedWorker",
+ "MessagePort",
+ "MessageEvent",
+ "WorkerNavigator",
+ "MessageChannel",
+ "WorkerLocation",
+ "ImageData",
+ "File",
+ "Blob",
+ "FileList",
+ "XMLHttpRequest",
+ "ProgressEvent",
+ "FormData",
+ "ArrayBuffer",
+ "Int8Array",
+ "Uint8Array",
+ "Uint8ClampedArray",
+ "Int16Array",
+ "Uint16Array",
+ "Int32Array",
+ "Uint32Array",
+ "Float32Array",
+ "Float64Array",
+ "DataView",
+ "CanvasProxy",
+ "ImageBitmap",
+ "CanvasRenderingContext2D",
+ "DrawingStyle",
+ "CanvasGradient",
+ "CanvasPattern",
+ "Path",
+ "TextMetrics"
+];
+for (var i = 0; i < expected.length; ++i) {
+ test(function () {
+ assert_own_property(self, expected[i]);
+ }, "The " + expected[i] + " interface object should be exposed.");
+}
+done();
diff --git a/tests/wpt/web-platform-tests/workers/semantics/interface-objects/002.worker.js b/tests/wpt/web-platform-tests/workers/semantics/interface-objects/002.worker.js
new file mode 100644
index 00000000000..3fa58a25ca9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/semantics/interface-objects/002.worker.js
@@ -0,0 +1,18 @@
+importScripts("/resources/testharness.js");
+var unexpected = [
+ "AbstractView",
+ "AbstractWorker",
+ "ApplicationCache",
+ "Location",
+ "Navigator",
+ "DOMImplementation",
+ "Audio",
+ "HTMLCanvasElement",
+ "MouseEvent",
+];
+for (var i = 0; i < unexpected.length; ++i) {
+ test(function () {
+ assert_false(unexpected[i] in self);
+ }, "The " + unexpected[i] + " interface object should not be exposed.");
+}
+done();
diff --git a/tests/wpt/web-platform-tests/workers/semantics/interface-objects/003.html b/tests/wpt/web-platform-tests/workers/semantics/interface-objects/003.html
new file mode 100644
index 00000000000..23ae59b4576
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/semantics/interface-objects/003.html
@@ -0,0 +1,30 @@
+<!--
+onconnect = function(e) {
+ var expected = 'ApplicationCache WorkerGlobalScope EventTarget ErrorEvent Event Worker DOMException SharedWorker MessagePort MessageEvent WorkerNavigator MessageChannel WorkerLocation Database ImageData File Blob FileList XMLHttpRequest ProgressEvent FormData ArrayBuffer Int8Array Uint8Array Uint8ClampedArray Int16Array Uint16Array Int32Array Uint32Array Float32Array Float64Array DataView CanvasProxy ImageBitmap CanvasRenderingContext2d DrawingStyle CanvasGradient CanvasPattern Path TextMetrics'.split(' ');
+ var log = [];
+ for (var i = 0; i < expected.length; ++i) {
+ if (!(expected[i] in self))
+ log.push(expected[i]);
+ }
+ e.ports[0].postMessage(log.join(', '));
+}
+/*
+-->
+<!doctype html>
+<title>available interface objects in shared worker</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+ var worker = new SharedWorker('#');
+ worker.port.onmessage = this.step_func(function(e) {
+ assert_equals(e.data, '', 'these interface objects were missing');
+ this.done();
+ });
+});
+</script>
+<!--
+*/
+//-->
+
diff --git a/tests/wpt/web-platform-tests/workers/semantics/interface-objects/004.html b/tests/wpt/web-platform-tests/workers/semantics/interface-objects/004.html
new file mode 100644
index 00000000000..4ad468a7f40
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/semantics/interface-objects/004.html
@@ -0,0 +1,30 @@
+<!--
+onconnect = function(e) {
+ var unexpected = 'AbstractView AbstractWorker Location Navigator DOMImplementation Audio HTMLCanvasElement MouseEvent'.split(' ');
+ var log = [];
+ for (var i = 0; i < unexpected.length; ++i) {
+ if (unexpected[i] in self)
+ log.push(unexpected[i]);
+ }
+ e.ports[0].postMessage(log.join(', '));
+}
+/*
+-->
+<!doctype html>
+<title>unavailable interface objects in shared worker</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+ var worker = new SharedWorker('#');
+ worker.port.onmessage = this.step_func(function(e) {
+ assert_equals(e.data, '', 'these interface objects were not expected');
+ this.done();
+ });
+});
+</script>
+<!--
+*/
+//-->
+
diff --git a/tests/wpt/web-platform-tests/workers/semantics/multiple-workers/001.html b/tests/wpt/web-platform-tests/workers/semantics/multiple-workers/001.html
new file mode 100644
index 00000000000..82ddcc3c177
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/semantics/multiple-workers/001.html
@@ -0,0 +1,41 @@
+<!--
+if ('onmessage' in self) { // dedicated worker
+ onmessage = function(e) {
+ postMessage(e.data);
+ }
+} else { // shared worker
+ onconnect = function(e) {
+ e.ports[0].onmessage = function(e) {
+ this.postMessage(e.data);
+ }
+ }
+}
+/*
+-->
+<!doctype html>
+<title>dedicated and shared worker in same page</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+ var worker = new Worker('#');
+ worker.onmessage = this.step_func(function(e) {
+ assert_equals(e.data, 'dedicated');
+ this.done();
+ });
+ worker.postMessage('dedicated');
+}, 'dedicated');
+async_test(function() {
+ var shared = new SharedWorker('#', '');
+ shared.port.onmessage = this.step_func(function(e) {
+ assert_equals(e.data, 'shared');
+ this.done();
+ });
+ shared.port.postMessage('shared');
+}, 'shared');
+</script>
+<!--
+*/
+//-->
+
diff --git a/tests/wpt/web-platform-tests/workers/semantics/multiple-workers/002.html b/tests/wpt/web-platform-tests/workers/semantics/multiple-workers/002.html
new file mode 100644
index 00000000000..9ab1f54f4c5
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/semantics/multiple-workers/002.html
@@ -0,0 +1,28 @@
+<!--
+postMessage(1);
+/*
+-->
+<!doctype html>
+<title>creating 3 sibling dedicated workers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function(t) {
+ var w1 = new Worker('#');
+ var w2 = new Worker('#');
+ var w3 = new Worker('#');
+ var got = [false, false, false];
+ var check_done = t.step_func(function() {
+ if (got.every(function(x) {return x})) {
+ t.done();
+ }
+ });
+ w1.onmessage = t.step_func(function(e) {got[0] = true; check_done()});
+ w2.onmessage = t.step_func(function(e) {got[1] = true; check_done()});
+ w3.onmessage = t.step_func(function(e) {got[2] = true; check_done()});
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/semantics/multiple-workers/003.html b/tests/wpt/web-platform-tests/workers/semantics/multiple-workers/003.html
new file mode 100644
index 00000000000..85c688bc082
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/semantics/multiple-workers/003.html
@@ -0,0 +1,34 @@
+<!--
+if (location.hash == '#1') {
+ var w2 = new Worker('#2');
+ w2.onmessage = function(e) {
+ postMessage('1'+e.data);
+ }
+} else if (location.hash == '#2') {
+ var w3 = new Worker('#3');
+ w3.onmessage = function(e) {
+ postMessage('2'+e.data);
+ }
+} else {
+ postMessage('3');
+}
+
+/*
+-->
+<!doctype html>
+<title>creating 3 nested dedicated workers</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+ var w1 = new Worker('#1');
+ w1.onmessage = this.step_func(function(e) {
+ assert_equals(e.data, '123');
+ this.done();
+ });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/semantics/multiple-workers/004-1.html b/tests/wpt/web-platform-tests/workers/semantics/multiple-workers/004-1.html
new file mode 100644
index 00000000000..eac038c5bee
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/semantics/multiple-workers/004-1.html
@@ -0,0 +1,7 @@
+<!doctype html>
+<title></title>
+<script>
+window.onload = function() {
+ var w=new SharedWorker('004-2.js', 'x');
+};
+</script>
diff --git a/tests/wpt/web-platform-tests/workers/semantics/multiple-workers/004-2.js b/tests/wpt/web-platform-tests/workers/semantics/multiple-workers/004-2.js
new file mode 100644
index 00000000000..e59cd6927e3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/semantics/multiple-workers/004-2.js
@@ -0,0 +1,6 @@
+var port;
+onconnect = function(e) {
+ if (!port)
+ port = e.ports[0];
+ port.postMessage(1);
+} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/workers/semantics/multiple-workers/004.html b/tests/wpt/web-platform-tests/workers/semantics/multiple-workers/004.html
new file mode 100644
index 00000000000..c4733700865
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/semantics/multiple-workers/004.html
@@ -0,0 +1,34 @@
+<!doctype html>
+<title>shared worker with multiple documents</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var i = 0;
+var load_count = 0;
+
+var w1 = new SharedWorker('004-2.js', 'x');
+w1.port.onmessage = function(e) {
+ i++;
+ check_result();
+};
+
+
+function iframe_loaded() {
+ load_count++;
+ check_result();
+}
+
+function check_result() {
+ //timeout to allow for extra, unexpected, messages to arrive
+ if (i == 3 && load_count == 2) {
+ setTimeout(function() {
+ assert_equals(load_count, 2);
+ assert_equals(i, 3);
+ done();
+ }, 500);
+ }
+}
+</script>
+<iframe src=004-1.html onload="iframe_loaded()"></iframe>
+<iframe src=004-1.html onload="iframe_loaded()"></iframe>
diff --git a/tests/wpt/web-platform-tests/workers/semantics/multiple-workers/005.html b/tests/wpt/web-platform-tests/workers/semantics/multiple-workers/005.html
new file mode 100644
index 00000000000..289c25ec6cb
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/semantics/multiple-workers/005.html
@@ -0,0 +1,37 @@
+<!--
+if (location.hash == '#1') {
+ var w2 = new SharedWorker('#2');
+ w2.port.onmessage = function(e) {
+ postMessage('1'+e.data);
+ }
+} else if (location.hash == '#2') {
+ onconnect = function(e) {
+ var port = e.ports[0];
+ var w3 = new Worker('#3');
+ w3.onmessage = function(e) {
+ port.postMessage('2'+e.data);
+ }
+ }
+} else {
+ postMessage('3');
+}
+
+/*
+-->
+<!doctype html>
+<title>dedicated worker in shared worker in dedicated worker</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+ var w1 = new Worker('#1');
+ w1.onmessage = this.step_func(function(e) {
+ assert_equals(e.data, '123');
+ this.done();
+ });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/semantics/multiple-workers/006-1.js b/tests/wpt/web-platform-tests/workers/semantics/multiple-workers/006-1.js
new file mode 100644
index 00000000000..6c1ed932321
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/semantics/multiple-workers/006-1.js
@@ -0,0 +1,3 @@
+ onconnect = function(e) {
+ e.ports[0].postMessage('3');
+ } \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/workers/semantics/multiple-workers/006.html b/tests/wpt/web-platform-tests/workers/semantics/multiple-workers/006.html
new file mode 100644
index 00000000000..ef21242563b
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/semantics/multiple-workers/006.html
@@ -0,0 +1,35 @@
+<!--
+if (location.hash == '#1') {
+ onconnect = function(e) {
+ var port = e.ports[0];
+ var w2 = new Worker('#2');
+ w2.onmessage = function(e) {
+ port.postMessage('1'+e.data);
+ }
+ }
+} else if (location.hash == '#2') {
+ var w3 = new SharedWorker('006-1.js');
+ w3.port.onmessage = function(e) {
+ postMessage('2'+e.data);
+ }
+}
+
+/*
+-->
+<!doctype html>
+<title>shared worker in dedicated worker in shared worker</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+ var w1 = new SharedWorker('#1');
+ w1.port.onmessage = this.step_func(function(e) {
+ assert_equals(e.data, '123');
+ this.done();
+ });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/semantics/multiple-workers/007.html b/tests/wpt/web-platform-tests/workers/semantics/multiple-workers/007.html
new file mode 100644
index 00000000000..e99345073ba
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/semantics/multiple-workers/007.html
@@ -0,0 +1,39 @@
+<!--
+if (location.hash == '#1') {
+ onconnect = function(e) {
+ var port = e.ports[0];
+ var w2 = new Worker('#2');
+ w2.onmessage = function(e) {
+ port.postMessage('1'+e.data);
+ }
+ }
+} else if (location.hash == '#2') {
+ var w3 = new SharedWorker('#3');
+ w3.port.onmessage = function(e) {
+ postMessage('2'+e.data);
+ }
+} else {
+ onconnect = function(e) {
+ e.ports[0].postMessage('3');
+ }
+}
+
+/*
+-->
+<!doctype html>
+<title>shared worker in dedicated worker in shared worker</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+ var w1 = new SharedWorker('#1');
+ w1.port.onmessage = this.step_func(function(e) {
+ assert_equals(e.data, '123');
+ this.done();
+ });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/semantics/multiple-workers/008-1.html b/tests/wpt/web-platform-tests/workers/semantics/multiple-workers/008-1.html
new file mode 100644
index 00000000000..82a8a383507
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/semantics/multiple-workers/008-1.html
@@ -0,0 +1,8 @@
+<!doctype html>
+<title>008-1</title>
+<script>
+var w1 = new SharedWorker('008.html#');
+w1.port.onmessage = function(e) {
+ e.ports[0].postMessage(2);
+}
+</script> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/workers/semantics/multiple-workers/008.html b/tests/wpt/web-platform-tests/workers/semantics/multiple-workers/008.html
new file mode 100644
index 00000000000..fbb41e0d0b3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/semantics/multiple-workers/008.html
@@ -0,0 +1,31 @@
+<!--
+var channel = new MessageChannel();
+var i = 0;
+onconnect = function(e) {
+ i++;
+ e.ports[0].postMessage(1, [channel['port' + i]]);
+}
+
+/*
+-->
+<!doctype html>
+<title>messagechannel in shared worker</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<iframe src=008-1.html></iframe>
+<script>
+var t = async_test();
+onload = t.step_func(function() {
+ var w1 = new SharedWorker('#');
+ w1.port.onmessage = this.step_func(function(e) {
+ e.ports[0].onmessage = this.step_func(function(e) {
+ assert_equals(e.data, 2);
+ this.done();
+ });
+ });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/semantics/navigation/001-1.html b/tests/wpt/web-platform-tests/workers/semantics/navigation/001-1.html
new file mode 100644
index 00000000000..9d7ecee1767
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/semantics/navigation/001-1.html
@@ -0,0 +1,23 @@
+<!--
+setInterval(function() { postMessage(new Date()) }, 10)
+/*
+-->
+<!doctype html>
+<title>001-1</title>
+<script>
+onload = function() {
+ var worker = new Worker('#');
+ worker.onmessage = function(e) {
+ var started = !!parent.date;
+ parent.date = e.data;
+ if (!started) {
+ parent.start_test()
+ }
+ }
+}
+</script>
+<a href='data:text/html,<title>foo</title><script>onload=function(){parent.after_load()}</script>'>link</a>
+<!--
+*/
+//-->
+
diff --git a/tests/wpt/web-platform-tests/workers/semantics/navigation/001.html b/tests/wpt/web-platform-tests/workers/semantics/navigation/001.html
new file mode 100644
index 00000000000..1a1378b442e
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/semantics/navigation/001.html
@@ -0,0 +1,37 @@
+<!--
+
+/*
+-->
+<!doctype html>
+<title>navigating</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var date;
+var newDate;
+</script>
+<iframe></iframe>
+<script>
+var t = async_test();
+var iframe = document.querySelector('iframe');
+onload = t.step_func(function() {
+ iframe.src = "001-1.html?" + Math.random();
+});
+var start_test = t.step_func(function() {
+ window[0].document.links[0].click();
+});
+var after_load = t.step_func(function() {
+ history.back();
+ newDate = new Date();
+ setTimeout(this.step_func(function() {
+ assert_greater_than(Number(date), Number(newDate));
+ assert_equals(window[0].document.title, '001-1');
+ this.done();
+ }), 500);
+});
+</script>
+<!--
+*/
+//-->
+
diff --git a/tests/wpt/web-platform-tests/workers/semantics/navigation/002.html b/tests/wpt/web-platform-tests/workers/semantics/navigation/002.html
new file mode 100644
index 00000000000..c0d5eb5c093
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/semantics/navigation/002.html
@@ -0,0 +1,36 @@
+<!--
+
+/*
+-->
+<!doctype html>
+<title>navigating 2</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var date;
+var newDate;
+</script>
+<iframe></iframe>
+<script>
+var t = async_test();
+var iframe = document.querySelector('iframe');
+onload = t.step_func(function() {
+ iframe.src = "001-1.html?" + Math.random();
+});
+var start_test = t.step_func(function() {
+ window[0].document.links[0].click();
+});
+var after_load = t.step_func(function() {
+ newDate = new Date();
+ setTimeout(this.step_func(function() {
+ assert_less_than(Number(date), Number(newDate));
+ assert_equals(window[0].document.title, 'foo');
+ this.done();
+ }), 500);
+});
+</script>
+<!--
+*/
+//-->
+
diff --git a/tests/wpt/web-platform-tests/workers/semantics/reporting-errors/001.html b/tests/wpt/web-platform-tests/workers/semantics/reporting-errors/001.html
new file mode 100644
index 00000000000..adba81f6353
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/semantics/reporting-errors/001.html
@@ -0,0 +1,53 @@
+<!--
+var port;
+var timeout;
+onerror = function(a,b,c,d,e) {
+ // will return undefined, thus the error is "not handled"
+ // so error should be reported to the user, but this test doesn't check
+ // that.
+ // just make sure that this method is invoked with five arguments
+ clearTimeout(timeout);
+ var log = '';
+ if (arguments.length != 5)
+ log += 'got ' + arguments.length + ' arguments, expected 5. ';
+ if (typeof a != 'string')
+ log += 'first argument wasn\'t a string. ';
+ if (b != location.href)
+ log += 'second argument was ' + b + ', expected ' + location.href + '. ';
+ if (typeof c != 'number')
+ log += 'third argument wasn\'t a number. ';
+ if (typeof d != 'number')
+ log += 'fourth argument wasn\'t a number. ';
+ if (e != 42)
+ log += 'fifth argument wasn\'t the thrown exception. ';
+ port.postMessage(log);
+}
+onconnect = function (e) {
+ port = e.ports[0];
+ timeout = setTimeout(function() { port.postMessage('self.onerror was not invoked'); }, 250);
+ throw 42; // will "report the error"
+}
+
+
+/*
+-->
+<!doctype html>
+<title>shared worker, not handled</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+setup({allow_uncaught_exception:true});
+async_test(function() {
+ window.onerror = this.step_func(function(a) {
+ assert_unreached('window.onerror invoked: ' + a);
+ });
+ var worker = new SharedWorker('#', '');
+ worker.port.onmessage = this.step_func_done(function(e) {
+ assert_equals(e.data, '');
+ });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/semantics/reporting-errors/002.html b/tests/wpt/web-platform-tests/workers/semantics/reporting-errors/002.html
new file mode 100644
index 00000000000..c2cd377b435
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/semantics/reporting-errors/002.html
@@ -0,0 +1,59 @@
+<!--
+var port;
+var timeout;
+addEventListener('error', function(e) {
+ // event is not canceled, thus the error is "not handled"
+ // so error should be reported to the user, but this test doesn't check
+ // that.
+ // just make sure that this event has the right properties
+ clearTimeout(timeout);
+ var log = '';
+ if (!self.ErrorEvent || Object.getPrototypeOf(e) != ErrorEvent.prototype)
+ log += 'event should be an ErrorEvent. ';
+ if (e.bubbles)
+ log += 'event should not bubble. ';
+ if (!e.cancelable)
+ log += 'event should be cancelable. ';
+ if (!e.isTrusted)
+ log += 'event should be trusted. ';
+ if (typeof e.message != 'string')
+ log += 'message wasn\'t a string. ';
+ if (e.filename != location.href)
+ log += 'filename was ' + e.filename + ', expected ' + location.href + '. ';
+ if (typeof e.lineno != 'number')
+ log += 'lineno wasn\'t a number. ';
+ if (typeof e.colno != 'number')
+ log += 'colno argument wasn\'t a number. ';
+ if (e.error != 42)
+ log += 'fifth argument wasn\'t the thrown exception. ';
+ port.postMessage(log);
+}, false);
+onconnect = function (e) {
+ port = e.ports[0];
+ timeout = setTimeout(function() { port.postMessage('No error event fired'); }, 250);
+ throw 42; // will "report the error"
+}
+
+
+/*
+-->
+<!doctype html>
+<title>shared worker, addEventListener</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+setup({allow_uncaught_exception:true});
+async_test(function() {
+ window.onerror = this.step_func(function(a) {
+ assert_unreached('window.onerror invoked: ' + a);
+ });
+ var worker = new SharedWorker('#', '');
+ worker.port.onmessage = this.step_func_done(function(e) {
+ assert_equals(e.data, '');
+ });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/semantics/reporting-errors/003.html b/tests/wpt/web-platform-tests/workers/semantics/reporting-errors/003.html
new file mode 100644
index 00000000000..1b01c7cafc0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/semantics/reporting-errors/003.html
@@ -0,0 +1,39 @@
+<!--
+onconnect = function (e) {
+ setTimeout(function() { e.ports[0].postMessage(''); }, 250);
+ y(); // will "report the error"
+ // onerror is null so it'll be "not handled", and the error should be
+ // reported to the user, although we don't test that here
+ // make sure we don't fire an error event on the message port or the
+ // SharedWorker object
+}
+
+
+/*
+-->
+<!doctype html>
+<title>shared worker, no error event on worker or port</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+setup({allow_uncaught_exception:true});
+async_test(function() {
+ window.onerror = this.step_func(function(a) {
+ assert_unreached('window.onerror invoked: ' + a);
+ });
+ var worker = new SharedWorker('#', '');
+ worker.addEventListener('error', this.step_func(function(e) {
+ assert_unreached('error on worker');
+ }), false);
+ worker.port.addEventListener('error', this.step_func(function(e) {
+ assert_unreached('error on port');
+ }), false);
+ worker.port.onmessage = this.step_func_done(function(e) {
+ assert_equals(e.data, '');
+ });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/semantics/reporting-errors/004-1.html b/tests/wpt/web-platform-tests/workers/semantics/reporting-errors/004-1.html
new file mode 100644
index 00000000000..676c21e6068
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/semantics/reporting-errors/004-1.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<script>
+parent.t.step(function() {
+ window.onerror = this.step_func(function(a) {
+ assert_unreached('(inner) window.onerror invoked: ' + a);
+ });
+ var worker = new SharedWorker('004.html#', '');
+ worker.addEventListener('error', this.step_func(function(e) {
+ parent.assert_unreached('(inner) error on worker');
+ }), false);
+ worker.port.addEventListener('error', this.step_func(function(e) {
+ parent.assert_unreached('(inner) error on port');
+ }), false);
+ worker.port.onmessage = this.step_func_done(function(e) {
+ parent.assert_equals(e.data, 2);
+ });
+});
+</script>
diff --git a/tests/wpt/web-platform-tests/workers/semantics/reporting-errors/004.html b/tests/wpt/web-platform-tests/workers/semantics/reporting-errors/004.html
new file mode 100644
index 00000000000..1dd1eb3b52a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/semantics/reporting-errors/004.html
@@ -0,0 +1,39 @@
+<!--
+var i = 0;
+onconnect = function (e) {
+ i++;
+ setTimeout(function() { e.ports[0].postMessage(i); }, 250);
+ y(); // will "report the error"
+}
+
+/*
+-->
+<!doctype html>
+<title>shared worker in two documents and window.onerror</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+setup({allow_uncaught_exception:true});
+var t = async_test(function() {
+ window.onerror = this.step_func(function(a) {
+ assert_unreached('(outer) window.onerror invoked: ' + a);
+ });
+ var worker = new SharedWorker('#', '');
+ worker.addEventListener('error', this.step_func(function(e) {
+ assert_unreached('(outer) error on worker');
+ }), false);
+ worker.port.addEventListener('error', this.step_func(function(e) {
+ assert_unreached('(outer) error on port');
+ }), false);
+ worker.port.onmessage = this.step_func(function(e) {
+ assert_equals(e.data, 1);
+ var iframe = document.createElement('iframe');
+ iframe.src = '004-1.html';
+ document.body.appendChild(iframe);
+ });
+});
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/semantics/run-a-worker/001.html b/tests/wpt/web-platform-tests/workers/semantics/run-a-worker/001.html
new file mode 100644
index 00000000000..aa0fc67efc7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/semantics/run-a-worker/001.html
@@ -0,0 +1,22 @@
+<!--
+postMessage(this === self);
+
+/*
+-->
+<!doctype html>
+<title>worker global scope, dedicated worker</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+ var worker = new Worker('#');
+ worker.onmessage = this.step_func(function(e) {
+ assert_true(e.data);
+ this.done();
+ });
+});
+</script>
+<!--
+*/
+//--> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/workers/semantics/run-a-worker/002.html b/tests/wpt/web-platform-tests/workers/semantics/run-a-worker/002.html
new file mode 100644
index 00000000000..3617ad7272a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/semantics/run-a-worker/002.html
@@ -0,0 +1,24 @@
+<!--
+var passed = this === self;
+onconnect = function(e) {
+ e.ports[0].postMessage(passed);
+}
+/*
+-->
+<!doctype html>
+<title>worker global scope, shared worker</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+ var worker = new SharedWorker('#');
+ worker.port.onmessage = this.step_func(function(e) {
+ assert_true(e.data);
+ this.done();
+ });
+});
+</script>
+<!--
+*/
+//--> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/workers/semantics/run-a-worker/003.html b/tests/wpt/web-platform-tests/workers/semantics/run-a-worker/003.html
new file mode 100644
index 00000000000..5b104f7f851
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/semantics/run-a-worker/003.html
@@ -0,0 +1,27 @@
+<!--
+/*
+-->
+<!doctype html>
+<title>handling for 404 response</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+setup({allow_uncaught_exception: true});
+
+async_test(function() {
+ var worker = new Worker('404_worker');
+ worker.onerror = this.step_func(function(e) { this.done(); });
+}, 'worker', {timeout:500});
+
+async_test(function() {
+ var shared = new SharedWorker('404_shared');
+ // NOTE: this handler will not fire, as runtime scripting errors
+ // are not forwarded to SharedWorker objects, but instead reported to the user directly.
+ shared.onerror = this.step_func(function(e) { assert_unreached(); }, shared, 'error');
+ setTimeout(this.step_func(function() { this.done(); }), 500);
+}, 'shared');
+</script>
+<!--
+*/
+//-->
diff --git a/tests/wpt/web-platform-tests/workers/semantics/structured-clone/common.js b/tests/wpt/web-platform-tests/workers/semantics/structured-clone/common.js
new file mode 100644
index 00000000000..56c2a300401
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/semantics/structured-clone/common.js
@@ -0,0 +1,596 @@
+function createWorker(msg) {
+ // `type` is defined in the test case itself
+ if (type == 'dedicated')
+ return new Worker('dedicated.js#'+encodeURIComponent(msg));
+ else if (type == 'shared')
+ return (new SharedWorker('shared.js#'+encodeURIComponent(msg))).port;
+ else
+ assert_unreached('invalid or missing `type`');
+}
+
+function check(msg, input, callback, test_obj) {
+ if (!test_obj)
+ test_obj = async_test(msg);
+ test_obj.step(function() {
+ var w = createWorker(msg);
+ if (typeof input === 'function')
+ input = this.step(input);
+ w.postMessage(input);
+ w.onmessage = this.step_func(function(ev) { callback(ev.data, input, this); });
+ });
+}
+
+function compare_primitive(actual, input, test_obj) {
+ assert_equals(actual, input);
+ if (test_obj)
+ test_obj.done();
+}
+function compare_Array(callback, callback_is_async) {
+ return function(actual, input, test_obj) {
+ if (typeof actual === 'string')
+ assert_unreached(actual);
+ assert_true(actual instanceof Array, 'instanceof Array');
+ assert_not_equals(actual, input);
+ assert_equals(actual.length, input.length, 'length');
+ callback(actual, input);
+ if (test_obj && !callback_is_async)
+ test_obj.done();
+ }
+}
+
+function compare_Object(callback, callback_is_async) {
+ return function(actual, input, test_obj) {
+ if (typeof actual === 'string')
+ assert_unreached(actual);
+ assert_true(actual instanceof Object, 'instanceof Object');
+ assert_false(actual instanceof Array, 'instanceof Array');
+ assert_not_equals(actual, input);
+ callback(actual, input);
+ if (test_obj && !callback_is_async)
+ test_obj.done();
+ }
+}
+
+function enumerate_props(compare_func, test_obj) {
+ return function(actual, input) {
+ for (var x in input) {
+ compare_func(actual[x], input[x], test_obj);
+ }
+ };
+}
+
+check('primitive undefined', undefined, compare_primitive);
+check('primitive null', null, compare_primitive);
+check('primitive true', true, compare_primitive);
+check('primitive false', false, compare_primitive);
+check('primitive string, empty string', '', compare_primitive);
+check('primitive string, lone high surrogate', '\uD800', compare_primitive);
+check('primitive string, lone low surrogate', '\uDC00', compare_primitive);
+check('primitive string, NUL', '\u0000', compare_primitive);
+check('primitive string, astral character', '\uDBFF\uDFFD', compare_primitive);
+check('primitive number, 0.2', 0.2, compare_primitive);
+check('primitive number, 0', 0, compare_primitive);
+check('primitive number, -0', -0, compare_primitive);
+check('primitive number, NaN', NaN, compare_primitive);
+check('primitive number, Infinity', Infinity, compare_primitive);
+check('primitive number, -Infinity', -Infinity, compare_primitive);
+check('primitive number, 9007199254740992', 9007199254740992, compare_primitive);
+check('primitive number, -9007199254740992', -9007199254740992, compare_primitive);
+check('primitive number, 9007199254740994', 9007199254740994, compare_primitive);
+check('primitive number, -9007199254740994', -9007199254740994, compare_primitive);
+
+check('Array primitives', [undefined,
+ null,
+ true,
+ false,
+ '',
+ '\uD800',
+ '\uDC00',
+ '\u0000',
+ '\uDBFF\uDFFD',
+ 0.2,
+ 0,
+ -0,
+ NaN,
+ Infinity,
+ -Infinity,
+ 9007199254740992,
+ -9007199254740992,
+ 9007199254740994,
+ -9007199254740994], compare_Array(enumerate_props(compare_primitive)));
+check('Object primitives', {'undefined':undefined,
+ 'null':null,
+ 'true':true,
+ 'false':false,
+ 'empty':'',
+ 'high surrogate':'\uD800',
+ 'low surrogate':'\uDC00',
+ 'nul':'\u0000',
+ 'astral':'\uDBFF\uDFFD',
+ '0.2':0.2,
+ '0':0,
+ '-0':-0,
+ 'NaN':NaN,
+ 'Infinity':Infinity,
+ '-Infinity':-Infinity,
+ '9007199254740992':9007199254740992,
+ '-9007199254740992':-9007199254740992,
+ '9007199254740994':9007199254740994,
+ '-9007199254740994':-9007199254740994}, compare_Object(enumerate_props(compare_primitive)));
+
+function compare_Boolean(actual, input, test_obj) {
+ if (typeof actual === 'string')
+ assert_unreached(actual);
+ assert_true(actual instanceof Boolean, 'instanceof Boolean');
+ assert_equals(String(actual), String(input), 'converted to primitive');
+ assert_not_equals(actual, input);
+ if (test_obj)
+ test_obj.done();
+}
+check('Boolean true', new Boolean(true), compare_Boolean);
+check('Boolean false', new Boolean(false), compare_Boolean);
+check('Array Boolean objects', [new Boolean(true), new Boolean(false)], compare_Array(enumerate_props(compare_Boolean)));
+check('Object Boolean objects', {'true':new Boolean(true), 'false':new Boolean(false)}, compare_Object(enumerate_props(compare_Boolean)));
+
+function compare_obj(what) {
+ var Type = window[what];
+ return function(actual, input, test_obj) {
+ if (typeof actual === 'string')
+ assert_unreached(actual);
+ assert_true(actual instanceof Type, 'instanceof '+what);
+ assert_equals(Type(actual), Type(input), 'converted to primitive');
+ assert_not_equals(actual, input);
+ if (test_obj)
+ test_obj.done();
+ };
+}
+check('String empty string', new String(''), compare_obj('String'));
+check('String lone high surrogate', new String('\uD800'), compare_obj('String'));
+check('String lone low surrogate', new String('\uDC00'), compare_obj('String'));
+check('String NUL', new String('\u0000'), compare_obj('String'));
+check('String astral character', new String('\uDBFF\uDFFD'), compare_obj('String'));
+check('Array String objects', [new String(''),
+ new String('\uD800'),
+ new String('\uDC00'),
+ new String('\u0000'),
+ new String('\uDBFF\uDFFD')], compare_Array(enumerate_props(compare_obj('String'))));
+check('Object String objects', {'empty':new String(''),
+ 'high surrogate':new String('\uD800'),
+ 'low surrogate':new String('\uDC00'),
+ 'nul':new String('\u0000'),
+ 'astral':new String('\uDBFF\uDFFD')}, compare_Object(enumerate_props(compare_obj('String'))));
+
+check('Number 0.2', new Number(0.2), compare_obj('Number'));
+check('Number 0', new Number(0), compare_obj('Number'));
+check('Number -0', new Number(-0), compare_obj('Number'));
+check('Number NaN', new Number(NaN), compare_obj('Number'));
+check('Number Infinity', new Number(Infinity), compare_obj('Number'));
+check('Number -Infinity', new Number(-Infinity), compare_obj('Number'));
+check('Number 9007199254740992', new Number(9007199254740992), compare_obj('Number'));
+check('Number -9007199254740992', new Number(-9007199254740992), compare_obj('Number'));
+check('Number 9007199254740994', new Number(9007199254740994), compare_obj('Number'));
+check('Number -9007199254740994', new Number(-9007199254740994), compare_obj('Number'));
+check('Array Number objects', [new Number(0.2),
+ new Number(0),
+ new Number(-0),
+ new Number(NaN),
+ new Number(Infinity),
+ new Number(-Infinity),
+ new Number(9007199254740992),
+ new Number(-9007199254740992),
+ new Number(9007199254740994),
+ new Number(-9007199254740994)], compare_Array(enumerate_props(compare_obj('Number'))));
+check('Object Number objects', {'0.2':new Number(0.2),
+ '0':new Number(0),
+ '-0':new Number(-0),
+ 'NaN':new Number(NaN),
+ 'Infinity':new Number(Infinity),
+ '-Infinity':new Number(-Infinity),
+ '9007199254740992':new Number(9007199254740992),
+ '-9007199254740992':new Number(-9007199254740992),
+ '9007199254740994':new Number(9007199254740994),
+ '-9007199254740994':new Number(-9007199254740994)}, compare_Object(enumerate_props(compare_obj('Number'))));
+
+function compare_Date(actual, input, test_obj) {
+ if (typeof actual === 'string')
+ assert_unreached(actual);
+ assert_true(actual instanceof Date, 'instanceof Date');
+ assert_equals(Number(actual), Number(input), 'converted to primitive');
+ assert_not_equals(actual, input);
+ if (test_obj)
+ test_obj.done();
+}
+check('Date 0', new Date(0), compare_Date);
+check('Date -0', new Date(-0), compare_Date);
+check('Date -8.64e15', new Date(-8.64e15), compare_Date);
+check('Date 8.64e15', new Date(8.64e15), compare_Date);
+check('Array Date objects', [new Date(0),
+ new Date(-0),
+ new Date(-8.64e15),
+ new Date(8.64e15)], compare_Array(enumerate_props(compare_Date)));
+check('Object Date objects', {'0':new Date(0),
+ '-0':new Date(-0),
+ '-8.64e15':new Date(-8.64e15),
+ '8.64e15':new Date(8.64e15)}, compare_Object(enumerate_props(compare_Date)));
+
+function compare_RegExp(expected_source) {
+ // XXX ES6 spec doesn't define exact serialization for `source` (it allows several ways to escape)
+ return function(actual, input, test_obj) {
+ if (typeof actual === 'string')
+ assert_unreached(actual);
+ assert_true(actual instanceof RegExp, 'instanceof RegExp');
+ assert_equals(actual.global, input.global, 'global');
+ assert_equals(actual.ignoreCase, input.ignoreCase, 'ignoreCase');
+ assert_equals(actual.multiline, input.multiline, 'multiline');
+ assert_equals(actual.source, expected_source, 'source');
+ assert_equals(actual.sticky, input.sticky, 'sticky');
+ assert_equals(actual.unicode, input.unicode, 'unicode');
+ assert_equals(actual.lastIndex, 0, 'lastIndex');
+ assert_not_equals(actual, input);
+ if (test_obj)
+ test_obj.done();
+ }
+}
+function func_RegExp_flags_lastIndex() {
+ var r = /foo/gim;
+ r.lastIndex = 2;
+ return r;
+}
+function func_RegExp_sticky() {
+ return new RegExp('foo', 'y');
+}
+function func_RegExp_unicode() {
+ return new RegExp('foo', 'u');
+}
+check('RegExp flags and lastIndex', func_RegExp_flags_lastIndex, compare_RegExp('foo'));
+check('RegExp sticky flag', func_RegExp_sticky, compare_RegExp('foo'));
+check('RegExp unicode flag', func_RegExp_unicode, compare_RegExp('foo'));
+check('RegExp empty', new RegExp(''), compare_RegExp('(?:)'));
+check('RegExp slash', new RegExp('/'), compare_RegExp('\\/'));
+check('RegExp new line', new RegExp('\n'), compare_RegExp('\\n'));
+check('Array RegExp object, RegExp flags and lastIndex', [func_RegExp_flags_lastIndex()], compare_Array(enumerate_props(compare_RegExp('foo'))));
+check('Array RegExp object, RegExp sticky flag', function() { return [func_RegExp_sticky()]; }, compare_Array(enumerate_props(compare_RegExp('foo'))));
+check('Array RegExp object, RegExp unicode flag', function() { return [func_RegExp_unicode()]; }, compare_Array(enumerate_props(compare_RegExp('foo'))));
+check('Array RegExp object, RegExp empty', [new RegExp('')], compare_Array(enumerate_props(compare_RegExp('(?:)'))));
+check('Array RegExp object, RegExp slash', [new RegExp('/')], compare_Array(enumerate_props(compare_RegExp('\\/'))));
+check('Array RegExp object, RegExp new line', [new RegExp('\n')], compare_Array(enumerate_props(compare_RegExp('\\n'))));
+check('Object RegExp object, RegExp flags and lastIndex', {'x':func_RegExp_flags_lastIndex()}, compare_Object(enumerate_props(compare_RegExp('foo'))));
+check('Object RegExp object, RegExp sticky flag', function() { return {'x':func_RegExp_sticky()}; }, compare_Object(enumerate_props(compare_RegExp('foo'))));
+check('Object RegExp object, RegExp unicode flag', function() { return {'x':func_RegExp_unicode()}; }, compare_Object(enumerate_props(compare_RegExp('foo'))));
+check('Object RegExp object, RegExp empty', {'x':new RegExp('')}, compare_Object(enumerate_props(compare_RegExp('(?:)'))));
+check('Object RegExp object, RegExp slash', {'x':new RegExp('/')}, compare_Object(enumerate_props(compare_RegExp('\\/'))));
+check('Object RegExp object, RegExp new line', {'x':new RegExp('\n')}, compare_Object(enumerate_props(compare_RegExp('\\n'))));
+
+function compare_Blob(actual, input, test_obj, expect_File) {
+ if (typeof actual === 'string')
+ assert_unreached(actual);
+ assert_true(actual instanceof Blob, 'instanceof Blob');
+ if (!expect_File)
+ assert_false(actual instanceof File, 'instanceof File');
+ assert_equals(actual.size, input.size, 'size');
+ assert_equals(actual.type, input.type, 'type');
+ assert_not_equals(actual, input);
+ var ev_reader = new FileReader();
+ var input_reader = new FileReader();
+ var read_count = 0;
+ var read_done = test_obj.step_func(function() {
+ read_count++;
+ if (read_count == 2) {
+ var ev_result = ev_reader.result;
+ var input_result = input_reader.result;
+ assert_equals(ev_result.byteLength, input_result.byteLength, 'byteLength');
+ var ev_view = new DataView(ev_result);
+ var input_view = new DataView(input_result);
+ for (var i = 0; i < ev_result.byteLength; ++i) {
+ assert_equals(ev_view.getUint8(i), input_view.getUint8(i), 'getUint8('+i+')');
+ }
+ if (test_obj)
+ test_obj.done();
+ }
+ });
+ var read_error = test_obj.step_func(function() { assert_unreached('FileReader error'); });
+ ev_reader.readAsArrayBuffer(actual);
+ ev_reader.onload = read_done;
+ ev_reader.onabort = ev_reader.onerror = read_error;
+ input_reader.readAsArrayBuffer(input);
+ input_reader.onload = read_done;
+ input_reader.onabort = input_reader.onerror = read_error;
+}
+function func_Blob_basic() {
+ return new Blob(['foo'], {type:'text/x-bar'});
+}
+check('Blob basic', func_Blob_basic, compare_Blob);
+
+function b(str) {
+ return parseInt(str, 2);
+}
+function encode_cesu8(codeunits) {
+ // http://www.unicode.org/reports/tr26/ section 2.2
+ // only the 3-byte form is supported
+ var rv = [];
+ codeunits.forEach(function(codeunit) {
+ rv.push(b('11100000') + ((codeunit & b('1111000000000000')) >> 12));
+ rv.push(b('10000000') + ((codeunit & b('0000111111000000')) >> 6));
+ rv.push(b('10000000') + (codeunit & b('0000000000111111')));
+ });
+ return rv;
+}
+function func_Blob_bytes(arr) {
+ return function() {
+ var buffer = new ArrayBuffer(arr.length);
+ var view = new DataView(buffer);
+ for (var i = 0; i < arr.length; ++i) {
+ view.setUint8(i, arr[i]);
+ }
+ return new Blob([view]);
+ };
+}
+check('Blob unpaired high surrogate (invalid utf-8)', func_Blob_bytes(encode_cesu8([0xD800])), compare_Blob);
+check('Blob unpaired low surrogate (invalid utf-8)', func_Blob_bytes(encode_cesu8([0xDC00])), compare_Blob);
+check('Blob paired surrogates (invalid utf-8)', func_Blob_bytes(encode_cesu8([0xD800, 0xDC00])), compare_Blob);
+
+function func_Blob_empty() {
+ return new Blob(['']);
+}
+check('Blob empty', func_Blob_empty , compare_Blob);
+function func_Blob_NUL() {
+ return new Blob(['\u0000']);
+}
+check('Blob NUL', func_Blob_NUL, compare_Blob);
+
+async_test(function(test_obj) {
+ check(test_obj.name, [test_obj.step(func_Blob_basic)], compare_Array(enumerate_props(compare_Blob, test_obj), true), test_obj);
+}, 'Array Blob object, Blob basic');
+async_test(function(test_obj) {
+ check(test_obj.name, [test_obj.step(func_Blob_bytes([0xD800]))], compare_Array(enumerate_props(compare_Blob, test_obj), true), test_obj);
+}, 'Array Blob object, Blob unpaired high surrogate (invalid utf-8)');
+async_test(function(test_obj) {
+ check(test_obj.name, [test_obj.step(func_Blob_bytes([0xDC00]))], compare_Array(enumerate_props(compare_Blob, test_obj), true), test_obj);
+}, 'Array Blob object, Blob unpaired low surrogate (invalid utf-8)');
+async_test(function(test_obj) {
+ check(test_obj.name, [test_obj.step(func_Blob_bytes([0xD800, 0xDC00]))], compare_Array(enumerate_props(compare_Blob, test_obj), true), test_obj);
+}, 'Array Blob object, Blob paired surrogates (invalid utf-8)');
+async_test(function(test_obj) {
+ check(test_obj.name, [test_obj.step(func_Blob_empty)], compare_Array(enumerate_props(compare_Blob, test_obj), true), test_obj);
+}, 'Array Blob object, Blob empty');
+async_test(function(test_obj) {
+ check(test_obj.name, [test_obj.step(func_Blob_NUL)], compare_Array(enumerate_props(compare_Blob, test_obj), true), test_obj);
+}, 'Array Blob object, Blob NUL');
+
+async_test(function(test_obj) {
+ check(test_obj.name, {'x':test_obj.step(func_Blob_basic)}, compare_Object(enumerate_props(compare_Blob, test_obj), true), test_obj);
+}, 'Object Blob object, Blob basic');
+async_test(function(test_obj) {
+ check(test_obj.name, {'x':test_obj.step(func_Blob_bytes([0xD800]))}, compare_Object(enumerate_props(compare_Blob, test_obj), true), test_obj);
+}, 'Object Blob object, Blob unpaired high surrogate (invalid utf-8)');
+async_test(function(test_obj) {
+ check(test_obj.name, {'x':test_obj.step(func_Blob_bytes([0xDC00]))}, compare_Object(enumerate_props(compare_Blob, test_obj), true), test_obj);
+}, 'Object Blob object, Blob unpaired low surrogate (invalid utf-8)');
+async_test(function(test_obj) {
+ check(test_obj.name, {'x':test_obj.step(func_Blob_bytes([0xD800, 0xDC00]))}, compare_Object(enumerate_props(compare_Blob, test_obj), true), test_obj);
+}, 'Object Blob object, Blob paired surrogates (invalid utf-8)');
+async_test(function(test_obj) {
+ check(test_obj.name, {'x':test_obj.step(func_Blob_empty)}, compare_Object(enumerate_props(compare_Blob, test_obj), true), test_obj);
+}, 'Object Blob object, Blob empty');
+async_test(function(test_obj) {
+ check(test_obj.name, {'x':test_obj.step(func_Blob_NUL)}, compare_Object(enumerate_props(compare_Blob, test_obj), true), test_obj);
+}, 'Object Blob object, Blob NUL');
+
+function compare_File(actual, input, test_obj) {
+ assert_true(actual instanceof File, 'instanceof File');
+ assert_equals(actual.name, input.name, 'name');
+ assert_equals(actual.lastModified, input.lastModified, 'lastModified');
+ compare_Blob(actual, input, test_obj, true);
+}
+function func_File_basic() {
+ return new File(['foo'], 'bar', {type:'text/x-bar', lastModified:42});
+}
+check('File basic', func_File_basic, compare_File);
+
+function compare_FileList(actual, input, test_obj) {
+ if (typeof actual === 'string')
+ assert_unreached(actual);
+ assert_true(actual instanceof FileList, 'instanceof FileList');
+ assert_equals(actual.length, input.length, 'length');
+ assert_not_equals(actual, input);
+ // XXX when there's a way to populate or construct a FileList,
+ // check the items in the FileList
+ if (test_obj)
+ test_obj.done();
+}
+function func_FileList_empty() {
+ var input = document.createElement('input');
+ input.type = 'file';
+ return input.files;
+}
+check('FileList empty', func_FileList_empty, compare_FileList);
+check('Array FileList object, FileList empty', [func_FileList_empty], compare_Array(enumerate_props(compare_FileList)));
+check('Object FileList object, FileList empty', {'x':func_FileList_empty}, compare_Object(enumerate_props(compare_FileList)));
+
+function compare_ArrayBufferView(view) {
+ var Type = window[view];
+ return function(actual, input, test_obj) {
+ if (typeof actual === 'string')
+ assert_unreached(actual);
+ assert_true(actual instanceof Type, 'instanceof '+view);
+ assert_equals(actual.length, input.length, 'length');
+ assert_not_equals(actual.buffer, input.buffer, 'buffer');
+ for (var i = 0; i < actual.length; ++i) {
+ assert_equals(actual[i], input[i], 'actual['+i+']');
+ }
+ if (test_obj)
+ test_obj.done();
+ };
+}
+function compare_ImageData(actual, input, test_obj) {
+ if (typeof actual === 'string')
+ assert_unreached(actual);
+ assert_equals(actual.width, input.width, 'width');
+ assert_equals(actual.height, input.height, 'height');
+ assert_not_equals(actual.data, input.data, 'data');
+ compare_ArrayBufferView('Uint8ClampedArray')(actual.data, input.data, null);
+ if (test_obj)
+ test_obj.done();
+}
+function func_ImageData_1x1_transparent_black() {
+ var canvas = document.createElement('canvas');
+ var ctx = canvas.getContext('2d');
+ return ctx.createImageData(1, 1);
+}
+check('ImageData 1x1 transparent black', func_ImageData_1x1_transparent_black, compare_ImageData);
+function func_ImageData_1x1_non_transparent_non_black() {
+ var canvas = document.createElement('canvas');
+ var ctx = canvas.getContext('2d');
+ var imagedata = ctx.createImageData(1, 1);
+ imagedata.data[0] = 100;
+ imagedata.data[1] = 101;
+ imagedata.data[2] = 102;
+ imagedata.data[3] = 103;
+ return imagedata;
+}
+check('ImageData 1x1 non-transparent non-black', func_ImageData_1x1_non_transparent_non_black, compare_ImageData);
+async_test(function(test_obj) {
+ check(test_obj.name, [test_obj.step(func_ImageData_1x1_transparent_black)], compare_Array(enumerate_props(compare_ImageData)), test_obj);
+}, 'Array ImageData object, ImageData 1x1 transparent black');
+async_test(function(test_obj) {
+ check(test_obj.name, [test_obj.step(func_ImageData_1x1_non_transparent_non_black)], compare_Array(enumerate_props(compare_ImageData)), test_obj);
+}, 'Array ImageData object, ImageData 1x1 non-transparent non-black');
+async_test(function(test_obj) {
+ check(test_obj.name, {'x':test_obj.step(func_ImageData_1x1_transparent_black)}, compare_Object(enumerate_props(compare_ImageData)), test_obj);
+}, 'Object ImageData object, ImageData 1x1 transparent black');
+async_test(function(test_obj) {
+ check(test_obj.name, {'x':test_obj.step(func_ImageData_1x1_non_transparent_non_black)}, compare_Object(enumerate_props(compare_ImageData)), test_obj);
+}, 'Object ImageData object, ImageData 1x1 non-transparent non-black');
+
+function compare_ImageBitmap(actual, input, test_obj) {
+ if (typeof actual === 'string')
+ assert_unreached(actual);
+ assert_equals(actual instanceof ImageBitmap, 'instanceof ImageBitmap');
+ assert_not_equals(actual, input);
+ // XXX paint the ImageBitmap on a canvas and check the data
+ if (test_obj)
+ test_obj.done();
+}
+function get_canvas_1x1_transparent_black() {
+ var canvas = document.createElement('canvas');
+ canvas.width = 1;
+ canvas.height = 1;
+ return canvas;
+}
+async_test(function(test_obj) {
+ var canvas = get_canvas_1x1_transparent_black();
+ createImageBitmap(canvas, function(image) { check(test_obj.name, image, compare_ImageBitmap, test_obj); });
+}, 'ImageBitmap 1x1 transparent black');
+function get_canvas_1x1_non_transparent_non_black() {
+ var canvas = document.createElement('canvas');
+ canvas.width = 1;
+ canvas.height = 1;
+ var ctx = canvas.getContext('2d');
+ var imagedata = ctx.getImageData(0, 0, 1, 1);
+ imagedata.data[0] = 100;
+ imagedata.data[1] = 101;
+ imagedata.data[2] = 102;
+ imagedata.data[3] = 103;
+ return canvas;
+}
+async_test(function(test_obj) {
+ var canvas = get_canvas_1x1_non_transparent_non_black();
+ createImageBitmap(canvas, function(image) { check(test_obj.name, image, compare_ImageBitmap, test_obj); });
+}, 'ImageBitmap 1x1 non-transparent non-black');
+
+async_test(function(test_obj) {
+ var canvas = get_canvas_1x1_transparent_black();
+ createImageBitmap(canvas, function(image) { check(test_obj.name, [image], compare_Array(enumerate_props(compare_ImageBitmap)), test_obj); });
+}, 'Array ImageBitmap object, ImageBitmap 1x1 transparent black');
+async_test(function(test_obj) {
+ var canvas = get_canvas_1x1_non_transparent_non_black();
+ createImageBitmap(canvas, function(image) { check(test_obj.name, [image], compare_Array(enumerate_props(compare_ImageBitmap)), test_obj); });
+}, 'Array ImageBitmap object, ImageBitmap 1x1 non-transparent non-black');
+
+async_test(function(test_obj) {
+ var canvas = get_canvas_1x1_transparent_black();
+ createImageBitmap(canvas, function(image) { check(test_obj.name, {'x':image}, compare_Object(enumerate_props(compare_ImageBitmap)), test_obj); });
+}, 'Object ImageBitmap object, ImageBitmap 1x1 transparent black');
+async_test(function(test_obj) {
+ var canvas = get_canvas_1x1_non_transparent_non_black();
+ createImageBitmap(canvas, function(image) { check(test_obj.name, {'x':image}, compare_Object(enumerate_props(compare_ImageBitmap)), test_obj); });
+}, 'Object ImageBitmap object, ImageBitmap 1x1 non-transparent non-black');
+
+check('Array sparse', new Array(10), compare_Array(enumerate_props(compare_primitive)));
+check('Array with non-index property', function() {
+ var rv = [];
+ rv.foo = 'bar';
+ return rv;
+}, compare_Array(enumerate_props(compare_primitive)));
+check('Object with index property and length', {'0':'foo', 'length':1}, compare_Object(enumerate_props(compare_primitive)));
+function check_circular_property(prop) {
+ return function(actual) {
+ assert_equals(actual[prop], actual);
+ };
+}
+check('Array with circular reference', function() {
+ var rv = [];
+ rv[0] = rv;
+ return rv;
+}, compare_Array(check_circular_property('0')));
+check('Object with circular reference', function() {
+ var rv = {};
+ rv['x'] = rv;
+ return rv;
+}, compare_Object(check_circular_property('x')));
+function check_identical_property_values(prop1, prop2) {
+ return function(actual) {
+ assert_equals(actual[prop1], actual[prop2]);
+ };
+}
+check('Array with identical property values', function() {
+ var obj = {}
+ return [obj, obj];
+}, compare_Array(check_identical_property_values('0', '1')));
+check('Object with identical property values', function() {
+ var obj = {}
+ return {'x':obj, 'y':obj};
+}, compare_Object(check_identical_property_values('x', 'y')));
+
+function check_absent_property(prop) {
+ return function(actual) {
+ assert_false(prop in actual);
+ };
+}
+check('Object with property on prototype', function() {
+ var Foo = function() {};
+ Foo.prototype = {'foo':'bar'};
+ return new Foo();
+}, compare_Object(check_absent_property('foo')));
+
+check('Object with non-enumerable property', function() {
+ var rv = {};
+ Object.defineProperty(rv, 'foo', {value:'bar', enumerable:false, writable:true, configurable:true});
+ return rv;
+}, compare_Object(check_absent_property('foo')));
+
+function check_writable_property(prop) {
+ return function(actual, input) {
+ assert_equals(actual[prop], input[prop]);
+ actual[prop] += ' baz';
+ assert_equals(actual[prop], input[prop] + ' baz');
+ };
+}
+check('Object with non-writable property', function() {
+ var rv = {};
+ Object.defineProperty(rv, 'foo', {value:'bar', enumerable:true, writable:false, configurable:true});
+ return rv;
+}, compare_Object(check_writable_property('foo')));
+
+function check_configurable_property(prop) {
+ return function(actual, input) {
+ assert_equals(actual[prop], input[prop]);
+ delete actual[prop];
+ assert_false('prop' in actual);
+ };
+}
+check('Object with non-configurable property', function() {
+ var rv = {};
+ Object.defineProperty(rv, 'foo', {value:'bar', enumerable:true, writable:true, configurable:false});
+ return rv;
+}, compare_Object(check_configurable_property('foo')));
diff --git a/tests/wpt/web-platform-tests/workers/semantics/structured-clone/dedicated.html b/tests/wpt/web-platform-tests/workers/semantics/structured-clone/dedicated.html
new file mode 100644
index 00000000000..5dd8c3561e9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/semantics/structured-clone/dedicated.html
@@ -0,0 +1,9 @@
+<!doctype html>
+<title>structured clone to dedicated worker</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var type = 'dedicated';
+</script>
+<script src="common.js"></script>
diff --git a/tests/wpt/web-platform-tests/workers/semantics/structured-clone/dedicated.js b/tests/wpt/web-platform-tests/workers/semantics/structured-clone/dedicated.js
new file mode 100644
index 00000000000..4744578b229
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/semantics/structured-clone/dedicated.js
@@ -0,0 +1,4 @@
+importScripts('worker-common.js');
+onmessage = function(ev) {
+ check(ev.data, self);
+};
diff --git a/tests/wpt/web-platform-tests/workers/semantics/structured-clone/shared.html b/tests/wpt/web-platform-tests/workers/semantics/structured-clone/shared.html
new file mode 100644
index 00000000000..6f74354d482
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/semantics/structured-clone/shared.html
@@ -0,0 +1,9 @@
+<!doctype html>
+<title>structured clone to shared worker</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var type = 'shared';
+</script>
+<script src="common.js"></script>
diff --git a/tests/wpt/web-platform-tests/workers/semantics/structured-clone/shared.js b/tests/wpt/web-platform-tests/workers/semantics/structured-clone/shared.js
new file mode 100644
index 00000000000..372a9ec98d6
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/semantics/structured-clone/shared.js
@@ -0,0 +1,6 @@
+importScripts('worker-common.js');
+onconnect = function(connect_ev) {
+ connect_ev.ports[0].onmessage = function(message_ev) {
+ check(message_ev.data, this);
+ };
+};
diff --git a/tests/wpt/web-platform-tests/workers/semantics/structured-clone/worker-common.js b/tests/wpt/web-platform-tests/workers/semantics/structured-clone/worker-common.js
new file mode 100644
index 00000000000..fd63ff5a5d7
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/semantics/structured-clone/worker-common.js
@@ -0,0 +1,1018 @@
+var msg = decodeURIComponent(location.hash.substr(1));
+
+var log = [];
+function check_true(actual, msg) {
+ if (actual !== true) {
+ log.push(msg);
+ return false;
+ }
+ return true;
+}
+
+function check_Blob(msg, input, port, expect_File, orig_input) {
+ expect_File = !!expect_File;
+ orig_input = orig_input || input;
+ try {
+ var expected;
+ switch (msg) {
+ case 'Blob basic':
+ case 'File basic':
+ expected = [0x66, 0x6F, 0x6F];
+ expected.type = 'text/x-bar';
+ if (expect_File) {
+ expected.name = 'bar';
+ expected.lastModified = 42;
+ }
+ break;
+ case 'Blob unpaired high surrogate (invalid utf-8)':
+ expected = [0xED, 0xA0, 0x80];
+ expected.type = '';
+ break;
+ case 'Blob unpaired low surrogate (invalid utf-8)':
+ expected = [0xED, 0xB0, 0x80];
+ expected.type = '';
+ break;
+ case 'Blob paired surrogates (invalid utf-8)':
+ expected = [0xED, 0xA0, 0x80, 0xED, 0xB0, 0x80];
+ expected.type = '';
+ break;
+ case 'Blob empty':
+ expected = [];
+ expected.type = '';
+ break;
+ case 'Blob NUL':
+ var expected = [0x00];
+ expected.type = '';
+ break;
+ default:
+ check_true(false, 'check_Blob: unknown test');
+ return;
+ break;
+ }
+ if (check_true(input instanceof Blob, 'input instanceof Blob') &&
+ check_true((input instanceof File) == expect_File, '(input instanceof File) == expect_File') &&
+ check_true(input.size === expected.length, 'input.size === expected.length') &&
+ check_true(input.type === expected.type, 'input.type === expected.type')) {
+ if (!expect_File || (check_true(input.name === expected.name, 'input.name === expected.name') &&
+ check_true(input.lastModified === expected.lastModified))) {
+ var reader = new FileReader();
+ var read_done = function() {
+ try {
+ var result = reader.result;
+ check_true(result.byteLength === expected.length, 'result.byteLength === expected.length')
+ var view = new DataView(result);
+ for (var i = 0; i < result.byteLength; ++i) {
+ check_true(view.getUint8(i) === expected[i], 'view.getUint8('+i+') === expected['+i+']')
+ }
+ if (log.length === 0) {
+ port.postMessage(orig_input);
+ } else {
+ port.postMessage('FAIL '+log);
+ }
+ close();
+ } catch(ex) {
+ postMessage('FAIL '+ex);
+ close();
+ }
+ }
+ var read_error = function() { port.postMessage('FAIL (got FileReader error)'); close(); };
+ reader.readAsArrayBuffer(input);
+ reader.onload = read_done;
+ reader.onabort = reader.onerror = read_error;
+ }
+ } else {
+ port.postMessage('FAIL '+log);
+ close();
+ }
+ } catch(ex) {
+ postMessage('FAIL '+ex);
+ close();
+ }
+}
+
+function check_ImageData(input, expected) {
+ if (check_true(input instanceof ImageData, 'input instanceof ImageData') &&
+ check_true(input.width === expected.width, 'input.width === '+expected.width) &&
+ check_true(input.height === expected.height, 'input.height === '+expected.height) &&
+ check_true(input.data instanceof Uint8ClampedArray, 'input.data instanceof Uint8ClampedArray') &&
+ check_true(input.data.length === expected.data.length, 'input.data.length === '+expected.data.length) &&
+ check_true(!('CanvasPixelArray' in self), "!('CanvasPixelArray' in self)")) {
+ for (var i = 0; i < input.length; ++i) {
+ if (!(check_true(input.data[i] === expected.data[i], 'input.data['+i+'] === '+expected.data[i]))) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+}
+
+function check_ImageBitmap(input, expected) {
+ return check_true(input instanceof ImageBitmap, 'input instanceof ImageBitmap');
+ // XXX paint it on a proxy canvas and check the data
+}
+
+function check_RegExp(msg, input) {
+ // XXX ES6 spec doesn't define exact serialization for `source` (it allows several ways to escape)
+ switch (msg) {
+ case 'RegExp flags and lastIndex':
+ return check_true(input instanceof RegExp, "input instanceof RegExp") &&
+ check_true(input.source === 'foo', "input.source === 'foo'") &&
+ check_true(input.global === true, "input.global === true") &&
+ check_true(input.ignoreCase === true, "input.ignoreCase === true") &&
+ check_true(input.multiline === true, "input.multiline === true") &&
+ check_true(input.lastIndex === 0, "input.lastIndex === 0");
+ break;
+ case 'RegExp sticky flag':
+ return check_true(input instanceof RegExp, "input instanceof RegExp") &&
+ check_true(input.source === 'foo', "input.source === 'foo'") &&
+ check_true(input.global === false, "input.global === false") &&
+ check_true(input.ignoreCase === false, "input.ignoreCase === false") &&
+ check_true(input.multiline === false, "input.multiline === false") &&
+ check_true(input.sticky === true, "input.sticky === true") &&
+ check_true(input.unicode === false, "input.unicode === false") &&
+ check_true(input.lastIndex === 0, "input.lastIndex === 0");
+ break;
+ case 'RegExp unicode flag':
+ return check_true(input instanceof RegExp, "input instanceof RegExp") &&
+ check_true(input.source === 'foo', "input.source === 'foo'") &&
+ check_true(input.global === false, "input.global === false") &&
+ check_true(input.ignoreCase === false, "input.ignoreCase === false") &&
+ check_true(input.multiline === false, "input.multiline === false") &&
+ check_true(input.sticky === false, "input.sticky === false") &&
+ check_true(input.unicode === true, "input.unicode === true") &&
+ check_true(input.lastIndex === 0, "input.lastIndex === 0");
+ break;
+ case 'RegExp empty':
+ return check_true(input instanceof RegExp, "input instanceof RegExp") &&
+ check_true(input.source === '(?:)', "input.source === '(?:)'") &&
+ check_true(input.global === false, "input.global === false") &&
+ check_true(input.ignoreCase === false, "input.ignoreCase === false") &&
+ check_true(input.multiline === false, "input.multiline === false") &&
+ check_true(input.lastIndex === 0, "input.lastIndex === 0");
+ break;
+ case 'RegExp slash':
+ return check_true(input instanceof RegExp, "input instanceof RegExp") &&
+ check_true(input.source === '\\/', "input.source === '\\\\/'") &&
+ check_true(input.global === false, "input.global === false") &&
+ check_true(input.ignoreCase === false, "input.ignoreCase === false") &&
+ check_true(input.multiline === false, "input.multiline === false") &&
+ check_true(input.lastIndex === 0, "input.lastIndex === 0");
+ break;
+ case 'RegExp new line':
+ return check_true(input instanceof RegExp, "input instanceof RegExp") &&
+ check_true(input.source === '\\n', "input.source === '\\\\n'") &&
+ check_true(input.global === false, "input.global === false") &&
+ check_true(input.ignoreCase === false, "input.ignoreCase === false") &&
+ check_true(input.multiline === false, "input.multiline === false") &&
+ check_true(input.lastIndex === 0, "input.lastIndex === 0");
+ break;
+ default:
+ check_true(false, 'check_RegExp: unknown test');
+ return false;
+ break;
+ }
+}
+
+function check_FileList(msg, input) {
+ try {
+ return check_true(input instanceof FileList, 'input instanceof FileList') &&
+ check_true(input.length === 0, 'input.length === 0');
+ } catch(ex) {
+ return check_true(false, ex);
+ }
+}
+
+function check(input, port) {
+ try {
+ switch (msg) {
+ case 'primitive undefined':
+ if (check_true(input === undefined, 'input === undefined')) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'primitive null':
+ if (check_true(input === null, 'input === null')) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'primitive true':
+ if (check_true(input === true, 'input === true')) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'primitive false':
+ if (check_true(input === false, 'input === false')) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'primitive string, empty string':
+ if (check_true(input === '', "input === ''")) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'primitive string, lone high surrogate':
+ if (check_true(input === '\uD800', "input === '\uD800'")) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'primitive string, lone low surrogate':
+ if (check_true(input === '\uDC00', "input === '\uDC00'")) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'primitive string, NUL':
+ if (check_true(input === '\u0000', "input === '\u0000'")) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'primitive string, astral character':
+ if (check_true(input === '\uDBFF\uDFFD', "input === '\uDBFF\uDFFD'")) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'primitive number, 0.2':
+ if (check_true(input === 0.2, "input === 0.2")) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'primitive number, 0':
+ if (check_true(input === 0, "input === 0") &&
+ check_true(1/input === Infinity, "1/input === Infinity")) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'primitive number, -0':
+ if (check_true(input === 0, "input === 0") &&
+ check_true(1/input === -Infinity, "1/input === -Infinity")) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'primitive number, NaN':
+ if (check_true(input !== input, "input !== input")) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'primitive number, Infinity':
+ if (check_true(input === Infinity, "input === Infinity")) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'primitive number, -Infinity':
+ if (check_true(input === -Infinity, "input === -Infinity")) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'primitive number, 9007199254740992':
+ if (check_true(input === 9007199254740992, "input === 9007199254740992")) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'primitive number, -9007199254740992':
+ if (check_true(input === -9007199254740992, "input === -9007199254740992")) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'primitive number, 9007199254740994':
+ if (check_true(input === 9007199254740994, "input === 9007199254740994")) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'primitive number, -9007199254740994':
+ if (check_true(input === -9007199254740994, "input === -9007199254740994")) {
+ port.postMessage(input);
+ close();
+ break;
+ }
+ case 'Array primitives':
+ if (check_true(input instanceof Array, 'input instanceof Array') &&
+ check_true(input.length === 19, 'input.length === 19') &&
+ check_true(input[0] === undefined, 'input[0] === undefined') &&
+ check_true(input[1] === null, 'input[1] === null') &&
+ check_true(input[2] === true, 'input[2] === true') &&
+ check_true(input[3] === false, 'input[3] === false') &&
+ check_true(input[4] === '', "input[4] === ''") &&
+ check_true(input[5] === '\uD800', "input[5] === '\\uD800'") &&
+ check_true(input[6] === '\uDC00', "input[6] === '\\uDC00'") &&
+ check_true(input[7] === '\u0000', "input[7] === '\\u0000'") &&
+ check_true(input[8] === '\uDBFF\uDFFD', "input[8] === '\\uDBFF\\uDFFD'") &&
+ check_true(input[9] === 0.2, "input[9] === 0.2") &&
+ check_true(1/input[10] === Infinity, "1/input[10] === Infinity") &&
+ check_true(1/input[11] === -Infinity, "1/input[11] === -Infinity") &&
+ check_true(input[12] !== input[11], "input[12] !== input[11]") &&
+ check_true(input[13] === Infinity, "input[13] === Infinity") &&
+ check_true(input[14] === -Infinity, "input[14] === -Infinity") &&
+ check_true(input[15] === 9007199254740992, "input[15] === 9007199254740992") &&
+ check_true(input[16] === -9007199254740992, "input[16] === -9007199254740992") &&
+ check_true(input[17] === 9007199254740994, "input[17] === 9007199254740994") &&
+ check_true(input[18] === -9007199254740994, "input[18] === -9007199254740994")) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'Object primitives':
+ (function() {
+ if (check_true(input instanceof Object, 'input instanceof Object') &&
+ check_true(!(input instanceof Array), '!(input instanceof Array)') &&
+ check_true(input['undefined'] === undefined, "input['undefined'] === undefined") &&
+ check_true(input['null'] === null, "input['null'] === null") &&
+ check_true(input['true'] === true, "input['true'] === true") &&
+ check_true(input['false'] === false, "input['false'] === false") &&
+ check_true(input['empty'] === '', "input['empty'] === ''") &&
+ check_true(input['high surrogate'] === '\uD800', "input['high surrogate'] === '\uD800'") &&
+ check_true(input['low surrogate'] === '\uDC00', "input['low surrogate'] === '\uDC00'") &&
+ check_true(input['nul'] === '\u0000', "input['nul'] === '\u0000'") &&
+ check_true(input['astral'] === '\uDBFF\uDFFD', "input['astral'] === '\uDBFF\uDFFD'") &&
+ check_true(input['0.2'] === 0.2, "input['0.2'] === 0.2") &&
+ check_true(1/input['0'] === Infinity, "1/input['0'] === Infinity") &&
+ check_true(1/input['-0'] === -Infinity, "1/input['-0'] === -Infinity") &&
+ check_true(input['NaN'] !== input['NaN'], "input['NaN'] !== input['NaN']") &&
+ check_true(input['Infinity'] === Infinity, "input['Infinity'] === Infinity") &&
+ check_true(input['-Infinity'] === -Infinity, "input['-Infinity'] === -Infinity") &&
+ check_true(input['9007199254740992'] === 9007199254740992, "input['9007199254740992'] === 9007199254740992") &&
+ check_true(input['-9007199254740992'] === -9007199254740992, "input['-9007199254740992'] === -9007199254740992") &&
+ check_true(input['9007199254740994'] === 9007199254740994, "input['9007199254740994'] === 9007199254740994") &&
+ check_true(input['-9007199254740994'] === -9007199254740994, "input['9007199254740994'] === -9007199254740994")) {
+ var i = 0;
+ for (var x in input) {
+ i++;
+ }
+ if (check_true(i === 19, 'i === 19')) {
+ port.postMessage(input);
+ close();
+ }
+ }
+ })();
+ break;
+ case 'Boolean true':
+ if (check_true(input instanceof Boolean, "input instanceof Boolean") &&
+ check_true(String(input) === 'true', "String(input) === 'true'")) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'Boolean false':
+ if (check_true(input instanceof Boolean, "input instanceof Boolean") &&
+ check_true(String(input) === 'false', "String(input) === 'false'")) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'Array Boolean objects':
+ (function() {
+ if (check_true(input instanceof Array, 'input instanceof Array') &&
+ check_true(input.length === 2, 'input.length === 2') &&
+ check_true(String(input[0]) === 'true', "String(input[0]) === 'true'") &&
+ check_true(String(input[1]) === 'false', "String(input[1]) === 'false'")) {
+ for (var i = 0; i < input.length; ++i) {
+ if (!check_true(input[i] instanceof Boolean, 'input['+i+'] instanceof Boolean'))
+ return;
+ }
+ port.postMessage(input);
+ close();
+ }
+ })();
+ break;
+ case 'Object Boolean objects':
+ (function() {
+ if (check_true(input instanceof Object, 'input instanceof Object') &&
+ check_true(!(input instanceof Array), '!(input instanceof Array)') &&
+ check_true(String(input['true']) === 'true', "String(input['true']) === 'true'") &&
+ check_true(String(input['false']) === 'false', "String(input['false']) === 'false'")) {
+ var i = 0;
+ for (var x in input) {
+ i++;
+ if (!check_true(input[x] instanceof Boolean, 'input['+x+'] instanceof Boolean'))
+ return;
+ }
+ if (check_true(i === 2, 'i === 2')) {
+ port.postMessage(input);
+ close();
+ }
+ }
+ })();
+ break;
+ case 'String empty string':
+ if (check_true(input instanceof String, "input instanceof String") &&
+ check_true(String(input) === '', "String(input) === ''")) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'String lone high surrogate':
+ if (check_true(input instanceof String, "input instanceof String") &&
+ check_true(String(input) === '\uD800', "String(input) === '\\uD800'")) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'String lone low surrogate':
+ if (check_true(input instanceof String, "input instanceof String") &&
+ check_true(String(input) === '\uDC00', "String(input) === '\\uDC00'")) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'String NUL':
+ if (check_true(input instanceof String, "input instanceof String") &&
+ check_true(String(input) === '\u0000', "String(input) === '\\u0000'")) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'String astral character':
+ if (check_true(input instanceof String, "input instanceof String") &&
+ check_true(String(input) === '\uDBFF\uDFFD', "String(input) === '\\uDBFF\\uDFFD'")) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'Array String objects':
+ (function() {
+ if (check_true(input instanceof Array, 'input instanceof Array') &&
+ check_true(input.length === 5, 'input.length === 5') &&
+ check_true(String(input[0]) === '', "String(input[0]) === ''") &&
+ check_true(String(input[1]) === '\uD800', "String(input[1]) === '\\uD800'") &&
+ check_true(String(input[2]) === '\uDC00', "String(input[1]) === '\\uDC00'") &&
+ check_true(String(input[3]) === '\u0000', "String(input[2]) === '\\u0000'") &&
+ check_true(String(input[4]) === '\uDBFF\uDFFD', "String(input[3]) === '\\uDBFF\\uDFFD'")) {
+ for (var i = 0; i < input.length; ++i) {
+ if (!check_true(input[i] instanceof String, 'input['+i+'] instanceof String'))
+ return;
+ }
+ port.postMessage(input);
+ close();
+ }
+ })();
+ break;
+ case 'Object String objects':
+ (function() {
+ if (check_true(input instanceof Object, 'input instanceof Object') &&
+ check_true(!(input instanceof Array), '!(input instanceof Array)') &&
+ check_true(String(input['empty']) === '', "String(input['empty']) === ''") &&
+ check_true(String(input['high surrogate']) === '\uD800', "String(input['high surrogate']) === '\\uD800'") &&
+ check_true(String(input['low surrogate']) === '\uDC00', "String(input['low surrogate']) === '\\uDC00'") &&
+ check_true(String(input['nul']) === '\u0000', "String(input['nul']) === '\\u0000'") &&
+ check_true(String(input['astral']) === '\uDBFF\uDFFD', "String(input['astral']) === '\\uDBFF\\uDFFD'")) {
+ var i = 0;
+ for (var x in input) {
+ i++;
+ if (!check_true(input[x] instanceof String, 'input['+x+'] instanceof Boolean'))
+ return;
+ }
+ if (check_true(i === 5, 'i === 5')) {
+ port.postMessage(input);
+ close();
+ }
+ }
+ })();
+ break;
+ case 'Number 0.2':
+ if (check_true(input instanceof Number, "input instanceof Number") &&
+ check_true(Number(input) === 0.2, "Number(input) === 0.2")) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'Number 0':
+ if (check_true(input instanceof Number, "input instanceof Number") &&
+ check_true(1/Number(input) === Infinity, "1/Number(input) === Infinity")) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'Number -0':
+ if (check_true(input instanceof Number, "input instanceof Number") &&
+ check_true(1/Number(input) === -Infinity, "1/Number(input) === -Infinity")) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'Number NaN':
+ if (check_true(input instanceof Number, "input instanceof Number") &&
+ check_true(Number(input) !== Number(input), "Number(input) !== Number(input)")) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'Number Infinity':
+ if (check_true(input instanceof Number, "input instanceof Number") &&
+ check_true(Number(input) === Infinity, "Number(input) === Infinity")) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'Number -Infinity':
+ if (check_true(input instanceof Number, "input instanceof Number") &&
+ check_true(Number(input) === -Infinity, "Number(input) === -Infinity")) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'Number 9007199254740992':
+ if (check_true(input instanceof Number) &&
+ check_true(Number(input) === 9007199254740992, "Number(input) === 9007199254740992")) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'Number -9007199254740992':
+ if (check_true(input instanceof Number, "input instanceof Number") &&
+ check_true(Number(input) === -9007199254740992, "Number(input) === -9007199254740992")) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'Number 9007199254740994':
+ if (check_true(input instanceof Number, "input instanceof Number") &&
+ check_true(Number(input) === 9007199254740994, "Number(input) === 9007199254740994")) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'Number -9007199254740994':
+ if (check_true(input instanceof Number, "input instanceof Number") &&
+ check_true(Number(input) === -9007199254740994, "Number(input) === -9007199254740994")) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'Array Number objects':
+ (function() {
+ if (check_true(input instanceof Array, 'input instanceof Array') &&
+ check_true(input.length === 10, 'input.length === 10') &&
+ check_true(Number(input[0]) === 0.2, "Number(input[0]) === 0.2") &&
+ check_true(1/Number(input[1]) === Infinity, "1/Number(input[1]) === Infinity") &&
+ check_true(1/Number(input[2]) === -Infinity, "1/Number(input[2]) === -Infinity") &&
+ check_true(Number(input[3]) !== Number(input[3]), "Number(input[3]) !== Number(input[3])") &&
+ check_true(Number(input[4]) === Infinity, "Number(input[4]) === Infinity") &&
+ check_true(Number(input[5]) === -Infinity, "Number(input[5]) === -Infinity") &&
+ check_true(Number(input[6]) === 9007199254740992, "Number(input[6]) === 9007199254740992") &&
+ check_true(Number(input[7]) === -9007199254740992, "Number(input[7]) === -9007199254740992") &&
+ check_true(Number(input[8]) === 9007199254740994, "Number(input[8]) === 9007199254740994") &&
+ check_true(Number(input[9]) === -9007199254740994, "Number(input[9]) === -9007199254740994")) {
+ for (var i = 0; i < input.length; ++i) {
+ if (!check_true(input[i] instanceof Number, 'input['+i+'] instanceof Number'))
+ return;
+ }
+ port.postMessage(input);
+ close();
+ }
+ })();
+ break;
+ case 'Object Number objects':
+ (function() {
+ if (check_true(input instanceof Object, 'input instanceof Object') &&
+ check_true(!(input instanceof Array), '!(input instanceof Array)') &&
+ check_true(Number(input['0.2']) === 0.2, "Number(input['0.2']) === 0.2") &&
+ check_true(1/Number(input['0']) === Infinity, "1/Number(input['0']) === Infinity") &&
+ check_true(1/Number(input['-0']) === -Infinity, "1/Number(input['-0']) === -Infinity") &&
+ check_true(Number(input['NaN']) !== Number(input['NaN']), "Number(input['NaN']) !== Number(input['NaN'])") &&
+ check_true(Number(input['Infinity']) === Infinity, "Number(input['Infinity']) === Infinity") &&
+ check_true(Number(input['-Infinity']) === -Infinity, "Number(input['-Infinity']) === -Infinity") &&
+ check_true(Number(input['9007199254740992']) === 9007199254740992, "Number(input['9007199254740992']) === 9007199254740992") &&
+ check_true(Number(input['-9007199254740992']) === -9007199254740992, "Number(input['-9007199254740992']) === -9007199254740992") &&
+ check_true(Number(input['9007199254740994']) === 9007199254740994, "Number(input['9007199254740994']) === 9007199254740994") &&
+ check_true(Number(input['-9007199254740994']) === -9007199254740994, "Number(input['-9007199254740994']) === -9007199254740994")) {
+ var i = 0;
+ for (var x in input) {
+ i++;
+ if (!check_true(input[x] instanceof Number, 'input['+x+'] instanceof Number'))
+ return;
+ }
+ if (check_true(i === 10, 'i === 10')) {
+ port.postMessage(input);
+ close();
+ }
+ }
+ })();
+ break;
+ case 'Date 0':
+ if (check_true(input instanceof Date, "input instanceof Date") &&
+ check_true(1/Number(input) === 1/Number(new Date(0)), "1/Number(input) === 1/Number(new Date(0))")) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'Date -0':
+ if (check_true(input instanceof Date, "input instanceof Date") &&
+ check_true(1/Number(input) === 1/Number(new Date(-0)), "1/Number(input) === 1/Number(new Date(-0))")) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'Date -8.64e15':
+ if (check_true(input instanceof Date, "input instanceof Date") &&
+ check_true(Number(input) === -8.64e15, "Number(input) === -8.64e15")) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'Date 8.64e15':
+ if (check_true(input instanceof Date, "input instanceof Date") &&
+ check_true(Number(input) === 8.64e15, "Number(input) === 8.64e15")) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'Array Date objects':
+ (function() {
+ if (check_true(input instanceof Array, 'input instanceof Array') &&
+ check_true(input.length === 4, 'input.length === 4') &&
+ check_true(1/Number(input[0]) === 1/new Date(0), '1/Number(input[0]) === 1/new Date(0)') &&
+ check_true(1/Number(input[1]) === 1/new Date(-0), '1/Number(input[1]) === 1/new Date(-0)') &&
+ check_true(Number(input[2]) === -8.64e15, 'Number(input[2]) === -8.64e15') &&
+ check_true(Number(input[3]) === 8.64e15, 'Number(input[3]) === 8.64e15')) {
+ for (var i = 0; i < input.length; ++i) {
+ if (!check_true(input[i] instanceof Date, 'input['+i+'] instanceof Date'))
+ return;
+ }
+ port.postMessage(input);
+ close();
+ }
+ })();
+ break;
+ case 'Object Date objects':
+ (function() {
+ if (check_true(input instanceof Object, 'input instanceof Object') &&
+ check_true(!(input instanceof Array), '!(input instanceof Array)') &&
+ check_true(1/Number(input['0']) === 1/new Date(0), "1/Number(input['0']) === 1/new Date(0)") &&
+ check_true(1/Number(input['-0']) === 1/new Date(-0), "1/Number(input[1]) === 1/new Date(-0)") &&
+ check_true(Number(input['-8.64e15']) === -8.64e15, "Number(input['-8.64e15']) === -8.64e15") &&
+ check_true(Number(input['8.64e15']) === 8.64e15, "Number(input['8.64e15']) === 8.64e15")) {
+ var i = 0;
+ for (var x in input) {
+ i++;
+ if (!check_true(input[x] instanceof Date, 'input['+x+'] instanceof Date'))
+ return;
+ }
+ port.postMessage(input);
+ close();
+ }
+ })();
+ break;
+ case 'RegExp flags and lastIndex':
+ case 'RegExp empty':
+ case 'RegExp slash':
+ case 'RegExp new line':
+ if (check_RegExp(msg, input)) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'Array RegExp object, RegExp flags and lastIndex':
+ case 'Array RegExp object, RegExp empty':
+ case 'Array RegExp object, RegExp slash':
+ case 'Array RegExp object, RegExp new line':
+ if (check_true(input instanceof Array, 'input instanceof Array') &&
+ check_true(input.length === 1, 'input.length === 1') &&
+ check_RegExp(msg.substr('Array RegExp object, '.length), input[0])) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'Object RegExp object, RegExp flags and lastIndex':
+ case 'Object RegExp object, RegExp empty':
+ case 'Object RegExp object, RegExp slash':
+ case 'Object RegExp object, RegExp new line':
+ (function() {
+ if (check_true(input instanceof Object, 'input instanceof Object') &&
+ check_true(!(input instanceof Array), '!(input instanceof Array)') &&
+ check_RegExp(msg.substr('Object RegExp object, '.length), input['x'])) {
+ var i = 0;
+ for (var x in input) {
+ i++;
+ }
+ if (check_true(i === 1, 'i === 1')) {
+ port.postMessage(input);
+ close();
+ }
+ }
+ })();
+ break;
+ case 'Blob basic':
+ case 'Blob unpaired high surrogate (invalid utf-8)':
+ case 'Blob unpaired low surrogate (invalid utf-8)':
+ case 'Blob paired surrogates (invalid utf-8)':
+ case 'Blob empty':
+ case 'Blob NUL':
+ check_Blob(msg, input, port);
+ // no postMessage or close here, check_Blob takes care of that
+ break;
+ case 'Array Blob object, Blob basic':
+ case 'Array Blob object, Blob unpaired high surrogate (invalid utf-8)':
+ case 'Array Blob object, Blob unpaired low surrogate (invalid utf-8)':
+ case 'Array Blob object, Blob paired surrogates (invalid utf-8)':
+ case 'Array Blob object, Blob empty':
+ case 'Array Blob object, Blob NUL':
+ if (check_true(input instanceof Array, 'input instanceof Array') &&
+ check_true(input.length === 1, 'input.length === 1')) {
+ check_Blob(msg.substr('Array Blob object, '.length), input[0], port, false, input);
+ // no postMessage or close here, check_Blob takes care of that
+ }
+ break;
+ case 'Object Blob object, Blob basic':
+ case 'Object Blob object, Blob unpaired high surrogate (invalid utf-8)':
+ case 'Object Blob object, Blob unpaired low surrogate (invalid utf-8)':
+ case 'Object Blob object, Blob paired surrogates (invalid utf-8)':
+ case 'Object Blob object, Blob empty':
+ case 'Object Blob object, Blob NUL':
+ (function() {
+ if (check_true(input instanceof Object, 'input instanceof Object') &&
+ check_true(!(input instanceof Array), '!(input instanceof Array)')) {
+ var i = 0;
+ for (var x in input) {
+ i++;
+ }
+ if (check_true(i === 1, 'i === 1')) {
+ check_Blob(msg.substr('Object Blob object, '.length), input['x'], port, false, input);
+ // no postMessage or close here, check_Blob takes care of that
+ }
+ }
+ })();
+ break;
+ case 'File basic':
+ check_Blob(msg, input, port, true);
+ // no postMessage or close here, check_Blob takes care of that
+ break;
+ case 'FileList empty':
+ if (check_FileList(msg, input)) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'Array FileList object, FileList empty':
+ if (check_true(input instanceof Array, 'input instanceof Array') &&
+ check_true(input.length === 1, 'input.length === 1') &&
+ check_FileList(msg.substr('Array FileList object, '.length), input[0])) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'Object FileList object, FileList empty':
+ (function() {
+ if (check_true(input instanceof Object, 'input instanceof Object') &&
+ check_true(!(input instanceof Array), '!(input instanceof Array)') &&
+ check_FileList(msg.substr('Array FileList object, '.length), input['x'])) {
+ var i = 0;
+ for (var x in input) {
+ i++;
+ }
+ if (check_true(i === 1, 'i === 1')) {
+ port.postMessage(input);
+ close();
+ }
+ }
+ })();
+ break;
+ case 'ImageData 1x1 transparent black':
+ if (check_ImageData(input, {width:1, height:1, data:[0,0,0,0]})) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'ImageData 1x1 non-transparent non-black':
+ if (check_ImageData(input, {width:1, height:1, data:[100, 101, 102, 103]})) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'Array ImageData object, ImageData 1x1 transparent black':
+ if (check_true(input instanceof Array, 'input instanceof Array') &&
+ check_true(input.length === 1, 'input.length === 1') &&
+ check_ImageData(input[0], {width:1, height:1, data:[0,0,0,0]})) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'Array ImageData object, ImageData 1x1 non-transparent non-black':
+ if (check_true(input instanceof Array, 'input instanceof Array') &&
+ check_true(input.length === 1, 'input.length === 1') &&
+ check_ImageData(input[0], {width:1, height:1, data:[100, 101, 102, 103]})) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'Object ImageData object, ImageData 1x1 transparent black':
+ (function(){
+ if (check_true(input instanceof Object, 'input instanceof Object') &&
+ check_true(!(input instanceof Array), '!(input instanceof Array)') &&
+ check_ImageData(input['x'], {width:1, height:1, data:[0,0,0,0]})) {
+ var i = 0;
+ for (var x in input) {
+ i++;
+ }
+ if (check_true(i === 1, 'i === 1')) {
+ port.postMessage(input);
+ close();
+ }
+ }
+ })();
+ break;
+ case 'Object ImageData object, ImageData 1x1 non-transparent non-black':
+ (function() {
+ if (check_true(input instanceof Object, 'input instanceof Object') &&
+ check_true(!(input instanceof Array), '!(input instanceof Array)') &&
+ check_ImageData(input['x'], {width:1, height:1, data:[100, 101, 102, 103]})) {
+ var i = 0;
+ for (var x in input) {
+ i++;
+ }
+ if (check_true(i === 1, 'i === 1')) {
+ port.postMessage(input);
+ close();
+ }
+ }
+ })();
+ break;
+ case 'ImageBitmap 1x1 transparent black':
+ if (check_ImageBitmap(input, {width:1, height:1, data:[0, 0, 0, 0]})) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'ImageBitmap 1x1 non-transparent non-black':
+ if (check_ImageBitmap(input, {width:1, height:1, data:[100, 101, 102, 103]})) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'Array ImageBitmap object, ImageBitmap 1x1 transparent black':
+ if (check_true(input instanceof Array, 'input instanceof Array') &&
+ check_true(input.length === 1, 'input.length === 1') &&
+ check_ImageBitmap(input[0], {width:1, height:1, data:[0, 0, 0, 0]})) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'Array ImageBitmap object, ImageBitmap 1x1 non-transparent non-black':
+ if (check_true(input instanceof Array, 'input instanceof Array') &&
+ check_true(input.length === 1, 'input.length === 1') &&
+ check_ImageBitmap(input[0], {width:1, height:1, data:[100, 101, 102, 103]})) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'Object ImageBitmap object, ImageBitmap 1x1 transparent black':
+ (function() {
+ if (check_true(input instanceof Object, 'input instanceof Object') &&
+ check_true(!(input instanceof Array), '!(input instanceof Array)') &&
+ check_ImageBitmap(input['x'], {width:1, height:1, data:[0, 0, 0, 0]})) {
+ var i = 0;
+ for (var x in input) {
+ i++;
+ }
+ if (check_true(i === 1, 'i === 1')) {
+ port.postMessage(input);
+ close();
+ }
+ }
+ })();
+ break;
+ case 'Object ImageBitmap object, ImageBitmap 1x1 non-transparent non-black':
+ (function() {
+ if (check_true(input instanceof Object, 'input instanceof Object') &&
+ check_true(!(input instanceof Array), '!(input instanceof Array)') &&
+ check_ImageBitmap(input['x'], {width:1, height:1, data:[100, 101, 102, 103]})) {
+ var i = 0;
+ for (var x in input) {
+ i++;
+ }
+ if (check_true(i === 1, 'i === 1')) {
+ port.postMessage(input);
+ close();
+ }
+ }
+ })();
+ break;
+ case 'Array sparse':
+ (function() {
+ if (check_true(input instanceof Array, 'input instanceof Array') &&
+ check_true(input.length === 10, 'input.length === 10')) {
+ for (var x in input) {
+ check_true(false, 'unexpected enumerable property '+x);
+ return;
+ }
+ port.postMessage(input);
+ close();
+ }
+ })();
+ break;
+ case 'Array with non-index property':
+ if (check_true(input instanceof Array, 'input instanceof Array') &&
+ check_true(input.length === 0, 'input.length === 0') &&
+ check_true(input.foo === 'bar', "input.foo === 'bar'")) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'Object with index property and length':
+ if (check_true(input instanceof Object, 'input instanceof Object') &&
+ check_true(!(input instanceof Array), '!(input instanceof Array)') &&
+ check_true(input[0] === 'foo', "input[0] === 'foo'") &&
+ check_true(input.length === 1, 'input.length === 1')) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'Array with circular reference':
+ if (check_true(input instanceof Array, 'input instanceof Array') &&
+ check_true(input.length === 1, 'input.length === 1') &&
+ check_true(input[0] === input, "input[0] === input")) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'Object with circular reference':
+ if (check_true(input instanceof Object, 'input instanceof Object') &&
+ check_true(!(input instanceof Array), '!(input instanceof Array)') &&
+ check_true(input['x'] === input, "input['x'] === input")) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'Array with identical property values':
+ if (check_true(input instanceof Array, 'input instanceof Array') &&
+ check_true(input.length === 2, 'input.length === 2') &&
+ check_true(input[0] === input[1], "input[0] === input[1]")) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'Object with identical property values':
+ if (check_true(input instanceof Object, 'input instanceof Object') &&
+ check_true(!(input instanceof Array), '!(input instanceof Array)') &&
+ check_true(input['x'] === input['y'], "input['x'] === input['y']")) {
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'Object with property on prototype':
+ case 'Object with non-enumerable property':
+ if (check_true(input instanceof Object, 'input instanceof Object') &&
+ check_true(!(input instanceof Array), '!(input instanceof Array)') &&
+ check_true(!('foo' in input), "!('foo' in input)")) {
+ input = {};
+ Object.defineProperty(input, 'foo', {value:'bar', enumerable:false, writable:true, configurable:true});
+ port.postMessage(input);
+ close();
+ }
+ break;
+ case 'Object with non-writable property':
+ if (check_true(input instanceof Object, 'input instanceof Object') &&
+ check_true(!(input instanceof Array), '!(input instanceof Array)') &&
+ check_true(input.foo === 'bar', "input.foo === bar")) {
+ input.foo += ' baz';
+ if (check_true(input.foo === 'bar baz', "input.foo === 'bar baz'")) {
+ input = {};
+ Object.defineProperty(input, 'foo', {value:'bar', enumerable:true, writable:false, configurable:true});
+ port.postMessage(input);
+ close();
+ }
+ }
+ break;
+ case 'Object with non-configurable property':
+ if (check_true(input instanceof Object, 'input instanceof Object') &&
+ check_true(!(input instanceof Array), '!(input instanceof Array)') &&
+ check_true(input.foo === 'bar', "input.foo === bar")) {
+ delete input.foo;
+ if (check_true(!('foo' in input), "!('foo' in input)")) {
+ input = {};
+ Object.defineProperty(input, 'foo', {value:'bar', enumerable:true, writable:true, configurable:false});
+ port.postMessage(input);
+ close();
+ }
+ }
+ break;
+
+ default:
+ port.postMessage('FAIL: unknown test');
+ close();
+ }
+ if (log.length > 0) {
+ port.postMessage('FAIL '+log);
+ close();
+ }
+ } catch (ex) {
+ port.postMessage('FAIL '+ex);
+ close();
+ }
+}
diff --git a/tests/wpt/web-platform-tests/workers/semantics/xhr/001-1.xml b/tests/wpt/web-platform-tests/workers/semantics/xhr/001-1.xml
new file mode 100644
index 00000000000..5d735bdf619
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/semantics/xhr/001-1.xml
@@ -0,0 +1 @@
+<x>foo</x> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/workers/semantics/xhr/001.html b/tests/wpt/web-platform-tests/workers/semantics/xhr/001.html
new file mode 100644
index 00000000000..e26e21c62f8
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/semantics/xhr/001.html
@@ -0,0 +1,35 @@
+<!--
+var xhr = new XMLHttpRequest();
+var log = '';
+xhr.onreadystatechange = function(e) {
+ if (this.readyState == 4) {
+ if (this.responseXML != null)
+ log += 'responseXML was not null. ';
+ if (this.responseText != '<x>foo</x>')
+ log += 'responseText was ' + this.responseText + ', expected <x>foo</x>. ';
+ postMessage(log);
+ }
+}
+xhr.open('GET', '001-1.xml', true);
+xhr.send();
+/*
+-->
+<!doctype html>
+<title>async XMLHttpRequest in dedicated worker</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var t = async_test();
+function runtest() {
+ var worker = new Worker('#');
+ worker.onmessage = this.step_func(function(e) {
+ assert_equals(e.data, '');
+ this.done();
+ });
+}
+</script>
+<iframe src=001-1.xml onload="t.step(runtest);"></iframe>
+<!--
+*/
+//--> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/workers/semantics/xhr/002.html b/tests/wpt/web-platform-tests/workers/semantics/xhr/002.html
new file mode 100644
index 00000000000..0d3386e982f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/semantics/xhr/002.html
@@ -0,0 +1,32 @@
+<!--
+var xhr = new XMLHttpRequest();
+var log = '';
+xhr.open('GET', '001-1.xml', false);
+xhr.send();
+if (xhr.responseXML != null)
+ log += 'responseXML was not null. ';
+if (xhr.responseText != '<x>foo</x>')
+ log += 'responseText was ' + this.responseText + ', expected <x>foo</x>. ';
+postMessage(log);
+
+/*
+-->
+<!doctype html>
+<title>sync XMLHttpRequest in dedicated worker</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var t = async_test();
+function runtest() {
+ var worker = new Worker('#');
+ worker.onmessage = this.step_func(function(e) {
+ assert_equals(e.data, '');
+ this.done();
+ });
+}
+</script>
+<iframe src=001-1.xml onload="t.step(runtest);"></iframe>
+<!--
+*/
+//--> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/workers/semantics/xhr/003.html b/tests/wpt/web-platform-tests/workers/semantics/xhr/003.html
new file mode 100644
index 00000000000..70edaf41702
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/semantics/xhr/003.html
@@ -0,0 +1,41 @@
+<!--
+onconnect = function(e) {
+ var xhr = new XMLHttpRequest();
+ var log = '';
+ var port = e.ports[0];
+ var postMessage = port.postMessage;
+ xhr.onreadystatechange = function(e) {
+ if (this.readyState == 4) {
+ if (this.responseXML != null)
+ log += 'responseXML was not null. ';
+ if (this.responseText && this.responseText != '<x>foo</x>')
+ log += 'responseText was ' + this.responseText + ', expected <x>foo</x>. ';
+ postMessage.call(port, log);
+ }
+ }
+ xhr.open('GET', '001-1.xml', true);
+ xhr.send();
+}
+
+/*
+-->
+<!doctype html>
+<title>async XMLHttpRequest in shared worker</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var t = async_test();
+function runtest() {
+ var worker = new SharedWorker('#', '');
+ worker.port.onmessage = this.step_func(function(e) {
+ assert_equals(e.data, '');
+ this.done();
+ });
+}
+</script>
+<iframe src=001-1.xml onload="t.step(runtest);"></iframe>
+<!--
+*/
+//-->
+
diff --git a/tests/wpt/web-platform-tests/workers/semantics/xhr/004.html b/tests/wpt/web-platform-tests/workers/semantics/xhr/004.html
new file mode 100644
index 00000000000..ec5893a4b79
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/semantics/xhr/004.html
@@ -0,0 +1,36 @@
+<!--
+onconnect = function(e) {
+ var xhr = new XMLHttpRequest();
+ var log = '';
+ xhr.open('GET', '001-1.xml', false);
+ xhr.send();
+ if (xhr.responseXML != null)
+ log += 'responseXML was not null. ';
+ if (xhr.responseText != '<x>foo</x>')
+ log += 'responseText was ' + xhr.responseText + ', expected <x>foo</x>. ';
+ e.ports[0].postMessage(log);
+}
+
+/*
+-->
+<!doctype html>
+<title>sync XMLHttpRequest in shared worker</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var t = async_test();
+function runtest() {
+ var worker = new SharedWorker('#', '');
+ worker.port.onmessage = this.step_func(function(e) {
+ assert_equals(e.data, '');
+ this.done();
+ });
+}
+</script>
+<iframe src=001-1.xml onload="t.step(runtest);"></iframe>
+<!--
+*/
+//-->
+
+
diff --git a/tests/wpt/web-platform-tests/workers/semantics/xhr/005.html b/tests/wpt/web-platform-tests/workers/semantics/xhr/005.html
new file mode 100644
index 00000000000..84abdb0c426
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/semantics/xhr/005.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<title>base url, dedicated worker</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var t = async_test();
+var i = 0;
+function runtest() {
+ i++;
+ if (i != 2)
+ return;
+ var worker = new Worker('support/005-1.js');
+ worker.onmessage = this.step_func(function(e) {
+ assert_true(e.data);
+ this.done();
+ });
+}
+</script>
+<iframe src=001-1.xml onload="t.step(runtest);"></iframe>
+<iframe src=support/001-1.xml onload="t.step(runtest);"></iframe>
diff --git a/tests/wpt/web-platform-tests/workers/semantics/xhr/006.html b/tests/wpt/web-platform-tests/workers/semantics/xhr/006.html
new file mode 100644
index 00000000000..7411b4baef3
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/semantics/xhr/006.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<title>base url, shared worker</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var t = async_test();
+var i = 0;
+function runtest() {
+ i++;
+ if (i != 2)
+ return;
+ var worker = new SharedWorker('support/006-1.js','');
+ worker.port.onmessage = this.step_func(function(e) {
+ assert_true(e.data);
+ this.done();
+ });
+}
+</script>
+<iframe src=001-1.xml onload="t.step(runtest);"></iframe>
+<iframe src=support/001-1.xml onload="t.step(runtest);"></iframe>
diff --git a/tests/wpt/web-platform-tests/workers/semantics/xhr/support/001-1.xml b/tests/wpt/web-platform-tests/workers/semantics/xhr/support/001-1.xml
new file mode 100644
index 00000000000..ecea58a9357
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/semantics/xhr/support/001-1.xml
@@ -0,0 +1 @@
+<x>bar</x> \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/workers/semantics/xhr/support/005-1.js b/tests/wpt/web-platform-tests/workers/semantics/xhr/support/005-1.js
new file mode 100644
index 00000000000..45f6519a210
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/semantics/xhr/support/005-1.js
@@ -0,0 +1,5 @@
+var xhr = new XMLHttpRequest();
+xhr.open('GET', '001-1.xml', false);
+xhr.send();
+var passed = xhr.responseText == '<x>bar</x>';
+postMessage(passed); \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/workers/semantics/xhr/support/006-1.js b/tests/wpt/web-platform-tests/workers/semantics/xhr/support/006-1.js
new file mode 100644
index 00000000000..d446781eb7c
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/semantics/xhr/support/006-1.js
@@ -0,0 +1,7 @@
+onconnect = function(e) {
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', '001-1.xml', false);
+ xhr.send();
+ var passed = xhr.responseText == '<x>bar</x>';
+ e.ports[0].postMessage(passed);
+} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/workers/support/ErrorEvent.js b/tests/wpt/web-platform-tests/workers/support/ErrorEvent.js
new file mode 100644
index 00000000000..22ea6d4fb51
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/support/ErrorEvent.js
@@ -0,0 +1,10 @@
+onmessage = function(evt)
+{
+ throw(new Error(evt.data));
+}
+
+onerror = function(message, location, line, col)
+{
+ postMessage( {"message": message, "filename": location, "lineno": line, "colno": col} );
+ return false; // "not handled" so the error propagates up to the Worker object
+}
diff --git a/tests/wpt/web-platform-tests/workers/support/ImportScripts.js b/tests/wpt/web-platform-tests/workers/support/ImportScripts.js
new file mode 100644
index 00000000000..7f2a2bcb552
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/support/ImportScripts.js
@@ -0,0 +1,9 @@
+try
+{
+ importScripts("WorkerBasic.js");
+}
+catch(ex)
+{
+ result = "Fail";
+ postMessage(result);
+}
diff --git a/tests/wpt/web-platform-tests/workers/support/ImportScriptsNetworkErr.js b/tests/wpt/web-platform-tests/workers/support/ImportScriptsNetworkErr.js
new file mode 100644
index 00000000000..8179c8b1001
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/support/ImportScriptsNetworkErr.js
@@ -0,0 +1,15 @@
+var result = "Fail";
+
+try
+{
+ importScripts("NonExistentFile.js");
+}
+catch(ex)
+{
+ if (ex.code != null && ex.code == ex.NETWORK_ERR)
+ {
+ result = "Pass";
+ }
+}
+
+postMessage(result); \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/workers/support/Timer.js b/tests/wpt/web-platform-tests/workers/support/Timer.js
new file mode 100644
index 00000000000..a86a224dbb4
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/support/Timer.js
@@ -0,0 +1,50 @@
+var count = 0;
+var id;
+
+onmessage = function(evt)
+{
+ try
+ {
+ switch(evt.data)
+ {
+ case "TimeoutHandler":
+ count = 0;
+ id = setTimeout("TimeoutHandler()", 10);
+ postMessage('hello');
+ break;
+ case "IntervalHandler":
+ count = 0;
+ id = setInterval("IntervalHandler()", 10);
+ postMessage('hello');
+ break;
+ }
+ }
+ catch(ex)
+ {
+ postMessage("Fail");
+ }
+}
+
+function TimeoutHandler()
+{
+ count++;
+ postMessage("worker");
+
+ id = setTimeout("TimeoutHandler()", 10);
+
+ if (count >= 2)
+ {
+ clearTimeout(id);
+ }
+}
+
+function IntervalHandler()
+{
+ count++;
+ postMessage("worker");
+
+ if (count >= 2)
+ {
+ clearInterval(id);
+ }
+}
diff --git a/tests/wpt/web-platform-tests/workers/support/WorkerBasic.js b/tests/wpt/web-platform-tests/workers/support/WorkerBasic.js
new file mode 100644
index 00000000000..6bb6d32b141
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/support/WorkerBasic.js
@@ -0,0 +1,7 @@
+var result = "Fail";
+
+onmessage = function(evt)
+{
+ result = "Pass";
+ postMessage(result);
+} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/workers/support/WorkerClose.js b/tests/wpt/web-platform-tests/workers/support/WorkerClose.js
new file mode 100644
index 00000000000..81f99993d81
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/support/WorkerClose.js
@@ -0,0 +1,5 @@
+onmessage = function(evt)
+{
+ postMessage(evt.data);
+ self.close();
+} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/workers/support/WorkerDataCloneErr.js b/tests/wpt/web-platform-tests/workers/support/WorkerDataCloneErr.js
new file mode 100644
index 00000000000..b7e8b0ae167
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/support/WorkerDataCloneErr.js
@@ -0,0 +1,15 @@
+var result = "Fail";
+
+try
+{
+ postMessage(navigator);
+}
+catch(ex)
+{
+ if(ex.code != null && ex.code == ex.DATA_CLONE_ERR)
+ {
+ result = "Pass";
+ }
+}
+
+postMessage(result); \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/workers/support/WorkerLocation.js b/tests/wpt/web-platform-tests/workers/support/WorkerLocation.js
new file mode 100644
index 00000000000..a57e2fc6609
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/support/WorkerLocation.js
@@ -0,0 +1,12 @@
+var obj = new Object();
+obj.location = location.toString();
+obj.href = location.href;
+obj.protocol = location.protocol;
+obj.host = location.host;
+obj.hostname = location.hostname;
+obj.port = location.port;
+obj.pathname = location.pathname;
+obj.search = location.search;
+obj.hash = location.hash;
+
+postMessage(obj);
diff --git a/tests/wpt/web-platform-tests/workers/support/WorkerNavigator.js b/tests/wpt/web-platform-tests/workers/support/WorkerNavigator.js
new file mode 100644
index 00000000000..084e45b2458
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/support/WorkerNavigator.js
@@ -0,0 +1,8 @@
+var obj = new Object();
+obj.appName = navigator.appName;
+obj.appVersion = navigator.appVersion;
+obj.platform = navigator.platform;
+obj.userAgent = navigator.userAgent;
+obj.onLine = navigator.onLine;
+
+postMessage(obj);
diff --git a/tests/wpt/web-platform-tests/workers/support/WorkerTerminate.js b/tests/wpt/web-platform-tests/workers/support/WorkerTerminate.js
new file mode 100644
index 00000000000..03e028746da
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/support/WorkerTerminate.js
@@ -0,0 +1,10 @@
+onmessage = function(evt)
+{
+ for (var i=0; true; i++)
+ {
+ if (i%1000 == 1)
+ {
+ postMessage(i);
+ }
+ }
+} \ No newline at end of file
diff --git a/tests/wpt/web-platform-tests/workers/support/WorkerText.txt b/tests/wpt/web-platform-tests/workers/support/WorkerText.txt
new file mode 100644
index 00000000000..e4eeb5391da
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/support/WorkerText.txt
@@ -0,0 +1,2 @@
+var result = "Pass";
+postMessage(result);
diff --git a/tests/wpt/web-platform-tests/workers/workers.js b/tests/wpt/web-platform-tests/workers/workers.js
new file mode 100644
index 00000000000..d2887df8b54
--- /dev/null
+++ b/tests/wpt/web-platform-tests/workers/workers.js
@@ -0,0 +1,8 @@
+function listenForMessages(t, worker) {
+ worker.addEventListener('message', t.step_func(function(e) {
+ if (e.data === 'done') {
+ t.done();
+ }
+ assert_unreached(e.data);
+ }), false);
+}